diff --git a/.clang-format b/.clang-format index 2573430fb..6ed326e11 100644 --- a/.clang-format +++ b/.clang-format @@ -1,5 +1,5 @@ --- -IndentWidth: 4 +BasedOnStyle: LLVM ColumnLimit: 120 UseTab: Never --- @@ -8,7 +8,6 @@ DerivePointerAlignment: false PointerAlignment: Left AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false -BreakBeforeBraces: Allman IndentCaseLabels: false AllowShortBlocksOnASingleLine: true AlignOperands: true @@ -24,6 +23,6 @@ NamespaceIndentation: None BinPackArguments: true BinPackParameters: true SortIncludes: false -AccessModifierOffset: -4 +AccessModifierOffset: -2 ConstructorInitializerIndentWidth: 0 ConstructorInitializerAllOnOneLineOrOnePerLine: true diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 7743f54aa..e288eb80f 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -10,7 +10,6 @@ - diff --git a/DataSpec/AssetNameMap.cpp b/DataSpec/AssetNameMap.cpp index 1a22d08e0..0fc2c0dc7 100644 --- a/DataSpec/AssetNameMap.cpp +++ b/DataSpec/AssetNameMap.cpp @@ -6,79 +6,70 @@ extern "C" const size_t ASSET_NAME_MP32_SZ; extern "C" const uint8_t ASSET_NAME_MP64[]; extern "C" const size_t ASSET_NAME_MP64_SZ; -namespace DataSpec::AssetNameMap -{ +namespace DataSpec::AssetNameMap { logvisor::Module Log("AssetNameMap"); -struct SAsset -{ - std::string name; - std::string directory; - hecl::FourCC type; - SAsset() = default; - SAsset(const hecl::FourCC& typeIn, athena::io::IStreamReader& in) - : type(typeIn) - { - uint32_t nameLen = in.readUint32Big(); - name = in.readString(nameLen); - uint32_t dirLen = in.readUint32Big(); - directory = in.readString(dirLen); - } +struct SAsset { + std::string name; + std::string directory; + hecl::FourCC type; + SAsset() = default; + SAsset(const hecl::FourCC& typeIn, athena::io::IStreamReader& in) : type(typeIn) { + uint32_t nameLen = in.readUint32Big(); + name = in.readString(nameLen); + uint32_t dirLen = in.readUint32Big(); + directory = in.readString(dirLen); + } }; static std::unordered_map g_AssetNameMap; static bool g_AssetNameMapInit = false; -void LoadAssetMap(athena::io::MemoryReader& ar) -{ - if (!ar.hasError()) - { - hecl::FourCC magic; - if (ar.length() >= 4) - ar.readBytesToBuf(&magic, 4); - if (magic != FOURCC('AIDM')) - Log.report(logvisor::Warning, _SYS_STR("Unable to load asset map; Assets will not have proper filenames for most files.")); - else - { - uint32_t assetCount = ar.readUint32Big(); - g_AssetNameMap.reserve(assetCount); - for (uint32_t i = 0 ; i= 4) + ar.readBytesToBuf(&magic, 4); + if (magic != FOURCC('AIDM')) + Log.report(logvisor::Warning, + _SYS_STR("Unable to load asset map; Assets will not have proper filenames for most files.")); + else { + uint32_t assetCount = ar.readUint32Big(); + g_AssetNameMap.reserve(assetCount); + for (uint32_t i = 0; i < assetCount; ++i) { + hecl::FourCC type; + ar.readBytesToBuf(&type, 4); + uint64_t id = ar.readUint64Big(); + g_AssetNameMap[id] = SAsset(type, ar); + } } + } } -void InitAssetNameMap() -{ - if (g_AssetNameMapInit) - return; +void InitAssetNameMap() { + if (g_AssetNameMapInit) + return; - Log.report(logvisor::Info, "Initializing asset name database..."); + Log.report(logvisor::Info, "Initializing asset name database..."); - /* First load the 32bit map for MP1/2 */ - { - athena::io::MemoryReader ar(ASSET_NAME_MP32, ASSET_NAME_MP32_SZ); - LoadAssetMap(ar); - } - /* Now load the 64bit map for MP3 */ - { - athena::io::MemoryReader ar(ASSET_NAME_MP64, ASSET_NAME_MP64_SZ); - LoadAssetMap(ar); - } - g_AssetNameMapInit = true; + /* First load the 32bit map for MP1/2 */ + { + athena::io::MemoryReader ar(ASSET_NAME_MP32, ASSET_NAME_MP32_SZ); + LoadAssetMap(ar); + } + /* Now load the 64bit map for MP3 */ + { + athena::io::MemoryReader ar(ASSET_NAME_MP64, ASSET_NAME_MP64_SZ); + LoadAssetMap(ar); + } + g_AssetNameMapInit = true; } -const std::string* TranslateIdToName(const UniqueID32& id) -{ - if (g_AssetNameMap.find(id.toUint64()) == g_AssetNameMap.end()) - return nullptr; +const std::string* TranslateIdToName(const UniqueID32& id) { + if (g_AssetNameMap.find(id.toUint64()) == g_AssetNameMap.end()) + return nullptr; - return &g_AssetNameMap[id.toUint64()].name; + return &g_AssetNameMap[id.toUint64()].name; } -} +} // namespace DataSpec::AssetNameMap diff --git a/DataSpec/AssetNameMap.hpp b/DataSpec/AssetNameMap.hpp index e73bcdc46..fb3e5c49c 100644 --- a/DataSpec/AssetNameMap.hpp +++ b/DataSpec/AssetNameMap.hpp @@ -4,9 +4,8 @@ #include #include "DNACommon/DNACommon.hpp" -namespace DataSpec::AssetNameMap -{ +namespace DataSpec::AssetNameMap { void InitAssetNameMap(); const std::string* TranslateIdToName(const UniqueID32&); const std::string* TranslateIdToName(const UniqueID64&); -} +} // namespace DataSpec::AssetNameMap diff --git a/DataSpec/Blender/BlenderSupport.cpp b/DataSpec/Blender/BlenderSupport.cpp index 276ef7315..032638071 100644 --- a/DataSpec/Blender/BlenderSupport.cpp +++ b/DataSpec/Blender/BlenderSupport.cpp @@ -5,20 +5,18 @@ extern "C" uint8_t RETRO_MASTER_SHADER[]; extern "C" size_t RETRO_MASTER_SHADER_SZ; -namespace DataSpec::Blender -{ +namespace DataSpec::Blender { -bool BuildMasterShader(const hecl::ProjectPath& path) -{ - hecl::blender::Connection& conn = hecl::blender::Connection::SharedConnection(); - if (!conn.createBlend(path, hecl::blender::BlendType::None)) - return false; - { - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os << RETRO_MASTER_SHADER; - os << "make_master_shader_library()\n"; - } - return conn.saveBlend(); +bool BuildMasterShader(const hecl::ProjectPath& path) { + hecl::blender::Connection& conn = hecl::blender::Connection::SharedConnection(); + if (!conn.createBlend(path, hecl::blender::BlendType::None)) + return false; + { + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os << RETRO_MASTER_SHADER; + os << "make_master_shader_library()\n"; + } + return conn.saveBlend(); } -} +} // namespace DataSpec::Blender diff --git a/DataSpec/Blender/BlenderSupport.hpp b/DataSpec/Blender/BlenderSupport.hpp index 8a52bc0e4..8a5cd7eca 100644 --- a/DataSpec/Blender/BlenderSupport.hpp +++ b/DataSpec/Blender/BlenderSupport.hpp @@ -2,10 +2,8 @@ #include -namespace DataSpec::Blender -{ +namespace DataSpec::Blender { bool BuildMasterShader(const hecl::ProjectPath& path); } - diff --git a/DataSpec/DNACommon/ANCS.cpp b/DataSpec/DNACommon/ANCS.cpp index 5981c402b..0b1ed8e7d 100644 --- a/DataSpec/DNACommon/ANCS.cpp +++ b/DataSpec/DNACommon/ANCS.cpp @@ -7,302 +7,259 @@ #include "DataSpec/DNAMP3/CHAR.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAANCS -{ +namespace DataSpec::DNAANCS { template -bool ReadANCSToBlender(hecl::blender::Connection& conn, - const ANCSDNA& ancs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - const SpecBase& dataspec, - std::function fileChanged, - bool force) -{ - /* Extract character CMDL/CSKR first */ - std::vector> chResInfo; - ancs.getCharacterResInfo(chResInfo); - for (const auto& info : chResInfo) - { - const nod::Node* node; - const typename PAKRouter::EntryType* cmdlE = - pakRouter.lookupEntry(info.cmdl, &node, true, false); - if (cmdlE) - { - hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); - if (force || cmdlPath.isNone()) - { - cmdlPath.makeDirChain(false); - if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh)) - return false; +bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, + std::function fileChanged, bool force) { + /* Extract character CMDL/CSKR first */ + std::vector> chResInfo; + ancs.getCharacterResInfo(chResInfo); + for (const auto& info : chResInfo) { + const nod::Node* node; + const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, &node, true, false); + if (cmdlE) { + hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); + if (force || cmdlPath.isNone()) { + cmdlPath.makeDirChain(false); + if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh)) + return false; - std::string bestName = pakRouter.getBestEntryName(*cmdlE); - hecl::SystemStringConv bestNameView(bestName); - fileChanged(bestNameView.c_str()); + std::string bestName = pakRouter.getBestEntryName(*cmdlE); + hecl::SystemStringConv bestNameView(bestName); + fileChanged(bestNameView.c_str()); - typename ANCSDNA::CSKRType cskr; - pakRouter.lookupAndReadDNA(info.cskr, cskr); - typename ANCSDNA::CINFType cinf; - pakRouter.lookupAndReadDNA(info.cinf, cinf); - using RigPair = std::pair; - RigPair rigPair(&cskr, &cinf); + typename ANCSDNA::CSKRType cskr; + pakRouter.lookupAndReadDNA(info.cskr, cskr); + typename ANCSDNA::CINFType cinf; + pakRouter.lookupAndReadDNA(info.cinf, cinf); + using RigPair = std::pair; + RigPair rigPair(&cskr, &cinf); - PAKEntryReadStream rs = cmdlE->beginReadStream(*node); - DNACMDL::ReadCMDLToBlender - (conn, rs, pakRouter, *cmdlE, dataspec, rigPair); + PAKEntryReadStream rs = cmdlE->beginReadStream(*node); + DNACMDL::ReadCMDLToBlender( + conn, rs, pakRouter, *cmdlE, dataspec, rigPair); - conn.saveBlend(); - } + conn.saveBlend(); + } + } + } + + /* Extract attachment CMDL/CSKRs first */ + auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id); + for (auto it = attRange.first; it != attRange.second; ++it) { + auto cmdlid = it->second.first.second; + + const nod::Node* node; + const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(cmdlid, &node, true, false); + if (cmdlE) { + hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); + if (force || cmdlPath.isNone()) { + cmdlPath.makeDirChain(false); + if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh)) + return false; + + std::string bestName = pakRouter.getBestEntryName(*cmdlE); + hecl::SystemStringConv bestNameView(bestName); + fileChanged(bestNameView.c_str()); + + const auto* rp = pakRouter.lookupCMDLRigPair(cmdlid); + typename ANCSDNA::CSKRType cskr; + pakRouter.lookupAndReadDNA(rp->first, cskr); + typename ANCSDNA::CINFType cinf; + pakRouter.lookupAndReadDNA(rp->second, cinf); + using RigPair = std::pair; + RigPair rigPair(&cskr, &cinf); + + PAKEntryReadStream rs = cmdlE->beginReadStream(*node); + DNACMDL::ReadCMDLToBlender( + conn, rs, pakRouter, *cmdlE, dataspec, rigPair); + + conn.saveBlend(); + } + } + } + + std::string bestName = pakRouter.getBestEntryName(entry); + hecl::SystemStringConv bestNameView(bestName); + fileChanged(bestNameView.c_str()); + + /* Establish ANCS blend */ + if (!conn.createBlend(outPath, hecl::blender::BlendType::Actor)) + return false; + + std::string firstName; + typename ANCSDNA::CINFType firstCinf; + { + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + + os.format( + "import bpy\n" + "from mathutils import Vector\n" + "bpy.context.scene.name = '%s'\n" + "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n" + "\n" + "# Using 'Blender Game'\n" + "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" + "\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n" + "\n" + "actor_data = bpy.context.scene.hecl_sact_data\n" + "arm_obj = None\n", + pakRouter.getBestEntryName(entry).c_str()); + + std::unordered_set cinfsDone; + for (const auto& info : chResInfo) { + /* Provide data to add-on */ + os.format( + "actor_subtype = actor_data.subtypes.add()\n" + "actor_subtype.name = '%s'\n\n", + info.name.c_str()); + + /* Build CINF if needed */ + if (cinfsDone.find(info.cinf) == cinfsDone.end()) { + typename ANCSDNA::CINFType cinf; + pakRouter.lookupAndReadDNA(info.cinf, cinf); + cinf.sendCINFToBlender(os, info.cinf); + if (cinfsDone.empty()) { + firstName = ANCSDNA::CINFType::GetCINFArmatureName(info.cinf); + firstCinf = cinf; } + cinfsDone.insert(info.cinf); + } else + os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str()); + os << "actor_subtype.linked_armature = arm_obj.name\n"; + + /* Link CMDL */ + const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info.cmdl, nullptr, true, false); + if (cmdlE) { + hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); + os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true); + + /* Attach CMDL to CINF */ + os << "if obj.name not in bpy.context.scene.objects:\n" + " bpy.context.scene.objects.link(obj)\n" + "obj.parent = arm_obj\n" + "obj.parent_type = 'ARMATURE'\n" + "actor_subtype.linked_mesh = obj.name\n\n"; + } + + /* Link overlays */ + for (const auto& overlay : info.overlays) { + os << "overlay = actor_subtype.overlays.add()\n"; + os.format("overlay.name = '%s'\n", overlay.first.c_str()); + + /* Link CMDL */ + const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(overlay.second.first, nullptr, true, false); + if (cmdlE) { + hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); + os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true); + + /* Attach CMDL to CINF */ + os << "if obj.name not in bpy.context.scene.objects:\n" + " bpy.context.scene.objects.link(obj)\n" + "obj.parent = arm_obj\n" + "obj.parent_type = 'ARMATURE'\n" + "overlay.linked_mesh = obj.name\n\n"; + } + } } - /* Extract attachment CMDL/CSKRs first */ - auto attRange = pakRouter.lookupCharacterAttachmentRigs(entry.id); - for (auto it = attRange.first; it != attRange.second; ++it) - { - auto cmdlid = it->second.first.second; + /* Link attachments */ + for (auto it = attRange.first; it != attRange.second; ++it) { + os << "attachment = actor_data.attachments.add()\n"; + os.format("attachment.name = '%s'\n", it->second.second.c_str()); - const nod::Node* node; - const typename PAKRouter::EntryType* cmdlE = - pakRouter.lookupEntry(cmdlid, &node, true, false); - if (cmdlE) - { - hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); - if (force || cmdlPath.isNone()) - { - cmdlPath.makeDirChain(false); - if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh)) - return false; + auto cinfid = it->second.first.first; + auto cmdlid = it->second.first.second; - std::string bestName = pakRouter.getBestEntryName(*cmdlE); - hecl::SystemStringConv bestNameView(bestName); - fileChanged(bestNameView.c_str()); + if (cinfid) { + /* Build CINF if needed */ + if (cinfsDone.find(cinfid) == cinfsDone.end()) { + typename ANCSDNA::CINFType cinf; + pakRouter.lookupAndReadDNA(cinfid, cinf); + cinf.sendCINFToBlender(os, cinfid); + if (cinfsDone.empty()) { + firstName = ANCSDNA::CINFType::GetCINFArmatureName(cinfid); + firstCinf = cinf; + } + cinfsDone.insert(cinfid); + } else + os.format("arm_obj = bpy.data.objects['CINF_%s']\n", cinfid.toString().c_str()); + os << "attachment.linked_armature = arm_obj.name\n"; + } - const auto* rp = pakRouter.lookupCMDLRigPair(cmdlid); - typename ANCSDNA::CSKRType cskr; - pakRouter.lookupAndReadDNA(rp->first, cskr); - typename ANCSDNA::CINFType cinf; - pakRouter.lookupAndReadDNA(rp->second, cinf); - using RigPair = std::pair; - RigPair rigPair(&cskr, &cinf); + /* Link CMDL */ + const typename PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(cmdlid, nullptr, true, false); + if (cmdlE) { + hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); + os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).data(), true); - PAKEntryReadStream rs = cmdlE->beginReadStream(*node); - DNACMDL::ReadCMDLToBlender - (conn, rs, pakRouter, *cmdlE, dataspec, rigPair); - - conn.saveBlend(); - } - } + /* Attach CMDL to CINF */ + os << "if obj.name not in bpy.context.scene.objects:\n" + " bpy.context.scene.objects.link(obj)\n" + "obj.parent = arm_obj\n" + "obj.parent_type = 'ARMATURE'\n" + "attachment.linked_mesh = obj.name\n\n"; + } } + } - std::string bestName = pakRouter.getBestEntryName(entry); - hecl::SystemStringConv bestNameView(bestName); - fileChanged(bestNameView.c_str()); + { + hecl::blender::DataStream ds = conn.beginData(); + std::unordered_map matrices = ds.getBoneMatrices(firstName); + ds.close(); + DNAANIM::RigInverter inverter(firstCinf, matrices); - /* Establish ANCS blend */ - if (!conn.createBlend(outPath, hecl::blender::BlendType::Actor)) - return false; + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os << "import bpy\n" + "actor_data = bpy.context.scene.hecl_sact_data\n"; - std::string firstName; - typename ANCSDNA::CINFType firstCinf; - { - hecl::blender::PyOutStream os = conn.beginPythonOut(true); + /* Get animation primitives */ + std::map> animResInfo; + ancs.getAnimationResInfo(&pakRouter, animResInfo); + for (const auto& id : animResInfo) { + typename ANCSDNA::ANIMType anim; + if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true)) { + os.format( + "act = bpy.data.actions.new('%s')\n" + "act.use_fake_user = True\n", + id.second.name.c_str()); + anim.sendANIMToBlender(os, inverter, id.second.additive); + } - os.format("import bpy\n" - "from mathutils import Vector\n" - "bpy.context.scene.name = '%s'\n" - "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n" - "\n" - "# Using 'Blender Game'\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" - "\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "\n" - "actor_data = bpy.context.scene.hecl_sact_data\n" - "arm_obj = None\n", - pakRouter.getBestEntryName(entry).c_str()); + os.format( + "actor_action = actor_data.actions.add()\n" + "actor_action.name = '%s'\n", + id.second.name.c_str()); - std::unordered_set cinfsDone; - for (const auto& info : chResInfo) - { - /* Provide data to add-on */ - os.format("actor_subtype = actor_data.subtypes.add()\n" - "actor_subtype.name = '%s'\n\n", - info.name.c_str()); - - /* Build CINF if needed */ - if (cinfsDone.find(info.cinf) == cinfsDone.end()) - { - typename ANCSDNA::CINFType cinf; - pakRouter.lookupAndReadDNA(info.cinf, cinf); - cinf.sendCINFToBlender(os, info.cinf); - if (cinfsDone.empty()) - { - firstName = ANCSDNA::CINFType::GetCINFArmatureName(info.cinf); - firstCinf = cinf; - } - cinfsDone.insert(info.cinf); - } - else - os.format("arm_obj = bpy.data.objects['CINF_%s']\n", info.cinf.toString().c_str()); - os << "actor_subtype.linked_armature = arm_obj.name\n"; - - /* Link CMDL */ - const typename PAKRouter::EntryType* cmdlE = - pakRouter.lookupEntry(info.cmdl, nullptr, true, false); - if (cmdlE) - { - hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); - os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), - pakRouter.getBestEntryName(*cmdlE).data(), true); - - /* Attach CMDL to CINF */ - os << "if obj.name not in bpy.context.scene.objects:\n" - " bpy.context.scene.objects.link(obj)\n" - "obj.parent = arm_obj\n" - "obj.parent_type = 'ARMATURE'\n" - "actor_subtype.linked_mesh = obj.name\n\n"; - } - - /* Link overlays */ - for (const auto& overlay : info.overlays) - { - os << "overlay = actor_subtype.overlays.add()\n"; - os.format("overlay.name = '%s'\n", overlay.first.c_str()); - - /* Link CMDL */ - const typename PAKRouter::EntryType* cmdlE = - pakRouter.lookupEntry(overlay.second.first, nullptr, true, false); - if (cmdlE) - { - hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); - os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), - pakRouter.getBestEntryName(*cmdlE).data(), true); - - /* Attach CMDL to CINF */ - os << "if obj.name not in bpy.context.scene.objects:\n" - " bpy.context.scene.objects.link(obj)\n" - "obj.parent = arm_obj\n" - "obj.parent_type = 'ARMATURE'\n" - "overlay.linked_mesh = obj.name\n\n"; - } - } - } - - /* Link attachments */ - for (auto it = attRange.first; it != attRange.second; ++it) - { - os << "attachment = actor_data.attachments.add()\n"; - os.format("attachment.name = '%s'\n", it->second.second.c_str()); - - auto cinfid = it->second.first.first; - auto cmdlid = it->second.first.second; - - if (cinfid) - { - /* Build CINF if needed */ - if (cinfsDone.find(cinfid) == cinfsDone.end()) - { - typename ANCSDNA::CINFType cinf; - pakRouter.lookupAndReadDNA(cinfid, cinf); - cinf.sendCINFToBlender(os, cinfid); - if (cinfsDone.empty()) - { - firstName = ANCSDNA::CINFType::GetCINFArmatureName(cinfid); - firstCinf = cinf; - } - cinfsDone.insert(cinfid); - } - else - os.format("arm_obj = bpy.data.objects['CINF_%s']\n", cinfid.toString().c_str()); - os << "attachment.linked_armature = arm_obj.name\n"; - } - - /* Link CMDL */ - const typename PAKRouter::EntryType* cmdlE = - pakRouter.lookupEntry(cmdlid, nullptr, true, false); - if (cmdlE) - { - hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE); - os.linkBlend(cmdlPath.getAbsolutePathUTF8().data(), - pakRouter.getBestEntryName(*cmdlE).data(), true); - - /* Attach CMDL to CINF */ - os << "if obj.name not in bpy.context.scene.objects:\n" - " bpy.context.scene.objects.link(obj)\n" - "obj.parent = arm_obj\n" - "obj.parent_type = 'ARMATURE'\n" - "attachment.linked_mesh = obj.name\n\n"; - } - } + /* Extract EVNT if present */ + anim.extractEVNT(id.second, outPath, pakRouter, force); } - - { - hecl::blender::DataStream ds = conn.beginData(); - std::unordered_map matrices = ds.getBoneMatrices(firstName); - ds.close(); - DNAANIM::RigInverter inverter(firstCinf, matrices); - - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os << "import bpy\n" - "actor_data = bpy.context.scene.hecl_sact_data\n"; - - /* Get animation primitives */ - std::map> animResInfo; - ancs.getAnimationResInfo(&pakRouter, animResInfo); - for (const auto& id : animResInfo) - { - typename ANCSDNA::ANIMType anim; - if (pakRouter.lookupAndReadDNA(id.second.animId, anim, true)) - { - os.format("act = bpy.data.actions.new('%s')\n" - "act.use_fake_user = True\n", id.second.name.c_str()); - anim.sendANIMToBlender(os, inverter, id.second.additive); - } - - os.format("actor_action = actor_data.actions.add()\n" - "actor_action.name = '%s'\n", id.second.name.c_str()); - - /* Extract EVNT if present */ - anim.extractEVNT(id.second, outPath, pakRouter, force); - } - } - conn.saveBlend(); - return true; + } + conn.saveBlend(); + return true; } -template bool ReadANCSToBlender, DNAMP1::ANCS, DNAMP1::MaterialSet, DNACMDL::SurfaceHeader_1, 2> - (hecl::blender::Connection& conn, - const DNAMP1::ANCS& ancs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - const SpecBase& dataspec, - std::function fileChanged, - bool force); -template bool ReadANCSToBlender, DNAMP2::ANCS, DNAMP2::MaterialSet, DNACMDL::SurfaceHeader_2, 4> - (hecl::blender::Connection& conn, - const DNAMP2::ANCS& ancs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - const SpecBase& dataspec, - std::function fileChanged, - bool force); -template bool ReadANCSToBlender, DNAMP3::CHAR, DNAMP3::MaterialSet, DNACMDL::SurfaceHeader_3, 4> - (hecl::blender::Connection& conn, - const DNAMP3::CHAR& ancs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - const SpecBase& dataspec, - std::function fileChanged, - bool force); +template bool +ReadANCSToBlender, DNAMP1::ANCS, DNAMP1::MaterialSet, DNACMDL::SurfaceHeader_1, 2>( + hecl::blender::Connection& conn, const DNAMP1::ANCS& ancs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, + const SpecBase& dataspec, std::function fileChanged, bool force); +template bool +ReadANCSToBlender, DNAMP2::ANCS, DNAMP2::MaterialSet, DNACMDL::SurfaceHeader_2, 4>( + hecl::blender::Connection& conn, const DNAMP2::ANCS& ancs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, + const SpecBase& dataspec, std::function fileChanged, bool force); +template bool +ReadANCSToBlender, DNAMP3::CHAR, DNAMP3::MaterialSet, DNACMDL::SurfaceHeader_3, 4>( + hecl::blender::Connection& conn, const DNAMP3::CHAR& ancs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, + const SpecBase& dataspec, std::function fileChanged, bool force); -} +} // namespace DataSpec::DNAANCS diff --git a/DataSpec/DNACommon/ANCS.hpp b/DataSpec/DNACommon/ANCS.hpp index 52ec8bbfa..8ad77a9cb 100644 --- a/DataSpec/DNACommon/ANCS.hpp +++ b/DataSpec/DNACommon/ANCS.hpp @@ -5,41 +5,32 @@ #include "CMDL.hpp" #include "RigInverter.hpp" -namespace DataSpec::DNAANCS -{ +namespace DataSpec::DNAANCS { using Actor = hecl::blender::Actor; using Armature = hecl::blender::Armature; using Action = hecl::blender::Action; template -struct CharacterResInfo -{ - std::string name; - IDTYPE cmdl; - IDTYPE cskr; - IDTYPE cinf; - std::vector>> overlays; +struct CharacterResInfo { + std::string name; + IDTYPE cmdl; + IDTYPE cskr; + IDTYPE cinf; + std::vector>> overlays; }; template -struct AnimationResInfo -{ - std::string name; - IDTYPE animId; - IDTYPE evntId; - bool additive; +struct AnimationResInfo { + std::string name; + IDTYPE animId; + IDTYPE evntId; + bool additive; }; template -bool ReadANCSToBlender(hecl::blender::Connection& conn, - const ANCSDNA& ancs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - const SpecBase& dataspec, - std::function fileChanged, - bool force=false); - -} +bool ReadANCSToBlender(hecl::blender::Connection& conn, const ANCSDNA& ancs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, + std::function fileChanged, bool force = false); +} // namespace DataSpec::DNAANCS diff --git a/DataSpec/DNACommon/ANIM.cpp b/DataSpec/DNACommon/ANIM.cpp index 64888baa8..0f9177734 100644 --- a/DataSpec/DNACommon/ANIM.cpp +++ b/DataSpec/DNACommon/ANIM.cpp @@ -3,529 +3,439 @@ #define DUMP_KEYS 0 -namespace DataSpec::DNAANIM -{ +namespace DataSpec::DNAANIM { -size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector& channels) -{ - size_t bitsPerKeyFrame = 0; - for (const Channel& chan : channels) - { - switch (chan.type) - { - case Channel::Type::Rotation: - bitsPerKeyFrame += 1; - case Channel::Type::Translation: - case Channel::Type::Scale: - bitsPerKeyFrame += chan.q[0]; - bitsPerKeyFrame += chan.q[1]; - bitsPerKeyFrame += chan.q[2]; - break; - case Channel::Type::KfHead: - bitsPerKeyFrame += 1; - break; - case Channel::Type::RotationMP3: - bitsPerKeyFrame += chan.q[0]; - bitsPerKeyFrame += chan.q[1]; - bitsPerKeyFrame += chan.q[2]; - bitsPerKeyFrame += chan.q[3]; - break; - default: break; - } +size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector& channels) { + size_t bitsPerKeyFrame = 0; + for (const Channel& chan : channels) { + switch (chan.type) { + case Channel::Type::Rotation: + bitsPerKeyFrame += 1; + case Channel::Type::Translation: + case Channel::Type::Scale: + bitsPerKeyFrame += chan.q[0]; + bitsPerKeyFrame += chan.q[1]; + bitsPerKeyFrame += chan.q[2]; + break; + case Channel::Type::KfHead: + bitsPerKeyFrame += 1; + break; + case Channel::Type::RotationMP3: + bitsPerKeyFrame += chan.q[0]; + bitsPerKeyFrame += chan.q[1]; + bitsPerKeyFrame += chan.q[2]; + bitsPerKeyFrame += chan.q[3]; + break; + default: + break; } - return (bitsPerKeyFrame * keyFrameCount + 31) / 32 * 4; + } + return (bitsPerKeyFrame * keyFrameCount + 31) / 32 * 4; } -static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div) -{ - float q = M_PIF / 2.0f / float(div); - zeus::simd_floats f(quat.simd); - return - { - { - atInt32(std::asin(f[1]) / q), - atInt32(std::asin(f[2]) / q), - atInt32(std::asin(f[3]) / q), - }, - (f[0] < 0.f) - }; +static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div) { + float q = M_PIF / 2.0f / float(div); + zeus::simd_floats f(quat.simd); + return {{ + atInt32(std::asin(f[1]) / q), + atInt32(std::asin(f[2]) / q), + atInt32(std::asin(f[3]) / q), + }, + (f[0] < 0.f)}; } -static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div) -{ - float q = M_PIF / 2.0f / float(div); - athena::simd_floats f = { - 0.0f, - std::sin(v.v[0] * q), - std::sin(v.v[1] * q), - std::sin(v.v[2] * q), - }; - f[0] = std::sqrt(std::max((1.0f - - (f[1] * f[1] + - f[2] * f[2] + - f[3] * f[3])), 0.0f)); - f[0] = v.w ? -f[0] : f[0]; - Value retval; - retval.simd.copy_from(f); - return retval; +static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div) { + float q = M_PIF / 2.0f / float(div); + athena::simd_floats f = { + 0.0f, + std::sin(v.v[0] * q), + std::sin(v.v[1] * q), + std::sin(v.v[2] * q), + }; + f[0] = std::sqrt(std::max((1.0f - (f[1] * f[1] + f[2] * f[2] + f[3] * f[3])), 0.0f)); + f[0] = v.w ? -f[0] : f[0]; + Value retval; + retval.simd.copy_from(f); + return retval; } -static inline Value DequantizeRotation_3(const QuantizedRot& v, atUint32 div) -{ - float q = 1.0f / float(div); - athena::simd_floats f = { - 0.0f, - v.v[0] * q, - v.v[1] * q, - v.v[2] * q, - }; - f[0] = std::sqrt(std::max((1.0f - - (f[1] * f[1] + - f[2] * f[2] + - f[3] * f[3])), 0.0f)); - f[0] = v.w ? -f[0] : f[0]; - Value retval; - retval.simd.copy_from(f); - return retval; +static inline Value DequantizeRotation_3(const QuantizedRot& v, atUint32 div) { + float q = 1.0f / float(div); + athena::simd_floats f = { + 0.0f, + v.v[0] * q, + v.v[1] * q, + v.v[2] * q, + }; + f[0] = std::sqrt(std::max((1.0f - (f[1] * f[1] + f[2] * f[2] + f[3] * f[3])), 0.0f)); + f[0] = v.w ? -f[0] : f[0]; + Value retval; + retval.simd.copy_from(f); + return retval; } -bool BitstreamReader::dequantizeBit(const atUint8* data) -{ - atUint32 byteCur = (m_bitCur / 32) * 4; - atUint32 bitRem = m_bitCur % 32; +bool BitstreamReader::dequantizeBit(const atUint8* data) { + atUint32 byteCur = (m_bitCur / 32) * 4; + atUint32 bitRem = m_bitCur % 32; - /* Fill 32 bit buffer with region containing bits */ - /* Make them least significant */ - atUint32 tempBuf = hecl::SBig(*reinterpret_cast(data + byteCur)) >> bitRem; + /* Fill 32 bit buffer with region containing bits */ + /* Make them least significant */ + atUint32 tempBuf = hecl::SBig(*reinterpret_cast(data + byteCur)) >> bitRem; - /* That's it */ - m_bitCur += 1; - return tempBuf & 0x1; + /* That's it */ + m_bitCur += 1; + return tempBuf & 0x1; } -atInt32 BitstreamReader::dequantize(const atUint8* data, atUint8 q) -{ - atUint32 byteCur = (m_bitCur / 32) * 4; - atUint32 bitRem = m_bitCur % 32; +atInt32 BitstreamReader::dequantize(const atUint8* data, atUint8 q) { + atUint32 byteCur = (m_bitCur / 32) * 4; + atUint32 bitRem = m_bitCur % 32; - /* Fill 32 bit buffer with region containing bits */ - /* Make them least significant */ - atUint32 tempBuf = hecl::SBig(*reinterpret_cast(data + byteCur)) >> bitRem; + /* Fill 32 bit buffer with region containing bits */ + /* Make them least significant */ + atUint32 tempBuf = hecl::SBig(*reinterpret_cast(data + byteCur)) >> bitRem; - /* If this shift underflows the value, buffer the next 32 bits */ - /* And tack onto shifted buffer */ - if ((bitRem + q) > 32) - { - atUint32 tempBuf2 = hecl::SBig(*reinterpret_cast(data + byteCur + 4)); - tempBuf |= (tempBuf2 << (32 - bitRem)); + /* If this shift underflows the value, buffer the next 32 bits */ + /* And tack onto shifted buffer */ + if ((bitRem + q) > 32) { + atUint32 tempBuf2 = hecl::SBig(*reinterpret_cast(data + byteCur + 4)); + tempBuf |= (tempBuf2 << (32 - bitRem)); + } + + /* Mask it */ + atUint32 mask = (1 << q) - 1; + tempBuf &= mask; + + /* Sign extend */ + atUint32 sign = (tempBuf >> (q - 1)) & 0x1; + if (sign) + tempBuf |= ~0u << q; + + /* Return delta value */ + m_bitCur += q; + return atInt32(tempBuf); +} + +std::vector> BitstreamReader::read(const atUint8* data, size_t keyFrameCount, + const std::vector& channels, atUint32 rotDiv, + float transMult, float scaleMult) { + m_bitCur = 0; + std::vector> chanKeys; + std::vector chanAccum; + chanKeys.reserve(channels.size()); + chanAccum.reserve(channels.size()); + for (const Channel& chan : channels) { + chanAccum.push_back(chan.i); + + chanKeys.emplace_back(); + std::vector& keys = chanKeys.back(); + keys.reserve(keyFrameCount); + switch (chan.type) { + case Channel::Type::Rotation: { + QuantizedRot qr = {{chan.i[0], chan.i[1], chan.i[2]}, false}; + keys.emplace_back(DequantizeRotation(qr, rotDiv)); + break; } - - /* Mask it */ - atUint32 mask = (1 << q) - 1; - tempBuf &= mask; - - /* Sign extend */ - atUint32 sign = (tempBuf >> (q - 1)) & 0x1; - if (sign) - tempBuf |= ~0u << q; - - /* Return delta value */ - m_bitCur += q; - return atInt32(tempBuf); -} - -std::vector> -BitstreamReader::read(const atUint8* data, - size_t keyFrameCount, - const std::vector& channels, - atUint32 rotDiv, - float transMult, - float scaleMult) -{ - m_bitCur = 0; - std::vector> chanKeys; - std::vector chanAccum; - chanKeys.reserve(channels.size()); - chanAccum.reserve(channels.size()); - for (const Channel& chan : channels) - { - chanAccum.push_back(chan.i); - - chanKeys.emplace_back(); - std::vector& keys = chanKeys.back(); - keys.reserve(keyFrameCount); - switch (chan.type) - { - case Channel::Type::Rotation: - { - QuantizedRot qr = {{chan.i[0], chan.i[1], chan.i[2]}, false}; - keys.emplace_back(DequantizeRotation(qr, rotDiv)); - break; - } - case Channel::Type::Translation: - { - keys.push_back({chan.i[0] * transMult, chan.i[1] * transMult, chan.i[2] * transMult}); - break; - } - case Channel::Type::Scale: - { - keys.push_back({chan.i[0] * scaleMult, chan.i[1] * scaleMult, chan.i[2] * scaleMult}); - break; - } - case Channel::Type::KfHead: - { - break; - } - case Channel::Type::RotationMP3: - { - QuantizedRot qr = {{chan.i[1], chan.i[2], chan.i[3]}, bool(chan.i[0] & 0x1)}; - keys.emplace_back(DequantizeRotation_3(qr, rotDiv)); - break; - } - default: break; - } + case Channel::Type::Translation: { + keys.push_back({chan.i[0] * transMult, chan.i[1] * transMult, chan.i[2] * transMult}); + break; } - - for (size_t f=0 ; femplace_back(DequantizeRotation(qr, rotDiv)); -#if DUMP_KEYS - fprintf(stderr, "%d R: %d %d %d %d\t", chan.id, wBit, p[0], p[1], p[2]); -#endif - break; - } - case Channel::Type::Translation: - { - atInt32 val1 = dequantize(data, chan.q[0]); - p[0] += val1; - atInt32 val2 = dequantize(data, chan.q[1]); - p[1] += val2; - atInt32 val3 = dequantize(data, chan.q[2]); - p[2] += val3; - kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult}); -#if DUMP_KEYS - fprintf(stderr, "%d T: %d %d %d\t", chan.id, p[0], p[1], p[2]); -#endif - break; - } - case Channel::Type::Scale: - { - p[0] += dequantize(data, chan.q[0]); - p[1] += dequantize(data, chan.q[1]); - p[2] += dequantize(data, chan.q[2]); - kit->push_back({p[0] * scaleMult, p[1] * scaleMult, p[2] * scaleMult}); -#if DUMP_KEYS - fprintf(stderr, "%d S: %d %d %d\t", chan.id, p[0], p[1], p[2]); -#endif - break; - } - case Channel::Type::KfHead: - { - dequantizeBit(data); - break; - } - case Channel::Type::RotationMP3: - { - atInt32 val1 = dequantize(data, chan.q[0]); - p[0] += val1; - atInt32 val2 = dequantize(data, chan.q[1]); - p[1] += val2; - atInt32 val3 = dequantize(data, chan.q[2]); - p[2] += val3; - atInt32 val4 = dequantize(data, chan.q[3]); - p[3] += val4; - QuantizedRot qr = {{p[1], p[2], p[3]}, bool(p[0] & 0x1)}; - kit->emplace_back(DequantizeRotation_3(qr, rotDiv)); - break; - } - default: break; - } - ++kit; - ++ait; - } -#if DUMP_KEYS - fprintf(stderr, "\n"); -#endif + case Channel::Type::Scale: { + keys.push_back({chan.i[0] * scaleMult, chan.i[1] * scaleMult, chan.i[2] * scaleMult}); + break; } - - return chanKeys; -} - -void BitstreamWriter::quantizeBit(atUint8* data, bool val) -{ - atUint32 byteCur = (m_bitCur / 32) * 4; - atUint32 bitRem = m_bitCur % 32; - - /* Fill 32 bit buffer with region containing bits */ - /* Make them least significant */ - *(atUint32*)(data + byteCur) = - hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur)) | (val << bitRem)); - - m_bitCur += 1; -} - -void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt32 val) -{ - atUint32 byteCur = (m_bitCur / 32) * 4; - atUint32 bitRem = m_bitCur % 32; - - atUint32 masked = val & ((1 << q) - 1); - - /* Fill 32 bit buffer with region containing bits */ - /* Make them least significant */ - *(atUint32*)(data + byteCur) = - hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur)) | (masked << bitRem)); - - /* If this shift underflows the value, buffer the next 32 bits */ - /* And tack onto shifted buffer */ - if ((bitRem + q) > 32) - { - *(atUint32*)(data + byteCur + 4) = - hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur + 4)) | (masked >> (32 - bitRem))); + case Channel::Type::KfHead: { + break; } + case Channel::Type::RotationMP3: { + QuantizedRot qr = {{chan.i[1], chan.i[2], chan.i[3]}, bool(chan.i[0] & 0x1)}; + keys.emplace_back(DequantizeRotation_3(qr, rotDiv)); + break; + } + default: + break; + } + } - m_bitCur += q; -} - -std::unique_ptr -BitstreamWriter::write(const std::vector>& chanKeys, - size_t keyFrameCount, std::vector& channels, - atUint32 quantRange, - atUint32& rotDivOut, - float& transMultOut, - float& scaleMultOut, - size_t& sizeOut) -{ - m_bitCur = 0; - rotDivOut = quantRange; /* Normalized range of values */ - float quantRangeF = float(quantRange); - - /* Pre-pass to calculate translation multiplier */ - float maxTransVal = 0.0f; - float maxScaleVal = 0.0f; + for (size_t f = 0; f < keyFrameCount; ++f) { +#if DUMP_KEYS + fprintf(stderr, "\nFRAME %" PRISize " %u %u\n", f, (m_bitCur / 32) * 4, m_bitCur % 32); + int lastId = -1; +#endif auto kit = chanKeys.begin(); - for (Channel& chan : channels) - { - switch (chan.type) - { - case Channel::Type::Translation: - { - for (auto it=kit->begin(); - it != kit->end(); - ++it) - { - const Value* key = &*it; - zeus::simd_floats f(key->simd); - maxTransVal = std::max(maxTransVal, std::fabs(f[0])); - maxTransVal = std::max(maxTransVal, std::fabs(f[1])); - maxTransVal = std::max(maxTransVal, std::fabs(f[2])); - } - break; - } - case Channel::Type::Scale: - { - for (auto it=kit->begin(); - it != kit->end(); - ++it) - { - const Value* key = &*it; - zeus::simd_floats f(key->simd); - maxScaleVal = std::max(maxScaleVal, std::fabs(f[0])); - maxScaleVal = std::max(maxScaleVal, std::fabs(f[1])); - maxScaleVal = std::max(maxScaleVal, std::fabs(f[2])); - } - break; - } - default: break; - } - ++kit; + auto ait = chanAccum.begin(); + for (const Channel& chan : channels) { +#if DUMP_KEYS + if (chan.id != lastId) { + lastId = chan.id; + fprintf(stderr, "\n"); + } +#endif + QuantizedValue& p = *ait; + switch (chan.type) { + case Channel::Type::Rotation: { + bool wBit = dequantizeBit(data); + p[0] += dequantize(data, chan.q[0]); + p[1] += dequantize(data, chan.q[1]); + p[2] += dequantize(data, chan.q[2]); + QuantizedRot qr = {{p[0], p[1], p[2]}, wBit}; + kit->emplace_back(DequantizeRotation(qr, rotDiv)); +#if DUMP_KEYS + fprintf(stderr, "%d R: %d %d %d %d\t", chan.id, wBit, p[0], p[1], p[2]); +#endif + break; + } + case Channel::Type::Translation: { + atInt32 val1 = dequantize(data, chan.q[0]); + p[0] += val1; + atInt32 val2 = dequantize(data, chan.q[1]); + p[1] += val2; + atInt32 val3 = dequantize(data, chan.q[2]); + p[2] += val3; + kit->push_back({p[0] * transMult, p[1] * transMult, p[2] * transMult}); +#if DUMP_KEYS + fprintf(stderr, "%d T: %d %d %d\t", chan.id, p[0], p[1], p[2]); +#endif + break; + } + case Channel::Type::Scale: { + p[0] += dequantize(data, chan.q[0]); + p[1] += dequantize(data, chan.q[1]); + p[2] += dequantize(data, chan.q[2]); + kit->push_back({p[0] * scaleMult, p[1] * scaleMult, p[2] * scaleMult}); +#if DUMP_KEYS + fprintf(stderr, "%d S: %d %d %d\t", chan.id, p[0], p[1], p[2]); +#endif + break; + } + case Channel::Type::KfHead: { + dequantizeBit(data); + break; + } + case Channel::Type::RotationMP3: { + atInt32 val1 = dequantize(data, chan.q[0]); + p[0] += val1; + atInt32 val2 = dequantize(data, chan.q[1]); + p[1] += val2; + atInt32 val3 = dequantize(data, chan.q[2]); + p[2] += val3; + atInt32 val4 = dequantize(data, chan.q[3]); + p[3] += val4; + QuantizedRot qr = {{p[1], p[2], p[3]}, bool(p[0] & 0x1)}; + kit->emplace_back(DequantizeRotation_3(qr, rotDiv)); + break; + } + default: + break; + } + ++kit; + ++ait; } - transMultOut = maxTransVal / quantRangeF; - scaleMultOut = maxScaleVal / quantRangeF; +#if DUMP_KEYS + fprintf(stderr, "\n"); +#endif + } - /* Output channel inits */ - std::vector initVals; - initVals.reserve(channels.size()); - kit = chanKeys.begin(); - for (Channel& chan : channels) - { - chan.q[0] = 1; - chan.q[1] = 1; - chan.q[2] = 1; - switch (chan.type) - { - case Channel::Type::Rotation: - { - QuantizedRot qr = QuantizeRotation((*kit)[0], rotDivOut); - chan.i = qr.v; - initVals.push_back(chan.i); - break; - } - case Channel::Type::Translation: - { - zeus::simd_floats f((*kit)[0].simd); - chan.i = {atInt32(f[0] / transMultOut), - atInt32(f[1] / transMultOut), - atInt32(f[2] / transMultOut)}; - initVals.push_back(chan.i); - break; - } - case Channel::Type::Scale: - { - zeus::simd_floats f((*kit)[0].simd); - chan.i = {atInt32(f[0] / scaleMultOut), - atInt32(f[1] / scaleMultOut), - atInt32(f[2] / scaleMultOut)}; - initVals.push_back(chan.i); - break; - } - default: break; - } - ++kit; - } - - /* Pre-pass to analyze quantization factors for channels */ - std::vector lastVals = initVals; - kit = chanKeys.begin(); - auto vit = lastVals.begin(); - for (Channel& chan : channels) - { - QuantizedValue& last = *vit++; - switch (chan.type) - { - case Channel::Type::Rotation: - { - for (auto it=kit->begin() + 1; - it != kit->end(); - ++it) - { - QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut); - chan.q[0] = std::max(chan.q[0], atUint8(qrCur.v.qFrom(last, 0))); - chan.q[1] = std::max(chan.q[1], atUint8(qrCur.v.qFrom(last, 1))); - chan.q[2] = std::max(chan.q[2], atUint8(qrCur.v.qFrom(last, 2))); - last = qrCur.v; - } - break; - } - case Channel::Type::Translation: - { - for (auto it=kit->begin() + 1; - it != kit->end(); - ++it) - { - zeus::simd_floats f(it->simd); - QuantizedValue cur = {atInt32(f[0] / transMultOut), - atInt32(f[1] / transMultOut), - atInt32(f[2] / transMultOut)}; - chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0))); - chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1))); - chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2))); - last = cur; - } - break; - } - case Channel::Type::Scale: - { - for (auto it=kit->begin() + 1; - it != kit->end(); - ++it) - { - zeus::simd_floats f(it->simd); - QuantizedValue cur = {atInt32(f[0] / scaleMultOut), - atInt32(f[1] / scaleMultOut), - atInt32(f[2] / scaleMultOut)}; - chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0))); - chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1))); - chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2))); - last = cur; - } - break; - } - default: break; - } - ++kit; - } - - /* Generate Bitstream */ - sizeOut = ComputeBitstreamSize(keyFrameCount, channels); - std::unique_ptr newData(new atUint8[sizeOut]); - memset(newData.get(), 0, sizeOut); - - lastVals = initVals; - for (size_t f=0 ; f 32) { + *(atUint32*)(data + byteCur + 4) = + hecl::SBig(hecl::SBig(*(atUint32*)(data + byteCur + 4)) | (masked >> (32 - bitRem))); + } + + m_bitCur += q; +} + +std::unique_ptr BitstreamWriter::write(const std::vector>& chanKeys, size_t keyFrameCount, + std::vector& channels, atUint32 quantRange, + atUint32& rotDivOut, float& transMultOut, float& scaleMultOut, + size_t& sizeOut) { + m_bitCur = 0; + rotDivOut = quantRange; /* Normalized range of values */ + float quantRangeF = float(quantRange); + + /* Pre-pass to calculate translation multiplier */ + float maxTransVal = 0.0f; + float maxScaleVal = 0.0f; + auto kit = chanKeys.begin(); + for (Channel& chan : channels) { + switch (chan.type) { + case Channel::Type::Translation: { + for (auto it = kit->begin(); it != kit->end(); ++it) { + const Value* key = &*it; + zeus::simd_floats f(key->simd); + maxTransVal = std::max(maxTransVal, std::fabs(f[0])); + maxTransVal = std::max(maxTransVal, std::fabs(f[1])); + maxTransVal = std::max(maxTransVal, std::fabs(f[2])); + } + break; + } + case Channel::Type::Scale: { + for (auto it = kit->begin(); it != kit->end(); ++it) { + const Value* key = &*it; + zeus::simd_floats f(key->simd); + maxScaleVal = std::max(maxScaleVal, std::fabs(f[0])); + maxScaleVal = std::max(maxScaleVal, std::fabs(f[1])); + maxScaleVal = std::max(maxScaleVal, std::fabs(f[2])); + } + break; + } + default: + break; + } + ++kit; + } + transMultOut = maxTransVal / quantRangeF; + scaleMultOut = maxScaleVal / quantRangeF; + + /* Output channel inits */ + std::vector initVals; + initVals.reserve(channels.size()); + kit = chanKeys.begin(); + for (Channel& chan : channels) { + chan.q[0] = 1; + chan.q[1] = 1; + chan.q[2] = 1; + switch (chan.type) { + case Channel::Type::Rotation: { + QuantizedRot qr = QuantizeRotation((*kit)[0], rotDivOut); + chan.i = qr.v; + initVals.push_back(chan.i); + break; + } + case Channel::Type::Translation: { + zeus::simd_floats f((*kit)[0].simd); + chan.i = {atInt32(f[0] / transMultOut), atInt32(f[1] / transMultOut), atInt32(f[2] / transMultOut)}; + initVals.push_back(chan.i); + break; + } + case Channel::Type::Scale: { + zeus::simd_floats f((*kit)[0].simd); + chan.i = {atInt32(f[0] / scaleMultOut), atInt32(f[1] / scaleMultOut), atInt32(f[2] / scaleMultOut)}; + initVals.push_back(chan.i); + break; + } + default: + break; + } + ++kit; + } + + /* Pre-pass to analyze quantization factors for channels */ + std::vector lastVals = initVals; + kit = chanKeys.begin(); + auto vit = lastVals.begin(); + for (Channel& chan : channels) { + QuantizedValue& last = *vit++; + switch (chan.type) { + case Channel::Type::Rotation: { + for (auto it = kit->begin() + 1; it != kit->end(); ++it) { + QuantizedRot qrCur = QuantizeRotation(*it, rotDivOut); + chan.q[0] = std::max(chan.q[0], atUint8(qrCur.v.qFrom(last, 0))); + chan.q[1] = std::max(chan.q[1], atUint8(qrCur.v.qFrom(last, 1))); + chan.q[2] = std::max(chan.q[2], atUint8(qrCur.v.qFrom(last, 2))); + last = qrCur.v; + } + break; + } + case Channel::Type::Translation: { + for (auto it = kit->begin() + 1; it != kit->end(); ++it) { + zeus::simd_floats f(it->simd); + QuantizedValue cur = {atInt32(f[0] / transMultOut), atInt32(f[1] / transMultOut), atInt32(f[2] / transMultOut)}; + chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0))); + chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1))); + chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2))); + last = cur; + } + break; + } + case Channel::Type::Scale: { + for (auto it = kit->begin() + 1; it != kit->end(); ++it) { + zeus::simd_floats f(it->simd); + QuantizedValue cur = {atInt32(f[0] / scaleMultOut), atInt32(f[1] / scaleMultOut), atInt32(f[2] / scaleMultOut)}; + chan.q[0] = std::max(chan.q[0], atUint8(cur.qFrom(last, 0))); + chan.q[1] = std::max(chan.q[1], atUint8(cur.qFrom(last, 1))); + chan.q[2] = std::max(chan.q[2], atUint8(cur.qFrom(last, 2))); + last = cur; + } + break; + } + default: + break; + } + ++kit; + } + + /* Generate Bitstream */ + sizeOut = ComputeBitstreamSize(keyFrameCount, channels); + std::unique_ptr newData(new atUint8[sizeOut]); + memset(newData.get(), 0, sizeOut); + + lastVals = initVals; + for (size_t f = 0; f < keyFrameCount; ++f) { + kit = chanKeys.begin(); + vit = lastVals.begin(); + for (const Channel& chan : channels) { + const Value& val = (*kit++)[f + 1]; + QuantizedValue& last = *vit++; + switch (chan.type) { + case Channel::Type::Rotation: { + QuantizedRot qrCur = QuantizeRotation(val, rotDivOut); + quantizeBit(newData.get(), qrCur.w); + quantize(newData.get(), chan.q[0], qrCur.v[0] - last.v[0]); + quantize(newData.get(), chan.q[1], qrCur.v[1] - last.v[1]); + quantize(newData.get(), chan.q[2], qrCur.v[2] - last.v[2]); + last = qrCur.v; + break; + } + case Channel::Type::Translation: { + zeus::simd_floats f(val.simd); + QuantizedValue cur = {atInt32(f[0] / transMultOut), atInt32(f[1] / transMultOut), atInt32(f[2] / transMultOut)}; + quantize(newData.get(), chan.q[0], cur[0] - last[0]); + quantize(newData.get(), chan.q[1], cur[1] - last[1]); + quantize(newData.get(), chan.q[2], cur[2] - last[2]); + last = cur; + break; + } + case Channel::Type::Scale: { + zeus::simd_floats f(val.simd); + QuantizedValue cur = {atInt32(f[0] / scaleMultOut), atInt32(f[1] / scaleMultOut), atInt32(f[2] / scaleMultOut)}; + quantize(newData.get(), chan.q[0], cur[0] - last[0]); + quantize(newData.get(), chan.q[1], cur[1] - last[1]); + quantize(newData.get(), chan.q[2], cur[2] - last[2]); + last = cur; + break; + } + default: + break; + } + } + } + return newData; +} + +} // namespace DataSpec::DNAANIM diff --git a/DataSpec/DNACommon/ANIM.hpp b/DataSpec/DNACommon/ANIM.hpp index 93bab6450..268971bb2 100644 --- a/DataSpec/DNACommon/ANIM.hpp +++ b/DataSpec/DNACommon/ANIM.hpp @@ -3,87 +3,61 @@ #include "DNACommon.hpp" #include -namespace DataSpec::DNAANIM -{ +namespace DataSpec::DNAANIM { -struct Value -{ - athena::simd simd; - Value() = default; - Value(const athena::simd& s) : simd(s) {} - Value(const atVec3f& v) : simd(v.simd) {} - Value(const atVec4f& v) : simd(v.simd) {} - Value(float x, float y, float z) : simd(x, y, z, 0.f) {} - Value(float w, float x, float y, float z) : simd(w, x, y, z) {} +struct Value { + athena::simd simd; + Value() = default; + Value(const athena::simd& s) : simd(s) {} + Value(const atVec3f& v) : simd(v.simd) {} + Value(const atVec4f& v) : simd(v.simd) {} + Value(float x, float y, float z) : simd(x, y, z, 0.f) {} + Value(float w, float x, float y, float z) : simd(w, x, y, z) {} }; -struct QuantizedValue -{ - atInt32 v[4]; - atInt32& operator[] (size_t idx) - {return v[idx];} - atInt32 operator[] (size_t idx) const - {return v[idx];} +struct QuantizedValue { + atInt32 v[4]; + atInt32& operator[](size_t idx) { return v[idx]; } + atInt32 operator[](size_t idx) const { return v[idx]; } - int qFrom(const QuantizedValue& other, size_t idx) const - { - atInt32 delta = std::abs(v[idx] - other.v[idx]); - if (delta == 0) - return 1; - return int(std::ceil(std::log2(delta))) + 1; - } + int qFrom(const QuantizedValue& other, size_t idx) const { + atInt32 delta = std::abs(v[idx] - other.v[idx]); + if (delta == 0) + return 1; + return int(std::ceil(std::log2(delta))) + 1; + } }; -struct QuantizedRot -{ - QuantizedValue v; - bool w; +struct QuantizedRot { + QuantizedValue v; + bool w; }; -struct Channel -{ - enum class Type - { - Rotation, - Translation, - Scale, - KfHead, - RotationMP3 - } type; - atInt32 id = -1; - QuantizedValue i = {}; - atUint8 q[4] = {}; +struct Channel { + enum class Type { Rotation, Translation, Scale, KfHead, RotationMP3 } type; + atInt32 id = -1; + QuantizedValue i = {}; + atUint8 q[4] = {}; }; size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector& channels); -class BitstreamReader -{ - size_t m_bitCur; - atInt32 dequantize(const atUint8* data, atUint8 q); - bool dequantizeBit(const atUint8* data); +class BitstreamReader { + size_t m_bitCur; + atInt32 dequantize(const atUint8* data, atUint8 q); + bool dequantizeBit(const atUint8* data); + public: - std::vector> - read(const atUint8* data, - size_t keyFrameCount, - const std::vector& channels, - atUint32 rotDiv, - float transMult, - float scaleMult); + std::vector> read(const atUint8* data, size_t keyFrameCount, const std::vector& channels, + atUint32 rotDiv, float transMult, float scaleMult); }; -class BitstreamWriter -{ - size_t m_bitCur; - void quantize(atUint8* data, atUint8 q, atInt32 val); - void quantizeBit(atUint8* data, bool val); +class BitstreamWriter { + size_t m_bitCur; + void quantize(atUint8* data, atUint8 q, atInt32 val); + void quantizeBit(atUint8* data, bool val); + public: - std::unique_ptr - write(const std::vector>& chanKeys, - size_t keyFrameCount, std::vector& channels, - atUint32 quantRange, - atUint32& rotDivOut, - float& transMultOut, - float& scaleMultOut, - size_t& sizeOut); + std::unique_ptr write(const std::vector>& chanKeys, size_t keyFrameCount, + std::vector& channels, atUint32 quantRange, atUint32& rotDivOut, + float& transMultOut, float& scaleMultOut, size_t& sizeOut); }; -} - +} // namespace DataSpec::DNAANIM diff --git a/DataSpec/DNACommon/AROTBuilder.cpp b/DataSpec/DNACommon/AROTBuilder.cpp index 9f76a12e1..6c917b870 100644 --- a/DataSpec/DNACommon/AROTBuilder.cpp +++ b/DataSpec/DNACommon/AROTBuilder.cpp @@ -2,8 +2,7 @@ #include "hecl/Blender/Connection.hpp" #include "../DNAMP1/PATH.hpp" -namespace DataSpec -{ +namespace DataSpec { logvisor::Module Log("AROTBuilder"); #define AROT_MAX_LEVEL 10 @@ -12,505 +11,419 @@ logvisor::Module Log("AROTBuilder"); #define COLLISION_MIN_NODE_TRIANGLES 8 #define PATH_MIN_NODE_REGIONS 16 -static zeus::CAABox SplitAABB(const zeus::CAABox& aabb, int i) -{ - zeus::CAABox pos, neg; - aabb.splitZ(neg, pos); - if (i & 4) - { - zeus::CAABox(pos).splitY(neg, pos); - if (i & 2) - { - zeus::CAABox(pos).splitX(neg, pos); - if (i & 1) - return pos; - else - return neg; - } - else - { - zeus::CAABox(neg).splitX(neg, pos); - if (i & 1) - return pos; - else - return neg; - } +static zeus::CAABox SplitAABB(const zeus::CAABox& aabb, int i) { + zeus::CAABox pos, neg; + aabb.splitZ(neg, pos); + if (i & 4) { + zeus::CAABox(pos).splitY(neg, pos); + if (i & 2) { + zeus::CAABox(pos).splitX(neg, pos); + if (i & 1) + return pos; + else + return neg; + } else { + zeus::CAABox(neg).splitX(neg, pos); + if (i & 1) + return pos; + else + return neg; } - else - { - zeus::CAABox(neg).splitY(neg, pos); - if (i & 2) - { - zeus::CAABox(pos).splitX(neg, pos); - if (i & 1) - return pos; - else - return neg; - } - else - { - zeus::CAABox(neg).splitX(neg, pos); - if (i & 1) - return pos; - else - return neg; - } + } else { + zeus::CAABox(neg).splitY(neg, pos); + if (i & 2) { + zeus::CAABox(pos).splitX(neg, pos); + if (i & 1) + return pos; + else + return neg; + } else { + zeus::CAABox(neg).splitX(neg, pos); + if (i & 1) + return pos; + else + return neg; } + } } -void AROTBuilder::Node::mergeSets(int a, int b) -{ - childNodes[a].childIndices.insert(childNodes[b].childIndices.cbegin(), childNodes[b].childIndices.cend()); - childNodes[b].childIndices = childNodes[a].childIndices; +void AROTBuilder::Node::mergeSets(int a, int b) { + childNodes[a].childIndices.insert(childNodes[b].childIndices.cbegin(), childNodes[b].childIndices.cend()); + childNodes[b].childIndices = childNodes[a].childIndices; } -bool AROTBuilder::Node::compareSets(int a, int b) const -{ - return childNodes[a].childIndices != childNodes[b].childIndices; +bool AROTBuilder::Node::compareSets(int a, int b) const { + return childNodes[a].childIndices != childNodes[b].childIndices; } void AROTBuilder::Node::addChild(int level, int minChildren, const std::vector& triBoxes, - const zeus::CAABox& curAABB, BspNodeType& typeOut) -{ - /* Gather intersecting faces */ - for (int i=0 ; i(); - flags = 0; - } + if (!compSubdivs) { + typeOut = BspNodeType::Leaf; + childNodes = std::vector(); + flags = 0; + } } -size_t AROTBuilder::BitmapPool::addIndices(const std::set& indices) -{ - for (size_t i=0 ; i& indices) { + for (size_t i = 0; i < m_pool.size(); ++i) + if (m_pool[i] == indices) + return i; + m_pool.push_back(indices); + return m_pool.size() - 1; } -static const uint32_t AROTChildCounts[] = { 0, 2, 2, 4, 2, 4, 4, 8 }; +static const uint32_t AROTChildCounts[] = {0, 2, 2, 4, 2, 4, 4, 8}; -void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff) -{ - sz += 1; - poolIdx = bmpPool.addIndices(childIndices); - if (poolIdx > 65535) - Log.report(logvisor::Fatal, "AROT bitmap exceeds 16-bit node addressing; area too complex"); +void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff) { + sz += 1; + poolIdx = bmpPool.addIndices(childIndices); + if (poolIdx > 65535) + Log.report(logvisor::Fatal, "AROT bitmap exceeds 16-bit node addressing; area too complex"); - uint32_t childCount = AROTChildCounts[compSubdivs]; - nodeOff = curOff; - nodeSz = childCount * 2 + 4; - curOff += nodeSz; - if (childNodes.size()) - { - for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k) - { - for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j) - { - for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i) - { - int idx = k*4 + j*2 + i; - childNodes[idx].nodeCount(sz, idxRefs, bmpPool, curOff); - } - } + uint32_t childCount = AROTChildCounts[compSubdivs]; + nodeOff = curOff; + nodeSz = childCount * 2 + 4; + curOff += nodeSz; + if (childNodes.size()) { + for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) { + for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) { + for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) { + int idx = k * 4 + j * 2 + i; + childNodes[idx].nodeCount(sz, idxRefs, bmpPool, curOff); } - idxRefs += childCount; + } } + idxRefs += childCount; + } } -void AROTBuilder::Node::writeIndirectionTable(athena::io::MemoryWriter& w) -{ - w.writeUint32Big(nodeOff); - if (childNodes.size()) - { - for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k) - { - for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j) - { - for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i) - { - int idx = k*4 + j*2 + i; - childNodes[idx].writeIndirectionTable(w); - } - } +void AROTBuilder::Node::writeIndirectionTable(athena::io::MemoryWriter& w) { + w.writeUint32Big(nodeOff); + if (childNodes.size()) { + for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) { + for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) { + for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) { + int idx = k * 4 + j * 2 + i; + childNodes[idx].writeIndirectionTable(w); } + } } + } } -void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx) -{ - w.writeUint16Big(poolIdx); - w.writeUint16Big(compSubdivs); +void AROTBuilder::Node::writeNodes(athena::io::MemoryWriter& w, int nodeIdx) { + w.writeUint16Big(poolIdx); + w.writeUint16Big(compSubdivs); - if (childNodes.size()) - { - int curIdx = nodeIdx + 1; - if (curIdx > 65535) - Log.report(logvisor::Fatal, "AROT node exceeds 16-bit node addressing; area too complex"); + if (childNodes.size()) { + int curIdx = nodeIdx + 1; + if (curIdx > 65535) + Log.report(logvisor::Fatal, "AROT node exceeds 16-bit node addressing; area too complex"); - int childIndices[8]; + int childIndices[8]; - for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k) - { - for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j) - { - for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i) - { - int idx = k*4 + j*2 + i; - w.writeUint16Big(curIdx); - childIndices[idx] = curIdx; - childNodes[idx].advanceIndex(curIdx); - } - } - } - - for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k) - { - for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j) - { - for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i) - { - int idx = k*4 + j*2 + i; - childNodes[idx].writeNodes(w, childIndices[idx]); - } - } + for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) { + for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) { + for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) { + int idx = k * 4 + j * 2 + i; + w.writeUint16Big(curIdx); + childIndices[idx] = curIdx; + childNodes[idx].advanceIndex(curIdx); } + } } + + for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) { + for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) { + for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) { + int idx = k * 4 + j * 2 + i; + childNodes[idx].writeNodes(w, childIndices[idx]); + } + } + } + } } -void AROTBuilder::Node::advanceIndex(int& nodeIdx) -{ - ++nodeIdx; - if (childNodes.size()) - { - for (int k=0 ; k < 1 + ((compSubdivs & 0x4) != 0) ; ++k) - { - for (int j=0 ; j < 1 + ((compSubdivs & 0x2) != 0) ; ++j) - { - for (int i=0 ; i < 1 + ((compSubdivs & 0x1) != 0) ; ++i) - { - int idx = k*4 + j*2 + i; - childNodes[idx].advanceIndex(nodeIdx); - } - } +void AROTBuilder::Node::advanceIndex(int& nodeIdx) { + ++nodeIdx; + if (childNodes.size()) { + for (int k = 0; k < 1 + ((compSubdivs & 0x4) != 0); ++k) { + for (int j = 0; j < 1 + ((compSubdivs & 0x2) != 0); ++j) { + for (int i = 0; i < 1 + ((compSubdivs & 0x1) != 0); ++i) { + int idx = k * 4 + j * 2 + i; + childNodes[idx].advanceIndex(nodeIdx); } + } } + } } -void AROTBuilder::Node::colSize(size_t& totalSz) -{ - if (childIndices.size()) - { - nodeOff = totalSz; - if (childNodes.empty()) - { - totalSz += 26 + childIndices.size() * 2; - } - else - { - totalSz += 36; - for (int i=0 ; i<8 ; ++i) - childNodes[i].colSize(totalSz); - } +void AROTBuilder::Node::colSize(size_t& totalSz) { + if (childIndices.size()) { + nodeOff = totalSz; + if (childNodes.empty()) { + totalSz += 26 + childIndices.size() * 2; + } else { + totalSz += 36; + for (int i = 0; i < 8; ++i) + childNodes[i].colSize(totalSz); } + } } -void AROTBuilder::Node::writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB) -{ - if (childIndices.size()) - { - if (childNodes.empty()) - { - float* aabbOut = reinterpret_cast(ptr); - aabbOut[0] = hecl::SBig(curAABB.min[0]); - aabbOut[1] = hecl::SBig(curAABB.min[1]); - aabbOut[2] = hecl::SBig(curAABB.min[2]); - aabbOut[3] = hecl::SBig(curAABB.max[0]); - aabbOut[4] = hecl::SBig(curAABB.max[1]); - aabbOut[5] = hecl::SBig(curAABB.max[2]); - athena::io::MemoryWriter w(ptr + 24, INT32_MAX); - w.writeUint16Big(childIndices.size()); - for (int idx : childIndices) - w.writeUint16Big(idx); - ptr += 26 + childIndices.size() * 2; - } - else - { - uint16_t* pflags = reinterpret_cast(ptr); - uint32_t* offsets = reinterpret_cast(ptr + 4); - memset(pflags, 0, sizeof(uint32_t) * 9); - for (int i=0 ; i<8 ; ++i) - { - const Node& chNode = childNodes[i]; - BspNodeType type = BspNodeType((flags >> (i * 2)) & 0x3); - if (type != BspNodeType::Invalid) - offsets[i] = hecl::SBig(uint32_t(chNode.nodeOff - nodeOff - 36)); - } +void AROTBuilder::Node::writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB) { + if (childIndices.size()) { + if (childNodes.empty()) { + float* aabbOut = reinterpret_cast(ptr); + aabbOut[0] = hecl::SBig(curAABB.min[0]); + aabbOut[1] = hecl::SBig(curAABB.min[1]); + aabbOut[2] = hecl::SBig(curAABB.min[2]); + aabbOut[3] = hecl::SBig(curAABB.max[0]); + aabbOut[4] = hecl::SBig(curAABB.max[1]); + aabbOut[5] = hecl::SBig(curAABB.max[2]); + athena::io::MemoryWriter w(ptr + 24, INT32_MAX); + w.writeUint16Big(childIndices.size()); + for (int idx : childIndices) + w.writeUint16Big(idx); + ptr += 26 + childIndices.size() * 2; + } else { + uint16_t* pflags = reinterpret_cast(ptr); + uint32_t* offsets = reinterpret_cast(ptr + 4); + memset(pflags, 0, sizeof(uint32_t) * 9); + for (int i = 0; i < 8; ++i) { + const Node& chNode = childNodes[i]; + BspNodeType type = BspNodeType((flags >> (i * 2)) & 0x3); + if (type != BspNodeType::Invalid) + offsets[i] = hecl::SBig(uint32_t(chNode.nodeOff - nodeOff - 36)); + } - *pflags = hecl::SBig(flags); - ptr += 36; + *pflags = hecl::SBig(flags); + ptr += 36; - for (int i=0 ; i<8 ; ++i) - childNodes[i].writeColNodes(ptr, SplitAABB(curAABB, i)); - } + for (int i = 0; i < 8; ++i) + childNodes[i].writeColNodes(ptr, SplitAABB(curAABB, i)); } + } } -void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount) -{ - ++nodeCount; - if (childNodes.empty()) - { - lookupCount += childIndices.size(); - } - else - { - for (int i=0 ; i<8 ; ++i) - childNodes[i].pathCountNodesAndLookups(nodeCount, lookupCount); - } +void AROTBuilder::Node::pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount) { + ++nodeCount; + if (childNodes.empty()) { + lookupCount += childIndices.size(); + } else { + for (int i = 0; i < 8; ++i) + childNodes[i].pathCountNodesAndLookups(nodeCount, lookupCount); + } } -void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB) -{ - if (childNodes.empty()) - { - path.octree.emplace_back(); - DNAMP1::PATH::OctreeNode& n = path.octree.back(); - n.isLeaf = 1; - n.aabb[0] = curAABB.min; - n.aabb[1] = curAABB.max; - n.centroid = curAABB.center(); - for (int i=0 ; i<8 ; ++i) - n.children[i] = 0xffffffff; - n.regionCount = childIndices.size(); - n.regionStart = path.octreeRegionLookup.size(); - for (int r : childIndices) - path.octreeRegionLookup.push_back(r); +void AROTBuilder::Node::pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB) { + if (childNodes.empty()) { + path.octree.emplace_back(); + DNAMP1::PATH::OctreeNode& n = path.octree.back(); + n.isLeaf = 1; + n.aabb[0] = curAABB.min; + n.aabb[1] = curAABB.max; + n.centroid = curAABB.center(); + for (int i = 0; i < 8; ++i) + n.children[i] = 0xffffffff; + n.regionCount = childIndices.size(); + n.regionStart = path.octreeRegionLookup.size(); + for (int r : childIndices) + path.octreeRegionLookup.push_back(r); + } else { + atUint32 children[8]; + for (int i = 0; i < 8; ++i) { + /* Head recursion (first node will be a leaf) */ + children[i] = path.octree.size(); + childNodes[i].pathWrite(path, SplitAABB(curAABB, i)); } - else - { - atUint32 children[8]; - for (int i=0 ; i<8 ; ++i) - { - /* Head recursion (first node will be a leaf) */ - children[i] = path.octree.size(); - childNodes[i].pathWrite(path, SplitAABB(curAABB, i)); - } - path.octree.emplace_back(); - DNAMP1::PATH::OctreeNode& n = path.octree.back(); - n.isLeaf = 0; - n.aabb[0] = curAABB.min; - n.aabb[1] = curAABB.max; - n.centroid = curAABB.center(); - for (int i=0 ; i<8 ; ++i) - n.children[i] = children[i]; - n.regionCount = 0; - n.regionStart = 0; - } + path.octree.emplace_back(); + DNAMP1::PATH::OctreeNode& n = path.octree.back(); + n.isLeaf = 0; + n.aabb[0] = curAABB.min; + n.aabb[1] = curAABB.max; + n.centroid = curAABB.center(); + for (int i = 0; i < 8; ++i) + n.children[i] = children[i]; + n.regionCount = 0; + n.regionStart = 0; + } } void AROTBuilder::build(std::vector>& secs, const zeus::CAABox& fullAabb, - const std::vector& meshAabbs, const std::vector& meshes) -{ - /* Recursively split */ - BspNodeType rootType; - rootNode.addChild(0, AROT_MIN_MODELS, meshAabbs, fullAabb, rootType); + const std::vector& meshAabbs, const std::vector& meshes) { + /* Recursively split */ + BspNodeType rootType; + rootNode.addChild(0, AROT_MIN_MODELS, meshAabbs, fullAabb, rootType); - /* Calculate indexing metrics */ - size_t totalNodeCount = 0; - size_t idxRefCount = 0; - size_t curOff = 0; - rootNode.nodeCount(totalNodeCount, idxRefCount, bmpPool, curOff); - size_t bmpWordCount = ROUND_UP_32(meshes.size()) / 32; - size_t arotSz = 64 + bmpWordCount * bmpPool.m_pool.size() * 4 + totalNodeCount * 8 + idxRefCount * 2; + /* Calculate indexing metrics */ + size_t totalNodeCount = 0; + size_t idxRefCount = 0; + size_t curOff = 0; + rootNode.nodeCount(totalNodeCount, idxRefCount, bmpPool, curOff); + size_t bmpWordCount = ROUND_UP_32(meshes.size()) / 32; + size_t arotSz = 64 + bmpWordCount * bmpPool.m_pool.size() * 4 + totalNodeCount * 8 + idxRefCount * 2; - /* Write header */ - secs.emplace_back(arotSz, 0); - athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); - w.writeUint32Big('AROT'); - w.writeUint32Big(1); - w.writeUint32Big(bmpPool.m_pool.size()); - w.writeUint32Big(meshes.size()); - w.writeUint32Big(totalNodeCount); - w.writeVec3fBig(fullAabb.min); - w.writeVec3fBig(fullAabb.max); - w.seekAlign32(); + /* Write header */ + secs.emplace_back(arotSz, 0); + athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); + w.writeUint32Big('AROT'); + w.writeUint32Big(1); + w.writeUint32Big(bmpPool.m_pool.size()); + w.writeUint32Big(meshes.size()); + w.writeUint32Big(totalNodeCount); + w.writeVec3fBig(fullAabb.min); + w.writeVec3fBig(fullAabb.max); + w.seekAlign32(); - /* Write bitmap */ - std::vector bmpWords; - bmpWords.reserve(bmpWordCount); - for (const std::set& bmp : bmpPool.m_pool) - { - bmpWords.clear(); - bmpWords.resize(bmpWordCount); + /* Write bitmap */ + std::vector bmpWords; + bmpWords.reserve(bmpWordCount); + for (const std::set& bmp : bmpPool.m_pool) { + bmpWords.clear(); + bmpWords.resize(bmpWordCount); - auto bmpIt = bmp.cbegin(); - if (bmpIt != bmp.cend()) - { - int curIdx = 0; - for (int w=0 ; w, uint32_t> AROTBuilder::buildCol(const ColMesh& mesh, BspNodeType& rootOut) -{ - /* Accumulate total AABB */ - zeus::CAABox fullAABB; - for (const auto& vert : mesh.verts) - fullAABB.accumulateBounds(zeus::CVector3f(vert)); +std::pair, uint32_t> AROTBuilder::buildCol(const ColMesh& mesh, BspNodeType& rootOut) { + /* Accumulate total AABB */ + zeus::CAABox fullAABB; + for (const auto& vert : mesh.verts) + fullAABB.accumulateBounds(zeus::CVector3f(vert)); - /* Predetermine triangle AABBs */ - std::vector triBoxes; - triBoxes.reserve(mesh.trianges.size()); - for (const ColMesh::Triangle& tri : mesh.trianges) - { - triBoxes.emplace_back(); - zeus::CAABox& aabb = triBoxes.back(); - for (int e=0 ; e<3 ; ++e) - { - const ColMesh::Edge& edge = mesh.edges[tri.edges[e]]; - for (int v=0 ; v<2 ; ++v) - { - const auto& vert = mesh.verts[edge.verts[v]]; - aabb.accumulateBounds(zeus::CVector3f(vert)); - } - } + /* Predetermine triangle AABBs */ + std::vector triBoxes; + triBoxes.reserve(mesh.trianges.size()); + for (const ColMesh::Triangle& tri : mesh.trianges) { + triBoxes.emplace_back(); + zeus::CAABox& aabb = triBoxes.back(); + for (int e = 0; e < 3; ++e) { + const ColMesh::Edge& edge = mesh.edges[tri.edges[e]]; + for (int v = 0; v < 2; ++v) { + const auto& vert = mesh.verts[edge.verts[v]]; + aabb.accumulateBounds(zeus::CVector3f(vert)); + } } + } - /* Recursively split */ - rootNode.addChild(0, COLLISION_MIN_NODE_TRIANGLES, triBoxes, fullAABB, rootOut); + /* Recursively split */ + rootNode.addChild(0, COLLISION_MIN_NODE_TRIANGLES, triBoxes, fullAABB, rootOut); - /* Calculate offsets and write out */ - size_t totalSize = 0; - rootNode.colSize(totalSize); - std::unique_ptr ret(new uint8_t[totalSize]); - uint8_t* ptr = ret.get(); - rootNode.writeColNodes(ptr, fullAABB); + /* Calculate offsets and write out */ + size_t totalSize = 0; + rootNode.colSize(totalSize); + std::unique_ptr ret(new uint8_t[totalSize]); + uint8_t* ptr = ret.get(); + rootNode.writeColNodes(ptr, fullAABB); - return {std::move(ret), totalSize}; + return {std::move(ret), totalSize}; } -void AROTBuilder::buildPath(DNAMP1::PATH& path) -{ - /* Accumulate total AABB and gather region boxes */ - std::vector regionBoxes; - regionBoxes.reserve(path.regions.size()); - zeus::CAABox fullAABB; - for (const DNAMP1::PATH::Region& r : path.regions) - { - regionBoxes.emplace_back(r.aabb[0], r.aabb[1]); - fullAABB.accumulateBounds(regionBoxes.back()); - } +void AROTBuilder::buildPath(DNAMP1::PATH& path) { + /* Accumulate total AABB and gather region boxes */ + std::vector regionBoxes; + regionBoxes.reserve(path.regions.size()); + zeus::CAABox fullAABB; + for (const DNAMP1::PATH::Region& r : path.regions) { + regionBoxes.emplace_back(r.aabb[0], r.aabb[1]); + fullAABB.accumulateBounds(regionBoxes.back()); + } - /* Recursively split */ - BspNodeType dontCare; - rootNode.addChild(0, PATH_MIN_NODE_REGIONS, regionBoxes, fullAABB, dontCare); + /* Recursively split */ + BspNodeType dontCare; + rootNode.addChild(0, PATH_MIN_NODE_REGIONS, regionBoxes, fullAABB, dontCare); - /* Write out */ - size_t nodeCount = 0; - size_t lookupCount = 0; - rootNode.pathCountNodesAndLookups(nodeCount, lookupCount); - path.octreeNodeCount = nodeCount; - path.octree.reserve(nodeCount); - path.octreeRegionLookupCount = lookupCount; - path.octreeRegionLookup.reserve(lookupCount); - rootNode.pathWrite(path, fullAABB); + /* Write out */ + size_t nodeCount = 0; + size_t lookupCount = 0; + rootNode.pathCountNodesAndLookups(nodeCount, lookupCount); + path.octreeNodeCount = nodeCount; + path.octree.reserve(nodeCount); + path.octreeRegionLookupCount = lookupCount; + path.octreeRegionLookup.reserve(lookupCount); + rootNode.pathWrite(path, fullAABB); } -} +} // namespace DataSpec diff --git a/DataSpec/DNACommon/AROTBuilder.hpp b/DataSpec/DNACommon/AROTBuilder.hpp index da8bac3e5..1ecabbce7 100644 --- a/DataSpec/DNACommon/AROTBuilder.hpp +++ b/DataSpec/DNACommon/AROTBuilder.hpp @@ -6,55 +6,49 @@ #include "CMDL.hpp" #include -namespace DataSpec -{ -namespace DNAMP1 -{ +namespace DataSpec { +namespace DNAMP1 { struct PATH; } -struct AROTBuilder -{ - using ColMesh = hecl::blender::ColMesh; +struct AROTBuilder { + using ColMesh = hecl::blender::ColMesh; - struct BitmapPool - { - std::vector> m_pool; - size_t addIndices(const std::set& indices); - } bmpPool; + struct BitmapPool { + std::vector> m_pool; + size_t addIndices(const std::set& indices); + } bmpPool; - struct Node - { - std::vector childNodes; - std::set childIndices; - size_t poolIdx = 0; - uint16_t flags = 0; - uint16_t compSubdivs = 0; + struct Node { + std::vector childNodes; + std::set childIndices; + size_t poolIdx = 0; + uint16_t flags = 0; + uint16_t compSubdivs = 0; - size_t nodeOff = 0; - size_t nodeSz = 4; + size_t nodeOff = 0; + size_t nodeSz = 4; - void addChild(int level, int minChildren, const std::vector& triBoxes, - const zeus::CAABox& curAABB, BspNodeType& typeOut); - void mergeSets(int a, int b); - bool compareSets(int a, int b) const; - void nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff); - void writeIndirectionTable(athena::io::MemoryWriter& w); - void writeNodes(athena::io::MemoryWriter& w, int nodeIdx); - void advanceIndex(int& nodeIdx); + void addChild(int level, int minChildren, const std::vector& triBoxes, const zeus::CAABox& curAABB, + BspNodeType& typeOut); + void mergeSets(int a, int b); + bool compareSets(int a, int b) const; + void nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPool, size_t& curOff); + void writeIndirectionTable(athena::io::MemoryWriter& w); + void writeNodes(athena::io::MemoryWriter& w, int nodeIdx); + void advanceIndex(int& nodeIdx); - void colSize(size_t& totalSz); - void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB); + void colSize(size_t& totalSz); + void writeColNodes(uint8_t*& ptr, const zeus::CAABox& curAABB); - void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount); - void pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB); - } rootNode; + void pathCountNodesAndLookups(size_t& nodeCount, size_t& lookupCount); + void pathWrite(DNAMP1::PATH& path, const zeus::CAABox& curAABB); + } rootNode; - void build(std::vector>& secs, const zeus::CAABox& fullAabb, - const std::vector& meshAabbs, const std::vector& meshes); - std::pair, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut); - void buildPath(DNAMP1::PATH& path); + void build(std::vector>& secs, const zeus::CAABox& fullAabb, + const std::vector& meshAabbs, const std::vector& meshes); + std::pair, uint32_t> buildCol(const ColMesh& mesh, BspNodeType& rootOut); + void buildPath(DNAMP1::PATH& path); }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/ATBL.cpp b/DataSpec/DNACommon/ATBL.cpp index 94e83f7f7..49e0fa459 100644 --- a/DataSpec/DNACommon/ATBL.cpp +++ b/DataSpec/DNACommon/ATBL.cpp @@ -1,61 +1,55 @@ #include "ATBL.hpp" -namespace DataSpec::DNAAudio -{ +namespace DataSpec::DNAAudio { -bool ATBL::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - uint32_t idxCount = rs.readUint32Big(); - athena::io::YAMLDocWriter w("ATBL"); - for (uint32_t i=0 ; im_mapChildren) - { - unsigned long i = strtoul(pair.first.c_str(), nullptr, 0); - maxI = std::max(maxI, i); - } + unsigned long maxI = 0; + for (const auto& pair : dr.getRootNode()->m_mapChildren) { + unsigned long i = strtoul(pair.first.c_str(), nullptr, 0); + maxI = std::max(maxI, i); + } - std::vector vecOut; - vecOut.resize(maxI + 1, 0xffff); + std::vector vecOut; + vecOut.resize(maxI + 1, 0xffff); - for (const auto& pair : dr.getRootNode()->m_mapChildren) - { - unsigned long i = strtoul(pair.first.c_str(), nullptr, 0); - vecOut[i] = hecl::SBig(uint16_t(strtoul(pair.second->m_scalarString.c_str(), nullptr, 0))); - } + for (const auto& pair : dr.getRootNode()->m_mapChildren) { + unsigned long i = strtoul(pair.first.c_str(), nullptr, 0); + vecOut[i] = hecl::SBig(uint16_t(strtoul(pair.second->m_scalarString.c_str(), nullptr, 0))); + } - athena::io::FileWriter w(outPath.getAbsolutePath()); - if (w.hasError()) - return false; - w.writeUint32Big(uint32_t(vecOut.size())); - w.writeBytes(vecOut.data(), vecOut.size() * 2); + athena::io::FileWriter w(outPath.getAbsolutePath()); + if (w.hasError()) + return false; + w.writeUint32Big(uint32_t(vecOut.size())); + w.writeBytes(vecOut.data(), vecOut.size() * 2); - return true; + return true; } -} +} // namespace DataSpec::DNAAudio diff --git a/DataSpec/DNACommon/ATBL.hpp b/DataSpec/DNACommon/ATBL.hpp index 42bdf1863..406e3869c 100644 --- a/DataSpec/DNACommon/ATBL.hpp +++ b/DataSpec/DNACommon/ATBL.hpp @@ -3,15 +3,12 @@ #include "DNACommon.hpp" #include "PAK.hpp" -namespace DataSpec::DNAAudio -{ +namespace DataSpec::DNAAudio { -class ATBL -{ +class ATBL { public: - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath); + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath); }; -} - +} // namespace DataSpec::DNAAudio diff --git a/DataSpec/DNACommon/BabeDead.cpp b/DataSpec/DNACommon/BabeDead.cpp index 12c8b9976..b804470cb 100644 --- a/DataSpec/DNACommon/BabeDead.cpp +++ b/DataSpec/DNACommon/BabeDead.cpp @@ -4,163 +4,156 @@ #include "zeus/CTransform.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec -{ +namespace DataSpec { -template -void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, - const BabeDeadLight& light, unsigned s, unsigned l) -{ - switch (light.lightType) - { - case BabeDeadLight::LightType::LocalAmbient: - case BabeDeadLight::LightType::LocalAmbient2: - os.format("bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n" - "bg_node.inputs[1].default_value = %f\n", - light.color.simd[0], light.color.simd[1], light.color.simd[2], - light.q / 8.f); - return; - case BabeDeadLight::LightType::Directional: - os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SUN')\n" - "lamp.color = (%f,%f,%f)\n" - "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" - "lamp_obj.rotation_mode = 'QUATERNION'\n" - "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n" - "lamp.shadow_method = '%s'\n" - "\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], - light.direction.simd[0], light.direction.simd[1], light.direction.simd[2], - light.castShadows ? "RAY_SHADOW" : "NOSHADOW"); - return; - case BabeDeadLight::LightType::Custom: - os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'POINT')\n" - "lamp.color = (%f,%f,%f)\n" - "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" - "lamp.shadow_soft_size = 1.0\n" - "lamp.shadow_method = '%s'\n" - "\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], - light.castShadows ? "RAY_SHADOW" : "NOSHADOW"); - break; - case BabeDeadLight::LightType::Spot: - case BabeDeadLight::LightType::Spot2: - os.format("lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n" - "lamp.color = (%f,%f,%f)\n" - "lamp.spot_size = %.6g\n" - "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" - "lamp_obj.rotation_mode = 'QUATERNION'\n" - "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n" - "lamp.shadow_soft_size = 0.5\n" - "lamp.shadow_method = '%s'\n" - "\n", s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], - zeus::degToRad(light.spotCutoff), - light.direction.simd[0], light.direction.simd[1], light.direction.simd[2], - light.castShadows ? "RAY_SHADOW" : "NOSHADOW"); - break; - default: return; - } +template +void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLight& light, unsigned s, unsigned l) { + switch (light.lightType) { + case BabeDeadLight::LightType::LocalAmbient: + case BabeDeadLight::LightType::LocalAmbient2: + os.format( + "bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n" + "bg_node.inputs[1].default_value = %f\n", + light.color.simd[0], light.color.simd[1], light.color.simd[2], light.q / 8.f); + return; + case BabeDeadLight::LightType::Directional: + os.format( + "lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SUN')\n" + "lamp.color = (%f,%f,%f)\n" + "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" + "lamp_obj.rotation_mode = 'QUATERNION'\n" + "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n" + "lamp.shadow_method = '%s'\n" + "\n", + s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], light.direction.simd[0], + light.direction.simd[1], light.direction.simd[2], light.castShadows ? "RAY_SHADOW" : "NOSHADOW"); + return; + case BabeDeadLight::LightType::Custom: + os.format( + "lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'POINT')\n" + "lamp.color = (%f,%f,%f)\n" + "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" + "lamp.shadow_soft_size = 1.0\n" + "lamp.shadow_method = '%s'\n" + "\n", + s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], + light.castShadows ? "RAY_SHADOW" : "NOSHADOW"); + break; + case BabeDeadLight::LightType::Spot: + case BabeDeadLight::LightType::Spot2: + os.format( + "lamp = bpy.data.lamps.new('LAMP_%01u_%03u', 'SPOT')\n" + "lamp.color = (%f,%f,%f)\n" + "lamp.spot_size = %.6g\n" + "lamp_obj = bpy.data.objects.new(lamp.name, lamp)\n" + "lamp_obj.rotation_mode = 'QUATERNION'\n" + "lamp_obj.rotation_quaternion = Vector((0,0,-1)).rotation_difference(Vector((%f,%f,%f)))\n" + "lamp.shadow_soft_size = 0.5\n" + "lamp.shadow_method = '%s'\n" + "\n", + s, l, light.color.simd[0], light.color.simd[1], light.color.simd[2], zeus::degToRad(light.spotCutoff), + light.direction.simd[0], light.direction.simd[1], light.direction.simd[2], + light.castShadows ? "RAY_SHADOW" : "NOSHADOW"); + break; + default: + return; + } - os.format("lamp.retro_layer = %u\n" - "lamp.retro_origtype = %u\n" - "lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n" - "lamp.constant_coefficient = 0\n" - "lamp.use_nodes = True\n" - "falloff_node = lamp.node_tree.nodes.new('ShaderNodeLightFalloff')\n" - "lamp.energy = 0.0\n" - "falloff_node.inputs[0].default_value = %f\n" - "hue_sat_node = lamp.node_tree.nodes.new('ShaderNodeHueSaturation')\n" - "hue_sat_node.inputs[1].default_value = 1.25\n" - "hue_sat_node.inputs[4].default_value = (%f,%f,%f,1.0)\n" - "lamp.node_tree.links.new(hue_sat_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[0])\n" - "lamp_obj.location = (%f,%f,%f)\n" - "bpy.context.scene.objects.link(lamp_obj)\n" - "\n", s, light.lightType, light.q / 8.f, - light.color.simd[0], light.color.simd[1], light.color.simd[2], - light.position.simd[0], light.position.simd[1], light.position.simd[2]); + os.format( + "lamp.retro_layer = %u\n" + "lamp.retro_origtype = %u\n" + "lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n" + "lamp.constant_coefficient = 0\n" + "lamp.use_nodes = True\n" + "falloff_node = lamp.node_tree.nodes.new('ShaderNodeLightFalloff')\n" + "lamp.energy = 0.0\n" + "falloff_node.inputs[0].default_value = %f\n" + "hue_sat_node = lamp.node_tree.nodes.new('ShaderNodeHueSaturation')\n" + "hue_sat_node.inputs[1].default_value = 1.25\n" + "hue_sat_node.inputs[4].default_value = (%f,%f,%f,1.0)\n" + "lamp.node_tree.links.new(hue_sat_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[0])\n" + "lamp_obj.location = (%f,%f,%f)\n" + "bpy.context.scene.objects.link(lamp_obj)\n" + "\n", + s, light.lightType, light.q / 8.f, light.color.simd[0], light.color.simd[1], light.color.simd[2], + light.position.simd[0], light.position.simd[1], light.position.simd[2]); - switch (light.falloff) - { - case BabeDeadLight::Falloff::Constant: - os << "falloff_node.inputs[0].default_value *= 150.0\n" - "lamp.node_tree.links.new(falloff_node.outputs[2], lamp.node_tree.nodes['Emission'].inputs[1])\n"; - if (light.q > FLT_EPSILON) - os.format("lamp.constant_coefficient = 2.0 / %f\n", light.q); - break; - case BabeDeadLight::Falloff::Linear: - os << "lamp.node_tree.links.new(falloff_node.outputs[1], lamp.node_tree.nodes['Emission'].inputs[1])\n"; - if (light.q > FLT_EPSILON) - os.format("lamp.linear_coefficient = 250 / %f\n", light.q); - break; - case BabeDeadLight::Falloff::Quadratic: - os << "lamp.node_tree.links.new(falloff_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[1])\n"; - if (light.q > FLT_EPSILON) - os.format("lamp.quadratic_coefficient = 25000 / %f\n", light.q); - break; - default: break; - } + switch (light.falloff) { + case BabeDeadLight::Falloff::Constant: + os << "falloff_node.inputs[0].default_value *= 150.0\n" + "lamp.node_tree.links.new(falloff_node.outputs[2], lamp.node_tree.nodes['Emission'].inputs[1])\n"; + if (light.q > FLT_EPSILON) + os.format("lamp.constant_coefficient = 2.0 / %f\n", light.q); + break; + case BabeDeadLight::Falloff::Linear: + os << "lamp.node_tree.links.new(falloff_node.outputs[1], lamp.node_tree.nodes['Emission'].inputs[1])\n"; + if (light.q > FLT_EPSILON) + os.format("lamp.linear_coefficient = 250 / %f\n", light.q); + break; + case BabeDeadLight::Falloff::Quadratic: + os << "lamp.node_tree.links.new(falloff_node.outputs[0], lamp.node_tree.nodes['Emission'].inputs[1])\n"; + if (light.q > FLT_EPSILON) + os.format("lamp.quadratic_coefficient = 25000 / %f\n", light.q); + break; + default: + break; + } } -template void ReadBabeDeadLightToBlender -(hecl::blender::PyOutStream& os, const DNAMP1::MREA::BabeDeadLight& light, unsigned s, unsigned l); -template void ReadBabeDeadLightToBlender -(hecl::blender::PyOutStream& os, const DNAMP3::MREA::BabeDeadLight& light, unsigned s, unsigned l); +template void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, + const DNAMP1::MREA::BabeDeadLight& light, + unsigned s, unsigned l); +template void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, + const DNAMP3::MREA::BabeDeadLight& light, + unsigned s, unsigned l); -template -void WriteBabeDeadLightFromBlender(BabeDeadLight& lightOut, const hecl::blender::Light& lightIn) -{ - using InterType = hecl::blender::Light::Type; - switch (lightIn.type) - { - case InterType::Ambient: - lightOut.lightType = BabeDeadLight::LightType::LocalAmbient; - break; - case InterType::Directional: - lightOut.lightType = BabeDeadLight::LightType::Directional; - break; - case InterType::Custom: - default: - lightOut.lightType = BabeDeadLight::LightType::Custom; - break; - case InterType::Spot: - lightOut.lightType = BabeDeadLight::LightType::Spot; - break; - } +template +void WriteBabeDeadLightFromBlender(BabeDeadLight& lightOut, const hecl::blender::Light& lightIn) { + using InterType = hecl::blender::Light::Type; + switch (lightIn.type) { + case InterType::Ambient: + lightOut.lightType = BabeDeadLight::LightType::LocalAmbient; + break; + case InterType::Directional: + lightOut.lightType = BabeDeadLight::LightType::Directional; + break; + case InterType::Custom: + default: + lightOut.lightType = BabeDeadLight::LightType::Custom; + break; + case InterType::Spot: + lightOut.lightType = BabeDeadLight::LightType::Spot; + break; + } - if (lightIn.type == InterType::Ambient) - { - lightOut.falloff = BabeDeadLight::Falloff::Constant; - lightOut.q = lightIn.energy * 8.f; - } - else if (lightIn.linear > lightIn.constant && - lightIn.linear > lightIn.quadratic) - { - lightOut.falloff = BabeDeadLight::Falloff::Linear; - lightOut.q = 250.f / lightIn.linear; - } - else if (lightIn.quadratic > lightIn.constant && - lightIn.quadratic > lightIn.linear) - { - lightOut.falloff = BabeDeadLight::Falloff::Quadratic; - lightOut.q = 25000.f / lightIn.quadratic; - } - else - { - lightOut.falloff = BabeDeadLight::Falloff::Constant; - lightOut.q = 2.f / lightIn.constant; - } + if (lightIn.type == InterType::Ambient) { + lightOut.falloff = BabeDeadLight::Falloff::Constant; + lightOut.q = lightIn.energy * 8.f; + } else if (lightIn.linear > lightIn.constant && lightIn.linear > lightIn.quadratic) { + lightOut.falloff = BabeDeadLight::Falloff::Linear; + lightOut.q = 250.f / lightIn.linear; + } else if (lightIn.quadratic > lightIn.constant && lightIn.quadratic > lightIn.linear) { + lightOut.falloff = BabeDeadLight::Falloff::Quadratic; + lightOut.q = 25000.f / lightIn.quadratic; + } else { + lightOut.falloff = BabeDeadLight::Falloff::Constant; + lightOut.q = 2.f / lightIn.constant; + } - lightOut.color = lightIn.color; - lightOut.spotCutoff = zeus::radToDeg(lightIn.spotCutoff); - lightOut.castShadows = lightIn.shadow; - lightOut.position.simd[0] = lightIn.sceneXf[0].simd[3]; - lightOut.position.simd[1] = lightIn.sceneXf[1].simd[3]; - lightOut.position.simd[2] = lightIn.sceneXf[2].simd[3]; + lightOut.color = lightIn.color; + lightOut.spotCutoff = zeus::radToDeg(lightIn.spotCutoff); + lightOut.castShadows = lightIn.shadow; + lightOut.position.simd[0] = lightIn.sceneXf[0].simd[3]; + lightOut.position.simd[1] = lightIn.sceneXf[1].simd[3]; + lightOut.position.simd[2] = lightIn.sceneXf[2].simd[3]; - zeus::CTransform lightXf(&lightIn.sceneXf[0]); - lightOut.direction = (lightXf.basis.transposed() * zeus::CVector3f(0.f, 0.f, -1.f)).normalized(); + zeus::CTransform lightXf(&lightIn.sceneXf[0]); + lightOut.direction = (lightXf.basis.transposed() * zeus::CVector3f(0.f, 0.f, -1.f)).normalized(); } -template void WriteBabeDeadLightFromBlender -(DNAMP1::MREA::BabeDeadLight& lightOut, const hecl::blender::Light& lightIn); -template void WriteBabeDeadLightFromBlender -(DNAMP3::MREA::BabeDeadLight& lightOut, const hecl::blender::Light& lightIn); +template void WriteBabeDeadLightFromBlender(DNAMP1::MREA::BabeDeadLight& lightOut, + const hecl::blender::Light& lightIn); +template void WriteBabeDeadLightFromBlender(DNAMP3::MREA::BabeDeadLight& lightOut, + const hecl::blender::Light& lightIn); -} +} // namespace DataSpec diff --git a/DataSpec/DNACommon/BabeDead.hpp b/DataSpec/DNACommon/BabeDead.hpp index 49e00ffa1..7ef2662b0 100644 --- a/DataSpec/DNACommon/BabeDead.hpp +++ b/DataSpec/DNACommon/BabeDead.hpp @@ -4,15 +4,12 @@ #include "hecl/hecl.hpp" #include -namespace DataSpec -{ +namespace DataSpec { -template -void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, - const BabeDeadLight& light, unsigned s, unsigned l); +template +void ReadBabeDeadLightToBlender(hecl::blender::PyOutStream& os, const BabeDeadLight& light, unsigned s, unsigned l); -template +template void WriteBabeDeadLightFromBlender(BabeDeadLight& lightOut, const hecl::blender::Light& lightIn); -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/CMDL.cpp b/DataSpec/DNACommon/CMDL.cpp index f70b14c47..5fde36861 100644 --- a/DataSpec/DNACommon/CMDL.cpp +++ b/DataSpec/DNACommon/CMDL.cpp @@ -9,2494 +9,2261 @@ #include "zeus/CAABox.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNACMDL -{ +namespace DataSpec::DNACMDL { template -void GetVertexAttributes(const MaterialSet& matSet, - std::vector& attributesOut) -{ - attributesOut.clear(); - attributesOut.reserve(matSet.materials.size()); +void GetVertexAttributes(const MaterialSet& matSet, std::vector& attributesOut) { + attributesOut.clear(); + attributesOut.reserve(matSet.materials.size()); - for (const typename MaterialSet::Material& mat : matSet.materials) - { - const typename MaterialSet::Material::VAFlags& vaFlags = mat.getVAFlags(); - attributesOut.emplace_back(); - VertexAttributes& va = attributesOut.back(); + for (const typename MaterialSet::Material& mat : matSet.materials) { + const typename MaterialSet::Material::VAFlags& vaFlags = mat.getVAFlags(); + attributesOut.emplace_back(); + VertexAttributes& va = attributesOut.back(); - va.pos = vaFlags.position(); - va.norm = vaFlags.normal(); - va.color0 = vaFlags.color0(); - va.color1 = vaFlags.color1(); + va.pos = vaFlags.position(); + va.norm = vaFlags.normal(); + va.color0 = vaFlags.color0(); + va.color1 = vaFlags.color1(); - if ((va.uvs[0] = vaFlags.tex0())) - ++va.uvCount; - if ((va.uvs[1] = vaFlags.tex1())) - ++va.uvCount; - if ((va.uvs[2] = vaFlags.tex2())) - ++va.uvCount; - if ((va.uvs[3] = vaFlags.tex3())) - ++va.uvCount; - if ((va.uvs[4] = vaFlags.tex4())) - ++va.uvCount; - if ((va.uvs[5] = vaFlags.tex5())) - ++va.uvCount; - if ((va.uvs[6] = vaFlags.tex6())) - ++va.uvCount; + if ((va.uvs[0] = vaFlags.tex0())) + ++va.uvCount; + if ((va.uvs[1] = vaFlags.tex1())) + ++va.uvCount; + if ((va.uvs[2] = vaFlags.tex2())) + ++va.uvCount; + if ((va.uvs[3] = vaFlags.tex3())) + ++va.uvCount; + if ((va.uvs[4] = vaFlags.tex4())) + ++va.uvCount; + if ((va.uvs[5] = vaFlags.tex5())) + ++va.uvCount; + if ((va.uvs[6] = vaFlags.tex6())) + ++va.uvCount; - va.pnMtxIdx = vaFlags.pnMatIdx(); + va.pnMtxIdx = vaFlags.pnMatIdx(); - if ((va.texMtxIdx[0] = vaFlags.tex0MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[1] = vaFlags.tex1MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[2] = vaFlags.tex2MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[3] = vaFlags.tex3MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[4] = vaFlags.tex4MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[5] = vaFlags.tex5MatIdx())) - ++va.texMtxIdxCount; - if ((va.texMtxIdx[6] = vaFlags.tex6MatIdx())) - ++va.texMtxIdxCount; + if ((va.texMtxIdx[0] = vaFlags.tex0MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[1] = vaFlags.tex1MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[2] = vaFlags.tex2MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[3] = vaFlags.tex3MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[4] = vaFlags.tex4MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[5] = vaFlags.tex5MatIdx())) + ++va.texMtxIdxCount; + if ((va.texMtxIdx[6] = vaFlags.tex6MatIdx())) + ++va.texMtxIdxCount; - va.shortUVs = mat.getFlags().lightmapUVArray(); - } + va.shortUVs = mat.getFlags().lightmapUVArray(); + } } template -void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, - const MaterialSet& matSet, - const PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - unsigned setIdx) -{ - /* Texmaps */ - os << "texmap_list = []\n"; - for (const UniqueID32& tex : matSet.head.textureIDs) - { - std::string texName = pakRouter.getBestEntryName(tex); - const nod::Node* node; - const typename PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(tex, &node); - hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); - if (!txtrPath.isNone()) - { - txtrPath.makeDirChain(false); - PAKEntryReadStream rs = texEntry->beginReadStream(*node); - TXTR::Extract(rs, txtrPath); - } - hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex); - hecl::SystemUTF8Conv resPathView(resPath); - os.format("if '%s' in bpy.data.textures:\n" - " image = bpy.data.images['%s']\n" - " texture = bpy.data.textures[image.name]\n" - "else:\n" - " image = bpy.data.images.load('''//%s''')\n" - " image.name = '%s'\n" - " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" - " texture.image = image\n" - "texmap_list.append(texture)\n" - "\n", texName.c_str(), texName.c_str(), - resPathView.c_str(), texName.c_str()); +void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, unsigned setIdx) { + /* Texmaps */ + os << "texmap_list = []\n"; + for (const UniqueID32& tex : matSet.head.textureIDs) { + std::string texName = pakRouter.getBestEntryName(tex); + const nod::Node* node; + const typename PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(tex, &node); + hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); + if (!txtrPath.isNone()) { + txtrPath.makeDirChain(false); + PAKEntryReadStream rs = texEntry->beginReadStream(*node); + TXTR::Extract(rs, txtrPath); } + hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, tex); + hecl::SystemUTF8Conv resPathView(resPath); + os.format( + "if '%s' in bpy.data.textures:\n" + " image = bpy.data.images['%s']\n" + " texture = bpy.data.textures[image.name]\n" + "else:\n" + " image = bpy.data.images.load('''//%s''')\n" + " image.name = '%s'\n" + " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" + " texture.image = image\n" + "texmap_list.append(texture)\n" + "\n", + texName.c_str(), texName.c_str(), resPathView.c_str(), texName.c_str()); + } - unsigned m=0; - for (const typename MaterialSet::Material& mat : matSet.materials) - { - MaterialSet::ConstructMaterial(os, mat, setIdx, m++); - os << "materials.append(new_material)\n"; - } + unsigned m = 0; + for (const typename MaterialSet::Material& mat : matSet.materials) { + MaterialSet::ConstructMaterial(os, mat, setIdx, m++); + os << "materials.append(new_material)\n"; + } } template -void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os, - const MaterialSet& matSet, - const PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - unsigned setIdx) -{ - unsigned m=0; - for (const typename MaterialSet::Material& mat : matSet.materials) - { - MaterialSet::ConstructMaterial(os, pakRouter, entry, mat, setIdx, m++); - os << "materials.append(new_material)\n"; - } +void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, unsigned setIdx) { + unsigned m = 0; + for (const typename MaterialSet::Material& mat : matSet.materials) { + MaterialSet::ConstructMaterial(os, pakRouter, entry, mat, setIdx, m++); + os << "materials.append(new_material)\n"; + } } -template void ReadMaterialSetToBlender_3, DNAMP3::MaterialSet> -(hecl::blender::PyOutStream& os, - const DNAMP3::MaterialSet& matSet, - const PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - unsigned setIdx); +template void ReadMaterialSetToBlender_3, DNAMP3::MaterialSet>( + hecl::blender::PyOutStream& os, const DNAMP3::MaterialSet& matSet, const PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, unsigned setIdx); -class DLReader -{ +class DLReader { public: - /* Class used for splitting verts with shared positions but different skinning matrices */ - class ExtraVertTracker - { - std::map>> m_extraVerts; - atUint16 m_maxBasePos = 0; - atUint16 m_nextOverPos = 1; - public: - atInt16 addPosSkinPair(atUint16 pos, atInt16 skin) - { - m_maxBasePos = std::max(m_maxBasePos, pos); - auto search = m_extraVerts.find(pos); - if (search == m_extraVerts.end()) - { - m_extraVerts[pos] = {std::make_pair(skin, 0)}; - return skin; - } - std::vector>& vertTrack = search->second; - for (const std::pair& s : vertTrack) - if (s.first == skin) - return vertTrack.front().first; - vertTrack.push_back(std::make_pair(skin, m_nextOverPos++)); - return vertTrack.front().first; - } + /* Class used for splitting verts with shared positions but different skinning matrices */ + class ExtraVertTracker { + std::map>> m_extraVerts; + atUint16 m_maxBasePos = 0; + atUint16 m_nextOverPos = 1; - template - atUint32 sendAdditionalVertsToBlender(hecl::blender::PyOutStream& os, - const RigPair& rp, atUint32 baseVert) const - { - atUint32 addedVerts = 0; - atUint32 nextVert = 1; - while (nextVert < m_nextOverPos) - { - for (const std::pair>>& ev : m_extraVerts) - { - for (const std::pair& se : ev.second) - { - if (se.second == nextVert) - { - os.format("bm.verts.ensure_lookup_table()\n" - "orig_vert = bm.verts[%u]\n" - "vert = bm.verts.new(orig_vert.co)\n", - ev.first + baseVert); - rp.first->weightVertex(os, *rp.second, se.first); - ++nextVert; - ++addedVerts; - } - } - } - } - return addedVerts; - } + public: + atInt16 addPosSkinPair(atUint16 pos, atInt16 skin) { + m_maxBasePos = std::max(m_maxBasePos, pos); + auto search = m_extraVerts.find(pos); + if (search == m_extraVerts.end()) { + m_extraVerts[pos] = {std::make_pair(skin, 0)}; + return skin; + } + std::vector>& vertTrack = search->second; + for (const std::pair& s : vertTrack) + if (s.first == skin) + return vertTrack.front().first; + vertTrack.push_back(std::make_pair(skin, m_nextOverPos++)); + return vertTrack.front().first; + } - atUint16 lookupVertIdx(atUint16 pos, atInt16 skin) const - { - auto search = m_extraVerts.find(pos); - if (search == m_extraVerts.end()) - return -1; - const std::vector>& vertTrack = search->second; - if (vertTrack.front().first == skin) - return pos; - for (auto it=vertTrack.begin()+1 ; it!=vertTrack.end() ; ++it) - if (it->first == skin) - return m_maxBasePos + it->second; - return -1; + template + atUint32 sendAdditionalVertsToBlender(hecl::blender::PyOutStream& os, const RigPair& rp, atUint32 baseVert) const { + atUint32 addedVerts = 0; + atUint32 nextVert = 1; + while (nextVert < m_nextOverPos) { + for (const std::pair>>& ev : m_extraVerts) { + for (const std::pair& se : ev.second) { + if (se.second == nextVert) { + os.format( + "bm.verts.ensure_lookup_table()\n" + "orig_vert = bm.verts[%u]\n" + "vert = bm.verts.new(orig_vert.co)\n", + ev.first + baseVert); + rp.first->weightVertex(os, *rp.second, se.first); + ++nextVert; + ++addedVerts; + } + } } - }; + } + return addedVerts; + } + + atUint16 lookupVertIdx(atUint16 pos, atInt16 skin) const { + auto search = m_extraVerts.find(pos); + if (search == m_extraVerts.end()) + return -1; + const std::vector>& vertTrack = search->second; + if (vertTrack.front().first == skin) + return pos; + for (auto it = vertTrack.begin() + 1; it != vertTrack.end(); ++it) + if (it->first == skin) + return m_maxBasePos + it->second; + return -1; + } + }; private: - const VertexAttributes& m_va; - std::unique_ptr m_dl; - size_t m_dlSize; - ExtraVertTracker& m_evt; - const atInt16* m_bankIn; - atUint8* m_cur; - atUint16 readVal(GX::AttrType type) - { - atUint16 retval = 0; - switch (type) - { - case GX::DIRECT: - case GX::INDEX8: - if ((m_cur - m_dl.get()) >= intptr_t(m_dlSize)) - return 0; - retval = *m_cur; - ++m_cur; - break; - case GX::INDEX16: - if ((m_cur - m_dl.get() + 1) >= intptr_t(m_dlSize)) - return 0; - retval = hecl::SBig(*(atUint16*)m_cur); - m_cur += 2; - break; - default: break; - } - return retval; + const VertexAttributes& m_va; + std::unique_ptr m_dl; + size_t m_dlSize; + ExtraVertTracker& m_evt; + const atInt16* m_bankIn; + atUint8* m_cur; + atUint16 readVal(GX::AttrType type) { + atUint16 retval = 0; + switch (type) { + case GX::DIRECT: + case GX::INDEX8: + if ((m_cur - m_dl.get()) >= intptr_t(m_dlSize)) + return 0; + retval = *m_cur; + ++m_cur; + break; + case GX::INDEX16: + if ((m_cur - m_dl.get() + 1) >= intptr_t(m_dlSize)) + return 0; + retval = hecl::SBig(*(atUint16*)m_cur); + m_cur += 2; + break; + default: + break; } + return retval; + } + public: - DLReader(const VertexAttributes& va, std::unique_ptr&& dl, - size_t dlSize, ExtraVertTracker& evt, const atInt16* bankIn=nullptr) - : m_va(va), m_dl(std::move(dl)), m_dlSize(dlSize), m_evt(evt), m_bankIn(bankIn) - { - m_cur = m_dl.get(); + DLReader(const VertexAttributes& va, std::unique_ptr&& dl, size_t dlSize, ExtraVertTracker& evt, + const atInt16* bankIn = nullptr) + : m_va(va), m_dl(std::move(dl)), m_dlSize(dlSize), m_evt(evt), m_bankIn(bankIn) { + m_cur = m_dl.get(); + } + + operator bool() { return ((m_cur - m_dl.get()) < intptr_t(m_dlSize)) && *m_cur; } + + GX::Primitive readPrimitive() { return GX::Primitive(*m_cur++ & 0xf8); } + + GX::Primitive readPrimitiveAndVat(unsigned& vatOut) { + atUint8 val = *m_cur++; + vatOut = val & 0x7; + return GX::Primitive(val & 0xf8); + } + + atUint16 readVertCount() { + atUint16 retval = hecl::SBig(*(atUint16*)m_cur); + m_cur += 2; + return retval; + } + + struct DLPrimVert { + atUint16 pos = 0; + atUint16 norm = 0; + atUint16 color[2] = {0}; + atUint16 uvs[7] = {0}; + atUint8 pnMtxIdx = 0; + atUint8 texMtxIdx[7] = {0}; + }; + + DLPrimVert readVert(bool peek = false) { + atUint8* bakCur = m_cur; + DLPrimVert retval; + retval.pnMtxIdx = readVal(m_va.pnMtxIdx); + retval.texMtxIdx[0] = readVal(m_va.texMtxIdx[0]); + retval.texMtxIdx[1] = readVal(m_va.texMtxIdx[1]); + retval.texMtxIdx[2] = readVal(m_va.texMtxIdx[2]); + retval.texMtxIdx[3] = readVal(m_va.texMtxIdx[3]); + retval.texMtxIdx[4] = readVal(m_va.texMtxIdx[4]); + retval.texMtxIdx[5] = readVal(m_va.texMtxIdx[5]); + retval.texMtxIdx[6] = readVal(m_va.texMtxIdx[6]); + if (m_bankIn) { + atUint16 posIdx = readVal(m_va.pos); + atUint8 mtxIdx = retval.pnMtxIdx / 3; + atInt16 skinIdx = -1; + if (mtxIdx < 10) + skinIdx = m_bankIn[mtxIdx]; + retval.pos = m_evt.lookupVertIdx(posIdx, skinIdx); + } else + retval.pos = readVal(m_va.pos); + retval.norm = readVal(m_va.norm); + retval.color[0] = readVal(m_va.color0); + retval.color[1] = readVal(m_va.color1); + retval.uvs[0] = readVal(m_va.uvs[0]); + retval.uvs[1] = readVal(m_va.uvs[1]); + retval.uvs[2] = readVal(m_va.uvs[2]); + retval.uvs[3] = readVal(m_va.uvs[3]); + retval.uvs[4] = readVal(m_va.uvs[4]); + retval.uvs[5] = readVal(m_va.uvs[5]); + retval.uvs[6] = readVal(m_va.uvs[6]); + if (peek) + m_cur = bakCur; + return retval; + } + + void preReadMaxIdxs(DLPrimVert& out) { + atUint8* bakCur = m_cur; + while (*this) { + readPrimitive(); + atUint16 vc = readVertCount(); + for (atUint16 v = 0; v < vc; ++v) { + atUint16 val; + val = readVal(m_va.pnMtxIdx); + out.pnMtxIdx = std::max(out.pnMtxIdx, atUint8(val)); + val = readVal(m_va.texMtxIdx[0]); + out.texMtxIdx[0] = std::max(out.texMtxIdx[0], atUint8(val)); + val = readVal(m_va.texMtxIdx[1]); + out.texMtxIdx[1] = std::max(out.texMtxIdx[1], atUint8(val)); + val = readVal(m_va.texMtxIdx[2]); + out.texMtxIdx[2] = std::max(out.texMtxIdx[2], atUint8(val)); + val = readVal(m_va.texMtxIdx[3]); + out.texMtxIdx[3] = std::max(out.texMtxIdx[3], atUint8(val)); + val = readVal(m_va.texMtxIdx[4]); + out.texMtxIdx[4] = std::max(out.texMtxIdx[4], atUint8(val)); + val = readVal(m_va.texMtxIdx[5]); + out.texMtxIdx[5] = std::max(out.texMtxIdx[5], atUint8(val)); + val = readVal(m_va.texMtxIdx[6]); + out.texMtxIdx[6] = std::max(out.texMtxIdx[6], atUint8(val)); + val = readVal(m_va.pos); + out.pos = std::max(out.pos, val); + val = readVal(m_va.norm); + out.norm = std::max(out.norm, val); + val = readVal(m_va.color0); + out.color[0] = std::max(out.color[0], val); + val = readVal(m_va.color1); + out.color[1] = std::max(out.color[1], val); + val = readVal(m_va.uvs[0]); + out.uvs[0] = std::max(out.uvs[0], val); + val = readVal(m_va.uvs[1]); + out.uvs[1] = std::max(out.uvs[1], val); + val = readVal(m_va.uvs[2]); + out.uvs[2] = std::max(out.uvs[2], val); + val = readVal(m_va.uvs[3]); + out.uvs[3] = std::max(out.uvs[3], val); + val = readVal(m_va.uvs[4]); + out.uvs[4] = std::max(out.uvs[4], val); + val = readVal(m_va.uvs[5]); + out.uvs[5] = std::max(out.uvs[5], val); + val = readVal(m_va.uvs[6]); + out.uvs[6] = std::max(out.uvs[6], val); + } } + m_cur = bakCur; + } - operator bool() - { - return ((m_cur - m_dl.get()) < intptr_t(m_dlSize)) && *m_cur; - } - - GX::Primitive readPrimitive() - { - return GX::Primitive(*m_cur++ & 0xf8); - } - - GX::Primitive readPrimitiveAndVat(unsigned& vatOut) - { - atUint8 val = *m_cur++; - vatOut = val & 0x7; - return GX::Primitive(val & 0xf8); - } - - atUint16 readVertCount() - { - atUint16 retval = hecl::SBig(*(atUint16*)m_cur); - m_cur += 2; - return retval; - } - - struct DLPrimVert - { - atUint16 pos = 0; - atUint16 norm = 0; - atUint16 color[2] = {0}; - atUint16 uvs[7] = {0}; - atUint8 pnMtxIdx = 0; - atUint8 texMtxIdx[7] = {0}; - }; - - DLPrimVert readVert(bool peek=false) - { - atUint8* bakCur = m_cur; - DLPrimVert retval; - retval.pnMtxIdx = readVal(m_va.pnMtxIdx); - retval.texMtxIdx[0] = readVal(m_va.texMtxIdx[0]); - retval.texMtxIdx[1] = readVal(m_va.texMtxIdx[1]); - retval.texMtxIdx[2] = readVal(m_va.texMtxIdx[2]); - retval.texMtxIdx[3] = readVal(m_va.texMtxIdx[3]); - retval.texMtxIdx[4] = readVal(m_va.texMtxIdx[4]); - retval.texMtxIdx[5] = readVal(m_va.texMtxIdx[5]); - retval.texMtxIdx[6] = readVal(m_va.texMtxIdx[6]); - if (m_bankIn) - { - atUint16 posIdx = readVal(m_va.pos); - atUint8 mtxIdx = retval.pnMtxIdx / 3; - atInt16 skinIdx = -1; - if (mtxIdx < 10) - skinIdx = m_bankIn[mtxIdx]; - retval.pos = m_evt.lookupVertIdx(posIdx, skinIdx); - } - else - retval.pos = readVal(m_va.pos); - retval.norm = readVal(m_va.norm); - retval.color[0] = readVal(m_va.color0); - retval.color[1] = readVal(m_va.color1); - retval.uvs[0] = readVal(m_va.uvs[0]); - retval.uvs[1] = readVal(m_va.uvs[1]); - retval.uvs[2] = readVal(m_va.uvs[2]); - retval.uvs[3] = readVal(m_va.uvs[3]); - retval.uvs[4] = readVal(m_va.uvs[4]); - retval.uvs[5] = readVal(m_va.uvs[5]); - retval.uvs[6] = readVal(m_va.uvs[6]); - if (peek) - m_cur = bakCur; - return retval; - } - - void preReadMaxIdxs(DLPrimVert& out) - { - atUint8* bakCur = m_cur; - while (*this) - { - readPrimitive(); - atUint16 vc = readVertCount(); - for (atUint16 v=0 ; v& skinOut) - { - atUint8* bakCur = m_cur; - while (*this) - { - readPrimitive(); - atUint16 vc = readVertCount(); - for (atUint16 v=0 ; v& skinOut) { + atUint8* bakCur = m_cur; + while (*this) { + readPrimitive(); + atUint16 vc = readVertCount(); + for (atUint16 v = 0; v < vc; ++v) { + atUint16 val; + atUint8 pnMtxVal = readVal(m_va.pnMtxIdx); + out.pnMtxIdx = std::max(out.pnMtxIdx, pnMtxVal); + val = readVal(m_va.texMtxIdx[0]); + out.texMtxIdx[0] = std::max(out.texMtxIdx[0], atUint8(val)); + val = readVal(m_va.texMtxIdx[1]); + out.texMtxIdx[1] = std::max(out.texMtxIdx[1], atUint8(val)); + val = readVal(m_va.texMtxIdx[2]); + out.texMtxIdx[2] = std::max(out.texMtxIdx[2], atUint8(val)); + val = readVal(m_va.texMtxIdx[3]); + out.texMtxIdx[3] = std::max(out.texMtxIdx[3], atUint8(val)); + val = readVal(m_va.texMtxIdx[4]); + out.texMtxIdx[4] = std::max(out.texMtxIdx[4], atUint8(val)); + val = readVal(m_va.texMtxIdx[5]); + out.texMtxIdx[5] = std::max(out.texMtxIdx[5], atUint8(val)); + val = readVal(m_va.texMtxIdx[6]); + out.texMtxIdx[6] = std::max(out.texMtxIdx[6], atUint8(val)); + atUint16 posVal = readVal(m_va.pos); + out.pos = std::max(out.pos, posVal); + val = readVal(m_va.norm); + out.norm = std::max(out.norm, val); + val = readVal(m_va.color0); + out.color[0] = std::max(out.color[0], val); + val = readVal(m_va.color1); + out.color[1] = std::max(out.color[1], val); + val = readVal(m_va.uvs[0]); + out.uvs[0] = std::max(out.uvs[0], val); + val = readVal(m_va.uvs[1]); + out.uvs[1] = std::max(out.uvs[1], val); + val = readVal(m_va.uvs[2]); + out.uvs[2] = std::max(out.uvs[2], val); + val = readVal(m_va.uvs[3]); + out.uvs[3] = std::max(out.uvs[3], val); + val = readVal(m_va.uvs[4]); + out.uvs[4] = std::max(out.uvs[4], val); + val = readVal(m_va.uvs[5]); + out.uvs[5] = std::max(out.uvs[5], val); + val = readVal(m_va.uvs[6]); + out.uvs[6] = std::max(out.uvs[6], val); + + atInt16 skinIdx = m_bankIn[pnMtxVal / 3]; + skinOut[posVal] = m_evt.addPosSkinPair(posVal, skinIdx); + } } + m_cur = bakCur; + } }; -void InitGeomBlenderContext(hecl::blender::PyOutStream& os, - const hecl::ProjectPath& masterShaderPath, - bool solidShading) -{ - os << "import math\n" - "from mathutils import Vector\n" - "\n" - "# Using 'Blender Game'\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" - "\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "\n" - "def loop_from_facevert(bm, face, vert_idx):\n" - " for loop in face.loops:\n" - " if loop.vert[bm.verts.layers.int['CMDLOriginalPosIdxs']] == vert_idx:\n" - " return loop\n" - "\n" - "def loops_from_edgevert(bm, edge, vert):\n" - " ret = []\n" - " for face in edge.link_faces:\n" - " for loop in face.loops:\n" - " if loop.vert == vert:\n" - " ret.append(loop)\n" - " return ret\n" - "\n" - "def add_triangle(bm, vert_seq, vert_indices, norm_seq, norm_indices, mat_nr, od_list, two_face_vert):\n" - " if len(set(vert_indices)) != 3:\n" - " return None, None\n" - "\n" - " ret_mesh = bm\n" - " vert_seq.ensure_lookup_table()\n" - " verts = [vert_seq[i] for i in vert_indices]\n" - "\n" - " # Try getting existing face\n" - " face = bm.faces.get(verts)\n" - "\n" - " if face is not None and face.material_index != mat_nr: # Same poly, new material\n" - " # Overdraw detected; track copy\n" - " od_entry = None\n" - " for entry in od_list:\n" - " if entry['material'] == mat_nr:\n" - " od_entry = entry\n" - " if od_entry is None:\n" - " bm_cpy = bm.copy()\n" - " od_entry = {'material':mat_nr, 'bm':bm_cpy}\n" - " bmesh.ops.delete(od_entry['bm'], geom=od_entry['bm'].faces, context=3)\n" - " od_list.append(od_entry)\n" - " od_entry['bm'].verts.ensure_lookup_table()\n" - " verts = [od_entry['bm'].verts[i] for i in vert_indices]\n" - " face = od_entry['bm'].faces.get(verts)\n" - " if face is None:\n" - " face = od_entry['bm'].faces.new(verts)\n" - " else: # Probably a double-sided surface\n" - " verts = [od_entry['bm'].verts[i + two_face_vert] for i in vert_indices]\n" - " face = od_entry['bm'].faces.get(verts)\n" - " if face is None:\n" - " face = od_entry['bm'].faces.new(verts)\n" - " ret_mesh = od_entry['bm']\n" - "\n" - " elif face is not None: # Same material, probably double-sided\n" - " verts = [vert_seq[i + two_face_vert] for i in vert_indices]\n" - " face = bm.faces.get(verts)\n" - " if face is None:\n" - " face = bm.faces.new(verts)\n" - "\n" - " else: # Make totally new face\n" - " face = bm.faces.new(verts)\n" - "\n" - " for i in range(3):\n" - " face.verts[i][ret_mesh.verts.layers.int['CMDLOriginalPosIdxs']] = vert_indices[i]\n" - " face.loops[i][ret_mesh.loops.layers.int['CMDLOriginalNormIdxs']] = norm_indices[i]\n" - " face.material_index = mat_nr\n" - " face.smooth = True\n" - "\n" - " return face, ret_mesh\n" - "\n" - "def expand_lightmap_triangle(lightmap_tri_tracker, uva, uvb, uvc):\n" - " result = ([uva[0],uva[1]], [uvb[0],uvb[1]], [uvc[0],uvc[1]])\n" - " inst = 0\n" - " if uva in lightmap_tri_tracker:\n" - " inst = lightmap_tri_tracker[uva]\n" - " lightmap_tri_tracker[uva] = inst + 1\n" - " if uva == uvb:\n" - " result[1][0] += 0.005\n" - " if uva == uvc:\n" - " result[2][1] -= 0.005\n" - " if inst & 0x1 and uva == uvb and uva == uvc:\n" - " result[0][0] += 0.005\n" - " result[0][1] -= 0.005\n" - " return result\n" - "\n"; +void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectPath& masterShaderPath, + bool solidShading) { + os << "import math\n" + "from mathutils import Vector\n" + "\n" + "# Using 'Blender Game'\n" + "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" + "\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " if ob.type != 'LAMP' and ob.type != 'CAMERA':\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n" + "\n" + "def loop_from_facevert(bm, face, vert_idx):\n" + " for loop in face.loops:\n" + " if loop.vert[bm.verts.layers.int['CMDLOriginalPosIdxs']] == vert_idx:\n" + " return loop\n" + "\n" + "def loops_from_edgevert(bm, edge, vert):\n" + " ret = []\n" + " for face in edge.link_faces:\n" + " for loop in face.loops:\n" + " if loop.vert == vert:\n" + " ret.append(loop)\n" + " return ret\n" + "\n" + "def add_triangle(bm, vert_seq, vert_indices, norm_seq, norm_indices, mat_nr, od_list, two_face_vert):\n" + " if len(set(vert_indices)) != 3:\n" + " return None, None\n" + "\n" + " ret_mesh = bm\n" + " vert_seq.ensure_lookup_table()\n" + " verts = [vert_seq[i] for i in vert_indices]\n" + "\n" + " # Try getting existing face\n" + " face = bm.faces.get(verts)\n" + "\n" + " if face is not None and face.material_index != mat_nr: # Same poly, new material\n" + " # Overdraw detected; track copy\n" + " od_entry = None\n" + " for entry in od_list:\n" + " if entry['material'] == mat_nr:\n" + " od_entry = entry\n" + " if od_entry is None:\n" + " bm_cpy = bm.copy()\n" + " od_entry = {'material':mat_nr, 'bm':bm_cpy}\n" + " bmesh.ops.delete(od_entry['bm'], geom=od_entry['bm'].faces, context=3)\n" + " od_list.append(od_entry)\n" + " od_entry['bm'].verts.ensure_lookup_table()\n" + " verts = [od_entry['bm'].verts[i] for i in vert_indices]\n" + " face = od_entry['bm'].faces.get(verts)\n" + " if face is None:\n" + " face = od_entry['bm'].faces.new(verts)\n" + " else: # Probably a double-sided surface\n" + " verts = [od_entry['bm'].verts[i + two_face_vert] for i in vert_indices]\n" + " face = od_entry['bm'].faces.get(verts)\n" + " if face is None:\n" + " face = od_entry['bm'].faces.new(verts)\n" + " ret_mesh = od_entry['bm']\n" + "\n" + " elif face is not None: # Same material, probably double-sided\n" + " verts = [vert_seq[i + two_face_vert] for i in vert_indices]\n" + " face = bm.faces.get(verts)\n" + " if face is None:\n" + " face = bm.faces.new(verts)\n" + "\n" + " else: # Make totally new face\n" + " face = bm.faces.new(verts)\n" + "\n" + " for i in range(3):\n" + " face.verts[i][ret_mesh.verts.layers.int['CMDLOriginalPosIdxs']] = vert_indices[i]\n" + " face.loops[i][ret_mesh.loops.layers.int['CMDLOriginalNormIdxs']] = norm_indices[i]\n" + " face.material_index = mat_nr\n" + " face.smooth = True\n" + "\n" + " return face, ret_mesh\n" + "\n" + "def expand_lightmap_triangle(lightmap_tri_tracker, uva, uvb, uvc):\n" + " result = ([uva[0],uva[1]], [uvb[0],uvb[1]], [uvc[0],uvc[1]])\n" + " inst = 0\n" + " if uva in lightmap_tri_tracker:\n" + " inst = lightmap_tri_tracker[uva]\n" + " lightmap_tri_tracker[uva] = inst + 1\n" + " if uva == uvb:\n" + " result[1][0] += 0.005\n" + " if uva == uvc:\n" + " result[2][1] -= 0.005\n" + " if inst & 0x1 and uva == uvb and uva == uvc:\n" + " result[0][0] += 0.005\n" + " result[0][1] -= 0.005\n" + " return result\n" + "\n"; - if (solidShading) - { - os << "for ar in bpy.context.screen.areas:\n" - " for sp in ar.spaces:\n" - " if sp.type == 'VIEW_3D':\n" - " sp.viewport_shade = 'SOLID'\n"; - } + if (solidShading) { + os << "for ar in bpy.context.screen.areas:\n" + " for sp in ar.spaces:\n" + " if sp.type == 'VIEW_3D':\n" + " sp.viewport_shade = 'SOLID'\n"; + } - /* Link master shader library */ - os.format("# Master shader library\n" - "with bpy.data.libraries.load('%s', link=True, relative=True) as (data_from, data_to):\n" - " data_to.node_groups = data_from.node_groups\n" - "\n", masterShaderPath.getAbsolutePathUTF8().data()); + /* Link master shader library */ + os.format( + "# Master shader library\n" + "with bpy.data.libraries.load('%s', link=True, relative=True) as (data_from, data_to):\n" + " data_to.node_groups = data_from.node_groups\n" + "\n", + masterShaderPath.getAbsolutePathUTF8().data()); } -void FinishBlenderMesh(hecl::blender::PyOutStream& os, - unsigned matSetCount, int meshIdx) -{ - if (meshIdx < 0) - os.format("mesh = bpy.data.meshes.new(bpy.context.scene.name)\n" - "obj = bpy.data.objects.new(mesh.name, mesh)\n" - "obj.show_transparent = True\n" - "bpy.context.scene.objects.link(obj)\n" - "mesh.hecl_material_count = %u\n", matSetCount); - else - os.format("mesh = bpy.data.meshes.new(bpy.context.scene.name + '_%03d')\n" - "obj = bpy.data.objects.new(mesh.name, mesh)\n" - "obj.show_transparent = True\n" - "bpy.context.scene.objects.link(obj)\n" - "mesh.hecl_material_count = %u\n", meshIdx, matSetCount); +void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int meshIdx) { + if (meshIdx < 0) + os.format( + "mesh = bpy.data.meshes.new(bpy.context.scene.name)\n" + "obj = bpy.data.objects.new(mesh.name, mesh)\n" + "obj.show_transparent = True\n" + "bpy.context.scene.objects.link(obj)\n" + "mesh.hecl_material_count = %u\n", + matSetCount); + else + os.format( + "mesh = bpy.data.meshes.new(bpy.context.scene.name + '_%03d')\n" + "obj = bpy.data.objects.new(mesh.name, mesh)\n" + "obj.show_transparent = True\n" + "bpy.context.scene.objects.link(obj)\n" + "mesh.hecl_material_count = %u\n", + meshIdx, matSetCount); - os << "mesh.use_auto_smooth = True\n" - "mesh.auto_smooth_angle = math.pi\n" - "mesh.show_edge_sharp = True\n" - "\n" - "for material in materials:\n" - " mesh.materials.append(material)\n" - "\n" - "# Merge OD meshes\n" - "for od_entry in od_list:\n" - " vert_dict = [{},{}]\n" - "\n" - " for vert in od_entry['bm'].verts:\n" - " if len(vert.link_faces):\n" - " if vert.index >= two_face_vert:\n" - " use_vert_dict = vert_dict[1]\n" - " else:\n" - " use_vert_dict = vert_dict[0]\n" - " copy_vert = bm.verts.new(vert.co, vert)\n" - " use_vert_dict[vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] = copy_vert\n" - " copy_vert[orig_pidx_lay] = vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]\n" - "\n" - " for face in od_entry['bm'].faces:\n" - " if face.verts[0].index >= two_face_vert:\n" - " use_vert_dict = vert_dict[1]\n" - " else:\n" - " use_vert_dict = vert_dict[0]\n" - " merge_verts = [use_vert_dict[fv[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] for fv in face.verts]\n" - " if bm.faces.get(merge_verts) is not None:\n" - " continue\n" - " merge_face = bm.faces.new(merge_verts)\n" - " for i in range(len(face.loops)):\n" - " old = face.loops[i]\n" - " new = merge_face.loops[i]\n" - " for j in range(len(od_entry['bm'].loops.layers.uv)):\n" - " new[bm.loops.layers.uv[j]] = old[od_entry['bm'].loops.layers.uv[j]]\n" - " new[orig_nidx_lay] = old[od_entry['bm'].loops.layers.int['CMDLOriginalNormIdxs']]\n" - " merge_face.smooth = True\n" - " merge_face.material_index = face.material_index\n" - "\n" - " od_entry['bm'].free()\n" - "\n" - "verts_to_del = []\n" - "for v in bm.verts:\n" - " if len(v.link_faces) == 0:\n" - " verts_to_del.append(v)\n" - "bmesh.ops.delete(bm, geom=verts_to_del, context=1)\n" - "\n" - "for edge in bm.edges:\n" - " if edge.is_manifold:\n" - " pass_count = 0\n" - " for vert in edge.verts:\n" - " loops = loops_from_edgevert(bm, edge, vert)\n" - " norm0 = Vector(norm_list[loops[0][orig_nidx_lay]])\n" - " norm1 = Vector(norm_list[loops[1][orig_nidx_lay]])\n" - " if norm0.dot(norm1) < 0.9:\n" - " pass_count += 1\n" - " if pass_count > 0:\n" - " edge.smooth = False\n" - "\n" - "bm.to_mesh(mesh)\n" - "bm.free()\n" - "\n" - "# Remove redundant materials\n" - "present_mats = set()\n" - "for poly in mesh.polygons:\n" - " present_mats.add(poly.material_index)\n" - "for mat_idx in reversed(range(len(mesh.materials))):\n" - " if mat_idx not in present_mats:\n" - " mesh.materials.pop(index=mat_idx, update_data=True)\n" - "\n" - "mesh.update()\n" - "\n"; + os << "mesh.use_auto_smooth = True\n" + "mesh.auto_smooth_angle = math.pi\n" + "mesh.show_edge_sharp = True\n" + "\n" + "for material in materials:\n" + " mesh.materials.append(material)\n" + "\n" + "# Merge OD meshes\n" + "for od_entry in od_list:\n" + " vert_dict = [{},{}]\n" + "\n" + " for vert in od_entry['bm'].verts:\n" + " if len(vert.link_faces):\n" + " if vert.index >= two_face_vert:\n" + " use_vert_dict = vert_dict[1]\n" + " else:\n" + " use_vert_dict = vert_dict[0]\n" + " copy_vert = bm.verts.new(vert.co, vert)\n" + " use_vert_dict[vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] = copy_vert\n" + " copy_vert[orig_pidx_lay] = vert[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]\n" + "\n" + " for face in od_entry['bm'].faces:\n" + " if face.verts[0].index >= two_face_vert:\n" + " use_vert_dict = vert_dict[1]\n" + " else:\n" + " use_vert_dict = vert_dict[0]\n" + " merge_verts = [use_vert_dict[fv[od_entry['bm'].verts.layers.int['CMDLOriginalPosIdxs']]] for fv in " + "face.verts]\n" + " if bm.faces.get(merge_verts) is not None:\n" + " continue\n" + " merge_face = bm.faces.new(merge_verts)\n" + " for i in range(len(face.loops)):\n" + " old = face.loops[i]\n" + " new = merge_face.loops[i]\n" + " for j in range(len(od_entry['bm'].loops.layers.uv)):\n" + " new[bm.loops.layers.uv[j]] = old[od_entry['bm'].loops.layers.uv[j]]\n" + " new[orig_nidx_lay] = old[od_entry['bm'].loops.layers.int['CMDLOriginalNormIdxs']]\n" + " merge_face.smooth = True\n" + " merge_face.material_index = face.material_index\n" + "\n" + " od_entry['bm'].free()\n" + "\n" + "verts_to_del = []\n" + "for v in bm.verts:\n" + " if len(v.link_faces) == 0:\n" + " verts_to_del.append(v)\n" + "bmesh.ops.delete(bm, geom=verts_to_del, context=1)\n" + "\n" + "for edge in bm.edges:\n" + " if edge.is_manifold:\n" + " pass_count = 0\n" + " for vert in edge.verts:\n" + " loops = loops_from_edgevert(bm, edge, vert)\n" + " norm0 = Vector(norm_list[loops[0][orig_nidx_lay]])\n" + " norm1 = Vector(norm_list[loops[1][orig_nidx_lay]])\n" + " if norm0.dot(norm1) < 0.9:\n" + " pass_count += 1\n" + " if pass_count > 0:\n" + " edge.smooth = False\n" + "\n" + "bm.to_mesh(mesh)\n" + "bm.free()\n" + "\n" + "# Remove redundant materials\n" + "present_mats = set()\n" + "for poly in mesh.polygons:\n" + " present_mats.add(poly.material_index)\n" + "for mat_idx in reversed(range(len(mesh.materials))):\n" + " if mat_idx not in present_mats:\n" + " mesh.materials.pop(index=mat_idx, update_data=True)\n" + "\n" + "mesh.update()\n" + "\n"; } template -atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, - athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - const RigPair& rp, - bool shortNormals, - bool shortUVs, - std::vector& vertAttribs, - int meshIdx, - atUint32 secCount, - atUint32 matSetCount, - const atUint32* secSizes, - atUint32 surfaceCount) -{ - os << "# Begin bmesh\n" - "bm = bmesh.new()\n" - "\n" - "# Overdraw-tracking\n" - "od_list = []\n" - "\n" - "orig_pidx_lay = bm.verts.layers.int.new('CMDLOriginalPosIdxs')\n" - "orig_nidx_lay = bm.loops.layers.int.new('CMDLOriginalNormIdxs')\n" - "\n" - "lightmap_tri_tracker = {}\n"; +atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::IStreamReader& reader, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const RigPair& rp, + bool shortNormals, bool shortUVs, std::vector& vertAttribs, + int meshIdx, atUint32 secCount, atUint32 matSetCount, const atUint32* secSizes, + atUint32 surfaceCount) { + os << "# Begin bmesh\n" + "bm = bmesh.new()\n" + "\n" + "# Overdraw-tracking\n" + "od_list = []\n" + "\n" + "orig_pidx_lay = bm.verts.layers.int.new('CMDLOriginalPosIdxs')\n" + "orig_nidx_lay = bm.loops.layers.int.new('CMDLOriginalNormIdxs')\n" + "\n" + "lightmap_tri_tracker = {}\n"; - if (rp.first) - os << "dvert_lay = bm.verts.layers.deform.verify()\n"; + if (rp.first) + os << "dvert_lay = bm.verts.layers.deform.verify()\n"; - /* Pre-read pass to determine maximum used vert indices */ - atUint32 matSecCount = 0; - if (matSetCount) - matSecCount = MaterialSet::OneSection() ? 1 : matSetCount; - bool visitedDLOffsets = false; - atUint32 lastDlSec = secCount; - atUint64 afterHeaderPos = reader.position(); - DLReader::DLPrimVert maxIdxs; - std::vector skinIndices; - DLReader::ExtraVertTracker extraTracker; - for (size_t s=0 ; s skinIndices; + DLReader::ExtraVertTracker extraTracker; + for (size_t s = 0; s < lastDlSec; ++s) { + atUint64 secStart = reader.position(); + if (s < matSecCount) { + if (!s) { + MaterialSet matSet; + matSet.read(reader); + matSet.ensureTexturesExtracted(pakRouter); + GetVertexAttributes(matSet, vertAttribs); + } + } else { + switch (s - matSecCount) { + case 0: { + /* Positions */ + if (SurfaceHeader::UseMatrixSkinning() && rp.first) + skinIndices.assign(secSizes[s] / 12, -1); + break; + } + case 1: { + /* Normals */ + break; + } + case 2: { + /* Colors */ + break; + } + case 3: { + /* Float UVs */ + break; + } + case 4: { + if (surfaceCount) { + /* MP3 MREA case */ + visitedDLOffsets = true; + lastDlSec = 4 + surfaceCount; + } else { + /* Short UVs */ + if (shortUVs) + break; + + /* DL Offsets (here or next section) */ + visitedDLOffsets = true; + lastDlSec = s + reader.readUint32Big() + 1; + break; } + } + default: { + if (!visitedDLOffsets) { + visitedDLOffsets = true; + lastDlSec = s + reader.readUint32Big() + 1; + break; + } + + /* GX Display List (surface) */ + SurfaceHeader sHead; + sHead.read(reader); + const atInt16* bankIn = nullptr; + if (SurfaceHeader::UseMatrixSkinning() && rp.first) + bankIn = rp.first->getMatrixBank(sHead.skinMatrixBankIdx()); + + /* Do max index pre-read */ + atUint32 realDlSize = secSizes[s] - (reader.position() - secStart); + DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize, extraTracker, bankIn); + if (SurfaceHeader::UseMatrixSkinning() && rp.first) + dl.preReadMaxIdxs(maxIdxs, skinIndices); else - { - switch (s-matSecCount) - { - case 0: - { - /* Positions */ - if (SurfaceHeader::UseMatrixSkinning() && rp.first) - skinIndices.assign(secSizes[s] / 12, -1); - break; - } - case 1: - { - /* Normals */ - break; - } - case 2: - { - /* Colors */ - break; - } - case 3: - { - /* Float UVs */ - break; - } - case 4: - { - if (surfaceCount) - { - /* MP3 MREA case */ - visitedDLOffsets = true; - lastDlSec = 4 + surfaceCount; - } - else - { - /* Short UVs */ - if (shortUVs) - break; - - /* DL Offsets (here or next section) */ - visitedDLOffsets = true; - lastDlSec = s + reader.readUint32Big() + 1; - break; - } - } - default: - { - if (!visitedDLOffsets) - { - visitedDLOffsets = true; - lastDlSec = s + reader.readUint32Big() + 1; - break; - } - - /* GX Display List (surface) */ - SurfaceHeader sHead; - sHead.read(reader); - const atInt16* bankIn = nullptr; - if (SurfaceHeader::UseMatrixSkinning() && rp.first) - bankIn = rp.first->getMatrixBank(sHead.skinMatrixBankIdx()); - - /* Do max index pre-read */ - atUint32 realDlSize = secSizes[s] - (reader.position() - secStart); - DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), - realDlSize, extraTracker, bankIn); - if (SurfaceHeader::UseMatrixSkinning() && rp.first) - dl.preReadMaxIdxs(maxIdxs, skinIndices); - else - dl.preReadMaxIdxs(maxIdxs); - - } - } - } - - if (s < secCount - 1) - reader.seek(secStart + secSizes[s], athena::Begin); + dl.preReadMaxIdxs(maxIdxs); + } + } } - reader.seek(afterHeaderPos, athena::Begin); + if (s < secCount - 1) + reader.seek(secStart + secSizes[s], athena::Begin); + } - visitedDLOffsets = false; - unsigned createdUVLayers = 0; - unsigned surfIdx = 0; + reader.seek(afterHeaderPos, athena::Begin); - for (size_t s=0 ; s positions; + positions.reserve(vertCount); + for (size_t i = 0; i <= maxIdxs.pos; ++i) { + positions.push_back(reader.readVec3fBig()); + const atVec3f& pos = positions.back(); + os.format("vert = bm.verts.new((%f,%f,%f))\n", pos.simd[0], pos.simd[1], pos.simd[2]); + if (rp.first) { + if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) + rp.first->weightVertex(os, *rp.second, skinIndices[i]); + else if (!SurfaceHeader::UseMatrixSkinning()) + rp.first->weightVertex(os, *rp.second, i); + } } - else - { - switch (s-matSecCount) - { - case 0: - { - /* Positions */ - atUint32 vertCount = maxIdxs.pos + 1; - std::vector positions; - positions.reserve(vertCount); - for (size_t i=0 ; i<=maxIdxs.pos ; ++i) - { - positions.push_back(reader.readVec3fBig()); - const atVec3f& pos = positions.back(); - os.format("vert = bm.verts.new((%f,%f,%f))\n", - pos.simd[0], pos.simd[1], pos.simd[2]); - if (rp.first) - { - if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) - rp.first->weightVertex(os, *rp.second, skinIndices[i]); - else if (!SurfaceHeader::UseMatrixSkinning()) - rp.first->weightVertex(os, *rp.second, i); - } - } - if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) - vertCount += extraTracker.sendAdditionalVertsToBlender(os, rp, 0); - os.format("two_face_vert = %u\n", vertCount); - for (size_t i=0 ; i<=maxIdxs.pos ; ++i) - { - const atVec3f& pos = positions[i]; - os.format("vert = bm.verts.new((%f,%f,%f))\n", - pos.simd[0], pos.simd[1], pos.simd[2]); - if (rp.first) - { - if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) - rp.first->weightVertex(os, *rp.second, skinIndices[i]); - else if (!SurfaceHeader::UseMatrixSkinning()) - rp.first->weightVertex(os, *rp.second, i); - } - } - if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) - extraTracker.sendAdditionalVertsToBlender(os, rp, vertCount); - break; + if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) + vertCount += extraTracker.sendAdditionalVertsToBlender(os, rp, 0); + os.format("two_face_vert = %u\n", vertCount); + for (size_t i = 0; i <= maxIdxs.pos; ++i) { + const atVec3f& pos = positions[i]; + os.format("vert = bm.verts.new((%f,%f,%f))\n", pos.simd[0], pos.simd[1], pos.simd[2]); + if (rp.first) { + if (SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) + rp.first->weightVertex(os, *rp.second, skinIndices[i]); + else if (!SurfaceHeader::UseMatrixSkinning()) + rp.first->weightVertex(os, *rp.second, i); + } + } + if (rp.first && SurfaceHeader::UseMatrixSkinning() && !skinIndices.empty()) + extraTracker.sendAdditionalVertsToBlender(os, rp, vertCount); + break; + } + case 1: { + /* Normals */ + os << "norm_list = []\n"; + if (shortNormals) { + size_t normCount = secSizes[s] / 6; + for (size_t i = 0; i < normCount; ++i) { + float x = reader.readInt16Big() / 16384.0f; + float y = reader.readInt16Big() / 16384.0f; + float z = reader.readInt16Big() / 16384.0f; + os.format("norm_list.append((%f,%f,%f))\n", x, y, z); + } + } else { + size_t normCount = secSizes[s] / 12; + for (size_t i = 0; i < normCount; ++i) { + const atVec3f norm = reader.readVec3fBig(); + os.format("norm_list.append((%f,%f,%f))\n", norm.simd[0], norm.simd[1], norm.simd[2]); + } + } + break; + } + case 2: { + /* Colors */ + break; + } + case 3: { + /* Float UVs */ + os << "uv_list = []\n"; + size_t uvCount = secSizes[s] / 8; + for (size_t i = 0; i < uvCount; ++i) { + const atVec2f uv = reader.readVec2fBig(); + os.format("uv_list.append((%f,%f))\n", uv.simd[0], uv.simd[1]); + } + break; + } + case 4: { + if (surfaceCount) { + /* MP3 MREA case */ + visitedDLOffsets = true; + } else { + /* Short UVs */ + os << "suv_list = []\n"; + if (shortUVs) { + size_t uvCount = secSizes[s] / 4; + for (size_t i = 0; i < uvCount; ++i) { + float x = reader.readInt16Big() / 32768.0f; + float y = reader.readInt16Big() / 32768.0f; + os.format("suv_list.append((%f,%f))\n", x, y); } - case 1: - { - /* Normals */ - os << "norm_list = []\n"; - if (shortNormals) - { - size_t normCount = secSizes[s] / 6; - for (size_t i=0 ; igetMatrixBank(sHead.skinMatrixBankIdx()); - - os.format("materials[%u].pass_index = %u\n", sHead.matIdx, surfIdx++); - if (matUVCount > createdUVLayers) - { - for (unsigned l=createdUVLayers ; l= vertCount - 3); - - /* Advance one prim vert */ - primVerts[c%3] = dl.readVert(peek); - ++c; - } - } - else if (ptype == GX::TRIANGLES) - { - for (int v=0 ; v= vertCount) - break; - - /* Advance 3 Prim Verts */ - for (int pv=0 ; pv<3 ; ++pv) - primVerts[pv] = dl.readVert(); - } - } - else if (ptype == GX::TRIANGLEFAN) - { - ++c; - for (int v=0 ; v= vertCount) - break; - - /* Advance one prim vert */ - primVerts[(c+2)%3] = dl.readVert(); - ++c; - } - } - os << "\n"; - } - } - } + /* DL Offsets (here or next section) */ + visitedDLOffsets = true; + break; + } + } + default: { + if (!visitedDLOffsets) { + visitedDLOffsets = true; + break; } - if (s < secCount - 1) - reader.seek(secStart + secSizes[s], athena::Begin); + /* GX Display List (surface) */ + SurfaceHeader sHead; + sHead.read(reader); + VertexAttributes& curVA = vertAttribs[sHead.matIdx]; + unsigned matUVCount = curVA.uvCount; + bool matShortUVs = curVA.shortUVs; + const atInt16* bankIn = nullptr; + if (SurfaceHeader::UseMatrixSkinning() && rp.first) + bankIn = rp.first->getMatrixBank(sHead.skinMatrixBankIdx()); + + os.format("materials[%u].pass_index = %u\n", sHead.matIdx, surfIdx++); + if (matUVCount > createdUVLayers) { + for (unsigned l = createdUVLayers; l < matUVCount; ++l) + os.format("bm.loops.layers.uv.new('UV_%u')\n", l); + createdUVLayers = matUVCount; + } + + atUint32 realDlSize = secSizes[s] - (reader.position() - secStart); + DLReader dl(vertAttribs[sHead.matIdx], reader.readUBytes(realDlSize), realDlSize, extraTracker, bankIn); + + while (dl) { + GX::Primitive ptype = dl.readPrimitive(); + atUint16 vertCount = dl.readVertCount(); + + /* First vert */ + DLReader::DLPrimVert firstPrimVert = dl.readVert(true); + + /* 3 Prim Verts to start */ + int c = 0; + DLReader::DLPrimVert primVerts[3] = {dl.readVert(), dl.readVert(), dl.readVert()}; + + if (ptype == GX::TRIANGLESTRIP) { + atUint8 flip = 0; + for (int v = 0; v < vertCount - 2; ++v) { + if (flip) { + os.format( + "last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list, " + "two_face_vert)\n", + primVerts[c % 3].pos, primVerts[(c + 2) % 3].pos, primVerts[(c + 1) % 3].pos, primVerts[c % 3].norm, + primVerts[(c + 2) % 3].norm, primVerts[(c + 1) % 3].norm, sHead.matIdx); + if (matUVCount) { + os << "if last_face is not None:\n"; + for (unsigned j = 0; j < matUVCount; ++j) { + if (j == 0 && matShortUVs) + os.format( + " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[%u], suv_list[%u], " + "suv_list[%u])\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[0]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[1]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[2]\n", + primVerts[c % 3].uvs[j], primVerts[(c + 2) % 3].uvs[j], primVerts[(c + 1) % 3].uvs[j], + primVerts[c % 3].pos, j, primVerts[(c + 2) % 3].pos, j, primVerts[(c + 1) % 3].pos, j); + else + os.format( + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n", + primVerts[c % 3].pos, j, primVerts[c % 3].uvs[j], primVerts[(c + 2) % 3].pos, j, + primVerts[(c + 2) % 3].uvs[j], primVerts[(c + 1) % 3].pos, j, primVerts[(c + 1) % 3].uvs[j]); + } + } + } else { + os.format( + "last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list, " + "two_face_vert)\n", + primVerts[c % 3].pos, primVerts[(c + 1) % 3].pos, primVerts[(c + 2) % 3].pos, primVerts[c % 3].norm, + primVerts[(c + 1) % 3].norm, primVerts[(c + 2) % 3].norm, sHead.matIdx); + if (matUVCount) { + os << "if last_face is not None:\n"; + for (unsigned j = 0; j < matUVCount; ++j) { + if (j == 0 && matShortUVs) + os.format( + " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[%u], suv_list[%u], " + "suv_list[%u])\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[0]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[1]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[2]\n", + primVerts[c % 3].uvs[j], primVerts[(c + 1) % 3].uvs[j], primVerts[(c + 2) % 3].uvs[j], + primVerts[c % 3].pos, j, primVerts[(c + 1) % 3].pos, j, primVerts[(c + 2) % 3].pos, j); + else + os.format( + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n", + primVerts[c % 3].pos, j, primVerts[c % 3].uvs[j], primVerts[(c + 1) % 3].pos, j, + primVerts[(c + 1) % 3].uvs[j], primVerts[(c + 2) % 3].pos, j, primVerts[(c + 2) % 3].uvs[j]); + } + } + } + flip ^= 1; + + bool peek = (v >= vertCount - 3); + + /* Advance one prim vert */ + primVerts[c % 3] = dl.readVert(peek); + ++c; + } + } else if (ptype == GX::TRIANGLES) { + for (int v = 0; v < vertCount; v += 3) { + + os.format( + "last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list, " + "two_face_vert)\n", + primVerts[0].pos, primVerts[1].pos, primVerts[2].pos, primVerts[0].norm, primVerts[1].norm, + primVerts[2].norm, sHead.matIdx); + if (matUVCount) { + os << "if last_face is not None:\n"; + for (unsigned j = 0; j < matUVCount; ++j) { + if (j == 0 && matShortUVs) + os.format( + " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[%u], suv_list[%u], " + "suv_list[%u])\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[0]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[1]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[2]\n", + primVerts[0].uvs[j], primVerts[1].uvs[j], primVerts[2].uvs[j], primVerts[0].pos, j, + primVerts[1].pos, j, primVerts[2].pos, j); + else + os.format( + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n", + primVerts[0].pos, j, primVerts[0].uvs[j], primVerts[1].pos, j, primVerts[1].uvs[j], + primVerts[2].pos, j, primVerts[2].uvs[j]); + } + } + + /* Break if done */ + if (v + 3 >= vertCount) + break; + + /* Advance 3 Prim Verts */ + for (int pv = 0; pv < 3; ++pv) + primVerts[pv] = dl.readVert(); + } + } else if (ptype == GX::TRIANGLEFAN) { + ++c; + for (int v = 0; v < vertCount - 2; ++v) { + os.format( + "last_face, last_mesh = add_triangle(bm, bm.verts, (%u,%u,%u), norm_list, (%u,%u,%u), %u, od_list, " + "two_face_vert)\n", + firstPrimVert.pos, primVerts[c % 3].pos, primVerts[(c + 1) % 3].pos, firstPrimVert.norm, + primVerts[c % 3].norm, primVerts[(c + 1) % 3].norm, sHead.matIdx); + if (matUVCount) { + os << "if last_face is not None:\n"; + for (unsigned j = 0; j < matUVCount; ++j) { + if (j == 0 && matShortUVs) + os.format( + " uv_tri = expand_lightmap_triangle(lightmap_tri_tracker, suv_list[%u], suv_list[%u], " + "suv_list[%u])\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[0]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[1]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_tri[2]\n", + firstPrimVert.uvs[j], primVerts[c % 3].uvs[j], primVerts[(c + 1) % 3].uvs[j], firstPrimVert.pos, + j, primVerts[c % 3].pos, j, primVerts[(c + 1) % 3].pos, j); + else + os.format( + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n" + " loop_from_facevert(last_mesh, last_face, %u)[last_mesh.loops.layers.uv[%u]].uv = " + "uv_list[%u]\n", + firstPrimVert.pos, j, firstPrimVert.uvs[j], primVerts[c % 3].pos, j, primVerts[c % 3].uvs[j], + primVerts[(c + 1) % 3].pos, j, primVerts[(c + 1) % 3].uvs[j]); + } + } + + /* Break if done */ + if (v + 3 >= vertCount) + break; + + /* Advance one prim vert */ + primVerts[(c + 2) % 3] = dl.readVert(); + ++c; + } + } + os << "\n"; + } + } + } } - /* Finish Mesh */ - FinishBlenderMesh(os, matSetCount, meshIdx); + if (s < secCount - 1) + reader.seek(secStart + secSizes[s], athena::Begin); + } - if (rp.first) - rp.second->sendVertexGroupsToBlender(os); + /* Finish Mesh */ + FinishBlenderMesh(os, matSetCount, meshIdx); - return lastDlSec; + if (rp.first) + rp.second->sendVertexGroupsToBlender(os); + + return lastDlSec; } template -bool ReadCMDLToBlender(hecl::blender::Connection& conn, - athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - const SpecBase& dataspec, - const RigPair& rp) -{ - Header head; - head.read(reader); +bool ReadCMDLToBlender(hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, const RigPair& rp) { + Header head; + head.read(reader); - if (head.magic != 0xDEADBABE) - { - LogDNACommon.report(logvisor::Error, "invalid CMDL magic"); - return false; - } + if (head.magic != 0xDEADBABE) { + LogDNACommon.report(logvisor::Error, "invalid CMDL magic"); + return false; + } - if (head.version != Version) - { - LogDNACommon.report(logvisor::Error, "invalid CMDL version"); - return false; - } + if (head.version != Version) { + LogDNACommon.report(logvisor::Error, "invalid CMDL version"); + return false; + } - /* Open Py Stream and read sections */ - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "\n" - "bpy.context.scene.name = '%s'\n" - "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n", - pakRouter.getBestEntryName(entry).c_str()); - InitGeomBlenderContext(os, dataspec.getMasterShaderPath(), false); - MaterialSet::RegisterMaterialProps(os); + /* Open Py Stream and read sections */ + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os.format( + "import bpy\n" + "import bmesh\n" + "\n" + "bpy.context.scene.name = '%s'\n" + "bpy.context.scene.hecl_mesh_obj = bpy.context.scene.name\n", + pakRouter.getBestEntryName(entry).c_str()); + InitGeomBlenderContext(os, dataspec.getMasterShaderPath(), false); + MaterialSet::RegisterMaterialProps(os); - os << "# Materials\n" - "materials = []\n" - "\n"; + os << "# Materials\n" + "materials = []\n" + "\n"; - std::vector vertAttribs; - ReadGeomSectionsToBlender - (os, reader, pakRouter, entry, rp, head.flags.shortNormals(), - head.flags.shortUVs(), vertAttribs, -1, - head.secCount, head.matSetCount, head.secSizes.data()); + std::vector vertAttribs; + ReadGeomSectionsToBlender( + os, reader, pakRouter, entry, rp, head.flags.shortNormals(), head.flags.shortUVs(), vertAttribs, -1, + head.secCount, head.matSetCount, head.secSizes.data()); - return true; + return true; } template bool ReadCMDLToBlender, DNAMP1::MaterialSet, - std::pair, DNACMDL::SurfaceHeader_1, 2> -(hecl::blender::Connection& conn, - athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - const SpecBase& dataspec, - const std::pair& rp); + std::pair, DNACMDL::SurfaceHeader_1, 2>( + hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, const SpecBase& dataspec, + const std::pair& rp); template bool ReadCMDLToBlender, DNAMP2::MaterialSet, - std::pair, DNACMDL::SurfaceHeader_2, 4> -(hecl::blender::Connection& conn, - athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - const SpecBase& dataspec, - const std::pair& rp); + std::pair, DNACMDL::SurfaceHeader_2, 4>( + hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, const SpecBase& dataspec, + const std::pair& rp); template bool ReadCMDLToBlender, DNAMP3::MaterialSet, - std::pair, DNACMDL::SurfaceHeader_3, 4> -(hecl::blender::Connection& conn, - athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - const SpecBase& dataspec, - const std::pair& rp); + std::pair, DNACMDL::SurfaceHeader_3, 4>( + hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, const SpecBase& dataspec, + const std::pair& rp); template bool ReadCMDLToBlender, DNAMP3::MaterialSet, - std::pair, DNACMDL::SurfaceHeader_3, 5> -(hecl::blender::Connection& conn, - athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - const SpecBase& dataspec, - const std::pair& rp); + std::pair, DNACMDL::SurfaceHeader_3, 5>( + hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, const SpecBase& dataspec, + const std::pair& rp); template -void NameCMDL(athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - typename PAKRouter::EntryType& entry, - const SpecBase& dataspec) -{ - Header head; - head.read(reader); - std::string bestName = hecl::Format("CMDL_%s", entry.id.toString().c_str()); +void NameCMDL(athena::io::IStreamReader& reader, PAKRouter& pakRouter, typename PAKRouter::EntryType& entry, + const SpecBase& dataspec) { + Header head; + head.read(reader); + std::string bestName = hecl::Format("CMDL_%s", entry.id.toString().c_str()); - /* Pre-read pass to determine maximum used vert indices */ - atUint32 matSecCount = 0; - if (head.matSetCount) - matSecCount = MaterialSet::OneSection() ? 1 : head.matSetCount; - atUint32 lastDlSec = head.secCount; - for (size_t s=0 ; s, DNAMP1::MaterialSet> -(athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - PAKRouter::EntryType& entry, - const SpecBase& dataspec); +template void NameCMDL, DNAMP1::MaterialSet>( + athena::io::IStreamReader& reader, PAKRouter& pakRouter, + PAKRouter::EntryType& entry, const SpecBase& dataspec); template -static void WriteDLVal(W& writer, GX::AttrType type, atUint32 val) -{ - switch (type) - { - case GX::DIRECT: - case GX::INDEX8: - writer.writeUByte(atUint8(val)); - break; - case GX::INDEX16: - writer.writeUint16Big(atUint16(val)); - break; - default: break; - } +static void WriteDLVal(W& writer, GX::AttrType type, atUint32 val) { + switch (type) { + case GX::DIRECT: + case GX::INDEX8: + writer.writeUByte(atUint8(val)); + break; + case GX::INDEX16: + writer.writeUint16Big(atUint16(val)); + break; + default: + break; + } } template -bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh) -{ - bool skinned = !mesh.skins.empty(); +bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh) { + bool skinned = !mesh.skins.empty(); - Header head; - head.magic = 0xDEADBABE; - head.version = Version; - head.flags.setSkinned(skinned); - head.flags.setShortNormals(!skinned); - head.flags.setShortUVs(true); /* This just means there's an (empty) short UV section */ - head.aabbMin = mesh.aabbMin.val; - head.aabbMax = mesh.aabbMax.val; - head.matSetCount = mesh.materialSets.size(); - head.secCount = head.matSetCount + 6 + mesh.surfaces.size(); - head.secSizes.reserve(head.secCount); + Header head; + head.magic = 0xDEADBABE; + head.version = Version; + head.flags.setSkinned(skinned); + head.flags.setShortNormals(!skinned); + head.flags.setShortUVs(true); /* This just means there's an (empty) short UV section */ + head.aabbMin = mesh.aabbMin.val; + head.aabbMax = mesh.aabbMax.val; + head.matSetCount = mesh.materialSets.size(); + head.secCount = head.matSetCount + 6 + mesh.surfaces.size(); + head.secSizes.reserve(head.secCount); - /* Lengths of padding to insert while writing */ - std::vector paddingSizes; - paddingSizes.reserve(head.secCount); + /* Lengths of padding to insert while writing */ + std::vector paddingSizes; + paddingSizes.reserve(head.secCount); - /* Build material sets */ - std::vector matSets; - matSets.reserve(mesh.materialSets.size()); - { - hecl::Frontend::Frontend FE; - for (const std::vector& mset : mesh.materialSets) - { - matSets.emplace_back(); - MaterialSet& targetMSet = matSets.back(); - std::vector texPaths; - std::vector setBackends; - setBackends.reserve(mset.size()); + /* Build material sets */ + std::vector matSets; + matSets.reserve(mesh.materialSets.size()); + { + hecl::Frontend::Frontend FE; + for (const std::vector& mset : mesh.materialSets) { + matSets.emplace_back(); + MaterialSet& targetMSet = matSets.back(); + std::vector texPaths; + std::vector setBackends; + setBackends.reserve(mset.size()); - size_t endOff = 0; - for (const Material& mat : mset) - { - std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); - hecl::Frontend::IR matIR = FE.compileSource(mat.source, diagName); - setBackends.emplace_back(); - hecl::Backend::GX& matGX = setBackends.back(); - matGX.reset(matIR, FE.getDiagnostics()); + size_t endOff = 0; + for (const Material& mat : mset) { + std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); + hecl::Frontend::IR matIR = FE.compileSource(mat.source, diagName); + setBackends.emplace_back(); + hecl::Backend::GX& matGX = setBackends.back(); + matGX.reset(matIR, FE.getDiagnostics()); - targetMSet.materials.emplace_back(matGX, mat.iprops, mat.texs, texPaths, - mesh.colorLayerCount, false, false); + targetMSet.materials.emplace_back(matGX, mat.iprops, mat.texs, texPaths, mesh.colorLayerCount, false, false); - targetMSet.materials.back().binarySize(endOff); - targetMSet.head.addMaterialEndOff(endOff); + targetMSet.materials.back().binarySize(endOff); + targetMSet.head.addMaterialEndOff(endOff); + } + + texPaths.reserve(mset.size() * 4); + for (const Material& mat : mset) { + for (const hecl::ProjectPath& path : mat.texs) { + bool found = false; + for (const hecl::ProjectPath& ePath : texPaths) { + if (path == ePath) { + found = true; + break; } - - texPaths.reserve(mset.size()*4); - for (const Material& mat : mset) - { - for (const hecl::ProjectPath& path : mat.texs) - { - bool found = false; - for (const hecl::ProjectPath& ePath : texPaths) - { - if (path == ePath) - { - found = true; - break; - } - } - if (!found) - texPaths.push_back(path); - } - } - - for (const hecl::ProjectPath& path : texPaths) - targetMSet.head.addTexture(path); - - size_t secSz = 0; - targetMSet.binarySize(secSz); - size_t secSz32 = ROUND_UP_32(secSz); - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + } + if (!found) + texPaths.push_back(path); } + } + + for (const hecl::ProjectPath& path : texPaths) + targetMSet.head.addTexture(path); + + size_t secSz = 0; + targetMSet.binarySize(secSz); + size_t secSz32 = ROUND_UP_32(secSz); + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); } + } - /* Vertex Positions */ - size_t secSz = mesh.pos.size() * 12; - size_t secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + /* Vertex Positions */ + size_t secSz = mesh.pos.size() * 12; + size_t secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); - /* Vertex Normals */ - secSz = mesh.norm.size() * (skinned ? 12 : 6); + /* Vertex Normals */ + secSz = mesh.norm.size() * (skinned ? 12 : 6); + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* Vertex Colors */ + secSz = mesh.color.size() * 4; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* UV coords */ + secSz = mesh.uv.size() * 8; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* LUV coords */ + secSz = 0; + secSz32 = ROUND_UP_32(secSz); + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* Surface index */ + std::vector surfEndOffs; + surfEndOffs.reserve(mesh.surfaces.size()); + secSz = mesh.surfaces.size() * 4 + 4; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); + + /* Surfaces */ + size_t endOff = 0; + size_t firstSurfSec = head.secSizes.size(); + for (const Mesh::Surface& surf : mesh.surfaces) { + size_t vertSz = matSets.at(0).materials.at(surf.materialIdx).getVAFlags().vertDLSize(); + if (surf.verts.size() > 65536) + LogDNACommon.report(logvisor::Fatal, "GX DisplayList overflow"); + size_t secSz = 64; + for (auto it = surf.verts.cbegin(); it != surf.verts.cend();) { + atUint16 vertCount = 0; + auto itEnd = surf.verts.cend(); + for (auto it2 = it; it2 != surf.verts.cend(); ++it2, ++vertCount) + if (it2->iPos == 0xffffffff) { + if (vertCount == 3) { + /* All primitives here on out are triangles */ + vertCount = atUint16((surf.verts.cend() - it + 1) * 3 / 4); + break; + } + itEnd = it2; + break; + } + secSz += 3 + vertCount * vertSz; + if (itEnd == surf.verts.cend()) + break; + it = itEnd + 1; + } secSz32 = ROUND_UP_32(secSz); if (secSz32 == 0) - secSz32 = 32; + secSz32 = 32; head.secSizes.push_back(secSz32); paddingSizes.push_back(secSz32 - secSz); + endOff += secSz32; + surfEndOffs.push_back(endOff); + } - /* Vertex Colors */ - secSz = mesh.color.size() * 4; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + /* Write sections */ + athena::io::FileWriter writer(outPath.getAbsolutePath()); + head.write(writer); + std::vector::const_iterator padIt = paddingSizes.cbegin(); - /* UV coords */ - secSz = mesh.uv.size() * 8; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + /* Material Sets */ + for (const MaterialSet& mset : matSets) { + mset.write(writer); + writer.fill(atUint8(0), *padIt); + ++padIt; + } - /* LUV coords */ - secSz = 0; - secSz32 = ROUND_UP_32(secSz); - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + /* Vertex Positions */ + for (const atVec3f& pos : mesh.pos) + writer.writeVec3fBig(pos); + writer.fill(atUint8(0), *padIt); + ++padIt; - /* Surface index */ - std::vector surfEndOffs; - surfEndOffs.reserve(mesh.surfaces.size()); - secSz = mesh.surfaces.size() * 4 + 4; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); - - /* Surfaces */ - size_t endOff = 0; - size_t firstSurfSec = head.secSizes.size(); - for (const Mesh::Surface& surf : mesh.surfaces) - { - size_t vertSz = matSets.at(0).materials.at(surf.materialIdx).getVAFlags().vertDLSize(); - if (surf.verts.size() > 65536) - LogDNACommon.report(logvisor::Fatal, "GX DisplayList overflow"); - size_t secSz = 64; - for (auto it = surf.verts.cbegin() ; it != surf.verts.cend() ;) - { - atUint16 vertCount = 0; - auto itEnd = surf.verts.cend(); - for (auto it2 = it ; it2 != surf.verts.cend() ; ++it2, ++vertCount) - if (it2->iPos == 0xffffffff) - { - if (vertCount == 3) - { - /* All primitives here on out are triangles */ - vertCount = atUint16((surf.verts.cend() - it + 1) * 3 / 4); - break; - } - itEnd = it2; - break; - } - secSz += 3 + vertCount * vertSz; - if (itEnd == surf.verts.cend()) - break; - it = itEnd + 1; - } - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); - endOff += secSz32; - surfEndOffs.push_back(endOff); + /* Vertex Normals */ + for (const atVec3f& norm : mesh.norm) { + if (skinned) { + writer.writeVec3fBig(norm); + } else { + for (int i = 0; i < 3; ++i) { + int tmpV = int(norm.simd[i] * 16384.f); + tmpV = zeus::clamp(-32768, tmpV, 32767); + writer.writeInt16Big(atInt16(tmpV)); + } } + } + writer.fill(atUint8(0), *padIt); + ++padIt; - /* Write sections */ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - head.write(writer); - std::vector::const_iterator padIt = paddingSizes.cbegin(); + /* Vertex Colors */ + for (const atVec3f& col : mesh.color) { + GX::Color qCol(col); + qCol.write(writer); + } + writer.fill(atUint8(0), *padIt); + ++padIt; - /* Material Sets */ - for (const MaterialSet& mset : matSets) - { - mset.write(writer); - writer.fill(atUint8(0), *padIt); - ++padIt; - } + /* UV coords */ + for (const atVec2f& uv : mesh.uv) + writer.writeVec2fBig(uv); + writer.fill(atUint8(0), *padIt); + ++padIt; - /* Vertex Positions */ - for (const atVec3f& pos : mesh.pos) - writer.writeVec3fBig(pos); - writer.fill(atUint8(0), *padIt); - ++padIt; + /* LUV coords */ + writer.fill(atUint8(0), *padIt); + ++padIt; - /* Vertex Normals */ - for (const atVec3f& norm : mesh.norm) - { - if (skinned) - { - writer.writeVec3fBig(norm); - } - else - { - for (int i = 0; i < 3; ++i) - { - int tmpV = int(norm.simd[i] * 16384.f); - tmpV = zeus::clamp(-32768, tmpV, 32767); - writer.writeInt16Big(atInt16(tmpV)); - } - } - } - writer.fill(atUint8(0), *padIt); - ++padIt; + /* Surface index */ + writer.writeUint32Big(surfEndOffs.size()); + for (size_t off : surfEndOffs) + writer.writeUint32Big(off); + writer.fill(atUint8(0), *padIt); + ++padIt; - /* Vertex Colors */ - for (const atVec3f& col : mesh.color) - { - GX::Color qCol(col); - qCol.write(writer); - } - writer.fill(atUint8(0), *padIt); - ++padIt; + /* Surfaces */ + GX::Primitive prim = GX::TRIANGLES; + if (mesh.topology == hecl::HMDLTopology::Triangles) + prim = GX::TRIANGLES; + else if (mesh.topology == hecl::HMDLTopology::TriStrips) + prim = GX::TRIANGLESTRIP; + else + LogDNACommon.report(logvisor::Fatal, "unrecognized mesh output mode"); + auto surfSizeIt = head.secSizes.begin() + firstSurfSec; + for (const Mesh::Surface& surf : mesh.surfaces) { + const typename MaterialSet::Material::VAFlags& vaFlags = matSets.at(0).materials.at(surf.materialIdx).getVAFlags(); - /* UV coords */ - for (const atVec2f& uv : mesh.uv) - writer.writeVec2fBig(uv); - writer.fill(atUint8(0), *padIt); - ++padIt; + SurfaceHeader header; + header.centroid = surf.centroid; + header.matIdx = surf.materialIdx; + header.dlSize = (*surfSizeIt++ - 64) | 0x80000000; + header.reflectionNormal = surf.reflectionNormal; + header.write(writer); - /* LUV coords */ - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Surface index */ - writer.writeUint32Big(surfEndOffs.size()); - for (size_t off : surfEndOffs) - writer.writeUint32Big(off); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Surfaces */ - GX::Primitive prim = GX::TRIANGLES; - if (mesh.topology == hecl::HMDLTopology::Triangles) - prim = GX::TRIANGLES; - else if (mesh.topology == hecl::HMDLTopology::TriStrips) - prim = GX::TRIANGLESTRIP; - else - LogDNACommon.report(logvisor::Fatal, "unrecognized mesh output mode"); - auto surfSizeIt = head.secSizes.begin() + firstSurfSec; - for (const Mesh::Surface& surf : mesh.surfaces) - { - const typename MaterialSet::Material::VAFlags& vaFlags = - matSets.at(0).materials.at(surf.materialIdx).getVAFlags(); - - SurfaceHeader header; - header.centroid = surf.centroid; - header.matIdx = surf.materialIdx; - header.dlSize = (*surfSizeIt++ - 64) | 0x80000000; - header.reflectionNormal = surf.reflectionNormal; - header.write(writer); - - GX::Primitive usePrim = prim; - for (auto it = surf.verts.cbegin() ; it != surf.verts.cend() ;) - { - atUint16 vertCount = 0; - auto itEnd = surf.verts.cend(); - for (auto it2 = it ; it2 != surf.verts.cend() ; ++it2, ++vertCount) - if (it2->iPos == 0xffffffff) - { - if (vertCount == 3) - { - /* All primitives here on out are triangles */ - usePrim = GX::TRIANGLES; - vertCount = atUint16((surf.verts.cend() - it + 1) * 3 / 4); - break; - } - itEnd = it2; - break; - } - - /* VAT0 = float normals, float UVs - * VAT1 = short normals, float UVs */ - writer.writeUByte(usePrim | (skinned ? 0x0 : 0x1)); - writer.writeUint16Big(vertCount); - - for (auto it2 = it ; it2 != itEnd ; ++it2) - { - const Mesh::Surface::Vert& vert = *it2; - if (vert.iPos == 0xffffffff) - continue; - atUint32 skinIdx = vert.iBankSkin * 3; - WriteDLVal(writer, vaFlags.pnMatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex0MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex1MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex2MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex3MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex4MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex5MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.tex6MatIdx(), skinIdx); - WriteDLVal(writer, vaFlags.position(), vert.iPos); - WriteDLVal(writer, vaFlags.normal(), vert.iNorm); - WriteDLVal(writer, vaFlags.color0(), vert.iColor[0]); - WriteDLVal(writer, vaFlags.color1(), vert.iColor[1]); - WriteDLVal(writer, vaFlags.tex0(), vert.iUv[0]); - WriteDLVal(writer, vaFlags.tex1(), vert.iUv[1]); - WriteDLVal(writer, vaFlags.tex2(), vert.iUv[2]); - WriteDLVal(writer, vaFlags.tex3(), vert.iUv[3]); - WriteDLVal(writer, vaFlags.tex4(), vert.iUv[4]); - WriteDLVal(writer, vaFlags.tex5(), vert.iUv[5]); - WriteDLVal(writer, vaFlags.tex6(), vert.iUv[6]); - } - - if (itEnd == surf.verts.cend()) - break; - it = itEnd + 1; + GX::Primitive usePrim = prim; + for (auto it = surf.verts.cbegin(); it != surf.verts.cend();) { + atUint16 vertCount = 0; + auto itEnd = surf.verts.cend(); + for (auto it2 = it; it2 != surf.verts.cend(); ++it2, ++vertCount) + if (it2->iPos == 0xffffffff) { + if (vertCount == 3) { + /* All primitives here on out are triangles */ + usePrim = GX::TRIANGLES; + vertCount = atUint16((surf.verts.cend() - it + 1) * 3 / 4); + break; + } + itEnd = it2; + break; } - writer.fill(atUint8(0), *padIt); - ++padIt; + /* VAT0 = float normals, float UVs + * VAT1 = short normals, float UVs */ + writer.writeUByte(usePrim | (skinned ? 0x0 : 0x1)); + writer.writeUint16Big(vertCount); + + for (auto it2 = it; it2 != itEnd; ++it2) { + const Mesh::Surface::Vert& vert = *it2; + if (vert.iPos == 0xffffffff) + continue; + atUint32 skinIdx = vert.iBankSkin * 3; + WriteDLVal(writer, vaFlags.pnMatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex0MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex1MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex2MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex3MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex4MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex5MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.tex6MatIdx(), skinIdx); + WriteDLVal(writer, vaFlags.position(), vert.iPos); + WriteDLVal(writer, vaFlags.normal(), vert.iNorm); + WriteDLVal(writer, vaFlags.color0(), vert.iColor[0]); + WriteDLVal(writer, vaFlags.color1(), vert.iColor[1]); + WriteDLVal(writer, vaFlags.tex0(), vert.iUv[0]); + WriteDLVal(writer, vaFlags.tex1(), vert.iUv[1]); + WriteDLVal(writer, vaFlags.tex2(), vert.iUv[2]); + WriteDLVal(writer, vaFlags.tex3(), vert.iUv[3]); + WriteDLVal(writer, vaFlags.tex4(), vert.iUv[4]); + WriteDLVal(writer, vaFlags.tex5(), vert.iUv[5]); + WriteDLVal(writer, vaFlags.tex6(), vert.iUv[6]); + } + + if (itEnd == surf.verts.cend()) + break; + it = itEnd + 1; } - writer.close(); - return true; + writer.fill(atUint8(0), *padIt); + ++padIt; + } + + writer.close(); + return true; } -template bool WriteCMDL -(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh); +template bool WriteCMDL(const hecl::ProjectPath& outPath, + const hecl::ProjectPath& inPath, + const Mesh& mesh); template -bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, - const Mesh& mesh, hecl::blender::PoolSkinIndex& poolSkinIndex) -{ - Header head; - head.magic = 0xDEADBABE; - head.version = 0x10000 | Version; - head.aabbMin = mesh.aabbMin.val; - head.aabbMax = mesh.aabbMax.val; - head.matSetCount = mesh.materialSets.size(); - head.secCount = head.matSetCount + 4 + mesh.surfaces.size(); - head.secSizes.reserve(head.secCount); +bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh, + hecl::blender::PoolSkinIndex& poolSkinIndex) { + Header head; + head.magic = 0xDEADBABE; + head.version = 0x10000 | Version; + head.aabbMin = mesh.aabbMin.val; + head.aabbMax = mesh.aabbMax.val; + head.matSetCount = mesh.materialSets.size(); + head.secCount = head.matSetCount + 4 + mesh.surfaces.size(); + head.secSizes.reserve(head.secCount); - /* Lengths of padding to insert while writing */ - std::vector paddingSizes; - paddingSizes.reserve(head.secCount); + /* Lengths of padding to insert while writing */ + std::vector paddingSizes; + paddingSizes.reserve(head.secCount); - /* Build material sets */ - std::vector matSets; - matSets.reserve(mesh.materialSets.size()); - { - hecl::Frontend::Frontend FE; - for (const std::vector& mset : mesh.materialSets) - { - matSets.emplace_back(); - MaterialSet& targetMSet = matSets.back(); - std::vector texPaths; - texPaths.reserve(mset.size()*4); - for (const Material& mat : mset) - { - for (const hecl::ProjectPath& path : mat.texs) - { - bool found = false; - for (const hecl::ProjectPath& ePath : texPaths) - { - if (path == ePath) - { - found = true; - break; - } - } - if (!found) - texPaths.push_back(path); - } + /* Build material sets */ + std::vector matSets; + matSets.reserve(mesh.materialSets.size()); + { + hecl::Frontend::Frontend FE; + for (const std::vector& mset : mesh.materialSets) { + matSets.emplace_back(); + MaterialSet& targetMSet = matSets.back(); + std::vector texPaths; + texPaths.reserve(mset.size() * 4); + for (const Material& mat : mset) { + for (const hecl::ProjectPath& path : mat.texs) { + bool found = false; + for (const hecl::ProjectPath& ePath : texPaths) { + if (path == ePath) { + found = true; + break; } - - size_t endOff = 0; - for (const Material& mat : mset) - { - std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); - targetMSet.materials.emplace_back(FE, diagName, mat, mat.iprops, texPaths); - targetMSet.materials.back().binarySize(endOff); - targetMSet.head.addMaterialEndOff(endOff); - } - - for (const hecl::ProjectPath& path : texPaths) - targetMSet.head.addTexture(path); - - size_t secSz = 0; - targetMSet.binarySize(secSz); - size_t secSz32 = ROUND_UP_32(secSz); - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + } + if (!found) + texPaths.push_back(path); } + } + + size_t endOff = 0; + for (const Material& mat : mset) { + std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); + targetMSet.materials.emplace_back(FE, diagName, mat, mat.iprops, texPaths); + targetMSet.materials.back().binarySize(endOff); + targetMSet.head.addMaterialEndOff(endOff); + } + + for (const hecl::ProjectPath& path : texPaths) + targetMSet.head.addTexture(path); + + size_t secSz = 0; + targetMSet.binarySize(secSz); + size_t secSz32 = ROUND_UP_32(secSz); + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); } + } - hecl::blender::HMDLBuffers bufs = mesh.getHMDLBuffers(false, poolSkinIndex); + hecl::blender::HMDLBuffers bufs = mesh.getHMDLBuffers(false, poolSkinIndex); - /* Metadata */ - size_t secSz = 0; - bufs.m_meta.binarySize(secSz); - size_t secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + /* Metadata */ + size_t secSz = 0; + bufs.m_meta.binarySize(secSz); + size_t secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); - /* VBO */ - secSz = bufs.m_vboSz; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + /* VBO */ + secSz = bufs.m_vboSz; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); - /* IBO */ - secSz = bufs.m_iboSz; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + /* IBO */ + secSz = bufs.m_iboSz; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); - /* Surface index */ - std::vector surfEndOffs; - surfEndOffs.reserve(bufs.m_surfaces.size()); - secSz = bufs.m_surfaces.size() * 4 + 4; - secSz32 = ROUND_UP_32(secSz); - if (secSz32 == 0) - secSz32 = 32; - head.secSizes.push_back(secSz32); - paddingSizes.push_back(secSz32 - secSz); + /* Surface index */ + std::vector surfEndOffs; + surfEndOffs.reserve(bufs.m_surfaces.size()); + secSz = bufs.m_surfaces.size() * 4 + 4; + secSz32 = ROUND_UP_32(secSz); + if (secSz32 == 0) + secSz32 = 32; + head.secSizes.push_back(secSz32); + paddingSizes.push_back(secSz32 - secSz); - /* Surfaces */ - size_t endOff = 0; - for (const hecl::blender::HMDLBuffers::Surface& surf : bufs.m_surfaces) - { - (void)surf; - head.secSizes.push_back(64); - paddingSizes.push_back(0); - endOff += 64; - surfEndOffs.push_back(endOff); - } + /* Surfaces */ + size_t endOff = 0; + for (const hecl::blender::HMDLBuffers::Surface& surf : bufs.m_surfaces) { + (void)surf; + head.secSizes.push_back(64); + paddingSizes.push_back(0); + endOff += 64; + surfEndOffs.push_back(endOff); + } - /* Write sections */ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - head.write(writer); - std::vector::const_iterator padIt = paddingSizes.cbegin(); + /* Write sections */ + athena::io::FileWriter writer(outPath.getAbsolutePath()); + head.write(writer); + std::vector::const_iterator padIt = paddingSizes.cbegin(); - /* Material Sets */ - for (const MaterialSet& mset : matSets) - { - mset.write(writer); - writer.fill(atUint8(0), *padIt); - ++padIt; - } - - /* Metadata */ - bufs.m_meta.write(writer); + /* Material Sets */ + for (const MaterialSet& mset : matSets) { + mset.write(writer); writer.fill(atUint8(0), *padIt); ++padIt; + } + + /* Metadata */ + bufs.m_meta.write(writer); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* VBO */ + writer.writeUBytes(bufs.m_vboData.get(), bufs.m_vboSz); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* IBO */ + writer.writeUBytes(bufs.m_iboData.get(), bufs.m_iboSz); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Surface index */ + writer.writeUint32Big(surfEndOffs.size()); + for (size_t off : surfEndOffs) + writer.writeUint32Big(off); + writer.fill(atUint8(0), *padIt); + ++padIt; + + /* Surfaces */ + for (const hecl::blender::HMDLBuffers::Surface& surf : bufs.m_surfaces) { + const Mesh::Surface& osurf = surf.m_origSurf; + + SurfaceHeader header; + header.centroid = osurf.centroid; + header.matIdx = osurf.materialIdx; + header.reflectionNormal = osurf.reflectionNormal; + header.idxStart = surf.m_start; + header.idxCount = surf.m_count; + header.skinMtxBankIdx = osurf.skinBankIdx; + header.write(writer); - /* VBO */ - writer.writeUBytes(bufs.m_vboData.get(), bufs.m_vboSz); writer.fill(atUint8(0), *padIt); ++padIt; + } - /* IBO */ - writer.writeUBytes(bufs.m_iboData.get(), bufs.m_iboSz); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Surface index */ - writer.writeUint32Big(surfEndOffs.size()); - for (size_t off : surfEndOffs) - writer.writeUint32Big(off); - writer.fill(atUint8(0), *padIt); - ++padIt; - - /* Surfaces */ - for (const hecl::blender::HMDLBuffers::Surface& surf : bufs.m_surfaces) - { - const Mesh::Surface& osurf = surf.m_origSurf; - - SurfaceHeader header; - header.centroid = osurf.centroid; - header.matIdx = osurf.materialIdx; - header.reflectionNormal = osurf.reflectionNormal; - header.idxStart = surf.m_start; - header.idxCount = surf.m_count; - header.skinMtxBankIdx = osurf.skinBankIdx; - header.write(writer); - - writer.fill(atUint8(0), *padIt); - ++padIt; - } - - /* Ensure final surface's alignment writes zeros */ - writer.seek(-1, athena::Current); - writer.writeUByte(0); - writer.close(); - return true; + /* Ensure final surface's alignment writes zeros */ + writer.seek(-1, athena::Current); + writer.writeUByte(0); + writer.close(); + return true; } -template bool WriteHMDLCMDL -(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh, - hecl::blender::PoolSkinIndex& poolSkinIndex); +template bool WriteHMDLCMDL( + const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh, + hecl::blender::PoolSkinIndex& poolSkinIndex); -struct MaterialPool -{ - std::vector materials; - size_t addMaterial(const Material& mat, bool& newMat) - { - size_t ret = 0; - newMat = false; - for (const Material* testMat : materials) - { - if (mat == *testMat) - return ret; - ++ret; - } - materials.push_back(&mat); - newMat = true; +struct MaterialPool { + std::vector materials; + size_t addMaterial(const Material& mat, bool& newMat) { + size_t ret = 0; + newMat = false; + for (const Material* testMat : materials) { + if (mat == *testMat) return ret; + ++ret; } + materials.push_back(&mat); + newMat = true; + return ret; + } }; template bool WriteMREASecs(std::vector>& secsOut, const hecl::ProjectPath& inPath, - const std::vector& meshes, zeus::CAABox& fullAABB, std::vector& meshAABBs) -{ - /* Build material set */ - std::vector surfToGlobalMats; - MaterialSet matSet; - { - MaterialPool matPool; + const std::vector& meshes, zeus::CAABox& fullAABB, std::vector& meshAABBs) { + /* Build material set */ + std::vector surfToGlobalMats; + MaterialSet matSet; + { + MaterialPool matPool; - size_t surfCount = 0; - for (const Mesh& mesh : meshes) - surfCount += mesh.surfaces.size(); - surfToGlobalMats.reserve(surfCount); - - hecl::Frontend::Frontend FE; - size_t endOff = 0; - std::vector texPaths; - std::vector setBackends; - for (const Mesh& mesh : meshes) - { - if (mesh.materialSets.size()) - { - std::vector meshToGlobalMats; - meshToGlobalMats.reserve(mesh.materialSets[0].size()); - - for (const Material& mat : mesh.materialSets[0]) - { - bool newMat; - size_t idx = matPool.addMaterial(mat, newMat); - meshToGlobalMats.push_back(idx); - if (!newMat) - continue; - - for (const hecl::ProjectPath& path : mat.texs) - { - bool found = false; - for (const hecl::ProjectPath& ePath : texPaths) - { - if (path == ePath) - { - found = true; - break; - } - } - if (!found) - texPaths.push_back(path); - } - - std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); - hecl::Frontend::IR matIR = FE.compileSource(mat.source, diagName); - setBackends.emplace_back(); - hecl::Backend::GX& matGX = setBackends.back(); - matGX.reset(matIR, FE.getDiagnostics()); - - auto lightmapped = mat.iprops.find("retro_lightmapped"); - bool lm = lightmapped != mat.iprops.cend() && lightmapped->second != 0; - - matSet.materials.emplace_back(matGX, mat.iprops, mat.texs, texPaths, - mesh.colorLayerCount, lm, false); - - matSet.materials.back().binarySize(endOff); - matSet.head.addMaterialEndOff(endOff); - } - - for (const Mesh::Surface& surf : mesh.surfaces) - surfToGlobalMats.push_back(meshToGlobalMats[surf.materialIdx]); - } - } - for (const hecl::ProjectPath& path : texPaths) - matSet.head.addTexture(path); - - size_t secSz = 0; - matSet.binarySize(secSz); - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - matSet.write(w); - } - - /* Iterate meshes */ - auto matIt = surfToGlobalMats.cbegin(); + size_t surfCount = 0; for (const Mesh& mesh : meshes) + surfCount += mesh.surfaces.size(); + surfToGlobalMats.reserve(surfCount); + + hecl::Frontend::Frontend FE; + size_t endOff = 0; + std::vector texPaths; + std::vector setBackends; + for (const Mesh& mesh : meshes) { + if (mesh.materialSets.size()) { + std::vector meshToGlobalMats; + meshToGlobalMats.reserve(mesh.materialSets[0].size()); + + for (const Material& mat : mesh.materialSets[0]) { + bool newMat; + size_t idx = matPool.addMaterial(mat, newMat); + meshToGlobalMats.push_back(idx); + if (!newMat) + continue; + + for (const hecl::ProjectPath& path : mat.texs) { + bool found = false; + for (const hecl::ProjectPath& ePath : texPaths) { + if (path == ePath) { + found = true; + break; + } + } + if (!found) + texPaths.push_back(path); + } + + std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); + hecl::Frontend::IR matIR = FE.compileSource(mat.source, diagName); + setBackends.emplace_back(); + hecl::Backend::GX& matGX = setBackends.back(); + matGX.reset(matIR, FE.getDiagnostics()); + + auto lightmapped = mat.iprops.find("retro_lightmapped"); + bool lm = lightmapped != mat.iprops.cend() && lightmapped->second != 0; + + matSet.materials.emplace_back(matGX, mat.iprops, mat.texs, texPaths, mesh.colorLayerCount, lm, false); + + matSet.materials.back().binarySize(endOff); + matSet.head.addMaterialEndOff(endOff); + } + + for (const Mesh::Surface& surf : mesh.surfaces) + surfToGlobalMats.push_back(meshToGlobalMats[surf.materialIdx]); + } + } + for (const hecl::ProjectPath& path : texPaths) + matSet.head.addTexture(path); + + size_t secSz = 0; + matSet.binarySize(secSz); + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + matSet.write(w); + } + + /* Iterate meshes */ + auto matIt = surfToGlobalMats.cbegin(); + for (const Mesh& mesh : meshes) { + zeus::CTransform meshXf(mesh.sceneXf.val); + meshXf.basis.transpose(); + + /* Header */ { - zeus::CTransform meshXf(mesh.sceneXf.val); - meshXf.basis.transpose(); + MeshHeader meshHeader = {}; + meshHeader.visorFlags.setFromBlenderProps(mesh.customProps); + memmove(meshHeader.xfMtx, &mesh.sceneXf, 48); - /* Header */ - { - MeshHeader meshHeader = {}; - meshHeader.visorFlags.setFromBlenderProps(mesh.customProps); - memmove(meshHeader.xfMtx, &mesh.sceneXf, 48); + zeus::CAABox aabb(zeus::CVector3f(mesh.aabbMin), zeus::CVector3f(mesh.aabbMax)); + aabb = aabb.getTransformedAABox(meshXf); + meshAABBs.push_back(aabb); + fullAABB.accumulateBounds(aabb); + meshHeader.aabb[0] = aabb.min; + meshHeader.aabb[1] = aabb.max; - zeus::CAABox aabb(zeus::CVector3f(mesh.aabbMin), zeus::CVector3f(mesh.aabbMax)); - aabb = aabb.getTransformedAABox(meshXf); - meshAABBs.push_back(aabb); - fullAABB.accumulateBounds(aabb); - meshHeader.aabb[0] = aabb.min; - meshHeader.aabb[1] = aabb.max; - - size_t secSz = 0; - meshHeader.binarySize(secSz); - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - meshHeader.write(w); - } - - std::vector surfEndOffs; - surfEndOffs.reserve(mesh.surfaces.size()); - size_t endOff = 0; - auto smatIt = matIt; - for (const Mesh::Surface& surf : mesh.surfaces) - { - const typename MaterialSet::Material::VAFlags& vaFlags = - matSet.materials.at(*smatIt++).getVAFlags(); - size_t vertSz = vaFlags.vertDLSize(); - - endOff += 96; - for (auto it = surf.verts.cbegin() ; it != surf.verts.cend() ;) - { - atUint16 vertCount = 0; - auto itEnd = surf.verts.cend(); - for (auto it2 = it ; it2 != surf.verts.cend() ; ++it2, ++vertCount) - if (it2->iPos == 0xffffffff) - { - if (vertCount == 3) - { - /* All primitives here on out are triangles */ - vertCount = atUint16((surf.verts.cend() - it + 1) * 3 / 4); - break; - } - itEnd = it2; - break; - } - endOff += 3 + vertSz * vertCount; - if (itEnd == surf.verts.cend()) - break; - it = itEnd + 1; - } - endOff = ROUND_UP_32(endOff); - surfEndOffs.push_back(endOff); - } - - /* Positions */ - { - size_t secSz = ROUND_UP_32(mesh.pos.size() * 12); - if (secSz == 0) - secSz = 32; - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - for (const hecl::blender::Vector3f& v : mesh.pos) - { - zeus::CVector3f preXfPos = meshXf * zeus::CVector3f(v); - w.writeVec3fBig(preXfPos); - } - } - - /* Normals */ - { - size_t secSz = ROUND_UP_32(mesh.norm.size() * 6); - if (secSz == 0) - secSz = 32; - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - for (const hecl::blender::Vector3f& v : mesh.norm) - { - zeus::CVector3f preXfNorm = (meshXf.basis * zeus::CVector3f(v)).normalized(); - for (int i=0 ; i<3 ; ++i) - { - int tmpV = int(preXfNorm[i] * 16384.f); - tmpV = zeus::clamp(-32768, tmpV, 32767); - w.writeInt16Big(atInt16(tmpV)); - } - } - } - - /* Colors */ - { - size_t secSz = ROUND_UP_32(mesh.color.size() * 4); - if (secSz == 0) - secSz = 32; - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - for (const hecl::blender::Vector3f& v : mesh.color) - { - zeus::CColor col((zeus::CVector4f(zeus::CVector3f(v)))); - col.writeRGBA8(w); - } - } - - /* UVs */ - { - size_t secSz = ROUND_UP_32(mesh.uv.size() * 8); - if (secSz == 0) - secSz = 32; - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - for (const hecl::blender::Vector2f& v : mesh.uv) - w.writeVec2fBig(v.val); - } - - /* LUVs */ - { - size_t secSz = ROUND_UP_32(mesh.luv.size() * 4); - if (secSz == 0) - secSz = 32; - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - for (const hecl::blender::Vector2f& v : mesh.luv) - { - for (int i=0 ; i<2 ; ++i) - { - int tmpV = int(v.val.simd[i] * 32768.f); - tmpV = zeus::clamp(-32768, tmpV, 32767); - w.writeInt16Big(atInt16(tmpV)); - } - } - } - - /* Surface index */ - { - secsOut.emplace_back((surfEndOffs.size() + 1) * 4, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - w.writeUint32Big(surfEndOffs.size()); - for (size_t off : surfEndOffs) - w.writeUint32Big(off); - } - - /* Surfaces */ - GX::Primitive prim = GX::TRIANGLES; - if (mesh.topology == hecl::HMDLTopology::Triangles) - prim = GX::TRIANGLES; - else if (mesh.topology == hecl::HMDLTopology::TriStrips) - prim = GX::TRIANGLESTRIP; - else - LogDNACommon.report(logvisor::Fatal, "unrecognized mesh output mode"); - auto surfEndOffIt = surfEndOffs.begin(); - size_t lastEndOff = 0; - for (const Mesh::Surface& surf : mesh.surfaces) - { - size_t matIdx = *matIt++; - const typename MaterialSet::Material& mat = matSet.materials.at(matIdx); - const typename MaterialSet::Material::VAFlags& vaFlags = mat.getVAFlags(); - - SurfaceHeader header; - header.centroid = meshXf * zeus::CVector3f(surf.centroid); - header.matIdx = matIdx; - uint32_t dlSize = uint32_t(*surfEndOffIt - lastEndOff - 96); - header.dlSize = dlSize | 0x80000000; - lastEndOff = *surfEndOffIt++; - header.reflectionNormal = (meshXf.basis * zeus::CVector3f(surf.reflectionNormal)).normalized(); - header.aabbSz = 24; - zeus::CAABox aabb(zeus::CVector3f(surf.aabbMin), zeus::CVector3f(surf.aabbMax)); - aabb = aabb.getTransformedAABox(meshXf); - header.aabb[0] = aabb.min; - header.aabb[1] = aabb.max; - - size_t secSz = 0; - header.binarySize(secSz); - secSz += dlSize; - secSz = ROUND_UP_32(secSz); - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - header.write(w); - - GX::Primitive usePrim = prim; - for (auto it = surf.verts.cbegin() ; it != surf.verts.cend() ;) - { - atUint16 vertCount = 0; - auto itEnd = surf.verts.cend(); - for (auto it2 = it ; it2 != surf.verts.cend() ; ++it2, ++vertCount) - if (it2->iPos == 0xffffffff) - { - if (vertCount == 3) - { - /* All primitives here on out are triangles */ - usePrim = GX::TRIANGLES; - vertCount = atUint16((surf.verts.cend() - it + 1) * 3 / 4); - break; - } - itEnd = it2; - break; - } - - /* VAT1 = short normals, float UVs - * VAT2 = short normals, short UVs */ - w.writeUByte(usePrim | (mat.flags.lightmapUVArray() ? 0x2 : 0x1)); - w.writeUint16Big(vertCount); - - for (auto it2 = it ; it2 != itEnd ; ++it2) - { - const Mesh::Surface::Vert& vert = *it2; - if (vert.iPos == 0xffffffff) - continue; - atUint32 skinIdx = vert.iBankSkin * 3; - WriteDLVal(w, vaFlags.pnMatIdx(), skinIdx); - WriteDLVal(w, vaFlags.tex0MatIdx(), skinIdx); - WriteDLVal(w, vaFlags.tex1MatIdx(), skinIdx); - WriteDLVal(w, vaFlags.tex2MatIdx(), skinIdx); - WriteDLVal(w, vaFlags.tex3MatIdx(), skinIdx); - WriteDLVal(w, vaFlags.tex4MatIdx(), skinIdx); - WriteDLVal(w, vaFlags.tex5MatIdx(), skinIdx); - WriteDLVal(w, vaFlags.tex6MatIdx(), skinIdx); - WriteDLVal(w, vaFlags.position(), vert.iPos); - WriteDLVal(w, vaFlags.normal(), vert.iNorm); - WriteDLVal(w, vaFlags.color0(), vert.iColor[0]); - WriteDLVal(w, vaFlags.color1(), vert.iColor[1]); - WriteDLVal(w, vaFlags.tex0(), vert.iUv[0]); - WriteDLVal(w, vaFlags.tex1(), vert.iUv[1]); - WriteDLVal(w, vaFlags.tex2(), vert.iUv[2]); - WriteDLVal(w, vaFlags.tex3(), vert.iUv[3]); - WriteDLVal(w, vaFlags.tex4(), vert.iUv[4]); - WriteDLVal(w, vaFlags.tex5(), vert.iUv[5]); - WriteDLVal(w, vaFlags.tex6(), vert.iUv[6]); - } - - if (itEnd == surf.verts.cend()) - break; - it = itEnd + 1; - } - } + size_t secSz = 0; + meshHeader.binarySize(secSz); + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + meshHeader.write(w); } - return true; + std::vector surfEndOffs; + surfEndOffs.reserve(mesh.surfaces.size()); + size_t endOff = 0; + auto smatIt = matIt; + for (const Mesh::Surface& surf : mesh.surfaces) { + const typename MaterialSet::Material::VAFlags& vaFlags = matSet.materials.at(*smatIt++).getVAFlags(); + size_t vertSz = vaFlags.vertDLSize(); + + endOff += 96; + for (auto it = surf.verts.cbegin(); it != surf.verts.cend();) { + atUint16 vertCount = 0; + auto itEnd = surf.verts.cend(); + for (auto it2 = it; it2 != surf.verts.cend(); ++it2, ++vertCount) + if (it2->iPos == 0xffffffff) { + if (vertCount == 3) { + /* All primitives here on out are triangles */ + vertCount = atUint16((surf.verts.cend() - it + 1) * 3 / 4); + break; + } + itEnd = it2; + break; + } + endOff += 3 + vertSz * vertCount; + if (itEnd == surf.verts.cend()) + break; + it = itEnd + 1; + } + endOff = ROUND_UP_32(endOff); + surfEndOffs.push_back(endOff); + } + + /* Positions */ + { + size_t secSz = ROUND_UP_32(mesh.pos.size() * 12); + if (secSz == 0) + secSz = 32; + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + for (const hecl::blender::Vector3f& v : mesh.pos) { + zeus::CVector3f preXfPos = meshXf * zeus::CVector3f(v); + w.writeVec3fBig(preXfPos); + } + } + + /* Normals */ + { + size_t secSz = ROUND_UP_32(mesh.norm.size() * 6); + if (secSz == 0) + secSz = 32; + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + for (const hecl::blender::Vector3f& v : mesh.norm) { + zeus::CVector3f preXfNorm = (meshXf.basis * zeus::CVector3f(v)).normalized(); + for (int i = 0; i < 3; ++i) { + int tmpV = int(preXfNorm[i] * 16384.f); + tmpV = zeus::clamp(-32768, tmpV, 32767); + w.writeInt16Big(atInt16(tmpV)); + } + } + } + + /* Colors */ + { + size_t secSz = ROUND_UP_32(mesh.color.size() * 4); + if (secSz == 0) + secSz = 32; + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + for (const hecl::blender::Vector3f& v : mesh.color) { + zeus::CColor col((zeus::CVector4f(zeus::CVector3f(v)))); + col.writeRGBA8(w); + } + } + + /* UVs */ + { + size_t secSz = ROUND_UP_32(mesh.uv.size() * 8); + if (secSz == 0) + secSz = 32; + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + for (const hecl::blender::Vector2f& v : mesh.uv) + w.writeVec2fBig(v.val); + } + + /* LUVs */ + { + size_t secSz = ROUND_UP_32(mesh.luv.size() * 4); + if (secSz == 0) + secSz = 32; + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + for (const hecl::blender::Vector2f& v : mesh.luv) { + for (int i = 0; i < 2; ++i) { + int tmpV = int(v.val.simd[i] * 32768.f); + tmpV = zeus::clamp(-32768, tmpV, 32767); + w.writeInt16Big(atInt16(tmpV)); + } + } + } + + /* Surface index */ + { + secsOut.emplace_back((surfEndOffs.size() + 1) * 4, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + w.writeUint32Big(surfEndOffs.size()); + for (size_t off : surfEndOffs) + w.writeUint32Big(off); + } + + /* Surfaces */ + GX::Primitive prim = GX::TRIANGLES; + if (mesh.topology == hecl::HMDLTopology::Triangles) + prim = GX::TRIANGLES; + else if (mesh.topology == hecl::HMDLTopology::TriStrips) + prim = GX::TRIANGLESTRIP; + else + LogDNACommon.report(logvisor::Fatal, "unrecognized mesh output mode"); + auto surfEndOffIt = surfEndOffs.begin(); + size_t lastEndOff = 0; + for (const Mesh::Surface& surf : mesh.surfaces) { + size_t matIdx = *matIt++; + const typename MaterialSet::Material& mat = matSet.materials.at(matIdx); + const typename MaterialSet::Material::VAFlags& vaFlags = mat.getVAFlags(); + + SurfaceHeader header; + header.centroid = meshXf * zeus::CVector3f(surf.centroid); + header.matIdx = matIdx; + uint32_t dlSize = uint32_t(*surfEndOffIt - lastEndOff - 96); + header.dlSize = dlSize | 0x80000000; + lastEndOff = *surfEndOffIt++; + header.reflectionNormal = (meshXf.basis * zeus::CVector3f(surf.reflectionNormal)).normalized(); + header.aabbSz = 24; + zeus::CAABox aabb(zeus::CVector3f(surf.aabbMin), zeus::CVector3f(surf.aabbMax)); + aabb = aabb.getTransformedAABox(meshXf); + header.aabb[0] = aabb.min; + header.aabb[1] = aabb.max; + + size_t secSz = 0; + header.binarySize(secSz); + secSz += dlSize; + secSz = ROUND_UP_32(secSz); + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + header.write(w); + + GX::Primitive usePrim = prim; + for (auto it = surf.verts.cbegin(); it != surf.verts.cend();) { + atUint16 vertCount = 0; + auto itEnd = surf.verts.cend(); + for (auto it2 = it; it2 != surf.verts.cend(); ++it2, ++vertCount) + if (it2->iPos == 0xffffffff) { + if (vertCount == 3) { + /* All primitives here on out are triangles */ + usePrim = GX::TRIANGLES; + vertCount = atUint16((surf.verts.cend() - it + 1) * 3 / 4); + break; + } + itEnd = it2; + break; + } + + /* VAT1 = short normals, float UVs + * VAT2 = short normals, short UVs */ + w.writeUByte(usePrim | (mat.flags.lightmapUVArray() ? 0x2 : 0x1)); + w.writeUint16Big(vertCount); + + for (auto it2 = it; it2 != itEnd; ++it2) { + const Mesh::Surface::Vert& vert = *it2; + if (vert.iPos == 0xffffffff) + continue; + atUint32 skinIdx = vert.iBankSkin * 3; + WriteDLVal(w, vaFlags.pnMatIdx(), skinIdx); + WriteDLVal(w, vaFlags.tex0MatIdx(), skinIdx); + WriteDLVal(w, vaFlags.tex1MatIdx(), skinIdx); + WriteDLVal(w, vaFlags.tex2MatIdx(), skinIdx); + WriteDLVal(w, vaFlags.tex3MatIdx(), skinIdx); + WriteDLVal(w, vaFlags.tex4MatIdx(), skinIdx); + WriteDLVal(w, vaFlags.tex5MatIdx(), skinIdx); + WriteDLVal(w, vaFlags.tex6MatIdx(), skinIdx); + WriteDLVal(w, vaFlags.position(), vert.iPos); + WriteDLVal(w, vaFlags.normal(), vert.iNorm); + WriteDLVal(w, vaFlags.color0(), vert.iColor[0]); + WriteDLVal(w, vaFlags.color1(), vert.iColor[1]); + WriteDLVal(w, vaFlags.tex0(), vert.iUv[0]); + WriteDLVal(w, vaFlags.tex1(), vert.iUv[1]); + WriteDLVal(w, vaFlags.tex2(), vert.iUv[2]); + WriteDLVal(w, vaFlags.tex3(), vert.iUv[3]); + WriteDLVal(w, vaFlags.tex4(), vert.iUv[4]); + WriteDLVal(w, vaFlags.tex5(), vert.iUv[5]); + WriteDLVal(w, vaFlags.tex6(), vert.iUv[6]); + } + + if (itEnd == surf.verts.cend()) + break; + it = itEnd + 1; + } + } + } + + return true; } -template bool WriteMREASecs - (std::vector>& secsOut, const hecl::ProjectPath& inPath, - const std::vector& meshes, zeus::CAABox& fullAABB, std::vector& meshAABBs); +template bool WriteMREASecs( + std::vector>& secsOut, const hecl::ProjectPath& inPath, const std::vector& meshes, + zeus::CAABox& fullAABB, std::vector& meshAABBs); template bool WriteHMDLMREASecs(std::vector>& secsOut, const hecl::ProjectPath& inPath, - const std::vector& meshes, zeus::CAABox& fullAABB, std::vector& meshAABBs) -{ - /* Build material set */ - std::vector surfToGlobalMats; - { - MaterialPool matPool; + const std::vector& meshes, zeus::CAABox& fullAABB, std::vector& meshAABBs) { + /* Build material set */ + std::vector surfToGlobalMats; + { + MaterialPool matPool; - size_t surfCount = 0; - for (const Mesh& mesh : meshes) - surfCount += mesh.surfaces.size(); - surfToGlobalMats.reserve(surfCount); - - MaterialSet matSet; - hecl::Frontend::Frontend FE; - size_t endOff = 0; - std::vector texPaths; - for (const Mesh& mesh : meshes) - { - if (mesh.materialSets.size()) - { - std::vector meshToGlobalMats; - meshToGlobalMats.reserve(mesh.materialSets[0].size()); - - for (const Material& mat : mesh.materialSets[0]) - { - bool newMat; - size_t idx = matPool.addMaterial(mat, newMat); - meshToGlobalMats.push_back(idx); - if (!newMat) - continue; - - for (const hecl::ProjectPath& path : mat.texs) - { - bool found = false; - for (const hecl::ProjectPath& ePath : texPaths) - { - if (path == ePath) - { - found = true; - break; - } - } - if (!found) - texPaths.push_back(path); - } - - std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); - matSet.materials.emplace_back(FE, diagName, mat, mat.iprops, texPaths); - matSet.materials.back().binarySize(endOff); - matSet.head.addMaterialEndOff(endOff); - } - - for (const Mesh::Surface& surf : mesh.surfaces) - surfToGlobalMats.push_back(meshToGlobalMats[surf.materialIdx]); - } - } - for (const hecl::ProjectPath& path : texPaths) - matSet.head.addTexture(path); - - size_t secSz = 0; - matSet.binarySize(secSz); - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - matSet.write(w); - } - - /* Iterate meshes */ - auto matIt = surfToGlobalMats.cbegin(); + size_t surfCount = 0; for (const Mesh& mesh : meshes) - { - zeus::CTransform meshXf(mesh.sceneXf.val); - meshXf.basis.transpose(); + surfCount += mesh.surfaces.size(); + surfToGlobalMats.reserve(surfCount); - /* Header */ - { - MeshHeader meshHeader = {}; - meshHeader.visorFlags.setFromBlenderProps(mesh.customProps); - memmove(meshHeader.xfMtx, &mesh.sceneXf, 48); + MaterialSet matSet; + hecl::Frontend::Frontend FE; + size_t endOff = 0; + std::vector texPaths; + for (const Mesh& mesh : meshes) { + if (mesh.materialSets.size()) { + std::vector meshToGlobalMats; + meshToGlobalMats.reserve(mesh.materialSets[0].size()); - zeus::CAABox aabb(zeus::CVector3f(mesh.aabbMin), zeus::CVector3f(mesh.aabbMax)); - aabb = aabb.getTransformedAABox(meshXf); - meshAABBs.push_back(aabb); - fullAABB.accumulateBounds(aabb); - meshHeader.aabb[0] = aabb.min; - meshHeader.aabb[1] = aabb.max; + for (const Material& mat : mesh.materialSets[0]) { + bool newMat; + size_t idx = matPool.addMaterial(mat, newMat); + meshToGlobalMats.push_back(idx); + if (!newMat) + continue; - size_t secSz = 0; - meshHeader.binarySize(secSz); - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - meshHeader.write(w); + for (const hecl::ProjectPath& path : mat.texs) { + bool found = false; + for (const hecl::ProjectPath& ePath : texPaths) { + if (path == ePath) { + found = true; + break; + } + } + if (!found) + texPaths.push_back(path); + } + + std::string diagName = hecl::Format("%s:%s", inPath.getLastComponentUTF8().data(), mat.name.c_str()); + matSet.materials.emplace_back(FE, diagName, mat, mat.iprops, texPaths); + matSet.materials.back().binarySize(endOff); + matSet.head.addMaterialEndOff(endOff); } - hecl::blender::PoolSkinIndex poolSkinIndex; - hecl::blender::HMDLBuffers bufs = mesh.getHMDLBuffers(true, poolSkinIndex); - - std::vector surfEndOffs; - surfEndOffs.reserve(bufs.m_surfaces.size()); - size_t endOff = 0; - for (const hecl::blender::HMDLBuffers::Surface& surf : bufs.m_surfaces) - { - (void)surf; - endOff += 96; - surfEndOffs.push_back(endOff); - } - - /* Metadata */ - { - size_t secSz = 0; - bufs.m_meta.binarySize(secSz); - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - bufs.m_meta.write(w); - } - - /* VBO */ - { - secsOut.emplace_back(bufs.m_vboSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - w.writeUBytes(bufs.m_vboData.get(), bufs.m_vboSz); - } - - /* IBO */ - { - secsOut.emplace_back(bufs.m_iboSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - w.writeUBytes(bufs.m_iboData.get(), bufs.m_iboSz); - } - - /* Surface index */ - { - secsOut.emplace_back((surfEndOffs.size() + 1) * 4, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - w.writeUint32Big(surfEndOffs.size()); - for (size_t off : surfEndOffs) - w.writeUint32Big(off); - } - - /* Surfaces */ - for (const hecl::blender::HMDLBuffers::Surface& surf : bufs.m_surfaces) - { - const Mesh::Surface& osurf = surf.m_origSurf; - - SurfaceHeader header; - header.centroid = meshXf * zeus::CVector3f(osurf.centroid); - header.matIdx = *matIt++; - header.reflectionNormal = (meshXf.basis * zeus::CVector3f(osurf.reflectionNormal)).normalized(); - header.idxStart = surf.m_start; - header.idxCount = surf.m_count; - header.skinMtxBankIdx = osurf.skinBankIdx; - - header.aabbSz = 24; - zeus::CAABox aabb(zeus::CVector3f(surf.m_origSurf.aabbMin), zeus::CVector3f(surf.m_origSurf.aabbMax)); - aabb = aabb.getTransformedAABox(meshXf); - header.aabb[0] = aabb.min; - header.aabb[1] = aabb.max; - - size_t secSz = 0; - header.binarySize(secSz); - secsOut.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); - header.write(w); - } + for (const Mesh::Surface& surf : mesh.surfaces) + surfToGlobalMats.push_back(meshToGlobalMats[surf.materialIdx]); + } } + for (const hecl::ProjectPath& path : texPaths) + matSet.head.addTexture(path); - return true; -} + size_t secSz = 0; + matSet.binarySize(secSz); + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + matSet.write(w); + } -template bool WriteHMDLMREASecs -(std::vector>& secsOut, const hecl::ProjectPath& inPath, - const std::vector& meshes, zeus::CAABox& fullAABB, std::vector& meshAABBs); + /* Iterate meshes */ + auto matIt = surfToGlobalMats.cbegin(); + for (const Mesh& mesh : meshes) { + zeus::CTransform meshXf(mesh.sceneXf.val); + meshXf.basis.transpose(); -template <> -void SurfaceHeader_1::Enumerate(typename Read::StreamT& reader) -{ - /* centroid */ - centroid = reader.readVec3fBig(); - /* matIdx */ - matIdx = reader.readUint32Big(); - /* dlSize */ - dlSize = reader.readUint32Big(); - /* idxStart */ - idxStart = reader.readUint32Big(); - /* idxCount */ - idxCount = reader.readUint32Big(); - /* aabbSz */ - aabbSz = reader.readUint32Big(); - /* reflectionNormal */ - reflectionNormal = reader.readVec3fBig(); - /* aabb */ - size_t remAABB = aabbSz; - if (remAABB >= 24) + /* Header */ { - aabb[0] = reader.readVec3fBig(); - aabb[1] = reader.readVec3fBig(); - remAABB -= 24; - } - reader.seek(remAABB, athena::Current); - /* align */ - reader.seekAlign32(); -} + MeshHeader meshHeader = {}; + meshHeader.visorFlags.setFromBlenderProps(mesh.customProps); + memmove(meshHeader.xfMtx, &mesh.sceneXf, 48); -template <> -void SurfaceHeader_1::Enumerate(typename Write::StreamT& writer) -{ - /* centroid */ - writer.writeVec3fBig(centroid); - /* matIdx */ - writer.writeUint32Big(matIdx); - /* dlSize */ - writer.writeUint32Big(dlSize); - /* idxStart */ - writer.writeUint32Big(idxStart); - /* idxCount */ - writer.writeUint32Big(idxCount); - /* aabbSz */ - writer.writeUint32Big(aabbSz ? 24 : 0); - /* reflectionNormal */ - writer.writeVec3fBig(reflectionNormal); - /* aabb */ - if (aabbSz) + zeus::CAABox aabb(zeus::CVector3f(mesh.aabbMin), zeus::CVector3f(mesh.aabbMax)); + aabb = aabb.getTransformedAABox(meshXf); + meshAABBs.push_back(aabb); + fullAABB.accumulateBounds(aabb); + meshHeader.aabb[0] = aabb.min; + meshHeader.aabb[1] = aabb.max; + + size_t secSz = 0; + meshHeader.binarySize(secSz); + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + meshHeader.write(w); + } + + hecl::blender::PoolSkinIndex poolSkinIndex; + hecl::blender::HMDLBuffers bufs = mesh.getHMDLBuffers(true, poolSkinIndex); + + std::vector surfEndOffs; + surfEndOffs.reserve(bufs.m_surfaces.size()); + size_t endOff = 0; + for (const hecl::blender::HMDLBuffers::Surface& surf : bufs.m_surfaces) { + (void)surf; + endOff += 96; + surfEndOffs.push_back(endOff); + } + + /* Metadata */ { - writer.writeVec3fBig(aabb[0]); - writer.writeVec3fBig(aabb[1]); + size_t secSz = 0; + bufs.m_meta.binarySize(secSz); + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + bufs.m_meta.write(w); } - /* align */ - writer.seekAlign32(); -} -template <> -void SurfaceHeader_1::Enumerate(typename BinarySize::StreamT& s) -{ - s += (aabbSz ? 24 : 0); - s += 44; - s = (s + 31) & ~31; -} - -template <> -void SurfaceHeader_2::Enumerate(typename Read::StreamT& reader) -{ - /* centroid */ - centroid = reader.readVec3fBig(); - /* matIdx */ - matIdx = reader.readUint32Big(); - /* dlSize */ - dlSize = reader.readUint32Big(); - /* idxStart */ - idxStart = reader.readUint32Big(); - /* idxCount */ - idxCount = reader.readUint32Big(); - /* aabbSz */ - aabbSz = reader.readUint32Big(); - /* reflectionNormal */ - reflectionNormal = reader.readVec3fBig(); - /* skinMtxBankIdx */ - skinMtxBankIdx = reader.readInt16Big(); - /* surfaceGroup */ - surfaceGroup = reader.readUint16Big(); - /* aabb */ - size_t remAABB = aabbSz; - if (remAABB >= 24) + /* VBO */ { - aabb[0] = reader.readVec3fBig(); - aabb[1] = reader.readVec3fBig(); - remAABB -= 24; + secsOut.emplace_back(bufs.m_vboSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + w.writeUBytes(bufs.m_vboData.get(), bufs.m_vboSz); } - reader.seek(remAABB, athena::Current); - /* align */ - reader.seekAlign32(); -} -template <> -void SurfaceHeader_2::Enumerate(typename Write::StreamT& writer) -{ - /* centroid */ - writer.writeVec3fBig(centroid); - /* matIdx */ - writer.writeUint32Big(matIdx); - /* dlSize */ - writer.writeUint32Big(dlSize); - /* idxStart */ - writer.writeUint32Big(idxStart); - /* idxCount */ - writer.writeUint32Big(idxCount); - /* aabbSz */ - writer.writeUint32Big(aabbSz ? 24 : 0); - /* reflectionNormal */ - writer.writeVec3fBig(reflectionNormal); - /* skinMtxBankIdx */ - writer.writeInt16Big(skinMtxBankIdx); - /* surfaceGroup */ - writer.writeUint16Big(surfaceGroup); - /* aabb */ - if (aabbSz) + /* IBO */ { - writer.writeVec3fBig(aabb[0]); - writer.writeVec3fBig(aabb[1]); + secsOut.emplace_back(bufs.m_iboSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + w.writeUBytes(bufs.m_iboData.get(), bufs.m_iboSz); } - /* align */ - writer.seekAlign32(); -} -template <> -void SurfaceHeader_2::Enumerate(typename BinarySize::StreamT& s) -{ - s += (aabbSz ? 24 : 0); - s += 48; - s = (s + 31) & ~31; -} - -template <> -void SurfaceHeader_3::Enumerate(typename Read::StreamT& reader) -{ - /* centroid */ - centroid = reader.readVec3fBig(); - /* matIdx */ - matIdx = reader.readUint32Big(); - /* dlSize */ - dlSize = reader.readUint32Big(); - /* idxStart */ - idxStart = reader.readUint32Big(); - /* idxCount */ - idxCount = reader.readUint32Big(); - /* aabbSz */ - aabbSz = reader.readUint32Big(); - /* reflectionNormal */ - reflectionNormal = reader.readVec3fBig(); - /* skinMtxBankIdx */ - skinMtxBankIdx = reader.readInt16Big(); - /* surfaceGroup */ - surfaceGroup = reader.readUint16Big(); - /* aabb */ - size_t remAABB = aabbSz; - if (remAABB >= 24) + /* Surface index */ { - aabb[0] = reader.readVec3fBig(); - aabb[1] = reader.readVec3fBig(); - remAABB -= 24; + secsOut.emplace_back((surfEndOffs.size() + 1) * 4, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + w.writeUint32Big(surfEndOffs.size()); + for (size_t off : surfEndOffs) + w.writeUint32Big(off); } - reader.seek(remAABB, athena::Current); - /* unk3 */ - unk3 = reader.readUByte(); - /* align */ - reader.seekAlign32(); + + /* Surfaces */ + for (const hecl::blender::HMDLBuffers::Surface& surf : bufs.m_surfaces) { + const Mesh::Surface& osurf = surf.m_origSurf; + + SurfaceHeader header; + header.centroid = meshXf * zeus::CVector3f(osurf.centroid); + header.matIdx = *matIt++; + header.reflectionNormal = (meshXf.basis * zeus::CVector3f(osurf.reflectionNormal)).normalized(); + header.idxStart = surf.m_start; + header.idxCount = surf.m_count; + header.skinMtxBankIdx = osurf.skinBankIdx; + + header.aabbSz = 24; + zeus::CAABox aabb(zeus::CVector3f(surf.m_origSurf.aabbMin), zeus::CVector3f(surf.m_origSurf.aabbMax)); + aabb = aabb.getTransformedAABox(meshXf); + header.aabb[0] = aabb.min; + header.aabb[1] = aabb.max; + + size_t secSz = 0; + header.binarySize(secSz); + secsOut.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secsOut.back().data(), secsOut.back().size()); + header.write(w); + } + } + + return true; +} + +template bool WriteHMDLMREASecs( + std::vector>& secsOut, const hecl::ProjectPath& inPath, const std::vector& meshes, + zeus::CAABox& fullAABB, std::vector& meshAABBs); + +template <> +void SurfaceHeader_1::Enumerate(typename Read::StreamT& reader) { + /* centroid */ + centroid = reader.readVec3fBig(); + /* matIdx */ + matIdx = reader.readUint32Big(); + /* dlSize */ + dlSize = reader.readUint32Big(); + /* idxStart */ + idxStart = reader.readUint32Big(); + /* idxCount */ + idxCount = reader.readUint32Big(); + /* aabbSz */ + aabbSz = reader.readUint32Big(); + /* reflectionNormal */ + reflectionNormal = reader.readVec3fBig(); + /* aabb */ + size_t remAABB = aabbSz; + if (remAABB >= 24) { + aabb[0] = reader.readVec3fBig(); + aabb[1] = reader.readVec3fBig(); + remAABB -= 24; + } + reader.seek(remAABB, athena::Current); + /* align */ + reader.seekAlign32(); } template <> -void SurfaceHeader_3::Enumerate(typename Write::StreamT& writer) -{ - /* centroid */ - writer.writeVec3fBig(centroid); - /* matIdx */ - writer.writeUint32Big(matIdx); - /* dlSize */ - writer.writeUint32Big(dlSize); - /* idxStart */ - writer.writeUint32Big(idxStart); - /* idxCount */ - writer.writeUint32Big(idxCount); - /* aabbSz */ - writer.writeUint32Big(aabbSz ? 24 : 0); - /* reflectionNormal */ - writer.writeVec3fBig(reflectionNormal); - /* skinMtxBankIdx */ - writer.writeInt16Big(skinMtxBankIdx); - /* surfaceGroup */ - writer.writeUint16Big(surfaceGroup); - /* aabb */ - if (aabbSz) - { - writer.writeVec3fBig(aabb[0]); - writer.writeVec3fBig(aabb[1]); - } - /* unk3 */ - writer.writeUByte(unk3); - /* align */ - writer.seekAlign32(); +void SurfaceHeader_1::Enumerate(typename Write::StreamT& writer) { + /* centroid */ + writer.writeVec3fBig(centroid); + /* matIdx */ + writer.writeUint32Big(matIdx); + /* dlSize */ + writer.writeUint32Big(dlSize); + /* idxStart */ + writer.writeUint32Big(idxStart); + /* idxCount */ + writer.writeUint32Big(idxCount); + /* aabbSz */ + writer.writeUint32Big(aabbSz ? 24 : 0); + /* reflectionNormal */ + writer.writeVec3fBig(reflectionNormal); + /* aabb */ + if (aabbSz) { + writer.writeVec3fBig(aabb[0]); + writer.writeVec3fBig(aabb[1]); + } + /* align */ + writer.seekAlign32(); } template <> -void SurfaceHeader_3::Enumerate(typename BinarySize::StreamT& s) -{ - s += (aabbSz ? 24 : 0); - s += 49; - s = (s + 31) & ~31; +void SurfaceHeader_1::Enumerate(typename BinarySize::StreamT& s) { + s += (aabbSz ? 24 : 0); + s += 44; + s = (s + 31) & ~31; } +template <> +void SurfaceHeader_2::Enumerate(typename Read::StreamT& reader) { + /* centroid */ + centroid = reader.readVec3fBig(); + /* matIdx */ + matIdx = reader.readUint32Big(); + /* dlSize */ + dlSize = reader.readUint32Big(); + /* idxStart */ + idxStart = reader.readUint32Big(); + /* idxCount */ + idxCount = reader.readUint32Big(); + /* aabbSz */ + aabbSz = reader.readUint32Big(); + /* reflectionNormal */ + reflectionNormal = reader.readVec3fBig(); + /* skinMtxBankIdx */ + skinMtxBankIdx = reader.readInt16Big(); + /* surfaceGroup */ + surfaceGroup = reader.readUint16Big(); + /* aabb */ + size_t remAABB = aabbSz; + if (remAABB >= 24) { + aabb[0] = reader.readVec3fBig(); + aabb[1] = reader.readVec3fBig(); + remAABB -= 24; + } + reader.seek(remAABB, athena::Current); + /* align */ + reader.seekAlign32(); } + +template <> +void SurfaceHeader_2::Enumerate(typename Write::StreamT& writer) { + /* centroid */ + writer.writeVec3fBig(centroid); + /* matIdx */ + writer.writeUint32Big(matIdx); + /* dlSize */ + writer.writeUint32Big(dlSize); + /* idxStart */ + writer.writeUint32Big(idxStart); + /* idxCount */ + writer.writeUint32Big(idxCount); + /* aabbSz */ + writer.writeUint32Big(aabbSz ? 24 : 0); + /* reflectionNormal */ + writer.writeVec3fBig(reflectionNormal); + /* skinMtxBankIdx */ + writer.writeInt16Big(skinMtxBankIdx); + /* surfaceGroup */ + writer.writeUint16Big(surfaceGroup); + /* aabb */ + if (aabbSz) { + writer.writeVec3fBig(aabb[0]); + writer.writeVec3fBig(aabb[1]); + } + /* align */ + writer.seekAlign32(); +} + +template <> +void SurfaceHeader_2::Enumerate(typename BinarySize::StreamT& s) { + s += (aabbSz ? 24 : 0); + s += 48; + s = (s + 31) & ~31; +} + +template <> +void SurfaceHeader_3::Enumerate(typename Read::StreamT& reader) { + /* centroid */ + centroid = reader.readVec3fBig(); + /* matIdx */ + matIdx = reader.readUint32Big(); + /* dlSize */ + dlSize = reader.readUint32Big(); + /* idxStart */ + idxStart = reader.readUint32Big(); + /* idxCount */ + idxCount = reader.readUint32Big(); + /* aabbSz */ + aabbSz = reader.readUint32Big(); + /* reflectionNormal */ + reflectionNormal = reader.readVec3fBig(); + /* skinMtxBankIdx */ + skinMtxBankIdx = reader.readInt16Big(); + /* surfaceGroup */ + surfaceGroup = reader.readUint16Big(); + /* aabb */ + size_t remAABB = aabbSz; + if (remAABB >= 24) { + aabb[0] = reader.readVec3fBig(); + aabb[1] = reader.readVec3fBig(); + remAABB -= 24; + } + reader.seek(remAABB, athena::Current); + /* unk3 */ + unk3 = reader.readUByte(); + /* align */ + reader.seekAlign32(); +} + +template <> +void SurfaceHeader_3::Enumerate(typename Write::StreamT& writer) { + /* centroid */ + writer.writeVec3fBig(centroid); + /* matIdx */ + writer.writeUint32Big(matIdx); + /* dlSize */ + writer.writeUint32Big(dlSize); + /* idxStart */ + writer.writeUint32Big(idxStart); + /* idxCount */ + writer.writeUint32Big(idxCount); + /* aabbSz */ + writer.writeUint32Big(aabbSz ? 24 : 0); + /* reflectionNormal */ + writer.writeVec3fBig(reflectionNormal); + /* skinMtxBankIdx */ + writer.writeInt16Big(skinMtxBankIdx); + /* surfaceGroup */ + writer.writeUint16Big(surfaceGroup); + /* aabb */ + if (aabbSz) { + writer.writeVec3fBig(aabb[0]); + writer.writeVec3fBig(aabb[1]); + } + /* unk3 */ + writer.writeUByte(unk3); + /* align */ + writer.seekAlign32(); +} + +template <> +void SurfaceHeader_3::Enumerate(typename BinarySize::StreamT& s) { + s += (aabbSz ? 24 : 0); + s += 49; + s = (s + 31) & ~31; +} + +} // namespace DataSpec::DNACMDL diff --git a/DataSpec/DNACommon/CMDL.hpp b/DataSpec/DNACommon/CMDL.hpp index fa5a43af7..54513bd33 100644 --- a/DataSpec/DNACommon/CMDL.hpp +++ b/DataSpec/DNACommon/CMDL.hpp @@ -8,165 +8,144 @@ #include "TXTR.hpp" #include "zeus/CAABox.hpp" -namespace DataSpec::DNACMDL -{ +namespace DataSpec::DNACMDL { using Mesh = hecl::blender::Mesh; using Material = hecl::blender::Material; -struct Header : BigDNA -{ +struct Header : BigDNA { + AT_DECL_DNA + Value magic; + Value version; + struct Flags : BigDNA { AT_DECL_DNA - Value magic; - Value version; - struct Flags : BigDNA - { - AT_DECL_DNA - Value flags = 0; - bool skinned() const {return (flags & 0x1) != 0;} - void setSkinned(bool val) {flags &= ~0x1; flags |= val;} - bool shortNormals() const {return (flags & 0x2) != 0;} - void setShortNormals(bool val) {flags &= ~0x2; flags |= val << 1;} - bool shortUVs() const {return (flags & 0x4) != 0;} - void setShortUVs(bool val) {flags &= ~0x4; flags |= val << 2;} - } flags; - Value aabbMin; - Value aabbMax; - Value secCount; - Value matSetCount; - Vector secSizes; - Align<32> align; + Value flags = 0; + bool skinned() const { return (flags & 0x1) != 0; } + void setSkinned(bool val) { + flags &= ~0x1; + flags |= val; + } + bool shortNormals() const { return (flags & 0x2) != 0; } + void setShortNormals(bool val) { + flags &= ~0x2; + flags |= val << 1; + } + bool shortUVs() const { return (flags & 0x4) != 0; } + void setShortUVs(bool val) { + flags &= ~0x4; + flags |= val << 2; + } + } flags; + Value aabbMin; + Value aabbMax; + Value secCount; + Value matSetCount; + Vector secSizes; + Align<32> align; }; -struct SurfaceHeader_1 : BigDNA -{ - AT_DECL_EXPLICIT_DNA - Value centroid; - Value matIdx = 0; - Value dlSize = 0; - Value idxStart = 0; /* Actually used by game to stash CCubeModel pointer */ - Value idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */ - Value aabbSz = 0; - Value reflectionNormal; - Value aabb[2]; - Align<32> align; +struct SurfaceHeader_1 : BigDNA { + AT_DECL_EXPLICIT_DNA + Value centroid; + Value matIdx = 0; + Value dlSize = 0; + Value idxStart = 0; /* Actually used by game to stash CCubeModel pointer */ + Value idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */ + Value aabbSz = 0; + Value reflectionNormal; + Value aabb[2]; + Align<32> align; - static constexpr bool UseMatrixSkinning() {return false;} - static constexpr atInt16 skinMatrixBankIdx() {return -1;} + static constexpr bool UseMatrixSkinning() { return false; } + static constexpr atInt16 skinMatrixBankIdx() { return -1; } }; -struct SurfaceHeader_2 : BigDNA -{ - AT_DECL_EXPLICIT_DNA - Value centroid; - Value matIdx = 0; - Value dlSize = 0; - Value idxStart = 0; /* Actually used by game to stash CCubeModel pointer */ - Value idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */ - Value aabbSz = 0; - Value reflectionNormal; - Value skinMtxBankIdx; - Value surfaceGroup; - Value aabb[2]; - Align<32> align; +struct SurfaceHeader_2 : BigDNA { + AT_DECL_EXPLICIT_DNA + Value centroid; + Value matIdx = 0; + Value dlSize = 0; + Value idxStart = 0; /* Actually used by game to stash CCubeModel pointer */ + Value idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */ + Value aabbSz = 0; + Value reflectionNormal; + Value skinMtxBankIdx; + Value surfaceGroup; + Value aabb[2]; + Align<32> align; - static constexpr bool UseMatrixSkinning() {return false;} - atInt16 skinMatrixBankIdx() const {return skinMtxBankIdx;} + static constexpr bool UseMatrixSkinning() { return false; } + atInt16 skinMatrixBankIdx() const { return skinMtxBankIdx; } }; -struct SurfaceHeader_3 : BigDNA -{ - AT_DECL_EXPLICIT_DNA - Value centroid; - Value matIdx = 0; - Value dlSize = 0; - Value idxStart = 0; /* Actually used by game to stash CCubeModel pointer */ - Value idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */ - Value aabbSz = 0; - Value reflectionNormal; - Value skinMtxBankIdx; - Value surfaceGroup; - Value aabb[2]; - Value unk3; - Align<32> align; +struct SurfaceHeader_3 : BigDNA { + AT_DECL_EXPLICIT_DNA + Value centroid; + Value matIdx = 0; + Value dlSize = 0; + Value idxStart = 0; /* Actually used by game to stash CCubeModel pointer */ + Value idxCount = 0; /* Actually used by game to stash next CCubeSurface pointer */ + Value aabbSz = 0; + Value reflectionNormal; + Value skinMtxBankIdx; + Value surfaceGroup; + Value aabb[2]; + Value unk3; + Align<32> align; - static constexpr bool UseMatrixSkinning() {return true;} - atInt16 skinMatrixBankIdx() const {return skinMtxBankIdx;} + static constexpr bool UseMatrixSkinning() { return true; } + atInt16 skinMatrixBankIdx() const { return skinMtxBankIdx; } }; -struct VertexAttributes -{ - GX::AttrType pos = GX::NONE; - GX::AttrType norm = GX::NONE; - GX::AttrType color0 = GX::NONE; - GX::AttrType color1 = GX::NONE; - unsigned uvCount = 0; - GX::AttrType uvs[7] = {GX::NONE}; - GX::AttrType pnMtxIdx = GX::NONE; - unsigned texMtxIdxCount = 0; - GX::AttrType texMtxIdx[7] = {GX::NONE}; - bool shortUVs; +struct VertexAttributes { + GX::AttrType pos = GX::NONE; + GX::AttrType norm = GX::NONE; + GX::AttrType color0 = GX::NONE; + GX::AttrType color1 = GX::NONE; + unsigned uvCount = 0; + GX::AttrType uvs[7] = {GX::NONE}; + GX::AttrType pnMtxIdx = GX::NONE; + unsigned texMtxIdxCount = 0; + GX::AttrType texMtxIdx[7] = {GX::NONE}; + bool shortUVs; }; template -void GetVertexAttributes(const MaterialSet& matSet, - std::vector& attributesOut); +void GetVertexAttributes(const MaterialSet& matSet, std::vector& attributesOut); template -void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, - const MaterialSet& matSet, - const PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - unsigned setIdx); +void ReadMaterialSetToBlender_1_2(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, unsigned setIdx); template -void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os, - const MaterialSet& matSet, - const PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - unsigned setIdx); +void ReadMaterialSetToBlender_3(hecl::blender::PyOutStream& os, const MaterialSet& matSet, const PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, unsigned setIdx); -void InitGeomBlenderContext(hecl::blender::PyOutStream& os, - const hecl::ProjectPath& masterShaderPath, +void InitGeomBlenderContext(hecl::blender::PyOutStream& os, const hecl::ProjectPath& masterShaderPath, bool solidShading); -void FinishBlenderMesh(hecl::blender::PyOutStream& os, - unsigned matSetCount, int meshIdx); +void FinishBlenderMesh(hecl::blender::PyOutStream& os, unsigned matSetCount, int meshIdx); template -atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, - athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - const RigPair& rp, - bool shortNormals, - bool shortUVs, - std::vector& vertAttribs, - int meshIdx, - atUint32 secCount, - atUint32 matSetCount, - const atUint32* secSizes, - atUint32 surfaceCount=0); +atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os, athena::io::IStreamReader& reader, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, const RigPair& rp, + bool shortNormals, bool shortUVs, std::vector& vertAttribs, + int meshIdx, atUint32 secCount, atUint32 matSetCount, const atUint32* secSizes, + atUint32 surfaceCount = 0); template -bool ReadCMDLToBlender(hecl::blender::Connection& conn, - athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - const SpecBase& dataspec, - const RigPair& rp); +bool ReadCMDLToBlender(hecl::blender::Connection& conn, athena::io::IStreamReader& reader, PAKRouter& pakRouter, + const typename PAKRouter::EntryType& entry, const SpecBase& dataspec, const RigPair& rp); template -void NameCMDL(athena::io::IStreamReader& reader, - PAKRouter& pakRouter, - typename PAKRouter::EntryType& entry, +void NameCMDL(athena::io::IStreamReader& reader, PAKRouter& pakRouter, typename PAKRouter::EntryType& entry, const SpecBase& dataspec); template bool WriteCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh); template -bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, - const Mesh& mesh, hecl::blender::PoolSkinIndex& poolSkinIndex); +bool WriteHMDLCMDL(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const Mesh& mesh, + hecl::blender::PoolSkinIndex& poolSkinIndex); template bool WriteMREASecs(std::vector>& secsOut, const hecl::ProjectPath& inPath, @@ -176,5 +155,4 @@ template bool WriteHMDLMREASecs(std::vector>& secsOut, const hecl::ProjectPath& inPath, const std::vector& meshes, zeus::CAABox& fullAABB, std::vector& meshAABBs); -} - +} // namespace DataSpec::DNACMDL diff --git a/DataSpec/DNACommon/CRSC.cpp b/DataSpec/DNACommon/CRSC.cpp index 2bce30521..bdbffc362 100644 --- a/DataSpec/DNACommon/CRSC.cpp +++ b/DataSpec/DNACommon/CRSC.cpp @@ -1,341 +1,268 @@ #include "CRSC.hpp" -namespace DataSpec::DNAParticle -{ -static const std::vector GeneratorTypes = -{ - SBIG('NODP'),SBIG('DEFS'),SBIG('CRTS'),SBIG('MTLS'), - SBIG('GRAS'),SBIG('ICEE'),SBIG('GOOO'),SBIG('WODS'), - SBIG('WATR'),SBIG('1MUD'),SBIG('1LAV'),SBIG('1SAN'), - SBIG('1PRJ'),SBIG('DCHR'),SBIG('DCHS'),SBIG('DCSH'), - SBIG('DENM'),SBIG('DESP'),SBIG('DESH'),SBIG('BTLE'), - SBIG('WASP'),SBIG('TALP'),SBIG('PTGM'),SBIG('SPIR'), - SBIG('FPIR'),SBIG('FFLE'),SBIG('PARA'),SBIG('BMON'), - SBIG('BFLR'),SBIG('PBOS'),SBIG('IBOS'),SBIG('1SVA'), - SBIG('1RPR'),SBIG('1MTR'),SBIG('1PDS'),SBIG('1FLB'), - SBIG('1DRN'),SBIG('1MRE'),SBIG('CHOZ'),SBIG('JZAP'), - SBIG('1ISE'),SBIG('1BSE'),SBIG('1ATB'),SBIG('1ATA'), - SBIG('BTSP'),SBIG('WWSP'),SBIG('TASP'),SBIG('TGSP'), - SBIG('SPSP'),SBIG('FPSP'),SBIG('FFSP'),SBIG('PSSP'), - SBIG('BMSP'),SBIG('BFSP'),SBIG('PBSP'),SBIG('IBSP'), - SBIG('2SVA'),SBIG('2RPR'),SBIG('2MTR'),SBIG('2PDS'), - SBIG('2FLB'),SBIG('2DRN'),SBIG('2MRE'),SBIG('CHSP'), - SBIG('JZSP'),SBIG('3ISE'),SBIG('3BSE'),SBIG('3ATB'), - SBIG('3ATA'),SBIG('BTSH'),SBIG('WWSH'),SBIG('TASH'), - SBIG('TGSH'),SBIG('SPSH'),SBIG('FPSH'),SBIG('FFSH'), - SBIG('PSSH'),SBIG('BMSH'),SBIG('BFSH'),SBIG('PBSH'), - SBIG('IBSH'),SBIG('3SVA'),SBIG('3RPR'),SBIG('3MTR'), - SBIG('3PDS'),SBIG('3FLB'),SBIG('3DRN'),SBIG('3MRE'), - SBIG('CHSH'),SBIG('JZSH'),SBIG('5ISE'),SBIG('5BSE'), - SBIG('5ATB'),SBIG('5ATA') +namespace DataSpec::DNAParticle { +static const std::vector GeneratorTypes = { + SBIG('NODP'), SBIG('DEFS'), SBIG('CRTS'), SBIG('MTLS'), SBIG('GRAS'), SBIG('ICEE'), SBIG('GOOO'), SBIG('WODS'), + SBIG('WATR'), SBIG('1MUD'), SBIG('1LAV'), SBIG('1SAN'), SBIG('1PRJ'), SBIG('DCHR'), SBIG('DCHS'), SBIG('DCSH'), + SBIG('DENM'), SBIG('DESP'), SBIG('DESH'), SBIG('BTLE'), SBIG('WASP'), SBIG('TALP'), SBIG('PTGM'), SBIG('SPIR'), + SBIG('FPIR'), SBIG('FFLE'), SBIG('PARA'), SBIG('BMON'), SBIG('BFLR'), SBIG('PBOS'), SBIG('IBOS'), SBIG('1SVA'), + SBIG('1RPR'), SBIG('1MTR'), SBIG('1PDS'), SBIG('1FLB'), SBIG('1DRN'), SBIG('1MRE'), SBIG('CHOZ'), SBIG('JZAP'), + SBIG('1ISE'), SBIG('1BSE'), SBIG('1ATB'), SBIG('1ATA'), SBIG('BTSP'), SBIG('WWSP'), SBIG('TASP'), SBIG('TGSP'), + SBIG('SPSP'), SBIG('FPSP'), SBIG('FFSP'), SBIG('PSSP'), SBIG('BMSP'), SBIG('BFSP'), SBIG('PBSP'), SBIG('IBSP'), + SBIG('2SVA'), SBIG('2RPR'), SBIG('2MTR'), SBIG('2PDS'), SBIG('2FLB'), SBIG('2DRN'), SBIG('2MRE'), SBIG('CHSP'), + SBIG('JZSP'), SBIG('3ISE'), SBIG('3BSE'), SBIG('3ATB'), SBIG('3ATA'), SBIG('BTSH'), SBIG('WWSH'), SBIG('TASH'), + SBIG('TGSH'), SBIG('SPSH'), SBIG('FPSH'), SBIG('FFSH'), SBIG('PSSH'), SBIG('BMSH'), SBIG('BFSH'), SBIG('PBSH'), + SBIG('IBSH'), SBIG('3SVA'), SBIG('3RPR'), SBIG('3MTR'), SBIG('3PDS'), SBIG('3FLB'), SBIG('3DRN'), SBIG('3MRE'), + SBIG('CHSH'), SBIG('JZSH'), SBIG('5ISE'), SBIG('5BSE'), SBIG('5ATB'), SBIG('5ATA')}; + +static const std::vector SFXTypes = { + SBIG('DSFX'), SBIG('CSFX'), SBIG('MSFX'), SBIG('GRFX'), SBIG('NSFX'), SBIG('DSFX'), SBIG('CSFX'), SBIG('MSFX'), + SBIG('GRFX'), SBIG('ICFX'), SBIG('GOFX'), SBIG('WSFX'), SBIG('WTFX'), SBIG('2MUD'), SBIG('2LAV'), SBIG('2SAN'), + SBIG('2PRJ'), SBIG('DCFX'), SBIG('DSFX'), SBIG('DSHX'), SBIG('DEFX'), SBIG('ESFX'), SBIG('SHFX'), SBIG('BEFX'), + SBIG('WWFX'), SBIG('TAFX'), SBIG('GTFX'), SBIG('SPFX'), SBIG('FPFX'), SBIG('FFFX'), SBIG('PAFX'), SBIG('BMFX'), + SBIG('BFFX'), SBIG('PBFX'), SBIG('IBFX'), SBIG('4SVA'), SBIG('4RPR'), SBIG('4MTR'), SBIG('4PDS'), SBIG('4FLB'), + SBIG('4DRN'), SBIG('4MRE'), SBIG('CZFX'), SBIG('JZAS'), SBIG('2ISE'), SBIG('2BSE'), SBIG('2ATB'), SBIG('2ATA'), + SBIG('BSFX'), SBIG('WSFX'), SBIG('TSFX'), SBIG('GSFX'), SBIG('SSFX'), SBIG('FSFX'), SBIG('SFFX'), SBIG('PSFX'), + SBIG('MSFX'), SBIG('SBFX'), SBIG('PBSX'), SBIG('IBSX'), SBIG('5SVA'), SBIG('5RPR'), SBIG('5MTR'), SBIG('5PDS'), + SBIG('5FLB'), SBIG('5DRN'), SBIG('5MRE'), SBIG('CSFX'), SBIG('JZPS'), SBIG('4ISE'), SBIG('4BSE'), SBIG('4ATB'), + SBIG('4ATA'), SBIG('BHFX'), SBIG('WHFX'), SBIG('THFX'), SBIG('GHFX'), SBIG('SHFX'), SBIG('FHFX'), SBIG('HFFX'), + SBIG('PHFX'), SBIG('MHFX'), SBIG('HBFX'), SBIG('PBHX'), SBIG('IBHX'), SBIG('6SVA'), SBIG('6RPR'), SBIG('6MTR'), + SBIG('6PDS'), SBIG('6FLB'), SBIG('6DRN'), SBIG('6MRE'), SBIG('CHFX'), SBIG('JZHS'), SBIG('6ISE'), SBIG('6BSE'), + SBIG('6ATB'), SBIG('6ATA'), }; -static const std::vector SFXTypes = -{ - SBIG('DSFX'),SBIG('CSFX'),SBIG('MSFX'),SBIG('GRFX'), - SBIG('NSFX'),SBIG('DSFX'),SBIG('CSFX'),SBIG('MSFX'), - SBIG('GRFX'),SBIG('ICFX'),SBIG('GOFX'),SBIG('WSFX'), - SBIG('WTFX'),SBIG('2MUD'),SBIG('2LAV'),SBIG('2SAN'), - SBIG('2PRJ'),SBIG('DCFX'),SBIG('DSFX'),SBIG('DSHX'), - SBIG('DEFX'),SBIG('ESFX'),SBIG('SHFX'),SBIG('BEFX'), - SBIG('WWFX'),SBIG('TAFX'),SBIG('GTFX'),SBIG('SPFX'), - SBIG('FPFX'),SBIG('FFFX'),SBIG('PAFX'),SBIG('BMFX'), - SBIG('BFFX'),SBIG('PBFX'),SBIG('IBFX'),SBIG('4SVA'), - SBIG('4RPR'),SBIG('4MTR'),SBIG('4PDS'),SBIG('4FLB'), - SBIG('4DRN'),SBIG('4MRE'),SBIG('CZFX'),SBIG('JZAS'), - SBIG('2ISE'),SBIG('2BSE'),SBIG('2ATB'),SBIG('2ATA'), - SBIG('BSFX'),SBIG('WSFX'),SBIG('TSFX'),SBIG('GSFX'), - SBIG('SSFX'),SBIG('FSFX'),SBIG('SFFX'),SBIG('PSFX'), - SBIG('MSFX'),SBIG('SBFX'),SBIG('PBSX'),SBIG('IBSX'), - SBIG('5SVA'),SBIG('5RPR'),SBIG('5MTR'),SBIG('5PDS'), - SBIG('5FLB'),SBIG('5DRN'),SBIG('5MRE'),SBIG('CSFX'), - SBIG('JZPS'),SBIG('4ISE'),SBIG('4BSE'),SBIG('4ATB'), - SBIG('4ATA'),SBIG('BHFX'),SBIG('WHFX'),SBIG('THFX'), - SBIG('GHFX'),SBIG('SHFX'),SBIG('FHFX'),SBIG('HFFX'), - SBIG('PHFX'),SBIG('MHFX'),SBIG('HBFX'),SBIG('PBHX'), - SBIG('IBHX'),SBIG('6SVA'),SBIG('6RPR'),SBIG('6MTR'), - SBIG('6PDS'),SBIG('6FLB'),SBIG('6DRN'),SBIG('6MRE'), - SBIG('CHFX'),SBIG('JZHS'),SBIG('6ISE'),SBIG('6BSE'), - SBIG('6ATB'),SBIG('6ATA'), -}; - -static const std::vector DecalTypes = -{ - SBIG('NCDL'),SBIG('DDCL'),SBIG('CODL'),SBIG('MEDL'), - SBIG('GRDL'),SBIG('ICDL'),SBIG('GODL'),SBIG('WODL'), - SBIG('WTDL'),SBIG('3MUD'),SBIG('3LAV'),SBIG('3SAN'), - SBIG('CHDL'),SBIG('ENDL') -}; +static const std::vector DecalTypes = {SBIG('NCDL'), SBIG('DDCL'), SBIG('CODL'), SBIG('MEDL'), SBIG('GRDL'), + SBIG('ICDL'), SBIG('GODL'), SBIG('WODL'), SBIG('WTDL'), SBIG('3MUD'), + SBIG('3LAV'), SBIG('3SAN'), SBIG('CHDL'), SBIG('ENDL')}; template <> -const char* CRSM::DNAType() { return "CRSM"; } +const char* CRSM::DNAType() { + return "CRSM"; +} template <> -const char* CRSM::DNAType() { return "CRSM"; } - -template -void CRSM::_read(athena::io::YAMLDocReader& r) -{ - for (const auto& elem : r.getCurNode()->m_mapChildren) - { - if (elem.first.size() < 4) - { - LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); - continue; - } - - if (auto rec = r.enterSubRecord(elem.first.c_str())) - { - FourCC clsId(elem.first.c_str()); - auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(), [&clsId](const FourCC& other) -> bool{ - return clsId == other; - }); - if (gen != GeneratorTypes.end()) - { - x0_generators[clsId].read(r); - continue; - } - - auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(), [&clsId](const FourCC& other) -> bool{ - return clsId == other; - }); - if (sfx != SFXTypes.end()) - { - x10_sfx[clsId] = r.readInt32(clsId.toString().c_str()); - continue; - } - - auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(), [&clsId](const FourCC& other) -> bool{ - return clsId == other; - }); - if (decal != DecalTypes.end()) - { - x20_decals[clsId].read(r); - continue; - } - if (clsId == SBIG('RNGE')) - x30_RNGE = r.readFloat(nullptr); - else if (clsId == SBIG('FOFF')) - x34_FOFF = r.readFloat(nullptr); - } - } +const char* CRSM::DNAType() { + return "CRSM"; } template -void CRSM::_write(athena::io::YAMLDocWriter& w) const -{ - for (const auto& pair : x0_generators) - if (pair.second) - if (auto rec = w.enterSubRecord(pair.first.toString().c_str())) - pair.second.write(w); +void CRSM::_read(athena::io::YAMLDocReader& r) { + for (const auto& elem : r.getCurNode()->m_mapChildren) { + if (elem.first.size() < 4) { + LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); + continue; + } - for (const auto& pair : x10_sfx) - if (pair.second != ~0) - w.writeUint32(pair.first.toString().c_str(), pair.second); + if (auto rec = r.enterSubRecord(elem.first.c_str())) { + FourCC clsId(elem.first.c_str()); + auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(), + [&clsId](const FourCC& other) -> bool { return clsId == other; }); + if (gen != GeneratorTypes.end()) { + x0_generators[clsId].read(r); + continue; + } - for (const auto& pair : x20_decals) - if (pair.second) - if (auto rec = w.enterSubRecord(pair.first.toString().c_str())) - pair.second.write(w); + auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(), + [&clsId](const FourCC& other) -> bool { return clsId == other; }); + if (sfx != SFXTypes.end()) { + x10_sfx[clsId] = r.readInt32(clsId.toString().c_str()); + continue; + } - if (x30_RNGE != 50.f) - w.writeFloat("RNGE", x30_RNGE); - if (x34_FOFF != 0.2f) - w.writeFloat("FOFF", x34_FOFF); + auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(), + [&clsId](const FourCC& other) -> bool { return clsId == other; }); + if (decal != DecalTypes.end()) { + x20_decals[clsId].read(r); + continue; + } + if (clsId == SBIG('RNGE')) + x30_RNGE = r.readFloat(nullptr); + else if (clsId == SBIG('FOFF')) + x34_FOFF = r.readFloat(nullptr); + } + } } template -void CRSM::_binarySize(size_t& __isz) const -{ - __isz += 4; - for (const auto& pair : x0_generators) - { - if (pair.second) - { - __isz += 4; - pair.second.binarySize(__isz); - } - } - for (const auto& pair : x10_sfx) - { - if (pair.second != ~0) - __isz += 12; - } +void CRSM::_write(athena::io::YAMLDocWriter& w) const { + for (const auto& pair : x0_generators) + if (pair.second) + if (auto rec = w.enterSubRecord(pair.first.toString().c_str())) + pair.second.write(w); - for (const auto& pair : x20_decals) - { - if (pair.second) - { - __isz += 4; - pair.second.binarySize(__isz); - } - } + for (const auto& pair : x10_sfx) + if (pair.second != ~0) + w.writeUint32(pair.first.toString().c_str(), pair.second); - if (x30_RNGE != 50.f) - __isz += 12; - if (x34_FOFF != 0.2f) - __isz += 12; + for (const auto& pair : x20_decals) + if (pair.second) + if (auto rec = w.enterSubRecord(pair.first.toString().c_str())) + pair.second.write(w); + + if (x30_RNGE != 50.f) + w.writeFloat("RNGE", x30_RNGE); + if (x34_FOFF != 0.2f) + w.writeFloat("FOFF", x34_FOFF); } template -void CRSM::_read(athena::io::IStreamReader &r) -{ - uint32_t clsId; +void CRSM::_binarySize(size_t& __isz) const { + __isz += 4; + for (const auto& pair : x0_generators) { + if (pair.second) { + __isz += 4; + pair.second.binarySize(__isz); + } + } + for (const auto& pair : x10_sfx) { + if (pair.second != ~0) + __isz += 12; + } + + for (const auto& pair : x20_decals) { + if (pair.second) { + __isz += 4; + pair.second.binarySize(__isz); + } + } + + if (x30_RNGE != 50.f) + __isz += 12; + if (x34_FOFF != 0.2f) + __isz += 12; +} + +template +void CRSM::_read(athena::io::IStreamReader& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId != SBIG('CRSM')) { + LogModule.report(logvisor::Warning, "non CRSM provided to CRSM parser"); + return; + } + + while (clsId != SBIG('_END')) { r.readBytesToBuf(&clsId, 4); - if (clsId != SBIG('CRSM')) - { - LogModule.report(logvisor::Warning, "non CRSM provided to CRSM parser"); - return; + auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(), + [&clsId](const FourCC& other) -> bool { return clsId == other; }); + if (gen != GeneratorTypes.end()) { + x0_generators[clsId].read(r); + continue; } - while (clsId != SBIG('_END')) - { - r.readBytesToBuf(&clsId, 4); - auto gen = std::find_if(GeneratorTypes.begin(), GeneratorTypes.end(), [&clsId](const FourCC& other) -> bool{ - return clsId == other; - }); - if (gen != GeneratorTypes.end()) - { - x0_generators[clsId].read(r); - continue; - } - - auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(), [&clsId](const FourCC& other) -> bool{ - return clsId == other; - }); - if (sfx != SFXTypes.end()) - { - uint32_t fcc; - r.readBytesToBuf(&fcc, 4); - if (fcc != SBIG('NONE')) - x10_sfx[clsId] = r.readInt32Big(); - else - x10_sfx[clsId] = ~0; - continue; - } - - auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(), [&clsId](const FourCC& other) -> bool{ - return clsId == other; - }); - if (decal != DecalTypes.end()) - { - x20_decals[clsId].read(r); - continue; - } - if (clsId == SBIG('RNGE')) - { - r.readUint32(); - x30_RNGE = r.readFloatBig(); - continue; - } - if (clsId == SBIG('FOFF')) - { - r.readUint32(); - x34_FOFF = r.readFloatBig(); - continue; - } - if (clsId != SBIG('_END')) - LogModule.report(logvisor::Fatal, "Unknown CRSM class %.4s @%" PRIi64, &clsId, r.position()); + auto sfx = std::find_if(SFXTypes.begin(), SFXTypes.end(), + [&clsId](const FourCC& other) -> bool { return clsId == other; }); + if (sfx != SFXTypes.end()) { + uint32_t fcc; + r.readBytesToBuf(&fcc, 4); + if (fcc != SBIG('NONE')) + x10_sfx[clsId] = r.readInt32Big(); + else + x10_sfx[clsId] = ~0; + continue; } + + auto decal = std::find_if(DecalTypes.begin(), DecalTypes.end(), + [&clsId](const FourCC& other) -> bool { return clsId == other; }); + if (decal != DecalTypes.end()) { + x20_decals[clsId].read(r); + continue; + } + if (clsId == SBIG('RNGE')) { + r.readUint32(); + x30_RNGE = r.readFloatBig(); + continue; + } + if (clsId == SBIG('FOFF')) { + r.readUint32(); + x34_FOFF = r.readFloatBig(); + continue; + } + if (clsId != SBIG('_END')) + LogModule.report(logvisor::Fatal, "Unknown CRSM class %.4s @%" PRIi64, &clsId, r.position()); + } } template -void CRSM::_write(athena::io::IStreamWriter& w) const -{ - w.writeBytes("CRSM", 4); - for (const auto& pair : x0_generators) - { - w.writeBytes(pair.first.getChars(), 4); - pair.second.write(w); - } +void CRSM::_write(athena::io::IStreamWriter& w) const { + w.writeBytes("CRSM", 4); + for (const auto& pair : x0_generators) { + w.writeBytes(pair.first.getChars(), 4); + pair.second.write(w); + } - for (const auto& pair : x10_sfx) - { - w.writeBytes(pair.first.getChars(), 4); - if (pair.second != ~0) - { - w.writeBytes("CNST", 4); - w.writeUint32Big(pair.second); - } - else - { - w.writeBytes("NONE", 4); - } + for (const auto& pair : x10_sfx) { + w.writeBytes(pair.first.getChars(), 4); + if (pair.second != ~0) { + w.writeBytes("CNST", 4); + w.writeUint32Big(pair.second); + } else { + w.writeBytes("NONE", 4); } + } - for (const auto& pair : x20_decals) - { - w.writeBytes(pair.first.getChars(), 4); - pair.second.write(w); - } + for (const auto& pair : x20_decals) { + w.writeBytes(pair.first.getChars(), 4); + pair.second.write(w); + } - if (x30_RNGE != 50.f) - { - w.writeBytes("RNGECNST", 8); - w.writeFloatBig(x30_RNGE); - } - if (x34_FOFF != 0.2f) - { - w.writeBytes("FOFFCNST", 8); - w.writeFloatBig(x34_FOFF); - } - w.writeBytes("_END", 4); + if (x30_RNGE != 50.f) { + w.writeBytes("RNGECNST", 8); + w.writeFloatBig(x30_RNGE); + } + if (x34_FOFF != 0.2f) { + w.writeBytes("FOFFCNST", 8); + w.writeFloatBig(x34_FOFF); + } + w.writeBytes("_END", 4); } AT_SUBSPECIALIZE_DNA_YAML(CRSM) AT_SUBSPECIALIZE_DNA_YAML(CRSM) template -void CRSM::gatherDependencies(std::vector& pathsOut) const -{ - for (const auto& p : x0_generators) - g_curSpec->flattenDependencies(p.second.id, pathsOut); - for (const auto& p : x20_decals) - g_curSpec->flattenDependencies(p.second.id, pathsOut); +void CRSM::gatherDependencies(std::vector& pathsOut) const { + for (const auto& p : x0_generators) + g_curSpec->flattenDependencies(p.second.id, pathsOut); + for (const auto& p : x20_decals) + g_curSpec->flattenDependencies(p.second.id, pathsOut); } template -CRSM::CRSM() - : x30_RNGE(50.f), - x34_FOFF(0.2f) -{ - for (const auto& sfx : SFXTypes) - x10_sfx[sfx] = ~0; +CRSM::CRSM() : x30_RNGE(50.f), x34_FOFF(0.2f) { + for (const auto& sfx : SFXTypes) + x10_sfx[sfx] = ~0; } template struct CRSM; template struct CRSM; template -bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - CRSM crsm; - crsm.read(rs); - athena::io::ToYAMLStream(crsm, writer); - return true; - } - return false; +bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + CRSM crsm; + crsm.read(rs); + athena::io::ToYAMLStream(crsm, writer); + return true; + } + return false; } template bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template -bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - crsm.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; +bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + crsm.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } template bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath); template bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath); -} - +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/CRSC.hpp b/DataSpec/DNACommon/CRSC.hpp index 6c0c7223f..8eb4b4145 100644 --- a/DataSpec/DNACommon/CRSC.hpp +++ b/DataSpec/DNACommon/CRSC.hpp @@ -5,26 +5,24 @@ #include "athena/FileWriter.hpp" #include "optional.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template -struct CRSM : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA - std::unordered_map> x0_generators; - std::unordered_map x10_sfx; - std::unordered_map> x20_decals; - float x30_RNGE; - float x34_FOFF; +struct CRSM : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + std::unordered_map> x0_generators; + std::unordered_map x10_sfx; + std::unordered_map> x20_decals; + float x30_RNGE; + float x34_FOFF; - CRSM(); + CRSM(); - void gatherDependencies(std::vector&) const; + void gatherDependencies(std::vector&) const; }; template bool ExtractCRSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteCRSM(const CRSM& crsm, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/DGRP.cpp b/DataSpec/DNACommon/DGRP.cpp index 55ce858c0..1d14de93c 100644 --- a/DataSpec/DNACommon/DGRP.cpp +++ b/DataSpec/DNACommon/DGRP.cpp @@ -3,39 +3,35 @@ #include "athena/FileWriter.hpp" #include "DGRP.hpp" -namespace DataSpec::DNADGRP -{ +namespace DataSpec::DNADGRP { template -bool ExtractDGRP(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - DGRP dgrp; - dgrp.read(rs); - athena::io::ToYAMLStream(dgrp, writer); - return true; - } - return false; +bool ExtractDGRP(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + DGRP dgrp; + dgrp.read(rs); + athena::io::ToYAMLStream(dgrp, writer); + return true; + } + return false; } template bool ExtractDGRP(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractDGRP(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template -bool WriteDGRP(const DGRP& dgrp, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - dgrp.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; +bool WriteDGRP(const DGRP& dgrp, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + dgrp.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } template bool WriteDGRP(const DGRP& dgrp, const hecl::ProjectPath& outPath); template bool WriteDGRP(const DGRP& dgrp, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNADGRP diff --git a/DataSpec/DNACommon/DGRP.hpp b/DataSpec/DNACommon/DGRP.hpp index 5c3ee9074..394c11a2d 100644 --- a/DataSpec/DNACommon/DGRP.hpp +++ b/DataSpec/DNACommon/DGRP.hpp @@ -3,41 +3,36 @@ #include "DNACommon.hpp" #include "PAK.hpp" -namespace DataSpec::DNADGRP -{ +namespace DataSpec::DNADGRP { template -struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) DGRP : BigDNA -{ +struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) DGRP : BigDNA { + AT_DECL_DNA_YAML + Value dependCount; + struct ObjectTag : BigDNA { AT_DECL_DNA_YAML - Value dependCount; - struct ObjectTag : BigDNA - { - AT_DECL_DNA_YAML - DNAFourCC type; - Value id; + DNAFourCC type; + Value id; - bool validate() const - { - if (!id.operator bool()) - return false; - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); - return path && !path.isNone(); - } - }; - - Vector depends; - - void validateDeps() - { - std::vector newDeps; - newDeps.reserve(depends.size()); - for (const ObjectTag& tag : depends) - if (tag.validate()) - newDeps.push_back(tag); - depends = std::move(newDeps); - dependCount = atUint32(depends.size()); + bool validate() const { + if (!id.operator bool()) + return false; + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); + return path && !path.isNone(); } + }; + + Vector depends; + + void validateDeps() { + std::vector newDeps; + newDeps.reserve(depends.size()); + for (const ObjectTag& tag : depends) + if (tag.validate()) + newDeps.push_back(tag); + depends = std::move(newDeps); + dependCount = atUint32(depends.size()); + } }; template @@ -45,5 +40,4 @@ bool ExtractDGRP(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteDGRP(const DGRP& dgrp, const hecl::ProjectPath& outPath); -} - +} // namespace DataSpec::DNADGRP diff --git a/DataSpec/DNACommon/DNACommon.cpp b/DataSpec/DNACommon/DNACommon.cpp index 07878d4cd..c9b517df0 100644 --- a/DataSpec/DNACommon/DNACommon.cpp +++ b/DataSpec/DNACommon/DNACommon.cpp @@ -2,8 +2,7 @@ #include "PAK.hpp" #include "boo/ThreadLocalPtr.hpp" -namespace DataSpec -{ +namespace DataSpec { logvisor::Module LogDNACommon("urde::DNACommon"); ThreadLocalPtr g_curSpec; @@ -16,305 +15,270 @@ ThreadLocalPtr> UniqueIDBridge::s_restorer128; UniqueID32 UniqueID32::kInvalidId; template -hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const IDType& id, bool silenceWarnings) -{ - /* Try PAKRouter first (only available at extract) */ - PAKRouterBase* pakRouter = g_PakRouter.get(); - if (pakRouter) - { - hecl::ProjectPath path = pakRouter->getWorking(id, silenceWarnings); - if (path) - return path; - } +hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const IDType& id, bool silenceWarnings) { + /* Try PAKRouter first (only available at extract) */ + PAKRouterBase* pakRouter = g_PakRouter.get(); + if (pakRouter) { + hecl::ProjectPath path = pakRouter->getWorking(id, silenceWarnings); + if (path) + return path; + } - /* Try project cache second (populated with paths read from YAML resources) */ - hecl::Database::Project* project = s_Project.get(); - if (!project) - { - if (pakRouter) - { - if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id) - LogDNACommon.report(logvisor::Warning, - "unable to translate %s to path", id.toString().c_str()); - return {}; - } - LogDNACommon.report(logvisor::Fatal, - "g_PakRouter or s_Project must be set to non-null before " - "calling UniqueIDBridge::TranslatePakIdToPath"); - return {}; + /* Try project cache second (populated with paths read from YAML resources) */ + hecl::Database::Project* project = s_Project.get(); + if (!project) { + if (pakRouter) { + if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id) + LogDNACommon.report(logvisor::Warning, "unable to translate %s to path", id.toString().c_str()); + return {}; } + LogDNACommon.report(logvisor::Fatal, + "g_PakRouter or s_Project must be set to non-null before " + "calling UniqueIDBridge::TranslatePakIdToPath"); + return {}; + } - const hecl::ProjectPath* search = project->lookupBridgePath(id.toUint64()); - if (!search) - { - if (IDRestorer* restorer = GetIDRestorer()) - if (IDType newId = restorer->originalToNew(id)) - if (const hecl::ProjectPath* newSearch = project->lookupBridgePath(newId.toUint64())) - return *newSearch; - if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id) - LogDNACommon.report(logvisor::Warning, - "unable to translate %s to path", id.toString().c_str()); - return {}; - } - return *search; + const hecl::ProjectPath* search = project->lookupBridgePath(id.toUint64()); + if (!search) { + if (IDRestorer* restorer = GetIDRestorer()) + if (IDType newId = restorer->originalToNew(id)) + if (const hecl::ProjectPath* newSearch = project->lookupBridgePath(newId.toUint64())) + return *newSearch; + if (hecl::VerbosityLevel >= 1 && !silenceWarnings && id) + LogDNACommon.report(logvisor::Warning, "unable to translate %s to path", id.toString().c_str()); + return {}; + } + return *search; } -template -hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID32& id, bool silenceWarnings); -template -hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID64& id, bool silenceWarnings); -template -hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID128& id, bool silenceWarnings); +template hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID32& id, bool silenceWarnings); +template hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID64& id, bool silenceWarnings); +template hecl::ProjectPath UniqueIDBridge::TranslatePakIdToPath(const UniqueID128& id, bool silenceWarnings); template -hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str) -{ - if (str.empty()) - return {}; - hecl::Database::Project* project = s_Project.get(); - if (!project) - LogDNACommon.report(logvisor::Fatal, - "UniqueIDBridge::setGlobalProject must be called before MakePathFromString"); - hecl::ProjectPath path = hecl::ProjectPath(*project, str); - project->addBridgePathToCache(IDType(path).toUint64(), path); - return path; +hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str) { + if (str.empty()) + return {}; + hecl::Database::Project* project = s_Project.get(); + if (!project) + LogDNACommon.report(logvisor::Fatal, "UniqueIDBridge::setGlobalProject must be called before MakePathFromString"); + hecl::ProjectPath path = hecl::ProjectPath(*project, str); + project->addBridgePathToCache(IDType(path).toUint64(), path); + return path; } -template -hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str); -template -hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str); +template hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str); +template hecl::ProjectPath UniqueIDBridge::MakePathFromString(std::string_view str); template -void UniqueIDBridge::TransformOldHashToNewHash(IDType& id) -{ - id = TranslatePakIdToPath(id); +void UniqueIDBridge::TransformOldHashToNewHash(IDType& id) { + id = TranslatePakIdToPath(id); } -template -void UniqueIDBridge::TransformOldHashToNewHash(UniqueID32& id); -template -void UniqueIDBridge::TransformOldHashToNewHash(UniqueID64& id); +template void UniqueIDBridge::TransformOldHashToNewHash(UniqueID32& id); +template void UniqueIDBridge::TransformOldHashToNewHash(UniqueID64& id); -void UniqueIDBridge::SetThreadProject(hecl::Database::Project& project) -{ - s_Project.reset(&project); -} +void UniqueIDBridge::SetThreadProject(hecl::Database::Project& project) { s_Project.reset(&project); } /** PAK 32-bit Unique ID */ -void UniqueID32::assign(uint32_t id, bool noOriginal) -{ - m_id = id ? id : 0xffffffff; - if (!noOriginal) - if (IDRestorer* restorer = UniqueIDBridge::GetIDRestorer()) - if (UniqueID32 origId = restorer->newToOriginal(*this)) - *this = origId; +void UniqueID32::assign(uint32_t id, bool noOriginal) { + m_id = id ? id : 0xffffffff; + if (!noOriginal) + if (IDRestorer* restorer = UniqueIDBridge::GetIDRestorer()) + if (UniqueID32 origId = restorer->newToOriginal(*this)) + *this = origId; } template <> -void UniqueID32::Enumerate(typename Read::StreamT& reader) -{assign(reader.readUint32Big());} -template <> -void UniqueID32::Enumerate(typename Write::StreamT& writer) -{writer.writeUint32Big(m_id);} -template <> -void UniqueID32::Enumerate(typename ReadYaml::StreamT& reader) -{ - *this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr)); +void UniqueID32::Enumerate(typename Read::StreamT& reader) { + assign(reader.readUint32Big()); } template <> -void UniqueID32::Enumerate(typename WriteYaml::StreamT& writer) -{ - if (!operator bool()) - return; - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this); - if (!path) - return; - writer.writeString(nullptr, path.getAuxInfo().size() ? - (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) : - path.getRelativePathUTF8()); +void UniqueID32::Enumerate(typename Write::StreamT& writer) { + writer.writeUint32Big(m_id); } template <> -void UniqueID32::Enumerate(typename BinarySize::StreamT& s) -{s += 4;} +void UniqueID32::Enumerate(typename ReadYaml::StreamT& reader) { + *this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr)); +} +template <> +void UniqueID32::Enumerate(typename WriteYaml::StreamT& writer) { + if (!operator bool()) + return; + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this); + if (!path) + return; + writer.writeString(nullptr, path.getAuxInfo().size() + ? (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) + : path.getRelativePathUTF8()); +} +template <> +void UniqueID32::Enumerate(typename BinarySize::StreamT& s) { + s += 4; +} -std::string UniqueID32::toString() const -{ - char buf[9]; - snprintf(buf, 9, "%08X", m_id); - return std::string(buf); +std::string UniqueID32::toString() const { + char buf[9]; + snprintf(buf, 9, "%08X", m_id); + return std::string(buf); } template <> -void UniqueID32Zero::Enumerate(typename Read::StreamT& reader) -{UniqueID32::Enumerate(reader);} +void UniqueID32Zero::Enumerate(typename Read::StreamT& reader) { + UniqueID32::Enumerate(reader); +} template <> -void UniqueID32Zero::Enumerate(typename Write::StreamT& writer) -{writer.writeUint32Big(*this ? m_id : 0);} +void UniqueID32Zero::Enumerate(typename Write::StreamT& writer) { + writer.writeUint32Big(*this ? m_id : 0); +} template <> -void UniqueID32Zero::Enumerate(typename ReadYaml::StreamT& reader) -{UniqueID32::Enumerate(reader);} +void UniqueID32Zero::Enumerate(typename ReadYaml::StreamT& reader) { + UniqueID32::Enumerate(reader); +} template <> -void UniqueID32Zero::Enumerate(typename WriteYaml::StreamT& writer) -{UniqueID32::Enumerate(writer);} +void UniqueID32Zero::Enumerate(typename WriteYaml::StreamT& writer) { + UniqueID32::Enumerate(writer); +} template <> -void UniqueID32Zero::Enumerate(typename BinarySize::StreamT& s) -{UniqueID32::Enumerate(s);} - -AuxiliaryID32& AuxiliaryID32::operator=(const hecl::ProjectPath& path) -{ - assign(path.ensureAuxInfo(m_auxStr).hash().val32()); - return *this; +void UniqueID32Zero::Enumerate(typename BinarySize::StreamT& s) { + UniqueID32::Enumerate(s); } -AuxiliaryID32& AuxiliaryID32::operator=(const UniqueID32& id) -{ - m_baseId = id; - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); - if (path) - { - if (m_addExtension) - path = path.getWithExtension(m_addExtension); - *this = path; - } - return *this; +AuxiliaryID32& AuxiliaryID32::operator=(const hecl::ProjectPath& path) { + assign(path.ensureAuxInfo(m_auxStr).hash().val32()); + return *this; } -template <> -void AuxiliaryID32::Enumerate(typename Read::StreamT& reader) -{ - assign(reader.readUint32Big()); - m_baseId = *this; -} -template <> -void AuxiliaryID32::Enumerate(typename Write::StreamT& writer) -{ - writer.writeUint32Big(m_id); -} -template <> -void AuxiliaryID32::Enumerate(typename ReadYaml::StreamT& reader) -{ - hecl::ProjectPath readPath = UniqueIDBridge::MakePathFromString(reader.readString(nullptr)); - *this = readPath.ensureAuxInfo(m_auxStr); -} -template <> -void AuxiliaryID32::Enumerate(typename WriteYaml::StreamT& writer) -{ - if (!operator bool()) - return; - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this, true); - if (!path) - path = UniqueIDBridge::TranslatePakIdToPath(m_baseId); - if (!path) - return; +AuxiliaryID32& AuxiliaryID32::operator=(const UniqueID32& id) { + m_baseId = id; + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); + if (path) { if (m_addExtension) - path = path.getWithExtension(m_addExtension); - hecl::SystemUTF8Conv ufx8AuxStr(m_auxStr); - writer.writeString(nullptr, std::string(path.getRelativePathUTF8()) + '|' + ufx8AuxStr); + path = path.getWithExtension(m_addExtension); + *this = path; + } + return *this; } +template <> +void AuxiliaryID32::Enumerate(typename Read::StreamT& reader) { + assign(reader.readUint32Big()); + m_baseId = *this; +} +template <> +void AuxiliaryID32::Enumerate(typename Write::StreamT& writer) { + writer.writeUint32Big(m_id); +} +template <> +void AuxiliaryID32::Enumerate(typename ReadYaml::StreamT& reader) { + hecl::ProjectPath readPath = UniqueIDBridge::MakePathFromString(reader.readString(nullptr)); + *this = readPath.ensureAuxInfo(m_auxStr); +} +template <> +void AuxiliaryID32::Enumerate(typename WriteYaml::StreamT& writer) { + if (!operator bool()) + return; + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this, true); + if (!path) + path = UniqueIDBridge::TranslatePakIdToPath(m_baseId); + if (!path) + return; + if (m_addExtension) + path = path.getWithExtension(m_addExtension); + hecl::SystemUTF8Conv ufx8AuxStr(m_auxStr); + writer.writeString(nullptr, std::string(path.getRelativePathUTF8()) + '|' + ufx8AuxStr); +} /** PAK 64-bit Unique ID */ -void UniqueID64::assign(uint64_t id, bool noOriginal) -{ - m_id = id ? id : 0xffffffffffffffff; - if (!noOriginal) - if (IDRestorer* restorer = UniqueIDBridge::GetIDRestorer()) - if (UniqueID64 origId = restorer->newToOriginal(*this)) - *this = origId; +void UniqueID64::assign(uint64_t id, bool noOriginal) { + m_id = id ? id : 0xffffffffffffffff; + if (!noOriginal) + if (IDRestorer* restorer = UniqueIDBridge::GetIDRestorer()) + if (UniqueID64 origId = restorer->newToOriginal(*this)) + *this = origId; } template <> -void UniqueID64::Enumerate(typename Read::StreamT& reader) -{assign(reader.readUint64Big());} -template <> -void UniqueID64::Enumerate(typename Write::StreamT& writer) -{writer.writeUint64Big(m_id);} -template <> -void UniqueID64::Enumerate(typename ReadYaml::StreamT& reader) -{ - *this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr)); +void UniqueID64::Enumerate(typename Read::StreamT& reader) { + assign(reader.readUint64Big()); } template <> -void UniqueID64::Enumerate(typename WriteYaml::StreamT& writer) -{ - if (!operator bool()) - return; - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this); - if (!path) - return; - writer.writeString(nullptr, path.getAuxInfo().size() ? - (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) : - path.getRelativePathUTF8()); +void UniqueID64::Enumerate(typename Write::StreamT& writer) { + writer.writeUint64Big(m_id); } template <> -void UniqueID64::Enumerate(typename BinarySize::StreamT& s) -{s += 8;} +void UniqueID64::Enumerate(typename ReadYaml::StreamT& reader) { + *this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr)); +} +template <> +void UniqueID64::Enumerate(typename WriteYaml::StreamT& writer) { + if (!operator bool()) + return; + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this); + if (!path) + return; + writer.writeString(nullptr, path.getAuxInfo().size() + ? (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) + : path.getRelativePathUTF8()); +} +template <> +void UniqueID64::Enumerate(typename BinarySize::StreamT& s) { + s += 8; +} -std::string UniqueID64::toString() const -{ - char buf[17]; - snprintf(buf, 17, "%016" PRIX64, m_id); - return std::string(buf); +std::string UniqueID64::toString() const { + char buf[17]; + snprintf(buf, 17, "%016" PRIX64, m_id); + return std::string(buf); } /** PAK 128-bit Unique ID */ template <> -void UniqueID128::Enumerate(typename Read::StreamT& reader) -{ - m_id.id[0] = reader.readUint64Big(); - m_id.id[1] = reader.readUint64Big(); +void UniqueID128::Enumerate(typename Read::StreamT& reader) { + m_id.id[0] = reader.readUint64Big(); + m_id.id[1] = reader.readUint64Big(); } template <> -void UniqueID128::Enumerate(typename Write::StreamT& writer) -{ - writer.writeUint64Big(m_id.id[0]); - writer.writeUint64Big(m_id.id[1]); +void UniqueID128::Enumerate(typename Write::StreamT& writer) { + writer.writeUint64Big(m_id.id[0]); + writer.writeUint64Big(m_id.id[1]); } template <> -void UniqueID128::Enumerate(typename ReadYaml::StreamT& reader) -{ - *this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr)); +void UniqueID128::Enumerate(typename ReadYaml::StreamT& reader) { + *this = UniqueIDBridge::MakePathFromString(reader.readString(nullptr)); } template <> -void UniqueID128::Enumerate(typename WriteYaml::StreamT& writer) -{ - if (!operator bool()) - return; - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this); - if (!path) - return; - writer.writeString(nullptr, path.getAuxInfo().size() ? - (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) : - path.getRelativePathUTF8()); +void UniqueID128::Enumerate(typename WriteYaml::StreamT& writer) { + if (!operator bool()) + return; + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(*this); + if (!path) + return; + writer.writeString(nullptr, path.getAuxInfo().size() + ? (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) + : path.getRelativePathUTF8()); } template <> -void UniqueID128::Enumerate(typename BinarySize::StreamT& s) -{s += 16;} - -std::string UniqueID128::toString() const -{ - char buf[33]; - snprintf(buf, 33, "%016" PRIX64 "%016" PRIX64, m_id.id[0], m_id.id[1]); - return std::string(buf); +void UniqueID128::Enumerate(typename BinarySize::StreamT& s) { + s += 16; } +std::string UniqueID128::toString() const { + char buf[33]; + snprintf(buf, 33, "%016" PRIX64 "%016" PRIX64, m_id.id[0], m_id.id[1]); + return std::string(buf); +} /** Word Bitmap reader/writer */ -void WordBitmap::read(athena::io::IStreamReader& reader, size_t bitCount) -{ - m_bitCount = bitCount; - size_t wordCount = (bitCount + 31) / 32; - m_words.clear(); - m_words.reserve(wordCount); - for (size_t w=0 ; w BigDNAVYaml; /** FourCC with DNA read/write */ using DNAFourCC = hecl::DNAFourCC; -class DNAColor final : public BigDNA, public zeus::CColor -{ +class DNAColor final : public BigDNA, public zeus::CColor { public: - DNAColor() = default; - DNAColor(const zeus::CColor& color) : zeus::CColor(color) {} - AT_DECL_EXPLICIT_DNA_YAML + DNAColor() = default; + DNAColor(const zeus::CColor& color) : zeus::CColor(color) {} + AT_DECL_EXPLICIT_DNA_YAML }; -template <> inline void DNAColor::Enumerate(typename Read::StreamT& _r) -{ zeus::CColor::readRGBABig(_r); } -template <> inline void DNAColor::Enumerate(typename Write::StreamT& _w) -{ zeus::CColor::writeRGBABig(_w); } -template <> inline void DNAColor::Enumerate(typename ReadYaml::StreamT& _r) -{ - size_t count; - if (auto v = _r.enterSubVector(nullptr, count)) - { - zeus::simd_floats f; - f[0] = (count >= 1) ? _r.readFloat(nullptr) : 0.f; - f[1] = (count >= 2) ? _r.readFloat(nullptr) : 0.f; - f[2] = (count >= 3) ? _r.readFloat(nullptr) : 0.f; - f[3] = (count >= 4) ? _r.readFloat(nullptr) : 0.f; - mSimd.copy_from(f); - } +template <> +inline void DNAColor::Enumerate(typename Read::StreamT& _r) { + zeus::CColor::readRGBABig(_r); } -template <> inline void DNAColor::Enumerate(typename WriteYaml::StreamT& _w) -{ - if (auto v = _w.enterSubVector(nullptr)) - { - zeus::simd_floats f(mSimd); - _w.writeFloat(nullptr, f[0]); - _w.writeFloat(nullptr, f[1]); - _w.writeFloat(nullptr, f[2]); - _w.writeFloat(nullptr, f[3]); - } +template <> +inline void DNAColor::Enumerate(typename Write::StreamT& _w) { + zeus::CColor::writeRGBABig(_w); +} +template <> +inline void DNAColor::Enumerate(typename ReadYaml::StreamT& _r) { + size_t count; + if (auto v = _r.enterSubVector(nullptr, count)) { + zeus::simd_floats f; + f[0] = (count >= 1) ? _r.readFloat(nullptr) : 0.f; + f[1] = (count >= 2) ? _r.readFloat(nullptr) : 0.f; + f[2] = (count >= 3) ? _r.readFloat(nullptr) : 0.f; + f[3] = (count >= 4) ? _r.readFloat(nullptr) : 0.f; + mSimd.copy_from(f); + } +} +template <> +inline void DNAColor::Enumerate(typename WriteYaml::StreamT& _w) { + if (auto v = _w.enterSubVector(nullptr)) { + zeus::simd_floats f(mSimd); + _w.writeFloat(nullptr, f[0]); + _w.writeFloat(nullptr, f[1]); + _w.writeFloat(nullptr, f[2]); + _w.writeFloat(nullptr, f[3]); + } +} +template <> +inline void DNAColor::Enumerate(typename BinarySize::StreamT& _s) { + _s += 16; } -template <> inline void DNAColor::Enumerate(typename BinarySize::StreamT& _s) -{ _s += 16; } using FourCC = hecl::FourCC; class UniqueID32; @@ -69,277 +71,266 @@ class UniqueID64; class UniqueID128; /** Common virtual interface for runtime ambiguity resolution */ -class PAKRouterBase -{ +class PAKRouterBase { protected: - const SpecBase& m_dataSpec; + const SpecBase& m_dataSpec; + public: - PAKRouterBase(const SpecBase& dataSpec) : m_dataSpec(dataSpec) {} - hecl::Database::Project& getProject() const {return m_dataSpec.getProject();} - virtual hecl::ProjectPath getWorking(const UniqueID32&, bool silenceWarnings=false) const - { - LogDNACommon.report(logvisor::Fatal, - "PAKRouter IDType mismatch; expected UniqueID32 specialization"); - return hecl::ProjectPath(); - } - virtual hecl::ProjectPath getWorking(const UniqueID64&, bool silenceWarnings=false) const - { - LogDNACommon.report(logvisor::Fatal, - "PAKRouter IDType mismatch; expected UniqueID64 specialization"); - return hecl::ProjectPath(); - } - virtual hecl::ProjectPath getWorking(const UniqueID128&, bool silenceWarnings=false) const - { - LogDNACommon.report(logvisor::Fatal, - "PAKRouter IDType mismatch; expected UniqueID128 specialization"); - return hecl::ProjectPath(); - } + PAKRouterBase(const SpecBase& dataSpec) : m_dataSpec(dataSpec) {} + hecl::Database::Project& getProject() const { return m_dataSpec.getProject(); } + virtual hecl::ProjectPath getWorking(const UniqueID32&, bool silenceWarnings = false) const { + LogDNACommon.report(logvisor::Fatal, "PAKRouter IDType mismatch; expected UniqueID32 specialization"); + return hecl::ProjectPath(); + } + virtual hecl::ProjectPath getWorking(const UniqueID64&, bool silenceWarnings = false) const { + LogDNACommon.report(logvisor::Fatal, "PAKRouter IDType mismatch; expected UniqueID64 specialization"); + return hecl::ProjectPath(); + } + virtual hecl::ProjectPath getWorking(const UniqueID128&, bool silenceWarnings = false) const { + LogDNACommon.report(logvisor::Fatal, "PAKRouter IDType mismatch; expected UniqueID128 specialization"); + return hecl::ProjectPath(); + } }; /** Globally-accessed manager allowing UniqueID* classes to directly * lookup destination paths of resources */ -class UniqueIDBridge -{ - friend class UniqueID32; - friend class UniqueID64; +class UniqueIDBridge { + friend class UniqueID32; + friend class UniqueID64; + + static ThreadLocalPtr s_Project; + static ThreadLocalPtr> s_restorer32; + static ThreadLocalPtr> s_restorer64; + static ThreadLocalPtr> s_restorer128; - static ThreadLocalPtr s_Project; - static ThreadLocalPtr> s_restorer32; - static ThreadLocalPtr> s_restorer64; - static ThreadLocalPtr> s_restorer128; public: - template - static hecl::ProjectPath TranslatePakIdToPath(const IDType& id, bool silenceWarnings=false); - template - static hecl::ProjectPath MakePathFromString(std::string_view str); - template - static void TransformOldHashToNewHash(IDType& id); + template + static hecl::ProjectPath TranslatePakIdToPath(const IDType& id, bool silenceWarnings = false); + template + static hecl::ProjectPath MakePathFromString(std::string_view str); + template + static void TransformOldHashToNewHash(IDType& id); - static void SetThreadProject(hecl::Database::Project& project); + static void SetThreadProject(hecl::Database::Project& project); - template - static IDRestorer* GetIDRestorer(); - template - static void SetIDRestorer(IDRestorer* restorer); + template + static IDRestorer* GetIDRestorer(); + template + static void SetIDRestorer(IDRestorer* restorer); }; template <> -inline IDRestorer* UniqueIDBridge::GetIDRestorer() -{ - return s_restorer32.get(); +inline IDRestorer* UniqueIDBridge::GetIDRestorer() { + return s_restorer32.get(); } template <> -inline void UniqueIDBridge::SetIDRestorer(IDRestorer* restorer) -{ - s_restorer32.reset(restorer); +inline void UniqueIDBridge::SetIDRestorer(IDRestorer* restorer) { + s_restorer32.reset(restorer); } template <> -inline IDRestorer* UniqueIDBridge::GetIDRestorer() -{ - return s_restorer64.get(); +inline IDRestorer* UniqueIDBridge::GetIDRestorer() { + return s_restorer64.get(); } template <> -inline void UniqueIDBridge::SetIDRestorer(IDRestorer* restorer) -{ - s_restorer64.reset(restorer); +inline void UniqueIDBridge::SetIDRestorer(IDRestorer* restorer) { + s_restorer64.reset(restorer); } template <> -inline IDRestorer* UniqueIDBridge::GetIDRestorer() -{ - return s_restorer128.get(); +inline IDRestorer* UniqueIDBridge::GetIDRestorer() { + return s_restorer128.get(); } template <> -inline void UniqueIDBridge::SetIDRestorer(IDRestorer* restorer) -{ - s_restorer128.reset(restorer); +inline void UniqueIDBridge::SetIDRestorer(IDRestorer* restorer) { + s_restorer128.reset(restorer); } /** PAK 32-bit Unique ID */ -class UniqueID32 : public BigDNA -{ +class UniqueID32 : public BigDNA { protected: - uint32_t m_id = 0xffffffff; + uint32_t m_id = 0xffffffff; + public: - using value_type = uint32_t; - static UniqueID32 kInvalidId; - AT_DECL_EXPLICIT_DNA_YAML - operator bool() const {return m_id != 0xffffffff && m_id != 0;} - void assign(uint32_t id, bool noOriginal = false); + using value_type = uint32_t; + static UniqueID32 kInvalidId; + AT_DECL_EXPLICIT_DNA_YAML + operator bool() const { return m_id != 0xffffffff && m_id != 0; } + void assign(uint32_t id, bool noOriginal = false); - UniqueID32& operator=(const hecl::ProjectPath& path) - {assign(path.hash().val32()); return *this;} + UniqueID32& operator=(const hecl::ProjectPath& path) { + assign(path.hash().val32()); + return *this; + } - bool operator!=(const UniqueID32& other) const {return m_id != other.m_id;} - bool operator==(const UniqueID32& other) const {return m_id == other.m_id;} - bool operator<(const UniqueID32& other) const {return m_id < other.m_id;} - uint32_t toUint32() const {return m_id;} - uint64_t toUint64() const {return m_id;} - std::string toString() const; - void clear() {m_id = 0xffffffff;} + bool operator!=(const UniqueID32& other) const { return m_id != other.m_id; } + bool operator==(const UniqueID32& other) const { return m_id == other.m_id; } + bool operator<(const UniqueID32& other) const { return m_id < other.m_id; } + uint32_t toUint32() const { return m_id; } + uint64_t toUint64() const { return m_id; } + std::string toString() const; + void clear() { m_id = 0xffffffff; } - UniqueID32() = default; - UniqueID32(uint32_t idin, bool noOriginal = false) {assign(idin, noOriginal);} - UniqueID32(athena::io::IStreamReader& reader) {read(reader);} - UniqueID32(const hecl::ProjectPath& path) {*this = path;} - UniqueID32(const char* hexStr) - { - char copy[9]; - strncpy(copy, hexStr, 8); - copy[8] = '\0'; - assign(strtoul(copy, nullptr, 16)); - } - UniqueID32(const wchar_t* hexStr) - { - wchar_t copy[9]; - wcsncpy(copy, hexStr, 8); - copy[8] = L'\0'; - assign(wcstoul(copy, nullptr, 16)); - } + UniqueID32() = default; + UniqueID32(uint32_t idin, bool noOriginal = false) { assign(idin, noOriginal); } + UniqueID32(athena::io::IStreamReader& reader) { read(reader); } + UniqueID32(const hecl::ProjectPath& path) { *this = path; } + UniqueID32(const char* hexStr) { + char copy[9]; + strncpy(copy, hexStr, 8); + copy[8] = '\0'; + assign(strtoul(copy, nullptr, 16)); + } + UniqueID32(const wchar_t* hexStr) { + wchar_t copy[9]; + wcsncpy(copy, hexStr, 8); + copy[8] = L'\0'; + assign(wcstoul(copy, nullptr, 16)); + } - static constexpr size_t BinarySize() {return 4;} + static constexpr size_t BinarySize() { return 4; } }; /** PAK 32-bit Unique ID - writes zero when invalid */ -class UniqueID32Zero : public UniqueID32 -{ +class UniqueID32Zero : public UniqueID32 { public: - AT_DECL_DNA_YAML - Delete __d2; - using UniqueID32::UniqueID32; + AT_DECL_DNA_YAML + Delete __d2; + using UniqueID32::UniqueID32; }; -class AuxiliaryID32 : public UniqueID32 -{ - const hecl::SystemChar* m_auxStr; - const hecl::SystemChar* m_addExtension; - UniqueID32 m_baseId; -public: - AT_DECL_DNA - Delete __d2; - AuxiliaryID32(const hecl::SystemChar* auxStr, - const hecl::SystemChar* addExtension=nullptr) - : m_auxStr(auxStr), m_addExtension(addExtension) {} +class AuxiliaryID32 : public UniqueID32 { + const hecl::SystemChar* m_auxStr; + const hecl::SystemChar* m_addExtension; + UniqueID32 m_baseId; - AuxiliaryID32& operator=(const hecl::ProjectPath& path); - AuxiliaryID32& operator=(const UniqueID32& id); - const UniqueID32& getBaseId() const {return m_baseId;} +public: + AT_DECL_DNA + Delete __d2; + AuxiliaryID32(const hecl::SystemChar* auxStr, const hecl::SystemChar* addExtension = nullptr) + : m_auxStr(auxStr), m_addExtension(addExtension) {} + + AuxiliaryID32& operator=(const hecl::ProjectPath& path); + AuxiliaryID32& operator=(const UniqueID32& id); + const UniqueID32& getBaseId() const { return m_baseId; } }; /** PAK 64-bit Unique ID */ -class UniqueID64 : public BigDNA -{ - uint64_t m_id = 0xffffffffffffffff; +class UniqueID64 : public BigDNA { + uint64_t m_id = 0xffffffffffffffff; + public: - using value_type = uint64_t; - AT_DECL_EXPLICIT_DNA_YAML - operator bool() const {return m_id != 0xffffffffffffffff && m_id != 0;} - void assign(uint64_t id, bool noOriginal = false); + using value_type = uint64_t; + AT_DECL_EXPLICIT_DNA_YAML + operator bool() const { return m_id != 0xffffffffffffffff && m_id != 0; } + void assign(uint64_t id, bool noOriginal = false); - UniqueID64& operator=(const hecl::ProjectPath& path) - {assign(path.hash().val64()); return *this;} + UniqueID64& operator=(const hecl::ProjectPath& path) { + assign(path.hash().val64()); + return *this; + } - bool operator!=(const UniqueID64& other) const {return m_id != other.m_id;} - bool operator==(const UniqueID64& other) const {return m_id == other.m_id;} - bool operator<(const UniqueID64& other) const {return m_id < other.m_id;} - uint64_t toUint64() const {return m_id;} - std::string toString() const; - void clear() {m_id = 0xffffffffffffffff;} + bool operator!=(const UniqueID64& other) const { return m_id != other.m_id; } + bool operator==(const UniqueID64& other) const { return m_id == other.m_id; } + bool operator<(const UniqueID64& other) const { return m_id < other.m_id; } + uint64_t toUint64() const { return m_id; } + std::string toString() const; + void clear() { m_id = 0xffffffffffffffff; } - UniqueID64() = default; - UniqueID64(uint64_t idin, bool noOriginal = false) {assign(idin, noOriginal);} - UniqueID64(athena::io::IStreamReader& reader) {read(reader);} - UniqueID64(const hecl::ProjectPath& path) {*this = path;} - UniqueID64(const char* hexStr) - { - char copy[17]; - strncpy(copy, hexStr, 16); - copy[16] = '\0'; + UniqueID64() = default; + UniqueID64(uint64_t idin, bool noOriginal = false) { assign(idin, noOriginal); } + UniqueID64(athena::io::IStreamReader& reader) { read(reader); } + UniqueID64(const hecl::ProjectPath& path) { *this = path; } + UniqueID64(const char* hexStr) { + char copy[17]; + strncpy(copy, hexStr, 16); + copy[16] = '\0'; #if _WIN32 - assign(_strtoui64(copy, nullptr, 16)); + assign(_strtoui64(copy, nullptr, 16)); #else - assign(strtouq(copy, nullptr, 16)); + assign(strtouq(copy, nullptr, 16)); #endif - } - UniqueID64(const wchar_t* hexStr) - { - wchar_t copy[17]; - wcsncpy(copy, hexStr, 16); - copy[16] = L'\0'; + } + UniqueID64(const wchar_t* hexStr) { + wchar_t copy[17]; + wcsncpy(copy, hexStr, 16); + copy[16] = L'\0'; #if _WIN32 - assign(_wcstoui64(copy, nullptr, 16)); + assign(_wcstoui64(copy, nullptr, 16)); #else - assign(wcstoull(copy, nullptr, 16)); + assign(wcstoull(copy, nullptr, 16)); #endif - } + } - static constexpr size_t BinarySize() {return 8;} + static constexpr size_t BinarySize() { return 8; } }; /** PAK 128-bit Unique ID */ -class UniqueID128 : public BigDNA -{ +class UniqueID128 : public BigDNA { public: - union Value - { - uint64_t id[2]; + union Value { + uint64_t id[2]; #if __SSE__ - __m128i id128; + __m128i id128; #endif - }; + }; + private: - Value m_id; + Value m_id; + public: - using value_type = uint64_t; - AT_DECL_EXPLICIT_DNA_YAML - UniqueID128() {m_id.id[0]=0xffffffffffffffff; m_id.id[1]=0xffffffffffffffff;} - UniqueID128(uint64_t idin, bool noOriginal = false) - { - m_id.id[0] = idin; - m_id.id[1] = 0; - } - operator bool() const - {return m_id.id[0] != 0xffffffffffffffff && m_id.id[0] != 0 && m_id.id[1] != 0xffffffffffffffff && m_id.id[1] != 0;} + using value_type = uint64_t; + AT_DECL_EXPLICIT_DNA_YAML + UniqueID128() { + m_id.id[0] = 0xffffffffffffffff; + m_id.id[1] = 0xffffffffffffffff; + } + UniqueID128(uint64_t idin, bool noOriginal = false) { + m_id.id[0] = idin; + m_id.id[1] = 0; + } + operator bool() const { + return m_id.id[0] != 0xffffffffffffffff && m_id.id[0] != 0 && m_id.id[1] != 0xffffffffffffffff && m_id.id[1] != 0; + } - UniqueID128& operator=(const hecl::ProjectPath& path) - { - m_id.id[0] = path.hash().val64(); - m_id.id[1] = 0; - return *this; - } - UniqueID128(const hecl::ProjectPath& path) {*this = path;} + UniqueID128& operator=(const hecl::ProjectPath& path) { + m_id.id[0] = path.hash().val64(); + m_id.id[1] = 0; + return *this; + } + UniqueID128(const hecl::ProjectPath& path) { *this = path; } - bool operator!=(const UniqueID128& other) const - { + bool operator!=(const UniqueID128& other) const { #if __SSE__ - __m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128); - int vmask = _mm_movemask_epi8(vcmp); - return vmask != 0xffff; + __m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128); + int vmask = _mm_movemask_epi8(vcmp); + return vmask != 0xffff; #else - return (m_id.id[0] != other.m_id.id[0]) || (m_id.id[1] != other.m_id.id[1]); + return (m_id.id[0] != other.m_id.id[0]) || (m_id.id[1] != other.m_id.id[1]); #endif - } - bool operator==(const UniqueID128& other) const - { + } + bool operator==(const UniqueID128& other) const { #if __SSE__ - __m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128); - int vmask = _mm_movemask_epi8(vcmp); - return vmask == 0xffff; + __m128i vcmp = _mm_cmpeq_epi32(m_id.id128, other.m_id.id128); + int vmask = _mm_movemask_epi8(vcmp); + return vmask == 0xffff; #else - return (m_id.id[0] == other.m_id.id[0]) && (m_id.id[1] == other.m_id.id[1]); + return (m_id.id[0] == other.m_id.id[0]) && (m_id.id[1] == other.m_id.id[1]); #endif - } - void clear() {m_id.id[0] = 0xffffffffffffffff; m_id.id[1] = 0xffffffffffffffff;} - uint64_t toUint64() const {return m_id.id[0];} - uint64_t toHighUint64() const {return m_id.id[0];} - uint64_t toLowUint64() const {return m_id.id[1];} - std::string toString() const; + } + void clear() { + m_id.id[0] = 0xffffffffffffffff; + m_id.id[1] = 0xffffffffffffffff; + } + uint64_t toUint64() const { return m_id.id[0]; } + uint64_t toHighUint64() const { return m_id.id[0]; } + uint64_t toLowUint64() const { return m_id.id[1]; } + std::string toString() const; - static constexpr size_t BinarySize() {return 16;} + static constexpr size_t BinarySize() { return 16; } }; /** Casts ID type to its null-zero equivalent */ @@ -347,63 +338,66 @@ template using CastIDToZero = typename std::conditional_t, UniqueID32Zero, T>; /** Word Bitmap reader/writer */ -class WordBitmap -{ - std::vector m_words; - size_t m_bitCount = 0; +class WordBitmap { + std::vector m_words; + size_t m_bitCount = 0; + public: - void read(athena::io::IStreamReader& reader, size_t bitCount); - void write(athena::io::IStreamWriter& writer) const; - void reserve(size_t bitCount) { m_words.reserve((bitCount + 31) / 32); } - void binarySize(size_t& __isz) const; - size_t getBitCount() const {return m_bitCount;} - bool getBit(size_t idx) const - { - size_t wordIdx = idx / 32; - if (wordIdx >= m_words.size()) - return false; - size_t wordCur = idx % 32; - return (m_words[wordIdx] >> wordCur) & 0x1; - } - void setBit(size_t idx) - { - size_t wordIdx = idx / 32; - while (wordIdx >= m_words.size()) - m_words.push_back(0); - size_t wordCur = idx % 32; - m_words[wordIdx] |= (1 << wordCur); - m_bitCount = std::max(m_bitCount, idx + 1); - } - void unsetBit(size_t idx) - { - size_t wordIdx = idx / 32; - while (wordIdx >= m_words.size()) - m_words.push_back(0); - size_t wordCur = idx % 32; - m_words[wordIdx] &= ~(1 << wordCur); - m_bitCount = std::max(m_bitCount, idx + 1); - } - void clear() { m_words.clear(); m_bitCount = 0; } + void read(athena::io::IStreamReader& reader, size_t bitCount); + void write(athena::io::IStreamWriter& writer) const; + void reserve(size_t bitCount) { m_words.reserve((bitCount + 31) / 32); } + void binarySize(size_t& __isz) const; + size_t getBitCount() const { return m_bitCount; } + bool getBit(size_t idx) const { + size_t wordIdx = idx / 32; + if (wordIdx >= m_words.size()) + return false; + size_t wordCur = idx % 32; + return (m_words[wordIdx] >> wordCur) & 0x1; + } + void setBit(size_t idx) { + size_t wordIdx = idx / 32; + while (wordIdx >= m_words.size()) + m_words.push_back(0); + size_t wordCur = idx % 32; + m_words[wordIdx] |= (1 << wordCur); + m_bitCount = std::max(m_bitCount, idx + 1); + } + void unsetBit(size_t idx) { + size_t wordIdx = idx / 32; + while (wordIdx >= m_words.size()) + m_words.push_back(0); + size_t wordCur = idx % 32; + m_words[wordIdx] &= ~(1 << wordCur); + m_bitCount = std::max(m_bitCount, idx + 1); + } + void clear() { + m_words.clear(); + m_bitCount = 0; + } - class Iterator - { - friend class WordBitmap; - const WordBitmap& m_bmp; - size_t m_idx = 0; - Iterator(const WordBitmap& bmp, size_t idx) : m_bmp(bmp), m_idx(idx) {} - public: - using iterator_category = std::forward_iterator_tag; - using value_type = bool; - using difference_type = std::ptrdiff_t; - using pointer = bool*; - using reference = bool&; + class Iterator { + friend class WordBitmap; + const WordBitmap& m_bmp; + size_t m_idx = 0; + Iterator(const WordBitmap& bmp, size_t idx) : m_bmp(bmp), m_idx(idx) {} - Iterator& operator++() {++m_idx; return *this;} - bool operator*() {return m_bmp.getBit(m_idx);} - bool operator!=(const Iterator& other) const {return m_idx != other.m_idx;} - }; - Iterator begin() const {return Iterator(*this, 0);} - Iterator end() const {return Iterator(*this, m_bitCount);} + public: + using iterator_category = std::forward_iterator_tag; + using value_type = bool; + using difference_type = std::ptrdiff_t; + using pointer = bool*; + using reference = bool&; + + Iterator& operator++() { + ++m_idx; + return *this; + } + bool operator*() { return m_bmp.getBit(m_idx); } + bool operator!=(const Iterator& other) const { return m_idx != other.m_idx; } + }; + Iterator begin() const { return Iterator(*this, 0); } + Iterator end() const { return Iterator(*this, m_bitCount); } }; /** Resource cooker function */ @@ -411,60 +405,47 @@ typedef std::function /** Mappings of resources involved in extracting characters */ template -struct CharacterAssociations -{ - using RigPair = std::pair; - /* CMDL -> (CSKR, CINF) */ - std::unordered_map m_cmdlRigs; - /* (CSKR, CINF) -> ANCS */ - std::unordered_map> m_cskrCinfToCharacter; - /* ANCS -> (CINF, CMDL) */ - std::unordered_multimap> m_characterToAttachmentRigs; - using MultimapIteratorPair = std::pair< - typename std::unordered_multimap>::const_iterator, - typename std::unordered_multimap>::const_iterator>; - void addAttachmentRig(IDType character, IDType cinf, IDType cmdl, const char* name) - { - auto range = m_characterToAttachmentRigs.equal_range(character); - for (auto it = range.first; it != range.second; ++it) - if (it->second.second == name) - return; - m_characterToAttachmentRigs.insert( - std::make_pair(character, std::make_pair(std::make_pair(cinf, cmdl), name))); - } +struct CharacterAssociations { + using RigPair = std::pair; + /* CMDL -> (CSKR, CINF) */ + std::unordered_map m_cmdlRigs; + /* (CSKR, CINF) -> ANCS */ + std::unordered_map> m_cskrCinfToCharacter; + /* ANCS -> (CINF, CMDL) */ + std::unordered_multimap> m_characterToAttachmentRigs; + using MultimapIteratorPair = + std::pair>::const_iterator, + typename std::unordered_multimap>::const_iterator>; + void addAttachmentRig(IDType character, IDType cinf, IDType cmdl, const char* name) { + auto range = m_characterToAttachmentRigs.equal_range(character); + for (auto it = range.first; it != range.second; ++it) + if (it->second.second == name) + return; + m_characterToAttachmentRigs.insert(std::make_pair(character, std::make_pair(std::make_pair(cinf, cmdl), name))); + } }; -} +} // namespace DataSpec /* Hash template-specializations for UniqueID types */ -namespace std -{ -template<> -struct hash -{ - size_t operator()(const DataSpec::DNAFourCC& fcc) const - {return fcc.toUint32();} +namespace std { +template <> +struct hash { + size_t operator()(const DataSpec::DNAFourCC& fcc) const { return fcc.toUint32(); } }; -template<> -struct hash -{ - size_t operator()(const DataSpec::UniqueID32& id) const - {return id.toUint32();} +template <> +struct hash { + size_t operator()(const DataSpec::UniqueID32& id) const { return id.toUint32(); } }; -template<> -struct hash -{ - size_t operator()(const DataSpec::UniqueID64& id) const - {return id.toUint64();} +template <> +struct hash { + size_t operator()(const DataSpec::UniqueID64& id) const { return id.toUint64(); } }; -template<> -struct hash -{ - size_t operator()(const DataSpec::UniqueID128& id) const - {return id.toHighUint64() ^ id.toLowUint64();} +template <> +struct hash { + size_t operator()(const DataSpec::UniqueID128& id) const { return id.toHighUint64() ^ id.toLowUint64(); } }; -} - +} // namespace std diff --git a/DataSpec/DNACommon/DPSC.cpp b/DataSpec/DNACommon/DPSC.cpp index fd130c84f..e7fa74359 100644 --- a/DataSpec/DNACommon/DPSC.cpp +++ b/DataSpec/DNACommon/DPSC.cpp @@ -1,418 +1,377 @@ #include "DPSC.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template <> -const char* DPSM::DNAType() { return "DPSM"; } +const char* DPSM::DNAType() { + return "DPSM"; +} template <> -const char* DPSM::DNAType() { return "DPSM"; } - -template -void DPSM::_read(athena::io::YAMLDocReader& r) -{ - for (const auto& elem : r.getCurNode()->m_mapChildren) - { - if (elem.first.size() < 4) - { - LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); - continue; - } - - if (auto rec = r.enterSubRecord(elem.first.c_str())) - { - bool loadFirstDesc = false; - uint32_t clsId = *reinterpret_cast(elem.first.c_str()); - switch(clsId) - { - case SBIG('1SZE'): - case SBIG('1LFT'): - case SBIG('1ROT'): - case SBIG('1OFF'): - case SBIG('1CLR'): - case SBIG('1TEX'): - case SBIG('1ADD'): - loadFirstDesc = true; - case SBIG('2SZE'): - case SBIG('2LFT'): - case SBIG('2ROT'): - case SBIG('2OFF'): - case SBIG('2CLR'): - case SBIG('2TEX'): - case SBIG('2ADD'): - if (loadFirstDesc) - readQuadDecalInfo(r, clsId, x0_quad); - else - readQuadDecalInfo(r, clsId, x1c_quad); - break; - case SBIG('DMDL'): - x38_DMDL.read(r); - break; - case SBIG('DLFT'): - x48_DLFT.read(r); - break; - case SBIG('DMOP'): - x4c_DMOP.read(r); - break; - case SBIG('DMRT'): - x50_DMRT.read(r); - break; - case SBIG('DMSC'): - x54_DMSC.read(r); - break; - case SBIG('DMCL'): - x58_DMCL.read(r); - break; - case SBIG('DMAB'): - x5c_24_DMAB = r.readBool(nullptr); - break; - case SBIG('DMOO'): - x5c_25_DMOO = r.readBool(nullptr); - break; - } - } - } +const char* DPSM::DNAType() { + return "DPSM"; } template -void DPSM::_write(athena::io::YAMLDocWriter& w) const -{ - writeQuadDecalInfo(w, x0_quad, true); - writeQuadDecalInfo(w, x1c_quad, false); +void DPSM::_read(athena::io::YAMLDocReader& r) { + for (const auto& elem : r.getCurNode()->m_mapChildren) { + if (elem.first.size() < 4) { + LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); + continue; + } - if (x38_DMDL) - if (auto rec = w.enterSubRecord("DMDL")) - x38_DMDL.write(w); - if (x48_DLFT) - if (auto rec = w.enterSubRecord("DLFT")) - x48_DLFT.write(w); - if (x4c_DMOP) - if (auto rec = w.enterSubRecord("DMOP")) - x4c_DMOP.write(w); - if (x50_DMRT) - if (auto rec = w.enterSubRecord("DMRT")) - x50_DMRT.write(w); - if (x54_DMSC) - if (auto rec = w.enterSubRecord("DMSC")) - x54_DMSC.write(w); - if (x58_DMCL) - if (auto rec = w.enterSubRecord("DMCL")) - x54_DMSC.write(w); + if (auto rec = r.enterSubRecord(elem.first.c_str())) { + bool loadFirstDesc = false; + uint32_t clsId = *reinterpret_cast(elem.first.c_str()); + switch (clsId) { + case SBIG('1SZE'): + case SBIG('1LFT'): + case SBIG('1ROT'): + case SBIG('1OFF'): + case SBIG('1CLR'): + case SBIG('1TEX'): + case SBIG('1ADD'): + loadFirstDesc = true; + case SBIG('2SZE'): + case SBIG('2LFT'): + case SBIG('2ROT'): + case SBIG('2OFF'): + case SBIG('2CLR'): + case SBIG('2TEX'): + case SBIG('2ADD'): + if (loadFirstDesc) + readQuadDecalInfo(r, clsId, x0_quad); + else + readQuadDecalInfo(r, clsId, x1c_quad); + break; + case SBIG('DMDL'): + x38_DMDL.read(r); + break; + case SBIG('DLFT'): + x48_DLFT.read(r); + break; + case SBIG('DMOP'): + x4c_DMOP.read(r); + break; + case SBIG('DMRT'): + x50_DMRT.read(r); + break; + case SBIG('DMSC'): + x54_DMSC.read(r); + break; + case SBIG('DMCL'): + x58_DMCL.read(r); + break; + case SBIG('DMAB'): + x5c_24_DMAB = r.readBool(nullptr); + break; + case SBIG('DMOO'): + x5c_25_DMOO = r.readBool(nullptr); + break; + } + } + } +} - if (x5c_24_DMAB) - w.writeBool("DMAB", x5c_24_DMAB); - if (x5c_25_DMOO) - w.writeBool("DMOO", x5c_25_DMOO); +template +void DPSM::_write(athena::io::YAMLDocWriter& w) const { + writeQuadDecalInfo(w, x0_quad, true); + writeQuadDecalInfo(w, x1c_quad, false); + + if (x38_DMDL) + if (auto rec = w.enterSubRecord("DMDL")) + x38_DMDL.write(w); + if (x48_DLFT) + if (auto rec = w.enterSubRecord("DLFT")) + x48_DLFT.write(w); + if (x4c_DMOP) + if (auto rec = w.enterSubRecord("DMOP")) + x4c_DMOP.write(w); + if (x50_DMRT) + if (auto rec = w.enterSubRecord("DMRT")) + x50_DMRT.write(w); + if (x54_DMSC) + if (auto rec = w.enterSubRecord("DMSC")) + x54_DMSC.write(w); + if (x58_DMCL) + if (auto rec = w.enterSubRecord("DMCL")) + x54_DMSC.write(w); + + if (x5c_24_DMAB) + w.writeBool("DMAB", x5c_24_DMAB); + if (x5c_25_DMOO) + w.writeBool("DMOO", x5c_25_DMOO); } template template -void DPSM::readQuadDecalInfo(Reader& r, uint32_t clsId, typename DPSM::SQuadDescr& quad) -{ - switch(clsId) - { - case SBIG('1LFT'): - case SBIG('2LFT'): - quad.x0_LFT.read(r); +void DPSM::readQuadDecalInfo(Reader& r, uint32_t clsId, typename DPSM::SQuadDescr& quad) { + switch (clsId) { + case SBIG('1LFT'): + case SBIG('2LFT'): + quad.x0_LFT.read(r); break; - case SBIG('1SZE'): - case SBIG('2SZE'): - quad.x4_SZE.read(r); + case SBIG('1SZE'): + case SBIG('2SZE'): + quad.x4_SZE.read(r); break; - case SBIG('1ROT'): - case SBIG('2ROT'): - quad.x8_ROT.read(r); + case SBIG('1ROT'): + case SBIG('2ROT'): + quad.x8_ROT.read(r); break; - case SBIG('1OFF'): - case SBIG('2OFF'): - quad.xc_OFF.read(r); + case SBIG('1OFF'): + case SBIG('2OFF'): + quad.xc_OFF.read(r); break; - case SBIG('1CLR'): - case SBIG('2CLR'): - quad.x10_CLR.read(r); + case SBIG('1CLR'): + case SBIG('2CLR'): + quad.x10_CLR.read(r); break; - case SBIG('1TEX'): - case SBIG('2TEX'): - quad.x14_TEX.read(r); + case SBIG('1TEX'): + case SBIG('2TEX'): + quad.x14_TEX.read(r); break; - case SBIG('1ADD'): - case SBIG('2ADD'): - quad.x18_ADD.read(r); + case SBIG('1ADD'): + case SBIG('2ADD'): + quad.x18_ADD.read(r); break; - } + } } template -void DPSM::writeQuadDecalInfo(athena::io::YAMLDocWriter& w, - const typename DPSM::SQuadDescr& quad, bool first) const -{ - if (quad.x0_LFT) - if (auto rec = w.enterSubRecord((first ? "1LFT" : "2LFT"))) - quad.x0_LFT.write(w); - if (quad.x4_SZE) - if (auto rec = w.enterSubRecord((first ? "1SZE" : "2SZE"))) - quad.x4_SZE.write(w); - if (quad.x8_ROT) - if (auto rec = w.enterSubRecord((first ? "1ROT" : "2ROT"))) - quad.x8_ROT.write(w); - if (quad.xc_OFF) - if (auto rec = w.enterSubRecord((first ? "1OFF" : "2OFF"))) - quad.xc_OFF.write(w); - if (quad.x10_CLR) - if (auto rec = w.enterSubRecord((first ? "1CLR" : "2CLR"))) - quad.x10_CLR.write(w); - if (quad.x14_TEX) - if (auto rec = w.enterSubRecord((first ? "1TEX" : "2TEX"))) - quad.x14_TEX.write(w); - if (quad.x18_ADD) - if (auto rec = w.enterSubRecord((first ? "1ADD" : "2ADD"))) - quad.x18_ADD.write(w); +void DPSM::writeQuadDecalInfo(athena::io::YAMLDocWriter& w, const typename DPSM::SQuadDescr& quad, + bool first) const { + if (quad.x0_LFT) + if (auto rec = w.enterSubRecord((first ? "1LFT" : "2LFT"))) + quad.x0_LFT.write(w); + if (quad.x4_SZE) + if (auto rec = w.enterSubRecord((first ? "1SZE" : "2SZE"))) + quad.x4_SZE.write(w); + if (quad.x8_ROT) + if (auto rec = w.enterSubRecord((first ? "1ROT" : "2ROT"))) + quad.x8_ROT.write(w); + if (quad.xc_OFF) + if (auto rec = w.enterSubRecord((first ? "1OFF" : "2OFF"))) + quad.xc_OFF.write(w); + if (quad.x10_CLR) + if (auto rec = w.enterSubRecord((first ? "1CLR" : "2CLR"))) + quad.x10_CLR.write(w); + if (quad.x14_TEX) + if (auto rec = w.enterSubRecord((first ? "1TEX" : "2TEX"))) + quad.x14_TEX.write(w); + if (quad.x18_ADD) + if (auto rec = w.enterSubRecord((first ? "1ADD" : "2ADD"))) + quad.x18_ADD.write(w); } template -void DPSM::_binarySize(size_t& s) const -{ +void DPSM::_binarySize(size_t& s) const { + s += 4; + getQuadDecalBinarySize(s, x0_quad); + getQuadDecalBinarySize(s, x1c_quad); + if (x38_DMDL) { s += 4; - getQuadDecalBinarySize(s, x0_quad); - getQuadDecalBinarySize(s, x1c_quad); - if (x38_DMDL) - { - s += 4; - x38_DMDL.binarySize(s); - } - if (x48_DLFT) - { - s += 4; - x48_DLFT.binarySize(s); - } - if (x4c_DMOP) - { - s += 4; - x4c_DMOP.binarySize(s); - } - if (x50_DMRT) - { - s += 4; - x50_DMRT.binarySize(s); - } - if (x54_DMSC) - { - s += 4; - x54_DMSC.binarySize(s); - } - if (x58_DMCL) - { - x58_DMCL.binarySize(s); - } - if (x5c_24_DMAB) - s += 9; - if (x5c_25_DMOO) - s += 9; + x38_DMDL.binarySize(s); + } + if (x48_DLFT) { + s += 4; + x48_DLFT.binarySize(s); + } + if (x4c_DMOP) { + s += 4; + x4c_DMOP.binarySize(s); + } + if (x50_DMRT) { + s += 4; + x50_DMRT.binarySize(s); + } + if (x54_DMSC) { + s += 4; + x54_DMSC.binarySize(s); + } + if (x58_DMCL) { + x58_DMCL.binarySize(s); + } + if (x5c_24_DMAB) + s += 9; + if (x5c_25_DMOO) + s += 9; } template -void DPSM::getQuadDecalBinarySize(size_t& s, const typename DPSM::SQuadDescr& quad) const -{ - if (quad.x0_LFT) - { - s += 4; - quad.x0_LFT.binarySize(s); - } - if (quad.x4_SZE) - { - s += 4; - quad.x4_SZE.binarySize(s); - } - if (quad.x8_ROT) - { - s += 4; - quad.x8_ROT.binarySize(s); - } - if (quad.xc_OFF) - { - s += 4; - quad.xc_OFF.binarySize(s); - } - if (quad.x10_CLR) - { - s += 4; - quad.x10_CLR.binarySize(s); - } - if (quad.x14_TEX) - { - s += 4; - quad.x14_TEX.binarySize(s); - } - if (quad.x18_ADD) - { - s += 4; - quad.x18_ADD.binarySize(s); - } +void DPSM::getQuadDecalBinarySize(size_t& s, const typename DPSM::SQuadDescr& quad) const { + if (quad.x0_LFT) { + s += 4; + quad.x0_LFT.binarySize(s); + } + if (quad.x4_SZE) { + s += 4; + quad.x4_SZE.binarySize(s); + } + if (quad.x8_ROT) { + s += 4; + quad.x8_ROT.binarySize(s); + } + if (quad.xc_OFF) { + s += 4; + quad.xc_OFF.binarySize(s); + } + if (quad.x10_CLR) { + s += 4; + quad.x10_CLR.binarySize(s); + } + if (quad.x14_TEX) { + s += 4; + quad.x14_TEX.binarySize(s); + } + if (quad.x18_ADD) { + s += 4; + quad.x18_ADD.binarySize(s); + } } template -void DPSM::_read(athena::io::IStreamReader& r) -{ - uint32_t clsId; +void DPSM::_read(athena::io::IStreamReader& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId != SBIG('DPSM')) { + LogModule.report(logvisor::Warning, "non DPSM provided to DPSM parser"); + return; + } + bool loadFirstDesc = false; + r.readBytesToBuf(&clsId, 4); + while (clsId != SBIG('_END')) { + switch (clsId) { + case SBIG('1SZE'): + case SBIG('1LFT'): + case SBIG('1ROT'): + case SBIG('1OFF'): + case SBIG('1CLR'): + case SBIG('1TEX'): + case SBIG('1ADD'): + loadFirstDesc = true; + case SBIG('2SZE'): + case SBIG('2LFT'): + case SBIG('2ROT'): + case SBIG('2OFF'): + case SBIG('2CLR'): + case SBIG('2TEX'): + case SBIG('2ADD'): + if (loadFirstDesc) + readQuadDecalInfo(r, clsId, x0_quad); + else + readQuadDecalInfo(r, clsId, x1c_quad); + break; + case SBIG('DMDL'): + x38_DMDL.read(r); + break; + case SBIG('DLFT'): + x48_DLFT.read(r); + break; + case SBIG('DMOP'): + x4c_DMOP.read(r); + break; + case SBIG('DMRT'): + x50_DMRT.read(r); + break; + case SBIG('DMSC'): + x54_DMSC.read(r); + break; + case SBIG('DMCL'): + x58_DMCL.read(r); + break; + case SBIG('DMAB'): + r.readUint32(); + x5c_24_DMAB = r.readBool(); + break; + case SBIG('DMOO'): + r.readUint32(); + x5c_25_DMOO = r.readBool(); + break; + default: + LogModule.report(logvisor::Fatal, "Unknown DPSM class %.4s @%" PRIi64, &clsId, r.position()); + break; + } r.readBytesToBuf(&clsId, 4); - if (clsId != SBIG('DPSM')) - { - LogModule.report(logvisor::Warning, "non DPSM provided to DPSM parser"); - return; - } - bool loadFirstDesc = false; - r.readBytesToBuf(&clsId, 4); - while (clsId != SBIG('_END')) - { - switch(clsId) - { - case SBIG('1SZE'): - case SBIG('1LFT'): - case SBIG('1ROT'): - case SBIG('1OFF'): - case SBIG('1CLR'): - case SBIG('1TEX'): - case SBIG('1ADD'): - loadFirstDesc = true; - case SBIG('2SZE'): - case SBIG('2LFT'): - case SBIG('2ROT'): - case SBIG('2OFF'): - case SBIG('2CLR'): - case SBIG('2TEX'): - case SBIG('2ADD'): - if (loadFirstDesc) - readQuadDecalInfo(r, clsId, x0_quad); - else - readQuadDecalInfo(r, clsId, x1c_quad); - break; - case SBIG('DMDL'): - x38_DMDL.read(r); - break; - case SBIG('DLFT'): - x48_DLFT.read(r); - break; - case SBIG('DMOP'): - x4c_DMOP.read(r); - break; - case SBIG('DMRT'): - x50_DMRT.read(r); - break; - case SBIG('DMSC'): - x54_DMSC.read(r); - break; - case SBIG('DMCL'): - x58_DMCL.read(r); - break; - case SBIG('DMAB'): - r.readUint32(); - x5c_24_DMAB = r.readBool(); - break; - case SBIG('DMOO'): - r.readUint32(); - x5c_25_DMOO = r.readBool(); - break; - default: - LogModule.report(logvisor::Fatal, "Unknown DPSM class %.4s @%" PRIi64, &clsId, r.position()); - break; - } - r.readBytesToBuf(&clsId, 4); - } + } } template -void DPSM::_write(athena::io::IStreamWriter& w) const -{ - w.writeBytes("DPSM", 4); - writeQuadDecalInfo(w, x0_quad, true); - writeQuadDecalInfo(w, x1c_quad, false); - if (x38_DMDL) - { - w.writeBytes("DMDL", 4); - x38_DMDL.write(w); - } - if (x48_DLFT) - { - w.writeBytes("DLFT", 4); - x48_DLFT.write(w); - } - if (x4c_DMOP) - { - w.writeBytes("DMOP", 4); - x4c_DMOP.write(w); - } - if (x50_DMRT) - { - w.writeBytes("DMRT", 4); - x50_DMRT.write(w); - } - if (x54_DMSC) - { - w.writeBytes("DMSC", 4); - x54_DMSC.write(w); - } - if (x58_DMCL) - { - w.writeBytes("DMCL", 4); - x58_DMCL.write(w); - } - if (x5c_24_DMAB) - w.writeBytes("DMABCNST\x01", 9); - if (x5c_25_DMOO) - w.writeBytes("DMOOCNST\x01", 9); - w.writeBytes("_END", 4); +void DPSM::_write(athena::io::IStreamWriter& w) const { + w.writeBytes("DPSM", 4); + writeQuadDecalInfo(w, x0_quad, true); + writeQuadDecalInfo(w, x1c_quad, false); + if (x38_DMDL) { + w.writeBytes("DMDL", 4); + x38_DMDL.write(w); + } + if (x48_DLFT) { + w.writeBytes("DLFT", 4); + x48_DLFT.write(w); + } + if (x4c_DMOP) { + w.writeBytes("DMOP", 4); + x4c_DMOP.write(w); + } + if (x50_DMRT) { + w.writeBytes("DMRT", 4); + x50_DMRT.write(w); + } + if (x54_DMSC) { + w.writeBytes("DMSC", 4); + x54_DMSC.write(w); + } + if (x58_DMCL) { + w.writeBytes("DMCL", 4); + x58_DMCL.write(w); + } + if (x5c_24_DMAB) + w.writeBytes("DMABCNST\x01", 9); + if (x5c_25_DMOO) + w.writeBytes("DMOOCNST\x01", 9); + w.writeBytes("_END", 4); } template -void DPSM::writeQuadDecalInfo(athena::io::IStreamWriter& w, - const typename DPSM::SQuadDescr& quad, bool first) const -{ - if (quad.x0_LFT) - { - w.writeBytes((first ? "1LFT" : "2LFT"), 4); - quad.x0_LFT.write(w); - } - if (quad.x4_SZE) - { - w.writeBytes((first ? "1SZE" : "2SZE"), 4); - quad.x4_SZE.write(w); - } - if (quad.x8_ROT) - { - w.writeBytes((first ? "1ROT" : "2ROT"), 4); - quad.x8_ROT.write(w); - } - if (quad.xc_OFF) - { - w.writeBytes((first ? "1OFF" : "2OFF"), 4); - quad.xc_OFF.write(w); - } - if (quad.x10_CLR) - { - w.writeBytes((first ? "1CLR" : "2CLR"), 4); - quad.x10_CLR.write(w); - } - if (quad.x14_TEX) - { - w.writeBytes((first ? "1TEX" : "2TEX"), 4); - quad.x14_TEX.write(w); - } - if (quad.x18_ADD) - { - w.writeBytes((first ? "1ADD" : "2ADD"), 4); - quad.x18_ADD.write(w); - } +void DPSM::writeQuadDecalInfo(athena::io::IStreamWriter& w, const typename DPSM::SQuadDescr& quad, + bool first) const { + if (quad.x0_LFT) { + w.writeBytes((first ? "1LFT" : "2LFT"), 4); + quad.x0_LFT.write(w); + } + if (quad.x4_SZE) { + w.writeBytes((first ? "1SZE" : "2SZE"), 4); + quad.x4_SZE.write(w); + } + if (quad.x8_ROT) { + w.writeBytes((first ? "1ROT" : "2ROT"), 4); + quad.x8_ROT.write(w); + } + if (quad.xc_OFF) { + w.writeBytes((first ? "1OFF" : "2OFF"), 4); + quad.xc_OFF.write(w); + } + if (quad.x10_CLR) { + w.writeBytes((first ? "1CLR" : "2CLR"), 4); + quad.x10_CLR.write(w); + } + if (quad.x14_TEX) { + w.writeBytes((first ? "1TEX" : "2TEX"), 4); + quad.x14_TEX.write(w); + } + if (quad.x18_ADD) { + w.writeBytes((first ? "1ADD" : "2ADD"), 4); + quad.x18_ADD.write(w); + } } template -void DPSM::gatherDependencies(std::vector& pathsOut) const -{ - if (x0_quad.x14_TEX.m_elem) - x0_quad.x14_TEX.m_elem->gatherDependencies(pathsOut); - if (x1c_quad.x14_TEX.m_elem) - x1c_quad.x14_TEX.m_elem->gatherDependencies(pathsOut); - g_curSpec->flattenDependencies(x38_DMDL.id, pathsOut); +void DPSM::gatherDependencies(std::vector& pathsOut) const { + if (x0_quad.x14_TEX.m_elem) + x0_quad.x14_TEX.m_elem->gatherDependencies(pathsOut); + if (x1c_quad.x14_TEX.m_elem) + x1c_quad.x14_TEX.m_elem->gatherDependencies(pathsOut); + g_curSpec->flattenDependencies(x38_DMDL.id, pathsOut); } AT_SUBSPECIALIZE_DNA_YAML(DPSM) @@ -421,36 +380,32 @@ template struct DPSM; template struct DPSM; template -bool ExtractDPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - DPSM dpsm; - dpsm.read(rs); - athena::io::ToYAMLStream(dpsm, writer); - return true; - } - return false; +bool ExtractDPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + DPSM dpsm; + dpsm.read(rs); + athena::io::ToYAMLStream(dpsm, writer); + return true; + } + return false; } template bool ExtractDPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractDPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template -bool WriteDPSM(const DPSM& dpsm, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - dpsm.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; +bool WriteDPSM(const DPSM& dpsm, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + dpsm.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } template bool WriteDPSM(const DPSM& dpsm, const hecl::ProjectPath& outPath); template bool WriteDPSM(const DPSM& dpsm, const hecl::ProjectPath& outPath); - -} +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/DPSC.hpp b/DataSpec/DNACommon/DPSC.hpp index 2bb59763d..523cd64b5 100644 --- a/DataSpec/DNACommon/DPSC.hpp +++ b/DataSpec/DNACommon/DPSC.hpp @@ -4,46 +4,45 @@ #include "PAK.hpp" #include "athena/FileWriter.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template -struct DPSM : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA +struct DPSM : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA - struct SQuadDescr - { - IntElementFactory x0_LFT; - RealElementFactory x4_SZE; - RealElementFactory x8_ROT; - VectorElementFactory xc_OFF; - ColorElementFactory x10_CLR; - UVElementFactory x14_TEX; - BoolHelper x18_ADD; + struct SQuadDescr { + IntElementFactory x0_LFT; + RealElementFactory x4_SZE; + RealElementFactory x8_ROT; + VectorElementFactory xc_OFF; + ColorElementFactory x10_CLR; + UVElementFactory x14_TEX; + BoolHelper x18_ADD; + }; + + SQuadDescr x0_quad; + SQuadDescr x1c_quad; + ChildResourceFactory x38_DMDL; + IntElementFactory x48_DLFT; + VectorElementFactory x4c_DMOP; + VectorElementFactory x50_DMRT; + VectorElementFactory x54_DMSC; + ColorElementFactory x58_DMCL; + union { + struct { + bool x5c_24_DMAB : 1; + bool x5c_25_DMOO : 1; }; + uint8_t dummy; + }; + template + void readQuadDecalInfo(Reader& r, uint32_t clsId, SQuadDescr& quad); + void writeQuadDecalInfo(athena::io::YAMLDocWriter& w, const SQuadDescr& quad, bool first) const; + void getQuadDecalBinarySize(size_t& s, const SQuadDescr& desc) const; + void writeQuadDecalInfo(athena::io::IStreamWriter& w, const SQuadDescr& quad, bool first) const; - SQuadDescr x0_quad; - SQuadDescr x1c_quad; - ChildResourceFactory x38_DMDL; - IntElementFactory x48_DLFT; - VectorElementFactory x4c_DMOP; - VectorElementFactory x50_DMRT; - VectorElementFactory x54_DMSC; - ColorElementFactory x58_DMCL; - union - { - struct { bool x5c_24_DMAB : 1; bool x5c_25_DMOO : 1;}; - uint8_t dummy; - }; - template - void readQuadDecalInfo(Reader& r, uint32_t clsId, SQuadDescr& quad); - void writeQuadDecalInfo(athena::io::YAMLDocWriter& w, const SQuadDescr& quad, bool first) const; - void getQuadDecalBinarySize(size_t& s, const SQuadDescr& desc) const; - void writeQuadDecalInfo(athena::io::IStreamWriter& w, const SQuadDescr& quad, bool first) const; - - void gatherDependencies(std::vector&) const; + void gatherDependencies(std::vector&) const; }; template @@ -52,5 +51,4 @@ bool ExtractDPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteDPSM(const DPSM& dpsm, const hecl::ProjectPath& outPath); -} - +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/DeafBabe.cpp b/DataSpec/DNACommon/DeafBabe.cpp index e4d9d62c5..3ad8fcee9 100644 --- a/DataSpec/DNACommon/DeafBabe.cpp +++ b/DataSpec/DNACommon/DeafBabe.cpp @@ -6,260 +6,246 @@ #include "hecl/Blender/Connection.hpp" #include -namespace DataSpec -{ +namespace DataSpec { -template -void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, bool isDcln, atInt32 idx) -{ - os << "material_index = []\n" - "col_bm = bmesh.new()\n"; - for (const atVec3f& vert : db.verts) - { - zeus::simd_floats f(vert.simd); - os.format("col_bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]); +template +void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, bool isDcln, atInt32 idx) { + os << "material_index = []\n" + "col_bm = bmesh.new()\n"; + for (const atVec3f& vert : db.verts) { + zeus::simd_floats f(vert.simd); + os.format("col_bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]); + } + + os << "col_bm.verts.ensure_lookup_table()\n"; + + int triIdx = 0; + for (const typename DEAFBABE::Triangle& tri : db.triangleEdgeConnections) { + const typename DEAFBABE::Material& triMat = db.materials[db.triMats[triIdx++]]; + const typename DEAFBABE::Edge& edge0 = db.edgeVertConnections[tri.edges[0]]; + const typename DEAFBABE::Edge& edge1 = db.edgeVertConnections[tri.edges[1]]; + const typename DEAFBABE::Edge& edge2 = db.edgeVertConnections[tri.edges[2]]; + if (!edge0.verts[0] && !edge1.verts[0] && !edge2.verts[0]) + break; + + int vindices[3]; + vindices[2] = + (edge1.verts[0] != edge0.verts[0] && edge1.verts[0] != edge0.verts[1]) ? edge1.verts[0] : edge1.verts[1]; + + if (triMat.flipFace()) { + vindices[0] = edge0.verts[1]; + vindices[1] = edge0.verts[0]; + } else { + vindices[0] = edge0.verts[0]; + vindices[1] = edge0.verts[1]; } - os << "col_bm.verts.ensure_lookup_table()\n"; + os << "tri_verts = []\n"; + os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[0]); + os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[1]); + os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[2]); - int triIdx = 0; - for (const typename DEAFBABE::Triangle& tri : db.triangleEdgeConnections) - { - const typename DEAFBABE::Material& triMat = db.materials[db.triMats[triIdx++]]; - const typename DEAFBABE::Edge& edge0 = db.edgeVertConnections[tri.edges[0]]; - const typename DEAFBABE::Edge& edge1 = db.edgeVertConnections[tri.edges[1]]; - const typename DEAFBABE::Edge& edge2 = db.edgeVertConnections[tri.edges[2]]; - if (!edge0.verts[0] && !edge1.verts[0] && !edge2.verts[0]) - break; + os.format( + "face = col_bm.faces.get(tri_verts)\n" + "if face is None:\n" + " face = col_bm.faces.new(tri_verts)\n" + "else:\n" + " face = face.copy()\n" + " for i in range(3):\n" + " face.verts[i].co = tri_verts[i].co\n" + " col_bm.verts.ensure_lookup_table()\n" + "face.material_index = select_material(0x%016" PRIX64 + ")\n" + "face.smooth = False\n" + "\n", + atUint64(triMat.material)); + } - int vindices[3]; - vindices[2] = - (edge1.verts[0] != edge0.verts[0] && edge1.verts[0] != edge0.verts[1]) ? - edge1.verts[0] : edge1.verts[1]; + db.insertNoClimb(os); - if (triMat.flipFace()) - { - vindices[0] = edge0.verts[1]; - vindices[1] = edge0.verts[0]; - } - else - { - vindices[0] = edge0.verts[0]; - vindices[1] = edge0.verts[1]; - } + if (isDcln) + os.format("col_mesh = bpy.data.meshes.new('CMESH_%i')\n", idx); + else + os << "col_mesh = bpy.data.meshes.new('CMESH')\n"; - os << "tri_verts = []\n"; - os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[0]); - os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[1]); - os.format("tri_verts.append(col_bm.verts[%u])\n", vindices[2]); + os << "col_bm.to_mesh(col_mesh)\n" + "col_mesh_obj = bpy.data.objects.new(col_mesh.name, col_mesh)\n" + "\n" + "for mat_name in material_index:\n" + " mat = material_dict[mat_name]\n" + " col_mesh.materials.append(mat)\n" + "\n" + "bpy.context.scene.objects.link(col_mesh_obj)\n" + "bpy.context.scene.objects.active = col_mesh_obj\n" + "bpy.ops.object.mode_set(mode='EDIT')\n" + "bpy.ops.mesh.tris_convert_to_quads()\n" + "bpy.ops.object.mode_set(mode='OBJECT')\n" + "bpy.context.scene.objects.active = None\n"; + if (!isDcln) + os << "col_mesh_obj.layers[1] = True\n" + "col_mesh_obj.layers[0] = False\n"; - os.format("face = col_bm.faces.get(tri_verts)\n" - "if face is None:\n" - " face = col_bm.faces.new(tri_verts)\n" - "else:\n" - " face = face.copy()\n" - " for i in range(3):\n" - " face.verts[i].co = tri_verts[i].co\n" - " col_bm.verts.ensure_lookup_table()\n" - "face.material_index = select_material(0x%016" PRIX64 ")\n" - "face.smooth = False\n" - "\n", - atUint64(triMat.material)); - } - - db.insertNoClimb(os); - - if (isDcln) - os.format("col_mesh = bpy.data.meshes.new('CMESH_%i')\n", idx); - else - os << "col_mesh = bpy.data.meshes.new('CMESH')\n"; - - os << "col_bm.to_mesh(col_mesh)\n" - "col_mesh_obj = bpy.data.objects.new(col_mesh.name, col_mesh)\n" - "\n" - "for mat_name in material_index:\n" - " mat = material_dict[mat_name]\n" - " col_mesh.materials.append(mat)\n" - "\n" - "bpy.context.scene.objects.link(col_mesh_obj)\n" - "bpy.context.scene.objects.active = col_mesh_obj\n" - "bpy.ops.object.mode_set(mode='EDIT')\n" - "bpy.ops.mesh.tris_convert_to_quads()\n" - "bpy.ops.object.mode_set(mode='OBJECT')\n" - "bpy.context.scene.objects.active = None\n"; - if (!isDcln) - os << "col_mesh_obj.layers[1] = True\n" - "col_mesh_obj.layers[0] = False\n"; - - - os << "col_mesh_obj.draw_type = 'SOLID'\n" - "col_mesh_obj.game.physics_type = 'STATIC'\n" - "\n"; + os << "col_mesh_obj.draw_type = 'SOLID'\n" + "col_mesh_obj.game.physics_type = 'STATIC'\n" + "\n"; } -template void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DNAMP1::DeafBabe& db, bool isDcln, atInt32 idx); -template void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DNAMP2::DeafBabe& db, bool isDcln, atInt32 idx); -template void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DNAMP1::DCLN::Collision& db, bool isDcln, atInt32 idx); +template void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DNAMP1::DeafBabe& db, + bool isDcln, atInt32 idx); +template void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DNAMP2::DeafBabe& db, + bool isDcln, atInt32 idx); +template void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, + const DNAMP1::DCLN::Collision& db, bool isDcln, + atInt32 idx); -template -static void PopulateAreaFields(DEAFBABE& db, - const hecl::blender::ColMesh& colMesh, - const zeus::CAABox& fullAABB, - std::enable_if_t::value || - std::is_same::value, int>* = 0) -{ - AROTBuilder builder; - auto octree = builder.buildCol(colMesh, db.rootNodeType); - static_cast&>(db.bspTree) = std::move(octree.first); - db.bspSize = octree.second; +template +static void PopulateAreaFields( + DEAFBABE& db, const hecl::blender::ColMesh& colMesh, const zeus::CAABox& fullAABB, + std::enable_if_t::value || std::is_same::value, + int>* = 0) { + AROTBuilder builder; + auto octree = builder.buildCol(colMesh, db.rootNodeType); + static_cast&>(db.bspTree) = std::move(octree.first); + db.bspSize = octree.second; - db.unk1 = 0x1000000; - size_t dbSize = 0; - db.binarySize(dbSize); - db.length = dbSize - 8; - db.magic = 0xDEAFBABE; - db.version = 3; - db.aabb[0] = fullAABB.min; - db.aabb[1] = fullAABB.max; + db.unk1 = 0x1000000; + size_t dbSize = 0; + db.binarySize(dbSize); + db.length = dbSize - 8; + db.magic = 0xDEAFBABE; + db.version = 3; + db.aabb[0] = fullAABB.min; + db.aabb[1] = fullAABB.max; } -template -static void PopulateAreaFields(DEAFBABE& db, - const hecl::blender::ColMesh& colMesh, - const zeus::CAABox& fullAABB, - std::enable_if_t::value, int>* = 0) -{ - db.magic = 0xDEAFBABE; - db.version = 2; - db.memSize = 0; +template +static void PopulateAreaFields(DEAFBABE& db, const hecl::blender::ColMesh& colMesh, const zeus::CAABox& fullAABB, + std::enable_if_t::value, int>* = 0) { + db.magic = 0xDEAFBABE; + db.version = 2; + db.memSize = 0; } -class MaterialPool -{ - std::unordered_map m_materials; +class MaterialPool { + std::unordered_map m_materials; + public: - template - int AddOrLookup(const M& mat, V& vec) - { - auto search = m_materials.find(mat.material); - if (search != m_materials.end()) - return search->second; - auto idx = int(vec.size()); - vec.push_back(mat); - m_materials[mat.material] = idx; - return idx; - } + template + int AddOrLookup(const M& mat, V& vec) { + auto search = m_materials.find(mat.material); + if (search != m_materials.end()) + return search->second; + auto idx = int(vec.size()); + vec.push_back(mat); + m_materials[mat.material] = idx; + return idx; + } }; -template -void DeafBabeBuildFromBlender(DEAFBABE& db, const hecl::blender::ColMesh& colMesh) -{ - using BlendMat = hecl::blender::ColMesh::Material; +template +void DeafBabeBuildFromBlender(DEAFBABE& db, const hecl::blender::ColMesh& colMesh) { + using BlendMat = hecl::blender::ColMesh::Material; - auto MakeMat = [](const BlendMat& mat, bool flipFace) -> typename DEAFBABE::Material - { - typename DEAFBABE::Material dbMat = {}; - dbMat.setUnknown(mat.unknown); - dbMat.setSurfaceStone(mat.surfaceStone); - dbMat.setSurfaceMetal(mat.surfaceMetal); - dbMat.setSurfaceGrass(mat.surfaceGrass); - dbMat.setSurfaceIce(mat.surfaceIce); - dbMat.setPillar(mat.pillar); - dbMat.setSurfaceMetalGrating(mat.surfaceMetalGrating); - dbMat.setSurfacePhazon(mat.surfacePhazon); - dbMat.setSurfaceDirt(mat.surfaceDirt); - dbMat.setSurfaceLava(mat.surfaceLava); - dbMat.setSurfaceSPMetal(mat.surfaceSPMetal); - dbMat.setSurfaceLavaStone(mat.surfaceLavaStone); - dbMat.setSurfaceSnow(mat.surfaceSnow); - dbMat.setSurfaceMudSlow(mat.surfaceMudSlow); - dbMat.setSurfaceFabric(mat.surfaceFabric); - dbMat.setHalfPipe(mat.halfPipe); - dbMat.setSurfaceMud(mat.surfaceMud); - dbMat.setSurfaceGlass(mat.surfaceGlass); - dbMat.setUnused3(mat.unused3); - dbMat.setUnused4(mat.unused4); - dbMat.setSurfaceShield(mat.surfaceShield); - dbMat.setSurfaceSand(mat.surfaceSand); - dbMat.setSurfaceMothOrSeedOrganics(mat.surfaceMothOrSeedOrganics); - dbMat.setSurfaceWeb(mat.surfaceWeb); - dbMat.setProjectilePassthrough(mat.projPassthrough); - dbMat.setSolid(mat.solid); - dbMat.setNoPlatformCollision(mat.noPlatformCollision); - dbMat.setCameraPassthrough(mat.camPassthrough); - dbMat.setSurfaceWood(mat.surfaceWood); - dbMat.setSurfaceOrganic(mat.surfaceOrganic); - dbMat.setNoEdgeCollision(mat.noEdgeCollision); - dbMat.setSurfaceRubber(mat.surfaceRubber); - dbMat.setSeeThrough(mat.seeThrough); - dbMat.setScanPassthrough(mat.scanPassthrough); - dbMat.setAiPassthrough(mat.aiPassthrough); - dbMat.setCeiling(mat.ceiling); - dbMat.setWall(mat.wall); - dbMat.setFloor(mat.floor); - dbMat.setAiBlock(mat.aiBlock); - dbMat.setJumpNotAllowed(mat.jumpNotAllowed); - dbMat.setSpiderBall(mat.spiderBall); - dbMat.setScrewAttackWallJump(mat.screwAttackWallJump); - dbMat.setFlipFace(flipFace); - return dbMat; - }; + auto MakeMat = [](const BlendMat& mat, bool flipFace) -> typename DEAFBABE::Material { + typename DEAFBABE::Material dbMat = {}; + dbMat.setUnknown(mat.unknown); + dbMat.setSurfaceStone(mat.surfaceStone); + dbMat.setSurfaceMetal(mat.surfaceMetal); + dbMat.setSurfaceGrass(mat.surfaceGrass); + dbMat.setSurfaceIce(mat.surfaceIce); + dbMat.setPillar(mat.pillar); + dbMat.setSurfaceMetalGrating(mat.surfaceMetalGrating); + dbMat.setSurfacePhazon(mat.surfacePhazon); + dbMat.setSurfaceDirt(mat.surfaceDirt); + dbMat.setSurfaceLava(mat.surfaceLava); + dbMat.setSurfaceSPMetal(mat.surfaceSPMetal); + dbMat.setSurfaceLavaStone(mat.surfaceLavaStone); + dbMat.setSurfaceSnow(mat.surfaceSnow); + dbMat.setSurfaceMudSlow(mat.surfaceMudSlow); + dbMat.setSurfaceFabric(mat.surfaceFabric); + dbMat.setHalfPipe(mat.halfPipe); + dbMat.setSurfaceMud(mat.surfaceMud); + dbMat.setSurfaceGlass(mat.surfaceGlass); + dbMat.setUnused3(mat.unused3); + dbMat.setUnused4(mat.unused4); + dbMat.setSurfaceShield(mat.surfaceShield); + dbMat.setSurfaceSand(mat.surfaceSand); + dbMat.setSurfaceMothOrSeedOrganics(mat.surfaceMothOrSeedOrganics); + dbMat.setSurfaceWeb(mat.surfaceWeb); + dbMat.setProjectilePassthrough(mat.projPassthrough); + dbMat.setSolid(mat.solid); + dbMat.setNoPlatformCollision(mat.noPlatformCollision); + dbMat.setCameraPassthrough(mat.camPassthrough); + dbMat.setSurfaceWood(mat.surfaceWood); + dbMat.setSurfaceOrganic(mat.surfaceOrganic); + dbMat.setNoEdgeCollision(mat.noEdgeCollision); + dbMat.setSurfaceRubber(mat.surfaceRubber); + dbMat.setSeeThrough(mat.seeThrough); + dbMat.setScanPassthrough(mat.scanPassthrough); + dbMat.setAiPassthrough(mat.aiPassthrough); + dbMat.setCeiling(mat.ceiling); + dbMat.setWall(mat.wall); + dbMat.setFloor(mat.floor); + dbMat.setAiBlock(mat.aiBlock); + dbMat.setJumpNotAllowed(mat.jumpNotAllowed); + dbMat.setSpiderBall(mat.spiderBall); + dbMat.setScrewAttackWallJump(mat.screwAttackWallJump); + dbMat.setFlipFace(flipFace); + return dbMat; + }; - MaterialPool matPool; - db.materials.reserve(colMesh.materials.size() * 2); + MaterialPool matPool; + db.materials.reserve(colMesh.materials.size() * 2); - zeus::CAABox fullAABB; + zeus::CAABox fullAABB; - db.verts.reserve(colMesh.verts.size()); - db.vertMats.resize(colMesh.verts.size()); - for (const auto& vert : colMesh.verts) - { - fullAABB.accumulateBounds(zeus::CVector3f(vert)); - db.verts.push_back(vert); + db.verts.reserve(colMesh.verts.size()); + db.vertMats.resize(colMesh.verts.size()); + for (const auto& vert : colMesh.verts) { + fullAABB.accumulateBounds(zeus::CVector3f(vert)); + db.verts.push_back(vert); + } + db.vertMatsCount = colMesh.verts.size(); + db.vertCount = colMesh.verts.size(); + + db.edgeVertConnections.reserve(colMesh.edges.size()); + db.edgeMats.resize(colMesh.edges.size()); + for (const auto& edge : colMesh.edges) { + db.edgeVertConnections.emplace_back(); + db.edgeVertConnections.back().verts[0] = edge.verts[0]; + db.edgeVertConnections.back().verts[1] = edge.verts[1]; + } + db.edgeMatsCount = colMesh.edges.size(); + db.edgeVertsCount = colMesh.edges.size(); + + db.triMats.reserve(colMesh.trianges.size()); + db.triangleEdgeConnections.reserve(colMesh.trianges.size()); + for (const auto& tri : colMesh.trianges) { + int triMatIdx = matPool.AddOrLookup(MakeMat(colMesh.materials[tri.matIdx], tri.flip), db.materials); + db.triMats.push_back(triMatIdx); + + db.triangleEdgeConnections.emplace_back(); + db.triangleEdgeConnections.back().edges[0] = tri.edges[0]; + db.triangleEdgeConnections.back().edges[1] = tri.edges[1]; + db.triangleEdgeConnections.back().edges[2] = tri.edges[2]; + + for (int e = 0; e < 3; ++e) { + db.edgeMats[tri.edges[e]] = triMatIdx; + for (int v = 0; v < 2; ++v) + db.vertMats[colMesh.edges[e].verts[v]] = triMatIdx; } - db.vertMatsCount = colMesh.verts.size(); - db.vertCount = colMesh.verts.size(); + } + db.triMatsCount = colMesh.trianges.size(); + db.triangleEdgesCount = colMesh.trianges.size() * 3; - db.edgeVertConnections.reserve(colMesh.edges.size()); - db.edgeMats.resize(colMesh.edges.size()); - for (const auto& edge : colMesh.edges) - { - db.edgeVertConnections.emplace_back(); - db.edgeVertConnections.back().verts[0] = edge.verts[0]; - db.edgeVertConnections.back().verts[1] = edge.verts[1]; - } - db.edgeMatsCount = colMesh.edges.size(); - db.edgeVertsCount = colMesh.edges.size(); + db.materialCount = db.materials.size(); - db.triMats.reserve(colMesh.trianges.size()); - db.triangleEdgeConnections.reserve(colMesh.trianges.size()); - for (const auto& tri : colMesh.trianges) - { - int triMatIdx = matPool.AddOrLookup(MakeMat(colMesh.materials[tri.matIdx], tri.flip), db.materials); - db.triMats.push_back(triMatIdx); - - db.triangleEdgeConnections.emplace_back(); - db.triangleEdgeConnections.back().edges[0] = tri.edges[0]; - db.triangleEdgeConnections.back().edges[1] = tri.edges[1]; - db.triangleEdgeConnections.back().edges[2] = tri.edges[2]; - - for (int e=0 ; e<3 ; ++e) - { - db.edgeMats[tri.edges[e]] = triMatIdx; - for (int v=0 ; v<2 ; ++v) - db.vertMats[colMesh.edges[e].verts[v]] = triMatIdx; - } - } - db.triMatsCount = colMesh.trianges.size(); - db.triangleEdgesCount = colMesh.trianges.size() * 3; - - db.materialCount = db.materials.size(); - - PopulateAreaFields(db, colMesh, fullAABB); + PopulateAreaFields(db, colMesh, fullAABB); } template void DeafBabeBuildFromBlender(DNAMP1::DeafBabe& db, const hecl::blender::ColMesh& colMesh); template void DeafBabeBuildFromBlender(DNAMP2::DeafBabe& db, const hecl::blender::ColMesh& colMesh); -template void DeafBabeBuildFromBlender(DNAMP1::DCLN::Collision& db, const hecl::blender::ColMesh& colMesh); +template void DeafBabeBuildFromBlender(DNAMP1::DCLN::Collision& db, + const hecl::blender::ColMesh& colMesh); -} +} // namespace DataSpec diff --git a/DataSpec/DNACommon/DeafBabe.hpp b/DataSpec/DNACommon/DeafBabe.hpp index bd802bf53..99f56f129 100644 --- a/DataSpec/DNACommon/DeafBabe.hpp +++ b/DataSpec/DNACommon/DeafBabe.hpp @@ -2,21 +2,14 @@ #include "DNACommon.hpp" -namespace DataSpec -{ +namespace DataSpec { -enum class BspNodeType : atUint32 -{ - Invalid, - Branch, - Leaf -}; +enum class BspNodeType : atUint32 { Invalid, Branch, Leaf }; -template +template void DeafBabeSendToBlender(hecl::blender::PyOutStream& os, const DEAFBABE& db, bool isDcln = false, atInt32 idx = -1); -template +template void DeafBabeBuildFromBlender(DEAFBABE& db, const hecl::blender::ColMesh& colMesh); -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/EGMC.hpp b/DataSpec/DNACommon/EGMC.hpp index d0bba8134..ce3c3e608 100644 --- a/DataSpec/DNACommon/EGMC.hpp +++ b/DataSpec/DNACommon/EGMC.hpp @@ -2,20 +2,17 @@ #include "DNACommon.hpp" -namespace DataSpec::DNACommon -{ -struct EGMC : public BigDNA -{ +namespace DataSpec::DNACommon { +struct EGMC : public BigDNA { + AT_DECL_DNA + Value count; + + struct Object : BigDNA { AT_DECL_DNA - Value count; + Value mesh; + Value instanceId; + }; - struct Object : BigDNA - { - AT_DECL_DNA - Value mesh; - Value instanceId; - }; - - Vector objects; + Vector objects; }; -} +} // namespace DataSpec::DNACommon diff --git a/DataSpec/DNACommon/ELSC.cpp b/DataSpec/DNACommon/ELSC.cpp index 0157f9eed..43f09fb06 100644 --- a/DataSpec/DNACommon/ELSC.cpp +++ b/DataSpec/DNACommon/ELSC.cpp @@ -1,502 +1,449 @@ #include "ELSC.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template -void ELSM::_read(athena::io::IStreamReader& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId != SBIG('ELSM')) - { - LogModule.report(logvisor::Warning, "non ELSM provided to ELSM parser"); - return; - } +void ELSM::_read(athena::io::IStreamReader& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId != SBIG('ELSM')) { + LogModule.report(logvisor::Warning, "non ELSM provided to ELSM parser"); + return; + } - r.readBytesToBuf(&clsId, 4); - while (clsId != SBIG('_END')) - { - switch(clsId) - { - case SBIG('LIFE'): - x0_LIFE.read(r); - break; - case SBIG('SLIF'): - x4_SLIF.read(r); - break; - case SBIG('GRAT'): - x8_GRAT.read(r); - break; - case SBIG('SCNT'): - xc_SCNT.read(r); - break; - case SBIG('SSEG'): - x10_SSEG.read(r); - break; - case SBIG('COLR'): - x14_COLR.read(r); - break; - case SBIG('IEMT'): - x18_IEMT.read(r); - break; - case SBIG('FEMT'): - x1c_FEMT.read(r); - break; - case SBIG('AMPL'): - x20_AMPL.read(r); - break; - case SBIG('AMPD'): - x24_AMPD.read(r); - break; - case SBIG('LWD1'): - x28_LWD1.read(r); - break; - case SBIG('LWD2'): - x2c_LWD2.read(r); - break; - case SBIG('LWD3'): - x30_LWD3.read(r); - break; - case SBIG('LCL1'): - x34_LCL1.read(r); - break; - case SBIG('LCL2'): - x38_LCL2.read(r); - break; - case SBIG('LCL3'): - x3c_LCL3.read(r); - break; - case SBIG('SSWH'): - x40_SSWH.read(r); - break; - case SBIG('GPSM'): - x50_GPSM.read(r); - break; - case SBIG('EPSM'): - x60_EPSM.read(r); - break; - case SBIG('ZERY'): - x70_ZERY.read(r); - break; - default: - LogModule.report(logvisor::Fatal, "Unknown ELSM class %.4s @%" PRIi64, &clsId, r.position()); - break; - } - r.readBytesToBuf(&clsId, 4); + r.readBytesToBuf(&clsId, 4); + while (clsId != SBIG('_END')) { + switch (clsId) { + case SBIG('LIFE'): + x0_LIFE.read(r); + break; + case SBIG('SLIF'): + x4_SLIF.read(r); + break; + case SBIG('GRAT'): + x8_GRAT.read(r); + break; + case SBIG('SCNT'): + xc_SCNT.read(r); + break; + case SBIG('SSEG'): + x10_SSEG.read(r); + break; + case SBIG('COLR'): + x14_COLR.read(r); + break; + case SBIG('IEMT'): + x18_IEMT.read(r); + break; + case SBIG('FEMT'): + x1c_FEMT.read(r); + break; + case SBIG('AMPL'): + x20_AMPL.read(r); + break; + case SBIG('AMPD'): + x24_AMPD.read(r); + break; + case SBIG('LWD1'): + x28_LWD1.read(r); + break; + case SBIG('LWD2'): + x2c_LWD2.read(r); + break; + case SBIG('LWD3'): + x30_LWD3.read(r); + break; + case SBIG('LCL1'): + x34_LCL1.read(r); + break; + case SBIG('LCL2'): + x38_LCL2.read(r); + break; + case SBIG('LCL3'): + x3c_LCL3.read(r); + break; + case SBIG('SSWH'): + x40_SSWH.read(r); + break; + case SBIG('GPSM'): + x50_GPSM.read(r); + break; + case SBIG('EPSM'): + x60_EPSM.read(r); + break; + case SBIG('ZERY'): + x70_ZERY.read(r); + break; + default: + LogModule.report(logvisor::Fatal, "Unknown ELSM class %.4s @%" PRIi64, &clsId, r.position()); + break; } + r.readBytesToBuf(&clsId, 4); + } } template -void ELSM::_write(athena::io::IStreamWriter& w) const -{ - w.writeBytes((atInt8*)"ELSM", 4); - if (x0_LIFE) - { - w.writeBytes((atInt8*)"LIFE", 4); - x0_LIFE.write(w); - } - if (x4_SLIF) - { - w.writeBytes((atInt8*)"SLIF", 4); - x4_SLIF.write(w); - } - if (x8_GRAT) - { - w.writeBytes((atInt8*)"GRAT", 4); - x8_GRAT.write(w); - } - if (xc_SCNT) - { - w.writeBytes((atInt8*)"SCNT", 4); - xc_SCNT.write(w); - } - if (x10_SSEG) - { - w.writeBytes((atInt8*)"SSEG", 4); - x10_SSEG.write(w); - } - if (x14_COLR) - { - w.writeBytes((atInt8*)"COLR", 4); - x14_COLR.write(w); - } - if (x18_IEMT) - { - w.writeBytes((atInt8*)"IEMT", 4); - x18_IEMT.write(w); - } - if (x1c_FEMT) - { - w.writeBytes((atInt8*)"FEMT", 4); - x1c_FEMT.write(w); - } - if (x20_AMPL) - { - w.writeBytes((atInt8*)"AMPL", 4); - x20_AMPL.write(w); - } - if (x24_AMPD) - { - w.writeBytes((atInt8*)"AMPD", 4); - x24_AMPD.write(w); - } - if (x28_LWD1) - { - w.writeBytes((atInt8*)"LWD1", 4); - x28_LWD1.write(w); - } - if (x2c_LWD2) - { - w.writeBytes((atInt8*)"LWD2", 4); - x2c_LWD2.write(w); - } - if (x30_LWD3) - { - w.writeBytes((atInt8*)"LWD3", 4); - x30_LWD3.write(w); - } - if (x34_LCL1) - { - w.writeBytes((atInt8*)"LCL1", 4); - x34_LCL1.write(w); - } - if (x38_LCL2) - { - w.writeBytes((atInt8*)"LCL2", 4); - x38_LCL2.write(w); - } - if (x3c_LCL3) - { - w.writeBytes((atInt8*)"LCL3", 4); - x3c_LCL3.write(w); - } - if (x40_SSWH) - { - w.writeBytes((atInt8*)"SSWH", 4); - x40_SSWH.write(w); - } - if (x50_GPSM) - { - w.writeBytes((atInt8*)"GPSM", 4); - x50_GPSM.write(w); - } - if (x60_EPSM) - { - w.writeBytes((atInt8*)"EPSM", 4); - x60_EPSM.write(w); - } - if (x70_ZERY) - { - w.writeBytes((atInt8*)"ZERY", 4); - x70_ZERY.write(w); - } - w.writeBytes("_END", 4); +void ELSM::_write(athena::io::IStreamWriter& w) const { + w.writeBytes((atInt8*)"ELSM", 4); + if (x0_LIFE) { + w.writeBytes((atInt8*)"LIFE", 4); + x0_LIFE.write(w); + } + if (x4_SLIF) { + w.writeBytes((atInt8*)"SLIF", 4); + x4_SLIF.write(w); + } + if (x8_GRAT) { + w.writeBytes((atInt8*)"GRAT", 4); + x8_GRAT.write(w); + } + if (xc_SCNT) { + w.writeBytes((atInt8*)"SCNT", 4); + xc_SCNT.write(w); + } + if (x10_SSEG) { + w.writeBytes((atInt8*)"SSEG", 4); + x10_SSEG.write(w); + } + if (x14_COLR) { + w.writeBytes((atInt8*)"COLR", 4); + x14_COLR.write(w); + } + if (x18_IEMT) { + w.writeBytes((atInt8*)"IEMT", 4); + x18_IEMT.write(w); + } + if (x1c_FEMT) { + w.writeBytes((atInt8*)"FEMT", 4); + x1c_FEMT.write(w); + } + if (x20_AMPL) { + w.writeBytes((atInt8*)"AMPL", 4); + x20_AMPL.write(w); + } + if (x24_AMPD) { + w.writeBytes((atInt8*)"AMPD", 4); + x24_AMPD.write(w); + } + if (x28_LWD1) { + w.writeBytes((atInt8*)"LWD1", 4); + x28_LWD1.write(w); + } + if (x2c_LWD2) { + w.writeBytes((atInt8*)"LWD2", 4); + x2c_LWD2.write(w); + } + if (x30_LWD3) { + w.writeBytes((atInt8*)"LWD3", 4); + x30_LWD3.write(w); + } + if (x34_LCL1) { + w.writeBytes((atInt8*)"LCL1", 4); + x34_LCL1.write(w); + } + if (x38_LCL2) { + w.writeBytes((atInt8*)"LCL2", 4); + x38_LCL2.write(w); + } + if (x3c_LCL3) { + w.writeBytes((atInt8*)"LCL3", 4); + x3c_LCL3.write(w); + } + if (x40_SSWH) { + w.writeBytes((atInt8*)"SSWH", 4); + x40_SSWH.write(w); + } + if (x50_GPSM) { + w.writeBytes((atInt8*)"GPSM", 4); + x50_GPSM.write(w); + } + if (x60_EPSM) { + w.writeBytes((atInt8*)"EPSM", 4); + x60_EPSM.write(w); + } + if (x70_ZERY) { + w.writeBytes((atInt8*)"ZERY", 4); + x70_ZERY.write(w); + } + w.writeBytes("_END", 4); } template -void ELSM::_binarySize(size_t& s) const -{ +void ELSM::_binarySize(size_t& s) const { + s += 4; + if (x0_LIFE) { s += 4; - if (x0_LIFE) - { - s += 4; - x0_LIFE.binarySize(s); - } - if (x4_SLIF) - { - s += 4; - x4_SLIF.binarySize(s); - } - if (x8_GRAT) - { - s += 4; - x8_GRAT.binarySize(s); - } - if (xc_SCNT) - { - s += 4; - xc_SCNT.binarySize(s); - } - if (x10_SSEG) - { - s += 4; - x10_SSEG.binarySize(s); - } - if (x14_COLR) - { - s += 4; - x14_COLR.binarySize(s); - } - if (x18_IEMT) - { - s += 4; - x18_IEMT.binarySize(s); - } - if (x1c_FEMT) - { - s += 4; - x1c_FEMT.binarySize(s); - } - if (x20_AMPL) - { - s += 4; - x20_AMPL.binarySize(s); - } - if (x24_AMPD) - { - s += 4; - x24_AMPD.binarySize(s); - } - if (x28_LWD1) - { - s += 4; - x28_LWD1.binarySize(s); - } - if (x2c_LWD2) - { - s += 4; - x2c_LWD2.binarySize(s); - } - if (x30_LWD3) - { - s += 4; - x30_LWD3.binarySize(s); - } - if (x34_LCL1) - { - s += 4; - x34_LCL1.binarySize(s); - } - if (x38_LCL2) - { - s += 4; - x38_LCL2.binarySize(s); - } - if (x3c_LCL3) - { - s += 4; - x3c_LCL3.binarySize(s); - } - if (x40_SSWH) - { - s += 4; - x40_SSWH.binarySize(s); - } - if (x50_GPSM) - { - s += 4; - x50_GPSM.binarySize(s); - } - if (x60_EPSM) - { - s += 4; - x60_EPSM.binarySize(s); - } - if (x70_ZERY) - { - s += 4; - x70_ZERY.binarySize(s); - } + x0_LIFE.binarySize(s); + } + if (x4_SLIF) { + s += 4; + x4_SLIF.binarySize(s); + } + if (x8_GRAT) { + s += 4; + x8_GRAT.binarySize(s); + } + if (xc_SCNT) { + s += 4; + xc_SCNT.binarySize(s); + } + if (x10_SSEG) { + s += 4; + x10_SSEG.binarySize(s); + } + if (x14_COLR) { + s += 4; + x14_COLR.binarySize(s); + } + if (x18_IEMT) { + s += 4; + x18_IEMT.binarySize(s); + } + if (x1c_FEMT) { + s += 4; + x1c_FEMT.binarySize(s); + } + if (x20_AMPL) { + s += 4; + x20_AMPL.binarySize(s); + } + if (x24_AMPD) { + s += 4; + x24_AMPD.binarySize(s); + } + if (x28_LWD1) { + s += 4; + x28_LWD1.binarySize(s); + } + if (x2c_LWD2) { + s += 4; + x2c_LWD2.binarySize(s); + } + if (x30_LWD3) { + s += 4; + x30_LWD3.binarySize(s); + } + if (x34_LCL1) { + s += 4; + x34_LCL1.binarySize(s); + } + if (x38_LCL2) { + s += 4; + x38_LCL2.binarySize(s); + } + if (x3c_LCL3) { + s += 4; + x3c_LCL3.binarySize(s); + } + if (x40_SSWH) { + s += 4; + x40_SSWH.binarySize(s); + } + if (x50_GPSM) { + s += 4; + x50_GPSM.binarySize(s); + } + if (x60_EPSM) { + s += 4; + x60_EPSM.binarySize(s); + } + if (x70_ZERY) { + s += 4; + x70_ZERY.binarySize(s); + } } template -void ELSM::_read(athena::io::YAMLDocReader& r) -{ - for (const auto& elem : r.getCurNode()->m_mapChildren) - { - if (elem.first.size() < 4) - { - LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); - continue; - } - - if (auto rec = r.enterSubRecord(elem.first.c_str())) - { - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('LIFE'): - x0_LIFE.read(r); - break; - case SBIG('SLIF'): - x4_SLIF.read(r); - break; - case SBIG('GRAT'): - x8_GRAT.read(r); - break; - case SBIG('SCNT'): - xc_SCNT.read(r); - break; - case SBIG('SSEG'): - x10_SSEG.read(r); - break; - case SBIG('COLR'): - x14_COLR.read(r); - break; - case SBIG('IEMT'): - x18_IEMT.read(r); - break; - case SBIG('FEMT'): - x1c_FEMT.read(r); - break; - case SBIG('AMPL'): - x20_AMPL.read(r); - break; - case SBIG('AMPD'): - x24_AMPD.read(r); - break; - case SBIG('LWD1'): - x28_LWD1.read(r); - break; - case SBIG('LWD2'): - x2c_LWD2.read(r); - break; - case SBIG('LWD3'): - x30_LWD3.read(r); - break; - case SBIG('LCL1'): - x34_LCL1.read(r); - break; - case SBIG('LCL2'): - x38_LCL2.read(r); - break; - case SBIG('LCL3'): - x3c_LCL3.read(r); - break; - case SBIG('SSWH'): - x40_SSWH.read(r); - break; - case SBIG('GPSM'): - x50_GPSM.read(r); - break; - case SBIG('EPSM'): - x60_EPSM.read(r); - break; - case SBIG('ZERY'): - x70_ZERY.read(r); - break; - default: - break; - } - } +void ELSM::_read(athena::io::YAMLDocReader& r) { + for (const auto& elem : r.getCurNode()->m_mapChildren) { + if (elem.first.size() < 4) { + LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); + continue; } + + if (auto rec = r.enterSubRecord(elem.first.c_str())) { + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('LIFE'): + x0_LIFE.read(r); + break; + case SBIG('SLIF'): + x4_SLIF.read(r); + break; + case SBIG('GRAT'): + x8_GRAT.read(r); + break; + case SBIG('SCNT'): + xc_SCNT.read(r); + break; + case SBIG('SSEG'): + x10_SSEG.read(r); + break; + case SBIG('COLR'): + x14_COLR.read(r); + break; + case SBIG('IEMT'): + x18_IEMT.read(r); + break; + case SBIG('FEMT'): + x1c_FEMT.read(r); + break; + case SBIG('AMPL'): + x20_AMPL.read(r); + break; + case SBIG('AMPD'): + x24_AMPD.read(r); + break; + case SBIG('LWD1'): + x28_LWD1.read(r); + break; + case SBIG('LWD2'): + x2c_LWD2.read(r); + break; + case SBIG('LWD3'): + x30_LWD3.read(r); + break; + case SBIG('LCL1'): + x34_LCL1.read(r); + break; + case SBIG('LCL2'): + x38_LCL2.read(r); + break; + case SBIG('LCL3'): + x3c_LCL3.read(r); + break; + case SBIG('SSWH'): + x40_SSWH.read(r); + break; + case SBIG('GPSM'): + x50_GPSM.read(r); + break; + case SBIG('EPSM'): + x60_EPSM.read(r); + break; + case SBIG('ZERY'): + x70_ZERY.read(r); + break; + default: + break; + } + } + } } template -void ELSM::_write(athena::io::YAMLDocWriter& w) const -{ - if (x0_LIFE) - if (auto rec = w.enterSubRecord("LIFE")) - x0_LIFE.write(w); - if (x4_SLIF) - if (auto rec = w.enterSubRecord("SLIF")) - x4_SLIF.write(w); - if (x8_GRAT) - if (auto rec = w.enterSubRecord("GRAT")) - x8_GRAT.write(w); - if (xc_SCNT) - if (auto rec = w.enterSubRecord("SCNT")) - xc_SCNT.write(w); - if (x10_SSEG) - if (auto rec = w.enterSubRecord("SSEG")) - x10_SSEG.write(w); - if (x14_COLR) - if (auto rec = w.enterSubRecord("COLR")) - x14_COLR.write(w); - if (x18_IEMT) - if (auto rec = w.enterSubRecord("IEMT")) - x18_IEMT.write(w); - if (x1c_FEMT) - if (auto rec = w.enterSubRecord("FEMT")) - x1c_FEMT.write(w); - if (x20_AMPL) - if (auto rec = w.enterSubRecord("AMPL")) - x20_AMPL.write(w); - if (x24_AMPD) - if (auto rec = w.enterSubRecord("AMPD")) - x24_AMPD.write(w); - if (x28_LWD1) - if (auto rec = w.enterSubRecord("LWD1")) - x28_LWD1.write(w); - if (x2c_LWD2) - if (auto rec = w.enterSubRecord("LWD2")) - x2c_LWD2.write(w); - if (x30_LWD3) - if (auto rec = w.enterSubRecord("LWD3")) - x30_LWD3.write(w); - if (x34_LCL1) - if (auto rec = w.enterSubRecord("LCL1")) - x34_LCL1.write(w); - if (x38_LCL2) - if (auto rec = w.enterSubRecord("LCL2")) - x38_LCL2.write(w); - if (x3c_LCL3) - if (auto rec = w.enterSubRecord("LCL3")) - x3c_LCL3.write(w); - if (x40_SSWH) - if (auto rec = w.enterSubRecord("SSWH")) - x40_SSWH.write(w); - if (x50_GPSM) - if (auto rec = w.enterSubRecord("GPSM")) - x50_GPSM.write(w); - if (x60_EPSM) - if (auto rec = w.enterSubRecord("EPSM")) - x60_EPSM.write(w); - if (x70_ZERY) - if (auto rec = w.enterSubRecord("ZERY")) - x70_ZERY.write(w); +void ELSM::_write(athena::io::YAMLDocWriter& w) const { + if (x0_LIFE) + if (auto rec = w.enterSubRecord("LIFE")) + x0_LIFE.write(w); + if (x4_SLIF) + if (auto rec = w.enterSubRecord("SLIF")) + x4_SLIF.write(w); + if (x8_GRAT) + if (auto rec = w.enterSubRecord("GRAT")) + x8_GRAT.write(w); + if (xc_SCNT) + if (auto rec = w.enterSubRecord("SCNT")) + xc_SCNT.write(w); + if (x10_SSEG) + if (auto rec = w.enterSubRecord("SSEG")) + x10_SSEG.write(w); + if (x14_COLR) + if (auto rec = w.enterSubRecord("COLR")) + x14_COLR.write(w); + if (x18_IEMT) + if (auto rec = w.enterSubRecord("IEMT")) + x18_IEMT.write(w); + if (x1c_FEMT) + if (auto rec = w.enterSubRecord("FEMT")) + x1c_FEMT.write(w); + if (x20_AMPL) + if (auto rec = w.enterSubRecord("AMPL")) + x20_AMPL.write(w); + if (x24_AMPD) + if (auto rec = w.enterSubRecord("AMPD")) + x24_AMPD.write(w); + if (x28_LWD1) + if (auto rec = w.enterSubRecord("LWD1")) + x28_LWD1.write(w); + if (x2c_LWD2) + if (auto rec = w.enterSubRecord("LWD2")) + x2c_LWD2.write(w); + if (x30_LWD3) + if (auto rec = w.enterSubRecord("LWD3")) + x30_LWD3.write(w); + if (x34_LCL1) + if (auto rec = w.enterSubRecord("LCL1")) + x34_LCL1.write(w); + if (x38_LCL2) + if (auto rec = w.enterSubRecord("LCL2")) + x38_LCL2.write(w); + if (x3c_LCL3) + if (auto rec = w.enterSubRecord("LCL3")) + x3c_LCL3.write(w); + if (x40_SSWH) + if (auto rec = w.enterSubRecord("SSWH")) + x40_SSWH.write(w); + if (x50_GPSM) + if (auto rec = w.enterSubRecord("GPSM")) + x50_GPSM.write(w); + if (x60_EPSM) + if (auto rec = w.enterSubRecord("EPSM")) + x60_EPSM.write(w); + if (x70_ZERY) + if (auto rec = w.enterSubRecord("ZERY")) + x70_ZERY.write(w); } AT_SUBSPECIALIZE_DNA_YAML(ELSM) AT_SUBSPECIALIZE_DNA_YAML(ELSM) template <> -const char* ELSM::DNAType() { return "urde::ELSM"; } +const char* ELSM::DNAType() { + return "urde::ELSM"; +} template <> -const char* ELSM::DNAType() { return "urde::ELSM"; } +const char* ELSM::DNAType() { + return "urde::ELSM"; +} template -void ELSM::gatherDependencies(std::vector& pathsOut) const -{ - g_curSpec->flattenDependencies(x40_SSWH.id, pathsOut); - g_curSpec->flattenDependencies(x50_GPSM.id, pathsOut); - g_curSpec->flattenDependencies(x60_EPSM.id, pathsOut); +void ELSM::gatherDependencies(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(x40_SSWH.id, pathsOut); + g_curSpec->flattenDependencies(x50_GPSM.id, pathsOut); + g_curSpec->flattenDependencies(x60_EPSM.id, pathsOut); } template struct ELSM; template struct ELSM; template -bool ExtractELSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - ELSM elsm; - elsm.read(rs); - athena::io::ToYAMLStream(elsm, writer); - return true; - } - return false; +bool ExtractELSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + ELSM elsm; + elsm.read(rs); + athena::io::ToYAMLStream(elsm, writer); + return true; + } + return false; } template bool ExtractELSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractELSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template -bool WriteELSM(const ELSM& elsm, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - elsm.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; +bool WriteELSM(const ELSM& elsm, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + elsm.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } template bool WriteELSM(const ELSM& gpsm, const hecl::ProjectPath& outPath); template bool WriteELSM(const ELSM& gpsm, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/ELSC.hpp b/DataSpec/DNACommon/ELSC.hpp index 8eee8563a..0e441d50a 100644 --- a/DataSpec/DNACommon/ELSC.hpp +++ b/DataSpec/DNACommon/ELSC.hpp @@ -4,35 +4,33 @@ #include "PAK.hpp" #include "athena/FileWriter.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template -struct ELSM : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA - IntElementFactory x0_LIFE; - IntElementFactory x4_SLIF; - RealElementFactory x8_GRAT; - IntElementFactory xc_SCNT; - IntElementFactory x10_SSEG; - ColorElementFactory x14_COLR; - EmitterElementFactory x18_IEMT; - EmitterElementFactory x1c_FEMT; - RealElementFactory x20_AMPL; - RealElementFactory x24_AMPD; - RealElementFactory x28_LWD1; - RealElementFactory x2c_LWD2; - RealElementFactory x30_LWD3; - ColorElementFactory x34_LCL1; - ColorElementFactory x38_LCL2; - ColorElementFactory x3c_LCL3; - ChildResourceFactory x40_SSWH; - ChildResourceFactory x50_GPSM; - ChildResourceFactory x60_EPSM; - BoolHelper x70_ZERY; +struct ELSM : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + IntElementFactory x0_LIFE; + IntElementFactory x4_SLIF; + RealElementFactory x8_GRAT; + IntElementFactory xc_SCNT; + IntElementFactory x10_SSEG; + ColorElementFactory x14_COLR; + EmitterElementFactory x18_IEMT; + EmitterElementFactory x1c_FEMT; + RealElementFactory x20_AMPL; + RealElementFactory x24_AMPD; + RealElementFactory x28_LWD1; + RealElementFactory x2c_LWD2; + RealElementFactory x30_LWD3; + ColorElementFactory x34_LCL1; + ColorElementFactory x38_LCL2; + ColorElementFactory x3c_LCL3; + ChildResourceFactory x40_SSWH; + ChildResourceFactory x50_GPSM; + ChildResourceFactory x60_EPSM; + BoolHelper x70_ZERY; - void gatherDependencies(std::vector&) const; + void gatherDependencies(std::vector&) const; }; template @@ -41,4 +39,4 @@ bool ExtractELSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteELSM(const ELSM& elsm, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/FONT.cpp b/DataSpec/DNACommon/FONT.cpp index 2bb156718..b653ac406 100644 --- a/DataSpec/DNACommon/FONT.cpp +++ b/DataSpec/DNACommon/FONT.cpp @@ -1,246 +1,231 @@ #include "FONT.hpp" -namespace DataSpec::DNAFont -{ +namespace DataSpec::DNAFont { logvisor::Module LogModule("urde::DNAFont"); template -void FONT::_read(athena::io::IStreamReader& __dna_reader) -{ - /* magic */ - atUint32 magic; - __dna_reader.readBytesToBuf(&magic, 4); - if (magic != SBIG('FONT')) - { - LogModule.report(logvisor::Fatal, "Invalid FONT magic '%s'", &magic); - return; - } - /* version */ - version = __dna_reader.readUint32Big(); - /* unknown1 */ - unknown1 = __dna_reader.readUint32Big(); - /* lineHeight */ - lineHeight = __dna_reader.readInt32Big(); - /* verticalOffset */ - verticalOffset = __dna_reader.readInt32Big(); - /* lineMargin */ - lineMargin = __dna_reader.readInt32Big(); - /* unknown2 */ - unknown2 = __dna_reader.readBool(); - /* unknown3 */ - unknown3 = __dna_reader.readBool(); - /* unknown4 */ - unknown4 = __dna_reader.readUint32Big(); - /* fontSize */ - fontSize = __dna_reader.readUint32Big(); - /* name */ - name = __dna_reader.readString(-1); - /* textureId */ - textureId.read(__dna_reader); - /* textureFormat */ - textureFormat = __dna_reader.readUint32Big(); - /* glyphCount */ - glyphCount = __dna_reader.readUint32Big(); - /* glyphs */ - for (atUint32 i = 0; i < glyphCount; i++) - { - if (version < 4) - glyphs.emplace_back(new GlyphMP1); - else - glyphs.emplace_back(new GlyphMP2); - glyphs.back()->read(__dna_reader); - } - /* kerningInfoCount */ - kerningInfoCount = __dna_reader.readUint32Big(); - /* kerningInfo */ - __dna_reader.enumerate(kerningInfo, kerningInfoCount); +void FONT::_read(athena::io::IStreamReader& __dna_reader) { + /* magic */ + atUint32 magic; + __dna_reader.readBytesToBuf(&magic, 4); + if (magic != SBIG('FONT')) { + LogModule.report(logvisor::Fatal, "Invalid FONT magic '%s'", &magic); + return; + } + /* version */ + version = __dna_reader.readUint32Big(); + /* unknown1 */ + unknown1 = __dna_reader.readUint32Big(); + /* lineHeight */ + lineHeight = __dna_reader.readInt32Big(); + /* verticalOffset */ + verticalOffset = __dna_reader.readInt32Big(); + /* lineMargin */ + lineMargin = __dna_reader.readInt32Big(); + /* unknown2 */ + unknown2 = __dna_reader.readBool(); + /* unknown3 */ + unknown3 = __dna_reader.readBool(); + /* unknown4 */ + unknown4 = __dna_reader.readUint32Big(); + /* fontSize */ + fontSize = __dna_reader.readUint32Big(); + /* name */ + name = __dna_reader.readString(-1); + /* textureId */ + textureId.read(__dna_reader); + /* textureFormat */ + textureFormat = __dna_reader.readUint32Big(); + /* glyphCount */ + glyphCount = __dna_reader.readUint32Big(); + /* glyphs */ + for (atUint32 i = 0; i < glyphCount; i++) { + if (version < 4) + glyphs.emplace_back(new GlyphMP1); + else + glyphs.emplace_back(new GlyphMP2); + glyphs.back()->read(__dna_reader); + } + /* kerningInfoCount */ + kerningInfoCount = __dna_reader.readUint32Big(); + /* kerningInfo */ + __dna_reader.enumerate(kerningInfo, kerningInfoCount); } template -void FONT::_write(athena::io::IStreamWriter& __dna_writer) const -{ - /* magic */ - __dna_writer.writeBytes((atInt8*)"FONT", 4); - /* version */ - __dna_writer.writeUint32Big(version); - /* unknown1 */ - __dna_writer.writeUint32Big(unknown1); - /* lineHeight */ - __dna_writer.writeInt32Big(lineHeight); - /* verticalOffset */ - __dna_writer.writeInt32Big(verticalOffset); - /* lineMargin */ - __dna_writer.writeInt32Big(lineMargin); - /* unknown2 */ - __dna_writer.writeBool(unknown2); - /* unknown3 */ - __dna_writer.writeBool(unknown3); - /* unknown4 */ - __dna_writer.writeUint32Big(unknown4); - /* fontSize */ - __dna_writer.writeUint32Big(fontSize); - /* name */ - __dna_writer.writeString(name, -1); - /* textureId */ - textureId.write(__dna_writer); - /* textureFormat */ - __dna_writer.writeUint32Big(textureFormat); - /* glyphCount */ - __dna_writer.writeUint32Big(glyphCount); - /* glyphs */ +void FONT::_write(athena::io::IStreamWriter& __dna_writer) const { + /* magic */ + __dna_writer.writeBytes((atInt8*)"FONT", 4); + /* version */ + __dna_writer.writeUint32Big(version); + /* unknown1 */ + __dna_writer.writeUint32Big(unknown1); + /* lineHeight */ + __dna_writer.writeInt32Big(lineHeight); + /* verticalOffset */ + __dna_writer.writeInt32Big(verticalOffset); + /* lineMargin */ + __dna_writer.writeInt32Big(lineMargin); + /* unknown2 */ + __dna_writer.writeBool(unknown2); + /* unknown3 */ + __dna_writer.writeBool(unknown3); + /* unknown4 */ + __dna_writer.writeUint32Big(unknown4); + /* fontSize */ + __dna_writer.writeUint32Big(fontSize); + /* name */ + __dna_writer.writeString(name, -1); + /* textureId */ + textureId.write(__dna_writer); + /* textureFormat */ + __dna_writer.writeUint32Big(textureFormat); + /* glyphCount */ + __dna_writer.writeUint32Big(glyphCount); + /* glyphs */ + for (const std::unique_ptr& glyph : glyphs) + glyph->write(__dna_writer); + /* kerningInfoCount */ + __dna_writer.writeUint32Big(kerningInfoCount); + /* kerningInfo */ + __dna_writer.enumerate(kerningInfo); +} + +template +void FONT::_read(athena::io::YAMLDocReader& __dna_docin) { + /* version */ + version = __dna_docin.readUint32("version"); + /* unknown1 */ + unknown1 = __dna_docin.readUint32("unknown1"); + /* lineHeight */ + lineHeight = __dna_docin.readInt32("lineHeight"); + /* verticalOffset */ + verticalOffset = __dna_docin.readInt32("verticalOffset"); + /* lineMargin */ + lineMargin = __dna_docin.readInt32("lineMargin"); + /* unknown2 */ + unknown2 = __dna_docin.readBool("unknown2"); + /* unknown3 */ + unknown3 = __dna_docin.readBool("unknown3"); + /* unknown4 */ + unknown4 = __dna_docin.readUint32("unknown4"); + /* fontSize */ + fontSize = __dna_docin.readUint32("fontSize"); + /* name */ + name = __dna_docin.readString("name"); + /* textureId */ + __dna_docin.enumerate("textureId", textureId); + /* textureFormat */ + textureFormat = __dna_docin.readUint32("textureFormat"); + /* glyphCount */ + /* glyphs */ + size_t count; + if (auto v = __dna_docin.enterSubVector("glyphs", count)) { + glyphCount = count; + for (atUint32 i = 0; i < glyphCount; i++) { + if (version < 4) + glyphs.emplace_back(new GlyphMP1); + else + glyphs.emplace_back(new GlyphMP2); + + if (auto rec = __dna_docin.enterSubRecord(nullptr)) + glyphs.back()->read(__dna_docin); + } + } + /* kerningInfoCount squelched */ + /* kerningInfo */ + kerningInfoCount = __dna_docin.enumerate("kerningInfo", kerningInfo); +} + +template +void FONT::_write(athena::io::YAMLDocWriter& __dna_docout) const { + /* version */ + __dna_docout.writeUint32("version", version); + /* unknown1 */ + __dna_docout.writeUint32("unknown1", unknown1); + /* lineHeight */ + __dna_docout.writeInt32("lineHeight", lineHeight); + /* verticalOffset */ + __dna_docout.writeInt32("verticalOffset", verticalOffset); + /* lineMargin */ + __dna_docout.writeInt32("lineMargin", lineMargin); + /* unknown2 */ + __dna_docout.writeBool("unknown2", unknown2); + /* unknown3 */ + __dna_docout.writeBool("unknown3", unknown3); + /* unknown4 */ + __dna_docout.writeUint32("unknown4", unknown4); + /* fontSize */ + __dna_docout.writeUint32("fontSize", fontSize); + /* name */ + __dna_docout.writeString("name", name); + /* textureId */ + __dna_docout.enumerate("textureId", textureId); + /* textureFormat */ + __dna_docout.writeUint32("textureFormat", textureFormat); + /* glyphCount squelched */ + /* glyphs */ + if (auto v = __dna_docout.enterSubVector("glyphs")) for (const std::unique_ptr& glyph : glyphs) - glyph->write(__dna_writer); - /* kerningInfoCount */ - __dna_writer.writeUint32Big(kerningInfoCount); - /* kerningInfo */ - __dna_writer.enumerate(kerningInfo); -} - -template -void FONT::_read(athena::io::YAMLDocReader& __dna_docin) -{ - /* version */ - version = __dna_docin.readUint32("version"); - /* unknown1 */ - unknown1 = __dna_docin.readUint32("unknown1"); - /* lineHeight */ - lineHeight = __dna_docin.readInt32("lineHeight"); - /* verticalOffset */ - verticalOffset = __dna_docin.readInt32("verticalOffset"); - /* lineMargin */ - lineMargin = __dna_docin.readInt32("lineMargin"); - /* unknown2 */ - unknown2 = __dna_docin.readBool("unknown2"); - /* unknown3 */ - unknown3 = __dna_docin.readBool("unknown3"); - /* unknown4 */ - unknown4 = __dna_docin.readUint32("unknown4"); - /* fontSize */ - fontSize = __dna_docin.readUint32("fontSize"); - /* name */ - name = __dna_docin.readString("name"); - /* textureId */ - __dna_docin.enumerate("textureId", textureId); - /* textureFormat */ - textureFormat = __dna_docin.readUint32("textureFormat"); - /* glyphCount */ - /* glyphs */ - size_t count; - if (auto v = __dna_docin.enterSubVector("glyphs", count)) - { - glyphCount = count; - for (atUint32 i = 0; i < glyphCount; i++) - { - if (version < 4) - glyphs.emplace_back(new GlyphMP1); - else - glyphs.emplace_back(new GlyphMP2); - - if (auto rec = __dna_docin.enterSubRecord(nullptr)) - glyphs.back()->read(__dna_docin); - } - } - /* kerningInfoCount squelched */ - /* kerningInfo */ - kerningInfoCount = __dna_docin.enumerate("kerningInfo", kerningInfo); -} - -template -void FONT::_write(athena::io::YAMLDocWriter& __dna_docout) const -{ - /* version */ - __dna_docout.writeUint32("version", version); - /* unknown1 */ - __dna_docout.writeUint32("unknown1", unknown1); - /* lineHeight */ - __dna_docout.writeInt32("lineHeight", lineHeight); - /* verticalOffset */ - __dna_docout.writeInt32("verticalOffset", verticalOffset); - /* lineMargin */ - __dna_docout.writeInt32("lineMargin", lineMargin); - /* unknown2 */ - __dna_docout.writeBool("unknown2", unknown2); - /* unknown3 */ - __dna_docout.writeBool("unknown3", unknown3); - /* unknown4 */ - __dna_docout.writeUint32("unknown4", unknown4); - /* fontSize */ - __dna_docout.writeUint32("fontSize", fontSize); - /* name */ - __dna_docout.writeString("name", name); - /* textureId */ - __dna_docout.enumerate("textureId", textureId); - /* textureFormat */ - __dna_docout.writeUint32("textureFormat", textureFormat); - /* glyphCount squelched */ - /* glyphs */ - if (auto v = __dna_docout.enterSubVector("glyphs")) - for (const std::unique_ptr& glyph : glyphs) - if (auto rec = __dna_docout.enterSubRecord(nullptr)) - glyph->write(__dna_docout); - /* kerningInfoCount squelched */ - /* kerningInfo */ - __dna_docout.enumerate("kerningInfo", kerningInfo); + if (auto rec = __dna_docout.enterSubRecord(nullptr)) + glyph->write(__dna_docout); + /* kerningInfoCount squelched */ + /* kerningInfo */ + __dna_docout.enumerate("kerningInfo", kerningInfo); } template <> -const char* FONT::DNAType() -{ - return "FONT"; +const char* FONT::DNAType() { + return "FONT"; } template <> -const char* FONT::DNAType() -{ - return "FONT"; +const char* FONT::DNAType() { + return "FONT"; } template -void FONT::_binarySize(size_t& __isz) const -{ - __isz += name.size() + 1; - textureId.binarySize(__isz); - for (const std::unique_ptr& glyph : glyphs) - glyph->binarySize(__isz); - for (const KerningInfo& k : kerningInfo) - k.binarySize(__isz); - __isz += 46; +void FONT::_binarySize(size_t& __isz) const { + __isz += name.size() + 1; + textureId.binarySize(__isz); + for (const std::unique_ptr& glyph : glyphs) + glyph->binarySize(__isz); + for (const KerningInfo& k : kerningInfo) + k.binarySize(__isz); + __isz += 46; } AT_SUBSPECIALIZE_DNA_YAML(FONT) AT_SUBSPECIALIZE_DNA_YAML(FONT) template -bool ExtractFONT(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - FONT font; - font.read(rs); - athena::io::ToYAMLStream(font, writer); - return true; - } - return false; +bool ExtractFONT(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + FONT font; + font.read(rs); + athena::io::ToYAMLStream(font, writer); + return true; + } + return false; } template bool ExtractFONT(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractFONT(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template -bool WriteFONT(const FONT& font, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - font.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; +bool WriteFONT(const FONT& font, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + font.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } template bool WriteFONT(const FONT& font, const hecl::ProjectPath& outPath); template bool WriteFONT(const FONT& font, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAFont diff --git a/DataSpec/DNACommon/FONT.hpp b/DataSpec/DNACommon/FONT.hpp index d011907e1..ddc84bcbf 100644 --- a/DataSpec/DNACommon/FONT.hpp +++ b/DataSpec/DNACommon/FONT.hpp @@ -3,117 +3,109 @@ #include "PAK.hpp" #include "athena/FileWriter.hpp" -namespace DataSpec::DNAFont -{ -struct GlyphRect : BigDNA -{ - AT_DECL_DNA_YAML - Value left; - Value top; - Value right; - Value bottom; +namespace DataSpec::DNAFont { +struct GlyphRect : BigDNA { + AT_DECL_DNA_YAML + Value left; + Value top; + Value right; + Value bottom; }; -struct IGlyph : BigDNAVYaml -{ - AT_DECL_DNA_YAML - Value m_character; - GlyphRect m_glyphRect; +struct IGlyph : BigDNAVYaml { + AT_DECL_DNA_YAML + Value m_character; + GlyphRect m_glyphRect; - atUint16 character() const { return m_character; } - float left() const { return m_glyphRect.left; } - float top() const { return m_glyphRect.top; } - float right() const { return m_glyphRect.right; } - float bottom() const { return m_glyphRect.bottom; } - GlyphRect rect() const { return m_glyphRect; } + atUint16 character() const { return m_character; } + float left() const { return m_glyphRect.left; } + float top() const { return m_glyphRect.top; } + float right() const { return m_glyphRect.right; } + float bottom() const { return m_glyphRect.bottom; } + GlyphRect rect() const { return m_glyphRect; } - virtual atInt32 layer() const { return 0; } - virtual atInt32 leftPadding() const=0; - virtual atInt32 advance() const =0; - virtual atInt32 rightPadding() const=0; - virtual atInt32 width() const=0; - virtual atInt32 height() const=0; - virtual atInt32 baseline() const=0; - virtual atInt32 kerningIndex() const =0; + virtual atInt32 layer() const { return 0; } + virtual atInt32 leftPadding() const = 0; + virtual atInt32 advance() const = 0; + virtual atInt32 rightPadding() const = 0; + virtual atInt32 width() const = 0; + virtual atInt32 height() const = 0; + virtual atInt32 baseline() const = 0; + virtual atInt32 kerningIndex() const = 0; }; -struct GlyphMP1 : IGlyph -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value m_leftPadding; - Value m_advance; - Value m_rightPadding; - Value m_width; - Value m_height; - Value m_baseline; - Value m_kerningIndex; +struct GlyphMP1 : IGlyph { + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value m_leftPadding; + Value m_advance; + Value m_rightPadding; + Value m_width; + Value m_height; + Value m_baseline; + Value m_kerningIndex; - atInt32 leftPadding() const { return m_leftPadding; } - atInt32 advance() const { return m_advance; } - atInt32 rightPadding() const { return m_rightPadding; } - atInt32 width() const { return m_width; } - atInt32 height() const { return m_height; } - atInt32 baseline() const { return m_baseline; } - atInt32 kerningIndex() const { return m_kerningIndex; } + atInt32 leftPadding() const { return m_leftPadding; } + atInt32 advance() const { return m_advance; } + atInt32 rightPadding() const { return m_rightPadding; } + atInt32 width() const { return m_width; } + atInt32 height() const { return m_height; } + atInt32 baseline() const { return m_baseline; } + atInt32 kerningIndex() const { return m_kerningIndex; } }; -struct GlyphMP2 : IGlyph -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value m_layer; - Value m_leftPadding; - Value m_advance; - Value m_rightPadding; - Value m_width; - Value m_height; - Value m_baseline; - Value m_kerningIndex; +struct GlyphMP2 : IGlyph { + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value m_layer; + Value m_leftPadding; + Value m_advance; + Value m_rightPadding; + Value m_width; + Value m_height; + Value m_baseline; + Value m_kerningIndex; - atInt32 layer() const { return m_layer; } - atInt32 leftPadding() const { return m_leftPadding; } - atInt32 advance() const { return m_advance; } - atInt32 rightPadding() const { return m_rightPadding; } - atInt32 width() const { return m_width; } - atInt32 height() const { return m_height; } - atInt32 baseline() const { return m_baseline; } - atInt32 kerningIndex() const { return m_kerningIndex; } + atInt32 layer() const { return m_layer; } + atInt32 leftPadding() const { return m_leftPadding; } + atInt32 advance() const { return m_advance; } + atInt32 rightPadding() const { return m_rightPadding; } + atInt32 width() const { return m_width; } + atInt32 height() const { return m_height; } + atInt32 baseline() const { return m_baseline; } + atInt32 kerningIndex() const { return m_kerningIndex; } }; -struct KerningInfo : BigDNA -{ - AT_DECL_DNA_YAML - Value thisChar; - Value nextChar; - Value adjust; +struct KerningInfo : BigDNA { + AT_DECL_DNA_YAML + Value thisChar; + Value nextChar; + Value adjust; }; template -struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) FONT : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA - Value version; - Value unknown1; - Value lineHeight; - Value verticalOffset; - Value lineMargin; - Value unknown2; - Value unknown3; - Value unknown4; - Value fontSize; // in points - String<-1> name; - Value textureId; - Value textureFormat; - Value glyphCount; - std::vector> glyphs; - Value kerningInfoCount; - Vector kerningInfo; +struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) FONT : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + Value version; + Value unknown1; + Value lineHeight; + Value verticalOffset; + Value lineMargin; + Value unknown2; + Value unknown3; + Value unknown4; + Value fontSize; // in points + String<-1> name; + Value textureId; + Value textureFormat; + Value glyphCount; + std::vector> glyphs; + Value kerningInfoCount; + Vector kerningInfo; - void gatherDependencies(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(textureId, pathsOut); - } + void gatherDependencies(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(textureId, pathsOut); + } }; template @@ -122,5 +114,4 @@ bool ExtractFONT(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteFONT(const FONT& font, const hecl::ProjectPath& outPath); -} - +} // namespace DataSpec::DNAFont diff --git a/DataSpec/DNACommon/FSM2.cpp b/DataSpec/DNACommon/FSM2.cpp index f942ffb56..974926e40 100644 --- a/DataSpec/DNACommon/FSM2.cpp +++ b/DataSpec/DNACommon/FSM2.cpp @@ -4,82 +4,75 @@ #include "FSM2.hpp" -namespace DataSpec::DNAFSM2 -{ +namespace DataSpec::DNAFSM2 { logvisor::Module LogDNAFSM2("urde::DNAFSM2"); template template -void FSM2::Enumerate(typename Op::StreamT& s) -{ - Do({"header"}, header, s); - if (header.magic != SBIG('FSM2')) - { - LogDNAFSM2.report(logvisor::Fatal, "Invalid FSM2 magic '%.4s' expected 'FSM2'", header.magic.toString().c_str()); - return; - } +void FSM2::Enumerate(typename Op::StreamT& s) { + Do({"header"}, header, s); + if (header.magic != SBIG('FSM2')) { + LogDNAFSM2.report(logvisor::Fatal, "Invalid FSM2 magic '%.4s' expected 'FSM2'", header.magic.toString().c_str()); + return; + } - if (header.version == 1) - { - if (!detail) - detail.reset(new FSMV1); - Do({"detail"}, static_cast(*detail), s); - } - else if (header.version == 2) - { - if (!detail) - detail.reset(new FSMV2); - Do({"detail"}, static_cast(*detail), s); - } - else - { - LogDNAFSM2.report(logvisor::Fatal, "Invalid FSM2 version '%i'", header.version); - return; - } + if (header.version == 1) { + if (!detail) + detail.reset(new FSMV1); + Do({"detail"}, static_cast(*detail), s); + } else if (header.version == 2) { + if (!detail) + detail.reset(new FSMV2); + Do({"detail"}, static_cast(*detail), s); + } else { + LogDNAFSM2.report(logvisor::Fatal, "Invalid FSM2 version '%i'", header.version); + return; + } } AT_SPECIALIZE_DNA(FSM2) AT_SPECIALIZE_DNA(FSM2) template <> -const char* FSM2::DNAType() { return "urde::FSM2"; } +const char* FSM2::DNAType() { + return "urde::FSM2"; +} template <> -const char* FSM2::DNAType() { return "urde::FSM2"; } +const char* FSM2::DNAType() { + return "urde::FSM2"; +} template struct FSM2; template struct FSM2; template -bool ExtractFSM2(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - FSM2 fsm2; - fsm2.read(rs); - athena::io::ToYAMLStream(fsm2, writer); - return true; - } - return false; +bool ExtractFSM2(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + FSM2 fsm2; + fsm2.read(rs); + athena::io::ToYAMLStream(fsm2, writer); + return true; + } + return false; } template bool ExtractFSM2(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractFSM2(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template -bool WriteFSM2(const FSM2& fsm2, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - fsm2.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; +bool WriteFSM2(const FSM2& fsm2, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + fsm2.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } template bool WriteFSM2(const FSM2& fsm2, const hecl::ProjectPath& outPath); template bool WriteFSM2(const FSM2& fsm2, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAFSM2 diff --git a/DataSpec/DNACommon/FSM2.hpp b/DataSpec/DNACommon/FSM2.hpp index 244a6ff5b..c04c2705f 100644 --- a/DataSpec/DNACommon/FSM2.hpp +++ b/DataSpec/DNACommon/FSM2.hpp @@ -4,146 +4,131 @@ #include "DNACommon.hpp" #include "athena/FileWriter.hpp" -namespace DataSpec::DNAFSM2 -{ -struct IFSM : BigDNAVYaml -{ - Delete _d; +namespace DataSpec::DNAFSM2 { +struct IFSM : BigDNAVYaml { + Delete _d; }; template -struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) FSM2 : BigDNA -{ - struct Header : BigDNA - { - AT_DECL_DNA_YAML - DNAFourCC magic = FOURCC('FSM2'); - Value version; - } header; +struct AT_SPECIALIZE_PARMS(DataSpec::UniqueID32, DataSpec::UniqueID64) FSM2 : BigDNA { + struct Header : BigDNA { + AT_DECL_DNA_YAML + DNAFourCC magic = FOURCC('FSM2'); + Value version; + } header; - struct CommonStruct : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknown; + struct CommonStruct : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unknown; + }; + + struct FSMV1 : IFSM { + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value stateCount; + Value unknown1Count; + Value unknown2Count; + Value unknown3Count; + struct State : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unknownCount; + Vector unknown; }; - struct FSMV1 : IFSM - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value stateCount; - Value unknown1Count; - Value unknown2Count; - Value unknown3Count; - struct State : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknownCount; - Vector unknown; - }; - - struct Unknown1 : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknown1; - Value unknown2Count; - Vector unknown2; - Value unknown3; - }; - - struct Unknown2 : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknownCount; - Vector unknown; - }; - - struct Unknown3 : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknownCount; - Vector unknown; - Value fsmId; - }; - - Vector states; - Vector unknown1; - Vector unknown2; - Vector unknown3; + struct Unknown1 : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unknown1; + Value unknown2Count; + Vector unknown2; + Value unknown3; }; - struct FSMV2 : IFSM - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value stateCount; - Value unknown1Count; - Value unknown2Count; - Value unknown3Count; - struct State : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5Count; - Vector unknown5; - }; - - struct Unknown1 : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6Count; - Vector unknown6; - Value unknown7; - }; - - struct Unknown2 : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5Count; - Vector unknown5; - }; - - struct Unknown3 : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5Count; - Vector unknown5; - Value fsmId; - }; - - Vector states; - Vector unknown1; - Vector unknown2; - Vector unknown3; + struct Unknown2 : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unknownCount; + Vector unknown; }; - std::unique_ptr detail; - AT_DECL_EXPLICIT_DNA_YAML + struct Unknown3 : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unknownCount; + Vector unknown; + Value fsmId; + }; + + Vector states; + Vector unknown1; + Vector unknown2; + Vector unknown3; + }; + + struct FSMV2 : IFSM { + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value stateCount; + Value unknown1Count; + Value unknown2Count; + Value unknown3Count; + struct State : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5Count; + Vector unknown5; + }; + + struct Unknown1 : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6Count; + Vector unknown6; + Value unknown7; + }; + + struct Unknown2 : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5Count; + Vector unknown5; + }; + + struct Unknown3 : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5Count; + Vector unknown5; + Value fsmId; + }; + + Vector states; + Vector unknown1; + Vector unknown2; + Vector unknown3; + }; + + std::unique_ptr detail; + AT_DECL_EXPLICIT_DNA_YAML }; template @@ -151,4 +136,4 @@ bool ExtractFSM2(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteFSM2(const FSM2& fsm2, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAFSM2 diff --git a/DataSpec/DNACommon/GX.hpp b/DataSpec/DNACommon/GX.hpp index 688578993..1cc035871 100644 --- a/DataSpec/DNACommon/GX.hpp +++ b/DataSpec/DNACommon/GX.hpp @@ -2,4 +2,3 @@ #include "hecl/Backend/GX.hpp" using GX = hecl::Backend::GX; - diff --git a/DataSpec/DNACommon/MAPA.cpp b/DataSpec/DNACommon/MAPA.cpp index 2bfdc3a04..406f64eaf 100644 --- a/DataSpec/DNACommon/MAPA.cpp +++ b/DataSpec/DNACommon/MAPA.cpp @@ -9,487 +9,419 @@ #include "zeus/CAABox.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMAPA -{ +namespace DataSpec::DNAMAPA { static logvisor::Module Log("DNAMAPA"); template <> -void MAPA::Enumerate(typename Read::StreamT& __dna_reader) -{ - /* magic */ - magic = __dna_reader.readUint32Big(); - if (magic != 0xDEADD00D) - { - LogDNACommon.report(logvisor::Error, "invalid MAPA magic"); - return; - } - /* version */ - version = __dna_reader.readUint32Big(); - if (version == 2) - header.reset(new HeaderMP1); - else if (version == 3) - header.reset(new HeaderMP2); - else if (version == 5) - header.reset(new HeaderMP3); +void MAPA::Enumerate(typename Read::StreamT& __dna_reader) { + /* magic */ + magic = __dna_reader.readUint32Big(); + if (magic != 0xDEADD00D) { + LogDNACommon.report(logvisor::Error, "invalid MAPA magic"); + return; + } + /* version */ + version = __dna_reader.readUint32Big(); + if (version == 2) + header.reset(new HeaderMP1); + else if (version == 3) + header.reset(new HeaderMP2); + else if (version == 5) + header.reset(new HeaderMP3); + else { + LogDNACommon.report(logvisor::Error, "invalid MAPA version"); + return; + } + + header->read(__dna_reader); + + for (atUint32 i = 0; i < header->mappableObjectCount(); i++) { + std::unique_ptr mo = nullptr; + if (version != 5) + mo.reset(new MappableObjectMP1_2); else - { - LogDNACommon.report(logvisor::Error, "invalid MAPA version"); - return; - } + mo.reset(new MappableObjectMP3); + mo->read(__dna_reader); + mappableObjects.push_back(std::move(mo)); + } - header->read(__dna_reader); - - for (atUint32 i = 0; i < header->mappableObjectCount(); i++) - { - std::unique_ptr mo = nullptr; - if (version != 5) - mo.reset(new MappableObjectMP1_2); - else - mo.reset(new MappableObjectMP3); - mo->read(__dna_reader); - mappableObjects.push_back(std::move(mo)); - } - - /* vertices */ - __dna_reader.enumerateBig(vertices, header->vertexCount()); - /* surfaceHeaders */ - __dna_reader.enumerate(surfaceHeaders, header->surfaceCount()); - /* surfaces */ - __dna_reader.enumerate(surfaces, header->surfaceCount()); + /* vertices */ + __dna_reader.enumerateBig(vertices, header->vertexCount()); + /* surfaceHeaders */ + __dna_reader.enumerate(surfaceHeaders, header->surfaceCount()); + /* surfaces */ + __dna_reader.enumerate(surfaces, header->surfaceCount()); } template <> -void MAPA::Enumerate(typename Write::StreamT& __dna_writer) -{ - /* magic */ - __dna_writer.writeUint32Big(magic); - /* version */ - __dna_writer.writeUint32Big(version); - header->write(__dna_writer); +void MAPA::Enumerate(typename Write::StreamT& __dna_writer) { + /* magic */ + __dna_writer.writeUint32Big(magic); + /* version */ + __dna_writer.writeUint32Big(version); + header->write(__dna_writer); - /* mappableObjects */ - for (const std::unique_ptr& mo : mappableObjects) - mo->write(__dna_writer); - /* vertices */ - __dna_writer.enumerateBig(vertices); - /* surfaceHeaders */ - __dna_writer.enumerate(surfaceHeaders); - /* surfaces */ - __dna_writer.enumerate(surfaces); + /* mappableObjects */ + for (const std::unique_ptr& mo : mappableObjects) + mo->write(__dna_writer); + /* vertices */ + __dna_writer.enumerateBig(vertices); + /* surfaceHeaders */ + __dna_writer.enumerate(surfaceHeaders); + /* surfaces */ + __dna_writer.enumerate(surfaces); } template <> -void MAPA::Enumerate(typename BinarySize::StreamT& s) -{ - header->binarySize(s); +void MAPA::Enumerate(typename BinarySize::StreamT& s) { + header->binarySize(s); - for (const std::unique_ptr& mo : mappableObjects) - mo->binarySize(s); + for (const std::unique_ptr& mo : mappableObjects) + mo->binarySize(s); - s += vertices.size() * 12; - for (const SurfaceHeader& sh : surfaceHeaders) - sh.binarySize(s); - for (const Surface& su : surfaces) - su.binarySize(s); - s += 8; + s += vertices.size() * 12; + for (const SurfaceHeader& sh : surfaceHeaders) + sh.binarySize(s); + for (const Surface& su : surfaces) + su.binarySize(s); + s += 8; } -static const char* RetroMapVisModes[] = -{ - "ALWAYS", - "MAPSTATIONORVISIT", - "VISIT", - "NEVER" -}; +static const char* RetroMapVisModes[] = {"ALWAYS", "MAPSTATIONORVISIT", "VISIT", "NEVER"}; -static const char* RetroMapObjVisModes[] = -{ - "ALWAYS", - "MAPSTATIONORVISIT", - "VISIT", - "NEVER", - "MAPSTATIONORVISIT2" -}; +static const char* RetroMapObjVisModes[] = {"ALWAYS", "MAPSTATIONORVISIT", "VISIT", "NEVER", "MAPSTATIONORVISIT2"}; template -bool ReadMAPAToBlender(hecl::blender::Connection& conn, - const MAPA& mapa, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - bool force) -{ - if (!force && outPath.isFile()) - return true; - - if (!conn.createBlend(outPath, hecl::blender::BlendType::MapArea)) - return false; - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - - os << "import bpy, bmesh\n" - "from mathutils import Matrix\n" - "\n" - "bpy.types.Object.retro_mappable_type = bpy.props.IntProperty(name='Retro: MAPA object type', default=-1)\n" - "bpy.types.Object.retro_mappable_sclyid = bpy.props.StringProperty(name='Retro: MAPA object SCLY ID')\n" - "bpy.types.Scene.retro_map_vis_mode = bpy.props.EnumProperty(items=[('ALWAYS', 'Always', 'Always Visible', 0)," - "('MAPSTATIONORVISIT', 'Map Station or Visit', 'Visible after Map Station or Visit', 1)," - "('VISIT', 'Visit', 'Visible after Visit', 2)," - "('NEVER', 'Never', 'Never Visible', 3)]," - "name='Retro: Map Visibility Mode')\n" - "bpy.types.Object.retro_mapobj_vis_mode = bpy.props.EnumProperty(items=[('ALWAYS', 'Always', 'Always Visible', 0)," - "('MAPSTATIONORVISIT', 'Map Station or Visit', 'Visible after Map Station or Visit', 1)," - "('VISIT', 'Visit', 'Visible after Door Visit', 2)," - "('NEVER', 'Never', 'Never Visible', 3)," - "('MAPSTATIONORVISIT2', 'Map Station or Visit 2', 'Visible after Map Station or Visit', 4)]," - "name='Retro: Map Object Visibility Mode')\n" - "\n" - "for ar in bpy.context.screen.areas:\n" - " for sp in ar.spaces:\n" - " if sp.type == 'VIEW_3D':\n" - " sp.viewport_shade = 'SOLID'\n" - "\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "\n" - "def add_triangle(bm, verts):\n" - " verts = [bm.verts[vi] for vi in verts]\n" - " face = bm.faces.get(verts)\n" - " if face:\n" - " face = face.copy()\n" - " bm.verts.ensure_lookup_table()\n" - " face.normal_flip()\n" - " else:\n" - " bm.faces.new(verts)\n" - "\n" - "def add_border(bm, verts):\n" - " verts = [bm.verts[vi] for vi in verts]\n" - " edge = bm.edges.get(verts)\n" - " if not edge:\n" - " edge = bm.edges.new(verts)\n" - " edge.seam = True\n" - "\n"; - - os.format("bpy.context.scene.name = 'MAPA_%s'\n" - "bpy.context.scene.retro_map_vis_mode = '%s'\n", - entry.id.toString().c_str(), - RetroMapVisModes[mapa.header->visMode()]); - - /* Add empties representing MappableObjects */ - int moIdx = 0; - for (const std::unique_ptr& mo : mapa.mappableObjects) - { - if (mapa.version < 5) - { - const MAPA::MappableObjectMP1_2* moMP12 = static_cast(mo.get()); - zeus::simd_floats mtxF[3]; - for (int i = 0; i < 3; ++i) - moMP12->transformMtx[i].simd.copy_to(mtxF[i]); - os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" - "bpy.context.scene.objects.link(obj)\n" - "obj.retro_mappable_type = %d\n" - "obj.retro_mapobj_vis_mode = '%s'\n" - "obj.retro_mappable_sclyid = '0x%08X'\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "obj.rotation_mode = 'QUATERNION'\n" - "obj.location = mtxd[0]\n" - "obj.rotation_quaternion = mtxd[1]\n" - "obj.scale = mtxd[2]\n", - moIdx, moMP12->type, RetroMapObjVisModes[moMP12->visMode], moMP12->sclyId, - mtxF[0][0], mtxF[0][1], mtxF[0][2], mtxF[0][3], - mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3], - mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]); - ++moIdx; - continue; - } - else - { - const MAPA::MappableObjectMP3* moMP3 = static_cast(mo.get()); - zeus::simd_floats mtxF[3]; - for (int i = 0; i < 3; ++i) - moMP3->transformMtx[i].simd.copy_to(mtxF[i]); - os.format("obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" - "bpy.context.scene.objects.link(obj)\n" - "obj.retro_mappable_type = %d\n" - "obj.retro_mapobj_vis_mode = '%s'\n" - "obj.retro_mappable_sclyid = '0x%08X'\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "obj.rotation_mode = 'QUATERNION'\n" - "obj.location = mtxd[0]\n" - "obj.rotation_quaternion = mtxd[1]\n" - "obj.scale = mtxd[2]\n", - moIdx, moMP3->type, RetroMapObjVisModes[moMP3->visMode], moMP3->sclyId, - mtxF[0][0], mtxF[0][1], mtxF[0][2], mtxF[0][3], - mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3], - mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]); - ++moIdx; - continue; - } - } - - os << "# Begin bmesh\n" - "bm = bmesh.new()\n" - "\n"; - - /* Read in verts */ - for (const atVec3f& vert : mapa.vertices) - { - zeus::simd_floats f(vert.simd); - os.format("bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]); - } - os << "bm.verts.ensure_lookup_table()\n"; - - /* Read in surfaces */ - for (const typename MAPA::Surface& surf : mapa.surfaces) - { - for (const typename MAPA::Surface::Primitive& prim : surf.primitives) - { - auto iit = prim.indices.cbegin(); - - /* 3 Prim Verts to start */ - int c = 0; - unsigned int primVerts[3] = - { - *iit++, - *iit++, - *iit++ - }; - - if (GX::Primitive(prim.type) == GX::TRIANGLESTRIP) - { - atUint8 flip = 0; - for (size_t v=0 ; v= prim.indexCount - 3); - - /* Advance one prim vert */ - if (peek) - primVerts[c%3] = *iit; - else - primVerts[c%3] = *iit++; - ++c; - } - } - else if (GX::Primitive(prim.type) == GX::TRIANGLES) - { - for (size_t v=0 ; v= prim.indexCount) - break; - - /* Advance 3 Prim Verts */ - for (int pv=0 ; pv<3 ; ++pv) - primVerts[pv] = *iit++; - } - } - } - - for (const typename MAPA::Surface::Border& border : surf.borders) - { - auto iit = border.indices.cbegin(); - for (size_t i=0 ; ivisMode()]); + + /* Add empties representing MappableObjects */ + int moIdx = 0; + for (const std::unique_ptr& mo : mapa.mappableObjects) { + if (mapa.version < 5) { + const MAPA::MappableObjectMP1_2* moMP12 = static_cast(mo.get()); + zeus::simd_floats mtxF[3]; + for (int i = 0; i < 3; ++i) + moMP12->transformMtx[i].simd.copy_to(mtxF[i]); + os.format( + "obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.retro_mappable_type = %d\n" + "obj.retro_mapobj_vis_mode = '%s'\n" + "obj.retro_mappable_sclyid = '0x%08X'\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "obj.rotation_mode = 'QUATERNION'\n" + "obj.location = mtxd[0]\n" + "obj.rotation_quaternion = mtxd[1]\n" + "obj.scale = mtxd[2]\n", + moIdx, moMP12->type, RetroMapObjVisModes[moMP12->visMode], moMP12->sclyId, mtxF[0][0], mtxF[0][1], mtxF[0][2], + mtxF[0][3], mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3], mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]); + ++moIdx; + continue; + } else { + const MAPA::MappableObjectMP3* moMP3 = static_cast(mo.get()); + zeus::simd_floats mtxF[3]; + for (int i = 0; i < 3; ++i) + moMP3->transformMtx[i].simd.copy_to(mtxF[i]); + os.format( + "obj = bpy.data.objects.new('MAPOBJ_%02d', None)\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.retro_mappable_type = %d\n" + "obj.retro_mapobj_vis_mode = '%s'\n" + "obj.retro_mappable_sclyid = '0x%08X'\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "obj.rotation_mode = 'QUATERNION'\n" + "obj.location = mtxd[0]\n" + "obj.rotation_quaternion = mtxd[1]\n" + "obj.scale = mtxd[2]\n", + moIdx, moMP3->type, RetroMapObjVisModes[moMP3->visMode], moMP3->sclyId, mtxF[0][0], mtxF[0][1], mtxF[0][2], + mtxF[0][3], mtxF[1][0], mtxF[1][1], mtxF[1][2], mtxF[1][3], mtxF[2][0], mtxF[2][1], mtxF[2][2], mtxF[2][3]); + ++moIdx; + continue; + } + } + + os << "# Begin bmesh\n" + "bm = bmesh.new()\n" + "\n"; + + /* Read in verts */ + for (const atVec3f& vert : mapa.vertices) { + zeus::simd_floats f(vert.simd); + os.format("bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]); + } + os << "bm.verts.ensure_lookup_table()\n"; + + /* Read in surfaces */ + for (const typename MAPA::Surface& surf : mapa.surfaces) { + for (const typename MAPA::Surface::Primitive& prim : surf.primitives) { + auto iit = prim.indices.cbegin(); + + /* 3 Prim Verts to start */ + int c = 0; + unsigned int primVerts[3] = {*iit++, *iit++, *iit++}; + + if (GX::Primitive(prim.type) == GX::TRIANGLESTRIP) { + atUint8 flip = 0; + for (size_t v = 0; v < prim.indexCount - 2; ++v) { + if (flip) { + os.format("add_triangle(bm, (%u,%u,%u))\n", primVerts[c % 3], primVerts[(c + 2) % 3], + primVerts[(c + 1) % 3]); + } else { + os.format("add_triangle(bm, (%u,%u,%u))\n", primVerts[c % 3], primVerts[(c + 1) % 3], + primVerts[(c + 2) % 3]); + } + flip ^= 1; + + /* Break if done */ + if (iit == prim.indices.cend()) + break; + + bool peek = (v >= prim.indexCount - 3); + + /* Advance one prim vert */ + if (peek) + primVerts[c % 3] = *iit; + else + primVerts[c % 3] = *iit++; + ++c; + } + } else if (GX::Primitive(prim.type) == GX::TRIANGLES) { + for (size_t v = 0; v < prim.indexCount; v += 3) { + os.format("add_triangle(bm, (%u,%u,%u))\n", primVerts[0], primVerts[1], primVerts[2]); + + /* Break if done */ + if (v + 3 >= prim.indexCount) + break; + + /* Advance 3 Prim Verts */ + for (int pv = 0; pv < 3; ++pv) + primVerts[pv] = *iit++; + } + } + } + + for (const typename MAPA::Surface::Border& border : surf.borders) { + auto iit = border.indices.cbegin(); + for (size_t i = 0; i < border.indexCount - 1; ++i) { + os.format("add_border(bm, (%u,%u))\n", *iit, *(iit + 1)); + ++iit; + } + } + } + + os << "mesh = bpy.data.meshes.new('MAP')\n" + "mesh.show_edge_seams = True\n" + "obj = bpy.data.objects.new(mesh.name, mesh)\n" + "bm.to_mesh(mesh)\n" + "bpy.context.scene.objects.link(obj)\n" + "bm.free()\n"; + + const zeus::CMatrix4f* tmpMtx = pakRouter.lookupMAPATransform(entry.id); + const zeus::CMatrix4f& mtx = tmpMtx ? *tmpMtx : zeus::CMatrix4f::skIdentityMatrix4f; + os.format( + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "obj.rotation_mode = 'QUATERNION'\n" + "obj.location = mtxd[0]\n" + "obj.rotation_quaternion = mtxd[1]\n" + "obj.scale = mtxd[2]\n", + mtx[0][0], mtx[1][0], mtx[2][0], mtx[3][0], mtx[0][1], mtx[1][1], mtx[2][1], mtx[3][1], mtx[0][2], mtx[1][2], + mtx[2][2], mtx[3][2]); + + /* World background */ + hecl::ProjectPath worldBlend(outPath.getParentPath().getParentPath(), "!world.blend"); + if (worldBlend.isFile()) + os.linkBackground("//../!world.blend", "World"); + + os.centerView(); + os.close(); + conn.saveBlend(); + return true; } -template bool ReadMAPAToBlender> -(hecl::blender::Connection& conn, - const MAPA& mapa, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - bool force); +template bool ReadMAPAToBlender>(hecl::blender::Connection& conn, const MAPA& mapa, + const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, + bool force); -template bool ReadMAPAToBlender> -(hecl::blender::Connection& conn, - const MAPA& mapa, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - bool force); +template bool ReadMAPAToBlender>(hecl::blender::Connection& conn, const MAPA& mapa, + const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, + bool force); -template bool ReadMAPAToBlender> -(hecl::blender::Connection& conn, - const MAPA& mapa, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - bool force); +template bool ReadMAPAToBlender>(hecl::blender::Connection& conn, const MAPA& mapa, + const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, + bool force); template -bool Cook(const hecl::blender::MapArea& mapaIn, const hecl::ProjectPath& out) -{ - if (mapaIn.verts.size() >= 256) - { - Log.report(logvisor::Error, _SYS_STR("MAPA %s vertex range exceeded [%d/%d]"), - out.getRelativePath().data(), mapaIn.verts.size(), 255); - return false; +bool Cook(const hecl::blender::MapArea& mapaIn, const hecl::ProjectPath& out) { + if (mapaIn.verts.size() >= 256) { + Log.report(logvisor::Error, _SYS_STR("MAPA %s vertex range exceeded [%d/%d]"), out.getRelativePath().data(), + mapaIn.verts.size(), 255); + return false; + } + + MAPAType mapa; + mapa.magic = 0xDEADD00D; + mapa.version = MAPAType::Version(); + + zeus::CAABox aabb; + for (const hecl::blender::Vector3f& vert : mapaIn.verts) + aabb.accumulateBounds(vert.val); + + mapa.header = std::make_unique(); + typename MAPAType::Header& header = static_cast(*mapa.header); + header.unknown1 = 0; + header.mapVisMode = mapaIn.visType.val; + header.boundingBox[0] = aabb.min; + header.boundingBox[1] = aabb.max; + header.moCount = mapaIn.pois.size(); + header.vtxCount = mapaIn.verts.size(); + header.surfCount = mapaIn.surfaces.size(); + + mapa.mappableObjects.reserve(mapaIn.pois.size()); + for (const hecl::blender::MapArea::POI& poi : mapaIn.pois) { + mapa.mappableObjects.push_back(std::make_unique()); + typename MAPAType::MappableObject& mobj = + static_cast(*mapa.mappableObjects.back()); + mobj.type = MAPA::IMappableObject::Type(poi.type); + mobj.visMode = poi.visMode; + mobj.sclyId = poi.objid; + mobj.transformMtx[0] = poi.xf.val[0]; + mobj.transformMtx[1] = poi.xf.val[1]; + mobj.transformMtx[2] = poi.xf.val[2]; + } + + mapa.vertices.reserve(mapaIn.verts.size()); + for (const hecl::blender::Vector3f& vert : mapaIn.verts) + mapa.vertices.push_back(vert.val); + + size_t offsetCur = 0; + for (const auto& mo : mapa.mappableObjects) + mo->binarySize(offsetCur); + offsetCur += mapa.vertices.size() * 12; + offsetCur += mapaIn.surfaces.size() * 32; + + mapa.surfaceHeaders.reserve(mapaIn.surfaces.size()); + mapa.surfaces.reserve(mapaIn.surfaces.size()); + for (const hecl::blender::MapArea::Surface& surfIn : mapaIn.surfaces) { + mapa.surfaceHeaders.emplace_back(); + DNAMAPA::MAPA::SurfaceHeader& surfHead = mapa.surfaceHeaders.back(); + mapa.surfaces.emplace_back(); + DNAMAPA::MAPA::Surface& surf = mapa.surfaces.back(); + + surf.primitiveCount = 1; + surf.primitives.emplace_back(); + DNAMAPA::MAPA::Surface::Primitive& prim = surf.primitives.back(); + prim.type = GX::TRIANGLESTRIP; + prim.indexCount = surfIn.count; + prim.indices.reserve(surfIn.count); + auto itBegin = mapaIn.indices.begin() + surfIn.start.val; + auto itEnd = itBegin + surfIn.count; + for (auto it = itBegin; it != itEnd; ++it) + prim.indices.push_back(it->val); + + surf.borderCount = surfIn.borders.size(); + surf.borders.reserve(surfIn.borders.size()); + for (const auto& borderIn : surfIn.borders) { + surf.borders.emplace_back(); + DNAMAPA::MAPA::Surface::Border& border = surf.borders.back(); + border.indexCount = borderIn.second.val; + border.indices.reserve(borderIn.second.val); + auto it2Begin = mapaIn.indices.begin() + borderIn.first.val; + auto it2End = it2Begin + borderIn.second.val; + for (auto it = it2Begin; it != it2End; ++it) + border.indices.push_back(it->val); } - MAPAType mapa; - mapa.magic = 0xDEADD00D; - mapa.version = MAPAType::Version(); + surfHead.normal = surfIn.normal.val; + surfHead.centroid = surfIn.centerOfMass; + surfHead.polyOff = offsetCur; + offsetCur += 4; + prim.binarySize(offsetCur); + surfHead.edgeOff = offsetCur; + offsetCur += 4; + for (const auto& border : surf.borders) + border.binarySize(offsetCur); + } - zeus::CAABox aabb; - for (const hecl::blender::Vector3f& vert : mapaIn.verts) - aabb.accumulateBounds(vert.val); - - mapa.header = std::make_unique(); - typename MAPAType::Header& header = static_cast(*mapa.header); - header.unknown1 = 0; - header.mapVisMode = mapaIn.visType.val; - header.boundingBox[0] = aabb.min; - header.boundingBox[1] = aabb.max; - header.moCount = mapaIn.pois.size(); - header.vtxCount = mapaIn.verts.size(); - header.surfCount = mapaIn.surfaces.size(); - - mapa.mappableObjects.reserve(mapaIn.pois.size()); - for (const hecl::blender::MapArea::POI& poi : mapaIn.pois) - { - mapa.mappableObjects.push_back(std::make_unique()); - typename MAPAType::MappableObject& mobj = - static_cast(*mapa.mappableObjects.back()); - mobj.type = MAPA::IMappableObject::Type(poi.type); - mobj.visMode = poi.visMode; - mobj.sclyId = poi.objid; - mobj.transformMtx[0] = poi.xf.val[0]; - mobj.transformMtx[1] = poi.xf.val[1]; - mobj.transformMtx[2] = poi.xf.val[2]; - } - - mapa.vertices.reserve(mapaIn.verts.size()); - for (const hecl::blender::Vector3f& vert : mapaIn.verts) - mapa.vertices.push_back(vert.val); - - size_t offsetCur = 0; - for (const auto& mo : mapa.mappableObjects) - mo->binarySize(offsetCur); - offsetCur += mapa.vertices.size() * 12; - offsetCur += mapaIn.surfaces.size() * 32; - - mapa.surfaceHeaders.reserve(mapaIn.surfaces.size()); - mapa.surfaces.reserve(mapaIn.surfaces.size()); - for (const hecl::blender::MapArea::Surface& surfIn : mapaIn.surfaces) - { - mapa.surfaceHeaders.emplace_back(); - DNAMAPA::MAPA::SurfaceHeader& surfHead = mapa.surfaceHeaders.back(); - mapa.surfaces.emplace_back(); - DNAMAPA::MAPA::Surface& surf = mapa.surfaces.back(); - - surf.primitiveCount = 1; - surf.primitives.emplace_back(); - DNAMAPA::MAPA::Surface::Primitive& prim = surf.primitives.back(); - prim.type = GX::TRIANGLESTRIP; - prim.indexCount = surfIn.count; - prim.indices.reserve(surfIn.count); - auto itBegin = mapaIn.indices.begin() + surfIn.start.val; - auto itEnd = itBegin + surfIn.count; - for (auto it = itBegin ; it != itEnd ; ++it) - prim.indices.push_back(it->val); - - surf.borderCount = surfIn.borders.size(); - surf.borders.reserve(surfIn.borders.size()); - for (const auto& borderIn : surfIn.borders) - { - surf.borders.emplace_back(); - DNAMAPA::MAPA::Surface::Border& border = surf.borders.back(); - border.indexCount = borderIn.second.val; - border.indices.reserve(borderIn.second.val); - auto it2Begin = mapaIn.indices.begin() + borderIn.first.val; - auto it2End = it2Begin + borderIn.second.val; - for (auto it = it2Begin ; it != it2End ; ++it) - border.indices.push_back(it->val); - } - - surfHead.normal = surfIn.normal.val; - surfHead.centroid = surfIn.centerOfMass; - surfHead.polyOff = offsetCur; - offsetCur += 4; - prim.binarySize(offsetCur); - surfHead.edgeOff = offsetCur; - offsetCur += 4; - for (const auto& border : surf.borders) - border.binarySize(offsetCur); - } - - athena::io::FileWriter f(out.getAbsolutePath()); - mapa.write(f); - int64_t rem = f.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - f.writeBytes((atInt8*)"\xff", 1); - return true; + athena::io::FileWriter f(out.getAbsolutePath()); + mapa.write(f); + int64_t rem = f.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + f.writeBytes((atInt8*)"\xff", 1); + return true; } template bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out); template bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out); template bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out); -} +} // namespace DataSpec::DNAMAPA diff --git a/DataSpec/DNACommon/MAPA.hpp b/DataSpec/DNACommon/MAPA.hpp index e5dcf3871..59d045a40 100644 --- a/DataSpec/DNACommon/MAPA.hpp +++ b/DataSpec/DNACommon/MAPA.hpp @@ -3,190 +3,169 @@ #include "DNACommon.hpp" #include "GX.hpp" +namespace DataSpec::DNAMAPA { +struct MAPA : BigDNA { + AT_DECL_EXPLICIT_DNA + Value magic; + Value version; + struct IMAPAHeader : BigDNAV { + Delete _d; + virtual atUint32 visMode() const = 0; + virtual atUint32 mappableObjectCount() const = 0; + virtual atUint32 vertexCount() const = 0; + virtual atUint32 surfaceCount() const = 0; + }; -namespace DataSpec::DNAMAPA -{ -struct MAPA : BigDNA -{ - AT_DECL_EXPLICIT_DNA - Value magic; - Value version; - struct IMAPAHeader : BigDNAV - { - Delete _d; - virtual atUint32 visMode() const=0; - virtual atUint32 mappableObjectCount() const=0; - virtual atUint32 vertexCount() const=0; - virtual atUint32 surfaceCount() const=0; + struct HeaderMP1 : IMAPAHeader { + AT_DECL_DNA + AT_DECL_DNAV + Value unknown1 = 0; + Value mapVisMode = 0; + Value boundingBox[2] = {}; + Value moCount = 0; + Value vtxCount = 0; + Value surfCount = 0; + atUint32 visMode() const { return mapVisMode; } + atUint32 mappableObjectCount() const { return moCount; } + atUint32 vertexCount() const { return vtxCount; } + atUint32 surfaceCount() const { return surfCount; } + }; + + struct HeaderMP2 : IMAPAHeader { + AT_DECL_DNA + AT_DECL_DNAV + Value unknown1 = 0; + Value mapVisMode = 0; + Value boundingBox[2] = {}; + Value unknown3 = 0; + Value unknown4 = 0; + Value unknown5 = 0; + Value moCount = 0; + Value vtxCount = 0; + Value surfCount = 0; + atUint32 visMode() const { return mapVisMode; } + atUint32 mappableObjectCount() const { return moCount; } + atUint32 vertexCount() const { return vtxCount; } + atUint32 surfaceCount() const { return surfCount; } + }; + + struct HeaderMP3 : IMAPAHeader { + AT_DECL_DNA + AT_DECL_DNAV + Value unknown1 = 0; + Value mapVisMode = 0; + Value boundingBox[2] = {}; + Value unknown3 = 0; + Value unknown4 = 0; + Value unknown5 = 0; + Value unknown6 = 0; + Value moCount = 0; + Value vtxCount = 0; + Value surfCount = 0; + Value internalNameLength = 0; + Value unknown7 = 0; + String internalName; + atUint32 visMode() const { return mapVisMode; } + atUint32 mappableObjectCount() const { return moCount; } + atUint32 vertexCount() const { return vtxCount; } + atUint32 surfaceCount() const { return surfCount; } + }; + + std::unique_ptr header; + + struct IMappableObject : BigDNAV { + Delete _d; + enum class Type : atUint32 { + BlueDoor = 0, + ShieldDoor = 1, + IceDoor = 2, + WaveDoor = 3, + PlasmaDoor = 4, + BigDoor1 = 5, + BigDoor2 = 6, + IceDoorCeiling = 7, + IceDoorFloor = 8, + WaveDoorCeiling = 9, + WaveDoorFloor = 10, + IceDoorFloor2 = 13, + WaveDoorFloor2 = 14, + DownArrowYellow = 27, /* Maintenance Tunnel */ + UpArrowYellow = 28, /* Phazon Processing Center */ + DownArrowGreen = 29, /* Elevator A */ + UpArrowGreen = 30, /* Elite Control Access */ + DownArrowRed = 31, /* Elevator B */ + UpArrowRed = 32, /* Fungal Hall Access */ + TransportLift = 33, + SaveStation = 34, + MissileStation = 37 }; + }; - struct HeaderMP1 : IMAPAHeader - { - AT_DECL_DNA - AT_DECL_DNAV - Value unknown1 = 0; - Value mapVisMode = 0; - Value boundingBox[2] = {}; - Value moCount = 0; - Value vtxCount = 0; - Value surfCount = 0; - atUint32 visMode() const { return mapVisMode; } - atUint32 mappableObjectCount() const { return moCount;} - atUint32 vertexCount() const { return vtxCount; } - atUint32 surfaceCount() const { return surfCount; } + struct MappableObjectMP1_2 : IMappableObject { + AT_DECL_DNA + AT_DECL_DNAV + Value type; + Value visMode; + Value sclyId; + Value seek1 = -1; + Value transformMtx[3]; + Value seek2[4] = {-1, -1, -1, -1}; + }; + + struct MappableObjectMP3 : IMappableObject { + AT_DECL_DNA + AT_DECL_DNAV + Value type; + Value visMode; + Value sclyId; + Buffer unknownHash; + Value seek1 = -1; + Value transformMtx[3]; + Value seek2[4] = {-1, -1, -1, -1}; + }; + + std::vector> mappableObjects; + VectorvertexCount())> vertices; + + struct SurfaceHeader : BigDNA { + AT_DECL_DNA + Value normal; + Value centroid; + Value polyOff; + Value edgeOff; + }; + + VectorsurfaceCount())> surfaceHeaders; + + struct Surface : BigDNA { + AT_DECL_DNA + Value primitiveCount; + struct Primitive : BigDNA { + AT_DECL_DNA + Value type; + Value indexCount; + Vector indices; + Align<4> align; }; - - struct HeaderMP2 : IMAPAHeader - { - AT_DECL_DNA - AT_DECL_DNAV - Value unknown1 = 0; - Value mapVisMode = 0; - Value boundingBox[2] = {}; - Value unknown3 = 0; - Value unknown4 = 0; - Value unknown5 = 0; - Value moCount = 0; - Value vtxCount = 0; - Value surfCount = 0; - atUint32 visMode() const { return mapVisMode; } - atUint32 mappableObjectCount() const { return moCount;} - atUint32 vertexCount() const { return vtxCount; } - atUint32 surfaceCount() const { return surfCount; } + Vector primitives; + Value borderCount; + struct Border : BigDNA { + AT_DECL_DNA + Value indexCount; + Vector indices; + Align<4> align; }; + Vector borders; + }; - struct HeaderMP3 : IMAPAHeader - { - AT_DECL_DNA - AT_DECL_DNAV - Value unknown1 = 0; - Value mapVisMode = 0; - Value boundingBox[2] = {}; - Value unknown3 = 0; - Value unknown4 = 0; - Value unknown5 = 0; - Value unknown6 = 0; - Value moCount = 0; - Value vtxCount = 0; - Value surfCount = 0; - Value internalNameLength = 0; - Value unknown7 = 0; - String internalName; - atUint32 visMode() const { return mapVisMode; } - atUint32 mappableObjectCount() const { return moCount;} - atUint32 vertexCount() const { return vtxCount; } - atUint32 surfaceCount() const { return surfCount; } - }; - - - std::unique_ptr header; - - struct IMappableObject : BigDNAV - { - Delete _d; - enum class Type : atUint32 - { - BlueDoor = 0, - ShieldDoor = 1, - IceDoor = 2, - WaveDoor = 3, - PlasmaDoor = 4, - BigDoor1 = 5, - BigDoor2 = 6, - IceDoorCeiling = 7, - IceDoorFloor = 8, - WaveDoorCeiling = 9, - WaveDoorFloor = 10, - IceDoorFloor2 = 13, - WaveDoorFloor2 = 14, - DownArrowYellow = 27, /* Maintenance Tunnel */ - UpArrowYellow = 28, /* Phazon Processing Center */ - DownArrowGreen = 29, /* Elevator A */ - UpArrowGreen = 30, /* Elite Control Access */ - DownArrowRed = 31, /* Elevator B */ - UpArrowRed = 32, /* Fungal Hall Access */ - TransportLift = 33, - SaveStation = 34, - MissileStation = 37 - }; - }; - - struct MappableObjectMP1_2 : IMappableObject - { - AT_DECL_DNA - AT_DECL_DNAV - Value type; - Value visMode; - Value sclyId; - Value seek1 = -1; - Value transformMtx[3]; - Value seek2[4] = {-1, -1, -1, -1}; - }; - - struct MappableObjectMP3 : IMappableObject - { - AT_DECL_DNA - AT_DECL_DNAV - Value type; - Value visMode; - Value sclyId; - Buffer unknownHash; - Value seek1 = -1; - Value transformMtx[3]; - Value seek2[4] = {-1, -1, -1, -1}; - }; - - std::vector> mappableObjects; - VectorvertexCount())> vertices; - - struct SurfaceHeader : BigDNA - { - AT_DECL_DNA - Value normal; - Value centroid; - Value polyOff; - Value edgeOff; - }; - - VectorsurfaceCount())> surfaceHeaders; - - struct Surface : BigDNA - { - AT_DECL_DNA - Value primitiveCount; - struct Primitive : BigDNA - { - AT_DECL_DNA - Value type; - Value indexCount; - Vector indices; - Align<4> align; - }; - Vector primitives; - Value borderCount; - struct Border : BigDNA - { - AT_DECL_DNA - Value indexCount; - Vector indices; - Align<4> align; - }; - Vector borders; - }; - - VectorsurfaceCount())> surfaces; + VectorsurfaceCount())> surfaces; }; template -bool ReadMAPAToBlender(hecl::blender::Connection& conn, - const MAPA& mapa, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - bool force); +bool ReadMAPAToBlender(hecl::blender::Connection& conn, const MAPA& mapa, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force); template bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out); -} - +} // namespace DataSpec::DNAMAPA diff --git a/DataSpec/DNACommon/MAPU.cpp b/DataSpec/DNACommon/MAPU.cpp index 05265000f..ac5dc6324 100644 --- a/DataSpec/DNACommon/MAPU.cpp +++ b/DataSpec/DNACommon/MAPU.cpp @@ -5,157 +5,139 @@ #include "zeus/CTransform.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMAPU -{ +namespace DataSpec::DNAMAPU { template -bool ReadMAPUToBlender(hecl::blender::Connection& conn, - const MAPU& mapu, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - bool force) -{ - if (!force && outPath.isFile()) - return true; - - if (!conn.createBlend(outPath, hecl::blender::BlendType::MapUniverse)) - return false; - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - - os << "import bpy\n" - "from mathutils import Matrix\n" - "\n" - "# Clear Scene\n" - "bpy.context.scene.camera = None\n" - "for ob in bpy.data.objects:\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "\n" - "bpy.types.Object.retro_mapworld_color = bpy.props.FloatVectorProperty(name='Retro: MapWorld Color'," - " description='Sets map world color', subtype='COLOR', size=4, min=0.0, max=1.0)\n" - "bpy.types.Object.retro_mapworld_path = bpy.props.StringProperty(name='Retro: MapWorld Path'," - " description='Sets path to World root')\n" - "\n"; - - hecl::ProjectPath hexPath = pakRouter.getWorking(mapu.hexMapa); - os.linkBlend(hexPath.getAbsolutePathUTF8().data(), - pakRouter.getBestEntryName(mapu.hexMapa).data()); - os << "hexMesh = bpy.data.objects['MAP'].data\n"; - - for (const MAPU::World& wld : mapu.worlds) - { - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(wld.mlvl); - const MAPU::Transform& wldXf = wld.transform; - zeus::simd_floats wldXfF[3]; - for (int i = 0; i < 3; ++i) - wldXf.xf[i].simd.copy_to(wldXfF[i]); - zeus::simd_floats hexColorF(wld.hexColor.mSimd); - os.format("wldObj = bpy.data.objects.new('%s', None)\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "wldObj.rotation_mode = 'QUATERNION'\n" - "wldObj.location = mtxd[0]\n" - "wldObj.rotation_quaternion = mtxd[1]\n" - "wldObj.scale = mtxd[2]\n" - "wldObj.retro_mapworld_color = (%f, %f, %f, %f)\n" - "wldObj.retro_mapworld_path = '''%s'''\n" - "bpy.context.scene.objects.link(wldObj)\n", wld.name.c_str(), - wldXfF[0][0], wldXfF[0][1], wldXfF[0][2], wldXfF[0][3], - wldXfF[1][0], wldXfF[1][1], wldXfF[1][2], wldXfF[1][3], - wldXfF[2][0], wldXfF[2][1], wldXfF[2][2], wldXfF[2][3], - hexColorF[0], hexColorF[1], hexColorF[2], hexColorF[3], - path.getParentPath().getRelativePathUTF8().data()); - int idx = 0; - for (const MAPU::Transform& hexXf : wld.hexTransforms) - { - zeus::simd_floats hexXfF[3]; - for (int i = 0; i < 3; ++i) - hexXf.xf[i].simd.copy_to(hexXfF[i]); - os.format("obj = bpy.data.objects.new('%s_%d', hexMesh)\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "obj.rotation_mode = 'QUATERNION'\n" - "obj.location = mtxd[0]\n" - "obj.rotation_quaternion = mtxd[1]\n" - "obj.scale = mtxd[2]\n" - "bpy.context.scene.objects.link(obj)\n" - "obj.parent = wldObj\n", - wld.name.c_str(), idx++, - hexXfF[0][0], hexXfF[0][1], hexXfF[0][2], hexXfF[0][3], - hexXfF[1][0], hexXfF[1][1], hexXfF[1][2], hexXfF[1][3], - hexXfF[2][0], hexXfF[2][1], hexXfF[2][2], hexXfF[2][3]); - } - } - - os << "for screen in bpy.data.screens:\n" - " for area in screen.areas:\n" - " for space in area.spaces:\n" - " if space.type == 'VIEW_3D':\n" - " space.viewport_shade = 'SOLID'\n" - " space.clip_end = 8000.0\n"; - - os.centerView(); - os.close(); - conn.saveBlend(); +bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force) { + if (!force && outPath.isFile()) return true; -} -template bool ReadMAPUToBlender> -(hecl::blender::Connection& conn, - const MAPU& mapu, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - bool force); + if (!conn.createBlend(outPath, hecl::blender::BlendType::MapUniverse)) + return false; + hecl::blender::PyOutStream os = conn.beginPythonOut(true); -template bool ReadMAPUToBlender> -(hecl::blender::Connection& conn, - const MAPU& mapu, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - bool force); + os << "import bpy\n" + "from mathutils import Matrix\n" + "\n" + "# Clear Scene\n" + "bpy.context.scene.camera = None\n" + "for ob in bpy.data.objects:\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n" + "\n" + "bpy.types.Object.retro_mapworld_color = bpy.props.FloatVectorProperty(name='Retro: MapWorld Color'," + " description='Sets map world color', subtype='COLOR', size=4, min=0.0, max=1.0)\n" + "bpy.types.Object.retro_mapworld_path = bpy.props.StringProperty(name='Retro: MapWorld Path'," + " description='Sets path to World root')\n" + "\n"; -bool MAPU::Cook(const hecl::blender::MapUniverse& mapuIn, const hecl::ProjectPath& out) -{ - MAPU mapu; + hecl::ProjectPath hexPath = pakRouter.getWorking(mapu.hexMapa); + os.linkBlend(hexPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(mapu.hexMapa).data()); + os << "hexMesh = bpy.data.objects['MAP'].data\n"; - mapu.magic = 0xABCDEF01; - mapu.version = 1; - mapu.hexMapa = mapuIn.hexagonPath; - - mapu.worldCount = mapuIn.worlds.size(); - mapu.worlds.reserve(mapuIn.worlds.size()); - for (const hecl::blender::MapUniverse::World& wld : mapuIn.worlds) - { - mapu.worlds.emplace_back(); - MAPU::World& wldOut = mapu.worlds.back(); - wldOut.name = wld.name; - wldOut.mlvl = hecl::ProjectPath(wld.worldPath, _SYS_STR("!world.*")); - wldOut.transform.xf[0] = wld.xf.val[0]; - wldOut.transform.xf[1] = wld.xf.val[1]; - wldOut.transform.xf[2] = wld.xf.val[2]; - wldOut.hexCount = wld.hexagons.size(); - wldOut.hexTransforms.reserve(wld.hexagons.size()); - for (const hecl::blender::Matrix4f& mtx : wld.hexagons) - { - wldOut.hexTransforms.emplace_back(); - MAPU::Transform& xf = wldOut.hexTransforms.back(); - xf.xf[0] = mtx.val[0]; - xf.xf[1] = mtx.val[1]; - xf.xf[2] = mtx.val[2]; - } - wldOut.hexColor = zeus::CColor(wld.color.val); + for (const MAPU::World& wld : mapu.worlds) { + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(wld.mlvl); + const MAPU::Transform& wldXf = wld.transform; + zeus::simd_floats wldXfF[3]; + for (int i = 0; i < 3; ++i) + wldXf.xf[i].simd.copy_to(wldXfF[i]); + zeus::simd_floats hexColorF(wld.hexColor.mSimd); + os.format( + "wldObj = bpy.data.objects.new('%s', None)\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "wldObj.rotation_mode = 'QUATERNION'\n" + "wldObj.location = mtxd[0]\n" + "wldObj.rotation_quaternion = mtxd[1]\n" + "wldObj.scale = mtxd[2]\n" + "wldObj.retro_mapworld_color = (%f, %f, %f, %f)\n" + "wldObj.retro_mapworld_path = '''%s'''\n" + "bpy.context.scene.objects.link(wldObj)\n", + wld.name.c_str(), wldXfF[0][0], wldXfF[0][1], wldXfF[0][2], wldXfF[0][3], wldXfF[1][0], wldXfF[1][1], + wldXfF[1][2], wldXfF[1][3], wldXfF[2][0], wldXfF[2][1], wldXfF[2][2], wldXfF[2][3], hexColorF[0], hexColorF[1], + hexColorF[2], hexColorF[3], path.getParentPath().getRelativePathUTF8().data()); + int idx = 0; + for (const MAPU::Transform& hexXf : wld.hexTransforms) { + zeus::simd_floats hexXfF[3]; + for (int i = 0; i < 3; ++i) + hexXf.xf[i].simd.copy_to(hexXfF[i]); + os.format( + "obj = bpy.data.objects.new('%s_%d', hexMesh)\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "obj.rotation_mode = 'QUATERNION'\n" + "obj.location = mtxd[0]\n" + "obj.rotation_quaternion = mtxd[1]\n" + "obj.scale = mtxd[2]\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.parent = wldObj\n", + wld.name.c_str(), idx++, hexXfF[0][0], hexXfF[0][1], hexXfF[0][2], hexXfF[0][3], hexXfF[1][0], hexXfF[1][1], + hexXfF[1][2], hexXfF[1][3], hexXfF[2][0], hexXfF[2][1], hexXfF[2][2], hexXfF[2][3]); } + } - athena::io::FileWriter f(out.getAbsolutePath()); - mapu.write(f); - int64_t rem = f.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - f.writeBytes((atInt8*)"\xff", 1); - return true; + os << "for screen in bpy.data.screens:\n" + " for area in screen.areas:\n" + " for space in area.spaces:\n" + " if space.type == 'VIEW_3D':\n" + " space.viewport_shade = 'SOLID'\n" + " space.clip_end = 8000.0\n"; + + os.centerView(); + os.close(); + conn.saveBlend(); + return true; } +template bool ReadMAPUToBlender>(hecl::blender::Connection& conn, const MAPU& mapu, + const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, + bool force); + +template bool ReadMAPUToBlender>(hecl::blender::Connection& conn, const MAPU& mapu, + const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, + bool force); + +bool MAPU::Cook(const hecl::blender::MapUniverse& mapuIn, const hecl::ProjectPath& out) { + MAPU mapu; + + mapu.magic = 0xABCDEF01; + mapu.version = 1; + mapu.hexMapa = mapuIn.hexagonPath; + + mapu.worldCount = mapuIn.worlds.size(); + mapu.worlds.reserve(mapuIn.worlds.size()); + for (const hecl::blender::MapUniverse::World& wld : mapuIn.worlds) { + mapu.worlds.emplace_back(); + MAPU::World& wldOut = mapu.worlds.back(); + wldOut.name = wld.name; + wldOut.mlvl = hecl::ProjectPath(wld.worldPath, _SYS_STR("!world.*")); + wldOut.transform.xf[0] = wld.xf.val[0]; + wldOut.transform.xf[1] = wld.xf.val[1]; + wldOut.transform.xf[2] = wld.xf.val[2]; + wldOut.hexCount = wld.hexagons.size(); + wldOut.hexTransforms.reserve(wld.hexagons.size()); + for (const hecl::blender::Matrix4f& mtx : wld.hexagons) { + wldOut.hexTransforms.emplace_back(); + MAPU::Transform& xf = wldOut.hexTransforms.back(); + xf.xf[0] = mtx.val[0]; + xf.xf[1] = mtx.val[1]; + xf.xf[2] = mtx.val[2]; + } + wldOut.hexColor = zeus::CColor(wld.color.val); + } + + athena::io::FileWriter f(out.getAbsolutePath()); + mapu.write(f); + int64_t rem = f.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + f.writeBytes((atInt8*)"\xff", 1); + return true; } + +} // namespace DataSpec::DNAMAPU diff --git a/DataSpec/DNACommon/MAPU.hpp b/DataSpec/DNACommon/MAPU.hpp index 2ef725712..b101be7bc 100644 --- a/DataSpec/DNACommon/MAPU.hpp +++ b/DataSpec/DNACommon/MAPU.hpp @@ -2,42 +2,33 @@ #include "DNACommon.hpp" -namespace DataSpec::DNAMAPU -{ -struct MAPU : BigDNA -{ +namespace DataSpec::DNAMAPU { +struct MAPU : BigDNA { + AT_DECL_DNA + Value magic; + Value version; + UniqueID32 hexMapa; + Value worldCount; + struct Transform : BigDNA { AT_DECL_DNA - Value magic; - Value version; - UniqueID32 hexMapa; - Value worldCount; - struct Transform : BigDNA - { - AT_DECL_DNA - Value xf[3]; - }; - struct World : BigDNA - { - AT_DECL_DNA - String<-1> name; - UniqueID32 mlvl; - Transform transform; - Value hexCount; - Vector hexTransforms; - DNAColor hexColor; - }; - Vector worlds; + Value xf[3]; + }; + struct World : BigDNA { + AT_DECL_DNA + String<-1> name; + UniqueID32 mlvl; + Transform transform; + Value hexCount; + Vector hexTransforms; + DNAColor hexColor; + }; + Vector worlds; - static bool Cook(const hecl::blender::MapUniverse& mapu, const hecl::ProjectPath& out); + static bool Cook(const hecl::blender::MapUniverse& mapu, const hecl::ProjectPath& out); }; template -bool ReadMAPUToBlender(hecl::blender::Connection& conn, - const MAPU& mapu, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - bool force); - -} +bool ReadMAPUToBlender(hecl::blender::Connection& conn, const MAPU& mapu, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force); +} // namespace DataSpec::DNAMAPU diff --git a/DataSpec/DNACommon/MLVL.cpp b/DataSpec/DNACommon/MLVL.cpp index c699e6dcc..b31d9962e 100644 --- a/DataSpec/DNACommon/MLVL.cpp +++ b/DataSpec/DNACommon/MLVL.cpp @@ -4,130 +4,109 @@ #include "../DNAMP3/MLVL.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMLVL -{ +namespace DataSpec::DNAMLVL { template -bool ReadMLVLToBlender(hecl::blender::Connection& conn, - const MLVL& mlvl, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - bool force, - std::function fileChanged) -{ - hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true); - if (!force && blendPath.isFile()) - return true; - - /* Create World Blend */ - if (!conn.createBlend(blendPath, hecl::blender::BlendType::World)) - return false; - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "from mathutils import Matrix\n" - "\n" - "bpy.context.scene.name = 'World'\n" - "\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n"); - - /* Insert area empties */ - int areaIdx = 0; - for (const auto& area : mlvl.areas) - { - const typename PAKRouter::EntryType* mreaEntry = pakRouter.lookupEntry(area.areaMREAId); - hecl::SystemUTF8Conv areaDirName(*mreaEntry->unique.m_areaName); - - os.AABBToBMesh(area.aabb[0], area.aabb[1]); - zeus::simd_floats xfMtxF[3]; - for (int i = 0; i < 3; ++i) - area.transformMtx[i].simd.copy_to(xfMtxF[i]); - os.format("box_mesh = bpy.data.meshes.new('''%s''')\n" - "bm.to_mesh(box_mesh)\n" - "bm.free()\n" - "box = bpy.data.objects.new(box_mesh.name, box_mesh)\n" - "bpy.context.scene.objects.link(box)\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "box.rotation_mode = 'QUATERNION'\n" - "box.location = mtxd[0]\n" - "box.rotation_quaternion = mtxd[1]\n" - "box.scale = mtxd[2]\n", - areaDirName.str().data(), - xfMtxF[0][0], xfMtxF[0][1], xfMtxF[0][2], xfMtxF[0][3], - xfMtxF[1][0], xfMtxF[1][1], xfMtxF[1][2], xfMtxF[1][3], - xfMtxF[2][0], xfMtxF[2][1], xfMtxF[2][2], xfMtxF[2][3]); - - /* Insert dock planes */ - int dockIdx = 0; - for (const auto& dock : area.docks) - { - os << "bm = bmesh.new()\n"; - zeus::CVector3f pvAvg; - for (const atVec3f& pv : dock.planeVerts) - pvAvg += pv; - pvAvg /= zeus::CVector3f(dock.planeVerts.size()); - int idx = 0; - for (const atVec3f& pv : dock.planeVerts) - { - const zeus::CVector3f pvRel = zeus::CVector3f(pv) - pvAvg; - os.format("bm.verts.new((%f,%f,%f))\n" - "bm.verts.ensure_lookup_table()\n", - pvRel[0], pvRel[1], pvRel[2]); - if (idx) - os << "bm.edges.new((bm.verts[-2], bm.verts[-1]))\n"; - ++idx; - } - os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n"; - os.format("dockMesh = bpy.data.meshes.new('DOCK_%02d_%02d')\n", areaIdx, dockIdx); - os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n" - "bpy.context.scene.objects.link(dockObj)\n" - "bm.to_mesh(dockMesh)\n" - "bm.free()\n" - "dockObj.parent = box\n"; - os.format("dockObj.location = (%f,%f,%f)\n", - float(pvAvg[0]), float(pvAvg[1]), float(pvAvg[2])); - ++dockIdx; - } - ++areaIdx; - } - - os.centerView(); - os.close(); - conn.saveBlend(); +bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force, + std::function fileChanged) { + hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true); + if (!force && blendPath.isFile()) return true; + + /* Create World Blend */ + if (!conn.createBlend(blendPath, hecl::blender::BlendType::World)) + return false; + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os.format( + "import bpy\n" + "import bmesh\n" + "from mathutils import Matrix\n" + "\n" + "bpy.context.scene.name = 'World'\n" + "\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " if ob.type != 'CAMERA':\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n"); + + /* Insert area empties */ + int areaIdx = 0; + for (const auto& area : mlvl.areas) { + const typename PAKRouter::EntryType* mreaEntry = pakRouter.lookupEntry(area.areaMREAId); + hecl::SystemUTF8Conv areaDirName(*mreaEntry->unique.m_areaName); + + os.AABBToBMesh(area.aabb[0], area.aabb[1]); + zeus::simd_floats xfMtxF[3]; + for (int i = 0; i < 3; ++i) + area.transformMtx[i].simd.copy_to(xfMtxF[i]); + os.format( + "box_mesh = bpy.data.meshes.new('''%s''')\n" + "bm.to_mesh(box_mesh)\n" + "bm.free()\n" + "box = bpy.data.objects.new(box_mesh.name, box_mesh)\n" + "bpy.context.scene.objects.link(box)\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "box.rotation_mode = 'QUATERNION'\n" + "box.location = mtxd[0]\n" + "box.rotation_quaternion = mtxd[1]\n" + "box.scale = mtxd[2]\n", + areaDirName.str().data(), xfMtxF[0][0], xfMtxF[0][1], xfMtxF[0][2], xfMtxF[0][3], xfMtxF[1][0], xfMtxF[1][1], + xfMtxF[1][2], xfMtxF[1][3], xfMtxF[2][0], xfMtxF[2][1], xfMtxF[2][2], xfMtxF[2][3]); + + /* Insert dock planes */ + int dockIdx = 0; + for (const auto& dock : area.docks) { + os << "bm = bmesh.new()\n"; + zeus::CVector3f pvAvg; + for (const atVec3f& pv : dock.planeVerts) + pvAvg += pv; + pvAvg /= zeus::CVector3f(dock.planeVerts.size()); + int idx = 0; + for (const atVec3f& pv : dock.planeVerts) { + const zeus::CVector3f pvRel = zeus::CVector3f(pv) - pvAvg; + os.format( + "bm.verts.new((%f,%f,%f))\n" + "bm.verts.ensure_lookup_table()\n", + pvRel[0], pvRel[1], pvRel[2]); + if (idx) + os << "bm.edges.new((bm.verts[-2], bm.verts[-1]))\n"; + ++idx; + } + os << "bm.edges.new((bm.verts[-1], bm.verts[0]))\n"; + os.format("dockMesh = bpy.data.meshes.new('DOCK_%02d_%02d')\n", areaIdx, dockIdx); + os << "dockObj = bpy.data.objects.new(dockMesh.name, dockMesh)\n" + "bpy.context.scene.objects.link(dockObj)\n" + "bm.to_mesh(dockMesh)\n" + "bm.free()\n" + "dockObj.parent = box\n"; + os.format("dockObj.location = (%f,%f,%f)\n", float(pvAvg[0]), float(pvAvg[1]), float(pvAvg[2])); + ++dockIdx; + } + ++areaIdx; + } + + os.centerView(); + os.close(); + conn.saveBlend(); + return true; } -template bool ReadMLVLToBlender, DNAMP1::MLVL> -(hecl::blender::Connection& conn, - const DNAMP1::MLVL& mlvl, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - bool force, - std::function fileChanged); +template bool ReadMLVLToBlender, DNAMP1::MLVL>( + hecl::blender::Connection& conn, const DNAMP1::MLVL& mlvl, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAKRouter::EntryType& entry, bool force, + std::function fileChanged); -template bool ReadMLVLToBlender, DNAMP2::MLVL> -(hecl::blender::Connection& conn, - const DNAMP2::MLVL& mlvl, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - bool force, - std::function fileChanged); +template bool ReadMLVLToBlender, DNAMP2::MLVL>( + hecl::blender::Connection& conn, const DNAMP2::MLVL& mlvl, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAKRouter::EntryType& entry, bool force, + std::function fileChanged); -template bool ReadMLVLToBlender, DNAMP3::MLVL> -(hecl::blender::Connection& conn, - const DNAMP3::MLVL& mlvl, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - bool force, - std::function fileChanged); +template bool ReadMLVLToBlender, DNAMP3::MLVL>( + hecl::blender::Connection& conn, const DNAMP3::MLVL& mlvl, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAKRouter::EntryType& entry, bool force, + std::function fileChanged); -} +} // namespace DataSpec::DNAMLVL diff --git a/DataSpec/DNACommon/MLVL.hpp b/DataSpec/DNACommon/MLVL.hpp index 5fce304e1..c2fa0271a 100644 --- a/DataSpec/DNACommon/MLVL.hpp +++ b/DataSpec/DNACommon/MLVL.hpp @@ -3,17 +3,11 @@ #include "DNACommon.hpp" #include "zeus/CVector3f.hpp" -namespace DataSpec::DNAMLVL -{ +namespace DataSpec::DNAMLVL { template -bool ReadMLVLToBlender(hecl::blender::Connection& conn, - const MLVL& mlvl, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const typename PAKRouter::EntryType& entry, - bool force, +bool ReadMLVLToBlender(hecl::blender::Connection& conn, const MLVL& mlvl, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const typename PAKRouter::EntryType& entry, bool force, std::function fileChanged); } - diff --git a/DataSpec/DNACommon/OBBTreeBuilder.cpp b/DataSpec/DNACommon/OBBTreeBuilder.cpp index 895fdcacf..861e9db80 100644 --- a/DataSpec/DNACommon/OBBTreeBuilder.cpp +++ b/DataSpec/DNACommon/OBBTreeBuilder.cpp @@ -5,86 +5,80 @@ #include "gmm/gmm.h" #include "hecl/Blender/Connection.hpp" -namespace DataSpec -{ +namespace DataSpec { using ColMesh = hecl::blender::ColMesh; -struct FittedOBB -{ - zeus::CTransform xf; - zeus::CVector3f he; +struct FittedOBB { + zeus::CTransform xf; + zeus::CVector3f he; }; -static std::vector MakeRootTriangleIndex(const ColMesh& mesh) -{ - std::vector ret; - ret.reserve(mesh.trianges.size()); - for (int i = 0; i < mesh.trianges.size(); ++i) - ret.push_back(i); - return ret; +static std::vector MakeRootTriangleIndex(const ColMesh& mesh) { + std::vector ret; + ret.reserve(mesh.trianges.size()); + for (int i = 0; i < mesh.trianges.size(); ++i) + ret.push_back(i); + return ret; } -static std::unordered_set GetTriangleVerts(const ColMesh& mesh, int triIdx) -{ - const ColMesh::Triangle& T = mesh.trianges[triIdx]; - std::unordered_set verts; - verts.insert(mesh.edges[T.edges[0]].verts[0]); - verts.insert(mesh.edges[T.edges[0]].verts[1]); - verts.insert(mesh.edges[T.edges[1]].verts[0]); - verts.insert(mesh.edges[T.edges[1]].verts[1]); - verts.insert(mesh.edges[T.edges[2]].verts[0]); - verts.insert(mesh.edges[T.edges[2]].verts[1]); - return verts; +static std::unordered_set GetTriangleVerts(const ColMesh& mesh, int triIdx) { + const ColMesh::Triangle& T = mesh.trianges[triIdx]; + std::unordered_set verts; + verts.insert(mesh.edges[T.edges[0]].verts[0]); + verts.insert(mesh.edges[T.edges[0]].verts[1]); + verts.insert(mesh.edges[T.edges[1]].verts[0]); + verts.insert(mesh.edges[T.edges[1]].verts[1]); + verts.insert(mesh.edges[T.edges[2]].verts[0]); + verts.insert(mesh.edges[T.edges[2]].verts[1]); + return verts; } // method to set the OBB parameters which produce a box oriented according to // the covariance matrix C, which just containts the points pnts -static FittedOBB BuildFromCovarianceMatrix(gmm::dense_matrix& C, - const ColMesh& mesh, const std::vector& index) -{ - FittedOBB ret; +static FittedOBB BuildFromCovarianceMatrix(gmm::dense_matrix& C, const ColMesh& mesh, + const std::vector& index) { + FittedOBB ret; - // extract the eigenvalues and eigenvectors from C - gmm::dense_matrix eigvec(3,3); - std::vector eigval(3); - using namespace gmm; - using MAT1 = gmm::dense_matrix; - gmm::symmetric_qr_algorithm(C, eigval, eigvec, default_tol_for_qr); + // extract the eigenvalues and eigenvectors from C + gmm::dense_matrix eigvec(3, 3); + std::vector eigval(3); + using namespace gmm; + using MAT1 = gmm::dense_matrix; + gmm::symmetric_qr_algorithm(C, eigval, eigvec, default_tol_for_qr); - // find the right, up and forward vectors from the eigenvectors - zeus::CVector3f r(eigvec(0,0), eigvec(1,0), eigvec(2,0)); - zeus::CVector3f u(eigvec(0,1), eigvec(1,1), eigvec(2,1)); - zeus::CVector3f f(eigvec(0,2), eigvec(1,2), eigvec(2,2)); - r.normalize(); u.normalize(), f.normalize(); + // find the right, up and forward vectors from the eigenvectors + zeus::CVector3f r(eigvec(0, 0), eigvec(1, 0), eigvec(2, 0)); + zeus::CVector3f u(eigvec(0, 1), eigvec(1, 1), eigvec(2, 1)); + zeus::CVector3f f(eigvec(0, 2), eigvec(1, 2), eigvec(2, 2)); + r.normalize(); + u.normalize(), f.normalize(); - // set the rotation matrix using the eigvenvectors - ret.xf.basis[0] = r; - ret.xf.basis[1] = u; - ret.xf.basis[2] = f; + // set the rotation matrix using the eigvenvectors + ret.xf.basis[0] = r; + ret.xf.basis[1] = u; + ret.xf.basis[2] = f; - // now build the bounding box extents in the rotated frame - zeus::CVector3f minim(1e10f, 1e10f, 1e10f), maxim(-1e10f, -1e10f, -1e10f); - for (int triIdx : index) - { - std::unordered_set verts = GetTriangleVerts(mesh, triIdx); - for (uint32_t v : verts) - { - const zeus::CVector3f& p = mesh.verts[v].val; - zeus::CVector3f p_prime(r.dot(p), u.dot(p), f.dot(p)); - minim = zeus::min(minim, p_prime); - maxim = zeus::max(maxim, p_prime); - } + // now build the bounding box extents in the rotated frame + zeus::CVector3f minim(1e10f, 1e10f, 1e10f), maxim(-1e10f, -1e10f, -1e10f); + for (int triIdx : index) { + std::unordered_set verts = GetTriangleVerts(mesh, triIdx); + for (uint32_t v : verts) { + const zeus::CVector3f& p = mesh.verts[v].val; + zeus::CVector3f p_prime(r.dot(p), u.dot(p), f.dot(p)); + minim = zeus::min(minim, p_prime); + maxim = zeus::max(maxim, p_prime); } + } - // set the center of the OBB to be the average of the - // minimum and maximum, and the extents be half of the - // difference between the minimum and maximum - zeus::CVector3f center = (maxim + minim) * 0.5f; - ret.xf.origin = ret.xf.basis * center; - ret.he = (maxim - minim) * 0.5f; + // set the center of the OBB to be the average of the + // minimum and maximum, and the extents be half of the + // difference between the minimum and maximum + zeus::CVector3f center = (maxim + minim) * 0.5f; + ret.xf.origin = ret.xf.basis * center; + ret.he = (maxim - minim) * 0.5f; - return ret; + return ret; } // builds an OBB from triangles specified as an array of @@ -93,166 +87,164 @@ static FittedOBB BuildFromCovarianceMatrix(gmm::dense_matrix& C, // method build_from_covariance_matrix() method to fit // the box. ALL points will be fit in the box, regardless // of whether they are indexed by a triangle or not. -static FittedOBB FitOBB(const ColMesh& mesh, const std::vector& index) -{ - float Ai, Am=0.0; - zeus::CVector3f mu, mui; - gmm::dense_matrix C(3,3); - float cxx=0.0, cxy=0.0, cxz=0.0, cyy=0.0, cyz=0.0, czz=0.0; +static FittedOBB FitOBB(const ColMesh& mesh, const std::vector& index) { + float Ai, Am = 0.0; + zeus::CVector3f mu, mui; + gmm::dense_matrix C(3, 3); + float cxx = 0.0, cxy = 0.0, cxz = 0.0, cyy = 0.0, cyz = 0.0, czz = 0.0; - // loop over the triangles this time to find the - // mean location - for (int i : index) - { - std::unordered_set verts = GetTriangleVerts(mesh, i); - auto it = verts.begin(); - zeus::CVector3f p = mesh.verts[*it++].val; - zeus::CVector3f q = mesh.verts[*it++].val; - zeus::CVector3f r = mesh.verts[*it++].val; - mui = (p+q+r)/3.f; - Ai = (q-p).cross(r-p).magnitude() / 2.f; - mu += mui*Ai; - Am += Ai; + // loop over the triangles this time to find the + // mean location + for (int i : index) { + std::unordered_set verts = GetTriangleVerts(mesh, i); + auto it = verts.begin(); + zeus::CVector3f p = mesh.verts[*it++].val; + zeus::CVector3f q = mesh.verts[*it++].val; + zeus::CVector3f r = mesh.verts[*it++].val; + mui = (p + q + r) / 3.f; + Ai = (q - p).cross(r - p).magnitude() / 2.f; + mu += mui * Ai; + Am += Ai; - // these bits set the c terms to Am*E[xx], Am*E[xy], Am*E[xz].... - cxx += ( 9.0*mui.x()*mui.x() + p.x()*p.x() + q.x()*q.x() + r.x()*r.x() )*(Ai/12.0); - cxy += ( 9.0*mui.x()*mui.y() + p.x()*p.y() + q.x()*q.y() + r.x()*r.y() )*(Ai/12.0); - cxz += ( 9.0*mui.x()*mui.z() + p.x()*p.z() + q.x()*q.z() + r.x()*r.z() )*(Ai/12.0); - cyy += ( 9.0*mui.y()*mui.y() + p.y()*p.y() + q.y()*q.y() + r.y()*r.y() )*(Ai/12.0); - cyz += ( 9.0*mui.y()*mui.z() + p.y()*p.z() + q.y()*q.z() + r.y()*r.z() )*(Ai/12.0); - } + // these bits set the c terms to Am*E[xx], Am*E[xy], Am*E[xz].... + cxx += (9.0 * mui.x() * mui.x() + p.x() * p.x() + q.x() * q.x() + r.x() * r.x()) * (Ai / 12.0); + cxy += (9.0 * mui.x() * mui.y() + p.x() * p.y() + q.x() * q.y() + r.x() * r.y()) * (Ai / 12.0); + cxz += (9.0 * mui.x() * mui.z() + p.x() * p.z() + q.x() * q.z() + r.x() * r.z()) * (Ai / 12.0); + cyy += (9.0 * mui.y() * mui.y() + p.y() * p.y() + q.y() * q.y() + r.y() * r.y()) * (Ai / 12.0); + cyz += (9.0 * mui.y() * mui.z() + p.y() * p.z() + q.y() * q.z() + r.y() * r.z()) * (Ai / 12.0); + } - if (zeus::close_enough(Am, 0.f)) - return {}; + if (zeus::close_enough(Am, 0.f)) + return {}; - // divide out the Am fraction from the average position and - // covariance terms - mu = mu / Am; - cxx /= Am; cxy /= Am; cxz /= Am; cyy /= Am; cyz /= Am; czz /= Am; + // divide out the Am fraction from the average position and + // covariance terms + mu = mu / Am; + cxx /= Am; + cxy /= Am; + cxz /= Am; + cyy /= Am; + cyz /= Am; + czz /= Am; - // now subtract off the E[x]*E[x], E[x]*E[y], ... terms - cxx -= mu.x()*mu.x(); cxy -= mu.x()*mu.y(); cxz -= mu.x()*mu.z(); - cyy -= mu.y()*mu.y(); cyz -= mu.y()*mu.z(); czz -= mu.z()*mu.z(); + // now subtract off the E[x]*E[x], E[x]*E[y], ... terms + cxx -= mu.x() * mu.x(); + cxy -= mu.x() * mu.y(); + cxz -= mu.x() * mu.z(); + cyy -= mu.y() * mu.y(); + cyz -= mu.y() * mu.z(); + czz -= mu.z() * mu.z(); - // now build the covariance matrix - C(0,0)=cxx; C(0,1)=cxy; C(0,2)=cxz; - C(1,0)=cxy; C(1,1)=cyy; C(1,2)=cyz; - C(2,0)=cxz; C(2,1)=cyz; C(2,2)=czz; + // now build the covariance matrix + C(0, 0) = cxx; + C(0, 1) = cxy; + C(0, 2) = cxz; + C(1, 0) = cxy; + C(1, 1) = cyy; + C(1, 2) = cyz; + C(2, 0) = cxz; + C(2, 1) = cyz; + C(2, 2) = czz; - // set the obb parameters from the covariance matrix - return BuildFromCovarianceMatrix(C, mesh, index); + // set the obb parameters from the covariance matrix + return BuildFromCovarianceMatrix(C, mesh, index); } template -static void MakeLeaf(const ColMesh& mesh, const std::vector& index, Node& n) -{ - n.left.reset(); - n.right.reset(); - n.isLeaf = true; - n.leafData = std::make_unique(); - n.leafData->triangleIndexCount = atUint32(index.size()); - n.leafData->triangleIndices.reserve(n.leafData->triangleIndexCount); - for (int i : index) - n.leafData->triangleIndices.push_back(i); +static void MakeLeaf(const ColMesh& mesh, const std::vector& index, Node& n) { + n.left.reset(); + n.right.reset(); + n.isLeaf = true; + n.leafData = std::make_unique(); + n.leafData->triangleIndexCount = atUint32(index.size()); + n.leafData->triangleIndices.reserve(n.leafData->triangleIndexCount); + for (int i : index) + n.leafData->triangleIndices.push_back(i); } template -static std::unique_ptr RecursiveMakeNode(const ColMesh& mesh, const std::vector& index) -{ - // calculate root OBB - FittedOBB obb = FitOBB(mesh, index); +static std::unique_ptr RecursiveMakeNode(const ColMesh& mesh, const std::vector& index) { + // calculate root OBB + FittedOBB obb = FitOBB(mesh, index); - // make results row-major and also invert the rotation basis - obb.xf.basis.transpose(); + // make results row-major and also invert the rotation basis + obb.xf.basis.transpose(); - std::unique_ptr n = std::make_unique(); - for (int i = 0; i < 3; ++i) - { - n->xf[i] = zeus::CVector4f{obb.xf.basis[i]}; - n->xf[i].simd[3] = float(obb.xf.origin[i]); - } - n->halfExtent = obb.he; - - // terminate branch when volume < 1.0 - if (obb.he[0] * obb.he[1] * obb.he[2] < 1.f) - { - MakeLeaf(mesh, index, *n); - return n; - } - - n->isLeaf = false; - - std::vector indexNeg[3]; - std::vector indexPos[3]; - for (int c = 0; c < 3; ++c) - { - // subdivide negative side - indexNeg[c].reserve(index.size()); - for (int i : index) - { - std::unordered_set verts = GetTriangleVerts(mesh, i); - for (uint32_t vtx : verts) - { - zeus::CVector3f v = mesh.verts[vtx].val; - v = obb.xf.basis * (v - obb.xf.origin); - if (v[c] < 0.f) - { - indexNeg[c].push_back(i); - break; - } - } - } - - // subdivide positive side - indexPos[c].reserve(index.size()); - for (int i : index) - { - std::unordered_set verts = GetTriangleVerts(mesh, i); - for (uint32_t vtx : verts) - { - zeus::CVector3f v = mesh.verts[vtx].val; - v = obb.xf.basis * (v - obb.xf.origin); - if (v[c] >= 0.f) - { - indexPos[c].push_back(i); - break; - } - } - } - } - - size_t idxMin = index.size(); - int minComp = -1; - for (int c = 0; c < 3; ++c) - { - size_t test = std::max(indexNeg[c].size(), indexPos[c].size()); - if (test < idxMin && test < index.size() * 3 / 4) - { - minComp = c; - idxMin = test; - } - } - - if (minComp == -1) - { - MakeLeaf(mesh, index, *n); - return n; - } - - n->left = RecursiveMakeNode(mesh, indexNeg[minComp]); - n->right = RecursiveMakeNode(mesh, indexPos[minComp]); + std::unique_ptr n = std::make_unique(); + for (int i = 0; i < 3; ++i) { + n->xf[i] = zeus::CVector4f{obb.xf.basis[i]}; + n->xf[i].simd[3] = float(obb.xf.origin[i]); + } + n->halfExtent = obb.he; + // terminate branch when volume < 1.0 + if (obb.he[0] * obb.he[1] * obb.he[2] < 1.f) { + MakeLeaf(mesh, index, *n); return n; + } + + n->isLeaf = false; + + std::vector indexNeg[3]; + std::vector indexPos[3]; + for (int c = 0; c < 3; ++c) { + // subdivide negative side + indexNeg[c].reserve(index.size()); + for (int i : index) { + std::unordered_set verts = GetTriangleVerts(mesh, i); + for (uint32_t vtx : verts) { + zeus::CVector3f v = mesh.verts[vtx].val; + v = obb.xf.basis * (v - obb.xf.origin); + if (v[c] < 0.f) { + indexNeg[c].push_back(i); + break; + } + } + } + + // subdivide positive side + indexPos[c].reserve(index.size()); + for (int i : index) { + std::unordered_set verts = GetTriangleVerts(mesh, i); + for (uint32_t vtx : verts) { + zeus::CVector3f v = mesh.verts[vtx].val; + v = obb.xf.basis * (v - obb.xf.origin); + if (v[c] >= 0.f) { + indexPos[c].push_back(i); + break; + } + } + } + } + + size_t idxMin = index.size(); + int minComp = -1; + for (int c = 0; c < 3; ++c) { + size_t test = std::max(indexNeg[c].size(), indexPos[c].size()); + if (test < idxMin && test < index.size() * 3 / 4) { + minComp = c; + idxMin = test; + } + } + + if (minComp == -1) { + MakeLeaf(mesh, index, *n); + return n; + } + + n->left = RecursiveMakeNode(mesh, indexNeg[minComp]); + n->right = RecursiveMakeNode(mesh, indexPos[minComp]); + + return n; } template -std::unique_ptr OBBTreeBuilder::buildCol(const ColMesh& mesh) -{ - std::vector root = MakeRootTriangleIndex(mesh); - return RecursiveMakeNode(mesh, root); +std::unique_ptr OBBTreeBuilder::buildCol(const ColMesh& mesh) { + std::vector root = MakeRootTriangleIndex(mesh); + return RecursiveMakeNode(mesh, root); } template std::unique_ptr OBBTreeBuilder::buildCol(const ColMesh& mesh); -} +} // namespace DataSpec diff --git a/DataSpec/DNACommon/OBBTreeBuilder.hpp b/DataSpec/DNACommon/OBBTreeBuilder.hpp index b33c6d869..a8db2f2d7 100644 --- a/DataSpec/DNACommon/OBBTreeBuilder.hpp +++ b/DataSpec/DNACommon/OBBTreeBuilder.hpp @@ -2,15 +2,12 @@ #include "DNACommon.hpp" -namespace DataSpec -{ +namespace DataSpec { -struct OBBTreeBuilder -{ - using ColMesh = hecl::blender::ColMesh; - template - static std::unique_ptr buildCol(const ColMesh& mesh); +struct OBBTreeBuilder { + using ColMesh = hecl::blender::ColMesh; + template + static std::unique_ptr buildCol(const ColMesh& mesh); }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/PAK.cpp b/DataSpec/DNACommon/PAK.cpp index d2d12ea0e..b58fa0622 100644 --- a/DataSpec/DNACommon/PAK.cpp +++ b/DataSpec/DNACommon/PAK.cpp @@ -3,103 +3,79 @@ #include "../DNAMP2/DNAMP2.hpp" #include "../DNAMP3/DNAMP3.hpp" -namespace DataSpec -{ +namespace DataSpec { template -void UniqueResult::checkEntry(const PAKBRIDGE& pakBridge, const typename PAKBRIDGE::PAKType::Entry& entry) -{ - UniqueResult::Type resultType = UniqueResult::Type::NotFound; - bool foundOneLayer = false; - const hecl::SystemString* levelName = nullptr; - typename PAKBRIDGE::PAKType::IDType levelId; - typename PAKBRIDGE::PAKType::IDType areaId; - unsigned layerIdx; - for (const auto& lpair : pakBridge.m_levelDeps) - { - if (entry.id == lpair.first) - { - levelName = &lpair.second.name; +void UniqueResult::checkEntry(const PAKBRIDGE& pakBridge, const typename PAKBRIDGE::PAKType::Entry& entry) { + UniqueResult::Type resultType = UniqueResult::Type::NotFound; + bool foundOneLayer = false; + const hecl::SystemString* levelName = nullptr; + typename PAKBRIDGE::PAKType::IDType levelId; + typename PAKBRIDGE::PAKType::IDType areaId; + unsigned layerIdx; + for (const auto& lpair : pakBridge.m_levelDeps) { + if (entry.id == lpair.first) { + levelName = &lpair.second.name; + resultType = UniqueResult::Type::Level; + break; + } + + for (const auto& pair : lpair.second.areas) { + unsigned l = 0; + for (const auto& layer : pair.second.layers) { + if (layer.resources.find(entry.id) != layer.resources.end()) { + if (foundOneLayer) { + if (areaId == pair.first) { + resultType = UniqueResult::Type::Area; + } else if (levelId == lpair.first) { + resultType = UniqueResult::Type::Level; + break; + } else { + m_type = UniqueResult::Type::Pak; + return; + } + continue; + } else + resultType = UniqueResult::Type::Layer; + levelName = &lpair.second.name; + levelId = lpair.first; + areaId = pair.first; + layerIdx = l; + foundOneLayer = true; + } + ++l; + } + if (pair.second.resources.find(entry.id) != pair.second.resources.end()) { + if (foundOneLayer) { + if (areaId == pair.first) { + resultType = UniqueResult::Type::Area; + } else if (levelId == lpair.first) { resultType = UniqueResult::Type::Level; break; - } - - for (const auto& pair : lpair.second.areas) - { - unsigned l=0; - for (const auto& layer : pair.second.layers) - { - if (layer.resources.find(entry.id) != layer.resources.end()) - { - if (foundOneLayer) - { - if (areaId == pair.first) - { - resultType = UniqueResult::Type::Area; - } - else if (levelId == lpair.first) - { - resultType = UniqueResult::Type::Level; - break; - } - else - { - m_type = UniqueResult::Type::Pak; - return; - } - continue; - } - else - resultType = UniqueResult::Type::Layer; - levelName = &lpair.second.name; - levelId = lpair.first; - areaId = pair.first; - layerIdx = l; - foundOneLayer = true; - } - ++l; - } - if (pair.second.resources.find(entry.id) != pair.second.resources.end()) - { - if (foundOneLayer) - { - if (areaId == pair.first) - { - resultType = UniqueResult::Type::Area; - } - else if (levelId == lpair.first) - { - resultType = UniqueResult::Type::Level; - break; - } - else - { - m_type = UniqueResult::Type::Pak; - return; - } - continue; - } - else - resultType = UniqueResult::Type::Area; - levelName = &lpair.second.name; - levelId = lpair.first; - areaId = pair.first; - foundOneLayer = true; - } - } + } else { + m_type = UniqueResult::Type::Pak; + return; + } + continue; + } else + resultType = UniqueResult::Type::Area; + levelName = &lpair.second.name; + levelId = lpair.first; + areaId = pair.first; + foundOneLayer = true; + } } - m_type = resultType; - m_levelName = levelName; - if (resultType == UniqueResult::Type::Layer || resultType == UniqueResult::Type::Area) - { - const typename PAKBRIDGE::Level::Area& area = pakBridge.m_levelDeps.at(levelId).areas.at(areaId); - m_areaName = &area.name; - if (resultType == UniqueResult::Type::Layer) - { - const typename PAKBRIDGE::Level::Area::Layer& layer = area.layers[layerIdx]; - m_layerName = &layer.name; - } + } + m_type = resultType; + m_levelName = levelName; + if (resultType == UniqueResult::Type::Layer || resultType == UniqueResult::Type::Area) { + const typename PAKBRIDGE::Level::Area& area = pakBridge.m_levelDeps.at(levelId).areas.at(areaId); + m_areaName = &area.name; + if (resultType == UniqueResult::Type::Layer) { + const typename PAKBRIDGE::Level::Area::Layer& layer = area.layers[layerIdx]; + m_layerName = &layer.name; } + } } template void UniqueResult::checkEntry(const DNAMP1::PAKBridge& pakBridge, @@ -109,684 +85,590 @@ template void UniqueResult::checkEntry(const DNAMP2::PAKBridge& pakBridge, template void UniqueResult::checkEntry(const DNAMP3::PAKBridge& pakBridge, const DNAMP3::PAKBridge::PAKType::Entry& entry); -hecl::ProjectPath UniqueResult::uniquePath(const hecl::ProjectPath& pakPath) const -{ - if (m_type == Type::Pak) - return pakPath; +hecl::ProjectPath UniqueResult::uniquePath(const hecl::ProjectPath& pakPath) const { + if (m_type == Type::Pak) + return pakPath; - hecl::ProjectPath levelDir; - if (m_levelName) - levelDir.assign(pakPath, *m_levelName); - else - levelDir = pakPath; + hecl::ProjectPath levelDir; + if (m_levelName) + levelDir.assign(pakPath, *m_levelName); + else + levelDir = pakPath; - if (m_type == Type::Area) - { - hecl::ProjectPath areaDir(levelDir, *m_areaName); - return areaDir; - } - else if (m_type == Type::Layer) - { - hecl::ProjectPath areaDir(levelDir, *m_areaName); - hecl::ProjectPath layerDir(areaDir, *m_layerName); - return layerDir; - } + if (m_type == Type::Area) { + hecl::ProjectPath areaDir(levelDir, *m_areaName); + return areaDir; + } else if (m_type == Type::Layer) { + hecl::ProjectPath areaDir(levelDir, *m_areaName); + hecl::ProjectPath layerDir(areaDir, *m_layerName); + return layerDir; + } - return levelDir; + return levelDir; } template -void PAKRouter::build(std::vector& bridges, std::function progress) -{ - m_bridges = &bridges; - m_bridgePaths.clear(); +void PAKRouter::build(std::vector& bridges, std::function progress) { + m_bridges = &bridges; + m_bridgePaths.clear(); - m_uniqueEntries.clear(); - m_sharedEntries.clear(); - m_charAssoc.m_cmdlRigs.clear(); - size_t count = 0; - float bridgesSz = bridges.size(); + m_uniqueEntries.clear(); + m_sharedEntries.clear(); + m_charAssoc.m_cmdlRigs.clear(); + size_t count = 0; + float bridgesSz = bridges.size(); - /* Route entries unique/shared per-pak */ - size_t bridgeIdx = 0; - for (BRIDGETYPE& bridge : bridges) - { - const auto& name = bridge.getName(); - hecl::SystemStringConv sysName(name); + /* Route entries unique/shared per-pak */ + size_t bridgeIdx = 0; + for (BRIDGETYPE& bridge : bridges) { + const auto& name = bridge.getName(); + hecl::SystemStringConv sysName(name); - hecl::SystemStringView::const_iterator extit = sysName.sys_str().end() - 4; - hecl::SystemString baseName(sysName.sys_str().begin(), extit); + hecl::SystemStringView::const_iterator extit = sysName.sys_str().end() - 4; + hecl::SystemString baseName(sysName.sys_str().begin(), extit); - m_bridgePaths.emplace_back(std::make_pair(hecl::ProjectPath(m_gameWorking, baseName), - hecl::ProjectPath(m_gameCooked, baseName))); + m_bridgePaths.emplace_back( + std::make_pair(hecl::ProjectPath(m_gameWorking, baseName), hecl::ProjectPath(m_gameCooked, baseName))); - /* Index this PAK */ - bridge.build(); + /* Index this PAK */ + bridge.build(); - /* Add to global entry lookup */ - const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); - for (const auto& entry : pak.m_entries) - { - if (!pak.m_noShare) - { - auto sSearch = m_sharedEntries.find(entry.first); - if (sSearch != m_sharedEntries.end()) - continue; - auto uSearch = m_uniqueEntries.find(entry.first); - if (uSearch != m_uniqueEntries.end()) - { - m_uniqueEntries.erase(uSearch); - m_sharedEntries[entry.first] = std::make_pair(bridgeIdx, &entry.second); - } - else - m_uniqueEntries[entry.first] = std::make_pair(bridgeIdx, &entry.second); - } - else - m_uniqueEntries[entry.first] = std::make_pair(bridgeIdx, &entry.second); - } - - /* Add RigPairs to global map */ - bridge.addCMDLRigPairs(*this, m_charAssoc); - - progress(++count / bridgesSz); - ++bridgeIdx; + /* Add to global entry lookup */ + const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + for (const auto& entry : pak.m_entries) { + if (!pak.m_noShare) { + auto sSearch = m_sharedEntries.find(entry.first); + if (sSearch != m_sharedEntries.end()) + continue; + auto uSearch = m_uniqueEntries.find(entry.first); + if (uSearch != m_uniqueEntries.end()) { + m_uniqueEntries.erase(uSearch); + m_sharedEntries[entry.first] = std::make_pair(bridgeIdx, &entry.second); + } else + m_uniqueEntries[entry.first] = std::make_pair(bridgeIdx, &entry.second); + } else + m_uniqueEntries[entry.first] = std::make_pair(bridgeIdx, &entry.second); } - /* Add named resources to catalog YAML files */ - for (BRIDGETYPE& bridge : bridges) - { - athena::io::YAMLDocWriter catalogWriter(nullptr); + /* Add RigPairs to global map */ + bridge.addCMDLRigPairs(*this, m_charAssoc); - enterPAKBridge(bridge); + progress(++count / bridgesSz); + ++bridgeIdx; + } - /* Add MAPA transforms to global map */ - bridge.addMAPATransforms(*this, m_mapaTransforms, m_overrideEntries); + /* Add named resources to catalog YAML files */ + for (BRIDGETYPE& bridge : bridges) { + athena::io::YAMLDocWriter catalogWriter(nullptr); - const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); - for (const auto& namedEntry : pak.m_nameEntries) - { - if (namedEntry.name == "holo_cinf") - continue; /* Problematic corner case */ - if (auto rec = catalogWriter.enterSubRecord(namedEntry.name.c_str())) - { - hecl::ProjectPath working = getWorking(namedEntry.id); - if (working.getAuxInfoUTF8().size()) - { - if (auto v = catalogWriter.enterSubVector(nullptr)) - { - catalogWriter.writeString(nullptr, working.getRelativePathUTF8()); - catalogWriter.writeString(nullptr, working.getAuxInfoUTF8()); - } - } - else - catalogWriter.writeString(nullptr, working.getRelativePathUTF8()); - } - } + enterPAKBridge(bridge); - /* Write catalog */ - intptr_t curBridgeIdx = reinterpret_cast(m_curBridgeIdx.get()); - const hecl::ProjectPath& pakPath = m_bridgePaths[curBridgeIdx].first; - pakPath.makeDirChain(true); - athena::io::FileWriter writer(hecl::ProjectPath(pakPath, "!catalog.yaml").getAbsolutePath()); - catalogWriter.finish(&writer); + /* Add MAPA transforms to global map */ + bridge.addMAPATransforms(*this, m_mapaTransforms, m_overrideEntries); + + const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + for (const auto& namedEntry : pak.m_nameEntries) { + if (namedEntry.name == "holo_cinf") + continue; /* Problematic corner case */ + if (auto rec = catalogWriter.enterSubRecord(namedEntry.name.c_str())) { + hecl::ProjectPath working = getWorking(namedEntry.id); + if (working.getAuxInfoUTF8().size()) { + if (auto v = catalogWriter.enterSubVector(nullptr)) { + catalogWriter.writeString(nullptr, working.getRelativePathUTF8()); + catalogWriter.writeString(nullptr, working.getAuxInfoUTF8()); + } + } else + catalogWriter.writeString(nullptr, working.getRelativePathUTF8()); + } } + + /* Write catalog */ + intptr_t curBridgeIdx = reinterpret_cast(m_curBridgeIdx.get()); + const hecl::ProjectPath& pakPath = m_bridgePaths[curBridgeIdx].first; + pakPath.makeDirChain(true); + athena::io::FileWriter writer(hecl::ProjectPath(pakPath, "!catalog.yaml").getAbsolutePath()); + catalogWriter.finish(&writer); + } } template -void PAKRouter::enterPAKBridge(const BRIDGETYPE& pakBridge) -{ - g_PakRouter.reset(this); - auto pit = m_bridgePaths.begin(); - size_t bridgeIdx = 0; - for (const BRIDGETYPE& bridge : *m_bridges) - { - if (&bridge == &pakBridge) - { - m_pak.reset(&pakBridge.getPAK()); - m_node.reset(&pakBridge.getNode()); - m_curBridgeIdx.reset(reinterpret_cast(bridgeIdx)); - return; - } - ++pit; - ++bridgeIdx; +void PAKRouter::enterPAKBridge(const BRIDGETYPE& pakBridge) { + g_PakRouter.reset(this); + auto pit = m_bridgePaths.begin(); + size_t bridgeIdx = 0; + for (const BRIDGETYPE& bridge : *m_bridges) { + if (&bridge == &pakBridge) { + m_pak.reset(&pakBridge.getPAK()); + m_node.reset(&pakBridge.getNode()); + m_curBridgeIdx.reset(reinterpret_cast(bridgeIdx)); + return; } - LogDNACommon.report(logvisor::Fatal, - "PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()"); + ++pit; + ++bridgeIdx; + } + LogDNACommon.report(logvisor::Fatal, "PAKBridge provided to PAKRouter::enterPAKBridge() was not part of build()"); } template -hecl::ProjectPath PAKRouter::getCharacterWorking(const EntryType* entry) const -{ - auto characterSearch = m_charAssoc.m_cskrCinfToCharacter.find(entry->id); - if (characterSearch != m_charAssoc.m_cskrCinfToCharacter.cend()) - { - hecl::ProjectPath characterPath = getWorking(characterSearch->second.first); - if (entry->type == FOURCC('EVNT')) - { - hecl::SystemStringConv wideStr(characterSearch->second.second); - return characterPath.getWithExtension((hecl::SystemString(_SYS_STR(".")) + wideStr.c_str()).c_str(), true); - } - return characterPath.ensureAuxInfo(characterSearch->second.second); +hecl::ProjectPath PAKRouter::getCharacterWorking(const EntryType* entry) const { + auto characterSearch = m_charAssoc.m_cskrCinfToCharacter.find(entry->id); + if (characterSearch != m_charAssoc.m_cskrCinfToCharacter.cend()) { + hecl::ProjectPath characterPath = getWorking(characterSearch->second.first); + if (entry->type == FOURCC('EVNT')) { + hecl::SystemStringConv wideStr(characterSearch->second.second); + return characterPath.getWithExtension((hecl::SystemString(_SYS_STR(".")) + wideStr.c_str()).c_str(), true); } - return {}; + return characterPath.ensureAuxInfo(characterSearch->second.second); + } + return {}; } template hecl::ProjectPath PAKRouter::getWorking(const EntryType* entry, - const ResExtractor& extractor) const -{ - if (!entry) - return hecl::ProjectPath(); - - auto overrideSearch = m_overrideEntries.find(entry->id); - if (overrideSearch != m_overrideEntries.end()) - return overrideSearch->second; - - const PAKType* pak = m_pak.get(); - intptr_t curBridgeIdx = reinterpret_cast(m_curBridgeIdx.get()); - if (pak && pak->m_noShare) - { - const EntryType* singleSearch = pak->lookupEntry(entry->id); - if (singleSearch) - { - const hecl::ProjectPath& pakPath = m_bridgePaths[curBridgeIdx].first; -#if HECL_UCS2 - hecl::SystemString entName = hecl::UTF8ToWide(getBestEntryName(*entry)); -#else - hecl::SystemString entName = getBestEntryName(*entry); -#endif - hecl::SystemString auxInfo; - if (extractor.fileExts[0] && !extractor.fileExts[1]) - entName += extractor.fileExts[0]; - else if (extractor.fileExts[0]) - entName += _SYS_STR(".*"); - else if (hecl::ProjectPath chWork = getCharacterWorking(entry)) - return chWork; - return hecl::ProjectPath(pakPath, entName).ensureAuxInfo(auxInfo); - } - } - - auto uniqueSearch = m_uniqueEntries.find(entry->id); - if (uniqueSearch != m_uniqueEntries.end()) - { - const BRIDGETYPE& bridge = m_bridges->at(uniqueSearch->second.first); - const hecl::ProjectPath& pakPath = m_bridgePaths[uniqueSearch->second.first].first; -#if HECL_UCS2 - hecl::SystemString entName = hecl::UTF8ToWide(getBestEntryName(*entry)); -#else - hecl::SystemString entName = getBestEntryName(*entry); -#endif - hecl::SystemString auxInfo; - if (extractor.fileExts[0] && !extractor.fileExts[1]) - entName += extractor.fileExts[0]; - else if (extractor.fileExts[0]) - entName += _SYS_STR(".*"); - else if (hecl::ProjectPath chWork = getCharacterWorking(entry)) - return chWork; - if (bridge.getPAK().m_noShare) - { - return hecl::ProjectPath(pakPath, entName).ensureAuxInfo(auxInfo); - } - else - { - hecl::ProjectPath uniquePath = entry->unique.uniquePath(pakPath); - return hecl::ProjectPath(uniquePath, entName).ensureAuxInfo(auxInfo); - } - } - - auto sharedSearch = m_sharedEntries.find(entry->id); - if (sharedSearch != m_sharedEntries.end()) - { -#if HECL_UCS2 - hecl::SystemString entBase = hecl::UTF8ToWide(getBestEntryName(*entry)); -#else - hecl::SystemString entBase = getBestEntryName(*entry); -#endif - hecl::SystemString auxInfo; - hecl::SystemString entName = entBase; - if (extractor.fileExts[0] && !extractor.fileExts[1]) - entName += extractor.fileExts[0]; - else if (extractor.fileExts[0]) - entName += _SYS_STR(".*"); - else if (hecl::ProjectPath chWork = getCharacterWorking(entry)) - return chWork; - hecl::ProjectPath sharedPath(m_sharedWorking, entName); - return sharedPath.ensureAuxInfo(auxInfo); - } - - LogDNACommon.report(logvisor::Fatal, "Unable to find entry %s", entry->id.toString().c_str()); + const ResExtractor& extractor) const { + if (!entry) return hecl::ProjectPath(); + + auto overrideSearch = m_overrideEntries.find(entry->id); + if (overrideSearch != m_overrideEntries.end()) + return overrideSearch->second; + + const PAKType* pak = m_pak.get(); + intptr_t curBridgeIdx = reinterpret_cast(m_curBridgeIdx.get()); + if (pak && pak->m_noShare) { + const EntryType* singleSearch = pak->lookupEntry(entry->id); + if (singleSearch) { + const hecl::ProjectPath& pakPath = m_bridgePaths[curBridgeIdx].first; +#if HECL_UCS2 + hecl::SystemString entName = hecl::UTF8ToWide(getBestEntryName(*entry)); +#else + hecl::SystemString entName = getBestEntryName(*entry); +#endif + hecl::SystemString auxInfo; + if (extractor.fileExts[0] && !extractor.fileExts[1]) + entName += extractor.fileExts[0]; + else if (extractor.fileExts[0]) + entName += _SYS_STR(".*"); + else if (hecl::ProjectPath chWork = getCharacterWorking(entry)) + return chWork; + return hecl::ProjectPath(pakPath, entName).ensureAuxInfo(auxInfo); + } + } + + auto uniqueSearch = m_uniqueEntries.find(entry->id); + if (uniqueSearch != m_uniqueEntries.end()) { + const BRIDGETYPE& bridge = m_bridges->at(uniqueSearch->second.first); + const hecl::ProjectPath& pakPath = m_bridgePaths[uniqueSearch->second.first].first; +#if HECL_UCS2 + hecl::SystemString entName = hecl::UTF8ToWide(getBestEntryName(*entry)); +#else + hecl::SystemString entName = getBestEntryName(*entry); +#endif + hecl::SystemString auxInfo; + if (extractor.fileExts[0] && !extractor.fileExts[1]) + entName += extractor.fileExts[0]; + else if (extractor.fileExts[0]) + entName += _SYS_STR(".*"); + else if (hecl::ProjectPath chWork = getCharacterWorking(entry)) + return chWork; + if (bridge.getPAK().m_noShare) { + return hecl::ProjectPath(pakPath, entName).ensureAuxInfo(auxInfo); + } else { + hecl::ProjectPath uniquePath = entry->unique.uniquePath(pakPath); + return hecl::ProjectPath(uniquePath, entName).ensureAuxInfo(auxInfo); + } + } + + auto sharedSearch = m_sharedEntries.find(entry->id); + if (sharedSearch != m_sharedEntries.end()) { +#if HECL_UCS2 + hecl::SystemString entBase = hecl::UTF8ToWide(getBestEntryName(*entry)); +#else + hecl::SystemString entBase = getBestEntryName(*entry); +#endif + hecl::SystemString auxInfo; + hecl::SystemString entName = entBase; + if (extractor.fileExts[0] && !extractor.fileExts[1]) + entName += extractor.fileExts[0]; + else if (extractor.fileExts[0]) + entName += _SYS_STR(".*"); + else if (hecl::ProjectPath chWork = getCharacterWorking(entry)) + return chWork; + hecl::ProjectPath sharedPath(m_sharedWorking, entName); + return sharedPath.ensureAuxInfo(auxInfo); + } + + LogDNACommon.report(logvisor::Fatal, "Unable to find entry %s", entry->id.toString().c_str()); + return hecl::ProjectPath(); } template -hecl::ProjectPath PAKRouter::getWorking(const EntryType* entry) const -{ - if (!entry) - return hecl::ProjectPath(); - return getWorking(entry, BRIDGETYPE::LookupExtractor(*m_node.get(), *m_pak.get(), *entry)); -} - -template -hecl::ProjectPath PAKRouter::getWorking(const IDType& id, bool silenceWarnings) const -{ - return getWorking(lookupEntry(id, nullptr, silenceWarnings, false)); -} - -template -hecl::ProjectPath PAKRouter::getCooked(const EntryType* entry) const -{ - if (!entry) - return hecl::ProjectPath(); - - auto overrideSearch = m_overrideEntries.find(entry->id); - if (overrideSearch != m_overrideEntries.end()) - { - return overrideSearch->second.getCookedPath( - *m_dataSpec.overrideDataSpec(overrideSearch->second, - m_dataSpec.getDataSpecEntry(), - hecl::blender::SharedBlenderToken)); - } - - const PAKType* pak = m_pak.get(); - intptr_t curBridgeIdx = reinterpret_cast(m_curBridgeIdx.get()); - if (pak && pak->m_noShare) - { - const EntryType* singleSearch = pak->lookupEntry(entry->id); - if (singleSearch) - { - const hecl::ProjectPath& pakPath = m_bridgePaths[curBridgeIdx].second; - return hecl::ProjectPath(pakPath, getBestEntryName(*entry)); - } - } - auto uniqueSearch = m_uniqueEntries.find(entry->id); - if (uniqueSearch != m_uniqueEntries.end()) - { - const BRIDGETYPE& bridge = m_bridges->at(uniqueSearch->second.first); - const hecl::ProjectPath& pakPath = m_bridgePaths[uniqueSearch->second.first].second; - if (bridge.getPAK().m_noShare) - { - return hecl::ProjectPath(pakPath, getBestEntryName(*entry)); - } - else - { - hecl::ProjectPath uniquePath = entry->unique.uniquePath(pakPath); - return hecl::ProjectPath(uniquePath, getBestEntryName(*entry)); - } - } - auto sharedSearch = m_sharedEntries.find(entry->id); - if (sharedSearch != m_sharedEntries.end()) - { - return hecl::ProjectPath(m_sharedCooked, getBestEntryName(*entry)); - } - LogDNACommon.report(logvisor::Fatal, "Unable to find entry %s", entry->id.toString().c_str()); +hecl::ProjectPath PAKRouter::getWorking(const EntryType* entry) const { + if (!entry) return hecl::ProjectPath(); + return getWorking(entry, BRIDGETYPE::LookupExtractor(*m_node.get(), *m_pak.get(), *entry)); } template -hecl::ProjectPath PAKRouter::getCooked(const IDType& id, bool silenceWarnings) const -{ - return getCooked(lookupEntry(id, nullptr, silenceWarnings, false)); +hecl::ProjectPath PAKRouter::getWorking(const IDType& id, bool silenceWarnings) const { + return getWorking(lookupEntry(id, nullptr, silenceWarnings, false)); } template -hecl::SystemString PAKRouter::getResourceRelativePath(const EntryType& a, const IDType& b) const -{ - const nod::Node* node = m_node.get(); - const PAKType* pak = m_pak.get(); - if (!pak) - LogDNACommon.report(logvisor::Fatal, - "PAKRouter::enterPAKBridge() must be called before PAKRouter::getResourceRelativePath()"); - const typename BRIDGETYPE::PAKType::Entry* be = lookupEntry(b); - if (!be) - return hecl::SystemString(); - hecl::ProjectPath aPath = getWorking(&a, BRIDGETYPE::LookupExtractor(*node, *pak, a)); - hecl::SystemString ret; - for (int i=0 ; i::getCooked(const EntryType* entry) const { + if (!entry) + return hecl::ProjectPath(); -template -std::string PAKRouter::getBestEntryName(const EntryType& entry, bool stdOverride) const -{ - std::string name; - for (const BRIDGETYPE& bridge : *m_bridges) - { - const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + auto overrideSearch = m_overrideEntries.find(entry->id); + if (overrideSearch != m_overrideEntries.end()) { + return overrideSearch->second.getCookedPath(*m_dataSpec.overrideDataSpec( + overrideSearch->second, m_dataSpec.getDataSpecEntry(), hecl::blender::SharedBlenderToken)); + } - if (stdOverride && isShared()) - { - if (entry.type == FOURCC('MLVL')) - return "!world"; - else if (entry.type == FOURCC('MREA')) - return "!area"; - else if (entry.type == FOURCC('MAPA')) - return "!map"; - else if (entry.type == FOURCC('PATH')) - return "!path"; - } - - bool named; - name = pak.bestEntryName(bridge.getNode(), entry, named); - if (named) - return name; + const PAKType* pak = m_pak.get(); + intptr_t curBridgeIdx = reinterpret_cast(m_curBridgeIdx.get()); + if (pak && pak->m_noShare) { + const EntryType* singleSearch = pak->lookupEntry(entry->id); + if (singleSearch) { + const hecl::ProjectPath& pakPath = m_bridgePaths[curBridgeIdx].second; + return hecl::ProjectPath(pakPath, getBestEntryName(*entry)); } - return name; + } + auto uniqueSearch = m_uniqueEntries.find(entry->id); + if (uniqueSearch != m_uniqueEntries.end()) { + const BRIDGETYPE& bridge = m_bridges->at(uniqueSearch->second.first); + const hecl::ProjectPath& pakPath = m_bridgePaths[uniqueSearch->second.first].second; + if (bridge.getPAK().m_noShare) { + return hecl::ProjectPath(pakPath, getBestEntryName(*entry)); + } else { + hecl::ProjectPath uniquePath = entry->unique.uniquePath(pakPath); + return hecl::ProjectPath(uniquePath, getBestEntryName(*entry)); + } + } + auto sharedSearch = m_sharedEntries.find(entry->id); + if (sharedSearch != m_sharedEntries.end()) { + return hecl::ProjectPath(m_sharedCooked, getBestEntryName(*entry)); + } + LogDNACommon.report(logvisor::Fatal, "Unable to find entry %s", entry->id.toString().c_str()); + return hecl::ProjectPath(); } template -std::string PAKRouter::getBestEntryName(const IDType& entry, bool stdOverride) const -{ - std::string name; - for (const BRIDGETYPE& bridge : *m_bridges) - { - const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); - const typename BRIDGETYPE::PAKType::Entry* e = pak.lookupEntry(entry); - if (!e) - continue; +hecl::ProjectPath PAKRouter::getCooked(const IDType& id, bool silenceWarnings) const { + return getCooked(lookupEntry(id, nullptr, silenceWarnings, false)); +} - if (stdOverride && isShared()) - { - if (e->type == FOURCC('MLVL')) - return "!world"; - else if (e->type == FOURCC('MREA')) - return "!area"; - else if (e->type == FOURCC('MAPA')) - return "!map"; - else if (e->type == FOURCC('PATH')) - return "!path"; - } +template +hecl::SystemString PAKRouter::getResourceRelativePath(const EntryType& a, const IDType& b) const { + const nod::Node* node = m_node.get(); + const PAKType* pak = m_pak.get(); + if (!pak) + LogDNACommon.report(logvisor::Fatal, + "PAKRouter::enterPAKBridge() must be called before PAKRouter::getResourceRelativePath()"); + const typename BRIDGETYPE::PAKType::Entry* be = lookupEntry(b); + if (!be) + return hecl::SystemString(); + hecl::ProjectPath aPath = getWorking(&a, BRIDGETYPE::LookupExtractor(*node, *pak, a)); + hecl::SystemString ret; + for (int i = 0; i < aPath.levelCount(); ++i) + ret += _SYS_STR("../"); + hecl::ProjectPath bPath = getWorking(be, BRIDGETYPE::LookupExtractor(*node, *pak, *be)); + ret += bPath.getRelativePath(); + return ret; +} - bool named; - name = pak.bestEntryName(bridge.getNode(), *e, named); - if (named) - return name; +template +std::string PAKRouter::getBestEntryName(const EntryType& entry, bool stdOverride) const { + std::string name; + for (const BRIDGETYPE& bridge : *m_bridges) { + const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + + if (stdOverride && isShared()) { + if (entry.type == FOURCC('MLVL')) + return "!world"; + else if (entry.type == FOURCC('MREA')) + return "!area"; + else if (entry.type == FOURCC('MAPA')) + return "!map"; + else if (entry.type == FOURCC('PATH')) + return "!path"; } - return name; + + bool named; + name = pak.bestEntryName(bridge.getNode(), entry, named); + if (named) + return name; + } + return name; +} + +template +std::string PAKRouter::getBestEntryName(const IDType& entry, bool stdOverride) const { + std::string name; + for (const BRIDGETYPE& bridge : *m_bridges) { + const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + const typename BRIDGETYPE::PAKType::Entry* e = pak.lookupEntry(entry); + if (!e) + continue; + + if (stdOverride && isShared()) { + if (e->type == FOURCC('MLVL')) + return "!world"; + else if (e->type == FOURCC('MREA')) + return "!area"; + else if (e->type == FOURCC('MAPA')) + return "!map"; + else if (e->type == FOURCC('PATH')) + return "!path"; + } + + bool named; + name = pak.bestEntryName(bridge.getNode(), *e, named); + if (named) + return name; + } + return name; } template bool PAKRouter::extractResources(const BRIDGETYPE& pakBridge, bool force, hecl::blender::Token& btok, - std::function progress) -{ - enterPAKBridge(pakBridge); - size_t count = 0; - size_t sz = m_pak->m_entries.size(); - float fsz = sz; - for (unsigned w=0 ; countm_firstEntries) - { - const auto* entryPtr = m_pak->lookupEntry(item); - ResExtractor extractor = BRIDGETYPE::LookupExtractor(*m_node.get(), *m_pak.get(), *entryPtr); - if (extractor.weight != w) - continue; + std::function progress) { + enterPAKBridge(pakBridge); + size_t count = 0; + size_t sz = m_pak->m_entries.size(); + float fsz = sz; + for (unsigned w = 0; count < sz; ++w) { + for (const auto& item : m_pak->m_firstEntries) { + const auto* entryPtr = m_pak->lookupEntry(item); + ResExtractor extractor = BRIDGETYPE::LookupExtractor(*m_node.get(), *m_pak.get(), *entryPtr); + if (extractor.weight != w) + continue; - std::string bestName = getBestEntryName(*entryPtr, false); - hecl::SystemStringConv bestNameView(bestName); - float thisFac = ++count / fsz; - progress(bestNameView.c_str(), thisFac); + std::string bestName = getBestEntryName(*entryPtr, false); + hecl::SystemStringConv bestNameView(bestName); + float thisFac = ++count / fsz; + progress(bestNameView.c_str(), thisFac); - const nod::Node* node = m_node.get(); + const nod::Node* node = m_node.get(); - hecl::ProjectPath working = getWorking(entryPtr, extractor); - working.makeDirChain(false); - hecl::ResourceLock resLk(working); - if (!resLk) - continue; + hecl::ProjectPath working = getWorking(entryPtr, extractor); + working.makeDirChain(false); + hecl::ResourceLock resLk(working); + if (!resLk) + continue; - /* Extract to unmodified directory */ - hecl::ProjectPath cooked = working.getCookedPath(m_dataSpec.getUnmodifiedSpec()); - if (force || cooked.isNone()) - { - cooked.makeDirChain(false); - PAKEntryReadStream s = entryPtr->beginReadStream(*node); - FILE* fout = hecl::Fopen(cooked.getAbsolutePath().data(), _SYS_STR("wb")); - fwrite(s.data(), 1, s.length(), fout); - fclose(fout); - } + /* Extract to unmodified directory */ + hecl::ProjectPath cooked = working.getCookedPath(m_dataSpec.getUnmodifiedSpec()); + if (force || cooked.isNone()) { + cooked.makeDirChain(false); + PAKEntryReadStream s = entryPtr->beginReadStream(*node); + FILE* fout = hecl::Fopen(cooked.getAbsolutePath().data(), _SYS_STR("wb")); + fwrite(s.data(), 1, s.length(), fout); + fclose(fout); + } - if (extractor.func_a) /* Doesn't need PAKRouter access */ - { - if (force || !extractor.IsFullyExtracted(working)) - { - PAKEntryReadStream s = entryPtr->beginReadStream(*node); - extractor.func_a(s, working); - } - } - else if (extractor.func_b) /* Needs PAKRouter access */ - { - if (force || !extractor.IsFullyExtracted(working)) - { - PAKEntryReadStream s = entryPtr->beginReadStream(*node); - extractor.func_b(m_dataSpec, s, working, *this, *entryPtr, force, btok, - [&progress, thisFac](const hecl::SystemChar* update) - { - progress(update, thisFac); - }); - } - } + if (extractor.func_a) /* Doesn't need PAKRouter access */ + { + if (force || !extractor.IsFullyExtracted(working)) { + PAKEntryReadStream s = entryPtr->beginReadStream(*node); + extractor.func_a(s, working); } + } else if (extractor.func_b) /* Needs PAKRouter access */ + { + if (force || !extractor.IsFullyExtracted(working)) { + PAKEntryReadStream s = entryPtr->beginReadStream(*node); + extractor.func_b(m_dataSpec, s, working, *this, *entryPtr, force, btok, + [&progress, thisFac](const hecl::SystemChar* update) { progress(update, thisFac); }); + } + } } + } - return true; + return true; } template const typename BRIDGETYPE::PAKType::Entry* PAKRouter::lookupEntry(const IDType& entry, const nod::Node** nodeOut, bool silenceWarnings, - bool currentPAK) const -{ - if (!entry) - return nullptr; + bool currentPAK) const { + if (!entry) + return nullptr; - if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, - "PAKRouter::build() must be called before PAKRouter::lookupEntry()"); + if (!m_bridges) + LogDNACommon.report(logvisor::Fatal, "PAKRouter::build() must be called before PAKRouter::lookupEntry()"); - const PAKType* pak = m_pak.get(); - const nod::Node* node = m_node.get(); - if (pak) - { - const EntryType* ent = pak->lookupEntry(entry); - if (ent) - { - if (nodeOut) - *nodeOut = node; - return ent; - } - } - - if (currentPAK) - { -#ifndef NDEBUG - if (!silenceWarnings) - LogDNACommon.report(logvisor::Warning, - "unable to find PAK entry %s in current PAK", entry.toString().c_str()); -#endif - return nullptr; - } - - for (const BRIDGETYPE& bridge : *m_bridges) - { - const PAKType& pak = bridge.getPAK(); - const EntryType* ent = pak.lookupEntry(entry); - if (ent) - { - if (nodeOut) - *nodeOut = &bridge.getNode(); - return ent; - } + const PAKType* pak = m_pak.get(); + const nod::Node* node = m_node.get(); + if (pak) { + const EntryType* ent = pak->lookupEntry(entry); + if (ent) { + if (nodeOut) + *nodeOut = node; + return ent; } + } + if (currentPAK) { #ifndef NDEBUG if (!silenceWarnings) - LogDNACommon.report(logvisor::Warning, - "unable to find PAK entry %s", entry.toString().c_str()); + LogDNACommon.report(logvisor::Warning, "unable to find PAK entry %s in current PAK", entry.toString().c_str()); #endif - if (nodeOut) - *nodeOut = nullptr; return nullptr; + } + + for (const BRIDGETYPE& bridge : *m_bridges) { + const PAKType& pak = bridge.getPAK(); + const EntryType* ent = pak.lookupEntry(entry); + if (ent) { + if (nodeOut) + *nodeOut = &bridge.getNode(); + return ent; + } + } + +#ifndef NDEBUG + if (!silenceWarnings) + LogDNACommon.report(logvisor::Warning, "unable to find PAK entry %s", entry.toString().c_str()); +#endif + if (nodeOut) + *nodeOut = nullptr; + return nullptr; } template const typename CharacterAssociations::IDType>::RigPair* -PAKRouter::lookupCMDLRigPair(const IDType& id) const -{ - auto search = m_charAssoc.m_cmdlRigs.find(id); - if (search == m_charAssoc.m_cmdlRigs.end()) - return nullptr; - return &search->second; +PAKRouter::lookupCMDLRigPair(const IDType& id) const { + auto search = m_charAssoc.m_cmdlRigs.find(id); + if (search == m_charAssoc.m_cmdlRigs.end()) + return nullptr; + return &search->second; } template const typename CharacterAssociations::IDType>::MultimapIteratorPair -PAKRouter::lookupCharacterAttachmentRigs(const IDType& id) const -{ - return m_charAssoc.m_characterToAttachmentRigs.equal_range(id); +PAKRouter::lookupCharacterAttachmentRigs(const IDType& id) const { + return m_charAssoc.m_characterToAttachmentRigs.equal_range(id); } template -const zeus::CMatrix4f* PAKRouter::lookupMAPATransform(const IDType& id) const -{ - auto search = m_mapaTransforms.find(id); - if (search == m_mapaTransforms.end()) - return nullptr; - return &search->second; +const zeus::CMatrix4f* PAKRouter::lookupMAPATransform(const IDType& id) const { + auto search = m_mapaTransforms.find(id); + if (search == m_mapaTransforms.end()) + return nullptr; + return &search->second; } template -hecl::ProjectPath PAKRouter::getAreaLayerWorking(const IDType& areaId, int layerIdx) const -{ - if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, - "PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"); - auto bridgePathIt = m_bridgePaths.cbegin(); - for (const BRIDGETYPE& bridge : *m_bridges) - { - for (const auto& level : bridge.m_levelDeps) - for (const auto& area : level.second.areas) - if (area.first == areaId) - { - hecl::ProjectPath levelPath(bridgePathIt->first, level.second.name); - hecl::ProjectPath areaPath(levelPath, area.second.name); - if (layerIdx < 0) - return areaPath; - return hecl::ProjectPath(areaPath, area.second.layers.at(layerIdx).name); - } - ++bridgePathIt; - } - return hecl::ProjectPath(); +hecl::ProjectPath PAKRouter::getAreaLayerWorking(const IDType& areaId, int layerIdx) const { + if (!m_bridges) + LogDNACommon.report(logvisor::Fatal, "PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"); + auto bridgePathIt = m_bridgePaths.cbegin(); + for (const BRIDGETYPE& bridge : *m_bridges) { + for (const auto& level : bridge.m_levelDeps) + for (const auto& area : level.second.areas) + if (area.first == areaId) { + hecl::ProjectPath levelPath(bridgePathIt->first, level.second.name); + hecl::ProjectPath areaPath(levelPath, area.second.name); + if (layerIdx < 0) + return areaPath; + return hecl::ProjectPath(areaPath, area.second.layers.at(layerIdx).name); + } + ++bridgePathIt; + } + return hecl::ProjectPath(); } template -hecl::ProjectPath PAKRouter::getAreaLayerWorking(const IDType& areaId, int layerIdx, bool& activeOut) const -{ - activeOut = false; - if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, - "PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"); - auto bridgePathIt = m_bridgePaths.cbegin(); - for (const BRIDGETYPE& bridge : *m_bridges) - { - for (const auto& level : bridge.m_levelDeps) - for (const auto& area : level.second.areas) - if (area.first == areaId) - { - hecl::ProjectPath levelPath(bridgePathIt->first, level.second.name); - hecl::ProjectPath areaPath(levelPath, area.second.name); - if (layerIdx < 0) - return areaPath; - const typename Level::Area::Layer& layer = area.second.layers.at(layerIdx); - activeOut = layer.active; - return hecl::ProjectPath(areaPath, layer.name); - } - ++bridgePathIt; - } - return hecl::ProjectPath(); -} - - -template -hecl::ProjectPath PAKRouter::getAreaLayerCooked(const IDType& areaId, int layerIdx) const -{ - if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, - "PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"); - auto bridgePathIt = m_bridgePaths.cbegin(); - for (const BRIDGETYPE& bridge : *m_bridges) - { - for (const auto& level : bridge.m_levelDeps) - for (const auto& area : level.second.areas) - if (area.first == areaId) - { - hecl::ProjectPath levelPath(bridgePathIt->second, level.second.name); - hecl::ProjectPath areaPath(levelPath, area.second.name); - if (layerIdx < 0) - return areaPath; - return hecl::ProjectPath(areaPath, area.second.layers.at(layerIdx).name); - } - ++bridgePathIt; - } - return hecl::ProjectPath(); +hecl::ProjectPath PAKRouter::getAreaLayerWorking(const IDType& areaId, int layerIdx, + bool& activeOut) const { + activeOut = false; + if (!m_bridges) + LogDNACommon.report(logvisor::Fatal, "PAKRouter::build() must be called before PAKRouter::getAreaLayerWorking()"); + auto bridgePathIt = m_bridgePaths.cbegin(); + for (const BRIDGETYPE& bridge : *m_bridges) { + for (const auto& level : bridge.m_levelDeps) + for (const auto& area : level.second.areas) + if (area.first == areaId) { + hecl::ProjectPath levelPath(bridgePathIt->first, level.second.name); + hecl::ProjectPath areaPath(levelPath, area.second.name); + if (layerIdx < 0) + return areaPath; + const typename Level::Area::Layer& layer = area.second.layers.at(layerIdx); + activeOut = layer.active; + return hecl::ProjectPath(areaPath, layer.name); + } + ++bridgePathIt; + } + return hecl::ProjectPath(); } template -hecl::ProjectPath PAKRouter::getAreaLayerCooked(const IDType& areaId, int layerIdx, bool& activeOut) const -{ - activeOut = false; - if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, - "PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"); - auto bridgePathIt = m_bridgePaths.cbegin(); - for (const BRIDGETYPE& bridge : *m_bridges) - { - for (const auto& level : bridge.m_levelDeps) - for (const auto& area : level.second.areas) - if (area.first == areaId) - { - hecl::ProjectPath levelPath(bridgePathIt->second, level.second.name); - hecl::ProjectPath areaPath(levelPath, area.second.name); - if (layerIdx < 0) - return areaPath; - const typename Level::Area::Layer& layer = area.second.layers.at(layerIdx); - activeOut = layer.active; - return hecl::ProjectPath(areaPath, layer.name); - } - ++bridgePathIt; - } - return hecl::ProjectPath(); +hecl::ProjectPath PAKRouter::getAreaLayerCooked(const IDType& areaId, int layerIdx) const { + if (!m_bridges) + LogDNACommon.report(logvisor::Fatal, "PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"); + auto bridgePathIt = m_bridgePaths.cbegin(); + for (const BRIDGETYPE& bridge : *m_bridges) { + for (const auto& level : bridge.m_levelDeps) + for (const auto& area : level.second.areas) + if (area.first == areaId) { + hecl::ProjectPath levelPath(bridgePathIt->second, level.second.name); + hecl::ProjectPath areaPath(levelPath, area.second.name); + if (layerIdx < 0) + return areaPath; + return hecl::ProjectPath(areaPath, area.second.layers.at(layerIdx).name); + } + ++bridgePathIt; + } + return hecl::ProjectPath(); } template -void PAKRouter::enumerateResources(const std::function& func) -{ - if (!m_bridges) - LogDNACommon.report(logvisor::Fatal, - "PAKRouter::build() must be called before PAKRouter::enumerateResources()"); - for (const auto& entryPair : m_uniqueEntries) - if (!func(entryPair.second.second)) - return; - for (const auto& entryPair : m_sharedEntries) - if (!func(entryPair.second.second)) - return; +hecl::ProjectPath PAKRouter::getAreaLayerCooked(const IDType& areaId, int layerIdx, bool& activeOut) const { + activeOut = false; + if (!m_bridges) + LogDNACommon.report(logvisor::Fatal, "PAKRouter::build() must be called before PAKRouter::getAreaLayerCooked()"); + auto bridgePathIt = m_bridgePaths.cbegin(); + for (const BRIDGETYPE& bridge : *m_bridges) { + for (const auto& level : bridge.m_levelDeps) + for (const auto& area : level.second.areas) + if (area.first == areaId) { + hecl::ProjectPath levelPath(bridgePathIt->second, level.second.name); + hecl::ProjectPath areaPath(levelPath, area.second.name); + if (layerIdx < 0) + return areaPath; + const typename Level::Area::Layer& layer = area.second.layers.at(layerIdx); + activeOut = layer.active; + return hecl::ProjectPath(areaPath, layer.name); + } + ++bridgePathIt; + } + return hecl::ProjectPath(); } template -bool PAKRouter::mreaHasDupeResources(const IDType& id) const -{ - const PAKType* pak = m_pak.get(); - if (!pak) - LogDNACommon.report(logvisor::Fatal, - "PAKRouter::enterPAKBridge() must be called before PAKRouter::mreaHasDupeResources()"); - return pak->mreaHasDupeResources(id); +void PAKRouter::enumerateResources(const std::function& func) { + if (!m_bridges) + LogDNACommon.report(logvisor::Fatal, "PAKRouter::build() must be called before PAKRouter::enumerateResources()"); + for (const auto& entryPair : m_uniqueEntries) + if (!func(entryPair.second.second)) + return; + for (const auto& entryPair : m_sharedEntries) + if (!func(entryPair.second.second)) + return; +} + +template +bool PAKRouter::mreaHasDupeResources(const IDType& id) const { + const PAKType* pak = m_pak.get(); + if (!pak) + LogDNACommon.report(logvisor::Fatal, + "PAKRouter::enterPAKBridge() must be called before PAKRouter::mreaHasDupeResources()"); + return pak->mreaHasDupeResources(id); } template class PAKRouter; template class PAKRouter; template class PAKRouter; -} +} // namespace DataSpec diff --git a/DataSpec/DNACommon/PAK.hpp b/DataSpec/DNACommon/PAK.hpp index 191674f1e..bd365e06d 100644 --- a/DataSpec/DNACommon/PAK.hpp +++ b/DataSpec/DNACommon/PAK.hpp @@ -5,73 +5,61 @@ #include #include "zeus/CMatrix4f.hpp" -namespace DataSpec -{ +namespace DataSpec { /** PAK entry stream reader */ -class PAKEntryReadStream : public athena::io::IStreamReader -{ - std::unique_ptr m_buf; - atUint64 m_sz; - atUint64 m_pos; +class PAKEntryReadStream : public athena::io::IStreamReader { + std::unique_ptr m_buf; + atUint64 m_sz; + atUint64 m_pos; + public: - PAKEntryReadStream() {} - operator bool() const {return m_buf.operator bool();} - PAKEntryReadStream(const PAKEntryReadStream& other) = delete; - PAKEntryReadStream(PAKEntryReadStream&& other) = default; - PAKEntryReadStream& operator=(const PAKEntryReadStream& other) = delete; - PAKEntryReadStream& operator=(PAKEntryReadStream&& other) = default; - PAKEntryReadStream(std::unique_ptr&& buf, atUint64 sz, atUint64 pos) - : m_buf(std::move(buf)), m_sz(sz), m_pos(pos) - { - if (m_pos >= m_sz) - LogDNACommon.report(logvisor::Fatal, "PAK stream cursor overrun"); - } - void seek(atInt64 pos, athena::SeekOrigin origin) - { - if (origin == athena::Begin) - m_pos = pos; - else if (origin == athena::Current) - m_pos += pos; - else if (origin == athena::End) - m_pos = m_sz + pos; - if (m_pos > m_sz) - LogDNACommon.report(logvisor::Fatal, "PAK stream cursor overrun"); - } - atUint64 position() const {return m_pos;} - atUint64 length() const {return m_sz;} - const atUint8* data() const {return m_buf.get();} - atUint64 readUBytesToBuf(void* buf, atUint64 len) - { - atUint64 bufEnd = m_pos + len; - if (bufEnd > m_sz) - len -= bufEnd - m_sz; - memmove(buf, m_buf.get() + m_pos, len); - m_pos += len; - return len; - } + PAKEntryReadStream() {} + operator bool() const { return m_buf.operator bool(); } + PAKEntryReadStream(const PAKEntryReadStream& other) = delete; + PAKEntryReadStream(PAKEntryReadStream&& other) = default; + PAKEntryReadStream& operator=(const PAKEntryReadStream& other) = delete; + PAKEntryReadStream& operator=(PAKEntryReadStream&& other) = default; + PAKEntryReadStream(std::unique_ptr&& buf, atUint64 sz, atUint64 pos) + : m_buf(std::move(buf)), m_sz(sz), m_pos(pos) { + if (m_pos >= m_sz) + LogDNACommon.report(logvisor::Fatal, "PAK stream cursor overrun"); + } + void seek(atInt64 pos, athena::SeekOrigin origin) { + if (origin == athena::Begin) + m_pos = pos; + else if (origin == athena::Current) + m_pos += pos; + else if (origin == athena::End) + m_pos = m_sz + pos; + if (m_pos > m_sz) + LogDNACommon.report(logvisor::Fatal, "PAK stream cursor overrun"); + } + atUint64 position() const { return m_pos; } + atUint64 length() const { return m_sz; } + const atUint8* data() const { return m_buf.get(); } + atUint64 readUBytesToBuf(void* buf, atUint64 len) { + atUint64 bufEnd = m_pos + len; + if (bufEnd > m_sz) + len -= bufEnd - m_sz; + memmove(buf, m_buf.get() + m_pos, len); + m_pos += len; + return len; + } }; -struct UniqueResult -{ - enum class Type - { - NotFound, - Pak, - Level, - Area, - Layer - } m_type = Type::NotFound; - const hecl::SystemString* m_levelName = nullptr; - const hecl::SystemString* m_areaName = nullptr; - const hecl::SystemString* m_layerName = nullptr; - UniqueResult() = default; - UniqueResult(Type tp) : m_type(tp) {} +struct UniqueResult { + enum class Type { NotFound, Pak, Level, Area, Layer } m_type = Type::NotFound; + const hecl::SystemString* m_levelName = nullptr; + const hecl::SystemString* m_areaName = nullptr; + const hecl::SystemString* m_layerName = nullptr; + UniqueResult() = default; + UniqueResult(Type tp) : m_type(tp) {} - template - void checkEntry(const PAKBRIDGE& pakBridge, const typename PAKBRIDGE::PAKType::Entry& entry); + template + void checkEntry(const PAKBRIDGE& pakBridge, const typename PAKBRIDGE::PAKType::Entry& entry); - hecl::ProjectPath uniquePath(const hecl::ProjectPath& pakPath) const; + hecl::ProjectPath uniquePath(const hecl::ProjectPath& pakPath) const; }; template @@ -79,161 +67,154 @@ class PAKRouter; /** Resource extractor type */ template -struct ResExtractor -{ - std::function func_a; - std::function&, - const typename PAKBRIDGE::PAKType::Entry&, bool, hecl::blender::Token&, - std::function)> func_b; - std::array fileExts = {}; - unsigned weight = 0; - std::function&, - typename PAKBRIDGE::PAKType::Entry&)> func_name; +struct ResExtractor { + std::function func_a; + std::function&, + const typename PAKBRIDGE::PAKType::Entry&, bool, hecl::blender::Token&, + std::function)> + func_b; + std::array fileExts = {}; + unsigned weight = 0; + std::function&, typename PAKBRIDGE::PAKType::Entry&)> + func_name; - ResExtractor() = default; + ResExtractor() = default; - ResExtractor(std::function func, - std::array&& fileExtsIn, unsigned weightin=0, - std::function&, - typename PAKBRIDGE::PAKType::Entry&)> nfunc={}) - : func_a(std::move(func)), fileExts(std::move(fileExtsIn)), weight(weightin), func_name(std::move(nfunc)) {} + ResExtractor(std::function func, + std::array&& fileExtsIn, unsigned weightin = 0, + std::function&, + typename PAKBRIDGE::PAKType::Entry&)> + nfunc = {}) + : func_a(std::move(func)), fileExts(std::move(fileExtsIn)), weight(weightin), func_name(std::move(nfunc)) {} - ResExtractor(std::function&, - const typename PAKBRIDGE::PAKType::Entry&, bool, hecl::blender::Token&, - std::function)> func, - std::array&& fileExtsIn, unsigned weightin=0, - std::function&, - typename PAKBRIDGE::PAKType::Entry&)> nfunc={}) - : func_b(std::move(func)), fileExts(std::move(fileExtsIn)), weight(weightin), func_name(std::move(nfunc)) {} + ResExtractor(std::function&, + const typename PAKBRIDGE::PAKType::Entry&, bool, hecl::blender::Token&, + std::function)> + func, + std::array&& fileExtsIn, unsigned weightin = 0, + std::function&, + typename PAKBRIDGE::PAKType::Entry&)> + nfunc = {}) + : func_b(std::move(func)), fileExts(std::move(fileExtsIn)), weight(weightin), func_name(std::move(nfunc)) {} - bool IsFullyExtracted(const hecl::ProjectPath& path) const - { - hecl::ProjectPath::Type tp = path.getPathType(); - if (tp == hecl::ProjectPath::Type::None) - return false; - else if (tp == hecl::ProjectPath::Type::Glob) - { - for (int i=0 ; i<6 ; ++i) - { - if (!fileExts[i]) - break; - hecl::ProjectPath withExt = path.getWithExtension(fileExts[i], true); - if (withExt.isNone()) - return false; - } - } - return true; + bool IsFullyExtracted(const hecl::ProjectPath& path) const { + hecl::ProjectPath::Type tp = path.getPathType(); + if (tp == hecl::ProjectPath::Type::None) + return false; + else if (tp == hecl::ProjectPath::Type::Glob) { + for (int i = 0; i < 6; ++i) { + if (!fileExts[i]) + break; + hecl::ProjectPath withExt = path.getWithExtension(fileExts[i], true); + if (withExt.isNone()) + return false; + } } + return true; + } }; /** Level hierarchy representation */ template -struct Level -{ +struct Level { + hecl::SystemString name; + struct Area { hecl::SystemString name; - struct Area - { - hecl::SystemString name; - struct Layer - { - hecl::SystemString name; - bool active; - std::unordered_set resources; - }; - std::vector layers; - std::unordered_set resources; + struct Layer { + hecl::SystemString name; + bool active; + std::unordered_set resources; }; - std::unordered_map areas; + std::vector layers; + std::unordered_set resources; + }; + std::unordered_map areas; }; /** PAKRouter (for detecting shared entry locations) */ template -class PAKRouter : public PAKRouterBase -{ +class PAKRouter : public PAKRouterBase { public: - using PAKType = typename BRIDGETYPE::PAKType; - using IDType = typename PAKType::IDType; - using EntryType = typename PAKType::Entry; + using PAKType = typename BRIDGETYPE::PAKType; + using IDType = typename PAKType::IDType; + using EntryType = typename PAKType::Entry; private: - const std::vector* m_bridges = nullptr; - std::vector> m_bridgePaths; - ThreadLocalPtr m_curBridgeIdx; - const hecl::ProjectPath& m_gameWorking; - const hecl::ProjectPath& m_gameCooked; - hecl::ProjectPath m_sharedWorking; - hecl::ProjectPath m_sharedCooked; - ThreadLocalPtr m_pak; - ThreadLocalPtr m_node; - std::unordered_map> m_uniqueEntries; - std::unordered_map> m_sharedEntries; - std::unordered_map m_overrideEntries; - CharacterAssociations m_charAssoc; - std::unordered_map m_mapaTransforms; + const std::vector* m_bridges = nullptr; + std::vector> m_bridgePaths; + ThreadLocalPtr m_curBridgeIdx; + const hecl::ProjectPath& m_gameWorking; + const hecl::ProjectPath& m_gameCooked; + hecl::ProjectPath m_sharedWorking; + hecl::ProjectPath m_sharedCooked; + ThreadLocalPtr m_pak; + ThreadLocalPtr m_node; + std::unordered_map> m_uniqueEntries; + std::unordered_map> m_sharedEntries; + std::unordered_map m_overrideEntries; + CharacterAssociations m_charAssoc; + std::unordered_map m_mapaTransforms; - hecl::ProjectPath getCharacterWorking(const EntryType* entry) const; + hecl::ProjectPath getCharacterWorking(const EntryType* entry) const; public: - PAKRouter(const SpecBase& dataSpec, const hecl::ProjectPath& working, const hecl::ProjectPath& cooked) - : PAKRouterBase(dataSpec), - m_gameWorking(working), m_gameCooked(cooked), - m_sharedWorking(working, "Shared"), m_sharedCooked(cooked, "Shared") {} + PAKRouter(const SpecBase& dataSpec, const hecl::ProjectPath& working, const hecl::ProjectPath& cooked) + : PAKRouterBase(dataSpec) + , m_gameWorking(working) + , m_gameCooked(cooked) + , m_sharedWorking(working, "Shared") + , m_sharedCooked(cooked, "Shared") {} - void build(std::vector& bridges, std::function progress); + void build(std::vector& bridges, std::function progress); - void enterPAKBridge(const BRIDGETYPE& pakBridge); + void enterPAKBridge(const BRIDGETYPE& pakBridge); - using PAKRouterBase::getWorking; - hecl::ProjectPath getWorking(const EntryType* entry, - const ResExtractor& extractor) const; - hecl::ProjectPath getWorking(const EntryType* entry) const; - hecl::ProjectPath getWorking(const IDType& id, bool silenceWarnings=false) const; - hecl::ProjectPath getCooked(const EntryType* entry) const; - hecl::ProjectPath getCooked(const IDType& id, bool silenceWarnings=false) const; - bool isShared() const - { - const PAKType* pak = m_pak.get(); - return pak ? !pak->m_noShare : false; - } + using PAKRouterBase::getWorking; + hecl::ProjectPath getWorking(const EntryType* entry, const ResExtractor& extractor) const; + hecl::ProjectPath getWorking(const EntryType* entry) const; + hecl::ProjectPath getWorking(const IDType& id, bool silenceWarnings = false) const; + hecl::ProjectPath getCooked(const EntryType* entry) const; + hecl::ProjectPath getCooked(const IDType& id, bool silenceWarnings = false) const; + bool isShared() const { + const PAKType* pak = m_pak.get(); + return pak ? !pak->m_noShare : false; + } - hecl::SystemString getResourceRelativePath(const EntryType& a, const IDType& b) const; + hecl::SystemString getResourceRelativePath(const EntryType& a, const IDType& b) const; - std::string getBestEntryName(const EntryType& entry, bool stdOverride=true) const; - std::string getBestEntryName(const IDType& entry, bool stdOverride=true) const; + std::string getBestEntryName(const EntryType& entry, bool stdOverride = true) const; + std::string getBestEntryName(const IDType& entry, bool stdOverride = true) const; - bool extractResources(const BRIDGETYPE& pakBridge, bool force, hecl::blender::Token& btok, - std::function progress); + bool extractResources(const BRIDGETYPE& pakBridge, bool force, hecl::blender::Token& btok, + std::function progress); - const typename BRIDGETYPE::PAKType::Entry* lookupEntry(const IDType& entry, - const nod::Node** nodeOut=nullptr, - bool silenceWarnings=false, - bool currentPAK=false) const; + const typename BRIDGETYPE::PAKType::Entry* lookupEntry(const IDType& entry, const nod::Node** nodeOut = nullptr, + bool silenceWarnings = false, bool currentPAK = false) const; - template - bool lookupAndReadDNA(const IDType& id, DNA& out, bool silenceWarnings=false) - { - const nod::Node* node; - const EntryType* entry = lookupEntry(id, &node, silenceWarnings); - if (!entry) - return false; - PAKEntryReadStream rs = entry->beginReadStream(*node); - out.read(rs); - return true; - } + template + bool lookupAndReadDNA(const IDType& id, DNA& out, bool silenceWarnings = false) { + const nod::Node* node; + const EntryType* entry = lookupEntry(id, &node, silenceWarnings); + if (!entry) + return false; + PAKEntryReadStream rs = entry->beginReadStream(*node); + out.read(rs); + return true; + } - const typename CharacterAssociations::RigPair* lookupCMDLRigPair(const IDType& id) const; - const typename CharacterAssociations::MultimapIteratorPair lookupCharacterAttachmentRigs(const IDType& id) const; - const zeus::CMatrix4f* lookupMAPATransform(const IDType& mapaId) const; + const typename CharacterAssociations::RigPair* lookupCMDLRigPair(const IDType& id) const; + const typename CharacterAssociations::MultimapIteratorPair + lookupCharacterAttachmentRigs(const IDType& id) const; + const zeus::CMatrix4f* lookupMAPATransform(const IDType& mapaId) const; - hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx) const; - hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx, bool& activeOut) const; - hecl::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx) const; - hecl::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx, bool& activeOut) const; + hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx) const; + hecl::ProjectPath getAreaLayerWorking(const IDType& areaId, int layerIdx, bool& activeOut) const; + hecl::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx) const; + hecl::ProjectPath getAreaLayerCooked(const IDType& areaId, int layerIdx, bool& activeOut) const; - void enumerateResources(const std::function& func); + void enumerateResources(const std::function& func); - bool mreaHasDupeResources(const IDType& id) const; + bool mreaHasDupeResources(const IDType& id) const; }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/PART.cpp b/DataSpec/DNACommon/PART.cpp index 2e511d1e3..23b982064 100644 --- a/DataSpec/DNACommon/PART.cpp +++ b/DataSpec/DNACommon/PART.cpp @@ -1,1594 +1,1437 @@ #include "PART.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template <> -const char* GPSM::DNAType() {return "GPSM";} +const char* GPSM::DNAType() { + return "GPSM"; +} template <> -const char* GPSM::DNAType() {return "GPSM";} +const char* GPSM::DNAType() { + return "GPSM"; +} template -void GPSM::_read(typename ReadYaml::StreamT& r) -{ - for (const auto& elem : r.getCurNode()->m_mapChildren) - { - if (elem.first.size() < 4) - { - LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); - continue; - } - - if (auto rec = r.enterSubRecord(elem.first.c_str())) - { - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('PMCL'): - x78_PMCL.read(r); - break; - case SBIG('LFOR'): - x118_LFOR.read(r); - break; - case SBIG('IDTS'): - xa4_IDTS.read(r); - break; - case SBIG('EMTR'): - x40_EMTR.read(r); - break; - case SBIG('COLR'): - x30_COLR.read(r); - break; - case SBIG('CIND'): - x45_30_CIND = r.readBool(nullptr); - break; - case SBIG('AAPH'): - x44_26_AAPH = r.readBool(nullptr); - break; - case SBIG('CSSD'): - xa0_CSSD.read(r); - break; - case SBIG('GRTE'): - x2c_GRTE.read(r); - break; - case SBIG('FXLL'): - x44_25_FXLL = r.readBool(nullptr); - break; - case SBIG('ICTS'): - x8c_ICTS.read(r); - break; - case SBIG('KSSM'): - xd0_KSSM.read(r); - break; - case SBIG('ILOC'): - x38_ILOC.read(r); - break; - case SBIG('IITS'): - xb8_IITS.read(r); - break; - case SBIG('IVEC'): - x3c_IVEC.read(r); - break; - case SBIG('LDIR'): - x110_LDIR.read(r); - break; - case SBIG('LCLR'): - x104_LCLR.read(r); - break; - case SBIG('LENG'): - x20_LENG.read(r); - break; - case SBIG('MAXP'): - x28_MAXP.read(r); - break; - case SBIG('LOFF'): - x10c_LOFF.read(r); - break; - case SBIG('LINT'): - x108_LINT.read(r); - break; - case SBIG('LINE'): - x44_24_LINE = r.readBool(nullptr); - break; - case SBIG('LFOT'): - x114_LFOT.read(r); - break; - case SBIG('LIT_'): - x44_29_LIT_ = r.readBool(nullptr); - break; - case SBIG('LTME'): - x34_LTME.read(r); - break; - case SBIG('LSLA'): - x11c_LSLA.read(r); - break; - case SBIG('LTYP'): - x100_LTYP.read(r); - break; - case SBIG('NDSY'): - xb4_NDSY.read(r); - break; - case SBIG('MBSP'): - x48_MBSP.read(r); - break; - case SBIG('MBLR'): - x44_30_MBLR = r.readBool(nullptr); - break; - case SBIG('NCSY'): - x9c_NCSY.read(r); - break; - case SBIG('PISY'): - xc8_PISY.read(r); - break; - case SBIG('OPTS'): - x45_31_OPTS = r.readBool(nullptr); - break; - case SBIG('PMAB'): - x44_31_PMAB = r.readBool(nullptr); - break; - case SBIG('SESD'): - xf8_SESD.read(r); - break; - case SBIG('SEPO'): - xfc_SEPO.read(r); - break; - case SBIG('PSLT'): - xc_PSLT.read(r); - break; - case SBIG('PMSC'): - x74_PMSC.read(r); - break; - case SBIG('PMOP'): - x6c_PMOP.read(r); - break; - case SBIG('PMDL'): - x5c_PMDL.read(r); - break; - case SBIG('PMRT'): - x70_PMRT.read(r); - break; - case SBIG('POFS'): - x18_POFS.read(r); - break; - case SBIG('PMUS'): - x45_24_PMUS = r.readBool(nullptr); - break; - case SBIG('PSIV'): - x0_PSIV.read(r); - break; - case SBIG('ROTA'): - x50_ROTA.read(r); - break; - case SBIG('PSVM'): - x4_PSVM.read(r); - break; - case SBIG('PSTS'): - x14_PSTS.read(r); - break; - case SBIG('PSOV'): - x8_PSOV.read(r); - break; - case SBIG('PSWT'): - x10_PSWT.read(r); - break; - case SBIG('PMLC'): - xec_PMLC.read(r); - break; - case SBIG('SEED'): - x1c_SEED.read(r); - break; - case SBIG('PMOO'): - x45_25_PMOO = r.readBool(nullptr); - break; - case SBIG('SSSD'): - xe4_SSSD.read(r); - break; - case SBIG('SORT'): - x44_28_SORT = r.readBool(nullptr); - break; - case SBIG('SIZE'): - x4c_SIZE.read(r); - break; - case SBIG('SISY'): - xcc_SISY.read(r); - break; - case SBIG('SSPO'): - xe8_SSPO.read(r); - break; - case SBIG('TEXR'): - x54_TEXR.read(r); - break; - case SBIG('SSWH'): - xd4_SSWH.read(r); - break; - case SBIG('TIND'): - x58_TIND.read(r); - break; - case SBIG('VMD4'): - x45_29_VMD4 = r.readBool(nullptr); - break; - case SBIG('VMD3'): - x45_28_VMD3 = r.readBool(nullptr); - break; - case SBIG('VMD2'): - x45_27_VMD2 = r.readBool(nullptr); - break; - case SBIG('VMD1'): - x45_26_VMD1 = r.readBool(nullptr); - break; - case SBIG('VEL4'): - x88_VEL4.read(r); - break; - case SBIG('VEL3'): - x84_VEL3.read(r); - break; - case SBIG('VEL2'): - x80_VEL2.read(r); - break; - case SBIG('VEL1'): - x7c_VEL1.read(r); - break; - case SBIG('ZBUF'): - x44_27_ZBUF = r.readBool(nullptr); - break; - case SBIG('WIDT'): - x24_WIDT.read(r); - break; - case SBIG('ORNT'): - x30_30_ORNT = r.readBool(nullptr); - break; - case SBIG('RSOP'): - x30_31_RSOP = r.readBool(nullptr); - break; - case SBIG('ADV1'): - x10c_ADV1.read(r); - break; - case SBIG('ADV2'): - x110_ADV2.read(r); - break; - case SBIG('ADV3'): - x114_ADV3.read(r); - break; - case SBIG('ADV4'): - x118_ADV4.read(r); - break; - case SBIG('ADV5'): - x11c_ADV5.read(r); - break; - case SBIG('ADV6'): - x120_ADV6.read(r); - break; - case SBIG('ADV7'): - x124_ADV7.read(r); - break; - case SBIG('SELC'): - xd8_SELC.read(r); - break; - default: - break; - } - } +void GPSM::_read(typename ReadYaml::StreamT& r) { + for (const auto& elem : r.getCurNode()->m_mapChildren) { + if (elem.first.size() < 4) { + LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); + continue; } + + if (auto rec = r.enterSubRecord(elem.first.c_str())) { + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('PMCL'): + x78_PMCL.read(r); + break; + case SBIG('LFOR'): + x118_LFOR.read(r); + break; + case SBIG('IDTS'): + xa4_IDTS.read(r); + break; + case SBIG('EMTR'): + x40_EMTR.read(r); + break; + case SBIG('COLR'): + x30_COLR.read(r); + break; + case SBIG('CIND'): + x45_30_CIND = r.readBool(nullptr); + break; + case SBIG('AAPH'): + x44_26_AAPH = r.readBool(nullptr); + break; + case SBIG('CSSD'): + xa0_CSSD.read(r); + break; + case SBIG('GRTE'): + x2c_GRTE.read(r); + break; + case SBIG('FXLL'): + x44_25_FXLL = r.readBool(nullptr); + break; + case SBIG('ICTS'): + x8c_ICTS.read(r); + break; + case SBIG('KSSM'): + xd0_KSSM.read(r); + break; + case SBIG('ILOC'): + x38_ILOC.read(r); + break; + case SBIG('IITS'): + xb8_IITS.read(r); + break; + case SBIG('IVEC'): + x3c_IVEC.read(r); + break; + case SBIG('LDIR'): + x110_LDIR.read(r); + break; + case SBIG('LCLR'): + x104_LCLR.read(r); + break; + case SBIG('LENG'): + x20_LENG.read(r); + break; + case SBIG('MAXP'): + x28_MAXP.read(r); + break; + case SBIG('LOFF'): + x10c_LOFF.read(r); + break; + case SBIG('LINT'): + x108_LINT.read(r); + break; + case SBIG('LINE'): + x44_24_LINE = r.readBool(nullptr); + break; + case SBIG('LFOT'): + x114_LFOT.read(r); + break; + case SBIG('LIT_'): + x44_29_LIT_ = r.readBool(nullptr); + break; + case SBIG('LTME'): + x34_LTME.read(r); + break; + case SBIG('LSLA'): + x11c_LSLA.read(r); + break; + case SBIG('LTYP'): + x100_LTYP.read(r); + break; + case SBIG('NDSY'): + xb4_NDSY.read(r); + break; + case SBIG('MBSP'): + x48_MBSP.read(r); + break; + case SBIG('MBLR'): + x44_30_MBLR = r.readBool(nullptr); + break; + case SBIG('NCSY'): + x9c_NCSY.read(r); + break; + case SBIG('PISY'): + xc8_PISY.read(r); + break; + case SBIG('OPTS'): + x45_31_OPTS = r.readBool(nullptr); + break; + case SBIG('PMAB'): + x44_31_PMAB = r.readBool(nullptr); + break; + case SBIG('SESD'): + xf8_SESD.read(r); + break; + case SBIG('SEPO'): + xfc_SEPO.read(r); + break; + case SBIG('PSLT'): + xc_PSLT.read(r); + break; + case SBIG('PMSC'): + x74_PMSC.read(r); + break; + case SBIG('PMOP'): + x6c_PMOP.read(r); + break; + case SBIG('PMDL'): + x5c_PMDL.read(r); + break; + case SBIG('PMRT'): + x70_PMRT.read(r); + break; + case SBIG('POFS'): + x18_POFS.read(r); + break; + case SBIG('PMUS'): + x45_24_PMUS = r.readBool(nullptr); + break; + case SBIG('PSIV'): + x0_PSIV.read(r); + break; + case SBIG('ROTA'): + x50_ROTA.read(r); + break; + case SBIG('PSVM'): + x4_PSVM.read(r); + break; + case SBIG('PSTS'): + x14_PSTS.read(r); + break; + case SBIG('PSOV'): + x8_PSOV.read(r); + break; + case SBIG('PSWT'): + x10_PSWT.read(r); + break; + case SBIG('PMLC'): + xec_PMLC.read(r); + break; + case SBIG('SEED'): + x1c_SEED.read(r); + break; + case SBIG('PMOO'): + x45_25_PMOO = r.readBool(nullptr); + break; + case SBIG('SSSD'): + xe4_SSSD.read(r); + break; + case SBIG('SORT'): + x44_28_SORT = r.readBool(nullptr); + break; + case SBIG('SIZE'): + x4c_SIZE.read(r); + break; + case SBIG('SISY'): + xcc_SISY.read(r); + break; + case SBIG('SSPO'): + xe8_SSPO.read(r); + break; + case SBIG('TEXR'): + x54_TEXR.read(r); + break; + case SBIG('SSWH'): + xd4_SSWH.read(r); + break; + case SBIG('TIND'): + x58_TIND.read(r); + break; + case SBIG('VMD4'): + x45_29_VMD4 = r.readBool(nullptr); + break; + case SBIG('VMD3'): + x45_28_VMD3 = r.readBool(nullptr); + break; + case SBIG('VMD2'): + x45_27_VMD2 = r.readBool(nullptr); + break; + case SBIG('VMD1'): + x45_26_VMD1 = r.readBool(nullptr); + break; + case SBIG('VEL4'): + x88_VEL4.read(r); + break; + case SBIG('VEL3'): + x84_VEL3.read(r); + break; + case SBIG('VEL2'): + x80_VEL2.read(r); + break; + case SBIG('VEL1'): + x7c_VEL1.read(r); + break; + case SBIG('ZBUF'): + x44_27_ZBUF = r.readBool(nullptr); + break; + case SBIG('WIDT'): + x24_WIDT.read(r); + break; + case SBIG('ORNT'): + x30_30_ORNT = r.readBool(nullptr); + break; + case SBIG('RSOP'): + x30_31_RSOP = r.readBool(nullptr); + break; + case SBIG('ADV1'): + x10c_ADV1.read(r); + break; + case SBIG('ADV2'): + x110_ADV2.read(r); + break; + case SBIG('ADV3'): + x114_ADV3.read(r); + break; + case SBIG('ADV4'): + x118_ADV4.read(r); + break; + case SBIG('ADV5'): + x11c_ADV5.read(r); + break; + case SBIG('ADV6'): + x120_ADV6.read(r); + break; + case SBIG('ADV7'): + x124_ADV7.read(r); + break; + case SBIG('SELC'): + xd8_SELC.read(r); + break; + default: + break; + } + } + } } template -void GPSM::_write(typename WriteYaml::StreamT& w) const -{ - if (x0_PSIV) - if (auto rec = w.enterSubRecord("PSIV")) - x0_PSIV.write(w); - if (x4_PSVM) - if (auto rec = w.enterSubRecord("PSVM")) - x4_PSVM.write(w); - if (x8_PSOV) - if (auto rec = w.enterSubRecord("PSOV")) - x8_PSOV.write(w); - if (xc_PSLT) - if (auto rec = w.enterSubRecord("PSLT")) - xc_PSLT.write(w); - if (x10_PSWT) - if (auto rec = w.enterSubRecord("PSWT")) - x10_PSWT.write(w); - if (x14_PSTS) - if (auto rec = w.enterSubRecord("PSTS")) - x14_PSTS.write(w); - if (x18_POFS) - if (auto rec = w.enterSubRecord("POFS")) - x18_POFS.write(w); - if (x1c_SEED) - if (auto rec = w.enterSubRecord("SEED")) - x1c_SEED.write(w); - if (x20_LENG) - if (auto rec = w.enterSubRecord("LENG")) - x20_LENG.write(w); - if (x24_WIDT) - if (auto rec = w.enterSubRecord("WIDT")) - x24_WIDT.write(w); - if (x28_MAXP) - if (auto rec = w.enterSubRecord("MAXP")) - x28_MAXP.write(w); - if (x2c_GRTE) - if (auto rec = w.enterSubRecord("GRTE")) - x2c_GRTE.write(w); - if (x30_COLR) - if (auto rec = w.enterSubRecord("COLR")) - x30_COLR.write(w); - if (x34_LTME) - if (auto rec = w.enterSubRecord("LTME")) - x34_LTME.write(w); - if (x38_ILOC) - if (auto rec = w.enterSubRecord("ILOC")) - x38_ILOC.write(w); - if (x3c_IVEC) - if (auto rec = w.enterSubRecord("IVEC")) - x3c_IVEC.write(w); - if (x40_EMTR) - if (auto rec = w.enterSubRecord("EMTR")) - x40_EMTR.write(w); - if (x44_24_LINE) - w.writeBool("LINE", true); - if (x44_25_FXLL) - w.writeBool("FXLL", true); - if (x44_26_AAPH) - w.writeBool("AAPH", true); - if (x44_27_ZBUF) - w.writeBool("ZBUF", true); - if (x44_28_SORT) - w.writeBool("SORT", true); - if (x44_29_LIT_) - w.writeBool("LIT_", true); - if (x44_30_MBLR) - w.writeBool("MBLR", true); - if (x44_31_PMAB) - w.writeBool("PMAB", true); - if (x45_24_PMUS) - w.writeBool("PMUS", true); - if (!x45_25_PMOO) - w.writeBool("PMOO", false); - if (x45_26_VMD1) - w.writeBool("VMD1", true); - if (x45_27_VMD2) - w.writeBool("VMD2", true); - if (x45_28_VMD3) - w.writeBool("VMD3", true); - if (x45_29_VMD4) - w.writeBool("VMD4", true); - if (x45_30_CIND) - w.writeBool("CIND", true); - if (x45_31_OPTS) - w.writeBool("OPTS", true); - if (x30_30_ORNT) - w.writeBool("ORNT", true); - if (x30_31_RSOP) - w.writeBool("RSOP", true); - if (x48_MBSP) - if (auto rec = w.enterSubRecord("MBSP")) - x48_MBSP.write(w); - if (x4c_SIZE) - if (auto rec = w.enterSubRecord("SIZE")) - x4c_SIZE.write(w); - if (x50_ROTA) - if (auto rec = w.enterSubRecord("ROTA")) - x50_ROTA.write(w); - if (x54_TEXR) - if (auto rec = w.enterSubRecord("TEXR")) - x54_TEXR.write(w); - if (x58_TIND) - if (auto rec = w.enterSubRecord("TIND")) - x58_TIND.write(w); - if (x5c_PMDL) - if (auto rec = w.enterSubRecord("PMDL")) - x5c_PMDL.write(w); - if (x6c_PMOP) - if (auto rec = w.enterSubRecord("PMOP")) - x6c_PMOP.write(w); - if (x70_PMRT) - if (auto rec = w.enterSubRecord("PMRT")) - x70_PMRT.write(w); - if (x74_PMSC) - if (auto rec = w.enterSubRecord("PMSC")) - x74_PMSC.write(w); - if (x78_PMCL) - if (auto rec = w.enterSubRecord("PMCL")) - x78_PMCL.write(w); - if (x7c_VEL1) - if (auto rec = w.enterSubRecord("VEL1")) - x7c_VEL1.write(w); - if (x80_VEL2) - if (auto rec = w.enterSubRecord("VEL2")) - x80_VEL2.write(w); - if (x84_VEL3) - if (auto rec = w.enterSubRecord("VEL3")) - x84_VEL3.write(w); - if (x88_VEL4) - if (auto rec = w.enterSubRecord("VEL4")) - x88_VEL4.write(w); - if (x8c_ICTS) - if (auto rec = w.enterSubRecord("ICTS")) - x8c_ICTS.write(w); - if (x9c_NCSY) - if (auto rec = w.enterSubRecord("NCSY")) - x9c_NCSY.write(w); - if (xa0_CSSD) - if (auto rec = w.enterSubRecord("CSSD")) - xa0_CSSD.write(w); - if (xa4_IDTS) - if (auto rec = w.enterSubRecord("IDTS")) - xa4_IDTS.write(w); - if (xb4_NDSY) - if (auto rec = w.enterSubRecord("NDSY")) - xb4_NDSY.write(w); - if (xb8_IITS) - if (auto rec = w.enterSubRecord("IITS")) - xb8_IITS.write(w); - if (xc8_PISY) - if (auto rec = w.enterSubRecord("PISY")) - xc8_PISY.write(w); - if (xcc_SISY) - if (auto rec = w.enterSubRecord("SISY")) - xcc_SISY.write(w); - if (xd0_KSSM) - if (auto rec = w.enterSubRecord("KSSM")) - xd0_KSSM.write(w); - if (xd4_SSWH) - if (auto rec = w.enterSubRecord("SSWH")) - xd4_SSWH.write(w); - if (xd8_SELC) - if (auto rec = w.enterSubRecord("SELC")) - xd8_SELC.write(w); - if (xe4_SSSD) - if (auto rec = w.enterSubRecord("SSSD")) - xe4_SSSD.write(w); - if (xe8_SSPO) - if (auto rec = w.enterSubRecord("SSPO")) - xe8_SSPO.write(w); - if (xf8_SESD) - if (auto rec = w.enterSubRecord("SESD")) - xf8_SESD.write(w); - if (xfc_SEPO) - if (auto rec = w.enterSubRecord("SEPO")) - xfc_SEPO.write(w); - if (xec_PMLC) - if (auto rec = w.enterSubRecord("PMLC")) - xec_PMLC.write(w); - if (x100_LTYP) - if (auto rec = w.enterSubRecord("LTYP")) - x100_LTYP.write(w); - if (x104_LCLR) - if (auto rec = w.enterSubRecord("LCLR")) - x104_LCLR.write(w); - if (x108_LINT) - if (auto rec = w.enterSubRecord("LINT")) - x108_LINT.write(w); - if (x10c_LOFF) - if (auto rec = w.enterSubRecord("LOFF")) - x10c_LOFF.write(w); - if (x110_LDIR) - if (auto rec = w.enterSubRecord("LDIR")) - x110_LDIR.write(w); - if (x114_LFOT) - if (auto rec = w.enterSubRecord("LFOT")) - x114_LFOT.write(w); - if (x118_LFOR) - if (auto rec = w.enterSubRecord("LFOR")) - x118_LFOR.write(w); - if (x11c_LSLA) - if (auto rec = w.enterSubRecord("LSLA")) - x11c_LSLA.write(w); - if (x10c_ADV1) - if (auto rec = w.enterSubRecord("ADV1")) - x10c_ADV1.write(w); - if (x110_ADV2) - if (auto rec = w.enterSubRecord("ADV2")) - x110_ADV2.write(w); - if (x114_ADV3) - if (auto rec = w.enterSubRecord("ADV3")) - x114_ADV3.write(w); - if (x118_ADV4) - if (auto rec = w.enterSubRecord("ADV4")) - x118_ADV4.write(w); - if (x11c_ADV5) - if (auto rec = w.enterSubRecord("ADV5")) - x11c_ADV5.write(w); - if (x120_ADV6) - if (auto rec = w.enterSubRecord("ADV6")) - x120_ADV6.write(w); - if (x124_ADV7) - if (auto rec = w.enterSubRecord("ADV7")) - x124_ADV7.write(w); - if (x128_ADV8) - if (auto rec = w.enterSubRecord("ADV8")) - x128_ADV8.write(w); +void GPSM::_write(typename WriteYaml::StreamT& w) const { + if (x0_PSIV) + if (auto rec = w.enterSubRecord("PSIV")) + x0_PSIV.write(w); + if (x4_PSVM) + if (auto rec = w.enterSubRecord("PSVM")) + x4_PSVM.write(w); + if (x8_PSOV) + if (auto rec = w.enterSubRecord("PSOV")) + x8_PSOV.write(w); + if (xc_PSLT) + if (auto rec = w.enterSubRecord("PSLT")) + xc_PSLT.write(w); + if (x10_PSWT) + if (auto rec = w.enterSubRecord("PSWT")) + x10_PSWT.write(w); + if (x14_PSTS) + if (auto rec = w.enterSubRecord("PSTS")) + x14_PSTS.write(w); + if (x18_POFS) + if (auto rec = w.enterSubRecord("POFS")) + x18_POFS.write(w); + if (x1c_SEED) + if (auto rec = w.enterSubRecord("SEED")) + x1c_SEED.write(w); + if (x20_LENG) + if (auto rec = w.enterSubRecord("LENG")) + x20_LENG.write(w); + if (x24_WIDT) + if (auto rec = w.enterSubRecord("WIDT")) + x24_WIDT.write(w); + if (x28_MAXP) + if (auto rec = w.enterSubRecord("MAXP")) + x28_MAXP.write(w); + if (x2c_GRTE) + if (auto rec = w.enterSubRecord("GRTE")) + x2c_GRTE.write(w); + if (x30_COLR) + if (auto rec = w.enterSubRecord("COLR")) + x30_COLR.write(w); + if (x34_LTME) + if (auto rec = w.enterSubRecord("LTME")) + x34_LTME.write(w); + if (x38_ILOC) + if (auto rec = w.enterSubRecord("ILOC")) + x38_ILOC.write(w); + if (x3c_IVEC) + if (auto rec = w.enterSubRecord("IVEC")) + x3c_IVEC.write(w); + if (x40_EMTR) + if (auto rec = w.enterSubRecord("EMTR")) + x40_EMTR.write(w); + if (x44_24_LINE) + w.writeBool("LINE", true); + if (x44_25_FXLL) + w.writeBool("FXLL", true); + if (x44_26_AAPH) + w.writeBool("AAPH", true); + if (x44_27_ZBUF) + w.writeBool("ZBUF", true); + if (x44_28_SORT) + w.writeBool("SORT", true); + if (x44_29_LIT_) + w.writeBool("LIT_", true); + if (x44_30_MBLR) + w.writeBool("MBLR", true); + if (x44_31_PMAB) + w.writeBool("PMAB", true); + if (x45_24_PMUS) + w.writeBool("PMUS", true); + if (!x45_25_PMOO) + w.writeBool("PMOO", false); + if (x45_26_VMD1) + w.writeBool("VMD1", true); + if (x45_27_VMD2) + w.writeBool("VMD2", true); + if (x45_28_VMD3) + w.writeBool("VMD3", true); + if (x45_29_VMD4) + w.writeBool("VMD4", true); + if (x45_30_CIND) + w.writeBool("CIND", true); + if (x45_31_OPTS) + w.writeBool("OPTS", true); + if (x30_30_ORNT) + w.writeBool("ORNT", true); + if (x30_31_RSOP) + w.writeBool("RSOP", true); + if (x48_MBSP) + if (auto rec = w.enterSubRecord("MBSP")) + x48_MBSP.write(w); + if (x4c_SIZE) + if (auto rec = w.enterSubRecord("SIZE")) + x4c_SIZE.write(w); + if (x50_ROTA) + if (auto rec = w.enterSubRecord("ROTA")) + x50_ROTA.write(w); + if (x54_TEXR) + if (auto rec = w.enterSubRecord("TEXR")) + x54_TEXR.write(w); + if (x58_TIND) + if (auto rec = w.enterSubRecord("TIND")) + x58_TIND.write(w); + if (x5c_PMDL) + if (auto rec = w.enterSubRecord("PMDL")) + x5c_PMDL.write(w); + if (x6c_PMOP) + if (auto rec = w.enterSubRecord("PMOP")) + x6c_PMOP.write(w); + if (x70_PMRT) + if (auto rec = w.enterSubRecord("PMRT")) + x70_PMRT.write(w); + if (x74_PMSC) + if (auto rec = w.enterSubRecord("PMSC")) + x74_PMSC.write(w); + if (x78_PMCL) + if (auto rec = w.enterSubRecord("PMCL")) + x78_PMCL.write(w); + if (x7c_VEL1) + if (auto rec = w.enterSubRecord("VEL1")) + x7c_VEL1.write(w); + if (x80_VEL2) + if (auto rec = w.enterSubRecord("VEL2")) + x80_VEL2.write(w); + if (x84_VEL3) + if (auto rec = w.enterSubRecord("VEL3")) + x84_VEL3.write(w); + if (x88_VEL4) + if (auto rec = w.enterSubRecord("VEL4")) + x88_VEL4.write(w); + if (x8c_ICTS) + if (auto rec = w.enterSubRecord("ICTS")) + x8c_ICTS.write(w); + if (x9c_NCSY) + if (auto rec = w.enterSubRecord("NCSY")) + x9c_NCSY.write(w); + if (xa0_CSSD) + if (auto rec = w.enterSubRecord("CSSD")) + xa0_CSSD.write(w); + if (xa4_IDTS) + if (auto rec = w.enterSubRecord("IDTS")) + xa4_IDTS.write(w); + if (xb4_NDSY) + if (auto rec = w.enterSubRecord("NDSY")) + xb4_NDSY.write(w); + if (xb8_IITS) + if (auto rec = w.enterSubRecord("IITS")) + xb8_IITS.write(w); + if (xc8_PISY) + if (auto rec = w.enterSubRecord("PISY")) + xc8_PISY.write(w); + if (xcc_SISY) + if (auto rec = w.enterSubRecord("SISY")) + xcc_SISY.write(w); + if (xd0_KSSM) + if (auto rec = w.enterSubRecord("KSSM")) + xd0_KSSM.write(w); + if (xd4_SSWH) + if (auto rec = w.enterSubRecord("SSWH")) + xd4_SSWH.write(w); + if (xd8_SELC) + if (auto rec = w.enterSubRecord("SELC")) + xd8_SELC.write(w); + if (xe4_SSSD) + if (auto rec = w.enterSubRecord("SSSD")) + xe4_SSSD.write(w); + if (xe8_SSPO) + if (auto rec = w.enterSubRecord("SSPO")) + xe8_SSPO.write(w); + if (xf8_SESD) + if (auto rec = w.enterSubRecord("SESD")) + xf8_SESD.write(w); + if (xfc_SEPO) + if (auto rec = w.enterSubRecord("SEPO")) + xfc_SEPO.write(w); + if (xec_PMLC) + if (auto rec = w.enterSubRecord("PMLC")) + xec_PMLC.write(w); + if (x100_LTYP) + if (auto rec = w.enterSubRecord("LTYP")) + x100_LTYP.write(w); + if (x104_LCLR) + if (auto rec = w.enterSubRecord("LCLR")) + x104_LCLR.write(w); + if (x108_LINT) + if (auto rec = w.enterSubRecord("LINT")) + x108_LINT.write(w); + if (x10c_LOFF) + if (auto rec = w.enterSubRecord("LOFF")) + x10c_LOFF.write(w); + if (x110_LDIR) + if (auto rec = w.enterSubRecord("LDIR")) + x110_LDIR.write(w); + if (x114_LFOT) + if (auto rec = w.enterSubRecord("LFOT")) + x114_LFOT.write(w); + if (x118_LFOR) + if (auto rec = w.enterSubRecord("LFOR")) + x118_LFOR.write(w); + if (x11c_LSLA) + if (auto rec = w.enterSubRecord("LSLA")) + x11c_LSLA.write(w); + if (x10c_ADV1) + if (auto rec = w.enterSubRecord("ADV1")) + x10c_ADV1.write(w); + if (x110_ADV2) + if (auto rec = w.enterSubRecord("ADV2")) + x110_ADV2.write(w); + if (x114_ADV3) + if (auto rec = w.enterSubRecord("ADV3")) + x114_ADV3.write(w); + if (x118_ADV4) + if (auto rec = w.enterSubRecord("ADV4")) + x118_ADV4.write(w); + if (x11c_ADV5) + if (auto rec = w.enterSubRecord("ADV5")) + x11c_ADV5.write(w); + if (x120_ADV6) + if (auto rec = w.enterSubRecord("ADV6")) + x120_ADV6.write(w); + if (x124_ADV7) + if (auto rec = w.enterSubRecord("ADV7")) + x124_ADV7.write(w); + if (x128_ADV8) + if (auto rec = w.enterSubRecord("ADV8")) + x128_ADV8.write(w); } template -void GPSM::_binarySize(typename BinarySize::StreamT& s) const -{ +void GPSM::_binarySize(typename BinarySize::StreamT& s) const { + s += 4; + if (x0_PSIV) { s += 4; - if (x0_PSIV) - { - s += 4; - x0_PSIV.binarySize(s); - } - if (x4_PSVM) - { - s += 4; - x4_PSVM.binarySize(s); - } - if (x8_PSOV) - { - s += 4; - x8_PSOV.binarySize(s); - } - if (xc_PSLT) - { - s += 4; - xc_PSLT.binarySize(s); - } - if (x10_PSWT) - { - s += 4; - x10_PSWT.binarySize(s); - } - if (x14_PSTS) - { - s += 4; - x14_PSTS.binarySize(s); - } - if (x18_POFS) - { - s += 4; - x18_POFS.binarySize(s); - } - if (x1c_SEED) - { - s += 4; - x1c_SEED.binarySize(s); - } - if (x20_LENG) - { - s += 4; - x20_LENG.binarySize(s); - } - if (x24_WIDT) - { - s += 4; - x24_WIDT.binarySize(s); - } - if (x28_MAXP) - { - s += 4; - x28_MAXP.binarySize(s); - } - if (x2c_GRTE) - { - s += 4; - x2c_GRTE.binarySize(s); - } - if (x30_COLR) - { - s += 4; - x30_COLR.binarySize(s); - } - if (x34_LTME) - { - s += 4; - x34_LTME.binarySize(s); - } - if (x38_ILOC) - { - s += 4; - x38_ILOC.binarySize(s); - } - if (x3c_IVEC) - { - s += 4; - x3c_IVEC.binarySize(s); - } - if (x40_EMTR) - { - s += 4; - x40_EMTR.binarySize(s); - } - if (x44_24_LINE) - s += 9; - if (x44_25_FXLL) - s += 9; - if (x44_26_AAPH) - s += 9; - if (x44_27_ZBUF) - s += 9; - if (x44_28_SORT) - s += 9; - if (x44_29_LIT_) - s += 9; - if (x44_30_MBLR) - s += 9; - if (x44_31_PMAB) - s += 9; - if (x45_24_PMUS) - s += 9; - if (!x45_25_PMOO) - s += 9; - if (x45_26_VMD1) - s += 9; - if (x45_27_VMD2) - s += 9; - if (x45_28_VMD3) - s += 9; - if (x45_29_VMD4) - s += 9; - if (x45_30_CIND) - s += 9; - if (x45_31_OPTS) - s += 9; - if (x30_30_ORNT) - s += 9; - if (x30_31_RSOP) - s += 9; - if (x48_MBSP) - { - s += 4; - x48_MBSP.binarySize(s); - } - if (x4c_SIZE) - { - s += 4; - x4c_SIZE.binarySize(s); - } - if (x50_ROTA) - { - s += 4; - x50_ROTA.binarySize(s); - } - if (x54_TEXR) - { - s += 4; - x54_TEXR.binarySize(s); - } - if (x58_TIND) - { - s += 4; - x58_TIND.binarySize(s); - } - if (x5c_PMDL) - { - s += 4; - x5c_PMDL.binarySize(s); - } - if (x6c_PMOP) - { - s += 4; - x6c_PMOP.binarySize(s); - } - if (x70_PMRT) - { - s += 4; - x70_PMRT.binarySize(s); - } - if (x74_PMSC) - { - s += 4; - x74_PMSC.binarySize(s); - } - if (x78_PMCL) - { - s += 4; - x78_PMCL.binarySize(s); - } - if (x7c_VEL1) - { - s += 4; - x7c_VEL1.binarySize(s); - } - if (x80_VEL2) - { - s += 4; - x80_VEL2.binarySize(s); - } - if (x84_VEL3) - { - s += 4; - x84_VEL3.binarySize(s); - } - if (x88_VEL4) - { - s += 4; - x88_VEL4.binarySize(s); - } - if (x8c_ICTS) - { - s += 4; - x8c_ICTS.binarySize(s); - } - if (x9c_NCSY) - { - s += 4; - x9c_NCSY.binarySize(s); - } - if (xa0_CSSD) - { - s += 4; - xa0_CSSD.binarySize(s); - } - if (xa4_IDTS) - { - s += 4; - xa4_IDTS.binarySize(s); - } - if (xb4_NDSY) - { - s += 4; - xb4_NDSY.binarySize(s); - } - if (xb8_IITS) - { - s += 4; - xb8_IITS.binarySize(s); - } - if (xc8_PISY) - { - s += 4; - xc8_PISY.binarySize(s); - } - if (xcc_SISY) - { - s += 4; - xcc_SISY.binarySize(s); - } - if (xd0_KSSM) - { - s += 4; - xd0_KSSM.binarySize(s); - } - if (xd4_SSWH) - { - s += 4; - xd4_SSWH.binarySize(s); - } - if (xd8_SELC) - { - s += 4; - xd8_SELC.binarySize(s); - } - if (xe4_SSSD) - { - s += 4; - xe4_SSSD.binarySize(s); - } - if (xe8_SSPO) - { - s += 4; - xe8_SSPO.binarySize(s); - } - if (xf8_SESD) - { - s += 4; - xf8_SESD.binarySize(s); - } - if (xfc_SEPO) - { - s += 4; - xfc_SEPO.binarySize(s); - } - if (xec_PMLC) - { - s += 4; - xec_PMLC.binarySize(s); - } - if (x100_LTYP) - { - s += 4; - x100_LTYP.binarySize(s); - } - if (x104_LCLR) - { - s += 4; - x104_LCLR.binarySize(s); - } - if (x108_LINT) - { - s += 4; - x108_LINT.binarySize(s); - } - if (x10c_LOFF) - { - s += 4; - x10c_LOFF.binarySize(s); - } - if (x110_LDIR) - { - s += 4; - x110_LDIR.binarySize(s); - } - if (x114_LFOT) - { - s += 4; - x114_LFOT.binarySize(s); - } - if (x118_LFOR) - { - s += 4; - x118_LFOR.binarySize(s); - } - if (x11c_LSLA) - { - s += 4; - x11c_LSLA.binarySize(s); - } - if (x10c_ADV1) - { - s += 4; - x10c_ADV1.binarySize(s); - } - if (x110_ADV2) - { - s += 4; - x110_ADV2.binarySize(s); - } - if (x114_ADV3) - { - s += 4; - x114_ADV3.binarySize(s); - } - if (x118_ADV4) - { - s += 4; - x118_ADV4.binarySize(s); - } - if (x11c_ADV5) - { - s += 4; - x11c_ADV5.binarySize(s); - } - if (x120_ADV6) - { - s += 4; - x120_ADV6.binarySize(s); - } - if (x124_ADV7) - { - s += 4; - x124_ADV7.binarySize(s); - } - if (x128_ADV8) - { - s += 4; - x128_ADV8.binarySize(s); - } + x0_PSIV.binarySize(s); + } + if (x4_PSVM) { + s += 4; + x4_PSVM.binarySize(s); + } + if (x8_PSOV) { + s += 4; + x8_PSOV.binarySize(s); + } + if (xc_PSLT) { + s += 4; + xc_PSLT.binarySize(s); + } + if (x10_PSWT) { + s += 4; + x10_PSWT.binarySize(s); + } + if (x14_PSTS) { + s += 4; + x14_PSTS.binarySize(s); + } + if (x18_POFS) { + s += 4; + x18_POFS.binarySize(s); + } + if (x1c_SEED) { + s += 4; + x1c_SEED.binarySize(s); + } + if (x20_LENG) { + s += 4; + x20_LENG.binarySize(s); + } + if (x24_WIDT) { + s += 4; + x24_WIDT.binarySize(s); + } + if (x28_MAXP) { + s += 4; + x28_MAXP.binarySize(s); + } + if (x2c_GRTE) { + s += 4; + x2c_GRTE.binarySize(s); + } + if (x30_COLR) { + s += 4; + x30_COLR.binarySize(s); + } + if (x34_LTME) { + s += 4; + x34_LTME.binarySize(s); + } + if (x38_ILOC) { + s += 4; + x38_ILOC.binarySize(s); + } + if (x3c_IVEC) { + s += 4; + x3c_IVEC.binarySize(s); + } + if (x40_EMTR) { + s += 4; + x40_EMTR.binarySize(s); + } + if (x44_24_LINE) + s += 9; + if (x44_25_FXLL) + s += 9; + if (x44_26_AAPH) + s += 9; + if (x44_27_ZBUF) + s += 9; + if (x44_28_SORT) + s += 9; + if (x44_29_LIT_) + s += 9; + if (x44_30_MBLR) + s += 9; + if (x44_31_PMAB) + s += 9; + if (x45_24_PMUS) + s += 9; + if (!x45_25_PMOO) + s += 9; + if (x45_26_VMD1) + s += 9; + if (x45_27_VMD2) + s += 9; + if (x45_28_VMD3) + s += 9; + if (x45_29_VMD4) + s += 9; + if (x45_30_CIND) + s += 9; + if (x45_31_OPTS) + s += 9; + if (x30_30_ORNT) + s += 9; + if (x30_31_RSOP) + s += 9; + if (x48_MBSP) { + s += 4; + x48_MBSP.binarySize(s); + } + if (x4c_SIZE) { + s += 4; + x4c_SIZE.binarySize(s); + } + if (x50_ROTA) { + s += 4; + x50_ROTA.binarySize(s); + } + if (x54_TEXR) { + s += 4; + x54_TEXR.binarySize(s); + } + if (x58_TIND) { + s += 4; + x58_TIND.binarySize(s); + } + if (x5c_PMDL) { + s += 4; + x5c_PMDL.binarySize(s); + } + if (x6c_PMOP) { + s += 4; + x6c_PMOP.binarySize(s); + } + if (x70_PMRT) { + s += 4; + x70_PMRT.binarySize(s); + } + if (x74_PMSC) { + s += 4; + x74_PMSC.binarySize(s); + } + if (x78_PMCL) { + s += 4; + x78_PMCL.binarySize(s); + } + if (x7c_VEL1) { + s += 4; + x7c_VEL1.binarySize(s); + } + if (x80_VEL2) { + s += 4; + x80_VEL2.binarySize(s); + } + if (x84_VEL3) { + s += 4; + x84_VEL3.binarySize(s); + } + if (x88_VEL4) { + s += 4; + x88_VEL4.binarySize(s); + } + if (x8c_ICTS) { + s += 4; + x8c_ICTS.binarySize(s); + } + if (x9c_NCSY) { + s += 4; + x9c_NCSY.binarySize(s); + } + if (xa0_CSSD) { + s += 4; + xa0_CSSD.binarySize(s); + } + if (xa4_IDTS) { + s += 4; + xa4_IDTS.binarySize(s); + } + if (xb4_NDSY) { + s += 4; + xb4_NDSY.binarySize(s); + } + if (xb8_IITS) { + s += 4; + xb8_IITS.binarySize(s); + } + if (xc8_PISY) { + s += 4; + xc8_PISY.binarySize(s); + } + if (xcc_SISY) { + s += 4; + xcc_SISY.binarySize(s); + } + if (xd0_KSSM) { + s += 4; + xd0_KSSM.binarySize(s); + } + if (xd4_SSWH) { + s += 4; + xd4_SSWH.binarySize(s); + } + if (xd8_SELC) { + s += 4; + xd8_SELC.binarySize(s); + } + if (xe4_SSSD) { + s += 4; + xe4_SSSD.binarySize(s); + } + if (xe8_SSPO) { + s += 4; + xe8_SSPO.binarySize(s); + } + if (xf8_SESD) { + s += 4; + xf8_SESD.binarySize(s); + } + if (xfc_SEPO) { + s += 4; + xfc_SEPO.binarySize(s); + } + if (xec_PMLC) { + s += 4; + xec_PMLC.binarySize(s); + } + if (x100_LTYP) { + s += 4; + x100_LTYP.binarySize(s); + } + if (x104_LCLR) { + s += 4; + x104_LCLR.binarySize(s); + } + if (x108_LINT) { + s += 4; + x108_LINT.binarySize(s); + } + if (x10c_LOFF) { + s += 4; + x10c_LOFF.binarySize(s); + } + if (x110_LDIR) { + s += 4; + x110_LDIR.binarySize(s); + } + if (x114_LFOT) { + s += 4; + x114_LFOT.binarySize(s); + } + if (x118_LFOR) { + s += 4; + x118_LFOR.binarySize(s); + } + if (x11c_LSLA) { + s += 4; + x11c_LSLA.binarySize(s); + } + if (x10c_ADV1) { + s += 4; + x10c_ADV1.binarySize(s); + } + if (x110_ADV2) { + s += 4; + x110_ADV2.binarySize(s); + } + if (x114_ADV3) { + s += 4; + x114_ADV3.binarySize(s); + } + if (x118_ADV4) { + s += 4; + x118_ADV4.binarySize(s); + } + if (x11c_ADV5) { + s += 4; + x11c_ADV5.binarySize(s); + } + if (x120_ADV6) { + s += 4; + x120_ADV6.binarySize(s); + } + if (x124_ADV7) { + s += 4; + x124_ADV7.binarySize(s); + } + if (x128_ADV8) { + s += 4; + x128_ADV8.binarySize(s); + } } template -void GPSM::_read(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId != SBIG('GPSM')) - { - LogModule.report(logvisor::Warning, "non GPSM provided to GPSM parser"); - return; +void GPSM::_read(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId != SBIG('GPSM')) { + LogModule.report(logvisor::Warning, "non GPSM provided to GPSM parser"); + return; + } + r.readBytesToBuf(&clsId, 4); + while (clsId != SBIG('_END')) { + switch (clsId) { + case SBIG('PMCL'): + x78_PMCL.read(r); + break; + case SBIG('LFOR'): + x118_LFOR.read(r); + break; + case SBIG('IDTS'): + xa4_IDTS.read(r); + break; + case SBIG('EMTR'): + x40_EMTR.read(r); + break; + case SBIG('COLR'): + x30_COLR.read(r); + break; + case SBIG('CIND'): + r.readUint32Big(); + x45_30_CIND = r.readBool(); + break; + case SBIG('AAPH'): + r.readUint32Big(); + x44_26_AAPH = r.readBool(); + break; + case SBIG('CSSD'): + xa0_CSSD.read(r); + break; + case SBIG('GRTE'): + x2c_GRTE.read(r); + break; + case SBIG('FXLL'): + r.readUint32Big(); + x44_25_FXLL = r.readBool(); + break; + case SBIG('ICTS'): + x8c_ICTS.read(r); + break; + case SBIG('KSSM'): + xd0_KSSM.read(r); + break; + case SBIG('ILOC'): + x38_ILOC.read(r); + break; + case SBIG('IITS'): + xb8_IITS.read(r); + break; + case SBIG('IVEC'): + x3c_IVEC.read(r); + break; + case SBIG('LDIR'): + x110_LDIR.read(r); + break; + case SBIG('LCLR'): + x104_LCLR.read(r); + break; + case SBIG('LENG'): + x20_LENG.read(r); + break; + case SBIG('MAXP'): + x28_MAXP.read(r); + break; + case SBIG('LOFF'): + x10c_LOFF.read(r); + break; + case SBIG('LINT'): + x108_LINT.read(r); + break; + case SBIG('LINE'): + r.readUint32Big(); + x44_24_LINE = r.readBool(); + break; + case SBIG('LFOT'): + x114_LFOT.read(r); + break; + case SBIG('LIT_'): + r.readUint32Big(); + x44_29_LIT_ = r.readBool(); + break; + case SBIG('LTME'): + x34_LTME.read(r); + break; + case SBIG('LSLA'): + x11c_LSLA.read(r); + break; + case SBIG('LTYP'): + x100_LTYP.read(r); + break; + case SBIG('NDSY'): + xb4_NDSY.read(r); + break; + case SBIG('MBSP'): + x48_MBSP.read(r); + break; + case SBIG('MBLR'): + r.readUint32Big(); + x44_30_MBLR = r.readBool(); + break; + case SBIG('NCSY'): + x9c_NCSY.read(r); + break; + case SBIG('PISY'): + xc8_PISY.read(r); + break; + case SBIG('OPTS'): + r.readUint32Big(); + x45_31_OPTS = r.readBool(); + break; + case SBIG('PMAB'): + r.readUint32Big(); + x44_31_PMAB = r.readBool(); + break; + case SBIG('SESD'): + xf8_SESD.read(r); + break; + case SBIG('SEPO'): + xfc_SEPO.read(r); + break; + case SBIG('PSLT'): + xc_PSLT.read(r); + break; + case SBIG('PMSC'): + x74_PMSC.read(r); + break; + case SBIG('PMOP'): + x6c_PMOP.read(r); + break; + case SBIG('PMDL'): + x5c_PMDL.read(r); + break; + case SBIG('PMRT'): + x70_PMRT.read(r); + break; + case SBIG('POFS'): + x18_POFS.read(r); + break; + case SBIG('PMUS'): + r.readUint32Big(); + x45_24_PMUS = r.readBool(); + break; + case SBIG('PSIV'): + x0_PSIV.read(r); + break; + case SBIG('ROTA'): + x50_ROTA.read(r); + break; + case SBIG('PSVM'): + x4_PSVM.read(r); + break; + case SBIG('PSTS'): + x14_PSTS.read(r); + break; + case SBIG('PSOV'): + x8_PSOV.read(r); + break; + case SBIG('PSWT'): + x10_PSWT.read(r); + break; + case SBIG('PMLC'): + xec_PMLC.read(r); + break; + case SBIG('SEED'): + x1c_SEED.read(r); + break; + case SBIG('PMOO'): + r.readUint32Big(); + x45_25_PMOO = r.readBool(); + break; + case SBIG('SSSD'): + xe4_SSSD.read(r); + break; + case SBIG('SORT'): + r.readUint32Big(); + x44_28_SORT = r.readBool(); + break; + case SBIG('SIZE'): + x4c_SIZE.read(r); + break; + case SBIG('SISY'): + xcc_SISY.read(r); + break; + case SBIG('SSPO'): + xe8_SSPO.read(r); + break; + case SBIG('TEXR'): + x54_TEXR.read(r); + break; + case SBIG('SSWH'): + xd4_SSWH.read(r); + break; + case SBIG('TIND'): + x58_TIND.read(r); + break; + case SBIG('VMD4'): + r.readUint32Big(); + x45_29_VMD4 = r.readBool(); + break; + case SBIG('VMD3'): + r.readUint32Big(); + x45_28_VMD3 = r.readBool(); + break; + case SBIG('VMD2'): + r.readUint32Big(); + x45_27_VMD2 = r.readBool(); + break; + case SBIG('VMD1'): + r.readUint32Big(); + x45_26_VMD1 = r.readBool(); + break; + case SBIG('VEL4'): + x88_VEL4.read(r); + break; + case SBIG('VEL3'): + x84_VEL3.read(r); + break; + case SBIG('VEL2'): + x80_VEL2.read(r); + break; + case SBIG('VEL1'): + x7c_VEL1.read(r); + break; + case SBIG('ZBUF'): + r.readUint32Big(); + x44_27_ZBUF = r.readBool(); + break; + case SBIG('WIDT'): + x24_WIDT.read(r); + break; + case SBIG('ORNT'): + r.readUint32Big(); + x30_30_ORNT = r.readBool(); + break; + case SBIG('RSOP'): + r.readUint32Big(); + x30_31_RSOP = r.readBool(); + break; + case SBIG('ADV1'): + x10c_ADV1.read(r); + break; + case SBIG('ADV2'): + x110_ADV2.read(r); + break; + case SBIG('ADV3'): + x114_ADV3.read(r); + break; + case SBIG('ADV4'): + x118_ADV4.read(r); + break; + case SBIG('ADV5'): + x11c_ADV5.read(r); + break; + case SBIG('ADV6'): + x120_ADV6.read(r); + break; + case SBIG('ADV7'): + x124_ADV7.read(r); + break; + case SBIG('ADV8'): + x128_ADV8.read(r); + break; + case SBIG('SELC'): + xd8_SELC.read(r); + break; + default: + LogModule.report(logvisor::Fatal, "Unknown GPSM class %.4s @%" PRIi64, &clsId, r.position()); + break; } r.readBytesToBuf(&clsId, 4); - while (clsId != SBIG('_END')) - { - switch (clsId) - { - case SBIG('PMCL'): - x78_PMCL.read(r); - break; - case SBIG('LFOR'): - x118_LFOR.read(r); - break; - case SBIG('IDTS'): - xa4_IDTS.read(r); - break; - case SBIG('EMTR'): - x40_EMTR.read(r); - break; - case SBIG('COLR'): - x30_COLR.read(r); - break; - case SBIG('CIND'): - r.readUint32Big(); - x45_30_CIND = r.readBool(); - break; - case SBIG('AAPH'): - r.readUint32Big(); - x44_26_AAPH = r.readBool(); - break; - case SBIG('CSSD'): - xa0_CSSD.read(r); - break; - case SBIG('GRTE'): - x2c_GRTE.read(r); - break; - case SBIG('FXLL'): - r.readUint32Big(); - x44_25_FXLL = r.readBool(); - break; - case SBIG('ICTS'): - x8c_ICTS.read(r); - break; - case SBIG('KSSM'): - xd0_KSSM.read(r); - break; - case SBIG('ILOC'): - x38_ILOC.read(r); - break; - case SBIG('IITS'): - xb8_IITS.read(r); - break; - case SBIG('IVEC'): - x3c_IVEC.read(r); - break; - case SBIG('LDIR'): - x110_LDIR.read(r); - break; - case SBIG('LCLR'): - x104_LCLR.read(r); - break; - case SBIG('LENG'): - x20_LENG.read(r); - break; - case SBIG('MAXP'): - x28_MAXP.read(r); - break; - case SBIG('LOFF'): - x10c_LOFF.read(r); - break; - case SBIG('LINT'): - x108_LINT.read(r); - break; - case SBIG('LINE'): - r.readUint32Big(); - x44_24_LINE = r.readBool(); - break; - case SBIG('LFOT'): - x114_LFOT.read(r); - break; - case SBIG('LIT_'): - r.readUint32Big(); - x44_29_LIT_ = r.readBool(); - break; - case SBIG('LTME'): - x34_LTME.read(r); - break; - case SBIG('LSLA'): - x11c_LSLA.read(r); - break; - case SBIG('LTYP'): - x100_LTYP.read(r); - break; - case SBIG('NDSY'): - xb4_NDSY.read(r); - break; - case SBIG('MBSP'): - x48_MBSP.read(r); - break; - case SBIG('MBLR'): - r.readUint32Big(); - x44_30_MBLR = r.readBool(); - break; - case SBIG('NCSY'): - x9c_NCSY.read(r); - break; - case SBIG('PISY'): - xc8_PISY.read(r); - break; - case SBIG('OPTS'): - r.readUint32Big(); - x45_31_OPTS = r.readBool(); - break; - case SBIG('PMAB'): - r.readUint32Big(); - x44_31_PMAB = r.readBool(); - break; - case SBIG('SESD'): - xf8_SESD.read(r); - break; - case SBIG('SEPO'): - xfc_SEPO.read(r); - break; - case SBIG('PSLT'): - xc_PSLT.read(r); - break; - case SBIG('PMSC'): - x74_PMSC.read(r); - break; - case SBIG('PMOP'): - x6c_PMOP.read(r); - break; - case SBIG('PMDL'): - x5c_PMDL.read(r); - break; - case SBIG('PMRT'): - x70_PMRT.read(r); - break; - case SBIG('POFS'): - x18_POFS.read(r); - break; - case SBIG('PMUS'): - r.readUint32Big(); - x45_24_PMUS = r.readBool(); - break; - case SBIG('PSIV'): - x0_PSIV.read(r); - break; - case SBIG('ROTA'): - x50_ROTA.read(r); - break; - case SBIG('PSVM'): - x4_PSVM.read(r); - break; - case SBIG('PSTS'): - x14_PSTS.read(r); - break; - case SBIG('PSOV'): - x8_PSOV.read(r); - break; - case SBIG('PSWT'): - x10_PSWT.read(r); - break; - case SBIG('PMLC'): - xec_PMLC.read(r); - break; - case SBIG('SEED'): - x1c_SEED.read(r); - break; - case SBIG('PMOO'): - r.readUint32Big(); - x45_25_PMOO = r.readBool(); - break; - case SBIG('SSSD'): - xe4_SSSD.read(r); - break; - case SBIG('SORT'): - r.readUint32Big(); - x44_28_SORT = r.readBool(); - break; - case SBIG('SIZE'): - x4c_SIZE.read(r); - break; - case SBIG('SISY'): - xcc_SISY.read(r); - break; - case SBIG('SSPO'): - xe8_SSPO.read(r); - break; - case SBIG('TEXR'): - x54_TEXR.read(r); - break; - case SBIG('SSWH'): - xd4_SSWH.read(r); - break; - case SBIG('TIND'): - x58_TIND.read(r); - break; - case SBIG('VMD4'): - r.readUint32Big(); - x45_29_VMD4 = r.readBool(); - break; - case SBIG('VMD3'): - r.readUint32Big(); - x45_28_VMD3 = r.readBool(); - break; - case SBIG('VMD2'): - r.readUint32Big(); - x45_27_VMD2 = r.readBool(); - break; - case SBIG('VMD1'): - r.readUint32Big(); - x45_26_VMD1 = r.readBool(); - break; - case SBIG('VEL4'): - x88_VEL4.read(r); - break; - case SBIG('VEL3'): - x84_VEL3.read(r); - break; - case SBIG('VEL2'): - x80_VEL2.read(r); - break; - case SBIG('VEL1'): - x7c_VEL1.read(r); - break; - case SBIG('ZBUF'): - r.readUint32Big(); - x44_27_ZBUF = r.readBool(); - break; - case SBIG('WIDT'): - x24_WIDT.read(r); - break; - case SBIG('ORNT'): - r.readUint32Big(); - x30_30_ORNT = r.readBool(); - break; - case SBIG('RSOP'): - r.readUint32Big(); - x30_31_RSOP = r.readBool(); - break; - case SBIG('ADV1'): - x10c_ADV1.read(r); - break; - case SBIG('ADV2'): - x110_ADV2.read(r); - break; - case SBIG('ADV3'): - x114_ADV3.read(r); - break; - case SBIG('ADV4'): - x118_ADV4.read(r); - break; - case SBIG('ADV5'): - x11c_ADV5.read(r); - break; - case SBIG('ADV6'): - x120_ADV6.read(r); - break; - case SBIG('ADV7'): - x124_ADV7.read(r); - break; - case SBIG('ADV8'): - x128_ADV8.read(r); - break; - case SBIG('SELC'): - xd8_SELC.read(r); - break; - default: - LogModule.report(logvisor::Fatal, "Unknown GPSM class %.4s @%" PRIi64, &clsId, r.position()); - break; - } - r.readBytesToBuf(&clsId, 4); - } + } } template -void GPSM::_write(typename Write::StreamT& w) const -{ - w.writeBytes((atInt8*)"GPSM", 4); - if (x0_PSIV) - { - w.writeBytes((atInt8*)"PSIV", 4); - x0_PSIV.write(w); - } - if (x4_PSVM) - { - w.writeBytes((atInt8*)"PSVM", 4); - x4_PSVM.write(w); - } - if (x8_PSOV) - { - w.writeBytes((atInt8*)"PSOV", 4); - x8_PSOV.write(w); - } - if (xc_PSLT) - { - w.writeBytes((atInt8*)"PSLT", 4); - xc_PSLT.write(w); - } - if (x10_PSWT) - { - w.writeBytes((atInt8*)"PSWT", 4); - x10_PSWT.write(w); - } - if (x14_PSTS) - { - w.writeBytes((atInt8*)"PSTS", 4); - x14_PSTS.write(w); - } - if (x18_POFS) - { - w.writeBytes((atInt8*)"POFS", 4); - x18_POFS.write(w); - } - if (x1c_SEED) - { - w.writeBytes((atInt8*)"SEED", 4); - x1c_SEED.write(w); - } - if (x20_LENG) - { - w.writeBytes((atInt8*)"LENG", 4); - x20_LENG.write(w); - } - if (x24_WIDT) - { - w.writeBytes((atInt8*)"WIDT", 4); - x24_WIDT.write(w); - } - if (x28_MAXP) - { - w.writeBytes((atInt8*)"MAXP", 4); - x28_MAXP.write(w); - } - if (x2c_GRTE) - { - w.writeBytes((atInt8*)"GRTE", 4); - x2c_GRTE.write(w); - } - if (x30_COLR) - { - w.writeBytes((atInt8*)"COLR", 4); - x30_COLR.write(w); - } - if (x34_LTME) - { - w.writeBytes((atInt8*)"LTME", 4); - x34_LTME.write(w); - } - if (x38_ILOC) - { - w.writeBytes((atInt8*)"ILOC", 4); - x38_ILOC.write(w); - } - if (x3c_IVEC) - { - w.writeBytes((atInt8*)"IVEC", 4); - x3c_IVEC.write(w); - } - if (x40_EMTR) - { - w.writeBytes((atInt8*)"EMTR", 4); - x40_EMTR.write(w); - } - if (x44_24_LINE) - { - w.writeBytes((atInt8*)"LINECNST\x01", 9); - } - if (x44_25_FXLL) - { - w.writeBytes((atInt8*)"FXLLCNST\x01", 9); - } - if (x44_26_AAPH) - { - w.writeBytes((atInt8*)"AAPHCNST\x01", 9); - } - if (x44_27_ZBUF) - { - w.writeBytes((atInt8*)"ZBUFCNST\x01", 9); - } - if (x44_28_SORT) - { - w.writeBytes((atInt8*)"SORTCNST\x01", 9); - } - if (x44_29_LIT_) - { - w.writeBytes((atInt8*)"LIT_CNST\x01", 9); - } - if (x44_30_MBLR) - { - w.writeBytes((atInt8*)"MBLRCNST\x01", 9); - } - if (x44_31_PMAB) - { - w.writeBytes((atInt8*)"PMABCNST\x01", 9); - } - if (x45_24_PMUS) - { - w.writeBytes((atInt8*)"PMUSCNST\x01", 9); - } - if (!x45_25_PMOO) - { - w.writeBytes((atInt8*)"PMOOCNST\x00", 9); - } - if (x45_26_VMD1) - { - w.writeBytes((atInt8*)"VMD1CNST\x01", 9); - } - if (x45_27_VMD2) - { - w.writeBytes((atInt8*)"VMD2CNST\x01", 9); - } - if (x45_28_VMD3) - { - w.writeBytes((atInt8*)"VMD3CNST\x01", 9); - } - if (x45_29_VMD4) - { - w.writeBytes((atInt8*)"VMD4CNST\x01", 9); - } - if (x45_30_CIND) - { - w.writeBytes((atInt8*)"CINDCNST\x01", 9); - } - if (x45_31_OPTS) - { - w.writeBytes((atInt8*)"OPTSCNST\x01", 9); - } - if (x30_30_ORNT) - { - w.writeBytes((atInt8*)"ORNTCNST\x01", 9); - } - if (x30_31_RSOP) - { - w.writeBytes((atInt8*)"RSOPCNST\x01", 9); - } - if (x48_MBSP) - { - w.writeBytes((atInt8*)"MBSP", 4); - x48_MBSP.write(w); - } - if (x4c_SIZE) - { - w.writeBytes((atInt8*)"SIZE", 4); - x4c_SIZE.write(w); - } - if (x50_ROTA) - { - w.writeBytes((atInt8*)"ROTA", 4); - x50_ROTA.write(w); - } - if (x54_TEXR) - { - w.writeBytes((atInt8*)"TEXR", 4); - x54_TEXR.write(w); - } - if (x58_TIND) - { - w.writeBytes((atInt8*)"TIND", 4); - x58_TIND.write(w); - } - if (x5c_PMDL) - { - w.writeBytes((atInt8*)"PMDL", 4); - x5c_PMDL.write(w); - } - if (x6c_PMOP) - { - w.writeBytes((atInt8*)"PMOP", 4); - x6c_PMOP.write(w); - } - if (x70_PMRT) - { - w.writeBytes((atInt8*)"PMRT", 4); - x70_PMRT.write(w); - } - if (x74_PMSC) - { - w.writeBytes((atInt8*)"PMSC", 4); - x74_PMSC.write(w); - } - if (x78_PMCL) - { - w.writeBytes((atInt8*)"PMCL", 4); - x78_PMCL.write(w); - } - if (x7c_VEL1) - { - w.writeBytes((atInt8*)"VEL1", 4); - x7c_VEL1.write(w); - } - if (x80_VEL2) - { - w.writeBytes((atInt8*)"VEL2", 4); - x80_VEL2.write(w); - } - if (x84_VEL3) - { - w.writeBytes((atInt8*)"VEL3", 4); - x84_VEL3.write(w); - } - if (x88_VEL4) - { - w.writeBytes((atInt8*)"VEL4", 4); - x88_VEL4.write(w); - } - if (x8c_ICTS) - { - w.writeBytes((atInt8*)"ICTS", 4); - x8c_ICTS.write(w); - } - if (x9c_NCSY) - { - w.writeBytes((atInt8*)"NCSY", 4); - x9c_NCSY.write(w); - } - if (xa0_CSSD) - { - w.writeBytes((atInt8*)"CSSD", 4); - xa0_CSSD.write(w); - } - if (xa4_IDTS) - { - w.writeBytes((atInt8*)"IDTS", 4); - xa4_IDTS.write(w); - } - if (xb4_NDSY) - { - w.writeBytes((atInt8*)"NDSY", 4); - xb4_NDSY.write(w); - } - if (xb8_IITS) - { - w.writeBytes((atInt8*)"IITS", 4); - xb8_IITS.write(w); - } - if (xc8_PISY) - { - w.writeBytes((atInt8*)"PISY", 4); - xc8_PISY.write(w); - } - if (xcc_SISY) - { - w.writeBytes((atInt8*)"SISY", 4); - xcc_SISY.write(w); - } - if (xd0_KSSM) - { - w.writeBytes((atInt8*)"KSSM", 4); - xd0_KSSM.write(w); - } - if (xd4_SSWH) - { - w.writeBytes((atInt8*)"SSWH", 4); - xd4_SSWH.write(w); - } - if (xd8_SELC) - { - w.writeBytes((atInt8*)"SELC", 4); - xd8_SELC.write(w); - } - if (xe4_SSSD) - { - w.writeBytes((atInt8*)"SSSD", 4); - xe4_SSSD.write(w); - } - if (xe8_SSPO) - { - w.writeBytes((atInt8*)"SSPO", 4); - xe8_SSPO.write(w); - } - if (xf8_SESD) - { - w.writeBytes((atInt8*)"SESD", 4); - xf8_SESD.write(w); - } - if (xfc_SEPO) - { - w.writeBytes((atInt8*)"SEPO", 4); - xfc_SEPO.write(w); - } - if (xec_PMLC) - { - w.writeBytes((atInt8*)"PMLC", 4); - xec_PMLC.write(w); - } - if (x100_LTYP) - { - w.writeBytes((atInt8*)"LTYP", 4); - x100_LTYP.write(w); - } - if (x104_LCLR) - { - w.writeBytes((atInt8*)"LCLR", 4); - x104_LCLR.write(w); - } - if (x108_LINT) - { - w.writeBytes((atInt8*)"LINT", 4); - x108_LINT.write(w); - } - if (x10c_LOFF) - { - w.writeBytes((atInt8*)"LOFF", 4); - x10c_LOFF.write(w); - } - if (x110_LDIR) - { - w.writeBytes((atInt8*)"LDIR", 4); - x110_LDIR.write(w); - } - if (x114_LFOT) - { - w.writeBytes((atInt8*)"LFOT", 4); - x114_LFOT.write(w); - } - if (x118_LFOR) - { - w.writeBytes((atInt8*)"LFOR", 4); - x118_LFOR.write(w); - } - if (x11c_LSLA) - { - w.writeBytes((atInt8*)"LSLA", 4); - x11c_LSLA.write(w); - } - if (x10c_ADV1) - { - w.writeBytes((atInt8*)"ADV1", 4); - x10c_ADV1.write(w); - } - if (x110_ADV2) - { - w.writeBytes((atInt8*)"ADV2", 4); - x110_ADV2.write(w); - } - if (x114_ADV3) - { - w.writeBytes((atInt8*)"ADV3", 4); - x114_ADV3.write(w); - } - if (x118_ADV4) - { - w.writeBytes((atInt8*)"ADV4", 4); - x118_ADV4.write(w); - } - if (x11c_ADV5) - { - w.writeBytes((atInt8*)"ADV5", 4); - x11c_ADV5.write(w); - } - if (x120_ADV6) - { - w.writeBytes((atInt8*)"ADV6", 4); - x120_ADV6.write(w); - } - if (x124_ADV7) - { - w.writeBytes((atInt8*)"ADV7", 4); - x124_ADV7.write(w); - } - if (x128_ADV8) - { - w.writeBytes((atInt8*)"ADV8", 4); - x128_ADV8.write(w); - } - w.writeBytes("_END", 4); +void GPSM::_write(typename Write::StreamT& w) const { + w.writeBytes((atInt8*)"GPSM", 4); + if (x0_PSIV) { + w.writeBytes((atInt8*)"PSIV", 4); + x0_PSIV.write(w); + } + if (x4_PSVM) { + w.writeBytes((atInt8*)"PSVM", 4); + x4_PSVM.write(w); + } + if (x8_PSOV) { + w.writeBytes((atInt8*)"PSOV", 4); + x8_PSOV.write(w); + } + if (xc_PSLT) { + w.writeBytes((atInt8*)"PSLT", 4); + xc_PSLT.write(w); + } + if (x10_PSWT) { + w.writeBytes((atInt8*)"PSWT", 4); + x10_PSWT.write(w); + } + if (x14_PSTS) { + w.writeBytes((atInt8*)"PSTS", 4); + x14_PSTS.write(w); + } + if (x18_POFS) { + w.writeBytes((atInt8*)"POFS", 4); + x18_POFS.write(w); + } + if (x1c_SEED) { + w.writeBytes((atInt8*)"SEED", 4); + x1c_SEED.write(w); + } + if (x20_LENG) { + w.writeBytes((atInt8*)"LENG", 4); + x20_LENG.write(w); + } + if (x24_WIDT) { + w.writeBytes((atInt8*)"WIDT", 4); + x24_WIDT.write(w); + } + if (x28_MAXP) { + w.writeBytes((atInt8*)"MAXP", 4); + x28_MAXP.write(w); + } + if (x2c_GRTE) { + w.writeBytes((atInt8*)"GRTE", 4); + x2c_GRTE.write(w); + } + if (x30_COLR) { + w.writeBytes((atInt8*)"COLR", 4); + x30_COLR.write(w); + } + if (x34_LTME) { + w.writeBytes((atInt8*)"LTME", 4); + x34_LTME.write(w); + } + if (x38_ILOC) { + w.writeBytes((atInt8*)"ILOC", 4); + x38_ILOC.write(w); + } + if (x3c_IVEC) { + w.writeBytes((atInt8*)"IVEC", 4); + x3c_IVEC.write(w); + } + if (x40_EMTR) { + w.writeBytes((atInt8*)"EMTR", 4); + x40_EMTR.write(w); + } + if (x44_24_LINE) { + w.writeBytes((atInt8*)"LINECNST\x01", 9); + } + if (x44_25_FXLL) { + w.writeBytes((atInt8*)"FXLLCNST\x01", 9); + } + if (x44_26_AAPH) { + w.writeBytes((atInt8*)"AAPHCNST\x01", 9); + } + if (x44_27_ZBUF) { + w.writeBytes((atInt8*)"ZBUFCNST\x01", 9); + } + if (x44_28_SORT) { + w.writeBytes((atInt8*)"SORTCNST\x01", 9); + } + if (x44_29_LIT_) { + w.writeBytes((atInt8*)"LIT_CNST\x01", 9); + } + if (x44_30_MBLR) { + w.writeBytes((atInt8*)"MBLRCNST\x01", 9); + } + if (x44_31_PMAB) { + w.writeBytes((atInt8*)"PMABCNST\x01", 9); + } + if (x45_24_PMUS) { + w.writeBytes((atInt8*)"PMUSCNST\x01", 9); + } + if (!x45_25_PMOO) { + w.writeBytes((atInt8*)"PMOOCNST\x00", 9); + } + if (x45_26_VMD1) { + w.writeBytes((atInt8*)"VMD1CNST\x01", 9); + } + if (x45_27_VMD2) { + w.writeBytes((atInt8*)"VMD2CNST\x01", 9); + } + if (x45_28_VMD3) { + w.writeBytes((atInt8*)"VMD3CNST\x01", 9); + } + if (x45_29_VMD4) { + w.writeBytes((atInt8*)"VMD4CNST\x01", 9); + } + if (x45_30_CIND) { + w.writeBytes((atInt8*)"CINDCNST\x01", 9); + } + if (x45_31_OPTS) { + w.writeBytes((atInt8*)"OPTSCNST\x01", 9); + } + if (x30_30_ORNT) { + w.writeBytes((atInt8*)"ORNTCNST\x01", 9); + } + if (x30_31_RSOP) { + w.writeBytes((atInt8*)"RSOPCNST\x01", 9); + } + if (x48_MBSP) { + w.writeBytes((atInt8*)"MBSP", 4); + x48_MBSP.write(w); + } + if (x4c_SIZE) { + w.writeBytes((atInt8*)"SIZE", 4); + x4c_SIZE.write(w); + } + if (x50_ROTA) { + w.writeBytes((atInt8*)"ROTA", 4); + x50_ROTA.write(w); + } + if (x54_TEXR) { + w.writeBytes((atInt8*)"TEXR", 4); + x54_TEXR.write(w); + } + if (x58_TIND) { + w.writeBytes((atInt8*)"TIND", 4); + x58_TIND.write(w); + } + if (x5c_PMDL) { + w.writeBytes((atInt8*)"PMDL", 4); + x5c_PMDL.write(w); + } + if (x6c_PMOP) { + w.writeBytes((atInt8*)"PMOP", 4); + x6c_PMOP.write(w); + } + if (x70_PMRT) { + w.writeBytes((atInt8*)"PMRT", 4); + x70_PMRT.write(w); + } + if (x74_PMSC) { + w.writeBytes((atInt8*)"PMSC", 4); + x74_PMSC.write(w); + } + if (x78_PMCL) { + w.writeBytes((atInt8*)"PMCL", 4); + x78_PMCL.write(w); + } + if (x7c_VEL1) { + w.writeBytes((atInt8*)"VEL1", 4); + x7c_VEL1.write(w); + } + if (x80_VEL2) { + w.writeBytes((atInt8*)"VEL2", 4); + x80_VEL2.write(w); + } + if (x84_VEL3) { + w.writeBytes((atInt8*)"VEL3", 4); + x84_VEL3.write(w); + } + if (x88_VEL4) { + w.writeBytes((atInt8*)"VEL4", 4); + x88_VEL4.write(w); + } + if (x8c_ICTS) { + w.writeBytes((atInt8*)"ICTS", 4); + x8c_ICTS.write(w); + } + if (x9c_NCSY) { + w.writeBytes((atInt8*)"NCSY", 4); + x9c_NCSY.write(w); + } + if (xa0_CSSD) { + w.writeBytes((atInt8*)"CSSD", 4); + xa0_CSSD.write(w); + } + if (xa4_IDTS) { + w.writeBytes((atInt8*)"IDTS", 4); + xa4_IDTS.write(w); + } + if (xb4_NDSY) { + w.writeBytes((atInt8*)"NDSY", 4); + xb4_NDSY.write(w); + } + if (xb8_IITS) { + w.writeBytes((atInt8*)"IITS", 4); + xb8_IITS.write(w); + } + if (xc8_PISY) { + w.writeBytes((atInt8*)"PISY", 4); + xc8_PISY.write(w); + } + if (xcc_SISY) { + w.writeBytes((atInt8*)"SISY", 4); + xcc_SISY.write(w); + } + if (xd0_KSSM) { + w.writeBytes((atInt8*)"KSSM", 4); + xd0_KSSM.write(w); + } + if (xd4_SSWH) { + w.writeBytes((atInt8*)"SSWH", 4); + xd4_SSWH.write(w); + } + if (xd8_SELC) { + w.writeBytes((atInt8*)"SELC", 4); + xd8_SELC.write(w); + } + if (xe4_SSSD) { + w.writeBytes((atInt8*)"SSSD", 4); + xe4_SSSD.write(w); + } + if (xe8_SSPO) { + w.writeBytes((atInt8*)"SSPO", 4); + xe8_SSPO.write(w); + } + if (xf8_SESD) { + w.writeBytes((atInt8*)"SESD", 4); + xf8_SESD.write(w); + } + if (xfc_SEPO) { + w.writeBytes((atInt8*)"SEPO", 4); + xfc_SEPO.write(w); + } + if (xec_PMLC) { + w.writeBytes((atInt8*)"PMLC", 4); + xec_PMLC.write(w); + } + if (x100_LTYP) { + w.writeBytes((atInt8*)"LTYP", 4); + x100_LTYP.write(w); + } + if (x104_LCLR) { + w.writeBytes((atInt8*)"LCLR", 4); + x104_LCLR.write(w); + } + if (x108_LINT) { + w.writeBytes((atInt8*)"LINT", 4); + x108_LINT.write(w); + } + if (x10c_LOFF) { + w.writeBytes((atInt8*)"LOFF", 4); + x10c_LOFF.write(w); + } + if (x110_LDIR) { + w.writeBytes((atInt8*)"LDIR", 4); + x110_LDIR.write(w); + } + if (x114_LFOT) { + w.writeBytes((atInt8*)"LFOT", 4); + x114_LFOT.write(w); + } + if (x118_LFOR) { + w.writeBytes((atInt8*)"LFOR", 4); + x118_LFOR.write(w); + } + if (x11c_LSLA) { + w.writeBytes((atInt8*)"LSLA", 4); + x11c_LSLA.write(w); + } + if (x10c_ADV1) { + w.writeBytes((atInt8*)"ADV1", 4); + x10c_ADV1.write(w); + } + if (x110_ADV2) { + w.writeBytes((atInt8*)"ADV2", 4); + x110_ADV2.write(w); + } + if (x114_ADV3) { + w.writeBytes((atInt8*)"ADV3", 4); + x114_ADV3.write(w); + } + if (x118_ADV4) { + w.writeBytes((atInt8*)"ADV4", 4); + x118_ADV4.write(w); + } + if (x11c_ADV5) { + w.writeBytes((atInt8*)"ADV5", 4); + x11c_ADV5.write(w); + } + if (x120_ADV6) { + w.writeBytes((atInt8*)"ADV6", 4); + x120_ADV6.write(w); + } + if (x124_ADV7) { + w.writeBytes((atInt8*)"ADV7", 4); + x124_ADV7.write(w); + } + if (x128_ADV8) { + w.writeBytes((atInt8*)"ADV8", 4); + x128_ADV8.write(w); + } + w.writeBytes("_END", 4); } AT_SUBSPECIALIZE_DNA_YAML(GPSM) AT_SUBSPECIALIZE_DNA_YAML(GPSM) template -void GPSM::gatherDependencies(std::vector& pathsOut) const -{ - if (x54_TEXR.m_elem) - x54_TEXR.m_elem->gatherDependencies(pathsOut); - if (x58_TIND.m_elem) - x58_TIND.m_elem->gatherDependencies(pathsOut); - g_curSpec->flattenDependencies(x5c_PMDL.id, pathsOut); - g_curSpec->flattenDependencies(x8c_ICTS.id, pathsOut); - g_curSpec->flattenDependencies(xa4_IDTS.id, pathsOut); - g_curSpec->flattenDependencies(xb8_IITS.id, pathsOut); - xd0_KSSM.gatherDependencies(pathsOut); - g_curSpec->flattenDependencies(xd4_SSWH.id, pathsOut); - g_curSpec->flattenDependencies(xec_PMLC.id, pathsOut); - g_curSpec->flattenDependencies(xd8_SELC.id, pathsOut); +void GPSM::gatherDependencies(std::vector& pathsOut) const { + if (x54_TEXR.m_elem) + x54_TEXR.m_elem->gatherDependencies(pathsOut); + if (x58_TIND.m_elem) + x58_TIND.m_elem->gatherDependencies(pathsOut); + g_curSpec->flattenDependencies(x5c_PMDL.id, pathsOut); + g_curSpec->flattenDependencies(x8c_ICTS.id, pathsOut); + g_curSpec->flattenDependencies(xa4_IDTS.id, pathsOut); + g_curSpec->flattenDependencies(xb8_IITS.id, pathsOut); + xd0_KSSM.gatherDependencies(pathsOut); + g_curSpec->flattenDependencies(xd4_SSWH.id, pathsOut); + g_curSpec->flattenDependencies(xec_PMLC.id, pathsOut); + g_curSpec->flattenDependencies(xd8_SELC.id, pathsOut); } template struct GPSM; template struct GPSM; template -bool ExtractGPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - GPSM gpsm; - gpsm.read(rs); - athena::io::ToYAMLStream(gpsm, writer); - return true; - } - return false; +bool ExtractGPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + GPSM gpsm; + gpsm.read(rs); + athena::io::ToYAMLStream(gpsm, writer); + return true; + } + return false; } template bool ExtractGPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractGPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template -bool WriteGPSM(const GPSM& gpsm, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - gpsm.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; +bool WriteGPSM(const GPSM& gpsm, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + gpsm.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } template bool WriteGPSM(const GPSM& gpsm, const hecl::ProjectPath& outPath); template bool WriteGPSM(const GPSM& gpsm, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/PART.hpp b/DataSpec/DNACommon/PART.hpp index 9d0da1c5c..9f2c445cc 100644 --- a/DataSpec/DNACommon/PART.hpp +++ b/DataSpec/DNACommon/PART.hpp @@ -4,106 +4,109 @@ #include "PAK.hpp" #include "athena/FileWriter.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template -struct GPSM : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA - VectorElementFactory x0_PSIV; - ModVectorElementFactory x4_PSVM; - VectorElementFactory x8_PSOV; - IntElementFactory xc_PSLT; - IntElementFactory x10_PSWT; - RealElementFactory x14_PSTS; - VectorElementFactory x18_POFS; - IntElementFactory x1c_SEED; - RealElementFactory x20_LENG; - RealElementFactory x24_WIDT; - IntElementFactory x28_MAXP; - RealElementFactory x2c_GRTE; - ColorElementFactory x30_COLR; - IntElementFactory x34_LTME; - VectorElementFactory x38_ILOC; - VectorElementFactory x3c_IVEC; - EmitterElementFactory x40_EMTR; - union - { - struct - { - bool x44_28_SORT : 1; bool x44_30_MBLR : 1; bool x44_24_LINE : 1; bool x44_29_LIT_ : 1; - bool x44_26_AAPH : 1; bool x44_27_ZBUF : 1; bool x44_25_FXLL : 1; bool x44_31_PMAB : 1; - bool x45_29_VMD4 : 1; bool x45_28_VMD3 : 1; bool x45_27_VMD2 : 1; bool x45_26_VMD1 : 1; - bool x45_31_OPTS : 1; bool x45_24_PMUS : 1; bool x45_25_PMOO : 1; bool x45_30_CIND : 1; - }; - uint16_t dummy1 = 0; +struct GPSM : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + VectorElementFactory x0_PSIV; + ModVectorElementFactory x4_PSVM; + VectorElementFactory x8_PSOV; + IntElementFactory xc_PSLT; + IntElementFactory x10_PSWT; + RealElementFactory x14_PSTS; + VectorElementFactory x18_POFS; + IntElementFactory x1c_SEED; + RealElementFactory x20_LENG; + RealElementFactory x24_WIDT; + IntElementFactory x28_MAXP; + RealElementFactory x2c_GRTE; + ColorElementFactory x30_COLR; + IntElementFactory x34_LTME; + VectorElementFactory x38_ILOC; + VectorElementFactory x3c_IVEC; + EmitterElementFactory x40_EMTR; + union { + struct { + bool x44_28_SORT : 1; + bool x44_30_MBLR : 1; + bool x44_24_LINE : 1; + bool x44_29_LIT_ : 1; + bool x44_26_AAPH : 1; + bool x44_27_ZBUF : 1; + bool x44_25_FXLL : 1; + bool x44_31_PMAB : 1; + bool x45_29_VMD4 : 1; + bool x45_28_VMD3 : 1; + bool x45_27_VMD2 : 1; + bool x45_26_VMD1 : 1; + bool x45_31_OPTS : 1; + bool x45_24_PMUS : 1; + bool x45_25_PMOO : 1; + bool x45_30_CIND : 1; }; - IntElementFactory x48_MBSP; - RealElementFactory x4c_SIZE; - RealElementFactory x50_ROTA; - UVElementFactory x54_TEXR; - UVElementFactory x58_TIND; - ChildResourceFactory x5c_PMDL; - VectorElementFactory x6c_PMOP; - VectorElementFactory x70_PMRT; - VectorElementFactory x74_PMSC; - ColorElementFactory x78_PMCL; - ModVectorElementFactory x7c_VEL1; - ModVectorElementFactory x80_VEL2; - ModVectorElementFactory x84_VEL3; - ModVectorElementFactory x88_VEL4; - ChildResourceFactory x8c_ICTS; - IntElementFactory x9c_NCSY; - IntElementFactory xa0_CSSD; - ChildResourceFactory xa4_IDTS; - IntElementFactory xb4_NDSY; - ChildResourceFactory xb8_IITS; - IntElementFactory xc8_PISY; - IntElementFactory xcc_SISY; - SpawnSystemKeyframeData xd0_KSSM; - ChildResourceFactory xd4_SSWH; - IntElementFactory xe4_SSSD; - VectorElementFactory xe8_SSPO; - IntElementFactory xf8_SESD; - VectorElementFactory xfc_SEPO; - ChildResourceFactory xec_PMLC; - IntElementFactory x100_LTYP; - ColorElementFactory x104_LCLR; - RealElementFactory x108_LINT; - VectorElementFactory x10c_LOFF; - VectorElementFactory x110_LDIR; - IntElementFactory x114_LFOT; - RealElementFactory x118_LFOR; - RealElementFactory x11c_LSLA; + uint16_t dummy1 = 0; + }; + IntElementFactory x48_MBSP; + RealElementFactory x4c_SIZE; + RealElementFactory x50_ROTA; + UVElementFactory x54_TEXR; + UVElementFactory x58_TIND; + ChildResourceFactory x5c_PMDL; + VectorElementFactory x6c_PMOP; + VectorElementFactory x70_PMRT; + VectorElementFactory x74_PMSC; + ColorElementFactory x78_PMCL; + ModVectorElementFactory x7c_VEL1; + ModVectorElementFactory x80_VEL2; + ModVectorElementFactory x84_VEL3; + ModVectorElementFactory x88_VEL4; + ChildResourceFactory x8c_ICTS; + IntElementFactory x9c_NCSY; + IntElementFactory xa0_CSSD; + ChildResourceFactory xa4_IDTS; + IntElementFactory xb4_NDSY; + ChildResourceFactory xb8_IITS; + IntElementFactory xc8_PISY; + IntElementFactory xcc_SISY; + SpawnSystemKeyframeData xd0_KSSM; + ChildResourceFactory xd4_SSWH; + IntElementFactory xe4_SSSD; + VectorElementFactory xe8_SSPO; + IntElementFactory xf8_SESD; + VectorElementFactory xfc_SEPO; + ChildResourceFactory xec_PMLC; + IntElementFactory x100_LTYP; + ColorElementFactory x104_LCLR; + RealElementFactory x108_LINT; + VectorElementFactory x10c_LOFF; + VectorElementFactory x110_LDIR; + IntElementFactory x114_LFOT; + RealElementFactory x118_LFOR; + RealElementFactory x11c_LSLA; - /* 0-00 additions */ - ChildResourceFactory xd8_SELC; - union - { - struct - { - bool x30_30_ORNT : 1; - bool x30_31_RSOP : 1; - }; - uint16_t dummy2 = 0; + /* 0-00 additions */ + ChildResourceFactory xd8_SELC; + union { + struct { + bool x30_30_ORNT : 1; + bool x30_31_RSOP : 1; }; - RealElementFactory x10c_ADV1; - RealElementFactory x110_ADV2; - RealElementFactory x114_ADV3; - RealElementFactory x118_ADV4; - RealElementFactory x11c_ADV5; - RealElementFactory x120_ADV6; - RealElementFactory x124_ADV7; - RealElementFactory x128_ADV8; + uint16_t dummy2 = 0; + }; + RealElementFactory x10c_ADV1; + RealElementFactory x110_ADV2; + RealElementFactory x114_ADV3; + RealElementFactory x118_ADV4; + RealElementFactory x11c_ADV5; + RealElementFactory x120_ADV6; + RealElementFactory x124_ADV7; + RealElementFactory x128_ADV8; - GPSM() - { - x45_25_PMOO = true; - } + GPSM() { x45_25_PMOO = true; } - void gatherDependencies(std::vector&) const; + void gatherDependencies(std::vector&) const; }; template @@ -112,5 +115,4 @@ bool ExtractGPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteGPSM(const GPSM& gpsm, const hecl::ProjectPath& outPath); -} - +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/ParticleCommon.cpp b/DataSpec/DNACommon/ParticleCommon.cpp index 8903bc7d8..96fd9af53 100644 --- a/DataSpec/DNACommon/ParticleCommon.cpp +++ b/DataSpec/DNACommon/ParticleCommon.cpp @@ -1,1267 +1,1163 @@ #include "ParticleCommon.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { logvisor::Module LogModule("urde::DNAParticle"); template <> -void REConstant::Enumerate(typename ReadYaml::StreamT& r) -{ - val = r.readFloat(nullptr); +void REConstant::Enumerate(typename ReadYaml::StreamT& r) { + val = r.readFloat(nullptr); } template <> -void REConstant::Enumerate(typename WriteYaml::StreamT& w) -{ - w.writeFloat(nullptr, val); +void REConstant::Enumerate(typename WriteYaml::StreamT& w) { + w.writeFloat(nullptr, val); } template <> -void REConstant::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; +void REConstant::Enumerate(typename BinarySize::StreamT& s) { + s += 4; } template <> -void REConstant::Enumerate(typename Read::StreamT& r) -{ - val = r.readFloatBig(); +void REConstant::Enumerate(typename Read::StreamT& r) { + val = r.readFloatBig(); } template <> -void REConstant::Enumerate(typename Write::StreamT& w) -{ - w.writeFloatBig(val); +void REConstant::Enumerate(typename Write::StreamT& w) { + w.writeFloatBig(val); } template <> -void IEConstant::Enumerate(typename ReadYaml::StreamT& r) -{ - val = r.readUint32(nullptr); +void IEConstant::Enumerate(typename ReadYaml::StreamT& r) { + val = r.readUint32(nullptr); } template <> -void IEConstant::Enumerate(typename WriteYaml::StreamT& w) -{ - w.writeUint32(nullptr, val); +void IEConstant::Enumerate(typename WriteYaml::StreamT& w) { + w.writeUint32(nullptr, val); } template <> -void IEConstant::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; +void IEConstant::Enumerate(typename BinarySize::StreamT& s) { + s += 4; } template <> -void IEConstant::Enumerate(typename Read::StreamT& r) -{ - val = r.readUint32Big(); +void IEConstant::Enumerate(typename Read::StreamT& r) { + val = r.readUint32Big(); } template <> -void IEConstant::Enumerate(typename Write::StreamT& w) -{ - w.writeUint32Big(val); +void IEConstant::Enumerate(typename Write::StreamT& w) { + w.writeUint32Big(val); } template <> -void VEConstant::Enumerate(typename ReadYaml::StreamT& r) -{ - size_t elemCount; - if (auto v = r.enterSubVector(nullptr, elemCount)) - { - for (int i=0 ; i<3 && i(typename ReadYaml::StreamT& r) { + size_t elemCount; + if (auto v = r.enterSubVector(nullptr, elemCount)) { + for (int i = 0; i < 3 && i < elemCount; ++i) { + if (auto rec = r.enterSubRecord(nullptr)) + comps[i].read(r); } + } } template <> -void VEConstant::Enumerate(typename WriteYaml::StreamT& w) -{ - if (auto v = w.enterSubVector(nullptr)) - for (int i=0 ; i<3 ; ++i) - if (auto rec = w.enterSubRecord(nullptr)) - comps[i].write(w); +void VEConstant::Enumerate(typename WriteYaml::StreamT& w) { + if (auto v = w.enterSubVector(nullptr)) + for (int i = 0; i < 3; ++i) + if (auto rec = w.enterSubRecord(nullptr)) + comps[i].write(w); } template <> -void VEConstant::Enumerate(typename BinarySize::StreamT& s) -{ - comps[0].binarySize(s); - comps[1].binarySize(s); - comps[2].binarySize(s); +void VEConstant::Enumerate(typename BinarySize::StreamT& s) { + comps[0].binarySize(s); + comps[1].binarySize(s); + comps[2].binarySize(s); } template <> -void VEConstant::Enumerate(typename Read::StreamT& r) -{ - comps[0].read(r); - comps[1].read(r); - comps[2].read(r); +void VEConstant::Enumerate(typename Read::StreamT& r) { + comps[0].read(r); + comps[1].read(r); + comps[2].read(r); } template <> -void VEConstant::Enumerate(typename Write::StreamT& w) -{ - comps[0].write(w); - comps[1].write(w); - comps[2].write(w); +void VEConstant::Enumerate(typename Write::StreamT& w) { + comps[0].write(w); + comps[1].write(w); + comps[2].write(w); } template <> -void CEConstant::Enumerate(typename ReadYaml::StreamT& r) -{ - for (int i=0 ; i<4 ; ++i) - if (auto rec = r.enterSubRecord(nullptr)) - comps[i].read(r); +void CEConstant::Enumerate(typename ReadYaml::StreamT& r) { + for (int i = 0; i < 4; ++i) + if (auto rec = r.enterSubRecord(nullptr)) + comps[i].read(r); } template <> -void CEConstant::Enumerate(typename WriteYaml::StreamT& w) -{ - if (auto v = w.enterSubVector(nullptr)) - for (int i=0 ; i<4 ; ++i) - if (auto rec = w.enterSubRecord(nullptr)) - comps[i].write(w); +void CEConstant::Enumerate(typename WriteYaml::StreamT& w) { + if (auto v = w.enterSubVector(nullptr)) + for (int i = 0; i < 4; ++i) + if (auto rec = w.enterSubRecord(nullptr)) + comps[i].write(w); } template <> -void CEConstant::Enumerate(typename BinarySize::StreamT& s) -{ - comps[0].binarySize(s); - comps[1].binarySize(s); - comps[2].binarySize(s); - comps[3].binarySize(s); +void CEConstant::Enumerate(typename BinarySize::StreamT& s) { + comps[0].binarySize(s); + comps[1].binarySize(s); + comps[2].binarySize(s); + comps[3].binarySize(s); } template <> -void CEConstant::Enumerate(typename Read::StreamT& r) -{ - comps[0].read(r); - comps[1].read(r); - comps[2].read(r); - comps[3].read(r); +void CEConstant::Enumerate(typename Read::StreamT& r) { + comps[0].read(r); + comps[1].read(r); + comps[2].read(r); + comps[3].read(r); } template <> -void CEConstant::Enumerate(typename Write::StreamT& w) -{ - comps[0].write(w); - comps[1].write(w); - comps[2].write(w); - comps[3].write(w); +void CEConstant::Enumerate(typename Write::StreamT& w) { + comps[0].write(w); + comps[1].write(w); + comps[2].write(w); + comps[3].write(w); } template <> -void MVEConstant::Enumerate(typename ReadYaml::StreamT& r) -{ - for (int i=0 ; i<3 ; ++i) - if (auto rec = r.enterSubRecord(nullptr)) - comps[i].read(r); +void MVEConstant::Enumerate(typename ReadYaml::StreamT& r) { + for (int i = 0; i < 3; ++i) + if (auto rec = r.enterSubRecord(nullptr)) + comps[i].read(r); } template <> -void MVEConstant::Enumerate(typename WriteYaml::StreamT& w) -{ - if (auto v = w.enterSubVector(nullptr)) - for (int i=0 ; i<3 ; ++i) - if (auto rec = w.enterSubRecord(nullptr)) - comps[i].write(w); +void MVEConstant::Enumerate(typename WriteYaml::StreamT& w) { + if (auto v = w.enterSubVector(nullptr)) + for (int i = 0; i < 3; ++i) + if (auto rec = w.enterSubRecord(nullptr)) + comps[i].write(w); } template <> -void MVEConstant::Enumerate(typename BinarySize::StreamT& s) -{ - comps[0].binarySize(s); - comps[1].binarySize(s); - comps[2].binarySize(s); +void MVEConstant::Enumerate(typename BinarySize::StreamT& s) { + comps[0].binarySize(s); + comps[1].binarySize(s); + comps[2].binarySize(s); } template <> -void MVEConstant::Enumerate(typename Read::StreamT& r) -{ - comps[0].read(r); - comps[1].read(r); - comps[2].read(r); +void MVEConstant::Enumerate(typename Read::StreamT& r) { + comps[0].read(r); + comps[1].read(r); + comps[2].read(r); } template <> -void MVEConstant::Enumerate(typename Write::StreamT& w) -{ - comps[0].write(w); - comps[1].write(w); - comps[2].write(w); +void MVEConstant::Enumerate(typename Write::StreamT& w) { + comps[0].write(w); + comps[1].write(w); + comps[2].write(w); } template <> -void RealElementFactory::Enumerate(typename ReadYaml::StreamT& r) -{ - const auto& mapChildren = r.getCurNode()->m_mapChildren; - if (mapChildren.empty()) - { - m_elem.reset(); - return; - } +void RealElementFactory::Enumerate(typename ReadYaml::StreamT& r) { + const auto& mapChildren = r.getCurNode()->m_mapChildren; + if (mapChildren.empty()) { + m_elem.reset(); + return; + } - const auto& elem = mapChildren[0]; - if (elem.first.size() < 4) - LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); + const auto& elem = mapChildren[0]; + if (elem.first.size() < 4) + LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('LFTW'): - m_elem.reset(new struct RELifetimeTween); - break; - case SBIG('CNST'): - m_elem.reset(new struct REConstant); - break; - case SBIG('CHAN'): - m_elem.reset(new struct RETimeChain); - break; - case SBIG('ADD_'): - m_elem.reset(new struct REAdd); - break; - case SBIG('CLMP'): - m_elem.reset(new struct REClamp); - break; - case SBIG('KEYE'): - case SBIG('KEYP'): - m_elem.reset(new struct REKeyframeEmitter); - break; - case SBIG('IRND'): - m_elem.reset(new struct REInitialRandom); - break; - case SBIG('RAND'): - m_elem.reset(new struct RERandom); - break; - case SBIG('MULT'): - m_elem.reset(new struct REMultiply); - break; - case SBIG('PULS'): - m_elem.reset(new struct REPulse); - break; - case SBIG('SCAL'): - m_elem.reset(new struct RETimeScale); - break; - case SBIG('RLPT'): - m_elem.reset(new struct RELifetimePercent); - break; - case SBIG('SINE'): - m_elem.reset(new struct RESineWave); - break; - case SBIG('ISWT'): - m_elem.reset(new struct REInitialSwitch); - break; - case SBIG('CLTN'): - m_elem.reset(new struct RECompareLessThan); - break; - case SBIG('CEQL'): - m_elem.reset(new struct RECompareEquals); - break; - case SBIG('PAP1'): - m_elem.reset(new struct REParticleAdvanceParam1); - break; - case SBIG('PAP2'): - m_elem.reset(new struct REParticleAdvanceParam2); - break; - case SBIG('PAP3'): - m_elem.reset(new struct REParticleAdvanceParam3); - break; - case SBIG('PAP4'): - m_elem.reset(new struct REParticleAdvanceParam4); - break; - case SBIG('PAP5'): - m_elem.reset(new struct REParticleAdvanceParam5); - break; - case SBIG('PAP6'): - m_elem.reset(new struct REParticleAdvanceParam6); - break; - case SBIG('PAP7'): - m_elem.reset(new struct REParticleAdvanceParam7); - break; - case SBIG('PAP8'): - m_elem.reset(new struct REParticleAdvanceParam8); - break; - case SBIG('PSLL'): - m_elem.reset(new struct REParticleSizeOrLineLength); - break; - case SBIG('PRLW'): - m_elem.reset(new struct REParticleRotationOrLineWidth); - break; - case SBIG('SUB_'): - m_elem.reset(new struct RESubtract); - break; - case SBIG('VMAG'): - m_elem.reset(new struct REVectorMagnitude); - break; - case SBIG('VXTR'): - m_elem.reset(new struct REVectorXToReal); - break; - case SBIG('VYTR'): - m_elem.reset(new struct REVectorYToReal); - break; - case SBIG('VZTR'): - m_elem.reset(new struct REVectorZToReal); - break; - case SBIG('CEXT'): - m_elem.reset(new struct RECEXT); - break; - case SBIG('ITRL'): - m_elem.reset(new struct REIntTimesReal); - break; - default: - m_elem.reset(); - return; - } - if (auto rec = r.enterSubRecord(elem.first.c_str())) - m_elem->read(r); -} - -template <> -void RealElementFactory::Enumerate(typename WriteYaml::StreamT& w) -{ - if (m_elem) - if (auto rec = w.enterSubRecord(m_elem->ClassID())) - m_elem->write(w); -} - -template <> -void RealElementFactory::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - if (m_elem) - m_elem->binarySize(s); -} - -template <> -void RealElementFactory::Enumerate(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - switch (clsId) - { - case SBIG('LFTW'): - m_elem.reset(new struct RELifetimeTween); - break; - case SBIG('CNST'): - m_elem.reset(new struct REConstant); - break; - case SBIG('CHAN'): - m_elem.reset(new struct RETimeChain); - break; - case SBIG('ADD_'): - m_elem.reset(new struct REAdd); - break; - case SBIG('CLMP'): - m_elem.reset(new struct REClamp); - break; - case SBIG('KEYE'): - case SBIG('KEYP'): - m_elem.reset(new struct REKeyframeEmitter); - break; - case SBIG('IRND'): - m_elem.reset(new struct REInitialRandom); - break; - case SBIG('RAND'): - m_elem.reset(new struct RERandom); - break; - case SBIG('MULT'): - m_elem.reset(new struct REMultiply); - break; - case SBIG('PULS'): - m_elem.reset(new struct REPulse); - break; - case SBIG('SCAL'): - m_elem.reset(new struct RETimeScale); - break; - case SBIG('RLPT'): - m_elem.reset(new struct RELifetimePercent); - break; - case SBIG('SINE'): - m_elem.reset(new struct RESineWave); - break; - case SBIG('ISWT'): - m_elem.reset(new struct REInitialSwitch); - break; - case SBIG('CLTN'): - m_elem.reset(new struct RECompareLessThan); - break; - case SBIG('CEQL'): - m_elem.reset(new struct RECompareEquals); - break; - case SBIG('PAP1'): - m_elem.reset(new struct REParticleAdvanceParam1); - break; - case SBIG('PAP2'): - m_elem.reset(new struct REParticleAdvanceParam2); - break; - case SBIG('PAP3'): - m_elem.reset(new struct REParticleAdvanceParam3); - break; - case SBIG('PAP4'): - m_elem.reset(new struct REParticleAdvanceParam4); - break; - case SBIG('PAP5'): - m_elem.reset(new struct REParticleAdvanceParam5); - break; - case SBIG('PAP6'): - m_elem.reset(new struct REParticleAdvanceParam6); - break; - case SBIG('PAP7'): - m_elem.reset(new struct REParticleAdvanceParam7); - break; - case SBIG('PAP8'): - m_elem.reset(new struct REParticleAdvanceParam8); - break; - case SBIG('PSLL'): - m_elem.reset(new struct REParticleSizeOrLineLength); - break; - case SBIG('PRLW'): - m_elem.reset(new struct REParticleRotationOrLineWidth); - break; - case SBIG('SUB_'): - m_elem.reset(new struct RESubtract); - break; - case SBIG('VMAG'): - m_elem.reset(new struct REVectorMagnitude); - break; - case SBIG('VXTR'): - m_elem.reset(new struct REVectorXToReal); - break; - case SBIG('VYTR'): - m_elem.reset(new struct REVectorYToReal); - break; - case SBIG('VZTR'): - m_elem.reset(new struct REVectorZToReal); - break; - case SBIG('CEXT'): - m_elem.reset(new struct RECEXT); - break; - case SBIG('ITRL'): - m_elem.reset(new struct REIntTimesReal); - break; - case SBIG('NONE'): - m_elem.reset(); - return; - default: - m_elem.reset(); - LogModule.report(logvisor::Fatal, "Unknown RealElement class %.4s @%" PRIi64, &clsId, r.position()); - return; - } + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('LFTW'): + m_elem.reset(new struct RELifetimeTween); + break; + case SBIG('CNST'): + m_elem.reset(new struct REConstant); + break; + case SBIG('CHAN'): + m_elem.reset(new struct RETimeChain); + break; + case SBIG('ADD_'): + m_elem.reset(new struct REAdd); + break; + case SBIG('CLMP'): + m_elem.reset(new struct REClamp); + break; + case SBIG('KEYE'): + case SBIG('KEYP'): + m_elem.reset(new struct REKeyframeEmitter); + break; + case SBIG('IRND'): + m_elem.reset(new struct REInitialRandom); + break; + case SBIG('RAND'): + m_elem.reset(new struct RERandom); + break; + case SBIG('MULT'): + m_elem.reset(new struct REMultiply); + break; + case SBIG('PULS'): + m_elem.reset(new struct REPulse); + break; + case SBIG('SCAL'): + m_elem.reset(new struct RETimeScale); + break; + case SBIG('RLPT'): + m_elem.reset(new struct RELifetimePercent); + break; + case SBIG('SINE'): + m_elem.reset(new struct RESineWave); + break; + case SBIG('ISWT'): + m_elem.reset(new struct REInitialSwitch); + break; + case SBIG('CLTN'): + m_elem.reset(new struct RECompareLessThan); + break; + case SBIG('CEQL'): + m_elem.reset(new struct RECompareEquals); + break; + case SBIG('PAP1'): + m_elem.reset(new struct REParticleAdvanceParam1); + break; + case SBIG('PAP2'): + m_elem.reset(new struct REParticleAdvanceParam2); + break; + case SBIG('PAP3'): + m_elem.reset(new struct REParticleAdvanceParam3); + break; + case SBIG('PAP4'): + m_elem.reset(new struct REParticleAdvanceParam4); + break; + case SBIG('PAP5'): + m_elem.reset(new struct REParticleAdvanceParam5); + break; + case SBIG('PAP6'): + m_elem.reset(new struct REParticleAdvanceParam6); + break; + case SBIG('PAP7'): + m_elem.reset(new struct REParticleAdvanceParam7); + break; + case SBIG('PAP8'): + m_elem.reset(new struct REParticleAdvanceParam8); + break; + case SBIG('PSLL'): + m_elem.reset(new struct REParticleSizeOrLineLength); + break; + case SBIG('PRLW'): + m_elem.reset(new struct REParticleRotationOrLineWidth); + break; + case SBIG('SUB_'): + m_elem.reset(new struct RESubtract); + break; + case SBIG('VMAG'): + m_elem.reset(new struct REVectorMagnitude); + break; + case SBIG('VXTR'): + m_elem.reset(new struct REVectorXToReal); + break; + case SBIG('VYTR'): + m_elem.reset(new struct REVectorYToReal); + break; + case SBIG('VZTR'): + m_elem.reset(new struct REVectorZToReal); + break; + case SBIG('CEXT'): + m_elem.reset(new struct RECEXT); + break; + case SBIG('ITRL'): + m_elem.reset(new struct REIntTimesReal); + break; + default: + m_elem.reset(); + return; + } + if (auto rec = r.enterSubRecord(elem.first.c_str())) m_elem->read(r); } template <> -void RealElementFactory::Enumerate(typename Write::StreamT& w) -{ - if (m_elem) - { - w.writeBytes((atInt8*)m_elem->ClassID(), 4); - m_elem->write(w); - } - else - w.writeBytes((atInt8*)"NONE", 4); -} - - -template <> -void IntElementFactory::Enumerate(typename ReadYaml::StreamT& r) -{ - const auto& mapChildren = r.getCurNode()->m_mapChildren; - if (mapChildren.empty()) - { - m_elem.reset(); - return; - } - - const auto& elem = mapChildren[0]; - if (elem.first.size() < 4) - LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); - - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('KEYE'): - case SBIG('KEYP'): - m_elem.reset(new struct IEKeyframeEmitter); - break; - case SBIG('DETH'): - m_elem.reset(new struct IEDeath); - break; - case SBIG('CLMP'): - m_elem.reset(new struct IEClamp); - break; - case SBIG('CHAN'): - m_elem.reset(new struct IETimeChain); - break; - case SBIG('ADD_'): - m_elem.reset(new struct IEAdd); - break; - case SBIG('CNST'): - m_elem.reset(new struct IEConstant); - break; - case SBIG('IMPL'): - m_elem.reset(new struct IEImpulse); - break; - case SBIG('ILPT'): - m_elem.reset(new struct IELifetimePercent); - break; - case SBIG('IRND'): - m_elem.reset(new struct IEInitialRandom); - break; - case SBIG('PULS'): - m_elem.reset(new struct IEPulse); - break; - case SBIG('MULT'): - m_elem.reset(new struct IEMultiply); - break; - case SBIG('SPAH'): - m_elem.reset(new struct IESampleAndHold); - break; - case SBIG('RAND'): - m_elem.reset(new struct IERandom); - break; - case SBIG('TSCL'): - m_elem.reset(new struct IETimeScale); - break; - case SBIG('GTCP'): - m_elem.reset(new struct IEGTCP); - break; - case SBIG('MODU'): - m_elem.reset(new struct IEModulo); - break; - case SBIG('SUB_'): - m_elem.reset(new struct IESubtract); - break; - default: - m_elem.reset(); - return; - } - if (auto rec = r.enterSubRecord(elem.first.c_str())) - m_elem->read(r); +void RealElementFactory::Enumerate(typename WriteYaml::StreamT& w) { + if (m_elem) + if (auto rec = w.enterSubRecord(m_elem->ClassID())) + m_elem->write(w); } template <> -void IntElementFactory::Enumerate(typename WriteYaml::StreamT& w) -{ - if (m_elem) - if (auto rec = w.enterSubRecord(m_elem->ClassID())) - m_elem->write(w); +void RealElementFactory::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + if (m_elem) + m_elem->binarySize(s); } template <> -void IntElementFactory::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - if (m_elem) - m_elem->binarySize(s); +void RealElementFactory::Enumerate(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + switch (clsId) { + case SBIG('LFTW'): + m_elem.reset(new struct RELifetimeTween); + break; + case SBIG('CNST'): + m_elem.reset(new struct REConstant); + break; + case SBIG('CHAN'): + m_elem.reset(new struct RETimeChain); + break; + case SBIG('ADD_'): + m_elem.reset(new struct REAdd); + break; + case SBIG('CLMP'): + m_elem.reset(new struct REClamp); + break; + case SBIG('KEYE'): + case SBIG('KEYP'): + m_elem.reset(new struct REKeyframeEmitter); + break; + case SBIG('IRND'): + m_elem.reset(new struct REInitialRandom); + break; + case SBIG('RAND'): + m_elem.reset(new struct RERandom); + break; + case SBIG('MULT'): + m_elem.reset(new struct REMultiply); + break; + case SBIG('PULS'): + m_elem.reset(new struct REPulse); + break; + case SBIG('SCAL'): + m_elem.reset(new struct RETimeScale); + break; + case SBIG('RLPT'): + m_elem.reset(new struct RELifetimePercent); + break; + case SBIG('SINE'): + m_elem.reset(new struct RESineWave); + break; + case SBIG('ISWT'): + m_elem.reset(new struct REInitialSwitch); + break; + case SBIG('CLTN'): + m_elem.reset(new struct RECompareLessThan); + break; + case SBIG('CEQL'): + m_elem.reset(new struct RECompareEquals); + break; + case SBIG('PAP1'): + m_elem.reset(new struct REParticleAdvanceParam1); + break; + case SBIG('PAP2'): + m_elem.reset(new struct REParticleAdvanceParam2); + break; + case SBIG('PAP3'): + m_elem.reset(new struct REParticleAdvanceParam3); + break; + case SBIG('PAP4'): + m_elem.reset(new struct REParticleAdvanceParam4); + break; + case SBIG('PAP5'): + m_elem.reset(new struct REParticleAdvanceParam5); + break; + case SBIG('PAP6'): + m_elem.reset(new struct REParticleAdvanceParam6); + break; + case SBIG('PAP7'): + m_elem.reset(new struct REParticleAdvanceParam7); + break; + case SBIG('PAP8'): + m_elem.reset(new struct REParticleAdvanceParam8); + break; + case SBIG('PSLL'): + m_elem.reset(new struct REParticleSizeOrLineLength); + break; + case SBIG('PRLW'): + m_elem.reset(new struct REParticleRotationOrLineWidth); + break; + case SBIG('SUB_'): + m_elem.reset(new struct RESubtract); + break; + case SBIG('VMAG'): + m_elem.reset(new struct REVectorMagnitude); + break; + case SBIG('VXTR'): + m_elem.reset(new struct REVectorXToReal); + break; + case SBIG('VYTR'): + m_elem.reset(new struct REVectorYToReal); + break; + case SBIG('VZTR'): + m_elem.reset(new struct REVectorZToReal); + break; + case SBIG('CEXT'): + m_elem.reset(new struct RECEXT); + break; + case SBIG('ITRL'): + m_elem.reset(new struct REIntTimesReal); + break; + case SBIG('NONE'): + m_elem.reset(); + return; + default: + m_elem.reset(); + LogModule.report(logvisor::Fatal, "Unknown RealElement class %.4s @%" PRIi64, &clsId, r.position()); + return; + } + m_elem->read(r); } template <> -void IntElementFactory::Enumerate(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - switch (clsId) - { - case SBIG('KEYE'): - case SBIG('KEYP'): - m_elem.reset(new struct IEKeyframeEmitter); - break; - case SBIG('DETH'): - m_elem.reset(new struct IEDeath); - break; - case SBIG('CLMP'): - m_elem.reset(new struct IEClamp); - break; - case SBIG('CHAN'): - m_elem.reset(new struct IETimeChain); - break; - case SBIG('ADD_'): - m_elem.reset(new struct IEAdd); - break; - case SBIG('CNST'): - m_elem.reset(new struct IEConstant); - break; - case SBIG('IMPL'): - m_elem.reset(new struct IEImpulse); - break; - case SBIG('ILPT'): - m_elem.reset(new struct IELifetimePercent); - break; - case SBIG('IRND'): - m_elem.reset(new struct IEInitialRandom); - break; - case SBIG('PULS'): - m_elem.reset(new struct IEPulse); - break; - case SBIG('MULT'): - m_elem.reset(new struct IEMultiply); - break; - case SBIG('SPAH'): - m_elem.reset(new struct IESampleAndHold); - break; - case SBIG('RAND'): - m_elem.reset(new struct IERandom); - break; - case SBIG('TSCL'): - m_elem.reset(new struct IETimeScale); - break; - case SBIG('GTCP'): - m_elem.reset(new struct IEGTCP); - break; - case SBIG('MODU'): - m_elem.reset(new struct IEModulo); - break; - case SBIG('SUB_'): - m_elem.reset(new struct IESubtract); - break; - case SBIG('NONE'): - m_elem.reset(); - return; - default: - m_elem.reset(); - LogModule.report(logvisor::Fatal, "Unknown IntElement class %.4s @%" PRIi64, &clsId, r.position()); - return; - } +void RealElementFactory::Enumerate(typename Write::StreamT& w) { + if (m_elem) { + w.writeBytes((atInt8*)m_elem->ClassID(), 4); + m_elem->write(w); + } else + w.writeBytes((atInt8*)"NONE", 4); +} + +template <> +void IntElementFactory::Enumerate(typename ReadYaml::StreamT& r) { + const auto& mapChildren = r.getCurNode()->m_mapChildren; + if (mapChildren.empty()) { + m_elem.reset(); + return; + } + + const auto& elem = mapChildren[0]; + if (elem.first.size() < 4) + LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); + + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('KEYE'): + case SBIG('KEYP'): + m_elem.reset(new struct IEKeyframeEmitter); + break; + case SBIG('DETH'): + m_elem.reset(new struct IEDeath); + break; + case SBIG('CLMP'): + m_elem.reset(new struct IEClamp); + break; + case SBIG('CHAN'): + m_elem.reset(new struct IETimeChain); + break; + case SBIG('ADD_'): + m_elem.reset(new struct IEAdd); + break; + case SBIG('CNST'): + m_elem.reset(new struct IEConstant); + break; + case SBIG('IMPL'): + m_elem.reset(new struct IEImpulse); + break; + case SBIG('ILPT'): + m_elem.reset(new struct IELifetimePercent); + break; + case SBIG('IRND'): + m_elem.reset(new struct IEInitialRandom); + break; + case SBIG('PULS'): + m_elem.reset(new struct IEPulse); + break; + case SBIG('MULT'): + m_elem.reset(new struct IEMultiply); + break; + case SBIG('SPAH'): + m_elem.reset(new struct IESampleAndHold); + break; + case SBIG('RAND'): + m_elem.reset(new struct IERandom); + break; + case SBIG('TSCL'): + m_elem.reset(new struct IETimeScale); + break; + case SBIG('GTCP'): + m_elem.reset(new struct IEGTCP); + break; + case SBIG('MODU'): + m_elem.reset(new struct IEModulo); + break; + case SBIG('SUB_'): + m_elem.reset(new struct IESubtract); + break; + default: + m_elem.reset(); + return; + } + if (auto rec = r.enterSubRecord(elem.first.c_str())) m_elem->read(r); } template <> -void IntElementFactory::Enumerate(typename Write::StreamT& w) -{ - if (m_elem) - { - w.writeBytes((atInt8*)m_elem->ClassID(), 4); - m_elem->write(w); - } - else - w.writeBytes((atInt8*)"NONE", 4); +void IntElementFactory::Enumerate(typename WriteYaml::StreamT& w) { + if (m_elem) + if (auto rec = w.enterSubRecord(m_elem->ClassID())) + m_elem->write(w); } template <> -void VectorElementFactory::Enumerate(typename ReadYaml::StreamT& r) -{ - const auto& mapChildren = r.getCurNode()->m_mapChildren; - if (mapChildren.empty()) - { - m_elem.reset(); - return; - } - - const auto& elem = mapChildren[0]; - if (elem.first.size() < 4) - LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); - - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('CONE'): - m_elem.reset(new struct VECone); - break; - case SBIG('CHAN'): - m_elem.reset(new struct VETimeChain); - break; - case SBIG('ANGC'): - m_elem.reset(new struct VEAngleCone); - break; - case SBIG('ADD_'): - m_elem.reset(new struct VEAdd); - break; - case SBIG('CCLU'): - m_elem.reset(new struct VECircleCluster); - break; - case SBIG('CNST'): - m_elem.reset(new struct VEConstant); - break; - case SBIG('CIRC'): - m_elem.reset(new struct VECircle); - break; - case SBIG('KEYE'): - case SBIG('KEYP'): - m_elem.reset(new struct VEKeyframeEmitter); - break; - case SBIG('MULT'): - m_elem.reset(new struct VEMultiply); - break; - case SBIG('RTOV'): - m_elem.reset(new struct VERealToVector); - break; - case SBIG('PULS'): - m_elem.reset(new struct VEPulse); - break; - case SBIG('PVEL'): - m_elem.reset(new struct VEParticleVelocity); - break; - case SBIG('SPOS'): - m_elem.reset(new struct VESPOS); - break; - case SBIG('PLCO'): - m_elem.reset(new struct VEPLCO); - break; - case SBIG('PLOC'): - m_elem.reset(new struct VEPLOC); - break; - case SBIG('PSOR'): - m_elem.reset(new struct VEPSOR); - break; - case SBIG('PSOF'): - m_elem.reset(new struct VEPSOF); - break; - default: - m_elem.reset(); - return; - } - if (auto rec = r.enterSubRecord(elem.first.c_str())) - m_elem->read(r); +void IntElementFactory::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + if (m_elem) + m_elem->binarySize(s); } template <> -void VectorElementFactory::Enumerate(typename WriteYaml::StreamT& w) -{ - if (m_elem) - if (auto rec = w.enterSubRecord(m_elem->ClassID())) - m_elem->write(w); +void IntElementFactory::Enumerate(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + switch (clsId) { + case SBIG('KEYE'): + case SBIG('KEYP'): + m_elem.reset(new struct IEKeyframeEmitter); + break; + case SBIG('DETH'): + m_elem.reset(new struct IEDeath); + break; + case SBIG('CLMP'): + m_elem.reset(new struct IEClamp); + break; + case SBIG('CHAN'): + m_elem.reset(new struct IETimeChain); + break; + case SBIG('ADD_'): + m_elem.reset(new struct IEAdd); + break; + case SBIG('CNST'): + m_elem.reset(new struct IEConstant); + break; + case SBIG('IMPL'): + m_elem.reset(new struct IEImpulse); + break; + case SBIG('ILPT'): + m_elem.reset(new struct IELifetimePercent); + break; + case SBIG('IRND'): + m_elem.reset(new struct IEInitialRandom); + break; + case SBIG('PULS'): + m_elem.reset(new struct IEPulse); + break; + case SBIG('MULT'): + m_elem.reset(new struct IEMultiply); + break; + case SBIG('SPAH'): + m_elem.reset(new struct IESampleAndHold); + break; + case SBIG('RAND'): + m_elem.reset(new struct IERandom); + break; + case SBIG('TSCL'): + m_elem.reset(new struct IETimeScale); + break; + case SBIG('GTCP'): + m_elem.reset(new struct IEGTCP); + break; + case SBIG('MODU'): + m_elem.reset(new struct IEModulo); + break; + case SBIG('SUB_'): + m_elem.reset(new struct IESubtract); + break; + case SBIG('NONE'): + m_elem.reset(); + return; + default: + m_elem.reset(); + LogModule.report(logvisor::Fatal, "Unknown IntElement class %.4s @%" PRIi64, &clsId, r.position()); + return; + } + m_elem->read(r); } template <> -void VectorElementFactory::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - if (m_elem) - m_elem->binarySize(s); +void IntElementFactory::Enumerate(typename Write::StreamT& w) { + if (m_elem) { + w.writeBytes((atInt8*)m_elem->ClassID(), 4); + m_elem->write(w); + } else + w.writeBytes((atInt8*)"NONE", 4); } template <> -void VectorElementFactory::Enumerate(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - switch (clsId) - { - case SBIG('CONE'): - m_elem.reset(new struct VECone); - break; - case SBIG('CHAN'): - m_elem.reset(new struct VETimeChain); - break; - case SBIG('ANGC'): - m_elem.reset(new struct VEAngleCone); - break; - case SBIG('ADD_'): - m_elem.reset(new struct VEAdd); - break; - case SBIG('CCLU'): - m_elem.reset(new struct VECircleCluster); - break; - case SBIG('CNST'): - m_elem.reset(new struct VEConstant); - break; - case SBIG('CIRC'): - m_elem.reset(new struct VECircle); - break; - case SBIG('KEYE'): - case SBIG('KEYP'): - m_elem.reset(new struct VEKeyframeEmitter); - break; - case SBIG('MULT'): - m_elem.reset(new struct VEMultiply); - break; - case SBIG('RTOV'): - m_elem.reset(new struct VERealToVector); - break; - case SBIG('PULS'): - m_elem.reset(new struct VEPulse); - break; - case SBIG('PVEL'): - m_elem.reset(new struct VEParticleVelocity); - break; - case SBIG('SPOS'): - m_elem.reset(new struct VESPOS); - break; - case SBIG('PLCO'): - m_elem.reset(new struct VEPLCO); - break; - case SBIG('PLOC'): - m_elem.reset(new struct VEPLOC); - break; - case SBIG('PSOR'): - m_elem.reset(new struct VEPSOR); - break; - case SBIG('PSOF'): - m_elem.reset(new struct VEPSOF); - break; - case SBIG('NONE'): - m_elem.reset(); - return; - default: - m_elem.reset(); - LogModule.report(logvisor::Fatal, "Unknown VectorElement class %.4s @%" PRIi64, &clsId, r.position()); - return; - } +void VectorElementFactory::Enumerate(typename ReadYaml::StreamT& r) { + const auto& mapChildren = r.getCurNode()->m_mapChildren; + if (mapChildren.empty()) { + m_elem.reset(); + return; + } + + const auto& elem = mapChildren[0]; + if (elem.first.size() < 4) + LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); + + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('CONE'): + m_elem.reset(new struct VECone); + break; + case SBIG('CHAN'): + m_elem.reset(new struct VETimeChain); + break; + case SBIG('ANGC'): + m_elem.reset(new struct VEAngleCone); + break; + case SBIG('ADD_'): + m_elem.reset(new struct VEAdd); + break; + case SBIG('CCLU'): + m_elem.reset(new struct VECircleCluster); + break; + case SBIG('CNST'): + m_elem.reset(new struct VEConstant); + break; + case SBIG('CIRC'): + m_elem.reset(new struct VECircle); + break; + case SBIG('KEYE'): + case SBIG('KEYP'): + m_elem.reset(new struct VEKeyframeEmitter); + break; + case SBIG('MULT'): + m_elem.reset(new struct VEMultiply); + break; + case SBIG('RTOV'): + m_elem.reset(new struct VERealToVector); + break; + case SBIG('PULS'): + m_elem.reset(new struct VEPulse); + break; + case SBIG('PVEL'): + m_elem.reset(new struct VEParticleVelocity); + break; + case SBIG('SPOS'): + m_elem.reset(new struct VESPOS); + break; + case SBIG('PLCO'): + m_elem.reset(new struct VEPLCO); + break; + case SBIG('PLOC'): + m_elem.reset(new struct VEPLOC); + break; + case SBIG('PSOR'): + m_elem.reset(new struct VEPSOR); + break; + case SBIG('PSOF'): + m_elem.reset(new struct VEPSOF); + break; + default: + m_elem.reset(); + return; + } + if (auto rec = r.enterSubRecord(elem.first.c_str())) m_elem->read(r); } template <> -void VectorElementFactory::Enumerate(typename Write::StreamT& w) -{ - if (m_elem) - { - w.writeBytes((atInt8*)m_elem->ClassID(), 4); - m_elem->write(w); - } - else - w.writeBytes((atInt8*)"NONE", 4); -} - - -template <> -void ColorElementFactory::Enumerate(typename ReadYaml::StreamT& r) -{ - const auto& mapChildren = r.getCurNode()->m_mapChildren; - if (mapChildren.empty()) - { - m_elem.reset(); - return; - } - - const auto& elem = mapChildren[0]; - if (elem.first.size() < 4) - LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); - - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('KEYE'): - case SBIG('KEYP'): - m_elem.reset(new struct CEKeyframeEmitter); - break; - case SBIG('CNST'): - m_elem.reset(new struct CEConstant); - break; - case SBIG('CHAN'): - m_elem.reset(new struct CETimeChain); - break; - case SBIG('CFDE'): - m_elem.reset(new struct CEFadeEnd); - break; - case SBIG('FADE'): - m_elem.reset(new struct CEFade); - break; - case SBIG('PULS'): - m_elem.reset(new struct CEPulse); - break; - default: - m_elem.reset(); - return; - } - if (auto rec = r.enterSubRecord(elem.first.c_str())) - m_elem->read(r); +void VectorElementFactory::Enumerate(typename WriteYaml::StreamT& w) { + if (m_elem) + if (auto rec = w.enterSubRecord(m_elem->ClassID())) + m_elem->write(w); } template <> -void ColorElementFactory::Enumerate(typename WriteYaml::StreamT& w) -{ - if (m_elem) - if (auto rec = w.enterSubRecord(m_elem->ClassID())) - m_elem->write(w); +void VectorElementFactory::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + if (m_elem) + m_elem->binarySize(s); } template <> -void ColorElementFactory::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - if (m_elem) - m_elem->binarySize(s); +void VectorElementFactory::Enumerate(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + switch (clsId) { + case SBIG('CONE'): + m_elem.reset(new struct VECone); + break; + case SBIG('CHAN'): + m_elem.reset(new struct VETimeChain); + break; + case SBIG('ANGC'): + m_elem.reset(new struct VEAngleCone); + break; + case SBIG('ADD_'): + m_elem.reset(new struct VEAdd); + break; + case SBIG('CCLU'): + m_elem.reset(new struct VECircleCluster); + break; + case SBIG('CNST'): + m_elem.reset(new struct VEConstant); + break; + case SBIG('CIRC'): + m_elem.reset(new struct VECircle); + break; + case SBIG('KEYE'): + case SBIG('KEYP'): + m_elem.reset(new struct VEKeyframeEmitter); + break; + case SBIG('MULT'): + m_elem.reset(new struct VEMultiply); + break; + case SBIG('RTOV'): + m_elem.reset(new struct VERealToVector); + break; + case SBIG('PULS'): + m_elem.reset(new struct VEPulse); + break; + case SBIG('PVEL'): + m_elem.reset(new struct VEParticleVelocity); + break; + case SBIG('SPOS'): + m_elem.reset(new struct VESPOS); + break; + case SBIG('PLCO'): + m_elem.reset(new struct VEPLCO); + break; + case SBIG('PLOC'): + m_elem.reset(new struct VEPLOC); + break; + case SBIG('PSOR'): + m_elem.reset(new struct VEPSOR); + break; + case SBIG('PSOF'): + m_elem.reset(new struct VEPSOF); + break; + case SBIG('NONE'): + m_elem.reset(); + return; + default: + m_elem.reset(); + LogModule.report(logvisor::Fatal, "Unknown VectorElement class %.4s @%" PRIi64, &clsId, r.position()); + return; + } + m_elem->read(r); } template <> -void ColorElementFactory::Enumerate(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - switch (clsId) - { - case SBIG('KEYE'): - case SBIG('KEYP'): - m_elem.reset(new struct CEKeyframeEmitter); - break; - case SBIG('CNST'): - m_elem.reset(new struct CEConstant); - break; - case SBIG('CHAN'): - m_elem.reset(new struct CETimeChain); - break; - case SBIG('CFDE'): - m_elem.reset(new struct CEFadeEnd); - break; - case SBIG('FADE'): - m_elem.reset(new struct CEFade); - break; - case SBIG('PULS'): - m_elem.reset(new struct CEPulse); - break; - case SBIG('NONE'): - m_elem.reset(); - return; - default: - m_elem.reset(); - LogModule.report(logvisor::Fatal, "Unknown ColorElement class %.4s @%" PRIi64, &clsId, r.position()); - return; - } +void VectorElementFactory::Enumerate(typename Write::StreamT& w) { + if (m_elem) { + w.writeBytes((atInt8*)m_elem->ClassID(), 4); + m_elem->write(w); + } else + w.writeBytes((atInt8*)"NONE", 4); +} + +template <> +void ColorElementFactory::Enumerate(typename ReadYaml::StreamT& r) { + const auto& mapChildren = r.getCurNode()->m_mapChildren; + if (mapChildren.empty()) { + m_elem.reset(); + return; + } + + const auto& elem = mapChildren[0]; + if (elem.first.size() < 4) + LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); + + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('KEYE'): + case SBIG('KEYP'): + m_elem.reset(new struct CEKeyframeEmitter); + break; + case SBIG('CNST'): + m_elem.reset(new struct CEConstant); + break; + case SBIG('CHAN'): + m_elem.reset(new struct CETimeChain); + break; + case SBIG('CFDE'): + m_elem.reset(new struct CEFadeEnd); + break; + case SBIG('FADE'): + m_elem.reset(new struct CEFade); + break; + case SBIG('PULS'): + m_elem.reset(new struct CEPulse); + break; + default: + m_elem.reset(); + return; + } + if (auto rec = r.enterSubRecord(elem.first.c_str())) m_elem->read(r); } template <> -void ColorElementFactory::Enumerate(typename Write::StreamT& w) -{ - if (m_elem) - { - w.writeBytes((atInt8*)m_elem->ClassID(), 4); - m_elem->write(w); - } - else - w.writeBytes((atInt8*)"NONE", 4); -} - - -template <> -void ModVectorElementFactory::Enumerate(typename ReadYaml::StreamT& r) -{ - const auto& mapChildren = r.getCurNode()->m_mapChildren; - if (mapChildren.empty()) - { - m_elem.reset(); - return; - } - - const auto& elem = mapChildren[0]; - if (elem.first.size() < 4) - LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); - - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('IMPL'): - m_elem.reset(new struct MVEImplosion); - break; - case SBIG('EMPL'): - m_elem.reset(new struct MVEExponentialImplosion); - break; - case SBIG('CHAN'): - m_elem.reset(new struct MVETimeChain); - break; - case SBIG('BNCE'): - m_elem.reset(new struct MVEBounce); - break; - case SBIG('CNST'): - m_elem.reset(new struct MVEConstant); - break; - case SBIG('GRAV'): - m_elem.reset(new struct MVEGravity); - break; - case SBIG('EXPL'): - m_elem.reset(new struct MVEExplode); - break; - case SBIG('SPOS'): - m_elem.reset(new struct MVESetPosition); - break; - case SBIG('LMPL'): - m_elem.reset(new struct MVELinearImplosion); - break; - case SBIG('PULS'): - m_elem.reset(new struct MVEPulse); - break; - case SBIG('WIND'): - m_elem.reset(new struct MVEWind); - break; - case SBIG('SWRL'): - m_elem.reset(new struct MVESwirl); - break; - default: - m_elem.reset(); - return; - } - if (auto rec = r.enterSubRecord(elem.first.c_str())) - m_elem->read(r); +void ColorElementFactory::Enumerate(typename WriteYaml::StreamT& w) { + if (m_elem) + if (auto rec = w.enterSubRecord(m_elem->ClassID())) + m_elem->write(w); } template <> -void ModVectorElementFactory::Enumerate(typename WriteYaml::StreamT& w) -{ - if (m_elem) - if (auto rec = w.enterSubRecord(m_elem->ClassID())) - m_elem->write(w); +void ColorElementFactory::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + if (m_elem) + m_elem->binarySize(s); } template <> -void ModVectorElementFactory::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - if (m_elem) - m_elem->binarySize(s); +void ColorElementFactory::Enumerate(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + switch (clsId) { + case SBIG('KEYE'): + case SBIG('KEYP'): + m_elem.reset(new struct CEKeyframeEmitter); + break; + case SBIG('CNST'): + m_elem.reset(new struct CEConstant); + break; + case SBIG('CHAN'): + m_elem.reset(new struct CETimeChain); + break; + case SBIG('CFDE'): + m_elem.reset(new struct CEFadeEnd); + break; + case SBIG('FADE'): + m_elem.reset(new struct CEFade); + break; + case SBIG('PULS'): + m_elem.reset(new struct CEPulse); + break; + case SBIG('NONE'): + m_elem.reset(); + return; + default: + m_elem.reset(); + LogModule.report(logvisor::Fatal, "Unknown ColorElement class %.4s @%" PRIi64, &clsId, r.position()); + return; + } + m_elem->read(r); } template <> -void ModVectorElementFactory::Enumerate(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - switch (clsId) - { - case SBIG('IMPL'): - m_elem.reset(new struct MVEImplosion); - break; - case SBIG('EMPL'): - m_elem.reset(new struct MVEExponentialImplosion); - break; - case SBIG('CHAN'): - m_elem.reset(new struct MVETimeChain); - break; - case SBIG('BNCE'): - m_elem.reset(new struct MVEBounce); - break; - case SBIG('CNST'): - m_elem.reset(new struct MVEConstant); - break; - case SBIG('GRAV'): - m_elem.reset(new struct MVEGravity); - break; - case SBIG('EXPL'): - m_elem.reset(new struct MVEExplode); - break; - case SBIG('SPOS'): - m_elem.reset(new struct MVESetPosition); - break; - case SBIG('LMPL'): - m_elem.reset(new struct MVELinearImplosion); - break; - case SBIG('PULS'): - m_elem.reset(new struct MVEPulse); - break; - case SBIG('WIND'): - m_elem.reset(new struct MVEWind); - break; - case SBIG('SWRL'): - m_elem.reset(new struct MVESwirl); - break; - case SBIG('NONE'): - m_elem.reset(); - return; - default: - m_elem.reset(); - LogModule.report(logvisor::Fatal, "Unknown ModVectorElement class %.4s @%" PRIi64, &clsId, r.position()); - return; - } +void ColorElementFactory::Enumerate(typename Write::StreamT& w) { + if (m_elem) { + w.writeBytes((atInt8*)m_elem->ClassID(), 4); + m_elem->write(w); + } else + w.writeBytes((atInt8*)"NONE", 4); +} + +template <> +void ModVectorElementFactory::Enumerate(typename ReadYaml::StreamT& r) { + const auto& mapChildren = r.getCurNode()->m_mapChildren; + if (mapChildren.empty()) { + m_elem.reset(); + return; + } + + const auto& elem = mapChildren[0]; + if (elem.first.size() < 4) + LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); + + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('IMPL'): + m_elem.reset(new struct MVEImplosion); + break; + case SBIG('EMPL'): + m_elem.reset(new struct MVEExponentialImplosion); + break; + case SBIG('CHAN'): + m_elem.reset(new struct MVETimeChain); + break; + case SBIG('BNCE'): + m_elem.reset(new struct MVEBounce); + break; + case SBIG('CNST'): + m_elem.reset(new struct MVEConstant); + break; + case SBIG('GRAV'): + m_elem.reset(new struct MVEGravity); + break; + case SBIG('EXPL'): + m_elem.reset(new struct MVEExplode); + break; + case SBIG('SPOS'): + m_elem.reset(new struct MVESetPosition); + break; + case SBIG('LMPL'): + m_elem.reset(new struct MVELinearImplosion); + break; + case SBIG('PULS'): + m_elem.reset(new struct MVEPulse); + break; + case SBIG('WIND'): + m_elem.reset(new struct MVEWind); + break; + case SBIG('SWRL'): + m_elem.reset(new struct MVESwirl); + break; + default: + m_elem.reset(); + return; + } + if (auto rec = r.enterSubRecord(elem.first.c_str())) m_elem->read(r); } template <> -void ModVectorElementFactory::Enumerate(typename Write::StreamT& w) -{ - if (m_elem) - { - w.writeBytes((atInt8*)m_elem->ClassID(), 4); - m_elem->write(w); - } - else - w.writeBytes((atInt8*)"NONE", 4); -} - - -template <> -void EmitterElementFactory::Enumerate(typename ReadYaml::StreamT& r) -{ - const auto& mapChildren = r.getCurNode()->m_mapChildren; - if (mapChildren.empty()) - { - m_elem.reset(); - return; - } - - const auto& elem = mapChildren[0]; - if (elem.first.size() < 4) - LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); - - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('SETR'): - m_elem.reset(new struct EESimpleEmitterTR); - break; - case SBIG('SEMR'): - m_elem.reset(new struct EESimpleEmitter); - break; - case SBIG('SPHE'): - m_elem.reset(new struct VESphere); - break; - case SBIG('ASPH'): - m_elem.reset(new struct VEAngleSphere); - break; - default: - m_elem.reset(); - return; - } - if (auto rec = r.enterSubRecord(elem.first.c_str())) - m_elem->read(r); +void ModVectorElementFactory::Enumerate(typename WriteYaml::StreamT& w) { + if (m_elem) + if (auto rec = w.enterSubRecord(m_elem->ClassID())) + m_elem->write(w); } template <> -void EmitterElementFactory::Enumerate(typename WriteYaml::StreamT& w) -{ - if (m_elem) - if (auto rec = w.enterSubRecord(m_elem->ClassID())) - m_elem->write(w); +void ModVectorElementFactory::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + if (m_elem) + m_elem->binarySize(s); } template <> -void EmitterElementFactory::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - if (m_elem) - m_elem->binarySize(s); +void ModVectorElementFactory::Enumerate(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + switch (clsId) { + case SBIG('IMPL'): + m_elem.reset(new struct MVEImplosion); + break; + case SBIG('EMPL'): + m_elem.reset(new struct MVEExponentialImplosion); + break; + case SBIG('CHAN'): + m_elem.reset(new struct MVETimeChain); + break; + case SBIG('BNCE'): + m_elem.reset(new struct MVEBounce); + break; + case SBIG('CNST'): + m_elem.reset(new struct MVEConstant); + break; + case SBIG('GRAV'): + m_elem.reset(new struct MVEGravity); + break; + case SBIG('EXPL'): + m_elem.reset(new struct MVEExplode); + break; + case SBIG('SPOS'): + m_elem.reset(new struct MVESetPosition); + break; + case SBIG('LMPL'): + m_elem.reset(new struct MVELinearImplosion); + break; + case SBIG('PULS'): + m_elem.reset(new struct MVEPulse); + break; + case SBIG('WIND'): + m_elem.reset(new struct MVEWind); + break; + case SBIG('SWRL'): + m_elem.reset(new struct MVESwirl); + break; + case SBIG('NONE'): + m_elem.reset(); + return; + default: + m_elem.reset(); + LogModule.report(logvisor::Fatal, "Unknown ModVectorElement class %.4s @%" PRIi64, &clsId, r.position()); + return; + } + m_elem->read(r); } template <> -void EmitterElementFactory::Enumerate(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - switch (clsId) - { - case SBIG('SETR'): - m_elem.reset(new struct EESimpleEmitterTR); - break; - case SBIG('SEMR'): - m_elem.reset(new struct EESimpleEmitter); - break; - case SBIG('SPHE'): - m_elem.reset(new struct VESphere); - break; - case SBIG('ASPH'): - m_elem.reset(new struct VEAngleSphere); - break; - case SBIG('NONE'): - m_elem.reset(); - return; - default: - m_elem.reset(); - LogModule.report(logvisor::Fatal, "Unknown EmitterElement class %.4s @%" PRIi64, &clsId, r.position()); - return; - } +void ModVectorElementFactory::Enumerate(typename Write::StreamT& w) { + if (m_elem) { + w.writeBytes((atInt8*)m_elem->ClassID(), 4); + m_elem->write(w); + } else + w.writeBytes((atInt8*)"NONE", 4); +} + +template <> +void EmitterElementFactory::Enumerate(typename ReadYaml::StreamT& r) { + const auto& mapChildren = r.getCurNode()->m_mapChildren; + if (mapChildren.empty()) { + m_elem.reset(); + return; + } + + const auto& elem = mapChildren[0]; + if (elem.first.size() < 4) + LogModule.report(logvisor::Fatal, "short FourCC in element '%s'", elem.first.c_str()); + + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('SETR'): + m_elem.reset(new struct EESimpleEmitterTR); + break; + case SBIG('SEMR'): + m_elem.reset(new struct EESimpleEmitter); + break; + case SBIG('SPHE'): + m_elem.reset(new struct VESphere); + break; + case SBIG('ASPH'): + m_elem.reset(new struct VEAngleSphere); + break; + default: + m_elem.reset(); + return; + } + if (auto rec = r.enterSubRecord(elem.first.c_str())) m_elem->read(r); } template <> -void EmitterElementFactory::Enumerate(typename Write::StreamT& w) -{ - if (m_elem) - { - w.writeBytes((atInt8*)m_elem->ClassID(), 4); - m_elem->write(w); - } - else - w.writeBytes((atInt8*)"NONE", 4); +void EmitterElementFactory::Enumerate(typename WriteYaml::StreamT& w) { + if (m_elem) + if (auto rec = w.enterSubRecord(m_elem->ClassID())) + m_elem->write(w); } template <> -void BoolHelper::Enumerate(typename ReadYaml::StreamT& r) -{ - value = r.readBool(nullptr); -} -template <> -void BoolHelper::Enumerate(typename WriteYaml::StreamT& w) -{ - w.writeBool(nullptr, value); -} -template <> -void BoolHelper::Enumerate(typename BinarySize::StreamT& s) -{ - s += 5; -} -template <> -void BoolHelper::Enumerate(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId == SBIG('CNST')) - value = r.readBool(); - else - value = false; -} -template <> -void BoolHelper::Enumerate(typename Write::StreamT& w) -{ - w.writeBytes((atInt8*)"CNST", 4); - w.writeBool(value); +void EmitterElementFactory::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + if (m_elem) + m_elem->binarySize(s); } template <> -void EESimpleEmitterTR::Enumerate(typename ReadYaml::StreamT& r) -{ - position.m_elem.reset(); - velocity.m_elem.reset(); - if (auto rec = r.enterSubRecord("ILOC")) - position.read(r); - if (auto rec = r.enterSubRecord("IVEC")) - velocity.read(r); +void EmitterElementFactory::Enumerate(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + switch (clsId) { + case SBIG('SETR'): + m_elem.reset(new struct EESimpleEmitterTR); + break; + case SBIG('SEMR'): + m_elem.reset(new struct EESimpleEmitter); + break; + case SBIG('SPHE'): + m_elem.reset(new struct VESphere); + break; + case SBIG('ASPH'): + m_elem.reset(new struct VEAngleSphere); + break; + case SBIG('NONE'): + m_elem.reset(); + return; + default: + m_elem.reset(); + LogModule.report(logvisor::Fatal, "Unknown EmitterElement class %.4s @%" PRIi64, &clsId, r.position()); + return; + } + m_elem->read(r); +} + +template <> +void EmitterElementFactory::Enumerate(typename Write::StreamT& w) { + if (m_elem) { + w.writeBytes((atInt8*)m_elem->ClassID(), 4); + m_elem->write(w); + } else + w.writeBytes((atInt8*)"NONE", 4); +} + +template <> +void BoolHelper::Enumerate(typename ReadYaml::StreamT& r) { + value = r.readBool(nullptr); } template <> -void EESimpleEmitterTR::Enumerate(typename WriteYaml::StreamT& w) -{ - if (auto rec = w.enterSubRecord("ILOC")) - position.write(w); - if (auto rec = w.enterSubRecord("IVEC")) - velocity.write(w); +void BoolHelper::Enumerate(typename WriteYaml::StreamT& w) { + w.writeBool(nullptr, value); } template <> -void EESimpleEmitterTR::Enumerate(typename BinarySize::StreamT& s) -{ - s += 8; - position.binarySize(s); - velocity.binarySize(s); +void BoolHelper::Enumerate(typename BinarySize::StreamT& s) { + s += 5; } template <> -void EESimpleEmitterTR::Enumerate(typename Read::StreamT& r) -{ - position.m_elem.reset(); - velocity.m_elem.reset(); - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId == SBIG('ILOC')) - { - position.read(r); - r.readBytesToBuf(&clsId, 4); - if (clsId == SBIG('IVEC')) - velocity.read(r); - } +void BoolHelper::Enumerate(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId == SBIG('CNST')) + value = r.readBool(); + else + value = false; } template <> -void EESimpleEmitterTR::Enumerate(typename Write::StreamT& w) -{ - w.writeBytes((atInt8*)"ILOC", 4); +void BoolHelper::Enumerate(typename Write::StreamT& w) { + w.writeBytes((atInt8*)"CNST", 4); + w.writeBool(value); +} + +template <> +void EESimpleEmitterTR::Enumerate(typename ReadYaml::StreamT& r) { + position.m_elem.reset(); + velocity.m_elem.reset(); + if (auto rec = r.enterSubRecord("ILOC")) + position.read(r); + if (auto rec = r.enterSubRecord("IVEC")) + velocity.read(r); +} +template <> +void EESimpleEmitterTR::Enumerate(typename WriteYaml::StreamT& w) { + if (auto rec = w.enterSubRecord("ILOC")) position.write(w); - w.writeBytes((atInt8*)"IVEC", 4); + if (auto rec = w.enterSubRecord("IVEC")) velocity.write(w); } - template <> -const char* UVEConstant::DNAType() { return "UVEConstant"; } +void EESimpleEmitterTR::Enumerate(typename BinarySize::StreamT& s) { + s += 8; + position.binarySize(s); + velocity.binarySize(s); +} template <> -const char* UVEConstant::DNAType() { return "UVEConstant"; } - -template -void UVEConstant::_read(typename ReadYaml::StreamT& r) -{ - tex.clear(); - if (auto rec = r.enterSubRecord("tex")) - tex.read(r); -} -template -void UVEConstant::_write(typename WriteYaml::StreamT& w) const -{ - if (auto rec = w.enterSubRecord("tex")) - tex.write(w); -} -template -void UVEConstant::_binarySize(typename BinarySize::StreamT& _s) const -{ - _s += 4; - tex.binarySize(_s); -} -template -void UVEConstant::_read(typename Read::StreamT& r) -{ - tex.clear(); - uint32_t clsId; +void EESimpleEmitterTR::Enumerate(typename Read::StreamT& r) { + position.m_elem.reset(); + velocity.m_elem.reset(); + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId == SBIG('ILOC')) { + position.read(r); r.readBytesToBuf(&clsId, 4); - if (clsId == SBIG('CNST')) - tex.read(r); + if (clsId == SBIG('IVEC')) + velocity.read(r); + } +} +template <> +void EESimpleEmitterTR::Enumerate(typename Write::StreamT& w) { + w.writeBytes((atInt8*)"ILOC", 4); + position.write(w); + w.writeBytes((atInt8*)"IVEC", 4); + velocity.write(w); +} + +template <> +const char* UVEConstant::DNAType() { + return "UVEConstant"; +} +template <> +const char* UVEConstant::DNAType() { + return "UVEConstant"; +} + +template +void UVEConstant::_read(typename ReadYaml::StreamT& r) { + tex.clear(); + if (auto rec = r.enterSubRecord("tex")) + tex.read(r); } template -void UVEConstant::_write(typename Write::StreamT& w) const -{ - w.writeBytes((atInt8*)"CNST", 4); +void UVEConstant::_write(typename WriteYaml::StreamT& w) const { + if (auto rec = w.enterSubRecord("tex")) tex.write(w); } +template +void UVEConstant::_binarySize(typename BinarySize::StreamT& _s) const { + _s += 4; + tex.binarySize(_s); +} +template +void UVEConstant::_read(typename Read::StreamT& r) { + tex.clear(); + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId == SBIG('CNST')) + tex.read(r); +} +template +void UVEConstant::_write(typename Write::StreamT& w) const { + w.writeBytes((atInt8*)"CNST", 4); + tex.write(w); +} AT_SUBSPECIALIZE_DNA_YAML(UVEConstant) AT_SUBSPECIALIZE_DNA_YAML(UVEConstant) @@ -1270,86 +1166,85 @@ template struct UVEConstant; template struct UVEConstant; template <> -const char* UVEAnimTexture::DNAType() { return "UVEAnimTexture"; } +const char* UVEAnimTexture::DNAType() { + return "UVEAnimTexture"; +} template <> -const char* UVEAnimTexture::DNAType() { return "UVEAnimTexture"; } +const char* UVEAnimTexture::DNAType() { + return "UVEAnimTexture"; +} template -void UVEAnimTexture::_read(typename ReadYaml::StreamT& r) -{ - tex.clear(); - if (auto rec = r.enterSubRecord("tex")) - tex.read(r); - if (auto rec = r.enterSubRecord("tileW")) - tileW.read(r); - if (auto rec = r.enterSubRecord("tileH")) - tileH.read(r); - if (auto rec = r.enterSubRecord("strideW")) - strideW.read(r); - if (auto rec = r.enterSubRecord("strideH")) - strideH.read(r); - if (auto rec = r.enterSubRecord("cycleFrames")) - cycleFrames.read(r); - if (auto rec = r.enterSubRecord("loop")) - loop = r.readBool(nullptr); -} -template -void UVEAnimTexture::_write(typename WriteYaml::StreamT& w) const -{ - if (auto rec = w.enterSubRecord("tex")) - tex.write(w); - if (auto rec = w.enterSubRecord("tileW")) - tileW.write(w); - if (auto rec = w.enterSubRecord("tileH")) - tileH.write(w); - if (auto rec = w.enterSubRecord("strideW")) - strideW.write(w); - if (auto rec = w.enterSubRecord("strideH")) - strideH.write(w); - if (auto rec = w.enterSubRecord("cycleFrames")) - cycleFrames.write(w); - w.writeBool("loop", loop); -} -template -void UVEAnimTexture::_binarySize(typename BinarySize::StreamT& _s) const -{ - _s += 9; - tex.binarySize(_s); - tileW.binarySize(_s); - tileH.binarySize(_s); - strideW.binarySize(_s); - strideH.binarySize(_s); - cycleFrames.binarySize(_s); -} -template -void UVEAnimTexture::_read(typename Read::StreamT& r) -{ - tex.clear(); - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId == SBIG('CNST')) - tex.read(r); +void UVEAnimTexture::_read(typename ReadYaml::StreamT& r) { + tex.clear(); + if (auto rec = r.enterSubRecord("tex")) + tex.read(r); + if (auto rec = r.enterSubRecord("tileW")) tileW.read(r); + if (auto rec = r.enterSubRecord("tileH")) tileH.read(r); + if (auto rec = r.enterSubRecord("strideW")) strideW.read(r); + if (auto rec = r.enterSubRecord("strideH")) strideH.read(r); + if (auto rec = r.enterSubRecord("cycleFrames")) cycleFrames.read(r); - r.readBytesToBuf(&clsId, 4); - if (clsId == SBIG('CNST')) - loop = r.readBool(); + if (auto rec = r.enterSubRecord("loop")) + loop = r.readBool(nullptr); } template -void UVEAnimTexture::_write(typename Write::StreamT& w) const -{ - w.writeBytes((atInt8*)"CNST", 4); +void UVEAnimTexture::_write(typename WriteYaml::StreamT& w) const { + if (auto rec = w.enterSubRecord("tex")) tex.write(w); + if (auto rec = w.enterSubRecord("tileW")) tileW.write(w); + if (auto rec = w.enterSubRecord("tileH")) tileH.write(w); + if (auto rec = w.enterSubRecord("strideW")) strideW.write(w); + if (auto rec = w.enterSubRecord("strideH")) strideH.write(w); + if (auto rec = w.enterSubRecord("cycleFrames")) cycleFrames.write(w); - w.writeBytes((atInt8*)"CNST", 4); - w.writeBool(loop); + w.writeBool("loop", loop); +} +template +void UVEAnimTexture::_binarySize(typename BinarySize::StreamT& _s) const { + _s += 9; + tex.binarySize(_s); + tileW.binarySize(_s); + tileH.binarySize(_s); + strideW.binarySize(_s); + strideH.binarySize(_s); + cycleFrames.binarySize(_s); +} +template +void UVEAnimTexture::_read(typename Read::StreamT& r) { + tex.clear(); + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId == SBIG('CNST')) + tex.read(r); + tileW.read(r); + tileH.read(r); + strideW.read(r); + strideH.read(r); + cycleFrames.read(r); + r.readBytesToBuf(&clsId, 4); + if (clsId == SBIG('CNST')) + loop = r.readBool(); +} +template +void UVEAnimTexture::_write(typename Write::StreamT& w) const { + w.writeBytes((atInt8*)"CNST", 4); + tex.write(w); + tileW.write(w); + tileH.write(w); + strideW.write(w); + strideH.write(w); + cycleFrames.write(w); + w.writeBytes((atInt8*)"CNST", 4); + w.writeBool(loop); } AT_SUBSPECIALIZE_DNA_YAML(UVEAnimTexture) @@ -1359,69 +1254,61 @@ template struct UVEAnimTexture; template struct UVEAnimTexture; template <> -const char* UVElementFactory::DNAType() { return "UVElementFactory"; } +const char* UVElementFactory::DNAType() { + return "UVElementFactory"; +} template <> -const char* UVElementFactory::DNAType() { return "UVElementFactory"; } +const char* UVElementFactory::DNAType() { + return "UVElementFactory"; +} template -void UVElementFactory::_read(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - switch (clsId) - { - case SBIG('CNST'): - m_elem.reset(new struct UVEConstant); - break; - case SBIG('ATEX'): - m_elem.reset(new struct UVEAnimTexture); - break; - default: - m_elem.reset(); - return; - } +void UVElementFactory::_read(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + switch (clsId) { + case SBIG('CNST'): + m_elem.reset(new struct UVEConstant); + break; + case SBIG('ATEX'): + m_elem.reset(new struct UVEAnimTexture); + break; + default: + m_elem.reset(); + return; + } + m_elem->read(r); +} +template +void UVElementFactory::_write(typename Write::StreamT& w) const { + if (m_elem) { + w.writeBytes((atInt8*)m_elem->ClassID(), 4); + m_elem->write(w); + } else + w.writeBytes((atInt8*)"NONE", 4); +} +template +void UVElementFactory::_read(typename ReadYaml::StreamT& r) { + if (auto rec = r.enterSubRecord("CNST")) { + m_elem.reset(new struct UVEConstant); m_elem->read(r); + } else if (auto rec = r.enterSubRecord("ATEX")) { + m_elem.reset(new struct UVEAnimTexture); + m_elem->read(r); + } else + m_elem.reset(); } template -void UVElementFactory::_write(typename Write::StreamT& w) const -{ - if (m_elem) - { - w.writeBytes((atInt8*)m_elem->ClassID(), 4); - m_elem->write(w); - } - else - w.writeBytes((atInt8*)"NONE", 4); +void UVElementFactory::_write(typename WriteYaml::StreamT& w) const { + if (m_elem) + if (auto rec = w.enterSubRecord(m_elem->ClassID())) + m_elem->write(w); } template -void UVElementFactory::_read(typename ReadYaml::StreamT& r) -{ - if (auto rec = r.enterSubRecord("CNST")) - { - m_elem.reset(new struct UVEConstant); - m_elem->read(r); - } - else if (auto rec = r.enterSubRecord("ATEX")) - { - m_elem.reset(new struct UVEAnimTexture); - m_elem->read(r); - } - else - m_elem.reset(); -} -template -void UVElementFactory::_write(typename WriteYaml::StreamT& w) const -{ - if (m_elem) - if (auto rec = w.enterSubRecord(m_elem->ClassID())) - m_elem->write(w); -} -template -void UVElementFactory::_binarySize(typename BinarySize::StreamT& _s) const -{ - if (m_elem) - m_elem->binarySize(_s); - _s += 4; +void UVElementFactory::_binarySize(typename BinarySize::StreamT& _s) const { + if (m_elem) + m_elem->binarySize(_s); + _s += 4; } AT_SUBSPECIALIZE_DNA_YAML(UVElementFactory) @@ -1431,155 +1318,142 @@ template struct UVElementFactory; template struct UVElementFactory; template <> -const char* SpawnSystemKeyframeData::SpawnSystemKeyframeInfo::DNAType() -{ return "SpawnSystemKeyframeData::SpawnSystemKeyframeInfo"; } +const char* SpawnSystemKeyframeData::SpawnSystemKeyframeInfo::DNAType() { + return "SpawnSystemKeyframeData::SpawnSystemKeyframeInfo"; +} template <> -const char* SpawnSystemKeyframeData::SpawnSystemKeyframeInfo::DNAType() -{ return "SpawnSystemKeyframeData::SpawnSystemKeyframeInfo"; } +const char* SpawnSystemKeyframeData::SpawnSystemKeyframeInfo::DNAType() { + return "SpawnSystemKeyframeData::SpawnSystemKeyframeInfo"; +} template template -void SpawnSystemKeyframeData::SpawnSystemKeyframeInfo::Enumerate(typename Op::StreamT& s) -{ - Do({"id"}, id, s); - Do({"a"}, a, s); - Do({"b"}, b, s); - Do({"c"}, c, s); +void SpawnSystemKeyframeData::SpawnSystemKeyframeInfo::Enumerate(typename Op::StreamT& s) { + Do({"id"}, id, s); + Do({"a"}, a, s); + Do({"b"}, b, s); + Do({"c"}, c, s); } template <> -const char* SpawnSystemKeyframeData::DNAType() { return "SpawnSystemKeyframeData"; } +const char* SpawnSystemKeyframeData::DNAType() { + return "SpawnSystemKeyframeData"; +} template <> -const char* SpawnSystemKeyframeData::DNAType() { return "SpawnSystemKeyframeData"; } - -template -void SpawnSystemKeyframeData::_read(typename ReadYaml::StreamT& r) -{ - if (auto rec = r.enterSubRecord("a")) - a = r.readUint32(nullptr); - if (auto rec = r.enterSubRecord("b")) - b = r.readUint32(nullptr); - if (auto rec = r.enterSubRecord("endFrame")) - endFrame = r.readUint32(nullptr); - if (auto rec = r.enterSubRecord("d")) - d = r.readUint32(nullptr); - spawns.clear(); - size_t spawnCount; - if (auto v = r.enterSubVector("spawns", spawnCount)) - { - spawns.reserve(spawnCount); - for (const auto& child : r.getCurNode()->m_seqChildren) - { - (void)child; - if (auto rec = r.enterSubRecord(nullptr)) - { - spawns.emplace_back(); - spawns.back().first = r.readUint32("startFrame"); - size_t systemCount; - if (auto v = r.enterSubVector("systems", systemCount)) - { - spawns.back().second.reserve(systemCount); - for (const auto& in : r.getCurNode()->m_seqChildren) - { - (void)in; - spawns.back().second.emplace_back(); - SpawnSystemKeyframeInfo& info = spawns.back().second.back(); - if (auto rec = r.enterSubRecord(nullptr)) - info.read(r); - } - } - } - } - } +const char* SpawnSystemKeyframeData::DNAType() { + return "SpawnSystemKeyframeData"; } template -void SpawnSystemKeyframeData::_write(typename WriteYaml::StreamT& w) const -{ - if (spawns.empty()) - return; - w.writeUint32("a", a); - w.writeUint32("b", b); - w.writeUint32("endFrame", endFrame); - w.writeUint32("d", d); - if (auto v = w.enterSubVector("spawns")) - { - for (const auto& spawn : spawns) - { - if (auto rec = w.enterSubRecord(nullptr)) - { - w.writeUint32("startFrame", spawn.first); - if (auto v = w.enterSubVector("systems")) - for (const auto& info : spawn.second) - if (auto rec = w.enterSubRecord(nullptr)) - info.write(w); - } - } - } -} - -template -void SpawnSystemKeyframeData::_binarySize(typename BinarySize::StreamT& s) const -{ - s += 20; - for (const auto& spawn : spawns) - { - s += 8; - for (const auto& info : spawn.second) - info.binarySize(s); - } -} - -template -void SpawnSystemKeyframeData::_read(typename Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId != SBIG('CNST')) - return; - - a = r.readUint32Big(); - b = r.readUint32Big(); - endFrame = r.readUint32Big(); - d = r.readUint32Big(); - uint32_t count = r.readUint32Big(); - spawns.clear(); - spawns.reserve(count); - for (size_t i=0 ; i::_read(typename ReadYaml::StreamT& r) { + if (auto rec = r.enterSubRecord("a")) + a = r.readUint32(nullptr); + if (auto rec = r.enterSubRecord("b")) + b = r.readUint32(nullptr); + if (auto rec = r.enterSubRecord("endFrame")) + endFrame = r.readUint32(nullptr); + if (auto rec = r.enterSubRecord("d")) + d = r.readUint32(nullptr); + spawns.clear(); + size_t spawnCount; + if (auto v = r.enterSubVector("spawns", spawnCount)) { + spawns.reserve(spawnCount); + for (const auto& child : r.getCurNode()->m_seqChildren) { + (void)child; + if (auto rec = r.enterSubRecord(nullptr)) { spawns.emplace_back(); - spawns.back().first = r.readUint32Big(); - uint32_t infoCount = r.readUint32Big(); - spawns.back().second.reserve(infoCount); - for (size_t j=0 ; jm_seqChildren) { + (void)in; spawns.back().second.emplace_back(); - spawns.back().second.back().read(r); + SpawnSystemKeyframeInfo& info = spawns.back().second.back(); + if (auto rec = r.enterSubRecord(nullptr)) + info.read(r); + } } + } } + } } template -void SpawnSystemKeyframeData::_write(typename Write::StreamT& w) const -{ - if (spawns.empty()) - { - w.writeBytes((atInt8*)"NONE", 4); - return; +void SpawnSystemKeyframeData::_write(typename WriteYaml::StreamT& w) const { + if (spawns.empty()) + return; + w.writeUint32("a", a); + w.writeUint32("b", b); + w.writeUint32("endFrame", endFrame); + w.writeUint32("d", d); + if (auto v = w.enterSubVector("spawns")) { + for (const auto& spawn : spawns) { + if (auto rec = w.enterSubRecord(nullptr)) { + w.writeUint32("startFrame", spawn.first); + if (auto v = w.enterSubVector("systems")) + for (const auto& info : spawn.second) + if (auto rec = w.enterSubRecord(nullptr)) + info.write(w); + } } - w.writeBytes((atInt8*)"CNST", 4); - w.writeUint32Big(a); - w.writeUint32Big(b); - w.writeUint32Big(endFrame); - w.writeUint32Big(d); - w.writeUint32Big(spawns.size()); - for (const auto& spawn : spawns) - { - w.writeUint32Big(spawn.first); - w.writeUint32Big(spawn.second.size()); - for (const auto& info : spawn.second) - info.write(w); + } +} + +template +void SpawnSystemKeyframeData::_binarySize(typename BinarySize::StreamT& s) const { + s += 20; + for (const auto& spawn : spawns) { + s += 8; + for (const auto& info : spawn.second) + info.binarySize(s); + } +} + +template +void SpawnSystemKeyframeData::_read(typename Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId != SBIG('CNST')) + return; + + a = r.readUint32Big(); + b = r.readUint32Big(); + endFrame = r.readUint32Big(); + d = r.readUint32Big(); + uint32_t count = r.readUint32Big(); + spawns.clear(); + spawns.reserve(count); + for (size_t i = 0; i < count; ++i) { + spawns.emplace_back(); + spawns.back().first = r.readUint32Big(); + uint32_t infoCount = r.readUint32Big(); + spawns.back().second.reserve(infoCount); + for (size_t j = 0; j < infoCount; ++j) { + spawns.back().second.emplace_back(); + spawns.back().second.back().read(r); } + } +} + +template +void SpawnSystemKeyframeData::_write(typename Write::StreamT& w) const { + if (spawns.empty()) { + w.writeBytes((atInt8*)"NONE", 4); + return; + } + w.writeBytes((atInt8*)"CNST", 4); + w.writeUint32Big(a); + w.writeUint32Big(b); + w.writeUint32Big(endFrame); + w.writeUint32Big(d); + w.writeUint32Big(spawns.size()); + for (const auto& spawn : spawns) { + w.writeUint32Big(spawn.first); + w.writeUint32Big(spawn.second.size()); + for (const auto& info : spawn.second) + info.write(w); + } } AT_SUBSPECIALIZE_DNA_YAML(SpawnSystemKeyframeData) @@ -1589,54 +1463,51 @@ template struct SpawnSystemKeyframeData; template struct SpawnSystemKeyframeData; template <> -const char* ChildResourceFactory::DNAType() { return "ChildResourceFactory"; } +const char* ChildResourceFactory::DNAType() { + return "ChildResourceFactory"; +} template <> -const char* ChildResourceFactory::DNAType() { return "ChildResourceFactory"; } - -template -void ChildResourceFactory::_read(typename ReadYaml::StreamT& r) -{ - id.clear(); - if (auto rec = r.enterSubRecord("CNST")) - id.read(r); +const char* ChildResourceFactory::DNAType() { + return "ChildResourceFactory"; } template -void ChildResourceFactory::_write(typename WriteYaml::StreamT& w) const -{ - if (id) - if (auto rec = w.enterSubRecord("CNST")) - id.write(w); +void ChildResourceFactory::_read(typename ReadYaml::StreamT& r) { + id.clear(); + if (auto rec = r.enterSubRecord("CNST")) + id.read(r); } template -void ChildResourceFactory::_binarySize(typename BinarySize::StreamT& s) const -{ - if (id) - id.binarySize(s); - s += 4; +void ChildResourceFactory::_write(typename WriteYaml::StreamT& w) const { + if (id) + if (auto rec = w.enterSubRecord("CNST")) + id.write(w); } template -void ChildResourceFactory::_read(typename Read::StreamT& r) -{ - id.clear(); - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId == SBIG('CNST')) - id.read(r); +void ChildResourceFactory::_binarySize(typename BinarySize::StreamT& s) const { + if (id) + id.binarySize(s); + s += 4; } template -void ChildResourceFactory::_write(typename Write::StreamT& w) const -{ - if (id) - { - w.writeBytes((atInt8*)"CNST", 4); - id.write(w); - } - else - w.writeBytes((atInt8*)"NONE", 4); +void ChildResourceFactory::_read(typename Read::StreamT& r) { + id.clear(); + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId == SBIG('CNST')) + id.read(r); +} + +template +void ChildResourceFactory::_write(typename Write::StreamT& w) const { + if (id) { + w.writeBytes((atInt8*)"CNST", 4); + id.write(w); + } else + w.writeBytes((atInt8*)"NONE", 4); } AT_SUBSPECIALIZE_DNA_YAML(ChildResourceFactory) @@ -1645,4 +1516,4 @@ AT_SUBSPECIALIZE_DNA_YAML(ChildResourceFactory) template struct ChildResourceFactory; template struct ChildResourceFactory; -} +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/ParticleCommon.hpp b/DataSpec/DNACommon/ParticleCommon.hpp index eefcd9552..f52097caa 100644 --- a/DataSpec/DNACommon/ParticleCommon.hpp +++ b/DataSpec/DNACommon/ParticleCommon.hpp @@ -2,902 +2,808 @@ #include "DNACommon.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { extern logvisor::Module LogModule; -struct IElement : BigDNAVYaml -{ - Delete _d; - virtual ~IElement() = default; - virtual const char* ClassID() const=0; - const char* DNATypeV() const {return ClassID();} +struct IElement : BigDNAVYaml { + Delete _d; + virtual ~IElement() = default; + virtual const char* ClassID() const = 0; + const char* DNATypeV() const { return ClassID(); } }; - -struct IRealElement : IElement {Delete _d2;}; -struct RealElementFactory : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - std::unique_ptr m_elem; - operator bool() const {return m_elem.operator bool();} + +struct IRealElement : IElement { + Delete _d2; +}; +struct RealElementFactory : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + std::unique_ptr m_elem; + operator bool() const { return m_elem.operator bool(); } +}; + +struct IIntElement : IElement { + Delete _d2; +}; +struct IntElementFactory : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + std::unique_ptr m_elem; + operator bool() const { return m_elem.operator bool(); } +}; + +struct IVectorElement : IElement { + Delete _d2; +}; +struct VectorElementFactory : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + std::unique_ptr m_elem; + operator bool() const { return m_elem.operator bool(); } +}; + +struct IColorElement : IElement { + Delete _d2; +}; +struct ColorElementFactory : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + std::unique_ptr m_elem; + operator bool() const { return m_elem.operator bool(); } +}; + +struct IModVectorElement : IElement { + Delete _d2; +}; +struct ModVectorElementFactory : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + std::unique_ptr m_elem; + operator bool() const { return m_elem.operator bool(); } +}; + +struct IEmitterElement : IElement { + Delete _d2; +}; +struct EmitterElementFactory : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + std::unique_ptr m_elem; + operator bool() const { return m_elem.operator bool(); } +}; + +struct IUVElement : IElement { + Delete _d2; + virtual void gatherDependencies(std::vector& pathsOut) const = 0; +}; + +struct BoolHelper : IElement { + AT_DECL_EXPLICIT_DNA_YAML + bool value = false; + operator bool() const { return value; } + BoolHelper& operator=(bool val) { + value = val; + return *this; + } + const char* ClassID() const { return "BoolHelper"; } +}; + +struct RELifetimeTween : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "LFTW"; } +}; + +struct REConstant : IRealElement { + AT_DECL_EXPLICIT_DNA_YAML + Value val; + const char* ClassID() const { return "CNST"; } +}; + +struct RETimeChain : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory a; + RealElementFactory b; + IntElementFactory thresholdFrame; + const char* ClassID() const { return "CHAN"; } +}; + +struct REAdd : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "ADD_"; } +}; + +struct REClamp : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory min; + RealElementFactory max; + RealElementFactory val; + const char* ClassID() const { return "CLMP"; } +}; + +struct REKeyframeEmitter : IRealElement { + AT_DECL_DNA_YAML + Value percentageTween; + Value unk1; + Value loop; + Value unk2; + Value loopEnd; + Value loopStart; + Value count; + Vector keys; + const char* ClassID() const { return percentageTween ? "KEYP" : "KEYE"; } +}; + +struct REInitialRandom : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "IRND"; } +}; + +struct RERandom : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "RAND"; } +}; + +struct REMultiply : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "MULT"; } +}; + +struct REPulse : IRealElement { + AT_DECL_DNA_YAML + IntElementFactory aDuration; + IntElementFactory bDuration; + RealElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "PULS"; } +}; + +struct RETimeScale : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory dv; + const char* ClassID() const { return "SCAL"; } +}; + +struct RELifetimePercent : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory percent; + const char* ClassID() const { return "RLPT"; } +}; + +struct RESineWave : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory frequency; + RealElementFactory amplitude; + RealElementFactory phase; + const char* ClassID() const { return "SINE"; } +}; + +struct REInitialSwitch : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "ISWT"; } +}; + +struct RECompareLessThan : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory ca; + RealElementFactory cb; + RealElementFactory pass; + RealElementFactory fail; + const char* ClassID() const { return "CLTN"; } +}; + +struct RECompareEquals : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory ca; + RealElementFactory cb; + RealElementFactory pass; + RealElementFactory fail; + const char* ClassID() const { return "CEQL"; } +}; + +struct REParticleAdvanceParam1 : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PAP1"; } +}; + +struct REParticleAdvanceParam2 : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PAP2"; } +}; + +struct REParticleAdvanceParam3 : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PAP3"; } +}; + +struct REParticleAdvanceParam4 : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PAP4"; } +}; + +struct REParticleAdvanceParam5 : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PAP5"; } +}; + +struct REParticleAdvanceParam6 : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PAP6"; } +}; + +struct REParticleAdvanceParam7 : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PAP7"; } +}; + +struct REParticleAdvanceParam8 : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PAP8"; } +}; + +struct REParticleSizeOrLineLength : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PSLL"; } +}; + +struct REParticleRotationOrLineWidth : IRealElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PRLW"; } +}; + +struct RESubtract : IRealElement { + AT_DECL_DNA_YAML + RealElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "SUB_"; } +}; + +struct REVectorMagnitude : IRealElement { + AT_DECL_DNA_YAML + VectorElementFactory vec; + const char* ClassID() const { return "VMAG"; } +}; + +struct REVectorXToReal : IRealElement { + AT_DECL_DNA_YAML + VectorElementFactory vec; + const char* ClassID() const { return "VXTR"; } +}; + +struct REVectorYToReal : IRealElement { + AT_DECL_DNA_YAML + VectorElementFactory vec; + const char* ClassID() const { return "VYTR"; } }; - -struct IIntElement : IElement {Delete _d2;}; -struct IntElementFactory : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - std::unique_ptr m_elem; - operator bool() const {return m_elem.operator bool();} -}; - -struct IVectorElement : IElement {Delete _d2;}; -struct VectorElementFactory : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - std::unique_ptr m_elem; - operator bool() const {return m_elem.operator bool();} -}; - -struct IColorElement : IElement {Delete _d2;}; -struct ColorElementFactory : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - std::unique_ptr m_elem; - operator bool() const {return m_elem.operator bool();} -}; - -struct IModVectorElement : IElement {Delete _d2;}; -struct ModVectorElementFactory : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - std::unique_ptr m_elem; - operator bool() const {return m_elem.operator bool();} -}; - -struct IEmitterElement : IElement {Delete _d2;}; -struct EmitterElementFactory : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - std::unique_ptr m_elem; - operator bool() const {return m_elem.operator bool();} -}; - -struct IUVElement : IElement -{ - Delete _d2; - virtual void gatherDependencies(std::vector& pathsOut) const=0; -}; - -struct BoolHelper : IElement -{ - AT_DECL_EXPLICIT_DNA_YAML - bool value = false; - operator bool() const {return value;} - BoolHelper& operator=(bool val) {value = val; return *this;} - const char* ClassID() const {return "BoolHelper";} -}; - -struct RELifetimeTween : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "LFTW";} -}; - -struct REConstant : IRealElement -{ - AT_DECL_EXPLICIT_DNA_YAML - Value val; - const char* ClassID() const {return "CNST";} -}; - -struct RETimeChain : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory a; - RealElementFactory b; - IntElementFactory thresholdFrame; - const char* ClassID() const {return "CHAN";} -}; - -struct REAdd : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "ADD_";} -}; - -struct REClamp : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory min; - RealElementFactory max; - RealElementFactory val; - const char* ClassID() const {return "CLMP";} -}; - -struct REKeyframeEmitter : IRealElement -{ - AT_DECL_DNA_YAML - Value percentageTween; - Value unk1; - Value loop; - Value unk2; - Value loopEnd; - Value loopStart; - Value count; - Vector keys; - const char* ClassID() const {return percentageTween ? "KEYP" : "KEYE";} -}; - -struct REInitialRandom : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "IRND";} -}; - -struct RERandom : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "RAND";} + +struct REVectorZToReal : IRealElement { + AT_DECL_DNA_YAML + VectorElementFactory vec; + const char* ClassID() const { return "VZTR"; } +}; + +struct RECEXT : IRealElement { + AT_DECL_DNA_YAML + IntElementFactory index; + const char* ClassID() const { return "CEXT"; } +}; + +struct REIntTimesReal : IRealElement { + AT_DECL_DNA_YAML + IntElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "ITRL"; } +}; + +struct IEKeyframeEmitter : IIntElement { + AT_DECL_DNA_YAML + Value percentageTween; + Value unk1; + Value loop; + Value unk2; + Value loopEnd; + Value loopStart; + Value count; + Vector keys; + const char* ClassID() const { return percentageTween ? "KEYP" : "KEYE"; } }; -struct REMultiply : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "MULT";} +struct IEDeath : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory passthrough; + IntElementFactory thresholdFrame; + const char* ClassID() const { return "DETH"; } }; -struct REPulse : IRealElement -{ - AT_DECL_DNA_YAML - IntElementFactory aDuration; - IntElementFactory bDuration; - RealElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "PULS";} +struct IEClamp : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory min; + IntElementFactory max; + IntElementFactory val; + const char* ClassID() const { return "CLMP"; } }; -struct RETimeScale : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory dv; - const char* ClassID() const {return "SCAL";} +struct IETimeChain : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory a; + IntElementFactory b; + IntElementFactory thresholdFrame; + const char* ClassID() const { return "CHAN"; } }; -struct RELifetimePercent : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory percent; - const char* ClassID() const {return "RLPT";} +struct IEAdd : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory a; + IntElementFactory b; + const char* ClassID() const { return "ADD_"; } }; -struct RESineWave : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory frequency; - RealElementFactory amplitude; - RealElementFactory phase; - const char* ClassID() const {return "SINE";} +struct IEConstant : IIntElement { + AT_DECL_EXPLICIT_DNA_YAML + Value val; + const char* ClassID() const { return "CNST"; } }; -struct REInitialSwitch : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "ISWT";} +struct IEImpulse : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory val; + const char* ClassID() const { return "IMPL"; } }; -struct RECompareLessThan : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory ca; - RealElementFactory cb; - RealElementFactory pass; - RealElementFactory fail; - const char* ClassID() const {return "CLTN";} +struct IELifetimePercent : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory percent; + const char* ClassID() const { return "ILPT"; } }; -struct RECompareEquals : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory ca; - RealElementFactory cb; - RealElementFactory pass; - RealElementFactory fail; - const char* ClassID() const {return "CEQL";} +struct IEInitialRandom : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory a; + IntElementFactory b; + const char* ClassID() const { return "IRND"; } }; -struct REParticleAdvanceParam1 : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PAP1";} +struct IEPulse : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory aDuration; + IntElementFactory bDuration; + IntElementFactory a; + IntElementFactory b; + const char* ClassID() const { return "PULS"; } }; -struct REParticleAdvanceParam2 : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PAP2";} +struct IEMultiply : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory a; + IntElementFactory b; + const char* ClassID() const { return "MULT"; } }; -struct REParticleAdvanceParam3 : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PAP3";} +struct IESampleAndHold : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory val; + IntElementFactory waitMin; + IntElementFactory waitMax; + const char* ClassID() const { return "SPAH"; } }; -struct REParticleAdvanceParam4 : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PAP4";} +struct IERandom : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory a; + IntElementFactory b; + const char* ClassID() const { return "RAND"; } }; -struct REParticleAdvanceParam5 : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PAP5";} +struct IETimeScale : IIntElement { + AT_DECL_DNA_YAML + RealElementFactory dv; + const char* ClassID() const { return "TSCL"; } }; -struct REParticleAdvanceParam6 : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PAP6";} +struct IEGTCP : IIntElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "GTCP"; } }; -struct REParticleAdvanceParam7 : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PAP7";} +struct IEModulo : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory a; + IntElementFactory b; + const char* ClassID() const { return "MODU"; } }; -struct REParticleAdvanceParam8 : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PAP8";} +struct IESubtract : IIntElement { + AT_DECL_DNA_YAML + IntElementFactory direction; + IntElementFactory baseRadius; + const char* ClassID() const { return "SUB_"; } }; -struct REParticleSizeOrLineLength : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PSLL";} +struct VECone : IVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory a; + RealElementFactory b; + const char* ClassID() const { return "CONE"; } }; -struct REParticleRotationOrLineWidth : IRealElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PRLW";} +struct VETimeChain : IVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory a; + VectorElementFactory b; + IntElementFactory thresholdFrame; + const char* ClassID() const { return "CHAN"; } }; -struct RESubtract : IRealElement -{ - AT_DECL_DNA_YAML - RealElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "SUB_";} +struct VEAngleCone : IVectorElement { + AT_DECL_DNA_YAML + RealElementFactory angleXBias; + RealElementFactory angleYBias; + RealElementFactory angleXRange; + RealElementFactory angleYRange; + RealElementFactory magnitude; + const char* ClassID() const { return "ANGC"; } }; -struct REVectorMagnitude : IRealElement -{ - AT_DECL_DNA_YAML - VectorElementFactory vec; - const char* ClassID() const {return "VMAG";} +struct VEAdd : IVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory a; + VectorElementFactory b; + const char* ClassID() const { return "ADD_"; } }; -struct REVectorXToReal : IRealElement -{ - AT_DECL_DNA_YAML - VectorElementFactory vec; - const char* ClassID() const {return "VXTR";} +struct VECircleCluster : IVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory circleOffset; + VectorElementFactory circleNormal; + IntElementFactory cycleFrames; + RealElementFactory randomFactor; + const char* ClassID() const { return "CCLU"; } }; -struct REVectorYToReal : IRealElement -{ - AT_DECL_DNA_YAML - VectorElementFactory vec; - const char* ClassID() const {return "VYTR";} +struct VEConstant : IVectorElement { + AT_DECL_EXPLICIT_DNA_YAML + RealElementFactory comps[3]; + const char* ClassID() const { return "CNST"; } }; -struct REVectorZToReal : IRealElement -{ - AT_DECL_DNA_YAML - VectorElementFactory vec; - const char* ClassID() const {return "VZTR";} +struct VECircle : IVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory circleOffset; + VectorElementFactory circleNormal; + RealElementFactory angleConstant; + RealElementFactory angleLinear; + RealElementFactory circleRadius; + const char* ClassID() const { return "CIRC"; } }; -struct RECEXT : IRealElement -{ - AT_DECL_DNA_YAML - IntElementFactory index; - const char* ClassID() const {return "CEXT";} +struct VEKeyframeEmitter : IVectorElement { + AT_DECL_DNA_YAML + Value percentageTween; + Value unk1; + Value loop; + Value unk2; + Value loopEnd; + Value loopStart; + Value count; + Vector keys; + const char* ClassID() const { return percentageTween ? "KEYP" : "KEYE"; } }; -struct REIntTimesReal : IRealElement -{ - AT_DECL_DNA_YAML - IntElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "ITRL";} +struct VEMultiply : IVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory a; + VectorElementFactory b; + const char* ClassID() const { return "MULT"; } }; -struct IEKeyframeEmitter : IIntElement -{ - AT_DECL_DNA_YAML - Value percentageTween; - Value unk1; - Value loop; - Value unk2; - Value loopEnd; - Value loopStart; - Value count; - Vector keys; - const char* ClassID() const {return percentageTween ? "KEYP" : "KEYE";} +struct VERealToVector : IVectorElement { + AT_DECL_DNA_YAML + RealElementFactory a; + const char* ClassID() const { return "RTOV"; } }; -struct IEDeath : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory passthrough; - IntElementFactory thresholdFrame; - const char* ClassID() const {return "DETH";} +struct VEPulse : IVectorElement { + AT_DECL_DNA_YAML + IntElementFactory aDuration; + IntElementFactory bDuration; + VectorElementFactory a; + VectorElementFactory b; + const char* ClassID() const { return "PULS"; } }; -struct IEClamp : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory min; - IntElementFactory max; - IntElementFactory val; - const char* ClassID() const {return "CLMP";} +struct VEParticleVelocity : IVectorElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PVEL"; } }; -struct IETimeChain : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory a; - IntElementFactory b; - IntElementFactory thresholdFrame; - const char* ClassID() const {return "CHAN";} +struct VESPOS : IVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory a; + const char* ClassID() const { return "SPOS"; } }; -struct IEAdd : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory a; - IntElementFactory b; - const char* ClassID() const {return "ADD_";} +struct VEPLCO : IVectorElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PLCO"; } }; -struct IEConstant : IIntElement -{ - AT_DECL_EXPLICIT_DNA_YAML - Value val; - const char* ClassID() const {return "CNST";} +struct VEPLOC : IVectorElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PLOC"; } }; -struct IEImpulse : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory val; - const char* ClassID() const {return "IMPL";} +struct VEPSOR : IVectorElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PSOR"; } }; -struct IELifetimePercent : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory percent; - const char* ClassID() const {return "ILPT";} -}; +struct VEPSOF : IVectorElement { + AT_DECL_DNA_YAML + const char* ClassID() const { return "PSOF"; } +}; + +struct CEKeyframeEmitter : IColorElement { + AT_DECL_DNA_YAML + Value percentageTween; + Value unk1; + Value loop; + Value unk2; + Value loopEnd; + Value loopStart; + Value count; + Vector keys; + const char* ClassID() const { return percentageTween ? "KEYP" : "KEYE"; } +}; -struct IEInitialRandom : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory a; - IntElementFactory b; - const char* ClassID() const {return "IRND";} -}; +struct CEConstant : IColorElement { + AT_DECL_EXPLICIT_DNA_YAML + RealElementFactory comps[4]; + const char* ClassID() const { return "CNST"; } +}; -struct IEPulse : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory aDuration; - IntElementFactory bDuration; - IntElementFactory a; - IntElementFactory b; - const char* ClassID() const {return "PULS";} -}; - -struct IEMultiply : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory a; - IntElementFactory b; - const char* ClassID() const {return "MULT";} -}; - -struct IESampleAndHold : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory val; - IntElementFactory waitMin; - IntElementFactory waitMax; - const char* ClassID() const {return "SPAH";} -}; - -struct IERandom : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory a; - IntElementFactory b; - const char* ClassID() const {return "RAND";} -}; - -struct IETimeScale : IIntElement -{ - AT_DECL_DNA_YAML - RealElementFactory dv; - const char* ClassID() const {return "TSCL";} -}; - -struct IEGTCP : IIntElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "GTCP";} -}; - -struct IEModulo : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory a; - IntElementFactory b; - const char* ClassID() const {return "MODU";} -}; - -struct IESubtract : IIntElement -{ - AT_DECL_DNA_YAML - IntElementFactory direction; - IntElementFactory baseRadius; - const char* ClassID() const {return "SUB_";} -}; - -struct VECone : IVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory a; - RealElementFactory b; - const char* ClassID() const {return "CONE";} -}; - -struct VETimeChain : IVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory a; - VectorElementFactory b; - IntElementFactory thresholdFrame; - const char* ClassID() const {return "CHAN";} -}; - -struct VEAngleCone : IVectorElement -{ - AT_DECL_DNA_YAML - RealElementFactory angleXBias; - RealElementFactory angleYBias; - RealElementFactory angleXRange; - RealElementFactory angleYRange; - RealElementFactory magnitude; - const char* ClassID() const {return "ANGC";} -}; - -struct VEAdd : IVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory a; - VectorElementFactory b; - const char* ClassID() const {return "ADD_";} +struct CETimeChain : IColorElement { + AT_DECL_DNA_YAML + ColorElementFactory a; + ColorElementFactory b; + IntElementFactory thresholdFrame; + const char* ClassID() const { return "CHAN"; } }; - -struct VECircleCluster : IVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory circleOffset; - VectorElementFactory circleNormal; - IntElementFactory cycleFrames; - RealElementFactory randomFactor; - const char* ClassID() const {return "CCLU";} + +struct CEFadeEnd : IColorElement { + AT_DECL_DNA_YAML + ColorElementFactory a; + ColorElementFactory b; + RealElementFactory startFrame; + RealElementFactory endFrame; + const char* ClassID() const { return "CFDE"; } +}; + +struct CEFade : IColorElement { + AT_DECL_DNA_YAML + ColorElementFactory a; + ColorElementFactory b; + RealElementFactory endFrame; + const char* ClassID() const { return "FADE"; } }; - -struct VEConstant : IVectorElement -{ - AT_DECL_EXPLICIT_DNA_YAML - RealElementFactory comps[3]; - const char* ClassID() const {return "CNST";} -}; - -struct VECircle : IVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory circleOffset; - VectorElementFactory circleNormal; - RealElementFactory angleConstant; - RealElementFactory angleLinear; - RealElementFactory circleRadius; - const char* ClassID() const {return "CIRC";} -}; - -struct VEKeyframeEmitter : IVectorElement -{ - AT_DECL_DNA_YAML - Value percentageTween; - Value unk1; - Value loop; - Value unk2; - Value loopEnd; - Value loopStart; - Value count; - Vector keys; - const char* ClassID() const {return percentageTween ? "KEYP" : "KEYE";} -}; - -struct VEMultiply : IVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory a; - VectorElementFactory b; - const char* ClassID() const {return "MULT";} -}; - -struct VERealToVector : IVectorElement -{ - AT_DECL_DNA_YAML - RealElementFactory a; - const char* ClassID() const {return "RTOV";} -}; - -struct VEPulse : IVectorElement -{ - AT_DECL_DNA_YAML - IntElementFactory aDuration; - IntElementFactory bDuration; - VectorElementFactory a; - VectorElementFactory b; - const char* ClassID() const {return "PULS";} -}; - -struct VEParticleVelocity : IVectorElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PVEL";} -}; - -struct VESPOS : IVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory a; - const char* ClassID() const {return "SPOS";} -}; - -struct VEPLCO : IVectorElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PLCO";} -}; - -struct VEPLOC : IVectorElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PLOC";} -}; - -struct VEPSOR : IVectorElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PSOR";} -}; - -struct VEPSOF : IVectorElement -{ - AT_DECL_DNA_YAML - const char* ClassID() const {return "PSOF";} -}; - -struct CEKeyframeEmitter : IColorElement -{ - AT_DECL_DNA_YAML - Value percentageTween; - Value unk1; - Value loop; - Value unk2; - Value loopEnd; - Value loopStart; - Value count; - Vector keys; - const char* ClassID() const {return percentageTween ? "KEYP" : "KEYE";} -}; - -struct CEConstant : IColorElement -{ - AT_DECL_EXPLICIT_DNA_YAML - RealElementFactory comps[4]; - const char* ClassID() const {return "CNST";} -}; - -struct CETimeChain : IColorElement -{ - AT_DECL_DNA_YAML - ColorElementFactory a; - ColorElementFactory b; - IntElementFactory thresholdFrame; - const char* ClassID() const {return "CHAN";} -}; - -struct CEFadeEnd : IColorElement -{ - AT_DECL_DNA_YAML - ColorElementFactory a; - ColorElementFactory b; - RealElementFactory startFrame; - RealElementFactory endFrame; - const char* ClassID() const {return "CFDE";} -}; - -struct CEFade : IColorElement -{ - AT_DECL_DNA_YAML - ColorElementFactory a; - ColorElementFactory b; - RealElementFactory endFrame; - const char* ClassID() const {return "FADE";} -}; - -struct CEPulse : IColorElement -{ - AT_DECL_DNA_YAML - IntElementFactory aDuration; - IntElementFactory bDuration; - ColorElementFactory a; - ColorElementFactory b; - const char* ClassID() const {return "PULS";} -}; - -struct MVEImplosion : IModVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory implodePoint; - RealElementFactory velocityScale; - RealElementFactory maxRadius; - RealElementFactory minRadius; - BoolHelper enableMinRadius; - const char* ClassID() const {return "IMPL";} -}; - -struct MVEExponentialImplosion : IModVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory implodePoint; - RealElementFactory velocityScale; - RealElementFactory maxRadius; - RealElementFactory minRadius; - BoolHelper enableMinRadius; - const char* ClassID() const {return "EMPL";} -}; - -struct MVETimeChain : IModVectorElement -{ - AT_DECL_DNA_YAML - ModVectorElementFactory a; - ModVectorElementFactory b; - IntElementFactory thresholdFrame; - const char* ClassID() const {return "CHAN";} -}; - -struct MVEBounce : IModVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory planePoint; - VectorElementFactory planeNormal; - RealElementFactory friction; - RealElementFactory restitution; - BoolHelper dieOnPenetrate; - const char* ClassID() const {return "BNCE";} -}; - -struct MVEConstant : IModVectorElement -{ - AT_DECL_EXPLICIT_DNA_YAML - RealElementFactory comps[3]; - const char* ClassID() const {return "CNST";} -}; - -struct MVEGravity : IModVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory acceleration; - const char* ClassID() const {return "GRAV";} -}; - -struct MVEExplode : IModVectorElement -{ - AT_DECL_DNA_YAML - RealElementFactory impulseMagnitude; - RealElementFactory falloffFactor; - const char* ClassID() const {return "EXPL";} -}; - -struct MVESetPosition : IModVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory position; - const char* ClassID() const {return "SPOS";} -}; - -struct MVELinearImplosion : IModVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory implodePoint; - RealElementFactory velocityScale; - RealElementFactory maxRadius; - RealElementFactory minRadius; - BoolHelper enableMinRadius; - const char* ClassID() const {return "LMPL";} -}; - -struct MVEPulse : IModVectorElement -{ - AT_DECL_DNA_YAML - IntElementFactory aDuration; - IntElementFactory bDuration; - ModVectorElementFactory a; - ModVectorElementFactory b; - const char* ClassID() const {return "PULS";} -}; - -struct MVEWind : IModVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory windVelocity; - RealElementFactory factor; - const char* ClassID() const {return "WIND";} -}; - -struct MVESwirl : IModVectorElement -{ - AT_DECL_DNA_YAML - VectorElementFactory helixPoint; - VectorElementFactory curveBinormal; - RealElementFactory filterGain; - RealElementFactory tangentialVelocity; - const char* ClassID() const {return "SWRL";} -}; - -struct EESimpleEmitter : IEmitterElement -{ - AT_DECL_DNA_YAML - VectorElementFactory position; - VectorElementFactory velocity; - const char* ClassID() const {return "SEMR";} -}; - -struct VESphere : IEmitterElement -{ - AT_DECL_DNA_YAML - VectorElementFactory sphereOrigin; - RealElementFactory sphereRadius; - RealElementFactory magnitude; - const char* ClassID() const {return "SPHE";} -}; - -struct VEAngleSphere : IEmitterElement -{ - AT_DECL_DNA_YAML - VectorElementFactory sphereOrigin; - RealElementFactory sphereRadius; - RealElementFactory magnitude; - RealElementFactory angleXBias; - RealElementFactory angleYBias; - RealElementFactory angleXRange; - RealElementFactory angleYRange; - const char* ClassID() const {return "ASPH";} -}; - -struct EESimpleEmitterTR : EESimpleEmitter -{ - AT_DECL_EXPLICIT_DNA_YAML - const char* ClassID() const {return "SETR";} + +struct CEPulse : IColorElement { + AT_DECL_DNA_YAML + IntElementFactory aDuration; + IntElementFactory bDuration; + ColorElementFactory a; + ColorElementFactory b; + const char* ClassID() const { return "PULS"; } +}; + +struct MVEImplosion : IModVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory implodePoint; + RealElementFactory velocityScale; + RealElementFactory maxRadius; + RealElementFactory minRadius; + BoolHelper enableMinRadius; + const char* ClassID() const { return "IMPL"; } +}; + +struct MVEExponentialImplosion : IModVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory implodePoint; + RealElementFactory velocityScale; + RealElementFactory maxRadius; + RealElementFactory minRadius; + BoolHelper enableMinRadius; + const char* ClassID() const { return "EMPL"; } +}; + +struct MVETimeChain : IModVectorElement { + AT_DECL_DNA_YAML + ModVectorElementFactory a; + ModVectorElementFactory b; + IntElementFactory thresholdFrame; + const char* ClassID() const { return "CHAN"; } +}; + +struct MVEBounce : IModVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory planePoint; + VectorElementFactory planeNormal; + RealElementFactory friction; + RealElementFactory restitution; + BoolHelper dieOnPenetrate; + const char* ClassID() const { return "BNCE"; } +}; + +struct MVEConstant : IModVectorElement { + AT_DECL_EXPLICIT_DNA_YAML + RealElementFactory comps[3]; + const char* ClassID() const { return "CNST"; } +}; + +struct MVEGravity : IModVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory acceleration; + const char* ClassID() const { return "GRAV"; } +}; + +struct MVEExplode : IModVectorElement { + AT_DECL_DNA_YAML + RealElementFactory impulseMagnitude; + RealElementFactory falloffFactor; + const char* ClassID() const { return "EXPL"; } +}; + +struct MVESetPosition : IModVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory position; + const char* ClassID() const { return "SPOS"; } +}; + +struct MVELinearImplosion : IModVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory implodePoint; + RealElementFactory velocityScale; + RealElementFactory maxRadius; + RealElementFactory minRadius; + BoolHelper enableMinRadius; + const char* ClassID() const { return "LMPL"; } +}; + +struct MVEPulse : IModVectorElement { + AT_DECL_DNA_YAML + IntElementFactory aDuration; + IntElementFactory bDuration; + ModVectorElementFactory a; + ModVectorElementFactory b; + const char* ClassID() const { return "PULS"; } +}; + +struct MVEWind : IModVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory windVelocity; + RealElementFactory factor; + const char* ClassID() const { return "WIND"; } +}; + +struct MVESwirl : IModVectorElement { + AT_DECL_DNA_YAML + VectorElementFactory helixPoint; + VectorElementFactory curveBinormal; + RealElementFactory filterGain; + RealElementFactory tangentialVelocity; + const char* ClassID() const { return "SWRL"; } +}; + +struct EESimpleEmitter : IEmitterElement { + AT_DECL_DNA_YAML + VectorElementFactory position; + VectorElementFactory velocity; + const char* ClassID() const { return "SEMR"; } +}; + +struct VESphere : IEmitterElement { + AT_DECL_DNA_YAML + VectorElementFactory sphereOrigin; + RealElementFactory sphereRadius; + RealElementFactory magnitude; + const char* ClassID() const { return "SPHE"; } +}; + +struct VEAngleSphere : IEmitterElement { + AT_DECL_DNA_YAML + VectorElementFactory sphereOrigin; + RealElementFactory sphereRadius; + RealElementFactory magnitude; + RealElementFactory angleXBias; + RealElementFactory angleYBias; + RealElementFactory angleXRange; + RealElementFactory angleYRange; + const char* ClassID() const { return "ASPH"; } +}; + +struct EESimpleEmitterTR : EESimpleEmitter { + AT_DECL_EXPLICIT_DNA_YAML + const char* ClassID() const { return "SETR"; } }; template -struct UVEConstant : IUVElement -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA - CastIDToZero tex; - const char* ClassID() const {return "CNST";} +struct UVEConstant : IUVElement { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + CastIDToZero tex; + const char* ClassID() const { return "CNST"; } - void gatherDependencies(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(tex, pathsOut); - } + void gatherDependencies(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(tex, pathsOut); + } }; template -struct UVEAnimTexture : IUVElement -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA - CastIDToZero tex; - IntElementFactory tileW; - IntElementFactory tileH; - IntElementFactory strideW; - IntElementFactory strideH; - IntElementFactory cycleFrames; - Value loop = false; - const char* ClassID() const {return "ATEX";} +struct UVEAnimTexture : IUVElement { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + CastIDToZero tex; + IntElementFactory tileW; + IntElementFactory tileH; + IntElementFactory strideW; + IntElementFactory strideH; + IntElementFactory cycleFrames; + Value loop = false; + const char* ClassID() const { return "ATEX"; } - void gatherDependencies(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(tex, pathsOut); - } + void gatherDependencies(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(tex, pathsOut); + } }; template -struct UVElementFactory : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA - DNAFourCC m_type; - std::unique_ptr m_elem; - operator bool() const {return m_elem.operator bool();} +struct UVElementFactory : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + DNAFourCC m_type; + std::unique_ptr m_elem; + operator bool() const { return m_elem.operator bool(); } }; template -struct SpawnSystemKeyframeData : BigDNA -{ +struct SpawnSystemKeyframeData : BigDNA { + Value a; + Value b; + Value endFrame; + Value d; + + struct SpawnSystemKeyframeInfo : BigDNA { + IDType id; Value a; Value b; - Value endFrame; - Value d; - - struct SpawnSystemKeyframeInfo : BigDNA - { - IDType id; - Value a; - Value b; - Value c; - AT_DECL_EXPLICIT_DNA_YAML - }; - - std::vector>> spawns; - + Value c; AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA + }; - operator bool() const {return spawns.size() != 0;} + std::vector>> spawns; - void gatherDependencies(std::vector& pathsOut) const - { - for (const auto& p : spawns) - for (const SpawnSystemKeyframeInfo& info : p.second) - g_curSpec->flattenDependencies(info.id, pathsOut); - } + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + + operator bool() const { return spawns.size() != 0; } + + void gatherDependencies(std::vector& pathsOut) const { + for (const auto& p : spawns) + for (const SpawnSystemKeyframeInfo& info : p.second) + g_curSpec->flattenDependencies(info.id, pathsOut); + } }; template -struct ChildResourceFactory : BigDNA -{ - IDType id; - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA - operator bool() const {return id.operator bool();} +struct ChildResourceFactory : BigDNA { + IDType id; + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + operator bool() const { return id.operator bool(); } }; -} - +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/RigInverter.cpp b/DataSpec/DNACommon/RigInverter.cpp index 37e8dba67..9ee111fd2 100644 --- a/DataSpec/DNACommon/RigInverter.cpp +++ b/DataSpec/DNACommon/RigInverter.cpp @@ -4,177 +4,144 @@ #include "DataSpec/DNAMP3/CINF.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAANIM -{ +namespace DataSpec::DNAANIM { template RigInverter::Bone::Bone(const CINFType& cinf, const typename CINFType::Bone& origBone) -: m_origBone(origBone) -{ - atUint32 parentIdx = cinf.getInternalBoneIdxFromId(origBone.parentId); - zeus::CVector3f boneOrigin(origBone.origin); - zeus::CVector3f naturalTail = boneOrigin + zeus::CVector3f{0.f, 0.5f, 0.f}; - if (parentIdx != -1) - { - const typename CINFType::Bone& pBone = cinf.bones[parentIdx]; - m_parentDelta = boneOrigin - zeus::CVector3f(pBone.origin); +: m_origBone(origBone) { + atUint32 parentIdx = cinf.getInternalBoneIdxFromId(origBone.parentId); + zeus::CVector3f boneOrigin(origBone.origin); + zeus::CVector3f naturalTail = boneOrigin + zeus::CVector3f{0.f, 0.5f, 0.f}; + if (parentIdx != -1) { + const typename CINFType::Bone& pBone = cinf.bones[parentIdx]; + m_parentDelta = boneOrigin - zeus::CVector3f(pBone.origin); + } + + size_t actualChildren = 0; + for (atUint32 chId : origBone.linked) { + if (chId == origBone.parentId) + continue; + atUint32 chIdx = cinf.getInternalBoneIdxFromId(chId); + if (chIdx != -1) + ++actualChildren; + } + + const std::string* bName = cinf.getBoneNameFromId(origBone.id); + bool isLCTR = false; + if (bName) + isLCTR = bName->find("_LCTR") != std::string::npos; + + if (parentIdx == -1) { + /* Root will always use +Y tail */ + m_tail = naturalTail; + } else if (actualChildren) { + /* Position tail to average of children */ + for (atUint32 chId : origBone.linked) { + if (chId == origBone.parentId) + continue; + atUint32 chIdx = cinf.getInternalBoneIdxFromId(chId); + if (chIdx != -1) { + const typename CINFType::Bone& chBone = cinf.bones[chIdx]; + m_tail += chBone.origin; + } } - - size_t actualChildren = 0; - for (atUint32 chId : origBone.linked) - { - if (chId == origBone.parentId) - continue; - atUint32 chIdx = cinf.getInternalBoneIdxFromId(chId); - if (chIdx != -1) - ++actualChildren; + m_tail /= zeus::CVector3f(float(actualChildren)); + if ((m_tail - boneOrigin).magSquared() < 0.001f) + m_tail = naturalTail; + else if (isLCTR) + m_tail = boneOrigin + zeus::CVector3f{0.f, 1.0f, 0.f} * (m_tail - boneOrigin).magnitude(); + } else if (parentIdx != -1) { + /* Extrapolate by delta with parent */ + m_tail = boneOrigin + m_parentDelta; + float deltaMag = m_parentDelta.magnitude(); + if (deltaMag < 0.001f) { + deltaMag = 0.5f; + m_tail = naturalTail; + } else if (deltaMag > 0.5f) { + /* Extreme bones capped to +0.5 value */ + deltaMag = 0.5f; + m_tail = boneOrigin + m_parentDelta.normalized() * 0.5f; } - const std::string* bName = cinf.getBoneNameFromId(origBone.id); - bool isLCTR = false; - if (bName) - isLCTR = bName->find("_LCTR") != std::string::npos; - - if (parentIdx == -1) - { - /* Root will always use +Y tail */ - m_tail = naturalTail; - } - else if (actualChildren) - { - /* Position tail to average of children */ - for (atUint32 chId : origBone.linked) - { - if (chId == origBone.parentId) - continue; - atUint32 chIdx = cinf.getInternalBoneIdxFromId(chId); - if (chIdx != -1) - { - const typename CINFType::Bone& chBone = cinf.bones[chIdx]; - m_tail += chBone.origin; - } - } - m_tail /= zeus::CVector3f(float(actualChildren)); - if ((m_tail - boneOrigin).magSquared() < 0.001f) - m_tail = naturalTail; - else if (isLCTR) - m_tail = boneOrigin + zeus::CVector3f{0.f, 1.0f, 0.f} * (m_tail - boneOrigin).magnitude(); - } - else if (parentIdx != -1) - { - /* Extrapolate by delta with parent */ - m_tail = boneOrigin + m_parentDelta; - float deltaMag = m_parentDelta.magnitude(); - if (deltaMag < 0.001f) - { - deltaMag = 0.5f; - m_tail = naturalTail; - } - else if (deltaMag > 0.5f) - { - /* Extreme bones capped to +0.5 value */ - deltaMag = 0.5f; - m_tail = boneOrigin + m_parentDelta.normalized() * 0.5f; - } - - if (isLCTR) - m_tail = boneOrigin + zeus::CVector3f{0.f, 1.0f, 0.f} * deltaMag; - } - else - { - /* Fallback to +Y tail */ - m_tail = naturalTail; - } + if (isLCTR) + m_tail = boneOrigin + zeus::CVector3f{0.f, 1.0f, 0.f} * deltaMag; + } else { + /* Fallback to +Y tail */ + m_tail = naturalTail; + } } template -RigInverter::RigInverter(const CINFType& cinf) -: m_cinf(cinf) -{ - m_bones.reserve(cinf.bones.size()); - for (const typename CINFType::Bone& b : cinf.bones) - m_bones.emplace_back(cinf, b); +RigInverter::RigInverter(const CINFType& cinf) : m_cinf(cinf) { + m_bones.reserve(cinf.bones.size()); + for (const typename CINFType::Bone& b : cinf.bones) + m_bones.emplace_back(cinf, b); } template RigInverter::RigInverter(const CINFType& cinf, - const std::unordered_map& matrices) -: m_cinf(cinf) -{ - m_bones.reserve(cinf.bones.size()); - for (const typename CINFType::Bone& b : cinf.bones) - { - m_bones.emplace_back(cinf, b); + const std::unordered_map& matrices) +: m_cinf(cinf) { + m_bones.reserve(cinf.bones.size()); + for (const typename CINFType::Bone& b : cinf.bones) { + m_bones.emplace_back(cinf, b); - const std::string* name = cinf.getBoneNameFromId(b.id); - if (name) - { - auto search = matrices.find(*name); - if (search != matrices.cend()) - { - zeus::CMatrix3f boneMtx(search->second[0], - search->second[1], - search->second[2]); - m_bones.back().m_inverter = boneMtx.transposed(); - m_bones.back().m_restorer = boneMtx; - } - } + const std::string* name = cinf.getBoneNameFromId(b.id); + if (name) { + auto search = matrices.find(*name); + if (search != matrices.cend()) { + zeus::CMatrix3f boneMtx(search->second[0], search->second[1], search->second[2]); + m_bones.back().m_inverter = boneMtx.transposed(); + m_bones.back().m_restorer = boneMtx; + } } + } } template -zeus::CQuaternion -RigInverter::invertRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const -{ - for (const Bone& b : m_bones) - if (b.m_origBone.id == boneId) - return b.m_restorer * zeus::CMatrix3f(origRot) * b.m_inverter; - return origRot; -} - -template -zeus::CVector3f -RigInverter::invertPosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const -{ - for (const Bone& b : m_bones) - if (b.m_origBone.id == boneId) - { - zeus::CVector3f localPos = origPos; - if (subDelta) - localPos -= b.m_parentDelta; - return b.m_restorer * localPos; - } - return origPos; +zeus::CQuaternion RigInverter::invertRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const { + for (const Bone& b : m_bones) + if (b.m_origBone.id == boneId) + return b.m_restorer * zeus::CMatrix3f(origRot) * b.m_inverter; + return origRot; } template -zeus::CQuaternion -RigInverter::restoreRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const -{ - for (const Bone& b : m_bones) - if (b.m_origBone.id == boneId) - return b.m_inverter * zeus::CMatrix3f(origRot) * b.m_restorer; - return origRot; +zeus::CVector3f RigInverter::invertPosition(atUint32 boneId, const zeus::CVector3f& origPos, + bool subDelta) const { + for (const Bone& b : m_bones) + if (b.m_origBone.id == boneId) { + zeus::CVector3f localPos = origPos; + if (subDelta) + localPos -= b.m_parentDelta; + return b.m_restorer * localPos; + } + return origPos; } template -zeus::CVector3f -RigInverter::restorePosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const -{ - for (const Bone& b : m_bones) - if (b.m_origBone.id == boneId) - { - zeus::CVector3f localPos = b.m_inverter * origPos; - if (subDelta) - localPos += b.m_parentDelta; - return localPos; - } - return origPos; +zeus::CQuaternion RigInverter::restoreRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const { + for (const Bone& b : m_bones) + if (b.m_origBone.id == boneId) + return b.m_inverter * zeus::CMatrix3f(origRot) * b.m_restorer; + return origRot; +} + +template +zeus::CVector3f RigInverter::restorePosition(atUint32 boneId, const zeus::CVector3f& origPos, + bool subDelta) const { + for (const Bone& b : m_bones) + if (b.m_origBone.id == boneId) { + zeus::CVector3f localPos = b.m_inverter * origPos; + if (subDelta) + localPos += b.m_parentDelta; + return localPos; + } + return origPos; } template class RigInverter; template class RigInverter; template class RigInverter; -} +} // namespace DataSpec::DNAANIM diff --git a/DataSpec/DNACommon/RigInverter.hpp b/DataSpec/DNACommon/RigInverter.hpp index 26288d30d..a5fbfb503 100644 --- a/DataSpec/DNACommon/RigInverter.hpp +++ b/DataSpec/DNACommon/RigInverter.hpp @@ -5,40 +5,37 @@ #include "zeus/CQuaternion.hpp" #include "hecl/hecl.hpp" -namespace DataSpec::DNAANIM -{ +namespace DataSpec::DNAANIM { /** One-shot process to invert CINF armature into connected rig, * inverting rotations/translations of ANIM data to match */ template -class RigInverter -{ +class RigInverter { public: - struct Bone - { - const typename CINFType::Bone& m_origBone; - zeus::CMatrix3f m_inverter; - zeus::CMatrix3f m_restorer; - zeus::CVector3f m_tail; - zeus::CVector3f m_parentDelta; - Bone(const CINFType& cinf, const typename CINFType::Bone& origBone); - }; + struct Bone { + const typename CINFType::Bone& m_origBone; + zeus::CMatrix3f m_inverter; + zeus::CMatrix3f m_restorer; + zeus::CVector3f m_tail; + zeus::CVector3f m_parentDelta; + Bone(const CINFType& cinf, const typename CINFType::Bone& origBone); + }; + private: - const CINFType& m_cinf; - std::vector m_bones; + const CINFType& m_cinf; + std::vector m_bones; + public: - RigInverter(const CINFType& cinf); - RigInverter(const CINFType& cinf, - const std::unordered_map& matrices); - const CINFType& getCINF() const {return m_cinf;} - const std::vector& getBones() const {return m_bones;} + RigInverter(const CINFType& cinf); + RigInverter(const CINFType& cinf, const std::unordered_map& matrices); + const CINFType& getCINF() const { return m_cinf; } + const std::vector& getBones() const { return m_bones; } - zeus::CQuaternion invertRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const; - zeus::CVector3f invertPosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const; + zeus::CQuaternion invertRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const; + zeus::CVector3f invertPosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const; - zeus::CQuaternion restoreRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const; - zeus::CVector3f restorePosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const; + zeus::CQuaternion restoreRotation(atUint32 boneId, const zeus::CQuaternion& origRot) const; + zeus::CVector3f restorePosition(atUint32 boneId, const zeus::CVector3f& origPos, bool subDelta) const; }; -} - +} // namespace DataSpec::DNAANIM diff --git a/DataSpec/DNACommon/SAVWCommon.hpp b/DataSpec/DNACommon/SAVWCommon.hpp index ac77430ee..f51563f28 100644 --- a/DataSpec/DNACommon/SAVWCommon.hpp +++ b/DataSpec/DNACommon/SAVWCommon.hpp @@ -2,51 +2,37 @@ #include "DNACommon.hpp" #include "PAK.hpp" -namespace DataSpec::SAVWCommon -{ -enum class EScanCategory -{ - None, - Data, - Lore, - Creature, - Research, - Artifact +namespace DataSpec::SAVWCommon { +enum class EScanCategory { None, Data, Lore, Creature, Research, Artifact }; + +struct Header : BigDNA { + AT_DECL_DNA_YAML + Value magic; + Value version; + Value areaCount; }; -struct Header : BigDNA -{ - AT_DECL_DNA_YAML - Value magic; - Value version; - Value areaCount; +struct EnvironmentVariable : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value unk1; + Value unk2; + Value unk3; }; -struct EnvironmentVariable : BigDNA -{ - AT_DECL_DNA_YAML - String<-1> name; - Value unk1; - Value unk2; - Value unk3; -}; - -struct Layer : BigDNA -{ - AT_DECL_DNA_YAML - Value areaId; - Value layer; +struct Layer : BigDNA { + AT_DECL_DNA_YAML + Value areaId; + Value layer; }; template -static bool ExtractSAVW(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - SAVW savw; - savw.read(rs); - athena::io::FileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(savw, writer); - return true; -} - +static bool ExtractSAVW(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + SAVW savw; + savw.read(rs); + athena::io::FileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(savw, writer); + return true; } +} // namespace DataSpec::SAVWCommon diff --git a/DataSpec/DNACommon/STRG.cpp b/DataSpec/DNACommon/STRG.cpp index 9ab09973d..8170dce75 100644 --- a/DataSpec/DNACommon/STRG.cpp +++ b/DataSpec/DNACommon/STRG.cpp @@ -3,46 +3,37 @@ #include "../DNAMP2/STRG.hpp" #include "../DNAMP3/STRG.hpp" -namespace DataSpec -{ +namespace DataSpec { -void ISTRG::gatherDependencies(std::vector& pathsOut) const -{ - /* TODO: parse out resource tokens */ -} +void ISTRG::gatherDependencies(std::vector& pathsOut) const { /* TODO: parse out resource tokens */ } -std::unique_ptr LoadSTRG(athena::io::IStreamReader& reader) -{ - uint32_t magic = reader.readUint32Big(); - if (magic != 0x87654321) - { - LogDNACommon.report(logvisor::Error, "invalid STRG magic"); - return std::unique_ptr(); - } - - uint32_t version = reader.readUint32Big(); - switch (version) - { - case 0: - { - DNAMP1::STRG* newStrg = new DNAMP1::STRG; - newStrg->_read(reader); - return std::unique_ptr(newStrg); - } - case 1: - { - DNAMP2::STRG* newStrg = new DNAMP2::STRG; - newStrg->_read(reader); - return std::unique_ptr(newStrg); - } - case 3: - { - DNAMP3::STRG* newStrg = new DNAMP3::STRG; - newStrg->_read(reader); - return std::unique_ptr(newStrg); - } - default: break; - } +std::unique_ptr LoadSTRG(athena::io::IStreamReader& reader) { + uint32_t magic = reader.readUint32Big(); + if (magic != 0x87654321) { + LogDNACommon.report(logvisor::Error, "invalid STRG magic"); return std::unique_ptr(); + } + + uint32_t version = reader.readUint32Big(); + switch (version) { + case 0: { + DNAMP1::STRG* newStrg = new DNAMP1::STRG; + newStrg->_read(reader); + return std::unique_ptr(newStrg); + } + case 1: { + DNAMP2::STRG* newStrg = new DNAMP2::STRG; + newStrg->_read(reader); + return std::unique_ptr(newStrg); + } + case 3: { + DNAMP3::STRG* newStrg = new DNAMP3::STRG; + newStrg->_read(reader); + return std::unique_ptr(newStrg); + } + default: + break; + } + return std::unique_ptr(); } -} +} // namespace DataSpec diff --git a/DataSpec/DNACommon/STRG.hpp b/DataSpec/DNACommon/STRG.hpp index 721c036c7..7c7372383 100644 --- a/DataSpec/DNACommon/STRG.hpp +++ b/DataSpec/DNACommon/STRG.hpp @@ -7,21 +7,18 @@ #include #include "DNACommon.hpp" -namespace DataSpec -{ -struct ISTRG : BigDNAVYaml -{ - virtual ~ISTRG() = default; +namespace DataSpec { +struct ISTRG : BigDNAVYaml { + virtual ~ISTRG() = default; - virtual size_t count() const=0; - virtual std::string getUTF8(const FourCC& lang, size_t idx) const=0; - virtual std::u16string getUTF16(const FourCC& lang, size_t idx) const=0; - virtual hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const=0; - virtual int32_t lookupIdx(std::string_view name) const=0; + virtual size_t count() const = 0; + virtual std::string getUTF8(const FourCC& lang, size_t idx) const = 0; + virtual std::u16string getUTF16(const FourCC& lang, size_t idx) const = 0; + virtual hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const = 0; + virtual int32_t lookupIdx(std::string_view name) const = 0; - virtual void gatherDependencies(std::vector& pathsOut) const; + virtual void gatherDependencies(std::vector& pathsOut) const; }; std::unique_ptr LoadSTRG(athena::io::IStreamReader& reader); -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/SWHC.cpp b/DataSpec/DNACommon/SWHC.cpp index 8b80907c6..4c48efbb1 100644 --- a/DataSpec/DNACommon/SWHC.cpp +++ b/DataSpec/DNACommon/SWHC.cpp @@ -1,590 +1,542 @@ #include "SWHC.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template <> -const char* SWSH::DNAType() { return "SWSH"; } +const char* SWSH::DNAType() { + return "SWSH"; +} template <> -const char* SWSH::DNAType() { return "SWSH"; } +const char* SWSH::DNAType() { + return "SWSH"; +} template -void SWSH::_read(typename BigDNA::ReadYaml::StreamT& r) -{ - for (const auto& elem : r.getCurNode()->m_mapChildren) - { - if (elem.first.size() < 4) - { - LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); - continue; - } - - if (auto rec = r.enterSubRecord(elem.first.c_str())) - { - switch(*reinterpret_cast(elem.first.data())) - { - case SBIG('PSLT'): - x0_PSLT.read(r); - break; - case SBIG('TIME'): - x4_TIME.read(r); - break; - case SBIG('LRAD'): - x8_LRAD.read(r); - break; - case SBIG('RRAD'): - xc_RRAD.read(r); - break; - case SBIG('LENG'): - x10_LENG.read(r); - break; - case SBIG('COLR'): - x14_COLR.read(r); - break; - case SBIG('SIDE'): - x18_SIDE.read(r); - break; - case SBIG('IROT'): - x1c_IROT.read(r); - break; - case SBIG('ROTM'): - x20_ROTM.read(r); - break; - case SBIG('POFS'): - x24_POFS.read(r); - break; - case SBIG('IVEL'): - x28_IVEL.read(r); - break; - case SBIG('NPOS'): - x2c_NPOS.read(r); - break; - case SBIG('VELM'): - x30_VELM.read(r); - break; - case SBIG('VLM2'): - x34_VLM2.read(r); - break; - case SBIG('SPLN'): - x38_SPLN.read(r); - break; - case SBIG('TEXR'): - x3c_TEXR.read(r); - break; - case SBIG('TSPN'): - x40_TSPN.read(r); - break; - case SBIG('LLRD'): - x44_24_LLRD = r.readBool(nullptr); - break; - case SBIG('CROS'): - x44_25_CROS = r.readBool(nullptr); - break; - case SBIG('VLS1'): - x44_26_VLS1 = r.readBool(nullptr); - break; - case SBIG('VLS2'): - x44_27_VLS2 = r.readBool(nullptr); - break; - case SBIG('SROT'): - x44_28_SROT = r.readBool(nullptr); - break; - case SBIG('WIRE'): - x44_29_WIRE = r.readBool(nullptr); - break; - case SBIG('TEXW'): - x44_30_TEXW = r.readBool(nullptr); - break; - case SBIG('AALP'): - x44_31_AALP = r.readBool(nullptr); - break; - case SBIG('ZBUF'): - x45_24_ZBUF = r.readBool(nullptr); - break; - case SBIG('ORNT'): - x45_25_ORNT = r.readBool(nullptr); - break; - case SBIG('CRND'): - x45_26_CRND = r.readBool(nullptr); - break; - default: - break; - } - } +void SWSH::_read(typename BigDNA::ReadYaml::StreamT& r) { + for (const auto& elem : r.getCurNode()->m_mapChildren) { + if (elem.first.size() < 4) { + LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); + continue; } + + if (auto rec = r.enterSubRecord(elem.first.c_str())) { + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('PSLT'): + x0_PSLT.read(r); + break; + case SBIG('TIME'): + x4_TIME.read(r); + break; + case SBIG('LRAD'): + x8_LRAD.read(r); + break; + case SBIG('RRAD'): + xc_RRAD.read(r); + break; + case SBIG('LENG'): + x10_LENG.read(r); + break; + case SBIG('COLR'): + x14_COLR.read(r); + break; + case SBIG('SIDE'): + x18_SIDE.read(r); + break; + case SBIG('IROT'): + x1c_IROT.read(r); + break; + case SBIG('ROTM'): + x20_ROTM.read(r); + break; + case SBIG('POFS'): + x24_POFS.read(r); + break; + case SBIG('IVEL'): + x28_IVEL.read(r); + break; + case SBIG('NPOS'): + x2c_NPOS.read(r); + break; + case SBIG('VELM'): + x30_VELM.read(r); + break; + case SBIG('VLM2'): + x34_VLM2.read(r); + break; + case SBIG('SPLN'): + x38_SPLN.read(r); + break; + case SBIG('TEXR'): + x3c_TEXR.read(r); + break; + case SBIG('TSPN'): + x40_TSPN.read(r); + break; + case SBIG('LLRD'): + x44_24_LLRD = r.readBool(nullptr); + break; + case SBIG('CROS'): + x44_25_CROS = r.readBool(nullptr); + break; + case SBIG('VLS1'): + x44_26_VLS1 = r.readBool(nullptr); + break; + case SBIG('VLS2'): + x44_27_VLS2 = r.readBool(nullptr); + break; + case SBIG('SROT'): + x44_28_SROT = r.readBool(nullptr); + break; + case SBIG('WIRE'): + x44_29_WIRE = r.readBool(nullptr); + break; + case SBIG('TEXW'): + x44_30_TEXW = r.readBool(nullptr); + break; + case SBIG('AALP'): + x44_31_AALP = r.readBool(nullptr); + break; + case SBIG('ZBUF'): + x45_24_ZBUF = r.readBool(nullptr); + break; + case SBIG('ORNT'): + x45_25_ORNT = r.readBool(nullptr); + break; + case SBIG('CRND'): + x45_26_CRND = r.readBool(nullptr); + break; + default: + break; + } + } + } } template -void SWSH::_write(typename BigDNA::WriteYaml::StreamT& w) const -{ - if (x0_PSLT) - if (auto rec = w.enterSubRecord("PSLT")) - x0_PSLT.write(w); - if (x4_TIME) - if (auto rec = w.enterSubRecord("TIME")) - x4_TIME.write(w); - if (x8_LRAD) - if (auto rec = w.enterSubRecord("LRAD")) - x8_LRAD.write(w); - if (xc_RRAD) - if (auto rec = w.enterSubRecord("RRAD")) - xc_RRAD.write(w); - if (x10_LENG) - if (auto rec = w.enterSubRecord("LENG")) - x10_LENG.write(w); - if (x14_COLR) - if (auto rec = w.enterSubRecord("COLR")) - x14_COLR.write(w); - if (x18_SIDE) - if (auto rec = w.enterSubRecord("SIDE")) - x18_SIDE.write(w); - if (x1c_IROT) - if (auto rec = w.enterSubRecord("IROT")) - x1c_IROT.write(w); - if (x20_ROTM) - if (auto rec = w.enterSubRecord("ROTM")) - x20_ROTM.write(w); - if (x24_POFS) - if (auto rec = w.enterSubRecord("POFS")) - x24_POFS.write(w); - if (x28_IVEL) - if (auto rec = w.enterSubRecord("IVEL")) - x28_IVEL.write(w); - if (x2c_NPOS) - if (auto rec = w.enterSubRecord("NPOS")) - x2c_NPOS.write(w); - if (x30_VELM) - if (auto rec = w.enterSubRecord("VELM")) - x30_VELM.write(w); - if (x34_VLM2) - if (auto rec = w.enterSubRecord("VLM2")) - x34_VLM2.write(w); - if (x38_SPLN) - if (auto rec = w.enterSubRecord("SPLN")) - x38_SPLN.write(w); - if (x3c_TEXR) - if (auto rec = w.enterSubRecord("TEXR")) - x3c_TEXR.write(w); - if (x40_TSPN) - if (auto rec = w.enterSubRecord("TSPN")) - x40_TSPN.write(w); +void SWSH::_write(typename BigDNA::WriteYaml::StreamT& w) const { + if (x0_PSLT) + if (auto rec = w.enterSubRecord("PSLT")) + x0_PSLT.write(w); + if (x4_TIME) + if (auto rec = w.enterSubRecord("TIME")) + x4_TIME.write(w); + if (x8_LRAD) + if (auto rec = w.enterSubRecord("LRAD")) + x8_LRAD.write(w); + if (xc_RRAD) + if (auto rec = w.enterSubRecord("RRAD")) + xc_RRAD.write(w); + if (x10_LENG) + if (auto rec = w.enterSubRecord("LENG")) + x10_LENG.write(w); + if (x14_COLR) + if (auto rec = w.enterSubRecord("COLR")) + x14_COLR.write(w); + if (x18_SIDE) + if (auto rec = w.enterSubRecord("SIDE")) + x18_SIDE.write(w); + if (x1c_IROT) + if (auto rec = w.enterSubRecord("IROT")) + x1c_IROT.write(w); + if (x20_ROTM) + if (auto rec = w.enterSubRecord("ROTM")) + x20_ROTM.write(w); + if (x24_POFS) + if (auto rec = w.enterSubRecord("POFS")) + x24_POFS.write(w); + if (x28_IVEL) + if (auto rec = w.enterSubRecord("IVEL")) + x28_IVEL.write(w); + if (x2c_NPOS) + if (auto rec = w.enterSubRecord("NPOS")) + x2c_NPOS.write(w); + if (x30_VELM) + if (auto rec = w.enterSubRecord("VELM")) + x30_VELM.write(w); + if (x34_VLM2) + if (auto rec = w.enterSubRecord("VLM2")) + x34_VLM2.write(w); + if (x38_SPLN) + if (auto rec = w.enterSubRecord("SPLN")) + x38_SPLN.write(w); + if (x3c_TEXR) + if (auto rec = w.enterSubRecord("TEXR")) + x3c_TEXR.write(w); + if (x40_TSPN) + if (auto rec = w.enterSubRecord("TSPN")) + x40_TSPN.write(w); - if (x44_24_LLRD) - w.writeBool("LLRD", true); - if (!x44_25_CROS) - w.writeBool("CROS", false); - if (x44_26_VLS1) - w.writeBool("VLS1", true); - if (x44_27_VLS2) - w.writeBool("VLS2", true); - if (x44_28_SROT) - w.writeBool("SROT", true); - if (x44_29_WIRE) - w.writeBool("WIRE", true); - if (x44_30_TEXW) - w.writeBool("TEXW", true); - if (x44_31_AALP) - w.writeBool("AALP", true); - if (x45_24_ZBUF) - w.writeBool("ZBUF", true); - if (x45_25_ORNT) - w.writeBool("ORNT", true); - if (x45_26_CRND) - w.writeBool("CRND", true); + if (x44_24_LLRD) + w.writeBool("LLRD", true); + if (!x44_25_CROS) + w.writeBool("CROS", false); + if (x44_26_VLS1) + w.writeBool("VLS1", true); + if (x44_27_VLS2) + w.writeBool("VLS2", true); + if (x44_28_SROT) + w.writeBool("SROT", true); + if (x44_29_WIRE) + w.writeBool("WIRE", true); + if (x44_30_TEXW) + w.writeBool("TEXW", true); + if (x44_31_AALP) + w.writeBool("AALP", true); + if (x45_24_ZBUF) + w.writeBool("ZBUF", true); + if (x45_25_ORNT) + w.writeBool("ORNT", true); + if (x45_26_CRND) + w.writeBool("CRND", true); } - template -void SWSH::_binarySize(typename BigDNA::BinarySize::StreamT& s) const -{ +void SWSH::_binarySize(typename BigDNA::BinarySize::StreamT& s) const { + s += 4; + if (x0_PSLT) { s += 4; - if (x0_PSLT) - { - s += 4; - x0_PSLT.binarySize(s); - } - if (x4_TIME) - { - s += 4; - x4_TIME.binarySize(s); - } - if (x8_LRAD) - { - s += 4; - x8_LRAD.binarySize(s); - } - if (xc_RRAD) - { - s += 4; - xc_RRAD.binarySize(s); - } - if (x10_LENG) - { - s += 4; - x10_LENG.binarySize(s); - } - if (x14_COLR) - { - s += 4; - x14_COLR.binarySize(s); - } - if (x18_SIDE) - { - s += 4; - x18_SIDE.binarySize(s); - } - if (x1c_IROT) - { - s += 4; - x1c_IROT.binarySize(s); - } - if (x20_ROTM) - { - s += 4; - x20_ROTM.binarySize(s); - } - if (x24_POFS) - { - s += 4; - x24_POFS.binarySize(s); - } - if (x28_IVEL) - { - s += 4; - x28_IVEL.binarySize(s); - } - if (x2c_NPOS) - { - s += 4; - x2c_NPOS.binarySize(s); - } - if (x30_VELM) - { - s += 4; - x30_VELM.binarySize(s); - } - if (x34_VLM2) - { - s += 4; - x34_VLM2.binarySize(s); - } - if (x38_SPLN) - { - s += 4; - x38_SPLN.binarySize(s); - } - if (x3c_TEXR) - { - s += 4; - x3c_TEXR.binarySize(s); - } - if (x40_TSPN) - { - s += 4; - x40_TSPN.binarySize(s); - } - if (x44_24_LLRD) - s += 9; - if (!x44_25_CROS) - s += 9; - if (x44_26_VLS1) - s += 9; - if (x44_27_VLS2) - s += 9; - if (x44_28_SROT) - s += 9; - if (x44_29_WIRE) - s += 9; - if (x44_30_TEXW) - s += 9; - if (x44_31_AALP) - s += 9; - if (x45_24_ZBUF) - s += 9; - if (x45_25_ORNT) - s += 9; - if (x45_26_CRND) - s += 9; + x0_PSLT.binarySize(s); + } + if (x4_TIME) { + s += 4; + x4_TIME.binarySize(s); + } + if (x8_LRAD) { + s += 4; + x8_LRAD.binarySize(s); + } + if (xc_RRAD) { + s += 4; + xc_RRAD.binarySize(s); + } + if (x10_LENG) { + s += 4; + x10_LENG.binarySize(s); + } + if (x14_COLR) { + s += 4; + x14_COLR.binarySize(s); + } + if (x18_SIDE) { + s += 4; + x18_SIDE.binarySize(s); + } + if (x1c_IROT) { + s += 4; + x1c_IROT.binarySize(s); + } + if (x20_ROTM) { + s += 4; + x20_ROTM.binarySize(s); + } + if (x24_POFS) { + s += 4; + x24_POFS.binarySize(s); + } + if (x28_IVEL) { + s += 4; + x28_IVEL.binarySize(s); + } + if (x2c_NPOS) { + s += 4; + x2c_NPOS.binarySize(s); + } + if (x30_VELM) { + s += 4; + x30_VELM.binarySize(s); + } + if (x34_VLM2) { + s += 4; + x34_VLM2.binarySize(s); + } + if (x38_SPLN) { + s += 4; + x38_SPLN.binarySize(s); + } + if (x3c_TEXR) { + s += 4; + x3c_TEXR.binarySize(s); + } + if (x40_TSPN) { + s += 4; + x40_TSPN.binarySize(s); + } + if (x44_24_LLRD) + s += 9; + if (!x44_25_CROS) + s += 9; + if (x44_26_VLS1) + s += 9; + if (x44_27_VLS2) + s += 9; + if (x44_28_SROT) + s += 9; + if (x44_29_WIRE) + s += 9; + if (x44_30_TEXW) + s += 9; + if (x44_31_AALP) + s += 9; + if (x45_24_ZBUF) + s += 9; + if (x45_25_ORNT) + s += 9; + if (x45_26_CRND) + s += 9; } template -void SWSH::_read(typename BigDNA::Read::StreamT& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId != SBIG('SWSH')) - { - LogModule.report(logvisor::Warning, "non SWSH provided to SWSH parser"); - return; - } +void SWSH::_read(typename BigDNA::Read::StreamT& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId != SBIG('SWSH')) { + LogModule.report(logvisor::Warning, "non SWSH provided to SWSH parser"); + return; + } - r.readBytesToBuf(&clsId, 4); - while (clsId != SBIG('_END')) - { - switch(clsId) - { - case SBIG('PSLT'): - x0_PSLT.read(r); - break; - case SBIG('TIME'): - x4_TIME.read(r); - break; - case SBIG('LRAD'): - x8_LRAD.read(r); - break; - case SBIG('RRAD'): - xc_RRAD.read(r); - break; - case SBIG('LENG'): - x10_LENG.read(r); - break; - case SBIG('COLR'): - x14_COLR.read(r); - break; - case SBIG('SIDE'): - x18_SIDE.read(r); - break; - case SBIG('IROT'): - x1c_IROT.read(r); - break; - case SBIG('ROTM'): - x20_ROTM.read(r); - break; - case SBIG('POFS'): - x24_POFS.read(r); - break; - case SBIG('IVEL'): - x28_IVEL.read(r); - break; - case SBIG('NPOS'): - x2c_NPOS.read(r); - break; - case SBIG('VELM'): - x30_VELM.read(r); - break; - case SBIG('VLM2'): - x34_VLM2.read(r); - break; - case SBIG('SPLN'): - x38_SPLN.read(r); - break; - case SBIG('TEXR'): - x3c_TEXR.read(r); - break; - case SBIG('TSPN'): - x40_TSPN.read(r); - break; - case SBIG('LLRD'): - r.readUint32Big(); - x44_24_LLRD = r.readBool(); - break; - case SBIG('CROS'): - r.readUint32Big(); - x44_25_CROS = r.readBool(); - break; - case SBIG('VLS1'): - r.readUint32Big(); - x44_26_VLS1 = r.readBool(); - break; - case SBIG('VLS2'): - r.readUint32Big(); - x44_27_VLS2 = r.readBool(); - break; - case SBIG('SROT'): - r.readUint32Big(); - x44_28_SROT = r.readBool(); - break; - case SBIG('WIRE'): - r.readUint32Big(); - x44_29_WIRE = r.readBool(); - break; - case SBIG('TEXW'): - r.readUint32Big(); - x44_30_TEXW = r.readBool(); - break; - case SBIG('AALP'): - r.readUint32Big(); - x44_31_AALP = r.readBool(); - break; - case SBIG('ZBUF'): - r.readUint32Big(); - x45_24_ZBUF = r.readBool(); - break; - case SBIG('ORNT'): - r.readUint32Big(); - x45_25_ORNT = r.readBool(); - break; - case SBIG('CRND'): - r.readUint32Big(); - x45_26_CRND = r.readBool(); - break; - default: - LogModule.report(logvisor::Fatal, "Unknown SWSH class %.4s @%" PRIi64, &clsId, r.position()); - break; - } - r.readBytesToBuf(&clsId, 4); + r.readBytesToBuf(&clsId, 4); + while (clsId != SBIG('_END')) { + switch (clsId) { + case SBIG('PSLT'): + x0_PSLT.read(r); + break; + case SBIG('TIME'): + x4_TIME.read(r); + break; + case SBIG('LRAD'): + x8_LRAD.read(r); + break; + case SBIG('RRAD'): + xc_RRAD.read(r); + break; + case SBIG('LENG'): + x10_LENG.read(r); + break; + case SBIG('COLR'): + x14_COLR.read(r); + break; + case SBIG('SIDE'): + x18_SIDE.read(r); + break; + case SBIG('IROT'): + x1c_IROT.read(r); + break; + case SBIG('ROTM'): + x20_ROTM.read(r); + break; + case SBIG('POFS'): + x24_POFS.read(r); + break; + case SBIG('IVEL'): + x28_IVEL.read(r); + break; + case SBIG('NPOS'): + x2c_NPOS.read(r); + break; + case SBIG('VELM'): + x30_VELM.read(r); + break; + case SBIG('VLM2'): + x34_VLM2.read(r); + break; + case SBIG('SPLN'): + x38_SPLN.read(r); + break; + case SBIG('TEXR'): + x3c_TEXR.read(r); + break; + case SBIG('TSPN'): + x40_TSPN.read(r); + break; + case SBIG('LLRD'): + r.readUint32Big(); + x44_24_LLRD = r.readBool(); + break; + case SBIG('CROS'): + r.readUint32Big(); + x44_25_CROS = r.readBool(); + break; + case SBIG('VLS1'): + r.readUint32Big(); + x44_26_VLS1 = r.readBool(); + break; + case SBIG('VLS2'): + r.readUint32Big(); + x44_27_VLS2 = r.readBool(); + break; + case SBIG('SROT'): + r.readUint32Big(); + x44_28_SROT = r.readBool(); + break; + case SBIG('WIRE'): + r.readUint32Big(); + x44_29_WIRE = r.readBool(); + break; + case SBIG('TEXW'): + r.readUint32Big(); + x44_30_TEXW = r.readBool(); + break; + case SBIG('AALP'): + r.readUint32Big(); + x44_31_AALP = r.readBool(); + break; + case SBIG('ZBUF'): + r.readUint32Big(); + x45_24_ZBUF = r.readBool(); + break; + case SBIG('ORNT'): + r.readUint32Big(); + x45_25_ORNT = r.readBool(); + break; + case SBIG('CRND'): + r.readUint32Big(); + x45_26_CRND = r.readBool(); + break; + default: + LogModule.report(logvisor::Fatal, "Unknown SWSH class %.4s @%" PRIi64, &clsId, r.position()); + break; } + r.readBytesToBuf(&clsId, 4); + } } template -void SWSH::_write(typename BigDNA::Write::StreamT& w) const -{ - w.writeBytes((atInt8*)"SWSH", 4); - if (x0_PSLT) - { - w.writeBytes((atInt8*)"PSLT", 4); - x0_PSLT.write(w); - } - if (x4_TIME) - { - w.writeBytes((atInt8*)"TIME", 4); - x4_TIME.write(w); - } - if (x8_LRAD) - { - w.writeBytes((atInt8*)"LRAD", 4); - x8_LRAD.write(w); - } - if (xc_RRAD) - { - w.writeBytes((atInt8*)"RRAD", 4); - xc_RRAD.write(w); - } - if (x10_LENG) - { - w.writeBytes((atInt8*)"LENG", 4); - x10_LENG.write(w); - } - if (x14_COLR) - { - w.writeBytes((atInt8*)"COLR", 4); - x14_COLR.write(w); - } - if (x18_SIDE) - { - w.writeBytes((atInt8*)"SIDE", 4); - x18_SIDE.write(w); - } - if (x1c_IROT) - { - w.writeBytes((atInt8*)"IROT", 4); - x1c_IROT.write(w); - } - if (x20_ROTM) - { - w.writeBytes((atInt8*)"ROTM", 4); - x20_ROTM.write(w); - } - if (x24_POFS) - { - w.writeBytes((atInt8*)"POFS", 4); - x24_POFS.write(w); - } - if (x28_IVEL) - { - w.writeBytes((atInt8*)"IVEL", 4); - x28_IVEL.write(w); - } - if (x2c_NPOS) - { - w.writeBytes((atInt8*)"NPOS", 4); - x2c_NPOS.write(w); - } - if (x30_VELM) - { - w.writeBytes((atInt8*)"VELM", 4); - x30_VELM.write(w); - } - if (x34_VLM2) - { - w.writeBytes((atInt8*)"VLM2", 4); - x34_VLM2.write(w); - } - if (x38_SPLN) - { - w.writeBytes((atInt8*)"SPLN", 4); - x38_SPLN.write(w); - } - if (x3c_TEXR) - { - w.writeBytes((atInt8*)"TEXR", 4); - x3c_TEXR.write(w); - } - if (x40_TSPN) - { - w.writeBytes((atInt8*)"TSPN", 4); - x40_TSPN.write(w); - } +void SWSH::_write(typename BigDNA::Write::StreamT& w) const { + w.writeBytes((atInt8*)"SWSH", 4); + if (x0_PSLT) { + w.writeBytes((atInt8*)"PSLT", 4); + x0_PSLT.write(w); + } + if (x4_TIME) { + w.writeBytes((atInt8*)"TIME", 4); + x4_TIME.write(w); + } + if (x8_LRAD) { + w.writeBytes((atInt8*)"LRAD", 4); + x8_LRAD.write(w); + } + if (xc_RRAD) { + w.writeBytes((atInt8*)"RRAD", 4); + xc_RRAD.write(w); + } + if (x10_LENG) { + w.writeBytes((atInt8*)"LENG", 4); + x10_LENG.write(w); + } + if (x14_COLR) { + w.writeBytes((atInt8*)"COLR", 4); + x14_COLR.write(w); + } + if (x18_SIDE) { + w.writeBytes((atInt8*)"SIDE", 4); + x18_SIDE.write(w); + } + if (x1c_IROT) { + w.writeBytes((atInt8*)"IROT", 4); + x1c_IROT.write(w); + } + if (x20_ROTM) { + w.writeBytes((atInt8*)"ROTM", 4); + x20_ROTM.write(w); + } + if (x24_POFS) { + w.writeBytes((atInt8*)"POFS", 4); + x24_POFS.write(w); + } + if (x28_IVEL) { + w.writeBytes((atInt8*)"IVEL", 4); + x28_IVEL.write(w); + } + if (x2c_NPOS) { + w.writeBytes((atInt8*)"NPOS", 4); + x2c_NPOS.write(w); + } + if (x30_VELM) { + w.writeBytes((atInt8*)"VELM", 4); + x30_VELM.write(w); + } + if (x34_VLM2) { + w.writeBytes((atInt8*)"VLM2", 4); + x34_VLM2.write(w); + } + if (x38_SPLN) { + w.writeBytes((atInt8*)"SPLN", 4); + x38_SPLN.write(w); + } + if (x3c_TEXR) { + w.writeBytes((atInt8*)"TEXR", 4); + x3c_TEXR.write(w); + } + if (x40_TSPN) { + w.writeBytes((atInt8*)"TSPN", 4); + x40_TSPN.write(w); + } - if (x44_24_LLRD) - w.writeBytes("LLRDCNST\x01", 9); - if (!x44_25_CROS) - w.writeBytes("CROSCNST\x00", 9); - if (x44_26_VLS1) - w.writeBytes("VLS1CNST\x01", 9); - if (x44_27_VLS2) - w.writeBytes("VLS2CNST\x01", 9); - if (x44_28_SROT) - w.writeBytes("SROTCNST\x01", 9); - if (x44_29_WIRE) - w.writeBytes("WIRECNST\x01", 9); - if (x44_30_TEXW) - w.writeBytes("TEXWCNST\x01", 9); - if (x44_31_AALP) - w.writeBytes("AALPCNST\x01", 9); - if (x45_24_ZBUF) - w.writeBytes("ZBUFCNST\x01", 9); - if (x45_25_ORNT) - w.writeBytes("ORNTCNST\x01", 9); - if (x45_26_CRND) - w.writeBytes("CRNDCNST\x01", 9); - w.writeBytes("_END", 4); + if (x44_24_LLRD) + w.writeBytes("LLRDCNST\x01", 9); + if (!x44_25_CROS) + w.writeBytes("CROSCNST\x00", 9); + if (x44_26_VLS1) + w.writeBytes("VLS1CNST\x01", 9); + if (x44_27_VLS2) + w.writeBytes("VLS2CNST\x01", 9); + if (x44_28_SROT) + w.writeBytes("SROTCNST\x01", 9); + if (x44_29_WIRE) + w.writeBytes("WIRECNST\x01", 9); + if (x44_30_TEXW) + w.writeBytes("TEXWCNST\x01", 9); + if (x44_31_AALP) + w.writeBytes("AALPCNST\x01", 9); + if (x45_24_ZBUF) + w.writeBytes("ZBUFCNST\x01", 9); + if (x45_25_ORNT) + w.writeBytes("ORNTCNST\x01", 9); + if (x45_26_CRND) + w.writeBytes("CRNDCNST\x01", 9); + w.writeBytes("_END", 4); } AT_SUBSPECIALIZE_DNA_YAML(SWSH) AT_SUBSPECIALIZE_DNA_YAML(SWSH) template -void SWSH::gatherDependencies(std::vector& pathsOut) const -{ - if (x3c_TEXR.m_elem) - x3c_TEXR.m_elem->gatherDependencies(pathsOut); +void SWSH::gatherDependencies(std::vector& pathsOut) const { + if (x3c_TEXR.m_elem) + x3c_TEXR.m_elem->gatherDependencies(pathsOut); } template struct SWSH; template struct SWSH; template -bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - SWSH swsh; - swsh.read(rs); - athena::io::ToYAMLStream(swsh, writer); - return true; - } - return false; +bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + SWSH swsh; + swsh.read(rs); + athena::io::ToYAMLStream(swsh, writer); + return true; + } + return false; } template bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template -bool WriteSWSH(const SWSH& swsh, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - swsh.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; +bool WriteSWSH(const SWSH& swsh, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + swsh.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } template bool WriteSWSH(const SWSH& swsh, const hecl::ProjectPath& outPath); template bool WriteSWSH(const SWSH& swsh, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/SWHC.hpp b/DataSpec/DNACommon/SWHC.hpp index 8ada3c9f3..c88b7387e 100644 --- a/DataSpec/DNACommon/SWHC.hpp +++ b/DataSpec/DNACommon/SWHC.hpp @@ -4,49 +4,50 @@ #include "PAK.hpp" #include "athena/FileWriter.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template -struct SWSH : public BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA +struct SWSH : public BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA - IntElementFactory x0_PSLT; - RealElementFactory x4_TIME; - RealElementFactory x8_LRAD; - RealElementFactory xc_RRAD; - IntElementFactory x10_LENG; - ColorElementFactory x14_COLR; - IntElementFactory x18_SIDE; - RealElementFactory x1c_IROT; - RealElementFactory x20_ROTM; - VectorElementFactory x24_POFS; - VectorElementFactory x28_IVEL; - VectorElementFactory x2c_NPOS; - ModVectorElementFactory x30_VELM; - ModVectorElementFactory x34_VLM2; - IntElementFactory x38_SPLN; - UVElementFactory x3c_TEXR; - IntElementFactory x40_TSPN; - union - { - struct - { - bool x44_24_LLRD : 1; bool x44_25_CROS : 1; bool x44_26_VLS1 : 1; bool x44_27_VLS2 : 1; - bool x44_28_SROT : 1; bool x44_29_WIRE : 1; bool x44_30_TEXW : 1; bool x44_31_AALP : 1; - bool x45_24_ZBUF : 1; bool x45_25_ORNT : 1; bool x45_26_CRND : 1; - }; - uint16_t dummy = 0; + IntElementFactory x0_PSLT; + RealElementFactory x4_TIME; + RealElementFactory x8_LRAD; + RealElementFactory xc_RRAD; + IntElementFactory x10_LENG; + ColorElementFactory x14_COLR; + IntElementFactory x18_SIDE; + RealElementFactory x1c_IROT; + RealElementFactory x20_ROTM; + VectorElementFactory x24_POFS; + VectorElementFactory x28_IVEL; + VectorElementFactory x2c_NPOS; + ModVectorElementFactory x30_VELM; + ModVectorElementFactory x34_VLM2; + IntElementFactory x38_SPLN; + UVElementFactory x3c_TEXR; + IntElementFactory x40_TSPN; + union { + struct { + bool x44_24_LLRD : 1; + bool x44_25_CROS : 1; + bool x44_26_VLS1 : 1; + bool x44_27_VLS2 : 1; + bool x44_28_SROT : 1; + bool x44_29_WIRE : 1; + bool x44_30_TEXW : 1; + bool x44_31_AALP : 1; + bool x45_24_ZBUF : 1; + bool x45_25_ORNT : 1; + bool x45_26_CRND : 1; }; + uint16_t dummy = 0; + }; - SWSH() - { - x44_25_CROS = true; - } + SWSH() { x44_25_CROS = true; } - void gatherDependencies(std::vector&) const; + void gatherDependencies(std::vector&) const; }; template @@ -54,4 +55,4 @@ bool ExtractSWSH(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteSWSH(const SWSH& gpsm, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/TXTR.cpp b/DataSpec/DNACommon/TXTR.cpp index 0a186c489..6a996fe73 100644 --- a/DataSpec/DNACommon/TXTR.cpp +++ b/DataSpec/DNACommon/TXTR.cpp @@ -4,235 +4,198 @@ #include "PAK.hpp" #include "athena/FileWriter.hpp" -namespace DataSpec -{ +namespace DataSpec { static logvisor::Module Log("libpng"); -static int CountBits(uint32_t n) -{ - int ret = 0; - for (int i=0 ; i<32 ; ++i) - if (((n >> i) & 1) != 0) - ++ret; - return ret; +static int CountBits(uint32_t n) { + int ret = 0; + for (int i = 0; i < 32; ++i) + if (((n >> i) & 1) != 0) + ++ret; + return ret; } /* Box filter algorithm (for mipmapping) */ -static void BoxFilter(const uint8_t* input, unsigned chanCount, - unsigned inWidth, unsigned inHeight, uint8_t* output, bool dxt1) -{ - unsigned mipWidth = 1; - unsigned mipHeight = 1; - if (inWidth > 1) - mipWidth = inWidth / 2; - if (inHeight > 1) - mipHeight = inHeight / 2; +static void BoxFilter(const uint8_t* input, unsigned chanCount, unsigned inWidth, unsigned inHeight, uint8_t* output, + bool dxt1) { + unsigned mipWidth = 1; + unsigned mipHeight = 1; + if (inWidth > 1) + mipWidth = inWidth / 2; + if (inHeight > 1) + mipHeight = inHeight / 2; - unsigned y,x,c; - for (y=0 ; y 0 && inHeight > 0) - { - ret += inWidth * inHeight; - inWidth /= 2; - inHeight /= 2; - } - return ret; +static size_t ComputeMippedTexelCount(unsigned inWidth, unsigned inHeight) { + size_t ret = 0; + while (inWidth > 0 && inHeight > 0) { + ret += inWidth * inHeight; + inWidth /= 2; + inHeight /= 2; + } + return ret; } /* GX uses this upsampling technique to extract full 8-bit range */ -static inline uint8_t Convert3To8(uint8_t v) -{ - /* Swizzle bits: 00000123 -> 12312312 */ - return (v << 5) | (v << 2) | (v >> 1); +static inline uint8_t Convert3To8(uint8_t v) { + /* Swizzle bits: 00000123 -> 12312312 */ + return (v << 5) | (v << 2) | (v >> 1); } -static inline uint8_t Convert8To3(uint8_t v) -{ - return v >> 5; +static inline uint8_t Convert8To3(uint8_t v) { return v >> 5; } + +static inline uint8_t Convert4To8(uint8_t v) { + /* Swizzle bits: 00001234 -> 12341234 */ + return (v << 4) | v; } -static inline uint8_t Convert4To8(uint8_t v) -{ - /* Swizzle bits: 00001234 -> 12341234 */ - return (v << 4) | v; +static inline uint8_t Convert8To4(uint8_t v) { return v >> 4; } + +static inline uint8_t Convert5To8(uint8_t v) { + /* Swizzle bits: 00012345 -> 12345123 */ + return (v << 3) | (v >> 2); } -static inline uint8_t Convert8To4(uint8_t v) -{ - return v >> 4; +static inline uint8_t Convert8To5(uint8_t v) { return v >> 3; } + +static inline uint8_t Convert6To8(uint8_t v) { + /* Swizzle bits: 00123456 -> 12345612 */ + return (v << 2) | (v >> 4); } -static inline uint8_t Convert5To8(uint8_t v) -{ - /* Swizzle bits: 00012345 -> 12345123 */ - return (v << 3) | (v >> 2); +static inline uint8_t Convert8To6(uint8_t v) { return v >> 2; } + +static inline uint8_t Lookup4BPP(const uint8_t* texels, int width, int x, int y) { + int bwidth = (width + 7) / 8; + int bx = x / 8; + int by = y / 8; + int rx = x % 8; + int ry = y % 8; + int bidx = by * bwidth + bx; + const uint8_t* btexels = &texels[32 * bidx]; + return btexels[ry * 4 + rx / 2] >> ((rx & 1) ? 0 : 4) & 0xf; } -static inline uint8_t Convert8To5(uint8_t v) -{ - return v >> 3; +static inline void Set4BPP(uint8_t* texels, int width, int x, int y, uint8_t val) { + int bwidth = (width + 7) / 8; + int bx = x / 8; + int by = y / 8; + int rx = x % 8; + int ry = y % 8; + int bidx = by * bwidth + bx; + uint8_t* btexels = &texels[32 * bidx]; + btexels[ry * 4 + rx / 2] |= (val & 0xf) << ((rx & 1) ? 0 : 4); } -static inline uint8_t Convert6To8(uint8_t v) -{ - /* Swizzle bits: 00123456 -> 12345612 */ - return (v << 2) | (v >> 4); +static inline uint8_t Lookup8BPP(const uint8_t* texels, int width, int x, int y) { + int bwidth = (width + 7) / 8; + int bx = x / 8; + int by = y / 4; + int rx = x % 8; + int ry = y % 4; + int bidx = by * bwidth + bx; + const uint8_t* btexels = &texels[32 * bidx]; + return btexels[ry * 8 + rx]; } -static inline uint8_t Convert8To6(uint8_t v) -{ - return v >> 2; +static inline void Set8BPP(uint8_t* texels, int width, int x, int y, uint8_t val) { + int bwidth = (width + 7) / 8; + int bx = x / 8; + int by = y / 4; + int rx = x % 8; + int ry = y % 4; + int bidx = by * bwidth + bx; + uint8_t* btexels = &texels[32 * bidx]; + btexels[ry * 8 + rx] = val; } -static inline uint8_t Lookup4BPP(const uint8_t* texels, int width, int x, int y) -{ - int bwidth = (width + 7) / 8; - int bx = x / 8; - int by = y / 8; - int rx = x % 8; - int ry = y % 8; - int bidx = by * bwidth + bx; - const uint8_t* btexels = &texels[32*bidx]; - return btexels[ry*4+rx/2] >> ((rx&1)?0:4) & 0xf; +static inline uint16_t Lookup16BPP(const uint8_t* texels, int width, int x, int y) { + int bwidth = (width + 3) / 4; + int bx = x / 4; + int by = y / 4; + int rx = x % 4; + int ry = y % 4; + int bidx = by * bwidth + bx; + const uint16_t* btexels = (uint16_t*)&texels[32 * bidx]; + return btexels[ry * 4 + rx]; } -static inline void Set4BPP(uint8_t* texels, int width, int x, int y, uint8_t val) -{ - int bwidth = (width + 7) / 8; - int bx = x / 8; - int by = y / 8; - int rx = x % 8; - int ry = y % 8; - int bidx = by * bwidth + bx; - uint8_t* btexels = &texels[32*bidx]; - btexels[ry*4+rx/2] |= (val & 0xf) << ((rx&1)?0:4); +static inline void Set16BPP(uint8_t* texels, int width, int x, int y, uint16_t val) { + int bwidth = (width + 3) / 4; + int bx = x / 4; + int by = y / 4; + int rx = x % 4; + int ry = y % 4; + int bidx = by * bwidth + bx; + uint16_t* btexels = (uint16_t*)&texels[32 * bidx]; + btexels[ry * 4 + rx] = val; } -static inline uint8_t Lookup8BPP(const uint8_t* texels, int width, int x, int y) -{ - int bwidth = (width + 7) / 8; - int bx = x / 8; - int by = y / 4; - int rx = x % 8; - int ry = y % 4; - int bidx = by * bwidth + bx; - const uint8_t* btexels = &texels[32*bidx]; - return btexels[ry*8+rx]; +static inline void LookupRGBA8(const uint8_t* texels, int width, int x, int y, uint8_t* r, uint8_t* g, uint8_t* b, + uint8_t* a) { + int bwidth = (width + 3) / 4; + int bx = x / 4; + int by = y / 4; + int rx = x % 4; + int ry = y % 4; + int bidx = (by * bwidth + bx) * 2; + const uint16_t* artexels = (uint16_t*)&texels[32 * bidx]; + const uint16_t* gbtexels = (uint16_t*)&texels[32 * (bidx + 1)]; + uint16_t ar = hecl::SBig(artexels[ry * 4 + rx]); + *a = ar >> 8 & 0xff; + *r = ar & 0xff; + uint16_t gb = hecl::SBig(gbtexels[ry * 4 + rx]); + *g = gb >> 8 & 0xff; + *b = gb & 0xff; } -static inline void Set8BPP(uint8_t* texels, int width, int x, int y, uint8_t val) -{ - int bwidth = (width + 7) / 8; - int bx = x / 8; - int by = y / 4; - int rx = x % 8; - int ry = y % 4; - int bidx = by * bwidth + bx; - uint8_t* btexels = &texels[32*bidx]; - btexels[ry*8+rx] = val; +static inline void SetRGBA8(uint8_t* texels, int width, int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + int bwidth = (width + 3) / 4; + int bx = x / 4; + int by = y / 4; + int rx = x % 4; + int ry = y % 4; + int bidx = (by * bwidth + bx) * 2; + uint16_t* artexels = (uint16_t*)&texels[32 * bidx]; + uint16_t* gbtexels = (uint16_t*)&texels[32 * (bidx + 1)]; + uint16_t ar = (a << 8) | r; + artexels[ry * 4 + rx] = hecl::SBig(ar); + uint16_t gb = (g << 8) | b; + gbtexels[ry * 4 + rx] = hecl::SBig(gb); } -static inline uint16_t Lookup16BPP(const uint8_t* texels, int width, int x, int y) -{ - int bwidth = (width + 3) / 4; - int bx = x / 4; - int by = y / 4; - int rx = x % 4; - int ry = y % 4; - int bidx = by * bwidth + bx; - const uint16_t* btexels = (uint16_t*)&texels[32*bidx]; - return btexels[ry*4+rx]; -} - -static inline void Set16BPP(uint8_t* texels, int width, int x, int y, uint16_t val) -{ - int bwidth = (width + 3) / 4; - int bx = x / 4; - int by = y / 4; - int rx = x % 4; - int ry = y % 4; - int bidx = by * bwidth + bx; - uint16_t* btexels = (uint16_t*)&texels[32*bidx]; - btexels[ry*4+rx] = val; -} - -static inline void LookupRGBA8(const uint8_t* texels, int width, int x, int y, - uint8_t* r, uint8_t* g, uint8_t* b, uint8_t* a) -{ - int bwidth = (width + 3) / 4; - int bx = x / 4; - int by = y / 4; - int rx = x % 4; - int ry = y % 4; - int bidx = (by * bwidth + bx) * 2; - const uint16_t* artexels = (uint16_t*)&texels[32*bidx]; - const uint16_t* gbtexels = (uint16_t*)&texels[32*(bidx+1)]; - uint16_t ar = hecl::SBig(artexels[ry*4+rx]); - *a = ar >> 8 & 0xff; - *r = ar & 0xff; - uint16_t gb = hecl::SBig(gbtexels[ry*4+rx]); - *g = gb >> 8 & 0xff; - *b = gb & 0xff; -} - -static inline void SetRGBA8(uint8_t* texels, int width, int x, int y, - uint8_t r, uint8_t g, uint8_t b, uint8_t a) -{ - int bwidth = (width + 3) / 4; - int bx = x / 4; - int by = y / 4; - int rx = x % 4; - int ry = y % 4; - int bidx = (by * bwidth + bx) * 2; - uint16_t* artexels = (uint16_t*)&texels[32*bidx]; - uint16_t* gbtexels = (uint16_t*)&texels[32*(bidx+1)]; - uint16_t ar = (a << 8) | r; - artexels[ry*4+rx] = hecl::SBig(ar); - uint16_t gb = (g << 8) | b; - gbtexels[ry*4+rx] = hecl::SBig(gb); -} - -static void DecodeI4(png_structp png, png_infop info, - const uint8_t* texels, int width, int height) -{ - png_set_IHDR(png, info, width, height, 8, - PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, info); - std::unique_ptr buf(new uint8_t[width]); - //memset(buf.get(), 0, width); - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x buf(new uint8_t[width]); + // memset(buf.get(), 0, width); + for (int y = height - 1; y >= 0; --y) { + for (int x = 0; x < width; ++x) + buf[x] = Convert4To8(Lookup4BPP(texels, width, x, y)); + png_write_row(png, buf.get()); + } } #if 0 @@ -247,50 +210,39 @@ static void EncodeI4(const uint8_t* rgbaIn, uint8_t* texels, int width, int heig } #endif -static void DecodeI8(png_structp png, png_infop info, - const uint8_t* texels, int width, int height) -{ - png_set_IHDR(png, info, width, height, 8, - PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, info); - std::unique_ptr buf(new uint8_t[width]); - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x buf(new uint8_t[width]); + for (int y = height - 1; y >= 0; --y) { + for (int x = 0; x < width; ++x) + buf[x] = Lookup8BPP(texels, width, x, y); + png_write_row(png, buf.get()); + } } -static void EncodeI8(const uint8_t* rgbaIn, uint8_t* texels, int width, int height) -{ - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x= 0; --y) { + for (int x = 0; x < width; ++x) + Set8BPP(texels, width, x, y, rgbaIn[x]); + rgbaIn += width; + } } -static void DecodeIA4(png_structp png, png_infop info, - const uint8_t* texels, int width, int height) -{ - png_set_IHDR(png, info, width, height, 8, - PNG_COLOR_TYPE_GRAY_ALPHA, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, info); - std::unique_ptr buf(new uint8_t[width*2]); - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x> 4 & 0xf); - buf[x*2+1] = Convert4To8(texel & 0xf); - } - png_write_row(png, buf.get()); +static void DecodeIA4(png_structp png, png_infop info, const uint8_t* texels, int width, int height) { + png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, info); + std::unique_ptr buf(new uint8_t[width * 2]); + for (int y = height - 1; y >= 0; --y) { + for (int x = 0; x < width; ++x) { + uint8_t texel = Lookup8BPP(texels, width, x, y); + buf[x * 2] = Convert4To8(texel >> 4 & 0xf); + buf[x * 2 + 1] = Convert4To8(texel & 0xf); } + png_write_row(png, buf.get()); + } } #if 0 @@ -309,507 +261,388 @@ static void EncodeIA4(const uint8_t* rgbaIn, uint8_t* texels, int width, int hei } #endif -static void DecodeIA8(png_structp png, png_infop info, - const uint8_t* texels, int width, int height) -{ - png_set_IHDR(png, info, width, height, 8, - PNG_COLOR_TYPE_GRAY_ALPHA, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, info); - std::unique_ptr buf(new uint16_t[width]); - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x buf(new uint16_t[width]); + for (int y = height - 1; y >= 0; --y) { + for (int x = 0; x < width; ++x) + buf[x] = Lookup16BPP(texels, width, x, y); + png_write_row(png, (png_bytep)buf.get()); + } } -static void EncodeIA8(const uint8_t* rgbaIn, uint8_t* texels, int width, int height) -{ - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x= 0; --y) { + for (int x = 0; x < width; ++x) + Set16BPP(texels, width, x, y, ((uint16_t*)rgbaIn)[x]); + rgbaIn += width * 2; + } } -static const uint8_t* DecodePalette(png_structp png, png_infop info, - int numEntries, const uint8_t* data) -{ - uint32_t format = hecl::SBig(*(uint32_t*)data); - data += 8; - png_color cEntries[256]; - png_byte aEntries[256]; - switch (format) - { - case 0: - { - /* IA8 */ - for (int e=0 ; e> 11 & 0x1f); - cEntries[e].green = Convert6To8(texel >> 5 & 0x3f); - cEntries[e].blue = Convert5To8(texel & 0x1f); - } - break; + break; + } + case 1: { + /* RGB565 */ + const uint16_t* data16 = (uint16_t*)data; + for (int e = 0; e < numEntries; ++e) { + uint16_t texel = hecl::SBig(data16[e]); + cEntries[e].red = Convert5To8(texel >> 11 & 0x1f); + cEntries[e].green = Convert6To8(texel >> 5 & 0x3f); + cEntries[e].blue = Convert5To8(texel & 0x1f); } - case 2: - { - /* RGB5A3 */ - const uint16_t* data16 = (uint16_t*)data; - for (int e=0 ; e> 10 & 0x1f); - cEntries[e].green = Convert5To8(texel >> 5 & 0x1f); - cEntries[e].blue = Convert5To8(texel & 0x1f); - aEntries[e] = 0xff; - } - else - { - cEntries[e].red = Convert4To8(texel >> 8 & 0xf); - cEntries[e].green = Convert4To8(texel >> 4 & 0xf); - cEntries[e].blue = Convert4To8(texel & 0xf); - aEntries[e] = Convert3To8(texel >> 12 & 0x7); - } - } - break; + break; + } + case 2: { + /* RGB5A3 */ + const uint16_t* data16 = (uint16_t*)data; + for (int e = 0; e < numEntries; ++e) { + uint16_t texel = hecl::SBig(data16[e]); + if (texel & 0x8000) { + cEntries[e].red = Convert5To8(texel >> 10 & 0x1f); + cEntries[e].green = Convert5To8(texel >> 5 & 0x1f); + cEntries[e].blue = Convert5To8(texel & 0x1f); + aEntries[e] = 0xff; + } else { + cEntries[e].red = Convert4To8(texel >> 8 & 0xf); + cEntries[e].green = Convert4To8(texel >> 4 & 0xf); + cEntries[e].blue = Convert4To8(texel & 0xf); + aEntries[e] = Convert3To8(texel >> 12 & 0x7); + } } - } - png_set_PLTE(png, info, cEntries, numEntries); - if (format == 0 || format == 2) - png_set_tRNS(png, info, aEntries, numEntries, nullptr); - data += numEntries * 2; - return data; + break; + } + } + png_set_PLTE(png, info, cEntries, numEntries); + if (format == 0 || format == 2) + png_set_tRNS(png, info, aEntries, numEntries, nullptr); + data += numEntries * 2; + return data; } -static uint8_t* EncodePalette(png_structp png, png_infop info, int numEntries, uint8_t* data) -{ - png_colorp cEntries; - int pngNumEntries; - if (png_get_PLTE(png, info, &cEntries, &pngNumEntries) != PNG_INFO_PLTE) - { - cEntries = nullptr; - pngNumEntries = 0; - } +static uint8_t* EncodePalette(png_structp png, png_infop info, int numEntries, uint8_t* data) { + png_colorp cEntries; + int pngNumEntries; + if (png_get_PLTE(png, info, &cEntries, &pngNumEntries) != PNG_INFO_PLTE) { + cEntries = nullptr; + pngNumEntries = 0; + } - png_bytep aEntries; - int pngNumAEntries; - png_color_16p trans_color = nullptr; - if (png_get_tRNS(png, info, &aEntries, &pngNumAEntries, &trans_color) != PNG_INFO_tRNS) - { - aEntries = nullptr; - pngNumAEntries = 0; - } + png_bytep aEntries; + int pngNumAEntries; + png_color_16p trans_color = nullptr; + if (png_get_tRNS(png, info, &aEntries, &pngNumAEntries, &trans_color) != PNG_INFO_tRNS) { + aEntries = nullptr; + pngNumAEntries = 0; + } - uint32_t format = 0; /* Default IA8 */ - for (int e=0 ; ered != ent->green || ent->red != ent->blue) - { - if (pngNumAEntries) - format = 2; /* RGB565 if not greyscale and has alpha */ - else - format = 1; /* RGB565 if not greyscale */ - break; + uint32_t format = 0; /* Default IA8 */ + for (int e = 0; e < pngNumEntries; ++e) { + png_colorp ent = &cEntries[e]; + if (ent->red != ent->green || ent->red != ent->blue) { + if (pngNumAEntries) + format = 2; /* RGB565 if not greyscale and has alpha */ + else + format = 1; /* RGB565 if not greyscale */ + break; + } + } + + ((uint32_t*)data)[0] = hecl::SBig(format); + data += 4; + ((uint16_t*)data)[0] = hecl::SBig(uint16_t(numEntries)); + ((uint16_t*)data)[1] = hecl::SBig(uint16_t(1)); + data += 4; + + switch (format) { + case 0: { + /* IA8 */ + for (int e = 0; e < numEntries; ++e) { + if (e < pngNumEntries) + data[e * 2] = cEntries[e].green; + else + data[e * 2] = 0; + if (e < pngNumAEntries) + data[e * 2 + 1] = aEntries[e]; + else + data[e * 2 + 1] = 0; + } + break; + } + case 1: { + /* RGB565 */ + uint16_t* data16 = (uint16_t*)data; + for (int e = 0; e < numEntries; ++e) { + if (e < pngNumEntries) { + uint16_t texel = Convert8To5(cEntries[e].red) << 11; + texel |= Convert8To6(cEntries[e].green) << 5; + texel |= Convert8To5(cEntries[e].blue); + data16[e] = hecl::SBig(texel); + } else { + data16[e] = 0; + } + } + break; + } + case 2: { + /* RGB5A3 */ + uint16_t* data16 = (uint16_t*)data; + for (int e = 0; e < numEntries; ++e) { + uint8_t alpha = 0; + if (e < pngNumAEntries) + alpha = aEntries[e]; + + uint16_t texel = 0; + if (alpha == 0xff) { + texel |= 0x8000; + if (e < pngNumEntries) { + texel |= Convert8To5(cEntries[e].red) << 10; + texel |= Convert8To5(cEntries[e].green) << 5; + texel |= Convert8To5(cEntries[e].blue); } - } - - ((uint32_t*)data)[0] = hecl::SBig(format); - data += 4; - ((uint16_t*)data)[0] = hecl::SBig(uint16_t(numEntries)); - ((uint16_t*)data)[1] = hecl::SBig(uint16_t(1)); - data += 4; - - switch (format) - { - case 0: - { - /* IA8 */ - for (int e=0 ; e> 11 & 0x1f); + entries[e].green = Convert6To8(texel >> 5 & 0x3f); + entries[e].blue = Convert5To8(texel & 0x1f); + entries[e].alpha = 0xff; + } + break; + } + case 2: { + /* RGB5A3 */ + GXEntry.name = (char*)"GX_RGB5A3"; + const uint16_t* data16 = (uint16_t*)data; + for (int e = 0; e < numEntries; ++e) { + uint16_t texel = hecl::SBig(data16[e]); + if (texel & 0x8000) { + entries[e].red = Convert5To8(texel >> 10 & 0x1f); + entries[e].green = Convert5To8(texel >> 5 & 0x1f); + entries[e].blue = Convert5To8(texel & 0x1f); + entries[e].alpha = 0xff; + } else { + entries[e].red = Convert4To8(texel >> 8 & 0xf); + entries[e].green = Convert4To8(texel >> 4 & 0xf); + entries[e].blue = Convert4To8(texel & 0xf); + entries[e].alpha = Convert3To8(texel >> 12 & 0x7); + } + } + break; + } + } + png_set_sPLT(png, info, &GXEntry, 1); + data += numEntries * 2; + return data; +} + +static uint8_t* EncodePaletteSPLT(png_structp png, png_infop info, int numEntries, uint8_t* data) { + png_sPLT_tp palettes; + int pngNumPalettes = png_get_sPLT(png, info, &palettes); + int pngNumEntries = 0; + png_sPLT_entryp cEntries = nullptr; + for (int i = 0; i < pngNumPalettes; ++i) { + png_sPLT_tp palette = &palettes[i]; + if (!strncmp(palette->name, "GX_", 3)) { + pngNumEntries = palette->nentries; + cEntries = palette->entries; + break; + } + } + + uint32_t format = 2; /* Default RGB5A3 */ + for (int e = 0; e < pngNumEntries; ++e) { + png_sPLT_entryp ent = &cEntries[e]; + if (ent->red != ent->green || ent->red != ent->blue) { + if (ent->alpha) { + format = 2; break; + } else + format = 1; } - case 1: - { - /* RGB565 */ - GXEntry.name = (char*)"GX_RGB565"; - const uint16_t* data16 = (uint16_t*)data; - for (int e=0 ; e> 11 & 0x1f); - entries[e].green = Convert6To8(texel >> 5 & 0x3f); - entries[e].blue = Convert5To8(texel & 0x1f); - entries[e].alpha = 0xff; + } + + ((uint32_t*)data)[0] = hecl::SBig(format); + data += 4; + ((uint16_t*)data)[0] = hecl::SBig(uint16_t(1)); + ((uint16_t*)data)[1] = hecl::SBig(uint16_t(numEntries)); + data += 4; + + switch (format) { + case 0: { + /* IA8 */ + for (int e = 0; e < numEntries; ++e) { + if (e < pngNumEntries) { + data[e * 2] = cEntries[e].green; + data[e * 2 + 1] = cEntries[e].alpha; + } else { + data[e * 2] = 0; + data[e * 2 + 1] = 0; + } + } + break; + } + case 1: { + /* RGB565 */ + uint16_t* data16 = (uint16_t*)data; + for (int e = 0; e < numEntries; ++e) { + if (e < pngNumEntries) { + uint16_t texel = Convert8To5(cEntries[e].red) << 11; + texel |= Convert8To6(cEntries[e].green) << 5; + texel |= Convert8To5(cEntries[e].blue); + data16[e] = hecl::SBig(texel); + } else { + data16[e] = 0; + } + } + break; + } + case 2: { + /* RGB5A3 */ + uint16_t* data16 = (uint16_t*)data; + for (int e = 0; e < numEntries; ++e) { + uint16_t texel = 0; + if (cEntries && cEntries[e].alpha == 0xff) { + texel |= 0x8000; + if (e < pngNumEntries) { + texel |= Convert8To5(cEntries[e].red) << 10; + texel |= Convert8To5(cEntries[e].green) << 5; + texel |= Convert8To5(cEntries[e].blue); } - break; - } - case 2: - { - /* RGB5A3 */ - GXEntry.name = (char*)"GX_RGB5A3"; - const uint16_t* data16 = (uint16_t*)data; - for (int e=0 ; e> 10 & 0x1f); - entries[e].green = Convert5To8(texel >> 5 & 0x1f); - entries[e].blue = Convert5To8(texel & 0x1f); - entries[e].alpha = 0xff; - } - else - { - entries[e].red = Convert4To8(texel >> 8 & 0xf); - entries[e].green = Convert4To8(texel >> 4 & 0xf); - entries[e].blue = Convert4To8(texel & 0xf); - entries[e].alpha = Convert3To8(texel >> 12 & 0x7); - } + } else { + if (e < pngNumEntries) { + texel |= Convert8To4(cEntries[e].red) << 8; + texel |= Convert8To4(cEntries[e].green) << 4; + texel |= Convert8To4(cEntries[e].blue); + texel |= Convert8To3(cEntries[e].alpha << 12); } - break; + } + data16[e] = hecl::SBig(texel); } - } - png_set_sPLT(png, info, &GXEntry, 1); - data += numEntries * 2; - return data; + break; + } + } + data += numEntries * 2; + return data; } -static uint8_t* EncodePaletteSPLT(png_structp png, png_infop info, int numEntries, uint8_t* data) -{ - png_sPLT_tp palettes; - int pngNumPalettes = png_get_sPLT(png, info, &palettes); - int pngNumEntries = 0; - png_sPLT_entryp cEntries = nullptr; - for (int i=0 ; iname, "GX_", 3)) - { - pngNumEntries = palette->nentries; - cEntries = palette->entries; - break; - } - } +static const png_color C4Colors[] = { + {0, 0, 0}, {155, 0, 0}, {0, 155, 0}, {0, 0, 155}, {155, 155, 0}, {155, 0, 155}, {0, 155, 155}, {155, 155, 155}, + {55, 55, 55}, {255, 0, 0}, {0, 255, 0}, {0, 0, 255}, {255, 255, 0}, {255, 0, 255}, {0, 255, 255}, {255, 255, 255}}; - uint32_t format = 2; /* Default RGB5A3 */ - for (int e=0 ; ered != ent->green || ent->red != ent->blue) - { - if (ent->alpha) - { - format = 2; - break; - } - else - format = 1; - } - } +static void C4Palette(png_structp png, png_infop info) { png_set_PLTE(png, info, C4Colors, 16); } - ((uint32_t*)data)[0] = hecl::SBig(format); - data += 4; - ((uint16_t*)data)[0] = hecl::SBig(uint16_t(1)); - ((uint16_t*)data)[1] = hecl::SBig(uint16_t(numEntries)); - data += 4; - - switch (format) - { - case 0: - { - /* IA8 */ - for (int e=0 ; e buf(new uint8_t[width]); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) + buf[x] = Lookup4BPP(texels, width, x, y); + png_write_row(png, buf.get()); + } } -static const png_color C4Colors[] = -{ - {0,0,0}, - {155,0,0}, - {0,155,0}, - {0,0,155}, - {155,155,0}, - {155,0,155}, - {0,155,155}, - {155,155,155}, - {55,55,55}, - {255,0,0}, - {0,255,0}, - {0,0,255}, - {255,255,0}, - {255,0,255}, - {0,255,255}, - {255,255,255} -}; - -static void C4Palette(png_structp png, png_infop info) -{ - png_set_PLTE(png, info, C4Colors, 16); +static void EncodeC4(png_structp png, png_infop info, const uint8_t* rgbaIn, uint8_t* data, int width, int height) { + uint8_t* texels = EncodePaletteSPLT(png, info, 16, data); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) + Set4BPP(texels, width, x, y, rgbaIn[x]); + rgbaIn += width; + } } -static void DecodeC4(png_structp png, png_infop info, - const uint8_t* data, int width, int height) -{ - png_set_IHDR(png, info, width, height, 8, - PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - C4Palette(png, info); - const uint8_t* texels = DecodePaletteSPLT(png, info, 16, data); - png_write_info(png, info); - std::unique_ptr buf(new uint8_t[width]); - for (int y=0 ; y buf(new uint8_t[width]); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) + buf[x] = Lookup8BPP(texels, width, x, y); + png_write_row(png, buf.get()); + } } -static void EncodeC4(png_structp png, png_infop info, const uint8_t* rgbaIn, - uint8_t* data, int width, int height) -{ - uint8_t* texels = EncodePaletteSPLT(png, info, 16, data); - for (int y=0 ; y buf(new uint8_t[width]); - for (int y=0 ; y buf(new uint8_t[width*3]); - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x> 11 & 0x1f); - buf[x*3+1] = Convert6To8(texel >> 5 & 0x3f); - buf[x*3+2] = Convert5To8(texel & 0x1f); - } - png_write_row(png, buf.get()); +static void DecodeRGB565(png_structp png, png_infop info, const uint8_t* texels, int width, int height) { + png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, info); + std::unique_ptr buf(new uint8_t[width * 3]); + for (int y = height - 1; y >= 0; --y) { + for (int x = 0; x < width; ++x) { + uint16_t texel = hecl::SBig(Lookup16BPP(texels, width, x, y)); + buf[x * 3] = Convert5To8(texel >> 11 & 0x1f); + buf[x * 3 + 1] = Convert6To8(texel >> 5 & 0x3f); + buf[x * 3 + 2] = Convert5To8(texel & 0x1f); } + png_write_row(png, buf.get()); + } } #if 0 @@ -829,36 +662,28 @@ static void EncodeRGB565(const uint8_t* rgbaIn, uint8_t* texels, int width, int } #endif -static void DecodeRGB5A3(png_structp png, png_infop info, - const uint8_t* texels, int width, int height) -{ - png_set_IHDR(png, info, width, height, 8, - PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, info); - std::unique_ptr buf(new uint8_t[width*4]); - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x> 10 & 0x1f); - buf[x*4+1] = Convert5To8(texel >> 5 & 0x1f); - buf[x*4+2] = Convert5To8(texel & 0x1f); - buf[x*4+3] = 0xff; - } - else - { - buf[x*4] = Convert4To8(texel >> 8 & 0xf); - buf[x*4+1] = Convert4To8(texel >> 4 & 0xf); - buf[x*4+2] = Convert4To8(texel & 0xf); - buf[x*4+3] = Convert3To8(texel >> 12 & 0x7); - } - } - png_write_row(png, buf.get()); +static void DecodeRGB5A3(png_structp png, png_infop info, const uint8_t* texels, int width, int height) { + png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, info); + std::unique_ptr buf(new uint8_t[width * 4]); + for (int y = height - 1; y >= 0; --y) { + for (int x = 0; x < width; ++x) { + uint16_t texel = hecl::SBig(Lookup16BPP(texels, width, x, y)); + if (texel & 0x8000) { + buf[x * 4] = Convert5To8(texel >> 10 & 0x1f); + buf[x * 4 + 1] = Convert5To8(texel >> 5 & 0x1f); + buf[x * 4 + 2] = Convert5To8(texel & 0x1f); + buf[x * 4 + 3] = 0xff; + } else { + buf[x * 4] = Convert4To8(texel >> 8 & 0xf); + buf[x * 4 + 1] = Convert4To8(texel >> 4 & 0xf); + buf[x * 4 + 2] = Convert4To8(texel & 0xf); + buf[x * 4 + 3] = Convert3To8(texel >> 12 & 0x7); + } } + png_write_row(png, buf.get()); + } } #if 0 @@ -890,1048 +715,879 @@ static void EncodeRGB5A3(const uint8_t* rgbaIn, uint8_t* texels, int width, int } #endif -static void DecodeRGBA8(png_structp png, png_infop info, - const uint8_t* texels, int width, int height) -{ - png_set_IHDR(png, info, width, height, 8, - PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, info); - std::unique_ptr buf(new uint8_t[width*4]); - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x buf(new uint8_t[width * 4]); + for (int y = height - 1; y >= 0; --y) { + for (int x = 0; x < width; ++x) + LookupRGBA8(texels, width, x, y, &buf[x * 4], &buf[x * 4 + 1], &buf[x * 4 + 2], &buf[x * 4 + 3]); + png_write_row(png, buf.get()); + } } -static void EncodeRGBA8(const uint8_t* rgbaIn, uint8_t* texels, int width, int height) -{ - for (int y=height-1 ; y>=0 ; --y) - { - for (int x=0 ; x= 0; --y) { + for (int x = 0; x < width; ++x) + SetRGBA8(texels, width, x, y, rgbaIn[x * 4], rgbaIn[x * 4 + 1], rgbaIn[x * 4 + 2], rgbaIn[x * 4 + 3]); + rgbaIn += width * 4; + } } -struct DXTBlock -{ - uint16_t color1; - uint16_t color2; - uint8_t lines[4]; +struct DXTBlock { + uint16_t color1; + uint16_t color2; + uint8_t lines[4]; }; -static void DecodeCMPR(png_structp png, png_infop info, - const uint8_t* texels, int width, int height) -{ - png_set_IHDR(png, info, width, height, 8, - PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, info); +static void DecodeCMPR(png_structp png, png_infop info, const uint8_t* texels, int width, int height) { + png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, info); - /* Decode 8 rows at a time */ - int bwidth = (width + 7) / 8; - int bpwidth = bwidth * 8; - std::unique_ptr buf(new uint32_t[bpwidth*8]); - uint32_t* bTargets[4] = { - buf.get(), - buf.get() + 4, - buf.get() + 4 * width, - buf.get() + 4 * width + 4 - }; - for (int y=height/8-1 ; y>=0 ; --y) - { - const DXTBlock* blks = (DXTBlock*)(texels + 32 * bwidth * y); - for (int x=0 ; x buf(new uint32_t[bpwidth * 8]); + uint32_t* bTargets[4] = {buf.get(), buf.get() + 4, buf.get() + 4 * width, buf.get() + 4 * width + 4}; + for (int y = height / 8 - 1; y >= 0; --y) { + const DXTBlock* blks = (DXTBlock*)(texels + 32 * bwidth * y); + for (int x = 0; x < width; x += 8) { + uint32_t blkOut[4][4][4]; + squish::Decompress((uint8_t*)blkOut[0][0], blks++, squish::kDxt1GCN); + squish::Decompress((uint8_t*)blkOut[1][0], blks++, squish::kDxt1GCN); + squish::Decompress((uint8_t*)blkOut[2][0], blks++, squish::kDxt1GCN); + squish::Decompress((uint8_t*)blkOut[3][0], blks++, squish::kDxt1GCN); - for (int bt=0 ; bt<4 ; ++bt) - for (int by=0 ; by<4 ; ++by) - memcpy(bTargets[bt] + x + width * by, blkOut[bt][by], 16); - } - for (int r=7 ; r>=0 ; --r) - png_write_row(png, (png_bytep)(bTargets[0] + width * r)); + for (int bt = 0; bt < 4; ++bt) + for (int by = 0; by < 4; ++by) + memcpy(bTargets[bt] + x + width * by, blkOut[bt][by], 16); } + for (int r = 7; r >= 0; --r) + png_write_row(png, (png_bytep)(bTargets[0] + width * r)); + } } -static void EncodeCMPR(const uint8_t* rgbaIn, uint8_t* texels, int width, int height) -{ - /* Encode 8 rows at a time */ - int bwidth = (width + 7) / 8; - int bpwidth = bwidth * 8; - std::unique_ptr buf(new uint32_t[bpwidth*8]); - uint32_t* bTargets[4] = { - buf.get(), - buf.get() + 4, - buf.get() + 4 * width, - buf.get() + 4 * width + 4 - }; - for (int y=height/8-1 ; y>=0 ; --y) - { - for (int r=7 ; r>=0 ; --r) - { - memcpy(bTargets[0] + width * r, rgbaIn, width * 4); - rgbaIn += width * 4; - } - DXTBlock* blks = (DXTBlock*)(texels + 32 * bwidth * y); - for (int x=0 ; x buf(new uint32_t[bpwidth * 8]); + uint32_t* bTargets[4] = {buf.get(), buf.get() + 4, buf.get() + 4 * width, buf.get() + 4 * width + 4}; + for (int y = height / 8 - 1; y >= 0; --y) { + for (int r = 7; r >= 0; --r) { + memcpy(bTargets[0] + width * r, rgbaIn, width * 4); + rgbaIn += width * 4; } + DXTBlock* blks = (DXTBlock*)(texels + 32 * bwidth * y); + for (int x = 0; x < width; x += 8) { + uint32_t blkIn[4][4][4]; + for (int bt = 0; bt < 4; ++bt) + for (int by = 0; by < 4; ++by) + memcpy(blkIn[bt][by], bTargets[bt] + x + width * by, 16); + + squish::Compress((uint8_t*)blkIn[0][0], blks++, squish::kDxt1GCN); + squish::Compress((uint8_t*)blkIn[1][0], blks++, squish::kDxt1GCN); + squish::Compress((uint8_t*)blkIn[2][0], blks++, squish::kDxt1GCN); + squish::Compress((uint8_t*)blkIn[3][0], blks++, squish::kDxt1GCN); + } + } } -static void PNGErr(png_structp png, png_const_charp msg) -{ - Log.report(logvisor::Error, msg); +static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, msg); } + +static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, msg); } + +bool TXTR::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + uint32_t format = rs.readUint32Big(); + uint16_t width = rs.readUint16Big(); + uint16_t height = rs.readUint16Big(); + uint32_t numMips = rs.readUint32Big(); + + FILE* fp = hecl::Fopen(outPath.getAbsolutePath().data(), _SYS_STR("wb")); + if (!fp) { + Log.report(logvisor::Error, _SYS_STR("Unable to open '%s' for writing"), outPath.getAbsolutePath().data()); + return false; + } + png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGErr, PNGWarn); + png_init_io(png, fp); + png_infop info = png_create_info_struct(png); + + png_text textStruct = {}; + textStruct.key = png_charp("urde_nomip"); + if (numMips == 1) + png_set_text(png, info, &textStruct, 1); + + switch (format) { + case 0: + DecodeI4(png, info, rs.data() + 12, width, height); + break; + case 1: + DecodeI8(png, info, rs.data() + 12, width, height); + break; + case 2: + DecodeIA4(png, info, rs.data() + 12, width, height); + break; + case 3: + DecodeIA8(png, info, rs.data() + 12, width, height); + break; + case 4: + DecodeC4(png, info, rs.data() + 12, width, height); + break; + case 5: + DecodeC8(png, info, rs.data() + 12, width, height); + break; + case 7: + DecodeRGB565(png, info, rs.data() + 12, width, height); + break; + case 8: + DecodeRGB5A3(png, info, rs.data() + 12, width, height); + break; + case 9: + DecodeRGBA8(png, info, rs.data() + 12, width, height); + break; + case 10: + DecodeCMPR(png, info, rs.data() + 12, width, height); + break; + } + + png_write_end(png, info); + png_write_flush(png); + png_destroy_write_struct(&png, &info); + fclose(fp); + + return true; } -static void PNGWarn(png_structp png, png_const_charp msg) -{ - Log.report(logvisor::Warning, msg); +static std::unique_ptr ReadPalette(png_structp png, png_infop info, size_t& szOut) { + std::unique_ptr ret; + png_sPLT_tp palettes; + int paletteCount = png_get_sPLT(png, info, &palettes); + if (paletteCount) { + for (int i = 0; i < paletteCount; ++i) { + png_sPLT_tp palette = &palettes[i]; + if (!strncmp(palette->name, "GX_", 3)) { + if (palette->nentries > 16) { + /* This is a C8 palette */ + ret.reset(new uint8_t[4 * 257]); + szOut = 4 * 257; + *reinterpret_cast(ret.get()) = hecl::SBig(256); + uint8_t* cur = ret.get() + 4; + for (int j = 0; j < 256; ++j) { + if (j < palette->nentries) { + png_sPLT_entryp entry = &palette->entries[j]; + if (palette->depth == 16) { + *cur++ = entry->red >> 8; + *cur++ = entry->green >> 8; + *cur++ = entry->blue >> 8; + *cur++ = entry->alpha >> 8; + } else { + *cur++ = entry->red; + *cur++ = entry->green; + *cur++ = entry->blue; + *cur++ = entry->alpha; + } + } else { + *cur++ = 0; + *cur++ = 0; + *cur++ = 0; + *cur++ = 0; + } + } + } else { + /* This is a C4 palette */ + ret.reset(new uint8_t[4 * 17]); + szOut = 4 * 17; + *reinterpret_cast(ret.get()) = hecl::SBig(16); + uint8_t* cur = ret.get() + 4; + for (int j = 0; j < 16; ++j) { + if (j < palette->nentries) { + png_sPLT_entryp entry = &palette->entries[j]; + if (palette->depth == 16) { + *cur++ = entry->red >> 8; + *cur++ = entry->green >> 8; + *cur++ = entry->blue >> 8; + *cur++ = entry->alpha >> 8; + } else { + *cur++ = entry->red; + *cur++ = entry->green; + *cur++ = entry->blue; + *cur++ = entry->alpha; + } + } else { + *cur++ = 0; + *cur++ = 0; + *cur++ = 0; + *cur++ = 0; + } + } + } + break; + } + } + } else { + png_colorp palettes; + int colorCount; + if (png_get_PLTE(png, info, &palettes, &colorCount) == PNG_INFO_PLTE) { + if (colorCount > 16) { + /* This is a C8 palette */ + ret.reset(new uint8_t[4 * 257]); + szOut = 4 * 257; + *reinterpret_cast(ret.get()) = hecl::SBig(256); + uint8_t* cur = ret.get() + 4; + for (int j = 0; j < 256; ++j) { + if (j < colorCount) { + png_colorp entry = &palettes[j]; + *cur++ = entry->red; + *cur++ = entry->green; + *cur++ = entry->blue; + *cur++ = 0xff; + } else { + *cur++ = 0; + *cur++ = 0; + *cur++ = 0; + *cur++ = 0; + } + } + } else { + /* This is a C4 palette */ + ret.reset(new uint8_t[4 * 17]); + szOut = 4 * 17; + *reinterpret_cast(ret.get()) = hecl::SBig(16); + uint8_t* cur = ret.get() + 4; + for (int j = 0; j < 16; ++j) { + if (j < colorCount) { + png_colorp entry = &palettes[j]; + *cur++ = entry->red; + *cur++ = entry->green; + *cur++ = entry->blue; + *cur++ = 0xff; + } else { + *cur++ = 0; + *cur++ = 0; + *cur++ = 0; + *cur++ = 0; + } + } + } + } + } + return ret; } -bool TXTR::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - uint32_t format = rs.readUint32Big(); - uint16_t width = rs.readUint16Big(); - uint16_t height = rs.readUint16Big(); - uint32_t numMips = rs.readUint32Big(); - - FILE* fp = hecl::Fopen(outPath.getAbsolutePath().data(), _SYS_STR("wb")); - if (!fp) - { - Log.report(logvisor::Error, - _SYS_STR("Unable to open '%s' for writing"), - outPath.getAbsolutePath().data()); - return false; +static int GetNumPaletteEntriesForGCN(png_structp png, png_infop info) { + png_sPLT_tp palettes; + int paletteCount = png_get_sPLT(png, info, &palettes); + if (paletteCount) { + for (int i = 0; i < paletteCount; ++i) { + png_sPLT_tp palette = &palettes[i]; + if (!strncmp(palette->name, "GX_", 3)) { + if (palette->nentries > 16) { + /* This is a C8 palette */ + return 256; + } else { + /* This is a C4 palette */ + return 16; + } + break; + } } - png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGErr, PNGWarn); - png_init_io(png, fp); - png_infop info = png_create_info_struct(png); - - png_text textStruct = {}; - textStruct.key = png_charp("urde_nomip"); - if (numMips == 1) - png_set_text(png, info, &textStruct, 1); - - switch (format) - { - case 0: - DecodeI4(png, info, rs.data() + 12, width, height); - break; - case 1: - DecodeI8(png, info, rs.data() + 12, width, height); - break; - case 2: - DecodeIA4(png, info, rs.data() + 12, width, height); - break; - case 3: - DecodeIA8(png, info, rs.data() + 12, width, height); - break; - case 4: - DecodeC4(png, info, rs.data() + 12, width, height); - break; - case 5: - DecodeC8(png, info, rs.data() + 12, width, height); - break; - case 7: - DecodeRGB565(png, info, rs.data() + 12, width, height); - break; - case 8: - DecodeRGB5A3(png, info, rs.data() + 12, width, height); - break; - case 9: - DecodeRGBA8(png, info, rs.data() + 12, width, height); - break; - case 10: - DecodeCMPR(png, info, rs.data() + 12, width, height); - break; + } else { + png_colorp palettes; + int colorCount; + if (png_get_PLTE(png, info, &palettes, &colorCount) == PNG_INFO_PLTE) { + if (colorCount > 16) { + /* This is a C8 palette */ + return 256; + } else { + /* This is a C4 palette */ + return 16; + } } - - png_write_end(png, info); - png_write_flush(png); - png_destroy_write_struct(&png, &info); - fclose(fp); - - return true; + } + return 0; } -static std::unique_ptr ReadPalette(png_structp png, png_infop info, size_t& szOut) -{ - std::unique_ptr ret; - png_sPLT_tp palettes; - int paletteCount = png_get_sPLT(png, info, &palettes); - if (paletteCount) - { - for (int i=0 ; iname, "GX_", 3)) - { - if (palette->nentries > 16) - { - /* This is a C8 palette */ - ret.reset(new uint8_t[4 * 257]); - szOut = 4 * 257; - *reinterpret_cast(ret.get()) = hecl::SBig(256); - uint8_t* cur = ret.get() + 4; - for (int j=0 ; j<256 ; ++j) - { - if (j < palette->nentries) - { - png_sPLT_entryp entry = &palette->entries[j]; - if (palette->depth == 16) - { - *cur++ = entry->red >> 8; - *cur++ = entry->green >> 8; - *cur++ = entry->blue >> 8; - *cur++ = entry->alpha >> 8; - } - else - { - *cur++ = entry->red; - *cur++ = entry->green; - *cur++ = entry->blue; - *cur++ = entry->alpha; - } - } - else - { - *cur++ = 0; - *cur++ = 0; - *cur++ = 0; - *cur++ = 0; - } - } - } - else - { - /* This is a C4 palette */ - ret.reset(new uint8_t[4 * 17]); - szOut = 4 * 17; - *reinterpret_cast(ret.get()) = hecl::SBig(16); - uint8_t* cur = ret.get() + 4; - for (int j=0 ; j<16 ; ++j) - { - if (j < palette->nentries) - { - png_sPLT_entryp entry = &palette->entries[j]; - if (palette->depth == 16) - { - *cur++ = entry->red >> 8; - *cur++ = entry->green >> 8; - *cur++ = entry->blue >> 8; - *cur++ = entry->alpha >> 8; - } - else - { - *cur++ = entry->red; - *cur++ = entry->green; - *cur++ = entry->blue; - *cur++ = entry->alpha; - } - } - else - { - *cur++ = 0; - *cur++ = 0; - *cur++ = 0; - *cur++ = 0; - } - } - } - break; - } - } - } - else - { - png_colorp palettes; - int colorCount; - if (png_get_PLTE(png, info, &palettes, &colorCount) == PNG_INFO_PLTE) - { - if (colorCount > 16) - { - /* This is a C8 palette */ - ret.reset(new uint8_t[4 * 257]); - szOut = 4 * 257; - *reinterpret_cast(ret.get()) = hecl::SBig(256); - uint8_t* cur = ret.get() + 4; - for (int j=0 ; j<256 ; ++j) - { - if (j < colorCount) - { - png_colorp entry = &palettes[j]; - *cur++ = entry->red; - *cur++ = entry->green; - *cur++ = entry->blue; - *cur++ = 0xff; - } - else - { - *cur++ = 0; - *cur++ = 0; - *cur++ = 0; - *cur++ = 0; - } - } - } - else - { - /* This is a C4 palette */ - ret.reset(new uint8_t[4 * 17]); - szOut = 4 * 17; - *reinterpret_cast(ret.get()) = hecl::SBig(16); - uint8_t* cur = ret.get() + 4; - for (int j=0 ; j<16 ; ++j) - { - if (j < colorCount) - { - png_colorp entry = &palettes[j]; - *cur++ = entry->red; - *cur++ = entry->green; - *cur++ = entry->blue; - *cur++ = 0xff; - } - else - { - *cur++ = 0; - *cur++ = 0; - *cur++ = 0; - *cur++ = 0; - } - } - } - } - } - return ret; -} +bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + FILE* inf = hecl::Fopen(inPath.getAbsolutePath().data(), _SYS_STR("rb")); + if (!inf) { + Log.report(logvisor::Error, _SYS_STR("Unable to open '%s' for reading"), inPath.getAbsolutePath().data()); + return false; + } -static int GetNumPaletteEntriesForGCN(png_structp png, png_infop info) -{ - png_sPLT_tp palettes; - int paletteCount = png_get_sPLT(png, info, &palettes); - if (paletteCount) - { - for (int i=0 ; iname, "GX_", 3)) - { - if (palette->nentries > 16) - { - /* This is a C8 palette */ - return 256; - } - else - { - /* This is a C4 palette */ - return 16; - } - break; - } - } - } - else - { - png_colorp palettes; - int colorCount; - if (png_get_PLTE(png, info, &palettes, &colorCount) == PNG_INFO_PLTE) - { - if (colorCount > 16) - { - /* This is a C8 palette */ - return 256; - } - else - { - /* This is a C4 palette */ - return 16; - } - } - } - return 0; -} - -bool TXTR::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) -{ - FILE* inf = hecl::Fopen(inPath.getAbsolutePath().data(), _SYS_STR("rb")); - if (!inf) - { - Log.report(logvisor::Error, - _SYS_STR("Unable to open '%s' for reading"), - inPath.getAbsolutePath().data()); - return false; - } - - /* Validate PNG */ - char header[8]; - fread(header, 1, 8, inf); - if (png_sig_cmp((png_const_bytep)header, 0, 8)) - { - Log.report(logvisor::Error, _SYS_STR("invalid PNG signature in '%s'"), - inPath.getAbsolutePath().data()); - fclose(inf); - return false; - } - - /* Setup PNG reader */ - png_structp pngRead = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (!pngRead) - { - Log.report(logvisor::Error, "unable to initialize libpng"); - fclose(inf); - return false; - } - png_infop info = png_create_info_struct(pngRead); - if (!info) - { - Log.report(logvisor::Error, "unable to initialize libpng info"); - fclose(inf); - png_destroy_read_struct(&pngRead, nullptr, nullptr); - return false; - } - - if (setjmp(png_jmpbuf(pngRead))) - { - Log.report(logvisor::Error, _SYS_STR("unable to initialize libpng I/O for '%s'"), - inPath.getAbsolutePath().data()); - fclose(inf); - png_destroy_read_struct(&pngRead, &info, nullptr); - return false; - } - - png_init_io(pngRead, inf); - png_set_sig_bytes(pngRead, 8); - - png_read_info(pngRead, info); - - png_uint_32 width = png_get_image_width(pngRead, info); - png_uint_32 height = png_get_image_height(pngRead, info); - png_byte colorType = png_get_color_type(pngRead, info); - png_byte bitDepth = png_get_bit_depth(pngRead, info); - - if (width < 4 || height < 4) - { - Log.report(logvisor::Error, "image must be 4x4 or larger"); - fclose(inf); - png_destroy_read_struct(&pngRead, &info, nullptr); - return false; - } - - /* Disable mipmapping if urde_nomip embedded */ - bool mipmap = true; - png_text* textStruct; - int numText; - png_get_text(pngRead, info, &textStruct, &numText); - for (int i=0 ; i>= 1) ++numMips; - } - - if (bitDepth != 8) - { - Log.report(logvisor::Error, _SYS_STR("'%s' is not 8 bits-per-channel"), - inPath.getAbsolutePath().data()); - fclose(inf); - png_destroy_read_struct(&pngRead, &info, nullptr); - return false; - } - - size_t rowSize = 0; - size_t nComps = 4; - int nPaletteEntries = 0; - switch (colorType) - { - case PNG_COLOR_TYPE_GRAY: - rowSize = width; - nComps = 1; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - rowSize = width * 2; - nComps = 2; - break; - case PNG_COLOR_TYPE_RGB: - rowSize = width * 3; - nComps = 4; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - rowSize = width * 4; - nComps = 4; - break; - case PNG_COLOR_TYPE_PALETTE: - nPaletteEntries = GetNumPaletteEntriesForGCN(pngRead, info); - rowSize = width; - nComps = 1; - break; - default: - Log.report(logvisor::Error, _SYS_STR("unsupported color type in '%s'"), - inPath.getAbsolutePath().data()); - fclose(inf); - png_destroy_read_struct(&pngRead, &info, nullptr); - return false; - } - - /* Intermediate row-read buf (file components) */ - std::unique_ptr rowBuf; - if (colorType == PNG_COLOR_TYPE_RGB) - rowBuf.reset(new uint8_t[rowSize]); - - /* Final mipmapped buf (RGBA components) */ - std::unique_ptr bufOut; - size_t bufLen = 0; - if (numMips > 1) - bufLen = ComputeMippedTexelCount(width, height) * nComps; - else - bufLen = width * height * nComps; - bufOut.reset(new uint8_t[bufLen]); - - if (setjmp(png_jmpbuf(pngRead))) - { - Log.report(logvisor::Error, _SYS_STR("unable to read image in '%s'"), - inPath.getAbsolutePath().data()); - fclose(inf); - png_destroy_read_struct(&pngRead, &info, nullptr); - return false; - } - - /* Track alpha values for DXT1 eligibility */ - bool doDXT1 = (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA) && - width >= 4 && height >= 4; - - /* Read into mip0 image buffer */ - for (int r=0 ; r>= 1) + ++numMips; + } + + if (bitDepth != 8) { + Log.report(logvisor::Error, _SYS_STR("'%s' is not 8 bits-per-channel"), inPath.getAbsolutePath().data()); + fclose(inf); + png_destroy_read_struct(&pngRead, &info, nullptr); + return false; + } + + size_t rowSize = 0; + size_t nComps = 4; + int nPaletteEntries = 0; + switch (colorType) { + case PNG_COLOR_TYPE_GRAY: + rowSize = width; + nComps = 1; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + rowSize = width * 2; + nComps = 2; + break; + case PNG_COLOR_TYPE_RGB: + rowSize = width * 3; + nComps = 4; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + rowSize = width * 4; + nComps = 4; + break; + case PNG_COLOR_TYPE_PALETTE: + nPaletteEntries = GetNumPaletteEntriesForGCN(pngRead, info); + rowSize = width; + nComps = 1; + break; + default: + Log.report(logvisor::Error, _SYS_STR("unsupported color type in '%s'"), inPath.getAbsolutePath().data()); + fclose(inf); + png_destroy_read_struct(&pngRead, &info, nullptr); + return false; + } + + /* Intermediate row-read buf (file components) */ + std::unique_ptr rowBuf; + if (colorType == PNG_COLOR_TYPE_RGB) + rowBuf.reset(new uint8_t[rowSize]); + + /* Final mipmapped buf (RGBA components) */ + std::unique_ptr bufOut; + size_t bufLen = 0; + if (numMips > 1) + bufLen = ComputeMippedTexelCount(width, height) * nComps; + else + bufLen = width * height * nComps; + bufOut.reset(new uint8_t[bufLen]); + + if (setjmp(png_jmpbuf(pngRead))) { + Log.report(logvisor::Error, _SYS_STR("unable to read image in '%s'"), inPath.getAbsolutePath().data()); + fclose(inf); + png_destroy_read_struct(&pngRead, &info, nullptr); + return false; + } + + /* Track alpha values for DXT1 eligibility */ + bool doDXT1 = (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA) && width >= 4 && height >= 4; + + /* Read into mip0 image buffer */ + for (int r = 0; r < height; ++r) { + if (colorType == PNG_COLOR_TYPE_RGB) { + png_read_row(pngRead, rowBuf.get(), nullptr); + for (unsigned i = 0; i < width; ++i) { + size_t inbase = i * 3; + size_t outbase = (r * width + i) * 4; + bufOut[outbase] = rowBuf[inbase]; + bufOut[outbase + 1] = rowBuf[inbase + 1]; + bufOut[outbase + 2] = rowBuf[inbase + 2]; + bufOut[outbase + 3] = 0xff; + } + } else { + png_read_row(pngRead, &bufOut[(r * width) * nComps], nullptr); + if (colorType == PNG_COLOR_TYPE_RGB_ALPHA) { + for (unsigned i = 0; i < width; ++i) { + size_t outbase = (r * width + i) * nComps; + if (bufOut[outbase + 3] != 0 && bufOut[outbase + 3] != 255) + doDXT1 = false; + } + } } - else - { - switch (colorType) - { - case PNG_COLOR_TYPE_GRAY: - minDimX = 8; - minDimY = 4; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - case PNG_COLOR_TYPE_RGB: - case PNG_COLOR_TYPE_RGB_ALPHA: - default: - minDimX = 4; - minDimY = 4; - break; - case PNG_COLOR_TYPE_PALETTE: - { - if (nPaletteEntries == 256) - { - minDimX = 8; - minDimY = 4; - } - else - { - minDimX = minDimY = 8; - } - break; - } - } + } + + png_destroy_read_struct(&pngRead, &info, nullptr); + fclose(inf); + + /* Reduce mipmaps to minimum allowed dimensions */ + int minDimX, minDimY; + if (doDXT1) { + minDimX = minDimY = 4; + } else { + switch (colorType) { + case PNG_COLOR_TYPE_GRAY: + minDimX = 8; + minDimY = 4; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_RGB_ALPHA: + default: + minDimX = 4; + minDimY = 4; + break; + case PNG_COLOR_TYPE_PALETTE: { + if (nPaletteEntries == 256) { + minDimX = 8; + minDimY = 4; + } else { + minDimX = minDimY = 8; + } + break; } - { - unsigned totalPixels = 0; - unsigned filterWidth = width; - unsigned filterHeight = height; - for (size_t i=0 ; i compOut; + size_t compLen = 0; + if (numMips > 1) { + const uint8_t* filterIn = bufOut.get(); + uint8_t* filterOut = bufOut.get() + width * height * nComps; + unsigned filterWidth = width; + unsigned filterHeight = height; + for (size_t i = 1; i < numMips; ++i) { + BoxFilter(filterIn, nComps, filterWidth, filterHeight, filterOut, doDXT1); + filterIn += filterWidth * filterHeight * nComps; + filterWidth /= 2; + filterHeight /= 2; + filterOut += filterWidth * filterHeight * nComps; + } + } + + /* Do DXT1 compression */ + int format; + if (doDXT1) { + int filterWidth = width; + int filterHeight = height; + for (size_t i = 0; i < numMips; ++i) { + compLen += squish::GetStorageRequirements(filterWidth, filterHeight, squish::kDxt1); + if (filterWidth == 8 || filterHeight == 8) { + numMips = i + 1; + break; + } + filterWidth /= 2; + filterHeight /= 2; } - /* Perform box-filter mipmap */ - std::unique_ptr compOut; - size_t compLen = 0; - if (numMips > 1) - { - const uint8_t* filterIn = bufOut.get(); - uint8_t* filterOut = bufOut.get() + width * height * nComps; - unsigned filterWidth = width; - unsigned filterHeight = height; - for (size_t i=1 ; i>= 1) + ++numMips; + } + + if (bitDepth != 8) { + Log.report(logvisor::Error, _SYS_STR("'%s' is not 8 bits-per-channel"), inPath.getAbsolutePath().data()); + fclose(inf); + png_destroy_read_struct(&pngRead, &info, nullptr); + return false; + } + + std::unique_ptr paletteBuf; + size_t paletteSize = 0; + + size_t rowSize = 0; + size_t nComps = 4; + switch (colorType) { + case PNG_COLOR_TYPE_GRAY: + rowSize = width; + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + rowSize = width * 2; + break; + case PNG_COLOR_TYPE_RGB: + rowSize = width * 3; + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + rowSize = width * 4; + break; + case PNG_COLOR_TYPE_PALETTE: + rowSize = width; + nComps = 1; + paletteBuf = ReadPalette(pngRead, info, paletteSize); + break; + default: + Log.report(logvisor::Error, _SYS_STR("unsupported color type in '%s'"), inPath.getAbsolutePath().data()); + fclose(inf); + png_destroy_read_struct(&pngRead, &info, nullptr); + return false; + } + + /* Intermediate row-read buf (file components) */ + std::unique_ptr rowBuf(new uint8_t[rowSize]); + + /* Final mipmapped buf (RGBA components) */ + std::unique_ptr bufOut; + size_t bufLen = 0; + if (numMips > 1) + bufLen = ComputeMippedTexelCount(width, height) * nComps; + else + bufLen = width * height * nComps; + bufOut.reset(new uint8_t[bufLen]); + + if (setjmp(png_jmpbuf(pngRead))) { + Log.report(logvisor::Error, _SYS_STR("unable to read image in '%s'"), inPath.getAbsolutePath().data()); + fclose(inf); + png_destroy_read_struct(&pngRead, &info, nullptr); + return false; + } + + /* Track alpha values for DXT1 eligibility */ + bool doDXT1 = (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA) && width >= 4 && height >= 4; + + /* Read and make RGBA */ + for (int r = height - 1; r >= 0; --r) { + png_read_row(pngRead, rowBuf.get(), nullptr); + switch (colorType) { + case PNG_COLOR_TYPE_GRAY: + for (unsigned i = 0; i < width; ++i) { + size_t outbase = (r * width + i) * 4; + bufOut[outbase] = rowBuf[i]; + bufOut[outbase + 1] = rowBuf[i]; + bufOut[outbase + 2] = rowBuf[i]; + bufOut[outbase + 3] = rowBuf[i]; + } + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + for (unsigned i = 0; i < width; ++i) { + size_t inbase = i * 2; + size_t outbase = (r * width + i) * 4; + bufOut[outbase] = rowBuf[inbase]; + bufOut[outbase + 1] = rowBuf[inbase]; + bufOut[outbase + 2] = rowBuf[inbase]; + bufOut[outbase + 3] = rowBuf[inbase + 1]; + } + break; + case PNG_COLOR_TYPE_RGB: + for (unsigned i = 0; i < width; ++i) { + size_t inbase = i * 3; + size_t outbase = (r * width + i) * 4; + bufOut[outbase] = rowBuf[inbase]; + bufOut[outbase + 1] = rowBuf[inbase + 1]; + bufOut[outbase + 2] = rowBuf[inbase + 2]; + bufOut[outbase + 3] = 0xff; + } + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + for (unsigned i = 0; i < width; ++i) { + size_t inbase = i * 4; + size_t outbase = (r * width + i) * 4; + bufOut[outbase] = rowBuf[inbase]; + bufOut[outbase + 1] = rowBuf[inbase + 1]; + bufOut[outbase + 2] = rowBuf[inbase + 2]; + bufOut[outbase + 3] = rowBuf[inbase + 3]; + if (rowBuf[inbase + 3] != 0 && rowBuf[inbase + 3] != 255) + doDXT1 = false; + } + break; + case PNG_COLOR_TYPE_PALETTE: + for (unsigned i = 0; i < width; ++i) + bufOut[r * width + i] = rowBuf[i]; + break; + default: + break; } + } - outf.writeInt32Big(format); - outf.writeInt16Big(width); - outf.writeInt16Big(height); - outf.writeInt32Big(numMips); + png_destroy_read_struct(&pngRead, &info, nullptr); + fclose(inf); + + /* Perform box-filter mipmap */ + if (numMips > 1) { + const uint8_t* filterIn = bufOut.get(); + uint8_t* filterOut = bufOut.get() + width * height * nComps; + unsigned filterWidth = width; + unsigned filterHeight = height; + for (size_t i = 1; i < numMips; ++i) { + BoxFilter(filterIn, nComps, filterWidth, filterHeight, filterOut, doDXT1); + filterIn += filterWidth * filterHeight * nComps; + filterWidth /= 2; + filterHeight /= 2; + filterOut += filterWidth * filterHeight * nComps; + } + } + + /* Do DXT1 compression */ + std::unique_ptr compOut; + size_t compLen = 0; + if (doDXT1) { + int filterWidth = width; + int filterHeight = height; + size_t i; + for (i = 0; i < numMips; ++i) { + compLen += squish::GetStorageRequirements(filterWidth, filterHeight, squish::kDxt1); + if (filterWidth == 4 || filterHeight == 4) { + ++i; + break; + } + filterWidth /= 2; + filterHeight /= 2; + } + numMips = i; + + compOut.reset(new uint8_t[compLen]); + + filterWidth = width; + filterHeight = height; + const uint8_t* rgbaIn = bufOut.get(); + uint8_t* blocksOut = compOut.get(); + for (i = 0; i < numMips; ++i) { + int thisLen = squish::GetStorageRequirements(filterWidth, filterHeight, squish::kDxt1); + squish::CompressImage(rgbaIn, filterWidth, filterHeight, blocksOut, squish::kDxt1); + rgbaIn += filterWidth * filterHeight * nComps; + blocksOut += thisLen; + filterWidth /= 2; + filterHeight /= 2; + } + } + + /* Do write out */ + athena::io::FileWriter outf(outPath.getAbsolutePath(), true, false); + if (outf.hasError()) { + Log.report(logvisor::Error, _SYS_STR("Unable to open '%s' for writing"), outPath.getAbsolutePath().data()); + return false; + } + + int format; + if (paletteBuf && paletteSize) + format = 17; + else if (compOut) + format = 18; + else + format = 16; + outf.writeInt32Big(format); + outf.writeInt16Big(width); + outf.writeInt16Big(height); + outf.writeInt32Big(numMips); + if (paletteBuf && paletteSize) + outf.writeUBytes(paletteBuf.get(), paletteSize); + if (compOut) outf.writeUBytes(compOut.get(), compLen); + else + outf.writeUBytes(bufOut.get(), bufLen); - return true; + return true; } -bool TXTR::CookPC(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) -{ - FILE* inf = hecl::Fopen(inPath.getAbsolutePath().data(), _SYS_STR("rb")); - if (!inf) - { - Log.report(logvisor::Error, - _SYS_STR("Unable to open '%s' for reading"), - inPath.getAbsolutePath().data()); - return false; - } - - /* Validate PNG */ - char header[8]; - fread(header, 1, 8, inf); - if (png_sig_cmp((png_const_bytep)header, 0, 8)) - { - Log.report(logvisor::Error, _SYS_STR("invalid PNG signature in '%s'"), - inPath.getAbsolutePath().data()); - fclose(inf); - return false; - } - - /* Setup PNG reader */ - png_structp pngRead = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (!pngRead) - { - Log.report(logvisor::Error, "unable to initialize libpng"); - fclose(inf); - return false; - } - png_infop info = png_create_info_struct(pngRead); - if (!info) - { - Log.report(logvisor::Error, "unable to initialize libpng info"); - fclose(inf); - png_destroy_read_struct(&pngRead, nullptr, nullptr); - return false; - } - - if (setjmp(png_jmpbuf(pngRead))) - { - Log.report(logvisor::Error, _SYS_STR("unable to initialize libpng I/O for '%s'"), - inPath.getAbsolutePath().data()); - fclose(inf); - png_destroy_read_struct(&pngRead, &info, nullptr); - return false; - } - - png_init_io(pngRead, inf); - png_set_sig_bytes(pngRead, 8); - - png_read_info(pngRead, info); - - png_uint_32 width = png_get_image_width(pngRead, info); - png_uint_32 height = png_get_image_height(pngRead, info); - png_byte colorType = png_get_color_type(pngRead, info); - png_byte bitDepth = png_get_bit_depth(pngRead, info); - - /* Disable mipmapping if urde_nomip embedded */ - bool mipmap = true; - png_text* textStruct; - int numText; - png_get_text(pngRead, info, &textStruct, &numText); - for (int i=0 ; i>= 1) ++numMips; - } - - if (bitDepth != 8) - { - Log.report(logvisor::Error, _SYS_STR("'%s' is not 8 bits-per-channel"), - inPath.getAbsolutePath().data()); - fclose(inf); - png_destroy_read_struct(&pngRead, &info, nullptr); - return false; - } - - std::unique_ptr paletteBuf; - size_t paletteSize = 0; - - size_t rowSize = 0; - size_t nComps = 4; - switch (colorType) - { - case PNG_COLOR_TYPE_GRAY: - rowSize = width; - break; - case PNG_COLOR_TYPE_GRAY_ALPHA: - rowSize = width * 2; - break; - case PNG_COLOR_TYPE_RGB: - rowSize = width * 3; - break; - case PNG_COLOR_TYPE_RGB_ALPHA: - rowSize = width * 4; - break; - case PNG_COLOR_TYPE_PALETTE: - rowSize = width; - nComps = 1; - paletteBuf = ReadPalette(pngRead, info, paletteSize); - break; - default: - Log.report(logvisor::Error, _SYS_STR("unsupported color type in '%s'"), - inPath.getAbsolutePath().data()); - fclose(inf); - png_destroy_read_struct(&pngRead, &info, nullptr); - return false; - } - - /* Intermediate row-read buf (file components) */ - std::unique_ptr rowBuf(new uint8_t[rowSize]); - - /* Final mipmapped buf (RGBA components) */ - std::unique_ptr bufOut; - size_t bufLen = 0; - if (numMips > 1) - bufLen = ComputeMippedTexelCount(width, height) * nComps; - else - bufLen = width * height * nComps; - bufOut.reset(new uint8_t[bufLen]); - - if (setjmp(png_jmpbuf(pngRead))) - { - Log.report(logvisor::Error, _SYS_STR("unable to read image in '%s'"), - inPath.getAbsolutePath().data()); - fclose(inf); - png_destroy_read_struct(&pngRead, &info, nullptr); - return false; - } - - /* Track alpha values for DXT1 eligibility */ - bool doDXT1 = (colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA) && - width >= 4 && height >= 4; - - /* Read and make RGBA */ - for (int r=height-1 ; r>=0 ; --r) - { - png_read_row(pngRead, rowBuf.get(), nullptr); - switch (colorType) - { - case PNG_COLOR_TYPE_GRAY: - for (unsigned i=0 ; i 1) - { - const uint8_t* filterIn = bufOut.get(); - uint8_t* filterOut = bufOut.get() + width * height * nComps; - unsigned filterWidth = width; - unsigned filterHeight = height; - for (size_t i=1 ; i compOut; - size_t compLen = 0; - if (doDXT1) - { - int filterWidth = width; - int filterHeight = height; - size_t i; - for (i=0 ; i 4) - b = 0; - switch (EBeamId(b)) - { - default: - case EBeamId::Power: - return x10_powerBeam; - case EBeamId::Ice: - return x14_iceBeam; - case EBeamId::Wave: - return x18_waveBeam; - case EBeamId::Plasma: - return x1c_plasmaBeam; - case EBeamId::Phazon: - return x20_phazonBeam; - } + ResId GetBeamModel(EBeamId beam) const { + auto b = int(beam); + if (b < 0 || b > 4) + b = 0; + switch (EBeamId(b)) { + default: + case EBeamId::Power: + return x10_powerBeam; + case EBeamId::Ice: + return x14_iceBeam; + case EBeamId::Wave: + return x18_waveBeam; + case EBeamId::Plasma: + return x1c_plasmaBeam; + case EBeamId::Phazon: + return x20_phazonBeam; } + } - const ResId* GetWeaponPair(EBeamId beam) const - { - auto b = int(beam); - if (b < 0 || b > 4) - return x34_weapons[0]; - return x34_weapons[b]; - } + const ResId* GetWeaponPair(EBeamId beam) const { + auto b = int(beam); + if (b < 0 || b > 4) + return x34_weapons[0]; + return x34_weapons[b]; + } - void ResolveResources(const urde::IFactory& factory) - { - x4_gunMotion = factory.GetResourceIdByName(GetGunMotion().c_str())->id; - x8_grappleArm = factory.GetResourceIdByName(GetGrappleArm().c_str())->id; - xc_rightHand = factory.GetResourceIdByName(GetRightHand().c_str())->id; + void ResolveResources(const urde::IFactory& factory) { + x4_gunMotion = factory.GetResourceIdByName(GetGunMotion().c_str())->id; + x8_grappleArm = factory.GetResourceIdByName(GetGrappleArm().c_str())->id; + xc_rightHand = factory.GetResourceIdByName(GetRightHand().c_str())->id; - x10_powerBeam = factory.GetResourceIdByName(GetPowerBeam().c_str())->id; - x14_iceBeam = factory.GetResourceIdByName(GetIceBeam().c_str())->id; - x18_waveBeam = factory.GetResourceIdByName(GetWaveBeam().c_str())->id; - x1c_plasmaBeam = factory.GetResourceIdByName(GetPlasmaBeam().c_str())->id; - x20_phazonBeam = factory.GetResourceIdByName(GetPhazonBeam().c_str())->id; + x10_powerBeam = factory.GetResourceIdByName(GetPowerBeam().c_str())->id; + x14_iceBeam = factory.GetResourceIdByName(GetIceBeam().c_str())->id; + x18_waveBeam = factory.GetResourceIdByName(GetWaveBeam().c_str())->id; + x1c_plasmaBeam = factory.GetResourceIdByName(GetPlasmaBeam().c_str())->id; + x20_phazonBeam = factory.GetResourceIdByName(GetPhazonBeam().c_str())->id; - x24_holoTransition = factory.GetResourceIdByName(GetHoloTransition().c_str())->id; + x24_holoTransition = factory.GetResourceIdByName(GetHoloTransition().c_str())->id; - x28_bombSet = factory.GetResourceIdByName(GetBombSet().c_str())->id; - x2c_bombExplode = factory.GetResourceIdByName(GetBombExplode().c_str())->id; - x30_powerBombExplode = factory.GetResourceIdByName(GetPowerBombExplode().c_str())->id; + x28_bombSet = factory.GetResourceIdByName(GetBombSet().c_str())->id; + x2c_bombExplode = factory.GetResourceIdByName(GetBombExplode().c_str())->id; + x30_powerBombExplode = factory.GetResourceIdByName(GetPowerBombExplode().c_str())->id; - for (int i=0 ; i<5 ; ++i) - for (int j=0 ; j<2 ; ++j) - x34_weapons[i][j] = factory.GetResourceIdByName(GetWeapon(i, j).c_str())->id; + for (int i = 0; i < 5; ++i) + for (int j = 0; j < 2; ++j) + x34_weapons[i][j] = factory.GetResourceIdByName(GetWeapon(i, j).c_str())->id; - for (int i=0 ; i<5 ; ++i) - x84_muzzle[i] = factory.GetResourceIdByName(GetMuzzleParticle(i).c_str())->id; + for (int i = 0; i < 5; ++i) + x84_muzzle[i] = factory.GetResourceIdByName(GetMuzzleParticle(i).c_str())->id; - for (int i=0 ; i<5 ; ++i) - x94_charge[i] = factory.GetResourceIdByName(GetChargeParticle(i).c_str())->id; + for (int i = 0; i < 5; ++i) + x94_charge[i] = factory.GetResourceIdByName(GetChargeParticle(i).c_str())->id; - for (int i=0 ; i<5 ; ++i) - xa4_auxMuzzle[i] = factory.GetResourceIdByName(GetAuxMuzzleParticle(i).c_str())->id; + for (int i = 0; i < 5; ++i) + xa4_auxMuzzle[i] = factory.GetResourceIdByName(GetAuxMuzzleParticle(i).c_str())->id; - xb4_grappleSegment = factory.GetResourceIdByName(GetGrappleSegmentParticle().c_str())->id; - xb8_grappleClaw = factory.GetResourceIdByName(GetGrappleClawParticle().c_str())->id; - xbc_grappleHit = factory.GetResourceIdByName(GetGrappleHitParticle().c_str())->id; - xc0_grappleMuzzle = factory.GetResourceIdByName(GetGrappleMuzzleParticle().c_str())->id; - xc4_grappleSwoosh = factory.GetResourceIdByName(GetGrappleSwooshParticle().c_str())->id; - } + xb4_grappleSegment = factory.GetResourceIdByName(GetGrappleSegmentParticle().c_str())->id; + xb8_grappleClaw = factory.GetResourceIdByName(GetGrappleClawParticle().c_str())->id; + xbc_grappleHit = factory.GetResourceIdByName(GetGrappleHitParticle().c_str())->id; + xc0_grappleMuzzle = factory.GetResourceIdByName(GetGrappleMuzzleParticle().c_str())->id; + xc4_grappleSwoosh = factory.GetResourceIdByName(GetGrappleSwooshParticle().c_str())->id; + } protected: - virtual const std::string& GetGunMotion() const=0; - virtual const std::string& GetGrappleArm() const=0; - virtual const std::string& GetRightHand() const=0; + virtual const std::string& GetGunMotion() const = 0; + virtual const std::string& GetGrappleArm() const = 0; + virtual const std::string& GetRightHand() const = 0; - virtual const std::string& GetPowerBeam() const=0; - virtual const std::string& GetIceBeam() const=0; - virtual const std::string& GetWaveBeam() const=0; - virtual const std::string& GetPlasmaBeam() const=0; - virtual const std::string& GetPhazonBeam() const=0; + virtual const std::string& GetPowerBeam() const = 0; + virtual const std::string& GetIceBeam() const = 0; + virtual const std::string& GetWaveBeam() const = 0; + virtual const std::string& GetPlasmaBeam() const = 0; + virtual const std::string& GetPhazonBeam() const = 0; - virtual const std::string& GetHoloTransition() const=0; + virtual const std::string& GetHoloTransition() const = 0; - virtual const std::string& GetBombSet() const=0; - virtual const std::string& GetBombExplode() const=0; - virtual const std::string& GetPowerBombExplode() const=0; + virtual const std::string& GetBombSet() const = 0; + virtual const std::string& GetBombExplode() const = 0; + virtual const std::string& GetPowerBombExplode() const = 0; - virtual const std::string& GetWeapon(size_t idx, bool ball) const=0; - virtual const std::string& GetMuzzleParticle(size_t idx) const=0; - virtual const std::string& GetChargeParticle(size_t idx) const=0; - virtual const std::string& GetAuxMuzzleParticle(size_t idx) const=0; + virtual const std::string& GetWeapon(size_t idx, bool ball) const = 0; + virtual const std::string& GetMuzzleParticle(size_t idx) const = 0; + virtual const std::string& GetChargeParticle(size_t idx) const = 0; + virtual const std::string& GetAuxMuzzleParticle(size_t idx) const = 0; - virtual const std::string& GetGrappleSegmentParticle() const=0; - virtual const std::string& GetGrappleClawParticle() const=0; - virtual const std::string& GetGrappleHitParticle() const=0; - virtual const std::string& GetGrappleMuzzleParticle() const=0; - virtual const std::string& GetGrappleSwooshParticle() const=0; + virtual const std::string& GetGrappleSegmentParticle() const = 0; + virtual const std::string& GetGrappleClawParticle() const = 0; + virtual const std::string& GetGrappleHitParticle() const = 0; + virtual const std::string& GetGrappleMuzzleParticle() const = 0; + virtual const std::string& GetGrappleSwooshParticle() const = 0; }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/Tweaks/ITweakParticle.hpp b/DataSpec/DNACommon/Tweaks/ITweakParticle.hpp index 5515ca585..80a7dceb0 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakParticle.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakParticle.hpp @@ -2,12 +2,8 @@ #include "ITweak.hpp" -namespace DataSpec -{ +namespace DataSpec { -struct ITweakParticle : ITweak -{ -}; - -} +struct ITweakParticle : ITweak {}; +} // namespace DataSpec diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp index 4bc3102c3..ca5592846 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp @@ -3,145 +3,142 @@ #include "ITweak.hpp" #include "zeus/CAABox.hpp" -namespace DataSpec -{ +namespace DataSpec { -struct ITweakPlayer : ITweak -{ - virtual float GetMaxTranslationalAcceleration(int s) const=0; - virtual float GetMaxRotationalAcceleration(int s) const=0; - virtual float GetPlayerTranslationFriction(int s) const=0; - virtual float GetPlayerRotationFriction(int s) const=0; - virtual float GetPlayerRotationMaxSpeed(int s) const=0; - virtual float GetPlayerTranslationMaxSpeed(int s) const=0; - virtual float GetNormalGravAccel() const=0; - virtual float GetFluidGravAccel() const=0; - virtual float GetVerticalJumpAccel() const=0; - virtual float GetHorizontalJumpAccel() const=0; - virtual float GetVerticalDoubleJumpAccel() const=0; - virtual float GetHorizontalDoubleJumpAccel() const=0; - virtual float GetWaterJumpFactor() const=0; - virtual float GetWaterBallJumpFactor() const=0; - virtual float GetLavaJumpFactor() const=0; - virtual float GetLavaBallJumpFactor() const=0; - virtual float GetPhazonJumpFactor() const=0; - virtual float GetPhazonBallJumpFactor() const=0; - virtual float GetAllowedJumpTime() const=0; - virtual float GetAllowedDoubleJumpTime() const=0; - virtual float GetMinDoubleJumpWindow() const=0; - virtual float GetMaxDoubleJumpWindow() const=0; - virtual float GetMinJumpTime() const=0; - virtual float GetMinDoubleJumpTime() const=0; - virtual float GetAllowedLedgeTime() const=0; - virtual float GetDoubleJumpImpulse() const=0; - virtual float GetBackwardsForceMultiplier() const=0; - virtual float GetBombJumpRadius() const=0; - virtual float GetBombJumpHeight() const=0; - virtual float GetEyeOffset() const=0; - virtual float GetTurnSpeedMultiplier() const=0; - virtual float GetFreeLookTurnSpeedMultiplier() const=0; - virtual float GetFreeLookSpeed() const=0; - virtual float GetFreeLookSnapSpeed() const=0; - virtual float GetFreeLookCenteredThresholdAngle() const=0; - virtual float GetFreeLookCenteredTime() const=0; - virtual float GetOrbitModeTimer() const=0; - virtual float GetOrbitUpperAngle() const=0; - virtual float GetOrbitLowerAngle() const=0; - virtual float GetOrbitHorizAngle() const=0; - virtual float GetOrbitMaxTargetDistance() const=0; - virtual float GetOrbitMaxLockDistance() const=0; - virtual float GetOrbitDistanceThreshold() const=0; - virtual uint32_t GetOrbitScreenBoxHalfExtentX(int zone) const=0; - virtual uint32_t GetOrbitScreenBoxHalfExtentY(int zone) const=0; - virtual uint32_t GetOrbitScreenBoxCenterX(int zone) const=0; - virtual uint32_t GetOrbitScreenBoxCenterY(int zone) const=0; - virtual uint32_t GetOrbitZoneIdealX(int zone) const=0; - virtual uint32_t GetOrbitZoneIdealY(int zone) const=0; - virtual float GetOrbitNearX() const=0; - virtual float GetOrbitNearZ() const=0; - virtual float GetOrbitFixedOffsetZDiff() const=0; - virtual float GetOrbitZRange() const=0; - virtual bool GetDashEnabled() const=0; - virtual bool GetDashOnButtonRelease() const=0; - virtual float GetDashButtonHoldCancelTime() const=0; - virtual float GetDashStrafeInputThreshold() const=0; - virtual float GetSidewaysDoubleJumpImpulse() const=0; - virtual float GetSidewaysVerticalDoubleJumpAccel() const=0; - virtual float GetSidewaysHorizontalDoubleJumpAccel() const=0; - virtual float GetScanningRange() const=0; // x218 - virtual bool GetScanRetention() const=0; - virtual bool GetScanFreezesGame() const=0; // x21c_25 - virtual bool GetOrbitWhileScanning() const=0; - virtual bool GetFallingDoubleJump() const=0; - virtual bool GetImpulseDoubleJump() const=0; - virtual bool GetFiringCancelsCameraPitch() const=0; - virtual bool GetAssistedAimingIgnoreHorizontal() const=0; - virtual bool GetAssistedAimingIgnoreVertical() const=0; - virtual float GetAimMaxDistance() const=0; - virtual float GetAimThresholdDistance() const=0; - virtual float GetAimBoxWidth() const=0; - virtual float GetAimBoxHeight() const=0; - virtual float GetAimTargetTimer() const=0; - virtual float GetAimAssistHorizontalAngle() const=0; - virtual float GetAimAssistVerticalAngle() const=0; - virtual float GetScanMaxTargetDistance() const=0; - virtual float GetScanMaxLockDistance() const=0; - virtual bool GetMoveDuringFreeLook() const=0; - virtual bool GetHoldButtonsForFreeLook() const=0; - virtual bool GetTwoButtonsForFreeLook() const=0; - virtual bool GetAimWhenOrbitingPoint() const=0; - virtual bool GetStayInFreeLookWhileFiring() const=0; - virtual bool GetOrbitFixedOffset() const=0; - virtual bool GetGunButtonTogglesHolster() const=0; - virtual bool GetGunNotFiringHolstersGun() const=0; - virtual float GetPlayerHeight() const=0; // x26c - virtual float GetPlayerXYHalfExtent() const=0; // x270 - virtual bool GetFreeLookTurnsPlayer() const=0; // x228_24 - virtual float GetStepUpHeight() const=0; // x274 - virtual float GetStepDownHeight() const=0; // x278 - virtual float GetPlayerBallHalfExtent() const=0; // x27c - virtual float GetOrbitDistanceMax() const=0; - virtual float GetGrappleSwingLength() const=0; - virtual float GetGrappleSwingPeriod() const=0; - virtual float GetGrapplePullSpeedMin() const=0; - virtual float GetMaxGrappleLockedTurnAlignDistance() const=0; - virtual float GetGrapplePullSpeedProportion() const=0; - virtual float GetGrapplePullSpeedMax() const=0; - virtual float GetGrappleLookCenterSpeed() const=0; - virtual float GetMaxGrappleTurnSpeed() const=0; - virtual float GetGrappleJumpForce() const=0; - virtual float GetGrappleReleaseTime() const=0; - virtual uint32_t GetGrappleJumpMode() const=0; - virtual bool GetOrbitReleaseBreaksGrapple() const=0; - virtual bool GetInvertGrappleTurn() const=0; - virtual float GetGrappleBeamSpeed() const=0; - virtual float GetGrappleBeamXWaveAmplitude() const=0; - virtual float GetGrappleBeamZWaveAmplitude() const=0; - virtual float GetGrappleBeamAnglePhaseDelta() const=0; - virtual float GetHorizontalFreeLookAngleVel() const=0; - virtual float GetVerticalFreeLookAngleVel() const=0; // x134 - virtual float GetOrbitCameraSpeed() const=0; // x184 - virtual float GetOrbitPreventionTime() const=0; - virtual float GetJumpCameraPitchDownStart() const=0; // x288 - virtual float GetJumpCameraPitchDownFull() const=0; // x28c - virtual float GetJumpCameraPitchDownAngle() const=0; // x290 - virtual float GetFallCameraPitchDownStart() const=0; // x294 - virtual float GetFallCameraPitchDownFull() const=0; // x298 - virtual float GetFallCameraPitchDownAngle() const=0; // x29c - virtual float GetFirstPersonCameraSpeed() const=0; // x280 - virtual float GetGrappleCameraSpeed() const=0; // x2b0 - virtual float GetFreeLookDampenFactor() const=0; // x14c - virtual float GetLeftLogicalThreshold() const=0; - virtual float GetRightLogicalThreshold() const=0; - virtual float GetOrbitMinDistance(int type) const=0; - virtual float GetOrbitNormalDistance(int type) const=0; - virtual float GetOrbitMaxDistance(int type) const=0; - virtual float GetFrozenTimeout() const=0; - virtual uint32_t GetIceBreakJumpCount() const=0; - virtual float GetVariaDamageReduction() const=0; - virtual float GetGravityDamageReduction() const=0; - virtual float GetPhazonDamageReduction() const=0; +struct ITweakPlayer : ITweak { + virtual float GetMaxTranslationalAcceleration(int s) const = 0; + virtual float GetMaxRotationalAcceleration(int s) const = 0; + virtual float GetPlayerTranslationFriction(int s) const = 0; + virtual float GetPlayerRotationFriction(int s) const = 0; + virtual float GetPlayerRotationMaxSpeed(int s) const = 0; + virtual float GetPlayerTranslationMaxSpeed(int s) const = 0; + virtual float GetNormalGravAccel() const = 0; + virtual float GetFluidGravAccel() const = 0; + virtual float GetVerticalJumpAccel() const = 0; + virtual float GetHorizontalJumpAccel() const = 0; + virtual float GetVerticalDoubleJumpAccel() const = 0; + virtual float GetHorizontalDoubleJumpAccel() const = 0; + virtual float GetWaterJumpFactor() const = 0; + virtual float GetWaterBallJumpFactor() const = 0; + virtual float GetLavaJumpFactor() const = 0; + virtual float GetLavaBallJumpFactor() const = 0; + virtual float GetPhazonJumpFactor() const = 0; + virtual float GetPhazonBallJumpFactor() const = 0; + virtual float GetAllowedJumpTime() const = 0; + virtual float GetAllowedDoubleJumpTime() const = 0; + virtual float GetMinDoubleJumpWindow() const = 0; + virtual float GetMaxDoubleJumpWindow() const = 0; + virtual float GetMinJumpTime() const = 0; + virtual float GetMinDoubleJumpTime() const = 0; + virtual float GetAllowedLedgeTime() const = 0; + virtual float GetDoubleJumpImpulse() const = 0; + virtual float GetBackwardsForceMultiplier() const = 0; + virtual float GetBombJumpRadius() const = 0; + virtual float GetBombJumpHeight() const = 0; + virtual float GetEyeOffset() const = 0; + virtual float GetTurnSpeedMultiplier() const = 0; + virtual float GetFreeLookTurnSpeedMultiplier() const = 0; + virtual float GetFreeLookSpeed() const = 0; + virtual float GetFreeLookSnapSpeed() const = 0; + virtual float GetFreeLookCenteredThresholdAngle() const = 0; + virtual float GetFreeLookCenteredTime() const = 0; + virtual float GetOrbitModeTimer() const = 0; + virtual float GetOrbitUpperAngle() const = 0; + virtual float GetOrbitLowerAngle() const = 0; + virtual float GetOrbitHorizAngle() const = 0; + virtual float GetOrbitMaxTargetDistance() const = 0; + virtual float GetOrbitMaxLockDistance() const = 0; + virtual float GetOrbitDistanceThreshold() const = 0; + virtual uint32_t GetOrbitScreenBoxHalfExtentX(int zone) const = 0; + virtual uint32_t GetOrbitScreenBoxHalfExtentY(int zone) const = 0; + virtual uint32_t GetOrbitScreenBoxCenterX(int zone) const = 0; + virtual uint32_t GetOrbitScreenBoxCenterY(int zone) const = 0; + virtual uint32_t GetOrbitZoneIdealX(int zone) const = 0; + virtual uint32_t GetOrbitZoneIdealY(int zone) const = 0; + virtual float GetOrbitNearX() const = 0; + virtual float GetOrbitNearZ() const = 0; + virtual float GetOrbitFixedOffsetZDiff() const = 0; + virtual float GetOrbitZRange() const = 0; + virtual bool GetDashEnabled() const = 0; + virtual bool GetDashOnButtonRelease() const = 0; + virtual float GetDashButtonHoldCancelTime() const = 0; + virtual float GetDashStrafeInputThreshold() const = 0; + virtual float GetSidewaysDoubleJumpImpulse() const = 0; + virtual float GetSidewaysVerticalDoubleJumpAccel() const = 0; + virtual float GetSidewaysHorizontalDoubleJumpAccel() const = 0; + virtual float GetScanningRange() const = 0; // x218 + virtual bool GetScanRetention() const = 0; + virtual bool GetScanFreezesGame() const = 0; // x21c_25 + virtual bool GetOrbitWhileScanning() const = 0; + virtual bool GetFallingDoubleJump() const = 0; + virtual bool GetImpulseDoubleJump() const = 0; + virtual bool GetFiringCancelsCameraPitch() const = 0; + virtual bool GetAssistedAimingIgnoreHorizontal() const = 0; + virtual bool GetAssistedAimingIgnoreVertical() const = 0; + virtual float GetAimMaxDistance() const = 0; + virtual float GetAimThresholdDistance() const = 0; + virtual float GetAimBoxWidth() const = 0; + virtual float GetAimBoxHeight() const = 0; + virtual float GetAimTargetTimer() const = 0; + virtual float GetAimAssistHorizontalAngle() const = 0; + virtual float GetAimAssistVerticalAngle() const = 0; + virtual float GetScanMaxTargetDistance() const = 0; + virtual float GetScanMaxLockDistance() const = 0; + virtual bool GetMoveDuringFreeLook() const = 0; + virtual bool GetHoldButtonsForFreeLook() const = 0; + virtual bool GetTwoButtonsForFreeLook() const = 0; + virtual bool GetAimWhenOrbitingPoint() const = 0; + virtual bool GetStayInFreeLookWhileFiring() const = 0; + virtual bool GetOrbitFixedOffset() const = 0; + virtual bool GetGunButtonTogglesHolster() const = 0; + virtual bool GetGunNotFiringHolstersGun() const = 0; + virtual float GetPlayerHeight() const = 0; // x26c + virtual float GetPlayerXYHalfExtent() const = 0; // x270 + virtual bool GetFreeLookTurnsPlayer() const = 0; // x228_24 + virtual float GetStepUpHeight() const = 0; // x274 + virtual float GetStepDownHeight() const = 0; // x278 + virtual float GetPlayerBallHalfExtent() const = 0; // x27c + virtual float GetOrbitDistanceMax() const = 0; + virtual float GetGrappleSwingLength() const = 0; + virtual float GetGrappleSwingPeriod() const = 0; + virtual float GetGrapplePullSpeedMin() const = 0; + virtual float GetMaxGrappleLockedTurnAlignDistance() const = 0; + virtual float GetGrapplePullSpeedProportion() const = 0; + virtual float GetGrapplePullSpeedMax() const = 0; + virtual float GetGrappleLookCenterSpeed() const = 0; + virtual float GetMaxGrappleTurnSpeed() const = 0; + virtual float GetGrappleJumpForce() const = 0; + virtual float GetGrappleReleaseTime() const = 0; + virtual uint32_t GetGrappleJumpMode() const = 0; + virtual bool GetOrbitReleaseBreaksGrapple() const = 0; + virtual bool GetInvertGrappleTurn() const = 0; + virtual float GetGrappleBeamSpeed() const = 0; + virtual float GetGrappleBeamXWaveAmplitude() const = 0; + virtual float GetGrappleBeamZWaveAmplitude() const = 0; + virtual float GetGrappleBeamAnglePhaseDelta() const = 0; + virtual float GetHorizontalFreeLookAngleVel() const = 0; + virtual float GetVerticalFreeLookAngleVel() const = 0; // x134 + virtual float GetOrbitCameraSpeed() const = 0; // x184 + virtual float GetOrbitPreventionTime() const = 0; + virtual float GetJumpCameraPitchDownStart() const = 0; // x288 + virtual float GetJumpCameraPitchDownFull() const = 0; // x28c + virtual float GetJumpCameraPitchDownAngle() const = 0; // x290 + virtual float GetFallCameraPitchDownStart() const = 0; // x294 + virtual float GetFallCameraPitchDownFull() const = 0; // x298 + virtual float GetFallCameraPitchDownAngle() const = 0; // x29c + virtual float GetFirstPersonCameraSpeed() const = 0; // x280 + virtual float GetGrappleCameraSpeed() const = 0; // x2b0 + virtual float GetFreeLookDampenFactor() const = 0; // x14c + virtual float GetLeftLogicalThreshold() const = 0; + virtual float GetRightLogicalThreshold() const = 0; + virtual float GetOrbitMinDistance(int type) const = 0; + virtual float GetOrbitNormalDistance(int type) const = 0; + virtual float GetOrbitMaxDistance(int type) const = 0; + virtual float GetFrozenTimeout() const = 0; + virtual uint32_t GetIceBreakJumpCount() const = 0; + virtual float GetVariaDamageReduction() const = 0; + virtual float GetGravityDamageReduction() const = 0; + virtual float GetPhazonDamageReduction() const = 0; }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayerControl.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayerControl.hpp index 6cc9b8c95..6f523e10c 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakPlayerControl.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakPlayerControl.hpp @@ -2,13 +2,10 @@ #include "ITweak.hpp" -namespace DataSpec -{ +namespace DataSpec { -struct ITweakPlayerControl : ITweak -{ - virtual atUint32 GetMapping(atUint32) const=0; +struct ITweakPlayerControl : ITweak { + virtual atUint32 GetMapping(atUint32) const = 0; }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp index 5ca7f2e72..9f9ffa00f 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp @@ -3,72 +3,70 @@ #include "ITweak.hpp" #include "zeus/CAABox.hpp" -namespace DataSpec -{ +namespace DataSpec { /* Same as CDamageInfo */ -struct SShotParam : BigDNA -{ - AT_DECL_DNA_YAML - Value weaponType = -1; - bool charged : 1; - bool combo : 1; - bool instaKill : 1; - Value damage = 0.f; - Value radiusDamage = 0.f; - Value radius = 0.f; - Value knockback = 0.f; - bool noImmunity : 1; - SShotParam() { charged = false; combo = false; instaKill = false; noImmunity = false; } +struct SShotParam : BigDNA { + AT_DECL_DNA_YAML + Value weaponType = -1; + bool charged : 1; + bool combo : 1; + bool instaKill : 1; + Value damage = 0.f; + Value radiusDamage = 0.f; + Value radius = 0.f; + Value knockback = 0.f; + bool noImmunity : 1; + SShotParam() { + charged = false; + combo = false; + instaKill = false; + noImmunity = false; + } }; -struct SComboShotParam : SShotParam -{ - AT_DECL_DNA_YAML - SComboShotParam() { combo = true; } +struct SComboShotParam : SShotParam { + AT_DECL_DNA_YAML + SComboShotParam() { combo = true; } }; -struct SChargedShotParam : SShotParam -{ - AT_DECL_DNA_YAML - SChargedShotParam() { charged = true; } +struct SChargedShotParam : SShotParam { + AT_DECL_DNA_YAML + SChargedShotParam() { charged = true; } }; -struct SWeaponInfo : BigDNA -{ - AT_DECL_DNA_YAML - Value x0_coolDown = 0.1f; - SShotParam x4_normal; - SChargedShotParam x20_charged; +struct SWeaponInfo : BigDNA { + AT_DECL_DNA_YAML + Value x0_coolDown = 0.1f; + SShotParam x4_normal; + SChargedShotParam x20_charged; }; -struct ITweakPlayerGun : ITweak -{ - AT_DECL_DNA_YAML - virtual float GetUpLookAngle() const = 0; - virtual float GetDownLookAngle() const = 0; - virtual float GetVerticalSpread() const = 0; - virtual float GetHorizontalSpread() const = 0; - virtual float GetHighVerticalSpread() const = 0; - virtual float GetHighHorizontalSpread() const = 0; - virtual float GetLowVerticalSpread() const = 0; - virtual float GetLowHorizontalSpread() const = 0; - virtual float GetAimVerticalSpeed() const = 0; // x24 - virtual float GetAimHorizontalSpeed() const = 0; // x28 - virtual float GetBombFuseTime() const = 0; // x2c - virtual float GetBombDropDelayTime() const = 0; // x30 - virtual float GetHoloHoldTime() const = 0; // x34 - virtual float GetGunTransformTime() const = 0; // x38 - virtual float GetGunHolsterTime() const = 0; - virtual float GetGunNotFiringTime() const = 0; - virtual float GetFixedVerticalAim() const = 0; - virtual float GetGunExtendDistance() const = 0; - virtual const zeus::CVector3f& GetGunPosition() const = 0; - virtual const zeus::CVector3f& GetGrapplingArmPosition() const = 0; - virtual float GetRichochetDamage(atUint32) const = 0; - virtual const SWeaponInfo& GetBeamInfo(atInt32 beam) const = 0; - virtual const SComboShotParam& GetComboShotInfo(atInt32 beam) const = 0; - virtual const SShotParam& GetBombInfo() const=0; - virtual const SShotParam& GetPowerBombInfo() const=0; +struct ITweakPlayerGun : ITweak { + AT_DECL_DNA_YAML + virtual float GetUpLookAngle() const = 0; + virtual float GetDownLookAngle() const = 0; + virtual float GetVerticalSpread() const = 0; + virtual float GetHorizontalSpread() const = 0; + virtual float GetHighVerticalSpread() const = 0; + virtual float GetHighHorizontalSpread() const = 0; + virtual float GetLowVerticalSpread() const = 0; + virtual float GetLowHorizontalSpread() const = 0; + virtual float GetAimVerticalSpeed() const = 0; // x24 + virtual float GetAimHorizontalSpeed() const = 0; // x28 + virtual float GetBombFuseTime() const = 0; // x2c + virtual float GetBombDropDelayTime() const = 0; // x30 + virtual float GetHoloHoldTime() const = 0; // x34 + virtual float GetGunTransformTime() const = 0; // x38 + virtual float GetGunHolsterTime() const = 0; + virtual float GetGunNotFiringTime() const = 0; + virtual float GetFixedVerticalAim() const = 0; + virtual float GetGunExtendDistance() const = 0; + virtual const zeus::CVector3f& GetGunPosition() const = 0; + virtual const zeus::CVector3f& GetGrapplingArmPosition() const = 0; + virtual float GetRichochetDamage(atUint32) const = 0; + virtual const SWeaponInfo& GetBeamInfo(atInt32 beam) const = 0; + virtual const SComboShotParam& GetComboShotInfo(atInt32 beam) const = 0; + virtual const SShotParam& GetBombInfo() const = 0; + virtual const SShotParam& GetPowerBombInfo() const = 0; }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp index fcc6152ca..4b7c2b8aa 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakPlayerRes.hpp @@ -4,163 +4,155 @@ #include "Runtime/IFactory.hpp" #include "Runtime/CPlayerState.hpp" -namespace DataSpec -{ +namespace DataSpec { -struct ITweakPlayerRes : ITweak -{ - using ResId = urde::CAssetId; - using EBeamId = urde::CPlayerState::EBeamId; +struct ITweakPlayerRes : ITweak { + using ResId = urde::CAssetId; + using EBeamId = urde::CPlayerState::EBeamId; - ResId x4_saveStationIcon; - ResId x8_missileStationIcon; - ResId xc_elevatorIcon; + ResId x4_saveStationIcon; + ResId x8_missileStationIcon; + ResId xc_elevatorIcon; - ResId x10_minesBreakFirstTopIcon; - ResId x14_minesBreakFirstBottomIcon; - ResId x18_minesBreakSecondTopIcon; - ResId x1c_minesBreakSecondBottomIcon; + ResId x10_minesBreakFirstTopIcon; + ResId x14_minesBreakFirstBottomIcon; + ResId x18_minesBreakSecondTopIcon; + ResId x1c_minesBreakSecondBottomIcon; - /* N, U, UL, L, DL, D, DR, R, UR */ - ResId x24_lStick[9]; - ResId x4c_cStick[9]; + /* N, U, UL, L, DL, D, DR, R, UR */ + ResId x24_lStick[9]; + ResId x4c_cStick[9]; - /* Out, In */ - ResId x74_lTrigger[2]; - ResId x80_rTrigger[2]; - ResId x8c_startButton[2]; - ResId x98_aButton[2]; - ResId xa4_bButton[2]; - ResId xb0_xButton[2]; - ResId xbc_yButton[2]; + /* Out, In */ + ResId x74_lTrigger[2]; + ResId x80_rTrigger[2]; + ResId x8c_startButton[2]; + ResId x98_aButton[2]; + ResId xa4_bButton[2]; + ResId xb0_xButton[2]; + ResId xbc_yButton[2]; - ResId xc4_ballTransitionsANCS; + ResId xc4_ballTransitionsANCS; - /* Power, Ice, Wave, Plasma, Phazon */ - ResId xc8_ballTransitions[5]; - ResId xc8_cineGun[5]; + /* Power, Ice, Wave, Plasma, Phazon */ + ResId xc8_ballTransitions[5]; + ResId xc8_cineGun[5]; - float xf0_cinematicMoveOutofIntoPlayerDistance; + float xf0_cinematicMoveOutofIntoPlayerDistance; - ResId GetBeamBallTransitionModel(EBeamId beam) const - { - int b = int(beam); - if (b < 0 || b > 4) - b = 0; - switch (EBeamId(b)) - { - case EBeamId::Power: - default: - return xc8_ballTransitions[0]; - case EBeamId::Ice: - return xc8_ballTransitions[1]; - case EBeamId::Wave: - return xc8_ballTransitions[2]; - case EBeamId::Plasma: - return xc8_ballTransitions[3]; - case EBeamId::Phazon: - return xc8_ballTransitions[4]; - } + ResId GetBeamBallTransitionModel(EBeamId beam) const { + int b = int(beam); + if (b < 0 || b > 4) + b = 0; + switch (EBeamId(b)) { + case EBeamId::Power: + default: + return xc8_ballTransitions[0]; + case EBeamId::Ice: + return xc8_ballTransitions[1]; + case EBeamId::Wave: + return xc8_ballTransitions[2]; + case EBeamId::Plasma: + return xc8_ballTransitions[3]; + case EBeamId::Phazon: + return xc8_ballTransitions[4]; } + } - ResId GetBeamCineModel(EBeamId beam) const - { - int b = int(beam); - if (b < 0 || b > 4) - b = 0; - switch (EBeamId(b)) - { - case EBeamId::Power: - default: - return xc8_cineGun[0]; - case EBeamId::Ice: - return xc8_cineGun[1]; - case EBeamId::Wave: - return xc8_cineGun[2]; - case EBeamId::Plasma: - return xc8_cineGun[3]; - case EBeamId::Phazon: - return xc8_cineGun[4]; - } + ResId GetBeamCineModel(EBeamId beam) const { + int b = int(beam); + if (b < 0 || b > 4) + b = 0; + switch (EBeamId(b)) { + case EBeamId::Power: + default: + return xc8_cineGun[0]; + case EBeamId::Ice: + return xc8_cineGun[1]; + case EBeamId::Wave: + return xc8_cineGun[2]; + case EBeamId::Plasma: + return xc8_cineGun[3]; + case EBeamId::Phazon: + return xc8_cineGun[4]; } + } - void ResolveResources(const urde::IFactory& factory) - { - x4_saveStationIcon = factory.GetResourceIdByName(_GetSaveStationIcon().data())->id; - x8_missileStationIcon = factory.GetResourceIdByName(_GetMissileStationIcon().data())->id; - xc_elevatorIcon = factory.GetResourceIdByName(_GetElevatorIcon().data())->id; + void ResolveResources(const urde::IFactory& factory) { + x4_saveStationIcon = factory.GetResourceIdByName(_GetSaveStationIcon().data())->id; + x8_missileStationIcon = factory.GetResourceIdByName(_GetMissileStationIcon().data())->id; + xc_elevatorIcon = factory.GetResourceIdByName(_GetElevatorIcon().data())->id; - x10_minesBreakFirstTopIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id; - x14_minesBreakFirstBottomIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id; - x18_minesBreakSecondTopIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id; - x1c_minesBreakSecondBottomIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id; + x10_minesBreakFirstTopIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id; + x14_minesBreakFirstBottomIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id; + x18_minesBreakSecondTopIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id; + x1c_minesBreakSecondBottomIcon = factory.GetResourceIdByName(_GetMinesBreakFirstTopIcon().data())->id; - for (int i=0 ; i<9 ; ++i) - x24_lStick[i] = factory.GetResourceIdByName(_GetLStick(i).data())->id; + for (int i = 0; i < 9; ++i) + x24_lStick[i] = factory.GetResourceIdByName(_GetLStick(i).data())->id; - for (int i=0 ; i<9 ; ++i) - x4c_cStick[i] = factory.GetResourceIdByName(_GetCStick(i).data())->id; + for (int i = 0; i < 9; ++i) + x4c_cStick[i] = factory.GetResourceIdByName(_GetCStick(i).data())->id; - for (int i=0 ; i<2 ; ++i) - x74_lTrigger[i] = factory.GetResourceIdByName(_GetLTrigger(i).data())->id; + for (int i = 0; i < 2; ++i) + x74_lTrigger[i] = factory.GetResourceIdByName(_GetLTrigger(i).data())->id; - for (int i=0 ; i<2 ; ++i) - x80_rTrigger[i] = factory.GetResourceIdByName(_GetRTrigger(i).data())->id; + for (int i = 0; i < 2; ++i) + x80_rTrigger[i] = factory.GetResourceIdByName(_GetRTrigger(i).data())->id; - for (int i=0 ; i<2 ; ++i) - x8c_startButton[i] = factory.GetResourceIdByName(_GetStartButton(i).data())->id; + for (int i = 0; i < 2; ++i) + x8c_startButton[i] = factory.GetResourceIdByName(_GetStartButton(i).data())->id; - for (int i=0 ; i<2 ; ++i) - x98_aButton[i] = factory.GetResourceIdByName(_GetAButton(i).data())->id; + for (int i = 0; i < 2; ++i) + x98_aButton[i] = factory.GetResourceIdByName(_GetAButton(i).data())->id; - for (int i=0 ; i<2 ; ++i) - xa4_bButton[i] = factory.GetResourceIdByName(_GetBButton(i).data())->id; + for (int i = 0; i < 2; ++i) + xa4_bButton[i] = factory.GetResourceIdByName(_GetBButton(i).data())->id; - for (int i=0 ; i<2 ; ++i) - xb0_xButton[i] = factory.GetResourceIdByName(_GetXButton(i).data())->id; + for (int i = 0; i < 2; ++i) + xb0_xButton[i] = factory.GetResourceIdByName(_GetXButton(i).data())->id; - for (int i=0 ; i<2 ; ++i) - xbc_yButton[i] = factory.GetResourceIdByName(_GetYButton(i).data())->id; + for (int i = 0; i < 2; ++i) + xbc_yButton[i] = factory.GetResourceIdByName(_GetYButton(i).data())->id; - xc4_ballTransitionsANCS = factory.GetResourceIdByName(_GetBallTransitionsANCS().data())->id; + xc4_ballTransitionsANCS = factory.GetResourceIdByName(_GetBallTransitionsANCS().data())->id; - for (int i=0 ; i<5 ; ++i) - xc8_ballTransitions[i] = factory.GetResourceIdByName(_GetBallTransitionBeamRes(i).data())->id; + for (int i = 0; i < 5; ++i) + xc8_ballTransitions[i] = factory.GetResourceIdByName(_GetBallTransitionBeamRes(i).data())->id; - for (int i=0 ; i<5 ; ++i) - xc8_cineGun[i] = factory.GetResourceIdByName(_GetBeamCineModel(i).data())->id; + for (int i = 0; i < 5; ++i) + xc8_cineGun[i] = factory.GetResourceIdByName(_GetBeamCineModel(i).data())->id; - xf0_cinematicMoveOutofIntoPlayerDistance = _GetCinematicMoveOutofIntoPlayerDistance(); - } + xf0_cinematicMoveOutofIntoPlayerDistance = _GetCinematicMoveOutofIntoPlayerDistance(); + } protected: - virtual std::string_view _GetSaveStationIcon() const=0; - virtual std::string_view _GetMissileStationIcon() const=0; - virtual std::string_view _GetElevatorIcon() const=0; + virtual std::string_view _GetSaveStationIcon() const = 0; + virtual std::string_view _GetMissileStationIcon() const = 0; + virtual std::string_view _GetElevatorIcon() const = 0; - virtual std::string_view _GetMinesBreakFirstTopIcon() const=0; - virtual std::string_view _GetMinesBreakFirstBottomIcon() const=0; - virtual std::string_view _GetMinesBreakSecondTopIcon() const=0; - virtual std::string_view _GetMinesBreakSecondBottomIcon() const=0; + virtual std::string_view _GetMinesBreakFirstTopIcon() const = 0; + virtual std::string_view _GetMinesBreakFirstBottomIcon() const = 0; + virtual std::string_view _GetMinesBreakSecondTopIcon() const = 0; + virtual std::string_view _GetMinesBreakSecondBottomIcon() const = 0; - virtual std::string_view _GetLStick(size_t idx) const=0; - virtual std::string_view _GetCStick(size_t idx) const=0; + virtual std::string_view _GetLStick(size_t idx) const = 0; + virtual std::string_view _GetCStick(size_t idx) const = 0; - virtual std::string_view _GetLTrigger(size_t idx) const=0; - virtual std::string_view _GetRTrigger(size_t idx) const=0; - virtual std::string_view _GetStartButton(size_t idx) const=0; - virtual std::string_view _GetAButton(size_t idx) const=0; - virtual std::string_view _GetBButton(size_t idx) const=0; - virtual std::string_view _GetXButton(size_t idx) const=0; - virtual std::string_view _GetYButton(size_t idx) const=0; + virtual std::string_view _GetLTrigger(size_t idx) const = 0; + virtual std::string_view _GetRTrigger(size_t idx) const = 0; + virtual std::string_view _GetStartButton(size_t idx) const = 0; + virtual std::string_view _GetAButton(size_t idx) const = 0; + virtual std::string_view _GetBButton(size_t idx) const = 0; + virtual std::string_view _GetXButton(size_t idx) const = 0; + virtual std::string_view _GetYButton(size_t idx) const = 0; - virtual std::string_view _GetBallTransitionsANCS() const=0; + virtual std::string_view _GetBallTransitionsANCS() const = 0; - virtual std::string_view _GetBallTransitionBeamRes(size_t idx) const=0; - virtual std::string_view _GetBeamCineModel(size_t idx) const=0; + virtual std::string_view _GetBallTransitionBeamRes(size_t idx) const = 0; + virtual std::string_view _GetBeamCineModel(size_t idx) const = 0; - virtual float _GetCinematicMoveOutofIntoPlayerDistance() const=0; + virtual float _GetCinematicMoveOutofIntoPlayerDistance() const = 0; }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/Tweaks/ITweakSlideShow.hpp b/DataSpec/DNACommon/Tweaks/ITweakSlideShow.hpp index f32c45092..ab506b4e4 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakSlideShow.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakSlideShow.hpp @@ -2,17 +2,14 @@ #include "ITweak.hpp" -namespace DataSpec -{ +namespace DataSpec { -struct ITweakSlideShow : ITweak -{ - virtual std::string_view GetFont() const=0; - virtual const zeus::CColor& GetFontColor() const=0; - virtual const zeus::CColor& GetOutlineColor() const=0; - virtual float GetScanPercentInterval() const=0; - virtual float GetX54() const=0; +struct ITweakSlideShow : ITweak { + virtual std::string_view GetFont() const = 0; + virtual const zeus::CColor& GetFontColor() const = 0; + virtual const zeus::CColor& GetOutlineColor() const = 0; + virtual float GetScanPercentInterval() const = 0; + virtual float GetX54() const = 0; }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/Tweaks/ITweakTargeting.hpp b/DataSpec/DNACommon/Tweaks/ITweakTargeting.hpp index 1d9c1f75b..69042fc30 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakTargeting.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakTargeting.hpp @@ -1,98 +1,95 @@ #pragma once #include "ITweak.hpp" -namespace DataSpec -{ -struct ITweakTargeting : public ITweak -{ - virtual atUint32 GetTargetRadiusMode() const=0; - virtual float GetCurrLockOnExitDuration() const=0; - virtual float GetCurrLockOnEnterDuration() const=0; - virtual float GetCurrLockOnSwitchDuration() const=0; - virtual float GetLockConfirmScale() const=0; - virtual float GetNextLockOnEnterDuration() const=0; - virtual float GetNextLockOnExitDuration() const=0; - virtual float GetNextLockOnSwitchDuration() const=0; - virtual float GetSeekerScale() const=0; - virtual float GetSeekerAngleSpeed() const=0; - virtual float GetXRayRetAngleSpeed() const=0; - virtual float GetOrbitPointZOffset() const=0; - virtual float GetOrbitPointInTime() const=0; - virtual float GetOrbitPointOutTime() const=0; - virtual const zeus::CColor& GetThermalReticuleColor() const=0; - virtual float GetTargetFlowerScale() const=0; - virtual const zeus::CColor& GetTargetFlowerColor() const=0; - virtual float GetMissileBracketDuration() const=0; - virtual float GetMissileBracketScaleStart() const=0; - virtual float GetMissileBracketScaleEnd() const=0; - virtual float GetMissileBracketScaleDuration() const=0; - virtual const zeus::CColor& GetMissileBracketColor() const=0; - virtual float GetChargeGaugeOvershootOffset() const=0; - virtual float GetChargeGaugeOvershootDuration() const=0; - virtual float GetOuterBeamSquaresScale() const=0; - virtual const zeus::CColor& GetOuterBeamSquareColor() const=0; - virtual float GetLockonDuration() const=0; - virtual float GetInnerBeamScale() const=0; - virtual const zeus::CColor& GetInnerBeamColorPower() const=0; - virtual const zeus::CColor& GetInnerBeamColorIce() const=0; - virtual const zeus::CColor& GetInnerBeamColorWave() const=0; - virtual const zeus::CColor& GetInnerBeamColorPlasma() const=0; - virtual const float* GetOuterBeamSquareAngles(int i) const=0; - virtual float GetChargeGaugeAngle(int i) const=0; - virtual float GetChargeGaugeScale() const=0; - virtual const zeus::CColor& GetChargeGaugeNonFullColor() const=0; - virtual atUint32 GetChargeTickCount() const=0; - virtual float GetChargeTickAnglePitch() const=0; - virtual float GetLockFireScale() const=0; - virtual float GetLockFireDuration() const=0; - virtual const zeus::CColor& GetLockFireColor() const=0; - virtual float GetLockDaggerScaleStart() const=0; - virtual float GetLockDaggerScaleEnd() const=0; - virtual const zeus::CColor& GetLockDaggerColor() const=0; - virtual float GetLockDaggerAngle0() const=0; - virtual float GetLockDaggerAngle1() const=0; - virtual float GetLockDaggerAngle2() const=0; - virtual const zeus::CColor& GetLockConfirmColor() const=0; - virtual const zeus::CColor& GetSeekerColor() const=0; - virtual float GetLockConfirmClampMin() const=0; - virtual float GetLockConfirmClampMax() const=0; - virtual float GetTargetFlowerClampMin() const=0; - virtual float GetTargetFlowerClampMax() const=0; - virtual float GetSeekerClampMin() const=0; - virtual float GetSeekerClampMax() const=0; - virtual float GetMissileBracketClampMin() const=0; - virtual float GetMissileBracketClampMax() const=0; - virtual float GetInnerBeamClampMin() const=0; - virtual float GetInnerBeamClampMax() const=0; - virtual float GetChargeGaugeClampMin() const=0; - virtual float GetChargeGaugeClampMax() const=0; - virtual float GetLockFireClampMin() const=0; - virtual float GetLockFireClampMax() const=0; - virtual float GetLockDaggerClampMin() const=0; - virtual float GetLockDaggerClampMax() const=0; - virtual float GetGrappleSelectScale() const=0; - virtual float GetGrappleScale() const=0; - virtual float GetGrappleClampMin() const=0; - virtual float GetGrappleClampMax() const=0; - virtual const zeus::CColor& GetGrapplePointSelectColor() const=0; - virtual const zeus::CColor& GetGrapplePointColor() const=0; - virtual const zeus::CColor& GetLockedGrapplePointSelectColor() const=0; - virtual float GetGrappleMinClampScale() const=0; - virtual const zeus::CColor& GetChargeGaugePulseColorHigh() const=0; - virtual float GetFullChargeFadeDuration() const=0; - virtual const zeus::CColor& GetOrbitPointColor() const=0; - virtual const zeus::CColor& GetCrosshairsColor() const=0; - virtual float GetCrosshairsScaleDuration() const=0; - virtual bool DrawOrbitPoint() const=0; - virtual const zeus::CColor& GetChargeGaugePulseColorLow() const=0; - virtual float GetChargeGaugePulsePeriod() const=0; - virtual float GetReticuleClampMin() const=0; - virtual float GetReticuleClampMax() const=0; - virtual const zeus::CColor& GetXRayRetRingColor() const=0; - virtual float GetReticuleScale() const=0; - virtual float GetScanTargetClampMin() const=0; - virtual float GetScanTargetClampMax() const=0; - virtual float GetAngularLagSpeed() const=0; +namespace DataSpec { +struct ITweakTargeting : public ITweak { + virtual atUint32 GetTargetRadiusMode() const = 0; + virtual float GetCurrLockOnExitDuration() const = 0; + virtual float GetCurrLockOnEnterDuration() const = 0; + virtual float GetCurrLockOnSwitchDuration() const = 0; + virtual float GetLockConfirmScale() const = 0; + virtual float GetNextLockOnEnterDuration() const = 0; + virtual float GetNextLockOnExitDuration() const = 0; + virtual float GetNextLockOnSwitchDuration() const = 0; + virtual float GetSeekerScale() const = 0; + virtual float GetSeekerAngleSpeed() const = 0; + virtual float GetXRayRetAngleSpeed() const = 0; + virtual float GetOrbitPointZOffset() const = 0; + virtual float GetOrbitPointInTime() const = 0; + virtual float GetOrbitPointOutTime() const = 0; + virtual const zeus::CColor& GetThermalReticuleColor() const = 0; + virtual float GetTargetFlowerScale() const = 0; + virtual const zeus::CColor& GetTargetFlowerColor() const = 0; + virtual float GetMissileBracketDuration() const = 0; + virtual float GetMissileBracketScaleStart() const = 0; + virtual float GetMissileBracketScaleEnd() const = 0; + virtual float GetMissileBracketScaleDuration() const = 0; + virtual const zeus::CColor& GetMissileBracketColor() const = 0; + virtual float GetChargeGaugeOvershootOffset() const = 0; + virtual float GetChargeGaugeOvershootDuration() const = 0; + virtual float GetOuterBeamSquaresScale() const = 0; + virtual const zeus::CColor& GetOuterBeamSquareColor() const = 0; + virtual float GetLockonDuration() const = 0; + virtual float GetInnerBeamScale() const = 0; + virtual const zeus::CColor& GetInnerBeamColorPower() const = 0; + virtual const zeus::CColor& GetInnerBeamColorIce() const = 0; + virtual const zeus::CColor& GetInnerBeamColorWave() const = 0; + virtual const zeus::CColor& GetInnerBeamColorPlasma() const = 0; + virtual const float* GetOuterBeamSquareAngles(int i) const = 0; + virtual float GetChargeGaugeAngle(int i) const = 0; + virtual float GetChargeGaugeScale() const = 0; + virtual const zeus::CColor& GetChargeGaugeNonFullColor() const = 0; + virtual atUint32 GetChargeTickCount() const = 0; + virtual float GetChargeTickAnglePitch() const = 0; + virtual float GetLockFireScale() const = 0; + virtual float GetLockFireDuration() const = 0; + virtual const zeus::CColor& GetLockFireColor() const = 0; + virtual float GetLockDaggerScaleStart() const = 0; + virtual float GetLockDaggerScaleEnd() const = 0; + virtual const zeus::CColor& GetLockDaggerColor() const = 0; + virtual float GetLockDaggerAngle0() const = 0; + virtual float GetLockDaggerAngle1() const = 0; + virtual float GetLockDaggerAngle2() const = 0; + virtual const zeus::CColor& GetLockConfirmColor() const = 0; + virtual const zeus::CColor& GetSeekerColor() const = 0; + virtual float GetLockConfirmClampMin() const = 0; + virtual float GetLockConfirmClampMax() const = 0; + virtual float GetTargetFlowerClampMin() const = 0; + virtual float GetTargetFlowerClampMax() const = 0; + virtual float GetSeekerClampMin() const = 0; + virtual float GetSeekerClampMax() const = 0; + virtual float GetMissileBracketClampMin() const = 0; + virtual float GetMissileBracketClampMax() const = 0; + virtual float GetInnerBeamClampMin() const = 0; + virtual float GetInnerBeamClampMax() const = 0; + virtual float GetChargeGaugeClampMin() const = 0; + virtual float GetChargeGaugeClampMax() const = 0; + virtual float GetLockFireClampMin() const = 0; + virtual float GetLockFireClampMax() const = 0; + virtual float GetLockDaggerClampMin() const = 0; + virtual float GetLockDaggerClampMax() const = 0; + virtual float GetGrappleSelectScale() const = 0; + virtual float GetGrappleScale() const = 0; + virtual float GetGrappleClampMin() const = 0; + virtual float GetGrappleClampMax() const = 0; + virtual const zeus::CColor& GetGrapplePointSelectColor() const = 0; + virtual const zeus::CColor& GetGrapplePointColor() const = 0; + virtual const zeus::CColor& GetLockedGrapplePointSelectColor() const = 0; + virtual float GetGrappleMinClampScale() const = 0; + virtual const zeus::CColor& GetChargeGaugePulseColorHigh() const = 0; + virtual float GetFullChargeFadeDuration() const = 0; + virtual const zeus::CColor& GetOrbitPointColor() const = 0; + virtual const zeus::CColor& GetCrosshairsColor() const = 0; + virtual float GetCrosshairsScaleDuration() const = 0; + virtual bool DrawOrbitPoint() const = 0; + virtual const zeus::CColor& GetChargeGaugePulseColorLow() const = 0; + virtual float GetChargeGaugePulsePeriod() const = 0; + virtual float GetReticuleClampMin() const = 0; + virtual float GetReticuleClampMax() const = 0; + virtual const zeus::CColor& GetXRayRetRingColor() const = 0; + virtual float GetReticuleScale() const = 0; + virtual float GetScanTargetClampMin() const = 0; + virtual float GetScanTargetClampMax() const = 0; + virtual float GetAngularLagSpeed() const = 0; }; -} - +} // namespace DataSpec diff --git a/DataSpec/DNACommon/Tweaks/TweakWriter.hpp b/DataSpec/DNACommon/Tweaks/TweakWriter.hpp index 0a891921c..fd09d4c3e 100644 --- a/DataSpec/DNACommon/Tweaks/TweakWriter.hpp +++ b/DataSpec/DNACommon/Tweaks/TweakWriter.hpp @@ -2,36 +2,31 @@ #include "../PAK.hpp" -namespace DataSpec -{ +namespace DataSpec { template -bool WriteTweak(const T& tweak, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - tweak.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; -} - -template -bool ExtractTweak(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - T tweak; - tweak.read(rs); - athena::io::ToYAMLStream(tweak, writer); - return true; - } +bool WriteTweak(const T& tweak, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) return false; + tweak.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } +template +bool ExtractTweak(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + T tweak; + tweak.read(rs); + athena::io::ToYAMLStream(tweak, writer); + return true; + } + return false; } +} // namespace DataSpec diff --git a/DataSpec/DNACommon/WPSC.cpp b/DataSpec/DNACommon/WPSC.cpp index 7c460ee78..de727229f 100644 --- a/DataSpec/DNACommon/WPSC.cpp +++ b/DataSpec/DNACommon/WPSC.cpp @@ -1,775 +1,693 @@ #include "WPSC.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template -void WPSM::_read(athena::io::YAMLDocReader& r) -{ - for (const auto& elem : r.getCurNode()->m_mapChildren) - { - if (elem.first.size() < 4) - { - LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); - continue; - } - - if (auto rec = r.enterSubRecord(elem.first.c_str())) - { - switch (*reinterpret_cast(elem.first.data())) - { - case SBIG('IORN'): - x0_IORN.read(r); - break; - case SBIG('IVEC'): - x4_IVEC.read(r); - break; - case SBIG('PSOV'): - x8_PSOV.read(r); - break; - case SBIG('PSVM'): - xc_PSVM.read(r); - break; - case SBIG('VMD2'): - x10_VMD2.read(r); - break; - case SBIG('PSLT'): - x14_PSLT.read(r); - break; - case SBIG('PSCL'): - x18_PSCL.read(r); - break; - case SBIG('PCOL'): - x1c_PCOL.read(r); - break; - case SBIG('POFS'): - x20_POFS.read(r); - break; - case SBIG('OFST'): - x24_OFST.read(r); - break; - case SBIG('APSO'): - x28_APSO.read(r); - break; - case SBIG('HOMG'): - x29_HOMG.read(r); - break; - case SBIG('AP11'): - x2a_AP11.read(r); - break; - case SBIG('AP21'): - x2b_AP21.read(r); - break; - case SBIG('AS11'): - x2c_AS11.read(r); - break; - case SBIG('AS12'): - x2d_AS12.read(r); - break; - case SBIG('AS13'): - x2e_AS13.read(r); - break; - case SBIG('TRAT'): - x30_TRAT.read(r); - break; - case SBIG('APSM'): - x34_APSM.read(r); - break; - case SBIG('APS2'): - x44_APS2.read(r); - break; - case SBIG('ASW1'): - x54_ASW1.read(r); - break; - case SBIG('ASW2'): - x64_ASW2.read(r); - break; - case SBIG('ASW3'): - x74_ASW3.read(r); - break; - case SBIG('OHEF'): - x84_OHEF.read(r); - break; - case SBIG('COLR'): - x94_COLR.read(r); - break; - case SBIG('EWTR'): - xa4_EWTR.read(r); - break; - case SBIG('LWTR'): - xa5_LWTR.read(r); - break; - case SBIG('SWTR'): - xa6_SWTR.read(r); - break; - case SBIG('PJFX'): - xa8_PJFX = r.readUint32(nullptr); - break; - case SBIG('RNGE'): - xac_RNGE.read(r); - break; - case SBIG('FOFF'): - xb0_FOFF.read(r); - break; - case SBIG('FC60'): - xunk_FC60.read(r); - break; - case SBIG('SPS1'): - xunk_SPS2.read(r); - break; - case SBIG('SPS2'): - xunk_SPS2.read(r); - break; - } - } +void WPSM::_read(athena::io::YAMLDocReader& r) { + for (const auto& elem : r.getCurNode()->m_mapChildren) { + if (elem.first.size() < 4) { + LogModule.report(logvisor::Warning, "short FourCC in element '%s'", elem.first.c_str()); + continue; } + + if (auto rec = r.enterSubRecord(elem.first.c_str())) { + switch (*reinterpret_cast(elem.first.data())) { + case SBIG('IORN'): + x0_IORN.read(r); + break; + case SBIG('IVEC'): + x4_IVEC.read(r); + break; + case SBIG('PSOV'): + x8_PSOV.read(r); + break; + case SBIG('PSVM'): + xc_PSVM.read(r); + break; + case SBIG('VMD2'): + x10_VMD2.read(r); + break; + case SBIG('PSLT'): + x14_PSLT.read(r); + break; + case SBIG('PSCL'): + x18_PSCL.read(r); + break; + case SBIG('PCOL'): + x1c_PCOL.read(r); + break; + case SBIG('POFS'): + x20_POFS.read(r); + break; + case SBIG('OFST'): + x24_OFST.read(r); + break; + case SBIG('APSO'): + x28_APSO.read(r); + break; + case SBIG('HOMG'): + x29_HOMG.read(r); + break; + case SBIG('AP11'): + x2a_AP11.read(r); + break; + case SBIG('AP21'): + x2b_AP21.read(r); + break; + case SBIG('AS11'): + x2c_AS11.read(r); + break; + case SBIG('AS12'): + x2d_AS12.read(r); + break; + case SBIG('AS13'): + x2e_AS13.read(r); + break; + case SBIG('TRAT'): + x30_TRAT.read(r); + break; + case SBIG('APSM'): + x34_APSM.read(r); + break; + case SBIG('APS2'): + x44_APS2.read(r); + break; + case SBIG('ASW1'): + x54_ASW1.read(r); + break; + case SBIG('ASW2'): + x64_ASW2.read(r); + break; + case SBIG('ASW3'): + x74_ASW3.read(r); + break; + case SBIG('OHEF'): + x84_OHEF.read(r); + break; + case SBIG('COLR'): + x94_COLR.read(r); + break; + case SBIG('EWTR'): + xa4_EWTR.read(r); + break; + case SBIG('LWTR'): + xa5_LWTR.read(r); + break; + case SBIG('SWTR'): + xa6_SWTR.read(r); + break; + case SBIG('PJFX'): + xa8_PJFX = r.readUint32(nullptr); + break; + case SBIG('RNGE'): + xac_RNGE.read(r); + break; + case SBIG('FOFF'): + xb0_FOFF.read(r); + break; + case SBIG('FC60'): + xunk_FC60.read(r); + break; + case SBIG('SPS1'): + xunk_SPS2.read(r); + break; + case SBIG('SPS2'): + xunk_SPS2.read(r); + break; + } + } + } } template -void WPSM::_write(athena::io::YAMLDocWriter& w) const -{ - if (x0_IORN) - if (auto rec = w.enterSubRecord("IORN")) - x0_IORN.write(w); - if (x4_IVEC) - if (auto rec = w.enterSubRecord("IVEC")) - x4_IVEC.write(w); - if (x8_PSOV) - if (auto rec = w.enterSubRecord("PSOV")) - x8_PSOV.write(w); - if (xc_PSVM) - if (auto rec = w.enterSubRecord("PSVM")) - xc_PSVM.write(w); - if (x10_VMD2) - if (auto rec = w.enterSubRecord("VMD2")) - x10_VMD2.write(w); - if (x14_PSLT) - if (auto rec = w.enterSubRecord("PSLT")) - x14_PSLT.write(w); - if (x18_PSCL) - if (auto rec = w.enterSubRecord("PSCL")) - x18_PSCL.write(w); - if (x1c_PCOL) - if (auto rec = w.enterSubRecord("PCOL")) - x1c_PCOL.write(w); - if (x20_POFS) - if (auto rec = w.enterSubRecord("POFS")) - x20_POFS.write(w); - if (x24_OFST) - if (auto rec = w.enterSubRecord("OFST")) - x24_OFST.write(w); - if (x28_APSO) - if (auto rec = w.enterSubRecord("APSO")) - x28_APSO.write(w); - if (x29_HOMG) - if (auto rec = w.enterSubRecord("HOMG")) - x29_HOMG.write(w); - if (x2a_AP11) - if (auto rec = w.enterSubRecord("AP11")) - x2a_AP11.write(w); - if (x2b_AP21) - if (auto rec = w.enterSubRecord("AP21")) - x2b_AP21.write(w); - if (x2c_AS11) - if (auto rec = w.enterSubRecord("AS11")) - x2c_AS11.write(w); - if (x2d_AS12) - if (auto rec = w.enterSubRecord("AS12")) - x2d_AS12.write(w); - if (x2e_AS13) - if (auto rec = w.enterSubRecord("AS13")) - x2e_AS13.write(w); - if (x30_TRAT) - if (auto rec = w.enterSubRecord("TRAT")) - x30_TRAT.write(w); - if (x34_APSM) - if (auto rec = w.enterSubRecord("APSM")) - x34_APSM.write(w); - if (x44_APS2) - if (auto rec = w.enterSubRecord("APS2")) - x44_APS2.write(w); - if (x54_ASW1) - if (auto rec = w.enterSubRecord("ASW1")) - x54_ASW1.write(w); - if (x64_ASW2) - if (auto rec = w.enterSubRecord("ASW2")) - x64_ASW2.write(w); - if (x74_ASW3) - if (auto rec = w.enterSubRecord("ASW3")) - x74_ASW3.write(w); - if (x84_OHEF) - if (auto rec = w.enterSubRecord("OHEF")) - x84_OHEF.write(w); - if (x94_COLR) - if (auto rec = w.enterSubRecord("COLR")) - x94_COLR.write(w); - if (!xa4_EWTR) - if (auto rec = w.enterSubRecord("EWTR")) - xa4_EWTR.write(w); - if (!xa5_LWTR) - if (auto rec = w.enterSubRecord("LWTR")) - xa5_LWTR.write(w); - if (!xa6_SWTR) - if (auto rec = w.enterSubRecord("SWTR")) - xa6_SWTR.write(w); - if (xa8_PJFX != ~0) - w.writeUint32("PJFX", xa8_PJFX); - if (xac_RNGE) - if (auto rec = w.enterSubRecord("RNGE")) - xac_RNGE.write(w); - if (xb0_FOFF) - if (auto rec = w.enterSubRecord("FOFF")) - xb0_FOFF.write(w); - if (xunk_FC60) - if (auto rec = w.enterSubRecord("FC60")) - xunk_FC60.write(w); - if (xunk_SPS1) - if (auto rec = w.enterSubRecord("SPS1")) - xunk_SPS1.write(w); - if (xunk_SPS1) - if (auto rec = w.enterSubRecord("SPS2")) - xunk_SPS2.write(w); +void WPSM::_write(athena::io::YAMLDocWriter& w) const { + if (x0_IORN) + if (auto rec = w.enterSubRecord("IORN")) + x0_IORN.write(w); + if (x4_IVEC) + if (auto rec = w.enterSubRecord("IVEC")) + x4_IVEC.write(w); + if (x8_PSOV) + if (auto rec = w.enterSubRecord("PSOV")) + x8_PSOV.write(w); + if (xc_PSVM) + if (auto rec = w.enterSubRecord("PSVM")) + xc_PSVM.write(w); + if (x10_VMD2) + if (auto rec = w.enterSubRecord("VMD2")) + x10_VMD2.write(w); + if (x14_PSLT) + if (auto rec = w.enterSubRecord("PSLT")) + x14_PSLT.write(w); + if (x18_PSCL) + if (auto rec = w.enterSubRecord("PSCL")) + x18_PSCL.write(w); + if (x1c_PCOL) + if (auto rec = w.enterSubRecord("PCOL")) + x1c_PCOL.write(w); + if (x20_POFS) + if (auto rec = w.enterSubRecord("POFS")) + x20_POFS.write(w); + if (x24_OFST) + if (auto rec = w.enterSubRecord("OFST")) + x24_OFST.write(w); + if (x28_APSO) + if (auto rec = w.enterSubRecord("APSO")) + x28_APSO.write(w); + if (x29_HOMG) + if (auto rec = w.enterSubRecord("HOMG")) + x29_HOMG.write(w); + if (x2a_AP11) + if (auto rec = w.enterSubRecord("AP11")) + x2a_AP11.write(w); + if (x2b_AP21) + if (auto rec = w.enterSubRecord("AP21")) + x2b_AP21.write(w); + if (x2c_AS11) + if (auto rec = w.enterSubRecord("AS11")) + x2c_AS11.write(w); + if (x2d_AS12) + if (auto rec = w.enterSubRecord("AS12")) + x2d_AS12.write(w); + if (x2e_AS13) + if (auto rec = w.enterSubRecord("AS13")) + x2e_AS13.write(w); + if (x30_TRAT) + if (auto rec = w.enterSubRecord("TRAT")) + x30_TRAT.write(w); + if (x34_APSM) + if (auto rec = w.enterSubRecord("APSM")) + x34_APSM.write(w); + if (x44_APS2) + if (auto rec = w.enterSubRecord("APS2")) + x44_APS2.write(w); + if (x54_ASW1) + if (auto rec = w.enterSubRecord("ASW1")) + x54_ASW1.write(w); + if (x64_ASW2) + if (auto rec = w.enterSubRecord("ASW2")) + x64_ASW2.write(w); + if (x74_ASW3) + if (auto rec = w.enterSubRecord("ASW3")) + x74_ASW3.write(w); + if (x84_OHEF) + if (auto rec = w.enterSubRecord("OHEF")) + x84_OHEF.write(w); + if (x94_COLR) + if (auto rec = w.enterSubRecord("COLR")) + x94_COLR.write(w); + if (!xa4_EWTR) + if (auto rec = w.enterSubRecord("EWTR")) + xa4_EWTR.write(w); + if (!xa5_LWTR) + if (auto rec = w.enterSubRecord("LWTR")) + xa5_LWTR.write(w); + if (!xa6_SWTR) + if (auto rec = w.enterSubRecord("SWTR")) + xa6_SWTR.write(w); + if (xa8_PJFX != ~0) + w.writeUint32("PJFX", xa8_PJFX); + if (xac_RNGE) + if (auto rec = w.enterSubRecord("RNGE")) + xac_RNGE.write(w); + if (xb0_FOFF) + if (auto rec = w.enterSubRecord("FOFF")) + xb0_FOFF.write(w); + if (xunk_FC60) + if (auto rec = w.enterSubRecord("FC60")) + xunk_FC60.write(w); + if (xunk_SPS1) + if (auto rec = w.enterSubRecord("SPS1")) + xunk_SPS1.write(w); + if (xunk_SPS1) + if (auto rec = w.enterSubRecord("SPS2")) + xunk_SPS2.write(w); } template -void WPSM::_binarySize(size_t& __isz) const -{ +void WPSM::_binarySize(size_t& __isz) const { + __isz += 4; + if (x0_IORN) { __isz += 4; - if (x0_IORN) - { - __isz += 4; - x0_IORN.binarySize(__isz); - } - if (x4_IVEC) - { - __isz += 4; - x4_IVEC.binarySize(__isz); - } - if (x8_PSOV) - { - __isz += 4; - x8_PSOV.binarySize(__isz); - } - if (xc_PSVM) - { - __isz += 4; - xc_PSVM.binarySize(__isz); - } - if (x10_VMD2) - { - __isz += 4; - x10_VMD2.binarySize(__isz); - } - if (x14_PSLT) - { - __isz += 4; - x14_PSLT.binarySize(__isz); - } - if (x18_PSCL) - { - __isz += 4; - x18_PSCL.binarySize(__isz); - } - if (x1c_PCOL) - { - __isz += 4; - x1c_PCOL.binarySize(__isz); - } - if (x20_POFS) - { - __isz += 4; - x20_POFS.binarySize(__isz); - } - if (x24_OFST) - { - __isz += 4; - x24_OFST.binarySize(__isz); - } - if (x28_APSO) - { - __isz += 4; - x28_APSO.binarySize(__isz); - } - if (x29_HOMG) - { - __isz += 4; - x29_HOMG.binarySize(__isz); - } - if (x2a_AP11) - { - __isz += 4; - x2a_AP11.binarySize(__isz); - } - if (x2b_AP21) - { - __isz += 4; - x2b_AP21.binarySize(__isz); - } - if (x2c_AS11) - { - __isz += 4; - x2c_AS11.binarySize(__isz); - } - if (x2d_AS12) - { - __isz += 4; - x2d_AS12.binarySize(__isz); - } - if (x2e_AS13) - { - __isz += 4; - x2e_AS13.binarySize(__isz); - } - if (x30_TRAT) - { - __isz += 4; - x30_TRAT.binarySize(__isz); - } - if (x34_APSM) - { - __isz += 4; - x34_APSM.binarySize(__isz); - } - if (x44_APS2) - { - __isz += 4; - x44_APS2.binarySize(__isz); - } - if (x54_ASW1) - { - __isz += 4; - x54_ASW1.binarySize(__isz); - } - if (x64_ASW2) - { - __isz += 4; - x64_ASW2.binarySize(__isz); - } - if (x74_ASW3) - { - __isz += 4; - x74_ASW3.binarySize(__isz); - } - if (x84_OHEF) - { - __isz += 4; - x84_OHEF.binarySize(__isz); - } - if (x94_COLR) - { - __isz += 4; - x94_COLR.binarySize(__isz); - } - if (!xa4_EWTR) - { - __isz += 4; - xa4_EWTR.binarySize(__isz); - } - if (!xa5_LWTR) - { - __isz += 4; - xa5_LWTR.binarySize(__isz); - } - if (!xa6_SWTR) - { - __isz += 4; - xa6_SWTR.binarySize(__isz); - } - if (xa8_PJFX != ~0) - __isz += 12; - if (xac_RNGE) - { - __isz += 4; - xac_RNGE.binarySize(__isz); - } - if (xb0_FOFF) - { - __isz += 4; - xb0_FOFF.binarySize(__isz); - } - if (xunk_FC60) - { - __isz += 4; - xunk_FC60.binarySize(__isz); - } - if (xunk_SPS1) - { - __isz += 4; - xunk_SPS1.binarySize(__isz); - } - if (xunk_SPS2) - { - __isz += 4; - xunk_SPS2.binarySize(__isz); - } + x0_IORN.binarySize(__isz); + } + if (x4_IVEC) { + __isz += 4; + x4_IVEC.binarySize(__isz); + } + if (x8_PSOV) { + __isz += 4; + x8_PSOV.binarySize(__isz); + } + if (xc_PSVM) { + __isz += 4; + xc_PSVM.binarySize(__isz); + } + if (x10_VMD2) { + __isz += 4; + x10_VMD2.binarySize(__isz); + } + if (x14_PSLT) { + __isz += 4; + x14_PSLT.binarySize(__isz); + } + if (x18_PSCL) { + __isz += 4; + x18_PSCL.binarySize(__isz); + } + if (x1c_PCOL) { + __isz += 4; + x1c_PCOL.binarySize(__isz); + } + if (x20_POFS) { + __isz += 4; + x20_POFS.binarySize(__isz); + } + if (x24_OFST) { + __isz += 4; + x24_OFST.binarySize(__isz); + } + if (x28_APSO) { + __isz += 4; + x28_APSO.binarySize(__isz); + } + if (x29_HOMG) { + __isz += 4; + x29_HOMG.binarySize(__isz); + } + if (x2a_AP11) { + __isz += 4; + x2a_AP11.binarySize(__isz); + } + if (x2b_AP21) { + __isz += 4; + x2b_AP21.binarySize(__isz); + } + if (x2c_AS11) { + __isz += 4; + x2c_AS11.binarySize(__isz); + } + if (x2d_AS12) { + __isz += 4; + x2d_AS12.binarySize(__isz); + } + if (x2e_AS13) { + __isz += 4; + x2e_AS13.binarySize(__isz); + } + if (x30_TRAT) { + __isz += 4; + x30_TRAT.binarySize(__isz); + } + if (x34_APSM) { + __isz += 4; + x34_APSM.binarySize(__isz); + } + if (x44_APS2) { + __isz += 4; + x44_APS2.binarySize(__isz); + } + if (x54_ASW1) { + __isz += 4; + x54_ASW1.binarySize(__isz); + } + if (x64_ASW2) { + __isz += 4; + x64_ASW2.binarySize(__isz); + } + if (x74_ASW3) { + __isz += 4; + x74_ASW3.binarySize(__isz); + } + if (x84_OHEF) { + __isz += 4; + x84_OHEF.binarySize(__isz); + } + if (x94_COLR) { + __isz += 4; + x94_COLR.binarySize(__isz); + } + if (!xa4_EWTR) { + __isz += 4; + xa4_EWTR.binarySize(__isz); + } + if (!xa5_LWTR) { + __isz += 4; + xa5_LWTR.binarySize(__isz); + } + if (!xa6_SWTR) { + __isz += 4; + xa6_SWTR.binarySize(__isz); + } + if (xa8_PJFX != ~0) + __isz += 12; + if (xac_RNGE) { + __isz += 4; + xac_RNGE.binarySize(__isz); + } + if (xb0_FOFF) { + __isz += 4; + xb0_FOFF.binarySize(__isz); + } + if (xunk_FC60) { + __isz += 4; + xunk_FC60.binarySize(__isz); + } + if (xunk_SPS1) { + __isz += 4; + xunk_SPS1.binarySize(__isz); + } + if (xunk_SPS2) { + __isz += 4; + xunk_SPS2.binarySize(__isz); + } } template -void WPSM::_read(athena::io::IStreamReader& r) -{ - uint32_t clsId; - r.readBytesToBuf(&clsId, 4); - if (clsId != SBIG('WPSM')) - { - LogModule.report(logvisor::Warning, "non WPSM provided to WPSM parser"); - return; +void WPSM::_read(athena::io::IStreamReader& r) { + uint32_t clsId; + r.readBytesToBuf(&clsId, 4); + if (clsId != SBIG('WPSM')) { + LogModule.report(logvisor::Warning, "non WPSM provided to WPSM parser"); + return; + } + r.readBytesToBuf(&clsId, 4); + while (clsId != SBIG('_END')) { + switch (clsId) { + case SBIG('IORN'): + x0_IORN.read(r); + break; + case SBIG('IVEC'): + x4_IVEC.read(r); + break; + case SBIG('PSOV'): + x8_PSOV.read(r); + break; + case SBIG('PSVM'): + xc_PSVM.read(r); + break; + case SBIG('VMD2'): + x10_VMD2.read(r); + break; + case SBIG('PSLT'): + x14_PSLT.read(r); + break; + case SBIG('PSCL'): + x18_PSCL.read(r); + break; + case SBIG('PCOL'): + x1c_PCOL.read(r); + break; + case SBIG('POFS'): + x20_POFS.read(r); + break; + case SBIG('OFST'): + x24_OFST.read(r); + break; + case SBIG('APSO'): + r.readUint32(); + x28_APSO = r.readBool(); + break; + case SBIG('HOMG'): + x29_HOMG.read(r); + break; + case SBIG('AP11'): + x2a_AP11.read(r); + break; + case SBIG('AP21'): + x2b_AP21.read(r); + break; + case SBIG('AS11'): + x2c_AS11.read(r); + break; + case SBIG('AS12'): + x2d_AS12.read(r); + break; + case SBIG('AS13'): + x2e_AS13.read(r); + break; + case SBIG('TRAT'): + x30_TRAT.read(r); + break; + case SBIG('APSM'): + x34_APSM.read(r); + break; + case SBIG('APS2'): + x44_APS2.read(r); + break; + case SBIG('ASW1'): + x54_ASW1.read(r); + break; + case SBIG('ASW2'): + x64_ASW2.read(r); + break; + case SBIG('ASW3'): + x74_ASW3.read(r); + break; + case SBIG('OHEF'): + x84_OHEF.read(r); + break; + case SBIG('COLR'): + x94_COLR.read(r); + break; + case SBIG('EWTR'): + r.readUint32(); + xa4_EWTR = r.readBool(); + break; + case SBIG('LWTR'): + r.readUint32(); + xa5_LWTR = r.readBool(); + break; + case SBIG('SWTR'): + r.readUint32(); + xa6_SWTR = r.readBool(); + break; + case SBIG('PJFX'): { + uint32_t fcc; + r.readBytesToBuf(&fcc, 4); + if (fcc != SBIG('NONE')) + xa8_PJFX = r.readUint32Big(); + } break; + case SBIG('RNGE'): + xac_RNGE.read(r); + break; + case SBIG('FOFF'): + xb0_FOFF.read(r); + break; + case SBIG('FC60'): + xunk_FC60.read(r); + break; + case SBIG('SPS1'): + xunk_SPS1.read(r); + break; + case SBIG('SPS2'): + xunk_SPS2.read(r); + break; + default: + LogModule.report(logvisor::Fatal, "Unknown WPSM class %.4s @%" PRIi64, &clsId, r.position()); + break; } r.readBytesToBuf(&clsId, 4); - while (clsId != SBIG('_END')) - { - switch(clsId) - { - case SBIG('IORN'): - x0_IORN.read(r); - break; - case SBIG('IVEC'): - x4_IVEC.read(r); - break; - case SBIG('PSOV'): - x8_PSOV.read(r); - break; - case SBIG('PSVM'): - xc_PSVM.read(r); - break; - case SBIG('VMD2'): - x10_VMD2.read(r); - break; - case SBIG('PSLT'): - x14_PSLT.read(r); - break; - case SBIG('PSCL'): - x18_PSCL.read(r); - break; - case SBIG('PCOL'): - x1c_PCOL.read(r); - break; - case SBIG('POFS'): - x20_POFS.read(r); - break; - case SBIG('OFST'): - x24_OFST.read(r); - break; - case SBIG('APSO'): - r.readUint32(); - x28_APSO = r.readBool(); - break; - case SBIG('HOMG'): - x29_HOMG.read(r); - break; - case SBIG('AP11'): - x2a_AP11.read(r); - break; - case SBIG('AP21'): - x2b_AP21.read(r); - break; - case SBIG('AS11'): - x2c_AS11.read(r); - break; - case SBIG('AS12'): - x2d_AS12.read(r); - break; - case SBIG('AS13'): - x2e_AS13.read(r); - break; - case SBIG('TRAT'): - x30_TRAT.read(r); - break; - case SBIG('APSM'): - x34_APSM.read(r); - break; - case SBIG('APS2'): - x44_APS2.read(r); - break; - case SBIG('ASW1'): - x54_ASW1.read(r); - break; - case SBIG('ASW2'): - x64_ASW2.read(r); - break; - case SBIG('ASW3'): - x74_ASW3.read(r); - break; - case SBIG('OHEF'): - x84_OHEF.read(r); - break; - case SBIG('COLR'): - x94_COLR.read(r); - break; - case SBIG('EWTR'): - r.readUint32(); - xa4_EWTR = r.readBool(); - break; - case SBIG('LWTR'): - r.readUint32(); - xa5_LWTR = r.readBool(); - break; - case SBIG('SWTR'): - r.readUint32(); - xa6_SWTR = r.readBool(); - break; - case SBIG('PJFX'): - { - uint32_t fcc; - r.readBytesToBuf(&fcc, 4); - if (fcc != SBIG('NONE')) - xa8_PJFX = r.readUint32Big(); - } - break; - case SBIG('RNGE'): - xac_RNGE.read(r); - break; - case SBIG('FOFF'): - xb0_FOFF.read(r); - break; - case SBIG('FC60'): - xunk_FC60.read(r); - break; - case SBIG('SPS1'): - xunk_SPS1.read(r); - break; - case SBIG('SPS2'): - xunk_SPS2.read(r); - break; - default: - LogModule.report(logvisor::Fatal, "Unknown WPSM class %.4s @%" PRIi64, &clsId, r.position()); - break; - } - r.readBytesToBuf(&clsId, 4); - } + } } template -void WPSM::_write(athena::io::IStreamWriter &w) const -{ - w.writeBytes("WPSM", 4); - if (x0_IORN) - { - w.writeBytes("IORN", 4); - x0_IORN.write(w); - } - if (x4_IVEC) - { - w.writeBytes("IVEC", 4); - x4_IVEC.write(w); - } - if (x8_PSOV) - { - w.writeBytes("PSOV", 4); - x8_PSOV.write(w); - } - if (xc_PSVM) - { - w.writeBytes("PSVM", 4); - xc_PSVM.write(w); - } - if (x10_VMD2) - { - w.writeBytes("VMD2", 4); - x10_VMD2.write(w); - } - if (x14_PSLT) - { - w.writeBytes("PSLT", 4); - x14_PSLT.write(w); - } - if (x18_PSCL) - { - w.writeBytes("PSCL", 4); - x18_PSCL.write(w); - } - if (x1c_PCOL) - { - w.writeBytes("PCOL", 4); - x1c_PCOL.write(w); - } - if (x20_POFS) - { - w.writeBytes("POFS", 4); - x20_POFS.write(w); - } - if (x24_OFST) - { - w.writeBytes("OFST", 4); - x24_OFST.write(w); - } - if (x28_APSO) - { - w.writeBytes("APSO", 4); - x28_APSO.write(w); - } - if (x29_HOMG) - { - w.writeBytes("HOMG", 4); - x29_HOMG.write(w); - } - if (x2a_AP11) - { - w.writeBytes("AP11", 4); - x2a_AP11.write(w); - } - if (x2b_AP21) - { - w.writeBytes("AP21", 4); - x2b_AP21.write(w); - } - if (x2c_AS11) - { - w.writeBytes("AS11", 4); - x2c_AS11.write(w); - } - if (x2d_AS12) - { - w.writeBytes("AS12", 4); - x2d_AS12.write(w); - } - if (x2e_AS13) - { - w.writeBytes("AS13", 4); - x2e_AS13.write(w); - } - if (x30_TRAT) - { - w.writeBytes("TRAT", 4); - x30_TRAT.write(w); - } - if (x34_APSM) - { - w.writeBytes("APSM", 4); - x34_APSM.write(w); - } - if (x44_APS2) - { - w.writeBytes("APS2", 4); - x44_APS2.write(w); - } - if (x54_ASW1) - { - w.writeBytes("ASW1", 4); - x54_ASW1.write(w); - } - if (x64_ASW2) - { - w.writeBytes("ASW2", 4); - x64_ASW2.write(w); - } - if (x74_ASW3) - { - w.writeBytes("ASW3", 4); - x74_ASW3.write(w); - } - if (x84_OHEF) - { - w.writeBytes("OHEF", 4); - x84_OHEF.write(w); - } - if (x94_COLR) - { - w.writeBytes("COLR", 4); - x94_COLR.write(w); - } - if (!xa4_EWTR) - { - w.writeBytes("EWTR", 4); - xa4_EWTR.write(w); - } - if (!xa5_LWTR) - { - w.writeBytes("LWTR", 4); - xa5_LWTR.write(w); - } - if (!xa6_SWTR) - { - w.writeBytes("SWTR", 4); - xa6_SWTR.write(w); - } - if (xa8_PJFX != ~0) - { - w.writeBytes("PJFXCNST", 8); - w.writeUint32(xa8_PJFX); - } - if (xac_RNGE) - { - w.writeBytes("RNGE", 4); - xac_RNGE.write(w); - } - if (xb0_FOFF) - { - w.writeBytes("FOFF", 4); - xb0_FOFF.write(w); - } - if (xunk_FC60) - { - w.writeBytes("FC60", 4); - xunk_FC60.write(w); - } - if (xunk_SPS1) - { - w.writeBytes("SPS1", 4); - xunk_SPS1.write(w); - } - if (xunk_SPS2) - { - w.writeBytes("SPS2", 4); - xunk_SPS2.write(w); - } +void WPSM::_write(athena::io::IStreamWriter& w) const { + w.writeBytes("WPSM", 4); + if (x0_IORN) { + w.writeBytes("IORN", 4); + x0_IORN.write(w); + } + if (x4_IVEC) { + w.writeBytes("IVEC", 4); + x4_IVEC.write(w); + } + if (x8_PSOV) { + w.writeBytes("PSOV", 4); + x8_PSOV.write(w); + } + if (xc_PSVM) { + w.writeBytes("PSVM", 4); + xc_PSVM.write(w); + } + if (x10_VMD2) { + w.writeBytes("VMD2", 4); + x10_VMD2.write(w); + } + if (x14_PSLT) { + w.writeBytes("PSLT", 4); + x14_PSLT.write(w); + } + if (x18_PSCL) { + w.writeBytes("PSCL", 4); + x18_PSCL.write(w); + } + if (x1c_PCOL) { + w.writeBytes("PCOL", 4); + x1c_PCOL.write(w); + } + if (x20_POFS) { + w.writeBytes("POFS", 4); + x20_POFS.write(w); + } + if (x24_OFST) { + w.writeBytes("OFST", 4); + x24_OFST.write(w); + } + if (x28_APSO) { + w.writeBytes("APSO", 4); + x28_APSO.write(w); + } + if (x29_HOMG) { + w.writeBytes("HOMG", 4); + x29_HOMG.write(w); + } + if (x2a_AP11) { + w.writeBytes("AP11", 4); + x2a_AP11.write(w); + } + if (x2b_AP21) { + w.writeBytes("AP21", 4); + x2b_AP21.write(w); + } + if (x2c_AS11) { + w.writeBytes("AS11", 4); + x2c_AS11.write(w); + } + if (x2d_AS12) { + w.writeBytes("AS12", 4); + x2d_AS12.write(w); + } + if (x2e_AS13) { + w.writeBytes("AS13", 4); + x2e_AS13.write(w); + } + if (x30_TRAT) { + w.writeBytes("TRAT", 4); + x30_TRAT.write(w); + } + if (x34_APSM) { + w.writeBytes("APSM", 4); + x34_APSM.write(w); + } + if (x44_APS2) { + w.writeBytes("APS2", 4); + x44_APS2.write(w); + } + if (x54_ASW1) { + w.writeBytes("ASW1", 4); + x54_ASW1.write(w); + } + if (x64_ASW2) { + w.writeBytes("ASW2", 4); + x64_ASW2.write(w); + } + if (x74_ASW3) { + w.writeBytes("ASW3", 4); + x74_ASW3.write(w); + } + if (x84_OHEF) { + w.writeBytes("OHEF", 4); + x84_OHEF.write(w); + } + if (x94_COLR) { + w.writeBytes("COLR", 4); + x94_COLR.write(w); + } + if (!xa4_EWTR) { + w.writeBytes("EWTR", 4); + xa4_EWTR.write(w); + } + if (!xa5_LWTR) { + w.writeBytes("LWTR", 4); + xa5_LWTR.write(w); + } + if (!xa6_SWTR) { + w.writeBytes("SWTR", 4); + xa6_SWTR.write(w); + } + if (xa8_PJFX != ~0) { + w.writeBytes("PJFXCNST", 8); + w.writeUint32(xa8_PJFX); + } + if (xac_RNGE) { + w.writeBytes("RNGE", 4); + xac_RNGE.write(w); + } + if (xb0_FOFF) { + w.writeBytes("FOFF", 4); + xb0_FOFF.write(w); + } + if (xunk_FC60) { + w.writeBytes("FC60", 4); + xunk_FC60.write(w); + } + if (xunk_SPS1) { + w.writeBytes("SPS1", 4); + xunk_SPS1.write(w); + } + if (xunk_SPS2) { + w.writeBytes("SPS2", 4); + xunk_SPS2.write(w); + } - w.writeBytes("_END", 4); + w.writeBytes("_END", 4); } AT_SUBSPECIALIZE_DNA_YAML(WPSM) AT_SUBSPECIALIZE_DNA_YAML(WPSM) template <> -const char* WPSM::DNAType() { return "WPSM"; } +const char* WPSM::DNAType() { + return "WPSM"; +} template <> -const char* WPSM::DNAType() { return "WPSM"; } +const char* WPSM::DNAType() { + return "WPSM"; +} template -void WPSM::gatherDependencies(std::vector& pathsOut) const -{ - g_curSpec->flattenDependencies(x34_APSM.id, pathsOut); - g_curSpec->flattenDependencies(x44_APS2.id, pathsOut); - g_curSpec->flattenDependencies(x54_ASW1.id, pathsOut); - g_curSpec->flattenDependencies(x64_ASW2.id, pathsOut); - g_curSpec->flattenDependencies(x74_ASW3.id, pathsOut); - g_curSpec->flattenDependencies(x84_OHEF.id, pathsOut); - g_curSpec->flattenDependencies(x94_COLR.id, pathsOut); +void WPSM::gatherDependencies(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(x34_APSM.id, pathsOut); + g_curSpec->flattenDependencies(x44_APS2.id, pathsOut); + g_curSpec->flattenDependencies(x54_ASW1.id, pathsOut); + g_curSpec->flattenDependencies(x64_ASW2.id, pathsOut); + g_curSpec->flattenDependencies(x74_ASW3.id, pathsOut); + g_curSpec->flattenDependencies(x84_OHEF.id, pathsOut); + g_curSpec->flattenDependencies(x94_COLR.id, pathsOut); } template struct WPSM; template struct WPSM; template -bool ExtractWPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - if (writer.isOpen()) - { - WPSM wpsm; - wpsm.read(rs); - athena::io::ToYAMLStream(wpsm, writer); - return true; - } - return false; +bool ExtractWPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + athena::io::FileWriter writer(outPath.getAbsolutePath()); + if (writer.isOpen()) { + WPSM wpsm; + wpsm.read(rs); + athena::io::ToYAMLStream(wpsm, writer); + return true; + } + return false; } template bool ExtractWPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool ExtractWPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template -bool WriteWPSM(const WPSM& wpsm, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); - if (w.hasError()) - return false; - wpsm.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; +bool WriteWPSM(const WPSM& wpsm, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath(), true, false); + if (w.hasError()) + return false; + wpsm.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } template bool WriteWPSM(const WPSM& wpsm, const hecl::ProjectPath& outPath); template bool WriteWPSM(const WPSM& wpsm, const hecl::ProjectPath& outPath); -} +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNACommon/WPSC.hpp b/DataSpec/DNACommon/WPSC.hpp index b230efbba..81071ef98 100644 --- a/DataSpec/DNACommon/WPSC.hpp +++ b/DataSpec/DNACommon/WPSC.hpp @@ -4,54 +4,53 @@ #include "PAK.hpp" #include "athena/FileWriter.hpp" -namespace DataSpec::DNAParticle -{ +namespace DataSpec::DNAParticle { template -struct WPSM : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_SUBDECL_DNA - VectorElementFactory x0_IORN; - VectorElementFactory x4_IVEC; - VectorElementFactory x8_PSOV; - ModVectorElementFactory xc_PSVM; - BoolHelper x10_VMD2; - IntElementFactory x14_PSLT; - VectorElementFactory x18_PSCL; - ColorElementFactory x1c_PCOL; - VectorElementFactory x20_POFS; - VectorElementFactory x24_OFST; - BoolHelper x28_APSO; - BoolHelper x29_HOMG; - BoolHelper x2a_AP11; - BoolHelper x2b_AP21; - BoolHelper x2c_AS11; - BoolHelper x2d_AS12; - BoolHelper x2e_AS13; - RealElementFactory x30_TRAT; - ChildResourceFactory x34_APSM; - ChildResourceFactory x44_APS2; - ChildResourceFactory x54_ASW1; - ChildResourceFactory x64_ASW2; - ChildResourceFactory x74_ASW3; - ChildResourceFactory x84_OHEF; - ChildResourceFactory x94_COLR; - BoolHelper xa4_EWTR; - BoolHelper xa5_LWTR; - BoolHelper xa6_SWTR; - uint32_t xa8_PJFX = ~0; - RealElementFactory xac_RNGE; - RealElementFactory xb0_FOFF; - BoolHelper xunk_FC60; - BoolHelper xunk_SPS1; - BoolHelper xunk_SPS2; +struct WPSM : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + AT_SUBDECL_DNA + VectorElementFactory x0_IORN; + VectorElementFactory x4_IVEC; + VectorElementFactory x8_PSOV; + ModVectorElementFactory xc_PSVM; + BoolHelper x10_VMD2; + IntElementFactory x14_PSLT; + VectorElementFactory x18_PSCL; + ColorElementFactory x1c_PCOL; + VectorElementFactory x20_POFS; + VectorElementFactory x24_OFST; + BoolHelper x28_APSO; + BoolHelper x29_HOMG; + BoolHelper x2a_AP11; + BoolHelper x2b_AP21; + BoolHelper x2c_AS11; + BoolHelper x2d_AS12; + BoolHelper x2e_AS13; + RealElementFactory x30_TRAT; + ChildResourceFactory x34_APSM; + ChildResourceFactory x44_APS2; + ChildResourceFactory x54_ASW1; + ChildResourceFactory x64_ASW2; + ChildResourceFactory x74_ASW3; + ChildResourceFactory x84_OHEF; + ChildResourceFactory x94_COLR; + BoolHelper xa4_EWTR; + BoolHelper xa5_LWTR; + BoolHelper xa6_SWTR; + uint32_t xa8_PJFX = ~0; + RealElementFactory xac_RNGE; + RealElementFactory xb0_FOFF; + BoolHelper xunk_FC60; + BoolHelper xunk_SPS1; + BoolHelper xunk_SPS2; - WPSM() - { - xa4_EWTR = true; xa5_LWTR = true; xa6_SWTR = true; - } + WPSM() { + xa4_EWTR = true; + xa5_LWTR = true; + xa6_SWTR = true; + } - void gatherDependencies(std::vector&) const; + void gatherDependencies(std::vector&) const; }; template @@ -60,5 +59,4 @@ bool ExtractWPSM(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); template bool WriteWPSM(const WPSM& wpsm, const hecl::ProjectPath& outPath); -} - +} // namespace DataSpec::DNAParticle diff --git a/DataSpec/DNAMP1/AFSM.cpp b/DataSpec/DNAMP1/AFSM.cpp index cb4e39038..0afb12183 100644 --- a/DataSpec/DNAMP1/AFSM.cpp +++ b/DataSpec/DNAMP1/AFSM.cpp @@ -1,127 +1,104 @@ #include "AFSM.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template <> -void AFSM::State::Transition::Enumerate(typename Read::StreamT& r) -{ - triggerCount = r.readUint32Big(); - int i = 0; - r.enumerate(triggers, triggerCount, - [&](athena::io::IStreamReader& in, Trigger& tr){ - tr.first = i == 0; - tr.read(in); - i++; - }); +void AFSM::State::Transition::Enumerate(typename Read::StreamT& r) { + triggerCount = r.readUint32Big(); + int i = 0; + r.enumerate(triggers, triggerCount, [&](athena::io::IStreamReader& in, Trigger& tr) { + tr.first = i == 0; + tr.read(in); + i++; + }); } template <> -void AFSM::State::Transition::Enumerate(typename Write::StreamT& w) -{ - w.writeInt32Big(triggerCount); - w.enumerate(triggers); +void AFSM::State::Transition::Enumerate(typename Write::StreamT& w) { + w.writeInt32Big(triggerCount); + w.enumerate(triggers); } template <> -void AFSM::State::Transition::Enumerate(typename ReadYaml::StreamT& r) -{ - int i = 0; - /* triggers */ - triggerCount = r.enumerate("triggers", triggers, - [&](athena::io::YAMLDocReader& in, Trigger& tr){ - tr.first = i == 0; - tr.read(in); - i++; - }); +void AFSM::State::Transition::Enumerate(typename ReadYaml::StreamT& r) { + int i = 0; + /* triggers */ + triggerCount = r.enumerate("triggers", triggers, [&](athena::io::YAMLDocReader& in, Trigger& tr) { + tr.first = i == 0; + tr.read(in); + i++; + }); } template <> -void AFSM::State::Transition::Enumerate(typename WriteYaml::StreamT& w) -{ - /* triggers */ - w.enumerate("triggers", triggers); +void AFSM::State::Transition::Enumerate(typename WriteYaml::StreamT& w) { + /* triggers */ + w.enumerate("triggers", triggers); } template <> -void AFSM::State::Transition::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - for (const Trigger& trig : triggers) - trig.binarySize(s); +void AFSM::State::Transition::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + for (const Trigger& trig : triggers) + trig.binarySize(s); } -const char* AFSM::State::Transition::DNAType() -{ - return "urde::DNAMP1::AFSM::Transition"; +const char* AFSM::State::Transition::DNAType() { return "urde::DNAMP1::AFSM::Transition"; } + +template <> +void AFSM::State::Transition::Trigger::Enumerate(athena::io::IStreamReader& __dna_reader) { + /* name */ + name = __dna_reader.readString(-1); + /* parameter */ + parameter = __dna_reader.readFloatBig(); + if (first) { + /* targetState */ + targetState = __dna_reader.readUint32Big(); + } } template <> -void AFSM::State::Transition::Trigger::Enumerate(athena::io::IStreamReader& __dna_reader) -{ - /* name */ - name = __dna_reader.readString(-1); - /* parameter */ - parameter = __dna_reader.readFloatBig(); - if (first) - { - /* targetState */ - targetState = __dna_reader.readUint32Big(); - } +void AFSM::State::Transition::Trigger::Enumerate(athena::io::IStreamWriter& __dna_writer) { + /* name */ + __dna_writer.writeString(name, -1); + /* parameter */ + __dna_writer.writeFloatBig(parameter); + if (first) { + /* targetState */ + __dna_writer.writeUint32Big(targetState); + } } template <> -void AFSM::State::Transition::Trigger::Enumerate(athena::io::IStreamWriter& __dna_writer) -{ - /* name */ - __dna_writer.writeString(name, -1); - /* parameter */ - __dna_writer.writeFloatBig(parameter); - if (first) - { - /* targetState */ - __dna_writer.writeUint32Big(targetState); - } +void AFSM::State::Transition::Trigger::Enumerate(athena::io::YAMLDocReader& __dna_docin) { + /* name */ + name = __dna_docin.readString("name"); + /* parameter */ + parameter = __dna_docin.readFloat("parameter"); + if (first) { + /* targetState */ + targetState = __dna_docin.readUint32("targetState"); + } } template <> -void AFSM::State::Transition::Trigger::Enumerate(athena::io::YAMLDocReader& __dna_docin) -{ - /* name */ - name = __dna_docin.readString("name"); - /* parameter */ - parameter = __dna_docin.readFloat("parameter"); - if (first) - { - /* targetState */ - targetState = __dna_docin.readUint32("targetState"); - } +void AFSM::State::Transition::Trigger::Enumerate(athena::io::YAMLDocWriter& __dna_docout) { + /* name */ + __dna_docout.writeString("name", name); + /* parameter */ + __dna_docout.writeFloat("parameter", parameter); + if (first) { + /* targetState */ + __dna_docout.writeUint32("targetState", targetState); + } } template <> -void AFSM::State::Transition::Trigger::Enumerate(athena::io::YAMLDocWriter& __dna_docout) -{ - /* name */ - __dna_docout.writeString("name", name); - /* parameter */ - __dna_docout.writeFloat("parameter", parameter); - if (first) - { - /* targetState */ - __dna_docout.writeUint32("targetState", targetState); - } +void AFSM::State::Transition::Trigger::Enumerate(size_t& __isz) { + __isz += name.size() + 1; + __isz += (first ? 8 : 4); } -template <> -void AFSM::State::Transition::Trigger::Enumerate(size_t& __isz) -{ - __isz += name.size() + 1; - __isz += (first ? 8 : 4); -} +const char* AFSM::State::Transition::Trigger::DNAType() { return "urde::DNAMP1::AFSM::State::Transition::Trigger"; } -const char* AFSM::State::Transition::Trigger::DNAType() -{ - return "urde::DNAMP1::AFSM::State::Transition::Trigger"; -} - -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/AFSM.hpp b/DataSpec/DNAMP1/AFSM.hpp index 1aa24997b..5dd6e2684 100644 --- a/DataSpec/DNAMP1/AFSM.hpp +++ b/DataSpec/DNAMP1/AFSM.hpp @@ -4,56 +4,48 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ -struct AFSM : public BigDNA -{ +namespace DataSpec::DNAMP1 { +struct AFSM : public BigDNA { + AT_DECL_DNA_YAML + Value stateCount; + Vector, AT_DNA_COUNT(stateCount)> stateNames; + Value triggerCount; + + struct State : public BigDNA { AT_DECL_DNA_YAML - Value stateCount; - Vector, AT_DNA_COUNT(stateCount)> stateNames; - Value triggerCount; + Value transitionCount; + struct Transition : public BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + Value triggerCount; - struct State : public BigDNA - { - AT_DECL_DNA_YAML - Value transitionCount; - struct Transition : public BigDNA - { - AT_DECL_EXPLICIT_DNA_YAML - Value triggerCount; - - struct Trigger : public BigDNA - { - AT_DECL_EXPLICIT_DNA_YAML - bool first = false; - String<-1> name; - Value parameter; - Value targetState; - }; - Vector triggers; - }; - Vector transitions; + struct Trigger : public BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + bool first = false; + String<-1> name; + Value parameter; + Value targetState; + }; + Vector triggers; }; - Vector states; + Vector transitions; + }; + Vector states; - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) - { - AFSM afsm; - afsm.read(rs); - athena::io::FileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(afsm, writer); - return true; - } + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + AFSM afsm; + afsm.read(rs); + athena::io::FileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(afsm, writer); + return true; + } - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) - { - AFSM afsm; - athena::io::FileReader reader(inPath.getAbsolutePath()); - athena::io::FromYAMLStream(afsm, reader); - athena::io::FileWriter ws(outPath.getAbsolutePath()); - afsm.write(ws); - return true; - } + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + AFSM afsm; + athena::io::FileReader reader(inPath.getAbsolutePath()); + athena::io::FromYAMLStream(afsm, reader); + athena::io::FileWriter ws(outPath.getAbsolutePath()); + afsm.write(ws); + return true; + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/AGSC.cpp b/DataSpec/DNAMP1/AGSC.cpp index 15e2332d3..db93e24b7 100644 --- a/DataSpec/DNAMP1/AGSC.cpp +++ b/DataSpec/DNAMP1/AGSC.cpp @@ -74,176 +74,170 @@ extern "C" const uint8_t Zoomer_H[]; extern "C" const uint8_t lumigek_H[]; extern "C" const uint8_t test_H[]; -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { using namespace std::literals; -static const std::pair Headers[] = -{ - {"Atomic"sv, Atomic_H}, - {"BetaBeetle"sv, BetaBeetle_H}, - {"Bird"sv, Bird_H}, - {"BloodFlower"sv, BloodFlower_H}, - {"Burrower"sv, Burrower_H}, - {"ChozoGhost"sv, ChozoGhost_H}, - {"ChubbWeed"sv, ChubbWeed_H}, - {"CineBoots"sv, CineBoots_H}, - {"CineGeneral"sv, CineGeneral_H}, - {"CineGun"sv, CineGun_H}, - {"CineMorphball"sv, CineMorphball_H}, - {"CineSuit"sv, CineSuit_H}, - {"CineVisor"sv, CineVisor_H}, - {"Crater"sv, Crater_H}, - {"Crystallite"sv, Crystallite_H}, - {"Drones"sv, Drones_H}, - {"EliteSpacePirate"sv, EliteSpacePirate_H}, - {"FireFlea"sv, FireFlea_H}, - {"Flaaghra"sv, Flaaghra_H}, - {"FlickerBat"sv, FlickerBat_H}, - {"FlyingPirate"sv, FlyingPirate_H}, - {"FrontEnd"sv, FrontEnd_H}, - {"GagantuanBeatle"sv, GagantuanBeatle_H}, - {"Gnats"sv, Gnats_H}, - {"Gryzbee"sv, Gryzbee_H}, - {"IceCrack"sv, IceCrack_H}, - {"IceWorld"sv, IceWorld_H}, - {"InjuredPirates"sv, InjuredPirates_H}, - {"IntroBoss"sv, IntroBoss_H}, - {"IntroWorld"sv, IntroWorld_H}, - {"JellyZap"sv, JellyZap_H}, - {"LavaWorld"sv, LavaWorld_H}, - {"Magdolite"sv, Magdolite_H}, - {"Metaree"sv, Metaree_H}, - {"MetroidPrime"sv, MetroidPrime_H}, - {"Metroid"sv, Metroid_H}, - {"MinesWorld"sv, MinesWorld_H}, - {"MiscSamus"sv, MiscSamus_H}, - {"Misc"sv, Misc_H}, - {"OmegaPirate"sv, OmegaPirate_H}, - {"OverWorld"sv, OverWorld_H}, - {"Parasite"sv, Parasite_H}, - {"PhazonGun"sv, PhazonGun_H}, - {"Phazon"sv, Phazon_H}, - {"PuddleSpore"sv, PuddleSpore_H}, - {"PuddleToad"sv, PuddleToad_H}, - {"Puffer"sv, Puffer_H}, - {"ReactorDoor"sv, ReactorDoor_H}, - {"Ridley"sv, Ridley_H}, - {"Ripper"sv, Ripper_H}, - {"RuinsWorld"sv, RuinsWorld_H}, - {"SamusShip"sv, SamusShip_H}, - {"Scarab"sv, Scarab_H}, - {"Seedling"sv, Seedling_H}, - {"SheeGoth"sv, SheeGoth_H}, - {"SnakeWeed"sv, SnakeWeed_H}, - {"Sova"sv, Sova_H}, - {"SpacePirate"sv, SpacePirate_H}, - {"SpankWeed"sv, SpankWeed_H}, - {"Thardus"sv, Thardus_H}, - {"TheEnd"sv, TheEnd_H}, - {"Torobyte"sv, Torobyte_H}, - {"Triclops"sv, Triclops_H}, - {"Turret"sv, Turret_H}, - {"UI"sv, UI_H}, - {"WarWasp"sv, WarWasp_H}, - {"Weapons"sv, Weapons_H}, - {"ZZZ"sv, ZZZ_H}, - {"Zoomer"sv, Zoomer_H}, - {"lumigek"sv, lumigek_H}, - {"test"sv, test_H} -}; +static const std::pair Headers[] = {{"Atomic"sv, Atomic_H}, + {"BetaBeetle"sv, BetaBeetle_H}, + {"Bird"sv, Bird_H}, + {"BloodFlower"sv, BloodFlower_H}, + {"Burrower"sv, Burrower_H}, + {"ChozoGhost"sv, ChozoGhost_H}, + {"ChubbWeed"sv, ChubbWeed_H}, + {"CineBoots"sv, CineBoots_H}, + {"CineGeneral"sv, CineGeneral_H}, + {"CineGun"sv, CineGun_H}, + {"CineMorphball"sv, CineMorphball_H}, + {"CineSuit"sv, CineSuit_H}, + {"CineVisor"sv, CineVisor_H}, + {"Crater"sv, Crater_H}, + {"Crystallite"sv, Crystallite_H}, + {"Drones"sv, Drones_H}, + {"EliteSpacePirate"sv, EliteSpacePirate_H}, + {"FireFlea"sv, FireFlea_H}, + {"Flaaghra"sv, Flaaghra_H}, + {"FlickerBat"sv, FlickerBat_H}, + {"FlyingPirate"sv, FlyingPirate_H}, + {"FrontEnd"sv, FrontEnd_H}, + {"GagantuanBeatle"sv, GagantuanBeatle_H}, + {"Gnats"sv, Gnats_H}, + {"Gryzbee"sv, Gryzbee_H}, + {"IceCrack"sv, IceCrack_H}, + {"IceWorld"sv, IceWorld_H}, + {"InjuredPirates"sv, InjuredPirates_H}, + {"IntroBoss"sv, IntroBoss_H}, + {"IntroWorld"sv, IntroWorld_H}, + {"JellyZap"sv, JellyZap_H}, + {"LavaWorld"sv, LavaWorld_H}, + {"Magdolite"sv, Magdolite_H}, + {"Metaree"sv, Metaree_H}, + {"MetroidPrime"sv, MetroidPrime_H}, + {"Metroid"sv, Metroid_H}, + {"MinesWorld"sv, MinesWorld_H}, + {"MiscSamus"sv, MiscSamus_H}, + {"Misc"sv, Misc_H}, + {"OmegaPirate"sv, OmegaPirate_H}, + {"OverWorld"sv, OverWorld_H}, + {"Parasite"sv, Parasite_H}, + {"PhazonGun"sv, PhazonGun_H}, + {"Phazon"sv, Phazon_H}, + {"PuddleSpore"sv, PuddleSpore_H}, + {"PuddleToad"sv, PuddleToad_H}, + {"Puffer"sv, Puffer_H}, + {"ReactorDoor"sv, ReactorDoor_H}, + {"Ridley"sv, Ridley_H}, + {"Ripper"sv, Ripper_H}, + {"RuinsWorld"sv, RuinsWorld_H}, + {"SamusShip"sv, SamusShip_H}, + {"Scarab"sv, Scarab_H}, + {"Seedling"sv, Seedling_H}, + {"SheeGoth"sv, SheeGoth_H}, + {"SnakeWeed"sv, SnakeWeed_H}, + {"Sova"sv, Sova_H}, + {"SpacePirate"sv, SpacePirate_H}, + {"SpankWeed"sv, SpankWeed_H}, + {"Thardus"sv, Thardus_H}, + {"TheEnd"sv, TheEnd_H}, + {"Torobyte"sv, Torobyte_H}, + {"Triclops"sv, Triclops_H}, + {"Turret"sv, Turret_H}, + {"UI"sv, UI_H}, + {"WarWasp"sv, WarWasp_H}, + {"Weapons"sv, Weapons_H}, + {"ZZZ"sv, ZZZ_H}, + {"Zoomer"sv, Zoomer_H}, + {"lumigek"sv, lumigek_H}, + {"test"sv, test_H}}; -bool AGSC::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& dir) -{ - dir.makeDirChain(true); +bool AGSC::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& dir) { + dir.makeDirChain(true); - Header head; - head.read(rs); + Header head; + head.read(rs); - uint32_t poolLen = rs.readUint32Big(); - auto pool = rs.readUBytes(poolLen); + uint32_t poolLen = rs.readUint32Big(); + auto pool = rs.readUBytes(poolLen); - uint32_t projLen = rs.readUint32Big(); - auto proj = rs.readUBytes(projLen); + uint32_t projLen = rs.readUint32Big(); + auto proj = rs.readUBytes(projLen); - uint32_t sampLen = rs.readUint32Big(); - auto samp = rs.readUBytes(sampLen); + uint32_t sampLen = rs.readUint32Big(); + auto samp = rs.readUBytes(sampLen); - uint32_t sdirLen = rs.readUint32Big(); - auto sdir = rs.readUBytes(sdirLen); + uint32_t sdirLen = rs.readUint32Big(); + auto sdir = rs.readUBytes(sdirLen); - amuse::AudioGroupData data(proj.get(), projLen, pool.get(), poolLen, - sdir.get(), sdirLen, samp.get(), sampLen, amuse::GCNDataTag{}); + amuse::AudioGroupData data(proj.get(), projLen, pool.get(), poolLen, sdir.get(), sdirLen, samp.get(), sampLen, + amuse::GCNDataTag{}); - /* Load into amuse representation */ - amuse::ProjectDatabase projDb; - projDb.setIdDatabases(); - amuse::AudioGroupDatabase group(data); - group.setGroupPath(dir.getAbsolutePath()); + /* Load into amuse representation */ + amuse::ProjectDatabase projDb; + projDb.setIdDatabases(); + amuse::AudioGroupDatabase group(data); + group.setGroupPath(dir.getAbsolutePath()); - /* Extract samples */ - group.getSdir().extractAllCompressed(dir.getAbsolutePath(), data.getSamp()); + /* Extract samples */ + group.getSdir().extractAllCompressed(dir.getAbsolutePath(), data.getSamp()); - /* Import C headers */ - auto lastComp = dir.getLastComponentUTF8(); - auto search = std::lower_bound(std::cbegin(Headers), std::cend(Headers), lastComp, - [](const auto& a, const auto& b) { return a.first < b; }); - if (search != std::cend(Headers) && search->first == lastComp) - group.importCHeader((char*)search->second); + /* Import C headers */ + auto lastComp = dir.getLastComponentUTF8(); + auto search = std::lower_bound(std::cbegin(Headers), std::cend(Headers), lastComp, + [](const auto& a, const auto& b) { return a.first < b; }); + if (search != std::cend(Headers) && search->first == lastComp) + group.importCHeader((char*)search->second); - /* Write out project/pool */ - { - auto projd = group.getProj().toYAML(); - athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!project.yaml")).getAbsolutePath()); - if (fo.hasError()) - return false; - fo.writeUBytes(projd.data(), projd.size()); - } + /* Write out project/pool */ + { + auto projd = group.getProj().toYAML(); + athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!project.yaml")).getAbsolutePath()); + if (fo.hasError()) + return false; + fo.writeUBytes(projd.data(), projd.size()); + } - { - auto poold = group.getPool().toYAML(); - athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!pool.yaml")).getAbsolutePath()); - if (fo.hasError()) - return false; - fo.writeUBytes(poold.data(), poold.size()); - } + { + auto poold = group.getPool().toYAML(); + athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!pool.yaml")).getAbsolutePath()); + if (fo.hasError()) + return false; + fo.writeUBytes(poold.data(), poold.size()); + } - return true; + return true; } -bool AGSC::Cook(const hecl::ProjectPath& dir, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath()); - if (w.hasError()) - return false; +bool AGSC::Cook(const hecl::ProjectPath& dir, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath()); + if (w.hasError()) + return false; - Header head; - head.audioDir = "Audio/"sv; - head.groupName = dir.getLastComponentUTF8(); - head.write(w); + Header head; + head.audioDir = "Audio/"sv; + head.groupName = dir.getLastComponentUTF8(); + head.write(w); - amuse::ProjectDatabase projDb; - projDb.setIdDatabases(); - amuse::AudioGroupDatabase group(dir.getAbsolutePath()); + amuse::ProjectDatabase projDb; + projDb.setIdDatabases(); + amuse::AudioGroupDatabase group(dir.getAbsolutePath()); - auto proj = group.getProj().toGCNData(group.getPool(), group.getSdir()); - auto pool = group.getPool().toData(); - auto sdirSamp = group.getSdir().toGCNData(group); + auto proj = group.getProj().toGCNData(group.getPool(), group.getSdir()); + auto pool = group.getPool().toData(); + auto sdirSamp = group.getSdir().toGCNData(group); - w.writeUint32Big(pool.size()); - w.writeUBytes(pool.data(), pool.size()); + w.writeUint32Big(pool.size()); + w.writeUBytes(pool.data(), pool.size()); - w.writeUint32Big(proj.size()); - w.writeUBytes(proj.data(), proj.size()); + w.writeUint32Big(proj.size()); + w.writeUBytes(proj.data(), proj.size()); - w.writeUint32Big(sdirSamp.second.size()); - w.writeUBytes(sdirSamp.second.data(), sdirSamp.second.size()); + w.writeUint32Big(sdirSamp.second.size()); + w.writeUBytes(sdirSamp.second.data(), sdirSamp.second.size()); - w.writeUint32Big(sdirSamp.first.size()); - w.writeUBytes(sdirSamp.first.data(), sdirSamp.first.size()); + w.writeUint32Big(sdirSamp.first.size()); + w.writeUBytes(sdirSamp.first.data(), sdirSamp.first.size()); - return true; + return true; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/AGSC.hpp b/DataSpec/DNAMP1/AGSC.hpp index 1b7beb56f..7c480e5e5 100644 --- a/DataSpec/DNAMP1/AGSC.hpp +++ b/DataSpec/DNAMP1/AGSC.hpp @@ -3,21 +3,17 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -class AGSC -{ +class AGSC { public: - struct Header : BigDNA - { - AT_DECL_DNA - String<-1> audioDir; - String<-1> groupName; - }; - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath); + struct Header : BigDNA { + AT_DECL_DNA + String<-1> audioDir; + String<-1> groupName; + }; + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ANCS.cpp b/DataSpec/DNAMP1/ANCS.cpp index 8859718d8..5e5b412f1 100644 --- a/DataSpec/DNAMP1/ANCS.cpp +++ b/DataSpec/DNAMP1/ANCS.cpp @@ -1,1627 +1,1407 @@ #include "ANCS.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec -{ +namespace DataSpec { extern hecl::Database::DataSpecEntry SpecEntMP1; extern hecl::Database::DataSpecEntry SpecEntMP1PC; -namespace DNAMP1 -{ +namespace DNAMP1 { template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate - (athena::io::IStreamReader& reader) -{ - parmType = reader.readUint32Big(); - weightFunction = reader.readUint32Big(); - weight = reader.readFloatBig(); - switch (DataType(parmType)) - { +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate( + athena::io::IStreamReader& reader) { + parmType = reader.readUint32Big(); + weightFunction = reader.readUint32Big(); + weight = reader.readFloatBig(); + switch (DataType(parmType)) { + case DataType::Int32: + range[0].int32 = reader.readInt32Big(); + range[1].int32 = reader.readInt32Big(); + break; + case DataType::UInt32: + case DataType::Enum: + range[0].uint32 = reader.readUint32Big(); + range[1].uint32 = reader.readUint32Big(); + break; + case DataType::Float: + range[0].float32 = reader.readFloatBig(); + range[1].float32 = reader.readFloatBig(); + break; + case DataType::Bool: + range[0].bool1 = reader.readBool(); + range[1].bool1 = reader.readBool(); + break; + } +} + +template <> +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate( + athena::io::IStreamWriter& writer) { + writer.writeUint32Big(parmType); + writer.writeUint32Big(weightFunction); + writer.writeFloatBig(weight); + switch (DataType(parmType)) { + case DataType::Int32: + writer.writeInt32Big(range[0].int32); + writer.writeInt32Big(range[1].int32); + break; + case DataType::UInt32: + case DataType::Enum: + writer.writeUint32Big(range[0].uint32); + writer.writeUint32Big(range[0].uint32); + break; + case DataType::Float: + writer.writeFloatBig(range[0].float32); + writer.writeFloatBig(range[0].float32); + break; + case DataType::Bool: + writer.writeBool(range[0].bool1); + writer.writeBool(range[0].bool1); + break; + } +} + +template <> +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate(size_t& __isz) { + __isz += 12; + switch (DataType(parmType)) { + case DataType::Int32: + case DataType::UInt32: + case DataType::Enum: + case DataType::Float: + __isz += 8; + break; + case DataType::Bool: + __isz += 2; + break; + } +} + +template <> +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate( + athena::io::YAMLDocReader& reader) { + parmType = reader.readUint32("parmType"); + weightFunction = reader.readUint32("weightFunction"); + weight = reader.readFloat("weight"); + size_t parmValCount; + if (auto v = reader.enterSubVector("range", parmValCount)) { + switch (DataType(parmType)) { case DataType::Int32: - range[0].int32 = reader.readInt32Big(); - range[1].int32 = reader.readInt32Big(); - break; + range[0].int32 = reader.readInt32(nullptr); + range[1].int32 = reader.readInt32(nullptr); + break; case DataType::UInt32: case DataType::Enum: - range[0].uint32 = reader.readUint32Big(); - range[1].uint32 = reader.readUint32Big(); - break; + range[0].uint32 = reader.readUint32(nullptr); + range[1].uint32 = reader.readUint32(nullptr); + break; case DataType::Float: - range[0].float32 = reader.readFloatBig(); - range[1].float32 = reader.readFloatBig(); - break; + range[0].float32 = reader.readFloat(nullptr); + range[1].float32 = reader.readFloat(nullptr); + break; case DataType::Bool: - range[0].bool1 = reader.readBool(); - range[1].bool1 = reader.readBool(); - break; + range[0].bool1 = reader.readBool(nullptr); + range[1].bool1 = reader.readBool(nullptr); + break; + default: + break; } + } } template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate - (athena::io::IStreamWriter& writer) -{ - writer.writeUint32Big(parmType); - writer.writeUint32Big(weightFunction); - writer.writeFloatBig(weight); - switch (DataType(parmType)) - { +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate( + athena::io::YAMLDocWriter& writer) { + writer.writeUint32("parmType", parmType); + writer.writeUint32("weightFunction", weightFunction); + writer.writeFloat("weight", weight); + if (auto v = writer.enterSubVector("range")) { + switch (DataType(parmType)) { case DataType::Int32: - writer.writeInt32Big(range[0].int32); - writer.writeInt32Big(range[1].int32); - break; + writer.writeInt32(nullptr, range[0].int32); + writer.writeInt32(nullptr, range[1].int32); + break; case DataType::UInt32: case DataType::Enum: - writer.writeUint32Big(range[0].uint32); - writer.writeUint32Big(range[0].uint32); - break; + writer.writeUint32(nullptr, range[0].uint32); + writer.writeUint32(nullptr, range[0].uint32); + break; case DataType::Float: - writer.writeFloatBig(range[0].float32); - writer.writeFloatBig(range[0].float32); - break; + writer.writeFloat(nullptr, range[0].float32); + writer.writeFloat(nullptr, range[0].float32); + break; case DataType::Bool: - writer.writeBool(range[0].bool1); - writer.writeBool(range[0].bool1); + writer.writeBool(nullptr, range[0].bool1); + writer.writeBool(nullptr, range[0].bool1); + break; + } + } +} + +const char* ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::DNAType() { + return "urde::DNAMP1::ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo"; +} + +template <> +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate( + athena::io::IStreamReader& reader) { + id = reader.readUint32Big(); + atUint32 parmInfoCount = reader.readUint32Big(); + atUint32 animInfoCount = reader.readUint32Big(); + + reader.enumerate(parmInfos, parmInfoCount); + + animInfos.clear(); + animInfos.reserve(animInfoCount); + reader.enumerate(animInfos, animInfoCount, + [this, parmInfoCount](athena::io::IStreamReader& reader, AnimInfo& ai) { + ai.id = reader.readUint32Big(); + ai.parmVals.reserve(parmInfoCount); + for (const ParmInfo& pi : parmInfos) { + switch (ParmInfo::DataType(pi.parmType)) { + case ParmInfo::DataType::Int32: + ai.parmVals.emplace_back(reader.readInt32Big()); + break; + case ParmInfo::DataType::UInt32: + case ParmInfo::DataType::Enum: + ai.parmVals.emplace_back(reader.readUint32Big()); + break; + case ParmInfo::DataType::Float: + ai.parmVals.emplace_back(reader.readFloatBig()); + break; + case ParmInfo::DataType::Bool: + ai.parmVals.emplace_back(reader.readBool()); + break; + default: + break; + } + } + }); +} + +template <> +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate( + athena::io::IStreamWriter& writer) { + writer.writeUint32Big(id); + writer.writeUint32Big(parmInfos.size()); + writer.writeUint32Big(animInfos.size()); + + for (const ParmInfo& pi : parmInfos) + pi.write(writer); + + for (const AnimInfo& ai : animInfos) { + writer.writeUint32Big(ai.id); + auto it = ai.parmVals.begin(); + for (const ParmInfo& pi : parmInfos) { + ParmInfo::Parm pVal; + if (it != ai.parmVals.end()) + pVal = *it++; + switch (ParmInfo::DataType(pi.parmType)) { + case ParmInfo::DataType::Int32: + writer.writeInt32Big(pVal.int32); break; - } -} - -template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate(size_t& __isz) -{ - __isz += 12; - switch (DataType(parmType)) - { - case DataType::Int32: - case DataType::UInt32: - case DataType::Enum: - case DataType::Float: - __isz += 8; + case ParmInfo::DataType::UInt32: + case ParmInfo::DataType::Enum: + writer.writeUint32Big(pVal.uint32); break; - case DataType::Bool: - __isz += 2; + case ParmInfo::DataType::Float: + writer.writeFloatBig(pVal.float32); break; + case ParmInfo::DataType::Bool: + writer.writeBool(pVal.bool1); + break; + default: + break; + } } + } } template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate - (athena::io::YAMLDocReader& reader) -{ - parmType = reader.readUint32("parmType"); - weightFunction = reader.readUint32("weightFunction"); - weight = reader.readFloat("weight"); - size_t parmValCount; - if (auto v = reader.enterSubVector("range", parmValCount)) - { - switch (DataType(parmType)) - { - case DataType::Int32: - range[0].int32 = reader.readInt32(nullptr); - range[1].int32 = reader.readInt32(nullptr); - break; - case DataType::UInt32: - case DataType::Enum: - range[0].uint32 = reader.readUint32(nullptr); - range[1].uint32 = reader.readUint32(nullptr); - break; - case DataType::Float: - range[0].float32 = reader.readFloat(nullptr); - range[1].float32 = reader.readFloat(nullptr); - break; - case DataType::Bool: - range[0].bool1 = reader.readBool(nullptr); - range[1].bool1 = reader.readBool(nullptr); - break; - default: break; - } +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate(size_t& __isz) { + __isz += 12; + for (const ParmInfo& pi : parmInfos) + pi.binarySize(__isz); + + __isz += animInfos.size() * 4; + for (const ParmInfo& pi : parmInfos) { + switch (ParmInfo::DataType(pi.parmType)) { + case ParmInfo::DataType::Int32: + case ParmInfo::DataType::UInt32: + case ParmInfo::DataType::Enum: + case ParmInfo::DataType::Float: + __isz += animInfos.size() * 4; + break; + case ParmInfo::DataType::Bool: + __isz += animInfos.size(); + break; + default: + break; } + } } template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::Enumerate - (athena::io::YAMLDocWriter& writer) -{ - writer.writeUint32("parmType", parmType); - writer.writeUint32("weightFunction", weightFunction); - writer.writeFloat("weight", weight); - if (auto v = writer.enterSubVector("range")) - { - switch (DataType(parmType)) - { - case DataType::Int32: - writer.writeInt32(nullptr, range[0].int32); - writer.writeInt32(nullptr, range[1].int32); - break; - case DataType::UInt32: - case DataType::Enum: - writer.writeUint32(nullptr, range[0].uint32); - writer.writeUint32(nullptr, range[0].uint32); - break; - case DataType::Float: - writer.writeFloat(nullptr, range[0].float32); - writer.writeFloat(nullptr, range[0].float32); - break; - case DataType::Bool: - writer.writeBool(nullptr, range[0].bool1); - writer.writeBool(nullptr, range[0].bool1); - break; - } - } -} +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate( + athena::io::YAMLDocReader& reader) { + id = reader.readUint32("id"); -const char* ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo::DNAType() -{ - return "urde::DNAMP1::ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::ParmInfo"; + size_t parmInfoCount = reader.enumerate("parmInfos", parmInfos); + + reader.enumerate("animInfos", animInfos, + [this, parmInfoCount](athena::io::YAMLDocReader& reader, AnimInfo& ai) { + ai.id = reader.readUint32("id"); + ai.parmVals.reserve(parmInfoCount); + size_t parmValCount; + if (auto v = reader.enterSubVector("parms", parmValCount)) { + for (const ParmInfo& pi : parmInfos) { + switch (ParmInfo::DataType(pi.parmType)) { + case ParmInfo::DataType::Int32: + ai.parmVals.emplace_back(reader.readInt32(nullptr)); + break; + case ParmInfo::DataType::UInt32: + case ParmInfo::DataType::Enum: + ai.parmVals.emplace_back(reader.readUint32(nullptr)); + break; + case ParmInfo::DataType::Float: + ai.parmVals.emplace_back(reader.readFloat(nullptr)); + break; + case ParmInfo::DataType::Bool: + ai.parmVals.emplace_back(reader.readBool(nullptr)); + break; + default: + break; + } + } + } + }); } template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate - (athena::io::IStreamReader& reader) -{ - id = reader.readUint32Big(); - atUint32 parmInfoCount = reader.readUint32Big(); - atUint32 animInfoCount = reader.readUint32Big(); +void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate( + athena::io::YAMLDocWriter& writer) { + writer.writeUint32("id", id); - reader.enumerate(parmInfos, parmInfoCount); + writer.enumerate("parmInfos", parmInfos); - animInfos.clear(); - animInfos.reserve(animInfoCount); - reader.enumerate(animInfos, animInfoCount, - [this, parmInfoCount](athena::io::IStreamReader& reader, AnimInfo& ai) - { - ai.id = reader.readUint32Big(); - ai.parmVals.reserve(parmInfoCount); - for (const ParmInfo& pi : parmInfos) - { - switch (ParmInfo::DataType(pi.parmType)) - { - case ParmInfo::DataType::Int32: - ai.parmVals.emplace_back(reader.readInt32Big()); - break; - case ParmInfo::DataType::UInt32: - case ParmInfo::DataType::Enum: - ai.parmVals.emplace_back(reader.readUint32Big()); - break; - case ParmInfo::DataType::Float: - ai.parmVals.emplace_back(reader.readFloatBig()); - break; - case ParmInfo::DataType::Bool: - ai.parmVals.emplace_back(reader.readBool()); - break; - default: break; - } - } - }); -} - -template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate - (athena::io::IStreamWriter& writer) -{ - writer.writeUint32Big(id); - writer.writeUint32Big(parmInfos.size()); - writer.writeUint32Big(animInfos.size()); - - for (const ParmInfo& pi : parmInfos) - pi.write(writer); - - for (const AnimInfo& ai : animInfos) - { - writer.writeUint32Big(ai.id); - auto it = ai.parmVals.begin(); - for (const ParmInfo& pi : parmInfos) - { - ParmInfo::Parm pVal; - if (it != ai.parmVals.end()) - pVal = *it++; - switch (ParmInfo::DataType(pi.parmType)) - { - case ParmInfo::DataType::Int32: - writer.writeInt32Big(pVal.int32); - break; - case ParmInfo::DataType::UInt32: - case ParmInfo::DataType::Enum: - writer.writeUint32Big(pVal.uint32); - break; - case ParmInfo::DataType::Float: - writer.writeFloatBig(pVal.float32); - break; - case ParmInfo::DataType::Bool: - writer.writeBool(pVal.bool1); - break; - default: break; - } - } - } -} - -template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate(size_t& __isz) -{ - __isz += 12; - for (const ParmInfo& pi : parmInfos) - pi.binarySize(__isz); - - __isz += animInfos.size() * 4; - for (const ParmInfo& pi : parmInfos) - { - switch (ParmInfo::DataType(pi.parmType)) - { + writer.enumerate("animInfos", animInfos, [this](athena::io::YAMLDocWriter& writer, const AnimInfo& ai) { + writer.writeUint32("id", ai.id); + auto it = ai.parmVals.begin(); + if (auto v = writer.enterSubVector("parms")) { + for (const ParmInfo& pi : parmInfos) { + ParmInfo::Parm pVal; + if (it != ai.parmVals.end()) + pVal = *it++; + switch (ParmInfo::DataType(pi.parmType)) { case ParmInfo::DataType::Int32: + writer.writeInt32(nullptr, pVal.int32); + break; case ParmInfo::DataType::UInt32: case ParmInfo::DataType::Enum: + writer.writeUint32(nullptr, pVal.uint32); + break; case ParmInfo::DataType::Float: - __isz += animInfos.size() * 4; - break; + writer.writeFloat(nullptr, pVal.float32); + break; case ParmInfo::DataType::Bool: - __isz += animInfos.size(); - break; - default: break; + writer.writeBool(nullptr, pVal.bool1); + break; + default: + break; } + } } + }); +} + +const char* ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::DNAType() { + return "urde::DNAMP1::ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState"; } template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate - (athena::io::YAMLDocReader& reader) -{ - id = reader.readUint32("id"); +void ANCS::CharacterSet::CharacterInfo::Enumerate(athena::io::IStreamReader& reader) { + idx = reader.readUint32Big(); + atUint16 sectionCount = reader.readUint16Big(); + name = reader.readString(); + cmdl.read(reader); + cskr.read(reader); + cinf.read(reader); - size_t parmInfoCount = reader.enumerate("parmInfos", parmInfos); + atUint32 animationCount = reader.readUint32Big(); + reader.enumerate(animations, animationCount); - reader.enumerate("animInfos", animInfos, - [this, parmInfoCount](athena::io::YAMLDocReader& reader, AnimInfo& ai) - { - ai.id = reader.readUint32("id"); - ai.parmVals.reserve(parmInfoCount); - size_t parmValCount; - if (auto v = reader.enterSubVector("parms", parmValCount)) - { - for (const ParmInfo& pi : parmInfos) - { - switch (ParmInfo::DataType(pi.parmType)) - { - case ParmInfo::DataType::Int32: - ai.parmVals.emplace_back(reader.readInt32(nullptr)); - break; - case ParmInfo::DataType::UInt32: - case ParmInfo::DataType::Enum: - ai.parmVals.emplace_back(reader.readUint32(nullptr)); - break; - case ParmInfo::DataType::Float: - ai.parmVals.emplace_back(reader.readFloat(nullptr)); - break; - case ParmInfo::DataType::Bool: - ai.parmVals.emplace_back(reader.readBool(nullptr)); - break; - default: break; - } - } - } - }); + pasDatabase.read(reader); + + atUint32 partCount = reader.readUint32Big(); + reader.enumerate(partResData.part, partCount); + + atUint32 swhcCount = reader.readUint32Big(); + reader.enumerate(partResData.swhc, swhcCount); + + atUint32 unkCount = reader.readUint32Big(); + reader.enumerate(partResData.unk, unkCount); + + partResData.elsc.clear(); + if (sectionCount > 5) { + atUint32 elscCount = reader.readUint32Big(); + reader.enumerate(partResData.elsc, elscCount); + } + + unk1 = reader.readUint32Big(); + + animAABBs.clear(); + if (sectionCount > 1) { + atUint32 aabbCount = reader.readUint32Big(); + reader.enumerate(animAABBs, aabbCount); + } + + effects.clear(); + if (sectionCount > 2) { + atUint32 effectCount = reader.readUint32Big(); + reader.enumerate(effects, effectCount); + } + + if (sectionCount > 3) { + cmdlIce.read(reader); + cskrIce.read(reader); + } + + animIdxs.clear(); + if (sectionCount > 4) { + atUint32 aidxCount = reader.readUint32Big(); + reader.enumerateBig(animIdxs, aidxCount); + } } template <> -void ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::Enumerate - (athena::io::YAMLDocWriter& writer) -{ - writer.writeUint32("id", id); +void ANCS::CharacterSet::CharacterInfo::Enumerate(athena::io::IStreamWriter& writer) { + writer.writeUint32Big(idx); - writer.enumerate("parmInfos", parmInfos); + atUint16 sectionCount; + if (partResData.elsc.size()) + sectionCount = 6; + else if (animIdxs.size()) + sectionCount = 5; + else if (cmdlIce) + sectionCount = 4; + else if (effects.size()) + sectionCount = 3; + else if (animAABBs.size()) + sectionCount = 2; + else + sectionCount = 1; + writer.writeUint16Big(sectionCount); - writer.enumerate("animInfos", animInfos, - [this](athena::io::YAMLDocWriter& writer, const AnimInfo& ai) - { - writer.writeUint32("id", ai.id); - auto it = ai.parmVals.begin(); - if (auto v = writer.enterSubVector("parms")) - { - for (const ParmInfo& pi : parmInfos) - { - ParmInfo::Parm pVal; - if (it != ai.parmVals.end()) - pVal = *it++; - switch (ParmInfo::DataType(pi.parmType)) - { - case ParmInfo::DataType::Int32: - writer.writeInt32(nullptr, pVal.int32); - break; - case ParmInfo::DataType::UInt32: - case ParmInfo::DataType::Enum: - writer.writeUint32(nullptr, pVal.uint32); - break; - case ParmInfo::DataType::Float: - writer.writeFloat(nullptr, pVal.float32); - break; - case ParmInfo::DataType::Bool: - writer.writeBool(nullptr, pVal.bool1); - break; - default: break; - } - } - } - }); -} + writer.writeString(name); + cmdl.write(writer); + cskr.write(writer); + cinf.write(writer); -const char* ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState::DNAType() -{ - return "urde::DNAMP1::ANCS::CharacterSet::CharacterInfo::PASDatabase::AnimState"; + writer.writeUint32Big(animations.size()); + writer.enumerate(animations); + + pasDatabase.write(writer); + + writer.writeUint32Big(partResData.part.size()); + writer.enumerate(partResData.part); + + writer.writeUint32Big(partResData.swhc.size()); + writer.enumerate(partResData.swhc); + + writer.writeUint32Big(partResData.unk.size()); + writer.enumerate(partResData.unk); + + if (sectionCount > 5) { + writer.writeUint32Big(partResData.elsc.size()); + writer.enumerate(partResData.elsc); + } + + writer.writeUint32Big(unk1); + + if (sectionCount > 1) { + writer.writeUint32Big(animAABBs.size()); + writer.enumerate(animAABBs); + } + + if (sectionCount > 2) { + writer.writeUint32Big(effects.size()); + writer.enumerate(effects); + } + + if (sectionCount > 3) { + cmdlIce.write(writer); + cskrIce.write(writer); + } + + if (sectionCount > 4) { + writer.writeUint32Big(animIdxs.size()); + for (atUint32 idx : animIdxs) + writer.writeUint32Big(idx); + } } template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(athena::io::IStreamReader& reader) -{ - idx = reader.readUint32Big(); - atUint16 sectionCount = reader.readUint16Big(); - name = reader.readString(); - cmdl.read(reader); - cskr.read(reader); - cinf.read(reader); +void ANCS::CharacterSet::CharacterInfo::Enumerate(size_t& __isz) { + __isz += 6; - atUint32 animationCount = reader.readUint32Big(); - reader.enumerate(animations, animationCount); + atUint16 sectionCount; + if (partResData.elsc.size()) + sectionCount = 6; + else if (animIdxs.size()) + sectionCount = 5; + else if (cmdlIce) + sectionCount = 4; + else if (effects.size()) + sectionCount = 3; + else if (animAABBs.size()) + sectionCount = 2; + else + sectionCount = 1; - pasDatabase.read(reader); + __isz += name.size() + 1; + __isz += 12; - atUint32 partCount = reader.readUint32Big(); - reader.enumerate(partResData.part, partCount); + __isz += 4; + for (const Animation& a : animations) + a.binarySize(__isz); - atUint32 swhcCount = reader.readUint32Big(); - reader.enumerate(partResData.swhc, swhcCount); + pasDatabase.binarySize(__isz); - atUint32 unkCount = reader.readUint32Big(); - reader.enumerate(partResData.unk, unkCount); + __isz += 4; + for (const UniqueID32& id : partResData.part) + id.binarySize(__isz); - partResData.elsc.clear(); - if (sectionCount > 5) - { - atUint32 elscCount = reader.readUint32Big(); - reader.enumerate(partResData.elsc, elscCount); - } + __isz += 4; + for (const UniqueID32& id : partResData.swhc) + id.binarySize(__isz); - unk1 = reader.readUint32Big(); - - animAABBs.clear(); - if (sectionCount > 1) - { - atUint32 aabbCount = reader.readUint32Big(); - reader.enumerate(animAABBs, aabbCount); - } - - effects.clear(); - if (sectionCount > 2) - { - atUint32 effectCount = reader.readUint32Big(); - reader.enumerate(effects, effectCount); - } - - if (sectionCount > 3) - { - cmdlIce.read(reader); - cskrIce.read(reader); - } - - animIdxs.clear(); - if (sectionCount > 4) - { - atUint32 aidxCount = reader.readUint32Big(); - reader.enumerateBig(animIdxs, aidxCount); - } -} - -template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(athena::io::IStreamWriter& writer) -{ - writer.writeUint32Big(idx); - - atUint16 sectionCount; - if (partResData.elsc.size()) - sectionCount = 6; - else if (animIdxs.size()) - sectionCount = 5; - else if (cmdlIce) - sectionCount = 4; - else if (effects.size()) - sectionCount = 3; - else if (animAABBs.size()) - sectionCount = 2; - else - sectionCount = 1; - writer.writeUint16Big(sectionCount); - - writer.writeString(name); - cmdl.write(writer); - cskr.write(writer); - cinf.write(writer); - - writer.writeUint32Big(animations.size()); - writer.enumerate(animations); - - pasDatabase.write(writer); - - writer.writeUint32Big(partResData.part.size()); - writer.enumerate(partResData.part); - - writer.writeUint32Big(partResData.swhc.size()); - writer.enumerate(partResData.swhc); - - writer.writeUint32Big(partResData.unk.size()); - writer.enumerate(partResData.unk); - - if (sectionCount > 5) - { - writer.writeUint32Big(partResData.elsc.size()); - writer.enumerate(partResData.elsc); - } - - writer.writeUint32Big(unk1); - - if (sectionCount > 1) - { - writer.writeUint32Big(animAABBs.size()); - writer.enumerate(animAABBs); - } - - if (sectionCount > 2) - { - writer.writeUint32Big(effects.size()); - writer.enumerate(effects); - } - - if (sectionCount > 3) - { - cmdlIce.write(writer); - cskrIce.write(writer); - } - - if (sectionCount > 4) - { - writer.writeUint32Big(animIdxs.size()); - for (atUint32 idx : animIdxs) - writer.writeUint32Big(idx); - } -} - -template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(size_t& __isz) -{ - __isz += 6; - - atUint16 sectionCount; - if (partResData.elsc.size()) - sectionCount = 6; - else if (animIdxs.size()) - sectionCount = 5; - else if (cmdlIce) - sectionCount = 4; - else if (effects.size()) - sectionCount = 3; - else if (animAABBs.size()) - sectionCount = 2; - else - sectionCount = 1; - - __isz += name.size() + 1; - __isz += 12; + __isz += 4; + for (const UniqueID32& id : partResData.unk) + id.binarySize(__isz); + if (sectionCount > 5) { __isz += 4; - for (const Animation& a : animations) - a.binarySize(__isz); + for (const UniqueID32& id : partResData.elsc) + id.binarySize(__isz); + } - pasDatabase.binarySize(__isz); + __isz += 4; + if (sectionCount > 1) { __isz += 4; - for (const UniqueID32& id : partResData.part) - id.binarySize(__isz); + for (const ActionAABB& aabb : animAABBs) + aabb.binarySize(__isz); + } + if (sectionCount > 2) { __isz += 4; - for (const UniqueID32& id : partResData.swhc) - id.binarySize(__isz); + for (const Effect& e : effects) + e.binarySize(__isz); + } + if (sectionCount > 3) + __isz += 8; + + if (sectionCount > 4) + __isz += 4 + animIdxs.size() * 4; +} + +template <> +void ANCS::CharacterSet::CharacterInfo::Enumerate(athena::io::YAMLDocReader& reader) { + idx = reader.readUint32("idx"); + atUint16 sectionCount = reader.readUint16("sectionCount"); + name = reader.readString("name"); + reader.enumerate("cmdl", cmdl); + + reader.enumerate("animations", animations); + + reader.enumerate("pasDatabase", pasDatabase); + + reader.enumerate("part", partResData.part); + + reader.enumerate("swhc", partResData.swhc); + + reader.enumerate("unk", partResData.unk); + + partResData.elsc.clear(); + if (sectionCount > 5) { + reader.enumerate("elsc", partResData.elsc); + } + + unk1 = reader.readUint32("unk1"); + + animAABBs.clear(); + if (sectionCount > 1) { + reader.enumerate("part", animAABBs); + } + + effects.clear(); + if (sectionCount > 2) { + reader.enumerate("effects", effects); + } + + if (sectionCount > 3) { + reader.enumerate("cmdlIce", cmdlIce); + } + + animIdxs.clear(); + if (sectionCount > 4) { + reader.enumerate("animIdxs", animIdxs); + } +} + +template <> +void ANCS::CharacterSet::CharacterInfo::Enumerate(athena::io::YAMLDocWriter& writer) { + writer.writeUint32("idx", idx); + + atUint16 sectionCount; + if (partResData.elsc.size()) + sectionCount = 6; + else if (animIdxs.size()) + sectionCount = 5; + else if (cmdlIce) + sectionCount = 4; + else if (effects.size()) + sectionCount = 3; + else if (animAABBs.size()) + sectionCount = 2; + else + sectionCount = 1; + writer.writeUint16("sectionCount", sectionCount); + + writer.writeString("name", name); + writer.enumerate("cmdl", cmdl); + + writer.enumerate("animations", animations); + + writer.enumerate("pasDatabase", pasDatabase); + + writer.enumerate("part", partResData.part); + + writer.enumerate("swhc", partResData.swhc); + + writer.enumerate("unk", partResData.unk); + + if (sectionCount > 5) { + writer.enumerate("elsc", partResData.elsc); + } + + writer.writeUint32("unk1", unk1); + + if (sectionCount > 1) { + writer.enumerate("animAABBs", animAABBs); + } + + if (sectionCount > 2) { + writer.enumerate("effects", effects); + } + + if (sectionCount > 3) { + writer.enumerate("cmdlIce", cmdlIce); + } + + if (sectionCount > 4) { + writer.enumerate("animIdxs", animIdxs); + } +} + +const char* ANCS::CharacterSet::CharacterInfo::DNAType() { return "urde::DNAMP1::ANCS::CharacterSet::CharacterInfo"; } + +template <> +void ANCS::AnimationSet::MetaAnimFactory::Enumerate(athena::io::IStreamReader& reader) { + IMetaAnim::Type type(IMetaAnim::Type(reader.readUint32Big())); + switch (type) { + case IMetaAnim::Type::Primitive: + m_anim.reset(new struct MetaAnimPrimitive); + m_anim->read(reader); + break; + case IMetaAnim::Type::Blend: + m_anim.reset(new struct MetaAnimBlend); + m_anim->read(reader); + break; + case IMetaAnim::Type::PhaseBlend: + m_anim.reset(new struct MetaAnimPhaseBlend); + m_anim->read(reader); + break; + case IMetaAnim::Type::Random: + m_anim.reset(new struct MetaAnimRandom); + m_anim->read(reader); + break; + case IMetaAnim::Type::Sequence: + m_anim.reset(new struct MetaAnimSequence); + m_anim->read(reader); + break; + default: + m_anim.reset(nullptr); + break; + } +} + +template <> +void ANCS::AnimationSet::MetaAnimFactory::Enumerate(athena::io::IStreamWriter& writer) { + if (!m_anim) + return; + writer.writeInt32Big(atUint32(m_anim->m_type)); + m_anim->write(writer); +} + +template <> +void ANCS::AnimationSet::MetaAnimFactory::Enumerate(size_t& __isz) { + if (!m_anim) + return; + __isz += 4; + m_anim->binarySize(__isz); +} + +template <> +void ANCS::AnimationSet::MetaAnimFactory::Enumerate(athena::io::YAMLDocReader& reader) { + std::string type = reader.readString("type"); + std::transform(type.begin(), type.end(), type.begin(), tolower); + if (!type.compare("primitive")) { + m_anim.reset(new struct MetaAnimPrimitive); + m_anim->read(reader); + } else if (!type.compare("blend")) { + m_anim.reset(new struct MetaAnimBlend); + m_anim->read(reader); + } else if (!type.compare("phaseblend")) { + m_anim.reset(new struct MetaAnimPhaseBlend); + m_anim->read(reader); + } else if (!type.compare("random")) { + m_anim.reset(new struct MetaAnimRandom); + m_anim->read(reader); + } else if (!type.compare("sequence")) { + m_anim.reset(new struct MetaAnimSequence); + m_anim->read(reader); + } else { + m_anim.reset(nullptr); + } +} + +template <> +void ANCS::AnimationSet::MetaAnimFactory::Enumerate(athena::io::YAMLDocWriter& writer) { + if (!m_anim) + return; + writer.writeString("type", m_anim->m_typeStr); + m_anim->write(writer); +} + +const char* ANCS::AnimationSet::MetaAnimFactory::DNAType() { + return "urde::DNAMP1::ANCS::AnimationSet::MetaAnimFactory"; +} + +template <> +void ANCS::AnimationSet::MetaTransFactory::Enumerate(athena::io::IStreamReader& reader) { + IMetaTrans::Type type(IMetaTrans::Type(reader.readUint32Big())); + switch (type) { + case IMetaTrans::Type::MetaAnim: + m_trans.reset(new struct MetaTransMetaAnim); + m_trans->read(reader); + break; + case IMetaTrans::Type::Trans: + m_trans.reset(new struct MetaTransTrans); + m_trans->read(reader); + break; + case IMetaTrans::Type::PhaseTrans: + m_trans.reset(new struct MetaTransPhaseTrans); + m_trans->read(reader); + break; + case IMetaTrans::Type::NoTrans: + default: + m_trans.reset(nullptr); + break; + } +} + +template <> +void ANCS::AnimationSet::MetaTransFactory::Enumerate(athena::io::IStreamWriter& writer) { + if (!m_trans) { + writer.writeInt32Big(atUint32(IMetaTrans::Type::NoTrans)); + return; + } + writer.writeInt32Big(atUint32(m_trans->m_type)); + m_trans->write(writer); +} + +template <> +void ANCS::AnimationSet::MetaTransFactory::Enumerate(size_t& __isz) { + __isz += 4; + if (!m_trans) + return; + m_trans->binarySize(__isz); +} + +template <> +void ANCS::AnimationSet::MetaTransFactory::Enumerate(athena::io::YAMLDocReader& reader) { + std::string type = reader.readString("type"); + std::transform(type.begin(), type.end(), type.begin(), tolower); + if (!type.compare("metaanim")) { + m_trans.reset(new struct MetaTransMetaAnim); + m_trans->read(reader); + } else if (!type.compare("trans")) { + m_trans.reset(new struct MetaTransTrans); + m_trans->read(reader); + } else if (!type.compare("phasetrans")) { + m_trans.reset(new struct MetaTransPhaseTrans); + m_trans->read(reader); + } else { + m_trans.reset(nullptr); + } +} + +template <> +void ANCS::AnimationSet::MetaTransFactory::Enumerate(athena::io::YAMLDocWriter& writer) { + if (!m_trans) { + writer.writeString("type", "NoTrans"); + return; + } + writer.writeString("type", m_trans->m_typeStr ? m_trans->m_typeStr : "NoTrans"); + m_trans->write(writer); +} + +const char* ANCS::AnimationSet::MetaTransFactory::DNAType() { + return "urde::DNAMP1::ANCS::AnimationSet::MetaTransFactory"; +} + +template <> +void ANCS::AnimationSet::Enumerate(athena::io::IStreamReader& reader) { + atUint16 sectionCount = reader.readUint16Big(); + + atUint32 animationCount = reader.readUint32Big(); + reader.enumerate(animations, animationCount); + + atUint32 transitionCount = reader.readUint32Big(); + reader.enumerate(transitions, transitionCount); + defaultTransition.read(reader); + + additiveAnims.clear(); + if (sectionCount > 1) { + atUint32 additiveAnimCount = reader.readUint32Big(); + reader.enumerate(additiveAnims, additiveAnimCount); + floatA = reader.readFloatBig(); + floatB = reader.readFloatBig(); + } + + halfTransitions.clear(); + if (sectionCount > 2) { + atUint32 halfTransitionCount = reader.readUint32Big(); + reader.enumerate(halfTransitions, halfTransitionCount); + } + + animResources.clear(); + if (sectionCount > 3) { + atUint32 animResourcesCount = reader.readUint32Big(); + reader.enumerate(animResources, animResourcesCount); + } +} + +template <> +void ANCS::AnimationSet::Enumerate(athena::io::IStreamWriter& writer) { + atUint16 sectionCount; + if (animResources.size()) + sectionCount = 4; + else if (halfTransitions.size()) + sectionCount = 3; + else if (additiveAnims.size()) + sectionCount = 2; + else + sectionCount = 1; + + writer.writeUint16Big(sectionCount); + + writer.writeUint32Big(animations.size()); + writer.enumerate(animations); + + writer.writeUint32Big(transitions.size()); + writer.enumerate(transitions); + defaultTransition.write(writer); + + if (sectionCount > 1) { + writer.writeUint32Big(additiveAnims.size()); + writer.enumerate(additiveAnims); + writer.writeFloatBig(floatA); + writer.writeFloatBig(floatB); + } + + if (sectionCount > 2) { + writer.writeUint32Big(halfTransitions.size()); + writer.enumerate(halfTransitions); + } + + if (sectionCount > 3) { + writer.writeUint32Big(animResources.size()); + writer.enumerate(animResources); + } +} + +template <> +void ANCS::AnimationSet::Enumerate(size_t& __isz) { + atUint16 sectionCount; + if (animResources.size()) + sectionCount = 4; + else if (halfTransitions.size()) + sectionCount = 3; + else if (additiveAnims.size()) + sectionCount = 2; + else + sectionCount = 1; + + __isz += 6; + for (const Animation& a : animations) + a.binarySize(__isz); + + __isz += 4; + for (const Transition& t : transitions) + t.binarySize(__isz); + defaultTransition.binarySize(__isz); + + if (sectionCount > 1) { __isz += 4; - for (const UniqueID32& id : partResData.unk) - id.binarySize(__isz); - - if (sectionCount > 5) - { - __isz += 4; - for (const UniqueID32& id : partResData.elsc) - id.binarySize(__isz); - } + for (const AdditiveAnimationInfo& aa : additiveAnims) + aa.binarySize(__isz); + __isz += 8; + } + if (sectionCount > 2) { __isz += 4; + for (const HalfTransition& ht : halfTransitions) + ht.binarySize(__isz); + } - if (sectionCount > 1) - { - __isz += 4; - for (const ActionAABB& aabb : animAABBs) - aabb.binarySize(__isz); - } - - if (sectionCount > 2) - { - __isz += 4; - for (const Effect& e : effects) - e.binarySize(__isz); - } - - if (sectionCount > 3) - __isz += 8; - - if (sectionCount > 4) - __isz += 4 + animIdxs.size() * 4; -} - -template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(athena::io::YAMLDocReader& reader) -{ - idx = reader.readUint32("idx"); - atUint16 sectionCount = reader.readUint16("sectionCount"); - name = reader.readString("name"); - reader.enumerate("cmdl", cmdl); - - reader.enumerate("animations", animations); - - reader.enumerate("pasDatabase", pasDatabase); - - reader.enumerate("part", partResData.part); - - reader.enumerate("swhc", partResData.swhc); - - reader.enumerate("unk", partResData.unk); - - partResData.elsc.clear(); - if (sectionCount > 5) - { - reader.enumerate("elsc", partResData.elsc); - } - - unk1 = reader.readUint32("unk1"); - - animAABBs.clear(); - if (sectionCount > 1) - { - reader.enumerate("part", animAABBs); - } - - effects.clear(); - if (sectionCount > 2) - { - reader.enumerate("effects", effects); - } - - if (sectionCount > 3) - { - reader.enumerate("cmdlIce", cmdlIce); - } - - animIdxs.clear(); - if (sectionCount > 4) - { - reader.enumerate("animIdxs", animIdxs); - } -} - -template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(athena::io::YAMLDocWriter& writer) -{ - writer.writeUint32("idx", idx); - - atUint16 sectionCount; - if (partResData.elsc.size()) - sectionCount = 6; - else if (animIdxs.size()) - sectionCount = 5; - else if (cmdlIce) - sectionCount = 4; - else if (effects.size()) - sectionCount = 3; - else if (animAABBs.size()) - sectionCount = 2; - else - sectionCount = 1; - writer.writeUint16("sectionCount", sectionCount); - - writer.writeString("name", name); - writer.enumerate("cmdl", cmdl); - - writer.enumerate("animations", animations); - - writer.enumerate("pasDatabase", pasDatabase); - - writer.enumerate("part", partResData.part); - - writer.enumerate("swhc", partResData.swhc); - - writer.enumerate("unk", partResData.unk); - - if (sectionCount > 5) - { - writer.enumerate("elsc", partResData.elsc); - } - - writer.writeUint32("unk1", unk1); - - if (sectionCount > 1) - { - writer.enumerate("animAABBs", animAABBs); - } - - if (sectionCount > 2) - { - writer.enumerate("effects", effects); - } - - if (sectionCount > 3) - { - writer.enumerate("cmdlIce", cmdlIce); - } - - if (sectionCount > 4) - { - writer.enumerate("animIdxs", animIdxs); - } -} - -const char* ANCS::CharacterSet::CharacterInfo::DNAType() -{ - return "urde::DNAMP1::ANCS::CharacterSet::CharacterInfo"; -} - -template <> -void ANCS::AnimationSet::MetaAnimFactory::Enumerate(athena::io::IStreamReader& reader) -{ - IMetaAnim::Type type(IMetaAnim::Type(reader.readUint32Big())); - switch (type) - { - case IMetaAnim::Type::Primitive: - m_anim.reset(new struct MetaAnimPrimitive); - m_anim->read(reader); - break; - case IMetaAnim::Type::Blend: - m_anim.reset(new struct MetaAnimBlend); - m_anim->read(reader); - break; - case IMetaAnim::Type::PhaseBlend: - m_anim.reset(new struct MetaAnimPhaseBlend); - m_anim->read(reader); - break; - case IMetaAnim::Type::Random: - m_anim.reset(new struct MetaAnimRandom); - m_anim->read(reader); - break; - case IMetaAnim::Type::Sequence: - m_anim.reset(new struct MetaAnimSequence); - m_anim->read(reader); - break; - default: - m_anim.reset(nullptr); - break; - } -} - -template <> -void ANCS::AnimationSet::MetaAnimFactory::Enumerate(athena::io::IStreamWriter& writer) -{ - if (!m_anim) - return; - writer.writeInt32Big(atUint32(m_anim->m_type)); - m_anim->write(writer); -} - -template <> -void ANCS::AnimationSet::MetaAnimFactory::Enumerate(size_t& __isz) -{ - if (!m_anim) - return; + if (sectionCount > 3) { __isz += 4; - m_anim->binarySize(__isz); + for (const AnimationResources& ar : animResources) + ar.binarySize(__isz); + } } template <> -void ANCS::AnimationSet::MetaAnimFactory::Enumerate(athena::io::YAMLDocReader& reader) -{ - std::string type = reader.readString("type"); - std::transform(type.begin(), type.end(), type.begin(), tolower); - if (!type.compare("primitive")) - { - m_anim.reset(new struct MetaAnimPrimitive); - m_anim->read(reader); - } - else if (!type.compare("blend")) - { - m_anim.reset(new struct MetaAnimBlend); - m_anim->read(reader); - } - else if (!type.compare("phaseblend")) - { - m_anim.reset(new struct MetaAnimPhaseBlend); - m_anim->read(reader); - } - else if (!type.compare("random")) - { - m_anim.reset(new struct MetaAnimRandom); - m_anim->read(reader); - } - else if (!type.compare("sequence")) - { - m_anim.reset(new struct MetaAnimSequence); - m_anim->read(reader); - } - else - { - m_anim.reset(nullptr); - } +void ANCS::AnimationSet::Enumerate(athena::io::YAMLDocReader& reader) { + atUint16 sectionCount = reader.readUint16("sectionCount"); + + reader.enumerate("animations", animations); + + reader.enumerate("transitions", transitions); + reader.enumerate("defaultTransition", defaultTransition); + + additiveAnims.clear(); + if (sectionCount > 1) { + reader.enumerate("additiveAnims", additiveAnims); + floatA = reader.readFloat("floatA"); + floatB = reader.readFloat("floatB"); + } + + halfTransitions.clear(); + if (sectionCount > 2) { + reader.enumerate("halfTransitions", halfTransitions); + } + + animResources.clear(); + if (sectionCount > 3) { + reader.enumerate("animResources", animResources); + } } template <> -void ANCS::AnimationSet::MetaAnimFactory::Enumerate(athena::io::YAMLDocWriter& writer) -{ - if (!m_anim) - return; - writer.writeString("type", m_anim->m_typeStr); - m_anim->write(writer); +void ANCS::AnimationSet::Enumerate(athena::io::YAMLDocWriter& writer) { + atUint16 sectionCount; + if (animResources.size()) + sectionCount = 4; + else if (halfTransitions.size()) + sectionCount = 3; + else if (additiveAnims.size()) + sectionCount = 2; + else + sectionCount = 1; + + writer.writeUint16("sectionCount", sectionCount); + + writer.enumerate("animations", animations); + + writer.enumerate("transitions", transitions); + writer.enumerate("defaultTransition", defaultTransition); + + if (sectionCount > 1) { + writer.enumerate("additiveAnims", additiveAnims); + writer.writeFloat("floatA", floatA); + writer.writeFloat("floatB", floatB); + } + + if (sectionCount > 2) { + writer.enumerate("halfTransitions", halfTransitions); + } + + if (sectionCount > 3) { + writer.enumerate("animResources", animResources); + } } -const char* ANCS::AnimationSet::MetaAnimFactory::DNAType() -{ - return "urde::DNAMP1::ANCS::AnimationSet::MetaAnimFactory"; +void ANCS::AnimationSet::MetaAnimPrimitive::gatherPrimitives( + PAKRouter* pakRouter, std::map>& out) { + if (!pakRouter) { + out[animIdx] = {animName, animId, UniqueID32(), false}; + return; + } + + const nod::Node* node; + const PAK::Entry* entry = pakRouter->lookupEntry(animId, &node, true); + if (!entry) { + out[animIdx] = {animName, animId, UniqueID32(), false}; + return; + } + + PAKEntryReadStream rs = entry->beginReadStream(*node); + out[animIdx] = {animName, animId, ANIM::GetEVNTId(rs), false}; } -template <> -void ANCS::AnimationSet::MetaTransFactory::Enumerate(athena::io::IStreamReader& reader) -{ - IMetaTrans::Type type(IMetaTrans::Type(reader.readUint32Big())); - switch (type) - { - case IMetaTrans::Type::MetaAnim: - m_trans.reset(new struct MetaTransMetaAnim); - m_trans->read(reader); - break; - case IMetaTrans::Type::Trans: - m_trans.reset(new struct MetaTransTrans); - m_trans->read(reader); - break; - case IMetaTrans::Type::PhaseTrans: - m_trans.reset(new struct MetaTransPhaseTrans); - m_trans->read(reader); - break; - case IMetaTrans::Type::NoTrans: - default: - m_trans.reset(nullptr); - break; +const char* ANCS::AnimationSet::DNAType() { return "urde::DNAMP1::ANCS::AnimationSet"; } + +bool ANCS::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true); + hecl::ProjectPath::Type yamlType = yamlPath.getPathType(); + hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true); + hecl::ProjectPath::Type blendType = blendPath.getPathType(); + + ANCS ancs; + ancs.read(rs); + + if (force || yamlType == hecl::ProjectPath::Type::None || blendType == hecl::ProjectPath::Type::None) { + if (force || yamlType == hecl::ProjectPath::Type::None) { + athena::io::FileWriter writer(yamlPath.getAbsolutePath()); + athena::io::ToYAMLStream(ancs, writer); } + + if (force || blendType == hecl::ProjectPath::Type::None) { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + DNAANCS::ReadANCSToBlender, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1, 2>( + conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force); + } + } + + return true; } -template <> -void ANCS::AnimationSet::MetaTransFactory::Enumerate(athena::io::IStreamWriter& writer) -{ - if (!m_trans) - { - writer.writeInt32Big(atUint32(IMetaTrans::Type::NoTrans)); - return; - } - writer.writeInt32Big(atUint32(m_trans->m_type)); - m_trans->write(writer); -} +bool ANCS::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor) { + /* Search for yaml */ + hecl::ProjectPath yamlPath = inPath.getWithExtension(_SYS_STR(".yaml"), true); + if (!yamlPath.isFile()) + Log.report(logvisor::Fatal, _SYS_STR("'%s' not found as file"), yamlPath.getRelativePath().data()); -template <> -void ANCS::AnimationSet::MetaTransFactory::Enumerate(size_t& __isz) -{ - __isz += 4; - if (!m_trans) - return; - m_trans->binarySize(__isz); -} + athena::io::FileReader reader(yamlPath.getAbsolutePath()); + if (!reader.isOpen()) + Log.report(logvisor::Fatal, _SYS_STR("can't open '%s' for reading"), yamlPath.getRelativePath().data()); -template <> -void ANCS::AnimationSet::MetaTransFactory::Enumerate(athena::io::YAMLDocReader& reader) -{ - std::string type = reader.readString("type"); - std::transform(type.begin(), type.end(), type.begin(), tolower); - if (!type.compare("metaanim")) - { - m_trans.reset(new struct MetaTransMetaAnim); - m_trans->read(reader); - } - else if (!type.compare("trans")) - { - m_trans.reset(new struct MetaTransTrans); - m_trans->read(reader); - } - else if (!type.compare("phasetrans")) - { - m_trans.reset(new struct MetaTransPhaseTrans); - m_trans->read(reader); - } - else - { - m_trans.reset(nullptr); - } + if (!athena::io::ValidateFromYAMLStream(reader)) { + Log.report(logvisor::Fatal, _SYS_STR("'%s' is not urde::DNAMP1::ANCS type"), yamlPath.getRelativePath().data()); + } -} + athena::io::YAMLDocReader yamlReader; + if (!yamlReader.parse(&reader)) { + Log.report(logvisor::Fatal, _SYS_STR("unable to parse '%s'"), yamlPath.getRelativePath().data()); + } + ANCS ancs; + ancs.read(yamlReader); -template <> -void ANCS::AnimationSet::MetaTransFactory::Enumerate(athena::io::YAMLDocWriter& writer) -{ - if (!m_trans) - { - writer.writeString("type", "NoTrans"); - return; - } - writer.writeString("type", m_trans->m_typeStr?m_trans->m_typeStr:"NoTrans"); - m_trans->write(writer); -} + /* Set Character Resource IDs */ + for (ANCS::CharacterSet::CharacterInfo& ch : ancs.characterSet.characters) { + ch.cmdl = UniqueID32{}; + ch.cskr = UniqueID32{}; + ch.cinf = UniqueID32{}; + ch.cmdlIce = UniqueID32Zero{}; + ch.cskrIce = UniqueID32Zero{}; -const char* ANCS::AnimationSet::MetaTransFactory::DNAType() -{ - return "urde::DNAMP1::ANCS::AnimationSet::MetaTransFactory"; -} + hecl::SystemStringConv chSysName(ch.name); + ch.cskr = inPath.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _SYS_STR(".CSKR")); -template <> -void ANCS::AnimationSet::Enumerate(athena::io::IStreamReader& reader) -{ - atUint16 sectionCount = reader.readUint16Big(); - - atUint32 animationCount = reader.readUint32Big(); - reader.enumerate(animations, animationCount); - - atUint32 transitionCount = reader.readUint32Big(); - reader.enumerate(transitions, transitionCount); - defaultTransition.read(reader); - - additiveAnims.clear(); - if (sectionCount > 1) - { - atUint32 additiveAnimCount = reader.readUint32Big(); - reader.enumerate(additiveAnims, additiveAnimCount); - floatA = reader.readFloatBig(); - floatB = reader.readFloatBig(); - } - - halfTransitions.clear(); - if (sectionCount > 2) - { - atUint32 halfTransitionCount = reader.readUint32Big(); - reader.enumerate(halfTransitions, halfTransitionCount); - } - - animResources.clear(); - if (sectionCount > 3) - { - atUint32 animResourcesCount = reader.readUint32Big(); - reader.enumerate(animResources, animResourcesCount); - } -} - -template <> -void ANCS::AnimationSet::Enumerate(athena::io::IStreamWriter& writer) -{ - atUint16 sectionCount; - if (animResources.size()) - sectionCount = 4; - else if (halfTransitions.size()) - sectionCount = 3; - else if (additiveAnims.size()) - sectionCount = 2; - else - sectionCount = 1; - - writer.writeUint16Big(sectionCount); - - writer.writeUint32Big(animations.size()); - writer.enumerate(animations); - - writer.writeUint32Big(transitions.size()); - writer.enumerate(transitions); - defaultTransition.write(writer); - - if (sectionCount > 1) - { - writer.writeUint32Big(additiveAnims.size()); - writer.enumerate(additiveAnims); - writer.writeFloatBig(floatA); - writer.writeFloatBig(floatB); - } - - if (sectionCount > 2) - { - writer.writeUint32Big(halfTransitions.size()); - writer.enumerate(halfTransitions); - } - - if (sectionCount > 3) - { - writer.writeUint32Big(animResources.size()); - writer.enumerate(animResources); - } -} - -template <> -void ANCS::AnimationSet::Enumerate(size_t& __isz) -{ - atUint16 sectionCount; - if (animResources.size()) - sectionCount = 4; - else if (halfTransitions.size()) - sectionCount = 3; - else if (additiveAnims.size()) - sectionCount = 2; - else - sectionCount = 1; - - __isz += 6; - for (const Animation& a : animations) - a.binarySize(__isz); - - __isz += 4; - for (const Transition& t : transitions) - t.binarySize(__isz); - defaultTransition.binarySize(__isz); - - if (sectionCount > 1) - { - __isz += 4; - for (const AdditiveAnimationInfo& aa : additiveAnims) - aa.binarySize(__isz); - __isz += 8; - } - - if (sectionCount > 2) - { - __isz += 4; - for (const HalfTransition& ht : halfTransitions) - ht.binarySize(__isz); - } - - if (sectionCount > 3) - { - __isz += 4; - for (const AnimationResources& ar : animResources) - ar.binarySize(__isz); - } -} - -template <> -void ANCS::AnimationSet::Enumerate(athena::io::YAMLDocReader& reader) -{ - atUint16 sectionCount = reader.readUint16("sectionCount"); - - reader.enumerate("animations", animations); - - reader.enumerate("transitions", transitions); - reader.enumerate("defaultTransition", defaultTransition); - - additiveAnims.clear(); - if (sectionCount > 1) - { - reader.enumerate("additiveAnims", additiveAnims); - floatA = reader.readFloat("floatA"); - floatB = reader.readFloat("floatB"); - } - - halfTransitions.clear(); - if (sectionCount > 2) - { - reader.enumerate("halfTransitions", halfTransitions); - } - - animResources.clear(); - if (sectionCount > 3) - { - reader.enumerate("animResources", animResources); - } -} - -template <> -void ANCS::AnimationSet::Enumerate(athena::io::YAMLDocWriter& writer) -{ - atUint16 sectionCount; - if (animResources.size()) - sectionCount = 4; - else if (halfTransitions.size()) - sectionCount = 3; - else if (additiveAnims.size()) - sectionCount = 2; - else - sectionCount = 1; - - writer.writeUint16("sectionCount", sectionCount); - - writer.enumerate("animations", animations); - - writer.enumerate("transitions", transitions); - writer.enumerate("defaultTransition", defaultTransition); - - if (sectionCount > 1) - { - writer.enumerate("additiveAnims", additiveAnims); - writer.writeFloat("floatA", floatA); - writer.writeFloat("floatB", floatB); - } - - if (sectionCount > 2) - { - writer.enumerate("halfTransitions", halfTransitions); - } - - if (sectionCount > 3) - { - writer.enumerate("animResources", animResources); - } -} - -void ANCS::AnimationSet::MetaAnimPrimitive:: -gatherPrimitives(PAKRouter* pakRouter, - std::map>& out) -{ - if (!pakRouter) - { - out[animIdx] = {animName, animId, UniqueID32(), false}; - return; - } - - const nod::Node* node; - const PAK::Entry* entry = pakRouter->lookupEntry(animId, &node, true); - if (!entry) - { - out[animIdx] = {animName, animId, UniqueID32(), false}; - return; - } - - PAKEntryReadStream rs = entry->beginReadStream(*node); - out[animIdx] = {animName, animId, ANIM::GetEVNTId(rs), false}; -} - -const char* ANCS::AnimationSet::DNAType() -{ - return "urde::DNAMP1::ANCS::AnimationSet"; -} - -bool ANCS::Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) -{ - hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true); - hecl::ProjectPath::Type yamlType = yamlPath.getPathType(); - hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true); - hecl::ProjectPath::Type blendType = blendPath.getPathType(); - - ANCS ancs; - ancs.read(rs); - - if (force || - yamlType == hecl::ProjectPath::Type::None || - blendType == hecl::ProjectPath::Type::None) - { - if (force || yamlType == hecl::ProjectPath::Type::None) - { - athena::io::FileWriter writer(yamlPath.getAbsolutePath()); - athena::io::ToYAMLStream(ancs, writer); + int subtypeIdx = 0; + ch.animAABBs.clear(); + for (const DNAANCS::Actor::Subtype& sub : actor.subtypes) { + if (!sub.name.compare(ch.name)) { + /* Add subtype AABBs */ + ch.animAABBs.reserve(actor.actions.size()); + for (const DNAANCS::Action& act : actor.actions) { + const auto& sourceAABB = act.subtypeAABBs[subtypeIdx]; + ch.animAABBs.emplace_back(); + auto& destAABB = ch.animAABBs.back(); + destAABB.name = act.name; + destAABB.aabb[0] = sourceAABB.first.val; + destAABB.aabb[1] = sourceAABB.second.val; } - if (force || blendType == hecl::ProjectPath::Type::None) - { - hecl::blender::Connection& conn = btok.getBlenderConnection(); - DNAANCS::ReadANCSToBlender, ANCS, MaterialSet, DNACMDL::SurfaceHeader_1, 2> - (conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force); + if (sub.armature >= 0) { + const DNAANCS::Armature& arm = actor.armatures[sub.armature]; + hecl::SystemStringConv armSysName(arm.name); + ch.cinf = inPath.ensureAuxInfo(hecl::SystemString(armSysName.sys_str()) + _SYS_STR(".CINF")); + ch.cmdl = sub.mesh; + auto search = std::find_if(sub.overlayMeshes.cbegin(), sub.overlayMeshes.cend(), + [](const auto& p) { return p.first == "ICE"; }); + if (search != sub.overlayMeshes.cend()) { + hecl::SystemStringConv overlaySys(search->first); + ch.cmdlIce = search->second; + ch.cskrIce = inPath.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _SYS_STR('.') + + overlaySys.c_str() + _SYS_STR(".CSKR")); + } } + + break; + } + ++subtypeIdx; } + std::sort(ch.animAABBs.begin(), ch.animAABBs.end(), + [](const ANCS::CharacterSet::CharacterInfo::ActionAABB& a, + const ANCS::CharacterSet::CharacterInfo::ActionAABB& b) { return a.name < b.name; }); + } + + /* Set Animation Resource IDs */ + ancs.enumeratePrimitives([&](AnimationSet::MetaAnimPrimitive& prim) -> bool { + hecl::SystemStringConv sysStr(prim.animName); + hecl::ProjectPath pathOut = inPath.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".ANIM")); + prim.animId = pathOut; return true; -} + }); -bool ANCS::Cook(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor) -{ - /* Search for yaml */ - hecl::ProjectPath yamlPath = inPath.getWithExtension(_SYS_STR(".yaml"), true); - if (!yamlPath.isFile()) - Log.report(logvisor::Fatal, _SYS_STR("'%s' not found as file"), - yamlPath.getRelativePath().data()); + /* Gather ANIM resources */ + ancs.animationSet.animResources.reserve(actor.actions.size()); + for (const DNAANCS::Action& act : actor.actions) { + hecl::SystemStringConv sysStr(act.name); + hecl::ProjectPath pathOut = inPath.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".ANIM")); - athena::io::FileReader reader(yamlPath.getAbsolutePath()); - if (!reader.isOpen()) - Log.report(logvisor::Fatal, _SYS_STR("can't open '%s' for reading"), - yamlPath.getRelativePath().data()); - - if (!athena::io::ValidateFromYAMLStream(reader)) - { - Log.report(logvisor::Fatal, _SYS_STR("'%s' is not urde::DNAMP1::ANCS type"), - yamlPath.getRelativePath().data()); - } - - athena::io::YAMLDocReader yamlReader; - if (!yamlReader.parse(&reader)) - { - Log.report(logvisor::Fatal, _SYS_STR("unable to parse '%s'"), - yamlPath.getRelativePath().data()); - } - ANCS ancs; - ancs.read(yamlReader); - - /* Set Character Resource IDs */ - for (ANCS::CharacterSet::CharacterInfo& ch : ancs.characterSet.characters) - { - ch.cmdl = UniqueID32{}; - ch.cskr = UniqueID32{}; - ch.cinf = UniqueID32{}; - ch.cmdlIce = UniqueID32Zero{}; - ch.cskrIce = UniqueID32Zero{}; - - hecl::SystemStringConv chSysName(ch.name); - ch.cskr = inPath.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _SYS_STR(".CSKR")); - - int subtypeIdx = 0; - ch.animAABBs.clear(); - for (const DNAANCS::Actor::Subtype& sub : actor.subtypes) - { - if (!sub.name.compare(ch.name)) - { - /* Add subtype AABBs */ - ch.animAABBs.reserve(actor.actions.size()); - for (const DNAANCS::Action& act : actor.actions) - { - const auto& sourceAABB = act.subtypeAABBs[subtypeIdx]; - ch.animAABBs.emplace_back(); - auto& destAABB = ch.animAABBs.back(); - destAABB.name = act.name; - destAABB.aabb[0] = sourceAABB.first.val; - destAABB.aabb[1] = sourceAABB.second.val; - } - - if (sub.armature >= 0) - { - const DNAANCS::Armature& arm = actor.armatures[sub.armature]; - hecl::SystemStringConv armSysName(arm.name); - ch.cinf = inPath.ensureAuxInfo(hecl::SystemString(armSysName.sys_str()) + _SYS_STR(".CINF")); - ch.cmdl = sub.mesh; - auto search = std::find_if(sub.overlayMeshes.cbegin(), sub.overlayMeshes.cend(), - [](const auto& p) { return p.first == "ICE"; }); - if (search != sub.overlayMeshes.cend()) - { - hecl::SystemStringConv overlaySys(search->first); - ch.cmdlIce = search->second; - ch.cskrIce = inPath.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _SYS_STR('.') + - overlaySys.c_str() + _SYS_STR(".CSKR")); - } - } - - break; - } - ++subtypeIdx; - } - - std::sort(ch.animAABBs.begin(), ch.animAABBs.end(), - [](const ANCS::CharacterSet::CharacterInfo::ActionAABB& a, - const ANCS::CharacterSet::CharacterInfo::ActionAABB& b) - { return a.name < b.name; }); - } - - /* Set Animation Resource IDs */ - ancs.enumeratePrimitives([&](AnimationSet::MetaAnimPrimitive& prim) -> bool - { - hecl::SystemStringConv sysStr(prim.animName); - hecl::ProjectPath pathOut = inPath.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".ANIM")); - prim.animId = pathOut; - return true; - }); - - /* Gather ANIM resources */ - ancs.animationSet.animResources.reserve(actor.actions.size()); - for (const DNAANCS::Action& act : actor.actions) - { - hecl::SystemStringConv sysStr(act.name); - hecl::ProjectPath pathOut = inPath.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".ANIM")); - - ancs.animationSet.animResources.emplace_back(); - ancs.animationSet.animResources.back().animId = pathOut; - - /* Check for associated EVNT YAML */ - hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_SYS_STR(".")) + - sysStr.c_str() + - _SYS_STR(".evnt.yaml")).c_str(), true); - evntYamlPath = evntYamlPath.ensureAuxInfo(_SYS_STR("")); - if (evntYamlPath.isFile()) - ancs.animationSet.animResources.back().evntId = evntYamlPath; - } - - /* Write out ANCS */ - athena::io::TransactionalFileWriter w(outPath.getAbsolutePath()); - ancs.write(w); - - return true; -} - -bool ANCS::CookCINF(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor) -{ - hecl::SystemString armName(inPath.getAuxInfo().begin(), - inPath.getAuxInfo().end() - 5); - - for (const DNAANCS::Armature& arm : actor.armatures) - { - hecl::SystemStringConv sysStr(arm.name); - if (sysStr.sys_str() == armName) - { - std::unordered_map boneIdMap; - CINF cinf(arm, boneIdMap); - - /* Write out CINF resource */ - athena::io::TransactionalFileWriter w(outPath.getAbsolutePath()); - cinf.write(w); - return true; - } - } - - return false; -} - -bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor, - const std::function& modelCookFunc) -{ - hecl::SystemString subName(inPath.getAuxInfo().begin(), - inPath.getAuxInfo().end() - 5); - hecl::SystemString overName; - auto dotPos = subName.rfind(_SYS_STR('.')); - if (dotPos != hecl::SystemString::npos) - { - overName = hecl::SystemString(subName.begin() + dotPos + 1, subName.end()); - subName = hecl::SystemString(subName.begin(), subName.begin() + dotPos); - } - hecl::SystemUTF8Conv subNameView(subName); - hecl::SystemUTF8Conv overNameView(overName); - - /* Build bone ID map */ - std::unordered_map boneIdMap; - for (const DNAANCS::Armature& arm : actor.armatures) - { - CINF cinf(arm, boneIdMap); - } - - const DNAANCS::Actor::Subtype* subtype = nullptr; - if (subName != _SYS_STR("ATTACH")) - { - for (const DNAANCS::Actor::Subtype& sub : actor.subtypes) - { - if (!sub.name.compare(subNameView.str())) - { - subtype = ⊂ - break; - } - } - if (!subtype) - Log.report(logvisor::Fatal, _SYS_STR("unable to find subtype '%s'"), subName.c_str()); - } - - const hecl::ProjectPath* modelPath = nullptr; - if (subName == _SYS_STR("ATTACH")) - { - const DNAANCS::Actor::Attachment* attachment = nullptr; - for (const DNAANCS::Actor::Attachment& att : actor.attachments) - { - if (!att.name.compare(overNameView.str())) - { - attachment = &att; - break; - } - } - if (!attachment) - Log.report(logvisor::Fatal, _SYS_STR("unable to find attachment '%s'"), overName.c_str()); - modelPath = &attachment->mesh; - } - else if (overName.empty()) - { - modelPath = &subtype->mesh; - } - else - { - for (const auto& overlay : subtype->overlayMeshes) - if (!overlay.first.compare(overNameView.str())) - { - modelPath = &overlay.second; - break; - } - } - if (!modelPath) - Log.report(logvisor::Fatal, _SYS_STR("unable to resolve model path of %s:%s"), subName.c_str(), overName.c_str()); - - if (!modelPath->isFile()) - Log.report(logvisor::Fatal, _SYS_STR("unable to resolve '%s'"), modelPath->getRelativePath().data()); - - hecl::ProjectPath skinIntPath = modelPath->getCookedPath(SpecEntMP1).getWithExtension(_SYS_STR(".skinint")); - if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath->getModtime()) - if (!modelCookFunc(*modelPath)) - Log.report(logvisor::Fatal, _SYS_STR("unable to cook '%s'"), modelPath->getRelativePath().data()); - - std::vector>, uint32_t>> skins; - uint32_t posCount = 0; - uint32_t normCount = 0; - athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024*32, false); - if (!skinIO.hasError()) - { - std::vector boneNames; - uint32_t boneNameCount = skinIO.readUint32Big(); - boneNames.reserve(boneNameCount); - for (uint32_t i=0 ; i>, uint32_t>& virtualBone = skins[i]; - uint32_t bindCount = skinIO.readUint32Big(); - virtualBone.first.reserve(bindCount); - for (uint32_t j=0 ; jsecond, weight); - } - virtualBone.second = skinIO.readUint32Big(); - } - - posCount = skinIO.readUint32Big(); - normCount = skinIO.readUint32Big(); - - skinIO.close(); - } - - athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath()); - - skinOut.writeUint32Big(skins.size()); - for (auto& virtuaBone : skins) - { - skinOut.writeUint32Big(virtuaBone.first.size()); - for (auto& bind : virtuaBone.first) - { - skinOut.writeUint32Big(bind.first); - skinOut.writeFloatBig(bind.second); - } - skinOut.writeUint32Big(virtuaBone.second); - } - - skinOut.writeUint32Big(0xffffffff); - skinOut.writeUint32Big(posCount); - skinOut.writeUint32Big(0xffffffff); - skinOut.writeUint32Big(normCount); - - return true; -} - -bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor, - const std::function& modelCookFunc) -{ - hecl::SystemString subName(inPath.getAuxInfo().begin(), - inPath.getAuxInfo().end() - 5); - hecl::SystemString overName; - auto dotPos = subName.rfind(_SYS_STR('.')); - if (dotPos != hecl::SystemString::npos) - { - overName = hecl::SystemString(subName.begin() + dotPos + 1, subName.end()); - subName = hecl::SystemString(subName.begin(), subName.begin() + dotPos); - } - hecl::SystemUTF8Conv subNameView(subName); - hecl::SystemUTF8Conv overNameView(overName); - - /* Build bone ID map */ - std::unordered_map boneIdMap; - for (const DNAANCS::Armature& arm : actor.armatures) - { - CINF cinf(arm, boneIdMap); - } - - const DNAANCS::Actor::Subtype* subtype = nullptr; - if (subName != _SYS_STR("ATTACH")) - { - for (const DNAANCS::Actor::Subtype& sub : actor.subtypes) - { - if (!sub.name.compare(subNameView.str())) - { - subtype = ⊂ - break; - } - } - if (!subtype) - Log.report(logvisor::Fatal, _SYS_STR("unable to find subtype '%s'"), subName.c_str()); - } - - const hecl::ProjectPath* modelPath = nullptr; - if (subName == _SYS_STR("ATTACH")) - { - const DNAANCS::Actor::Attachment* attachment = nullptr; - for (const DNAANCS::Actor::Attachment& att : actor.attachments) - { - if (!att.name.compare(overNameView.str())) - { - attachment = &att; - break; - } - } - if (!attachment) - Log.report(logvisor::Fatal, _SYS_STR("unable to find attachment '%s'"), overName.c_str()); - modelPath = &attachment->mesh; - } - else if (overName.empty()) - { - modelPath = &subtype->mesh; - } - else - { - for (const auto& overlay : subtype->overlayMeshes) - if (!overlay.first.compare(overNameView.str())) - { - modelPath = &overlay.second; - break; - } - } - if (!modelPath) - Log.report(logvisor::Fatal, _SYS_STR("unable to resolve model path of %s:%s"), subName.c_str(), overName.c_str()); - - if (!modelPath->isFile()) - Log.report(logvisor::Fatal, _SYS_STR("unable to resolve '%s'"), modelPath->getRelativePath().data()); - - hecl::ProjectPath skinIntPath = modelPath->getCookedPath(SpecEntMP1PC).getWithExtension(_SYS_STR(".skinint")); - if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath->getModtime()) - if (!modelCookFunc(*modelPath)) - Log.report(logvisor::Fatal, _SYS_STR("unable to cook '%s'"), modelPath->getRelativePath().data()); - - uint32_t bankCount = 0; - std::vector> skinBanks; - std::vector boneNames; - std::vector>> skins; - atUint64 uniquePoolIndexLen = 0; - std::unique_ptr uniquePoolIndexData; - athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024*32, false); - if (!skinIO.hasError()) - { - bankCount = skinIO.readUint32Big(); - skinBanks.reserve(bankCount); - for (uint32_t i=0 ; i& bonesOut = skinBanks.back(); - uint32_t boneCount = skinIO.readUint32Big(); - bonesOut.reserve(boneCount); - for (uint32_t j=0 ; j>& virtualBone = skins[i]; - uint32_t bindCount = skinIO.readUint32Big(); - virtualBone.reserve(bindCount); - for (uint32_t j=0 ; jsecond, weight); - } - } - - uniquePoolIndexLen = skinIO.length() - skinIO.position(); - uniquePoolIndexData = skinIO.readUBytes(uniquePoolIndexLen); - - skinIO.close(); - } - - athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath()); - - skinOut.writeUint32Big(bankCount); - for (const std::vector& bank : skinBanks) - { - skinOut.writeUint32Big(bank.size()); - for (uint32_t bIdx : bank) - { - const std::string& name = boneNames[bIdx]; - auto search = boneIdMap.find(name); - if (search == boneIdMap.cend()) - Log.report(logvisor::Fatal, "unable to find bone '%s' in %s", - name.c_str(), inPath.getRelativePathUTF8().data()); - skinOut.writeUint32Big(search->second); - } - } - - skinOut.writeUint32Big(skins.size()); - for (auto& virtuaBone : skins) - { - skinOut.writeUint32Big(virtuaBone.size()); - for (auto& bind : virtuaBone) - { - skinOut.writeUint32Big(bind.first); - skinOut.writeFloatBig(bind.second); - } - } - - if (uniquePoolIndexLen) - skinOut.writeUBytes(uniquePoolIndexData.get(), uniquePoolIndexLen); - - return true; -} - -bool ANCS::CookANIM(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor, - hecl::blender::DataStream& ds, - bool pc) -{ - hecl::SystemString actName(inPath.getAuxInfo().begin(), - inPath.getAuxInfo().end() - 5); - hecl::SystemUTF8Conv actNameView(actName); - DNAANCS::Action action = ds.compileActionChannelsOnly(actNameView.str()); - - if (!actor.armatures.size()) - Log.report(logvisor::Fatal, _SYS_STR("0 armatures in %s"), - inPath.getRelativePath().data()); - - /* Build bone ID map */ - std::unordered_map boneIdMap; - std::experimental::optional rigCinf; - std::experimental::optional> rigInv; - for (const DNAANCS::Armature& arm : actor.armatures) - { - if (!rigInv) - { - rigCinf.emplace(arm, boneIdMap); - auto matrices = ds.getBoneMatrices(arm.name); - rigInv.emplace(*rigCinf, matrices); - } - else - { - CINF cinf(arm, boneIdMap); - } - } - - ANIM anim(action, boneIdMap, *rigInv, pc); + ancs.animationSet.animResources.emplace_back(); + ancs.animationSet.animResources.back().animId = pathOut; /* Check for associated EVNT YAML */ - hecl::ProjectPath evntYamlPath = inPath.getWithExtension((hecl::SystemString(_SYS_STR(".")) + actName + - _SYS_STR(".evnt.yaml")).c_str(), true); + hecl::ProjectPath evntYamlPath = inPath.getWithExtension( + (hecl::SystemString(_SYS_STR(".")) + sysStr.c_str() + _SYS_STR(".evnt.yaml")).c_str(), true); evntYamlPath = evntYamlPath.ensureAuxInfo(_SYS_STR("")); if (evntYamlPath.isFile()) - anim.m_anim->evnt = evntYamlPath; + ancs.animationSet.animResources.back().evntId = evntYamlPath; + } - /* Write out ANIM resource */ - athena::io::TransactionalFileWriter w(outPath.getAbsolutePath()); - anim.write(w); - return true; + /* Write out ANCS */ + athena::io::TransactionalFileWriter w(outPath.getAbsolutePath()); + ancs.write(w); + + return true; } -} +bool ANCS::CookCINF(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor) { + hecl::SystemString armName(inPath.getAuxInfo().begin(), inPath.getAuxInfo().end() - 5); + + for (const DNAANCS::Armature& arm : actor.armatures) { + hecl::SystemStringConv sysStr(arm.name); + if (sysStr.sys_str() == armName) { + std::unordered_map boneIdMap; + CINF cinf(arm, boneIdMap); + + /* Write out CINF resource */ + athena::io::TransactionalFileWriter w(outPath.getAbsolutePath()); + cinf.write(w); + return true; + } + } + + return false; } +bool ANCS::CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor, + const std::function& modelCookFunc) { + hecl::SystemString subName(inPath.getAuxInfo().begin(), inPath.getAuxInfo().end() - 5); + hecl::SystemString overName; + auto dotPos = subName.rfind(_SYS_STR('.')); + if (dotPos != hecl::SystemString::npos) { + overName = hecl::SystemString(subName.begin() + dotPos + 1, subName.end()); + subName = hecl::SystemString(subName.begin(), subName.begin() + dotPos); + } + hecl::SystemUTF8Conv subNameView(subName); + hecl::SystemUTF8Conv overNameView(overName); + + /* Build bone ID map */ + std::unordered_map boneIdMap; + for (const DNAANCS::Armature& arm : actor.armatures) { + CINF cinf(arm, boneIdMap); + } + + const DNAANCS::Actor::Subtype* subtype = nullptr; + if (subName != _SYS_STR("ATTACH")) { + for (const DNAANCS::Actor::Subtype& sub : actor.subtypes) { + if (!sub.name.compare(subNameView.str())) { + subtype = ⊂ + break; + } + } + if (!subtype) + Log.report(logvisor::Fatal, _SYS_STR("unable to find subtype '%s'"), subName.c_str()); + } + + const hecl::ProjectPath* modelPath = nullptr; + if (subName == _SYS_STR("ATTACH")) { + const DNAANCS::Actor::Attachment* attachment = nullptr; + for (const DNAANCS::Actor::Attachment& att : actor.attachments) { + if (!att.name.compare(overNameView.str())) { + attachment = &att; + break; + } + } + if (!attachment) + Log.report(logvisor::Fatal, _SYS_STR("unable to find attachment '%s'"), overName.c_str()); + modelPath = &attachment->mesh; + } else if (overName.empty()) { + modelPath = &subtype->mesh; + } else { + for (const auto& overlay : subtype->overlayMeshes) + if (!overlay.first.compare(overNameView.str())) { + modelPath = &overlay.second; + break; + } + } + if (!modelPath) + Log.report(logvisor::Fatal, _SYS_STR("unable to resolve model path of %s:%s"), subName.c_str(), overName.c_str()); + + if (!modelPath->isFile()) + Log.report(logvisor::Fatal, _SYS_STR("unable to resolve '%s'"), modelPath->getRelativePath().data()); + + hecl::ProjectPath skinIntPath = modelPath->getCookedPath(SpecEntMP1).getWithExtension(_SYS_STR(".skinint")); + if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath->getModtime()) + if (!modelCookFunc(*modelPath)) + Log.report(logvisor::Fatal, _SYS_STR("unable to cook '%s'"), modelPath->getRelativePath().data()); + + std::vector>, uint32_t>> skins; + uint32_t posCount = 0; + uint32_t normCount = 0; + athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024 * 32, false); + if (!skinIO.hasError()) { + std::vector boneNames; + uint32_t boneNameCount = skinIO.readUint32Big(); + boneNames.reserve(boneNameCount); + for (uint32_t i = 0; i < boneNameCount; ++i) + boneNames.push_back(skinIO.readString()); + + uint32_t skinCount = skinIO.readUint32Big(); + skins.resize(skinCount); + for (uint32_t i = 0; i < skinCount; ++i) { + std::pair>, uint32_t>& virtualBone = skins[i]; + uint32_t bindCount = skinIO.readUint32Big(); + virtualBone.first.reserve(bindCount); + for (uint32_t j = 0; j < bindCount; ++j) { + uint32_t bIdx = skinIO.readUint32Big(); + float weight = skinIO.readFloatBig(); + const std::string& name = boneNames[bIdx]; + auto search = boneIdMap.find(name); + if (search == boneIdMap.cend()) + Log.report(logvisor::Fatal, "unable to find bone '%s' in %s", name.c_str(), + inPath.getRelativePathUTF8().data()); + virtualBone.first.emplace_back(search->second, weight); + } + virtualBone.second = skinIO.readUint32Big(); + } + + posCount = skinIO.readUint32Big(); + normCount = skinIO.readUint32Big(); + + skinIO.close(); + } + + athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath()); + + skinOut.writeUint32Big(skins.size()); + for (auto& virtuaBone : skins) { + skinOut.writeUint32Big(virtuaBone.first.size()); + for (auto& bind : virtuaBone.first) { + skinOut.writeUint32Big(bind.first); + skinOut.writeFloatBig(bind.second); + } + skinOut.writeUint32Big(virtuaBone.second); + } + + skinOut.writeUint32Big(0xffffffff); + skinOut.writeUint32Big(posCount); + skinOut.writeUint32Big(0xffffffff); + skinOut.writeUint32Big(normCount); + + return true; +} + +bool ANCS::CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor, + const std::function& modelCookFunc) { + hecl::SystemString subName(inPath.getAuxInfo().begin(), inPath.getAuxInfo().end() - 5); + hecl::SystemString overName; + auto dotPos = subName.rfind(_SYS_STR('.')); + if (dotPos != hecl::SystemString::npos) { + overName = hecl::SystemString(subName.begin() + dotPos + 1, subName.end()); + subName = hecl::SystemString(subName.begin(), subName.begin() + dotPos); + } + hecl::SystemUTF8Conv subNameView(subName); + hecl::SystemUTF8Conv overNameView(overName); + + /* Build bone ID map */ + std::unordered_map boneIdMap; + for (const DNAANCS::Armature& arm : actor.armatures) { + CINF cinf(arm, boneIdMap); + } + + const DNAANCS::Actor::Subtype* subtype = nullptr; + if (subName != _SYS_STR("ATTACH")) { + for (const DNAANCS::Actor::Subtype& sub : actor.subtypes) { + if (!sub.name.compare(subNameView.str())) { + subtype = ⊂ + break; + } + } + if (!subtype) + Log.report(logvisor::Fatal, _SYS_STR("unable to find subtype '%s'"), subName.c_str()); + } + + const hecl::ProjectPath* modelPath = nullptr; + if (subName == _SYS_STR("ATTACH")) { + const DNAANCS::Actor::Attachment* attachment = nullptr; + for (const DNAANCS::Actor::Attachment& att : actor.attachments) { + if (!att.name.compare(overNameView.str())) { + attachment = &att; + break; + } + } + if (!attachment) + Log.report(logvisor::Fatal, _SYS_STR("unable to find attachment '%s'"), overName.c_str()); + modelPath = &attachment->mesh; + } else if (overName.empty()) { + modelPath = &subtype->mesh; + } else { + for (const auto& overlay : subtype->overlayMeshes) + if (!overlay.first.compare(overNameView.str())) { + modelPath = &overlay.second; + break; + } + } + if (!modelPath) + Log.report(logvisor::Fatal, _SYS_STR("unable to resolve model path of %s:%s"), subName.c_str(), overName.c_str()); + + if (!modelPath->isFile()) + Log.report(logvisor::Fatal, _SYS_STR("unable to resolve '%s'"), modelPath->getRelativePath().data()); + + hecl::ProjectPath skinIntPath = modelPath->getCookedPath(SpecEntMP1PC).getWithExtension(_SYS_STR(".skinint")); + if (!skinIntPath.isFileOrGlob() || skinIntPath.getModtime() < modelPath->getModtime()) + if (!modelCookFunc(*modelPath)) + Log.report(logvisor::Fatal, _SYS_STR("unable to cook '%s'"), modelPath->getRelativePath().data()); + + uint32_t bankCount = 0; + std::vector> skinBanks; + std::vector boneNames; + std::vector>> skins; + atUint64 uniquePoolIndexLen = 0; + std::unique_ptr uniquePoolIndexData; + athena::io::FileReader skinIO(skinIntPath.getAbsolutePath(), 1024 * 32, false); + if (!skinIO.hasError()) { + bankCount = skinIO.readUint32Big(); + skinBanks.reserve(bankCount); + for (uint32_t i = 0; i < bankCount; ++i) { + skinBanks.emplace_back(); + std::vector& bonesOut = skinBanks.back(); + uint32_t boneCount = skinIO.readUint32Big(); + bonesOut.reserve(boneCount); + for (uint32_t j = 0; j < boneCount; ++j) { + uint32_t idx = skinIO.readUint32Big(); + bonesOut.push_back(idx); + } + } + + uint32_t boneNameCount = skinIO.readUint32Big(); + boneNames.reserve(boneNameCount); + for (uint32_t i = 0; i < boneNameCount; ++i) + boneNames.push_back(skinIO.readString()); + + uint32_t skinCount = skinIO.readUint32Big(); + skins.resize(skinCount); + for (uint32_t i = 0; i < skinCount; ++i) { + std::vector>& virtualBone = skins[i]; + uint32_t bindCount = skinIO.readUint32Big(); + virtualBone.reserve(bindCount); + for (uint32_t j = 0; j < bindCount; ++j) { + uint32_t bIdx = skinIO.readUint32Big(); + float weight = skinIO.readFloatBig(); + const std::string& name = boneNames[bIdx]; + auto search = boneIdMap.find(name); + if (search == boneIdMap.cend()) + Log.report(logvisor::Fatal, "unable to find bone '%s' in %s", name.c_str(), + inPath.getRelativePathUTF8().data()); + virtualBone.emplace_back(search->second, weight); + } + } + + uniquePoolIndexLen = skinIO.length() - skinIO.position(); + uniquePoolIndexData = skinIO.readUBytes(uniquePoolIndexLen); + + skinIO.close(); + } + + athena::io::TransactionalFileWriter skinOut(outPath.getAbsolutePath()); + + skinOut.writeUint32Big(bankCount); + for (const std::vector& bank : skinBanks) { + skinOut.writeUint32Big(bank.size()); + for (uint32_t bIdx : bank) { + const std::string& name = boneNames[bIdx]; + auto search = boneIdMap.find(name); + if (search == boneIdMap.cend()) + Log.report(logvisor::Fatal, "unable to find bone '%s' in %s", name.c_str(), + inPath.getRelativePathUTF8().data()); + skinOut.writeUint32Big(search->second); + } + } + + skinOut.writeUint32Big(skins.size()); + for (auto& virtuaBone : skins) { + skinOut.writeUint32Big(virtuaBone.size()); + for (auto& bind : virtuaBone) { + skinOut.writeUint32Big(bind.first); + skinOut.writeFloatBig(bind.second); + } + } + + if (uniquePoolIndexLen) + skinOut.writeUBytes(uniquePoolIndexData.get(), uniquePoolIndexLen); + + return true; +} + +bool ANCS::CookANIM(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor, + hecl::blender::DataStream& ds, bool pc) { + hecl::SystemString actName(inPath.getAuxInfo().begin(), inPath.getAuxInfo().end() - 5); + hecl::SystemUTF8Conv actNameView(actName); + DNAANCS::Action action = ds.compileActionChannelsOnly(actNameView.str()); + + if (!actor.armatures.size()) + Log.report(logvisor::Fatal, _SYS_STR("0 armatures in %s"), inPath.getRelativePath().data()); + + /* Build bone ID map */ + std::unordered_map boneIdMap; + std::experimental::optional rigCinf; + std::experimental::optional> rigInv; + for (const DNAANCS::Armature& arm : actor.armatures) { + if (!rigInv) { + rigCinf.emplace(arm, boneIdMap); + auto matrices = ds.getBoneMatrices(arm.name); + rigInv.emplace(*rigCinf, matrices); + } else { + CINF cinf(arm, boneIdMap); + } + } + + ANIM anim(action, boneIdMap, *rigInv, pc); + + /* Check for associated EVNT YAML */ + hecl::ProjectPath evntYamlPath = + inPath.getWithExtension((hecl::SystemString(_SYS_STR(".")) + actName + _SYS_STR(".evnt.yaml")).c_str(), true); + evntYamlPath = evntYamlPath.ensureAuxInfo(_SYS_STR("")); + if (evntYamlPath.isFile()) + anim.m_anim->evnt = evntYamlPath; + + /* Write out ANIM resource */ + athena::io::TransactionalFileWriter w(outPath.getAbsolutePath()); + anim.write(w); + return true; +} + +} // namespace DNAMP1 +} // namespace DataSpec diff --git a/DataSpec/DNAMP1/ANCS.hpp b/DataSpec/DNAMP1/ANCS.hpp index a838ced63..89c2e7236 100644 --- a/DataSpec/DNAMP1/ANCS.hpp +++ b/DataSpec/DNAMP1/ANCS.hpp @@ -10,510 +10,419 @@ #include "EVNT.hpp" #include "athena/FileReader.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct ANCS : BigDNA -{ - using CINFType = CINF; - using CSKRType = CSKR; - using ANIMType = ANIM; +struct ANCS : BigDNA { + using CINFType = CINF; + using CSKRType = CSKR; + using ANIMType = ANIM; + AT_DECL_DNA_YAML + Value version; + + struct CharacterSet : BigDNA { AT_DECL_DNA_YAML Value version; + Value characterCount; + struct CharacterInfo : BigDNA { + AT_DECL_DNA_YAML + Delete expl; - struct CharacterSet : BigDNA - { + atUint32 idx; + std::string name; + UniqueID32 cmdl; + UniqueID32 cskr; + UniqueID32 cinf; + + struct Animation : BigDNA { AT_DECL_DNA_YAML - Value version; - Value characterCount; - struct CharacterInfo : BigDNA - { - AT_DECL_DNA_YAML - Delete expl; + Value animIdx; + String<-1> strA; + String<-1> strB; + }; + std::vector animations; - atUint32 idx; - std::string name; - UniqueID32 cmdl; - UniqueID32 cskr; - UniqueID32 cinf; - - struct Animation : BigDNA - { - AT_DECL_DNA_YAML - Value animIdx; - String<-1> strA; - String<-1> strB; - }; - std::vector animations; - - struct PASDatabase : BigDNA - { - AT_DECL_DNA_YAML - Value magic; - Value animStateCount; - Value defaultState; - struct AnimState : BigDNA - { - AT_DECL_DNA_YAML - Delete expl; - atUint32 id; - - struct ParmInfo : BigDNA - { - AT_DECL_DNA_YAML - Delete expl; - enum class DataType - { - Int32 = 0, - UInt32 = 1, - Float = 2, - Bool = 3, - Enum = 4 - }; - union Parm - { - atInt32 int32; - atUint32 uint32; - float float32; - bool bool1; - Parm() : int32(0) {} - Parm(atInt32 val) : int32(val) {} - Parm(atUint32 val) : uint32(val) {} - Parm(float val) : float32(val) {} - Parm(bool val) : bool1(val) {} - }; - - atUint32 parmType; - atUint32 weightFunction; - float weight; - Parm range[2]; - }; - std::vector parmInfos; - - struct AnimInfo - { - atUint32 id; - std::vector parmVals; - }; - std::vector animInfos; - }; - Vector animStates; - } pasDatabase; - - struct ParticleResData - { - std::vector part; - std::vector swhc; - std::vector unk; - std::vector elsc; - } partResData; - - atUint32 unk1 = 0; - - struct ActionAABB : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value aabb[2]; - }; - std::vector animAABBs; - - struct Effect : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value compCount; - struct EffectComponent : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - DNAFourCC type; - UniqueID32 id; - String<-1> locator; - Value scale; - Value parentMode; - Value flags; - }; - Vector comps; - }; - std::vector effects; - - UniqueID32Zero cmdlIce; - UniqueID32Zero cskrIce; - - std::vector animIdxs; - }; - Vector characters; - } characterSet; - - struct AnimationSet : BigDNA - { + struct PASDatabase : BigDNA { AT_DECL_DNA_YAML - Delete expl; + Value magic; + Value animStateCount; + Value defaultState; + struct AnimState : BigDNA { + AT_DECL_DNA_YAML + Delete expl; + atUint32 id; - struct MetaAnimPrimitive; - struct IMetaAnim : BigDNAVYaml - { + struct ParmInfo : BigDNA { + AT_DECL_DNA_YAML Delete expl; - enum class Type - { - Primitive = 0, - Blend = 1, - PhaseBlend = 2, - Random = 3, - Sequence = 4 - } m_type; - const char* m_typeStr; - IMetaAnim(Type type, const char* typeStr) - : m_type(type), m_typeStr(typeStr) {} - virtual void gatherPrimitives(PAKRouter* pakRouter, - std::map>& out)=0; - virtual bool enumeratePrimitives(const std::function& func)=0; - }; - struct MetaAnimFactory : BigDNA - { - AT_DECL_EXPLICIT_DNA_YAML - std::unique_ptr m_anim; - }; - struct MetaAnimPrimitive : IMetaAnim - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - MetaAnimPrimitive() : IMetaAnim(Type::Primitive, "Primitive") {} - - UniqueID32 animId; - Value animIdx; - String<-1> animName; - Value unk1; - Value unk2; - - void gatherPrimitives(PAKRouter* pakRouter, - std::map>& out); - - bool enumeratePrimitives(const std::function& func) - { - return func(*this); - } - }; - struct MetaAnimBlend : IMetaAnim - { - MetaAnimBlend() - : IMetaAnim(Type::Blend, "Blend") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - MetaAnimFactory animA; - MetaAnimFactory animB; - Value unkFloat; - Value unk; - - void gatherPrimitives(PAKRouter* pakRouter, - std::map>& out) - { - animA.m_anim->gatherPrimitives(pakRouter, out); - animB.m_anim->gatherPrimitives(pakRouter, out); - } - - bool enumeratePrimitives(const std::function& func) - { - if (!animA.m_anim->enumeratePrimitives(func)) - return false; - if (!animB.m_anim->enumeratePrimitives(func)) - return false; - return true; - } - }; - struct MetaAnimPhaseBlend : IMetaAnim - { - MetaAnimPhaseBlend() - : IMetaAnim(Type::PhaseBlend, "PhaseBlend") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - MetaAnimFactory animA; - MetaAnimFactory animB; - Value unkFloat; - Value unk; - - void gatherPrimitives(PAKRouter* pakRouter, - std::map>& out) - { - animA.m_anim->gatherPrimitives(pakRouter, out); - animB.m_anim->gatherPrimitives(pakRouter, out); - } - - bool enumeratePrimitives(const std::function& func) - { - if (!animA.m_anim->enumeratePrimitives(func)) - return false; - if (!animB.m_anim->enumeratePrimitives(func)) - return false; - return true; - } - }; - struct MetaAnimRandom : IMetaAnim - { - MetaAnimRandom() : IMetaAnim(Type::Random, "Random") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value animCount; - struct Child : BigDNA - { - AT_DECL_DNA - MetaAnimFactory anim; - Value probability; + enum class DataType { Int32 = 0, UInt32 = 1, Float = 2, Bool = 3, Enum = 4 }; + union Parm { + atInt32 int32; + atUint32 uint32; + float float32; + bool bool1; + Parm() : int32(0) {} + Parm(atInt32 val) : int32(val) {} + Parm(atUint32 val) : uint32(val) {} + Parm(float val) : float32(val) {} + Parm(bool val) : bool1(val) {} }; - Vector children; - void gatherPrimitives(PAKRouter* pakRouter, - std::map>& out) - { - for (const auto& child : children) - child.anim.m_anim->gatherPrimitives(pakRouter, out); - } + atUint32 parmType; + atUint32 weightFunction; + float weight; + Parm range[2]; + }; + std::vector parmInfos; - bool enumeratePrimitives(const std::function& func) - { - for (auto& child : children) - if (!child.anim.m_anim->enumeratePrimitives(func)) - return false; - return true; - } + struct AnimInfo { + atUint32 id; + std::vector parmVals; + }; + std::vector animInfos; }; - struct MetaAnimSequence : IMetaAnim - { - MetaAnimSequence() : IMetaAnim(Type::Sequence, "Sequence") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value animCount; - Vector children; + Vector animStates; + } pasDatabase; - void gatherPrimitives(PAKRouter* pakRouter, - std::map>& out) - { - for (const auto& child : children) - child.m_anim->gatherPrimitives(pakRouter, out); - } + struct ParticleResData { + std::vector part; + std::vector swhc; + std::vector unk; + std::vector elsc; + } partResData; - bool enumeratePrimitives(const std::function& func) - { - for (auto& child : children) - if (!child.m_anim->enumeratePrimitives(func)) - return false; - return true; - } + atUint32 unk1 = 0; + + struct ActionAABB : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value aabb[2]; + }; + std::vector animAABBs; + + struct Effect : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value compCount; + struct EffectComponent : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + DNAFourCC type; + UniqueID32 id; + String<-1> locator; + Value scale; + Value parentMode; + Value flags; }; + Vector comps; + }; + std::vector effects; - struct Animation : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - MetaAnimFactory metaAnim; - }; - std::vector animations; + UniqueID32Zero cmdlIce; + UniqueID32Zero cskrIce; - struct IMetaTrans : BigDNAVYaml - { - Delete expl; - enum class Type - { - MetaAnim = 0, - Trans = 1, - PhaseTrans = 2, - NoTrans = 3, - } m_type; - const char* m_typeStr; - IMetaTrans(Type type, const char* typeStr) - : m_type(type), m_typeStr(typeStr) {} - virtual void gatherPrimitives(PAKRouter* pakRouter, - std::map>& out) {} - virtual bool enumeratePrimitives(const std::function& func) {return true;} - }; - struct MetaTransFactory : BigDNA - { - AT_DECL_DNA_YAML - Delete expl; - std::unique_ptr m_trans; - }; - struct MetaTransMetaAnim : IMetaTrans - { - MetaTransMetaAnim() - : IMetaTrans(Type::MetaAnim, "MetaAnim") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - MetaAnimFactory anim; + std::vector animIdxs; + }; + Vector characters; + } characterSet; - void gatherPrimitives(PAKRouter* pakRouter, - std::map>& out) - { - anim.m_anim->gatherPrimitives(pakRouter, out); - } + struct AnimationSet : BigDNA { + AT_DECL_DNA_YAML + Delete expl; - bool enumeratePrimitives(const std::function& func) - { - return anim.m_anim->enumeratePrimitives(func); - } - }; - struct MetaTransTrans : IMetaTrans - { - MetaTransTrans() - : IMetaTrans(Type::Trans, "Trans") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value transDurTime; - Value transDurTimeMode; - Value unk2; - Value runA; - Value flags; - }; - struct MetaTransPhaseTrans : IMetaTrans - { - MetaTransPhaseTrans() - : IMetaTrans(Type::PhaseTrans, "PhaseTrans") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value transDurTime; - Value transDurTimeMode; - Value unk2; - Value runA; - Value flags; - }; + struct MetaAnimPrimitive; + struct IMetaAnim : BigDNAVYaml { + Delete expl; + enum class Type { Primitive = 0, Blend = 1, PhaseBlend = 2, Random = 3, Sequence = 4 } m_type; + const char* m_typeStr; + IMetaAnim(Type type, const char* typeStr) : m_type(type), m_typeStr(typeStr) {} + virtual void gatherPrimitives(PAKRouter* pakRouter, + std::map>& out) = 0; + virtual bool enumeratePrimitives(const std::function& func) = 0; + }; + struct MetaAnimFactory : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + std::unique_ptr m_anim; + }; + struct MetaAnimPrimitive : IMetaAnim { + AT_DECL_DNA_YAML + AT_DECL_DNAV + MetaAnimPrimitive() : IMetaAnim(Type::Primitive, "Primitive") {} - struct Transition : BigDNA - { - AT_DECL_DNA_YAML - Value unk; - Value animIdxA; - Value animIdxB; - MetaTransFactory metaTrans; - }; - std::vector transitions; - MetaTransFactory defaultTransition; + UniqueID32 animId; + Value animIdx; + String<-1> animName; + Value unk1; + Value unk2; - struct AdditiveAnimationInfo : BigDNA - { - AT_DECL_DNA_YAML - Value animIdx; - Value unk1; - Value unk2; - }; - std::vector additiveAnims; + void gatherPrimitives(PAKRouter* pakRouter, + std::map>& out); - float floatA = 0.0; - float floatB = 0.0; + bool enumeratePrimitives(const std::function& func) { return func(*this); } + }; + struct MetaAnimBlend : IMetaAnim { + MetaAnimBlend() : IMetaAnim(Type::Blend, "Blend") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + MetaAnimFactory animA; + MetaAnimFactory animB; + Value unkFloat; + Value unk; - struct HalfTransition : BigDNA - { - AT_DECL_DNA_YAML - Value animIdx; - MetaTransFactory metaTrans; - }; - std::vector halfTransitions; + void gatherPrimitives(PAKRouter* pakRouter, + std::map>& out) { + animA.m_anim->gatherPrimitives(pakRouter, out); + animB.m_anim->gatherPrimitives(pakRouter, out); + } - struct AnimationResources : BigDNA - { - AT_DECL_DNA_YAML - UniqueID32 animId; - UniqueID32 evntId; - }; - std::vector animResources; - } animationSet; + bool enumeratePrimitives(const std::function& func) { + if (!animA.m_anim->enumeratePrimitives(func)) + return false; + if (!animB.m_anim->enumeratePrimitives(func)) + return false; + return true; + } + }; + struct MetaAnimPhaseBlend : IMetaAnim { + MetaAnimPhaseBlend() : IMetaAnim(Type::PhaseBlend, "PhaseBlend") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + MetaAnimFactory animA; + MetaAnimFactory animB; + Value unkFloat; + Value unk; - void getCharacterResInfo(std::vector>& out) const - { - out.clear(); - out.reserve(characterSet.characters.size()); - for (const CharacterSet::CharacterInfo& ci : characterSet.characters) - { - out.emplace_back(); - DNAANCS::CharacterResInfo& chOut = out.back(); - chOut.name = ci.name; - chOut.cmdl = ci.cmdl; - chOut.cskr = ci.cskr; - chOut.cinf = ci.cinf; + void gatherPrimitives(PAKRouter* pakRouter, + std::map>& out) { + animA.m_anim->gatherPrimitives(pakRouter, out); + animB.m_anim->gatherPrimitives(pakRouter, out); + } - if (ci.cmdlIce) - chOut.overlays.emplace_back("ICE", std::make_pair(ci.cmdlIce, ci.cskrIce)); - } + bool enumeratePrimitives(const std::function& func) { + if (!animA.m_anim->enumeratePrimitives(func)) + return false; + if (!animB.m_anim->enumeratePrimitives(func)) + return false; + return true; + } + }; + struct MetaAnimRandom : IMetaAnim { + MetaAnimRandom() : IMetaAnim(Type::Random, "Random") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value animCount; + struct Child : BigDNA { + AT_DECL_DNA + MetaAnimFactory anim; + Value probability; + }; + Vector children; + + void gatherPrimitives(PAKRouter* pakRouter, + std::map>& out) { + for (const auto& child : children) + child.anim.m_anim->gatherPrimitives(pakRouter, out); + } + + bool enumeratePrimitives(const std::function& func) { + for (auto& child : children) + if (!child.anim.m_anim->enumeratePrimitives(func)) + return false; + return true; + } + }; + struct MetaAnimSequence : IMetaAnim { + MetaAnimSequence() : IMetaAnim(Type::Sequence, "Sequence") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value animCount; + Vector children; + + void gatherPrimitives(PAKRouter* pakRouter, + std::map>& out) { + for (const auto& child : children) + child.m_anim->gatherPrimitives(pakRouter, out); + } + + bool enumeratePrimitives(const std::function& func) { + for (auto& child : children) + if (!child.m_anim->enumeratePrimitives(func)) + return false; + return true; + } + }; + + struct Animation : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + MetaAnimFactory metaAnim; + }; + std::vector animations; + + struct IMetaTrans : BigDNAVYaml { + Delete expl; + enum class Type { + MetaAnim = 0, + Trans = 1, + PhaseTrans = 2, + NoTrans = 3, + } m_type; + const char* m_typeStr; + IMetaTrans(Type type, const char* typeStr) : m_type(type), m_typeStr(typeStr) {} + virtual void gatherPrimitives(PAKRouter* pakRouter, + std::map>& out) {} + virtual bool enumeratePrimitives(const std::function& func) { return true; } + }; + struct MetaTransFactory : BigDNA { + AT_DECL_DNA_YAML + Delete expl; + std::unique_ptr m_trans; + }; + struct MetaTransMetaAnim : IMetaTrans { + MetaTransMetaAnim() : IMetaTrans(Type::MetaAnim, "MetaAnim") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + MetaAnimFactory anim; + + void gatherPrimitives(PAKRouter* pakRouter, + std::map>& out) { + anim.m_anim->gatherPrimitives(pakRouter, out); + } + + bool enumeratePrimitives(const std::function& func) { + return anim.m_anim->enumeratePrimitives(func); + } + }; + struct MetaTransTrans : IMetaTrans { + MetaTransTrans() : IMetaTrans(Type::Trans, "Trans") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value transDurTime; + Value transDurTimeMode; + Value unk2; + Value runA; + Value flags; + }; + struct MetaTransPhaseTrans : IMetaTrans { + MetaTransPhaseTrans() : IMetaTrans(Type::PhaseTrans, "PhaseTrans") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value transDurTime; + Value transDurTimeMode; + Value unk2; + Value runA; + Value flags; + }; + + struct Transition : BigDNA { + AT_DECL_DNA_YAML + Value unk; + Value animIdxA; + Value animIdxB; + MetaTransFactory metaTrans; + }; + std::vector transitions; + MetaTransFactory defaultTransition; + + struct AdditiveAnimationInfo : BigDNA { + AT_DECL_DNA_YAML + Value animIdx; + Value unk1; + Value unk2; + }; + std::vector additiveAnims; + + float floatA = 0.0; + float floatB = 0.0; + + struct HalfTransition : BigDNA { + AT_DECL_DNA_YAML + Value animIdx; + MetaTransFactory metaTrans; + }; + std::vector halfTransitions; + + struct AnimationResources : BigDNA { + AT_DECL_DNA_YAML + UniqueID32 animId; + UniqueID32 evntId; + }; + std::vector animResources; + } animationSet; + + void getCharacterResInfo(std::vector>& out) const { + out.clear(); + out.reserve(characterSet.characters.size()); + for (const CharacterSet::CharacterInfo& ci : characterSet.characters) { + out.emplace_back(); + DNAANCS::CharacterResInfo& chOut = out.back(); + chOut.name = ci.name; + chOut.cmdl = ci.cmdl; + chOut.cskr = ci.cskr; + chOut.cinf = ci.cinf; + + if (ci.cmdlIce) + chOut.overlays.emplace_back("ICE", std::make_pair(ci.cmdlIce, ci.cskrIce)); } + } - void getAnimationResInfo(PAKRouter* pakRouter, - std::map>& out) const - { - out.clear(); - for (const AnimationSet::Animation& ai : animationSet.animations) - if (AnimationSet::IMetaAnim* anim = ai.metaAnim.m_anim.get()) - anim->gatherPrimitives(pakRouter, out); - for (const AnimationSet::Transition& ti : animationSet.transitions) - if (AnimationSet::IMetaTrans* trans = ti.metaTrans.m_trans.get()) - trans->gatherPrimitives(pakRouter, out); - if (AnimationSet::IMetaTrans* trans = animationSet.defaultTransition.m_trans.get()) - trans->gatherPrimitives(pakRouter, out); - } + void getAnimationResInfo(PAKRouter* pakRouter, + std::map>& out) const { + out.clear(); + for (const AnimationSet::Animation& ai : animationSet.animations) + if (AnimationSet::IMetaAnim* anim = ai.metaAnim.m_anim.get()) + anim->gatherPrimitives(pakRouter, out); + for (const AnimationSet::Transition& ti : animationSet.transitions) + if (AnimationSet::IMetaTrans* trans = ti.metaTrans.m_trans.get()) + trans->gatherPrimitives(pakRouter, out); + if (AnimationSet::IMetaTrans* trans = animationSet.defaultTransition.m_trans.get()) + trans->gatherPrimitives(pakRouter, out); + } - void enumeratePrimitives(const std::function& func) - { - for (const AnimationSet::Animation& ai : animationSet.animations) - if (AnimationSet::IMetaAnim* anim = ai.metaAnim.m_anim.get()) - anim->enumeratePrimitives(func); - for (const AnimationSet::Transition& ti : animationSet.transitions) - if (AnimationSet::IMetaTrans* trans = ti.metaTrans.m_trans.get()) - trans->enumeratePrimitives(func); - if (AnimationSet::IMetaTrans* trans = animationSet.defaultTransition.m_trans.get()) - trans->enumeratePrimitives(func); - } + void enumeratePrimitives(const std::function& func) { + for (const AnimationSet::Animation& ai : animationSet.animations) + if (AnimationSet::IMetaAnim* anim = ai.metaAnim.m_anim.get()) + anim->enumeratePrimitives(func); + for (const AnimationSet::Transition& ti : animationSet.transitions) + if (AnimationSet::IMetaTrans* trans = ti.metaTrans.m_trans.get()) + trans->enumeratePrimitives(func); + if (AnimationSet::IMetaTrans* trans = animationSet.defaultTransition.m_trans.get()) + trans->enumeratePrimitives(func); + } - void gatherDependencies(std::vector& pathsOut, int charIdx) const - { - auto doCi = [&](const CharacterSet::CharacterInfo& ci) - { - for (const auto& id : ci.partResData.part) - g_curSpec->flattenDependencies(id, pathsOut); - for (const auto& id : ci.partResData.swhc) - g_curSpec->flattenDependencies(id, pathsOut); - for (const auto& id : ci.partResData.unk) - g_curSpec->flattenDependencies(id, pathsOut); - for (const auto& id : ci.partResData.elsc) - g_curSpec->flattenDependencies(id, pathsOut); - }; - if (charIdx < 0) - for (const CharacterSet::CharacterInfo& ci : characterSet.characters) - doCi(ci); - else if (charIdx < characterSet.characters.size()) - doCi(characterSet.characters[charIdx]); - } + void gatherDependencies(std::vector& pathsOut, int charIdx) const { + auto doCi = [&](const CharacterSet::CharacterInfo& ci) { + for (const auto& id : ci.partResData.part) + g_curSpec->flattenDependencies(id, pathsOut); + for (const auto& id : ci.partResData.swhc) + g_curSpec->flattenDependencies(id, pathsOut); + for (const auto& id : ci.partResData.unk) + g_curSpec->flattenDependencies(id, pathsOut); + for (const auto& id : ci.partResData.elsc) + g_curSpec->flattenDependencies(id, pathsOut); + }; + if (charIdx < 0) + for (const CharacterSet::CharacterInfo& ci : characterSet.characters) + doCi(ci); + else if (charIdx < characterSet.characters.size()) + doCi(characterSet.characters[charIdx]); + } - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged); + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged); - static bool Cook(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor); + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor); - static bool CookCINF(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor); + static bool CookCINF(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor); - static bool CookCSKR(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor, + static bool CookCSKR(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor, + const std::function& modelCookFunc); + static bool CookCSKRPC(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor, const std::function& modelCookFunc); - static bool CookCSKRPC(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor, - const std::function& modelCookFunc); - static bool CookANIM(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNAANCS::Actor& actor, - hecl::blender::DataStream& ds, - bool pc); + static bool CookANIM(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNAANCS::Actor& actor, + hecl::blender::DataStream& ds, bool pc); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ANIM.cpp b/DataSpec/DNAMP1/ANIM.cpp index 393b8082c..28a66f509 100644 --- a/DataSpec/DNAMP1/ANIM.cpp +++ b/DataSpec/DNAMP1/ANIM.cpp @@ -2,684 +2,618 @@ #include "zeus/CVector3f.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { using ANIMOutStream = hecl::blender::ANIMOutStream; -void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig) const -{ - os.format("act.hecl_fps = round(%f)\n" - "act.hecl_looping = %s\n", - (1.0f / mainInterval), looping ? "True" : "False"); +void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig) const { + os.format( + "act.hecl_fps = round(%f)\n" + "act.hecl_looping = %s\n", + (1.0f / mainInterval), looping ? "True" : "False"); - auto kit = chanKeys.begin(); + auto kit = chanKeys.begin(); - std::vector fixedRotKeys; - std::vector fixedTransKeys; + std::vector fixedRotKeys; + std::vector fixedTransKeys; + + for (const std::pair& bone : bones) { + const std::string* bName = rig.getCINF().getBoneNameFromId(bone.first); + if (!bName) + continue; + + os.format("bone_string = '%s'\n", bName->c_str()); + os << "action_group = act.groups.new(bone_string)\n" + "\n" + "rotCurves = []\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, " + "action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, " + "action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, " + "action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, " + "action_group=bone_string))\n" + "\n"; + + if (bone.second) + os << "transCurves = []\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, " + "action_group=bone_string))\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, " + "action_group=bone_string))\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, " + "action_group=bone_string))\n" + "\n"; + + ANIMOutStream ao = os.beginANIMCurve(); - for (const std::pair& bone : bones) { - const std::string* bName = rig.getCINF().getBoneNameFromId(bone.first); - if (!bName) - continue; + const std::vector& rotKeys = *kit++; + fixedRotKeys.clear(); + fixedRotKeys.resize(rotKeys.size()); - os.format("bone_string = '%s'\n", bName->c_str()); - os << "action_group = act.groups.new(bone_string)\n" - "\n" - "rotCurves = []\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string))\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string))\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string))\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string))\n" - "\n"; + for (int c = 0; c < 4; ++c) { + size_t idx = 0; + for (const DNAANIM::Value& val : rotKeys) + fixedRotKeys[idx++][c] = val.simd[c]; + } - if (bone.second) - os << "transCurves = []\n" - "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string))\n" - "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string))\n" - "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n" - "\n"; + for (zeus::CQuaternion& rot : fixedRotKeys) + rot = rig.invertRotation(bone.first, rot); - ANIMOutStream ao = os.beginANIMCurve(); - - { - const std::vector& rotKeys = *kit++; - fixedRotKeys.clear(); - fixedRotKeys.resize(rotKeys.size()); - - for (int c=0 ; c<4 ; ++c) - { - size_t idx = 0; - for (const DNAANIM::Value& val : rotKeys) - fixedRotKeys[idx++][c] = val.simd[c]; - } - - for (zeus::CQuaternion& rot : fixedRotKeys) - rot = rig.invertRotation(bone.first, rot); - - for (int c=0 ; c<4 ; ++c) - { - auto frameit = frames.begin(); - ao.changeCurve(ANIMOutStream::CurveType::Rotate, c, rotKeys.size()); - for (const zeus::CQuaternion& val : fixedRotKeys) - ao.write(*frameit++, val[c]); - } - } - - if (bone.second) - { - const std::vector& transKeys = *kit++; - fixedTransKeys.clear(); - fixedTransKeys.resize(transKeys.size()); - - for (int c=0 ; c<3 ; ++c) - { - size_t idx = 0; - for (const DNAANIM::Value& val : transKeys) - fixedTransKeys[idx++][c] = val.simd[c]; - } - - for (zeus::CVector3f& t : fixedTransKeys) - t = rig.invertPosition(bone.first, t, true); - - for (int c=0 ; c<3 ; ++c) - { - auto frameit = frames.begin(); - ao.changeCurve(ANIMOutStream::CurveType::Translate, c, fixedTransKeys.size()); - for (const zeus::CVector3f& val : fixedTransKeys) - ao.write(*frameit++, val[c]); - } - } + for (int c = 0; c < 4; ++c) { + auto frameit = frames.begin(); + ao.changeCurve(ANIMOutStream::CurveType::Rotate, c, rotKeys.size()); + for (const zeus::CQuaternion& val : fixedRotKeys) + ao.write(*frameit++, val[c]); + } } + + if (bone.second) { + const std::vector& transKeys = *kit++; + fixedTransKeys.clear(); + fixedTransKeys.resize(transKeys.size()); + + for (int c = 0; c < 3; ++c) { + size_t idx = 0; + for (const DNAANIM::Value& val : transKeys) + fixedTransKeys[idx++][c] = val.simd[c]; + } + + for (zeus::CVector3f& t : fixedTransKeys) + t = rig.invertPosition(bone.first, t, true); + + for (int c = 0; c < 3; ++c) { + auto frameit = frames.begin(); + ao.changeCurve(ANIMOutStream::CurveType::Translate, c, fixedTransKeys.size()); + for (const zeus::CVector3f& val : fixedTransKeys) + ao.write(*frameit++, val[c]); + } + } + } } -UniqueID32 ANIM::GetEVNTId(athena::io::IStreamReader& reader) -{ - atUint32 version = reader.readUint32Big(); - switch (version) - { - case 0: - { - ANIM0 anim0; - anim0.read(reader); - return anim0.evnt; - } - case 2: - case 3: - reader.seek(4); - return reader.readUint32Big(); - default: - Log.report(logvisor::Error, "unrecognized ANIM version"); - break; - } - return {}; +UniqueID32 ANIM::GetEVNTId(athena::io::IStreamReader& reader) { + atUint32 version = reader.readUint32Big(); + switch (version) { + case 0: { + ANIM0 anim0; + anim0.read(reader); + return anim0.evnt; + } + case 2: + case 3: + reader.seek(4); + return reader.readUint32Big(); + default: + Log.report(logvisor::Error, "unrecognized ANIM version"); + break; + } + return {}; } template <> -void ANIM::Enumerate(typename Read::StreamT& reader) -{ - atUint32 version = reader.readUint32Big(); - switch (version) - { - case 0: - m_anim.reset(new struct ANIM0); - m_anim->read(reader); - break; - case 2: - m_anim.reset(new struct ANIM2(false)); - m_anim->read(reader); - break; - case 3: - m_anim.reset(new struct ANIM2(true)); - m_anim->read(reader); - break; - default: - Log.report(logvisor::Error, "unrecognized ANIM version"); - break; - } +void ANIM::Enumerate(typename Read::StreamT& reader) { + atUint32 version = reader.readUint32Big(); + switch (version) { + case 0: + m_anim.reset(new struct ANIM0); + m_anim->read(reader); + break; + case 2: + m_anim.reset(new struct ANIM2(false)); + m_anim->read(reader); + break; + case 3: + m_anim.reset(new struct ANIM2(true)); + m_anim->read(reader); + break; + default: + Log.report(logvisor::Error, "unrecognized ANIM version"); + break; + } } template <> -void ANIM::Enumerate(typename Write::StreamT& writer) -{ - writer.writeUint32Big(m_anim->m_version); - m_anim->write(writer); +void ANIM::Enumerate(typename Write::StreamT& writer) { + writer.writeUint32Big(m_anim->m_version); + m_anim->write(writer); } template <> -void ANIM::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - m_anim->binarySize(s); +void ANIM::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + m_anim->binarySize(s); } const char* ANIM::ANIM0::DNAType() { return "ANIM0"; } template <> -void ANIM::ANIM0::Enumerate(athena::io::IStreamReader& reader) -{ - Header head; - head.read(reader); - mainInterval = head.interval; +void ANIM::ANIM0::Enumerate(athena::io::IStreamReader& reader) { + Header head; + head.read(reader); + mainInterval = head.interval; - frames.clear(); - frames.reserve(head.keyCount); - for (size_t k=0 ; k boneMap; - for (size_t b=0 ; b boneMap; + for (size_t b = 0; b < head.boneSlotCount; ++b) { + atUint8 idx = reader.readUByte(); + if (idx == 0xff) + continue; + boneMap[idx] = b; + } + + atUint32 boneCount = reader.readUint32Big(); + bones.clear(); + bones.reserve(boneCount); + channels.clear(); + for (size_t b = 0; b < boneCount; ++b) { + bones.emplace_back(boneMap[b], false); + atUint8 idx = reader.readUByte(); + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Rotation; + if (idx != 0xff) { + bones.back().second = true; + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Translation; } + } - atUint32 boneCount = reader.readUint32Big(); - bones.clear(); - bones.reserve(boneCount); - channels.clear(); - for (size_t b=0 ; b& bone : bones) { + chanKeys.emplace_back(); + std::vector& keys = chanKeys.back(); + for (size_t k = 0; k < head.keyCount; ++k) + keys.emplace_back(reader.readVec4fBig()); + + if (bone.second) + chanKeys.emplace_back(); + } + + reader.readUint32Big(); + auto kit = chanKeys.begin(); + for (const std::pair& bone : bones) { + ++kit; + if (bone.second) { + std::vector& keys = *kit++; + for (size_t k = 0; k < head.keyCount; ++k) + keys.emplace_back(reader.readVec3fBig()); } + } - reader.readUint32Big(); - chanKeys.clear(); - chanKeys.reserve(channels.size()); - for (const std::pair& bone : bones) - { - chanKeys.emplace_back(); - std::vector& keys = chanKeys.back(); - for (size_t k=0 ; k& bone : bones) - { - ++kit; - if (bone.second) - { - std::vector& keys = *kit++; - for (size_t k=0 ; k -void ANIM::ANIM0::Enumerate(athena::io::IStreamWriter& writer) -{ - Header head; - head.unk0 = 0; - head.unk1 = 0; - head.unk2 = 0; - head.keyCount = frames.size(); - head.duration = head.keyCount * mainInterval; - head.interval = mainInterval; +void ANIM::ANIM0::Enumerate(athena::io::IStreamWriter& writer) { + Header head; + head.unk0 = 0; + head.unk1 = 0; + head.unk2 = 0; + head.keyCount = frames.size(); + head.duration = head.keyCount * mainInterval; + head.interval = mainInterval; - atUint32 maxId = 0; - for (const std::pair& bone : bones) - maxId = std::max(maxId, bone.first); - head.boneSlotCount = maxId + 1; - head.write(writer); + atUint32 maxId = 0; + for (const std::pair& bone : bones) + maxId = std::max(maxId, bone.first); + head.boneSlotCount = maxId + 1; + head.write(writer); - for (size_t s=0 ; s& bone : bones) - { - if (s == bone.first) - { - writer.writeUByte(boneIdx); - found = true; - break; - } - ++boneIdx; - } - if (!found) - writer.writeUByte(0xff); - } - - writer.writeUint32Big(bones.size()); + for (size_t s = 0; s < head.boneSlotCount; ++s) { size_t boneIdx = 0; - for (const std::pair& bone : bones) - { - if (bone.second) - writer.writeUByte(boneIdx); - else - writer.writeUByte(0xff); - ++boneIdx; + bool found = false; + for (const std::pair& bone : bones) { + if (s == bone.first) { + writer.writeUByte(boneIdx); + found = true; + break; + } + ++boneIdx; } + if (!found) + writer.writeUByte(0xff); + } - writer.writeUint32Big(bones.size() * head.keyCount); - auto cit = chanKeys.begin(); - atUint32 transKeyCount = 0; - for (const std::pair& bone : bones) - { - const std::vector& keys = *cit++; - auto kit = keys.begin(); - for (size_t k=0 ; k& bone : bones) { + if (bone.second) + writer.writeUByte(boneIdx); + else + writer.writeUByte(0xff); + ++boneIdx; + } + + writer.writeUint32Big(bones.size() * head.keyCount); + auto cit = chanKeys.begin(); + atUint32 transKeyCount = 0; + for (const std::pair& bone : bones) { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k = 0; k < head.keyCount; ++k) + writer.writeVec4fBig(atVec4f{(*kit++).simd}); + if (bone.second) { + transKeyCount += head.keyCount; + ++cit; } + } - writer.writeUint32Big(transKeyCount); - cit = chanKeys.begin(); - for (const std::pair& bone : bones) - { - ++cit; - if (bone.second) - { - const std::vector& keys = *cit++; - auto kit = keys.begin(); - for (size_t k=0 ; k& bone : bones) { + ++cit; + if (bone.second) { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k = 0; k < head.keyCount; ++k) + writer.writeVec3fBig(atVec3f{(*kit++).simd}); } + } - evnt.write(writer); + evnt.write(writer); } template <> -void ANIM::ANIM0::Enumerate(size_t& __isz) -{ - Header head; +void ANIM::ANIM0::Enumerate(size_t& __isz) { + Header head; - atUint32 maxId = 0; - for (const std::pair& bone : bones) - maxId = std::max(maxId, bone.first); + atUint32 maxId = 0; + for (const std::pair& bone : bones) + maxId = std::max(maxId, bone.first); - head.binarySize(__isz); - __isz += maxId + 1; - __isz += bones.size() + 4; + head.binarySize(__isz); + __isz += maxId + 1; + __isz += bones.size() + 4; - __isz += 8; - for (const std::pair& bone : bones) - { - __isz += head.keyCount * 16; - if (bone.second) - __isz += head.keyCount * 12; - } + __isz += 8; + for (const std::pair& bone : bones) { + __isz += head.keyCount * 16; + if (bone.second) + __isz += head.keyCount * 12; + } - __isz += 4; + __isz += 4; } const char* ANIM::ANIM2::DNAType() { return "ANIM2"; } template <> -void ANIM::ANIM2::Enumerate(athena::io::IStreamReader& reader) -{ - Header head; - head.read(reader); - evnt = head.evnt; - mainInterval = head.interval; - looping = bool(head.looping); +void ANIM::ANIM2::Enumerate(athena::io::IStreamReader& reader) { + Header head; + head.read(reader); + evnt = head.evnt; + mainInterval = head.interval; + looping = bool(head.looping); - WordBitmap keyBmp; - keyBmp.read(reader, head.keyBitmapBitCount); - frames.clear(); - atUint32 frameAccum = 0; - for (bool bit : keyBmp) - { - if (bit) - frames.push_back(frameAccum); - ++frameAccum; + WordBitmap keyBmp; + keyBmp.read(reader, head.keyBitmapBitCount); + frames.clear(); + atUint32 frameAccum = 0; + for (bool bit : keyBmp) { + if (bit) + frames.push_back(frameAccum); + ++frameAccum; + } + reader.seek(8); + + bones.clear(); + bones.reserve(head.boneChannelCount); + channels.clear(); + channels.reserve(head.boneChannelCount); + atUint32 keyframeCount = 0; + + if (m_version == 3) { + for (size_t b = 0; b < head.boneChannelCount; ++b) { + ChannelDescPC desc; + desc.read(reader); + bones.emplace_back(desc.id, desc.keyCount2 != 0); + + if (desc.keyCount1) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Rotation; + chan.id = desc.id; + chan.i[0] = atInt32(desc.QinitRX) >> 8; + chan.q[0] = desc.QinitRX & 0xff; + chan.i[1] = atInt32(desc.QinitRY) >> 8; + chan.q[1] = desc.QinitRY & 0xff; + chan.i[2] = atInt32(desc.QinitRZ) >> 8; + chan.q[2] = desc.QinitRZ & 0xff; + } + keyframeCount = std::max(keyframeCount, desc.keyCount1); + + if (desc.keyCount2) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Translation; + chan.id = desc.id; + chan.i[0] = atInt32(desc.QinitTX) >> 8; + chan.q[0] = desc.QinitTX & 0xff; + chan.i[1] = atInt32(desc.QinitTY) >> 8; + chan.q[1] = desc.QinitTY & 0xff; + chan.i[2] = atInt32(desc.QinitTZ) >> 8; + chan.q[2] = desc.QinitTZ & 0xff; + } } - reader.seek(8); + } else { + for (size_t b = 0; b < head.boneChannelCount; ++b) { + ChannelDesc desc; + desc.read(reader); + bones.emplace_back(desc.id, desc.keyCount2 != 0); - bones.clear(); - bones.reserve(head.boneChannelCount); - channels.clear(); - channels.reserve(head.boneChannelCount); - atUint32 keyframeCount = 0; + if (desc.keyCount1) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Rotation; + chan.id = desc.id; + chan.i[0] = desc.initRX; + chan.q[0] = desc.qRX; + chan.i[1] = desc.initRY; + chan.q[1] = desc.qRY; + chan.i[2] = desc.initRZ; + chan.q[2] = desc.qRZ; + } + keyframeCount = std::max(keyframeCount, atUint32(desc.keyCount1)); - if (m_version == 3) - { - for (size_t b=0 ; b> 8; - chan.q[0] = desc.QinitRX & 0xff; - chan.i[1] = atInt32(desc.QinitRY) >> 8; - chan.q[1] = desc.QinitRY & 0xff; - chan.i[2] = atInt32(desc.QinitRZ) >> 8; - chan.q[2] = desc.QinitRZ & 0xff; - } - keyframeCount = std::max(keyframeCount, desc.keyCount1); - - if (desc.keyCount2) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::Translation; - chan.id = desc.id; - chan.i[0] = atInt32(desc.QinitTX) >> 8; - chan.q[0] = desc.QinitTX & 0xff; - chan.i[1] = atInt32(desc.QinitTY) >> 8; - chan.q[1] = desc.QinitTY & 0xff; - chan.i[2] = atInt32(desc.QinitTZ) >> 8; - chan.q[2] = desc.QinitTZ & 0xff; - } - } + if (desc.keyCount2) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Translation; + chan.id = desc.id; + chan.i[0] = desc.initTX; + chan.q[0] = desc.qTX; + chan.i[1] = desc.initTY; + chan.q[1] = desc.qTY; + chan.i[2] = desc.initTZ; + chan.q[2] = desc.qTZ; + } } - else - { - for (size_t b=0 ; b bsData = reader.readUBytes(bsSize); - DNAANIM::BitstreamReader bsReader; - chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult, 0.f); + size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels); + std::unique_ptr bsData = reader.readUBytes(bsSize); + DNAANIM::BitstreamReader bsReader; + chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult, 0.f); } template <> -void ANIM::ANIM2::Enumerate(athena::io::IStreamWriter& writer) -{ - Header head; - head.evnt = evnt; - head.unk0 = 1; - head.interval = mainInterval; - head.rootBoneId = 3; - head.looping = looping; - head.unk3 = 1; +void ANIM::ANIM2::Enumerate(athena::io::IStreamWriter& writer) { + Header head; + head.evnt = evnt; + head.unk0 = 1; + head.interval = mainInterval; + head.rootBoneId = 3; + head.looping = looping; + head.unk3 = 1; - WordBitmap keyBmp; - size_t frameCount = 0; - for (atUint32 frame : frames) - { - if (!keyBmp.getBit(frame)) - { - keyBmp.setBit(frame); - frameCount += 1; - } + WordBitmap keyBmp; + size_t frameCount = 0; + for (atUint32 frame : frames) { + if (!keyBmp.getBit(frame)) { + keyBmp.setBit(frame); + frameCount += 1; } - head.keyBitmapBitCount = keyBmp.getBitCount(); - head.duration = frames.back() * mainInterval; - head.boneChannelCount = bones.size(); + } + head.keyBitmapBitCount = keyBmp.getBitCount(); + head.duration = frames.back() * mainInterval; + head.boneChannelCount = bones.size(); - size_t keyframeCount = frameCount - 1; - std::vector qChannels = channels; - DNAANIM::BitstreamWriter bsWriter; - size_t bsSize; - float scaleMult; - std::unique_ptr bsData = bsWriter.write(chanKeys, keyframeCount, qChannels, - m_version == 3 ? 0x7fffff : 0x7fff, - head.rotDiv, head.translationMult, scaleMult, bsSize); + size_t keyframeCount = frameCount - 1; + std::vector qChannels = channels; + DNAANIM::BitstreamWriter bsWriter; + size_t bsSize; + float scaleMult; + std::unique_ptr bsData = + bsWriter.write(chanKeys, keyframeCount, qChannels, m_version == 3 ? 0x7fffff : 0x7fff, head.rotDiv, + head.translationMult, scaleMult, bsSize); - /* Tally up buffer size */ - size_t scratchSize = 0; - head.binarySize(scratchSize); - keyBmp.binarySize(scratchSize); - scratchSize += bsSize; - if (m_version == 3) - { - for (const std::pair& bone : bones) - { - ChannelDescPC desc; - desc.keyCount1 = keyframeCount; - if (bone.second) - desc.keyCount2 = keyframeCount; - desc.binarySize(scratchSize); - } + /* Tally up buffer size */ + size_t scratchSize = 0; + head.binarySize(scratchSize); + keyBmp.binarySize(scratchSize); + scratchSize += bsSize; + if (m_version == 3) { + for (const std::pair& bone : bones) { + ChannelDescPC desc; + desc.keyCount1 = keyframeCount; + if (bone.second) + desc.keyCount2 = keyframeCount; + desc.binarySize(scratchSize); } - else - { - for (const std::pair& bone : bones) - { - ChannelDesc desc; - desc.keyCount1 = keyframeCount; - if (bone.second) - desc.keyCount2 = keyframeCount; - desc.binarySize(scratchSize); - } + } else { + for (const std::pair& bone : bones) { + ChannelDesc desc; + desc.keyCount1 = keyframeCount; + if (bone.second) + desc.keyCount2 = keyframeCount; + desc.binarySize(scratchSize); } - head.scratchSize = scratchSize; + } + head.scratchSize = scratchSize; - head.write(writer); - keyBmp.write(writer); - writer.writeUint32Big(head.boneChannelCount); - writer.writeUint32Big(head.boneChannelCount); - auto cit = qChannels.begin(); + head.write(writer); + keyBmp.write(writer); + writer.writeUint32Big(head.boneChannelCount); + writer.writeUint32Big(head.boneChannelCount); + auto cit = qChannels.begin(); - if (m_version == 3) - { - for (const std::pair& bone : bones) - { - ChannelDescPC desc; - desc.id = bone.first; - DNAANIM::Channel& chan = *cit++; - desc.keyCount1 = keyframeCount; - desc.QinitRX = (chan.i[0] << 8) | chan.q[0]; - desc.QinitRY = (chan.i[1] << 8) | chan.q[1]; - desc.QinitRZ = (chan.i[2] << 8) | chan.q[2]; - if (bone.second) - { - DNAANIM::Channel& chan = *cit++; - desc.keyCount2 = keyframeCount; - desc.QinitTX = (chan.i[0] << 8) | chan.q[0]; - desc.QinitTY = (chan.i[1] << 8) | chan.q[1]; - desc.QinitTZ = (chan.i[2] << 8) | chan.q[2]; - } - desc.write(writer); - } + if (m_version == 3) { + for (const std::pair& bone : bones) { + ChannelDescPC desc; + desc.id = bone.first; + DNAANIM::Channel& chan = *cit++; + desc.keyCount1 = keyframeCount; + desc.QinitRX = (chan.i[0] << 8) | chan.q[0]; + desc.QinitRY = (chan.i[1] << 8) | chan.q[1]; + desc.QinitRZ = (chan.i[2] << 8) | chan.q[2]; + if (bone.second) { + DNAANIM::Channel& chan = *cit++; + desc.keyCount2 = keyframeCount; + desc.QinitTX = (chan.i[0] << 8) | chan.q[0]; + desc.QinitTY = (chan.i[1] << 8) | chan.q[1]; + desc.QinitTZ = (chan.i[2] << 8) | chan.q[2]; + } + desc.write(writer); } - else - { - for (const std::pair& bone : bones) - { - ChannelDesc desc; - desc.id = bone.first; - DNAANIM::Channel& chan = *cit++; - desc.keyCount1 = keyframeCount; - desc.initRX = chan.i[0]; - desc.qRX = chan.q[0]; - desc.initRY = chan.i[1]; - desc.qRY = chan.q[1]; - desc.initRZ = chan.i[2]; - desc.qRZ = chan.q[2]; - if (bone.second) - { - DNAANIM::Channel& chan = *cit++; - desc.keyCount2 = keyframeCount; - desc.initTX = chan.i[0]; - desc.qTX = chan.q[0]; - desc.initTY = chan.i[1]; - desc.qTY = chan.q[1]; - desc.initTZ = chan.i[2]; - desc.qTZ = chan.q[2]; - } - desc.write(writer); - } + } else { + for (const std::pair& bone : bones) { + ChannelDesc desc; + desc.id = bone.first; + DNAANIM::Channel& chan = *cit++; + desc.keyCount1 = keyframeCount; + desc.initRX = chan.i[0]; + desc.qRX = chan.q[0]; + desc.initRY = chan.i[1]; + desc.qRY = chan.q[1]; + desc.initRZ = chan.i[2]; + desc.qRZ = chan.q[2]; + if (bone.second) { + DNAANIM::Channel& chan = *cit++; + desc.keyCount2 = keyframeCount; + desc.initTX = chan.i[0]; + desc.qTX = chan.q[0]; + desc.initTY = chan.i[1]; + desc.qTY = chan.q[1]; + desc.initTZ = chan.i[2]; + desc.qTZ = chan.q[2]; + } + desc.write(writer); } + } - writer.writeUBytes(bsData.get(), bsSize); + writer.writeUBytes(bsData.get(), bsSize); } template <> -void ANIM::ANIM2::Enumerate(size_t& __isz) -{ - Header head; +void ANIM::ANIM2::Enumerate(size_t& __isz) { + Header head; - WordBitmap keyBmp; - for (atUint32 frame : frames) - keyBmp.setBit(frame); + WordBitmap keyBmp; + for (atUint32 frame : frames) + keyBmp.setBit(frame); - head.binarySize(__isz); - keyBmp.binarySize(__isz); - __isz += 8; - if (m_version == 3) - { - for (const std::pair& bone : bones) - { - __isz += 24; - if (bone.second) - __isz += 12; - } + head.binarySize(__isz); + keyBmp.binarySize(__isz); + __isz += 8; + if (m_version == 3) { + for (const std::pair& bone : bones) { + __isz += 24; + if (bone.second) + __isz += 12; } - else - { - for (const std::pair& bone : bones) - { - __isz += 17; - if (bone.second) - __isz += 9; - } + } else { + for (const std::pair& bone : bones) { + __isz += 17; + if (bone.second) + __isz += 9; } + } - __isz += DNAANIM::ComputeBitstreamSize(frames.size(), channels); + __isz += DNAANIM::ComputeBitstreamSize(frames.size(), channels); } -ANIM::ANIM(const BlenderAction& act, - const std::unordered_map& idMap, - const DNAANIM::RigInverter& rig, - bool pc) -{ - m_anim.reset(new struct ANIM2(pc)); - IANIM& newAnim = *m_anim; - newAnim.looping = act.looping; +ANIM::ANIM(const BlenderAction& act, const std::unordered_map& idMap, + const DNAANIM::RigInverter& rig, bool pc) { + m_anim.reset(new struct ANIM2(pc)); + IANIM& newAnim = *m_anim; + newAnim.looping = act.looping; - newAnim.bones.reserve(act.channels.size()); - size_t extChanCount = 0; - std::unordered_set addedBones; - addedBones.reserve(act.channels.size()); - for (const BlenderAction::Channel& chan : act.channels) - { - auto search = idMap.find(chan.boneName); - if (search == idMap.cend()) - { - Log.report(logvisor::Warning, "unable to find id for bone '%s'", chan.boneName.c_str()); - continue; - } - if (addedBones.find(search->second) != addedBones.cend()) - continue; - addedBones.insert(search->second); + newAnim.bones.reserve(act.channels.size()); + size_t extChanCount = 0; + std::unordered_set addedBones; + addedBones.reserve(act.channels.size()); + for (const BlenderAction::Channel& chan : act.channels) { + auto search = idMap.find(chan.boneName); + if (search == idMap.cend()) { + Log.report(logvisor::Warning, "unable to find id for bone '%s'", chan.boneName.c_str()); + continue; + } + if (addedBones.find(search->second) != addedBones.cend()) + continue; + addedBones.insert(search->second); - extChanCount += std::max(zeus::PopCount(chan.attrMask), 2); - newAnim.bones.emplace_back(search->second, (chan.attrMask & 0x2) != 0); + extChanCount += std::max(zeus::PopCount(chan.attrMask), 2); + newAnim.bones.emplace_back(search->second, (chan.attrMask & 0x2) != 0); + } + + newAnim.frames.reserve(act.frames.size()); + for (int32_t frame : act.frames) + newAnim.frames.push_back(frame); + + newAnim.channels.reserve(extChanCount); + newAnim.chanKeys.reserve(extChanCount); + + for (const BlenderAction::Channel& chan : act.channels) { + auto search = idMap.find(chan.boneName); + if (search == idMap.cend()) + continue; + + newAnim.channels.emplace_back(); + DNAANIM::Channel& newChan = newAnim.channels.back(); + newChan.type = DNAANIM::Channel::Type::Rotation; + newChan.id = search->second; + + newAnim.chanKeys.emplace_back(); + std::vector& rotVals = newAnim.chanKeys.back(); + rotVals.reserve(chan.keys.size()); + float sign = 0.f; + for (const BlenderAction::Channel::Key& key : chan.keys) { + zeus::CQuaternion q(key.rotation.val); + q = rig.restoreRotation(newChan.id, q); + if (sign == 0.f) + sign = q.w() < 0.f ? -1.f : 1.f; + q *= sign; + rotVals.emplace_back(q.mSimd); } - newAnim.frames.reserve(act.frames.size()); - for (int32_t frame : act.frames) - newAnim.frames.push_back(frame); + if (chan.attrMask & 0x2) { + newAnim.channels.emplace_back(); + DNAANIM::Channel& newChan = newAnim.channels.back(); + newChan.type = DNAANIM::Channel::Type::Translation; + newChan.id = search->second; - newAnim.channels.reserve(extChanCount); - newAnim.chanKeys.reserve(extChanCount); - - for (const BlenderAction::Channel& chan : act.channels) - { - auto search = idMap.find(chan.boneName); - if (search == idMap.cend()) - continue; - - newAnim.channels.emplace_back(); - DNAANIM::Channel& newChan = newAnim.channels.back(); - newChan.type = DNAANIM::Channel::Type::Rotation; - newChan.id = search->second; - - newAnim.chanKeys.emplace_back(); - std::vector& rotVals = newAnim.chanKeys.back(); - rotVals.reserve(chan.keys.size()); - float sign = 0.f; - for (const BlenderAction::Channel::Key& key : chan.keys) - { - zeus::CQuaternion q(key.rotation.val); - q = rig.restoreRotation(newChan.id, q); - if (sign == 0.f) - sign = q.w() < 0.f ? -1.f : 1.f; - q *= sign; - rotVals.emplace_back(q.mSimd); - } - - if (chan.attrMask & 0x2) - { - newAnim.channels.emplace_back(); - DNAANIM::Channel& newChan = newAnim.channels.back(); - newChan.type = DNAANIM::Channel::Type::Translation; - newChan.id = search->second; - - newAnim.chanKeys.emplace_back(); - std::vector& transVals = newAnim.chanKeys.back(); - transVals.reserve(chan.keys.size()); - for (const BlenderAction::Channel::Key& key : chan.keys) - { - zeus::CVector3f pos(key.position.val); - pos = rig.restorePosition(newChan.id, pos, true); - transVals.emplace_back(pos.mSimd); - } - } + newAnim.chanKeys.emplace_back(); + std::vector& transVals = newAnim.chanKeys.back(); + transVals.reserve(chan.keys.size()); + for (const BlenderAction::Channel::Key& key : chan.keys) { + zeus::CVector3f pos(key.position.val); + pos = rig.restorePosition(newChan.id, pos, true); + transVals.emplace_back(pos.mSimd); + } } + } - newAnim.mainInterval = act.interval; + newAnim.mainInterval = act.interval; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ANIM.hpp b/DataSpec/DNAMP1/ANIM.hpp index 2e11b492a..c5ddfdc3d 100644 --- a/DataSpec/DNAMP1/ANIM.hpp +++ b/DataSpec/DNAMP1/ANIM.hpp @@ -7,240 +7,211 @@ #include "EVNT.hpp" #include "DataSpec/DNACommon/ANCS.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct ANIM : BigDNA -{ +struct ANIM : BigDNA { + AT_DECL_EXPLICIT_DNA + + static UniqueID32 GetEVNTId(athena::io::IStreamReader& r); + + struct IANIM : BigDNAV { + Delete expl; + atUint32 m_version; + IANIM(atUint32 version) : m_version(version) {} + + std::vector> bones; + std::vector frames; + std::vector channels; + std::vector> chanKeys; + float mainInterval = 0.0; + UniqueID32Zero evnt; + bool looping = false; + + void sendANIMToBlender(hecl::blender::PyOutStream&, const DNAANIM::RigInverter& rig) const; + }; + + struct ANIM0 : IANIM { AT_DECL_EXPLICIT_DNA + AT_DECL_DNAV + ANIM0() : IANIM(0) {} - static UniqueID32 GetEVNTId(athena::io::IStreamReader& r); + struct Header : BigDNA { + AT_DECL_DNA + Value duration; + Value unk0; + Value interval; + Value unk1; + Value keyCount; + Value unk2; + Value boneSlotCount; + }; + }; - struct IANIM : BigDNAV - { - Delete expl; - atUint32 m_version; - IANIM(atUint32 version) : m_version(version) {} + struct ANIM2 : IANIM { + AT_DECL_EXPLICIT_DNA + AT_DECL_DNAV + ANIM2(bool pc) : IANIM(pc ? 3 : 2) {} - std::vector> bones; - std::vector frames; - std::vector channels; - std::vector> chanKeys; - float mainInterval = 0.0; - UniqueID32Zero evnt; - bool looping = false; - - void sendANIMToBlender(hecl::blender::PyOutStream&, const DNAANIM::RigInverter& rig) const; + struct Header : BigDNA { + AT_DECL_DNA + Value scratchSize; + UniqueID32Zero evnt; + Value unk0 = 1; + Value duration; + Value interval; + Value rootBoneId = 3; + Value looping = 0; + Value rotDiv; + Value translationMult; + Value boneChannelCount; + Value unk3; + Value keyBitmapBitCount; }; - struct ANIM0 : IANIM - { - AT_DECL_EXPLICIT_DNA - AT_DECL_DNAV - ANIM0() : IANIM(0) {} + struct ChannelDesc : BigDNA { + Delete expl; + Value id = 0; + Value keyCount1 = 0; + Value initRX = 0; + Value qRX = 0; + Value initRY = 0; + Value qRY = 0; + Value initRZ = 0; + Value qRZ = 0; + Value keyCount2 = 0; + Value initTX = 0; + Value qTX = 0; + Value initTY = 0; + Value qTY = 0; + Value initTZ = 0; + Value qTZ = 0; - struct Header : BigDNA - { - AT_DECL_DNA - Value duration; - Value unk0; - Value interval; - Value unk1; - Value keyCount; - Value unk2; - Value boneSlotCount; - }; - }; - - struct ANIM2 : IANIM - { - AT_DECL_EXPLICIT_DNA - AT_DECL_DNAV - ANIM2(bool pc) : IANIM(pc ? 3 : 2) {} - - struct Header : BigDNA - { - AT_DECL_DNA - Value scratchSize; - UniqueID32Zero evnt; - Value unk0 = 1; - Value duration; - Value interval; - Value rootBoneId = 3; - Value looping = 0; - Value rotDiv; - Value translationMult; - Value boneChannelCount; - Value unk3; - Value keyBitmapBitCount; - }; - - struct ChannelDesc : BigDNA - { - Delete expl; - Value id = 0; - Value keyCount1 = 0; - Value initRX = 0; - Value qRX = 0; - Value initRY = 0; - Value qRY = 0; - Value initRZ = 0; - Value qRZ = 0; - Value keyCount2 = 0; - Value initTX = 0; - Value qTX = 0; - Value initTY = 0; - Value qTY = 0; - Value initTZ = 0; - Value qTZ = 0; - - void read(athena::io::IStreamReader& reader) - { - id = reader.readUint32Big(); - keyCount1 = reader.readUint16Big(); - initRX = reader.readInt16Big(); - qRX = reader.readUByte(); - initRY = reader.readInt16Big(); - qRY = reader.readUByte(); - initRZ = reader.readInt16Big(); - qRZ = reader.readUByte(); - keyCount2 = reader.readUint16Big(); - if (keyCount2) - { - initTX = reader.readInt16Big(); - qTX = reader.readUByte(); - initTY = reader.readInt16Big(); - qTY = reader.readUByte(); - initTZ = reader.readInt16Big(); - qTZ = reader.readUByte(); - } - } - void write(athena::io::IStreamWriter& writer) const - { - writer.writeUint32Big(id); - writer.writeUint16Big(keyCount1); - writer.writeInt16Big(initRX); - writer.writeUByte(qRX); - writer.writeInt16Big(initRY); - writer.writeUByte(qRY); - writer.writeInt16Big(initRZ); - writer.writeUByte(qRZ); - writer.writeUint16Big(keyCount2); - if (keyCount2) - { - writer.writeInt16Big(initTX); - writer.writeUByte(qTX); - writer.writeInt16Big(initTY); - writer.writeUByte(qTY); - writer.writeInt16Big(initTZ); - writer.writeUByte(qTZ); - } - } - void binarySize(size_t& __isz) const - { - __isz += 17; - if (keyCount2) - __isz += 9; - } - }; - - struct ChannelDescPC : BigDNA - { - Delete expl; - Value id = 0; - Value keyCount1 = 0; - Value QinitRX = 0; - Value QinitRY = 0; - Value QinitRZ = 0; - Value keyCount2 = 0; - Value QinitTX = 0; - Value QinitTY = 0; - Value QinitTZ = 0; - - void read(athena::io::IStreamReader& reader) - { - id = reader.readUint32Big(); - keyCount1 = reader.readUint32Big(); - QinitRX = reader.readUint32Big(); - QinitRY = reader.readUint32Big(); - QinitRZ = reader.readUint32Big(); - keyCount2 = reader.readUint32Big(); - if (keyCount2) - { - QinitTX = reader.readUint32Big(); - QinitTY = reader.readUint32Big(); - QinitTZ = reader.readUint32Big(); - } - } - void write(athena::io::IStreamWriter& writer) const - { - writer.writeUint32Big(id); - writer.writeUint32Big(keyCount1); - writer.writeUint32Big(QinitRX); - writer.writeUint32Big(QinitRY); - writer.writeUint32Big(QinitRZ); - writer.writeUint32Big(keyCount2); - if (keyCount2) - { - writer.writeUint32Big(QinitTX); - writer.writeUint32Big(QinitTY); - writer.writeUint32Big(QinitTZ); - } - } - void binarySize(size_t& __isz) const - { - __isz += 24; - if (keyCount2) - __isz += 12; - } - }; - }; - - std::unique_ptr m_anim; - - void sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig, bool) const - { - m_anim->sendANIMToBlender(os, rig); - } - - bool isLooping() const - { - if (!m_anim) - return false; - return m_anim->looping; - } - - void extractEVNT(const DNAANCS::AnimationResInfo& animInfo, - const hecl::ProjectPath& outPath, PAKRouter& pakRouter, bool force) const - { - if (m_anim->evnt) - { - hecl::SystemStringConv sysStr(animInfo.name); - hecl::ProjectPath evntYamlPath = outPath.getWithExtension((hecl::SystemString(_SYS_STR(".")) + - sysStr.c_str() + - _SYS_STR(".evnt.yaml")).c_str(), true); - hecl::ProjectPath::Type evntYamlType = evntYamlPath.getPathType(); - - if (force || evntYamlType == hecl::ProjectPath::Type::None) - { - EVNT evnt; - if (pakRouter.lookupAndReadDNA(m_anim->evnt, evnt, true)) - { - athena::io::FileWriter writer(evntYamlPath.getAbsolutePath()); - athena::io::ToYAMLStream(evnt, writer); - } - } + void read(athena::io::IStreamReader& reader) { + id = reader.readUint32Big(); + keyCount1 = reader.readUint16Big(); + initRX = reader.readInt16Big(); + qRX = reader.readUByte(); + initRY = reader.readInt16Big(); + qRY = reader.readUByte(); + initRZ = reader.readInt16Big(); + qRZ = reader.readUByte(); + keyCount2 = reader.readUint16Big(); + if (keyCount2) { + initTX = reader.readInt16Big(); + qTX = reader.readUByte(); + initTY = reader.readInt16Big(); + qTY = reader.readUByte(); + initTZ = reader.readInt16Big(); + qTZ = reader.readUByte(); } + } + void write(athena::io::IStreamWriter& writer) const { + writer.writeUint32Big(id); + writer.writeUint16Big(keyCount1); + writer.writeInt16Big(initRX); + writer.writeUByte(qRX); + writer.writeInt16Big(initRY); + writer.writeUByte(qRY); + writer.writeInt16Big(initRZ); + writer.writeUByte(qRZ); + writer.writeUint16Big(keyCount2); + if (keyCount2) { + writer.writeInt16Big(initTX); + writer.writeUByte(qTX); + writer.writeInt16Big(initTY); + writer.writeUByte(qTY); + writer.writeInt16Big(initTZ); + writer.writeUByte(qTZ); + } + } + void binarySize(size_t& __isz) const { + __isz += 17; + if (keyCount2) + __isz += 9; + } + }; + + struct ChannelDescPC : BigDNA { + Delete expl; + Value id = 0; + Value keyCount1 = 0; + Value QinitRX = 0; + Value QinitRY = 0; + Value QinitRZ = 0; + Value keyCount2 = 0; + Value QinitTX = 0; + Value QinitTY = 0; + Value QinitTZ = 0; + + void read(athena::io::IStreamReader& reader) { + id = reader.readUint32Big(); + keyCount1 = reader.readUint32Big(); + QinitRX = reader.readUint32Big(); + QinitRY = reader.readUint32Big(); + QinitRZ = reader.readUint32Big(); + keyCount2 = reader.readUint32Big(); + if (keyCount2) { + QinitTX = reader.readUint32Big(); + QinitTY = reader.readUint32Big(); + QinitTZ = reader.readUint32Big(); + } + } + void write(athena::io::IStreamWriter& writer) const { + writer.writeUint32Big(id); + writer.writeUint32Big(keyCount1); + writer.writeUint32Big(QinitRX); + writer.writeUint32Big(QinitRY); + writer.writeUint32Big(QinitRZ); + writer.writeUint32Big(keyCount2); + if (keyCount2) { + writer.writeUint32Big(QinitTX); + writer.writeUint32Big(QinitTY); + writer.writeUint32Big(QinitTZ); + } + } + void binarySize(size_t& __isz) const { + __isz += 24; + if (keyCount2) + __isz += 12; + } + }; + }; + + std::unique_ptr m_anim; + + void sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig, bool) const { + m_anim->sendANIMToBlender(os, rig); + } + + bool isLooping() const { + if (!m_anim) + return false; + return m_anim->looping; + } + + void extractEVNT(const DNAANCS::AnimationResInfo& animInfo, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, bool force) const { + if (m_anim->evnt) { + hecl::SystemStringConv sysStr(animInfo.name); + hecl::ProjectPath evntYamlPath = outPath.getWithExtension( + (hecl::SystemString(_SYS_STR(".")) + sysStr.c_str() + _SYS_STR(".evnt.yaml")).c_str(), true); + hecl::ProjectPath::Type evntYamlType = evntYamlPath.getPathType(); + + if (force || evntYamlType == hecl::ProjectPath::Type::None) { + EVNT evnt; + if (pakRouter.lookupAndReadDNA(m_anim->evnt, evnt, true)) { + athena::io::FileWriter writer(evntYamlPath.getAbsolutePath()); + athena::io::ToYAMLStream(evnt, writer); + } + } } + } - using BlenderAction = hecl::blender::Action; + using BlenderAction = hecl::blender::Action; - ANIM() = default; - ANIM(const BlenderAction& act, - const std::unordered_map& idMap, - const DNAANIM::RigInverter& rig, - bool pc); + ANIM() = default; + ANIM(const BlenderAction& act, const std::unordered_map& idMap, + const DNAANIM::RigInverter& rig, bool pc); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CINF.cpp b/DataSpec/DNAMP1/CINF.cpp index 08aa5f0f5..db744ae08 100644 --- a/DataSpec/DNAMP1/CINF.cpp +++ b/DataSpec/DNAMP1/CINF.cpp @@ -1,184 +1,160 @@ #include "CINF.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -atUint32 CINF::getInternalBoneIdxFromId(atUint32 id) const -{ - atUint32 idx = 0; - for (const Bone& b : bones) - { - if (b.id == id) - return idx; - ++idx; +atUint32 CINF::getInternalBoneIdxFromId(atUint32 id) const { + atUint32 idx = 0; + for (const Bone& b : bones) { + if (b.id == id) + return idx; + ++idx; + } + return -1; +} + +atUint32 CINF::getBoneIdxFromId(atUint32 id) const { + atUint32 idx = 0; + for (atUint32 bid : boneIds) { + if (bid == id) + return idx; + ++idx; + } + return 0; +} + +const std::string* CINF::getBoneNameFromId(atUint32 id) const { + for (const Name& name : names) + if (id == name.boneId) + return &name.name; + return nullptr; +} + +void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const { + for (atUint32 bid : boneIds) { + for (const Name& name : names) { + if (name.boneId == bid) { + os.format("obj.vertex_groups.new('%s')\n", name.name.c_str()); + break; + } } - return -1; + } } -atUint32 CINF::getBoneIdxFromId(atUint32 id) const -{ - atUint32 idx = 0; - for (atUint32 bid : boneIds) - { - if (bid == id) - return idx; - ++idx; - } - return 0; +void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const { + DNAANIM::RigInverter inverter(*this); + + os.format( + "arm = bpy.data.armatures.new('CINF_%08X')\n" + "arm_obj = bpy.data.objects.new(arm.name, arm)\n" + "bpy.context.scene.objects.link(arm_obj)\n" + "bpy.context.scene.objects.active = arm_obj\n" + "bpy.ops.object.mode_set(mode='EDIT')\n" + "arm_bone_table = {}\n", + cinfId.toUint32()); + + for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) { + zeus::simd_floats originF(bone.m_origBone.origin.simd); + zeus::simd_floats tailF(bone.m_tail.mSimd); + os.format( + "bone = arm.edit_bones.new('%s')\n" + "bone.head = (%f,%f,%f)\n" + "bone.tail = (%f,%f,%f)\n" + "bone.use_inherit_scale = False\n" + "arm_bone_table[%u] = bone\n", + getBoneNameFromId(bone.m_origBone.id)->c_str(), originF[0], originF[1], originF[2], tailF[0], tailF[1], + tailF[2], bone.m_origBone.id); + } + + for (const Bone& bone : bones) + if (bone.parentId != 2) + os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId); + + os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; + + const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION"; + for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) + os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", getBoneNameFromId(bone.m_origBone.id)->c_str(), + rotMode); } -const std::string* CINF::getBoneNameFromId(atUint32 id) const -{ - for (const Name& name : names) - if (id == name.boneId) - return &name.name; - return nullptr; -} - -void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const -{ - for (atUint32 bid : boneIds) - { - for (const Name& name : names) - { - if (name.boneId == bid) - { - os.format("obj.vertex_groups.new('%s')\n", name.name.c_str()); - break; - } - } - } -} - -void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const -{ - DNAANIM::RigInverter inverter(*this); - - os.format("arm = bpy.data.armatures.new('CINF_%08X')\n" - "arm_obj = bpy.data.objects.new(arm.name, arm)\n" - "bpy.context.scene.objects.link(arm_obj)\n" - "bpy.context.scene.objects.active = arm_obj\n" - "bpy.ops.object.mode_set(mode='EDIT')\n" - "arm_bone_table = {}\n", - cinfId.toUint32()); - - for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - { - zeus::simd_floats originF(bone.m_origBone.origin.simd); - zeus::simd_floats tailF(bone.m_tail.mSimd); - os.format("bone = arm.edit_bones.new('%s')\n" - "bone.head = (%f,%f,%f)\n" - "bone.tail = (%f,%f,%f)\n" - "bone.use_inherit_scale = False\n" - "arm_bone_table[%u] = bone\n", - getBoneNameFromId(bone.m_origBone.id)->c_str(), - originF[0], originF[1], originF[2], - tailF[0], tailF[1], tailF[2], - bone.m_origBone.id); - } - - for (const Bone& bone : bones) - if (bone.parentId != 2) - os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId); - - os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; - - const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION"; - for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", - getBoneNameFromId(bone.m_origBone.id)->c_str(), rotMode); -} - -std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) -{ - return hecl::Format("CINF_%08X", cinfId.toUint32()); -} +std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return hecl::Format("CINF_%08X", cinfId.toUint32()); } int CINF::RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId, - std::unordered_map& idMap, std::map& nameMap) -{ - int selId; - auto search = idMap.find(bone->name); - if (search == idMap.end()) - { - selId = curId++; - idMap.emplace(std::make_pair(bone->name, selId)); + std::unordered_map& idMap, + std::map& nameMap) { + int selId; + auto search = idMap.find(bone->name); + if (search == idMap.end()) { + selId = curId++; + idMap.emplace(std::make_pair(bone->name, selId)); + } else + selId = search->second; + + bones.emplace_back(); + Bone& boneOut = bones.back(); + nameMap[bone->name] = selId; + boneOut.id = selId; + boneOut.parentId = parent; + boneOut.origin = bone->origin; + boneOut.linkedCount = bone->children.size() + 1; + boneOut.linked.reserve(boneOut.linkedCount); + + const BlenderBone* child; + boneOut.linked.push_back(parent); + for (size_t i = 0; (child = armature.getChild(bone, i)); ++i) + boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, curId, idMap, nameMap)); + + return boneOut.id; +} + +CINF::CINF(const Armature& armature, std::unordered_map& idMap) { + idMap.reserve(armature.bones.size()); + bones.reserve(armature.bones.size()); + + std::map nameMap; + + const BlenderBone* bone = armature.getRoot(); + if (bone) { + if (bone->children.size()) { + int curId = 4; + const BlenderBone* child; + for (size_t i = 0; (child = armature.getChild(bone, i)); ++i) + RecursiveAddArmatureBone(armature, child, 3, curId, idMap, nameMap); } - else - selId = search->second; bones.emplace_back(); Bone& boneOut = bones.back(); - nameMap[bone->name] = selId; - boneOut.id = selId; - boneOut.parentId = parent; + nameMap[bone->name] = 3; + boneOut.id = 3; + boneOut.parentId = 2; boneOut.origin = bone->origin; - boneOut.linkedCount = bone->children.size() + 1; - boneOut.linked.reserve(boneOut.linkedCount); + idMap.emplace(std::make_pair(bone->name, 3)); - const BlenderBone* child; - boneOut.linked.push_back(parent); - for (size_t i=0 ; (child = armature.getChild(bone, i)) ; ++i) - boneOut.linked.push_back(RecursiveAddArmatureBone(armature, child, boneOut.id, curId, idMap, nameMap)); - - return boneOut.id; -} - -CINF::CINF(const Armature& armature, std::unordered_map& idMap) -{ - idMap.reserve(armature.bones.size()); - bones.reserve(armature.bones.size()); - - std::map nameMap; - - const BlenderBone* bone = armature.getRoot(); - if (bone) - { - if (bone->children.size()) - { - int curId = 4; - const BlenderBone* child; - for (size_t i=0 ; (child = armature.getChild(bone, i)) ; ++i) - RecursiveAddArmatureBone(armature, child, 3, curId, idMap, nameMap); - } - - bones.emplace_back(); - Bone& boneOut = bones.back(); - nameMap[bone->name] = 3; - boneOut.id = 3; - boneOut.parentId = 2; - boneOut.origin = bone->origin; - idMap.emplace(std::make_pair(bone->name, 3)); - - if (bone->children.size()) - { - boneOut.linkedCount = 2; - boneOut.linked = {2, 4}; - } - else - { - boneOut.linkedCount = 1; - boneOut.linked = {2}; - } + if (bone->children.size()) { + boneOut.linkedCount = 2; + boneOut.linked = {2, 4}; + } else { + boneOut.linkedCount = 1; + boneOut.linked = {2}; } + } - boneCount = bones.size(); + boneCount = bones.size(); - names.reserve(nameMap.size()); - nameCount = nameMap.size(); - for (const auto& name : nameMap) - { - names.emplace_back(); - Name& nameOut = names.back(); - nameOut.name = name.first; - nameOut.boneId = name.second; - } + names.reserve(nameMap.size()); + nameCount = nameMap.size(); + for (const auto& name : nameMap) { + names.emplace_back(); + Name& nameOut = names.back(); + nameOut.name = name.first; + nameOut.boneId = name.second; + } - boneIdCount = boneCount; - boneIds.reserve(boneIdCount); - for (auto it=bones.crbegin() ; it != bones.crend() ; ++it) - boneIds.push_back(it->id); + boneIdCount = boneCount; + boneIds.reserve(boneIdCount); + for (auto it = bones.crbegin(); it != bones.crend(); ++it) + boneIds.push_back(it->id); } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CINF.hpp b/DataSpec/DNAMP1/CINF.hpp index 8078a6256..b6285afaa 100644 --- a/DataSpec/DNAMP1/CINF.hpp +++ b/DataSpec/DNAMP1/CINF.hpp @@ -3,52 +3,47 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DataSpec/DNACommon/RigInverter.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CINF : BigDNA -{ +struct CINF : BigDNA { + AT_DECL_DNA + Value boneCount; + struct Bone : BigDNA { AT_DECL_DNA - Value boneCount; - struct Bone : BigDNA - { - AT_DECL_DNA - Value id; - Value parentId; - Value origin; - Value linkedCount; - Vector linked; - }; - Vector bones; + Value id; + Value parentId; + Value origin; + Value linkedCount; + Vector linked; + }; + Vector bones; - Value boneIdCount; - Vector boneIds; + Value boneIdCount; + Vector boneIds; - Value nameCount; - struct Name : BigDNA - { - AT_DECL_DNA - String<-1> name; - Value boneId; - }; - Vector names; + Value nameCount; + struct Name : BigDNA { + AT_DECL_DNA + String<-1> name; + Value boneId; + }; + Vector names; - atUint32 getInternalBoneIdxFromId(atUint32 id) const; - atUint32 getBoneIdxFromId(atUint32 id) const; - const std::string* getBoneNameFromId(atUint32 id) const; - void sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const; - void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const; - static std::string GetCINFArmatureName(const UniqueID32& cinfId); + atUint32 getInternalBoneIdxFromId(atUint32 id) const; + atUint32 getBoneIdxFromId(atUint32 id) const; + const std::string* getBoneNameFromId(atUint32 id) const; + void sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const; + void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const; + static std::string GetCINFArmatureName(const UniqueID32& cinfId); - CINF() = default; - using Armature = hecl::blender::Armature; - using BlenderBone = hecl::blender::Bone; + CINF() = default; + using Armature = hecl::blender::Armature; + using BlenderBone = hecl::blender::Bone; - int RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId, - std::unordered_map& idMap, std::map& nameMap); + int RecursiveAddArmatureBone(const Armature& armature, const BlenderBone* bone, int parent, int& curId, + std::unordered_map& idMap, std::map& nameMap); - CINF(const Armature& armature, std::unordered_map& idMap); + CINF(const Armature& armature, std::unordered_map& idMap); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CMDL.cpp b/DataSpec/DNAMP1/CMDL.cpp index 000e593fc..a7809800a 100644 --- a/DataSpec/DNAMP1/CMDL.cpp +++ b/DataSpec/DNAMP1/CMDL.cpp @@ -1,38 +1,30 @@ #include "CMDL.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -bool CMDL::Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) -{ - /* Check for RigPair */ - const typename CharacterAssociations::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id); - CINF cinf; - CSKR cskr; - std::pair loadRp(nullptr, nullptr); - if (rp) - { - pakRouter.lookupAndReadDNA(rp->first, cskr); - pakRouter.lookupAndReadDNA(rp->second, cinf); - loadRp.first = &cskr; - loadRp.second = &cinf; - } +bool CMDL::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + /* Check for RigPair */ + const typename CharacterAssociations::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id); + CINF cinf; + CSKR cskr; + std::pair loadRp(nullptr, nullptr); + if (rp) { + pakRouter.lookupAndReadDNA(rp->first, cskr); + pakRouter.lookupAndReadDNA(rp->second, cinf); + loadRp.first = &cskr; + loadRp.second = &cinf; + } - /* Do extract */ - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::Mesh)) - return false; - DNACMDL::ReadCMDLToBlender, MaterialSet, std::pair, DNACMDL::SurfaceHeader_1, 2> - (conn, rs, pakRouter, entry, dataSpec, loadRp); - conn.saveBlend(); + /* Do extract */ + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::Mesh)) + return false; + DNACMDL::ReadCMDLToBlender, MaterialSet, std::pair, DNACMDL::SurfaceHeader_1, 2>( + conn, rs, pakRouter, entry, dataSpec, loadRp); + conn.saveBlend(); #if 0 /* Cook and re-extract test */ @@ -50,98 +42,82 @@ bool CMDL::Extract(const SpecBase& dataSpec, (conn, reader, pakRouter, entry, dataSpec, loadRp); return conn.saveBlend(); #elif 0 - /* HMDL cook test */ - hecl::ProjectPath tempOut = outPath.getWithExtension(_SYS_STR(".recook"), true); - hecl::blender::Connection::DataStream ds = conn.beginData(); - DNACMDL::Mesh mesh = ds.compileMesh(hecl::HMDLTopology::TriStrips, 16); - ds.close(); - DNACMDL::WriteHMDLCMDL(tempOut, outPath, mesh); + /* HMDL cook test */ + hecl::ProjectPath tempOut = outPath.getWithExtension(_SYS_STR(".recook"), true); + hecl::blender::Connection::DataStream ds = conn.beginData(); + DNACMDL::Mesh mesh = ds.compileMesh(hecl::HMDLTopology::TriStrips, 16); + ds.close(); + DNACMDL::WriteHMDLCMDL(tempOut, outPath, mesh); #endif - return true; + return true; } -bool CMDL::Cook(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNACMDL::Mesh& mesh) -{ - if (!mesh.skins.empty()) - { - DNACMDL::Mesh skinMesh = mesh.getContiguousSkinningVersion(); - if (!DNACMDL::WriteCMDL(outPath, inPath, skinMesh)) - return false; +bool CMDL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNACMDL::Mesh& mesh) { + if (!mesh.skins.empty()) { + DNACMDL::Mesh skinMesh = mesh.getContiguousSkinningVersion(); + if (!DNACMDL::WriteCMDL(outPath, inPath, skinMesh)) + return false; - /* Output skinning intermediate */ - auto vertCountIt = skinMesh.contiguousSkinVertCounts.cbegin(); - athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".skinint")).getAbsolutePath()); - writer.writeUint32Big(skinMesh.boneNames.size()); - for (const std::string& boneName : skinMesh.boneNames) - writer.writeString(boneName); + /* Output skinning intermediate */ + auto vertCountIt = skinMesh.contiguousSkinVertCounts.cbegin(); + athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".skinint")).getAbsolutePath()); + writer.writeUint32Big(skinMesh.boneNames.size()); + for (const std::string& boneName : skinMesh.boneNames) + writer.writeString(boneName); - writer.writeUint32Big(skinMesh.skins.size()); - for (const std::vector skin : skinMesh.skins) - { - writer.writeUint32Big(skin.size()); - for (const DNACMDL::Mesh::SkinBind& bind : skin) - { - writer.writeUint32Big(bind.boneIdx); - writer.writeFloatBig(bind.weight); - } - writer.writeUint32Big(*vertCountIt++); - } - writer.writeUint32Big(skinMesh.pos.size()); - writer.writeUint32Big(skinMesh.norm.size()); + writer.writeUint32Big(skinMesh.skins.size()); + for (const std::vector skin : skinMesh.skins) { + writer.writeUint32Big(skin.size()); + for (const DNACMDL::Mesh::SkinBind& bind : skin) { + writer.writeUint32Big(bind.boneIdx); + writer.writeFloatBig(bind.weight); + } + writer.writeUint32Big(*vertCountIt++); } - else if (!DNACMDL::WriteCMDL(outPath, inPath, mesh)) - return false; - return true; + writer.writeUint32Big(skinMesh.pos.size()); + writer.writeUint32Big(skinMesh.norm.size()); + } else if (!DNACMDL::WriteCMDL(outPath, inPath, mesh)) + return false; + return true; } -bool CMDL::HMDLCook(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNACMDL::Mesh& mesh) -{ - hecl::blender::PoolSkinIndex poolSkinIndex; - if (mesh.skins.size()) - { - if (!DNACMDL::WriteHMDLCMDL( - outPath, inPath, mesh, poolSkinIndex)) - return false; +bool CMDL::HMDLCook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNACMDL::Mesh& mesh) { + hecl::blender::PoolSkinIndex poolSkinIndex; + if (mesh.skins.size()) { + if (!DNACMDL::WriteHMDLCMDL(outPath, inPath, mesh, poolSkinIndex)) + return false; - /* Output skinning intermediate */ - athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".skinint")).getAbsolutePath()); - writer.writeUint32Big(mesh.skinBanks.banks.size()); - for (const DNACMDL::Mesh::SkinBanks::Bank& sb : mesh.skinBanks.banks) - { - writer.writeUint32Big(sb.m_boneIdxs.size()); - for (uint32_t bind : sb.m_boneIdxs) - writer.writeUint32Big(bind); - } - writer.writeUint32Big(mesh.boneNames.size()); - for (const std::string& boneName : mesh.boneNames) - writer.writeString(boneName); - - /* CVirtualBone structure just like original (for CPU skinning) */ - writer.writeUint32Big(mesh.skins.size()); - for (auto& s : mesh.skins) - { - writer.writeUint32Big(s.size()); - for (auto& b : s) - { - writer.writeUint32Big(b.boneIdx); - writer.writeFloatBig(b.weight); - } - } - - /* Write indirection table mapping pool verts to CVirtualBones */ - writer.writeUint32Big(poolSkinIndex.m_poolSz); - for (uint32_t i=0 ; i( - outPath, inPath, mesh, poolSkinIndex)) - return false; - return true; + writer.writeUint32Big(mesh.boneNames.size()); + for (const std::string& boneName : mesh.boneNames) + writer.writeString(boneName); + + /* CVirtualBone structure just like original (for CPU skinning) */ + writer.writeUint32Big(mesh.skins.size()); + for (auto& s : mesh.skins) { + writer.writeUint32Big(s.size()); + for (auto& b : s) { + writer.writeUint32Big(b.boneIdx); + writer.writeFloatBig(b.weight); + } + } + + /* Write indirection table mapping pool verts to CVirtualBones */ + writer.writeUint32Big(poolSkinIndex.m_poolSz); + for (uint32_t i = 0; i < poolSkinIndex.m_poolSz; ++i) + writer.writeUint32Big(poolSkinIndex.m_poolToSkinIndex[i]); + } else if (!DNACMDL::WriteHMDLCMDL(outPath, inPath, mesh, + poolSkinIndex)) + return false; + return true; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CMDL.hpp b/DataSpec/DNAMP1/CMDL.hpp index 36015d3ad..5a18bbadd 100644 --- a/DataSpec/DNAMP1/CMDL.hpp +++ b/DataSpec/DNAMP1/CMDL.hpp @@ -9,36 +9,21 @@ #include -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CMDL -{ - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged); +struct CMDL { + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged); - static void Name(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - PAKRouter& pakRouter, - PAK::Entry& entry) - { - DNACMDL::NameCMDL, MaterialSet>(rs, pakRouter, entry, dataSpec); - } + static void Name(const SpecBase& dataSpec, PAKEntryReadStream& rs, PAKRouter& pakRouter, + PAK::Entry& entry) { + DNACMDL::NameCMDL, MaterialSet>(rs, pakRouter, entry, dataSpec); + } - static bool Cook(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNACMDL::Mesh& mesh); + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNACMDL::Mesh& mesh); - static bool HMDLCook(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const DNACMDL::Mesh& mesh); + static bool HMDLCook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const DNACMDL::Mesh& mesh); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CMDLMaterials.cpp b/DataSpec/DNAMP1/CMDLMaterials.cpp index ee90ca8e9..027c45aeb 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.cpp +++ b/DataSpec/DNAMP1/CMDLMaterials.cpp @@ -4,1392 +4,1237 @@ using Stream = hecl::blender::PyOutStream; -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { using Material = MaterialSet::Material; -void MaterialSet::RegisterMaterialProps(Stream& out) -{ - out << "bpy.types.Material.retro_depth_sort = bpy.props.BoolProperty(name='Retro: Transparent Depth Sort')\n" - "bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Punchthrough Alpha')\n" - "bpy.types.Material.retro_samus_reflection = bpy.props.BoolProperty(name='Retro: Samus Reflection')\n" - "bpy.types.Material.retro_depth_write = bpy.props.BoolProperty(name='Retro: Depth Write')\n" - "bpy.types.Material.retro_samus_reflection_persp = bpy.props.BoolProperty(name='Retro: Samus Reflection Perspective')\n" - "bpy.types.Material.retro_shadow_occluder = bpy.props.BoolProperty(name='Retro: Shadow Occluder')\n" - "bpy.types.Material.retro_samus_reflection_indirect = bpy.props.BoolProperty(name='Retro: Samus Reflection Indirect Texture')\n" - "bpy.types.Material.retro_lightmapped = bpy.props.BoolProperty(name='Retro: Lightmapped')\n" - "\n"; +void MaterialSet::RegisterMaterialProps(Stream& out) { + out << "bpy.types.Material.retro_depth_sort = bpy.props.BoolProperty(name='Retro: Transparent Depth Sort')\n" + "bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Punchthrough Alpha')\n" + "bpy.types.Material.retro_samus_reflection = bpy.props.BoolProperty(name='Retro: Samus Reflection')\n" + "bpy.types.Material.retro_depth_write = bpy.props.BoolProperty(name='Retro: Depth Write')\n" + "bpy.types.Material.retro_samus_reflection_persp = bpy.props.BoolProperty(name='Retro: Samus Reflection " + "Perspective')\n" + "bpy.types.Material.retro_shadow_occluder = bpy.props.BoolProperty(name='Retro: Shadow Occluder')\n" + "bpy.types.Material.retro_samus_reflection_indirect = bpy.props.BoolProperty(name='Retro: Samus Reflection " + "Indirect Texture')\n" + "bpy.types.Material.retro_lightmapped = bpy.props.BoolProperty(name='Retro: Lightmapped')\n" + "\n"; } -void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t texIdx) -{ - char mtxLabel[64]; - if (mtxIdx == -1) - strncpy(mtxLabel, "IDENTITY", 64); - else - snprintf(mtxLabel, 64, "MTX_%u", mtxIdx); +void Material::AddTexture(Stream& out, GX::TexGenSrc type, int mtxIdx, uint32_t texIdx) { + char mtxLabel[64]; + if (mtxIdx == -1) + strncpy(mtxLabel, "IDENTITY", 64); + else + snprintf(mtxLabel, 64, "MTX_%u", mtxIdx); - out.format("# Texture\n" - "tex_uv_node = new_nodetree.nodes.new('ShaderNodeGeometry')\n" - "tex_uv_node.label = '%s'\n" - "tex_node = new_nodetree.nodes.new('ShaderNodeTexture')\n" - "tex_node.label = 'Texture %u'\n" - "texture_nodes.append(tex_node)\n" - "gridder.place_node(tex_uv_node, 1)\n" - "gridder.place_node(tex_node, 1)\n" - "tex_uv_node.location[0] -= 120\n" - "tex_node.location[0] += 120\n" - "tex_node.location[1] += 176\n", mtxLabel, texIdx); + out.format( + "# Texture\n" + "tex_uv_node = new_nodetree.nodes.new('ShaderNodeGeometry')\n" + "tex_uv_node.label = '%s'\n" + "tex_node = new_nodetree.nodes.new('ShaderNodeTexture')\n" + "tex_node.label = 'Texture %u'\n" + "texture_nodes.append(tex_node)\n" + "gridder.place_node(tex_uv_node, 1)\n" + "gridder.place_node(tex_node, 1)\n" + "tex_uv_node.location[0] -= 120\n" + "tex_node.location[0] += 120\n" + "tex_node.location[1] += 176\n", + mtxLabel, texIdx); - if (texIdx != 0xff) - out.format("tex_node.texture = tex_maps[%u]\n", texIdx); + if (texIdx != 0xff) + out.format("tex_node.texture = tex_maps[%u]\n", texIdx); - if (type == GX::TG_POS) - out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['View'], tex_node.inputs['Vector']))\n"); - else if (type == GX::TG_NRM) - out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n"); - else if (type >= GX::TG_TEX0 && type <= GX::TG_TEX7) - { - uint8_t texIdx = type - GX::TG_TEX0; - out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" - "tex_uv_node.uv_layer = 'UV_%u'\n", texIdx); - } - - out << "\n"; + if (type == GX::TG_POS) + out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['View'], tex_node.inputs['Vector']))\n"); + else if (type == GX::TG_NRM) + out.format("tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['Normal'], tex_node.inputs['Vector']))\n"); + else if (type >= GX::TG_TEX0 && type <= GX::TG_TEX7) { + uint8_t texIdx = type - GX::TG_TEX0; + out.format( + "tex_links.append(new_nodetree.links.new(tex_uv_node.outputs['UV'], tex_node.inputs['Vector']))\n" + "tex_uv_node.uv_layer = 'UV_%u'\n", + texIdx); + } + out << "\n"; } -void Material::AddTextureAnim(Stream& out, - UVAnimation::Mode type, - unsigned idx, const float* vals) -{ - switch (type) - { - case UVAnimation::Mode::MvInvNoTranslation: - out.format("for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_%u':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode0NodeN']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", - idx); - break; - case UVAnimation::Mode::MvInv: - out.format("for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_%u':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode1NodeN']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", - idx); - break; - case UVAnimation::Mode::Scroll: - out.format("for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_%u':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode2Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = (%f,%f,0)\n" - " node.inputs[2].default_value = (%f,%f,0)\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", - idx, vals[0], vals[1], vals[2], vals[3]); - break; - case UVAnimation::Mode::Rotation: - out.format("for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_%u':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode3Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = %f\n" - " node.inputs[2].default_value = %f\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", - idx, vals[0], vals[1]); - break; - case UVAnimation::Mode::HStrip: - out.format("for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_%u':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode4Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = %f\n" - " node.inputs[2].default_value = %f\n" - " node.inputs[3].default_value = %f\n" - " node.inputs[4].default_value = %f\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", - idx, vals[0], vals[1], vals[2], vals[3]); - break; - case UVAnimation::Mode::VStrip: - out.format("for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_%u':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode5Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = %f\n" - " node.inputs[2].default_value = %f\n" - " node.inputs[3].default_value = %f\n" - " node.inputs[4].default_value = %f\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", - idx, vals[0], vals[1], vals[2], vals[3]); - break; - case UVAnimation::Mode::Model: - out.format("for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_%u':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode6NodeN']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", - idx); - break; - case UVAnimation::Mode::CylinderEnvironment: - out.format("for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_%u':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode7NodeN']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = %f\n" - " node.inputs[2].default_value = %f\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", - idx, vals[0], vals[1]); - break; - case UVAnimation::Mode::Eight: - out.format("for link in list(tex_links):\n" - " if link.from_node.label == 'MTX_%u':\n" - " tex_links.remove(link)\n" - " soc_from = link.from_socket\n" - " soc_to = link.to_socket\n" - " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" - " node.node_tree = bpy.data.node_groups['RetroUVMode8Node']\n" - " node.location[0] = link.from_node.location[0] + 50\n" - " node.location[1] = link.from_node.location[1] - 50\n" - " node.inputs[1].default_value = %f\n" - " node.inputs[2].default_value = %f\n" - " node.inputs[3].default_value = %f\n" - " node.inputs[4].default_value = %f\n" - " node.inputs[5].default_value = %f\n" - " node.inputs[6].default_value = %f\n" - " node.inputs[7].default_value = %f\n" - " node.inputs[8].default_value = %f\n" - " node.inputs[9].default_value = %f\n" - " new_nodetree.links.remove(link)\n" - " new_nodetree.links.new(soc_from, node.inputs[0])\n" - " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", - idx, vals[0], vals[1], vals[2], vals[3], - vals[4], vals[5], vals[6], vals[7], vals[8]); - break; - default: break; - } +void Material::AddTextureAnim(Stream& out, UVAnimation::Mode type, unsigned idx, const float* vals) { + switch (type) { + case UVAnimation::Mode::MvInvNoTranslation: + out.format( + "for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_%u':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode0NodeN']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", + idx); + break; + case UVAnimation::Mode::MvInv: + out.format( + "for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_%u':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode1NodeN']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", + idx); + break; + case UVAnimation::Mode::Scroll: + out.format( + "for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_%u':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode2Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = (%f,%f,0)\n" + " node.inputs[2].default_value = (%f,%f,0)\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", + idx, vals[0], vals[1], vals[2], vals[3]); + break; + case UVAnimation::Mode::Rotation: + out.format( + "for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_%u':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode3Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = %f\n" + " node.inputs[2].default_value = %f\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", + idx, vals[0], vals[1]); + break; + case UVAnimation::Mode::HStrip: + out.format( + "for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_%u':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode4Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = %f\n" + " node.inputs[2].default_value = %f\n" + " node.inputs[3].default_value = %f\n" + " node.inputs[4].default_value = %f\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", + idx, vals[0], vals[1], vals[2], vals[3]); + break; + case UVAnimation::Mode::VStrip: + out.format( + "for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_%u':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode5Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = %f\n" + " node.inputs[2].default_value = %f\n" + " node.inputs[3].default_value = %f\n" + " node.inputs[4].default_value = %f\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", + idx, vals[0], vals[1], vals[2], vals[3]); + break; + case UVAnimation::Mode::Model: + out.format( + "for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_%u':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode6NodeN']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", + idx); + break; + case UVAnimation::Mode::CylinderEnvironment: + out.format( + "for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_%u':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode7NodeN']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = %f\n" + " node.inputs[2].default_value = %f\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", + idx, vals[0], vals[1]); + break; + case UVAnimation::Mode::Eight: + out.format( + "for link in list(tex_links):\n" + " if link.from_node.label == 'MTX_%u':\n" + " tex_links.remove(link)\n" + " soc_from = link.from_socket\n" + " soc_to = link.to_socket\n" + " node = new_nodetree.nodes.new('ShaderNodeGroup')\n" + " node.node_tree = bpy.data.node_groups['RetroUVMode8Node']\n" + " node.location[0] = link.from_node.location[0] + 50\n" + " node.location[1] = link.from_node.location[1] - 50\n" + " node.inputs[1].default_value = %f\n" + " node.inputs[2].default_value = %f\n" + " node.inputs[3].default_value = %f\n" + " node.inputs[4].default_value = %f\n" + " node.inputs[5].default_value = %f\n" + " node.inputs[6].default_value = %f\n" + " node.inputs[7].default_value = %f\n" + " node.inputs[8].default_value = %f\n" + " node.inputs[9].default_value = %f\n" + " new_nodetree.links.remove(link)\n" + " new_nodetree.links.new(soc_from, node.inputs[0])\n" + " new_nodetree.links.new(node.outputs[0], soc_to)\n\n", + idx, vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], vals[8]); + break; + default: + break; + } } -void Material::AddKcolor(Stream& out, const GX::Color& col, unsigned idx) -{ - out.format("# KColor\n" - "kc_node = new_nodetree.nodes.new('ShaderNodeRGB')\n" - "kc_node.label = 'KColor %u'\n" - "kc_node.outputs['Color'].default_value[0] = %f\n" - "kc_node.outputs['Color'].default_value[1] = %f\n" - "kc_node.outputs['Color'].default_value[2] = %f\n" - "kc_node.outputs['Color'].default_value[3] = %f\n" - "gridder.place_node(kc_node, 1)\n" - "\n" - "ka_node = new_nodetree.nodes.new('ShaderNodeValue')\n" - "ka_node.label = 'KAlpha %u'\n" - "ka_node.outputs['Value'].default_value = %f\n" - "gridder.place_node(ka_node, 1)\n" - "\n" - "kcolor_nodes.append((kc_node,ka_node))\n" - "\n", - idx, - (float)col.color[0] / (float)0xff, (float)col.color[1] / (float)0xff, - (float)col.color[2] / (float)0xff, (float)col.color[3] / (float)0xff, - idx, - (float)col.color[3] / (float)0xff); +void Material::AddKcolor(Stream& out, const GX::Color& col, unsigned idx) { + out.format( + "# KColor\n" + "kc_node = new_nodetree.nodes.new('ShaderNodeRGB')\n" + "kc_node.label = 'KColor %u'\n" + "kc_node.outputs['Color'].default_value[0] = %f\n" + "kc_node.outputs['Color'].default_value[1] = %f\n" + "kc_node.outputs['Color'].default_value[2] = %f\n" + "kc_node.outputs['Color'].default_value[3] = %f\n" + "gridder.place_node(kc_node, 1)\n" + "\n" + "ka_node = new_nodetree.nodes.new('ShaderNodeValue')\n" + "ka_node.label = 'KAlpha %u'\n" + "ka_node.outputs['Value'].default_value = %f\n" + "gridder.place_node(ka_node, 1)\n" + "\n" + "kcolor_nodes.append((kc_node,ka_node))\n" + "\n", + idx, (float)col.color[0] / (float)0xff, (float)col.color[1] / (float)0xff, (float)col.color[2] / (float)0xff, + (float)col.color[3] / (float)0xff, idx, (float)col.color[3] / (float)0xff); } -void Material::AddDynamicColor(Stream& out, unsigned idx) -{ - out.format("# Dynamic Color\n" - "node_name = 'DYNAMIC_C_%u'\n" - "if node_name not in new_nodetree.nodes:\n" - " dyn_c_node = new_nodetree.nodes.new('ShaderNodeRGB')\n" - " dyn_c_node.name = node_name\n" - " dyn_c_node.label = 'DYNAMIC_%u'\n" - " dyn_c_node.outputs['Color'].default_value = (1.0,1.0,1.0,1.0)\n" - " gridder.place_node(dyn_c_node, 1)\n" - "\n", - idx, idx); +void Material::AddDynamicColor(Stream& out, unsigned idx) { + out.format( + "# Dynamic Color\n" + "node_name = 'DYNAMIC_C_%u'\n" + "if node_name not in new_nodetree.nodes:\n" + " dyn_c_node = new_nodetree.nodes.new('ShaderNodeRGB')\n" + " dyn_c_node.name = node_name\n" + " dyn_c_node.label = 'DYNAMIC_%u'\n" + " dyn_c_node.outputs['Color'].default_value = (1.0,1.0,1.0,1.0)\n" + " gridder.place_node(dyn_c_node, 1)\n" + "\n", + idx, idx); } -void Material::AddDynamicAlpha(Stream& out, unsigned idx) -{ - out.format("# Dynamic Alpha\n" - "node_name = 'DYNAMIC_A_%u'\n" - "if node_name not in new_nodetree.nodes:\n" - " dyn_a_node = new_nodetree.nodes.new('ShaderNodeValue')\n" - " dyn_a_node.name = node_name\n" - " dyn_a_node.label = 'DYNAMIC_%u'\n" - " dyn_a_node.outputs['Value'].default_value = 1.0\n" - " gridder.place_node(dyn_a_node, 1)\n" - "\n", - idx, idx); +void Material::AddDynamicAlpha(Stream& out, unsigned idx) { + out.format( + "# Dynamic Alpha\n" + "node_name = 'DYNAMIC_A_%u'\n" + "if node_name not in new_nodetree.nodes:\n" + " dyn_a_node = new_nodetree.nodes.new('ShaderNodeValue')\n" + " dyn_a_node.name = node_name\n" + " dyn_a_node.label = 'DYNAMIC_%u'\n" + " dyn_a_node.outputs['Value'].default_value = 1.0\n" + " gridder.place_node(dyn_a_node, 1)\n" + "\n", + idx, idx); } +enum class Combiner { Add, Sub, Mult }; +static void AddColorCombiner(Stream& out, Combiner type, const char* a, const char* b, const char* v) { + out << "combiner_node = new_nodetree.nodes.new('ShaderNodeMixRGB')\n" + "combiner_node.inputs[0].default_value = 1.0\n" + "gridder.place_node_right(combiner_node, 2, 0)\n"; + if (type == Combiner::Add) + out << "combiner_node.blend_type = 'ADD'\n"; + else if (type == Combiner::Sub) + out << "combiner_node.blend_type = 'SUBTRACT'\n"; + else if (type == Combiner::Mult) + out << "combiner_node.blend_type = 'MULTIPLY'\n"; -enum class Combiner -{ - Add, - Sub, - Mult -}; -static void AddColorCombiner(Stream& out, Combiner type, - const char* a, const char* b, const char* v) -{ - out << "combiner_node = new_nodetree.nodes.new('ShaderNodeMixRGB')\n" - "combiner_node.inputs[0].default_value = 1.0\n" - "gridder.place_node_right(combiner_node, 2, 0)\n"; - if (type == Combiner::Add) - out << "combiner_node.blend_type = 'ADD'\n"; - else if (type == Combiner::Sub) - out << "combiner_node.blend_type = 'SUBTRACT'\n"; - else if (type == Combiner::Mult) - out << "combiner_node.blend_type = 'MULTIPLY'\n"; + if (a) { + if (!strcmp(a, "ZERO")) + out << "combiner_node.inputs['Color1'].default_value = (0.0, 0.0, 0.0, 0.0)\n"; + else if (!strcmp(a, "HALF")) + out << "combiner_node.inputs['Color1'].default_value = (0.5, 0.5, 0.5, 0.5)\n"; + else if (!strcmp(a, "ONE")) + out << "combiner_node.inputs['Color1'].default_value = (1.0, 1.0, 1.0, 1.0)\n"; + else if (!strcmp(a, "D0")) { + Material::AddDynamicColor(out, 0); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_0'].outputs['Color'], " + "combiner_node.inputs['Color1'])\n"; + } else if (!strcmp(a, "D1")) { + Material::AddDynamicColor(out, 1); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_1'].outputs['Color'], " + "combiner_node.inputs['Color1'])\n"; + } else if (!strcmp(a, "D2")) { + Material::AddDynamicColor(out, 2); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_2'].outputs['Color'], " + "combiner_node.inputs['Color1'])\n"; + } else if (!strlen(a)) { + } else + out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color1'])\n", a); + } - if (a) - { - if (!strcmp(a, "ZERO")) - out << "combiner_node.inputs['Color1'].default_value = (0.0, 0.0, 0.0, 0.0)\n"; - else if (!strcmp(a, "HALF")) - out << "combiner_node.inputs['Color1'].default_value = (0.5, 0.5, 0.5, 0.5)\n"; - else if (!strcmp(a, "ONE")) - out << "combiner_node.inputs['Color1'].default_value = (1.0, 1.0, 1.0, 1.0)\n"; - else if (!strcmp(a, "D0")) - { - Material::AddDynamicColor(out, 0); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_0'].outputs['Color'], combiner_node.inputs['Color1'])\n"; - } - else if (!strcmp(a, "D1")) - { - Material::AddDynamicColor(out, 1); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_1'].outputs['Color'], combiner_node.inputs['Color1'])\n"; - } - else if (!strcmp(a, "D2")) - { - Material::AddDynamicColor(out, 2); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_2'].outputs['Color'], combiner_node.inputs['Color1'])\n"; - } - else if (!strlen(a)) - {} - else - out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color1'])\n", a); - } + if (b) { + if (!strcmp(b, "ZERO")) + out << "combiner_node.inputs['Color2'].default_value = (0.0, 0.0, 0.0, 0.0)\n"; + else if (!strcmp(b, "HALF")) + out << "combiner_node.inputs['Color2'].default_value = (0.5, 0.5, 0.5, 0.5)\n"; + else if (!strcmp(b, "ONE")) + out << "combiner_node.inputs['Color2'].default_value = (1.0, 1.0, 1.0, 1.0)\n"; + else if (!strcmp(b, "D0")) { + Material::AddDynamicColor(out, 0); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_0'].outputs['Color'], " + "combiner_node.inputs['Color2'])\n"; + } else if (!strcmp(b, "D1")) { + Material::AddDynamicColor(out, 1); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_1'].outputs['Color'], " + "combiner_node.inputs['Color2'])\n"; + } else if (!strcmp(b, "D2")) { + Material::AddDynamicColor(out, 2); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_2'].outputs['Color'], " + "combiner_node.inputs['Color2'])\n"; + } else if (!strlen(b)) { + } else + out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color2'])\n", b); + } - if (b) - { - if (!strcmp(b, "ZERO")) - out << "combiner_node.inputs['Color2'].default_value = (0.0, 0.0, 0.0, 0.0)\n"; - else if (!strcmp(b, "HALF")) - out << "combiner_node.inputs['Color2'].default_value = (0.5, 0.5, 0.5, 0.5)\n"; - else if (!strcmp(b, "ONE")) - out << "combiner_node.inputs['Color2'].default_value = (1.0, 1.0, 1.0, 1.0)\n"; - else if (!strcmp(b, "D0")) - { - Material::AddDynamicColor(out, 0); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_0'].outputs['Color'], combiner_node.inputs['Color2'])\n"; - } - else if (!strcmp(b, "D1")) - { - Material::AddDynamicColor(out, 1); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_1'].outputs['Color'], combiner_node.inputs['Color2'])\n"; - } - else if (!strcmp(b, "D2")) - { - Material::AddDynamicColor(out, 2); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_C_2'].outputs['Color'], combiner_node.inputs['Color2'])\n"; - } - else if (!strlen(b)) - {} - else - out.format("new_nodetree.links.new(%s, combiner_node.inputs['Color2'])\n", b); - } + if (v) + out.format("new_nodetree.links.new(combiner_node.outputs['Color'], %s)\n", v); - if (v) - out.format("new_nodetree.links.new(combiner_node.outputs['Color'], %s)\n", v); - - out << "color_combiner_sockets.append(combiner_node.outputs['Color'])\n\n"; + out << "color_combiner_sockets.append(combiner_node.outputs['Color'])\n\n"; } -static void AddAlphaCombiner(Stream& out, Combiner type, - const char* a, const char* b, const char* v) -{ - out << "combiner_node = new_nodetree.nodes.new('ShaderNodeMath')\n" - "gridder.place_node_right(combiner_node, 2, 1)\n"; - if (type == Combiner::Add) - out << "combiner_node.operation = 'ADD'\n"; - else if (type == Combiner::Sub) - out << "combiner_node.operation = 'SUBTRACT'\n"; - else if (type == Combiner::Mult) - out << "combiner_node.operation = 'MULTIPLY'\n"; +static void AddAlphaCombiner(Stream& out, Combiner type, const char* a, const char* b, const char* v) { + out << "combiner_node = new_nodetree.nodes.new('ShaderNodeMath')\n" + "gridder.place_node_right(combiner_node, 2, 1)\n"; + if (type == Combiner::Add) + out << "combiner_node.operation = 'ADD'\n"; + else if (type == Combiner::Sub) + out << "combiner_node.operation = 'SUBTRACT'\n"; + else if (type == Combiner::Mult) + out << "combiner_node.operation = 'MULTIPLY'\n"; - if (a) - { - if (!strcmp(a, "ZERO")) - out << "combiner_node.inputs[0].default_value = 0.0\n"; - else if (!strcmp(a, "HALF")) - out << "combiner_node.inputs[0].default_value = 0.5\n"; - else if (!strcmp(a, "ONE")) - out << "combiner_node.inputs[0].default_value = 1.0\n"; - else if (!strcmp(a, "D0")) - { - Material::AddDynamicAlpha(out, 0); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_0'].outputs[0], combiner_node.inputs[0])\n"; - } - else if (!strcmp(a, "D1")) - { - Material::AddDynamicAlpha(out, 1); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_1'].outputs[0], combiner_node.inputs[0])\n"; - } - else if (!strcmp(a, "D2")) - { - Material::AddDynamicAlpha(out, 2); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_2'].outputs[0], combiner_node.inputs[0])\n"; - } - else - out.format("new_nodetree.links.new(%s, combiner_node.inputs[0])\n", a); - } + if (a) { + if (!strcmp(a, "ZERO")) + out << "combiner_node.inputs[0].default_value = 0.0\n"; + else if (!strcmp(a, "HALF")) + out << "combiner_node.inputs[0].default_value = 0.5\n"; + else if (!strcmp(a, "ONE")) + out << "combiner_node.inputs[0].default_value = 1.0\n"; + else if (!strcmp(a, "D0")) { + Material::AddDynamicAlpha(out, 0); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_0'].outputs[0], combiner_node.inputs[0])\n"; + } else if (!strcmp(a, "D1")) { + Material::AddDynamicAlpha(out, 1); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_1'].outputs[0], combiner_node.inputs[0])\n"; + } else if (!strcmp(a, "D2")) { + Material::AddDynamicAlpha(out, 2); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_2'].outputs[0], combiner_node.inputs[0])\n"; + } else + out.format("new_nodetree.links.new(%s, combiner_node.inputs[0])\n", a); + } - if (b) - { - if (!strcmp(b, "ZERO")) - out << "combiner_node.inputs[1].default_value = 0.0\n"; - else if (!strcmp(b, "HALF")) - out << "combiner_node.inputs[1].default_value = 0.5\n"; - else if (!strcmp(b, "ONE")) - out << "combiner_node.inputs[1].default_value = 1.0\n"; - else if (!strcmp(b, "D0")) - { - Material::AddDynamicAlpha(out, 0); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_0'].outputs[0], combiner_node.inputs[1])\n"; - } - else if (!strcmp(b, "D1")) - { - Material::AddDynamicAlpha(out, 1); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_1'].outputs[0], combiner_node.inputs[1])\n"; - } - else if (!strcmp(b, "D2")) - { - Material::AddDynamicAlpha(out, 2); - out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_2'].outputs[0], combiner_node.inputs[1])\n"; - } - else - out.format("new_nodetree.links.new(%s, combiner_node.inputs[1])\n", b); - } + if (b) { + if (!strcmp(b, "ZERO")) + out << "combiner_node.inputs[1].default_value = 0.0\n"; + else if (!strcmp(b, "HALF")) + out << "combiner_node.inputs[1].default_value = 0.5\n"; + else if (!strcmp(b, "ONE")) + out << "combiner_node.inputs[1].default_value = 1.0\n"; + else if (!strcmp(b, "D0")) { + Material::AddDynamicAlpha(out, 0); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_0'].outputs[0], combiner_node.inputs[1])\n"; + } else if (!strcmp(b, "D1")) { + Material::AddDynamicAlpha(out, 1); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_1'].outputs[0], combiner_node.inputs[1])\n"; + } else if (!strcmp(b, "D2")) { + Material::AddDynamicAlpha(out, 2); + out << "new_nodetree.links.new(new_nodetree.nodes['DYNAMIC_A_2'].outputs[0], combiner_node.inputs[1])\n"; + } else + out.format("new_nodetree.links.new(%s, combiner_node.inputs[1])\n", b); + } - if (v) - out.format("new_nodetree.links.new(combiner_node.outputs[0], %s)\n", v); + if (v) + out.format("new_nodetree.links.new(combiner_node.outputs[0], %s)\n", v); - out << "alpha_combiner_sockets.append(combiner_node.outputs[0])\n\n"; + out << "alpha_combiner_sockets.append(combiner_node.outputs[0])\n\n"; } -static void TranslateColorSocket(char* socketOut, GX::TevColorArg arg, - GX::TevKColorSel kcolor, - const MaterialSet::Material::TEVStageTexInfo& stageTex, - char c_regs[4][64], char a_regs[4][64]) { - if (arg == GX::CC_ZERO) - strcpy(socketOut, "ZERO"); - else if (arg == GX::CC_HALF) - strcpy(socketOut, "HALF"); - else if (arg == GX::CC_ONE) - strcpy(socketOut, "ONE"); - else if (arg == GX::CC_TEXC) - { - if (stageTex.tcgSlot == 0xff) - strcpy(socketOut, "ONE"); - else - sprintf(socketOut, "texture_nodes[%u].outputs['Color']", stageTex.tcgSlot); - } - else if (arg == GX::CC_TEXA) { - if (stageTex.tcgSlot == 0xff) - strcpy(socketOut, "ONE"); - else - sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot); - } - else if (arg == GX::CC_RASC) - strcpy(socketOut, "material_node.outputs['Color']"); - else if (arg == GX::CC_RASA) - strcpy(socketOut, "material_node.outputs['Alpha']"); - else if (arg == GX::CC_KONST) - { - int kreg = (kcolor - GX::TEV_KCSEL_K0) % 4; - if (kcolor < GX::TEV_KCSEL_K0) - strcpy(socketOut, "ONE"); - else if (kreg == 0) - strcpy(socketOut, "kcolor_nodes[0][0].outputs[0]"); - else if (kreg == 1) - strcpy(socketOut, "kcolor_nodes[1][0].outputs[0]"); - else if (kreg == 2) - strcpy(socketOut, "kcolor_nodes[2][0].outputs[0]"); - else if (kreg == 3) - strcpy(socketOut, "kcolor_nodes[3][0].outputs[0]"); - else - strcpy(socketOut, "ONE"); - } - else if (arg == GX::CC_CPREV) - strcpy(socketOut, c_regs[GX::TEVPREV]); - else if (arg == GX::CC_APREV) - strcpy(socketOut, a_regs[GX::TEVPREV]); - else if (arg == GX::CC_C0) - strcpy(socketOut, c_regs[GX::TEVREG0]); - else if (arg == GX::CC_A0) - strcpy(socketOut, a_regs[GX::TEVREG0]); - else if (arg == GX::CC_C1) - strcpy(socketOut, c_regs[GX::TEVREG1]); - else if (arg == GX::CC_A1) - strcpy(socketOut, a_regs[GX::TEVREG1]); - else if (arg == GX::CC_C2) - strcpy(socketOut, c_regs[GX::TEVREG2]); - else if (arg == GX::CC_A2) - strcpy(socketOut, a_regs[GX::TEVREG2]); -} - -static void TranslateAlphaSocket(char* socketOut, GX::TevAlphaArg arg, - GX::TevKAlphaSel kalpha, - const MaterialSet::Material::TEVStageTexInfo& stageTex, +static void TranslateColorSocket(char* socketOut, GX::TevColorArg arg, GX::TevKColorSel kcolor, + const MaterialSet::Material::TEVStageTexInfo& stageTex, char c_regs[4][64], char a_regs[4][64]) { - if (arg == GX::CA_ZERO) - strcpy(socketOut, "ZERO"); - else if (arg == GX::CA_TEXA) - { - if (stageTex.tcgSlot == 0xff) - strcpy(socketOut, "ONE"); - else - sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot); - } - else if (arg == GX::CA_RASA) - strcpy(socketOut, "material_node.outputs['Alpha']"); - else if (arg == GX::CA_KONST) { - int kreg = kalpha - GX::TEV_KASEL_K0_A; - if (kreg == 0) - strcpy(socketOut, "kcolor_nodes[0][1].outputs[0]"); - else if (kreg == 1) - strcpy(socketOut, "kcolor_nodes[1][1].outputs[0]"); - else if (kreg == 2) - strcpy(socketOut, "kcolor_nodes[2][1].outputs[0]"); - else if (kreg == 3) - strcpy(socketOut, "kcolor_nodes[3][1].outputs[0]"); - else - strcpy(socketOut, "ONE"); - } - else if (arg == GX::CA_APREV) - strcpy(socketOut, a_regs[GX::TEVPREV]); - else if (arg == GX::CA_A0) - strcpy(socketOut, a_regs[GX::TEVREG0]); - else if (arg == GX::CA_A1) - strcpy(socketOut, a_regs[GX::TEVREG1]); - else if (arg == GX::CA_A2) - strcpy(socketOut, a_regs[GX::TEVREG2]); + if (arg == GX::CC_ZERO) + strcpy(socketOut, "ZERO"); + else if (arg == GX::CC_HALF) + strcpy(socketOut, "HALF"); + else if (arg == GX::CC_ONE) + strcpy(socketOut, "ONE"); + else if (arg == GX::CC_TEXC) { + if (stageTex.tcgSlot == 0xff) + strcpy(socketOut, "ONE"); + else + sprintf(socketOut, "texture_nodes[%u].outputs['Color']", stageTex.tcgSlot); + } else if (arg == GX::CC_TEXA) { + if (stageTex.tcgSlot == 0xff) + strcpy(socketOut, "ONE"); + else + sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot); + } else if (arg == GX::CC_RASC) + strcpy(socketOut, "material_node.outputs['Color']"); + else if (arg == GX::CC_RASA) + strcpy(socketOut, "material_node.outputs['Alpha']"); + else if (arg == GX::CC_KONST) { + int kreg = (kcolor - GX::TEV_KCSEL_K0) % 4; + if (kcolor < GX::TEV_KCSEL_K0) + strcpy(socketOut, "ONE"); + else if (kreg == 0) + strcpy(socketOut, "kcolor_nodes[0][0].outputs[0]"); + else if (kreg == 1) + strcpy(socketOut, "kcolor_nodes[1][0].outputs[0]"); + else if (kreg == 2) + strcpy(socketOut, "kcolor_nodes[2][0].outputs[0]"); + else if (kreg == 3) + strcpy(socketOut, "kcolor_nodes[3][0].outputs[0]"); + else + strcpy(socketOut, "ONE"); + } else if (arg == GX::CC_CPREV) + strcpy(socketOut, c_regs[GX::TEVPREV]); + else if (arg == GX::CC_APREV) + strcpy(socketOut, a_regs[GX::TEVPREV]); + else if (arg == GX::CC_C0) + strcpy(socketOut, c_regs[GX::TEVREG0]); + else if (arg == GX::CC_A0) + strcpy(socketOut, a_regs[GX::TEVREG0]); + else if (arg == GX::CC_C1) + strcpy(socketOut, c_regs[GX::TEVREG1]); + else if (arg == GX::CC_A1) + strcpy(socketOut, a_regs[GX::TEVREG1]); + else if (arg == GX::CC_C2) + strcpy(socketOut, c_regs[GX::TEVREG2]); + else if (arg == GX::CC_A2) + strcpy(socketOut, a_regs[GX::TEVREG2]); +} + +static void TranslateAlphaSocket(char* socketOut, GX::TevAlphaArg arg, GX::TevKAlphaSel kalpha, + const MaterialSet::Material::TEVStageTexInfo& stageTex, char a_regs[4][64]) { + if (arg == GX::CA_ZERO) + strcpy(socketOut, "ZERO"); + else if (arg == GX::CA_TEXA) { + if (stageTex.tcgSlot == 0xff) + strcpy(socketOut, "ONE"); + else + sprintf(socketOut, "texture_nodes[%u].outputs['Value']", stageTex.tcgSlot); + } else if (arg == GX::CA_RASA) + strcpy(socketOut, "material_node.outputs['Alpha']"); + else if (arg == GX::CA_KONST) { + int kreg = kalpha - GX::TEV_KASEL_K0_A; + if (kreg == 0) + strcpy(socketOut, "kcolor_nodes[0][1].outputs[0]"); + else if (kreg == 1) + strcpy(socketOut, "kcolor_nodes[1][1].outputs[0]"); + else if (kreg == 2) + strcpy(socketOut, "kcolor_nodes[2][1].outputs[0]"); + else if (kreg == 3) + strcpy(socketOut, "kcolor_nodes[3][1].outputs[0]"); + else + strcpy(socketOut, "ONE"); + } else if (arg == GX::CA_APREV) + strcpy(socketOut, a_regs[GX::TEVPREV]); + else if (arg == GX::CA_A0) + strcpy(socketOut, a_regs[GX::TEVREG0]); + else if (arg == GX::CA_A1) + strcpy(socketOut, a_regs[GX::TEVREG1]); + else if (arg == GX::CA_A2) + strcpy(socketOut, a_regs[GX::TEVREG2]); } static void AddTEVStage(Stream& out, const MaterialSet::Material::TEVStage& stage, - const MaterialSet::Material::TEVStageTexInfo& stageTex, - char c_regs[4][64], char a_regs[4][64], - unsigned& c_combiner_idx, unsigned& a_combiner_idx) -{ - char ca[64]; - char cb[64]; - char cc[64]; - char cd[64]; - TranslateColorSocket(ca, stage.colorInA(), stage.kColorIn(), stageTex, c_regs, a_regs); - TranslateColorSocket(cb, stage.colorInB(), stage.kColorIn(), stageTex, c_regs, a_regs); - TranslateColorSocket(cc, stage.colorInC(), stage.kColorIn(), stageTex, c_regs, a_regs); - TranslateColorSocket(cd, stage.colorInD(), stage.kColorIn(), stageTex, c_regs, a_regs); + const MaterialSet::Material::TEVStageTexInfo& stageTex, char c_regs[4][64], char a_regs[4][64], + unsigned& c_combiner_idx, unsigned& a_combiner_idx) { + char ca[64]; + char cb[64]; + char cc[64]; + char cd[64]; + TranslateColorSocket(ca, stage.colorInA(), stage.kColorIn(), stageTex, c_regs, a_regs); + TranslateColorSocket(cb, stage.colorInB(), stage.kColorIn(), stageTex, c_regs, a_regs); + TranslateColorSocket(cc, stage.colorInC(), stage.kColorIn(), stageTex, c_regs, a_regs); + TranslateColorSocket(cd, stage.colorInD(), stage.kColorIn(), stageTex, c_regs, a_regs); - char aa[64]; - char ab[64]; - char ac[64]; - char ad[64]; - TranslateAlphaSocket(aa, stage.alphaInA(), stage.kAlphaIn(), stageTex, a_regs); - TranslateAlphaSocket(ab, stage.alphaInB(), stage.kAlphaIn(), stageTex, a_regs); - TranslateAlphaSocket(ac, stage.alphaInC(), stage.kAlphaIn(), stageTex, a_regs); - TranslateAlphaSocket(ad, stage.alphaInD(), stage.kAlphaIn(), stageTex, a_regs); + char aa[64]; + char ab[64]; + char ac[64]; + char ad[64]; + TranslateAlphaSocket(aa, stage.alphaInA(), stage.kAlphaIn(), stageTex, a_regs); + TranslateAlphaSocket(ab, stage.alphaInB(), stage.kAlphaIn(), stageTex, a_regs); + TranslateAlphaSocket(ac, stage.alphaInC(), stage.kAlphaIn(), stageTex, a_regs); + TranslateAlphaSocket(ad, stage.alphaInD(), stage.kAlphaIn(), stageTex, a_regs); - /* Apply color optimizations */ - unsigned c_tev_opts = 0; - if (stage.colorInA() == GX::CC_ZERO || stage.colorInC() == GX::CC_ONE) - c_tev_opts |= 1; - if (stage.colorInB() == GX::CC_ZERO || stage.colorInC() == GX::CC_ZERO) - c_tev_opts |= 2; - if (c_tev_opts & 1 || c_tev_opts & 2) - c_tev_opts |= 4; - if (stage.colorInD() == GX::CC_ZERO || (c_tev_opts & 7) == 7) - c_tev_opts |= 8; + /* Apply color optimizations */ + unsigned c_tev_opts = 0; + if (stage.colorInA() == GX::CC_ZERO || stage.colorInC() == GX::CC_ONE) + c_tev_opts |= 1; + if (stage.colorInB() == GX::CC_ZERO || stage.colorInC() == GX::CC_ZERO) + c_tev_opts |= 2; + if (c_tev_opts & 1 || c_tev_opts & 2) + c_tev_opts |= 4; + if (stage.colorInD() == GX::CC_ZERO || (c_tev_opts & 7) == 7) + c_tev_opts |= 8; - /* Special A/D (additive) optimization */ - if (stage.colorInA() != GX::CC_ZERO && - stage.colorInB() == GX::CC_ZERO && - stage.colorInC() == GX::CC_ZERO && - stage.colorInD() != GX::CC_ZERO) - { - c_tev_opts |= 0x1f; - AddColorCombiner(out, Combiner::Add, cd, ca, nullptr); + /* Special A/D (additive) optimization */ + if (stage.colorInA() != GX::CC_ZERO && stage.colorInB() == GX::CC_ZERO && stage.colorInC() == GX::CC_ZERO && + stage.colorInD() != GX::CC_ZERO) { + c_tev_opts |= 0x1f; + AddColorCombiner(out, Combiner::Add, cd, ca, nullptr); + ++c_combiner_idx; + } else if (stage.colorInA() != GX::CC_ZERO && stage.colorInB() == GX::CC_ZERO && stage.colorInC() == GX::CC_ZERO && + stage.colorInD() == GX::CC_ZERO) { + c_tev_opts |= 0xf; + } else if (stage.colorInA() == GX::CC_ZERO && stage.colorInB() == GX::CC_ZERO && stage.colorInC() == GX::CC_ZERO && + stage.colorInD() != GX::CC_ZERO) { + c_tev_opts |= 0xf; + } + + if (!(c_tev_opts & 1)) { + /* A nodes */ + AddColorCombiner(out, Combiner::Sub, "ONE", ca, nullptr); + ++c_combiner_idx; + if (strcmp(cc, "ONE")) { + AddColorCombiner(out, Combiner::Mult, cc, "color_combiner_sockets[-1]", nullptr); + ++c_combiner_idx; + } + } + + const char* c_soc_log[2] = {"color_combiner_sockets[-1]", "color_combiner_sockets[-2]"}; + + if (!(c_tev_opts & 2)) { + /* B nodes */ + if (!strcmp(cc, "ONE")) { + if (strcmp(cb, "ZERO") && strcmp(cb, "HALF") && strcmp(cb, "ONE") && strcmp(cb, "D0") && strcmp(cb, "D1") && + strcmp(cb, "D2")) { + out.format("color_combiner_sockets.append(%s)\n", cb); ++c_combiner_idx; + } else { + c_soc_log[1] = c_soc_log[0]; + c_soc_log[0] = cb; + } + } else { + AddColorCombiner(out, Combiner::Mult, cc, cb, nullptr); + ++c_combiner_idx; } - else if (stage.colorInA() != GX::CC_ZERO && - stage.colorInB() == GX::CC_ZERO && - stage.colorInC() == GX::CC_ZERO && - stage.colorInD() == GX::CC_ZERO) - { - c_tev_opts |= 0xf; - } - else if (stage.colorInA() == GX::CC_ZERO && - stage.colorInB() == GX::CC_ZERO && - stage.colorInC() == GX::CC_ZERO && - stage.colorInD() != GX::CC_ZERO) - { - c_tev_opts |= 0xf; - } + } - if (!(c_tev_opts & 1)) - { - /* A nodes */ - AddColorCombiner(out, Combiner::Sub, "ONE", ca, nullptr); - ++c_combiner_idx; - if (strcmp(cc, "ONE")) - { - AddColorCombiner(out, Combiner::Mult, cc, "color_combiner_sockets[-1]", nullptr); - ++c_combiner_idx; - } + if (!(c_tev_opts & 4)) { + /* A+B node */ + AddColorCombiner(out, Combiner::Add, c_soc_log[0], c_soc_log[1], nullptr); + ++c_combiner_idx; + } + + if (!(c_tev_opts & 8)) { + /* +D node */ + AddColorCombiner(out, Combiner::Add, cd, c_soc_log[0], nullptr); + ++c_combiner_idx; + } + + /* Apply alpha optimizations */ + unsigned a_tev_opts = 0; + if (stage.alphaInA() == GX::CA_ZERO) + a_tev_opts |= 1; + if (stage.alphaInB() == GX::CA_ZERO || stage.alphaInC() == GX::CA_ZERO) + a_tev_opts |= 2; + if (a_tev_opts & 1 || a_tev_opts & 2) + a_tev_opts |= 4; + if (stage.alphaInD() == GX::CA_ZERO || (a_tev_opts & 7) == 7) + a_tev_opts |= 8; + + /* Special A/D (additive) optimization */ + if (stage.alphaInA() != GX::CA_ZERO && stage.alphaInB() == GX::CA_ZERO && stage.alphaInC() == GX::CA_ZERO && + stage.alphaInD() != GX::CA_ZERO) { + a_tev_opts |= 0x1f; + AddAlphaCombiner(out, Combiner::Add, ad, aa, nullptr); + ++a_combiner_idx; + } else if (stage.alphaInA() != GX::CA_ZERO && stage.alphaInB() == GX::CA_ZERO && stage.alphaInC() == GX::CA_ZERO && + stage.alphaInD() == GX::CA_ZERO) { + a_tev_opts |= 0xf; + } else if (stage.alphaInA() == GX::CA_ZERO && stage.alphaInB() == GX::CA_ZERO && stage.alphaInC() == GX::CA_ZERO && + stage.alphaInD() != GX::CA_ZERO) { + a_tev_opts |= 0xf; + } + + if (!(a_tev_opts & 1)) { + /* A nodes */ + AddAlphaCombiner(out, Combiner::Sub, "ONE", aa, nullptr); + ++a_combiner_idx; + if (strcmp(ac, "ONE")) { + AddAlphaCombiner(out, Combiner::Mult, ac, "alpha_combiner_sockets[-1]", nullptr); + ++a_combiner_idx; } - - const char* c_soc_log[2] = {"color_combiner_sockets[-1]", "color_combiner_sockets[-2]"}; + } - if (!(c_tev_opts & 2)) - { - /* B nodes */ - if (!strcmp(cc, "ONE")) - { - if (strcmp(cb, "ZERO") && strcmp(cb, "HALF") && strcmp(cb, "ONE") && - strcmp(cb, "D0") && strcmp(cb, "D1") && strcmp(cb, "D2")) - { - out.format("color_combiner_sockets.append(%s)\n", cb); - ++c_combiner_idx; - } - else - { - c_soc_log[1] = c_soc_log[0]; - c_soc_log[0] = cb; - } - } - else - { - AddColorCombiner(out, Combiner::Mult, cc, cb, nullptr); - ++c_combiner_idx; - } - } + const char* a_soc_log[2] = {"alpha_combiner_sockets[-1]", "alpha_combiner_sockets[-2]"}; - if (!(c_tev_opts & 4)) - { - /* A+B node */ - AddColorCombiner(out, Combiner::Add, c_soc_log[0], c_soc_log[1], nullptr); - ++c_combiner_idx; - } - - if (!(c_tev_opts & 8)) - { - /* +D node */ - AddColorCombiner(out, Combiner::Add, cd, c_soc_log[0], nullptr); - ++c_combiner_idx; - } - - /* Apply alpha optimizations */ - unsigned a_tev_opts = 0; - if (stage.alphaInA() == GX::CA_ZERO) - a_tev_opts |= 1; - if (stage.alphaInB() == GX::CA_ZERO || stage.alphaInC() == GX::CA_ZERO) - a_tev_opts |= 2; - if (a_tev_opts & 1 || a_tev_opts & 2) - a_tev_opts |= 4; - if (stage.alphaInD() == GX::CA_ZERO || (a_tev_opts & 7) == 7) - a_tev_opts |= 8; - - /* Special A/D (additive) optimization */ - if (stage.alphaInA() != GX::CA_ZERO && - stage.alphaInB() == GX::CA_ZERO && - stage.alphaInC() == GX::CA_ZERO && - stage.alphaInD() != GX::CA_ZERO) - { - a_tev_opts |= 0x1f; - AddAlphaCombiner(out, Combiner::Add, ad, aa, nullptr); + if (!(a_tev_opts & 2)) { + /* B nodes */ + if (!strcmp(ac, "ONE")) { + if (strcmp(ab, "ZERO") && strcmp(ab, "HALF") && strcmp(ab, "ONE") && strcmp(ab, "D0") && strcmp(ab, "D1") && + strcmp(ab, "D2")) { + out.format("alpha_combiner_sockets.append(%s)\n", ab); ++a_combiner_idx; + } else { + a_soc_log[1] = a_soc_log[0]; + a_soc_log[0] = ab; + } + } else { + AddAlphaCombiner(out, Combiner::Mult, ac, ab, nullptr); + ++a_combiner_idx; } - else if (stage.alphaInA() != GX::CA_ZERO && - stage.alphaInB() == GX::CA_ZERO && - stage.alphaInC() == GX::CA_ZERO && - stage.alphaInD() == GX::CA_ZERO) - { - a_tev_opts |= 0xf; - } - else if (stage.alphaInA() == GX::CA_ZERO && - stage.alphaInB() == GX::CA_ZERO && - stage.alphaInC() == GX::CA_ZERO && - stage.alphaInD() != GX::CA_ZERO) - { - a_tev_opts |= 0xf; - } + } - if (!(a_tev_opts & 1)) - { - /* A nodes */ - AddAlphaCombiner(out, Combiner::Sub, "ONE", aa, nullptr); - ++a_combiner_idx; - if (strcmp(ac, "ONE")) - { - AddAlphaCombiner(out, Combiner::Mult, ac, "alpha_combiner_sockets[-1]", nullptr); - ++a_combiner_idx; - } - } - - const char* a_soc_log[2] = {"alpha_combiner_sockets[-1]", "alpha_combiner_sockets[-2]"}; + if (!(a_tev_opts & 4)) { + /* A+B node */ + AddAlphaCombiner(out, Combiner::Add, a_soc_log[0], a_soc_log[1], nullptr); + ++a_combiner_idx; + } - if (!(a_tev_opts & 2)) - { - /* B nodes */ - if (!strcmp(ac, "ONE")) - { - if (strcmp(ab, "ZERO") && strcmp(ab, "HALF") && strcmp(ab, "ONE") && - strcmp(ab, "D0") && strcmp(ab, "D1") && strcmp(ab, "D2")) - { - out.format("alpha_combiner_sockets.append(%s)\n", ab); - ++a_combiner_idx; - } - else - { - a_soc_log[1] = a_soc_log[0]; - a_soc_log[0] = ab; - } - } - else - { - AddAlphaCombiner(out, Combiner::Mult, ac, ab, nullptr); - ++a_combiner_idx; - } - } + if (!(a_tev_opts & 8)) { + /* +D node */ + AddAlphaCombiner(out, Combiner::Add, ad, a_soc_log[0], nullptr); + ++a_combiner_idx; + } - if (!(a_tev_opts & 4)) - { - /* A+B node */ - AddAlphaCombiner(out, Combiner::Add, a_soc_log[0], a_soc_log[1], nullptr); - ++a_combiner_idx; - } - - if (!(a_tev_opts & 8)) - { - /* +D node */ - AddAlphaCombiner(out, Combiner::Add, ad, a_soc_log[0], nullptr); - ++a_combiner_idx; - } - - /* Update TEV regs */ - if (c_tev_opts == 0xf) - { - if (stage.colorInD() != GX::CC_ZERO) - strncpy(c_regs[stage.colorOpOutReg()], cd, 64); - else if (stage.colorInA() != GX::CC_ZERO) - strncpy(c_regs[stage.colorOpOutReg()], ca, 64); - } - else - snprintf(c_regs[stage.colorOpOutReg()], 64, "color_combiner_sockets[%u]", c_combiner_idx - 1); - if (a_tev_opts == 0xf) - { - if (stage.alphaInD() != GX::CA_ZERO) - strncpy(a_regs[stage.alphaOpOutReg()], ad, 64); - else if (stage.alphaInA() != GX::CA_ZERO) - strncpy(a_regs[stage.alphaOpOutReg()], aa, 64); - } - else - snprintf(a_regs[stage.alphaOpOutReg()], 64, "alpha_combiner_sockets[%u]", a_combiner_idx - 1); - - /* Row Break in gridder */ - out << "gridder.row_break(2)\n"; + /* Update TEV regs */ + if (c_tev_opts == 0xf) { + if (stage.colorInD() != GX::CC_ZERO) + strncpy(c_regs[stage.colorOpOutReg()], cd, 64); + else if (stage.colorInA() != GX::CC_ZERO) + strncpy(c_regs[stage.colorOpOutReg()], ca, 64); + } else + snprintf(c_regs[stage.colorOpOutReg()], 64, "color_combiner_sockets[%u]", c_combiner_idx - 1); + if (a_tev_opts == 0xf) { + if (stage.alphaInD() != GX::CA_ZERO) + strncpy(a_regs[stage.alphaOpOutReg()], ad, 64); + else if (stage.alphaInA() != GX::CA_ZERO) + strncpy(a_regs[stage.alphaOpOutReg()], aa, 64); + } else + snprintf(a_regs[stage.alphaOpOutReg()], 64, "alpha_combiner_sockets[%u]", a_combiner_idx - 1); + /* Row Break in gridder */ + out << "gridder.row_break(2)\n"; } template -void _ConstructMaterial(Stream& out, - const MAT& material, - unsigned groupIdx, - unsigned matIdx) -{ - unsigned i; +void _ConstructMaterial(Stream& out, const MAT& material, unsigned groupIdx, unsigned matIdx) { + unsigned i; - out.format("new_material = bpy.data.materials.new('MAT_%u_%u')\n" - "new_material.use_shadows = True\n" - "new_material.use_transparent_shadows = True\n" - "new_material.diffuse_color = (1.0,1.0,1.0)\n" - "new_material.diffuse_intensity = 1.0\n" - "new_material.specular_intensity = 0.0\n" - "new_material.use_nodes = True\n" - "new_nodetree = new_material.node_tree\n" - "material_node = new_nodetree.nodes['Material']\n" - "final_node = new_nodetree.nodes['Output']\n" - "\n" - "gridder = hecl.Nodegrid(new_nodetree)\n" - "gridder.place_node(final_node, 3)\n" - "gridder.place_node(material_node, 0)\n" - "material_node.material = new_material\n" - "\n" - "texture_nodes = []\n" - "kcolor_nodes = []\n" - "color_combiner_sockets = []\n" - "alpha_combiner_sockets = []\n" - "tex_links = []\n" - "tev_reg_sockets = [None]*4\n" - "\n", groupIdx, matIdx); + out.format( + "new_material = bpy.data.materials.new('MAT_%u_%u')\n" + "new_material.use_shadows = True\n" + "new_material.use_transparent_shadows = True\n" + "new_material.diffuse_color = (1.0,1.0,1.0)\n" + "new_material.diffuse_intensity = 1.0\n" + "new_material.specular_intensity = 0.0\n" + "new_material.use_nodes = True\n" + "new_nodetree = new_material.node_tree\n" + "material_node = new_nodetree.nodes['Material']\n" + "final_node = new_nodetree.nodes['Output']\n" + "\n" + "gridder = hecl.Nodegrid(new_nodetree)\n" + "gridder.place_node(final_node, 3)\n" + "gridder.place_node(material_node, 0)\n" + "material_node.material = new_material\n" + "\n" + "texture_nodes = []\n" + "kcolor_nodes = []\n" + "color_combiner_sockets = []\n" + "alpha_combiner_sockets = []\n" + "tex_links = []\n" + "tev_reg_sockets = [None]*4\n" + "\n", + groupIdx, matIdx); - /* Material Flags */ - out.format("new_material.retro_depth_sort = %s\n" - "new_material.retro_alpha_test = %s\n" - "new_material.retro_samus_reflection = %s\n" - "new_material.retro_depth_write = %s\n" - "new_material.retro_samus_reflection_persp = %s\n" - "new_material.retro_shadow_occluder = %s\n" - "new_material.retro_samus_reflection_indirect = %s\n" - "new_material.retro_lightmapped = %s\n" - "new_material.game_settings.invisible = %s\n", - material.flags.depthSorting() ? "True" : "False", - material.flags.alphaTest() ? "True" : "False", - material.flags.samusReflection() ? "True" : "False", - material.flags.depthWrite() ? "True" : "False", - material.flags.samusReflectionSurfaceEye() ? "True" : "False", - material.flags.shadowOccluderMesh() ? "True" : "False", - material.flags.samusReflectionIndirectTexture() ? "True" : "False", - material.flags.lightmap() ? "True" : "False", - material.flags.shadowOccluderMesh() ? "True" : "False"); + /* Material Flags */ + out.format( + "new_material.retro_depth_sort = %s\n" + "new_material.retro_alpha_test = %s\n" + "new_material.retro_samus_reflection = %s\n" + "new_material.retro_depth_write = %s\n" + "new_material.retro_samus_reflection_persp = %s\n" + "new_material.retro_shadow_occluder = %s\n" + "new_material.retro_samus_reflection_indirect = %s\n" + "new_material.retro_lightmapped = %s\n" + "new_material.game_settings.invisible = %s\n", + material.flags.depthSorting() ? "True" : "False", material.flags.alphaTest() ? "True" : "False", + material.flags.samusReflection() ? "True" : "False", material.flags.depthWrite() ? "True" : "False", + material.flags.samusReflectionSurfaceEye() ? "True" : "False", + material.flags.shadowOccluderMesh() ? "True" : "False", + material.flags.samusReflectionIndirectTexture() ? "True" : "False", material.flags.lightmap() ? "True" : "False", + material.flags.shadowOccluderMesh() ? "True" : "False"); + /* Texture Indices */ + out << "tex_maps = []\n"; + for (atUint32 idx : material.textureIdxs) + out.format("tex_maps.append(texmap_list[%u])\n", idx); - /* Texture Indices */ - out << "tex_maps = []\n"; - for (atUint32 idx : material.textureIdxs) - out.format("tex_maps.append(texmap_list[%u])\n", idx); + /* KColor entries */ + if (material.flags.konstValuesEnabled()) { + unsigned i = 0; + for (const GX::Color& col : material.konstColors) + Material::AddKcolor(out, col, i++); + } - /* KColor entries */ - if (material.flags.konstValuesEnabled()) - { - unsigned i=0; - for (const GX::Color& col : material.konstColors) - Material::AddKcolor(out, col, i++); - } - - /* Blend factors */ - using BlendFactor = Material::BlendFactor; - if (material.blendDstFac != BlendFactor::BL_ZERO) - { - if (material.blendDstFac == BlendFactor::BL_ONE) - out << "new_material.game_settings.alpha_blend = 'ADD'\n" - "new_material.use_transparency = True\n" - "new_material.transparency_method = 'RAYTRACE'\n" - "new_material.alpha = 1.0\n"; - else - out << "new_material.game_settings.alpha_blend = 'ALPHA'\n" - "new_material.use_transparency = True\n" - "new_material.transparency_method = 'RAYTRACE'\n" - "new_material.alpha = 1.0\n"; - } - - /* Color channels (for combining dynamic lighting) */ - for (const Material::ColorChannel& chan : material.colorChannels) - { - if (!chan.lighting()) - out << "new_material.use_shadeless = True\n"; - } - - /* Add texture maps/tcgs */ - unsigned addedTcgs = 0; - for (i=0 ; i> material.tevStageTexInfo[i].tcgSlot & 1)) - { - const Material::TexCoordGen& tcg = material.tcgs[material.tevStageTexInfo[i].tcgSlot]; - GX::TexMtx mtx = tcg.mtx(); - int mtxIdx = -1; - if (mtx >= GX::TEXMTX0 && mtx <= GX::TEXMTX9) - mtxIdx = (mtx - GX::TEXMTX0) / 3; - Material::AddTexture(out, tcg.source(), mtxIdx, material.tevStageTexInfo[i].texSlot); - addedTcgs |= 1 << material.tevStageTexInfo[i].tcgSlot; - } - } - - /* Indirect texture node */ - if (material.flags.samusReflectionIndirectTexture()) - { - Material::AddTexture(out, GX::TexGenSrc::TG_POS, -1, material.indTexSlot[0]); - out << "# Indirect Texture\n" - "ind_out = new_nodetree.nodes.new('ShaderNodeOutput')\n" - "gridder.place_node(ind_out, 3)\n" - "ind_out.name = 'IndirectOutput'\n" - "ind_out.label = 'Indirect'\n" - "new_nodetree.links.new(tex_node.outputs['Color'], ind_out.inputs['Color'])\n"; - } - - /* TEV-emulation combiner-node index context */ - unsigned c_combiner_idx = 0; - unsigned a_combiner_idx = 0; - - /* Initialze TEV register sockets */ - char c_regs[4][64] = {"ONE", "D0", "D1", "D2"}; - char a_regs[4][64] = {"ONE", "D0", "D1", "D2"}; - - /* Has Lightmap? */ - if (material.flags.lightmap()) - { - if (material.tevStageTexInfo[0].texSlot != 0xff) - out << "new_material.hecl_lightmap = tex_maps[0].name\n" - "tex_maps[0].image.use_fake_user = True\n"; - } - - /* Add TEV stages */ - for (i=0 ; i> material.tevStageTexInfo[i].tcgSlot & 1)) { + const Material::TexCoordGen& tcg = material.tcgs[material.tevStageTexInfo[i].tcgSlot]; + GX::TexMtx mtx = tcg.mtx(); + int mtxIdx = -1; + if (mtx >= GX::TEXMTX0 && mtx <= GX::TEXMTX9) + mtxIdx = (mtx - GX::TEXMTX0) / 3; + Material::AddTexture(out, tcg.source(), mtxIdx, material.tevStageTexInfo[i].texSlot); + addedTcgs |= 1 << material.tevStageTexInfo[i].tcgSlot; + } + } + + /* Indirect texture node */ + if (material.flags.samusReflectionIndirectTexture()) { + Material::AddTexture(out, GX::TexGenSrc::TG_POS, -1, material.indTexSlot[0]); + out << "# Indirect Texture\n" + "ind_out = new_nodetree.nodes.new('ShaderNodeOutput')\n" + "gridder.place_node(ind_out, 3)\n" + "ind_out.name = 'IndirectOutput'\n" + "ind_out.label = 'Indirect'\n" + "new_nodetree.links.new(tex_node.outputs['Color'], ind_out.inputs['Color'])\n"; + } + + /* TEV-emulation combiner-node index context */ + unsigned c_combiner_idx = 0; + unsigned a_combiner_idx = 0; + + /* Initialze TEV register sockets */ + char c_regs[4][64] = {"ONE", "D0", "D1", "D2"}; + char a_regs[4][64] = {"ONE", "D0", "D1", "D2"}; + + /* Has Lightmap? */ + if (material.flags.lightmap()) { + if (material.tevStageTexInfo[0].texSlot != 0xff) + out << "new_material.hecl_lightmap = tex_maps[0].name\n" + "tex_maps[0].image.use_fake_user = True\n"; + } + + /* Add TEV stages */ + for (i = 0; i < material.tevStageCount; ++i) { + const Material::TEVStage& stage = material.tevStages[i]; + const Material::TEVStageTexInfo& stage_tex = material.tevStageTexInfo[i]; + AddTEVStage(out, stage, stage_tex, c_regs, a_regs, c_combiner_idx, a_combiner_idx); + } + + /* Connect final prev register */ + if (!strcmp(c_regs[GX::TEVPREV], "ONE")) + out << "final_node.inputs['Color'].default_value = (1.0,1.0,1.0,1.0)\n"; + else + out.format("new_nodetree.links.new(%s, final_node.inputs['Color'])\n", c_regs[GX::TEVPREV]); + + if (!strcmp(a_regs[GX::TEVPREV], "ONE")) + out << "final_node.inputs['Alpha'].default_value = 1.0\n"; + else + out.format("new_nodetree.links.new(%s, final_node.inputs['Alpha'])\n", a_regs[GX::TEVPREV]); + + /* Texmtx Animation Section */ + i = 0; + for (const Material::UVAnimation& anim : material.uvAnims) + Material::AddTextureAnim(out, anim.mode, i++, anim.vals); } -void MaterialSet::ConstructMaterial(Stream& out, - const MaterialSet::Material& material, - unsigned groupIdx, - unsigned matIdx) -{_ConstructMaterial(out, material, groupIdx, matIdx);} +void MaterialSet::ConstructMaterial(Stream& out, const MaterialSet::Material& material, unsigned groupIdx, + unsigned matIdx) { + _ConstructMaterial(out, material, groupIdx, matIdx); +} -MaterialSet::Material::Material(const hecl::Backend::GX& gx, - const std::unordered_map& iprops, +MaterialSet::Material::Material(const hecl::Backend::GX& gx, const std::unordered_map& iprops, const std::vector& texPathsIn, - std::vector& texPathsOut, - int colorCount, - bool lightmapUVs, - bool matrixSkinning) -{ - XXH32_state_t xxHash; - XXH32_reset(&xxHash, 0); + std::vector& texPathsOut, int colorCount, bool lightmapUVs, + bool matrixSkinning) { + XXH32_state_t xxHash; + XXH32_reset(&xxHash, 0); - if (gx.m_kcolorCount) - { - flags.setKonstValuesEnabled(true); - konstCount.push_back(gx.m_kcolorCount); + if (gx.m_kcolorCount) { + flags.setKonstValuesEnabled(true); + konstCount.push_back(gx.m_kcolorCount); + } + + auto search = iprops.find("retro_depth_sort"); + if (search != iprops.end()) + flags.setDepthSorting(search->second != 0); + + search = iprops.find("retro_alpha_test"); + if (search != iprops.end()) + flags.setPunchthroughAlpha(search->second != 0); + + search = iprops.find("retro_samus_reflection"); + if (search != iprops.end()) + flags.setSamusReflection(search->second != 0); + + search = iprops.find("retro_depth_write"); + if (search != iprops.end()) + flags.setDepthWrite(search->second != 0); + + search = iprops.find("retro_samus_reflection_persp"); + if (search != iprops.end()) + flags.setSamusReflectionSurfaceEye(search->second != 0); + + search = iprops.find("retro_shadow_occluder"); + if (search != iprops.end()) + flags.setShadowOccluderMesh(search->second != 0); + + search = iprops.find("retro_samus_reflection_indirect"); + if (search != iprops.end()) + flags.setSamusReflectionIndirectTexture(search->second != 0); + + search = iprops.find("retro_lightmapped"); + if (search != iprops.end()) + flags.setLightmap(search->second != 0); + + flags.setLightmapUVArray(lightmapUVs); + + atUint16 texFlags = 0; + atUint16 tcgFlags = 0; + tevStageTexInfo.reserve(gx.m_tevCount); + textureIdxs.reserve(gx.m_tevCount); + for (unsigned i = 0; i < gx.m_tevCount; ++i) { + const hecl::Backend::GX::TEVStage& stage = gx.m_tevs[i]; + tevStageTexInfo.emplace_back(); + TEVStageTexInfo& texInfo = tevStageTexInfo.back(); + if (stage.m_texGenIdx != -1) { + texInfo.tcgSlot = stage.m_texGenIdx; + const hecl::Backend::GX::TexCoordGen& tcg = gx.m_tcgs[stage.m_texGenIdx]; + if (tcg.m_src >= hecl::Backend::GX::TG_TEX0 && tcg.m_src <= hecl::Backend::GX::TG_TEX6) + tcgFlags |= 1 << (tcg.m_src - hecl::Backend::GX::TG_TEX0); } - - auto search = iprops.find("retro_depth_sort"); - if (search != iprops.end()) - flags.setDepthSorting(search->second != 0); - - search = iprops.find("retro_alpha_test"); - if (search != iprops.end()) - flags.setPunchthroughAlpha(search->second != 0); - - search = iprops.find("retro_samus_reflection"); - if (search != iprops.end()) - flags.setSamusReflection(search->second != 0); - - search = iprops.find("retro_depth_write"); - if (search != iprops.end()) - flags.setDepthWrite(search->second != 0); - - search = iprops.find("retro_samus_reflection_persp"); - if (search != iprops.end()) - flags.setSamusReflectionSurfaceEye(search->second != 0); - - search = iprops.find("retro_shadow_occluder"); - if (search != iprops.end()) - flags.setShadowOccluderMesh(search->second != 0); - - search = iprops.find("retro_samus_reflection_indirect"); - if (search != iprops.end()) - flags.setSamusReflectionIndirectTexture(search->second != 0); - - search = iprops.find("retro_lightmapped"); - if (search != iprops.end()) - flags.setLightmap(search->second != 0); - - flags.setLightmapUVArray(lightmapUVs); - - atUint16 texFlags = 0; - atUint16 tcgFlags = 0; - tevStageTexInfo.reserve(gx.m_tevCount); - textureIdxs.reserve(gx.m_tevCount); - for (unsigned i=0 ; i= hecl::Backend::GX::TG_TEX0 && tcg.m_src <= hecl::Backend::GX::TG_TEX6) - tcgFlags |= 1 << (tcg.m_src - hecl::Backend::GX::TG_TEX0); - } - if (stage.m_texMapIdx != -1) - { - texInfo.texSlot = textureIdxs.size(); - const hecl::ProjectPath& texPath = texPathsIn.at(stage.m_texMapIdx); - texFlags |= 1 << i; - ++textureCount; - bool found = false; - for (size_t t=0 ; t& iprops, - const std::vector& texPaths) -{ - auto search = iprops.find("retro_depth_sort"); - if (search != iprops.end()) - flags.setDepthSorting(search->second != 0); - - search = iprops.find("retro_alpha_test"); - if (search != iprops.end()) - flags.setPunchthroughAlpha(search->second != 0); - - search = iprops.find("retro_samus_reflection"); - if (search != iprops.end()) - flags.setSamusReflection(search->second != 0); - - search = iprops.find("retro_depth_write"); - if (search != iprops.end()) - flags.setDepthWrite(search->second != 0); - - search = iprops.find("retro_samus_reflection_persp"); - if (search != iprops.end()) - flags.setSamusReflectionSurfaceEye(search->second != 0); - - search = iprops.find("retro_shadow_occluder"); - if (search != iprops.end()) - flags.setShadowOccluderMesh(search->second != 0); - - search = iprops.find("retro_samus_reflection_indirect"); - if (search != iprops.end()) - flags.setSamusReflectionIndirectTexture(search->second != 0); - - search = iprops.find("retro_lightmapped"); - if (search != iprops.end()) - flags.setLightmap(search->second != 0); - - for (const hecl::ProjectPath& path : mat.texs) - { - size_t idx = 0; - for (const hecl::ProjectPath& tPath : texPaths) - { - if (path == tPath) - { - textureIdxs.push_back(idx); - ++textureCount; - break; - } - ++idx; - } - } - - if (flags.samusReflectionIndirectTexture()) - indTexSlot.push_back(textureIdxs.size()); - - heclSource = mat.source; - heclIr = FE.compileSource(mat.source, diagName); - - uvAnimsSize = 4; - uvAnimsCount = 0; - for (const hecl::Frontend::IR::Instruction& inst : heclIr.m_instructions) - { - if (inst.m_op != hecl::Frontend::IR::OpType::Call) - continue; - if (inst.m_call.m_name.compare("Texture")) - continue; - - const hecl::Frontend::IR::Instruction& sourceInst = inst.getChildInst(heclIr, 1); - if (sourceInst.m_op != hecl::Frontend::IR::OpType::Call) - continue; - if (sourceInst.m_call.m_name.compare(0, 11, "RetroUVMode")) - continue; - - std::vector gameArgs; - gameArgs.reserve(sourceInst.getChildCount() - 1); - for (int i=1 ; i& gameArgs) -{ - if (!gameFunction.compare("RetroUVMode0NodeN")) - mode = Mode::MvInvNoTranslation; - else if (!gameFunction.compare("RetroUVMode1NodeN")) - mode = Mode::MvInv; - else if (!gameFunction.compare("RetroUVMode2Node")) - { - mode = Mode::Scroll; - if (gameArgs.size() < 2) - Log.report(logvisor::Fatal, "Mode2 UV anim requires 2 vector arguments"); - vals[0] = gameArgs[0].simd[0]; - vals[1] = gameArgs[0].simd[1]; - vals[2] = gameArgs[1].simd[0]; - vals[3] = gameArgs[1].simd[1]; +HMDLMaterialSet::Material::Material(hecl::Frontend::Frontend& FE, const std::string& diagName, + const hecl::blender::Material& mat, + const std::unordered_map& iprops, + const std::vector& texPaths) { + auto search = iprops.find("retro_depth_sort"); + if (search != iprops.end()) + flags.setDepthSorting(search->second != 0); + + search = iprops.find("retro_alpha_test"); + if (search != iprops.end()) + flags.setPunchthroughAlpha(search->second != 0); + + search = iprops.find("retro_samus_reflection"); + if (search != iprops.end()) + flags.setSamusReflection(search->second != 0); + + search = iprops.find("retro_depth_write"); + if (search != iprops.end()) + flags.setDepthWrite(search->second != 0); + + search = iprops.find("retro_samus_reflection_persp"); + if (search != iprops.end()) + flags.setSamusReflectionSurfaceEye(search->second != 0); + + search = iprops.find("retro_shadow_occluder"); + if (search != iprops.end()) + flags.setShadowOccluderMesh(search->second != 0); + + search = iprops.find("retro_samus_reflection_indirect"); + if (search != iprops.end()) + flags.setSamusReflectionIndirectTexture(search->second != 0); + + search = iprops.find("retro_lightmapped"); + if (search != iprops.end()) + flags.setLightmap(search->second != 0); + + for (const hecl::ProjectPath& path : mat.texs) { + size_t idx = 0; + for (const hecl::ProjectPath& tPath : texPaths) { + if (path == tPath) { + textureIdxs.push_back(idx); + ++textureCount; + break; + } + ++idx; } - else if (!gameFunction.compare("RetroUVMode3Node")) - { - mode = Mode::Rotation; - if (gameArgs.size() < 2) - Log.report(logvisor::Fatal, "Mode3 UV anim requires 2 arguments"); - vals[0] = gameArgs[0].simd[0]; - vals[1] = gameArgs[1].simd[0]; + } + + if (flags.samusReflectionIndirectTexture()) + indTexSlot.push_back(textureIdxs.size()); + + heclSource = mat.source; + heclIr = FE.compileSource(mat.source, diagName); + + uvAnimsSize = 4; + uvAnimsCount = 0; + for (const hecl::Frontend::IR::Instruction& inst : heclIr.m_instructions) { + if (inst.m_op != hecl::Frontend::IR::OpType::Call) + continue; + if (inst.m_call.m_name.compare("Texture")) + continue; + + const hecl::Frontend::IR::Instruction& sourceInst = inst.getChildInst(heclIr, 1); + if (sourceInst.m_op != hecl::Frontend::IR::OpType::Call) + continue; + if (sourceInst.m_call.m_name.compare(0, 11, "RetroUVMode")) + continue; + + std::vector gameArgs; + gameArgs.reserve(sourceInst.getChildCount() - 1); + for (int i = 1; i < sourceInst.getChildCount(); ++i) { + const hecl::Frontend::IR::Instruction& ci = sourceInst.getChildInst(heclIr, i); + gameArgs.push_back(ci.getImmVec()); } - else if (!gameFunction.compare("RetroUVMode4Node")) - { - mode = Mode::HStrip; - if (gameArgs.size() < 4) - Log.report(logvisor::Fatal, "Mode4 UV anim requires 4 arguments"); - vals[0] = gameArgs[0].simd[0]; - vals[1] = gameArgs[1].simd[0]; - vals[2] = gameArgs[2].simd[0]; - vals[3] = gameArgs[3].simd[0]; - } - else if (!gameFunction.compare("RetroUVMode5Node")) - { - mode = Mode::VStrip; - if (gameArgs.size() < 4) - Log.report(logvisor::Fatal, "Mode5 UV anim requires 4 arguments"); - vals[0] = gameArgs[0].simd[0]; - vals[1] = gameArgs[1].simd[0]; - vals[2] = gameArgs[2].simd[0]; - vals[3] = gameArgs[3].simd[0]; - } - else if (!gameFunction.compare("RetroUVMode6NodeN")) - mode = Mode::Model; - else if (!gameFunction.compare("RetroUVMode7NodeN")) - { - mode = Mode::CylinderEnvironment; - if (gameArgs.size() < 2) - Log.report(logvisor::Fatal, "Mode7 UV anim requires 2 arguments"); - vals[0] = gameArgs[0].simd[0]; - vals[1] = gameArgs[1].simd[0]; - } - else - Log.report(logvisor::Fatal, "unsupported UV anim '%s'", gameFunction.c_str()); + + ++uvAnimsCount; + uvAnims.emplace_back(sourceInst.m_call.m_name, gameArgs); + size_t tmpUvAnimsSize = uvAnimsSize; + uvAnims.back().binarySize(tmpUvAnimsSize); + uvAnimsSize = tmpUvAnimsSize; + } +} + +MaterialSet::Material::UVAnimation::UVAnimation(const std::string& gameFunction, const std::vector& gameArgs) { + if (!gameFunction.compare("RetroUVMode0NodeN")) + mode = Mode::MvInvNoTranslation; + else if (!gameFunction.compare("RetroUVMode1NodeN")) + mode = Mode::MvInv; + else if (!gameFunction.compare("RetroUVMode2Node")) { + mode = Mode::Scroll; + if (gameArgs.size() < 2) + Log.report(logvisor::Fatal, "Mode2 UV anim requires 2 vector arguments"); + vals[0] = gameArgs[0].simd[0]; + vals[1] = gameArgs[0].simd[1]; + vals[2] = gameArgs[1].simd[0]; + vals[3] = gameArgs[1].simd[1]; + } else if (!gameFunction.compare("RetroUVMode3Node")) { + mode = Mode::Rotation; + if (gameArgs.size() < 2) + Log.report(logvisor::Fatal, "Mode3 UV anim requires 2 arguments"); + vals[0] = gameArgs[0].simd[0]; + vals[1] = gameArgs[1].simd[0]; + } else if (!gameFunction.compare("RetroUVMode4Node")) { + mode = Mode::HStrip; + if (gameArgs.size() < 4) + Log.report(logvisor::Fatal, "Mode4 UV anim requires 4 arguments"); + vals[0] = gameArgs[0].simd[0]; + vals[1] = gameArgs[1].simd[0]; + vals[2] = gameArgs[2].simd[0]; + vals[3] = gameArgs[3].simd[0]; + } else if (!gameFunction.compare("RetroUVMode5Node")) { + mode = Mode::VStrip; + if (gameArgs.size() < 4) + Log.report(logvisor::Fatal, "Mode5 UV anim requires 4 arguments"); + vals[0] = gameArgs[0].simd[0]; + vals[1] = gameArgs[1].simd[0]; + vals[2] = gameArgs[2].simd[0]; + vals[3] = gameArgs[3].simd[0]; + } else if (!gameFunction.compare("RetroUVMode6NodeN")) + mode = Mode::Model; + else if (!gameFunction.compare("RetroUVMode7NodeN")) { + mode = Mode::CylinderEnvironment; + if (gameArgs.size() < 2) + Log.report(logvisor::Fatal, "Mode7 UV anim requires 2 arguments"); + vals[0] = gameArgs[0].simd[0]; + vals[1] = gameArgs[1].simd[0]; + } else + Log.report(logvisor::Fatal, "unsupported UV anim '%s'", gameFunction.c_str()); } template -void MaterialSet::Material::UVAnimation::Enumerate(typename Op::StreamT& s) -{ - Do({}, mode, s); - switch (mode) - { - case Mode::MvInvNoTranslation: - case Mode::MvInv: - case Mode::Model: - break; - case Mode::Scroll: - case Mode::HStrip: - case Mode::VStrip: - for (int i=0 ; i<4 ; ++i) - Do({}, vals[i], s); - break; - case Mode::Rotation: - case Mode::CylinderEnvironment: - for (int i=0 ; i<2 ; ++i) - Do({}, vals[i], s); - break; - case Mode::Eight: - for (int i=0 ; i<9 ; ++i) - Do({}, vals[i], s); - break; - } +void MaterialSet::Material::UVAnimation::Enumerate(typename Op::StreamT& s) { + Do({}, mode, s); + switch (mode) { + case Mode::MvInvNoTranslation: + case Mode::MvInv: + case Mode::Model: + break; + case Mode::Scroll: + case Mode::HStrip: + case Mode::VStrip: + for (int i = 0; i < 4; ++i) + Do({}, vals[i], s); + break; + case Mode::Rotation: + case Mode::CylinderEnvironment: + for (int i = 0; i < 2; ++i) + Do({}, vals[i], s); + break; + case Mode::Eight: + for (int i = 0; i < 9; ++i) + Do({}, vals[i], s); + break; + } } AT_SPECIALIZE_DNA(MaterialSet::Material::UVAnimation) +} // namespace DataSpec::DNAMP1 + +namespace DataSpec::DNAMP2 { + +void MaterialSet::ConstructMaterial(Stream& out, const MaterialSet::Material& material, unsigned groupIdx, + unsigned matIdx) { + DataSpec::DNAMP1::_ConstructMaterial(out, material, groupIdx, matIdx); } -namespace DataSpec::DNAMP2 -{ - -void MaterialSet::ConstructMaterial(Stream& out, - const MaterialSet::Material& material, - unsigned groupIdx, - unsigned matIdx) -{DataSpec::DNAMP1::_ConstructMaterial(out, material, groupIdx, matIdx);} - -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP1/CMDLMaterials.hpp b/DataSpec/DNAMP1/CMDLMaterials.hpp index c9d0008f5..0700d5c83 100644 --- a/DataSpec/DNAMP1/CMDLMaterials.hpp +++ b/DataSpec/DNAMP1/CMDLMaterials.hpp @@ -5,411 +5,551 @@ #include "DataSpec/DNACommon/CMDL.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct MaterialSet : BigDNA -{ - static constexpr bool OneSection() {return false;} +struct MaterialSet : BigDNA { + static constexpr bool OneSection() { return false; } + AT_DECL_DNA + struct MaterialSetHead : BigDNA { AT_DECL_DNA - struct MaterialSetHead : BigDNA - { - AT_DECL_DNA - Value textureCount = 0; - Vector textureIDs; - Value materialCount = 0; - Vector materialEndOffs; + Value textureCount = 0; + Vector textureIDs; + Value materialCount = 0; + Vector materialEndOffs; - void addTexture(const UniqueID32& id) {textureIDs.push_back(id); ++textureCount;} - void addMaterialEndOff(atUint32 off) {materialEndOffs.push_back(off); ++materialCount;} + void addTexture(const UniqueID32& id) { + textureIDs.push_back(id); + ++textureCount; + } + void addMaterialEndOff(atUint32 off) { + materialEndOffs.push_back(off); + ++materialCount; + } - template - void ensureTexturesExtracted(PAKRouter& pakRouter) const - { - for (const auto& id : textureIDs) - { - const nod::Node* node; - const PAK::Entry* texEntry = pakRouter.lookupEntry(id, &node); - if (!texEntry) - continue; - hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); - if (txtrPath.isNone()) - { - txtrPath.makeDirChain(false); - PAKEntryReadStream rs = texEntry->beginReadStream(*node); - TXTR::Extract(rs, txtrPath); - } - } + template + void ensureTexturesExtracted(PAKRouter& pakRouter) const { + for (const auto& id : textureIDs) { + const nod::Node* node; + const PAK::Entry* texEntry = pakRouter.lookupEntry(id, &node); + if (!texEntry) + continue; + hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); + if (txtrPath.isNone()) { + txtrPath.makeDirChain(false); + PAKEntryReadStream rs = texEntry->beginReadStream(*node); + TXTR::Extract(rs, txtrPath); } - } head; + } + } + } head; - struct Material : BigDNA - { - AT_DECL_DNA - struct Flags : BigDNA - { - AT_DECL_DNA - Value flags = 0; - bool konstValuesEnabled() const {return (flags & 0x8) != 0;} - void setKonstValuesEnabled(bool enabled) {flags &= ~0x8; flags |= atUint32(enabled) << 3;} - bool depthSorting() const {return (flags & 0x10) != 0;} - void setDepthSorting(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;} - bool alphaTest() const {return (flags & 0x20) != 0;} - void setPunchthroughAlpha(bool enabled) {flags &= ~0x20; flags |= atUint32(enabled) << 5;} - bool samusReflection() const {return (flags & 0x40) != 0;} - void setSamusReflection(bool enabled) {flags &= ~0x40; flags |= atUint32(enabled) << 6;} - bool depthWrite() const {return (flags & 0x80) != 0;} - void setDepthWrite(bool enabled) {flags &= ~0x80; flags |= atUint32(enabled) << 7;} - bool samusReflectionSurfaceEye() const {return (flags & 0x100) != 0;} - void setSamusReflectionSurfaceEye(bool enabled) {flags &= ~0x100; flags |= atUint32(enabled) << 8;} - bool shadowOccluderMesh() const {return (flags & 0x200) != 0;} - void setShadowOccluderMesh(bool enabled) {flags &= ~0x200; flags |= atUint32(enabled) << 9;} - bool samusReflectionIndirectTexture() const {return (flags & 0x400) != 0;} - void setSamusReflectionIndirectTexture(bool enabled) {flags &= ~0x400; flags |= atUint32(enabled) << 10;} - bool lightmap() const {return (flags & 0x800) != 0;} - void setLightmap(bool enabled) {flags &= ~0x800; flags |= atUint32(enabled) << 11;} - bool lightmapUVArray() const {return (flags & 0x2000) != 0;} - void setLightmapUVArray(bool enabled) {flags &= ~0x2000; flags |= atUint32(enabled) << 13;} - atUint16 textureSlots() const {return (flags >> 16) != 0;} - void setTextureSlots(atUint16 texslots) {flags &= ~0xffff0000; flags |= atUint32(texslots) << 16;} - } flags; - const Flags& getFlags() const {return flags;} + struct Material : BigDNA { + AT_DECL_DNA + struct Flags : BigDNA { + AT_DECL_DNA + Value flags = 0; + bool konstValuesEnabled() const { return (flags & 0x8) != 0; } + void setKonstValuesEnabled(bool enabled) { + flags &= ~0x8; + flags |= atUint32(enabled) << 3; + } + bool depthSorting() const { return (flags & 0x10) != 0; } + void setDepthSorting(bool enabled) { + flags &= ~0x10; + flags |= atUint32(enabled) << 4; + } + bool alphaTest() const { return (flags & 0x20) != 0; } + void setPunchthroughAlpha(bool enabled) { + flags &= ~0x20; + flags |= atUint32(enabled) << 5; + } + bool samusReflection() const { return (flags & 0x40) != 0; } + void setSamusReflection(bool enabled) { + flags &= ~0x40; + flags |= atUint32(enabled) << 6; + } + bool depthWrite() const { return (flags & 0x80) != 0; } + void setDepthWrite(bool enabled) { + flags &= ~0x80; + flags |= atUint32(enabled) << 7; + } + bool samusReflectionSurfaceEye() const { return (flags & 0x100) != 0; } + void setSamusReflectionSurfaceEye(bool enabled) { + flags &= ~0x100; + flags |= atUint32(enabled) << 8; + } + bool shadowOccluderMesh() const { return (flags & 0x200) != 0; } + void setShadowOccluderMesh(bool enabled) { + flags &= ~0x200; + flags |= atUint32(enabled) << 9; + } + bool samusReflectionIndirectTexture() const { return (flags & 0x400) != 0; } + void setSamusReflectionIndirectTexture(bool enabled) { + flags &= ~0x400; + flags |= atUint32(enabled) << 10; + } + bool lightmap() const { return (flags & 0x800) != 0; } + void setLightmap(bool enabled) { + flags &= ~0x800; + flags |= atUint32(enabled) << 11; + } + bool lightmapUVArray() const { return (flags & 0x2000) != 0; } + void setLightmapUVArray(bool enabled) { + flags &= ~0x2000; + flags |= atUint32(enabled) << 13; + } + atUint16 textureSlots() const { return (flags >> 16) != 0; } + void setTextureSlots(atUint16 texslots) { + flags &= ~0xffff0000; + flags |= atUint32(texslots) << 16; + } + } flags; + const Flags& getFlags() const { return flags; } - Value textureCount = 0; - Vector textureIdxs; - struct VAFlags : BigDNA - { - AT_DECL_DNA - Value vaFlags = 0; - GX::AttrType position() const {return GX::AttrType(vaFlags & 0x3);} - void setPosition(GX::AttrType val) {vaFlags &= ~0x3; vaFlags |= atUint32(val);} - GX::AttrType normal() const {return GX::AttrType(vaFlags >> 2 & 0x3);} - void setNormal(GX::AttrType val) {vaFlags &= ~0xC; vaFlags |= atUint32(val) << 2;} - GX::AttrType color0() const {return GX::AttrType(vaFlags >> 4 & 0x3);} - void setColor0(GX::AttrType val) {vaFlags &= ~0x30; vaFlags |= atUint32(val) << 4;} - GX::AttrType color1() const {return GX::AttrType(vaFlags >> 6 & 0x3);} - void setColor1(GX::AttrType val) {vaFlags &= ~0xC0; vaFlags |= atUint32(val) << 6;} - GX::AttrType tex0() const {return GX::AttrType(vaFlags >> 8 & 0x3);} - void setTex0(GX::AttrType val) {vaFlags &= ~0x300; vaFlags |= atUint32(val) << 8;} - GX::AttrType tex1() const {return GX::AttrType(vaFlags >> 10 & 0x3);} - void setTex1(GX::AttrType val) {vaFlags &= ~0xC00; vaFlags |= atUint32(val) << 10;} - GX::AttrType tex2() const {return GX::AttrType(vaFlags >> 12 & 0x3);} - void setTex2(GX::AttrType val) {vaFlags &= ~0x3000; vaFlags |= atUint32(val) << 12;} - GX::AttrType tex3() const {return GX::AttrType(vaFlags >> 14 & 0x3);} - void setTex3(GX::AttrType val) {vaFlags &= ~0xC000; vaFlags |= atUint32(val) << 14;} - GX::AttrType tex4() const {return GX::AttrType(vaFlags >> 16 & 0x3);} - void setTex4(GX::AttrType val) {vaFlags &= ~0x30000; vaFlags |= atUint32(val) << 16;} - GX::AttrType tex5() const {return GX::AttrType(vaFlags >> 18 & 0x3);} - void setTex5(GX::AttrType val) {vaFlags &= ~0xC0000; vaFlags |= atUint32(val) << 18;} - GX::AttrType tex6() const {return GX::AttrType(vaFlags >> 20 & 0x3);} - void setTex6(GX::AttrType val) {vaFlags &= ~0x300000; vaFlags |= atUint32(val) << 20;} - GX::AttrType pnMatIdx() const {return GX::AttrType(vaFlags >> 24 & 0x1);} - void setPnMatIdx(GX::AttrType val) {vaFlags &= ~0x1000000; vaFlags |= atUint32(val & 0x1) << 24;} - GX::AttrType tex0MatIdx() const {return GX::AttrType(vaFlags >> 25 & 0x1);} - void setTex0MatIdx(GX::AttrType val) {vaFlags &= ~0x2000000; vaFlags |= atUint32(val & 0x1) << 25;} - GX::AttrType tex1MatIdx() const {return GX::AttrType(vaFlags >> 26 & 0x1);} - void setTex1MatIdx(GX::AttrType val) {vaFlags &= ~0x4000000; vaFlags |= atUint32(val & 0x1) << 26;} - GX::AttrType tex2MatIdx() const {return GX::AttrType(vaFlags >> 27 & 0x1);} - void setTex2MatIdx(GX::AttrType val) {vaFlags &= ~0x8000000; vaFlags |= atUint32(val & 0x1) << 27;} - GX::AttrType tex3MatIdx() const {return GX::AttrType(vaFlags >> 28 & 0x1);} - void setTex3MatIdx(GX::AttrType val) {vaFlags &= ~0x10000000; vaFlags |= atUint32(val & 0x1) << 28;} - GX::AttrType tex4MatIdx() const {return GX::AttrType(vaFlags >> 29 & 0x1);} - void setTex4MatIdx(GX::AttrType val) {vaFlags &= ~0x20000000; vaFlags |= atUint32(val & 0x1) << 29;} - GX::AttrType tex5MatIdx() const {return GX::AttrType(vaFlags >> 30 & 0x1);} - void setTex5MatIdx(GX::AttrType val) {vaFlags &= ~0x40000000; vaFlags |= atUint32(val & 0x1) << 30;} - GX::AttrType tex6MatIdx() const {return GX::AttrType(vaFlags >> 31 & 0x1);} - void setTex6MatIdx(GX::AttrType val) {vaFlags &= ~0x80000000; vaFlags |= atUint32(val & 0x1) << 31;} + Value textureCount = 0; + Vector textureIdxs; + struct VAFlags : BigDNA { + AT_DECL_DNA + Value vaFlags = 0; + GX::AttrType position() const { return GX::AttrType(vaFlags & 0x3); } + void setPosition(GX::AttrType val) { + vaFlags &= ~0x3; + vaFlags |= atUint32(val); + } + GX::AttrType normal() const { return GX::AttrType(vaFlags >> 2 & 0x3); } + void setNormal(GX::AttrType val) { + vaFlags &= ~0xC; + vaFlags |= atUint32(val) << 2; + } + GX::AttrType color0() const { return GX::AttrType(vaFlags >> 4 & 0x3); } + void setColor0(GX::AttrType val) { + vaFlags &= ~0x30; + vaFlags |= atUint32(val) << 4; + } + GX::AttrType color1() const { return GX::AttrType(vaFlags >> 6 & 0x3); } + void setColor1(GX::AttrType val) { + vaFlags &= ~0xC0; + vaFlags |= atUint32(val) << 6; + } + GX::AttrType tex0() const { return GX::AttrType(vaFlags >> 8 & 0x3); } + void setTex0(GX::AttrType val) { + vaFlags &= ~0x300; + vaFlags |= atUint32(val) << 8; + } + GX::AttrType tex1() const { return GX::AttrType(vaFlags >> 10 & 0x3); } + void setTex1(GX::AttrType val) { + vaFlags &= ~0xC00; + vaFlags |= atUint32(val) << 10; + } + GX::AttrType tex2() const { return GX::AttrType(vaFlags >> 12 & 0x3); } + void setTex2(GX::AttrType val) { + vaFlags &= ~0x3000; + vaFlags |= atUint32(val) << 12; + } + GX::AttrType tex3() const { return GX::AttrType(vaFlags >> 14 & 0x3); } + void setTex3(GX::AttrType val) { + vaFlags &= ~0xC000; + vaFlags |= atUint32(val) << 14; + } + GX::AttrType tex4() const { return GX::AttrType(vaFlags >> 16 & 0x3); } + void setTex4(GX::AttrType val) { + vaFlags &= ~0x30000; + vaFlags |= atUint32(val) << 16; + } + GX::AttrType tex5() const { return GX::AttrType(vaFlags >> 18 & 0x3); } + void setTex5(GX::AttrType val) { + vaFlags &= ~0xC0000; + vaFlags |= atUint32(val) << 18; + } + GX::AttrType tex6() const { return GX::AttrType(vaFlags >> 20 & 0x3); } + void setTex6(GX::AttrType val) { + vaFlags &= ~0x300000; + vaFlags |= atUint32(val) << 20; + } + GX::AttrType pnMatIdx() const { return GX::AttrType(vaFlags >> 24 & 0x1); } + void setPnMatIdx(GX::AttrType val) { + vaFlags &= ~0x1000000; + vaFlags |= atUint32(val & 0x1) << 24; + } + GX::AttrType tex0MatIdx() const { return GX::AttrType(vaFlags >> 25 & 0x1); } + void setTex0MatIdx(GX::AttrType val) { + vaFlags &= ~0x2000000; + vaFlags |= atUint32(val & 0x1) << 25; + } + GX::AttrType tex1MatIdx() const { return GX::AttrType(vaFlags >> 26 & 0x1); } + void setTex1MatIdx(GX::AttrType val) { + vaFlags &= ~0x4000000; + vaFlags |= atUint32(val & 0x1) << 26; + } + GX::AttrType tex2MatIdx() const { return GX::AttrType(vaFlags >> 27 & 0x1); } + void setTex2MatIdx(GX::AttrType val) { + vaFlags &= ~0x8000000; + vaFlags |= atUint32(val & 0x1) << 27; + } + GX::AttrType tex3MatIdx() const { return GX::AttrType(vaFlags >> 28 & 0x1); } + void setTex3MatIdx(GX::AttrType val) { + vaFlags &= ~0x10000000; + vaFlags |= atUint32(val & 0x1) << 28; + } + GX::AttrType tex4MatIdx() const { return GX::AttrType(vaFlags >> 29 & 0x1); } + void setTex4MatIdx(GX::AttrType val) { + vaFlags &= ~0x20000000; + vaFlags |= atUint32(val & 0x1) << 29; + } + GX::AttrType tex5MatIdx() const { return GX::AttrType(vaFlags >> 30 & 0x1); } + void setTex5MatIdx(GX::AttrType val) { + vaFlags &= ~0x40000000; + vaFlags |= atUint32(val & 0x1) << 30; + } + GX::AttrType tex6MatIdx() const { return GX::AttrType(vaFlags >> 31 & 0x1); } + void setTex6MatIdx(GX::AttrType val) { + vaFlags &= ~0x80000000; + vaFlags |= atUint32(val & 0x1) << 31; + } - size_t vertDLSize() const - { - static size_t ATTR_SZ[] = {0,1,1,2}; - size_t ret = 0; - ret += ATTR_SZ[position()]; - ret += ATTR_SZ[normal()]; - ret += ATTR_SZ[color0()]; - ret += ATTR_SZ[color1()]; - ret += ATTR_SZ[tex0()]; - ret += ATTR_SZ[tex1()]; - ret += ATTR_SZ[tex2()]; - ret += ATTR_SZ[tex3()]; - ret += ATTR_SZ[tex4()]; - ret += ATTR_SZ[tex5()]; - ret += ATTR_SZ[tex6()]; - ret += ATTR_SZ[pnMatIdx()]; - ret += ATTR_SZ[tex0MatIdx()]; - ret += ATTR_SZ[tex1MatIdx()]; - ret += ATTR_SZ[tex2MatIdx()]; - ret += ATTR_SZ[tex3MatIdx()]; - ret += ATTR_SZ[tex4MatIdx()]; - ret += ATTR_SZ[tex5MatIdx()]; - ret += ATTR_SZ[tex6MatIdx()]; - return ret; - } - } vaFlags; - const VAFlags& getVAFlags() const {return vaFlags;} - Value uniqueIdx; + size_t vertDLSize() const { + static size_t ATTR_SZ[] = {0, 1, 1, 2}; + size_t ret = 0; + ret += ATTR_SZ[position()]; + ret += ATTR_SZ[normal()]; + ret += ATTR_SZ[color0()]; + ret += ATTR_SZ[color1()]; + ret += ATTR_SZ[tex0()]; + ret += ATTR_SZ[tex1()]; + ret += ATTR_SZ[tex2()]; + ret += ATTR_SZ[tex3()]; + ret += ATTR_SZ[tex4()]; + ret += ATTR_SZ[tex5()]; + ret += ATTR_SZ[tex6()]; + ret += ATTR_SZ[pnMatIdx()]; + ret += ATTR_SZ[tex0MatIdx()]; + ret += ATTR_SZ[tex1MatIdx()]; + ret += ATTR_SZ[tex2MatIdx()]; + ret += ATTR_SZ[tex3MatIdx()]; + ret += ATTR_SZ[tex4MatIdx()]; + ret += ATTR_SZ[tex5MatIdx()]; + ret += ATTR_SZ[tex6MatIdx()]; + return ret; + } + } vaFlags; + const VAFlags& getVAFlags() const { return vaFlags; } + Value uniqueIdx; - Vector konstCount; - Vector konstColors; + Vector konstCount; + Vector konstColors; - using BlendFactor = GX::BlendFactor; - Value blendDstFac; - Value blendSrcFac; - Vector indTexSlot; + using BlendFactor = GX::BlendFactor; + Value blendDstFac; + Value blendSrcFac; + Vector indTexSlot; - Value colorChannelCount = 0; - struct ColorChannel : BigDNA - { - AT_DECL_DNA - Value flags = 0; - bool lighting() const {return (flags & 0x1) != 0;} - void setLighting(bool enabled) {flags &= ~0x1; flags |= atUint32(enabled);} - bool useAmbient() const {return (flags & 0x2) != 0;} - void setUseAmbient(bool enabled) {flags &= ~0x2; flags |= atUint32(enabled) << 1;} - bool useMaterial() const {return (flags & 0x4) != 0;} - void setUseMaterial(bool enabled) {flags &= ~0x4; flags |= atUint32(enabled) << 2;} - atUint8 lightmask() const {return atUint8(flags >> 3 & 0xff);} - void setLightmask(atUint8 mask) {flags &= ~0x7f8; flags |= atUint32(mask) << 3;} - GX::DiffuseFn diffuseFn() const {return GX::DiffuseFn(flags >> 11 & 0x3);} - void setDiffuseFn(GX::DiffuseFn fn) {flags &= ~0x1800; flags |= atUint32(fn) << 11;} - GX::AttnFn attenuationFn() const {return GX::AttnFn(flags >> 13 & 0x3);} - void setAttenuationFn(GX::AttnFn fn) {flags &= ~0x6000; flags |= atUint32(fn) << 13;} - }; - Vector colorChannels; - - Value tevStageCount = 0; - struct TEVStage : BigDNA - { - AT_DECL_DNA - Value ciFlags = 0; - Value aiFlags = 0; - Value ccFlags = 0; - Value acFlags = 0; - Value pad = 0; - Value kaInput = 0; - Value kcInput = 0; - Value rascInput = 0; - - GX::TevColorArg colorInA() const {return GX::TevColorArg(ciFlags & 0xf);} - void setColorInA(GX::TevColorArg val) {ciFlags &= ~0x1f; ciFlags |= atUint32(val);} - GX::TevColorArg colorInB() const {return GX::TevColorArg(ciFlags >> 5 & 0xf);} - void setColorInB(GX::TevColorArg val) {ciFlags &= ~0x3e0; ciFlags |= atUint32(val) << 5;} - GX::TevColorArg colorInC() const {return GX::TevColorArg(ciFlags >> 10 & 0xf);} - void setColorInC(GX::TevColorArg val) {ciFlags &= ~0x7c00; ciFlags |= atUint32(val) << 10;} - GX::TevColorArg colorInD() const {return GX::TevColorArg(ciFlags >> 15 & 0xf);} - void setColorInD(GX::TevColorArg val) {ciFlags &= ~0xf8000; ciFlags |= atUint32(val) << 15;} - - GX::TevAlphaArg alphaInA() const {return GX::TevAlphaArg(aiFlags & 0x7);} - void setAlphaInA(GX::TevAlphaArg val) {aiFlags &= ~0x1f; aiFlags |= atUint32(val);} - GX::TevAlphaArg alphaInB() const {return GX::TevAlphaArg(aiFlags >> 5 & 0x7);} - void setAlphaInB(GX::TevAlphaArg val) {aiFlags &= ~0x3e0; aiFlags |= atUint32(val) << 5;} - GX::TevAlphaArg alphaInC() const {return GX::TevAlphaArg(aiFlags >> 10 & 0x7);} - void setAlphaInC(GX::TevAlphaArg val) {aiFlags &= ~0x7c00; aiFlags |= atUint32(val) << 10;} - GX::TevAlphaArg alphaInD() const {return GX::TevAlphaArg(aiFlags >> 15 & 0x7);} - void setAlphaInD(GX::TevAlphaArg val) {aiFlags &= ~0xf8000; aiFlags |= atUint32(val) << 15;} - - GX::TevOp colorOp() const {return GX::TevOp(ccFlags & 0xf);} - void setColorOp(GX::TevOp val) {ccFlags &= ~0x1; ccFlags |= atUint32(val);} - GX::TevBias colorOpBias() const {return GX::TevBias(ccFlags >> 4 & 0x3);} - void setColorOpBias(GX::TevBias val) {ccFlags &= ~0x30; ccFlags |= atUint32(val) << 4;} - GX::TevScale colorOpScale() const {return GX::TevScale(ccFlags >> 6 & 0x3);} - void setColorOpScale(GX::TevScale val) {ccFlags &= ~0xc0; ccFlags |= atUint32(val) << 6;} - bool colorOpClamp() const {return ccFlags >> 8 & 0x1;} - void setColorOpClamp(bool val) {ccFlags &= ~0x100; ccFlags |= atUint32(val) << 8;} - GX::TevRegID colorOpOutReg() const {return GX::TevRegID(ccFlags >> 9 & 0x3);} - void setColorOpOutReg(GX::TevRegID val) {ccFlags &= ~0x600; ccFlags |= atUint32(val) << 9;} - - GX::TevOp alphaOp() const {return GX::TevOp(acFlags & 0xf);} - void setAlphaOp(GX::TevOp val) {acFlags &= ~0x1; acFlags |= atUint32(val);} - GX::TevBias alphaOpBias() const {return GX::TevBias(acFlags >> 4 & 0x3);} - void setAlphaOpBias(GX::TevBias val) {acFlags &= ~0x30; acFlags |= atUint32(val) << 4;} - GX::TevScale alphaOpScale() const {return GX::TevScale(acFlags >> 6 & 0x3);} - void setAlphaOpScale(GX::TevScale val) {acFlags &= ~0xc0; acFlags |= atUint32(val) << 6;} - bool alphaOpClamp() const {return acFlags >> 8 & 0x1;} - void setAlphaOpClamp(bool val) {acFlags &= ~0x100; acFlags |= atUint32(val) << 8;} - GX::TevRegID alphaOpOutReg() const {return GX::TevRegID(acFlags >> 9 & 0x3);} - void setAlphaOpOutReg(GX::TevRegID val) {acFlags &= ~0x600; acFlags |= atUint32(val) << 9;} - - GX::TevKColorSel kColorIn() const {return GX::TevKColorSel(kcInput);} - void setKColorIn(GX::TevKColorSel val) {kcInput = val;} - GX::TevKAlphaSel kAlphaIn() const {return GX::TevKAlphaSel(kaInput);} - void setKAlphaIn(GX::TevKAlphaSel val) {kaInput = val;} - - GX::ChannelID rasIn() const {return GX::ChannelID(rascInput);} - void setRASIn(GX::ChannelID id) {rascInput = id;} - }; - Vector tevStages; - struct TEVStageTexInfo : BigDNA - { - AT_DECL_DNA - Value pad = 0; - Value texSlot = 0xff; - Value tcgSlot = 0xff; - }; - Vector tevStageTexInfo; - - Value tcgCount = 0; - struct TexCoordGen : BigDNA - { - AT_DECL_DNA - Value flags = 0; - - GX::TexGenType type() const {return GX::TexGenType(flags & 0xf);} - void setType(GX::TexGenType val) {flags &= ~0xf; flags |= atUint32(val);} - GX::TexGenSrc source() const {return GX::TexGenSrc(flags >> 4 & 0x1f);} - void setSource(GX::TexGenSrc val) {flags &= ~0x1f0; flags |= atUint32(val) << 4;} - GX::TexMtx mtx() const {return GX::TexMtx((flags >> 9 & 0x1f) + 30);} - void setMtx(GX::TexMtx val) {flags &= ~0x3e00; flags |= (atUint32(val)-30) << 9;} - bool normalize() const {return flags >> 14 & 0x1;} - void setNormalize(bool val) {flags &= ~0x4000; flags |= atUint32(val) << 14;} - GX::PTTexMtx postMtx() const {return GX::PTTexMtx((flags >> 15 & 0x3f) + 64);} - void setPostMtx(GX::PTTexMtx val) {flags &= ~0x1f8000; flags |= (atUint32(val)-64) << 15;} - }; - Vector tcgs; - - Value uvAnimsSize = 4; - Value uvAnimsCount = 0; - struct UVAnimation : BigDNA - { - AT_DECL_EXPLICIT_DNA - enum class Mode - { - MvInvNoTranslation, - MvInv, - Scroll, - Rotation, - HStrip, - VStrip, - Model, - CylinderEnvironment, - Eight - } mode; - float vals[9]; - - UVAnimation() = default; - UVAnimation(const std::string& gameFunction, - const std::vector& gameArgs); - }; - Vector uvAnims; - - static void AddTexture(hecl::blender::PyOutStream& out, - GX::TexGenSrc type, int mtxIdx, uint32_t texIdx); - static void AddTextureAnim(hecl::blender::PyOutStream& out, - MaterialSet::Material::UVAnimation::Mode type, - unsigned idx, const float* vals); - static void AddKcolor(hecl::blender::PyOutStream& out, - const GX::Color& col, unsigned idx); - static void AddDynamicColor(hecl::blender::PyOutStream& out, unsigned idx); - static void AddDynamicAlpha(hecl::blender::PyOutStream& out, unsigned idx); - - Material() = default; - Material(const hecl::Backend::GX& gx, - const std::unordered_map& iprops, - const std::vector& texPathsIn, - std::vector& texPathsOut, - int colorCount, - bool lightmapUVs, - bool matrixSkinning); + Value colorChannelCount = 0; + struct ColorChannel : BigDNA { + AT_DECL_DNA + Value flags = 0; + bool lighting() const { return (flags & 0x1) != 0; } + void setLighting(bool enabled) { + flags &= ~0x1; + flags |= atUint32(enabled); + } + bool useAmbient() const { return (flags & 0x2) != 0; } + void setUseAmbient(bool enabled) { + flags &= ~0x2; + flags |= atUint32(enabled) << 1; + } + bool useMaterial() const { return (flags & 0x4) != 0; } + void setUseMaterial(bool enabled) { + flags &= ~0x4; + flags |= atUint32(enabled) << 2; + } + atUint8 lightmask() const { return atUint8(flags >> 3 & 0xff); } + void setLightmask(atUint8 mask) { + flags &= ~0x7f8; + flags |= atUint32(mask) << 3; + } + GX::DiffuseFn diffuseFn() const { return GX::DiffuseFn(flags >> 11 & 0x3); } + void setDiffuseFn(GX::DiffuseFn fn) { + flags &= ~0x1800; + flags |= atUint32(fn) << 11; + } + GX::AttnFn attenuationFn() const { return GX::AttnFn(flags >> 13 & 0x3); } + void setAttenuationFn(GX::AttnFn fn) { + flags &= ~0x6000; + flags |= atUint32(fn) << 13; + } }; - Vector materials; + Vector colorChannels; - static void RegisterMaterialProps(hecl::blender::PyOutStream& out); - static void ConstructMaterial(hecl::blender::PyOutStream& out, - const MaterialSet::Material& material, - unsigned groupIdx, unsigned matIdx); + Value tevStageCount = 0; + struct TEVStage : BigDNA { + AT_DECL_DNA + Value ciFlags = 0; + Value aiFlags = 0; + Value ccFlags = 0; + Value acFlags = 0; + Value pad = 0; + Value kaInput = 0; + Value kcInput = 0; + Value rascInput = 0; - void readToBlender(hecl::blender::PyOutStream& os, - const PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - unsigned setIdx) - { - DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx); - } + GX::TevColorArg colorInA() const { return GX::TevColorArg(ciFlags & 0xf); } + void setColorInA(GX::TevColorArg val) { + ciFlags &= ~0x1f; + ciFlags |= atUint32(val); + } + GX::TevColorArg colorInB() const { return GX::TevColorArg(ciFlags >> 5 & 0xf); } + void setColorInB(GX::TevColorArg val) { + ciFlags &= ~0x3e0; + ciFlags |= atUint32(val) << 5; + } + GX::TevColorArg colorInC() const { return GX::TevColorArg(ciFlags >> 10 & 0xf); } + void setColorInC(GX::TevColorArg val) { + ciFlags &= ~0x7c00; + ciFlags |= atUint32(val) << 10; + } + GX::TevColorArg colorInD() const { return GX::TevColorArg(ciFlags >> 15 & 0xf); } + void setColorInD(GX::TevColorArg val) { + ciFlags &= ~0xf8000; + ciFlags |= atUint32(val) << 15; + } - template - void nameTextures(PAKRouter& pakRouter, const char* prefix, int setIdx) const - { - int matIdx = 0; - for (const Material& mat : materials) - { - int stageIdx = 0; - for (const Material::TEVStage& stage : mat.tevStages) - { - (void)stage; - const Material::TEVStageTexInfo& texInfo = mat.tevStageTexInfo[stageIdx]; - if (texInfo.texSlot == 0xff) - { - ++stageIdx; - continue; - } - const nod::Node* node; - typename PAKRouter::EntryType* texEntry = (typename PAKRouter::EntryType*) - pakRouter.lookupEntry(head.textureIDs[mat.textureIdxs[texInfo.texSlot]], &node); - if (texEntry->name.size()) - { - if (texEntry->name.size() < 5 || texEntry->name.compare(0, 5, "mult_")) - texEntry->name = "mult_" + texEntry->name; - ++stageIdx; - continue; - } - if (setIdx < 0) - texEntry->name = hecl::Format("%s_%d_%d", prefix, matIdx, stageIdx); - else - texEntry->name = hecl::Format("%s_%d_%d_%d", prefix, setIdx, matIdx, stageIdx); + GX::TevAlphaArg alphaInA() const { return GX::TevAlphaArg(aiFlags & 0x7); } + void setAlphaInA(GX::TevAlphaArg val) { + aiFlags &= ~0x1f; + aiFlags |= atUint32(val); + } + GX::TevAlphaArg alphaInB() const { return GX::TevAlphaArg(aiFlags >> 5 & 0x7); } + void setAlphaInB(GX::TevAlphaArg val) { + aiFlags &= ~0x3e0; + aiFlags |= atUint32(val) << 5; + } + GX::TevAlphaArg alphaInC() const { return GX::TevAlphaArg(aiFlags >> 10 & 0x7); } + void setAlphaInC(GX::TevAlphaArg val) { + aiFlags &= ~0x7c00; + aiFlags |= atUint32(val) << 10; + } + GX::TevAlphaArg alphaInD() const { return GX::TevAlphaArg(aiFlags >> 15 & 0x7); } + void setAlphaInD(GX::TevAlphaArg val) { + aiFlags &= ~0xf8000; + aiFlags |= atUint32(val) << 15; + } - if (mat.flags.lightmap() && stageIdx == 0) - { - texEntry->name += "light"; - ++stageIdx; - continue; - } + GX::TevOp colorOp() const { return GX::TevOp(ccFlags & 0xf); } + void setColorOp(GX::TevOp val) { + ccFlags &= ~0x1; + ccFlags |= atUint32(val); + } + GX::TevBias colorOpBias() const { return GX::TevBias(ccFlags >> 4 & 0x3); } + void setColorOpBias(GX::TevBias val) { + ccFlags &= ~0x30; + ccFlags |= atUint32(val) << 4; + } + GX::TevScale colorOpScale() const { return GX::TevScale(ccFlags >> 6 & 0x3); } + void setColorOpScale(GX::TevScale val) { + ccFlags &= ~0xc0; + ccFlags |= atUint32(val) << 6; + } + bool colorOpClamp() const { return ccFlags >> 8 & 0x1; } + void setColorOpClamp(bool val) { + ccFlags &= ~0x100; + ccFlags |= atUint32(val) << 8; + } + GX::TevRegID colorOpOutReg() const { return GX::TevRegID(ccFlags >> 9 & 0x3); } + void setColorOpOutReg(GX::TevRegID val) { + ccFlags &= ~0x600; + ccFlags |= atUint32(val) << 9; + } - ++stageIdx; - } - ++matIdx; + GX::TevOp alphaOp() const { return GX::TevOp(acFlags & 0xf); } + void setAlphaOp(GX::TevOp val) { + acFlags &= ~0x1; + acFlags |= atUint32(val); + } + GX::TevBias alphaOpBias() const { return GX::TevBias(acFlags >> 4 & 0x3); } + void setAlphaOpBias(GX::TevBias val) { + acFlags &= ~0x30; + acFlags |= atUint32(val) << 4; + } + GX::TevScale alphaOpScale() const { return GX::TevScale(acFlags >> 6 & 0x3); } + void setAlphaOpScale(GX::TevScale val) { + acFlags &= ~0xc0; + acFlags |= atUint32(val) << 6; + } + bool alphaOpClamp() const { return acFlags >> 8 & 0x1; } + void setAlphaOpClamp(bool val) { + acFlags &= ~0x100; + acFlags |= atUint32(val) << 8; + } + GX::TevRegID alphaOpOutReg() const { return GX::TevRegID(acFlags >> 9 & 0x3); } + void setAlphaOpOutReg(GX::TevRegID val) { + acFlags &= ~0x600; + acFlags |= atUint32(val) << 9; + } + + GX::TevKColorSel kColorIn() const { return GX::TevKColorSel(kcInput); } + void setKColorIn(GX::TevKColorSel val) { kcInput = val; } + GX::TevKAlphaSel kAlphaIn() const { return GX::TevKAlphaSel(kaInput); } + void setKAlphaIn(GX::TevKAlphaSel val) { kaInput = val; } + + GX::ChannelID rasIn() const { return GX::ChannelID(rascInput); } + void setRASIn(GX::ChannelID id) { rascInput = id; } + }; + Vector tevStages; + struct TEVStageTexInfo : BigDNA { + AT_DECL_DNA + Value pad = 0; + Value texSlot = 0xff; + Value tcgSlot = 0xff; + }; + Vector tevStageTexInfo; + + Value tcgCount = 0; + struct TexCoordGen : BigDNA { + AT_DECL_DNA + Value flags = 0; + + GX::TexGenType type() const { return GX::TexGenType(flags & 0xf); } + void setType(GX::TexGenType val) { + flags &= ~0xf; + flags |= atUint32(val); + } + GX::TexGenSrc source() const { return GX::TexGenSrc(flags >> 4 & 0x1f); } + void setSource(GX::TexGenSrc val) { + flags &= ~0x1f0; + flags |= atUint32(val) << 4; + } + GX::TexMtx mtx() const { return GX::TexMtx((flags >> 9 & 0x1f) + 30); } + void setMtx(GX::TexMtx val) { + flags &= ~0x3e00; + flags |= (atUint32(val) - 30) << 9; + } + bool normalize() const { return flags >> 14 & 0x1; } + void setNormalize(bool val) { + flags &= ~0x4000; + flags |= atUint32(val) << 14; + } + GX::PTTexMtx postMtx() const { return GX::PTTexMtx((flags >> 15 & 0x3f) + 64); } + void setPostMtx(GX::PTTexMtx val) { + flags &= ~0x1f8000; + flags |= (atUint32(val) - 64) << 15; + } + }; + Vector tcgs; + + Value uvAnimsSize = 4; + Value uvAnimsCount = 0; + struct UVAnimation : BigDNA { + AT_DECL_EXPLICIT_DNA + enum class Mode { + MvInvNoTranslation, + MvInv, + Scroll, + Rotation, + HStrip, + VStrip, + Model, + CylinderEnvironment, + Eight + } mode; + float vals[9]; + + UVAnimation() = default; + UVAnimation(const std::string& gameFunction, const std::vector& gameArgs); + }; + Vector uvAnims; + + static void AddTexture(hecl::blender::PyOutStream& out, GX::TexGenSrc type, int mtxIdx, uint32_t texIdx); + static void AddTextureAnim(hecl::blender::PyOutStream& out, MaterialSet::Material::UVAnimation::Mode type, + unsigned idx, const float* vals); + static void AddKcolor(hecl::blender::PyOutStream& out, const GX::Color& col, unsigned idx); + static void AddDynamicColor(hecl::blender::PyOutStream& out, unsigned idx); + static void AddDynamicAlpha(hecl::blender::PyOutStream& out, unsigned idx); + + Material() = default; + Material(const hecl::Backend::GX& gx, const std::unordered_map& iprops, + const std::vector& texPathsIn, std::vector& texPathsOut, + int colorCount, bool lightmapUVs, bool matrixSkinning); + }; + Vector materials; + + static void RegisterMaterialProps(hecl::blender::PyOutStream& out); + static void ConstructMaterial(hecl::blender::PyOutStream& out, const MaterialSet::Material& material, + unsigned groupIdx, unsigned matIdx); + + void readToBlender(hecl::blender::PyOutStream& os, const PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, unsigned setIdx) { + DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx); + } + + template + void nameTextures(PAKRouter& pakRouter, const char* prefix, int setIdx) const { + int matIdx = 0; + for (const Material& mat : materials) { + int stageIdx = 0; + for (const Material::TEVStage& stage : mat.tevStages) { + (void)stage; + const Material::TEVStageTexInfo& texInfo = mat.tevStageTexInfo[stageIdx]; + if (texInfo.texSlot == 0xff) { + ++stageIdx; + continue; } - } + const nod::Node* node; + typename PAKRouter::EntryType* texEntry = (typename PAKRouter::EntryType*)pakRouter.lookupEntry( + head.textureIDs[mat.textureIdxs[texInfo.texSlot]], &node); + if (texEntry->name.size()) { + if (texEntry->name.size() < 5 || texEntry->name.compare(0, 5, "mult_")) + texEntry->name = "mult_" + texEntry->name; + ++stageIdx; + continue; + } + if (setIdx < 0) + texEntry->name = hecl::Format("%s_%d_%d", prefix, matIdx, stageIdx); + else + texEntry->name = hecl::Format("%s_%d_%d_%d", prefix, setIdx, matIdx, stageIdx); - void ensureTexturesExtracted(PAKRouter& pakRouter) const - { - head.ensureTexturesExtracted(pakRouter); + if (mat.flags.lightmap() && stageIdx == 0) { + texEntry->name += "light"; + ++stageIdx; + continue; + } + + ++stageIdx; + } + ++matIdx; } + } + + void ensureTexturesExtracted(PAKRouter& pakRouter) const { head.ensureTexturesExtracted(pakRouter); } }; -struct HMDLMaterialSet : BigDNA -{ - static constexpr bool OneSection() {return false;} +struct HMDLMaterialSet : BigDNA { + static constexpr bool OneSection() { return false; } + AT_DECL_DNA + MaterialSet::MaterialSetHead head; + + struct Material : BigDNA { AT_DECL_DNA - MaterialSet::MaterialSetHead head; + MaterialSet::Material::Flags flags; - struct Material : BigDNA - { - AT_DECL_DNA - MaterialSet::Material::Flags flags; + Value textureCount = 0; + Vector textureIdxs; - Value textureCount = 0; - Vector textureIdxs; + Vector indTexSlot; - Vector indTexSlot; + Value uvAnimsSize = 4; + Value uvAnimsCount = 0; + Vector uvAnims; - Value uvAnimsSize = 4; - Value uvAnimsCount = 0; - Vector uvAnims; + String<-1> heclSource; + hecl::Frontend::IR heclIr; - String<-1> heclSource; - hecl::Frontend::IR heclIr; - - Material() = default; - Material(hecl::Frontend::Frontend& FE, - const std::string& diagName, - const hecl::blender::Material& mat, - const std::unordered_map& iprops, - const std::vector& texPaths); - }; - Vector materials; + Material() = default; + Material(hecl::Frontend::Frontend& FE, const std::string& diagName, const hecl::blender::Material& mat, + const std::unordered_map& iprops, const std::vector& texPaths); + }; + Vector materials; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CSKR.cpp b/DataSpec/DNAMP1/CSKR.cpp index f414cd108..83acf7c7f 100644 --- a/DataSpec/DNAMP1/CSKR.cpp +++ b/DataSpec/DNAMP1/CSKR.cpp @@ -1,21 +1,16 @@ #include "CSKR.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const -{ - atUint32 accum = 0; - for (const SkinningRule& rule : skinningRules) - { - if (idx >= accum && idx < accum + rule.vertCount) - for (const SkinningRule::Weight& weight : rule.weights) - os.format("vert[dvert_lay][%u] = %f\n", - cinf.getBoneIdxFromId(weight.boneId), - weight.weight); - accum += rule.vertCount; - } +void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const { + atUint32 accum = 0; + for (const SkinningRule& rule : skinningRules) { + if (idx >= accum && idx < accum + rule.vertCount) + for (const SkinningRule::Weight& weight : rule.weights) + os.format("vert[dvert_lay][%u] = %f\n", cinf.getBoneIdxFromId(weight.boneId), weight.weight); + accum += rule.vertCount; + } } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CSKR.hpp b/DataSpec/DNAMP1/CSKR.hpp index 49c67cf7c..c31c9234a 100644 --- a/DataSpec/DNAMP1/CSKR.hpp +++ b/DataSpec/DNAMP1/CSKR.hpp @@ -3,35 +3,27 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "CINF.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CSKR : BigDNA -{ +struct CSKR : BigDNA { + AT_DECL_DNA + Value skinningRuleCount; + struct SkinningRule : BigDNA { AT_DECL_DNA - Value skinningRuleCount; - struct SkinningRule : BigDNA - { - AT_DECL_DNA - Value weightCount; - struct Weight : BigDNA - { - AT_DECL_DNA - Value boneId; - Value weight; - }; - Vector weights; - Value vertCount; + Value weightCount; + struct Weight : BigDNA { + AT_DECL_DNA + Value boneId; + Value weight; }; - Vector skinningRules; + Vector weights; + Value vertCount; + }; + Vector skinningRules; - const atInt16* getMatrixBank(size_t) const - { - return nullptr; - } + const atInt16* getMatrixBank(size_t) const { return nullptr; } - void weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const; + void weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CSNG.cpp b/DataSpec/DNAMP1/CSNG.cpp index 661a2e730..744ecbd54 100644 --- a/DataSpec/DNAMP1/CSNG.cpp +++ b/DataSpec/DNAMP1/CSNG.cpp @@ -1,102 +1,99 @@ #include "CSNG.hpp" #include "amuse/SongConverter.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -bool CSNG::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) -{ - hecl::ProjectPath midPath = outPath.getWithExtension(_SYS_STR(".mid"), true); - hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true); +bool CSNG::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + hecl::ProjectPath midPath = outPath.getWithExtension(_SYS_STR(".mid"), true); + hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true); + + Header head; + head.read(rs); + + { + athena::io::YAMLDocWriter dw("CSNG"); + dw.writeUint32("midiSetupId", head.midiSetupId); + dw.writeUint32("songGroupId", head.songGroupId); + if (auto rec = dw.enterSubRecord("agscId")) + head.agscId.write(dw); + + athena::io::FileWriter w(yamlPath.getAbsolutePath()); + if (w.hasError()) + return false; + dw.finish(&w); + } + + { + auto sng = rs.readUBytes(head.sngLength); + int version; + bool isBig; + auto midi = amuse::SongConverter::SongToMIDI(sng.get(), version, isBig); + + athena::io::FileWriter w(midPath.getAbsolutePath()); + if (w.hasError()) + return false; + w.writeUBytes(midi.data(), midi.size()); + } + + /* Update !songs.yaml for Amuse editor */ + hecl::ProjectPath audGrp(outPath.getParentPath().getParentPath(), _SYS_STR("AudioGrp")); + audGrp.makeDirChain(true); + hecl::ProjectPath songsPath(audGrp, _SYS_STR("!songs.yaml")); + std::experimental::optional r; + if (songsPath.isFile()) + r.emplace(songsPath.getAbsolutePath()); + athena::io::YAMLDocWriter ydw("amuse::Songs", r ? &*r : nullptr); + r = std::experimental::nullopt; + char id[16]; + snprintf(id, 16, "%04X", head.midiSetupId); + ydw.writeString(id, hecl::Format("../MidiData/%s", midPath.getLastComponentUTF8().data())); + athena::io::FileWriter w(songsPath.getAbsolutePath()); + ydw.finish(&w); + + return true; +} + +bool CSNG::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + hecl::ProjectPath midPath = inPath.getWithExtension(_SYS_STR(".mid"), true); + hecl::ProjectPath yamlPath = inPath.getWithExtension(_SYS_STR(".yaml"), true); + + std::vector sngData; + { + athena::io::FileReader midR(midPath.getAbsolutePath()); + if (midR.hasError()) + return false; + + uint32_t midLen = midR.length(); + std::vector midData; + midData.resize(midLen); + midR.readUBytesToBuf(midData.data(), midLen); + sngData = amuse::SongConverter::MIDIToSong(midData, 1, true); + } + + athena::io::FileWriter w(outPath.getAbsolutePath()); + if (w.hasError()) + return false; + + { + athena::io::FileReader yamlR(yamlPath.getAbsolutePath()); + if (yamlR.hasError()) + return false; + athena::io::YAMLDocReader dr; + if (!dr.parse(&yamlR)) + return false; Header head; - head.read(rs); + head.midiSetupId = dr.readUint32("midiSetupId"); + head.songGroupId = dr.readUint32("songGroupId"); + if (auto rec = dr.enterSubRecord("agscId")) + head.agscId.read(dr); + head.sngLength = sngData.size(); + head.write(w); + } - { - athena::io::YAMLDocWriter dw("CSNG"); - dw.writeUint32("midiSetupId", head.midiSetupId); - dw.writeUint32("songGroupId", head.songGroupId); - if (auto rec = dw.enterSubRecord("agscId")) - head.agscId.write(dw); + w.writeUBytes(sngData.data(), sngData.size()); - athena::io::FileWriter w(yamlPath.getAbsolutePath()); - if (w.hasError()) - return false; - dw.finish(&w); - } - - { - auto sng = rs.readUBytes(head.sngLength); - int version; - bool isBig; - auto midi = amuse::SongConverter::SongToMIDI(sng.get(), version, isBig); - - athena::io::FileWriter w(midPath.getAbsolutePath()); - if (w.hasError()) - return false; - w.writeUBytes(midi.data(), midi.size()); - } - - /* Update !songs.yaml for Amuse editor */ - hecl::ProjectPath audGrp(outPath.getParentPath().getParentPath(), _SYS_STR("AudioGrp")); - audGrp.makeDirChain(true); - hecl::ProjectPath songsPath(audGrp, _SYS_STR("!songs.yaml")); - std::experimental::optional r; - if (songsPath.isFile()) - r.emplace(songsPath.getAbsolutePath()); - athena::io::YAMLDocWriter ydw("amuse::Songs", r ? &*r : nullptr); - r = std::experimental::nullopt; - char id[16]; - snprintf(id, 16, "%04X", head.midiSetupId); - ydw.writeString(id, hecl::Format("../MidiData/%s", midPath.getLastComponentUTF8().data())); - athena::io::FileWriter w(songsPath.getAbsolutePath()); - ydw.finish(&w); - - return true; + return true; } -bool CSNG::Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) -{ - hecl::ProjectPath midPath = inPath.getWithExtension(_SYS_STR(".mid"), true); - hecl::ProjectPath yamlPath = inPath.getWithExtension(_SYS_STR(".yaml"), true); - - std::vector sngData; - { - athena::io::FileReader midR(midPath.getAbsolutePath()); - if (midR.hasError()) - return false; - - uint32_t midLen = midR.length(); - std::vector midData; - midData.resize(midLen); - midR.readUBytesToBuf(midData.data(), midLen); - sngData = amuse::SongConverter::MIDIToSong(midData, 1, true); - } - - athena::io::FileWriter w(outPath.getAbsolutePath()); - if (w.hasError()) - return false; - - { - athena::io::FileReader yamlR(yamlPath.getAbsolutePath()); - if (yamlR.hasError()) - return false; - athena::io::YAMLDocReader dr; - if (!dr.parse(&yamlR)) - return false; - - Header head; - head.midiSetupId = dr.readUint32("midiSetupId"); - head.songGroupId = dr.readUint32("songGroupId"); - if (auto rec = dr.enterSubRecord("agscId")) - head.agscId.read(dr); - head.sngLength = sngData.size(); - head.write(w); - } - - w.writeUBytes(sngData.data(), sngData.size()); - - return true; -} - -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/CSNG.hpp b/DataSpec/DNAMP1/CSNG.hpp index 26c65e900..da45efe47 100644 --- a/DataSpec/DNAMP1/CSNG.hpp +++ b/DataSpec/DNAMP1/CSNG.hpp @@ -3,24 +3,21 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { + +class CSNG { + struct Header : BigDNA { + AT_DECL_DNA + Value magic = 0x2; + Value midiSetupId; + Value songGroupId; + UniqueID32 agscId; + Value sngLength; + }; -class CSNG -{ - struct Header : BigDNA - { - AT_DECL_DNA - Value magic = 0x2; - Value midiSetupId; - Value songGroupId; - UniqueID32 agscId; - Value sngLength; - }; public: - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath); + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/DCLN.cpp b/DataSpec/DNAMP1/DCLN.cpp index 02b5ffcd8..8c5f71f57 100644 --- a/DataSpec/DNAMP1/DCLN.cpp +++ b/DataSpec/DNAMP1/DCLN.cpp @@ -1,138 +1,121 @@ #include "DCLN.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { #if DCLN_DUMP_OBB -void DCLN::Collision::Node::sendToBlender(hecl::blender::PyOutStream& os) const -{ - os.format("obj = bpy.data.objects.new('%s', None)\n" - "obj.empty_draw_type = 'CUBE'\n" - "bpy.context.scene.objects.link(obj)\n" - "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "obj.rotation_mode = 'QUATERNION'\n" - "obj.location = mtxd[0]\n" - "obj.rotation_quaternion = mtxd[1]\n" - "obj.scale = (%f,%f,%f)\n", isLeaf ? "leaf" : "branch", - xf[0].vec[0], xf[0].vec[1], xf[0].vec[2], xf[0].vec[3], - xf[1].vec[0], xf[1].vec[1], xf[1].vec[2], xf[1].vec[3], - xf[2].vec[0], xf[2].vec[1], xf[2].vec[2], xf[2].vec[3], - halfExtent.vec[0], halfExtent.vec[1], halfExtent.vec[2]); - if (isLeaf) - os << "obj.show_name = True\n"; - if (!isLeaf) - { - left->sendToBlender(os); - right->sendToBlender(os); - } +void DCLN::Collision::Node::sendToBlender(hecl::blender::PyOutStream& os) const { + os.format( + "obj = bpy.data.objects.new('%s', None)\n" + "obj.empty_draw_type = 'CUBE'\n" + "bpy.context.scene.objects.link(obj)\n" + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "obj.rotation_mode = 'QUATERNION'\n" + "obj.location = mtxd[0]\n" + "obj.rotation_quaternion = mtxd[1]\n" + "obj.scale = (%f,%f,%f)\n", + isLeaf ? "leaf" : "branch", xf[0].vec[0], xf[0].vec[1], xf[0].vec[2], xf[0].vec[3], xf[1].vec[0], xf[1].vec[1], + xf[1].vec[2], xf[1].vec[3], xf[2].vec[0], xf[2].vec[1], xf[2].vec[2], xf[2].vec[3], halfExtent.vec[0], + halfExtent.vec[1], halfExtent.vec[2]); + if (isLeaf) + os << "obj.show_name = True\n"; + if (!isLeaf) { + left->sendToBlender(os); + right->sendToBlender(os); + } } #endif template -void DCLN::Collision::Node::Enumerate(typename Op::StreamT& s) -{ - Do({"xf[0]"}, xf[0], s); - Do({"xf[1]"}, xf[1], s); - Do({"xf[2]"}, xf[2], s); - Do({"halfExtent"}, halfExtent, s); - Do({"isLeaf"}, isLeaf, s); - if (isLeaf) - { - if (!leafData) - leafData.reset(new LeafData); - Do({"leafData"}, *leafData, s); - } - else - { - if (!left) - left.reset(new Node); - Do({"left"}, *left, s); - if (!right) - right.reset(new Node); - Do({"right"}, *right, s); - } +void DCLN::Collision::Node::Enumerate(typename Op::StreamT& s) { + Do({"xf[0]"}, xf[0], s); + Do({"xf[1]"}, xf[1], s); + Do({"xf[2]"}, xf[2], s); + Do({"halfExtent"}, halfExtent, s); + Do({"isLeaf"}, isLeaf, s); + if (isLeaf) { + if (!leafData) + leafData.reset(new LeafData); + Do({"leafData"}, *leafData, s); + } else { + if (!left) + left.reset(new Node); + Do({"left"}, *left, s); + if (!right) + right.reset(new Node); + Do({"right"}, *right, s); + } } AT_SPECIALIZE_DNA(DCLN::Collision::Node) -void DCLN::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName) -{ - /* Open Py Stream and read sections */ - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "from mathutils import Vector, Matrix\n" - "\n" - "bpy.context.scene.name = '%s'\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n", - entryName.data()); +void DCLN::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName) { + /* Open Py Stream and read sections */ + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os.format( + "import bpy\n" + "import bmesh\n" + "from mathutils import Vector, Matrix\n" + "\n" + "bpy.context.scene.name = '%s'\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " if ob.type != 'CAMERA':\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n", + entryName.data()); - DeafBabe::BlenderInit(os); - atInt32 idx = 0; - for (const Collision& col : collision) - { - DeafBabeSendToBlender(os, col, true, idx++); + DeafBabe::BlenderInit(os); + atInt32 idx = 0; + for (const Collision& col : collision) { + DeafBabeSendToBlender(os, col, true, idx++); #if DCLN_DUMP_OBB - col.root.sendToBlender(os); + col.root.sendToBlender(os); #endif - } - os.centerView(); - os.close(); + } + os.centerView(); + os.close(); } -bool DCLN::Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) -{ - DCLN dcln; - dcln.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::ColMesh)) - return false; +bool DCLN::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + DCLN dcln; + dcln.read(rs); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::ColMesh)) + return false; - dcln.sendToBlender(conn, pakRouter.getBestEntryName(entry, false)); - return conn.saveBlend(); + dcln.sendToBlender(conn, pakRouter.getBestEntryName(entry, false)); + return conn.saveBlend(); } -bool DCLN::Cook(const hecl::ProjectPath& outPath, - const std::vector& meshes) -{ - DCLN dcln; - dcln.colCount = atUint32(meshes.size()); - for (const Mesh& mesh : meshes) - { - dcln.collision.emplace_back(); - Collision& colOut = dcln.collision.back(); - DeafBabeBuildFromBlender(colOut, mesh); - colOut.root = std::move(*OBBTreeBuilder::buildCol(mesh)); - colOut.memSize = atUint32(colOut.root.getMemoryUsage()); - } +bool DCLN::Cook(const hecl::ProjectPath& outPath, const std::vector& meshes) { + DCLN dcln; + dcln.colCount = atUint32(meshes.size()); + for (const Mesh& mesh : meshes) { + dcln.collision.emplace_back(); + Collision& colOut = dcln.collision.back(); + DeafBabeBuildFromBlender(colOut, mesh); + colOut.root = std::move(*OBBTreeBuilder::buildCol(mesh)); + colOut.memSize = atUint32(colOut.root.getMemoryUsage()); + } #if DCLN_DUMP_OBB - hecl::blender::Connection& conn = hecl::blender::SharedBlenderToken.getBlenderConnection(); - conn.createBlend(outPath.getWithExtension(_SYS_STR(".blend")), hecl::blender::BlendType::ColMesh); - dcln.sendToBlender(conn, "BLAH"); - conn.saveBlend(); + hecl::blender::Connection& conn = hecl::blender::SharedBlenderToken.getBlenderConnection(); + conn.createBlend(outPath.getWithExtension(_SYS_STR(".blend")), hecl::blender::BlendType::ColMesh); + dcln.sendToBlender(conn, "BLAH"); + conn.saveBlend(); #endif - athena::io::FileWriter w(outPath.getAbsolutePath()); - dcln.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; + athena::io::FileWriter w(outPath.getAbsolutePath()); + dcln.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/DCLN.hpp b/DataSpec/DNAMP1/DCLN.hpp index 7d4873cfa..f5e96a411 100644 --- a/DataSpec/DNAMP1/DCLN.hpp +++ b/DataSpec/DNAMP1/DCLN.hpp @@ -9,103 +9,86 @@ #define DCLN_DUMP_OBB 0 -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct DCLN : BigDNA -{ - using Mesh = hecl::blender::ColMesh; +struct DCLN : BigDNA { + using Mesh = hecl::blender::ColMesh; + + AT_DECL_DNA + Value colCount; + struct Collision : BigDNA { + using Material = DeafBabe::Material; + using Edge = DeafBabe::Edge; + using Triangle = DeafBabe::Triangle; AT_DECL_DNA - Value colCount; - struct Collision : BigDNA - { - using Material = DeafBabe::Material; - using Edge = DeafBabe::Edge; - using Triangle = DeafBabe::Triangle; + Value magic; + Value version; + Value memSize; + Value materialCount; + Vector materials; + Value vertMatsCount; + Vector vertMats; + Value edgeMatsCount; + Vector edgeMats; + Value triMatsCount; + Vector triMats; + Value edgeVertsCount; + Vector edgeVertConnections; + Value triangleEdgesCount; + Vector triangleEdgeConnections; + Value vertCount; + Vector verts; + struct Node : BigDNA { + AT_DECL_EXPLICIT_DNA + + struct LeafData : BigDNA { AT_DECL_DNA - Value magic; - Value version; - Value memSize; - Value materialCount; - Vector materials; - Value vertMatsCount; - Vector vertMats; - Value edgeMatsCount; - Vector edgeMats; - Value triMatsCount; - Vector triMats; - Value edgeVertsCount; - Vector edgeVertConnections; - Value triangleEdgesCount; - Vector triangleEdgeConnections; - Value vertCount; - Vector verts; + Value triangleIndexCount; + Vector triangleIndices; + size_t getMemoryUsage() const { return (((triangleIndices.size() * 2) + 16) + 3) & ~3; } + }; - struct Node : BigDNA - { - AT_DECL_EXPLICIT_DNA + Value xf[3]; + Value halfExtent; + Value isLeaf; + std::unique_ptr leafData; + std::unique_ptr left; + std::unique_ptr right; - struct LeafData : BigDNA - { - AT_DECL_DNA - Value triangleIndexCount; - Vector triangleIndices; - size_t getMemoryUsage() const { return (((triangleIndices.size() * 2) + 16) + 3) & ~3; } - }; - - Value xf[3]; - Value halfExtent; - Value isLeaf; - std::unique_ptr leafData; - std::unique_ptr left; - std::unique_ptr right; - - size_t getMemoryUsage() const - { - size_t ret = 80; - if (isLeaf) - ret += leafData->getMemoryUsage(); - else - { - ret += left->getMemoryUsage(); - ret += right->getMemoryUsage(); - } - - return (ret + 3) & ~3; - } - -#if DCLN_DUMP_OBB - void sendToBlender(hecl::blender::PyOutStream& os) const; -#endif - }; - Node root; - size_t getMemoryUsage() - { - return root.getMemoryUsage(); + size_t getMemoryUsage() const { + size_t ret = 80; + if (isLeaf) + ret += leafData->getMemoryUsage(); + else { + ret += left->getMemoryUsage(); + ret += right->getMemoryUsage(); } - /* Dummy MP2 member */ - void insertNoClimb(hecl::blender::PyOutStream&) const {} + return (ret + 3) & ~3; + } + +#if DCLN_DUMP_OBB + void sendToBlender(hecl::blender::PyOutStream& os) const; +#endif }; + Node root; + size_t getMemoryUsage() { return root.getMemoryUsage(); } + /* Dummy MP2 member */ + void insertNoClimb(hecl::blender::PyOutStream&) const {} + }; - Vector collision; + Vector collision; - void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName); + void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName); - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged); + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged); - static bool Cook(const hecl::ProjectPath& outPath, - const std::vector& meshes); + static bool Cook(const hecl::ProjectPath& outPath, const std::vector& meshes); }; -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/DNAMP1.cpp b/DataSpec/DNAMP1/DNAMP1.cpp index e94c657be..5d4a770f4 100644 --- a/DataSpec/DNAMP1/DNAMP1.cpp +++ b/DataSpec/DNAMP1/DNAMP1.cpp @@ -47,419 +47,373 @@ #include "MazeSeeds.hpp" #include "SnowForces.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { logvisor::Module Log("urde::DNAMP1"); -static bool GetNoShare(std::string_view name) -{ - std::string lowerName(name); - std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); - if (!lowerName.compare(0, 7, "metroid")) - return false; - return true; +static bool GetNoShare(std::string_view name) { + std::string lowerName(name); + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); + if (!lowerName.compare(0, 7, "metroid")) + return false; + return true; } PAKBridge::PAKBridge(const nod::Node& node, bool doExtract) -: m_node(node), m_pak(false, GetNoShare(node.getName())), m_doExtract(doExtract) -{ - nod::AthenaPartReadStream rs(node.beginReadStream()); - m_pak.read(rs); +: m_node(node), m_pak(false, GetNoShare(node.getName())), m_doExtract(doExtract) { + nod::AthenaPartReadStream rs(node.beginReadStream()); + m_pak.read(rs); - /* Append Level String */ - for (auto& ent : m_pak.m_entries) - { - PAK::Entry& entry = ent.second; - if (entry.type == FOURCC('MLVL')) - { - PAKEntryReadStream rs = entry.beginReadStream(m_node); - MLVL mlvl; - mlvl.read(rs); - PAK::Entry* nameEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldNameId); - if (nameEnt) - { - nameEnt->name = entry.name + "_name"; - PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); - STRG mlvlName; - mlvlName.read(rs); - if (m_levelString.size()) - m_levelString += _SYS_STR(", "); - m_levelString += mlvlName.getSystemString(FOURCC('ENGL'), 0); - } - } + /* Append Level String */ + for (auto& ent : m_pak.m_entries) { + PAK::Entry& entry = ent.second; + if (entry.type == FOURCC('MLVL')) { + PAKEntryReadStream rs = entry.beginReadStream(m_node); + MLVL mlvl; + mlvl.read(rs); + PAK::Entry* nameEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldNameId); + if (nameEnt) { + nameEnt->name = entry.name + "_name"; + PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); + STRG mlvlName; + mlvlName.read(rs); + if (m_levelString.size()) + m_levelString += _SYS_STR(", "); + m_levelString += mlvlName.getSystemString(FOURCC('ENGL'), 0); + } } + } } -static hecl::SystemString LayerName(std::string_view name) -{ - hecl::SystemString ret(hecl::SystemStringConv(name).sys_str()); - for (auto& ch : ret) - if (ch == _SYS_STR('/') || ch == _SYS_STR('\\')) - ch = _SYS_STR('-'); - return ret; +static hecl::SystemString LayerName(std::string_view name) { + hecl::SystemString ret(hecl::SystemStringConv(name).sys_str()); + for (auto& ch : ret) + if (ch == _SYS_STR('/') || ch == _SYS_STR('\\')) + ch = _SYS_STR('-'); + return ret; } -void PAKBridge::build() -{ - /* First pass: build per-area/per-layer dependency map */ - for (const auto& ent : m_pak.m_entries) - { - const PAK::Entry& entry = ent.second; - if (entry.type == FOURCC('MLVL')) - { - Level& level = m_levelDeps[entry.id]; +void PAKBridge::build() { + /* First pass: build per-area/per-layer dependency map */ + for (const auto& ent : m_pak.m_entries) { + const PAK::Entry& entry = ent.second; + if (entry.type == FOURCC('MLVL')) { + Level& level = m_levelDeps[entry.id]; - MLVL mlvl; - { - PAKEntryReadStream rs = entry.beginReadStream(m_node); - mlvl.read(rs); - } - bool named; - std::string bestName = m_pak.bestEntryName(m_node, entry, named); - level.name = hecl::SystemStringConv(bestName).sys_str(); - level.areas.reserve(mlvl.areaCount); - unsigned layerIdx = 0; + MLVL mlvl; + { + PAKEntryReadStream rs = entry.beginReadStream(m_node); + mlvl.read(rs); + } + bool named; + std::string bestName = m_pak.bestEntryName(m_node, entry, named); + level.name = hecl::SystemStringConv(bestName).sys_str(); + level.areas.reserve(mlvl.areaCount); + unsigned layerIdx = 0; - /* Make MAPW available to lookup MAPAs */ - PAK::Entry* worldMapEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldMap); - std::vector mapw; - if (worldMapEnt) - { - worldMapEnt->name = entry.name + "_mapw"; - PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node); - rs.seek(8, athena::Current); - atUint32 areaCount = rs.readUint32Big(); - mapw.reserve(areaCount); - for (atUint32 i=0 ; i mapw; + if (worldMapEnt) { + worldMapEnt->name = entry.name + "_mapw"; + PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node); + rs.seek(8, athena::Current); + atUint32 areaCount = rs.readUint32Big(); + mapw.reserve(areaCount); + for (atUint32 i = 0; i < areaCount; ++i) + mapw.emplace_back(rs); + } - PAK::Entry* savwEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.saveWorldId); - if (savwEnt) - savwEnt->name = entry.name + "_savw"; + PAK::Entry* savwEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.saveWorldId); + if (savwEnt) + savwEnt->name = entry.name + "_savw"; - PAK::Entry* skyEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldSkyboxId); - if (skyEnt) - skyEnt->name = entry.name + "_skybox"; + PAK::Entry* skyEnt = (PAK::Entry*)m_pak.lookupEntry(mlvl.worldSkyboxId); + if (skyEnt) + skyEnt->name = entry.name + "_skybox"; - /* Index areas */ - unsigned ai = 0; - for (const MLVL::Area& area : mlvl.areas) - { - Level::Area& areaDeps = level.areas[area.areaMREAId]; - MLVL::LayerFlags& layerFlags = mlvl.layerFlags[ai]; - PAK::Entry* areaNameEnt = (PAK::Entry*)m_pak.lookupEntry(area.areaNameId); - if (areaNameEnt) - { - STRG areaName; - { - PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node); - areaName.read(rs); - } - areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0); - areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name); - } - if (areaDeps.name.empty()) - { - std::string idStr = area.areaMREAId.toString(); - areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); - } - hecl::SystemChar num[16]; - hecl::SNPrintf(num, 16, _SYS_STR("%02u "), ai); - areaDeps.name = num + areaDeps.name; - - std::string lowerName(hecl::SystemUTF8Conv(areaDeps.name).str()); - for (char& ch : lowerName) - { - ch = tolower(ch); - if (ch == ' ') - ch = '_'; - } - if (areaNameEnt) - areaNameEnt->name = lowerName + "_name"; - PAK::Entry* areaEnt = (PAK::Entry*)m_pak.lookupEntry(area.areaMREAId); - if (areaEnt) - areaEnt->name = lowerName; - - areaDeps.layers.reserve(area.depLayerCount-1); - unsigned r=0; - for (unsigned l=1 ; l> (l-1) & 0x1; - layer.name = hecl::StringUtils::TrimWhitespace(layer.name); - - hecl::SNPrintf(num, 16, _SYS_STR("%02u "), l-1); - layer.name = num + layer.name; - - layer.resources.reserve(area.depLayers[l] - r); - for (; r ai) - areaDeps.resources.emplace(mapw[ai]); - ++ai; - } + /* Index areas */ + unsigned ai = 0; + for (const MLVL::Area& area : mlvl.areas) { + Level::Area& areaDeps = level.areas[area.areaMREAId]; + MLVL::LayerFlags& layerFlags = mlvl.layerFlags[ai]; + PAK::Entry* areaNameEnt = (PAK::Entry*)m_pak.lookupEntry(area.areaNameId); + if (areaNameEnt) { + STRG areaName; + { + PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node); + areaName.read(rs); + } + areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0); + areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name); } - } + if (areaDeps.name.empty()) { + std::string idStr = area.areaMREAId.toString(); + areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); + } + hecl::SystemChar num[16]; + hecl::SNPrintf(num, 16, _SYS_STR("%02u "), ai); + areaDeps.name = num + areaDeps.name; - /* Second pass: cross-compare uniqueness */ - for (auto& entry : m_pak.m_entries) - { - entry.second.unique.checkEntry(*this, entry.second); + std::string lowerName(hecl::SystemUTF8Conv(areaDeps.name).str()); + for (char& ch : lowerName) { + ch = tolower(ch); + if (ch == ' ') + ch = '_'; + } + if (areaNameEnt) + areaNameEnt->name = lowerName + "_name"; + PAK::Entry* areaEnt = (PAK::Entry*)m_pak.lookupEntry(area.areaMREAId); + if (areaEnt) + areaEnt->name = lowerName; + + areaDeps.layers.reserve(area.depLayerCount - 1); + unsigned r = 0; + for (unsigned l = 1; l < area.depLayerCount; ++l) { + areaDeps.layers.emplace_back(); + Level::Area::Layer& layer = areaDeps.layers.back(); + layer.name = LayerName(mlvl.layerNames[layerIdx++]); + layer.active = layerFlags.flags >> (l - 1) & 0x1; + layer.name = hecl::StringUtils::TrimWhitespace(layer.name); + + hecl::SNPrintf(num, 16, _SYS_STR("%02u "), l - 1); + layer.name = num + layer.name; + + layer.resources.reserve(area.depLayers[l] - r); + for (; r < area.depLayers[l]; ++r) + layer.resources.emplace(area.deps[r].id); + } + areaDeps.resources.reserve(area.depCount - r + 2); + for (; r < area.depCount; ++r) + areaDeps.resources.emplace(area.deps[r].id); + areaDeps.resources.emplace(area.areaMREAId); + if (mapw.size() > ai) + areaDeps.resources.emplace(mapw[ai]); + ++ai; + } } + } + + /* Second pass: cross-compare uniqueness */ + for (auto& entry : m_pak.m_entries) { + entry.second.unique.checkEntry(*this, entry.second); + } } -void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const -{ - for (const std::pair& entry : m_pak.m_entries) - { - if (entry.second.type == FOURCC('ANCS')) - { - PAKEntryReadStream rs = entry.second.beginReadStream(m_node); - ANCS ancs; - ancs.read(rs); - for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) - { - charAssoc.m_cmdlRigs[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf); - charAssoc.m_cskrCinfToCharacter[ci.cskr] = - std::make_pair(entry.second.id, hecl::Format("%s.CSKR", ci.name.c_str())); - charAssoc.m_cskrCinfToCharacter[ci.cinf] = - std::make_pair(entry.second.id, hecl::Format("CINF_%08X.CINF", ci.cinf.toUint32())); - PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdl); - PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskr); - PAK::Entry* cinfEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cinf); - cmdlEnt->name = hecl::Format("ANCS_%08X_%s_model", entry.first.toUint32(), ci.name.c_str()); - cskrEnt->name = hecl::Format("ANCS_%08X_%s_skin", entry.first.toUint32(), ci.name.c_str()); - cinfEnt->name = hecl::Format("ANCS_%08X_%s_skel", entry.first.toUint32(), ci.name.c_str()); - if (ci.cmdlIce && ci.cskrIce) - { - charAssoc.m_cmdlRigs[ci.cmdlIce] = std::make_pair(ci.cskrIce, ci.cinf); - charAssoc.m_cskrCinfToCharacter[ci.cskrIce] = - std::make_pair(entry.second.id, hecl::Format("%s.ICE.CSKR", ci.name.c_str())); - PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdlIce); - PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskrIce); - cmdlEnt->name = hecl::Format("ANCS_%08X_%s_icemodel", entry.first.toUint32(), ci.name.c_str()); - cskrEnt->name = hecl::Format("ANCS_%08X_%s_iceskin", entry.first.toUint32(), ci.name.c_str()); - } - } - std::map> animInfo; - ancs.getAnimationResInfo(&pakRouter, animInfo); - for (auto& ae : animInfo) - { - PAK::Entry* animEnt = (PAK::Entry*)m_pak.lookupEntry(ae.second.animId); - animEnt->name = hecl::Format("ANCS_%08X_%s", entry.first.toUint32(), ae.second.name.c_str()); - charAssoc.m_cskrCinfToCharacter[ae.second.animId] = - std::make_pair(entry.second.id, hecl::Format("%s.ANIM", ae.second.name.c_str())); - if (ae.second.evntId) - { - PAK::Entry* evntEnt = (PAK::Entry*)m_pak.lookupEntry(ae.second.evntId); - evntEnt->name = hecl::Format("ANCS_%08X_%s_evnt", entry.first.toUint32(), ae.second.name.c_str()); - charAssoc.m_cskrCinfToCharacter[ae.second.evntId] = - std::make_pair(entry.second.id, hecl::Format("%s.evnt.yaml", ae.second.name.c_str())); - } - } +void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + for (const std::pair& entry : m_pak.m_entries) { + if (entry.second.type == FOURCC('ANCS')) { + PAKEntryReadStream rs = entry.second.beginReadStream(m_node); + ANCS ancs; + ancs.read(rs); + for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) { + charAssoc.m_cmdlRigs[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf); + charAssoc.m_cskrCinfToCharacter[ci.cskr] = + std::make_pair(entry.second.id, hecl::Format("%s.CSKR", ci.name.c_str())); + charAssoc.m_cskrCinfToCharacter[ci.cinf] = + std::make_pair(entry.second.id, hecl::Format("CINF_%08X.CINF", ci.cinf.toUint32())); + PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdl); + PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskr); + PAK::Entry* cinfEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cinf); + cmdlEnt->name = hecl::Format("ANCS_%08X_%s_model", entry.first.toUint32(), ci.name.c_str()); + cskrEnt->name = hecl::Format("ANCS_%08X_%s_skin", entry.first.toUint32(), ci.name.c_str()); + cinfEnt->name = hecl::Format("ANCS_%08X_%s_skel", entry.first.toUint32(), ci.name.c_str()); + if (ci.cmdlIce && ci.cskrIce) { + charAssoc.m_cmdlRigs[ci.cmdlIce] = std::make_pair(ci.cskrIce, ci.cinf); + charAssoc.m_cskrCinfToCharacter[ci.cskrIce] = + std::make_pair(entry.second.id, hecl::Format("%s.ICE.CSKR", ci.name.c_str())); + PAK::Entry* cmdlEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cmdlIce); + PAK::Entry* cskrEnt = (PAK::Entry*)m_pak.lookupEntry(ci.cskrIce); + cmdlEnt->name = hecl::Format("ANCS_%08X_%s_icemodel", entry.first.toUint32(), ci.name.c_str()); + cskrEnt->name = hecl::Format("ANCS_%08X_%s_iceskin", entry.first.toUint32(), ci.name.c_str()); } - else if (entry.second.type == FOURCC('MREA')) - { - PAKEntryReadStream rs = entry.second.beginReadStream(m_node); - MREA::AddCMDLRigPairs(rs, pakRouter, charAssoc); + } + std::map> animInfo; + ancs.getAnimationResInfo(&pakRouter, animInfo); + for (auto& ae : animInfo) { + PAK::Entry* animEnt = (PAK::Entry*)m_pak.lookupEntry(ae.second.animId); + animEnt->name = hecl::Format("ANCS_%08X_%s", entry.first.toUint32(), ae.second.name.c_str()); + charAssoc.m_cskrCinfToCharacter[ae.second.animId] = + std::make_pair(entry.second.id, hecl::Format("%s.ANIM", ae.second.name.c_str())); + if (ae.second.evntId) { + PAK::Entry* evntEnt = (PAK::Entry*)m_pak.lookupEntry(ae.second.evntId); + evntEnt->name = hecl::Format("ANCS_%08X_%s_evnt", entry.first.toUint32(), ae.second.name.c_str()); + charAssoc.m_cskrCinfToCharacter[ae.second.evntId] = + std::make_pair(entry.second.id, hecl::Format("%s.evnt.yaml", ae.second.name.c_str())); } + } + } else if (entry.second.type == FOURCC('MREA')) { + PAKEntryReadStream rs = entry.second.beginReadStream(m_node); + MREA::AddCMDLRigPairs(rs, pakRouter, charAssoc); } + } } void PAKBridge::addPATHToMREA(PAKRouter& pakRouter, - std::unordered_map& pathToMrea) const -{ - for (const std::pair& entry : m_pak.m_entries) - { - if (entry.second.type == FOURCC('MREA')) - { - PAKEntryReadStream rs = entry.second.beginReadStream(m_node); - UniqueID32 pathID = MREA::GetPATHId(rs); - if (pathID) - pathToMrea[pathID] = entry.first; - } + std::unordered_map& pathToMrea) const { + for (const std::pair& entry : m_pak.m_entries) { + if (entry.second.type == FOURCC('MREA')) { + PAKEntryReadStream rs = entry.second.beginReadStream(m_node); + UniqueID32 pathID = MREA::GetPATHId(rs); + if (pathID) + pathToMrea[pathID] = entry.first; } + } } static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}}; void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, - std::unordered_map& addTo, - std::unordered_map& pathOverrides) const -{ - for (const std::pair& entry : m_pak.m_entries) - { - if (entry.second.type == FOURCC('MLVL')) + std::unordered_map& addTo, + std::unordered_map& pathOverrides) const { + for (const std::pair& entry : m_pak.m_entries) { + if (entry.second.type == FOURCC('MLVL')) { + MLVL mlvl; + { + PAKEntryReadStream rs = entry.second.beginReadStream(m_node); + mlvl.read(rs); + } + hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath(); + + if (mlvl.worldNameId) + pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _SYS_STR("!name.yaml")); + + for (const MLVL::Area& area : mlvl.areas) { { - MLVL mlvl; - { - PAKEntryReadStream rs = entry.second.beginReadStream(m_node); - mlvl.read(rs); - } - hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath(); - - if (mlvl.worldNameId) - pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _SYS_STR("!name.yaml")); - - for (const MLVL::Area& area : mlvl.areas) - { - { - /* Get PATH transform */ - const nod::Node* areaNode; - const PAK::Entry* areaEntry = pakRouter.lookupEntry(area.areaMREAId, &areaNode); - PAKEntryReadStream rs = areaEntry->beginReadStream(*areaNode); - UniqueID32 pathId = MREA::GetPATHId(rs); - if (pathId) - addTo[pathId] = zeus::CMatrix4f( - area.transformMtx[0], - area.transformMtx[1], - area.transformMtx[2], - BottomRow).transposed(); - } - - hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); - if (area.areaNameId) - pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _SYS_STR("!name.yaml")); - } - - if (mlvl.worldMap) - { - const nod::Node* mapNode; - const PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode); - if (mapEntry) - { - PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode); - u32 magic = rs.readUint32Big(); - if (magic == 0xDEADF00D) - { - rs.readUint32Big(); - u32 count = rs.readUint32Big(); - for (u32 i=0 ; ibeginReadStream(*areaNode); + UniqueID32 pathId = MREA::GetPATHId(rs); + if (pathId) + addTo[pathId] = zeus::CMatrix4f(area.transformMtx[0], area.transformMtx[1], area.transformMtx[2], BottomRow) + .transposed(); } - } -} -ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry) -{ - switch (entry.type) - { - case SBIG('STRG'): - return {STRG::Extract, {_SYS_STR(".yaml")}}; - case SBIG('SCAN'): - return {SCAN::Extract, {_SYS_STR(".yaml")}, 0, SCAN::Name}; - case SBIG('HINT'): - return {HINT::Extract, {_SYS_STR(".yaml")}}; - case SBIG('SAVW'): - return {SAVWCommon::ExtractSAVW, {_SYS_STR(".yaml")}}; - case SBIG('TXTR'): - return {TXTR::Extract, {_SYS_STR(".png")}}; - case SBIG('AFSM'): - return {AFSM::Extract, {_SYS_STR(".yaml")}}; - case SBIG('FRME'): - return {FRME::Extract, {_SYS_STR(".blend")}, 2}; - case SBIG('CMDL'): - return {CMDL::Extract, {_SYS_STR(".blend")}, 1, CMDL::Name}; - case SBIG('DCLN'): - return {DCLN::Extract, {_SYS_STR(".blend")}}; - case SBIG('ANCS'): - return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; - case SBIG('MLVL'): - return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3}; - case SBIG('MREA'): - return {MREA::Extract, {_SYS_STR(".blend")}, 4, MREA::Name}; - case SBIG('MAPA'): - return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; - case SBIG('MAPU'): - return {MAPU::Extract, {_SYS_STR(".blend")}, 5}; - case SBIG('PATH'): - return {PATH::Extract, {_SYS_STR(".blend")}, 5}; - case SBIG('PART'): - return {DNAParticle::ExtractGPSM, {_SYS_STR(".gpsm.yaml")}}; - case SBIG('ELSC'): - return {DNAParticle::ExtractELSM, {_SYS_STR(".elsm.yaml")}}; - case SBIG('SWHC'): - return {DNAParticle::ExtractSWSH, {_SYS_STR(".swsh.yaml")}}; - case SBIG('CRSC'): - return {DNAParticle::ExtractCRSM, {_SYS_STR(".crsm.yaml")}}; - case SBIG('WPSC'): - return {DNAParticle::ExtractWPSM, {_SYS_STR(".wpsm.yaml")}}; - case SBIG('DPSC'): - return {DNAParticle::ExtractDPSM, {_SYS_STR(".dpsm.yaml")}}; - case SBIG('FONT'): - return {DNAFont::ExtractFONT, {_SYS_STR(".yaml")}}; - case SBIG('DGRP'): - return {DNADGRP::ExtractDGRP, {_SYS_STR(".yaml")}}; - case SBIG('AGSC'): - return {AGSC::Extract, {}}; - case SBIG('CSNG'): - return {CSNG::Extract, {_SYS_STR(".mid"), _SYS_STR(".yaml")}}; - case SBIG('ATBL'): - return {DNAAudio::ATBL::Extract, {_SYS_STR(".yaml")}}; - case SBIG('CTWK'): - case SBIG('DUMB'): - { - bool named; - std::string name = pak.bestEntryName(pakNode, entry, named); - if (named) - { - if (!name.compare("PlayerRes")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("GunRes")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("Player")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("CameraBob")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("SlideShow")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("Game")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("Targeting")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("Gui")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("AutoMapper")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("PlayerControls") || !name.compare("PlayerControls2")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("Ball")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("Particle")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("GuiColors")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("PlayerGun")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("DUMB_MazeSeeds")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; - if (!name.compare("DUMB_SnowForces")) - return {ExtractTweak, {_SYS_STR(".yaml")}}; + hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); + if (area.areaNameId) + pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _SYS_STR("!name.yaml")); + } + + if (mlvl.worldMap) { + const nod::Node* mapNode; + const PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode); + if (mapEntry) { + PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode); + u32 magic = rs.readUint32Big(); + if (magic == 0xDEADF00D) { + rs.readUint32Big(); + u32 count = rs.readUint32Big(); + for (u32 i = 0; i < count && i < mlvl.areas.size(); ++i) { + MLVL::Area& areaData = mlvl.areas[i]; + UniqueID32 mapaId; + mapaId.read(rs); + addTo[mapaId] = zeus::CMatrix4f(areaData.transformMtx[0], areaData.transformMtx[1], + areaData.transformMtx[2], BottomRow) + .transposed(); + } + } } - break; + } } - } - return {}; + } } +ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry) { + switch (entry.type) { + case SBIG('STRG'): + return {STRG::Extract, {_SYS_STR(".yaml")}}; + case SBIG('SCAN'): + return {SCAN::Extract, {_SYS_STR(".yaml")}, 0, SCAN::Name}; + case SBIG('HINT'): + return {HINT::Extract, {_SYS_STR(".yaml")}}; + case SBIG('SAVW'): + return {SAVWCommon::ExtractSAVW, {_SYS_STR(".yaml")}}; + case SBIG('TXTR'): + return {TXTR::Extract, {_SYS_STR(".png")}}; + case SBIG('AFSM'): + return {AFSM::Extract, {_SYS_STR(".yaml")}}; + case SBIG('FRME'): + return {FRME::Extract, {_SYS_STR(".blend")}, 2}; + case SBIG('CMDL'): + return {CMDL::Extract, {_SYS_STR(".blend")}, 1, CMDL::Name}; + case SBIG('DCLN'): + return {DCLN::Extract, {_SYS_STR(".blend")}}; + case SBIG('ANCS'): + return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; + case SBIG('MLVL'): + return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3}; + case SBIG('MREA'): + return {MREA::Extract, {_SYS_STR(".blend")}, 4, MREA::Name}; + case SBIG('MAPA'): + return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; + case SBIG('MAPU'): + return {MAPU::Extract, {_SYS_STR(".blend")}, 5}; + case SBIG('PATH'): + return {PATH::Extract, {_SYS_STR(".blend")}, 5}; + case SBIG('PART'): + return {DNAParticle::ExtractGPSM, {_SYS_STR(".gpsm.yaml")}}; + case SBIG('ELSC'): + return {DNAParticle::ExtractELSM, {_SYS_STR(".elsm.yaml")}}; + case SBIG('SWHC'): + return {DNAParticle::ExtractSWSH, {_SYS_STR(".swsh.yaml")}}; + case SBIG('CRSC'): + return {DNAParticle::ExtractCRSM, {_SYS_STR(".crsm.yaml")}}; + case SBIG('WPSC'): + return {DNAParticle::ExtractWPSM, {_SYS_STR(".wpsm.yaml")}}; + case SBIG('DPSC'): + return {DNAParticle::ExtractDPSM, {_SYS_STR(".dpsm.yaml")}}; + case SBIG('FONT'): + return {DNAFont::ExtractFONT, {_SYS_STR(".yaml")}}; + case SBIG('DGRP'): + return {DNADGRP::ExtractDGRP, {_SYS_STR(".yaml")}}; + case SBIG('AGSC'): + return {AGSC::Extract, {}}; + case SBIG('CSNG'): + return {CSNG::Extract, {_SYS_STR(".mid"), _SYS_STR(".yaml")}}; + case SBIG('ATBL'): + return {DNAAudio::ATBL::Extract, {_SYS_STR(".yaml")}}; + case SBIG('CTWK'): + case SBIG('DUMB'): { + bool named; + std::string name = pak.bestEntryName(pakNode, entry, named); + if (named) { + if (!name.compare("PlayerRes")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("GunRes")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("Player")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("CameraBob")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("SlideShow")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("Game")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("Targeting")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("Gui")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("AutoMapper")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("PlayerControls") || !name.compare("PlayerControls2")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("Ball")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("Particle")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("GuiColors")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("PlayerGun")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("DUMB_MazeSeeds")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + if (!name.compare("DUMB_SnowForces")) + return {ExtractTweak, {_SYS_STR(".yaml")}}; + } + break; + } + } + return {}; } + +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/DNAMP1.hpp b/DataSpec/DNAMP1/DNAMP1.hpp index be4207b7b..ea75a73cc 100644 --- a/DataSpec/DNAMP1/DNAMP1.hpp +++ b/DataSpec/DNAMP1/DNAMP1.hpp @@ -4,40 +4,36 @@ #include "PAK.hpp" #include "zeus/CMatrix4f.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { extern logvisor::Module Log; /* MP1-specific, one-shot PAK traversal/extraction class */ -class PAKBridge -{ - const nod::Node& m_node; - PAK m_pak; +class PAKBridge { + const nod::Node& m_node; + PAK m_pak; + public: - bool m_doExtract; - using Level = DataSpec::Level; - std::unordered_map m_levelDeps; - hecl::SystemString m_levelString; + bool m_doExtract; + using Level = DataSpec::Level; + std::unordered_map m_levelDeps; + hecl::SystemString m_levelString; - PAKBridge(const nod::Node& node, bool doExtract=true); - void build(); - static ResExtractor LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry); - std::string_view getName() const {return m_node.getName();} - hecl::SystemStringView getLevelString() const {return m_levelString;} - using PAKType = PAK; - const PAKType& getPAK() const {return m_pak;} - const nod::Node& getNode() const {return m_node;} + PAKBridge(const nod::Node& node, bool doExtract = true); + void build(); + static ResExtractor LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry); + std::string_view getName() const { return m_node.getName(); } + hecl::SystemStringView getLevelString() const { return m_levelString; } + using PAKType = PAK; + const PAKType& getPAK() const { return m_pak; } + const nod::Node& getNode() const { return m_node; } - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; - void addPATHToMREA(PAKRouter& pakRouter, - std::unordered_map& pathToMrea) const; + void addPATHToMREA(PAKRouter& pakRouter, std::unordered_map& pathToMrea) const; - void addMAPATransforms(PAKRouter& pakRouter, - std::unordered_map& addTo, - std::unordered_map& pathOverrides) const; + void addMAPATransforms(PAKRouter& pakRouter, std::unordered_map& addTo, + std::unordered_map& pathOverrides) const; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/DeafBabe.cpp b/DataSpec/DNAMP1/DeafBabe.cpp index aecaa43ea..f02ad9e11 100644 --- a/DataSpec/DNAMP1/DeafBabe.cpp +++ b/DataSpec/DNAMP1/DeafBabe.cpp @@ -1,233 +1,232 @@ #include "DeafBabe.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) -{ - os << "TYPE_COLORS = {'NoSFX':(0.0, 0.0, 0.0),\n" - " 'Stone':(1.0, 0.43, 0.15),\n" - " 'Metal':(0.5, 0.5, 0.5),\n" - " 'Grass':(0.0, 0.42, 0.01)," - " 'Ice':(0.0, 0.1, 0.1),\n" - " 'Metal Grating':(0.09, 0.09, 0.09),\n" - " 'Phazon':(0.24, 0.0, 0.21),\n" - " 'Dirt':(0.1, 0.07, 0.05),\n" - " 'Stone':(0.12, 0.12, 0.12),\n" - " 'Lava':(0.8, 0.15, 0.0),\n" - " 'Stone/Rock':(0.06, 0.05, 0.03),\n" - " 'Snow':(0.9, 1.0, 1.0),\n" - " 'Mud (Slow)':(0.12, 0.06, 0.02),\n" - " 'Mud':(0.12, 0.06, 0.02),\n" - " 'Glass':(0.27, 0.38, 0.9),\n" - " 'Shield':(1.0, 0.6, 0.0),\n" - " 'Sand':(0.53, 0.44, 0.21),\n" - " 'Wood':(0.30, 0.15, 0.03),\n" - " 'Organic':(0.19, 0.45, 0.2)}\n" - "\n" - "# Diffuse Color Maker\n" - "def make_color(index, mat_type, name):\n" - " new_mat = bpy.data.materials.new(name)\n" - " if mat_type in TYPE_COLORS:\n" - " new_mat.diffuse_color = TYPE_COLORS[mat_type]\n" - " else:\n" - " new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" - " return new_mat\n" - "\n" - "bpy.types.Material.retro_unknown = bpy.props.BoolProperty(name='Retro: Unknown (U)')\n" - "bpy.types.Material.retro_surface_stone = bpy.props.BoolProperty(name='Retro Surface: Stone')\n" - "bpy.types.Material.retro_surface_metal = bpy.props.BoolProperty(name='Retro Surface: Metal')\n" - "bpy.types.Material.retro_surface_grass = bpy.props.BoolProperty(name='Retro Surface: Grass')\n" - "bpy.types.Material.retro_surface_ice = bpy.props.BoolProperty(name='Retro Surface: Ice')\n" - "bpy.types.Material.retro_pillar = bpy.props.BoolProperty(name='Retro Pillar (I)')\n" - "bpy.types.Material.retro_surface_metal_grating = bpy.props.BoolProperty(name='Retro Surface: Metal Grating')\n" - "bpy.types.Material.retro_surface_phazon = bpy.props.BoolProperty(name='Retro Surface: Phazon')\n" - "bpy.types.Material.retro_surface_dirt = bpy.props.BoolProperty(name='Retro Surface: Rock')\n" - "bpy.types.Material.retro_surface_lava = bpy.props.BoolProperty(name='Retro Surface: Lava')\n" - "bpy.types.Material.retro_surface_lava_stone = bpy.props.BoolProperty(name='Retro Surface: Lava Stone')\n" - "bpy.types.Material.retro_surface_snow = bpy.props.BoolProperty(name='Retro Surface: Snow')\n" - "bpy.types.Material.retro_surface_mud_slow = bpy.props.BoolProperty(name='Retro Surface: Mud (Slow)')\n" - "bpy.types.Material.retro_half_pipe = bpy.props.BoolProperty(name='Retro: Half Pipe (H)')\n" - "bpy.types.Material.retro_surface_mud = bpy.props.BoolProperty(name='Retro Surface: Mud')\n" - "bpy.types.Material.retro_surface_glass = bpy.props.BoolProperty(name='Retro Surface: Glass')\n" - "bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(name='Retro Surface: Shield')\n" - "bpy.types.Material.retro_surface_sand = bpy.props.BoolProperty(name='Retro Surface: Sand')\n" - "bpy.types.Material.retro_projectile_passthrough = bpy.props.BoolProperty(name='Retro: Projectile Passthrough (P)')\n" - "bpy.types.Material.retro_solid = bpy.props.BoolProperty(name='Retro: Solid (K)')\n" - "bpy.types.Material.retro_no_platform_collision = bpy.props.BoolProperty(name='Retro: No Platform Collision')\n" - "bpy.types.Material.retro_camera_passthrough = bpy.props.BoolProperty(name='Retro: Camera Passthrough (O)')\n" - "bpy.types.Material.retro_surface_wood = bpy.props.BoolProperty(name='Retro Surface: Wood')\n" - "bpy.types.Material.retro_surface_organic = bpy.props.BoolProperty(name='Retro Surface: Organic')\n" - "bpy.types.Material.retro_no_edge_collision = bpy.props.BoolProperty(name='Retro: No Edge Collision')\n" - "bpy.types.Material.retro_see_through = bpy.props.BoolProperty(name='Retro: See Through')\n" - "bpy.types.Material.retro_scan_passthrough = bpy.props.BoolProperty(name='Retro: Scan Passthrough (S)')\n" - "bpy.types.Material.retro_ai_passthrough = bpy.props.BoolProperty(name='Retro: AI Passthrough (A)')\n" - "bpy.types.Material.retro_ceiling = bpy.props.BoolProperty(name='Retro: Ceiling (C)')\n" - "bpy.types.Material.retro_wall = bpy.props.BoolProperty(name='Retro: Wall (W)')\n" - "bpy.types.Material.retro_floor = bpy.props.BoolProperty(name='Retro: Floor (F)')\n" - "\n" - "material_dict = {}\n" - "material_index = []\n" - "def get_type_id(data):\n" - "\n" - " ret = 0\n" - " for i in range(1, 24):\n" - " if i == 5 or i == 13 or i in range(18, 22):\n" - " continue\n" - " if ((data >> i) & 1):\n" - " ret = i\n" - " return ret\n" - "\n" - "def select_material(data):\n" - "\n" - " type_id = get_type_id(data)\n" - " mat_type = str(type_id)\n" - " if type_id == 0:\n" - " mat_type = 'NoSFX'\n" - " if type_id == 1:\n" - " mat_type = 'Stone'\n" - " elif type_id == 2:\n" - " mat_type = 'Metal'\n" - " elif type_id == 3:\n" - " mat_type = 'Grass'\n" - " elif type_id == 4:\n" - " mat_type = 'Ice'\n" - " elif type_id == 6:\n" - " mat_type = 'Metal Grating'\n" - " elif type_id == 7:\n" - " mat_type = 'Phazon'\n" - " elif type_id == 8:\n" - " mat_type = 'Dirt'\n" - " elif type_id == 9:\n" - " mat_type = 'Lava'\n" - " elif type_id == 10:\n" - " mat_type = 'Stone/Rock'\n" - " elif type_id == 11:\n" - " mat_type = 'Snow'\n" - " elif type_id == 12:\n" - " mat_type = 'Mud (Slow)'\n" - " elif type_id == 14:\n" - " mat_type = 'Mud'\n" - " elif type_id == 15:\n" - " mat_type = 'Glass'\n" - " elif type_id == 16:\n" - " mat_type = 'Shield'\n" - " elif type_id == 17:\n" - " mat_type = 'Sand'\n" - " elif type_id == 22:\n" - " mat_type = 'Wood'\n" - " elif type_id == 23:\n" - " mat_type = 'Organic'\n" - "\n" - " mat_flags = ''\n" - " if ((data >> 0) & 1):\n" - " mat_flags += 'U'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 5) & 1):\n" - " mat_flags += 'I'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 13) & 1):\n" - " mat_flags += 'H'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 18) & 1):\n" - " mat_flags += 'P'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 19) & 1):\n" - " mat_flags += 'K'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 20) & 1):\n" - " mat_flags += 'u'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 21) & 1):\n" - " mat_flags += 'O'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 24) & 1):\n" - " mat_flags += 'u'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 26) & 1):\n" - " mat_flags += 'T'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 27) & 1):\n" - " mat_flags += 'S'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 28) & 1):\n" - " mat_flags += 'A'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 29) & 1):\n" - " mat_flags += 'C'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 30) & 1):\n" - " mat_flags += 'W'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 31) & 1):\n" - " mat_flags += 'F'\n" - " else:\n" - " mat_flags += 'x'\n" - "\n" - " if len(mat_flags) > 0:\n" - " mat_flags = ' ' + mat_flags\n" - "\n" - " mat_name = mat_type + mat_flags\n" - "\n" - " if mat_name in material_index:\n" - " return material_index.index(mat_name)\n" - " elif mat_name in material_dict:\n" - " material_index.append(mat_name)\n" - " return len(material_index)-1\n" - " else:\n" - " mat = make_color(len(material_dict), mat_type, mat_name)\n" - " mat.diffuse_intensity = 1.0\n" - " mat.specular_intensity = 0.0\n" - " mat.retro_unknown = ((data >> 0) & 1)\n" - " mat.retro_surface_stone = ((data >> 1) & 1)\n" - " mat.retro_surface_metal = ((data >> 2) & 1)\n" - " mat.retro_surface_grass = ((data >> 3) & 1) \n" - " mat.retro_surface_ice = ((data >> 4) & 1)\n" - " mat.retro_pillar = ((data >> 5) & 1)\n" - " mat.retro_surface_metal_grating = ((data >> 6) & 1)\n" - " mat.retro_surface_phazon = ((data >> 7) & 1)\n" - " mat.retro_surface_dirt = ((data >> 8) & 1)\n" - " mat.retro_surface_lava = ((data >> 9) & 1)\n" - " mat.retro_surface_lava_stone = ((data >> 10) & 1)\n" - " mat.retro_surface_snow = ((data >> 11) & 1)\n" - " mat.retro_surface_mud_slow = ((data >> 12) & 1)\n" - " mat.retro_half_pipe = ((data >> 13) & 1)\n" - " mat.retro_surface_mud = ((data >> 14) & 1)\n" - " mat.retro_surface_glass = ((data >> 15) & 1)\n" - " mat.retro_surface_shield = ((data >> 16) & 1)\n" - " mat.retro_surface_sand = ((data >> 17) & 1)\n" - " mat.retro_projectile_passthrough = ((data >> 18) & 1)\n" - " mat.retro_solid = ((data >> 19) & 1)\n" - " mat.retro_no_platform_collision = ((data >> 20) & 1)\n" - " mat.retro_camera_passthrough = ((data >> 21) & 1)\n" - " mat.retro_surface_wood = ((data >> 22) & 1)\n" - " mat.retro_surface_organic = ((data >> 23) & 1)\n" - " mat.retro_no_edge_collision = ((data >> 24) & 1)\n" - " mat.retro_see_through = ((data >> 26) & 1)\n" - " mat.retro_scan_passthrough = ((data >> 27) & 1)\n" - " mat.retro_ai_passthrough = ((data >> 28) & 1)\n" - " mat.retro_ceiling = ((data >> 29) & 1)\n" - " mat.retro_wall= ((data >> 30) & 1)\n" - " mat.retro_floor = ((data >> 31) & 1)\n" - " material_dict[mat_name] = mat\n" - " material_index.append(mat_name)\n" - " return len(material_index)-1\n" - "\n" - "\n"; +void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) { + os << "TYPE_COLORS = {'NoSFX':(0.0, 0.0, 0.0),\n" + " 'Stone':(1.0, 0.43, 0.15),\n" + " 'Metal':(0.5, 0.5, 0.5),\n" + " 'Grass':(0.0, 0.42, 0.01)," + " 'Ice':(0.0, 0.1, 0.1),\n" + " 'Metal Grating':(0.09, 0.09, 0.09),\n" + " 'Phazon':(0.24, 0.0, 0.21),\n" + " 'Dirt':(0.1, 0.07, 0.05),\n" + " 'Stone':(0.12, 0.12, 0.12),\n" + " 'Lava':(0.8, 0.15, 0.0),\n" + " 'Stone/Rock':(0.06, 0.05, 0.03),\n" + " 'Snow':(0.9, 1.0, 1.0),\n" + " 'Mud (Slow)':(0.12, 0.06, 0.02),\n" + " 'Mud':(0.12, 0.06, 0.02),\n" + " 'Glass':(0.27, 0.38, 0.9),\n" + " 'Shield':(1.0, 0.6, 0.0),\n" + " 'Sand':(0.53, 0.44, 0.21),\n" + " 'Wood':(0.30, 0.15, 0.03),\n" + " 'Organic':(0.19, 0.45, 0.2)}\n" + "\n" + "# Diffuse Color Maker\n" + "def make_color(index, mat_type, name):\n" + " new_mat = bpy.data.materials.new(name)\n" + " if mat_type in TYPE_COLORS:\n" + " new_mat.diffuse_color = TYPE_COLORS[mat_type]\n" + " else:\n" + " new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" + " return new_mat\n" + "\n" + "bpy.types.Material.retro_unknown = bpy.props.BoolProperty(name='Retro: Unknown (U)')\n" + "bpy.types.Material.retro_surface_stone = bpy.props.BoolProperty(name='Retro Surface: Stone')\n" + "bpy.types.Material.retro_surface_metal = bpy.props.BoolProperty(name='Retro Surface: Metal')\n" + "bpy.types.Material.retro_surface_grass = bpy.props.BoolProperty(name='Retro Surface: Grass')\n" + "bpy.types.Material.retro_surface_ice = bpy.props.BoolProperty(name='Retro Surface: Ice')\n" + "bpy.types.Material.retro_pillar = bpy.props.BoolProperty(name='Retro Pillar (I)')\n" + "bpy.types.Material.retro_surface_metal_grating = bpy.props.BoolProperty(name='Retro Surface: Metal Grating')\n" + "bpy.types.Material.retro_surface_phazon = bpy.props.BoolProperty(name='Retro Surface: Phazon')\n" + "bpy.types.Material.retro_surface_dirt = bpy.props.BoolProperty(name='Retro Surface: Rock')\n" + "bpy.types.Material.retro_surface_lava = bpy.props.BoolProperty(name='Retro Surface: Lava')\n" + "bpy.types.Material.retro_surface_lava_stone = bpy.props.BoolProperty(name='Retro Surface: Lava Stone')\n" + "bpy.types.Material.retro_surface_snow = bpy.props.BoolProperty(name='Retro Surface: Snow')\n" + "bpy.types.Material.retro_surface_mud_slow = bpy.props.BoolProperty(name='Retro Surface: Mud (Slow)')\n" + "bpy.types.Material.retro_half_pipe = bpy.props.BoolProperty(name='Retro: Half Pipe (H)')\n" + "bpy.types.Material.retro_surface_mud = bpy.props.BoolProperty(name='Retro Surface: Mud')\n" + "bpy.types.Material.retro_surface_glass = bpy.props.BoolProperty(name='Retro Surface: Glass')\n" + "bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(name='Retro Surface: Shield')\n" + "bpy.types.Material.retro_surface_sand = bpy.props.BoolProperty(name='Retro Surface: Sand')\n" + "bpy.types.Material.retro_projectile_passthrough = bpy.props.BoolProperty(name='Retro: Projectile Passthrough " + "(P)')\n" + "bpy.types.Material.retro_solid = bpy.props.BoolProperty(name='Retro: Solid (K)')\n" + "bpy.types.Material.retro_no_platform_collision = bpy.props.BoolProperty(name='Retro: No Platform Collision')\n" + "bpy.types.Material.retro_camera_passthrough = bpy.props.BoolProperty(name='Retro: Camera Passthrough (O)')\n" + "bpy.types.Material.retro_surface_wood = bpy.props.BoolProperty(name='Retro Surface: Wood')\n" + "bpy.types.Material.retro_surface_organic = bpy.props.BoolProperty(name='Retro Surface: Organic')\n" + "bpy.types.Material.retro_no_edge_collision = bpy.props.BoolProperty(name='Retro: No Edge Collision')\n" + "bpy.types.Material.retro_see_through = bpy.props.BoolProperty(name='Retro: See Through')\n" + "bpy.types.Material.retro_scan_passthrough = bpy.props.BoolProperty(name='Retro: Scan Passthrough (S)')\n" + "bpy.types.Material.retro_ai_passthrough = bpy.props.BoolProperty(name='Retro: AI Passthrough (A)')\n" + "bpy.types.Material.retro_ceiling = bpy.props.BoolProperty(name='Retro: Ceiling (C)')\n" + "bpy.types.Material.retro_wall = bpy.props.BoolProperty(name='Retro: Wall (W)')\n" + "bpy.types.Material.retro_floor = bpy.props.BoolProperty(name='Retro: Floor (F)')\n" + "\n" + "material_dict = {}\n" + "material_index = []\n" + "def get_type_id(data):\n" + "\n" + " ret = 0\n" + " for i in range(1, 24):\n" + " if i == 5 or i == 13 or i in range(18, 22):\n" + " continue\n" + " if ((data >> i) & 1):\n" + " ret = i\n" + " return ret\n" + "\n" + "def select_material(data):\n" + "\n" + " type_id = get_type_id(data)\n" + " mat_type = str(type_id)\n" + " if type_id == 0:\n" + " mat_type = 'NoSFX'\n" + " if type_id == 1:\n" + " mat_type = 'Stone'\n" + " elif type_id == 2:\n" + " mat_type = 'Metal'\n" + " elif type_id == 3:\n" + " mat_type = 'Grass'\n" + " elif type_id == 4:\n" + " mat_type = 'Ice'\n" + " elif type_id == 6:\n" + " mat_type = 'Metal Grating'\n" + " elif type_id == 7:\n" + " mat_type = 'Phazon'\n" + " elif type_id == 8:\n" + " mat_type = 'Dirt'\n" + " elif type_id == 9:\n" + " mat_type = 'Lava'\n" + " elif type_id == 10:\n" + " mat_type = 'Stone/Rock'\n" + " elif type_id == 11:\n" + " mat_type = 'Snow'\n" + " elif type_id == 12:\n" + " mat_type = 'Mud (Slow)'\n" + " elif type_id == 14:\n" + " mat_type = 'Mud'\n" + " elif type_id == 15:\n" + " mat_type = 'Glass'\n" + " elif type_id == 16:\n" + " mat_type = 'Shield'\n" + " elif type_id == 17:\n" + " mat_type = 'Sand'\n" + " elif type_id == 22:\n" + " mat_type = 'Wood'\n" + " elif type_id == 23:\n" + " mat_type = 'Organic'\n" + "\n" + " mat_flags = ''\n" + " if ((data >> 0) & 1):\n" + " mat_flags += 'U'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 5) & 1):\n" + " mat_flags += 'I'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 13) & 1):\n" + " mat_flags += 'H'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 18) & 1):\n" + " mat_flags += 'P'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 19) & 1):\n" + " mat_flags += 'K'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 20) & 1):\n" + " mat_flags += 'u'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 21) & 1):\n" + " mat_flags += 'O'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 24) & 1):\n" + " mat_flags += 'u'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 26) & 1):\n" + " mat_flags += 'T'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 27) & 1):\n" + " mat_flags += 'S'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 28) & 1):\n" + " mat_flags += 'A'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 29) & 1):\n" + " mat_flags += 'C'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 30) & 1):\n" + " mat_flags += 'W'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 31) & 1):\n" + " mat_flags += 'F'\n" + " else:\n" + " mat_flags += 'x'\n" + "\n" + " if len(mat_flags) > 0:\n" + " mat_flags = ' ' + mat_flags\n" + "\n" + " mat_name = mat_type + mat_flags\n" + "\n" + " if mat_name in material_index:\n" + " return material_index.index(mat_name)\n" + " elif mat_name in material_dict:\n" + " material_index.append(mat_name)\n" + " return len(material_index)-1\n" + " else:\n" + " mat = make_color(len(material_dict), mat_type, mat_name)\n" + " mat.diffuse_intensity = 1.0\n" + " mat.specular_intensity = 0.0\n" + " mat.retro_unknown = ((data >> 0) & 1)\n" + " mat.retro_surface_stone = ((data >> 1) & 1)\n" + " mat.retro_surface_metal = ((data >> 2) & 1)\n" + " mat.retro_surface_grass = ((data >> 3) & 1) \n" + " mat.retro_surface_ice = ((data >> 4) & 1)\n" + " mat.retro_pillar = ((data >> 5) & 1)\n" + " mat.retro_surface_metal_grating = ((data >> 6) & 1)\n" + " mat.retro_surface_phazon = ((data >> 7) & 1)\n" + " mat.retro_surface_dirt = ((data >> 8) & 1)\n" + " mat.retro_surface_lava = ((data >> 9) & 1)\n" + " mat.retro_surface_lava_stone = ((data >> 10) & 1)\n" + " mat.retro_surface_snow = ((data >> 11) & 1)\n" + " mat.retro_surface_mud_slow = ((data >> 12) & 1)\n" + " mat.retro_half_pipe = ((data >> 13) & 1)\n" + " mat.retro_surface_mud = ((data >> 14) & 1)\n" + " mat.retro_surface_glass = ((data >> 15) & 1)\n" + " mat.retro_surface_shield = ((data >> 16) & 1)\n" + " mat.retro_surface_sand = ((data >> 17) & 1)\n" + " mat.retro_projectile_passthrough = ((data >> 18) & 1)\n" + " mat.retro_solid = ((data >> 19) & 1)\n" + " mat.retro_no_platform_collision = ((data >> 20) & 1)\n" + " mat.retro_camera_passthrough = ((data >> 21) & 1)\n" + " mat.retro_surface_wood = ((data >> 22) & 1)\n" + " mat.retro_surface_organic = ((data >> 23) & 1)\n" + " mat.retro_no_edge_collision = ((data >> 24) & 1)\n" + " mat.retro_see_through = ((data >> 26) & 1)\n" + " mat.retro_scan_passthrough = ((data >> 27) & 1)\n" + " mat.retro_ai_passthrough = ((data >> 28) & 1)\n" + " mat.retro_ceiling = ((data >> 29) & 1)\n" + " mat.retro_wall= ((data >> 30) & 1)\n" + " mat.retro_floor = ((data >> 31) & 1)\n" + " material_dict[mat_name] = mat\n" + " material_index.append(mat_name)\n" + " return len(material_index)-1\n" + "\n" + "\n"; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/DeafBabe.hpp b/DataSpec/DNAMP1/DeafBabe.hpp index 57195400b..cd7a3f77b 100644 --- a/DataSpec/DNAMP1/DeafBabe.hpp +++ b/DataSpec/DNAMP1/DeafBabe.hpp @@ -2,152 +2,239 @@ #include "DataSpec/DNACommon/DeafBabe.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct DeafBabe : BigDNA -{ +struct DeafBabe : BigDNA { + AT_DECL_DNA + using BspNodeType = DataSpec::BspNodeType; + + struct Material : BigDNA { AT_DECL_DNA - using BspNodeType = DataSpec::BspNodeType; - - struct Material : BigDNA - { - AT_DECL_DNA - Value material = 0; - bool unknown() const { return material & 1; } - void setUnknown(bool v) { material &= ~1; material |= int(v); } - bool surfaceStone() const { return (material >> 1) & 1; } - void setSurfaceStone(bool v) { material &= ~(1ull << 1); material |= (v << 1); } - bool surfaceMetal() const { return (material >> 2) & 1; } - void setSurfaceMetal(bool v) { material &= ~(1ull << 2); material |= (v << 2); } - bool surfaceGrass() const { return (material >> 3) & 1; } - void setSurfaceGrass(bool v) { material &= ~(1ull << 3); material |= (v << 3); } - bool surfaceIce() const { return (material >> 4) & 1; } - void setSurfaceIce(bool v) { material &= ~(1ull << 4); material |= (v << 4); } - bool pillar() const { return (material >> 5) & 1; } - void setPillar(bool v) { material &= ~(1ull << 5); material |= (v << 5); } - bool surfaceMetalGrating() const { return (material >> 6) & 1; } - void setSurfaceMetalGrating(bool v) { material &= ~(1ull << 6); material |= (v << 6); } - bool surfacePhazon() const { return (material >> 7) & 1; } - void setSurfacePhazon(bool v) { material &= ~(1ull << 7); material |= (v << 7); } - bool surfaceDirt() const { return (material >> 8) & 1; } - void setSurfaceDirt(bool v) { material &= ~(1ull << 8); material |= (v << 8); } - bool surfaceLava() const {return (material >> 9) & 1; } - void setSurfaceLava(bool v) { material &= ~(1ull << 9); material |= (v << 9); } - bool surfaceStoneRock() const { return (material >> 10) & 1; } - void setSurfaceLavaStone(bool v) { material &= ~(1ull << 10); material |= (v << 10); } - bool surfaceSnow() const { return (material >> 11) & 1; } - void setSurfaceSnow(bool v) { material &= ~(1ull << 11); material |= (v << 11); } - bool surfaceMudSlow() const { return (material >> 12) & 1; } - void setSurfaceMudSlow(bool v) { material &= ~(1ull << 12); material |= (v << 12); } - bool halfPipe() const { return (material >> 13) & 1; } - void setHalfPipe(bool v) { material &= ~(1ull << 13); material |= (v << 13); } - bool surfaceMud() const { return (material >> 14) & 1; } - void setSurfaceMud(bool v) { material &= ~(1ull << 14); material |= (v << 14); } - bool surfaceGlass() const { return (material >> 15) & 1; } - void setSurfaceGlass(bool v) { material &= ~(1ull << 15); material |= (v << 15); } - bool surfaceShield() const { return (material >> 16) & 1; } - void setSurfaceShield(bool v) { material &= ~(1ull << 16); material |= (v << 16); } - bool surfaceSand() const { return (material >> 17) & 1; } - void setSurfaceSand(bool v) { material &= ~(1ull << 17); material |= (v << 17); } - bool projectilePassthrough() const { return (material >> 18) & 1; } - void setProjectilePassthrough(bool v) { material &= ~(1ull << 18); material |= (v << 18); } - bool solid() const { return (material >> 19) & 1; } - void setSolid(bool v) { material &= ~(1ull << 19); material |= (v << 19); } - bool noPlatformCollision() const { return (material >> 20) & 1; } - void setNoPlatformCollision(bool v) { material &= ~(1ull << 20); material |= (v << 20); } - bool cameraPassthrough() const { return (material >> 21) & 1; } - void setCameraPassthrough(bool v) { material &= ~(1ull << 21); material |= (v << 21); } - bool surfaceWood() const { return (material >> 22) & 1; } - void setSurfaceWood(bool v) { material &= ~(1ull << 22); material |= (v << 22); } - bool surfaceOrganic() const { return (material >> 23) & 1; } - void setSurfaceOrganic(bool v) { material &= ~(1ull << 23); material |= (v << 23); } - bool noEdgeCollision() const { return (material >> 24) & 1; } - void setNoEdgeCollision(bool v) { material &= ~(1ull << 24); material |= (v << 24); } - bool flipFace() const { return (material >> 25) & 1; } - void setFlipFace(bool v) { material &= ~(1ull << 25); material |= (v << 25); } - bool seeThrough() const { return (material >> 26) & 1; } - void setSeeThrough(bool v) { material &= ~(1ull << 26); material |= (v << 26); } - bool scanPassthrough() const { return (material >> 27) & 1; } - void setScanPassthrough(bool v) { material &= ~(1ull << 27); material |= (v << 27); } - bool aiPassthrough() const { return (material >> 28) & 1; } - void setAiPassthrough(bool v) { material &= ~(1ull << 28); material |= (v << 28); } - bool ceiling() const { return (material >> 29) & 1; } - void setCeiling(bool v) { material &= ~(1ull << 29); material |= (v << 29); } - bool wall() const { return (material >> 30) & 1; } - void setWall(bool v) { material &= ~(1ull << 30); material |= (v << 30); } - bool floor() const { return (material >> 31) & 1; } - void setFloor(bool v) { material &= ~(1ull << 31); material |= (v << 31); } - - /* Dummies for later games */ - bool surfaceSPMetal() const { return false; } - void setSurfaceSPMetal(bool v) { } - bool surfaceFabric() const { return false; } - void setSurfaceFabric(bool v) { } - bool surfaceRubber() const { return false; } - void setSurfaceRubber(bool v) { } - bool surfaceMothOrSeedOrganics() const { return false; } - void setSurfaceMothOrSeedOrganics(bool v) { } - bool surfaceWeb() const { return false; } - void setSurfaceWeb(bool v) { } - bool unused3() const { return false; } - void setUnused3(bool v) {} - bool unused4() const { return false; } - void setUnused4(bool v) {} - bool aiBlock() const { return false; } - void setAiBlock(bool v) { } - bool jumpNotAllowed() const { return false; } - void setJumpNotAllowed(bool v) { } - bool spiderBall() const { return false; } - void setSpiderBall(bool v) { } - bool screwAttackWallJump() const { return false; } - void setScrewAttackWallJump(bool v) { } - }; - - struct Edge : BigDNA - { - AT_DECL_DNA - Value verts[2]; - }; - - struct Triangle : BigDNA - { - AT_DECL_DNA - Value edges[3]; - }; - - Value unk1; - Value length; - Value magic; - Value version; - Value aabb[2]; - Value rootNodeType; - Value bspSize; - Buffer bspTree; - Value materialCount; - Vector materials; - Value vertMatsCount; - Vector vertMats; - Value edgeMatsCount; - Vector edgeMats; - Value triMatsCount; - Vector triMats; - Value edgeVertsCount; - Vector edgeVertConnections; - Value triangleEdgesCount; - Vector triangleEdgeConnections; - Value vertCount; - Vector verts; - - /* Dummy MP2 member */ - void insertNoClimb(hecl::blender::PyOutStream&) const {} - - static void BlenderInit(hecl::blender::PyOutStream& os); - void sendToBlender(hecl::blender::PyOutStream& os) const - { - DeafBabeSendToBlender(os, *this); + Value material = 0; + bool unknown() const { return material & 1; } + void setUnknown(bool v) { + material &= ~1; + material |= int(v); } + bool surfaceStone() const { return (material >> 1) & 1; } + void setSurfaceStone(bool v) { + material &= ~(1ull << 1); + material |= (v << 1); + } + bool surfaceMetal() const { return (material >> 2) & 1; } + void setSurfaceMetal(bool v) { + material &= ~(1ull << 2); + material |= (v << 2); + } + bool surfaceGrass() const { return (material >> 3) & 1; } + void setSurfaceGrass(bool v) { + material &= ~(1ull << 3); + material |= (v << 3); + } + bool surfaceIce() const { return (material >> 4) & 1; } + void setSurfaceIce(bool v) { + material &= ~(1ull << 4); + material |= (v << 4); + } + bool pillar() const { return (material >> 5) & 1; } + void setPillar(bool v) { + material &= ~(1ull << 5); + material |= (v << 5); + } + bool surfaceMetalGrating() const { return (material >> 6) & 1; } + void setSurfaceMetalGrating(bool v) { + material &= ~(1ull << 6); + material |= (v << 6); + } + bool surfacePhazon() const { return (material >> 7) & 1; } + void setSurfacePhazon(bool v) { + material &= ~(1ull << 7); + material |= (v << 7); + } + bool surfaceDirt() const { return (material >> 8) & 1; } + void setSurfaceDirt(bool v) { + material &= ~(1ull << 8); + material |= (v << 8); + } + bool surfaceLava() const { return (material >> 9) & 1; } + void setSurfaceLava(bool v) { + material &= ~(1ull << 9); + material |= (v << 9); + } + bool surfaceStoneRock() const { return (material >> 10) & 1; } + void setSurfaceLavaStone(bool v) { + material &= ~(1ull << 10); + material |= (v << 10); + } + bool surfaceSnow() const { return (material >> 11) & 1; } + void setSurfaceSnow(bool v) { + material &= ~(1ull << 11); + material |= (v << 11); + } + bool surfaceMudSlow() const { return (material >> 12) & 1; } + void setSurfaceMudSlow(bool v) { + material &= ~(1ull << 12); + material |= (v << 12); + } + bool halfPipe() const { return (material >> 13) & 1; } + void setHalfPipe(bool v) { + material &= ~(1ull << 13); + material |= (v << 13); + } + bool surfaceMud() const { return (material >> 14) & 1; } + void setSurfaceMud(bool v) { + material &= ~(1ull << 14); + material |= (v << 14); + } + bool surfaceGlass() const { return (material >> 15) & 1; } + void setSurfaceGlass(bool v) { + material &= ~(1ull << 15); + material |= (v << 15); + } + bool surfaceShield() const { return (material >> 16) & 1; } + void setSurfaceShield(bool v) { + material &= ~(1ull << 16); + material |= (v << 16); + } + bool surfaceSand() const { return (material >> 17) & 1; } + void setSurfaceSand(bool v) { + material &= ~(1ull << 17); + material |= (v << 17); + } + bool projectilePassthrough() const { return (material >> 18) & 1; } + void setProjectilePassthrough(bool v) { + material &= ~(1ull << 18); + material |= (v << 18); + } + bool solid() const { return (material >> 19) & 1; } + void setSolid(bool v) { + material &= ~(1ull << 19); + material |= (v << 19); + } + bool noPlatformCollision() const { return (material >> 20) & 1; } + void setNoPlatformCollision(bool v) { + material &= ~(1ull << 20); + material |= (v << 20); + } + bool cameraPassthrough() const { return (material >> 21) & 1; } + void setCameraPassthrough(bool v) { + material &= ~(1ull << 21); + material |= (v << 21); + } + bool surfaceWood() const { return (material >> 22) & 1; } + void setSurfaceWood(bool v) { + material &= ~(1ull << 22); + material |= (v << 22); + } + bool surfaceOrganic() const { return (material >> 23) & 1; } + void setSurfaceOrganic(bool v) { + material &= ~(1ull << 23); + material |= (v << 23); + } + bool noEdgeCollision() const { return (material >> 24) & 1; } + void setNoEdgeCollision(bool v) { + material &= ~(1ull << 24); + material |= (v << 24); + } + bool flipFace() const { return (material >> 25) & 1; } + void setFlipFace(bool v) { + material &= ~(1ull << 25); + material |= (v << 25); + } + bool seeThrough() const { return (material >> 26) & 1; } + void setSeeThrough(bool v) { + material &= ~(1ull << 26); + material |= (v << 26); + } + bool scanPassthrough() const { return (material >> 27) & 1; } + void setScanPassthrough(bool v) { + material &= ~(1ull << 27); + material |= (v << 27); + } + bool aiPassthrough() const { return (material >> 28) & 1; } + void setAiPassthrough(bool v) { + material &= ~(1ull << 28); + material |= (v << 28); + } + bool ceiling() const { return (material >> 29) & 1; } + void setCeiling(bool v) { + material &= ~(1ull << 29); + material |= (v << 29); + } + bool wall() const { return (material >> 30) & 1; } + void setWall(bool v) { + material &= ~(1ull << 30); + material |= (v << 30); + } + bool floor() const { return (material >> 31) & 1; } + void setFloor(bool v) { + material &= ~(1ull << 31); + material |= (v << 31); + } + + /* Dummies for later games */ + bool surfaceSPMetal() const { return false; } + void setSurfaceSPMetal(bool v) {} + bool surfaceFabric() const { return false; } + void setSurfaceFabric(bool v) {} + bool surfaceRubber() const { return false; } + void setSurfaceRubber(bool v) {} + bool surfaceMothOrSeedOrganics() const { return false; } + void setSurfaceMothOrSeedOrganics(bool v) {} + bool surfaceWeb() const { return false; } + void setSurfaceWeb(bool v) {} + bool unused3() const { return false; } + void setUnused3(bool v) {} + bool unused4() const { return false; } + void setUnused4(bool v) {} + bool aiBlock() const { return false; } + void setAiBlock(bool v) {} + bool jumpNotAllowed() const { return false; } + void setJumpNotAllowed(bool v) {} + bool spiderBall() const { return false; } + void setSpiderBall(bool v) {} + bool screwAttackWallJump() const { return false; } + void setScrewAttackWallJump(bool v) {} + }; + + struct Edge : BigDNA { + AT_DECL_DNA + Value verts[2]; + }; + + struct Triangle : BigDNA { + AT_DECL_DNA + Value edges[3]; + }; + + Value unk1; + Value length; + Value magic; + Value version; + Value aabb[2]; + Value rootNodeType; + Value bspSize; + Buffer bspTree; + Value materialCount; + Vector materials; + Value vertMatsCount; + Vector vertMats; + Value edgeMatsCount; + Vector edgeMats; + Value triMatsCount; + Vector triMats; + Value edgeVertsCount; + Vector edgeVertConnections; + Value triangleEdgesCount; + Vector triangleEdgeConnections; + Value vertCount; + Vector verts; + + /* Dummy MP2 member */ + void insertNoClimb(hecl::blender::PyOutStream&) const {} + + static void BlenderInit(hecl::blender::PyOutStream& os); + void sendToBlender(hecl::blender::PyOutStream& os) const { DeafBabeSendToBlender(os, *this); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/EVNT.cpp b/DataSpec/DNAMP1/EVNT.cpp index 89bf366ae..ad8f0ee24 100644 --- a/DataSpec/DNAMP1/EVNT.cpp +++ b/DataSpec/DNAMP1/EVNT.cpp @@ -1,34 +1,28 @@ #include "EVNT.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template -void EVNT::Enumerate(typename Op::StreamT& s) -{ - Do({"version"}, version, s); +void EVNT::Enumerate(typename Op::StreamT& s) { + Do({"version"}, version, s); - DoSize({"boolPOICount"}, boolPOICount, s); - Do({"boolPOINodes"}, boolPOINodes, boolPOICount, s); + DoSize({"boolPOICount"}, boolPOICount, s); + Do({"boolPOINodes"}, boolPOINodes, boolPOICount, s); - DoSize({"int32POICount"}, int32POICount, s); - Do({"int32POINodes"}, int32POINodes, int32POICount, s); + DoSize({"int32POICount"}, int32POICount, s); + Do({"int32POINodes"}, int32POINodes, int32POICount, s); - DoSize({"particlePOICount"}, particlePOICount, s); - Do({"particlePOINodes"}, particlePOINodes, particlePOICount, s); + DoSize({"particlePOICount"}, particlePOICount, s); + Do({"particlePOINodes"}, particlePOINodes, particlePOICount, s); - if (version == 2) - { - DoSize({"soundPOICount"}, soundPOICount, s); - Do({"soundPOINodes"}, soundPOINodes, soundPOICount, s); - } + if (version == 2) { + DoSize({"soundPOICount"}, soundPOICount, s); + Do({"soundPOINodes"}, soundPOINodes, soundPOICount, s); + } } AT_SPECIALIZE_DNA_YAML(EVNT) -const char* EVNT::DNAType() -{ - return "urde::DNAMP1::EVNT"; -} +const char* EVNT::DNAType() { return "urde::DNAMP1::EVNT"; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/EVNT.hpp b/DataSpec/DNAMP1/EVNT.hpp index 2a3e8db4f..8d39a78ed 100644 --- a/DataSpec/DNAMP1/EVNT.hpp +++ b/DataSpec/DNAMP1/EVNT.hpp @@ -3,109 +3,90 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct EVNT : BigDNA -{ - AT_DECL_EXPLICIT_DNA_YAML - Value version; +struct EVNT : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + Value version; - struct POINode : BigDNA - { - AT_DECL_DNA_YAML - Value unk0; - String<-1> name; - Value type; - struct CharAnimTime : BigDNA - { - enum class Type : atUint32 - { - NonZero, - ZeroIncreasing, - ZeroSteady, - ZeroDecreasing, - Infinity - }; + struct POINode : BigDNA { + AT_DECL_DNA_YAML + Value unk0; + String<-1> name; + Value type; + struct CharAnimTime : BigDNA { + enum class Type : atUint32 { NonZero, ZeroIncreasing, ZeroSteady, ZeroDecreasing, Infinity }; - AT_DECL_DNA_YAML - Value time; - Value type; - }; - - CharAnimTime animTime; - Value idx; - Value unk2; - Value weight; - Value charIdx; - Value flags; + AT_DECL_DNA_YAML + Value time; + Value type; }; - struct BoolPOINode : POINode - { - AT_DECL_DNA_YAML - Value value; - }; - Value boolPOICount; - Vector boolPOINodes; + CharAnimTime animTime; + Value idx; + Value unk2; + Value weight; + Value charIdx; + Value flags; + }; - struct Int32POINode : POINode - { - AT_DECL_DNA_YAML - Value value; - String<-1> locator; - }; - Value int32POICount; - Vector int32POINodes; + struct BoolPOINode : POINode { + AT_DECL_DNA_YAML + Value value; + }; + Value boolPOICount; + Vector boolPOINodes; - struct ParticlePOINode : POINode - { - AT_DECL_DNA_YAML - Value duration; - DNAFourCC ptype; - UniqueID32 id; - String<-1> locator; - Value scale; - Value parentMode; - }; - Value particlePOICount; - Vector particlePOINodes; + struct Int32POINode : POINode { + AT_DECL_DNA_YAML + Value value; + String<-1> locator; + }; + Value int32POICount; + Vector int32POINodes; - struct SoundPOINode : POINode - { - AT_DECL_DNA_YAML - Value soundId; - Value falloff; - Value maxDist; - }; - Value soundPOICount; - Vector soundPOINodes; + struct ParticlePOINode : POINode { + AT_DECL_DNA_YAML + Value duration; + DNAFourCC ptype; + UniqueID32 id; + String<-1> locator; + Value scale; + Value parentMode; + }; + Value particlePOICount; + Vector particlePOINodes; - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) - { - EVNT evnt; - evnt.read(rs); - athena::io::FileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(evnt, writer); - return true; - } + struct SoundPOINode : POINode { + AT_DECL_DNA_YAML + Value soundId; + Value falloff; + Value maxDist; + }; + Value soundPOICount; + Vector soundPOINodes; - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) - { - EVNT evnt; - athena::io::FileReader reader(inPath.getAbsolutePath()); - athena::io::FromYAMLStream(evnt, reader); - athena::io::FileWriter ws(outPath.getAbsolutePath()); - evnt.write(ws); - return true; - } + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + EVNT evnt; + evnt.read(rs); + athena::io::FileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(evnt, writer); + return true; + } - void gatherDependencies(std::vector& pathsOut) const - { - for (const ParticlePOINode& node : particlePOINodes) - g_curSpec->flattenDependencies(node.id, pathsOut); - } + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + EVNT evnt; + athena::io::FileReader reader(inPath.getAbsolutePath()); + athena::io::FromYAMLStream(evnt, reader); + athena::io::FileWriter ws(outPath.getAbsolutePath()); + evnt.write(ws); + return true; + } + + void gatherDependencies(std::vector& pathsOut) const { + for (const ParticlePOINode& node : particlePOINodes) + g_curSpec->flattenDependencies(node.id, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/FRME.cpp b/DataSpec/DNAMP1/FRME.cpp index 9a0ea0057..93a3e641a 100644 --- a/DataSpec/DNAMP1/FRME.cpp +++ b/DataSpec/DNAMP1/FRME.cpp @@ -2,673 +2,625 @@ #include "DataSpec/DNACommon/TXTR.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template <> -void FRME::Enumerate(athena::io::IStreamReader& __dna_reader) -{ - /* version */ - version = __dna_reader.readUint32Big(); - /* unk1 */ - unk1 = __dna_reader.readUint32Big(); - /* modelCount */ - modelCount = __dna_reader.readUint32Big(); - /* unk3 */ - unk3 = __dna_reader.readUint32Big(); - /* widgetCount */ - widgetCount = __dna_reader.readUint32Big(); - /* widgets */ - __dna_reader.enumerate(widgets, widgetCount, [this](athena::io::IStreamReader& reader, Widget& w) { - w.owner = this; - w.read(reader); - }); +void FRME::Enumerate(athena::io::IStreamReader& __dna_reader) { + /* version */ + version = __dna_reader.readUint32Big(); + /* unk1 */ + unk1 = __dna_reader.readUint32Big(); + /* modelCount */ + modelCount = __dna_reader.readUint32Big(); + /* unk3 */ + unk3 = __dna_reader.readUint32Big(); + /* widgetCount */ + widgetCount = __dna_reader.readUint32Big(); + /* widgets */ + __dna_reader.enumerate(widgets, widgetCount, [this](athena::io::IStreamReader& reader, Widget& w) { + w.owner = this; + w.read(reader); + }); } template <> -void FRME::Enumerate(athena::io::IStreamWriter& __dna_writer) -{ - /* version */ - __dna_writer.writeUint32Big(version); - /* unk1 */ - __dna_writer.writeUint32Big(unk1); - /* modelCount */ - __dna_writer.writeUint32Big(modelCount); - /* unk3 */ - __dna_writer.writeUint32Big(unk3); - /* widgetCount */ - __dna_writer.writeUint32Big(widgetCount); - /* widgets */ - __dna_writer.enumerate(widgets); +void FRME::Enumerate(athena::io::IStreamWriter& __dna_writer) { + /* version */ + __dna_writer.writeUint32Big(version); + /* unk1 */ + __dna_writer.writeUint32Big(unk1); + /* modelCount */ + __dna_writer.writeUint32Big(modelCount); + /* unk3 */ + __dna_writer.writeUint32Big(unk3); + /* widgetCount */ + __dna_writer.writeUint32Big(widgetCount); + /* widgets */ + __dna_writer.enumerate(widgets); } template <> -void FRME::Enumerate(size_t& __isz) -{ - for (const Widget& w : widgets) - w.binarySize(__isz); - __isz += 20; +void FRME::Enumerate(size_t& __isz) { + for (const Widget& w : widgets) + w.binarySize(__isz); + __isz += 20; } template <> -void FRME::Widget::Enumerate(athena::io::IStreamReader& __dna_reader) -{ - /* type */ - type.read(__dna_reader); - /* header */ - header.read(__dna_reader); - switch(type) - { - case SBIG('BWIG'): widgetInfo.reset(new BWIGInfo); break; - case SBIG('HWIG'): widgetInfo.reset(new HWIGInfo); break; - case SBIG('CAMR'): widgetInfo.reset(new CAMRInfo); break; - case SBIG('LITE'): widgetInfo.reset(new LITEInfo); break; - case SBIG('ENRG'): widgetInfo.reset(new ENRGInfo); break; - case SBIG('MODL'): widgetInfo.reset(new MODLInfo); break; - case SBIG('METR'): widgetInfo.reset(new METRInfo); break; - case SBIG('GRUP'): widgetInfo.reset(new GRUPInfo); break; - case SBIG('PANE'): widgetInfo.reset(new PANEInfo); break; - case SBIG('TXPN'): widgetInfo.reset(new TXPNInfo(owner->version)); break; - case SBIG('IMGP'): widgetInfo.reset(new IMGPInfo); break; - case SBIG('TBGP'): widgetInfo.reset(new TBGPInfo); break; - case SBIG('SLGP'): widgetInfo.reset(new SLGPInfo); break; - default: - Log.report(logvisor::Fatal, _SYS_STR("Unsupported FRME widget type %.8X"), type.toUint32()); - } +void FRME::Widget::Enumerate(athena::io::IStreamReader& __dna_reader) { + /* type */ + type.read(__dna_reader); + /* header */ + header.read(__dna_reader); + switch (type) { + case SBIG('BWIG'): + widgetInfo.reset(new BWIGInfo); + break; + case SBIG('HWIG'): + widgetInfo.reset(new HWIGInfo); + break; + case SBIG('CAMR'): + widgetInfo.reset(new CAMRInfo); + break; + case SBIG('LITE'): + widgetInfo.reset(new LITEInfo); + break; + case SBIG('ENRG'): + widgetInfo.reset(new ENRGInfo); + break; + case SBIG('MODL'): + widgetInfo.reset(new MODLInfo); + break; + case SBIG('METR'): + widgetInfo.reset(new METRInfo); + break; + case SBIG('GRUP'): + widgetInfo.reset(new GRUPInfo); + break; + case SBIG('PANE'): + widgetInfo.reset(new PANEInfo); + break; + case SBIG('TXPN'): + widgetInfo.reset(new TXPNInfo(owner->version)); + break; + case SBIG('IMGP'): + widgetInfo.reset(new IMGPInfo); + break; + case SBIG('TBGP'): + widgetInfo.reset(new TBGPInfo); + break; + case SBIG('SLGP'): + widgetInfo.reset(new SLGPInfo); + break; + default: + Log.report(logvisor::Fatal, _SYS_STR("Unsupported FRME widget type %.8X"), type.toUint32()); + } - /* widgetInfo */ - widgetInfo->read(__dna_reader); + /* widgetInfo */ + widgetInfo->read(__dna_reader); - /* isWorker */ - isWorker = __dna_reader.readBool(); - if (isWorker) - { - /* workerId */ - workerId = __dna_reader.readUint16Big(); - } - /* origin */ - origin = __dna_reader.readVec3fBig(); - /* basis[0] */ - basis[0] = __dna_reader.readVec3fBig(); - /* basis[1] */ - basis[1] = __dna_reader.readVec3fBig(); - /* basis[2] */ - basis[2] = __dna_reader.readVec3fBig(); - /* rotationCenter */ - rotationCenter = __dna_reader.readVec3fBig(); - /* unk1 */ - unk1 = __dna_reader.readInt32Big(); - /* unk2 */ - unk2 = __dna_reader.readInt16Big(); + /* isWorker */ + isWorker = __dna_reader.readBool(); + if (isWorker) { + /* workerId */ + workerId = __dna_reader.readUint16Big(); + } + /* origin */ + origin = __dna_reader.readVec3fBig(); + /* basis[0] */ + basis[0] = __dna_reader.readVec3fBig(); + /* basis[1] */ + basis[1] = __dna_reader.readVec3fBig(); + /* basis[2] */ + basis[2] = __dna_reader.readVec3fBig(); + /* rotationCenter */ + rotationCenter = __dna_reader.readVec3fBig(); + /* unk1 */ + unk1 = __dna_reader.readInt32Big(); + /* unk2 */ + unk2 = __dna_reader.readInt16Big(); } template <> -void FRME::Widget::Enumerate(athena::io::IStreamWriter& __dna_writer) -{ - /* type */ - DNAFourCC _type = widgetInfo ? widgetInfo->fourcc() : FOURCC('BWIG'); - _type.write(__dna_writer); - /* header */ - header.write(__dna_writer); +void FRME::Widget::Enumerate(athena::io::IStreamWriter& __dna_writer) { + /* type */ + DNAFourCC _type = widgetInfo ? widgetInfo->fourcc() : FOURCC('BWIG'); + _type.write(__dna_writer); + /* header */ + header.write(__dna_writer); - /* widgetInfo */ - if (widgetInfo) - widgetInfo->write(__dna_writer); + /* widgetInfo */ + if (widgetInfo) + widgetInfo->write(__dna_writer); - /* isWorker */ - __dna_writer.writeBool(isWorker); - if (isWorker) - { - /* workerId */ - __dna_writer.writeUint16Big(workerId); - } - /* origin */ - __dna_writer.writeVec3fBig(origin); - /* basis[0] */ - __dna_writer.writeVec3fBig(basis[0]); - /* basis[1] */ - __dna_writer.writeVec3fBig(basis[1]); - /* basis[2] */ - __dna_writer.writeVec3fBig(basis[2]); - /* rotationCenter */ - __dna_writer.writeVec3fBig(rotationCenter); - /* unk1 */ - __dna_writer.writeInt32Big(unk1); - /* unk2 */ - __dna_writer.writeInt16Big(unk2); + /* isWorker */ + __dna_writer.writeBool(isWorker); + if (isWorker) { + /* workerId */ + __dna_writer.writeUint16Big(workerId); + } + /* origin */ + __dna_writer.writeVec3fBig(origin); + /* basis[0] */ + __dna_writer.writeVec3fBig(basis[0]); + /* basis[1] */ + __dna_writer.writeVec3fBig(basis[1]); + /* basis[2] */ + __dna_writer.writeVec3fBig(basis[2]); + /* rotationCenter */ + __dna_writer.writeVec3fBig(rotationCenter); + /* unk1 */ + __dna_writer.writeInt32Big(unk1); + /* unk2 */ + __dna_writer.writeInt16Big(unk2); } template <> -void FRME::Widget::Enumerate(size_t& __isz) -{ - type.binarySize(__isz); - header.binarySize(__isz); - if (widgetInfo) - widgetInfo->binarySize(__isz); - if (isWorker) - __isz += 4; - __isz += 67; -} - -template <> -void FRME::Widget::CAMRInfo::Enumerate(athena::io::IStreamReader& __dna_reader) -{ - projectionType = ProjectionType(__dna_reader.readUint32Big()); - if (projectionType == ProjectionType::Perspective) - projection.reset(new PerspectiveProjection); - else if (projectionType == ProjectionType::Orthographic) - projection.reset(new OrthographicProjection); - else - Log.report(logvisor::Fatal, _SYS_STR("Invalid CAMR projection mode! %i"), int(projectionType)); - - projection->read(__dna_reader); -} - -template <> -void FRME::Widget::CAMRInfo::Enumerate(athena::io::IStreamWriter& __dna_writer) -{ - if (!projection) - Log.report(logvisor::Fatal, _SYS_STR("Invalid CAMR projection object!")); - if (projection->type != projectionType) - Log.report(logvisor::Fatal, _SYS_STR("CAMR projection type does not match actual projection type!")); - - __dna_writer.writeUint32Big(atUint32(projectionType)); - projection->write(__dna_writer); -} - -template <> -void FRME::Widget::CAMRInfo::Enumerate(size_t& __isz) -{ - projection->binarySize(__isz); +void FRME::Widget::Enumerate(size_t& __isz) { + type.binarySize(__isz); + header.binarySize(__isz); + if (widgetInfo) + widgetInfo->binarySize(__isz); + if (isWorker) __isz += 4; + __isz += 67; } template <> -void FRME::Widget::LITEInfo::Enumerate(athena::io::IStreamReader& __dna_reader) -{ - /* type */ - type = ELightType(__dna_reader.readUint32Big()); - /* distC */ - distC = __dna_reader.readFloatBig(); - /* distL */ - distL = __dna_reader.readFloatBig(); - /* distQ */ - distQ = __dna_reader.readFloatBig(); - /* angC */ - angC = __dna_reader.readFloatBig(); - /* angL */ - angL = __dna_reader.readFloatBig(); - /* angQ */ - angQ = __dna_reader.readFloatBig(); - /* loadedIdx */ - loadedIdx = __dna_reader.readUint32Big(); +void FRME::Widget::CAMRInfo::Enumerate(athena::io::IStreamReader& __dna_reader) { + projectionType = ProjectionType(__dna_reader.readUint32Big()); + if (projectionType == ProjectionType::Perspective) + projection.reset(new PerspectiveProjection); + else if (projectionType == ProjectionType::Orthographic) + projection.reset(new OrthographicProjection); + else + Log.report(logvisor::Fatal, _SYS_STR("Invalid CAMR projection mode! %i"), int(projectionType)); - /* cutoff */ - if (type == ELightType::Spot) - cutoff = __dna_reader.readFloatBig(); + projection->read(__dna_reader); } template <> -void FRME::Widget::LITEInfo::Enumerate(athena::io::IStreamWriter& __dna_writer) -{ - /* type */ - __dna_writer.writeUint32Big(atUint32(type)); - /* distC */ - __dna_writer.writeFloatBig(distC); - /* distL */ - __dna_writer.writeFloatBig(distL); - /* distQ */ - __dna_writer.writeFloatBig(distQ); - /* angC */ - __dna_writer.writeFloatBig(angC); - /* angL */ - __dna_writer.writeFloatBig(angL); - /* angQ */ - __dna_writer.writeFloatBig(angQ); - /* loadedIdx */ - __dna_writer.writeUint32Big(loadedIdx); +void FRME::Widget::CAMRInfo::Enumerate(athena::io::IStreamWriter& __dna_writer) { + if (!projection) + Log.report(logvisor::Fatal, _SYS_STR("Invalid CAMR projection object!")); + if (projection->type != projectionType) + Log.report(logvisor::Fatal, _SYS_STR("CAMR projection type does not match actual projection type!")); - /* cutoff */ - if (type == ELightType::Spot) - __dna_writer.writeFloatBig(cutoff); + __dna_writer.writeUint32Big(atUint32(projectionType)); + projection->write(__dna_writer); } template <> -void FRME::Widget::LITEInfo::Enumerate(size_t& __isz) -{ - __isz += ((type == ELightType::Spot) ? 36 : 32); +void FRME::Widget::CAMRInfo::Enumerate(size_t& __isz) { + projection->binarySize(__isz); + __isz += 4; +} + +template <> +void FRME::Widget::LITEInfo::Enumerate(athena::io::IStreamReader& __dna_reader) { + /* type */ + type = ELightType(__dna_reader.readUint32Big()); + /* distC */ + distC = __dna_reader.readFloatBig(); + /* distL */ + distL = __dna_reader.readFloatBig(); + /* distQ */ + distQ = __dna_reader.readFloatBig(); + /* angC */ + angC = __dna_reader.readFloatBig(); + /* angL */ + angL = __dna_reader.readFloatBig(); + /* angQ */ + angQ = __dna_reader.readFloatBig(); + /* loadedIdx */ + loadedIdx = __dna_reader.readUint32Big(); + + /* cutoff */ + if (type == ELightType::Spot) + cutoff = __dna_reader.readFloatBig(); +} + +template <> +void FRME::Widget::LITEInfo::Enumerate(athena::io::IStreamWriter& __dna_writer) { + /* type */ + __dna_writer.writeUint32Big(atUint32(type)); + /* distC */ + __dna_writer.writeFloatBig(distC); + /* distL */ + __dna_writer.writeFloatBig(distL); + /* distQ */ + __dna_writer.writeFloatBig(distQ); + /* angC */ + __dna_writer.writeFloatBig(angC); + /* angL */ + __dna_writer.writeFloatBig(angL); + /* angQ */ + __dna_writer.writeFloatBig(angQ); + /* loadedIdx */ + __dna_writer.writeUint32Big(loadedIdx); + + /* cutoff */ + if (type == ELightType::Spot) + __dna_writer.writeFloatBig(cutoff); +} + +template <> +void FRME::Widget::LITEInfo::Enumerate(size_t& __isz) { + __isz += ((type == ELightType::Spot) ? 36 : 32); } template -void FRME::Widget::TXPNInfo::Enumerate(typename Op::StreamT& s) -{ - Do({"xDim"}, xDim, s); - Do({"zDim"}, zDim, s); - Do({"scaleCenter"}, scaleCenter, s); - Do({"font"}, font, s); - Do({"wordWrap"}, wordWrap, s); - Do({"horizontal"}, horizontal, s); - Do({"justification"}, justification, s); - Do({"verticalJustification"}, verticalJustification, s); - Do({"fillColor"}, fillColor, s); - Do({"outlineColor"}, outlineColor, s); - Do({"blockExtent"}, blockExtent, s); - if (version == 1) - { - Do({"jpnFont"}, jpnFont, s); - Do({"jpnPointScale[0]"}, jpnPointScale[0], s); - Do({"jpnPointScale[1]"}, jpnPointScale[1], s); - } +void FRME::Widget::TXPNInfo::Enumerate(typename Op::StreamT& s) { + Do({"xDim"}, xDim, s); + Do({"zDim"}, zDim, s); + Do({"scaleCenter"}, scaleCenter, s); + Do({"font"}, font, s); + Do({"wordWrap"}, wordWrap, s); + Do({"horizontal"}, horizontal, s); + Do({"justification"}, justification, s); + Do({"verticalJustification"}, verticalJustification, s); + Do({"fillColor"}, fillColor, s); + Do({"outlineColor"}, outlineColor, s); + Do({"blockExtent"}, blockExtent, s); + if (version == 1) { + Do({"jpnFont"}, jpnFont, s); + Do({"jpnPointScale[0]"}, jpnPointScale[0], s); + Do({"jpnPointScale[1]"}, jpnPointScale[1], s); + } } AT_SPECIALIZE_DNA(FRME::Widget::TXPNInfo) -bool FRME::Extract(const SpecBase &dataSpec, - PAKEntryReadStream &rs, - const hecl::ProjectPath &outPath, - PAKRouter &pakRouter, - const PAK::Entry &entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) -{ - FRME frme; - frme.read(rs); +bool FRME::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + FRME frme; + frme.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); + hecl::blender::Connection& conn = btok.getBlenderConnection(); #if 0 if (!force && outPath.isFile()) return true; #endif - if (!conn.createBlend(outPath, hecl::blender::BlendType::Frame)) - return false; + if (!conn.createBlend(outPath, hecl::blender::BlendType::Frame)) + return false; - hecl::blender::PyOutStream os = conn.beginPythonOut(true); + hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os << "import bpy, math, bmesh\n" - "from mathutils import Matrix, Quaternion\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "\n" - "def duplicateObject(copy_obj):\n" - " # Create new mesh\n" - " mesh = bpy.data.meshes.new(copy_obj.name)\n" - " # Create new object associated with the mesh\n" - " ob_new = bpy.data.objects.new(copy_obj.name, mesh)\n" - " # Copy data block from the old object into the new object\n" - " ob_new.data = copy_obj.data\n" - " ob_new.scale = copy_obj.scale\n" - " ob_new.location = copy_obj.location\n" - " # Link new object to the given scene and select it\n" - " bpy.context.scene.objects.link(ob_new)\n" - " return ob_new\n"; + os << "import bpy, math, bmesh\n" + "from mathutils import Matrix, Quaternion\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " if ob.type != 'CAMERA':\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n" + "\n" + "def duplicateObject(copy_obj):\n" + " # Create new mesh\n" + " mesh = bpy.data.meshes.new(copy_obj.name)\n" + " # Create new object associated with the mesh\n" + " ob_new = bpy.data.objects.new(copy_obj.name, mesh)\n" + " # Copy data block from the old object into the new object\n" + " ob_new.data = copy_obj.data\n" + " ob_new.scale = copy_obj.scale\n" + " ob_new.location = copy_obj.location\n" + " # Link new object to the given scene and select it\n" + " bpy.context.scene.objects.link(ob_new)\n" + " return ob_new\n"; - os.format("bpy.context.scene.name = '%s'\n" - "bpy.context.scene.render.resolution_x = 640\n" - "bpy.context.scene.render.resolution_y = 480\n" - "bpy.context.scene.render.engine = 'CYCLES'\n" - "bpy.context.scene.world.use_nodes = True\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" - "bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n" - "bg_node.inputs[1].default_value = 0.0\n", - pakRouter.getBestEntryName(entry).c_str()); + os.format( + "bpy.context.scene.name = '%s'\n" + "bpy.context.scene.render.resolution_x = 640\n" + "bpy.context.scene.render.resolution_y = 480\n" + "bpy.context.scene.render.engine = 'CYCLES'\n" + "bpy.context.scene.world.use_nodes = True\n" + "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" + "bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n" + "bg_node.inputs[1].default_value = 0.0\n", + pakRouter.getBestEntryName(entry).c_str()); - int pIdx = 0; - for (const FRME::Widget& w : frme.widgets) - { - os << "binding = None\n" - "angle = Quaternion((1.0, 0.0, 0.0), 0)\n"; - if (w.type == SBIG('CAMR')) - { - using CAMRInfo = Widget::CAMRInfo; - os.format("cam = bpy.data.cameras.new(name='%s')\n" - "binding = cam\n", w.header.name.c_str()); - if (CAMRInfo* info = static_cast(w.widgetInfo.get())) - { - if (info->projectionType == CAMRInfo::ProjectionType::Orthographic) - { - CAMRInfo::OrthographicProjection* proj = static_cast(info->projection.get()); - os.format("cam.type = 'ORTHO'\n" - "cam.ortho_scale = %f\n" - "cam.clip_start = %f\n" - "cam.clip_end = %f\n", - std::fabs(proj->right - proj->left), - proj->znear, proj->zfar); - } - else if (info->projectionType == CAMRInfo::ProjectionType::Perspective) - { - CAMRInfo::PerspectiveProjection* proj = static_cast(info->projection.get()); - os.format("cam.type = 'PERSP'\n" - "cam.lens_unit = 'FOV'\n" - "cam.clip_start = %f\n" - "cam.clip_end = %f\n" - "bpy.context.scene.render.resolution_x = 480 * %f\n", - proj->znear, proj->zfar, proj->aspect); - if (proj->aspect > 1.f) - os.format("cam.angle = math.atan2(%f, 1.0 / math.tan(math.radians(%f / 2.0))) * 2.0\n", - proj->aspect, proj->fov); - else - os.format("cam.angle = math.radians(%f)\n", proj->fov); - } - } - os << "angle = Quaternion((1.0, 0.0, 0.0), math.radians(90.0))\n"; + int pIdx = 0; + for (const FRME::Widget& w : frme.widgets) { + os << "binding = None\n" + "angle = Quaternion((1.0, 0.0, 0.0), 0)\n"; + if (w.type == SBIG('CAMR')) { + using CAMRInfo = Widget::CAMRInfo; + os.format( + "cam = bpy.data.cameras.new(name='%s')\n" + "binding = cam\n", + w.header.name.c_str()); + if (CAMRInfo* info = static_cast(w.widgetInfo.get())) { + if (info->projectionType == CAMRInfo::ProjectionType::Orthographic) { + CAMRInfo::OrthographicProjection* proj = + static_cast(info->projection.get()); + os.format( + "cam.type = 'ORTHO'\n" + "cam.ortho_scale = %f\n" + "cam.clip_start = %f\n" + "cam.clip_end = %f\n", + std::fabs(proj->right - proj->left), proj->znear, proj->zfar); + } else if (info->projectionType == CAMRInfo::ProjectionType::Perspective) { + CAMRInfo::PerspectiveProjection* proj = static_cast(info->projection.get()); + os.format( + "cam.type = 'PERSP'\n" + "cam.lens_unit = 'FOV'\n" + "cam.clip_start = %f\n" + "cam.clip_end = %f\n" + "bpy.context.scene.render.resolution_x = 480 * %f\n", + proj->znear, proj->zfar, proj->aspect); + if (proj->aspect > 1.f) + os.format("cam.angle = math.atan2(%f, 1.0 / math.tan(math.radians(%f / 2.0))) * 2.0\n", proj->aspect, + proj->fov); + else + os.format("cam.angle = math.radians(%f)\n", proj->fov); } - else if (w.type == SBIG('LITE')) - { - using LITEInfo = Widget::LITEInfo; - if (LITEInfo* info = static_cast(w.widgetInfo.get())) - { - switch(info->type) - { - case LITEInfo::ELightType::LocalAmbient: - { - zeus::simd_floats colorF(w.header.color.simd); - os.format("bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n" - "bg_node.inputs[1].default_value = %f\n", - colorF[0], colorF[1], colorF[2], - info->distQ / 8.0); - break; - } - case LITEInfo::ELightType::Spot: - case LITEInfo::ELightType::Directional: - os << "angle = Quaternion((1.0, 0.0, 0.0), math.radians(90.0))\n"; - default: - { - zeus::simd_floats colorF(w.header.color.simd); - os.format("lamp = bpy.data.lamps.new(name='%s', type='POINT')\n" - "lamp.color = (%f, %f, %f)\n" - "lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n" - "lamp.constant_coefficient = %f\n" - "lamp.linear_coefficient = %f\n" - "lamp.quadratic_coefficient = %f\n" - "lamp.retro_light_angle_constant = %f\n" - "lamp.retro_light_angle_linear = %f\n" - "lamp.retro_light_angle_quadratic = %f\n" - "lamp.retro_light_index = %d\n" - "binding = lamp\n", - w.header.name.c_str(), - colorF[0], colorF[1], colorF[2], - info->distC, info->distL, info->distQ, - info->angC, info->angL, info->angQ, info->loadedIdx); - if (info->type == LITEInfo::ELightType::Spot) - os.format("lamp.type = 'SPOT'\n" - "lamp.spot_size = %f\n", - info->cutoff); - else if (info->type == LITEInfo::ELightType::Directional) - os << "lamp.type = 'HEMI'\n"; - } - } - } + } + os << "angle = Quaternion((1.0, 0.0, 0.0), math.radians(90.0))\n"; + } else if (w.type == SBIG('LITE')) { + using LITEInfo = Widget::LITEInfo; + if (LITEInfo* info = static_cast(w.widgetInfo.get())) { + switch (info->type) { + case LITEInfo::ELightType::LocalAmbient: { + zeus::simd_floats colorF(w.header.color.simd); + os.format( + "bg_node.inputs[0].default_value = (%f,%f,%f,1.0)\n" + "bg_node.inputs[1].default_value = %f\n", + colorF[0], colorF[1], colorF[2], info->distQ / 8.0); + break; } - else if (w.type == SBIG('IMGP')) - { - using IMGPInfo = Widget::IMGPInfo; - if (IMGPInfo* info = static_cast(w.widgetInfo.get())) - { - std::string texName; - hecl::SystemString resPath; - if (info->texture) - { - texName = pakRouter.getBestEntryName(info->texture); - const nod::Node* node; - const PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(info->texture, &node); - hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); - if (txtrPath.isNone()) - { - txtrPath.makeDirChain(false); - PAKEntryReadStream rs = texEntry->beginReadStream(*node); - TXTR::Extract(rs, txtrPath); - } - resPath = pakRouter.getResourceRelativePath(entry, info->texture); - } - - if (resPath.size()) - { - hecl::SystemUTF8Conv resPathView(resPath); - os.format("if '%s' in bpy.data.images:\n" - " image = bpy.data.images['%s']\n" - "else:\n" - " image = bpy.data.images.load('''//%s''')\n" - " image.name = '%s'\n", - texName.c_str(), texName.c_str(), - resPathView.c_str(), texName.c_str()); - } - else - { - os << "image = None\n"; - } - - os.format("material = bpy.data.materials.new('%s')\n" - "material.specular_intensity = 0.0\n" - "tex_slot = material.texture_slots.add()\n" - "tex_slot.texture = bpy.data.textures.new('%s', 'IMAGE')\n" - "tex_slot.texture.image = image\n" - "material.active_texture = tex_slot.texture\n" - "bm = bmesh.new()\n" - "verts = []\n", - w.header.name.c_str(), w.header.name.c_str()); - - for (int i=0 ; iquadCoordCount ; ++i) - { - int ti; - if (i == 2) - ti = 3; - else if (i == 3) - ti = 2; - else - ti = i; - zeus::simd_floats f(info->quadCoords[ti].simd); - os.format("verts.append(bm.verts.new((%f,%f,%f)))\n", f[0], f[1], f[2]); - } - os << "bm.faces.new(verts)\n" - "bm.loops.layers.uv.new('UV')\n" - "bm.verts.ensure_lookup_table()\n"; - for (int i=0 ; iuvCoordCount ; ++i) - { - int ti; - if (i == 2) - ti = 3; - else if (i == 3) - ti = 2; - else - ti = i; - zeus::simd_floats f(info->uvCoords[ti].simd); - os.format("bm.verts[%d].link_loops[0][bm.loops.layers.uv[0]].uv = (%f,%f)\n", i, f[0], f[1]); - } - os.format("binding = bpy.data.meshes.new('%s')\n" - "bm.to_mesh(binding)\n" - "bm.free()\n" - "binding.materials.append(material)\n", - w.header.name.c_str()); - } + case LITEInfo::ELightType::Spot: + case LITEInfo::ELightType::Directional: + os << "angle = Quaternion((1.0, 0.0, 0.0), math.radians(90.0))\n"; + default: { + zeus::simd_floats colorF(w.header.color.simd); + os.format( + "lamp = bpy.data.lamps.new(name='%s', type='POINT')\n" + "lamp.color = (%f, %f, %f)\n" + "lamp.falloff_type = 'INVERSE_COEFFICIENTS'\n" + "lamp.constant_coefficient = %f\n" + "lamp.linear_coefficient = %f\n" + "lamp.quadratic_coefficient = %f\n" + "lamp.retro_light_angle_constant = %f\n" + "lamp.retro_light_angle_linear = %f\n" + "lamp.retro_light_angle_quadratic = %f\n" + "lamp.retro_light_index = %d\n" + "binding = lamp\n", + w.header.name.c_str(), colorF[0], colorF[1], colorF[2], info->distC, info->distL, info->distQ, info->angC, + info->angL, info->angQ, info->loadedIdx); + if (info->type == LITEInfo::ELightType::Spot) + os.format( + "lamp.type = 'SPOT'\n" + "lamp.spot_size = %f\n", + info->cutoff); + else if (info->type == LITEInfo::ELightType::Directional) + os << "lamp.type = 'HEMI'\n"; + } + } + } + } else if (w.type == SBIG('IMGP')) { + using IMGPInfo = Widget::IMGPInfo; + if (IMGPInfo* info = static_cast(w.widgetInfo.get())) { + std::string texName; + hecl::SystemString resPath; + if (info->texture) { + texName = pakRouter.getBestEntryName(info->texture); + const nod::Node* node; + const PAKRouter::EntryType* texEntry = pakRouter.lookupEntry(info->texture, &node); + hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); + if (txtrPath.isNone()) { + txtrPath.makeDirChain(false); + PAKEntryReadStream rs = texEntry->beginReadStream(*node); + TXTR::Extract(rs, txtrPath); + } + resPath = pakRouter.getResourceRelativePath(entry, info->texture); } - zeus::simd_floats colorF(w.header.color.simd); - os.format("frme_obj = bpy.data.objects.new(name='%s', object_data=binding)\n" - "frme_obj.pass_index = %d\n" - "parentName = '%s'\n" - "frme_obj.retro_widget_type = 'RETRO_%.4s'\n" - "frme_obj.retro_widget_use_anim_controller = %s\n" - "frme_obj.retro_widget_default_visible = %s\n" - "frme_obj.retro_widget_default_active = %s\n" - "frme_obj.retro_widget_cull_faces = %s\n" - "frme_obj.retro_widget_color = (%f,%f,%f,%f)\n" - "frme_obj.retro_widget_model_draw_flags = bpy.types.Object.retro_widget_model_draw_flags[1]['items'][%i][0]\n" - "frme_obj.retro_widget_is_worker = %s\n" - "frme_obj.retro_widget_worker_id = %d\n" - "if parentName not in bpy.data.objects:\n" - " frme_obj.retro_widget_parent = parentName\n" - "else:\n" - " frme_obj.parent = bpy.data.objects[parentName]\n", - w.header.name.c_str(), pIdx++, w.header.parent.c_str(), - w.type.getChars(), - w.header.useAnimController ? "True" : "False", - w.header.defaultVisible ? "True" : "False", - w.header.defaultActive ? "True" : "False", - w.header.cullFaces ? "True" : "False", - colorF[0], colorF[1], colorF[2], colorF[3], - w.header.modelDrawFlags, - w.isWorker ? "True" : "False", - w.workerId); - - if (w.type == SBIG('MODL')) - { - using MODLInfo = FRME::Widget::MODLInfo; - MODLInfo* info = static_cast(w.widgetInfo.get()); - hecl::ProjectPath modelPath = pakRouter.getWorking(info->model); - const PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info->model, nullptr, true, true); - - os.linkBlend(modelPath.getAbsolutePathUTF8().data(), - pakRouter.getBestEntryName(*cmdlE).c_str(), true); - - os.format("frme_obj.retro_model_light_mask = %d\n", info->lightMask); - os << "print(obj.name)\n" - "copy_obj = duplicateObject(obj)\n" - "copy_obj.parent = frme_obj\n" - "copy_obj.hide = False\n"; - } - else if (w.type == SBIG('CAMR')) - { - os << "bpy.context.scene.camera = frme_obj\n" - "if 'Camera' in bpy.data.objects:\n" - " cam = bpy.data.objects['Camera']\n" - " bpy.context.scene.objects.unlink(cam)\n" - " bpy.data.objects.remove(cam)\n"; - } - else if (w.type == SBIG('PANE')) - { - using PANEInfo = Widget::PANEInfo; - if (PANEInfo* info = static_cast(w.widgetInfo.get())) - { - zeus::simd_floats f(info->scaleCenter.simd); - os.format("frme_obj.retro_pane_dimensions = (%f,%f)\n" - "frme_obj.retro_pane_scale_center = (%f,%f,%f)\n", - info->xDim, info->zDim, f[0], f[1], f[2]); - } - } - else if (w.type == SBIG('TXPN')) - { - using TXPNInfo = Widget::TXPNInfo; - if (TXPNInfo* info = static_cast(w.widgetInfo.get())) - { - hecl::ProjectPath fontPath = pakRouter.getWorking(info->font, true); - hecl::ProjectPath jpFontPath; - if (frme.version >= 1) - jpFontPath = pakRouter.getWorking(info->jpnFont, true); - - zeus::simd_floats scaleF(info->scaleCenter.simd); - zeus::simd_floats fillF(info->fillColor.simd); - zeus::simd_floats outlineF(info->outlineColor.simd); - zeus::simd_floats extentF(info->blockExtent.simd); - os.format("frme_obj.retro_pane_dimensions = (%f,%f)\n" - "frme_obj.retro_pane_scale_center = (%f,%f,%f)\n" - "frme_obj.retro_textpane_font_path = '%s'\n" - "frme_obj.retro_textpane_word_wrap = %s\n" - "frme_obj.retro_textpane_horizontal = %s\n" - "frme_obj.retro_textpane_fill_color = (%f,%f,%f,%f)\n" - "frme_obj.retro_textpane_outline_color = (%f,%f,%f,%f)\n" - "frme_obj.retro_textpane_block_extent = (%f,%f)\n" - "frme_obj.retro_textpane_jp_font_path = '%s'\n" - "frme_obj.retro_textpane_jp_font_scale = (%d,%d)\n" - "frme_obj.retro_textpane_hjustification = bpy.types.Object.retro_textpane_hjustification[1]['items'][%d][0]\n" - "frme_obj.retro_textpane_vjustification = bpy.types.Object.retro_textpane_vjustification[1]['items'][%d][0]\n", - info->xDim, info->zDim, - scaleF[0], scaleF[1], scaleF[2], - fontPath.getRelativePathUTF8().data(), - info->wordWrap ? "True" : "False", - info->horizontal ? "True" : "False", - fillF[0], fillF[1], fillF[2], fillF[3], - outlineF[0], outlineF[1], outlineF[2], outlineF[3], - extentF[0], extentF[1], - jpFontPath.getRelativePathUTF8().data(), - info->jpnPointScale[0], - info->jpnPointScale[1], - int(info->justification), - int(info->verticalJustification)); - } - } - else if (w.type == SBIG('TBGP')) - { - using TBGPInfo = Widget::TBGPInfo; - if (TBGPInfo* info = static_cast(w.widgetInfo.get())) - { - os.format("frme_obj.retro_tablegroup_elem_count = %d\n" - "frme_obj.retro_tablegroup_elem_default = %d\n" - "frme_obj.retro_tablegroup_wraparound = %s\n", - info->elementCount, info->defaultSelection, - info->selectWraparound ? "True" : "False"); - } - } - else if (w.type == SBIG('GRUP')) - { - using GRUPInfo = Widget::GRUPInfo; - if (GRUPInfo* info = static_cast(w.widgetInfo.get())) - { - os.format("frme_obj.retro_group_default_worker = %d\n", - info->defaultWorker); - } - } - else if (w.type == SBIG('SLGP')) - { - using SLGPInfo = Widget::SLGPInfo; - if (SLGPInfo* info = static_cast(w.widgetInfo.get())) - { - os.format("frme_obj.retro_slider_min = %f\n" - "frme_obj.retro_slider_max = %f\n" - "frme_obj.retro_slider_default = %f\n" - "frme_obj.retro_slider_increment = %f\n", - info->min, info->max, info->cur, info->increment); - } - } - else if (w.type == SBIG('ENRG')) - { - using ENRGInfo = Widget::ENRGInfo; - if (ENRGInfo* info = static_cast(w.widgetInfo.get())) - { - hecl::ProjectPath txtrPath = pakRouter.getWorking(info->texture); - if (txtrPath) - os.format("frme_obj.retro_energybar_texture_path = '%s'\n", - txtrPath.getRelativePathUTF8().data()); - } - } - else if (w.type == SBIG('METR')) - { - using METRInfo = Widget::METRInfo; - if (METRInfo* info = static_cast(w.widgetInfo.get())) - { - os.format("frme_obj.retro_meter_no_round_up = %s\n" - "frme_obj.retro_meter_max_capacity = %d\n" - "frme_obj.retro_meter_worker_count = %d\n", - info->noRoundUp ? "True" : "False", - info->maxCapacity, info->workerCount); - } + if (resPath.size()) { + hecl::SystemUTF8Conv resPathView(resPath); + os.format( + "if '%s' in bpy.data.images:\n" + " image = bpy.data.images['%s']\n" + "else:\n" + " image = bpy.data.images.load('''//%s''')\n" + " image.name = '%s'\n", + texName.c_str(), texName.c_str(), resPathView.c_str(), texName.c_str()); + } else { + os << "image = None\n"; } - zeus::simd_floats xfMtxF[3]; - for (int i = 0; i < 3; ++i) - w.basis[i].simd.copy_to(xfMtxF[i]); - zeus::simd_floats originF(w.origin.simd); - os.format("mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "frme_obj.rotation_mode = 'QUATERNION'\n" - "frme_obj.location = mtxd[0]\n" - "frme_obj.rotation_quaternion = mtxd[1] * angle\n" - "frme_obj.scale = mtxd[2]\n" - "bpy.context.scene.objects.link(frme_obj)\n", - xfMtxF[0][0], xfMtxF[0][1], xfMtxF[0][2], originF[0], - xfMtxF[1][0], xfMtxF[1][1], xfMtxF[1][2], originF[1], - xfMtxF[2][0], xfMtxF[2][1], xfMtxF[2][2], originF[2]); + os.format( + "material = bpy.data.materials.new('%s')\n" + "material.specular_intensity = 0.0\n" + "tex_slot = material.texture_slots.add()\n" + "tex_slot.texture = bpy.data.textures.new('%s', 'IMAGE')\n" + "tex_slot.texture.image = image\n" + "material.active_texture = tex_slot.texture\n" + "bm = bmesh.new()\n" + "verts = []\n", + w.header.name.c_str(), w.header.name.c_str()); + + for (int i = 0; i < info->quadCoordCount; ++i) { + int ti; + if (i == 2) + ti = 3; + else if (i == 3) + ti = 2; + else + ti = i; + zeus::simd_floats f(info->quadCoords[ti].simd); + os.format("verts.append(bm.verts.new((%f,%f,%f)))\n", f[0], f[1], f[2]); + } + os << "bm.faces.new(verts)\n" + "bm.loops.layers.uv.new('UV')\n" + "bm.verts.ensure_lookup_table()\n"; + for (int i = 0; i < info->uvCoordCount; ++i) { + int ti; + if (i == 2) + ti = 3; + else if (i == 3) + ti = 2; + else + ti = i; + zeus::simd_floats f(info->uvCoords[ti].simd); + os.format("bm.verts[%d].link_loops[0][bm.loops.layers.uv[0]].uv = (%f,%f)\n", i, f[0], f[1]); + } + os.format( + "binding = bpy.data.meshes.new('%s')\n" + "bm.to_mesh(binding)\n" + "bm.free()\n" + "binding.materials.append(material)\n", + w.header.name.c_str()); + } } - os.centerView(); - os.close(); - conn.saveBlend(); - return true; + zeus::simd_floats colorF(w.header.color.simd); + os.format( + "frme_obj = bpy.data.objects.new(name='%s', object_data=binding)\n" + "frme_obj.pass_index = %d\n" + "parentName = '%s'\n" + "frme_obj.retro_widget_type = 'RETRO_%.4s'\n" + "frme_obj.retro_widget_use_anim_controller = %s\n" + "frme_obj.retro_widget_default_visible = %s\n" + "frme_obj.retro_widget_default_active = %s\n" + "frme_obj.retro_widget_cull_faces = %s\n" + "frme_obj.retro_widget_color = (%f,%f,%f,%f)\n" + "frme_obj.retro_widget_model_draw_flags = bpy.types.Object.retro_widget_model_draw_flags[1]['items'][%i][0]\n" + "frme_obj.retro_widget_is_worker = %s\n" + "frme_obj.retro_widget_worker_id = %d\n" + "if parentName not in bpy.data.objects:\n" + " frme_obj.retro_widget_parent = parentName\n" + "else:\n" + " frme_obj.parent = bpy.data.objects[parentName]\n", + w.header.name.c_str(), pIdx++, w.header.parent.c_str(), w.type.getChars(), + w.header.useAnimController ? "True" : "False", w.header.defaultVisible ? "True" : "False", + w.header.defaultActive ? "True" : "False", w.header.cullFaces ? "True" : "False", colorF[0], colorF[1], + colorF[2], colorF[3], w.header.modelDrawFlags, w.isWorker ? "True" : "False", w.workerId); + + if (w.type == SBIG('MODL')) { + using MODLInfo = FRME::Widget::MODLInfo; + MODLInfo* info = static_cast(w.widgetInfo.get()); + hecl::ProjectPath modelPath = pakRouter.getWorking(info->model); + const PAKRouter::EntryType* cmdlE = pakRouter.lookupEntry(info->model, nullptr, true, true); + + os.linkBlend(modelPath.getAbsolutePathUTF8().data(), pakRouter.getBestEntryName(*cmdlE).c_str(), true); + + os.format("frme_obj.retro_model_light_mask = %d\n", info->lightMask); + os << "print(obj.name)\n" + "copy_obj = duplicateObject(obj)\n" + "copy_obj.parent = frme_obj\n" + "copy_obj.hide = False\n"; + } else if (w.type == SBIG('CAMR')) { + os << "bpy.context.scene.camera = frme_obj\n" + "if 'Camera' in bpy.data.objects:\n" + " cam = bpy.data.objects['Camera']\n" + " bpy.context.scene.objects.unlink(cam)\n" + " bpy.data.objects.remove(cam)\n"; + } else if (w.type == SBIG('PANE')) { + using PANEInfo = Widget::PANEInfo; + if (PANEInfo* info = static_cast(w.widgetInfo.get())) { + zeus::simd_floats f(info->scaleCenter.simd); + os.format( + "frme_obj.retro_pane_dimensions = (%f,%f)\n" + "frme_obj.retro_pane_scale_center = (%f,%f,%f)\n", + info->xDim, info->zDim, f[0], f[1], f[2]); + } + } else if (w.type == SBIG('TXPN')) { + using TXPNInfo = Widget::TXPNInfo; + if (TXPNInfo* info = static_cast(w.widgetInfo.get())) { + hecl::ProjectPath fontPath = pakRouter.getWorking(info->font, true); + hecl::ProjectPath jpFontPath; + if (frme.version >= 1) + jpFontPath = pakRouter.getWorking(info->jpnFont, true); + + zeus::simd_floats scaleF(info->scaleCenter.simd); + zeus::simd_floats fillF(info->fillColor.simd); + zeus::simd_floats outlineF(info->outlineColor.simd); + zeus::simd_floats extentF(info->blockExtent.simd); + os.format( + "frme_obj.retro_pane_dimensions = (%f,%f)\n" + "frme_obj.retro_pane_scale_center = (%f,%f,%f)\n" + "frme_obj.retro_textpane_font_path = '%s'\n" + "frme_obj.retro_textpane_word_wrap = %s\n" + "frme_obj.retro_textpane_horizontal = %s\n" + "frme_obj.retro_textpane_fill_color = (%f,%f,%f,%f)\n" + "frme_obj.retro_textpane_outline_color = (%f,%f,%f,%f)\n" + "frme_obj.retro_textpane_block_extent = (%f,%f)\n" + "frme_obj.retro_textpane_jp_font_path = '%s'\n" + "frme_obj.retro_textpane_jp_font_scale = (%d,%d)\n" + "frme_obj.retro_textpane_hjustification = " + "bpy.types.Object.retro_textpane_hjustification[1]['items'][%d][0]\n" + "frme_obj.retro_textpane_vjustification = " + "bpy.types.Object.retro_textpane_vjustification[1]['items'][%d][0]\n", + info->xDim, info->zDim, scaleF[0], scaleF[1], scaleF[2], fontPath.getRelativePathUTF8().data(), + info->wordWrap ? "True" : "False", info->horizontal ? "True" : "False", fillF[0], fillF[1], fillF[2], + fillF[3], outlineF[0], outlineF[1], outlineF[2], outlineF[3], extentF[0], extentF[1], + jpFontPath.getRelativePathUTF8().data(), info->jpnPointScale[0], info->jpnPointScale[1], + int(info->justification), int(info->verticalJustification)); + } + } else if (w.type == SBIG('TBGP')) { + using TBGPInfo = Widget::TBGPInfo; + if (TBGPInfo* info = static_cast(w.widgetInfo.get())) { + os.format( + "frme_obj.retro_tablegroup_elem_count = %d\n" + "frme_obj.retro_tablegroup_elem_default = %d\n" + "frme_obj.retro_tablegroup_wraparound = %s\n", + info->elementCount, info->defaultSelection, info->selectWraparound ? "True" : "False"); + } + } else if (w.type == SBIG('GRUP')) { + using GRUPInfo = Widget::GRUPInfo; + if (GRUPInfo* info = static_cast(w.widgetInfo.get())) { + os.format("frme_obj.retro_group_default_worker = %d\n", info->defaultWorker); + } + } else if (w.type == SBIG('SLGP')) { + using SLGPInfo = Widget::SLGPInfo; + if (SLGPInfo* info = static_cast(w.widgetInfo.get())) { + os.format( + "frme_obj.retro_slider_min = %f\n" + "frme_obj.retro_slider_max = %f\n" + "frme_obj.retro_slider_default = %f\n" + "frme_obj.retro_slider_increment = %f\n", + info->min, info->max, info->cur, info->increment); + } + } else if (w.type == SBIG('ENRG')) { + using ENRGInfo = Widget::ENRGInfo; + if (ENRGInfo* info = static_cast(w.widgetInfo.get())) { + hecl::ProjectPath txtrPath = pakRouter.getWorking(info->texture); + if (txtrPath) + os.format("frme_obj.retro_energybar_texture_path = '%s'\n", txtrPath.getRelativePathUTF8().data()); + } + } else if (w.type == SBIG('METR')) { + using METRInfo = Widget::METRInfo; + if (METRInfo* info = static_cast(w.widgetInfo.get())) { + os.format( + "frme_obj.retro_meter_no_round_up = %s\n" + "frme_obj.retro_meter_max_capacity = %d\n" + "frme_obj.retro_meter_worker_count = %d\n", + info->noRoundUp ? "True" : "False", info->maxCapacity, info->workerCount); + } + } + + zeus::simd_floats xfMtxF[3]; + for (int i = 0; i < 3; ++i) + w.basis[i].simd.copy_to(xfMtxF[i]); + zeus::simd_floats originF(w.origin.simd); + os.format( + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "frme_obj.rotation_mode = 'QUATERNION'\n" + "frme_obj.location = mtxd[0]\n" + "frme_obj.rotation_quaternion = mtxd[1] * angle\n" + "frme_obj.scale = mtxd[2]\n" + "bpy.context.scene.objects.link(frme_obj)\n", + xfMtxF[0][0], xfMtxF[0][1], xfMtxF[0][2], originF[0], xfMtxF[1][0], xfMtxF[1][1], xfMtxF[1][2], originF[1], + xfMtxF[2][0], xfMtxF[2][1], xfMtxF[2][2], originF[2]); + } + + os.centerView(); + os.close(); + conn.saveBlend(); + return true; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/FRME.hpp b/DataSpec/DNAMP1/FRME.hpp index 671237a80..849509742 100644 --- a/DataSpec/DNAMP1/FRME.hpp +++ b/DataSpec/DNAMP1/FRME.hpp @@ -5,314 +5,272 @@ #include #include "athena/DNAOp.hpp" -namespace DataSpec::DNAMP1 -{ -struct FRME : BigDNA -{ +namespace DataSpec::DNAMP1 { +struct FRME : BigDNA { + AT_DECL_EXPLICIT_DNA + Value version; + Value unk1; + Value modelCount; // Matches MODL widgets + Value unk3; + Value widgetCount; + + struct Widget : BigDNA { AT_DECL_EXPLICIT_DNA - Value version; - Value unk1; - Value modelCount; // Matches MODL widgets - Value unk3; - Value widgetCount; + FRME* owner; + DNAFourCC type; + struct WidgetHeader : BigDNA { + AT_DECL_DNA + String<-1> name; + String<-1> parent; + Value useAnimController; + Value defaultVisible; + Value defaultActive; + Value cullFaces; + Value color; + Value modelDrawFlags; + } header; - struct Widget : BigDNA - { - AT_DECL_EXPLICIT_DNA - FRME* owner; - DNAFourCC type; - struct WidgetHeader : BigDNA - { - AT_DECL_DNA - String<-1> name; - String<-1> parent; - Value useAnimController; - Value defaultVisible; - Value defaultActive; - Value cullFaces; - Value color; - Value modelDrawFlags; - } header; - - struct IWidgetInfo : BigDNAV - { - Delete _dBase; - virtual FourCC fourcc() const=0; - }; - - std::unique_ptr widgetInfo; - Value isWorker; - Value workerId = 0; - Value origin; - Value basis[3]; - Value rotationCenter; - Value unk1; - Value unk2; - - struct BWIGInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::BWIG"; } - FourCC fourcc() const { return FOURCC('BWIG'); } - }; - - struct HWIGInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::HWIG"; } - FourCC fourcc() const { return FOURCC('HWIG'); } - }; - - struct CAMRInfo : IWidgetInfo - { - AT_DECL_EXPLICIT_DNA - const char* DNATypeV() const { return "FRME::CAMR"; } - enum class ProjectionType - { - Perspective, - Orthographic - }; - - Value projectionType; - struct IProjection : BigDNAV - { - Delete _d; - const ProjectionType type; - IProjection(ProjectionType t) : type(t) {} - }; - - struct PerspectiveProjection : IProjection - { - AT_DECL_DNA - AT_DECL_DNAV - PerspectiveProjection() : IProjection(ProjectionType::Perspective) {} - Value fov; - Value aspect; - Value znear; - Value zfar; - }; - - struct OrthographicProjection : IProjection - { - AT_DECL_DNA - AT_DECL_DNAV - OrthographicProjection() : IProjection(ProjectionType::Orthographic) {} - Value left; - Value right; - Value top; - Value bottom; - Value znear; - Value zfar; - }; - std::unique_ptr projection; - - FourCC fourcc() const { return FOURCC('CAMR'); } - }; - - struct MODLInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::MODL"; } - UniqueID32 model; - enum class BlendMode - { - Unknown0, - Unknown1, - Unknown2, - Additive - }; - - Value blendMode; - Value lightMask; - - FourCC fourcc() const { return FOURCC('MODL'); } - }; - - struct LITEInfo : IWidgetInfo - { - AT_DECL_EXPLICIT_DNA - const char* DNATypeV() const { return "FRME::LITE"; } - enum class ELightType : atUint32 - { - Spot = 0, - Point = 1, - Directional = 2, - LocalAmbient = 3, - Custom = 4, - }; - - Value type; - Value distC; - Value distL; - Value distQ; - Value angC; - Value angL; - Value angQ; - Value loadedIdx; - Value cutoff; /* Spot only */ - - FourCC fourcc() const { return FOURCC('LITE'); } - }; - - struct ENRGInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::ENRG"; } - UniqueID32 texture; - - FourCC fourcc() const { return FOURCC('ENRG'); } - }; - - struct METRInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::METR"; } - Value unk1; - Value noRoundUp; - Value maxCapacity; - Value workerCount; - - FourCC fourcc() const { return FOURCC('METR'); } - }; - - struct GRUPInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::GRUP"; } - Value defaultWorker; - Value unk3; - - FourCC fourcc() const { return FOURCC('GRUP'); } - }; - - struct TBGPInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::TBGP"; } - Value elementCount; - Value unk2; - Value unkEnum; - Value defaultSelection; - Value un4; - Value selectWraparound; - Value unk6; - Value unkFloat1; - Value unkFloat2; - Value unk7; - Value unkFloat3; - Value unk8; - Value unk9; - Value unk10; - Value unk11; - - FourCC fourcc() const { return FOURCC('TBGP'); } - }; - - struct SLGPInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::SLGP"; } - Value min; - Value max; - Value cur; - Value increment; - - FourCC fourcc() const { return FOURCC('SLGP'); } - }; - - struct PANEInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::PANE"; } - Value xDim; - Value zDim; - Value scaleCenter; - - FourCC fourcc() const { return FOURCC('PANE'); } - }; - - struct TXPNInfo : IWidgetInfo - { - const char* DNATypeV() const { return "FRME::TXPN"; } - enum class Justification : atUint32 - { - Left = 0, - Center, - Right, - Full, - NLeft, - NCenter, - NRight, - LeftMono, - CenterMono, - RightMono - }; - - enum class VerticalJustification : atUint32 - { - Top = 0, - Center, - Bottom, - Full, - NTop, - NCenter, - NBottom, - LeftMono, - CenterMono, - RightMono - }; - - AT_DECL_EXPLICIT_DNA - - atUint32 version = 0; - TXPNInfo() {} - TXPNInfo(atUint32 version) - : version(version) - {} - Value xDim; - Value zDim; - Value scaleCenter; - UniqueID32 font; - Value wordWrap; - Value horizontal; - Value justification; - Value verticalJustification; - Value fillColor; - Value outlineColor; - Value blockExtent; /* In points; converted to int by loader */ - /* The following is only found in V1 */ - UniqueID32 jpnFont; - Value jpnPointScale[2] = {}; - - FourCC fourcc() const { return FOURCC('TXPN'); } - }; - - struct IMGPInfo : IWidgetInfo - { - AT_DECL_DNA - const char* DNATypeV() const { return "FRME::IMGP"; } - UniqueID32 texture; - Value unk1; - Value unk2; - Value quadCoordCount; - Vector quadCoords; - Value uvCoordCount; - Vector uvCoords; - - FourCC fourcc() const { return FOURCC('IMGP'); } - }; + struct IWidgetInfo : BigDNAV { + Delete _dBase; + virtual FourCC fourcc() const = 0; }; - Vector widgets; - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged); + std::unique_ptr widgetInfo; + Value isWorker; + Value workerId = 0; + Value origin; + Value basis[3]; + Value rotationCenter; + Value unk1; + Value unk2; + + struct BWIGInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::BWIG"; } + FourCC fourcc() const { return FOURCC('BWIG'); } + }; + + struct HWIGInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::HWIG"; } + FourCC fourcc() const { return FOURCC('HWIG'); } + }; + + struct CAMRInfo : IWidgetInfo { + AT_DECL_EXPLICIT_DNA + const char* DNATypeV() const { return "FRME::CAMR"; } + enum class ProjectionType { Perspective, Orthographic }; + + Value projectionType; + struct IProjection : BigDNAV { + Delete _d; + const ProjectionType type; + IProjection(ProjectionType t) : type(t) {} + }; + + struct PerspectiveProjection : IProjection { + AT_DECL_DNA + AT_DECL_DNAV + PerspectiveProjection() : IProjection(ProjectionType::Perspective) {} + Value fov; + Value aspect; + Value znear; + Value zfar; + }; + + struct OrthographicProjection : IProjection { + AT_DECL_DNA + AT_DECL_DNAV + OrthographicProjection() : IProjection(ProjectionType::Orthographic) {} + Value left; + Value right; + Value top; + Value bottom; + Value znear; + Value zfar; + }; + std::unique_ptr projection; + + FourCC fourcc() const { return FOURCC('CAMR'); } + }; + + struct MODLInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::MODL"; } + UniqueID32 model; + enum class BlendMode { Unknown0, Unknown1, Unknown2, Additive }; + + Value blendMode; + Value lightMask; + + FourCC fourcc() const { return FOURCC('MODL'); } + }; + + struct LITEInfo : IWidgetInfo { + AT_DECL_EXPLICIT_DNA + const char* DNATypeV() const { return "FRME::LITE"; } + enum class ELightType : atUint32 { + Spot = 0, + Point = 1, + Directional = 2, + LocalAmbient = 3, + Custom = 4, + }; + + Value type; + Value distC; + Value distL; + Value distQ; + Value angC; + Value angL; + Value angQ; + Value loadedIdx; + Value cutoff; /* Spot only */ + + FourCC fourcc() const { return FOURCC('LITE'); } + }; + + struct ENRGInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::ENRG"; } + UniqueID32 texture; + + FourCC fourcc() const { return FOURCC('ENRG'); } + }; + + struct METRInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::METR"; } + Value unk1; + Value noRoundUp; + Value maxCapacity; + Value workerCount; + + FourCC fourcc() const { return FOURCC('METR'); } + }; + + struct GRUPInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::GRUP"; } + Value defaultWorker; + Value unk3; + + FourCC fourcc() const { return FOURCC('GRUP'); } + }; + + struct TBGPInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::TBGP"; } + Value elementCount; + Value unk2; + Value unkEnum; + Value defaultSelection; + Value un4; + Value selectWraparound; + Value unk6; + Value unkFloat1; + Value unkFloat2; + Value unk7; + Value unkFloat3; + Value unk8; + Value unk9; + Value unk10; + Value unk11; + + FourCC fourcc() const { return FOURCC('TBGP'); } + }; + + struct SLGPInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::SLGP"; } + Value min; + Value max; + Value cur; + Value increment; + + FourCC fourcc() const { return FOURCC('SLGP'); } + }; + + struct PANEInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::PANE"; } + Value xDim; + Value zDim; + Value scaleCenter; + + FourCC fourcc() const { return FOURCC('PANE'); } + }; + + struct TXPNInfo : IWidgetInfo { + const char* DNATypeV() const { return "FRME::TXPN"; } + enum class Justification : atUint32 { + Left = 0, + Center, + Right, + Full, + NLeft, + NCenter, + NRight, + LeftMono, + CenterMono, + RightMono + }; + + enum class VerticalJustification : atUint32 { + Top = 0, + Center, + Bottom, + Full, + NTop, + NCenter, + NBottom, + LeftMono, + CenterMono, + RightMono + }; + + AT_DECL_EXPLICIT_DNA + + atUint32 version = 0; + TXPNInfo() {} + TXPNInfo(atUint32 version) : version(version) {} + Value xDim; + Value zDim; + Value scaleCenter; + UniqueID32 font; + Value wordWrap; + Value horizontal; + Value justification; + Value verticalJustification; + Value fillColor; + Value outlineColor; + Value blockExtent; /* In points; converted to int by loader */ + /* The following is only found in V1 */ + UniqueID32 jpnFont; + Value jpnPointScale[2] = {}; + + FourCC fourcc() const { return FOURCC('TXPN'); } + }; + + struct IMGPInfo : IWidgetInfo { + AT_DECL_DNA + const char* DNATypeV() const { return "FRME::IMGP"; } + UniqueID32 texture; + Value unk1; + Value unk2; + Value quadCoordCount; + Vector quadCoords; + Value uvCoordCount; + Vector uvCoords; + + FourCC fourcc() const { return FOURCC('IMGP'); } + }; + }; + + Vector widgets; + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/HINT.hpp b/DataSpec/DNAMP1/HINT.hpp index b8af0cffa..f035bd68c 100644 --- a/DataSpec/DNAMP1/HINT.hpp +++ b/DataSpec/DNAMP1/HINT.hpp @@ -3,55 +3,48 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DataSpec/DNACommon/PAK.hpp" -namespace DataSpec::DNAMP1 -{ -struct HINT : BigDNA -{ +namespace DataSpec::DNAMP1 { +struct HINT : BigDNA { + AT_DECL_DNA_YAML + Value magic; + Value version; + + struct Hint : BigDNA { AT_DECL_DNA_YAML - Value magic; - Value version; - - struct Hint : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value immediateTime; - Value normalTime; - UniqueID32 stringID; - Value textPageCount; - struct Location : BigDNA - { - AT_DECL_DNA_YAML - UniqueID32 worldAssetID; - UniqueID32 areaAssetID; - Value areaID; - UniqueID32 stringID; - }; - - Value locationCount; - Vector locations; + String<-1> name; + Value immediateTime; + Value normalTime; + UniqueID32 stringID; + Value textPageCount; + struct Location : BigDNA { + AT_DECL_DNA_YAML + UniqueID32 worldAssetID; + UniqueID32 areaAssetID; + Value areaID; + UniqueID32 stringID; }; - Value hintCount; - Vector hints; + Value locationCount; + Vector locations; + }; + Value hintCount; + Vector hints; - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) - { - HINT hint; - hint.read(rs); - athena::io::FileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(hint, writer); - return true; - } + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + HINT hint; + hint.read(rs); + athena::io::FileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(hint, writer); + return true; + } - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) - { - HINT hint; - athena::io::FileReader reader(inPath.getAbsolutePath()); - athena::io::FromYAMLStream(hint, reader); - athena::io::FileWriter ws(outPath.getAbsolutePath()); - hint.write(ws); - return true; - } + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + HINT hint; + athena::io::FileReader reader(inPath.getAbsolutePath()); + athena::io::FromYAMLStream(hint, reader); + athena::io::FileWriter ws(outPath.getAbsolutePath()); + hint.write(ws); + return true; + } }; -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/MAPA.hpp b/DataSpec/DNAMP1/MAPA.hpp index 96cd2c7f0..c8d6674c6 100644 --- a/DataSpec/DNAMP1/MAPA.hpp +++ b/DataSpec/DNAMP1/MAPA.hpp @@ -6,34 +6,24 @@ #include "DataSpec/DNACommon/MAPA.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct MAPA : DNAMAPA::MAPA -{ - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) - { - MAPA mapa; - mapa.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - return DNAMAPA::ReadMAPAToBlender(conn, mapa, outPath, pakRouter, entry, force); - } +struct MAPA : DNAMAPA::MAPA { + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + MAPA mapa; + mapa.read(rs); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + return DNAMAPA::ReadMAPAToBlender(conn, mapa, outPath, pakRouter, entry, force); + } - static bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out) - { - return DNAMAPA::Cook(mapa, out); - } + static bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out) { + return DNAMAPA::Cook(mapa, out); + } - static uint32_t Version() { return 2; } - using Header = DNAMAPA::MAPA::HeaderMP1; - using MappableObject = DNAMAPA::MAPA::MappableObjectMP1_2; + static uint32_t Version() { return 2; } + using Header = DNAMAPA::MAPA::HeaderMP1; + using MappableObject = DNAMAPA::MAPA::MappableObjectMP1_2; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/MAPU.hpp b/DataSpec/DNAMP1/MAPU.hpp index c7997b6c0..bbd42b696 100644 --- a/DataSpec/DNAMP1/MAPU.hpp +++ b/DataSpec/DNAMP1/MAPU.hpp @@ -6,25 +6,16 @@ #include "DataSpec/DNACommon/MAPU.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct MAPU : DNAMAPU::MAPU -{ - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) - { - MAPU mapu; - mapu.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - return DNAMAPU::ReadMAPUToBlender(conn, mapu, outPath, pakRouter, entry, force); - } +struct MAPU : DNAMAPU::MAPU { + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + MAPU mapu; + mapu.read(rs); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + return DNAMAPU::ReadMAPUToBlender(conn, mapu, outPath, pakRouter, entry, force); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/MLVL.cpp b/DataSpec/DNAMP1/MLVL.cpp index 2f749cd3a..3edd546c4 100644 --- a/DataSpec/DNAMP1/MLVL.cpp +++ b/DataSpec/DNAMP1/MLVL.cpp @@ -9,569 +9,516 @@ #include "Runtime/World/ScriptObjectSupport.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { bool MLVL::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, - std::function fileChanged) -{ - MLVL mlvl; - mlvl.read(rs); - const nod::Node* node; - const typename PAKRouter::EntryType* savwEntry = pakRouter.lookupEntry(mlvl.saveWorldId, &node); - SAVW savw; + std::function fileChanged) { + MLVL mlvl; + mlvl.read(rs); + const nod::Node* node; + const typename PAKRouter::EntryType* savwEntry = pakRouter.lookupEntry(mlvl.saveWorldId, &node); + SAVW savw; + { + PAKEntryReadStream rs = savwEntry->beginReadStream(*node); + savw.read(rs); + } + + atUint32 areaIdx = 0; + for (const MLVL::Area& area : mlvl.areas) { + hecl::ProjectPath areaDir = pakRouter.getWorking(area.areaMREAId).getParentPath(); { - PAKEntryReadStream rs = savwEntry->beginReadStream(*node); - savw.read(rs); + athena::io::FileWriter fw(hecl::ProjectPath(areaDir, _SYS_STR("!memoryid.yaml")).getAbsolutePath()); + athena::io::YAMLDocWriter w(nullptr); + w.writeUint32("memoryid", area.areaId); + w.finish(&fw); } - - atUint32 areaIdx = 0; - for (const MLVL::Area& area : mlvl.areas) { - hecl::ProjectPath areaDir = pakRouter.getWorking(area.areaMREAId).getParentPath(); - { - athena::io::FileWriter fw(hecl::ProjectPath(areaDir, _SYS_STR("!memoryid.yaml")).getAbsolutePath()); - athena::io::YAMLDocWriter w(nullptr); - w.writeUint32("memoryid", area.areaId); - w.finish(&fw); - } - { - athena::io::FileWriter fw(hecl::ProjectPath(areaDir, _SYS_STR("!memoryrelays.yaml")).getAbsolutePath()); - athena::io::YAMLDocWriter w(nullptr); + athena::io::FileWriter fw(hecl::ProjectPath(areaDir, _SYS_STR("!memoryrelays.yaml")).getAbsolutePath()); + athena::io::YAMLDocWriter w(nullptr); - std::vector relayIds; - for (const atUint32& relay : savw.relays) - { - atUint16 aIdx = ((relay >> 16) & 0x3ff); - if (aIdx == areaIdx && std::find(relayIds.begin(), relayIds.end(), relay) == relayIds.end()) - relayIds.push_back(relay); - } + std::vector relayIds; + for (const atUint32& relay : savw.relays) { + atUint16 aIdx = ((relay >> 16) & 0x3ff); + if (aIdx == areaIdx && std::find(relayIds.begin(), relayIds.end(), relay) == relayIds.end()) + relayIds.push_back(relay); + } - w.enumerate("memrelays", relayIds); - w.finish(&fw); - } - if (pakRouter.mreaHasDupeResources(area.areaMREAId)) - athena::io::FileWriter(hecl::ProjectPath(areaDir, _SYS_STR("!duperes")).getAbsolutePath()); - - areaIdx++; + w.enumerate("memrelays", relayIds); + w.finish(&fw); } + if (pakRouter.mreaHasDupeResources(area.areaMREAId)) + athena::io::FileWriter(hecl::ProjectPath(areaDir, _SYS_STR("!duperes")).getAbsolutePath()); - athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".yaml"), true).getAbsolutePath()); - athena::io::ToYAMLStream(mlvl, writer, &MLVL::writeMeta); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter, entry, force, fileChanged); + areaIdx++; + } + + athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".yaml"), true).getAbsolutePath()); + athena::io::ToYAMLStream(mlvl, writer, &MLVL::writeMeta); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter, entry, force, fileChanged); } -struct LayerResources -{ - std::unordered_set addedPaths; - std::vector>> layerPaths; - std::unordered_set addedSharedPaths; - std::vector> sharedPaths; - void beginLayer() - { - layerPaths.resize(layerPaths.size() + 1); - addedPaths.clear(); +struct LayerResources { + std::unordered_set addedPaths; + std::vector>> layerPaths; + std::unordered_set addedSharedPaths; + std::vector> sharedPaths; + void beginLayer() { + layerPaths.resize(layerPaths.size() + 1); + addedPaths.clear(); + } + void addSharedPath(const hecl::ProjectPath& path, bool lazy) { + auto search = addedSharedPaths.find(path.hash()); + if (search == addedSharedPaths.cend()) { + sharedPaths.emplace_back(path, lazy); + addedSharedPaths.insert(path.hash()); } - void addSharedPath(const hecl::ProjectPath& path, bool lazy) - { - auto search = addedSharedPaths.find(path.hash()); - if (search == addedSharedPaths.cend()) - { - sharedPaths.emplace_back(path, lazy); - addedSharedPaths.insert(path.hash()); - } - } - void addPath(const hecl::ProjectPath& path, bool lazy) - { - auto search = addedPaths.find(path.hash()); - if (search == addedPaths.cend()) - { - layerPaths.back().emplace_back(path, lazy); - addedPaths.insert(path.hash()); - } + } + void addPath(const hecl::ProjectPath& path, bool lazy) { + auto search = addedPaths.find(path.hash()); + if (search == addedPaths.cend()) { + layerPaths.back().emplace_back(path, lazy); + addedPaths.insert(path.hash()); } + } }; bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const World& wld, - hecl::blender::Token& btok) -{ - MLVL mlvl = {}; - athena::io::FileReader reader(inPath.getWithExtension(_SYS_STR(".yaml"), true).getAbsolutePath()); - athena::io::FromYAMLStream(mlvl, reader, &MLVL::readMeta); + hecl::blender::Token& btok) { + MLVL mlvl = {}; + athena::io::FileReader reader(inPath.getWithExtension(_SYS_STR(".yaml"), true).getAbsolutePath()); + athena::io::FromYAMLStream(mlvl, reader, &MLVL::readMeta); - mlvl.magic = 0xDEAFBABE; - mlvl.version = 0x11; - hecl::ProjectPath namePath(inPath.getParentPath(), _SYS_STR("!name.yaml")); - if (namePath.isFile()) - mlvl.worldNameId = namePath; - hecl::ProjectPath globPath = inPath.getWithExtension(_SYS_STR(".*"), true); - hecl::ProjectPath savwPath = globPath.ensureAuxInfo(_SYS_STR("SAVW")); - mlvl.saveWorldId = savwPath; - hecl::ProjectPath mapwPath = globPath.ensureAuxInfo(_SYS_STR("MAPW")); - mlvl.worldMap = mapwPath; + mlvl.magic = 0xDEAFBABE; + mlvl.version = 0x11; + hecl::ProjectPath namePath(inPath.getParentPath(), _SYS_STR("!name.yaml")); + if (namePath.isFile()) + mlvl.worldNameId = namePath; + hecl::ProjectPath globPath = inPath.getWithExtension(_SYS_STR(".*"), true); + hecl::ProjectPath savwPath = globPath.ensureAuxInfo(_SYS_STR("SAVW")); + mlvl.saveWorldId = savwPath; + hecl::ProjectPath mapwPath = globPath.ensureAuxInfo(_SYS_STR("MAPW")); + mlvl.worldMap = mapwPath; - size_t areaIdx = 0; - size_t nameOffset = 0; - for (const World::Area& area : wld.areas) - { - if (area.path.getPathType() != hecl::ProjectPath::Type::Directory) - continue; + size_t areaIdx = 0; + size_t nameOffset = 0; + for (const World::Area& area : wld.areas) { + if (area.path.getPathType() != hecl::ProjectPath::Type::Directory) + continue; - hecl::ProjectPath areaPath(area.path, _SYS_STR("!area.blend")); - if (!areaPath.isFile()) - continue; + hecl::ProjectPath areaPath(area.path, _SYS_STR("!area.blend")); + if (!areaPath.isFile()) + continue; - Log.report(logvisor::Info, _SYS_STR("Visiting %s"), area.path.getRelativePath().data()); + Log.report(logvisor::Info, _SYS_STR("Visiting %s"), area.path.getRelativePath().data()); - hecl::ProjectPath memRelayPath(area.path, _SYS_STR("!memoryrelays.yaml")); + hecl::ProjectPath memRelayPath(area.path, _SYS_STR("!memoryrelays.yaml")); - std::vector memRelays; + std::vector memRelays; - if (memRelayPath.isFile()) - { - athena::io::FileReader fr(memRelayPath.getAbsolutePath()); - athena::io::YAMLDocReader r; - if (r.parse(&fr)) - r.enumerate("memrelays", memRelays); - } + if (memRelayPath.isFile()) { + athena::io::FileReader fr(memRelayPath.getAbsolutePath()); + athena::io::YAMLDocReader r; + if (r.parse(&fr)) + r.enumerate("memrelays", memRelays); + } - /* Bare minimum we'll need exactly the same number of links as relays */ - std::vector memRelayLinks(memRelays.size()); + /* Bare minimum we'll need exactly the same number of links as relays */ + std::vector memRelayLinks(memRelays.size()); - hecl::DirectoryEnumerator dEnum(area.path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsSorted); - bool areaInit = false; + hecl::DirectoryEnumerator dEnum(area.path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsSorted); + bool areaInit = false; - size_t layerIdx = 0; - LayerResources layerResources; - for (const hecl::DirectoryEnumerator::Entry& e : dEnum) - { - hecl::SystemString layerName; - hecl::SystemChar* endCh = nullptr; - hecl::StrToUl(e.m_name.c_str(), &endCh, 0); - if (!endCh) - layerName = hecl::StringUtils::TrimWhitespace(e.m_name); - else - layerName = hecl::StringUtils::TrimWhitespace(hecl::SystemString(endCh)); + size_t layerIdx = 0; + LayerResources layerResources; + for (const hecl::DirectoryEnumerator::Entry& e : dEnum) { + hecl::SystemString layerName; + hecl::SystemChar* endCh = nullptr; + hecl::StrToUl(e.m_name.c_str(), &endCh, 0); + if (!endCh) + layerName = hecl::StringUtils::TrimWhitespace(e.m_name); + else + layerName = hecl::StringUtils::TrimWhitespace(hecl::SystemString(endCh)); - hecl::ProjectPath objectsPath(area.path, e.m_name + _SYS_STR("/!objects.yaml")); - if (objectsPath.isNone()) - continue; + hecl::ProjectPath objectsPath(area.path, e.m_name + _SYS_STR("/!objects.yaml")); + if (objectsPath.isNone()) + continue; - SCLY::ScriptLayer layer; - { - athena::io::FileReader freader(objectsPath.getAbsolutePath()); - if (!freader.isOpen()) - continue; - if (!athena::io::ValidateFromYAMLStream(freader)) - continue; + SCLY::ScriptLayer layer; + { + athena::io::FileReader freader(objectsPath.getAbsolutePath()); + if (!freader.isOpen()) + continue; + if (!athena::io::ValidateFromYAMLStream(freader)) + continue; - athena::io::YAMLDocReader reader; - if (!reader.parse(&freader)) - continue; + athena::io::YAMLDocReader reader; + if (!reader.parse(&freader)) + continue; - layer.read(reader); - } + layer.read(reader); + } - layerResources.beginLayer(); + layerResources.beginLayer(); - /* Set active flag state */ - hecl::ProjectPath defActivePath(area.path, e.m_name + _SYS_STR("/!defaultactive")); - bool active = defActivePath.isNone() ? false : true; + /* Set active flag state */ + hecl::ProjectPath defActivePath(area.path, e.m_name + _SYS_STR("/!defaultactive")); + bool active = defActivePath.isNone() ? false : true; - if (!areaInit) - { - /* Finish last area */ - mlvl.finishLastArea(); + if (!areaInit) { + /* Finish last area */ + mlvl.finishLastArea(); - /* Populate area record */ - mlvl.areas.emplace_back(); - MLVL::Area& areaOut = mlvl.areas.back(); - - hecl::ProjectPath namePath(area.path, _SYS_STR("!name.yaml")); - if (namePath.isFile()) - areaOut.areaNameId = namePath; - - areaOut.transformMtx[0] = area.transform[0]; - areaOut.transformMtx[1] = area.transform[1]; - areaOut.transformMtx[2] = area.transform[2]; - areaOut.aabb[0] = area.aabb[0]; - areaOut.aabb[1] = area.aabb[1]; - areaOut.areaMREAId = areaPath; - areaOut.areaId = 0xffffffff; - - hecl::ProjectPath memIdPath(area.path, _SYS_STR("!memoryid.yaml")); - if (memIdPath.isFile()) - { - athena::io::FileReader fr(memIdPath.getAbsolutePath()); - athena::io::YAMLDocReader r; - if (r.parse(&fr)) - areaOut.areaId = r.readUint32("memoryid"); - } - - /* Attached Areas and Docks */ - { - std::unordered_set addedAreas; - areaOut.dockCount = area.docks.size(); - for (const World::Area::Dock& dock : area.docks) - { - areaOut.docks.emplace_back(); - MLVL::Area::Dock& dockOut = areaOut.docks.back(); - - if (dock.targetArea != -1 && dock.targetDock != -1) - { - dockOut.endpointCount = 1; - dockOut.endpoints.emplace_back(); - MLVL::Area::Dock::Endpoint& ep = dockOut.endpoints.back(); - ep.areaIdx = dock.targetArea; - ep.dockIdx = dock.targetDock; - - if (addedAreas.find(dock.targetArea) == addedAreas.cend()) - { - addedAreas.insert(dock.targetArea); - areaOut.attachedAreas.push_back(dock.targetArea); - } - } - else - { - dockOut.endpointCount = 0; - } - - dockOut.planeVertCount = 4; - dockOut.planeVerts.push_back(dock.verts[0]); - dockOut.planeVerts.push_back(dock.verts[1]); - dockOut.planeVerts.push_back(dock.verts[2]); - dockOut.planeVerts.push_back(dock.verts[3]); - } - areaOut.attachedAreaCount = areaOut.attachedAreas.size(); - } - - /* Layer flags */ - mlvl.layerFlags.emplace_back(); - mlvl.layerFlags.back().layerCount = 0; - mlvl.layerFlags.back().flags = ~0; - - /* Layer name offset */ - mlvl.layerNameOffsets.push_back(nameOffset); - - areaInit = true; - } - - /* Gather memory relays, scans, and dependencies */ - { - g_ThreadBlenderToken.reset(&btok); - std::vector depPaths; - std::vector lazyPaths; - for (std::unique_ptr& obj : layer.objects) - { - if (obj->type == int(urde::EScriptObjectType::MemoryRelay)) - { - MemoryRelay& memRelay = static_cast(*obj); - for (IScriptObject::Connection& conn : memRelay.connections) - { - MemRelayLink linkOut; - linkOut.memRelayId = memRelay.id; - linkOut.targetId = conn.target; - linkOut.msg = conn.msg; - linkOut.active = memRelay.active; - auto iter = std::find(memRelays.begin(), memRelays.end(), linkOut.memRelayId); - if (iter == memRelays.end()) - { - /* We must have a new relay, let's track it */ - memRelayLinks.push_back(linkOut); - memRelays.push_back(memRelay.id); - } - else /* Lets insert this in it's appropriate location, target order doesn't matter */ - { - atUint32 idx = iter - memRelays.begin(); - if (idx >= memRelayLinks.size()) - memRelayLinks.push_back(linkOut); - else - memRelayLinks.insert(memRelayLinks.begin() + idx, linkOut); - } - } - } - - obj->gatherDependencies(depPaths, lazyPaths); - } - - /* Cull duplicate paths and add typed hash to list */ - for (const hecl::ProjectPath& path : depPaths) - layerResources.addPath(path, false); - for (const hecl::ProjectPath& path : lazyPaths) - layerResources.addPath(path, true); - } - - hecl::SystemUTF8Conv layerU8(layerName); - mlvl.layerNames.emplace_back(layerU8.str()); - nameOffset += layerName.size() + 1; - - MLVL::LayerFlags& thisLayFlags = mlvl.layerFlags.back(); - ++thisLayFlags.layerCount; - if (!active) - thisLayFlags.flags &= ~(1 << layerIdx); - - ++layerIdx; - } - - if (!areaInit) - Log.report(logvisor::Info, _SYS_STR("No layer directories for area %s"), area.path.getRelativePath().data()); - - /* Build deplist */ + /* Populate area record */ + mlvl.areas.emplace_back(); MLVL::Area& areaOut = mlvl.areas.back(); - for (const std::vector>& layer : layerResources.layerPaths) - { - areaOut.depLayers.push_back(areaOut.deps.size()); - for (const std::pair& path : layer) - { - if (path.first) - { - urde::SObjectTag tag = g_curSpec->buildTagFromPath(path.first, btok); - if (tag.id.IsValid()) - { - if (path.second) - areaOut.lazyDeps.emplace_back(tag.id.Value(), tag.type); - else - areaOut.lazyDeps.emplace_back(0, FOURCC('NONE')); - areaOut.deps.emplace_back(tag.id.Value(), tag.type); - } - } - } + + hecl::ProjectPath namePath(area.path, _SYS_STR("!name.yaml")); + if (namePath.isFile()) + areaOut.areaNameId = namePath; + + areaOut.transformMtx[0] = area.transform[0]; + areaOut.transformMtx[1] = area.transform[1]; + areaOut.transformMtx[2] = area.transform[2]; + areaOut.aabb[0] = area.aabb[0]; + areaOut.aabb[1] = area.aabb[1]; + areaOut.areaMREAId = areaPath; + areaOut.areaId = 0xffffffff; + + hecl::ProjectPath memIdPath(area.path, _SYS_STR("!memoryid.yaml")); + if (memIdPath.isFile()) { + athena::io::FileReader fr(memIdPath.getAbsolutePath()); + athena::io::YAMLDocReader r; + if (r.parse(&fr)) + areaOut.areaId = r.readUint32("memoryid"); } - /* Append Memory Relays */ - mlvl.memRelayLinks.insert(mlvl.memRelayLinks.end(), memRelayLinks.begin(), memRelayLinks.end()); - - /* Cull duplicate area paths and add typed hash to list */ - auto& conn = btok.getBlenderConnection(); - if (conn.openBlend(areaPath)) + /* Attached Areas and Docks */ { - areaOut.depLayers.push_back(areaOut.deps.size()); + std::unordered_set addedAreas; + areaOut.dockCount = area.docks.size(); + for (const World::Area::Dock& dock : area.docks) { + areaOut.docks.emplace_back(); + MLVL::Area::Dock& dockOut = areaOut.docks.back(); - auto ds = conn.beginData(); - std::vector texs = ds.getTextures(); - ds.close(); + if (dock.targetArea != -1 && dock.targetDock != -1) { + dockOut.endpointCount = 1; + dockOut.endpoints.emplace_back(); + MLVL::Area::Dock::Endpoint& ep = dockOut.endpoints.back(); + ep.areaIdx = dock.targetArea; + ep.dockIdx = dock.targetDock; - for (const hecl::ProjectPath& path : texs) - layerResources.addSharedPath(path, false); - - for (const std::pair& path : layerResources.sharedPaths) - { - urde::SObjectTag tag = g_curSpec->buildTagFromPath(path.first, btok); - if (tag.id.IsValid()) - { - if (path.second) - areaOut.lazyDeps.emplace_back(tag.id.Value(), tag.type); - else - areaOut.lazyDeps.emplace_back(0, FOURCC('NONE')); - areaOut.deps.emplace_back(tag.id.Value(), tag.type); - } + if (addedAreas.find(dock.targetArea) == addedAreas.cend()) { + addedAreas.insert(dock.targetArea); + areaOut.attachedAreas.push_back(dock.targetArea); + } + } else { + dockOut.endpointCount = 0; } - hecl::ProjectPath pathPath(areaPath.getParentPath(), _SYS_STR("!path.blend")); - urde::SObjectTag pathTag = g_curSpec->buildTagFromPath(pathPath, btok); - if (pathTag.id.IsValid()) - { - areaOut.deps.emplace_back(pathTag.id.Value(), pathTag.type); - areaOut.lazyDeps.emplace_back(0, FOURCC('NONE')); + dockOut.planeVertCount = 4; + dockOut.planeVerts.push_back(dock.verts[0]); + dockOut.planeVerts.push_back(dock.verts[1]); + dockOut.planeVerts.push_back(dock.verts[2]); + dockOut.planeVerts.push_back(dock.verts[3]); + } + areaOut.attachedAreaCount = areaOut.attachedAreas.size(); + } + + /* Layer flags */ + mlvl.layerFlags.emplace_back(); + mlvl.layerFlags.back().layerCount = 0; + mlvl.layerFlags.back().flags = ~0; + + /* Layer name offset */ + mlvl.layerNameOffsets.push_back(nameOffset); + + areaInit = true; + } + + /* Gather memory relays, scans, and dependencies */ + { + g_ThreadBlenderToken.reset(&btok); + std::vector depPaths; + std::vector lazyPaths; + for (std::unique_ptr& obj : layer.objects) { + if (obj->type == int(urde::EScriptObjectType::MemoryRelay)) { + MemoryRelay& memRelay = static_cast(*obj); + for (IScriptObject::Connection& conn : memRelay.connections) { + MemRelayLink linkOut; + linkOut.memRelayId = memRelay.id; + linkOut.targetId = conn.target; + linkOut.msg = conn.msg; + linkOut.active = memRelay.active; + auto iter = std::find(memRelays.begin(), memRelays.end(), linkOut.memRelayId); + if (iter == memRelays.end()) { + /* We must have a new relay, let's track it */ + memRelayLinks.push_back(linkOut); + memRelays.push_back(memRelay.id); + } else /* Lets insert this in it's appropriate location, target order doesn't matter */ + { + atUint32 idx = iter - memRelays.begin(); + if (idx >= memRelayLinks.size()) + memRelayLinks.push_back(linkOut); + else + memRelayLinks.insert(memRelayLinks.begin() + idx, linkOut); + } } + } + + obj->gatherDependencies(depPaths, lazyPaths); } - ++areaIdx; + /* Cull duplicate paths and add typed hash to list */ + for (const hecl::ProjectPath& path : depPaths) + layerResources.addPath(path, false); + for (const hecl::ProjectPath& path : lazyPaths) + layerResources.addPath(path, true); + } + + hecl::SystemUTF8Conv layerU8(layerName); + mlvl.layerNames.emplace_back(layerU8.str()); + nameOffset += layerName.size() + 1; + + MLVL::LayerFlags& thisLayFlags = mlvl.layerFlags.back(); + ++thisLayFlags.layerCount; + if (!active) + thisLayFlags.flags &= ~(1 << layerIdx); + + ++layerIdx; } - /* Finish last area */ - mlvl.finishLastArea(); + if (!areaInit) + Log.report(logvisor::Info, _SYS_STR("No layer directories for area %s"), area.path.getRelativePath().data()); - mlvl.memRelayLinkCount = mlvl.memRelayLinks.size(); - mlvl.areaCount = mlvl.areas.size(); - mlvl.layerFlagCount = mlvl.layerFlags.size(); - mlvl.layerNameCount = mlvl.layerNames.size(); - mlvl.layerNameOffsetCount = mlvl.layerNameOffsets.size(); - - /* Write out */ - { - athena::io::FileWriter fo(outPath.getAbsolutePath()); - mlvl.write(fo); - int64_t rem = fo.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - fo.writeBytes((atInt8*)"\xff", 1); - } - - return true; -} - -bool MLVL::CookMAPW(const hecl::ProjectPath& outPath, - const World& wld, - hecl::blender::Token& btok) -{ - std::vector mapaTags; - mapaTags.reserve(wld.areas.size()); - - for (const World::Area& area : wld.areas) - { - if (area.path.getPathType() != hecl::ProjectPath::Type::Directory) - continue; - - /* Area map */ - hecl::ProjectPath mapPath(area.path, _SYS_STR("/!map.blend")); - if (mapPath.isFile()) - mapaTags.push_back(g_curSpec->buildTagFromPath(mapPath, btok)); - } - - /* Write out MAPW */ - { - athena::io::FileWriter fo(outPath.getAbsolutePath()); - fo.writeUint32Big(0xDEADF00D); - fo.writeUint32Big(1); - fo.writeUint32Big(mapaTags.size()); - for (const urde::SObjectTag& mapa : mapaTags) - fo.writeUint32Big(u32(mapa.id.Value())); - int64_t rem = fo.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - fo.writeBytes((atInt8*)"\xff", 1); - } - - return true; -} - -bool MLVL::CookSAVW(const hecl::ProjectPath& outPath, - const World& wld) -{ - SAVW savw = {}; - savw.header.magic = 0xC001D00D; - savw.header.version = 0x3; - std::unordered_set addedScans; - - for (const World::Area& area : wld.areas) - { - if (area.path.getPathType() != hecl::ProjectPath::Type::Directory) - continue; - - hecl::ProjectPath areaPath(area.path, _SYS_STR("/!area.blend")); - if (!areaPath.isFile()) - continue; - - hecl::ProjectPath memRelayPath(area.path, _SYS_STR("/!memoryrelays.yaml")); - std::vector memRelays; - if (memRelayPath.isFile()) - { - athena::io::FileReader fr(memRelayPath.getAbsolutePath()); - athena::io::YAMLDocReader r; - if (r.parse(&fr)) - r.enumerate("memrelays", memRelays); - } - savw.relays.insert(savw.relays.end(), memRelays.begin(), memRelays.end()); - - hecl::DirectoryEnumerator dEnum(area.path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsSorted); - - for (const hecl::DirectoryEnumerator::Entry& e : dEnum) - { - hecl::SystemString layerName; - hecl::SystemChar* endCh = nullptr; - hecl::StrToUl(e.m_name.c_str(), &endCh, 0); - if (!endCh) - layerName = hecl::StringUtils::TrimWhitespace(e.m_name); + /* Build deplist */ + MLVL::Area& areaOut = mlvl.areas.back(); + for (const std::vector>& layer : layerResources.layerPaths) { + areaOut.depLayers.push_back(areaOut.deps.size()); + for (const std::pair& path : layer) { + if (path.first) { + urde::SObjectTag tag = g_curSpec->buildTagFromPath(path.first, btok); + if (tag.id.IsValid()) { + if (path.second) + areaOut.lazyDeps.emplace_back(tag.id.Value(), tag.type); else - layerName = hecl::StringUtils::TrimWhitespace(hecl::SystemString(endCh)); - - hecl::ProjectPath objectsPath(area.path, e.m_name + _SYS_STR("/!objects.yaml")); - if (objectsPath.isNone()) - continue; - - SCLY::ScriptLayer layer; - { - athena::io::FileReader freader(objectsPath.getAbsolutePath()); - if (!freader.isOpen()) - continue; - if (!athena::io::ValidateFromYAMLStream(freader)) - continue; - - athena::io::YAMLDocReader reader; - if (!reader.parse(&freader)) - continue; - - layer.read(reader); - } - - /* Gather memory relays, scans, and dependencies */ - { - std::vector scans; - for (std::unique_ptr& obj : layer.objects) - { - if (obj->type == int(urde::EScriptObjectType::MemoryRelay)) - { - MemoryRelay& memRelay = static_cast(*obj); - auto iter = std::find(memRelays.begin(), memRelays.end(), memRelay.id); - if (iter == memRelays.end()) - { - /* We must have a new relay, let's track it */ - savw.relays.push_back(memRelay.id); - memRelays.push_back(memRelay.id); - } - } - else if (obj->type == int(urde::EScriptObjectType::SpecialFunction)) - { - SpecialFunction& specialFunc = static_cast(*obj); - if (specialFunc.function == ESpecialFunctionType::CinematicSkip) - savw.skippableCutscenes.push_back(specialFunc.id); - else if (specialFunc.function == ESpecialFunctionType::ScriptLayerController) - { - savw.layers.emplace_back(); - SAVWCommon::Layer& layer = savw.layers.back(); - layer.areaId = specialFunc.layerSwitch.area; - layer.layer = specialFunc.layerSwitch.layerIdx; - } - } - else if (obj->type == int(urde::EScriptObjectType::Door)) - { - DoorArea& doorArea = static_cast(*obj); - savw.doors.push_back(doorArea.id); - } - - obj->gatherScans(scans); - } - - /* Cull duplicate scans and add to list */ - for (const Scan& scan : scans) - { - if (!scan.scanId) - continue; - if (addedScans.find(scan.scanId) == addedScans.cend()) - { - addedScans.insert(scan.scanId); - hecl::ProjectPath scanPath = UniqueIDBridge::TranslatePakIdToPath(scan.scanId); - savw.scans.emplace_back(); - Scan& scanOut = savw.scans.back(); - scanOut.scanId = scan.scanId; - scanOut.category = SAVWCommon::EScanCategory(SCAN::GetCategory(scanPath)); - } - } - } + areaOut.lazyDeps.emplace_back(0, FOURCC('NONE')); + areaOut.deps.emplace_back(tag.id.Value(), tag.type); + } } + } } - /* Write out SAVW */ - { - savw.header.areaCount = wld.areas.size(); - savw.skippableCutsceneCount = savw.skippableCutscenes.size(); - savw.relayCount = savw.relays.size(); - savw.layerCount = savw.layers.size(); - savw.doorCount = savw.doors.size(); - savw.scanCount = savw.scans.size(); + /* Append Memory Relays */ + mlvl.memRelayLinks.insert(mlvl.memRelayLinks.end(), memRelayLinks.begin(), memRelayLinks.end()); - athena::io::FileWriter fo(outPath.getAbsolutePath()); - savw.write(fo); - int64_t rem = fo.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - fo.writeBytes((atInt8*)"\xff", 1); + /* Cull duplicate area paths and add typed hash to list */ + auto& conn = btok.getBlenderConnection(); + if (conn.openBlend(areaPath)) { + areaOut.depLayers.push_back(areaOut.deps.size()); + + auto ds = conn.beginData(); + std::vector texs = ds.getTextures(); + ds.close(); + + for (const hecl::ProjectPath& path : texs) + layerResources.addSharedPath(path, false); + + for (const std::pair& path : layerResources.sharedPaths) { + urde::SObjectTag tag = g_curSpec->buildTagFromPath(path.first, btok); + if (tag.id.IsValid()) { + if (path.second) + areaOut.lazyDeps.emplace_back(tag.id.Value(), tag.type); + else + areaOut.lazyDeps.emplace_back(0, FOURCC('NONE')); + areaOut.deps.emplace_back(tag.id.Value(), tag.type); + } + } + + hecl::ProjectPath pathPath(areaPath.getParentPath(), _SYS_STR("!path.blend")); + urde::SObjectTag pathTag = g_curSpec->buildTagFromPath(pathPath, btok); + if (pathTag.id.IsValid()) { + areaOut.deps.emplace_back(pathTag.id.Value(), pathTag.type); + areaOut.lazyDeps.emplace_back(0, FOURCC('NONE')); + } } - return true; + ++areaIdx; + } + + /* Finish last area */ + mlvl.finishLastArea(); + + mlvl.memRelayLinkCount = mlvl.memRelayLinks.size(); + mlvl.areaCount = mlvl.areas.size(); + mlvl.layerFlagCount = mlvl.layerFlags.size(); + mlvl.layerNameCount = mlvl.layerNames.size(); + mlvl.layerNameOffsetCount = mlvl.layerNameOffsets.size(); + + /* Write out */ + { + athena::io::FileWriter fo(outPath.getAbsolutePath()); + mlvl.write(fo); + int64_t rem = fo.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + fo.writeBytes((atInt8*)"\xff", 1); + } + + return true; } +bool MLVL::CookMAPW(const hecl::ProjectPath& outPath, const World& wld, hecl::blender::Token& btok) { + std::vector mapaTags; + mapaTags.reserve(wld.areas.size()); + + for (const World::Area& area : wld.areas) { + if (area.path.getPathType() != hecl::ProjectPath::Type::Directory) + continue; + + /* Area map */ + hecl::ProjectPath mapPath(area.path, _SYS_STR("/!map.blend")); + if (mapPath.isFile()) + mapaTags.push_back(g_curSpec->buildTagFromPath(mapPath, btok)); + } + + /* Write out MAPW */ + { + athena::io::FileWriter fo(outPath.getAbsolutePath()); + fo.writeUint32Big(0xDEADF00D); + fo.writeUint32Big(1); + fo.writeUint32Big(mapaTags.size()); + for (const urde::SObjectTag& mapa : mapaTags) + fo.writeUint32Big(u32(mapa.id.Value())); + int64_t rem = fo.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + fo.writeBytes((atInt8*)"\xff", 1); + } + + return true; } + +bool MLVL::CookSAVW(const hecl::ProjectPath& outPath, const World& wld) { + SAVW savw = {}; + savw.header.magic = 0xC001D00D; + savw.header.version = 0x3; + std::unordered_set addedScans; + + for (const World::Area& area : wld.areas) { + if (area.path.getPathType() != hecl::ProjectPath::Type::Directory) + continue; + + hecl::ProjectPath areaPath(area.path, _SYS_STR("/!area.blend")); + if (!areaPath.isFile()) + continue; + + hecl::ProjectPath memRelayPath(area.path, _SYS_STR("/!memoryrelays.yaml")); + std::vector memRelays; + if (memRelayPath.isFile()) { + athena::io::FileReader fr(memRelayPath.getAbsolutePath()); + athena::io::YAMLDocReader r; + if (r.parse(&fr)) + r.enumerate("memrelays", memRelays); + } + savw.relays.insert(savw.relays.end(), memRelays.begin(), memRelays.end()); + + hecl::DirectoryEnumerator dEnum(area.path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsSorted); + + for (const hecl::DirectoryEnumerator::Entry& e : dEnum) { + hecl::SystemString layerName; + hecl::SystemChar* endCh = nullptr; + hecl::StrToUl(e.m_name.c_str(), &endCh, 0); + if (!endCh) + layerName = hecl::StringUtils::TrimWhitespace(e.m_name); + else + layerName = hecl::StringUtils::TrimWhitespace(hecl::SystemString(endCh)); + + hecl::ProjectPath objectsPath(area.path, e.m_name + _SYS_STR("/!objects.yaml")); + if (objectsPath.isNone()) + continue; + + SCLY::ScriptLayer layer; + { + athena::io::FileReader freader(objectsPath.getAbsolutePath()); + if (!freader.isOpen()) + continue; + if (!athena::io::ValidateFromYAMLStream(freader)) + continue; + + athena::io::YAMLDocReader reader; + if (!reader.parse(&freader)) + continue; + + layer.read(reader); + } + + /* Gather memory relays, scans, and dependencies */ + { + std::vector scans; + for (std::unique_ptr& obj : layer.objects) { + if (obj->type == int(urde::EScriptObjectType::MemoryRelay)) { + MemoryRelay& memRelay = static_cast(*obj); + auto iter = std::find(memRelays.begin(), memRelays.end(), memRelay.id); + if (iter == memRelays.end()) { + /* We must have a new relay, let's track it */ + savw.relays.push_back(memRelay.id); + memRelays.push_back(memRelay.id); + } + } else if (obj->type == int(urde::EScriptObjectType::SpecialFunction)) { + SpecialFunction& specialFunc = static_cast(*obj); + if (specialFunc.function == ESpecialFunctionType::CinematicSkip) + savw.skippableCutscenes.push_back(specialFunc.id); + else if (specialFunc.function == ESpecialFunctionType::ScriptLayerController) { + savw.layers.emplace_back(); + SAVWCommon::Layer& layer = savw.layers.back(); + layer.areaId = specialFunc.layerSwitch.area; + layer.layer = specialFunc.layerSwitch.layerIdx; + } + } else if (obj->type == int(urde::EScriptObjectType::Door)) { + DoorArea& doorArea = static_cast(*obj); + savw.doors.push_back(doorArea.id); + } + + obj->gatherScans(scans); + } + + /* Cull duplicate scans and add to list */ + for (const Scan& scan : scans) { + if (!scan.scanId) + continue; + if (addedScans.find(scan.scanId) == addedScans.cend()) { + addedScans.insert(scan.scanId); + hecl::ProjectPath scanPath = UniqueIDBridge::TranslatePakIdToPath(scan.scanId); + savw.scans.emplace_back(); + Scan& scanOut = savw.scans.back(); + scanOut.scanId = scan.scanId; + scanOut.category = SAVWCommon::EScanCategory(SCAN::GetCategory(scanPath)); + } + } + } + } + } + + /* Write out SAVW */ + { + savw.header.areaCount = wld.areas.size(); + savw.skippableCutsceneCount = savw.skippableCutscenes.size(); + savw.relayCount = savw.relays.size(); + savw.layerCount = savw.layers.size(); + savw.doorCount = savw.doors.size(); + savw.scanCount = savw.scans.size(); + + athena::io::FileWriter fo(outPath.getAbsolutePath()); + savw.write(fo); + int64_t rem = fo.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + fo.writeBytes((atInt8*)"\xff", 1); + } + + return true; +} + +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/MLVL.hpp b/DataSpec/DNAMP1/MLVL.hpp index ed3c30eaf..0da794481 100644 --- a/DataSpec/DNAMP1/MLVL.hpp +++ b/DataSpec/DNAMP1/MLVL.hpp @@ -4,166 +4,141 @@ #include "DataSpec/DNACommon/MLVL.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct MLVL : BigDNA -{ +struct MLVL : BigDNA { + AT_DECL_DNA_YAML + Value magic; + Value version; + UniqueID32 worldNameId; + UniqueID32 saveWorldId; + UniqueID32 worldSkyboxId; + + Value memRelayLinkCount; + struct MemRelayLink : BigDNA { AT_DECL_DNA_YAML - Value magic; - Value version; - UniqueID32 worldNameId; - UniqueID32 saveWorldId; - UniqueID32 worldSkyboxId; + Value memRelayId; + Value targetId; + Value msg; + Value active; + }; + Vector memRelayLinks; - Value memRelayLinkCount; - struct MemRelayLink : BigDNA - { - AT_DECL_DNA_YAML - Value memRelayId; - Value targetId; - Value msg; - Value active; + Value areaCount; + Value unknown1; + struct Area : BigDNA { + AT_DECL_DNA_YAML + UniqueID32 areaNameId; + Value transformMtx[3]; + Value aabb[2]; + UniqueID32 areaMREAId; + Value areaId; + + Value attachedAreaCount; + Vector attachedAreas; + + struct Dependency : BigDNA { + AT_DECL_DNA_YAML + UniqueID32 id; + DNAFourCC type; + + Dependency() = default; + Dependency(const UniqueID32& idin, const hecl::FourCC& fcc) : id(idin), type(fcc) {} }; - Vector memRelayLinks; - Value areaCount; - Value unknown1; - struct Area : BigDNA - { + Value lazyDepCount; + Vector lazyDeps; + + Value depCount; + Vector deps; + + Value depLayerCount; + Vector depLayers; + + Value dockCount; + struct Dock : BigDNA { + AT_DECL_DNA_YAML + Value endpointCount; + struct Endpoint : BigDNA { AT_DECL_DNA_YAML - UniqueID32 areaNameId; - Value transformMtx[3]; - Value aabb[2]; - UniqueID32 areaMREAId; - Value areaId; + Value areaIdx; + Value dockIdx; + }; + Vector endpoints; - Value attachedAreaCount; - Vector attachedAreas; - - struct Dependency : BigDNA - { - AT_DECL_DNA_YAML - UniqueID32 id; - DNAFourCC type; - - Dependency() = default; - Dependency(const UniqueID32& idin, const hecl::FourCC& fcc) - : id(idin), type(fcc) {} - }; - - Value lazyDepCount; - Vector lazyDeps; - - Value depCount; - Vector deps; - - Value depLayerCount; - Vector depLayers; - - Value dockCount; - struct Dock : BigDNA - { - AT_DECL_DNA_YAML - Value endpointCount; - struct Endpoint : BigDNA - { - AT_DECL_DNA_YAML - Value areaIdx; - Value dockIdx; - }; - Vector endpoints; - - Value planeVertCount; - Vector planeVerts; - }; - Vector docks; + Value planeVertCount; + Vector planeVerts; }; - Vector areas; + Vector docks; + }; + Vector areas; - void finishLastArea() - { - if (areas.size()) - { - MLVL::Area& areaLast = areas.back(); - areaLast.attachedAreaCount = areaLast.attachedAreas.size(); - areaLast.lazyDepCount = areaLast.lazyDeps.size(); - areaLast.depCount = areaLast.deps.size(); - areaLast.depLayerCount = areaLast.depLayers.size(); - areaLast.dockCount = areaLast.docks.size(); - } + void finishLastArea() { + if (areas.size()) { + MLVL::Area& areaLast = areas.back(); + areaLast.attachedAreaCount = areaLast.attachedAreas.size(); + areaLast.lazyDepCount = areaLast.lazyDeps.size(); + areaLast.depCount = areaLast.deps.size(); + areaLast.depLayerCount = areaLast.depLayers.size(); + areaLast.dockCount = areaLast.docks.size(); } + } - UniqueID32 worldMap; - Value unknown2; - Value unknown3; + UniqueID32 worldMap; + Value unknown2; + Value unknown3; - Value audioGroupCount; - struct AudioGroup : BigDNA - { - AT_DECL_DNA_YAML - Value groupId; - UniqueID32 agscId; - }; - Vector audioGroups; - String<-1> unkString; + Value audioGroupCount; + struct AudioGroup : BigDNA { + AT_DECL_DNA_YAML + Value groupId; + UniqueID32 agscId; + }; + Vector audioGroups; + String<-1> unkString; - Value layerFlagCount; - struct LayerFlags : BigDNA - { - AT_DECL_DNA_YAML - Value layerCount; - Value flags; - }; - Vector layerFlags; + Value layerFlagCount; + struct LayerFlags : BigDNA { + AT_DECL_DNA_YAML + Value layerCount; + Value flags; + }; + Vector layerFlags; - Value layerNameCount; - Vector, AT_DNA_COUNT(layerNameCount)> layerNames; + Value layerNameCount; + Vector, AT_DNA_COUNT(layerNameCount)> layerNames; - Value layerNameOffsetCount; - Vector layerNameOffsets; + Value layerNameOffsetCount; + Vector layerNameOffsets; - void readMeta(athena::io::YAMLDocReader& __dna_docin) - { - /* worldSkyboxId */ - __dna_docin.enumerate("worldSkyboxId", worldSkyboxId); - /* audioGroupCount squelched */ - /* audioGroups */ - audioGroupCount = __dna_docin.enumerate("audioGroups", audioGroups); - } + void readMeta(athena::io::YAMLDocReader& __dna_docin) { + /* worldSkyboxId */ + __dna_docin.enumerate("worldSkyboxId", worldSkyboxId); + /* audioGroupCount squelched */ + /* audioGroups */ + audioGroupCount = __dna_docin.enumerate("audioGroups", audioGroups); + } - void writeMeta(athena::io::YAMLDocWriter& __dna_docout) const - { - /* worldSkyboxId */ - __dna_docout.enumerate("worldSkyboxId", worldSkyboxId); - /* audioGroupCount squelched */ - /* audioGroups */ - __dna_docout.enumerate("audioGroups", audioGroups); - } + void writeMeta(athena::io::YAMLDocWriter& __dna_docout) const { + /* worldSkyboxId */ + __dna_docout.enumerate("worldSkyboxId", worldSkyboxId); + /* audioGroupCount squelched */ + /* audioGroups */ + __dna_docout.enumerate("audioGroups", audioGroups); + } - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged); + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged); - using World = hecl::blender::World; + using World = hecl::blender::World; - static bool Cook(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const World& wld, - hecl::blender::Token& btok); + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, const World& wld, + hecl::blender::Token& btok); - static bool CookMAPW(const hecl::ProjectPath& outPath, - const World& wld, - hecl::blender::Token& btok); + static bool CookMAPW(const hecl::ProjectPath& outPath, const World& wld, hecl::blender::Token& btok); - static bool CookSAVW(const hecl::ProjectPath& outPath, - const World& wld); + static bool CookSAVW(const hecl::ProjectPath& outPath, const World& wld); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/MREA.cpp b/DataSpec/DNAMP1/MREA.cpp index c223cc884..d982ab2a1 100644 --- a/DataSpec/DNAMP1/MREA.cpp +++ b/DataSpec/DNAMP1/MREA.cpp @@ -15,831 +15,752 @@ extern hecl::SystemString ExeDir; -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -void MREA::ReadBabeDeadToBlender_1_2(hecl::blender::PyOutStream& os, - athena::io::IStreamReader& rs) -{ - atUint32 bdMagic = rs.readUint32Big(); - if (bdMagic != 0xBABEDEAD) - Log.report(logvisor::Fatal, "invalid BABEDEAD magic"); - os << "bpy.context.scene.render.engine = 'CYCLES'\n" - "bpy.context.scene.world.use_nodes = True\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" - "bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n" - "bg_node.inputs[1].default_value = 0.0\n"; - for (atUint32 s=0 ; s<2 ; ++s) - { - atUint32 lightCount = rs.readUint32Big(); - for (atUint32 l=0 ; l& pakRouter, CharacterAssociations& charAssoc) -{ - /* Do extract */ - Header head; - head.read(rs); - rs.seekAlign32(); +void MREA::AddCMDLRigPairs(PAKEntryReadStream& rs, PAKRouter& pakRouter, + CharacterAssociations& charAssoc) { + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); - /* Skip to SCLY */ - atUint32 curSec = 0; - atUint64 secStart = rs.position(); - while (curSec != head.sclySecIdx) - secStart += head.secSizes[curSec++]; - rs.seek(secStart, athena::Begin); - SCLY scly; - scly.read(rs); - scly.addCMDLRigPairs(pakRouter, charAssoc); + /* Skip to SCLY */ + atUint32 curSec = 0; + atUint64 secStart = rs.position(); + while (curSec != head.sclySecIdx) + secStart += head.secSizes[curSec++]; + rs.seek(secStart, athena::Begin); + SCLY scly; + scly.read(rs); + scly.addCMDLRigPairs(pakRouter, charAssoc); } -UniqueID32 MREA::GetPATHId(PAKEntryReadStream& rs) -{ - /* Do extract */ - Header head; - head.read(rs); - rs.seekAlign32(); +UniqueID32 MREA::GetPATHId(PAKEntryReadStream& rs) { + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); - /* Skip to PATH */ - atUint32 curSec = 0; - atUint64 secStart = rs.position(); - while (curSec != head.pathSecIdx) - secStart += head.secSizes[curSec++]; - if (!head.secSizes[curSec]) - return {}; - rs.seek(secStart, athena::Begin); - return {rs}; + /* Skip to PATH */ + atUint32 curSec = 0; + atUint64 secStart = rs.position(); + while (curSec != head.pathSecIdx) + secStart += head.secSizes[curSec++]; + if (!head.secSizes[curSec]) + return {}; + rs.seek(secStart, athena::Begin); + return {rs}; } #if DUMP_OCTREE /* Collision octree dumper */ -static void OutputOctreeNode(hecl::blender::PyOutStream& os, athena::io::MemoryReader& r, - BspNodeType type, const zeus::CAABox& aabb) -{ - if (type == BspNodeType::Branch) - { - u16 flags = r.readUint16Big(); - r.readUint16Big(); - u32 offsets[8]; - for (int i=0 ; i<8 ; ++i) - offsets[i] = r.readUint32Big(); - u32 dataStart = r.position(); - for (int i=0 ; i<8 ; ++i) - { - r.seek(dataStart + offsets[i], athena::Begin); - int chFlags = (flags >> (i * 2)) & 0x3; +static void OutputOctreeNode(hecl::blender::PyOutStream& os, athena::io::MemoryReader& r, BspNodeType type, + const zeus::CAABox& aabb) { + if (type == BspNodeType::Branch) { + u16 flags = r.readUint16Big(); + r.readUint16Big(); + u32 offsets[8]; + for (int i = 0; i < 8; ++i) + offsets[i] = r.readUint32Big(); + u32 dataStart = r.position(); + for (int i = 0; i < 8; ++i) { + r.seek(dataStart + offsets[i], athena::Begin); + int chFlags = (flags >> (i * 2)) & 0x3; - zeus::CAABox pos, neg, res; - aabb.splitZ(neg, pos); - if (i & 4) - { - zeus::CAABox(pos).splitY(neg, pos); - if (i & 2) - { - zeus::CAABox(pos).splitX(neg, pos); - if (i & 1) - res = pos; - else - res = neg; - } - else - { - zeus::CAABox(neg).splitX(neg, pos); - if (i & 1) - res = pos; - else - res = neg; - } - } - else - { - zeus::CAABox(neg).splitY(neg, pos); - if (i & 2) - { - zeus::CAABox(pos).splitX(neg, pos); - if (i & 1) - res = pos; - else - res = neg; - } - else - { - zeus::CAABox(neg).splitX(neg, pos); - if (i & 1) - res = pos; - else - res = neg; - } - } - - OutputOctreeNode(os, r, BspNodeType(chFlags), res); + zeus::CAABox pos, neg, res; + aabb.splitZ(neg, pos); + if (i & 4) { + zeus::CAABox(pos).splitY(neg, pos); + if (i & 2) { + zeus::CAABox(pos).splitX(neg, pos); + if (i & 1) + res = pos; + else + res = neg; + } else { + zeus::CAABox(neg).splitX(neg, pos); + if (i & 1) + res = pos; + else + res = neg; } + } else { + zeus::CAABox(neg).splitY(neg, pos); + if (i & 2) { + zeus::CAABox(pos).splitX(neg, pos); + if (i & 1) + res = pos; + else + res = neg; + } else { + zeus::CAABox(neg).splitX(neg, pos); + if (i & 1) + res = pos; + else + res = neg; + } + } + + OutputOctreeNode(os, r, BspNodeType(chFlags), res); } - else if (type == BspNodeType::Leaf) - { - zeus::CVector3f pos = aabb.center(); - zeus::CVector3f extent = aabb.extents(); - os.format("obj = bpy.data.objects.new('Leaf', None)\n" - "bpy.context.scene.objects.link(obj)\n" - "obj.location = (%f,%f,%f)\n" - "obj.scale = (%f,%f,%f)\n" - "obj.empty_draw_type = 'CUBE'\n" - "obj.layers[1] = True\n" - "obj.layers[0] = False\n", + } else if (type == BspNodeType::Leaf) { + zeus::CVector3f pos = aabb.center(); + zeus::CVector3f extent = aabb.extents(); + os.format( + "obj = bpy.data.objects.new('Leaf', None)\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.location = (%f,%f,%f)\n" + "obj.scale = (%f,%f,%f)\n" + "obj.empty_draw_type = 'CUBE'\n" + "obj.layers[1] = True\n" + "obj.layers[0] = False\n", pos.x, pos.y, pos.z, extent.x, extent.y, extent.z); - } + } } -static const uint32_t AROTChildCounts[] = { 0, 2, 2, 4, 2, 4, 4, 8 }; +static const uint32_t AROTChildCounts[] = {0, 2, 2, 4, 2, 4, 4, 8}; /* AROT octree dumper */ -static void OutputOctreeNode(hecl::blender::PyOutStream& os, athena::io::IStreamReader& r, - const zeus::CAABox& aabb) -{ - r.readUint16Big(); - u16 flags = r.readUint16Big(); - if (flags) - { - u32 childCount = AROTChildCounts[flags]; - r.seek(2 * childCount); +static void OutputOctreeNode(hecl::blender::PyOutStream& os, athena::io::IStreamReader& r, const zeus::CAABox& aabb) { + r.readUint16Big(); + u16 flags = r.readUint16Big(); + if (flags) { + u32 childCount = AROTChildCounts[flags]; + r.seek(2 * childCount); - zeus::CAABox Z[2] = {aabb}; - if ((flags & 0x4) != 0) - aabb.splitZ(Z[0], Z[1]); - for (int k=0 ; k < 1 + ((flags & 0x4) != 0) ; ++k) - { - zeus::CAABox Y[2] = {Z[k]}; - if ((flags & 0x2) != 0) - Z[k].splitY(Y[0], Y[1]); - for (int j=0 ; j < 1 + ((flags & 0x2) != 0) ; ++j) - { - zeus::CAABox X[2] = {Y[j]}; - if ((flags & 0x1) != 0) - Y[j].splitX(X[0], X[1]); - for (int i=0 ; i < 1 + ((flags & 0x1) != 0) ; ++i) - { - OutputOctreeNode(os, r, X[i]); - } - } + zeus::CAABox Z[2] = {aabb}; + if ((flags & 0x4) != 0) + aabb.splitZ(Z[0], Z[1]); + for (int k = 0; k < 1 + ((flags & 0x4) != 0); ++k) { + zeus::CAABox Y[2] = {Z[k]}; + if ((flags & 0x2) != 0) + Z[k].splitY(Y[0], Y[1]); + for (int j = 0; j < 1 + ((flags & 0x2) != 0); ++j) { + zeus::CAABox X[2] = {Y[j]}; + if ((flags & 0x1) != 0) + Y[j].splitX(X[0], X[1]); + for (int i = 0; i < 1 + ((flags & 0x1) != 0); ++i) { + OutputOctreeNode(os, r, X[i]); } + } } - else - { - zeus::CVector3f pos = aabb.center(); - zeus::CVector3f extent = aabb.extents(); - os.format("obj = bpy.data.objects.new('Leaf', None)\n" - "bpy.context.scene.objects.link(obj)\n" - "obj.location = (%f,%f,%f)\n" - "obj.scale = (%f,%f,%f)\n" - "obj.empty_draw_type = 'CUBE'\n" - "obj.layers[1] = True\n" - "obj.layers[0] = False\n", - pos.x, pos.y, pos.z, extent.x, extent.y, extent.z); - } + } else { + zeus::CVector3f pos = aabb.center(); + zeus::CVector3f extent = aabb.extents(); + os.format( + "obj = bpy.data.objects.new('Leaf', None)\n" + "bpy.context.scene.objects.link(obj)\n" + "obj.location = (%f,%f,%f)\n" + "obj.scale = (%f,%f,%f)\n" + "obj.empty_draw_type = 'CUBE'\n" + "obj.layers[1] = True\n" + "obj.layers[0] = False\n", + pos.x, pos.y, pos.z, extent.x, extent.y, extent.z); + } } #endif -bool MREA::Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function) -{ - using RigPair = std::pair; - RigPair dummy(nullptr, nullptr); +bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function) { + using RigPair = std::pair; + RigPair dummy(nullptr, nullptr); - if (!force && outPath.isFile()) - return true; + if (!force && outPath.isFile()) + return true; - /* Do extract */ - Header head; - head.read(rs); - rs.seekAlign32(); + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::Area)) + return false; + + /* Open Py Stream and read sections */ + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os.format( + "import bpy\n" + "import bmesh\n" + "from mathutils import Vector\n" + "\n" + "bpy.context.scene.name = '%s'\n", + pakRouter.getBestEntryName(entry, false).c_str()); + DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath(), true); + MaterialSet::RegisterMaterialProps(os); + os << "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " if ob.type != 'CAMERA':\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n" + "bpy.types.Lamp.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" + "bpy.types.Lamp.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" + "bpy.types.Object.retro_disable_enviro_visor = bpy.props.BoolProperty(name='Retro: Disable in Combat/Scan " + "Visor')\n" + "bpy.types.Object.retro_disable_thermal_visor = bpy.props.BoolProperty(name='Retro: Disable in Thermal " + "Visor')\n" + "bpy.types.Object.retro_disable_xray_visor = bpy.props.BoolProperty(name='Retro: Disable in X-Ray Visor')\n" + "bpy.types.Object.retro_thermal_level = bpy.props.EnumProperty(items=[('COOL', 'Cool', 'Cool Temperature')," + "('HOT', 'Hot', 'Hot Temperature')," + "('WARM', 'Warm', 'Warm Temperature')]," + "name='Retro: Thermal Visor Level')\n" + "\n"; + + /* One shared material set for all meshes */ + os << "# Materials\n" + "materials = []\n" + "\n"; + MaterialSet matSet; + atUint64 secStart = rs.position(); + matSet.read(rs); + matSet.readToBlender(os, pakRouter, entry, 0); + rs.seek(secStart + head.secSizes[0], athena::Begin); + std::vector vertAttribs; + DNACMDL::GetVertexAttributes(matSet, vertAttribs); + + /* Read meshes */ + atUint32 curSec = 1; + for (atUint32 m = 0; m < head.meshCount; ++m) { + MeshHeader mHeader; + secStart = rs.position(); + mHeader.read(rs); + rs.seek(secStart + head.secSizes[curSec++], athena::Begin); + curSec += DNACMDL::ReadGeomSectionsToBlender, MaterialSet, RigPair, DNACMDL::SurfaceHeader_1>( + os, rs, pakRouter, entry, dummy, true, true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]); + os.format( + "obj.retro_disable_enviro_visor = %s\n" + "obj.retro_disable_thermal_visor = %s\n" + "obj.retro_disable_xray_visor = %s\n" + "obj.retro_thermal_level = '%s'\n", + mHeader.visorFlags.disableEnviro() ? "True" : "False", mHeader.visorFlags.disableThermal() ? "True" : "False", + mHeader.visorFlags.disableXray() ? "True" : "False", mHeader.visorFlags.thermalLevelStr()); + } + + /* Skip AROT */ + secStart = rs.position(); + rs.seek(secStart + head.secSizes[curSec++], athena::Begin); + + /* Read SCLY layers */ + secStart = rs.position(); + SCLY scly; + scly.read(rs); + scly.exportToLayerDirectories(entry, pakRouter, force); + rs.seek(secStart + head.secSizes[curSec++], athena::Begin); + + /* Read collision meshes */ + DeafBabe collision; + secStart = rs.position(); + collision.read(rs); + DeafBabe::BlenderInit(os); + collision.sendToBlender(os); + rs.seek(secStart + head.secSizes[curSec++], athena::Begin); + + /* Skip unknown section */ + rs.seek(head.secSizes[curSec++], athena::Current); + + /* Read BABEDEAD Lights as Cycles emissives */ + secStart = rs.position(); + ReadBabeDeadToBlender_1_2(os, rs); + rs.seek(secStart + head.secSizes[curSec++], athena::Begin); + + /* Dump VISI entities */ + secStart = rs.position(); + if (head.secSizes[curSec] && rs.readUint32Big() == 'VISI') { + { + rs.seek(secStart, athena::Begin); + auto visiData = rs.readUBytes(head.secSizes[curSec]); + athena::io::FileWriter visiOut(outPath.getWithExtension(_SYS_STR(".visi"), true).getAbsolutePath()); + visiOut.writeUBytes(visiData.get(), head.secSizes[curSec]); + rs.seek(secStart + 4, athena::Begin); + } + + athena::io::YAMLDocWriter visiWriter("VISI"); + if (auto __vec = visiWriter.enterSubVector("entities")) { + rs.seek(18, athena::Current); + uint32_t entityCount = rs.readUint32Big(); + rs.seek(8, athena::Current); + for (int i = 0; i < entityCount; ++i) { + uint32_t entityId = rs.readUint32Big(); + visiWriter.writeUint32(nullptr, entityId); + } + } + hecl::ProjectPath visiMetadataPath(outPath.getParentPath(), _SYS_STR("!visi.yaml")); + athena::io::FileWriter visiMetadata(visiMetadataPath.getAbsolutePath()); + visiWriter.finish(&visiMetadata); + } + + /* Origins to center of mass */ + os << "bpy.context.scene.layers[1] = True\n" + "bpy.ops.object.select_by_type(type='MESH')\n" + "bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')\n" + "bpy.ops.object.select_all(action='DESELECT')\n" + "bpy.context.scene.layers[1] = False\n"; + + /* Link MLVL scene as background */ + os.linkBackground("//../!world.blend", "World"); + + os.centerView(); + os.close(); + return conn.saveBlend(); +} + +void MREA::Name(const SpecBase& dataSpec, PAKEntryReadStream& rs, PAKRouter& pakRouter, PAK::Entry& entry) { + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); + + /* One shared material set for all meshes */ + atUint64 secStart = rs.position(); + MaterialSet matSet; + matSet.read(rs); + matSet.nameTextures(pakRouter, hecl::Format("MREA_%s", entry.id.toString().c_str()).c_str(), -1); + rs.seek(secStart + head.secSizes[0], athena::Begin); + + /* Skip to SCLY */ + atUint32 curSec = 1; + secStart = rs.position(); + while (curSec != head.sclySecIdx) + secStart += head.secSizes[curSec++]; + rs.seek(secStart, athena::Begin); + SCLY scly; + scly.read(rs); + scly.nameIDs(pakRouter); + + /* Skip to PATH */ + while (curSec != head.pathSecIdx) + secStart += head.secSizes[curSec++]; + rs.seek(secStart, athena::Begin); + + UniqueID32 pathID(rs); + const nod::Node* node; + PAK::Entry* pathEnt = (PAK::Entry*)pakRouter.lookupEntry(pathID, &node); + pathEnt->name = entry.name + "_path"; +} + +void MREA::MeshHeader::VisorFlags::setFromBlenderProps(const std::unordered_map& props) { + auto search = props.find("retro_disable_enviro_visor"); + if (search != props.cend() && !search->second.compare("True")) + setDisableEnviro(true); + search = props.find("retro_disable_thermal_visor"); + if (search != props.cend() && !search->second.compare("True")) + setDisableThermal(true); + search = props.find("retro_disable_xray_visor"); + if (search != props.cend() && !search->second.compare("True")) + setDisableXray(true); + search = props.find("retro_thermal_level"); + if (search != props.cend()) { + if (!search->second.compare("COOL")) + setThermalLevel(ThermalLevel::Cool); + else if (!search->second.compare("HOT")) + setThermalLevel(ThermalLevel::Hot); + else if (!search->second.compare("WARM")) + setThermalLevel(ThermalLevel::Warm); + } +} + +bool MREA::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const std::vector& meshes, const ColMesh& cMesh, const std::vector& lights, + hecl::blender::Token& btok, const hecl::blender::Matrix4f* xf, bool pc) { + /* Discover area layers */ + hecl::ProjectPath areaDirPath = inPath.getParentPath(); + std::vector layerScriptPaths; + { + hecl::DirectoryEnumerator dEnum(inPath.getParentPath().getAbsolutePath(), + hecl::DirectoryEnumerator::Mode::DirsSorted, false, false, true); + for (const hecl::DirectoryEnumerator::Entry& ent : dEnum) { + hecl::ProjectPath layerScriptPath(areaDirPath, ent.m_name + _SYS_STR("/!objects.yaml")); + if (layerScriptPath.isFile()) + layerScriptPaths.push_back(std::move(layerScriptPath)); + } + } + + size_t secCount = 1 + meshes.size() * (pc ? 5 : 7); /* (materials, 5/7 fixed model secs) */ + + /* tally up surfaces */ + for (const DNACMDL::Mesh& mesh : meshes) + secCount += mesh.surfaces.size(); + + /* Header */ + Header head = {}; + head.magic = 0xDEADBEEF; + head.version = pc ? 0x1000F : 0xF; + if (xf) { + head.localToWorldMtx[0] = xf->val[0]; + head.localToWorldMtx[1] = xf->val[1]; + head.localToWorldMtx[2] = xf->val[2]; + } else { + head.localToWorldMtx[0].simd[0] = 1.f; + head.localToWorldMtx[1].simd[1] = 1.f; + head.localToWorldMtx[2].simd[2] = 1.f; + } + head.meshCount = meshes.size(); + head.geomSecIdx = 0; + head.arotSecIdx = secCount++; + head.sclySecIdx = secCount++; + head.collisionSecIdx = secCount++; + head.unkSecIdx = secCount++; + head.lightSecIdx = secCount++; + head.visiSecIdx = secCount++; + head.pathSecIdx = secCount++; + head.secCount = secCount; + + std::vector> secs; + secs.reserve(secCount + 2); + + /* Header section */ + { + size_t secSz = 0; + head.binarySize(secSz); + secs.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); + head.write(w); + int i = w.position(); + int end = ROUND_UP_32(i); + for (; i < end; ++i) + w.writeByte(0); + } + + /* Sizes section */ + secs.emplace_back(); + + /* Pre-emptively build full AABB and mesh AABBs in world coords */ + zeus::CAABox fullAabb; + std::vector meshAabbs; + meshAabbs.reserve(meshes.size()); + + /* Models */ + if (pc) { + if (!DNACMDL::WriteHMDLMREASecs(secs, inPath, meshes, + fullAabb, meshAabbs)) + return false; + } else { + if (!DNACMDL::WriteMREASecs(secs, inPath, meshes, fullAabb, + meshAabbs)) + return false; + } + + /* AROT */ + { + AROTBuilder arotBuilder; + arotBuilder.build(secs, fullAabb, meshAabbs, meshes); + +#if DUMP_OCTREE hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::Area)) - return false; + if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".octree.blend"), true), hecl::blender::BlendType::Area)) + return false; /* Open Py Stream and read sections */ hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "from mathutils import Vector\n" - "\n" - "bpy.context.scene.name = '%s'\n", - pakRouter.getBestEntryName(entry, false).c_str()); - DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath(), true); - MaterialSet::RegisterMaterialProps(os); - os << "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "bpy.types.Lamp.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" - "bpy.types.Lamp.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" - "bpy.types.Object.retro_disable_enviro_visor = bpy.props.BoolProperty(name='Retro: Disable in Combat/Scan Visor')\n" - "bpy.types.Object.retro_disable_thermal_visor = bpy.props.BoolProperty(name='Retro: Disable in Thermal Visor')\n" - "bpy.types.Object.retro_disable_xray_visor = bpy.props.BoolProperty(name='Retro: Disable in X-Ray Visor')\n" - "bpy.types.Object.retro_thermal_level = bpy.props.EnumProperty(items=[('COOL', 'Cool', 'Cool Temperature')," - "('HOT', 'Hot', 'Hot Temperature')," - "('WARM', 'Warm', 'Warm Temperature')]," - "name='Retro: Thermal Visor Level')\n" - "\n"; + os.format( + "import bpy\n" + "import bmesh\n" + "from mathutils import Vector\n" + "\n" + "bpy.context.scene.name = '%s'\n", + inPath.getLastComponentUTF8().data()); - /* One shared material set for all meshes */ - os << "# Materials\n" - "materials = []\n" - "\n"; - MaterialSet matSet; - atUint64 secStart = rs.position(); - matSet.read(rs); - matSet.readToBlender(os, pakRouter, entry, 0); - rs.seek(secStart + head.secSizes[0], athena::Begin); - std::vector vertAttribs; - DNACMDL::GetVertexAttributes(matSet, vertAttribs); - - /* Read meshes */ - atUint32 curSec = 1; - for (atUint32 m=0 ; m, MaterialSet, RigPair, DNACMDL::SurfaceHeader_1> - (os, rs, pakRouter, entry, dummy, true, - true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]); - os.format("obj.retro_disable_enviro_visor = %s\n" - "obj.retro_disable_thermal_visor = %s\n" - "obj.retro_disable_xray_visor = %s\n" - "obj.retro_thermal_level = '%s'\n", - mHeader.visorFlags.disableEnviro() ? "True" : "False", - mHeader.visorFlags.disableThermal() ? "True" : "False", - mHeader.visorFlags.disableXray() ? "True" : "False", - mHeader.visorFlags.thermalLevelStr()); - } - - /* Skip AROT */ - secStart = rs.position(); - rs.seek(secStart + head.secSizes[curSec++], athena::Begin); - - /* Read SCLY layers */ - secStart = rs.position(); - SCLY scly; - scly.read(rs); - scly.exportToLayerDirectories(entry, pakRouter, force); - rs.seek(secStart + head.secSizes[curSec++], athena::Begin); - - /* Read collision meshes */ - DeafBabe collision; - secStart = rs.position(); - collision.read(rs); - DeafBabe::BlenderInit(os); - collision.sendToBlender(os); - rs.seek(secStart + head.secSizes[curSec++], athena::Begin); - - /* Skip unknown section */ - rs.seek(head.secSizes[curSec++], athena::Current); - - /* Read BABEDEAD Lights as Cycles emissives */ - secStart = rs.position(); - ReadBabeDeadToBlender_1_2(os, rs); - rs.seek(secStart + head.secSizes[curSec++], athena::Begin); - - /* Dump VISI entities */ - secStart = rs.position(); - if (head.secSizes[curSec] && rs.readUint32Big() == 'VISI') - { - { - rs.seek(secStart, athena::Begin); - auto visiData = rs.readUBytes(head.secSizes[curSec]); - athena::io::FileWriter visiOut(outPath.getWithExtension(_SYS_STR(".visi"), true).getAbsolutePath()); - visiOut.writeUBytes(visiData.get(), head.secSizes[curSec]); - rs.seek(secStart + 4, athena::Begin); - } - - athena::io::YAMLDocWriter visiWriter("VISI"); - if (auto __vec = visiWriter.enterSubVector("entities")) - { - rs.seek(18, athena::Current); - uint32_t entityCount = rs.readUint32Big(); - rs.seek(8, athena::Current); - for (int i=0 ; i& pakRouter, - PAK::Entry& entry) -{ - /* Do extract */ - Header head; - head.read(rs); - rs.seekAlign32(); + /* SCLY */ + DNAMP1::SCLY sclyData = {}; + { + sclyData.fourCC = 'SCLY'; + sclyData.version = 1; + for (const hecl::ProjectPath& layer : layerScriptPaths) { + athena::io::FileReader freader(layer.getAbsolutePath()); + if (!freader.isOpen()) + continue; + if (!athena::io::ValidateFromYAMLStream(freader)) + continue; - /* One shared material set for all meshes */ - atUint64 secStart = rs.position(); - MaterialSet matSet; - matSet.read(rs); - matSet.nameTextures(pakRouter, hecl::Format("MREA_%s", entry.id.toString().c_str()).c_str(), -1); - rs.seek(secStart + head.secSizes[0], athena::Begin); + athena::io::YAMLDocReader reader; + if (!reader.parse(&freader)) + continue; - /* Skip to SCLY */ - atUint32 curSec = 1; - secStart = rs.position(); - while (curSec != head.sclySecIdx) - secStart += head.secSizes[curSec++]; - rs.seek(secStart, athena::Begin); - SCLY scly; - scly.read(rs); - scly.nameIDs(pakRouter); - - /* Skip to PATH */ - while (curSec != head.pathSecIdx) - secStart += head.secSizes[curSec++]; - rs.seek(secStart, athena::Begin); - - UniqueID32 pathID(rs); - const nod::Node* node; - PAK::Entry* pathEnt = (PAK::Entry*)pakRouter.lookupEntry(pathID, &node); - pathEnt->name = entry.name + "_path"; -} - -void MREA::MeshHeader::VisorFlags::setFromBlenderProps(const std::unordered_map& props) -{ - auto search = props.find("retro_disable_enviro_visor"); - if (search != props.cend() && !search->second.compare("True")) - setDisableEnviro(true); - search = props.find("retro_disable_thermal_visor"); - if (search != props.cend() && !search->second.compare("True")) - setDisableThermal(true); - search = props.find("retro_disable_xray_visor"); - if (search != props.cend() && !search->second.compare("True")) - setDisableXray(true); - search = props.find("retro_thermal_level"); - if (search != props.cend()) - { - if (!search->second.compare("COOL")) - setThermalLevel(ThermalLevel::Cool); - else if (!search->second.compare("HOT")) - setThermalLevel(ThermalLevel::Hot); - else if (!search->second.compare("WARM")) - setThermalLevel(ThermalLevel::Warm); + sclyData.layers.emplace_back(); + sclyData.layers.back().read(reader); + size_t layerSize = 0; + sclyData.layers.back().binarySize(layerSize); + sclyData.layerSizes.push_back(layerSize); } -} + sclyData.layerCount = sclyData.layers.size(); -bool MREA::Cook(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const std::vector& meshes, - const ColMesh& cMesh, - const std::vector& lights, - hecl::blender::Token& btok, - const hecl::blender::Matrix4f* xf, - bool pc) -{ - /* Discover area layers */ - hecl::ProjectPath areaDirPath = inPath.getParentPath(); - std::vector layerScriptPaths; - { - hecl::DirectoryEnumerator dEnum(inPath.getParentPath().getAbsolutePath(), - hecl::DirectoryEnumerator::Mode::DirsSorted, - false, false, true); - for (const hecl::DirectoryEnumerator::Entry& ent : dEnum) - { - hecl::ProjectPath layerScriptPath(areaDirPath, ent.m_name + _SYS_STR("/!objects.yaml")); - if (layerScriptPath.isFile()) - layerScriptPaths.push_back(std::move(layerScriptPath)); - } - } + size_t secSz = 0; + sclyData.binarySize(secSz); + secs.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); + sclyData.write(w); + } - size_t secCount = 1 + meshes.size() * (pc ? 5 : 7); /* (materials, 5/7 fixed model secs) */ - - /* tally up surfaces */ - for (const DNACMDL::Mesh& mesh : meshes) - secCount += mesh.surfaces.size(); - - /* Header */ - Header head = {}; - head.magic = 0xDEADBEEF; - head.version = pc ? 0x1000F : 0xF; - if (xf) - { - head.localToWorldMtx[0] = xf->val[0]; - head.localToWorldMtx[1] = xf->val[1]; - head.localToWorldMtx[2] = xf->val[2]; - } - else - { - head.localToWorldMtx[0].simd[0] = 1.f; - head.localToWorldMtx[1].simd[1] = 1.f; - head.localToWorldMtx[2].simd[2] = 1.f; - } - head.meshCount = meshes.size(); - head.geomSecIdx = 0; - head.arotSecIdx = secCount++; - head.sclySecIdx = secCount++; - head.collisionSecIdx = secCount++; - head.unkSecIdx = secCount++; - head.lightSecIdx = secCount++; - head.visiSecIdx = secCount++; - head.pathSecIdx = secCount++; - head.secCount = secCount; - - std::vector> secs; - secs.reserve(secCount + 2); - - /* Header section */ - { - size_t secSz = 0; - head.binarySize(secSz); - secs.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); - head.write(w); - int i = w.position(); - int end = ROUND_UP_32(i); - for (; i meshAabbs; - meshAabbs.reserve(meshes.size()); - - /* Models */ - if (pc) - { - if (!DNACMDL::WriteHMDLMREASecs - (secs, inPath, meshes, fullAabb, meshAabbs)) - return false; - } - else - { - if (!DNACMDL::WriteMREASecs - (secs, inPath, meshes, fullAabb, meshAabbs)) - return false; - } - - /* AROT */ - { - AROTBuilder arotBuilder; - arotBuilder.build(secs, fullAabb, meshAabbs, meshes); + /* Collision */ + { + DeafBabe collision = {}; + DeafBabeBuildFromBlender(collision, cMesh); #if DUMP_OCTREE - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".octree.blend"), true), hecl::blender::BlendType::Area)) - return false; + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".coctree.blend"), true), hecl::blender::BlendType::Area)) + return false; - /* Open Py Stream and read sections */ - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "from mathutils import Vector\n" - "\n" - "bpy.context.scene.name = '%s'\n", - inPath.getLastComponentUTF8().data()); + /* Open Py Stream and read sections */ + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os.format( + "import bpy\n" + "import bmesh\n" + "from mathutils import Vector\n" + "\n" + "bpy.context.scene.name = '%s'\n", + inPath.getLastComponentUTF8().data()); - athena::io::MemoryReader reader(secs.back().data(), secs.back().size()); - reader.readUint32Big(); - reader.readUint32Big(); - u32 numMeshBitmaps = reader.readUint32Big(); - u32 meshBitCount = reader.readUint32Big(); - u32 numNodes = reader.readUint32Big(); - auto aabbMin = reader.readVec3fBig(); - auto aabbMax = reader.readVec3fBig(); - reader.seekAlign32(); - reader.seek(ROUND_UP_32(meshBitCount) / 8 * numMeshBitmaps + numNodes * 4); - zeus::CAABox arotAABB(aabbMin, aabbMax); - OutputOctreeNode(os, reader, arotAABB); + athena::io::MemoryReader reader(collision.bspTree.get(), collision.bspSize); + zeus::CAABox colAABB(collision.aabb[0], collision.aabb[1]); + OutputOctreeNode(os, reader, collision.rootNodeType, colAABB); - os.centerView(); - os.close(); - conn.saveBlend(); -#endif - } - - /* SCLY */ - DNAMP1::SCLY sclyData = {}; - { - sclyData.fourCC = 'SCLY'; - sclyData.version = 1; - for (const hecl::ProjectPath& layer : layerScriptPaths) - { - athena::io::FileReader freader(layer.getAbsolutePath()); - if (!freader.isOpen()) - continue; - if (!athena::io::ValidateFromYAMLStream(freader)) - continue; - - athena::io::YAMLDocReader reader; - if (!reader.parse(&freader)) - continue; - - sclyData.layers.emplace_back(); - sclyData.layers.back().read(reader); - size_t layerSize = 0; - sclyData.layers.back().binarySize(layerSize); - sclyData.layerSizes.push_back(layerSize); - } - sclyData.layerCount = sclyData.layers.size(); - - size_t secSz = 0; - sclyData.binarySize(secSz); - secs.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); - sclyData.write(w); - } - - - /* Collision */ - { - DeafBabe collision = {}; - DeafBabeBuildFromBlender(collision, cMesh); - -#if DUMP_OCTREE - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(inPath.getWithExtension(_SYS_STR(".coctree.blend"), true), hecl::blender::BlendType::Area)) - return false; - - /* Open Py Stream and read sections */ - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "from mathutils import Vector\n" - "\n" - "bpy.context.scene.name = '%s'\n", - inPath.getLastComponentUTF8().data()); - - athena::io::MemoryReader reader(collision.bspTree.get(), collision.bspSize); - zeus::CAABox colAABB(collision.aabb[0], collision.aabb[1]); - OutputOctreeNode(os, reader, collision.rootNodeType, colAABB); - - os.centerView(); - os.close(); - conn.saveBlend(); + os.centerView(); + os.close(); + conn.saveBlend(); #endif - size_t secSz = 0; - collision.binarySize(secSz); - secs.emplace_back(secSz, 0); - athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); - collision.write(w); - } + size_t secSz = 0; + collision.binarySize(secSz); + secs.emplace_back(secSz, 0); + athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); + collision.write(w); + } - /* Unk */ - { - secs.emplace_back(8, 0); - athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); - w.writeUint32Big(1); - } + /* Unk */ + { + secs.emplace_back(8, 0); + athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); + w.writeUint32Big(1); + } - /* Lights */ - std::vector lightsVisi[2]; - { - int actualCounts[2] = {}; - for (const Light& l : lights) - if (l.layer == 0 || l.layer == 1) - ++actualCounts[l.layer]; - lightsVisi[0].reserve(actualCounts[0]); - lightsVisi[1].reserve(actualCounts[1]); + /* Lights */ + std::vector lightsVisi[2]; + { + int actualCounts[2] = {}; + for (const Light& l : lights) + if (l.layer == 0 || l.layer == 1) + ++actualCounts[l.layer]; + lightsVisi[0].reserve(actualCounts[0]); + lightsVisi[1].reserve(actualCounts[1]); - secs.emplace_back(12 + 65 * (actualCounts[0] + actualCounts[1]), 0); - athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); - w.writeUint32Big(0xBABEDEAD); + secs.emplace_back(12 + 65 * (actualCounts[0] + actualCounts[1]), 0); + athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); + w.writeUint32Big(0xBABEDEAD); - for (int lay=0 ; lay<2 ; ++lay) - { - int lightCount = 0; - for (const Light& l : lights) - { - if (l.layer == lay) - ++lightCount; - } - w.writeUint32Big(lightCount); - for (const Light& l : lights) - { - if (l.layer == lay) - { - BabeDeadLight light = {}; - WriteBabeDeadLightFromBlender(light, l); - light.write(w); - lightsVisi[l.layer].push_back(light.position); - } - } + for (int lay = 0; lay < 2; ++lay) { + int lightCount = 0; + for (const Light& l : lights) { + if (l.layer == lay) + ++lightCount; + } + w.writeUint32Big(lightCount); + for (const Light& l : lights) { + if (l.layer == lay) { + BabeDeadLight light = {}; + WriteBabeDeadLightFromBlender(light, l); + light.write(w); + lightsVisi[l.layer].push_back(light.position); } + } } + } - /* VISI */ - hecl::ProjectPath visiMetadataPath(areaDirPath, _SYS_STR("!visi.yaml")); - bool visiGood = false; - if (visiMetadataPath.isFile()) - { - athena::io::FileReader visiReader(visiMetadataPath.getAbsolutePath()); - athena::io::YAMLDocReader r; - if (r.parse(&visiReader)) - { - size_t entityCount; - std::vector> entities; - if (auto __vec = r.enterSubVector("entities", entityCount)) - { - entities.reserve(entityCount); - for (size_t i=0 ; i& obj : layer.objects) - { - if ((obj->id & ~0x03FF0000) == entityId) - { - zeus::CAABox entAABB = obj->getVISIAABB(btok); - if (!entAABB.invalid()) - entities.emplace_back(entityId, entAABB); - } - } - } - } + /* VISI */ + hecl::ProjectPath visiMetadataPath(areaDirPath, _SYS_STR("!visi.yaml")); + bool visiGood = false; + if (visiMetadataPath.isFile()) { + athena::io::FileReader visiReader(visiMetadataPath.getAbsolutePath()); + athena::io::YAMLDocReader r; + if (r.parse(&visiReader)) { + size_t entityCount; + std::vector> entities; + if (auto __vec = r.enterSubVector("entities", entityCount)) { + entities.reserve(entityCount); + for (size_t i = 0; i < entityCount; ++i) { + uint32_t entityId = r.readUint32(nullptr); + for (const SCLY::ScriptLayer& layer : sclyData.layers) { + for (const std::unique_ptr& obj : layer.objects) { + if ((obj->id & ~0x03FF0000) == entityId) { + zeus::CAABox entAABB = obj->getVISIAABB(btok); + if (!entAABB.invalid()) + entities.emplace_back(entityId, entAABB); + } } + } + } + } - // Check if pre-generated visi exists, recycle if able - hecl::ProjectPath preVisiPath = inPath.getWithExtension(_SYS_STR(".visi"), true); - if (preVisiPath.getPathType() == hecl::ProjectPath::Type::File) - { - athena::io::FileReader preVisiReader(preVisiPath.getAbsolutePath()); - atUint64 preVisiLen = preVisiReader.length(); - if (preVisiLen > 26) - { - auto preVisiData = preVisiReader.readUBytes(preVisiLen); - athena::io::MemoryReader preVisiDataReader(preVisiData.get(), preVisiLen); + // Check if pre-generated visi exists, recycle if able + hecl::ProjectPath preVisiPath = inPath.getWithExtension(_SYS_STR(".visi"), true); + if (preVisiPath.getPathType() == hecl::ProjectPath::Type::File) { + athena::io::FileReader preVisiReader(preVisiPath.getAbsolutePath()); + atUint64 preVisiLen = preVisiReader.length(); + if (preVisiLen > 26) { + auto preVisiData = preVisiReader.readUBytes(preVisiLen); + athena::io::MemoryReader preVisiDataReader(preVisiData.get(), preVisiLen); - atUint32 preVisiFourCC = preVisiDataReader.readUint32Big(); - atUint32 preVisiVersion = preVisiDataReader.readUint32Big(); - preVisiDataReader.readBool(); - preVisiDataReader.readBool(); - atUint32 preFeatureCount = preVisiDataReader.readUint32Big(); - atUint32 preLightsCount = preVisiDataReader.readUint32Big(); - atUint32 preLayer2LightCount = preVisiDataReader.readUint32Big(); - atUint32 preEntityCount = preVisiDataReader.readUint32Big(); + atUint32 preVisiFourCC = preVisiDataReader.readUint32Big(); + atUint32 preVisiVersion = preVisiDataReader.readUint32Big(); + preVisiDataReader.readBool(); + preVisiDataReader.readBool(); + atUint32 preFeatureCount = preVisiDataReader.readUint32Big(); + atUint32 preLightsCount = preVisiDataReader.readUint32Big(); + atUint32 preLayer2LightCount = preVisiDataReader.readUint32Big(); + atUint32 preEntityCount = preVisiDataReader.readUint32Big(); - if (preVisiFourCC == 'VISI' && preVisiVersion == 2 && - preFeatureCount == meshes.size() + entities.size() && - preLightsCount == lightsVisi[0].size() + lightsVisi[1].size() && - preLayer2LightCount == lightsVisi[1].size() && - preEntityCount == entities.size()) - { - secs.emplace_back(preVisiLen, 0); - memcpy(secs.back().data(), preVisiData.get(), preVisiLen); - visiGood = true; - } - } - } + if (preVisiFourCC == 'VISI' && preVisiVersion == 2 && preFeatureCount == meshes.size() + entities.size() && + preLightsCount == lightsVisi[0].size() + lightsVisi[1].size() && + preLayer2LightCount == lightsVisi[1].size() && preEntityCount == entities.size()) { + secs.emplace_back(preVisiLen, 0); + memcpy(secs.back().data(), preVisiData.get(), preVisiLen); + visiGood = true; + } + } + } #if !WINDOWS_STORE - if (!visiGood) - { - hecl::ProjectPath visiIntOut = outPath.getWithExtension(_SYS_STR(".visiint")); - athena::io::FileWriter w(visiIntOut.getAbsolutePath()); - w.writeUint32Big(meshes.size()); - for (const DNACMDL::Mesh& mesh : meshes) - { - w.writeUint32Big(uint32_t(mesh.topology)); + if (!visiGood) { + hecl::ProjectPath visiIntOut = outPath.getWithExtension(_SYS_STR(".visiint")); + athena::io::FileWriter w(visiIntOut.getAbsolutePath()); + w.writeUint32Big(meshes.size()); + for (const DNACMDL::Mesh& mesh : meshes) { + w.writeUint32Big(uint32_t(mesh.topology)); - w.writeUint32Big(mesh.pos.size()); - for (const auto& v : mesh.pos) - { - atVec3f xfPos = hecl::blender::MtxVecMul4RM(mesh.sceneXf, v); - w.writeVec3fBig(xfPos); - } + w.writeUint32Big(mesh.pos.size()); + for (const auto& v : mesh.pos) { + atVec3f xfPos = hecl::blender::MtxVecMul4RM(mesh.sceneXf, v); + w.writeVec3fBig(xfPos); + } - w.writeUint32Big(mesh.surfaces.size()); - for (const DNACMDL::Mesh::Surface& surf : mesh.surfaces) - { - w.writeUint32Big(surf.verts.size()); - for (const DNACMDL::Mesh::Surface::Vert& vert : surf.verts) - w.writeUint32Big(vert.iPos); - const DNACMDL::Material& mat = mesh.materialSets[0][surf.materialIdx]; - w.writeBool(mat.transparent); - } - } + w.writeUint32Big(mesh.surfaces.size()); + for (const DNACMDL::Mesh::Surface& surf : mesh.surfaces) { + w.writeUint32Big(surf.verts.size()); + for (const DNACMDL::Mesh::Surface::Vert& vert : surf.verts) + w.writeUint32Big(vert.iPos); + const DNACMDL::Material& mat = mesh.materialSets[0][surf.materialIdx]; + w.writeBool(mat.transparent); + } + } - w.writeUint32Big(entities.size()); - for (const auto& ent : entities) - { - w.writeUint32Big(ent.first); - w.writeVec3fBig(ent.second.min); - w.writeVec3fBig(ent.second.max); - } + w.writeUint32Big(entities.size()); + for (const auto& ent : entities) { + w.writeUint32Big(ent.first); + w.writeVec3fBig(ent.second.min); + w.writeVec3fBig(ent.second.max); + } - w.writeUint32Big(lightsVisi[0].size() + lightsVisi[1].size()); - w.writeUint32Big(lightsVisi[1].size()); - for (const auto& light : lightsVisi[1]) - w.writeVec3fBig(light); - for (const auto& light : lightsVisi[0]) - w.writeVec3fBig(light); + w.writeUint32Big(lightsVisi[0].size() + lightsVisi[1].size()); + w.writeUint32Big(lightsVisi[1].size()); + for (const auto& light : lightsVisi[1]) + w.writeVec3fBig(light); + for (const auto& light : lightsVisi[0]) + w.writeVec3fBig(light); - w.close(); + w.close(); - hecl::SystemString VisiGenPath = ExeDir + _SYS_STR("/visigen"); + hecl::SystemString VisiGenPath = ExeDir + _SYS_STR("/visigen"); #if _WIN32 - VisiGenPath += _SYS_STR(".exe"); + VisiGenPath += _SYS_STR(".exe"); #endif - hecl::SystemChar thrIdx[16]; - hecl::SNPrintf(thrIdx, 16, _SYS_STR("%d"), hecl::ClientProcess::GetThreadWorkerIdx()); - hecl::SystemChar parPid[32]; + hecl::SystemChar thrIdx[16]; + hecl::SNPrintf(thrIdx, 16, _SYS_STR("%d"), hecl::ClientProcess::GetThreadWorkerIdx()); + hecl::SystemChar parPid[32]; #if _WIN32 - hecl::SNPrintf(parPid, 32, _SYS_STR("%lluX"), reinterpret_cast(GetCurrentProcess())); + hecl::SNPrintf(parPid, 32, _SYS_STR("%lluX"), reinterpret_cast(GetCurrentProcess())); #else - hecl::SNPrintf(parPid, 32, _SYS_STR("%lluX"), (unsigned long long)getpid()); + hecl::SNPrintf(parPid, 32, _SYS_STR("%lluX"), (unsigned long long)getpid()); #endif - const hecl::SystemChar* args[] = {VisiGenPath.c_str(), - visiIntOut.getAbsolutePath().data(), - preVisiPath.getAbsolutePath().data(), - thrIdx, parPid, nullptr}; - if (0 == hecl::RunProcess(VisiGenPath.c_str(), args)) - { - athena::io::FileReader r(preVisiPath.getAbsolutePath()); - size_t length = r.length(); - secs.emplace_back(length, 0); - r.readBytesToBuf(secs.back().data(), length); - visiGood = true; - } - else - { - Log.report(logvisor::Fatal, _SYS_STR("Unable to launch %s"), VisiGenPath.c_str()); - } - } + const hecl::SystemChar* args[] = {VisiGenPath.c_str(), + visiIntOut.getAbsolutePath().data(), + preVisiPath.getAbsolutePath().data(), + thrIdx, + parPid, + nullptr}; + if (0 == hecl::RunProcess(VisiGenPath.c_str(), args)) { + athena::io::FileReader r(preVisiPath.getAbsolutePath()); + size_t length = r.length(); + secs.emplace_back(length, 0); + r.readBytesToBuf(secs.back().data(), length); + visiGood = true; + } else { + Log.report(logvisor::Fatal, _SYS_STR("Unable to launch %s"), VisiGenPath.c_str()); + } + } #endif - } } - if (!visiGood) - secs.emplace_back(4, 0); + } + if (!visiGood) + secs.emplace_back(4, 0); - /* PATH */ - { - hecl::ProjectPath pathPath(inPath.getParentPath(), _SYS_STR("!path.blend")); - UniqueID32 pathId = pathPath; - secs.emplace_back(4, 0); - athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); - pathId.write(w); + /* PATH */ + { + hecl::ProjectPath pathPath(inPath.getParentPath(), _SYS_STR("!path.blend")); + UniqueID32 pathId = pathPath; + secs.emplace_back(4, 0); + athena::io::MemoryWriter w(secs.back().data(), secs.back().size()); + pathId.write(w); + } + + /* Assemble sizes and add padding */ + { + std::vector& sizesSec = secs[1]; + sizesSec.assign((((head.secCount) + 7) & ~7) * 4, 0); + athena::io::MemoryWriter w(sizesSec.data(), sizesSec.size()); + for (auto it = secs.begin() + 2; it != secs.end(); ++it) { + std::vector& sec = *it; + int i = sec.size(); + int end = ROUND_UP_32(i); + sec.resize(end); + w.writeUint32Big(end); } + } - /* Assemble sizes and add padding */ - { - std::vector& sizesSec = secs[1]; - sizesSec.assign((((head.secCount) + 7) & ~7) * 4, 0); - athena::io::MemoryWriter w(sizesSec.data(), sizesSec.size()); - for (auto it = secs.begin() + 2 ; it != secs.end() ; ++it) - { - std::vector& sec = *it; - int i = sec.size(); - int end = ROUND_UP_32(i); - sec.resize(end); - w.writeUint32Big(end); - } - } + /* Output all padded sections to file */ + athena::io::FileWriter writer(outPath.getAbsolutePath()); + for (const std::vector& sec : secs) + writer.writeUBytes(sec.data(), sec.size()); - /* Output all padded sections to file */ - athena::io::FileWriter writer(outPath.getAbsolutePath()); - for (const std::vector& sec : secs) - writer.writeUBytes(sec.data(), sec.size()); - - return true; + return true; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/MREA.hpp b/DataSpec/DNAMP1/MREA.hpp index 93584a227..d02722e4d 100644 --- a/DataSpec/DNAMP1/MREA.hpp +++ b/DataSpec/DNAMP1/MREA.hpp @@ -4,134 +4,110 @@ #include "CMDLMaterials.hpp" #include "CSKR.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct MREA -{ - struct Header : BigDNA - { - AT_DECL_DNA - Value magic; - Value version; - Value localToWorldMtx[3]; - Value meshCount; - Value secCount; - Value geomSecIdx; - Value sclySecIdx; - Value collisionSecIdx; - Value unkSecIdx; - Value lightSecIdx; - Value visiSecIdx; - Value pathSecIdx; - Value arotSecIdx; - Vector secSizes; - }; +struct MREA { + struct Header : BigDNA { + AT_DECL_DNA + Value magic; + Value version; + Value localToWorldMtx[3]; + Value meshCount; + Value secCount; + Value geomSecIdx; + Value sclySecIdx; + Value collisionSecIdx; + Value unkSecIdx; + Value lightSecIdx; + Value visiSecIdx; + Value pathSecIdx; + Value arotSecIdx; + Vector secSizes; + }; - struct MeshHeader : BigDNA - { - AT_DECL_DNA - struct VisorFlags : BigDNA - { - AT_DECL_DNA - Value flags; - enum class ThermalLevel - { - Cool, - Hot, - Warm - }; - static const char* GetThermalLevelStr(ThermalLevel t) - { - switch (t) - { - case ThermalLevel::Cool: return "COOL"; - case ThermalLevel::Hot: return "HOT"; - case ThermalLevel::Warm: return "WARM"; - default: break; - } - return nullptr; - } - bool disableEnviro() const {return flags >> 1 & 0x1;} - void setDisableEnviro(bool v) {flags &= ~0x2; flags |= v << 1;} - bool disableThermal() const {return flags >> 2 & 0x1;} - void setDisableThermal(bool v) {flags &= ~0x4; flags |= v << 2;} - bool disableXray() const {return flags >> 3 & 0x1;} - void setDisableXray(bool v) {flags &= ~0x8; flags |= v << 3;} - ThermalLevel thermalLevel() const {return ThermalLevel(flags >> 4 & 0x3);} - void setThermalLevel(ThermalLevel v) {flags &= ~0x30; flags |= atUint32(v) << 4;} - const char* thermalLevelStr() const {return GetThermalLevelStr(thermalLevel());} - void setFromBlenderProps(const std::unordered_map& props); - } visorFlags; - Value xfMtx[3]; - Value aabb[2]; - }; + struct MeshHeader : BigDNA { + AT_DECL_DNA + struct VisorFlags : BigDNA { + AT_DECL_DNA + Value flags; + enum class ThermalLevel { Cool, Hot, Warm }; + static const char* GetThermalLevelStr(ThermalLevel t) { + switch (t) { + case ThermalLevel::Cool: + return "COOL"; + case ThermalLevel::Hot: + return "HOT"; + case ThermalLevel::Warm: + return "WARM"; + default: + break; + } + return nullptr; + } + bool disableEnviro() const { return flags >> 1 & 0x1; } + void setDisableEnviro(bool v) { + flags &= ~0x2; + flags |= v << 1; + } + bool disableThermal() const { return flags >> 2 & 0x1; } + void setDisableThermal(bool v) { + flags &= ~0x4; + flags |= v << 2; + } + bool disableXray() const { return flags >> 3 & 0x1; } + void setDisableXray(bool v) { + flags &= ~0x8; + flags |= v << 3; + } + ThermalLevel thermalLevel() const { return ThermalLevel(flags >> 4 & 0x3); } + void setThermalLevel(ThermalLevel v) { + flags &= ~0x30; + flags |= atUint32(v) << 4; + } + const char* thermalLevelStr() const { return GetThermalLevelStr(thermalLevel()); } + void setFromBlenderProps(const std::unordered_map& props); + } visorFlags; + Value xfMtx[3]; + Value aabb[2]; + }; - struct BabeDeadLight : BigDNA - { - AT_DECL_DNA - enum class LightType : atUint32 - { - LocalAmbient, - Directional, - Custom, - Spot, - Spot2, - LocalAmbient2 - }; - enum class Falloff : atUint32 - { - Constant, - Linear, - Quadratic - }; - Value lightType; - Value color; - Value position; - Value direction; - Value q; - Value spotCutoff; - Value unk5; - Value castShadows; - Value unk7; - Value falloff; - Value unk9; - }; + struct BabeDeadLight : BigDNA { + AT_DECL_DNA + enum class LightType : atUint32 { LocalAmbient, Directional, Custom, Spot, Spot2, LocalAmbient2 }; + enum class Falloff : atUint32 { Constant, Linear, Quadratic }; + Value lightType; + Value color; + Value position; + Value direction; + Value q; + Value spotCutoff; + Value unk5; + Value castShadows; + Value unk7; + Value falloff; + Value unk9; + }; - static void ReadBabeDeadToBlender_1_2(hecl::blender::PyOutStream& os, - athena::io::IStreamReader& rs); + static void ReadBabeDeadToBlender_1_2(hecl::blender::PyOutStream& os, athena::io::IStreamReader& rs); - static void AddCMDLRigPairs(PAKEntryReadStream& rs, - PAKRouter& pakRouter, CharacterAssociations& charAssoc); + static void AddCMDLRigPairs(PAKEntryReadStream& rs, PAKRouter& pakRouter, + CharacterAssociations& charAssoc); - static UniqueID32 GetPATHId(PAKEntryReadStream& rs); + static UniqueID32 GetPATHId(PAKEntryReadStream& rs); - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool, - hecl::blender::Token& btok, - std::function); + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool, hecl::blender::Token& btok, + std::function); - static void Name(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - PAKRouter& pakRouter, - PAK::Entry& entry); + static void Name(const SpecBase& dataSpec, PAKEntryReadStream& rs, PAKRouter& pakRouter, + PAK::Entry& entry); - using ColMesh = hecl::blender::ColMesh; - using Light = hecl::blender::Light; + using ColMesh = hecl::blender::ColMesh; + using Light = hecl::blender::Light; - static bool Cook(const hecl::ProjectPath& outPath, - const hecl::ProjectPath& inPath, - const std::vector& meshes, - const ColMesh& cMesh, - const std::vector& lights, - hecl::blender::Token& btok, - const hecl::blender::Matrix4f* xf, - bool pc); + static bool Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPath, + const std::vector& meshes, const ColMesh& cMesh, const std::vector& lights, + hecl::blender::Token& btok, const hecl::blender::Matrix4f* xf, bool pc); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/MazeSeeds.hpp b/DataSpec/DNAMP1/MazeSeeds.hpp index 76c03d8c3..d3826b357 100644 --- a/DataSpec/DNAMP1/MazeSeeds.hpp +++ b/DataSpec/DNAMP1/MazeSeeds.hpp @@ -4,12 +4,9 @@ #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ -struct MazeSeeds : BigDNA -{ - AT_DECL_DNA_YAML - Value seeds[300]; +namespace DataSpec::DNAMP1 { +struct MazeSeeds : BigDNA { + AT_DECL_DNA_YAML + Value seeds[300]; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/PAK.cpp b/DataSpec/DNAMP1/PAK.cpp index 3f9791b76..266e15060 100644 --- a/DataSpec/DNAMP1/PAK.cpp +++ b/DataSpec/DNAMP1/PAK.cpp @@ -4,208 +4,179 @@ #include "PAK.hpp" #include "AGSC.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template <> -void PAK::Enumerate(typename Read::StreamT& reader) -{ - atUint32 version = reader.readUint32Big(); - if (version != 0x00030005) - Log.report(logvisor::Fatal, "unexpected PAK magic"); - reader.readUint32Big(); +void PAK::Enumerate(typename Read::StreamT& reader) { + atUint32 version = reader.readUint32Big(); + if (version != 0x00030005) + Log.report(logvisor::Fatal, "unexpected PAK magic"); + reader.readUint32Big(); - atUint32 nameCount = reader.readUint32Big(); - m_nameEntries.clear(); - m_nameEntries.reserve(nameCount); - for (atUint32 n=0 ; n entries; + entries.reserve(count); + for (atUint32 e = 0; e < count; ++e) { + entries.emplace_back(); + entries.back().read(reader); + } + for (atUint32 e = 0; e < count; ++e) { + Entry& entry = entries[e]; + if (entry.compressed && m_useLzo) + entry.compressed = 2; + + auto search = m_entries.find(entry.id); + if (search == m_entries.end()) { + m_firstEntries.push_back(entry.id); + m_entries[entry.id] = std::move(entry); + } else { + /* Find next MREA to record which area has dupes */ + for (atUint32 e2 = e + 1; e2 < count; ++e2) { + Entry& entry2 = entries[e2]; + if (entry2.type != FOURCC('MREA')) + continue; + m_dupeMREAs.insert(entry2.id); + break; + } } + } - atUint32 count = reader.readUint32Big(); - m_entries.clear(); - m_entries.reserve(count); - m_firstEntries.clear(); - m_firstEntries.reserve(count); - std::vector entries; - entries.reserve(count); - for (atUint32 e=0 ; e -void PAK::Enumerate(typename Write::StreamT& writer) -{ - writer.writeUint32Big(0x00030005); - writer.writeUint32Big(0); +void PAK::Enumerate(typename Write::StreamT& writer) { + writer.writeUint32Big(0x00030005); + writer.writeUint32Big(0); - writer.writeUint32Big((atUint32)m_nameEntries.size()); - for (const NameEntry& entry : m_nameEntries) - { - NameEntry copy = entry; - copy.nameLen = copy.name.size(); - copy.write(writer); - } + writer.writeUint32Big((atUint32)m_nameEntries.size()); + for (const NameEntry& entry : m_nameEntries) { + NameEntry copy = entry; + copy.nameLen = copy.name.size(); + copy.write(writer); + } - writer.writeUint32Big(m_entries.size()); - for (const auto& entry : m_entries) - { - Entry tmp = entry.second; - if (tmp.compressed) - tmp.compressed = 1; - tmp.write(writer); - } + writer.writeUint32Big(m_entries.size()); + for (const auto& entry : m_entries) { + Entry tmp = entry.second; + if (tmp.compressed) + tmp.compressed = 1; + tmp.write(writer); + } } template <> -void PAK::Enumerate(typename BinarySize::StreamT& s) -{ - s += 12; +void PAK::Enumerate(typename BinarySize::StreamT& s) { + s += 12; - for (const NameEntry& entry : m_nameEntries) - s += 12 + entry.name.size(); + for (const NameEntry& entry : m_nameEntries) + s += 12 + entry.name.size(); - s += m_entries.size() * 20 + 4; + s += m_entries.size() * 20 + 4; } -std::unique_ptr -PAK::Entry::getBuffer(const nod::Node& pak, atUint64& szOut) const -{ - if (compressed) - { - std::unique_ptr strm = pak.beginReadStream(offset); +std::unique_ptr PAK::Entry::getBuffer(const nod::Node& pak, atUint64& szOut) const { + if (compressed) { + std::unique_ptr strm = pak.beginReadStream(offset); - atUint32 decompSz; - strm->read(&decompSz, 4); - decompSz = hecl::SBig(decompSz); - atUint8* buf = new atUint8[decompSz]; - atUint8* bufCur = buf; + atUint32 decompSz; + strm->read(&decompSz, 4); + decompSz = hecl::SBig(decompSz); + atUint8* buf = new atUint8[decompSz]; + atUint8* bufCur = buf; - atUint8 compBuf[0x8000]; - if (compressed == 1) - { - atUint32 compRem = size - 4; - z_stream zs = {}; - inflateInit(&zs); - zs.avail_out = decompSz; - zs.next_out = buf; - while (zs.avail_out) - { - atUint64 readSz = strm->read(compBuf, std::min(compRem, atUint32(0x8000))); - compRem -= readSz; - zs.avail_in = readSz; - zs.next_in = compBuf; - inflate(&zs, Z_FINISH); - } - inflateEnd(&zs); - } - else - { - atUint32 rem = decompSz; - while (rem) - { - atUint16 chunkSz; - strm->read(&chunkSz, 2); - chunkSz = hecl::SBig(chunkSz); - strm->read(compBuf, chunkSz); - lzo_uint dsz = rem; - lzo1x_decompress(compBuf, chunkSz, bufCur, &dsz, nullptr); - bufCur += dsz; - rem -= dsz; - } - } - - szOut = decompSz; - return std::unique_ptr(buf); - } - else - { - atUint8* buf = new atUint8[size]; - pak.beginReadStream(offset)->read(buf, size); - szOut = size; - return std::unique_ptr(buf); - } -} - -const PAK::Entry* PAK::lookupEntry(const UniqueID32& id) const -{ - auto result = m_entries.find(id); - if (result != m_entries.end()) - return &result->second; - return nullptr; -} - -const PAK::Entry* PAK::lookupEntry(std::string_view name) const -{ - auto result = m_nameMap.find(name.data()); - if (result != m_nameMap.end()) - { - auto result1 = m_entries.find(result->second); - if (result1 != m_entries.end()) - return &result1->second; - } - return nullptr; -} - -std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const -{ - std::unordered_map::const_iterator search; - if (entry.type == FOURCC('AGSC') && (search = m_entries.find(entry.id)) != m_entries.cend()) - { - /* Use internal AGSC name for entry */ - auto rs = search->second.beginReadStream(pakNode); - AGSC::Header header; - header.read(rs); - named = true; - return header.groupName; + atUint8 compBuf[0x8000]; + if (compressed == 1) { + atUint32 compRem = size - 4; + z_stream zs = {}; + inflateInit(&zs); + zs.avail_out = decompSz; + zs.next_out = buf; + while (zs.avail_out) { + atUint64 readSz = strm->read(compBuf, std::min(compRem, atUint32(0x8000))); + compRem -= readSz; + zs.avail_in = readSz; + zs.next_in = compBuf; + inflate(&zs, Z_FINISH); + } + inflateEnd(&zs); + } else { + atUint32 rem = decompSz; + while (rem) { + atUint16 chunkSz; + strm->read(&chunkSz, 2); + chunkSz = hecl::SBig(chunkSz); + strm->read(compBuf, chunkSz); + lzo_uint dsz = rem; + lzo1x_decompress(compBuf, chunkSz, bufCur, &dsz, nullptr); + bufCur += dsz; + rem -= dsz; + } } - /* Prefer named entries first */ - for (const NameEntry& nentry : m_nameEntries) - if (nentry.id == entry.id) - { - named = true; - return nentry.name; - } - - /* Otherwise return ID format string */ - named = false; - return entry.type.toString() + '_' + entry.id.toString(); + szOut = decompSz; + return std::unique_ptr(buf); + } else { + atUint8* buf = new atUint8[size]; + pak.beginReadStream(offset)->read(buf, size); + szOut = size; + return std::unique_ptr(buf); + } } +const PAK::Entry* PAK::lookupEntry(const UniqueID32& id) const { + auto result = m_entries.find(id); + if (result != m_entries.end()) + return &result->second; + return nullptr; } + +const PAK::Entry* PAK::lookupEntry(std::string_view name) const { + auto result = m_nameMap.find(name.data()); + if (result != m_nameMap.end()) { + auto result1 = m_entries.find(result->second); + if (result1 != m_entries.end()) + return &result1->second; + } + return nullptr; +} + +std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const { + std::unordered_map::const_iterator search; + if (entry.type == FOURCC('AGSC') && (search = m_entries.find(entry.id)) != m_entries.cend()) { + /* Use internal AGSC name for entry */ + auto rs = search->second.beginReadStream(pakNode); + AGSC::Header header; + header.read(rs); + named = true; + return header.groupName; + } + + /* Prefer named entries first */ + for (const NameEntry& nentry : m_nameEntries) + if (nentry.id == entry.id) { + named = true; + return nentry.name; + } + + /* Otherwise return ID format string */ + named = false; + return entry.type.toString() + '_' + entry.id.toString(); +} + +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/PAK.hpp b/DataSpec/DNAMP1/PAK.hpp index 12becbfa3..eef8938fa 100644 --- a/DataSpec/DNAMP1/PAK.hpp +++ b/DataSpec/DNAMP1/PAK.hpp @@ -5,60 +5,53 @@ #include #include "DataSpec/DNACommon/PAK.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct PAK : BigDNA -{ - bool m_useLzo; - bool m_noShare; - PAK(bool useLzo, bool noShare) : m_useLzo(useLzo), m_noShare(noShare) {} - AT_DECL_EXPLICIT_DNA +struct PAK : BigDNA { + bool m_useLzo; + bool m_noShare; + PAK(bool useLzo, bool noShare) : m_useLzo(useLzo), m_noShare(noShare) {} + AT_DECL_EXPLICIT_DNA - struct NameEntry : BigDNA - { - AT_DECL_DNA - DNAFourCC type; - UniqueID32 id; - Value nameLen; - String name; - }; + struct NameEntry : BigDNA { + AT_DECL_DNA + DNAFourCC type; + UniqueID32 id; + Value nameLen; + String name; + }; - struct Entry : BigDNA - { - AT_DECL_DNA - Value compressed; - DNAFourCC type; - UniqueID32 id; - Value size; - Value offset; - UniqueResult unique; - std::string name; /* backreferencing name for RE purposes */ + struct Entry : BigDNA { + AT_DECL_DNA + Value compressed; + DNAFourCC type; + UniqueID32 id; + Value size; + Value offset; + UniqueResult unique; + std::string name; /* backreferencing name for RE purposes */ - std::unique_ptr getBuffer(const nod::Node& pak, atUint64& szOut) const; - inline PAKEntryReadStream beginReadStream(const nod::Node& pak, atUint64 off=0) const - { - atUint64 sz; - std::unique_ptr buf = getBuffer(pak, sz); - return PAKEntryReadStream(std::move(buf), sz, off); - } - }; + std::unique_ptr getBuffer(const nod::Node& pak, atUint64& szOut) const; + inline PAKEntryReadStream beginReadStream(const nod::Node& pak, atUint64 off = 0) const { + atUint64 sz; + std::unique_ptr buf = getBuffer(pak, sz); + return PAKEntryReadStream(std::move(buf), sz, off); + } + }; - std::vector m_nameEntries; - std::unordered_map m_entries; - std::vector m_firstEntries; - std::unordered_map m_nameMap; - std::unordered_set m_dupeMREAs; + std::vector m_nameEntries; + std::unordered_map m_entries; + std::vector m_firstEntries; + std::unordered_map m_nameMap; + std::unordered_set m_dupeMREAs; - const Entry* lookupEntry(const UniqueID32& id) const; - const Entry* lookupEntry(std::string_view name) const; - std::string bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const; + const Entry* lookupEntry(const UniqueID32& id) const; + const Entry* lookupEntry(std::string_view name) const; + std::string bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const; - bool mreaHasDupeResources(const UniqueID32& id) const - { return m_dupeMREAs.find(id) != m_dupeMREAs.cend(); } + bool mreaHasDupeResources(const UniqueID32& id) const { return m_dupeMREAs.find(id) != m_dupeMREAs.cend(); } - using IDType = UniqueID32; + using IDType = UniqueID32; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/PATH.cpp b/DataSpec/DNAMP1/PATH.cpp index f70a36c01..126c97b0c 100644 --- a/DataSpec/DNAMP1/PATH.cpp +++ b/DataSpec/DNAMP1/PATH.cpp @@ -3,88 +3,86 @@ #include "zeus/CAABox.hpp" #include "DataSpec/DNACommon/AROTBuilder.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, - const zeus::CMatrix4f* xf) -{ - /* Open Py Stream and read sections */ - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "from mathutils import Vector, Matrix\n" - "\n" - "bpy.types.Material.retro_path_idx_mask = bpy.props.IntProperty(name='Retro: Path Index Mask')\n" - "bpy.types.Material.retro_path_type_mask = bpy.props.IntProperty(name='Retro: Path Type Mask')\n" - "\n" - "material_dict = {}\n" - "material_index = []\n" - "def make_ground_material(idxMask):\n" - " mat = bpy.data.materials.new('Ground %%X' %% idxMask)\n" - " mat.diffuse_color = (0.8, 0.460, 0.194)\n" - " return mat\n" - "def make_flyer_material(idxMask):\n" - " mat = bpy.data.materials.new('Flyer %%X' %% idxMask)\n" - " mat.diffuse_color = (0.016, 0.8, 0.8)\n" - " return mat\n" - "def make_swimmer_material(idxMask):\n" - " mat = bpy.data.materials.new('Swimmer %%X' %% idxMask)\n" - " mat.diffuse_color = (0.074, 0.293, 0.8)\n" - " return mat\n" - "def select_material(meshIdxMask, meshTypeMask):\n" - " key = (meshIdxMask, meshTypeMask)\n" - " if key in material_index:\n" - " return material_index.index(key)\n" - " elif key in material_dict:\n" - " material_index.append(key)\n" - " return len(material_index)-1\n" - " else:\n" - " if meshTypeMask == 0x2:\n" - " mat = make_flyer_material(meshIdxMask)\n" - " elif meshTypeMask == 0x4:\n" - " mat = make_swimmer_material(meshIdxMask)\n" - " else:\n" - " mat = make_ground_material(meshIdxMask)\n" - " mat.retro_path_idx_mask = meshIdxMask\n" - " mat.retro_path_type_mask = meshTypeMask\n" - " material_dict[key] = mat\n" - " material_index.append(key)\n" - " return len(material_index)-1\n" - "\n" - "bpy.context.scene.name = '%s'\n" - "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "\n" - "bm = bmesh.new()\n" - "height_lay = bm.faces.layers.float.new('Height')\n", - entryName.data()); +void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf) { + /* Open Py Stream and read sections */ + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os.format( + "import bpy\n" + "import bmesh\n" + "from mathutils import Vector, Matrix\n" + "\n" + "bpy.types.Material.retro_path_idx_mask = bpy.props.IntProperty(name='Retro: Path Index Mask')\n" + "bpy.types.Material.retro_path_type_mask = bpy.props.IntProperty(name='Retro: Path Type Mask')\n" + "\n" + "material_dict = {}\n" + "material_index = []\n" + "def make_ground_material(idxMask):\n" + " mat = bpy.data.materials.new('Ground %%X' %% idxMask)\n" + " mat.diffuse_color = (0.8, 0.460, 0.194)\n" + " return mat\n" + "def make_flyer_material(idxMask):\n" + " mat = bpy.data.materials.new('Flyer %%X' %% idxMask)\n" + " mat.diffuse_color = (0.016, 0.8, 0.8)\n" + " return mat\n" + "def make_swimmer_material(idxMask):\n" + " mat = bpy.data.materials.new('Swimmer %%X' %% idxMask)\n" + " mat.diffuse_color = (0.074, 0.293, 0.8)\n" + " return mat\n" + "def select_material(meshIdxMask, meshTypeMask):\n" + " key = (meshIdxMask, meshTypeMask)\n" + " if key in material_index:\n" + " return material_index.index(key)\n" + " elif key in material_dict:\n" + " material_index.append(key)\n" + " return len(material_index)-1\n" + " else:\n" + " if meshTypeMask == 0x2:\n" + " mat = make_flyer_material(meshIdxMask)\n" + " elif meshTypeMask == 0x4:\n" + " mat = make_swimmer_material(meshIdxMask)\n" + " else:\n" + " mat = make_ground_material(meshIdxMask)\n" + " mat.retro_path_idx_mask = meshIdxMask\n" + " mat.retro_path_type_mask = meshTypeMask\n" + " material_dict[key] = mat\n" + " material_index.append(key)\n" + " return len(material_index)-1\n" + "\n" + "bpy.context.scene.name = '%s'\n" + "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " if ob.type != 'CAMERA':\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n" + "\n" + "bm = bmesh.new()\n" + "height_lay = bm.faces.layers.float.new('Height')\n", + entryName.data()); - for (const Node& n : nodes) - { - zeus::simd_floats f(n.position.simd); - os.format("bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]); - } + for (const Node& n : nodes) { + zeus::simd_floats f(n.position.simd); + os.format("bm.verts.new((%f,%f,%f))\n", f[0], f[1], f[2]); + } - os << "bm.verts.ensure_lookup_table()\n"; + os << "bm.verts.ensure_lookup_table()\n"; - for (const Region& r : regions) - { - os << "tri_verts = []\n"; - for (int i=0 ; imultiplyOneOverW(r.centroid); @@ -105,100 +103,88 @@ void PATH::sendToBlender(hecl::blender::Connection& conn, std::string_view entry (aabb.max.v[2] - aabb.min.v[2]) / 2.f, center.x, center.y, center.z); #endif - } + } - os << "bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)\n" - "path_mesh = bpy.data.meshes.new('PATH')\n" - "bm.to_mesh(path_mesh)\n" - "path_mesh_obj = bpy.data.objects.new(path_mesh.name, path_mesh)\n" - "\n" - "for mat_name in material_index:\n" - " mat = material_dict[mat_name]\n" - " path_mesh.materials.append(mat)\n" - "\n" - "bpy.context.scene.objects.link(path_mesh_obj)\n" - "path_mesh_obj.draw_type = 'SOLID'\n" - "path_mesh_obj.game.physics_type = 'STATIC'\n" - "path_mesh_obj.layers[1] = True\n" - "bpy.context.scene.hecl_path_obj = path_mesh_obj.name\n" - "\n" - "for ar in bpy.context.screen.areas:\n" - " for sp in ar.spaces:\n" - " if sp.type == 'VIEW_3D':\n" - " sp.viewport_shade = 'SOLID'\n"; + os << "bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.001)\n" + "path_mesh = bpy.data.meshes.new('PATH')\n" + "bm.to_mesh(path_mesh)\n" + "path_mesh_obj = bpy.data.objects.new(path_mesh.name, path_mesh)\n" + "\n" + "for mat_name in material_index:\n" + " mat = material_dict[mat_name]\n" + " path_mesh.materials.append(mat)\n" + "\n" + "bpy.context.scene.objects.link(path_mesh_obj)\n" + "path_mesh_obj.draw_type = 'SOLID'\n" + "path_mesh_obj.game.physics_type = 'STATIC'\n" + "path_mesh_obj.layers[1] = True\n" + "bpy.context.scene.hecl_path_obj = path_mesh_obj.name\n" + "\n" + "for ar in bpy.context.screen.areas:\n" + " for sp in ar.spaces:\n" + " if sp.type == 'VIEW_3D':\n" + " sp.viewport_shade = 'SOLID'\n"; - if (xf) - { - const zeus::CMatrix4f& w = *xf; - zeus::simd_floats xfMtxF[4]; - for (int i = 0; i < 4; ++i) - w.m[i].mSimd.copy_to(xfMtxF[i]); - os.format("mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" - "mtxd = mtx.decompose()\n" - "path_mesh_obj.rotation_mode = 'QUATERNION'\n" - "path_mesh_obj.location = mtxd[0]\n" - "path_mesh_obj.rotation_quaternion = mtxd[1]\n" - "path_mesh_obj.scale = mtxd[2]\n", - xfMtxF[0][0], xfMtxF[1][0], xfMtxF[2][0], xfMtxF[3][0], - xfMtxF[0][1], xfMtxF[1][1], xfMtxF[2][1], xfMtxF[3][1], - xfMtxF[0][2], xfMtxF[1][2], xfMtxF[2][2], xfMtxF[3][2]); - } + if (xf) { + const zeus::CMatrix4f& w = *xf; + zeus::simd_floats xfMtxF[4]; + for (int i = 0; i < 4; ++i) + w.m[i].mSimd.copy_to(xfMtxF[i]); + os.format( + "mtx = Matrix(((%f,%f,%f,%f),(%f,%f,%f,%f),(%f,%f,%f,%f),(0.0,0.0,0.0,1.0)))\n" + "mtxd = mtx.decompose()\n" + "path_mesh_obj.rotation_mode = 'QUATERNION'\n" + "path_mesh_obj.location = mtxd[0]\n" + "path_mesh_obj.rotation_quaternion = mtxd[1]\n" + "path_mesh_obj.scale = mtxd[2]\n", + xfMtxF[0][0], xfMtxF[1][0], xfMtxF[2][0], xfMtxF[3][0], xfMtxF[0][1], xfMtxF[1][1], xfMtxF[2][1], xfMtxF[3][1], + xfMtxF[0][2], xfMtxF[1][2], xfMtxF[2][2], xfMtxF[3][2]); + } - os.linkBackground("//!area.blend"); - os.centerView(); - os.close(); + os.linkBackground("//!area.blend"); + os.centerView(); + os.close(); } -bool PATH::Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) -{ - PATH path; - path.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::PathMesh)) - return false; +bool PATH::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + PATH path; + path.read(rs); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::PathMesh)) + return false; - const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id); - path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf); - return conn.saveBlend(); + const zeus::CMatrix4f* xf = pakRouter.lookupMAPATransform(entry.id); + path.sendToBlender(conn, pakRouter.getBestEntryName(entry, false), xf); + return conn.saveBlend(); } -bool PATH::Cook(const hecl::ProjectPath& outPath, - const PathMesh& mesh) -{ - athena::io::MemoryReader r(mesh.data.data(), mesh.data.size()); - PATH path; - path.read(r); - if (!path.regions.empty()) - { - AROTBuilder octreeBuilder; - octreeBuilder.buildPath(path); - } - else - { - path.octreeNodeCount = 1; - path.octree.emplace_back(); - OctreeNode& n = path.octree.back(); - n.isLeaf = 1; - n.aabb[0] = zeus::CVector3f{FLT_MAX, FLT_MAX, FLT_MAX}; - n.aabb[1] = zeus::CVector3f{-FLT_MAX, -FLT_MAX, -FLT_MAX}; - for (int i=0 ; i<8 ; ++i) - n.children[i] = 0xffffffff; - } +bool PATH::Cook(const hecl::ProjectPath& outPath, const PathMesh& mesh) { + athena::io::MemoryReader r(mesh.data.data(), mesh.data.size()); + PATH path; + path.read(r); + if (!path.regions.empty()) { + AROTBuilder octreeBuilder; + octreeBuilder.buildPath(path); + } else { + path.octreeNodeCount = 1; + path.octree.emplace_back(); + OctreeNode& n = path.octree.back(); + n.isLeaf = 1; + n.aabb[0] = zeus::CVector3f{FLT_MAX, FLT_MAX, FLT_MAX}; + n.aabb[1] = zeus::CVector3f{-FLT_MAX, -FLT_MAX, -FLT_MAX}; + for (int i = 0; i < 8; ++i) + n.children[i] = 0xffffffff; + } - athena::io::FileWriter w(outPath.getAbsolutePath()); - path.write(w); - int64_t rem = w.position() % 32; - if (rem) - for (int64_t i=0 ; i<32-rem ; ++i) - w.writeUByte(0xff); - return true; + athena::io::FileWriter w(outPath.getAbsolutePath()); + path.write(w); + int64_t rem = w.position() % 32; + if (rem) + for (int64_t i = 0; i < 32 - rem; ++i) + w.writeUByte(0xff); + return true; } -} \ No newline at end of file +} // namespace DataSpec::DNAMP1 \ No newline at end of file diff --git a/DataSpec/DNAMP1/PATH.hpp b/DataSpec/DNAMP1/PATH.hpp index 5323d325b..de4229422 100644 --- a/DataSpec/DNAMP1/PATH.hpp +++ b/DataSpec/DNAMP1/PATH.hpp @@ -4,88 +4,74 @@ #include "DataSpec/DNACommon/PAK.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ -struct PATH : BigDNA -{ - using PathMesh = hecl::blender::PathMesh; +namespace DataSpec::DNAMP1 { +struct PATH : BigDNA { + using PathMesh = hecl::blender::PathMesh; + AT_DECL_DNA + Value version; + + struct Node : BigDNA { AT_DECL_DNA - Value version; + Value position; + Value normal; + }; + Value nodeCount; + Vector nodes; - struct Node : BigDNA - { - AT_DECL_DNA - Value position; - Value normal; - }; + struct Link : BigDNA { + AT_DECL_DNA + Value nodeIdx; + Value regionIdx; + Value width2d; + Value oneOverWidth2d; + }; + Value linkCount; + Vector links; + + struct Region : BigDNA { + AT_DECL_DNA Value nodeCount; - Vector nodes; - - struct Link : BigDNA - { - AT_DECL_DNA - Value nodeIdx; - Value regionIdx; - Value width2d; - Value oneOverWidth2d; - }; + Value nodeStart; Value linkCount; - Vector links; + Value linkStart; + Value meshIndexMask; + Value meshTypeMask; + Value height; + Value normal; + Value regionIdx; + Value centroid; + Value aabb[2]; + Value regionIdxPtr; + }; + Value regionCount; + Vector regions; - struct Region : BigDNA - { - AT_DECL_DNA - Value nodeCount; - Value nodeStart; - Value linkCount; - Value linkStart; - Value meshIndexMask; - Value meshTypeMask; - Value height; - Value normal; - Value regionIdx; - Value centroid; - Value aabb[2]; - Value regionIdxPtr; - }; + Vector bitmap1; + Vector bitmap2; + Vector bitmap3; + + Value octreeRegionLookupCount; + Vector octreeRegionLookup; + + struct OctreeNode : BigDNA { + AT_DECL_DNA + Value isLeaf; + Value aabb[2]; + Value centroid; + Value children[8]; Value regionCount; - Vector regions; + Value regionStart; + }; + Value octreeNodeCount; + Vector octree; - Vector bitmap1; - Vector bitmap2; - Vector bitmap3; + void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, const zeus::CMatrix4f* xf); - Value octreeRegionLookupCount; - Vector octreeRegionLookup; + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged); - struct OctreeNode : BigDNA - { - AT_DECL_DNA - Value isLeaf; - Value aabb[2]; - Value centroid; - Value children[8]; - Value regionCount; - Value regionStart; - }; - Value octreeNodeCount; - Vector octree; - - void sendToBlender(hecl::blender::Connection& conn, std::string_view entryName, - const zeus::CMatrix4f* xf); - - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged); - - static bool Cook(const hecl::ProjectPath& outPath, - const PathMesh& mesh); + static bool Cook(const hecl::ProjectPath& outPath, const PathMesh& mesh); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/SAVW.hpp b/DataSpec/DNAMP1/SAVW.hpp index b9998272c..54e52bbaf 100644 --- a/DataSpec/DNAMP1/SAVW.hpp +++ b/DataSpec/DNAMP1/SAVW.hpp @@ -3,32 +3,28 @@ #include "DataSpec/DNACommon/SAVWCommon.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ -struct Scan : BigDNA -{ - AT_DECL_DNA_YAML - UniqueID32 scanId; - Value category; +namespace DataSpec::DNAMP1 { +struct Scan : BigDNA { + AT_DECL_DNA_YAML + UniqueID32 scanId; + Value category; - Scan() = default; - Scan(const UniqueID32& id) : scanId(id), category(SAVWCommon::EScanCategory::None) {} + Scan() = default; + Scan(const UniqueID32& id) : scanId(id), category(SAVWCommon::EScanCategory::None) {} }; -struct SAVW : BigDNA -{ - AT_DECL_DNA_YAML - SAVWCommon::Header header; - Value skippableCutsceneCount; - Vector skippableCutscenes; - Value relayCount; - Vector relays; - Value layerCount; - Vector layers; - Value doorCount; - Vector doors; - Value scanCount; - Vector scans; +struct SAVW : BigDNA { + AT_DECL_DNA_YAML + SAVWCommon::Header header; + Value skippableCutsceneCount; + Vector skippableCutscenes; + Value relayCount; + Vector relays; + Value layerCount; + Vector layers; + Value doorCount; + Vector doors; + Value scanCount; + Vector scans; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/SCAN.cpp b/DataSpec/DNAMP1/SCAN.cpp index 083326c49..83e6832f3 100644 --- a/DataSpec/DNAMP1/SCAN.cpp +++ b/DataSpec/DNAMP1/SCAN.cpp @@ -1,81 +1,73 @@ #include "SCAN.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -static const std::vector PaneNames = -{ - "imagepane_pane0", "imagepane_pane1", "imagepane_pane2", "imagepane_pane3", "imagepane_pane01", - "imagepane_pane12", "imagepane_pane23", "imagepane_pane012", "imagepane_pane123", "imagepane_pane0123", - "imagepane_pane4", "imagepane_pane5", "imagepane_pane6", "imagepane_pane7", "imagepane_pane45", - "imagepane_pane56", "imagepane_pane67", "imagepane_pane456", "imagepane_pane567", "imagepane_pane4567" -}; +static const std::vector PaneNames = { + "imagepane_pane0", "imagepane_pane1", "imagepane_pane2", "imagepane_pane3", "imagepane_pane01", + "imagepane_pane12", "imagepane_pane23", "imagepane_pane012", "imagepane_pane123", "imagepane_pane0123", + "imagepane_pane4", "imagepane_pane5", "imagepane_pane6", "imagepane_pane7", "imagepane_pane45", + "imagepane_pane56", "imagepane_pane67", "imagepane_pane456", "imagepane_pane567", "imagepane_pane4567"}; template <> -void SCAN::Texture::Enumerate(typename Read::StreamT& r) -{ - texture.read(r); - appearanceRange = r.readFloatBig(); - position = Position(r.readUint32Big()); - width = r.readUint32Big(); - height = r.readUint32Big(); - interval = r.readFloatBig(); - fadeDuration = r.readFloatBig(); +void SCAN::Texture::Enumerate(typename Read::StreamT& r) { + texture.read(r); + appearanceRange = r.readFloatBig(); + position = Position(r.readUint32Big()); + width = r.readUint32Big(); + height = r.readUint32Big(); + interval = r.readFloatBig(); + fadeDuration = r.readFloatBig(); } template <> -void SCAN::Texture::Enumerate(typename Write::StreamT& w) -{ - texture.write(w); - w.writeFloatBig(appearanceRange); - w.writeUint32Big(atUint32(position)); - w.writeUint32Big(width); - w.writeUint32Big(height); - w.writeFloatBig(interval); - w.writeFloatBig(fadeDuration); +void SCAN::Texture::Enumerate(typename Write::StreamT& w) { + texture.write(w); + w.writeFloatBig(appearanceRange); + w.writeUint32Big(atUint32(position)); + w.writeUint32Big(width); + w.writeUint32Big(height); + w.writeFloatBig(interval); + w.writeFloatBig(fadeDuration); } template <> -void SCAN::Texture::Enumerate(typename ReadYaml::StreamT& r) -{ - r.enumerate("texture", texture); - appearanceRange = r.readFloat("appearanceRange"); - std::string tmp = r.readString("position"); +void SCAN::Texture::Enumerate(typename ReadYaml::StreamT& r) { + r.enumerate("texture", texture); + appearanceRange = r.readFloat("appearanceRange"); + std::string tmp = r.readString("position"); - auto idx = std::find(PaneNames.begin(), PaneNames.end(), tmp); - if (idx != PaneNames.end()) - position = Position(idx - PaneNames.begin()); - else - position = Position::Invalid; + auto idx = std::find(PaneNames.begin(), PaneNames.end(), tmp); + if (idx != PaneNames.end()) + position = Position(idx - PaneNames.begin()); + else + position = Position::Invalid; - width = r.readUint32("width"); - height = r.readUint32("height"); - interval = r.readFloat("interval"); - fadeDuration = r.readFloat("fadeDuration"); + width = r.readUint32("width"); + height = r.readUint32("height"); + interval = r.readFloat("interval"); + fadeDuration = r.readFloat("fadeDuration"); } template <> -void SCAN::Texture::Enumerate(typename WriteYaml::StreamT& w) -{ - w.enumerate("texture", texture); - w.writeFloat("appearanceRange", appearanceRange); - if (position != Position::Invalid) - w.writeString("position", PaneNames.at(atUint32(position))); - else - w.writeString("position", "undefined"); - w.writeUint32("width", width); - w.writeUint32("height", height); - w.writeFloat("interval", interval); - w.writeFloat("fadeDuration", fadeDuration); +void SCAN::Texture::Enumerate(typename WriteYaml::StreamT& w) { + w.enumerate("texture", texture); + w.writeFloat("appearanceRange", appearanceRange); + if (position != Position::Invalid) + w.writeString("position", PaneNames.at(atUint32(position))); + else + w.writeString("position", "undefined"); + w.writeUint32("width", width); + w.writeUint32("height", height); + w.writeFloat("interval", interval); + w.writeFloat("fadeDuration", fadeDuration); } const char* SCAN::Texture::DNAType() { return "urde::DNAMP1::SCAN::Texture"; } template <> -void SCAN::Texture::Enumerate(typename BinarySize::StreamT& s) -{ - texture.binarySize(s); - s += 24; +void SCAN::Texture::Enumerate(typename BinarySize::StreamT& s) { + texture.binarySize(s); + s += 24; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/SCAN.hpp b/DataSpec/DNAMP1/SCAN.hpp index 371dab5b2..2e0540886 100644 --- a/DataSpec/DNAMP1/SCAN.hpp +++ b/DataSpec/DNAMP1/SCAN.hpp @@ -4,111 +4,106 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ -struct SCAN : BigDNA -{ - AT_DECL_DNA_YAML - Value version; - Value magic; - UniqueID32 frame; - UniqueID32 string; +namespace DataSpec::DNAMP1 { +struct SCAN : BigDNA { + AT_DECL_DNA_YAML + Value version; + Value magic; + UniqueID32 frame; + UniqueID32 string; - enum class ScanSpeed : atUint32 - { Normal, Slow }; - Value scanSpeed; + enum class ScanSpeed : atUint32 { Normal, Slow }; + Value scanSpeed; - enum class Category : atUint32 - { - None, - SpacePirateData, - ChozoLore, - Creatures, - Research + enum class Category : atUint32 { None, SpacePirateData, ChozoLore, Creatures, Research }; + + Value category; + + Value isImportant; + + struct Texture : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + UniqueID32 texture; + Value appearanceRange; + enum class Position : atInt32 { + Pane0, + Pane1, + Pane2, + Pane3, + Pane01, + Pane12, + Pane23, + Pane012, + Pane123, + Pane0123, + Pane4, + Pane5, + Pane6, + Pane7, + Pane45, + Pane56, + Pane67, + Pane456, + Pane567, + Pane4567, + Invalid = -1 }; + Value position; + Value width; // width of animation cell + Value height; // height of animation cell + Value interval; // 0.0 - 1.0 + Value fadeDuration; // 0.0 - 1.0 + }; - Value category; + Texture textures[4]; - Value isImportant; + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + SCAN scan; + scan.read(rs); + athena::io::FileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(scan, writer); + return true; + } - struct Texture : BigDNA - { - AT_DECL_EXPLICIT_DNA_YAML - UniqueID32 texture; - Value appearanceRange; - enum class Position : atInt32 - { - Pane0, Pane1, Pane2, Pane3, Pane01, Pane12, Pane23, Pane012, - Pane123, Pane0123, Pane4, Pane5, Pane6, Pane7, Pane45, Pane56, - Pane67, Pane456, Pane567, Pane4567, Invalid = -1 - }; - Value position; - Value width; // width of animation cell - Value height; // height of animation cell - Value interval; // 0.0 - 1.0 - Value fadeDuration; // 0.0 - 1.0 - }; + static bool Cook(const SCAN& scan, const hecl::ProjectPath& outPath) { + athena::io::FileWriter ws(outPath.getAbsolutePath()); + scan.write(ws); + return true; + } - Texture textures[4]; + static Category GetCategory(const hecl::ProjectPath& inPath) { + SCAN scan; + athena::io::FileReader reader(inPath.getAbsolutePath()); + if (reader.hasError()) + return Category::None; + if (!athena::io::FromYAMLStream(scan, reader)) + return Category::None; + return scan.category; + } - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) - { - SCAN scan; - scan.read(rs); - athena::io::FileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(scan, writer); - return true; + static void Name(const SpecBase& dataSpec, PAKEntryReadStream& rs, PAKRouter& pakRouter, + PAK::Entry& entry) { + SCAN scan; + scan.read(rs); + if (scan.string) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(scan.string); + ent->name = hecl::Format("SCAN_%s_strg", entry.id.toString().c_str()); } - - static bool Cook(const SCAN& scan, const hecl::ProjectPath& outPath) - { - athena::io::FileWriter ws(outPath.getAbsolutePath()); - scan.write(ws); - return true; + for (int i = 0; i < 4; ++i) { + const Texture& tex = scan.textures[i]; + if (tex.texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(tex.texture); + ent->name = hecl::Format("SCAN_%s_tex%d", entry.id.toString().c_str(), i + 1); + } } + } - static Category GetCategory(const hecl::ProjectPath& inPath) - { - SCAN scan; - athena::io::FileReader reader(inPath.getAbsolutePath()); - if (reader.hasError()) - return Category::None; - if (!athena::io::FromYAMLStream(scan, reader)) - return Category::None; - return scan.category; - } - - static void Name(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - PAKRouter& pakRouter, - PAK::Entry& entry) - { - SCAN scan; - scan.read(rs); - if (scan.string) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(scan.string); - ent->name = hecl::Format("SCAN_%s_strg", entry.id.toString().c_str()); - } - for (int i=0 ; i<4 ; ++i) - { - const Texture& tex = scan.textures[i]; - if (tex.texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(tex.texture); - ent->name = hecl::Format("SCAN_%s_tex%d", entry.id.toString().c_str(), i+1); - } - } - } - - void gatherDependencies(std::vector& pathsOut) - { - g_curSpec->flattenDependencies(frame, pathsOut); - g_curSpec->flattenDependencies(string, pathsOut); - for (int i = 0; i < 4; ++i) - g_curSpec->flattenDependencies(textures[i].texture, pathsOut); - } + void gatherDependencies(std::vector& pathsOut) { + g_curSpec->flattenDependencies(frame, pathsOut); + g_curSpec->flattenDependencies(string, pathsOut); + for (int i = 0; i < 4; ++i) + g_curSpec->flattenDependencies(textures[i].texture, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/SCLY.cpp b/DataSpec/DNAMP1/SCLY.cpp index 22bddf070..83c5f0db9 100644 --- a/DataSpec/DNAMP1/SCLY.cpp +++ b/DataSpec/DNAMP1/SCLY.cpp @@ -1,231 +1,195 @@ #include "SCLY.hpp" #include "ScriptObjects/ScriptTypes.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template <> -void SCLY::Enumerate(athena::io::IStreamReader& rs) -{ - fourCC = rs.readUint32Little(); - version = rs.readUint32Big(); - layerCount = rs.readUint32Big(); - rs.enumerateBig(layerSizes, layerCount); - atUint32 i = 0; - rs.enumerate(layers, layerCount, - [&i,this](athena::io::IStreamReader& rs, ScriptLayer& layer) { - atUint64 start = rs.position(); - layer.read(rs); - rs.seek(start + layerSizes[i++], athena::Begin); - }); +void SCLY::Enumerate(athena::io::IStreamReader& rs) { + fourCC = rs.readUint32Little(); + version = rs.readUint32Big(); + layerCount = rs.readUint32Big(); + rs.enumerateBig(layerSizes, layerCount); + atUint32 i = 0; + rs.enumerate(layers, layerCount, [&i, this](athena::io::IStreamReader& rs, ScriptLayer& layer) { + atUint64 start = rs.position(); + layer.read(rs); + rs.seek(start + layerSizes[i++], athena::Begin); + }); } template <> -void SCLY::Enumerate(athena::io::IStreamWriter& ws) -{ - ws.writeUint32Big(fourCC); - ws.writeUint32Big(version); - ws.writeUint32Big(layerCount); - ws.enumerateBig(layerSizes); - ws.enumerate(layers); +void SCLY::Enumerate(athena::io::IStreamWriter& ws) { + ws.writeUint32Big(fourCC); + ws.writeUint32Big(version); + ws.writeUint32Big(layerCount); + ws.enumerateBig(layerSizes); + ws.enumerate(layers); } template <> -void SCLY::Enumerate(size_t& __isz) -{ - __isz += 12; - __isz += layerSizes.size() * 4; - for (const ScriptLayer& layer : layers) - layer.binarySize(__isz); +void SCLY::Enumerate(size_t& __isz) { + __isz += 12; + __isz += layerSizes.size() * 4; + for (const ScriptLayer& layer : layers) + layer.binarySize(__isz); } -void SCLY::exportToLayerDirectories(const PAK::Entry& entry, PAKRouter& pakRouter, bool force) const -{ - for (atUint32 i = 0; i < layerCount; i++) - { - bool active; - hecl::ProjectPath layerPath = pakRouter.getAreaLayerWorking(entry.id, i, active); - if (layerPath.isNone()) - layerPath.makeDirChain(true); +void SCLY::exportToLayerDirectories(const PAK::Entry& entry, PAKRouter& pakRouter, bool force) const { + for (atUint32 i = 0; i < layerCount; i++) { + bool active; + hecl::ProjectPath layerPath = pakRouter.getAreaLayerWorking(entry.id, i, active); + if (layerPath.isNone()) + layerPath.makeDirChain(true); - if (active) - { - hecl::ProjectPath activePath(layerPath, "!defaultactive"); - fclose(hecl::Fopen(activePath.getAbsolutePath().data(), _SYS_STR("wb"))); - } - - hecl::ProjectPath yamlFile(layerPath, _SYS_STR("!objects.yaml")); - if (force || yamlFile.isNone()) - { - athena::io::FileWriter writer(yamlFile.getAbsolutePath()); - athena::io::ToYAMLStream(layers[i], writer); - } + if (active) { + hecl::ProjectPath activePath(layerPath, "!defaultactive"); + fclose(hecl::Fopen(activePath.getAbsolutePath().data(), _SYS_STR("wb"))); } -} -void SCLY::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const -{ - for (const ScriptLayer& layer : layers) - layer.addCMDLRigPairs(pakRouter, charAssoc); -} - -void SCLY::ScriptLayer::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const -{ - for (const std::unique_ptr& obj : objects) - obj->addCMDLRigPairs(pakRouter, charAssoc); -} - -void SCLY::nameIDs(PAKRouter& pakRouter) const -{ - for (const ScriptLayer& layer : layers) - layer.nameIDs(pakRouter); -} - -void SCLY::ScriptLayer::nameIDs(PAKRouter& pakRouter) const -{ - for (const std::unique_ptr& obj : objects) - obj->nameIDs(pakRouter); -} - -template <> -void SCLY::Enumerate(athena::io::YAMLDocReader& docin) -{ - fourCC = docin.readUint32("fourCC"); - version = docin.readUint32("version"); - layerCount = docin.enumerate("layerSizes", layerSizes); - docin.enumerate("layers", layers); -} - -template <> -void SCLY::Enumerate(athena::io::YAMLDocWriter& docout) -{ - docout.writeUint32("fourCC", fourCC); - docout.writeUint32("version", version); - docout.enumerate("layerSizes", layerSizes); - docout.enumerate("layers", layers); -} - -const char* SCLY::DNAType() -{ - return "urde::DNAMP1::SCLY"; -} - -template <> -void SCLY::ScriptLayer::Enumerate(athena::io::IStreamReader& rs) -{ - unknown = rs.readUByte(); - objectCount = rs.readUint32Big(); - objects.clear(); - objects.reserve(objectCount); - for (atUint32 i = 0; i < objectCount; i++) - { - atUint8 type = rs.readUByte(); - atUint32 len = rs.readUint32Big(); - atUint64 start = rs.position(); - - auto iter = std::find_if(SCRIPT_OBJECT_DB.begin(), SCRIPT_OBJECT_DB.end(), [&type](const ScriptObjectSpec* obj) -> bool - { return obj->type == type; }); - - if (iter != SCRIPT_OBJECT_DB.end()) - { - std::unique_ptr obj((*iter)->a()); - obj->type = type; - obj->read(rs); - objects.push_back(std::move(obj)); - size_t actualLen = rs.position() - start; - if (actualLen != len) - Log.report(logvisor::Fatal, _SYS_STR("Error while reading object of type 0x%.2X, did not read the expected amount of data, read 0x%x, expected 0x%x"), (atUint32)type, actualLen, len); - rs.seek(start + len, athena::Begin); - } - else - Log.report(logvisor::Fatal, _SYS_STR("Unable to find type 0x%X in object database"), (atUint32)type); + hecl::ProjectPath yamlFile(layerPath, _SYS_STR("!objects.yaml")); + if (force || yamlFile.isNone()) { + athena::io::FileWriter writer(yamlFile.getAbsolutePath()); + athena::io::ToYAMLStream(layers[i], writer); } + } +} + +void SCLY::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + for (const ScriptLayer& layer : layers) + layer.addCMDLRigPairs(pakRouter, charAssoc); +} + +void SCLY::ScriptLayer::addCMDLRigPairs(PAKRouter& pakRouter, + CharacterAssociations& charAssoc) const { + for (const std::unique_ptr& obj : objects) + obj->addCMDLRigPairs(pakRouter, charAssoc); +} + +void SCLY::nameIDs(PAKRouter& pakRouter) const { + for (const ScriptLayer& layer : layers) + layer.nameIDs(pakRouter); +} + +void SCLY::ScriptLayer::nameIDs(PAKRouter& pakRouter) const { + for (const std::unique_ptr& obj : objects) + obj->nameIDs(pakRouter); } template <> -void SCLY::ScriptLayer::Enumerate(athena::io::YAMLDocReader& rs) -{ - unknown = rs.readUByte("unknown"); - size_t objCount; - objects.clear(); - if (auto v = rs.enterSubVector("objects", objCount)) - { - objectCount = objCount; - objects.reserve(objCount); - for (atUint32 i = 0; i < objectCount; i++) - { - if (auto rec = rs.enterSubRecord(nullptr)) - { - atUint8 type = rs.readUByte("type"); - auto iter = std::find_if(SCRIPT_OBJECT_DB.begin(), SCRIPT_OBJECT_DB.end(), [&type](const ScriptObjectSpec* obj) -> bool - { return obj->type == type; }); +void SCLY::Enumerate(athena::io::YAMLDocReader& docin) { + fourCC = docin.readUint32("fourCC"); + version = docin.readUint32("version"); + layerCount = docin.enumerate("layerSizes", layerSizes); + docin.enumerate("layers", layers); +} - if (iter != SCRIPT_OBJECT_DB.end()) - { - std::unique_ptr obj((*iter)->a()); - obj->read(rs); - obj->type = type; - objects.push_back(std::move(obj)); - } - else - Log.report(logvisor::Fatal, _SYS_STR("Unable to find type 0x%X in object database"), (atUint32)type); - } - } +template <> +void SCLY::Enumerate(athena::io::YAMLDocWriter& docout) { + docout.writeUint32("fourCC", fourCC); + docout.writeUint32("version", version); + docout.enumerate("layerSizes", layerSizes); + docout.enumerate("layers", layers); +} + +const char* SCLY::DNAType() { return "urde::DNAMP1::SCLY"; } + +template <> +void SCLY::ScriptLayer::Enumerate(athena::io::IStreamReader& rs) { + unknown = rs.readUByte(); + objectCount = rs.readUint32Big(); + objects.clear(); + objects.reserve(objectCount); + for (atUint32 i = 0; i < objectCount; i++) { + atUint8 type = rs.readUByte(); + atUint32 len = rs.readUint32Big(); + atUint64 start = rs.position(); + + auto iter = std::find_if(SCRIPT_OBJECT_DB.begin(), SCRIPT_OBJECT_DB.end(), + [&type](const ScriptObjectSpec* obj) -> bool { return obj->type == type; }); + + if (iter != SCRIPT_OBJECT_DB.end()) { + std::unique_ptr obj((*iter)->a()); + obj->type = type; + obj->read(rs); + objects.push_back(std::move(obj)); + size_t actualLen = rs.position() - start; + if (actualLen != len) + Log.report(logvisor::Fatal, + _SYS_STR("Error while reading object of type 0x%.2X, did not read the expected amount of data, read " + "0x%x, expected 0x%x"), + (atUint32)type, actualLen, len); + rs.seek(start + len, athena::Begin); + } else + Log.report(logvisor::Fatal, _SYS_STR("Unable to find type 0x%X in object database"), (atUint32)type); + } +} + +template <> +void SCLY::ScriptLayer::Enumerate(athena::io::YAMLDocReader& rs) { + unknown = rs.readUByte("unknown"); + size_t objCount; + objects.clear(); + if (auto v = rs.enterSubVector("objects", objCount)) { + objectCount = objCount; + objects.reserve(objCount); + for (atUint32 i = 0; i < objectCount; i++) { + if (auto rec = rs.enterSubRecord(nullptr)) { + atUint8 type = rs.readUByte("type"); + auto iter = std::find_if(SCRIPT_OBJECT_DB.begin(), SCRIPT_OBJECT_DB.end(), + [&type](const ScriptObjectSpec* obj) -> bool { return obj->type == type; }); + + if (iter != SCRIPT_OBJECT_DB.end()) { + std::unique_ptr obj((*iter)->a()); + obj->read(rs); + obj->type = type; + objects.push_back(std::move(obj)); + } else + Log.report(logvisor::Fatal, _SYS_STR("Unable to find type 0x%X in object database"), (atUint32)type); + } } - else - objectCount = 0; + } else + objectCount = 0; } template <> -void SCLY::ScriptLayer::Enumerate(athena::io::IStreamWriter& ws) -{ - ws.writeUByte(unknown); - ws.writeUint32Big(objectCount); - for (const std::unique_ptr& obj : objects) - { - ws.writeByte(obj->type); - size_t expLen = 0; - obj->binarySize(expLen); - ws.writeUint32Big(expLen); - auto start = ws.position(); - obj->write(ws); - auto wrote = ws.position() - start; - if (wrote != expLen) - Log.report(logvisor::Error, "expected writing %lu byte SCLY obj; wrote %llu", expLen, wrote); - } +void SCLY::ScriptLayer::Enumerate(athena::io::IStreamWriter& ws) { + ws.writeUByte(unknown); + ws.writeUint32Big(objectCount); + for (const std::unique_ptr& obj : objects) { + ws.writeByte(obj->type); + size_t expLen = 0; + obj->binarySize(expLen); + ws.writeUint32Big(expLen); + auto start = ws.position(); + obj->write(ws); + auto wrote = ws.position() - start; + if (wrote != expLen) + Log.report(logvisor::Error, "expected writing %lu byte SCLY obj; wrote %llu", expLen, wrote); + } } template <> -void SCLY::ScriptLayer::Enumerate(size_t& __isz) -{ +void SCLY::ScriptLayer::Enumerate(size_t& __isz) { + __isz += 5; + for (const std::unique_ptr& obj : objects) { __isz += 5; - for (const std::unique_ptr& obj : objects) - { - __isz += 5; - obj->binarySize(__isz); - } + obj->binarySize(__isz); + } } template <> -void SCLY::ScriptLayer::Enumerate(athena::io::YAMLDocWriter& ws) -{ - ws.writeUByte("unknown", unknown); - if (auto v = ws.enterSubVector("objects")) - { - for (const std::unique_ptr& obj : objects) - { - if (auto rec = ws.enterSubRecord(nullptr)) - { - ws.writeUByte("type", obj->type); - obj->write(ws); - } - } +void SCLY::ScriptLayer::Enumerate(athena::io::YAMLDocWriter& ws) { + ws.writeUByte("unknown", unknown); + if (auto v = ws.enterSubVector("objects")) { + for (const std::unique_ptr& obj : objects) { + if (auto rec = ws.enterSubRecord(nullptr)) { + ws.writeUByte("type", obj->type); + obj->write(ws); + } } + } } -const char* SCLY::ScriptLayer::DNAType() -{ - return "urde::DNAMP1::SCLY::ScriptLayer"; -} +const char* SCLY::ScriptLayer::DNAType() { return "urde::DNAMP1::SCLY::ScriptLayer"; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/SCLY.hpp b/DataSpec/DNAMP1/SCLY.hpp index 713185975..e61d40728 100644 --- a/DataSpec/DNAMP1/SCLY.hpp +++ b/DataSpec/DNAMP1/SCLY.hpp @@ -4,30 +4,27 @@ #include "ScriptObjects/IScriptObject.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ -struct SCLY : BigDNA -{ +namespace DataSpec::DNAMP1 { +struct SCLY : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + Value fourCC; + Value version; + Value layerCount; + + Vector layerSizes; + + struct ScriptLayer : BigDNA { AT_DECL_EXPLICIT_DNA_YAML - Value fourCC; - Value version; - Value layerCount; - - Vector layerSizes; - - struct ScriptLayer : BigDNA - { - AT_DECL_EXPLICIT_DNA_YAML - Value unknown; - Value objectCount; - Vector, AT_DNA_COUNT(objectCount)> objects; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; - void nameIDs(PAKRouter& pakRouter) const; - }; - Vector layers; - - void exportToLayerDirectories(const PAK::Entry &, PAKRouter&, bool) const; + Value unknown; + Value objectCount; + Vector, AT_DNA_COUNT(objectCount)> objects; void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; void nameIDs(PAKRouter& pakRouter) const; + }; + Vector layers; + + void exportToLayerDirectories(const PAK::Entry&, PAKRouter&, bool) const; + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; + void nameIDs(PAKRouter& pakRouter) const; }; -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/STRG.cpp b/DataSpec/DNAMP1/STRG.cpp index 2a1221438..f9c69e9b3 100644 --- a/DataSpec/DNAMP1/STRG.cpp +++ b/DataSpec/DNAMP1/STRG.cpp @@ -1,564 +1,460 @@ #include "STRG.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { const std::vector skLanguages = {FOURCC('ENGL'), FOURCC('FREN'), FOURCC('GERM'), FOURCC('SPAN'), FOURCC('ITAL'), FOURCC('DUTC'), FOURCC('JAPN')}; -static uint32_t ParseTag(const char16_t* str) -{ - char parseStr[9]; - int i; - for (i = 0; i < 8 && str[i]; ++i) - parseStr[i] = str[i]; - parseStr[i] = '\0'; - return strtoul(parseStr, nullptr, 16); +static uint32_t ParseTag(const char16_t* str) { + char parseStr[9]; + int i; + for (i = 0; i < 8 && str[i]; ++i) + parseStr[i] = str[i]; + parseStr[i] = '\0'; + return strtoul(parseStr, nullptr, 16); } static std::u16string_view::const_iterator SkipCommas(std::u16string& ret, std::u16string_view str, - std::u16string_view::const_iterator it, size_t count) -{ - for (size_t i = 0; i < count; ++i) - { - auto cpos = str.find(u',', it - str.begin()); - if (cpos == std::u16string::npos) - return str.end(); - auto end = str.begin() + cpos + 1; - ret.insert(ret.end(), it, end); - it = end; - } - return it; + std::u16string_view::const_iterator it, size_t count) { + for (size_t i = 0; i < count; ++i) { + auto cpos = str.find(u',', it - str.begin()); + if (cpos == std::u16string::npos) + return str.end(); + auto end = str.begin() + cpos + 1; + ret.insert(ret.end(), it, end); + it = end; + } + return it; } static std::u16string_view::const_iterator UncookTextureList(std::u16string& ret, std::u16string_view str, - std::u16string_view::const_iterator it) -{ - while (true) - { - UniqueID32 id = ParseTag(&*it); - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); - ret.append(hecl::UTF8ToChar16(path ? path.getRelativePathUTF8() : id.toString())); - it += 8; - if (*it == u';') - { - ret.push_back(u';'); - return it + 1; - } - else if (*it == u',') - { - ret.push_back(u','); - ++it; - } - else - { - break; - } + std::u16string_view::const_iterator it) { + while (true) { + UniqueID32 id = ParseTag(&*it); + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); + ret.append(hecl::UTF8ToChar16(path ? path.getRelativePathUTF8() : id.toString())); + it += 8; + if (*it == u';') { + ret.push_back(u';'); + return it + 1; + } else if (*it == u',') { + ret.push_back(u','); + ++it; + } else { + break; } + } - /* Failsafe */ - auto scpos = str.find(u';', it - str.begin()); - if (scpos == std::u16string::npos) - return str.end(); - return str.begin() + scpos + 1; + /* Failsafe */ + auto scpos = str.find(u';', it - str.begin()); + if (scpos == std::u16string::npos) + return str.end(); + return str.begin() + scpos + 1; } static std::u16string_view::const_iterator CookTextureList(std::u16string& ret, std::u16string_view str, - std::u16string_view::const_iterator it) -{ - while (true) - { - auto end = str.find_first_of(u",;", it - str.begin()); - if (end == std::u16string::npos) - Log.report(logvisor::Fatal, "Missing comma/semicolon token while pasing font tag"); - auto endIt = str.begin() + end; - hecl::ProjectPath path = - UniqueIDBridge::MakePathFromString(hecl::Char16ToUTF8(std::u16string(it, endIt))); - ret.append(hecl::UTF8ToChar16(UniqueID32(path).toString())); - it = endIt; - if (*it == u';') - { - ret.push_back(u';'); - return it + 1; - } - else if (*it == u',') - { - ret.push_back(u','); - ++it; - } - else - { - break; - } + std::u16string_view::const_iterator it) { + while (true) { + auto end = str.find_first_of(u",;", it - str.begin()); + if (end == std::u16string::npos) + Log.report(logvisor::Fatal, "Missing comma/semicolon token while pasing font tag"); + auto endIt = str.begin() + end; + hecl::ProjectPath path = + UniqueIDBridge::MakePathFromString(hecl::Char16ToUTF8(std::u16string(it, endIt))); + ret.append(hecl::UTF8ToChar16(UniqueID32(path).toString())); + it = endIt; + if (*it == u';') { + ret.push_back(u';'); + return it + 1; + } else if (*it == u',') { + ret.push_back(u','); + ++it; + } else { + break; } + } - /* Failsafe */ - auto scpos = str.find(u';', it - str.begin()); - if (scpos == std::u16string::npos) - return str.end(); - return str.begin() + scpos + 1; + /* Failsafe */ + auto scpos = str.find(u';', it - str.begin()); + if (scpos == std::u16string::npos) + return str.end(); + return str.begin() + scpos + 1; } static std::u16string_view::const_iterator GatherTextureList(std::vector& pathsOut, - std::u16string_view str, std::u16string_view::const_iterator it) -{ - while (true) - { - auto end = str.find_first_of(u",;", it - str.begin()); - if (end == std::u16string::npos) - Log.report(logvisor::Fatal, "Missing comma/semicolon token while pasing font tag"); - auto endIt = str.begin() + end; + std::u16string_view str, + std::u16string_view::const_iterator it) { + while (true) { + auto end = str.find_first_of(u",;", it - str.begin()); + if (end == std::u16string::npos) + Log.report(logvisor::Fatal, "Missing comma/semicolon token while pasing font tag"); + auto endIt = str.begin() + end; + hecl::ProjectPath path = + UniqueIDBridge::MakePathFromString(hecl::Char16ToUTF8(std::u16string(it, endIt))); + if (path) + pathsOut.push_back(path); + + it = endIt; + if (*it == u';') { + return it + 1; + } else if (*it == u',') { + ++it; + } else { + break; + } + } + + /* Failsafe */ + auto scpos = str.find(u';', it - str.begin()); + if (scpos == std::u16string::npos) + return str.end(); + return str.begin() + scpos + 1; +} + +static std::u16string UncookString(std::u16string_view str) { + std::u16string ret; + ret.reserve(str.size()); + for (auto it = str.begin(); it != str.end();) { + if (*it == u'&') { + ret.push_back(u'&'); + ++it; + if (!str.compare(it - str.begin(), 5, u"image")) { + ret.append(u"image="); + it += 6; + if (!str.compare(it - str.begin(), 1, u"A")) { + it = SkipCommas(ret, str, it, 2); + it = UncookTextureList(ret, str, it); + continue; + } else if (!str.compare(it - str.begin(), 2, u"SA")) { + it = SkipCommas(ret, str, it, 4); + it = UncookTextureList(ret, str, it); + continue; + } else if (!str.compare(it - str.begin(), 2, u"SI")) { + it = SkipCommas(ret, str, it, 3); + it = UncookTextureList(ret, str, it); + continue; + } + } else if (!str.compare(it - str.begin(), 4, u"font")) { + ret.append(u"font="); + it += 5; + UniqueID32 id = ParseTag(&*it); + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id, true); + ret.append(hecl::UTF8ToChar16(path ? path.getRelativePathUTF8() : id.toString())); + + ret.push_back(u';'); + auto scpos = str.find(u';', it - str.begin()); + if (scpos == std::u16string::npos) + it = str.end(); + else + it = str.begin() + scpos + 1; + } else { + auto scpos = str.find(u';', it - str.begin()); + if (scpos == std::u16string::npos) { + it = str.end(); + } else { + auto end = str.begin() + scpos + 1; + ret.insert(ret.end(), it, end); + it = end; + } + } + } else { + ret.push_back(*it); + ++it; + } + } + return ret; +} + +static std::u16string CookString(std::u16string_view str) { + std::u16string ret; + ret.reserve(str.size()); + for (auto it = str.begin(); it != str.end();) { + if (*it == u'&') { + ret.push_back(u'&'); + ++it; + if (!str.compare(it - str.begin(), 5, u"image")) { + ret.append(u"image="); + it += 6; + if (!str.compare(it - str.begin(), 1, u"A")) { + it = SkipCommas(ret, str, it, 2); + it = CookTextureList(ret, str, it); + continue; + } else if (!str.compare(it - str.begin(), 2, u"SA")) { + it = SkipCommas(ret, str, it, 4); + it = CookTextureList(ret, str, it); + continue; + } else if (!str.compare(it - str.begin(), 2, u"SI")) { + it = SkipCommas(ret, str, it, 3); + it = CookTextureList(ret, str, it); + continue; + } + } else if (!str.compare(it - str.begin(), 4, u"font")) { + ret.append(u"font="); + it += 5; + auto scpos = str.find(u';', it - str.begin()); + if (scpos == std::u16string::npos) + Log.report(logvisor::Fatal, "Missing semicolon token while pasing font tag"); hecl::ProjectPath path = - UniqueIDBridge::MakePathFromString(hecl::Char16ToUTF8(std::u16string(it, endIt))); - if (path) - pathsOut.push_back(path); - - it = endIt; - if (*it == u';') - { - return it + 1; - } - else if (*it == u',') - { - ++it; - } - else - { - break; + UniqueIDBridge::MakePathFromString(hecl::Char16ToUTF8(std::u16string(it, str.begin() + scpos))); + ret.append(hecl::UTF8ToChar16(UniqueID32(path).toString())); + ret.push_back(u';'); + it = str.begin() + scpos + 1; + } else { + auto scpos = str.find(u';', it - str.begin()); + if (scpos == std::u16string::npos) { + it = str.end(); + } else { + auto end = str.begin() + scpos + 1; + ret.insert(ret.end(), it, end); + it = end; } + } + } else { + ret.push_back(*it); + ++it; } - - /* Failsafe */ - auto scpos = str.find(u';', it - str.begin()); - if (scpos == std::u16string::npos) - return str.end(); - return str.begin() + scpos + 1; + } + return ret; } -static std::u16string UncookString(std::u16string_view str) -{ - std::u16string ret; - ret.reserve(str.size()); - for (auto it = str.begin(); it != str.end();) - { - if (*it == u'&') - { - ret.push_back(u'&'); - ++it; - if (!str.compare(it - str.begin(), 5, u"image")) - { - ret.append(u"image="); - it += 6; - if (!str.compare(it - str.begin(), 1, u"A")) - { - it = SkipCommas(ret, str, it, 2); - it = UncookTextureList(ret, str, it); - continue; - } - else if (!str.compare(it - str.begin(), 2, u"SA")) - { - it = SkipCommas(ret, str, it, 4); - it = UncookTextureList(ret, str, it); - continue; - } - else if (!str.compare(it - str.begin(), 2, u"SI")) - { - it = SkipCommas(ret, str, it, 3); - it = UncookTextureList(ret, str, it); - continue; - } - } - else if (!str.compare(it - str.begin(), 4, u"font")) - { - ret.append(u"font="); - it += 5; - UniqueID32 id = ParseTag(&*it); - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id, true); - ret.append(hecl::UTF8ToChar16(path ? path.getRelativePathUTF8() : id.toString())); - - ret.push_back(u';'); - auto scpos = str.find(u';', it - str.begin()); - if (scpos == std::u16string::npos) - it = str.end(); - else - it = str.begin() + scpos + 1; +void STRG::gatherDependencies(std::vector& pathsOut) const { + std::u16string skip; + for (const auto& lang : langs) { + for (const std::u16string& str : lang.second) { + std::u16string_view strView(str); + for (auto it = strView.begin(); it != strView.end();) { + if (*it == u'&') { + ++it; + if (!str.compare(it - strView.begin(), 5, u"image")) { + it += 6; + if (!str.compare(it - strView.begin(), 1, u"A")) { + it = SkipCommas(skip, str, it, 2); + it = GatherTextureList(pathsOut, str, it); + continue; + } else if (!str.compare(it - strView.begin(), 2, u"SA")) { + it = SkipCommas(skip, str, it, 4); + it = GatherTextureList(pathsOut, str, it); + continue; + } else if (!str.compare(it - strView.begin(), 2, u"SI")) { + it = SkipCommas(skip, str, it, 3); + it = GatherTextureList(pathsOut, str, it); + continue; } + } else if (!str.compare(it - strView.begin(), 4, u"font")) { + it += 5; + auto scpos = str.find(u';', it - strView.begin()); + if (scpos == std::u16string::npos) + Log.report(logvisor::Fatal, "Missing semicolon token while pasing font tag"); + hecl::ProjectPath path = UniqueIDBridge::MakePathFromString( + hecl::Char16ToUTF8(std::u16string(it, strView.begin() + scpos))); + if (path) + pathsOut.push_back(path); + it = strView.begin() + scpos + 1; + } else { + auto scpos = str.find(u';', it - strView.begin()); + if (scpos == std::u16string::npos) + it = strView.end(); else - { - auto scpos = str.find(u';', it - str.begin()); - if (scpos == std::u16string::npos) - { - it = str.end(); - } - else - { - auto end = str.begin() + scpos + 1; - ret.insert(ret.end(), it, end); - it = end; - } - } - } - else - { - ret.push_back(*it); - ++it; - } + it = strView.begin() + scpos + 1; + } + } else + ++it; + } } - return ret; + } } -static std::u16string CookString(std::u16string_view str) -{ - std::u16string ret; - ret.reserve(str.size()); - for (auto it = str.begin(); it != str.end();) - { - if (*it == u'&') - { - ret.push_back(u'&'); - ++it; - if (!str.compare(it - str.begin(), 5, u"image")) - { - ret.append(u"image="); - it += 6; - if (!str.compare(it - str.begin(), 1, u"A")) - { - it = SkipCommas(ret, str, it, 2); - it = CookTextureList(ret, str, it); - continue; - } - else if (!str.compare(it - str.begin(), 2, u"SA")) - { - it = SkipCommas(ret, str, it, 4); - it = CookTextureList(ret, str, it); - continue; - } - else if (!str.compare(it - str.begin(), 2, u"SI")) - { - it = SkipCommas(ret, str, it, 3); - it = CookTextureList(ret, str, it); - continue; - } - } - else if (!str.compare(it - str.begin(), 4, u"font")) - { - ret.append(u"font="); - it += 5; - auto scpos = str.find(u';', it - str.begin()); - if (scpos == std::u16string::npos) - Log.report(logvisor::Fatal, "Missing semicolon token while pasing font tag"); - hecl::ProjectPath path = UniqueIDBridge::MakePathFromString( - hecl::Char16ToUTF8(std::u16string(it, str.begin() + scpos))); - ret.append(hecl::UTF8ToChar16(UniqueID32(path).toString())); - ret.push_back(u';'); - it = str.begin() + scpos + 1; - } - else - { - auto scpos = str.find(u';', it - str.begin()); - if (scpos == std::u16string::npos) - { - it = str.end(); - } - else - { - auto end = str.begin() + scpos + 1; - ret.insert(ret.end(), it, end); - it = end; - } - } - } - else - { - ret.push_back(*it); - ++it; - } +void STRG::_read(athena::io::IStreamReader& reader) { + atUint32 langCount = reader.readUint32Big(); + atUint32 strCount = reader.readUint32Big(); + + std::vector> readLangs; + + readLangs.reserve(langCount); + for (atUint32 l = 0; l < langCount; ++l) { + DNAFourCC lang; + lang.read(reader); + atUint32 off = reader.readUint32Big(); + readLangs.emplace_back(lang, off); + } + + atUint32 tablesStart = reader.position(); + langs.clear(); + langs.reserve(skLanguages.size()); + for (const std::pair& lang : readLangs) { + std::vector strs; + reader.seek(tablesStart + lang.second, athena::SeekOrigin::Begin); + reader.readUint32Big(); // table size + atUint32 langStart = reader.position(); + for (atUint32 s = 0; s < strCount; ++s) { + atUint32 strOffset = reader.readUint32Big(); + atUint32 tmpOffset = reader.position(); + reader.seek(langStart + strOffset, athena::SeekOrigin::Begin); + strs.emplace_back(UncookString(reader.readU16StringBig())); + reader.seek(tmpOffset, athena::SeekOrigin::Begin); } - return ret; -} + langs.emplace_back(lang.first, strs); + } -void STRG::gatherDependencies(std::vector& pathsOut) const -{ - std::u16string skip; - for (const auto& lang : langs) - { - for (const std::u16string& str : lang.second) - { - std::u16string_view strView(str); - for (auto it = strView.begin(); it != strView.end();) - { - if (*it == u'&') - { - ++it; - if (!str.compare(it - strView.begin(), 5, u"image")) - { - it += 6; - if (!str.compare(it - strView.begin(), 1, u"A")) - { - it = SkipCommas(skip, str, it, 2); - it = GatherTextureList(pathsOut, str, it); - continue; - } - else if (!str.compare(it - strView.begin(), 2, u"SA")) - { - it = SkipCommas(skip, str, it, 4); - it = GatherTextureList(pathsOut, str, it); - continue; - } - else if (!str.compare(it - strView.begin(), 2, u"SI")) - { - it = SkipCommas(skip, str, it, 3); - it = GatherTextureList(pathsOut, str, it); - continue; - } - } - else if (!str.compare(it - strView.begin(), 4, u"font")) - { - it += 5; - auto scpos = str.find(u';', it - strView.begin()); - if (scpos == std::u16string::npos) - Log.report(logvisor::Fatal, "Missing semicolon token while pasing font tag"); - hecl::ProjectPath path = UniqueIDBridge::MakePathFromString( - hecl::Char16ToUTF8(std::u16string(it, strView.begin() + scpos))); - if (path) - pathsOut.push_back(path); - it = strView.begin() + scpos + 1; - } - else - { - auto scpos = str.find(u';', it - strView.begin()); - if (scpos == std::u16string::npos) - it = strView.end(); - else - it = strView.begin() + scpos + 1; - } - } - else - ++it; - } - } - } -} - -void STRG::_read(athena::io::IStreamReader& reader) -{ - atUint32 langCount = reader.readUint32Big(); - atUint32 strCount = reader.readUint32Big(); - - std::vector> readLangs; - - readLangs.reserve(langCount); - for (atUint32 l = 0; l < langCount; ++l) - { - DNAFourCC lang; - lang.read(reader); - atUint32 off = reader.readUint32Big(); - readLangs.emplace_back(lang, off); - } - - atUint32 tablesStart = reader.position(); - langs.clear(); - langs.reserve(skLanguages.size()); - for (const std::pair& lang : readLangs) - { - std::vector strs; - reader.seek(tablesStart + lang.second, athena::SeekOrigin::Begin); - reader.readUint32Big(); // table size - atUint32 langStart = reader.position(); - for (atUint32 s = 0; s < strCount; ++s) - { - atUint32 strOffset = reader.readUint32Big(); - atUint32 tmpOffset = reader.position(); - reader.seek(langStart + strOffset, athena::SeekOrigin::Begin); - strs.emplace_back(UncookString(reader.readU16StringBig())); - reader.seek(tmpOffset, athena::SeekOrigin::Begin); - } - langs.emplace_back(lang.first, strs); - } - - langMap.clear(); - langMap.reserve(langCount); - for (std::pair>& item : langs) - langMap.emplace(item.first, &item.second); + langMap.clear(); + langMap.reserve(langCount); + for (std::pair>& item : langs) + langMap.emplace(item.first, &item.second); } template <> -void STRG::Enumerate(typename Read::StreamT& reader) -{ - atUint32 magic = reader.readUint32Big(); - if (magic != 0x87654321) - Log.report(logvisor::Error, "invalid STRG magic"); +void STRG::Enumerate(typename Read::StreamT& reader) { + atUint32 magic = reader.readUint32Big(); + if (magic != 0x87654321) + Log.report(logvisor::Error, "invalid STRG magic"); - atUint32 version = reader.readUint32Big(); - if (version != 0) - Log.report(logvisor::Error, "invalid STRG version"); + atUint32 version = reader.readUint32Big(); + if (version != 0) + Log.report(logvisor::Error, "invalid STRG version"); - _read(reader); + _read(reader); } template <> -void STRG::Enumerate(typename Write::StreamT& writer) -{ - writer.writeUint32Big(0x87654321); - writer.writeUint32Big(0); - writer.writeUint32Big(langs.size()); - atUint32 strCount = STRG::count(); - writer.writeUint32Big(strCount); +void STRG::Enumerate(typename Write::StreamT& writer) { + writer.writeUint32Big(0x87654321); + writer.writeUint32Big(0); + writer.writeUint32Big(langs.size()); + atUint32 strCount = STRG::count(); + writer.writeUint32Big(strCount); - std::vector strings; - strings.reserve(strCount * langs.size()); + std::vector strings; + strings.reserve(strCount * langs.size()); - atUint32 offset = 0; - for (const std::pair>& lang : langs) - { - DNAFourCC(lang.first).write(writer); - writer.writeUint32Big(offset); - offset += strCount * 4 + 4; - atUint32 langStrCount = lang.second.size(); - for (atUint32 s = 0; s < strCount; ++s) - { - std::u16string str = CookString(lang.second[s]); - atUint32 chCount = str.size(); - if (s < langStrCount) - offset += (chCount + 1) * 2; - else - offset += 1; - strings.push_back(std::move(str)); - } + atUint32 offset = 0; + for (const std::pair>& lang : langs) { + DNAFourCC(lang.first).write(writer); + writer.writeUint32Big(offset); + offset += strCount * 4 + 4; + atUint32 langStrCount = lang.second.size(); + for (atUint32 s = 0; s < strCount; ++s) { + std::u16string str = CookString(lang.second[s]); + atUint32 chCount = str.size(); + if (s < langStrCount) + offset += (chCount + 1) * 2; + else + offset += 1; + strings.push_back(std::move(str)); + } + } + + auto langIt = strings.cbegin(); + for (const std::pair>& lang : langs) { + atUint32 langStrCount = lang.second.size(); + atUint32 tableSz = strCount * 4; + auto strIt = langIt; + for (atUint32 s = 0; s < strCount; ++s) { + if (s < langStrCount) + tableSz += ((strIt++)->size() + 1) * 2; + else + tableSz += 1; + } + writer.writeUint32Big(tableSz); + + offset = strCount * 4; + strIt = langIt; + for (atUint32 s = 0; s < strCount; ++s) { + writer.writeUint32Big(offset); + if (s < langStrCount) + offset += ((strIt++)->size() + 1) * 2; + else + offset += 1; } - auto langIt = strings.cbegin(); - for (const std::pair>& lang : langs) - { - atUint32 langStrCount = lang.second.size(); - atUint32 tableSz = strCount * 4; - auto strIt = langIt; - for (atUint32 s = 0; s < strCount; ++s) - { - if (s < langStrCount) - tableSz += ((strIt++)->size() + 1) * 2; - else - tableSz += 1; - } - writer.writeUint32Big(tableSz); - - offset = strCount * 4; - strIt = langIt; - for (atUint32 s = 0; s < strCount; ++s) - { - writer.writeUint32Big(offset); - if (s < langStrCount) - offset += ((strIt++)->size() + 1) * 2; - else - offset += 1; - } - - strIt = langIt; - for (atUint32 s = 0; s < strCount; ++s) - { - if (s < langStrCount) - writer.writeU16StringBig(*strIt++); - else - writer.writeUByte(0); - } - - langIt = strIt; + strIt = langIt; + for (atUint32 s = 0; s < strCount; ++s) { + if (s < langStrCount) + writer.writeU16StringBig(*strIt++); + else + writer.writeUByte(0); } + + langIt = strIt; + } } template <> -void STRG::Enumerate(typename BinarySize::StreamT& _s) -{ - _s += 16; - _s += langs.size() * 12; +void STRG::Enumerate(typename BinarySize::StreamT& _s) { + _s += 16; + _s += langs.size() * 12; - size_t strCount = STRG::count(); - _s += langs.size() * strCount * 4; - for (const std::pair>& lang : langs) - { - atUint32 langStrCount = lang.second.size(); - for (atUint32 s = 0; s < strCount; ++s) - { - if (s < langStrCount) - _s += (CookString(lang.second[s]).size() + 1) * 2; - else - _s += 1; - } + size_t strCount = STRG::count(); + _s += langs.size() * strCount * 4; + for (const std::pair>& lang : langs) { + atUint32 langStrCount = lang.second.size(); + for (atUint32 s = 0; s < strCount; ++s) { + if (s < langStrCount) + _s += (CookString(lang.second[s]).size() + 1) * 2; + else + _s += 1; } + } } template <> -void STRG::Enumerate(typename ReadYaml::StreamT& reader) -{ - const athena::io::YAMLNode* root = reader.getRootNode(); +void STRG::Enumerate(typename ReadYaml::StreamT& reader) { + const athena::io::YAMLNode* root = reader.getRootNode(); - /* Validate Pass */ - if (root->m_type == YAML_MAPPING_NODE) - { - for (const auto& lang : root->m_mapChildren) - { - if (lang.first == "DNAType") - continue; + /* Validate Pass */ + if (root->m_type == YAML_MAPPING_NODE) { + for (const auto& lang : root->m_mapChildren) { + if (lang.first == "DNAType") + continue; - if (lang.first.size() != 4) - { - Log.report(logvisor::Warning, "STRG language string '%s' must be exactly 4 characters; skipping", - lang.first.c_str()); - return; - } - if (lang.second->m_type != YAML_SEQUENCE_NODE) - { - Log.report(logvisor::Warning, "STRG language string '%s' must contain a sequence; skipping", - lang.first.c_str()); - return; - } - for (const auto& str : lang.second->m_seqChildren) - { - if (str->m_type != YAML_SCALAR_NODE) - { - Log.report(logvisor::Warning, "STRG language '%s' must contain all scalars; skipping", - lang.first.c_str()); - return; - } - } - } - } - else - { - Log.report(logvisor::Warning, "STRG must have a mapping root node; skipping"); + if (lang.first.size() != 4) { + Log.report(logvisor::Warning, "STRG language string '%s' must be exactly 4 characters; skipping", + lang.first.c_str()); return; + } + if (lang.second->m_type != YAML_SEQUENCE_NODE) { + Log.report(logvisor::Warning, "STRG language string '%s' must contain a sequence; skipping", + lang.first.c_str()); + return; + } + for (const auto& str : lang.second->m_seqChildren) { + if (str->m_type != YAML_SCALAR_NODE) { + Log.report(logvisor::Warning, "STRG language '%s' must contain all scalars; skipping", lang.first.c_str()); + return; + } + } } + } else { + Log.report(logvisor::Warning, "STRG must have a mapping root node; skipping"); + return; + } - /* Read Pass */ - langs.clear(); - for (const auto& lang : root->m_mapChildren) - { - if (lang.first == "DNAType") - continue; + /* Read Pass */ + langs.clear(); + for (const auto& lang : root->m_mapChildren) { + if (lang.first == "DNAType") + continue; - std::vector strs; - for (const auto& str : lang.second->m_seqChildren) - strs.emplace_back(hecl::UTF8ToChar16(str->m_scalarString)); - langs.emplace_back(FourCC(lang.first.c_str()), strs); - } + std::vector strs; + for (const auto& str : lang.second->m_seqChildren) + strs.emplace_back(hecl::UTF8ToChar16(str->m_scalarString)); + langs.emplace_back(FourCC(lang.first.c_str()), strs); + } - langMap.clear(); - langMap.reserve(langs.size()); - for (auto& item : langs) - langMap.emplace(item.first, &item.second); + langMap.clear(); + langMap.reserve(langs.size()); + for (auto& item : langs) + langMap.emplace(item.first, &item.second); } template <> -void STRG::Enumerate(typename WriteYaml::StreamT& writer) -{ - for (const auto& lang : langs) - { - if (auto v = writer.enterSubVector(lang.first.toString().c_str())) - for (const std::u16string& str : lang.second) - writer.writeU16String(nullptr, str); - } +void STRG::Enumerate(typename WriteYaml::StreamT& writer) { + for (const auto& lang : langs) { + if (auto v = writer.enterSubVector(lang.first.toString().c_str())) + for (const std::u16string& str : lang.second) + writer.writeU16String(nullptr, str); + } } const char* STRG::DNAType() { return "urde::DNAMP1::STRG"; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/STRG.hpp b/DataSpec/DNAMP1/STRG.hpp index ebf282abe..0d1af14eb 100644 --- a/DataSpec/DNAMP1/STRG.hpp +++ b/DataSpec/DNAMP1/STRG.hpp @@ -5,84 +5,73 @@ #include "DataSpec/DNACommon/STRG.hpp" #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct STRG : ISTRG -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_DECL_DNAV - void _read(athena::io::IStreamReader& reader); - std::vector>> langs; - std::unordered_map*> langMap; +struct STRG : ISTRG { + AT_DECL_EXPLICIT_DNA_YAML + AT_DECL_DNAV + void _read(athena::io::IStreamReader& reader); + std::vector>> langs; + std::unordered_map*> langMap; - int32_t lookupIdx(std::string_view name) const {return -1;} + int32_t lookupIdx(std::string_view name) const { return -1; } - size_t count() const - { - size_t retval = 0; - for (const auto& item : langs) - { - size_t sz = item.second.size(); - if (sz > retval) - retval = sz; - } - return retval; + size_t count() const { + size_t retval = 0; + for (const auto& item : langs) { + size_t sz = item.second.size(); + if (sz > retval) + retval = sz; } - std::string getUTF8(const FourCC& lang, size_t idx) const - { - auto search = langMap.find(lang); - if (search != langMap.end()) - return hecl::Char16ToUTF8(search->second->at(idx)); - return std::string(); - } - std::u16string getUTF16(const FourCC& lang, size_t idx) const - { - auto search = langMap.find(lang); - if (search != langMap.end()) - return search->second->at(idx); - return std::u16string(); - } - hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const - { - auto search = langMap.find(lang); - if (search != langMap.end()) + return retval; + } + std::string getUTF8(const FourCC& lang, size_t idx) const { + auto search = langMap.find(lang); + if (search != langMap.end()) + return hecl::Char16ToUTF8(search->second->at(idx)); + return std::string(); + } + std::u16string getUTF16(const FourCC& lang, size_t idx) const { + auto search = langMap.find(lang); + if (search != langMap.end()) + return search->second->at(idx); + return std::u16string(); + } + hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const { + auto search = langMap.find(lang); + if (search != langMap.end()) #if HECL_UCS2 - return hecl::Char16ToWide(search->second->at(idx)); + return hecl::Char16ToWide(search->second->at(idx)); #else - return hecl::Char16ToUTF8(search->second->at(idx)); + return hecl::Char16ToUTF8(search->second->at(idx)); #endif - return hecl::SystemString(); - } + return hecl::SystemString(); + } - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) - { - STRG strg; - strg.read(rs); - athena::io::TransactionalFileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(strg, writer); - return true; - } + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + STRG strg; + strg.read(rs); + athena::io::TransactionalFileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(strg, writer); + return true; + } - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) - { - STRG strg; - athena::io::FileReader reader(inPath.getAbsolutePath()); - athena::io::FromYAMLStream(strg, reader); - athena::io::TransactionalFileWriter ws(outPath.getAbsolutePath()); - strg.write(ws); - return true; - } + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + STRG strg; + athena::io::FileReader reader(inPath.getAbsolutePath()); + athena::io::FromYAMLStream(strg, reader); + athena::io::TransactionalFileWriter ws(outPath.getAbsolutePath()); + strg.write(ws); + return true; + } - static bool Cook(const STRG& strg, const hecl::ProjectPath& outPath) - { - athena::io::TransactionalFileWriter ws(outPath.getAbsolutePath()); - strg.write(ws); - return true; - } + static bool Cook(const STRG& strg, const hecl::ProjectPath& outPath) { + athena::io::TransactionalFileWriter ws(outPath.getAbsolutePath()); + strg.write(ws); + return true; + } - void gatherDependencies(std::vector &pathsOut) const; + void gatherDependencies(std::vector& pathsOut) const; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/AIJumpPoint.hpp b/DataSpec/DNAMP1/ScriptObjects/AIJumpPoint.hpp index 5a16e821c..7b77c7eae 100644 --- a/DataSpec/DNAMP1/ScriptObjects/AIJumpPoint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/AIJumpPoint.hpp @@ -4,17 +4,14 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct AIJumpPoint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value active; - Value unknown1; +namespace DataSpec::DNAMP1 { +struct AIJumpPoint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value active; + Value unknown1; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/AIKeyframe.hpp b/DataSpec/DNAMP1/ScriptObjects/AIKeyframe.hpp index e7fc8c468..25c066aef 100644 --- a/DataSpec/DNAMP1/ScriptObjects/AIKeyframe.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/AIKeyframe.hpp @@ -3,20 +3,17 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct AIKeyframe : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; +struct AIKeyframe : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Actor.cpp b/DataSpec/DNAMP1/ScriptObjects/Actor.cpp index 067be34bb..502a5f72c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Actor.cpp +++ b/DataSpec/DNAMP1/ScriptObjects/Actor.cpp @@ -1,37 +1,31 @@ #include "Actor.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -zeus::CAABox Actor::getVISIAABB(hecl::blender::Token& btok) const -{ - hecl::blender::Connection& conn = btok.getBlenderConnection(); - zeus::CAABox aabbOut; +zeus::CAABox Actor::getVISIAABB(hecl::blender::Token& btok) const { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + zeus::CAABox aabbOut; - if (model) - { - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(model); - conn.openBlend(path); - hecl::blender::DataStream ds = conn.beginData(); - auto aabb = ds.getMeshAABB(); - aabbOut = zeus::CAABox(aabb.first, aabb.second); - } - else if (animationParameters.animationCharacterSet) - { - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath( - animationParameters.animationCharacterSet); - conn.openBlend(path.getWithExtension(_SYS_STR(".blend"), true)); - hecl::blender::DataStream ds = conn.beginData(); - auto aabb = ds.getMeshAABB(); - aabbOut = zeus::CAABox(aabb.first, aabb.second); - } + if (model) { + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(model); + conn.openBlend(path); + hecl::blender::DataStream ds = conn.beginData(); + auto aabb = ds.getMeshAABB(); + aabbOut = zeus::CAABox(aabb.first, aabb.second); + } else if (animationParameters.animationCharacterSet) { + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(animationParameters.animationCharacterSet); + conn.openBlend(path.getWithExtension(_SYS_STR(".blend"), true)); + hecl::blender::DataStream ds = conn.beginData(); + auto aabb = ds.getMeshAABB(); + aabbOut = zeus::CAABox(aabb.first, aabb.second); + } - if (aabbOut.min.x() > aabbOut.max.x()) - return {}; + if (aabbOut.min.x() > aabbOut.max.x()) + return {}; - zeus::CTransform xf = ConvertEditorEulerToTransform4f(scale, orientation, location); - return aabbOut.getTransformedAABox(xf); + zeus::CTransform xf = ConvertEditorEulerToTransform4f(scale, orientation, location); + return aabbOut.getTransformedAABox(xf); } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Actor.hpp b/DataSpec/DNAMP1/ScriptObjects/Actor.hpp index 2ccdd7284..4dbb1db32 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Actor.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Actor.hpp @@ -3,67 +3,56 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Actor : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name SO_NAME_SPECPROP(); - Value location SO_LOCATION_SPECPROP(); - Value orientation SO_ORIENTATION_SPECPROP(); - Value scale SO_SCALE_SPECPROP(); - Value collisionExtent SO_COLLISION_EXTENT_SPECPROP(); - Value collisionOffset SO_COLLISION_OFFSET_SPECPROP(); - Value mass; - Value zMomentum; - HealthInfo healthInfo; - DamageVulnerability damageVulnerability; - UniqueID32 model; - AnimationParameters animationParameters; - ActorParameters actorParameters; - Value looping; - Value snow; - Value solid; - Value cameraPassthrough; - Value active; - Value shaderIdx; - Value xrayAlpha; - Value noThermalHotZ; - Value castsShadow; - Value scaleAdvancementDelta; - Value materialFlag54; +namespace DataSpec::DNAMP1 { +struct Actor : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name SO_NAME_SPECPROP(); + Value location SO_LOCATION_SPECPROP(); + Value orientation SO_ORIENTATION_SPECPROP(); + Value scale SO_SCALE_SPECPROP(); + Value collisionExtent SO_COLLISION_EXTENT_SPECPROP(); + Value collisionOffset SO_COLLISION_OFFSET_SPECPROP(); + Value mass; + Value zMomentum; + HealthInfo healthInfo; + DamageVulnerability damageVulnerability; + UniqueID32 model; + AnimationParameters animationParameters; + ActorParameters actorParameters; + Value looping; + Value snow; + Value solid; + Value cameraPassthrough; + Value active; + Value shaderIdx; + Value xrayAlpha; + Value noThermalHotZ; + Value castsShadow; + Value scaleAdvancementDelta; + Value materialFlag54; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } + + void nameIDs(PAKRouter& pakRouter) const { + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; } + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(model, pathsOut); + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(model, pathsOut); - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } - - zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const; + zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ActorContraption.hpp b/DataSpec/DNAMP1/ScriptObjects/ActorContraption.hpp index bff8c616c..063bc9734 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ActorContraption.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ActorContraption.hpp @@ -4,56 +4,45 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ActorContraption : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - Value unknown1; - Value scanOffset; - Value unknown2; - Value unknown3; - HealthInfo healthInfo; - DamageVulnerability damageVulnerability; - AnimationParameters animationParameters; - ActorParameters actorParameters; - UniqueID32 particle; - DamageInfo damageInfo; - Value active; // needs verification +namespace DataSpec::DNAMP1 { +struct ActorContraption : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + Value unknown1; + Value scanOffset; + Value unknown2; + Value unknown3; + HealthInfo healthInfo; + DamageVulnerability damageVulnerability; + AnimationParameters animationParameters; + ActorParameters actorParameters; + UniqueID32 particle; + DamageInfo damageInfo; + Value active; // needs verification - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; } + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle, pathsOut); - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle, pathsOut); + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ActorKeyframe.hpp b/DataSpec/DNAMP1/ScriptObjects/ActorKeyframe.hpp index 01d1cf84b..30e6c362f 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ActorKeyframe.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ActorKeyframe.hpp @@ -4,19 +4,16 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ActorKeyframe : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value animationId; - Value looping; - Value lifetime; - Value active; - Value fadeOut; - Value totalPlayback; +namespace DataSpec::DNAMP1 { +struct ActorKeyframe : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value animationId; + Value looping; + Value lifetime; + Value active; + Value fadeOut; + Value totalPlayback; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ActorRotate.hpp b/DataSpec/DNAMP1/ScriptObjects/ActorRotate.hpp index 65eb3dde1..774847722 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ActorRotate.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ActorRotate.hpp @@ -4,18 +4,15 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ActorRotate : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value rotationOffset; - Value timeScale; - Value unknown1; - Value unknown2; - Value active; +namespace DataSpec::DNAMP1 { +struct ActorRotate : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value rotationOffset; + Value timeScale; + Value unknown1; + Value unknown2; + Value active; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/AmbientAI.hpp b/DataSpec/DNAMP1/ScriptObjects/AmbientAI.hpp index 1e8b57119..c399cbff6 100644 --- a/DataSpec/DNAMP1/ScriptObjects/AmbientAI.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/AmbientAI.hpp @@ -4,51 +4,41 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct AmbientAI : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - Value collisionExtent; - Value collisionOffset; - Value mass; - HealthInfo healthInfo; - DamageVulnerability damageVulnerability; - AnimationParameters animationParameters; - ActorParameters actorParameters; - Value alertRange; - Value impactRange; - Value alertAnim; - Value impactAnim; - Value active; +namespace DataSpec::DNAMP1 { +struct AmbientAI : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + Value collisionExtent; + Value collisionOffset; + Value mass; + HealthInfo healthInfo; + DamageVulnerability damageVulnerability; + AnimationParameters animationParameters; + ActorParameters actorParameters; + Value alertRange; + Value impactRange; + Value alertAnim; + Value impactAnim; + Value active; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/AreaAttributes.hpp b/DataSpec/DNAMP1/ScriptObjects/AreaAttributes.hpp index a8db1a6d7..1460648b4 100644 --- a/DataSpec/DNAMP1/ScriptObjects/AreaAttributes.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/AreaAttributes.hpp @@ -4,34 +4,24 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct AreaAttributes : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - enum class EWeatherType : atUint32 - { - None, - Snow, - Rain - }; +namespace DataSpec::DNAMP1 { +struct AreaAttributes : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + enum class EWeatherType : atUint32 { None, Snow, Rain }; - Value unknown1; - Value skyboxEnabled; - Value weather; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - UniqueID32 skybox; - Value unknown6; + Value unknown1; + Value skyboxEnabled; + Value weather; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + UniqueID32 skybox; + Value unknown6; - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(skybox, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(skybox, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/AtomicAlpha.hpp b/DataSpec/DNAMP1/ScriptObjects/AtomicAlpha.hpp index c7c57cb01..e95b31966 100644 --- a/DataSpec/DNAMP1/ScriptObjects/AtomicAlpha.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/AtomicAlpha.hpp @@ -4,61 +4,49 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct AtomicAlpha : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - UniqueID32 wpsc; - UniqueID32 model; - DamageInfo damageInfo; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; +namespace DataSpec::DNAMP1 { +struct AtomicAlpha : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + UniqueID32 wpsc; + UniqueID32 model; + DamageInfo damageInfo; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); - ent->name = name + "_wpsc"; - } - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); + ent->name = name + "_wpsc"; } + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc, pathsOut); - g_curSpec->flattenDependencies(model, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc, pathsOut); + g_curSpec->flattenDependencies(model, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/AtomicBeta.hpp b/DataSpec/DNAMP1/ScriptObjects/AtomicBeta.hpp index 0ff7e317f..a10a7bebd 100644 --- a/DataSpec/DNAMP1/ScriptObjects/AtomicBeta.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/AtomicBeta.hpp @@ -4,74 +4,61 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct AtomicBeta : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - UniqueID32 elsc; - UniqueID32 wpsc; - DamageInfo damageInfo; - UniqueID32 part; - Value unknown1; - Value unknown2; - Value unknown3; - DamageVulnerability damageVulnerabilty; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; +namespace DataSpec::DNAMP1 { +struct AtomicBeta : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + UniqueID32 elsc; + UniqueID32 wpsc; + DamageInfo damageInfo; + UniqueID32 part; + Value unknown1; + Value unknown2; + Value unknown3; + DamageVulnerability damageVulnerabilty; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (elsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); - ent->name = name + "_elsc"; - } - if (wpsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); - ent->name = name + "_wpsc"; - } - if (part) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(part); - ent->name = name + "_part"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (elsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); + ent->name = name + "_elsc"; } + if (wpsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); + ent->name = name + "_wpsc"; + } + if (part) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(part); + ent->name = name + "_part"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(elsc, pathsOut); - g_curSpec->flattenDependencies(wpsc, pathsOut); - g_curSpec->flattenDependencies(part, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(elsc, pathsOut); + g_curSpec->flattenDependencies(wpsc, pathsOut); + g_curSpec->flattenDependencies(part, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Babygoth.hpp b/DataSpec/DNAMP1/ScriptObjects/Babygoth.hpp index ab8e80952..11d1b6e94 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Babygoth.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Babygoth.hpp @@ -4,144 +4,121 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Babygoth : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - UniqueID32 wpsc1; - DamageInfo damageInfo1; - DamageInfo damageInfo2; - UniqueID32 wpsc2; - UniqueID32 particle1; - DamageInfo damageInfo3; - DamageVulnerability damageVulnerabilty1; - DamageVulnerability damageVulnerabilty2; - UniqueID32 cmdlShelless; - UniqueID32 cskrShelless; - Value unknown3; - Value unknown4; - UniqueID32 particle2; - UniqueID32 particle3; - UniqueID32 particle4; - UniqueID32 particle5; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - UniqueID32 texture; - Value unknown11; - UniqueID32 particle6; +namespace DataSpec::DNAMP1 { +struct Babygoth : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + UniqueID32 wpsc1; + DamageInfo damageInfo1; + DamageInfo damageInfo2; + UniqueID32 wpsc2; + UniqueID32 particle1; + DamageInfo damageInfo3; + DamageVulnerability damageVulnerabilty1; + DamageVulnerability damageVulnerabilty2; + UniqueID32 cmdlShelless; + UniqueID32 cskrShelless; + Value unknown3; + Value unknown4; + UniqueID32 particle2; + UniqueID32 particle3; + UniqueID32 particle4; + UniqueID32 particle5; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + UniqueID32 texture; + Value unknown11; + UniqueID32 particle6; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - UniqueID32 cinf = patternedInfo.animationParameters.getCINF(pakRouter); - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + UniqueID32 cinf = patternedInfo.animationParameters.getCINF(pakRouter); + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - if (cmdlShelless && cskrShelless) - { - charAssoc.m_cmdlRigs[cmdlShelless] = std::make_pair(cskrShelless, cinf); - charAssoc.m_cskrCinfToCharacter[cskrShelless] = std::make_pair( - patternedInfo.animationParameters.animationCharacterSet, "ATTACH.SHELLESS.CSKR"); - charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, - {}, cmdlShelless, "SHELLESS"); - } + if (cmdlShelless && cskrShelless) { + charAssoc.m_cmdlRigs[cmdlShelless] = std::make_pair(cskrShelless, cinf); + charAssoc.m_cskrCinfToCharacter[cskrShelless] = + std::make_pair(patternedInfo.animationParameters.animationCharacterSet, "ATTACH.SHELLESS.CSKR"); + charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, {}, cmdlShelless, "SHELLESS"); } + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc1"; - } - if (wpsc2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); - ent->name = name + "_wpsc2"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (cmdlShelless) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cmdlShelless); - ent->name = name + "_emodel"; - } - if (cskrShelless) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cskrShelless); - ent->name = name + "_eskin"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - if (particle5) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); - ent->name = name + "_part5"; - } - if (texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); - ent->name = name + "_tex"; - } - if (particle6) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); - ent->name = name + "_part6"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc1"; } + if (wpsc2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); + ent->name = name + "_wpsc2"; + } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (cmdlShelless) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cmdlShelless); + ent->name = name + "_emodel"; + } + if (cskrShelless) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cskrShelless); + ent->name = name + "_eskin"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + if (particle5) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); + ent->name = name + "_part5"; + } + if (texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); + ent->name = name + "_tex"; + } + if (particle6) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); + ent->name = name + "_part6"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(wpsc2, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(cmdlShelless, pathsOut); - g_curSpec->flattenDependencies(cskrShelless, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - g_curSpec->flattenDependencies(particle5, pathsOut); - g_curSpec->flattenDependencies(texture, pathsOut); - g_curSpec->flattenDependencies(particle6, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(wpsc2, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(cmdlShelless, pathsOut); + g_curSpec->flattenDependencies(cskrShelless, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + g_curSpec->flattenDependencies(particle5, pathsOut); + g_curSpec->flattenDependencies(texture, pathsOut); + g_curSpec->flattenDependencies(particle6, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/BallTrigger.hpp b/DataSpec/DNAMP1/ScriptObjects/BallTrigger.hpp index 6ee229c3a..b090b02a7 100644 --- a/DataSpec/DNAMP1/ScriptObjects/BallTrigger.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/BallTrigger.hpp @@ -4,21 +4,18 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct BallTrigger : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value volume; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; +namespace DataSpec::DNAMP1 { +struct BallTrigger : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value volume; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Beetle.hpp b/DataSpec/DNAMP1/ScriptObjects/Beetle.hpp index 124e0d62f..6f3172b5c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Beetle.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Beetle.hpp @@ -4,57 +4,46 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Beetle : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - DamageInfo damageInfo; - Value unknown2; - Value unknown3; - DamageVulnerability damageVulnerabilty1; - DamageVulnerability damageVulnerabilty2; - UniqueID32 model; - Value unknown4; - Value unknown5; - Value unknown6; +namespace DataSpec::DNAMP1 { +struct Beetle : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + DamageInfo damageInfo; + Value unknown2; + Value unknown3; + DamageVulnerability damageVulnerabilty1; + DamageVulnerability damageVulnerabilty2; + UniqueID32 model; + Value unknown4; + Value unknown5; + Value unknown6; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(model, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(model, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/BloodFlower.hpp b/DataSpec/DNAMP1/ScriptObjects/BloodFlower.hpp index 00f841d39..31725c59c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/BloodFlower.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/BloodFlower.hpp @@ -4,95 +4,78 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct BloodFlower : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - UniqueID32 particle1; - UniqueID32 wpsc1; - UniqueID32 wpsc2; - DamageInfo damageInfo1; - DamageInfo damageInfo2; - DamageInfo damageInfo3; - UniqueID32 particle2; - UniqueID32 particle3; - UniqueID32 particle4; - Value unknown1; - UniqueID32 particle5; - Value unknown2; +namespace DataSpec::DNAMP1 { +struct BloodFlower : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + UniqueID32 particle1; + UniqueID32 wpsc1; + UniqueID32 wpsc2; + DamageInfo damageInfo1; + DamageInfo damageInfo2; + DamageInfo damageInfo3; + UniqueID32 particle2; + UniqueID32 particle3; + UniqueID32 particle4; + Value unknown1; + UniqueID32 particle5; + Value unknown2; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc1"; - } - if (wpsc2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); - ent->name = name + "_wpsc2"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - if (particle5) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); - ent->name = name + "_part5"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc1"; } + if (wpsc2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); + ent->name = name + "_wpsc2"; + } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + if (particle5) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); + ent->name = name + "_part5"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(wpsc2, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - g_curSpec->flattenDependencies(particle5, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(wpsc2, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + g_curSpec->flattenDependencies(particle5, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Burrower.hpp b/DataSpec/DNAMP1/ScriptObjects/Burrower.hpp index 098edfc20..332e90ed6 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Burrower.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Burrower.hpp @@ -4,78 +4,63 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Burrower : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - UniqueID32 particle1; - UniqueID32 particle2; - UniqueID32 wpsc; - DamageInfo damageInfo; - UniqueID32 particle3; - Value unknown; // always FF - UniqueID32 particle4; +namespace DataSpec::DNAMP1 { +struct Burrower : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + UniqueID32 particle1; + UniqueID32 particle2; + UniqueID32 wpsc; + DamageInfo damageInfo; + UniqueID32 particle3; + Value unknown; // always FF + UniqueID32 particle4; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); - ent->name = name + "_wpsc"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); + ent->name = name + "_wpsc"; } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Camera.hpp b/DataSpec/DNAMP1/ScriptObjects/Camera.hpp index ac5f4fd85..8803fe2dc 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Camera.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Camera.hpp @@ -4,27 +4,24 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Camera : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value active; - Value shotDuration; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value disableInput; - Value unknown9; - Value fov; - Value unknown11; - Value unknown12; +namespace DataSpec::DNAMP1 { +struct Camera : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value active; + Value shotDuration; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value disableInput; + Value unknown9; + Value fov; + Value unknown11; + Value unknown12; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/CameraBlurKeyframe.hpp b/DataSpec/DNAMP1/ScriptObjects/CameraBlurKeyframe.hpp index 56094c8f3..7993f58bb 100644 --- a/DataSpec/DNAMP1/ScriptObjects/CameraBlurKeyframe.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/CameraBlurKeyframe.hpp @@ -4,19 +4,16 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct CameraBlurKeyframe : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; - Value btype; - Value amount; - Value unk; - Value timeIn; - Value timeOut; +namespace DataSpec::DNAMP1 { +struct CameraBlurKeyframe : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; + Value btype; + Value amount; + Value unk; + Value timeIn; + Value timeOut; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/CameraFilterKeyframe.hpp b/DataSpec/DNAMP1/ScriptObjects/CameraFilterKeyframe.hpp index 68c62f4bc..f7d8d588b 100644 --- a/DataSpec/DNAMP1/ScriptObjects/CameraFilterKeyframe.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/CameraFilterKeyframe.hpp @@ -4,37 +4,30 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct CameraFilterKeyframe : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; - Value ftype; - Value shape; - Value filterIdx; - Value unk; - DNAColor color; - Value timeIn; - Value timeOut; - UniqueID32 texture; +namespace DataSpec::DNAMP1 { +struct CameraFilterKeyframe : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; + Value ftype; + Value shape; + Value filterIdx; + Value unk; + DNAColor color; + Value timeIn; + Value timeOut; + UniqueID32 texture; - void nameIDs(PAKRouter& pakRouter) const - { - if (texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); - ent->name = name + "_texture"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); + ent->name = name + "_texture"; } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(texture, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(texture, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/CameraHint.hpp b/DataSpec/DNAMP1/ScriptObjects/CameraHint.hpp index 24839a7fe..3f1575c2a 100644 --- a/DataSpec/DNAMP1/ScriptObjects/CameraHint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/CameraHint.hpp @@ -4,66 +4,60 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct CameraHint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; +namespace DataSpec::DNAMP1 { +struct CameraHint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value active; + Value priority; + Value behaviour; + struct CameraHintParameters : BigDNA { + AT_DECL_DNA + Value propertyCount; + Value calculateCamPos; // 0x1 + Value chaseAllowed; // 0x2 + Value boostAllowed; // 0x4 + Value obscureAvoidance; // 0x8 + Value volumeCollider; // 0x10 + Value applyImmediately; // 0x20 + Value lookAtBall; // 0x40 + Value hintDistanceSelection; // 0x80 + Value hintDistanceSelfPos; // 0x100 + Value controlInterpolation; // 0x200 + Value sinusoidalInterpolation; // 0x400 + Value sinusoidalInterpolationHintless; // 0x800 + Value clampVelocity; // 0x1000 + Value skipCinematic; // 0x2000 + Value noElevationInterp; // 0x4000 + Value directElevation; // 0x8000 + Value overrideLookDir; // 0x10000 + Value noElevationVelClamp; // 0x20000 + Value calculateTransformFromPrevCam; // 0x40000 + Value noSpline; // 0x80000 + Value unknown21; // 0x100000 + Value unknown22; // 0x200000 + } cameraHintParameters; + + struct BoolFloat : BigDNA { + AT_DECL_DNA Value active; - Value priority; - Value behaviour; - struct CameraHintParameters : BigDNA - { - AT_DECL_DNA - Value propertyCount; - Value calculateCamPos; // 0x1 - Value chaseAllowed; // 0x2 - Value boostAllowed; // 0x4 - Value obscureAvoidance; // 0x8 - Value volumeCollider; // 0x10 - Value applyImmediately; // 0x20 - Value lookAtBall; // 0x40 - Value hintDistanceSelection; // 0x80 - Value hintDistanceSelfPos; // 0x100 - Value controlInterpolation; // 0x200 - Value sinusoidalInterpolation; // 0x400 - Value sinusoidalInterpolationHintless; // 0x800 - Value clampVelocity; // 0x1000 - Value skipCinematic; // 0x2000 - Value noElevationInterp; // 0x4000 - Value directElevation; // 0x8000 - Value overrideLookDir; // 0x10000 - Value noElevationVelClamp; // 0x20000 - Value calculateTransformFromPrevCam; // 0x40000 - Value noSpline; // 0x80000 - Value unknown21; // 0x100000 - Value unknown22; // 0x200000 - } cameraHintParameters; - - struct BoolFloat : BigDNA - { - AT_DECL_DNA - Value active; - Value value; - } minDist, maxDist, backwardsDist; // 0x400000, 0x800000, 0x1000000 - struct BoolVec3f : BigDNA - { - AT_DECL_DNA - Value active; - Value value; - } lookAtOffset, chaseLookAtOffset; // 0x2000000, 0x4000000 - Value ballToCam; - BoolFloat fov, attitudeRange, azimuthRange, anglePerSecond; // 0x8000000, 0x10000000, 0x20000000, 0x40000000 - Value clampVelRange; - Value clampRotRange; - BoolFloat elevation; // 0x80000000 - Value interpolateTime; - Value clampVelTime; - Value controlInterpDur; + Value value; + } minDist, maxDist, backwardsDist; // 0x400000, 0x800000, 0x1000000 + struct BoolVec3f : BigDNA { + AT_DECL_DNA + Value active; + Value value; + } lookAtOffset, chaseLookAtOffset; // 0x2000000, 0x4000000 + Value ballToCam; + BoolFloat fov, attitudeRange, azimuthRange, anglePerSecond; // 0x8000000, 0x10000000, 0x20000000, 0x40000000 + Value clampVelRange; + Value clampRotRange; + BoolFloat elevation; // 0x80000000 + Value interpolateTime; + Value clampVelTime; + Value controlInterpDur; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/CameraHintTrigger.hpp b/DataSpec/DNAMP1/ScriptObjects/CameraHintTrigger.hpp index f55f61f57..f971444d5 100644 --- a/DataSpec/DNAMP1/ScriptObjects/CameraHintTrigger.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/CameraHintTrigger.hpp @@ -4,19 +4,16 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct CameraHintTrigger : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value volume; - Value unknown1; - Value unknown2; - Value unknown3; +namespace DataSpec::DNAMP1 { +struct CameraHintTrigger : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value volume; + Value unknown1; + Value unknown2; + Value unknown3; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/CameraPitchVolume.hpp b/DataSpec/DNAMP1/ScriptObjects/CameraPitchVolume.hpp index 6804e67db..380c40131 100644 --- a/DataSpec/DNAMP1/ScriptObjects/CameraPitchVolume.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/CameraPitchVolume.hpp @@ -4,20 +4,17 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct CameraPitchVolume : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value volume; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; +namespace DataSpec::DNAMP1 { +struct CameraPitchVolume : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value volume; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/CameraShaker.hpp b/DataSpec/DNAMP1/ScriptObjects/CameraShaker.hpp index 88fc7a42d..7a304cc31 100644 --- a/DataSpec/DNAMP1/ScriptObjects/CameraShaker.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/CameraShaker.hpp @@ -4,21 +4,18 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct CameraShaker : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value xMag; - Value xB; - Value yMag; - Value yB; - Value zMag; - Value zB; - Value duration; - Value active; +namespace DataSpec::DNAMP1 { +struct CameraShaker : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value xMag; + Value xB; + Value yMag; + Value yB; + Value zMag; + Value zB; + Value duration; + Value active; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/CameraWaypoint.hpp b/DataSpec/DNAMP1/ScriptObjects/CameraWaypoint.hpp index 2071be251..76f00591d 100644 --- a/DataSpec/DNAMP1/ScriptObjects/CameraWaypoint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/CameraWaypoint.hpp @@ -4,18 +4,15 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct CameraWaypoint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value active; - Value unknown2; - Value unknown3; +namespace DataSpec::DNAMP1 { +struct CameraWaypoint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value active; + Value unknown2; + Value unknown3; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ChozoGhost.hpp b/DataSpec/DNAMP1/ScriptObjects/ChozoGhost.hpp index d0d9ba817..0defcb83a 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ChozoGhost.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ChozoGhost.hpp @@ -4,84 +4,71 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ChozoGhost : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - UniqueID32 wpsc1; - DamageInfo damageInfo1; - UniqueID32 wpsc2; - DamageInfo damageInfo2; - BehaveChance BehaveChance1; - BehaveChance BehaveChance2; - BehaveChance BehaveChance3; - Value sound1; - Value unknown5; - Value sound2; - Value sound3; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - UniqueID32 particle; - Value soundId4; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; +namespace DataSpec::DNAMP1 { +struct ChozoGhost : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + UniqueID32 wpsc1; + DamageInfo damageInfo1; + UniqueID32 wpsc2; + DamageInfo damageInfo2; + BehaveChance BehaveChance1; + BehaveChance BehaveChance2; + BehaveChance BehaveChance3; + Value sound1; + Value unknown5; + Value sound2; + Value sound3; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + UniqueID32 particle; + Value soundId4; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc1"; - } - if (wpsc2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); - ent->name = name + "_wpsc2"; - } - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc1"; } + if (wpsc2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); + ent->name = name + "_wpsc2"; + } + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(wpsc2, pathsOut); - g_curSpec->flattenDependencies(particle, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(wpsc2, pathsOut); + g_curSpec->flattenDependencies(particle, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ColorModulate.hpp b/DataSpec/DNAMP1/ScriptObjects/ColorModulate.hpp index b3a3c01ee..5ec32626c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ColorModulate.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ColorModulate.hpp @@ -4,24 +4,21 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ColorModulate : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value colorA; - Value colorB; - Value blendMode; - Value timeA2B; - Value timeB2A; - Value doReverse; - Value resetTargetWhenDone; - Value depthCompare; - Value depthUpdate; - Value depthBackwards; - Value active; +namespace DataSpec::DNAMP1 { +struct ColorModulate : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value colorA; + Value colorB; + Value blendMode; + Value timeA2B; + Value timeB2A; + Value doReverse; + Value resetTargetWhenDone; + Value depthCompare; + Value depthUpdate; + Value depthBackwards; + Value active; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ControllerAction.hpp b/DataSpec/DNAMP1/ScriptObjects/ControllerAction.hpp index eedcf7c60..60635e0f4 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ControllerAction.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ControllerAction.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ControllerAction : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; - Value command; - Value deactivateOnClose; +namespace DataSpec::DNAMP1 { +struct ControllerAction : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; + Value command; + Value deactivateOnClose; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Counter.hpp b/DataSpec/DNAMP1/ScriptObjects/Counter.hpp index c00057d07..b902353f1 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Counter.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Counter.hpp @@ -4,17 +4,14 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Counter : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value startValue; // needs verification - Value maxValue; - Value unknown1; - Value unknown2; +namespace DataSpec::DNAMP1 { +struct Counter : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value startValue; // needs verification + Value maxValue; + Value unknown1; + Value unknown2; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/CoverPoint.hpp b/DataSpec/DNAMP1/ScriptObjects/CoverPoint.hpp index e8087cafd..72cc4a447 100644 --- a/DataSpec/DNAMP1/ScriptObjects/CoverPoint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/CoverPoint.hpp @@ -4,21 +4,18 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct CoverPoint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; +namespace DataSpec::DNAMP1 { +struct CoverPoint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/DamageableTrigger.hpp b/DataSpec/DNAMP1/ScriptObjects/DamageableTrigger.hpp index 6be868590..eeabb918a 100644 --- a/DataSpec/DNAMP1/ScriptObjects/DamageableTrigger.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/DamageableTrigger.hpp @@ -4,58 +4,48 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct DamageableTrigger : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value volume; - HealthInfo healthInfo; - DamageVulnerability damageVulnerabilty; - Value faceFlag; - UniqueID32 patternTex1; - UniqueID32 patternTex2; - UniqueID32 colorTex; - Value lockOn; - Value active; - VisorParameters visorParameters; +namespace DataSpec::DNAMP1 { +struct DamageableTrigger : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value volume; + HealthInfo healthInfo; + DamageVulnerability damageVulnerabilty; + Value faceFlag; + UniqueID32 patternTex1; + UniqueID32 patternTex2; + UniqueID32 colorTex; + Value lockOn; + Value active; + VisorParameters visorParameters; - void nameIDs(PAKRouter& pakRouter) const - { - if (patternTex1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternTex1); - ent->name = name + "_patternTex1"; - } - if (patternTex2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternTex2); - ent->name = name + "_patternTex2"; - } - if (colorTex) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(colorTex); - ent->name = name + "_colorTex"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (patternTex1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternTex1); + ent->name = name + "_patternTex1"; } + if (patternTex2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternTex2); + ent->name = name + "_patternTex2"; + } + if (colorTex) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(colorTex); + ent->name = name + "_colorTex"; + } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(patternTex1, pathsOut); - g_curSpec->flattenDependencies(patternTex2, pathsOut); - g_curSpec->flattenDependencies(colorTex, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(patternTex1, pathsOut); + g_curSpec->flattenDependencies(patternTex2, pathsOut); + g_curSpec->flattenDependencies(colorTex, pathsOut); + } - zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const - { - zeus::CVector3f halfExtent = zeus::CVector3f(volume) / 2.f; - zeus::CVector3f loc(location); - return zeus::CAABox(loc - halfExtent, loc + halfExtent); - } + zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const { + zeus::CVector3f halfExtent = zeus::CVector3f(volume) / 2.f; + zeus::CVector3f loc(location); + return zeus::CAABox(loc - halfExtent, loc + halfExtent); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Debris.hpp b/DataSpec/DNAMP1/ScriptObjects/Debris.hpp index 66ee4d0bf..49c2b7237 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Debris.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Debris.hpp @@ -4,58 +4,47 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Debris : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - Value zImpulse; - Value velocity; - DNAColor endsColor; - Value mass; - Value restitution; - Value duration; - Value scaleType; - Value randomAngImpulse; - UniqueID32 model; - ActorParameters actorParameters; - UniqueID32 particle; - Value particleScale; - Value b1; - Value active; +namespace DataSpec::DNAMP1 { +struct Debris : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + Value zImpulse; + Value velocity; + DNAColor endsColor; + Value mass; + Value restitution; + Value duration; + Value scaleType; + Value randomAngImpulse; + UniqueID32 model; + ActorParameters actorParameters; + UniqueID32 particle; + Value particleScale; + Value b1; + Value active; - void nameIDs(PAKRouter& pakRouter) const - { - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; } + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; + } + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(model, pathsOut); - g_curSpec->flattenDependencies(particle, pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(model, pathsOut); + g_curSpec->flattenDependencies(particle, pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/DebrisExtended.hpp b/DataSpec/DNAMP1/ScriptObjects/DebrisExtended.hpp index b788668f4..80b43a79b 100644 --- a/DataSpec/DNAMP1/ScriptObjects/DebrisExtended.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/DebrisExtended.hpp @@ -4,91 +4,78 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct DebrisExtended : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - Value linConeAngle; - Value linMinMag; - Value linMaxMag; - Value angMinMag; - Value angMaxMag; - Value minDuration; - Value maxDuration; - Value colorInT; - Value colorOutT; - DNAColor color; - DNAColor endsColor; - Value scaleOutT; - Value endScale; - Value restitution; - Value downwardSpeed; - Value localOffset; - UniqueID32 model; - ActorParameters actorParameters; - UniqueID32 particle1; - Value particle1Scale; - Value particle1GlobalTranslation; - Value deferDeleteTillParticle1Done; - Value particle1Or; - UniqueID32 particle2; - Value particle2Scale; - Value particle2GlobalTranslation; - Value deferDeleteTillParticle2Done; - Value particle2Or; - UniqueID32 particle3; - Value particle3Scale; - Value particle3Or; - Value solid; - Value dieOnProjectile; - Value noBounce; - Value active; +namespace DataSpec::DNAMP1 { +struct DebrisExtended : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + Value linConeAngle; + Value linMinMag; + Value linMaxMag; + Value angMinMag; + Value angMaxMag; + Value minDuration; + Value maxDuration; + Value colorInT; + Value colorOutT; + DNAColor color; + DNAColor endsColor; + Value scaleOutT; + Value endScale; + Value restitution; + Value downwardSpeed; + Value localOffset; + UniqueID32 model; + ActorParameters actorParameters; + UniqueID32 particle1; + Value particle1Scale; + Value particle1GlobalTranslation; + Value deferDeleteTillParticle1Done; + Value particle1Or; + UniqueID32 particle2; + Value particle2Scale; + Value particle2GlobalTranslation; + Value deferDeleteTillParticle2Done; + Value particle2Or; + UniqueID32 particle3; + Value particle3Scale; + Value particle3Or; + Value solid; + Value dieOnProjectile; + Value noBounce; + Value active; - void nameIDs(PAKRouter& pakRouter) const - { - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(model, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(model, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/DebugCameraWaypoint.hpp b/DataSpec/DNAMP1/ScriptObjects/DebugCameraWaypoint.hpp index b0cb3b912..8894c97ea 100644 --- a/DataSpec/DNAMP1/ScriptObjects/DebugCameraWaypoint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/DebugCameraWaypoint.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct DebugCameraWaypoint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value unknown1; +namespace DataSpec::DNAMP1 { +struct DebugCameraWaypoint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value unknown1; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/DistanceFog.hpp b/DataSpec/DNAMP1/ScriptObjects/DistanceFog.hpp index 29a3d5060..f8a01ce6d 100644 --- a/DataSpec/DNAMP1/ScriptObjects/DistanceFog.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/DistanceFog.hpp @@ -4,20 +4,17 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct DistanceFog : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value fogMode; - Value fogColor; // CColor - Value range; - Value colorDelta; - Value rangeDelta; - Value expl; - Value active; +namespace DataSpec::DNAMP1 { +struct DistanceFog : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value fogMode; + Value fogColor; // CColor + Value range; + Value colorDelta; + Value rangeDelta; + Value expl; + Value active; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Dock.hpp b/DataSpec/DNAMP1/ScriptObjects/Dock.hpp index b422cc803..546ac6a2d 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Dock.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Dock.hpp @@ -4,19 +4,16 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Dock : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; - Value location; - Value volume; - Value dock; - Value room; - Value loadConnected; +namespace DataSpec::DNAMP1 { +struct Dock : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; + Value location; + Value volume; + Value dock; + Value room; + Value loadConnected; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/DockAreaChange.hpp b/DataSpec/DNAMP1/ScriptObjects/DockAreaChange.hpp index df52df7b3..a53f6c035 100644 --- a/DataSpec/DNAMP1/ScriptObjects/DockAreaChange.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/DockAreaChange.hpp @@ -4,15 +4,12 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct DockAreaChange : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value unknown2; +namespace DataSpec::DNAMP1 { +struct DockAreaChange : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value unknown2; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/DoorArea.cpp b/DataSpec/DNAMP1/ScriptObjects/DoorArea.cpp index a30ccc9c0..6bb526f83 100644 --- a/DataSpec/DNAMP1/ScriptObjects/DoorArea.cpp +++ b/DataSpec/DNAMP1/ScriptObjects/DoorArea.cpp @@ -1,29 +1,25 @@ #include "DoorArea.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -zeus::CAABox DoorArea::getVISIAABB(hecl::blender::Token& btok) const -{ - hecl::blender::Connection& conn = btok.getBlenderConnection(); - zeus::CAABox aabbOut; +zeus::CAABox DoorArea::getVISIAABB(hecl::blender::Token& btok) const { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + zeus::CAABox aabbOut; - if (animationParameters.animationCharacterSet) - { - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath( - animationParameters.animationCharacterSet); - conn.openBlend(path.getWithExtension(_SYS_STR(".blend"), true)); - hecl::blender::DataStream ds = conn.beginData(); - auto aabb = ds.getMeshAABB(); - aabbOut = zeus::CAABox(aabb.first, aabb.second); - } + if (animationParameters.animationCharacterSet) { + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(animationParameters.animationCharacterSet); + conn.openBlend(path.getWithExtension(_SYS_STR(".blend"), true)); + hecl::blender::DataStream ds = conn.beginData(); + auto aabb = ds.getMeshAABB(); + aabbOut = zeus::CAABox(aabb.first, aabb.second); + } - if (aabbOut.min.x() > aabbOut.max.x()) - return {}; + if (aabbOut.min.x() > aabbOut.max.x()) + return {}; - zeus::CTransform xf = ConvertEditorEulerToTransform4f(scale, orientation, location); - return aabbOut.getTransformedAABox(xf); + zeus::CTransform xf = ConvertEditorEulerToTransform4f(scale, orientation, location); + return aabbOut.getTransformedAABox(xf); } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/DoorArea.hpp b/DataSpec/DNAMP1/ScriptObjects/DoorArea.hpp index 5f14efd4c..283c9b555 100644 --- a/DataSpec/DNAMP1/ScriptObjects/DoorArea.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/DoorArea.hpp @@ -4,51 +4,41 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct DoorArea : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - AnimationParameters animationParameters; - ActorParameters actorParameters; - Value orbitPos; - Value collisionExtent; - Value collisionOffset; - Value active; - Value open; - Value projectilesCollide; - Value animationLength; - Value isMorphballDoor; +namespace DataSpec::DNAMP1 { +struct DoorArea : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + AnimationParameters animationParameters; + ActorParameters actorParameters; + Value orbitPos; + Value collisionExtent; + Value collisionOffset; + Value active; + Value open; + Value projectilesCollide; + Value animationLength; + Value isMorphballDoor; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } - zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const; + zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Drone.hpp b/DataSpec/DNAMP1/ScriptObjects/Drone.hpp index 95cdaf09e..4b7310ed6 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Drone.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Drone.hpp @@ -4,96 +4,85 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Drone : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - Value unknown2; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - DamageInfo damageInfo1; - Value unknown3; - DamageInfo damageInfo2; - Value unknown4; - Value unknown5; - Value unknown6; - FlareDefinition flareDefinition1; - FlareDefinition flareDefinition2; - FlareDefinition flareDefinition3; - FlareDefinition flareDefinition4; - FlareDefinition flareDefinition5; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; - Value unknown16; - Value unknown17; - Value unknown18; - Value unknown19; - Value unknown20; - Value unknown21; - Value unknown22; - Value unknown23; - Value unknown24; - Value unknown25; - UniqueID32 crsc; - Value unknon26; - Value unknon27; - Value unknon28; - Value unknon29; - Value sound; // verification needed - Value unknown30; +namespace DataSpec::DNAMP1 { +struct Drone : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + Value unknown2; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + DamageInfo damageInfo1; + Value unknown3; + DamageInfo damageInfo2; + Value unknown4; + Value unknown5; + Value unknown6; + FlareDefinition flareDefinition1; + FlareDefinition flareDefinition2; + FlareDefinition flareDefinition3; + FlareDefinition flareDefinition4; + FlareDefinition flareDefinition5; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + Value unknown16; + Value unknown17; + Value unknown18; + Value unknown19; + Value unknown20; + Value unknown21; + Value unknown22; + Value unknown23; + Value unknown24; + Value unknown25; + UniqueID32 crsc; + Value unknon26; + Value unknon27; + Value unknon28; + Value unknon29; + Value sound; // verification needed + Value unknown30; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (crsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(crsc); - ent->name = name + "_crsc"; - } - flareDefinition1.nameIDs(pakRouter, name + "_flare1"); - flareDefinition2.nameIDs(pakRouter, name + "_flare2"); - flareDefinition3.nameIDs(pakRouter, name + "_flare3"); - flareDefinition4.nameIDs(pakRouter, name + "_flare4"); - flareDefinition5.nameIDs(pakRouter, name + "_flare5"); - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (crsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(crsc); + ent->name = name + "_crsc"; } + flareDefinition1.nameIDs(pakRouter, name + "_flare1"); + flareDefinition2.nameIDs(pakRouter, name + "_flare2"); + flareDefinition3.nameIDs(pakRouter, name + "_flare3"); + flareDefinition4.nameIDs(pakRouter, name + "_flare4"); + flareDefinition5.nameIDs(pakRouter, name + "_flare5"); + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(crsc, pathsOut); - flareDefinition1.depIDs(pathsOut); - flareDefinition2.depIDs(pathsOut); - flareDefinition3.depIDs(pathsOut); - flareDefinition4.depIDs(pathsOut); - flareDefinition5.depIDs(pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(crsc, pathsOut); + flareDefinition1.depIDs(pathsOut); + flareDefinition2.depIDs(pathsOut); + flareDefinition3.depIDs(pathsOut); + flareDefinition4.depIDs(pathsOut); + flareDefinition5.depIDs(pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Effect.hpp b/DataSpec/DNAMP1/ScriptObjects/Effect.hpp index 480157607..7efd693e6 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Effect.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Effect.hpp @@ -4,57 +4,49 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Effect : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - UniqueID32 part; - UniqueID32 elsc; - Value hotInThermal; - Value noTimerUnlessAreaOccluded; - Value rebuildSystemsOnActivate; - Value active; - Value useRateInverseCamDist; - Value rateInverseCamDist; - Value rateInverseCamDistRate; - Value duration; - Value durationResetWhileVisible; - Value useRateCamDistRange; - Value rateCamDistRangeMin; - Value rateCamDistRangeMax; - Value rateCamDistRangeFarRate; - Value combatVisorVisible; - Value thermalVisorVisible; - Value xrayVisorVisible; - Value dieWhenSystemsDone; - LightParameters lightParameters; +namespace DataSpec::DNAMP1 { +struct Effect : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + UniqueID32 part; + UniqueID32 elsc; + Value hotInThermal; + Value noTimerUnlessAreaOccluded; + Value rebuildSystemsOnActivate; + Value active; + Value useRateInverseCamDist; + Value rateInverseCamDist; + Value rateInverseCamDistRate; + Value duration; + Value durationResetWhileVisible; + Value useRateCamDistRange; + Value rateCamDistRangeMin; + Value rateCamDistRangeMax; + Value rateCamDistRangeFarRate; + Value combatVisorVisible; + Value thermalVisorVisible; + Value xrayVisorVisible; + Value dieWhenSystemsDone; + LightParameters lightParameters; - void nameIDs(PAKRouter& pakRouter) const - { - if (part) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(part); - ent->name = name + "_part"; - } - if (elsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); - ent->name = name + "_elsc"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (part) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(part); + ent->name = name + "_part"; } + if (elsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); + ent->name = name + "_elsc"; + } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(part, pathsOut); - g_curSpec->flattenDependencies(elsc, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(part, pathsOut); + g_curSpec->flattenDependencies(elsc, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ElectroMagneticPulse.hpp b/DataSpec/DNAMP1/ScriptObjects/ElectroMagneticPulse.hpp index 679c6628c..34abd964b 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ElectroMagneticPulse.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ElectroMagneticPulse.hpp @@ -4,39 +4,32 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ElectroMagneticPulse : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - UniqueID32 particle; +namespace DataSpec::DNAMP1 { +struct ElectroMagneticPulse : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + UniqueID32 particle; - void nameIDs(PAKRouter& pakRouter) const - { - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ElitePirate.hpp b/DataSpec/DNAMP1/ScriptObjects/ElitePirate.hpp index 85b07b459..bdee9b015 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ElitePirate.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ElitePirate.hpp @@ -4,137 +4,120 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ElitePirate : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters1; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - UniqueID32 particle1; - Value soundID1; - ActorParameters actorParameters2; - AnimationParameters animationParameters; - UniqueID32 particle2; - Value soundID2; - UniqueID32 model; - DamageInfo damageInfo1; - Value unknown9; - UniqueID32 particle3; - UniqueID32 particle4; - UniqueID32 particle5; - UniqueID32 particle6; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; - Value unknown16; - Value soundID3; - Value soundID4; - UniqueID32 particle7; - DamageInfo damageInfo2; - UniqueID32 elsc; - Value soundID5; - Value unknown17; - Value unknown18; +namespace DataSpec::DNAMP1 { +struct ElitePirate : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters1; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + UniqueID32 particle1; + Value soundID1; + ActorParameters actorParameters2; + AnimationParameters animationParameters; + UniqueID32 particle2; + Value soundID2; + UniqueID32 model; + DamageInfo damageInfo1; + Value unknown9; + UniqueID32 particle3; + UniqueID32 particle4; + UniqueID32 particle5; + UniqueID32 particle6; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + Value unknown16; + Value soundID3; + Value soundID4; + UniqueID32 particle7; + DamageInfo damageInfo2; + UniqueID32 elsc; + Value soundID5; + Value unknown17; + Value unknown18; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters1.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - actorParameters2.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters1.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + actorParameters2.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - if (particle5) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); - ent->name = name + "_part5"; - } - if (particle6) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); - ent->name = name + "_part6"; - } - if (particle7) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7); - ent->name = name + "_part7"; - } - if (elsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); - ent->name = name + "_elsc"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters1.nameIDs(pakRouter, name + "_actp1"); - actorParameters2.nameIDs(pakRouter, name + "_actp2"); - animationParameters.nameANCS(pakRouter, name + "_animp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + if (particle5) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); + ent->name = name + "_part5"; + } + if (particle6) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); + ent->name = name + "_part6"; + } + if (particle7) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7); + ent->name = name + "_part7"; + } + if (elsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); + ent->name = name + "_elsc"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters1.nameIDs(pakRouter, name + "_actp1"); + actorParameters2.nameIDs(pakRouter, name + "_actp2"); + animationParameters.nameANCS(pakRouter, name + "_animp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(model, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - g_curSpec->flattenDependencies(particle5, pathsOut); - g_curSpec->flattenDependencies(particle6, pathsOut); - g_curSpec->flattenDependencies(particle7, pathsOut); - g_curSpec->flattenDependencies(elsc, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters1.depIDs(pathsOut, lazyOut); - actorParameters2.depIDs(pathsOut, lazyOut); - animationParameters.depANCS(pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(model, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + g_curSpec->flattenDependencies(particle5, pathsOut); + g_curSpec->flattenDependencies(particle6, pathsOut); + g_curSpec->flattenDependencies(particle7, pathsOut); + g_curSpec->flattenDependencies(elsc, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters1.depIDs(pathsOut, lazyOut); + actorParameters2.depIDs(pathsOut, lazyOut); + animationParameters.depANCS(pathsOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters1.scanIDs(scansOut); - actorParameters2.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { + actorParameters1.scanIDs(scansOut); + actorParameters2.scanIDs(scansOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/EnergyBall.hpp b/DataSpec/DNAMP1/ScriptObjects/EnergyBall.hpp index ccdab04b9..a79b2ec82 100644 --- a/DataSpec/DNAMP1/ScriptObjects/EnergyBall.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/EnergyBall.hpp @@ -4,79 +4,65 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct EnergyBall : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - DamageInfo damageInfo1; - Value unknown3; - UniqueID32 texture; - Value soundID1; - UniqueID32 particle1; - UniqueID32 elsc; - Value soundID2; - Value unknown4; - Value unknown5; - UniqueID32 particle2; - DamageInfo damageInfo2; - Value unknown6; +namespace DataSpec::DNAMP1 { +struct EnergyBall : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + DamageInfo damageInfo1; + Value unknown3; + UniqueID32 texture; + Value soundID1; + UniqueID32 particle1; + UniqueID32 elsc; + Value soundID2; + Value unknown4; + Value unknown5; + UniqueID32 particle2; + DamageInfo damageInfo2; + Value unknown6; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); - ent->name = name + "_texture"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (elsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); - ent->name = name + "_elsc"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); + ent->name = name + "_texture"; } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (elsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); + ent->name = name + "_elsc"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(texture, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(elsc, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(texture, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(elsc, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/EnvFxDensityController.hpp b/DataSpec/DNAMP1/ScriptObjects/EnvFxDensityController.hpp index 2aca79857..a6e23b30f 100644 --- a/DataSpec/DNAMP1/ScriptObjects/EnvFxDensityController.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/EnvFxDensityController.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct EnvFxDensityController : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value unknown2; - Value unknown3; +namespace DataSpec::DNAMP1 { +struct EnvFxDensityController : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value unknown2; + Value unknown3; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Eyeball.hpp b/DataSpec/DNAMP1/ScriptObjects/Eyeball.hpp index c51116b96..cd6cadb47 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Eyeball.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Eyeball.hpp @@ -4,86 +4,71 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Eyeball : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown2; - Value unknown3; - UniqueID32 wpsc; - DamageInfo damageInfo; - UniqueID32 particle1; - UniqueID32 particle2; - UniqueID32 texture1; - UniqueID32 texture2; - Value unknown4; - Value unknown5; // always ff - Value unknown6; // always ff - Value unknown7; // always ff - Value unknown8; - Value unknown9; +namespace DataSpec::DNAMP1 { +struct Eyeball : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown2; + Value unknown3; + UniqueID32 wpsc; + DamageInfo damageInfo; + UniqueID32 particle1; + UniqueID32 particle2; + UniqueID32 texture1; + UniqueID32 texture2; + Value unknown4; + Value unknown5; // always ff + Value unknown6; // always ff + Value unknown7; // always ff + Value unknown8; + Value unknown9; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); - ent->name = name + "_wpsc"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (texture1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); - ent->name = name + "_tex1"; - } - if (texture2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); - ent->name = name + "_tex2"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); + ent->name = name + "_wpsc"; } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (texture1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); + ent->name = name + "_tex1"; + } + if (texture2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); + ent->name = name + "_tex2"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(texture1, pathsOut); - g_curSpec->flattenDependencies(texture2, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(texture1, pathsOut); + g_curSpec->flattenDependencies(texture2, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/FireFlea.hpp b/DataSpec/DNAMP1/ScriptObjects/FireFlea.hpp index ee23c3a68..31cf29ee8 100644 --- a/DataSpec/DNAMP1/ScriptObjects/FireFlea.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/FireFlea.hpp @@ -4,44 +4,34 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct FireFlea : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; +namespace DataSpec::DNAMP1 { +struct FireFlea : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/FishCloud.hpp b/DataSpec/DNAMP1/ScriptObjects/FishCloud.hpp index dfef63d8c..81e7d2529 100644 --- a/DataSpec/DNAMP1/ScriptObjects/FishCloud.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/FishCloud.hpp @@ -4,89 +4,78 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct FishCloud : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value volume; - Value unknown1; - UniqueID32 model; - AnimationParameters animationParameters; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; - Value unknown16; - Value unknown17; // CColor - Value unknown18; - Value unknown19; - UniqueID32 deathParticle1; - Value deathParticle1Frames; - UniqueID32 deathParticle2; - Value deathParticle2Frames; - UniqueID32 deathParticle3; - Value deathParticle3Frames; - UniqueID32 deathParticle4; - Value deathParticle4Frames; - Value deathSFX; - Value unknown29; - Value unknown30; +namespace DataSpec::DNAMP1 { +struct FishCloud : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value volume; + Value unknown1; + UniqueID32 model; + AnimationParameters animationParameters; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + Value unknown16; + Value unknown17; // CColor + Value unknown18; + Value unknown19; + UniqueID32 deathParticle1; + Value deathParticle1Frames; + UniqueID32 deathParticle2; + Value deathParticle2Frames; + UniqueID32 deathParticle3; + Value deathParticle3Frames; + UniqueID32 deathParticle4; + Value deathParticle4Frames; + Value deathSFX; + Value unknown29; + Value unknown30; - void nameIDs(PAKRouter& pakRouter) const - { - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - animationParameters.nameANCS(pakRouter, name + "_animp"); - if (deathParticle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(deathParticle1); - ent->name = name + "_deathParticle1"; - } - if (deathParticle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(deathParticle2); - ent->name = name + "_deathParticle2"; - } - if (deathParticle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(deathParticle3); - ent->name = name + "_deathParticle3"; - } - if (deathParticle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(deathParticle4); - ent->name = name + "_deathParticle4"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; } + animationParameters.nameANCS(pakRouter, name + "_animp"); + if (deathParticle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(deathParticle1); + ent->name = name + "_deathParticle1"; + } + if (deathParticle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(deathParticle2); + ent->name = name + "_deathParticle2"; + } + if (deathParticle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(deathParticle3); + ent->name = name + "_deathParticle3"; + } + if (deathParticle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(deathParticle4); + ent->name = name + "_deathParticle4"; + } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(model, pathsOut); - animationParameters.depANCS(pathsOut); - g_curSpec->flattenDependencies(deathParticle1, pathsOut); - g_curSpec->flattenDependencies(deathParticle2, pathsOut); - g_curSpec->flattenDependencies(deathParticle3, pathsOut); - g_curSpec->flattenDependencies(deathParticle4, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(model, pathsOut); + animationParameters.depANCS(pathsOut); + g_curSpec->flattenDependencies(deathParticle1, pathsOut); + g_curSpec->flattenDependencies(deathParticle2, pathsOut); + g_curSpec->flattenDependencies(deathParticle3, pathsOut); + g_curSpec->flattenDependencies(deathParticle4, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/FishCloudModifier.hpp b/DataSpec/DNAMP1/ScriptObjects/FishCloudModifier.hpp index 60970475c..d2bbf3669 100644 --- a/DataSpec/DNAMP1/ScriptObjects/FishCloudModifier.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/FishCloudModifier.hpp @@ -4,19 +4,16 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct FishCloudModifier : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value position; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; +namespace DataSpec::DNAMP1 { +struct FishCloudModifier : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value position; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Flaahgra.hpp b/DataSpec/DNAMP1/ScriptObjects/Flaahgra.hpp index cc2e69f66..727770c16 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Flaahgra.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Flaahgra.hpp @@ -4,88 +4,76 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Flaahgra : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters1; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - DamageVulnerability damageVulnerabilty; - UniqueID32 wpsc1; - DamageInfo damageInfo1; - UniqueID32 wpsc2; - DamageInfo damageInfo2; - UniqueID32 particle; - DamageInfo damageInfo3; - ActorParameters actorParameters2; - Value unknown5; - Value unknown6; - Value unknown7; - AnimationParameters animationParameters; - UniqueID32 dependencyGroup; +namespace DataSpec::DNAMP1 { +struct Flaahgra : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters1; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + DamageVulnerability damageVulnerabilty; + UniqueID32 wpsc1; + DamageInfo damageInfo1; + UniqueID32 wpsc2; + DamageInfo damageInfo2; + UniqueID32 particle; + DamageInfo damageInfo3; + ActorParameters actorParameters2; + Value unknown5; + Value unknown6; + Value unknown7; + AnimationParameters animationParameters; + UniqueID32 dependencyGroup; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters1.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - actorParameters2.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters1.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + actorParameters2.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc1"; - } - if (wpsc2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); - ent->name = name + "_wpsc2"; - } - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - if (dependencyGroup) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(dependencyGroup); - ent->name = name + "_dgrp"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters1.nameIDs(pakRouter, name + "_actp1"); - actorParameters2.nameIDs(pakRouter, name + "_actp2"); - animationParameters.nameANCS(pakRouter, name + "_animp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc1"; } + if (wpsc2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); + ent->name = name + "_wpsc2"; + } + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; + } + if (dependencyGroup) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(dependencyGroup); + ent->name = name + "_dgrp"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters1.nameIDs(pakRouter, name + "_actp1"); + actorParameters2.nameIDs(pakRouter, name + "_actp2"); + animationParameters.nameANCS(pakRouter, name + "_animp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(wpsc2, pathsOut); - g_curSpec->flattenDependencies(particle, pathsOut); - g_curSpec->flattenDependencies(dependencyGroup, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters1.depIDs(pathsOut, lazyOut); - actorParameters2.depIDs(pathsOut, lazyOut); - animationParameters.depANCS(pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(wpsc2, pathsOut); + g_curSpec->flattenDependencies(particle, pathsOut); + g_curSpec->flattenDependencies(dependencyGroup, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters1.depIDs(pathsOut, lazyOut); + actorParameters2.depIDs(pathsOut, lazyOut); + animationParameters.depANCS(pathsOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters1.scanIDs(scansOut); - actorParameters2.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { + actorParameters1.scanIDs(scansOut); + actorParameters2.scanIDs(scansOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/FlaahgraTentacle.hpp b/DataSpec/DNAMP1/ScriptObjects/FlaahgraTentacle.hpp index fcadf23b3..5af9af4c8 100644 --- a/DataSpec/DNAMP1/ScriptObjects/FlaahgraTentacle.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/FlaahgraTentacle.hpp @@ -4,41 +4,31 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct FlaahgraTentacle : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; +namespace DataSpec::DNAMP1 { +struct FlaahgraTentacle : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/FlickerBat.hpp b/DataSpec/DNAMP1/ScriptObjects/FlickerBat.hpp index 7976c404e..b3fddb4e3 100644 --- a/DataSpec/DNAMP1/ScriptObjects/FlickerBat.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/FlickerBat.hpp @@ -4,45 +4,35 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct FlickerBat : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown2; - Value unknown3; - Value unknown4; +namespace DataSpec::DNAMP1 { +struct FlickerBat : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown2; + Value unknown3; + Value unknown4; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/FlyingPirate.hpp b/DataSpec/DNAMP1/ScriptObjects/FlyingPirate.hpp index 1afd7ac6a..9acf4d63c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/FlyingPirate.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/FlyingPirate.hpp @@ -4,113 +4,96 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct FlyingPirate : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - UniqueID32 wpsc1; - DamageInfo damageInfo1; - Value unknown4; - UniqueID32 wpsc2; - DamageInfo damageInfo2; - UniqueID32 wpsc3; - Value unknown5; - Value unknown6; - UniqueID32 particle1; - DamageInfo damageInfo3; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; - UniqueID32 particle2; - UniqueID32 particle3; - UniqueID32 particle4; - Value unknown16; - Value unknown17; - Value unknown18; - Value unknown19; - Value unknown20; +namespace DataSpec::DNAMP1 { +struct FlyingPirate : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + UniqueID32 wpsc1; + DamageInfo damageInfo1; + Value unknown4; + UniqueID32 wpsc2; + DamageInfo damageInfo2; + UniqueID32 wpsc3; + Value unknown5; + Value unknown6; + UniqueID32 particle1; + DamageInfo damageInfo3; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + UniqueID32 particle2; + UniqueID32 particle3; + UniqueID32 particle4; + Value unknown16; + Value unknown17; + Value unknown18; + Value unknown19; + Value unknown20; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc1"; - } - if (wpsc2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); - ent->name = name + "_wpsc2"; - } - if (wpsc3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc3); - ent->name = name + "_wpsc3"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc1"; } + if (wpsc2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); + ent->name = name + "_wpsc2"; + } + if (wpsc3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc3); + ent->name = name + "_wpsc3"; + } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(wpsc2, pathsOut); - g_curSpec->flattenDependencies(wpsc3, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(wpsc2, pathsOut); + g_curSpec->flattenDependencies(wpsc3, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/FogVolume.hpp b/DataSpec/DNAMP1/ScriptObjects/FogVolume.hpp index 8a856dfb4..075398dc8 100644 --- a/DataSpec/DNAMP1/ScriptObjects/FogVolume.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/FogVolume.hpp @@ -4,19 +4,16 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct FogVolume : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value volume; - Value unknown1; - Value unknown2; - Value unkonwn3; - Value unknown4; +namespace DataSpec::DNAMP1 { +struct FogVolume : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value volume; + Value unknown1; + Value unknown2; + Value unkonwn3; + Value unknown4; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Geemer.hpp b/DataSpec/DNAMP1/ScriptObjects/Geemer.hpp index 8329c0962..6a2d9c5e0 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Geemer.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Geemer.hpp @@ -4,51 +4,41 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Geemer : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; +namespace DataSpec::DNAMP1 { +struct Geemer : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Generator.hpp b/DataSpec/DNAMP1/ScriptObjects/Generator.hpp index c1c1d63e5..e71b23f34 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Generator.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Generator.hpp @@ -4,20 +4,17 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Generator : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value spawnCount; - Value noReuseFollowers; - Value noInheritXf; - Value offset; - Value active; - Value minScale; - Value maxScale; +namespace DataSpec::DNAMP1 { +struct Generator : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value spawnCount; + Value noReuseFollowers; + Value noInheritXf; + Value offset; + Value active; + Value minScale; + Value maxScale; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/GrapplePoint.hpp b/DataSpec/DNAMP1/ScriptObjects/GrapplePoint.hpp index 04eda8b5e..3c6362e76 100644 --- a/DataSpec/DNAMP1/ScriptObjects/GrapplePoint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/GrapplePoint.hpp @@ -4,17 +4,14 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct GrapplePoint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value active; - GrappleParameters grappleParameters; +namespace DataSpec::DNAMP1 { +struct GrapplePoint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value active; + GrappleParameters grappleParameters; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/GunTurret.hpp b/DataSpec/DNAMP1/ScriptObjects/GunTurret.hpp index 6899f3769..af871ef57 100644 --- a/DataSpec/DNAMP1/ScriptObjects/GunTurret.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/GunTurret.hpp @@ -4,137 +4,118 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct GunTurret : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - Value unknown2; - Value scanOffset; - AnimationParameters animationParameters; - ActorParameters actorParameters; - HealthInfo healthInfo; - DamageVulnerability damageVulnerabilty; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; - Value unknown16; - Value unknown17; - UniqueID32 unknown18; - DamageInfo damageInfo; - UniqueID32 particle1; - UniqueID32 particle2; - UniqueID32 particle3; - UniqueID32 particle4; - UniqueID32 particle5; - UniqueID32 particle6; - UniqueID32 particle7; - Value unknown19; - Value unknown20; - Value unknown21; - Value unknown22; - Value unknown23; - Value unknown24; - UniqueID32 model; - Value unknown25; - Value unknown26; - Value unknown27; - Value unknown28; - Value unknown29; - Value unknown30; +namespace DataSpec::DNAMP1 { +struct GunTurret : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + Value unknown2; + Value scanOffset; + AnimationParameters animationParameters; + ActorParameters actorParameters; + HealthInfo healthInfo; + DamageVulnerability damageVulnerabilty; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + Value unknown16; + Value unknown17; + UniqueID32 unknown18; + DamageInfo damageInfo; + UniqueID32 particle1; + UniqueID32 particle2; + UniqueID32 particle3; + UniqueID32 particle4; + UniqueID32 particle5; + UniqueID32 particle6; + UniqueID32 particle7; + Value unknown19; + Value unknown20; + Value unknown21; + Value unknown22; + Value unknown23; + Value unknown24; + UniqueID32 model; + Value unknown25; + Value unknown26; + Value unknown27; + Value unknown28; + Value unknown29; + Value unknown30; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (unknown18) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown18); - ent->name = name + "_unknown18"; - } - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - if (particle5) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); - ent->name = name + "_part5"; - } - if (particle6) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); - ent->name = name + "_part6"; - } - if (particle7) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7); - ent->name = name + "_part7"; - } - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (unknown18) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown18); + ent->name = name + "_unknown18"; } + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; + } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + if (particle5) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); + ent->name = name + "_part5"; + } + if (particle6) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); + ent->name = name + "_part6"; + } + if (particle7) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7); + ent->name = name + "_part7"; + } + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(unknown18, pathsOut); - g_curSpec->flattenDependencies(model, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - g_curSpec->flattenDependencies(particle5, pathsOut); - g_curSpec->flattenDependencies(particle6, pathsOut); - g_curSpec->flattenDependencies(particle7, pathsOut); - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(unknown18, pathsOut); + g_curSpec->flattenDependencies(model, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + g_curSpec->flattenDependencies(particle5, pathsOut); + g_curSpec->flattenDependencies(particle6, pathsOut); + g_curSpec->flattenDependencies(particle7, pathsOut); + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/HUDMemo.hpp b/DataSpec/DNAMP1/ScriptObjects/HUDMemo.hpp index 4f831f7a3..1e4b8b711 100644 --- a/DataSpec/DNAMP1/ScriptObjects/HUDMemo.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/HUDMemo.hpp @@ -4,33 +4,26 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct HUDMemo : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value firstMessageTimer; - Value unknown1; - Value memoType; - UniqueID32 message; - Value active; +namespace DataSpec::DNAMP1 { +struct HUDMemo : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value firstMessageTimer; + Value unknown1; + Value memoType; + UniqueID32 message; + Value active; - void nameIDs(PAKRouter& pakRouter) const - { - if (message) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(message); - ent->name = name + "_message"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (message) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(message); + ent->name = name + "_message"; } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(message, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(message, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/IScriptObject.cpp b/DataSpec/DNAMP1/ScriptObjects/IScriptObject.cpp index a0b5b6189..2d9227c16 100644 --- a/DataSpec/DNAMP1/ScriptObjects/IScriptObject.cpp +++ b/DataSpec/DNAMP1/ScriptObjects/IScriptObject.cpp @@ -1,141 +1,174 @@ #include "IScriptObject.hpp" #include "ScriptTypes.hpp" -namespace DataSpec::DNAMP1 -{ -namespace priv -{ -static const ScriptObjectSpec ActorEnt = {0x00, []() -> IScriptObject* {return new struct Actor();}}; -static const ScriptObjectSpec WaypointEnt = {0x02, []() -> IScriptObject* {return new struct Waypoint();}}; -static const ScriptObjectSpec DoorAreaEnt = {0x03, []() -> IScriptObject* {return new struct DoorArea();}}; -static const ScriptObjectSpec TriggerEnt = {0x04, []() -> IScriptObject* {return new struct Trigger(); }}; -static const ScriptObjectSpec TimerEnt = {0x05, []() -> IScriptObject* {return new struct Timer(); }}; -static const ScriptObjectSpec CounterEnt = {0x06, []() -> IScriptObject* {return new struct Counter(); }}; -static const ScriptObjectSpec EffectEnt = {0x07, []() -> IScriptObject* {return new struct Effect(); }}; -static const ScriptObjectSpec PlatformEnt = {0x08, []() -> IScriptObject* {return new struct Platform(); }}; -static const ScriptObjectSpec SoundEnt = {0x09, []() -> IScriptObject* {return new struct Sound(); }}; -static const ScriptObjectSpec GeneratorEnt = {0x0A, []() -> IScriptObject* {return new struct Generator();}}; -static const ScriptObjectSpec DockEnt = {0x0B, []() -> IScriptObject* {return new struct Dock(); }}; -static const ScriptObjectSpec CameraEnt = {0x0C, []() -> IScriptObject* {return new struct Camera(); }}; -static const ScriptObjectSpec CameraWaypointEnt = {0x0D, []() -> IScriptObject* {return new struct CameraWaypoint(); }}; -static const ScriptObjectSpec NewIntroBossEnt = {0x0E, []() -> IScriptObject* {return new struct NewIntroBoss(); }}; -static const ScriptObjectSpec SpawnPointEnt = {0x0F, []() -> IScriptObject* {return new struct SpawnPoint(); }}; -static const ScriptObjectSpec CameraHintEnt = {0x10, []() -> IScriptObject* {return new struct CameraHint(); }}; -static const ScriptObjectSpec PickupEnt = {0x11, []() -> IScriptObject* {return new struct Pickup(); }}; -static const ScriptObjectSpec MemoryRelayEnt = {0x13, []() -> IScriptObject* {return new struct MemoryRelay(); }}; -static const ScriptObjectSpec RandomRelayEnt = {0x14, []() -> IScriptObject* {return new struct RandomRelay(); }}; -static const ScriptObjectSpec RelayEnt = {0x15, []() -> IScriptObject* {return new struct Relay(); }}; -static const ScriptObjectSpec BeetleEnt = {0x16, []() -> IScriptObject* {return new struct Beetle(); }}; -static const ScriptObjectSpec HUDMemoEnt = {0x17, []() -> IScriptObject* {return new struct HUDMemo(); }}; -static const ScriptObjectSpec CameraFilterKeyframeEnt = {0x18, []() -> IScriptObject* {return new struct CameraFilterKeyframe(); }}; -static const ScriptObjectSpec CameraBlurKeyframeEnt = {0x19, []() -> IScriptObject* {return new struct CameraBlurKeyframe(); }}; -static const ScriptObjectSpec DamageableTriggerEnt = {0x1A, []() -> IScriptObject* {return new struct DamageableTrigger(); }}; -static const ScriptObjectSpec DebrisEnt = {0x1B, []() -> IScriptObject* {return new struct Debris(); }}; -static const ScriptObjectSpec CameraShakerEnt = {0x1C, []() -> IScriptObject* {return new struct CameraShaker(); }}; -static const ScriptObjectSpec ActorKeyframeEnt = {0x1D, []() -> IScriptObject* {return new struct ActorKeyframe(); }}; -static const ScriptObjectSpec WaterEnt = {0x20, []() -> IScriptObject* {return new struct Water(); }}; -static const ScriptObjectSpec WarwaspEnt = {0x21, []() -> IScriptObject* {return new struct Warwasp(); }}; -static const ScriptObjectSpec SpacePirateEnt = {0x24, []() -> IScriptObject* {return new struct SpacePirate(); }}; -static const ScriptObjectSpec FlyingPirateEnt = {0x25, []() -> IScriptObject* {return new struct FlyingPirate(); }}; -static const ScriptObjectSpec ElitePirateEnt = {0x26, []() -> IScriptObject* {return new struct ElitePirate(); }}; -static const ScriptObjectSpec MetroidBetaEnt = {0x27, []() -> IScriptObject* {return new struct MetroidBeta(); }}; -static const ScriptObjectSpec ChozoGhostEnt = {0x28, []() -> IScriptObject* {return new struct ChozoGhost(); }}; -static const ScriptObjectSpec CoverPointEnt = {0x2A, []() -> IScriptObject* {return new struct CoverPoint(); }}; -static const ScriptObjectSpec SpiderBallWaypointEnt = {0x2C, []() -> IScriptObject* {return new struct SpiderBallWaypoint(); }}; -static const ScriptObjectSpec BloodFlowerEnt = {0x2D, []() -> IScriptObject* {return new struct BloodFlower(); }}; -static const ScriptObjectSpec FlickerBatEnt = {0x2E, []() -> IScriptObject* {return new struct FlickerBat(); }}; -static const ScriptObjectSpec PathCameraEnt = {0x2F, []() -> IScriptObject* {return new struct PathCamera(); }}; -static const ScriptObjectSpec GrapplePointEnt = {0x30, []() -> IScriptObject* {return new struct GrapplePoint(); }}; -static const ScriptObjectSpec PuddleSporeEnt = {0x31, []() -> IScriptObject* {return new struct PuddleSpore(); }}; -static const ScriptObjectSpec DebugCameraWaypointEnt = {0x32, []() -> IScriptObject* {return new struct DebugCameraWaypoint(); }}; -static const ScriptObjectSpec SpiderBallAttractionSurfaceEnt = {0x33, []() -> IScriptObject* {return new struct SpiderBallAttractionSurface(); }}; -static const ScriptObjectSpec PuddleToadGammaEnt = {0x34, []() -> IScriptObject* {return new struct PuddleToadGamma(); }}; -static const ScriptObjectSpec DistanceFogEnt = {0x35, []() -> IScriptObject* {return new struct DistanceFog(); }}; -static const ScriptObjectSpec FireFleaEnt = {0x36, []() -> IScriptObject* {return new struct FireFlea(); }}; -static const ScriptObjectSpec MetareeAlphaEnt = {0x37, []() -> IScriptObject* {return new struct MetareeAlpha(); }}; -static const ScriptObjectSpec DockAreaChangeEnt = {0x38, []() -> IScriptObject* {return new struct DockAreaChange(); }}; -static const ScriptObjectSpec ActorRotateEnt = {0x39, []() -> IScriptObject* {return new struct ActorRotate(); }}; -static const ScriptObjectSpec SpecialFunctionEnt = {0x3A, []() -> IScriptObject* {return new struct SpecialFunction(); }}; -static const ScriptObjectSpec SpankWeedEnt = {0x3B, []() -> IScriptObject* {return new struct SpankWeed(); }}; -static const ScriptObjectSpec ParasiteEnt = {0x3D, []() -> IScriptObject* {return new struct Parasite(); }}; -static const ScriptObjectSpec PlayerHintEnt = {0x3E, []() -> IScriptObject* {return new struct PlayerHint(); }}; -static const ScriptObjectSpec RipperEnt = {0x3F, []() -> IScriptObject* {return new struct Ripper(); }}; -static const ScriptObjectSpec PickupGeneratorEnt = {0x40, []() -> IScriptObject* {return new struct PickupGenerator(); }}; -static const ScriptObjectSpec AIKeyframeEnt = {0x41, []() -> IScriptObject* {return new struct AIKeyframe(); }}; -static const ScriptObjectSpec PointOfInterestEnt = {0x42, []() -> IScriptObject* {return new struct PointOfInterest(); }}; -static const ScriptObjectSpec DroneEnt = {0x43, []() -> IScriptObject* {return new struct Drone(); }}; -static const ScriptObjectSpec MetroidAlphaEnt = {0x44, []() -> IScriptObject* {return new struct MetroidAlpha(); }}; -static const ScriptObjectSpec DebrisExtendedEnt = {0x45, []() -> IScriptObject* {return new struct DebrisExtended(); }}; -static const ScriptObjectSpec SteamEnt = {0x46, []() -> IScriptObject* {return new struct Steam(); }}; -static const ScriptObjectSpec RippleEnt = {0x47, []() -> IScriptObject* {return new struct Ripple(); }}; -static const ScriptObjectSpec BallTriggerEnt = {0x48, []() -> IScriptObject* {return new struct BallTrigger(); }}; -static const ScriptObjectSpec TargetingPointEnt = {0x49, []() -> IScriptObject* {return new struct TargetingPoint(); }}; -static const ScriptObjectSpec ElectroMagneticPulseEnt = {0x4A, []() -> IScriptObject* {return new struct ElectroMagneticPulse(); }}; -static const ScriptObjectSpec IceSheegothEnt = {0x4B, []() -> IScriptObject* {return new struct IceSheegoth(); }}; -static const ScriptObjectSpec PlayerActorEnt = {0x4C, []() -> IScriptObject* {return new struct PlayerActor(); }}; -static const ScriptObjectSpec FlaahgraEnt = {0x4D, []() -> IScriptObject* {return new struct Flaahgra(); }}; -static const ScriptObjectSpec AreaAttributesEnt = {0x4E, []() -> IScriptObject* {return new struct AreaAttributes(); }}; -static const ScriptObjectSpec FishCloudEnt = {0x4F, []() -> IScriptObject* {return new struct FishCloud(); }}; -static const ScriptObjectSpec FishCloudModifierEnt = {0x50, []() -> IScriptObject* {return new struct FishCloudModifier(); }}; -static const ScriptObjectSpec VisorFlareEnt = {0x51, []() -> IScriptObject* {return new struct VisorFlare(); }}; -static const ScriptObjectSpec WorldTeleporterx52Ent = {0x52, []() -> IScriptObject* {return new struct WorldTeleporter(); }}; -static const ScriptObjectSpec VisorGooEnt = {0x53, []() -> IScriptObject* {return new struct VisorGoo(); }}; -static const ScriptObjectSpec JellyZapEnt = {0x54, []() -> IScriptObject* {return new struct JellyZap(); }}; -static const ScriptObjectSpec ControllerActionEnt = {0x55, []() -> IScriptObject* {return new struct ControllerAction(); }}; -static const ScriptObjectSpec SwitchEnt = {0x56, []() -> IScriptObject* {return new struct Switch(); }}; -static const ScriptObjectSpec PlayerStateChangeEnt = {0x57, []() -> IScriptObject* {return new struct PlayerStateChange(); }}; -static const ScriptObjectSpec ThardusEnt = {0x58, []() -> IScriptObject* {return new struct Thardus(); }}; -static const ScriptObjectSpec WallCrawlerSwarmEnt = {0x5A, []() -> IScriptObject* {return new struct WallCrawlerSwarm(); }}; -static const ScriptObjectSpec AIJumpPointEnt = {0x5B, []() -> IScriptObject* {return new struct AIJumpPoint(); }}; -static const ScriptObjectSpec FlaahgraTentacleEnt = {0x5C, []() -> IScriptObject* {return new struct FlaahgraTentacle(); }}; -static const ScriptObjectSpec RoomAcousticsEnt = {0x5D, []() -> IScriptObject* {return new struct RoomAcoustics(); }}; -static const ScriptObjectSpec ColorModulateEnt = {0x5E, []() -> IScriptObject* {return new struct ColorModulate(); }}; -static const ScriptObjectSpec ThardusRockProjectileEnt = {0x5F, []() -> IScriptObject* {return new struct ThardusRockProjectile(); }}; -static const ScriptObjectSpec MidiEnt = {0x60, []() -> IScriptObject* {return new struct Midi(); }}; -static const ScriptObjectSpec StreamedAudioEnt = {0x61, []() -> IScriptObject* {return new struct StreamedAudio(); }}; -static const ScriptObjectSpec WorldTeleporterx62Ent = {0x62, []() -> IScriptObject* {return new struct WorldTeleporter(); }}; // o.o, no this is not a trick -static const ScriptObjectSpec RepulsorEnt = {0x63, []() -> IScriptObject* {return new struct Repulsor(); }}; -static const ScriptObjectSpec GunTurretEnt = {0x64, []() -> IScriptObject* {return new struct GunTurret(); }}; -static const ScriptObjectSpec FogVolumeEnt = {0x65, []() -> IScriptObject* {return new struct FogVolume(); }}; -static const ScriptObjectSpec BabygothEnt = {0x66, []() -> IScriptObject* {return new struct Babygoth(); }}; -static const ScriptObjectSpec EyeballEnt = {0x67, []() -> IScriptObject* {return new struct Eyeball(); }}; -static const ScriptObjectSpec RadialDamageEnt = {0x68, []() -> IScriptObject* {return new struct RadialDamage(); }}; -static const ScriptObjectSpec CameraPitchVolumeEnt = {0x69, []() -> IScriptObject* {return new struct CameraPitchVolume(); }}; -static const ScriptObjectSpec EnvFxDensityControllerEnt = {0x6A, []() -> IScriptObject* {return new struct EnvFxDensityController(); }}; -static const ScriptObjectSpec MagdoliteEnt = {0x6B, []() -> IScriptObject* {return new struct Magdolite(); }}; -static const ScriptObjectSpec TeamAIMgrEnt = {0x6C, []() -> IScriptObject* {return new struct TeamAIMgr(); }}; -static const ScriptObjectSpec SnakeWeedSwarmEnt = {0x6D, []() -> IScriptObject* {return new struct SnakeWeedSwarm(); }}; -static const ScriptObjectSpec ActorContraptionEnt = {0x6E, []() -> IScriptObject* {return new struct ActorContraption(); }}; -static const ScriptObjectSpec OculusEnt = {0x6F, []() -> IScriptObject* {return new struct Oculus(); }}; -static const ScriptObjectSpec GeemerEnt = {0x70, []() -> IScriptObject* {return new struct Geemer(); }}; -static const ScriptObjectSpec SpindleCameraEnt = {0x71, []() -> IScriptObject* {return new struct SpindleCamera(); }}; -static const ScriptObjectSpec AtomicAlphaEnt = {0x72, []() -> IScriptObject* {return new struct AtomicAlpha(); }}; -static const ScriptObjectSpec CameraHintTriggerEnt = {0x73, []() -> IScriptObject* {return new struct CameraHintTrigger(); }}; -static const ScriptObjectSpec RumbleEffectEnt = {0x74, []() -> IScriptObject* {return new struct RumbleEffect(); }}; -static const ScriptObjectSpec AmbientAIEnt = {0x75, []() -> IScriptObject* {return new struct AmbientAI(); }}; -static const ScriptObjectSpec AtomicBetaEnt = {0x77, []() -> IScriptObject* {return new struct AtomicBeta(); }}; -static const ScriptObjectSpec IceZoomerEnt = {0x78, []() -> IScriptObject* {return new struct IceZoomer(); }}; -static const ScriptObjectSpec PufferEnt = {0x79, []() -> IScriptObject* {return new struct Puffer(); }}; -static const ScriptObjectSpec TryclopsEnt = {0x7A, []() -> IScriptObject* {return new struct Tryclops(); }}; -static const ScriptObjectSpec RidleyEnt = {0x7B, []() -> IScriptObject* {return new struct Ridley(); }}; -static const ScriptObjectSpec SeedlingEnt = {0x7C, []() -> IScriptObject* {return new struct Seedling(); }}; -static const ScriptObjectSpec ThermalHeatFaderEnt = {0x7D, []() -> IScriptObject* {return new struct ThermalHeatFader(); }}; -static const ScriptObjectSpec BurrowerEnt = {0x7F, []() -> IScriptObject* {return new struct Burrower(); }}; -static const ScriptObjectSpec ScriptBeamEnt = {0x81, []() -> IScriptObject* {return new struct ScriptBeam(); }}; -static const ScriptObjectSpec WorldLightFaderEnt = {0x82, []() -> IScriptObject* {return new struct WorldLightFader(); }}; -static const ScriptObjectSpec MetroidPrimeStage2Ent = {0x83, []() -> IScriptObject* {return new struct MetroidPrimeStage2(); }}; -static const ScriptObjectSpec MetroidPrimeStage1Ent = {0x84, []() -> IScriptObject* {return new struct MetroidPrimeStage1(); }}; -static const ScriptObjectSpec MazeNodeEnt = {0x85, []() -> IScriptObject* {return new struct MazeNode(); }}; -static const ScriptObjectSpec OmegaPirateEnt = {0x86, []() -> IScriptObject* {return new struct OmegaPirate(); }}; -static const ScriptObjectSpec PhazonPoolEnt = {0x87, []() -> IScriptObject* {return new struct PhazonPool(); }}; -static const ScriptObjectSpec PhazonHealingNoduleEnt = {0x88, []() -> IScriptObject* {return new struct PhazonHealingNodule(); }}; -static const ScriptObjectSpec NewCameraShakerEnt = {0x89, []() -> IScriptObject* {return new struct NewCameraShaker(); }}; -static const ScriptObjectSpec ShadowProjectorEnt = {0x8A, []() -> IScriptObject* {return new struct ShadowProjector(); }}; -static const ScriptObjectSpec EnergyBallEnt = {0x8B, []() -> IScriptObject* {return new struct EnergyBall(); }}; -} +namespace DataSpec::DNAMP1 { +namespace priv { +static const ScriptObjectSpec ActorEnt = {0x00, []() -> IScriptObject* { return new struct Actor(); }}; +static const ScriptObjectSpec WaypointEnt = {0x02, []() -> IScriptObject* { return new struct Waypoint(); }}; +static const ScriptObjectSpec DoorAreaEnt = {0x03, []() -> IScriptObject* { return new struct DoorArea(); }}; +static const ScriptObjectSpec TriggerEnt = {0x04, []() -> IScriptObject* { return new struct Trigger(); }}; +static const ScriptObjectSpec TimerEnt = {0x05, []() -> IScriptObject* { return new struct Timer(); }}; +static const ScriptObjectSpec CounterEnt = {0x06, []() -> IScriptObject* { return new struct Counter(); }}; +static const ScriptObjectSpec EffectEnt = {0x07, []() -> IScriptObject* { return new struct Effect(); }}; +static const ScriptObjectSpec PlatformEnt = {0x08, []() -> IScriptObject* { return new struct Platform(); }}; +static const ScriptObjectSpec SoundEnt = {0x09, []() -> IScriptObject* { return new struct Sound(); }}; +static const ScriptObjectSpec GeneratorEnt = {0x0A, []() -> IScriptObject* { return new struct Generator(); }}; +static const ScriptObjectSpec DockEnt = {0x0B, []() -> IScriptObject* { return new struct Dock(); }}; +static const ScriptObjectSpec CameraEnt = {0x0C, []() -> IScriptObject* { return new struct Camera(); }}; +static const ScriptObjectSpec CameraWaypointEnt = {0x0D, + []() -> IScriptObject* { return new struct CameraWaypoint(); }}; +static const ScriptObjectSpec NewIntroBossEnt = {0x0E, []() -> IScriptObject* { return new struct NewIntroBoss(); }}; +static const ScriptObjectSpec SpawnPointEnt = {0x0F, []() -> IScriptObject* { return new struct SpawnPoint(); }}; +static const ScriptObjectSpec CameraHintEnt = {0x10, []() -> IScriptObject* { return new struct CameraHint(); }}; +static const ScriptObjectSpec PickupEnt = {0x11, []() -> IScriptObject* { return new struct Pickup(); }}; +static const ScriptObjectSpec MemoryRelayEnt = {0x13, []() -> IScriptObject* { return new struct MemoryRelay(); }}; +static const ScriptObjectSpec RandomRelayEnt = {0x14, []() -> IScriptObject* { return new struct RandomRelay(); }}; +static const ScriptObjectSpec RelayEnt = {0x15, []() -> IScriptObject* { return new struct Relay(); }}; +static const ScriptObjectSpec BeetleEnt = {0x16, []() -> IScriptObject* { return new struct Beetle(); }}; +static const ScriptObjectSpec HUDMemoEnt = {0x17, []() -> IScriptObject* { return new struct HUDMemo(); }}; +static const ScriptObjectSpec CameraFilterKeyframeEnt = { + 0x18, []() -> IScriptObject* { return new struct CameraFilterKeyframe(); }}; +static const ScriptObjectSpec CameraBlurKeyframeEnt = { + 0x19, []() -> IScriptObject* { return new struct CameraBlurKeyframe(); }}; +static const ScriptObjectSpec DamageableTriggerEnt = { + 0x1A, []() -> IScriptObject* { return new struct DamageableTrigger(); }}; +static const ScriptObjectSpec DebrisEnt = {0x1B, []() -> IScriptObject* { return new struct Debris(); }}; +static const ScriptObjectSpec CameraShakerEnt = {0x1C, []() -> IScriptObject* { return new struct CameraShaker(); }}; +static const ScriptObjectSpec ActorKeyframeEnt = {0x1D, []() -> IScriptObject* { return new struct ActorKeyframe(); }}; +static const ScriptObjectSpec WaterEnt = {0x20, []() -> IScriptObject* { return new struct Water(); }}; +static const ScriptObjectSpec WarwaspEnt = {0x21, []() -> IScriptObject* { return new struct Warwasp(); }}; +static const ScriptObjectSpec SpacePirateEnt = {0x24, []() -> IScriptObject* { return new struct SpacePirate(); }}; +static const ScriptObjectSpec FlyingPirateEnt = {0x25, []() -> IScriptObject* { return new struct FlyingPirate(); }}; +static const ScriptObjectSpec ElitePirateEnt = {0x26, []() -> IScriptObject* { return new struct ElitePirate(); }}; +static const ScriptObjectSpec MetroidBetaEnt = {0x27, []() -> IScriptObject* { return new struct MetroidBeta(); }}; +static const ScriptObjectSpec ChozoGhostEnt = {0x28, []() -> IScriptObject* { return new struct ChozoGhost(); }}; +static const ScriptObjectSpec CoverPointEnt = {0x2A, []() -> IScriptObject* { return new struct CoverPoint(); }}; +static const ScriptObjectSpec SpiderBallWaypointEnt = { + 0x2C, []() -> IScriptObject* { return new struct SpiderBallWaypoint(); }}; +static const ScriptObjectSpec BloodFlowerEnt = {0x2D, []() -> IScriptObject* { return new struct BloodFlower(); }}; +static const ScriptObjectSpec FlickerBatEnt = {0x2E, []() -> IScriptObject* { return new struct FlickerBat(); }}; +static const ScriptObjectSpec PathCameraEnt = {0x2F, []() -> IScriptObject* { return new struct PathCamera(); }}; +static const ScriptObjectSpec GrapplePointEnt = {0x30, []() -> IScriptObject* { return new struct GrapplePoint(); }}; +static const ScriptObjectSpec PuddleSporeEnt = {0x31, []() -> IScriptObject* { return new struct PuddleSpore(); }}; +static const ScriptObjectSpec DebugCameraWaypointEnt = { + 0x32, []() -> IScriptObject* { return new struct DebugCameraWaypoint(); }}; +static const ScriptObjectSpec SpiderBallAttractionSurfaceEnt = { + 0x33, []() -> IScriptObject* { return new struct SpiderBallAttractionSurface(); }}; +static const ScriptObjectSpec PuddleToadGammaEnt = {0x34, + []() -> IScriptObject* { return new struct PuddleToadGamma(); }}; +static const ScriptObjectSpec DistanceFogEnt = {0x35, []() -> IScriptObject* { return new struct DistanceFog(); }}; +static const ScriptObjectSpec FireFleaEnt = {0x36, []() -> IScriptObject* { return new struct FireFlea(); }}; +static const ScriptObjectSpec MetareeAlphaEnt = {0x37, []() -> IScriptObject* { return new struct MetareeAlpha(); }}; +static const ScriptObjectSpec DockAreaChangeEnt = {0x38, + []() -> IScriptObject* { return new struct DockAreaChange(); }}; +static const ScriptObjectSpec ActorRotateEnt = {0x39, []() -> IScriptObject* { return new struct ActorRotate(); }}; +static const ScriptObjectSpec SpecialFunctionEnt = {0x3A, + []() -> IScriptObject* { return new struct SpecialFunction(); }}; +static const ScriptObjectSpec SpankWeedEnt = {0x3B, []() -> IScriptObject* { return new struct SpankWeed(); }}; +static const ScriptObjectSpec ParasiteEnt = {0x3D, []() -> IScriptObject* { return new struct Parasite(); }}; +static const ScriptObjectSpec PlayerHintEnt = {0x3E, []() -> IScriptObject* { return new struct PlayerHint(); }}; +static const ScriptObjectSpec RipperEnt = {0x3F, []() -> IScriptObject* { return new struct Ripper(); }}; +static const ScriptObjectSpec PickupGeneratorEnt = {0x40, + []() -> IScriptObject* { return new struct PickupGenerator(); }}; +static const ScriptObjectSpec AIKeyframeEnt = {0x41, []() -> IScriptObject* { return new struct AIKeyframe(); }}; +static const ScriptObjectSpec PointOfInterestEnt = {0x42, + []() -> IScriptObject* { return new struct PointOfInterest(); }}; +static const ScriptObjectSpec DroneEnt = {0x43, []() -> IScriptObject* { return new struct Drone(); }}; +static const ScriptObjectSpec MetroidAlphaEnt = {0x44, []() -> IScriptObject* { return new struct MetroidAlpha(); }}; +static const ScriptObjectSpec DebrisExtendedEnt = {0x45, + []() -> IScriptObject* { return new struct DebrisExtended(); }}; +static const ScriptObjectSpec SteamEnt = {0x46, []() -> IScriptObject* { return new struct Steam(); }}; +static const ScriptObjectSpec RippleEnt = {0x47, []() -> IScriptObject* { return new struct Ripple(); }}; +static const ScriptObjectSpec BallTriggerEnt = {0x48, []() -> IScriptObject* { return new struct BallTrigger(); }}; +static const ScriptObjectSpec TargetingPointEnt = {0x49, + []() -> IScriptObject* { return new struct TargetingPoint(); }}; +static const ScriptObjectSpec ElectroMagneticPulseEnt = { + 0x4A, []() -> IScriptObject* { return new struct ElectroMagneticPulse(); }}; +static const ScriptObjectSpec IceSheegothEnt = {0x4B, []() -> IScriptObject* { return new struct IceSheegoth(); }}; +static const ScriptObjectSpec PlayerActorEnt = {0x4C, []() -> IScriptObject* { return new struct PlayerActor(); }}; +static const ScriptObjectSpec FlaahgraEnt = {0x4D, []() -> IScriptObject* { return new struct Flaahgra(); }}; +static const ScriptObjectSpec AreaAttributesEnt = {0x4E, + []() -> IScriptObject* { return new struct AreaAttributes(); }}; +static const ScriptObjectSpec FishCloudEnt = {0x4F, []() -> IScriptObject* { return new struct FishCloud(); }}; +static const ScriptObjectSpec FishCloudModifierEnt = { + 0x50, []() -> IScriptObject* { return new struct FishCloudModifier(); }}; +static const ScriptObjectSpec VisorFlareEnt = {0x51, []() -> IScriptObject* { return new struct VisorFlare(); }}; +static const ScriptObjectSpec WorldTeleporterx52Ent = {0x52, + []() -> IScriptObject* { return new struct WorldTeleporter(); }}; +static const ScriptObjectSpec VisorGooEnt = {0x53, []() -> IScriptObject* { return new struct VisorGoo(); }}; +static const ScriptObjectSpec JellyZapEnt = {0x54, []() -> IScriptObject* { return new struct JellyZap(); }}; +static const ScriptObjectSpec ControllerActionEnt = {0x55, + []() -> IScriptObject* { return new struct ControllerAction(); }}; +static const ScriptObjectSpec SwitchEnt = {0x56, []() -> IScriptObject* { return new struct Switch(); }}; +static const ScriptObjectSpec PlayerStateChangeEnt = { + 0x57, []() -> IScriptObject* { return new struct PlayerStateChange(); }}; +static const ScriptObjectSpec ThardusEnt = {0x58, []() -> IScriptObject* { return new struct Thardus(); }}; +static const ScriptObjectSpec WallCrawlerSwarmEnt = {0x5A, + []() -> IScriptObject* { return new struct WallCrawlerSwarm(); }}; +static const ScriptObjectSpec AIJumpPointEnt = {0x5B, []() -> IScriptObject* { return new struct AIJumpPoint(); }}; +static const ScriptObjectSpec FlaahgraTentacleEnt = {0x5C, + []() -> IScriptObject* { return new struct FlaahgraTentacle(); }}; +static const ScriptObjectSpec RoomAcousticsEnt = {0x5D, []() -> IScriptObject* { return new struct RoomAcoustics(); }}; +static const ScriptObjectSpec ColorModulateEnt = {0x5E, []() -> IScriptObject* { return new struct ColorModulate(); }}; +static const ScriptObjectSpec ThardusRockProjectileEnt = { + 0x5F, []() -> IScriptObject* { return new struct ThardusRockProjectile(); }}; +static const ScriptObjectSpec MidiEnt = {0x60, []() -> IScriptObject* { return new struct Midi(); }}; +static const ScriptObjectSpec StreamedAudioEnt = {0x61, []() -> IScriptObject* { return new struct StreamedAudio(); }}; +static const ScriptObjectSpec WorldTeleporterx62Ent = { + 0x62, []() -> IScriptObject* { return new struct WorldTeleporter(); }}; // o.o, no this is not a trick +static const ScriptObjectSpec RepulsorEnt = {0x63, []() -> IScriptObject* { return new struct Repulsor(); }}; +static const ScriptObjectSpec GunTurretEnt = {0x64, []() -> IScriptObject* { return new struct GunTurret(); }}; +static const ScriptObjectSpec FogVolumeEnt = {0x65, []() -> IScriptObject* { return new struct FogVolume(); }}; +static const ScriptObjectSpec BabygothEnt = {0x66, []() -> IScriptObject* { return new struct Babygoth(); }}; +static const ScriptObjectSpec EyeballEnt = {0x67, []() -> IScriptObject* { return new struct Eyeball(); }}; +static const ScriptObjectSpec RadialDamageEnt = {0x68, []() -> IScriptObject* { return new struct RadialDamage(); }}; +static const ScriptObjectSpec CameraPitchVolumeEnt = { + 0x69, []() -> IScriptObject* { return new struct CameraPitchVolume(); }}; +static const ScriptObjectSpec EnvFxDensityControllerEnt = { + 0x6A, []() -> IScriptObject* { return new struct EnvFxDensityController(); }}; +static const ScriptObjectSpec MagdoliteEnt = {0x6B, []() -> IScriptObject* { return new struct Magdolite(); }}; +static const ScriptObjectSpec TeamAIMgrEnt = {0x6C, []() -> IScriptObject* { return new struct TeamAIMgr(); }}; +static const ScriptObjectSpec SnakeWeedSwarmEnt = {0x6D, + []() -> IScriptObject* { return new struct SnakeWeedSwarm(); }}; +static const ScriptObjectSpec ActorContraptionEnt = {0x6E, + []() -> IScriptObject* { return new struct ActorContraption(); }}; +static const ScriptObjectSpec OculusEnt = {0x6F, []() -> IScriptObject* { return new struct Oculus(); }}; +static const ScriptObjectSpec GeemerEnt = {0x70, []() -> IScriptObject* { return new struct Geemer(); }}; +static const ScriptObjectSpec SpindleCameraEnt = {0x71, []() -> IScriptObject* { return new struct SpindleCamera(); }}; +static const ScriptObjectSpec AtomicAlphaEnt = {0x72, []() -> IScriptObject* { return new struct AtomicAlpha(); }}; +static const ScriptObjectSpec CameraHintTriggerEnt = { + 0x73, []() -> IScriptObject* { return new struct CameraHintTrigger(); }}; +static const ScriptObjectSpec RumbleEffectEnt = {0x74, []() -> IScriptObject* { return new struct RumbleEffect(); }}; +static const ScriptObjectSpec AmbientAIEnt = {0x75, []() -> IScriptObject* { return new struct AmbientAI(); }}; +static const ScriptObjectSpec AtomicBetaEnt = {0x77, []() -> IScriptObject* { return new struct AtomicBeta(); }}; +static const ScriptObjectSpec IceZoomerEnt = {0x78, []() -> IScriptObject* { return new struct IceZoomer(); }}; +static const ScriptObjectSpec PufferEnt = {0x79, []() -> IScriptObject* { return new struct Puffer(); }}; +static const ScriptObjectSpec TryclopsEnt = {0x7A, []() -> IScriptObject* { return new struct Tryclops(); }}; +static const ScriptObjectSpec RidleyEnt = {0x7B, []() -> IScriptObject* { return new struct Ridley(); }}; +static const ScriptObjectSpec SeedlingEnt = {0x7C, []() -> IScriptObject* { return new struct Seedling(); }}; +static const ScriptObjectSpec ThermalHeatFaderEnt = {0x7D, + []() -> IScriptObject* { return new struct ThermalHeatFader(); }}; +static const ScriptObjectSpec BurrowerEnt = {0x7F, []() -> IScriptObject* { return new struct Burrower(); }}; +static const ScriptObjectSpec ScriptBeamEnt = {0x81, []() -> IScriptObject* { return new struct ScriptBeam(); }}; +static const ScriptObjectSpec WorldLightFaderEnt = {0x82, + []() -> IScriptObject* { return new struct WorldLightFader(); }}; +static const ScriptObjectSpec MetroidPrimeStage2Ent = { + 0x83, []() -> IScriptObject* { return new struct MetroidPrimeStage2(); }}; +static const ScriptObjectSpec MetroidPrimeStage1Ent = { + 0x84, []() -> IScriptObject* { return new struct MetroidPrimeStage1(); }}; +static const ScriptObjectSpec MazeNodeEnt = {0x85, []() -> IScriptObject* { return new struct MazeNode(); }}; +static const ScriptObjectSpec OmegaPirateEnt = {0x86, []() -> IScriptObject* { return new struct OmegaPirate(); }}; +static const ScriptObjectSpec PhazonPoolEnt = {0x87, []() -> IScriptObject* { return new struct PhazonPool(); }}; +static const ScriptObjectSpec PhazonHealingNoduleEnt = { + 0x88, []() -> IScriptObject* { return new struct PhazonHealingNodule(); }}; +static const ScriptObjectSpec NewCameraShakerEnt = {0x89, + []() -> IScriptObject* { return new struct NewCameraShaker(); }}; +static const ScriptObjectSpec ShadowProjectorEnt = {0x8A, + []() -> IScriptObject* { return new struct ShadowProjector(); }}; +static const ScriptObjectSpec EnergyBallEnt = {0x8B, []() -> IScriptObject* { return new struct EnergyBall(); }}; +} // namespace priv -const std::vector SCRIPT_OBJECT_DB = -{ +const std::vector SCRIPT_OBJECT_DB = { &priv::AIJumpPointEnt, &priv::AIKeyframeEnt, &priv::ActorEnt, @@ -265,16 +298,12 @@ const std::vector SCRIPT_OBJECT_DB = &priv::WorldTeleporterx62Ent, }; -zeus::CTransform ConvertEditorEulerToTransform4f(const zeus::CVector3f& scale, - const zeus::CVector3f& orientation, - const zeus::CVector3f& position) -{ - zeus::simd_floats f(orientation.mSimd); - return zeus::CTransform::RotateZ(zeus::degToRad(f[2])) * - zeus::CTransform::RotateY(zeus::degToRad(f[1])) * - zeus::CTransform::RotateX(zeus::degToRad(f[0])) * - zeus::CTransform::Scale(scale) + - position; +zeus::CTransform ConvertEditorEulerToTransform4f(const zeus::CVector3f& scale, const zeus::CVector3f& orientation, + const zeus::CVector3f& position) { + zeus::simd_floats f(orientation.mSimd); + return zeus::CTransform::RotateZ(zeus::degToRad(f[2])) * zeus::CTransform::RotateY(zeus::degToRad(f[1])) * + zeus::CTransform::RotateX(zeus::degToRad(f[0])) * zeus::CTransform::Scale(scale) + + position; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/IScriptObject.hpp b/DataSpec/DNAMP1/ScriptObjects/IScriptObject.hpp index c3e87db57..22e41d4df 100644 --- a/DataSpec/DNAMP1/ScriptObjects/IScriptObject.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/IScriptObject.hpp @@ -15,38 +15,32 @@ #define SO_COLLISION_OFFSET_SPECPROP() SPECTER_PROPERTY("Collision Offset", "") #define SO_ACTIVE_SPECPROP() SPECTER_PROPERTY("Active", "If enabled, object instance is drawn and updated") -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -zeus::CTransform ConvertEditorEulerToTransform4f(const zeus::CVector3f& scale, - const zeus::CVector3f& orientation, +zeus::CTransform ConvertEditorEulerToTransform4f(const zeus::CVector3f& scale, const zeus::CVector3f& orientation, const zeus::CVector3f& position); -struct IScriptObject : BigDNAVYaml -{ +struct IScriptObject : BigDNAVYaml { + AT_DECL_DNA_YAML + atUint32 type; + Value id; + struct Connection : BigDNA { AT_DECL_DNA_YAML - atUint32 type; - Value id; - struct Connection : BigDNA - { - AT_DECL_DNA_YAML - Value state; - Value msg; - Value target; - }; + Value state; + Value msg; + Value target; + }; - Value connectionCount; - Vector connections; - Value propertyCount; - virtual ~IScriptObject() = default; + Value connectionCount; + Vector connections; + Value propertyCount; + virtual ~IScriptObject() = default; - virtual void addCMDLRigPairs(PAKRouter&, - CharacterAssociations& charAssoc) const {} - virtual void nameIDs(PAKRouter& pakRouter) const {} - virtual void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const {} - virtual void gatherScans(std::vector& scansOut) const {} - virtual zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const { return {}; } + virtual void addCMDLRigPairs(PAKRouter&, CharacterAssociations& charAssoc) const {} + virtual void nameIDs(PAKRouter& pakRouter) const {} + virtual void gatherDependencies(std::vector& pathsOut, + std::vector& lazyOut) const {} + virtual void gatherScans(std::vector& scansOut) const {} + virtual zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const { return {}; } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/IceSheegoth.hpp b/DataSpec/DNAMP1/ScriptObjects/IceSheegoth.hpp index e17add372..4cf0b7c9a 100644 --- a/DataSpec/DNAMP1/ScriptObjects/IceSheegoth.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/IceSheegoth.hpp @@ -4,132 +4,112 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct IceSheegoth : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - DamageVulnerability damageVulnerabilty1; - DamageVulnerability damageVulnerabilty2; - DamageVulnerability damageVulnerabilty3; - UniqueID32 wpsc1; - DamageInfo damageInfo1; - Value unknown5; - Value unknown6; - UniqueID32 wpsc2; - UniqueID32 particle1; - DamageInfo damageInfo2; - UniqueID32 particle2; - UniqueID32 particle3; - UniqueID32 particle4; - UniqueID32 particle5; - UniqueID32 elsc; - Value unknown7; - Value unknown8; - DamageInfo damageInfo3; - Value soundID1; - Value unknown9; - Value unknown10; - Value unknown11; - UniqueID32 texture; - Value soundID2; - UniqueID32 particle6; - Value unknown12; - Value unknown13; +namespace DataSpec::DNAMP1 { +struct IceSheegoth : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + DamageVulnerability damageVulnerabilty1; + DamageVulnerability damageVulnerabilty2; + DamageVulnerability damageVulnerabilty3; + UniqueID32 wpsc1; + DamageInfo damageInfo1; + Value unknown5; + Value unknown6; + UniqueID32 wpsc2; + UniqueID32 particle1; + DamageInfo damageInfo2; + UniqueID32 particle2; + UniqueID32 particle3; + UniqueID32 particle4; + UniqueID32 particle5; + UniqueID32 elsc; + Value unknown7; + Value unknown8; + DamageInfo damageInfo3; + Value soundID1; + Value unknown9; + Value unknown10; + Value unknown11; + UniqueID32 texture; + Value soundID2; + UniqueID32 particle6; + Value unknown12; + Value unknown13; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc1"; - } - if (wpsc2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); - ent->name = name + "_wpsc2"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - if (particle5) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); - ent->name = name + "_part5"; - } - if (elsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); - ent->name = name + "_elsc"; - } - if (texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); - ent->name = name + "_texture"; - } - if (particle6) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); - ent->name = name + "_part6"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc1"; } + if (wpsc2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); + ent->name = name + "_wpsc2"; + } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + if (particle5) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); + ent->name = name + "_part5"; + } + if (elsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); + ent->name = name + "_elsc"; + } + if (texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); + ent->name = name + "_texture"; + } + if (particle6) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); + ent->name = name + "_part6"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(wpsc2, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - g_curSpec->flattenDependencies(particle5, pathsOut); - g_curSpec->flattenDependencies(elsc, pathsOut); - g_curSpec->flattenDependencies(texture, pathsOut); - g_curSpec->flattenDependencies(particle6, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(wpsc2, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + g_curSpec->flattenDependencies(particle5, pathsOut); + g_curSpec->flattenDependencies(elsc, pathsOut); + g_curSpec->flattenDependencies(texture, pathsOut); + g_curSpec->flattenDependencies(particle6, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/IceZoomer.hpp b/DataSpec/DNAMP1/ScriptObjects/IceZoomer.hpp index d9568eb19..bcf3e7ca8 100644 --- a/DataSpec/DNAMP1/ScriptObjects/IceZoomer.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/IceZoomer.hpp @@ -4,51 +4,41 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct IceZoomer : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - DamageVulnerability damageVulnerabilty; - Value unknown9; +namespace DataSpec::DNAMP1 { +struct IceZoomer : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + DamageVulnerability damageVulnerabilty; + Value unknown9; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/JellyZap.hpp b/DataSpec/DNAMP1/ScriptObjects/JellyZap.hpp index 46837bb10..3930dd34f 100644 --- a/DataSpec/DNAMP1/ScriptObjects/JellyZap.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/JellyZap.hpp @@ -4,55 +4,45 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct JellyZap : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - DamageInfo damageInfo; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; +namespace DataSpec::DNAMP1 { +struct JellyZap : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + DamageInfo damageInfo; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Magdolite.hpp b/DataSpec/DNAMP1/ScriptObjects/Magdolite.hpp index 184569ea2..6d39aa87e 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Magdolite.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Magdolite.hpp @@ -4,95 +4,79 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Magdolite : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - DamageInfo damageInfo1; - DamageInfo damageInfo2; - DamageVulnerability damageVulnerabilty1; - DamageVulnerability damageVulnerabilty2; - UniqueID32 cmdlHeadless; - UniqueID32 cskrHeadless; +namespace DataSpec::DNAMP1 { +struct Magdolite : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + DamageInfo damageInfo1; + DamageInfo damageInfo2; + DamageVulnerability damageVulnerabilty1; + DamageVulnerability damageVulnerabilty2; + UniqueID32 cmdlHeadless; + UniqueID32 cskrHeadless; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + struct MagdoliteParameters : BigDNA { + AT_DECL_DNA + Value propertyCount; + Value unknown1; + UniqueID32 particle; + Value unknown2; Value unknown3; Value unknown4; Value unknown5; - Value unknown6; - struct MagdoliteParameters : BigDNA - { - AT_DECL_DNA - Value propertyCount; - Value unknown1; - UniqueID32 particle; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - } magdoliteParameters; - Value unknown7; - Value unknown8; - Value unknown9; + } magdoliteParameters; + Value unknown7; + Value unknown8; + Value unknown9; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - UniqueID32 cinf = patternedInfo.animationParameters.getCINF(pakRouter); - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + UniqueID32 cinf = patternedInfo.animationParameters.getCINF(pakRouter); + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - if (cmdlHeadless && cskrHeadless) - { - charAssoc.m_cmdlRigs[cmdlHeadless] = std::make_pair(cskrHeadless, cinf); - charAssoc.m_cskrCinfToCharacter[cskrHeadless] = std::make_pair( - patternedInfo.animationParameters.animationCharacterSet, "ATTACH.HEADLESS.CSKR"); - charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, - {}, cmdlHeadless, "HEADLESS"); - } + if (cmdlHeadless && cskrHeadless) { + charAssoc.m_cmdlRigs[cmdlHeadless] = std::make_pair(cskrHeadless, cinf); + charAssoc.m_cskrCinfToCharacter[cskrHeadless] = + std::make_pair(patternedInfo.animationParameters.animationCharacterSet, "ATTACH.HEADLESS.CSKR"); + charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, {}, cmdlHeadless, "HEADLESS"); } + } - void nameIDs(PAKRouter& pakRouter) const - { - if (cmdlHeadless) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cmdlHeadless); - ent->name = name + "_emodel"; - } - if (cskrHeadless) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cskrHeadless); - ent->name = name + "_eskin"; - } - if (magdoliteParameters.particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(magdoliteParameters.particle); - ent->name = name + "_part"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (cmdlHeadless) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cmdlHeadless); + ent->name = name + "_emodel"; } + if (cskrHeadless) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cskrHeadless); + ent->name = name + "_eskin"; + } + if (magdoliteParameters.particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(magdoliteParameters.particle); + ent->name = name + "_part"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(cmdlHeadless, pathsOut); - g_curSpec->flattenDependencies(cskrHeadless, pathsOut); - g_curSpec->flattenDependencies(magdoliteParameters.particle, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(cmdlHeadless, pathsOut); + g_curSpec->flattenDependencies(cskrHeadless, pathsOut); + g_curSpec->flattenDependencies(magdoliteParameters.particle, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/MazeNode.hpp b/DataSpec/DNAMP1/ScriptObjects/MazeNode.hpp index a95c28b1c..aae7af705 100644 --- a/DataSpec/DNAMP1/ScriptObjects/MazeNode.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/MazeNode.hpp @@ -4,22 +4,19 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct MazeNode : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; +namespace DataSpec::DNAMP1 { +struct MazeNode : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/MemoryRelay.hpp b/DataSpec/DNAMP1/ScriptObjects/MemoryRelay.hpp index b03a4047c..52009f9fa 100644 --- a/DataSpec/DNAMP1/ScriptObjects/MemoryRelay.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/MemoryRelay.hpp @@ -4,15 +4,12 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct MemoryRelay : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown; - Value active; +namespace DataSpec::DNAMP1 { +struct MemoryRelay : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown; + Value active; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/MetareeAlpha.hpp b/DataSpec/DNAMP1/ScriptObjects/MetareeAlpha.hpp index 3b01142fc..6d3cdd709 100644 --- a/DataSpec/DNAMP1/ScriptObjects/MetareeAlpha.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/MetareeAlpha.hpp @@ -4,47 +4,37 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct MetareeAlpha : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - DamageInfo damageInfo; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; +namespace DataSpec::DNAMP1 { +struct MetareeAlpha : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + DamageInfo damageInfo; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/MetroidAlpha.hpp b/DataSpec/DNAMP1/ScriptObjects/MetroidAlpha.hpp index e3a806a54..9eb323f41 100644 --- a/DataSpec/DNAMP1/ScriptObjects/MetroidAlpha.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/MetroidAlpha.hpp @@ -4,63 +4,53 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct MetroidAlpha : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - DamageVulnerability damageVulnerabilty1; - DamageVulnerability damageVulnerabilty2; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - AnimationParameters animationParameters1; - AnimationParameters animationParameters2; - AnimationParameters animationParameters3; - AnimationParameters animationParameters4; - Value unknown8; +namespace DataSpec::DNAMP1 { +struct MetroidAlpha : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + DamageVulnerability damageVulnerabilty1; + DamageVulnerability damageVulnerabilty2; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + AnimationParameters animationParameters1; + AnimationParameters animationParameters2; + AnimationParameters animationParameters3; + AnimationParameters animationParameters4; + Value unknown8; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - animationParameters1.nameANCS(pakRouter, name + "_animp1"); - animationParameters2.nameANCS(pakRouter, name + "_animp2"); - animationParameters3.nameANCS(pakRouter, name + "_animp3"); - animationParameters4.nameANCS(pakRouter, name + "_animp4"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + animationParameters1.nameANCS(pakRouter, name + "_animp1"); + animationParameters2.nameANCS(pakRouter, name + "_animp2"); + animationParameters3.nameANCS(pakRouter, name + "_animp3"); + animationParameters4.nameANCS(pakRouter, name + "_animp4"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - animationParameters1.depANCS(pathsOut); - animationParameters2.depANCS(pathsOut); - animationParameters3.depANCS(pathsOut); - animationParameters4.depANCS(pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + animationParameters1.depANCS(pathsOut); + animationParameters2.depANCS(pathsOut); + animationParameters3.depANCS(pathsOut); + animationParameters4.depANCS(pathsOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/MetroidBeta.hpp b/DataSpec/DNAMP1/ScriptObjects/MetroidBeta.hpp index 256fff571..5077a444a 100644 --- a/DataSpec/DNAMP1/ScriptObjects/MetroidBeta.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/MetroidBeta.hpp @@ -4,88 +4,73 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct MetroidBeta : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - DamageVulnerability damageVulnerabilty1; - DamageVulnerability damageVulnerabilty2; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - UniqueID32 particle1; - UniqueID32 swhc; - UniqueID32 particle2; - UniqueID32 particle3; - UniqueID32 particle4; - Value unknown10; +namespace DataSpec::DNAMP1 { +struct MetroidBeta : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + DamageVulnerability damageVulnerabilty1; + DamageVulnerability damageVulnerabilty2; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + UniqueID32 particle1; + UniqueID32 swhc; + UniqueID32 particle2; + UniqueID32 particle3; + UniqueID32 particle4; + Value unknown10; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - if (swhc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(swhc); - ent->name = name + "_swhc"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + if (swhc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(swhc); + ent->name = name + "_swhc"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - g_curSpec->flattenDependencies(swhc, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + g_curSpec->flattenDependencies(swhc, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/MetroidPrimeStage1.hpp b/DataSpec/DNAMP1/ScriptObjects/MetroidPrimeStage1.hpp index 950dbc347..54926a3d3 100644 --- a/DataSpec/DNAMP1/ScriptObjects/MetroidPrimeStage1.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/MetroidPrimeStage1.hpp @@ -4,351 +4,300 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct MetroidPrimeStage1 : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value version; - String<-1> name; - Value location; - Value orientation; - Value scale; - Value unknown2; +namespace DataSpec::DNAMP1 { +struct MetroidPrimeStage1 : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value version; + String<-1> name; + Value location; + Value orientation; + Value scale; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + HealthInfo healthInfo1; + HealthInfo healthInfo2; + Value unknown9; + + struct PrimeParameters1 : BigDNA { + AT_DECL_DNA + Value propertyCount; + Value unknown1; + Value unknown2; Value unknown3; Value unknown4; Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - HealthInfo healthInfo1; - HealthInfo healthInfo2; - Value unknown9; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + } primeStruct1[4]; - struct PrimeParameters1 : BigDNA - { + Value unknown10; + Value unknown11; + + struct MassivePrimeStruct : BigDNA { + AT_DECL_DNA + Value propertyCount; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown2; + struct CameraShakeData : BigDNA { + AT_DECL_DNA + Value useSfx; + Value duration; + Value sfxDist; + struct CameraShakerComponent : BigDNA { + AT_DECL_DNA + Value useModulation; + struct CameraShakePoint : BigDNA { + AT_DECL_DNA + Value attackTime; + Value sustainTime; + Value duration; + Value magnitude; + }; + CameraShakePoint am; + CameraShakePoint fm; + } shakerComponents[3]; + } shakeDatas[3]; + + struct PrimeStruct2B : BigDNA { + AT_DECL_DNA + Value propertyCount; + UniqueID32 particle1; + UniqueID32 particle2; + UniqueID32 particle3; + DamageInfo damageInfo1; + Value unknown5; + Value unknown6; + UniqueID32 texture1; + Value unknown7; + Value unknown8; + + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (texture1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); + ent->name = name + "_tex1"; + } + } + + void depIDs(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(texture1, pathsOut); + } + } primeStruct2b; + + UniqueID32 particle4; + + struct PrimeStruct4 : BigDNA { + AT_DECL_DNA + BeamInfo beamInfo; + UniqueID32 wpsc; + DamageInfo damageInfo1; + struct PrimeStruct5 : BigDNA { AT_DECL_DNA Value propertyCount; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - } primeStruct1[4]; - - Value unknown10; - Value unknown11; - - struct MassivePrimeStruct : BigDNA - { - AT_DECL_DNA - Value propertyCount; - PatternedInfo patternedInfo; - ActorParameters actorParameters; + UniqueID32 unknown1; Value unknown2; - struct CameraShakeData : BigDNA - { - AT_DECL_DNA - Value useSfx; - Value duration; - Value sfxDist; - struct CameraShakerComponent : BigDNA - { - AT_DECL_DNA - Value useModulation; - struct CameraShakePoint : BigDNA - { - AT_DECL_DNA - Value attackTime; - Value sustainTime; - Value duration; - Value magnitude; - }; - CameraShakePoint am; - CameraShakePoint fm; - } shakerComponents[3]; - } shakeDatas[3]; + UniqueID32 unknown3; + UniqueID32 unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; - struct PrimeStruct2B : BigDNA - { - AT_DECL_DNA - Value propertyCount; - UniqueID32 particle1; - UniqueID32 particle2; - UniqueID32 particle3; - DamageInfo damageInfo1; - Value unknown5; - Value unknown6; - UniqueID32 texture1; - Value unknown7; - Value unknown8; - - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (texture1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); - ent->name = name + "_tex1"; - } - } - - void depIDs(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(texture1, pathsOut); - } - } primeStruct2b; - - UniqueID32 particle4; - - struct PrimeStruct4 : BigDNA - { - AT_DECL_DNA - BeamInfo beamInfo; - UniqueID32 wpsc; - DamageInfo damageInfo1; - struct PrimeStruct5 : BigDNA - { - AT_DECL_DNA - Value propertyCount; - UniqueID32 unknown1; - Value unknown2; - UniqueID32 unknown3; - UniqueID32 unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - if (unknown1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown1); - ent->name = name + "_unk1"; - } - if (unknown3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown3); - ent->name = name + "_unk3"; - } - if (unknown4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown4); - ent->name = name + "_unk4"; - } - } - - void depIDs(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(unknown1, pathsOut); - g_curSpec->flattenDependencies(unknown3, pathsOut); - g_curSpec->flattenDependencies(unknown4, pathsOut); - } - } primeStruct5; - Value unknown14; - DamageInfo damageInfo2; - - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - beamInfo.nameIDs(pakRouter, name + "_beamInfo"); - if (wpsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); - ent->name = name + "_wpsc"; - } - primeStruct5.nameIDs(pakRouter, name + "_prime5"); - } - - void depIDs(std::vector& pathsOut) const - { - beamInfo.depIDs(pathsOut); - g_curSpec->flattenDependencies(wpsc, pathsOut); - primeStruct5.depIDs(pathsOut); - } - } primeStruct4s[4]; - - UniqueID32 wpsc1; - DamageInfo damageInfo2; - CameraShakeData primeStruct2_4; - UniqueID32 wpsc2; - DamageInfo damageInfo3; - CameraShakeData primeStruct2_5; - - struct PrimeProjectileInfo : BigDNA - { - AT_DECL_DNA - Value propertyCount; - UniqueID32 particle; - DamageInfo damageInfo4; - Value unknown9; - Value unknown10; - Value unknown11; - UniqueID32 texture; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; - - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - if (texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); - ent->name = name + "_tex"; - } - } - - void depIDs(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(particle, pathsOut); - g_curSpec->flattenDependencies(texture, pathsOut); - } - } projectileInfo; - - DamageInfo damageInfo5; - CameraShakeData primeStruct2_6; - UniqueID32 particle6; - UniqueID32 swhc; - UniqueID32 particle7; - UniqueID32 particle8; - - struct PrimeStruct6 : BigDNA - { - AT_DECL_DNA - Value propertyCount; - DamageVulnerability damageVulnerability; - DNAColor unknown1; - Value unknown2; - Value unknown3; - } primeStruct6s[4]; - - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - primeStruct2b.nameIDs(pakRouter, name + "_prime2b"); - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - if (particle6) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); - ent->name = name + "_part6"; - } - if (particle7) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7); - ent->name = name + "_part7"; - } - if (particle8) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle8); - ent->name = name + "_part8"; - } - if (swhc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(swhc); - ent->name = name + "_swhc"; - } - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc1"; - } - if (wpsc2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); - ent->name = name + "_wpsc2"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - primeStruct4s[0].nameIDs(pakRouter, name + "_prime41"); - primeStruct4s[1].nameIDs(pakRouter, name + "_prime42"); - primeStruct4s[2].nameIDs(pakRouter, name + "_prime43"); - primeStruct4s[3].nameIDs(pakRouter, name + "_prime44"); - projectileInfo.nameIDs(pakRouter, name + "_projectileInfo"); + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + if (unknown1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown1); + ent->name = name + "_unk1"; + } + if (unknown3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown3); + ent->name = name + "_unk3"; + } + if (unknown4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown4); + ent->name = name + "_unk4"; + } } - void depIDs(std::vector& pathsOut, - std::vector& lazyOut) const - { - primeStruct2b.depIDs(pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - g_curSpec->flattenDependencies(particle6, pathsOut); - g_curSpec->flattenDependencies(particle7, pathsOut); - g_curSpec->flattenDependencies(particle8, pathsOut); - g_curSpec->flattenDependencies(swhc, pathsOut); - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(wpsc2, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - primeStruct4s[0].depIDs(pathsOut); - primeStruct4s[1].depIDs(pathsOut); - primeStruct4s[2].depIDs(pathsOut); - primeStruct4s[3].depIDs(pathsOut); - projectileInfo.depIDs(pathsOut); + void depIDs(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(unknown1, pathsOut); + g_curSpec->flattenDependencies(unknown3, pathsOut); + g_curSpec->flattenDependencies(unknown4, pathsOut); } + } primeStruct5; + Value unknown14; + DamageInfo damageInfo2; - void scanIDs(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + beamInfo.nameIDs(pakRouter, name + "_beamInfo"); + if (wpsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); + ent->name = name + "_wpsc"; } - } massivePrimeStruct; + primeStruct5.nameIDs(pakRouter, name + "_prime5"); + } - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - massivePrimeStruct.actorParameters.addCMDLRigPairs(pakRouter, charAssoc, - massivePrimeStruct.patternedInfo.animationParameters); + void depIDs(std::vector& pathsOut) const { + beamInfo.depIDs(pathsOut); + g_curSpec->flattenDependencies(wpsc, pathsOut); + primeStruct5.depIDs(pathsOut); + } + } primeStruct4s[4]; + + UniqueID32 wpsc1; + DamageInfo damageInfo2; + CameraShakeData primeStruct2_4; + UniqueID32 wpsc2; + DamageInfo damageInfo3; + CameraShakeData primeStruct2_5; + + struct PrimeProjectileInfo : BigDNA { + AT_DECL_DNA + Value propertyCount; + UniqueID32 particle; + DamageInfo damageInfo4; + Value unknown9; + Value unknown10; + Value unknown11; + UniqueID32 texture; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; + } + if (texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); + ent->name = name + "_tex"; + } + } + + void depIDs(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(particle, pathsOut); + g_curSpec->flattenDependencies(texture, pathsOut); + } + } projectileInfo; + + DamageInfo damageInfo5; + CameraShakeData primeStruct2_6; + UniqueID32 particle6; + UniqueID32 swhc; + UniqueID32 particle7; + UniqueID32 particle8; + + struct PrimeStruct6 : BigDNA { + AT_DECL_DNA + Value propertyCount; + DamageVulnerability damageVulnerability; + DNAColor unknown1; + Value unknown2; + Value unknown3; + } primeStruct6s[4]; + + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + primeStruct2b.nameIDs(pakRouter, name + "_prime2b"); + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + if (particle6) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); + ent->name = name + "_part6"; + } + if (particle7) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7); + ent->name = name + "_part7"; + } + if (particle8) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle8); + ent->name = name + "_part8"; + } + if (swhc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(swhc); + ent->name = name + "_swhc"; + } + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc1"; + } + if (wpsc2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); + ent->name = name + "_wpsc2"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + primeStruct4s[0].nameIDs(pakRouter, name + "_prime41"); + primeStruct4s[1].nameIDs(pakRouter, name + "_prime42"); + primeStruct4s[2].nameIDs(pakRouter, name + "_prime43"); + primeStruct4s[3].nameIDs(pakRouter, name + "_prime44"); + projectileInfo.nameIDs(pakRouter, name + "_projectileInfo"); } - void nameIDs(PAKRouter& pakRouter) const - { - massivePrimeStruct.nameIDs(pakRouter, name + "_massiveStruct"); + void depIDs(std::vector& pathsOut, std::vector& lazyOut) const { + primeStruct2b.depIDs(pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + g_curSpec->flattenDependencies(particle6, pathsOut); + g_curSpec->flattenDependencies(particle7, pathsOut); + g_curSpec->flattenDependencies(particle8, pathsOut); + g_curSpec->flattenDependencies(swhc, pathsOut); + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(wpsc2, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + primeStruct4s[0].depIDs(pathsOut); + primeStruct4s[1].depIDs(pathsOut); + primeStruct4s[2].depIDs(pathsOut); + primeStruct4s[3].depIDs(pathsOut); + projectileInfo.depIDs(pathsOut); } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - massivePrimeStruct.depIDs(pathsOut, lazyOut); - } + void scanIDs(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } + } massivePrimeStruct; - void gatherScans(std::vector& scansOut) const - { - massivePrimeStruct.scanIDs(scansOut); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + massivePrimeStruct.actorParameters.addCMDLRigPairs(pakRouter, charAssoc, + massivePrimeStruct.patternedInfo.animationParameters); + } + + void nameIDs(PAKRouter& pakRouter) const { + massivePrimeStruct.nameIDs(pakRouter, name + "_massiveStruct"); + } + + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + massivePrimeStruct.depIDs(pathsOut, lazyOut); + } + + void gatherScans(std::vector& scansOut) const { massivePrimeStruct.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/MetroidPrimeStage2.hpp b/DataSpec/DNAMP1/ScriptObjects/MetroidPrimeStage2.hpp index 52f94c9fa..bfdbef03e 100644 --- a/DataSpec/DNAMP1/ScriptObjects/MetroidPrimeStage2.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/MetroidPrimeStage2.hpp @@ -4,64 +4,51 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct MetroidPrimeStage2 : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - UniqueID32 particle1; - DamageInfo damageInfo; - UniqueID32 elsc; - Value unknown; - UniqueID32 particle2; +namespace DataSpec::DNAMP1 { +struct MetroidPrimeStage2 : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + UniqueID32 particle1; + DamageInfo damageInfo; + UniqueID32 elsc; + Value unknown; + UniqueID32 particle2; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (elsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); - ent->name = name + "_elsc"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (elsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); + ent->name = name + "_elsc"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(elsc, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(elsc, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Midi.hpp b/DataSpec/DNAMP1/ScriptObjects/Midi.hpp index 34cc896f4..55cc8cef3 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Midi.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Midi.hpp @@ -4,34 +4,27 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Midi : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; - UniqueID32 song; - Value fadeInTime; - Value fadeOutTime; - Value volume; +namespace DataSpec::DNAMP1 { +struct Midi : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; + UniqueID32 song; + Value fadeInTime; + Value fadeOutTime; + Value volume; - void nameIDs(PAKRouter& pakRouter) const - { - if (song) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(song); - ent->name = name + "_song"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (song) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(song); + ent->name = name + "_song"; } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - // Dedicated PAK for this - //g_curSpec->flattenDependencies(song, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + // Dedicated PAK for this + // g_curSpec->flattenDependencies(song, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/NewCameraShaker.hpp b/DataSpec/DNAMP1/ScriptObjects/NewCameraShaker.hpp index 3210e4b69..35366211b 100644 --- a/DataSpec/DNAMP1/ScriptObjects/NewCameraShaker.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/NewCameraShaker.hpp @@ -4,34 +4,29 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct NewCameraShaker : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value active; +namespace DataSpec::DNAMP1 { +struct NewCameraShaker : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value active; + PlayerParameters flags; + Value duration; + Value sfxDist; + struct CameraShakerComponent : BigDNA { + AT_DECL_DNA PlayerParameters flags; - Value duration; - Value sfxDist; - struct CameraShakerComponent : BigDNA - { - AT_DECL_DNA - PlayerParameters flags; - struct CameraShakePoint : BigDNA - { - AT_DECL_DNA - PlayerParameters flags; - Value attackTime; - Value sustainTime; - Value duration; - Value magnitude; - }; - CameraShakePoint am; - CameraShakePoint fm; - } shakerComponents[3]; + struct CameraShakePoint : BigDNA { + AT_DECL_DNA + PlayerParameters flags; + Value attackTime; + Value sustainTime; + Value duration; + Value magnitude; + }; + CameraShakePoint am; + CameraShakePoint fm; + } shakerComponents[3]; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/NewIntroBoss.hpp b/DataSpec/DNAMP1/ScriptObjects/NewIntroBoss.hpp index 54f3fb1e8..7a3e9cb77 100644 --- a/DataSpec/DNAMP1/ScriptObjects/NewIntroBoss.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/NewIntroBoss.hpp @@ -4,73 +4,59 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct NewIntroBoss : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - UniqueID32 weaponDesc; - DamageInfo damageInfo; - UniqueID32 particle1; - UniqueID32 particle2; - UniqueID32 texture1; - UniqueID32 texture2; +namespace DataSpec::DNAMP1 { +struct NewIntroBoss : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + UniqueID32 weaponDesc; + DamageInfo damageInfo; + UniqueID32 particle1; + UniqueID32 particle2; + UniqueID32 texture1; + UniqueID32 texture2; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (texture1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); - ent->name = name + "_tex1"; - } - if (texture2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); - ent->name = name + "_tex2"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (texture1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); + ent->name = name + "_tex1"; + } + if (texture2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); + ent->name = name + "_tex2"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(weaponDesc, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(texture1, pathsOut); - g_curSpec->flattenDependencies(texture2, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(weaponDesc, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(texture1, pathsOut); + g_curSpec->flattenDependencies(texture2, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Oculus.cpp b/DataSpec/DNAMP1/ScriptObjects/Oculus.cpp index 970c73f7a..e437bc2b9 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Oculus.cpp +++ b/DataSpec/DNAMP1/ScriptObjects/Oculus.cpp @@ -1,38 +1,33 @@ #include "Oculus.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template -void Oculus::Enumerate(typename Op::StreamT& s) -{ - IScriptObject::Enumerate(s); - Do({"name"}, name, s); - Do({"location"}, location, s); - Do({"orientation"}, orientation, s); - Do({"scale"}, scale, s); - Do({"patternedInfo"}, patternedInfo, s); - Do({"actorParameters"}, actorParameters, s); - Do({"unknown1"}, unknown1, s); - Do({"unknown2"}, unknown2, s); - Do({"unknown3"}, unknown3, s); - Do({"unknown4"}, unknown4, s); - Do({"unknown5"}, unknown5, s); - Do({"unknown6"}, unknown6, s); - Do({"damageVulnerabilty"}, damageVulnerabilty, s); - Do({"unknown7"}, unknown7, s); - Do({"damageInfo"}, damageInfo, s); - if (propertyCount == 16) - Do({"unknown8"}, unknown8, s); - else - unknown8 = 0.f; +void Oculus::Enumerate(typename Op::StreamT& s) { + IScriptObject::Enumerate(s); + Do({"name"}, name, s); + Do({"location"}, location, s); + Do({"orientation"}, orientation, s); + Do({"scale"}, scale, s); + Do({"patternedInfo"}, patternedInfo, s); + Do({"actorParameters"}, actorParameters, s); + Do({"unknown1"}, unknown1, s); + Do({"unknown2"}, unknown2, s); + Do({"unknown3"}, unknown3, s); + Do({"unknown4"}, unknown4, s); + Do({"unknown5"}, unknown5, s); + Do({"unknown6"}, unknown6, s); + Do({"damageVulnerabilty"}, damageVulnerabilty, s); + Do({"unknown7"}, unknown7, s); + Do({"damageInfo"}, damageInfo, s); + if (propertyCount == 16) + Do({"unknown8"}, unknown8, s); + else + unknown8 = 0.f; } -const char* Oculus::DNAType() -{ - return "urde::DNAMP1::Oculus"; -} +const char* Oculus::DNAType() { return "urde::DNAMP1::Oculus"; } AT_SPECIALIZE_DNA_YAML(Oculus) -} \ No newline at end of file +} // namespace DataSpec::DNAMP1 \ No newline at end of file diff --git a/DataSpec/DNAMP1/ScriptObjects/Oculus.hpp b/DataSpec/DNAMP1/ScriptObjects/Oculus.hpp index 6f2f671ea..d5c1b64bd 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Oculus.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Oculus.hpp @@ -4,54 +4,44 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Oculus : IScriptObject -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - DamageVulnerability damageVulnerabilty; - Value unknown7; - DamageInfo damageInfo; +namespace DataSpec::DNAMP1 { +struct Oculus : IScriptObject { + AT_DECL_EXPLICIT_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + DamageVulnerability damageVulnerabilty; + Value unknown7; + DamageInfo damageInfo; - /* Trilogy addition */ - Value unknown8; + /* Trilogy addition */ + Value unknown8; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/OmegaPirate.hpp b/DataSpec/DNAMP1/ScriptObjects/OmegaPirate.hpp index 51eda983b..af2597d06 100644 --- a/DataSpec/DNAMP1/ScriptObjects/OmegaPirate.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/OmegaPirate.hpp @@ -4,169 +4,148 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct OmegaPirate : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters1; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - UniqueID32 particle1; - Value soundID1; - ActorParameters actorParameters2; - AnimationParameters animationParameters; - UniqueID32 particle2; - Value soundID2; - UniqueID32 model1; - DamageInfo damageInfo1; - Value unknown9; - UniqueID32 particle3; - UniqueID32 particle4; - UniqueID32 particle5; - UniqueID32 particle6; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; - Value unknown16; - Value soundID3; - Value soundID4; - UniqueID32 particle7; - DamageInfo damageInfo2; - UniqueID32 elsc; - Value soundID5; - Value unknown17; - Value unknown18; - UniqueID32 cmdlPhazonVeins; - UniqueID32 cskrPhazonVeins; - UniqueID32 cinfPhazonVeins; +namespace DataSpec::DNAMP1 { +struct OmegaPirate : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters1; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + UniqueID32 particle1; + Value soundID1; + ActorParameters actorParameters2; + AnimationParameters animationParameters; + UniqueID32 particle2; + Value soundID2; + UniqueID32 model1; + DamageInfo damageInfo1; + Value unknown9; + UniqueID32 particle3; + UniqueID32 particle4; + UniqueID32 particle5; + UniqueID32 particle6; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + Value unknown16; + Value soundID3; + Value soundID4; + UniqueID32 particle7; + DamageInfo damageInfo2; + UniqueID32 elsc; + Value soundID5; + Value unknown17; + Value unknown18; + UniqueID32 cmdlPhazonVeins; + UniqueID32 cskrPhazonVeins; + UniqueID32 cinfPhazonVeins; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters1.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - actorParameters2.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - if (cmdlPhazonVeins && cskrPhazonVeins && cinfPhazonVeins) - { - charAssoc.m_cmdlRigs[cmdlPhazonVeins] = std::make_pair(cskrPhazonVeins, cinfPhazonVeins); - charAssoc.m_cskrCinfToCharacter[cskrPhazonVeins] = std::make_pair( - patternedInfo.animationParameters.animationCharacterSet, "ATTACH.VEINS.CSKR"); - charAssoc.m_cskrCinfToCharacter[cinfPhazonVeins] = std::make_pair( - patternedInfo.animationParameters.animationCharacterSet, - hecl::Format("CINF_%08X.CINF", cinfPhazonVeins.toUint32())); - charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, - cinfPhazonVeins, cmdlPhazonVeins, "VEINS"); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters1.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + actorParameters2.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + if (cmdlPhazonVeins && cskrPhazonVeins && cinfPhazonVeins) { + charAssoc.m_cmdlRigs[cmdlPhazonVeins] = std::make_pair(cskrPhazonVeins, cinfPhazonVeins); + charAssoc.m_cskrCinfToCharacter[cskrPhazonVeins] = + std::make_pair(patternedInfo.animationParameters.animationCharacterSet, "ATTACH.VEINS.CSKR"); + charAssoc.m_cskrCinfToCharacter[cinfPhazonVeins] = + std::make_pair(patternedInfo.animationParameters.animationCharacterSet, + hecl::Format("CINF_%08X.CINF", cinfPhazonVeins.toUint32())); + charAssoc.addAttachmentRig(patternedInfo.animationParameters.animationCharacterSet, cinfPhazonVeins, + cmdlPhazonVeins, "VEINS"); } + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (particle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); - ent->name = name + "_part3"; - } - if (particle4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); - ent->name = name + "_part4"; - } - if (particle5) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); - ent->name = name + "_part5"; - } - if (particle6) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); - ent->name = name + "_part6"; - } - if (particle7) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7); - ent->name = name + "_part7"; - } - if (elsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); - ent->name = name + "_elsc"; - } - if (model1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model1); - ent->name = name + "_model1"; - } - if (cmdlPhazonVeins) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cmdlPhazonVeins); - ent->name = name + "_model2"; - } - if (cskrPhazonVeins) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cskrPhazonVeins); - ent->name = name + "_skin"; - } - if (cinfPhazonVeins) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cinfPhazonVeins); - ent->name = name + "_rig"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters1.nameIDs(pakRouter, name + "_actp1"); - actorParameters2.nameIDs(pakRouter, name + "_actp2"); - animationParameters.nameANCS(pakRouter, name + "_animp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (particle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + ent->name = name + "_part3"; + } + if (particle4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle4); + ent->name = name + "_part4"; + } + if (particle5) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle5); + ent->name = name + "_part5"; + } + if (particle6) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle6); + ent->name = name + "_part6"; + } + if (particle7) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle7); + ent->name = name + "_part7"; + } + if (elsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); + ent->name = name + "_elsc"; + } + if (model1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model1); + ent->name = name + "_model1"; + } + if (cmdlPhazonVeins) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cmdlPhazonVeins); + ent->name = name + "_model2"; + } + if (cskrPhazonVeins) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cskrPhazonVeins); + ent->name = name + "_skin"; + } + if (cinfPhazonVeins) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(cinfPhazonVeins); + ent->name = name + "_rig"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters1.nameIDs(pakRouter, name + "_actp1"); + actorParameters2.nameIDs(pakRouter, name + "_actp2"); + animationParameters.nameANCS(pakRouter, name + "_animp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); - g_curSpec->flattenDependencies(particle4, pathsOut); - g_curSpec->flattenDependencies(particle5, pathsOut); - g_curSpec->flattenDependencies(particle6, pathsOut); - g_curSpec->flattenDependencies(particle7, pathsOut); - g_curSpec->flattenDependencies(elsc, pathsOut); - g_curSpec->flattenDependencies(model1, pathsOut); - g_curSpec->flattenDependencies(cmdlPhazonVeins, pathsOut); - g_curSpec->flattenDependencies(cskrPhazonVeins, pathsOut); - g_curSpec->flattenDependencies(cinfPhazonVeins, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters1.depIDs(pathsOut, lazyOut); - actorParameters2.depIDs(pathsOut, lazyOut); - animationParameters.depANCS(pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(particle4, pathsOut); + g_curSpec->flattenDependencies(particle5, pathsOut); + g_curSpec->flattenDependencies(particle6, pathsOut); + g_curSpec->flattenDependencies(particle7, pathsOut); + g_curSpec->flattenDependencies(elsc, pathsOut); + g_curSpec->flattenDependencies(model1, pathsOut); + g_curSpec->flattenDependencies(cmdlPhazonVeins, pathsOut); + g_curSpec->flattenDependencies(cskrPhazonVeins, pathsOut); + g_curSpec->flattenDependencies(cinfPhazonVeins, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters1.depIDs(pathsOut, lazyOut); + actorParameters2.depIDs(pathsOut, lazyOut); + animationParameters.depANCS(pathsOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters1.scanIDs(scansOut); - actorParameters2.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { + actorParameters1.scanIDs(scansOut); + actorParameters2.scanIDs(scansOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Parameters.cpp b/DataSpec/DNAMP1/ScriptObjects/Parameters.cpp index 909b7f389..6d965046f 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Parameters.cpp +++ b/DataSpec/DNAMP1/ScriptObjects/Parameters.cpp @@ -1,21 +1,19 @@ #include "Parameters.hpp" #include "../ANCS.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -UniqueID32 AnimationParameters::getCINF(PAKRouter& pakRouter) const -{ - if (!animationCharacterSet) - return UniqueID32(); - const nod::Node* node; - const PAK::Entry* ancsEnt = pakRouter.lookupEntry(animationCharacterSet, &node); - ANCS ancs; - { - PAKEntryReadStream rs = ancsEnt->beginReadStream(*node); - ancs.read(rs); - } - return ancs.characterSet.characters.at(character).cinf; +UniqueID32 AnimationParameters::getCINF(PAKRouter& pakRouter) const { + if (!animationCharacterSet) + return UniqueID32(); + const nod::Node* node; + const PAK::Entry* ancsEnt = pakRouter.lookupEntry(animationCharacterSet, &node); + ANCS ancs; + { + PAKEntryReadStream rs = ancsEnt->beginReadStream(*node); + ancs.read(rs); + } + return ancs.characterSet.characters.at(character).cinf; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Parameters.hpp b/DataSpec/DNAMP1/ScriptObjects/Parameters.hpp index 45ab1a8ca..b0002613c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Parameters.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Parameters.hpp @@ -5,530 +5,467 @@ #include "../SAVW.hpp" #include "specter/genie.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -enum class EPickupType : atUint32 -{ - PowerBeam = 0, - IceBeam = 1, - WaveBeam = 2, - PlasmaBeam = 3, - Missile = 4, - ScanVisor = 5, - MorphBallBomb = 6, - PowerBomb = 7, - Flamethrower = 8, - ThermalVisor = 9, - ChargeBeam = 10, - SuperMissile = 11, - GrappleBeam = 12, - XRayVisor = 13, - IceSpreader = 14, - SpaceJump = 15, - MorphBall = 16, - CombatVisor = 17, - BoostBall = 18, - SpiderBall = 19, - PowerSuit = 20, - GravitySuit = 21, - VariaSuit = 22, - PhazonSuit = 23, - EnergyTank = 24, - UnknownItem1 = 25, - HealthRefill = 26, - UnknownItem2 = 27, - WaveBuster = 28, - Truth = 29, - Strength = 30, - Elder = 31, - Wild = 32, - LifeGiver = 33, - Warrior = 34, - Chozo = 35, - Nature = 36, - Sun = 37, - World = 38, - Spirit = 39, - Newborn = 40 +enum class EPickupType : atUint32 { + PowerBeam = 0, + IceBeam = 1, + WaveBeam = 2, + PlasmaBeam = 3, + Missile = 4, + ScanVisor = 5, + MorphBallBomb = 6, + PowerBomb = 7, + Flamethrower = 8, + ThermalVisor = 9, + ChargeBeam = 10, + SuperMissile = 11, + GrappleBeam = 12, + XRayVisor = 13, + IceSpreader = 14, + SpaceJump = 15, + MorphBall = 16, + CombatVisor = 17, + BoostBall = 18, + SpiderBall = 19, + PowerSuit = 20, + GravitySuit = 21, + VariaSuit = 22, + PhazonSuit = 23, + EnergyTank = 24, + UnknownItem1 = 25, + HealthRefill = 26, + UnknownItem2 = 27, + WaveBuster = 28, + Truth = 29, + Strength = 30, + Elder = 31, + Wild = 32, + LifeGiver = 33, + Warrior = 34, + Chozo = 35, + Nature = 36, + Sun = 37, + World = 38, + Spirit = 39, + Newborn = 40 } SPECTER_ENUM("Pickup Type", "", EPickupType); -enum class ESpecialFunctionType : atUint32 -{ - What, - PlayerFollowLocator, - SpinnerController, - ObjectFollowLocator, - Function4, - InventoryActivator, - MapStation, - SaveStation, - IntroBossRingController, - ViewFrustumTest, - ShotSpinnerController, - EscapeSequence, - BossEnergyBar, - EndGame, - HUDFadeIn, - CinematicSkip, - ScriptLayerController, - RainSimulator, - AreaDamage, - ObjectFollowObject, - HintSystem, - DropBomb, - Function22, - MissileStation, - Billboard, - PlayerInAreaRelay, - HUDTarget, - FogFader, - EnterLogbook, - PowerBombStation, - Ending, - FusionRelay, - WeaponSwitch // PAL Only +enum class ESpecialFunctionType : atUint32 { + What, + PlayerFollowLocator, + SpinnerController, + ObjectFollowLocator, + Function4, + InventoryActivator, + MapStation, + SaveStation, + IntroBossRingController, + ViewFrustumTest, + ShotSpinnerController, + EscapeSequence, + BossEnergyBar, + EndGame, + HUDFadeIn, + CinematicSkip, + ScriptLayerController, + RainSimulator, + AreaDamage, + ObjectFollowObject, + HintSystem, + DropBomb, + Function22, + MissileStation, + Billboard, + PlayerInAreaRelay, + HUDTarget, + FogFader, + EnterLogbook, + PowerBombStation, + Ending, + FusionRelay, + WeaponSwitch // PAL Only } SPECTER_ENUM("Special Function", "", EPickupType); -struct AnimationParameters : BigDNA -{ - AT_DECL_DNA_YAML - UniqueID32 animationCharacterSet; - Value character; - Value defaultAnimation; +struct AnimationParameters : BigDNA { + AT_DECL_DNA_YAML + UniqueID32 animationCharacterSet; + Value character; + Value defaultAnimation; - UniqueID32 getCINF(PAKRouter& pakRouter) const; + UniqueID32 getCINF(PAKRouter& pakRouter) const; - void nameANCS(PAKRouter& pakRouter, const std::string& name) const - { - if (!animationCharacterSet) - return; - PAK::Entry* ancsEnt = (PAK::Entry*)pakRouter.lookupEntry(animationCharacterSet); - if (ancsEnt->name.empty()) - ancsEnt->name = name; - } + void nameANCS(PAKRouter& pakRouter, const std::string& name) const { + if (!animationCharacterSet) + return; + PAK::Entry* ancsEnt = (PAK::Entry*)pakRouter.lookupEntry(animationCharacterSet); + if (ancsEnt->name.empty()) + ancsEnt->name = name; + } - void depANCS(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(animationCharacterSet, pathsOut, character); - } + void depANCS(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(animationCharacterSet, pathsOut, character); + } - void depANCSAll(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(animationCharacterSet, pathsOut); - } + void depANCSAll(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(animationCharacterSet, pathsOut); + } }; -struct BehaveChance : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; +struct BehaveChance : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; }; -struct DamageInfo : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Value weaponType; - Value damage; - Value radius; - Value knockbackPower; +struct DamageInfo : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value weaponType; + Value damage; + Value radius; + Value knockbackPower; }; -struct DamageVulnerability : BigDNA -{ +struct DamageVulnerability : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value power; + Value ice; + Value wave; + Value plasma; + Value bomb; + Value powerBomb; + Value missile; + Value boostBall; + Value phazon; + Value enemyWeapon1; + Value enemyWeapon2Poison; + Value enemyWeapon3Lava; + Value enemyWeapon4; + Value unkownWeapon1; + Value unkownWeapon2; + Value deflected; + struct ChargedBeams : BigDNA { AT_DECL_DNA_YAML Value propertyCount; Value power; Value ice; Value wave; Value plasma; - Value bomb; - Value powerBomb; - Value missile; - Value boostBall; - Value phazon; - Value enemyWeapon1; - Value enemyWeapon2Poison; - Value enemyWeapon3Lava; - Value enemyWeapon4; - Value unkownWeapon1; - Value unkownWeapon2; Value deflected; - struct ChargedBeams : BigDNA - { - AT_DECL_DNA_YAML - Value propertyCount; - Value power; - Value ice; - Value wave; - Value plasma; - Value deflected; - } chargedBeams; + } chargedBeams; - struct BeamCombos : BigDNA - { - AT_DECL_DNA_YAML - Value propertyCount; - Value superMissiles; - Value iceSpreader; - Value wavebuster; - Value flameThrower; - Value deflected; - } beamCombos; -}; - -struct FlareDefinition : BigDNA -{ + struct BeamCombos : BigDNA { AT_DECL_DNA_YAML Value propertyCount; - UniqueID32 texture; - Value unknown1; - Value unknown2; - Value unknown4; // CColor + Value superMissiles; + Value iceSpreader; + Value wavebuster; + Value flameThrower; + Value deflected; + } beamCombos; +}; - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - if (texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); - ent->name = name + "_texture"; - } +struct FlareDefinition : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + UniqueID32 texture; + Value unknown1; + Value unknown2; + Value unknown4; // CColor + + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + if (texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); + ent->name = name + "_texture"; } + } - void depIDs(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(texture, pathsOut); - } + void depIDs(std::vector& pathsOut) const { g_curSpec->flattenDependencies(texture, pathsOut); } }; -struct GrappleParameters : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value disableTurning; +struct GrappleParameters : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value disableTurning; }; -struct HealthInfo : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Value health SPECTER_PROPERTY("Health", "Base health for object"); - Value knockbackResistence SPECTER_PROPERTY("Knockback Resistence", ""); +struct HealthInfo : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value health SPECTER_PROPERTY("Health", "Base health for object"); + Value knockbackResistence SPECTER_PROPERTY("Knockback Resistence", ""); } SPECTER_PROPERTY("Health Info", ""); -struct LightParameters : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Value unknown1; - Value unknown2; - Value shadowTesselation; - Value unknown3; - Value unknown4; - Value noLightsAmbient; // CColor - Value makeLights; - Value worldLightingOptions; - Value lightRecalculationOptions; - Value actorPosBias; - Value maxDynamicLights; - Value maxAreaLights; - Value ambientChannelOverflow; - Value layerIndex; +struct LightParameters : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value unknown1; + Value unknown2; + Value shadowTesselation; + Value unknown3; + Value unknown4; + Value noLightsAmbient; // CColor + Value makeLights; + Value worldLightingOptions; + Value lightRecalculationOptions; + Value actorPosBias; + Value maxDynamicLights; + Value maxAreaLights; + Value ambientChannelOverflow; + Value layerIndex; }; -struct PatternedInfo : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Value mass; - Value speed; - Value turnSpeed; - Value detectionRange; - Value detectionHeightRange; - Value dectectionAngle; - Value minAttackRange; - Value maxAttackRange; - Value averageAttackTime; - Value attackTimeVariation; - Value leashRadius; - Value playerLeashRadius; - Value playerLeashTime; - DamageInfo contactDamage; - Value damageWaitTime; - HealthInfo healthInfo; - DamageVulnerability damageVulnerability; - Value halfExtent; - Value height; - Value bodyOrigin; - Value stepUpHeight; - Value xDamage; - Value frozenXDamage; - Value xDamageDelay; - Value deathSfx; - AnimationParameters animationParameters; - Value active; - UniqueID32 stateMachine; - Value intoFreezeDur; - Value outOfFreezeDur; - Value unknown10; - Value particle1Frames; - Value particle1Scale; - UniqueID32 particle1; - UniqueID32 electric; - Value particle2Scale; - UniqueID32 particle2; - Value iceShatterSfx; +struct PatternedInfo : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value mass; + Value speed; + Value turnSpeed; + Value detectionRange; + Value detectionHeightRange; + Value dectectionAngle; + Value minAttackRange; + Value maxAttackRange; + Value averageAttackTime; + Value attackTimeVariation; + Value leashRadius; + Value playerLeashRadius; + Value playerLeashTime; + DamageInfo contactDamage; + Value damageWaitTime; + HealthInfo healthInfo; + DamageVulnerability damageVulnerability; + Value halfExtent; + Value height; + Value bodyOrigin; + Value stepUpHeight; + Value xDamage; + Value frozenXDamage; + Value xDamageDelay; + Value deathSfx; + AnimationParameters animationParameters; + Value active; + UniqueID32 stateMachine; + Value intoFreezeDur; + Value outOfFreezeDur; + Value unknown10; + Value particle1Frames; + Value particle1Scale; + UniqueID32 particle1; + UniqueID32 electric; + Value particle2Scale; + UniqueID32 particle2; + Value iceShatterSfx; - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - animationParameters.nameANCS(pakRouter, name + "_animp"); - if (stateMachine) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(stateMachine); - ent->name = name + "_fsm"; - } - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (electric) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(electric); - ent->name = name + "_elsc"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + animationParameters.nameANCS(pakRouter, name + "_animp"); + if (stateMachine) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(stateMachine); + ent->name = name + "_fsm"; } + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (electric) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(electric); + ent->name = name + "_elsc"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + } - void depIDs(std::vector& pathsOut) const - { - animationParameters.depANCS(pathsOut); - g_curSpec->flattenDependencies(stateMachine, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(electric, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - } + void depIDs(std::vector& pathsOut) const { + animationParameters.depANCS(pathsOut); + g_curSpec->flattenDependencies(stateMachine, pathsOut); + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(electric, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + } }; -struct PlayerHintParameters : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Value unknown1; - Value unknown2; - Value extendTargetDistance; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; +struct PlayerHintParameters : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value unknown1; + Value unknown2; + Value extendTargetDistance; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; }; -struct ScannableParameters : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - UniqueID32 scanId; +struct ScannableParameters : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + UniqueID32 scanId; - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - if (scanId) - { - PAK::Entry* scanEnt = (PAK::Entry*)pakRouter.lookupEntry(scanId); - scanEnt->name = name + "_scan"; - } + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + if (scanId) { + PAK::Entry* scanEnt = (PAK::Entry*)pakRouter.lookupEntry(scanId); + scanEnt->name = name + "_scan"; } + } - void depIDs(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(scanId, pathsOut); - } + void depIDs(std::vector& pathsOut) const { g_curSpec->flattenDependencies(scanId, pathsOut); } - void scanIDs(std::vector& scansOut) const - { - scansOut.emplace_back(scanId); - } + void scanIDs(std::vector& scansOut) const { scansOut.emplace_back(scanId); } }; -struct VisorParameters : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Value unknown1; - Value scanPassthrough; - Value visorMask; +struct VisorParameters : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value unknown1; + Value scanPassthrough; + Value visorMask; }; -struct PlayerParameters : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Vector bools; +struct PlayerParameters : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Vector bools; }; -struct ActorParameters : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - LightParameters lightParameters; - ScannableParameters scannableParameters; - UniqueID32 cmdlXray; - UniqueID32 cskrXray; - UniqueID32 cmdlThermal; - UniqueID32 cskrThermal; - Value globalTimeProvider; - Value fadeInTime; - Value fadeOutTime; - VisorParameters visorParameters; - Value thermalHeat; - Value renderUnsorted; - Value noSortThermal; - Value thermalMag; +struct ActorParameters : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + LightParameters lightParameters; + ScannableParameters scannableParameters; + UniqueID32 cmdlXray; + UniqueID32 cskrXray; + UniqueID32 cmdlThermal; + UniqueID32 cskrThermal; + Value globalTimeProvider; + Value fadeInTime; + Value fadeOutTime; + VisorParameters visorParameters; + Value thermalHeat; + Value renderUnsorted; + Value noSortThermal; + Value thermalMag; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc, - const AnimationParameters& animParms) const - { - auto cinf = animParms.getCINF(pakRouter); - if (cmdlXray && cskrXray) - { - charAssoc.m_cmdlRigs[cmdlXray] = std::make_pair(cskrXray, cinf); - charAssoc.m_cskrCinfToCharacter[cskrXray] = std::make_pair( - animParms.animationCharacterSet, "ATTACH.XRAY.CSKR"); - charAssoc.addAttachmentRig(animParms.animationCharacterSet, {}, cmdlXray, "XRAY"); - } - if (cmdlThermal && cskrThermal) - { - charAssoc.m_cmdlRigs[cmdlThermal] = std::make_pair(cskrThermal, cinf); - charAssoc.m_cskrCinfToCharacter[cskrThermal] = std::make_pair( - animParms.animationCharacterSet, "ATTACH.THERMAL.CSKR"); - charAssoc.addAttachmentRig(animParms.animationCharacterSet, {}, cmdlThermal, "THERMAL"); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc, + const AnimationParameters& animParms) const { + auto cinf = animParms.getCINF(pakRouter); + if (cmdlXray && cskrXray) { + charAssoc.m_cmdlRigs[cmdlXray] = std::make_pair(cskrXray, cinf); + charAssoc.m_cskrCinfToCharacter[cskrXray] = std::make_pair(animParms.animationCharacterSet, "ATTACH.XRAY.CSKR"); + charAssoc.addAttachmentRig(animParms.animationCharacterSet, {}, cmdlXray, "XRAY"); } + if (cmdlThermal && cskrThermal) { + charAssoc.m_cmdlRigs[cmdlThermal] = std::make_pair(cskrThermal, cinf); + charAssoc.m_cskrCinfToCharacter[cskrThermal] = + std::make_pair(animParms.animationCharacterSet, "ATTACH.THERMAL.CSKR"); + charAssoc.addAttachmentRig(animParms.animationCharacterSet, {}, cmdlThermal, "THERMAL"); + } + } - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - scannableParameters.nameIDs(pakRouter, name); - if (cmdlXray) - { - PAK::Entry* xmEnt = (PAK::Entry*)pakRouter.lookupEntry(cmdlXray); - xmEnt->name = name + "_xraymodel"; - } - if (cskrXray) - { - PAK::Entry* xsEnt = (PAK::Entry*)pakRouter.lookupEntry(cskrXray); - xsEnt->name = name + "_xrayskin"; - } - if (cmdlThermal) - { - PAK::Entry* xmEnt = (PAK::Entry*)pakRouter.lookupEntry(cmdlThermal); - xmEnt->name = name + "_thermalmodel"; - } - if (cskrThermal) - { - PAK::Entry* xsEnt = (PAK::Entry*)pakRouter.lookupEntry(cskrThermal); - xsEnt->name = name + "_thermalskin"; - } + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + scannableParameters.nameIDs(pakRouter, name); + if (cmdlXray) { + PAK::Entry* xmEnt = (PAK::Entry*)pakRouter.lookupEntry(cmdlXray); + xmEnt->name = name + "_xraymodel"; } + if (cskrXray) { + PAK::Entry* xsEnt = (PAK::Entry*)pakRouter.lookupEntry(cskrXray); + xsEnt->name = name + "_xrayskin"; + } + if (cmdlThermal) { + PAK::Entry* xmEnt = (PAK::Entry*)pakRouter.lookupEntry(cmdlThermal); + xmEnt->name = name + "_thermalmodel"; + } + if (cskrThermal) { + PAK::Entry* xsEnt = (PAK::Entry*)pakRouter.lookupEntry(cskrThermal); + xsEnt->name = name + "_thermalskin"; + } + } - void depIDs(std::vector& pathsOut, - std::vector& lazyOut) const - { - scannableParameters.depIDs(lazyOut); - g_curSpec->flattenDependencies(cmdlXray, pathsOut); - g_curSpec->flattenDependencies(cskrXray, pathsOut); - g_curSpec->flattenDependencies(cmdlThermal, pathsOut); - g_curSpec->flattenDependencies(cskrThermal, pathsOut); - } + void depIDs(std::vector& pathsOut, std::vector& lazyOut) const { + scannableParameters.depIDs(lazyOut); + g_curSpec->flattenDependencies(cmdlXray, pathsOut); + g_curSpec->flattenDependencies(cskrXray, pathsOut); + g_curSpec->flattenDependencies(cmdlThermal, pathsOut); + g_curSpec->flattenDependencies(cskrThermal, pathsOut); + } - void scanIDs(std::vector& scansOut) const - { - scannableParameters.scanIDs(scansOut); - } + void scanIDs(std::vector& scansOut) const { scannableParameters.scanIDs(scansOut); } }; -struct BeamInfo : BigDNA -{ - AT_DECL_DNA_YAML - Value propertyCount; - Value unknown1; - UniqueID32 particle1; - UniqueID32 particle2; - UniqueID32 texture1; - UniqueID32 texture2; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - DNAColor unknown11; - DNAColor unknown12; +struct BeamInfo : BigDNA { + AT_DECL_DNA_YAML + Value propertyCount; + Value unknown1; + UniqueID32 particle1; + UniqueID32 particle2; + UniqueID32 texture1; + UniqueID32 texture2; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + DNAColor unknown11; + DNAColor unknown12; - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (texture1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); - ent->name = name + "_tex1"; - } - if (texture2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); - ent->name = name + "_tex2"; - } + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (texture1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); + ent->name = name + "_tex1"; + } + if (texture2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); + ent->name = name + "_tex2"; + } + } - void depIDs(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(texture1, pathsOut); - g_curSpec->flattenDependencies(texture2, pathsOut); - } + void depIDs(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(texture1, pathsOut); + g_curSpec->flattenDependencies(texture2, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Parasite.hpp b/DataSpec/DNAMP1/ScriptObjects/Parasite.hpp index 329c8db70..7f36408e9 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Parasite.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Parasite.hpp @@ -4,60 +4,50 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Parasite : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value flavor; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value maxTelegraphReactDist; - Value advanceWpRadius; - Value unknown4; - Value alignAngVel; - Value unknown6; - Value stuckTimeThreshold; - Value collisionCloseMargin; - Value parasiteSearchRadius; - Value parasiteSeparationDist; - Value parasiteSeparationWeight; - Value parasiteAlignmentWeight; - Value parasiteCohesionWeight; - Value destinationSeekWeight; - Value forwardMoveWeight; - Value playerSeparationDist; - Value playerSeparationWeight; - Value playerObstructionMinDist; - Value disableMove; +namespace DataSpec::DNAMP1 { +struct Parasite : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value flavor; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value maxTelegraphReactDist; + Value advanceWpRadius; + Value unknown4; + Value alignAngVel; + Value unknown6; + Value stuckTimeThreshold; + Value collisionCloseMargin; + Value parasiteSearchRadius; + Value parasiteSeparationDist; + Value parasiteSeparationWeight; + Value parasiteAlignmentWeight; + Value parasiteCohesionWeight; + Value destinationSeekWeight; + Value forwardMoveWeight; + Value playerSeparationDist; + Value playerSeparationWeight; + Value playerObstructionMinDist; + Value disableMove; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PathCamera.hpp b/DataSpec/DNAMP1/ScriptObjects/PathCamera.hpp index 9426cea0c..9437f8d54 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PathCamera.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PathCamera.hpp @@ -4,34 +4,30 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PathCamera : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value active; - struct CameraParameters : BigDNA - { - AT_DECL_DNA - Value propertyCount; - Value closedLoop; - Value noFilter; - Value tangentOrientation; - Value easeDist; - Value useHintLookZ; - Value clampToClosedDoor; - } cameraParameters; +namespace DataSpec::DNAMP1 { +struct PathCamera : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value active; + struct CameraParameters : BigDNA { + AT_DECL_DNA + Value propertyCount; + Value closedLoop; + Value noFilter; + Value tangentOrientation; + Value easeDist; + Value useHintLookZ; + Value clampToClosedDoor; + } cameraParameters; - Value lengthExtent; - Value filterMag; - Value filterProportion; - Value initPos; - Value minEaseDist; - Value maxEaseDist; + Value lengthExtent; + Value filterMag; + Value filterProportion; + Value initPos; + Value minEaseDist; + Value maxEaseDist; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PhazonHealingNodule.hpp b/DataSpec/DNAMP1/ScriptObjects/PhazonHealingNodule.hpp index 7b449fa31..1ffc6d226 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PhazonHealingNodule.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PhazonHealingNodule.hpp @@ -4,50 +4,39 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PhazonHealingNodule : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - UniqueID32 elsc; - String<-1> unknown2; +namespace DataSpec::DNAMP1 { +struct PhazonHealingNodule : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + UniqueID32 elsc; + String<-1> unknown2; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (elsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); - ent->name = name + "_elsc"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (elsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); + ent->name = name + "_elsc"; } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(elsc, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(elsc, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PhazonPool.hpp b/DataSpec/DNAMP1/ScriptObjects/PhazonPool.hpp index 4f3b2a9f6..9bbf642e4 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PhazonPool.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PhazonPool.hpp @@ -4,63 +4,53 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PhazonPool : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - Value unknown1; - UniqueID32 model1; - UniqueID32 model2; - UniqueID32 particle1; - UniqueID32 particle2; - Value unknown2; - DamageInfo damageInfo; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; +namespace DataSpec::DNAMP1 { +struct PhazonPool : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + Value unknown1; + UniqueID32 model1; + UniqueID32 model2; + UniqueID32 particle1; + UniqueID32 particle2; + Value unknown2; + DamageInfo damageInfo; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; - void nameIDs(PAKRouter& pakRouter) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (model1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model1); - ent->name = name + "_model1"; - } - if (model2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model2); - ent->name = name + "_model2"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (model1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model1); + ent->name = name + "_model1"; + } + if (model2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model2); + ent->name = name + "_model2"; + } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(model1, pathsOut); - g_curSpec->flattenDependencies(model2, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(model1, pathsOut); + g_curSpec->flattenDependencies(model2, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Pickup.hpp b/DataSpec/DNAMP1/ScriptObjects/Pickup.hpp index 93b9154c2..0e0beb5b8 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Pickup.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Pickup.hpp @@ -4,65 +4,53 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Pickup : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - Value hitboxVolume; - Value scanPosition; - Value pickupType; - Value capacity; - Value amount; - Value dropRate; - Value lifetime; - Value spawnDelay; - UniqueID32 model; - AnimationParameters animationParameters; - ActorParameters actorParameters; - Value active; - Value unknown1; - UniqueID32 particle; +namespace DataSpec::DNAMP1 { +struct Pickup : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + Value hitboxVolume; + Value scanPosition; + Value pickupType; + Value capacity; + Value amount; + Value dropRate; + Value lifetime; + Value spawnDelay; + UniqueID32 model; + AnimationParameters animationParameters; + ActorParameters actorParameters; + Value active; + Value unknown1; + UniqueID32 particle; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; } + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; + } + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle, pathsOut); - g_curSpec->flattenDependencies(model, pathsOut); - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle, pathsOut); + g_curSpec->flattenDependencies(model, pathsOut); + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PickupGenerator.hpp b/DataSpec/DNAMP1/ScriptObjects/PickupGenerator.hpp index f9c5ed10f..5b677d03a 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PickupGenerator.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PickupGenerator.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PickupGenerator : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value offset; - Value active; - Value frequency; +namespace DataSpec::DNAMP1 { +struct PickupGenerator : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value offset; + Value active; + Value frequency; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Platform.cpp b/DataSpec/DNAMP1/ScriptObjects/Platform.cpp index ddf36bef2..33ffaf901 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Platform.cpp +++ b/DataSpec/DNAMP1/ScriptObjects/Platform.cpp @@ -1,37 +1,31 @@ #include "Platform.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -zeus::CAABox Platform::getVISIAABB(hecl::blender::Token& btok) const -{ - hecl::blender::Connection& conn = btok.getBlenderConnection(); - zeus::CAABox aabbOut; +zeus::CAABox Platform::getVISIAABB(hecl::blender::Token& btok) const { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + zeus::CAABox aabbOut; - if (model) - { - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(model); - conn.openBlend(path); - hecl::blender::DataStream ds = conn.beginData(); - auto aabb = ds.getMeshAABB(); - aabbOut = zeus::CAABox(aabb.first, aabb.second); - } - else if (animationParameters.animationCharacterSet) - { - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath( - animationParameters.animationCharacterSet); - conn.openBlend(path.getWithExtension(_SYS_STR(".blend"), true)); - hecl::blender::DataStream ds = conn.beginData(); - auto aabb = ds.getMeshAABB(); - aabbOut = zeus::CAABox(aabb.first, aabb.second); - } + if (model) { + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(model); + conn.openBlend(path); + hecl::blender::DataStream ds = conn.beginData(); + auto aabb = ds.getMeshAABB(); + aabbOut = zeus::CAABox(aabb.first, aabb.second); + } else if (animationParameters.animationCharacterSet) { + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(animationParameters.animationCharacterSet); + conn.openBlend(path.getWithExtension(_SYS_STR(".blend"), true)); + hecl::blender::DataStream ds = conn.beginData(); + auto aabb = ds.getMeshAABB(); + aabbOut = zeus::CAABox(aabb.first, aabb.second); + } - if (aabbOut.min.x() > aabbOut.max.x()) - return {}; + if (aabbOut.min.x() > aabbOut.max.x()) + return {}; - zeus::CTransform xf = ConvertEditorEulerToTransform4f(scale, orientation, location); - return aabbOut.getTransformedAABox(xf); + zeus::CTransform xf = ConvertEditorEulerToTransform4f(scale, orientation, location); + return aabbOut.getTransformedAABox(xf); } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Platform.hpp b/DataSpec/DNAMP1/ScriptObjects/Platform.hpp index 27eb3f1d2..ace3b13f0 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Platform.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Platform.hpp @@ -4,68 +4,56 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Platform : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - Value extent; - Value collisionCenter; - UniqueID32 model; - AnimationParameters animationParameters; - ActorParameters actorParameters; - Value speed; - Value active; - UniqueID32 dcln; - HealthInfo healthInfo; - DamageVulnerability damageVulnerabilty; - Value detectCollision; - Value xrayAlpha; - Value rainSplashes; - Value maxRainSplashes; - Value rainGenRate; +namespace DataSpec::DNAMP1 { +struct Platform : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + Value extent; + Value collisionCenter; + UniqueID32 model; + AnimationParameters animationParameters; + ActorParameters actorParameters; + Value speed; + Value active; + UniqueID32 dcln; + HealthInfo healthInfo; + DamageVulnerability damageVulnerabilty; + Value detectCollision; + Value xrayAlpha; + Value rainSplashes; + Value maxRainSplashes; + Value rainGenRate; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } + + void nameIDs(PAKRouter& pakRouter) const { + if (dcln) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(dcln); + ent->name = name + "_dcln"; } - - void nameIDs(PAKRouter& pakRouter) const - { - if (dcln) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(dcln); - ent->name = name + "_dcln"; - } - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; } + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(dcln, pathsOut); - g_curSpec->flattenDependencies(model, pathsOut); - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(dcln, pathsOut); + g_curSpec->flattenDependencies(model, pathsOut); + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } - zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const; + zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PlayerActor.hpp b/DataSpec/DNAMP1/ScriptObjects/PlayerActor.hpp index 8e6b20688..efbdf5016 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PlayerActor.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PlayerActor.hpp @@ -4,61 +4,50 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PlayerActor : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - Value boxExtents; - Value boxOffset; - Value mass; - Value zMomentum; - HealthInfo healthInfo; - DamageVulnerability damageVulnerability; - UniqueID32 model; - AnimationParameters animationParameters; - ActorParameters actorParameters; - Value loop; - Value snow; - Value solid; - Value active; - PlayerParameters playerParameters; - Value beamId; +namespace DataSpec::DNAMP1 { +struct PlayerActor : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + Value boxExtents; + Value boxOffset; + Value mass; + Value zMomentum; + HealthInfo healthInfo; + DamageVulnerability damageVulnerability; + UniqueID32 model; + AnimationParameters animationParameters; + ActorParameters actorParameters; + Value loop; + Value snow; + Value solid; + Value active; + PlayerParameters playerParameters; + Value beamId; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; } + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(model, pathsOut); - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - animationParameters.depANCSAll(lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(model, pathsOut); + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + animationParameters.depANCSAll(lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PlayerHint.hpp b/DataSpec/DNAMP1/ScriptObjects/PlayerHint.hpp index f1009a685..7419085bc 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PlayerHint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PlayerHint.hpp @@ -4,18 +4,15 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PlayerHint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value unknown1; - PlayerHintParameters playerHintParameters; - Value unknown2; +namespace DataSpec::DNAMP1 { +struct PlayerHint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value unknown1; + PlayerHintParameters playerHintParameters; + Value unknown2; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PlayerStateChange.hpp b/DataSpec/DNAMP1/ScriptObjects/PlayerStateChange.hpp index 348e9a3d3..08de833a3 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PlayerStateChange.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PlayerStateChange.hpp @@ -4,19 +4,16 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PlayerStateChange : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown; - Value item; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; +namespace DataSpec::DNAMP1 { +struct PlayerStateChange : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown; + Value item; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PointOfInterest.hpp b/DataSpec/DNAMP1/ScriptObjects/PointOfInterest.hpp index 719d87d3d..a4aa30002 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PointOfInterest.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PointOfInterest.hpp @@ -4,34 +4,23 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PointOfInterest : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value unknown1; - ScannableParameters scannableParameters; - Value unknown2; +namespace DataSpec::DNAMP1 { +struct PointOfInterest : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value unknown1; + ScannableParameters scannableParameters; + Value unknown2; - void nameIDs(PAKRouter& pakRouter) const - { - scannableParameters.nameIDs(pakRouter, name + "_scanp"); - } + void nameIDs(PAKRouter& pakRouter) const { scannableParameters.nameIDs(pakRouter, name + "_scanp"); } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - scannableParameters.depIDs(lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + scannableParameters.depIDs(lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - scannableParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { scannableParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PuddleSpore.hpp b/DataSpec/DNAMP1/ScriptObjects/PuddleSpore.hpp index a5be016b3..5fe0e8cfb 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PuddleSpore.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PuddleSpore.hpp @@ -4,63 +4,51 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PuddleSpore : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown2; - UniqueID32 particle; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - UniqueID32 wpsc; - DamageInfo damageInfo; +namespace DataSpec::DNAMP1 { +struct PuddleSpore : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown2; + UniqueID32 particle; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + UniqueID32 wpsc; + DamageInfo damageInfo; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - if (wpsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); - ent->name = name + "_wpsc"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; } + if (wpsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); + ent->name = name + "_wpsc"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle, pathsOut); - g_curSpec->flattenDependencies(wpsc, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle, pathsOut); + g_curSpec->flattenDependencies(wpsc, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/PuddleToadGamma.hpp b/DataSpec/DNAMP1/ScriptObjects/PuddleToadGamma.hpp index 1a88c0683..3ffe36a19 100644 --- a/DataSpec/DNAMP1/ScriptObjects/PuddleToadGamma.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/PuddleToadGamma.hpp @@ -4,58 +4,47 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct PuddleToadGamma : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - DamageInfo damageInfo1; - DamageInfo damageInfo2; - UniqueID32 dcln; +namespace DataSpec::DNAMP1 { +struct PuddleToadGamma : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + DamageInfo damageInfo1; + DamageInfo damageInfo2; + UniqueID32 dcln; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (dcln) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(dcln); - ent->name = name + "_dcln"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (dcln) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(dcln); + ent->name = name + "_dcln"; } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(dcln, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(dcln, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Puffer.hpp b/DataSpec/DNAMP1/ScriptObjects/Puffer.hpp index eb8b6a06c..782e3a2f1 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Puffer.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Puffer.hpp @@ -4,63 +4,51 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Puffer : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - UniqueID32 particle; - DamageInfo damageInfo1; - UniqueID32 texture; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - DamageInfo damageInfo2; - Value unknown6; +namespace DataSpec::DNAMP1 { +struct Puffer : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + UniqueID32 particle; + DamageInfo damageInfo1; + UniqueID32 texture; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + DamageInfo damageInfo2; + Value unknown6; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - if (texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); - ent->name = name + "_texture"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; } + if (texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); + ent->name = name + "_texture"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle, pathsOut); - g_curSpec->flattenDependencies(texture, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle, pathsOut); + g_curSpec->flattenDependencies(texture, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/RadialDamage.hpp b/DataSpec/DNAMP1/ScriptObjects/RadialDamage.hpp index d832f146a..9eb595969 100644 --- a/DataSpec/DNAMP1/ScriptObjects/RadialDamage.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/RadialDamage.hpp @@ -4,17 +4,14 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct RadialDamage : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value active; - DamageInfo damageInfo; - Value radius; +namespace DataSpec::DNAMP1 { +struct RadialDamage : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value active; + DamageInfo damageInfo; + Value radius; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/RandomRelay.hpp b/DataSpec/DNAMP1/ScriptObjects/RandomRelay.hpp index 50aa00123..f43182497 100644 --- a/DataSpec/DNAMP1/ScriptObjects/RandomRelay.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/RandomRelay.hpp @@ -4,17 +4,14 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct RandomRelay : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; +namespace DataSpec::DNAMP1 { +struct RandomRelay : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Relay.hpp b/DataSpec/DNAMP1/ScriptObjects/Relay.hpp index 4bc80de62..483bc84b6 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Relay.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Relay.hpp @@ -4,14 +4,11 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Relay : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; +namespace DataSpec::DNAMP1 { +struct Relay : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Repulsor.hpp b/DataSpec/DNAMP1/ScriptObjects/Repulsor.hpp index fb0c50215..920be7f52 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Repulsor.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Repulsor.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Repulsor : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value active; - Value unknown; +namespace DataSpec::DNAMP1 { +struct Repulsor : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value active; + Value unknown; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Ridley.cpp b/DataSpec/DNAMP1/ScriptObjects/Ridley.cpp index d8cf1909d..b34254990 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Ridley.cpp +++ b/DataSpec/DNAMP1/ScriptObjects/Ridley.cpp @@ -1,74 +1,68 @@ #include "Ridley.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template -void Ridley::Enumerate(typename Op::StreamT& s) -{ - IScriptObject::Enumerate(s); - Do({"name"}, name, s); - Do({"location"}, location, s); - Do({"orientation"}, orientation, s); - Do({"scale"}, scale, s); - Do({"patternedInfo"}, patternedInfo, s); - Do({"actorParameters"}, actorParameters, s); - Do({"model1"}, model1, s); - Do({"model2"}, model2, s); - if (propertyCount == 48) - { - Do({"model3"}, model3, s); - Do({"model4"}, model4, s); - Do({"model5"}, model5, s); - Do({"model6"}, model6, s); - Do({"model7"}, model7, s); - Do({"model8"}, model8, s); - Do({"model9"}, model9, s); - Do({"model10"}, model10, s); - Do({"model11"}, model11, s); - Do({"model12"}, model12, s); - } - Do({"particle"}, particle, s); - Do({"unknown1"}, unknown1, s); - Do({"unknown2"}, unknown2, s); - Do({"unknown3"}, unknown3, s); - Do({"unknown4"}, unknown4, s); - Do({"wpsc1"}, wpsc1, s); - Do({"damageInfo1"}, damageInfo1, s); - Do({"ridleyStruct1"}, ridleyStruct1, s); - Do({"soundID1"}, soundID1, s); - Do({"wpsc2"}, wpsc2, s); - if (propertyCount == 40) - Do({"wpsc3"}, wpsc3, s); - Do({"damageInfo2"}, damageInfo2, s); - Do({"ridleyStruct2_1"}, ridleyStruct2_1, s); - Do({"wpsc4"}, wpsc4, s); - Do({"damageInfo3"}, damageInfo3, s); - Do({"ridleyStruct2_2"}, ridleyStruct2_2, s); - Do({"soundID2"}, soundID2, s); - Do({"damageInfo4"}, damageInfo4, s); - Do({"ridleyStruct2_3"}, ridleyStruct2_3, s); - Do({"unknown5"}, unknown5, s); - Do({"unknown6"}, unknown6, s); - Do({"damageInfo5"}, damageInfo5, s); - Do({"unknown7"}, unknown7, s); - Do({"damageInfo6"}, damageInfo6, s); - Do({"unknown8"}, unknown8, s); - Do({"damageInfo7"}, damageInfo7, s); - Do({"unknown9"}, unknown9, s); - Do({"elsc"}, elsc, s); - Do({"unknown10"}, unknown10, s); - Do({"soundID3"}, soundID3, s); - Do({"damageInfo8"}, damageInfo8, s); - if (propertyCount == 40) - Do({"damageInfo9"}, damageInfo9, s); +void Ridley::Enumerate(typename Op::StreamT& s) { + IScriptObject::Enumerate(s); + Do({"name"}, name, s); + Do({"location"}, location, s); + Do({"orientation"}, orientation, s); + Do({"scale"}, scale, s); + Do({"patternedInfo"}, patternedInfo, s); + Do({"actorParameters"}, actorParameters, s); + Do({"model1"}, model1, s); + Do({"model2"}, model2, s); + if (propertyCount == 48) { + Do({"model3"}, model3, s); + Do({"model4"}, model4, s); + Do({"model5"}, model5, s); + Do({"model6"}, model6, s); + Do({"model7"}, model7, s); + Do({"model8"}, model8, s); + Do({"model9"}, model9, s); + Do({"model10"}, model10, s); + Do({"model11"}, model11, s); + Do({"model12"}, model12, s); + } + Do({"particle"}, particle, s); + Do({"unknown1"}, unknown1, s); + Do({"unknown2"}, unknown2, s); + Do({"unknown3"}, unknown3, s); + Do({"unknown4"}, unknown4, s); + Do({"wpsc1"}, wpsc1, s); + Do({"damageInfo1"}, damageInfo1, s); + Do({"ridleyStruct1"}, ridleyStruct1, s); + Do({"soundID1"}, soundID1, s); + Do({"wpsc2"}, wpsc2, s); + if (propertyCount == 40) + Do({"wpsc3"}, wpsc3, s); + Do({"damageInfo2"}, damageInfo2, s); + Do({"ridleyStruct2_1"}, ridleyStruct2_1, s); + Do({"wpsc4"}, wpsc4, s); + Do({"damageInfo3"}, damageInfo3, s); + Do({"ridleyStruct2_2"}, ridleyStruct2_2, s); + Do({"soundID2"}, soundID2, s); + Do({"damageInfo4"}, damageInfo4, s); + Do({"ridleyStruct2_3"}, ridleyStruct2_3, s); + Do({"unknown5"}, unknown5, s); + Do({"unknown6"}, unknown6, s); + Do({"damageInfo5"}, damageInfo5, s); + Do({"unknown7"}, unknown7, s); + Do({"damageInfo6"}, damageInfo6, s); + Do({"unknown8"}, unknown8, s); + Do({"damageInfo7"}, damageInfo7, s); + Do({"unknown9"}, unknown9, s); + Do({"elsc"}, elsc, s); + Do({"unknown10"}, unknown10, s); + Do({"soundID3"}, soundID3, s); + Do({"damageInfo8"}, damageInfo8, s); + if (propertyCount == 40) + Do({"damageInfo9"}, damageInfo9, s); } -const char* Ridley::DNAType() -{ - return "urde::DNAMP1::Ridley"; -} +const char* Ridley::DNAType() { return "urde::DNAMP1::Ridley"; } AT_SPECIALIZE_DNA_YAML(Ridley) -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Ridley.hpp b/DataSpec/DNAMP1/ScriptObjects/Ridley.hpp index ac9466a2e..9b5c8496b 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Ridley.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Ridley.hpp @@ -4,264 +4,228 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Ridley : IScriptObject -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - UniqueID32 model1; - UniqueID32 model2; - UniqueID32 model3; - UniqueID32 model4; - UniqueID32 model5; - UniqueID32 model6; - UniqueID32 model7; - UniqueID32 model8; - UniqueID32 model9; - UniqueID32 model10; - UniqueID32 model11; - UniqueID32 model12; - UniqueID32 particle; - Value unknown1; +namespace DataSpec::DNAMP1 { +struct Ridley : IScriptObject { + AT_DECL_EXPLICIT_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + UniqueID32 model1; + UniqueID32 model2; + UniqueID32 model3; + UniqueID32 model4; + UniqueID32 model5; + UniqueID32 model6; + UniqueID32 model7; + UniqueID32 model8; + UniqueID32 model9; + UniqueID32 model10; + UniqueID32 model11; + UniqueID32 model12; + UniqueID32 particle; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + UniqueID32 wpsc1; + DamageInfo damageInfo1; + struct RidleyStruct1 : BigDNA { + AT_DECL_DNA_YAML + Value unknown1; + Value unknown2; + UniqueID32 particle1; + UniqueID32 particle2; + UniqueID32 texture1; + UniqueID32 texture2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; // CColor + Value unknown13; // CColor + + void nameIDs(PAKRouter& pakRouter, const std::string& name) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; + } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + if (texture1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); + ent->name = name + "_tex1"; + } + if (texture2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); + ent->name = name + "_tex2"; + } + } + + void depIDs(std::vector& pathsOut) const { + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + g_curSpec->flattenDependencies(texture1, pathsOut); + g_curSpec->flattenDependencies(texture2, pathsOut); + } + } ridleyStruct1; + + Value soundID1; + UniqueID32 wpsc2; + UniqueID32 wpsc3; + DamageInfo damageInfo2; + + struct RidleyStruct2 : BigDNA { + AT_DECL_DNA_YAML + Value unknown1; Value unknown2; Value unknown3; Value unknown4; - UniqueID32 wpsc1; - DamageInfo damageInfo1; - struct RidleyStruct1 : BigDNA - { - AT_DECL_DNA_YAML - Value unknown1; - Value unknown2; - UniqueID32 particle1; - UniqueID32 particle2; - UniqueID32 texture1; - UniqueID32 texture2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; //CColor - Value unknown13; //CColor - - void nameIDs(PAKRouter& pakRouter, const std::string& name) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - if (texture1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); - ent->name = name + "_tex1"; - } - if (texture2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); - ent->name = name + "_tex2"; - } - } - - void depIDs(std::vector& pathsOut) const - { - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(texture1, pathsOut); - g_curSpec->flattenDependencies(texture2, pathsOut); - } - } ridleyStruct1; - - Value soundID1; - UniqueID32 wpsc2; - UniqueID32 wpsc3; - DamageInfo damageInfo2; - - struct RidleyStruct2 : BigDNA - { - AT_DECL_DNA_YAML - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - } ridleyStruct2_1; - - UniqueID32 wpsc4; - DamageInfo damageInfo3; - RidleyStruct2 ridleyStruct2_2; - Value soundID2; - DamageInfo damageInfo4; - RidleyStruct2 ridleyStruct2_3; Value unknown5; Value unknown6; - DamageInfo damageInfo5; Value unknown7; - DamageInfo damageInfo6; Value unknown8; - DamageInfo damageInfo7; - Value unknown9; - UniqueID32 elsc; - Value unknown10; - Value soundID3; - DamageInfo damageInfo8; + Value unknown9; + } ridleyStruct2_1; - /* Trilogy addition */ - DamageInfo damageInfo9; + UniqueID32 wpsc4; + DamageInfo damageInfo3; + RidleyStruct2 ridleyStruct2_2; + Value soundID2; + DamageInfo damageInfo4; + RidleyStruct2 ridleyStruct2_3; + Value unknown5; + Value unknown6; + DamageInfo damageInfo5; + Value unknown7; + DamageInfo damageInfo6; + Value unknown8; + DamageInfo damageInfo7; + Value unknown9; + UniqueID32 elsc; + Value unknown10; + Value soundID3; + DamageInfo damageInfo8; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + /* Trilogy addition */ + DamageInfo damageInfo9; + + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } + + void nameIDs(PAKRouter& pakRouter) const { + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; } - - void nameIDs(PAKRouter& pakRouter) const - { - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - if (model1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model1); - ent->name = name + "_model1"; - } - if (model2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model2); - ent->name = name + "_model2"; - } - if (model3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model3); - ent->name = name + "_model3"; - } - if (model4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model4); - ent->name = name + "_model4"; - } - if (model5) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model5); - ent->name = name + "_model5"; - } - if (model6) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model6); - ent->name = name + "_model6"; - } - if (model7) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model7); - ent->name = name + "_model7"; - } - if (model8) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model8); - ent->name = name + "_model8"; - } - if (model9) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model9); - ent->name = name + "_model9"; - } - if (model10) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model10); - ent->name = name + "_model10"; - } - if (model11) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model11); - ent->name = name + "_model11"; - } - if (model12) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model12); - ent->name = name + "_model12"; - } - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc1"; - } - if (wpsc2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); - ent->name = name + "_wpsc2"; - } - if (wpsc3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc3); - ent->name = name + "_wpsc3"; - } - if (wpsc4) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc4); - ent->name = name + "_wpsc4"; - } - if (elsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); - ent->name = name + "_elsc"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - ridleyStruct1.nameIDs(pakRouter, name + "_ridley1"); + if (model1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model1); + ent->name = name + "_model1"; } - - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle, pathsOut); - g_curSpec->flattenDependencies(model1, pathsOut); - g_curSpec->flattenDependencies(model2, pathsOut); - g_curSpec->flattenDependencies(model3, pathsOut); - g_curSpec->flattenDependencies(model4, pathsOut); - g_curSpec->flattenDependencies(model5, pathsOut); - g_curSpec->flattenDependencies(model6, pathsOut); - g_curSpec->flattenDependencies(model7, pathsOut); - g_curSpec->flattenDependencies(model8, pathsOut); - g_curSpec->flattenDependencies(model9, pathsOut); - g_curSpec->flattenDependencies(model10, pathsOut); - g_curSpec->flattenDependencies(model11, pathsOut); - g_curSpec->flattenDependencies(model12, pathsOut); - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(wpsc2, pathsOut); - g_curSpec->flattenDependencies(wpsc3, pathsOut); - g_curSpec->flattenDependencies(wpsc4, pathsOut); - g_curSpec->flattenDependencies(elsc, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - ridleyStruct1.depIDs(pathsOut); + if (model2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model2); + ent->name = name + "_model2"; } - - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); + if (model3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model3); + ent->name = name + "_model3"; } + if (model4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model4); + ent->name = name + "_model4"; + } + if (model5) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model5); + ent->name = name + "_model5"; + } + if (model6) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model6); + ent->name = name + "_model6"; + } + if (model7) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model7); + ent->name = name + "_model7"; + } + if (model8) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model8); + ent->name = name + "_model8"; + } + if (model9) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model9); + ent->name = name + "_model9"; + } + if (model10) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model10); + ent->name = name + "_model10"; + } + if (model11) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model11); + ent->name = name + "_model11"; + } + if (model12) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model12); + ent->name = name + "_model12"; + } + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc1"; + } + if (wpsc2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); + ent->name = name + "_wpsc2"; + } + if (wpsc3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc3); + ent->name = name + "_wpsc3"; + } + if (wpsc4) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc4); + ent->name = name + "_wpsc4"; + } + if (elsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(elsc); + ent->name = name + "_elsc"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + ridleyStruct1.nameIDs(pakRouter, name + "_ridley1"); + } + + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle, pathsOut); + g_curSpec->flattenDependencies(model1, pathsOut); + g_curSpec->flattenDependencies(model2, pathsOut); + g_curSpec->flattenDependencies(model3, pathsOut); + g_curSpec->flattenDependencies(model4, pathsOut); + g_curSpec->flattenDependencies(model5, pathsOut); + g_curSpec->flattenDependencies(model6, pathsOut); + g_curSpec->flattenDependencies(model7, pathsOut); + g_curSpec->flattenDependencies(model8, pathsOut); + g_curSpec->flattenDependencies(model9, pathsOut); + g_curSpec->flattenDependencies(model10, pathsOut); + g_curSpec->flattenDependencies(model11, pathsOut); + g_curSpec->flattenDependencies(model12, pathsOut); + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(wpsc2, pathsOut); + g_curSpec->flattenDependencies(wpsc3, pathsOut); + g_curSpec->flattenDependencies(wpsc4, pathsOut); + g_curSpec->flattenDependencies(elsc, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + ridleyStruct1.depIDs(pathsOut); + } + + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Ripper.hpp b/DataSpec/DNAMP1/ScriptObjects/Ripper.hpp index 504952952..78102625c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Ripper.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Ripper.hpp @@ -4,43 +4,33 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Ripper : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - GrappleParameters grappleParameters; +namespace DataSpec::DNAMP1 { +struct Ripper : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + GrappleParameters grappleParameters; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Ripple.hpp b/DataSpec/DNAMP1/ScriptObjects/Ripple.hpp index 236d722da..13304c91f 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Ripple.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Ripple.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Ripple : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value unknown1; - Value unknown2; +namespace DataSpec::DNAMP1 { +struct Ripple : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value unknown1; + Value unknown2; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/RoomAcoustics.hpp b/DataSpec/DNAMP1/ScriptObjects/RoomAcoustics.hpp index ef9454020..ae8c93856 100644 --- a/DataSpec/DNAMP1/ScriptObjects/RoomAcoustics.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/RoomAcoustics.hpp @@ -4,38 +4,35 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct RoomAcoustics : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; - Value volumeScale; - Value reverbHiEnable; - Value reverbHiTmpDisable; - Value reverbHiColoration; - Value reverbHiMix; - Value reverbHiTime; - Value reverbHiDamping; - Value reverbHiPreDelay; - Value reverbHiCrosstalk; - Value chorusEnable; - Value baseDelay; - Value variation; - Value period; - Value reverbStdEnable; - Value reverbStdTmpDisable; - Value reverbStdColoration; - Value reverbStdMix; - Value reverbStdTime; - Value reverbStdDamping; - Value reverbStdPreDelay; - Value delayEnable; - Value delay[3]; - Value feedback[3]; - Value output[3]; +namespace DataSpec::DNAMP1 { +struct RoomAcoustics : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; + Value volumeScale; + Value reverbHiEnable; + Value reverbHiTmpDisable; + Value reverbHiColoration; + Value reverbHiMix; + Value reverbHiTime; + Value reverbHiDamping; + Value reverbHiPreDelay; + Value reverbHiCrosstalk; + Value chorusEnable; + Value baseDelay; + Value variation; + Value period; + Value reverbStdEnable; + Value reverbStdTmpDisable; + Value reverbStdColoration; + Value reverbStdMix; + Value reverbStdTime; + Value reverbStdDamping; + Value reverbStdPreDelay; + Value delayEnable; + Value delay[3]; + Value feedback[3]; + Value output[3]; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/RumbleEffect.hpp b/DataSpec/DNAMP1/ScriptObjects/RumbleEffect.hpp index d3ed8722c..7697b6d6d 100644 --- a/DataSpec/DNAMP1/ScriptObjects/RumbleEffect.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/RumbleEffect.hpp @@ -4,24 +4,20 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct RumbleEffect : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; +namespace DataSpec::DNAMP1 { +struct RumbleEffect : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value unknown1; + Value unknown2; + Value unknown3; + struct RumbleEffectParameters : BigDNA { + AT_DECL_DNA + Value propertyCount; Value unknown1; - Value unknown2; - Value unknown3; - struct RumbleEffectParameters : BigDNA - { - AT_DECL_DNA - Value propertyCount; - Value unknown1; - Value unknown2; - } rumbleParameters; + Value unknown2; + } rumbleParameters; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ScriptBeam.hpp b/DataSpec/DNAMP1/ScriptObjects/ScriptBeam.hpp index c891b58cf..85b4dee6b 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ScriptBeam.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ScriptBeam.hpp @@ -4,36 +4,29 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ScriptBeam : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value unknown1; - UniqueID32 wpsc; - BeamInfo beamInfo; - DamageInfo damageInfo; +namespace DataSpec::DNAMP1 { +struct ScriptBeam : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value unknown1; + UniqueID32 wpsc; + BeamInfo beamInfo; + DamageInfo damageInfo; - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); - ent->name = name + "_wpsc"; - } - beamInfo.nameIDs(pakRouter, name + "_beamInfo"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc); + ent->name = name + "_wpsc"; } + beamInfo.nameIDs(pakRouter, name + "_beamInfo"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc, pathsOut); - beamInfo.depIDs(pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc, pathsOut); + beamInfo.depIDs(pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ScriptTypes.hpp b/DataSpec/DNAMP1/ScriptObjects/ScriptTypes.hpp index d4a2acce6..e77cca59f 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ScriptTypes.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ScriptTypes.hpp @@ -128,13 +128,11 @@ #include #include -namespace DataSpec::DNAMP1 -{ -struct ScriptObjectSpec -{ - atUint8 type; - std::function a; +namespace DataSpec::DNAMP1 { +struct ScriptObjectSpec { + atUint8 type; + std::function a; }; extern const std::vector SCRIPT_OBJECT_DB; -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Seedling.hpp b/DataSpec/DNAMP1/ScriptObjects/Seedling.hpp index 00d3167b9..3fd4a5263 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Seedling.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Seedling.hpp @@ -4,61 +4,49 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Seedling : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - UniqueID32 unknown1; - UniqueID32 unknown2; - DamageInfo damageInfo1; - DamageInfo damageInfo2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; +namespace DataSpec::DNAMP1 { +struct Seedling : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + UniqueID32 unknown1; + UniqueID32 unknown2; + DamageInfo damageInfo1; + DamageInfo damageInfo2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (unknown1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown1); - ent->name = name + "_unk1"; - } - if (unknown2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown2); - ent->name = name + "_unk2"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (unknown1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown1); + ent->name = name + "_unk1"; } + if (unknown2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unknown2); + ent->name = name + "_unk2"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(unknown1, pathsOut); - g_curSpec->flattenDependencies(unknown2, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(unknown1, pathsOut); + g_curSpec->flattenDependencies(unknown2, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ShadowProjector.hpp b/DataSpec/DNAMP1/ScriptObjects/ShadowProjector.hpp index 24419db82..9bd131ad4 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ShadowProjector.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ShadowProjector.hpp @@ -4,22 +4,19 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ShadowProjector : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; +namespace DataSpec::DNAMP1 { +struct ShadowProjector : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/SnakeWeedSwarm.hpp b/DataSpec/DNAMP1/ScriptObjects/SnakeWeedSwarm.hpp index 475dc430d..f448a2257 100644 --- a/DataSpec/DNAMP1/ScriptObjects/SnakeWeedSwarm.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/SnakeWeedSwarm.hpp @@ -4,60 +4,50 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct SnakeWeedSwarm : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value volume; - Value unknown1; - AnimationParameters animationParameters; - ActorParameters actorParameters; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; - DamageInfo damageInfo; - Value unknown16; - Value unknown17; - Value unknown18; - Value unknown19; +namespace DataSpec::DNAMP1 { +struct SnakeWeedSwarm : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value volume; + Value unknown1; + AnimationParameters animationParameters; + ActorParameters actorParameters; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + DamageInfo damageInfo; + Value unknown16; + Value unknown17; + Value unknown18; + Value unknown19; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Sound.hpp b/DataSpec/DNAMP1/ScriptObjects/Sound.hpp index a2d8d17af..16ebee4f3 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Sound.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Sound.hpp @@ -4,32 +4,29 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Sound : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value soundID; - Value active; - Value maxDist; - Value distComp; - Value startDelay; - Value minVol; - Value vol; - Value prio; - Value pan; - Value loop; - Value nonEmitter; - Value autoStart; - Value occlusionTest; - Value acoustics; - Value worldSfx; - Value allowDuplicates; - Value pitch; +namespace DataSpec::DNAMP1 { +struct Sound : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value soundID; + Value active; + Value maxDist; + Value distComp; + Value startDelay; + Value minVol; + Value vol; + Value prio; + Value pan; + Value loop; + Value nonEmitter; + Value autoStart; + Value occlusionTest; + Value acoustics; + Value worldSfx; + Value allowDuplicates; + Value pitch; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/SpacePirate.hpp b/DataSpec/DNAMP1/ScriptObjects/SpacePirate.hpp index 0b42099f9..e2dbbafe0 100644 --- a/DataSpec/DNAMP1/ScriptObjects/SpacePirate.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/SpacePirate.hpp @@ -4,83 +4,71 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct SpacePirate : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - UniqueID32 wpsc1; - DamageInfo damageInfo1; - Value soundID1; - DamageInfo damageInfo2; - Value unknown9; - UniqueID32 wpsc2; - DamageInfo damageInfo3; - Value unknown10; - Value soundID2; - Value unknown11; - Value unknown12; - Value soundID3; - Value unknown13; - Value unknown14; - Value unknown15; - Value unknown16; - Value unknown17; - Value unknown18; - Value soundID4; - Value soundID5; - Value unknown19; - Value unknown20; +namespace DataSpec::DNAMP1 { +struct SpacePirate : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + UniqueID32 wpsc1; + DamageInfo damageInfo1; + Value soundID1; + DamageInfo damageInfo2; + Value unknown9; + UniqueID32 wpsc2; + DamageInfo damageInfo3; + Value unknown10; + Value soundID2; + Value unknown11; + Value unknown12; + Value soundID3; + Value unknown13; + Value unknown14; + Value unknown15; + Value unknown16; + Value unknown17; + Value unknown18; + Value soundID4; + Value soundID5; + Value unknown19; + Value unknown20; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc1"; - } - if (wpsc2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); - ent->name = name + "_wpsc2"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc1"; } + if (wpsc2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc2); + ent->name = name + "_wpsc2"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(wpsc2, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(wpsc2, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/SpankWeed.hpp b/DataSpec/DNAMP1/ScriptObjects/SpankWeed.hpp index a7e8006de..2e0d11a81 100644 --- a/DataSpec/DNAMP1/ScriptObjects/SpankWeed.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/SpankWeed.hpp @@ -4,46 +4,36 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct SpankWeed : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; +namespace DataSpec::DNAMP1 { +struct SpankWeed : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/SpawnPoint.hpp b/DataSpec/DNAMP1/ScriptObjects/SpawnPoint.hpp index d47e74d06..4cbd3a896 100644 --- a/DataSpec/DNAMP1/ScriptObjects/SpawnPoint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/SpawnPoint.hpp @@ -4,47 +4,44 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct SpawnPoint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value powerBeam; - Value iceBeam; - Value waveBeam; - Value plasmaBeam; - Value missiles; - Value scanVisor; - Value morphBallBombs; - Value powerBombs; - Value flameThrower; - Value thermalVisor; - Value chargeBeam; - Value superMissile; - Value grappleBeam; - Value xrayVisor; - Value iceSpreader; - Value spaceJump; - Value morphBall; - Value combatVisor; - Value boostBall; - Value spiderBall; - Value powerSuit; // verification needed - Value gravitySuit; - Value variaSuit; - Value phazonSuit; - Value energyTanks; - Value unknownItem1; - Value healthRefill; - Value unknownItem2; - Value waveBuster; - Value defaultSpawn; - Value active; - Value morphed; +namespace DataSpec::DNAMP1 { +struct SpawnPoint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value powerBeam; + Value iceBeam; + Value waveBeam; + Value plasmaBeam; + Value missiles; + Value scanVisor; + Value morphBallBombs; + Value powerBombs; + Value flameThrower; + Value thermalVisor; + Value chargeBeam; + Value superMissile; + Value grappleBeam; + Value xrayVisor; + Value iceSpreader; + Value spaceJump; + Value morphBall; + Value combatVisor; + Value boostBall; + Value spiderBall; + Value powerSuit; // verification needed + Value gravitySuit; + Value variaSuit; + Value phazonSuit; + Value energyTanks; + Value unknownItem1; + Value healthRefill; + Value unknownItem2; + Value waveBuster; + Value defaultSpawn; + Value active; + Value morphed; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/SpecialFunction.hpp b/DataSpec/DNAMP1/ScriptObjects/SpecialFunction.hpp index f6e23fd43..64f6dbb40 100644 --- a/DataSpec/DNAMP1/ScriptObjects/SpecialFunction.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/SpecialFunction.hpp @@ -4,32 +4,28 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct SpecialFunction : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value function; - String<-1> unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - struct LayerSwitch : BigDNA - { - AT_DECL_DNA - Value area; - Value layerIdx; - } layerSwitch; - Value pickup; - Value unknown5; - Value unknown6; - Value unknown7; // Used by SpinnerController 1 - Value unknown8; // Used by SpinnerController 2 - Value unknown9; // Used by SpinnerController 3 +namespace DataSpec::DNAMP1 { +struct SpecialFunction : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value function; + String<-1> unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + struct LayerSwitch : BigDNA { + AT_DECL_DNA + Value area; + Value layerIdx; + } layerSwitch; + Value pickup; + Value unknown5; + Value unknown6; + Value unknown7; // Used by SpinnerController 1 + Value unknown8; // Used by SpinnerController 2 + Value unknown9; // Used by SpinnerController 3 }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/SpiderBallAttractionSurface.hpp b/DataSpec/DNAMP1/ScriptObjects/SpiderBallAttractionSurface.hpp index fd245c69f..26d79440b 100644 --- a/DataSpec/DNAMP1/ScriptObjects/SpiderBallAttractionSurface.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/SpiderBallAttractionSurface.hpp @@ -4,17 +4,14 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct SpiderBallAttractionSurface : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - Value active; +namespace DataSpec::DNAMP1 { +struct SpiderBallAttractionSurface : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + Value active; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/SpiderBallWaypoint.hpp b/DataSpec/DNAMP1/ScriptObjects/SpiderBallWaypoint.hpp index cce108c67..184657abf 100644 --- a/DataSpec/DNAMP1/ScriptObjects/SpiderBallWaypoint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/SpiderBallWaypoint.hpp @@ -4,17 +4,14 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct SpiderBallWaypoint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value unknown1; - Value unknown2; +namespace DataSpec::DNAMP1 { +struct SpiderBallWaypoint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value unknown1; + Value unknown2; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/SpindleCamera.hpp b/DataSpec/DNAMP1/ScriptObjects/SpindleCamera.hpp index e73299326..67aa0dea1 100644 --- a/DataSpec/DNAMP1/ScriptObjects/SpindleCamera.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/SpindleCamera.hpp @@ -4,31 +4,27 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct SpindleCamera : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value unknown1; +namespace DataSpec::DNAMP1 { +struct SpindleCamera : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value unknown1; + PlayerParameters playerParameters; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + struct SpindleCameraParameters : BigDNA { + AT_DECL_DNA + Value unknown1; PlayerParameters playerParameters; - Value unknown2; - Value unknown3; - Value unknown4; Value unknown5; - struct SpindleCameraParameters : BigDNA - { - AT_DECL_DNA - Value unknown1; - PlayerParameters playerParameters; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - } spindleCameraParameters[15]; + Value unknown6; + Value unknown7; + Value unknown8; + } spindleCameraParameters[15]; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Steam.hpp b/DataSpec/DNAMP1/ScriptObjects/Steam.hpp index ff7017ebc..0ec8b802f 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Steam.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Steam.hpp @@ -4,40 +4,33 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Steam : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value volume; - DamageInfo damageInfo; - Value unknown1; - Value unknown2; - Value unknown3; - UniqueID32 texture; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; +namespace DataSpec::DNAMP1 { +struct Steam : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value volume; + DamageInfo damageInfo; + Value unknown1; + Value unknown2; + Value unknown3; + UniqueID32 texture; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; - void nameIDs(PAKRouter& pakRouter) const - { - if (texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); - ent->name = name + "_texture"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); + ent->name = name + "_texture"; } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(texture, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(texture, lazyOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/StreamedAudio.hpp b/DataSpec/DNAMP1/ScriptObjects/StreamedAudio.hpp index c8e5b5119..e078cf9b3 100644 --- a/DataSpec/DNAMP1/ScriptObjects/StreamedAudio.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/StreamedAudio.hpp @@ -4,21 +4,18 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct StreamedAudio : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; - String<-1> fileName; - Value noStopOnDeactivate; - Value fadeInTime; - Value fadeOutTime; - Value volume; - Value oneShot; - Value music; +namespace DataSpec::DNAMP1 { +struct StreamedAudio : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; + String<-1> fileName; + Value noStopOnDeactivate; + Value fadeInTime; + Value fadeOutTime; + Value volume; + Value oneShot; + Value music; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Switch.hpp b/DataSpec/DNAMP1/ScriptObjects/Switch.hpp index b1eb61cba..bda3113bd 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Switch.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Switch.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Switch : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value unknown2; - Value unknown3; +namespace DataSpec::DNAMP1 { +struct Switch : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value unknown2; + Value unknown3; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/TargetingPoint.hpp b/DataSpec/DNAMP1/ScriptObjects/TargetingPoint.hpp index d63598d5a..9ff9a89d1 100644 --- a/DataSpec/DNAMP1/ScriptObjects/TargetingPoint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/TargetingPoint.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct TargetingPoint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value active; +namespace DataSpec::DNAMP1 { +struct TargetingPoint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value active; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/TeamAIMgr.hpp b/DataSpec/DNAMP1/ScriptObjects/TeamAIMgr.hpp index 8d340723a..e02fffe86 100644 --- a/DataSpec/DNAMP1/ScriptObjects/TeamAIMgr.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/TeamAIMgr.hpp @@ -4,22 +4,19 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct TeamAIMgr : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value aiCount; - Value meleeCount; - Value projectileCount; - Value unknownCount; - Value maxMeleeAttackerCount; - Value maxProjectileAttackerCount; - Value positionMode; - Value meleeTimeInterval; - Value projectileTimeInterval; +namespace DataSpec::DNAMP1 { +struct TeamAIMgr : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value aiCount; + Value meleeCount; + Value projectileCount; + Value unknownCount; + Value maxMeleeAttackerCount; + Value maxProjectileAttackerCount; + Value positionMode; + Value meleeTimeInterval; + Value projectileTimeInterval; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Thardus.hpp b/DataSpec/DNAMP1/ScriptObjects/Thardus.hpp index b2e61c666..79baa0d9d 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Thardus.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Thardus.hpp @@ -4,198 +4,162 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Thardus : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - UniqueID32 models[14]; - UniqueID32 particles1[3]; - UniqueID32 stateMachine; - UniqueID32 particles2[6]; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - UniqueID32 texture; - Value unknown9; - UniqueID32 particle; - Value unknown10; - Value unknown11; - Value unknown12; +namespace DataSpec::DNAMP1 { +struct Thardus : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + UniqueID32 models[14]; + UniqueID32 particles1[3]; + UniqueID32 stateMachine; + UniqueID32 particles2[6]; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + UniqueID32 texture; + Value unknown9; + UniqueID32 particle; + Value unknown10; + Value unknown11; + Value unknown12; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (models[0]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[0]); - ent->name = name + "_model1"; - } - if (models[1]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[1]); - ent->name = name + "_model2"; - } - if (models[2]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[2]); - ent->name = name + "_model3"; - } - if (models[3]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[3]); - ent->name = name + "_model4"; - } - if (models[4]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[4]); - ent->name = name + "_model5"; - } - if (models[5]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[5]); - ent->name = name + "_model6"; - } - if (models[6]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[6]); - ent->name = name + "_model7"; - } - if (models[7]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[7]); - ent->name = name + "_model8"; - } - if (models[8]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[8]); - ent->name = name + "_model9"; - } - if (models[9]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[9]); - ent->name = name + "_model10"; - } - if (models[10]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[10]); - ent->name = name + "_model11"; - } - if (models[11]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[11]); - ent->name = name + "_model12"; - } - if (models[12]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[12]); - ent->name = name + "_model13"; - } - if (models[13]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[13]); - ent->name = name + "_model14"; - } - if (particles1[0]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles1[0]); - ent->name = name + "_part1"; - } - if (particles1[1]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles1[1]); - ent->name = name + "_part2"; - } - if (particles1[2]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles1[2]); - ent->name = name + "_part3"; - } - if (stateMachine) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(stateMachine); - ent->name = name + "_fsm"; - } - if (particles2[0]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[0]); - ent->name = name + "_part4"; - } - if (particles2[1]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[1]); - ent->name = name + "_part5"; - } - if (particles2[2]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[2]); - ent->name = name + "_part6"; - } - if (particles2[3]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[3]); - ent->name = name + "_part7"; - } - if (particles2[4]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[4]); - ent->name = name + "_part8"; - } - if (particles2[5]) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[5]); - ent->name = name + "_part9"; - } - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part10"; - } - if (texture) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); - ent->name = name + "_texture"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (models[0]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[0]); + ent->name = name + "_model1"; } + if (models[1]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[1]); + ent->name = name + "_model2"; + } + if (models[2]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[2]); + ent->name = name + "_model3"; + } + if (models[3]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[3]); + ent->name = name + "_model4"; + } + if (models[4]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[4]); + ent->name = name + "_model5"; + } + if (models[5]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[5]); + ent->name = name + "_model6"; + } + if (models[6]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[6]); + ent->name = name + "_model7"; + } + if (models[7]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[7]); + ent->name = name + "_model8"; + } + if (models[8]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[8]); + ent->name = name + "_model9"; + } + if (models[9]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[9]); + ent->name = name + "_model10"; + } + if (models[10]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[10]); + ent->name = name + "_model11"; + } + if (models[11]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[11]); + ent->name = name + "_model12"; + } + if (models[12]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[12]); + ent->name = name + "_model13"; + } + if (models[13]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(models[13]); + ent->name = name + "_model14"; + } + if (particles1[0]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles1[0]); + ent->name = name + "_part1"; + } + if (particles1[1]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles1[1]); + ent->name = name + "_part2"; + } + if (particles1[2]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles1[2]); + ent->name = name + "_part3"; + } + if (stateMachine) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(stateMachine); + ent->name = name + "_fsm"; + } + if (particles2[0]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[0]); + ent->name = name + "_part4"; + } + if (particles2[1]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[1]); + ent->name = name + "_part5"; + } + if (particles2[2]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[2]); + ent->name = name + "_part6"; + } + if (particles2[3]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[3]); + ent->name = name + "_part7"; + } + if (particles2[4]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[4]); + ent->name = name + "_part8"; + } + if (particles2[5]) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particles2[5]); + ent->name = name + "_part9"; + } + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part10"; + } + if (texture) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture); + ent->name = name + "_texture"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - for (int i=0 ; i<14 ; ++i) - g_curSpec->flattenDependencies(models[i], pathsOut); - for (int i=0 ; i<3 ; ++i) - g_curSpec->flattenDependencies(particles1[i], pathsOut); - g_curSpec->flattenDependencies(stateMachine, pathsOut); - for (int i=0 ; i<6 ; ++i) - g_curSpec->flattenDependencies(particles2[i], pathsOut); - g_curSpec->flattenDependencies(particle, pathsOut); - g_curSpec->flattenDependencies(texture, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + for (int i = 0; i < 14; ++i) + g_curSpec->flattenDependencies(models[i], pathsOut); + for (int i = 0; i < 3; ++i) + g_curSpec->flattenDependencies(particles1[i], pathsOut); + g_curSpec->flattenDependencies(stateMachine, pathsOut); + for (int i = 0; i < 6; ++i) + g_curSpec->flattenDependencies(particles2[i], pathsOut); + g_curSpec->flattenDependencies(particle, pathsOut); + g_curSpec->flattenDependencies(texture, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ThardusRockProjectile.hpp b/DataSpec/DNAMP1/ScriptObjects/ThardusRockProjectile.hpp index 2ca9b7b07..77496bac8 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ThardusRockProjectile.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ThardusRockProjectile.hpp @@ -4,58 +4,46 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ThardusRockProjectile : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - UniqueID32 model; - UniqueID32 stateMachine; +namespace DataSpec::DNAMP1 { +struct ThardusRockProjectile : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + UniqueID32 model; + UniqueID32 stateMachine; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (model) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); - ent->name = name + "_model"; - } - if (stateMachine) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(stateMachine); - ent->name = name + "_fsm"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (model) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model); + ent->name = name + "_model"; } + if (stateMachine) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(stateMachine); + ent->name = name + "_fsm"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(model, pathsOut); - g_curSpec->flattenDependencies(stateMachine, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(model, pathsOut); + g_curSpec->flattenDependencies(stateMachine, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/ThermalHeatFader.hpp b/DataSpec/DNAMP1/ScriptObjects/ThermalHeatFader.hpp index bae91bb6e..cb96ca03c 100644 --- a/DataSpec/DNAMP1/ScriptObjects/ThermalHeatFader.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/ThermalHeatFader.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct ThermalHeatFader : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; - Value fadedLevel; - Value initialLevel; +namespace DataSpec::DNAMP1 { +struct ThermalHeatFader : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; + Value fadedLevel; + Value initialLevel; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Timer.hpp b/DataSpec/DNAMP1/ScriptObjects/Timer.hpp index cc5f132b7..2fade1756 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Timer.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Timer.hpp @@ -4,18 +4,15 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Timer : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value startTime; - Value maxRandomAddition; - Value resetToZero; - Value startImmediately; - Value active; +namespace DataSpec::DNAMP1 { +struct Timer : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value startTime; + Value maxRandomAddition; + Value resetToZero; + Value startImmediately; + Value active; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Trigger.hpp b/DataSpec/DNAMP1/ScriptObjects/Trigger.hpp index 9c219d1c4..305b3285e 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Trigger.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Trigger.hpp @@ -4,28 +4,24 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Trigger : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value volume; - DamageInfo damageInfo; - Value force; - Value unknown; - Value active; - Value unknown2; - Value unknown3; +namespace DataSpec::DNAMP1 { +struct Trigger : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value volume; + DamageInfo damageInfo; + Value force; + Value unknown; + Value active; + Value unknown2; + Value unknown3; - zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const - { - zeus::CVector3f halfExtent = zeus::CVector3f(volume) / 2.f; - zeus::CVector3f loc(location); - return zeus::CAABox(loc - halfExtent, loc + halfExtent); - } + zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const { + zeus::CVector3f halfExtent = zeus::CVector3f(volume) / 2.f; + zeus::CVector3f loc(location); + return zeus::CAABox(loc - halfExtent, loc + halfExtent); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Tryclops.hpp b/DataSpec/DNAMP1/ScriptObjects/Tryclops.hpp index 744bf772b..03aa40e70 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Tryclops.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Tryclops.hpp @@ -4,45 +4,35 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Tryclops : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; +namespace DataSpec::DNAMP1 { +struct Tryclops : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); - } + void nameIDs(PAKRouter& pakRouter) const { + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/VisorFlare.hpp b/DataSpec/DNAMP1/ScriptObjects/VisorFlare.hpp index 06500e8aa..e24a53788 100644 --- a/DataSpec/DNAMP1/ScriptObjects/VisorFlare.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/VisorFlare.hpp @@ -4,38 +4,32 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct VisorFlare : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - FlareDefinition flareDefinitions[5]; +namespace DataSpec::DNAMP1 { +struct VisorFlare : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; + Value unknown7; + FlareDefinition flareDefinitions[5]; - void nameIDs(PAKRouter& pakRouter) const - { - flareDefinitions[0].nameIDs(pakRouter, name + "_flare1"); - flareDefinitions[1].nameIDs(pakRouter, name + "_flare2"); - flareDefinitions[2].nameIDs(pakRouter, name + "_flare3"); - flareDefinitions[3].nameIDs(pakRouter, name + "_flare4"); - flareDefinitions[4].nameIDs(pakRouter, name + "_flare5"); - } + void nameIDs(PAKRouter& pakRouter) const { + flareDefinitions[0].nameIDs(pakRouter, name + "_flare1"); + flareDefinitions[1].nameIDs(pakRouter, name + "_flare2"); + flareDefinitions[2].nameIDs(pakRouter, name + "_flare3"); + flareDefinitions[3].nameIDs(pakRouter, name + "_flare4"); + flareDefinitions[4].nameIDs(pakRouter, name + "_flare5"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - for (int i=0 ; i<5 ; ++i) - flareDefinitions[i].depIDs(pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + for (int i = 0; i < 5; ++i) + flareDefinitions[i].depIDs(pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/VisorGoo.hpp b/DataSpec/DNAMP1/ScriptObjects/VisorGoo.hpp index 732b1142f..d888df2f1 100644 --- a/DataSpec/DNAMP1/ScriptObjects/VisorGoo.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/VisorGoo.hpp @@ -4,44 +4,36 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct VisorGoo : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value position; - UniqueID32 particle; - UniqueID32 electric; - Value minDist; - Value maxDist; - Value nearProb; - Value farProb; - DNAColor color; - Value sfx; - Value skipAngleTest; +namespace DataSpec::DNAMP1 { +struct VisorGoo : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value position; + UniqueID32 particle; + UniqueID32 electric; + Value minDist; + Value maxDist; + Value nearProb; + Value farProb; + DNAColor color; + Value sfx; + Value skipAngleTest; - void nameIDs(PAKRouter& pakRouter) const - { - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - if (electric) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(electric); - ent->name = name + "_elsc"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; } + if (electric) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(electric); + ent->name = name + "_elsc"; + } + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle, pathsOut); - g_curSpec->flattenDependencies(electric, pathsOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle, pathsOut); + g_curSpec->flattenDependencies(electric, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/WallCrawlerSwarm.hpp b/DataSpec/DNAMP1/ScriptObjects/WallCrawlerSwarm.hpp index f1c44e6e5..df64f79fd 100644 --- a/DataSpec/DNAMP1/ScriptObjects/WallCrawlerSwarm.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/WallCrawlerSwarm.hpp @@ -4,86 +4,74 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct WallCrawlerSwarm : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value volume; - Value active; - ActorParameters actorParameters; - Value unknown1; - AnimationParameters animationParameters; - Value unknown2; - Value unknown3; - UniqueID32 particle1; - UniqueID32 particle2; - Value unknown4; // always FF - Value unknown5; // always FF - DamageInfo damageInfo1; - Value unknown6; - DamageInfo damageInfo2; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14; - Value unknown15; - Value unknown16; - Value unknown17; - Value unknown18; - Value unknown19; - Value unknown20; - Value unknown21; - Value unkown22; - Value unkown23; - Value unkown24; - HealthInfo healthInfo; - DamageVulnerability damageVulnerabilty; - Value soundID1; // verification needed - Value soundID2; // verification needed +namespace DataSpec::DNAMP1 { +struct WallCrawlerSwarm : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value volume; + Value active; + ActorParameters actorParameters; + Value unknown1; + AnimationParameters animationParameters; + Value unknown2; + Value unknown3; + UniqueID32 particle1; + UniqueID32 particle2; + Value unknown4; // always FF + Value unknown5; // always FF + DamageInfo damageInfo1; + Value unknown6; + DamageInfo damageInfo2; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14; + Value unknown15; + Value unknown16; + Value unknown17; + Value unknown18; + Value unknown19; + Value unknown20; + Value unknown21; + Value unkown22; + Value unkown23; + Value unkown24; + HealthInfo healthInfo; + DamageVulnerability damageVulnerabilty; + Value soundID1; // verification needed + Value soundID2; // verification needed - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (particle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); - ent->name = name + "_part1"; - } - if (particle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); - ent->name = name + "_part2"; - } - animationParameters.nameANCS(pakRouter, name + "_animp"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (particle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + ent->name = name + "_part1"; } + if (particle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + ent->name = name + "_part2"; + } + animationParameters.nameANCS(pakRouter, name + "_animp"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - animationParameters.depANCS(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(particle1, pathsOut); + g_curSpec->flattenDependencies(particle2, pathsOut); + animationParameters.depANCS(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Warwasp.hpp b/DataSpec/DNAMP1/ScriptObjects/Warwasp.hpp index d457bf04b..ff55c55be 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Warwasp.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Warwasp.hpp @@ -4,60 +4,48 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Warwasp : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - Value location; - Value orientation; - Value scale; - PatternedInfo patternedInfo; - ActorParameters actorParameters; - Value unknown2; - DamageInfo damageInfo1; - UniqueID32 wpsc1; - DamageInfo damageInfo2; - UniqueID32 particle; - Value unknown3; +namespace DataSpec::DNAMP1 { +struct Warwasp : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + Value location; + Value orientation; + Value scale; + PatternedInfo patternedInfo; + ActorParameters actorParameters; + Value unknown2; + DamageInfo damageInfo1; + UniqueID32 wpsc1; + DamageInfo damageInfo2; + UniqueID32 particle; + Value unknown3; - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const - { - actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); - } + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + actorParameters.addCMDLRigPairs(pakRouter, charAssoc, patternedInfo.animationParameters); + } - void nameIDs(PAKRouter& pakRouter) const - { - if (wpsc1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); - ent->name = name + "_wpsc"; - } - if (particle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); - ent->name = name + "_part"; - } - patternedInfo.nameIDs(pakRouter, name + "_patterned"); - actorParameters.nameIDs(pakRouter, name + "_actp"); + void nameIDs(PAKRouter& pakRouter) const { + if (wpsc1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(wpsc1); + ent->name = name + "_wpsc"; } + if (particle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle); + ent->name = name + "_part"; + } + patternedInfo.nameIDs(pakRouter, name + "_patterned"); + actorParameters.nameIDs(pakRouter, name + "_actp"); + } - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(wpsc1, pathsOut); - g_curSpec->flattenDependencies(particle, pathsOut); - patternedInfo.depIDs(pathsOut); - actorParameters.depIDs(pathsOut, lazyOut); - } + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(wpsc1, pathsOut); + g_curSpec->flattenDependencies(particle, pathsOut); + patternedInfo.depIDs(pathsOut); + actorParameters.depIDs(pathsOut, lazyOut); + } - void gatherScans(std::vector& scansOut) const - { - actorParameters.scanIDs(scansOut); - } + void gatherScans(std::vector& scansOut) const { actorParameters.scanIDs(scansOut); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Water.cpp b/DataSpec/DNAMP1/ScriptObjects/Water.cpp index 39aedd9f7..2306b7943 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Water.cpp +++ b/DataSpec/DNAMP1/ScriptObjects/Water.cpp @@ -1,27 +1,27 @@ #include "Water.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template <> -void Water::UnusedBitset::Enumerate(typename Read::StreamT& in) -{ - if (in.readBool()) - { - atUint32 bitVal0 = in.readUint16Big(); - atUint32 bitVal1 = in.readUint16Big(); - atUint32 len = ((bitVal0 * bitVal1) + 31) / 31; - in.seek(len * 4); - } +void Water::UnusedBitset::Enumerate(typename Read::StreamT& in) { + if (in.readBool()) { + atUint32 bitVal0 = in.readUint16Big(); + atUint32 bitVal1 = in.readUint16Big(); + atUint32 len = ((bitVal0 * bitVal1) + 31) / 31; + in.seek(len * 4); + } } template <> -void Water::UnusedBitset::Enumerate(typename Write::StreamT& out) { out.writeBool(false); } +void Water::UnusedBitset::Enumerate(typename Write::StreamT& out) { + out.writeBool(false); +} template <> void Water::UnusedBitset::Enumerate(typename ReadYaml::StreamT& r) {} template <> void Water::UnusedBitset::Enumerate(typename WriteYaml::StreamT& w) {} template <> -void Water::UnusedBitset::Enumerate(typename BinarySize::StreamT& s) { s += 1; } - +void Water::UnusedBitset::Enumerate(typename BinarySize::StreamT& s) { + s += 1; } +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Water.hpp b/DataSpec/DNAMP1/ScriptObjects/Water.hpp index 56c79df39..048fb7877 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Water.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Water.hpp @@ -4,184 +4,160 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Water : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value volume; - DamageInfo damageInfo; - Value orientedForce; - Value triggerFlags; - Value thermalCold; - Value displaySurface; - UniqueID32 patternMap1; - UniqueID32 patternMap2; - UniqueID32 colorMap; - UniqueID32 bumpMap; - UniqueID32 envMap; - UniqueID32 envBumpMap; - Value bumpLightDir; - Value bumpScale; - Value morphInTime; - Value morphOutTime; - Value active; - Value fluidType; - Value unknownBool; - Value alpha; - struct FluidUVMotion : BigDNA - { - AT_DECL_DNA - struct FluidLayerMotion : BigDNA - { - AT_DECL_DNA - Value motionType; - Value timeToWrap; - Value orientation; - Value magnitude; - Value uvMul; - }; +namespace DataSpec::DNAMP1 { +struct Water : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value volume; + DamageInfo damageInfo; + Value orientedForce; + Value triggerFlags; + Value thermalCold; + Value displaySurface; + UniqueID32 patternMap1; + UniqueID32 patternMap2; + UniqueID32 colorMap; + UniqueID32 bumpMap; + UniqueID32 envMap; + UniqueID32 envBumpMap; + Value bumpLightDir; + Value bumpScale; + Value morphInTime; + Value morphOutTime; + Value active; + Value fluidType; + Value unknownBool; + Value alpha; + struct FluidUVMotion : BigDNA { + AT_DECL_DNA + struct FluidLayerMotion : BigDNA { + AT_DECL_DNA + Value motionType; + Value timeToWrap; + Value orientation; + Value magnitude; + Value uvMul; + }; - FluidLayerMotion pattern1Layer; - FluidLayerMotion pattern2Layer; - FluidLayerMotion colorLayer; - Value timeToWrap; - Value orientation; - } fluidUVMotion; + FluidLayerMotion pattern1Layer; + FluidLayerMotion pattern2Layer; + FluidLayerMotion colorLayer; + Value timeToWrap; + Value orientation; + } fluidUVMotion; - Value turbulenceSpeed; - Value turbulenceDistance; - Value turbulenceFrequencyMax; - Value turbulenceFrequencyMin; - Value turbulencePhaseMax; - Value turbulencePhaseMin; - Value turbulenceAmplitudeMax; - Value turbulenceAmplitudeMin; - Value splashColor; - Value insideFogColor; - UniqueID32 splashParticle1; - UniqueID32 splashParticle2; - UniqueID32 splashParticle3; - UniqueID32 visorRunoffParticle; - UniqueID32 unmorphVisorRunoffParticle; - Value visorRunoffSfx; - Value unmorphVisorRunoffSfx; - Value splashSfx1; - Value splashSfx2; - Value splashSfx3; - Value tileSize; - Value tileSubdivisions; - Value specularMin; - Value specularMax; - Value reflectionSize; - Value rippleIntensity; - Value reflectionBlend; - Value fogBias; - Value fogMagnitude; - Value fogSpeed; - Value fogColor; - UniqueID32 lightmap; - Value unitsPerLightmapTexel; - Value alphaInTime; - Value alphaOutTime; - Value unusedInt1; - Value unusedInt2; + Value turbulenceSpeed; + Value turbulenceDistance; + Value turbulenceFrequencyMax; + Value turbulenceFrequencyMin; + Value turbulencePhaseMax; + Value turbulencePhaseMin; + Value turbulenceAmplitudeMax; + Value turbulenceAmplitudeMin; + Value splashColor; + Value insideFogColor; + UniqueID32 splashParticle1; + UniqueID32 splashParticle2; + UniqueID32 splashParticle3; + UniqueID32 visorRunoffParticle; + UniqueID32 unmorphVisorRunoffParticle; + Value visorRunoffSfx; + Value unmorphVisorRunoffSfx; + Value splashSfx1; + Value splashSfx2; + Value splashSfx3; + Value tileSize; + Value tileSubdivisions; + Value specularMin; + Value specularMax; + Value reflectionSize; + Value rippleIntensity; + Value reflectionBlend; + Value fogBias; + Value fogMagnitude; + Value fogSpeed; + Value fogColor; + UniqueID32 lightmap; + Value unitsPerLightmapTexel; + Value alphaInTime; + Value alphaOutTime; + Value unusedInt1; + Value unusedInt2; - struct UnusedBitset : BigDNA - { - AT_DECL_EXPLICIT_DNA - } unusedBitset; + struct UnusedBitset : BigDNA{AT_DECL_EXPLICIT_DNA} unusedBitset; - void nameIDs(PAKRouter& pakRouter) const - { - if (patternMap1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap1); - ent->name = name + "_patternMap1"; - } - if (patternMap2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap2); - ent->name = name + "_patternMap2"; - } - if (colorMap) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(colorMap); - ent->name = name + "_colorMap"; - } - if (bumpMap) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(bumpMap); - ent->name = name + "_bumpMap"; - } - if (envMap) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envMap); - ent->name = name + "_envMap"; - } - if (envBumpMap) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envBumpMap); - ent->name = name + "_envBumpMap"; - } - if (lightmap) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(lightmap); - ent->name = name + "_lightmap"; - } - if (splashParticle1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle1); - ent->name = name + "_splashParticle1"; - } - if (splashParticle2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle2); - ent->name = name + "_splashParticle2"; - } - if (splashParticle3) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle3); - ent->name = name + "_splashParticle3"; - } - if (visorRunoffParticle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(visorRunoffParticle); - ent->name = name + "_visorRunoffParticle"; - } - if (unmorphVisorRunoffParticle) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unmorphVisorRunoffParticle); - ent->name = name + "_unmorphVisorRunoffParticle"; - } + void nameIDs(PAKRouter& pakRouter) const { + if (patternMap1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap1); + ent->name = name + "_patternMap1"; } - - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(patternMap1, pathsOut); - g_curSpec->flattenDependencies(patternMap2, pathsOut); - g_curSpec->flattenDependencies(colorMap, pathsOut); - g_curSpec->flattenDependencies(bumpMap, pathsOut); - g_curSpec->flattenDependencies(envMap, pathsOut); - g_curSpec->flattenDependencies(envBumpMap, pathsOut); - g_curSpec->flattenDependencies(lightmap, pathsOut); - g_curSpec->flattenDependencies(splashParticle1, pathsOut); - g_curSpec->flattenDependencies(splashParticle2, pathsOut); - g_curSpec->flattenDependencies(splashParticle3, pathsOut); - g_curSpec->flattenDependencies(visorRunoffParticle, pathsOut); - g_curSpec->flattenDependencies(unmorphVisorRunoffParticle, pathsOut); + if (patternMap2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap2); + ent->name = name + "_patternMap2"; } - - zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const - { - zeus::CVector3f halfExtent = zeus::CVector3f(volume) / 2.f; - zeus::CVector3f loc(location); - return zeus::CAABox(loc - halfExtent, loc + halfExtent); + if (colorMap) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(colorMap); + ent->name = name + "_colorMap"; } + if (bumpMap) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(bumpMap); + ent->name = name + "_bumpMap"; + } + if (envMap) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envMap); + ent->name = name + "_envMap"; + } + if (envBumpMap) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envBumpMap); + ent->name = name + "_envBumpMap"; + } + if (lightmap) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(lightmap); + ent->name = name + "_lightmap"; + } + if (splashParticle1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle1); + ent->name = name + "_splashParticle1"; + } + if (splashParticle2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle2); + ent->name = name + "_splashParticle2"; + } + if (splashParticle3) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle3); + ent->name = name + "_splashParticle3"; + } + if (visorRunoffParticle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(visorRunoffParticle); + ent->name = name + "_visorRunoffParticle"; + } + if (unmorphVisorRunoffParticle) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(unmorphVisorRunoffParticle); + ent->name = name + "_unmorphVisorRunoffParticle"; + } + } + + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(patternMap1, pathsOut); + g_curSpec->flattenDependencies(patternMap2, pathsOut); + g_curSpec->flattenDependencies(colorMap, pathsOut); + g_curSpec->flattenDependencies(bumpMap, pathsOut); + g_curSpec->flattenDependencies(envMap, pathsOut); + g_curSpec->flattenDependencies(envBumpMap, pathsOut); + g_curSpec->flattenDependencies(lightmap, pathsOut); + g_curSpec->flattenDependencies(splashParticle1, pathsOut); + g_curSpec->flattenDependencies(splashParticle2, pathsOut); + g_curSpec->flattenDependencies(splashParticle3, pathsOut); + g_curSpec->flattenDependencies(visorRunoffParticle, pathsOut); + g_curSpec->flattenDependencies(unmorphVisorRunoffParticle, pathsOut); + } + + zeus::CAABox getVISIAABB(hecl::blender::Token& btok) const { + zeus::CVector3f halfExtent = zeus::CVector3f(volume) / 2.f; + zeus::CVector3f loc(location); + return zeus::CAABox(loc - halfExtent, loc + halfExtent); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/Waypoint.hpp b/DataSpec/DNAMP1/ScriptObjects/Waypoint.hpp index 643cd7060..e0d4a1af3 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Waypoint.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Waypoint.hpp @@ -4,25 +4,22 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct Waypoint : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value location; - Value orientation; - Value active; - Value speed; - Value pause; - Value patternTranslate; - Value patternOrient; - Value patternFit; - Value behaviour; - Value behaviourOrient; - Value behaviourModifiers; // 0x2: single, 0x4: double - Value animation; +namespace DataSpec::DNAMP1 { +struct Waypoint : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value location; + Value orientation; + Value active; + Value speed; + Value pause; + Value patternTranslate; + Value patternOrient; + Value patternFit; + Value behaviour; + Value behaviourOrient; + Value behaviourModifiers; // 0x2: single, 0x4: double + Value animation; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/WorldLightFader.hpp b/DataSpec/DNAMP1/ScriptObjects/WorldLightFader.hpp index e61957ed3..aad57e36e 100644 --- a/DataSpec/DNAMP1/ScriptObjects/WorldLightFader.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/WorldLightFader.hpp @@ -4,16 +4,13 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ -struct WorldLightFader : IScriptObject -{ - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value active; - Value fadedLevel; - Value intialLevel; +namespace DataSpec::DNAMP1 { +struct WorldLightFader : IScriptObject { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value active; + Value fadedLevel; + Value intialLevel; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/WorldTeleporter.cpp b/DataSpec/DNAMP1/ScriptObjects/WorldTeleporter.cpp index f4872b0bb..d2392c1cc 100644 --- a/DataSpec/DNAMP1/ScriptObjects/WorldTeleporter.cpp +++ b/DataSpec/DNAMP1/ScriptObjects/WorldTeleporter.cpp @@ -1,56 +1,48 @@ #include "WorldTeleporter.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template -void WorldTeleporter::Enumerate(typename Op::StreamT& s) -{ - IScriptObject::Enumerate(s); - Do({"name"}, name, s); - Do({"unknown1"}, unknown1, s); - Do({"mlvl"}, mlvl, s); - Do({"mrea"}, mrea, s); - Do({"animationParameters"}, animationParameters, s); - Do({"unknown2"}, unknown2, s); - Do({"model1"}, model1, s); - Do({"unknown3"}, unknown3, s); - Do({"model2"}, model2, s); - Do({"unknown4"}, unknown4, s); - Do({"unknown5"}, unknown5, s); - Do({"soundID"}, soundID, s); - Do({"unknown6"}, unknown6, s); - Do({"unknown7"}, unknown7, s); - Do({"unknown8"}, unknown8, s); - Do({"font"}, font, s); - Do({"strg"}, strg, s); - Do({"unknown9"}, unknown9, s); - Do({"unknown10"}, unknown10, s); - Do({"unknown11"}, unknown11, s); - Do({"unknown12"}, unknown12, s); +void WorldTeleporter::Enumerate(typename Op::StreamT& s) { + IScriptObject::Enumerate(s); + Do({"name"}, name, s); + Do({"unknown1"}, unknown1, s); + Do({"mlvl"}, mlvl, s); + Do({"mrea"}, mrea, s); + Do({"animationParameters"}, animationParameters, s); + Do({"unknown2"}, unknown2, s); + Do({"model1"}, model1, s); + Do({"unknown3"}, unknown3, s); + Do({"model2"}, model2, s); + Do({"unknown4"}, unknown4, s); + Do({"unknown5"}, unknown5, s); + Do({"soundID"}, soundID, s); + Do({"unknown6"}, unknown6, s); + Do({"unknown7"}, unknown7, s); + Do({"unknown8"}, unknown8, s); + Do({"font"}, font, s); + Do({"strg"}, strg, s); + Do({"unknown9"}, unknown9, s); + Do({"unknown10"}, unknown10, s); + Do({"unknown11"}, unknown11, s); + Do({"unknown12"}, unknown12, s); - if (propertyCount == 26) - { - Do({"audioStream"}, audioStream, s); - Do({"unknown13"}, unknown13, s); - Do({"unknown14"}, unknown14, s); - Do({"unknown15"}, unknown15, s); - Do({"unknown16"}, unknown16, s); - } - else - { - unknown13 = false; - unknown14 = 0.0; - unknown15 = 0.0; - unknown16 = 0.0; - } + if (propertyCount == 26) { + Do({"audioStream"}, audioStream, s); + Do({"unknown13"}, unknown13, s); + Do({"unknown14"}, unknown14, s); + Do({"unknown15"}, unknown15, s); + Do({"unknown16"}, unknown16, s); + } else { + unknown13 = false; + unknown14 = 0.0; + unknown15 = 0.0; + unknown16 = 0.0; + } } -const char* WorldTeleporter::DNAType() -{ - return "urde::DNAMP1::WorldTeleporter"; -} +const char* WorldTeleporter::DNAType() { return "urde::DNAMP1::WorldTeleporter"; } AT_SPECIALIZE_DNA_YAML(WorldTeleporter) -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/ScriptObjects/WorldTeleporter.hpp b/DataSpec/DNAMP1/ScriptObjects/WorldTeleporter.hpp index bdfe20f00..19b127027 100644 --- a/DataSpec/DNAMP1/ScriptObjects/WorldTeleporter.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/WorldTeleporter.hpp @@ -4,69 +4,60 @@ #include "IScriptObject.hpp" #include "Parameters.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct WorldTeleporter : IScriptObject -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_DECL_DNAV - String<-1> name; - Value unknown1; - UniqueID32 mlvl; - UniqueID32 mrea; - AnimationParameters animationParameters; - Value unknown2; - UniqueID32 model1; - Value unknown3; - UniqueID32 model2; - Value unknown4; - Value unknown5; - Value soundID; // needs verifcation - Value unknown6; - Value unknown7; - Value unknown8; - UniqueID32 font; - UniqueID32 strg; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - - /* Trilogy additions (property count 26) */ - String<-1> audioStream; - Value unknown13; - Value unknown14; - Value unknown15; - Value unknown16; +struct WorldTeleporter : IScriptObject { + AT_DECL_EXPLICIT_DNA_YAML + AT_DECL_DNAV + String<-1> name; + Value unknown1; + UniqueID32 mlvl; + UniqueID32 mrea; + AnimationParameters animationParameters; + Value unknown2; + UniqueID32 model1; + Value unknown3; + UniqueID32 model2; + Value unknown4; + Value unknown5; + Value soundID; // needs verifcation + Value unknown6; + Value unknown7; + Value unknown8; + UniqueID32 font; + UniqueID32 strg; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; - void nameIDs(PAKRouter& pakRouter) const - { - if (model1) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model1); - ent->name = name + "_model1"; - } - if (model2) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model2); - ent->name = name + "_model2"; - } - if (strg) - { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(strg); - ent->name = name + "_strg"; - } + /* Trilogy additions (property count 26) */ + String<-1> audioStream; + Value unknown13; + Value unknown14; + Value unknown15; + Value unknown16; + + void nameIDs(PAKRouter& pakRouter) const { + if (model1) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model1); + ent->name = name + "_model1"; } - - void gatherDependencies(std::vector& pathsOut, - std::vector& lazyOut) const - { - g_curSpec->flattenDependencies(model1, pathsOut); - g_curSpec->flattenDependencies(model2, pathsOut); - g_curSpec->flattenDependencies(strg, pathsOut); + if (model2) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(model2); + ent->name = name + "_model2"; } + if (strg) { + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(strg); + ent->name = name + "_strg"; + } + } + + void gatherDependencies(std::vector& pathsOut, std::vector& lazyOut) const { + g_curSpec->flattenDependencies(model1, pathsOut); + g_curSpec->flattenDependencies(model2, pathsOut); + g_curSpec->flattenDependencies(strg, pathsOut); + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/SnowForces.hpp b/DataSpec/DNAMP1/SnowForces.hpp index 49ae3f463..d96ca7c2b 100644 --- a/DataSpec/DNAMP1/SnowForces.hpp +++ b/DataSpec/DNAMP1/SnowForces.hpp @@ -4,19 +4,15 @@ #include "DNAMP1.hpp" -namespace DataSpec::DNAMP1 -{ -struct SnowForces : BigDNA -{ - AT_DECL_DNA_YAML - struct Force : BigDNA - { - AT_DECL_DNA - Value gravity; - Value wind; - }; +namespace DataSpec::DNAMP1 { +struct SnowForces : BigDNA { + AT_DECL_DNA_YAML + struct Force : BigDNA { + AT_DECL_DNA + Value gravity; + Value wind; + }; - Value forces[256]; + Value forces[256]; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakAutoMapper.hpp b/DataSpec/DNAMP1/Tweaks/CTweakAutoMapper.hpp index 58b96366d..f76ed4d84 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakAutoMapper.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakAutoMapper.hpp @@ -3,137 +3,134 @@ #include "../../DataSpec/DNACommon/Tweaks/ITweakAutoMapper.hpp" #include "zeus/CVector3f.hpp" -namespace DataSpec::DNAMP1 -{ -struct CTweakAutoMapper final : public ITweakAutoMapper -{ - AT_DECL_DNA_YAML - Value x4_24_showOneMiniMapArea; - Value x4_25_; - Value x4_26_scaleMoveSpeedWithCamDist; - Value x8_camDist; - Value xc_minCamDist; - Value x10_maxCamDist; - Value x14_minCamRotateX; - Value x18_maxCamRotateX; - Value x1c_camAngle; - Value x20_; - DNAColor x24_automapperWidgetColor; - Value x28_miniCamDist; - Value x2c_miniCamXAngle; - Value x30_miniCamAngle; - Value x34_; - DNAColor x38_automapperWidgetMiniColor; - DNAColor x3c_surfColorVisited; - DNAColor x40_outlineColorVisited; - DNAColor x44_surfColorUnvisited; - DNAColor x48_outlineColorUnvisited; - DNAColor x4c_surfaceSelectColorVisited; - DNAColor x50_outlineSelectColorVisited; - Value x54_mapSurfaceNormColorLinear; - Value x58_mapSurfaceNormColorConstant; - Value x5c_; - float x60_ = 0.4f; - Value x64_openMapScreenTime; - Value x68_closeMapScreenTime; - Value x6c_hintPanTime; - Value x70_zoomUnitsPerFrame; - Value x74_rotateDegPerFrame; - Value x78_baseMapScreenCameraMoveSpeed; - DNAColor x7c_surfaceSelectColorUnvisited; - DNAColor x80_outlineSelectColorUnvisited; - Value x84_miniAlphaSurfaceVisited; - Value x88_alphaSurfaceVisited; - Value x8c_miniAlphaOutlineVisited; - Value x90_alphaOutlineVisited; - Value x94_miniAlphaSurfaceUnvisited; - Value x98_alphaSurfaceUnvisited; - Value x9c_miniAlphaOutlineUnvisited; - Value xa0_alphaOutlineUnvisited; - /* Originally 4 separate floats */ - Value xa4_doorCenter; - Value xb0_; - Value xb4_; - Value xb8_miniMapViewportWidth; - Value xbc_miniMapViewportHeight; - Value xc0_miniMapCamDistScale; - Value xc4_mapPlaneScaleX; - Value xc8_mapPlaneScaleZ; - Value xcc_; - Value xd0_universeCamDist; - Value xd4_minUniverseCamDist; - Value xd8_maxUniverseCamDist; - Value xdc_switchToFromUniverseTime; - Value xe0_camPanUnitsPerFrame; - Value xe4_automapperScaleX; - Value xe8_automapperScaleZ; - Value xec_camVerticalOffset; - DNAColor xf0_miniMapSamusModColor; - DNAColor xf4_areaFlashPulseColor; - DNAColor xf8_; - DNAColor xfc_; - Value x100_doorColorCount; - Vector x104_doorColors; - DNAColor x118_doorBorderColor; - DNAColor x11c_openDoorColor; +namespace DataSpec::DNAMP1 { +struct CTweakAutoMapper final : public ITweakAutoMapper { + AT_DECL_DNA_YAML + Value x4_24_showOneMiniMapArea; + Value x4_25_; + Value x4_26_scaleMoveSpeedWithCamDist; + Value x8_camDist; + Value xc_minCamDist; + Value x10_maxCamDist; + Value x14_minCamRotateX; + Value x18_maxCamRotateX; + Value x1c_camAngle; + Value x20_; + DNAColor x24_automapperWidgetColor; + Value x28_miniCamDist; + Value x2c_miniCamXAngle; + Value x30_miniCamAngle; + Value x34_; + DNAColor x38_automapperWidgetMiniColor; + DNAColor x3c_surfColorVisited; + DNAColor x40_outlineColorVisited; + DNAColor x44_surfColorUnvisited; + DNAColor x48_outlineColorUnvisited; + DNAColor x4c_surfaceSelectColorVisited; + DNAColor x50_outlineSelectColorVisited; + Value x54_mapSurfaceNormColorLinear; + Value x58_mapSurfaceNormColorConstant; + Value x5c_; + float x60_ = 0.4f; + Value x64_openMapScreenTime; + Value x68_closeMapScreenTime; + Value x6c_hintPanTime; + Value x70_zoomUnitsPerFrame; + Value x74_rotateDegPerFrame; + Value x78_baseMapScreenCameraMoveSpeed; + DNAColor x7c_surfaceSelectColorUnvisited; + DNAColor x80_outlineSelectColorUnvisited; + Value x84_miniAlphaSurfaceVisited; + Value x88_alphaSurfaceVisited; + Value x8c_miniAlphaOutlineVisited; + Value x90_alphaOutlineVisited; + Value x94_miniAlphaSurfaceUnvisited; + Value x98_alphaSurfaceUnvisited; + Value x9c_miniAlphaOutlineUnvisited; + Value xa0_alphaOutlineUnvisited; + /* Originally 4 separate floats */ + Value xa4_doorCenter; + Value xb0_; + Value xb4_; + Value xb8_miniMapViewportWidth; + Value xbc_miniMapViewportHeight; + Value xc0_miniMapCamDistScale; + Value xc4_mapPlaneScaleX; + Value xc8_mapPlaneScaleZ; + Value xcc_; + Value xd0_universeCamDist; + Value xd4_minUniverseCamDist; + Value xd8_maxUniverseCamDist; + Value xdc_switchToFromUniverseTime; + Value xe0_camPanUnitsPerFrame; + Value xe4_automapperScaleX; + Value xe8_automapperScaleZ; + Value xec_camVerticalOffset; + DNAColor xf0_miniMapSamusModColor; + DNAColor xf4_areaFlashPulseColor; + DNAColor xf8_; + DNAColor xfc_; + Value x100_doorColorCount; + Vector x104_doorColors; + DNAColor x118_doorBorderColor; + DNAColor x11c_openDoorColor; - CTweakAutoMapper() = default; - CTweakAutoMapper(athena::io::IStreamReader& r) { this->read(r); } - bool GetShowOneMiniMapArea() const { return x4_24_showOneMiniMapArea; } - bool GetScaleMoveSpeedWithCamDist() const { return x4_26_scaleMoveSpeedWithCamDist; } - float GetCamDist() const { return x8_camDist; } - float GetMinCamDist() const { return xc_minCamDist; } - float GetMaxCamDist() const { return x10_maxCamDist; } - float GetMinCamRotateX() const { return x14_minCamRotateX; } - float GetMaxCamRotateX() const { return x18_maxCamRotateX; } - float GetCamAngle() const { return x1c_camAngle; } - const zeus::CColor& GetAutomapperWidgetColor() const { return x24_automapperWidgetColor; } - float GetMiniCamDist() const { return x28_miniCamDist; } - float GetMiniCamXAngle() const { return x2c_miniCamXAngle; } - float GetMiniCamAngle() const { return x30_miniCamAngle; } - const zeus::CColor& GetAutomapperWidgetMiniColor() const { return x38_automapperWidgetMiniColor; } - const zeus::CColor& GetSurfaceVisitedColor() const { return x3c_surfColorVisited; } - const zeus::CColor& GetOutlineVisitedColor() const { return x40_outlineColorVisited; } - const zeus::CColor& GetSurfaceUnvisitedColor() const { return x44_surfColorUnvisited; } - const zeus::CColor& GetOutlineUnvisitedColor() const { return x48_outlineColorUnvisited; } - const zeus::CColor& GetSurfaceSelectVisitedColor() const { return x4c_surfaceSelectColorVisited; } - const zeus::CColor& GetOutlineSelectVisitedColor() const { return x50_outlineSelectColorVisited; } - float GetMapSurfaceNormColorLinear() const { return x54_mapSurfaceNormColorLinear; } - float GetMapSurfaceNormColorConstant() const { return x58_mapSurfaceNormColorConstant; } - float GetOpenMapScreenTime() const { return x64_openMapScreenTime; } - float GetCloseMapScreenTime() const { return x68_closeMapScreenTime; } - float GetHintPanTime() const { return x6c_hintPanTime; } - float GetCamZoomUnitsPerFrame() const { return x70_zoomUnitsPerFrame; } - float GetCamRotateDegreesPerFrame() const { return x74_rotateDegPerFrame; } - float GetBaseMapScreenCameraMoveSpeed() const { return x78_baseMapScreenCameraMoveSpeed; } - const zeus::CColor& GetSurfaceSelectUnvisitedColor() const { return x7c_surfaceSelectColorUnvisited; } - const zeus::CColor& GetOutlineSelectUnvisitedColor() const { return x80_outlineSelectColorUnvisited; } - float GetMiniAlphaSurfaceVisited() const { return x84_miniAlphaSurfaceVisited; } - float GetAlphaSurfaceVisited() const { return x88_alphaSurfaceVisited; } - float GetMiniAlphaOutlineVisited() const { return x8c_miniAlphaOutlineVisited; } - float GetAlphaOutlineVisited() const { return x90_alphaOutlineVisited; } - float GetMiniAlphaSurfaceUnvisited() const { return x94_miniAlphaSurfaceUnvisited; } - float GetAlphaSurfaceUnvisited() const { return x98_alphaSurfaceUnvisited; } - float GetMiniAlphaOutlineUnvisited() const { return x9c_miniAlphaOutlineUnvisited; } - float GetAlphaOutlineUnvisited() const { return xa0_alphaOutlineUnvisited; } - const zeus::CVector3f& GetDoorCenter() const { return xa4_doorCenter; } - float GetMiniMapViewportWidth() const { return xb8_miniMapViewportWidth; } - float GetMiniMapViewportHeight() const { return xbc_miniMapViewportHeight; } - float GetMiniMapCamDistScale() const { return xc0_miniMapCamDistScale; } - float GetMapPlaneScaleX() const { return xc4_mapPlaneScaleX; } - float GetMapPlaneScaleZ() const { return xc8_mapPlaneScaleZ; } - float GetUniverseCamDist() const { return xd0_universeCamDist; } - float GetMinUniverseCamDist() const { return xd4_minUniverseCamDist; } - float GetMaxUniverseCamDist() const { return xd8_maxUniverseCamDist; } - float GetSwitchToFromUniverseTime() const { return xdc_switchToFromUniverseTime; } - float GetCamPanUnitsPerFrame() const { return xe0_camPanUnitsPerFrame; } - float GetAutomapperScaleX() const { return xe4_automapperScaleX; } - float GetAutomapperScaleZ() const { return xe8_automapperScaleZ; } - float GetCamVerticalOffset() const { return xec_camVerticalOffset; } - const zeus::CColor& GetMiniMapSamusModColor() const { return xf0_miniMapSamusModColor; } - const zeus::CColor& GetAreaFlashPulseColor() const { return xf4_areaFlashPulseColor; } - const zeus::CColor& GetDoorColor(int idx) const { return x104_doorColors[idx]; } - const zeus::CColor& GetOpenDoorColor() const { return x11c_openDoorColor; } + CTweakAutoMapper() = default; + CTweakAutoMapper(athena::io::IStreamReader& r) { this->read(r); } + bool GetShowOneMiniMapArea() const { return x4_24_showOneMiniMapArea; } + bool GetScaleMoveSpeedWithCamDist() const { return x4_26_scaleMoveSpeedWithCamDist; } + float GetCamDist() const { return x8_camDist; } + float GetMinCamDist() const { return xc_minCamDist; } + float GetMaxCamDist() const { return x10_maxCamDist; } + float GetMinCamRotateX() const { return x14_minCamRotateX; } + float GetMaxCamRotateX() const { return x18_maxCamRotateX; } + float GetCamAngle() const { return x1c_camAngle; } + const zeus::CColor& GetAutomapperWidgetColor() const { return x24_automapperWidgetColor; } + float GetMiniCamDist() const { return x28_miniCamDist; } + float GetMiniCamXAngle() const { return x2c_miniCamXAngle; } + float GetMiniCamAngle() const { return x30_miniCamAngle; } + const zeus::CColor& GetAutomapperWidgetMiniColor() const { return x38_automapperWidgetMiniColor; } + const zeus::CColor& GetSurfaceVisitedColor() const { return x3c_surfColorVisited; } + const zeus::CColor& GetOutlineVisitedColor() const { return x40_outlineColorVisited; } + const zeus::CColor& GetSurfaceUnvisitedColor() const { return x44_surfColorUnvisited; } + const zeus::CColor& GetOutlineUnvisitedColor() const { return x48_outlineColorUnvisited; } + const zeus::CColor& GetSurfaceSelectVisitedColor() const { return x4c_surfaceSelectColorVisited; } + const zeus::CColor& GetOutlineSelectVisitedColor() const { return x50_outlineSelectColorVisited; } + float GetMapSurfaceNormColorLinear() const { return x54_mapSurfaceNormColorLinear; } + float GetMapSurfaceNormColorConstant() const { return x58_mapSurfaceNormColorConstant; } + float GetOpenMapScreenTime() const { return x64_openMapScreenTime; } + float GetCloseMapScreenTime() const { return x68_closeMapScreenTime; } + float GetHintPanTime() const { return x6c_hintPanTime; } + float GetCamZoomUnitsPerFrame() const { return x70_zoomUnitsPerFrame; } + float GetCamRotateDegreesPerFrame() const { return x74_rotateDegPerFrame; } + float GetBaseMapScreenCameraMoveSpeed() const { return x78_baseMapScreenCameraMoveSpeed; } + const zeus::CColor& GetSurfaceSelectUnvisitedColor() const { return x7c_surfaceSelectColorUnvisited; } + const zeus::CColor& GetOutlineSelectUnvisitedColor() const { return x80_outlineSelectColorUnvisited; } + float GetMiniAlphaSurfaceVisited() const { return x84_miniAlphaSurfaceVisited; } + float GetAlphaSurfaceVisited() const { return x88_alphaSurfaceVisited; } + float GetMiniAlphaOutlineVisited() const { return x8c_miniAlphaOutlineVisited; } + float GetAlphaOutlineVisited() const { return x90_alphaOutlineVisited; } + float GetMiniAlphaSurfaceUnvisited() const { return x94_miniAlphaSurfaceUnvisited; } + float GetAlphaSurfaceUnvisited() const { return x98_alphaSurfaceUnvisited; } + float GetMiniAlphaOutlineUnvisited() const { return x9c_miniAlphaOutlineUnvisited; } + float GetAlphaOutlineUnvisited() const { return xa0_alphaOutlineUnvisited; } + const zeus::CVector3f& GetDoorCenter() const { return xa4_doorCenter; } + float GetMiniMapViewportWidth() const { return xb8_miniMapViewportWidth; } + float GetMiniMapViewportHeight() const { return xbc_miniMapViewportHeight; } + float GetMiniMapCamDistScale() const { return xc0_miniMapCamDistScale; } + float GetMapPlaneScaleX() const { return xc4_mapPlaneScaleX; } + float GetMapPlaneScaleZ() const { return xc8_mapPlaneScaleZ; } + float GetUniverseCamDist() const { return xd0_universeCamDist; } + float GetMinUniverseCamDist() const { return xd4_minUniverseCamDist; } + float GetMaxUniverseCamDist() const { return xd8_maxUniverseCamDist; } + float GetSwitchToFromUniverseTime() const { return xdc_switchToFromUniverseTime; } + float GetCamPanUnitsPerFrame() const { return xe0_camPanUnitsPerFrame; } + float GetAutomapperScaleX() const { return xe4_automapperScaleX; } + float GetAutomapperScaleZ() const { return xe8_automapperScaleZ; } + float GetCamVerticalOffset() const { return xec_camVerticalOffset; } + const zeus::CColor& GetMiniMapSamusModColor() const { return xf0_miniMapSamusModColor; } + const zeus::CColor& GetAreaFlashPulseColor() const { return xf4_areaFlashPulseColor; } + const zeus::CColor& GetDoorColor(int idx) const { return x104_doorColors[idx]; } + const zeus::CColor& GetOpenDoorColor() const { return x11c_openDoorColor; } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakBall.cpp b/DataSpec/DNAMP1/Tweaks/CTweakBall.cpp index 06c0b5059..ccc4c0440 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakBall.cpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakBall.cpp @@ -1,457 +1,452 @@ #include "CTweakBall.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template <> -void CTweakBall::Enumerate(typename Read::StreamT& __dna_reader) -{ - /* x4_maxTranslationAcceleration[0] */ - x4_maxTranslationAcceleration[0] = __dna_reader.readFloatBig(); - /* x4_maxTranslationAcceleration[1] */ - x4_maxTranslationAcceleration[1] = __dna_reader.readFloatBig(); - /* x4_maxTranslationAcceleration[2] */ - x4_maxTranslationAcceleration[2] = __dna_reader.readFloatBig(); - /* x4_maxTranslationAcceleration[3] */ - x4_maxTranslationAcceleration[3] = __dna_reader.readFloatBig(); - /* x4_maxTranslationAcceleration[4] */ - x4_maxTranslationAcceleration[4] = __dna_reader.readFloatBig(); - /* x4_maxTranslationAcceleration[5] */ - x4_maxTranslationAcceleration[5] = __dna_reader.readFloatBig(); - /* x4_maxTranslationAcceleration[6] */ - x4_maxTranslationAcceleration[6] = __dna_reader.readFloatBig(); - /* x4_maxTranslationAcceleration[7] */ - x4_maxTranslationAcceleration[7] = __dna_reader.readFloatBig(); - /* x24_translationFriction[0] */ - x24_translationFriction[0] = __dna_reader.readFloatBig(); - /* x24_translationFriction[1] */ - x24_translationFriction[1] = __dna_reader.readFloatBig(); - /* x24_translationFriction[2] */ - x24_translationFriction[2] = __dna_reader.readFloatBig(); - /* x24_translationFriction[3] */ - x24_translationFriction[3] = __dna_reader.readFloatBig(); - /* x24_translationFriction[4] */ - x24_translationFriction[4] = __dna_reader.readFloatBig(); - /* x24_translationFriction[5] */ - x24_translationFriction[5] = __dna_reader.readFloatBig(); - /* x24_translationFriction[6] */ - x24_translationFriction[6] = __dna_reader.readFloatBig(); - /* x24_translationFriction[7] */ - x24_translationFriction[7] = __dna_reader.readFloatBig(); - /* x44_translationMaxSpeed[0] */ - x44_translationMaxSpeed[0] = __dna_reader.readFloatBig(); - /* x44_translationMaxSpeed[1] */ - x44_translationMaxSpeed[1] = __dna_reader.readFloatBig(); - /* x44_translationMaxSpeed[2] */ - x44_translationMaxSpeed[2] = __dna_reader.readFloatBig(); - /* x44_translationMaxSpeed[3] */ - x44_translationMaxSpeed[3] = __dna_reader.readFloatBig(); - /* x44_translationMaxSpeed[4] */ - x44_translationMaxSpeed[4] = __dna_reader.readFloatBig(); - /* x44_translationMaxSpeed[5] */ - x44_translationMaxSpeed[5] = __dna_reader.readFloatBig(); - /* x44_translationMaxSpeed[6] */ - x44_translationMaxSpeed[6] = __dna_reader.readFloatBig(); - /* x44_translationMaxSpeed[7] */ - x44_translationMaxSpeed[7] = __dna_reader.readFloatBig(); - /* x64_ */ - x64_ = __dna_reader.readFloatBig(); - /* x68_ */ - x68_ = __dna_reader.readFloatBig(); - /* x6c_ */ - x6c_ = __dna_reader.readFloatBig(); - /* x70_ */ - x70_ = __dna_reader.readFloatBig(); - /* xc4_ballForwardBrakingAcceleration[0] */ - xc4_ballForwardBrakingAcceleration[0] = __dna_reader.readFloatBig(); - /* xc4_ballForwardBrakingAcceleration[1] */ - xc4_ballForwardBrakingAcceleration[1] = __dna_reader.readFloatBig(); - /* xc4_ballForwardBrakingAcceleration[2] */ - xc4_ballForwardBrakingAcceleration[2] = __dna_reader.readFloatBig(); - /* xc4_ballForwardBrakingAcceleration[3] */ - xc4_ballForwardBrakingAcceleration[3] = __dna_reader.readFloatBig(); - /* xc4_ballForwardBrakingAcceleration[4] */ - xc4_ballForwardBrakingAcceleration[4] = __dna_reader.readFloatBig(); - /* xc4_ballForwardBrakingAcceleration[5] */ - xc4_ballForwardBrakingAcceleration[5] = __dna_reader.readFloatBig(); - /* xc4_ballForwardBrakingAcceleration[6] */ - xc4_ballForwardBrakingAcceleration[6] = __dna_reader.readFloatBig(); - /* xc4_ballForwardBrakingAcceleration[7] */ - xc4_ballForwardBrakingAcceleration[7] = __dna_reader.readFloatBig(); - /* xe4_ballGravity */ - xe4_ballGravity = __dna_reader.readFloatBig(); - /* xe8_ballWaterGravity */ - xe8_ballWaterGravity = __dna_reader.readFloatBig(); - /* x14c_ */ - x14c_ = __dna_reader.readFloatBig(); - /* x150_ */ - x150_ = __dna_reader.readFloatBig(); - /* x158_ */ - x158_ = __dna_reader.readFloatBig(); - /* x1dc_minimumAlignmentSpeed */ - x1dc_minimumAlignmentSpeed = __dna_reader.readFloatBig(); - /* x1e0_tireness */ - x1e0_tireness = __dna_reader.readFloatBig(); - /* x1ec_maxLeanAngle */ - x1ec_maxLeanAngle = __dna_reader.readFloatBig(); - /* x1f0_tireToMarbleThresholdSpeed */ - x1f0_tireToMarbleThresholdSpeed = __dna_reader.readFloatBig(); - /* x1f4_marbleToTireThresholdSpeed */ - x1f4_marbleToTireThresholdSpeed = __dna_reader.readFloatBig(); - /* x1f8_forceToLeanGain */ - x1f8_forceToLeanGain = __dna_reader.readFloatBig(); - /* x1fc_leanTrackingGain */ - x1fc_leanTrackingGain = __dna_reader.readFloatBig(); - /* x74_ballCameraAnglePerSecond */ - x74_ballCameraAnglePerSecond = __dna_reader.readFloatBig(); - /* x78_ballCameraOffset */ - x78_ballCameraOffset = __dna_reader.readVec3fBig(); - /* x84_ballCameraMinSpeedDistance */ - x84_ballCameraMinSpeedDistance = __dna_reader.readFloatBig(); - /* x88_ballCameraMaxSpeedDistance */ - x88_ballCameraMaxSpeedDistance = __dna_reader.readFloatBig(); - /* x8c_ballCameraBackwardsDistance */ - x8c_ballCameraBackwardsDistance = __dna_reader.readFloatBig(); - /* x90_ */ - x90_ = __dna_reader.readFloatBig(); - /* x94_ballCameraSpringConstant */ - x94_ballCameraSpringConstant = __dna_reader.readFloatBig(); - /* x98_ballCameraSpringMax */ - x98_ballCameraSpringMax = __dna_reader.readFloatBig(); - /* x9c_ballCameraSpringTardis */ - x9c_ballCameraSpringTardis = __dna_reader.readFloatBig(); - /* xa0_ballCameraCentroidSpringConstant */ - xa0_ballCameraCentroidSpringConstant = __dna_reader.readFloatBig(); - /* xa4_ballCameraCentroidSpringMax */ - xa4_ballCameraCentroidSpringMax = __dna_reader.readFloatBig(); - /* xa8_ballCameraCentroidSpringTardis */ - xa8_ballCameraCentroidSpringTardis = __dna_reader.readFloatBig(); - /* xac_ballCameraCentroidDistanceSpringConstant */ - xac_ballCameraCentroidDistanceSpringConstant = __dna_reader.readFloatBig(); - /* xb0_ballCameraCentroidDistanceSpringMax */ - xb0_ballCameraCentroidDistanceSpringMax = __dna_reader.readFloatBig(); - /* xb4_ballCameraCentroidDistanceSpringTardis */ - xb4_ballCameraCentroidDistanceSpringTardis = __dna_reader.readFloatBig(); - /* xb8_ballCameraLookAtSpringConstant */ - xb8_ballCameraLookAtSpringConstant = __dna_reader.readFloatBig(); - /* xbc_ballCameraLookAtSpringMax */ - xbc_ballCameraLookAtSpringMax = __dna_reader.readFloatBig(); - /* xc0_ballCameraLookAtSpringTardis */ - xc0_ballCameraLookAtSpringTardis = __dna_reader.readFloatBig(); - /* x154_ */ - x154_ = __dna_reader.readFloatBig(); - /* x15c_ */ - x15c_ = __dna_reader.readFloatBig(); - /* x160_ */ - x160_ = __dna_reader.readFloatBig(); - /* x164_ */ - x164_ = __dna_reader.readFloatBig(); - /* x168_ */ - x168_ = __dna_reader.readFloatBig(); - /* x16c_ */ - x16c_ = __dna_reader.readFloatBig(); - /* x170_conservativeDoorCamDistance */ - x170_conservativeDoorCamDistance = __dna_reader.readFloatBig(); - /* x174_ */ - x174_ = __dna_reader.readFloatBig(); - /* x178_ballCameraChaseElevation */ - x178_ballCameraChaseElevation = __dna_reader.readFloatBig(); - /* x17c_ballCameraChaseDampenAngle */ - x17c_ballCameraChaseDampenAngle = __dna_reader.readFloatBig(); - /* x180_ballCameraChaseDistance */ - x180_ballCameraChaseDistance = __dna_reader.readFloatBig(); - /* x184_ballCameraChaseYawSpeed */ - x184_ballCameraChaseYawSpeed = __dna_reader.readFloatBig(); - /* x188_ballCameraChaseAnglePerSecond */ - x188_ballCameraChaseAnglePerSecond = __dna_reader.readFloatBig(); - /* x18c_ballCameraChaseLookAtOffset */ - x18c_ballCameraChaseLookAtOffset = __dna_reader.readVec3fBig(); - /* x198_ballCameraChaseSpringConstant */ - x198_ballCameraChaseSpringConstant = __dna_reader.readFloatBig(); - /* x19c_ballCameraChaseSpringMax */ - x19c_ballCameraChaseSpringMax = __dna_reader.readFloatBig(); - /* x1a0_ballCameraChaseSpringTardis */ - x1a0_ballCameraChaseSpringTardis = __dna_reader.readFloatBig(); - /* x1a4_ballCameraBoostElevation */ - x1a4_ballCameraBoostElevation = __dna_reader.readFloatBig(); - /* x1a8_ballCameraBoostDampenAngle */ - x1a8_ballCameraBoostDampenAngle = __dna_reader.readFloatBig(); - /* x1ac_ballCameraBoostDistance */ - x1ac_ballCameraBoostDistance = __dna_reader.readFloatBig(); - /* x1b0_ballCameraBoostYawSpeed */ - x1b0_ballCameraBoostYawSpeed = __dna_reader.readFloatBig(); - /* x1b4_ballCameraBoostAnglePerSecond */ - x1b4_ballCameraBoostAnglePerSecond = __dna_reader.readFloatBig(); - /* x1b8_ballCameraBoostLookAtOffset */ - x1b8_ballCameraBoostLookAtOffset = __dna_reader.readVec3fBig(); - /* x1c4_ballCameraBoostSpringConstant */ - x1c4_ballCameraBoostSpringConstant = __dna_reader.readFloatBig(); - /* x1c8_ballCameraBoostSpringMax */ - x1c8_ballCameraBoostSpringMax = __dna_reader.readFloatBig(); - /* x1cc_ballCameraBoostSpringTardis */ - x1cc_ballCameraBoostSpringTardis = __dna_reader.readFloatBig(); - /* x1d0_ballCameraControlDistance */ - x1d0_ballCameraControlDistance = __dna_reader.readFloatBig(); - /* x1d4_ */ - x1d4_ = __dna_reader.readFloatBig(); - /* x1d8_ */ - x1d8_ = __dna_reader.readFloatBig(); - /* x1e4_leftStickDivisor */ - x1e4_leftStickDivisor = __dna_reader.readFloatBig(); - /* x1e8_rightStickDivisor */ - x1e8_rightStickDivisor = __dna_reader.readFloatBig(); - /* x200_ */ - x200_ = __dna_reader.readFloatBig(); - /* x204_ballTouchRadius */ - x204_ballTouchRadius = __dna_reader.readFloatBig(); - /* x20c_boostBallDrainTime */ - x20c_boostBallDrainTime = __dna_reader.readFloatBig(); - /* x218_boostBallMinChargeTime */ - x218_boostBallMinChargeTime = __dna_reader.readFloatBig(); - /* x21c_boostBallMinRelativeSpeedForDamage */ - x21c_boostBallMinRelativeSpeedForDamage = __dna_reader.readFloatBig(); - /* x220_boostBallChargeTime0 */ - x220_boostBallChargeTime0 = __dna_reader.readFloatBig(); - /* x224_boostBallChargeTime1 */ - x224_boostBallChargeTime1 = __dna_reader.readFloatBig(); - /* x210_boostBallMaxChargeTime */ - x228_boostBallChargeTime2 = x210_boostBallMaxChargeTime = __dna_reader.readFloatBig(); - /* x22c_boostBallIncrementalSpeed0 */ - x22c_boostBallIncrementalSpeed0 = __dna_reader.readFloatBig(); - /* x230_boostBallIncrementalSpeed1 */ - x230_boostBallIncrementalSpeed1 = __dna_reader.readFloatBig(); - /* x234_boostBallIncrementalSpeed2 */ - x234_boostBallIncrementalSpeed2 = __dna_reader.readFloatBig(); +void CTweakBall::Enumerate(typename Read::StreamT& __dna_reader) { + /* x4_maxTranslationAcceleration[0] */ + x4_maxTranslationAcceleration[0] = __dna_reader.readFloatBig(); + /* x4_maxTranslationAcceleration[1] */ + x4_maxTranslationAcceleration[1] = __dna_reader.readFloatBig(); + /* x4_maxTranslationAcceleration[2] */ + x4_maxTranslationAcceleration[2] = __dna_reader.readFloatBig(); + /* x4_maxTranslationAcceleration[3] */ + x4_maxTranslationAcceleration[3] = __dna_reader.readFloatBig(); + /* x4_maxTranslationAcceleration[4] */ + x4_maxTranslationAcceleration[4] = __dna_reader.readFloatBig(); + /* x4_maxTranslationAcceleration[5] */ + x4_maxTranslationAcceleration[5] = __dna_reader.readFloatBig(); + /* x4_maxTranslationAcceleration[6] */ + x4_maxTranslationAcceleration[6] = __dna_reader.readFloatBig(); + /* x4_maxTranslationAcceleration[7] */ + x4_maxTranslationAcceleration[7] = __dna_reader.readFloatBig(); + /* x24_translationFriction[0] */ + x24_translationFriction[0] = __dna_reader.readFloatBig(); + /* x24_translationFriction[1] */ + x24_translationFriction[1] = __dna_reader.readFloatBig(); + /* x24_translationFriction[2] */ + x24_translationFriction[2] = __dna_reader.readFloatBig(); + /* x24_translationFriction[3] */ + x24_translationFriction[3] = __dna_reader.readFloatBig(); + /* x24_translationFriction[4] */ + x24_translationFriction[4] = __dna_reader.readFloatBig(); + /* x24_translationFriction[5] */ + x24_translationFriction[5] = __dna_reader.readFloatBig(); + /* x24_translationFriction[6] */ + x24_translationFriction[6] = __dna_reader.readFloatBig(); + /* x24_translationFriction[7] */ + x24_translationFriction[7] = __dna_reader.readFloatBig(); + /* x44_translationMaxSpeed[0] */ + x44_translationMaxSpeed[0] = __dna_reader.readFloatBig(); + /* x44_translationMaxSpeed[1] */ + x44_translationMaxSpeed[1] = __dna_reader.readFloatBig(); + /* x44_translationMaxSpeed[2] */ + x44_translationMaxSpeed[2] = __dna_reader.readFloatBig(); + /* x44_translationMaxSpeed[3] */ + x44_translationMaxSpeed[3] = __dna_reader.readFloatBig(); + /* x44_translationMaxSpeed[4] */ + x44_translationMaxSpeed[4] = __dna_reader.readFloatBig(); + /* x44_translationMaxSpeed[5] */ + x44_translationMaxSpeed[5] = __dna_reader.readFloatBig(); + /* x44_translationMaxSpeed[6] */ + x44_translationMaxSpeed[6] = __dna_reader.readFloatBig(); + /* x44_translationMaxSpeed[7] */ + x44_translationMaxSpeed[7] = __dna_reader.readFloatBig(); + /* x64_ */ + x64_ = __dna_reader.readFloatBig(); + /* x68_ */ + x68_ = __dna_reader.readFloatBig(); + /* x6c_ */ + x6c_ = __dna_reader.readFloatBig(); + /* x70_ */ + x70_ = __dna_reader.readFloatBig(); + /* xc4_ballForwardBrakingAcceleration[0] */ + xc4_ballForwardBrakingAcceleration[0] = __dna_reader.readFloatBig(); + /* xc4_ballForwardBrakingAcceleration[1] */ + xc4_ballForwardBrakingAcceleration[1] = __dna_reader.readFloatBig(); + /* xc4_ballForwardBrakingAcceleration[2] */ + xc4_ballForwardBrakingAcceleration[2] = __dna_reader.readFloatBig(); + /* xc4_ballForwardBrakingAcceleration[3] */ + xc4_ballForwardBrakingAcceleration[3] = __dna_reader.readFloatBig(); + /* xc4_ballForwardBrakingAcceleration[4] */ + xc4_ballForwardBrakingAcceleration[4] = __dna_reader.readFloatBig(); + /* xc4_ballForwardBrakingAcceleration[5] */ + xc4_ballForwardBrakingAcceleration[5] = __dna_reader.readFloatBig(); + /* xc4_ballForwardBrakingAcceleration[6] */ + xc4_ballForwardBrakingAcceleration[6] = __dna_reader.readFloatBig(); + /* xc4_ballForwardBrakingAcceleration[7] */ + xc4_ballForwardBrakingAcceleration[7] = __dna_reader.readFloatBig(); + /* xe4_ballGravity */ + xe4_ballGravity = __dna_reader.readFloatBig(); + /* xe8_ballWaterGravity */ + xe8_ballWaterGravity = __dna_reader.readFloatBig(); + /* x14c_ */ + x14c_ = __dna_reader.readFloatBig(); + /* x150_ */ + x150_ = __dna_reader.readFloatBig(); + /* x158_ */ + x158_ = __dna_reader.readFloatBig(); + /* x1dc_minimumAlignmentSpeed */ + x1dc_minimumAlignmentSpeed = __dna_reader.readFloatBig(); + /* x1e0_tireness */ + x1e0_tireness = __dna_reader.readFloatBig(); + /* x1ec_maxLeanAngle */ + x1ec_maxLeanAngle = __dna_reader.readFloatBig(); + /* x1f0_tireToMarbleThresholdSpeed */ + x1f0_tireToMarbleThresholdSpeed = __dna_reader.readFloatBig(); + /* x1f4_marbleToTireThresholdSpeed */ + x1f4_marbleToTireThresholdSpeed = __dna_reader.readFloatBig(); + /* x1f8_forceToLeanGain */ + x1f8_forceToLeanGain = __dna_reader.readFloatBig(); + /* x1fc_leanTrackingGain */ + x1fc_leanTrackingGain = __dna_reader.readFloatBig(); + /* x74_ballCameraAnglePerSecond */ + x74_ballCameraAnglePerSecond = __dna_reader.readFloatBig(); + /* x78_ballCameraOffset */ + x78_ballCameraOffset = __dna_reader.readVec3fBig(); + /* x84_ballCameraMinSpeedDistance */ + x84_ballCameraMinSpeedDistance = __dna_reader.readFloatBig(); + /* x88_ballCameraMaxSpeedDistance */ + x88_ballCameraMaxSpeedDistance = __dna_reader.readFloatBig(); + /* x8c_ballCameraBackwardsDistance */ + x8c_ballCameraBackwardsDistance = __dna_reader.readFloatBig(); + /* x90_ */ + x90_ = __dna_reader.readFloatBig(); + /* x94_ballCameraSpringConstant */ + x94_ballCameraSpringConstant = __dna_reader.readFloatBig(); + /* x98_ballCameraSpringMax */ + x98_ballCameraSpringMax = __dna_reader.readFloatBig(); + /* x9c_ballCameraSpringTardis */ + x9c_ballCameraSpringTardis = __dna_reader.readFloatBig(); + /* xa0_ballCameraCentroidSpringConstant */ + xa0_ballCameraCentroidSpringConstant = __dna_reader.readFloatBig(); + /* xa4_ballCameraCentroidSpringMax */ + xa4_ballCameraCentroidSpringMax = __dna_reader.readFloatBig(); + /* xa8_ballCameraCentroidSpringTardis */ + xa8_ballCameraCentroidSpringTardis = __dna_reader.readFloatBig(); + /* xac_ballCameraCentroidDistanceSpringConstant */ + xac_ballCameraCentroidDistanceSpringConstant = __dna_reader.readFloatBig(); + /* xb0_ballCameraCentroidDistanceSpringMax */ + xb0_ballCameraCentroidDistanceSpringMax = __dna_reader.readFloatBig(); + /* xb4_ballCameraCentroidDistanceSpringTardis */ + xb4_ballCameraCentroidDistanceSpringTardis = __dna_reader.readFloatBig(); + /* xb8_ballCameraLookAtSpringConstant */ + xb8_ballCameraLookAtSpringConstant = __dna_reader.readFloatBig(); + /* xbc_ballCameraLookAtSpringMax */ + xbc_ballCameraLookAtSpringMax = __dna_reader.readFloatBig(); + /* xc0_ballCameraLookAtSpringTardis */ + xc0_ballCameraLookAtSpringTardis = __dna_reader.readFloatBig(); + /* x154_ */ + x154_ = __dna_reader.readFloatBig(); + /* x15c_ */ + x15c_ = __dna_reader.readFloatBig(); + /* x160_ */ + x160_ = __dna_reader.readFloatBig(); + /* x164_ */ + x164_ = __dna_reader.readFloatBig(); + /* x168_ */ + x168_ = __dna_reader.readFloatBig(); + /* x16c_ */ + x16c_ = __dna_reader.readFloatBig(); + /* x170_conservativeDoorCamDistance */ + x170_conservativeDoorCamDistance = __dna_reader.readFloatBig(); + /* x174_ */ + x174_ = __dna_reader.readFloatBig(); + /* x178_ballCameraChaseElevation */ + x178_ballCameraChaseElevation = __dna_reader.readFloatBig(); + /* x17c_ballCameraChaseDampenAngle */ + x17c_ballCameraChaseDampenAngle = __dna_reader.readFloatBig(); + /* x180_ballCameraChaseDistance */ + x180_ballCameraChaseDistance = __dna_reader.readFloatBig(); + /* x184_ballCameraChaseYawSpeed */ + x184_ballCameraChaseYawSpeed = __dna_reader.readFloatBig(); + /* x188_ballCameraChaseAnglePerSecond */ + x188_ballCameraChaseAnglePerSecond = __dna_reader.readFloatBig(); + /* x18c_ballCameraChaseLookAtOffset */ + x18c_ballCameraChaseLookAtOffset = __dna_reader.readVec3fBig(); + /* x198_ballCameraChaseSpringConstant */ + x198_ballCameraChaseSpringConstant = __dna_reader.readFloatBig(); + /* x19c_ballCameraChaseSpringMax */ + x19c_ballCameraChaseSpringMax = __dna_reader.readFloatBig(); + /* x1a0_ballCameraChaseSpringTardis */ + x1a0_ballCameraChaseSpringTardis = __dna_reader.readFloatBig(); + /* x1a4_ballCameraBoostElevation */ + x1a4_ballCameraBoostElevation = __dna_reader.readFloatBig(); + /* x1a8_ballCameraBoostDampenAngle */ + x1a8_ballCameraBoostDampenAngle = __dna_reader.readFloatBig(); + /* x1ac_ballCameraBoostDistance */ + x1ac_ballCameraBoostDistance = __dna_reader.readFloatBig(); + /* x1b0_ballCameraBoostYawSpeed */ + x1b0_ballCameraBoostYawSpeed = __dna_reader.readFloatBig(); + /* x1b4_ballCameraBoostAnglePerSecond */ + x1b4_ballCameraBoostAnglePerSecond = __dna_reader.readFloatBig(); + /* x1b8_ballCameraBoostLookAtOffset */ + x1b8_ballCameraBoostLookAtOffset = __dna_reader.readVec3fBig(); + /* x1c4_ballCameraBoostSpringConstant */ + x1c4_ballCameraBoostSpringConstant = __dna_reader.readFloatBig(); + /* x1c8_ballCameraBoostSpringMax */ + x1c8_ballCameraBoostSpringMax = __dna_reader.readFloatBig(); + /* x1cc_ballCameraBoostSpringTardis */ + x1cc_ballCameraBoostSpringTardis = __dna_reader.readFloatBig(); + /* x1d0_ballCameraControlDistance */ + x1d0_ballCameraControlDistance = __dna_reader.readFloatBig(); + /* x1d4_ */ + x1d4_ = __dna_reader.readFloatBig(); + /* x1d8_ */ + x1d8_ = __dna_reader.readFloatBig(); + /* x1e4_leftStickDivisor */ + x1e4_leftStickDivisor = __dna_reader.readFloatBig(); + /* x1e8_rightStickDivisor */ + x1e8_rightStickDivisor = __dna_reader.readFloatBig(); + /* x200_ */ + x200_ = __dna_reader.readFloatBig(); + /* x204_ballTouchRadius */ + x204_ballTouchRadius = __dna_reader.readFloatBig(); + /* x20c_boostBallDrainTime */ + x20c_boostBallDrainTime = __dna_reader.readFloatBig(); + /* x218_boostBallMinChargeTime */ + x218_boostBallMinChargeTime = __dna_reader.readFloatBig(); + /* x21c_boostBallMinRelativeSpeedForDamage */ + x21c_boostBallMinRelativeSpeedForDamage = __dna_reader.readFloatBig(); + /* x220_boostBallChargeTime0 */ + x220_boostBallChargeTime0 = __dna_reader.readFloatBig(); + /* x224_boostBallChargeTime1 */ + x224_boostBallChargeTime1 = __dna_reader.readFloatBig(); + /* x210_boostBallMaxChargeTime */ + x228_boostBallChargeTime2 = x210_boostBallMaxChargeTime = __dna_reader.readFloatBig(); + /* x22c_boostBallIncrementalSpeed0 */ + x22c_boostBallIncrementalSpeed0 = __dna_reader.readFloatBig(); + /* x230_boostBallIncrementalSpeed1 */ + x230_boostBallIncrementalSpeed1 = __dna_reader.readFloatBig(); + /* x234_boostBallIncrementalSpeed2 */ + x234_boostBallIncrementalSpeed2 = __dna_reader.readFloatBig(); } template <> -void CTweakBall::Enumerate(typename Write::StreamT& __dna_writer) -{ - /* x4_maxTranslationAcceleration[0] */ - __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[0]); - /* x4_maxTranslationAcceleration[1] */ - __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[1]); - /* x4_maxTranslationAcceleration[2] */ - __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[2]); - /* x4_maxTranslationAcceleration[3] */ - __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[3]); - /* x4_maxTranslationAcceleration[4] */ - __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[4]); - /* x4_maxTranslationAcceleration[5] */ - __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[5]); - /* x4_maxTranslationAcceleration[6] */ - __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[6]); - /* x4_maxTranslationAcceleration[7] */ - __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[7]); - /* x24_translationFriction[0] */ - __dna_writer.writeFloatBig(x24_translationFriction[0]); - /* x24_translationFriction[1] */ - __dna_writer.writeFloatBig(x24_translationFriction[1]); - /* x24_translationFriction[2] */ - __dna_writer.writeFloatBig(x24_translationFriction[2]); - /* x24_translationFriction[3] */ - __dna_writer.writeFloatBig(x24_translationFriction[3]); - /* x24_translationFriction[4] */ - __dna_writer.writeFloatBig(x24_translationFriction[4]); - /* x24_translationFriction[5] */ - __dna_writer.writeFloatBig(x24_translationFriction[5]); - /* x24_translationFriction[6] */ - __dna_writer.writeFloatBig(x24_translationFriction[6]); - /* x24_translationFriction[7] */ - __dna_writer.writeFloatBig(x24_translationFriction[7]); - /* x44_translationMaxSpeed[0] */ - __dna_writer.writeFloatBig(x44_translationMaxSpeed[0]); - /* x44_translationMaxSpeed[1] */ - __dna_writer.writeFloatBig(x44_translationMaxSpeed[1]); - /* x44_translationMaxSpeed[2] */ - __dna_writer.writeFloatBig(x44_translationMaxSpeed[2]); - /* x44_translationMaxSpeed[3] */ - __dna_writer.writeFloatBig(x44_translationMaxSpeed[3]); - /* x44_translationMaxSpeed[4] */ - __dna_writer.writeFloatBig(x44_translationMaxSpeed[4]); - /* x44_translationMaxSpeed[5] */ - __dna_writer.writeFloatBig(x44_translationMaxSpeed[5]); - /* x44_translationMaxSpeed[6] */ - __dna_writer.writeFloatBig(x44_translationMaxSpeed[6]); - /* x44_translationMaxSpeed[7] */ - __dna_writer.writeFloatBig(x44_translationMaxSpeed[7]); - /* x64_ */ - __dna_writer.writeFloatBig(x64_); - /* x68_ */ - __dna_writer.writeFloatBig(x68_); - /* x6c_ */ - __dna_writer.writeFloatBig(x6c_); - /* x70_ */ - __dna_writer.writeFloatBig(x70_); - /* xc4_ballForwardBrakingAcceleration[0] */ - __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[0]); - /* xc4_ballForwardBrakingAcceleration[1] */ - __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[1]); - /* xc4_ballForwardBrakingAcceleration[2] */ - __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[2]); - /* xc4_ballForwardBrakingAcceleration[3] */ - __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[3]); - /* xc4_ballForwardBrakingAcceleration[4] */ - __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[4]); - /* xc4_ballForwardBrakingAcceleration[5] */ - __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[5]); - /* xc4_ballForwardBrakingAcceleration[6] */ - __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[6]); - /* xc4_ballForwardBrakingAcceleration[7] */ - __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[7]); - /* xe4_ballGravity */ - __dna_writer.writeFloatBig(xe4_ballGravity); - /* xe8_ballWaterGravity */ - __dna_writer.writeFloatBig(xe8_ballWaterGravity); - /* x14c_ */ - __dna_writer.writeFloatBig(x14c_); - /* x150_ */ - __dna_writer.writeFloatBig(x150_); - /* x158_ */ - __dna_writer.writeFloatBig(x158_); - /* x1dc_minimumAlignmentSpeed */ - __dna_writer.writeFloatBig(x1dc_minimumAlignmentSpeed); - /* x1e0_tireness */ - __dna_writer.writeFloatBig(x1e0_tireness); - /* x1ec_maxLeanAngle */ - __dna_writer.writeFloatBig(x1ec_maxLeanAngle); - /* x1f0_tireToMarbleThresholdSpeed */ - __dna_writer.writeFloatBig(x1f0_tireToMarbleThresholdSpeed); - /* x1f4_marbleToTireThresholdSpeed */ - __dna_writer.writeFloatBig(x1f4_marbleToTireThresholdSpeed); - /* x1f8_forceToLeanGain */ - __dna_writer.writeFloatBig(x1f8_forceToLeanGain); - /* x1fc_leanTrackingGain */ - __dna_writer.writeFloatBig(x1fc_leanTrackingGain); - /* x74_ballCameraAnglePerSecond */ - __dna_writer.writeFloatBig(x74_ballCameraAnglePerSecond); - /* x78_ballCameraOffset */ - __dna_writer.writeVec3fBig(x78_ballCameraOffset); - /* x84_ballCameraMinSpeedDistance */ - __dna_writer.writeFloatBig(x84_ballCameraMinSpeedDistance); - /* x88_ballCameraMaxSpeedDistance */ - __dna_writer.writeFloatBig(x88_ballCameraMaxSpeedDistance); - /* x8c_ballCameraBackwardsDistance */ - __dna_writer.writeFloatBig(x8c_ballCameraBackwardsDistance); - /* x90_ */ - __dna_writer.writeFloatBig(x90_); - /* x94_ballCameraSpringConstant */ - __dna_writer.writeFloatBig(x94_ballCameraSpringConstant); - /* x98_ballCameraSpringMax */ - __dna_writer.writeFloatBig(x98_ballCameraSpringMax); - /* x9c_ballCameraSpringTardis */ - __dna_writer.writeFloatBig(x9c_ballCameraSpringTardis); - /* xa0_ballCameraCentroidSpringConstant */ - __dna_writer.writeFloatBig(xa0_ballCameraCentroidSpringConstant); - /* xa4_ballCameraCentroidSpringMax */ - __dna_writer.writeFloatBig(xa4_ballCameraCentroidSpringMax); - /* xa8_ballCameraCentroidSpringTardis */ - __dna_writer.writeFloatBig(xa8_ballCameraCentroidSpringTardis); - /* xac_ballCameraCentroidDistanceSpringConstant */ - __dna_writer.writeFloatBig(xac_ballCameraCentroidDistanceSpringConstant); - /* xb0_ballCameraCentroidDistanceSpringMax */ - __dna_writer.writeFloatBig(xb0_ballCameraCentroidDistanceSpringMax); - /* xb4_ballCameraCentroidDistanceSpringTardis */ - __dna_writer.writeFloatBig(xb4_ballCameraCentroidDistanceSpringTardis); - /* xb8_ballCameraLookAtSpringConstant */ - __dna_writer.writeFloatBig(xb8_ballCameraLookAtSpringConstant); - /* xbc_ballCameraLookAtSpringMax */ - __dna_writer.writeFloatBig(xbc_ballCameraLookAtSpringMax); - /* xc0_ballCameraLookAtSpringTardis */ - __dna_writer.writeFloatBig(xc0_ballCameraLookAtSpringTardis); - /* x154_ */ - __dna_writer.writeFloatBig(x154_); - /* x15c_ */ - __dna_writer.writeFloatBig(x15c_); - /* x160_ */ - __dna_writer.writeFloatBig(x160_); - /* x164_ */ - __dna_writer.writeFloatBig(x164_); - /* x168_ */ - __dna_writer.writeFloatBig(x168_); - /* x16c_ */ - __dna_writer.writeFloatBig(x16c_); - /* x170_conservativeDoorCamDistance */ - __dna_writer.writeFloatBig(x170_conservativeDoorCamDistance); - /* x174_ */ - __dna_writer.writeFloatBig(x174_); - /* x178_ballCameraChaseElevation */ - __dna_writer.writeFloatBig(x178_ballCameraChaseElevation); - /* x17c_ballCameraChaseDampenAngle */ - __dna_writer.writeFloatBig(x17c_ballCameraChaseDampenAngle); - /* x180_ballCameraChaseDistance */ - __dna_writer.writeFloatBig(x180_ballCameraChaseDistance); - /* x184_ballCameraChaseYawSpeed */ - __dna_writer.writeFloatBig(x184_ballCameraChaseYawSpeed); - /* x188_ballCameraChaseAnglePerSecond */ - __dna_writer.writeFloatBig(x188_ballCameraChaseAnglePerSecond); - /* x18c_ballCameraChaseLookAtOffset */ - __dna_writer.writeVec3fBig(x18c_ballCameraChaseLookAtOffset); - /* x198_ballCameraChaseSpringConstant */ - __dna_writer.writeFloatBig(x198_ballCameraChaseSpringConstant); - /* x19c_ballCameraChaseSpringMax */ - __dna_writer.writeFloatBig(x19c_ballCameraChaseSpringMax); - /* x1a0_ballCameraChaseSpringTardis */ - __dna_writer.writeFloatBig(x1a0_ballCameraChaseSpringTardis); - /* x1a4_ballCameraBoostElevation */ - __dna_writer.writeFloatBig(x1a4_ballCameraBoostElevation); - /* x1a8_ballCameraBoostDampenAngle */ - __dna_writer.writeFloatBig(x1a8_ballCameraBoostDampenAngle); - /* x1ac_ballCameraBoostDistance */ - __dna_writer.writeFloatBig(x1ac_ballCameraBoostDistance); - /* x1b0_ballCameraBoostYawSpeed */ - __dna_writer.writeFloatBig(x1b0_ballCameraBoostYawSpeed); - /* x1b4_ballCameraBoostAnglePerSecond */ - __dna_writer.writeFloatBig(x1b4_ballCameraBoostAnglePerSecond); - /* x1b8_ballCameraBoostLookAtOffset */ - __dna_writer.writeVec3fBig(x1b8_ballCameraBoostLookAtOffset); - /* x1c4_ballCameraBoostSpringConstant */ - __dna_writer.writeFloatBig(x1c4_ballCameraBoostSpringConstant); - /* x1c8_ballCameraBoostSpringMax */ - __dna_writer.writeFloatBig(x1c8_ballCameraBoostSpringMax); - /* x1cc_ballCameraBoostSpringTardis */ - __dna_writer.writeFloatBig(x1cc_ballCameraBoostSpringTardis); - /* x1d0_ballCameraControlDistance */ - __dna_writer.writeFloatBig(x1d0_ballCameraControlDistance); - /* x1d4_ */ - __dna_writer.writeFloatBig(x1d4_); - /* x1d8_ */ - __dna_writer.writeFloatBig(x1d8_); - /* x1e4_leftStickDivisor */ - __dna_writer.writeFloatBig(x1e4_leftStickDivisor); - /* x1e8_rightStickDivisor */ - __dna_writer.writeFloatBig(x1e8_rightStickDivisor); - /* x200_ */ - __dna_writer.writeFloatBig(x200_); - /* x204_ballTouchRadius */ - __dna_writer.writeFloatBig(x204_ballTouchRadius); - /* x20c_boostBallDrainTime */ - __dna_writer.writeFloatBig(x20c_boostBallDrainTime); - /* x218_boostBallMinChargeTime */ - __dna_writer.writeFloatBig(x218_boostBallMinChargeTime); - /* x21c_boostBallMinRelativeSpeedForDamage */ - __dna_writer.writeFloatBig(x21c_boostBallMinRelativeSpeedForDamage); - /* x220_boostBallChargeTime0 */ - __dna_writer.writeFloatBig(x220_boostBallChargeTime0); - /* x224_boostBallChargeTime1 */ - __dna_writer.writeFloatBig(x224_boostBallChargeTime1); - /* x210_boostBallMaxChargeTime */ - __dna_writer.writeFloatBig(x210_boostBallMaxChargeTime); - /* x22c_boostBallIncrementalSpeed0 */ - __dna_writer.writeFloatBig(x22c_boostBallIncrementalSpeed0); - /* x230_boostBallIncrementalSpeed1 */ - __dna_writer.writeFloatBig(x230_boostBallIncrementalSpeed1); - /* x234_boostBallIncrementalSpeed2 */ - __dna_writer.writeFloatBig(x234_boostBallIncrementalSpeed2); +void CTweakBall::Enumerate(typename Write::StreamT& __dna_writer) { + /* x4_maxTranslationAcceleration[0] */ + __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[0]); + /* x4_maxTranslationAcceleration[1] */ + __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[1]); + /* x4_maxTranslationAcceleration[2] */ + __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[2]); + /* x4_maxTranslationAcceleration[3] */ + __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[3]); + /* x4_maxTranslationAcceleration[4] */ + __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[4]); + /* x4_maxTranslationAcceleration[5] */ + __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[5]); + /* x4_maxTranslationAcceleration[6] */ + __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[6]); + /* x4_maxTranslationAcceleration[7] */ + __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[7]); + /* x24_translationFriction[0] */ + __dna_writer.writeFloatBig(x24_translationFriction[0]); + /* x24_translationFriction[1] */ + __dna_writer.writeFloatBig(x24_translationFriction[1]); + /* x24_translationFriction[2] */ + __dna_writer.writeFloatBig(x24_translationFriction[2]); + /* x24_translationFriction[3] */ + __dna_writer.writeFloatBig(x24_translationFriction[3]); + /* x24_translationFriction[4] */ + __dna_writer.writeFloatBig(x24_translationFriction[4]); + /* x24_translationFriction[5] */ + __dna_writer.writeFloatBig(x24_translationFriction[5]); + /* x24_translationFriction[6] */ + __dna_writer.writeFloatBig(x24_translationFriction[6]); + /* x24_translationFriction[7] */ + __dna_writer.writeFloatBig(x24_translationFriction[7]); + /* x44_translationMaxSpeed[0] */ + __dna_writer.writeFloatBig(x44_translationMaxSpeed[0]); + /* x44_translationMaxSpeed[1] */ + __dna_writer.writeFloatBig(x44_translationMaxSpeed[1]); + /* x44_translationMaxSpeed[2] */ + __dna_writer.writeFloatBig(x44_translationMaxSpeed[2]); + /* x44_translationMaxSpeed[3] */ + __dna_writer.writeFloatBig(x44_translationMaxSpeed[3]); + /* x44_translationMaxSpeed[4] */ + __dna_writer.writeFloatBig(x44_translationMaxSpeed[4]); + /* x44_translationMaxSpeed[5] */ + __dna_writer.writeFloatBig(x44_translationMaxSpeed[5]); + /* x44_translationMaxSpeed[6] */ + __dna_writer.writeFloatBig(x44_translationMaxSpeed[6]); + /* x44_translationMaxSpeed[7] */ + __dna_writer.writeFloatBig(x44_translationMaxSpeed[7]); + /* x64_ */ + __dna_writer.writeFloatBig(x64_); + /* x68_ */ + __dna_writer.writeFloatBig(x68_); + /* x6c_ */ + __dna_writer.writeFloatBig(x6c_); + /* x70_ */ + __dna_writer.writeFloatBig(x70_); + /* xc4_ballForwardBrakingAcceleration[0] */ + __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[0]); + /* xc4_ballForwardBrakingAcceleration[1] */ + __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[1]); + /* xc4_ballForwardBrakingAcceleration[2] */ + __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[2]); + /* xc4_ballForwardBrakingAcceleration[3] */ + __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[3]); + /* xc4_ballForwardBrakingAcceleration[4] */ + __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[4]); + /* xc4_ballForwardBrakingAcceleration[5] */ + __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[5]); + /* xc4_ballForwardBrakingAcceleration[6] */ + __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[6]); + /* xc4_ballForwardBrakingAcceleration[7] */ + __dna_writer.writeFloatBig(xc4_ballForwardBrakingAcceleration[7]); + /* xe4_ballGravity */ + __dna_writer.writeFloatBig(xe4_ballGravity); + /* xe8_ballWaterGravity */ + __dna_writer.writeFloatBig(xe8_ballWaterGravity); + /* x14c_ */ + __dna_writer.writeFloatBig(x14c_); + /* x150_ */ + __dna_writer.writeFloatBig(x150_); + /* x158_ */ + __dna_writer.writeFloatBig(x158_); + /* x1dc_minimumAlignmentSpeed */ + __dna_writer.writeFloatBig(x1dc_minimumAlignmentSpeed); + /* x1e0_tireness */ + __dna_writer.writeFloatBig(x1e0_tireness); + /* x1ec_maxLeanAngle */ + __dna_writer.writeFloatBig(x1ec_maxLeanAngle); + /* x1f0_tireToMarbleThresholdSpeed */ + __dna_writer.writeFloatBig(x1f0_tireToMarbleThresholdSpeed); + /* x1f4_marbleToTireThresholdSpeed */ + __dna_writer.writeFloatBig(x1f4_marbleToTireThresholdSpeed); + /* x1f8_forceToLeanGain */ + __dna_writer.writeFloatBig(x1f8_forceToLeanGain); + /* x1fc_leanTrackingGain */ + __dna_writer.writeFloatBig(x1fc_leanTrackingGain); + /* x74_ballCameraAnglePerSecond */ + __dna_writer.writeFloatBig(x74_ballCameraAnglePerSecond); + /* x78_ballCameraOffset */ + __dna_writer.writeVec3fBig(x78_ballCameraOffset); + /* x84_ballCameraMinSpeedDistance */ + __dna_writer.writeFloatBig(x84_ballCameraMinSpeedDistance); + /* x88_ballCameraMaxSpeedDistance */ + __dna_writer.writeFloatBig(x88_ballCameraMaxSpeedDistance); + /* x8c_ballCameraBackwardsDistance */ + __dna_writer.writeFloatBig(x8c_ballCameraBackwardsDistance); + /* x90_ */ + __dna_writer.writeFloatBig(x90_); + /* x94_ballCameraSpringConstant */ + __dna_writer.writeFloatBig(x94_ballCameraSpringConstant); + /* x98_ballCameraSpringMax */ + __dna_writer.writeFloatBig(x98_ballCameraSpringMax); + /* x9c_ballCameraSpringTardis */ + __dna_writer.writeFloatBig(x9c_ballCameraSpringTardis); + /* xa0_ballCameraCentroidSpringConstant */ + __dna_writer.writeFloatBig(xa0_ballCameraCentroidSpringConstant); + /* xa4_ballCameraCentroidSpringMax */ + __dna_writer.writeFloatBig(xa4_ballCameraCentroidSpringMax); + /* xa8_ballCameraCentroidSpringTardis */ + __dna_writer.writeFloatBig(xa8_ballCameraCentroidSpringTardis); + /* xac_ballCameraCentroidDistanceSpringConstant */ + __dna_writer.writeFloatBig(xac_ballCameraCentroidDistanceSpringConstant); + /* xb0_ballCameraCentroidDistanceSpringMax */ + __dna_writer.writeFloatBig(xb0_ballCameraCentroidDistanceSpringMax); + /* xb4_ballCameraCentroidDistanceSpringTardis */ + __dna_writer.writeFloatBig(xb4_ballCameraCentroidDistanceSpringTardis); + /* xb8_ballCameraLookAtSpringConstant */ + __dna_writer.writeFloatBig(xb8_ballCameraLookAtSpringConstant); + /* xbc_ballCameraLookAtSpringMax */ + __dna_writer.writeFloatBig(xbc_ballCameraLookAtSpringMax); + /* xc0_ballCameraLookAtSpringTardis */ + __dna_writer.writeFloatBig(xc0_ballCameraLookAtSpringTardis); + /* x154_ */ + __dna_writer.writeFloatBig(x154_); + /* x15c_ */ + __dna_writer.writeFloatBig(x15c_); + /* x160_ */ + __dna_writer.writeFloatBig(x160_); + /* x164_ */ + __dna_writer.writeFloatBig(x164_); + /* x168_ */ + __dna_writer.writeFloatBig(x168_); + /* x16c_ */ + __dna_writer.writeFloatBig(x16c_); + /* x170_conservativeDoorCamDistance */ + __dna_writer.writeFloatBig(x170_conservativeDoorCamDistance); + /* x174_ */ + __dna_writer.writeFloatBig(x174_); + /* x178_ballCameraChaseElevation */ + __dna_writer.writeFloatBig(x178_ballCameraChaseElevation); + /* x17c_ballCameraChaseDampenAngle */ + __dna_writer.writeFloatBig(x17c_ballCameraChaseDampenAngle); + /* x180_ballCameraChaseDistance */ + __dna_writer.writeFloatBig(x180_ballCameraChaseDistance); + /* x184_ballCameraChaseYawSpeed */ + __dna_writer.writeFloatBig(x184_ballCameraChaseYawSpeed); + /* x188_ballCameraChaseAnglePerSecond */ + __dna_writer.writeFloatBig(x188_ballCameraChaseAnglePerSecond); + /* x18c_ballCameraChaseLookAtOffset */ + __dna_writer.writeVec3fBig(x18c_ballCameraChaseLookAtOffset); + /* x198_ballCameraChaseSpringConstant */ + __dna_writer.writeFloatBig(x198_ballCameraChaseSpringConstant); + /* x19c_ballCameraChaseSpringMax */ + __dna_writer.writeFloatBig(x19c_ballCameraChaseSpringMax); + /* x1a0_ballCameraChaseSpringTardis */ + __dna_writer.writeFloatBig(x1a0_ballCameraChaseSpringTardis); + /* x1a4_ballCameraBoostElevation */ + __dna_writer.writeFloatBig(x1a4_ballCameraBoostElevation); + /* x1a8_ballCameraBoostDampenAngle */ + __dna_writer.writeFloatBig(x1a8_ballCameraBoostDampenAngle); + /* x1ac_ballCameraBoostDistance */ + __dna_writer.writeFloatBig(x1ac_ballCameraBoostDistance); + /* x1b0_ballCameraBoostYawSpeed */ + __dna_writer.writeFloatBig(x1b0_ballCameraBoostYawSpeed); + /* x1b4_ballCameraBoostAnglePerSecond */ + __dna_writer.writeFloatBig(x1b4_ballCameraBoostAnglePerSecond); + /* x1b8_ballCameraBoostLookAtOffset */ + __dna_writer.writeVec3fBig(x1b8_ballCameraBoostLookAtOffset); + /* x1c4_ballCameraBoostSpringConstant */ + __dna_writer.writeFloatBig(x1c4_ballCameraBoostSpringConstant); + /* x1c8_ballCameraBoostSpringMax */ + __dna_writer.writeFloatBig(x1c8_ballCameraBoostSpringMax); + /* x1cc_ballCameraBoostSpringTardis */ + __dna_writer.writeFloatBig(x1cc_ballCameraBoostSpringTardis); + /* x1d0_ballCameraControlDistance */ + __dna_writer.writeFloatBig(x1d0_ballCameraControlDistance); + /* x1d4_ */ + __dna_writer.writeFloatBig(x1d4_); + /* x1d8_ */ + __dna_writer.writeFloatBig(x1d8_); + /* x1e4_leftStickDivisor */ + __dna_writer.writeFloatBig(x1e4_leftStickDivisor); + /* x1e8_rightStickDivisor */ + __dna_writer.writeFloatBig(x1e8_rightStickDivisor); + /* x200_ */ + __dna_writer.writeFloatBig(x200_); + /* x204_ballTouchRadius */ + __dna_writer.writeFloatBig(x204_ballTouchRadius); + /* x20c_boostBallDrainTime */ + __dna_writer.writeFloatBig(x20c_boostBallDrainTime); + /* x218_boostBallMinChargeTime */ + __dna_writer.writeFloatBig(x218_boostBallMinChargeTime); + /* x21c_boostBallMinRelativeSpeedForDamage */ + __dna_writer.writeFloatBig(x21c_boostBallMinRelativeSpeedForDamage); + /* x220_boostBallChargeTime0 */ + __dna_writer.writeFloatBig(x220_boostBallChargeTime0); + /* x224_boostBallChargeTime1 */ + __dna_writer.writeFloatBig(x224_boostBallChargeTime1); + /* x210_boostBallMaxChargeTime */ + __dna_writer.writeFloatBig(x210_boostBallMaxChargeTime); + /* x22c_boostBallIncrementalSpeed0 */ + __dna_writer.writeFloatBig(x22c_boostBallIncrementalSpeed0); + /* x230_boostBallIncrementalSpeed1 */ + __dna_writer.writeFloatBig(x230_boostBallIncrementalSpeed1); + /* x234_boostBallIncrementalSpeed2 */ + __dna_writer.writeFloatBig(x234_boostBallIncrementalSpeed2); } template <> -void CTweakBall::Enumerate(typename ReadYaml::StreamT& __dna_docin) -{ - /* x4_maxTranslationAcceleration */ - size_t __x4_Count; - if (auto v = __dna_docin.enterSubVector("x4_maxTranslationAcceleration", __x4_Count)) - { +void CTweakBall::Enumerate(typename ReadYaml::StreamT& __dna_docin) { + /* x4_maxTranslationAcceleration */ + size_t __x4_Count; + if (auto v = __dna_docin.enterSubVector("x4_maxTranslationAcceleration", __x4_Count)) { /* x4_maxTranslationAcceleration[0] */ x4_maxTranslationAcceleration[0] = __dna_docin.readFloat("x4_maxTranslationAcceleration"); /* x4_maxTranslationAcceleration[1] */ @@ -468,11 +463,10 @@ void CTweakBall::Enumerate(typename ReadYaml::StreamT& __dna_d x4_maxTranslationAcceleration[6] = __dna_docin.readFloat("x4_maxTranslationAcceleration"); /* x4_maxTranslationAcceleration[7] */ x4_maxTranslationAcceleration[7] = __dna_docin.readFloat("x4_maxTranslationAcceleration"); - } - /* x24_translationFriction */ - size_t __x24_Count; - if (auto v = __dna_docin.enterSubVector("x24_translationFriction", __x24_Count)) - { + } + /* x24_translationFriction */ + size_t __x24_Count; + if (auto v = __dna_docin.enterSubVector("x24_translationFriction", __x24_Count)) { /* x24_translationFriction[0] */ x24_translationFriction[0] = __dna_docin.readFloat("x24_translationFriction"); /* x24_translationFriction[1] */ @@ -489,11 +483,10 @@ void CTweakBall::Enumerate(typename ReadYaml::StreamT& __dna_d x24_translationFriction[6] = __dna_docin.readFloat("x24_translationFriction"); /* x24_translationFriction[7] */ x24_translationFriction[7] = __dna_docin.readFloat("x24_translationFriction"); - } - /* x44_translationMaxSpeed */ - size_t __x44_Count; - if (auto v = __dna_docin.enterSubVector("x44_translationMaxSpeed", __x44_Count)) - { + } + /* x44_translationMaxSpeed */ + size_t __x44_Count; + if (auto v = __dna_docin.enterSubVector("x44_translationMaxSpeed", __x44_Count)) { /* x44_translationMaxSpeed[0] */ x44_translationMaxSpeed[0] = __dna_docin.readFloat("x44_translationMaxSpeed"); /* x44_translationMaxSpeed[1] */ @@ -510,19 +503,18 @@ void CTweakBall::Enumerate(typename ReadYaml::StreamT& __dna_d x44_translationMaxSpeed[6] = __dna_docin.readFloat("x44_translationMaxSpeed"); /* x44_translationMaxSpeed[7] */ x44_translationMaxSpeed[7] = __dna_docin.readFloat("x44_translationMaxSpeed"); - } - /* x64_ */ - x64_ = __dna_docin.readFloat("x64_"); - /* x68_ */ - x68_ = __dna_docin.readFloat("x68_"); - /* x6c_ */ - x6c_ = __dna_docin.readFloat("x6c_"); - /* x70_ */ - x70_ = __dna_docin.readFloat("x70_"); - /* xc4_ballForwardBrakingAcceleration */ - size_t __xc4_Count; - if (auto v = __dna_docin.enterSubVector("xc4_ballForwardBrakingAcceleration", __xc4_Count)) - { + } + /* x64_ */ + x64_ = __dna_docin.readFloat("x64_"); + /* x68_ */ + x68_ = __dna_docin.readFloat("x68_"); + /* x6c_ */ + x6c_ = __dna_docin.readFloat("x6c_"); + /* x70_ */ + x70_ = __dna_docin.readFloat("x70_"); + /* xc4_ballForwardBrakingAcceleration */ + size_t __xc4_Count; + if (auto v = __dna_docin.enterSubVector("xc4_ballForwardBrakingAcceleration", __xc4_Count)) { /* xc4_ballForwardBrakingAcceleration[0] */ xc4_ballForwardBrakingAcceleration[0] = __dna_docin.readFloat("xc4_ballForwardBrakingAcceleration"); /* xc4_ballForwardBrakingAcceleration[1] */ @@ -539,159 +531,157 @@ void CTweakBall::Enumerate(typename ReadYaml::StreamT& __dna_d xc4_ballForwardBrakingAcceleration[6] = __dna_docin.readFloat("xc4_ballForwardBrakingAcceleration"); /* xc4_ballForwardBrakingAcceleration[7] */ xc4_ballForwardBrakingAcceleration[7] = __dna_docin.readFloat("xc4_ballForwardBrakingAcceleration"); - } - /* xe4_ballGravity */ - xe4_ballGravity = __dna_docin.readFloat("xe4_ballGravity"); - /* xe8_ballWaterGravity */ - xe8_ballWaterGravity = __dna_docin.readFloat("xe8_ballWaterGravity"); - /* x14c_ */ - x14c_ = __dna_docin.readFloat("x14c_"); - /* x150_ */ - x150_ = __dna_docin.readFloat("x150_"); - /* x158_ */ - x158_ = __dna_docin.readFloat("x158_"); - /* x1dc_minimumAlignmentSpeed */ - x1dc_minimumAlignmentSpeed = __dna_docin.readFloat("x1dc_minimumAlignmentSpeed"); - /* x1e0_tireness */ - x1e0_tireness = __dna_docin.readFloat("x1e0_tireness"); - /* x1ec_maxLeanAngle */ - x1ec_maxLeanAngle = __dna_docin.readFloat("x1ec_maxLeanAngle"); - /* x1f0_tireToMarbleThresholdSpeed */ - x1f0_tireToMarbleThresholdSpeed = __dna_docin.readFloat("x1f0_tireToMarbleThresholdSpeed"); - /* x1f4_marbleToTireThresholdSpeed */ - x1f4_marbleToTireThresholdSpeed = __dna_docin.readFloat("x1f4_marbleToTireThresholdSpeed"); - /* x1f8_forceToLeanGain */ - x1f8_forceToLeanGain = __dna_docin.readFloat("x1f8_forceToLeanGain"); - /* x1fc_leanTrackingGain */ - x1fc_leanTrackingGain = __dna_docin.readFloat("x1fc_leanTrackingGain"); - /* x74_ballCameraAnglePerSecond */ - x74_ballCameraAnglePerSecond = __dna_docin.readFloat("x74_ballCameraAnglePerSecond"); - /* x78_ballCameraOffset */ - x78_ballCameraOffset = __dna_docin.readVec3f("x78_ballCameraOffset"); - /* x84_ballCameraMinSpeedDistance */ - x84_ballCameraMinSpeedDistance = __dna_docin.readFloat("x84_ballCameraMinSpeedDistance"); - /* x88_ballCameraMaxSpeedDistance */ - x88_ballCameraMaxSpeedDistance = __dna_docin.readFloat("x88_ballCameraMaxSpeedDistance"); - /* x8c_ballCameraBackwardsDistance */ - x8c_ballCameraBackwardsDistance = __dna_docin.readFloat("x8c_ballCameraBackwardsDistance"); - /* x90_ */ - x90_ = __dna_docin.readFloat("x90_"); - /* x94_ballCameraSpringConstant */ - x94_ballCameraSpringConstant = __dna_docin.readFloat("x94_ballCameraSpringConstant"); - /* x98_ballCameraSpringMax */ - x98_ballCameraSpringMax = __dna_docin.readFloat("x98_ballCameraSpringMax"); - /* x9c_ballCameraSpringTardis */ - x9c_ballCameraSpringTardis = __dna_docin.readFloat("x9c_ballCameraSpringTardis"); - /* xa0_ballCameraCentroidSpringConstant */ - xa0_ballCameraCentroidSpringConstant = __dna_docin.readFloat("xa0_ballCameraCentroidSpringConstant"); - /* xa4_ballCameraCentroidSpringMax */ - xa4_ballCameraCentroidSpringMax = __dna_docin.readFloat("xa4_ballCameraCentroidSpringMax"); - /* xa8_ballCameraCentroidSpringTardis */ - xa8_ballCameraCentroidSpringTardis = __dna_docin.readFloat("xa8_ballCameraCentroidSpringTardis"); - /* xac_ballCameraCentroidDistanceSpringConstant */ - xac_ballCameraCentroidDistanceSpringConstant = __dna_docin.readFloat("xac_ballCameraCentroidDistanceSpringConstant"); - /* xb0_ballCameraCentroidDistanceSpringMax */ - xb0_ballCameraCentroidDistanceSpringMax = __dna_docin.readFloat("xb0_ballCameraCentroidDistanceSpringMax"); - /* xb4_ballCameraCentroidDistanceSpringTardis */ - xb4_ballCameraCentroidDistanceSpringTardis = __dna_docin.readFloat("xb4_ballCameraCentroidDistanceSpringTardis"); - /* xb8_ballCameraLookAtSpringConstant */ - xb8_ballCameraLookAtSpringConstant = __dna_docin.readFloat("xb8_ballCameraLookAtSpringConstant"); - /* xbc_ballCameraLookAtSpringMax */ - xbc_ballCameraLookAtSpringMax = __dna_docin.readFloat("xbc_ballCameraLookAtSpringMax"); - /* xc0_ballCameraLookAtSpringTardis */ - xc0_ballCameraLookAtSpringTardis = __dna_docin.readFloat("xc0_ballCameraLookAtSpringTardis"); - /* x154_ */ - x154_ = __dna_docin.readFloat("x154_"); - /* x15c_ */ - x15c_ = __dna_docin.readFloat("x15c_"); - /* x160_ */ - x160_ = __dna_docin.readFloat("x160_"); - /* x164_ */ - x164_ = __dna_docin.readFloat("x164_"); - /* x168_ */ - x168_ = __dna_docin.readFloat("x168_"); - /* x16c_ */ - x16c_ = __dna_docin.readFloat("x16c_"); - /* x170_conservativeDoorCamDistance */ - x170_conservativeDoorCamDistance = __dna_docin.readFloat("x170_conservativeDoorCamDistance"); - /* x174_ */ - x174_ = __dna_docin.readFloat("x174_"); - /* x178_ballCameraChaseElevation */ - x178_ballCameraChaseElevation = __dna_docin.readFloat("x178_ballCameraChaseElevation"); - /* x17c_ballCameraChaseDampenAngle */ - x17c_ballCameraChaseDampenAngle = __dna_docin.readFloat("x17c_ballCameraChaseDampenAngle"); - /* x180_ballCameraChaseDistance */ - x180_ballCameraChaseDistance = __dna_docin.readFloat("x180_ballCameraChaseDistance"); - /* x184_ballCameraChaseYawSpeed */ - x184_ballCameraChaseYawSpeed = __dna_docin.readFloat("x184_ballCameraChaseYawSpeed"); - /* x188_ballCameraChaseAnglePerSecond */ - x188_ballCameraChaseAnglePerSecond = __dna_docin.readFloat("x188_ballCameraChaseAnglePerSecond"); - /* x18c_ballCameraChaseLookAtOffset */ - x18c_ballCameraChaseLookAtOffset = __dna_docin.readVec3f("x18c_ballCameraChaseLookAtOffset"); - /* x198_ballCameraChaseSpringConstant */ - x198_ballCameraChaseSpringConstant = __dna_docin.readFloat("x198_ballCameraChaseSpringConstant"); - /* x19c_ballCameraChaseSpringMax */ - x19c_ballCameraChaseSpringMax = __dna_docin.readFloat("x19c_ballCameraChaseSpringMax"); - /* x1a0_ballCameraChaseSpringTardis */ - x1a0_ballCameraChaseSpringTardis = __dna_docin.readFloat("x1a0_ballCameraChaseSpringTardis"); - /* x1a4_ballCameraBoostElevation */ - x1a4_ballCameraBoostElevation = __dna_docin.readFloat("x1a4_ballCameraBoostElevation"); - /* x1a8_ballCameraBoostDampenAngle */ - x1a8_ballCameraBoostDampenAngle = __dna_docin.readFloat("x1a8_ballCameraBoostDampenAngle"); - /* x1ac_ballCameraBoostDistance */ - x1ac_ballCameraBoostDistance = __dna_docin.readFloat("x1ac_ballCameraBoostDistance"); - /* x1b0_ballCameraBoostYawSpeed */ - x1b0_ballCameraBoostYawSpeed = __dna_docin.readFloat("x1b0_ballCameraBoostYawSpeed"); - /* x1b4_ballCameraBoostAnglePerSecond */ - x1b4_ballCameraBoostAnglePerSecond = __dna_docin.readFloat("x1b4_ballCameraBoostAnglePerSecond"); - /* x1b8_ballCameraBoostLookAtOffset */ - x1b8_ballCameraBoostLookAtOffset = __dna_docin.readVec3f("x1b8_ballCameraBoostLookAtOffset"); - /* x1c4_ballCameraBoostSpringConstant */ - x1c4_ballCameraBoostSpringConstant = __dna_docin.readFloat("x1c4_ballCameraBoostSpringConstant"); - /* x1c8_ballCameraBoostSpringMax */ - x1c8_ballCameraBoostSpringMax = __dna_docin.readFloat("x1c8_ballCameraBoostSpringMax"); - /* x1cc_ballCameraBoostSpringTardis */ - x1cc_ballCameraBoostSpringTardis = __dna_docin.readFloat("x1cc_ballCameraBoostSpringTardis"); - /* x1d0_ballCameraControlDistance */ - x1d0_ballCameraControlDistance = __dna_docin.readFloat("x1d0_ballCameraControlDistance"); - /* x1d4_ */ - x1d4_ = __dna_docin.readFloat("x1d4_"); - /* x1d8_ */ - x1d8_ = __dna_docin.readFloat("x1d8_"); - /* x1e4_leftStickDivisor */ - x1e4_leftStickDivisor = __dna_docin.readFloat("x1e4_leftStickDivisor"); - /* x1e8_rightStickDivisor */ - x1e8_rightStickDivisor = __dna_docin.readFloat("x1e8_rightStickDivisor"); - /* x200_ */ - x200_ = __dna_docin.readFloat("x200_"); - /* x204_ballTouchRadius */ - x204_ballTouchRadius = __dna_docin.readFloat("x204_ballTouchRadius"); - /* x20c_boostBallDrainTime */ - x20c_boostBallDrainTime = __dna_docin.readFloat("x20c_boostBallDrainTime"); - /* x218_boostBallMinChargeTime */ - x218_boostBallMinChargeTime = __dna_docin.readFloat("x218_boostBallMinChargeTime"); - /* x21c_boostBallMinRelativeSpeedForDamage */ - x21c_boostBallMinRelativeSpeedForDamage = __dna_docin.readFloat("x21c_boostBallMinRelativeSpeedForDamage"); - /* x220_boostBallChargeTime0 */ - x220_boostBallChargeTime0 = __dna_docin.readFloat("x220_boostBallChargeTime0"); - /* x224_boostBallChargeTime1 */ - x224_boostBallChargeTime1 = __dna_docin.readFloat("x224_boostBallChargeTime1"); - /* x210_boostBallMaxChargeTime */ - x228_boostBallChargeTime2 = x210_boostBallMaxChargeTime = __dna_docin.readFloat("x210_boostBallMaxChargeTime"); - /* x22c_boostBallIncrementalSpeed0 */ - x22c_boostBallIncrementalSpeed0 = __dna_docin.readFloat("x22c_boostBallIncrementalSpeed0"); - /* x230_boostBallIncrementalSpeed1 */ - x230_boostBallIncrementalSpeed1 = __dna_docin.readFloat("x230_boostBallIncrementalSpeed1"); - /* x234_boostBallIncrementalSpeed2 */ - x234_boostBallIncrementalSpeed2 = __dna_docin.readFloat("x234_boostBallIncrementalSpeed2"); + } + /* xe4_ballGravity */ + xe4_ballGravity = __dna_docin.readFloat("xe4_ballGravity"); + /* xe8_ballWaterGravity */ + xe8_ballWaterGravity = __dna_docin.readFloat("xe8_ballWaterGravity"); + /* x14c_ */ + x14c_ = __dna_docin.readFloat("x14c_"); + /* x150_ */ + x150_ = __dna_docin.readFloat("x150_"); + /* x158_ */ + x158_ = __dna_docin.readFloat("x158_"); + /* x1dc_minimumAlignmentSpeed */ + x1dc_minimumAlignmentSpeed = __dna_docin.readFloat("x1dc_minimumAlignmentSpeed"); + /* x1e0_tireness */ + x1e0_tireness = __dna_docin.readFloat("x1e0_tireness"); + /* x1ec_maxLeanAngle */ + x1ec_maxLeanAngle = __dna_docin.readFloat("x1ec_maxLeanAngle"); + /* x1f0_tireToMarbleThresholdSpeed */ + x1f0_tireToMarbleThresholdSpeed = __dna_docin.readFloat("x1f0_tireToMarbleThresholdSpeed"); + /* x1f4_marbleToTireThresholdSpeed */ + x1f4_marbleToTireThresholdSpeed = __dna_docin.readFloat("x1f4_marbleToTireThresholdSpeed"); + /* x1f8_forceToLeanGain */ + x1f8_forceToLeanGain = __dna_docin.readFloat("x1f8_forceToLeanGain"); + /* x1fc_leanTrackingGain */ + x1fc_leanTrackingGain = __dna_docin.readFloat("x1fc_leanTrackingGain"); + /* x74_ballCameraAnglePerSecond */ + x74_ballCameraAnglePerSecond = __dna_docin.readFloat("x74_ballCameraAnglePerSecond"); + /* x78_ballCameraOffset */ + x78_ballCameraOffset = __dna_docin.readVec3f("x78_ballCameraOffset"); + /* x84_ballCameraMinSpeedDistance */ + x84_ballCameraMinSpeedDistance = __dna_docin.readFloat("x84_ballCameraMinSpeedDistance"); + /* x88_ballCameraMaxSpeedDistance */ + x88_ballCameraMaxSpeedDistance = __dna_docin.readFloat("x88_ballCameraMaxSpeedDistance"); + /* x8c_ballCameraBackwardsDistance */ + x8c_ballCameraBackwardsDistance = __dna_docin.readFloat("x8c_ballCameraBackwardsDistance"); + /* x90_ */ + x90_ = __dna_docin.readFloat("x90_"); + /* x94_ballCameraSpringConstant */ + x94_ballCameraSpringConstant = __dna_docin.readFloat("x94_ballCameraSpringConstant"); + /* x98_ballCameraSpringMax */ + x98_ballCameraSpringMax = __dna_docin.readFloat("x98_ballCameraSpringMax"); + /* x9c_ballCameraSpringTardis */ + x9c_ballCameraSpringTardis = __dna_docin.readFloat("x9c_ballCameraSpringTardis"); + /* xa0_ballCameraCentroidSpringConstant */ + xa0_ballCameraCentroidSpringConstant = __dna_docin.readFloat("xa0_ballCameraCentroidSpringConstant"); + /* xa4_ballCameraCentroidSpringMax */ + xa4_ballCameraCentroidSpringMax = __dna_docin.readFloat("xa4_ballCameraCentroidSpringMax"); + /* xa8_ballCameraCentroidSpringTardis */ + xa8_ballCameraCentroidSpringTardis = __dna_docin.readFloat("xa8_ballCameraCentroidSpringTardis"); + /* xac_ballCameraCentroidDistanceSpringConstant */ + xac_ballCameraCentroidDistanceSpringConstant = __dna_docin.readFloat("xac_ballCameraCentroidDistanceSpringConstant"); + /* xb0_ballCameraCentroidDistanceSpringMax */ + xb0_ballCameraCentroidDistanceSpringMax = __dna_docin.readFloat("xb0_ballCameraCentroidDistanceSpringMax"); + /* xb4_ballCameraCentroidDistanceSpringTardis */ + xb4_ballCameraCentroidDistanceSpringTardis = __dna_docin.readFloat("xb4_ballCameraCentroidDistanceSpringTardis"); + /* xb8_ballCameraLookAtSpringConstant */ + xb8_ballCameraLookAtSpringConstant = __dna_docin.readFloat("xb8_ballCameraLookAtSpringConstant"); + /* xbc_ballCameraLookAtSpringMax */ + xbc_ballCameraLookAtSpringMax = __dna_docin.readFloat("xbc_ballCameraLookAtSpringMax"); + /* xc0_ballCameraLookAtSpringTardis */ + xc0_ballCameraLookAtSpringTardis = __dna_docin.readFloat("xc0_ballCameraLookAtSpringTardis"); + /* x154_ */ + x154_ = __dna_docin.readFloat("x154_"); + /* x15c_ */ + x15c_ = __dna_docin.readFloat("x15c_"); + /* x160_ */ + x160_ = __dna_docin.readFloat("x160_"); + /* x164_ */ + x164_ = __dna_docin.readFloat("x164_"); + /* x168_ */ + x168_ = __dna_docin.readFloat("x168_"); + /* x16c_ */ + x16c_ = __dna_docin.readFloat("x16c_"); + /* x170_conservativeDoorCamDistance */ + x170_conservativeDoorCamDistance = __dna_docin.readFloat("x170_conservativeDoorCamDistance"); + /* x174_ */ + x174_ = __dna_docin.readFloat("x174_"); + /* x178_ballCameraChaseElevation */ + x178_ballCameraChaseElevation = __dna_docin.readFloat("x178_ballCameraChaseElevation"); + /* x17c_ballCameraChaseDampenAngle */ + x17c_ballCameraChaseDampenAngle = __dna_docin.readFloat("x17c_ballCameraChaseDampenAngle"); + /* x180_ballCameraChaseDistance */ + x180_ballCameraChaseDistance = __dna_docin.readFloat("x180_ballCameraChaseDistance"); + /* x184_ballCameraChaseYawSpeed */ + x184_ballCameraChaseYawSpeed = __dna_docin.readFloat("x184_ballCameraChaseYawSpeed"); + /* x188_ballCameraChaseAnglePerSecond */ + x188_ballCameraChaseAnglePerSecond = __dna_docin.readFloat("x188_ballCameraChaseAnglePerSecond"); + /* x18c_ballCameraChaseLookAtOffset */ + x18c_ballCameraChaseLookAtOffset = __dna_docin.readVec3f("x18c_ballCameraChaseLookAtOffset"); + /* x198_ballCameraChaseSpringConstant */ + x198_ballCameraChaseSpringConstant = __dna_docin.readFloat("x198_ballCameraChaseSpringConstant"); + /* x19c_ballCameraChaseSpringMax */ + x19c_ballCameraChaseSpringMax = __dna_docin.readFloat("x19c_ballCameraChaseSpringMax"); + /* x1a0_ballCameraChaseSpringTardis */ + x1a0_ballCameraChaseSpringTardis = __dna_docin.readFloat("x1a0_ballCameraChaseSpringTardis"); + /* x1a4_ballCameraBoostElevation */ + x1a4_ballCameraBoostElevation = __dna_docin.readFloat("x1a4_ballCameraBoostElevation"); + /* x1a8_ballCameraBoostDampenAngle */ + x1a8_ballCameraBoostDampenAngle = __dna_docin.readFloat("x1a8_ballCameraBoostDampenAngle"); + /* x1ac_ballCameraBoostDistance */ + x1ac_ballCameraBoostDistance = __dna_docin.readFloat("x1ac_ballCameraBoostDistance"); + /* x1b0_ballCameraBoostYawSpeed */ + x1b0_ballCameraBoostYawSpeed = __dna_docin.readFloat("x1b0_ballCameraBoostYawSpeed"); + /* x1b4_ballCameraBoostAnglePerSecond */ + x1b4_ballCameraBoostAnglePerSecond = __dna_docin.readFloat("x1b4_ballCameraBoostAnglePerSecond"); + /* x1b8_ballCameraBoostLookAtOffset */ + x1b8_ballCameraBoostLookAtOffset = __dna_docin.readVec3f("x1b8_ballCameraBoostLookAtOffset"); + /* x1c4_ballCameraBoostSpringConstant */ + x1c4_ballCameraBoostSpringConstant = __dna_docin.readFloat("x1c4_ballCameraBoostSpringConstant"); + /* x1c8_ballCameraBoostSpringMax */ + x1c8_ballCameraBoostSpringMax = __dna_docin.readFloat("x1c8_ballCameraBoostSpringMax"); + /* x1cc_ballCameraBoostSpringTardis */ + x1cc_ballCameraBoostSpringTardis = __dna_docin.readFloat("x1cc_ballCameraBoostSpringTardis"); + /* x1d0_ballCameraControlDistance */ + x1d0_ballCameraControlDistance = __dna_docin.readFloat("x1d0_ballCameraControlDistance"); + /* x1d4_ */ + x1d4_ = __dna_docin.readFloat("x1d4_"); + /* x1d8_ */ + x1d8_ = __dna_docin.readFloat("x1d8_"); + /* x1e4_leftStickDivisor */ + x1e4_leftStickDivisor = __dna_docin.readFloat("x1e4_leftStickDivisor"); + /* x1e8_rightStickDivisor */ + x1e8_rightStickDivisor = __dna_docin.readFloat("x1e8_rightStickDivisor"); + /* x200_ */ + x200_ = __dna_docin.readFloat("x200_"); + /* x204_ballTouchRadius */ + x204_ballTouchRadius = __dna_docin.readFloat("x204_ballTouchRadius"); + /* x20c_boostBallDrainTime */ + x20c_boostBallDrainTime = __dna_docin.readFloat("x20c_boostBallDrainTime"); + /* x218_boostBallMinChargeTime */ + x218_boostBallMinChargeTime = __dna_docin.readFloat("x218_boostBallMinChargeTime"); + /* x21c_boostBallMinRelativeSpeedForDamage */ + x21c_boostBallMinRelativeSpeedForDamage = __dna_docin.readFloat("x21c_boostBallMinRelativeSpeedForDamage"); + /* x220_boostBallChargeTime0 */ + x220_boostBallChargeTime0 = __dna_docin.readFloat("x220_boostBallChargeTime0"); + /* x224_boostBallChargeTime1 */ + x224_boostBallChargeTime1 = __dna_docin.readFloat("x224_boostBallChargeTime1"); + /* x210_boostBallMaxChargeTime */ + x228_boostBallChargeTime2 = x210_boostBallMaxChargeTime = __dna_docin.readFloat("x210_boostBallMaxChargeTime"); + /* x22c_boostBallIncrementalSpeed0 */ + x22c_boostBallIncrementalSpeed0 = __dna_docin.readFloat("x22c_boostBallIncrementalSpeed0"); + /* x230_boostBallIncrementalSpeed1 */ + x230_boostBallIncrementalSpeed1 = __dna_docin.readFloat("x230_boostBallIncrementalSpeed1"); + /* x234_boostBallIncrementalSpeed2 */ + x234_boostBallIncrementalSpeed2 = __dna_docin.readFloat("x234_boostBallIncrementalSpeed2"); } template <> -void CTweakBall::Enumerate(typename WriteYaml::StreamT& __dna_docout) -{ - /* x4_maxTranslationAcceleration */ - if (auto v = __dna_docout.enterSubVector("x4_maxTranslationAcceleration")) - { +void CTweakBall::Enumerate(typename WriteYaml::StreamT& __dna_docout) { + /* x4_maxTranslationAcceleration */ + if (auto v = __dna_docout.enterSubVector("x4_maxTranslationAcceleration")) { /* x4_maxTranslationAcceleration[0] */ __dna_docout.writeFloat("x4_maxTranslationAcceleration", x4_maxTranslationAcceleration[0]); /* x4_maxTranslationAcceleration[1] */ @@ -708,10 +698,9 @@ void CTweakBall::Enumerate(typename WriteYaml::StreamT& __dna __dna_docout.writeFloat("x4_maxTranslationAcceleration", x4_maxTranslationAcceleration[6]); /* x4_maxTranslationAcceleration[7] */ __dna_docout.writeFloat("x4_maxTranslationAcceleration", x4_maxTranslationAcceleration[7]); - } - /* x24_translationFriction */ - if (auto v = __dna_docout.enterSubVector("x24_translationFriction")) - { + } + /* x24_translationFriction */ + if (auto v = __dna_docout.enterSubVector("x24_translationFriction")) { /* x24_translationFriction[0] */ __dna_docout.writeFloat("x24_translationFriction", x24_translationFriction[0]); /* x24_translationFriction[1] */ @@ -728,10 +717,9 @@ void CTweakBall::Enumerate(typename WriteYaml::StreamT& __dna __dna_docout.writeFloat("x24_translationFriction", x24_translationFriction[6]); /* x24_translationFriction[7] */ __dna_docout.writeFloat("x24_translationFriction", x24_translationFriction[7]); - } - /* x44_translationMaxSpeed */ - if (auto v = __dna_docout.enterSubVector("x44_translationMaxSpeed")) - { + } + /* x44_translationMaxSpeed */ + if (auto v = __dna_docout.enterSubVector("x44_translationMaxSpeed")) { /* x44_translationMaxSpeed[0] */ __dna_docout.writeFloat("x44_translationMaxSpeed", x44_translationMaxSpeed[0]); /* x44_translationMaxSpeed[1] */ @@ -748,18 +736,17 @@ void CTweakBall::Enumerate(typename WriteYaml::StreamT& __dna __dna_docout.writeFloat("x44_translationMaxSpeed", x44_translationMaxSpeed[6]); /* x44_translationMaxSpeed[7] */ __dna_docout.writeFloat("x44_translationMaxSpeed", x44_translationMaxSpeed[7]); - } - /* x64_ */ - __dna_docout.writeFloat("x64_", x64_); - /* x68_ */ - __dna_docout.writeFloat("x68_", x68_); - /* x6c_ */ - __dna_docout.writeFloat("x6c_", x6c_); - /* x70_ */ - __dna_docout.writeFloat("x70_", x70_); - /* xc4_ballForwardBrakingAcceleration */ - if (auto v = __dna_docout.enterSubVector("xc4_ballForwardBrakingAcceleration")) - { + } + /* x64_ */ + __dna_docout.writeFloat("x64_", x64_); + /* x68_ */ + __dna_docout.writeFloat("x68_", x68_); + /* x6c_ */ + __dna_docout.writeFloat("x6c_", x6c_); + /* x70_ */ + __dna_docout.writeFloat("x70_", x70_); + /* xc4_ballForwardBrakingAcceleration */ + if (auto v = __dna_docout.enterSubVector("xc4_ballForwardBrakingAcceleration")) { /* xc4_ballForwardBrakingAcceleration[0] */ __dna_docout.writeFloat("xc4_ballForwardBrakingAcceleration", xc4_ballForwardBrakingAcceleration[0]); /* xc4_ballForwardBrakingAcceleration[1] */ @@ -776,162 +763,158 @@ void CTweakBall::Enumerate(typename WriteYaml::StreamT& __dna __dna_docout.writeFloat("xc4_ballForwardBrakingAcceleration", xc4_ballForwardBrakingAcceleration[6]); /* xc4_ballForwardBrakingAcceleration[7] */ __dna_docout.writeFloat("xc4_ballForwardBrakingAcceleration", xc4_ballForwardBrakingAcceleration[7]); - } - /* xe4_ballGravity */ - __dna_docout.writeFloat("xe4_ballGravity", xe4_ballGravity); - /* xe8_ballWaterGravity */ - __dna_docout.writeFloat("xe8_ballWaterGravity", xe8_ballWaterGravity); - /* x14c_ */ - __dna_docout.writeFloat("x14c_", x14c_); - /* x150_ */ - __dna_docout.writeFloat("x150_", x150_); - /* x158_ */ - __dna_docout.writeFloat("x158_", x158_); - /* x1dc_minimumAlignmentSpeed */ - __dna_docout.writeFloat("x1dc_minimumAlignmentSpeed", x1dc_minimumAlignmentSpeed); - /* x1e0_tireness */ - __dna_docout.writeFloat("x1e0_tireness", x1e0_tireness); - /* x1ec_maxLeanAngle */ - __dna_docout.writeFloat("x1ec_maxLeanAngle", x1ec_maxLeanAngle); - /* x1f0_tireToMarbleThresholdSpeed */ - __dna_docout.writeFloat("x1f0_tireToMarbleThresholdSpeed", x1f0_tireToMarbleThresholdSpeed); - /* x1f4_marbleToTireThresholdSpeed */ - __dna_docout.writeFloat("x1f4_marbleToTireThresholdSpeed", x1f4_marbleToTireThresholdSpeed); - /* x1f8_forceToLeanGain */ - __dna_docout.writeFloat("x1f8_forceToLeanGain", x1f8_forceToLeanGain); - /* x1fc_leanTrackingGain */ - __dna_docout.writeFloat("x1fc_leanTrackingGain", x1fc_leanTrackingGain); - /* x74_ballCameraAnglePerSecond */ - __dna_docout.writeFloat("x74_ballCameraAnglePerSecond", x74_ballCameraAnglePerSecond); - /* x78_ballCameraOffset */ - __dna_docout.writeVec3f("x78_ballCameraOffset", x78_ballCameraOffset); - /* x84_ballCameraMinSpeedDistance */ - __dna_docout.writeFloat("x84_ballCameraMinSpeedDistance", x84_ballCameraMinSpeedDistance); - /* x88_ballCameraMaxSpeedDistance */ - __dna_docout.writeFloat("x88_ballCameraMaxSpeedDistance", x88_ballCameraMaxSpeedDistance); - /* x8c_ballCameraBackwardsDistance */ - __dna_docout.writeFloat("x8c_ballCameraBackwardsDistance", x8c_ballCameraBackwardsDistance); - /* x90_ */ - __dna_docout.writeFloat("x90_", x90_); - /* x94_ballCameraSpringConstant */ - __dna_docout.writeFloat("x94_ballCameraSpringConstant", x94_ballCameraSpringConstant); - /* x98_ballCameraSpringMax */ - __dna_docout.writeFloat("x98_ballCameraSpringMax", x98_ballCameraSpringMax); - /* x9c_ballCameraSpringTardis */ - __dna_docout.writeFloat("x9c_ballCameraSpringTardis", x9c_ballCameraSpringTardis); - /* xa0_ballCameraCentroidSpringConstant */ - __dna_docout.writeFloat("xa0_ballCameraCentroidSpringConstant", xa0_ballCameraCentroidSpringConstant); - /* xa4_ballCameraCentroidSpringMax */ - __dna_docout.writeFloat("xa4_ballCameraCentroidSpringMax", xa4_ballCameraCentroidSpringMax); - /* xa8_ballCameraCentroidSpringTardis */ - __dna_docout.writeFloat("xa8_ballCameraCentroidSpringTardis", xa8_ballCameraCentroidSpringTardis); - /* xac_ballCameraCentroidDistanceSpringConstant */ - __dna_docout.writeFloat("xac_ballCameraCentroidDistanceSpringConstant", xac_ballCameraCentroidDistanceSpringConstant); - /* xb0_ballCameraCentroidDistanceSpringMax */ - __dna_docout.writeFloat("xb0_ballCameraCentroidDistanceSpringMax", xb0_ballCameraCentroidDistanceSpringMax); - /* xb4_ballCameraCentroidDistanceSpringTardis */ - __dna_docout.writeFloat("xb4_ballCameraCentroidDistanceSpringTardis", xb4_ballCameraCentroidDistanceSpringTardis); - /* xb8_ballCameraLookAtSpringConstant */ - __dna_docout.writeFloat("xb8_ballCameraLookAtSpringConstant", xb8_ballCameraLookAtSpringConstant); - /* xbc_ballCameraLookAtSpringMax */ - __dna_docout.writeFloat("xbc_ballCameraLookAtSpringMax", xbc_ballCameraLookAtSpringMax); - /* xc0_ballCameraLookAtSpringTardis */ - __dna_docout.writeFloat("xc0_ballCameraLookAtSpringTardis", xc0_ballCameraLookAtSpringTardis); - /* x154_ */ - __dna_docout.writeFloat("x154_", x154_); - /* x15c_ */ - __dna_docout.writeFloat("x15c_", x15c_); - /* x160_ */ - __dna_docout.writeFloat("x160_", x160_); - /* x164_ */ - __dna_docout.writeFloat("x164_", x164_); - /* x168_ */ - __dna_docout.writeFloat("x168_", x168_); - /* x16c_ */ - __dna_docout.writeFloat("x16c_", x16c_); - /* x170_conservativeDoorCamDistance */ - __dna_docout.writeFloat("x170_conservativeDoorCamDistance", x170_conservativeDoorCamDistance); - /* x174_ */ - __dna_docout.writeFloat("x174_", x174_); - /* x178_ballCameraChaseElevation */ - __dna_docout.writeFloat("x178_ballCameraChaseElevation", x178_ballCameraChaseElevation); - /* x17c_ballCameraChaseDampenAngle */ - __dna_docout.writeFloat("x17c_ballCameraChaseDampenAngle", x17c_ballCameraChaseDampenAngle); - /* x180_ballCameraChaseDistance */ - __dna_docout.writeFloat("x180_ballCameraChaseDistance", x180_ballCameraChaseDistance); - /* x184_ballCameraChaseYawSpeed */ - __dna_docout.writeFloat("x184_ballCameraChaseYawSpeed", x184_ballCameraChaseYawSpeed); - /* x188_ballCameraChaseAnglePerSecond */ - __dna_docout.writeFloat("x188_ballCameraChaseAnglePerSecond", x188_ballCameraChaseAnglePerSecond); - /* x18c_ballCameraChaseLookAtOffset */ - __dna_docout.writeVec3f("x18c_ballCameraChaseLookAtOffset", x18c_ballCameraChaseLookAtOffset); - /* x198_ballCameraChaseSpringConstant */ - __dna_docout.writeFloat("x198_ballCameraChaseSpringConstant", x198_ballCameraChaseSpringConstant); - /* x19c_ballCameraChaseSpringMax */ - __dna_docout.writeFloat("x19c_ballCameraChaseSpringMax", x19c_ballCameraChaseSpringMax); - /* x1a0_ballCameraChaseSpringTardis */ - __dna_docout.writeFloat("x1a0_ballCameraChaseSpringTardis", x1a0_ballCameraChaseSpringTardis); - /* x1a4_ballCameraBoostElevation */ - __dna_docout.writeFloat("x1a4_ballCameraBoostElevation", x1a4_ballCameraBoostElevation); - /* x1a8_ballCameraBoostDampenAngle */ - __dna_docout.writeFloat("x1a8_ballCameraBoostDampenAngle", x1a8_ballCameraBoostDampenAngle); - /* x1ac_ballCameraBoostDistance */ - __dna_docout.writeFloat("x1ac_ballCameraBoostDistance", x1ac_ballCameraBoostDistance); - /* x1b0_ballCameraBoostYawSpeed */ - __dna_docout.writeFloat("x1b0_ballCameraBoostYawSpeed", x1b0_ballCameraBoostYawSpeed); - /* x1b4_ballCameraBoostAnglePerSecond */ - __dna_docout.writeFloat("x1b4_ballCameraBoostAnglePerSecond", x1b4_ballCameraBoostAnglePerSecond); - /* x1b8_ballCameraBoostLookAtOffset */ - __dna_docout.writeVec3f("x1b8_ballCameraBoostLookAtOffset", x1b8_ballCameraBoostLookAtOffset); - /* x1c4_ballCameraBoostSpringConstant */ - __dna_docout.writeFloat("x1c4_ballCameraBoostSpringConstant", x1c4_ballCameraBoostSpringConstant); - /* x1c8_ballCameraBoostSpringMax */ - __dna_docout.writeFloat("x1c8_ballCameraBoostSpringMax", x1c8_ballCameraBoostSpringMax); - /* x1cc_ballCameraBoostSpringTardis */ - __dna_docout.writeFloat("x1cc_ballCameraBoostSpringTardis", x1cc_ballCameraBoostSpringTardis); - /* x1d0_ballCameraControlDistance */ - __dna_docout.writeFloat("x1d0_ballCameraControlDistance", x1d0_ballCameraControlDistance); - /* x1d4_ */ - __dna_docout.writeFloat("x1d4_", x1d4_); - /* x1d8_ */ - __dna_docout.writeFloat("x1d8_", x1d8_); - /* x1e4_leftStickDivisor */ - __dna_docout.writeFloat("x1e4_leftStickDivisor", x1e4_leftStickDivisor); - /* x1e8_rightStickDivisor */ - __dna_docout.writeFloat("x1e8_rightStickDivisor", x1e8_rightStickDivisor); - /* x200_ */ - __dna_docout.writeFloat("x200_", x200_); - /* x204_ballTouchRadius */ - __dna_docout.writeFloat("x204_ballTouchRadius", x204_ballTouchRadius); - /* x20c_boostBallDrainTime */ - __dna_docout.writeFloat("x20c_boostBallDrainTime", x20c_boostBallDrainTime); - /* x218_boostBallMinChargeTime */ - __dna_docout.writeFloat("x218_boostBallMinChargeTime", x218_boostBallMinChargeTime); - /* x21c_boostBallMinRelativeSpeedForDamage */ - __dna_docout.writeFloat("x21c_boostBallMinRelativeSpeedForDamage", x21c_boostBallMinRelativeSpeedForDamage); - /* x220_boostBallChargeTime0 */ - __dna_docout.writeFloat("x220_boostBallChargeTime0", x220_boostBallChargeTime0); - /* x224_boostBallChargeTime1 */ - __dna_docout.writeFloat("x224_boostBallChargeTime1", x224_boostBallChargeTime1); - /* x210_boostBallMaxChargeTime */ - __dna_docout.writeFloat("x210_boostBallMaxChargeTime", x210_boostBallMaxChargeTime); - /* x22c_boostBallIncrementalSpeed0 */ - __dna_docout.writeFloat("x22c_boostBallIncrementalSpeed0", x22c_boostBallIncrementalSpeed0); - /* x230_boostBallIncrementalSpeed1 */ - __dna_docout.writeFloat("x230_boostBallIncrementalSpeed1", x230_boostBallIncrementalSpeed1); - /* x234_boostBallIncrementalSpeed2 */ - __dna_docout.writeFloat("x234_boostBallIncrementalSpeed2", x234_boostBallIncrementalSpeed2); + } + /* xe4_ballGravity */ + __dna_docout.writeFloat("xe4_ballGravity", xe4_ballGravity); + /* xe8_ballWaterGravity */ + __dna_docout.writeFloat("xe8_ballWaterGravity", xe8_ballWaterGravity); + /* x14c_ */ + __dna_docout.writeFloat("x14c_", x14c_); + /* x150_ */ + __dna_docout.writeFloat("x150_", x150_); + /* x158_ */ + __dna_docout.writeFloat("x158_", x158_); + /* x1dc_minimumAlignmentSpeed */ + __dna_docout.writeFloat("x1dc_minimumAlignmentSpeed", x1dc_minimumAlignmentSpeed); + /* x1e0_tireness */ + __dna_docout.writeFloat("x1e0_tireness", x1e0_tireness); + /* x1ec_maxLeanAngle */ + __dna_docout.writeFloat("x1ec_maxLeanAngle", x1ec_maxLeanAngle); + /* x1f0_tireToMarbleThresholdSpeed */ + __dna_docout.writeFloat("x1f0_tireToMarbleThresholdSpeed", x1f0_tireToMarbleThresholdSpeed); + /* x1f4_marbleToTireThresholdSpeed */ + __dna_docout.writeFloat("x1f4_marbleToTireThresholdSpeed", x1f4_marbleToTireThresholdSpeed); + /* x1f8_forceToLeanGain */ + __dna_docout.writeFloat("x1f8_forceToLeanGain", x1f8_forceToLeanGain); + /* x1fc_leanTrackingGain */ + __dna_docout.writeFloat("x1fc_leanTrackingGain", x1fc_leanTrackingGain); + /* x74_ballCameraAnglePerSecond */ + __dna_docout.writeFloat("x74_ballCameraAnglePerSecond", x74_ballCameraAnglePerSecond); + /* x78_ballCameraOffset */ + __dna_docout.writeVec3f("x78_ballCameraOffset", x78_ballCameraOffset); + /* x84_ballCameraMinSpeedDistance */ + __dna_docout.writeFloat("x84_ballCameraMinSpeedDistance", x84_ballCameraMinSpeedDistance); + /* x88_ballCameraMaxSpeedDistance */ + __dna_docout.writeFloat("x88_ballCameraMaxSpeedDistance", x88_ballCameraMaxSpeedDistance); + /* x8c_ballCameraBackwardsDistance */ + __dna_docout.writeFloat("x8c_ballCameraBackwardsDistance", x8c_ballCameraBackwardsDistance); + /* x90_ */ + __dna_docout.writeFloat("x90_", x90_); + /* x94_ballCameraSpringConstant */ + __dna_docout.writeFloat("x94_ballCameraSpringConstant", x94_ballCameraSpringConstant); + /* x98_ballCameraSpringMax */ + __dna_docout.writeFloat("x98_ballCameraSpringMax", x98_ballCameraSpringMax); + /* x9c_ballCameraSpringTardis */ + __dna_docout.writeFloat("x9c_ballCameraSpringTardis", x9c_ballCameraSpringTardis); + /* xa0_ballCameraCentroidSpringConstant */ + __dna_docout.writeFloat("xa0_ballCameraCentroidSpringConstant", xa0_ballCameraCentroidSpringConstant); + /* xa4_ballCameraCentroidSpringMax */ + __dna_docout.writeFloat("xa4_ballCameraCentroidSpringMax", xa4_ballCameraCentroidSpringMax); + /* xa8_ballCameraCentroidSpringTardis */ + __dna_docout.writeFloat("xa8_ballCameraCentroidSpringTardis", xa8_ballCameraCentroidSpringTardis); + /* xac_ballCameraCentroidDistanceSpringConstant */ + __dna_docout.writeFloat("xac_ballCameraCentroidDistanceSpringConstant", xac_ballCameraCentroidDistanceSpringConstant); + /* xb0_ballCameraCentroidDistanceSpringMax */ + __dna_docout.writeFloat("xb0_ballCameraCentroidDistanceSpringMax", xb0_ballCameraCentroidDistanceSpringMax); + /* xb4_ballCameraCentroidDistanceSpringTardis */ + __dna_docout.writeFloat("xb4_ballCameraCentroidDistanceSpringTardis", xb4_ballCameraCentroidDistanceSpringTardis); + /* xb8_ballCameraLookAtSpringConstant */ + __dna_docout.writeFloat("xb8_ballCameraLookAtSpringConstant", xb8_ballCameraLookAtSpringConstant); + /* xbc_ballCameraLookAtSpringMax */ + __dna_docout.writeFloat("xbc_ballCameraLookAtSpringMax", xbc_ballCameraLookAtSpringMax); + /* xc0_ballCameraLookAtSpringTardis */ + __dna_docout.writeFloat("xc0_ballCameraLookAtSpringTardis", xc0_ballCameraLookAtSpringTardis); + /* x154_ */ + __dna_docout.writeFloat("x154_", x154_); + /* x15c_ */ + __dna_docout.writeFloat("x15c_", x15c_); + /* x160_ */ + __dna_docout.writeFloat("x160_", x160_); + /* x164_ */ + __dna_docout.writeFloat("x164_", x164_); + /* x168_ */ + __dna_docout.writeFloat("x168_", x168_); + /* x16c_ */ + __dna_docout.writeFloat("x16c_", x16c_); + /* x170_conservativeDoorCamDistance */ + __dna_docout.writeFloat("x170_conservativeDoorCamDistance", x170_conservativeDoorCamDistance); + /* x174_ */ + __dna_docout.writeFloat("x174_", x174_); + /* x178_ballCameraChaseElevation */ + __dna_docout.writeFloat("x178_ballCameraChaseElevation", x178_ballCameraChaseElevation); + /* x17c_ballCameraChaseDampenAngle */ + __dna_docout.writeFloat("x17c_ballCameraChaseDampenAngle", x17c_ballCameraChaseDampenAngle); + /* x180_ballCameraChaseDistance */ + __dna_docout.writeFloat("x180_ballCameraChaseDistance", x180_ballCameraChaseDistance); + /* x184_ballCameraChaseYawSpeed */ + __dna_docout.writeFloat("x184_ballCameraChaseYawSpeed", x184_ballCameraChaseYawSpeed); + /* x188_ballCameraChaseAnglePerSecond */ + __dna_docout.writeFloat("x188_ballCameraChaseAnglePerSecond", x188_ballCameraChaseAnglePerSecond); + /* x18c_ballCameraChaseLookAtOffset */ + __dna_docout.writeVec3f("x18c_ballCameraChaseLookAtOffset", x18c_ballCameraChaseLookAtOffset); + /* x198_ballCameraChaseSpringConstant */ + __dna_docout.writeFloat("x198_ballCameraChaseSpringConstant", x198_ballCameraChaseSpringConstant); + /* x19c_ballCameraChaseSpringMax */ + __dna_docout.writeFloat("x19c_ballCameraChaseSpringMax", x19c_ballCameraChaseSpringMax); + /* x1a0_ballCameraChaseSpringTardis */ + __dna_docout.writeFloat("x1a0_ballCameraChaseSpringTardis", x1a0_ballCameraChaseSpringTardis); + /* x1a4_ballCameraBoostElevation */ + __dna_docout.writeFloat("x1a4_ballCameraBoostElevation", x1a4_ballCameraBoostElevation); + /* x1a8_ballCameraBoostDampenAngle */ + __dna_docout.writeFloat("x1a8_ballCameraBoostDampenAngle", x1a8_ballCameraBoostDampenAngle); + /* x1ac_ballCameraBoostDistance */ + __dna_docout.writeFloat("x1ac_ballCameraBoostDistance", x1ac_ballCameraBoostDistance); + /* x1b0_ballCameraBoostYawSpeed */ + __dna_docout.writeFloat("x1b0_ballCameraBoostYawSpeed", x1b0_ballCameraBoostYawSpeed); + /* x1b4_ballCameraBoostAnglePerSecond */ + __dna_docout.writeFloat("x1b4_ballCameraBoostAnglePerSecond", x1b4_ballCameraBoostAnglePerSecond); + /* x1b8_ballCameraBoostLookAtOffset */ + __dna_docout.writeVec3f("x1b8_ballCameraBoostLookAtOffset", x1b8_ballCameraBoostLookAtOffset); + /* x1c4_ballCameraBoostSpringConstant */ + __dna_docout.writeFloat("x1c4_ballCameraBoostSpringConstant", x1c4_ballCameraBoostSpringConstant); + /* x1c8_ballCameraBoostSpringMax */ + __dna_docout.writeFloat("x1c8_ballCameraBoostSpringMax", x1c8_ballCameraBoostSpringMax); + /* x1cc_ballCameraBoostSpringTardis */ + __dna_docout.writeFloat("x1cc_ballCameraBoostSpringTardis", x1cc_ballCameraBoostSpringTardis); + /* x1d0_ballCameraControlDistance */ + __dna_docout.writeFloat("x1d0_ballCameraControlDistance", x1d0_ballCameraControlDistance); + /* x1d4_ */ + __dna_docout.writeFloat("x1d4_", x1d4_); + /* x1d8_ */ + __dna_docout.writeFloat("x1d8_", x1d8_); + /* x1e4_leftStickDivisor */ + __dna_docout.writeFloat("x1e4_leftStickDivisor", x1e4_leftStickDivisor); + /* x1e8_rightStickDivisor */ + __dna_docout.writeFloat("x1e8_rightStickDivisor", x1e8_rightStickDivisor); + /* x200_ */ + __dna_docout.writeFloat("x200_", x200_); + /* x204_ballTouchRadius */ + __dna_docout.writeFloat("x204_ballTouchRadius", x204_ballTouchRadius); + /* x20c_boostBallDrainTime */ + __dna_docout.writeFloat("x20c_boostBallDrainTime", x20c_boostBallDrainTime); + /* x218_boostBallMinChargeTime */ + __dna_docout.writeFloat("x218_boostBallMinChargeTime", x218_boostBallMinChargeTime); + /* x21c_boostBallMinRelativeSpeedForDamage */ + __dna_docout.writeFloat("x21c_boostBallMinRelativeSpeedForDamage", x21c_boostBallMinRelativeSpeedForDamage); + /* x220_boostBallChargeTime0 */ + __dna_docout.writeFloat("x220_boostBallChargeTime0", x220_boostBallChargeTime0); + /* x224_boostBallChargeTime1 */ + __dna_docout.writeFloat("x224_boostBallChargeTime1", x224_boostBallChargeTime1); + /* x210_boostBallMaxChargeTime */ + __dna_docout.writeFloat("x210_boostBallMaxChargeTime", x210_boostBallMaxChargeTime); + /* x22c_boostBallIncrementalSpeed0 */ + __dna_docout.writeFloat("x22c_boostBallIncrementalSpeed0", x22c_boostBallIncrementalSpeed0); + /* x230_boostBallIncrementalSpeed1 */ + __dna_docout.writeFloat("x230_boostBallIncrementalSpeed1", x230_boostBallIncrementalSpeed1); + /* x234_boostBallIncrementalSpeed2 */ + __dna_docout.writeFloat("x234_boostBallIncrementalSpeed2", x234_boostBallIncrementalSpeed2); } -const char* CTweakBall::DNAType() -{ - return "DataSpec::DNAMP1::CTweakBall"; -} +const char* CTweakBall::DNAType() { return "DataSpec::DNAMP1::CTweakBall"; } template <> -void CTweakBall::Enumerate(typename BinarySize::StreamT& s) -{ - s += 456; +void CTweakBall::Enumerate(typename BinarySize::StreamT& s) { + s += 456; } -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakBall.hpp b/DataSpec/DNAMP1/Tweaks/CTweakBall.hpp index 875b83474..62f941d34 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakBall.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakBall.hpp @@ -3,217 +3,210 @@ #include "../../DNACommon/Tweaks/ITweakBall.hpp" #include "zeus/CVector3f.hpp" -namespace DataSpec::DNAMP1 -{ -struct CTweakBall final : public ITweakBall -{ - AT_DECL_EXPLICIT_DNA_YAML - Value x4_maxTranslationAcceleration[8]; - Value x24_translationFriction[8]; - Value x44_translationMaxSpeed[8]; - Value x64_; - Value x68_; - Value x6c_; - Value x70_; - Value x74_ballCameraAnglePerSecond; - Value x78_ballCameraOffset; - Value x84_ballCameraMinSpeedDistance; - Value x88_ballCameraMaxSpeedDistance; - Value x8c_ballCameraBackwardsDistance; - Value x90_; - Value x94_ballCameraSpringConstant; - Value x98_ballCameraSpringMax; - Value x9c_ballCameraSpringTardis; - Value xa0_ballCameraCentroidSpringConstant; - Value xa4_ballCameraCentroidSpringMax; - Value xa8_ballCameraCentroidSpringTardis; - Value xac_ballCameraCentroidDistanceSpringConstant; - Value xb0_ballCameraCentroidDistanceSpringMax; - Value xb4_ballCameraCentroidDistanceSpringTardis; - Value xb8_ballCameraLookAtSpringConstant; - Value xbc_ballCameraLookAtSpringMax; - Value xc0_ballCameraLookAtSpringTardis; - Value xc4_ballForwardBrakingAcceleration[8]; - Value xe4_ballGravity; - Value xe8_ballWaterGravity; - float xec_ = 10000.f; - float xf0_ = 1000.f; - float xf4_ = 40000.f; - float xf8_ = 40000.f; - float xfc_ = 40000.f; - float x100_ = 40000.f; - float x104_ = 40000.f; - float x108_ = 40000.f; - float x10c_ = 10000.f; - float x110_ = 1000.f; - float x114_ = 40000.f; - float x118_ = 40000.f; - float x11c_ = 40000.f; - float x120_ = 40000.f; - float x124_ = 40000.f; - float x128_ = 40000.f; - float x12c_ballSlipFactor[8] = { 10000.f, 10000.f, 1000.f, 10000.f, 2000.f, 2000.f, 2000.f, 2000.f }; - Value x14c_; - Value x150_; - Value x158_; - Value x154_; - Value x15c_; - Value x160_; - Value x164_; - Value x168_; - Value x16c_; - Value x170_conservativeDoorCamDistance; - Value x174_; - Value x178_ballCameraChaseElevation; - Value x17c_ballCameraChaseDampenAngle; - Value x180_ballCameraChaseDistance; - Value x184_ballCameraChaseYawSpeed; - Value x188_ballCameraChaseAnglePerSecond; - Value x18c_ballCameraChaseLookAtOffset; - Value x198_ballCameraChaseSpringConstant; - Value x19c_ballCameraChaseSpringMax; - Value x1a0_ballCameraChaseSpringTardis; - Value x1a4_ballCameraBoostElevation; - Value x1a8_ballCameraBoostDampenAngle; - Value x1ac_ballCameraBoostDistance; - Value x1b0_ballCameraBoostYawSpeed; - Value x1b4_ballCameraBoostAnglePerSecond; - Value x1b8_ballCameraBoostLookAtOffset; - Value x1c4_ballCameraBoostSpringConstant; - Value x1c8_ballCameraBoostSpringMax; - Value x1cc_ballCameraBoostSpringTardis; - Value x1d0_ballCameraControlDistance; - Value x1d4_; - Value x1d8_; - Value x1dc_minimumAlignmentSpeed; - Value x1e0_tireness; - Value x1ec_maxLeanAngle; - Value x1f0_tireToMarbleThresholdSpeed; - Value x1f4_marbleToTireThresholdSpeed; - Value x1f8_forceToLeanGain; - Value x1fc_leanTrackingGain; - Value x1e4_leftStickDivisor; - Value x1e8_rightStickDivisor; - Value x200_; - Value x204_ballTouchRadius; - float x208_; - Value x20c_boostBallDrainTime; - Value x218_boostBallMinChargeTime; - Value x21c_boostBallMinRelativeSpeedForDamage; - Value x220_boostBallChargeTime0; - Value x224_boostBallChargeTime1; - float x228_boostBallChargeTime2; - Value x210_boostBallMaxChargeTime; - Value x22c_boostBallIncrementalSpeed0; - Value x230_boostBallIncrementalSpeed1; - Value x234_boostBallIncrementalSpeed2; +namespace DataSpec::DNAMP1 { +struct CTweakBall final : public ITweakBall { + AT_DECL_EXPLICIT_DNA_YAML + Value x4_maxTranslationAcceleration[8]; + Value x24_translationFriction[8]; + Value x44_translationMaxSpeed[8]; + Value x64_; + Value x68_; + Value x6c_; + Value x70_; + Value x74_ballCameraAnglePerSecond; + Value x78_ballCameraOffset; + Value x84_ballCameraMinSpeedDistance; + Value x88_ballCameraMaxSpeedDistance; + Value x8c_ballCameraBackwardsDistance; + Value x90_; + Value x94_ballCameraSpringConstant; + Value x98_ballCameraSpringMax; + Value x9c_ballCameraSpringTardis; + Value xa0_ballCameraCentroidSpringConstant; + Value xa4_ballCameraCentroidSpringMax; + Value xa8_ballCameraCentroidSpringTardis; + Value xac_ballCameraCentroidDistanceSpringConstant; + Value xb0_ballCameraCentroidDistanceSpringMax; + Value xb4_ballCameraCentroidDistanceSpringTardis; + Value xb8_ballCameraLookAtSpringConstant; + Value xbc_ballCameraLookAtSpringMax; + Value xc0_ballCameraLookAtSpringTardis; + Value xc4_ballForwardBrakingAcceleration[8]; + Value xe4_ballGravity; + Value xe8_ballWaterGravity; + float xec_ = 10000.f; + float xf0_ = 1000.f; + float xf4_ = 40000.f; + float xf8_ = 40000.f; + float xfc_ = 40000.f; + float x100_ = 40000.f; + float x104_ = 40000.f; + float x108_ = 40000.f; + float x10c_ = 10000.f; + float x110_ = 1000.f; + float x114_ = 40000.f; + float x118_ = 40000.f; + float x11c_ = 40000.f; + float x120_ = 40000.f; + float x124_ = 40000.f; + float x128_ = 40000.f; + float x12c_ballSlipFactor[8] = {10000.f, 10000.f, 1000.f, 10000.f, 2000.f, 2000.f, 2000.f, 2000.f}; + Value x14c_; + Value x150_; + Value x158_; + Value x154_; + Value x15c_; + Value x160_; + Value x164_; + Value x168_; + Value x16c_; + Value x170_conservativeDoorCamDistance; + Value x174_; + Value x178_ballCameraChaseElevation; + Value x17c_ballCameraChaseDampenAngle; + Value x180_ballCameraChaseDistance; + Value x184_ballCameraChaseYawSpeed; + Value x188_ballCameraChaseAnglePerSecond; + Value x18c_ballCameraChaseLookAtOffset; + Value x198_ballCameraChaseSpringConstant; + Value x19c_ballCameraChaseSpringMax; + Value x1a0_ballCameraChaseSpringTardis; + Value x1a4_ballCameraBoostElevation; + Value x1a8_ballCameraBoostDampenAngle; + Value x1ac_ballCameraBoostDistance; + Value x1b0_ballCameraBoostYawSpeed; + Value x1b4_ballCameraBoostAnglePerSecond; + Value x1b8_ballCameraBoostLookAtOffset; + Value x1c4_ballCameraBoostSpringConstant; + Value x1c8_ballCameraBoostSpringMax; + Value x1cc_ballCameraBoostSpringTardis; + Value x1d0_ballCameraControlDistance; + Value x1d4_; + Value x1d8_; + Value x1dc_minimumAlignmentSpeed; + Value x1e0_tireness; + Value x1ec_maxLeanAngle; + Value x1f0_tireToMarbleThresholdSpeed; + Value x1f4_marbleToTireThresholdSpeed; + Value x1f8_forceToLeanGain; + Value x1fc_leanTrackingGain; + Value x1e4_leftStickDivisor; + Value x1e8_rightStickDivisor; + Value x200_; + Value x204_ballTouchRadius; + float x208_; + Value x20c_boostBallDrainTime; + Value x218_boostBallMinChargeTime; + Value x21c_boostBallMinRelativeSpeedForDamage; + Value x220_boostBallChargeTime0; + Value x224_boostBallChargeTime1; + float x228_boostBallChargeTime2; + Value x210_boostBallMaxChargeTime; + Value x22c_boostBallIncrementalSpeed0; + Value x230_boostBallIncrementalSpeed1; + Value x234_boostBallIncrementalSpeed2; - CTweakBall()=default; - CTweakBall(athena::io::IStreamReader& r) - { - this->read(r); - x6c_ = -x6c_; - x70_ = -x70_; - x74_ballCameraAnglePerSecond = zeus::degToRad(x74_ballCameraAnglePerSecond); - x90_ = zeus::degToRad(x90_); - xe4_ballGravity = -xe4_ballGravity; - xe8_ballWaterGravity = -xe8_ballWaterGravity; - x15c_ = zeus::degToRad(x15c_); - x16c_ = zeus::degToRad(x16c_); - x174_ = zeus::degToRad(x174_); - x17c_ballCameraChaseDampenAngle = zeus::degToRad(x17c_ballCameraChaseDampenAngle); - x184_ballCameraChaseYawSpeed = zeus::degToRad(x184_ballCameraChaseYawSpeed); - x188_ballCameraChaseAnglePerSecond = zeus::degToRad(x188_ballCameraChaseAnglePerSecond); - x1a8_ballCameraBoostDampenAngle = zeus::degToRad(x1a8_ballCameraBoostDampenAngle); - x1b0_ballCameraBoostYawSpeed = zeus::degToRad(x1b0_ballCameraBoostYawSpeed); - x1b4_ballCameraBoostAnglePerSecond = zeus::degToRad(x1b4_ballCameraBoostAnglePerSecond); - x1ec_maxLeanAngle = zeus::degToRad(x1ec_maxLeanAngle); - } + CTweakBall() = default; + CTweakBall(athena::io::IStreamReader& r) { + this->read(r); + x6c_ = -x6c_; + x70_ = -x70_; + x74_ballCameraAnglePerSecond = zeus::degToRad(x74_ballCameraAnglePerSecond); + x90_ = zeus::degToRad(x90_); + xe4_ballGravity = -xe4_ballGravity; + xe8_ballWaterGravity = -xe8_ballWaterGravity; + x15c_ = zeus::degToRad(x15c_); + x16c_ = zeus::degToRad(x16c_); + x174_ = zeus::degToRad(x174_); + x17c_ballCameraChaseDampenAngle = zeus::degToRad(x17c_ballCameraChaseDampenAngle); + x184_ballCameraChaseYawSpeed = zeus::degToRad(x184_ballCameraChaseYawSpeed); + x188_ballCameraChaseAnglePerSecond = zeus::degToRad(x188_ballCameraChaseAnglePerSecond); + x1a8_ballCameraBoostDampenAngle = zeus::degToRad(x1a8_ballCameraBoostDampenAngle); + x1b0_ballCameraBoostYawSpeed = zeus::degToRad(x1b0_ballCameraBoostYawSpeed); + x1b4_ballCameraBoostAnglePerSecond = zeus::degToRad(x1b4_ballCameraBoostAnglePerSecond); + x1ec_maxLeanAngle = zeus::degToRad(x1ec_maxLeanAngle); + } - float GetMaxBallTranslationAcceleration(int s) const { return x4_maxTranslationAcceleration[s]; } - float GetBallTranslationFriction(int s) const { return x24_translationFriction[s]; } - float GetBallTranslationMaxSpeed(int s) const { return x44_translationMaxSpeed[s]; } - float GetBallCameraElevation() const { return 2.736f; } - float GetBallCameraAnglePerSecond() const { return x74_ballCameraAnglePerSecond; } - const zeus::CVector3f& GetBallCameraOffset() const { return x78_ballCameraOffset; } - float GetBallCameraMinSpeedDistance() const { return x84_ballCameraMinSpeedDistance; } - float GetBallCameraMaxSpeedDistance() const { return x88_ballCameraMaxSpeedDistance; } - float GetBallCameraBackwardsDistance() const { return x8c_ballCameraBackwardsDistance; } - float GetBallCameraSpringConstant() const { return x94_ballCameraSpringConstant; } - float GetBallCameraSpringMax() const { return x98_ballCameraSpringMax; } - float GetBallCameraSpringTardis() const { return x9c_ballCameraSpringTardis; } - float GetBallCameraCentroidSpringConstant() const { return xa0_ballCameraCentroidSpringConstant; } - float GetBallCameraCentroidSpringMax() const { return xa4_ballCameraCentroidSpringMax; } - float GetBallCameraCentroidSpringTardis() const { return xa8_ballCameraCentroidSpringTardis; } - float GetBallCameraCentroidDistanceSpringConstant() const { return xac_ballCameraCentroidDistanceSpringConstant; } - float GetBallCameraCentroidDistanceSpringMax() const { return xb0_ballCameraCentroidDistanceSpringMax; } - float GetBallCameraCentroidDistanceSpringTardis() const { return xb4_ballCameraCentroidDistanceSpringTardis; } - float GetBallCameraLookAtSpringConstant() const { return xb8_ballCameraLookAtSpringConstant; } - float GetBallCameraLookAtSpringMax() const { return xbc_ballCameraLookAtSpringMax; } - float GetBallCameraLookAtSpringTardis() const { return xc0_ballCameraLookAtSpringTardis; } - float GetBallForwardBrakingAcceleration(int s) const { return xc4_ballForwardBrakingAcceleration[s]; } - float GetBallGravity() const { return xe4_ballGravity; } - float GetBallWaterGravity() const { return xe8_ballWaterGravity; } - float GetBallSlipFactor(int s) const { return x12c_ballSlipFactor[s]; } - float GetConservativeDoorCameraDistance() const { return x170_conservativeDoorCamDistance; } - float GetBallCameraChaseElevation() const { return x178_ballCameraChaseElevation; } - float GetBallCameraChaseDampenAngle() const { return x17c_ballCameraChaseDampenAngle; } - float GetBallCameraChaseDistance() const { return x180_ballCameraChaseDistance; } - float GetBallCameraChaseYawSpeed() const { return x184_ballCameraChaseYawSpeed; } - float GetBallCameraChaseAnglePerSecond() const { return x188_ballCameraChaseAnglePerSecond; } - const zeus::CVector3f& GetBallCameraChaseLookAtOffset() const { return x18c_ballCameraChaseLookAtOffset; } - float GetBallCameraChaseSpringConstant() const { return x198_ballCameraChaseSpringConstant; } - float GetBallCameraChaseSpringMax() const { return x19c_ballCameraChaseSpringMax; } - float GetBallCameraChaseSpringTardis() const { return x1a0_ballCameraChaseSpringTardis; } - float GetBallCameraBoostElevation() const { return x1a4_ballCameraBoostElevation; } - float GetBallCameraBoostDampenAngle() const { return x1a8_ballCameraBoostDampenAngle; } - float GetBallCameraBoostDistance() const { return x1ac_ballCameraBoostDistance; } - float GetBallCameraBoostYawSpeed() const { return x1b0_ballCameraBoostYawSpeed; } - float GetBallCameraBoostAnglePerSecond() const { return x1b4_ballCameraBoostAnglePerSecond; } - const zeus::CVector3f& GetBallCameraBoostLookAtOffset() const { return x1b8_ballCameraBoostLookAtOffset; } - float GetBallCameraBoostSpringConstant() const { return x1c4_ballCameraBoostSpringConstant; } - float GetBallCameraBoostSpringMax() const { return x1c8_ballCameraBoostSpringMax; } - float GetBallCameraBoostSpringTardis() const { return x1cc_ballCameraBoostSpringTardis; } - float GetBallCameraControlDistance() const { return x1d0_ballCameraControlDistance; } - float GetMinimumAlignmentSpeed() const { return x1dc_minimumAlignmentSpeed; } - float GetTireness() const { return x1e0_tireness; } - float GetMaxLeanAngle() const { return x1ec_maxLeanAngle; } - float GetTireToMarbleThresholdSpeed() const { return x1f0_tireToMarbleThresholdSpeed; } - float GetMarbleToTireThresholdSpeed() const { return x1f4_marbleToTireThresholdSpeed; } - float GetForceToLeanGain() const { return x1f8_forceToLeanGain; } - float GetLeanTrackingGain() const { return x1fc_leanTrackingGain; } - float GetLeftStickDivisor() const { return x1e4_leftStickDivisor; } - float GetRightStickDivisor() const { return x1e8_rightStickDivisor; } - float GetBallTouchRadius() const { return x204_ballTouchRadius; } - float GetBoostBallDrainTime() const { return x20c_boostBallDrainTime; } - float GetBoostBallMaxChargeTime() const { return x210_boostBallMaxChargeTime; } - float GetBoostBallMinChargeTime() const { return x218_boostBallMinChargeTime; } - float GetBoostBallMinRelativeSpeedForDamage() const { return x21c_boostBallMinRelativeSpeedForDamage; } - float GetBoostBallChargeTimeTable(int i) const - { - switch (i) - { - default: - case 0: - return x220_boostBallChargeTime0; - case 1: - return x224_boostBallChargeTime1; - case 2: - return x228_boostBallChargeTime2; - } + float GetMaxBallTranslationAcceleration(int s) const { return x4_maxTranslationAcceleration[s]; } + float GetBallTranslationFriction(int s) const { return x24_translationFriction[s]; } + float GetBallTranslationMaxSpeed(int s) const { return x44_translationMaxSpeed[s]; } + float GetBallCameraElevation() const { return 2.736f; } + float GetBallCameraAnglePerSecond() const { return x74_ballCameraAnglePerSecond; } + const zeus::CVector3f& GetBallCameraOffset() const { return x78_ballCameraOffset; } + float GetBallCameraMinSpeedDistance() const { return x84_ballCameraMinSpeedDistance; } + float GetBallCameraMaxSpeedDistance() const { return x88_ballCameraMaxSpeedDistance; } + float GetBallCameraBackwardsDistance() const { return x8c_ballCameraBackwardsDistance; } + float GetBallCameraSpringConstant() const { return x94_ballCameraSpringConstant; } + float GetBallCameraSpringMax() const { return x98_ballCameraSpringMax; } + float GetBallCameraSpringTardis() const { return x9c_ballCameraSpringTardis; } + float GetBallCameraCentroidSpringConstant() const { return xa0_ballCameraCentroidSpringConstant; } + float GetBallCameraCentroidSpringMax() const { return xa4_ballCameraCentroidSpringMax; } + float GetBallCameraCentroidSpringTardis() const { return xa8_ballCameraCentroidSpringTardis; } + float GetBallCameraCentroidDistanceSpringConstant() const { return xac_ballCameraCentroidDistanceSpringConstant; } + float GetBallCameraCentroidDistanceSpringMax() const { return xb0_ballCameraCentroidDistanceSpringMax; } + float GetBallCameraCentroidDistanceSpringTardis() const { return xb4_ballCameraCentroidDistanceSpringTardis; } + float GetBallCameraLookAtSpringConstant() const { return xb8_ballCameraLookAtSpringConstant; } + float GetBallCameraLookAtSpringMax() const { return xbc_ballCameraLookAtSpringMax; } + float GetBallCameraLookAtSpringTardis() const { return xc0_ballCameraLookAtSpringTardis; } + float GetBallForwardBrakingAcceleration(int s) const { return xc4_ballForwardBrakingAcceleration[s]; } + float GetBallGravity() const { return xe4_ballGravity; } + float GetBallWaterGravity() const { return xe8_ballWaterGravity; } + float GetBallSlipFactor(int s) const { return x12c_ballSlipFactor[s]; } + float GetConservativeDoorCameraDistance() const { return x170_conservativeDoorCamDistance; } + float GetBallCameraChaseElevation() const { return x178_ballCameraChaseElevation; } + float GetBallCameraChaseDampenAngle() const { return x17c_ballCameraChaseDampenAngle; } + float GetBallCameraChaseDistance() const { return x180_ballCameraChaseDistance; } + float GetBallCameraChaseYawSpeed() const { return x184_ballCameraChaseYawSpeed; } + float GetBallCameraChaseAnglePerSecond() const { return x188_ballCameraChaseAnglePerSecond; } + const zeus::CVector3f& GetBallCameraChaseLookAtOffset() const { return x18c_ballCameraChaseLookAtOffset; } + float GetBallCameraChaseSpringConstant() const { return x198_ballCameraChaseSpringConstant; } + float GetBallCameraChaseSpringMax() const { return x19c_ballCameraChaseSpringMax; } + float GetBallCameraChaseSpringTardis() const { return x1a0_ballCameraChaseSpringTardis; } + float GetBallCameraBoostElevation() const { return x1a4_ballCameraBoostElevation; } + float GetBallCameraBoostDampenAngle() const { return x1a8_ballCameraBoostDampenAngle; } + float GetBallCameraBoostDistance() const { return x1ac_ballCameraBoostDistance; } + float GetBallCameraBoostYawSpeed() const { return x1b0_ballCameraBoostYawSpeed; } + float GetBallCameraBoostAnglePerSecond() const { return x1b4_ballCameraBoostAnglePerSecond; } + const zeus::CVector3f& GetBallCameraBoostLookAtOffset() const { return x1b8_ballCameraBoostLookAtOffset; } + float GetBallCameraBoostSpringConstant() const { return x1c4_ballCameraBoostSpringConstant; } + float GetBallCameraBoostSpringMax() const { return x1c8_ballCameraBoostSpringMax; } + float GetBallCameraBoostSpringTardis() const { return x1cc_ballCameraBoostSpringTardis; } + float GetBallCameraControlDistance() const { return x1d0_ballCameraControlDistance; } + float GetMinimumAlignmentSpeed() const { return x1dc_minimumAlignmentSpeed; } + float GetTireness() const { return x1e0_tireness; } + float GetMaxLeanAngle() const { return x1ec_maxLeanAngle; } + float GetTireToMarbleThresholdSpeed() const { return x1f0_tireToMarbleThresholdSpeed; } + float GetMarbleToTireThresholdSpeed() const { return x1f4_marbleToTireThresholdSpeed; } + float GetForceToLeanGain() const { return x1f8_forceToLeanGain; } + float GetLeanTrackingGain() const { return x1fc_leanTrackingGain; } + float GetLeftStickDivisor() const { return x1e4_leftStickDivisor; } + float GetRightStickDivisor() const { return x1e8_rightStickDivisor; } + float GetBallTouchRadius() const { return x204_ballTouchRadius; } + float GetBoostBallDrainTime() const { return x20c_boostBallDrainTime; } + float GetBoostBallMaxChargeTime() const { return x210_boostBallMaxChargeTime; } + float GetBoostBallMinChargeTime() const { return x218_boostBallMinChargeTime; } + float GetBoostBallMinRelativeSpeedForDamage() const { return x21c_boostBallMinRelativeSpeedForDamage; } + float GetBoostBallChargeTimeTable(int i) const { + switch (i) { + default: + case 0: + return x220_boostBallChargeTime0; + case 1: + return x224_boostBallChargeTime1; + case 2: + return x228_boostBallChargeTime2; } - float GetBoostBallIncrementalSpeedTable(int i) const - { - switch (i) - { - default: - case 0: - return x22c_boostBallIncrementalSpeed0; - case 1: - return x230_boostBallIncrementalSpeed1; - case 2: - return x234_boostBallIncrementalSpeed2; - } + } + float GetBoostBallIncrementalSpeedTable(int i) const { + switch (i) { + default: + case 0: + return x22c_boostBallIncrementalSpeed0; + case 1: + return x230_boostBallIncrementalSpeed1; + case 2: + return x234_boostBallIncrementalSpeed2; } + } }; -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakCameraBob.hpp b/DataSpec/DNAMP1/Tweaks/CTweakCameraBob.hpp index af6876517..743705047 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakCameraBob.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakCameraBob.hpp @@ -2,25 +2,22 @@ #include "../../DNACommon/DNACommon.hpp" -namespace DataSpec::DNAMP1 -{ -struct CTweakCameraBob : BigDNA -{ - AT_DECL_DNA_YAML - Value cameraBobExtentX; - Value cameraBobExtentY; - Value cameraBobPeriod; - Value orbitScale; - Value maxOrbitScale; - Value slowSpeedPeriodScale; - Value targetMagnitudeTrackingRate; - Value landingBobSpringConstant; - Value viewWanderRadius; - Value viewWanderSpeedMin; - Value viewWanderSpeedMax; - Value viewWanderRollVariation; - Value gunBobMagnitude; - Value helmetBobMagnitude; +namespace DataSpec::DNAMP1 { +struct CTweakCameraBob : BigDNA { + AT_DECL_DNA_YAML + Value cameraBobExtentX; + Value cameraBobExtentY; + Value cameraBobPeriod; + Value orbitScale; + Value maxOrbitScale; + Value slowSpeedPeriodScale; + Value targetMagnitudeTrackingRate; + Value landingBobSpringConstant; + Value viewWanderRadius; + Value viewWanderSpeedMin; + Value viewWanderSpeedMax; + Value viewWanderRollVariation; + Value gunBobMagnitude; + Value helmetBobMagnitude; }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGame.cpp b/DataSpec/DNAMP1/Tweaks/CTweakGame.cpp index 64b65dc2b..50ff36f54 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGame.cpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGame.cpp @@ -1,11 +1,10 @@ #include "CTweakGame.hpp" #include "hecl/CVarManager.hpp" -namespace DataSpec::DNAMP1 -{ -void CTweakGame::initCVars(hecl::CVarManager* mgr) -{ - //mgr->findOrMakeCVar("tweaks.game.hardmodeDamageMult", "", x60_hardmodeDamageMult, hecl::CVar::EFlags::Game | hecl::CVar::Archive | hecl::CVar::Cheat); - //mgr->findOrMakeCVar("tweaks.game.hardmodeWeaponMult", "", x64_hardmodeWeaponMult, hecl::CVar::EFlags::Game | hecl::CVar::Archive | hecl::CVar::Cheat); -} +namespace DataSpec::DNAMP1 { +void CTweakGame::initCVars(hecl::CVarManager* mgr) { + // mgr->findOrMakeCVar("tweaks.game.hardmodeDamageMult", "", x60_hardmodeDamageMult, hecl::CVar::EFlags::Game | + // hecl::CVar::Archive | hecl::CVar::Cheat); mgr->findOrMakeCVar("tweaks.game.hardmodeWeaponMult", "", + // x64_hardmodeWeaponMult, hecl::CVar::EFlags::Game | hecl::CVar::Archive | hecl::CVar::Cheat); } +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp b/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp index ea139b5f2..ec90d88ee 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp @@ -2,60 +2,56 @@ #include "../../DNACommon/Tweaks/ITweakGame.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CTweakGame final : ITweakGame -{ - AT_DECL_DNA_YAML - String<-1> x4_worldPrefix; - String<-1> x14_ruinsArea; // ???? - Value x24_fov; - Value x28_unknown1; - Value x29_unknown2; - Value x2a_unknown3; - Value x2b_splashScreensDisabled; - Value x2c_unknown5; - Value x30_pressStartDelay; - Value x34_wavecapIntensityNormal; - Value x38_wavecapIntensityPoison; - Value x3c_wavecapIntensityLava; - Value x40_rippleIntensityNormal; - Value x44_rippleIntentityPoison; - Value x48_rippleIntensityLava; - Value x4c_fluidEnvBumpScale; - Value x50_waterFogDistanceBase; - Value x54_waterFogDistanceRange; - Value x58_gravityWaterFogDistanceBase; - Value x5c_gravityWaterFogDistanceRange; - Value x60_hardmodeDamageMult; - Value x64_hardmodeWeaponMult; +struct CTweakGame final : ITweakGame { + AT_DECL_DNA_YAML + String<-1> x4_worldPrefix; + String<-1> x14_ruinsArea; // ???? + Value x24_fov; + Value x28_unknown1; + Value x29_unknown2; + Value x2a_unknown3; + Value x2b_splashScreensDisabled; + Value x2c_unknown5; + Value x30_pressStartDelay; + Value x34_wavecapIntensityNormal; + Value x38_wavecapIntensityPoison; + Value x3c_wavecapIntensityLava; + Value x40_rippleIntensityNormal; + Value x44_rippleIntentityPoison; + Value x48_rippleIntensityLava; + Value x4c_fluidEnvBumpScale; + Value x50_waterFogDistanceBase; + Value x54_waterFogDistanceRange; + Value x58_gravityWaterFogDistanceBase; + Value x5c_gravityWaterFogDistanceRange; + Value x60_hardmodeDamageMult; + Value x64_hardmodeWeaponMult; - std::string_view GetWorldPrefix() const { return x4_worldPrefix; } - bool GetSplashScreensDisabled() const { return x2b_splashScreensDisabled; } - float GetFirstPersonFOV() const { return x24_fov; } - float GetPressStartDelay() const { return x30_pressStartDelay; } - float GetWavecapIntensityNormal() const { return x34_wavecapIntensityNormal; } - float GetWavecapIntensityPoison() const { return x38_wavecapIntensityPoison; } - float GetWavecapIntensityLava() const { return x3c_wavecapIntensityLava; } - float GetRippleIntensityNormal() const { return x40_rippleIntensityNormal; } - float GetRippleIntensityPoison() const { return x44_rippleIntentityPoison; } - float GetRippleIntensityLava() const { return x48_rippleIntensityLava; } - float GetFluidEnvBumpScale() const { return x4c_fluidEnvBumpScale; } - float GetWaterFogDistanceBase() const { return x50_waterFogDistanceBase; } - float GetWaterFogDistanceRange() const { return x54_waterFogDistanceRange; } - float GetGravityWaterFogDistanceBase() const { return x58_gravityWaterFogDistanceBase; } - float GetGravityWaterFogDistanceRange() const { return x5c_gravityWaterFogDistanceRange; } - float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; } - float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; } - CTweakGame() = default; - CTweakGame(athena::io::IStreamReader& in) - { - this->read(in); - x2b_splashScreensDisabled = false; - } + std::string_view GetWorldPrefix() const { return x4_worldPrefix; } + bool GetSplashScreensDisabled() const { return x2b_splashScreensDisabled; } + float GetFirstPersonFOV() const { return x24_fov; } + float GetPressStartDelay() const { return x30_pressStartDelay; } + float GetWavecapIntensityNormal() const { return x34_wavecapIntensityNormal; } + float GetWavecapIntensityPoison() const { return x38_wavecapIntensityPoison; } + float GetWavecapIntensityLava() const { return x3c_wavecapIntensityLava; } + float GetRippleIntensityNormal() const { return x40_rippleIntensityNormal; } + float GetRippleIntensityPoison() const { return x44_rippleIntentityPoison; } + float GetRippleIntensityLava() const { return x48_rippleIntensityLava; } + float GetFluidEnvBumpScale() const { return x4c_fluidEnvBumpScale; } + float GetWaterFogDistanceBase() const { return x50_waterFogDistanceBase; } + float GetWaterFogDistanceRange() const { return x54_waterFogDistanceRange; } + float GetGravityWaterFogDistanceBase() const { return x58_gravityWaterFogDistanceBase; } + float GetGravityWaterFogDistanceRange() const { return x5c_gravityWaterFogDistanceRange; } + float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; } + float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; } + CTweakGame() = default; + CTweakGame(athena::io::IStreamReader& in) { + this->read(in); + x2b_splashScreensDisabled = false; + } - void initCVars(hecl::CVarManager* mgr); + void initCVars(hecl::CVarManager* mgr); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp b/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp index 257b34a0d..6d5edf84c 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGui.hpp @@ -2,334 +2,332 @@ #include "../../DNACommon/Tweaks/ITweakGui.hpp" -namespace DataSpec::DNAMP1 -{ -struct CTweakGui final : ITweakGui -{ - AT_DECL_DNA_YAML - Value x4_; - Value x8_mapAlphaInterp; - Value xc_pauseBlurFactor; - Value x10_radarXYRadius; - Value x14_; - Value x18_; - Value x1c_; - Value x20_; - Value x24_radarZRadius; - Value x28_radarZCloseRadius; - atUint32 x2c_ = 0; - Value x30_; - Value x34_energyBarFilledSpeed; - Value x38_energyBarShadowSpeed; - Value x3c_energyBarDrainDelay; - Value x40_energyBarAlwaysResetDelay; - Value x44_hudDamagePracticalsGainConstant; - Value x48_hudDamagePracticalsGainLinear; - Value x4c_hudDamagePracticalsInitConstant; - Value x50_hudDamagePracticalsInitLinear; - Value x54_hudDamageLightSpotAngle; - Value x58_damageLightAngleC; - Value x5c_damageLightAngleL; - Value x60_damageLightAngleQ; - Value x64_damageLightPreTranslate; - Value x70_damageLightCenterTranslate; - Value x7c_damageLightXfXAngle; - Value x80_damageLightXfZAngle; - Value x84_hudDecoShakeTranslateVelConstant; - Value x88_hudDecoShakeTranslateVelLinear; - Value x8c_maxDecoDamageShakeTranslate; - Value x90_decoDamageShakeDeceleration; - Value x94_decoShakeGainConstant; - Value x98_decoShakeGainLinear; - Value x9c_decoShakeInitConstant; - Value xa0_decoShakeInitLinear; - Value xa4_maxDecoDamageShakeRotate; - Value xa8_hudCamFovTweak; - Value xac_hudCamYTweak; - Value xb0_hudCamZTweak; - Value xb4_; - Value xb8_; - Value xbc_; - Value xc0_beamVisorMenuAnimTime; - Value xc4_visorBeamMenuItemActiveScale; - Value xc8_visorBeamMenuItemInactiveScale; - Value xcc_visorBeamMenuItemTranslate; - Value xd0_; - Value xd4_; - Value xd8_; - Value xdc_; - Value xe0_; - Value xe4_threatRange; - Value xe8_radarScopeCoordRadius; - Value xec_radarPlayerPaintRadius; - Value xf0_radarEnemyPaintRadius; - Value xf4_missileArrowVisTime; - Value xf8_hudVisMode; - Value xfc_helmetVisMode; - Value x100_enableAutoMapper; - Value x104_; - Value x108_enableTargetingManager; - Value x10c_enablePlayerVisor; - Value x110_threatWarningFraction; - Value x114_missileWarningFraction; - Value x118_freeLookFadeTime; - Value x11c_; - Value x120_; - Value x124_; - Value x128_; - Value x12c_freeLookSfxPitchScale; - Value x130_noAbsoluteFreeLookSfxPitch; - Value x134_; - Value x138_; - Value x13c_faceReflectionOrthoWidth; - Value x140_faceReflectionOrthoHeight; - Value x144_faceReflectionDistance; - Value x148_faceReflectionHeight; - Value x14c_faceReflectionAspect; - String<-1> x150_; - String<-1> x160_; - String<-1> x170_; - String<-1> x180_; - String<-1> x190_; - Value x1a0_missileWarningPulseTime; - Value x1a4_explosionLightFalloffMultConstant; - Value x1a8_explosionLightFalloffMultLinear; - Value x1ac_explosionLightFalloffMultQuadratic; - Value x1b0_; - Value x1b4_hudDamagePeakFactor; - Value x1b8_hudDamageFilterGainConstant; - Value x1bc_hudDamageFilterGainLinear; - Value x1c0_hudDamageFilterInitConstant; - Value x1c4_hudDamageFilterInitLinear; - Value x1c8_energyDrainModPeriod; - Value x1cc_energyDrainSinusoidalPulse; - Value x1cd_energyDrainFilterAdditive; - Value x1d0_hudDamagePulseDuration; - Value x1d4_hudDamageColorGain; - Value x1d8_hudDecoShakeTranslateGain; - Value x1dc_hudLagOffsetScale; - Value x1e0_; - Value x1e4_; - Value x1e8_; - Value x1ec_; - Value x1f0_; - Value x1f4_; - Value x1f8_; - Value x1fc_; - zeus::CColor x200_; - float x204_xrayBlurScaleLinear = 0.0014f; - float x208_xrayBlurScaleQuadratic = 0.0000525f; - Value x20c_; - Value x210_scanSidesAngle; - Value x214_scanSidesXScale; - Value x218_scanSidesPositionEnd; - Value x21c_; - Value x220_scanSidesDuration; - Value x224_scanSidesStartTime; - float x228_scanSidesEndTime; - Value x22c_scanDataDotRadius; - Value x230_scanDataDotPosRandMag; - Value x234_scanDataDotSeekDurationMin; - Value x238_scanDataDotSeekDurationMax; - Value x23c_scanDataDotHoldDurationMin; - Value x240_scanDataDotHoldDurationMax; - Value x244_scanAppearanceDuration; - Value x248_scanPaneFlashFactor; - Value x24c_scanPaneFadeInTime; - Value x250_scanPaneFadeOutTime; - Value x254_ballViewportYReduction; - Value x258_scanWindowIdleW; - Value x25c_scanWindowIdleH; - Value x260_scanWindowActiveW; - Value x264_scanWindowActiveH; - Value x268_scanWindowMagnification; - Value x26c_scanWindowScanningAspect; - Value x270_scanSidesPositionStart; - Value x274_showAutomapperInMorphball; - bool x275_latchArticleText = true; - Value x278_wtMgrCharsPerSfx; - Value x27c_xrayFogMode; - Value x280_xrayFogNearZ; - Value x284_xrayFogFarZ; - DNAColor x288_xrayFogColor; - Value x28c_thermalVisorLevel; - DNAColor x290_thermalVisorColor; - DNAColor x294_hudLightAddPerVisor[4]; - DNAColor x2a4_hudLightMultiplyPerVisor[4]; - DNAColor x2b4_hudReflectivityLightColor; - Value x2b8_hudLightAttMulConstant; - Value x2bc_hudLightAttMulLinear; - Value x2c0_hudLightAttMulQuadratic; - Value m_scanSpeedsCount; - Vector x2c4_scanSpeeds; - String<-1> x2d0_; - String<-1> x2e0_; - String<-1> x2f0_; - DNAColor x300_; - DNAColor x304_; - Value x308_; - Value x30c_; - Value x310_; - String<-1> x314_; - String<-1> x324_; - String<-1> x334_; - DNAColor x344_; - DNAColor x348_; - DNAColor x34c_; - DNAColor x350_; - DNAColor x354_; - DNAColor x358_; - Value x35c_; - Value x360_; - Value x364_; +namespace DataSpec::DNAMP1 { +struct CTweakGui final : ITweakGui { + AT_DECL_DNA_YAML + Value x4_; + Value x8_mapAlphaInterp; + Value xc_pauseBlurFactor; + Value x10_radarXYRadius; + Value x14_; + Value x18_; + Value x1c_; + Value x20_; + Value x24_radarZRadius; + Value x28_radarZCloseRadius; + atUint32 x2c_ = 0; + Value x30_; + Value x34_energyBarFilledSpeed; + Value x38_energyBarShadowSpeed; + Value x3c_energyBarDrainDelay; + Value x40_energyBarAlwaysResetDelay; + Value x44_hudDamagePracticalsGainConstant; + Value x48_hudDamagePracticalsGainLinear; + Value x4c_hudDamagePracticalsInitConstant; + Value x50_hudDamagePracticalsInitLinear; + Value x54_hudDamageLightSpotAngle; + Value x58_damageLightAngleC; + Value x5c_damageLightAngleL; + Value x60_damageLightAngleQ; + Value x64_damageLightPreTranslate; + Value x70_damageLightCenterTranslate; + Value x7c_damageLightXfXAngle; + Value x80_damageLightXfZAngle; + Value x84_hudDecoShakeTranslateVelConstant; + Value x88_hudDecoShakeTranslateVelLinear; + Value x8c_maxDecoDamageShakeTranslate; + Value x90_decoDamageShakeDeceleration; + Value x94_decoShakeGainConstant; + Value x98_decoShakeGainLinear; + Value x9c_decoShakeInitConstant; + Value xa0_decoShakeInitLinear; + Value xa4_maxDecoDamageShakeRotate; + Value xa8_hudCamFovTweak; + Value xac_hudCamYTweak; + Value xb0_hudCamZTweak; + Value xb4_; + Value xb8_; + Value xbc_; + Value xc0_beamVisorMenuAnimTime; + Value xc4_visorBeamMenuItemActiveScale; + Value xc8_visorBeamMenuItemInactiveScale; + Value xcc_visorBeamMenuItemTranslate; + Value xd0_; + Value xd4_; + Value xd8_; + Value xdc_; + Value xe0_; + Value xe4_threatRange; + Value xe8_radarScopeCoordRadius; + Value xec_radarPlayerPaintRadius; + Value xf0_radarEnemyPaintRadius; + Value xf4_missileArrowVisTime; + Value xf8_hudVisMode; + Value xfc_helmetVisMode; + Value x100_enableAutoMapper; + Value x104_; + Value x108_enableTargetingManager; + Value x10c_enablePlayerVisor; + Value x110_threatWarningFraction; + Value x114_missileWarningFraction; + Value x118_freeLookFadeTime; + Value x11c_; + Value x120_; + Value x124_; + Value x128_; + Value x12c_freeLookSfxPitchScale; + Value x130_noAbsoluteFreeLookSfxPitch; + Value x134_; + Value x138_; + Value x13c_faceReflectionOrthoWidth; + Value x140_faceReflectionOrthoHeight; + Value x144_faceReflectionDistance; + Value x148_faceReflectionHeight; + Value x14c_faceReflectionAspect; + String<-1> x150_; + String<-1> x160_; + String<-1> x170_; + String<-1> x180_; + String<-1> x190_; + Value x1a0_missileWarningPulseTime; + Value x1a4_explosionLightFalloffMultConstant; + Value x1a8_explosionLightFalloffMultLinear; + Value x1ac_explosionLightFalloffMultQuadratic; + Value x1b0_; + Value x1b4_hudDamagePeakFactor; + Value x1b8_hudDamageFilterGainConstant; + Value x1bc_hudDamageFilterGainLinear; + Value x1c0_hudDamageFilterInitConstant; + Value x1c4_hudDamageFilterInitLinear; + Value x1c8_energyDrainModPeriod; + Value x1cc_energyDrainSinusoidalPulse; + Value x1cd_energyDrainFilterAdditive; + Value x1d0_hudDamagePulseDuration; + Value x1d4_hudDamageColorGain; + Value x1d8_hudDecoShakeTranslateGain; + Value x1dc_hudLagOffsetScale; + Value x1e0_; + Value x1e4_; + Value x1e8_; + Value x1ec_; + Value x1f0_; + Value x1f4_; + Value x1f8_; + Value x1fc_; + zeus::CColor x200_; + float x204_xrayBlurScaleLinear = 0.0014f; + float x208_xrayBlurScaleQuadratic = 0.0000525f; + Value x20c_; + Value x210_scanSidesAngle; + Value x214_scanSidesXScale; + Value x218_scanSidesPositionEnd; + Value x21c_; + Value x220_scanSidesDuration; + Value x224_scanSidesStartTime; + float x228_scanSidesEndTime; + Value x22c_scanDataDotRadius; + Value x230_scanDataDotPosRandMag; + Value x234_scanDataDotSeekDurationMin; + Value x238_scanDataDotSeekDurationMax; + Value x23c_scanDataDotHoldDurationMin; + Value x240_scanDataDotHoldDurationMax; + Value x244_scanAppearanceDuration; + Value x248_scanPaneFlashFactor; + Value x24c_scanPaneFadeInTime; + Value x250_scanPaneFadeOutTime; + Value x254_ballViewportYReduction; + Value x258_scanWindowIdleW; + Value x25c_scanWindowIdleH; + Value x260_scanWindowActiveW; + Value x264_scanWindowActiveH; + Value x268_scanWindowMagnification; + Value x26c_scanWindowScanningAspect; + Value x270_scanSidesPositionStart; + Value x274_showAutomapperInMorphball; + bool x275_latchArticleText = true; + Value x278_wtMgrCharsPerSfx; + Value x27c_xrayFogMode; + Value x280_xrayFogNearZ; + Value x284_xrayFogFarZ; + DNAColor x288_xrayFogColor; + Value x28c_thermalVisorLevel; + DNAColor x290_thermalVisorColor; + DNAColor x294_hudLightAddPerVisor[4]; + DNAColor x2a4_hudLightMultiplyPerVisor[4]; + DNAColor x2b4_hudReflectivityLightColor; + Value x2b8_hudLightAttMulConstant; + Value x2bc_hudLightAttMulLinear; + Value x2c0_hudLightAttMulQuadratic; + Value m_scanSpeedsCount; + Vector x2c4_scanSpeeds; + String<-1> x2d0_; + String<-1> x2e0_; + String<-1> x2f0_; + DNAColor x300_; + DNAColor x304_; + Value x308_; + Value x30c_; + Value x310_; + String<-1> x314_; + String<-1> x324_; + String<-1> x334_; + DNAColor x344_; + DNAColor x348_; + DNAColor x34c_; + DNAColor x350_; + DNAColor x354_; + DNAColor x358_; + Value x35c_; + Value x360_; + Value x364_; - CTweakGui() = default; - CTweakGui(athena::io::IStreamReader& r) { this->read(r); FixupValues(); } + CTweakGui() = default; + CTweakGui(athena::io::IStreamReader& r) { + this->read(r); + FixupValues(); + } - float GetMapAlphaInterpolant() const { return x8_mapAlphaInterp; } - float GetPauseBlurFactor() const { return xc_pauseBlurFactor; } - float GetRadarXYRadius() const { return x10_radarXYRadius; } - float GetRadarZRadius() const { return x24_radarZRadius; } - float GetRadarZCloseRadius() const { return x28_radarZCloseRadius; } - float GetEnergyBarFilledSpeed() const { return x34_energyBarFilledSpeed; } - float GetEnergyBarShadowSpeed() const { return x38_energyBarShadowSpeed; } - float GetEnergyBarDrainDelay() const { return x3c_energyBarDrainDelay; } - bool GetEnergyBarAlwaysResetDelay() const { return x40_energyBarAlwaysResetDelay; } - float GetHudDamagePracticalsGainConstant() const { return x44_hudDamagePracticalsGainConstant; } - float GetHudDamagePracticalsGainLinear() const { return x48_hudDamagePracticalsGainLinear; } - float GetHudDamagePracticalsInitConstant() const { return x4c_hudDamagePracticalsInitConstant; } - float GetHudDamagePracticalsInitLinear() const { return x50_hudDamagePracticalsInitLinear; } - float GetHudDamageLightSpotAngle() const { return x54_hudDamageLightSpotAngle; } - float GetDamageLightAngleC() const { return x58_damageLightAngleC; } - float GetDamageLightAngleL() const { return x5c_damageLightAngleL; } - float GetDamageLightAngleQ() const { return x60_damageLightAngleQ; } - atVec3f GetDamageLightPreTranslate() const { return x64_damageLightPreTranslate; } - atVec3f GetDamageLightCenterTranslate() const { return x70_damageLightCenterTranslate; } - float GetDamageLightXfXAngle() const { return x7c_damageLightXfXAngle; } - float GetDamageLightXfZAngle() const { return x80_damageLightXfZAngle; } - float GetHudDecoShakeTranslateVelConstant() const { return x84_hudDecoShakeTranslateVelConstant; } - float GetHudDecoShakeTranslateVelLinear() const { return x88_hudDecoShakeTranslateVelLinear; } - float GetMaxDecoDamageShakeTranslate() const { return x8c_maxDecoDamageShakeTranslate; } - float GetDecoDamageShakeDeceleration() const { return x90_decoDamageShakeDeceleration; } - float GetDecoShakeGainConstant() const { return x94_decoShakeGainConstant; } - float GetDecoShakeGainLinear() const { return x98_decoShakeGainLinear; } - float GetDecoShakeInitConstant() const { return x9c_decoShakeInitConstant; } - float GetDecoShakeInitLinear() const { return xa0_decoShakeInitLinear; } - float GetMaxDecoDamageShakeRotate() const { return xa4_maxDecoDamageShakeRotate; } - atUint32 GetHudCamFovTweak() const { return xa8_hudCamFovTweak; } - atUint32 GetHudCamYTweak() const { return xac_hudCamYTweak; } - atUint32 GetHudCamZTweak() const { return xb0_hudCamZTweak; } - float GetBeamVisorMenuAnimTime() const { return xc0_beamVisorMenuAnimTime; } - float GetVisorBeamMenuItemActiveScale() const { return xc4_visorBeamMenuItemActiveScale; } - float GetVisorBeamMenuItemInactiveScale() const { return xc8_visorBeamMenuItemInactiveScale; } - float GetVisorBeamMenuItemTranslate() const { return xcc_visorBeamMenuItemTranslate; } - float GetThreatRange() const { return xe4_threatRange; } - float GetRadarScopeCoordRadius() const { return xe8_radarScopeCoordRadius; } - float GetRadarPlayerPaintRadius() const { return xec_radarPlayerPaintRadius; } - float GetRadarEnemyPaintRadius() const { return xf0_radarEnemyPaintRadius; } - float GetMissileArrowVisTime() const { return xf4_missileArrowVisTime; } - EHudVisMode GetHudVisMode() const { return xf8_hudVisMode; } - EHelmetVisMode GetHelmetVisMode() const { return xfc_helmetVisMode; } - atUint32 GetEnableAutoMapper() const { return x100_enableAutoMapper; } - atUint32 GetEnableTargetingManager() const { return x108_enableTargetingManager; } - atUint32 GetEnablePlayerVisor() const { return x10c_enablePlayerVisor; } - float GetThreatWarningFraction() const { return x110_threatWarningFraction; } - float GetMissileWarningFraction() const { return x114_missileWarningFraction; } - float GetFreeLookFadeTime() const { return x118_freeLookFadeTime; } - float GetFreeLookSfxPitchScale() const { return x12c_freeLookSfxPitchScale; } - bool GetNoAbsoluteFreeLookSfxPitch() const { return x130_noAbsoluteFreeLookSfxPitch; } - float GetFaceReflectionOrthoWidth() const { return x13c_faceReflectionOrthoWidth; } - float GetFaceReflectionOrthoHeight() const { return x140_faceReflectionOrthoHeight; } - float GetFaceReflectionDistance() const { return x144_faceReflectionDistance; } - float GetFaceReflectionHeight() const { return x148_faceReflectionHeight; } - float GetFaceReflectionAspect() const { return x14c_faceReflectionAspect; } - float GetMissileWarningPulseTime() const { return x1a0_missileWarningPulseTime; } - float GetExplosionLightFalloffMultConstant() const { return x1a4_explosionLightFalloffMultConstant; } - float GetExplosionLightFalloffMultLinear() const { return x1a8_explosionLightFalloffMultLinear; } - float GetExplosionLightFalloffMultQuadratic() const { return x1ac_explosionLightFalloffMultQuadratic; } - float GetHudDamagePeakFactor() const { return x1b4_hudDamagePeakFactor; } - float GetHudDamageFilterGainConstant() const { return x1b8_hudDamageFilterGainConstant; } - float GetHudDamageFilterGainLinear() const { return x1bc_hudDamageFilterGainLinear; } - float GetHudDamageFilterInitConstant() const { return x1c0_hudDamageFilterInitConstant; } - float GetHudDamageFilterInitLinear() const { return x1c4_hudDamageFilterInitLinear; } - float GetEnergyDrainModPeriod() const { return x1c8_energyDrainModPeriod; } - bool GetEnergyDrainSinusoidalPulse() const { return x1cc_energyDrainSinusoidalPulse; } - bool GetEnergyDrainFilterAdditive() const { return x1cd_energyDrainFilterAdditive; } - float GetHudDamagePulseDuration() const { return x1d0_hudDamagePulseDuration; } - float GetHudDamageColorGain() const { return x1d4_hudDamageColorGain; } - float GetHudDecoShakeTranslateGain() const { return x1d8_hudDecoShakeTranslateGain; } - float GetHudLagOffsetScale() const { return x1dc_hudLagOffsetScale; } - float GetXrayBlurScaleLinear() const { return x204_xrayBlurScaleLinear; } - float GetXrayBlurScaleQuadratic() const { return x208_xrayBlurScaleQuadratic; } - float GetScanSidesAngle() const { return x210_scanSidesAngle; } - float GetScanSidesXScale() const { return x214_scanSidesXScale; } - float GetScanSidesPositionEnd() const { return x218_scanSidesPositionEnd; } - float GetScanSidesDuration() const { return x220_scanSidesDuration; } - float GetScanSidesStartTime() const { return x224_scanSidesStartTime; } - float GetScanSidesEndTime() const { return x228_scanSidesEndTime; } - float GetScanDataDotRadius() const { return x22c_scanDataDotRadius; } - float GetScanDataDotPosRandMagnitude() const { return x230_scanDataDotPosRandMag; } - float GetScanDataDotSeekDurationMin() const { return x234_scanDataDotSeekDurationMin; } - float GetScanDataDotSeekDurationMax() const { return x238_scanDataDotSeekDurationMax; } - float GetScanDataDotHoldDurationMin() const { return x23c_scanDataDotHoldDurationMin; } - float GetScanDataDotHoldDurationMax() const { return x240_scanDataDotHoldDurationMax; } - float GetScanAppearanceDuration() const { return x244_scanAppearanceDuration; } - float GetScanPaneFlashFactor() const { return x248_scanPaneFlashFactor; } - float GetScanPaneFadeInTime() const { return x24c_scanPaneFadeInTime; } - float GetScanPaneFadeOutTime() const { return x250_scanPaneFadeOutTime; } - float GetBallViewportYReduction() const { return x254_ballViewportYReduction; } - float GetScanWindowIdleWidth() const { return x258_scanWindowIdleW; } - float GetScanWindowIdleHeight() const { return x25c_scanWindowIdleH; } - float GetScanWindowActiveWidth() const { return x260_scanWindowActiveW; } - float GetScanWindowActiveHeight() const { return x264_scanWindowActiveH; } - float GetScanWindowMagnification() const { return x268_scanWindowMagnification; } - float GetScanWindowScanningAspect() const { return x26c_scanWindowScanningAspect; } - float GetScanSidesPositionStart() const { return x270_scanSidesPositionStart; } - bool GetShowAutomapperInMorphball() const { return x274_showAutomapperInMorphball; } - bool GetLatchArticleText() const { return x275_latchArticleText; } - float GetWorldTransManagerCharsPerSfx() const { return x278_wtMgrCharsPerSfx; } - atUint32 GetXRayFogMode() const { return x27c_xrayFogMode; } - float GetXRayFogNearZ() const { return x280_xrayFogNearZ; } - float GetXRayFogFarZ() const { return x284_xrayFogFarZ; } - const zeus::CColor& GetXRayFogColor() const { return x288_xrayFogColor; } - float GetThermalVisorLevel() const { return x28c_thermalVisorLevel; } - const zeus::CColor& GetThermalVisorColor() const { return x290_thermalVisorColor; } - const zeus::CColor& GetVisorHudLightAdd(int v) const { return x294_hudLightAddPerVisor[v]; } - const zeus::CColor& GetVisorHudLightMultiply(int v) const { return x2a4_hudLightMultiplyPerVisor[v]; } - const zeus::CColor& GetHudReflectivityLightColor() const { return x2b4_hudReflectivityLightColor; } - float GetHudLightAttMulConstant() const { return x2b8_hudLightAttMulConstant; } - float GetHudLightAttMulLinear() const { return x2bc_hudLightAttMulLinear; } - float GetHudLightAttMulQuadratic() const { return x2c0_hudLightAttMulQuadratic; } + float GetMapAlphaInterpolant() const { return x8_mapAlphaInterp; } + float GetPauseBlurFactor() const { return xc_pauseBlurFactor; } + float GetRadarXYRadius() const { return x10_radarXYRadius; } + float GetRadarZRadius() const { return x24_radarZRadius; } + float GetRadarZCloseRadius() const { return x28_radarZCloseRadius; } + float GetEnergyBarFilledSpeed() const { return x34_energyBarFilledSpeed; } + float GetEnergyBarShadowSpeed() const { return x38_energyBarShadowSpeed; } + float GetEnergyBarDrainDelay() const { return x3c_energyBarDrainDelay; } + bool GetEnergyBarAlwaysResetDelay() const { return x40_energyBarAlwaysResetDelay; } + float GetHudDamagePracticalsGainConstant() const { return x44_hudDamagePracticalsGainConstant; } + float GetHudDamagePracticalsGainLinear() const { return x48_hudDamagePracticalsGainLinear; } + float GetHudDamagePracticalsInitConstant() const { return x4c_hudDamagePracticalsInitConstant; } + float GetHudDamagePracticalsInitLinear() const { return x50_hudDamagePracticalsInitLinear; } + float GetHudDamageLightSpotAngle() const { return x54_hudDamageLightSpotAngle; } + float GetDamageLightAngleC() const { return x58_damageLightAngleC; } + float GetDamageLightAngleL() const { return x5c_damageLightAngleL; } + float GetDamageLightAngleQ() const { return x60_damageLightAngleQ; } + atVec3f GetDamageLightPreTranslate() const { return x64_damageLightPreTranslate; } + atVec3f GetDamageLightCenterTranslate() const { return x70_damageLightCenterTranslate; } + float GetDamageLightXfXAngle() const { return x7c_damageLightXfXAngle; } + float GetDamageLightXfZAngle() const { return x80_damageLightXfZAngle; } + float GetHudDecoShakeTranslateVelConstant() const { return x84_hudDecoShakeTranslateVelConstant; } + float GetHudDecoShakeTranslateVelLinear() const { return x88_hudDecoShakeTranslateVelLinear; } + float GetMaxDecoDamageShakeTranslate() const { return x8c_maxDecoDamageShakeTranslate; } + float GetDecoDamageShakeDeceleration() const { return x90_decoDamageShakeDeceleration; } + float GetDecoShakeGainConstant() const { return x94_decoShakeGainConstant; } + float GetDecoShakeGainLinear() const { return x98_decoShakeGainLinear; } + float GetDecoShakeInitConstant() const { return x9c_decoShakeInitConstant; } + float GetDecoShakeInitLinear() const { return xa0_decoShakeInitLinear; } + float GetMaxDecoDamageShakeRotate() const { return xa4_maxDecoDamageShakeRotate; } + atUint32 GetHudCamFovTweak() const { return xa8_hudCamFovTweak; } + atUint32 GetHudCamYTweak() const { return xac_hudCamYTweak; } + atUint32 GetHudCamZTweak() const { return xb0_hudCamZTweak; } + float GetBeamVisorMenuAnimTime() const { return xc0_beamVisorMenuAnimTime; } + float GetVisorBeamMenuItemActiveScale() const { return xc4_visorBeamMenuItemActiveScale; } + float GetVisorBeamMenuItemInactiveScale() const { return xc8_visorBeamMenuItemInactiveScale; } + float GetVisorBeamMenuItemTranslate() const { return xcc_visorBeamMenuItemTranslate; } + float GetThreatRange() const { return xe4_threatRange; } + float GetRadarScopeCoordRadius() const { return xe8_radarScopeCoordRadius; } + float GetRadarPlayerPaintRadius() const { return xec_radarPlayerPaintRadius; } + float GetRadarEnemyPaintRadius() const { return xf0_radarEnemyPaintRadius; } + float GetMissileArrowVisTime() const { return xf4_missileArrowVisTime; } + EHudVisMode GetHudVisMode() const { return xf8_hudVisMode; } + EHelmetVisMode GetHelmetVisMode() const { return xfc_helmetVisMode; } + atUint32 GetEnableAutoMapper() const { return x100_enableAutoMapper; } + atUint32 GetEnableTargetingManager() const { return x108_enableTargetingManager; } + atUint32 GetEnablePlayerVisor() const { return x10c_enablePlayerVisor; } + float GetThreatWarningFraction() const { return x110_threatWarningFraction; } + float GetMissileWarningFraction() const { return x114_missileWarningFraction; } + float GetFreeLookFadeTime() const { return x118_freeLookFadeTime; } + float GetFreeLookSfxPitchScale() const { return x12c_freeLookSfxPitchScale; } + bool GetNoAbsoluteFreeLookSfxPitch() const { return x130_noAbsoluteFreeLookSfxPitch; } + float GetFaceReflectionOrthoWidth() const { return x13c_faceReflectionOrthoWidth; } + float GetFaceReflectionOrthoHeight() const { return x140_faceReflectionOrthoHeight; } + float GetFaceReflectionDistance() const { return x144_faceReflectionDistance; } + float GetFaceReflectionHeight() const { return x148_faceReflectionHeight; } + float GetFaceReflectionAspect() const { return x14c_faceReflectionAspect; } + float GetMissileWarningPulseTime() const { return x1a0_missileWarningPulseTime; } + float GetExplosionLightFalloffMultConstant() const { return x1a4_explosionLightFalloffMultConstant; } + float GetExplosionLightFalloffMultLinear() const { return x1a8_explosionLightFalloffMultLinear; } + float GetExplosionLightFalloffMultQuadratic() const { return x1ac_explosionLightFalloffMultQuadratic; } + float GetHudDamagePeakFactor() const { return x1b4_hudDamagePeakFactor; } + float GetHudDamageFilterGainConstant() const { return x1b8_hudDamageFilterGainConstant; } + float GetHudDamageFilterGainLinear() const { return x1bc_hudDamageFilterGainLinear; } + float GetHudDamageFilterInitConstant() const { return x1c0_hudDamageFilterInitConstant; } + float GetHudDamageFilterInitLinear() const { return x1c4_hudDamageFilterInitLinear; } + float GetEnergyDrainModPeriod() const { return x1c8_energyDrainModPeriod; } + bool GetEnergyDrainSinusoidalPulse() const { return x1cc_energyDrainSinusoidalPulse; } + bool GetEnergyDrainFilterAdditive() const { return x1cd_energyDrainFilterAdditive; } + float GetHudDamagePulseDuration() const { return x1d0_hudDamagePulseDuration; } + float GetHudDamageColorGain() const { return x1d4_hudDamageColorGain; } + float GetHudDecoShakeTranslateGain() const { return x1d8_hudDecoShakeTranslateGain; } + float GetHudLagOffsetScale() const { return x1dc_hudLagOffsetScale; } + float GetXrayBlurScaleLinear() const { return x204_xrayBlurScaleLinear; } + float GetXrayBlurScaleQuadratic() const { return x208_xrayBlurScaleQuadratic; } + float GetScanSidesAngle() const { return x210_scanSidesAngle; } + float GetScanSidesXScale() const { return x214_scanSidesXScale; } + float GetScanSidesPositionEnd() const { return x218_scanSidesPositionEnd; } + float GetScanSidesDuration() const { return x220_scanSidesDuration; } + float GetScanSidesStartTime() const { return x224_scanSidesStartTime; } + float GetScanSidesEndTime() const { return x228_scanSidesEndTime; } + float GetScanDataDotRadius() const { return x22c_scanDataDotRadius; } + float GetScanDataDotPosRandMagnitude() const { return x230_scanDataDotPosRandMag; } + float GetScanDataDotSeekDurationMin() const { return x234_scanDataDotSeekDurationMin; } + float GetScanDataDotSeekDurationMax() const { return x238_scanDataDotSeekDurationMax; } + float GetScanDataDotHoldDurationMin() const { return x23c_scanDataDotHoldDurationMin; } + float GetScanDataDotHoldDurationMax() const { return x240_scanDataDotHoldDurationMax; } + float GetScanAppearanceDuration() const { return x244_scanAppearanceDuration; } + float GetScanPaneFlashFactor() const { return x248_scanPaneFlashFactor; } + float GetScanPaneFadeInTime() const { return x24c_scanPaneFadeInTime; } + float GetScanPaneFadeOutTime() const { return x250_scanPaneFadeOutTime; } + float GetBallViewportYReduction() const { return x254_ballViewportYReduction; } + float GetScanWindowIdleWidth() const { return x258_scanWindowIdleW; } + float GetScanWindowIdleHeight() const { return x25c_scanWindowIdleH; } + float GetScanWindowActiveWidth() const { return x260_scanWindowActiveW; } + float GetScanWindowActiveHeight() const { return x264_scanWindowActiveH; } + float GetScanWindowMagnification() const { return x268_scanWindowMagnification; } + float GetScanWindowScanningAspect() const { return x26c_scanWindowScanningAspect; } + float GetScanSidesPositionStart() const { return x270_scanSidesPositionStart; } + bool GetShowAutomapperInMorphball() const { return x274_showAutomapperInMorphball; } + bool GetLatchArticleText() const { return x275_latchArticleText; } + float GetWorldTransManagerCharsPerSfx() const { return x278_wtMgrCharsPerSfx; } + atUint32 GetXRayFogMode() const { return x27c_xrayFogMode; } + float GetXRayFogNearZ() const { return x280_xrayFogNearZ; } + float GetXRayFogFarZ() const { return x284_xrayFogFarZ; } + const zeus::CColor& GetXRayFogColor() const { return x288_xrayFogColor; } + float GetThermalVisorLevel() const { return x28c_thermalVisorLevel; } + const zeus::CColor& GetThermalVisorColor() const { return x290_thermalVisorColor; } + const zeus::CColor& GetVisorHudLightAdd(int v) const { return x294_hudLightAddPerVisor[v]; } + const zeus::CColor& GetVisorHudLightMultiply(int v) const { return x2a4_hudLightMultiplyPerVisor[v]; } + const zeus::CColor& GetHudReflectivityLightColor() const { return x2b4_hudReflectivityLightColor; } + float GetHudLightAttMulConstant() const { return x2b8_hudLightAttMulConstant; } + float GetHudLightAttMulLinear() const { return x2bc_hudLightAttMulLinear; } + float GetHudLightAttMulQuadratic() const { return x2c0_hudLightAttMulQuadratic; } - float GetScanSpeed(int idx) const - { - if (idx < 0 || idx >= x2c4_scanSpeeds.size()) - return 0.f; - return x2c4_scanSpeeds[idx]; - } + float GetScanSpeed(int idx) const { + if (idx < 0 || idx >= x2c4_scanSpeeds.size()) + return 0.f; + return x2c4_scanSpeeds[idx]; + } - void FixupValues() - { - xd8_ = zeus::degToRad(xd8_); - xdc_ = zeus::degToRad(xdc_); + void FixupValues() { + xd8_ = zeus::degToRad(xd8_); + xdc_ = zeus::degToRad(xdc_); - x200_ = zeus::CColor(x1f4_ * 0.25f, x1f8_ * 0.25f, x1fc_ * 0.25f, 1.f); + x200_ = zeus::CColor(x1f4_ * 0.25f, x1f8_ * 0.25f, x1fc_ * 0.25f, 1.f); - x210_scanSidesAngle = zeus::degToRad(x210_scanSidesAngle); - x228_scanSidesEndTime = x220_scanSidesDuration + x224_scanSidesStartTime; + x210_scanSidesAngle = zeus::degToRad(x210_scanSidesAngle); + x228_scanSidesEndTime = x220_scanSidesDuration + x224_scanSidesStartTime; - if (x27c_xrayFogMode == 1) - x27c_xrayFogMode = 2; - else if (x27c_xrayFogMode == 2) - x27c_xrayFogMode = 4; - else if (x27c_xrayFogMode == 3) - x27c_xrayFogMode = 5; - else - x27c_xrayFogMode = 0; + if (x27c_xrayFogMode == 1) + x27c_xrayFogMode = 2; + else if (x27c_xrayFogMode == 2) + x27c_xrayFogMode = 4; + else if (x27c_xrayFogMode == 3) + x27c_xrayFogMode = 5; + else + x27c_xrayFogMode = 0; - x84_hudDecoShakeTranslateVelConstant *= 2.0f; - } + x84_hudDecoShakeTranslateVelConstant *= 2.0f; + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGuiColors.hpp b/DataSpec/DNAMP1/Tweaks/CTweakGuiColors.hpp index fca9b01f2..e7e823668 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGuiColors.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGuiColors.hpp @@ -2,232 +2,226 @@ #include "../../DNACommon/Tweaks/ITweakGuiColors.hpp" -namespace DataSpec::DNAMP1 -{ -struct CTweakGuiColors final : public ITweakGuiColors -{ - AT_DECL_DNA_YAML - DNAColor x4_pauseBlurFilterColor; - DNAColor x8_radarStuffColor; - DNAColor xc_radarPlayerPaintColor; - DNAColor x10_radarEnemyPaintColor; - DNAColor x14_hudMessageFill; - DNAColor x18_hudMessageOutline; - DNAColor x1c_hudFrameColor; - DNAColor x20_; - DNAColor x24_; - DNAColor x28_missileIconColorActive; - DNAColor x2c_visorBeamMenuItemActive; - DNAColor x30_visorBeamMenuColorInactive; - DNAColor x34_energyBarFilledLowEnergy; - DNAColor x38_energyBarShadowLowEnergy; - DNAColor x3c_energyBarEmptyLowEnergy; - DNAColor x40_hudDamageLightColor; - DNAColor x44_; - DNAColor x48_; - DNAColor x4c_visorMenuTextFont; - DNAColor x50_visorMenuTextOutline; - DNAColor x54_beamMenuTextFont; - DNAColor x58_beamMenuTextOutline; - DNAColor x5c_energyWarningFont; - DNAColor x60_threatWarningFont; - DNAColor x64_missileWarningFont; - DNAColor x68_threatBarFilled; - DNAColor x6c_threatBarShadow; - DNAColor x70_threatBarEmpty; - DNAColor x74_missileBarFilled; - DNAColor x78_missileBarShadow; - DNAColor x7c_missileBarEmpty; - DNAColor x80_threatIconColor; - DNAColor x84_; - DNAColor x88_tickDecoColor; - DNAColor x8c_helmetLightColor; - DNAColor x90_threatIconSafeColor; - DNAColor x94_missileIconColorInactive; - DNAColor x98_missileIconColorChargedCanAlt; - DNAColor x9c_missileIconColorChargedNoAlt; - DNAColor xa0_missileIconColorDepleteAlt; - DNAColor xa4_; - DNAColor xa8_; - DNAColor xac_; - DNAColor xb0_visorBeamMenuLozColor; - DNAColor xb4_energyWarningOutline; - DNAColor xb8_threatWarningOutline; - DNAColor xbc_missileWarningOutline; - DNAColor xc0_; - DNAColor xc4_damageAmbientColor; - DNAColor xc8_scanFrameInactiveColor; - DNAColor xcc_scanFrameActiveColor; - DNAColor xd0_scanFrameImpulseColor; - DNAColor xd4_scanVisorHudLightMultiply; - DNAColor xd8_scanVisorScreenDimColor; - DNAColor xdc_thermalVisorHudLightMultiply; - DNAColor xe0_energyDrainFilterColor; - DNAColor xe4_damageAmbientPulseColor; - DNAColor xe8_energyBarFlashColor; - DNAColor xec_; - DNAColor xf0_; - DNAColor xf4_; - DNAColor xf8_; - DNAColor xfc_; - DNAColor x100_xrayEnergyDecoColor; - DNAColor x104_; - DNAColor x108_; - DNAColor x10c_; - DNAColor x110_; - DNAColor x114_; - DNAColor x118_; - DNAColor x11c_; - DNAColor x120_; - DNAColor x124_; - DNAColor x128_; - DNAColor x12c_; - DNAColor x130_; - DNAColor x134_; - DNAColor x138_scanDataDotColor; - DNAColor x13c_powerBombDigitAvailableFont; - DNAColor x140_powerBombDigitAvailableOutline; - DNAColor x144_; - DNAColor x148_ballBombFilled; - DNAColor x14c_ballBombEmpty; - DNAColor x150_powerBombIconAvailable; - DNAColor x154_; - DNAColor x158_ballEnergyDeco; - DNAColor x15c_ballBombDeco; - DNAColor x160_powerBombDigitDepletedFont; - DNAColor x164_powerBombDigitDepletedOutline; - DNAColor x168_powerBombIconUnavailable; - DNAColor x16c_; - DNAColor x170_; - DNAColor x174_scanDisplayImagePaneColor; - DNAColor x178_; - DNAColor x17c_threatIconWarningColor; - DNAColor x180_hudCounterFill; - DNAColor x184_hudCounterOutline; - DNAColor x188_scanIconCriticalColor; - DNAColor x18c_scanIconCriticalDimColor; - DNAColor x190_scanIconNoncriticalColor; - DNAColor x194_scanIconNoncriticalDimColor; - DNAColor x198_scanReticuleColor; - DNAColor x19c_threatDigitsFont; - DNAColor x1a0_threatDigitsOutline; - DNAColor x1a4_missileDigitsFont; - DNAColor x1a8_missileDigitsOutline; - DNAColor x1ac_thermalDecoColor; - DNAColor x1b0_thermalOutlinesColor; - DNAColor x1b4_; - DNAColor x1b8_thermalLockColor; - DNAColor x1bc_pauseItemAmber; - DNAColor x1c0_pauseItemBlue; - struct PerVisorColors : BigDNA - { - AT_DECL_DNA - DNAColor x0_energyBarFilled; - DNAColor x4_energyBarEmpty; - DNAColor x8_energyBarShadow; - DNAColor xc_energyTankFilled; - DNAColor x10_energyTankEmpty; - DNAColor x14_energyDigitsFont; - DNAColor x18_energyDigitsOutline; - }; - Value x1c4_perVisorCount; - /* Combat, Scan, XRay, Thermal, Ball */ - Vector x1c4_perVisorColors; +namespace DataSpec::DNAMP1 { +struct CTweakGuiColors final : public ITweakGuiColors { + AT_DECL_DNA_YAML + DNAColor x4_pauseBlurFilterColor; + DNAColor x8_radarStuffColor; + DNAColor xc_radarPlayerPaintColor; + DNAColor x10_radarEnemyPaintColor; + DNAColor x14_hudMessageFill; + DNAColor x18_hudMessageOutline; + DNAColor x1c_hudFrameColor; + DNAColor x20_; + DNAColor x24_; + DNAColor x28_missileIconColorActive; + DNAColor x2c_visorBeamMenuItemActive; + DNAColor x30_visorBeamMenuColorInactive; + DNAColor x34_energyBarFilledLowEnergy; + DNAColor x38_energyBarShadowLowEnergy; + DNAColor x3c_energyBarEmptyLowEnergy; + DNAColor x40_hudDamageLightColor; + DNAColor x44_; + DNAColor x48_; + DNAColor x4c_visorMenuTextFont; + DNAColor x50_visorMenuTextOutline; + DNAColor x54_beamMenuTextFont; + DNAColor x58_beamMenuTextOutline; + DNAColor x5c_energyWarningFont; + DNAColor x60_threatWarningFont; + DNAColor x64_missileWarningFont; + DNAColor x68_threatBarFilled; + DNAColor x6c_threatBarShadow; + DNAColor x70_threatBarEmpty; + DNAColor x74_missileBarFilled; + DNAColor x78_missileBarShadow; + DNAColor x7c_missileBarEmpty; + DNAColor x80_threatIconColor; + DNAColor x84_; + DNAColor x88_tickDecoColor; + DNAColor x8c_helmetLightColor; + DNAColor x90_threatIconSafeColor; + DNAColor x94_missileIconColorInactive; + DNAColor x98_missileIconColorChargedCanAlt; + DNAColor x9c_missileIconColorChargedNoAlt; + DNAColor xa0_missileIconColorDepleteAlt; + DNAColor xa4_; + DNAColor xa8_; + DNAColor xac_; + DNAColor xb0_visorBeamMenuLozColor; + DNAColor xb4_energyWarningOutline; + DNAColor xb8_threatWarningOutline; + DNAColor xbc_missileWarningOutline; + DNAColor xc0_; + DNAColor xc4_damageAmbientColor; + DNAColor xc8_scanFrameInactiveColor; + DNAColor xcc_scanFrameActiveColor; + DNAColor xd0_scanFrameImpulseColor; + DNAColor xd4_scanVisorHudLightMultiply; + DNAColor xd8_scanVisorScreenDimColor; + DNAColor xdc_thermalVisorHudLightMultiply; + DNAColor xe0_energyDrainFilterColor; + DNAColor xe4_damageAmbientPulseColor; + DNAColor xe8_energyBarFlashColor; + DNAColor xec_; + DNAColor xf0_; + DNAColor xf4_; + DNAColor xf8_; + DNAColor xfc_; + DNAColor x100_xrayEnergyDecoColor; + DNAColor x104_; + DNAColor x108_; + DNAColor x10c_; + DNAColor x110_; + DNAColor x114_; + DNAColor x118_; + DNAColor x11c_; + DNAColor x120_; + DNAColor x124_; + DNAColor x128_; + DNAColor x12c_; + DNAColor x130_; + DNAColor x134_; + DNAColor x138_scanDataDotColor; + DNAColor x13c_powerBombDigitAvailableFont; + DNAColor x140_powerBombDigitAvailableOutline; + DNAColor x144_; + DNAColor x148_ballBombFilled; + DNAColor x14c_ballBombEmpty; + DNAColor x150_powerBombIconAvailable; + DNAColor x154_; + DNAColor x158_ballEnergyDeco; + DNAColor x15c_ballBombDeco; + DNAColor x160_powerBombDigitDepletedFont; + DNAColor x164_powerBombDigitDepletedOutline; + DNAColor x168_powerBombIconUnavailable; + DNAColor x16c_; + DNAColor x170_; + DNAColor x174_scanDisplayImagePaneColor; + DNAColor x178_; + DNAColor x17c_threatIconWarningColor; + DNAColor x180_hudCounterFill; + DNAColor x184_hudCounterOutline; + DNAColor x188_scanIconCriticalColor; + DNAColor x18c_scanIconCriticalDimColor; + DNAColor x190_scanIconNoncriticalColor; + DNAColor x194_scanIconNoncriticalDimColor; + DNAColor x198_scanReticuleColor; + DNAColor x19c_threatDigitsFont; + DNAColor x1a0_threatDigitsOutline; + DNAColor x1a4_missileDigitsFont; + DNAColor x1a8_missileDigitsOutline; + DNAColor x1ac_thermalDecoColor; + DNAColor x1b0_thermalOutlinesColor; + DNAColor x1b4_; + DNAColor x1b8_thermalLockColor; + DNAColor x1bc_pauseItemAmber; + DNAColor x1c0_pauseItemBlue; + struct PerVisorColors : BigDNA { + AT_DECL_DNA + DNAColor x0_energyBarFilled; + DNAColor x4_energyBarEmpty; + DNAColor x8_energyBarShadow; + DNAColor xc_energyTankFilled; + DNAColor x10_energyTankEmpty; + DNAColor x14_energyDigitsFont; + DNAColor x18_energyDigitsOutline; + }; + Value x1c4_perVisorCount; + /* Combat, Scan, XRay, Thermal, Ball */ + Vector x1c4_perVisorColors; - CTweakGuiColors() = default; - CTweakGuiColors(athena::io::IStreamReader& r) { this->read(r); } + CTweakGuiColors() = default; + CTweakGuiColors(athena::io::IStreamReader& r) { this->read(r); } - const zeus::CColor& GetPauseBlurFilterColor() const { return x4_pauseBlurFilterColor; } - const zeus::CColor& GetRadarStuffColor() const { return x8_radarStuffColor; } - const zeus::CColor& GetRadarPlayerPaintColor() const { return xc_radarPlayerPaintColor; } - const zeus::CColor& GetRadarEnemyPaintColor() const { return x10_radarEnemyPaintColor; } - const zeus::CColor& GetHudMessageFill() const { return x14_hudMessageFill; } - const zeus::CColor& GetHudMessageOutline() const { return x18_hudMessageOutline; } - const zeus::CColor& GetHudFrameColor() const { return x1c_hudFrameColor; } - const zeus::CColor& GetMissileIconColorActive() const { return x28_missileIconColorActive; } - const zeus::CColor& GetVisorBeamMenuItemActive() const { return x2c_visorBeamMenuItemActive; } - const zeus::CColor& GetVisorBeamMenuItemInactive() const { return x30_visorBeamMenuColorInactive; } - const zeus::CColor& GetEnergyBarFilledLowEnergy() const { return x34_energyBarFilledLowEnergy; } - const zeus::CColor& GetEnergyBarShadowLowEnergy() const { return x38_energyBarShadowLowEnergy; } - const zeus::CColor& GetEnergyBarEmptyLowEnergy() const { return x3c_energyBarEmptyLowEnergy; } - const zeus::CColor& GetHudDamageLightColor() const { return x40_hudDamageLightColor; } - const zeus::CColor& GetVisorMenuTextFont() const { return x4c_visorMenuTextFont; } - const zeus::CColor& GetVisorMenuTextOutline() const { return x50_visorMenuTextOutline; } - const zeus::CColor& GetBeamMenuTextFont() const { return x54_beamMenuTextFont; } - const zeus::CColor& GetBeamMenuTextOutline() const { return x58_beamMenuTextOutline; } - const zeus::CColor& GetEnergyWarningFont() const { return x5c_energyWarningFont; } - const zeus::CColor& GetThreatWarningFont() const { return x60_threatWarningFont; } - const zeus::CColor& GetMissileWarningFont() const { return x64_missileWarningFont; } - const zeus::CColor& GetThreatBarFilled() const { return x68_threatBarFilled; } - const zeus::CColor& GetThreatBarShadow() const { return x6c_threatBarShadow; } - const zeus::CColor& GetThreatBarEmpty() const { return x70_threatBarEmpty; } - const zeus::CColor& GetMissileBarFilled() const { return x74_missileBarFilled; } - const zeus::CColor& GetMissileBarShadow() const { return x78_missileBarShadow; } - const zeus::CColor& GetMissileBarEmpty() const { return x7c_missileBarEmpty; } - const zeus::CColor& GetThreatIconColor() const { return x80_threatIconColor; } - const zeus::CColor& GetTickDecoColor() const { return x88_tickDecoColor; } - const zeus::CColor& GetHelmetLightColor() const { return x8c_helmetLightColor; } - const zeus::CColor& GetThreatIconSafeColor() const { return x90_threatIconSafeColor; } - const zeus::CColor& GetMissileIconColorInactive() const { return x94_missileIconColorInactive; } - const zeus::CColor& GetMissileIconColorChargedCanAlt() const { return x98_missileIconColorChargedCanAlt; } - const zeus::CColor& GetMissileIconColorChargedNoAlt() const { return x9c_missileIconColorChargedNoAlt; } - const zeus::CColor& GetMissileIconColorDepleteAlt() const { return xa0_missileIconColorDepleteAlt; } - const zeus::CColor& GetVisorBeamMenuLozColor() const { return xb0_visorBeamMenuLozColor; } - const zeus::CColor& GetEnergyWarningOutline() const { return xb4_energyWarningOutline; } - const zeus::CColor& GetThreatWarningOutline() const { return xb8_threatWarningOutline; } - const zeus::CColor& GetMissileWarningOutline() const { return xbc_missileWarningOutline; } - const zeus::CColor& GetDamageAmbientColor() const { return xc4_damageAmbientColor; } - const zeus::CColor& GetScanFrameInactiveColor() const { return xc8_scanFrameInactiveColor; } - const zeus::CColor& GetScanFrameActiveColor() const { return xcc_scanFrameActiveColor; } - const zeus::CColor& GetScanFrameImpulseColor() const { return xd0_scanFrameImpulseColor; } - const zeus::CColor& GetScanVisorHudLightMultiply() const { return xd4_scanVisorHudLightMultiply; } - const zeus::CColor& GetScanVisorScreenDimColor() const { return xd8_scanVisorScreenDimColor; } - const zeus::CColor& GetThermalVisorHudLightMultiply() const { return xdc_thermalVisorHudLightMultiply; } - const zeus::CColor& GetEnergyDrainFilterColor() const { return xe0_energyDrainFilterColor; } - const zeus::CColor& GetDamageAmbientPulseColor() const { return xe4_damageAmbientPulseColor; } - const zeus::CColor& GetEnergyBarFlashColor() const { return xe8_energyBarFlashColor; } - const zeus::CColor& GetXRayEnergyDecoColor() const { return x100_xrayEnergyDecoColor; } - const zeus::CColor& GetScanDataDotColor() const { return x138_scanDataDotColor; } - const zeus::CColor& GetPowerBombDigitAvailableFont() const { return x13c_powerBombDigitAvailableFont; } - const zeus::CColor& GetPowerBombDigitAvailableOutline() const { return x140_powerBombDigitAvailableOutline; } - const zeus::CColor& GetBallBombFilledColor() const { return x148_ballBombFilled; } - const zeus::CColor& GetBallBombEmptyColor() const { return x14c_ballBombEmpty; } - const zeus::CColor& GetPowerBombIconAvailableColor() const { return x150_powerBombIconAvailable; } - const zeus::CColor& GetBallBombEnergyColor() const { return x158_ballEnergyDeco; } - const zeus::CColor& GetBallBombDecoColor() const { return x15c_ballBombDeco; } - const zeus::CColor& GetPowerBombDigitDelpetedFont() const { return x160_powerBombDigitDepletedFont; } - const zeus::CColor& GetPowerBombDigitDelpetedOutline() const { return x164_powerBombDigitDepletedOutline; } - const zeus::CColor& GetPowerBombIconDepletedColor() const { return x168_powerBombIconUnavailable; } - const zeus::CColor& GetScanDisplayImagePaneColor() const { return x174_scanDisplayImagePaneColor; } - const zeus::CColor& GetThreatIconWarningColor() const { return x17c_threatIconWarningColor; } - const zeus::CColor& GetHudCounterFill() const { return x180_hudCounterFill; } - const zeus::CColor& GetHudCounterOutline() const { return x184_hudCounterOutline; } - const zeus::CColor& GetScanIconCriticalColor() const { return x188_scanIconCriticalColor; } - const zeus::CColor& GetScanIconCriticalDimColor() const { return x18c_scanIconCriticalDimColor; } - const zeus::CColor& GetScanIconNoncriticalColor() const { return x190_scanIconNoncriticalColor; } - const zeus::CColor& GetScanIconNoncriticalDimColor() const { return x194_scanIconNoncriticalDimColor; } - const zeus::CColor& GetScanReticuleColor() const { return x198_scanReticuleColor; } - const zeus::CColor& GetThreatDigitsFont() const { return x19c_threatDigitsFont; } - const zeus::CColor& GetThreatDigitsOutline() const { return x1a0_threatDigitsOutline; } - const zeus::CColor& GetMissileDigitsFont() const { return x1a4_missileDigitsFont; } - const zeus::CColor& GetMissileDigitsOutline() const { return x1a8_missileDigitsOutline; } - const zeus::CColor& GetThermalDecoColor() const { return x1ac_thermalDecoColor; } - const zeus::CColor& GetThermalOutlinesColor() const { return x1b0_thermalOutlinesColor; } - const zeus::CColor& GetThermalLockColor() const { return x1b8_thermalLockColor; } - const zeus::CColor& GetPauseItemAmberColor() const { return x1bc_pauseItemAmber; } - const zeus::CColor& GetPauseItemBlueColor() const { return x1c0_pauseItemBlue; } + const zeus::CColor& GetPauseBlurFilterColor() const { return x4_pauseBlurFilterColor; } + const zeus::CColor& GetRadarStuffColor() const { return x8_radarStuffColor; } + const zeus::CColor& GetRadarPlayerPaintColor() const { return xc_radarPlayerPaintColor; } + const zeus::CColor& GetRadarEnemyPaintColor() const { return x10_radarEnemyPaintColor; } + const zeus::CColor& GetHudMessageFill() const { return x14_hudMessageFill; } + const zeus::CColor& GetHudMessageOutline() const { return x18_hudMessageOutline; } + const zeus::CColor& GetHudFrameColor() const { return x1c_hudFrameColor; } + const zeus::CColor& GetMissileIconColorActive() const { return x28_missileIconColorActive; } + const zeus::CColor& GetVisorBeamMenuItemActive() const { return x2c_visorBeamMenuItemActive; } + const zeus::CColor& GetVisorBeamMenuItemInactive() const { return x30_visorBeamMenuColorInactive; } + const zeus::CColor& GetEnergyBarFilledLowEnergy() const { return x34_energyBarFilledLowEnergy; } + const zeus::CColor& GetEnergyBarShadowLowEnergy() const { return x38_energyBarShadowLowEnergy; } + const zeus::CColor& GetEnergyBarEmptyLowEnergy() const { return x3c_energyBarEmptyLowEnergy; } + const zeus::CColor& GetHudDamageLightColor() const { return x40_hudDamageLightColor; } + const zeus::CColor& GetVisorMenuTextFont() const { return x4c_visorMenuTextFont; } + const zeus::CColor& GetVisorMenuTextOutline() const { return x50_visorMenuTextOutline; } + const zeus::CColor& GetBeamMenuTextFont() const { return x54_beamMenuTextFont; } + const zeus::CColor& GetBeamMenuTextOutline() const { return x58_beamMenuTextOutline; } + const zeus::CColor& GetEnergyWarningFont() const { return x5c_energyWarningFont; } + const zeus::CColor& GetThreatWarningFont() const { return x60_threatWarningFont; } + const zeus::CColor& GetMissileWarningFont() const { return x64_missileWarningFont; } + const zeus::CColor& GetThreatBarFilled() const { return x68_threatBarFilled; } + const zeus::CColor& GetThreatBarShadow() const { return x6c_threatBarShadow; } + const zeus::CColor& GetThreatBarEmpty() const { return x70_threatBarEmpty; } + const zeus::CColor& GetMissileBarFilled() const { return x74_missileBarFilled; } + const zeus::CColor& GetMissileBarShadow() const { return x78_missileBarShadow; } + const zeus::CColor& GetMissileBarEmpty() const { return x7c_missileBarEmpty; } + const zeus::CColor& GetThreatIconColor() const { return x80_threatIconColor; } + const zeus::CColor& GetTickDecoColor() const { return x88_tickDecoColor; } + const zeus::CColor& GetHelmetLightColor() const { return x8c_helmetLightColor; } + const zeus::CColor& GetThreatIconSafeColor() const { return x90_threatIconSafeColor; } + const zeus::CColor& GetMissileIconColorInactive() const { return x94_missileIconColorInactive; } + const zeus::CColor& GetMissileIconColorChargedCanAlt() const { return x98_missileIconColorChargedCanAlt; } + const zeus::CColor& GetMissileIconColorChargedNoAlt() const { return x9c_missileIconColorChargedNoAlt; } + const zeus::CColor& GetMissileIconColorDepleteAlt() const { return xa0_missileIconColorDepleteAlt; } + const zeus::CColor& GetVisorBeamMenuLozColor() const { return xb0_visorBeamMenuLozColor; } + const zeus::CColor& GetEnergyWarningOutline() const { return xb4_energyWarningOutline; } + const zeus::CColor& GetThreatWarningOutline() const { return xb8_threatWarningOutline; } + const zeus::CColor& GetMissileWarningOutline() const { return xbc_missileWarningOutline; } + const zeus::CColor& GetDamageAmbientColor() const { return xc4_damageAmbientColor; } + const zeus::CColor& GetScanFrameInactiveColor() const { return xc8_scanFrameInactiveColor; } + const zeus::CColor& GetScanFrameActiveColor() const { return xcc_scanFrameActiveColor; } + const zeus::CColor& GetScanFrameImpulseColor() const { return xd0_scanFrameImpulseColor; } + const zeus::CColor& GetScanVisorHudLightMultiply() const { return xd4_scanVisorHudLightMultiply; } + const zeus::CColor& GetScanVisorScreenDimColor() const { return xd8_scanVisorScreenDimColor; } + const zeus::CColor& GetThermalVisorHudLightMultiply() const { return xdc_thermalVisorHudLightMultiply; } + const zeus::CColor& GetEnergyDrainFilterColor() const { return xe0_energyDrainFilterColor; } + const zeus::CColor& GetDamageAmbientPulseColor() const { return xe4_damageAmbientPulseColor; } + const zeus::CColor& GetEnergyBarFlashColor() const { return xe8_energyBarFlashColor; } + const zeus::CColor& GetXRayEnergyDecoColor() const { return x100_xrayEnergyDecoColor; } + const zeus::CColor& GetScanDataDotColor() const { return x138_scanDataDotColor; } + const zeus::CColor& GetPowerBombDigitAvailableFont() const { return x13c_powerBombDigitAvailableFont; } + const zeus::CColor& GetPowerBombDigitAvailableOutline() const { return x140_powerBombDigitAvailableOutline; } + const zeus::CColor& GetBallBombFilledColor() const { return x148_ballBombFilled; } + const zeus::CColor& GetBallBombEmptyColor() const { return x14c_ballBombEmpty; } + const zeus::CColor& GetPowerBombIconAvailableColor() const { return x150_powerBombIconAvailable; } + const zeus::CColor& GetBallBombEnergyColor() const { return x158_ballEnergyDeco; } + const zeus::CColor& GetBallBombDecoColor() const { return x15c_ballBombDeco; } + const zeus::CColor& GetPowerBombDigitDelpetedFont() const { return x160_powerBombDigitDepletedFont; } + const zeus::CColor& GetPowerBombDigitDelpetedOutline() const { return x164_powerBombDigitDepletedOutline; } + const zeus::CColor& GetPowerBombIconDepletedColor() const { return x168_powerBombIconUnavailable; } + const zeus::CColor& GetScanDisplayImagePaneColor() const { return x174_scanDisplayImagePaneColor; } + const zeus::CColor& GetThreatIconWarningColor() const { return x17c_threatIconWarningColor; } + const zeus::CColor& GetHudCounterFill() const { return x180_hudCounterFill; } + const zeus::CColor& GetHudCounterOutline() const { return x184_hudCounterOutline; } + const zeus::CColor& GetScanIconCriticalColor() const { return x188_scanIconCriticalColor; } + const zeus::CColor& GetScanIconCriticalDimColor() const { return x18c_scanIconCriticalDimColor; } + const zeus::CColor& GetScanIconNoncriticalColor() const { return x190_scanIconNoncriticalColor; } + const zeus::CColor& GetScanIconNoncriticalDimColor() const { return x194_scanIconNoncriticalDimColor; } + const zeus::CColor& GetScanReticuleColor() const { return x198_scanReticuleColor; } + const zeus::CColor& GetThreatDigitsFont() const { return x19c_threatDigitsFont; } + const zeus::CColor& GetThreatDigitsOutline() const { return x1a0_threatDigitsOutline; } + const zeus::CColor& GetMissileDigitsFont() const { return x1a4_missileDigitsFont; } + const zeus::CColor& GetMissileDigitsOutline() const { return x1a8_missileDigitsOutline; } + const zeus::CColor& GetThermalDecoColor() const { return x1ac_thermalDecoColor; } + const zeus::CColor& GetThermalOutlinesColor() const { return x1b0_thermalOutlinesColor; } + const zeus::CColor& GetThermalLockColor() const { return x1b8_thermalLockColor; } + const zeus::CColor& GetPauseItemAmberColor() const { return x1bc_pauseItemAmber; } + const zeus::CColor& GetPauseItemBlueColor() const { return x1c0_pauseItemBlue; } - VisorEnergyInitColors GetVisorEnergyInitColors(int idx) const - { - const PerVisorColors& colors = x1c4_perVisorColors[idx]; - return {colors.xc_energyTankFilled, colors.x10_energyTankEmpty, - colors.x14_energyDigitsFont, colors.x18_energyDigitsOutline}; - } - VisorEnergyBarColors GetVisorEnergyBarColors(int idx) const - { - const PerVisorColors& colors = x1c4_perVisorColors[idx]; - return {colors.x0_energyBarFilled, colors.x4_energyBarEmpty, colors.x8_energyBarShadow}; - } + VisorEnergyInitColors GetVisorEnergyInitColors(int idx) const { + const PerVisorColors& colors = x1c4_perVisorColors[idx]; + return {colors.xc_energyTankFilled, colors.x10_energyTankEmpty, colors.x14_energyDigitsFont, + colors.x18_energyDigitsOutline}; + } + VisorEnergyBarColors GetVisorEnergyBarColors(int idx) const { + const PerVisorColors& colors = x1c4_perVisorColors[idx]; + return {colors.x0_energyBarFilled, colors.x4_energyBarEmpty, colors.x8_energyBarShadow}; + } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGunRes.hpp b/DataSpec/DNAMP1/Tweaks/CTweakGunRes.hpp index 1dbed2afb..eec9bd36c 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGunRes.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGunRes.hpp @@ -2,94 +2,91 @@ #include "../../DNACommon/Tweaks/ITweakGunRes.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CTweakGunRes final : ITweakGunRes -{ - AT_DECL_DNA_YAML +struct CTweakGunRes final : ITweakGunRes { + AT_DECL_DNA_YAML - String<-1> m_gunMotion; - String<-1> m_grappleArm; - String<-1> m_rightHand; + String<-1> m_gunMotion; + String<-1> m_grappleArm; + String<-1> m_rightHand; - String<-1> m_powerBeam; - String<-1> m_iceBeam; - String<-1> m_waveBeam; - String<-1> m_plasmaBeam; - String<-1> m_phazonBeam; + String<-1> m_powerBeam; + String<-1> m_iceBeam; + String<-1> m_waveBeam; + String<-1> m_plasmaBeam; + String<-1> m_phazonBeam; - String<-1> m_holoTransition; + String<-1> m_holoTransition; - String<-1> m_bombSet; - String<-1> m_bombExplode; - String<-1> m_powerBombExplode; + String<-1> m_bombSet; + String<-1> m_bombExplode; + String<-1> m_powerBombExplode; - String<-1> m_powerBeamWp; - String<-1> m_powerBallWp; - String<-1> m_iceBeamWp; - String<-1> m_iceBallWp; - String<-1> m_waveBeamWp; - String<-1> m_waveBallWp; - String<-1> m_plasmaBeamWp; - String<-1> m_plasmaBallWp; - String<-1> m_phazonBeamWp; - String<-1> m_phazonBallWp; + String<-1> m_powerBeamWp; + String<-1> m_powerBallWp; + String<-1> m_iceBeamWp; + String<-1> m_iceBallWp; + String<-1> m_waveBeamWp; + String<-1> m_waveBallWp; + String<-1> m_plasmaBeamWp; + String<-1> m_plasmaBallWp; + String<-1> m_phazonBeamWp; + String<-1> m_phazonBallWp; - String<-1> m_powerMuzzle; - String<-1> m_iceMuzzle; - String<-1> m_waveMuzzle; - String<-1> m_plasmaMuzzle; - String<-1> m_phazonMuzzle; + String<-1> m_powerMuzzle; + String<-1> m_iceMuzzle; + String<-1> m_waveMuzzle; + String<-1> m_plasmaMuzzle; + String<-1> m_phazonMuzzle; - String<-1> m_powerCharge; - String<-1> m_iceCharge; - String<-1> m_waveCharge; - String<-1> m_plasmaCharge; - String<-1> m_phazonCharge; + String<-1> m_powerCharge; + String<-1> m_iceCharge; + String<-1> m_waveCharge; + String<-1> m_plasmaCharge; + String<-1> m_phazonCharge; - String<-1> m_powerAuxMuzzle; - String<-1> m_iceAuxMuzzle; - String<-1> m_waveAuxMuzzle; - String<-1> m_plasmaAuxMuzzle; - String<-1> m_phazonAuxMuzzle; + String<-1> m_powerAuxMuzzle; + String<-1> m_iceAuxMuzzle; + String<-1> m_waveAuxMuzzle; + String<-1> m_plasmaAuxMuzzle; + String<-1> m_phazonAuxMuzzle; - String<-1> m_grappleSegment; - String<-1> m_grappleClaw; - String<-1> m_grappleHit; - String<-1> m_grappleMuzzle; - String<-1> m_grappleSwoosh; + String<-1> m_grappleSegment; + String<-1> m_grappleClaw; + String<-1> m_grappleHit; + String<-1> m_grappleMuzzle; + String<-1> m_grappleSwoosh; - const std::string& GetGunMotion() const { return m_gunMotion; } - const std::string& GetGrappleArm() const { return m_grappleArm; } - const std::string& GetRightHand() const { return m_rightHand; } + const std::string& GetGunMotion() const { return m_gunMotion; } + const std::string& GetGrappleArm() const { return m_grappleArm; } + const std::string& GetRightHand() const { return m_rightHand; } - const std::string& GetPowerBeam() const { return m_powerBeam; } - const std::string& GetIceBeam() const { return m_iceBeam; } - const std::string& GetWaveBeam() const { return m_waveBeam; } - const std::string& GetPlasmaBeam() const { return m_plasmaBeam; } - const std::string& GetPhazonBeam() const { return m_phazonBeam; } + const std::string& GetPowerBeam() const { return m_powerBeam; } + const std::string& GetIceBeam() const { return m_iceBeam; } + const std::string& GetWaveBeam() const { return m_waveBeam; } + const std::string& GetPlasmaBeam() const { return m_plasmaBeam; } + const std::string& GetPhazonBeam() const { return m_phazonBeam; } - const std::string& GetHoloTransition() const { return m_holoTransition; } + const std::string& GetHoloTransition() const { return m_holoTransition; } - const std::string& GetBombSet() const { return m_bombSet; } - const std::string& GetBombExplode() const { return m_bombExplode; } - const std::string& GetPowerBombExplode() const { return m_powerBombExplode; } + const std::string& GetBombSet() const { return m_bombSet; } + const std::string& GetBombExplode() const { return m_bombExplode; } + const std::string& GetPowerBombExplode() const { return m_powerBombExplode; } - const std::string& GetWeapon(size_t idx, bool ball) const { return (&m_powerBeamWp)[idx * 2 + ball]; } - const std::string& GetMuzzleParticle(size_t idx) const { return (&m_powerMuzzle)[idx]; } - const std::string& GetChargeParticle(size_t idx) const { return (&m_powerCharge)[idx]; } - const std::string& GetAuxMuzzleParticle(size_t idx) const { return (&m_powerAuxMuzzle)[idx]; } + const std::string& GetWeapon(size_t idx, bool ball) const { return (&m_powerBeamWp)[idx * 2 + ball]; } + const std::string& GetMuzzleParticle(size_t idx) const { return (&m_powerMuzzle)[idx]; } + const std::string& GetChargeParticle(size_t idx) const { return (&m_powerCharge)[idx]; } + const std::string& GetAuxMuzzleParticle(size_t idx) const { return (&m_powerAuxMuzzle)[idx]; } - const std::string& GetGrappleSegmentParticle() const { return m_grappleSegment; } - const std::string& GetGrappleClawParticle() const { return m_grappleClaw; } - const std::string& GetGrappleHitParticle() const { return m_grappleHit; } - const std::string& GetGrappleMuzzleParticle() const { return m_grappleMuzzle; } - const std::string& GetGrappleSwooshParticle() const { return m_grappleSwoosh; } + const std::string& GetGrappleSegmentParticle() const { return m_grappleSegment; } + const std::string& GetGrappleClawParticle() const { return m_grappleClaw; } + const std::string& GetGrappleHitParticle() const { return m_grappleHit; } + const std::string& GetGrappleMuzzleParticle() const { return m_grappleMuzzle; } + const std::string& GetGrappleSwooshParticle() const { return m_grappleSwoosh; } - CTweakGunRes() = default; - CTweakGunRes(athena::io::IStreamReader& in) { read(in); } + CTweakGunRes() = default; + CTweakGunRes(athena::io::IStreamReader& in) { read(in); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakParticle.hpp b/DataSpec/DNAMP1/Tweaks/CTweakParticle.hpp index b54c82afa..79e4cfb02 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakParticle.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakParticle.hpp @@ -2,19 +2,16 @@ #include "../../DNACommon/Tweaks/ITweakParticle.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CTweakParticle final : ITweakParticle -{ - AT_DECL_DNA_YAML - String<-1> m_particle; - String<-1> m_powerBeam; - String<-1> m_genThrust; +struct CTweakParticle final : ITweakParticle { + AT_DECL_DNA_YAML + String<-1> m_particle; + String<-1> m_powerBeam; + String<-1> m_genThrust; - CTweakParticle()=default; - CTweakParticle(athena::io::IStreamReader& reader) { this->read(reader); } + CTweakParticle() = default; + CTweakParticle(athena::io::IStreamReader& reader) { this->read(reader); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.cpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.cpp index 1a7df051f..a81bb4dee 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.cpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.cpp @@ -1,898 +1,893 @@ #include "CTweakPlayer.hpp" #include "zeus/Math.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { template <> -void CTweakPlayer::Enumerate(athena::io::IStreamReader& __dna_reader) -{ - /* x4_maxTranslationalAcceleration[0] */ - x4_maxTranslationalAcceleration[0] = __dna_reader.readFloatBig(); - /* x4_maxTranslationalAcceleration[1] */ - x4_maxTranslationalAcceleration[1] = __dna_reader.readFloatBig(); - /* x4_maxTranslationalAcceleration[2] */ - x4_maxTranslationalAcceleration[2] = __dna_reader.readFloatBig(); - /* x4_maxTranslationalAcceleration[3] */ - x4_maxTranslationalAcceleration[3] = __dna_reader.readFloatBig(); - /* x4_maxTranslationalAcceleration[4] */ - x4_maxTranslationalAcceleration[4] = __dna_reader.readFloatBig(); - /* x4_maxTranslationalAcceleration[5] */ - x4_maxTranslationalAcceleration[5] = __dna_reader.readFloatBig(); - /* x4_maxTranslationalAcceleration[6] */ - x4_maxTranslationalAcceleration[6] = __dna_reader.readFloatBig(); - /* x4_maxTranslationalAcceleration[7] */ - x4_maxTranslationalAcceleration[7] = __dna_reader.readFloatBig(); - /* x24_maxRotationalAcceleration[0] */ - x24_maxRotationalAcceleration[0] = __dna_reader.readFloatBig(); - /* x24_maxRotationalAcceleration[1] */ - x24_maxRotationalAcceleration[1] = __dna_reader.readFloatBig(); - /* x24_maxRotationalAcceleration[2] */ - x24_maxRotationalAcceleration[2] = __dna_reader.readFloatBig(); - /* x24_maxRotationalAcceleration[3] */ - x24_maxRotationalAcceleration[3] = __dna_reader.readFloatBig(); - /* x24_maxRotationalAcceleration[4] */ - x24_maxRotationalAcceleration[4] = __dna_reader.readFloatBig(); - /* x24_maxRotationalAcceleration[5] */ - x24_maxRotationalAcceleration[5] = __dna_reader.readFloatBig(); - /* x24_maxRotationalAcceleration[6] */ - x24_maxRotationalAcceleration[6] = __dna_reader.readFloatBig(); - /* x24_maxRotationalAcceleration[7] */ - x24_maxRotationalAcceleration[7] = __dna_reader.readFloatBig(); - /* x44_translationFriction[0] */ - x44_translationFriction[0] = __dna_reader.readFloatBig(); - /* x44_translationFriction[1] */ - x44_translationFriction[1] = __dna_reader.readFloatBig(); - /* x44_translationFriction[2] */ - x44_translationFriction[2] = __dna_reader.readFloatBig(); - /* x44_translationFriction[3] */ - x44_translationFriction[3] = __dna_reader.readFloatBig(); - /* x44_translationFriction[4] */ - x44_translationFriction[4] = __dna_reader.readFloatBig(); - /* x44_translationFriction[5] */ - x44_translationFriction[5] = __dna_reader.readFloatBig(); - /* x44_translationFriction[6] */ - x44_translationFriction[6] = __dna_reader.readFloatBig(); - /* x44_translationFriction[7] */ - x44_translationFriction[7] = __dna_reader.readFloatBig(); - /* x64_rotationFriction[0] */ - x64_rotationFriction[0] = __dna_reader.readFloatBig(); - /* x64_rotationFriction[1] */ - x64_rotationFriction[1] = __dna_reader.readFloatBig(); - /* x64_rotationFriction[2] */ - x64_rotationFriction[2] = __dna_reader.readFloatBig(); - /* x64_rotationFriction[3] */ - x64_rotationFriction[3] = __dna_reader.readFloatBig(); - /* x64_rotationFriction[4] */ - x64_rotationFriction[4] = __dna_reader.readFloatBig(); - /* x64_rotationFriction[5] */ - x64_rotationFriction[5] = __dna_reader.readFloatBig(); - /* x64_rotationFriction[6] */ - x64_rotationFriction[6] = __dna_reader.readFloatBig(); - /* x64_rotationFriction[7] */ - x64_rotationFriction[7] = __dna_reader.readFloatBig(); - /* x84_rotationMaxSpeed[0] */ - x84_rotationMaxSpeed[0] = __dna_reader.readFloatBig(); - /* x84_rotationMaxSpeed[1] */ - x84_rotationMaxSpeed[1] = __dna_reader.readFloatBig(); - /* x84_rotationMaxSpeed[2] */ - x84_rotationMaxSpeed[2] = __dna_reader.readFloatBig(); - /* x84_rotationMaxSpeed[3] */ - x84_rotationMaxSpeed[3] = __dna_reader.readFloatBig(); - /* x84_rotationMaxSpeed[4] */ - x84_rotationMaxSpeed[4] = __dna_reader.readFloatBig(); - /* x84_rotationMaxSpeed[5] */ - x84_rotationMaxSpeed[5] = __dna_reader.readFloatBig(); - /* x84_rotationMaxSpeed[6] */ - x84_rotationMaxSpeed[6] = __dna_reader.readFloatBig(); - /* x84_rotationMaxSpeed[7] */ - x84_rotationMaxSpeed[7] = __dna_reader.readFloatBig(); - /* xa4_translationMaxSpeed[0] */ - xa4_translationMaxSpeed[0] = __dna_reader.readFloatBig(); - /* xa4_translationMaxSpeed[1] */ - xa4_translationMaxSpeed[1] = __dna_reader.readFloatBig(); - /* xa4_translationMaxSpeed[2] */ - xa4_translationMaxSpeed[2] = __dna_reader.readFloatBig(); - /* xa4_translationMaxSpeed[3] */ - xa4_translationMaxSpeed[3] = __dna_reader.readFloatBig(); - /* xa4_translationMaxSpeed[4] */ - xa4_translationMaxSpeed[4] = __dna_reader.readFloatBig(); - /* xa4_translationMaxSpeed[5] */ - xa4_translationMaxSpeed[5] = __dna_reader.readFloatBig(); - /* xa4_translationMaxSpeed[6] */ - xa4_translationMaxSpeed[6] = __dna_reader.readFloatBig(); - /* xa4_translationMaxSpeed[7] */ - xa4_translationMaxSpeed[7] = __dna_reader.readFloatBig(); - /* xc4_normalGravAccel */ - xc4_normalGravAccel = __dna_reader.readFloatBig(); - /* xc8_fluidGravAccel */ - xc8_fluidGravAccel = __dna_reader.readFloatBig(); - /* xcc_verticalJumpAccel */ - xcc_verticalJumpAccel = __dna_reader.readFloatBig(); - /* xd0_horizontalJumpAccel */ - xd0_horizontalJumpAccel = __dna_reader.readFloatBig(); - /* xd4_verticalDoubleJumpAccel */ - xd4_verticalDoubleJumpAccel = __dna_reader.readFloatBig(); - /* xd8_horizontalDoubleJumpAccel */ - xd8_horizontalDoubleJumpAccel = __dna_reader.readFloatBig(); - /* xdc_waterJumpFactor */ - xdc_waterJumpFactor = __dna_reader.readFloatBig(); - /* xe0_waterBallJumpFactor */ - xe0_waterBallJumpFactor = __dna_reader.readFloatBig(); - /* xe4_lavaJumpFactor */ - xe4_lavaJumpFactor = __dna_reader.readFloatBig(); - /* xe8_lavaBallJumpFactor */ - xe8_lavaBallJumpFactor = __dna_reader.readFloatBig(); - /* xec_phazonJumpFactor */ - xec_phazonJumpFactor = __dna_reader.readFloatBig(); - /* xf0_phazonBallJumpFactor */ - xf0_phazonBallJumpFactor = __dna_reader.readFloatBig(); - /* xf4_allowedJumpTime */ - xf4_allowedJumpTime = __dna_reader.readFloatBig(); - /* xf8_allowedDoubleJumpTime */ - xf8_allowedDoubleJumpTime = __dna_reader.readFloatBig(); - /* xfc_minDoubleJumpWindow */ - xfc_minDoubleJumpWindow = __dna_reader.readFloatBig(); - /* x100_maxDoubleJumpWindow */ - x100_maxDoubleJumpWindow = __dna_reader.readFloatBig(); - /* x104_ */ - x104_ = __dna_reader.readFloatBig(); - /* x108_minJumpTime */ - x108_minJumpTime = __dna_reader.readFloatBig(); - /* x10c_minDoubleJumpTime */ - x10c_minDoubleJumpTime = __dna_reader.readFloatBig(); - /* x110_allowedLedgeTime */ - x110_allowedLedgeTime = __dna_reader.readFloatBig(); - /* x114_doubleJumpImpulse */ - x114_doubleJumpImpulse = __dna_reader.readFloatBig(); - /* x118_backwardsForceMultiplier */ - x118_backwardsForceMultiplier = __dna_reader.readFloatBig(); - /* x11c_bombJumpRadius */ - x11c_bombJumpRadius = __dna_reader.readFloatBig(); - /* x120_bombJumpHeight */ - x120_bombJumpHeight = __dna_reader.readFloatBig(); - /* x124_eyeOffset */ - x124_eyeOffset = __dna_reader.readFloatBig(); - /* x128_turnSpeedMultiplier */ - x128_turnSpeedMultiplier = __dna_reader.readFloatBig(); - /* x12c_freeLookTurnSpeedMultiplier */ - x12c_freeLookTurnSpeedMultiplier = __dna_reader.readFloatBig(); - /* x130_horizontalFreeLookAngleVel */ - x130_horizontalFreeLookAngleVel = __dna_reader.readFloatBig(); - /* x134_verticalFreeLookAngleVel */ - x134_verticalFreeLookAngleVel = __dna_reader.readFloatBig(); - /* x138_freeLookSpeed */ - x138_freeLookSpeed = __dna_reader.readFloatBig(); - /* x13c_freeLookSnapSpeed */ - x13c_freeLookSnapSpeed = __dna_reader.readFloatBig(); - /* x140_ */ - x140_ = __dna_reader.readFloatBig(); - /* x144_freeLookCenteredThresholdAngle */ - x144_freeLookCenteredThresholdAngle = __dna_reader.readFloatBig(); - /* x148_freeLookCenteredTime */ - x148_freeLookCenteredTime = __dna_reader.readFloatBig(); - /* x14c_freeLookDampenFactor */ - x14c_freeLookDampenFactor = __dna_reader.readFloatBig(); - /* x150_leftDiv */ - x150_leftDiv = __dna_reader.readFloatBig(); - /* x154_rightDiv */ - x154_rightDiv = __dna_reader.readFloatBig(); - /* x228_24_freelookTurnsPlayer */ - x228_24_freelookTurnsPlayer = __dna_reader.readBool(); - /* x228_25_ */ - x228_25_ = __dna_reader.readBool(); - /* x228_26_ */ - x228_26_ = __dna_reader.readBool(); - /* x228_27_moveDuringFreeLook */ - x228_27_moveDuringFreeLook = __dna_reader.readBool(); - /* x228_28_holdButtonsForFreeLook */ - x228_28_holdButtonsForFreeLook = __dna_reader.readBool(); - /* x228_29_twoButtonsForFreeLook */ - x228_29_twoButtonsForFreeLook = __dna_reader.readBool(); - /* x228_30_ */ - x228_30_ = __dna_reader.readBool(); - /* x228_31_ */ - x228_31_ = __dna_reader.readBool(); - /* x229_24_ */ - x229_24_ = __dna_reader.readBool(); - /* x229_25_aimWhenOrbitingPoint */ - x229_25_aimWhenOrbitingPoint = __dna_reader.readBool(); - /* x229_26_stayInFreeLookWhileFiring */ - x229_26_stayInFreeLookWhileFiring = __dna_reader.readBool(); - /* x229_27_ */ - x229_27_ = __dna_reader.readBool(); - /* x229_28_ */ - x229_28_ = __dna_reader.readBool(); - /* x229_29_orbitFixedOffset */ - x229_29_orbitFixedOffset = __dna_reader.readBool(); - /* x229_30_gunButtonTogglesHolster */ - x229_30_gunButtonTogglesHolster = __dna_reader.readBool(); - /* x229_31_gunNotFiringHolstersGun */ - x229_31_gunNotFiringHolstersGun = __dna_reader.readBool(); - /* x22a_24_fallingDoubleJump */ - x22a_24_fallingDoubleJump = __dna_reader.readBool(); - /* x22a_25_impulseDoubleJump */ - x22a_25_impulseDoubleJump = __dna_reader.readBool(); - /* x22a_26_firingCancelsCameraPitch */ - x22a_26_firingCancelsCameraPitch = __dna_reader.readBool(); - /* x22a_27_assistedAimingIgnoreHorizontal */ - x22a_27_assistedAimingIgnoreHorizontal = __dna_reader.readBool(); - /* x22a_28_assistedAimingIgnoreVertical */ - x22a_28_assistedAimingIgnoreVertical = __dna_reader.readBool(); - /* x22c_ */ - x22c_ = __dna_reader.readFloatBig(); - /* x230_ */ - x230_ = __dna_reader.readFloatBig(); - /* x234_aimMaxDistance */ - x234_aimMaxDistance = __dna_reader.readFloatBig(); - /* x238_ */ - x238_ = __dna_reader.readFloatBig(); - /* x23c_ */ - x23c_ = __dna_reader.readFloatBig(); - /* x240_ */ - x240_ = __dna_reader.readFloatBig(); - /* x244_ */ - x244_ = __dna_reader.readFloatBig(); - /* x248_ */ - x248_ = __dna_reader.readFloatBig(); - /* x24c_aimThresholdDistance */ - x24c_aimThresholdDistance = __dna_reader.readFloatBig(); - /* x250_ */ - x250_ = __dna_reader.readFloatBig(); - /* x254_ */ - x254_ = __dna_reader.readFloatBig(); - /* x258_aimBoxWidth */ - x258_aimBoxWidth = __dna_reader.readFloatBig(); - /* x25c_aimBoxHeight */ - x25c_aimBoxHeight = __dna_reader.readFloatBig(); - /* x260_aimTargetTimer */ - x260_aimTargetTimer = __dna_reader.readFloatBig(); - /* x264_aimAssistHorizontalAngle */ - x264_aimAssistHorizontalAngle = __dna_reader.readFloatBig(); - /* x268_aimAssistVerticalAngle */ - x268_aimAssistVerticalAngle = __dna_reader.readFloatBig(); - /* x158_orbitMinDistance[0] */ - x158_orbitMinDistance[0] = __dna_reader.readFloatBig(); - /* x164_orbitNormalDistance[0] */ - x164_orbitNormalDistance[0] = __dna_reader.readFloatBig(); - /* x170_orbitMaxDistance[0] */ - x170_orbitMaxDistance[0] = __dna_reader.readFloatBig(); - /* x158_orbitMinDistance[1] */ - x158_orbitMinDistance[1] = __dna_reader.readFloatBig(); - /* x164_orbitNormalDistance[1] */ - x164_orbitNormalDistance[1] = __dna_reader.readFloatBig(); - /* x170_orbitMaxDistance[1] */ - x170_orbitMaxDistance[1] = __dna_reader.readFloatBig(); - /* x158_orbitMinDistance[2] */ - x158_orbitMinDistance[2] = __dna_reader.readFloatBig(); - /* x164_orbitNormalDistance[2] */ - x164_orbitNormalDistance[2] = __dna_reader.readFloatBig(); - /* x170_orbitMaxDistance[2] */ - x170_orbitMaxDistance[2] = __dna_reader.readFloatBig(); - /* x17c_ */ - x17c_ = __dna_reader.readFloatBig(); - /* x180_orbitModeTimer */ - x180_orbitModeTimer = __dna_reader.readFloatBig(); - /* x184_orbitCameraSpeed */ - x184_orbitCameraSpeed = __dna_reader.readFloatBig(); - /* x188_orbitUpperAngle */ - x188_orbitUpperAngle = __dna_reader.readFloatBig(); - /* x18c_orbitLowerAngle */ - x18c_orbitLowerAngle = __dna_reader.readFloatBig(); - /* x190_orbitHorizAngle */ - x190_orbitHorizAngle = __dna_reader.readFloatBig(); - /* x194_ */ - x194_ = __dna_reader.readFloatBig(); - /* x198_ */ - x198_ = __dna_reader.readFloatBig(); - /* x19c_orbitMaxTargetDistance */ - x19c_orbitMaxTargetDistance = __dna_reader.readFloatBig(); - /* x1a0_orbitMaxLockDistance */ - x1a0_orbitMaxLockDistance = __dna_reader.readFloatBig(); - /* x1a4_orbitDistanceThreshold */ - x1a4_orbitDistanceThreshold = __dna_reader.readFloatBig(); - /* x1a8_orbitScreenBoxHalfExtentX[0] */ - x1a8_orbitScreenBoxHalfExtentX[0] = __dna_reader.readUint32Big(); - /* x1b0_orbitScreenBoxHalfExtentY[0] */ - x1b0_orbitScreenBoxHalfExtentY[0] = __dna_reader.readUint32Big(); - /* x1b8_orbitScreenBoxCenterX[0] */ - x1b8_orbitScreenBoxCenterX[0] = __dna_reader.readUint32Big(); - /* x1c0_orbitScreenBoxCenterY[0] */ - x1c0_orbitScreenBoxCenterY[0] = __dna_reader.readUint32Big(); - /* x1c8_orbitZoneIdealX[0] */ - x1c8_orbitZoneIdealX[0] = __dna_reader.readUint32Big(); - /* x1d0_orbitZoneIdealY[0] */ - x1d0_orbitZoneIdealY[0] = __dna_reader.readUint32Big(); - /* x1a8_orbitScreenBoxHalfExtentX[1] */ - x1a8_orbitScreenBoxHalfExtentX[1] = __dna_reader.readUint32Big(); - /* x1b0_orbitScreenBoxHalfExtentY[1] */ - x1b0_orbitScreenBoxHalfExtentY[1] = __dna_reader.readUint32Big(); - /* x1b8_orbitScreenBoxCenterX[1] */ - x1b8_orbitScreenBoxCenterX[1] = __dna_reader.readUint32Big(); - /* x1c0_orbitScreenBoxCenterY[1] */ - x1c0_orbitScreenBoxCenterY[1] = __dna_reader.readUint32Big(); - /* x1c8_orbitZoneIdealX[1] */ - x1c8_orbitZoneIdealX[1] = __dna_reader.readUint32Big(); - /* x1d0_orbitZoneIdealY[1] */ - x1d0_orbitZoneIdealY[1] = __dna_reader.readUint32Big(); - /* x1d8_orbitNearX */ - x1d8_orbitNearX = __dna_reader.readFloatBig(); - /* x1dc_orbitNearZ */ - x1dc_orbitNearZ = __dna_reader.readFloatBig(); - /* x1e0_ */ - x1e0_ = __dna_reader.readFloatBig(); - /* x1e4_ */ - x1e4_ = __dna_reader.readFloatBig(); - /* x1e8_orbitFixedOffsetZDiff */ - x1e8_orbitFixedOffsetZDiff = __dna_reader.readFloatBig(); - /* x1ec_orbitZRange */ - x1ec_orbitZRange = __dna_reader.readFloatBig(); - /* x1f0_ */ - x1f0_ = __dna_reader.readFloatBig(); - /* x1f4_ */ - x1f4_ = __dna_reader.readFloatBig(); - /* x1f8_ */ - x1f8_ = __dna_reader.readFloatBig(); - /* x1fc_orbitPreventionTime */ - x1fc_orbitPreventionTime = __dna_reader.readFloatBig(); - /* x200_24_dashEnabled */ - x200_24_dashEnabled = __dna_reader.readBool(); - /* x200_25_dashOnButtonRelease */ - x200_25_dashOnButtonRelease = __dna_reader.readBool(); - /* x204_dashButtonHoldCancelTime */ - x204_dashButtonHoldCancelTime = __dna_reader.readFloatBig(); - /* x208_dashStrafeInputThreshold */ - x208_dashStrafeInputThreshold = __dna_reader.readFloatBig(); - /* x20c_sidewaysDoubleJumpImpulse */ - x20c_sidewaysDoubleJumpImpulse = __dna_reader.readFloatBig(); - /* x210_sidewaysVerticalDoubleJumpAccel */ - x210_sidewaysVerticalDoubleJumpAccel = __dna_reader.readFloatBig(); - /* x214_sidewaysHorizontalDoubleJumpAccel */ - x214_sidewaysHorizontalDoubleJumpAccel = __dna_reader.readFloatBig(); - /* x218_scanningRange */ - x218_scanningRange = __dna_reader.readFloatBig(); - /* x21c_24_scanRetention */ - x21c_24_scanRetention = __dna_reader.readBool(); - /* x21c_25_scanFreezesGame */ - x21c_25_scanFreezesGame = __dna_reader.readBool(); - /* x21c_26_orbitWhileScanning */ - x21c_26_orbitWhileScanning = __dna_reader.readBool(); - /* x220_scanMaxTargetDistance */ - x220_scanMaxTargetDistance = __dna_reader.readFloatBig(); - /* x224_scanMaxLockDistance */ - x224_scanMaxLockDistance = __dna_reader.readFloatBig(); - /* x2a0_orbitDistanceMax */ - x2a0_orbitDistanceMax = __dna_reader.readFloatBig(); - /* x2a4_grappleSwingLength */ - x2a4_grappleSwingLength = __dna_reader.readFloatBig(); - /* x2a8_grappleSwingPeriod */ - x2a8_grappleSwingPeriod = __dna_reader.readFloatBig(); - /* x2ac_grapplePullSpeedMin */ - x2ac_grapplePullSpeedMin = __dna_reader.readFloatBig(); - /* x2b0_grappleCameraSpeed */ - x2b0_grappleCameraSpeed = __dna_reader.readFloatBig(); - /* x2b4_maxGrappleLockedTurnAlignDistance */ - x2b4_maxGrappleLockedTurnAlignDistance = __dna_reader.readFloatBig(); - /* x2b8_grapplePullSpeedProportion */ - x2b8_grapplePullSpeedProportion = __dna_reader.readFloatBig(); - /* x2bc_grapplePullSpeedMax */ - x2bc_grapplePullSpeedMax = __dna_reader.readFloatBig(); - /* x2c0_grappleLookCenterSpeed */ - x2c0_grappleLookCenterSpeed = __dna_reader.readFloatBig(); - /* x2c4_maxGrappleTurnSpeed */ - x2c4_maxGrappleTurnSpeed = __dna_reader.readFloatBig(); - /* x2c8_grappleJumpForce */ - x2c8_grappleJumpForce = __dna_reader.readFloatBig(); - /* x2cc_grappleReleaseTime */ - x2cc_grappleReleaseTime = __dna_reader.readFloatBig(); - /* x2d0_grappleJumpMode */ - x2d0_grappleJumpMode = __dna_reader.readUint32Big(); - /* x2d4_orbitReleaseBreaksGrapple */ - x2d4_orbitReleaseBreaksGrapple = __dna_reader.readBool(); - /* x2d5_invertGrappleTurn */ - x2d5_invertGrappleTurn = __dna_reader.readBool(); - /* x2d8_grappleBeamSpeed */ - x2d8_grappleBeamSpeed = __dna_reader.readFloatBig(); - /* x2dc_grappleBeamXWaveAmplitude */ - x2dc_grappleBeamXWaveAmplitude = __dna_reader.readFloatBig(); - /* x2e0_grappleBeamZWaveAmplitude */ - x2e0_grappleBeamZWaveAmplitude = __dna_reader.readFloatBig(); - /* x2e4_grappleBeamAnglePhaseDelta */ - x2e4_grappleBeamAnglePhaseDelta = __dna_reader.readFloatBig(); - /* x26c_playerHeight */ - x26c_playerHeight = __dna_reader.readFloatBig(); - /* x270_playerXYHalfExtent */ - x270_playerXYHalfExtent = __dna_reader.readFloatBig(); - /* x274_stepUpHeight */ - x274_stepUpHeight = __dna_reader.readFloatBig(); - /* x278_stepDownHeight */ - x278_stepDownHeight = __dna_reader.readFloatBig(); - /* x27c_playerBallHalfExtent */ - x27c_playerBallHalfExtent = __dna_reader.readFloatBig(); - /* x280_ */ - x280_firstPersonCameraSpeed = __dna_reader.readFloatBig(); - /* x284_ */ - x284_ = __dna_reader.readFloatBig(); - /* x288_jumpCameraPitchDownStart */ - x288_jumpCameraPitchDownStart = __dna_reader.readFloatBig(); - /* x28c_jumpCameraPitchDownFull */ - x28c_jumpCameraPitchDownFull = __dna_reader.readFloatBig(); - /* x290_jumpCameraPitchDownAngle */ - x290_jumpCameraPitchDownAngle = __dna_reader.readFloatBig(); - /* x294_fallCameraPitchDownStart */ - x294_fallCameraPitchDownStart = __dna_reader.readFloatBig(); - /* x298_fallCameraPitchDownFull */ - x298_fallCameraPitchDownFull = __dna_reader.readFloatBig(); - /* x29c_fallCameraPitchDownAngle */ - x29c_fallCameraPitchDownAngle = __dna_reader.readFloatBig(); - /* x2e8_ */ - x2e8_ = __dna_reader.readFloatBig(); - /* x2ec_ */ - x2ec_ = __dna_reader.readFloatBig(); - /* x2f0_ */ - x2f0_ = __dna_reader.readFloatBig(); - /* x2f4_ */ - x2f4_ = __dna_reader.readBool(); - /* x2f8_frozenTimeout */ - x2f8_frozenTimeout = __dna_reader.readFloatBig(); - /* x2fc_iceBreakJumpCount */ - x2fc_iceBreakJumpCount = __dna_reader.readUint32Big(); - /* x300_variaDamageReduction */ - x300_variaDamageReduction = __dna_reader.readFloatBig(); - /* x304_gravityDamageReduction */ - x304_gravityDamageReduction = __dna_reader.readFloatBig(); - /* x308_phazonDamageReduction */ - x308_phazonDamageReduction = __dna_reader.readFloatBig(); +void CTweakPlayer::Enumerate(athena::io::IStreamReader& __dna_reader) { + /* x4_maxTranslationalAcceleration[0] */ + x4_maxTranslationalAcceleration[0] = __dna_reader.readFloatBig(); + /* x4_maxTranslationalAcceleration[1] */ + x4_maxTranslationalAcceleration[1] = __dna_reader.readFloatBig(); + /* x4_maxTranslationalAcceleration[2] */ + x4_maxTranslationalAcceleration[2] = __dna_reader.readFloatBig(); + /* x4_maxTranslationalAcceleration[3] */ + x4_maxTranslationalAcceleration[3] = __dna_reader.readFloatBig(); + /* x4_maxTranslationalAcceleration[4] */ + x4_maxTranslationalAcceleration[4] = __dna_reader.readFloatBig(); + /* x4_maxTranslationalAcceleration[5] */ + x4_maxTranslationalAcceleration[5] = __dna_reader.readFloatBig(); + /* x4_maxTranslationalAcceleration[6] */ + x4_maxTranslationalAcceleration[6] = __dna_reader.readFloatBig(); + /* x4_maxTranslationalAcceleration[7] */ + x4_maxTranslationalAcceleration[7] = __dna_reader.readFloatBig(); + /* x24_maxRotationalAcceleration[0] */ + x24_maxRotationalAcceleration[0] = __dna_reader.readFloatBig(); + /* x24_maxRotationalAcceleration[1] */ + x24_maxRotationalAcceleration[1] = __dna_reader.readFloatBig(); + /* x24_maxRotationalAcceleration[2] */ + x24_maxRotationalAcceleration[2] = __dna_reader.readFloatBig(); + /* x24_maxRotationalAcceleration[3] */ + x24_maxRotationalAcceleration[3] = __dna_reader.readFloatBig(); + /* x24_maxRotationalAcceleration[4] */ + x24_maxRotationalAcceleration[4] = __dna_reader.readFloatBig(); + /* x24_maxRotationalAcceleration[5] */ + x24_maxRotationalAcceleration[5] = __dna_reader.readFloatBig(); + /* x24_maxRotationalAcceleration[6] */ + x24_maxRotationalAcceleration[6] = __dna_reader.readFloatBig(); + /* x24_maxRotationalAcceleration[7] */ + x24_maxRotationalAcceleration[7] = __dna_reader.readFloatBig(); + /* x44_translationFriction[0] */ + x44_translationFriction[0] = __dna_reader.readFloatBig(); + /* x44_translationFriction[1] */ + x44_translationFriction[1] = __dna_reader.readFloatBig(); + /* x44_translationFriction[2] */ + x44_translationFriction[2] = __dna_reader.readFloatBig(); + /* x44_translationFriction[3] */ + x44_translationFriction[3] = __dna_reader.readFloatBig(); + /* x44_translationFriction[4] */ + x44_translationFriction[4] = __dna_reader.readFloatBig(); + /* x44_translationFriction[5] */ + x44_translationFriction[5] = __dna_reader.readFloatBig(); + /* x44_translationFriction[6] */ + x44_translationFriction[6] = __dna_reader.readFloatBig(); + /* x44_translationFriction[7] */ + x44_translationFriction[7] = __dna_reader.readFloatBig(); + /* x64_rotationFriction[0] */ + x64_rotationFriction[0] = __dna_reader.readFloatBig(); + /* x64_rotationFriction[1] */ + x64_rotationFriction[1] = __dna_reader.readFloatBig(); + /* x64_rotationFriction[2] */ + x64_rotationFriction[2] = __dna_reader.readFloatBig(); + /* x64_rotationFriction[3] */ + x64_rotationFriction[3] = __dna_reader.readFloatBig(); + /* x64_rotationFriction[4] */ + x64_rotationFriction[4] = __dna_reader.readFloatBig(); + /* x64_rotationFriction[5] */ + x64_rotationFriction[5] = __dna_reader.readFloatBig(); + /* x64_rotationFriction[6] */ + x64_rotationFriction[6] = __dna_reader.readFloatBig(); + /* x64_rotationFriction[7] */ + x64_rotationFriction[7] = __dna_reader.readFloatBig(); + /* x84_rotationMaxSpeed[0] */ + x84_rotationMaxSpeed[0] = __dna_reader.readFloatBig(); + /* x84_rotationMaxSpeed[1] */ + x84_rotationMaxSpeed[1] = __dna_reader.readFloatBig(); + /* x84_rotationMaxSpeed[2] */ + x84_rotationMaxSpeed[2] = __dna_reader.readFloatBig(); + /* x84_rotationMaxSpeed[3] */ + x84_rotationMaxSpeed[3] = __dna_reader.readFloatBig(); + /* x84_rotationMaxSpeed[4] */ + x84_rotationMaxSpeed[4] = __dna_reader.readFloatBig(); + /* x84_rotationMaxSpeed[5] */ + x84_rotationMaxSpeed[5] = __dna_reader.readFloatBig(); + /* x84_rotationMaxSpeed[6] */ + x84_rotationMaxSpeed[6] = __dna_reader.readFloatBig(); + /* x84_rotationMaxSpeed[7] */ + x84_rotationMaxSpeed[7] = __dna_reader.readFloatBig(); + /* xa4_translationMaxSpeed[0] */ + xa4_translationMaxSpeed[0] = __dna_reader.readFloatBig(); + /* xa4_translationMaxSpeed[1] */ + xa4_translationMaxSpeed[1] = __dna_reader.readFloatBig(); + /* xa4_translationMaxSpeed[2] */ + xa4_translationMaxSpeed[2] = __dna_reader.readFloatBig(); + /* xa4_translationMaxSpeed[3] */ + xa4_translationMaxSpeed[3] = __dna_reader.readFloatBig(); + /* xa4_translationMaxSpeed[4] */ + xa4_translationMaxSpeed[4] = __dna_reader.readFloatBig(); + /* xa4_translationMaxSpeed[5] */ + xa4_translationMaxSpeed[5] = __dna_reader.readFloatBig(); + /* xa4_translationMaxSpeed[6] */ + xa4_translationMaxSpeed[6] = __dna_reader.readFloatBig(); + /* xa4_translationMaxSpeed[7] */ + xa4_translationMaxSpeed[7] = __dna_reader.readFloatBig(); + /* xc4_normalGravAccel */ + xc4_normalGravAccel = __dna_reader.readFloatBig(); + /* xc8_fluidGravAccel */ + xc8_fluidGravAccel = __dna_reader.readFloatBig(); + /* xcc_verticalJumpAccel */ + xcc_verticalJumpAccel = __dna_reader.readFloatBig(); + /* xd0_horizontalJumpAccel */ + xd0_horizontalJumpAccel = __dna_reader.readFloatBig(); + /* xd4_verticalDoubleJumpAccel */ + xd4_verticalDoubleJumpAccel = __dna_reader.readFloatBig(); + /* xd8_horizontalDoubleJumpAccel */ + xd8_horizontalDoubleJumpAccel = __dna_reader.readFloatBig(); + /* xdc_waterJumpFactor */ + xdc_waterJumpFactor = __dna_reader.readFloatBig(); + /* xe0_waterBallJumpFactor */ + xe0_waterBallJumpFactor = __dna_reader.readFloatBig(); + /* xe4_lavaJumpFactor */ + xe4_lavaJumpFactor = __dna_reader.readFloatBig(); + /* xe8_lavaBallJumpFactor */ + xe8_lavaBallJumpFactor = __dna_reader.readFloatBig(); + /* xec_phazonJumpFactor */ + xec_phazonJumpFactor = __dna_reader.readFloatBig(); + /* xf0_phazonBallJumpFactor */ + xf0_phazonBallJumpFactor = __dna_reader.readFloatBig(); + /* xf4_allowedJumpTime */ + xf4_allowedJumpTime = __dna_reader.readFloatBig(); + /* xf8_allowedDoubleJumpTime */ + xf8_allowedDoubleJumpTime = __dna_reader.readFloatBig(); + /* xfc_minDoubleJumpWindow */ + xfc_minDoubleJumpWindow = __dna_reader.readFloatBig(); + /* x100_maxDoubleJumpWindow */ + x100_maxDoubleJumpWindow = __dna_reader.readFloatBig(); + /* x104_ */ + x104_ = __dna_reader.readFloatBig(); + /* x108_minJumpTime */ + x108_minJumpTime = __dna_reader.readFloatBig(); + /* x10c_minDoubleJumpTime */ + x10c_minDoubleJumpTime = __dna_reader.readFloatBig(); + /* x110_allowedLedgeTime */ + x110_allowedLedgeTime = __dna_reader.readFloatBig(); + /* x114_doubleJumpImpulse */ + x114_doubleJumpImpulse = __dna_reader.readFloatBig(); + /* x118_backwardsForceMultiplier */ + x118_backwardsForceMultiplier = __dna_reader.readFloatBig(); + /* x11c_bombJumpRadius */ + x11c_bombJumpRadius = __dna_reader.readFloatBig(); + /* x120_bombJumpHeight */ + x120_bombJumpHeight = __dna_reader.readFloatBig(); + /* x124_eyeOffset */ + x124_eyeOffset = __dna_reader.readFloatBig(); + /* x128_turnSpeedMultiplier */ + x128_turnSpeedMultiplier = __dna_reader.readFloatBig(); + /* x12c_freeLookTurnSpeedMultiplier */ + x12c_freeLookTurnSpeedMultiplier = __dna_reader.readFloatBig(); + /* x130_horizontalFreeLookAngleVel */ + x130_horizontalFreeLookAngleVel = __dna_reader.readFloatBig(); + /* x134_verticalFreeLookAngleVel */ + x134_verticalFreeLookAngleVel = __dna_reader.readFloatBig(); + /* x138_freeLookSpeed */ + x138_freeLookSpeed = __dna_reader.readFloatBig(); + /* x13c_freeLookSnapSpeed */ + x13c_freeLookSnapSpeed = __dna_reader.readFloatBig(); + /* x140_ */ + x140_ = __dna_reader.readFloatBig(); + /* x144_freeLookCenteredThresholdAngle */ + x144_freeLookCenteredThresholdAngle = __dna_reader.readFloatBig(); + /* x148_freeLookCenteredTime */ + x148_freeLookCenteredTime = __dna_reader.readFloatBig(); + /* x14c_freeLookDampenFactor */ + x14c_freeLookDampenFactor = __dna_reader.readFloatBig(); + /* x150_leftDiv */ + x150_leftDiv = __dna_reader.readFloatBig(); + /* x154_rightDiv */ + x154_rightDiv = __dna_reader.readFloatBig(); + /* x228_24_freelookTurnsPlayer */ + x228_24_freelookTurnsPlayer = __dna_reader.readBool(); + /* x228_25_ */ + x228_25_ = __dna_reader.readBool(); + /* x228_26_ */ + x228_26_ = __dna_reader.readBool(); + /* x228_27_moveDuringFreeLook */ + x228_27_moveDuringFreeLook = __dna_reader.readBool(); + /* x228_28_holdButtonsForFreeLook */ + x228_28_holdButtonsForFreeLook = __dna_reader.readBool(); + /* x228_29_twoButtonsForFreeLook */ + x228_29_twoButtonsForFreeLook = __dna_reader.readBool(); + /* x228_30_ */ + x228_30_ = __dna_reader.readBool(); + /* x228_31_ */ + x228_31_ = __dna_reader.readBool(); + /* x229_24_ */ + x229_24_ = __dna_reader.readBool(); + /* x229_25_aimWhenOrbitingPoint */ + x229_25_aimWhenOrbitingPoint = __dna_reader.readBool(); + /* x229_26_stayInFreeLookWhileFiring */ + x229_26_stayInFreeLookWhileFiring = __dna_reader.readBool(); + /* x229_27_ */ + x229_27_ = __dna_reader.readBool(); + /* x229_28_ */ + x229_28_ = __dna_reader.readBool(); + /* x229_29_orbitFixedOffset */ + x229_29_orbitFixedOffset = __dna_reader.readBool(); + /* x229_30_gunButtonTogglesHolster */ + x229_30_gunButtonTogglesHolster = __dna_reader.readBool(); + /* x229_31_gunNotFiringHolstersGun */ + x229_31_gunNotFiringHolstersGun = __dna_reader.readBool(); + /* x22a_24_fallingDoubleJump */ + x22a_24_fallingDoubleJump = __dna_reader.readBool(); + /* x22a_25_impulseDoubleJump */ + x22a_25_impulseDoubleJump = __dna_reader.readBool(); + /* x22a_26_firingCancelsCameraPitch */ + x22a_26_firingCancelsCameraPitch = __dna_reader.readBool(); + /* x22a_27_assistedAimingIgnoreHorizontal */ + x22a_27_assistedAimingIgnoreHorizontal = __dna_reader.readBool(); + /* x22a_28_assistedAimingIgnoreVertical */ + x22a_28_assistedAimingIgnoreVertical = __dna_reader.readBool(); + /* x22c_ */ + x22c_ = __dna_reader.readFloatBig(); + /* x230_ */ + x230_ = __dna_reader.readFloatBig(); + /* x234_aimMaxDistance */ + x234_aimMaxDistance = __dna_reader.readFloatBig(); + /* x238_ */ + x238_ = __dna_reader.readFloatBig(); + /* x23c_ */ + x23c_ = __dna_reader.readFloatBig(); + /* x240_ */ + x240_ = __dna_reader.readFloatBig(); + /* x244_ */ + x244_ = __dna_reader.readFloatBig(); + /* x248_ */ + x248_ = __dna_reader.readFloatBig(); + /* x24c_aimThresholdDistance */ + x24c_aimThresholdDistance = __dna_reader.readFloatBig(); + /* x250_ */ + x250_ = __dna_reader.readFloatBig(); + /* x254_ */ + x254_ = __dna_reader.readFloatBig(); + /* x258_aimBoxWidth */ + x258_aimBoxWidth = __dna_reader.readFloatBig(); + /* x25c_aimBoxHeight */ + x25c_aimBoxHeight = __dna_reader.readFloatBig(); + /* x260_aimTargetTimer */ + x260_aimTargetTimer = __dna_reader.readFloatBig(); + /* x264_aimAssistHorizontalAngle */ + x264_aimAssistHorizontalAngle = __dna_reader.readFloatBig(); + /* x268_aimAssistVerticalAngle */ + x268_aimAssistVerticalAngle = __dna_reader.readFloatBig(); + /* x158_orbitMinDistance[0] */ + x158_orbitMinDistance[0] = __dna_reader.readFloatBig(); + /* x164_orbitNormalDistance[0] */ + x164_orbitNormalDistance[0] = __dna_reader.readFloatBig(); + /* x170_orbitMaxDistance[0] */ + x170_orbitMaxDistance[0] = __dna_reader.readFloatBig(); + /* x158_orbitMinDistance[1] */ + x158_orbitMinDistance[1] = __dna_reader.readFloatBig(); + /* x164_orbitNormalDistance[1] */ + x164_orbitNormalDistance[1] = __dna_reader.readFloatBig(); + /* x170_orbitMaxDistance[1] */ + x170_orbitMaxDistance[1] = __dna_reader.readFloatBig(); + /* x158_orbitMinDistance[2] */ + x158_orbitMinDistance[2] = __dna_reader.readFloatBig(); + /* x164_orbitNormalDistance[2] */ + x164_orbitNormalDistance[2] = __dna_reader.readFloatBig(); + /* x170_orbitMaxDistance[2] */ + x170_orbitMaxDistance[2] = __dna_reader.readFloatBig(); + /* x17c_ */ + x17c_ = __dna_reader.readFloatBig(); + /* x180_orbitModeTimer */ + x180_orbitModeTimer = __dna_reader.readFloatBig(); + /* x184_orbitCameraSpeed */ + x184_orbitCameraSpeed = __dna_reader.readFloatBig(); + /* x188_orbitUpperAngle */ + x188_orbitUpperAngle = __dna_reader.readFloatBig(); + /* x18c_orbitLowerAngle */ + x18c_orbitLowerAngle = __dna_reader.readFloatBig(); + /* x190_orbitHorizAngle */ + x190_orbitHorizAngle = __dna_reader.readFloatBig(); + /* x194_ */ + x194_ = __dna_reader.readFloatBig(); + /* x198_ */ + x198_ = __dna_reader.readFloatBig(); + /* x19c_orbitMaxTargetDistance */ + x19c_orbitMaxTargetDistance = __dna_reader.readFloatBig(); + /* x1a0_orbitMaxLockDistance */ + x1a0_orbitMaxLockDistance = __dna_reader.readFloatBig(); + /* x1a4_orbitDistanceThreshold */ + x1a4_orbitDistanceThreshold = __dna_reader.readFloatBig(); + /* x1a8_orbitScreenBoxHalfExtentX[0] */ + x1a8_orbitScreenBoxHalfExtentX[0] = __dna_reader.readUint32Big(); + /* x1b0_orbitScreenBoxHalfExtentY[0] */ + x1b0_orbitScreenBoxHalfExtentY[0] = __dna_reader.readUint32Big(); + /* x1b8_orbitScreenBoxCenterX[0] */ + x1b8_orbitScreenBoxCenterX[0] = __dna_reader.readUint32Big(); + /* x1c0_orbitScreenBoxCenterY[0] */ + x1c0_orbitScreenBoxCenterY[0] = __dna_reader.readUint32Big(); + /* x1c8_orbitZoneIdealX[0] */ + x1c8_orbitZoneIdealX[0] = __dna_reader.readUint32Big(); + /* x1d0_orbitZoneIdealY[0] */ + x1d0_orbitZoneIdealY[0] = __dna_reader.readUint32Big(); + /* x1a8_orbitScreenBoxHalfExtentX[1] */ + x1a8_orbitScreenBoxHalfExtentX[1] = __dna_reader.readUint32Big(); + /* x1b0_orbitScreenBoxHalfExtentY[1] */ + x1b0_orbitScreenBoxHalfExtentY[1] = __dna_reader.readUint32Big(); + /* x1b8_orbitScreenBoxCenterX[1] */ + x1b8_orbitScreenBoxCenterX[1] = __dna_reader.readUint32Big(); + /* x1c0_orbitScreenBoxCenterY[1] */ + x1c0_orbitScreenBoxCenterY[1] = __dna_reader.readUint32Big(); + /* x1c8_orbitZoneIdealX[1] */ + x1c8_orbitZoneIdealX[1] = __dna_reader.readUint32Big(); + /* x1d0_orbitZoneIdealY[1] */ + x1d0_orbitZoneIdealY[1] = __dna_reader.readUint32Big(); + /* x1d8_orbitNearX */ + x1d8_orbitNearX = __dna_reader.readFloatBig(); + /* x1dc_orbitNearZ */ + x1dc_orbitNearZ = __dna_reader.readFloatBig(); + /* x1e0_ */ + x1e0_ = __dna_reader.readFloatBig(); + /* x1e4_ */ + x1e4_ = __dna_reader.readFloatBig(); + /* x1e8_orbitFixedOffsetZDiff */ + x1e8_orbitFixedOffsetZDiff = __dna_reader.readFloatBig(); + /* x1ec_orbitZRange */ + x1ec_orbitZRange = __dna_reader.readFloatBig(); + /* x1f0_ */ + x1f0_ = __dna_reader.readFloatBig(); + /* x1f4_ */ + x1f4_ = __dna_reader.readFloatBig(); + /* x1f8_ */ + x1f8_ = __dna_reader.readFloatBig(); + /* x1fc_orbitPreventionTime */ + x1fc_orbitPreventionTime = __dna_reader.readFloatBig(); + /* x200_24_dashEnabled */ + x200_24_dashEnabled = __dna_reader.readBool(); + /* x200_25_dashOnButtonRelease */ + x200_25_dashOnButtonRelease = __dna_reader.readBool(); + /* x204_dashButtonHoldCancelTime */ + x204_dashButtonHoldCancelTime = __dna_reader.readFloatBig(); + /* x208_dashStrafeInputThreshold */ + x208_dashStrafeInputThreshold = __dna_reader.readFloatBig(); + /* x20c_sidewaysDoubleJumpImpulse */ + x20c_sidewaysDoubleJumpImpulse = __dna_reader.readFloatBig(); + /* x210_sidewaysVerticalDoubleJumpAccel */ + x210_sidewaysVerticalDoubleJumpAccel = __dna_reader.readFloatBig(); + /* x214_sidewaysHorizontalDoubleJumpAccel */ + x214_sidewaysHorizontalDoubleJumpAccel = __dna_reader.readFloatBig(); + /* x218_scanningRange */ + x218_scanningRange = __dna_reader.readFloatBig(); + /* x21c_24_scanRetention */ + x21c_24_scanRetention = __dna_reader.readBool(); + /* x21c_25_scanFreezesGame */ + x21c_25_scanFreezesGame = __dna_reader.readBool(); + /* x21c_26_orbitWhileScanning */ + x21c_26_orbitWhileScanning = __dna_reader.readBool(); + /* x220_scanMaxTargetDistance */ + x220_scanMaxTargetDistance = __dna_reader.readFloatBig(); + /* x224_scanMaxLockDistance */ + x224_scanMaxLockDistance = __dna_reader.readFloatBig(); + /* x2a0_orbitDistanceMax */ + x2a0_orbitDistanceMax = __dna_reader.readFloatBig(); + /* x2a4_grappleSwingLength */ + x2a4_grappleSwingLength = __dna_reader.readFloatBig(); + /* x2a8_grappleSwingPeriod */ + x2a8_grappleSwingPeriod = __dna_reader.readFloatBig(); + /* x2ac_grapplePullSpeedMin */ + x2ac_grapplePullSpeedMin = __dna_reader.readFloatBig(); + /* x2b0_grappleCameraSpeed */ + x2b0_grappleCameraSpeed = __dna_reader.readFloatBig(); + /* x2b4_maxGrappleLockedTurnAlignDistance */ + x2b4_maxGrappleLockedTurnAlignDistance = __dna_reader.readFloatBig(); + /* x2b8_grapplePullSpeedProportion */ + x2b8_grapplePullSpeedProportion = __dna_reader.readFloatBig(); + /* x2bc_grapplePullSpeedMax */ + x2bc_grapplePullSpeedMax = __dna_reader.readFloatBig(); + /* x2c0_grappleLookCenterSpeed */ + x2c0_grappleLookCenterSpeed = __dna_reader.readFloatBig(); + /* x2c4_maxGrappleTurnSpeed */ + x2c4_maxGrappleTurnSpeed = __dna_reader.readFloatBig(); + /* x2c8_grappleJumpForce */ + x2c8_grappleJumpForce = __dna_reader.readFloatBig(); + /* x2cc_grappleReleaseTime */ + x2cc_grappleReleaseTime = __dna_reader.readFloatBig(); + /* x2d0_grappleJumpMode */ + x2d0_grappleJumpMode = __dna_reader.readUint32Big(); + /* x2d4_orbitReleaseBreaksGrapple */ + x2d4_orbitReleaseBreaksGrapple = __dna_reader.readBool(); + /* x2d5_invertGrappleTurn */ + x2d5_invertGrappleTurn = __dna_reader.readBool(); + /* x2d8_grappleBeamSpeed */ + x2d8_grappleBeamSpeed = __dna_reader.readFloatBig(); + /* x2dc_grappleBeamXWaveAmplitude */ + x2dc_grappleBeamXWaveAmplitude = __dna_reader.readFloatBig(); + /* x2e0_grappleBeamZWaveAmplitude */ + x2e0_grappleBeamZWaveAmplitude = __dna_reader.readFloatBig(); + /* x2e4_grappleBeamAnglePhaseDelta */ + x2e4_grappleBeamAnglePhaseDelta = __dna_reader.readFloatBig(); + /* x26c_playerHeight */ + x26c_playerHeight = __dna_reader.readFloatBig(); + /* x270_playerXYHalfExtent */ + x270_playerXYHalfExtent = __dna_reader.readFloatBig(); + /* x274_stepUpHeight */ + x274_stepUpHeight = __dna_reader.readFloatBig(); + /* x278_stepDownHeight */ + x278_stepDownHeight = __dna_reader.readFloatBig(); + /* x27c_playerBallHalfExtent */ + x27c_playerBallHalfExtent = __dna_reader.readFloatBig(); + /* x280_ */ + x280_firstPersonCameraSpeed = __dna_reader.readFloatBig(); + /* x284_ */ + x284_ = __dna_reader.readFloatBig(); + /* x288_jumpCameraPitchDownStart */ + x288_jumpCameraPitchDownStart = __dna_reader.readFloatBig(); + /* x28c_jumpCameraPitchDownFull */ + x28c_jumpCameraPitchDownFull = __dna_reader.readFloatBig(); + /* x290_jumpCameraPitchDownAngle */ + x290_jumpCameraPitchDownAngle = __dna_reader.readFloatBig(); + /* x294_fallCameraPitchDownStart */ + x294_fallCameraPitchDownStart = __dna_reader.readFloatBig(); + /* x298_fallCameraPitchDownFull */ + x298_fallCameraPitchDownFull = __dna_reader.readFloatBig(); + /* x29c_fallCameraPitchDownAngle */ + x29c_fallCameraPitchDownAngle = __dna_reader.readFloatBig(); + /* x2e8_ */ + x2e8_ = __dna_reader.readFloatBig(); + /* x2ec_ */ + x2ec_ = __dna_reader.readFloatBig(); + /* x2f0_ */ + x2f0_ = __dna_reader.readFloatBig(); + /* x2f4_ */ + x2f4_ = __dna_reader.readBool(); + /* x2f8_frozenTimeout */ + x2f8_frozenTimeout = __dna_reader.readFloatBig(); + /* x2fc_iceBreakJumpCount */ + x2fc_iceBreakJumpCount = __dna_reader.readUint32Big(); + /* x300_variaDamageReduction */ + x300_variaDamageReduction = __dna_reader.readFloatBig(); + /* x304_gravityDamageReduction */ + x304_gravityDamageReduction = __dna_reader.readFloatBig(); + /* x308_phazonDamageReduction */ + x308_phazonDamageReduction = __dna_reader.readFloatBig(); } template <> -void CTweakPlayer::Enumerate(athena::io::IStreamWriter& __dna_writer) -{ - /* x4_maxTranslationalAcceleration[0] */ - __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[0]); - /* x4_maxTranslationalAcceleration[1] */ - __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[1]); - /* x4_maxTranslationalAcceleration[2] */ - __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[2]); - /* x4_maxTranslationalAcceleration[3] */ - __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[3]); - /* x4_maxTranslationalAcceleration[4] */ - __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[4]); - /* x4_maxTranslationalAcceleration[5] */ - __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[5]); - /* x4_maxTranslationalAcceleration[6] */ - __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[6]); - /* x4_maxTranslationalAcceleration[7] */ - __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[7]); - /* x24_maxRotationalAcceleration[0] */ - __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[0]); - /* x24_maxRotationalAcceleration[1] */ - __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[1]); - /* x24_maxRotationalAcceleration[2] */ - __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[2]); - /* x24_maxRotationalAcceleration[3] */ - __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[3]); - /* x24_maxRotationalAcceleration[4] */ - __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[4]); - /* x24_maxRotationalAcceleration[5] */ - __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[5]); - /* x24_maxRotationalAcceleration[6] */ - __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[6]); - /* x24_maxRotationalAcceleration[7] */ - __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[7]); - /* x44_translationFriction[0] */ - __dna_writer.writeFloatBig(x44_translationFriction[0]); - /* x44_translationFriction[1] */ - __dna_writer.writeFloatBig(x44_translationFriction[1]); - /* x44_translationFriction[2] */ - __dna_writer.writeFloatBig(x44_translationFriction[2]); - /* x44_translationFriction[3] */ - __dna_writer.writeFloatBig(x44_translationFriction[3]); - /* x44_translationFriction[4] */ - __dna_writer.writeFloatBig(x44_translationFriction[4]); - /* x44_translationFriction[5] */ - __dna_writer.writeFloatBig(x44_translationFriction[5]); - /* x44_translationFriction[6] */ - __dna_writer.writeFloatBig(x44_translationFriction[6]); - /* x44_translationFriction[7] */ - __dna_writer.writeFloatBig(x44_translationFriction[7]); - /* x64_rotationFriction[0] */ - __dna_writer.writeFloatBig(x64_rotationFriction[0]); - /* x64_rotationFriction[1] */ - __dna_writer.writeFloatBig(x64_rotationFriction[1]); - /* x64_rotationFriction[2] */ - __dna_writer.writeFloatBig(x64_rotationFriction[2]); - /* x64_rotationFriction[3] */ - __dna_writer.writeFloatBig(x64_rotationFriction[3]); - /* x64_rotationFriction[4] */ - __dna_writer.writeFloatBig(x64_rotationFriction[4]); - /* x64_rotationFriction[5] */ - __dna_writer.writeFloatBig(x64_rotationFriction[5]); - /* x64_rotationFriction[6] */ - __dna_writer.writeFloatBig(x64_rotationFriction[6]); - /* x64_rotationFriction[7] */ - __dna_writer.writeFloatBig(x64_rotationFriction[7]); - /* x84_rotationMaxSpeed[0] */ - __dna_writer.writeFloatBig(x84_rotationMaxSpeed[0]); - /* x84_rotationMaxSpeed[1] */ - __dna_writer.writeFloatBig(x84_rotationMaxSpeed[1]); - /* x84_rotationMaxSpeed[2] */ - __dna_writer.writeFloatBig(x84_rotationMaxSpeed[2]); - /* x84_rotationMaxSpeed[3] */ - __dna_writer.writeFloatBig(x84_rotationMaxSpeed[3]); - /* x84_rotationMaxSpeed[4] */ - __dna_writer.writeFloatBig(x84_rotationMaxSpeed[4]); - /* x84_rotationMaxSpeed[5] */ - __dna_writer.writeFloatBig(x84_rotationMaxSpeed[5]); - /* x84_rotationMaxSpeed[6] */ - __dna_writer.writeFloatBig(x84_rotationMaxSpeed[6]); - /* x84_rotationMaxSpeed[7] */ - __dna_writer.writeFloatBig(x84_rotationMaxSpeed[7]); - /* xa4_translationMaxSpeed[0] */ - __dna_writer.writeFloatBig(xa4_translationMaxSpeed[0]); - /* xa4_translationMaxSpeed[1] */ - __dna_writer.writeFloatBig(xa4_translationMaxSpeed[1]); - /* xa4_translationMaxSpeed[2] */ - __dna_writer.writeFloatBig(xa4_translationMaxSpeed[2]); - /* xa4_translationMaxSpeed[3] */ - __dna_writer.writeFloatBig(xa4_translationMaxSpeed[3]); - /* xa4_translationMaxSpeed[4] */ - __dna_writer.writeFloatBig(xa4_translationMaxSpeed[4]); - /* xa4_translationMaxSpeed[5] */ - __dna_writer.writeFloatBig(xa4_translationMaxSpeed[5]); - /* xa4_translationMaxSpeed[6] */ - __dna_writer.writeFloatBig(xa4_translationMaxSpeed[6]); - /* xa4_translationMaxSpeed[7] */ - __dna_writer.writeFloatBig(xa4_translationMaxSpeed[7]); - /* xc4_normalGravAccel */ - __dna_writer.writeFloatBig(xc4_normalGravAccel); - /* xc8_fluidGravAccel */ - __dna_writer.writeFloatBig(xc8_fluidGravAccel); - /* xcc_verticalJumpAccel */ - __dna_writer.writeFloatBig(xcc_verticalJumpAccel); - /* xd0_horizontalJumpAccel */ - __dna_writer.writeFloatBig(xd0_horizontalJumpAccel); - /* xd4_verticalDoubleJumpAccel */ - __dna_writer.writeFloatBig(xd4_verticalDoubleJumpAccel); - /* xd8_horizontalDoubleJumpAccel */ - __dna_writer.writeFloatBig(xd8_horizontalDoubleJumpAccel); - /* xdc_waterJumpFactor */ - __dna_writer.writeFloatBig(xdc_waterJumpFactor); - /* xe0_waterBallJumpFactor */ - __dna_writer.writeFloatBig(xe0_waterBallJumpFactor); - /* xe4_lavaJumpFactor */ - __dna_writer.writeFloatBig(xe4_lavaJumpFactor); - /* xe8_lavaBallJumpFactor */ - __dna_writer.writeFloatBig(xe8_lavaBallJumpFactor); - /* xec_phazonJumpFactor */ - __dna_writer.writeFloatBig(xec_phazonJumpFactor); - /* xf0_phazonBallJumpFactor */ - __dna_writer.writeFloatBig(xf0_phazonBallJumpFactor); - /* xf4_allowedJumpTime */ - __dna_writer.writeFloatBig(xf4_allowedJumpTime); - /* xf8_allowedDoubleJumpTime */ - __dna_writer.writeFloatBig(xf8_allowedDoubleJumpTime); - /* xfc_minDoubleJumpWindow */ - __dna_writer.writeFloatBig(xfc_minDoubleJumpWindow); - /* x100_maxDoubleJumpWindow */ - __dna_writer.writeFloatBig(x100_maxDoubleJumpWindow); - /* x104_ */ - __dna_writer.writeFloatBig(x104_); - /* x108_minJumpTime */ - __dna_writer.writeFloatBig(x108_minJumpTime); - /* x10c_minDoubleJumpTime */ - __dna_writer.writeFloatBig(x10c_minDoubleJumpTime); - /* x110_allowedLedgeTime */ - __dna_writer.writeFloatBig(x110_allowedLedgeTime); - /* x114_doubleJumpImpulse */ - __dna_writer.writeFloatBig(x114_doubleJumpImpulse); - /* x118_backwardsForceMultiplier */ - __dna_writer.writeFloatBig(x118_backwardsForceMultiplier); - /* x11c_bombJumpRadius */ - __dna_writer.writeFloatBig(x11c_bombJumpRadius); - /* x120_bombJumpHeight */ - __dna_writer.writeFloatBig(x120_bombJumpHeight); - /* x124_eyeOffset */ - __dna_writer.writeFloatBig(x124_eyeOffset); - /* x128_turnSpeedMultiplier */ - __dna_writer.writeFloatBig(x128_turnSpeedMultiplier); - /* x12c_freeLookTurnSpeedMultiplier */ - __dna_writer.writeFloatBig(x12c_freeLookTurnSpeedMultiplier); - /* x130_horizontalFreeLookAngleVel */ - __dna_writer.writeFloatBig(x130_horizontalFreeLookAngleVel); - /* x134_verticalFreeLookAngleVel */ - __dna_writer.writeFloatBig(x134_verticalFreeLookAngleVel); - /* x138_freeLookSpeed */ - __dna_writer.writeFloatBig(x138_freeLookSpeed); - /* x13c_freeLookSnapSpeed */ - __dna_writer.writeFloatBig(x13c_freeLookSnapSpeed); - /* x140_ */ - __dna_writer.writeFloatBig(x140_); - /* x144_freeLookCenteredThresholdAngle */ - __dna_writer.writeFloatBig(x144_freeLookCenteredThresholdAngle); - /* x148_freeLookCenteredTime */ - __dna_writer.writeFloatBig(x148_freeLookCenteredTime); - /* x14c_freeLookDampenFactor */ - __dna_writer.writeFloatBig(x14c_freeLookDampenFactor); - /* x150_leftDiv */ - __dna_writer.writeFloatBig(x150_leftDiv); - /* x154_rightDiv */ - __dna_writer.writeFloatBig(x154_rightDiv); - /* x228_24_freelookTurnsPlayer */ - __dna_writer.writeBool(x228_24_freelookTurnsPlayer); - /* x228_25_ */ - __dna_writer.writeBool(x228_25_); - /* x228_26_ */ - __dna_writer.writeBool(x228_26_); - /* x228_27_moveDuringFreeLook */ - __dna_writer.writeBool(x228_27_moveDuringFreeLook); - /* x228_28_holdButtonsForFreeLook */ - __dna_writer.writeBool(x228_28_holdButtonsForFreeLook); - /* x228_29_twoButtonsForFreeLook */ - __dna_writer.writeBool(x228_29_twoButtonsForFreeLook); - /* x228_30_ */ - __dna_writer.writeBool(x228_30_); - /* x228_31_ */ - __dna_writer.writeBool(x228_31_); - /* x229_24_ */ - __dna_writer.writeBool(x229_24_); - /* x229_25_aimWhenOrbitingPoint */ - __dna_writer.writeBool(x229_25_aimWhenOrbitingPoint); - /* x229_26_stayInFreeLookWhileFiring */ - __dna_writer.writeBool(x229_26_stayInFreeLookWhileFiring); - /* x229_27_ */ - __dna_writer.writeBool(x229_27_); - /* x229_28_ */ - __dna_writer.writeBool(x229_28_); - /* x229_29_orbitFixedOffset */ - __dna_writer.writeBool(x229_29_orbitFixedOffset); - /* x229_30_gunButtonTogglesHolster */ - __dna_writer.writeBool(x229_30_gunButtonTogglesHolster); - /* x229_31_gunNotFiringHolstersGun */ - __dna_writer.writeBool(x229_31_gunNotFiringHolstersGun); - /* x22a_24_fallingDoubleJump */ - __dna_writer.writeBool(x22a_24_fallingDoubleJump); - /* x22a_25_impulseDoubleJump */ - __dna_writer.writeBool(x22a_25_impulseDoubleJump); - /* x22a_26_firingCancelsCameraPitch */ - __dna_writer.writeBool(x22a_26_firingCancelsCameraPitch); - /* x22a_27_assistedAimingIgnoreHorizontal */ - __dna_writer.writeBool(x22a_27_assistedAimingIgnoreHorizontal); - /* x22a_28_assistedAimingIgnoreVertical */ - __dna_writer.writeBool(x22a_28_assistedAimingIgnoreVertical); - /* x22c_ */ - __dna_writer.writeFloatBig(x22c_); - /* x230_ */ - __dna_writer.writeFloatBig(x230_); - /* x234_aimMaxDistance */ - __dna_writer.writeFloatBig(x234_aimMaxDistance); - /* x238_ */ - __dna_writer.writeFloatBig(x238_); - /* x23c_ */ - __dna_writer.writeFloatBig(x23c_); - /* x240_ */ - __dna_writer.writeFloatBig(x240_); - /* x244_ */ - __dna_writer.writeFloatBig(x244_); - /* x248_ */ - __dna_writer.writeFloatBig(x248_); - /* x24c_aimThresholdDistance */ - __dna_writer.writeFloatBig(x24c_aimThresholdDistance); - /* x250_ */ - __dna_writer.writeFloatBig(x250_); - /* x254_ */ - __dna_writer.writeFloatBig(x254_); - /* x258_aimBoxWidth */ - __dna_writer.writeFloatBig(x258_aimBoxWidth); - /* x25c_aimBoxHeight */ - __dna_writer.writeFloatBig(x25c_aimBoxHeight); - /* x260_aimTargetTimer */ - __dna_writer.writeFloatBig(x260_aimTargetTimer); - /* x264_aimAssistHorizontalAngle */ - __dna_writer.writeFloatBig(x264_aimAssistHorizontalAngle); - /* x268_aimAssistVerticalAngle */ - __dna_writer.writeFloatBig(x268_aimAssistVerticalAngle); - /* x158_orbitMinDistance[0] */ - __dna_writer.writeFloatBig(x158_orbitMinDistance[0]); - /* x164_orbitNormalDistance[0] */ - __dna_writer.writeFloatBig(x164_orbitNormalDistance[0]); - /* x170_orbitMaxDistance[0] */ - __dna_writer.writeFloatBig(x170_orbitMaxDistance[0]); - /* x158_orbitMinDistance[1] */ - __dna_writer.writeFloatBig(x158_orbitMinDistance[1]); - /* x164_orbitNormalDistance[1] */ - __dna_writer.writeFloatBig(x164_orbitNormalDistance[1]); - /* x170_orbitMaxDistance[1] */ - __dna_writer.writeFloatBig(x170_orbitMaxDistance[1]); - /* x158_orbitMinDistance[2] */ - __dna_writer.writeFloatBig(x158_orbitMinDistance[2]); - /* x164_orbitNormalDistance[2] */ - __dna_writer.writeFloatBig(x164_orbitNormalDistance[2]); - /* x170_orbitMaxDistance[2] */ - __dna_writer.writeFloatBig(x170_orbitMaxDistance[2]); - /* x17c_ */ - __dna_writer.writeFloatBig(x17c_); - /* x180_orbitModeTimer */ - __dna_writer.writeFloatBig(x180_orbitModeTimer); - /* x184_orbitCameraSpeed */ - __dna_writer.writeFloatBig(x184_orbitCameraSpeed); - /* x188_orbitUpperAngle */ - __dna_writer.writeFloatBig(x188_orbitUpperAngle); - /* x18c_orbitLowerAngle */ - __dna_writer.writeFloatBig(x18c_orbitLowerAngle); - /* x190_orbitHorizAngle */ - __dna_writer.writeFloatBig(x190_orbitHorizAngle); - /* x194_ */ - __dna_writer.writeFloatBig(x194_); - /* x198_ */ - __dna_writer.writeFloatBig(x198_); - /* x19c_orbitMaxTargetDistance */ - __dna_writer.writeFloatBig(x19c_orbitMaxTargetDistance); - /* x1a0_orbitMaxLockDistance */ - __dna_writer.writeFloatBig(x1a0_orbitMaxLockDistance); - /* x1a4_orbitDistanceThreshold */ - __dna_writer.writeFloatBig(x1a4_orbitDistanceThreshold); - /* x1a8_orbitScreenBoxHalfExtentX[0] */ - __dna_writer.writeUint32Big(x1a8_orbitScreenBoxHalfExtentX[0]); - /* x1b0_orbitScreenBoxHalfExtentY[0] */ - __dna_writer.writeUint32Big(x1b0_orbitScreenBoxHalfExtentY[0]); - /* x1b8_orbitScreenBoxCenterX[0] */ - __dna_writer.writeUint32Big(x1b8_orbitScreenBoxCenterX[0]); - /* x1c0_orbitScreenBoxCenterY[0] */ - __dna_writer.writeUint32Big(x1c0_orbitScreenBoxCenterY[0]); - /* x1c8_orbitZoneIdealX[0] */ - __dna_writer.writeUint32Big(x1c8_orbitZoneIdealX[0]); - /* x1d0_orbitZoneIdealY[0] */ - __dna_writer.writeUint32Big(x1d0_orbitZoneIdealY[0]); - /* x1a8_orbitScreenBoxHalfExtentX[1] */ - __dna_writer.writeUint32Big(x1a8_orbitScreenBoxHalfExtentX[1]); - /* x1b0_orbitScreenBoxHalfExtentY[1] */ - __dna_writer.writeUint32Big(x1b0_orbitScreenBoxHalfExtentY[1]); - /* x1b8_orbitScreenBoxCenterX[1] */ - __dna_writer.writeUint32Big(x1b8_orbitScreenBoxCenterX[1]); - /* x1c0_orbitScreenBoxCenterY[1] */ - __dna_writer.writeUint32Big(x1c0_orbitScreenBoxCenterY[1]); - /* x1c8_orbitZoneIdealX[1] */ - __dna_writer.writeUint32Big(x1c8_orbitZoneIdealX[1]); - /* x1d0_orbitZoneIdealY[1] */ - __dna_writer.writeUint32Big(x1d0_orbitZoneIdealY[1]); - /* x1d8_orbitNearX */ - __dna_writer.writeFloatBig(x1d8_orbitNearX); - /* x1dc_orbitNearZ */ - __dna_writer.writeFloatBig(x1dc_orbitNearZ); - /* x1e0_ */ - __dna_writer.writeFloatBig(x1e0_); - /* x1e4_ */ - __dna_writer.writeFloatBig(x1e4_); - /* x1e8_orbitFixedOffsetZDiff */ - __dna_writer.writeFloatBig(x1e8_orbitFixedOffsetZDiff); - /* x1ec_orbitZRange */ - __dna_writer.writeFloatBig(x1ec_orbitZRange); - /* x1f0_ */ - __dna_writer.writeFloatBig(x1f0_); - /* x1f4_ */ - __dna_writer.writeFloatBig(x1f4_); - /* x1f8_ */ - __dna_writer.writeFloatBig(x1f8_); - /* x1fc_orbitPreventionTime */ - __dna_writer.writeFloatBig(x1fc_orbitPreventionTime); - /* x200_24_dashEnabled */ - __dna_writer.writeBool(x200_24_dashEnabled); - /* x200_25_dashOnButtonRelease */ - __dna_writer.writeBool(x200_25_dashOnButtonRelease); - /* x204_dashButtonHoldCancelTime */ - __dna_writer.writeFloatBig(x204_dashButtonHoldCancelTime); - /* x208_dashStrafeInputThreshold */ - __dna_writer.writeFloatBig(x208_dashStrafeInputThreshold); - /* x20c_sidewaysDoubleJumpImpulse */ - __dna_writer.writeFloatBig(x20c_sidewaysDoubleJumpImpulse); - /* x210_sidewaysVerticalDoubleJumpAccel */ - __dna_writer.writeFloatBig(x210_sidewaysVerticalDoubleJumpAccel); - /* x214_sidewaysHorizontalDoubleJumpAccel */ - __dna_writer.writeFloatBig(x214_sidewaysHorizontalDoubleJumpAccel); - /* x218_scanningRange */ - __dna_writer.writeFloatBig(x218_scanningRange); - /* x21c_24_scanRetention */ - __dna_writer.writeBool(x21c_24_scanRetention); - /* x21c_25_scanFreezesGame */ - __dna_writer.writeBool(x21c_25_scanFreezesGame); - /* x21c_26_orbitWhileScanning */ - __dna_writer.writeBool(x21c_26_orbitWhileScanning); - /* x220_scanMaxTargetDistance */ - __dna_writer.writeFloatBig(x220_scanMaxTargetDistance); - /* x224_scanMaxLockDistance */ - __dna_writer.writeFloatBig(x224_scanMaxLockDistance); - /* x2a0_orbitDistanceMax */ - __dna_writer.writeFloatBig(x2a0_orbitDistanceMax); - /* x2a4_grappleSwingLength */ - __dna_writer.writeFloatBig(x2a4_grappleSwingLength); - /* x2a8_grappleSwingPeriod */ - __dna_writer.writeFloatBig(x2a8_grappleSwingPeriod); - /* x2ac_grapplePullSpeedMin */ - __dna_writer.writeFloatBig(x2ac_grapplePullSpeedMin); - /* x2b0_grappleCameraSpeed */ - __dna_writer.writeFloatBig(x2b0_grappleCameraSpeed); - /* x2b4_maxGrappleLockedTurnAlignDistance */ - __dna_writer.writeFloatBig(x2b4_maxGrappleLockedTurnAlignDistance); - /* x2b8_grapplePullSpeedProportion */ - __dna_writer.writeFloatBig(x2b8_grapplePullSpeedProportion); - /* x2bc_grapplePullSpeedMax */ - __dna_writer.writeFloatBig(x2bc_grapplePullSpeedMax); - /* x2c0_grappleLookCenterSpeed */ - __dna_writer.writeFloatBig(x2c0_grappleLookCenterSpeed); - /* x2c4_maxGrappleTurnSpeed */ - __dna_writer.writeFloatBig(x2c4_maxGrappleTurnSpeed); - /* x2c8_grappleJumpForce */ - __dna_writer.writeFloatBig(x2c8_grappleJumpForce); - /* x2cc_grappleReleaseTime */ - __dna_writer.writeFloatBig(x2cc_grappleReleaseTime); - /* x2d0_grappleJumpMode */ - __dna_writer.writeUint32Big(x2d0_grappleJumpMode); - /* x2d4_orbitReleaseBreaksGrapple */ - __dna_writer.writeBool(x2d4_orbitReleaseBreaksGrapple); - /* x2d5_invertGrappleTurn */ - __dna_writer.writeBool(x2d5_invertGrappleTurn); - /* x2d8_grappleBeamSpeed */ - __dna_writer.writeFloatBig(x2d8_grappleBeamSpeed); - /* x2dc_grappleBeamXWaveAmplitude */ - __dna_writer.writeFloatBig(x2dc_grappleBeamXWaveAmplitude); - /* x2e0_grappleBeamZWaveAmplitude */ - __dna_writer.writeFloatBig(x2e0_grappleBeamZWaveAmplitude); - /* x2e4_grappleBeamAnglePhaseDelta */ - __dna_writer.writeFloatBig(x2e4_grappleBeamAnglePhaseDelta); - /* x26c_playerHeight */ - __dna_writer.writeFloatBig(x26c_playerHeight); - /* x270_playerXYHalfExtent */ - __dna_writer.writeFloatBig(x270_playerXYHalfExtent); - /* x274_stepUpHeight */ - __dna_writer.writeFloatBig(x274_stepUpHeight); - /* x278_stepDownHeight */ - __dna_writer.writeFloatBig(x278_stepDownHeight); - /* x27c_playerBallHalfExtent */ - __dna_writer.writeFloatBig(x27c_playerBallHalfExtent); - /* x280_ */ - __dna_writer.writeFloatBig(x280_firstPersonCameraSpeed); - /* x284_ */ - __dna_writer.writeFloatBig(x284_); - /* x288_jumpCameraPitchDownStart */ - __dna_writer.writeFloatBig(x288_jumpCameraPitchDownStart); - /* x28c_jumpCameraPitchDownFull */ - __dna_writer.writeFloatBig(x28c_jumpCameraPitchDownFull); - /* x290_jumpCameraPitchDownAngle */ - __dna_writer.writeFloatBig(x290_jumpCameraPitchDownAngle); - /* x294_fallCameraPitchDownStart */ - __dna_writer.writeFloatBig(x294_fallCameraPitchDownStart); - /* x298_fallCameraPitchDownFull */ - __dna_writer.writeFloatBig(x298_fallCameraPitchDownFull); - /* x29c_fallCameraPitchDownAngle */ - __dna_writer.writeFloatBig(x29c_fallCameraPitchDownAngle); - /* x2e8_ */ - __dna_writer.writeFloatBig(x2e8_); - /* x2ec_ */ - __dna_writer.writeFloatBig(x2ec_); - /* x2f0_ */ - __dna_writer.writeFloatBig(x2f0_); - /* x2f4_ */ - __dna_writer.writeBool(x2f4_); - /* x2f8_frozenTimeout */ - __dna_writer.writeFloatBig(x2f8_frozenTimeout); - /* x2fc_iceBreakJumpCount */ - __dna_writer.writeUint32Big(x2fc_iceBreakJumpCount); - /* x300_variaDamageReduction */ - __dna_writer.writeFloatBig(x300_variaDamageReduction); - /* x304_gravityDamageReduction */ - __dna_writer.writeFloatBig(x304_gravityDamageReduction); - /* x308_phazonDamageReduction */ - __dna_writer.writeFloatBig(x308_phazonDamageReduction); +void CTweakPlayer::Enumerate(athena::io::IStreamWriter& __dna_writer) { + /* x4_maxTranslationalAcceleration[0] */ + __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[0]); + /* x4_maxTranslationalAcceleration[1] */ + __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[1]); + /* x4_maxTranslationalAcceleration[2] */ + __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[2]); + /* x4_maxTranslationalAcceleration[3] */ + __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[3]); + /* x4_maxTranslationalAcceleration[4] */ + __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[4]); + /* x4_maxTranslationalAcceleration[5] */ + __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[5]); + /* x4_maxTranslationalAcceleration[6] */ + __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[6]); + /* x4_maxTranslationalAcceleration[7] */ + __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[7]); + /* x24_maxRotationalAcceleration[0] */ + __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[0]); + /* x24_maxRotationalAcceleration[1] */ + __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[1]); + /* x24_maxRotationalAcceleration[2] */ + __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[2]); + /* x24_maxRotationalAcceleration[3] */ + __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[3]); + /* x24_maxRotationalAcceleration[4] */ + __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[4]); + /* x24_maxRotationalAcceleration[5] */ + __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[5]); + /* x24_maxRotationalAcceleration[6] */ + __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[6]); + /* x24_maxRotationalAcceleration[7] */ + __dna_writer.writeFloatBig(x24_maxRotationalAcceleration[7]); + /* x44_translationFriction[0] */ + __dna_writer.writeFloatBig(x44_translationFriction[0]); + /* x44_translationFriction[1] */ + __dna_writer.writeFloatBig(x44_translationFriction[1]); + /* x44_translationFriction[2] */ + __dna_writer.writeFloatBig(x44_translationFriction[2]); + /* x44_translationFriction[3] */ + __dna_writer.writeFloatBig(x44_translationFriction[3]); + /* x44_translationFriction[4] */ + __dna_writer.writeFloatBig(x44_translationFriction[4]); + /* x44_translationFriction[5] */ + __dna_writer.writeFloatBig(x44_translationFriction[5]); + /* x44_translationFriction[6] */ + __dna_writer.writeFloatBig(x44_translationFriction[6]); + /* x44_translationFriction[7] */ + __dna_writer.writeFloatBig(x44_translationFriction[7]); + /* x64_rotationFriction[0] */ + __dna_writer.writeFloatBig(x64_rotationFriction[0]); + /* x64_rotationFriction[1] */ + __dna_writer.writeFloatBig(x64_rotationFriction[1]); + /* x64_rotationFriction[2] */ + __dna_writer.writeFloatBig(x64_rotationFriction[2]); + /* x64_rotationFriction[3] */ + __dna_writer.writeFloatBig(x64_rotationFriction[3]); + /* x64_rotationFriction[4] */ + __dna_writer.writeFloatBig(x64_rotationFriction[4]); + /* x64_rotationFriction[5] */ + __dna_writer.writeFloatBig(x64_rotationFriction[5]); + /* x64_rotationFriction[6] */ + __dna_writer.writeFloatBig(x64_rotationFriction[6]); + /* x64_rotationFriction[7] */ + __dna_writer.writeFloatBig(x64_rotationFriction[7]); + /* x84_rotationMaxSpeed[0] */ + __dna_writer.writeFloatBig(x84_rotationMaxSpeed[0]); + /* x84_rotationMaxSpeed[1] */ + __dna_writer.writeFloatBig(x84_rotationMaxSpeed[1]); + /* x84_rotationMaxSpeed[2] */ + __dna_writer.writeFloatBig(x84_rotationMaxSpeed[2]); + /* x84_rotationMaxSpeed[3] */ + __dna_writer.writeFloatBig(x84_rotationMaxSpeed[3]); + /* x84_rotationMaxSpeed[4] */ + __dna_writer.writeFloatBig(x84_rotationMaxSpeed[4]); + /* x84_rotationMaxSpeed[5] */ + __dna_writer.writeFloatBig(x84_rotationMaxSpeed[5]); + /* x84_rotationMaxSpeed[6] */ + __dna_writer.writeFloatBig(x84_rotationMaxSpeed[6]); + /* x84_rotationMaxSpeed[7] */ + __dna_writer.writeFloatBig(x84_rotationMaxSpeed[7]); + /* xa4_translationMaxSpeed[0] */ + __dna_writer.writeFloatBig(xa4_translationMaxSpeed[0]); + /* xa4_translationMaxSpeed[1] */ + __dna_writer.writeFloatBig(xa4_translationMaxSpeed[1]); + /* xa4_translationMaxSpeed[2] */ + __dna_writer.writeFloatBig(xa4_translationMaxSpeed[2]); + /* xa4_translationMaxSpeed[3] */ + __dna_writer.writeFloatBig(xa4_translationMaxSpeed[3]); + /* xa4_translationMaxSpeed[4] */ + __dna_writer.writeFloatBig(xa4_translationMaxSpeed[4]); + /* xa4_translationMaxSpeed[5] */ + __dna_writer.writeFloatBig(xa4_translationMaxSpeed[5]); + /* xa4_translationMaxSpeed[6] */ + __dna_writer.writeFloatBig(xa4_translationMaxSpeed[6]); + /* xa4_translationMaxSpeed[7] */ + __dna_writer.writeFloatBig(xa4_translationMaxSpeed[7]); + /* xc4_normalGravAccel */ + __dna_writer.writeFloatBig(xc4_normalGravAccel); + /* xc8_fluidGravAccel */ + __dna_writer.writeFloatBig(xc8_fluidGravAccel); + /* xcc_verticalJumpAccel */ + __dna_writer.writeFloatBig(xcc_verticalJumpAccel); + /* xd0_horizontalJumpAccel */ + __dna_writer.writeFloatBig(xd0_horizontalJumpAccel); + /* xd4_verticalDoubleJumpAccel */ + __dna_writer.writeFloatBig(xd4_verticalDoubleJumpAccel); + /* xd8_horizontalDoubleJumpAccel */ + __dna_writer.writeFloatBig(xd8_horizontalDoubleJumpAccel); + /* xdc_waterJumpFactor */ + __dna_writer.writeFloatBig(xdc_waterJumpFactor); + /* xe0_waterBallJumpFactor */ + __dna_writer.writeFloatBig(xe0_waterBallJumpFactor); + /* xe4_lavaJumpFactor */ + __dna_writer.writeFloatBig(xe4_lavaJumpFactor); + /* xe8_lavaBallJumpFactor */ + __dna_writer.writeFloatBig(xe8_lavaBallJumpFactor); + /* xec_phazonJumpFactor */ + __dna_writer.writeFloatBig(xec_phazonJumpFactor); + /* xf0_phazonBallJumpFactor */ + __dna_writer.writeFloatBig(xf0_phazonBallJumpFactor); + /* xf4_allowedJumpTime */ + __dna_writer.writeFloatBig(xf4_allowedJumpTime); + /* xf8_allowedDoubleJumpTime */ + __dna_writer.writeFloatBig(xf8_allowedDoubleJumpTime); + /* xfc_minDoubleJumpWindow */ + __dna_writer.writeFloatBig(xfc_minDoubleJumpWindow); + /* x100_maxDoubleJumpWindow */ + __dna_writer.writeFloatBig(x100_maxDoubleJumpWindow); + /* x104_ */ + __dna_writer.writeFloatBig(x104_); + /* x108_minJumpTime */ + __dna_writer.writeFloatBig(x108_minJumpTime); + /* x10c_minDoubleJumpTime */ + __dna_writer.writeFloatBig(x10c_minDoubleJumpTime); + /* x110_allowedLedgeTime */ + __dna_writer.writeFloatBig(x110_allowedLedgeTime); + /* x114_doubleJumpImpulse */ + __dna_writer.writeFloatBig(x114_doubleJumpImpulse); + /* x118_backwardsForceMultiplier */ + __dna_writer.writeFloatBig(x118_backwardsForceMultiplier); + /* x11c_bombJumpRadius */ + __dna_writer.writeFloatBig(x11c_bombJumpRadius); + /* x120_bombJumpHeight */ + __dna_writer.writeFloatBig(x120_bombJumpHeight); + /* x124_eyeOffset */ + __dna_writer.writeFloatBig(x124_eyeOffset); + /* x128_turnSpeedMultiplier */ + __dna_writer.writeFloatBig(x128_turnSpeedMultiplier); + /* x12c_freeLookTurnSpeedMultiplier */ + __dna_writer.writeFloatBig(x12c_freeLookTurnSpeedMultiplier); + /* x130_horizontalFreeLookAngleVel */ + __dna_writer.writeFloatBig(x130_horizontalFreeLookAngleVel); + /* x134_verticalFreeLookAngleVel */ + __dna_writer.writeFloatBig(x134_verticalFreeLookAngleVel); + /* x138_freeLookSpeed */ + __dna_writer.writeFloatBig(x138_freeLookSpeed); + /* x13c_freeLookSnapSpeed */ + __dna_writer.writeFloatBig(x13c_freeLookSnapSpeed); + /* x140_ */ + __dna_writer.writeFloatBig(x140_); + /* x144_freeLookCenteredThresholdAngle */ + __dna_writer.writeFloatBig(x144_freeLookCenteredThresholdAngle); + /* x148_freeLookCenteredTime */ + __dna_writer.writeFloatBig(x148_freeLookCenteredTime); + /* x14c_freeLookDampenFactor */ + __dna_writer.writeFloatBig(x14c_freeLookDampenFactor); + /* x150_leftDiv */ + __dna_writer.writeFloatBig(x150_leftDiv); + /* x154_rightDiv */ + __dna_writer.writeFloatBig(x154_rightDiv); + /* x228_24_freelookTurnsPlayer */ + __dna_writer.writeBool(x228_24_freelookTurnsPlayer); + /* x228_25_ */ + __dna_writer.writeBool(x228_25_); + /* x228_26_ */ + __dna_writer.writeBool(x228_26_); + /* x228_27_moveDuringFreeLook */ + __dna_writer.writeBool(x228_27_moveDuringFreeLook); + /* x228_28_holdButtonsForFreeLook */ + __dna_writer.writeBool(x228_28_holdButtonsForFreeLook); + /* x228_29_twoButtonsForFreeLook */ + __dna_writer.writeBool(x228_29_twoButtonsForFreeLook); + /* x228_30_ */ + __dna_writer.writeBool(x228_30_); + /* x228_31_ */ + __dna_writer.writeBool(x228_31_); + /* x229_24_ */ + __dna_writer.writeBool(x229_24_); + /* x229_25_aimWhenOrbitingPoint */ + __dna_writer.writeBool(x229_25_aimWhenOrbitingPoint); + /* x229_26_stayInFreeLookWhileFiring */ + __dna_writer.writeBool(x229_26_stayInFreeLookWhileFiring); + /* x229_27_ */ + __dna_writer.writeBool(x229_27_); + /* x229_28_ */ + __dna_writer.writeBool(x229_28_); + /* x229_29_orbitFixedOffset */ + __dna_writer.writeBool(x229_29_orbitFixedOffset); + /* x229_30_gunButtonTogglesHolster */ + __dna_writer.writeBool(x229_30_gunButtonTogglesHolster); + /* x229_31_gunNotFiringHolstersGun */ + __dna_writer.writeBool(x229_31_gunNotFiringHolstersGun); + /* x22a_24_fallingDoubleJump */ + __dna_writer.writeBool(x22a_24_fallingDoubleJump); + /* x22a_25_impulseDoubleJump */ + __dna_writer.writeBool(x22a_25_impulseDoubleJump); + /* x22a_26_firingCancelsCameraPitch */ + __dna_writer.writeBool(x22a_26_firingCancelsCameraPitch); + /* x22a_27_assistedAimingIgnoreHorizontal */ + __dna_writer.writeBool(x22a_27_assistedAimingIgnoreHorizontal); + /* x22a_28_assistedAimingIgnoreVertical */ + __dna_writer.writeBool(x22a_28_assistedAimingIgnoreVertical); + /* x22c_ */ + __dna_writer.writeFloatBig(x22c_); + /* x230_ */ + __dna_writer.writeFloatBig(x230_); + /* x234_aimMaxDistance */ + __dna_writer.writeFloatBig(x234_aimMaxDistance); + /* x238_ */ + __dna_writer.writeFloatBig(x238_); + /* x23c_ */ + __dna_writer.writeFloatBig(x23c_); + /* x240_ */ + __dna_writer.writeFloatBig(x240_); + /* x244_ */ + __dna_writer.writeFloatBig(x244_); + /* x248_ */ + __dna_writer.writeFloatBig(x248_); + /* x24c_aimThresholdDistance */ + __dna_writer.writeFloatBig(x24c_aimThresholdDistance); + /* x250_ */ + __dna_writer.writeFloatBig(x250_); + /* x254_ */ + __dna_writer.writeFloatBig(x254_); + /* x258_aimBoxWidth */ + __dna_writer.writeFloatBig(x258_aimBoxWidth); + /* x25c_aimBoxHeight */ + __dna_writer.writeFloatBig(x25c_aimBoxHeight); + /* x260_aimTargetTimer */ + __dna_writer.writeFloatBig(x260_aimTargetTimer); + /* x264_aimAssistHorizontalAngle */ + __dna_writer.writeFloatBig(x264_aimAssistHorizontalAngle); + /* x268_aimAssistVerticalAngle */ + __dna_writer.writeFloatBig(x268_aimAssistVerticalAngle); + /* x158_orbitMinDistance[0] */ + __dna_writer.writeFloatBig(x158_orbitMinDistance[0]); + /* x164_orbitNormalDistance[0] */ + __dna_writer.writeFloatBig(x164_orbitNormalDistance[0]); + /* x170_orbitMaxDistance[0] */ + __dna_writer.writeFloatBig(x170_orbitMaxDistance[0]); + /* x158_orbitMinDistance[1] */ + __dna_writer.writeFloatBig(x158_orbitMinDistance[1]); + /* x164_orbitNormalDistance[1] */ + __dna_writer.writeFloatBig(x164_orbitNormalDistance[1]); + /* x170_orbitMaxDistance[1] */ + __dna_writer.writeFloatBig(x170_orbitMaxDistance[1]); + /* x158_orbitMinDistance[2] */ + __dna_writer.writeFloatBig(x158_orbitMinDistance[2]); + /* x164_orbitNormalDistance[2] */ + __dna_writer.writeFloatBig(x164_orbitNormalDistance[2]); + /* x170_orbitMaxDistance[2] */ + __dna_writer.writeFloatBig(x170_orbitMaxDistance[2]); + /* x17c_ */ + __dna_writer.writeFloatBig(x17c_); + /* x180_orbitModeTimer */ + __dna_writer.writeFloatBig(x180_orbitModeTimer); + /* x184_orbitCameraSpeed */ + __dna_writer.writeFloatBig(x184_orbitCameraSpeed); + /* x188_orbitUpperAngle */ + __dna_writer.writeFloatBig(x188_orbitUpperAngle); + /* x18c_orbitLowerAngle */ + __dna_writer.writeFloatBig(x18c_orbitLowerAngle); + /* x190_orbitHorizAngle */ + __dna_writer.writeFloatBig(x190_orbitHorizAngle); + /* x194_ */ + __dna_writer.writeFloatBig(x194_); + /* x198_ */ + __dna_writer.writeFloatBig(x198_); + /* x19c_orbitMaxTargetDistance */ + __dna_writer.writeFloatBig(x19c_orbitMaxTargetDistance); + /* x1a0_orbitMaxLockDistance */ + __dna_writer.writeFloatBig(x1a0_orbitMaxLockDistance); + /* x1a4_orbitDistanceThreshold */ + __dna_writer.writeFloatBig(x1a4_orbitDistanceThreshold); + /* x1a8_orbitScreenBoxHalfExtentX[0] */ + __dna_writer.writeUint32Big(x1a8_orbitScreenBoxHalfExtentX[0]); + /* x1b0_orbitScreenBoxHalfExtentY[0] */ + __dna_writer.writeUint32Big(x1b0_orbitScreenBoxHalfExtentY[0]); + /* x1b8_orbitScreenBoxCenterX[0] */ + __dna_writer.writeUint32Big(x1b8_orbitScreenBoxCenterX[0]); + /* x1c0_orbitScreenBoxCenterY[0] */ + __dna_writer.writeUint32Big(x1c0_orbitScreenBoxCenterY[0]); + /* x1c8_orbitZoneIdealX[0] */ + __dna_writer.writeUint32Big(x1c8_orbitZoneIdealX[0]); + /* x1d0_orbitZoneIdealY[0] */ + __dna_writer.writeUint32Big(x1d0_orbitZoneIdealY[0]); + /* x1a8_orbitScreenBoxHalfExtentX[1] */ + __dna_writer.writeUint32Big(x1a8_orbitScreenBoxHalfExtentX[1]); + /* x1b0_orbitScreenBoxHalfExtentY[1] */ + __dna_writer.writeUint32Big(x1b0_orbitScreenBoxHalfExtentY[1]); + /* x1b8_orbitScreenBoxCenterX[1] */ + __dna_writer.writeUint32Big(x1b8_orbitScreenBoxCenterX[1]); + /* x1c0_orbitScreenBoxCenterY[1] */ + __dna_writer.writeUint32Big(x1c0_orbitScreenBoxCenterY[1]); + /* x1c8_orbitZoneIdealX[1] */ + __dna_writer.writeUint32Big(x1c8_orbitZoneIdealX[1]); + /* x1d0_orbitZoneIdealY[1] */ + __dna_writer.writeUint32Big(x1d0_orbitZoneIdealY[1]); + /* x1d8_orbitNearX */ + __dna_writer.writeFloatBig(x1d8_orbitNearX); + /* x1dc_orbitNearZ */ + __dna_writer.writeFloatBig(x1dc_orbitNearZ); + /* x1e0_ */ + __dna_writer.writeFloatBig(x1e0_); + /* x1e4_ */ + __dna_writer.writeFloatBig(x1e4_); + /* x1e8_orbitFixedOffsetZDiff */ + __dna_writer.writeFloatBig(x1e8_orbitFixedOffsetZDiff); + /* x1ec_orbitZRange */ + __dna_writer.writeFloatBig(x1ec_orbitZRange); + /* x1f0_ */ + __dna_writer.writeFloatBig(x1f0_); + /* x1f4_ */ + __dna_writer.writeFloatBig(x1f4_); + /* x1f8_ */ + __dna_writer.writeFloatBig(x1f8_); + /* x1fc_orbitPreventionTime */ + __dna_writer.writeFloatBig(x1fc_orbitPreventionTime); + /* x200_24_dashEnabled */ + __dna_writer.writeBool(x200_24_dashEnabled); + /* x200_25_dashOnButtonRelease */ + __dna_writer.writeBool(x200_25_dashOnButtonRelease); + /* x204_dashButtonHoldCancelTime */ + __dna_writer.writeFloatBig(x204_dashButtonHoldCancelTime); + /* x208_dashStrafeInputThreshold */ + __dna_writer.writeFloatBig(x208_dashStrafeInputThreshold); + /* x20c_sidewaysDoubleJumpImpulse */ + __dna_writer.writeFloatBig(x20c_sidewaysDoubleJumpImpulse); + /* x210_sidewaysVerticalDoubleJumpAccel */ + __dna_writer.writeFloatBig(x210_sidewaysVerticalDoubleJumpAccel); + /* x214_sidewaysHorizontalDoubleJumpAccel */ + __dna_writer.writeFloatBig(x214_sidewaysHorizontalDoubleJumpAccel); + /* x218_scanningRange */ + __dna_writer.writeFloatBig(x218_scanningRange); + /* x21c_24_scanRetention */ + __dna_writer.writeBool(x21c_24_scanRetention); + /* x21c_25_scanFreezesGame */ + __dna_writer.writeBool(x21c_25_scanFreezesGame); + /* x21c_26_orbitWhileScanning */ + __dna_writer.writeBool(x21c_26_orbitWhileScanning); + /* x220_scanMaxTargetDistance */ + __dna_writer.writeFloatBig(x220_scanMaxTargetDistance); + /* x224_scanMaxLockDistance */ + __dna_writer.writeFloatBig(x224_scanMaxLockDistance); + /* x2a0_orbitDistanceMax */ + __dna_writer.writeFloatBig(x2a0_orbitDistanceMax); + /* x2a4_grappleSwingLength */ + __dna_writer.writeFloatBig(x2a4_grappleSwingLength); + /* x2a8_grappleSwingPeriod */ + __dna_writer.writeFloatBig(x2a8_grappleSwingPeriod); + /* x2ac_grapplePullSpeedMin */ + __dna_writer.writeFloatBig(x2ac_grapplePullSpeedMin); + /* x2b0_grappleCameraSpeed */ + __dna_writer.writeFloatBig(x2b0_grappleCameraSpeed); + /* x2b4_maxGrappleLockedTurnAlignDistance */ + __dna_writer.writeFloatBig(x2b4_maxGrappleLockedTurnAlignDistance); + /* x2b8_grapplePullSpeedProportion */ + __dna_writer.writeFloatBig(x2b8_grapplePullSpeedProportion); + /* x2bc_grapplePullSpeedMax */ + __dna_writer.writeFloatBig(x2bc_grapplePullSpeedMax); + /* x2c0_grappleLookCenterSpeed */ + __dna_writer.writeFloatBig(x2c0_grappleLookCenterSpeed); + /* x2c4_maxGrappleTurnSpeed */ + __dna_writer.writeFloatBig(x2c4_maxGrappleTurnSpeed); + /* x2c8_grappleJumpForce */ + __dna_writer.writeFloatBig(x2c8_grappleJumpForce); + /* x2cc_grappleReleaseTime */ + __dna_writer.writeFloatBig(x2cc_grappleReleaseTime); + /* x2d0_grappleJumpMode */ + __dna_writer.writeUint32Big(x2d0_grappleJumpMode); + /* x2d4_orbitReleaseBreaksGrapple */ + __dna_writer.writeBool(x2d4_orbitReleaseBreaksGrapple); + /* x2d5_invertGrappleTurn */ + __dna_writer.writeBool(x2d5_invertGrappleTurn); + /* x2d8_grappleBeamSpeed */ + __dna_writer.writeFloatBig(x2d8_grappleBeamSpeed); + /* x2dc_grappleBeamXWaveAmplitude */ + __dna_writer.writeFloatBig(x2dc_grappleBeamXWaveAmplitude); + /* x2e0_grappleBeamZWaveAmplitude */ + __dna_writer.writeFloatBig(x2e0_grappleBeamZWaveAmplitude); + /* x2e4_grappleBeamAnglePhaseDelta */ + __dna_writer.writeFloatBig(x2e4_grappleBeamAnglePhaseDelta); + /* x26c_playerHeight */ + __dna_writer.writeFloatBig(x26c_playerHeight); + /* x270_playerXYHalfExtent */ + __dna_writer.writeFloatBig(x270_playerXYHalfExtent); + /* x274_stepUpHeight */ + __dna_writer.writeFloatBig(x274_stepUpHeight); + /* x278_stepDownHeight */ + __dna_writer.writeFloatBig(x278_stepDownHeight); + /* x27c_playerBallHalfExtent */ + __dna_writer.writeFloatBig(x27c_playerBallHalfExtent); + /* x280_ */ + __dna_writer.writeFloatBig(x280_firstPersonCameraSpeed); + /* x284_ */ + __dna_writer.writeFloatBig(x284_); + /* x288_jumpCameraPitchDownStart */ + __dna_writer.writeFloatBig(x288_jumpCameraPitchDownStart); + /* x28c_jumpCameraPitchDownFull */ + __dna_writer.writeFloatBig(x28c_jumpCameraPitchDownFull); + /* x290_jumpCameraPitchDownAngle */ + __dna_writer.writeFloatBig(x290_jumpCameraPitchDownAngle); + /* x294_fallCameraPitchDownStart */ + __dna_writer.writeFloatBig(x294_fallCameraPitchDownStart); + /* x298_fallCameraPitchDownFull */ + __dna_writer.writeFloatBig(x298_fallCameraPitchDownFull); + /* x29c_fallCameraPitchDownAngle */ + __dna_writer.writeFloatBig(x29c_fallCameraPitchDownAngle); + /* x2e8_ */ + __dna_writer.writeFloatBig(x2e8_); + /* x2ec_ */ + __dna_writer.writeFloatBig(x2ec_); + /* x2f0_ */ + __dna_writer.writeFloatBig(x2f0_); + /* x2f4_ */ + __dna_writer.writeBool(x2f4_); + /* x2f8_frozenTimeout */ + __dna_writer.writeFloatBig(x2f8_frozenTimeout); + /* x2fc_iceBreakJumpCount */ + __dna_writer.writeUint32Big(x2fc_iceBreakJumpCount); + /* x300_variaDamageReduction */ + __dna_writer.writeFloatBig(x300_variaDamageReduction); + /* x304_gravityDamageReduction */ + __dna_writer.writeFloatBig(x304_gravityDamageReduction); + /* x308_phazonDamageReduction */ + __dna_writer.writeFloatBig(x308_phazonDamageReduction); } template <> -void CTweakPlayer::Enumerate(athena::io::YAMLDocReader& __dna_docin) -{ - /* x4_maxTranslationalAcceleration */ - size_t __x4_Count; - if (auto v = __dna_docin.enterSubVector("x4_maxTranslationalAcceleration", __x4_Count)) - { +void CTweakPlayer::Enumerate(athena::io::YAMLDocReader& __dna_docin) { + /* x4_maxTranslationalAcceleration */ + size_t __x4_Count; + if (auto v = __dna_docin.enterSubVector("x4_maxTranslationalAcceleration", __x4_Count)) { /* x4_maxTranslationalAcceleration[0] */ x4_maxTranslationalAcceleration[0] = __dna_docin.readFloat("x4_maxTranslationalAcceleration"); /* x4_maxTranslationalAcceleration[1] */ @@ -909,11 +904,10 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocReader& __dna_ x4_maxTranslationalAcceleration[6] = __dna_docin.readFloat("x4_maxTranslationalAcceleration"); /* x4_maxTranslationalAcceleration[7] */ x4_maxTranslationalAcceleration[7] = __dna_docin.readFloat("x4_maxTranslationalAcceleration"); - } - /* x24_maxRotationalAcceleration */ - size_t __x24_Count; - if (auto v = __dna_docin.enterSubVector("x24_maxRotationalAcceleration", __x24_Count)) - { + } + /* x24_maxRotationalAcceleration */ + size_t __x24_Count; + if (auto v = __dna_docin.enterSubVector("x24_maxRotationalAcceleration", __x24_Count)) { /* x24_maxRotationalAcceleration[0] */ x24_maxRotationalAcceleration[0] = __dna_docin.readFloat("x24_maxRotationalAcceleration"); /* x24_maxRotationalAcceleration[1] */ @@ -930,11 +924,10 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocReader& __dna_ x24_maxRotationalAcceleration[6] = __dna_docin.readFloat("x24_maxRotationalAcceleration"); /* x24_maxRotationalAcceleration[7] */ x24_maxRotationalAcceleration[7] = __dna_docin.readFloat("x24_maxRotationalAcceleration"); - } - /* x44_translationFriction */ - size_t __x44_Count; - if (auto v = __dna_docin.enterSubVector("x44_translationFriction", __x44_Count)) - { + } + /* x44_translationFriction */ + size_t __x44_Count; + if (auto v = __dna_docin.enterSubVector("x44_translationFriction", __x44_Count)) { /* x44_translationFriction[0] */ x44_translationFriction[0] = __dna_docin.readFloat("x44_translationFriction"); /* x44_translationFriction[1] */ @@ -951,11 +944,10 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocReader& __dna_ x44_translationFriction[6] = __dna_docin.readFloat("x44_translationFriction"); /* x44_translationFriction[7] */ x44_translationFriction[7] = __dna_docin.readFloat("x44_translationFriction"); - } - /* x64_rotationFriction */ - size_t __x64_Count; - if (auto v = __dna_docin.enterSubVector("x64_rotationFriction", __x64_Count)) - { + } + /* x64_rotationFriction */ + size_t __x64_Count; + if (auto v = __dna_docin.enterSubVector("x64_rotationFriction", __x64_Count)) { /* x64_rotationFriction[0] */ x64_rotationFriction[0] = __dna_docin.readFloat("x64_rotationFriction"); /* x64_rotationFriction[1] */ @@ -972,11 +964,10 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocReader& __dna_ x64_rotationFriction[6] = __dna_docin.readFloat("x64_rotationFriction"); /* x64_rotationFriction[7] */ x64_rotationFriction[7] = __dna_docin.readFloat("x64_rotationFriction"); - } - /* x84_rotationMaxSpeed */ - size_t __x84_Count; - if (auto v = __dna_docin.enterSubVector("x84_rotationMaxSpeed", __x84_Count)) - { + } + /* x84_rotationMaxSpeed */ + size_t __x84_Count; + if (auto v = __dna_docin.enterSubVector("x84_rotationMaxSpeed", __x84_Count)) { /* x84_rotationMaxSpeed[0] */ x84_rotationMaxSpeed[0] = __dna_docin.readFloat("x84_rotationMaxSpeed"); /* x84_rotationMaxSpeed[1] */ @@ -993,11 +984,10 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocReader& __dna_ x84_rotationMaxSpeed[6] = __dna_docin.readFloat("x84_rotationMaxSpeed"); /* x84_rotationMaxSpeed[7] */ x84_rotationMaxSpeed[7] = __dna_docin.readFloat("x84_rotationMaxSpeed"); - } - /* xa4_translationMaxSpeed */ - size_t __xa4_Count; - if (auto v = __dna_docin.enterSubVector("xa4_translationMaxSpeed", __xa4_Count)) - { + } + /* xa4_translationMaxSpeed */ + size_t __xa4_Count; + if (auto v = __dna_docin.enterSubVector("xa4_translationMaxSpeed", __xa4_Count)) { /* xa4_translationMaxSpeed[0] */ xa4_translationMaxSpeed[0] = __dna_docin.readFloat("xa4_translationMaxSpeed"); /* xa4_translationMaxSpeed[1] */ @@ -1014,400 +1004,389 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocReader& __dna_ xa4_translationMaxSpeed[6] = __dna_docin.readFloat("xa4_translationMaxSpeed"); /* xa4_translationMaxSpeed[7] */ xa4_translationMaxSpeed[7] = __dna_docin.readFloat("xa4_translationMaxSpeed"); - } - /* xc4_normalGravAccel */ - xc4_normalGravAccel = __dna_docin.readFloat("xc4_normalGravAccel"); - /* xc8_fluidGravAccel */ - xc8_fluidGravAccel = __dna_docin.readFloat("xc8_fluidGravAccel"); - /* xcc_verticalJumpAccel */ - xcc_verticalJumpAccel = __dna_docin.readFloat("xcc_verticalJumpAccel"); - /* xd0_horizontalJumpAccel */ - xd0_horizontalJumpAccel = __dna_docin.readFloat("xd0_horizontalJumpAccel"); - /* xd4_verticalDoubleJumpAccel */ - xd4_verticalDoubleJumpAccel = __dna_docin.readFloat("xd4_verticalDoubleJumpAccel"); - /* xd8_horizontalDoubleJumpAccel */ - xd8_horizontalDoubleJumpAccel = __dna_docin.readFloat("xd8_horizontalDoubleJumpAccel"); - /* xdc_waterJumpFactor */ - xdc_waterJumpFactor = __dna_docin.readFloat("xdc_waterJumpFactor"); - /* xe0_waterBallJumpFactor */ - xe0_waterBallJumpFactor = __dna_docin.readFloat("xe0_waterBallJumpFactor"); - /* xe4_lavaJumpFactor */ - xe4_lavaJumpFactor = __dna_docin.readFloat("xe4_lavaJumpFactor"); - /* xe8_lavaBallJumpFactor */ - xe8_lavaBallJumpFactor = __dna_docin.readFloat("xe8_lavaBallJumpFactor"); - /* xec_phazonJumpFactor */ - xec_phazonJumpFactor = __dna_docin.readFloat("xec_phazonJumpFactor"); - /* xf0_phazonBallJumpFactor */ - xf0_phazonBallJumpFactor = __dna_docin.readFloat("xf0_phazonBallJumpFactor"); - /* xf4_allowedJumpTime */ - xf4_allowedJumpTime = __dna_docin.readFloat("xf4_allowedJumpTime"); - /* xf8_allowedDoubleJumpTime */ - xf8_allowedDoubleJumpTime = __dna_docin.readFloat("xf8_allowedDoubleJumpTime"); - /* xfc_minDoubleJumpWindow */ - xfc_minDoubleJumpWindow = __dna_docin.readFloat("xfc_minDoubleJumpWindow"); - /* x100_maxDoubleJumpWindow */ - x100_maxDoubleJumpWindow = __dna_docin.readFloat("x100_maxDoubleJumpWindow"); - /* x104_ */ - x104_ = __dna_docin.readFloat("x104_"); - /* x108_minJumpTime */ - x108_minJumpTime = __dna_docin.readFloat("x108_minJumpTime"); - /* x10c_minDoubleJumpTime */ - x10c_minDoubleJumpTime = __dna_docin.readFloat("x10c_minDoubleJumpTime"); - /* x110_allowedLedgeTime */ - x110_allowedLedgeTime = __dna_docin.readFloat("x110_allowedLedgeTime"); - /* x114_doubleJumpImpulse */ - x114_doubleJumpImpulse = __dna_docin.readFloat("x114_doubleJumpImpulse"); - /* x118_backwardsForceMultiplier */ - x118_backwardsForceMultiplier = __dna_docin.readFloat("x118_backwardsForceMultiplier"); - /* x11c_bombJumpRadius */ - x11c_bombJumpRadius = __dna_docin.readFloat("x11c_bombJumpRadius"); - /* x120_bombJumpHeight */ - x120_bombJumpHeight = __dna_docin.readFloat("x120_bombJumpHeight"); - /* x124_eyeOffset */ - x124_eyeOffset = __dna_docin.readFloat("x124_eyeOffset"); - /* x128_turnSpeedMultiplier */ - x128_turnSpeedMultiplier = __dna_docin.readFloat("x128_turnSpeedMultiplier"); - /* x12c_freeLookTurnSpeedMultiplier */ - x12c_freeLookTurnSpeedMultiplier = __dna_docin.readFloat("x12c_freeLookTurnSpeedMultiplier"); - /* x130_horizontalFreeLookAngleVel */ - x130_horizontalFreeLookAngleVel = __dna_docin.readFloat("x130_horizontalFreeLookAngleVel"); - /* x134_verticalFreeLookAngleVel */ - x134_verticalFreeLookAngleVel = __dna_docin.readFloat("x134_verticalFreeLookAngleVel"); - /* x138_freeLookSpeed */ - x138_freeLookSpeed = __dna_docin.readFloat("x138_freeLookSpeed"); - /* x13c_freeLookSnapSpeed */ - x13c_freeLookSnapSpeed = __dna_docin.readFloat("x13c_freeLookSnapSpeed"); - /* x140_ */ - x140_ = __dna_docin.readFloat("x140_"); - /* x144_freeLookCenteredThresholdAngle */ - x144_freeLookCenteredThresholdAngle = __dna_docin.readFloat("x144_freeLookCenteredThresholdAngle"); - /* x148_freeLookCenteredTime */ - x148_freeLookCenteredTime = __dna_docin.readFloat("x148_freeLookCenteredTime"); - /* x14c_freeLookDampenFactor */ - x14c_freeLookDampenFactor = __dna_docin.readFloat("x14c_freeLookDampenFactor"); - /* x150_leftDiv */ - x150_leftDiv = __dna_docin.readFloat("x150_leftDiv"); - /* x154_rightDiv */ - x154_rightDiv = __dna_docin.readFloat("x154_rightDiv"); - /* x228_24_freelookTurnsPlayer */ - x228_24_freelookTurnsPlayer = __dna_docin.readBool("x228_24_freelookTurnsPlayer"); - /* x228_25_ */ - x228_25_ = __dna_docin.readBool("x228_25_"); - /* x228_26_ */ - x228_26_ = __dna_docin.readBool("x228_26_"); - /* x228_27_moveDuringFreeLook */ - x228_27_moveDuringFreeLook = __dna_docin.readBool("x228_27_moveDuringFreeLook"); - /* x228_28_holdButtonsForFreeLook */ - x228_28_holdButtonsForFreeLook = __dna_docin.readBool("x228_28_holdButtonsForFreeLook"); - /* x228_29_twoButtonsForFreeLook */ - x228_29_twoButtonsForFreeLook = __dna_docin.readBool("x228_29_twoButtonsForFreeLook"); - /* x228_30_ */ - x228_30_ = __dna_docin.readBool("x228_30_"); - /* x228_31_ */ - x228_31_ = __dna_docin.readBool("x228_31_"); - /* x229_24_ */ - x229_24_ = __dna_docin.readBool("x229_24_"); - /* x229_25_aimWhenOrbitingPoint */ - x229_25_aimWhenOrbitingPoint = __dna_docin.readBool("x229_25_aimWhenOrbitingPoint"); - /* x229_26_stayInFreeLookWhileFiring */ - x229_26_stayInFreeLookWhileFiring = __dna_docin.readBool("x229_26_stayInFreeLookWhileFiring"); - /* x229_27_ */ - x229_27_ = __dna_docin.readBool("x229_27_"); - /* x229_28_ */ - x229_28_ = __dna_docin.readBool("x229_28_"); - /* x229_29_orbitFixedOffset */ - x229_29_orbitFixedOffset = __dna_docin.readBool("x229_29_orbitFixedOffset"); - /* x229_30_gunButtonTogglesHolster */ - x229_30_gunButtonTogglesHolster = __dna_docin.readBool("x229_30_gunButtonTogglesHolster"); - /* x229_31_gunNotFiringHolstersGun */ - x229_31_gunNotFiringHolstersGun = __dna_docin.readBool("x229_31_gunNotFiringHolstersGun"); - /* x22a_24_fallingDoubleJump */ - x22a_24_fallingDoubleJump = __dna_docin.readBool("x22a_24_fallingDoubleJump"); - /* x22a_25_impulseDoubleJump */ - x22a_25_impulseDoubleJump = __dna_docin.readBool("x22a_25_impulseDoubleJump"); - /* x22a_26_firingCancelsCameraPitch */ - x22a_26_firingCancelsCameraPitch = __dna_docin.readBool("x22a_26_firingCancelsCameraPitch"); - /* x22a_27_assistedAimingIgnoreHorizontal */ - x22a_27_assistedAimingIgnoreHorizontal = __dna_docin.readBool("x22a_27_assistedAimingIgnoreHorizontal"); - /* x22a_28_assistedAimingIgnoreVertical */ - x22a_28_assistedAimingIgnoreVertical = __dna_docin.readBool("x22a_28_assistedAimingIgnoreVertical"); - /* x22c_ */ - x22c_ = __dna_docin.readFloat("x22c_"); - /* x230_ */ - x230_ = __dna_docin.readFloat("x230_"); - /* x234_aimMaxDistance */ - x234_aimMaxDistance = __dna_docin.readFloat("x234_aimMaxDistance"); - /* x238_ */ - x238_ = __dna_docin.readFloat("x238_"); - /* x23c_ */ - x23c_ = __dna_docin.readFloat("x23c_"); - /* x240_ */ - x240_ = __dna_docin.readFloat("x240_"); - /* x244_ */ - x244_ = __dna_docin.readFloat("x244_"); - /* x248_ */ - x248_ = __dna_docin.readFloat("x248_"); - /* x24c_aimThresholdDistance */ - x24c_aimThresholdDistance = __dna_docin.readFloat("x24c_aimThresholdDistance"); - /* x250_ */ - x250_ = __dna_docin.readFloat("x250_"); - /* x254_ */ - x254_ = __dna_docin.readFloat("x254_"); - /* x258_aimBoxWidth */ - x258_aimBoxWidth = __dna_docin.readFloat("x258_aimBoxWidth"); - /* x25c_aimBoxHeight */ - x25c_aimBoxHeight = __dna_docin.readFloat("x25c_aimBoxHeight"); - /* x260_aimTargetTimer */ - x260_aimTargetTimer = __dna_docin.readFloat("x260_aimTargetTimer"); - /* x264_aimAssistHorizontalAngle */ - x264_aimAssistHorizontalAngle = __dna_docin.readFloat("x264_aimAssistHorizontalAngle"); - /* x268_aimAssistVerticalAngle */ - x268_aimAssistVerticalAngle = __dna_docin.readFloat("x268_aimAssistVerticalAngle"); - /* x158_orbitMinDistance */ - size_t __x158_Count; - if (auto v = __dna_docin.enterSubVector("x158_orbitMinDistance", __x158_Count)) - { + } + /* xc4_normalGravAccel */ + xc4_normalGravAccel = __dna_docin.readFloat("xc4_normalGravAccel"); + /* xc8_fluidGravAccel */ + xc8_fluidGravAccel = __dna_docin.readFloat("xc8_fluidGravAccel"); + /* xcc_verticalJumpAccel */ + xcc_verticalJumpAccel = __dna_docin.readFloat("xcc_verticalJumpAccel"); + /* xd0_horizontalJumpAccel */ + xd0_horizontalJumpAccel = __dna_docin.readFloat("xd0_horizontalJumpAccel"); + /* xd4_verticalDoubleJumpAccel */ + xd4_verticalDoubleJumpAccel = __dna_docin.readFloat("xd4_verticalDoubleJumpAccel"); + /* xd8_horizontalDoubleJumpAccel */ + xd8_horizontalDoubleJumpAccel = __dna_docin.readFloat("xd8_horizontalDoubleJumpAccel"); + /* xdc_waterJumpFactor */ + xdc_waterJumpFactor = __dna_docin.readFloat("xdc_waterJumpFactor"); + /* xe0_waterBallJumpFactor */ + xe0_waterBallJumpFactor = __dna_docin.readFloat("xe0_waterBallJumpFactor"); + /* xe4_lavaJumpFactor */ + xe4_lavaJumpFactor = __dna_docin.readFloat("xe4_lavaJumpFactor"); + /* xe8_lavaBallJumpFactor */ + xe8_lavaBallJumpFactor = __dna_docin.readFloat("xe8_lavaBallJumpFactor"); + /* xec_phazonJumpFactor */ + xec_phazonJumpFactor = __dna_docin.readFloat("xec_phazonJumpFactor"); + /* xf0_phazonBallJumpFactor */ + xf0_phazonBallJumpFactor = __dna_docin.readFloat("xf0_phazonBallJumpFactor"); + /* xf4_allowedJumpTime */ + xf4_allowedJumpTime = __dna_docin.readFloat("xf4_allowedJumpTime"); + /* xf8_allowedDoubleJumpTime */ + xf8_allowedDoubleJumpTime = __dna_docin.readFloat("xf8_allowedDoubleJumpTime"); + /* xfc_minDoubleJumpWindow */ + xfc_minDoubleJumpWindow = __dna_docin.readFloat("xfc_minDoubleJumpWindow"); + /* x100_maxDoubleJumpWindow */ + x100_maxDoubleJumpWindow = __dna_docin.readFloat("x100_maxDoubleJumpWindow"); + /* x104_ */ + x104_ = __dna_docin.readFloat("x104_"); + /* x108_minJumpTime */ + x108_minJumpTime = __dna_docin.readFloat("x108_minJumpTime"); + /* x10c_minDoubleJumpTime */ + x10c_minDoubleJumpTime = __dna_docin.readFloat("x10c_minDoubleJumpTime"); + /* x110_allowedLedgeTime */ + x110_allowedLedgeTime = __dna_docin.readFloat("x110_allowedLedgeTime"); + /* x114_doubleJumpImpulse */ + x114_doubleJumpImpulse = __dna_docin.readFloat("x114_doubleJumpImpulse"); + /* x118_backwardsForceMultiplier */ + x118_backwardsForceMultiplier = __dna_docin.readFloat("x118_backwardsForceMultiplier"); + /* x11c_bombJumpRadius */ + x11c_bombJumpRadius = __dna_docin.readFloat("x11c_bombJumpRadius"); + /* x120_bombJumpHeight */ + x120_bombJumpHeight = __dna_docin.readFloat("x120_bombJumpHeight"); + /* x124_eyeOffset */ + x124_eyeOffset = __dna_docin.readFloat("x124_eyeOffset"); + /* x128_turnSpeedMultiplier */ + x128_turnSpeedMultiplier = __dna_docin.readFloat("x128_turnSpeedMultiplier"); + /* x12c_freeLookTurnSpeedMultiplier */ + x12c_freeLookTurnSpeedMultiplier = __dna_docin.readFloat("x12c_freeLookTurnSpeedMultiplier"); + /* x130_horizontalFreeLookAngleVel */ + x130_horizontalFreeLookAngleVel = __dna_docin.readFloat("x130_horizontalFreeLookAngleVel"); + /* x134_verticalFreeLookAngleVel */ + x134_verticalFreeLookAngleVel = __dna_docin.readFloat("x134_verticalFreeLookAngleVel"); + /* x138_freeLookSpeed */ + x138_freeLookSpeed = __dna_docin.readFloat("x138_freeLookSpeed"); + /* x13c_freeLookSnapSpeed */ + x13c_freeLookSnapSpeed = __dna_docin.readFloat("x13c_freeLookSnapSpeed"); + /* x140_ */ + x140_ = __dna_docin.readFloat("x140_"); + /* x144_freeLookCenteredThresholdAngle */ + x144_freeLookCenteredThresholdAngle = __dna_docin.readFloat("x144_freeLookCenteredThresholdAngle"); + /* x148_freeLookCenteredTime */ + x148_freeLookCenteredTime = __dna_docin.readFloat("x148_freeLookCenteredTime"); + /* x14c_freeLookDampenFactor */ + x14c_freeLookDampenFactor = __dna_docin.readFloat("x14c_freeLookDampenFactor"); + /* x150_leftDiv */ + x150_leftDiv = __dna_docin.readFloat("x150_leftDiv"); + /* x154_rightDiv */ + x154_rightDiv = __dna_docin.readFloat("x154_rightDiv"); + /* x228_24_freelookTurnsPlayer */ + x228_24_freelookTurnsPlayer = __dna_docin.readBool("x228_24_freelookTurnsPlayer"); + /* x228_25_ */ + x228_25_ = __dna_docin.readBool("x228_25_"); + /* x228_26_ */ + x228_26_ = __dna_docin.readBool("x228_26_"); + /* x228_27_moveDuringFreeLook */ + x228_27_moveDuringFreeLook = __dna_docin.readBool("x228_27_moveDuringFreeLook"); + /* x228_28_holdButtonsForFreeLook */ + x228_28_holdButtonsForFreeLook = __dna_docin.readBool("x228_28_holdButtonsForFreeLook"); + /* x228_29_twoButtonsForFreeLook */ + x228_29_twoButtonsForFreeLook = __dna_docin.readBool("x228_29_twoButtonsForFreeLook"); + /* x228_30_ */ + x228_30_ = __dna_docin.readBool("x228_30_"); + /* x228_31_ */ + x228_31_ = __dna_docin.readBool("x228_31_"); + /* x229_24_ */ + x229_24_ = __dna_docin.readBool("x229_24_"); + /* x229_25_aimWhenOrbitingPoint */ + x229_25_aimWhenOrbitingPoint = __dna_docin.readBool("x229_25_aimWhenOrbitingPoint"); + /* x229_26_stayInFreeLookWhileFiring */ + x229_26_stayInFreeLookWhileFiring = __dna_docin.readBool("x229_26_stayInFreeLookWhileFiring"); + /* x229_27_ */ + x229_27_ = __dna_docin.readBool("x229_27_"); + /* x229_28_ */ + x229_28_ = __dna_docin.readBool("x229_28_"); + /* x229_29_orbitFixedOffset */ + x229_29_orbitFixedOffset = __dna_docin.readBool("x229_29_orbitFixedOffset"); + /* x229_30_gunButtonTogglesHolster */ + x229_30_gunButtonTogglesHolster = __dna_docin.readBool("x229_30_gunButtonTogglesHolster"); + /* x229_31_gunNotFiringHolstersGun */ + x229_31_gunNotFiringHolstersGun = __dna_docin.readBool("x229_31_gunNotFiringHolstersGun"); + /* x22a_24_fallingDoubleJump */ + x22a_24_fallingDoubleJump = __dna_docin.readBool("x22a_24_fallingDoubleJump"); + /* x22a_25_impulseDoubleJump */ + x22a_25_impulseDoubleJump = __dna_docin.readBool("x22a_25_impulseDoubleJump"); + /* x22a_26_firingCancelsCameraPitch */ + x22a_26_firingCancelsCameraPitch = __dna_docin.readBool("x22a_26_firingCancelsCameraPitch"); + /* x22a_27_assistedAimingIgnoreHorizontal */ + x22a_27_assistedAimingIgnoreHorizontal = __dna_docin.readBool("x22a_27_assistedAimingIgnoreHorizontal"); + /* x22a_28_assistedAimingIgnoreVertical */ + x22a_28_assistedAimingIgnoreVertical = __dna_docin.readBool("x22a_28_assistedAimingIgnoreVertical"); + /* x22c_ */ + x22c_ = __dna_docin.readFloat("x22c_"); + /* x230_ */ + x230_ = __dna_docin.readFloat("x230_"); + /* x234_aimMaxDistance */ + x234_aimMaxDistance = __dna_docin.readFloat("x234_aimMaxDistance"); + /* x238_ */ + x238_ = __dna_docin.readFloat("x238_"); + /* x23c_ */ + x23c_ = __dna_docin.readFloat("x23c_"); + /* x240_ */ + x240_ = __dna_docin.readFloat("x240_"); + /* x244_ */ + x244_ = __dna_docin.readFloat("x244_"); + /* x248_ */ + x248_ = __dna_docin.readFloat("x248_"); + /* x24c_aimThresholdDistance */ + x24c_aimThresholdDistance = __dna_docin.readFloat("x24c_aimThresholdDistance"); + /* x250_ */ + x250_ = __dna_docin.readFloat("x250_"); + /* x254_ */ + x254_ = __dna_docin.readFloat("x254_"); + /* x258_aimBoxWidth */ + x258_aimBoxWidth = __dna_docin.readFloat("x258_aimBoxWidth"); + /* x25c_aimBoxHeight */ + x25c_aimBoxHeight = __dna_docin.readFloat("x25c_aimBoxHeight"); + /* x260_aimTargetTimer */ + x260_aimTargetTimer = __dna_docin.readFloat("x260_aimTargetTimer"); + /* x264_aimAssistHorizontalAngle */ + x264_aimAssistHorizontalAngle = __dna_docin.readFloat("x264_aimAssistHorizontalAngle"); + /* x268_aimAssistVerticalAngle */ + x268_aimAssistVerticalAngle = __dna_docin.readFloat("x268_aimAssistVerticalAngle"); + /* x158_orbitMinDistance */ + size_t __x158_Count; + if (auto v = __dna_docin.enterSubVector("x158_orbitMinDistance", __x158_Count)) { /* x158_orbitMinDistance[0] */ x158_orbitMinDistance[0] = __dna_docin.readFloat("x158_orbitMinDistance"); /* x158_orbitMinDistance[1] */ x158_orbitMinDistance[1] = __dna_docin.readFloat("x158_orbitMinDistance"); /* x158_orbitMinDistance[2] */ x158_orbitMinDistance[2] = __dna_docin.readFloat("x158_orbitMinDistance"); - } - /* x164_orbitNormalDistance */ - size_t __x164_Count; - if (auto v = __dna_docin.enterSubVector("x164_orbitNormalDistance", __x164_Count)) - { + } + /* x164_orbitNormalDistance */ + size_t __x164_Count; + if (auto v = __dna_docin.enterSubVector("x164_orbitNormalDistance", __x164_Count)) { /* x164_orbitNormalDistance[0] */ x164_orbitNormalDistance[0] = __dna_docin.readFloat("x164_orbitNormalDistance"); /* x164_orbitNormalDistance[1] */ x164_orbitNormalDistance[1] = __dna_docin.readFloat("x164_orbitNormalDistance"); /* x164_orbitNormalDistance[2] */ x164_orbitNormalDistance[2] = __dna_docin.readFloat("x164_orbitNormalDistance"); - } - /* x170_orbitMaxDistance */ - size_t __x170_Count; - if (auto v = __dna_docin.enterSubVector("x170_orbitMaxDistance", __x170_Count)) - { + } + /* x170_orbitMaxDistance */ + size_t __x170_Count; + if (auto v = __dna_docin.enterSubVector("x170_orbitMaxDistance", __x170_Count)) { /* x170_orbitMaxDistance[0] */ x170_orbitMaxDistance[0] = __dna_docin.readFloat("x170_orbitMaxDistance"); /* x170_orbitMaxDistance[1] */ x170_orbitMaxDistance[1] = __dna_docin.readFloat("x170_orbitMaxDistance"); /* x170_orbitMaxDistance[2] */ x170_orbitMaxDistance[2] = __dna_docin.readFloat("x170_orbitMaxDistance"); - } - /* x17c_ */ - x17c_ = __dna_docin.readFloat("x17c_"); - /* x180_orbitModeTimer */ - x180_orbitModeTimer = __dna_docin.readFloat("x180_orbitModeTimer"); - /* x184_orbitCameraSpeed */ - x184_orbitCameraSpeed = __dna_docin.readFloat("x184_orbitCameraSpeed"); - /* x188_orbitUpperAngle */ - x188_orbitUpperAngle = __dna_docin.readFloat("x188_orbitUpperAngle"); - /* x18c_orbitLowerAngle */ - x18c_orbitLowerAngle = __dna_docin.readFloat("x18c_orbitLowerAngle"); - /* x190_orbitHorizAngle */ - x190_orbitHorizAngle = __dna_docin.readFloat("x190_orbitHorizAngle"); - /* x194_ */ - x194_ = __dna_docin.readFloat("x194_"); - /* x198_ */ - x198_ = __dna_docin.readFloat("x198_"); - /* x19c_orbitMaxTargetDistance */ - x19c_orbitMaxTargetDistance = __dna_docin.readFloat("x19c_orbitMaxTargetDistance"); - /* x1a0_orbitMaxLockDistance */ - x1a0_orbitMaxLockDistance = __dna_docin.readFloat("x1a0_orbitMaxLockDistance"); - /* x1a4_orbitDistanceThreshold */ - x1a4_orbitDistanceThreshold = __dna_docin.readFloat("x1a4_orbitDistanceThreshold"); - /* x1a8_orbitScreenBoxHalfExtentX */ - size_t __x1a8_Count; - if (auto v = __dna_docin.enterSubVector("x1a8_orbitScreenBoxHalfExtentX", __x1a8_Count)) - { + } + /* x17c_ */ + x17c_ = __dna_docin.readFloat("x17c_"); + /* x180_orbitModeTimer */ + x180_orbitModeTimer = __dna_docin.readFloat("x180_orbitModeTimer"); + /* x184_orbitCameraSpeed */ + x184_orbitCameraSpeed = __dna_docin.readFloat("x184_orbitCameraSpeed"); + /* x188_orbitUpperAngle */ + x188_orbitUpperAngle = __dna_docin.readFloat("x188_orbitUpperAngle"); + /* x18c_orbitLowerAngle */ + x18c_orbitLowerAngle = __dna_docin.readFloat("x18c_orbitLowerAngle"); + /* x190_orbitHorizAngle */ + x190_orbitHorizAngle = __dna_docin.readFloat("x190_orbitHorizAngle"); + /* x194_ */ + x194_ = __dna_docin.readFloat("x194_"); + /* x198_ */ + x198_ = __dna_docin.readFloat("x198_"); + /* x19c_orbitMaxTargetDistance */ + x19c_orbitMaxTargetDistance = __dna_docin.readFloat("x19c_orbitMaxTargetDistance"); + /* x1a0_orbitMaxLockDistance */ + x1a0_orbitMaxLockDistance = __dna_docin.readFloat("x1a0_orbitMaxLockDistance"); + /* x1a4_orbitDistanceThreshold */ + x1a4_orbitDistanceThreshold = __dna_docin.readFloat("x1a4_orbitDistanceThreshold"); + /* x1a8_orbitScreenBoxHalfExtentX */ + size_t __x1a8_Count; + if (auto v = __dna_docin.enterSubVector("x1a8_orbitScreenBoxHalfExtentX", __x1a8_Count)) { /* x1a8_orbitScreenBoxHalfExtentX[0] */ x1a8_orbitScreenBoxHalfExtentX[0] = __dna_docin.readUint32("x1a8_orbitScreenBoxHalfExtentX"); /* x1a8_orbitScreenBoxHalfExtentX[1] */ x1a8_orbitScreenBoxHalfExtentX[1] = __dna_docin.readUint32("x1a8_orbitScreenBoxHalfExtentX"); - } - /* x1b0_orbitScreenBoxHalfExtentY */ - size_t __x1b0_Count; - if (auto v = __dna_docin.enterSubVector("x1b0_orbitScreenBoxHalfExtentY", __x1b0_Count)) - { + } + /* x1b0_orbitScreenBoxHalfExtentY */ + size_t __x1b0_Count; + if (auto v = __dna_docin.enterSubVector("x1b0_orbitScreenBoxHalfExtentY", __x1b0_Count)) { /* x1b0_orbitScreenBoxHalfExtentY[0] */ x1b0_orbitScreenBoxHalfExtentY[0] = __dna_docin.readUint32("x1b0_orbitScreenBoxHalfExtentY"); /* x1b0_orbitScreenBoxHalfExtentY[1] */ x1b0_orbitScreenBoxHalfExtentY[1] = __dna_docin.readUint32("x1b0_orbitScreenBoxHalfExtentY"); - } - /* x1b8_orbitScreenBoxCenterX */ - size_t __x1b8_Count; - if (auto v = __dna_docin.enterSubVector("x1b8_orbitScreenBoxCenterX", __x1b8_Count)) - { + } + /* x1b8_orbitScreenBoxCenterX */ + size_t __x1b8_Count; + if (auto v = __dna_docin.enterSubVector("x1b8_orbitScreenBoxCenterX", __x1b8_Count)) { /* x1b8_orbitScreenBoxCenterX[0] */ x1b8_orbitScreenBoxCenterX[0] = __dna_docin.readUint32("x1b8_orbitScreenBoxCenterX"); /* x1b8_orbitScreenBoxCenterX[1] */ x1b8_orbitScreenBoxCenterX[1] = __dna_docin.readUint32("x1b8_orbitScreenBoxCenterX"); - } - /* x1c0_orbitScreenBoxCenterY */ - size_t __x1c0_Count; - if (auto v = __dna_docin.enterSubVector("x1c0_orbitScreenBoxCenterY", __x1c0_Count)) - { + } + /* x1c0_orbitScreenBoxCenterY */ + size_t __x1c0_Count; + if (auto v = __dna_docin.enterSubVector("x1c0_orbitScreenBoxCenterY", __x1c0_Count)) { /* x1c0_orbitScreenBoxCenterY[0] */ x1c0_orbitScreenBoxCenterY[0] = __dna_docin.readUint32("x1c0_orbitScreenBoxCenterY"); /* x1c0_orbitScreenBoxCenterY[1] */ x1c0_orbitScreenBoxCenterY[1] = __dna_docin.readUint32("x1c0_orbitScreenBoxCenterY"); - } - /* x1c8_orbitZoneIdealX */ - size_t __x1c8_Count; - if (auto v = __dna_docin.enterSubVector("x1c8_orbitZoneIdealX", __x1c8_Count)) - { + } + /* x1c8_orbitZoneIdealX */ + size_t __x1c8_Count; + if (auto v = __dna_docin.enterSubVector("x1c8_orbitZoneIdealX", __x1c8_Count)) { /* x1c8_orbitZoneIdealX[0] */ x1c8_orbitZoneIdealX[0] = __dna_docin.readUint32("x1c8_orbitZoneIdealX"); /* x1c8_orbitZoneIdealX[1] */ x1c8_orbitZoneIdealX[1] = __dna_docin.readUint32("x1c8_orbitZoneIdealX"); - } - /* x1d0_orbitZoneIdealY */ - size_t __x1d0_Count; - if (auto v = __dna_docin.enterSubVector("x1d0_orbitZoneIdealY", __x1d0_Count)) - { + } + /* x1d0_orbitZoneIdealY */ + size_t __x1d0_Count; + if (auto v = __dna_docin.enterSubVector("x1d0_orbitZoneIdealY", __x1d0_Count)) { /* x1d0_orbitZoneIdealY[0] */ x1d0_orbitZoneIdealY[0] = __dna_docin.readUint32("x1d0_orbitZoneIdealY"); /* x1d0_orbitZoneIdealY[1] */ x1d0_orbitZoneIdealY[1] = __dna_docin.readUint32("x1d0_orbitZoneIdealY"); - } - /* x1d8_orbitNearX */ - x1d8_orbitNearX = __dna_docin.readFloat("x1d8_orbitNearX"); - /* x1dc_orbitNearZ */ - x1dc_orbitNearZ = __dna_docin.readFloat("x1dc_orbitNearZ"); - /* x1e0_ */ - x1e0_ = __dna_docin.readFloat("x1e0_"); - /* x1e4_ */ - x1e4_ = __dna_docin.readFloat("x1e4_"); - /* x1e8_orbitFixedOffsetZDiff */ - x1e8_orbitFixedOffsetZDiff = __dna_docin.readFloat("x1e8_orbitFixedOffsetZDiff"); - /* x1ec_orbitZRange */ - x1ec_orbitZRange = __dna_docin.readFloat("x1ec_orbitZRange"); - /* x1f0_ */ - x1f0_ = __dna_docin.readFloat("x1f0_"); - /* x1f4_ */ - x1f4_ = __dna_docin.readFloat("x1f4_"); - /* x1f8_ */ - x1f8_ = __dna_docin.readFloat("x1f8_"); - /* x1fc_orbitPreventionTime */ - x1fc_orbitPreventionTime = __dna_docin.readFloat("x1fc_orbitPreventionTime"); - /* x200_24_dashEnabled */ - x200_24_dashEnabled = __dna_docin.readBool("x200_24_dashEnabled"); - /* x200_25_dashOnButtonRelease */ - x200_25_dashOnButtonRelease = __dna_docin.readBool("x200_25_dashOnButtonRelease"); - /* x204_dashButtonHoldCancelTime */ - x204_dashButtonHoldCancelTime = __dna_docin.readFloat("x204_dashButtonHoldCancelTime"); - /* x208_dashStrafeInputThreshold */ - x208_dashStrafeInputThreshold = __dna_docin.readFloat("x208_dashStrafeInputThreshold"); - /* x20c_sidewaysDoubleJumpImpulse */ - x20c_sidewaysDoubleJumpImpulse = __dna_docin.readFloat("x20c_sidewaysDoubleJumpImpulse"); - /* x210_sidewaysVerticalDoubleJumpAccel */ - x210_sidewaysVerticalDoubleJumpAccel = __dna_docin.readFloat("x210_sidewaysVerticalDoubleJumpAccel"); - /* x214_sidewaysHorizontalDoubleJumpAccel */ - x214_sidewaysHorizontalDoubleJumpAccel = __dna_docin.readFloat("x214_sidewaysHorizontalDoubleJumpAccel"); - /* x218_scanningRange */ - x218_scanningRange = __dna_docin.readFloat("x218_scanningRange"); - /* x21c_24_scanRetention */ - x21c_24_scanRetention = __dna_docin.readBool("x21c_24_scanRetention"); - /* x21c_25_scanFreezesGame */ - x21c_25_scanFreezesGame = __dna_docin.readBool("x21c_25_scanFreezesGame"); - /* x21c_26_orbitWhileScanning */ - x21c_26_orbitWhileScanning = __dna_docin.readBool("x21c_26_orbitWhileScanning"); - /* x220_scanMaxTargetDistance */ - x220_scanMaxTargetDistance = __dna_docin.readFloat("x220_scanMaxTargetDistance"); - /* x224_scanMaxLockDistance */ - x224_scanMaxLockDistance = __dna_docin.readFloat("x224_scanMaxLockDistance"); - /* x2a0_orbitDistanceMax */ - x2a0_orbitDistanceMax = __dna_docin.readFloat("x2a0_orbitDistanceMax"); - /* x2a4_grappleSwingLength */ - x2a4_grappleSwingLength = __dna_docin.readFloat("x2a4_grappleSwingLength"); - /* x2a8_grappleSwingPeriod */ - x2a8_grappleSwingPeriod = __dna_docin.readFloat("x2a8_grappleSwingPeriod"); - /* x2ac_grapplePullSpeedMin */ - x2ac_grapplePullSpeedMin = __dna_docin.readFloat("x2ac_grapplePullSpeedMin"); - /* x2b0_grappleCameraSpeed */ - x2b0_grappleCameraSpeed = __dna_docin.readFloat("x2b0_grappleCameraSpeed"); - /* x2b4_maxGrappleLockedTurnAlignDistance */ - x2b4_maxGrappleLockedTurnAlignDistance = __dna_docin.readFloat("x2b4_maxGrappleLockedTurnAlignDistance"); - /* x2b8_grapplePullSpeedProportion */ - x2b8_grapplePullSpeedProportion = __dna_docin.readFloat("x2b8_grapplePullSpeedProportion"); - /* x2bc_grapplePullSpeedMax */ - x2bc_grapplePullSpeedMax = __dna_docin.readFloat("x2bc_grapplePullSpeedMax"); - /* x2c0_grappleLookCenterSpeed */ - x2c0_grappleLookCenterSpeed = __dna_docin.readFloat("x2c0_grappleLookCenterSpeed"); - /* x2c4_maxGrappleTurnSpeed */ - x2c4_maxGrappleTurnSpeed = __dna_docin.readFloat("x2c4_maxGrappleTurnSpeed"); - /* x2c8_grappleJumpForce */ - x2c8_grappleJumpForce = __dna_docin.readFloat("x2c8_grappleJumpForce"); - /* x2cc_grappleReleaseTime */ - x2cc_grappleReleaseTime = __dna_docin.readFloat("x2cc_grappleReleaseTime"); - /* x2d0_grappleJumpMode */ - x2d0_grappleJumpMode = __dna_docin.readUint32("x2d0_grappleJumpMode"); - /* x2d4_orbitReleaseBreaksGrapple */ - x2d4_orbitReleaseBreaksGrapple = __dna_docin.readBool("x2d4_orbitReleaseBreaksGrapple"); - /* x2d5_invertGrappleTurn */ - x2d5_invertGrappleTurn = __dna_docin.readBool("x2d5_invertGrappleTurn"); - /* x2d8_grappleBeamSpeed */ - x2d8_grappleBeamSpeed = __dna_docin.readFloat("x2d8_grappleBeamSpeed"); - /* x2dc_grappleBeamXWaveAmplitude */ - x2dc_grappleBeamXWaveAmplitude = __dna_docin.readFloat("x2dc_grappleBeamXWaveAmplitude"); - /* x2e0_grappleBeamZWaveAmplitude */ - x2e0_grappleBeamZWaveAmplitude = __dna_docin.readFloat("x2e0_grappleBeamZWaveAmplitude"); - /* x2e4_grappleBeamAnglePhaseDelta */ - x2e4_grappleBeamAnglePhaseDelta = __dna_docin.readFloat("x2e4_grappleBeamAnglePhaseDelta"); - /* x26c_playerHeight */ - x26c_playerHeight = __dna_docin.readFloat("x26c_playerHeight"); - /* x270_playerXYHalfExtent */ - x270_playerXYHalfExtent = __dna_docin.readFloat("x270_playerXYHalfExtent"); - /* x274_stepUpHeight */ - x274_stepUpHeight = __dna_docin.readFloat("x274_stepUpHeight"); - /* x278_stepDownHeight */ - x278_stepDownHeight = __dna_docin.readFloat("x278_stepDownHeight"); - /* x27c_playerBallHalfExtent */ - x27c_playerBallHalfExtent = __dna_docin.readFloat("x27c_playerBallHalfExtent"); - /* x280_ */ - x280_firstPersonCameraSpeed = __dna_docin.readFloat("x280_"); - /* x284_ */ - x284_ = __dna_docin.readFloat("x284_"); - /* x288_jumpCameraPitchDownStart */ - x288_jumpCameraPitchDownStart = __dna_docin.readFloat("x288_jumpCameraPitchDownStart"); - /* x28c_jumpCameraPitchDownFull */ - x28c_jumpCameraPitchDownFull = __dna_docin.readFloat("x28c_jumpCameraPitchDownFull"); - /* x290_jumpCameraPitchDownAngle */ - x290_jumpCameraPitchDownAngle = __dna_docin.readFloat("x290_jumpCameraPitchDownAngle"); - /* x294_fallCameraPitchDownStart */ - x294_fallCameraPitchDownStart = __dna_docin.readFloat("x294_fallCameraPitchDownStart"); - /* x298_fallCameraPitchDownFull */ - x298_fallCameraPitchDownFull = __dna_docin.readFloat("x298_fallCameraPitchDownFull"); - /* x29c_fallCameraPitchDownAngle */ - x29c_fallCameraPitchDownAngle = __dna_docin.readFloat("x29c_fallCameraPitchDownAngle"); - /* x2e8_ */ - x2e8_ = __dna_docin.readFloat("x2e8_"); - /* x2ec_ */ - x2ec_ = __dna_docin.readFloat("x2ec_"); - /* x2f0_ */ - x2f0_ = __dna_docin.readFloat("x2f0_"); - /* x2f4_ */ - x2f4_ = __dna_docin.readBool("x2f4_"); - /* x2f8_frozenTimeout */ - x2f8_frozenTimeout = __dna_docin.readFloat("x2f8_frozenTimeout"); - /* x2fc_iceBreakJumpCount */ - x2fc_iceBreakJumpCount = __dna_docin.readUint32("x2fc_iceBreakJumpCount"); - /* x300_variaDamageReduction */ - x300_variaDamageReduction = __dna_docin.readFloat("x300_variaDamageReduction"); - /* x304_gravityDamageReduction */ - x304_gravityDamageReduction = __dna_docin.readFloat("x304_gravityDamageReduction"); - /* x308_phazonDamageReduction */ - x308_phazonDamageReduction = __dna_docin.readFloat("x308_phazonDamageReduction"); + } + /* x1d8_orbitNearX */ + x1d8_orbitNearX = __dna_docin.readFloat("x1d8_orbitNearX"); + /* x1dc_orbitNearZ */ + x1dc_orbitNearZ = __dna_docin.readFloat("x1dc_orbitNearZ"); + /* x1e0_ */ + x1e0_ = __dna_docin.readFloat("x1e0_"); + /* x1e4_ */ + x1e4_ = __dna_docin.readFloat("x1e4_"); + /* x1e8_orbitFixedOffsetZDiff */ + x1e8_orbitFixedOffsetZDiff = __dna_docin.readFloat("x1e8_orbitFixedOffsetZDiff"); + /* x1ec_orbitZRange */ + x1ec_orbitZRange = __dna_docin.readFloat("x1ec_orbitZRange"); + /* x1f0_ */ + x1f0_ = __dna_docin.readFloat("x1f0_"); + /* x1f4_ */ + x1f4_ = __dna_docin.readFloat("x1f4_"); + /* x1f8_ */ + x1f8_ = __dna_docin.readFloat("x1f8_"); + /* x1fc_orbitPreventionTime */ + x1fc_orbitPreventionTime = __dna_docin.readFloat("x1fc_orbitPreventionTime"); + /* x200_24_dashEnabled */ + x200_24_dashEnabled = __dna_docin.readBool("x200_24_dashEnabled"); + /* x200_25_dashOnButtonRelease */ + x200_25_dashOnButtonRelease = __dna_docin.readBool("x200_25_dashOnButtonRelease"); + /* x204_dashButtonHoldCancelTime */ + x204_dashButtonHoldCancelTime = __dna_docin.readFloat("x204_dashButtonHoldCancelTime"); + /* x208_dashStrafeInputThreshold */ + x208_dashStrafeInputThreshold = __dna_docin.readFloat("x208_dashStrafeInputThreshold"); + /* x20c_sidewaysDoubleJumpImpulse */ + x20c_sidewaysDoubleJumpImpulse = __dna_docin.readFloat("x20c_sidewaysDoubleJumpImpulse"); + /* x210_sidewaysVerticalDoubleJumpAccel */ + x210_sidewaysVerticalDoubleJumpAccel = __dna_docin.readFloat("x210_sidewaysVerticalDoubleJumpAccel"); + /* x214_sidewaysHorizontalDoubleJumpAccel */ + x214_sidewaysHorizontalDoubleJumpAccel = __dna_docin.readFloat("x214_sidewaysHorizontalDoubleJumpAccel"); + /* x218_scanningRange */ + x218_scanningRange = __dna_docin.readFloat("x218_scanningRange"); + /* x21c_24_scanRetention */ + x21c_24_scanRetention = __dna_docin.readBool("x21c_24_scanRetention"); + /* x21c_25_scanFreezesGame */ + x21c_25_scanFreezesGame = __dna_docin.readBool("x21c_25_scanFreezesGame"); + /* x21c_26_orbitWhileScanning */ + x21c_26_orbitWhileScanning = __dna_docin.readBool("x21c_26_orbitWhileScanning"); + /* x220_scanMaxTargetDistance */ + x220_scanMaxTargetDistance = __dna_docin.readFloat("x220_scanMaxTargetDistance"); + /* x224_scanMaxLockDistance */ + x224_scanMaxLockDistance = __dna_docin.readFloat("x224_scanMaxLockDistance"); + /* x2a0_orbitDistanceMax */ + x2a0_orbitDistanceMax = __dna_docin.readFloat("x2a0_orbitDistanceMax"); + /* x2a4_grappleSwingLength */ + x2a4_grappleSwingLength = __dna_docin.readFloat("x2a4_grappleSwingLength"); + /* x2a8_grappleSwingPeriod */ + x2a8_grappleSwingPeriod = __dna_docin.readFloat("x2a8_grappleSwingPeriod"); + /* x2ac_grapplePullSpeedMin */ + x2ac_grapplePullSpeedMin = __dna_docin.readFloat("x2ac_grapplePullSpeedMin"); + /* x2b0_grappleCameraSpeed */ + x2b0_grappleCameraSpeed = __dna_docin.readFloat("x2b0_grappleCameraSpeed"); + /* x2b4_maxGrappleLockedTurnAlignDistance */ + x2b4_maxGrappleLockedTurnAlignDistance = __dna_docin.readFloat("x2b4_maxGrappleLockedTurnAlignDistance"); + /* x2b8_grapplePullSpeedProportion */ + x2b8_grapplePullSpeedProportion = __dna_docin.readFloat("x2b8_grapplePullSpeedProportion"); + /* x2bc_grapplePullSpeedMax */ + x2bc_grapplePullSpeedMax = __dna_docin.readFloat("x2bc_grapplePullSpeedMax"); + /* x2c0_grappleLookCenterSpeed */ + x2c0_grappleLookCenterSpeed = __dna_docin.readFloat("x2c0_grappleLookCenterSpeed"); + /* x2c4_maxGrappleTurnSpeed */ + x2c4_maxGrappleTurnSpeed = __dna_docin.readFloat("x2c4_maxGrappleTurnSpeed"); + /* x2c8_grappleJumpForce */ + x2c8_grappleJumpForce = __dna_docin.readFloat("x2c8_grappleJumpForce"); + /* x2cc_grappleReleaseTime */ + x2cc_grappleReleaseTime = __dna_docin.readFloat("x2cc_grappleReleaseTime"); + /* x2d0_grappleJumpMode */ + x2d0_grappleJumpMode = __dna_docin.readUint32("x2d0_grappleJumpMode"); + /* x2d4_orbitReleaseBreaksGrapple */ + x2d4_orbitReleaseBreaksGrapple = __dna_docin.readBool("x2d4_orbitReleaseBreaksGrapple"); + /* x2d5_invertGrappleTurn */ + x2d5_invertGrappleTurn = __dna_docin.readBool("x2d5_invertGrappleTurn"); + /* x2d8_grappleBeamSpeed */ + x2d8_grappleBeamSpeed = __dna_docin.readFloat("x2d8_grappleBeamSpeed"); + /* x2dc_grappleBeamXWaveAmplitude */ + x2dc_grappleBeamXWaveAmplitude = __dna_docin.readFloat("x2dc_grappleBeamXWaveAmplitude"); + /* x2e0_grappleBeamZWaveAmplitude */ + x2e0_grappleBeamZWaveAmplitude = __dna_docin.readFloat("x2e0_grappleBeamZWaveAmplitude"); + /* x2e4_grappleBeamAnglePhaseDelta */ + x2e4_grappleBeamAnglePhaseDelta = __dna_docin.readFloat("x2e4_grappleBeamAnglePhaseDelta"); + /* x26c_playerHeight */ + x26c_playerHeight = __dna_docin.readFloat("x26c_playerHeight"); + /* x270_playerXYHalfExtent */ + x270_playerXYHalfExtent = __dna_docin.readFloat("x270_playerXYHalfExtent"); + /* x274_stepUpHeight */ + x274_stepUpHeight = __dna_docin.readFloat("x274_stepUpHeight"); + /* x278_stepDownHeight */ + x278_stepDownHeight = __dna_docin.readFloat("x278_stepDownHeight"); + /* x27c_playerBallHalfExtent */ + x27c_playerBallHalfExtent = __dna_docin.readFloat("x27c_playerBallHalfExtent"); + /* x280_ */ + x280_firstPersonCameraSpeed = __dna_docin.readFloat("x280_"); + /* x284_ */ + x284_ = __dna_docin.readFloat("x284_"); + /* x288_jumpCameraPitchDownStart */ + x288_jumpCameraPitchDownStart = __dna_docin.readFloat("x288_jumpCameraPitchDownStart"); + /* x28c_jumpCameraPitchDownFull */ + x28c_jumpCameraPitchDownFull = __dna_docin.readFloat("x28c_jumpCameraPitchDownFull"); + /* x290_jumpCameraPitchDownAngle */ + x290_jumpCameraPitchDownAngle = __dna_docin.readFloat("x290_jumpCameraPitchDownAngle"); + /* x294_fallCameraPitchDownStart */ + x294_fallCameraPitchDownStart = __dna_docin.readFloat("x294_fallCameraPitchDownStart"); + /* x298_fallCameraPitchDownFull */ + x298_fallCameraPitchDownFull = __dna_docin.readFloat("x298_fallCameraPitchDownFull"); + /* x29c_fallCameraPitchDownAngle */ + x29c_fallCameraPitchDownAngle = __dna_docin.readFloat("x29c_fallCameraPitchDownAngle"); + /* x2e8_ */ + x2e8_ = __dna_docin.readFloat("x2e8_"); + /* x2ec_ */ + x2ec_ = __dna_docin.readFloat("x2ec_"); + /* x2f0_ */ + x2f0_ = __dna_docin.readFloat("x2f0_"); + /* x2f4_ */ + x2f4_ = __dna_docin.readBool("x2f4_"); + /* x2f8_frozenTimeout */ + x2f8_frozenTimeout = __dna_docin.readFloat("x2f8_frozenTimeout"); + /* x2fc_iceBreakJumpCount */ + x2fc_iceBreakJumpCount = __dna_docin.readUint32("x2fc_iceBreakJumpCount"); + /* x300_variaDamageReduction */ + x300_variaDamageReduction = __dna_docin.readFloat("x300_variaDamageReduction"); + /* x304_gravityDamageReduction */ + x304_gravityDamageReduction = __dna_docin.readFloat("x304_gravityDamageReduction"); + /* x308_phazonDamageReduction */ + x308_phazonDamageReduction = __dna_docin.readFloat("x308_phazonDamageReduction"); } template <> -void CTweakPlayer::Enumerate(athena::io::YAMLDocWriter& __dna_docout) -{ - /* x4_maxTranslationalAcceleration */ - if (auto v = __dna_docout.enterSubVector("x4_maxTranslationalAcceleration")) - { +void CTweakPlayer::Enumerate(athena::io::YAMLDocWriter& __dna_docout) { + /* x4_maxTranslationalAcceleration */ + if (auto v = __dna_docout.enterSubVector("x4_maxTranslationalAcceleration")) { /* x4_maxTranslationalAcceleration[0] */ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[0]); /* x4_maxTranslationalAcceleration[1] */ @@ -1424,10 +1403,9 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocWriter& __dna __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[6]); /* x4_maxTranslationalAcceleration[7] */ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[7]); - } - /* x24_maxRotationalAcceleration */ - if (auto v = __dna_docout.enterSubVector("x24_maxRotationalAcceleration")) - { + } + /* x24_maxRotationalAcceleration */ + if (auto v = __dna_docout.enterSubVector("x24_maxRotationalAcceleration")) { /* x24_maxRotationalAcceleration[0] */ __dna_docout.writeFloat("x24_maxRotationalAcceleration", x24_maxRotationalAcceleration[0]); /* x24_maxRotationalAcceleration[1] */ @@ -1444,10 +1422,9 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocWriter& __dna __dna_docout.writeFloat("x24_maxRotationalAcceleration", x24_maxRotationalAcceleration[6]); /* x24_maxRotationalAcceleration[7] */ __dna_docout.writeFloat("x24_maxRotationalAcceleration", x24_maxRotationalAcceleration[7]); - } - /* x44_translationFriction */ - if (auto v = __dna_docout.enterSubVector("x44_translationFriction")) - { + } + /* x44_translationFriction */ + if (auto v = __dna_docout.enterSubVector("x44_translationFriction")) { /* x44_translationFriction[0] */ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[0]); /* x44_translationFriction[1] */ @@ -1464,10 +1441,9 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocWriter& __dna __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[6]); /* x44_translationFriction[7] */ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[7]); - } - /* x64_rotationFriction */ - if (auto v = __dna_docout.enterSubVector("x64_rotationFriction")) - { + } + /* x64_rotationFriction */ + if (auto v = __dna_docout.enterSubVector("x64_rotationFriction")) { /* x64_rotationFriction[0] */ __dna_docout.writeFloat("x64_rotationFriction", x64_rotationFriction[0]); /* x64_rotationFriction[1] */ @@ -1484,10 +1460,9 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocWriter& __dna __dna_docout.writeFloat("x64_rotationFriction", x64_rotationFriction[6]); /* x64_rotationFriction[7] */ __dna_docout.writeFloat("x64_rotationFriction", x64_rotationFriction[7]); - } - /* x84_rotationMaxSpeed */ - if (auto v = __dna_docout.enterSubVector("x84_rotationMaxSpeed")) - { + } + /* x84_rotationMaxSpeed */ + if (auto v = __dna_docout.enterSubVector("x84_rotationMaxSpeed")) { /* x84_rotationMaxSpeed[0] */ __dna_docout.writeFloat("x84_rotationMaxSpeed", x84_rotationMaxSpeed[0]); /* x84_rotationMaxSpeed[1] */ @@ -1504,10 +1479,9 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocWriter& __dna __dna_docout.writeFloat("x84_rotationMaxSpeed", x84_rotationMaxSpeed[6]); /* x84_rotationMaxSpeed[7] */ __dna_docout.writeFloat("x84_rotationMaxSpeed", x84_rotationMaxSpeed[7]); - } - /* xa4_translationMaxSpeed */ - if (auto v = __dna_docout.enterSubVector("xa4_translationMaxSpeed")) - { + } + /* xa4_translationMaxSpeed */ + if (auto v = __dna_docout.enterSubVector("xa4_translationMaxSpeed")) { /* xa4_translationMaxSpeed[0] */ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[0]); /* xa4_translationMaxSpeed[1] */ @@ -1524,425 +1498,411 @@ void CTweakPlayer::Enumerate(athena::io::YAMLDocWriter& __dna __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[6]); /* xa4_translationMaxSpeed[7] */ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[7]); - } - /* xc4_normalGravAccel */ - __dna_docout.writeFloat("xc4_normalGravAccel", xc4_normalGravAccel); - /* xc8_fluidGravAccel */ - __dna_docout.writeFloat("xc8_fluidGravAccel", xc8_fluidGravAccel); - /* xcc_verticalJumpAccel */ - __dna_docout.writeFloat("xcc_verticalJumpAccel", xcc_verticalJumpAccel); - /* xd0_horizontalJumpAccel */ - __dna_docout.writeFloat("xd0_horizontalJumpAccel", xd0_horizontalJumpAccel); - /* xd4_verticalDoubleJumpAccel */ - __dna_docout.writeFloat("xd4_verticalDoubleJumpAccel", xd4_verticalDoubleJumpAccel); - /* xd8_horizontalDoubleJumpAccel */ - __dna_docout.writeFloat("xd8_horizontalDoubleJumpAccel", xd8_horizontalDoubleJumpAccel); - /* xdc_waterJumpFactor */ - __dna_docout.writeFloat("xdc_waterJumpFactor", xdc_waterJumpFactor); - /* xe0_waterBallJumpFactor */ - __dna_docout.writeFloat("xe0_waterBallJumpFactor", xe0_waterBallJumpFactor); - /* xe4_lavaJumpFactor */ - __dna_docout.writeFloat("xe4_lavaJumpFactor", xe4_lavaJumpFactor); - /* xe8_lavaBallJumpFactor */ - __dna_docout.writeFloat("xe8_lavaBallJumpFactor", xe8_lavaBallJumpFactor); - /* xec_phazonJumpFactor */ - __dna_docout.writeFloat("xec_phazonJumpFactor", xec_phazonJumpFactor); - /* xf0_phazonBallJumpFactor */ - __dna_docout.writeFloat("xf0_phazonBallJumpFactor", xf0_phazonBallJumpFactor); - /* xf4_allowedJumpTime */ - __dna_docout.writeFloat("xf4_allowedJumpTime", xf4_allowedJumpTime); - /* xf8_allowedDoubleJumpTime */ - __dna_docout.writeFloat("xf8_allowedDoubleJumpTime", xf8_allowedDoubleJumpTime); - /* xfc_minDoubleJumpWindow */ - __dna_docout.writeFloat("xfc_minDoubleJumpWindow", xfc_minDoubleJumpWindow); - /* x100_maxDoubleJumpWindow */ - __dna_docout.writeFloat("x100_maxDoubleJumpWindow", x100_maxDoubleJumpWindow); - /* x104_ */ - __dna_docout.writeFloat("x104_", x104_); - /* x108_minJumpTime */ - __dna_docout.writeFloat("x108_minJumpTime", x108_minJumpTime); - /* x10c_minDoubleJumpTime */ - __dna_docout.writeFloat("x10c_minDoubleJumpTime", x10c_minDoubleJumpTime); - /* x110_allowedLedgeTime */ - __dna_docout.writeFloat("x110_allowedLedgeTime", x110_allowedLedgeTime); - /* x114_doubleJumpImpulse */ - __dna_docout.writeFloat("x114_doubleJumpImpulse", x114_doubleJumpImpulse); - /* x118_backwardsForceMultiplier */ - __dna_docout.writeFloat("x118_backwardsForceMultiplier", x118_backwardsForceMultiplier); - /* x11c_bombJumpRadius */ - __dna_docout.writeFloat("x11c_bombJumpRadius", x11c_bombJumpRadius); - /* x120_bombJumpHeight */ - __dna_docout.writeFloat("x120_bombJumpHeight", x120_bombJumpHeight); - /* x124_eyeOffset */ - __dna_docout.writeFloat("x124_eyeOffset", x124_eyeOffset); - /* x128_turnSpeedMultiplier */ - __dna_docout.writeFloat("x128_turnSpeedMultiplier", x128_turnSpeedMultiplier); - /* x12c_freeLookTurnSpeedMultiplier */ - __dna_docout.writeFloat("x12c_freeLookTurnSpeedMultiplier", x12c_freeLookTurnSpeedMultiplier); - /* x130_horizontalFreeLookAngleVel */ - __dna_docout.writeFloat("x130_horizontalFreeLookAngleVel", x130_horizontalFreeLookAngleVel); - /* x134_verticalFreeLookAngleVel */ - __dna_docout.writeFloat("x134_verticalFreeLookAngleVel", x134_verticalFreeLookAngleVel); - /* x138_freeLookSpeed */ - __dna_docout.writeFloat("x138_freeLookSpeed", x138_freeLookSpeed); - /* x13c_freeLookSnapSpeed */ - __dna_docout.writeFloat("x13c_freeLookSnapSpeed", x13c_freeLookSnapSpeed); - /* x140_ */ - __dna_docout.writeFloat("x140_", x140_); - /* x144_freeLookCenteredThresholdAngle */ - __dna_docout.writeFloat("x144_freeLookCenteredThresholdAngle", x144_freeLookCenteredThresholdAngle); - /* x148_freeLookCenteredTime */ - __dna_docout.writeFloat("x148_freeLookCenteredTime", x148_freeLookCenteredTime); - /* x14c_freeLookDampenFactor */ - __dna_docout.writeFloat("x14c_freeLookDampenFactor", x14c_freeLookDampenFactor); - /* x150_leftDiv */ - __dna_docout.writeFloat("x150_leftDiv", x150_leftDiv); - /* x154_rightDiv */ - __dna_docout.writeFloat("x154_rightDiv", x154_rightDiv); - /* x228_24_freelookTurnsPlayer */ - __dna_docout.writeBool("x228_24_freelookTurnsPlayer", x228_24_freelookTurnsPlayer); - /* x228_25_ */ - __dna_docout.writeBool("x228_25_", x228_25_); - /* x228_26_ */ - __dna_docout.writeBool("x228_26_", x228_26_); - /* x228_27_moveDuringFreeLook */ - __dna_docout.writeBool("x228_27_moveDuringFreeLook", x228_27_moveDuringFreeLook); - /* x228_28_holdButtonsForFreeLook */ - __dna_docout.writeBool("x228_28_holdButtonsForFreeLook", x228_28_holdButtonsForFreeLook); - /* x228_29_twoButtonsForFreeLook */ - __dna_docout.writeBool("x228_29_twoButtonsForFreeLook", x228_29_twoButtonsForFreeLook); - /* x228_30_ */ - __dna_docout.writeBool("x228_30_", x228_30_); - /* x228_31_ */ - __dna_docout.writeBool("x228_31_", x228_31_); - /* x229_24_ */ - __dna_docout.writeBool("x229_24_", x229_24_); - /* x229_25_aimWhenOrbitingPoint */ - __dna_docout.writeBool("x229_25_aimWhenOrbitingPoint", x229_25_aimWhenOrbitingPoint); - /* x229_26_stayInFreeLookWhileFiring */ - __dna_docout.writeBool("x229_26_stayInFreeLookWhileFiring", x229_26_stayInFreeLookWhileFiring); - /* x229_27_ */ - __dna_docout.writeBool("x229_27_", x229_27_); - /* x229_28_ */ - __dna_docout.writeBool("x229_28_", x229_28_); - /* x229_29_orbitFixedOffset */ - __dna_docout.writeBool("x229_29_orbitFixedOffset", x229_29_orbitFixedOffset); - /* x229_30_gunButtonTogglesHolster */ - __dna_docout.writeBool("x229_30_gunButtonTogglesHolster", x229_30_gunButtonTogglesHolster); - /* x229_31_gunNotFiringHolstersGun */ - __dna_docout.writeBool("x229_31_gunNotFiringHolstersGun", x229_31_gunNotFiringHolstersGun); - /* x22a_24_fallingDoubleJump */ - __dna_docout.writeBool("x22a_24_fallingDoubleJump", x22a_24_fallingDoubleJump); - /* x22a_25_impulseDoubleJump */ - __dna_docout.writeBool("x22a_25_impulseDoubleJump", x22a_25_impulseDoubleJump); - /* x22a_26_firingCancelsCameraPitch */ - __dna_docout.writeBool("x22a_26_firingCancelsCameraPitch", x22a_26_firingCancelsCameraPitch); - /* x22a_27_assistedAimingIgnoreHorizontal */ - __dna_docout.writeBool("x22a_27_assistedAimingIgnoreHorizontal", x22a_27_assistedAimingIgnoreHorizontal); - /* x22a_28_assistedAimingIgnoreVertical */ - __dna_docout.writeBool("x22a_28_assistedAimingIgnoreVertical", x22a_28_assistedAimingIgnoreVertical); - /* x22c_ */ - __dna_docout.writeFloat("x22c_", x22c_); - /* x230_ */ - __dna_docout.writeFloat("x230_", x230_); - /* x234_aimMaxDistance */ - __dna_docout.writeFloat("x234_aimMaxDistance", x234_aimMaxDistance); - /* x238_ */ - __dna_docout.writeFloat("x238_", x238_); - /* x23c_ */ - __dna_docout.writeFloat("x23c_", x23c_); - /* x240_ */ - __dna_docout.writeFloat("x240_", x240_); - /* x244_ */ - __dna_docout.writeFloat("x244_", x244_); - /* x248_ */ - __dna_docout.writeFloat("x248_", x248_); - /* x24c_aimThresholdDistance */ - __dna_docout.writeFloat("x24c_aimThresholdDistance", x24c_aimThresholdDistance); - /* x250_ */ - __dna_docout.writeFloat("x250_", x250_); - /* x254_ */ - __dna_docout.writeFloat("x254_", x254_); - /* x258_aimBoxWidth */ - __dna_docout.writeFloat("x258_aimBoxWidth", x258_aimBoxWidth); - /* x25c_aimBoxHeight */ - __dna_docout.writeFloat("x25c_aimBoxHeight", x25c_aimBoxHeight); - /* x260_aimTargetTimer */ - __dna_docout.writeFloat("x260_aimTargetTimer", x260_aimTargetTimer); - /* x264_aimAssistHorizontalAngle */ - __dna_docout.writeFloat("x264_aimAssistHorizontalAngle", x264_aimAssistHorizontalAngle); - /* x268_aimAssistVerticalAngle */ - __dna_docout.writeFloat("x268_aimAssistVerticalAngle", x268_aimAssistVerticalAngle); - /* x158_orbitMinDistance */ - if (auto v = __dna_docout.enterSubVector("x158_orbitMinDistance")) - { + } + /* xc4_normalGravAccel */ + __dna_docout.writeFloat("xc4_normalGravAccel", xc4_normalGravAccel); + /* xc8_fluidGravAccel */ + __dna_docout.writeFloat("xc8_fluidGravAccel", xc8_fluidGravAccel); + /* xcc_verticalJumpAccel */ + __dna_docout.writeFloat("xcc_verticalJumpAccel", xcc_verticalJumpAccel); + /* xd0_horizontalJumpAccel */ + __dna_docout.writeFloat("xd0_horizontalJumpAccel", xd0_horizontalJumpAccel); + /* xd4_verticalDoubleJumpAccel */ + __dna_docout.writeFloat("xd4_verticalDoubleJumpAccel", xd4_verticalDoubleJumpAccel); + /* xd8_horizontalDoubleJumpAccel */ + __dna_docout.writeFloat("xd8_horizontalDoubleJumpAccel", xd8_horizontalDoubleJumpAccel); + /* xdc_waterJumpFactor */ + __dna_docout.writeFloat("xdc_waterJumpFactor", xdc_waterJumpFactor); + /* xe0_waterBallJumpFactor */ + __dna_docout.writeFloat("xe0_waterBallJumpFactor", xe0_waterBallJumpFactor); + /* xe4_lavaJumpFactor */ + __dna_docout.writeFloat("xe4_lavaJumpFactor", xe4_lavaJumpFactor); + /* xe8_lavaBallJumpFactor */ + __dna_docout.writeFloat("xe8_lavaBallJumpFactor", xe8_lavaBallJumpFactor); + /* xec_phazonJumpFactor */ + __dna_docout.writeFloat("xec_phazonJumpFactor", xec_phazonJumpFactor); + /* xf0_phazonBallJumpFactor */ + __dna_docout.writeFloat("xf0_phazonBallJumpFactor", xf0_phazonBallJumpFactor); + /* xf4_allowedJumpTime */ + __dna_docout.writeFloat("xf4_allowedJumpTime", xf4_allowedJumpTime); + /* xf8_allowedDoubleJumpTime */ + __dna_docout.writeFloat("xf8_allowedDoubleJumpTime", xf8_allowedDoubleJumpTime); + /* xfc_minDoubleJumpWindow */ + __dna_docout.writeFloat("xfc_minDoubleJumpWindow", xfc_minDoubleJumpWindow); + /* x100_maxDoubleJumpWindow */ + __dna_docout.writeFloat("x100_maxDoubleJumpWindow", x100_maxDoubleJumpWindow); + /* x104_ */ + __dna_docout.writeFloat("x104_", x104_); + /* x108_minJumpTime */ + __dna_docout.writeFloat("x108_minJumpTime", x108_minJumpTime); + /* x10c_minDoubleJumpTime */ + __dna_docout.writeFloat("x10c_minDoubleJumpTime", x10c_minDoubleJumpTime); + /* x110_allowedLedgeTime */ + __dna_docout.writeFloat("x110_allowedLedgeTime", x110_allowedLedgeTime); + /* x114_doubleJumpImpulse */ + __dna_docout.writeFloat("x114_doubleJumpImpulse", x114_doubleJumpImpulse); + /* x118_backwardsForceMultiplier */ + __dna_docout.writeFloat("x118_backwardsForceMultiplier", x118_backwardsForceMultiplier); + /* x11c_bombJumpRadius */ + __dna_docout.writeFloat("x11c_bombJumpRadius", x11c_bombJumpRadius); + /* x120_bombJumpHeight */ + __dna_docout.writeFloat("x120_bombJumpHeight", x120_bombJumpHeight); + /* x124_eyeOffset */ + __dna_docout.writeFloat("x124_eyeOffset", x124_eyeOffset); + /* x128_turnSpeedMultiplier */ + __dna_docout.writeFloat("x128_turnSpeedMultiplier", x128_turnSpeedMultiplier); + /* x12c_freeLookTurnSpeedMultiplier */ + __dna_docout.writeFloat("x12c_freeLookTurnSpeedMultiplier", x12c_freeLookTurnSpeedMultiplier); + /* x130_horizontalFreeLookAngleVel */ + __dna_docout.writeFloat("x130_horizontalFreeLookAngleVel", x130_horizontalFreeLookAngleVel); + /* x134_verticalFreeLookAngleVel */ + __dna_docout.writeFloat("x134_verticalFreeLookAngleVel", x134_verticalFreeLookAngleVel); + /* x138_freeLookSpeed */ + __dna_docout.writeFloat("x138_freeLookSpeed", x138_freeLookSpeed); + /* x13c_freeLookSnapSpeed */ + __dna_docout.writeFloat("x13c_freeLookSnapSpeed", x13c_freeLookSnapSpeed); + /* x140_ */ + __dna_docout.writeFloat("x140_", x140_); + /* x144_freeLookCenteredThresholdAngle */ + __dna_docout.writeFloat("x144_freeLookCenteredThresholdAngle", x144_freeLookCenteredThresholdAngle); + /* x148_freeLookCenteredTime */ + __dna_docout.writeFloat("x148_freeLookCenteredTime", x148_freeLookCenteredTime); + /* x14c_freeLookDampenFactor */ + __dna_docout.writeFloat("x14c_freeLookDampenFactor", x14c_freeLookDampenFactor); + /* x150_leftDiv */ + __dna_docout.writeFloat("x150_leftDiv", x150_leftDiv); + /* x154_rightDiv */ + __dna_docout.writeFloat("x154_rightDiv", x154_rightDiv); + /* x228_24_freelookTurnsPlayer */ + __dna_docout.writeBool("x228_24_freelookTurnsPlayer", x228_24_freelookTurnsPlayer); + /* x228_25_ */ + __dna_docout.writeBool("x228_25_", x228_25_); + /* x228_26_ */ + __dna_docout.writeBool("x228_26_", x228_26_); + /* x228_27_moveDuringFreeLook */ + __dna_docout.writeBool("x228_27_moveDuringFreeLook", x228_27_moveDuringFreeLook); + /* x228_28_holdButtonsForFreeLook */ + __dna_docout.writeBool("x228_28_holdButtonsForFreeLook", x228_28_holdButtonsForFreeLook); + /* x228_29_twoButtonsForFreeLook */ + __dna_docout.writeBool("x228_29_twoButtonsForFreeLook", x228_29_twoButtonsForFreeLook); + /* x228_30_ */ + __dna_docout.writeBool("x228_30_", x228_30_); + /* x228_31_ */ + __dna_docout.writeBool("x228_31_", x228_31_); + /* x229_24_ */ + __dna_docout.writeBool("x229_24_", x229_24_); + /* x229_25_aimWhenOrbitingPoint */ + __dna_docout.writeBool("x229_25_aimWhenOrbitingPoint", x229_25_aimWhenOrbitingPoint); + /* x229_26_stayInFreeLookWhileFiring */ + __dna_docout.writeBool("x229_26_stayInFreeLookWhileFiring", x229_26_stayInFreeLookWhileFiring); + /* x229_27_ */ + __dna_docout.writeBool("x229_27_", x229_27_); + /* x229_28_ */ + __dna_docout.writeBool("x229_28_", x229_28_); + /* x229_29_orbitFixedOffset */ + __dna_docout.writeBool("x229_29_orbitFixedOffset", x229_29_orbitFixedOffset); + /* x229_30_gunButtonTogglesHolster */ + __dna_docout.writeBool("x229_30_gunButtonTogglesHolster", x229_30_gunButtonTogglesHolster); + /* x229_31_gunNotFiringHolstersGun */ + __dna_docout.writeBool("x229_31_gunNotFiringHolstersGun", x229_31_gunNotFiringHolstersGun); + /* x22a_24_fallingDoubleJump */ + __dna_docout.writeBool("x22a_24_fallingDoubleJump", x22a_24_fallingDoubleJump); + /* x22a_25_impulseDoubleJump */ + __dna_docout.writeBool("x22a_25_impulseDoubleJump", x22a_25_impulseDoubleJump); + /* x22a_26_firingCancelsCameraPitch */ + __dna_docout.writeBool("x22a_26_firingCancelsCameraPitch", x22a_26_firingCancelsCameraPitch); + /* x22a_27_assistedAimingIgnoreHorizontal */ + __dna_docout.writeBool("x22a_27_assistedAimingIgnoreHorizontal", x22a_27_assistedAimingIgnoreHorizontal); + /* x22a_28_assistedAimingIgnoreVertical */ + __dna_docout.writeBool("x22a_28_assistedAimingIgnoreVertical", x22a_28_assistedAimingIgnoreVertical); + /* x22c_ */ + __dna_docout.writeFloat("x22c_", x22c_); + /* x230_ */ + __dna_docout.writeFloat("x230_", x230_); + /* x234_aimMaxDistance */ + __dna_docout.writeFloat("x234_aimMaxDistance", x234_aimMaxDistance); + /* x238_ */ + __dna_docout.writeFloat("x238_", x238_); + /* x23c_ */ + __dna_docout.writeFloat("x23c_", x23c_); + /* x240_ */ + __dna_docout.writeFloat("x240_", x240_); + /* x244_ */ + __dna_docout.writeFloat("x244_", x244_); + /* x248_ */ + __dna_docout.writeFloat("x248_", x248_); + /* x24c_aimThresholdDistance */ + __dna_docout.writeFloat("x24c_aimThresholdDistance", x24c_aimThresholdDistance); + /* x250_ */ + __dna_docout.writeFloat("x250_", x250_); + /* x254_ */ + __dna_docout.writeFloat("x254_", x254_); + /* x258_aimBoxWidth */ + __dna_docout.writeFloat("x258_aimBoxWidth", x258_aimBoxWidth); + /* x25c_aimBoxHeight */ + __dna_docout.writeFloat("x25c_aimBoxHeight", x25c_aimBoxHeight); + /* x260_aimTargetTimer */ + __dna_docout.writeFloat("x260_aimTargetTimer", x260_aimTargetTimer); + /* x264_aimAssistHorizontalAngle */ + __dna_docout.writeFloat("x264_aimAssistHorizontalAngle", x264_aimAssistHorizontalAngle); + /* x268_aimAssistVerticalAngle */ + __dna_docout.writeFloat("x268_aimAssistVerticalAngle", x268_aimAssistVerticalAngle); + /* x158_orbitMinDistance */ + if (auto v = __dna_docout.enterSubVector("x158_orbitMinDistance")) { /* x158_orbitMinDistance[0] */ __dna_docout.writeFloat("x158_orbitMinDistance", x158_orbitMinDistance[0]); /* x158_orbitMinDistance[1] */ __dna_docout.writeFloat("x158_orbitMinDistance", x158_orbitMinDistance[1]); /* x158_orbitMinDistance[2] */ __dna_docout.writeFloat("x158_orbitMinDistance", x158_orbitMinDistance[2]); - } - /* x164_orbitNormalDistance */ - if (auto v = __dna_docout.enterSubVector("x164_orbitNormalDistance")) - { + } + /* x164_orbitNormalDistance */ + if (auto v = __dna_docout.enterSubVector("x164_orbitNormalDistance")) { /* x164_orbitNormalDistance[0] */ __dna_docout.writeFloat("x164_orbitNormalDistance", x164_orbitNormalDistance[0]); /* x164_orbitNormalDistance[1] */ __dna_docout.writeFloat("x164_orbitNormalDistance", x164_orbitNormalDistance[1]); /* x164_orbitNormalDistance[2] */ __dna_docout.writeFloat("x164_orbitNormalDistance", x164_orbitNormalDistance[2]); - } - /* x170_orbitMaxDistance */ - if (auto v = __dna_docout.enterSubVector("x170_orbitMaxDistance")) - { + } + /* x170_orbitMaxDistance */ + if (auto v = __dna_docout.enterSubVector("x170_orbitMaxDistance")) { /* x170_orbitMaxDistance[0] */ __dna_docout.writeFloat("x170_orbitMaxDistance", x170_orbitMaxDistance[0]); /* x170_orbitMaxDistance[1] */ __dna_docout.writeFloat("x170_orbitMaxDistance", x170_orbitMaxDistance[1]); /* x170_orbitMaxDistance[2] */ __dna_docout.writeFloat("x170_orbitMaxDistance", x170_orbitMaxDistance[2]); - } - /* x17c_ */ - __dna_docout.writeFloat("x17c_", x17c_); - /* x180_orbitModeTimer */ - __dna_docout.writeFloat("x180_orbitModeTimer", x180_orbitModeTimer); - /* x184_orbitCameraSpeed */ - __dna_docout.writeFloat("x184_orbitCameraSpeed", x184_orbitCameraSpeed); - /* x188_orbitUpperAngle */ - __dna_docout.writeFloat("x188_orbitUpperAngle", x188_orbitUpperAngle); - /* x18c_orbitLowerAngle */ - __dna_docout.writeFloat("x18c_orbitLowerAngle", x18c_orbitLowerAngle); - /* x190_orbitHorizAngle */ - __dna_docout.writeFloat("x190_orbitHorizAngle", x190_orbitHorizAngle); - /* x194_ */ - __dna_docout.writeFloat("x194_", x194_); - /* x198_ */ - __dna_docout.writeFloat("x198_", x198_); - /* x19c_orbitMaxTargetDistance */ - __dna_docout.writeFloat("x19c_orbitMaxTargetDistance", x19c_orbitMaxTargetDistance); - /* x1a0_orbitMaxLockDistance */ - __dna_docout.writeFloat("x1a0_orbitMaxLockDistance", x1a0_orbitMaxLockDistance); - /* x1a4_orbitDistanceThreshold */ - __dna_docout.writeFloat("x1a4_orbitDistanceThreshold", x1a4_orbitDistanceThreshold); - /* x1a8_orbitScreenBoxHalfExtentX */ - if (auto v = __dna_docout.enterSubVector("x1a8_orbitScreenBoxHalfExtentX")) - { + } + /* x17c_ */ + __dna_docout.writeFloat("x17c_", x17c_); + /* x180_orbitModeTimer */ + __dna_docout.writeFloat("x180_orbitModeTimer", x180_orbitModeTimer); + /* x184_orbitCameraSpeed */ + __dna_docout.writeFloat("x184_orbitCameraSpeed", x184_orbitCameraSpeed); + /* x188_orbitUpperAngle */ + __dna_docout.writeFloat("x188_orbitUpperAngle", x188_orbitUpperAngle); + /* x18c_orbitLowerAngle */ + __dna_docout.writeFloat("x18c_orbitLowerAngle", x18c_orbitLowerAngle); + /* x190_orbitHorizAngle */ + __dna_docout.writeFloat("x190_orbitHorizAngle", x190_orbitHorizAngle); + /* x194_ */ + __dna_docout.writeFloat("x194_", x194_); + /* x198_ */ + __dna_docout.writeFloat("x198_", x198_); + /* x19c_orbitMaxTargetDistance */ + __dna_docout.writeFloat("x19c_orbitMaxTargetDistance", x19c_orbitMaxTargetDistance); + /* x1a0_orbitMaxLockDistance */ + __dna_docout.writeFloat("x1a0_orbitMaxLockDistance", x1a0_orbitMaxLockDistance); + /* x1a4_orbitDistanceThreshold */ + __dna_docout.writeFloat("x1a4_orbitDistanceThreshold", x1a4_orbitDistanceThreshold); + /* x1a8_orbitScreenBoxHalfExtentX */ + if (auto v = __dna_docout.enterSubVector("x1a8_orbitScreenBoxHalfExtentX")) { /* x1a8_orbitScreenBoxHalfExtentX[0] */ __dna_docout.writeUint32("x1a8_orbitScreenBoxHalfExtentX", x1a8_orbitScreenBoxHalfExtentX[0]); /* x1a8_orbitScreenBoxHalfExtentX[1] */ __dna_docout.writeUint32("x1a8_orbitScreenBoxHalfExtentX", x1a8_orbitScreenBoxHalfExtentX[1]); - } - /* x1b0_orbitScreenBoxHalfExtentY */ - if (auto v = __dna_docout.enterSubVector("x1b0_orbitScreenBoxHalfExtentY")) - { + } + /* x1b0_orbitScreenBoxHalfExtentY */ + if (auto v = __dna_docout.enterSubVector("x1b0_orbitScreenBoxHalfExtentY")) { /* x1b0_orbitScreenBoxHalfExtentY[0] */ __dna_docout.writeUint32("x1b0_orbitScreenBoxHalfExtentY", x1b0_orbitScreenBoxHalfExtentY[0]); /* x1b0_orbitScreenBoxHalfExtentY[1] */ __dna_docout.writeUint32("x1b0_orbitScreenBoxHalfExtentY", x1b0_orbitScreenBoxHalfExtentY[1]); - } - /* x1b8_orbitScreenBoxCenterX */ - if (auto v = __dna_docout.enterSubVector("x1b8_orbitScreenBoxCenterX")) - { + } + /* x1b8_orbitScreenBoxCenterX */ + if (auto v = __dna_docout.enterSubVector("x1b8_orbitScreenBoxCenterX")) { /* x1b8_orbitScreenBoxCenterX[0] */ __dna_docout.writeUint32("x1b8_orbitScreenBoxCenterX", x1b8_orbitScreenBoxCenterX[0]); /* x1b8_orbitScreenBoxCenterX[1] */ __dna_docout.writeUint32("x1b8_orbitScreenBoxCenterX", x1b8_orbitScreenBoxCenterX[1]); - } - /* x1c0_orbitScreenBoxCenterY */ - if (auto v = __dna_docout.enterSubVector("x1c0_orbitScreenBoxCenterY")) - { + } + /* x1c0_orbitScreenBoxCenterY */ + if (auto v = __dna_docout.enterSubVector("x1c0_orbitScreenBoxCenterY")) { /* x1c0_orbitScreenBoxCenterY[0] */ __dna_docout.writeUint32("x1c0_orbitScreenBoxCenterY", x1c0_orbitScreenBoxCenterY[0]); /* x1c0_orbitScreenBoxCenterY[1] */ __dna_docout.writeUint32("x1c0_orbitScreenBoxCenterY", x1c0_orbitScreenBoxCenterY[1]); - } - /* x1c8_orbitZoneIdealX */ - if (auto v = __dna_docout.enterSubVector("x1c8_orbitZoneIdealX")) - { + } + /* x1c8_orbitZoneIdealX */ + if (auto v = __dna_docout.enterSubVector("x1c8_orbitZoneIdealX")) { /* x1c8_orbitZoneIdealX[0] */ __dna_docout.writeUint32("x1c8_orbitZoneIdealX", x1c8_orbitZoneIdealX[0]); /* x1c8_orbitZoneIdealX[1] */ __dna_docout.writeUint32("x1c8_orbitZoneIdealX", x1c8_orbitZoneIdealX[1]); - } - /* x1d0_orbitZoneIdealY */ - if (auto v = __dna_docout.enterSubVector("x1d0_orbitZoneIdealY")) - { + } + /* x1d0_orbitZoneIdealY */ + if (auto v = __dna_docout.enterSubVector("x1d0_orbitZoneIdealY")) { /* x1d0_orbitZoneIdealY[0] */ __dna_docout.writeUint32("x1d0_orbitZoneIdealY", x1d0_orbitZoneIdealY[0]); /* x1d0_orbitZoneIdealY[1] */ __dna_docout.writeUint32("x1d0_orbitZoneIdealY", x1d0_orbitZoneIdealY[1]); - } - /* x1d8_orbitNearX */ - __dna_docout.writeFloat("x1d8_orbitNearX", x1d8_orbitNearX); - /* x1dc_orbitNearZ */ - __dna_docout.writeFloat("x1dc_orbitNearZ", x1dc_orbitNearZ); - /* x1e0_ */ - __dna_docout.writeFloat("x1e0_", x1e0_); - /* x1e4_ */ - __dna_docout.writeFloat("x1e4_", x1e4_); - /* x1e8_orbitFixedOffsetZDiff */ - __dna_docout.writeFloat("x1e8_orbitFixedOffsetZDiff", x1e8_orbitFixedOffsetZDiff); - /* x1ec_orbitZRange */ - __dna_docout.writeFloat("x1ec_orbitZRange", x1ec_orbitZRange); - /* x1f0_ */ - __dna_docout.writeFloat("x1f0_", x1f0_); - /* x1f4_ */ - __dna_docout.writeFloat("x1f4_", x1f4_); - /* x1f8_ */ - __dna_docout.writeFloat("x1f8_", x1f8_); - /* x1fc_orbitPreventionTime */ - __dna_docout.writeFloat("x1fc_orbitPreventionTime", x1fc_orbitPreventionTime); - /* x200_24_dashEnabled */ - __dna_docout.writeBool("x200_24_dashEnabled", x200_24_dashEnabled); - /* x200_25_dashOnButtonRelease */ - __dna_docout.writeBool("x200_25_dashOnButtonRelease", x200_25_dashOnButtonRelease); - /* x204_dashButtonHoldCancelTime */ - __dna_docout.writeFloat("x204_dashButtonHoldCancelTime", x204_dashButtonHoldCancelTime); - /* x208_dashStrafeInputThreshold */ - __dna_docout.writeFloat("x208_dashStrafeInputThreshold", x208_dashStrafeInputThreshold); - /* x20c_sidewaysDoubleJumpImpulse */ - __dna_docout.writeFloat("x20c_sidewaysDoubleJumpImpulse", x20c_sidewaysDoubleJumpImpulse); - /* x210_sidewaysVerticalDoubleJumpAccel */ - __dna_docout.writeFloat("x210_sidewaysVerticalDoubleJumpAccel", x210_sidewaysVerticalDoubleJumpAccel); - /* x214_sidewaysHorizontalDoubleJumpAccel */ - __dna_docout.writeFloat("x214_sidewaysHorizontalDoubleJumpAccel", x214_sidewaysHorizontalDoubleJumpAccel); - /* x218_scanningRange */ - __dna_docout.writeFloat("x218_scanningRange", x218_scanningRange); - /* x21c_24_scanRetention */ - __dna_docout.writeBool("x21c_24_scanRetention", x21c_24_scanRetention); - /* x21c_25_scanFreezesGame */ - __dna_docout.writeBool("x21c_25_scanFreezesGame", x21c_25_scanFreezesGame); - /* x21c_26_orbitWhileScanning */ - __dna_docout.writeBool("x21c_26_orbitWhileScanning", x21c_26_orbitWhileScanning); - /* x220_scanMaxTargetDistance */ - __dna_docout.writeFloat("x220_scanMaxTargetDistance", x220_scanMaxTargetDistance); - /* x224_scanMaxLockDistance */ - __dna_docout.writeFloat("x224_scanMaxLockDistance", x224_scanMaxLockDistance); - /* x2a0_orbitDistanceMax */ - __dna_docout.writeFloat("x2a0_orbitDistanceMax", x2a0_orbitDistanceMax); - /* x2a4_grappleSwingLength */ - __dna_docout.writeFloat("x2a4_grappleSwingLength", x2a4_grappleSwingLength); - /* x2a8_grappleSwingPeriod */ - __dna_docout.writeFloat("x2a8_grappleSwingPeriod", x2a8_grappleSwingPeriod); - /* x2ac_grapplePullSpeedMin */ - __dna_docout.writeFloat("x2ac_grapplePullSpeedMin", x2ac_grapplePullSpeedMin); - /* x2b0_grappleCameraSpeed */ - __dna_docout.writeFloat("x2b0_grappleCameraSpeed", x2b0_grappleCameraSpeed); - /* x2b4_maxGrappleLockedTurnAlignDistance */ - __dna_docout.writeFloat("x2b4_maxGrappleLockedTurnAlignDistance", x2b4_maxGrappleLockedTurnAlignDistance); - /* x2b8_grapplePullSpeedProportion */ - __dna_docout.writeFloat("x2b8_grapplePullSpeedProportion", x2b8_grapplePullSpeedProportion); - /* x2bc_grapplePullSpeedMax */ - __dna_docout.writeFloat("x2bc_grapplePullSpeedMax", x2bc_grapplePullSpeedMax); - /* x2c0_grappleLookCenterSpeed */ - __dna_docout.writeFloat("x2c0_grappleLookCenterSpeed", x2c0_grappleLookCenterSpeed); - /* x2c4_maxGrappleTurnSpeed */ - __dna_docout.writeFloat("x2c4_maxGrappleTurnSpeed", x2c4_maxGrappleTurnSpeed); - /* x2c8_grappleJumpForce */ - __dna_docout.writeFloat("x2c8_grappleJumpForce", x2c8_grappleJumpForce); - /* x2cc_grappleReleaseTime */ - __dna_docout.writeFloat("x2cc_grappleReleaseTime", x2cc_grappleReleaseTime); - /* x2d0_grappleJumpMode */ - __dna_docout.writeUint32("x2d0_grappleJumpMode", x2d0_grappleJumpMode); - /* x2d4_orbitReleaseBreaksGrapple */ - __dna_docout.writeBool("x2d4_orbitReleaseBreaksGrapple", x2d4_orbitReleaseBreaksGrapple); - /* x2d5_invertGrappleTurn */ - __dna_docout.writeBool("x2d5_invertGrappleTurn", x2d5_invertGrappleTurn); - /* x2d8_grappleBeamSpeed */ - __dna_docout.writeFloat("x2d8_grappleBeamSpeed", x2d8_grappleBeamSpeed); - /* x2dc_grappleBeamXWaveAmplitude */ - __dna_docout.writeFloat("x2dc_grappleBeamXWaveAmplitude", x2dc_grappleBeamXWaveAmplitude); - /* x2e0_grappleBeamZWaveAmplitude */ - __dna_docout.writeFloat("x2e0_grappleBeamZWaveAmplitude", x2e0_grappleBeamZWaveAmplitude); - /* x2e4_grappleBeamAnglePhaseDelta */ - __dna_docout.writeFloat("x2e4_grappleBeamAnglePhaseDelta", x2e4_grappleBeamAnglePhaseDelta); - /* x26c_playerHeight */ - __dna_docout.writeFloat("x26c_playerHeight", x26c_playerHeight); - /* x270_playerXYHalfExtent */ - __dna_docout.writeFloat("x270_playerXYHalfExtent", x270_playerXYHalfExtent); - /* x274_stepUpHeight */ - __dna_docout.writeFloat("x274_stepUpHeight", x274_stepUpHeight); - /* x278_stepDownHeight */ - __dna_docout.writeFloat("x278_stepDownHeight", x278_stepDownHeight); - /* x27c_playerBallHalfExtent */ - __dna_docout.writeFloat("x27c_playerBallHalfExtent", x27c_playerBallHalfExtent); - /* x280_ */ - __dna_docout.writeFloat("x280_", x280_firstPersonCameraSpeed); - /* x284_ */ - __dna_docout.writeFloat("x284_", x284_); - /* x288_jumpCameraPitchDownStart */ - __dna_docout.writeFloat("x288_jumpCameraPitchDownStart", x288_jumpCameraPitchDownStart); - /* x28c_jumpCameraPitchDownFull */ - __dna_docout.writeFloat("x28c_jumpCameraPitchDownFull", x28c_jumpCameraPitchDownFull); - /* x290_jumpCameraPitchDownAngle */ - __dna_docout.writeFloat("x290_jumpCameraPitchDownAngle", x290_jumpCameraPitchDownAngle); - /* x294_fallCameraPitchDownStart */ - __dna_docout.writeFloat("x294_fallCameraPitchDownStart", x294_fallCameraPitchDownStart); - /* x298_fallCameraPitchDownFull */ - __dna_docout.writeFloat("x298_fallCameraPitchDownFull", x298_fallCameraPitchDownFull); - /* x29c_fallCameraPitchDownAngle */ - __dna_docout.writeFloat("x29c_fallCameraPitchDownAngle", x29c_fallCameraPitchDownAngle); - /* x2e8_ */ - __dna_docout.writeFloat("x2e8_", x2e8_); - /* x2ec_ */ - __dna_docout.writeFloat("x2ec_", x2ec_); - /* x2f0_ */ - __dna_docout.writeFloat("x2f0_", x2f0_); - /* x2f4_ */ - __dna_docout.writeBool("x2f4_", x2f4_); - /* x2f8_frozenTimeout */ - __dna_docout.writeFloat("x2f8_frozenTimeout", x2f8_frozenTimeout); - /* x2fc_iceBreakJumpCount */ - __dna_docout.writeUint32("x2fc_iceBreakJumpCount", x2fc_iceBreakJumpCount); - /* x300_variaDamageReduction */ - __dna_docout.writeFloat("x300_variaDamageReduction", x300_variaDamageReduction); - /* x304_gravityDamageReduction */ - __dna_docout.writeFloat("x304_gravityDamageReduction", x304_gravityDamageReduction); - /* x308_phazonDamageReduction */ - __dna_docout.writeFloat("x308_phazonDamageReduction", x308_phazonDamageReduction); + } + /* x1d8_orbitNearX */ + __dna_docout.writeFloat("x1d8_orbitNearX", x1d8_orbitNearX); + /* x1dc_orbitNearZ */ + __dna_docout.writeFloat("x1dc_orbitNearZ", x1dc_orbitNearZ); + /* x1e0_ */ + __dna_docout.writeFloat("x1e0_", x1e0_); + /* x1e4_ */ + __dna_docout.writeFloat("x1e4_", x1e4_); + /* x1e8_orbitFixedOffsetZDiff */ + __dna_docout.writeFloat("x1e8_orbitFixedOffsetZDiff", x1e8_orbitFixedOffsetZDiff); + /* x1ec_orbitZRange */ + __dna_docout.writeFloat("x1ec_orbitZRange", x1ec_orbitZRange); + /* x1f0_ */ + __dna_docout.writeFloat("x1f0_", x1f0_); + /* x1f4_ */ + __dna_docout.writeFloat("x1f4_", x1f4_); + /* x1f8_ */ + __dna_docout.writeFloat("x1f8_", x1f8_); + /* x1fc_orbitPreventionTime */ + __dna_docout.writeFloat("x1fc_orbitPreventionTime", x1fc_orbitPreventionTime); + /* x200_24_dashEnabled */ + __dna_docout.writeBool("x200_24_dashEnabled", x200_24_dashEnabled); + /* x200_25_dashOnButtonRelease */ + __dna_docout.writeBool("x200_25_dashOnButtonRelease", x200_25_dashOnButtonRelease); + /* x204_dashButtonHoldCancelTime */ + __dna_docout.writeFloat("x204_dashButtonHoldCancelTime", x204_dashButtonHoldCancelTime); + /* x208_dashStrafeInputThreshold */ + __dna_docout.writeFloat("x208_dashStrafeInputThreshold", x208_dashStrafeInputThreshold); + /* x20c_sidewaysDoubleJumpImpulse */ + __dna_docout.writeFloat("x20c_sidewaysDoubleJumpImpulse", x20c_sidewaysDoubleJumpImpulse); + /* x210_sidewaysVerticalDoubleJumpAccel */ + __dna_docout.writeFloat("x210_sidewaysVerticalDoubleJumpAccel", x210_sidewaysVerticalDoubleJumpAccel); + /* x214_sidewaysHorizontalDoubleJumpAccel */ + __dna_docout.writeFloat("x214_sidewaysHorizontalDoubleJumpAccel", x214_sidewaysHorizontalDoubleJumpAccel); + /* x218_scanningRange */ + __dna_docout.writeFloat("x218_scanningRange", x218_scanningRange); + /* x21c_24_scanRetention */ + __dna_docout.writeBool("x21c_24_scanRetention", x21c_24_scanRetention); + /* x21c_25_scanFreezesGame */ + __dna_docout.writeBool("x21c_25_scanFreezesGame", x21c_25_scanFreezesGame); + /* x21c_26_orbitWhileScanning */ + __dna_docout.writeBool("x21c_26_orbitWhileScanning", x21c_26_orbitWhileScanning); + /* x220_scanMaxTargetDistance */ + __dna_docout.writeFloat("x220_scanMaxTargetDistance", x220_scanMaxTargetDistance); + /* x224_scanMaxLockDistance */ + __dna_docout.writeFloat("x224_scanMaxLockDistance", x224_scanMaxLockDistance); + /* x2a0_orbitDistanceMax */ + __dna_docout.writeFloat("x2a0_orbitDistanceMax", x2a0_orbitDistanceMax); + /* x2a4_grappleSwingLength */ + __dna_docout.writeFloat("x2a4_grappleSwingLength", x2a4_grappleSwingLength); + /* x2a8_grappleSwingPeriod */ + __dna_docout.writeFloat("x2a8_grappleSwingPeriod", x2a8_grappleSwingPeriod); + /* x2ac_grapplePullSpeedMin */ + __dna_docout.writeFloat("x2ac_grapplePullSpeedMin", x2ac_grapplePullSpeedMin); + /* x2b0_grappleCameraSpeed */ + __dna_docout.writeFloat("x2b0_grappleCameraSpeed", x2b0_grappleCameraSpeed); + /* x2b4_maxGrappleLockedTurnAlignDistance */ + __dna_docout.writeFloat("x2b4_maxGrappleLockedTurnAlignDistance", x2b4_maxGrappleLockedTurnAlignDistance); + /* x2b8_grapplePullSpeedProportion */ + __dna_docout.writeFloat("x2b8_grapplePullSpeedProportion", x2b8_grapplePullSpeedProportion); + /* x2bc_grapplePullSpeedMax */ + __dna_docout.writeFloat("x2bc_grapplePullSpeedMax", x2bc_grapplePullSpeedMax); + /* x2c0_grappleLookCenterSpeed */ + __dna_docout.writeFloat("x2c0_grappleLookCenterSpeed", x2c0_grappleLookCenterSpeed); + /* x2c4_maxGrappleTurnSpeed */ + __dna_docout.writeFloat("x2c4_maxGrappleTurnSpeed", x2c4_maxGrappleTurnSpeed); + /* x2c8_grappleJumpForce */ + __dna_docout.writeFloat("x2c8_grappleJumpForce", x2c8_grappleJumpForce); + /* x2cc_grappleReleaseTime */ + __dna_docout.writeFloat("x2cc_grappleReleaseTime", x2cc_grappleReleaseTime); + /* x2d0_grappleJumpMode */ + __dna_docout.writeUint32("x2d0_grappleJumpMode", x2d0_grappleJumpMode); + /* x2d4_orbitReleaseBreaksGrapple */ + __dna_docout.writeBool("x2d4_orbitReleaseBreaksGrapple", x2d4_orbitReleaseBreaksGrapple); + /* x2d5_invertGrappleTurn */ + __dna_docout.writeBool("x2d5_invertGrappleTurn", x2d5_invertGrappleTurn); + /* x2d8_grappleBeamSpeed */ + __dna_docout.writeFloat("x2d8_grappleBeamSpeed", x2d8_grappleBeamSpeed); + /* x2dc_grappleBeamXWaveAmplitude */ + __dna_docout.writeFloat("x2dc_grappleBeamXWaveAmplitude", x2dc_grappleBeamXWaveAmplitude); + /* x2e0_grappleBeamZWaveAmplitude */ + __dna_docout.writeFloat("x2e0_grappleBeamZWaveAmplitude", x2e0_grappleBeamZWaveAmplitude); + /* x2e4_grappleBeamAnglePhaseDelta */ + __dna_docout.writeFloat("x2e4_grappleBeamAnglePhaseDelta", x2e4_grappleBeamAnglePhaseDelta); + /* x26c_playerHeight */ + __dna_docout.writeFloat("x26c_playerHeight", x26c_playerHeight); + /* x270_playerXYHalfExtent */ + __dna_docout.writeFloat("x270_playerXYHalfExtent", x270_playerXYHalfExtent); + /* x274_stepUpHeight */ + __dna_docout.writeFloat("x274_stepUpHeight", x274_stepUpHeight); + /* x278_stepDownHeight */ + __dna_docout.writeFloat("x278_stepDownHeight", x278_stepDownHeight); + /* x27c_playerBallHalfExtent */ + __dna_docout.writeFloat("x27c_playerBallHalfExtent", x27c_playerBallHalfExtent); + /* x280_ */ + __dna_docout.writeFloat("x280_", x280_firstPersonCameraSpeed); + /* x284_ */ + __dna_docout.writeFloat("x284_", x284_); + /* x288_jumpCameraPitchDownStart */ + __dna_docout.writeFloat("x288_jumpCameraPitchDownStart", x288_jumpCameraPitchDownStart); + /* x28c_jumpCameraPitchDownFull */ + __dna_docout.writeFloat("x28c_jumpCameraPitchDownFull", x28c_jumpCameraPitchDownFull); + /* x290_jumpCameraPitchDownAngle */ + __dna_docout.writeFloat("x290_jumpCameraPitchDownAngle", x290_jumpCameraPitchDownAngle); + /* x294_fallCameraPitchDownStart */ + __dna_docout.writeFloat("x294_fallCameraPitchDownStart", x294_fallCameraPitchDownStart); + /* x298_fallCameraPitchDownFull */ + __dna_docout.writeFloat("x298_fallCameraPitchDownFull", x298_fallCameraPitchDownFull); + /* x29c_fallCameraPitchDownAngle */ + __dna_docout.writeFloat("x29c_fallCameraPitchDownAngle", x29c_fallCameraPitchDownAngle); + /* x2e8_ */ + __dna_docout.writeFloat("x2e8_", x2e8_); + /* x2ec_ */ + __dna_docout.writeFloat("x2ec_", x2ec_); + /* x2f0_ */ + __dna_docout.writeFloat("x2f0_", x2f0_); + /* x2f4_ */ + __dna_docout.writeBool("x2f4_", x2f4_); + /* x2f8_frozenTimeout */ + __dna_docout.writeFloat("x2f8_frozenTimeout", x2f8_frozenTimeout); + /* x2fc_iceBreakJumpCount */ + __dna_docout.writeUint32("x2fc_iceBreakJumpCount", x2fc_iceBreakJumpCount); + /* x300_variaDamageReduction */ + __dna_docout.writeFloat("x300_variaDamageReduction", x300_variaDamageReduction); + /* x304_gravityDamageReduction */ + __dna_docout.writeFloat("x304_gravityDamageReduction", x304_gravityDamageReduction); + /* x308_phazonDamageReduction */ + __dna_docout.writeFloat("x308_phazonDamageReduction", x308_phazonDamageReduction); } -void CTweakPlayer::FixupValues() -{ - x130_horizontalFreeLookAngleVel = zeus::degToRad(x130_horizontalFreeLookAngleVel); - x134_verticalFreeLookAngleVel = zeus::degToRad(x134_verticalFreeLookAngleVel); - x138_freeLookSpeed = zeus::degToRad(x138_freeLookSpeed); - x13c_freeLookSnapSpeed = zeus::degToRad(x13c_freeLookSnapSpeed); - x140_ = zeus::degToRad(x140_); - x144_freeLookCenteredThresholdAngle = zeus::degToRad(x144_freeLookCenteredThresholdAngle); - x23c_ = zeus::degToRad(x23c_); - x240_ = zeus::degToRad(x240_); - x244_ = zeus::degToRad(x244_); - x248_ = zeus::degToRad(x248_); - x250_ = zeus::degToRad(x250_); - x264_aimAssistHorizontalAngle = zeus::degToRad(x264_aimAssistHorizontalAngle); - x268_aimAssistVerticalAngle = zeus::degToRad(x268_aimAssistVerticalAngle); - x17c_ = zeus::degToRad(x17c_); - x184_orbitCameraSpeed = zeus::degToRad(x184_orbitCameraSpeed); - x188_orbitUpperAngle = zeus::degToRad(x188_orbitUpperAngle); - x18c_orbitLowerAngle = zeus::degToRad(x18c_orbitLowerAngle); - x190_orbitHorizAngle = zeus::degToRad(x190_orbitHorizAngle); - x194_ = zeus::degToRad(x194_); - x198_ = zeus::degToRad(x198_); - x1f0_ = zeus::degToRad(x1f0_); - x1f4_ = zeus::degToRad(x1f4_); - x2b0_grappleCameraSpeed = zeus::degToRad(x2b0_grappleCameraSpeed); - x2c0_grappleLookCenterSpeed = zeus::degToRad(x2c0_grappleLookCenterSpeed); - x280_firstPersonCameraSpeed = zeus::degToRad(x280_firstPersonCameraSpeed); - x284_ = zeus::degToRad(x284_); - x290_jumpCameraPitchDownAngle = zeus::degToRad(x290_jumpCameraPitchDownAngle); - x29c_fallCameraPitchDownAngle = zeus::degToRad(x29c_fallCameraPitchDownAngle); +void CTweakPlayer::FixupValues() { + x130_horizontalFreeLookAngleVel = zeus::degToRad(x130_horizontalFreeLookAngleVel); + x134_verticalFreeLookAngleVel = zeus::degToRad(x134_verticalFreeLookAngleVel); + x138_freeLookSpeed = zeus::degToRad(x138_freeLookSpeed); + x13c_freeLookSnapSpeed = zeus::degToRad(x13c_freeLookSnapSpeed); + x140_ = zeus::degToRad(x140_); + x144_freeLookCenteredThresholdAngle = zeus::degToRad(x144_freeLookCenteredThresholdAngle); + x23c_ = zeus::degToRad(x23c_); + x240_ = zeus::degToRad(x240_); + x244_ = zeus::degToRad(x244_); + x248_ = zeus::degToRad(x248_); + x250_ = zeus::degToRad(x250_); + x264_aimAssistHorizontalAngle = zeus::degToRad(x264_aimAssistHorizontalAngle); + x268_aimAssistVerticalAngle = zeus::degToRad(x268_aimAssistVerticalAngle); + x17c_ = zeus::degToRad(x17c_); + x184_orbitCameraSpeed = zeus::degToRad(x184_orbitCameraSpeed); + x188_orbitUpperAngle = zeus::degToRad(x188_orbitUpperAngle); + x18c_orbitLowerAngle = zeus::degToRad(x18c_orbitLowerAngle); + x190_orbitHorizAngle = zeus::degToRad(x190_orbitHorizAngle); + x194_ = zeus::degToRad(x194_); + x198_ = zeus::degToRad(x198_); + x1f0_ = zeus::degToRad(x1f0_); + x1f4_ = zeus::degToRad(x1f4_); + x2b0_grappleCameraSpeed = zeus::degToRad(x2b0_grappleCameraSpeed); + x2c0_grappleLookCenterSpeed = zeus::degToRad(x2c0_grappleLookCenterSpeed); + x280_firstPersonCameraSpeed = zeus::degToRad(x280_firstPersonCameraSpeed); + x284_ = zeus::degToRad(x284_); + x290_jumpCameraPitchDownAngle = zeus::degToRad(x290_jumpCameraPitchDownAngle); + x29c_fallCameraPitchDownAngle = zeus::degToRad(x29c_fallCameraPitchDownAngle); } -const char* CTweakPlayer::DNAType() -{ - return "DataSpec::DNAMP1::CTweakPlayer"; -} +const char* CTweakPlayer::DNAType() { return "DataSpec::DNAMP1::CTweakPlayer"; } template <> -void CTweakPlayer::Enumerate(size_t& __isz) -{ - __isz += 785; -} +void CTweakPlayer::Enumerate(size_t& __isz) { + __isz += 785; } +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp index 776f0bfde..5afaa1892 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp @@ -2,318 +2,314 @@ #include "../../DNACommon/Tweaks/ITweakPlayer.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CTweakPlayer final : ITweakPlayer -{ - AT_DECL_EXPLICIT_DNA_YAML - Value x4_maxTranslationalAcceleration[8]; - Value x24_maxRotationalAcceleration[8]; - Value x44_translationFriction[8]; - Value x64_rotationFriction[8]; - Value x84_rotationMaxSpeed[8]; - Value xa4_translationMaxSpeed[8]; - Value xc4_normalGravAccel; - Value xc8_fluidGravAccel; - Value xcc_verticalJumpAccel; - Value xd0_horizontalJumpAccel; - Value xd4_verticalDoubleJumpAccel; - Value xd8_horizontalDoubleJumpAccel; - Value xdc_waterJumpFactor; - Value xe0_waterBallJumpFactor; - Value xe4_lavaJumpFactor; - Value xe8_lavaBallJumpFactor; - Value xec_phazonJumpFactor; - Value xf0_phazonBallJumpFactor; - Value xf4_allowedJumpTime; - Value xf8_allowedDoubleJumpTime; - Value xfc_minDoubleJumpWindow; - Value x100_maxDoubleJumpWindow; - Value x104_; - Value x108_minJumpTime; - Value x10c_minDoubleJumpTime; - Value x110_allowedLedgeTime; - Value x114_doubleJumpImpulse; - Value x118_backwardsForceMultiplier; - Value x11c_bombJumpRadius; - Value x120_bombJumpHeight; - Value x124_eyeOffset; - Value x128_turnSpeedMultiplier; - Value x12c_freeLookTurnSpeedMultiplier; - Value x130_horizontalFreeLookAngleVel; - Value x134_verticalFreeLookAngleVel; - Value x138_freeLookSpeed; - Value x13c_freeLookSnapSpeed; - Value x140_; - Value x144_freeLookCenteredThresholdAngle; - Value x148_freeLookCenteredTime; - Value x14c_freeLookDampenFactor; - Value x150_leftDiv; - Value x154_rightDiv; - Value x158_orbitMinDistance[3]; - Value x164_orbitNormalDistance[3]; - Value x170_orbitMaxDistance[3]; - Value x17c_; - Value x180_orbitModeTimer; - Value x184_orbitCameraSpeed; - Value x188_orbitUpperAngle; - Value x18c_orbitLowerAngle; - Value x190_orbitHorizAngle; - Value x194_; - Value x198_; - Value x19c_orbitMaxTargetDistance; - Value x1a0_orbitMaxLockDistance; - Value x1a4_orbitDistanceThreshold; - Value x1a8_orbitScreenBoxHalfExtentX[2]; - Value x1b0_orbitScreenBoxHalfExtentY[2]; - Value x1b8_orbitScreenBoxCenterX[2]; - Value x1c0_orbitScreenBoxCenterY[2]; - Value x1c8_orbitZoneIdealX[2]; - Value x1d0_orbitZoneIdealY[2]; - Value x1d8_orbitNearX; - Value x1dc_orbitNearZ; - Value x1e0_; - Value x1e4_; - Value x1e8_orbitFixedOffsetZDiff; - Value x1ec_orbitZRange; - Value x1f0_; - Value x1f4_; - Value x1f8_; - Value x1fc_orbitPreventionTime; - Value x200_24_dashEnabled : 1; - Value x200_25_dashOnButtonRelease : 1; - Value x204_dashButtonHoldCancelTime; - Value x208_dashStrafeInputThreshold; - Value x20c_sidewaysDoubleJumpImpulse; - Value x210_sidewaysVerticalDoubleJumpAccel; - Value x214_sidewaysHorizontalDoubleJumpAccel; - Value x218_scanningRange; - Value x21c_24_scanRetention : 1; - Value x21c_25_scanFreezesGame : 1; - Value x21c_26_orbitWhileScanning : 1; - Value x220_scanMaxTargetDistance; - Value x224_scanMaxLockDistance; - Value x228_24_freelookTurnsPlayer : 1; - Value x228_25_ : 1; - Value x228_26_ : 1; - Value x228_27_moveDuringFreeLook : 1; - Value x228_28_holdButtonsForFreeLook : 1; - Value x228_29_twoButtonsForFreeLook : 1; - Value x228_30_ : 1; - Value x228_31_ : 1; - Value x229_24_ : 1; - Value x229_25_aimWhenOrbitingPoint : 1; - Value x229_26_stayInFreeLookWhileFiring : 1; - Value x229_27_ : 1; - Value x229_28_ : 1; - Value x229_29_orbitFixedOffset : 1; - Value x229_30_gunButtonTogglesHolster : 1; - Value x229_31_gunNotFiringHolstersGun : 1; - Value x22a_24_fallingDoubleJump : 1; - Value x22a_25_impulseDoubleJump : 1; - Value x22a_26_firingCancelsCameraPitch : 1; - Value x22a_27_assistedAimingIgnoreHorizontal : 1; - Value x22a_28_assistedAimingIgnoreVertical : 1; - Value x22c_; - Value x230_; - Value x234_aimMaxDistance; - Value x238_; - Value x23c_; - Value x240_; - Value x244_; - Value x248_; - Value x24c_aimThresholdDistance; - Value x250_; - Value x254_; - Value x258_aimBoxWidth; - Value x25c_aimBoxHeight; - Value x260_aimTargetTimer; - Value x264_aimAssistHorizontalAngle; - Value x268_aimAssistVerticalAngle; - Value x26c_playerHeight; - Value x270_playerXYHalfExtent; - Value x274_stepUpHeight; - Value x278_stepDownHeight; - Value x27c_playerBallHalfExtent; - Value x280_firstPersonCameraSpeed; - Value x284_; - Value x288_jumpCameraPitchDownStart; - Value x28c_jumpCameraPitchDownFull; - Value x290_jumpCameraPitchDownAngle; - Value x294_fallCameraPitchDownStart; - Value x298_fallCameraPitchDownFull; - Value x29c_fallCameraPitchDownAngle; - Value x2a0_orbitDistanceMax; - Value x2a4_grappleSwingLength; - Value x2a8_grappleSwingPeriod; - Value x2ac_grapplePullSpeedMin; - Value x2b0_grappleCameraSpeed; - Value x2b4_maxGrappleLockedTurnAlignDistance; - Value x2b8_grapplePullSpeedProportion; - Value x2bc_grapplePullSpeedMax; - Value x2c0_grappleLookCenterSpeed; - Value x2c4_maxGrappleTurnSpeed; - Value x2c8_grappleJumpForce; - Value x2cc_grappleReleaseTime; - Value x2d0_grappleJumpMode; - Value x2d4_orbitReleaseBreaksGrapple; - Value x2d5_invertGrappleTurn; - Value x2d8_grappleBeamSpeed; - Value x2dc_grappleBeamXWaveAmplitude; - Value x2e0_grappleBeamZWaveAmplitude; - Value x2e4_grappleBeamAnglePhaseDelta; - Value x2e8_; - Value x2ec_; - Value x2f0_; - Value x2f4_; - Value x2f8_frozenTimeout; - Value x2fc_iceBreakJumpCount; - Value x300_variaDamageReduction; - Value x304_gravityDamageReduction; - Value x308_phazonDamageReduction; - float GetMaxTranslationalAcceleration(int s) const { return x4_maxTranslationalAcceleration[s]; } - float GetMaxRotationalAcceleration(int s) const { return x24_maxRotationalAcceleration[s]; } - float GetPlayerTranslationFriction(int s) const { return x44_translationFriction[s]; } - float GetPlayerRotationFriction(int s) const { return x64_rotationFriction[s]; } - float GetPlayerRotationMaxSpeed(int s) const { return x84_rotationMaxSpeed[s]; } - float GetPlayerTranslationMaxSpeed(int s) const { return xa4_translationMaxSpeed[s]; } - float GetNormalGravAccel() const { return xc4_normalGravAccel; } - float GetFluidGravAccel() const { return xc8_fluidGravAccel; } - float GetVerticalJumpAccel() const { return xcc_verticalJumpAccel; } - float GetHorizontalJumpAccel() const { return xd0_horizontalJumpAccel; } - float GetVerticalDoubleJumpAccel() const { return xd4_verticalDoubleJumpAccel; } - float GetHorizontalDoubleJumpAccel() const { return xd8_horizontalDoubleJumpAccel; } - float GetWaterJumpFactor() const { return xdc_waterJumpFactor; } - float GetWaterBallJumpFactor() const { return xe0_waterBallJumpFactor; } - float GetLavaJumpFactor() const { return xe4_lavaJumpFactor; } - float GetLavaBallJumpFactor() const { return xe8_lavaBallJumpFactor; } - float GetPhazonJumpFactor() const { return xec_phazonJumpFactor; } - float GetPhazonBallJumpFactor() const { return xf0_phazonBallJumpFactor; } - float GetAllowedJumpTime() const { return xf4_allowedJumpTime; } - float GetAllowedDoubleJumpTime() const { return xf8_allowedDoubleJumpTime; } - float GetMinDoubleJumpWindow() const { return xfc_minDoubleJumpWindow; } - float GetMaxDoubleJumpWindow() const { return x100_maxDoubleJumpWindow; } - float GetMinJumpTime() const { return x108_minJumpTime; } - float GetMinDoubleJumpTime() const { return x10c_minDoubleJumpTime; } - float GetAllowedLedgeTime() const { return x110_allowedLedgeTime; } - float GetDoubleJumpImpulse() const { return x114_doubleJumpImpulse; } - float GetBackwardsForceMultiplier() const { return x118_backwardsForceMultiplier; } - float GetBombJumpRadius() const { return x11c_bombJumpRadius; } - float GetBombJumpHeight() const { return x120_bombJumpHeight; } - float GetEyeOffset() const { return x124_eyeOffset; } - float GetTurnSpeedMultiplier() const { return x128_turnSpeedMultiplier; } - float GetFreeLookTurnSpeedMultiplier() const { return x12c_freeLookTurnSpeedMultiplier; } - float GetFreeLookSpeed() const { return x138_freeLookSpeed; } - float GetFreeLookSnapSpeed() const { return x13c_freeLookSnapSpeed; } - float GetFreeLookCenteredThresholdAngle() const { return x144_freeLookCenteredThresholdAngle; } - float GetFreeLookCenteredTime() const { return x148_freeLookCenteredTime; } - float GetOrbitModeTimer() const { return x180_orbitModeTimer; } - float GetOrbitUpperAngle() const { return x188_orbitUpperAngle; } - float GetOrbitLowerAngle() const { return x18c_orbitLowerAngle; } - float GetOrbitHorizAngle() const { return x190_orbitHorizAngle; } - float GetOrbitMaxTargetDistance() const { return x19c_orbitMaxTargetDistance; } - float GetOrbitMaxLockDistance() const { return x1a0_orbitMaxLockDistance; } - float GetOrbitDistanceThreshold() const { return x1a4_orbitDistanceThreshold; } - uint32_t GetOrbitScreenBoxHalfExtentX(int zone) const { return x1a8_orbitScreenBoxHalfExtentX[zone]; } - uint32_t GetOrbitScreenBoxHalfExtentY(int zone) const { return x1b0_orbitScreenBoxHalfExtentY[zone]; } - uint32_t GetOrbitScreenBoxCenterX(int zone) const { return x1b8_orbitScreenBoxCenterX[zone]; } - uint32_t GetOrbitScreenBoxCenterY(int zone) const { return x1c0_orbitScreenBoxCenterY[zone]; } - uint32_t GetOrbitZoneIdealX(int zone) const { return x1c8_orbitZoneIdealX[zone]; } - uint32_t GetOrbitZoneIdealY(int zone) const { return x1d0_orbitZoneIdealY[zone]; } - float GetOrbitNearX() const { return x1d8_orbitNearX; } - float GetOrbitNearZ() const { return x1dc_orbitNearZ; } - float GetOrbitFixedOffsetZDiff() const { return x1e8_orbitFixedOffsetZDiff; } - float GetOrbitZRange() const { return x1ec_orbitZRange; } - bool GetDashEnabled() const { return x200_24_dashEnabled; } - bool GetDashOnButtonRelease() const { return x200_25_dashOnButtonRelease; } - float GetDashButtonHoldCancelTime() const { return x204_dashButtonHoldCancelTime; } - float GetDashStrafeInputThreshold() const { return x208_dashStrafeInputThreshold; } - float GetSidewaysDoubleJumpImpulse() const { return x20c_sidewaysDoubleJumpImpulse; } - float GetSidewaysVerticalDoubleJumpAccel() const { return x210_sidewaysVerticalDoubleJumpAccel; } - float GetSidewaysHorizontalDoubleJumpAccel() const { return x214_sidewaysHorizontalDoubleJumpAccel; } - float GetScanningRange() const { return x218_scanningRange; } - bool GetScanRetention() const { return x21c_24_scanRetention; } - bool GetScanFreezesGame() const { return x21c_25_scanFreezesGame; } - bool GetOrbitWhileScanning() const { return x21c_26_orbitWhileScanning; } - float GetScanMaxTargetDistance() const { return x220_scanMaxTargetDistance; } - float GetScanMaxLockDistance() const { return x224_scanMaxLockDistance; } - bool GetMoveDuringFreeLook() const { return x228_27_moveDuringFreeLook; } - bool GetHoldButtonsForFreeLook() const { return x228_28_holdButtonsForFreeLook; } - bool GetTwoButtonsForFreeLook() const { return x228_29_twoButtonsForFreeLook; } - bool GetAimWhenOrbitingPoint() const { return x229_25_aimWhenOrbitingPoint; } - bool GetStayInFreeLookWhileFiring() const { return x229_26_stayInFreeLookWhileFiring; } - bool GetOrbitFixedOffset() const { return x229_29_orbitFixedOffset; } - bool GetGunButtonTogglesHolster() const { return x229_30_gunButtonTogglesHolster; } - bool GetGunNotFiringHolstersGun() const { return x229_31_gunNotFiringHolstersGun; } - bool GetFallingDoubleJump() const { return x22a_24_fallingDoubleJump; } - bool GetImpulseDoubleJump() const { return x22a_25_impulseDoubleJump; } - bool GetFiringCancelsCameraPitch() const { return x22a_26_firingCancelsCameraPitch; } - bool GetAssistedAimingIgnoreHorizontal() const { return x22a_27_assistedAimingIgnoreHorizontal; } - bool GetAssistedAimingIgnoreVertical() const { return x22a_28_assistedAimingIgnoreVertical; } - float GetAimMaxDistance() const { return x234_aimMaxDistance; } - float GetAimThresholdDistance() const { return x24c_aimThresholdDistance; } - float GetAimBoxWidth() const { return x258_aimBoxWidth; } - float GetAimBoxHeight() const { return x25c_aimBoxHeight; } - float GetAimTargetTimer() const { return x260_aimTargetTimer; } - float GetAimAssistHorizontalAngle() const { return x264_aimAssistHorizontalAngle; } - float GetAimAssistVerticalAngle() const { return x268_aimAssistVerticalAngle; } - float GetPlayerHeight() const { return x26c_playerHeight; } - float GetPlayerXYHalfExtent() const { return x270_playerXYHalfExtent; } - float GetStepUpHeight() const { return x274_stepUpHeight; } - float GetStepDownHeight() const { return x278_stepDownHeight; } - float GetPlayerBallHalfExtent() const { return x27c_playerBallHalfExtent; } - float GetOrbitDistanceMax() const { return x2a0_orbitDistanceMax; } - float GetGrappleSwingLength() const { return x2a4_grappleSwingLength; } - float GetGrappleSwingPeriod() const { return x2a8_grappleSwingPeriod; } - float GetGrapplePullSpeedMin() const { return x2ac_grapplePullSpeedMin; } - float GetMaxGrappleLockedTurnAlignDistance() const { return x2b4_maxGrappleLockedTurnAlignDistance; } - float GetGrapplePullSpeedProportion() const { return x2b8_grapplePullSpeedProportion; } - float GetGrapplePullSpeedMax() const { return x2bc_grapplePullSpeedMax; } - float GetGrappleLookCenterSpeed() const { return x2c0_grappleLookCenterSpeed; } - float GetMaxGrappleTurnSpeed() const { return x2c4_maxGrappleTurnSpeed; } - float GetGrappleJumpForce() const { return x2c8_grappleJumpForce; } - float GetGrappleReleaseTime() const { return x2cc_grappleReleaseTime; } - uint32_t GetGrappleJumpMode() const { return x2d0_grappleJumpMode; } - bool GetOrbitReleaseBreaksGrapple() const { return x2d4_orbitReleaseBreaksGrapple; } - bool GetInvertGrappleTurn() const { return x2d5_invertGrappleTurn; } - float GetGrappleBeamSpeed() const { return x2d8_grappleBeamSpeed; } - float GetGrappleBeamXWaveAmplitude() const { return x2dc_grappleBeamXWaveAmplitude; } - float GetGrappleBeamZWaveAmplitude() const { return x2e0_grappleBeamZWaveAmplitude; } - float GetGrappleBeamAnglePhaseDelta() const { return x2e4_grappleBeamAnglePhaseDelta; } - float GetHorizontalFreeLookAngleVel() const { return x130_horizontalFreeLookAngleVel; } - float GetVerticalFreeLookAngleVel() const { return x134_verticalFreeLookAngleVel; } - float GetOrbitCameraSpeed() const { return x184_orbitCameraSpeed; } - float GetOrbitPreventionTime() const { return x1fc_orbitPreventionTime; } - bool GetFreeLookTurnsPlayer() const { return x228_24_freelookTurnsPlayer; } - float GetJumpCameraPitchDownStart() const { return x288_jumpCameraPitchDownStart; } - float GetJumpCameraPitchDownFull() const { return x28c_jumpCameraPitchDownFull; } - float GetJumpCameraPitchDownAngle() const { return x290_jumpCameraPitchDownAngle; } - float GetFallCameraPitchDownStart() const { return x294_fallCameraPitchDownStart; } - float GetFallCameraPitchDownFull() const { return x298_fallCameraPitchDownFull; } - float GetFallCameraPitchDownAngle() const { return x29c_fallCameraPitchDownAngle; } - float GetFirstPersonCameraSpeed() const { return x280_firstPersonCameraSpeed; } - float GetGrappleCameraSpeed() const { return x2b0_grappleCameraSpeed; } - float GetFreeLookDampenFactor() const { return x14c_freeLookDampenFactor; } - float GetLeftLogicalThreshold() const { return x150_leftDiv; } - float GetRightLogicalThreshold() const { return x154_rightDiv; } - float GetOrbitMinDistance(int type) const { return x158_orbitMinDistance[type]; } - float GetOrbitNormalDistance(int type) const { return x164_orbitNormalDistance[type]; } - float GetOrbitMaxDistance(int type) const { return x170_orbitMaxDistance[type]; } - float GetFrozenTimeout() const { return x2f8_frozenTimeout; } - uint32_t GetIceBreakJumpCount() const { return x2fc_iceBreakJumpCount; } - float GetVariaDamageReduction() const { return x300_variaDamageReduction; } - float GetGravityDamageReduction() const { return x304_gravityDamageReduction; } - float GetPhazonDamageReduction() const { return x308_phazonDamageReduction; } - CTweakPlayer() = default; - CTweakPlayer(athena::io::IStreamReader& reader) - { - read(reader); - FixupValues(); - } +struct CTweakPlayer final : ITweakPlayer { + AT_DECL_EXPLICIT_DNA_YAML + Value x4_maxTranslationalAcceleration[8]; + Value x24_maxRotationalAcceleration[8]; + Value x44_translationFriction[8]; + Value x64_rotationFriction[8]; + Value x84_rotationMaxSpeed[8]; + Value xa4_translationMaxSpeed[8]; + Value xc4_normalGravAccel; + Value xc8_fluidGravAccel; + Value xcc_verticalJumpAccel; + Value xd0_horizontalJumpAccel; + Value xd4_verticalDoubleJumpAccel; + Value xd8_horizontalDoubleJumpAccel; + Value xdc_waterJumpFactor; + Value xe0_waterBallJumpFactor; + Value xe4_lavaJumpFactor; + Value xe8_lavaBallJumpFactor; + Value xec_phazonJumpFactor; + Value xf0_phazonBallJumpFactor; + Value xf4_allowedJumpTime; + Value xf8_allowedDoubleJumpTime; + Value xfc_minDoubleJumpWindow; + Value x100_maxDoubleJumpWindow; + Value x104_; + Value x108_minJumpTime; + Value x10c_minDoubleJumpTime; + Value x110_allowedLedgeTime; + Value x114_doubleJumpImpulse; + Value x118_backwardsForceMultiplier; + Value x11c_bombJumpRadius; + Value x120_bombJumpHeight; + Value x124_eyeOffset; + Value x128_turnSpeedMultiplier; + Value x12c_freeLookTurnSpeedMultiplier; + Value x130_horizontalFreeLookAngleVel; + Value x134_verticalFreeLookAngleVel; + Value x138_freeLookSpeed; + Value x13c_freeLookSnapSpeed; + Value x140_; + Value x144_freeLookCenteredThresholdAngle; + Value x148_freeLookCenteredTime; + Value x14c_freeLookDampenFactor; + Value x150_leftDiv; + Value x154_rightDiv; + Value x158_orbitMinDistance[3]; + Value x164_orbitNormalDistance[3]; + Value x170_orbitMaxDistance[3]; + Value x17c_; + Value x180_orbitModeTimer; + Value x184_orbitCameraSpeed; + Value x188_orbitUpperAngle; + Value x18c_orbitLowerAngle; + Value x190_orbitHorizAngle; + Value x194_; + Value x198_; + Value x19c_orbitMaxTargetDistance; + Value x1a0_orbitMaxLockDistance; + Value x1a4_orbitDistanceThreshold; + Value x1a8_orbitScreenBoxHalfExtentX[2]; + Value x1b0_orbitScreenBoxHalfExtentY[2]; + Value x1b8_orbitScreenBoxCenterX[2]; + Value x1c0_orbitScreenBoxCenterY[2]; + Value x1c8_orbitZoneIdealX[2]; + Value x1d0_orbitZoneIdealY[2]; + Value x1d8_orbitNearX; + Value x1dc_orbitNearZ; + Value x1e0_; + Value x1e4_; + Value x1e8_orbitFixedOffsetZDiff; + Value x1ec_orbitZRange; + Value x1f0_; + Value x1f4_; + Value x1f8_; + Value x1fc_orbitPreventionTime; + Value x200_24_dashEnabled : 1; + Value x200_25_dashOnButtonRelease : 1; + Value x204_dashButtonHoldCancelTime; + Value x208_dashStrafeInputThreshold; + Value x20c_sidewaysDoubleJumpImpulse; + Value x210_sidewaysVerticalDoubleJumpAccel; + Value x214_sidewaysHorizontalDoubleJumpAccel; + Value x218_scanningRange; + Value x21c_24_scanRetention : 1; + Value x21c_25_scanFreezesGame : 1; + Value x21c_26_orbitWhileScanning : 1; + Value x220_scanMaxTargetDistance; + Value x224_scanMaxLockDistance; + Value x228_24_freelookTurnsPlayer : 1; + Value x228_25_ : 1; + Value x228_26_ : 1; + Value x228_27_moveDuringFreeLook : 1; + Value x228_28_holdButtonsForFreeLook : 1; + Value x228_29_twoButtonsForFreeLook : 1; + Value x228_30_ : 1; + Value x228_31_ : 1; + Value x229_24_ : 1; + Value x229_25_aimWhenOrbitingPoint : 1; + Value x229_26_stayInFreeLookWhileFiring : 1; + Value x229_27_ : 1; + Value x229_28_ : 1; + Value x229_29_orbitFixedOffset : 1; + Value x229_30_gunButtonTogglesHolster : 1; + Value x229_31_gunNotFiringHolstersGun : 1; + Value x22a_24_fallingDoubleJump : 1; + Value x22a_25_impulseDoubleJump : 1; + Value x22a_26_firingCancelsCameraPitch : 1; + Value x22a_27_assistedAimingIgnoreHorizontal : 1; + Value x22a_28_assistedAimingIgnoreVertical : 1; + Value x22c_; + Value x230_; + Value x234_aimMaxDistance; + Value x238_; + Value x23c_; + Value x240_; + Value x244_; + Value x248_; + Value x24c_aimThresholdDistance; + Value x250_; + Value x254_; + Value x258_aimBoxWidth; + Value x25c_aimBoxHeight; + Value x260_aimTargetTimer; + Value x264_aimAssistHorizontalAngle; + Value x268_aimAssistVerticalAngle; + Value x26c_playerHeight; + Value x270_playerXYHalfExtent; + Value x274_stepUpHeight; + Value x278_stepDownHeight; + Value x27c_playerBallHalfExtent; + Value x280_firstPersonCameraSpeed; + Value x284_; + Value x288_jumpCameraPitchDownStart; + Value x28c_jumpCameraPitchDownFull; + Value x290_jumpCameraPitchDownAngle; + Value x294_fallCameraPitchDownStart; + Value x298_fallCameraPitchDownFull; + Value x29c_fallCameraPitchDownAngle; + Value x2a0_orbitDistanceMax; + Value x2a4_grappleSwingLength; + Value x2a8_grappleSwingPeriod; + Value x2ac_grapplePullSpeedMin; + Value x2b0_grappleCameraSpeed; + Value x2b4_maxGrappleLockedTurnAlignDistance; + Value x2b8_grapplePullSpeedProportion; + Value x2bc_grapplePullSpeedMax; + Value x2c0_grappleLookCenterSpeed; + Value x2c4_maxGrappleTurnSpeed; + Value x2c8_grappleJumpForce; + Value x2cc_grappleReleaseTime; + Value x2d0_grappleJumpMode; + Value x2d4_orbitReleaseBreaksGrapple; + Value x2d5_invertGrappleTurn; + Value x2d8_grappleBeamSpeed; + Value x2dc_grappleBeamXWaveAmplitude; + Value x2e0_grappleBeamZWaveAmplitude; + Value x2e4_grappleBeamAnglePhaseDelta; + Value x2e8_; + Value x2ec_; + Value x2f0_; + Value x2f4_; + Value x2f8_frozenTimeout; + Value x2fc_iceBreakJumpCount; + Value x300_variaDamageReduction; + Value x304_gravityDamageReduction; + Value x308_phazonDamageReduction; + float GetMaxTranslationalAcceleration(int s) const { return x4_maxTranslationalAcceleration[s]; } + float GetMaxRotationalAcceleration(int s) const { return x24_maxRotationalAcceleration[s]; } + float GetPlayerTranslationFriction(int s) const { return x44_translationFriction[s]; } + float GetPlayerRotationFriction(int s) const { return x64_rotationFriction[s]; } + float GetPlayerRotationMaxSpeed(int s) const { return x84_rotationMaxSpeed[s]; } + float GetPlayerTranslationMaxSpeed(int s) const { return xa4_translationMaxSpeed[s]; } + float GetNormalGravAccel() const { return xc4_normalGravAccel; } + float GetFluidGravAccel() const { return xc8_fluidGravAccel; } + float GetVerticalJumpAccel() const { return xcc_verticalJumpAccel; } + float GetHorizontalJumpAccel() const { return xd0_horizontalJumpAccel; } + float GetVerticalDoubleJumpAccel() const { return xd4_verticalDoubleJumpAccel; } + float GetHorizontalDoubleJumpAccel() const { return xd8_horizontalDoubleJumpAccel; } + float GetWaterJumpFactor() const { return xdc_waterJumpFactor; } + float GetWaterBallJumpFactor() const { return xe0_waterBallJumpFactor; } + float GetLavaJumpFactor() const { return xe4_lavaJumpFactor; } + float GetLavaBallJumpFactor() const { return xe8_lavaBallJumpFactor; } + float GetPhazonJumpFactor() const { return xec_phazonJumpFactor; } + float GetPhazonBallJumpFactor() const { return xf0_phazonBallJumpFactor; } + float GetAllowedJumpTime() const { return xf4_allowedJumpTime; } + float GetAllowedDoubleJumpTime() const { return xf8_allowedDoubleJumpTime; } + float GetMinDoubleJumpWindow() const { return xfc_minDoubleJumpWindow; } + float GetMaxDoubleJumpWindow() const { return x100_maxDoubleJumpWindow; } + float GetMinJumpTime() const { return x108_minJumpTime; } + float GetMinDoubleJumpTime() const { return x10c_minDoubleJumpTime; } + float GetAllowedLedgeTime() const { return x110_allowedLedgeTime; } + float GetDoubleJumpImpulse() const { return x114_doubleJumpImpulse; } + float GetBackwardsForceMultiplier() const { return x118_backwardsForceMultiplier; } + float GetBombJumpRadius() const { return x11c_bombJumpRadius; } + float GetBombJumpHeight() const { return x120_bombJumpHeight; } + float GetEyeOffset() const { return x124_eyeOffset; } + float GetTurnSpeedMultiplier() const { return x128_turnSpeedMultiplier; } + float GetFreeLookTurnSpeedMultiplier() const { return x12c_freeLookTurnSpeedMultiplier; } + float GetFreeLookSpeed() const { return x138_freeLookSpeed; } + float GetFreeLookSnapSpeed() const { return x13c_freeLookSnapSpeed; } + float GetFreeLookCenteredThresholdAngle() const { return x144_freeLookCenteredThresholdAngle; } + float GetFreeLookCenteredTime() const { return x148_freeLookCenteredTime; } + float GetOrbitModeTimer() const { return x180_orbitModeTimer; } + float GetOrbitUpperAngle() const { return x188_orbitUpperAngle; } + float GetOrbitLowerAngle() const { return x18c_orbitLowerAngle; } + float GetOrbitHorizAngle() const { return x190_orbitHorizAngle; } + float GetOrbitMaxTargetDistance() const { return x19c_orbitMaxTargetDistance; } + float GetOrbitMaxLockDistance() const { return x1a0_orbitMaxLockDistance; } + float GetOrbitDistanceThreshold() const { return x1a4_orbitDistanceThreshold; } + uint32_t GetOrbitScreenBoxHalfExtentX(int zone) const { return x1a8_orbitScreenBoxHalfExtentX[zone]; } + uint32_t GetOrbitScreenBoxHalfExtentY(int zone) const { return x1b0_orbitScreenBoxHalfExtentY[zone]; } + uint32_t GetOrbitScreenBoxCenterX(int zone) const { return x1b8_orbitScreenBoxCenterX[zone]; } + uint32_t GetOrbitScreenBoxCenterY(int zone) const { return x1c0_orbitScreenBoxCenterY[zone]; } + uint32_t GetOrbitZoneIdealX(int zone) const { return x1c8_orbitZoneIdealX[zone]; } + uint32_t GetOrbitZoneIdealY(int zone) const { return x1d0_orbitZoneIdealY[zone]; } + float GetOrbitNearX() const { return x1d8_orbitNearX; } + float GetOrbitNearZ() const { return x1dc_orbitNearZ; } + float GetOrbitFixedOffsetZDiff() const { return x1e8_orbitFixedOffsetZDiff; } + float GetOrbitZRange() const { return x1ec_orbitZRange; } + bool GetDashEnabled() const { return x200_24_dashEnabled; } + bool GetDashOnButtonRelease() const { return x200_25_dashOnButtonRelease; } + float GetDashButtonHoldCancelTime() const { return x204_dashButtonHoldCancelTime; } + float GetDashStrafeInputThreshold() const { return x208_dashStrafeInputThreshold; } + float GetSidewaysDoubleJumpImpulse() const { return x20c_sidewaysDoubleJumpImpulse; } + float GetSidewaysVerticalDoubleJumpAccel() const { return x210_sidewaysVerticalDoubleJumpAccel; } + float GetSidewaysHorizontalDoubleJumpAccel() const { return x214_sidewaysHorizontalDoubleJumpAccel; } + float GetScanningRange() const { return x218_scanningRange; } + bool GetScanRetention() const { return x21c_24_scanRetention; } + bool GetScanFreezesGame() const { return x21c_25_scanFreezesGame; } + bool GetOrbitWhileScanning() const { return x21c_26_orbitWhileScanning; } + float GetScanMaxTargetDistance() const { return x220_scanMaxTargetDistance; } + float GetScanMaxLockDistance() const { return x224_scanMaxLockDistance; } + bool GetMoveDuringFreeLook() const { return x228_27_moveDuringFreeLook; } + bool GetHoldButtonsForFreeLook() const { return x228_28_holdButtonsForFreeLook; } + bool GetTwoButtonsForFreeLook() const { return x228_29_twoButtonsForFreeLook; } + bool GetAimWhenOrbitingPoint() const { return x229_25_aimWhenOrbitingPoint; } + bool GetStayInFreeLookWhileFiring() const { return x229_26_stayInFreeLookWhileFiring; } + bool GetOrbitFixedOffset() const { return x229_29_orbitFixedOffset; } + bool GetGunButtonTogglesHolster() const { return x229_30_gunButtonTogglesHolster; } + bool GetGunNotFiringHolstersGun() const { return x229_31_gunNotFiringHolstersGun; } + bool GetFallingDoubleJump() const { return x22a_24_fallingDoubleJump; } + bool GetImpulseDoubleJump() const { return x22a_25_impulseDoubleJump; } + bool GetFiringCancelsCameraPitch() const { return x22a_26_firingCancelsCameraPitch; } + bool GetAssistedAimingIgnoreHorizontal() const { return x22a_27_assistedAimingIgnoreHorizontal; } + bool GetAssistedAimingIgnoreVertical() const { return x22a_28_assistedAimingIgnoreVertical; } + float GetAimMaxDistance() const { return x234_aimMaxDistance; } + float GetAimThresholdDistance() const { return x24c_aimThresholdDistance; } + float GetAimBoxWidth() const { return x258_aimBoxWidth; } + float GetAimBoxHeight() const { return x25c_aimBoxHeight; } + float GetAimTargetTimer() const { return x260_aimTargetTimer; } + float GetAimAssistHorizontalAngle() const { return x264_aimAssistHorizontalAngle; } + float GetAimAssistVerticalAngle() const { return x268_aimAssistVerticalAngle; } + float GetPlayerHeight() const { return x26c_playerHeight; } + float GetPlayerXYHalfExtent() const { return x270_playerXYHalfExtent; } + float GetStepUpHeight() const { return x274_stepUpHeight; } + float GetStepDownHeight() const { return x278_stepDownHeight; } + float GetPlayerBallHalfExtent() const { return x27c_playerBallHalfExtent; } + float GetOrbitDistanceMax() const { return x2a0_orbitDistanceMax; } + float GetGrappleSwingLength() const { return x2a4_grappleSwingLength; } + float GetGrappleSwingPeriod() const { return x2a8_grappleSwingPeriod; } + float GetGrapplePullSpeedMin() const { return x2ac_grapplePullSpeedMin; } + float GetMaxGrappleLockedTurnAlignDistance() const { return x2b4_maxGrappleLockedTurnAlignDistance; } + float GetGrapplePullSpeedProportion() const { return x2b8_grapplePullSpeedProportion; } + float GetGrapplePullSpeedMax() const { return x2bc_grapplePullSpeedMax; } + float GetGrappleLookCenterSpeed() const { return x2c0_grappleLookCenterSpeed; } + float GetMaxGrappleTurnSpeed() const { return x2c4_maxGrappleTurnSpeed; } + float GetGrappleJumpForce() const { return x2c8_grappleJumpForce; } + float GetGrappleReleaseTime() const { return x2cc_grappleReleaseTime; } + uint32_t GetGrappleJumpMode() const { return x2d0_grappleJumpMode; } + bool GetOrbitReleaseBreaksGrapple() const { return x2d4_orbitReleaseBreaksGrapple; } + bool GetInvertGrappleTurn() const { return x2d5_invertGrappleTurn; } + float GetGrappleBeamSpeed() const { return x2d8_grappleBeamSpeed; } + float GetGrappleBeamXWaveAmplitude() const { return x2dc_grappleBeamXWaveAmplitude; } + float GetGrappleBeamZWaveAmplitude() const { return x2e0_grappleBeamZWaveAmplitude; } + float GetGrappleBeamAnglePhaseDelta() const { return x2e4_grappleBeamAnglePhaseDelta; } + float GetHorizontalFreeLookAngleVel() const { return x130_horizontalFreeLookAngleVel; } + float GetVerticalFreeLookAngleVel() const { return x134_verticalFreeLookAngleVel; } + float GetOrbitCameraSpeed() const { return x184_orbitCameraSpeed; } + float GetOrbitPreventionTime() const { return x1fc_orbitPreventionTime; } + bool GetFreeLookTurnsPlayer() const { return x228_24_freelookTurnsPlayer; } + float GetJumpCameraPitchDownStart() const { return x288_jumpCameraPitchDownStart; } + float GetJumpCameraPitchDownFull() const { return x28c_jumpCameraPitchDownFull; } + float GetJumpCameraPitchDownAngle() const { return x290_jumpCameraPitchDownAngle; } + float GetFallCameraPitchDownStart() const { return x294_fallCameraPitchDownStart; } + float GetFallCameraPitchDownFull() const { return x298_fallCameraPitchDownFull; } + float GetFallCameraPitchDownAngle() const { return x29c_fallCameraPitchDownAngle; } + float GetFirstPersonCameraSpeed() const { return x280_firstPersonCameraSpeed; } + float GetGrappleCameraSpeed() const { return x2b0_grappleCameraSpeed; } + float GetFreeLookDampenFactor() const { return x14c_freeLookDampenFactor; } + float GetLeftLogicalThreshold() const { return x150_leftDiv; } + float GetRightLogicalThreshold() const { return x154_rightDiv; } + float GetOrbitMinDistance(int type) const { return x158_orbitMinDistance[type]; } + float GetOrbitNormalDistance(int type) const { return x164_orbitNormalDistance[type]; } + float GetOrbitMaxDistance(int type) const { return x170_orbitMaxDistance[type]; } + float GetFrozenTimeout() const { return x2f8_frozenTimeout; } + uint32_t GetIceBreakJumpCount() const { return x2fc_iceBreakJumpCount; } + float GetVariaDamageReduction() const { return x300_variaDamageReduction; } + float GetGravityDamageReduction() const { return x304_gravityDamageReduction; } + float GetPhazonDamageReduction() const { return x308_phazonDamageReduction; } + CTweakPlayer() = default; + CTweakPlayer(athena::io::IStreamReader& reader) { + read(reader); + FixupValues(); + } - void FixupValues(); + void FixupValues(); }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayerControl.hpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayerControl.hpp index 12aa5fb98..664bc3d78 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakPlayerControl.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayerControl.hpp @@ -2,17 +2,14 @@ #include "../../DNACommon/Tweaks/ITweakPlayerControl.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CTweakPlayerControl final : ITweakPlayerControl -{ - AT_DECL_DNA_YAML - Vector m_mappings; - atUint32 GetMapping(atUint32 command) const {return m_mappings[command];} - CTweakPlayerControl() = default; - CTweakPlayerControl(athena::io::IStreamReader& reader) {this->read(reader);} +struct CTweakPlayerControl final : ITweakPlayerControl { + AT_DECL_DNA_YAML + Vector m_mappings; + atUint32 GetMapping(atUint32 command) const { return m_mappings[command]; } + CTweakPlayerControl() = default; + CTweakPlayerControl(athena::io::IStreamReader& reader) { this->read(reader); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayerGun.hpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayerGun.hpp index 39f2da746..e0e66c780 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakPlayerGun.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayerGun.hpp @@ -2,114 +2,106 @@ #include "../../DNACommon/Tweaks/ITweakPlayerGun.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CTweakPlayerGun final : ITweakPlayerGun -{ - AT_DECL_DNA_YAML - Value x4_upLookAngle; - Value x8_downLookAngle; - Value xc_verticalSpread; - Value x10_horizontalSpread; - Value x14_highVerticalSpread; - Value x18_highHorizontalSpread; - Value x1c_lowVerticalSpread; - Value x20_lowHorizontalSpread; - Value x24_aimVerticalSpeed; - Value x28_aimHorizontalSpeed; - Value x2c_bombFuseTime; - Value x30_bombDropDelayTime; - Value x34_holoHoldTime; - Value x38_gunTransformTime; - Value x3c_gunHolsterTime; - Value x40_gunNotFiringTime; - Value x44_fixedVerticalAim; - Value x48_gunExtendDistance; - Value x4c_gunPosition; - Value x58_; - Value x64_grapplingArmPosition; - SShotParam x70_bomb; - SShotParam x8c_powerBomb; - SShotParam x1d4_missile; - SWeaponInfo xa8_beams[5]; - SComboShotParam x1f0_combos[5]; // Originally rstl::prereserved_vector - Value x280_ricochetData[6]; // Originally rstl::prereserved_vector, extended to 6 to capture - // PhazonBeam's value - CTweakPlayerGun() = default; - CTweakPlayerGun(athena::io::IStreamReader& r) - { - this->read(r); - x44_fixedVerticalAim = zeus::degToRad(x44_fixedVerticalAim); - } +struct CTweakPlayerGun final : ITweakPlayerGun { + AT_DECL_DNA_YAML + Value x4_upLookAngle; + Value x8_downLookAngle; + Value xc_verticalSpread; + Value x10_horizontalSpread; + Value x14_highVerticalSpread; + Value x18_highHorizontalSpread; + Value x1c_lowVerticalSpread; + Value x20_lowHorizontalSpread; + Value x24_aimVerticalSpeed; + Value x28_aimHorizontalSpeed; + Value x2c_bombFuseTime; + Value x30_bombDropDelayTime; + Value x34_holoHoldTime; + Value x38_gunTransformTime; + Value x3c_gunHolsterTime; + Value x40_gunNotFiringTime; + Value x44_fixedVerticalAim; + Value x48_gunExtendDistance; + Value x4c_gunPosition; + Value x58_; + Value x64_grapplingArmPosition; + SShotParam x70_bomb; + SShotParam x8c_powerBomb; + SShotParam x1d4_missile; + SWeaponInfo xa8_beams[5]; + SComboShotParam x1f0_combos[5]; // Originally rstl::prereserved_vector + Value x280_ricochetData[6]; // Originally rstl::prereserved_vector, extended to 6 to capture + // PhazonBeam's value + CTweakPlayerGun() = default; + CTweakPlayerGun(athena::io::IStreamReader& r) { + this->read(r); + x44_fixedVerticalAim = zeus::degToRad(x44_fixedVerticalAim); + } - float GetUpLookAngle() const { return x4_upLookAngle; } - float GetDownLookAngle() const { return x8_downLookAngle; } - float GetVerticalSpread() const { return xc_verticalSpread; } - float GetHorizontalSpread() const { return x10_horizontalSpread; } - float GetHighVerticalSpread() const { return x14_highVerticalSpread; } - float GetHighHorizontalSpread() const { return x18_highHorizontalSpread; } - float GetLowVerticalSpread() const { return x1c_lowVerticalSpread; } - float GetLowHorizontalSpread() const { return x20_lowHorizontalSpread; } - float GetAimVerticalSpeed() const { return x24_aimVerticalSpeed; } - float GetAimHorizontalSpeed() const { return x28_aimHorizontalSpeed; } - float GetBombFuseTime() const { return x2c_bombFuseTime; } - float GetBombDropDelayTime() const { return x30_bombDropDelayTime; } - float GetHoloHoldTime() const { return x34_holoHoldTime; } - float GetGunTransformTime() const { return x38_gunTransformTime; } - float GetGunHolsterTime() const { return x3c_gunHolsterTime; } - float GetGunNotFiringTime() const { return x40_gunNotFiringTime; } - float GetFixedVerticalAim() const { return x44_fixedVerticalAim; } - float GetGunExtendDistance() const { return x48_gunExtendDistance; } - const zeus::CVector3f& GetGunPosition() const { return x4c_gunPosition; } - const zeus::CVector3f& GetGrapplingArmPosition() const { return x64_grapplingArmPosition; } - float GetRichochetDamage(atUint32 type) const - { - switch (type) - { - case 0: // Power - return x280_ricochetData[0]; - case 1: // Ice - return x280_ricochetData[1]; - case 2: // Wave - return x280_ricochetData[2]; - case 3: // Plasma - return x280_ricochetData[3]; - case 6: // Missile - return x280_ricochetData[4]; - case 8: // Phazon - /* Note: In order to return the same value as retail we have to do a bit of a hack - * Retro accidentally forgot to load in PhazonBeam's richochet value, as a result, it loads the - * pointer to CTweakParticle's vtable. - */ + float GetUpLookAngle() const { return x4_upLookAngle; } + float GetDownLookAngle() const { return x8_downLookAngle; } + float GetVerticalSpread() const { return xc_verticalSpread; } + float GetHorizontalSpread() const { return x10_horizontalSpread; } + float GetHighVerticalSpread() const { return x14_highVerticalSpread; } + float GetHighHorizontalSpread() const { return x18_highHorizontalSpread; } + float GetLowVerticalSpread() const { return x1c_lowVerticalSpread; } + float GetLowHorizontalSpread() const { return x20_lowHorizontalSpread; } + float GetAimVerticalSpeed() const { return x24_aimVerticalSpeed; } + float GetAimHorizontalSpeed() const { return x28_aimHorizontalSpeed; } + float GetBombFuseTime() const { return x2c_bombFuseTime; } + float GetBombDropDelayTime() const { return x30_bombDropDelayTime; } + float GetHoloHoldTime() const { return x34_holoHoldTime; } + float GetGunTransformTime() const { return x38_gunTransformTime; } + float GetGunHolsterTime() const { return x3c_gunHolsterTime; } + float GetGunNotFiringTime() const { return x40_gunNotFiringTime; } + float GetFixedVerticalAim() const { return x44_fixedVerticalAim; } + float GetGunExtendDistance() const { return x48_gunExtendDistance; } + const zeus::CVector3f& GetGunPosition() const { return x4c_gunPosition; } + const zeus::CVector3f& GetGrapplingArmPosition() const { return x64_grapplingArmPosition; } + float GetRichochetDamage(atUint32 type) const { + switch (type) { + case 0: // Power + return x280_ricochetData[0]; + case 1: // Ice + return x280_ricochetData[1]; + case 2: // Wave + return x280_ricochetData[2]; + case 3: // Plasma + return x280_ricochetData[3]; + case 6: // Missile + return x280_ricochetData[4]; + case 8: // Phazon + /* Note: In order to return the same value as retail we have to do a bit of a hack + * Retro accidentally forgot to load in PhazonBeam's richochet value, as a result, it loads the + * pointer to CTweakParticle's vtable. + */ #if MP_v1088 - return float(0x803D9CC4); + return float(0x803D9CC4); #else - return x280_ricochetData[5]; + return x280_ricochetData[5]; #endif - default: - return 1.f; - } + default: + return 1.f; } + } - const SWeaponInfo& GetBeamInfo(atInt32 beam) const - { - if (beam < 0 || beam > 5) - return xa8_beams[0]; - return xa8_beams[beam]; - } + const SWeaponInfo& GetBeamInfo(atInt32 beam) const { + if (beam < 0 || beam > 5) + return xa8_beams[0]; + return xa8_beams[beam]; + } - const SComboShotParam& GetComboShotInfo(atInt32 beam) const - { - if (beam < 0 || beam > 5) - return x1f0_combos[0]; - return x1f0_combos[beam]; - } + const SComboShotParam& GetComboShotInfo(atInt32 beam) const { + if (beam < 0 || beam > 5) + return x1f0_combos[0]; + return x1f0_combos[beam]; + } - const SShotParam& GetBombInfo() const { return x70_bomb; } - const SShotParam& GetPowerBombInfo() const { return x8c_powerBomb; } - const SShotParam& GetMissileInfo() const { return x1d4_missile; } + const SShotParam& GetBombInfo() const { return x70_bomb; } + const SShotParam& GetPowerBombInfo() const { return x8c_powerBomb; } + const SShotParam& GetMissileInfo() const { return x1d4_missile; } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayerRes.hpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayerRes.hpp index ae815fa4f..43ed66deb 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakPlayerRes.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayerRes.hpp @@ -2,103 +2,100 @@ #include "../../DNACommon/Tweaks/ITweakPlayerRes.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CTweakPlayerRes final : ITweakPlayerRes -{ - AT_DECL_DNA_YAML +struct CTweakPlayerRes final : ITweakPlayerRes { + AT_DECL_DNA_YAML - String<-1> m_saveStationIcon; - String<-1> m_missileStationIcon; - String<-1> m_elevatorIcon; + String<-1> m_saveStationIcon; + String<-1> m_missileStationIcon; + String<-1> m_elevatorIcon; - String<-1> m_minesBreakFirstTopIcon; - String<-1> m_minesBreakFirstBottomIcon; - String<-1> m_minesBreakSecondTopIcon; - String<-1> m_minesBreakSecondBottomIcon; + String<-1> m_minesBreakFirstTopIcon; + String<-1> m_minesBreakFirstBottomIcon; + String<-1> m_minesBreakSecondTopIcon; + String<-1> m_minesBreakSecondBottomIcon; - String<-1> m_lStickN; - String<-1> m_lStickU; - String<-1> m_lStickUL; - String<-1> m_lStickL; - String<-1> m_lStickDL; - String<-1> m_lStickD; - String<-1> m_lStickDR; - String<-1> m_lStickR; - String<-1> m_lStickUR; + String<-1> m_lStickN; + String<-1> m_lStickU; + String<-1> m_lStickUL; + String<-1> m_lStickL; + String<-1> m_lStickDL; + String<-1> m_lStickD; + String<-1> m_lStickDR; + String<-1> m_lStickR; + String<-1> m_lStickUR; - String<-1> m_cStickN; - String<-1> m_cStickU; - String<-1> m_cStickUL; - String<-1> m_cStickL; - String<-1> m_cStickDL; - String<-1> m_cStickD; - String<-1> m_cStickDR; - String<-1> m_cStickR; - String<-1> m_cStickUR; + String<-1> m_cStickN; + String<-1> m_cStickU; + String<-1> m_cStickUL; + String<-1> m_cStickL; + String<-1> m_cStickDL; + String<-1> m_cStickD; + String<-1> m_cStickDR; + String<-1> m_cStickR; + String<-1> m_cStickUR; - String<-1> m_lTriggerOut; - String<-1> m_lTriggerIn; - String<-1> m_rTriggerOut; - String<-1> m_rTriggerIn; + String<-1> m_lTriggerOut; + String<-1> m_lTriggerIn; + String<-1> m_rTriggerOut; + String<-1> m_rTriggerIn; - String<-1> m_startButtonOut; - String<-1> m_startButtonIn; - String<-1> m_aButtonOut; - String<-1> m_aButtonIn; - String<-1> m_bButtonOut; - String<-1> m_bButtonIn; - String<-1> m_xButtonOut; - String<-1> m_xButtonIn; - String<-1> m_yButtonOut; - String<-1> m_yButtonIn; + String<-1> m_startButtonOut; + String<-1> m_startButtonIn; + String<-1> m_aButtonOut; + String<-1> m_aButtonIn; + String<-1> m_bButtonOut; + String<-1> m_bButtonIn; + String<-1> m_xButtonOut; + String<-1> m_xButtonIn; + String<-1> m_yButtonOut; + String<-1> m_yButtonIn; - String<-1> m_ballTransitionsANCS; - String<-1> m_ballTransitionsPower; - String<-1> m_ballTransitionsIce; - String<-1> m_ballTransitionsWave; - String<-1> m_ballTransitionsPlasma; - String<-1> m_ballTransitionsPhazon; + String<-1> m_ballTransitionsANCS; + String<-1> m_ballTransitionsPower; + String<-1> m_ballTransitionsIce; + String<-1> m_ballTransitionsWave; + String<-1> m_ballTransitionsPlasma; + String<-1> m_ballTransitionsPhazon; - String<-1> m_cinePower; - String<-1> m_cineIce; - String<-1> m_cineWave; - String<-1> m_cinePlasma; - String<-1> m_cinePhazon; + String<-1> m_cinePower; + String<-1> m_cineIce; + String<-1> m_cineWave; + String<-1> m_cinePlasma; + String<-1> m_cinePhazon; - Value m_cinematicMoveOutofIntoPlayerDistance; + Value m_cinematicMoveOutofIntoPlayerDistance; - std::string_view _GetSaveStationIcon() const { return m_saveStationIcon; } - std::string_view _GetMissileStationIcon() const { return m_missileStationIcon; } - std::string_view _GetElevatorIcon() const { return m_elevatorIcon; } + std::string_view _GetSaveStationIcon() const { return m_saveStationIcon; } + std::string_view _GetMissileStationIcon() const { return m_missileStationIcon; } + std::string_view _GetElevatorIcon() const { return m_elevatorIcon; } - std::string_view _GetMinesBreakFirstTopIcon() const { return m_minesBreakFirstTopIcon; } - std::string_view _GetMinesBreakFirstBottomIcon() const { return m_minesBreakFirstBottomIcon; } - std::string_view _GetMinesBreakSecondTopIcon() const { return m_minesBreakSecondTopIcon; } - std::string_view _GetMinesBreakSecondBottomIcon() const { return m_minesBreakSecondBottomIcon; } + std::string_view _GetMinesBreakFirstTopIcon() const { return m_minesBreakFirstTopIcon; } + std::string_view _GetMinesBreakFirstBottomIcon() const { return m_minesBreakFirstBottomIcon; } + std::string_view _GetMinesBreakSecondTopIcon() const { return m_minesBreakSecondTopIcon; } + std::string_view _GetMinesBreakSecondBottomIcon() const { return m_minesBreakSecondBottomIcon; } - std::string_view _GetLStick(size_t idx) const { return (&m_lStickN)[idx]; } - std::string_view _GetCStick(size_t idx) const { return (&m_cStickN)[idx]; } + std::string_view _GetLStick(size_t idx) const { return (&m_lStickN)[idx]; } + std::string_view _GetCStick(size_t idx) const { return (&m_cStickN)[idx]; } - std::string_view _GetLTrigger(size_t idx) const { return (&m_lTriggerOut)[idx]; } - std::string_view _GetRTrigger(size_t idx) const { return (&m_rTriggerOut)[idx]; } - std::string_view _GetStartButton(size_t idx) const { return (&m_startButtonOut)[idx]; } - std::string_view _GetAButton(size_t idx) const { return (&m_aButtonOut)[idx]; } - std::string_view _GetBButton(size_t idx) const { return (&m_bButtonOut)[idx]; } - std::string_view _GetXButton(size_t idx) const { return (&m_xButtonOut)[idx]; } - std::string_view _GetYButton(size_t idx) const { return (&m_yButtonOut)[idx]; } + std::string_view _GetLTrigger(size_t idx) const { return (&m_lTriggerOut)[idx]; } + std::string_view _GetRTrigger(size_t idx) const { return (&m_rTriggerOut)[idx]; } + std::string_view _GetStartButton(size_t idx) const { return (&m_startButtonOut)[idx]; } + std::string_view _GetAButton(size_t idx) const { return (&m_aButtonOut)[idx]; } + std::string_view _GetBButton(size_t idx) const { return (&m_bButtonOut)[idx]; } + std::string_view _GetXButton(size_t idx) const { return (&m_xButtonOut)[idx]; } + std::string_view _GetYButton(size_t idx) const { return (&m_yButtonOut)[idx]; } - std::string_view _GetBallTransitionsANCS() const { return m_ballTransitionsANCS; } + std::string_view _GetBallTransitionsANCS() const { return m_ballTransitionsANCS; } - std::string_view _GetBallTransitionBeamRes(size_t idx) const { return (&m_ballTransitionsPower)[idx]; } - std::string_view _GetBeamCineModel(size_t idx) const { return (&m_cinePower)[idx]; } + std::string_view _GetBallTransitionBeamRes(size_t idx) const { return (&m_ballTransitionsPower)[idx]; } + std::string_view _GetBeamCineModel(size_t idx) const { return (&m_cinePower)[idx]; } - float _GetCinematicMoveOutofIntoPlayerDistance() const { return m_cinematicMoveOutofIntoPlayerDistance; } + float _GetCinematicMoveOutofIntoPlayerDistance() const { return m_cinematicMoveOutofIntoPlayerDistance; } - CTweakPlayerRes() = default; - CTweakPlayerRes(athena::io::IStreamReader& in) { read(in); } + CTweakPlayerRes() = default; + CTweakPlayerRes(athena::io::IStreamReader& in) { read(in); } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakSlideShow.hpp b/DataSpec/DNAMP1/Tweaks/CTweakSlideShow.hpp index aa15cac56..f56130d61 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakSlideShow.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakSlideShow.hpp @@ -3,39 +3,36 @@ #include "../../DNACommon/Tweaks/ITweakSlideShow.hpp" #include "zeus/CColor.hpp" -namespace DataSpec::DNAMP1 -{ +namespace DataSpec::DNAMP1 { -struct CTweakSlideShow final : ITweakSlideShow -{ - AT_DECL_DNA_YAML +struct CTweakSlideShow final : ITweakSlideShow { + AT_DECL_DNA_YAML - String<-1> x4_pakName; - String<-1> x14_fontAssetName; - DNAColor x24_fontColor; - DNAColor x28_outlineColor; - Value x2c_scanPercentInterval; - Value x30_; - Value x34_; - Value x38_; - Value x3c_; - DNAColor x40_; - Value x44_; - Value x48_; - Value x4c_; - Value x50_; - Value x54_; - Value x58_; + String<-1> x4_pakName; + String<-1> x14_fontAssetName; + DNAColor x24_fontColor; + DNAColor x28_outlineColor; + Value x2c_scanPercentInterval; + Value x30_; + Value x34_; + Value x38_; + Value x3c_; + DNAColor x40_; + Value x44_; + Value x48_; + Value x4c_; + Value x50_; + Value x54_; + Value x58_; - CTweakSlideShow() = default; - CTweakSlideShow(athena::io::IStreamReader& in) { read(in); } + CTweakSlideShow() = default; + CTweakSlideShow(athena::io::IStreamReader& in) { read(in); } - std::string_view GetFont() const { return x14_fontAssetName; } - const zeus::CColor& GetFontColor() const { return x24_fontColor; } - const zeus::CColor& GetOutlineColor() const { return x28_outlineColor; } - float GetScanPercentInterval() const { return x2c_scanPercentInterval; } - float GetX54() const { return x54_; } + std::string_view GetFont() const { return x14_fontAssetName; } + const zeus::CColor& GetFontColor() const { return x24_fontColor; } + const zeus::CColor& GetOutlineColor() const { return x28_outlineColor; } + float GetScanPercentInterval() const { return x2c_scanPercentInterval; } + float GetX54() const { return x54_; } }; -} - +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP1/Tweaks/CTweakTargeting.hpp b/DataSpec/DNAMP1/Tweaks/CTweakTargeting.hpp index 52ef02b4a..02f65511c 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakTargeting.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakTargeting.hpp @@ -2,242 +2,238 @@ #include "../../DNACommon/Tweaks/ITweakTargeting.hpp" -namespace DataSpec::DNAMP1 -{ -struct CTweakTargeting final : public ITweakTargeting -{ - AT_DECL_DNA_YAML - Value x4_targetRadiusMode; - Value x8_currLockOnExitDuration; - Value xc_currLockOnEnterDuration; - Value x10_currLockOnSwitchDuration; - Value x14_lockConfirmScale; - Value x18_nextLockOnEnterDuration; - Value x1c_nextLockOnExitDuration; - Value x20_nextLockOnSwitchDuration; - Value x24_seekerScale; - Value x28_seekerAngleSpeed; - Value x2c_xrayRetAngleSpeed; - Value x30_; - Value x3c_; - Value x48_; - Value x4c_; - Value x50_orbitPointZOffset; - Value x54_orbitPointInTime; - Value x58_orbitPointOutTime; - Value x5c_; - Value x60_; - Value x6c_; - Value x78_; - Value x84_; - Value x90_; - Value x94_; - Value x98_; - Value x9c_; - Value xa0_; - Value xa4_; - Value xa8_; - Value xac_; - DNAColor xb0_thermalReticuleColor; - Value xb4_targetFlowerScale; - DNAColor xb8_targetFlowerColor; - Value xbc_missileBracketDuration; - Value xc0_missileBracketScaleStart; - Value xc4_missileBracketScaleEnd; - Value xc8_missileBracketScaleDuration; - DNAColor xcc_missileBracketColor; - Value xd0_LockonDuration; - Value xd4_innerBeamScale; - DNAColor xd8_innerBeamColorPower; - DNAColor xdc_innerBeamColorIce; - DNAColor xe0_innerBeamColorWave; - DNAColor xe4_innerBeamColorPlasma; - Value xe8_chargeGaugeOvershootOffset; - Value xec_chargeGaugeOvershootDuration; - Value xf0_outerBeamSquaresScale; - DNAColor xf4_outerBeamSquareColor; - Value xf8_outerBeamSquareAngleCount; - struct UnkVec : BigDNA - { - AT_DECL_DNA - Value count; - Vector floats; - }; - Vector xf8_outerBeamSquareAngles; - Value x108_chargeGaugeAngleCount; - Vector x108_chargeGaugeAngles; - Value x118_chargeGaugeScale; - DNAColor x11c_chargeGaugeNonFullColor; - Value x120_chargeTickCount; - Value x124_chargeTickAnglePitch; - Value x128_lockFireScale; - Value x12c_lockFireDuration; - DNAColor x130_lockFireColor; - Value x134_lockDaggerScaleStart; - Value x138_lockDaggerScaleEnd; - DNAColor x13c_lockDaggerColor; - Value x140_lockDaggerAngle0; - Value x144_lockDaggerAngle1; - Value x148_lockDaggerAngle2; - DNAColor x14c_lockConfirmColor; - DNAColor x150_seekerColor; - Value x154_lockConfirmClampMin; - Value x158_lockConfirmClampMax; - Value x15c_targetFlowerClampMin; - Value x160_targetFlowerClampMax; - Value x164_seekerClampMin; - Value x168_seekerClampMax; - Value x16c_missileBracketClampMin; - Value x170_missileBracketClampMax; - Value x174_innerBeamClampMin; - Value x178_innerBeamClampMax; - Value x17c_chargeGaugeClampMin; - Value x180_chargeGaugeClampMax; - Value x184_lockFireClampMin; - Value x188_lockFireClampMax; - Value x18c_lockDaggerClampMin; - Value x190_lockDaggerClampMax; - Value x194_grappleSelectScale; - Value x198_grappleScale; - Value x19c_grappleClampMin; - Value x1a0_grappleClampMax; - DNAColor x1a4_grapplePointSelectColor; - DNAColor x1a8_grapplePointColor; - DNAColor x1ac_lockedGrapplePointSelectColor; - Value x1b0_grappleMinClampScale; - DNAColor x1b4_chargeGaugePulseColorHigh; - Value x1b8_fullChargeFadeDuration; - DNAColor x1bc_orbitPointColor; - DNAColor x1c0_crosshairsColor; - Value x1c4_crosshairsScaleDur; - Value x1c8_drawOrbitPoint; - DNAColor x1cc_chargeGaugePulseColorLow; - Value x1d0_chargeGaugePulsePeriod; - DNAColor x1d4_; - DNAColor x1d8_; - DNAColor x1dc_; - Value x1e0_; - Value x1e4_; - Value x1e8_; - Value x1ec_; - Value x1f0_; - Value x1f4_; - Value x1f8_; - Value x1fc_; - Value x200_; - Value x204_; - Value x208_; - Value x20c_reticuleClampMin; - Value x210_reticuleClampMax; - DNAColor x214_xrayRetRingColor; - Value x218_reticuleScale; - Value x21c_scanTargetClampMin; - Value x220_scanTargetClampMax; - Value x224_angularLagSpeed; +namespace DataSpec::DNAMP1 { +struct CTweakTargeting final : public ITweakTargeting { + AT_DECL_DNA_YAML + Value x4_targetRadiusMode; + Value x8_currLockOnExitDuration; + Value xc_currLockOnEnterDuration; + Value x10_currLockOnSwitchDuration; + Value x14_lockConfirmScale; + Value x18_nextLockOnEnterDuration; + Value x1c_nextLockOnExitDuration; + Value x20_nextLockOnSwitchDuration; + Value x24_seekerScale; + Value x28_seekerAngleSpeed; + Value x2c_xrayRetAngleSpeed; + Value x30_; + Value x3c_; + Value x48_; + Value x4c_; + Value x50_orbitPointZOffset; + Value x54_orbitPointInTime; + Value x58_orbitPointOutTime; + Value x5c_; + Value x60_; + Value x6c_; + Value x78_; + Value x84_; + Value x90_; + Value x94_; + Value x98_; + Value x9c_; + Value xa0_; + Value xa4_; + Value xa8_; + Value xac_; + DNAColor xb0_thermalReticuleColor; + Value xb4_targetFlowerScale; + DNAColor xb8_targetFlowerColor; + Value xbc_missileBracketDuration; + Value xc0_missileBracketScaleStart; + Value xc4_missileBracketScaleEnd; + Value xc8_missileBracketScaleDuration; + DNAColor xcc_missileBracketColor; + Value xd0_LockonDuration; + Value xd4_innerBeamScale; + DNAColor xd8_innerBeamColorPower; + DNAColor xdc_innerBeamColorIce; + DNAColor xe0_innerBeamColorWave; + DNAColor xe4_innerBeamColorPlasma; + Value xe8_chargeGaugeOvershootOffset; + Value xec_chargeGaugeOvershootDuration; + Value xf0_outerBeamSquaresScale; + DNAColor xf4_outerBeamSquareColor; + Value xf8_outerBeamSquareAngleCount; + struct UnkVec : BigDNA { + AT_DECL_DNA + Value count; + Vector floats; + }; + Vector xf8_outerBeamSquareAngles; + Value x108_chargeGaugeAngleCount; + Vector x108_chargeGaugeAngles; + Value x118_chargeGaugeScale; + DNAColor x11c_chargeGaugeNonFullColor; + Value x120_chargeTickCount; + Value x124_chargeTickAnglePitch; + Value x128_lockFireScale; + Value x12c_lockFireDuration; + DNAColor x130_lockFireColor; + Value x134_lockDaggerScaleStart; + Value x138_lockDaggerScaleEnd; + DNAColor x13c_lockDaggerColor; + Value x140_lockDaggerAngle0; + Value x144_lockDaggerAngle1; + Value x148_lockDaggerAngle2; + DNAColor x14c_lockConfirmColor; + DNAColor x150_seekerColor; + Value x154_lockConfirmClampMin; + Value x158_lockConfirmClampMax; + Value x15c_targetFlowerClampMin; + Value x160_targetFlowerClampMax; + Value x164_seekerClampMin; + Value x168_seekerClampMax; + Value x16c_missileBracketClampMin; + Value x170_missileBracketClampMax; + Value x174_innerBeamClampMin; + Value x178_innerBeamClampMax; + Value x17c_chargeGaugeClampMin; + Value x180_chargeGaugeClampMax; + Value x184_lockFireClampMin; + Value x188_lockFireClampMax; + Value x18c_lockDaggerClampMin; + Value x190_lockDaggerClampMax; + Value x194_grappleSelectScale; + Value x198_grappleScale; + Value x19c_grappleClampMin; + Value x1a0_grappleClampMax; + DNAColor x1a4_grapplePointSelectColor; + DNAColor x1a8_grapplePointColor; + DNAColor x1ac_lockedGrapplePointSelectColor; + Value x1b0_grappleMinClampScale; + DNAColor x1b4_chargeGaugePulseColorHigh; + Value x1b8_fullChargeFadeDuration; + DNAColor x1bc_orbitPointColor; + DNAColor x1c0_crosshairsColor; + Value x1c4_crosshairsScaleDur; + Value x1c8_drawOrbitPoint; + DNAColor x1cc_chargeGaugePulseColorLow; + Value x1d0_chargeGaugePulsePeriod; + DNAColor x1d4_; + DNAColor x1d8_; + DNAColor x1dc_; + Value x1e0_; + Value x1e4_; + Value x1e8_; + Value x1ec_; + Value x1f0_; + Value x1f4_; + Value x1f8_; + Value x1fc_; + Value x200_; + Value x204_; + Value x208_; + Value x20c_reticuleClampMin; + Value x210_reticuleClampMax; + DNAColor x214_xrayRetRingColor; + Value x218_reticuleScale; + Value x21c_scanTargetClampMin; + Value x220_scanTargetClampMax; + Value x224_angularLagSpeed; - CTweakTargeting() = default; - CTweakTargeting(athena::io::IStreamReader& r) - { - this->read(r); - x124_chargeTickAnglePitch = -zeus::degToRad(x124_chargeTickAnglePitch); - x140_lockDaggerAngle0 = zeus::degToRad(x140_lockDaggerAngle0); - x144_lockDaggerAngle1 = zeus::degToRad(x144_lockDaggerAngle1); - x148_lockDaggerAngle2 = zeus::degToRad(x148_lockDaggerAngle2); - x208_ = zeus::degToRad(x208_); - for (int i=0 ; i<4 ; ++i) - for (float& f : xf8_outerBeamSquareAngles[i].floats) - f = zeus::degToRad(f); - for (int i=0 ; i<4 ; ++i) - x108_chargeGaugeAngles[i] = zeus::degToRad(x108_chargeGaugeAngles[i]); - } + CTweakTargeting() = default; + CTweakTargeting(athena::io::IStreamReader& r) { + this->read(r); + x124_chargeTickAnglePitch = -zeus::degToRad(x124_chargeTickAnglePitch); + x140_lockDaggerAngle0 = zeus::degToRad(x140_lockDaggerAngle0); + x144_lockDaggerAngle1 = zeus::degToRad(x144_lockDaggerAngle1); + x148_lockDaggerAngle2 = zeus::degToRad(x148_lockDaggerAngle2); + x208_ = zeus::degToRad(x208_); + for (int i = 0; i < 4; ++i) + for (float& f : xf8_outerBeamSquareAngles[i].floats) + f = zeus::degToRad(f); + for (int i = 0; i < 4; ++i) + x108_chargeGaugeAngles[i] = zeus::degToRad(x108_chargeGaugeAngles[i]); + } - atUint32 GetTargetRadiusMode() const { return x4_targetRadiusMode; } - float GetCurrLockOnExitDuration() const { return x8_currLockOnExitDuration; } - float GetCurrLockOnEnterDuration() const { return xc_currLockOnEnterDuration; } - float GetCurrLockOnSwitchDuration() const { return x10_currLockOnSwitchDuration; } - float GetLockConfirmScale() const { return x14_lockConfirmScale; } - float GetNextLockOnEnterDuration() const { return x18_nextLockOnEnterDuration; } - float GetNextLockOnExitDuration() const { return x1c_nextLockOnExitDuration; } - float GetNextLockOnSwitchDuration() const { return x20_nextLockOnSwitchDuration; } - float GetSeekerScale() const { return x24_seekerScale; } - float GetSeekerAngleSpeed() const { return x28_seekerAngleSpeed; } - float GetXRayRetAngleSpeed() const { return x2c_xrayRetAngleSpeed; } - float GetOrbitPointZOffset() const { return x50_orbitPointZOffset; } - float GetOrbitPointInTime() const { return x54_orbitPointInTime; } - float GetOrbitPointOutTime() const { return x58_orbitPointOutTime; } - const zeus::CColor& GetThermalReticuleColor() const { return xb0_thermalReticuleColor; } - float GetTargetFlowerScale() const { return xb4_targetFlowerScale; } - const zeus::CColor& GetTargetFlowerColor() const { return xb8_targetFlowerColor; } - float GetMissileBracketDuration() const { return xbc_missileBracketDuration; } - float GetMissileBracketScaleStart() const { return xc0_missileBracketScaleStart; } - float GetMissileBracketScaleEnd() const { return xc4_missileBracketScaleEnd; } - float GetMissileBracketScaleDuration() const { return xc8_missileBracketScaleDuration; } - const zeus::CColor& GetMissileBracketColor() const { return xcc_missileBracketColor; } - float GetChargeGaugeOvershootOffset() const { return xe8_chargeGaugeOvershootOffset; } - float GetChargeGaugeOvershootDuration() const { return xec_chargeGaugeOvershootDuration; } - float GetOuterBeamSquaresScale() const { return xf0_outerBeamSquaresScale; } - const zeus::CColor& GetOuterBeamSquareColor() const { return xf4_outerBeamSquareColor; } - float GetLockonDuration() const { return xd0_LockonDuration; } - float GetInnerBeamScale() const { return xd4_innerBeamScale; } - const zeus::CColor& GetInnerBeamColorPower() const { return xd8_innerBeamColorPower; } - const zeus::CColor& GetInnerBeamColorIce() const { return xdc_innerBeamColorIce; } - const zeus::CColor& GetInnerBeamColorWave() const { return xe0_innerBeamColorWave; } - const zeus::CColor& GetInnerBeamColorPlasma() const { return xe4_innerBeamColorPlasma; } - const float* GetOuterBeamSquareAngles(int i) const { return xf8_outerBeamSquareAngles[i].floats.data(); } - float GetChargeGaugeAngle(int i) const { return x108_chargeGaugeAngles[i]; } - float GetChargeGaugeScale() const { return x118_chargeGaugeScale; } - const zeus::CColor& GetChargeGaugeNonFullColor() const { return x11c_chargeGaugeNonFullColor; } - atUint32 GetChargeTickCount() const { return x120_chargeTickCount; } - float GetChargeTickAnglePitch() const { return x124_chargeTickAnglePitch; } - float GetLockFireScale() const { return x128_lockFireScale; } - float GetLockFireDuration() const { return x12c_lockFireDuration; } - const zeus::CColor& GetLockFireColor() const { return x130_lockFireColor; } - float GetLockDaggerScaleStart() const { return x134_lockDaggerScaleStart; } - float GetLockDaggerScaleEnd() const { return x138_lockDaggerScaleEnd; } - const zeus::CColor& GetLockDaggerColor() const { return x13c_lockDaggerColor; } - float GetLockDaggerAngle0() const { return x140_lockDaggerAngle0; } - float GetLockDaggerAngle1() const { return x144_lockDaggerAngle1; } - float GetLockDaggerAngle2() const { return x148_lockDaggerAngle2; } - const zeus::CColor& GetLockConfirmColor() const { return x14c_lockConfirmColor; } - const zeus::CColor& GetSeekerColor() const { return x150_seekerColor; } - float GetLockConfirmClampMin() const { return x154_lockConfirmClampMin; } - float GetLockConfirmClampMax() const { return x158_lockConfirmClampMax; } - float GetTargetFlowerClampMin() const { return x15c_targetFlowerClampMin; } - float GetTargetFlowerClampMax() const { return x160_targetFlowerClampMax; } - float GetSeekerClampMin() const { return x164_seekerClampMin; } - float GetSeekerClampMax() const { return x168_seekerClampMax; } - float GetMissileBracketClampMin() const { return x16c_missileBracketClampMin; } - float GetMissileBracketClampMax() const { return x170_missileBracketClampMax; } - float GetInnerBeamClampMin() const { return x174_innerBeamClampMin; } - float GetInnerBeamClampMax() const { return x178_innerBeamClampMax; } - float GetChargeGaugeClampMin() const { return x17c_chargeGaugeClampMin; } - float GetChargeGaugeClampMax() const { return x180_chargeGaugeClampMax; } - float GetLockFireClampMin() const { return x184_lockFireClampMin; } - float GetLockFireClampMax() const { return x188_lockFireClampMax; } - float GetLockDaggerClampMin() const { return x18c_lockDaggerClampMin; } - float GetLockDaggerClampMax() const { return x190_lockDaggerClampMax; } - float GetGrappleSelectScale() const { return x194_grappleSelectScale; } - float GetGrappleScale() const { return x198_grappleScale; } - float GetGrappleClampMin() const { return x19c_grappleClampMin; } - float GetGrappleClampMax() const { return x1a0_grappleClampMax; } - const zeus::CColor& GetGrapplePointSelectColor() const { return x1a4_grapplePointSelectColor; } - const zeus::CColor& GetGrapplePointColor() const { return x1a8_grapplePointColor; } - const zeus::CColor& GetLockedGrapplePointSelectColor() const { return x1ac_lockedGrapplePointSelectColor; } - float GetGrappleMinClampScale() const { return x1b0_grappleMinClampScale; } - const zeus::CColor& GetChargeGaugePulseColorHigh() const { return x1b4_chargeGaugePulseColorHigh; } - float GetFullChargeFadeDuration() const { return x1b8_fullChargeFadeDuration; } - const zeus::CColor& GetOrbitPointColor() const { return x1bc_orbitPointColor; } - const zeus::CColor& GetCrosshairsColor() const { return x1c0_crosshairsColor; } - float GetCrosshairsScaleDuration() const { return x1c4_crosshairsScaleDur; } - bool DrawOrbitPoint() const { return x1c8_drawOrbitPoint; } - const zeus::CColor& GetChargeGaugePulseColorLow() const { return x1cc_chargeGaugePulseColorLow; } - float GetChargeGaugePulsePeriod() const { return x1d0_chargeGaugePulsePeriod; } - float GetReticuleClampMin() const { return x20c_reticuleClampMin; } - float GetReticuleClampMax() const { return x210_reticuleClampMax; } - const zeus::CColor& GetXRayRetRingColor() const { return x214_xrayRetRingColor; } - float GetReticuleScale() const { return x218_reticuleScale; } - float GetScanTargetClampMin() const { return x21c_scanTargetClampMin; } - float GetScanTargetClampMax() const { return x220_scanTargetClampMax; } - float GetAngularLagSpeed() const { return x224_angularLagSpeed; } + atUint32 GetTargetRadiusMode() const { return x4_targetRadiusMode; } + float GetCurrLockOnExitDuration() const { return x8_currLockOnExitDuration; } + float GetCurrLockOnEnterDuration() const { return xc_currLockOnEnterDuration; } + float GetCurrLockOnSwitchDuration() const { return x10_currLockOnSwitchDuration; } + float GetLockConfirmScale() const { return x14_lockConfirmScale; } + float GetNextLockOnEnterDuration() const { return x18_nextLockOnEnterDuration; } + float GetNextLockOnExitDuration() const { return x1c_nextLockOnExitDuration; } + float GetNextLockOnSwitchDuration() const { return x20_nextLockOnSwitchDuration; } + float GetSeekerScale() const { return x24_seekerScale; } + float GetSeekerAngleSpeed() const { return x28_seekerAngleSpeed; } + float GetXRayRetAngleSpeed() const { return x2c_xrayRetAngleSpeed; } + float GetOrbitPointZOffset() const { return x50_orbitPointZOffset; } + float GetOrbitPointInTime() const { return x54_orbitPointInTime; } + float GetOrbitPointOutTime() const { return x58_orbitPointOutTime; } + const zeus::CColor& GetThermalReticuleColor() const { return xb0_thermalReticuleColor; } + float GetTargetFlowerScale() const { return xb4_targetFlowerScale; } + const zeus::CColor& GetTargetFlowerColor() const { return xb8_targetFlowerColor; } + float GetMissileBracketDuration() const { return xbc_missileBracketDuration; } + float GetMissileBracketScaleStart() const { return xc0_missileBracketScaleStart; } + float GetMissileBracketScaleEnd() const { return xc4_missileBracketScaleEnd; } + float GetMissileBracketScaleDuration() const { return xc8_missileBracketScaleDuration; } + const zeus::CColor& GetMissileBracketColor() const { return xcc_missileBracketColor; } + float GetChargeGaugeOvershootOffset() const { return xe8_chargeGaugeOvershootOffset; } + float GetChargeGaugeOvershootDuration() const { return xec_chargeGaugeOvershootDuration; } + float GetOuterBeamSquaresScale() const { return xf0_outerBeamSquaresScale; } + const zeus::CColor& GetOuterBeamSquareColor() const { return xf4_outerBeamSquareColor; } + float GetLockonDuration() const { return xd0_LockonDuration; } + float GetInnerBeamScale() const { return xd4_innerBeamScale; } + const zeus::CColor& GetInnerBeamColorPower() const { return xd8_innerBeamColorPower; } + const zeus::CColor& GetInnerBeamColorIce() const { return xdc_innerBeamColorIce; } + const zeus::CColor& GetInnerBeamColorWave() const { return xe0_innerBeamColorWave; } + const zeus::CColor& GetInnerBeamColorPlasma() const { return xe4_innerBeamColorPlasma; } + const float* GetOuterBeamSquareAngles(int i) const { return xf8_outerBeamSquareAngles[i].floats.data(); } + float GetChargeGaugeAngle(int i) const { return x108_chargeGaugeAngles[i]; } + float GetChargeGaugeScale() const { return x118_chargeGaugeScale; } + const zeus::CColor& GetChargeGaugeNonFullColor() const { return x11c_chargeGaugeNonFullColor; } + atUint32 GetChargeTickCount() const { return x120_chargeTickCount; } + float GetChargeTickAnglePitch() const { return x124_chargeTickAnglePitch; } + float GetLockFireScale() const { return x128_lockFireScale; } + float GetLockFireDuration() const { return x12c_lockFireDuration; } + const zeus::CColor& GetLockFireColor() const { return x130_lockFireColor; } + float GetLockDaggerScaleStart() const { return x134_lockDaggerScaleStart; } + float GetLockDaggerScaleEnd() const { return x138_lockDaggerScaleEnd; } + const zeus::CColor& GetLockDaggerColor() const { return x13c_lockDaggerColor; } + float GetLockDaggerAngle0() const { return x140_lockDaggerAngle0; } + float GetLockDaggerAngle1() const { return x144_lockDaggerAngle1; } + float GetLockDaggerAngle2() const { return x148_lockDaggerAngle2; } + const zeus::CColor& GetLockConfirmColor() const { return x14c_lockConfirmColor; } + const zeus::CColor& GetSeekerColor() const { return x150_seekerColor; } + float GetLockConfirmClampMin() const { return x154_lockConfirmClampMin; } + float GetLockConfirmClampMax() const { return x158_lockConfirmClampMax; } + float GetTargetFlowerClampMin() const { return x15c_targetFlowerClampMin; } + float GetTargetFlowerClampMax() const { return x160_targetFlowerClampMax; } + float GetSeekerClampMin() const { return x164_seekerClampMin; } + float GetSeekerClampMax() const { return x168_seekerClampMax; } + float GetMissileBracketClampMin() const { return x16c_missileBracketClampMin; } + float GetMissileBracketClampMax() const { return x170_missileBracketClampMax; } + float GetInnerBeamClampMin() const { return x174_innerBeamClampMin; } + float GetInnerBeamClampMax() const { return x178_innerBeamClampMax; } + float GetChargeGaugeClampMin() const { return x17c_chargeGaugeClampMin; } + float GetChargeGaugeClampMax() const { return x180_chargeGaugeClampMax; } + float GetLockFireClampMin() const { return x184_lockFireClampMin; } + float GetLockFireClampMax() const { return x188_lockFireClampMax; } + float GetLockDaggerClampMin() const { return x18c_lockDaggerClampMin; } + float GetLockDaggerClampMax() const { return x190_lockDaggerClampMax; } + float GetGrappleSelectScale() const { return x194_grappleSelectScale; } + float GetGrappleScale() const { return x198_grappleScale; } + float GetGrappleClampMin() const { return x19c_grappleClampMin; } + float GetGrappleClampMax() const { return x1a0_grappleClampMax; } + const zeus::CColor& GetGrapplePointSelectColor() const { return x1a4_grapplePointSelectColor; } + const zeus::CColor& GetGrapplePointColor() const { return x1a8_grapplePointColor; } + const zeus::CColor& GetLockedGrapplePointSelectColor() const { return x1ac_lockedGrapplePointSelectColor; } + float GetGrappleMinClampScale() const { return x1b0_grappleMinClampScale; } + const zeus::CColor& GetChargeGaugePulseColorHigh() const { return x1b4_chargeGaugePulseColorHigh; } + float GetFullChargeFadeDuration() const { return x1b8_fullChargeFadeDuration; } + const zeus::CColor& GetOrbitPointColor() const { return x1bc_orbitPointColor; } + const zeus::CColor& GetCrosshairsColor() const { return x1c0_crosshairsColor; } + float GetCrosshairsScaleDuration() const { return x1c4_crosshairsScaleDur; } + bool DrawOrbitPoint() const { return x1c8_drawOrbitPoint; } + const zeus::CColor& GetChargeGaugePulseColorLow() const { return x1cc_chargeGaugePulseColorLow; } + float GetChargeGaugePulsePeriod() const { return x1d0_chargeGaugePulsePeriod; } + float GetReticuleClampMin() const { return x20c_reticuleClampMin; } + float GetReticuleClampMax() const { return x210_reticuleClampMax; } + const zeus::CColor& GetXRayRetRingColor() const { return x214_xrayRetRingColor; } + float GetReticuleScale() const { return x218_reticuleScale; } + float GetScanTargetClampMin() const { return x21c_scanTargetClampMin; } + float GetScanTargetClampMax() const { return x220_scanTargetClampMax; } + float GetAngularLagSpeed() const { return x224_angularLagSpeed; } }; -} +} // namespace DataSpec::DNAMP1 diff --git a/DataSpec/DNAMP2/AFSM.hpp b/DataSpec/DNAMP2/AFSM.hpp index d106d908e..174b89611 100644 --- a/DataSpec/DNAMP2/AFSM.hpp +++ b/DataSpec/DNAMP2/AFSM.hpp @@ -2,7 +2,6 @@ #include "../DNAMP1/AFSM.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { using AFSM = DNAMP1::AFSM; } diff --git a/DataSpec/DNAMP2/AGSC.cpp b/DataSpec/DNAMP2/AGSC.cpp index 699fb45ab..152721e92 100644 --- a/DataSpec/DNAMP2/AGSC.cpp +++ b/DataSpec/DNAMP2/AGSC.cpp @@ -2,83 +2,80 @@ #include "amuse/AudioGroup.hpp" #include "amuse/AudioGroupData.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -bool AGSC::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& dir) -{ - dir.makeDirChain(true); +bool AGSC::Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& dir) { + dir.makeDirChain(true); - Header head; - head.read(rs); + Header head; + head.read(rs); - auto pool = rs.readUBytes(head.poolSz); - auto proj = rs.readUBytes(head.projSz); - auto sdir = rs.readUBytes(head.sdirSz); - auto samp = rs.readUBytes(head.sampSz); + auto pool = rs.readUBytes(head.poolSz); + auto proj = rs.readUBytes(head.projSz); + auto sdir = rs.readUBytes(head.sdirSz); + auto samp = rs.readUBytes(head.sampSz); - amuse::AudioGroupData data(proj.get(), head.projSz, pool.get(), head.poolSz, - sdir.get(), head.sdirSz, samp.get(), head.sampSz, amuse::GCNDataTag{}); + amuse::AudioGroupData data(proj.get(), head.projSz, pool.get(), head.poolSz, sdir.get(), head.sdirSz, samp.get(), + head.sampSz, amuse::GCNDataTag{}); - /* Load into amuse representation */ - amuse::ProjectDatabase projDb; - projDb.setIdDatabases(); - amuse::AudioGroupDatabase group(data); - group.setGroupPath(dir.getAbsolutePath()); + /* Load into amuse representation */ + amuse::ProjectDatabase projDb; + projDb.setIdDatabases(); + amuse::AudioGroupDatabase group(data); + group.setGroupPath(dir.getAbsolutePath()); - /* Extract samples */ - group.getSdir().extractAllCompressed(dir.getAbsolutePath(), data.getSamp()); + /* Extract samples */ + group.getSdir().extractAllCompressed(dir.getAbsolutePath(), data.getSamp()); - /* Write out project/pool */ - { - auto projd = group.getProj().toYAML(); - athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!project.yaml")).getAbsolutePath()); - if (fo.hasError()) - return false; - fo.writeUBytes(projd.data(), projd.size()); - } + /* Write out project/pool */ + { + auto projd = group.getProj().toYAML(); + athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!project.yaml")).getAbsolutePath()); + if (fo.hasError()) + return false; + fo.writeUBytes(projd.data(), projd.size()); + } - { - auto poold = group.getPool().toYAML(); - athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!pool.yaml")).getAbsolutePath()); - if (fo.hasError()) - return false; - fo.writeUBytes(poold.data(), poold.size()); - } + { + auto poold = group.getPool().toYAML(); + athena::io::FileWriter fo(hecl::ProjectPath(dir, _SYS_STR("!pool.yaml")).getAbsolutePath()); + if (fo.hasError()) + return false; + fo.writeUBytes(poold.data(), poold.size()); + } - return true; + return true; } -bool AGSC::Cook(const hecl::ProjectPath& dir, const hecl::ProjectPath& outPath) -{ - athena::io::FileWriter w(outPath.getAbsolutePath()); - if (w.hasError()) - return false; +bool AGSC::Cook(const hecl::ProjectPath& dir, const hecl::ProjectPath& outPath) { + athena::io::FileWriter w(outPath.getAbsolutePath()); + if (w.hasError()) + return false; - amuse::ProjectDatabase projDb; - projDb.setIdDatabases(); - amuse::AudioGroupDatabase group(dir.getAbsolutePath()); + amuse::ProjectDatabase projDb; + projDb.setIdDatabases(); + amuse::AudioGroupDatabase group(dir.getAbsolutePath()); - auto proj = group.getProj().toGCNData(group.getPool(), group.getSdir()); - auto pool = group.getPool().toData(); - auto sdirSamp = group.getSdir().toGCNData(group); + auto proj = group.getProj().toGCNData(group.getPool(), group.getSdir()); + auto pool = group.getPool().toData(); + auto sdirSamp = group.getSdir().toGCNData(group); - Header head; - head.groupName = dir.getLastComponentUTF8(); - for (const auto& p : group.getProj().sfxGroups()) - head.groupId = p.first.id; - head.poolSz = pool.size(); - head.projSz = proj.size(); - head.sdirSz = sdirSamp.first.size(); - head.sampSz = sdirSamp.second.size(); - head.write(w); + Header head; + head.groupName = dir.getLastComponentUTF8(); + for (const auto& p : group.getProj().sfxGroups()) + head.groupId = p.first.id; + head.poolSz = pool.size(); + head.projSz = proj.size(); + head.sdirSz = sdirSamp.first.size(); + head.sampSz = sdirSamp.second.size(); + head.write(w); - w.writeUBytes(pool.data(), pool.size()); - w.writeUBytes(proj.data(), proj.size()); - w.writeUBytes(sdirSamp.first.data(), sdirSamp.first.size()); - w.writeUBytes(sdirSamp.second.data(), sdirSamp.second.size()); + w.writeUBytes(pool.data(), pool.size()); + w.writeUBytes(proj.data(), proj.size()); + w.writeUBytes(sdirSamp.first.data(), sdirSamp.first.size()); + w.writeUBytes(sdirSamp.second.data(), sdirSamp.second.size()); - return true; + return true; } -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/AGSC.hpp b/DataSpec/DNAMP2/AGSC.hpp index 9b57f9961..215b44126 100644 --- a/DataSpec/DNAMP2/AGSC.hpp +++ b/DataSpec/DNAMP2/AGSC.hpp @@ -3,26 +3,22 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DNAMP2.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -class AGSC -{ +class AGSC { public: - struct Header : BigDNA - { - AT_DECL_DNA - Value unk; - String<-1> groupName; - Value groupId = -1; - Value poolSz = 0; - Value projSz = 0; - Value sdirSz = 0; - Value sampSz = 0; - }; - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath); + struct Header : BigDNA { + AT_DECL_DNA + Value unk; + String<-1> groupName; + Value groupId = -1; + Value poolSz = 0; + Value projSz = 0; + Value sdirSz = 0; + Value sampSz = 0; + }; + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath); + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath); }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/ANCS.cpp b/DataSpec/DNAMP2/ANCS.cpp index 233a89561..dff5c519f 100644 --- a/DataSpec/DNAMP2/ANCS.cpp +++ b/DataSpec/DNAMP2/ANCS.cpp @@ -1,605 +1,545 @@ #include "ANCS.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(typename Read::StreamT& reader) -{ - idx = reader.readUint32Big(); - atUint16 sectionCount = reader.readUint16Big(); - name = reader.readString(); - cmdl.read(reader); - cskr.read(reader); - cinf.read(reader); +void ANCS::CharacterSet::CharacterInfo::Enumerate(typename Read::StreamT& reader) { + idx = reader.readUint32Big(); + atUint16 sectionCount = reader.readUint16Big(); + name = reader.readString(); + cmdl.read(reader); + cskr.read(reader); + cinf.read(reader); - atUint32 animationCount = reader.readUint32Big(); - reader.enumerate(animations, animationCount); + atUint32 animationCount = reader.readUint32Big(); + reader.enumerate(animations, animationCount); - pasDatabase.read(reader); + pasDatabase.read(reader); - atUint32 partCount = reader.readUint32Big(); - reader.enumerate(partResData.part, partCount); + atUint32 partCount = reader.readUint32Big(); + reader.enumerate(partResData.part, partCount); - atUint32 swhcCount = reader.readUint32Big(); - reader.enumerate(partResData.swhc, swhcCount); + atUint32 swhcCount = reader.readUint32Big(); + reader.enumerate(partResData.swhc, swhcCount); - atUint32 unkCount = reader.readUint32Big(); - reader.enumerate(partResData.unk, unkCount); + atUint32 unkCount = reader.readUint32Big(); + reader.enumerate(partResData.unk, unkCount); - atUint32 elscCount = reader.readUint32Big(); - reader.enumerate(partResData.elsc, elscCount); + atUint32 elscCount = reader.readUint32Big(); + reader.enumerate(partResData.elsc, elscCount); - atUint32 spscCount = reader.readUint32Big(); - reader.enumerate(partResData.spsc, spscCount); + atUint32 spscCount = reader.readUint32Big(); + reader.enumerate(partResData.spsc, spscCount); - atUint32 unkCount2 = reader.readUint32Big(); - if (unkCount2) - abort(); - reader.enumerate(partResData.unk2, unkCount2); + atUint32 unkCount2 = reader.readUint32Big(); + if (unkCount2) + abort(); + reader.enumerate(partResData.unk2, unkCount2); - unk1 = reader.readUint32Big(); + unk1 = reader.readUint32Big(); - animAABBs.clear(); - if (sectionCount > 1) - { - atUint32 aabbCount = reader.readUint32Big(); - reader.enumerate(animAABBs, aabbCount); - } + animAABBs.clear(); + if (sectionCount > 1) { + atUint32 aabbCount = reader.readUint32Big(); + reader.enumerate(animAABBs, aabbCount); + } - effects.clear(); - if (sectionCount > 2) - { - atUint32 effectCount = reader.readUint32Big(); - reader.enumerate(effects, effectCount); - } + effects.clear(); + if (sectionCount > 2) { + atUint32 effectCount = reader.readUint32Big(); + reader.enumerate(effects, effectCount); + } - if (sectionCount > 3) - { - cmdlIce.read(reader); - cskrIce.read(reader); - } + if (sectionCount > 3) { + cmdlIce.read(reader); + cskrIce.read(reader); + } - animIdxs.clear(); - if (sectionCount > 4) - { - atUint32 aidxCount = reader.readUint32Big(); - reader.enumerateBig(animIdxs, aidxCount); - } + animIdxs.clear(); + if (sectionCount > 4) { + atUint32 aidxCount = reader.readUint32Big(); + reader.enumerateBig(animIdxs, aidxCount); + } - extents.clear(); - if (sectionCount > 9) - { - unk4 = reader.readUint32Big(); - unk5 = reader.readUByte(); - atUint32 extentsCount = reader.readUint32Big(); - reader.enumerate(extents, extentsCount); - } + extents.clear(); + if (sectionCount > 9) { + unk4 = reader.readUint32Big(); + unk5 = reader.readUByte(); + atUint32 extentsCount = reader.readUint32Big(); + reader.enumerate(extents, extentsCount); + } } template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(typename Write::StreamT& writer) -{ - writer.writeUint32Big(idx); +void ANCS::CharacterSet::CharacterInfo::Enumerate(typename Write::StreamT& writer) { + writer.writeUint32Big(idx); - atUint16 sectionCount; - if (unk4 || unk5 || extents.size()) - sectionCount = 10; - else if (partResData.elsc.size()) - sectionCount = 6; - else if (animIdxs.size()) - sectionCount = 5; - else if (cmdlIce) - sectionCount = 4; - else if (effects.size()) - sectionCount = 3; - else if (animAABBs.size()) - sectionCount = 2; - else - sectionCount = 1; - writer.writeUint16Big(sectionCount); + atUint16 sectionCount; + if (unk4 || unk5 || extents.size()) + sectionCount = 10; + else if (partResData.elsc.size()) + sectionCount = 6; + else if (animIdxs.size()) + sectionCount = 5; + else if (cmdlIce) + sectionCount = 4; + else if (effects.size()) + sectionCount = 3; + else if (animAABBs.size()) + sectionCount = 2; + else + sectionCount = 1; + writer.writeUint16Big(sectionCount); - writer.writeString(name); - cmdl.write(writer); - cskr.write(writer); - cinf.write(writer); + writer.writeString(name); + cmdl.write(writer); + cskr.write(writer); + cinf.write(writer); - writer.writeUint32Big(animations.size()); - writer.enumerate(animations); + writer.writeUint32Big(animations.size()); + writer.enumerate(animations); - pasDatabase.write(writer); + pasDatabase.write(writer); - writer.writeUint32Big(partResData.part.size()); - writer.enumerate(partResData.part); + writer.writeUint32Big(partResData.part.size()); + writer.enumerate(partResData.part); - writer.writeUint32Big(partResData.swhc.size()); - writer.enumerate(partResData.swhc); + writer.writeUint32Big(partResData.swhc.size()); + writer.enumerate(partResData.swhc); - writer.writeUint32Big(partResData.unk.size()); - writer.enumerate(partResData.unk); + writer.writeUint32Big(partResData.unk.size()); + writer.enumerate(partResData.unk); - writer.writeUint32Big(partResData.elsc.size()); - writer.enumerate(partResData.elsc); + writer.writeUint32Big(partResData.elsc.size()); + writer.enumerate(partResData.elsc); - writer.writeUint32Big(partResData.spsc.size()); - writer.enumerate(partResData.spsc); + writer.writeUint32Big(partResData.spsc.size()); + writer.enumerate(partResData.spsc); - writer.writeUint32Big(partResData.unk2.size()); - writer.enumerate(partResData.unk2); + writer.writeUint32Big(partResData.unk2.size()); + writer.enumerate(partResData.unk2); - writer.writeUint32Big(unk1); + writer.writeUint32Big(unk1); - if (sectionCount > 1) - { - writer.writeUint32Big(animAABBs.size()); - writer.enumerate(animAABBs); - } + if (sectionCount > 1) { + writer.writeUint32Big(animAABBs.size()); + writer.enumerate(animAABBs); + } - if (sectionCount > 2) - { - writer.writeUint32Big(effects.size()); - writer.enumerate(effects); - } + if (sectionCount > 2) { + writer.writeUint32Big(effects.size()); + writer.enumerate(effects); + } - if (sectionCount > 3) - { - cmdlIce.write(writer); - cskrIce.write(writer); - } + if (sectionCount > 3) { + cmdlIce.write(writer); + cskrIce.write(writer); + } - if (sectionCount > 4) - { - writer.writeUint32Big(animIdxs.size()); - for (atUint32 idx : animIdxs) - writer.writeUint32Big(idx); - } + if (sectionCount > 4) { + writer.writeUint32Big(animIdxs.size()); + for (atUint32 idx : animIdxs) + writer.writeUint32Big(idx); + } - if (sectionCount > 9) - { - writer.writeUint32Big(unk4); - writer.writeUByte(unk5); - writer.writeUint32Big(extents.size()); - writer.enumerate(extents); - } + if (sectionCount > 9) { + writer.writeUint32Big(unk4); + writer.writeUByte(unk5); + writer.writeUint32Big(extents.size()); + writer.enumerate(extents); + } } template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(typename BinarySize::StreamT& s) -{ - atUint16 sectionCount; - if (unk4 || unk5 || extents.size()) - sectionCount = 10; - else if (partResData.elsc.size()) - sectionCount = 6; - else if (animIdxs.size()) - sectionCount = 5; - else if (cmdlIce) - sectionCount = 4; - else if (effects.size()) - sectionCount = 3; - else if (animAABBs.size()) - sectionCount = 2; - else - sectionCount = 1; +void ANCS::CharacterSet::CharacterInfo::Enumerate(typename BinarySize::StreamT& s) { + atUint16 sectionCount; + if (unk4 || unk5 || extents.size()) + sectionCount = 10; + else if (partResData.elsc.size()) + sectionCount = 6; + else if (animIdxs.size()) + sectionCount = 5; + else if (cmdlIce) + sectionCount = 4; + else if (effects.size()) + sectionCount = 3; + else if (animAABBs.size()) + sectionCount = 2; + else + sectionCount = 1; - s += 6; + s += 6; - s += name.size() + 1; - s += 12; + s += name.size() + 1; + s += 12; + s += 4; + for (const Animation& anim : animations) + anim.binarySize(s); + + pasDatabase.binarySize(s); + + s += 4; + for (const UniqueID32& id : partResData.part) + id.binarySize(s); + + s += 4; + for (const UniqueID32& id : partResData.swhc) + id.binarySize(s); + + s += 4; + for (const UniqueID32& id : partResData.unk) + id.binarySize(s); + + s += 4; + for (const UniqueID32& id : partResData.elsc) + id.binarySize(s); + + s += 4; + for (const UniqueID32& id : partResData.spsc) + id.binarySize(s); + + s += 4; + for (const UniqueID32& id : partResData.unk2) + id.binarySize(s); + + s += 4; + + if (sectionCount > 1) { s += 4; - for (const Animation& anim : animations) - anim.binarySize(s); - - pasDatabase.binarySize(s); + for (const MP1CharacterInfo::ActionAABB& aabb : animAABBs) + aabb.binarySize(s); + } + if (sectionCount > 2) { s += 4; - for (const UniqueID32& id : partResData.part) - id.binarySize(s); + for (const Effect& e : effects) + e.binarySize(s); + } - s += 4; - for (const UniqueID32& id : partResData.swhc) - id.binarySize(s); + if (sectionCount > 3) + s += 8; - s += 4; - for (const UniqueID32& id : partResData.unk) - id.binarySize(s); + if (sectionCount > 4) + s += 4 + animIdxs.size() * 4; - s += 4; - for (const UniqueID32& id : partResData.elsc) - id.binarySize(s); - - s += 4; - for (const UniqueID32& id : partResData.spsc) - id.binarySize(s); - - s += 4; - for (const UniqueID32& id : partResData.unk2) - id.binarySize(s); - - s += 4; - - if (sectionCount > 1) - { - s += 4; - for (const MP1CharacterInfo::ActionAABB& aabb : animAABBs) - aabb.binarySize(s); - } - - if (sectionCount > 2) - { - s += 4; - for (const Effect& e : effects) - e.binarySize(s); - } - - if (sectionCount > 3) - s += 8; - - if (sectionCount > 4) - s += 4 + animIdxs.size() * 4; - - if (sectionCount > 9) - { - s += 9; - for (const Extents& e : extents) - e.binarySize(s); - } + if (sectionCount > 9) { + s += 9; + for (const Extents& e : extents) + e.binarySize(s); + } } template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(typename ReadYaml::StreamT& reader) -{ - idx = reader.readUint32("idx"); - atUint16 sectionCount = reader.readUint16("sectionCount"); - name = reader.readString("name"); +void ANCS::CharacterSet::CharacterInfo::Enumerate(typename ReadYaml::StreamT& reader) { + idx = reader.readUint32("idx"); + atUint16 sectionCount = reader.readUint16("sectionCount"); + name = reader.readString("name"); - reader.enumerate("animations", animations); + reader.enumerate("animations", animations); - reader.enumerate("pasDatabase", pasDatabase); + reader.enumerate("pasDatabase", pasDatabase); - reader.enumerate("part", partResData.part); + reader.enumerate("part", partResData.part); - reader.enumerate("swhc", partResData.swhc); + reader.enumerate("swhc", partResData.swhc); - reader.enumerate("unk", partResData.unk); + reader.enumerate("unk", partResData.unk); - reader.enumerate("elsc", partResData.elsc); + reader.enumerate("elsc", partResData.elsc); - reader.enumerate("spsc", partResData.spsc); + reader.enumerate("spsc", partResData.spsc); - reader.enumerate("unk2", partResData.unk2); + reader.enumerate("unk2", partResData.unk2); - unk1 = reader.readUint32("unk1"); + unk1 = reader.readUint32("unk1"); - animAABBs.clear(); - if (sectionCount > 1) - { - reader.enumerate("part", animAABBs); - } + animAABBs.clear(); + if (sectionCount > 1) { + reader.enumerate("part", animAABBs); + } - effects.clear(); - if (sectionCount > 2) - { - reader.enumerate("effects", effects); - } + effects.clear(); + if (sectionCount > 2) { + reader.enumerate("effects", effects); + } - if (sectionCount > 3) - { - reader.enumerate("cmdlIce", cmdlIce); - } + if (sectionCount > 3) { + reader.enumerate("cmdlIce", cmdlIce); + } - animIdxs.clear(); - if (sectionCount > 4) - { - reader.enumerate("animIdxs", animIdxs); - } + animIdxs.clear(); + if (sectionCount > 4) { + reader.enumerate("animIdxs", animIdxs); + } - extents.clear(); - if (sectionCount > 9) - { - unk4 = reader.readUint32("unk4"); - unk5 = reader.readUByte("unk5"); - reader.enumerate("extents", extents); - } + extents.clear(); + if (sectionCount > 9) { + unk4 = reader.readUint32("unk4"); + unk5 = reader.readUByte("unk5"); + reader.enumerate("extents", extents); + } } template <> -void ANCS::CharacterSet::CharacterInfo::Enumerate(typename WriteYaml::StreamT& writer) -{ - writer.writeUint32("idx", idx); +void ANCS::CharacterSet::CharacterInfo::Enumerate(typename WriteYaml::StreamT& writer) { + writer.writeUint32("idx", idx); - atUint16 sectionCount; - if (unk4 || unk5 || extents.size()) - sectionCount = 10; - else if (partResData.elsc.size()) - sectionCount = 6; - else if (animIdxs.size()) - sectionCount = 5; - else if (cmdlIce) - sectionCount = 4; - else if (effects.size()) - sectionCount = 3; - else if (animAABBs.size()) - sectionCount = 2; - else - sectionCount = 1; - writer.writeUint16("sectionCount", sectionCount); + atUint16 sectionCount; + if (unk4 || unk5 || extents.size()) + sectionCount = 10; + else if (partResData.elsc.size()) + sectionCount = 6; + else if (animIdxs.size()) + sectionCount = 5; + else if (cmdlIce) + sectionCount = 4; + else if (effects.size()) + sectionCount = 3; + else if (animAABBs.size()) + sectionCount = 2; + else + sectionCount = 1; + writer.writeUint16("sectionCount", sectionCount); - writer.writeString("name", name); - writer.enumerate("cmdl", cmdl); + writer.writeString("name", name); + writer.enumerate("cmdl", cmdl); - writer.enumerate("animations", animations); + writer.enumerate("animations", animations); - writer.enumerate("pasDatabase", pasDatabase); + writer.enumerate("pasDatabase", pasDatabase); - writer.enumerate("part", partResData.part); + writer.enumerate("part", partResData.part); - writer.enumerate("swhc", partResData.swhc); + writer.enumerate("swhc", partResData.swhc); - writer.enumerate("unk", partResData.unk); + writer.enumerate("unk", partResData.unk); - writer.enumerate("elsc", partResData.elsc); + writer.enumerate("elsc", partResData.elsc); - writer.enumerate("spsc", partResData.spsc); + writer.enumerate("spsc", partResData.spsc); - writer.enumerate("unk2", partResData.unk2); + writer.enumerate("unk2", partResData.unk2); - writer.writeUint32("unk1", unk1); + writer.writeUint32("unk1", unk1); - if (sectionCount > 1) - { - writer.enumerate("animAABBs", animAABBs); - } + if (sectionCount > 1) { + writer.enumerate("animAABBs", animAABBs); + } - if (sectionCount > 2) - { - writer.enumerate("effects", effects); - } + if (sectionCount > 2) { + writer.enumerate("effects", effects); + } - if (sectionCount > 3) - { - writer.enumerate("cmdlIce", cmdlIce); - } + if (sectionCount > 3) { + writer.enumerate("cmdlIce", cmdlIce); + } - if (sectionCount > 4) - { - writer.enumerate("animIdxs", animIdxs); - } + if (sectionCount > 4) { + writer.enumerate("animIdxs", animIdxs); + } - if (sectionCount > 9) - { - writer.writeUint32("unk4", unk4); - writer.writeUByte("unk5", unk5); - writer.enumerate("extents", extents); - } + if (sectionCount > 9) { + writer.writeUint32("unk4", unk4); + writer.writeUByte("unk5", unk5); + writer.enumerate("extents", extents); + } } -const char* ANCS::CharacterSet::CharacterInfo::DNAType() -{ - return "urde::DNAMP2::ANCS::CharacterSet::CharacterInfo"; +const char* ANCS::CharacterSet::CharacterInfo::DNAType() { return "urde::DNAMP2::ANCS::CharacterSet::CharacterInfo"; } + +template <> +void ANCS::AnimationSet::Enumerate(typename Read::StreamT& reader) { + atUint16 sectionCount = reader.readUint16Big(); + + atUint32 animationCount = reader.readUint32Big(); + reader.enumerate(animations, animationCount); + + atUint32 transitionCount = reader.readUint32Big(); + reader.enumerate(transitions, transitionCount); + defaultTransition.read(reader); + + additiveAnims.clear(); + if (sectionCount > 1) { + atUint32 additiveAnimCount = reader.readUint32Big(); + reader.enumerate(additiveAnims, additiveAnimCount); + floatA = reader.readFloatBig(); + floatB = reader.readFloatBig(); + } + + halfTransitions.clear(); + if (sectionCount > 2) { + atUint32 halfTransitionCount = reader.readUint32Big(); + reader.enumerate(halfTransitions, halfTransitionCount); + } + + evnts.clear(); + if (sectionCount > 3) { + atUint32 evntsCount = reader.readUint32Big(); + reader.enumerate(evnts, evntsCount); + } } template <> -void ANCS::AnimationSet::Enumerate(typename Read::StreamT& reader) -{ - atUint16 sectionCount = reader.readUint16Big(); +void ANCS::AnimationSet::Enumerate(typename Write::StreamT& writer) { + atUint16 sectionCount; + if (evnts.size()) + sectionCount = 4; + else if (halfTransitions.size()) + sectionCount = 3; + else if (additiveAnims.size()) + sectionCount = 2; + else + sectionCount = 1; - atUint32 animationCount = reader.readUint32Big(); - reader.enumerate(animations, animationCount); + writer.writeUint16Big(sectionCount); - atUint32 transitionCount = reader.readUint32Big(); - reader.enumerate(transitions, transitionCount); - defaultTransition.read(reader); + writer.writeUint32Big(animations.size()); + writer.enumerate(animations); - additiveAnims.clear(); - if (sectionCount > 1) - { - atUint32 additiveAnimCount = reader.readUint32Big(); - reader.enumerate(additiveAnims, additiveAnimCount); - floatA = reader.readFloatBig(); - floatB = reader.readFloatBig(); - } + writer.writeUint32Big(transitions.size()); + writer.enumerate(transitions); + defaultTransition.write(writer); - halfTransitions.clear(); - if (sectionCount > 2) - { - atUint32 halfTransitionCount = reader.readUint32Big(); - reader.enumerate(halfTransitions, halfTransitionCount); - } + if (sectionCount > 1) { + writer.writeUint32Big(additiveAnims.size()); + writer.enumerate(additiveAnims); + writer.writeFloatBig(floatA); + writer.writeFloatBig(floatB); + } - evnts.clear(); - if (sectionCount > 3) - { - atUint32 evntsCount = reader.readUint32Big(); - reader.enumerate(evnts, evntsCount); - } + if (sectionCount > 2) { + writer.writeUint32Big(halfTransitions.size()); + writer.enumerate(halfTransitions); + } + + if (sectionCount > 3) { + writer.writeUint32Big(evnts.size()); + writer.enumerate(evnts); + } } template <> -void ANCS::AnimationSet::Enumerate(typename Write::StreamT& writer) -{ - atUint16 sectionCount; - if (evnts.size()) - sectionCount = 4; - else if (halfTransitions.size()) - sectionCount = 3; - else if (additiveAnims.size()) - sectionCount = 2; - else - sectionCount = 1; +void ANCS::AnimationSet::Enumerate(typename BinarySize::StreamT& s) { + atUint16 sectionCount; + if (evnts.size()) + sectionCount = 4; + else if (halfTransitions.size()) + sectionCount = 3; + else if (additiveAnims.size()) + sectionCount = 2; + else + sectionCount = 1; - writer.writeUint16Big(sectionCount); + s += 6; + for (const MP1AnimationSet::Animation& anim : animations) + anim.binarySize(s); - writer.writeUint32Big(animations.size()); - writer.enumerate(animations); - - writer.writeUint32Big(transitions.size()); - writer.enumerate(transitions); - defaultTransition.write(writer); - - if (sectionCount > 1) - { - writer.writeUint32Big(additiveAnims.size()); - writer.enumerate(additiveAnims); - writer.writeFloatBig(floatA); - writer.writeFloatBig(floatB); - } - - if (sectionCount > 2) - { - writer.writeUint32Big(halfTransitions.size()); - writer.enumerate(halfTransitions); - } - - if (sectionCount > 3) - { - writer.writeUint32Big(evnts.size()); - writer.enumerate(evnts); - } -} - -template <> -void ANCS::AnimationSet::Enumerate(typename BinarySize::StreamT& s) -{ - atUint16 sectionCount; - if (evnts.size()) - sectionCount = 4; - else if (halfTransitions.size()) - sectionCount = 3; - else if (additiveAnims.size()) - sectionCount = 2; - else - sectionCount = 1; - - s += 6; - for (const MP1AnimationSet::Animation& anim : animations) - anim.binarySize(s); + s += 4; + for (const MP1AnimationSet::Transition& trans : transitions) + trans.binarySize(s); + defaultTransition.binarySize(s); + if (sectionCount > 1) { s += 4; - for (const MP1AnimationSet::Transition& trans : transitions) - trans.binarySize(s); - defaultTransition.binarySize(s); + for (const MP1AnimationSet::AdditiveAnimationInfo& aaInfo : additiveAnims) + aaInfo.binarySize(s); + s += 8; + } - if (sectionCount > 1) - { - s += 4; - for (const MP1AnimationSet::AdditiveAnimationInfo& aaInfo : additiveAnims) - aaInfo.binarySize(s); - s += 8; - } + if (sectionCount > 2) { + s += 4; + for (const MP1AnimationSet::HalfTransition& ht : halfTransitions) + ht.binarySize(s); + } - if (sectionCount > 2) - { - s += 4; - for (const MP1AnimationSet::HalfTransition& ht : halfTransitions) - ht.binarySize(s); - } - - if (sectionCount > 3) - { - s += 4; - for (const EVNT& evnt : evnts) - evnt.binarySize(s); - } + if (sectionCount > 3) { + s += 4; + for (const EVNT& evnt : evnts) + evnt.binarySize(s); + } } template <> -void ANCS::AnimationSet::Enumerate(typename ReadYaml::StreamT& reader) -{ - atUint16 sectionCount = reader.readUint16("sectionCount"); +void ANCS::AnimationSet::Enumerate(typename ReadYaml::StreamT& reader) { + atUint16 sectionCount = reader.readUint16("sectionCount"); - reader.enumerate("animations", animations); + reader.enumerate("animations", animations); - reader.enumerate("transitions", transitions); - reader.enumerate("defaultTransition", defaultTransition); + reader.enumerate("transitions", transitions); + reader.enumerate("defaultTransition", defaultTransition); - additiveAnims.clear(); - if (sectionCount > 1) - { - reader.enumerate("additiveAnims", additiveAnims); - floatA = reader.readFloat("floatA"); - floatB = reader.readFloat("floatB"); - } + additiveAnims.clear(); + if (sectionCount > 1) { + reader.enumerate("additiveAnims", additiveAnims); + floatA = reader.readFloat("floatA"); + floatB = reader.readFloat("floatB"); + } - halfTransitions.clear(); - if (sectionCount > 2) - { - reader.enumerate("halfTransitions", halfTransitions); - } + halfTransitions.clear(); + if (sectionCount > 2) { + reader.enumerate("halfTransitions", halfTransitions); + } - evnts.clear(); - if (sectionCount > 3) - { - reader.enumerate("evnts", evnts); - } + evnts.clear(); + if (sectionCount > 3) { + reader.enumerate("evnts", evnts); + } } template <> -void ANCS::AnimationSet::Enumerate(typename WriteYaml::StreamT& writer) -{ - atUint16 sectionCount; - if (evnts.size()) - sectionCount = 4; - else if (halfTransitions.size()) - sectionCount = 3; - else if (additiveAnims.size()) - sectionCount = 2; - else - sectionCount = 1; +void ANCS::AnimationSet::Enumerate(typename WriteYaml::StreamT& writer) { + atUint16 sectionCount; + if (evnts.size()) + sectionCount = 4; + else if (halfTransitions.size()) + sectionCount = 3; + else if (additiveAnims.size()) + sectionCount = 2; + else + sectionCount = 1; - writer.writeUint16("sectionCount", sectionCount); + writer.writeUint16("sectionCount", sectionCount); - writer.enumerate("animations", animations); + writer.enumerate("animations", animations); - writer.enumerate("transitions", transitions); - writer.enumerate("defaultTransition", defaultTransition); + writer.enumerate("transitions", transitions); + writer.enumerate("defaultTransition", defaultTransition); - if (sectionCount > 1) - { - writer.enumerate("additiveAnims", additiveAnims); - writer.writeFloat("floatA", floatA); - writer.writeFloat("floatB", floatB); - } + if (sectionCount > 1) { + writer.enumerate("additiveAnims", additiveAnims); + writer.writeFloat("floatA", floatA); + writer.writeFloat("floatB", floatB); + } - if (sectionCount > 2) - { - writer.enumerate("halfTransitions", halfTransitions); - } + if (sectionCount > 2) { + writer.enumerate("halfTransitions", halfTransitions); + } - if (sectionCount > 3) - { - writer.enumerate("evnts", evnts); - } + if (sectionCount > 3) { + writer.enumerate("evnts", evnts); + } } -const char* ANCS::AnimationSet::DNAType() -{ - return "urde::DNAMP2::ANCS::AnimationSet"; -} +const char* ANCS::AnimationSet::DNAType() { return "urde::DNAMP2::ANCS::AnimationSet"; } template -void ANCS::AnimationSet::EVNT::Enumerate(typename Op::StreamT& s) -{ - Do({"version"}, version, s); - DoSize({"loopEventCount"}, loopEventCount, s); - Do({"loopEvents"}, loopEvents, loopEventCount, s); - if (version == 2) - { - DoSize({"uevtEventCount"}, uevtEventCount, s); - Do({"uevtEvents"}, uevtEvents, uevtEventCount, s); - } - DoSize({"effectEventCount"}, effectEventCount, s); - Do({"effectEvents"}, effectEvents, effectEventCount, s); - DoSize({"sfxEventCount"}, sfxEventCount, s); - Do({"sfxEvents"}, sfxEvents, sfxEventCount, s); +void ANCS::AnimationSet::EVNT::Enumerate(typename Op::StreamT& s) { + Do({"version"}, version, s); + DoSize({"loopEventCount"}, loopEventCount, s); + Do({"loopEvents"}, loopEvents, loopEventCount, s); + if (version == 2) { + DoSize({"uevtEventCount"}, uevtEventCount, s); + Do({"uevtEvents"}, uevtEvents, uevtEventCount, s); + } + DoSize({"effectEventCount"}, effectEventCount, s); + Do({"effectEvents"}, effectEvents, effectEventCount, s); + DoSize({"sfxEventCount"}, sfxEventCount, s); + Do({"sfxEvents"}, sfxEvents, sfxEventCount, s); } AT_SPECIALIZE_DNA(ANCS::AnimationSet::EVNT) -const char* ANCS::AnimationSet::EVNT::DNAType() -{ - return "urde::DNAMP2::ANCS::AnimationSet::EVNT"; -} +const char* ANCS::AnimationSet::EVNT::DNAType() { return "urde::DNAMP2::ANCS::AnimationSet::EVNT"; } -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/ANCS.hpp b/DataSpec/DNAMP2/ANCS.hpp index 5583ecd11..3935c194c 100644 --- a/DataSpec/DNAMP2/ANCS.hpp +++ b/DataSpec/DNAMP2/ANCS.hpp @@ -9,251 +9,220 @@ #include "ANIM.hpp" #include "../DNAMP1/ANCS.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct ANCS : BigDNA -{ - using CINFType = CINF; - using CSKRType = CSKR; - using ANIMType = ANIM; +struct ANCS : BigDNA { + using CINFType = CINF; + using CSKRType = CSKR; + using ANIMType = ANIM; + AT_DECL_DNA_YAML + Value version; + + struct CharacterSet : BigDNA { AT_DECL_DNA_YAML Value version; + Value characterCount; + struct CharacterInfo : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo; - struct CharacterSet : BigDNA - { + atUint32 idx; + std::string name; + UniqueID32 cmdl; + UniqueID32 cskr; + UniqueID32 cinf; + + struct Animation : BigDNA { AT_DECL_DNA_YAML - Value version; - Value characterCount; - struct CharacterInfo : BigDNA - { - AT_DECL_EXPLICIT_DNA_YAML - using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo; + Value animIdx; + String<-1> strA; + }; + std::vector animations; - atUint32 idx; - std::string name; - UniqueID32 cmdl; - UniqueID32 cskr; - UniqueID32 cinf; + MP1CharacterInfo::PASDatabase pasDatabase; + struct ParticleResData { + std::vector part; + std::vector swhc; + std::vector unk; + std::vector elsc; + std::vector spsc; + std::vector unk2; + } partResData; - struct Animation : BigDNA - { - AT_DECL_DNA_YAML - Value animIdx; - String<-1> strA; - }; - std::vector animations; + atUint32 unk1 = 0; - MP1CharacterInfo::PASDatabase pasDatabase; - struct ParticleResData - { - std::vector part; - std::vector swhc; - std::vector unk; - std::vector elsc; - std::vector spsc; - std::vector unk2; - } partResData; + std::vector animAABBs; - atUint32 unk1 = 0; - - std::vector animAABBs; - - struct Effect : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value compCount; - struct EffectComponent : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - DNAFourCC type; - UniqueID32 id; - Value unkMP2; - Value unk1; - Value unk2; - Value unk3; - }; - Vector comps; - }; - std::vector effects; - - UniqueID32 cmdlIce; - UniqueID32 cskrIce; - - std::vector animIdxs; - - atUint32 unk4; - atUint8 unk5; - - struct Extents : BigDNA - { - AT_DECL_DNA_YAML - Value animIdx; - Value aabb[2]; - }; - std::vector extents; - }; - Vector characters; - } characterSet; - - struct AnimationSet : BigDNA - { + struct Effect : BigDNA { AT_DECL_DNA_YAML - Delete expl; - - using MP1AnimationSet = DNAMP1::ANCS::AnimationSet; - - std::vector animations; - - std::vector transitions; - MP1AnimationSet::MetaTransFactory defaultTransition; - - std::vector additiveAnims; - - float floatA = 0.0; - float floatB = 0.0; - - std::vector halfTransitions; - - struct EVNT : BigDNA - { - AT_DECL_EXPLICIT_DNA_YAML - atUint32 version; - - struct EventBase : BigDNA - { - AT_DECL_DNA_YAML - Value unk0; - String<-1> name; - Value type; - Value startTime; - Value unk1; - Value idx; - Value unk2; - Value unk3; - Value unk4; - Value unk5; - }; - - struct LoopEvent : EventBase - { - AT_DECL_DNA_YAML - Value flag; - }; - Value loopEventCount; - Vector loopEvents; - - struct UEVTEvent : EventBase - { - AT_DECL_DNA_YAML - Value uevtType; - String<-1> boneName; - }; - Value uevtEventCount; - Vector uevtEvents; - - struct EffectEvent : EventBase - { - AT_DECL_DNA_YAML - Value frameCount; - DNAFourCC effectType; - UniqueID32 effectId; - Value boneId; - Value scale; - Value parentMode; - }; - Value effectEventCount; - Vector effectEvents; - - struct SFXEvent : EventBase - { - AT_DECL_DNA_YAML - Value soundId; - Value smallNum; - Value bigNum; - Value sfxUnk1; - Value sfxUnk2; - Value sfxUnk3; - Value sfxUnk4; - }; - Value sfxEventCount; - Vector sfxEvents; + String<-1> name; + Value compCount; + struct EffectComponent : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + DNAFourCC type; + UniqueID32 id; + Value unkMP2; + Value unk1; + Value unk2; + Value unk3; }; - std::vector evnts; - } animationSet; + Vector comps; + }; + std::vector effects; - void getCharacterResInfo(std::vector>& out) const - { - out.clear(); - out.reserve(characterSet.characters.size()); - for (const CharacterSet::CharacterInfo& ci : characterSet.characters) - { - out.emplace_back(); - DNAANCS::CharacterResInfo& chOut = out.back(); - chOut.name = ci.name; - chOut.cmdl = ci.cmdl; - chOut.cskr = ci.cskr; - chOut.cinf = ci.cinf; + UniqueID32 cmdlIce; + UniqueID32 cskrIce; - if (ci.cmdlIce) - chOut.overlays.emplace_back("ICE", std::make_pair(ci.cmdlIce, ci.cskrIce)); - } + std::vector animIdxs; + + atUint32 unk4; + atUint8 unk5; + + struct Extents : BigDNA { + AT_DECL_DNA_YAML + Value animIdx; + Value aabb[2]; + }; + std::vector extents; + }; + Vector characters; + } characterSet; + + struct AnimationSet : BigDNA { + AT_DECL_DNA_YAML + Delete expl; + + using MP1AnimationSet = DNAMP1::ANCS::AnimationSet; + + std::vector animations; + + std::vector transitions; + MP1AnimationSet::MetaTransFactory defaultTransition; + + std::vector additiveAnims; + + float floatA = 0.0; + float floatB = 0.0; + + std::vector halfTransitions; + + struct EVNT : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + atUint32 version; + + struct EventBase : BigDNA { + AT_DECL_DNA_YAML + Value unk0; + String<-1> name; + Value type; + Value startTime; + Value unk1; + Value idx; + Value unk2; + Value unk3; + Value unk4; + Value unk5; + }; + + struct LoopEvent : EventBase { + AT_DECL_DNA_YAML + Value flag; + }; + Value loopEventCount; + Vector loopEvents; + + struct UEVTEvent : EventBase { + AT_DECL_DNA_YAML + Value uevtType; + String<-1> boneName; + }; + Value uevtEventCount; + Vector uevtEvents; + + struct EffectEvent : EventBase { + AT_DECL_DNA_YAML + Value frameCount; + DNAFourCC effectType; + UniqueID32 effectId; + Value boneId; + Value scale; + Value parentMode; + }; + Value effectEventCount; + Vector effectEvents; + + struct SFXEvent : EventBase { + AT_DECL_DNA_YAML + Value soundId; + Value smallNum; + Value bigNum; + Value sfxUnk1; + Value sfxUnk2; + Value sfxUnk3; + Value sfxUnk4; + }; + Value sfxEventCount; + Vector sfxEvents; + }; + std::vector evnts; + } animationSet; + + void getCharacterResInfo(std::vector>& out) const { + out.clear(); + out.reserve(characterSet.characters.size()); + for (const CharacterSet::CharacterInfo& ci : characterSet.characters) { + out.emplace_back(); + DNAANCS::CharacterResInfo& chOut = out.back(); + chOut.name = ci.name; + chOut.cmdl = ci.cmdl; + chOut.cskr = ci.cskr; + chOut.cinf = ci.cinf; + + if (ci.cmdlIce) + chOut.overlays.emplace_back("ICE", std::make_pair(ci.cmdlIce, ci.cskrIce)); + } + } + + void getAnimationResInfo(PAKRouter* pakRouter, + std::map>& out) const { + out.clear(); + for (const DNAMP1::ANCS::AnimationSet::Animation& ai : animationSet.animations) + ai.metaAnim.m_anim->gatherPrimitives(nullptr, out); + for (const DNAMP1::ANCS::AnimationSet::Transition& ti : animationSet.transitions) + if (ti.metaTrans.m_trans) + ti.metaTrans.m_trans->gatherPrimitives(nullptr, out); + if (animationSet.defaultTransition.m_trans) + animationSet.defaultTransition.m_trans->gatherPrimitives(nullptr, out); + } + + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const DNAMP2::PAK::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged) { + hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true); + hecl::ProjectPath::Type yamlType = yamlPath.getPathType(); + hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true); + hecl::ProjectPath::Type blendType = blendPath.getPathType(); + + if (force || yamlType == hecl::ProjectPath::Type::None || blendType == hecl::ProjectPath::Type::None) { + ANCS ancs; + ancs.read(rs); + + if (force || yamlType == hecl::ProjectPath::Type::None) { + athena::io::FileWriter writer(yamlPath.getAbsolutePath()); + athena::io::ToYAMLStream(ancs, writer); + } + + if (force || blendType == hecl::ProjectPath::Type::None) { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + DNAANCS::ReadANCSToBlender, ANCS, MaterialSet, DNACMDL::SurfaceHeader_2, 4>( + conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force); + } } - void getAnimationResInfo(PAKRouter* pakRouter, - std::map>& out) const - { - out.clear(); - for (const DNAMP1::ANCS::AnimationSet::Animation& ai : animationSet.animations) - ai.metaAnim.m_anim->gatherPrimitives(nullptr, out); - for (const DNAMP1::ANCS::AnimationSet::Transition& ti : animationSet.transitions) - if (ti.metaTrans.m_trans) - ti.metaTrans.m_trans->gatherPrimitives(nullptr, out); - if (animationSet.defaultTransition.m_trans) - animationSet.defaultTransition.m_trans->gatherPrimitives(nullptr, out); - } - - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const DNAMP2::PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) - { - hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true); - hecl::ProjectPath::Type yamlType = yamlPath.getPathType(); - hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true); - hecl::ProjectPath::Type blendType = blendPath.getPathType(); - - if (force || - yamlType == hecl::ProjectPath::Type::None || - blendType == hecl::ProjectPath::Type::None) - { - ANCS ancs; - ancs.read(rs); - - if (force || yamlType == hecl::ProjectPath::Type::None) - { - athena::io::FileWriter writer(yamlPath.getAbsolutePath()); - athena::io::ToYAMLStream(ancs, writer); - } - - if (force || blendType == hecl::ProjectPath::Type::None) - { - hecl::blender::Connection& conn = btok.getBlenderConnection(); - DNAANCS::ReadANCSToBlender, ANCS, MaterialSet, DNACMDL::SurfaceHeader_2, 4> - (conn, ancs, blendPath, pakRouter, entry, dataSpec, fileChanged, force); - } - } - - return true; - } + return true; + } }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/ANIM.cpp b/DataSpec/DNAMP2/ANIM.cpp index 6d5d0bc6c..71373c021 100644 --- a/DataSpec/DNAMP2/ANIM.cpp +++ b/DataSpec/DNAMP2/ANIM.cpp @@ -1,626 +1,571 @@ #include "ANIM.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { using ANIMOutStream = hecl::blender::ANIMOutStream; -void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig) const -{ - os.format("act.hecl_fps = round(%f)\n" - "act.hecl_looping = %s\n", - (1.0f / mainInterval), looping ? "True" : "False"); +void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig) const { + os.format( + "act.hecl_fps = round(%f)\n" + "act.hecl_looping = %s\n", + (1.0f / mainInterval), looping ? "True" : "False"); - auto kit = chanKeys.begin(); + auto kit = chanKeys.begin(); - std::vector fixedRotKeys; - std::vector fixedTransKeys; + std::vector fixedRotKeys; + std::vector fixedTransKeys; - for (const std::pair>& bone : bones) - { - const std::string* bName = rig.getCINF().getBoneNameFromId(bone.first); - if (!bName) - continue; + for (const std::pair>& bone : bones) { + const std::string* bName = rig.getCINF().getBoneNameFromId(bone.first); + if (!bName) + continue; - os.format("bone_string = '%s'\n", bName->c_str()); - os << "action_group = act.groups.new(bone_string)\n" - "\n"; + os.format("bone_string = '%s'\n", bName->c_str()); + os << "action_group = act.groups.new(bone_string)\n" + "\n"; - if (std::get<0>(bone.second)) - os << "rotCurves = []\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string))\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string))\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string))\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string))\n" - "\n"; + if (std::get<0>(bone.second)) + os << "rotCurves = []\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, " + "action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, " + "action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, " + "action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, " + "action_group=bone_string))\n" + "\n"; - if (std::get<1>(bone.second)) - os << "transCurves = []\n" - "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string))\n" - "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string))\n" - "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n" - "\n"; + if (std::get<1>(bone.second)) + os << "transCurves = []\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, " + "action_group=bone_string))\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, " + "action_group=bone_string))\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, " + "action_group=bone_string))\n" + "\n"; - if (std::get<2>(bone.second)) - os << "scaleCurves = []\n" - "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=0, action_group=bone_string))\n" - "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=1, action_group=bone_string))\n" - "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=2, action_group=bone_string))\n" - "\n"; + if (std::get<2>(bone.second)) + os << "scaleCurves = []\n" + "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=0, " + "action_group=bone_string))\n" + "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=1, " + "action_group=bone_string))\n" + "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=2, " + "action_group=bone_string))\n" + "\n"; - ANIMOutStream ao = os.beginANIMCurve(); - if (std::get<0>(bone.second)) - { - const std::vector& rotKeys = *kit++; - fixedRotKeys.clear(); - fixedRotKeys.resize(rotKeys.size()); + ANIMOutStream ao = os.beginANIMCurve(); + if (std::get<0>(bone.second)) { + const std::vector& rotKeys = *kit++; + fixedRotKeys.clear(); + fixedRotKeys.resize(rotKeys.size()); - for (int c=0 ; c<4 ; ++c) - { - size_t idx = 0; - for (const DNAANIM::Value& val : rotKeys) - fixedRotKeys[idx++][c] = val.simd[c]; - } + for (int c = 0; c < 4; ++c) { + size_t idx = 0; + for (const DNAANIM::Value& val : rotKeys) + fixedRotKeys[idx++][c] = val.simd[c]; + } - for (zeus::CQuaternion& rot : fixedRotKeys) - rot = rig.invertRotation(bone.first, rot); + for (zeus::CQuaternion& rot : fixedRotKeys) + rot = rig.invertRotation(bone.first, rot); - for (int c=0 ; c<4 ; ++c) - { - auto frameit = frames.begin(); - ao.changeCurve(ANIMOutStream::CurveType::Rotate, c, rotKeys.size()); - for (const zeus::CQuaternion& val : fixedRotKeys) - ao.write(*frameit++, val[c]); - } - } - - if (std::get<1>(bone.second)) - { - const std::vector& transKeys = *kit++; - fixedTransKeys.clear(); - fixedTransKeys.resize(transKeys.size()); - - for (int c=0 ; c<3 ; ++c) - { - size_t idx = 0; - for (const DNAANIM::Value& val : transKeys) - fixedTransKeys[idx++][c] = val.simd[c]; - } - - for (zeus::CVector3f& t : fixedTransKeys) - t = rig.invertPosition(bone.first, t, true); - - for (int c=0 ; c<3 ; ++c) - { - auto frameit = frames.begin(); - ao.changeCurve(ANIMOutStream::CurveType::Translate, c, fixedTransKeys.size()); - for (const zeus::CVector3f& val : fixedTransKeys) - ao.write(*frameit++, val[c]); - } - } - - if (std::get<2>(bone.second)) - { - const std::vector& scaleKeys = *kit++; - for (int c=0 ; c<3 ; ++c) - { - auto frameit = frames.begin(); - ao.changeCurve(ANIMOutStream::CurveType::Scale, c, scaleKeys.size()); - for (const DNAANIM::Value& val : scaleKeys) - ao.write(*frameit++, val.simd[c]); - } - } + for (int c = 0; c < 4; ++c) { + auto frameit = frames.begin(); + ao.changeCurve(ANIMOutStream::CurveType::Rotate, c, rotKeys.size()); + for (const zeus::CQuaternion& val : fixedRotKeys) + ao.write(*frameit++, val[c]); + } } -} -template <> -void ANIM::Enumerate(typename Read::StreamT& reader) -{ - atUint32 version = reader.readUint32Big(); - switch (version) - { - case 0: - m_anim.reset(new struct ANIM0); - m_anim->read(reader); - break; - case 2: - m_anim.reset(new struct ANIM2); - m_anim->read(reader); - break; - default: - Log.report(logvisor::Fatal, "unrecognized ANIM version"); - break; + if (std::get<1>(bone.second)) { + const std::vector& transKeys = *kit++; + fixedTransKeys.clear(); + fixedTransKeys.resize(transKeys.size()); + + for (int c = 0; c < 3; ++c) { + size_t idx = 0; + for (const DNAANIM::Value& val : transKeys) + fixedTransKeys[idx++][c] = val.simd[c]; + } + + for (zeus::CVector3f& t : fixedTransKeys) + t = rig.invertPosition(bone.first, t, true); + + for (int c = 0; c < 3; ++c) { + auto frameit = frames.begin(); + ao.changeCurve(ANIMOutStream::CurveType::Translate, c, fixedTransKeys.size()); + for (const zeus::CVector3f& val : fixedTransKeys) + ao.write(*frameit++, val[c]); + } } + + if (std::get<2>(bone.second)) { + const std::vector& scaleKeys = *kit++; + for (int c = 0; c < 3; ++c) { + auto frameit = frames.begin(); + ao.changeCurve(ANIMOutStream::CurveType::Scale, c, scaleKeys.size()); + for (const DNAANIM::Value& val : scaleKeys) + ao.write(*frameit++, val.simd[c]); + } + } + } } template <> -void ANIM::Enumerate(typename Write::StreamT& writer) -{ - writer.writeUint32Big(m_anim->m_version); - m_anim->write(writer); +void ANIM::Enumerate(typename Read::StreamT& reader) { + atUint32 version = reader.readUint32Big(); + switch (version) { + case 0: + m_anim.reset(new struct ANIM0); + m_anim->read(reader); + break; + case 2: + m_anim.reset(new struct ANIM2); + m_anim->read(reader); + break; + default: + Log.report(logvisor::Fatal, "unrecognized ANIM version"); + break; + } } template <> -void ANIM::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - m_anim->binarySize(s); +void ANIM::Enumerate(typename Write::StreamT& writer) { + writer.writeUint32Big(m_anim->m_version); + m_anim->write(writer); +} + +template <> +void ANIM::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + m_anim->binarySize(s); } const char* ANIM::ANIM0::DNAType() { return "ANIM0"; } template <> -void ANIM::ANIM0::Enumerate(typename Read::StreamT& reader) -{ - Header head; - head.read(reader); - mainInterval = head.interval; +void ANIM::ANIM0::Enumerate(typename Read::StreamT& reader) { + Header head; + head.read(reader); + mainInterval = head.interval; - frames.clear(); - frames.reserve(head.keyCount); - for (size_t k=0 ; k boneMap; - for (size_t b=0 ; b boneMap; + for (size_t b = 0; b < head.boneSlotCount; ++b) { + atUint8 idx = reader.readUByte(); + if (idx == 0xff) + continue; + boneMap[idx] = b; + } + + atUint32 boneCount = reader.readUint32Big(); + bones.clear(); + bones.reserve(boneCount); + for (size_t b = 0; b < boneCount; ++b) { + bones.emplace_back(boneMap[b], std::make_tuple(false, false, false)); + atUint8 idx = reader.readUByte(); + if (idx != 0xff) + std::get<0>(bones.back().second) = true; + } + + boneCount = reader.readUint32Big(); + for (size_t b = 0; b < boneCount; ++b) { + atUint8 idx = reader.readUByte(); + if (idx != 0xff) + std::get<1>(bones[b].second) = true; + } + + boneCount = reader.readUint32Big(); + for (size_t b = 0; b < boneCount; ++b) { + atUint8 idx = reader.readUByte(); + if (idx != 0xff) + std::get<2>(bones[b].second) = true; + } + + channels.clear(); + chanKeys.clear(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Rotation; + chanKeys.emplace_back(); } - - atUint32 boneCount = reader.readUint32Big(); - bones.clear(); - bones.reserve(boneCount); - for (size_t b=0 ; b(bones.back().second) = true; + if (std::get<1>(bone.second)) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Translation; + chanKeys.emplace_back(); } - - boneCount = reader.readUint32Big(); - for (size_t b=0 ; b(bones[b].second) = true; + if (std::get<2>(bone.second)) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Scale; + chanKeys.emplace_back(); } + } - boneCount = reader.readUint32Big(); - for (size_t b=0 ; b(bones[b].second) = true; + reader.readUint32Big(); + auto kit = chanKeys.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + ++kit; + if (std::get<1>(bone.second)) + ++kit; + if (std::get<2>(bone.second)) { + std::vector& keys = *kit++; + for (size_t k = 0; k < head.keyCount; ++k) + keys.emplace_back(reader.readVec3fBig()); } + } - channels.clear(); - chanKeys.clear(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::Rotation; - chanKeys.emplace_back(); - } - if (std::get<1>(bone.second)) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::Translation; - chanKeys.emplace_back(); - } - if (std::get<2>(bone.second)) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::Scale; - chanKeys.emplace_back(); - } + reader.readUint32Big(); + kit = chanKeys.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) { + std::vector& keys = *kit++; + for (size_t k = 0; k < head.keyCount; ++k) + keys.emplace_back(reader.readVec4fBig()); } + if (std::get<1>(bone.second)) + ++kit; + if (std::get<2>(bone.second)) + ++kit; + } - reader.readUint32Big(); - auto kit = chanKeys.begin(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - ++kit; - if (std::get<1>(bone.second)) - ++kit; - if (std::get<2>(bone.second)) - { - std::vector& keys = *kit++; - for (size_t k=0 ; k>& bone : bones) - { - if (std::get<0>(bone.second)) - { - std::vector& keys = *kit++; - for (size_t k=0 ; k(bone.second)) - ++kit; - if (std::get<2>(bone.second)) - ++kit; - } - - reader.readUint32Big(); - kit = chanKeys.begin(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - ++kit; - if (std::get<1>(bone.second)) - { - std::vector& keys = *kit++; - for (size_t k=0 ; k(bone.second)) - ++kit; + reader.readUint32Big(); + kit = chanKeys.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + ++kit; + if (std::get<1>(bone.second)) { + std::vector& keys = *kit++; + for (size_t k = 0; k < head.keyCount; ++k) + keys.emplace_back(reader.readVec3fBig()); } + if (std::get<2>(bone.second)) + ++kit; + } } template <> -void ANIM::ANIM0::Enumerate(typename Write::StreamT& writer) -{ - Header head; - head.unk0 = 0; - head.unk1 = 0; - head.unk2 = 0; - head.keyCount = frames.size(); - head.duration = head.keyCount * mainInterval; - head.interval = mainInterval; +void ANIM::ANIM0::Enumerate(typename Write::StreamT& writer) { + Header head; + head.unk0 = 0; + head.unk1 = 0; + head.unk2 = 0; + head.keyCount = frames.size(); + head.duration = head.keyCount * mainInterval; + head.interval = mainInterval; - atUint32 maxId = 0; - for (const std::pair>& bone : bones) - maxId = std::max(maxId, bone.first); - head.boneSlotCount = maxId + 1; - head.write(writer); + atUint32 maxId = 0; + for (const std::pair>& bone : bones) + maxId = std::max(maxId, bone.first); + head.boneSlotCount = maxId + 1; + head.write(writer); - for (size_t s=0 ; s>& bone : bones) - { - if (s == bone.first) - { - writer.writeUByte(boneIdx); - found = true; - break; - } - ++boneIdx; - } - if (!found) - writer.writeUByte(0xff); - } - - writer.writeUint32Big(bones.size()); + for (size_t s = 0; s < head.boneSlotCount; ++s) { size_t boneIdx = 0; - size_t rotKeyCount = 0; - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - { - writer.writeUByte(boneIdx); - ++rotKeyCount; - } - else - writer.writeUByte(0xff); - ++boneIdx; + bool found = false; + for (const std::pair>& bone : bones) { + if (s == bone.first) { + writer.writeUByte(boneIdx); + found = true; + break; + } + ++boneIdx; } + if (!found) + writer.writeUByte(0xff); + } - writer.writeUint32Big(bones.size()); - boneIdx = 0; - size_t transKeyCount = 0; - for (const std::pair>& bone : bones) - { - if (std::get<1>(bone.second)) - { - writer.writeUByte(boneIdx); - ++transKeyCount; - } - else - writer.writeUByte(0xff); - ++boneIdx; - } + writer.writeUint32Big(bones.size()); + size_t boneIdx = 0; + size_t rotKeyCount = 0; + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) { + writer.writeUByte(boneIdx); + ++rotKeyCount; + } else + writer.writeUByte(0xff); + ++boneIdx; + } - writer.writeUint32Big(bones.size()); - boneIdx = 0; - size_t scaleKeyCount = 0; - for (const std::pair>& bone : bones) - { - if (std::get<2>(bone.second)) - { - writer.writeUByte(boneIdx); - ++scaleKeyCount; - } - else - writer.writeUByte(0xff); - ++boneIdx; - } + writer.writeUint32Big(bones.size()); + boneIdx = 0; + size_t transKeyCount = 0; + for (const std::pair>& bone : bones) { + if (std::get<1>(bone.second)) { + writer.writeUByte(boneIdx); + ++transKeyCount; + } else + writer.writeUByte(0xff); + ++boneIdx; + } - writer.writeUint32Big(scaleKeyCount * head.keyCount); - auto cit = chanKeys.begin(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - ++cit; - if (std::get<1>(bone.second)) - ++cit; - if (std::get<2>(bone.second)) - { - const std::vector& keys = *cit++; - auto kit = keys.begin(); - for (size_t k=0 ; k>& bone : bones) { + if (std::get<2>(bone.second)) { + writer.writeUByte(boneIdx); + ++scaleKeyCount; + } else + writer.writeUByte(0xff); + ++boneIdx; + } - writer.writeUint32Big(rotKeyCount * head.keyCount); - cit = chanKeys.begin(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - { - const std::vector& keys = *cit++; - auto kit = keys.begin(); - for (size_t k=0 ; k(bone.second)) - ++cit; - if (std::get<2>(bone.second)) - ++cit; + writer.writeUint32Big(scaleKeyCount * head.keyCount); + auto cit = chanKeys.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + ++cit; + if (std::get<1>(bone.second)) + ++cit; + if (std::get<2>(bone.second)) { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k = 0; k < head.keyCount; ++k) + writer.writeVec3fBig(atVec3f{(*kit++).simd}); } + } - writer.writeUint32Big(transKeyCount * head.keyCount); - cit = chanKeys.begin(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - ++cit; - if (std::get<1>(bone.second)) - { - const std::vector& keys = *cit++; - auto kit = keys.begin(); - for (size_t k=0 ; k(bone.second)) - ++cit; + writer.writeUint32Big(rotKeyCount * head.keyCount); + cit = chanKeys.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k = 0; k < head.keyCount; ++k) + writer.writeVec4fBig(atVec4f{(*kit++).simd}); } + if (std::get<1>(bone.second)) + ++cit; + if (std::get<2>(bone.second)) + ++cit; + } + + writer.writeUint32Big(transKeyCount * head.keyCount); + cit = chanKeys.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + ++cit; + if (std::get<1>(bone.second)) { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k = 0; k < head.keyCount; ++k) + writer.writeVec3fBig(atVec3f{(*kit++).simd}); + } + if (std::get<2>(bone.second)) + ++cit; + } } template <> -void ANIM::ANIM0::Enumerate(typename BinarySize::StreamT& s) -{ - Header head; +void ANIM::ANIM0::Enumerate(typename BinarySize::StreamT& s) { + Header head; - atUint32 maxId = 0; - for (const std::pair>& bone : bones) - maxId = std::max(maxId, bone.first); + atUint32 maxId = 0; + for (const std::pair>& bone : bones) + maxId = std::max(maxId, bone.first); - head.binarySize(s); - s += maxId + 1; - s += bones.size() * 3 + 12; + head.binarySize(s); + s += maxId + 1; + s += bones.size() * 3 + 12; - s += 12; - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - s += head.keyCount * 16; - if (std::get<1>(bone.second)) - s += head.keyCount * 12; - if (std::get<2>(bone.second)) - s += head.keyCount * 12; - } + s += 12; + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + s += head.keyCount * 16; + if (std::get<1>(bone.second)) + s += head.keyCount * 12; + if (std::get<2>(bone.second)) + s += head.keyCount * 12; + } } const char* ANIM::ANIM2::DNAType() { return "ANIM2"; } template <> -void ANIM::ANIM2::Enumerate(typename Read::StreamT& reader) -{ - Header head; - head.read(reader); - mainInterval = head.interval; - looping = bool(head.looping); +void ANIM::ANIM2::Enumerate(typename Read::StreamT& reader) { + Header head; + head.read(reader); + mainInterval = head.interval; + looping = bool(head.looping); - WordBitmap keyBmp; - keyBmp.read(reader, head.keyBitmapBitCount); - frames.clear(); - atUint32 frameAccum = 0; - for (bool bit : keyBmp) - { - if (bit) - frames.push_back(frameAccum); - ++frameAccum; + WordBitmap keyBmp; + keyBmp.read(reader, head.keyBitmapBitCount); + frames.clear(); + atUint32 frameAccum = 0; + for (bool bit : keyBmp) { + if (bit) + frames.push_back(frameAccum); + ++frameAccum; + } + reader.seek(4); + + bones.clear(); + bones.reserve(head.boneChannelCount); + channels.clear(); + channels.reserve(head.boneChannelCount); + atUint16 keyframeCount = 0; + for (size_t b = 0; b < head.boneChannelCount; ++b) { + ChannelDesc desc; + desc.read(reader); + bones.emplace_back(desc.id, std::make_tuple(desc.keyCount1 != 0, desc.keyCount2 != 0, desc.keyCount3 != 0)); + + if (desc.keyCount1) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Rotation; + chan.i[0] = desc.initRX; + chan.q[0] = desc.qRX; + chan.i[1] = desc.initRY; + chan.q[1] = desc.qRY; + chan.i[2] = desc.initRZ; + chan.q[2] = desc.qRZ; } - reader.seek(4); + keyframeCount = std::max(keyframeCount, desc.keyCount1); - bones.clear(); - bones.reserve(head.boneChannelCount); - channels.clear(); - channels.reserve(head.boneChannelCount); - atUint16 keyframeCount = 0; - for (size_t b=0 ; b bsData = reader.readUBytes(bsSize); - DNAANIM::BitstreamReader bsReader; - chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult, head.scaleMult); + if (desc.keyCount3) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Scale; + chan.i[0] = desc.initSX; + chan.q[0] = desc.qSX; + chan.i[1] = desc.initSY; + chan.q[1] = desc.qSY; + chan.i[2] = desc.initSZ; + chan.q[2] = desc.qSZ; + } + keyframeCount = std::max(keyframeCount, desc.keyCount3); + } + + size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels); + std::unique_ptr bsData = reader.readUBytes(bsSize); + DNAANIM::BitstreamReader bsReader; + chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult, head.scaleMult); } template <> -void ANIM::ANIM2::Enumerate(typename Write::StreamT& writer) -{ - /* TODO: conform to MP1 ANIM3 */ - Header head; - head.unk1 = 1; - head.looping = looping; - head.interval = mainInterval; - head.rootBoneId = 0; - head.scaleMult = 0.f; +void ANIM::ANIM2::Enumerate(typename Write::StreamT& writer) { + /* TODO: conform to MP1 ANIM3 */ + Header head; + head.unk1 = 1; + head.looping = looping; + head.interval = mainInterval; + head.rootBoneId = 0; + head.scaleMult = 0.f; - WordBitmap keyBmp; - size_t frameCount = 0; - for (atUint32 frame : frames) - { - while (keyBmp.getBit(frame)) - ++frame; - keyBmp.setBit(frame); - frameCount = frame + 1; + WordBitmap keyBmp; + size_t frameCount = 0; + for (atUint32 frame : frames) { + while (keyBmp.getBit(frame)) + ++frame; + keyBmp.setBit(frame); + frameCount = frame + 1; + } + head.keyBitmapBitCount = keyBmp.getBitCount(); + head.duration = frameCount * mainInterval; + head.boneChannelCount = bones.size(); + + size_t keyframeCount = frames.size(); + std::vector qChannels = channels; + DNAANIM::BitstreamWriter bsWriter; + size_t bsSize; + std::unique_ptr bsData = + bsWriter.write(chanKeys, keyframeCount, qChannels, m_version == 3 ? 0x7fffff : 0x7fff, head.rotDiv, + head.translationMult, head.scaleMult, bsSize); + + /* TODO: Figure out proper scratch size computation */ + head.scratchSize = keyframeCount * channels.size() * 16; + + head.write(writer); + keyBmp.write(writer); + writer.writeUint32Big(head.boneChannelCount); + auto cit = qChannels.begin(); + for (const std::pair>& bone : bones) { + ChannelDesc desc; + if (std::get<0>(bone.second)) { + DNAANIM::Channel& chan = *cit++; + desc.keyCount1 = keyframeCount; + desc.initRX = chan.i[0]; + desc.qRX = chan.q[0]; + desc.initRY = chan.i[1]; + desc.qRY = chan.q[1]; + desc.initRZ = chan.i[2]; + desc.qRZ = chan.q[2]; } - head.keyBitmapBitCount = keyBmp.getBitCount(); - head.duration = frameCount * mainInterval; - head.boneChannelCount = bones.size(); - - size_t keyframeCount = frames.size(); - std::vector qChannels = channels; - DNAANIM::BitstreamWriter bsWriter; - size_t bsSize; - std::unique_ptr bsData = bsWriter.write(chanKeys, keyframeCount, qChannels, - m_version == 3 ? 0x7fffff : 0x7fff, - head.rotDiv, head.translationMult, head.scaleMult, bsSize); - - /* TODO: Figure out proper scratch size computation */ - head.scratchSize = keyframeCount * channels.size() * 16; - - head.write(writer); - keyBmp.write(writer); - writer.writeUint32Big(head.boneChannelCount); - auto cit = qChannels.begin(); - for (const std::pair>& bone : bones) - { - ChannelDesc desc; - if (std::get<0>(bone.second)) - { - DNAANIM::Channel& chan = *cit++; - desc.keyCount1 = keyframeCount; - desc.initRX = chan.i[0]; - desc.qRX = chan.q[0]; - desc.initRY = chan.i[1]; - desc.qRY = chan.q[1]; - desc.initRZ = chan.i[2]; - desc.qRZ = chan.q[2]; - } - if (std::get<1>(bone.second)) - { - DNAANIM::Channel& chan = *cit++; - desc.keyCount2 = keyframeCount; - desc.initTX = chan.i[0]; - desc.qTX = chan.q[0]; - desc.initTY = chan.i[1]; - desc.qTY = chan.q[1]; - desc.initTZ = chan.i[2]; - desc.qTZ = chan.q[2]; - } - if (std::get<2>(bone.second)) - { - DNAANIM::Channel& chan = *cit++; - desc.keyCount3 = keyframeCount; - desc.initSX = chan.i[0]; - desc.qSX = chan.q[0]; - desc.initSY = chan.i[1]; - desc.qSY = chan.q[1]; - desc.initSZ = chan.i[2]; - desc.qSZ = chan.q[2]; - } + if (std::get<1>(bone.second)) { + DNAANIM::Channel& chan = *cit++; + desc.keyCount2 = keyframeCount; + desc.initTX = chan.i[0]; + desc.qTX = chan.q[0]; + desc.initTY = chan.i[1]; + desc.qTY = chan.q[1]; + desc.initTZ = chan.i[2]; + desc.qTZ = chan.q[2]; } + if (std::get<2>(bone.second)) { + DNAANIM::Channel& chan = *cit++; + desc.keyCount3 = keyframeCount; + desc.initSX = chan.i[0]; + desc.qSX = chan.q[0]; + desc.initSY = chan.i[1]; + desc.qSY = chan.q[1]; + desc.initSZ = chan.i[2]; + desc.qSZ = chan.q[2]; + } + } - writer.writeUBytes(bsData.get(), bsSize); + writer.writeUBytes(bsData.get(), bsSize); } template <> -void ANIM::ANIM2::Enumerate(typename BinarySize::StreamT& s) -{ - Header head; +void ANIM::ANIM2::Enumerate(typename BinarySize::StreamT& s) { + Header head; - WordBitmap keyBmp; - for (atUint32 frame : frames) - { - while (keyBmp.getBit(frame)) - ++frame; - keyBmp.setBit(frame); - } + WordBitmap keyBmp; + for (atUint32 frame : frames) { + while (keyBmp.getBit(frame)) + ++frame; + keyBmp.setBit(frame); + } - head.binarySize(s); - keyBmp.binarySize(s); - s += 4; - for (const std::pair>& bone : bones) - { - s += 7; - if (std::get<0>(bone.second)) - s += 9; - if (std::get<1>(bone.second)) - s += 9; - if (std::get<2>(bone.second)) - s += 9; - } + head.binarySize(s); + keyBmp.binarySize(s); + s += 4; + for (const std::pair>& bone : bones) { + s += 7; + if (std::get<0>(bone.second)) + s += 9; + if (std::get<1>(bone.second)) + s += 9; + if (std::get<2>(bone.second)) + s += 9; + } - s += DNAANIM::ComputeBitstreamSize(frames.size(), channels); + s += DNAANIM::ComputeBitstreamSize(frames.size(), channels); } -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/ANIM.hpp b/DataSpec/DNAMP2/ANIM.hpp index 757da6d83..8ca3193cd 100644 --- a/DataSpec/DNAMP2/ANIM.hpp +++ b/DataSpec/DNAMP2/ANIM.hpp @@ -6,190 +6,170 @@ #include "CINF.hpp" #include "DataSpec/DNACommon/ANCS.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct ANIM : BigDNA -{ +struct ANIM : BigDNA { + AT_DECL_EXPLICIT_DNA + + struct IANIM : BigDNAV { + Delete expl; + atUint32 m_version; + IANIM(atUint32 version) : m_version(version) {} + + std::vector>> bones; + std::vector frames; + std::vector channels; + std::vector> chanKeys; + float mainInterval = 0.0; + bool looping = false; + + void sendANIMToBlender(hecl::blender::PyOutStream&, const DNAANIM::RigInverter& rig) const; + }; + + struct ANIM0 : IANIM { AT_DECL_EXPLICIT_DNA + AT_DECL_DNAV + ANIM0() : IANIM(0) {} - struct IANIM : BigDNAV - { - Delete expl; - atUint32 m_version; - IANIM(atUint32 version) : m_version(version) {} + struct Header : BigDNA { + AT_DECL_DNA + Value duration; + Value unk0; + Value interval; + Value unk1; + Value keyCount; + Value unk2; + Value boneSlotCount; + }; + }; - std::vector>> bones; - std::vector frames; - std::vector channels; - std::vector> chanKeys; - float mainInterval = 0.0; - bool looping = false; + struct ANIM2 : IANIM { + AT_DECL_EXPLICIT_DNA + AT_DECL_DNAV + ANIM2() : IANIM(2) {} - void sendANIMToBlender(hecl::blender::PyOutStream&, const DNAANIM::RigInverter& rig) const; + struct Header : BigDNA { + AT_DECL_DNA + Value scratchSize; + Value unk1; + Value duration; + Value interval; + Value rootBoneId = 3; + Value looping = 0; + Value rotDiv; + Value translationMult; + Value scaleMult; + Value boneChannelCount; + Value unk3 = 1; + Value keyBitmapBitCount; }; - struct ANIM0 : IANIM - { - AT_DECL_EXPLICIT_DNA - AT_DECL_DNAV - ANIM0() : IANIM(0) {} + struct ChannelDesc : BigDNA { + Delete expl; + Value id = 0; + Value keyCount1 = 0; + Value initRX = 0; + Value qRX = 0; + Value initRY = 0; + Value qRY = 0; + Value initRZ = 0; + Value qRZ = 0; + Value keyCount2 = 0; + Value initTX = 0; + Value qTX = 0; + Value initTY = 0; + Value qTY = 0; + Value initTZ = 0; + Value qTZ = 0; + Value keyCount3 = 0; + Value initSX = 0; + Value qSX = 0; + Value initSY = 0; + Value qSY = 0; + Value initSZ = 0; + Value qSZ = 0; - struct Header : BigDNA - { - AT_DECL_DNA - Value duration; - Value unk0; - Value interval; - Value unk1; - Value keyCount; - Value unk2; - Value boneSlotCount; - }; + void read(athena::io::IStreamReader& reader) { + id = reader.readUByte(); + keyCount1 = reader.readUint16Big(); + if (keyCount1) { + initRX = reader.readInt16Big(); + qRX = reader.readUByte(); + initRY = reader.readInt16Big(); + qRY = reader.readUByte(); + initRZ = reader.readInt16Big(); + qRZ = reader.readUByte(); + } + keyCount2 = reader.readUint16Big(); + if (keyCount2) { + initTX = reader.readInt16Big(); + qTX = reader.readUByte(); + initTY = reader.readInt16Big(); + qTY = reader.readUByte(); + initTZ = reader.readInt16Big(); + qTZ = reader.readUByte(); + } + keyCount3 = reader.readUint16Big(); + if (keyCount3) { + initSX = reader.readInt16Big(); + qSX = reader.readUByte(); + initSY = reader.readInt16Big(); + qSY = reader.readUByte(); + initSZ = reader.readInt16Big(); + qSZ = reader.readUByte(); + } + } + void write(athena::io::IStreamWriter& writer) const { + writer.writeUByte(id); + writer.writeUint16Big(keyCount1); + if (keyCount1) { + writer.writeInt16Big(initRX); + writer.writeUByte(qRX); + writer.writeInt16Big(initRY); + writer.writeUByte(qRY); + writer.writeInt16Big(initRZ); + writer.writeUByte(qRZ); + } + writer.writeUint16Big(keyCount2); + if (keyCount2) { + writer.writeInt16Big(initTX); + writer.writeUByte(qTX); + writer.writeInt16Big(initTY); + writer.writeUByte(qTY); + writer.writeInt16Big(initTZ); + writer.writeUByte(qTZ); + } + writer.writeUint16Big(keyCount3); + if (keyCount3) { + writer.writeInt16Big(initSX); + writer.writeUByte(qSX); + writer.writeInt16Big(initSY); + writer.writeUByte(qSY); + writer.writeInt16Big(initSZ); + writer.writeUByte(qSZ); + } + } + size_t binarySize(size_t __isz) const { + __isz += 7; + if (keyCount1) + __isz += 9; + if (keyCount2) + __isz += 9; + if (keyCount3) + __isz += 9; + return __isz; + } }; + }; - struct ANIM2 : IANIM - { - AT_DECL_EXPLICIT_DNA - AT_DECL_DNAV - ANIM2() : IANIM(2) {} + std::unique_ptr m_anim; - struct Header : BigDNA - { - AT_DECL_DNA - Value scratchSize; - Value unk1; - Value duration; - Value interval; - Value rootBoneId = 3; - Value looping = 0; - Value rotDiv; - Value translationMult; - Value scaleMult; - Value boneChannelCount; - Value unk3 = 1; - Value keyBitmapBitCount; - }; - - struct ChannelDesc : BigDNA - { - Delete expl; - Value id = 0; - Value keyCount1 = 0; - Value initRX = 0; - Value qRX = 0; - Value initRY = 0; - Value qRY = 0; - Value initRZ = 0; - Value qRZ = 0; - Value keyCount2 = 0; - Value initTX = 0; - Value qTX = 0; - Value initTY = 0; - Value qTY = 0; - Value initTZ = 0; - Value qTZ = 0; - Value keyCount3 = 0; - Value initSX = 0; - Value qSX = 0; - Value initSY = 0; - Value qSY = 0; - Value initSZ = 0; - Value qSZ = 0; - - void read(athena::io::IStreamReader& reader) - { - id = reader.readUByte(); - keyCount1 = reader.readUint16Big(); - if (keyCount1) - { - initRX = reader.readInt16Big(); - qRX = reader.readUByte(); - initRY = reader.readInt16Big(); - qRY = reader.readUByte(); - initRZ = reader.readInt16Big(); - qRZ = reader.readUByte(); - } - keyCount2 = reader.readUint16Big(); - if (keyCount2) - { - initTX = reader.readInt16Big(); - qTX = reader.readUByte(); - initTY = reader.readInt16Big(); - qTY = reader.readUByte(); - initTZ = reader.readInt16Big(); - qTZ = reader.readUByte(); - } - keyCount3 = reader.readUint16Big(); - if (keyCount3) - { - initSX = reader.readInt16Big(); - qSX = reader.readUByte(); - initSY = reader.readInt16Big(); - qSY = reader.readUByte(); - initSZ = reader.readInt16Big(); - qSZ = reader.readUByte(); - } - } - void write(athena::io::IStreamWriter& writer) const - { - writer.writeUByte(id); - writer.writeUint16Big(keyCount1); - if (keyCount1) - { - writer.writeInt16Big(initRX); - writer.writeUByte(qRX); - writer.writeInt16Big(initRY); - writer.writeUByte(qRY); - writer.writeInt16Big(initRZ); - writer.writeUByte(qRZ); - } - writer.writeUint16Big(keyCount2); - if (keyCount2) - { - writer.writeInt16Big(initTX); - writer.writeUByte(qTX); - writer.writeInt16Big(initTY); - writer.writeUByte(qTY); - writer.writeInt16Big(initTZ); - writer.writeUByte(qTZ); - } - writer.writeUint16Big(keyCount3); - if (keyCount3) - { - writer.writeInt16Big(initSX); - writer.writeUByte(qSX); - writer.writeInt16Big(initSY); - writer.writeUByte(qSY); - writer.writeInt16Big(initSZ); - writer.writeUByte(qSZ); - } - } - size_t binarySize(size_t __isz) const - { - __isz += 7; - if (keyCount1) - __isz += 9; - if (keyCount2) - __isz += 9; - if (keyCount3) - __isz += 9; - return __isz; - } - }; - }; - - std::unique_ptr m_anim; - - void sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig, bool) const - { - m_anim->sendANIMToBlender(os, rig); - } - - void extractEVNT(const DNAANCS::AnimationResInfo& animInfo, - const hecl::ProjectPath& outPath, PAKRouter& pakRouter, bool force) const {} + void sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig, bool) const { + m_anim->sendANIMToBlender(os, rig); + } + void extractEVNT(const DNAANCS::AnimationResInfo& animInfo, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, bool force) const {} }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CINF.cpp b/DataSpec/DNAMP2/CINF.cpp index 5da04bdad..8054c44c9 100644 --- a/DataSpec/DNAMP2/CINF.cpp +++ b/DataSpec/DNAMP2/CINF.cpp @@ -1,98 +1,83 @@ #include "CINF.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -atUint32 CINF::getInternalBoneIdxFromId(atUint32 id) const -{ - atUint32 idx = 0; - for (const Bone& b : bones) - { - if (b.id == id) - return idx; - ++idx; +atUint32 CINF::getInternalBoneIdxFromId(atUint32 id) const { + atUint32 idx = 0; + for (const Bone& b : bones) { + if (b.id == id) + return idx; + ++idx; + } + return -1; +} + +atUint32 CINF::getBoneIdxFromId(atUint32 id) const { + atUint32 idx = 0; + for (atUint32 bid : boneIds) { + if (bid == id) + return idx; + ++idx; + } + return 0; +} + +const std::string* CINF::getBoneNameFromId(atUint32 id) const { + for (const Name& name : names) + if (id == name.boneId) + return &name.name; + return nullptr; +} + +void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const { + for (atUint32 bid : boneIds) { + for (const Name& name : names) { + if (name.boneId == bid) { + os.format("obj.vertex_groups.new('%s')\n", name.name.c_str()); + break; + } } - return -1; + } } -atUint32 CINF::getBoneIdxFromId(atUint32 id) const -{ - atUint32 idx = 0; - for (atUint32 bid : boneIds) - { - if (bid == id) - return idx; - ++idx; - } - return 0; +void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const { + DNAANIM::RigInverter inverter(*this); + + os.format( + "arm = bpy.data.armatures.new('CINF_%08X')\n" + "arm_obj = bpy.data.objects.new(arm.name, arm)\n" + "bpy.context.scene.objects.link(arm_obj)\n" + "bpy.context.scene.objects.active = arm_obj\n" + "bpy.ops.object.mode_set(mode='EDIT')\n" + "arm_bone_table = {}\n", + cinfId.toUint32()); + + for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) { + zeus::simd_floats originF(bone.m_origBone.origin.simd); + zeus::simd_floats tailF(bone.m_tail.mSimd); + os.format( + "bone = arm.edit_bones.new('%s')\n" + "bone.head = (%f,%f,%f)\n" + "bone.tail = (%f,%f,%f)\n" + "bone.use_inherit_scale = False\n" + "arm_bone_table[%u] = bone\n", + getBoneNameFromId(bone.m_origBone.id)->c_str(), originF[0], originF[1], originF[2], tailF[0], tailF[1], + tailF[2], bone.m_origBone.id); + } + + for (const Bone& bone : bones) + if (bone.parentId != 97) + os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId); + + os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; + + const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION"; + for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) + os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", getBoneNameFromId(bone.m_origBone.id)->c_str(), + rotMode); } -const std::string* CINF::getBoneNameFromId(atUint32 id) const -{ - for (const Name& name : names) - if (id == name.boneId) - return &name.name; - return nullptr; -} +std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) { return hecl::Format("CINF_%08X", cinfId.toUint32()); } -void CINF::sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const -{ - for (atUint32 bid : boneIds) - { - for (const Name& name : names) - { - if (name.boneId == bid) - { - os.format("obj.vertex_groups.new('%s')\n", name.name.c_str()); - break; - } - } - } -} - -void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const -{ - DNAANIM::RigInverter inverter(*this); - - os.format("arm = bpy.data.armatures.new('CINF_%08X')\n" - "arm_obj = bpy.data.objects.new(arm.name, arm)\n" - "bpy.context.scene.objects.link(arm_obj)\n" - "bpy.context.scene.objects.active = arm_obj\n" - "bpy.ops.object.mode_set(mode='EDIT')\n" - "arm_bone_table = {}\n", - cinfId.toUint32()); - - for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - { - zeus::simd_floats originF(bone.m_origBone.origin.simd); - zeus::simd_floats tailF(bone.m_tail.mSimd); - os.format("bone = arm.edit_bones.new('%s')\n" - "bone.head = (%f,%f,%f)\n" - "bone.tail = (%f,%f,%f)\n" - "bone.use_inherit_scale = False\n" - "arm_bone_table[%u] = bone\n", - getBoneNameFromId(bone.m_origBone.id)->c_str(), - originF[0], originF[1], originF[2], - tailF[0], tailF[1], tailF[2], - bone.m_origBone.id); - } - - for (const Bone& bone : bones) - if (bone.parentId != 97) - os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId); - - os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; - - const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION"; - for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", - getBoneNameFromId(bone.m_origBone.id)->c_str(), rotMode); -} - -std::string CINF::GetCINFArmatureName(const UniqueID32& cinfId) -{ - return hecl::Format("CINF_%08X", cinfId.toUint32()); -} - -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CINF.hpp b/DataSpec/DNAMP2/CINF.hpp index 0107d7d73..6cebbd0c1 100644 --- a/DataSpec/DNAMP2/CINF.hpp +++ b/DataSpec/DNAMP2/CINF.hpp @@ -3,45 +3,40 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DataSpec/DNACommon/RigInverter.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct CINF : BigDNA -{ +struct CINF : BigDNA { + AT_DECL_DNA + Value boneCount; + struct Bone : BigDNA { AT_DECL_DNA - Value boneCount; - struct Bone : BigDNA - { - AT_DECL_DNA - Value id; - Value parentId; - Value origin; - Value q1; - Value q2; - Value linkedCount; - Vector linked; - }; - Vector bones; + Value id; + Value parentId; + Value origin; + Value q1; + Value q2; + Value linkedCount; + Vector linked; + }; + Vector bones; - Value boneIdCount; - Vector boneIds; + Value boneIdCount; + Vector boneIds; - Value nameCount; - struct Name : BigDNA - { - AT_DECL_DNA - String<-1> name; - Value boneId; - }; - Vector names; - - atUint32 getInternalBoneIdxFromId(atUint32 id) const; - atUint32 getBoneIdxFromId(atUint32 id) const; - const std::string* getBoneNameFromId(atUint32 id) const; - void sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const; - void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const; - static std::string GetCINFArmatureName(const UniqueID32& cinfId); + Value nameCount; + struct Name : BigDNA { + AT_DECL_DNA + String<-1> name; + Value boneId; + }; + Vector names; + + atUint32 getInternalBoneIdxFromId(atUint32 id) const; + atUint32 getBoneIdxFromId(atUint32 id) const; + const std::string* getBoneNameFromId(atUint32 id) const; + void sendVertexGroupsToBlender(hecl::blender::PyOutStream& os) const; + void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID32& cinfId) const; + static std::string GetCINFArmatureName(const UniqueID32& cinfId); }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CMDL.cpp b/DataSpec/DNAMP2/CMDL.cpp index bf891670e..8c3676640 100644 --- a/DataSpec/DNAMP2/CMDL.cpp +++ b/DataSpec/DNAMP2/CMDL.cpp @@ -1,38 +1,30 @@ #include "CMDL.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -bool CMDL::Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const DNAMP2::PAK::Entry& entry, - bool, - hecl::blender::Token& btok, - std::function) -{ - /* Check for RigPair */ - const typename CharacterAssociations::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id); - CINF cinf; - CSKR cskr; - std::pair loadRp(nullptr, nullptr); - if (rp) - { - pakRouter.lookupAndReadDNA(rp->first, cskr); - pakRouter.lookupAndReadDNA(rp->second, cinf); - loadRp.first = &cskr; - loadRp.second = &cinf; - } +bool CMDL::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const DNAMP2::PAK::Entry& entry, bool, hecl::blender::Token& btok, + std::function) { + /* Check for RigPair */ + const typename CharacterAssociations::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id); + CINF cinf; + CSKR cskr; + std::pair loadRp(nullptr, nullptr); + if (rp) { + pakRouter.lookupAndReadDNA(rp->first, cskr); + pakRouter.lookupAndReadDNA(rp->second, cinf); + loadRp.first = &cskr; + loadRp.second = &cinf; + } - /* Do extract */ - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::Mesh)) - return false; - DNACMDL::ReadCMDLToBlender, MaterialSet, std::pair, DNACMDL::SurfaceHeader_2, 4> - (conn, rs, pakRouter, entry, dataSpec, loadRp); - return conn.saveBlend(); + /* Do extract */ + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::Mesh)) + return false; + DNACMDL::ReadCMDLToBlender, MaterialSet, std::pair, DNACMDL::SurfaceHeader_2, 4>( + conn, rs, pakRouter, entry, dataSpec, loadRp); + return conn.saveBlend(); } -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CMDL.hpp b/DataSpec/DNAMP2/CMDL.hpp index 281c2d638..bf4ec2b08 100644 --- a/DataSpec/DNAMP2/CMDL.hpp +++ b/DataSpec/DNAMP2/CMDL.hpp @@ -7,20 +7,12 @@ #include "CINF.hpp" #include "CSKR.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct CMDL -{ - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const DNAMP2::PAK::Entry& entry, - bool, - hecl::blender::Token& btok, - std::function); +struct CMDL { + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const DNAMP2::PAK::Entry& entry, bool, + hecl::blender::Token& btok, std::function); }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CMDLMaterials.hpp b/DataSpec/DNAMP2/CMDLMaterials.hpp index 58868a112..503d91761 100644 --- a/DataSpec/DNAMP2/CMDLMaterials.hpp +++ b/DataSpec/DNAMP2/CMDLMaterials.hpp @@ -5,78 +5,66 @@ #include "../DNAMP1/CMDLMaterials.hpp" #include "DNAMP2.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { /* Structurally identical to DNAMP1::MaterialSet except unk0 and unk1 fields */ -struct MaterialSet : BigDNA -{ - static constexpr bool OneSection() {return false;} +struct MaterialSet : BigDNA { + static constexpr bool OneSection() { return false; } + AT_DECL_DNA + DNAMP1::MaterialSet::MaterialSetHead head; + + struct Material : BigDNA { AT_DECL_DNA - DNAMP1::MaterialSet::MaterialSetHead head; + using Flags = DNAMP1::MaterialSet::Material::Flags; + Flags flags; + const Flags& getFlags() const { return flags; } - struct Material : BigDNA - { - AT_DECL_DNA - using Flags = DNAMP1::MaterialSet::Material::Flags; - Flags flags; - const Flags& getFlags() const {return flags;} + Value textureCount; + Vector textureIdxs; + using VAFlags = DNAMP1::MaterialSet::Material::VAFlags; + DNAMP1::MaterialSet::Material::VAFlags vaFlags; + const VAFlags& getVAFlags() const { return vaFlags; } + Value unk0; /* MP2 only */ + Value unk1; /* MP2 only */ + Value uniqueIdx; - Value textureCount; - Vector textureIdxs; - using VAFlags = DNAMP1::MaterialSet::Material::VAFlags; - DNAMP1::MaterialSet::Material::VAFlags vaFlags; - const VAFlags& getVAFlags() const {return vaFlags;} - Value unk0; /* MP2 only */ - Value unk1; /* MP2 only */ - Value uniqueIdx; + Vector konstCount; + Vector konstColors; - Vector konstCount; - Vector konstColors; + using BlendFactor = GX::BlendFactor; + Value blendDstFac; + Value blendSrcFac; + Vector indTexSlot; - using BlendFactor = GX::BlendFactor; - Value blendDstFac; - Value blendSrcFac; - Vector indTexSlot; + Value colorChannelCount; + Vector colorChannels; - Value colorChannelCount; - Vector colorChannels; + Value tevStageCount; + Vector tevStages; + Vector tevStageTexInfo; - Value tevStageCount; - Vector tevStages; - Vector tevStageTexInfo; + Value tcgCount; + Vector tcgs; - Value tcgCount; - Vector tcgs; + Value uvAnimsSize; + Value uvAnimsCount; + Vector uvAnims; + }; + Vector materials; - Value uvAnimsSize; - Value uvAnimsCount; - Vector uvAnims; - }; - Vector materials; + static void RegisterMaterialProps(hecl::blender::PyOutStream& out) { + DNAMP1::MaterialSet::RegisterMaterialProps(out); + } + static void ConstructMaterial(hecl::blender::PyOutStream& out, const MaterialSet::Material& material, + unsigned groupIdx, unsigned matIdx); - static void RegisterMaterialProps(hecl::blender::PyOutStream& out) - { - DNAMP1::MaterialSet::RegisterMaterialProps(out); - } - static void ConstructMaterial(hecl::blender::PyOutStream& out, - const MaterialSet::Material& material, - unsigned groupIdx, unsigned matIdx); + void readToBlender(hecl::blender::PyOutStream& os, const PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, unsigned setIdx) { + DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx); + } - void readToBlender(hecl::blender::PyOutStream& os, - const PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - unsigned setIdx) - { - DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx); - } - - void ensureTexturesExtracted(PAKRouter& pakRouter) const - { - head.ensureTexturesExtracted(pakRouter); - } + void ensureTexturesExtracted(PAKRouter& pakRouter) const { head.ensureTexturesExtracted(pakRouter); } }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CSKR.cpp b/DataSpec/DNAMP2/CSKR.cpp index 214b5bf3d..2bb48adff 100644 --- a/DataSpec/DNAMP2/CSKR.cpp +++ b/DataSpec/DNAMP2/CSKR.cpp @@ -1,21 +1,16 @@ #include "CSKR.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const -{ - atUint32 accum = 0; - for (const SkinningRule& rule : skinningRules) - { - if (idx >= accum && idx < accum + rule.vertCount) - for (const SkinningRule::Weight& weight : rule.weights) - os.format("vert[dvert_lay][%u] = %f\n", - cinf.getBoneIdxFromId(weight.boneId), - weight.weight); - accum += rule.vertCount; - } +void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const { + atUint32 accum = 0; + for (const SkinningRule& rule : skinningRules) { + if (idx >= accum && idx < accum + rule.vertCount) + for (const SkinningRule::Weight& weight : rule.weights) + os.format("vert[dvert_lay][%u] = %f\n", cinf.getBoneIdxFromId(weight.boneId), weight.weight); + accum += rule.vertCount; + } } -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/CSKR.hpp b/DataSpec/DNAMP2/CSKR.hpp index c1a236c4d..a46ccdda7 100644 --- a/DataSpec/DNAMP2/CSKR.hpp +++ b/DataSpec/DNAMP2/CSKR.hpp @@ -4,20 +4,14 @@ #include "CINF.hpp" #include "../DNAMP1/CSKR.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct CSKR : DNAMP1::CSKR -{ - Delete expl; +struct CSKR : DNAMP1::CSKR { + Delete expl; - const atInt16* getMatrixBank(size_t) const - { - return nullptr; - } + const atInt16* getMatrixBank(size_t) const { return nullptr; } - void weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const; + void weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atUint32 idx) const; }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/DNAMP2.cpp b/DataSpec/DNAMP2/DNAMP2.cpp index 570ca8b47..9a92f2175 100644 --- a/DataSpec/DNAMP2/DNAMP2.cpp +++ b/DataSpec/DNAMP2/DNAMP2.cpp @@ -19,278 +19,246 @@ #include "DataSpec/DNACommon/ATBL.hpp" #include "Runtime/GCNTypes.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { logvisor::Module Log("urde::DNAMP2"); -static bool GetNoShare(std::string_view name) -{ - std::string lowerName(name); - std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); - if (!lowerName.compare(0, 7, "metroid")) - return false; - return true; +static bool GetNoShare(std::string_view name) { + std::string lowerName(name); + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); + if (!lowerName.compare(0, 7, "metroid")) + return false; + return true; } -PAKBridge::PAKBridge(const nod::Node& node, - bool doExtract) -: m_node(node), m_pak(true, GetNoShare(node.getName())), m_doExtract(doExtract) -{ - nod::AthenaPartReadStream rs(node.beginReadStream()); - m_pak.read(rs); +PAKBridge::PAKBridge(const nod::Node& node, bool doExtract) +: m_node(node), m_pak(true, GetNoShare(node.getName())), m_doExtract(doExtract) { + nod::AthenaPartReadStream rs(node.beginReadStream()); + m_pak.read(rs); - /* Append Level String */ - for (const auto& entry : m_pak.m_entries) - { - const DNAMP2::PAK::Entry& e = entry.second; - if (e.type == FOURCC('MLVL')) - { - PAKEntryReadStream rs = e.beginReadStream(m_node); - MLVL mlvl; - mlvl.read(rs); - const DNAMP2::PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId); - if (nameEnt) - { - PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); - STRG mlvlName; - mlvlName.read(rs); - if (m_levelString.size()) - m_levelString += _SYS_STR(", "); - m_levelString += mlvlName.getSystemString(FOURCC('ENGL'), 0); - } + /* Append Level String */ + for (const auto& entry : m_pak.m_entries) { + const DNAMP2::PAK::Entry& e = entry.second; + if (e.type == FOURCC('MLVL')) { + PAKEntryReadStream rs = e.beginReadStream(m_node); + MLVL mlvl; + mlvl.read(rs); + const DNAMP2::PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId); + if (nameEnt) { + PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); + STRG mlvlName; + mlvlName.read(rs); + if (m_levelString.size()) + m_levelString += _SYS_STR(", "); + m_levelString += mlvlName.getSystemString(FOURCC('ENGL'), 0); + } + } + } +} + +static hecl::SystemString LayerName(std::string_view name) { + hecl::SystemString ret(hecl::SystemStringConv(name).sys_str()); + for (auto& ch : ret) + if (ch == _SYS_STR('/') || ch == _SYS_STR('\\')) + ch = _SYS_STR('-'); + return ret; +} + +void PAKBridge::build() { + /* First pass: build per-area/per-layer dependency map */ + for (const auto& entry : m_pak.m_entries) { + const DNAMP2::PAK::Entry& e = entry.second; + if (e.type == FOURCC('MLVL')) { + Level& level = m_levelDeps[e.id]; + + MLVL mlvl; + { + PAKEntryReadStream rs = e.beginReadStream(m_node); + mlvl.read(rs); + } + bool named; + std::string bestName = m_pak.bestEntryName(m_node, e, named); + level.name = hecl::SystemStringConv(bestName).sys_str(); + level.areas.reserve(mlvl.areaCount); + unsigned layerIdx = 0; + + /* Make MAPW available to lookup MAPAs */ + const DNAMP2::PAK::Entry* worldMapEnt = m_pak.lookupEntry(mlvl.worldMap); + std::vector mapw; + if (worldMapEnt) { + PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node); + rs.seek(8, athena::Current); + atUint32 areaCount = rs.readUint32Big(); + mapw.reserve(areaCount); + for (atUint32 i = 0; i < areaCount; ++i) + mapw.emplace_back(rs); + } + + /* Index areas */ + unsigned ai = 0; + for (const MLVL::Area& area : mlvl.areas) { + Level::Area& areaDeps = level.areas[area.areaMREAId]; + MLVL::LayerFlags& layerFlags = mlvl.layerFlags[ai]; + const DNAMP2::PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId); + if (areaNameEnt) { + STRG areaName; + { + PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node); + areaName.read(rs); + } + areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0); + areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name); } - } -} - -static hecl::SystemString LayerName(std::string_view name) -{ - hecl::SystemString ret(hecl::SystemStringConv(name).sys_str()); - for (auto& ch : ret) - if (ch == _SYS_STR('/') || ch == _SYS_STR('\\')) - ch = _SYS_STR('-'); - return ret; -} - -void PAKBridge::build() -{ - /* First pass: build per-area/per-layer dependency map */ - for (const auto& entry : m_pak.m_entries) - { - const DNAMP2::PAK::Entry& e = entry.second; - if (e.type == FOURCC('MLVL')) - { - Level& level = m_levelDeps[e.id]; - - MLVL mlvl; - { - PAKEntryReadStream rs = e.beginReadStream(m_node); - mlvl.read(rs); - } - bool named; - std::string bestName = m_pak.bestEntryName(m_node, e, named); - level.name = hecl::SystemStringConv(bestName).sys_str(); - level.areas.reserve(mlvl.areaCount); - unsigned layerIdx = 0; - - /* Make MAPW available to lookup MAPAs */ - const DNAMP2::PAK::Entry* worldMapEnt = m_pak.lookupEntry(mlvl.worldMap); - std::vector mapw; - if (worldMapEnt) - { - PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node); - rs.seek(8, athena::Current); - atUint32 areaCount = rs.readUint32Big(); - mapw.reserve(areaCount); - for (atUint32 i=0 ; ibeginReadStream(m_node); - areaName.read(rs); - } - areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0); - areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name); - } - if (areaDeps.name.empty()) - { - areaDeps.name = hecl::SystemStringConv(area.internalAreaName).sys_str(); - if (areaDeps.name.empty()) - { - std::string idStr = area.areaMREAId.toString(); - areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); - } - } - hecl::SystemChar num[16]; - hecl::SNPrintf(num, 16, _SYS_STR("%02u "), ai); - areaDeps.name = num + areaDeps.name; - - areaDeps.layers.reserve(area.depLayerCount-1); - unsigned r=0; - for (unsigned l=1 ; l> (l-1) & 0x1; - layer.name = hecl::StringUtils::TrimWhitespace(layer.name); - hecl::SNPrintf(num, 16, _SYS_STR("%02u "), l-1); - layer.name = num + layer.name; - - layer.resources.reserve(area.depLayers[l] - r); - for (; r ai) - areaDeps.resources.emplace(mapw[ai]); - ++ai; - } + if (areaDeps.name.empty()) { + areaDeps.name = hecl::SystemStringConv(area.internalAreaName).sys_str(); + if (areaDeps.name.empty()) { + std::string idStr = area.areaMREAId.toString(); + areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); + } } - } + hecl::SystemChar num[16]; + hecl::SNPrintf(num, 16, _SYS_STR("%02u "), ai); + areaDeps.name = num + areaDeps.name; - /* Second pass: cross-compare uniqueness */ - for (auto& entry : m_pak.m_entries) - { - entry.second.unique.checkEntry(*this, entry.second); + areaDeps.layers.reserve(area.depLayerCount - 1); + unsigned r = 0; + for (unsigned l = 1; l < area.depLayerCount; ++l) { + areaDeps.layers.emplace_back(); + Level::Area::Layer& layer = areaDeps.layers.back(); + layer.name = LayerName(mlvl.layerNames[layerIdx++]); + layer.active = layerFlags.flags >> (l - 1) & 0x1; + layer.name = hecl::StringUtils::TrimWhitespace(layer.name); + hecl::SNPrintf(num, 16, _SYS_STR("%02u "), l - 1); + layer.name = num + layer.name; + + layer.resources.reserve(area.depLayers[l] - r); + for (; r < area.depLayers[l]; ++r) + layer.resources.emplace(area.deps[r].id); + } + areaDeps.resources.reserve(area.depCount - r + 2); + for (; r < area.depCount; ++r) + areaDeps.resources.emplace(area.deps[r].id); + areaDeps.resources.emplace(area.areaMREAId); + if (mapw.size() > ai) + areaDeps.resources.emplace(mapw[ai]); + ++ai; + } } + } + + /* Second pass: cross-compare uniqueness */ + for (auto& entry : m_pak.m_entries) { + entry.second.unique.checkEntry(*this, entry.second); + } } -void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const -{ - for (const std::pair& entry : m_pak.m_entries) - { - if (entry.second.type == FOURCC('ANCS')) - { - PAKEntryReadStream rs = entry.second.beginReadStream(m_node); - ANCS ancs; - ancs.read(rs); - for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) - { - charAssoc.m_cmdlRigs[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf); - charAssoc.m_cskrCinfToCharacter[ci.cskr] = std::make_pair(entry.second.id, hecl::Format("%s.CSKR", ci.name.c_str())); - charAssoc.m_cskrCinfToCharacter[ci.cinf] = std::make_pair(entry.second.id, hecl::Format("CINF_%08X.CINF", ci.cinf.toUint32())); - if (ci.cmdlIce) - { - charAssoc.m_cmdlRigs[ci.cmdlIce] = std::make_pair(ci.cskrIce, ci.cinf); - charAssoc.m_cskrCinfToCharacter[ci.cskrIce] = std::make_pair(entry.second.id, hecl::Format("%s.ICE.CSKR", ci.name.c_str())); - } - } +void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + for (const std::pair& entry : m_pak.m_entries) { + if (entry.second.type == FOURCC('ANCS')) { + PAKEntryReadStream rs = entry.second.beginReadStream(m_node); + ANCS ancs; + ancs.read(rs); + for (const ANCS::CharacterSet::CharacterInfo& ci : ancs.characterSet.characters) { + charAssoc.m_cmdlRigs[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf); + charAssoc.m_cskrCinfToCharacter[ci.cskr] = + std::make_pair(entry.second.id, hecl::Format("%s.CSKR", ci.name.c_str())); + charAssoc.m_cskrCinfToCharacter[ci.cinf] = + std::make_pair(entry.second.id, hecl::Format("CINF_%08X.CINF", ci.cinf.toUint32())); + if (ci.cmdlIce) { + charAssoc.m_cmdlRigs[ci.cmdlIce] = std::make_pair(ci.cskrIce, ci.cinf); + charAssoc.m_cskrCinfToCharacter[ci.cskrIce] = + std::make_pair(entry.second.id, hecl::Format("%s.ICE.CSKR", ci.name.c_str())); } + } } + } } static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}}; void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, - std::unordered_map& addTo, - std::unordered_map& pathOverrides) const -{ - for (const std::pair& entry : m_pak.m_entries) - { - if (entry.second.type == FOURCC('MLVL')) - { - MLVL mlvl; - { - PAKEntryReadStream rs = entry.second.beginReadStream(m_node); - mlvl.read(rs); - } - hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath(); + std::unordered_map& addTo, + std::unordered_map& pathOverrides) const { + for (const std::pair& entry : m_pak.m_entries) { + if (entry.second.type == FOURCC('MLVL')) { + MLVL mlvl; + { + PAKEntryReadStream rs = entry.second.beginReadStream(m_node); + mlvl.read(rs); + } + hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath(); - if (mlvl.worldNameId) - pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _SYS_STR("!name.yaml")); + if (mlvl.worldNameId) + pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _SYS_STR("!name.yaml")); - for (const MLVL::Area& area : mlvl.areas) - { - hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); - if (area.areaNameId) - pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _SYS_STR("!name.yaml")); - } + for (const MLVL::Area& area : mlvl.areas) { + hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); + if (area.areaNameId) + pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _SYS_STR("!name.yaml")); + } - if (mlvl.worldMap) - { - const nod::Node* mapNode; - const DNAMP2::PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode); - if (mapEntry) - { - PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode); - u32 magic = rs.readUint32Big(); - if (magic == 0xDEADF00D) - { - rs.readUint32Big(); - u32 count = rs.readUint32Big(); - for (u32 i=0 ; ibeginReadStream(*mapNode); + u32 magic = rs.readUint32Big(); + if (magic == 0xDEADF00D) { + rs.readUint32Big(); + u32 count = rs.readUint32Big(); + for (u32 i = 0; i < count && i < mlvl.areas.size(); ++i) { + MLVL::Area& areaData = mlvl.areas[i]; + UniqueID32 mapaId; + mapaId.read(rs); + addTo[mapaId] = zeus::CMatrix4f(areaData.transformMtx[0], areaData.transformMtx[1], + areaData.transformMtx[2], BottomRow) + .transposed(); } + } } + } } + } } ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, const DNAMP2::PAK& pak, - const DNAMP2::PAK::Entry& entry) -{ - switch (entry.type) - { - case SBIG('HINT'): - return {DNAMP1::HINT::Extract, {_SYS_STR(".yaml")}}; - case SBIG('STRG'): - return {STRG::Extract, {_SYS_STR(".yaml")}}; - case SBIG('TXTR'): - return {TXTR::Extract, {_SYS_STR(".png")}}; - case SBIG('AFSM'): - return {AFSM::Extract, {_SYS_STR(".yaml")}}; - case SBIG('SAVW'): - return {SAVWCommon::ExtractSAVW, {_SYS_STR(".yaml")}}; - case SBIG('CMDL'): - return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; - case SBIG('ANCS'): - return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; - case SBIG('MLVL'): - return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3}; - case SBIG('MREA'): - return {MREA::Extract, {_SYS_STR(".blend")}, 4}; - case SBIG('MAPA'): - return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; - case SBIG('MAPU'): - return {MAPU::Extract, {_SYS_STR(".blend")}, 5}; - case SBIG('FSM2'): - return {DNAFSM2::ExtractFSM2, {_SYS_STR(".yaml")}}; - case SBIG('FONT'): - return {DNAFont::ExtractFONT, {_SYS_STR(".yaml")}}; - case SBIG('DGRP'): - return {DNADGRP::ExtractDGRP, {_SYS_STR(".yaml")}}; - case SBIG('AGSC'): - return {AGSC::Extract, {}}; - case SBIG('CSNG'): - return {DNAMP1::CSNG::Extract, {_SYS_STR(".mid"), _SYS_STR(".yaml")}}; - case SBIG('ATBL'): - return {DNAAudio::ATBL::Extract, {_SYS_STR(".yaml")}}; - } - return {}; + const DNAMP2::PAK::Entry& entry) { + switch (entry.type) { + case SBIG('HINT'): + return {DNAMP1::HINT::Extract, {_SYS_STR(".yaml")}}; + case SBIG('STRG'): + return {STRG::Extract, {_SYS_STR(".yaml")}}; + case SBIG('TXTR'): + return {TXTR::Extract, {_SYS_STR(".png")}}; + case SBIG('AFSM'): + return {AFSM::Extract, {_SYS_STR(".yaml")}}; + case SBIG('SAVW'): + return {SAVWCommon::ExtractSAVW, {_SYS_STR(".yaml")}}; + case SBIG('CMDL'): + return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; + case SBIG('ANCS'): + return {ANCS::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; + case SBIG('MLVL'): + return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3}; + case SBIG('MREA'): + return {MREA::Extract, {_SYS_STR(".blend")}, 4}; + case SBIG('MAPA'): + return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; + case SBIG('MAPU'): + return {MAPU::Extract, {_SYS_STR(".blend")}, 5}; + case SBIG('FSM2'): + return {DNAFSM2::ExtractFSM2, {_SYS_STR(".yaml")}}; + case SBIG('FONT'): + return {DNAFont::ExtractFONT, {_SYS_STR(".yaml")}}; + case SBIG('DGRP'): + return {DNADGRP::ExtractDGRP, {_SYS_STR(".yaml")}}; + case SBIG('AGSC'): + return {AGSC::Extract, {}}; + case SBIG('CSNG'): + return {DNAMP1::CSNG::Extract, {_SYS_STR(".mid"), _SYS_STR(".yaml")}}; + case SBIG('ATBL'): + return {DNAAudio::ATBL::Extract, {_SYS_STR(".yaml")}}; + } + return {}; } -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/DNAMP2.hpp b/DataSpec/DNAMP2/DNAMP2.hpp index 8840c8e80..279bba2c3 100644 --- a/DataSpec/DNAMP2/DNAMP2.hpp +++ b/DataSpec/DNAMP2/DNAMP2.hpp @@ -3,39 +3,36 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "PAK.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { extern logvisor::Module Log; /* MP2-specific, one-shot PAK traversal/extraction class */ -class PAKBridge -{ - const nod::Node& m_node; - DNAMP2::PAK m_pak; +class PAKBridge { + const nod::Node& m_node; + DNAMP2::PAK m_pak; + public: - bool m_doExtract; - using Level = DataSpec::Level; - std::unordered_map m_levelDeps; - hecl::SystemString m_levelString; + bool m_doExtract; + using Level = DataSpec::Level; + std::unordered_map m_levelDeps; + hecl::SystemString m_levelString; - PAKBridge(const nod::Node& node, bool doExtract=true); - void build(); - static ResExtractor LookupExtractor(const nod::Node& pakNode, - const DNAMP2::PAK& pak, const DNAMP2::PAK::Entry& entry); - std::string_view getName() const {return m_node.getName();} - hecl::SystemStringView getLevelString() const {return m_levelString;} + PAKBridge(const nod::Node& node, bool doExtract = true); + void build(); + static ResExtractor LookupExtractor(const nod::Node& pakNode, const DNAMP2::PAK& pak, + const DNAMP2::PAK::Entry& entry); + std::string_view getName() const { return m_node.getName(); } + hecl::SystemStringView getLevelString() const { return m_levelString; } - using PAKType = DNAMP2::PAK; - const PAKType& getPAK() const {return m_pak;} - const nod::Node& getNode() const {return m_node;} + using PAKType = DNAMP2::PAK; + const PAKType& getPAK() const { return m_pak; } + const nod::Node& getNode() const { return m_node; } - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; - void addMAPATransforms(PAKRouter& pakRouter, - std::unordered_map& addTo, - std::unordered_map& pathOverrides) const; + void addMAPATransforms(PAKRouter& pakRouter, std::unordered_map& addTo, + std::unordered_map& pathOverrides) const; }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/DeafBabe.cpp b/DataSpec/DNAMP2/DeafBabe.cpp index 72d6d98d5..995222068 100644 --- a/DataSpec/DNAMP2/DeafBabe.cpp +++ b/DataSpec/DNAMP2/DeafBabe.cpp @@ -1,271 +1,275 @@ #include "DeafBabe.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) -{ - os << "TYPE_COLORS = {'NoSFX':(0.0, 0.0, 0.0),\n" - " 'Stone':(1.0, 0.43, 0.15),\n" - " 'Metal':(0.5, 0.5, 0.5),\n" - " 'Grass':(0.0, 0.42, 0.01)," - " 'Ice':(0.0, 0.1, 0.1),\n" - " 'Metal Grating':(0.09, 0.09, 0.09),\n" - " 'Phazon':(0.24, 0.0, 0.21),\n" - " 'Dirt':(0.1, 0.07, 0.05),\n" - " 'Stone':(0.12, 0.12, 0.12),\n" - " 'SP Metal':(0.41, 0.44, 0.5),\n" - " 'Snow':(0.9, 1.0, 1.0),\n" - " 'Fabric':(0.27, 0.34, 0.39),\n" - " 'Moth/Seed Organics':(0.0, 0.02, 0.05),\n" - " 'Glass':(0.27, 0.38, 0.9),\n" - " 'Shield':(1.0, 0.6, 0.0),\n" - " 'Web':(1.0, 1.0, 0.28),\n" - " 'Sand':(0.53, 0.44, 0.21),\n" - " 'Wood':(0.30, 0.15, 0.03),\n" - " 'Organic':(0.19, 0.45, 0.2),\n" - " 'Rubber':(0.09, 0.02, 0.01)}\n" - "\n" - "# Diffuse Color Maker\n" - "def make_color(index, mat_type, name):\n" - " new_mat = bpy.data.materials.new(name)\n" - " if mat_type in TYPE_COLORS:\n" - " new_mat.diffuse_color = TYPE_COLORS[mat_type]\n" - " else:\n" - " new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" - " return new_mat\n" - "\n" - "bpy.types.Material.retro_unknown = bpy.props.BoolProperty(description='Retro: Unknown (U)')\n" - "bpy.types.Material.retro_surface_stone = bpy.props.BoolProperty(description='Retro Surface: Stone')\n" - "bpy.types.Material.retro_surface_metal = bpy.props.BoolProperty(description='Retro Surface: Metal')\n" - "bpy.types.Material.retro_surface_grass = bpy.props.BoolProperty(description='Retro Surface: Grass')\n" - "bpy.types.Material.retro_surface_ice = bpy.props.BoolProperty(description='Retro Surface: Ice')\n" - "bpy.types.Material.retro_pillar = bpy.props.BoolProperty(description='Retro Pillar (I)')\n" - "bpy.types.Material.retro_surface_metal_grating = bpy.props.BoolProperty(description='Retro Surface: Metal Grating')\n" - "bpy.types.Material.retro_surface_phazon = bpy.props.BoolProperty(description='Retro Surface: Phazon')\n" - "bpy.types.Material.retro_surface_dirt = bpy.props.BoolProperty(description='Retro Surface: Rock')\n" - "bpy.types.Material.retro_surface_sp_metal = bpy.props.BoolProperty(description='Retro Surface: Lava')\n" - "bpy.types.Material.retro_surface_snow = bpy.props.BoolProperty(description='Retro Surface: Snow')\n" - "bpy.types.Material.retro_surface_fabric = bpy.props.BoolProperty(description='Retro Surface: fabric')\n" - "bpy.types.Material.retro_half_pipe = bpy.props.BoolProperty(description='Retro: Half Pipe (H)')\n" - "bpy.types.Material.retro_unused3 = bpy.props.BoolProperty(description='Retro: Unused 3 (U)')\n" - "bpy.types.Material.retro_unused4 = bpy.props.BoolProperty(description='Retro: Unused 4 (U)')\n" - "bpy.types.Material.retro_surface_mud = bpy.props.BoolProperty(description='Retro Surface: Mud')\n" - "bpy.types.Material.retro_surface_glass = bpy.props.BoolProperty(description='Retro Surface: Glass')\n" - "bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(description='Retro Surface: Shield')\n" - "bpy.types.Material.retro_surface_sand = bpy.props.BoolProperty(description='Retro Surface: Sand')\n" - "bpy.types.Material.retro_surface_moth_or_seed_organics = bpy.props.BoolProperty(description='Retro Surface: Moth/Seed Organics')\n" - "bpy.types.Material.retro_surface_web = bpy.props.BoolProperty(description='Retro Surface: Web')\n" - "bpy.types.Material.retro_projectile_passthrough = bpy.props.BoolProperty(description='Retro: Projectile Passthrough (P)')\n" - "bpy.types.Material.retro_camera_passthrough = bpy.props.BoolProperty(description='Retro: Camera Passthrough (O)')\n" - "bpy.types.Material.retro_surface_wood = bpy.props.BoolProperty(description='Retro Surface: Wood')\n" - "bpy.types.Material.retro_surface_organic = bpy.props.BoolProperty(description='Retro Surface: Organic')\n" - "bpy.types.Material.retro_surface_rubber = bpy.props.BoolProperty(description='Retro Surface: Rubber')\n" - "bpy.types.Material.retro_see_through = bpy.props.BoolProperty(description='Retro: See Through (T)')\n" - "bpy.types.Material.retro_scan_passthrough = bpy.props.BoolProperty(description='Retro: Scan Passthrough (S)')\n" - "bpy.types.Material.retro_ai_passthrough = bpy.props.BoolProperty(description='Retro: AI Passthrough (A)')\n" - "bpy.types.Material.retro_ceiling = bpy.props.BoolProperty(description='Retro: Ceiling (C)')\n" - "bpy.types.Material.retro_wall = bpy.props.BoolProperty(description='Retro: Wall (W)')\n" - "bpy.types.Material.retro_floor = bpy.props.BoolProperty(description='Retro: Floor (F)')\n" - "bpy.types.Material.retro_ai_block = bpy.props.BoolProperty(description='Retro: AI Block (B)')\n" - "bpy.types.Material.retro_jump_not_allowed = bpy.props.BoolProperty(description='Retro: Jump Not Allowed (J)')\n" - "bpy.types.Material.retro_spider_ball = bpy.props.BoolProperty(description='Retro: Spider Ball (D)')\n" - "bpy.types.Material.retro_screw_attack_wall_jump = bpy.props.BoolProperty(description='Retro: Screw Attack Wall Jump (R)')\n" - "\n" - "material_dict = {}\n" - "material_index = []\n" - "def get_type_id(data):\n" - "\n" - " ret = 0\n" - " for i in range(1, 26):\n" - " if i == 5 or i == 13 or i == 14 or i == 15 or i == 20 or i == 21 or i == 24:\n" - " continue\n" - " if ((data >> i) & 1):\n" - " ret = i\n" - " return ret\n" - "\n" - "def select_material(data):\n" - "\n" - " type_id = get_type_id(data)\n" - " mat_type = str(type_id)\n" - " if type_id == 0:\n" - " mat_type = 'NoSFX'\n" - " if type_id == 1:\n" - " mat_type = 'Stone'\n" - " elif type_id == 2:\n" - " mat_type = 'Metal'\n" - " elif type_id == 3:\n" - " mat_type = 'Grass'\n" - " elif type_id == 4:\n" - " mat_type = 'Ice'\n" - " elif type_id == 6:\n" - " mat_type = 'Metal Grating'\n" - " elif type_id == 7:\n" - " mat_type = 'Phazon'\n" - " elif type_id == 8:\n" - " mat_type = 'Dirt'\n" - " elif type_id == 9:\n" - " mat_type = 'SP Metal'\n" - " elif type_id == 10:\n" - " mat_type = 'Glass'\n" - " elif type_id == 11:\n" - " mat_type = 'Snow'\n" - " elif type_id == 12:\n" - " mat_type = 'Fabric'\n" - " elif type_id == 16:\n" - " mat_type = 'Shield'\n" - " elif type_id == 17:\n" - " mat_type = 'Sand'\n" - " elif type_id == 18:\n" - " mat_type = 'Moth/Seed Organics'\n" - " elif type_id == 19:\n" - " mat_type = 'Web'\n" - " elif type_id == 22:\n" - " mat_type = 'Wood'\n" - " elif type_id == 23:\n" - " mat_type = 'Organic'\n" - " elif type_id == 25:\n" - " mat_type = 'Rubber'\n" - "\n" - " mat_flags = ''\n" - " if ((data >> 0) & 1):\n" - " mat_flags += 'U'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 5) & 1):\n" - " mat_flags += 'I'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 13) & 1):\n" - " mat_flags += 'H'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 14) & 1):\n" - " mat_flags += 'U'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 15) & 1):\n" - " mat_flags += 'U'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 20) & 1):\n" - " mat_flags += 'P'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 21) & 1):\n" - " mat_flags += 'O'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 26) & 1):\n" - " mat_flags += 'T'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 27) & 1):\n" - " mat_flags += 'S'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 28) & 1):\n" - " mat_flags += 'A'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 29) & 1):\n" - " mat_flags += 'C'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 30) & 1):\n" - " mat_flags += 'W'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 31) & 1):\n" - " mat_flags += 'F'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 48) & 1):\n" - " mat_flags += 'B'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 58) & 1):\n" - " mat_flags += 'J'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 61) & 1):\n" - " mat_flags += 'D'\n" - " else:\n" - " mat_flags += 'x'\n" - " if ((data >> 62) & 1):\n" - " mat_flags += 'R'\n" - " else:\n" - " mat_flags += 'x'\n" - "\n" - " if len(mat_flags) > 0:\n" - " mat_flags = ' ' + mat_flags\n" - "\n" - " mat_name = mat_type + mat_flags\n" - "\n" - " if mat_name in material_index:\n" - " return material_index.index(mat_name)\n" - " elif mat_name in material_dict:\n" - " material_index.append(mat_name)\n" - " return len(material_index)-1\n" - " else:\n" - " mat = make_color(len(material_dict), mat_type, mat_name)\n" - " mat.diffuse_intensity = 1.0\n" - " mat.specular_intensity = 0.0\n" - " mat.retro_unknown = ((data >> 0) & 1)\n" - " mat.retro_surface_stone = ((data >> 1) & 1)\n" - " mat.retro_surface_metal = ((data >> 2) & 1)\n" - " mat.retro_surface_grass = ((data >> 3) & 1) \n" - " mat.retro_surface_ice = ((data >> 4) & 1)\n" - " mat.retro_pillar = ((data >> 5) & 1)\n" - " mat.retro_surface_metal_grating = ((data >> 6) & 1)\n" - " mat.retro_surface_phazon = ((data >> 7) & 1)\n" - " mat.retro_surface_dirt = ((data >> 8) & 1)\n" - " mat.retro_surface_sp_metal = ((data >> 9) & 1)\n" - " mat.retro_surface_glass = ((data >> 10) & 1)\n" - " mat.retro_surface_snow = ((data >> 11) & 1)\n" - " mat.retro_surface_fabric = ((data >> 12) & 1)\n" - " mat.retro_half_pipe = ((data >> 13) & 1)\n" - " mat.retro_unused3 = ((data >> 14) & 1)\n" - " mat.retro_unused4 = ((data >> 15) & 1)\n" - " mat.retro_surface_shield = ((data >> 16) & 1)\n" - " mat.retro_surface_sand = ((data >> 17) & 1)\n" - " mat.retro_surface_moth_or_seed_organics = ((data >> 18) & 1)\n" - " mat.retro_surface_web = ((data >> 19) & 1)\n" - " mat.retro_projectile_passthrough = ((data >> 20) & 1)\n" - " mat.retro_camera_passthrough = ((data >> 21) & 1)\n" - " mat.retro_surface_wood = ((data >> 22) & 1)\n" - " mat.retro_surface_organic = ((data >> 23) & 1)\n" - " mat.retro_surface_rubber = ((data >> 25) & 1)\n" - " mat.retro_see_through = ((data >> 26) & 1)\n" - " mat.retro_scan_passthrough = ((data >> 27) & 1)\n" - " mat.retro_ai_passthrough = ((data >> 28) & 1)\n" - " mat.retro_ceiling = ((data >> 29) & 1)\n" - " mat.retro_wall= ((data >> 30) & 1)\n" - " mat.retro_floor = ((data >> 31) & 1)\n" - " mat.retro_ai_block = ((data >> 48) & 1)\n" - " mat.retro_jump_not_allowed = ((data >> 58) & 1)\n" - " mat.retro_spider_ball = ((data >> 61) & 1)\n" - " mat.retro_screw_attack_wall_jump = ((data >> 62) & 1)\n" - " material_dict[mat_name] = mat\n" - " material_index.append(mat_name)\n" - " return len(material_index)-1\n" - "\n" - "\n"; +void DeafBabe::BlenderInit(hecl::blender::PyOutStream& os) { + os << "TYPE_COLORS = {'NoSFX':(0.0, 0.0, 0.0),\n" + " 'Stone':(1.0, 0.43, 0.15),\n" + " 'Metal':(0.5, 0.5, 0.5),\n" + " 'Grass':(0.0, 0.42, 0.01)," + " 'Ice':(0.0, 0.1, 0.1),\n" + " 'Metal Grating':(0.09, 0.09, 0.09),\n" + " 'Phazon':(0.24, 0.0, 0.21),\n" + " 'Dirt':(0.1, 0.07, 0.05),\n" + " 'Stone':(0.12, 0.12, 0.12),\n" + " 'SP Metal':(0.41, 0.44, 0.5),\n" + " 'Snow':(0.9, 1.0, 1.0),\n" + " 'Fabric':(0.27, 0.34, 0.39),\n" + " 'Moth/Seed Organics':(0.0, 0.02, 0.05),\n" + " 'Glass':(0.27, 0.38, 0.9),\n" + " 'Shield':(1.0, 0.6, 0.0),\n" + " 'Web':(1.0, 1.0, 0.28),\n" + " 'Sand':(0.53, 0.44, 0.21),\n" + " 'Wood':(0.30, 0.15, 0.03),\n" + " 'Organic':(0.19, 0.45, 0.2),\n" + " 'Rubber':(0.09, 0.02, 0.01)}\n" + "\n" + "# Diffuse Color Maker\n" + "def make_color(index, mat_type, name):\n" + " new_mat = bpy.data.materials.new(name)\n" + " if mat_type in TYPE_COLORS:\n" + " new_mat.diffuse_color = TYPE_COLORS[mat_type]\n" + " else:\n" + " new_mat.diffuse_color.hsv = ((index / 6.0) % 1.0, 1.0-((index // 6) / 6.0), 1)\n" + " return new_mat\n" + "\n" + "bpy.types.Material.retro_unknown = bpy.props.BoolProperty(description='Retro: Unknown (U)')\n" + "bpy.types.Material.retro_surface_stone = bpy.props.BoolProperty(description='Retro Surface: Stone')\n" + "bpy.types.Material.retro_surface_metal = bpy.props.BoolProperty(description='Retro Surface: Metal')\n" + "bpy.types.Material.retro_surface_grass = bpy.props.BoolProperty(description='Retro Surface: Grass')\n" + "bpy.types.Material.retro_surface_ice = bpy.props.BoolProperty(description='Retro Surface: Ice')\n" + "bpy.types.Material.retro_pillar = bpy.props.BoolProperty(description='Retro Pillar (I)')\n" + "bpy.types.Material.retro_surface_metal_grating = bpy.props.BoolProperty(description='Retro Surface: Metal " + "Grating')\n" + "bpy.types.Material.retro_surface_phazon = bpy.props.BoolProperty(description='Retro Surface: Phazon')\n" + "bpy.types.Material.retro_surface_dirt = bpy.props.BoolProperty(description='Retro Surface: Rock')\n" + "bpy.types.Material.retro_surface_sp_metal = bpy.props.BoolProperty(description='Retro Surface: Lava')\n" + "bpy.types.Material.retro_surface_snow = bpy.props.BoolProperty(description='Retro Surface: Snow')\n" + "bpy.types.Material.retro_surface_fabric = bpy.props.BoolProperty(description='Retro Surface: fabric')\n" + "bpy.types.Material.retro_half_pipe = bpy.props.BoolProperty(description='Retro: Half Pipe (H)')\n" + "bpy.types.Material.retro_unused3 = bpy.props.BoolProperty(description='Retro: Unused 3 (U)')\n" + "bpy.types.Material.retro_unused4 = bpy.props.BoolProperty(description='Retro: Unused 4 (U)')\n" + "bpy.types.Material.retro_surface_mud = bpy.props.BoolProperty(description='Retro Surface: Mud')\n" + "bpy.types.Material.retro_surface_glass = bpy.props.BoolProperty(description='Retro Surface: Glass')\n" + "bpy.types.Material.retro_surface_shield = bpy.props.BoolProperty(description='Retro Surface: Shield')\n" + "bpy.types.Material.retro_surface_sand = bpy.props.BoolProperty(description='Retro Surface: Sand')\n" + "bpy.types.Material.retro_surface_moth_or_seed_organics = bpy.props.BoolProperty(description='Retro Surface: " + "Moth/Seed Organics')\n" + "bpy.types.Material.retro_surface_web = bpy.props.BoolProperty(description='Retro Surface: Web')\n" + "bpy.types.Material.retro_projectile_passthrough = bpy.props.BoolProperty(description='Retro: Projectile " + "Passthrough (P)')\n" + "bpy.types.Material.retro_camera_passthrough = bpy.props.BoolProperty(description='Retro: Camera Passthrough " + "(O)')\n" + "bpy.types.Material.retro_surface_wood = bpy.props.BoolProperty(description='Retro Surface: Wood')\n" + "bpy.types.Material.retro_surface_organic = bpy.props.BoolProperty(description='Retro Surface: Organic')\n" + "bpy.types.Material.retro_surface_rubber = bpy.props.BoolProperty(description='Retro Surface: Rubber')\n" + "bpy.types.Material.retro_see_through = bpy.props.BoolProperty(description='Retro: See Through (T)')\n" + "bpy.types.Material.retro_scan_passthrough = bpy.props.BoolProperty(description='Retro: Scan Passthrough " + "(S)')\n" + "bpy.types.Material.retro_ai_passthrough = bpy.props.BoolProperty(description='Retro: AI Passthrough (A)')\n" + "bpy.types.Material.retro_ceiling = bpy.props.BoolProperty(description='Retro: Ceiling (C)')\n" + "bpy.types.Material.retro_wall = bpy.props.BoolProperty(description='Retro: Wall (W)')\n" + "bpy.types.Material.retro_floor = bpy.props.BoolProperty(description='Retro: Floor (F)')\n" + "bpy.types.Material.retro_ai_block = bpy.props.BoolProperty(description='Retro: AI Block (B)')\n" + "bpy.types.Material.retro_jump_not_allowed = bpy.props.BoolProperty(description='Retro: Jump Not Allowed " + "(J)')\n" + "bpy.types.Material.retro_spider_ball = bpy.props.BoolProperty(description='Retro: Spider Ball (D)')\n" + "bpy.types.Material.retro_screw_attack_wall_jump = bpy.props.BoolProperty(description='Retro: Screw Attack " + "Wall Jump (R)')\n" + "\n" + "material_dict = {}\n" + "material_index = []\n" + "def get_type_id(data):\n" + "\n" + " ret = 0\n" + " for i in range(1, 26):\n" + " if i == 5 or i == 13 or i == 14 or i == 15 or i == 20 or i == 21 or i == 24:\n" + " continue\n" + " if ((data >> i) & 1):\n" + " ret = i\n" + " return ret\n" + "\n" + "def select_material(data):\n" + "\n" + " type_id = get_type_id(data)\n" + " mat_type = str(type_id)\n" + " if type_id == 0:\n" + " mat_type = 'NoSFX'\n" + " if type_id == 1:\n" + " mat_type = 'Stone'\n" + " elif type_id == 2:\n" + " mat_type = 'Metal'\n" + " elif type_id == 3:\n" + " mat_type = 'Grass'\n" + " elif type_id == 4:\n" + " mat_type = 'Ice'\n" + " elif type_id == 6:\n" + " mat_type = 'Metal Grating'\n" + " elif type_id == 7:\n" + " mat_type = 'Phazon'\n" + " elif type_id == 8:\n" + " mat_type = 'Dirt'\n" + " elif type_id == 9:\n" + " mat_type = 'SP Metal'\n" + " elif type_id == 10:\n" + " mat_type = 'Glass'\n" + " elif type_id == 11:\n" + " mat_type = 'Snow'\n" + " elif type_id == 12:\n" + " mat_type = 'Fabric'\n" + " elif type_id == 16:\n" + " mat_type = 'Shield'\n" + " elif type_id == 17:\n" + " mat_type = 'Sand'\n" + " elif type_id == 18:\n" + " mat_type = 'Moth/Seed Organics'\n" + " elif type_id == 19:\n" + " mat_type = 'Web'\n" + " elif type_id == 22:\n" + " mat_type = 'Wood'\n" + " elif type_id == 23:\n" + " mat_type = 'Organic'\n" + " elif type_id == 25:\n" + " mat_type = 'Rubber'\n" + "\n" + " mat_flags = ''\n" + " if ((data >> 0) & 1):\n" + " mat_flags += 'U'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 5) & 1):\n" + " mat_flags += 'I'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 13) & 1):\n" + " mat_flags += 'H'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 14) & 1):\n" + " mat_flags += 'U'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 15) & 1):\n" + " mat_flags += 'U'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 20) & 1):\n" + " mat_flags += 'P'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 21) & 1):\n" + " mat_flags += 'O'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 26) & 1):\n" + " mat_flags += 'T'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 27) & 1):\n" + " mat_flags += 'S'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 28) & 1):\n" + " mat_flags += 'A'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 29) & 1):\n" + " mat_flags += 'C'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 30) & 1):\n" + " mat_flags += 'W'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 31) & 1):\n" + " mat_flags += 'F'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 48) & 1):\n" + " mat_flags += 'B'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 58) & 1):\n" + " mat_flags += 'J'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 61) & 1):\n" + " mat_flags += 'D'\n" + " else:\n" + " mat_flags += 'x'\n" + " if ((data >> 62) & 1):\n" + " mat_flags += 'R'\n" + " else:\n" + " mat_flags += 'x'\n" + "\n" + " if len(mat_flags) > 0:\n" + " mat_flags = ' ' + mat_flags\n" + "\n" + " mat_name = mat_type + mat_flags\n" + "\n" + " if mat_name in material_index:\n" + " return material_index.index(mat_name)\n" + " elif mat_name in material_dict:\n" + " material_index.append(mat_name)\n" + " return len(material_index)-1\n" + " else:\n" + " mat = make_color(len(material_dict), mat_type, mat_name)\n" + " mat.diffuse_intensity = 1.0\n" + " mat.specular_intensity = 0.0\n" + " mat.retro_unknown = ((data >> 0) & 1)\n" + " mat.retro_surface_stone = ((data >> 1) & 1)\n" + " mat.retro_surface_metal = ((data >> 2) & 1)\n" + " mat.retro_surface_grass = ((data >> 3) & 1) \n" + " mat.retro_surface_ice = ((data >> 4) & 1)\n" + " mat.retro_pillar = ((data >> 5) & 1)\n" + " mat.retro_surface_metal_grating = ((data >> 6) & 1)\n" + " mat.retro_surface_phazon = ((data >> 7) & 1)\n" + " mat.retro_surface_dirt = ((data >> 8) & 1)\n" + " mat.retro_surface_sp_metal = ((data >> 9) & 1)\n" + " mat.retro_surface_glass = ((data >> 10) & 1)\n" + " mat.retro_surface_snow = ((data >> 11) & 1)\n" + " mat.retro_surface_fabric = ((data >> 12) & 1)\n" + " mat.retro_half_pipe = ((data >> 13) & 1)\n" + " mat.retro_unused3 = ((data >> 14) & 1)\n" + " mat.retro_unused4 = ((data >> 15) & 1)\n" + " mat.retro_surface_shield = ((data >> 16) & 1)\n" + " mat.retro_surface_sand = ((data >> 17) & 1)\n" + " mat.retro_surface_moth_or_seed_organics = ((data >> 18) & 1)\n" + " mat.retro_surface_web = ((data >> 19) & 1)\n" + " mat.retro_projectile_passthrough = ((data >> 20) & 1)\n" + " mat.retro_camera_passthrough = ((data >> 21) & 1)\n" + " mat.retro_surface_wood = ((data >> 22) & 1)\n" + " mat.retro_surface_organic = ((data >> 23) & 1)\n" + " mat.retro_surface_rubber = ((data >> 25) & 1)\n" + " mat.retro_see_through = ((data >> 26) & 1)\n" + " mat.retro_scan_passthrough = ((data >> 27) & 1)\n" + " mat.retro_ai_passthrough = ((data >> 28) & 1)\n" + " mat.retro_ceiling = ((data >> 29) & 1)\n" + " mat.retro_wall= ((data >> 30) & 1)\n" + " mat.retro_floor = ((data >> 31) & 1)\n" + " mat.retro_ai_block = ((data >> 48) & 1)\n" + " mat.retro_jump_not_allowed = ((data >> 58) & 1)\n" + " mat.retro_spider_ball = ((data >> 61) & 1)\n" + " mat.retro_screw_attack_wall_jump = ((data >> 62) & 1)\n" + " material_dict[mat_name] = mat\n" + " material_index.append(mat_name)\n" + " return len(material_index)-1\n" + "\n" + "\n"; } -void DeafBabe::insertNoClimb(hecl::blender::PyOutStream& os) const -{ - for (atInt16 edgeIdx : noClimbEdges) - { - if (edgeIdx == -1) - continue; - const Edge& edge = edgeVertConnections[edgeIdx]; - os.format("edge = col_bm.edges.get((col_bm.verts[%u], col_bm.verts[%u]))\n" - "if edge:\n" - " edge.seam = True\n", - edge.verts[0], edge.verts[1]); - } +void DeafBabe::insertNoClimb(hecl::blender::PyOutStream& os) const { + for (atInt16 edgeIdx : noClimbEdges) { + if (edgeIdx == -1) + continue; + const Edge& edge = edgeVertConnections[edgeIdx]; + os.format( + "edge = col_bm.edges.get((col_bm.verts[%u], col_bm.verts[%u]))\n" + "if edge:\n" + " edge.seam = True\n", + edge.verts[0], edge.verts[1]); + } } -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/DeafBabe.hpp b/DataSpec/DNAMP2/DeafBabe.hpp index 68c8c0647..5ebbf267a 100644 --- a/DataSpec/DNAMP2/DeafBabe.hpp +++ b/DataSpec/DNAMP2/DeafBabe.hpp @@ -2,143 +2,244 @@ #include "../DNAMP1/DeafBabe.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct DeafBabe : BigDNA -{ +struct DeafBabe : BigDNA { + AT_DECL_DNA + using BspNodeType = DataSpec::BspNodeType; + + struct Material : BigDNA { AT_DECL_DNA - using BspNodeType = DataSpec::BspNodeType; - - struct Material : BigDNA - { - AT_DECL_DNA - Value material = 0; - bool unknown() const { return material & 1; } - void setUnknown(bool v) { material &= ~1; material |= atUint64(v); } - bool surfaceStone() const { return (material >> 1ull) & 1; } - void setSurfaceStone(bool v) { material &= ~(1ull << 1ull); material |= (atUint64(v) << 1ull); } - bool surfaceMetal() const { return (material >> 2) & 1; } - void setSurfaceMetal(bool v) { material &= ~(1ull << 2ull); material |= (atUint64(v) << 2ull); } - bool surfaceGrass() const { return (material >> 3) & 1; } - void setSurfaceGrass(bool v) { material &= ~(1ull << 3ull); material |= (atUint64(v) << 3ull); } - bool surfaceIce() const { return (material >> 4ull) & 1; } - void setSurfaceIce(bool v) { material &= ~(1ull << 4ull); material |= (atUint64(v) << 4ull); } - bool pillar() const { return (material >> 5ull) & 1; } - void setPillar(bool v) { material &= ~(1ull << 5ull); material |= (atUint64(v) << 5ull); } - bool surfaceMetalGrating() const { return (material >> 6ull) & 1; } - void setSurfaceMetalGrating(bool v) { material &= ~(1ull << 6ull); material |= (atUint64(v) << 6ull); } - bool surfacePhazon() const { return (material >> 7ull) & 1; } - void setSurfacePhazon(bool v) { material &= ~(1ull << 7ull); material |= (atUint64(v) << 7ull); } - bool surfaceDirt() const { return (material >> 8ull) & 1; } - void setSurfaceDirt(bool v) { material &= ~(1ull << 8); material |= (atUint64(v) << 8ull); } - bool surfaceSPMetal() const {return (material >> 9ull) & 1; } - void setSurfaceSPMetal(bool v) { material &= ~(1ull << 9ull); material |= (atUint64(v) << 9ull); } - bool surfaceGlass() const { return (material >> 10ull) & 1; } - void setSurfaceGlass(bool v) { material &= ~(1ull << 10ull); material |= (atUint64(v) << 10ull); } - bool surfaceSnow() const { return (material >> 11ull) & 1; } - void setSurfaceSnow(bool v) { material &= ~(1ull << 11ull); material |= (atUint64(v) << 11ull); } - bool surfaceFabric() const { return (material >> 12ull) & 1; } - void setSurfaceFabric(bool v) { material &= ~(1ull << 12ull); material |= (atUint64(v) << 12ull); } - bool halfPipe() const { return (material >> 13ull) & 1; } - void setHalfPipe(bool v) { material &= ~(1ull << 13ull); material |= (atUint64(v) << 13ull); } - bool unused3() const { return (material >> 14ull) & 1; } - void setUnused3(bool v) { material &= ~(1ull << 14ull); material |= (atUint64(v) << 14ull); } - bool unused4() const { return (material >> 15ull) & 1; } - void setUnused4(bool v) { material &= ~(1ull << 15ull); material |= (atUint64(v) << 15ull); } - bool surfaceShield() const { return (material >> 16ull) & 1; } - void setSurfaceShield(bool v) { material &= ~(1ull << 16); material |= (atUint64(v) << 16ull); } - bool surfaceSand() const { return (material >> 17ull) & 1; } - void setSurfaceSand(bool v) { material &= ~(1ull << 17ull); material |= (atUint64(v) << 17ull); } - bool surfaceMothOrSeedOrganics() const { return (material >> 18) & 1; } - void setSurfaceMothOrSeedOrganics(bool v) { material &= ~(1ull << 18); material |= (atUint64(v) << 18ull); } - bool surfaceWeb() const { return (material >> 19ull) & 1; } - void setSurfaceWeb(bool v) { material &= ~(1ull << 19ull); material |= (atUint64(v) << 19ull); } - bool projectilePassthrough() const { return (material >> 20ull) & 1; } - void setProjectilePassthrough(bool v) { material &= ~(1ull << 20ull); material |= (atUint64(v) << 20ull); } - bool cameraPassthrough() const { return (material >> 21ull) & 1; } - void setCameraPassthrough(bool v) { material &= ~(1ull << 21ull); material |= (atUint64(v) << 21ull); } - bool surfaceWood() const { return (material >> 22ull) & 1; } - void setSurfaceWood(bool v) { material &= ~(1ull << 22ull); material |= (atUint64(v) << 22ull); } - bool surfaceOrganic() const { return (material >> 23ull) & 1; } - void setSurfaceOrganic(bool v) { material &= ~(1ull << 23ull); material |= (atUint64(v) << 23ull); } - bool flipFace() const { return (material >> 24ull) & 1; } - void setFlipFace(bool v) { material &= ~(1ull << 24ull); material |= (atUint64(v) << 24ull); } - bool surfaceRubber() const { return (material >> 25) & 1; } - void setSurfaceRubber(bool v) { material &= ~(1ull << 25ull); material |= (atUint64(v) << 25ull); } - bool seeThrough() const { return (material >> 26ull) & 1; } - void setSeeThrough(bool v) { material &= ~(1ull << 26ull); material |= (atUint64(v) << 26ull); } - bool scanPassthrough() const { return (material >> 27ull) & 1; } - void setScanPassthrough(bool v) { material &= ~(1ull << 27ull); material |= (atUint64(v) << 27ull); } - bool aiPassthrough() const { return (material >> 28) & 1; } - void setAiPassthrough(bool v) { material &= ~(1ull << 28ull); material |= (atUint64(v) << 28ull); } - bool ceiling() const { return (material >> 29ull) & 1; } - void setCeiling(bool v) { material &= ~(1ull << 29ull); material |= (atUint64(v) << 29ull); } - bool wall() const { return (material >> 30ull) & 1; } - void setWall(bool v) { material &= ~(1ull << 30ull); material |= (atUint64(v) << 30ull); } - bool floor() const { return (material >> 31ull) & 1; } - void setFloor(bool v) { material &= ~(1ull << 31ull); material |= (atUint64(v) << 31ull); } - bool aiBlock() const { return (material >> 48ull) & 1; } - void setAiBlock(bool v) { material &= ~(1ull << 48ull); material |= (atUint64(v) << 48ull); } - bool jumpNotAllowed() const { return (material >> 58ull) & 1; } - void setJumpNotAllowed(bool v) { material &= ~(1ull << 58ull); material |= (atUint64(v) << 58ull); } - bool spiderBall() const { return (material >> 61ull) & 1; } - void setSpiderBall(bool v) { material &= ~(1ull << 61ull); material |= (atUint64(v) << 61ull); } - bool screwAttackWallJump() const { return (material >> 62ull) & 1; } - void setScrewAttackWallJump(bool v) { material &= ~(1ull << 62ull); material |= (atUint64(v) << 62ull); } - - /* Dummies for MP1*/ - bool surfaceLava() const { return false; } - void setSurfaceLava(bool v) {} - bool surfaceMudSlow() const { return false; } - void setSurfaceMudSlow(bool v) {} - bool surfaceMud() const { return false; } - void setSurfaceMud(bool v) {} - bool surfaceStoneRock() const { return false; } - void setSurfaceLavaStone(bool v) {} - bool solid() const { return false; } - void setSolid(bool v) {} - bool noPlatformCollision() const { return false; } - void setNoPlatformCollision(bool v) { } - bool noEdgeCollision() const { return false; } - void setNoEdgeCollision(bool v) { } - }; - - using Edge = DNAMP1::DeafBabe::Edge; - using Triangle = DNAMP1::DeafBabe::Triangle; - - Value unk1; - Value length; - Value magic; - Value version; - Value aabb[2]; - Value rootNodeType; - Value bspSize; - Buffer bspTree; - Value materialCount; - Vector materials; - Value vertMatsCount; - Vector vertMats; - Value edgeMatsCount; - Vector edgeMats; - Value triMatsCount; - Vector triMats; - Value edgeVertsCount; - Vector edgeVertConnections; - Value triangleEdgesCount; - Vector triangleEdgeConnections; - Value noClimbEdgeCount; - Vector noClimbEdges; - Value vertCount; - Vector verts; - - static void BlenderInit(hecl::blender::PyOutStream& os); - void insertNoClimb(hecl::blender::PyOutStream& os) const; - void sendToBlender(hecl::blender::PyOutStream& os) const - { - DeafBabeSendToBlender(os, *this); + Value material = 0; + bool unknown() const { return material & 1; } + void setUnknown(bool v) { + material &= ~1; + material |= atUint64(v); } + bool surfaceStone() const { return (material >> 1ull) & 1; } + void setSurfaceStone(bool v) { + material &= ~(1ull << 1ull); + material |= (atUint64(v) << 1ull); + } + bool surfaceMetal() const { return (material >> 2) & 1; } + void setSurfaceMetal(bool v) { + material &= ~(1ull << 2ull); + material |= (atUint64(v) << 2ull); + } + bool surfaceGrass() const { return (material >> 3) & 1; } + void setSurfaceGrass(bool v) { + material &= ~(1ull << 3ull); + material |= (atUint64(v) << 3ull); + } + bool surfaceIce() const { return (material >> 4ull) & 1; } + void setSurfaceIce(bool v) { + material &= ~(1ull << 4ull); + material |= (atUint64(v) << 4ull); + } + bool pillar() const { return (material >> 5ull) & 1; } + void setPillar(bool v) { + material &= ~(1ull << 5ull); + material |= (atUint64(v) << 5ull); + } + bool surfaceMetalGrating() const { return (material >> 6ull) & 1; } + void setSurfaceMetalGrating(bool v) { + material &= ~(1ull << 6ull); + material |= (atUint64(v) << 6ull); + } + bool surfacePhazon() const { return (material >> 7ull) & 1; } + void setSurfacePhazon(bool v) { + material &= ~(1ull << 7ull); + material |= (atUint64(v) << 7ull); + } + bool surfaceDirt() const { return (material >> 8ull) & 1; } + void setSurfaceDirt(bool v) { + material &= ~(1ull << 8); + material |= (atUint64(v) << 8ull); + } + bool surfaceSPMetal() const { return (material >> 9ull) & 1; } + void setSurfaceSPMetal(bool v) { + material &= ~(1ull << 9ull); + material |= (atUint64(v) << 9ull); + } + bool surfaceGlass() const { return (material >> 10ull) & 1; } + void setSurfaceGlass(bool v) { + material &= ~(1ull << 10ull); + material |= (atUint64(v) << 10ull); + } + bool surfaceSnow() const { return (material >> 11ull) & 1; } + void setSurfaceSnow(bool v) { + material &= ~(1ull << 11ull); + material |= (atUint64(v) << 11ull); + } + bool surfaceFabric() const { return (material >> 12ull) & 1; } + void setSurfaceFabric(bool v) { + material &= ~(1ull << 12ull); + material |= (atUint64(v) << 12ull); + } + bool halfPipe() const { return (material >> 13ull) & 1; } + void setHalfPipe(bool v) { + material &= ~(1ull << 13ull); + material |= (atUint64(v) << 13ull); + } + bool unused3() const { return (material >> 14ull) & 1; } + void setUnused3(bool v) { + material &= ~(1ull << 14ull); + material |= (atUint64(v) << 14ull); + } + bool unused4() const { return (material >> 15ull) & 1; } + void setUnused4(bool v) { + material &= ~(1ull << 15ull); + material |= (atUint64(v) << 15ull); + } + bool surfaceShield() const { return (material >> 16ull) & 1; } + void setSurfaceShield(bool v) { + material &= ~(1ull << 16); + material |= (atUint64(v) << 16ull); + } + bool surfaceSand() const { return (material >> 17ull) & 1; } + void setSurfaceSand(bool v) { + material &= ~(1ull << 17ull); + material |= (atUint64(v) << 17ull); + } + bool surfaceMothOrSeedOrganics() const { return (material >> 18) & 1; } + void setSurfaceMothOrSeedOrganics(bool v) { + material &= ~(1ull << 18); + material |= (atUint64(v) << 18ull); + } + bool surfaceWeb() const { return (material >> 19ull) & 1; } + void setSurfaceWeb(bool v) { + material &= ~(1ull << 19ull); + material |= (atUint64(v) << 19ull); + } + bool projectilePassthrough() const { return (material >> 20ull) & 1; } + void setProjectilePassthrough(bool v) { + material &= ~(1ull << 20ull); + material |= (atUint64(v) << 20ull); + } + bool cameraPassthrough() const { return (material >> 21ull) & 1; } + void setCameraPassthrough(bool v) { + material &= ~(1ull << 21ull); + material |= (atUint64(v) << 21ull); + } + bool surfaceWood() const { return (material >> 22ull) & 1; } + void setSurfaceWood(bool v) { + material &= ~(1ull << 22ull); + material |= (atUint64(v) << 22ull); + } + bool surfaceOrganic() const { return (material >> 23ull) & 1; } + void setSurfaceOrganic(bool v) { + material &= ~(1ull << 23ull); + material |= (atUint64(v) << 23ull); + } + bool flipFace() const { return (material >> 24ull) & 1; } + void setFlipFace(bool v) { + material &= ~(1ull << 24ull); + material |= (atUint64(v) << 24ull); + } + bool surfaceRubber() const { return (material >> 25) & 1; } + void setSurfaceRubber(bool v) { + material &= ~(1ull << 25ull); + material |= (atUint64(v) << 25ull); + } + bool seeThrough() const { return (material >> 26ull) & 1; } + void setSeeThrough(bool v) { + material &= ~(1ull << 26ull); + material |= (atUint64(v) << 26ull); + } + bool scanPassthrough() const { return (material >> 27ull) & 1; } + void setScanPassthrough(bool v) { + material &= ~(1ull << 27ull); + material |= (atUint64(v) << 27ull); + } + bool aiPassthrough() const { return (material >> 28) & 1; } + void setAiPassthrough(bool v) { + material &= ~(1ull << 28ull); + material |= (atUint64(v) << 28ull); + } + bool ceiling() const { return (material >> 29ull) & 1; } + void setCeiling(bool v) { + material &= ~(1ull << 29ull); + material |= (atUint64(v) << 29ull); + } + bool wall() const { return (material >> 30ull) & 1; } + void setWall(bool v) { + material &= ~(1ull << 30ull); + material |= (atUint64(v) << 30ull); + } + bool floor() const { return (material >> 31ull) & 1; } + void setFloor(bool v) { + material &= ~(1ull << 31ull); + material |= (atUint64(v) << 31ull); + } + bool aiBlock() const { return (material >> 48ull) & 1; } + void setAiBlock(bool v) { + material &= ~(1ull << 48ull); + material |= (atUint64(v) << 48ull); + } + bool jumpNotAllowed() const { return (material >> 58ull) & 1; } + void setJumpNotAllowed(bool v) { + material &= ~(1ull << 58ull); + material |= (atUint64(v) << 58ull); + } + bool spiderBall() const { return (material >> 61ull) & 1; } + void setSpiderBall(bool v) { + material &= ~(1ull << 61ull); + material |= (atUint64(v) << 61ull); + } + bool screwAttackWallJump() const { return (material >> 62ull) & 1; } + void setScrewAttackWallJump(bool v) { + material &= ~(1ull << 62ull); + material |= (atUint64(v) << 62ull); + } + + /* Dummies for MP1*/ + bool surfaceLava() const { return false; } + void setSurfaceLava(bool v) {} + bool surfaceMudSlow() const { return false; } + void setSurfaceMudSlow(bool v) {} + bool surfaceMud() const { return false; } + void setSurfaceMud(bool v) {} + bool surfaceStoneRock() const { return false; } + void setSurfaceLavaStone(bool v) {} + bool solid() const { return false; } + void setSolid(bool v) {} + bool noPlatformCollision() const { return false; } + void setNoPlatformCollision(bool v) {} + bool noEdgeCollision() const { return false; } + void setNoEdgeCollision(bool v) {} + }; + + using Edge = DNAMP1::DeafBabe::Edge; + using Triangle = DNAMP1::DeafBabe::Triangle; + + Value unk1; + Value length; + Value magic; + Value version; + Value aabb[2]; + Value rootNodeType; + Value bspSize; + Buffer bspTree; + Value materialCount; + Vector materials; + Value vertMatsCount; + Vector vertMats; + Value edgeMatsCount; + Vector edgeMats; + Value triMatsCount; + Vector triMats; + Value edgeVertsCount; + Vector edgeVertConnections; + Value triangleEdgesCount; + Vector triangleEdgeConnections; + Value noClimbEdgeCount; + Vector noClimbEdges; + Value vertCount; + Vector verts; + + static void BlenderInit(hecl::blender::PyOutStream& os); + void insertNoClimb(hecl::blender::PyOutStream& os) const; + void sendToBlender(hecl::blender::PyOutStream& os) const { DeafBabeSendToBlender(os, *this); } }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/MAPA.hpp b/DataSpec/DNAMP2/MAPA.hpp index 820137c4b..122aab86b 100644 --- a/DataSpec/DNAMP2/MAPA.hpp +++ b/DataSpec/DNAMP2/MAPA.hpp @@ -4,34 +4,24 @@ #include "DataSpec/DNACommon/MAPA.hpp" #include "DNAMP2.hpp" -namespace DataSpec::DNAMP2 -{ -struct MAPA : DNAMAPA::MAPA -{ - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const DNAMP2::PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) - { - MAPA mapa; - mapa.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - return DNAMAPA::ReadMAPAToBlender(conn, mapa, outPath, pakRouter, entry, force); - } +namespace DataSpec::DNAMP2 { +struct MAPA : DNAMAPA::MAPA { + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const DNAMP2::PAK::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged) { + MAPA mapa; + mapa.read(rs); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + return DNAMAPA::ReadMAPAToBlender(conn, mapa, outPath, pakRouter, entry, force); + } - static bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out) - { - return DNAMAPA::Cook(mapa, out); - } + static bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out) { + return DNAMAPA::Cook(mapa, out); + } - static uint32_t Version() { return 3; } - using Header = DNAMAPA::MAPA::HeaderMP2; - using MappableObject = DNAMAPA::MAPA::MappableObjectMP1_2; + static uint32_t Version() { return 3; } + using Header = DNAMAPA::MAPA::HeaderMP2; + using MappableObject = DNAMAPA::MAPA::MappableObjectMP1_2; }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/MAPU.hpp b/DataSpec/DNAMP2/MAPU.hpp index 32ece287d..3d030d808 100644 --- a/DataSpec/DNAMP2/MAPU.hpp +++ b/DataSpec/DNAMP2/MAPU.hpp @@ -6,25 +6,16 @@ #include "DataSpec/DNACommon/MAPU.hpp" #include "DNAMP2.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct MAPU : DNAMAPU::MAPU -{ - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const DNAMP2::PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) - { - MAPU mapu; - mapu.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - return DNAMAPU::ReadMAPUToBlender(conn, mapu, outPath, pakRouter, entry, force); - } +struct MAPU : DNAMAPU::MAPU { + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const DNAMP2::PAK::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged) { + MAPU mapu; + mapu.read(rs); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + return DNAMAPU::ReadMAPUToBlender(conn, mapu, outPath, pakRouter, entry, force); + } }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/MLVL.hpp b/DataSpec/DNAMP2/MLVL.hpp index 9a450b29b..18e558acf 100644 --- a/DataSpec/DNAMP2/MLVL.hpp +++ b/DataSpec/DNAMP2/MLVL.hpp @@ -4,111 +4,95 @@ #include "DataSpec/DNACommon/MLVL.hpp" #include "DNAMP2.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct MLVL : BigDNA -{ +struct MLVL : BigDNA { + AT_DECL_DNA_YAML + Value magic; + Value version; + UniqueID32 worldNameId; + UniqueID32 darkWorldNameId; + Value unk; + UniqueID32 saveWorldId; + UniqueID32 worldSkyboxId; + + Value areaCount; + struct Area : BigDNA { AT_DECL_DNA_YAML - Value magic; - Value version; - UniqueID32 worldNameId; - UniqueID32 darkWorldNameId; - Value unk; - UniqueID32 saveWorldId; - UniqueID32 worldSkyboxId; + UniqueID32 areaNameId; + Value transformMtx[3]; + Value aabb[2]; + UniqueID32 areaMREAId; + Value areaId; - Value areaCount; - struct Area : BigDNA - { - AT_DECL_DNA_YAML - UniqueID32 areaNameId; - Value transformMtx[3]; - Value aabb[2]; - UniqueID32 areaMREAId; - Value areaId; + Value attachedAreaCount; + Vector attachedAreas; + Value padding; - Value attachedAreaCount; - Vector attachedAreas; - Value padding; - - Value depCount; - struct Dependency : BigDNA - { - AT_DECL_DNA_YAML - UniqueID32 id; - DNAFourCC type; - }; - Vector deps; - - Value depLayerCount; - Vector depLayers; - - Value dockCount; - struct Dock : BigDNA - { - AT_DECL_DNA_YAML - Value endpointCount; - struct Endpoint : BigDNA - { - AT_DECL_DNA_YAML - Value areaIdx; - Value dockIdx; - }; - Vector endpoints; - - Value planeVertCount; - Vector planeVerts; - }; - Vector docks; - - Value relCount; - Vector, AT_DNA_COUNT(relCount)> relFilenames; - Value relOffsetCount; - Vector relOffsets; - - String<-1> internalAreaName; + Value depCount; + struct Dependency : BigDNA { + AT_DECL_DNA_YAML + UniqueID32 id; + DNAFourCC type; }; - Vector areas; + Vector deps; - UniqueID32 worldMap; - Value unknown2; - Value unknown3; + Value depLayerCount; + Vector depLayers; - Value layerFlagCount; - struct LayerFlags : BigDNA - { + Value dockCount; + struct Dock : BigDNA { + AT_DECL_DNA_YAML + Value endpointCount; + struct Endpoint : BigDNA { AT_DECL_DNA_YAML - Value layerCount; - Value flags; + Value areaIdx; + Value dockIdx; + }; + Vector endpoints; + + Value planeVertCount; + Vector planeVerts; }; - Vector layerFlags; + Vector docks; - Value layerNameCount; - Vector, AT_DNA_COUNT(layerNameCount)> layerNames; + Value relCount; + Vector, AT_DNA_COUNT(relCount)> relFilenames; + Value relOffsetCount; + Vector relOffsets; - Value layerNameOffsetCount; - Vector layerNameOffsets; + String<-1> internalAreaName; + }; + Vector areas; + UniqueID32 worldMap; + Value unknown2; + Value unknown3; - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const DNAMP2::PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) - { - MLVL mlvl; - mlvl.read(rs); - athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".yaml"), true).getAbsolutePath()); - athena::io::ToYAMLStream(mlvl, writer); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter, - entry, force, fileChanged); - } + Value layerFlagCount; + struct LayerFlags : BigDNA { + AT_DECL_DNA_YAML + Value layerCount; + Value flags; + }; + Vector layerFlags; + + Value layerNameCount; + Vector, AT_DNA_COUNT(layerNameCount)> layerNames; + + Value layerNameOffsetCount; + Vector layerNameOffsets; + + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const DNAMP2::PAK::Entry& entry, bool force, + hecl::blender::Token& btok, std::function fileChanged) { + MLVL mlvl; + mlvl.read(rs); + athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".yaml"), true).getAbsolutePath()); + athena::io::ToYAMLStream(mlvl, writer); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter, entry, force, fileChanged); + } }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/MREA.cpp b/DataSpec/DNAMP2/MREA.cpp index fb1a90b0d..2b4ed4a49 100644 --- a/DataSpec/DNAMP2/MREA.cpp +++ b/DataSpec/DNAMP2/MREA.cpp @@ -6,318 +6,294 @@ #include "DeafBabe.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec -{ +namespace DataSpec { extern hecl::Database::DataSpecEntry SpecEntMP2ORIG; -namespace DNAMP2 -{ +namespace DNAMP2 { -void MREA::StreamReader::nextBlock() -{ - if (m_nextBlk >= m_blkCount) - Log.report(logvisor::Fatal, "MREA stream overrun"); +void MREA::StreamReader::nextBlock() { + if (m_nextBlk >= m_blkCount) + Log.report(logvisor::Fatal, "MREA stream overrun"); - BlockInfo& info = m_blockInfos[m_nextBlk++]; + BlockInfo& info = m_blockInfos[m_nextBlk++]; - /* Reallocate read buffer if needed */ - if (info.bufSize > m_compBufSz) - { - m_compBufSz = info.bufSize; - m_compBuf.reset(new atUint8[m_compBufSz]); + /* Reallocate read buffer if needed */ + if (info.bufSize > m_compBufSz) { + m_compBufSz = info.bufSize; + m_compBuf.reset(new atUint8[m_compBufSz]); + } + + /* Reallocate decompress buffer if needed */ + if (info.decompSize > m_decompBufSz) { + m_decompBufSz = info.decompSize; + m_decompBuf.reset(new atUint8[m_decompBufSz]); + } + + if (info.compSize == 0) { + /* Read uncompressed block */ + m_source.readUBytesToBuf(m_decompBuf.get(), info.decompSize); + } else { + /* Read compressed segments */ + atUint32 blockStart = ROUND_UP_32(info.compSize) - info.compSize; + m_source.seek(blockStart); + atUint32 rem = info.decompSize; + atUint8* bufCur = m_decompBuf.get(); + while (rem) { + atInt16 chunkSz = m_source.readInt16Big(); + if (chunkSz < 0) { + chunkSz = -chunkSz; + m_source.readUBytesToBuf(bufCur, chunkSz); + bufCur += chunkSz; + rem -= chunkSz; + } else { + m_source.readUBytesToBuf(m_compBuf.get(), chunkSz); + lzo_uint dsz = rem; + lzo1x_decompress(m_compBuf.get(), chunkSz, bufCur, &dsz, nullptr); + bufCur += dsz; + rem -= dsz; + } } + } - /* Reallocate decompress buffer if needed */ - if (info.decompSize > m_decompBufSz) - { - m_decompBufSz = info.decompSize; - m_decompBuf.reset(new atUint8[m_decompBufSz]); - } - - if (info.compSize == 0) - { - /* Read uncompressed block */ - m_source.readUBytesToBuf(m_decompBuf.get(), info.decompSize); - } - else - { - /* Read compressed segments */ - atUint32 blockStart = ROUND_UP_32(info.compSize) - info.compSize; - m_source.seek(blockStart); - atUint32 rem = info.decompSize; - atUint8* bufCur = m_decompBuf.get(); - while (rem) - { - atInt16 chunkSz = m_source.readInt16Big(); - if (chunkSz < 0) - { - chunkSz = -chunkSz; - m_source.readUBytesToBuf(bufCur, chunkSz); - bufCur += chunkSz; - rem -= chunkSz; - } - else - { - m_source.readUBytesToBuf(m_compBuf.get(), chunkSz); - lzo_uint dsz = rem; - lzo1x_decompress(m_compBuf.get(), chunkSz, bufCur, &dsz, nullptr); - bufCur += dsz; - rem -= dsz; - } - } - } - - m_posInBlk = 0; - m_blkSz = info.decompSize; + m_posInBlk = 0; + m_blkSz = info.decompSize; } MREA::StreamReader::StreamReader(athena::io::IStreamReader& source, atUint32 blkCount) -: m_compBufSz(0x4120), m_compBuf(new atUint8[0x4120]), - m_decompBufSz(0x4120), m_decompBuf(new atUint8[0x4120]), - m_source(source), m_blkCount(blkCount) -{ - m_blockInfos.reserve(blkCount); - for (atUint32 i=0 ; i= m_totalDecompLen) + Log.report(logvisor::Fatal, "MREA stream seek overrun"); + + /* Determine which block contains position */ + atUint32 dAccum = 0; + atUint32 cAccum = 0; + atUint32 bIdx = 0; + for (BlockInfo& info : m_blockInfos) { + atUint32 newAccum = dAccum + info.decompSize; + if (newAccum > target) + break; + dAccum = newAccum; + ++bIdx; + if (info.compSize) + cAccum += ROUND_UP_32(info.compSize); + else + cAccum += info.decompSize; + } + + /* Seek source if needed */ + if (bIdx != m_nextBlk - 1) { + m_source.seek(m_blkBase + cAccum, athena::Begin); + m_nextBlk = bIdx; nextBlock(); + } + + m_pos = target; + m_posInBlk = target - dAccum; } -void MREA::StreamReader::seek(atInt64 diff, athena::SeekOrigin whence) -{ - atUint64 target = diff; - if (whence == athena::Current) - target = m_pos + diff; - else if (whence == athena::End) - target = m_totalDecompLen - diff; - - if (target >= m_totalDecompLen) - Log.report(logvisor::Fatal, "MREA stream seek overrun"); - - /* Determine which block contains position */ - atUint32 dAccum = 0; - atUint32 cAccum = 0; - atUint32 bIdx = 0; - for (BlockInfo& info : m_blockInfos) - { - atUint32 newAccum = dAccum + info.decompSize; - if (newAccum > target) - break; - dAccum = newAccum; - ++bIdx; - if (info.compSize) - cAccum += ROUND_UP_32(info.compSize); - else - cAccum += info.decompSize; - } - - /* Seek source if needed */ - if (bIdx != m_nextBlk-1) - { - m_source.seek(m_blkBase + cAccum, athena::Begin); - m_nextBlk = bIdx; - nextBlock(); - } - - m_pos = target; - m_posInBlk = target - dAccum; +atUint64 MREA::StreamReader::readUBytesToBuf(void* buf, atUint64 len) { + atUint8* bufCur = reinterpret_cast(buf); + atUint64 rem = len; + while (rem) { + atUint64 lRem = rem; + atUint64 blkRem = m_blkSz - m_posInBlk; + if (lRem > blkRem) + lRem = blkRem; + memcpy(bufCur, &m_decompBuf[m_posInBlk], lRem); + bufCur += lRem; + rem -= lRem; + m_posInBlk += lRem; + m_pos += lRem; + if (rem) + nextBlock(); + } + return len; } -atUint64 MREA::StreamReader::readUBytesToBuf(void* buf, atUint64 len) -{ - atUint8* bufCur = reinterpret_cast(buf); - atUint64 rem = len; - while (rem) - { - atUint64 lRem = rem; - atUint64 blkRem = m_blkSz - m_posInBlk; - if (lRem > blkRem) - lRem = blkRem; - memcpy(bufCur, &m_decompBuf[m_posInBlk], lRem); - bufCur += lRem; - rem -= lRem; - m_posInBlk += lRem; - m_pos += lRem; - if (rem) - nextBlock(); - } - return len; +void MREA::StreamReader::writeDecompInfos(athena::io::IStreamWriter& writer) const { + for (const BlockInfo& info : m_blockInfos) { + BlockInfo modInfo = info; + modInfo.compSize = 0; + modInfo.write(writer); + } } -void MREA::StreamReader::writeDecompInfos(athena::io::IStreamWriter& writer) const -{ - for (const BlockInfo& info : m_blockInfos) - { - BlockInfo modInfo = info; - modInfo.compSize = 0; - modInfo.write(writer); - } -} +bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const DNAMP2::PAK::Entry& entry, bool force, + hecl::blender::Token& btok, std::function) { + using RigPair = std::pair; + RigPair dummy(nullptr, nullptr); -bool MREA::Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const DNAMP2::PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function) -{ - using RigPair = std::pair; - RigPair dummy(nullptr, nullptr); + if (!force && outPath.isFile()) + return true; - if (!force && outPath.isFile()) - return true; + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); - /* Do extract */ - Header head; - head.read(rs); - rs.seekAlign32(); + /* MREA decompression stream */ + StreamReader drs(rs, head.compressedBlockCount); + hecl::ProjectPath decompPath = outPath.getCookedPath(SpecEntMP2ORIG).getWithExtension(_SYS_STR(".decomp")); + decompPath.makeDirChain(false); + athena::io::FileWriter mreaDecompOut(decompPath.getAbsolutePath()); + head.write(mreaDecompOut); + mreaDecompOut.seekAlign32(); + drs.writeDecompInfos(mreaDecompOut); + mreaDecompOut.seekAlign32(); + atUint64 decompLen = drs.length(); + mreaDecompOut.writeBytes(drs.readBytes(decompLen).get(), decompLen); + mreaDecompOut.close(); + drs.seek(0, athena::Begin); - /* MREA decompression stream */ - StreamReader drs(rs, head.compressedBlockCount); - hecl::ProjectPath decompPath = outPath.getCookedPath(SpecEntMP2ORIG).getWithExtension(_SYS_STR(".decomp")); - decompPath.makeDirChain(false); - athena::io::FileWriter mreaDecompOut(decompPath.getAbsolutePath()); - head.write(mreaDecompOut); - mreaDecompOut.seekAlign32(); - drs.writeDecompInfos(mreaDecompOut); - mreaDecompOut.seekAlign32(); - atUint64 decompLen = drs.length(); - mreaDecompOut.writeBytes(drs.readBytes(decompLen).get(), decompLen); - mreaDecompOut.close(); - drs.seek(0, athena::Begin); + /* Start up blender connection */ + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::Area)) + return false; - /* Start up blender connection */ - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::Area)) - return false; + /* Calculate offset to EGMC section */ + atUint64 egmcOffset = 0; + for (unsigned i = 0; i < head.egmcSecIdx; i++) + egmcOffset += head.secSizes[i]; - /* Calculate offset to EGMC section */ - atUint64 egmcOffset = 0; - for (unsigned i = 0; i < head.egmcSecIdx; i++) - egmcOffset += head.secSizes[i]; + /* Load EGMC if possible so we can assign meshes to scanIds */ + drs.seek(egmcOffset, athena::Begin); + UniqueID32 egmcId(drs); + DNACommon::EGMC egmc; + pakRouter.lookupAndReadDNA(egmcId, egmc); - /* Load EGMC if possible so we can assign meshes to scanIds */ - drs.seek(egmcOffset, athena::Begin); - UniqueID32 egmcId(drs); - DNACommon::EGMC egmc; - pakRouter.lookupAndReadDNA(egmcId, egmc); + drs.seek(0, athena::Begin); - drs.seek(0, athena::Begin); + /* Open Py Stream and read sections */ + hecl::blender::PyOutStream os = conn.beginPythonOut(true); + os.format( + "import bpy\n" + "import bmesh\n" + "from mathutils import Vector\n" + "\n" + "bpy.context.scene.name = '%s'\n", + pakRouter.getBestEntryName(entry, false).c_str()); + DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath(), true); + MaterialSet::RegisterMaterialProps(os); + os << "# Clear Scene\n" + "for ob in bpy.data.objects:\n" + " if ob.type != 'CAMERA':\n" + " bpy.context.scene.objects.unlink(ob)\n" + " bpy.data.objects.remove(ob)\n" + "bpy.types.Lamp.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" + "bpy.types.Lamp.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" + "bpy.types.Object.retro_disable_enviro_visor = bpy.props.BoolProperty(name='Retro: Disable in Combat/Scan " + "Visor')\n" + "bpy.types.Object.retro_disable_thermal_visor = bpy.props.BoolProperty(name='Retro: Disable in Thermal " + "Visor')\n" + "bpy.types.Object.retro_disable_xray_visor = bpy.props.BoolProperty(name='Retro: Disable in X-Ray Visor')\n" + "bpy.types.Object.retro_thermal_level = bpy.props.EnumProperty(items=[('COOL', 'Cool', 'Cool Temperature')," + "('HOT', 'Hot', 'Hot Temperature')," + "('WARM', 'Warm', 'Warm Temperature')]," + "name='Retro: Thermal Visor Level')\n" + "\n"; - /* Open Py Stream and read sections */ - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "from mathutils import Vector\n" - "\n" - "bpy.context.scene.name = '%s'\n", - pakRouter.getBestEntryName(entry, false).c_str()); - DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath(), true); - MaterialSet::RegisterMaterialProps(os); - os << "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "bpy.types.Lamp.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" - "bpy.types.Lamp.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" - "bpy.types.Object.retro_disable_enviro_visor = bpy.props.BoolProperty(name='Retro: Disable in Combat/Scan Visor')\n" - "bpy.types.Object.retro_disable_thermal_visor = bpy.props.BoolProperty(name='Retro: Disable in Thermal Visor')\n" - "bpy.types.Object.retro_disable_xray_visor = bpy.props.BoolProperty(name='Retro: Disable in X-Ray Visor')\n" - "bpy.types.Object.retro_thermal_level = bpy.props.EnumProperty(items=[('COOL', 'Cool', 'Cool Temperature')," - "('HOT', 'Hot', 'Hot Temperature')," - "('WARM', 'Warm', 'Warm Temperature')]," - "name='Retro: Thermal Visor Level')\n" - "\n"; + /* One shared material set for all meshes */ + os << "# Materials\n" + "materials = []\n" + "\n"; + MaterialSet matSet; + atUint64 secStart = drs.position(); + matSet.read(drs); + matSet.readToBlender(os, pakRouter, entry, 0); + drs.seek(secStart + head.secSizes[0], athena::Begin); + std::vector vertAttribs; + DNACMDL::GetVertexAttributes(matSet, vertAttribs); - /* One shared material set for all meshes */ - os << "# Materials\n" - "materials = []\n" - "\n"; - MaterialSet matSet; - atUint64 secStart = drs.position(); - matSet.read(drs); - matSet.readToBlender(os, pakRouter, entry, 0); - drs.seek(secStart + head.secSizes[0], athena::Begin); - std::vector vertAttribs; - DNACMDL::GetVertexAttributes(matSet, vertAttribs); - - /* Read meshes */ - atUint32 curSec = 1; - for (atUint32 m=0 ; m, MaterialSet, RigPair, DNACMDL::SurfaceHeader_2> - (os, drs, pakRouter, entry, dummy, true, - true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]); - os.format("obj.retro_disable_enviro_visor = %s\n" - "obj.retro_disable_thermal_visor = %s\n" - "obj.retro_disable_xray_visor = %s\n" - "obj.retro_thermal_level = '%s'\n", - mHeader.visorFlags.disableEnviro() ? "True" : "False", - mHeader.visorFlags.disableThermal() ? "True" : "False", - mHeader.visorFlags.disableXray() ? "True" : "False", - mHeader.visorFlags.thermalLevelStr()); - - /* Seek through AROT-relation sections */ - drs.seek(head.secSizes[curSec++], athena::Current); - drs.seek(head.secSizes[curSec++], athena::Current); - } - - /* Skip AROT */ - drs.seek(head.secSizes[curSec++], athena::Current); - - /* Skip BVH */ - drs.seek(head.secSizes[curSec++], athena::Current); - - /* Skip Bitmap */ - drs.seek(head.secSizes[curSec++], athena::Current); - - /* Skip SCLY (for now) */ - for (atUint32 l=0 ; l, MaterialSet, RigPair, DNACMDL::SurfaceHeader_2>( + os, drs, pakRouter, entry, dummy, true, true, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec]); + os.format( + "obj.retro_disable_enviro_visor = %s\n" + "obj.retro_disable_thermal_visor = %s\n" + "obj.retro_disable_xray_visor = %s\n" + "obj.retro_thermal_level = '%s'\n", + mHeader.visorFlags.disableEnviro() ? "True" : "False", mHeader.visorFlags.disableThermal() ? "True" : "False", + mHeader.visorFlags.disableXray() ? "True" : "False", mHeader.visorFlags.thermalLevelStr()); - /* Skip unknown section */ + /* Seek through AROT-relation sections */ + drs.seek(head.secSizes[curSec++], athena::Current); + drs.seek(head.secSizes[curSec++], athena::Current); + } + + /* Skip AROT */ + drs.seek(head.secSizes[curSec++], athena::Current); + + /* Skip BVH */ + drs.seek(head.secSizes[curSec++], athena::Current); + + /* Skip Bitmap */ + drs.seek(head.secSizes[curSec++], athena::Current); + + /* Skip SCLY (for now) */ + for (atUint32 l = 0; l < head.sclyLayerCount; ++l) drs.seek(head.secSizes[curSec++], athena::Current); - /* Read BABEDEAD Lights as Cycles emissives */ - secStart = drs.position(); - DNAMP1::MREA::ReadBabeDeadToBlender_1_2(os, drs); - drs.seek(secStart + head.secSizes[curSec++], athena::Begin); + /* Skip SCGN (for now) */ + drs.seek(head.secSizes[curSec++], athena::Current); - /* Origins to center of mass */ - os << "bpy.context.scene.layers[1] = True\n" - "bpy.ops.object.select_by_type(type='MESH')\n" - "bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')\n" - "bpy.ops.object.select_all(action='DESELECT')\n" - "bpy.context.scene.layers[1] = False\n"; + /* Read collision meshes */ + DeafBabe collision; + secStart = drs.position(); + collision.read(drs); + DeafBabe::BlenderInit(os); + collision.sendToBlender(os); + drs.seek(secStart + head.secSizes[curSec++], athena::Begin); - os.centerView(); - os.close(); - return conn.saveBlend(); + /* Skip unknown section */ + drs.seek(head.secSizes[curSec++], athena::Current); + + /* Read BABEDEAD Lights as Cycles emissives */ + secStart = drs.position(); + DNAMP1::MREA::ReadBabeDeadToBlender_1_2(os, drs); + drs.seek(secStart + head.secSizes[curSec++], athena::Begin); + + /* Origins to center of mass */ + os << "bpy.context.scene.layers[1] = True\n" + "bpy.ops.object.select_by_type(type='MESH')\n" + "bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')\n" + "bpy.ops.object.select_all(action='DESELECT')\n" + "bpy.context.scene.layers[1] = False\n"; + + os.centerView(); + os.close(); + return conn.saveBlend(); } -} -} +} // namespace DNAMP2 +} // namespace DataSpec diff --git a/DataSpec/DNAMP2/MREA.hpp b/DataSpec/DNAMP2/MREA.hpp index 4e4f142ce..55923482e 100644 --- a/DataSpec/DNAMP2/MREA.hpp +++ b/DataSpec/DNAMP2/MREA.hpp @@ -4,125 +4,123 @@ #include "CMDLMaterials.hpp" #include "CSKR.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct MREA -{ - class StreamReader : public athena::io::IStreamReader - { - protected: - struct BlockInfo : BigDNA - { - AT_DECL_DNA - Value bufSize; - Value decompSize; - Value compSize; - Value secCount; - }; - std::vector m_blockInfos; - - size_t m_compBufSz; - std::unique_ptr m_compBuf; - size_t m_decompBufSz; - std::unique_ptr m_decompBuf; - athena::io::IStreamReader& m_source; - atUint64 m_blkBase; - atUint32 m_blkCount; - atUint32 m_totalDecompLen = 0; - atUint32 m_pos = 0; - - atUint32 m_nextBlk = 0; - atUint32 m_posInBlk = 0; - atUint32 m_blkSz = 0; - void nextBlock(); - - StreamReader(athena::io::IStreamReader& source) - : m_compBufSz(0x4120), m_compBuf(new atUint8[0x4120]), - m_decompBufSz(0x4120), m_decompBuf(new atUint8[0x4120]), - m_source(source) {} /* Empty constructor for inheriting */ - - public: - StreamReader(athena::io::IStreamReader& source, atUint32 blkCount); - void seek(atInt64 diff, athena::SeekOrigin whence); - atUint64 position() const {return m_pos;} - atUint64 length() const {return m_totalDecompLen;} - atUint64 readUBytesToBuf(void* buf, atUint64 len); - void writeDecompInfos(athena::io::IStreamWriter& writer) const; +struct MREA { + class StreamReader : public athena::io::IStreamReader { + protected: + struct BlockInfo : BigDNA { + AT_DECL_DNA + Value bufSize; + Value decompSize; + Value compSize; + Value secCount; }; + std::vector m_blockInfos; - struct Header : BigDNA - { - AT_DECL_DNA - Value magic; - Value version; - Value localToWorldMtx[3]; - Value meshCount; - Value sclyLayerCount; - Value secCount; - Value geomSecIdx; - Value sclySecIdx; - Value scgnSecIdx; - Value collisionSecIdx; - Value unkSecIdx; - Value lightSecIdx; - Value emptySecIdx; - Value pathSecIdx; - Value unk2SecIdx; - Value unk3SecIdx; - Value egmcSecIdx; - Value compressedBlockCount; - Seek<12, athena::Current> align1; - Vector secSizes; - }; + size_t m_compBufSz; + std::unique_ptr m_compBuf; + size_t m_decompBufSz; + std::unique_ptr m_decompBuf; + athena::io::IStreamReader& m_source; + atUint64 m_blkBase; + atUint32 m_blkCount; + atUint32 m_totalDecompLen = 0; + atUint32 m_pos = 0; - struct MeshHeader : BigDNA - { - AT_DECL_DNA - struct VisorFlags : BigDNA - { - AT_DECL_DNA - Value flags; - enum class ThermalLevel - { - Cool, - Hot, - Warm - }; - static const char* GetThermalLevelStr(ThermalLevel t) - { - switch (t) - { - case ThermalLevel::Cool: return "COOL"; - case ThermalLevel::Hot: return "HOT"; - case ThermalLevel::Warm: return "WARM"; - default: break; - } - return nullptr; - } - bool disableEnviro() const {return flags >> 1 & 0x1;} - void setDisableEnviro(bool v) {flags &= ~0x2; flags |= v << 1;} - bool disableThermal() const {return flags >> 2 & 0x1;} - void setDisableThermal(bool v) {flags &= ~0x4; flags |= v << 2;} - bool disableXray() const {return flags >> 3 & 0x1;} - void setDisableXray(bool v) {flags &= ~0x8; flags |= v << 3;} - ThermalLevel thermalLevel() const {return ThermalLevel(flags >> 4 & 0x3);} - void setThermalLevel(ThermalLevel v) {flags &= ~0x30; flags |= atUint32(v) << 4;} - const char* thermalLevelStr() const {return GetThermalLevelStr(thermalLevel());} - } visorFlags; - Value xfMtx[3]; - Value aabb[2]; - }; + atUint32 m_nextBlk = 0; + atUint32 m_posInBlk = 0; + atUint32 m_blkSz = 0; + void nextBlock(); - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const DNAMP2::PAK::Entry& entry, - bool, - hecl::blender::Token& btok, - std::function); + StreamReader(athena::io::IStreamReader& source) + : m_compBufSz(0x4120) + , m_compBuf(new atUint8[0x4120]) + , m_decompBufSz(0x4120) + , m_decompBuf(new atUint8[0x4120]) + , m_source(source) {} /* Empty constructor for inheriting */ + + public: + StreamReader(athena::io::IStreamReader& source, atUint32 blkCount); + void seek(atInt64 diff, athena::SeekOrigin whence); + atUint64 position() const { return m_pos; } + atUint64 length() const { return m_totalDecompLen; } + atUint64 readUBytesToBuf(void* buf, atUint64 len); + void writeDecompInfos(athena::io::IStreamWriter& writer) const; + }; + + struct Header : BigDNA { + AT_DECL_DNA + Value magic; + Value version; + Value localToWorldMtx[3]; + Value meshCount; + Value sclyLayerCount; + Value secCount; + Value geomSecIdx; + Value sclySecIdx; + Value scgnSecIdx; + Value collisionSecIdx; + Value unkSecIdx; + Value lightSecIdx; + Value emptySecIdx; + Value pathSecIdx; + Value unk2SecIdx; + Value unk3SecIdx; + Value egmcSecIdx; + Value compressedBlockCount; + Seek<12, athena::Current> align1; + Vector secSizes; + }; + + struct MeshHeader : BigDNA { + AT_DECL_DNA + struct VisorFlags : BigDNA { + AT_DECL_DNA + Value flags; + enum class ThermalLevel { Cool, Hot, Warm }; + static const char* GetThermalLevelStr(ThermalLevel t) { + switch (t) { + case ThermalLevel::Cool: + return "COOL"; + case ThermalLevel::Hot: + return "HOT"; + case ThermalLevel::Warm: + return "WARM"; + default: + break; + } + return nullptr; + } + bool disableEnviro() const { return flags >> 1 & 0x1; } + void setDisableEnviro(bool v) { + flags &= ~0x2; + flags |= v << 1; + } + bool disableThermal() const { return flags >> 2 & 0x1; } + void setDisableThermal(bool v) { + flags &= ~0x4; + flags |= v << 2; + } + bool disableXray() const { return flags >> 3 & 0x1; } + void setDisableXray(bool v) { + flags &= ~0x8; + flags |= v << 3; + } + ThermalLevel thermalLevel() const { return ThermalLevel(flags >> 4 & 0x3); } + void setThermalLevel(ThermalLevel v) { + flags &= ~0x30; + flags |= atUint32(v) << 4; + } + const char* thermalLevelStr() const { return GetThermalLevelStr(thermalLevel()); } + } visorFlags; + Value xfMtx[3]; + Value aabb[2]; + }; + + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const DNAMP2::PAK::Entry& entry, bool, + hecl::blender::Token& btok, std::function); }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/PAK.cpp b/DataSpec/DNAMP2/PAK.cpp index 0d792fe74..9ada54fb6 100644 --- a/DataSpec/DNAMP2/PAK.cpp +++ b/DataSpec/DNAMP2/PAK.cpp @@ -1,23 +1,20 @@ #include "PAK.hpp" #include "AGSC.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const -{ - std::unordered_map::const_iterator search; - if (entry.type == FOURCC('AGSC') && (search = m_entries.find(entry.id)) != m_entries.cend()) - { - /* Use internal AGSC name for entry */ - auto rs = search->second.beginReadStream(pakNode); - AGSC::Header header; - header.read(rs); - named = true; - return header.groupName; - } +std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const { + std::unordered_map::const_iterator search; + if (entry.type == FOURCC('AGSC') && (search = m_entries.find(entry.id)) != m_entries.cend()) { + /* Use internal AGSC name for entry */ + auto rs = search->second.beginReadStream(pakNode); + AGSC::Header header; + header.read(rs); + named = true; + return header.groupName; + } - return DNAMP1::PAK::bestEntryName(pakNode, entry, named); + return DNAMP1::PAK::bestEntryName(pakNode, entry, named); } -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/PAK.hpp b/DataSpec/DNAMP2/PAK.hpp index 0cd1a4e84..39186f764 100644 --- a/DataSpec/DNAMP2/PAK.hpp +++ b/DataSpec/DNAMP2/PAK.hpp @@ -2,15 +2,12 @@ #include "../DNAMP1/PAK.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { /* Same PAK format as MP1 */ -struct PAK : DNAMP1::PAK -{ - using DNAMP1::PAK::PAK; - std::string bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const; +struct PAK : DNAMP1::PAK { + using DNAMP1::PAK::PAK; + std::string bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const; }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/PTLA.hpp b/DataSpec/DNAMP2/PTLA.hpp index 58ce9e972..fad338ea3 100644 --- a/DataSpec/DNAMP2/PTLA.hpp +++ b/DataSpec/DNAMP2/PTLA.hpp @@ -2,66 +2,59 @@ #include "DataSpec/DNACommon/DNACommon.hpp" -namespace DataSpec::DNAMP2 -{ -struct PTLA : BigDNA -{ +namespace DataSpec::DNAMP2 { +struct PTLA : BigDNA { + AT_DECL_DNA + Value magic; + struct UnknownStruct1 : BigDNA { AT_DECL_DNA - Value magic; - struct UnknownStruct1 : BigDNA - { - AT_DECL_DNA - Value count; - struct Entry : BigDNA - { - AT_DECL_DNA - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - }; - Vector entries; - Value unknown1; - Value unknown2[2]; + Value count; + struct Entry : BigDNA { + AT_DECL_DNA + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + Value unknown6; }; - Value count1; - Vector entries1; + Vector entries; + Value unknown1; + Value unknown2[2]; + }; + Value count1; + Vector entries1; - struct UnknownStruct2 : BigDNA - { - AT_DECL_DNA - Value count; - struct Entry : BigDNA - { - AT_DECL_DNA - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - }; - Vector entries; - Value unknown; + struct UnknownStruct2 : BigDNA { + AT_DECL_DNA + Value count; + struct Entry : BigDNA { + AT_DECL_DNA + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; }; - Value count2; - Vector entries2; + Vector entries; + Value unknown; + }; + Value count2; + Vector entries2; - Value shortCount1; - Vector shorts1; + Value shortCount1; + Vector shorts1; - Value shortCount2; - Vector shorts2; + Value shortCount2; + Vector shorts2; - struct UnknownStruct3 : BigDNA - { - AT_DECL_DNA - Value unknown1[2]; - Value unknown2; - Value unknown3; - Value unknown4; - }; - Value count3; - Vector entries3; + struct UnknownStruct3 : BigDNA { + AT_DECL_DNA + Value unknown1[2]; + Value unknown2; + Value unknown3; + Value unknown4; + }; + Value count3; + Vector entries3; }; -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/SAVW.hpp b/DataSpec/DNAMP2/SAVW.hpp index cb2e5551e..e0eea6563 100644 --- a/DataSpec/DNAMP2/SAVW.hpp +++ b/DataSpec/DNAMP2/SAVW.hpp @@ -3,17 +3,14 @@ #include "../DNAMP1/SAVW.hpp" #include "DNAMP2.hpp" -namespace DataSpec::DNAMP2 -{ -struct SAVW : DNAMP1::SAVW -{ - AT_DECL_DNA_YAML - Value systemVarCount; - Vector systemVars; - Value gameVarCount; - Vector gameVars; - Value gameObjectCount; - Vector gameObjects; +namespace DataSpec::DNAMP2 { +struct SAVW : DNAMP1::SAVW { + AT_DECL_DNA_YAML + Value systemVarCount; + Vector systemVars; + Value gameVarCount; + Vector gameVars; + Value gameObjectCount; + Vector gameObjects; }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/STRG.cpp b/DataSpec/DNAMP2/STRG.cpp index 1f08e1d3b..e0383fa5e 100644 --- a/DataSpec/DNAMP2/STRG.cpp +++ b/DataSpec/DNAMP2/STRG.cpp @@ -1,251 +1,217 @@ #include "STRG.hpp" #include "DNAMP2.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -void STRG::_read(athena::io::IStreamReader& reader) -{ - atUint32 langCount = reader.readUint32Big(); - atUint32 strCount = reader.readUint32Big(); +void STRG::_read(athena::io::IStreamReader& reader) { + atUint32 langCount = reader.readUint32Big(); + atUint32 strCount = reader.readUint32Big(); - std::vector readLangs; - readLangs.reserve(langCount); - for (atUint32 l=0 ; l readLangs; + readLangs.reserve(langCount); + for (atUint32 l = 0; l < langCount; ++l) { + DNAFourCC lang; + lang.read(reader); + readLangs.emplace_back(lang); + reader.seek(8); + } - atUint32 nameCount = reader.readUint32Big(); - atUint32 nameTableSz = reader.readUint32Big(); - std::unique_ptr nameTableBuf(new uint8_t[nameTableSz]); - reader.readUBytesToBuf(nameTableBuf.get(), nameTableSz); - struct NameIdxEntry - { - atUint32 nameOff; - atUint32 strIdx; - }* nameIndex = (NameIdxEntry*)nameTableBuf.get(); - for (atUint32 n=0 ; n nameTableBuf(new uint8_t[nameTableSz]); + reader.readUBytesToBuf(nameTableBuf.get(), nameTableSz); + struct NameIdxEntry { + atUint32 nameOff; + atUint32 strIdx; + }* nameIndex = (NameIdxEntry*)nameTableBuf.get(); + for (atUint32 n = 0; n < nameCount; ++n) { + const char* name = (char*)(nameTableBuf.get() + hecl::SBig(nameIndex[n].nameOff)); + names[name] = hecl::SBig(nameIndex[n].strIdx); + } - langs.clear(); - langs.reserve(langCount); - for (FourCC& lang : readLangs) - { - std::vector strs; - reader.seek(strCount * 4); - for (atUint32 s=0 ; s strs; + reader.seek(strCount * 4); + for (atUint32 s = 0; s < strCount; ++s) + strs.emplace_back(reader.readU16StringBig()); + langs.emplace_back(lang, strs); + } - langMap.clear(); - langMap.reserve(langCount); - for (std::pair>& item : langs) - langMap.emplace(item.first, &item.second); + langMap.clear(); + langMap.reserve(langCount); + for (std::pair>& item : langs) + langMap.emplace(item.first, &item.second); } template <> -void STRG::Enumerate(athena::io::IStreamReader& reader) -{ - atUint32 magic = reader.readUint32Big(); - if (magic != 0x87654321) - Log.report(logvisor::Error, "invalid STRG magic"); +void STRG::Enumerate(athena::io::IStreamReader& reader) { + atUint32 magic = reader.readUint32Big(); + if (magic != 0x87654321) + Log.report(logvisor::Error, "invalid STRG magic"); - atUint32 version = reader.readUint32Big(); - if (version != 1) - Log.report(logvisor::Error, "invalid STRG version"); + atUint32 version = reader.readUint32Big(); + if (version != 1) + Log.report(logvisor::Error, "invalid STRG version"); - _read(reader); + _read(reader); } template <> -void STRG::Enumerate(athena::io::IStreamWriter& writer) -{ - writer.writeUint32Big(0x87654321); - writer.writeUint32Big(1); - writer.writeUint32Big(langs.size()); - atUint32 strCount = STRG::count(); - writer.writeUint32Big(strCount); +void STRG::Enumerate(athena::io::IStreamWriter& writer) { + writer.writeUint32Big(0x87654321); + writer.writeUint32Big(1); + writer.writeUint32Big(langs.size()); + atUint32 strCount = STRG::count(); + writer.writeUint32Big(strCount); - atUint32 offset = 0; - for (const std::pair>& lang : langs) - { - lang.first.write(writer); - writer.writeUint32Big(offset); - offset += strCount * 4 + 4; - atUint32 langStrCount = lang.second.size(); - atUint32 tableSz = strCount * 4; - for (atUint32 s=0 ; s>& lang : langs) { + lang.first.write(writer); + writer.writeUint32Big(offset); + offset += strCount * 4 + 4; + atUint32 langStrCount = lang.second.size(); + atUint32 tableSz = strCount * 4; + for (atUint32 s = 0; s < strCount; ++s) { + atUint32 chCount = lang.second[s].size(); + if (s < langStrCount) { + offset += chCount * 2 + 1; + tableSz += chCount * 2 + 1; + } else { + offset += 1; + tableSz += 1; + } + } + writer.writeUint32Big(tableSz); + } + + atUint32 nameTableSz = names.size() * 8; + for (const std::pair& name : names) + nameTableSz += name.first.size() + 1; + writer.writeUint32Big(names.size()); + writer.writeUint32Big(nameTableSz); + offset = names.size() * 8; + for (const std::pair& name : names) { + writer.writeUint32Big(offset); + writer.writeInt32Big(name.second); + offset += name.first.size() + 1; + } + for (const std::pair& name : names) + writer.writeString(name.first); + + for (const std::pair>& lang : langs) { + offset = strCount * 4; + atUint32 langStrCount = lang.second.size(); + for (atUint32 s = 0; s < strCount; ++s) { + writer.writeUint32Big(offset); + if (s < langStrCount) + offset += lang.second[s].size() * 2 + 1; + else + offset += 1; } - atUint32 nameTableSz = names.size() * 8; - for (const std::pair& name : names) - nameTableSz += name.first.size() + 1; - writer.writeUint32Big(names.size()); - writer.writeUint32Big(nameTableSz); - offset = names.size() * 8; - for (const std::pair& name : names) - { - writer.writeUint32Big(offset); - writer.writeInt32Big(name.second); - offset += name.first.size() + 1; - } - for (const std::pair& name : names) - writer.writeString(name.first); - - for (const std::pair>& lang : langs) - { - offset = strCount * 4; - atUint32 langStrCount = lang.second.size(); - for (atUint32 s=0 ; s -void STRG::Enumerate(size_t& __isz) -{ - __isz += 16; +void STRG::Enumerate(size_t& __isz) { + __isz += 16; - __isz += langs.size() * 12; + __isz += langs.size() * 12; - __isz += 8; - __isz += names.size() * 8; - for (const std::pair& name : names) - __isz += name.first.size() + 1; + __isz += 8; + __isz += names.size() * 8; + for (const std::pair& name : names) + __isz += name.first.size() + 1; - size_t strCount = STRG::count(); - for (const std::pair>& lang : langs) - { - atUint32 langStrCount = lang.second.size(); - __isz += strCount * 4; + size_t strCount = STRG::count(); + for (const std::pair>& lang : langs) { + atUint32 langStrCount = lang.second.size(); + __isz += strCount * 4; - for (atUint32 s=0 ; s -void STRG::Enumerate(athena::io::YAMLDocReader& reader) -{ - const athena::io::YAMLNode* root = reader.getRootNode(); +void STRG::Enumerate(athena::io::YAMLDocReader& reader) { + const athena::io::YAMLNode* root = reader.getRootNode(); - /* Validate Pass */ - if (root->m_type == YAML_MAPPING_NODE) - { - for (const auto& lang : root->m_mapChildren) - { - if (!lang.first.compare("names")) - continue; - if (lang.first.size() != 4) - { - Log.report(logvisor::Warning, "STRG language string '%s' must be exactly 4 characters; skipping", lang.first.c_str()); - return; - } - if (lang.second->m_type != YAML_SEQUENCE_NODE) - { - Log.report(logvisor::Warning, "STRG language string '%s' must contain a sequence; skipping", lang.first.c_str()); - return; - } - for (const auto& str : lang.second->m_seqChildren) - { - if (str->m_type != YAML_SCALAR_NODE) - { - Log.report(logvisor::Warning, "STRG language '%s' must contain all scalars; skipping", lang.first.c_str()); - return; - } - } - } - } - else - { - Log.report(logvisor::Warning, "STRG must have a mapping root node; skipping"); + /* Validate Pass */ + if (root->m_type == YAML_MAPPING_NODE) { + for (const auto& lang : root->m_mapChildren) { + if (!lang.first.compare("names")) + continue; + if (lang.first.size() != 4) { + Log.report(logvisor::Warning, "STRG language string '%s' must be exactly 4 characters; skipping", + lang.first.c_str()); return; + } + if (lang.second->m_type != YAML_SEQUENCE_NODE) { + Log.report(logvisor::Warning, "STRG language string '%s' must contain a sequence; skipping", + lang.first.c_str()); + return; + } + for (const auto& str : lang.second->m_seqChildren) { + if (str->m_type != YAML_SCALAR_NODE) { + Log.report(logvisor::Warning, "STRG language '%s' must contain all scalars; skipping", lang.first.c_str()); + return; + } + } } + } else { + Log.report(logvisor::Warning, "STRG must have a mapping root node; skipping"); + return; + } - /* Read Pass */ - langs.clear(); - for (const auto& lang : root->m_mapChildren) - { - std::vector strs; - for (const auto& str : lang.second->m_seqChildren) - strs.emplace_back(hecl::UTF8ToChar16(str->m_scalarString)); - langs.emplace_back(FourCC(lang.first.c_str()), strs); - } + /* Read Pass */ + langs.clear(); + for (const auto& lang : root->m_mapChildren) { + std::vector strs; + for (const auto& str : lang.second->m_seqChildren) + strs.emplace_back(hecl::UTF8ToChar16(str->m_scalarString)); + langs.emplace_back(FourCC(lang.first.c_str()), strs); + } - names.clear(); - const athena::io::YAMLNode* namesNode = root->findMapChild("names"); - if (namesNode) - for (const auto& item : namesNode->m_mapChildren) - names[item.first] = athena::io::NodeToVal(item.second.get()); + names.clear(); + const athena::io::YAMLNode* namesNode = root->findMapChild("names"); + if (namesNode) + for (const auto& item : namesNode->m_mapChildren) + names[item.first] = athena::io::NodeToVal(item.second.get()); - langMap.clear(); - langMap.reserve(langs.size()); - for (std::pair>& item : langs) - langMap.emplace(item.first, &item.second); + langMap.clear(); + langMap.reserve(langs.size()); + for (std::pair>& item : langs) + langMap.emplace(item.first, &item.second); } template <> -void STRG::Enumerate(athena::io::YAMLDocWriter& writer) -{ - for (const auto& lang : langs) - { - if (auto v = writer.enterSubVector(lang.first.toString().c_str())) - for (const std::u16string& str : lang.second) - writer.writeU16String(nullptr, str); - } - if (names.size()) - { - if (auto rec = writer.enterSubRecord("names")) - for (const auto& name : names) - if (auto rec = writer.enterSubRecord(name.first.c_str())) - writer.writeInt32(nullptr, name.second); - } +void STRG::Enumerate(athena::io::YAMLDocWriter& writer) { + for (const auto& lang : langs) { + if (auto v = writer.enterSubVector(lang.first.toString().c_str())) + for (const std::u16string& str : lang.second) + writer.writeU16String(nullptr, str); + } + if (names.size()) { + if (auto rec = writer.enterSubRecord("names")) + for (const auto& name : names) + if (auto rec = writer.enterSubRecord(name.first.c_str())) + writer.writeInt32(nullptr, name.second); + } } -const char* STRG::DNAType() -{ - return "urde::DNAMP2::STRG"; -} +const char* STRG::DNAType() { return "urde::DNAMP2::STRG"; } -} +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP2/STRG.hpp b/DataSpec/DNAMP2/STRG.hpp index 715a7ebeb..835a95439 100644 --- a/DataSpec/DNAMP2/STRG.hpp +++ b/DataSpec/DNAMP2/STRG.hpp @@ -4,82 +4,71 @@ #include "DataSpec/DNACommon/PAK.hpp" #include "DataSpec/DNACommon/STRG.hpp" -namespace DataSpec::DNAMP2 -{ +namespace DataSpec::DNAMP2 { -struct STRG : ISTRG -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_DECL_DNAV - void _read(athena::io::IStreamReader& reader); - std::vector>> langs; - std::unordered_map*> langMap; - std::map names; +struct STRG : ISTRG { + AT_DECL_EXPLICIT_DNA_YAML + AT_DECL_DNAV + void _read(athena::io::IStreamReader& reader); + std::vector>> langs; + std::unordered_map*> langMap; + std::map names; - int32_t lookupIdx(std::string_view name) const - { - auto search = names.find(name.data()); - if (search == names.end()) - return -1; - return search->second; - } + int32_t lookupIdx(std::string_view name) const { + auto search = names.find(name.data()); + if (search == names.end()) + return -1; + return search->second; + } - size_t count() const - { - size_t retval = 0; - for (const auto& item : langs) - { - size_t sz = item.second.size(); - if (sz > retval) - retval = sz; - } - return retval; + size_t count() const { + size_t retval = 0; + for (const auto& item : langs) { + size_t sz = item.second.size(); + if (sz > retval) + retval = sz; } - std::string getUTF8(const FourCC& lang, size_t idx) const - { - auto search = langMap.find(lang); - if (search != langMap.end()) - return hecl::Char16ToUTF8(search->second->at(idx)); - return std::string(); - } - std::u16string getUTF16(const FourCC& lang, size_t idx) const - { - auto search = langMap.find(lang); - if (search != langMap.end()) - return search->second->at(idx); - return std::u16string(); - } - hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const - { - auto search = langMap.find(lang); - if (search != langMap.end()) + return retval; + } + std::string getUTF8(const FourCC& lang, size_t idx) const { + auto search = langMap.find(lang); + if (search != langMap.end()) + return hecl::Char16ToUTF8(search->second->at(idx)); + return std::string(); + } + std::u16string getUTF16(const FourCC& lang, size_t idx) const { + auto search = langMap.find(lang); + if (search != langMap.end()) + return search->second->at(idx); + return std::u16string(); + } + hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const { + auto search = langMap.find(lang); + if (search != langMap.end()) #if HECL_UCS2 - return hecl::Char16ToWide(search->second->at(idx)); + return hecl::Char16ToWide(search->second->at(idx)); #else - return hecl::Char16ToUTF8(search->second->at(idx)); + return hecl::Char16ToUTF8(search->second->at(idx)); #endif - return hecl::SystemString(); - } + return hecl::SystemString(); + } - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) - { - STRG strg; - strg.read(rs); - athena::io::TransactionalFileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(strg, writer); - return true; - } + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + STRG strg; + strg.read(rs); + athena::io::TransactionalFileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(strg, writer); + return true; + } - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) - { - STRG strg; - athena::io::FileReader reader(inPath.getAbsolutePath()); - athena::io::FromYAMLStream(strg, reader); - athena::io::TransactionalFileWriter ws(outPath.getAbsolutePath()); - strg.write(ws); - return true; - } + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + STRG strg; + athena::io::FileReader reader(inPath.getAbsolutePath()); + athena::io::FromYAMLStream(strg, reader); + athena::io::TransactionalFileWriter ws(outPath.getAbsolutePath()); + strg.write(ws); + return true; + } }; -} - +} // namespace DataSpec::DNAMP2 diff --git a/DataSpec/DNAMP3/ANIM.cpp b/DataSpec/DNAMP3/ANIM.cpp index b61a95d9d..26c1006f2 100644 --- a/DataSpec/DNAMP3/ANIM.cpp +++ b/DataSpec/DNAMP3/ANIM.cpp @@ -3,591 +3,536 @@ #include "zeus/Math.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { using ANIMOutStream = hecl::blender::ANIMOutStream; -void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, - const DNAANIM::RigInverter& rig, - bool additive) const -{ - os.format("act.hecl_fps = round(%f)\n" - "act.hecl_additive = %s\n" - "act.hecl_looping = %s\n", - 1.0f / mainInterval, additive ? "True" : "False", looping ? "True" : "False"); +void ANIM::IANIM::sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig, + bool additive) const { + os.format( + "act.hecl_fps = round(%f)\n" + "act.hecl_additive = %s\n" + "act.hecl_looping = %s\n", + 1.0f / mainInterval, additive ? "True" : "False", looping ? "True" : "False"); - auto kit = chanKeys.begin() + 1; + auto kit = chanKeys.begin() + 1; - std::vector fixedRotKeys; - std::vector fixedTransKeys; + std::vector fixedRotKeys; + std::vector fixedTransKeys; - for (const std::pair>& bone : bones) - { - const std::string* bName = rig.getCINF().getBoneNameFromId(bone.first); - if (!bName) - { - if (std::get<0>(bone.second)) - ++kit; - if (std::get<1>(bone.second)) - ++kit; - if (std::get<2>(bone.second)) - ++kit; - continue; - } - - os.format("bone_string = '%s'\n", bName->c_str()); - os << "action_group = act.groups.new(bone_string)\n" - "\n"; - - if (std::get<0>(bone.second)) - os << "rotCurves = []\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string))\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string))\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string))\n" - "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string))\n" - "\n"; - - if (std::get<1>(bone.second)) - os << "transCurves = []\n" - "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string))\n" - "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string))\n" - "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n" - "\n"; - - if (std::get<2>(bone.second)) - os << "scaleCurves = []\n" - "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=0, action_group=bone_string))\n" - "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=1, action_group=bone_string))\n" - "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=2, action_group=bone_string))\n" - "\n"; - - ANIMOutStream ao = os.beginANIMCurve(); - if (std::get<0>(bone.second)) - { - const std::vector& rotKeys = *kit++; - fixedRotKeys.clear(); - fixedRotKeys.resize(rotKeys.size()); - - for (int c=0 ; c<4 ; ++c) - { - size_t idx = 0; - for (const DNAANIM::Value& val : rotKeys) - fixedRotKeys[idx++][c] = val.simd[c]; - } - - for (zeus::CQuaternion& rot : fixedRotKeys) - rot = rig.invertRotation(bone.first, rot); - - for (int c=0 ; c<4 ; ++c) - { - auto frameit = frames.begin(); - ao.changeCurve(ANIMOutStream::CurveType::Rotate, c, rotKeys.size()); - for (const zeus::CQuaternion& val : fixedRotKeys) - ao.write(*frameit++, val[c]); - } - } - - if (std::get<1>(bone.second)) - { - const std::vector& transKeys = *kit++; - fixedTransKeys.clear(); - fixedTransKeys.resize(transKeys.size()); - - for (int c=0 ; c<3 ; ++c) - { - size_t idx = 0; - for (const DNAANIM::Value& val : transKeys) - fixedTransKeys[idx++][c] = val.simd[c]; - } - - for (zeus::CVector3f& t : fixedTransKeys) - t = rig.invertPosition(bone.first, t, !additive); - - for (int c=0 ; c<3 ; ++c) - { - auto frameit = frames.begin(); - ao.changeCurve(ANIMOutStream::CurveType::Translate, c, fixedTransKeys.size()); - for (const zeus::CVector3f& val : fixedTransKeys) - ao.write(*frameit++, val[c]); - } - } - - if (std::get<2>(bone.second)) - { - const std::vector& scaleKeys = *kit++; - for (int c=0 ; c<3 ; ++c) - { - auto frameit = frames.begin(); - ao.changeCurve(ANIMOutStream::CurveType::Scale, c, scaleKeys.size()); - for (const DNAANIM::Value& val : scaleKeys) - ao.write(*frameit++, val.simd[c]); - } - } + for (const std::pair>& bone : bones) { + const std::string* bName = rig.getCINF().getBoneNameFromId(bone.first); + if (!bName) { + if (std::get<0>(bone.second)) + ++kit; + if (std::get<1>(bone.second)) + ++kit; + if (std::get<2>(bone.second)) + ++kit; + continue; } -} -template <> -void ANIM::Enumerate(typename Read::StreamT& reader) -{ - atUint32 version = reader.readUint32Big(); - switch (version) - { - case 0: - m_anim.reset(new struct ANIM0); - m_anim->read(reader); - break; - case 1: - m_anim.reset(new struct ANIM1); - m_anim->read(reader); - break; - default: - Log.report(logvisor::Fatal, "unrecognized ANIM version"); - break; + os.format("bone_string = '%s'\n", bName->c_str()); + os << "action_group = act.groups.new(bone_string)\n" + "\n"; + + if (std::get<0>(bone.second)) + os << "rotCurves = []\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, " + "action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, " + "action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, " + "action_group=bone_string))\n" + "rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, " + "action_group=bone_string))\n" + "\n"; + + if (std::get<1>(bone.second)) + os << "transCurves = []\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, " + "action_group=bone_string))\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, " + "action_group=bone_string))\n" + "transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, " + "action_group=bone_string))\n" + "\n"; + + if (std::get<2>(bone.second)) + os << "scaleCurves = []\n" + "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=0, " + "action_group=bone_string))\n" + "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=1, " + "action_group=bone_string))\n" + "scaleCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].scale', index=2, " + "action_group=bone_string))\n" + "\n"; + + ANIMOutStream ao = os.beginANIMCurve(); + if (std::get<0>(bone.second)) { + const std::vector& rotKeys = *kit++; + fixedRotKeys.clear(); + fixedRotKeys.resize(rotKeys.size()); + + for (int c = 0; c < 4; ++c) { + size_t idx = 0; + for (const DNAANIM::Value& val : rotKeys) + fixedRotKeys[idx++][c] = val.simd[c]; + } + + for (zeus::CQuaternion& rot : fixedRotKeys) + rot = rig.invertRotation(bone.first, rot); + + for (int c = 0; c < 4; ++c) { + auto frameit = frames.begin(); + ao.changeCurve(ANIMOutStream::CurveType::Rotate, c, rotKeys.size()); + for (const zeus::CQuaternion& val : fixedRotKeys) + ao.write(*frameit++, val[c]); + } } + + if (std::get<1>(bone.second)) { + const std::vector& transKeys = *kit++; + fixedTransKeys.clear(); + fixedTransKeys.resize(transKeys.size()); + + for (int c = 0; c < 3; ++c) { + size_t idx = 0; + for (const DNAANIM::Value& val : transKeys) + fixedTransKeys[idx++][c] = val.simd[c]; + } + + for (zeus::CVector3f& t : fixedTransKeys) + t = rig.invertPosition(bone.first, t, !additive); + + for (int c = 0; c < 3; ++c) { + auto frameit = frames.begin(); + ao.changeCurve(ANIMOutStream::CurveType::Translate, c, fixedTransKeys.size()); + for (const zeus::CVector3f& val : fixedTransKeys) + ao.write(*frameit++, val[c]); + } + } + + if (std::get<2>(bone.second)) { + const std::vector& scaleKeys = *kit++; + for (int c = 0; c < 3; ++c) { + auto frameit = frames.begin(); + ao.changeCurve(ANIMOutStream::CurveType::Scale, c, scaleKeys.size()); + for (const DNAANIM::Value& val : scaleKeys) + ao.write(*frameit++, val.simd[c]); + } + } + } } template <> -void ANIM::Enumerate(typename Write::StreamT& writer) -{ - writer.writeUint32Big(m_anim->m_version); - m_anim->write(writer); +void ANIM::Enumerate(typename Read::StreamT& reader) { + atUint32 version = reader.readUint32Big(); + switch (version) { + case 0: + m_anim.reset(new struct ANIM0); + m_anim->read(reader); + break; + case 1: + m_anim.reset(new struct ANIM1); + m_anim->read(reader); + break; + default: + Log.report(logvisor::Fatal, "unrecognized ANIM version"); + break; + } } template <> -void ANIM::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - m_anim->binarySize(s); +void ANIM::Enumerate(typename Write::StreamT& writer) { + writer.writeUint32Big(m_anim->m_version); + m_anim->write(writer); +} + +template <> +void ANIM::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + m_anim->binarySize(s); } const char* ANIM::ANIM0::DNAType() { return "ANIM0"; } template <> -void ANIM::ANIM0::Enumerate(athena::io::IStreamReader& reader) -{ - Header head; - head.read(reader); - mainInterval = head.interval; +void ANIM::ANIM0::Enumerate(athena::io::IStreamReader& reader) { + Header head; + head.read(reader); + mainInterval = head.interval; - frames.clear(); - frames.reserve(head.keyCount); - for (size_t k=0 ; k boneMap; - for (size_t b=0 ; b boneMap; + for (size_t b = 0; b < head.boneSlotCount; ++b) { + atUint8 idx = reader.readUByte(); + if (idx == 0xff) + continue; + boneMap[idx] = b; + } + + atUint32 boneCount = reader.readUint32Big(); + bones.clear(); + bones.reserve(boneCount); + for (size_t b = 0; b < boneCount; ++b) { + bones.emplace_back(boneMap[b], std::make_tuple(false, false, false)); + atUint8 idx = reader.readUByte(); + if (idx != 0xff) + std::get<0>(bones.back().second) = true; + } + + boneCount = reader.readUint32Big(); + for (size_t b = 0; b < boneCount; ++b) { + atUint8 idx = reader.readUByte(); + if (idx != 0xff) + std::get<1>(bones[b].second) = true; + } + + boneCount = reader.readUint32Big(); + for (size_t b = 0; b < boneCount; ++b) { + atUint8 idx = reader.readUByte(); + if (idx != 0xff) + std::get<2>(bones[b].second) = true; + } + + channels.clear(); + chanKeys.clear(); + channels.emplace_back(); + channels.back().type = DNAANIM::Channel::Type::KfHead; + chanKeys.emplace_back(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Rotation; + chanKeys.emplace_back(); } - - atUint32 boneCount = reader.readUint32Big(); - bones.clear(); - bones.reserve(boneCount); - for (size_t b=0 ; b(bones.back().second) = true; + if (std::get<1>(bone.second)) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Translation; + chanKeys.emplace_back(); } - - boneCount = reader.readUint32Big(); - for (size_t b=0 ; b(bones[b].second) = true; + if (std::get<2>(bone.second)) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Scale; + chanKeys.emplace_back(); } + } - boneCount = reader.readUint32Big(); - for (size_t b=0 ; b(bones[b].second) = true; + reader.readUint32Big(); + auto kit = chanKeys.begin() + 1; + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + ++kit; + if (std::get<1>(bone.second)) + ++kit; + if (std::get<2>(bone.second)) { + std::vector& keys = *kit++; + for (size_t k = 0; k < head.keyCount; ++k) + keys.emplace_back(reader.readVec3fBig()); } + } - channels.clear(); - chanKeys.clear(); - channels.emplace_back(); - channels.back().type = DNAANIM::Channel::Type::KfHead; - chanKeys.emplace_back(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::Rotation; - chanKeys.emplace_back(); - } - if (std::get<1>(bone.second)) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::Translation; - chanKeys.emplace_back(); - } - if (std::get<2>(bone.second)) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::Scale; - chanKeys.emplace_back(); - } + reader.readUint32Big(); + kit = chanKeys.begin() + 1; + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) { + std::vector& keys = *kit++; + for (size_t k = 0; k < head.keyCount; ++k) + keys.emplace_back(reader.readVec4fBig()); } + if (std::get<1>(bone.second)) + ++kit; + if (std::get<2>(bone.second)) + ++kit; + } - reader.readUint32Big(); - auto kit = chanKeys.begin() + 1; - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - ++kit; - if (std::get<1>(bone.second)) - ++kit; - if (std::get<2>(bone.second)) - { - std::vector& keys = *kit++; - for (size_t k=0 ; k>& bone : bones) - { - if (std::get<0>(bone.second)) - { - std::vector& keys = *kit++; - for (size_t k=0 ; k(bone.second)) - ++kit; - if (std::get<2>(bone.second)) - ++kit; - } - - reader.readUint32Big(); - kit = chanKeys.begin() + 1; - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - ++kit; - if (std::get<1>(bone.second)) - { - std::vector& keys = *kit++; - for (size_t k=0 ; k(bone.second)) - ++kit; + reader.readUint32Big(); + kit = chanKeys.begin() + 1; + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + ++kit; + if (std::get<1>(bone.second)) { + std::vector& keys = *kit++; + for (size_t k = 0; k < head.keyCount; ++k) + keys.emplace_back(reader.readVec3fBig()); } + if (std::get<2>(bone.second)) + ++kit; + } } template <> -void ANIM::ANIM0::Enumerate(athena::io::IStreamWriter& writer) -{ - Header head; - head.unk0 = 0; - head.unk1 = 0; - head.unk2 = 0; - head.keyCount = frames.size(); - head.duration = head.keyCount * mainInterval; - head.interval = mainInterval; +void ANIM::ANIM0::Enumerate(athena::io::IStreamWriter& writer) { + Header head; + head.unk0 = 0; + head.unk1 = 0; + head.unk2 = 0; + head.keyCount = frames.size(); + head.duration = head.keyCount * mainInterval; + head.interval = mainInterval; - atUint32 maxId = 0; - for (const std::pair>& bone : bones) - maxId = std::max(maxId, bone.first); - head.boneSlotCount = maxId + 1; - head.write(writer); + atUint32 maxId = 0; + for (const std::pair>& bone : bones) + maxId = std::max(maxId, bone.first); + head.boneSlotCount = maxId + 1; + head.write(writer); - for (size_t s=0 ; s>& bone : bones) - { - if (s == bone.first) - { - writer.writeUByte(boneIdx); - found = true; - break; - } - ++boneIdx; - } - if (!found) - writer.writeUByte(0xff); - } - - writer.writeUint32Big(bones.size()); + for (size_t s = 0; s < head.boneSlotCount; ++s) { size_t boneIdx = 0; - size_t rotKeyCount = 0; - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - { - writer.writeUByte(boneIdx); - ++rotKeyCount; - } - else - writer.writeUByte(0xff); - ++boneIdx; + bool found = false; + for (const std::pair>& bone : bones) { + if (s == bone.first) { + writer.writeUByte(boneIdx); + found = true; + break; + } + ++boneIdx; } + if (!found) + writer.writeUByte(0xff); + } - writer.writeUint32Big(bones.size()); - boneIdx = 0; - size_t transKeyCount = 0; - for (const std::pair>& bone : bones) - { - if (std::get<1>(bone.second)) - { - writer.writeUByte(boneIdx); - ++transKeyCount; - } - else - writer.writeUByte(0xff); - ++boneIdx; - } + writer.writeUint32Big(bones.size()); + size_t boneIdx = 0; + size_t rotKeyCount = 0; + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) { + writer.writeUByte(boneIdx); + ++rotKeyCount; + } else + writer.writeUByte(0xff); + ++boneIdx; + } - writer.writeUint32Big(bones.size()); - boneIdx = 0; - size_t scaleKeyCount = 0; - for (const std::pair>& bone : bones) - { - if (std::get<2>(bone.second)) - { - writer.writeUByte(boneIdx); - ++scaleKeyCount; - } - else - writer.writeUByte(0xff); - ++boneIdx; - } + writer.writeUint32Big(bones.size()); + boneIdx = 0; + size_t transKeyCount = 0; + for (const std::pair>& bone : bones) { + if (std::get<1>(bone.second)) { + writer.writeUByte(boneIdx); + ++transKeyCount; + } else + writer.writeUByte(0xff); + ++boneIdx; + } - writer.writeUint32Big(scaleKeyCount * head.keyCount); - auto cit = chanKeys.begin(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - ++cit; - if (std::get<1>(bone.second)) - ++cit; - if (std::get<2>(bone.second)) - { - const std::vector& keys = *cit++; - auto kit = keys.begin(); - for (size_t k=0 ; k>& bone : bones) { + if (std::get<2>(bone.second)) { + writer.writeUByte(boneIdx); + ++scaleKeyCount; + } else + writer.writeUByte(0xff); + ++boneIdx; + } - writer.writeUint32Big(rotKeyCount * head.keyCount); - cit = chanKeys.begin(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - { - const std::vector& keys = *cit++; - auto kit = keys.begin(); - for (size_t k=0 ; k(bone.second)) - ++cit; - if (std::get<2>(bone.second)) - ++cit; + writer.writeUint32Big(scaleKeyCount * head.keyCount); + auto cit = chanKeys.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + ++cit; + if (std::get<1>(bone.second)) + ++cit; + if (std::get<2>(bone.second)) { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k = 0; k < head.keyCount; ++k) + writer.writeVec3fBig(atVec3f{(*kit++).simd}); } + } - writer.writeUint32Big(transKeyCount * head.keyCount); - cit = chanKeys.begin(); - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - ++cit; - if (std::get<1>(bone.second)) - { - const std::vector& keys = *cit++; - auto kit = keys.begin(); - for (size_t k=0 ; k(bone.second)) - ++cit; + writer.writeUint32Big(rotKeyCount * head.keyCount); + cit = chanKeys.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k = 0; k < head.keyCount; ++k) + writer.writeVec4fBig(atVec4f{(*kit++).simd}); } + if (std::get<1>(bone.second)) + ++cit; + if (std::get<2>(bone.second)) + ++cit; + } + + writer.writeUint32Big(transKeyCount * head.keyCount); + cit = chanKeys.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + ++cit; + if (std::get<1>(bone.second)) { + const std::vector& keys = *cit++; + auto kit = keys.begin(); + for (size_t k = 0; k < head.keyCount; ++k) + writer.writeVec3fBig(atVec3f{(*kit++).simd}); + } + if (std::get<2>(bone.second)) + ++cit; + } } template <> -void ANIM::ANIM0::Enumerate(size_t& __isz) -{ - Header head; +void ANIM::ANIM0::Enumerate(size_t& __isz) { + Header head; - atUint32 maxId = 0; - for (const std::pair>& bone : bones) - maxId = std::max(maxId, bone.first); + atUint32 maxId = 0; + for (const std::pair>& bone : bones) + maxId = std::max(maxId, bone.first); - head.binarySize(__isz); - __isz += maxId + 1; - __isz += bones.size() * 3 + 12; + head.binarySize(__isz); + __isz += maxId + 1; + __isz += bones.size() * 3 + 12; - __isz += 12; - for (const std::pair>& bone : bones) - { - if (std::get<0>(bone.second)) - __isz += head.keyCount * 16; - if (std::get<1>(bone.second)) - __isz += head.keyCount * 12; - if (std::get<2>(bone.second)) - __isz += head.keyCount * 12; - } + __isz += 12; + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) + __isz += head.keyCount * 16; + if (std::get<1>(bone.second)) + __isz += head.keyCount * 12; + if (std::get<2>(bone.second)) + __isz += head.keyCount * 12; + } } -static float ComputeFrames(const std::vector& keyTimes, std::vector& framesOut) -{ - if (keyTimes.size() <= 1) - return 0.0; +static float ComputeFrames(const std::vector& keyTimes, std::vector& framesOut) { + if (keyTimes.size() <= 1) + return 0.0; - float mainInterval = FLT_MAX; - float lastTime = keyTimes[0]; - for (auto it=keyTimes.begin() + 1 ; it != keyTimes.end() ; ++it) - { - float diff = *it - lastTime; - if (diff < mainInterval) - mainInterval = diff; - lastTime = *it; - } + float mainInterval = FLT_MAX; + float lastTime = keyTimes[0]; + for (auto it = keyTimes.begin() + 1; it != keyTimes.end(); ++it) { + float diff = *it - lastTime; + if (diff < mainInterval) + mainInterval = diff; + lastTime = *it; + } - float fps = round(1.0 / mainInterval); - if (fps < 15.0) - fps = 15.0; - mainInterval = 1.0 / fps; + float fps = round(1.0 / mainInterval); + if (fps < 15.0) + fps = 15.0; + mainInterval = 1.0 / fps; - framesOut.clear(); - framesOut.reserve(keyTimes.size()); - atUint32 frameAccum = 0; - for (float time : keyTimes) - { - while (frameAccum * mainInterval < time) - ++frameAccum; - framesOut.push_back(frameAccum); - } + framesOut.clear(); + framesOut.reserve(keyTimes.size()); + atUint32 frameAccum = 0; + for (float time : keyTimes) { + while (frameAccum * mainInterval < time) + ++frameAccum; + framesOut.push_back(frameAccum); + } - return mainInterval; + return mainInterval; } const char* ANIM::ANIM1::DNAType() { return "ANIM1"; } template <> -void ANIM::ANIM1::Enumerate(athena::io::IStreamReader& reader) -{ - Header head; - head.read(reader); +void ANIM::ANIM1::Enumerate(athena::io::IStreamReader& reader) { + Header head; + head.read(reader); - std::vector keyTimes; - keyTimes.reserve(head.keyCount); - for (size_t k=0 ; k keyTimes; + keyTimes.reserve(head.keyCount); + for (size_t k = 0; k < head.keyCount; ++k) + keyTimes.push_back(reader.readFloatBig()); + mainInterval = ComputeFrames(keyTimes, frames); - atUint8 boneFlagCount = reader.readUByte(); - bones.clear(); - bones.reserve(boneFlagCount); - atUint32 boneChannelCount = 0; - for (atUint8 f=0 ; f initBlock; + initBlock.reserve(head.initBlockSize / 2); + for (size_t i = 0; i < head.initBlockSize / 2; ++i) + initBlock.push_back(reader.readInt16Big()); + + atUint32 rawChannelCount = reader.readUint32Big(); + reader.readUint32Big(); + reader.readUint32Big(); + + std::vector chanBitCounts; + chanBitCounts.reserve(rawChannelCount); + for (size_t c = 0; c < rawChannelCount; ++c) + chanBitCounts.push_back(reader.readUByte()); + + channels.clear(); + channels.reserve(boneChannelCount + 1); + channels.emplace_back(); + channels.back().type = DNAANIM::Channel::Type::KfHead; + auto initsIt = initBlock.begin(); + auto bitsIt = chanBitCounts.begin(); + for (const std::pair>& bone : bones) { + if (std::get<0>(bone.second)) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::RotationMP3; + chan.i[0] = *initsIt++; + chan.q[0] = *bitsIt++; + chan.i[1] = *initsIt++; + chan.q[1] = *bitsIt++; + chan.i[2] = *initsIt++; + chan.q[2] = *bitsIt++; + chan.i[3] = *initsIt++; + chan.q[3] = *bitsIt++; } - std::vector initBlock; - initBlock.reserve(head.initBlockSize/2); - for (size_t i=0 ; i chanBitCounts; - chanBitCounts.reserve(rawChannelCount); - for (size_t c=0 ; c>& bone : bones) - { - if (std::get<0>(bone.second)) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::RotationMP3; - chan.i[0] = *initsIt++; - chan.q[0] = *bitsIt++; - chan.i[1] = *initsIt++; - chan.q[1] = *bitsIt++; - chan.i[2] = *initsIt++; - chan.q[2] = *bitsIt++; - chan.i[3] = *initsIt++; - chan.q[3] = *bitsIt++; - } - - if (std::get<1>(bone.second)) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::Translation; - chan.i[0] = *initsIt++; - chan.q[0] = *bitsIt++; - chan.i[1] = *initsIt++; - chan.q[1] = *bitsIt++; - chan.i[2] = *initsIt++; - chan.q[2] = *bitsIt++; - } - - if (std::get<2>(bone.second)) - { - channels.emplace_back(); - DNAANIM::Channel& chan = channels.back(); - chan.type = DNAANIM::Channel::Type::Scale; - chan.i[0] = *initsIt++; - chan.q[0] = *bitsIt++; - chan.i[1] = *initsIt++; - chan.q[1] = *bitsIt++; - chan.i[2] = *initsIt++; - chan.q[2] = *bitsIt++; - } + if (std::get<1>(bone.second)) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Translation; + chan.i[0] = *initsIt++; + chan.q[0] = *bitsIt++; + chan.i[1] = *initsIt++; + chan.q[1] = *bitsIt++; + chan.i[2] = *initsIt++; + chan.q[2] = *bitsIt++; } - size_t bsSize = DNAANIM::ComputeBitstreamSize(head.keyCount-1, channels); - std::unique_ptr bsData = reader.readUBytes(bsSize); - DNAANIM::BitstreamReader bsReader; - chanKeys = bsReader.read(bsData.get(), head.keyCount-1, channels, 32767, head.translationMult, head.scaleMult); + if (std::get<2>(bone.second)) { + channels.emplace_back(); + DNAANIM::Channel& chan = channels.back(); + chan.type = DNAANIM::Channel::Type::Scale; + chan.i[0] = *initsIt++; + chan.q[0] = *bitsIt++; + chan.i[1] = *initsIt++; + chan.q[1] = *bitsIt++; + chan.i[2] = *initsIt++; + chan.q[2] = *bitsIt++; + } + } + + size_t bsSize = DNAANIM::ComputeBitstreamSize(head.keyCount - 1, channels); + std::unique_ptr bsData = reader.readUBytes(bsSize); + DNAANIM::BitstreamReader bsReader; + chanKeys = bsReader.read(bsData.get(), head.keyCount - 1, channels, 32767, head.translationMult, head.scaleMult); } template <> -void ANIM::ANIM1::Enumerate(athena::io::IStreamWriter& writer) -{ -} +void ANIM::ANIM1::Enumerate(athena::io::IStreamWriter& writer) {} template <> -void ANIM::ANIM1::Enumerate(size_t& __isz) -{ -} +void ANIM::ANIM1::Enumerate(size_t& __isz) {} -} +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/ANIM.hpp b/DataSpec/DNAMP3/ANIM.hpp index a7b024b48..1acf10ed8 100644 --- a/DataSpec/DNAMP3/ANIM.hpp +++ b/DataSpec/DNAMP3/ANIM.hpp @@ -6,95 +6,81 @@ #include "CINF.hpp" #include "DataSpec/DNACommon/ANCS.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct ANIM : BigDNA -{ +struct ANIM : BigDNA { + AT_DECL_EXPLICIT_DNA + + struct IANIM : BigDNAV { + Delete expl; + atUint32 m_version; + IANIM(atUint32 version) : m_version(version) {} + + std::vector>> bones; + std::vector frames; + std::vector channels; + std::vector> chanKeys; + float mainInterval = 0.0; + bool looping = false; + + void sendANIMToBlender(hecl::blender::PyOutStream&, const DNAANIM::RigInverter& rig, bool additive) const; + }; + + struct ANIM0 : IANIM { AT_DECL_EXPLICIT_DNA + AT_DECL_DNAV + ANIM0() : IANIM(0) {} - struct IANIM : BigDNAV - { - Delete expl; - atUint32 m_version; - IANIM(atUint32 version) : m_version(version) {} - - std::vector>> bones; - std::vector frames; - std::vector channels; - std::vector> chanKeys; - float mainInterval = 0.0; - bool looping = false; - - void sendANIMToBlender(hecl::blender::PyOutStream&, - const DNAANIM::RigInverter& rig, - bool additive) const; + struct Header : BigDNA { + AT_DECL_DNA + Value unkS; + Value duration; + Value unk0; + Value interval; + Value unk1; + Value keyCount; + Value unk2; + Value boneSlotCount; }; + }; - struct ANIM0 : IANIM - { - AT_DECL_EXPLICIT_DNA - AT_DECL_DNAV - ANIM0() : IANIM(0) {} + struct ANIM1 : IANIM { + AT_DECL_EXPLICIT_DNA + AT_DECL_DNAV + ANIM1() : IANIM(1) {} - struct Header : BigDNA - { - AT_DECL_DNA - Value unkS; - Value duration; - Value unk0; - Value interval; - Value unk1; - Value keyCount; - Value unk2; - Value boneSlotCount; - }; + struct Header : BigDNA { + AT_DECL_DNA + Value unk1; + Value unk2; + Value unk3; + Value unk4[3]; + Value translationMult; + Value scaleMult; + Value unk7; + Value unk8; + Value unk9; + Value duration; + Value keyCount; + Value blobSize; + Value unk10; + Value floatsSize; + Value flagsSize; + Value initBlockSize; + Value streamSize; + Value unk11; + Value boneCount; }; + }; - struct ANIM1 : IANIM - { - AT_DECL_EXPLICIT_DNA - AT_DECL_DNAV - ANIM1() : IANIM(1) {} + std::unique_ptr m_anim; - struct Header : BigDNA - { - AT_DECL_DNA - Value unk1; - Value unk2; - Value unk3; - Value unk4[3]; - Value translationMult; - Value scaleMult; - Value unk7; - Value unk8; - Value unk9; - Value duration; - Value keyCount; - Value blobSize; - Value unk10; - Value floatsSize; - Value flagsSize; - Value initBlockSize; - Value streamSize; - Value unk11; - Value boneCount; - }; - }; - - std::unique_ptr m_anim; - - void sendANIMToBlender(hecl::blender::PyOutStream& os, - const DNAANIM::RigInverter& rig, - bool additive) const - { - m_anim->sendANIMToBlender(os, rig, additive); - } - - void extractEVNT(const DNAANCS::AnimationResInfo& animInfo, - const hecl::ProjectPath& outPath, PAKRouter& pakRouter, bool force) const {} + void sendANIMToBlender(hecl::blender::PyOutStream& os, const DNAANIM::RigInverter& rig, bool additive) const { + m_anim->sendANIMToBlender(os, rig, additive); + } + void extractEVNT(const DNAANCS::AnimationResInfo& animInfo, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, bool force) const {} }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CAUD.cpp b/DataSpec/DNAMP3/CAUD.cpp index 2e1e28e6a..7930a8855 100644 --- a/DataSpec/DNAMP3/CAUD.cpp +++ b/DataSpec/DNAMP3/CAUD.cpp @@ -1,24 +1,21 @@ #include "CAUD.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { template -void CAUD::CSMPInfo::UnknownStruct2::UnknownQuad::Enumerate(typename Op::StreamT& s) -{ - Do({"unknown1"}, unknown1, s); - Do({"unknown2"}, unknown2, s); - Do({"unknown3"}, unknown3, s); - Do({"unknown4"}, unknown4, s); - if (unknown4 == 5) - Do({"unknown5"}, unknown5, s); +void CAUD::CSMPInfo::UnknownStruct2::UnknownQuad::Enumerate(typename Op::StreamT& s) { + Do({"unknown1"}, unknown1, s); + Do({"unknown2"}, unknown2, s); + Do({"unknown3"}, unknown3, s); + Do({"unknown4"}, unknown4, s); + if (unknown4 == 5) + Do({"unknown5"}, unknown5, s); } AT_SPECIALIZE_DNA_YAML(CAUD::CSMPInfo::UnknownStruct2::UnknownQuad) -const char* CAUD::CSMPInfo::UnknownStruct2::UnknownQuad::DNAType() -{ - return "DataSpec::DNAMP3::CAUD::CSMPInfo::UnknownStruct2::UnknownQuad"; +const char* CAUD::CSMPInfo::UnknownStruct2::UnknownQuad::DNAType() { + return "DataSpec::DNAMP3::CAUD::CSMPInfo::UnknownStruct2::UnknownQuad"; } -} +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CAUD.hpp b/DataSpec/DNAMP3/CAUD.hpp index 28f6f6708..6edb47108 100644 --- a/DataSpec/DNAMP3/CAUD.hpp +++ b/DataSpec/DNAMP3/CAUD.hpp @@ -3,117 +3,107 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "DataSpec/DNACommon/PAK.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct CAUD : BigDNA -{ +struct CAUD : BigDNA { + AT_DECL_DNA_YAML + DNAFourCC magic; + Value version; + String<-1> name; + Value nameCount; + Vector, AT_DNA_COUNT(nameCount)> names; + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + + struct CSMPInfo : BigDNA { AT_DECL_DNA_YAML - DNAFourCC magic; - Value version; - String<-1> name; - Value nameCount; - Vector, AT_DNA_COUNT(nameCount)> names; + Value dataLen; + UniqueID64 csmpId; Value unknown1; Value unknown2; - Value unknown3; + Value unknown3; Value unknown4; - Value unknown5; - - struct CSMPInfo : BigDNA - { - AT_DECL_DNA_YAML - Value dataLen; - UniqueID64 csmpId; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; - Value unknown13; - Value unknown14[8]; - struct UnknownStruct1 : BigDNA - { - AT_DECL_DNA_YAML - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - }; - Value unknown15; - Vector unknown16; - struct UnknownStruct2 : BigDNA - { - AT_DECL_DNA_YAML - Value unknown1; - Vector unknown2; - Value unknown3; - Value unknown4; - Value unknown5; - struct UnknownPair : BigDNA - { - AT_DECL_DNA_YAML - Value unknown1; - Value unknown2; - }; - Value unknown6; - Vector unknown7; - struct UnknownQuad: BigDNA - { - AT_DECL_EXPLICIT_DNA_YAML - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5[5]; - }; - - Value unknown8; - Vector unknown9; - }; - UnknownStruct2 unknown17[4]; - Value unknown18; - Value unknown19; - Value unknown20; - Value unknown21; - Value unknown22; - Value unknown23; - Value unknown24; - Value unknown25; - Value unknown26; - Value unknown27; - Value unknown28; - struct UnknownStruct3 : BigDNA - { - AT_DECL_DNA_YAML - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - }; - Vector unknown29; - Value unknown30; - Value unknown31; + Value unknown5; + Value unknown6; + Value unknown7; + Value unknown8; + Value unknown9; + Value unknown10; + Value unknown11; + Value unknown12; + Value unknown13; + Value unknown14[8]; + struct UnknownStruct1 : BigDNA { + AT_DECL_DNA_YAML + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; }; + Value unknown15; + Vector unknown16; + struct UnknownStruct2 : BigDNA { + AT_DECL_DNA_YAML + Value unknown1; + Vector unknown2; + Value unknown3; + Value unknown4; + Value unknown5; + struct UnknownPair : BigDNA { + AT_DECL_DNA_YAML + Value unknown1; + Value unknown2; + }; + Value unknown6; + Vector unknown7; + struct UnknownQuad : BigDNA { + AT_DECL_EXPLICIT_DNA_YAML + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + Value unknown5[5]; + }; - Value infoCount; - Vector info; + Value unknown8; + Vector unknown9; + }; + UnknownStruct2 unknown17[4]; + Value unknown18; + Value unknown19; + Value unknown20; + Value unknown21; + Value unknown22; + Value unknown23; + Value unknown24; + Value unknown25; + Value unknown26; + Value unknown27; + Value unknown28; + struct UnknownStruct3 : BigDNA { + AT_DECL_DNA_YAML + Value unknown1; + Value unknown2; + Value unknown3; + Value unknown4; + }; + Vector unknown29; + Value unknown30; + Value unknown31; + }; - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) - { - CAUD caud; - caud.read(rs); - athena::io::FileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(caud, writer); - return true; - } + Value infoCount; + Vector info; + + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + CAUD caud; + caud.read(rs); + athena::io::FileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(caud, writer); + return true; + } }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CHAR.cpp b/DataSpec/DNAMP3/CHAR.cpp index 3b83c0c38..10bc8eee8 100644 --- a/DataSpec/DNAMP3/CHAR.cpp +++ b/DataSpec/DNAMP3/CHAR.cpp @@ -1,183 +1,157 @@ #include "CHAR.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { template <> -void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(athena::io::IStreamReader& reader) -{ - EventBase::read(reader); - caudId.read(reader); - unk1 = reader.readUint32Big(); - unk2 = reader.readUint32Big(); - unk3 = reader.readUint32Big(); - reader.enumerateBig(unk3Vals, unk3); - extraType = reader.readUint32Big(); - if (extraType == 1) - extraFloat = reader.readFloatBig(); - else if (extraType == 2) - reader.seek(35, athena::Current); +void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(athena::io::IStreamReader& reader) { + EventBase::read(reader); + caudId.read(reader); + unk1 = reader.readUint32Big(); + unk2 = reader.readUint32Big(); + unk3 = reader.readUint32Big(); + reader.enumerateBig(unk3Vals, unk3); + extraType = reader.readUint32Big(); + if (extraType == 1) + extraFloat = reader.readFloatBig(); + else if (extraType == 2) + reader.seek(35, athena::Current); } template <> -void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(athena::io::IStreamWriter& writer) -{ - EventBase::write(writer); - caudId.write(writer); - writer.writeUint32Big(unk1); - writer.writeUint32Big(unk2); - writer.writeUint32Big(unk3); - writer.enumerateBig(unk3Vals); - writer.writeUint32Big(extraType); - if (extraType == 1) - writer.writeFloatBig(extraFloat); - else if (extraType == 2) - writer.seek(35, athena::Current); +void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(athena::io::IStreamWriter& writer) { + EventBase::write(writer); + caudId.write(writer); + writer.writeUint32Big(unk1); + writer.writeUint32Big(unk2); + writer.writeUint32Big(unk3); + writer.enumerateBig(unk3Vals); + writer.writeUint32Big(extraType); + if (extraType == 1) + writer.writeFloatBig(extraFloat); + else if (extraType == 2) + writer.seek(35, athena::Current); } template <> -void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(size_t& __isz) -{ - EventBase::binarySize(__isz); - caudId.binarySize(__isz); - __isz += 16; - __isz += unk3Vals.size() * 4; - if (extraType == 1) - __isz += 4; - else if (extraType == 2) - __isz += 35; -} - -template <> -void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(athena::io::YAMLDocReader& reader) -{ - EventBase::read(reader); - reader.enumerate("caudId", caudId); - unk1 = reader.readUint32("unk1"); - unk2 = reader.readUint32("unk2"); - unk3 = reader.enumerate("unk3Vals", unk3Vals); - extraType = reader.readUint32("extraType"); - if (extraType == 1) - extraFloat = reader.readFloat("extraFloat"); -} - -template <> -void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(athena::io::YAMLDocWriter& writer) -{ - EventBase::write(writer); - writer.enumerate("caudId", caudId); - writer.writeUint32("unk1", unk1); - writer.writeUint32("unk2", unk2); - writer.enumerate("unk3Vals", unk3Vals); - writer.writeUint32("extraType", extraType); - if (extraType == 1) - writer.writeFloat("extraFloat", extraFloat); -} - -const char* CHAR::AnimationInfo::EVNT::SFXEvent::DNAType() -{ - return "urde::DNAMP3::CHAR::AnimationInfo::EVNT::SFXEvent"; -} - -template <> -void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(athena::io::IStreamReader& reader) -{ - IMetaAnim::Type type(IMetaAnim::Type(reader.readUint32Big())); - switch (type) - { - case IMetaAnim::Type::Primitive: - m_anim.reset(new struct MetaAnimPrimitive); - m_anim->read(reader); - break; - case IMetaAnim::Type::Blend: - m_anim.reset(new struct MetaAnimBlend); - m_anim->read(reader); - break; - case IMetaAnim::Type::PhaseBlend: - m_anim.reset(new struct MetaAnimPhaseBlend); - m_anim->read(reader); - break; - case IMetaAnim::Type::Random: - m_anim.reset(new struct MetaAnimRandom); - m_anim->read(reader); - break; - case IMetaAnim::Type::Sequence: - m_anim.reset(new struct MetaAnimSequence); - m_anim->read(reader); - break; - default: - m_anim.reset(nullptr); - break; - } -} - -template <> -void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(athena::io::IStreamWriter& writer) -{ - if (!m_anim) - return; - writer.writeInt32Big(atInt32(m_anim->m_type)); - m_anim->write(writer); -} - -template <> -void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(size_t& __isz) -{ - if (!m_anim) - return; +void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(size_t& __isz) { + EventBase::binarySize(__isz); + caudId.binarySize(__isz); + __isz += 16; + __isz += unk3Vals.size() * 4; + if (extraType == 1) __isz += 4; - m_anim->binarySize(__isz); + else if (extraType == 2) + __isz += 35; } template <> -void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(athena::io::YAMLDocReader& reader) -{ - std::string type = reader.readString("type"); - std::transform(type.begin(), type.end(), type.begin(), tolower); - if (!type.compare("primitive")) - { - m_anim.reset(new struct MetaAnimPrimitive); - m_anim->read(reader); - } - else if (!type.compare("blend")) - { - m_anim.reset(new struct MetaAnimBlend); - m_anim->read(reader); - } - else if (!type.compare("phaseblend")) - { - m_anim.reset(new struct MetaAnimPhaseBlend); - m_anim->read(reader); - } - else if (!type.compare("random")) - { - m_anim.reset(new struct MetaAnimRandom); - m_anim->read(reader); - } - else if (!type.compare("sequence")) - { - m_anim.reset(new struct MetaAnimSequence); - m_anim->read(reader); - } - else - { - m_anim.reset(nullptr); - } - +void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(athena::io::YAMLDocReader& reader) { + EventBase::read(reader); + reader.enumerate("caudId", caudId); + unk1 = reader.readUint32("unk1"); + unk2 = reader.readUint32("unk2"); + unk3 = reader.enumerate("unk3Vals", unk3Vals); + extraType = reader.readUint32("extraType"); + if (extraType == 1) + extraFloat = reader.readFloat("extraFloat"); } template <> -void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(athena::io::YAMLDocWriter& writer) -{ - if (!m_anim) - return; - writer.writeString("type", m_anim->m_typeStr); - m_anim->write(writer); +void CHAR::AnimationInfo::EVNT::SFXEvent::Enumerate(athena::io::YAMLDocWriter& writer) { + EventBase::write(writer); + writer.enumerate("caudId", caudId); + writer.writeUint32("unk1", unk1); + writer.writeUint32("unk2", unk2); + writer.enumerate("unk3Vals", unk3Vals); + writer.writeUint32("extraType", extraType); + if (extraType == 1) + writer.writeFloat("extraFloat", extraFloat); } -const char* CHAR::AnimationInfo::MetaAnimFactory::DNAType() -{ - return "urde::DNAMP3::CHAR::AnimationInfo::MetaAnimFactory"; +const char* CHAR::AnimationInfo::EVNT::SFXEvent::DNAType() { + return "urde::DNAMP3::CHAR::AnimationInfo::EVNT::SFXEvent"; } +template <> +void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(athena::io::IStreamReader& reader) { + IMetaAnim::Type type(IMetaAnim::Type(reader.readUint32Big())); + switch (type) { + case IMetaAnim::Type::Primitive: + m_anim.reset(new struct MetaAnimPrimitive); + m_anim->read(reader); + break; + case IMetaAnim::Type::Blend: + m_anim.reset(new struct MetaAnimBlend); + m_anim->read(reader); + break; + case IMetaAnim::Type::PhaseBlend: + m_anim.reset(new struct MetaAnimPhaseBlend); + m_anim->read(reader); + break; + case IMetaAnim::Type::Random: + m_anim.reset(new struct MetaAnimRandom); + m_anim->read(reader); + break; + case IMetaAnim::Type::Sequence: + m_anim.reset(new struct MetaAnimSequence); + m_anim->read(reader); + break; + default: + m_anim.reset(nullptr); + break; + } } + +template <> +void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(athena::io::IStreamWriter& writer) { + if (!m_anim) + return; + writer.writeInt32Big(atInt32(m_anim->m_type)); + m_anim->write(writer); +} + +template <> +void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(size_t& __isz) { + if (!m_anim) + return; + __isz += 4; + m_anim->binarySize(__isz); +} + +template <> +void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(athena::io::YAMLDocReader& reader) { + std::string type = reader.readString("type"); + std::transform(type.begin(), type.end(), type.begin(), tolower); + if (!type.compare("primitive")) { + m_anim.reset(new struct MetaAnimPrimitive); + m_anim->read(reader); + } else if (!type.compare("blend")) { + m_anim.reset(new struct MetaAnimBlend); + m_anim->read(reader); + } else if (!type.compare("phaseblend")) { + m_anim.reset(new struct MetaAnimPhaseBlend); + m_anim->read(reader); + } else if (!type.compare("random")) { + m_anim.reset(new struct MetaAnimRandom); + m_anim->read(reader); + } else if (!type.compare("sequence")) { + m_anim.reset(new struct MetaAnimSequence); + m_anim->read(reader); + } else { + m_anim.reset(nullptr); + } +} + +template <> +void CHAR::AnimationInfo::MetaAnimFactory::Enumerate(athena::io::YAMLDocWriter& writer) { + if (!m_anim) + return; + writer.writeString("type", m_anim->m_typeStr); + m_anim->write(writer); +} + +const char* CHAR::AnimationInfo::MetaAnimFactory::DNAType() { + return "urde::DNAMP3::CHAR::AnimationInfo::MetaAnimFactory"; +} + +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CHAR.hpp b/DataSpec/DNAMP3/CHAR.hpp index 23f51baba..1c97cd944 100644 --- a/DataSpec/DNAMP3/CHAR.hpp +++ b/DataSpec/DNAMP3/CHAR.hpp @@ -9,342 +9,293 @@ #include "ANIM.hpp" #include "../DNAMP2/ANCS.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct CHAR : BigDNA -{ - using CINFType = CINF; - using CSKRType = CSKR; - using ANIMType = ANIM; +struct CHAR : BigDNA { + using CINFType = CINF; + using CSKRType = CSKR; + using ANIMType = ANIM; + AT_DECL_DNA_YAML + Value version; + + struct CharacterInfo : BigDNA { AT_DECL_DNA_YAML - Value version; - - struct CharacterInfo : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - UniqueID64 cmdl; - UniqueID64 cskr; - Value overlayCount; - struct Overlay : BigDNA - { - AT_DECL_DNA_YAML - DNAFourCC type; - UniqueID64 cmdl; - UniqueID64 cskr; - }; - Vector overlays; - UniqueID64 cinf; - UniqueID64 sand; - - using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo; - MP1CharacterInfo::PASDatabase pasDatabase; - - struct ParticleResData : BigDNA - { - AT_DECL_DNA_YAML - Value partCount; - Vector part; - Value swhcCount; - Vector swhc; - Value unkCount; - Vector unk; - Value elscCount; - Vector elsc; - Value spscCount; - Vector spsc; - Value unk2Count; - Vector unk2; - } partResData; - - } characterInfo; - - struct AnimationInfo : BigDNA - { - AT_DECL_DNA_YAML - - struct EVNT : BigDNA - { - AT_DECL_DNA_YAML - Value eventIdx; - String<-1> eventName; - - struct EventBase : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name1; - Value unk0; - String<-1> name2; - Value type; - Value unk1; - Value unk2; - Value unk3; - Value unk4; - Value unk5; - Value unk6; - Value unk7; - Value unk8; - Value unk9; - Value unk10; - Value unk11; - Value unk12; - Value unk13; - }; - - struct EffectEvent : EventBase - { - AT_DECL_DNA_YAML - DNAFourCC effectType; - UniqueID64 effectId; - Value scale; - Value parentMode; - }; - Value effectCount; - Vector effectEvents; - - struct SFXEvent : EventBase - { - AT_DECL_DNA_YAML - Delete expl; - - UniqueID64 caudId; - Value unk1_; - Value unk2_; - Value unk3_; - std::vector unk3Vals; - Value extraType; - Value extraFloat; - }; - Value sfxCount; - Vector sfxEvents; - }; - Value evntCount; - Vector evnts; - - struct IMetaAnim : BigDNAVYaml - { - Delete expl; - enum class Type - { - Primitive = 0, - Blend = 1, - PhaseBlend = 2, - Random = 3, - Sequence = 4 - } m_type; - const char* m_typeStr; - IMetaAnim(Type type, const char* typeStr) - : m_type(type), m_typeStr(typeStr) {} - virtual void gatherPrimitives(std::map>& out)=0; - }; - struct MetaAnimFactory : BigDNA - { - AT_DECL_DNA_YAML - Delete expl; - std::unique_ptr m_anim; - }; - struct MetaAnimPrimitive : IMetaAnim - { - MetaAnimPrimitive() : IMetaAnim(Type::Primitive, "Primitive") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - UniqueID64 animId; - Value animIdx; - String<-1> animName; - Value unk1; - Value unk2; - - void gatherPrimitives(std::map>& out) - { - out[animIdx] = {animName, animId, UniqueID64(), false}; - } - }; - struct MetaAnimBlend : IMetaAnim - { - MetaAnimBlend() : IMetaAnim(Type::Blend, "Blend") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - MetaAnimFactory animA; - MetaAnimFactory animB; - Value unkFloat; - Value unk; - - void gatherPrimitives(std::map>& out) - { - animA.m_anim->gatherPrimitives(out); - animB.m_anim->gatherPrimitives(out); - } - }; - struct MetaAnimPhaseBlend : IMetaAnim - { - MetaAnimPhaseBlend() : IMetaAnim(Type::PhaseBlend, "PhaseBlend") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - MetaAnimFactory animA; - MetaAnimFactory animB; - Value unkFloat; - Value unk; - - void gatherPrimitives(std::map>& out) - { - animA.m_anim->gatherPrimitives(out); - animB.m_anim->gatherPrimitives(out); - } - }; - struct MetaAnimRandom : IMetaAnim - { - MetaAnimRandom() : IMetaAnim(Type::Random, "Random") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value animCount; - struct Child : BigDNA - { - AT_DECL_DNA_YAML - MetaAnimFactory anim; - Value probability; - }; - Vector children; - - void gatherPrimitives(std::map>& out) - { - for (const auto& child : children) - child.anim.m_anim->gatherPrimitives(out); - } - }; - struct MetaAnimSequence : IMetaAnim - { - MetaAnimSequence() : IMetaAnim(Type::Sequence, "Sequence") {} - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value animCount; - Vector children; - - void gatherPrimitives(std::map>& out) - { - for (const auto& child : children) - child.m_anim->gatherPrimitives(out); - } - }; - - struct Animation : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - MetaAnimFactory metaAnim; - }; - Value animationCount; - Vector animations; - - struct ActionAABB : BigDNA - { - AT_DECL_DNA_YAML - UniqueID64 animId; - Value aabb[2]; - }; - Value animAABBCount; - Vector animAABBs; - - Value unkByte; - - Value additiveMapCount; - Vector additiveMap; - - } animationInfo; - - struct HitboxSet : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value hitboxCount; - struct Hitbox : BigDNA - { - AT_DECL_DNA_YAML - Value unk1; - Value unk2; - Value unk3; - Value unk4; - Value unk5; - Value unk6; - Value unk7; - Value unk8; - Value unk9; - Value unk10; - Value unk11; - Value unk12; - Value unk13; - String<-1> boneName; - Value unk14; - }; - Vector hitboxes; + String<-1> name; + UniqueID64 cmdl; + UniqueID64 cskr; + Value overlayCount; + struct Overlay : BigDNA { + AT_DECL_DNA_YAML + DNAFourCC type; + UniqueID64 cmdl; + UniqueID64 cskr; }; - Value hitboxSetCount; - Vector hitboxSets; + Vector overlays; + UniqueID64 cinf; + UniqueID64 sand; - void getCharacterResInfo(std::vector>& out) const - { - out.clear(); - out.reserve(1); - out.emplace_back(); - DNAANCS::CharacterResInfo& chOut = out.back(); - chOut.name = characterInfo.name; - chOut.cmdl = characterInfo.cmdl; - chOut.cskr = characterInfo.cskr; - chOut.cinf = characterInfo.cinf; + using MP1CharacterInfo = DNAMP1::ANCS::CharacterSet::CharacterInfo; + MP1CharacterInfo::PASDatabase pasDatabase; - for (const CharacterInfo::Overlay& overlay : characterInfo.overlays) - chOut.overlays.emplace_back(overlay.type.toString(), std::make_pair(overlay.cmdl, overlay.cskr)); + struct ParticleResData : BigDNA { + AT_DECL_DNA_YAML + Value partCount; + Vector part; + Value swhcCount; + Vector swhc; + Value unkCount; + Vector unk; + Value elscCount; + Vector elsc; + Value spscCount; + Vector spsc; + Value unk2Count; + Vector unk2; + } partResData; + + } characterInfo; + + struct AnimationInfo : BigDNA { + AT_DECL_DNA_YAML + + struct EVNT : BigDNA { + AT_DECL_DNA_YAML + Value eventIdx; + String<-1> eventName; + + struct EventBase : BigDNA { + AT_DECL_DNA_YAML + String<-1> name1; + Value unk0; + String<-1> name2; + Value type; + Value unk1; + Value unk2; + Value unk3; + Value unk4; + Value unk5; + Value unk6; + Value unk7; + Value unk8; + Value unk9; + Value unk10; + Value unk11; + Value unk12; + Value unk13; + }; + + struct EffectEvent : EventBase { + AT_DECL_DNA_YAML + DNAFourCC effectType; + UniqueID64 effectId; + Value scale; + Value parentMode; + }; + Value effectCount; + Vector effectEvents; + + struct SFXEvent : EventBase { + AT_DECL_DNA_YAML + Delete expl; + + UniqueID64 caudId; + Value unk1_; + Value unk2_; + Value unk3_; + std::vector unk3Vals; + Value extraType; + Value extraFloat; + }; + Value sfxCount; + Vector sfxEvents; + }; + Value evntCount; + Vector evnts; + + struct IMetaAnim : BigDNAVYaml { + Delete expl; + enum class Type { Primitive = 0, Blend = 1, PhaseBlend = 2, Random = 3, Sequence = 4 } m_type; + const char* m_typeStr; + IMetaAnim(Type type, const char* typeStr) : m_type(type), m_typeStr(typeStr) {} + virtual void gatherPrimitives(std::map>& out) = 0; + }; + struct MetaAnimFactory : BigDNA { + AT_DECL_DNA_YAML + Delete expl; + std::unique_ptr m_anim; + }; + struct MetaAnimPrimitive : IMetaAnim { + MetaAnimPrimitive() : IMetaAnim(Type::Primitive, "Primitive") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + UniqueID64 animId; + Value animIdx; + String<-1> animName; + Value unk1; + Value unk2; + + void gatherPrimitives(std::map>& out) { + out[animIdx] = {animName, animId, UniqueID64(), false}; + } + }; + struct MetaAnimBlend : IMetaAnim { + MetaAnimBlend() : IMetaAnim(Type::Blend, "Blend") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + MetaAnimFactory animA; + MetaAnimFactory animB; + Value unkFloat; + Value unk; + + void gatherPrimitives(std::map>& out) { + animA.m_anim->gatherPrimitives(out); + animB.m_anim->gatherPrimitives(out); + } + }; + struct MetaAnimPhaseBlend : IMetaAnim { + MetaAnimPhaseBlend() : IMetaAnim(Type::PhaseBlend, "PhaseBlend") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + MetaAnimFactory animA; + MetaAnimFactory animB; + Value unkFloat; + Value unk; + + void gatherPrimitives(std::map>& out) { + animA.m_anim->gatherPrimitives(out); + animB.m_anim->gatherPrimitives(out); + } + }; + struct MetaAnimRandom : IMetaAnim { + MetaAnimRandom() : IMetaAnim(Type::Random, "Random") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value animCount; + struct Child : BigDNA { + AT_DECL_DNA_YAML + MetaAnimFactory anim; + Value probability; + }; + Vector children; + + void gatherPrimitives(std::map>& out) { + for (const auto& child : children) + child.anim.m_anim->gatherPrimitives(out); + } + }; + struct MetaAnimSequence : IMetaAnim { + MetaAnimSequence() : IMetaAnim(Type::Sequence, "Sequence") {} + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value animCount; + Vector children; + + void gatherPrimitives(std::map>& out) { + for (const auto& child : children) + child.m_anim->gatherPrimitives(out); + } + }; + + struct Animation : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + MetaAnimFactory metaAnim; + }; + Value animationCount; + Vector animations; + + struct ActionAABB : BigDNA { + AT_DECL_DNA_YAML + UniqueID64 animId; + Value aabb[2]; + }; + Value animAABBCount; + Vector animAABBs; + + Value unkByte; + + Value additiveMapCount; + Vector additiveMap; + + } animationInfo; + + struct HitboxSet : BigDNA { + AT_DECL_DNA_YAML + String<-1> name; + Value hitboxCount; + struct Hitbox : BigDNA { + AT_DECL_DNA_YAML + Value unk1; + Value unk2; + Value unk3; + Value unk4; + Value unk5; + Value unk6; + Value unk7; + Value unk8; + Value unk9; + Value unk10; + Value unk11; + Value unk12; + Value unk13; + String<-1> boneName; + Value unk14; + }; + Vector hitboxes; + }; + Value hitboxSetCount; + Vector hitboxSets; + + void getCharacterResInfo(std::vector>& out) const { + out.clear(); + out.reserve(1); + out.emplace_back(); + DNAANCS::CharacterResInfo& chOut = out.back(); + chOut.name = characterInfo.name; + chOut.cmdl = characterInfo.cmdl; + chOut.cskr = characterInfo.cskr; + chOut.cinf = characterInfo.cinf; + + for (const CharacterInfo::Overlay& overlay : characterInfo.overlays) + chOut.overlays.emplace_back(overlay.type.toString(), std::make_pair(overlay.cmdl, overlay.cskr)); + } + + void getAnimationResInfo(PAKRouter* pakRouter, + std::map>& out) const { + out.clear(); + for (const AnimationInfo::Animation& ai : animationInfo.animations) + ai.metaAnim.m_anim->gatherPrimitives(out); + for (auto& animRes : out) + animRes.second.additive = animationInfo.additiveMap.at(animRes.first); + } + + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true); + hecl::ProjectPath::Type yamlType = yamlPath.getPathType(); + hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true); + hecl::ProjectPath::Type blendType = blendPath.getPathType(); + + if (force || yamlType == hecl::ProjectPath::Type::None || blendType == hecl::ProjectPath::Type::None) { + CHAR aChar; + aChar.read(rs); + + if (force || yamlType == hecl::ProjectPath::Type::None) { + athena::io::FileWriter writer(yamlPath.getAbsolutePath()); + athena::io::ToYAMLStream(aChar, writer); + } + + if (force || blendType == hecl::ProjectPath::Type::None) { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + DNAANCS::ReadANCSToBlender, CHAR, MaterialSet, DNACMDL::SurfaceHeader_3, 4>( + conn, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force); + } } - void getAnimationResInfo(PAKRouter* pakRouter, - std::map>& out) const - { - out.clear(); - for (const AnimationInfo::Animation& ai : animationInfo.animations) - ai.metaAnim.m_anim->gatherPrimitives(out); - for (auto& animRes : out) - animRes.second.additive = animationInfo.additiveMap.at(animRes.first); - } - - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) - { - hecl::ProjectPath yamlPath = outPath.getWithExtension(_SYS_STR(".yaml"), true); - hecl::ProjectPath::Type yamlType = yamlPath.getPathType(); - hecl::ProjectPath blendPath = outPath.getWithExtension(_SYS_STR(".blend"), true); - hecl::ProjectPath::Type blendType = blendPath.getPathType(); - - if (force || - yamlType == hecl::ProjectPath::Type::None || - blendType == hecl::ProjectPath::Type::None) - { - CHAR aChar; - aChar.read(rs); - - if (force || yamlType == hecl::ProjectPath::Type::None) - { - athena::io::FileWriter writer(yamlPath.getAbsolutePath()); - athena::io::ToYAMLStream(aChar, writer); - } - - if (force || blendType == hecl::ProjectPath::Type::None) - { - hecl::blender::Connection& conn = btok.getBlenderConnection(); - DNAANCS::ReadANCSToBlender, CHAR, MaterialSet, DNACMDL::SurfaceHeader_3, 4> - (conn, aChar, blendPath, pakRouter, entry, dataSpec, fileChanged, force); - } - } - - return true; - } + return true; + } }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CINF.cpp b/DataSpec/DNAMP3/CINF.cpp index 5028f85db..0a51b4fcf 100644 --- a/DataSpec/DNAMP3/CINF.cpp +++ b/DataSpec/DNAMP3/CINF.cpp @@ -1,55 +1,50 @@ #include "CINF.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& cinfId) const -{ - DNAANIM::RigInverter inverter(*this); +void CINF::sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& cinfId) const { + DNAANIM::RigInverter inverter(*this); - os.format("arm = bpy.data.armatures.new('CINF_%016" PRIX64 "')\n" - "arm_obj = bpy.data.objects.new(arm.name, arm)\n" - "bpy.context.scene.objects.link(arm_obj)\n" - "bpy.context.scene.objects.active = arm_obj\n" - "bpy.ops.object.mode_set(mode='EDIT')\n" - "arm_bone_table = {}\n", - cinfId.toUint64()); + os.format("arm = bpy.data.armatures.new('CINF_%016" PRIX64 + "')\n" + "arm_obj = bpy.data.objects.new(arm.name, arm)\n" + "bpy.context.scene.objects.link(arm_obj)\n" + "bpy.context.scene.objects.active = arm_obj\n" + "bpy.ops.object.mode_set(mode='EDIT')\n" + "arm_bone_table = {}\n", + cinfId.toUint64()); - for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - { - zeus::simd_floats originF(bone.m_origBone.origin.simd); - zeus::simd_floats tailF(bone.m_tail.mSimd); - os.format("bone = arm.edit_bones.new('%s')\n" - "bone.head = (%f,%f,%f)\n" - "bone.tail = (%f,%f,%f)\n" - "bone.use_inherit_scale = False\n" - "arm_bone_table[%u] = bone\n", - getBoneNameFromId(bone.m_origBone.id)->c_str(), - originF[0], originF[1], originF[2], - tailF[0], tailF[1], tailF[2], - bone.m_origBone.id); - } + for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) { + zeus::simd_floats originF(bone.m_origBone.origin.simd); + zeus::simd_floats tailF(bone.m_tail.mSimd); + os.format( + "bone = arm.edit_bones.new('%s')\n" + "bone.head = (%f,%f,%f)\n" + "bone.tail = (%f,%f,%f)\n" + "bone.use_inherit_scale = False\n" + "arm_bone_table[%u] = bone\n", + getBoneNameFromId(bone.m_origBone.id)->c_str(), originF[0], originF[1], originF[2], tailF[0], tailF[1], + tailF[2], bone.m_origBone.id); + } - if (bones.size()) - { - atUint32 nullId = bones[0].parentId; - for (const Bone& bone : bones) - if (bone.parentId != nullId) - os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId); - } + if (bones.size()) { + atUint32 nullId = bones[0].parentId; + for (const Bone& bone : bones) + if (bone.parentId != nullId) + os.format("arm_bone_table[%u].parent = arm_bone_table[%u]\n", bone.id, bone.parentId); + } - os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; + os << "bpy.ops.object.mode_set(mode='OBJECT')\n"; - const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION"; - for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) - os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", - getBoneNameFromId(bone.m_origBone.id)->c_str(), rotMode); + const char* rotMode = os.getConnection().hasSLERP() ? "QUATERNION_SLERP" : "QUATERNION"; + for (const DNAANIM::RigInverter::Bone& bone : inverter.getBones()) + os.format("arm_obj.pose.bones['%s'].rotation_mode = '%s'\n", getBoneNameFromId(bone.m_origBone.id)->c_str(), + rotMode); } -std::string CINF::GetCINFArmatureName(const UniqueID64& cinfId) -{ - return hecl::Format("CINF_%016" PRIX64, cinfId.toUint64()); +std::string CINF::GetCINFArmatureName(const UniqueID64& cinfId) { + return hecl::Format("CINF_%016" PRIX64, cinfId.toUint64()); } -} +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CINF.hpp b/DataSpec/DNAMP3/CINF.hpp index 1eeffa3c1..353f21bb8 100644 --- a/DataSpec/DNAMP3/CINF.hpp +++ b/DataSpec/DNAMP3/CINF.hpp @@ -3,15 +3,12 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "../DNAMP2/CINF.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct CINF : DNAMP2::CINF -{ - Delete expl; - void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& cinfId) const; - static std::string GetCINFArmatureName(const UniqueID64& cinfId); +struct CINF : DNAMP2::CINF { + Delete expl; + void sendCINFToBlender(hecl::blender::PyOutStream& os, const UniqueID64& cinfId) const; + static std::string GetCINFArmatureName(const UniqueID64& cinfId); }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CMDL.cpp b/DataSpec/DNAMP3/CMDL.cpp index 99367a13f..eb4012745 100644 --- a/DataSpec/DNAMP3/CMDL.cpp +++ b/DataSpec/DNAMP3/CMDL.cpp @@ -1,39 +1,30 @@ #include "CMDL.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -bool CMDL::Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool, - hecl::blender::Token& btok, - std::function) -{ - /* Check for RigPair */ - const typename CharacterAssociations::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id); - CINF cinf; - CSKR cskr; - std::pair loadRp(nullptr, nullptr); - if (rp) - { - pakRouter.lookupAndReadDNA(rp->first, cskr); - pakRouter.lookupAndReadDNA(rp->second, cinf); - loadRp.first = &cskr; - loadRp.second = &cinf; - } - - /* Do extract */ - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::Mesh)) - return false; - DNACMDL::ReadCMDLToBlender, MaterialSet, std::pair, DNACMDL::SurfaceHeader_3, 5> - (conn, rs, pakRouter, entry, dataSpec, loadRp); - return conn.saveBlend(); -} +bool CMDL::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool, hecl::blender::Token& btok, + std::function) { + /* Check for RigPair */ + const typename CharacterAssociations::RigPair* rp = pakRouter.lookupCMDLRigPair(entry.id); + CINF cinf; + CSKR cskr; + std::pair loadRp(nullptr, nullptr); + if (rp) { + pakRouter.lookupAndReadDNA(rp->first, cskr); + pakRouter.lookupAndReadDNA(rp->second, cinf); + loadRp.first = &cskr; + loadRp.second = &cinf; + } + /* Do extract */ + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.createBlend(outPath, hecl::blender::BlendType::Mesh)) + return false; + DNACMDL::ReadCMDLToBlender, MaterialSet, std::pair, DNACMDL::SurfaceHeader_3, 5>( + conn, rs, pakRouter, entry, dataSpec, loadRp); + return conn.saveBlend(); } +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CMDL.hpp b/DataSpec/DNAMP3/CMDL.hpp index 21e973c99..63df8cdc9 100644 --- a/DataSpec/DNAMP3/CMDL.hpp +++ b/DataSpec/DNAMP3/CMDL.hpp @@ -7,20 +7,12 @@ #include "CINF.hpp" #include "CSKR.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct CMDL -{ - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool, - hecl::blender::Token& btok, - std::function); +struct CMDL { + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool, hecl::blender::Token& btok, + std::function); }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CMDLMaterials.cpp b/DataSpec/DNAMP3/CMDLMaterials.cpp index df4f92af9..ae9835054 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.cpp +++ b/DataSpec/DNAMP3/CMDLMaterials.cpp @@ -3,382 +3,344 @@ using Stream = hecl::blender::PyOutStream; -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { using Material = MaterialSet::Material; template <> -void MaterialSet::Material::SectionFactory::Enumerate(typename Read::StreamT& reader) -{ - DNAFourCC type; - type.read(reader); - switch (ISection::Type(type.toUint32())) - { - case ISection::Type::PASS: - section.reset(new struct SectionPASS); - section->read(reader); - break; - case ISection::Type::CLR: - section.reset(new struct SectionCLR); - section->read(reader); - break; - case ISection::Type::INT: - section.reset(new struct SectionINT); - section->read(reader); - break; - default: - section.reset(nullptr); - break; +void MaterialSet::Material::SectionFactory::Enumerate(typename Read::StreamT& reader) { + DNAFourCC type; + type.read(reader); + switch (ISection::Type(type.toUint32())) { + case ISection::Type::PASS: + section.reset(new struct SectionPASS); + section->read(reader); + break; + case ISection::Type::CLR: + section.reset(new struct SectionCLR); + section->read(reader); + break; + case ISection::Type::INT: + section.reset(new struct SectionINT); + section->read(reader); + break; + default: + section.reset(nullptr); + break; + } +} +template <> +void MaterialSet::Material::SectionFactory::Enumerate(typename Write::StreamT& writer) { + if (!section) + return; + writer.writeUBytes((atUint8*)§ion->m_type, 4); + section->write(writer); +} +template <> +void MaterialSet::Material::SectionFactory::Enumerate(typename BinarySize::StreamT& s) { + s += 4; + section->binarySize(s); +} + +template <> +void MaterialSet::Material::Enumerate(typename Read::StreamT& reader) { + header.read(reader); + sections.clear(); + do { + sections.emplace_back(); + sections.back().read(reader); + } while (sections.back().section); + sections.pop_back(); +} +template <> +void MaterialSet::Material::Enumerate(typename Write::StreamT& writer) { + header.write(writer); + for (const SectionFactory& section : sections) + section.write(writer); + writer.writeUBytes((atUint8*)"END ", 4); +} +template <> +void MaterialSet::Material::Enumerate(typename BinarySize::StreamT& s) { + header.binarySize(s); + for (const SectionFactory& section : sections) + section.binarySize(s); + s += 4; +} + +void MaterialSet::RegisterMaterialProps(Stream& out) { + out << "bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Punchthrough Alpha')\n" + "bpy.types.Material.retro_shadow_occluder = bpy.props.BoolProperty(name='Retro: Shadow Occluder')\n" + "bpy.types.Material.retro_lightmapped = bpy.props.BoolProperty(name='Retro: Lightmapped')\n" + "bpy.types.Material.retro_opac = bpy.props.IntProperty(name='Retro: OPAC')\n" + "bpy.types.Material.retro_blod = bpy.props.IntProperty(name='Retro: BLOD')\n" + "bpy.types.Material.retro_bloi = bpy.props.IntProperty(name='Retro: BLOI')\n" + "bpy.types.Material.retro_bnif = bpy.props.IntProperty(name='Retro: BNIF')\n" + "bpy.types.Material.retro_xrbr = bpy.props.IntProperty(name='Retro: XRBR')\n" + "\n"; +} + +void MaterialSet::ConstructMaterial(Stream& out, const PAKRouter& pakRouter, const PAK::Entry& entry, + const Material& material, unsigned groupIdx, unsigned matIdx) { + unsigned i; + + out.format( + "new_material = bpy.data.materials.new('MAT_%u_%u')\n" + "new_material.use_shadows = True\n" + "new_material.use_transparent_shadows = True\n" + "new_material.diffuse_color = (1.0,1.0,1.0)\n" + "new_material.diffuse_intensity = 1.0\n" + "new_material.specular_intensity = 0.0\n" + "new_material.use_nodes = True\n" + "new_nodetree = new_material.node_tree\n" + "material_node = new_nodetree.nodes['Material']\n" + "final_node = new_nodetree.nodes['Output']\n" + "\n" + "gridder = hecl.Nodegrid(new_nodetree)\n" + "gridder.place_node(final_node, 3)\n" + "gridder.place_node(material_node, 0)\n" + "material_node.material = new_material\n" + "\n" + "texture_nodes = []\n" + "kcolor_nodes = []\n" + "color_combiner_nodes = []\n" + "alpha_combiner_nodes = []\n" + "tex_links = []\n" + "tev_reg_sockets = [None]*4\n" + "\n", + groupIdx, matIdx); + + /* Material Flags */ + out.format( + "new_material.retro_alpha_test = %s\n" + "new_material.retro_shadow_occluder = %s\n" + "new_material.game_settings.invisible = %s\n", + material.header.flags.alphaTest() ? "True" : "False", + material.header.flags.shadowOccluderMesh() ? "True" : "False", + material.header.flags.shadowOccluderMesh() ? "True" : "False"); + + /* Blend factors */ + if (material.header.flags.alphaBlending()) + out << "new_material.game_settings.alpha_blend = 'ALPHA'\n" + "new_material.use_transparency = True\n" + "new_material.transparency_method = 'RAYTRACE'\n" + "new_material.alpha = 1.0\n"; + else if (material.header.flags.additiveBlending()) + out << "new_material.game_settings.alpha_blend = 'ADD'\n" + "new_material.use_transparency = True\n" + "new_material.transparency_method = 'RAYTRACE'\n" + "new_material.alpha = 1.0\n"; + + /* Texmap list */ + out << "tex_maps = []\n" + "pnode = None\n" + "anode = None\n" + "rflv_tex_node = None\n"; + + /* Add PASSes */ + i = 0; + unsigned texMapIdx = 0; + unsigned texMtxIdx = 0; + unsigned kColorIdx = 0; + Material::ISection* prevSection = nullptr; + for (const Material::SectionFactory& factory : material.sections) { + factory.section->constructNode(out, pakRouter, entry, prevSection, i++, texMapIdx, texMtxIdx, kColorIdx); + Material::SectionPASS* pass = Material::SectionPASS::castTo(factory.section.get()); + if (!pass || + (pass && Material::SectionPASS::Subtype(pass->subtype.toUint32()) != Material::SectionPASS::Subtype::RFLV)) + prevSection = factory.section.get(); + } + + /* Connect final PASS */ + out << "if pnode:\n" + " new_nodetree.links.new(pnode.outputs['Next Color'], final_node.inputs['Color'])\n" + "else:\n" + " new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], final_node.inputs['Color'])\n" + "if anode:\n" + " new_nodetree.links.new(anode.outputs['Value'], final_node.inputs['Alpha'])\n" + "elif pnode:\n" + " new_nodetree.links.new(pnode.outputs['Next Alpha'], final_node.inputs['Alpha'])\n" + "else:\n" + " new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], final_node.inputs['Alpha'])\n"; +} + +void Material::SectionPASS::constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, + const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, + unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const { + /* Add Texture nodes */ + if (txtrId) { + std::string texName = pakRouter.getBestEntryName(txtrId); + const nod::Node* node; + const PAK::Entry* texEntry = pakRouter.lookupEntry(txtrId, &node); + hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); + if (txtrPath.isNone()) { + txtrPath.makeDirChain(false); + PAKEntryReadStream rs = texEntry->beginReadStream(*node); + TXTR::Extract(rs, txtrPath); } -} -template <> -void MaterialSet::Material::SectionFactory::Enumerate(typename Write::StreamT& writer) -{ - if (!section) - return; - writer.writeUBytes((atUint8*)§ion->m_type, 4); - section->write(writer); -} -template <> -void MaterialSet::Material::SectionFactory::Enumerate(typename BinarySize::StreamT& s) -{ - s += 4; - section->binarySize(s); -} + hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, txtrId); + hecl::SystemUTF8Conv resPathView(resPath); + out.format( + "if '%s' in bpy.data.textures:\n" + " image = bpy.data.images['%s']\n" + " texture = bpy.data.textures[image.name]\n" + "else:\n" + " image = bpy.data.images.load('''//%s''')\n" + " image.name = '%s'\n" + " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" + " texture.image = image\n" + "tex_maps.append(texture)\n" + "\n", + texName.c_str(), texName.c_str(), resPathView.c_str(), texName.c_str()); + if (uvAnim.size()) { + const UVAnimation& uva = uvAnim[0]; + DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uva.unk1 + (uva.unk1 < 2 ? 0 : 2)), texMtxIdx, + texMapIdx++); + DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals); + } else + DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uvSrc + 4), -1, texMapIdx++); + } -template <> -void MaterialSet::Material::Enumerate(typename Read::StreamT& reader) -{ - header.read(reader); - sections.clear(); - do { - sections.emplace_back(); - sections.back().read(reader); - } while (sections.back().section); - sections.pop_back(); -} -template <> -void MaterialSet::Material::Enumerate(typename Write::StreamT& writer) -{ - header.write(writer); - for (const SectionFactory& section : sections) - section.write(writer); - writer.writeUBytes((atUint8*)"END ", 4); -} -template <> -void MaterialSet::Material::Enumerate(typename BinarySize::StreamT& s) -{ - header.binarySize(s); - for (const SectionFactory& section : sections) - section.binarySize(s); - s += 4; -} - -void MaterialSet::RegisterMaterialProps(Stream& out) -{ - out << "bpy.types.Material.retro_alpha_test = bpy.props.BoolProperty(name='Retro: Punchthrough Alpha')\n" - "bpy.types.Material.retro_shadow_occluder = bpy.props.BoolProperty(name='Retro: Shadow Occluder')\n" - "bpy.types.Material.retro_lightmapped = bpy.props.BoolProperty(name='Retro: Lightmapped')\n" - "bpy.types.Material.retro_opac = bpy.props.IntProperty(name='Retro: OPAC')\n" - "bpy.types.Material.retro_blod = bpy.props.IntProperty(name='Retro: BLOD')\n" - "bpy.types.Material.retro_bloi = bpy.props.IntProperty(name='Retro: BLOI')\n" - "bpy.types.Material.retro_bnif = bpy.props.IntProperty(name='Retro: BNIF')\n" - "bpy.types.Material.retro_xrbr = bpy.props.IntProperty(name='Retro: XRBR')\n" - "\n"; -} - -void MaterialSet::ConstructMaterial(Stream& out, - const PAKRouter& pakRouter, - const PAK::Entry& entry, - const Material& material, - unsigned groupIdx, - unsigned matIdx) -{ - unsigned i; - - out.format("new_material = bpy.data.materials.new('MAT_%u_%u')\n" - "new_material.use_shadows = True\n" - "new_material.use_transparent_shadows = True\n" - "new_material.diffuse_color = (1.0,1.0,1.0)\n" - "new_material.diffuse_intensity = 1.0\n" - "new_material.specular_intensity = 0.0\n" - "new_material.use_nodes = True\n" - "new_nodetree = new_material.node_tree\n" - "material_node = new_nodetree.nodes['Material']\n" - "final_node = new_nodetree.nodes['Output']\n" - "\n" - "gridder = hecl.Nodegrid(new_nodetree)\n" - "gridder.place_node(final_node, 3)\n" - "gridder.place_node(material_node, 0)\n" - "material_node.material = new_material\n" - "\n" - "texture_nodes = []\n" - "kcolor_nodes = []\n" - "color_combiner_nodes = []\n" - "alpha_combiner_nodes = []\n" - "tex_links = []\n" - "tev_reg_sockets = [None]*4\n" - "\n", groupIdx, matIdx); - - /* Material Flags */ - out.format("new_material.retro_alpha_test = %s\n" - "new_material.retro_shadow_occluder = %s\n" - "new_material.game_settings.invisible = %s\n", - material.header.flags.alphaTest() ? "True" : "False", - material.header.flags.shadowOccluderMesh() ? "True" : "False", - material.header.flags.shadowOccluderMesh() ? "True" : "False"); - - - /* Blend factors */ - if (material.header.flags.alphaBlending()) - out << "new_material.game_settings.alpha_blend = 'ALPHA'\n" - "new_material.use_transparency = True\n" - "new_material.transparency_method = 'RAYTRACE'\n" - "new_material.alpha = 1.0\n"; - else if (material.header.flags.additiveBlending()) - out << "new_material.game_settings.alpha_blend = 'ADD'\n" - "new_material.use_transparency = True\n" - "new_material.transparency_method = 'RAYTRACE'\n" - "new_material.alpha = 1.0\n"; - - /* Texmap list */ - out << "tex_maps = []\n" - "pnode = None\n" - "anode = None\n" - "rflv_tex_node = None\n"; - - /* Add PASSes */ - i=0; - unsigned texMapIdx = 0; - unsigned texMtxIdx = 0; - unsigned kColorIdx = 0; - Material::ISection* prevSection = nullptr; - for (const Material::SectionFactory& factory : material.sections) - { - factory.section->constructNode(out, pakRouter, entry, prevSection, i++, texMapIdx, texMtxIdx, kColorIdx); - Material::SectionPASS* pass = Material::SectionPASS::castTo(factory.section.get()); - if (!pass || (pass && Material::SectionPASS::Subtype(pass->subtype.toUint32()) != Material::SectionPASS::Subtype::RFLV)) - prevSection = factory.section.get(); - } - - /* Connect final PASS */ - out << "if pnode:\n" - " new_nodetree.links.new(pnode.outputs['Next Color'], final_node.inputs['Color'])\n" - "else:\n" - " new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], final_node.inputs['Color'])\n" - "if anode:\n" - " new_nodetree.links.new(anode.outputs['Value'], final_node.inputs['Alpha'])\n" - "elif pnode:\n" - " new_nodetree.links.new(pnode.outputs['Next Alpha'], final_node.inputs['Alpha'])\n" - "else:\n" - " new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], final_node.inputs['Alpha'])\n"; -} - -void Material::SectionPASS::constructNode(hecl::blender::PyOutStream& out, - const PAKRouter& pakRouter, - const PAK::Entry& entry, - const Material::ISection* prevSection, - unsigned idx, - unsigned& texMapIdx, - unsigned& texMtxIdx, - unsigned& kColorIdx) const -{ - /* Add Texture nodes */ + /* Special case for RFLV (environment UV mask) */ + if (Subtype(subtype.toUint32()) == Subtype::RFLV) { if (txtrId) - { - std::string texName = pakRouter.getBestEntryName(txtrId); - const nod::Node* node; - const PAK::Entry* texEntry = pakRouter.lookupEntry(txtrId, &node); - hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry); - if (txtrPath.isNone()) - { - txtrPath.makeDirChain(false); - PAKEntryReadStream rs = texEntry->beginReadStream(*node); - TXTR::Extract(rs, txtrPath); - } - hecl::SystemString resPath = pakRouter.getResourceRelativePath(entry, txtrId); - hecl::SystemUTF8Conv resPathView(resPath); - out.format("if '%s' in bpy.data.textures:\n" - " image = bpy.data.images['%s']\n" - " texture = bpy.data.textures[image.name]\n" - "else:\n" - " image = bpy.data.images.load('''//%s''')\n" - " image.name = '%s'\n" - " texture = bpy.data.textures.new(image.name, 'IMAGE')\n" - " texture.image = image\n" - "tex_maps.append(texture)\n" - "\n", texName.c_str(), texName.c_str(), - resPathView.c_str(), texName.c_str()); - if (uvAnim.size()) - { - const UVAnimation& uva = uvAnim[0]; - DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uva.unk1 + (uva.unk1 < 2 ? 0 : 2)), texMtxIdx, texMapIdx++); - DNAMP1::MaterialSet::Material::AddTextureAnim(out, uva.anim.mode, texMtxIdx++, uva.anim.vals); - } - else - DNAMP1::MaterialSet::Material::AddTexture(out, GX::TexGenSrc(uvSrc + 4), -1, texMapIdx++); - } + out << "rflv_tex_node = texture_nodes[-1]\n"; + return; + } - /* Special case for RFLV (environment UV mask) */ - if (Subtype(subtype.toUint32()) == Subtype::RFLV) - { - if (txtrId) - out << "rflv_tex_node = texture_nodes[-1]\n"; - return; + /* Add PASS node */ + bool linkRAS = false; + out << "prev_pnode = pnode\n" + "pnode = new_nodetree.nodes.new('ShaderNodeGroup')\n"; + switch (Subtype(subtype.toUint32())) { + case Subtype::DIFF: { + out << "pnode.node_tree = bpy.data.node_groups['RetroPassDIFF']\n"; + if (txtrId) { + out << "new_material.hecl_lightmap = texture.name\n" + << "texture.image.use_fake_user = True\n"; } + linkRAS = true; + break; + } + case Subtype::RIML: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassRIML']\n"; + if (idx == 0) + linkRAS = true; + break; + case Subtype::BLOL: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOL']\n"; + if (idx == 0) + linkRAS = true; + break; + case Subtype::BLOD: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOD']\n"; + if (idx == 0) + linkRAS = true; + break; + case Subtype::CLR: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassCLR']\n"; + if (idx == 0) + linkRAS = true; + break; + case Subtype::TRAN: + if (flags.TRANInvert()) + out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRANInv']\n"; + else + out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRAN']\n"; + break; + case Subtype::INCA: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassINCA']\n"; + break; + case Subtype::RFLV: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLV']\n"; + break; + case Subtype::RFLD: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLD']\n" + "if rflv_tex_node:\n" + " new_nodetree.links.new(rflv_tex_node.outputs['Color'], pnode.inputs['Mask Color'])\n" + " new_nodetree.links.new(rflv_tex_node.outputs['Value'], pnode.inputs['Mask Alpha'])\n"; + break; + case Subtype::LRLD: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassLRLD']\n"; + break; + case Subtype::LURD: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassLURD']\n"; + break; + case Subtype::BLOI: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOI']\n"; + break; + case Subtype::XRAY: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassXRAY']\n"; + break; + case Subtype::TOON: + out << "pnode.node_tree = bpy.data.node_groups['RetroPassTOON']\n"; + break; + default: + break; + } + out << "gridder.place_node(pnode, 2)\n"; - /* Add PASS node */ - bool linkRAS = false; - out << "prev_pnode = pnode\n" - "pnode = new_nodetree.nodes.new('ShaderNodeGroup')\n"; - switch (Subtype(subtype.toUint32())) - { - case Subtype::DIFF: - { - out << "pnode.node_tree = bpy.data.node_groups['RetroPassDIFF']\n"; - if (txtrId) - { - out << "new_material.hecl_lightmap = texture.name\n" - << "texture.image.use_fake_user = True\n"; - } - linkRAS = true; - break; - } - case Subtype::RIML: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassRIML']\n"; - if (idx == 0) - linkRAS = true; - break; - case Subtype::BLOL: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOL']\n"; - if (idx == 0) - linkRAS = true; - break; - case Subtype::BLOD: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOD']\n"; - if (idx == 0) - linkRAS = true; - break; - case Subtype::CLR: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassCLR']\n"; - if (idx == 0) - linkRAS = true; - break; - case Subtype::TRAN: - if (flags.TRANInvert()) - out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRANInv']\n"; - else - out << "pnode.node_tree = bpy.data.node_groups['RetroPassTRAN']\n"; - break; - case Subtype::INCA: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassINCA']\n"; - break; - case Subtype::RFLV: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLV']\n"; - break; - case Subtype::RFLD: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassRFLD']\n" - "if rflv_tex_node:\n" - " new_nodetree.links.new(rflv_tex_node.outputs['Color'], pnode.inputs['Mask Color'])\n" - " new_nodetree.links.new(rflv_tex_node.outputs['Value'], pnode.inputs['Mask Alpha'])\n"; - break; - case Subtype::LRLD: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassLRLD']\n"; - break; - case Subtype::LURD: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassLURD']\n"; - break; - case Subtype::BLOI: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassBLOI']\n"; - break; - case Subtype::XRAY: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassXRAY']\n"; - break; - case Subtype::TOON: - out << "pnode.node_tree = bpy.data.node_groups['RetroPassTOON']\n"; - break; - default: break; - } - out << "gridder.place_node(pnode, 2)\n"; + if (txtrId) { + out << "new_nodetree.links.new(texture_nodes[-1].outputs['Color'], pnode.inputs['Tex Color'])\n" + "new_nodetree.links.new(texture_nodes[-1].outputs['Value'], pnode.inputs['Tex Alpha'])\n"; + } - if (txtrId) - { - out << "new_nodetree.links.new(texture_nodes[-1].outputs['Color'], pnode.inputs['Tex Color'])\n" - "new_nodetree.links.new(texture_nodes[-1].outputs['Value'], pnode.inputs['Tex Alpha'])\n"; - } + if (linkRAS) + out << "new_nodetree.links.new(material_node.outputs['Color'], pnode.inputs['Prev Color'])\n" + "new_nodetree.links.new(material_node.outputs['Alpha'], pnode.inputs['Prev Alpha'])\n"; + else if (prevSection) { + if (prevSection->m_type == ISection::Type::PASS && + Subtype(static_cast(prevSection)->subtype.toUint32()) != Subtype::RFLV) + out << "new_nodetree.links.new(prev_pnode.outputs['Next Color'], pnode.inputs['Prev Color'])\n" + "new_nodetree.links.new(prev_pnode.outputs['Next Alpha'], pnode.inputs['Prev Alpha'])\n"; + else if (prevSection->m_type == ISection::Type::CLR) + out << "new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], pnode.inputs['Prev Color'])\n" + "new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], pnode.inputs['Prev Alpha'])\n"; + } - if (linkRAS) - out << "new_nodetree.links.new(material_node.outputs['Color'], pnode.inputs['Prev Color'])\n" - "new_nodetree.links.new(material_node.outputs['Alpha'], pnode.inputs['Prev Alpha'])\n"; - else if (prevSection) - { - if (prevSection->m_type == ISection::Type::PASS && - Subtype(static_cast(prevSection)->subtype.toUint32()) != Subtype::RFLV) - out << "new_nodetree.links.new(prev_pnode.outputs['Next Color'], pnode.inputs['Prev Color'])\n" - "new_nodetree.links.new(prev_pnode.outputs['Next Alpha'], pnode.inputs['Prev Alpha'])\n"; - else if (prevSection->m_type == ISection::Type::CLR) - out << "new_nodetree.links.new(kcolor_nodes[-1][0].outputs[0], pnode.inputs['Prev Color'])\n" - "new_nodetree.links.new(kcolor_nodes[-1][1].outputs[0], pnode.inputs['Prev Alpha'])\n"; - } - - /* Row Break in gridder */ - out << "gridder.row_break(2)\n"; + /* Row Break in gridder */ + out << "gridder.row_break(2)\n"; } -void Material::SectionCLR::constructNode(hecl::blender::PyOutStream& out, - const PAKRouter& pakRouter, - const PAK::Entry& entry, - const Material::ISection* prevSection, - unsigned idx, - unsigned& texMapIdx, - unsigned& texMtxIdx, - unsigned& kColorIdx) const -{ - DNAMP1::MaterialSet::Material::AddKcolor(out, color, kColorIdx++); - switch (Subtype(subtype.toUint32())) - { - case Subtype::DIFB: - out << "kc_node.label += ' DIFB'\n" - "ka_node.label += ' DIFB'\n"; - break; - default: break; - } +void Material::SectionCLR::constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, + const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, + unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const { + DNAMP1::MaterialSet::Material::AddKcolor(out, color, kColorIdx++); + switch (Subtype(subtype.toUint32())) { + case Subtype::DIFB: + out << "kc_node.label += ' DIFB'\n" + "ka_node.label += ' DIFB'\n"; + break; + default: + break; + } } -void Material::SectionINT::constructNode(hecl::blender::PyOutStream& out, - const PAKRouter& pakRouter, - const PAK::Entry& entry, - const Material::ISection* prevSection, - unsigned idx, - unsigned& texMapIdx, - unsigned& texMtxIdx, - unsigned& kColorIdx) const -{ - switch (Subtype(subtype.toUint32())) - { - case Subtype::OPAC: - { - GX::Color clr(value); - out.format("anode = new_nodetree.nodes.new('ShaderNodeValue')\n" - "anode.outputs['Value'].default_value = %f\n", - float(clr[3]) / float(0xff)); - out << "gridder.place_node(anode, 1)\n"; - } - break; - case Subtype::BLOD: - out.format("new_material.retro_blod = %d\n", value); - break; - case Subtype::BLOI: - out.format("new_material.retro_bloi = %d\n", value); - break; - case Subtype::BNIF: - out.format("new_material.retro_bnif = %d\n", value); - break; - case Subtype::XRBR: - out.format("new_material.retro_xrbr = %d\n", value); - break; - default: break; - } +void Material::SectionINT::constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, + const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, + unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const { + switch (Subtype(subtype.toUint32())) { + case Subtype::OPAC: { + GX::Color clr(value); + out.format( + "anode = new_nodetree.nodes.new('ShaderNodeValue')\n" + "anode.outputs['Value'].default_value = %f\n", + float(clr[3]) / float(0xff)); + out << "gridder.place_node(anode, 1)\n"; + } break; + case Subtype::BLOD: + out.format("new_material.retro_blod = %d\n", value); + break; + case Subtype::BLOI: + out.format("new_material.retro_bloi = %d\n", value); + break; + case Subtype::BNIF: + out.format("new_material.retro_bnif = %d\n", value); + break; + case Subtype::XRBR: + out.format("new_material.retro_xrbr = %d\n", value); + break; + default: + break; + } } -} +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CMDLMaterials.hpp b/DataSpec/DNAMP3/CMDLMaterials.hpp index dd8ff4107..2e4f8a4d2 100644 --- a/DataSpec/DNAMP3/CMDLMaterials.hpp +++ b/DataSpec/DNAMP3/CMDLMaterials.hpp @@ -5,202 +5,171 @@ #include "../DNAMP1/CMDLMaterials.hpp" #include "DNAMP3.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct MaterialSet : BigDNA -{ - static constexpr bool OneSection() {return true;} +struct MaterialSet : BigDNA { + static constexpr bool OneSection() { return true; } - AT_DECL_DNA - Value materialCount; + AT_DECL_DNA + Value materialCount; - /* Dummy methods from MP1/2 */ - void addTexture(const UniqueID32&) {} - void addMaterialEndOff(atUint32) {++materialCount;} + /* Dummy methods from MP1/2 */ + void addTexture(const UniqueID32&) {} + void addMaterialEndOff(atUint32) { ++materialCount; } - struct Material : BigDNA - { - AT_DECL_EXPLICIT_DNA - using VAFlags = DNAMP1::MaterialSet::Material::VAFlags; - struct Header : BigDNA - { - AT_DECL_DNA - Value size; - struct Flags : BigDNA - { - AT_DECL_DNA - Value flags; - bool alphaBlending() const {return (flags & 0x8) != 0;} - void setAlphaBlending(bool enabled) {flags &= ~0x8; flags |= atUint32(enabled) << 3;} - bool alphaTest() const {return (flags & 0x10) != 0;} - void setPunchthroughAlpha(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;} - bool additiveBlending() const {return (flags & 0x20) != 0;} - void setAdditiveBlending(bool enabled) {flags &= ~0x20; flags |= atUint32(enabled) << 5;} - bool shadowOccluderMesh() const {return (flags & 0x100) != 0;} - void setShadowOccluderMesh(bool enabled) {flags &= ~0x100; flags |= atUint32(enabled) << 8;} - bool lightmapUVArray() const {return false;} /* For polymorphic compatibility with MP1/2 */ - } flags; - Value uniqueIdx; - Value unk1; - VAFlags vaFlags; - Value unk2; - Value unk3; - Value unk4; - } header; - const Header::Flags& getFlags() const {return header.flags;} - const VAFlags& getVAFlags() const {return header.vaFlags;} + struct Material : BigDNA { + AT_DECL_EXPLICIT_DNA + using VAFlags = DNAMP1::MaterialSet::Material::VAFlags; + struct Header : BigDNA { + AT_DECL_DNA + Value size; + struct Flags : BigDNA { + AT_DECL_DNA + Value flags; + bool alphaBlending() const { return (flags & 0x8) != 0; } + void setAlphaBlending(bool enabled) { + flags &= ~0x8; + flags |= atUint32(enabled) << 3; + } + bool alphaTest() const { return (flags & 0x10) != 0; } + void setPunchthroughAlpha(bool enabled) { + flags &= ~0x10; + flags |= atUint32(enabled) << 4; + } + bool additiveBlending() const { return (flags & 0x20) != 0; } + void setAdditiveBlending(bool enabled) { + flags &= ~0x20; + flags |= atUint32(enabled) << 5; + } + bool shadowOccluderMesh() const { return (flags & 0x100) != 0; } + void setShadowOccluderMesh(bool enabled) { + flags &= ~0x100; + flags |= atUint32(enabled) << 8; + } + bool lightmapUVArray() const { return false; } /* For polymorphic compatibility with MP1/2 */ + } flags; + Value uniqueIdx; + Value unk1; + VAFlags vaFlags; + Value unk2; + Value unk3; + Value unk4; + } header; + const Header::Flags& getFlags() const { return header.flags; } + const VAFlags& getVAFlags() const { return header.vaFlags; } - struct ISection : BigDNAV - { - Delete expl; - enum class Type : atUint32 - { - PASS = SBIG('PASS'), - CLR = SBIG('CLR '), - INT = SBIG('INT ') - } m_type; - ISection(Type type) : m_type(type) {} - virtual void constructNode(hecl::blender::PyOutStream& out, - const PAKRouter& pakRouter, - const PAK::Entry& entry, - const Material::ISection* prevSection, - unsigned idx, - unsigned& texMapIdx, - unsigned& texMtxIdx, - unsigned& kColorIdx) const=0; - }; - struct SectionPASS : ISection - { - SectionPASS() : ISection(ISection::Type::PASS) {} - static SectionPASS* castTo(ISection* sec) - { return sec->m_type == Type::PASS ? static_cast(sec) : nullptr; } - AT_DECL_DNA - AT_DECL_DNAV - Value size; - enum class Subtype : atUint32 - { - DIFF = SBIG('DIFF'), - RIML = SBIG('RIML'), - BLOL = SBIG('BLOL'), - BLOD = SBIG('BLOD'), - CLR = SBIG('CLR '), - TRAN = SBIG('TRAN'), - INCA = SBIG('INCA'), - RFLV = SBIG('RFLV'), - RFLD = SBIG('RFLD'), - LRLD = SBIG('LRLD'), - LURD = SBIG('LURD'), - BLOI = SBIG('BLOI'), - XRAY = SBIG('XRAY'), - TOON = SBIG('TOON') - }; - DNAFourCC subtype; - struct Flags : BigDNA - { - AT_DECL_DNA - Value flags; - bool TRANInvert() const {return (flags & 0x10) != 0;} - void setTRANInvert(bool enabled) {flags &= ~0x10; flags |= atUint32(enabled) << 4;} - } flags; - UniqueID64 txtrId; - Value uvSrc; - Value uvAnimSize; - struct UVAnimation : BigDNA - { - AT_DECL_DNA - Value unk1; - Value unk2; - DNAMP1::MaterialSet::Material::UVAnimation anim; - }; - Vector uvAnim; - - void constructNode(hecl::blender::PyOutStream& out, - const PAKRouter& pakRouter, - const PAK::Entry& entry, - const Material::ISection* prevSection, - unsigned idx, - unsigned& texMapIdx, - unsigned& texMtxIdx, - unsigned& kColorIdx) const; - }; - struct SectionCLR : ISection - { - SectionCLR() : ISection(ISection::Type::CLR) {} - static SectionCLR* castTo(ISection* sec) - { return sec->m_type == Type::CLR ? static_cast(sec) : nullptr; } - AT_DECL_DNA - AT_DECL_DNAV - enum class Subtype : atUint32 - { - CLR = SBIG('CLR '), - DIFB = SBIG('DIFB') - }; - DNAFourCC subtype; - GX::Color color; - - void constructNode(hecl::blender::PyOutStream& out, - const PAKRouter& pakRouter, - const PAK::Entry& entry, - const Material::ISection* prevSection, - unsigned idx, - unsigned& texMapIdx, - unsigned& texMtxIdx, - unsigned& kColorIdx) const; - }; - struct SectionINT : ISection - { - SectionINT() : ISection(ISection::Type::INT) {} - static SectionINT* castTo(ISection* sec) - { return sec->m_type == Type::INT ? static_cast(sec) : nullptr; } - AT_DECL_DNA - AT_DECL_DNAV - enum class Subtype : atUint32 - { - OPAC = SBIG('OPAC'), - BLOD = SBIG('BLOD'), - BLOI = SBIG('BLOI'), - BNIF = SBIG('BNIF'), - XRBR = SBIG('XRBR') - }; - DNAFourCC subtype; - Value value; - - void constructNode(hecl::blender::PyOutStream& out, - const PAKRouter& pakRouter, - const PAK::Entry& entry, - const Material::ISection* prevSection, - unsigned idx, - unsigned& texMapIdx, - unsigned& texMtxIdx, - unsigned& kColorIdx) const; - }; - struct SectionFactory : BigDNA - { - AT_DECL_EXPLICIT_DNA - std::unique_ptr section; - }; - std::vector sections; + struct ISection : BigDNAV { + Delete expl; + enum class Type : atUint32 { PASS = SBIG('PASS'), CLR = SBIG('CLR '), INT = SBIG('INT ') } m_type; + ISection(Type type) : m_type(type) {} + virtual void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, + const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, + unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const = 0; }; - Vector materials; + struct SectionPASS : ISection { + SectionPASS() : ISection(ISection::Type::PASS) {} + static SectionPASS* castTo(ISection* sec) { + return sec->m_type == Type::PASS ? static_cast(sec) : nullptr; + } + AT_DECL_DNA + AT_DECL_DNAV + Value size; + enum class Subtype : atUint32 { + DIFF = SBIG('DIFF'), + RIML = SBIG('RIML'), + BLOL = SBIG('BLOL'), + BLOD = SBIG('BLOD'), + CLR = SBIG('CLR '), + TRAN = SBIG('TRAN'), + INCA = SBIG('INCA'), + RFLV = SBIG('RFLV'), + RFLD = SBIG('RFLD'), + LRLD = SBIG('LRLD'), + LURD = SBIG('LURD'), + BLOI = SBIG('BLOI'), + XRAY = SBIG('XRAY'), + TOON = SBIG('TOON') + }; + DNAFourCC subtype; + struct Flags : BigDNA { + AT_DECL_DNA + Value flags; + bool TRANInvert() const { return (flags & 0x10) != 0; } + void setTRANInvert(bool enabled) { + flags &= ~0x10; + flags |= atUint32(enabled) << 4; + } + } flags; + UniqueID64 txtrId; + Value uvSrc; + Value uvAnimSize; + struct UVAnimation : BigDNA { + AT_DECL_DNA + Value unk1; + Value unk2; + DNAMP1::MaterialSet::Material::UVAnimation anim; + }; + Vector uvAnim; - static void RegisterMaterialProps(hecl::blender::PyOutStream& out); - static void ConstructMaterial(hecl::blender::PyOutStream& out, - const PAKRouter& pakRouter, - const PAK::Entry& entry, - const MaterialSet::Material& material, - unsigned groupIdx, unsigned matIdx); + void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, + const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, + unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const; + }; + struct SectionCLR : ISection { + SectionCLR() : ISection(ISection::Type::CLR) {} + static SectionCLR* castTo(ISection* sec) { + return sec->m_type == Type::CLR ? static_cast(sec) : nullptr; + } + AT_DECL_DNA + AT_DECL_DNAV + enum class Subtype : atUint32 { CLR = SBIG('CLR '), DIFB = SBIG('DIFB') }; + DNAFourCC subtype; + GX::Color color; - void readToBlender(hecl::blender::PyOutStream& os, - const PAKRouter& pakRouter, - const PAKRouter::EntryType& entry, - unsigned setIdx) - { - DNACMDL::ReadMaterialSetToBlender_3(os, *this, pakRouter, entry, setIdx); - } + void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, + const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, + unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const; + }; + struct SectionINT : ISection { + SectionINT() : ISection(ISection::Type::INT) {} + static SectionINT* castTo(ISection* sec) { + return sec->m_type == Type::INT ? static_cast(sec) : nullptr; + } + AT_DECL_DNA + AT_DECL_DNAV + enum class Subtype : atUint32 { + OPAC = SBIG('OPAC'), + BLOD = SBIG('BLOD'), + BLOI = SBIG('BLOI'), + BNIF = SBIG('BNIF'), + XRBR = SBIG('XRBR') + }; + DNAFourCC subtype; + Value value; - void ensureTexturesExtracted(PAKRouter& pakRouter) const {} + void constructNode(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, + const PAK::Entry& entry, const Material::ISection* prevSection, unsigned idx, + unsigned& texMapIdx, unsigned& texMtxIdx, unsigned& kColorIdx) const; + }; + struct SectionFactory : BigDNA { + AT_DECL_EXPLICIT_DNA + std::unique_ptr section; + }; + std::vector sections; + }; + Vector materials; + + static void RegisterMaterialProps(hecl::blender::PyOutStream& out); + static void ConstructMaterial(hecl::blender::PyOutStream& out, const PAKRouter& pakRouter, + const PAK::Entry& entry, const MaterialSet::Material& material, unsigned groupIdx, + unsigned matIdx); + + void readToBlender(hecl::blender::PyOutStream& os, const PAKRouter& pakRouter, + const PAKRouter::EntryType& entry, unsigned setIdx) { + DNACMDL::ReadMaterialSetToBlender_3(os, *this, pakRouter, entry, setIdx); + } + + void ensureTexturesExtracted(PAKRouter& pakRouter) const {} }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CSKR.cpp b/DataSpec/DNAMP3/CSKR.cpp index cff8c2928..b6df74644 100644 --- a/DataSpec/DNAMP3/CSKR.cpp +++ b/DataSpec/DNAMP3/CSKR.cpp @@ -1,19 +1,14 @@ #include "CSKR.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec::DNAMP3 -{ - -void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atInt16 skinIdx) const -{ - if (skinIdx < 0) - return; - const DNAMP2::CSKR::SkinningRule& rule = data.skinningRules[skinIdx]; - for (const DNAMP2::CSKR::SkinningRule::Weight& weight : rule.weights) - os.format("vert[dvert_lay][%u] = %f\n", - cinf.getBoneIdxFromId(weight.boneId), - weight.weight); -} +namespace DataSpec::DNAMP3 { +void CSKR::weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atInt16 skinIdx) const { + if (skinIdx < 0) + return; + const DNAMP2::CSKR::SkinningRule& rule = data.skinningRules[skinIdx]; + for (const DNAMP2::CSKR::SkinningRule::Weight& weight : rule.weights) + os.format("vert[dvert_lay][%u] = %f\n", cinf.getBoneIdxFromId(weight.boneId), weight.weight); } +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/CSKR.hpp b/DataSpec/DNAMP3/CSKR.hpp index 03d392efa..2de889e0c 100644 --- a/DataSpec/DNAMP3/CSKR.hpp +++ b/DataSpec/DNAMP3/CSKR.hpp @@ -4,41 +4,34 @@ #include "CINF.hpp" #include "../DNAMP2/CSKR.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct CSKR : BigDNA -{ +struct CSKR : BigDNA { + AT_DECL_DNA + DNAFourCC magic; + Value version; + DNAMP2::CSKR data; + Value matrixCount; + struct MatrixBindings : BigDNA { AT_DECL_DNA - DNAFourCC magic; - Value version; - DNAMP2::CSKR data; - Value matrixCount; - struct MatrixBindings : BigDNA - { - AT_DECL_DNA - Value mtxs[10]; - }; - Vector mtxBindings; + Value mtxs[10]; + }; + Vector mtxBindings; - Value unkCount1; - Vector unk1; - Value unkCount2; - Vector unk2; - Value unkCount3; - Vector unk3; - Value unkCount4; - Vector unk4; - Value unkCount5; - Vector unk5; + Value unkCount1; + Vector unk1; + Value unkCount2; + Vector unk2; + Value unkCount3; + Vector unk3; + Value unkCount4; + Vector unk4; + Value unkCount5; + Vector unk5; - const atInt16* getMatrixBank(size_t idx) const - { - return mtxBindings.at(idx).mtxs; - } + const atInt16* getMatrixBank(size_t idx) const { return mtxBindings.at(idx).mtxs; } - void weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atInt16 skinIdx) const; + void weightVertex(hecl::blender::PyOutStream& os, const CINF& cinf, atInt16 skinIdx) const; }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/DNAMP3.cpp b/DataSpec/DNAMP3/DNAMP3.cpp index 6084654aa..9145c0d07 100644 --- a/DataSpec/DNAMP3/DNAMP3.cpp +++ b/DataSpec/DNAMP3/DNAMP3.cpp @@ -17,281 +17,244 @@ #include "DataSpec/DNACommon/DGRP.hpp" #include "Runtime/GCNTypes.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { logvisor::Module Log("urde::DNAMP3"); -static bool GetNoShare(std::string_view name) -{ - std::string lowerName(name); - std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); - if (!lowerName.compare(0, 7, "metroid")) - return false; - return true; +static bool GetNoShare(std::string_view name) { + std::string lowerName(name); + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); + if (!lowerName.compare(0, 7, "metroid")) + return false; + return true; } -PAKBridge::PAKBridge(const nod::Node& node, - bool doExtract) -: m_node(node), m_pak(GetNoShare(node.getName())), m_doExtract(doExtract) -{ - nod::AthenaPartReadStream rs(node.beginReadStream()); - m_pak.read(rs); +PAKBridge::PAKBridge(const nod::Node& node, bool doExtract) +: m_node(node), m_pak(GetNoShare(node.getName())), m_doExtract(doExtract) { + nod::AthenaPartReadStream rs(node.beginReadStream()); + m_pak.read(rs); - /* Append Level String */ - std::set uniq; - for (auto& ent : m_pak.m_entries) - { - PAK::Entry& entry = ent.second; - if (entry.type == FOURCC('MLVL')) - { - PAKEntryReadStream rs = entry.beginReadStream(m_node); - MLVL mlvl; - mlvl.read(rs); - const PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId); - if (nameEnt) - { - PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); - STRG mlvlName; - mlvlName.read(rs); - uniq.insert(mlvlName.getSystemString(FOURCC('ENGL'), 0)); - } + /* Append Level String */ + std::set uniq; + for (auto& ent : m_pak.m_entries) { + PAK::Entry& entry = ent.second; + if (entry.type == FOURCC('MLVL')) { + PAKEntryReadStream rs = entry.beginReadStream(m_node); + MLVL mlvl; + mlvl.read(rs); + const PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId); + if (nameEnt) { + PAKEntryReadStream rs = nameEnt->beginReadStream(m_node); + STRG mlvlName; + mlvlName.read(rs); + uniq.insert(mlvlName.getSystemString(FOURCC('ENGL'), 0)); + } + } + } + bool comma = false; + for (const hecl::SystemString& str : uniq) { + if (comma) + m_levelString += _SYS_STR(", "); + comma = true; + m_levelString += str; + } +} + +static hecl::SystemString LayerName(std::string_view name) { + hecl::SystemString ret(hecl::SystemStringConv(name).sys_str()); + for (auto& ch : ret) + if (ch == _SYS_STR('/') || ch == _SYS_STR('\\')) + ch = _SYS_STR('-'); + return ret; +} + +void PAKBridge::build() { + /* First pass: build per-area/per-layer dependency map */ + for (const auto& ent : m_pak.m_entries) { + const PAK::Entry& entry = ent.second; + if (entry.type == FOURCC('MLVL')) { + Level& level = m_levelDeps[entry.id]; + + MLVL mlvl; + { + PAKEntryReadStream rs = entry.beginReadStream(m_node); + mlvl.read(rs); + } + bool named; + std::string bestName = m_pak.bestEntryName(m_node, entry, named); + level.name = hecl::SystemStringConv(bestName).sys_str(); + level.areas.reserve(mlvl.areaCount); + unsigned layerIdx = 0; + + /* Make MAPW available to lookup MAPAs */ + const PAK::Entry* worldMapEnt = m_pak.lookupEntry(mlvl.worldMap); + std::vector mapw; + if (worldMapEnt) { + PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node); + rs.seek(8, athena::Current); + atUint32 areaCount = rs.readUint32Big(); + mapw.reserve(areaCount); + for (atUint32 i = 0; i < areaCount; ++i) + mapw.emplace_back(rs); + } + + /* Index areas */ + unsigned ai = 0; + auto layerFlagsIt = mlvl.layerFlags.begin(); + for (const MLVL::Area& area : mlvl.areas) { + Level::Area& areaDeps = level.areas[area.areaMREAId]; + const PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId); + if (areaNameEnt) { + STRG areaName; + { + PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node); + areaName.read(rs); + } + areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0); + areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name); } - } - bool comma = false; - for (const hecl::SystemString& str : uniq) - { - if (comma) - m_levelString += _SYS_STR(", "); - comma = true; - m_levelString += str; - } -} - -static hecl::SystemString LayerName(std::string_view name) -{ - hecl::SystemString ret(hecl::SystemStringConv(name).sys_str()); - for (auto& ch : ret) - if (ch == _SYS_STR('/') || ch == _SYS_STR('\\')) - ch = _SYS_STR('-'); - return ret; -} - -void PAKBridge::build() -{ - /* First pass: build per-area/per-layer dependency map */ - for (const auto& ent : m_pak.m_entries) - { - const PAK::Entry& entry = ent.second; - if (entry.type == FOURCC('MLVL')) - { - Level& level = m_levelDeps[entry.id]; - - MLVL mlvl; - { - PAKEntryReadStream rs = entry.beginReadStream(m_node); - mlvl.read(rs); - } - bool named; - std::string bestName = m_pak.bestEntryName(m_node, entry, named); - level.name = hecl::SystemStringConv(bestName).sys_str(); - level.areas.reserve(mlvl.areaCount); - unsigned layerIdx = 0; - - /* Make MAPW available to lookup MAPAs */ - const PAK::Entry* worldMapEnt = m_pak.lookupEntry(mlvl.worldMap); - std::vector mapw; - if (worldMapEnt) - { - PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node); - rs.seek(8, athena::Current); - atUint32 areaCount = rs.readUint32Big(); - mapw.reserve(areaCount); - for (atUint32 i=0 ; ibeginReadStream(m_node); - areaName.read(rs); - } - areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0); - areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name); - } - if (areaDeps.name.empty()) - { - areaDeps.name = hecl::SystemStringConv(area.internalAreaName).sys_str(); - if (areaDeps.name.empty()) - { - std::string idStr = area.areaMREAId.toString(); - areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); - } - } - hecl::SystemChar num[16]; - hecl::SNPrintf(num, 16, _SYS_STR("%02u "), ai); - areaDeps.name = num + areaDeps.name; - - const MLVL::LayerFlags& layerFlags = *layerFlagsIt++; - if (layerFlags.layerCount) - { - areaDeps.layers.reserve(layerFlags.layerCount); - for (unsigned l=1 ; l> (l-1) & 0x1; - layer.name = hecl::StringUtils::TrimWhitespace(layer.name); - hecl::SNPrintf(num, 16, _SYS_STR("%02u "), l-1); - layer.name = num + layer.name; - } - } - - /* Load area DEPS */ - const PAK::Entry* areaEntry = m_pak.lookupEntry(area.areaMREAId); - if (areaEntry) - { - PAKEntryReadStream ars = areaEntry->beginReadStream(m_node); - MREA::ExtractLayerDeps(ars, areaDeps); - } - areaDeps.resources.emplace(area.areaMREAId); - if (mapw.size() > ai) - areaDeps.resources.emplace(mapw[ai]); - ++ai; - } + if (areaDeps.name.empty()) { + areaDeps.name = hecl::SystemStringConv(area.internalAreaName).sys_str(); + if (areaDeps.name.empty()) { + std::string idStr = area.areaMREAId.toString(); + areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str(); + } } - } + hecl::SystemChar num[16]; + hecl::SNPrintf(num, 16, _SYS_STR("%02u "), ai); + areaDeps.name = num + areaDeps.name; - /* Second pass: cross-compare uniqueness */ - for (auto& entry : m_pak.m_entries) - { - entry.second.unique.checkEntry(*this, entry.second); + const MLVL::LayerFlags& layerFlags = *layerFlagsIt++; + if (layerFlags.layerCount) { + areaDeps.layers.reserve(layerFlags.layerCount); + for (unsigned l = 1; l < layerFlags.layerCount; ++l) { + areaDeps.layers.emplace_back(); + Level::Area::Layer& layer = areaDeps.layers.back(); + layer.name = LayerName(mlvl.layerNames[layerIdx++]); + layer.active = layerFlags.flags >> (l - 1) & 0x1; + layer.name = hecl::StringUtils::TrimWhitespace(layer.name); + hecl::SNPrintf(num, 16, _SYS_STR("%02u "), l - 1); + layer.name = num + layer.name; + } + } + + /* Load area DEPS */ + const PAK::Entry* areaEntry = m_pak.lookupEntry(area.areaMREAId); + if (areaEntry) { + PAKEntryReadStream ars = areaEntry->beginReadStream(m_node); + MREA::ExtractLayerDeps(ars, areaDeps); + } + areaDeps.resources.emplace(area.areaMREAId); + if (mapw.size() > ai) + areaDeps.resources.emplace(mapw[ai]); + ++ai; + } } + } + + /* Second pass: cross-compare uniqueness */ + for (auto& entry : m_pak.m_entries) { + entry.second.unique.checkEntry(*this, entry.second); + } } -void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const -{ - for (const std::pair& entry : m_pak.m_entries) - { - if (entry.second.type == FOURCC('CHAR')) - { - PAKEntryReadStream rs = entry.second.beginReadStream(m_node); - CHAR aChar; - aChar.read(rs); - const CHAR::CharacterInfo& ci = aChar.characterInfo; - charAssoc.m_cmdlRigs[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf); - charAssoc.m_cskrCinfToCharacter[ci.cskr] = - std::make_pair(entry.second.id, hecl::Format("%s.CSKR", ci.name.c_str())); - charAssoc.m_cskrCinfToCharacter[ci.cinf] = - std::make_pair(entry.second.id, hecl::Format("CINF_%" PRIX64 ".CINF", ci.cinf.toUint64())); - for (const CHAR::CharacterInfo::Overlay& overlay : ci.overlays) - { - charAssoc.m_cmdlRigs[overlay.cmdl] = std::make_pair(overlay.cskr, ci.cinf); - charAssoc.m_cskrCinfToCharacter[overlay.cskr] = std::make_pair(entry.second.id, - hecl::Format("%s.%.4s.CSKR", ci.name.c_str(), overlay.type.getChars())); - } - } +void PAKBridge::addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const { + for (const std::pair& entry : m_pak.m_entries) { + if (entry.second.type == FOURCC('CHAR')) { + PAKEntryReadStream rs = entry.second.beginReadStream(m_node); + CHAR aChar; + aChar.read(rs); + const CHAR::CharacterInfo& ci = aChar.characterInfo; + charAssoc.m_cmdlRigs[ci.cmdl] = std::make_pair(ci.cskr, ci.cinf); + charAssoc.m_cskrCinfToCharacter[ci.cskr] = + std::make_pair(entry.second.id, hecl::Format("%s.CSKR", ci.name.c_str())); + charAssoc.m_cskrCinfToCharacter[ci.cinf] = + std::make_pair(entry.second.id, hecl::Format("CINF_%" PRIX64 ".CINF", ci.cinf.toUint64())); + for (const CHAR::CharacterInfo::Overlay& overlay : ci.overlays) { + charAssoc.m_cmdlRigs[overlay.cmdl] = std::make_pair(overlay.cskr, ci.cinf); + charAssoc.m_cskrCinfToCharacter[overlay.cskr] = + std::make_pair(entry.second.id, hecl::Format("%s.%.4s.CSKR", ci.name.c_str(), overlay.type.getChars())); + } } + } } static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}}; void PAKBridge::addMAPATransforms(PAKRouter& pakRouter, - std::unordered_map& addTo, - std::unordered_map& pathOverrides) const -{ - for (const std::pair& entry : m_pak.m_entries) - { - if (entry.second.type == FOURCC('MLVL')) - { - MLVL mlvl; - { - PAKEntryReadStream rs = entry.second.beginReadStream(m_node); - mlvl.read(rs); - } - hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath(); + std::unordered_map& addTo, + std::unordered_map& pathOverrides) const { + for (const std::pair& entry : m_pak.m_entries) { + if (entry.second.type == FOURCC('MLVL')) { + MLVL mlvl; + { + PAKEntryReadStream rs = entry.second.beginReadStream(m_node); + mlvl.read(rs); + } + hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath(); - if (mlvl.worldNameId) - pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _SYS_STR("!name.yaml")); + if (mlvl.worldNameId) + pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath, _SYS_STR("!name.yaml")); - for (const MLVL::Area& area : mlvl.areas) - { - hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); - if (area.areaNameId) - pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _SYS_STR("!name.yaml")); - } + for (const MLVL::Area& area : mlvl.areas) { + hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath(); + if (area.areaNameId) + pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath, _SYS_STR("!name.yaml")); + } - if (mlvl.worldMap) - { - const nod::Node* mapNode; - const PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode); - if (mapEntry) - { - PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode); - u32 magic = rs.readUint32Big(); - if (magic == 0xDEADF00D) - { - rs.readUint32Big(); - u32 count = rs.readUint32Big(); - for (u32 i=0 ; ibeginReadStream(*mapNode); + u32 magic = rs.readUint32Big(); + if (magic == 0xDEADF00D) { + rs.readUint32Big(); + u32 count = rs.readUint32Big(); + for (u32 i = 0; i < count && i < mlvl.areas.size(); ++i) { + MLVL::Area& areaData = mlvl.areas[i]; + UniqueID64 mapaId; + mapaId.read(rs); + addTo[mapaId] = zeus::CMatrix4f(areaData.transformMtx[0], areaData.transformMtx[1], + areaData.transformMtx[2], BottomRow) + .transposed(); } + } } + } } + } } -ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry) -{ - switch (entry.type) - { -// case SBIG('CAUD'): -// return {CAUD::Extract, {_SYS_STR(".yaml")}}; - case SBIG('STRG'): - return {STRG::Extract, {_SYS_STR(".yaml")}}; - case SBIG('TXTR'): - return {TXTR::Extract, {_SYS_STR(".png")}}; - case SBIG('SAVW'): - return {SAVWCommon::ExtractSAVW, {_SYS_STR(".yaml")}}; - case SBIG('HINT'): - return {HINT::Extract, {_SYS_STR(".yaml")}}; - case SBIG('CMDL'): - return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; - case SBIG('CHAR'): - return {CHAR::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; - case SBIG('MLVL'): - return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3}; - case SBIG('MREA'): - return {MREA::Extract, {_SYS_STR(".blend")}, 4}; - case SBIG('MAPA'): - return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; - case SBIG('FSM2'): - return {DNAFSM2::ExtractFSM2, {_SYS_STR(".yaml")}}; - case SBIG('FONT'): - return {DNAFont::ExtractFONT, {_SYS_STR(".yaml")}}; - case SBIG('DGRP'): - return {DNADGRP::ExtractDGRP, {_SYS_STR(".yaml")}}; - } - return {}; +ResExtractor PAKBridge::LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry) { + switch (entry.type) { + // case SBIG('CAUD'): + // return {CAUD::Extract, {_SYS_STR(".yaml")}}; + case SBIG('STRG'): + return {STRG::Extract, {_SYS_STR(".yaml")}}; + case SBIG('TXTR'): + return {TXTR::Extract, {_SYS_STR(".png")}}; + case SBIG('SAVW'): + return {SAVWCommon::ExtractSAVW, {_SYS_STR(".yaml")}}; + case SBIG('HINT'): + return {HINT::Extract, {_SYS_STR(".yaml")}}; + case SBIG('CMDL'): + return {CMDL::Extract, {_SYS_STR(".blend")}, 1}; + case SBIG('CHAR'): + return {CHAR::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2}; + case SBIG('MLVL'): + return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3}; + case SBIG('MREA'): + return {MREA::Extract, {_SYS_STR(".blend")}, 4}; + case SBIG('MAPA'): + return {MAPA::Extract, {_SYS_STR(".blend")}, 4}; + case SBIG('FSM2'): + return {DNAFSM2::ExtractFSM2, {_SYS_STR(".yaml")}}; + case SBIG('FONT'): + return {DNAFont::ExtractFONT, {_SYS_STR(".yaml")}}; + case SBIG('DGRP'): + return {DNADGRP::ExtractDGRP, {_SYS_STR(".yaml")}}; + } + return {}; } -} +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/DNAMP3.hpp b/DataSpec/DNAMP3/DNAMP3.hpp index 5f0c5ef4e..3e7d05c6f 100644 --- a/DataSpec/DNAMP3/DNAMP3.hpp +++ b/DataSpec/DNAMP3/DNAMP3.hpp @@ -3,38 +3,35 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "PAK.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { extern logvisor::Module Log; /* MP3-specific, one-shot PAK traversal/extraction class */ -class PAKBridge -{ - const nod::Node& m_node; - PAK m_pak; +class PAKBridge { + const nod::Node& m_node; + PAK m_pak; + public: - bool m_doExtract; - using Level = DataSpec::Level; - std::unordered_map m_levelDeps; - hecl::SystemString m_levelString; + bool m_doExtract; + using Level = DataSpec::Level; + std::unordered_map m_levelDeps; + hecl::SystemString m_levelString; - PAKBridge(const nod::Node& node, bool doExtract=true); - void build(); - static ResExtractor LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry); - std::string_view getName() const {return m_node.getName();} - hecl::SystemStringView getLevelString() const {return m_levelString;} + PAKBridge(const nod::Node& node, bool doExtract = true); + void build(); + static ResExtractor LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry); + std::string_view getName() const { return m_node.getName(); } + hecl::SystemStringView getLevelString() const { return m_levelString; } - using PAKType = PAK; - const PAKType& getPAK() const {return m_pak;} - const nod::Node& getNode() const {return m_node;} + using PAKType = PAK; + const PAKType& getPAK() const { return m_pak; } + const nod::Node& getNode() const { return m_node; } - void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; + void addCMDLRigPairs(PAKRouter& pakRouter, CharacterAssociations& charAssoc) const; - void addMAPATransforms(PAKRouter& pakRouter, - std::unordered_map& addTo, - std::unordered_map& pathOverrides) const; + void addMAPATransforms(PAKRouter& pakRouter, std::unordered_map& addTo, + std::unordered_map& pathOverrides) const; }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/HINT.hpp b/DataSpec/DNAMP3/HINT.hpp index 7f3f1336a..7885f9f00 100644 --- a/DataSpec/DNAMP3/HINT.hpp +++ b/DataSpec/DNAMP3/HINT.hpp @@ -3,45 +3,40 @@ #include "DataSpec/DNACommon/DNACommon.hpp" #include "PAK.hpp" -namespace DataSpec::DNAMP3 -{ -struct HINT : BigDNA -{ +namespace DataSpec::DNAMP3 { +struct HINT : BigDNA { + AT_DECL_DNA_YAML + Value magic; + Value version; + + struct Hint : BigDNA { AT_DECL_DNA_YAML - Value magic; - Value version; - - struct Hint : BigDNA - { - AT_DECL_DNA_YAML - String<-1> name; - Value unknown1; - Value fadeInTime; - UniqueID64 stringID; - Value unknown2; - struct Location : BigDNA - { - AT_DECL_DNA_YAML - UniqueID64 worldAssetID; - UniqueID64 areaAssetID; - Value areaID; - UniqueID64 stringID; - Value unknown[3]; - }; - - Value locationCount; - Vector locations; + String<-1> name; + Value unknown1; + Value fadeInTime; + UniqueID64 stringID; + Value unknown2; + struct Location : BigDNA { + AT_DECL_DNA_YAML + UniqueID64 worldAssetID; + UniqueID64 areaAssetID; + Value areaID; + UniqueID64 stringID; + Value unknown[3]; }; - Value hintCount; - Vector hints; - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) - { - HINT hint; - hint.read(rs); - athena::io::FileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(hint, writer); - return true; - } + Value locationCount; + Vector locations; + }; + Value hintCount; + Vector hints; + + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + HINT hint; + hint.read(rs); + athena::io::FileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(hint, writer); + return true; + } }; -} +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/MAPA.hpp b/DataSpec/DNAMP3/MAPA.hpp index 6b5e4a7cc..b0794b42e 100644 --- a/DataSpec/DNAMP3/MAPA.hpp +++ b/DataSpec/DNAMP3/MAPA.hpp @@ -4,34 +4,24 @@ #include "DataSpec/DNACommon/MAPA.hpp" #include "DNAMP3.hpp" -namespace DataSpec::DNAMP3 -{ -struct MAPA : DNAMAPA::MAPA -{ - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) - { - MAPA mapa; - mapa.read(rs); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - return DNAMAPA::ReadMAPAToBlender(conn, mapa, outPath, pakRouter, entry, force); - } +namespace DataSpec::DNAMP3 { +struct MAPA : DNAMAPA::MAPA { + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + MAPA mapa; + mapa.read(rs); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + return DNAMAPA::ReadMAPAToBlender(conn, mapa, outPath, pakRouter, entry, force); + } - static bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out) - { - return DNAMAPA::Cook(mapa, out); - } + static bool Cook(const hecl::blender::MapArea& mapa, const hecl::ProjectPath& out) { + return DNAMAPA::Cook(mapa, out); + } - static uint32_t Version() { return 5; } - using Header = DNAMAPA::MAPA::HeaderMP3; - using MappableObject = DNAMAPA::MAPA::MappableObjectMP3; + static uint32_t Version() { return 5; } + using Header = DNAMAPA::MAPA::HeaderMP3; + using MappableObject = DNAMAPA::MAPA::MappableObjectMP3; }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/MLVL.hpp b/DataSpec/DNAMP3/MLVL.hpp index 5c6bc54e9..c48cca2d1 100644 --- a/DataSpec/DNAMP3/MLVL.hpp +++ b/DataSpec/DNAMP3/MLVL.hpp @@ -4,100 +4,84 @@ #include "DataSpec/DNACommon/MLVL.hpp" #include "DNAMP3.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct MLVL : BigDNA -{ +struct MLVL : BigDNA { + AT_DECL_DNA_YAML + Value magic; + Value version; + UniqueID64 worldNameId; + Value unk; + UniqueID64 saveWorldId; + UniqueID64 worldSkyboxId; + + Value areaCount; + struct Area : BigDNA { AT_DECL_DNA_YAML - Value magic; - Value version; - UniqueID64 worldNameId; - Value unk; - UniqueID64 saveWorldId; - UniqueID64 worldSkyboxId; + UniqueID64 areaNameId; + Value transformMtx[3]; + Value aabb[2]; + UniqueID64 areaMREAId; + Value areaId; - Value areaCount; - struct Area : BigDNA - { + Value attachedAreaCount; + Vector attachedAreas; + + Value dockCount; + struct Dock : BigDNA { + AT_DECL_DNA_YAML + Value endpointCount; + struct Endpoint : BigDNA { AT_DECL_DNA_YAML - UniqueID64 areaNameId; - Value transformMtx[3]; - Value aabb[2]; - UniqueID64 areaMREAId; - Value areaId; + Value areaIdx; + Value dockIdx; + }; + Vector endpoints; - Value attachedAreaCount; - Vector attachedAreas; - - Value dockCount; - struct Dock : BigDNA - { - AT_DECL_DNA_YAML - Value endpointCount; - struct Endpoint : BigDNA - { - AT_DECL_DNA_YAML - Value areaIdx; - Value dockIdx; - }; - Vector endpoints; - - Value planeVertCount; - Vector planeVerts; - }; - Vector docks; - - String<-1> internalAreaName; + Value planeVertCount; + Vector planeVerts; }; - Vector areas; + Vector docks; - UniqueID64 worldMap; - Value unknown2; - Value unknown3; + String<-1> internalAreaName; + }; + Vector areas; - Value layerFlagCount; - struct LayerFlags : BigDNA - { - AT_DECL_DNA_YAML - Value layerCount; - Value flags; - }; - Vector layerFlags; + UniqueID64 worldMap; + Value unknown2; + Value unknown3; - Value layerNameCount; - Vector, AT_DNA_COUNT(layerNameCount)> layerNames; + Value layerFlagCount; + struct LayerFlags : BigDNA { + AT_DECL_DNA_YAML + Value layerCount; + Value flags; + }; + Vector layerFlags; - Value layerIDCount; - struct LayerID : BigDNA - { - AT_DECL_DNA_YAML - Value id[2]; - }; - Vector layerIDs; + Value layerNameCount; + Vector, AT_DNA_COUNT(layerNameCount)> layerNames; - Value layerNameOffsetCount; - Vector layerNameOffsets; + Value layerIDCount; + struct LayerID : BigDNA { + AT_DECL_DNA_YAML + Value id[2]; + }; + Vector layerIDs; + Value layerNameOffsetCount; + Vector layerNameOffsets; - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function fileChanged) - { - MLVL mlvl; - mlvl.read(rs); - athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".yaml"), true).getAbsolutePath()); - athena::io::ToYAMLStream(mlvl, writer); - hecl::blender::Connection& conn = btok.getBlenderConnection(); - return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter, - entry, force, fileChanged); - } + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function fileChanged) { + MLVL mlvl; + mlvl.read(rs); + athena::io::FileWriter writer(outPath.getWithExtension(_SYS_STR(".yaml"), true).getAbsolutePath()); + athena::io::ToYAMLStream(mlvl, writer); + hecl::blender::Connection& conn = btok.getBlenderConnection(); + return DNAMLVL::ReadMLVLToBlender(conn, mlvl, outPath, pakRouter, entry, force, fileChanged); + } }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/MREA.cpp b/DataSpec/DNAMP3/MREA.cpp index 2b33eba6a..349dcd261 100644 --- a/DataSpec/DNAMP3/MREA.cpp +++ b/DataSpec/DNAMP3/MREA.cpp @@ -4,289 +4,258 @@ #include "DataSpec/DNACommon/BabeDead.hpp" #include "hecl/Blender/Connection.hpp" -namespace DataSpec -{ +namespace DataSpec { extern hecl::Database::DataSpecEntry SpecEntMP3ORIG; -namespace DNAMP3 -{ +namespace DNAMP3 { -MREA::StreamReader::StreamReader(athena::io::IStreamReader& source, - atUint32 blkCount, atUint32 secIdxCount) -: DNAMP2::MREA::StreamReader(source) -{ - m_blkCount = blkCount; - m_blockInfos.reserve(blkCount); - for (atUint32 i=0 ; i& idx = m_secIdxs.back(); - idx.first.read(source); - idx.second = source.readUint32Big(); - } - source.seekAlign32(); - m_blkBase = source.position(); - nextBlock(); +MREA::StreamReader::StreamReader(athena::io::IStreamReader& source, atUint32 blkCount, atUint32 secIdxCount) +: DNAMP2::MREA::StreamReader(source) { + m_blkCount = blkCount; + m_blockInfos.reserve(blkCount); + for (atUint32 i = 0; i < blkCount; ++i) { + m_blockInfos.emplace_back(); + BlockInfo& info = m_blockInfos.back(); + info.read(source); + m_totalDecompLen += info.decompSize; + } + source.seekAlign32(); + m_secIdxs.reserve(secIdxCount); + for (atUint32 i = 0; i < secIdxCount; ++i) { + m_secIdxs.emplace_back(); + std::pair& idx = m_secIdxs.back(); + idx.first.read(source); + idx.second = source.readUint32Big(); + } + source.seekAlign32(); + m_blkBase = source.position(); + nextBlock(); } -void MREA::StreamReader::writeSecIdxs(athena::io::IStreamWriter& writer) const -{ - for (const std::pair& idx : m_secIdxs) - { - idx.first.write(writer); - writer.writeUint32Big(idx.second); - } +void MREA::StreamReader::writeSecIdxs(athena::io::IStreamWriter& writer) const { + for (const std::pair& idx : m_secIdxs) { + idx.first.write(writer); + writer.writeUint32Big(idx.second); + } } -void MREA::ReadBabeDeadToBlender_3(hecl::blender::PyOutStream& os, - athena::io::IStreamReader& rs) -{ - atUint32 bdMagic = rs.readUint32Big(); - if (bdMagic != 0xBABEDEAD) - Log.report(logvisor::Fatal, "invalid BABEDEAD magic"); - os << "bpy.context.scene.render.engine = 'CYCLES'\n" - "bpy.context.scene.world.use_nodes = True\n" - "bpy.context.scene.render.engine = 'BLENDER_GAME'\n" - "bg_node = bpy.context.scene.world.node_tree.nodes['Background']\n" - "bg_node.inputs[1].default_value = 0.0\n"; - for (atUint32 s=0 ; s<4 ; ++s) - { - atUint32 lightCount = rs.readUint32Big(); - for (atUint32 l=0 ; l& pakRouter, - const PAK::Entry& entry, - bool force, - hecl::blender::Token& btok, - std::function) -{ - using RigPair = std::pair; - RigPair dummy(nullptr, nullptr); +bool MREA::Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool force, hecl::blender::Token& btok, + std::function) { + using RigPair = std::pair; + RigPair dummy(nullptr, nullptr); - if (!force && outPath.isFile()) - return true; + if (!force && outPath.isFile()) + return true; - /* Do extract */ - Header head; - head.read(rs); - rs.seekAlign32(); + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); - /* MREA decompression stream */ - StreamReader drs(rs, head.compressedBlockCount, head.secIndexCount); - hecl::ProjectPath decompPath = outPath.getCookedPath(SpecEntMP3ORIG).getWithExtension(_SYS_STR(".decomp")); - decompPath.makeDirChain(false); - athena::io::FileWriter mreaDecompOut(decompPath.getAbsolutePath()); - head.write(mreaDecompOut); - mreaDecompOut.seekAlign32(); - drs.writeDecompInfos(mreaDecompOut); - mreaDecompOut.seekAlign32(); - drs.writeSecIdxs(mreaDecompOut); - mreaDecompOut.seekAlign32(); - atUint64 decompLen = drs.length(); - mreaDecompOut.writeBytes(drs.readBytes(decompLen).get(), decompLen); - mreaDecompOut.close(); - drs.seek(0, athena::Begin); + /* MREA decompression stream */ + StreamReader drs(rs, head.compressedBlockCount, head.secIndexCount); + hecl::ProjectPath decompPath = outPath.getCookedPath(SpecEntMP3ORIG).getWithExtension(_SYS_STR(".decomp")); + decompPath.makeDirChain(false); + athena::io::FileWriter mreaDecompOut(decompPath.getAbsolutePath()); + head.write(mreaDecompOut); + mreaDecompOut.seekAlign32(); + drs.writeDecompInfos(mreaDecompOut); + mreaDecompOut.seekAlign32(); + drs.writeSecIdxs(mreaDecompOut); + mreaDecompOut.seekAlign32(); + atUint64 decompLen = drs.length(); + mreaDecompOut.writeBytes(drs.readBytes(decompLen).get(), decompLen); + mreaDecompOut.close(); + drs.seek(0, athena::Begin); - - /* Start up blender connection */ - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(outPath, hecl::blender::BlendType::Area)) - return false; - - /* Open Py Stream and read sections */ - hecl::blender::PyOutStream os = conn.beginPythonOut(true); - os.format("import bpy\n" - "import bmesh\n" - "from mathutils import Vector\n" - "\n" - "bpy.context.scene.name = '%s'\n", - pakRouter.getBestEntryName(entry, false).c_str()); - DNACMDL::InitGeomBlenderContext(os, dataSpec.getMasterShaderPath(), true); - MaterialSet::RegisterMaterialProps(os); - os << "# Clear Scene\n" - "for ob in bpy.data.objects:\n" - " if ob.type != 'CAMERA':\n" - " bpy.context.scene.objects.unlink(ob)\n" - " bpy.data.objects.remove(ob)\n" - "bpy.types.Lamp.retro_layer = bpy.props.IntProperty(name='Retro: Light Layer')\n" - "bpy.types.Lamp.retro_origtype = bpy.props.IntProperty(name='Retro: Original Type')\n" - "\n"; - - /* One shared material set for all meshes */ - os << "# Materials\n" - "materials = []\n" - "\n"; - MaterialSet matSet; - atUint64 secStart = drs.position(); - matSet.read(drs); - matSet.readToBlender(os, pakRouter, entry, 0); - drs.seek(secStart + head.secSizes[0], athena::Begin); - std::vector vertAttribs; - DNACMDL::GetVertexAttributes(matSet, vertAttribs); - - /* Read mesh info */ - atUint32 curSec = 1; - std::vector surfaceCounts; - surfaceCounts.reserve(head.meshCount); - for (atUint32 m=0 ; mfirst == FOURCC('WOBJ')) - ++secIdxIt; - - /* Skip AROT */ - if (secIdxIt->first == FOURCC('ROCT')) - { - drs.seek(head.secSizes[curSec++], athena::Current); - ++secIdxIt; - } - - /* Skip AABB */ - if (secIdxIt->first == FOURCC('AABB')) - { - drs.seek(head.secSizes[curSec++], athena::Current); - ++secIdxIt; - } - - /* Now the meshes themselves */ - if (secIdxIt->first == FOURCC('GPUD')) - { - for (atUint32 m=0 ; m, MaterialSet, RigPair, DNACMDL::SurfaceHeader_3> - (os, drs, pakRouter, entry, dummy, true, - false, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec], surfaceCounts[m]); - } - ++secIdxIt; - } - - /* Skip DEPS */ - if (secIdxIt->first == FOURCC('DEPS')) - { - drs.seek(head.secSizes[curSec++], athena::Current); - ++secIdxIt; - } - - /* Skip SOBJ (SCLY) */ - if (secIdxIt->first == FOURCC('SOBJ')) - { - for (atUint32 l=0 ; lfirst == FOURCC('SGEN')) - { - drs.seek(head.secSizes[curSec++], athena::Current); - ++secIdxIt; - } - - /* Read Collision Meshes */ - if (secIdxIt->first == FOURCC('COLI')) - { - DNAMP2::DeafBabe collision; - secStart = drs.position(); - collision.read(drs); - DNAMP2::DeafBabe::BlenderInit(os); - collision.sendToBlender(os); - drs.seek(secStart + head.secSizes[curSec++], athena::Begin); - ++secIdxIt; - } - - /* Read BABEDEAD Lights as Cycles emissives */ - if (secIdxIt->first == FOURCC('LITE')) - { - secStart = drs.position(); - ReadBabeDeadToBlender_3(os, drs); - drs.seek(secStart + head.secSizes[curSec++], athena::Begin); - ++secIdxIt; - } - - /* Origins to center of mass */ - os << "bpy.context.scene.layers[1] = True\n" - "bpy.ops.object.select_by_type(type='MESH')\n" - "bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')\n" - "bpy.ops.object.select_all(action='DESELECT')\n" - "bpy.context.scene.layers[1] = False\n"; - - os.centerView(); - os.close(); - return conn.saveBlend(); -} - -bool MREA::ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Level::Area& areaOut) -{ - /* Do extract */ - Header head; - head.read(rs); - rs.seekAlign32(); - - /* MREA decompression stream */ - StreamReader drs(rs, head.compressedBlockCount, head.secIndexCount); - for (const std::pair& idx : drs.m_secIdxs) - { - if (idx.first == FOURCC('DEPS')) - { - drs.seek(head.getSecOffset(idx.second), athena::Begin); - DEPS deps; - deps.read(drs); - - unsigned r=0; - for (unsigned l=1 ; l areaOut.layers.size()) - break; - PAKBridge::Level::Area::Layer& layer = areaOut.layers.at(l-1); - layer.resources.reserve(deps.depLayers[l] - r); - for (; r vertAttribs; + DNACMDL::GetVertexAttributes(matSet, vertAttribs); + + /* Read mesh info */ + atUint32 curSec = 1; + std::vector surfaceCounts; + surfaceCounts.reserve(head.meshCount); + for (atUint32 m = 0; m < head.meshCount; ++m) { + /* Mesh header */ + MeshHeader mHeader; + secStart = drs.position(); + mHeader.read(drs); + drs.seek(secStart + head.secSizes[curSec++], athena::Begin); + + /* Surface count from here */ + secStart = drs.position(); + surfaceCounts.push_back(drs.readUint32Big()); + drs.seek(secStart + head.secSizes[curSec++], athena::Begin); + + /* Seek through AROT-relation sections */ + drs.seek(head.secSizes[curSec++], athena::Current); + drs.seek(head.secSizes[curSec++], athena::Current); + } + + /* Skip though WOBJs */ + auto secIdxIt = drs.beginSecIdxs(); + while (secIdxIt->first == FOURCC('WOBJ')) + ++secIdxIt; + + /* Skip AROT */ + if (secIdxIt->first == FOURCC('ROCT')) { + drs.seek(head.secSizes[curSec++], athena::Current); + ++secIdxIt; + } + + /* Skip AABB */ + if (secIdxIt->first == FOURCC('AABB')) { + drs.seek(head.secSizes[curSec++], athena::Current); + ++secIdxIt; + } + + /* Now the meshes themselves */ + if (secIdxIt->first == FOURCC('GPUD')) { + for (atUint32 m = 0; m < head.meshCount; ++m) { + curSec += + DNACMDL::ReadGeomSectionsToBlender, MaterialSet, RigPair, DNACMDL::SurfaceHeader_3>( + os, drs, pakRouter, entry, dummy, true, false, vertAttribs, m, head.secCount, 0, &head.secSizes[curSec], + surfaceCounts[m]); + } + ++secIdxIt; + } + + /* Skip DEPS */ + if (secIdxIt->first == FOURCC('DEPS')) { + drs.seek(head.secSizes[curSec++], athena::Current); + ++secIdxIt; + } + + /* Skip SOBJ (SCLY) */ + if (secIdxIt->first == FOURCC('SOBJ')) { + for (atUint32 l = 0; l < head.sclyLayerCount; ++l) + drs.seek(head.secSizes[curSec++], athena::Current); + ++secIdxIt; + } + + /* Skip SGEN */ + if (secIdxIt->first == FOURCC('SGEN')) { + drs.seek(head.secSizes[curSec++], athena::Current); + ++secIdxIt; + } + + /* Read Collision Meshes */ + if (secIdxIt->first == FOURCC('COLI')) { + DNAMP2::DeafBabe collision; + secStart = drs.position(); + collision.read(drs); + DNAMP2::DeafBabe::BlenderInit(os); + collision.sendToBlender(os); + drs.seek(secStart + head.secSizes[curSec++], athena::Begin); + ++secIdxIt; + } + + /* Read BABEDEAD Lights as Cycles emissives */ + if (secIdxIt->first == FOURCC('LITE')) { + secStart = drs.position(); + ReadBabeDeadToBlender_3(os, drs); + drs.seek(secStart + head.secSizes[curSec++], athena::Begin); + ++secIdxIt; + } + + /* Origins to center of mass */ + os << "bpy.context.scene.layers[1] = True\n" + "bpy.ops.object.select_by_type(type='MESH')\n" + "bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')\n" + "bpy.ops.object.select_all(action='DESELECT')\n" + "bpy.context.scene.layers[1] = False\n"; + + os.centerView(); + os.close(); + return conn.saveBlend(); } +bool MREA::ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Level::Area& areaOut) { + /* Do extract */ + Header head; + head.read(rs); + rs.seekAlign32(); + + /* MREA decompression stream */ + StreamReader drs(rs, head.compressedBlockCount, head.secIndexCount); + for (const std::pair& idx : drs.m_secIdxs) { + if (idx.first == FOURCC('DEPS')) { + drs.seek(head.getSecOffset(idx.second), athena::Begin); + DEPS deps; + deps.read(drs); + + unsigned r = 0; + for (unsigned l = 1; l < deps.depLayerCount; ++l) { + if (l > areaOut.layers.size()) + break; + PAKBridge::Level::Area::Layer& layer = areaOut.layers.at(l - 1); + layer.resources.reserve(deps.depLayers[l] - r); + for (; r < deps.depLayers[l]; ++r) + layer.resources.emplace(deps.deps[r].id); + } + areaOut.resources.reserve(deps.depCount - r + 2); + for (; r < deps.depCount; ++r) + areaOut.resources.emplace(deps.deps[r].id); + + return true; + } + } + return false; } -} + +} // namespace DNAMP3 +} // namespace DataSpec diff --git a/DataSpec/DNAMP3/MREA.hpp b/DataSpec/DNAMP3/MREA.hpp index 58ec8b629..170a3c42e 100644 --- a/DataSpec/DNAMP3/MREA.hpp +++ b/DataSpec/DNAMP3/MREA.hpp @@ -5,124 +5,90 @@ #include "CSKR.hpp" #include "../DNAMP2/MREA.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct MREA -{ - struct StreamReader : DNAMP2::MREA::StreamReader - { - std::vector> m_secIdxs; - StreamReader(athena::io::IStreamReader& source, - atUint32 blkCount, atUint32 secIdxCount); - std::vector>::const_iterator beginSecIdxs() - { - return m_secIdxs.begin(); - } - void writeSecIdxs(athena::io::IStreamWriter& writer) const; +struct MREA { + struct StreamReader : DNAMP2::MREA::StreamReader { + std::vector> m_secIdxs; + StreamReader(athena::io::IStreamReader& source, atUint32 blkCount, atUint32 secIdxCount); + std::vector>::const_iterator beginSecIdxs() { return m_secIdxs.begin(); } + void writeSecIdxs(athena::io::IStreamWriter& writer) const; + }; + + struct Header : BigDNA { + AT_DECL_DNA + Value magic; + Value version; + Value localToWorldMtx[3]; + Value meshCount; + Value sclyLayerCount; + Value secCount; + Value compressedBlockCount; + Value secIndexCount; + Seek<20, athena::Current> align1; + Vector secSizes; + + atUint32 getSecOffset(atUint32 idx) const { + if (idx >= secSizes.size()) + return -1; + atUint32 retval = 0; + for (atUint32 i = 0; i < idx; ++i) + retval += secSizes[i]; + return retval; + } + }; + + struct MeshHeader : BigDNA { + AT_DECL_DNA + struct VisorFlags : BigDNA { + AT_DECL_DNA + Value flags; + } visorFlags; + Value xfMtx[3]; + Value aabb[2]; + }; + + struct DEPS : BigDNA { + AT_DECL_DNA + Value depCount; + struct Dependency : BigDNA { + AT_DECL_DNA + UniqueID64 id; + DNAFourCC type; }; + Vector deps; + Value depLayerCount; + Vector depLayers; + }; - struct Header : BigDNA - { - AT_DECL_DNA - Value magic; - Value version; - Value localToWorldMtx[3]; - Value meshCount; - Value sclyLayerCount; - Value secCount; - Value compressedBlockCount; - Value secIndexCount; - Seek<20, athena::Current> align1; - Vector secSizes; + struct BabeDeadLight : BigDNA { + AT_DECL_DNA + enum class LightType : atUint32 { LocalAmbient, Directional, Custom, Spot, Spot2, LocalAmbient2 }; + enum class Falloff : atUint32 { Constant, Linear, Quadratic }; + Value lightType; + Value color; + Value alpha = 1.f; + Value position; + Value direction; + Value codirection; + Value q; + Value spotCutoff; + Value unk7; + Value castShadows; + Value unk9; + Value falloff; + Value unk11; + Value unk12; + Value unk13; + }; - atUint32 getSecOffset(atUint32 idx) const - { - if (idx >= secSizes.size()) - return -1; - atUint32 retval = 0; - for (atUint32 i=0 ; i flags; - } visorFlags; - Value xfMtx[3]; - Value aabb[2]; - }; + static bool Extract(const SpecBase& dataSpec, PAKEntryReadStream& rs, const hecl::ProjectPath& outPath, + PAKRouter& pakRouter, const PAK::Entry& entry, bool, hecl::blender::Token& btok, + std::function); - struct DEPS : BigDNA - { - AT_DECL_DNA - Value depCount; - struct Dependency : BigDNA - { - AT_DECL_DNA - UniqueID64 id; - DNAFourCC type; - }; - Vector deps; - Value depLayerCount; - Vector depLayers; - }; - - struct BabeDeadLight : BigDNA - { - AT_DECL_DNA - enum class LightType : atUint32 - { - LocalAmbient, - Directional, - Custom, - Spot, - Spot2, - LocalAmbient2 - }; - enum class Falloff : atUint32 - { - Constant, - Linear, - Quadratic - }; - Value lightType; - Value color; - Value alpha = 1.f; - Value position; - Value direction; - Value codirection; - Value q; - Value spotCutoff; - Value unk7; - Value castShadows; - Value unk9; - Value falloff; - Value unk11; - Value unk12; - Value unk13; - }; - - static void ReadBabeDeadToBlender_3(hecl::blender::PyOutStream& os, - athena::io::IStreamReader& rs); - - static bool Extract(const SpecBase& dataSpec, - PAKEntryReadStream& rs, - const hecl::ProjectPath& outPath, - PAKRouter& pakRouter, - const PAK::Entry& entry, - bool, - hecl::blender::Token& btok, - std::function); - - static bool ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Level::Area& areaOut); + static bool ExtractLayerDeps(PAKEntryReadStream& rs, PAKBridge::Level::Area& areaOut); }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/PAK.cpp b/DataSpec/DNAMP3/PAK.cpp index 1513323bb..69163f549 100644 --- a/DataSpec/DNAMP3/PAK.cpp +++ b/DataSpec/DNAMP3/PAK.cpp @@ -1,261 +1,231 @@ #include "PAK.hpp" #include "DNAMP3.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { const hecl::FourCC CMPD("CMPD"); template <> -void PAK::Enumerate(athena::io::IStreamReader& reader) -{ - m_header.read(reader); - if (m_header.version != 2) - Log.report(logvisor::Fatal, "unexpected PAK magic"); +void PAK::Enumerate(athena::io::IStreamReader& reader) { + m_header.read(reader); + if (m_header.version != 2) + Log.report(logvisor::Fatal, "unexpected PAK magic"); - reader.seek(8, athena::Current); - atUint32 strgSz = reader.readUint32Big(); - reader.seek(4, athena::Current); - atUint32 rshdSz = reader.readUint32Big(); - reader.seek(44, athena::Current); - atUint32 dataOffset = 128 + strgSz + rshdSz; + reader.seek(8, athena::Current); + atUint32 strgSz = reader.readUint32Big(); + reader.seek(4, athena::Current); + atUint32 rshdSz = reader.readUint32Big(); + reader.seek(44, athena::Current); + atUint32 dataOffset = 128 + strgSz + rshdSz; - atUint64 strgBase = reader.position(); - atUint32 nameCount = reader.readUint32Big(); - m_nameEntries.clear(); - m_nameEntries.reserve(nameCount); - for (atUint32 n=0 ; n entries; + entries.reserve(count); + for (atUint32 e = 0; e < count; ++e) { + entries.emplace_back(); + entries.back().read(reader); + } + for (atUint32 e = 0; e < count; ++e) { + Entry& entry = entries[e]; + entry.offset += dataOffset; + + auto search = m_entries.find(entry.id); + if (search == m_entries.end()) { + m_firstEntries.push_back(entry.id); + m_entries[entry.id] = std::move(entry); + } else { + /* Find next MREA to record which area has dupes */ + for (atUint32 e2 = e + 1; e2 < count; ++e2) { + Entry& entry2 = entries[e2]; + if (entry2.type != FOURCC('MREA')) + continue; + m_dupeMREAs.insert(entry2.id); + break; + } } - reader.seek(strgBase + strgSz, athena::Begin); + } - atUint32 count = reader.readUint32Big(); - m_entries.clear(); - m_entries.reserve(count); - m_firstEntries.clear(); - m_firstEntries.reserve(count); - std::vector entries; - entries.reserve(count); - for (atUint32 e=0 ; e -void PAK::Enumerate(athena::io::IStreamWriter& writer) -{ - m_header.write(writer); +void PAK::Enumerate(athena::io::IStreamWriter& writer) { + m_header.write(writer); - DNAFourCC("STRG").write(writer); - atUint32 strgSz = 4; - for (const NameEntry& entry : m_nameEntries) - strgSz += (atUint32)entry.name.size() + 13; - atUint32 strgPad = ((strgSz + 63) & ~63) - strgSz; - strgSz += strgPad; - writer.writeUint32Big(strgSz); + DNAFourCC("STRG").write(writer); + atUint32 strgSz = 4; + for (const NameEntry& entry : m_nameEntries) + strgSz += (atUint32)entry.name.size() + 13; + atUint32 strgPad = ((strgSz + 63) & ~63) - strgSz; + strgSz += strgPad; + writer.writeUint32Big(strgSz); - DNAFourCC("RSHD").write(writer); - atUint32 rshdSz = 4 + 24 * m_entries.size(); - atUint32 rshdPad = ((rshdSz + 63) & ~63) - rshdSz; - rshdSz += rshdPad; - writer.writeUint32Big(rshdSz); - atUint32 dataOffset = 128 + strgSz + rshdSz; + DNAFourCC("RSHD").write(writer); + atUint32 rshdSz = 4 + 24 * m_entries.size(); + atUint32 rshdPad = ((rshdSz + 63) & ~63) - rshdSz; + rshdSz += rshdPad; + writer.writeUint32Big(rshdSz); + atUint32 dataOffset = 128 + strgSz + rshdSz; - DNAFourCC("DATA").write(writer); - atUint32 dataSz = 0; - for (const auto& entry : m_entries) - dataSz += (entry.second.size + 63) & ~63; - atUint32 dataPad = ((dataSz + 63) & ~63) - dataSz; - dataSz += dataPad; - writer.writeUint32Big(dataSz); - writer.seek(36, athena::Current); + DNAFourCC("DATA").write(writer); + atUint32 dataSz = 0; + for (const auto& entry : m_entries) + dataSz += (entry.second.size + 63) & ~63; + atUint32 dataPad = ((dataSz + 63) & ~63) - dataSz; + dataSz += dataPad; + writer.writeUint32Big(dataSz); + writer.seek(36, athena::Current); - writer.writeUint32Big((atUint32)m_nameEntries.size()); - for (const NameEntry& entry : m_nameEntries) - entry.write(writer); - writer.seek(strgPad, athena::Current); + writer.writeUint32Big((atUint32)m_nameEntries.size()); + for (const NameEntry& entry : m_nameEntries) + entry.write(writer); + writer.seek(strgPad, athena::Current); - writer.writeUint32Big((atUint32)m_entries.size()); - for (const auto& entry : m_entries) - { - Entry copy = entry.second; - copy.offset -= dataOffset; - copy.write(writer); - } - writer.seek(rshdPad, athena::Current); + writer.writeUint32Big((atUint32)m_entries.size()); + for (const auto& entry : m_entries) { + Entry copy = entry.second; + copy.offset -= dataOffset; + copy.write(writer); + } + writer.seek(rshdPad, athena::Current); } template <> -void PAK::Enumerate(size_t& __isz) -{ - m_header.binarySize(__isz); +void PAK::Enumerate(size_t& __isz) { + m_header.binarySize(__isz); - size_t strgSz = 4; - for (const NameEntry& entry : m_nameEntries) - strgSz += entry.name.size() + 13; - size_t strgPad = ((strgSz + 63) & ~63) - strgSz; + size_t strgSz = 4; + for (const NameEntry& entry : m_nameEntries) + strgSz += entry.name.size() + 13; + size_t strgPad = ((strgSz + 63) & ~63) - strgSz; - size_t rshdSz = 4 + 24 * m_entries.size(); - size_t rshdPad = ((rshdSz + 63) & ~63) - rshdSz; + size_t rshdSz = 4 + 24 * m_entries.size(); + size_t rshdPad = ((rshdSz + 63) & ~63) - rshdSz; - __isz += 60; + __isz += 60; - __isz += 4; - for (const NameEntry& entry : m_nameEntries) - entry.binarySize(__isz); - __isz += strgPad; + __isz += 4; + for (const NameEntry& entry : m_nameEntries) + entry.binarySize(__isz); + __isz += strgPad; - __isz += 4; - for (const auto& entry : m_entries) - entry.second.binarySize(__isz); - __isz += rshdPad; + __isz += 4; + for (const auto& entry : m_entries) + entry.second.binarySize(__isz); + __isz += rshdPad; } -std::unique_ptr PAK::Entry::getBuffer(const nod::Node& pak, atUint64& szOut) const -{ - if (compressed) - { - std::unique_ptr strm = pak.beginReadStream(offset); - struct - { - hecl::FourCC magic; - atUint32 blockCount; - } head; - strm->read(&head, 8); - if (head.magic != CMPD) - { - Log.report(logvisor::Error, "invalid CMPD block"); - return std::unique_ptr(); - } - head.blockCount = hecl::SBig(head.blockCount); - - struct Block - { - atUint32 compSz; - atUint32 decompSz; - }; - std::unique_ptr blocks(new Block[head.blockCount]); - strm->read(blocks.get(), 8 * head.blockCount); - - atUint64 maxBlockSz = 0; - atUint64 totalDecompSz = 0; - for (atUint32 b=0 ; b maxBlockSz) - maxBlockSz = block.compSz; - totalDecompSz += block.decompSz; - } - - std::unique_ptr compBuf(new atUint8[maxBlockSz]); - atUint8* buf = new atUint8[totalDecompSz]; - atUint8* bufCur = buf; - for (atUint32 b=0 ; bread(compBufCur, block.compSz); - if (block.compSz == block.decompSz) - { - memcpy(bufCur, compBufCur, block.decompSz); - bufCur += block.decompSz; - } - else - { - atUint32 rem = block.decompSz; - while (rem) - { - atUint16 chunkSz = hecl::SBig(*(atUint16*)compBufCur); - compBufCur += 2; - lzo_uint dsz = rem; - lzo1x_decompress(compBufCur, chunkSz, bufCur, &dsz, nullptr); - compBufCur += chunkSz; - bufCur += dsz; - rem -= dsz; - } - } - } - - szOut = totalDecompSz; - return std::unique_ptr(buf); +std::unique_ptr PAK::Entry::getBuffer(const nod::Node& pak, atUint64& szOut) const { + if (compressed) { + std::unique_ptr strm = pak.beginReadStream(offset); + struct { + hecl::FourCC magic; + atUint32 blockCount; + } head; + strm->read(&head, 8); + if (head.magic != CMPD) { + Log.report(logvisor::Error, "invalid CMPD block"); + return std::unique_ptr(); } - else - { - atUint8* buf = new atUint8[size]; - pak.beginReadStream(offset)->read(buf, size); - szOut = size; - return std::unique_ptr(buf); + head.blockCount = hecl::SBig(head.blockCount); + + struct Block { + atUint32 compSz; + atUint32 decompSz; + }; + std::unique_ptr blocks(new Block[head.blockCount]); + strm->read(blocks.get(), 8 * head.blockCount); + + atUint64 maxBlockSz = 0; + atUint64 totalDecompSz = 0; + for (atUint32 b = 0; b < head.blockCount; ++b) { + Block& block = blocks[b]; + block.compSz = hecl::SBig(block.compSz) & 0xffffff; + block.decompSz = hecl::SBig(block.decompSz); + if (block.compSz > maxBlockSz) + maxBlockSz = block.compSz; + totalDecompSz += block.decompSz; } -} -const PAK::Entry* PAK::lookupEntry(const UniqueID64& id) const -{ - auto result = m_entries.find(id); - if (result != m_entries.end()) - return &result->second; - return nullptr; -} - -const PAK::Entry* PAK::lookupEntry(std::string_view name) const -{ - auto result = m_nameMap.find(name.data()); - if (result != m_nameMap.end()) - { - auto result1 = m_entries.find(result->second); - if (result1 != m_entries.end()) - return &result1->second; - } - return nullptr; -} - -std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const -{ - /* Prefer named entries first */ - for (const NameEntry& nentry : m_nameEntries) - if (nentry.id == entry.id) - { - named = true; - return nentry.name; + std::unique_ptr compBuf(new atUint8[maxBlockSz]); + atUint8* buf = new atUint8[totalDecompSz]; + atUint8* bufCur = buf; + for (atUint32 b = 0; b < head.blockCount; ++b) { + Block& block = blocks[b]; + atUint8* compBufCur = compBuf.get(); + strm->read(compBufCur, block.compSz); + if (block.compSz == block.decompSz) { + memcpy(bufCur, compBufCur, block.decompSz); + bufCur += block.decompSz; + } else { + atUint32 rem = block.decompSz; + while (rem) { + atUint16 chunkSz = hecl::SBig(*(atUint16*)compBufCur); + compBufCur += 2; + lzo_uint dsz = rem; + lzo1x_decompress(compBufCur, chunkSz, bufCur, &dsz, nullptr); + compBufCur += chunkSz; + bufCur += dsz; + rem -= dsz; } + } + } - /* Otherwise return ID format string */ - named = false; - return entry.type.toString() + '_' + entry.id.toString(); + szOut = totalDecompSz; + return std::unique_ptr(buf); + } else { + atUint8* buf = new atUint8[size]; + pak.beginReadStream(offset)->read(buf, size); + szOut = size; + return std::unique_ptr(buf); + } } +const PAK::Entry* PAK::lookupEntry(const UniqueID64& id) const { + auto result = m_entries.find(id); + if (result != m_entries.end()) + return &result->second; + return nullptr; } + +const PAK::Entry* PAK::lookupEntry(std::string_view name) const { + auto result = m_nameMap.find(name.data()); + if (result != m_nameMap.end()) { + auto result1 = m_entries.find(result->second); + if (result1 != m_entries.end()) + return &result1->second; + } + return nullptr; +} + +std::string PAK::bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const { + /* Prefer named entries first */ + for (const NameEntry& nentry : m_nameEntries) + if (nentry.id == entry.id) { + named = true; + return nentry.name; + } + + /* Otherwise return ID format string */ + named = false; + return entry.type.toString() + '_' + entry.id.toString(); +} + +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/PAK.hpp b/DataSpec/DNAMP3/PAK.hpp index 669ff8f9c..b1283a563 100644 --- a/DataSpec/DNAMP3/PAK.hpp +++ b/DataSpec/DNAMP3/PAK.hpp @@ -6,70 +6,62 @@ #include #include "DataSpec/DNACommon/PAK.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { extern const hecl::FourCC CMPD; -struct PAK : BigDNA -{ - bool m_noShare; - PAK(bool noShare) : m_noShare(noShare) {} +struct PAK : BigDNA { + bool m_noShare; + PAK(bool noShare) : m_noShare(noShare) {} - struct Header : BigDNA - { - AT_DECL_DNA - Value version; - Value headSz; - Value md5sum[16]; - Seek<40, athena::Current> seek; - } m_header; + struct Header : BigDNA { + AT_DECL_DNA + Value version; + Value headSz; + Value md5sum[16]; + Seek<40, athena::Current> seek; + } m_header; - struct NameEntry : BigDNA - { - AT_DECL_DNA - String<-1> name; - DNAFourCC type; - UniqueID64 id; - }; + struct NameEntry : BigDNA { + AT_DECL_DNA + String<-1> name; + DNAFourCC type; + UniqueID64 id; + }; - struct Entry : BigDNA - { - AT_DECL_DNA - Value compressed; - DNAFourCC type; - UniqueID64 id; - Value size; - Value offset; - UniqueResult unique; - std::string name; + struct Entry : BigDNA { + AT_DECL_DNA + Value compressed; + DNAFourCC type; + UniqueID64 id; + Value size; + Value offset; + UniqueResult unique; + std::string name; - std::unique_ptr getBuffer(const nod::Node& pak, atUint64& szOut) const; - inline PAKEntryReadStream beginReadStream(const nod::Node& pak, atUint64 off=0) const - { - atUint64 sz; - std::unique_ptr buf = getBuffer(pak, sz); - return PAKEntryReadStream(std::move(buf), sz, off); - } - }; + std::unique_ptr getBuffer(const nod::Node& pak, atUint64& szOut) const; + inline PAKEntryReadStream beginReadStream(const nod::Node& pak, atUint64 off = 0) const { + atUint64 sz; + std::unique_ptr buf = getBuffer(pak, sz); + return PAKEntryReadStream(std::move(buf), sz, off); + } + }; - std::vector m_nameEntries; - std::unordered_map m_entries; - std::vector m_firstEntries; - std::unordered_map m_nameMap; - std::unordered_set m_dupeMREAs; + std::vector m_nameEntries; + std::unordered_map m_entries; + std::vector m_firstEntries; + std::unordered_map m_nameMap; + std::unordered_set m_dupeMREAs; - AT_DECL_EXPLICIT_DNA + AT_DECL_EXPLICIT_DNA - const Entry* lookupEntry(const UniqueID64& id) const; - const Entry* lookupEntry(std::string_view name) const; - std::string bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const; + const Entry* lookupEntry(const UniqueID64& id) const; + const Entry* lookupEntry(std::string_view name) const; + std::string bestEntryName(const nod::Node& pakNode, const Entry& entry, bool& named) const; - bool mreaHasDupeResources(const UniqueID64& id) const - { return m_dupeMREAs.find(id) != m_dupeMREAs.cend(); } + bool mreaHasDupeResources(const UniqueID64& id) const { return m_dupeMREAs.find(id) != m_dupeMREAs.cend(); } - typedef UniqueID64 IDType; + typedef UniqueID64 IDType; }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/SAVW.hpp b/DataSpec/DNAMP3/SAVW.hpp index 289bf4c00..77c03914c 100644 --- a/DataSpec/DNAMP3/SAVW.hpp +++ b/DataSpec/DNAMP3/SAVW.hpp @@ -3,45 +3,39 @@ #include "DataSpec/DNACommon/SAVWCommon.hpp" #include "DNAMP3.hpp" -namespace DataSpec::DNAMP3 -{ -struct Scan : BigDNA -{ - AT_DECL_DNA_YAML - UniqueID64 scanId; - Value category; +namespace DataSpec::DNAMP3 { +struct Scan : BigDNA { + AT_DECL_DNA_YAML + UniqueID64 scanId; + Value category; }; -struct SavedState : BigDNA -{ +struct SavedState : BigDNA { + AT_DECL_DNA_YAML + struct ID : BigDNA { AT_DECL_DNA_YAML - struct ID : BigDNA - { - AT_DECL_DNA_YAML - Value id[2]; - }; - ID id; - Value instance; + Value id[2]; + }; + ID id; + Value instance; }; -struct SAVW : BigDNA -{ - AT_DECL_DNA_YAML - SAVWCommon::Header header; - Value skippableCutsceneCount; - Vector skippableCutscenes; - Value relayCount; - Vector relays; - Value doorCount; - Vector doors; - Value scanCount; - Vector scans; - Value systemVarCount; - Vector systemVars; - Value gameVarCount; - Vector gameVars; - Value gameObjectCount; - Vector gameObjects; +struct SAVW : BigDNA { + AT_DECL_DNA_YAML + SAVWCommon::Header header; + Value skippableCutsceneCount; + Vector skippableCutscenes; + Value relayCount; + Vector relays; + Value doorCount; + Vector doors; + Value scanCount; + Vector scans; + Value systemVarCount; + Vector systemVars; + Value gameVarCount; + Vector gameVars; + Value gameObjectCount; + Vector gameObjects; }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/STRG.cpp b/DataSpec/DNAMP3/STRG.cpp index 6870e5c56..12c23ad73 100644 --- a/DataSpec/DNAMP3/STRG.cpp +++ b/DataSpec/DNAMP3/STRG.cpp @@ -1,270 +1,227 @@ #include "STRG.hpp" #include "DNAMP3.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -void STRG::_read(athena::io::IStreamReader& reader) -{ - atUint32 langCount = reader.readUint32Big(); - atUint32 strCount = reader.readUint32Big(); +void STRG::_read(athena::io::IStreamReader& reader) { + atUint32 langCount = reader.readUint32Big(); + atUint32 strCount = reader.readUint32Big(); - atUint32 nameCount = reader.readUint32Big(); - atUint32 nameTableSz = reader.readUint32Big(); - if (nameTableSz) - { - std::unique_ptr nameTableBuf(new uint8_t[nameTableSz]); - reader.readUBytesToBuf(nameTableBuf.get(), nameTableSz); - struct NameIdxEntry - { - atUint32 nameOff; - atUint32 strIdx; - }* nameIndex = (NameIdxEntry*)nameTableBuf.get(); - for (atUint32 n=0 ; n nameTableBuf(new uint8_t[nameTableSz]); + reader.readUBytesToBuf(nameTableBuf.get(), nameTableSz); + struct NameIdxEntry { + atUint32 nameOff; + atUint32 strIdx; + }* nameIndex = (NameIdxEntry*)nameTableBuf.get(); + for (atUint32 n = 0; n < nameCount; ++n) { + const char* name = (char*)(nameTableBuf.get() + hecl::SBig(nameIndex[n].nameOff)); + names[name] = hecl::SBig(nameIndex[n].strIdx); } + } - std::vector readLangs; - readLangs.reserve(langCount); - for (atUint32 l=0 ; l strOffs(new atUint32[langCount * strCount]); - for (atUint32 l=0 ; l readLangs; + readLangs.reserve(langCount); + for (atUint32 l = 0; l < langCount; ++l) { + DNAFourCC lang; + lang.read(reader); + readLangs.emplace_back(lang); + } + std::unique_ptr strOffs(new atUint32[langCount * strCount]); + for (atUint32 l = 0; l < langCount; ++l) { + reader.readUint32Big(); + for (atUint32 s = 0; s < strCount; ++s) + strOffs[l * strCount + s] = reader.readUint32Big(); + } - atUint64 strBase = reader.position(); - langs.clear(); - langs.reserve(langCount); - for (atUint32 l=0 ; l strs; - for (atUint32 s=0 ; s strs; + for (atUint32 s = 0; s < strCount; ++s) { + reader.seek(strBase + strOffs[l * strCount + s], athena::Begin); + atUint32 len = reader.readUint32Big(); + strs.emplace_back(reader.readString(len)); } + langs.emplace_back(readLangs[l], strs); + } - langMap.clear(); - langMap.reserve(langCount); - for (std::pair>& item : langs) - langMap.emplace(item.first, &item.second); + langMap.clear(); + langMap.reserve(langCount); + for (std::pair>& item : langs) + langMap.emplace(item.first, &item.second); } template <> -void STRG::Enumerate(athena::io::IStreamReader& reader) -{ - atUint32 magic = reader.readUint32Big(); - if (magic != 0x87654321) - { - Log.report(logvisor::Error, "invalid STRG magic"); +void STRG::Enumerate(athena::io::IStreamReader& reader) { + atUint32 magic = reader.readUint32Big(); + if (magic != 0x87654321) { + Log.report(logvisor::Error, "invalid STRG magic"); + return; + } + + atUint32 version = reader.readUint32Big(); + if (version != 3) { + Log.report(logvisor::Error, "invalid STRG version"); + return; + } + + _read(reader); +} + +template <> +void STRG::Enumerate(athena::io::YAMLDocReader& reader) { + const athena::io::YAMLNode* root = reader.getRootNode(); + + /* Validate Pass */ + if (root->m_type == YAML_MAPPING_NODE) { + for (const auto& lang : root->m_mapChildren) { + if (!lang.first.compare("names")) + continue; + if (lang.first.size() != 4) { + Log.report(logvisor::Warning, "STRG language string '%s' must be exactly 4 characters; skipping", + lang.first.c_str()); return; - } - - atUint32 version = reader.readUint32Big(); - if (version != 3) - { - Log.report(logvisor::Error, "invalid STRG version"); + } + if (lang.second->m_type != YAML_SEQUENCE_NODE) { + Log.report(logvisor::Warning, "STRG language string '%s' must contain a sequence; skipping", + lang.first.c_str()); return; + } + for (const auto& str : lang.second->m_seqChildren) { + if (str->m_type != YAML_SCALAR_NODE) { + Log.report(logvisor::Warning, "STRG language '%s' must contain all scalars; skipping", lang.first.c_str()); + return; + } + } } + } else { + Log.report(logvisor::Warning, "STRG must have a mapping root node; skipping"); + return; + } - _read(reader); + const athena::io::YAMLNode* nameYAML = root->findMapChild("names"); + names.clear(); + if (nameYAML && nameYAML->m_type == YAML_MAPPING_NODE) + for (const auto& item : nameYAML->m_mapChildren) + if (item.second->m_type == YAML_SCALAR_NODE) + names[item.first] = athena::io::NodeToVal(item.second.get()); + + langs.clear(); + langs.reserve(root->m_mapChildren.size()); + for (const auto& item : root->m_mapChildren) { + if (!item.first.compare("names") || item.first.size() != 4 || item.second->m_type != YAML_SEQUENCE_NODE) + continue; + + std::vector strs; + for (const auto& node : item.second->m_seqChildren) + if (node->m_type == YAML_SCALAR_NODE) + strs.emplace_back(node->m_scalarString); + langs.emplace_back(std::make_pair(DNAFourCC(item.first.c_str()), std::move(strs))); + } + + langMap.clear(); + langMap.reserve(langs.size()); + for (std::pair>& item : langs) + langMap.emplace(item.first, &item.second); } template <> -void STRG::Enumerate(athena::io::YAMLDocReader& reader) -{ - const athena::io::YAMLNode* root = reader.getRootNode(); +void STRG::Enumerate(athena::io::IStreamWriter& writer) { + writer.writeUint32Big(0x87654321); + writer.writeUint32Big(3); + writer.writeUint32Big(langs.size()); + atUint32 strCount = STRG::count(); + writer.writeUint32Big(strCount); - /* Validate Pass */ - if (root->m_type == YAML_MAPPING_NODE) - { - for (const auto& lang : root->m_mapChildren) - { - if (!lang.first.compare("names")) - continue; - if (lang.first.size() != 4) - { - Log.report(logvisor::Warning, "STRG language string '%s' must be exactly 4 characters; skipping", lang.first.c_str()); - return; - } - if (lang.second->m_type != YAML_SEQUENCE_NODE) - { - Log.report(logvisor::Warning, - "STRG language string '%s' must contain a sequence; skipping", lang.first.c_str()); - return; - } - for (const auto& str : lang.second->m_seqChildren) - { - if (str->m_type != YAML_SCALAR_NODE) - { - Log.report(logvisor::Warning, "STRG language '%s' must contain all scalars; skipping", lang.first.c_str()); - return; - } - } - } + atUint32 nameTableSz = names.size() * 8; + for (const auto& name : names) + nameTableSz += name.first.size() + 1; + writer.writeUint32Big(names.size()); + writer.writeUint32Big(nameTableSz); + atUint32 offset = names.size() * 8; + for (const auto& name : names) { + writer.writeUint32Big(offset); + writer.writeInt32Big(name.second); + offset += name.first.size() + 1; + } + for (const auto& name : names) + writer.writeString(name.first); + + for (const auto& lang : langs) + lang.first.write(writer); + + offset = 0; + for (const auto& lang : langs) { + atUint32 langSz = 0; + for (const std::string& str : lang.second) + langSz += str.size() + 5; + writer.writeUint32Big(langSz); + + for (const std::string& str : lang.second) { + writer.writeUint32Big(offset); + offset += str.size() + 5; } - else - { - Log.report(logvisor::Warning, "STRG must have a mapping root node; skipping"); - return; + } + + for (atUint32 s = 0; s < strCount; ++s) { + for (const auto& lang : langs) { + if (s >= lang.second.size()) { + writer.writeUint32Big(1); + writer.writeUByte(0); + } else { + const std::string& str = lang.second[s]; + writer.writeUint32Big(str.size() + 1); + writer.writeString(str); + } } - - const athena::io::YAMLNode* nameYAML = root->findMapChild("names"); - names.clear(); - if (nameYAML && nameYAML->m_type == YAML_MAPPING_NODE) - for (const auto& item : nameYAML->m_mapChildren) - if (item.second->m_type == YAML_SCALAR_NODE) - names[item.first] = athena::io::NodeToVal(item.second.get()); - - langs.clear(); - langs.reserve(root->m_mapChildren.size()); - for (const auto& item : root->m_mapChildren) - { - if (!item.first.compare("names") || item.first.size() != 4 || - item.second->m_type != YAML_SEQUENCE_NODE) - continue; - - std::vector strs; - for (const auto& node : item.second->m_seqChildren) - if (node->m_type == YAML_SCALAR_NODE) - strs.emplace_back(node->m_scalarString); - langs.emplace_back(std::make_pair(DNAFourCC(item.first.c_str()), std::move(strs))); - } - - langMap.clear(); - langMap.reserve(langs.size()); - for (std::pair>& item : langs) - langMap.emplace(item.first, &item.second); + } } template <> -void STRG::Enumerate(athena::io::IStreamWriter& writer) -{ - writer.writeUint32Big(0x87654321); - writer.writeUint32Big(3); - writer.writeUint32Big(langs.size()); - atUint32 strCount = STRG::count(); - writer.writeUint32Big(strCount); +void STRG::Enumerate(size_t& __isz) { + __isz += 24; + __isz += names.size() * 8; + for (const auto& name : names) + __isz += name.first.size() + 1; - atUint32 nameTableSz = names.size() * 8; - for (const auto& name : names) - nameTableSz += name.first.size() + 1; - writer.writeUint32Big(names.size()); - writer.writeUint32Big(nameTableSz); - atUint32 offset = names.size() * 8; - for (const auto& name : names) - { - writer.writeUint32Big(offset); - writer.writeInt32Big(name.second); - offset += name.first.size() + 1; - } - for (const auto& name : names) - writer.writeString(name.first); - - for (const auto& lang : langs) - lang.first.write(writer); - - offset = 0; - for (const auto& lang : langs) - { - atUint32 langSz = 0; - for (const std::string& str : lang.second) - langSz += str.size() + 5; - writer.writeUint32Big(langSz); - - for (const std::string& str : lang.second) - { - writer.writeUint32Big(offset); - offset += str.size() + 5; - } - } - - for (atUint32 s=0 ; s= lang.second.size()) - { - writer.writeUint32Big(1); - writer.writeUByte(0); - } - else - { - const std::string& str = lang.second[s]; - writer.writeUint32Big(str.size() + 1); - writer.writeString(str); - } - } + __isz += langs.size() * 4; + + for (const auto& lang : langs) + __isz += 4 + lang.second.size() * 4; + + size_t strCount = STRG::count(); + for (atUint32 s = 0; s < strCount; ++s) { + for (const auto& lang : langs) { + if (s >= lang.second.size()) { + __isz += 5; + } else { + const std::string& str = lang.second[s]; + __isz += str.size() + 5; + } } + } } template <> -void STRG::Enumerate(size_t& __isz) -{ - __isz += 24; - __isz += names.size() * 8; - for (const auto& name : names) - __isz += name.first.size() + 1; +void STRG::Enumerate(athena::io::YAMLDocWriter& writer) { + for (const auto& item : langs) { + if (auto v = writer.enterSubVector(item.first.toString().c_str())) + for (const std::string& str : item.second) + writer.writeString(nullptr, str); + } - __isz += langs.size() * 4; - - for (const auto& lang : langs) - __isz += 4 + lang.second.size() * 4; - - size_t strCount = STRG::count(); - for (atUint32 s=0 ; s= lang.second.size()) - { - __isz += 5; - } - else - { - const std::string& str = lang.second[s]; - __isz += str.size() + 5; - } - } - } + if (names.size()) { + if (auto rec = writer.enterSubRecord("names")) + for (const auto& item : names) + if (auto rec = writer.enterSubRecord(item.first.c_str())) + writer.writeInt32(nullptr, item.second); + } } -template <> -void STRG::Enumerate(athena::io::YAMLDocWriter& writer) -{ - for (const auto& item : langs) - { - if (auto v = writer.enterSubVector(item.first.toString().c_str())) - for (const std::string& str : item.second) - writer.writeString(nullptr, str); - } +const char* STRG::DNAType() { return "urde::DNAMP3::STRG"; } - if (names.size()) - { - if (auto rec = writer.enterSubRecord("names")) - for (const auto& item : names) - if (auto rec = writer.enterSubRecord(item.first.c_str())) - writer.writeInt32(nullptr, item.second); - } -} - -const char* STRG::DNAType() -{ - return "urde::DNAMP3::STRG"; -} - -} +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/DNAMP3/STRG.hpp b/DataSpec/DNAMP3/STRG.hpp index 722f48905..88f46881c 100644 --- a/DataSpec/DNAMP3/STRG.hpp +++ b/DataSpec/DNAMP3/STRG.hpp @@ -4,81 +4,70 @@ #include "DataSpec/DNACommon/PAK.hpp" #include "DataSpec/DNACommon/STRG.hpp" -namespace DataSpec::DNAMP3 -{ +namespace DataSpec::DNAMP3 { -struct STRG : ISTRG -{ - AT_DECL_EXPLICIT_DNA_YAML - AT_DECL_DNAV - void _read(athena::io::IStreamReader& reader); - std::vector>> langs; - std::unordered_map*> langMap; - std::map names; +struct STRG : ISTRG { + AT_DECL_EXPLICIT_DNA_YAML + AT_DECL_DNAV + void _read(athena::io::IStreamReader& reader); + std::vector>> langs; + std::unordered_map*> langMap; + std::map names; - int32_t lookupIdx(std::string_view name) const - { - auto search = names.find(name.data()); - if (search == names.end()) - return -1; - return search->second; - } + int32_t lookupIdx(std::string_view name) const { + auto search = names.find(name.data()); + if (search == names.end()) + return -1; + return search->second; + } - size_t count() const - { - size_t retval = 0; - for (const auto& item : langs) - { - size_t sz = item.second.size(); - if (sz > retval) - retval = sz; - } - return retval; + size_t count() const { + size_t retval = 0; + for (const auto& item : langs) { + size_t sz = item.second.size(); + if (sz > retval) + retval = sz; } - std::string getUTF8(const FourCC& lang, size_t idx) const - { - auto search = langMap.find(lang); - if (search != langMap.end()) - return search->second->at(idx); - return std::string(); - } - std::u16string getUTF16(const FourCC& lang, size_t idx) const - { - auto search = langMap.find(lang); - if (search != langMap.end()) - return hecl::UTF8ToChar16(search->second->at(idx)); - return std::u16string(); - } - hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const - { - auto search = langMap.find(lang); - if (search != langMap.end()) + return retval; + } + std::string getUTF8(const FourCC& lang, size_t idx) const { + auto search = langMap.find(lang); + if (search != langMap.end()) + return search->second->at(idx); + return std::string(); + } + std::u16string getUTF16(const FourCC& lang, size_t idx) const { + auto search = langMap.find(lang); + if (search != langMap.end()) + return hecl::UTF8ToChar16(search->second->at(idx)); + return std::u16string(); + } + hecl::SystemString getSystemString(const FourCC& lang, size_t idx) const { + auto search = langMap.find(lang); + if (search != langMap.end()) #if HECL_UCS2 - return hecl::UTF8ToWide(search->second->at(idx)); + return hecl::UTF8ToWide(search->second->at(idx)); #else - return search->second->at(idx); + return search->second->at(idx); #endif - return hecl::SystemString(); - } + return hecl::SystemString(); + } - static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) - { - std::unique_ptr strg = LoadSTRG(rs); - athena::io::TransactionalFileWriter writer(outPath.getAbsolutePath()); - athena::io::ToYAMLStream(*strg, writer); - return true; - } + static bool Extract(PAKEntryReadStream& rs, const hecl::ProjectPath& outPath) { + std::unique_ptr strg = LoadSTRG(rs); + athena::io::TransactionalFileWriter writer(outPath.getAbsolutePath()); + athena::io::ToYAMLStream(*strg, writer); + return true; + } - static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) - { - STRG strg; - athena::io::FileReader reader(inPath.getAbsolutePath()); - athena::io::FromYAMLStream(strg, reader); - athena::io::TransactionalFileWriter ws(outPath.getAbsolutePath()); - strg.write(ws); - return true; - } + static bool Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + STRG strg; + athena::io::FileReader reader(inPath.getAbsolutePath()); + athena::io::FromYAMLStream(strg, reader); + athena::io::TransactionalFileWriter ws(outPath.getAbsolutePath()); + strg.write(ws); + return true; + } }; -} - +} // namespace DataSpec::DNAMP3 diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp index 3a0f602fa..788e2fc96 100644 --- a/DataSpec/SpecBase.cpp +++ b/DataSpec/SpecBase.cpp @@ -18,1465 +18,1246 @@ #define DUMP_CACHE_FILL 1 -namespace DataSpec -{ +namespace DataSpec { static logvisor::Module Log("urde::SpecBase"); -static const hecl::SystemChar* MomErr[] = -{ - _SYS_STR("Your metroid is in another castle"), - _SYS_STR("HECL is experiencing a PTSD attack"), - _SYS_STR("Unable to freeze metroids"), - _SYS_STR("Ridley ate your homework"), - _SYS_STR("Expected 0 maternal symbolisms, found 2147483647"), - _SYS_STR("Contradictive narratives unsupported"), - _SYS_STR("Wiimote profile \"NES + Zapper\" not recognized"), - _SYS_STR("Unable to find Waldo"), - _SYS_STR("Expected Ridley, found furby"), - _SYS_STR("Adam has not authorized this, please do not bug the developers"), - _SYS_STR("Lady returned objection"), - _SYS_STR("Unterminated plot thread 'Deleter' detected") -}; +static const hecl::SystemChar* MomErr[] = {_SYS_STR("Your metroid is in another castle"), + _SYS_STR("HECL is experiencing a PTSD attack"), + _SYS_STR("Unable to freeze metroids"), + _SYS_STR("Ridley ate your homework"), + _SYS_STR("Expected 0 maternal symbolisms, found 2147483647"), + _SYS_STR("Contradictive narratives unsupported"), + _SYS_STR("Wiimote profile \"NES + Zapper\" not recognized"), + _SYS_STR("Unable to find Waldo"), + _SYS_STR("Expected Ridley, found furby"), + _SYS_STR("Adam has not authorized this, please do not bug the developers"), + _SYS_STR("Lady returned objection"), + _SYS_STR("Unterminated plot thread 'Deleter' detected")}; constexpr uint32_t MomErrCount = std::extent::value; SpecBase::SpecBase(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) -: hecl::Database::IDataSpec(specEntry), m_project(project), m_pc(pc), - m_masterShader(project.getProjectWorkingPath(), ".hecl/RetroMasterShader.blend") -{ - AssetNameMap::InitAssetNameMap(); - SpecBase::setThreadProject(); +: hecl::Database::IDataSpec(specEntry) +, m_project(project) +, m_pc(pc) +, m_masterShader(project.getProjectWorkingPath(), ".hecl/RetroMasterShader.blend") { + AssetNameMap::InitAssetNameMap(); + SpecBase::setThreadProject(); } -SpecBase::~SpecBase() -{ - cancelBackgroundIndex(); -} +SpecBase::~SpecBase() { cancelBackgroundIndex(); } static const hecl::SystemString regNONE = _SYS_STR(""); static const hecl::SystemString regE = _SYS_STR("NTSC"); static const hecl::SystemString regJ = _SYS_STR("NTSC-J"); static const hecl::SystemString regP = _SYS_STR("PAL"); -void SpecBase::setThreadProject() -{ - UniqueIDBridge::SetThreadProject(m_project); +void SpecBase::setThreadProject() { UniqueIDBridge::SetThreadProject(m_project); } + +template +IDRestorer::IDRestorer(const hecl::ProjectPath& yamlPath, const hecl::Database::Project& project) { + using ValType = typename IDType::value_type; + if (!yamlPath.isFile()) + return; + + athena::io::YAMLDocReader r; + athena::io::FileReader fr(yamlPath.getAbsolutePath()); + if (!fr.isOpen() || !r.parse(&fr)) + return; + + m_newToOrig.reserve(r.getRootNode()->m_mapChildren.size()); + m_origToNew.reserve(r.getRootNode()->m_mapChildren.size()); + for (const auto& node : r.getRootNode()->m_mapChildren) { + char* end = const_cast(node.first.c_str()); + ValType id = strtoull(end, &end, 16); + if (end != node.first.c_str() + sizeof(ValType) * 2) + continue; + + hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str()); + m_newToOrig.push_back(std::make_pair(IDType{path.hash().valT(), true}, IDType{id, true})); + m_origToNew.push_back(std::make_pair(IDType{id, true}, IDType{path.hash().valT(), true})); + } + + std::sort(m_newToOrig.begin(), m_newToOrig.end(), + [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); + std::sort(m_origToNew.begin(), m_origToNew.end(), + [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); + + Log.report(logvisor::Info, _SYS_STR("Loaded Original IDs '%s'"), yamlPath.getRelativePath().data()); } template -IDRestorer::IDRestorer(const hecl::ProjectPath& yamlPath, const hecl::Database::Project& project) -{ - using ValType = typename IDType::value_type; - if (!yamlPath.isFile()) - return; - - athena::io::YAMLDocReader r; - athena::io::FileReader fr(yamlPath.getAbsolutePath()); - if (!fr.isOpen() || !r.parse(&fr)) - return; - - m_newToOrig.reserve(r.getRootNode()->m_mapChildren.size()); - m_origToNew.reserve(r.getRootNode()->m_mapChildren.size()); - for (const auto& node : r.getRootNode()->m_mapChildren) - { - char* end = const_cast(node.first.c_str()); - ValType id = strtoull(end, &end, 16); - if (end != node.first.c_str() + sizeof(ValType) * 2) - continue; - - hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str()); - m_newToOrig.push_back(std::make_pair(IDType{path.hash().valT(), true}, IDType{id, true})); - m_origToNew.push_back(std::make_pair(IDType{id, true}, IDType{path.hash().valT(), true})); - } - - std::sort(m_newToOrig.begin(), m_newToOrig.end(), - [](const std::pair& a, const std::pair& b) { - return a.first < b.first; - }); - std::sort(m_origToNew.begin(), m_origToNew.end(), - [](const std::pair& a, const std::pair& b) { - return a.first < b.first; - }); - - Log.report(logvisor::Info, _SYS_STR("Loaded Original IDs '%s'"), yamlPath.getRelativePath().data()); +IDType IDRestorer::newToOriginal(IDType id) const { + if (!id) + return {}; + auto search = + rstl::binary_find(m_newToOrig.cbegin(), m_newToOrig.cend(), id, [](const auto& id) { return id.first; }); + if (search == m_newToOrig.cend()) + return {}; + return search->second; } template -IDType IDRestorer::newToOriginal(IDType id) const -{ - if (!id) - return {}; - auto search = rstl::binary_find(m_newToOrig.cbegin(), m_newToOrig.cend(), id, - [](const auto& id) { return id.first; }); - if (search == m_newToOrig.cend()) - return {}; - return search->second; -} - -template -IDType IDRestorer::originalToNew(IDType id) const -{ - if (!id) - return {}; - auto search = rstl::binary_find(m_origToNew.cbegin(), m_origToNew.cend(), id, - [](const auto& id) { return id.first; }); - if (search == m_origToNew.cend()) - return {}; - return search->second; +IDType IDRestorer::originalToNew(IDType id) const { + if (!id) + return {}; + auto search = + rstl::binary_find(m_origToNew.cbegin(), m_origToNew.cend(), id, [](const auto& id) { return id.first; }); + if (search == m_origToNew.cend()) + return {}; + return search->second; } template class IDRestorer; template class IDRestorer; template class IDRestorer; -bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector& reps) -{ - m_disc = nod::OpenDiscFromImage(info.srcpath, m_isWii); - if (!m_disc) - return false; - const char* gameID = m_disc->getHeader().m_gameID; - - if (!memcmp(gameID, "R3O", 3)) - { - std::srand(std::time(0)); - int r = std::rand() % MomErrCount; - Log.report(logvisor::Fatal, MomErr[r]); - } - - m_standalone = true; - if (m_isWii && (!memcmp(gameID, "R3M", 3) || !memcmp(gameID, "R3I", 3) || !memcmp(gameID, "R32", 3))) - m_standalone = false; - - if (m_standalone && !checkStandaloneID(gameID)) - return false; - - char region = m_disc->getHeader().m_gameID[3]; - const hecl::SystemString* regstr = ®NONE; - switch (region) - { - case 'E': - regstr = ®E; - break; - case 'J': - regstr = ®J; - break; - case 'P': - regstr = ®P; - break; - } - - if (m_standalone) - return checkFromStandaloneDisc(*m_disc, *regstr, info.extractArgs, reps); - else - return checkFromTrilogyDisc(*m_disc, *regstr, info.extractArgs, reps); -} - -void SpecBase::doExtract(const ExtractPassInfo& info, const hecl::MultiProgressPrinter& progress) -{ - setThreadProject(); - DataSpec::g_curSpec.reset(this); - if (!Blender::BuildMasterShader(m_masterShader)) - Log.report(logvisor::Fatal, "Unable to build master shader blend"); - if (m_isWii) - { - /* Extract root files for repacking later */ - hecl::ProjectPath outDir(m_project.getProjectWorkingPath(), _SYS_STR("out")); - outDir.makeDirChain(true); - nod::ExtractionContext ctx = {info.force, nullptr}; - - if (!m_standalone) - { - progress.print(_SYS_STR("Trilogy Files"), _SYS_STR(""), 0.0); - nod::IPartition* data = m_disc->getDataPartition(); - const nod::Node& root = data->getFSTRoot(); - for (const nod::Node& child : root) - if (child.getKind() == nod::Node::Kind::File) - child.extractToDirectory(outDir.getAbsolutePath(), ctx); - progress.print(_SYS_STR("Trilogy Files"), _SYS_STR(""), 1.0); - } - } - extractFromDisc(*m_disc, info.force, progress); -} - -static bool IsPathAudioGroup(const hecl::ProjectPath& path) -{ - return (path.getPathType() == hecl::ProjectPath::Type::Directory && - hecl::ProjectPath(path, _SYS_STR("!project.yaml")).isFile() && - hecl::ProjectPath(path, _SYS_STR("!pool.yaml")).isFile()); -} - -static bool IsPathSong(const hecl::ProjectPath& path) -{ - if (path.getPathType() != hecl::ProjectPath::Type::Glob || - !path.getWithExtension(_SYS_STR(".mid"), true).isFile() || - !path.getWithExtension(_SYS_STR(".yaml"), true).isFile()) - { - if (path.isFile() && - !hecl::StrCmp(_SYS_STR("mid"), path.getLastComponentExt().data()) && - path.getWithExtension(_SYS_STR(".yaml"), true).isFile()) - return true; - return false; - } - return true; -} - -bool SpecBase::canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok, int cookPass) -{ - if (!checkPathPrefix(path)) - return false; - - hecl::ProjectPath asBlend; - if (path.getPathType() == hecl::ProjectPath::Type::Glob) - asBlend = path.getWithExtension(_SYS_STR(".blend"), true); - else - asBlend = path; - - if (hecl::IsPathBlend(asBlend)) - { - hecl::blender::BlendType type = hecl::blender::GetBlendType(asBlend.getAbsolutePath()); - if (type != hecl::blender::BlendType::None) - return cookPass < 0 || - (cookPass == 0 && type == hecl::blender::BlendType::Mesh) || // CMDL only - (cookPass == 1 && type != hecl::blender::BlendType::Mesh); // Non-CMDL only - return false; - } - - /* Non-CMDLs shall not pass */ - if (cookPass == 0) - return false; - - if (hecl::IsPathPNG(path)) - { - return true; - } - else if (hecl::IsPathYAML(path)) - { - athena::io::FileReader reader(path.getAbsolutePath()); - bool retval = validateYAMLDNAType(reader); - return retval; - } - else if (IsPathAudioGroup(path)) - { - return true; - } - else if (IsPathSong(path)) - { - return true; - } +bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector& reps) { + m_disc = nod::OpenDiscFromImage(info.srcpath, m_isWii); + if (!m_disc) return false; + const char* gameID = m_disc->getHeader().m_gameID; + + if (!memcmp(gameID, "R3O", 3)) { + std::srand(std::time(0)); + int r = std::rand() % MomErrCount; + Log.report(logvisor::Fatal, MomErr[r]); + } + + m_standalone = true; + if (m_isWii && (!memcmp(gameID, "R3M", 3) || !memcmp(gameID, "R3I", 3) || !memcmp(gameID, "R32", 3))) + m_standalone = false; + + if (m_standalone && !checkStandaloneID(gameID)) + return false; + + char region = m_disc->getHeader().m_gameID[3]; + const hecl::SystemString* regstr = ®NONE; + switch (region) { + case 'E': + regstr = ®E; + break; + case 'J': + regstr = ®J; + break; + case 'P': + regstr = ®P; + break; + } + + if (m_standalone) + return checkFromStandaloneDisc(*m_disc, *regstr, info.extractArgs, reps); + else + return checkFromTrilogyDisc(*m_disc, *regstr, info.extractArgs, reps); +} + +void SpecBase::doExtract(const ExtractPassInfo& info, const hecl::MultiProgressPrinter& progress) { + setThreadProject(); + DataSpec::g_curSpec.reset(this); + if (!Blender::BuildMasterShader(m_masterShader)) + Log.report(logvisor::Fatal, "Unable to build master shader blend"); + if (m_isWii) { + /* Extract root files for repacking later */ + hecl::ProjectPath outDir(m_project.getProjectWorkingPath(), _SYS_STR("out")); + outDir.makeDirChain(true); + nod::ExtractionContext ctx = {info.force, nullptr}; + + if (!m_standalone) { + progress.print(_SYS_STR("Trilogy Files"), _SYS_STR(""), 0.0); + nod::IPartition* data = m_disc->getDataPartition(); + const nod::Node& root = data->getFSTRoot(); + for (const nod::Node& child : root) + if (child.getKind() == nod::Node::Kind::File) + child.extractToDirectory(outDir.getAbsolutePath(), ctx); + progress.print(_SYS_STR("Trilogy Files"), _SYS_STR(""), 1.0); + } + } + extractFromDisc(*m_disc, info.force, progress); +} + +static bool IsPathAudioGroup(const hecl::ProjectPath& path) { + return (path.getPathType() == hecl::ProjectPath::Type::Directory && + hecl::ProjectPath(path, _SYS_STR("!project.yaml")).isFile() && + hecl::ProjectPath(path, _SYS_STR("!pool.yaml")).isFile()); +} + +static bool IsPathSong(const hecl::ProjectPath& path) { + if (path.getPathType() != hecl::ProjectPath::Type::Glob || !path.getWithExtension(_SYS_STR(".mid"), true).isFile() || + !path.getWithExtension(_SYS_STR(".yaml"), true).isFile()) { + if (path.isFile() && !hecl::StrCmp(_SYS_STR("mid"), path.getLastComponentExt().data()) && + path.getWithExtension(_SYS_STR(".yaml"), true).isFile()) + return true; + return false; + } + return true; +} + +bool SpecBase::canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok, int cookPass) { + if (!checkPathPrefix(path)) + return false; + + hecl::ProjectPath asBlend; + if (path.getPathType() == hecl::ProjectPath::Type::Glob) + asBlend = path.getWithExtension(_SYS_STR(".blend"), true); + else + asBlend = path; + + if (hecl::IsPathBlend(asBlend)) { + hecl::blender::BlendType type = hecl::blender::GetBlendType(asBlend.getAbsolutePath()); + if (type != hecl::blender::BlendType::None) + return cookPass < 0 || (cookPass == 0 && type == hecl::blender::BlendType::Mesh) || // CMDL only + (cookPass == 1 && type != hecl::blender::BlendType::Mesh); // Non-CMDL only + return false; + } + + /* Non-CMDLs shall not pass */ + if (cookPass == 0) + return false; + + if (hecl::IsPathPNG(path)) { + return true; + } else if (hecl::IsPathYAML(path)) { + athena::io::FileReader reader(path.getAbsolutePath()); + bool retval = validateYAMLDNAType(reader); + return retval; + } else if (IsPathAudioGroup(path)) { + return true; + } else if (IsPathSong(path)) { + return true; + } + return false; } const hecl::Database::DataSpecEntry* SpecBase::overrideDataSpec(const hecl::ProjectPath& path, const hecl::Database::DataSpecEntry* oldEntry, - hecl::blender::Token& btok) const -{ - if (!checkPathPrefix(path)) - return nullptr; + hecl::blender::Token& btok) const { + if (!checkPathPrefix(path)) + return nullptr; - hecl::ProjectPath asBlend; - if (path.getPathType() == hecl::ProjectPath::Type::Glob) - asBlend = path.getWithExtension(_SYS_STR(".blend"), true); - else - asBlend = path; + hecl::ProjectPath asBlend; + if (path.getPathType() == hecl::ProjectPath::Type::Glob) + asBlend = path.getWithExtension(_SYS_STR(".blend"), true); + else + asBlend = path; - if (hecl::IsPathBlend(asBlend)) - { - if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CSKR")) || - hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".ANIM"))) - return oldEntry; + if (hecl::IsPathBlend(asBlend)) { + if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CSKR")) || + hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".ANIM"))) + return oldEntry; - hecl::blender::BlendType type = hecl::blender::GetBlendType(asBlend.getAbsolutePath()); - if (type == hecl::blender::BlendType::None) - { - Log.report(logvisor::Error, _SYS_STR("unable to cook '%s'"), - path.getAbsolutePath().data()); - return nullptr; - } - if (type == hecl::blender::BlendType::Mesh || - type == hecl::blender::BlendType::Area) - return oldEntry; + hecl::blender::BlendType type = hecl::blender::GetBlendType(asBlend.getAbsolutePath()); + if (type == hecl::blender::BlendType::None) { + Log.report(logvisor::Error, _SYS_STR("unable to cook '%s'"), path.getAbsolutePath().data()); + return nullptr; } - else if (hecl::IsPathPNG(path)) - { - return oldEntry; - } - return &getOriginalSpec(); + if (type == hecl::blender::BlendType::Mesh || type == hecl::blender::BlendType::Area) + return oldEntry; + } else if (hecl::IsPathPNG(path)) { + return oldEntry; + } + return &getOriginalSpec(); } -void SpecBase::doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath, - bool fast, hecl::blender::Token& btok, FCookProgress progress) -{ - cookedPath.makeDirChain(false); - DataSpec::g_curSpec.reset(this); +void SpecBase::doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath, bool fast, + hecl::blender::Token& btok, FCookProgress progress) { + cookedPath.makeDirChain(false); + DataSpec::g_curSpec.reset(this); - hecl::ProjectPath asBlend; - if (path.getPathType() == hecl::ProjectPath::Type::Glob) - asBlend = path.getWithExtension(_SYS_STR(".blend"), true); - else - asBlend = path; + hecl::ProjectPath asBlend; + if (path.getPathType() == hecl::ProjectPath::Type::Glob) + asBlend = path.getWithExtension(_SYS_STR(".blend"), true); + else + asBlend = path; - if (hecl::IsPathBlend(asBlend)) - { - hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.openBlend(asBlend)) - return; - switch (conn.getBlendType()) - { - case hecl::blender::BlendType::Mesh: - { - hecl::blender::DataStream ds = conn.beginData(); - cookMesh(cookedPath, path, ds, fast, btok, progress); - break; - } - case hecl::blender::BlendType::ColMesh: - { - hecl::blender::DataStream ds = conn.beginData(); - cookColMesh(cookedPath, path, ds, fast, btok, progress); - break; - } - case hecl::blender::BlendType::PathMesh: - { - hecl::blender::DataStream ds = conn.beginData(); - cookPathMesh(cookedPath, path, ds, fast, btok, progress); - break; - } - case hecl::blender::BlendType::Actor: - { - hecl::blender::DataStream ds = conn.beginData(); - cookActor(cookedPath, path, ds, fast, btok, progress); - break; - } - case hecl::blender::BlendType::Area: - { - hecl::blender::DataStream ds = conn.beginData(); - cookArea(cookedPath, path, ds, fast, btok, progress); - break; - } - case hecl::blender::BlendType::World: - { - hecl::blender::DataStream ds = conn.beginData(); - cookWorld(cookedPath, path, ds, fast, btok, progress); - break; - } - case hecl::blender::BlendType::Frame: - { - hecl::blender::DataStream ds = conn.beginData(); - cookGuiFrame(cookedPath, path, ds, btok, progress); - break; - } - case hecl::blender::BlendType::MapArea: - { - hecl::blender::DataStream ds = conn.beginData(); - cookMapArea(cookedPath, path, ds, btok, progress); - break; - } - case hecl::blender::BlendType::MapUniverse: - { - hecl::blender::DataStream ds = conn.beginData(); - cookMapUniverse(cookedPath, path, ds, btok, progress); - break; - } - default: break; - } - } - else if (hecl::IsPathPNG(path)) - { - if (m_pc) - TXTR::CookPC(path, cookedPath); - else - TXTR::Cook(path, cookedPath); - } - else if (hecl::IsPathYAML(path)) - { - athena::io::FileReader reader(path.getAbsolutePath()); - cookYAML(cookedPath, path, reader, progress); - } - else if (IsPathAudioGroup(path)) - { - cookAudioGroup(cookedPath, path, progress); - } - else if (IsPathSong(path)) - { - cookSong(cookedPath, path, progress); - } -} - -void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, - std::vector& pathsOut, - hecl::blender::Token& btok, - int charIdx) -{ + if (hecl::IsPathBlend(asBlend)) { hecl::blender::Connection& conn = btok.getBlenderConnection(); - if (!conn.openBlend(in)) - return; - switch (conn.getBlendType()) - { - case hecl::blender::BlendType::Mesh: - { - hecl::blender::DataStream ds = conn.beginData(); - std::vector texs = ds.getTextures(); - for (const hecl::ProjectPath& tex : texs) - pathsOut.push_back(tex); - break; + if (!conn.openBlend(asBlend)) + return; + switch (conn.getBlendType()) { + case hecl::blender::BlendType::Mesh: { + hecl::blender::DataStream ds = conn.beginData(); + cookMesh(cookedPath, path, ds, fast, btok, progress); + break; } - case hecl::blender::BlendType::Actor: - { - hecl::ProjectPath asGlob = in.getWithExtension(_SYS_STR(".*"), true); - hecl::blender::DataStream ds = conn.beginData(); - hecl::blender::Actor actor = ds.compileActorCharacterOnly(); - auto actNames = ds.getActionNames(); - ds.close(); - - auto doSubtype = [&](Actor::Subtype& sub) - { - if (sub.armature >= 0) - { - if (hecl::IsPathBlend(sub.mesh)) - { - flattenDependenciesBlend(sub.mesh, pathsOut, btok); - pathsOut.push_back(sub.mesh); - } - - hecl::SystemStringConv chSysName(sub.name); - pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _SYS_STR(".CSKR"))); - - const auto& arm = actor.armatures[sub.armature]; - hecl::SystemStringConv armSysName(arm.name); - pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(armSysName.sys_str()) + _SYS_STR(".CINF"))); - for (const auto& overlay : sub.overlayMeshes) - { - hecl::SystemStringConv ovelaySys(overlay.first); - if (hecl::IsPathBlend(overlay.second)) - { - flattenDependenciesBlend(overlay.second, pathsOut, btok); - pathsOut.push_back(overlay.second); - } - pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _SYS_STR('.') + - ovelaySys.c_str() + _SYS_STR(".CSKR"))); - } - } - }; - if (charIdx < 0) - for (auto& sub : actor.subtypes) - doSubtype(sub); - else if (charIdx < actor.subtypes.size()) - doSubtype(actor.subtypes[charIdx]); - - for (const Actor::Attachment& att : actor.attachments) - { - if (hecl::IsPathBlend(att.mesh)) - { - flattenDependenciesBlend(att.mesh, pathsOut, btok); - pathsOut.push_back(att.mesh); - } - - hecl::SystemStringConv chSysName(att.name); - pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(_SYS_STR("ATTACH.")) + - chSysName.c_str() + _SYS_STR(".CSKR"))); - - if (att.armature >= 0) - { - const auto& arm = actor.armatures[att.armature]; - hecl::SystemStringConv armSysName(arm.name); - pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(armSysName.sys_str()) + _SYS_STR(".CINF"))); - } - } - - for (const auto& act : actNames) - { - hecl::SystemStringConv actSysName(act); - pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(actSysName.sys_str()) + _SYS_STR(".ANIM"))); - hecl::ProjectPath evntPath = asGlob.ensureAuxInfo(hecl::SystemStringView{}).getWithExtension( - hecl::SysFormat(_SYS_STR(".%s.evnt.yaml"), actSysName.c_str()).c_str(), true); - if (evntPath.isFile()) - pathsOut.push_back(evntPath); - } - - hecl::ProjectPath yamlPath = asGlob.getWithExtension(_SYS_STR(".yaml"), true); - if (yamlPath.isFile()) - { - athena::io::FileReader reader(yamlPath.getAbsolutePath()); - flattenDependenciesANCSYAML(reader, pathsOut, charIdx); - } - - pathsOut.push_back(asGlob); - return; + case hecl::blender::BlendType::ColMesh: { + hecl::blender::DataStream ds = conn.beginData(); + cookColMesh(cookedPath, path, ds, fast, btok, progress); + break; } - case hecl::blender::BlendType::Area: - { - hecl::blender::DataStream ds = conn.beginData(); - std::vector texs = ds.getTextures(); - for (const hecl::ProjectPath& tex : texs) - pathsOut.push_back(tex); - break; + case hecl::blender::BlendType::PathMesh: { + hecl::blender::DataStream ds = conn.beginData(); + cookPathMesh(cookedPath, path, ds, fast, btok, progress); + break; } - default: break; + case hecl::blender::BlendType::Actor: { + hecl::blender::DataStream ds = conn.beginData(); + cookActor(cookedPath, path, ds, fast, btok, progress); + break; } -} - -void SpecBase::flattenDependencies(const hecl::ProjectPath& path, - std::vector& pathsOut, - hecl::blender::Token& btok, - int charIdx) -{ - DataSpec::g_curSpec.reset(this); - g_ThreadBlenderToken.reset(&btok); - - hecl::ProjectPath asBlend; - if (path.getPathType() == hecl::ProjectPath::Type::Glob) - asBlend = path.getWithExtension(_SYS_STR(".blend"), true); + case hecl::blender::BlendType::Area: { + hecl::blender::DataStream ds = conn.beginData(); + cookArea(cookedPath, path, ds, fast, btok, progress); + break; + } + case hecl::blender::BlendType::World: { + hecl::blender::DataStream ds = conn.beginData(); + cookWorld(cookedPath, path, ds, fast, btok, progress); + break; + } + case hecl::blender::BlendType::Frame: { + hecl::blender::DataStream ds = conn.beginData(); + cookGuiFrame(cookedPath, path, ds, btok, progress); + break; + } + case hecl::blender::BlendType::MapArea: { + hecl::blender::DataStream ds = conn.beginData(); + cookMapArea(cookedPath, path, ds, btok, progress); + break; + } + case hecl::blender::BlendType::MapUniverse: { + hecl::blender::DataStream ds = conn.beginData(); + cookMapUniverse(cookedPath, path, ds, btok, progress); + break; + } + default: + break; + } + } else if (hecl::IsPathPNG(path)) { + if (m_pc) + TXTR::CookPC(path, cookedPath); else - asBlend = path; + TXTR::Cook(path, cookedPath); + } else if (hecl::IsPathYAML(path)) { + athena::io::FileReader reader(path.getAbsolutePath()); + cookYAML(cookedPath, path, reader, progress); + } else if (IsPathAudioGroup(path)) { + cookAudioGroup(cookedPath, path, progress); + } else if (IsPathSong(path)) { + cookSong(cookedPath, path, progress); + } +} - if (hecl::IsPathBlend(asBlend)) - { - flattenDependenciesBlend(asBlend, pathsOut, btok, charIdx); - } - else if (hecl::IsPathYAML(path)) - { - athena::io::FileReader reader(path.getAbsolutePath()); - flattenDependenciesYAML(reader, pathsOut); +void SpecBase::flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector& pathsOut, + hecl::blender::Token& btok, int charIdx) { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + if (!conn.openBlend(in)) + return; + switch (conn.getBlendType()) { + case hecl::blender::BlendType::Mesh: { + hecl::blender::DataStream ds = conn.beginData(); + std::vector texs = ds.getTextures(); + for (const hecl::ProjectPath& tex : texs) + pathsOut.push_back(tex); + break; + } + case hecl::blender::BlendType::Actor: { + hecl::ProjectPath asGlob = in.getWithExtension(_SYS_STR(".*"), true); + hecl::blender::DataStream ds = conn.beginData(); + hecl::blender::Actor actor = ds.compileActorCharacterOnly(); + auto actNames = ds.getActionNames(); + ds.close(); + + auto doSubtype = [&](Actor::Subtype& sub) { + if (sub.armature >= 0) { + if (hecl::IsPathBlend(sub.mesh)) { + flattenDependenciesBlend(sub.mesh, pathsOut, btok); + pathsOut.push_back(sub.mesh); + } + + hecl::SystemStringConv chSysName(sub.name); + pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _SYS_STR(".CSKR"))); + + const auto& arm = actor.armatures[sub.armature]; + hecl::SystemStringConv armSysName(arm.name); + pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(armSysName.sys_str()) + _SYS_STR(".CINF"))); + for (const auto& overlay : sub.overlayMeshes) { + hecl::SystemStringConv ovelaySys(overlay.first); + if (hecl::IsPathBlend(overlay.second)) { + flattenDependenciesBlend(overlay.second, pathsOut, btok); + pathsOut.push_back(overlay.second); + } + pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(chSysName.sys_str()) + _SYS_STR('.') + + ovelaySys.c_str() + _SYS_STR(".CSKR"))); + } + } + }; + if (charIdx < 0) + for (auto& sub : actor.subtypes) + doSubtype(sub); + else if (charIdx < actor.subtypes.size()) + doSubtype(actor.subtypes[charIdx]); + + for (const Actor::Attachment& att : actor.attachments) { + if (hecl::IsPathBlend(att.mesh)) { + flattenDependenciesBlend(att.mesh, pathsOut, btok); + pathsOut.push_back(att.mesh); + } + + hecl::SystemStringConv chSysName(att.name); + pathsOut.push_back( + asGlob.ensureAuxInfo(hecl::SystemString(_SYS_STR("ATTACH.")) + chSysName.c_str() + _SYS_STR(".CSKR"))); + + if (att.armature >= 0) { + const auto& arm = actor.armatures[att.armature]; + hecl::SystemStringConv armSysName(arm.name); + pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(armSysName.sys_str()) + _SYS_STR(".CINF"))); + } } - pathsOut.push_back(path); + for (const auto& act : actNames) { + hecl::SystemStringConv actSysName(act); + pathsOut.push_back(asGlob.ensureAuxInfo(hecl::SystemString(actSysName.sys_str()) + _SYS_STR(".ANIM"))); + hecl::ProjectPath evntPath = + asGlob.ensureAuxInfo(hecl::SystemStringView{}) + .getWithExtension(hecl::SysFormat(_SYS_STR(".%s.evnt.yaml"), actSysName.c_str()).c_str(), true); + if (evntPath.isFile()) + pathsOut.push_back(evntPath); + } + + hecl::ProjectPath yamlPath = asGlob.getWithExtension(_SYS_STR(".yaml"), true); + if (yamlPath.isFile()) { + athena::io::FileReader reader(yamlPath.getAbsolutePath()); + flattenDependenciesANCSYAML(reader, pathsOut, charIdx); + } + + pathsOut.push_back(asGlob); + return; + } + case hecl::blender::BlendType::Area: { + hecl::blender::DataStream ds = conn.beginData(); + std::vector texs = ds.getTextures(); + for (const hecl::ProjectPath& tex : texs) + pathsOut.push_back(tex); + break; + } + default: + break; + } } -void SpecBase::flattenDependencies(const UniqueID32& id, std::vector& pathsOut, int charIdx) -{ - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); - if (path) - flattenDependencies(path, pathsOut, *g_ThreadBlenderToken.get(), charIdx); +void SpecBase::flattenDependencies(const hecl::ProjectPath& path, std::vector& pathsOut, + hecl::blender::Token& btok, int charIdx) { + DataSpec::g_curSpec.reset(this); + g_ThreadBlenderToken.reset(&btok); + + hecl::ProjectPath asBlend; + if (path.getPathType() == hecl::ProjectPath::Type::Glob) + asBlend = path.getWithExtension(_SYS_STR(".blend"), true); + else + asBlend = path; + + if (hecl::IsPathBlend(asBlend)) { + flattenDependenciesBlend(asBlend, pathsOut, btok, charIdx); + } else if (hecl::IsPathYAML(path)) { + athena::io::FileReader reader(path.getAbsolutePath()); + flattenDependenciesYAML(reader, pathsOut); + } + + pathsOut.push_back(path); } -void SpecBase::flattenDependencies(const UniqueID64& id, std::vector& pathsOut, int charIdx) -{ - hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); - if (path) - flattenDependencies(path, pathsOut, *g_ThreadBlenderToken.get(), charIdx); +void SpecBase::flattenDependencies(const UniqueID32& id, std::vector& pathsOut, int charIdx) { + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); + if (path) + flattenDependencies(path, pathsOut, *g_ThreadBlenderToken.get(), charIdx); } -bool SpecBase::canPackage(const hecl::ProjectPath& path) -{ - auto components = path.getPathComponents(); - if (components.size() <= 1) - return false; - return path.isFile() || path.isDirectory(); +void SpecBase::flattenDependencies(const UniqueID64& id, std::vector& pathsOut, int charIdx) { + hecl::ProjectPath path = UniqueIDBridge::TranslatePakIdToPath(id); + if (path) + flattenDependencies(path, pathsOut, *g_ThreadBlenderToken.get(), charIdx); +} + +bool SpecBase::canPackage(const hecl::ProjectPath& path) { + auto components = path.getPathComponents(); + if (components.size() <= 1) + return false; + return path.isFile() || path.isDirectory(); } void SpecBase::recursiveBuildResourceList(std::vector& listOut, std::unordered_set& addedTags, - const hecl::ProjectPath& path, - hecl::blender::Token& btok) -{ - hecl::DirectoryEnumerator dEnum(path.getAbsolutePath(), - hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true); - for (const auto& ent : dEnum) - { - hecl::ProjectPath childPath(path, ent.m_name); - if (ent.m_isDir) - { - if (hecl::ProjectPath(childPath, _SYS_STR("!project.yaml")).isFile() && - hecl::ProjectPath(childPath, _SYS_STR("!pool.yaml")).isFile()) - { - /* Handle AudioGroup case */ - if (urde::SObjectTag tag = tagFromPath(childPath, btok)) - { - if (addedTags.find(tag) != addedTags.end()) - continue; - addedTags.insert(tag); - listOut.push_back(tag); - } - continue; - } + const hecl::ProjectPath& path, hecl::blender::Token& btok) { + hecl::DirectoryEnumerator dEnum(path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, + false, true); + for (const auto& ent : dEnum) { + hecl::ProjectPath childPath(path, ent.m_name); + if (ent.m_isDir) { + if (hecl::ProjectPath(childPath, _SYS_STR("!project.yaml")).isFile() && + hecl::ProjectPath(childPath, _SYS_STR("!pool.yaml")).isFile()) { + /* Handle AudioGroup case */ + if (urde::SObjectTag tag = tagFromPath(childPath, btok)) { + if (addedTags.find(tag) != addedTags.end()) + continue; + addedTags.insert(tag); + listOut.push_back(tag); + } + continue; + } - recursiveBuildResourceList(listOut, addedTags, childPath, btok); - } - else - { - std::vector subPaths; - flattenDependencies(childPath, subPaths, btok); - for (const auto& subPath : subPaths) - { - if (urde::SObjectTag tag = tagFromPath(subPath, btok)) - { - if (addedTags.find(tag) != addedTags.end()) - continue; - addedTags.insert(tag); - listOut.push_back(tag); - } - } + recursiveBuildResourceList(listOut, addedTags, childPath, btok); + } else { + std::vector subPaths; + flattenDependencies(childPath, subPaths, btok); + for (const auto& subPath : subPaths) { + if (urde::SObjectTag tag = tagFromPath(subPath, btok)) { + if (addedTags.find(tag) != addedTags.end()) + continue; + addedTags.insert(tag); + listOut.push_back(tag); } + } } + } } void SpecBase::copyBuildListData(std::vector>& fileIndex, const std::vector& buildList, - const hecl::Database::DataSpecEntry* entry, - bool fast, const hecl::MultiProgressPrinter& progress, - athena::io::FileWriter& pakOut, - const std::unordered_map>& mlvlData) -{ - fileIndex.reserve(buildList.size()); - int loadIdx = 0; - for (const auto& tag : buildList) - { - hecl::SystemString str = hecl::SysFormat(_SYS_STR("Copying %.4") FMT_CSTR_SYS " %08X", - tag.type.getChars(), (unsigned int)tag.id.Value()); - progress.print(str.c_str(), nullptr, ++loadIdx / float(buildList.size())); + const hecl::Database::DataSpecEntry* entry, bool fast, + const hecl::MultiProgressPrinter& progress, athena::io::FileWriter& pakOut, + const std::unordered_map>& mlvlData) { + fileIndex.reserve(buildList.size()); + int loadIdx = 0; + for (const auto& tag : buildList) { + hecl::SystemString str = hecl::SysFormat(_SYS_STR("Copying %.4") FMT_CSTR_SYS " %08X", tag.type.getChars(), + (unsigned int)tag.id.Value()); + progress.print(str.c_str(), nullptr, ++loadIdx / float(buildList.size())); - fileIndex.emplace_back(); - auto& thisIdx = fileIndex.back(); + fileIndex.emplace_back(); + auto& thisIdx = fileIndex.back(); - if (tag.type == FOURCC('MLVL')) - { - auto search = mlvlData.find(tag.id); - if (search == mlvlData.end()) - Log.report(logvisor::Fatal, _SYS_STR("Unable to find MLVL %08X"), tag.id.Value()); + if (tag.type == FOURCC('MLVL')) { + auto search = mlvlData.find(tag.id); + if (search == mlvlData.end()) + Log.report(logvisor::Fatal, _SYS_STR("Unable to find MLVL %08X"), tag.id.Value()); - std::get<0>(thisIdx) = pakOut.position(); - std::get<1>(thisIdx) = ROUND_UP_32(search->second.size()); - std::get<2>(thisIdx) = false; - pakOut.writeUBytes(search->second.data(), search->second.size()); - for (atUint64 i = search->second.size() ; i < std::get<1>(thisIdx) ; ++i) - pakOut.writeUByte(0xff); + std::get<0>(thisIdx) = pakOut.position(); + std::get<1>(thisIdx) = ROUND_UP_32(search->second.size()); + std::get<2>(thisIdx) = false; + pakOut.writeUBytes(search->second.data(), search->second.size()); + for (atUint64 i = search->second.size(); i < std::get<1>(thisIdx); ++i) + pakOut.writeUByte(0xff); - continue; - } - - hecl::ProjectPath path = pathFromTag(tag); - hecl::ProjectPath cooked = getCookedPath(path, true); - athena::io::FileReader r(cooked.getAbsolutePath()); - if (r.hasError()) - Log.report(logvisor::Fatal, _SYS_STR("Unable to open resource %s"), cooked.getRelativePath().data()); - atUint64 size = r.length(); - auto data = r.readUBytes(size); - auto compData = compressPakData(tag, data.get(), size); - if (compData.first) - { - std::get<0>(thisIdx) = pakOut.position(); - std::get<1>(thisIdx) = ROUND_UP_32(compData.second + 4); - std::get<2>(thisIdx) = true; - pakOut.writeUint32Big(atUint32(size)); - pakOut.writeUBytes(compData.first.get(), compData.second); - for (atUint64 i = compData.second + 4 ; i < std::get<1>(thisIdx) ; ++i) - pakOut.writeUByte(0xff); - } - else - { - std::get<0>(thisIdx) = pakOut.position(); - std::get<1>(thisIdx) = ROUND_UP_32(size); - std::get<2>(thisIdx) = false; - pakOut.writeUBytes(data.get(), size); - for (atUint64 i = size ; i < std::get<1>(thisIdx) ; ++i) - pakOut.writeUByte(0xff); - } + continue; } - progress.startNewLine(); + + hecl::ProjectPath path = pathFromTag(tag); + hecl::ProjectPath cooked = getCookedPath(path, true); + athena::io::FileReader r(cooked.getAbsolutePath()); + if (r.hasError()) + Log.report(logvisor::Fatal, _SYS_STR("Unable to open resource %s"), cooked.getRelativePath().data()); + atUint64 size = r.length(); + auto data = r.readUBytes(size); + auto compData = compressPakData(tag, data.get(), size); + if (compData.first) { + std::get<0>(thisIdx) = pakOut.position(); + std::get<1>(thisIdx) = ROUND_UP_32(compData.second + 4); + std::get<2>(thisIdx) = true; + pakOut.writeUint32Big(atUint32(size)); + pakOut.writeUBytes(compData.first.get(), compData.second); + for (atUint64 i = compData.second + 4; i < std::get<1>(thisIdx); ++i) + pakOut.writeUByte(0xff); + } else { + std::get<0>(thisIdx) = pakOut.position(); + std::get<1>(thisIdx) = ROUND_UP_32(size); + std::get<2>(thisIdx) = false; + pakOut.writeUBytes(data.get(), size); + for (atUint64 i = size; i < std::get<1>(thisIdx); ++i) + pakOut.writeUByte(0xff); + } + } + progress.startNewLine(); } -void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::DataSpecEntry* entry, - bool fast, hecl::blender::Token& btok, const hecl::MultiProgressPrinter& progress, - hecl::ClientProcess* cp) -{ - /* Prepare complete resource index */ - if (!m_backgroundRunning && m_tagToPath.empty()) - beginBackgroundIndex(); - waitForIndexComplete(); +void SpecBase::doPackage(const hecl::ProjectPath& path, const hecl::Database::DataSpecEntry* entry, bool fast, + hecl::blender::Token& btok, const hecl::MultiProgressPrinter& progress, + hecl::ClientProcess* cp) { + /* Prepare complete resource index */ + if (!m_backgroundRunning && m_tagToPath.empty()) + beginBackgroundIndex(); + waitForIndexComplete(); - /* Name pak based on root-relative components */ - auto components = path.getWithExtension(_SYS_STR(""), true).getPathComponents(); - if (components.size() <= 1) - return; - hecl::ProjectPath outPath; - if (hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files/") + components[0]).isDirectory()) - outPath.assign(m_project.getProjectWorkingPath(), - _SYS_STR("out/files/") + components[0] + _SYS_STR("/") + components[1] + entry->m_pakExt.data()); - else - outPath.assign(m_project.getProjectWorkingPath(), - _SYS_STR("out/files/") + components[1] + entry->m_pakExt.data()); - outPath.makeDirChain(false); + /* Name pak based on root-relative components */ + auto components = path.getWithExtension(_SYS_STR(""), true).getPathComponents(); + if (components.size() <= 1) + return; + hecl::ProjectPath outPath; + if (hecl::ProjectPath(m_project.getProjectWorkingPath(), _SYS_STR("out/files/") + components[0]).isDirectory()) + outPath.assign(m_project.getProjectWorkingPath(), + _SYS_STR("out/files/") + components[0] + _SYS_STR("/") + components[1] + entry->m_pakExt.data()); + else + outPath.assign(m_project.getProjectWorkingPath(), _SYS_STR("out/files/") + components[1] + entry->m_pakExt.data()); + outPath.makeDirChain(false); - /* Output file */ - athena::io::FileWriter pakOut(outPath.getAbsolutePath()); - std::vector buildList; - atUint64 resTableOffset = 0; - std::unordered_map> mlvlData; + /* Output file */ + athena::io::FileWriter pakOut(outPath.getAbsolutePath()); + std::vector buildList; + atUint64 resTableOffset = 0; + std::unordered_map> mlvlData; - if (path.getPathType() == hecl::ProjectPath::Type::File && - !hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!world.blend"))) /* World PAK */ - { - /* Force-cook MLVL and write resource list structure */ - m_project.cookPath(path, progress, false, true, fast, entry, cp); - if (cp) - cp->waitUntilComplete(); - progress.startNewLine(); - hecl::ProjectPath cooked = getCookedPath(path, true); - buildWorldPakList(path, cooked, btok, pakOut, buildList, resTableOffset, mlvlData); - if (int64_t rem = pakOut.position() % 32) - for (int64_t i=0 ; i<32-rem ; ++i) - pakOut.writeUByte(0xff); - } - else if (path.getPathType() == hecl::ProjectPath::Type::Directory) /* General PAK */ - { - /* Build resource list */ - std::unordered_set addedTags; - recursiveBuildResourceList(buildList, addedTags, path, btok); - std::vector> nameList; - - /* Build name list */ - for (const auto& item : buildList) - { - auto search = m_catalogTagToNames.find(item); - if (search != m_catalogTagToNames.end()) - for (const auto& name : search->second) - nameList.emplace_back(item, name); - } - - /* Write resource list structure */ - buildPakList(btok, pakOut, buildList, nameList, resTableOffset); - if (int64_t rem = pakOut.position() % 32) - for (int64_t i=0 ; i<32-rem ; ++i) - pakOut.writeUByte(0xff); - } - else if (path.getPathType() == hecl::ProjectPath::Type::File) /* One-file General PAK */ - { - /* Build resource list */ - std::vector subPaths; - flattenDependencies(path, subPaths, btok); - std::unordered_set addedTags; - std::vector> nameList; - for (const auto& subPath : subPaths) - { - if (urde::SObjectTag tag = tagFromPath(subPath, btok)) - { - if (addedTags.find(tag) != addedTags.end()) - continue; - addedTags.insert(tag); - buildList.push_back(tag); - } - } - - /* Build name list */ - for (const auto& item : buildList) - { - auto search = m_catalogTagToNames.find(item); - if (search != m_catalogTagToNames.end()) - for (const auto& name : search->second) - nameList.emplace_back(item, name); - } - - /* Write resource list structure */ - buildPakList(btok, pakOut, buildList, nameList, resTableOffset); - if (int64_t rem = pakOut.position() % 32) - for (int64_t i=0 ; i<32-rem ; ++i) - pakOut.writeUByte(0xff); - } - - /* Async cook resource list if using ClientProcess */ + if (path.getPathType() == hecl::ProjectPath::Type::File && + !hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!world.blend"))) /* World PAK */ + { + /* Force-cook MLVL and write resource list structure */ + m_project.cookPath(path, progress, false, true, fast, entry, cp); if (cp) - { - Log.report(logvisor::Info, _SYS_STR("Validating resources")); - progress.setMainIndeterminate(true); - for (int i=0 ; im_numCookPasses ; ++i) - { - std::unordered_set addedTags; - addedTags.reserve(buildList.size()); - for (auto& tag : buildList) - { - if (addedTags.find(tag) != addedTags.end()) - continue; - addedTags.insert(tag); + cp->waitUntilComplete(); + progress.startNewLine(); + hecl::ProjectPath cooked = getCookedPath(path, true); + buildWorldPakList(path, cooked, btok, pakOut, buildList, resTableOffset, mlvlData); + if (int64_t rem = pakOut.position() % 32) + for (int64_t i = 0; i < 32 - rem; ++i) + pakOut.writeUByte(0xff); + } else if (path.getPathType() == hecl::ProjectPath::Type::Directory) /* General PAK */ + { + /* Build resource list */ + std::unordered_set addedTags; + recursiveBuildResourceList(buildList, addedTags, path, btok); + std::vector> nameList; - hecl::ProjectPath depPath = pathFromTag(tag); - if (!depPath) - { - Log.report(logvisor::Fatal, _SYS_STR("Unable to resolve %.4s %08X"), - tag.type.getChars(), tag.id.Value()); - } - m_project.cookPath(depPath, progress, false, false, fast, entry, cp, i); - } + /* Build name list */ + for (const auto& item : buildList) { + auto search = m_catalogTagToNames.find(item); + if (search != m_catalogTagToNames.end()) + for (const auto& name : search->second) + nameList.emplace_back(item, name); + } + + /* Write resource list structure */ + buildPakList(btok, pakOut, buildList, nameList, resTableOffset); + if (int64_t rem = pakOut.position() % 32) + for (int64_t i = 0; i < 32 - rem; ++i) + pakOut.writeUByte(0xff); + } else if (path.getPathType() == hecl::ProjectPath::Type::File) /* One-file General PAK */ + { + /* Build resource list */ + std::vector subPaths; + flattenDependencies(path, subPaths, btok); + std::unordered_set addedTags; + std::vector> nameList; + for (const auto& subPath : subPaths) { + if (urde::SObjectTag tag = tagFromPath(subPath, btok)) { + if (addedTags.find(tag) != addedTags.end()) + continue; + addedTags.insert(tag); + buildList.push_back(tag); + } + } + + /* Build name list */ + for (const auto& item : buildList) { + auto search = m_catalogTagToNames.find(item); + if (search != m_catalogTagToNames.end()) + for (const auto& name : search->second) + nameList.emplace_back(item, name); + } + + /* Write resource list structure */ + buildPakList(btok, pakOut, buildList, nameList, resTableOffset); + if (int64_t rem = pakOut.position() % 32) + for (int64_t i = 0; i < 32 - rem; ++i) + pakOut.writeUByte(0xff); + } + + /* Async cook resource list if using ClientProcess */ + if (cp) { + Log.report(logvisor::Info, _SYS_STR("Validating resources")); + progress.setMainIndeterminate(true); + for (int i = 0; i < entry->m_numCookPasses; ++i) { + std::unordered_set addedTags; + addedTags.reserve(buildList.size()); + for (auto& tag : buildList) { + if (addedTags.find(tag) != addedTags.end()) + continue; + addedTags.insert(tag); + + hecl::ProjectPath depPath = pathFromTag(tag); + if (!depPath) { + Log.report(logvisor::Fatal, _SYS_STR("Unable to resolve %.4s %08X"), tag.type.getChars(), tag.id.Value()); } - progress.setMainIndeterminate(false); - cp->waitUntilComplete(); - progress.startNewLine(); + m_project.cookPath(depPath, progress, false, false, fast, entry, cp, i); + } } + progress.setMainIndeterminate(false); + cp->waitUntilComplete(); + progress.startNewLine(); + } - /* Write resource data and build file index */ - std::vector> fileIndex; - Log.report(logvisor::Info, _SYS_STR("Copying data into %s"), outPath.getRelativePath().data()); - copyBuildListData(fileIndex, buildList, entry, fast, progress, pakOut, mlvlData); + /* Write resource data and build file index */ + std::vector> fileIndex; + Log.report(logvisor::Info, _SYS_STR("Copying data into %s"), outPath.getRelativePath().data()); + copyBuildListData(fileIndex, buildList, entry, fast, progress, pakOut, mlvlData); - /* Write file index */ - writePakFileIndex(pakOut, buildList, fileIndex, resTableOffset); - pakOut.close(); + /* Write file index */ + writePakFileIndex(pakOut, buildList, fileIndex, resTableOffset); + pakOut.close(); } -void SpecBase::interruptCook() -{ - cancelBackgroundIndex(); -} +void SpecBase::interruptCook() { cancelBackgroundIndex(); } -hecl::ProjectPath SpecBase::getCookedPath(const hecl::ProjectPath& working, bool pcTarget) const -{ - const hecl::Database::DataSpecEntry* spec = &getOriginalSpec(); - if (pcTarget) - spec = overrideDataSpec(working, getDataSpecEntry(), hecl::blender::SharedBlenderToken); - if (!spec) - return {}; - return working.getCookedPath(*spec); -} - -static void PNGErr(png_structp png, png_const_charp msg) -{ - Log.report(logvisor::Error, msg); -} - -static void PNGWarn(png_structp png, png_const_charp msg) -{ - Log.report(logvisor::Warning, msg); -} - -static inline uint8_t Convert4To8(uint8_t v) -{ - /* Swizzle bits: 00001234 -> 12341234 */ - return (v << 4) | v; -} - -void SpecBase::extractRandomStaticEntropy(const uint8_t* buf, const hecl::ProjectPath& noAramPath) -{ - hecl::ProjectPath entropyPath(noAramPath, _SYS_STR("RandomStaticEntropy.png")); - hecl::ProjectPath catalogPath(noAramPath, _SYS_STR("!catalog.yaml")); - - if (FILE* fp = hecl::Fopen(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) - { - fprintf(fp, "RandomStaticEntropy: %s\n", entropyPath.getRelativePathUTF8().data()); - fclose(fp); - } - - FILE* fp = hecl::Fopen(entropyPath.getAbsolutePath().data(), _SYS_STR("wb")); - if (!fp) - { - Log.report(logvisor::Error, - _SYS_STR("Unable to open '%s' for writing"), - entropyPath.getAbsolutePath().data()); - return; - } - png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGErr, PNGWarn); - png_init_io(png, fp); - png_infop info = png_create_info_struct(png); - - png_text textStruct = {}; - textStruct.key = png_charp("urde_nomip"); - png_set_text(png, info, &textStruct, 1); - - png_set_IHDR(png, info, 1024, 512, 8, - PNG_COLOR_TYPE_GRAY_ALPHA, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_write_info(png, info); - - std::unique_ptr rowbuf(new uint8_t[1024*2]); - for (int y=0 ; y<512 ; ++y) - { - for (int x=0 ; x<1024 ; ++x) - { - uint8_t texel = buf[y*1024+x]; - rowbuf[x*2] = Convert4To8(texel >> 4 & 0xf); - rowbuf[x*2+1] = Convert4To8(texel & 0xf); - } - png_write_row(png, rowbuf.get()); - } - - png_write_end(png, info); - png_write_flush(png); - png_destroy_write_struct(&png, &info); - fclose(fp); -} - -void SpecBase::clearTagCache() -{ - m_tagToPath.clear(); - m_pathToTag.clear(); - m_catalogNameToTag.clear(); - m_catalogTagToNames.clear(); -} - -hecl::ProjectPath SpecBase::pathFromTag(const urde::SObjectTag& tag) const -{ - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); - auto search = m_tagToPath.find(tag); - if (search != m_tagToPath.cend()) - return search->second; +hecl::ProjectPath SpecBase::getCookedPath(const hecl::ProjectPath& working, bool pcTarget) const { + const hecl::Database::DataSpecEntry* spec = &getOriginalSpec(); + if (pcTarget) + spec = overrideDataSpec(working, getDataSpecEntry(), hecl::blender::SharedBlenderToken); + if (!spec) return {}; + return working.getCookedPath(*spec); } -urde::SObjectTag SpecBase::tagFromPath(const hecl::ProjectPath& path, - hecl::blender::Token& btok) const -{ - auto search = m_pathToTag.find(path.hash()); - if (search != m_pathToTag.cend()) - return search->second; - return buildTagFromPath(path, btok); +static void PNGErr(png_structp png, png_const_charp msg) { Log.report(logvisor::Error, msg); } + +static void PNGWarn(png_structp png, png_const_charp msg) { Log.report(logvisor::Warning, msg); } + +static inline uint8_t Convert4To8(uint8_t v) { + /* Swizzle bits: 00001234 -> 12341234 */ + return (v << 4) | v; } -bool SpecBase::waitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut) -{ - std::unique_lock lk(m_backgroundIndexMutex); - auto search = m_tagToPath.find(tag); - if (search == m_tagToPath.end()) - { - if (m_backgroundRunning) - { - while (m_backgroundRunning) - { - lk.unlock(); - std::this_thread::sleep_for(std::chrono::milliseconds(2)); - lk.lock(); - search = m_tagToPath.find(tag); - if (search != m_tagToPath.end()) - break; - } - if (search == m_tagToPath.end()) - return false; - } - else - return false; +void SpecBase::extractRandomStaticEntropy(const uint8_t* buf, const hecl::ProjectPath& noAramPath) { + hecl::ProjectPath entropyPath(noAramPath, _SYS_STR("RandomStaticEntropy.png")); + hecl::ProjectPath catalogPath(noAramPath, _SYS_STR("!catalog.yaml")); + + if (FILE* fp = hecl::Fopen(catalogPath.getAbsolutePath().data(), _SYS_STR("a"))) { + fprintf(fp, "RandomStaticEntropy: %s\n", entropyPath.getRelativePathUTF8().data()); + fclose(fp); + } + + FILE* fp = hecl::Fopen(entropyPath.getAbsolutePath().data(), _SYS_STR("wb")); + if (!fp) { + Log.report(logvisor::Error, _SYS_STR("Unable to open '%s' for writing"), entropyPath.getAbsolutePath().data()); + return; + } + png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGErr, PNGWarn); + png_init_io(png, fp); + png_infop info = png_create_info_struct(png); + + png_text textStruct = {}; + textStruct.key = png_charp("urde_nomip"); + png_set_text(png, info, &textStruct, 1); + + png_set_IHDR(png, info, 1024, 512, 8, PNG_COLOR_TYPE_GRAY_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + png_write_info(png, info); + + std::unique_ptr rowbuf(new uint8_t[1024 * 2]); + for (int y = 0; y < 512; ++y) { + for (int x = 0; x < 1024; ++x) { + uint8_t texel = buf[y * 1024 + x]; + rowbuf[x * 2] = Convert4To8(texel >> 4 & 0xf); + rowbuf[x * 2 + 1] = Convert4To8(texel & 0xf); } - lk.unlock(); - pathOut = &search->second; - return true; + png_write_row(png, rowbuf.get()); + } + + png_write_end(png, info); + png_write_flush(png); + png_destroy_write_struct(&png, &info); + fclose(fp); } -const urde::SObjectTag* SpecBase::getResourceIdByName(std::string_view name) const -{ - std::string lower(name); - std::transform(lower.cbegin(), lower.cend(), lower.begin(), tolower); - - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); - auto search = m_catalogNameToTag.find(lower); - if (search == m_catalogNameToTag.end()) - { - if (m_backgroundRunning) - { - while (m_backgroundRunning) - { - lk.unlock(); - std::this_thread::sleep_for(std::chrono::milliseconds(2)); - lk.lock(); - search = m_catalogNameToTag.find(lower); - if (search != m_catalogNameToTag.end()) - break; - } - if (search == m_catalogNameToTag.end()) - return nullptr; - } - else - return nullptr; - } - return &search->second; +void SpecBase::clearTagCache() { + m_tagToPath.clear(); + m_pathToTag.clear(); + m_catalogNameToTag.clear(); + m_catalogTagToNames.clear(); } -FourCC SpecBase::getResourceTypeById(urde::CAssetId id) const -{ - if (!id.IsValid()) +hecl::ProjectPath SpecBase::pathFromTag(const urde::SObjectTag& tag) const { + std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + auto search = m_tagToPath.find(tag); + if (search != m_tagToPath.cend()) + return search->second; + return {}; +} + +urde::SObjectTag SpecBase::tagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { + auto search = m_pathToTag.find(path.hash()); + if (search != m_pathToTag.cend()) + return search->second; + return buildTagFromPath(path, btok); +} + +bool SpecBase::waitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut) { + std::unique_lock lk(m_backgroundIndexMutex); + auto search = m_tagToPath.find(tag); + if (search == m_tagToPath.end()) { + if (m_backgroundRunning) { + while (m_backgroundRunning) { + lk.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + lk.lock(); + search = m_tagToPath.find(tag); + if (search != m_tagToPath.end()) + break; + } + if (search == m_tagToPath.end()) + return false; + } else + return false; + } + lk.unlock(); + pathOut = &search->second; + return true; +} + +const urde::SObjectTag* SpecBase::getResourceIdByName(std::string_view name) const { + std::string lower(name); + std::transform(lower.cbegin(), lower.cend(), lower.begin(), tolower); + + std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + auto search = m_catalogNameToTag.find(lower); + if (search == m_catalogNameToTag.end()) { + if (m_backgroundRunning) { + while (m_backgroundRunning) { + lk.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + lk.lock(); + search = m_catalogNameToTag.find(lower); + if (search != m_catalogNameToTag.end()) + break; + } + if (search == m_catalogNameToTag.end()) + return nullptr; + } else + return nullptr; + } + return &search->second; +} + +FourCC SpecBase::getResourceTypeById(urde::CAssetId id) const { + if (!id.IsValid()) + return {}; + + std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + urde::SObjectTag searchTag = {FourCC(), id}; + auto search = m_tagToPath.find(searchTag); + if (search == m_tagToPath.end()) { + if (m_backgroundRunning) { + while (m_backgroundRunning) { + lk.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + lk.lock(); + search = m_tagToPath.find(searchTag); + if (search != m_tagToPath.end()) + break; + } + if (search == m_tagToPath.end()) return {}; + } else + return {}; + } - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); - urde::SObjectTag searchTag = {FourCC(), id}; - auto search = m_tagToPath.find(searchTag); - if (search == m_tagToPath.end()) - { - if (m_backgroundRunning) - { - while (m_backgroundRunning) - { - lk.unlock(); - std::this_thread::sleep_for(std::chrono::milliseconds(2)); - lk.lock(); - search = m_tagToPath.find(searchTag); - if (search != m_tagToPath.end()) - break; - } - if (search == m_tagToPath.end()) - return {}; - } - else - return {}; - } - - return search->first.type; + return search->first.type; } -void SpecBase::enumerateResources(const std::function& lambda) const -{ - waitForIndexComplete(); - for (const auto& pair : m_tagToPath) - { - if (!lambda(pair.first)) - break; - } +void SpecBase::enumerateResources(const std::function& lambda) const { + waitForIndexComplete(); + for (const auto& pair : m_tagToPath) { + if (!lambda(pair.first)) + break; + } } void SpecBase::enumerateNamedResources( - const std::function& lambda) const -{ - waitForIndexComplete(); - for (const auto& pair : m_catalogNameToTag) - { - if (!lambda(pair.first, pair.second)) - break; + const std::function& lambda) const { + waitForIndexComplete(); + for (const auto& pair : m_catalogNameToTag) { + if (!lambda(pair.first, pair.second)) + break; + } +} + +static void WriteTag(athena::io::YAMLDocWriter& cacheWriter, const urde::SObjectTag& pathTag, + const hecl::ProjectPath& path) { + char idStr[9]; + snprintf(idStr, 9, "%08X", uint32_t(pathTag.id.Value())); + if (auto v = cacheWriter.enterSubVector(idStr)) { + cacheWriter.writeString(nullptr, pathTag.type.toString().c_str()); + cacheWriter.writeString(nullptr, path.getAuxInfo().size() ? (std::string(path.getRelativePathUTF8()) + '|' + + path.getAuxInfoUTF8().data()) + : path.getRelativePathUTF8()); + } +} + +static void WriteNameTag(athena::io::YAMLDocWriter& nameWriter, const urde::SObjectTag& pathTag, + std::string_view name) { + char idStr[9]; + snprintf(idStr, 9, "%08X", uint32_t(pathTag.id.Value())); + nameWriter.writeString(name.data(), idStr); +} + +void SpecBase::readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAMLDocWriter& nameWriter) { + athena::io::FileReader freader(catalogPath.getAbsolutePath()); + if (!freader.isOpen()) + return; + + athena::io::YAMLDocReader reader; + bool res = reader.parse(&freader); + if (!res) + return; + + const athena::io::YAMLNode* root = reader.getRootNode(); + for (const auto& p : root->m_mapChildren) { + /* Hash as lowercase since lookup is case-insensitive */ + std::string pLower = p.first; + std::transform(pLower.cbegin(), pLower.cend(), pLower.begin(), tolower); + + /* Avoid redundant filesystem access for re-caches */ + if (m_catalogNameToTag.find(pLower) != m_catalogNameToTag.cend()) + continue; + + athena::io::YAMLNode& node = *p.second; + hecl::ProjectPath path; + if (node.m_type == YAML_SCALAR_NODE) { + path = hecl::ProjectPath(m_project.getProjectWorkingPath(), node.m_scalarString); + } else if (node.m_type == YAML_SEQUENCE_NODE) { + if (node.m_seqChildren.size() >= 2) + path = hecl::ProjectPath(m_project.getProjectWorkingPath(), node.m_seqChildren[0]->m_scalarString) + .ensureAuxInfo(node.m_seqChildren[1]->m_scalarString); + else if (node.m_seqChildren.size() == 1) + path = hecl::ProjectPath(m_project.getProjectWorkingPath(), node.m_seqChildren[0]->m_scalarString); } -} + if (path.isNone()) + continue; + urde::SObjectTag pathTag = tagFromPath(path, m_backgroundBlender); + if (pathTag) { + std::unique_lock lk(m_backgroundIndexMutex); + m_catalogNameToTag[pLower] = pathTag; + m_catalogTagToNames[pathTag].insert(p.first); -static void WriteTag(athena::io::YAMLDocWriter& cacheWriter, - const urde::SObjectTag& pathTag, const hecl::ProjectPath& path) -{ - char idStr[9]; - snprintf(idStr, 9, "%08X", uint32_t(pathTag.id.Value())); - if (auto v = cacheWriter.enterSubVector(idStr)) - { - cacheWriter.writeString(nullptr, pathTag.type.toString().c_str()); - cacheWriter.writeString(nullptr, path.getAuxInfo().size() ? - (std::string(path.getRelativePathUTF8()) + '|' + path.getAuxInfoUTF8().data()) : - path.getRelativePathUTF8()); - } -} - -static void WriteNameTag(athena::io::YAMLDocWriter& nameWriter, - const urde::SObjectTag& pathTag, - std::string_view name) -{ - char idStr[9]; - snprintf(idStr, 9, "%08X", uint32_t(pathTag.id.Value())); - nameWriter.writeString(name.data(), idStr); -} - -void SpecBase::readCatalog(const hecl::ProjectPath& catalogPath, - athena::io::YAMLDocWriter& nameWriter) -{ - athena::io::FileReader freader(catalogPath.getAbsolutePath()); - if (!freader.isOpen()) - return; - - athena::io::YAMLDocReader reader; - bool res = reader.parse(&freader); - if (!res) - return; - - const athena::io::YAMLNode* root = reader.getRootNode(); - for (const auto& p : root->m_mapChildren) - { - /* Hash as lowercase since lookup is case-insensitive */ - std::string pLower = p.first; - std::transform(pLower.cbegin(), pLower.cend(), pLower.begin(), tolower); - - /* Avoid redundant filesystem access for re-caches */ - if (m_catalogNameToTag.find(pLower) != m_catalogNameToTag.cend()) - continue; - - athena::io::YAMLNode& node = *p.second; - hecl::ProjectPath path; - if (node.m_type == YAML_SCALAR_NODE) - { - path = hecl::ProjectPath(m_project.getProjectWorkingPath(), node.m_scalarString); - } - else if (node.m_type == YAML_SEQUENCE_NODE) - { - if (node.m_seqChildren.size() >= 2) - path = hecl::ProjectPath(m_project.getProjectWorkingPath(), node.m_seqChildren[0]->m_scalarString). - ensureAuxInfo(node.m_seqChildren[1]->m_scalarString); - else if (node.m_seqChildren.size() == 1) - path = hecl::ProjectPath(m_project.getProjectWorkingPath(), node.m_seqChildren[0]->m_scalarString); - } - if (path.isNone()) - continue; - urde::SObjectTag pathTag = tagFromPath(path, m_backgroundBlender); - if (pathTag) - { - std::unique_lock lk(m_backgroundIndexMutex); - m_catalogNameToTag[pLower] = pathTag; - m_catalogTagToNames[pathTag].insert(p.first); - - WriteNameTag(nameWriter, pathTag, p.first); + WriteNameTag(nameWriter, pathTag, p.first); #if 0 fprintf(stderr, "%s %s %08X\n", p.first.c_str(), pathTag.type.toString().c_str(), uint32_t(pathTag.id)); #endif - } } + } } -void SpecBase::backgroundIndexRecursiveCatalogs(const hecl::ProjectPath& dir, - athena::io::YAMLDocWriter& nameWriter, - int level) -{ - hecl::DirectoryEnumerator dEnum(dir.getAbsolutePath(), - hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, - false, false, true); +void SpecBase::backgroundIndexRecursiveCatalogs(const hecl::ProjectPath& dir, athena::io::YAMLDocWriter& nameWriter, + int level) { + hecl::DirectoryEnumerator dEnum(dir.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, + false, true); - /* Enumerate all items */ - for (const hecl::DirectoryEnumerator::Entry& ent : dEnum) - { - hecl::ProjectPath path(dir, ent.m_name); - if (ent.m_isDir && level < 1) - backgroundIndexRecursiveCatalogs(path, nameWriter, level + 1); - else - { - if (!path.isFile()) - continue; + /* Enumerate all items */ + for (const hecl::DirectoryEnumerator::Entry& ent : dEnum) { + hecl::ProjectPath path(dir, ent.m_name); + if (ent.m_isDir && level < 1) + backgroundIndexRecursiveCatalogs(path, nameWriter, level + 1); + else { + if (!path.isFile()) + continue; - /* Read catalog.yaml for .pak directory if exists */ - if (level == 1 && !ent.m_name.compare(_SYS_STR("!catalog.yaml"))) - { - readCatalog(path, nameWriter); - continue; - } - } - - /* bail if cancelled by client */ - if (!m_backgroundRunning) - break; + /* Read catalog.yaml for .pak directory if exists */ + if (level == 1 && !ent.m_name.compare(_SYS_STR("!catalog.yaml"))) { + readCatalog(path, nameWriter); + continue; + } } + + /* bail if cancelled by client */ + if (!m_backgroundRunning) + break; + } } #if DUMP_CACHE_FILL -static void DumpCacheAdd(const urde::SObjectTag& pathTag, const hecl::ProjectPath& path) -{ - fprintf(stderr, "%s %08X %s\n", - pathTag.type.toString().c_str(), uint32_t(pathTag.id.Value()), - path.getRelativePathUTF8().data()); +static void DumpCacheAdd(const urde::SObjectTag& pathTag, const hecl::ProjectPath& path) { + fprintf(stderr, "%s %08X %s\n", pathTag.type.toString().c_str(), uint32_t(pathTag.id.Value()), + path.getRelativePathUTF8().data()); } #endif -bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, - athena::io::YAMLDocWriter& cacheWriter) -{ - /* Avoid redundant filesystem access for re-caches */ - if (m_pathToTag.find(path.hash()) != m_pathToTag.cend()) - return true; - - /* Try as glob */ - hecl::ProjectPath asGlob = path.getWithExtension(_SYS_STR(".*"), true); - if (m_pathToTag.find(asGlob.hash()) != m_pathToTag.cend()) - return true; - - /* Classify intermediate into tag */ - urde::SObjectTag pathTag = buildTagFromPath(path, m_backgroundBlender); - if (pathTag) - { - std::unique_lock lk(m_backgroundIndexMutex); - bool useGlob = false; - - /* Special multi-resource intermediates */ - if (pathTag.type == SBIG('ANCS')) - { - hecl::blender::Connection& conn = m_backgroundBlender.getBlenderConnection(); - if (!conn.openBlend(path) || conn.getBlendType() != hecl::blender::BlendType::Actor) - return false; - - /* Transform tag to glob */ - pathTag = {SBIG('ANCS'), asGlob.hash().val32()}; - useGlob = true; - - hecl::blender::DataStream ds = conn.beginData(); - std::vector armatureNames = ds.getArmatureNames(); - std::vector subtypeNames = ds.getSubtypeNames(); - std::vector actionNames = ds.getActionNames(); - - for (const std::string& arm : armatureNames) - { - hecl::SystemStringConv sysStr(arm); - hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".CINF")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); - m_tagToPath[pathTag] = subPath; - m_pathToTag[subPath.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, subPath); -#if DUMP_CACHE_FILL - DumpCacheAdd(pathTag, subPath); -#endif - } - - for (const std::string& sub : subtypeNames) - { - hecl::SystemStringConv sysStr(sub); - hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".CSKR")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); - m_tagToPath[pathTag] = subPath; - m_pathToTag[subPath.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, subPath); -#if DUMP_CACHE_FILL - DumpCacheAdd(pathTag, subPath); -#endif - - std::vector overlayNames = ds.getSubtypeOverlayNames(sub); - for (const auto& overlay : overlayNames) - { - hecl::SystemStringConv overlaySys(overlay); - hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR('.') + - overlaySys.c_str() + _SYS_STR(".CSKR")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); - m_tagToPath[pathTag] = subPath; - m_pathToTag[subPath.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, subPath); -#if DUMP_CACHE_FILL - DumpCacheAdd(pathTag, subPath); -#endif - } - } - - std::vector attachmentNames = ds.getAttachmentNames(); - for (const auto& attachment : attachmentNames) - { - hecl::SystemStringConv attachmentSys(attachment); - hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(_SYS_STR("ATTACH.")) + - attachmentSys.c_str() + _SYS_STR(".CSKR")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); - m_tagToPath[pathTag] = subPath; - m_pathToTag[subPath.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, subPath); -#if DUMP_CACHE_FILL - DumpCacheAdd(pathTag, subPath); -#endif - } - - for (const std::string& act : actionNames) - { - hecl::SystemStringConv sysStr(act); - hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".ANIM")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); - m_tagToPath[pathTag] = subPath; - m_pathToTag[subPath.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, subPath); -#if DUMP_CACHE_FILL - DumpCacheAdd(pathTag, subPath); -#endif - } - } - else if (pathTag.type == SBIG('MLVL')) - { - /* Transform tag to glob */ - pathTag = {SBIG('MLVL'), asGlob.hash().val32()}; - useGlob = true; - - hecl::ProjectPath subPath = asGlob.ensureAuxInfo(_SYS_STR("MAPW")); - urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); - m_tagToPath[pathTag] = subPath; - m_pathToTag[subPath.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, subPath); -#if DUMP_CACHE_FILL - DumpCacheAdd(pathTag, subPath); -#endif - - subPath = asGlob.ensureAuxInfo(_SYS_STR("SAVW")); - pathTag = buildTagFromPath(subPath, m_backgroundBlender); - m_tagToPath[pathTag] = subPath; - m_pathToTag[subPath.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, subPath); -#if DUMP_CACHE_FILL - DumpCacheAdd(pathTag, subPath); -#endif - } - - /* Cache in-memory */ - const hecl::ProjectPath& usePath = useGlob ? asGlob : path; - m_tagToPath[pathTag] = usePath; - m_pathToTag[usePath.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, usePath); -#if DUMP_CACHE_FILL - DumpCacheAdd(pathTag, usePath); -#endif - } - +bool SpecBase::addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDocWriter& cacheWriter) { + /* Avoid redundant filesystem access for re-caches */ + if (m_pathToTag.find(path.hash()) != m_pathToTag.cend()) return true; -} -void SpecBase::backgroundIndexRecursiveProc(const hecl::ProjectPath& dir, - athena::io::YAMLDocWriter& cacheWriter, - athena::io::YAMLDocWriter& nameWriter, - int level) -{ - hecl::DirectoryEnumerator dEnum(dir.getAbsolutePath(), - hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, - false, false, true); + /* Try as glob */ + hecl::ProjectPath asGlob = path.getWithExtension(_SYS_STR(".*"), true); + if (m_pathToTag.find(asGlob.hash()) != m_pathToTag.cend()) + return true; - /* Enumerate all items */ - for (const hecl::DirectoryEnumerator::Entry& ent : dEnum) - { - /* bail if cancelled by client */ - if (!m_backgroundRunning) - break; + /* Classify intermediate into tag */ + urde::SObjectTag pathTag = buildTagFromPath(path, m_backgroundBlender); + if (pathTag) { + std::unique_lock lk(m_backgroundIndexMutex); + bool useGlob = false; - hecl::ProjectPath path(dir, ent.m_name); - if (ent.m_isDir) - { - /* Index AGSC here */ - if (hecl::ProjectPath(path, "!project.yaml").isFile() && - hecl::ProjectPath(path, "!pool.yaml").isFile()) - { - urde::SObjectTag pathTag(SBIG('AGSC'), path.hash().val32()); - m_tagToPath[pathTag] = path; - m_pathToTag[path.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, path); - } - else - { - backgroundIndexRecursiveProc(path, cacheWriter, nameWriter, level + 1); - } + /* Special multi-resource intermediates */ + if (pathTag.type == SBIG('ANCS')) { + hecl::blender::Connection& conn = m_backgroundBlender.getBlenderConnection(); + if (!conn.openBlend(path) || conn.getBlendType() != hecl::blender::BlendType::Actor) + return false; + + /* Transform tag to glob */ + pathTag = {SBIG('ANCS'), asGlob.hash().val32()}; + useGlob = true; + + hecl::blender::DataStream ds = conn.beginData(); + std::vector armatureNames = ds.getArmatureNames(); + std::vector subtypeNames = ds.getSubtypeNames(); + std::vector actionNames = ds.getActionNames(); + + for (const std::string& arm : armatureNames) { + hecl::SystemStringConv sysStr(arm); + hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".CINF")); + urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + m_tagToPath[pathTag] = subPath; + m_pathToTag[subPath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, subPath); +#if DUMP_CACHE_FILL + DumpCacheAdd(pathTag, subPath); +#endif + } + + for (const std::string& sub : subtypeNames) { + hecl::SystemStringConv sysStr(sub); + hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".CSKR")); + urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + m_tagToPath[pathTag] = subPath; + m_pathToTag[subPath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, subPath); +#if DUMP_CACHE_FILL + DumpCacheAdd(pathTag, subPath); +#endif + + std::vector overlayNames = ds.getSubtypeOverlayNames(sub); + for (const auto& overlay : overlayNames) { + hecl::SystemStringConv overlaySys(overlay); + hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR('.') + + overlaySys.c_str() + _SYS_STR(".CSKR")); + urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + m_tagToPath[pathTag] = subPath; + m_pathToTag[subPath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, subPath); +#if DUMP_CACHE_FILL + DumpCacheAdd(pathTag, subPath); +#endif } - else - { - if (!path.isFile()) - continue; + } - /* Read catalog.yaml for .pak directory if exists */ - if (level == 1 && !ent.m_name.compare(_SYS_STR("!catalog.yaml"))) - { - readCatalog(path, nameWriter); - continue; - } + std::vector attachmentNames = ds.getAttachmentNames(); + for (const auto& attachment : attachmentNames) { + hecl::SystemStringConv attachmentSys(attachment); + hecl::ProjectPath subPath = + asGlob.ensureAuxInfo(hecl::SystemString(_SYS_STR("ATTACH.")) + attachmentSys.c_str() + _SYS_STR(".CSKR")); + urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + m_tagToPath[pathTag] = subPath; + m_pathToTag[subPath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, subPath); +#if DUMP_CACHE_FILL + DumpCacheAdd(pathTag, subPath); +#endif + } - /* Index the regular file */ - addFileToIndex(path, cacheWriter); + for (const std::string& act : actionNames) { + hecl::SystemStringConv sysStr(act); + hecl::ProjectPath subPath = asGlob.ensureAuxInfo(hecl::SystemString(sysStr.sys_str()) + _SYS_STR(".ANIM")); + urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + m_tagToPath[pathTag] = subPath; + m_pathToTag[subPath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, subPath); +#if DUMP_CACHE_FILL + DumpCacheAdd(pathTag, subPath); +#endif + } + } else if (pathTag.type == SBIG('MLVL')) { + /* Transform tag to glob */ + pathTag = {SBIG('MLVL'), asGlob.hash().val32()}; + useGlob = true; + + hecl::ProjectPath subPath = asGlob.ensureAuxInfo(_SYS_STR("MAPW")); + urde::SObjectTag pathTag = buildTagFromPath(subPath, m_backgroundBlender); + m_tagToPath[pathTag] = subPath; + m_pathToTag[subPath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, subPath); +#if DUMP_CACHE_FILL + DumpCacheAdd(pathTag, subPath); +#endif + + subPath = asGlob.ensureAuxInfo(_SYS_STR("SAVW")); + pathTag = buildTagFromPath(subPath, m_backgroundBlender); + m_tagToPath[pathTag] = subPath; + m_pathToTag[subPath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, subPath); +#if DUMP_CACHE_FILL + DumpCacheAdd(pathTag, subPath); +#endif + } + + /* Cache in-memory */ + const hecl::ProjectPath& usePath = useGlob ? asGlob : path; + m_tagToPath[pathTag] = usePath; + m_pathToTag[usePath.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, usePath); +#if DUMP_CACHE_FILL + DumpCacheAdd(pathTag, usePath); +#endif + } + + return true; +} + +void SpecBase::backgroundIndexRecursiveProc(const hecl::ProjectPath& dir, athena::io::YAMLDocWriter& cacheWriter, + athena::io::YAMLDocWriter& nameWriter, int level) { + hecl::DirectoryEnumerator dEnum(dir.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, + false, true); + + /* Enumerate all items */ + for (const hecl::DirectoryEnumerator::Entry& ent : dEnum) { + /* bail if cancelled by client */ + if (!m_backgroundRunning) + break; + + hecl::ProjectPath path(dir, ent.m_name); + if (ent.m_isDir) { + /* Index AGSC here */ + if (hecl::ProjectPath(path, "!project.yaml").isFile() && hecl::ProjectPath(path, "!pool.yaml").isFile()) { + urde::SObjectTag pathTag(SBIG('AGSC'), path.hash().val32()); + m_tagToPath[pathTag] = path; + m_pathToTag[path.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, path); + } else { + backgroundIndexRecursiveProc(path, cacheWriter, nameWriter, level + 1); + } + } else { + if (!path.isFile()) + continue; + + /* Read catalog.yaml for .pak directory if exists */ + if (level == 1 && !ent.m_name.compare(_SYS_STR("!catalog.yaml"))) { + readCatalog(path, nameWriter); + continue; + } + + /* Index the regular file */ + addFileToIndex(path, cacheWriter); + } + } +} + +void SpecBase::backgroundIndexProc() { + logvisor::RegisterThreadName("Resource Index"); + + hecl::ProjectPath tagCachePath(m_project.getProjectCookedPath(getOriginalSpec()), _SYS_STR("tag_cache.yaml")); + hecl::ProjectPath nameCachePath(m_project.getProjectCookedPath(getOriginalSpec()), _SYS_STR("name_cache.yaml")); + hecl::ProjectPath specRoot(m_project.getProjectWorkingPath(), getOriginalSpec().m_name); + + /* Cache will be overwritten with validated entries afterwards */ + athena::io::YAMLDocWriter cacheWriter(nullptr); + athena::io::YAMLDocWriter nameWriter(nullptr); + + /* Read in tag cache */ + if (tagCachePath.isFile()) { + athena::io::FileReader reader(tagCachePath.getAbsolutePath()); + if (reader.isOpen()) { + Log.report(logvisor::Info, _SYS_STR("Cache index of '%s' loading"), getOriginalSpec().m_name.data()); + athena::io::YAMLDocReader cacheReader; + if (cacheReader.parse(&reader)) { + std::unique_lock lk(m_backgroundIndexMutex); + size_t tagCount = cacheReader.getRootNode()->m_mapChildren.size(); + m_tagToPath.reserve(tagCount); + m_pathToTag.reserve(tagCount); + size_t loadIdx = 0; + for (const auto& child : cacheReader.getRootNode()->m_mapChildren) { + if (!m_backgroundRunning) + return; + + const athena::io::YAMLNode& node = *child.second; + unsigned long id = strtoul(child.first.c_str(), nullptr, 16); + hecl::FourCC type(node.m_seqChildren.at(0)->m_scalarString.c_str()); + hecl::ProjectPath path(m_project.getProjectWorkingPath(), node.m_seqChildren.at(1)->m_scalarString); + + if (path.isFileOrGlob()) { + urde::SObjectTag pathTag(type, id); + m_tagToPath[pathTag] = path; + m_pathToTag[path.hash()] = pathTag; + WriteTag(cacheWriter, pathTag, path); + } + + ++loadIdx; + if (!(loadIdx % 100)) + fprintf(stderr, "\r %" PRISize " / %" PRISize, loadIdx, tagCount); } - } -} + fprintf(stderr, "\r %" PRISize " / %" PRISize "\n", loadIdx, tagCount); + } + Log.report(logvisor::Info, _SYS_STR("Cache index of '%s' loaded; %d tags"), getOriginalSpec().m_name.data(), + m_tagToPath.size()); -void SpecBase::backgroundIndexProc() -{ - logvisor::RegisterThreadName("Resource Index"); - - hecl::ProjectPath tagCachePath(m_project.getProjectCookedPath(getOriginalSpec()), _SYS_STR("tag_cache.yaml")); - hecl::ProjectPath nameCachePath(m_project.getProjectCookedPath(getOriginalSpec()), _SYS_STR("name_cache.yaml")); - hecl::ProjectPath specRoot(m_project.getProjectWorkingPath(), getOriginalSpec().m_name); - - /* Cache will be overwritten with validated entries afterwards */ - athena::io::YAMLDocWriter cacheWriter(nullptr); - athena::io::YAMLDocWriter nameWriter(nullptr); - - /* Read in tag cache */ - if (tagCachePath.isFile()) - { - athena::io::FileReader reader(tagCachePath.getAbsolutePath()); - if (reader.isOpen()) - { - Log.report(logvisor::Info, _SYS_STR("Cache index of '%s' loading"), getOriginalSpec().m_name.data()); - athena::io::YAMLDocReader cacheReader; - if (cacheReader.parse(&reader)) - { - std::unique_lock lk(m_backgroundIndexMutex); - size_t tagCount = cacheReader.getRootNode()->m_mapChildren.size(); - m_tagToPath.reserve(tagCount); - m_pathToTag.reserve(tagCount); - size_t loadIdx = 0; - for (const auto& child : cacheReader.getRootNode()->m_mapChildren) - { - if (!m_backgroundRunning) - return; - - const athena::io::YAMLNode& node = *child.second; - unsigned long id = strtoul(child.first.c_str(), nullptr, 16); - hecl::FourCC type(node.m_seqChildren.at(0)->m_scalarString.c_str()); - hecl::ProjectPath path(m_project.getProjectWorkingPath(), - node.m_seqChildren.at(1)->m_scalarString); - - if (path.isFileOrGlob()) - { - urde::SObjectTag pathTag(type, id); - m_tagToPath[pathTag] = path; - m_pathToTag[path.hash()] = pathTag; - WriteTag(cacheWriter, pathTag, path); - } - - ++loadIdx; - if (!(loadIdx % 100)) - fprintf(stderr, "\r %" PRISize " / %" PRISize, loadIdx, tagCount); - } - fprintf(stderr, "\r %" PRISize " / %" PRISize "\n", loadIdx, tagCount); - } - Log.report(logvisor::Info, _SYS_STR("Cache index of '%s' loaded; %d tags"), - getOriginalSpec().m_name.data(), m_tagToPath.size()); - - if (nameCachePath.isFile()) - { - /* Read in name cache */ - Log.report(logvisor::Info, _SYS_STR("Name index of '%s' loading"), getOriginalSpec().m_name.data()); - athena::io::FileReader nreader(nameCachePath.getAbsolutePath()); - athena::io::YAMLDocReader nameReader; - if (nameReader.parse(&nreader)) - { - std::unique_lock lk(m_backgroundIndexMutex); - m_catalogNameToTag.reserve(nameReader.getRootNode()->m_mapChildren.size()); - m_catalogTagToNames.reserve(nameReader.getRootNode()->m_mapChildren.size()); - for (const auto& child : nameReader.getRootNode()->m_mapChildren) - { - unsigned long id = strtoul(child.second->m_scalarString.c_str(), nullptr, 16); - auto search = m_tagToPath.find(urde::SObjectTag(FourCC(), uint32_t(id))); - if (search != m_tagToPath.cend()) - { - std::string chLower = child.first; - std::transform(chLower.cbegin(), chLower.cend(), chLower.begin(), tolower); - m_catalogNameToTag[chLower] = search->first; - m_catalogTagToNames[search->first].insert(child.first); - WriteNameTag(nameWriter, search->first, child.first); - } - } - } - Log.report(logvisor::Info, _SYS_STR("Name index of '%s' loaded; %d names"), - getOriginalSpec().m_name.data(), m_catalogNameToTag.size()); + if (nameCachePath.isFile()) { + /* Read in name cache */ + Log.report(logvisor::Info, _SYS_STR("Name index of '%s' loading"), getOriginalSpec().m_name.data()); + athena::io::FileReader nreader(nameCachePath.getAbsolutePath()); + athena::io::YAMLDocReader nameReader; + if (nameReader.parse(&nreader)) { + std::unique_lock lk(m_backgroundIndexMutex); + m_catalogNameToTag.reserve(nameReader.getRootNode()->m_mapChildren.size()); + m_catalogTagToNames.reserve(nameReader.getRootNode()->m_mapChildren.size()); + for (const auto& child : nameReader.getRootNode()->m_mapChildren) { + unsigned long id = strtoul(child.second->m_scalarString.c_str(), nullptr, 16); + auto search = m_tagToPath.find(urde::SObjectTag(FourCC(), uint32_t(id))); + if (search != m_tagToPath.cend()) { + std::string chLower = child.first; + std::transform(chLower.cbegin(), chLower.cend(), chLower.begin(), tolower); + m_catalogNameToTag[chLower] = search->first; + m_catalogTagToNames[search->first].insert(child.first); + WriteNameTag(nameWriter, search->first, child.first); } + } } + Log.report(logvisor::Info, _SYS_STR("Name index of '%s' loaded; %d names"), getOriginalSpec().m_name.data(), + m_catalogNameToTag.size()); + } } + } - /* Add special original IDs resource if exists (not name-cached to disk) */ - hecl::ProjectPath oidsPath(specRoot, "!original_ids.yaml"); - urde::SObjectTag oidsTag = buildTagFromPath(oidsPath, m_backgroundBlender); - if (oidsTag) - { - m_catalogNameToTag["mp1originalids"] = oidsTag; - m_catalogTagToNames[oidsTag].insert("MP1OriginalIDs"); - } + /* Add special original IDs resource if exists (not name-cached to disk) */ + hecl::ProjectPath oidsPath(specRoot, "!original_ids.yaml"); + urde::SObjectTag oidsTag = buildTagFromPath(oidsPath, m_backgroundBlender); + if (oidsTag) { + m_catalogNameToTag["mp1originalids"] = oidsTag; + m_catalogTagToNames[oidsTag].insert("MP1OriginalIDs"); + } - Log.report(logvisor::Info, _SYS_STR("Background index of '%s' started"), getOriginalSpec().m_name.data()); - backgroundIndexRecursiveProc(specRoot, cacheWriter, nameWriter, 0); + Log.report(logvisor::Info, _SYS_STR("Background index of '%s' started"), getOriginalSpec().m_name.data()); + backgroundIndexRecursiveProc(specRoot, cacheWriter, nameWriter, 0); - tagCachePath.makeDirChain(false); - athena::io::FileWriter twriter(tagCachePath.getAbsolutePath()); - cacheWriter.finish(&twriter); + tagCachePath.makeDirChain(false); + athena::io::FileWriter twriter(tagCachePath.getAbsolutePath()); + cacheWriter.finish(&twriter); - athena::io::FileWriter nwriter(nameCachePath.getAbsolutePath()); - nameWriter.finish(&nwriter); + athena::io::FileWriter nwriter(nameCachePath.getAbsolutePath()); + nameWriter.finish(&nwriter); - m_backgroundBlender.shutdown(); - Log.report(logvisor::Info, _SYS_STR("Background index of '%s' complete; %d tags, %d names"), - getOriginalSpec().m_name.data(), m_tagToPath.size(), m_catalogNameToTag.size()); - m_backgroundRunning = false; + m_backgroundBlender.shutdown(); + Log.report(logvisor::Info, _SYS_STR("Background index of '%s' complete; %d tags, %d names"), + getOriginalSpec().m_name.data(), m_tagToPath.size(), m_catalogNameToTag.size()); + m_backgroundRunning = false; } -void SpecBase::cancelBackgroundIndex() -{ - m_backgroundRunning = false; - if (m_backgroundIndexTh.joinable()) - m_backgroundIndexTh.join(); +void SpecBase::cancelBackgroundIndex() { + m_backgroundRunning = false; + if (m_backgroundIndexTh.joinable()) + m_backgroundIndexTh.join(); } -void SpecBase::beginBackgroundIndex() -{ - cancelBackgroundIndex(); - clearTagCache(); - m_backgroundRunning = true; - m_backgroundIndexTh = std::thread(std::bind(&SpecBase::backgroundIndexProc, this)); +void SpecBase::beginBackgroundIndex() { + cancelBackgroundIndex(); + clearTagCache(); + m_backgroundRunning = true; + m_backgroundIndexTh = std::thread(std::bind(&SpecBase::backgroundIndexProc, this)); } -void SpecBase::waitForIndexComplete() const -{ - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); - while (m_backgroundRunning) - { - lk.unlock(); - std::this_thread::sleep_for(std::chrono::milliseconds(2)); - lk.lock(); - } +void SpecBase::waitForIndexComplete() const { + std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + while (m_backgroundRunning) { + lk.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + lk.lock(); + } } -} +} // namespace DataSpec diff --git a/DataSpec/SpecBase.hpp b/DataSpec/SpecBase.hpp index e2f411f7a..25a30031a 100644 --- a/DataSpec/SpecBase.hpp +++ b/DataSpec/SpecBase.hpp @@ -7,236 +7,196 @@ #include "hecl/Blender/Token.hpp" #include "Runtime/RetroTypes.hpp" -namespace nod -{ +namespace nod { class DiscBase; class Node; -} +} // namespace nod -namespace athena::io -{ +namespace athena::io { class FileWriter; class YAMLDocWriter; -} +} // namespace athena::io -namespace DataSpec -{ +namespace DataSpec { template -class IDRestorer -{ - std::vector> m_newToOrig; - std::vector> m_origToNew; +class IDRestorer { + std::vector> m_newToOrig; + std::vector> m_origToNew; + public: - IDRestorer(const hecl::ProjectPath& yamlPath, const hecl::Database::Project& project); - IDType newToOriginal(IDType id) const; - IDType originalToNew(IDType id) const; + IDRestorer(const hecl::ProjectPath& yamlPath, const hecl::Database::Project& project); + IDType newToOriginal(IDType id) const; + IDType originalToNew(IDType id) const; }; -struct SpecBase : hecl::Database::IDataSpec -{ - /* HECL Adaptors */ - void setThreadProject(); - bool canExtract(const ExtractPassInfo& info, std::vector& reps); - void doExtract(const ExtractPassInfo& info, const hecl::MultiProgressPrinter& progress); +struct SpecBase : hecl::Database::IDataSpec { + /* HECL Adaptors */ + void setThreadProject(); + bool canExtract(const ExtractPassInfo& info, std::vector& reps); + void doExtract(const ExtractPassInfo& info, const hecl::MultiProgressPrinter& progress); - bool canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok, int cookPass); - const hecl::Database::DataSpecEntry* overrideDataSpec(const hecl::ProjectPath& path, - const hecl::Database::DataSpecEntry* oldEntry, - hecl::blender::Token& btok) const; - void doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath, - bool fast, hecl::blender::Token& btok, FCookProgress progress); + bool canCook(const hecl::ProjectPath& path, hecl::blender::Token& btok, int cookPass); + const hecl::Database::DataSpecEntry* overrideDataSpec(const hecl::ProjectPath& path, + const hecl::Database::DataSpecEntry* oldEntry, + hecl::blender::Token& btok) const; + void doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& cookedPath, bool fast, hecl::blender::Token& btok, + FCookProgress progress); - bool canPackage(const hecl::ProjectPath& path); - void doPackage(const hecl::ProjectPath& path, const hecl::Database::DataSpecEntry* entry, - bool fast, hecl::blender::Token& btok, const hecl::MultiProgressPrinter& progress, - hecl::ClientProcess* cp); + bool canPackage(const hecl::ProjectPath& path); + void doPackage(const hecl::ProjectPath& path, const hecl::Database::DataSpecEntry* entry, bool fast, + hecl::blender::Token& btok, const hecl::MultiProgressPrinter& progress, hecl::ClientProcess* cp); - void interruptCook(); + void interruptCook(); - /* Extract handlers */ - virtual bool checkStandaloneID(const char* id) const=0; - virtual bool checkFromStandaloneDisc(nod::DiscBase& disc, - const hecl::SystemString& regstr, - const std::vector& args, - std::vector& reps)=0; - virtual bool checkFromTrilogyDisc(nod::DiscBase& disc, - const hecl::SystemString& regstr, - const std::vector& args, - std::vector& reps)=0; - virtual bool extractFromDisc(nod::DiscBase& disc, bool force, - const hecl::MultiProgressPrinter& progress)=0; + /* Extract handlers */ + virtual bool checkStandaloneID(const char* id) const = 0; + virtual bool checkFromStandaloneDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, + const std::vector& args, + std::vector& reps) = 0; + virtual bool checkFromTrilogyDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, + const std::vector& args, std::vector& reps) = 0; + virtual bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) = 0; - /* Convert path to object tag */ - virtual urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, - hecl::blender::Token& btok) const=0; + /* Convert path to object tag */ + virtual urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const = 0; - /* Even if PC spec is being cooked, this will return the vanilla GCN spec */ - virtual const hecl::Database::DataSpecEntry& getOriginalSpec() const=0; + /* Even if PC spec is being cooked, this will return the vanilla GCN spec */ + virtual const hecl::Database::DataSpecEntry& getOriginalSpec() const = 0; - /* This will return a pseudo-spec for unmodified resources */ - virtual const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const=0; + /* This will return a pseudo-spec for unmodified resources */ + virtual const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const = 0; - /* Basic path check (game directory matching) */ - virtual bool checkPathPrefix(const hecl::ProjectPath& path) const=0; + /* Basic path check (game directory matching) */ + virtual bool checkPathPrefix(const hecl::ProjectPath& path) const = 0; - /* Pre-cook handlers */ - virtual bool validateYAMLDNAType(athena::io::IStreamReader& fp) const=0; + /* Pre-cook handlers */ + virtual bool validateYAMLDNAType(athena::io::IStreamReader& fp) const = 0; - /* Cook handlers */ - using BlendStream = hecl::blender::DataStream; - using Mesh = hecl::blender::Mesh; - using ColMesh = hecl::blender::ColMesh; - using PathMesh = hecl::blender::PathMesh; - using Light = hecl::blender::Light; - using Actor = hecl::blender::Actor; + /* Cook handlers */ + using BlendStream = hecl::blender::DataStream; + using Mesh = hecl::blender::Mesh; + using ColMesh = hecl::blender::ColMesh; + using PathMesh = hecl::blender::PathMesh; + using Light = hecl::blender::Light; + using Actor = hecl::blender::Actor; - virtual void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress)=0; - virtual void cookColMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress)=0; - virtual void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress)=0; - virtual void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress)=0; - virtual void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress)=0; - virtual void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress)=0; - virtual void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress)=0; - virtual void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - athena::io::IStreamReader& fin, FCookProgress progress)=0; - virtual void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - FCookProgress progress)=0; - virtual void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - FCookProgress progress)=0; - virtual void cookMapArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress)=0; - virtual void cookMapUniverse(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress)=0; + virtual void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) = 0; + virtual void cookColMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) = 0; + virtual void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) = 0; + virtual void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) = 0; + virtual void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) = 0; + virtual void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) = 0; + virtual void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) = 0; + virtual void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin, + FCookProgress progress) = 0; + virtual void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) = 0; + virtual void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) = 0; + virtual void cookMapArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) = 0; + virtual void cookMapUniverse(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) = 0; - /* Dependency flatteners */ - void flattenDependencies(const hecl::ProjectPath& in, - std::vector& pathsOut, - hecl::blender::Token& btok, - int charIdx = -1); - void flattenDependencies(const class UniqueID32& id, std::vector& pathsOut, int charIdx = -1); - void flattenDependencies(const class UniqueID64& id, std::vector& pathsOut, int charIdx = -1); - void flattenDependenciesBlend(const hecl::ProjectPath& in, - std::vector& pathsOut, - hecl::blender::Token& btok, - int charIdx = -1); - virtual void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector& pathsOut)=0; - virtual void flattenDependenciesANCSYAML(athena::io::IStreamReader& fin, - std::vector& pathsOut, - int charIdx = -1)=0; + /* Dependency flatteners */ + void flattenDependencies(const hecl::ProjectPath& in, std::vector& pathsOut, + hecl::blender::Token& btok, int charIdx = -1); + void flattenDependencies(const class UniqueID32& id, std::vector& pathsOut, int charIdx = -1); + void flattenDependencies(const class UniqueID64& id, std::vector& pathsOut, int charIdx = -1); + void flattenDependenciesBlend(const hecl::ProjectPath& in, std::vector& pathsOut, + hecl::blender::Token& btok, int charIdx = -1); + virtual void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector& pathsOut) = 0; + virtual void flattenDependenciesANCSYAML(athena::io::IStreamReader& fin, std::vector& pathsOut, + int charIdx = -1) = 0; - virtual void buildWorldPakList(const hecl::ProjectPath& worldPath, - const hecl::ProjectPath& worldPathCooked, - hecl::blender::Token& btok, - athena::io::FileWriter& w, - std::vector& listOut, - atUint64& resTableOffset, - std::unordered_map>& mlvlData) {} - virtual void buildPakList(hecl::blender::Token& btok, - athena::io::FileWriter& w, - const std::vector& list, - const std::vector>& nameList, - atUint64& resTableOffset) {} - virtual void writePakFileIndex(athena::io::FileWriter& w, - const std::vector& tags, - const std::vector>& index, - atUint64 resTableOffset) {} - virtual std::pair, size_t> - compressPakData(const urde::SObjectTag& tag, const uint8_t* data, size_t len) { return {}; } + virtual void buildWorldPakList(const hecl::ProjectPath& worldPath, const hecl::ProjectPath& worldPathCooked, + hecl::blender::Token& btok, athena::io::FileWriter& w, + std::vector& listOut, atUint64& resTableOffset, + std::unordered_map>& mlvlData) {} + virtual void buildPakList(hecl::blender::Token& btok, athena::io::FileWriter& w, + const std::vector& list, + const std::vector>& nameList, + atUint64& resTableOffset) {} + virtual void writePakFileIndex(athena::io::FileWriter& w, const std::vector& tags, + const std::vector>& index, atUint64 resTableOffset) {} + virtual std::pair, size_t> compressPakData(const urde::SObjectTag& tag, + const uint8_t* data, size_t len) { + return {}; + } - const hecl::ProjectPath& getMasterShaderPath() const {return m_masterShader;} + const hecl::ProjectPath& getMasterShaderPath() const { return m_masterShader; } - /* Support functions for resolving paths from IDs */ - virtual hecl::ProjectPath getWorking(class UniqueID32&) {return hecl::ProjectPath();} - virtual hecl::ProjectPath getWorking(class UniqueID64&) {return hecl::ProjectPath();} + /* Support functions for resolving paths from IDs */ + virtual hecl::ProjectPath getWorking(class UniqueID32&) { return hecl::ProjectPath(); } + virtual hecl::ProjectPath getWorking(class UniqueID64&) { return hecl::ProjectPath(); } - hecl::ProjectPath getCookedPath(const hecl::ProjectPath& working, bool pcTarget) const; + hecl::ProjectPath getCookedPath(const hecl::ProjectPath& working, bool pcTarget) const; - /* Project accessor */ - hecl::Database::Project& getProject() const {return m_project;} + /* Project accessor */ + hecl::Database::Project& getProject() const { return m_project; } - /* Extract RandomStatic entropy */ - void extractRandomStaticEntropy(const uint8_t* buf, const hecl::ProjectPath& noAramPath); + /* Extract RandomStatic entropy */ + void extractRandomStaticEntropy(const uint8_t* buf, const hecl::ProjectPath& noAramPath); - /* Tag cache functions */ - urde::SObjectTag tagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const; - hecl::ProjectPath pathFromTag(const urde::SObjectTag& tag) const; - bool waitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut); - const urde::SObjectTag* getResourceIdByName(std::string_view name) const; - hecl::FourCC getResourceTypeById(urde::CAssetId id) const; - void enumerateResources(const std::function& lambda) const; - void enumerateNamedResources( - const std::function& lambda) const; - void cancelBackgroundIndex(); - void beginBackgroundIndex(); - bool backgroundIndexRunning() const { return m_backgroundRunning; } - void waitForIndexComplete() const; + /* Tag cache functions */ + urde::SObjectTag tagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const; + hecl::ProjectPath pathFromTag(const urde::SObjectTag& tag) const; + bool waitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut); + const urde::SObjectTag* getResourceIdByName(std::string_view name) const; + hecl::FourCC getResourceTypeById(urde::CAssetId id) const; + void enumerateResources(const std::function& lambda) const; + void enumerateNamedResources(const std::function& lambda) const; + void cancelBackgroundIndex(); + void beginBackgroundIndex(); + bool backgroundIndexRunning() const { return m_backgroundRunning; } + void waitForIndexComplete() const; - virtual void getTagListForFile(const char* pakName, std::vector& out) const {} + virtual void getTagListForFile(const char* pakName, std::vector& out) const {} + + SpecBase(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc); + ~SpecBase(); - SpecBase(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc); - ~SpecBase(); protected: - hecl::Database::Project& m_project; - bool m_pc; - hecl::ProjectPath m_masterShader; + hecl::Database::Project& m_project; + bool m_pc; + hecl::ProjectPath m_masterShader; - std::unordered_map m_tagToPath; - std::unordered_map m_pathToTag; - std::unordered_map m_catalogNameToTag; - std::unordered_map> m_catalogTagToNames; - void clearTagCache(); - - hecl::blender::Token m_backgroundBlender; - std::thread m_backgroundIndexTh; - std::mutex m_backgroundIndexMutex; - bool m_backgroundRunning = false; + std::unordered_map m_tagToPath; + std::unordered_map m_pathToTag; + std::unordered_map m_catalogNameToTag; + std::unordered_map> m_catalogTagToNames; + void clearTagCache(); - void readCatalog(const hecl::ProjectPath& catalogPath, - athena::io::YAMLDocWriter& nameWriter); - bool addFileToIndex(const hecl::ProjectPath& path, - athena::io::YAMLDocWriter& cacheWriter); - void backgroundIndexRecursiveProc(const hecl::ProjectPath& path, - athena::io::YAMLDocWriter& cacheWriter, - athena::io::YAMLDocWriter& nameWriter, - int level); - void backgroundIndexRecursiveCatalogs(const hecl::ProjectPath& path, - athena::io::YAMLDocWriter& nameWriter, - int level); - void backgroundIndexProc(); + hecl::blender::Token m_backgroundBlender; + std::thread m_backgroundIndexTh; + std::mutex m_backgroundIndexMutex; + bool m_backgroundRunning = false; - void recursiveBuildResourceList(std::vector& listOut, - std::unordered_set& addedTags, - const hecl::ProjectPath& path, - hecl::blender::Token& btok); - void copyBuildListData(std::vector>& fileIndex, - const std::vector& buildList, - const hecl::Database::DataSpecEntry* entry, - bool fast, const hecl::MultiProgressPrinter& progress, - athena::io::FileWriter& pakOut, - const std::unordered_map>& mlvlData); + void readCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAMLDocWriter& nameWriter); + bool addFileToIndex(const hecl::ProjectPath& path, athena::io::YAMLDocWriter& cacheWriter); + void backgroundIndexRecursiveProc(const hecl::ProjectPath& path, athena::io::YAMLDocWriter& cacheWriter, + athena::io::YAMLDocWriter& nameWriter, int level); + void backgroundIndexRecursiveCatalogs(const hecl::ProjectPath& path, athena::io::YAMLDocWriter& nameWriter, + int level); + void backgroundIndexProc(); - std::unique_ptr m_disc; - bool m_isWii; - bool m_standalone; + void recursiveBuildResourceList(std::vector& listOut, + std::unordered_set& addedTags, const hecl::ProjectPath& path, + hecl::blender::Token& btok); + void copyBuildListData(std::vector>& fileIndex, + const std::vector& buildList, const hecl::Database::DataSpecEntry* entry, + bool fast, const hecl::MultiProgressPrinter& progress, athena::io::FileWriter& pakOut, + const std::unordered_map>& mlvlData); + + std::unique_ptr m_disc; + bool m_isWii; + bool m_standalone; }; -} - - +} // namespace DataSpec diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index d28c808c3..5826335ab 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -53,8 +53,7 @@ #include "hecl/Blender/SDNARead.hpp" #include "nod/nod.hpp" -namespace DataSpec -{ +namespace DataSpec { using namespace std::literals; @@ -63,356 +62,300 @@ extern hecl::Database::DataSpecEntry SpecEntMP1; extern hecl::Database::DataSpecEntry SpecEntMP1PC; extern hecl::Database::DataSpecEntry SpecEntMP1ORIG; -static const std::unordered_set IndividualOrigIDs = -{ - 0xB7BBD0B4, - 0x1F9DA858, - 0x2A13C23E, - 0xF13452F8, - 0xA91A7703, - 0xC042EC91, - 0x12A12131, - 0x5F556002, - 0xA9798329, - 0xB306E26F, - 0xCD7B1ACA, - 0x8ADA8184, - 0x1A29C0E6, - 0x5D9F9796, - 0x951546A8, - 0x7946C4C5, - 0x409AA72E, +static const std::unordered_set IndividualOrigIDs = { + 0xB7BBD0B4, 0x1F9DA858, 0x2A13C23E, 0xF13452F8, 0xA91A7703, 0xC042EC91, 0x12A12131, 0x5F556002, 0xA9798329, + 0xB306E26F, 0xCD7B1ACA, 0x8ADA8184, 0x1A29C0E6, 0x5D9F9796, 0x951546A8, 0x7946C4C5, 0x409AA72E, }; -struct OriginalIDs -{ - static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project) - { - std::unordered_set addedIDs; - std::vector originalIDs; +struct OriginalIDs { + static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project) { + std::unordered_set addedIDs; + std::vector originalIDs; - pakRouter.enumerateResources([&](const DNAMP1::PAK::Entry* ent) { - if (ent->type == FOURCC('MLVL') || - ent->type == FOURCC('SCAN') || - ent->type == FOURCC('MREA') || - IndividualOrigIDs.find(ent->id.toUint32()) != IndividualOrigIDs.end()) - { - if (addedIDs.find(ent->id) == addedIDs.cend()) - { - addedIDs.insert(ent->id); - originalIDs.push_back(ent->id); - } - } - return true; - }); - std::sort(originalIDs.begin(), originalIDs.end()); - - athena::io::YAMLDocWriter yamlW("MP1OriginalIDs"); - for (const UniqueID32& id : originalIDs) - { - hecl::ProjectPath path = pakRouter.getWorking(id); - yamlW.writeString(id.toString().c_str(), path.getRelativePathUTF8()); + pakRouter.enumerateResources([&](const DNAMP1::PAK::Entry* ent) { + if (ent->type == FOURCC('MLVL') || ent->type == FOURCC('SCAN') || ent->type == FOURCC('MREA') || + IndividualOrigIDs.find(ent->id.toUint32()) != IndividualOrigIDs.end()) { + if (addedIDs.find(ent->id) == addedIDs.cend()) { + addedIDs.insert(ent->id); + originalIDs.push_back(ent->id); } - hecl::ProjectPath path(project.getProjectWorkingPath(), "MP1/!original_ids.yaml"); - path.makeDirChain(false); - athena::io::FileWriter fileW(path.getAbsolutePath()); - yamlW.finish(&fileW); + } + return true; + }); + std::sort(originalIDs.begin(), originalIDs.end()); + + athena::io::YAMLDocWriter yamlW("MP1OriginalIDs"); + for (const UniqueID32& id : originalIDs) { + hecl::ProjectPath path = pakRouter.getWorking(id); + yamlW.writeString(id.toString().c_str(), path.getRelativePathUTF8()); + } + hecl::ProjectPath path(project.getProjectWorkingPath(), "MP1/!original_ids.yaml"); + path.makeDirChain(false); + athena::io::FileWriter fileW(path.getAbsolutePath()); + yamlW.finish(&fileW); + } + + static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + hecl::Database::Project& project = inPath.getProject(); + athena::io::YAMLDocReader r; + athena::io::FileReader fr(inPath.getAbsolutePath()); + if (!fr.isOpen() || !r.parse(&fr)) + return; + + std::vector> originalIDs; + originalIDs.reserve(r.getRootNode()->m_mapChildren.size()); + for (const auto& node : r.getRootNode()->m_mapChildren) { + char* end = const_cast(node.first.c_str()); + u32 id = strtoul(end, &end, 16); + if (end != node.first.c_str() + 8) + continue; + + hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str()); + originalIDs.push_back(std::make_pair(id, path.hash().val32())); + } + std::sort(originalIDs.begin(), originalIDs.end(), + [](const std::pair& a, const std::pair& b) { + return a.first < b.first; + }); + + athena::io::FileWriter w(outPath.getAbsolutePath()); + w.writeUint32Big(originalIDs.size()); + for (const auto& idPair : originalIDs) { + idPair.first.write(w); + idPair.second.write(w); } - static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) - { - hecl::Database::Project& project = inPath.getProject(); - athena::io::YAMLDocReader r; - athena::io::FileReader fr(inPath.getAbsolutePath()); - if (!fr.isOpen() || !r.parse(&fr)) - return; - - std::vector> originalIDs; - originalIDs.reserve(r.getRootNode()->m_mapChildren.size()); - for (const auto& node : r.getRootNode()->m_mapChildren) - { - char* end = const_cast(node.first.c_str()); - u32 id = strtoul(end, &end, 16); - if (end != node.first.c_str() + 8) - continue; - - hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str()); - originalIDs.push_back(std::make_pair(id, path.hash().val32())); - } - std::sort(originalIDs.begin(), originalIDs.end(), - [](const std::pair& a, const std::pair& b) { - return a.first < b.first; - }); - - athena::io::FileWriter w(outPath.getAbsolutePath()); - w.writeUint32Big(originalIDs.size()); - for (const auto& idPair : originalIDs) - { - idPair.first.write(w); - idPair.second.write(w); - } - - std::sort(originalIDs.begin(), originalIDs.end(), - [](const std::pair& a, const std::pair& b) { - return a.second < b.second; - }); - for (const auto& idPair : originalIDs) - { - idPair.second.write(w); - idPair.first.write(w); - } + std::sort(originalIDs.begin(), originalIDs.end(), + [](const std::pair& a, const std::pair& b) { + return a.second < b.second; + }); + for (const auto& idPair : originalIDs) { + idPair.second.write(w); + idPair.first.write(w); } + } }; -struct SpecMP1 : SpecBase -{ - bool checkStandaloneID(const char* id) const - { - return !memcmp(id, "GM8", 3); - } +struct SpecMP1 : SpecBase { + bool checkStandaloneID(const char* id) const { return !memcmp(id, "GM8", 3); } - std::vector m_nonPaks; - std::vector m_paks; - std::map m_orderedPaks; + std::vector m_nonPaks; + std::vector m_paks; + std::map m_orderedPaks; - hecl::ProjectPath m_workPath; - hecl::ProjectPath m_cookPath; - PAKRouter m_pakRouter; + hecl::ProjectPath m_workPath; + hecl::ProjectPath m_cookPath; + PAKRouter m_pakRouter; - std::unique_ptr m_dolBuf; + std::unique_ptr m_dolBuf; - IDRestorer m_idRestorer; + IDRestorer m_idRestorer; - std::unordered_map m_mreaPathToXF; + std::unordered_map m_mreaPathToXF; - void setThreadProject() - { - SpecBase::setThreadProject(); - UniqueIDBridge::SetIDRestorer(&m_idRestorer); - } + void setThreadProject() { + SpecBase::setThreadProject(); + UniqueIDBridge::SetIDRestorer(&m_idRestorer); + } - SpecMP1(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) - : SpecBase(specEntry, project, pc) - , m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP1")) - , m_cookPath(project.getProjectCookedPath(SpecEntMP1), _SYS_STR("MP1")) - , m_pakRouter(*this, m_workPath, m_cookPath) - , m_idRestorer({project.getProjectWorkingPath(), "MP1/!original_ids.yaml"}, project) - { - setThreadProject(); - } + SpecMP1(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) + : SpecBase(specEntry, project, pc) + , m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP1")) + , m_cookPath(project.getProjectCookedPath(SpecEntMP1), _SYS_STR("MP1")) + , m_pakRouter(*this, m_workPath, m_cookPath) + , m_idRestorer({project.getProjectWorkingPath(), "MP1/!original_ids.yaml"}, project) { + setThreadProject(); + } - void buildPaks(nod::Node& root, const std::vector& args, ExtractReport& rep) - { - m_nonPaks.clear(); - m_paks.clear(); - for (const nod::Node& child : root) - { - bool isPak = false; - auto name = child.getName(); - std::string lowerName(name); - std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); - if (name.size() > 4) - { - std::string::iterator extit = lowerName.end() - 4; - if (!std::string(extit, lowerName.end()).compare(".pak")) - { - /* This is a pak */ - isPak = true; - std::string lowerBase(lowerName.begin(), extit); + void buildPaks(nod::Node& root, const std::vector& args, ExtractReport& rep) { + m_nonPaks.clear(); + m_paks.clear(); + for (const nod::Node& child : root) { + bool isPak = false; + auto name = child.getName(); + std::string lowerName(name); + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); + if (name.size() > 4) { + std::string::iterator extit = lowerName.end() - 4; + if (!std::string(extit, lowerName.end()).compare(".pak")) { + /* This is a pak */ + isPak = true; + std::string lowerBase(lowerName.begin(), extit); - /* Needs filter */ - bool good = true; - if (args.size()) - { - good = false; - if (!lowerName.compare(0, 7, "metroid")) - { - hecl::SystemChar idxChar = lowerName[7]; - for (const hecl::SystemString& arg : args) - { - if (arg.size() == 1 && iswdigit(arg[0])) - if (arg[0] == idxChar) - good = true; - } - } - else - good = true; + /* Needs filter */ + bool good = true; + if (args.size()) { + good = false; + if (!lowerName.compare(0, 7, "metroid")) { + hecl::SystemChar idxChar = lowerName[7]; + for (const hecl::SystemString& arg : args) { + if (arg.size() == 1 && iswdigit(arg[0])) + if (arg[0] == idxChar) + good = true; + } + } else + good = true; - if (!good) - { - for (const hecl::SystemString& arg : args) - { - std::string lowerArg(hecl::SystemUTF8Conv(arg).str()); - std::transform(lowerArg.begin(), lowerArg.end(), lowerArg.begin(), tolower); - if (!lowerArg.compare(0, lowerBase.size(), lowerBase)) - good = true; - } - } - } - - m_paks.emplace_back(child, good); - } + if (!good) { + for (const hecl::SystemString& arg : args) { + std::string lowerArg(hecl::SystemUTF8Conv(arg).str()); + std::transform(lowerArg.begin(), lowerArg.end(), lowerArg.begin(), tolower); + if (!lowerArg.compare(0, lowerBase.size(), lowerBase)) + good = true; + } } + } - if (!isPak) - m_nonPaks.push_back(&child); + m_paks.emplace_back(child, good); } + } - /* Sort PAKs alphabetically */ - m_orderedPaks.clear(); - for (DNAMP1::PAKBridge& dpak : m_paks) - m_orderedPaks[std::string(dpak.getName())] = &dpak; - - /* Assemble extract report */ - rep.childOpts.reserve(m_orderedPaks.size()); - for (const std::pair& item : m_orderedPaks) - { - if (!item.second->m_doExtract) - continue; - rep.childOpts.emplace_back(); - ExtractReport& childRep = rep.childOpts.back(); - hecl::SystemStringConv nameView(item.first); - childRep.name = nameView.sys_str(); - childRep.desc = item.second->getLevelString(); - } + if (!isPak) + m_nonPaks.push_back(&child); } - bool checkFromStandaloneDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, - const std::vector& args, std::vector& reps) - { - nod::IPartition* partition = disc.getDataPartition(); - m_dolBuf = partition->getDOLBuf(); - const char* buildInfo = (char*)memmem(m_dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19; + /* Sort PAKs alphabetically */ + m_orderedPaks.clear(); + for (DNAMP1::PAKBridge& dpak : m_paks) + m_orderedPaks[std::string(dpak.getName())] = &dpak; - if (!buildInfo) - return false; + /* Assemble extract report */ + rep.childOpts.reserve(m_orderedPaks.size()); + for (const std::pair& item : m_orderedPaks) { + if (!item.second->m_doExtract) + continue; + rep.childOpts.emplace_back(); + ExtractReport& childRep = rep.childOpts.back(); + hecl::SystemStringConv nameView(item.first); + childRep.name = nameView.sys_str(); + childRep.desc = item.second->getLevelString(); + } + } - /* Root Report */ - reps.emplace_back(); - ExtractReport& rep = reps.back(); - rep.name = _SYS_STR("MP1"); - rep.desc = _SYS_STR("Metroid Prime ") + regstr; - if (buildInfo) - { - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); - rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); - } + bool checkFromStandaloneDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, + const std::vector& args, std::vector& reps) { + nod::IPartition* partition = disc.getDataPartition(); + m_dolBuf = partition->getDOLBuf(); + const char* buildInfo = (char*)memmem(m_dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19; - /* Iterate PAKs and build level options */ - nod::Node& root = partition->getFSTRoot(); - buildPaks(root, args, rep); + if (!buildInfo) + return false; - return true; + /* Root Report */ + reps.emplace_back(); + ExtractReport& rep = reps.back(); + rep.name = _SYS_STR("MP1"); + rep.desc = _SYS_STR("Metroid Prime ") + regstr; + if (buildInfo) { + std::string buildStr(buildInfo); + hecl::SystemStringConv buildView(buildStr); + rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); } - bool checkFromTrilogyDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, - const std::vector& args, std::vector& reps) - { - std::vector mp1args; - bool doExtract = false; - if (args.size()) - { - /* Needs filter */ - for (const hecl::SystemString& arg : args) - { - hecl::SystemString lowerArg = arg; - hecl::ToLower(lowerArg); - if (!lowerArg.compare(0, 3, _SYS_STR("mp1"))) - { - doExtract = true; - mp1args.reserve(args.size()); - size_t slashPos = arg.find(_SYS_STR('/')); - if (slashPos == hecl::SystemString::npos) - slashPos = arg.find(_SYS_STR('\\')); - if (slashPos != hecl::SystemString::npos) - mp1args.emplace_back(hecl::SystemString(arg.begin() + slashPos + 1, arg.end())); - } - } + /* Iterate PAKs and build level options */ + nod::Node& root = partition->getFSTRoot(); + buildPaks(root, args, rep); + + return true; + } + + bool checkFromTrilogyDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, + const std::vector& args, std::vector& reps) { + std::vector mp1args; + bool doExtract = false; + if (args.size()) { + /* Needs filter */ + for (const hecl::SystemString& arg : args) { + hecl::SystemString lowerArg = arg; + hecl::ToLower(lowerArg); + if (!lowerArg.compare(0, 3, _SYS_STR("mp1"))) { + doExtract = true; + mp1args.reserve(args.size()); + size_t slashPos = arg.find(_SYS_STR('/')); + if (slashPos == hecl::SystemString::npos) + slashPos = arg.find(_SYS_STR('\\')); + if (slashPos != hecl::SystemString::npos) + mp1args.emplace_back(hecl::SystemString(arg.begin() + slashPos + 1, arg.end())); } - else - doExtract = true; + } + } else + doExtract = true; - if (!doExtract) - return false; + if (!doExtract) + return false; - nod::IPartition* partition = disc.getDataPartition(); - nod::Node& root = partition->getFSTRoot(); - nod::Node::DirectoryIterator dolIt = root.find("rs5mp1_p.dol"); - if (dolIt == root.end()) - { - dolIt = root.find("rs5mp1jpn_p.dol"); - if (dolIt == root.end()) - return false; - } - - m_dolBuf = dolIt->getBuf(); - const char* buildInfo = (char*)memmem(m_dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; - - /* Root Report */ - reps.emplace_back(); - ExtractReport& rep = reps.back(); - rep.name = _SYS_STR("MP1"); - rep.desc = _SYS_STR("Metroid Prime ") + regstr; - if (buildInfo) - { - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); - rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); - } - - /* Iterate PAKs and build level options */ - nod::Node::DirectoryIterator mp1It = root.find("MP1"); - if (mp1It == root.end()) - { - mp1It = root.find("MP1JPN"); - if (mp1It == root.end()) - return false; - } - buildPaks(*mp1It, mp1args, rep); - - return true; + nod::IPartition* partition = disc.getDataPartition(); + nod::Node& root = partition->getFSTRoot(); + nod::Node::DirectoryIterator dolIt = root.find("rs5mp1_p.dol"); + if (dolIt == root.end()) { + dolIt = root.find("rs5mp1jpn_p.dol"); + if (dolIt == root.end()) + return false; } - bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) - { - m_project.enableDataSpecs({_SYS_STR("MP1-PC")}); + m_dolBuf = dolIt->getBuf(); + const char* buildInfo = (char*)memmem(m_dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; - nod::ExtractionContext ctx = {force, nullptr}; + /* Root Report */ + reps.emplace_back(); + ExtractReport& rep = reps.back(); + rep.name = _SYS_STR("MP1"); + rep.desc = _SYS_STR("Metroid Prime ") + regstr; + if (buildInfo) { + std::string buildStr(buildInfo); + hecl::SystemStringConv buildView(buildStr); + rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); + } - m_workPath.makeDir(); + /* Iterate PAKs and build level options */ + nod::Node::DirectoryIterator mp1It = root.find("MP1"); + if (mp1It == root.end()) { + mp1It = root.find("MP1JPN"); + if (mp1It == root.end()) + return false; + } + buildPaks(*mp1It, mp1args, rep); - progress.startNewLine(); - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 0.0); - m_pakRouter.build(m_paks, [&progress](float factor) { progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), factor); }); - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 1.0); + return true; + } - hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _SYS_STR("out")); - outPath.makeDir(); - disc.getDataPartition()->extractSysFiles(outPath.getAbsolutePath(), ctx); - hecl::ProjectPath mp1OutPath(outPath, m_standalone ? _SYS_STR("files") : _SYS_STR("files/MP1")); - mp1OutPath.makeDirChain(true); + bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) { + m_project.enableDataSpecs({_SYS_STR("MP1-PC")}); - /* Extract non-pak files */ - progress.startNewLine(); - progress.print(_SYS_STR("MP1 Root"), _SYS_STR(""), 0.0); - int prog = 0; - ctx.progressCB = [&](std::string_view name, float) { - hecl::SystemStringConv nameView(name); - progress.print(_SYS_STR("MP1 Root"), nameView.c_str(), prog / (float)m_nonPaks.size()); - }; - for (const nod::Node* node : m_nonPaks) - { - node->extractToDirectory(mp1OutPath.getAbsolutePath(), ctx); - prog++; - } - progress.print(_SYS_STR("MP1 Root"), _SYS_STR(""), 1.0); + nod::ExtractionContext ctx = {force, nullptr}; - /* Extract unique resources */ - hecl::ClientProcess process; - progress.startNewLine(); - for (std::pair& pair : m_orderedPaks) - { + m_workPath.makeDir(); + + progress.startNewLine(); + progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 0.0); + m_pakRouter.build(m_paks, + [&progress](float factor) { progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), factor); }); + progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 1.0); + + hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _SYS_STR("out")); + outPath.makeDir(); + disc.getDataPartition()->extractSysFiles(outPath.getAbsolutePath(), ctx); + hecl::ProjectPath mp1OutPath(outPath, m_standalone ? _SYS_STR("files") : _SYS_STR("files/MP1")); + mp1OutPath.makeDirChain(true); + + /* Extract non-pak files */ + progress.startNewLine(); + progress.print(_SYS_STR("MP1 Root"), _SYS_STR(""), 0.0); + int prog = 0; + ctx.progressCB = [&](std::string_view name, float) { + hecl::SystemStringConv nameView(name); + progress.print(_SYS_STR("MP1 Root"), nameView.c_str(), prog / (float)m_nonPaks.size()); + }; + for (const nod::Node* node : m_nonPaks) { + node->extractToDirectory(mp1OutPath.getAbsolutePath(), ctx); + prog++; + } + progress.print(_SYS_STR("MP1 Root"), _SYS_STR(""), 1.0); + + /* Extract unique resources */ + hecl::ClientProcess process; + progress.startNewLine(); + for (std::pair& pair : m_orderedPaks) { #if 0 const DNAMP1::PAK::Entry* ent = pair.second->getPAK().lookupEntry(UniqueID32("A4DFCAD6")); if (ent) @@ -426,1126 +369,922 @@ struct SpecMP1 : SpecBase continue; #endif - DNAMP1::PAKBridge& pak = *pair.second; - if (!pak.m_doExtract) - continue; + DNAMP1::PAKBridge& pak = *pair.second; + if (!pak.m_doExtract) + continue; - auto name = pak.getName(); - hecl::SystemStringConv sysName(name); + auto name = pak.getName(); + hecl::SystemStringConv sysName(name); - auto pakName = hecl::SystemString(sysName.sys_str()); - process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) { - int threadIdx = hecl::ClientProcess::GetThreadWorkerIdx(); - m_pakRouter.extractResources(pak, force, btok, - [&progress, &pakName, threadIdx](const hecl::SystemChar* substr, float factor) { - progress.print(pakName.c_str(), substr, factor, threadIdx); - }); - }); - } + auto pakName = hecl::SystemString(sysName.sys_str()); + process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) { + int threadIdx = hecl::ClientProcess::GetThreadWorkerIdx(); + m_pakRouter.extractResources(pak, force, btok, + [&progress, &pakName, threadIdx](const hecl::SystemChar* substr, float factor) { + progress.print(pakName.c_str(), substr, factor, threadIdx); + }); + }); + } - process.waitUntilComplete(); + process.waitUntilComplete(); - /* Extract part of .dol for RandomStatic entropy */ - hecl::ProjectPath noAramPath(m_project.getProjectWorkingPath(), _SYS_STR("MP1/NoARAM")); - extractRandomStaticEntropy(m_dolBuf.get() + 0x4f60, noAramPath); + /* Extract part of .dol for RandomStatic entropy */ + hecl::ProjectPath noAramPath(m_project.getProjectWorkingPath(), _SYS_STR("MP1/NoARAM")); + extractRandomStaticEntropy(m_dolBuf.get() + 0x4f60, noAramPath); - /* Generate original ID mapping for MLVL and SCAN entries - marks complete project */ - OriginalIDs::Generate(m_pakRouter, m_project); + /* Generate original ID mapping for MLVL and SCAN entries - marks complete project */ + OriginalIDs::Generate(m_pakRouter, m_project); + return true; + } + + const hecl::Database::DataSpecEntry& getOriginalSpec() const { return SpecEntMP1; } + + const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const { return SpecEntMP1ORIG; } + + hecl::ProjectPath getWorking(class UniqueID32& id) { return m_pakRouter.getWorking(id); } + + bool checkPathPrefix(const hecl::ProjectPath& path) const { + return path.getRelativePath().compare(0, 4, _SYS_STR("MP1/")) == 0; + } + + bool validateYAMLDNAType(athena::io::IStreamReader& fp) const { + athena::io::YAMLDocReader reader; + yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)athena::io::YAMLAthenaReader, &fp); + return reader.ClassTypeOperation([](const char* classType) { + if (!strcmp(classType, DNAMP1::MLVL::DNAType())) return true; + else if (!strcmp(classType, DNAMP1::STRG::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::SCAN::DNAType())) + return true; + else if (!strcmp(classType, DNAParticle::GPSM::DNAType())) + return true; + else if (!strcmp(classType, DNAParticle::SWSH::DNAType())) + return true; + else if (!strcmp(classType, DNAParticle::ELSM::DNAType())) + return true; + else if (!strcmp(classType, DNAParticle::WPSM::DNAType())) + return true; + else if (!strcmp(classType, DNAParticle::CRSM::DNAType())) + return true; + else if (!strcmp(classType, DNAParticle::DPSM::DNAType())) + return true; + else if (!strcmp(classType, DNADGRP::DGRP::DNAType())) + return true; + else if (!strcmp(classType, DNAFont::FONT::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakPlayerRes::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakGunRes::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakSlideShow::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakPlayer::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakCameraBob::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakGame::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakAutoMapper::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakTargeting::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakGui::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakPlayerControl::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakBall::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakParticle::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakGuiColors::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::CTweakPlayerGun::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::HINT::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::EVNT::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::MazeSeeds::DNAType())) + return true; + else if (!strcmp(classType, DNAMP1::SnowForces::DNAType())) + return true; + else if (!strcmp(classType, "ATBL")) + return true; + else if (!strcmp(classType, DNAMP1::AFSM::DNAType())) + return true; + else if (!strcmp(classType, "MP1OriginalIDs")) + return true; + return false; + }); + } + + urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { + if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CINF"))) + return {SBIG('CINF'), path.hash().val32()}; + else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CSKR"))) + return {SBIG('CSKR'), path.hash().val32()}; + else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".ANIM"))) + return {SBIG('ANIM'), path.hash().val32()}; + else if (const hecl::SystemChar* ext = path.getLastComponentExt().data()) { + if (ext[0] == _SYS_STR('*') || !hecl::StrCmp(ext, _SYS_STR("mid"))) { + if (path.getWithExtension(_SYS_STR(".mid"), true).isFile() && + path.getWithExtension(_SYS_STR(".yaml"), true).isFile()) { + hecl::ProjectPath glob = path.getWithExtension(_SYS_STR(".*"), true); + return {SBIG('CSNG'), glob.hash().val32()}; + } + } } - const hecl::Database::DataSpecEntry& getOriginalSpec() const { return SpecEntMP1; } - - const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const { return SpecEntMP1ORIG; } - - hecl::ProjectPath getWorking(class UniqueID32& id) { return m_pakRouter.getWorking(id); } - - bool checkPathPrefix(const hecl::ProjectPath& path) const - { - return path.getRelativePath().compare(0, 4, _SYS_STR("MP1/")) == 0; + if (path.getPathType() == hecl::ProjectPath::Type::Directory) { + if (hecl::ProjectPath(path, _SYS_STR("!project.yaml")).isFile() && + hecl::ProjectPath(path, _SYS_STR("!pool.yaml")).isFile()) + return {SBIG('AGSC'), path.hash().val32()}; } - bool validateYAMLDNAType(athena::io::IStreamReader& fp) const - { - athena::io::YAMLDocReader reader; - yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)athena::io::YAMLAthenaReader, &fp); - return reader.ClassTypeOperation([](const char* classType) { - if (!strcmp(classType, DNAMP1::MLVL::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::STRG::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::SCAN::DNAType())) - return true; - else if (!strcmp(classType, DNAParticle::GPSM::DNAType())) - return true; - else if (!strcmp(classType, DNAParticle::SWSH::DNAType())) - return true; - else if (!strcmp(classType, DNAParticle::ELSM::DNAType())) - return true; - else if (!strcmp(classType, DNAParticle::WPSM::DNAType())) - return true; - else if (!strcmp(classType, DNAParticle::CRSM::DNAType())) - return true; - else if (!strcmp(classType, DNAParticle::DPSM::DNAType())) - return true; - else if (!strcmp(classType, DNADGRP::DGRP::DNAType())) - return true; - else if (!strcmp(classType, DNAFont::FONT::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakPlayerRes::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakGunRes::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakSlideShow::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakPlayer::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakCameraBob::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakGame::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakAutoMapper::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakTargeting::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakGui::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakPlayerControl::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakBall::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakParticle::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakGuiColors::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::CTweakPlayerGun::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::HINT::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::EVNT::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::MazeSeeds::DNAType())) - return true; - else if (!strcmp(classType, DNAMP1::SnowForces::DNAType())) - return true; - else if (!strcmp(classType, "ATBL")) - return true; - else if (!strcmp(classType, DNAMP1::AFSM::DNAType())) - return true; - else if (!strcmp(classType, "MP1OriginalIDs")) - return true; - return false; - }); - } + hecl::ProjectPath asBlend; + if (path.getPathType() == hecl::ProjectPath::Type::Glob) + asBlend = path.getWithExtension(_SYS_STR(".blend"), true); + else + asBlend = path; - urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const - { - if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CINF"))) - return {SBIG('CINF'), path.hash().val32()}; - else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CSKR"))) - return {SBIG('CSKR'), path.hash().val32()}; - else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".ANIM"))) - return {SBIG('ANIM'), path.hash().val32()}; - else if (const hecl::SystemChar* ext = path.getLastComponentExt().data()) - { - if (ext[0] == _SYS_STR('*') || !hecl::StrCmp(ext, _SYS_STR("mid"))) - { - if (path.getWithExtension(_SYS_STR(".mid"), true).isFile() && - path.getWithExtension(_SYS_STR(".yaml"), true).isFile()) - { - hecl::ProjectPath glob = path.getWithExtension(_SYS_STR(".*"), true); - return {SBIG('CSNG'), glob.hash().val32()}; - } - } + if (hecl::IsPathBlend(asBlend)) { + switch (hecl::blender::GetBlendType(asBlend.getAbsolutePath())) { + case hecl::blender::BlendType::Mesh: + return {SBIG('CMDL'), path.hash().val32()}; + case hecl::blender::BlendType::ColMesh: + return {SBIG('DCLN'), path.hash().val32()}; + case hecl::blender::BlendType::PathMesh: + return {SBIG('PATH'), path.hash().val32()}; + case hecl::blender::BlendType::Actor: + if (path.getAuxInfo().size()) { + if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CINF"))) + return {SBIG('CINF'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; + else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CSKR"))) + return {SBIG('CSKR'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; + else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".ANIM"))) + return {SBIG('ANIM'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; } - - if (path.getPathType() == hecl::ProjectPath::Type::Directory) - { - if (hecl::ProjectPath(path, _SYS_STR("!project.yaml")).isFile() && - hecl::ProjectPath(path, _SYS_STR("!pool.yaml")).isFile()) - return {SBIG('AGSC'), path.hash().val32()}; - } - - hecl::ProjectPath asBlend; - if (path.getPathType() == hecl::ProjectPath::Type::Glob) - asBlend = path.getWithExtension(_SYS_STR(".blend"), true); - else - asBlend = path; - - if (hecl::IsPathBlend(asBlend)) - { - switch (hecl::blender::GetBlendType(asBlend.getAbsolutePath())) - { - case hecl::blender::BlendType::Mesh: - return {SBIG('CMDL'), path.hash().val32()}; - case hecl::blender::BlendType::ColMesh: - return {SBIG('DCLN'), path.hash().val32()}; - case hecl::blender::BlendType::PathMesh: - return {SBIG('PATH'), path.hash().val32()}; - case hecl::blender::BlendType::Actor: - if (path.getAuxInfo().size()) - { - if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CINF"))) - return {SBIG('CINF'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; - else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".CSKR"))) - return {SBIG('CSKR'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; - else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR(".ANIM"))) - return {SBIG('ANIM'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; - } - return {SBIG('ANCS'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; - case hecl::blender::BlendType::Area: - return {SBIG('MREA'), path.hash().val32()}; - case hecl::blender::BlendType::World: - { - if (path.getAuxInfo().size()) - { - if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR("MAPW"))) - return {SBIG('MAPW'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; - else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR("SAVW"))) - return {SBIG('SAVW'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; - } - return {SBIG('MLVL'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; - } - case hecl::blender::BlendType::MapArea: - return {SBIG('MAPA'), path.hash().val32()}; - case hecl::blender::BlendType::MapUniverse: - return {SBIG('MAPU'), path.hash().val32()}; - case hecl::blender::BlendType::Frame: - return {SBIG('FRME'), path.hash().val32()}; - default: - return {}; - } - } - else if (hecl::IsPathPNG(path)) - { - return {SBIG('TXTR'), path.hash().val32()}; - } - else if (hecl::IsPathYAML(path)) - { - FILE* fp = hecl::Fopen(path.getAbsolutePath().data(), _SYS_STR("r")); - if (!fp) - return {}; - - athena::io::YAMLDocReader reader; - yaml_parser_set_input_file(reader.getParser(), fp); - - urde::SObjectTag resTag; - if (reader.ClassTypeOperation([&](const char* className) -> bool { - if (!strcmp(className, DNAParticle::GPSM::DNAType())) - { - resTag.type = SBIG('PART'); - return true; - } - if (!strcmp(className, DNAParticle::SWSH::DNAType())) - { - resTag.type = SBIG('SWHC'); - return true; - } - if (!strcmp(className, DNAParticle::ELSM::DNAType())) - { - resTag.type = SBIG('ELSC'); - return true; - } - if (!strcmp(className, DNAParticle::WPSM::DNAType())) - { - resTag.type = SBIG('WPSC'); - return true; - } - if (!strcmp(className, DNAParticle::CRSM::DNAType())) - { - resTag.type = SBIG('CRSC'); - return true; - } - if (!strcmp(className, DNAParticle::DPSM::DNAType())) - { - resTag.type = SBIG('DPSC'); - return true; - } - else if (!strcmp(className, DNAFont::FONT::DNAType())) - { - resTag.type = SBIG('FONT'); - return true; - } - else if (!strcmp(className, DNAMP1::EVNT::DNAType())) - { - resTag.type = SBIG('EVNT'); - return true; - } - else if (!strcmp(className, DNADGRP::DGRP::DNAType())) - { - resTag.type = SBIG('DGRP'); - return true; - } - else if (!strcmp(className, DataSpec::DNAMP1::STRG::DNAType())) - { - resTag.type = SBIG('STRG'); - return true; - } - else if (!strcmp(className, DataSpec::DNAMP1::SCAN::DNAType())) - { - resTag.type = SBIG('SCAN'); - return true; - } - else if (!strcmp(className, DataSpec::DNAMP1::CTweakPlayerRes::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakGunRes::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakSlideShow::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakPlayer::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakCameraBob::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakGame::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakTargeting::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakAutoMapper::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakGui::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakPlayerControl::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakBall::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakParticle::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakGuiColors::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::CTweakPlayerGun::DNAType())) - { - resTag.type = SBIG('CTWK'); - return true; - } - else if (!strcmp(className, DataSpec::DNAMP1::MazeSeeds::DNAType()) || - !strcmp(className, DataSpec::DNAMP1::SnowForces::DNAType())) - { - resTag.type = SBIG('DUMB'); - return true; - } - else if (!strcmp(className, DataSpec::DNAMP1::HINT::DNAType())) - { - resTag.type = SBIG('HINT'); - return true; - } - else if (!strcmp(className, "ATBL")) - { - resTag.type = SBIG('ATBL'); - return true; - } - else if (!strcmp(className, DataSpec::DNAMP1::AFSM::DNAType())) - { - resTag.type = SBIG('AFSM'); - return true; - } - else if (!strcmp(className, "MP1OriginalIDs")) - { - resTag.type = SBIG('OIDS'); - return true; - } - - return false; - })) - { - resTag.id = path.hash().val32(); - fclose(fp); - return resTag; - } - fclose(fp); + return {SBIG('ANCS'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; + case hecl::blender::BlendType::Area: + return {SBIG('MREA'), path.hash().val32()}; + case hecl::blender::BlendType::World: { + if (path.getAuxInfo().size()) { + if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR("MAPW"))) + return {SBIG('MAPW'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; + else if (hecl::StringUtils::EndsWith(path.getAuxInfo(), _SYS_STR("SAVW"))) + return {SBIG('SAVW'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; } + return {SBIG('MLVL'), path.getWithExtension(_SYS_STR(".*"), true).hash().val32()}; + } + case hecl::blender::BlendType::MapArea: + return {SBIG('MAPA'), path.hash().val32()}; + case hecl::blender::BlendType::MapUniverse: + return {SBIG('MAPU'), path.hash().val32()}; + case hecl::blender::BlendType::Frame: + return {SBIG('FRME'), path.hash().val32()}; + default: + return {}; + } + } else if (hecl::IsPathPNG(path)) { + return {SBIG('TXTR'), path.hash().val32()}; + } else if (hecl::IsPathYAML(path)) { + FILE* fp = hecl::Fopen(path.getAbsolutePath().data(), _SYS_STR("r")); + if (!fp) return {}; - } - void getTagListForFile(const char* pakName, std::vector& out) const - { - std::string pathPrefix("MP1/"); - pathPrefix += pakName; - pathPrefix += '/'; + athena::io::YAMLDocReader reader; + yaml_parser_set_input_file(reader.getParser(), fp); - std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); - for (const auto& tag : m_tagToPath) - if (!tag.second.getRelativePathUTF8().compare(0, pathPrefix.size(), pathPrefix)) - out.push_back(tag.first); - } - - void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, - hecl::blender::Token& btok, FCookProgress progress) - { - Mesh mesh = - ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, m_pc ? 16 : -1, - [&progress](int surfCount) { progress(hecl::SysFormat(_SYS_STR("%d"), surfCount).c_str()); }); - - if (m_pc) - DNAMP1::CMDL::HMDLCook(out, in, mesh); - else - DNAMP1::CMDL::Cook(out, in, mesh); - } - - void cookColMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, - hecl::blender::Token& btok, FCookProgress progress) - { - std::vector mesh = ds.compileColMeshes(); - ds.close(); - DNAMP1::DCLN::Cook(out, mesh); - } - - void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, - hecl::blender::Token& btok, FCookProgress progress) - { - PathMesh mesh = ds.compilePathMesh(); - ds.close(); - DNAMP1::PATH::Cook(out, mesh); - } - - void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, - hecl::blender::Token& btok, FCookProgress progress) - { - if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR(".CINF"))) - { - Actor actor = ds.compileActorCharacterOnly(); - DNAMP1::ANCS::CookCINF(out, in, actor); - } - else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR(".CSKR"))) - { - Actor actor = ds.compileActorCharacterOnly(); - ds.close(); - if (m_pc) - { - DNAMP1::ANCS::CookCSKRPC(out, in, actor, [&](const hecl::ProjectPath& modelPath) { - hecl::ProjectPath cooked = modelPath.getCookedPath(SpecEntMP1PC); - doCook(modelPath, cooked, fast, btok, progress); - return true; - }); + urde::SObjectTag resTag; + if (reader.ClassTypeOperation([&](const char* className) -> bool { + if (!strcmp(className, DNAParticle::GPSM::DNAType())) { + resTag.type = SBIG('PART'); + return true; } - else - { - DNAMP1::ANCS::CookCSKR(out, in, actor, [&](const hecl::ProjectPath& modelPath) { - hecl::ProjectPath cooked = modelPath.getCookedPath(SpecEntMP1); - doCook(modelPath, cooked, fast, btok, progress); - return true; - }); + if (!strcmp(className, DNAParticle::SWSH::DNAType())) { + resTag.type = SBIG('SWHC'); + return true; } - } - else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR(".ANIM"))) - { - Actor actor = ds.compileActorCharacterOnly(); - DNAMP1::ANCS::CookANIM(out, in, actor, ds, m_pc); - } - else - { - Actor actor = ds.compileActor(); - DNAMP1::ANCS::Cook(out, in, actor); - } - } - - void buildAreaXFs(hecl::blender::Token& btok) - { - hecl::blender::Connection& conn = btok.getBlenderConnection(); - for (const auto& ent : m_workPath.enumerateDir()) - { - if (ent.m_isDir) - { - hecl::ProjectPath pakPath(m_workPath, ent.m_name); - for (const auto& ent2 : pakPath.enumerateDir()) - { - if (ent2.m_isDir) - { - hecl::ProjectPath wldPath(pakPath, ent2.m_name + _SYS_STR("/!world.blend")); - if (wldPath.isFile()) - { - if (!conn.openBlend(wldPath)) - continue; - hecl::blender::DataStream ds = conn.beginData(); - hecl::blender::World world = ds.compileWorld(); - for (const auto& area : world.areas) - m_mreaPathToXF[area.path.hash()] = area.transform; - } - } - } + if (!strcmp(className, DNAParticle::ELSM::DNAType())) { + resTag.type = SBIG('ELSC'); + return true; } - } + if (!strcmp(className, DNAParticle::WPSM::DNAType())) { + resTag.type = SBIG('WPSC'); + return true; + } + if (!strcmp(className, DNAParticle::CRSM::DNAType())) { + resTag.type = SBIG('CRSC'); + return true; + } + if (!strcmp(className, DNAParticle::DPSM::DNAType())) { + resTag.type = SBIG('DPSC'); + return true; + } else if (!strcmp(className, DNAFont::FONT::DNAType())) { + resTag.type = SBIG('FONT'); + return true; + } else if (!strcmp(className, DNAMP1::EVNT::DNAType())) { + resTag.type = SBIG('EVNT'); + return true; + } else if (!strcmp(className, DNADGRP::DGRP::DNAType())) { + resTag.type = SBIG('DGRP'); + return true; + } else if (!strcmp(className, DataSpec::DNAMP1::STRG::DNAType())) { + resTag.type = SBIG('STRG'); + return true; + } else if (!strcmp(className, DataSpec::DNAMP1::SCAN::DNAType())) { + resTag.type = SBIG('SCAN'); + return true; + } else if (!strcmp(className, DataSpec::DNAMP1::CTweakPlayerRes::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakGunRes::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakSlideShow::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakPlayer::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakCameraBob::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakGame::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakTargeting::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakAutoMapper::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakGui::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakPlayerControl::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakBall::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakParticle::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakGuiColors::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::CTweakPlayerGun::DNAType())) { + resTag.type = SBIG('CTWK'); + return true; + } else if (!strcmp(className, DataSpec::DNAMP1::MazeSeeds::DNAType()) || + !strcmp(className, DataSpec::DNAMP1::SnowForces::DNAType())) { + resTag.type = SBIG('DUMB'); + return true; + } else if (!strcmp(className, DataSpec::DNAMP1::HINT::DNAType())) { + resTag.type = SBIG('HINT'); + return true; + } else if (!strcmp(className, "ATBL")) { + resTag.type = SBIG('ATBL'); + return true; + } else if (!strcmp(className, DataSpec::DNAMP1::AFSM::DNAType())) { + resTag.type = SBIG('AFSM'); + return true; + } else if (!strcmp(className, "MP1OriginalIDs")) { + resTag.type = SBIG('OIDS'); + return true; + } + + return false; + })) { + resTag.id = path.hash().val32(); + fclose(fp); + return resTag; + } + fclose(fp); } + return {}; + } - void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, - hecl::blender::Token& btok, FCookProgress progress) - { - std::vector meshes = ds.getMeshList(); - std::vector meshCompiles; - meshCompiles.reserve(meshes.size()); + void getTagListForFile(const char* pakName, std::vector& out) const { + std::string pathPrefix("MP1/"); + pathPrefix += pakName; + pathPrefix += '/'; - std::experimental::optional colMesh; + std::unique_lock lk(const_cast(*this).m_backgroundIndexMutex); + for (const auto& tag : m_tagToPath) + if (!tag.second.getRelativePathUTF8().compare(0, pathPrefix.size(), pathPrefix)) + out.push_back(tag.first); + } - for (const std::string& mesh : meshes) - { - hecl::SystemStringConv meshSys(mesh); - if (!mesh.compare("CMESH")) - { - colMesh = ds.compileColMesh(mesh); - progress(_SYS_STR("Collision Mesh")); + void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) { + Mesh mesh = + ds.compileMesh(fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, m_pc ? 16 : -1, + [&progress](int surfCount) { progress(hecl::SysFormat(_SYS_STR("%d"), surfCount).c_str()); }); + + if (m_pc) + DNAMP1::CMDL::HMDLCook(out, in, mesh); + else + DNAMP1::CMDL::Cook(out, in, mesh); + } + + void cookColMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) { + std::vector mesh = ds.compileColMeshes(); + ds.close(); + DNAMP1::DCLN::Cook(out, mesh); + } + + void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) { + PathMesh mesh = ds.compilePathMesh(); + ds.close(); + DNAMP1::PATH::Cook(out, mesh); + } + + void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) { + if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR(".CINF"))) { + Actor actor = ds.compileActorCharacterOnly(); + DNAMP1::ANCS::CookCINF(out, in, actor); + } else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR(".CSKR"))) { + Actor actor = ds.compileActorCharacterOnly(); + ds.close(); + if (m_pc) { + DNAMP1::ANCS::CookCSKRPC(out, in, actor, [&](const hecl::ProjectPath& modelPath) { + hecl::ProjectPath cooked = modelPath.getCookedPath(SpecEntMP1PC); + doCook(modelPath, cooked, fast, btok, progress); + return true; + }); + } else { + DNAMP1::ANCS::CookCSKR(out, in, actor, [&](const hecl::ProjectPath& modelPath) { + hecl::ProjectPath cooked = modelPath.getCookedPath(SpecEntMP1); + doCook(modelPath, cooked, fast, btok, progress); + return true; + }); + } + } else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR(".ANIM"))) { + Actor actor = ds.compileActorCharacterOnly(); + DNAMP1::ANCS::CookANIM(out, in, actor, ds, m_pc); + } else { + Actor actor = ds.compileActor(); + DNAMP1::ANCS::Cook(out, in, actor); + } + } + + void buildAreaXFs(hecl::blender::Token& btok) { + hecl::blender::Connection& conn = btok.getBlenderConnection(); + for (const auto& ent : m_workPath.enumerateDir()) { + if (ent.m_isDir) { + hecl::ProjectPath pakPath(m_workPath, ent.m_name); + for (const auto& ent2 : pakPath.enumerateDir()) { + if (ent2.m_isDir) { + hecl::ProjectPath wldPath(pakPath, ent2.m_name + _SYS_STR("/!world.blend")); + if (wldPath.isFile()) { + if (!conn.openBlend(wldPath)) continue; + hecl::blender::DataStream ds = conn.beginData(); + hecl::blender::World world = ds.compileWorld(); + for (const auto& area : world.areas) + m_mreaPathToXF[area.path.hash()] = area.transform; } - meshCompiles.push_back(ds.compileMesh( - mesh, fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1, !m_pc, - [&](int surfCount) { progress(hecl::SysFormat(_SYS_STR("%s %d"), meshSys.c_str(), surfCount).c_str()); })); + } } + } + } + } - if (!colMesh) - Log.report(logvisor::Fatal, _SYS_STR("unable to find mesh named 'CMESH' in %s"), in.getAbsolutePath().data()); + void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) { + std::vector meshes = ds.getMeshList(); + std::vector meshCompiles; + meshCompiles.reserve(meshes.size()); - std::vector lights = ds.compileLights(); + std::experimental::optional colMesh; - ds.close(); - - if (m_mreaPathToXF.empty()) - buildAreaXFs(btok); - - const hecl::blender::Matrix4f* xf = nullptr; - auto xfSearch = m_mreaPathToXF.find(in.getParentPath().hash()); - if (xfSearch != m_mreaPathToXF.cend()) - xf = &xfSearch->second; - DNAMP1::MREA::Cook(out, in, meshCompiles, *colMesh, lights, btok, xf, m_pc); + for (const std::string& mesh : meshes) { + hecl::SystemStringConv meshSys(mesh); + if (!mesh.compare("CMESH")) { + colMesh = ds.compileColMesh(mesh); + progress(_SYS_STR("Collision Mesh")); + continue; + } + meshCompiles.push_back(ds.compileMesh( + mesh, fast ? hecl::HMDLTopology::Triangles : hecl::HMDLTopology::TriStrips, -1, !m_pc, + [&](int surfCount) { progress(hecl::SysFormat(_SYS_STR("%s %d"), meshSys.c_str(), surfCount).c_str()); })); } - void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, - hecl::blender::Token& btok, FCookProgress progress) + if (!colMesh) + Log.report(logvisor::Fatal, _SYS_STR("unable to find mesh named 'CMESH' in %s"), in.getAbsolutePath().data()); + + std::vector lights = ds.compileLights(); + + ds.close(); + + if (m_mreaPathToXF.empty()) + buildAreaXFs(btok); + + const hecl::blender::Matrix4f* xf = nullptr; + auto xfSearch = m_mreaPathToXF.find(in.getParentPath().hash()); + if (xfSearch != m_mreaPathToXF.cend()) + xf = &xfSearch->second; + DNAMP1::MREA::Cook(out, in, meshCompiles, *colMesh, lights, btok, xf, m_pc); + } + + void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) { + if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR("MAPW"))) { + hecl::blender::World world = ds.compileWorld(); + ds.close(); + DNAMP1::MLVL::CookMAPW(out, world, btok); + } else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR("SAVW"))) { + hecl::blender::World world = ds.compileWorld(); + ds.close(); + DNAMP1::MLVL::CookSAVW(out, world); + } else { + hecl::blender::World world = ds.compileWorld(); + ds.close(); + DNAMP1::MLVL::Cook(out, in, world, btok); + } + } + + void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) { + auto data = ds.compileGuiFrame(0); + athena::io::MemoryReader r(data.data(), data.size()); + DNAMP1::FRME frme; + frme.read(r); + athena::io::FileWriter w(out.getAbsolutePath()); + frme.write(w); + } + + void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin, + FCookProgress progress) { + athena::io::YAMLDocReader reader; + if (reader.parse(&fin)) { + std::string classStr = reader.readString("DNAType"); + if (classStr.empty()) + return; + + if (!classStr.compare(DNAMP1::STRG::DNAType())) { + DNAMP1::STRG strg; + strg.read(reader); + DNAMP1::STRG::Cook(strg, out); + } else if (!classStr.compare(DNAMP1::SCAN::DNAType())) { + DNAMP1::SCAN scan; + scan.read(reader); + DNAMP1::SCAN::Cook(scan, out); + } else if (!classStr.compare(DNAParticle::GPSM::DNAType())) { + DNAParticle::GPSM gpsm; + gpsm.read(reader); + DNAParticle::WriteGPSM(gpsm, out); + } else if (!classStr.compare(DNAParticle::SWSH::DNAType())) { + DNAParticle::SWSH swsh; + swsh.read(reader); + DNAParticle::WriteSWSH(swsh, out); + } else if (!classStr.compare(DNAParticle::ELSM::DNAType())) { + DNAParticle::ELSM elsm; + elsm.read(reader); + DNAParticle::WriteELSM(elsm, out); + } else if (!classStr.compare(DNAParticle::WPSM::DNAType())) { + DNAParticle::WPSM wpsm; + wpsm.read(reader); + DNAParticle::WriteWPSM(wpsm, out); + } else if (!classStr.compare(DNAParticle::CRSM::DNAType())) { + DNAParticle::CRSM crsm; + crsm.read(reader); + DNAParticle::WriteCRSM(crsm, out); + } else if (!classStr.compare(DNAParticle::DPSM::DNAType())) { + DNAParticle::DPSM dpsm; + dpsm.read(reader); + DNAParticle::WriteDPSM(dpsm, out); + } else if (!classStr.compare(DNADGRP::DGRP::DNAType())) { + DNADGRP::DGRP dgrp; + dgrp.read(reader); + dgrp.validateDeps(); + DNADGRP::WriteDGRP(dgrp, out); + } else if (!classStr.compare(DNAFont::FONT::DNAType())) { + DNAFont::FONT font; + font.read(reader); + DNAFont::WriteFONT(font, out); + } else if (!classStr.compare(DNAMP1::CTweakPlayerRes::DNAType())) { + DNAMP1::CTweakPlayerRes playerRes; + playerRes.read(reader); + WriteTweak(playerRes, out); + } else if (!classStr.compare(DNAMP1::CTweakGunRes::DNAType())) { + DNAMP1::CTweakGunRes gunRes; + gunRes.read(reader); + WriteTweak(gunRes, out); + } else if (!classStr.compare(DNAMP1::CTweakSlideShow::DNAType())) { + DNAMP1::CTweakSlideShow slideShow; + slideShow.read(reader); + WriteTweak(slideShow, out); + } else if (!classStr.compare(DNAMP1::CTweakPlayer::DNAType())) { + DNAMP1::CTweakPlayer player; + player.read(reader); + WriteTweak(player, out); + } else if (!classStr.compare(DNAMP1::CTweakCameraBob::DNAType())) { + DNAMP1::CTweakCameraBob cBob; + cBob.read(reader); + WriteTweak(cBob, out); + } else if (!classStr.compare(DNAMP1::CTweakGame::DNAType())) { + DNAMP1::CTweakGame cGame; + cGame.read(reader); + WriteTweak(cGame, out); + } else if (!classStr.compare(DNAMP1::CTweakAutoMapper::DNAType())) { + DNAMP1::CTweakAutoMapper autoMapper; + autoMapper.read(reader); + WriteTweak(autoMapper, out); + } else if (!classStr.compare(DNAMP1::CTweakTargeting::DNAType())) { + DNAMP1::CTweakTargeting targeting; + targeting.read(reader); + WriteTweak(targeting, out); + } else if (!classStr.compare(DNAMP1::CTweakGui::DNAType())) { + DNAMP1::CTweakGui gui; + gui.read(reader); + WriteTweak(gui, out); + } else if (!classStr.compare(DNAMP1::CTweakPlayerControl::DNAType())) { + DNAMP1::CTweakPlayerControl pc; + pc.read(reader); + WriteTweak(pc, out); + } else if (!classStr.compare(DNAMP1::CTweakBall::DNAType())) { + DNAMP1::CTweakBall ball; + ball.read(reader); + WriteTweak(ball, out); + } else if (!classStr.compare(DNAMP1::CTweakParticle::DNAType())) { + DNAMP1::CTweakParticle part; + part.read(reader); + WriteTweak(part, out); + } else if (!classStr.compare(DNAMP1::CTweakGuiColors::DNAType())) { + DNAMP1::CTweakGuiColors gColors; + gColors.read(reader); + WriteTweak(gColors, out); + } else if (!classStr.compare(DNAMP1::CTweakPlayerGun::DNAType())) { + DNAMP1::CTweakPlayerGun pGun; + pGun.read(reader); + WriteTweak(pGun, out); + } else if (!classStr.compare(DNAMP1::CTweakPlayerControl::DNAType())) { + DNAMP1::CTweakPlayerControl pControl; + pControl.read(reader); + WriteTweak(pControl, out); + } else if (!classStr.compare(DNAMP1::MazeSeeds::DNAType())) { + DNAMP1::MazeSeeds mSeeds; + mSeeds.read(reader); + WriteTweak(mSeeds, out); + } else if (!classStr.compare(DNAMP1::SnowForces::DNAType())) { + DNAMP1::SnowForces sForces; + sForces.read(reader); + WriteTweak(sForces, out); + } else if (!classStr.compare(DNAMP1::HINT::DNAType())) { + DNAMP1::HINT::Cook(in, out); + } else if (!classStr.compare(DNAMP1::EVNT::DNAType())) { + DNAMP1::EVNT::Cook(in, out); + } else if (!classStr.compare("ATBL")) { + DNAAudio::ATBL::Cook(in, out); + } else if (!classStr.compare(DNAMP1::AFSM::DNAType())) { + DNAMP1::AFSM::Cook(in, out); + } else if (!classStr.compare("MP1OriginalIDs")) { + OriginalIDs::Cook(in, out); + } + } + progress(_SYS_STR("Done")); + } + + void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector& pathsOut) { + athena::io::YAMLDocReader reader; + if (reader.parse(&fin)) { + std::string classStr = reader.readString("DNAType"); + if (classStr.empty()) + return; + + if (!classStr.compare(DNAMP1::STRG::DNAType())) { + DNAMP1::STRG strg; + strg.read(reader); + strg.gatherDependencies(pathsOut); + } + if (!classStr.compare(DNAMP1::SCAN::DNAType())) { + DNAMP1::SCAN scan; + scan.read(reader); + scan.gatherDependencies(pathsOut); + } else if (!classStr.compare(DNAParticle::GPSM::DNAType())) { + DNAParticle::GPSM gpsm; + gpsm.read(reader); + gpsm.gatherDependencies(pathsOut); + } else if (!classStr.compare(DNAParticle::SWSH::DNAType())) { + DNAParticle::SWSH swsh; + swsh.read(reader); + swsh.gatherDependencies(pathsOut); + } else if (!classStr.compare(DNAParticle::ELSM::DNAType())) { + DNAParticle::ELSM elsm; + elsm.read(reader); + elsm.gatherDependencies(pathsOut); + } else if (!classStr.compare(DNAParticle::WPSM::DNAType())) { + DNAParticle::WPSM wpsm; + wpsm.read(reader); + wpsm.gatherDependencies(pathsOut); + } else if (!classStr.compare(DNAParticle::CRSM::DNAType())) { + DNAParticle::CRSM crsm; + crsm.read(reader); + crsm.gatherDependencies(pathsOut); + } else if (!classStr.compare(DNAParticle::DPSM::DNAType())) { + DNAParticle::DPSM dpsm; + dpsm.read(reader); + dpsm.gatherDependencies(pathsOut); + } else if (!classStr.compare(DNAFont::FONT::DNAType())) { + DNAFont::FONT font; + font.read(reader); + font.gatherDependencies(pathsOut); + } else if (!classStr.compare(DNAMP1::EVNT::DNAType())) { + DNAMP1::EVNT evnt; + evnt.read(reader); + evnt.gatherDependencies(pathsOut); + } + } + } + + void flattenDependenciesANCSYAML(athena::io::IStreamReader& fin, std::vector& pathsOut, + int charIdx) { + athena::io::YAMLDocReader reader; + if (reader.parse(&fin)) { + std::string classStr = reader.readString("DNAType"); + if (!classStr.compare(DNAMP1::ANCS::DNAType())) { + DNAMP1::ANCS ancs; + ancs.read(reader); + ancs.gatherDependencies(pathsOut, charIdx); + } + } + } + + UniqueID32 newToOriginal(urde::CAssetId id) const { + if (UniqueID32 origId = m_idRestorer.newToOriginal({uint32_t(id.Value()), true})) + return {origId.toUint32(), true}; + return {uint32_t(id.Value()), true}; + } + + urde::CAssetId originalToNew(UniqueID32 id) const { + if (UniqueID32 newId = m_idRestorer.originalToNew(id)) + return newId.toUint32(); + return id.toUint32(); + } + + void buildWorldPakList(const hecl::ProjectPath& worldPath, const hecl::ProjectPath& worldPathCooked, + hecl::blender::Token& btok, athena::io::FileWriter& w, std::vector& listOut, + atUint64& resTableOffset, std::unordered_map>& mlvlData) { + DNAMP1::MLVL mlvl; { - if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR("MAPW"))) - { - hecl::blender::World world = ds.compileWorld(); - ds.close(); - DNAMP1::MLVL::CookMAPW(out, world, btok); - } - else if (hecl::StringUtils::EndsWith(in.getAuxInfo(), _SYS_STR("SAVW"))) - { - hecl::blender::World world = ds.compileWorld(); - ds.close(); - DNAMP1::MLVL::CookSAVW(out, world); - } - else - { - hecl::blender::World world = ds.compileWorld(); - ds.close(); - DNAMP1::MLVL::Cook(out, in, world, btok); - } + athena::io::FileReader r(worldPathCooked.getAbsolutePath()); + if (r.hasError()) + Log.report(logvisor::Fatal, _SYS_STR("Unable to open world %s"), worldPathCooked.getRelativePath().data()); + mlvl.read(r); } - void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, - hecl::blender::Token& btok, FCookProgress progress) - { - auto data = ds.compileGuiFrame(0); - athena::io::MemoryReader r(data.data(), data.size()); - DNAMP1::FRME frme; - frme.read(r); - athena::io::FileWriter w(out.getAbsolutePath()); - frme.write(w); + size_t count = 5; + for (const auto& area : mlvl.areas) { + auto lazyIt = area.lazyDeps.cbegin(); + auto it = area.deps.cbegin(); + while (it != area.deps.cend()) { + if (it->id != lazyIt->id) + ++count; + ++lazyIt; + ++it; + } + } + listOut.reserve(count); + + urde::SObjectTag worldTag = tagFromPath(worldPath.getWithExtension(_SYS_STR(".*"), true), btok); + + w.writeUint32Big(m_pc ? 0x80030005 : 0x00030005); + w.writeUint32Big(0); + + w.writeUint32Big(1); + DNAMP1::PAK::NameEntry nameEnt; + hecl::ProjectPath parentDir = worldPath.getParentPath(); + nameEnt.type = worldTag.type; + nameEnt.id = newToOriginal(worldTag.id); + nameEnt.nameLen = atUint32(parentDir.getLastComponent().size()); + nameEnt.name = parentDir.getLastComponentUTF8(); + nameEnt.write(w); + + std::unordered_set addedTags; + for (auto& area : mlvl.areas) { + urde::SObjectTag areaTag(FOURCC('MREA'), originalToNew(area.areaMREAId)); + + bool dupeRes = false; + if (hecl::ProjectPath areaDir = pathFromTag(areaTag).getParentPath()) + dupeRes = hecl::ProjectPath(areaDir, _SYS_STR("!duperes")).isFile(); + + urde::SObjectTag nameTag(FOURCC('STRG'), originalToNew(area.areaNameId)); + if (nameTag) + listOut.push_back(nameTag); + for (const auto& dep : area.deps) { + urde::CAssetId newId = originalToNew(dep.id); + if (dupeRes || addedTags.find(newId) == addedTags.end()) { + listOut.push_back({dep.type, newId}); + addedTags.insert(newId); + } + } + if (areaTag) + listOut.push_back(areaTag); + + std::vector strippedDeps; + strippedDeps.reserve(area.deps.size()); + std::vector strippedDepLayers; + strippedDepLayers.reserve(area.depLayers.size()); + auto lazyIt = area.lazyDeps.cbegin(); + auto it = area.deps.cbegin(); + auto layerIt = area.depLayers.cbegin(); + while (it != area.deps.cend()) { + while (layerIt != area.depLayers.cend() && it - area.deps.cbegin() == *layerIt) { + strippedDepLayers.push_back(atUint32(strippedDeps.size())); + ++layerIt; + } + if (it->id != lazyIt->id) + strippedDeps.push_back(*it); + ++lazyIt; + ++it; + } + + area.lazyDepCount = 0; + area.lazyDeps.clear(); + area.depCount = strippedDeps.size(); + area.deps = std::move(strippedDeps); + area.depLayerCount = strippedDepLayers.size(); + area.depLayers = std::move(strippedDepLayers); } - void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin, - FCookProgress progress) - { - athena::io::YAMLDocReader reader; - if (reader.parse(&fin)) - { - std::string classStr = reader.readString("DNAType"); - if (classStr.empty()) - return; + urde::SObjectTag nameTag(FOURCC('STRG'), originalToNew(mlvl.worldNameId)); + if (nameTag) + listOut.push_back(nameTag); - if (!classStr.compare(DNAMP1::STRG::DNAType())) - { - DNAMP1::STRG strg; - strg.read(reader); - DNAMP1::STRG::Cook(strg, out); - } - else if (!classStr.compare(DNAMP1::SCAN::DNAType())) - { - DNAMP1::SCAN scan; - scan.read(reader); - DNAMP1::SCAN::Cook(scan, out); - } - else if (!classStr.compare(DNAParticle::GPSM::DNAType())) - { - DNAParticle::GPSM gpsm; - gpsm.read(reader); - DNAParticle::WriteGPSM(gpsm, out); - } - else if (!classStr.compare(DNAParticle::SWSH::DNAType())) - { - DNAParticle::SWSH swsh; - swsh.read(reader); - DNAParticle::WriteSWSH(swsh, out); - } - else if (!classStr.compare(DNAParticle::ELSM::DNAType())) - { - DNAParticle::ELSM elsm; - elsm.read(reader); - DNAParticle::WriteELSM(elsm, out); - } - else if (!classStr.compare(DNAParticle::WPSM::DNAType())) - { - DNAParticle::WPSM wpsm; - wpsm.read(reader); - DNAParticle::WriteWPSM(wpsm, out); - } - else if (!classStr.compare(DNAParticle::CRSM::DNAType())) - { - DNAParticle::CRSM crsm; - crsm.read(reader); - DNAParticle::WriteCRSM(crsm, out); - } - else if (!classStr.compare(DNAParticle::DPSM::DNAType())) - { - DNAParticle::DPSM dpsm; - dpsm.read(reader); - DNAParticle::WriteDPSM(dpsm, out); - } - else if (!classStr.compare(DNADGRP::DGRP::DNAType())) - { - DNADGRP::DGRP dgrp; - dgrp.read(reader); - dgrp.validateDeps(); - DNADGRP::WriteDGRP(dgrp, out); - } - else if (!classStr.compare(DNAFont::FONT::DNAType())) - { - DNAFont::FONT font; - font.read(reader); - DNAFont::WriteFONT(font, out); - } - else if (!classStr.compare(DNAMP1::CTweakPlayerRes::DNAType())) - { - DNAMP1::CTweakPlayerRes playerRes; - playerRes.read(reader); - WriteTweak(playerRes, out); - } - else if (!classStr.compare(DNAMP1::CTweakGunRes::DNAType())) - { - DNAMP1::CTweakGunRes gunRes; - gunRes.read(reader); - WriteTweak(gunRes, out); - } - else if (!classStr.compare(DNAMP1::CTweakSlideShow::DNAType())) - { - DNAMP1::CTweakSlideShow slideShow; - slideShow.read(reader); - WriteTweak(slideShow, out); - } - else if (!classStr.compare(DNAMP1::CTweakPlayer::DNAType())) - { - DNAMP1::CTweakPlayer player; - player.read(reader); - WriteTweak(player, out); - } - else if (!classStr.compare(DNAMP1::CTweakCameraBob::DNAType())) - { - DNAMP1::CTweakCameraBob cBob; - cBob.read(reader); - WriteTweak(cBob, out); - } - else if (!classStr.compare(DNAMP1::CTweakGame::DNAType())) - { - DNAMP1::CTweakGame cGame; - cGame.read(reader); - WriteTweak(cGame, out); - } - else if (!classStr.compare(DNAMP1::CTweakAutoMapper::DNAType())) - { - DNAMP1::CTweakAutoMapper autoMapper; - autoMapper.read(reader); - WriteTweak(autoMapper, out); - } - else if (!classStr.compare(DNAMP1::CTweakTargeting::DNAType())) - { - DNAMP1::CTweakTargeting targeting; - targeting.read(reader); - WriteTweak(targeting, out); - } - else if (!classStr.compare(DNAMP1::CTweakGui::DNAType())) - { - DNAMP1::CTweakGui gui; - gui.read(reader); - WriteTweak(gui, out); - } - else if (!classStr.compare(DNAMP1::CTweakPlayerControl::DNAType())) - { - DNAMP1::CTweakPlayerControl pc; - pc.read(reader); - WriteTweak(pc, out); - } - else if (!classStr.compare(DNAMP1::CTweakBall::DNAType())) - { - DNAMP1::CTweakBall ball; - ball.read(reader); - WriteTweak(ball, out); - } - else if (!classStr.compare(DNAMP1::CTweakParticle::DNAType())) - { - DNAMP1::CTweakParticle part; - part.read(reader); - WriteTweak(part, out); - } - else if (!classStr.compare(DNAMP1::CTweakGuiColors::DNAType())) - { - DNAMP1::CTweakGuiColors gColors; - gColors.read(reader); - WriteTweak(gColors, out); - } - else if (!classStr.compare(DNAMP1::CTweakPlayerGun::DNAType())) - { - DNAMP1::CTweakPlayerGun pGun; - pGun.read(reader); - WriteTweak(pGun, out); - } - else if (!classStr.compare(DNAMP1::CTweakPlayerControl::DNAType())) - { - DNAMP1::CTweakPlayerControl pControl; - pControl.read(reader); - WriteTweak(pControl, out); - } - else if (!classStr.compare(DNAMP1::MazeSeeds::DNAType())) - { - DNAMP1::MazeSeeds mSeeds; - mSeeds.read(reader); - WriteTweak(mSeeds, out); - } - else if (!classStr.compare(DNAMP1::SnowForces::DNAType())) - { - DNAMP1::SnowForces sForces; - sForces.read(reader); - WriteTweak(sForces, out); - } - else if (!classStr.compare(DNAMP1::HINT::DNAType())) - { - DNAMP1::HINT::Cook(in, out); - } - else if (!classStr.compare(DNAMP1::EVNT::DNAType())) - { - DNAMP1::EVNT::Cook(in, out); - } - else if (!classStr.compare("ATBL")) - { - DNAAudio::ATBL::Cook(in, out); - } - else if (!classStr.compare(DNAMP1::AFSM::DNAType())) - { - DNAMP1::AFSM::Cook(in, out); - } - else if (!classStr.compare("MP1OriginalIDs")) - { - OriginalIDs::Cook(in, out); - } - } - progress(_SYS_STR("Done")); + urde::SObjectTag savwTag(FOURCC('SAVW'), originalToNew(mlvl.saveWorldId)); + if (savwTag) { + if (hecl::ProjectPath savwPath = pathFromTag(savwTag)) + m_project.cookPath(savwPath, {}, false, true); + listOut.push_back(savwTag); } - void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector& pathsOut) - { - athena::io::YAMLDocReader reader; - if (reader.parse(&fin)) - { - std::string classStr = reader.readString("DNAType"); - if (classStr.empty()) - return; + urde::SObjectTag mapTag(FOURCC('MAPW'), originalToNew(mlvl.worldMap)); + if (mapTag) { + if (hecl::ProjectPath mapPath = pathFromTag(mapTag)) { + m_project.cookPath(mapPath, {}, false, true); + if (hecl::ProjectPath mapCookedPath = getCookedPath(mapPath, true)) { + athena::io::FileReader r(mapCookedPath.getAbsolutePath()); + if (r.hasError()) + Log.report(logvisor::Fatal, _SYS_STR("Unable to open %s"), mapCookedPath.getRelativePath().data()); - if (!classStr.compare(DNAMP1::STRG::DNAType())) - { - DNAMP1::STRG strg; - strg.read(reader); - strg.gatherDependencies(pathsOut); - } - if (!classStr.compare(DNAMP1::SCAN::DNAType())) - { - DNAMP1::SCAN scan; - scan.read(reader); - scan.gatherDependencies(pathsOut); - } - else if (!classStr.compare(DNAParticle::GPSM::DNAType())) - { - DNAParticle::GPSM gpsm; - gpsm.read(reader); - gpsm.gatherDependencies(pathsOut); - } - else if (!classStr.compare(DNAParticle::SWSH::DNAType())) - { - DNAParticle::SWSH swsh; - swsh.read(reader); - swsh.gatherDependencies(pathsOut); - } - else if (!classStr.compare(DNAParticle::ELSM::DNAType())) - { - DNAParticle::ELSM elsm; - elsm.read(reader); - elsm.gatherDependencies(pathsOut); - } - else if (!classStr.compare(DNAParticle::WPSM::DNAType())) - { - DNAParticle::WPSM wpsm; - wpsm.read(reader); - wpsm.gatherDependencies(pathsOut); - } - else if (!classStr.compare(DNAParticle::CRSM::DNAType())) - { - DNAParticle::CRSM crsm; - crsm.read(reader); - crsm.gatherDependencies(pathsOut); - } - else if (!classStr.compare(DNAParticle::DPSM::DNAType())) - { - DNAParticle::DPSM dpsm; - dpsm.read(reader); - dpsm.gatherDependencies(pathsOut); - } - else if (!classStr.compare(DNAFont::FONT::DNAType())) - { - DNAFont::FONT font; - font.read(reader); - font.gatherDependencies(pathsOut); - } - else if (!classStr.compare(DNAMP1::EVNT::DNAType())) - { - DNAMP1::EVNT evnt; - evnt.read(reader); - evnt.gatherDependencies(pathsOut); - } + if (r.readUint32Big() != 0xDEADF00D) + Log.report(logvisor::Fatal, _SYS_STR("Corrupt MAPW %s"), mapCookedPath.getRelativePath().data()); + r.readUint32Big(); + atUint32 mapaCount = r.readUint32Big(); + for (int i = 0; i < mapaCount; ++i) { + UniqueID32 id; + id.read(r); + listOut.push_back({FOURCC('MAPA'), originalToNew(id)}); + } } + } + listOut.push_back(mapTag); } - void flattenDependenciesANCSYAML(athena::io::IStreamReader& fin, - std::vector& pathsOut, - int charIdx) - { - athena::io::YAMLDocReader reader; - if (reader.parse(&fin)) - { - std::string classStr = reader.readString("DNAType"); - if (!classStr.compare(DNAMP1::ANCS::DNAType())) - { - DNAMP1::ANCS ancs; - ancs.read(reader); - ancs.gatherDependencies(pathsOut, charIdx); - } + urde::SObjectTag skyboxTag(FOURCC('CMDL'), originalToNew(mlvl.worldSkyboxId)); + if (skyboxTag) { + listOut.push_back(skyboxTag); + hecl::ProjectPath skyboxPath = pathFromTag(skyboxTag); + if (btok.getBlenderConnection().openBlend(skyboxPath)) { + auto data = btok.getBlenderConnection().beginData(); + std::vector textures = data.getTextures(); + for (const auto& tex : textures) { + urde::SObjectTag texTag = tagFromPath(tex, btok); + if (!texTag) + Log.report(logvisor::Fatal, _SYS_STR("Unable to resolve %s"), tex.getRelativePath().data()); + listOut.push_back(texTag); } + } } - UniqueID32 newToOriginal(urde::CAssetId id) const - { - if (UniqueID32 origId = m_idRestorer.newToOriginal({uint32_t(id.Value()), true})) - return {origId.toUint32(), true}; - return {uint32_t(id.Value()), true}; + listOut.push_back(worldTag); + + w.writeUint32Big(atUint32(listOut.size())); + resTableOffset = w.position(); + for (const auto& item : listOut) { + DNAMP1::PAK::Entry ent; + ent.compressed = 0; + ent.type = item.type; + ent.id = newToOriginal(item.id.Value()); + ent.size = 0; + ent.offset = 0; + ent.write(w); } - urde::CAssetId originalToNew(UniqueID32 id) const { - if (UniqueID32 newId = m_idRestorer.originalToNew(id)) - return newId.toUint32(); - return id.toUint32(); + std::vector& mlvlOut = mlvlData[worldTag.id]; + size_t mlvlSize = 0; + mlvl.binarySize(mlvlSize); + mlvlOut.resize(mlvlSize); + athena::io::MemoryWriter w(&mlvlOut[0], mlvlSize); + mlvl.write(w); + } + } + + void buildPakList(hecl::blender::Token& btok, athena::io::FileWriter& w, const std::vector& list, + const std::vector>& nameList, atUint64& resTableOffset) { + w.writeUint32Big(m_pc ? 0x80030005 : 0x00030005); + w.writeUint32Big(0); + + w.writeUint32Big(atUint32(nameList.size())); + for (const auto& item : nameList) { + DNAMP1::PAK::NameEntry nameEnt; + nameEnt.type = item.first.type; + nameEnt.id = newToOriginal(item.first.id); + nameEnt.nameLen = atUint32(item.second.size()); + nameEnt.name = item.second; + nameEnt.write(w); } - void buildWorldPakList(const hecl::ProjectPath& worldPath, - const hecl::ProjectPath& worldPathCooked, - hecl::blender::Token& btok, - athena::io::FileWriter& w, - std::vector& listOut, - atUint64& resTableOffset, - std::unordered_map>& mlvlData) - { - DNAMP1::MLVL mlvl; - { - athena::io::FileReader r(worldPathCooked.getAbsolutePath()); - if (r.hasError()) - Log.report(logvisor::Fatal, _SYS_STR("Unable to open world %s"), worldPathCooked.getRelativePath().data()); - mlvl.read(r); - } - - size_t count = 5; - for (const auto& area : mlvl.areas) - { - auto lazyIt = area.lazyDeps.cbegin(); - auto it = area.deps.cbegin(); - while (it != area.deps.cend()) - { - if (it->id != lazyIt->id) - ++count; - ++lazyIt; - ++it; - } - } - listOut.reserve(count); - - urde::SObjectTag worldTag = tagFromPath(worldPath.getWithExtension(_SYS_STR(".*"), true), btok); - - w.writeUint32Big(m_pc ? 0x80030005 : 0x00030005); - w.writeUint32Big(0); - - w.writeUint32Big(1); - DNAMP1::PAK::NameEntry nameEnt; - hecl::ProjectPath parentDir = worldPath.getParentPath(); - nameEnt.type = worldTag.type; - nameEnt.id = newToOriginal(worldTag.id); - nameEnt.nameLen = atUint32(parentDir.getLastComponent().size()); - nameEnt.name = parentDir.getLastComponentUTF8(); - nameEnt.write(w); - - std::unordered_set addedTags; - for (auto& area : mlvl.areas) - { - urde::SObjectTag areaTag(FOURCC('MREA'), originalToNew(area.areaMREAId)); - - bool dupeRes = false; - if (hecl::ProjectPath areaDir = pathFromTag(areaTag).getParentPath()) - dupeRes = hecl::ProjectPath(areaDir, _SYS_STR("!duperes")).isFile(); - - urde::SObjectTag nameTag(FOURCC('STRG'), originalToNew(area.areaNameId)); - if (nameTag) - listOut.push_back(nameTag); - for (const auto& dep : area.deps) - { - urde::CAssetId newId = originalToNew(dep.id); - if (dupeRes || addedTags.find(newId) == addedTags.end()) - { - listOut.push_back({dep.type, newId}); - addedTags.insert(newId); - } - } - if (areaTag) - listOut.push_back(areaTag); - - std::vector strippedDeps; - strippedDeps.reserve(area.deps.size()); - std::vector strippedDepLayers; - strippedDepLayers.reserve(area.depLayers.size()); - auto lazyIt = area.lazyDeps.cbegin(); - auto it = area.deps.cbegin(); - auto layerIt = area.depLayers.cbegin(); - while (it != area.deps.cend()) - { - while (layerIt != area.depLayers.cend() && it - area.deps.cbegin() == *layerIt) - { - strippedDepLayers.push_back(atUint32(strippedDeps.size())); - ++layerIt; - } - if (it->id != lazyIt->id) - strippedDeps.push_back(*it); - ++lazyIt; - ++it; - } - - area.lazyDepCount = 0; - area.lazyDeps.clear(); - area.depCount = strippedDeps.size(); - area.deps = std::move(strippedDeps); - area.depLayerCount = strippedDepLayers.size(); - area.depLayers = std::move(strippedDepLayers); - } - - urde::SObjectTag nameTag(FOURCC('STRG'), originalToNew(mlvl.worldNameId)); - if (nameTag) - listOut.push_back(nameTag); - - urde::SObjectTag savwTag(FOURCC('SAVW'), originalToNew(mlvl.saveWorldId)); - if (savwTag) - { - if (hecl::ProjectPath savwPath = pathFromTag(savwTag)) - m_project.cookPath(savwPath, {}, false, true); - listOut.push_back(savwTag); - } - - urde::SObjectTag mapTag(FOURCC('MAPW'), originalToNew(mlvl.worldMap)); - if (mapTag) - { - if (hecl::ProjectPath mapPath = pathFromTag(mapTag)) - { - m_project.cookPath(mapPath, {}, false, true); - if (hecl::ProjectPath mapCookedPath = getCookedPath(mapPath, true)) - { - athena::io::FileReader r(mapCookedPath.getAbsolutePath()); - if (r.hasError()) - Log.report(logvisor::Fatal, _SYS_STR("Unable to open %s"), mapCookedPath.getRelativePath().data()); - - if (r.readUint32Big() != 0xDEADF00D) - Log.report(logvisor::Fatal, _SYS_STR("Corrupt MAPW %s"), mapCookedPath.getRelativePath().data()); - r.readUint32Big(); - atUint32 mapaCount = r.readUint32Big(); - for (int i=0 ; i textures = data.getTextures(); - for (const auto& tex : textures) - { - urde::SObjectTag texTag = tagFromPath(tex, btok); - if (!texTag) - Log.report(logvisor::Fatal, _SYS_STR("Unable to resolve %s"), tex.getRelativePath().data()); - listOut.push_back(texTag); - } - } - } - - listOut.push_back(worldTag); - - w.writeUint32Big(atUint32(listOut.size())); - resTableOffset = w.position(); - for (const auto& item : listOut) - { - DNAMP1::PAK::Entry ent; - ent.compressed = 0; - ent.type = item.type; - ent.id = newToOriginal(item.id.Value()); - ent.size = 0; - ent.offset = 0; - ent.write(w); - } - - { - std::vector& mlvlOut = mlvlData[worldTag.id]; - size_t mlvlSize = 0; - mlvl.binarySize(mlvlSize); - mlvlOut.resize(mlvlSize); - athena::io::MemoryWriter w(&mlvlOut[0], mlvlSize); - mlvl.write(w); - } + w.writeUint32Big(atUint32(list.size())); + resTableOffset = w.position(); + for (const auto& item : list) { + DNAMP1::PAK::Entry ent; + ent.compressed = 0; + ent.type = item.type; + ent.id = newToOriginal(item.id); + ent.size = 0; + ent.offset = 0; + ent.write(w); } + } - void buildPakList(hecl::blender::Token& btok, - athena::io::FileWriter& w, - const std::vector& list, - const std::vector>& nameList, - atUint64& resTableOffset) - { - w.writeUint32Big(m_pc ? 0x80030005 : 0x00030005); - w.writeUint32Big(0); + void writePakFileIndex(athena::io::FileWriter& w, const std::vector& tags, + const std::vector>& index, atUint64 resTableOffset) { + w.seek(resTableOffset, athena::Begin); - w.writeUint32Big(atUint32(nameList.size())); - for (const auto& item : nameList) - { - DNAMP1::PAK::NameEntry nameEnt; - nameEnt.type = item.first.type; - nameEnt.id = newToOriginal(item.first.id); - nameEnt.nameLen = atUint32(item.second.size()); - nameEnt.name = item.second; - nameEnt.write(w); - } - - w.writeUint32Big(atUint32(list.size())); - resTableOffset = w.position(); - for (const auto& item : list) - { - DNAMP1::PAK::Entry ent; - ent.compressed = 0; - ent.type = item.type; - ent.id = newToOriginal(item.id); - ent.size = 0; - ent.offset = 0; - ent.write(w); - } + auto it = tags.begin(); + for (const auto& item : index) { + const urde::SObjectTag& tag = *it++; + DNAMP1::PAK::Entry ent; + ent.compressed = atUint32(std::get<2>(item)); + ent.type = tag.type; + ent.id = newToOriginal(tag.id); + ent.size = atUint32(std::get<1>(item)); + ent.offset = atUint32(std::get<0>(item)); + ent.write(w); } + } - void writePakFileIndex(athena::io::FileWriter& w, - const std::vector& tags, - const std::vector>& index, - atUint64 resTableOffset) - { - w.seek(resTableOffset, athena::Begin); - - auto it = tags.begin(); - for (const auto& item : index) - { - const urde::SObjectTag& tag = *it++; - DNAMP1::PAK::Entry ent; - ent.compressed = atUint32(std::get<2>(item)); - ent.type = tag.type; - ent.id = newToOriginal(tag.id); - ent.size = atUint32(std::get<1>(item)); - ent.offset = atUint32(std::get<0>(item)); - ent.write(w); - } + std::pair, size_t> compressPakData(const urde::SObjectTag& tag, const uint8_t* data, + size_t len) { + bool doCompress = false; + switch (tag.type) { + case SBIG('TXTR'): + case SBIG('CMDL'): + case SBIG('CSKR'): + case SBIG('ANCS'): + case SBIG('ANIM'): + case SBIG('FONT'): + doCompress = true; + break; + case SBIG('PART'): + case SBIG('ELSC'): + case SBIG('SWHC'): + case SBIG('WPSC'): + case SBIG('DPSC'): + case SBIG('CRSC'): + doCompress = len >= 0x400; + break; + default: + break; } + if (!doCompress) + return {}; - std::pair, size_t> - compressPakData(const urde::SObjectTag& tag, const uint8_t* data, size_t len) - { - bool doCompress = false; - switch (tag.type) - { - case SBIG('TXTR'): - case SBIG('CMDL'): - case SBIG('CSKR'): - case SBIG('ANCS'): - case SBIG('ANIM'): - case SBIG('FONT'): - doCompress = true; - break; - case SBIG('PART'): - case SBIG('ELSC'): - case SBIG('SWHC'): - case SBIG('WPSC'): - case SBIG('DPSC'): - case SBIG('CRSC'): - doCompress = len >= 0x400; - break; - default: - break; - } - if (!doCompress) - return {}; + uLong destLen = compressBound(len); + std::pair, size_t> ret; + ret.first.reset(new uint8_t[destLen]); + compress2(ret.first.get(), &destLen, data, len, Z_BEST_COMPRESSION); + ret.second = destLen; + return ret; + }; - uLong destLen = compressBound(len); - std::pair, size_t> ret; - ret.first.reset(new uint8_t[destLen]); - compress2(ret.first.get(), &destLen, data, len, Z_BEST_COMPRESSION); - ret.second = destLen; - return ret; - }; + void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) { + DNAMP1::AGSC::Cook(in, out); + progress(_SYS_STR("Done")); + } - void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) - { - DNAMP1::AGSC::Cook(in, out); - progress(_SYS_STR("Done")); - } + void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) { + DNAMP1::CSNG::Cook(in, out); + progress(_SYS_STR("Done")); + } - void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) - { - DNAMP1::CSNG::Cook(in, out); - progress(_SYS_STR("Done")); - } + void cookMapArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) { + hecl::blender::MapArea mapa = ds.compileMapArea(); + ds.close(); + DNAMP1::MAPA::Cook(mapa, out); + progress(_SYS_STR("Done")); + } - void cookMapArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress) - { - hecl::blender::MapArea mapa = ds.compileMapArea(); - ds.close(); - DNAMP1::MAPA::Cook(mapa, out); - progress(_SYS_STR("Done")); - } - - void cookMapUniverse(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress) - { - hecl::blender::MapUniverse mapu = ds.compileMapUniverse(); - ds.close(); - DNAMAPU::MAPU::Cook(mapu, out); - progress(_SYS_STR("Done")); - } + void cookMapUniverse(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) { + hecl::blender::MapUniverse mapu = ds.compileMapUniverse(); + ds.close(); + DNAMAPU::MAPU::Cook(mapu, out); + progress(_SYS_STR("Done")); + } }; hecl::Database::DataSpecEntry SpecEntMP1 = { _SYS_STR("MP1"sv), _SYS_STR("Data specification for original Metroid Prime engine"sv), _SYS_STR(".pak"sv), 2, [](hecl::Database::Project& project, hecl::Database::DataSpecTool) -> std::unique_ptr { - return std::make_unique(&SpecEntMP1, project, false); + return std::make_unique(&SpecEntMP1, project, false); }}; hecl::Database::DataSpecEntry SpecEntMP1PC = { - _SYS_STR("MP1-PC"sv), _SYS_STR("Data specification for PC-optimized Metroid Prime engine"sv), _SYS_STR(".upak"sv), 2, - [](hecl::Database::Project& project, hecl::Database::DataSpecTool tool) -> std::unique_ptr { - if (tool != hecl::Database::DataSpecTool::Extract) - return std::make_unique(&SpecEntMP1PC, project, true); - return {}; + _SYS_STR("MP1-PC"sv), _SYS_STR("Data specification for PC-optimized Metroid Prime engine"sv), _SYS_STR(".upak"sv), + 2, + [](hecl::Database::Project& project, + hecl::Database::DataSpecTool tool) -> std::unique_ptr { + if (tool != hecl::Database::DataSpecTool::Extract) + return std::make_unique(&SpecEntMP1PC, project, true); + return {}; }}; hecl::Database::DataSpecEntry SpecEntMP1ORIG = { _SYS_STR("MP1-ORIG"sv), _SYS_STR("Data specification for unmodified Metroid Prime resources"sv), {}, 2, {}}; -} +} // namespace DataSpec diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp index ab92f300b..08bfc4b77 100644 --- a/DataSpec/SpecMP2.cpp +++ b/DataSpec/SpecMP2.cpp @@ -17,8 +17,7 @@ #include "Runtime/RetroTypes.hpp" #include "nod/nod.hpp" -namespace DataSpec -{ +namespace DataSpec { using namespace std::literals; @@ -26,551 +25,427 @@ static logvisor::Module Log("urde::SpecMP2"); extern hecl::Database::DataSpecEntry SpecEntMP2; extern hecl::Database::DataSpecEntry SpecEntMP2ORIG; -static const std::unordered_set IndividualOrigIDs = -{ - 0xB7BBD0B4, - 0x1F9DA858, - 0x2A13C23E, - 0xF13452F8, - 0xA91A7703, - 0xC042EC91, - 0x12A12131, - 0x5F556002, - 0xA9798329, - 0xB306E26F, - 0xCD7B1ACA, - 0x8ADA8184, - 0x1A29C0E6, - 0x5D9F9796, - 0x951546A8, - 0x7946C4C5, - 0x409AA72E, +static const std::unordered_set IndividualOrigIDs = { + 0xB7BBD0B4, 0x1F9DA858, 0x2A13C23E, 0xF13452F8, 0xA91A7703, 0xC042EC91, 0x12A12131, 0x5F556002, 0xA9798329, + 0xB306E26F, 0xCD7B1ACA, 0x8ADA8184, 0x1A29C0E6, 0x5D9F9796, 0x951546A8, 0x7946C4C5, 0x409AA72E, }; -struct OriginalIDs -{ - static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project) - { - std::unordered_set addedIDs; - std::vector originalIDs; +struct OriginalIDs { + static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project) { + std::unordered_set addedIDs; + std::vector originalIDs; - pakRouter.enumerateResources([&](const DNAMP2::PAK::Entry* ent) { - if (ent->type == FOURCC('MLVL') || - ent->type == FOURCC('SCAN') || - ent->type == FOURCC('MREA') || - IndividualOrigIDs.find(ent->id.toUint32()) != IndividualOrigIDs.end()) - { - if (addedIDs.find(ent->id) == addedIDs.cend()) - { - addedIDs.insert(ent->id); - originalIDs.push_back(ent->id); - } + pakRouter.enumerateResources([&](const DNAMP2::PAK::Entry* ent) { + if (ent->type == FOURCC('MLVL') || ent->type == FOURCC('SCAN') || ent->type == FOURCC('MREA') || + IndividualOrigIDs.find(ent->id.toUint32()) != IndividualOrigIDs.end()) { + if (addedIDs.find(ent->id) == addedIDs.cend()) { + addedIDs.insert(ent->id); + originalIDs.push_back(ent->id); + } + } + return true; + }); + std::sort(originalIDs.begin(), originalIDs.end()); + + athena::io::YAMLDocWriter yamlW("MP2OriginalIDs"); + for (const UniqueID32& id : originalIDs) { + hecl::ProjectPath path = pakRouter.getWorking(id); + yamlW.writeString(id.toString().c_str(), path.getRelativePathUTF8()); + } + hecl::ProjectPath path(project.getProjectWorkingPath(), "MP2/!original_ids.yaml"); + path.makeDirChain(false); + athena::io::FileWriter fileW(path.getAbsolutePath()); + yamlW.finish(&fileW); + } + + static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + hecl::Database::Project& project = inPath.getProject(); + athena::io::YAMLDocReader r; + athena::io::FileReader fr(inPath.getAbsolutePath()); + if (!fr.isOpen() || !r.parse(&fr)) + return; + + std::vector> originalIDs; + originalIDs.reserve(r.getRootNode()->m_mapChildren.size()); + for (const auto& node : r.getRootNode()->m_mapChildren) { + char* end = const_cast(node.first.c_str()); + u32 id = strtoul(end, &end, 16); + if (end != node.first.c_str() + 8) + continue; + + hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str()); + originalIDs.push_back(std::make_pair(id, path.hash().val32())); + } + std::sort(originalIDs.begin(), originalIDs.end(), + [](const std::pair& a, const std::pair& b) { + return a.first < b.first; + }); + + athena::io::FileWriter w(outPath.getAbsolutePath()); + w.writeUint32Big(originalIDs.size()); + for (const auto& idPair : originalIDs) { + idPair.first.write(w); + idPair.second.write(w); + } + + std::sort(originalIDs.begin(), originalIDs.end(), + [](const std::pair& a, const std::pair& b) { + return a.second < b.second; + }); + for (const auto& idPair : originalIDs) { + idPair.second.write(w); + idPair.first.write(w); + } + } +}; + +struct SpecMP2 : SpecBase { + bool checkStandaloneID(const char* id) const { + if (!memcmp(id, "G2M", 3)) + return true; + return false; + } + + std::vector m_nonPaks; + std::vector m_paks; + std::map m_orderedPaks; + + hecl::ProjectPath m_workPath; + hecl::ProjectPath m_cookPath; + PAKRouter m_pakRouter; + IDRestorer m_idRestorer; + + void setThreadProject() { + SpecBase::setThreadProject(); + UniqueIDBridge::SetIDRestorer(&m_idRestorer); + } + + SpecMP2(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) + : SpecBase(specEntry, project, pc) + , m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP2")) + , m_cookPath(project.getProjectCookedPath(SpecEntMP2), _SYS_STR("MP2")) + , m_pakRouter(*this, m_workPath, m_cookPath) + , m_idRestorer({project.getProjectWorkingPath(), "MP2/!original_ids.yaml"}, project) { + setThreadProject(); + } + + void buildPaks(nod::Node& root, const std::vector& args, ExtractReport& rep) { + m_nonPaks.clear(); + m_paks.clear(); + for (const nod::Node& child : root) { + bool isPak = false; + auto name = child.getName(); + std::string lowerName(name); + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); + if (name.size() > 4) { + std::string::iterator extit = lowerName.end() - 4; + if (!std::string(extit, lowerName.end()).compare(".pak")) { + /* This is a pak */ + isPak = true; + std::string lowerBase(lowerName.begin(), extit); + + /* Needs filter */ + bool good = true; + if (args.size()) { + good = false; + if (!lowerName.compare(0, 7, "metroid")) { + hecl::SystemChar idxChar = lowerName[7]; + for (const hecl::SystemString& arg : args) { + if (arg.size() == 1 && iswdigit(arg[0])) + if (arg[0] == idxChar) + good = true; + } + } else + good = true; + + if (!good) { + for (const hecl::SystemString& arg : args) { + std::string lowerArg(hecl::SystemUTF8Conv(arg).str()); + std::transform(lowerArg.begin(), lowerArg.end(), lowerArg.begin(), tolower); + if (!lowerArg.compare(0, lowerBase.size(), lowerBase)) + good = true; + } } - return true; - }); - std::sort(originalIDs.begin(), originalIDs.end()); + } - athena::io::YAMLDocWriter yamlW("MP2OriginalIDs"); - for (const UniqueID32& id : originalIDs) - { - hecl::ProjectPath path = pakRouter.getWorking(id); - yamlW.writeString(id.toString().c_str(), path.getRelativePathUTF8()); + m_paks.emplace_back(child, good); } - hecl::ProjectPath path(project.getProjectWorkingPath(), "MP2/!original_ids.yaml"); - path.makeDirChain(false); - athena::io::FileWriter fileW(path.getAbsolutePath()); - yamlW.finish(&fileW); + } + + if (!isPak) + m_nonPaks.push_back(&child); } - static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) - { - hecl::Database::Project& project = inPath.getProject(); - athena::io::YAMLDocReader r; - athena::io::FileReader fr(inPath.getAbsolutePath()); - if (!fr.isOpen() || !r.parse(&fr)) - return; + /* Sort PAKs alphabetically */ + m_orderedPaks.clear(); + for (DNAMP2::PAKBridge& dpak : m_paks) + m_orderedPaks[std::string(dpak.getName())] = &dpak; - std::vector> originalIDs; - originalIDs.reserve(r.getRootNode()->m_mapChildren.size()); - for (const auto& node : r.getRootNode()->m_mapChildren) - { - char* end = const_cast(node.first.c_str()); - u32 id = strtoul(end, &end, 16); - if (end != node.first.c_str() + 8) - continue; - - hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str()); - originalIDs.push_back(std::make_pair(id, path.hash().val32())); - } - std::sort(originalIDs.begin(), originalIDs.end(), - [](const std::pair& a, const std::pair& b) { - return a.first < b.first; - }); - - athena::io::FileWriter w(outPath.getAbsolutePath()); - w.writeUint32Big(originalIDs.size()); - for (const auto& idPair : originalIDs) - { - idPair.first.write(w); - idPair.second.write(w); - } - - std::sort(originalIDs.begin(), originalIDs.end(), - [](const std::pair& a, const std::pair& b) { - return a.second < b.second; - }); - for (const auto& idPair : originalIDs) - { - idPair.second.write(w); - idPair.first.write(w); - } + /* Assemble extract report */ + for (const std::pair& item : m_orderedPaks) { + if (!item.second->m_doExtract) + continue; + rep.childOpts.emplace_back(); + ExtractReport& childRep = rep.childOpts.back(); + hecl::SystemStringConv nameView(item.first); + childRep.name = hecl::SystemString(nameView.sys_str()); + childRep.desc = item.second->getLevelString(); } -}; + } -struct SpecMP2 : SpecBase -{ - bool checkStandaloneID(const char* id) const - { - if (!memcmp(id, "G2M", 3)) - return true; + bool checkFromStandaloneDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, + const std::vector& args, std::vector& reps) { + nod::IPartition* partition = disc.getDataPartition(); + std::unique_ptr dolBuf = partition->getDOLBuf(); + const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19; + if (!buildInfo) + return false; + + /* Root Report */ + reps.emplace_back(); + ExtractReport& rep = reps.back(); + rep.name = _SYS_STR("MP2"); + rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr; + std::string buildStr(buildInfo); + hecl::SystemStringConv buildView(buildStr); + rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); + + /* Iterate PAKs and build level options */ + nod::Node& root = partition->getFSTRoot(); + buildPaks(root, args, rep); + + return true; + } + + bool checkFromTrilogyDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, + const std::vector& args, std::vector& reps) { + std::vector mp2args; + bool doExtract = false; + if (args.size()) { + /* Needs filter */ + for (const hecl::SystemString& arg : args) { + hecl::SystemString lowerArg = arg; + hecl::ToLower(lowerArg); + if (!lowerArg.compare(0, 3, _SYS_STR("mp2"))) { + doExtract = true; + mp2args.reserve(args.size()); + size_t slashPos = arg.find(_SYS_STR('/')); + if (slashPos == hecl::SystemString::npos) + slashPos = arg.find(_SYS_STR('\\')); + if (slashPos != hecl::SystemString::npos) + mp2args.emplace_back(hecl::SystemString(arg.begin() + slashPos + 1, arg.end())); + } + } + } else + doExtract = true; + + if (!doExtract) + return false; + + nod::IPartition* partition = disc.getDataPartition(); + nod::Node& root = partition->getFSTRoot(); + nod::Node::DirectoryIterator dolIt = root.find("rs5mp2_p.dol"); + if (dolIt == root.end()) { + dolIt = root.find("rs5mp2jpn_p.dol"); + if (dolIt == root.end()) return false; } - std::vector m_nonPaks; - std::vector m_paks; - std::map m_orderedPaks; + std::unique_ptr dolBuf = dolIt->getBuf(); + const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; - hecl::ProjectPath m_workPath; - hecl::ProjectPath m_cookPath; - PAKRouter m_pakRouter; - IDRestorer m_idRestorer; - - void setThreadProject() - { - SpecBase::setThreadProject(); - UniqueIDBridge::SetIDRestorer(&m_idRestorer); + /* Root Report */ + reps.emplace_back(); + ExtractReport& rep = reps.back(); + rep.name = _SYS_STR("MP2"); + rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr; + if (buildInfo) { + std::string buildStr(buildInfo); + hecl::SystemStringConv buildView(buildStr); + rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); } - SpecMP2(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) - : SpecBase(specEntry, project, pc), - m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP2")), - m_cookPath(project.getProjectCookedPath(SpecEntMP2), _SYS_STR("MP2")), - m_pakRouter(*this, m_workPath, m_cookPath), - m_idRestorer({project.getProjectWorkingPath(), "MP2/!original_ids.yaml"}, project) - { - setThreadProject(); + /* Iterate PAKs and build level options */ + nod::Node::DirectoryIterator mp2It = root.find("MP2"); + if (mp2It == root.end()) { + mp2It = root.find("MP2JPN"); + if (mp2It == root.end()) + return false; + } + buildPaks(*mp2It, mp2args, rep); + + return true; + } + + bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) { + nod::ExtractionContext ctx = {force, nullptr}; + + m_workPath.makeDir(); + + progress.startNewLine(); + progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 0.0); + m_pakRouter.build(m_paks, + [&progress](float factor) { progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), factor); }); + progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 1.0); + + hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _SYS_STR("out")); + outPath.makeDir(); + disc.getDataPartition()->extractSysFiles(outPath.getAbsolutePath(), ctx); + hecl::ProjectPath mp2OutPath(outPath, m_standalone ? _SYS_STR("files") : _SYS_STR("files/MP2")); + mp2OutPath.makeDirChain(true); + + progress.startNewLine(); + progress.print(_SYS_STR("MP2 Root"), _SYS_STR(""), 0.0); + int prog = 0; + ctx.progressCB = [&prog, &progress](std::string_view name, float) { + hecl::SystemStringConv nameView(name); + progress.print(_SYS_STR("MP2 Root"), nameView.c_str(), prog); + }; + for (const nod::Node* node : m_nonPaks) { + node->extractToDirectory(mp2OutPath.getAbsolutePath(), ctx); + prog++; + } + progress.print(_SYS_STR("MP2 Root"), _SYS_STR(""), 1.0); + + hecl::ClientProcess process; + progress.startNewLine(); + for (std::pair& pair : m_orderedPaks) { + DNAMP2::PAKBridge& pak = *pair.second; + if (!pak.m_doExtract) + continue; + + auto name = pak.getName(); + hecl::SystemStringConv sysName(name); + + auto pakName = hecl::SystemString(sysName.sys_str()); + process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) { + int threadIdx = hecl::ClientProcess::GetThreadWorkerIdx(); + m_pakRouter.extractResources(pak, force, btok, + [&progress, &pakName, threadIdx](const hecl::SystemChar* substr, float factor) { + progress.print(pakName.c_str(), substr, factor, threadIdx); + }); + }); } - void buildPaks(nod::Node& root, - const std::vector& args, - ExtractReport& rep) - { - m_nonPaks.clear(); - m_paks.clear(); - for (const nod::Node& child : root) - { - bool isPak = false; - auto name = child.getName(); - std::string lowerName(name); - std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); - if (name.size() > 4) - { - std::string::iterator extit = lowerName.end() - 4; - if (!std::string(extit, lowerName.end()).compare(".pak")) - { - /* This is a pak */ - isPak = true; - std::string lowerBase(lowerName.begin(), extit); + process.waitUntilComplete(); - /* Needs filter */ - bool good = true; - if (args.size()) - { - good = false; - if (!lowerName.compare(0, 7, "metroid")) - { - hecl::SystemChar idxChar = lowerName[7]; - for (const hecl::SystemString& arg : args) - { - if (arg.size() == 1 && iswdigit(arg[0])) - if (arg[0] == idxChar) - good = true; - } - } - else - good = true; + /* Generate original ID mapping for MLVL and SCAN entries - marks complete project */ + OriginalIDs::Generate(m_pakRouter, m_project); - if (!good) - { - for (const hecl::SystemString& arg : args) - { - std::string lowerArg(hecl::SystemUTF8Conv(arg).str()); - std::transform(lowerArg.begin(), lowerArg.end(), lowerArg.begin(), tolower); - if (!lowerArg.compare(0, lowerBase.size(), lowerBase)) - good = true; - } - } - } + return true; + } - m_paks.emplace_back(child, good); - } - } + const hecl::Database::DataSpecEntry& getOriginalSpec() const { return SpecEntMP2; } - if (!isPak) - m_nonPaks.push_back(&child); - } + const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const { return SpecEntMP2ORIG; } - /* Sort PAKs alphabetically */ - m_orderedPaks.clear(); - for (DNAMP2::PAKBridge& dpak : m_paks) - m_orderedPaks[std::string(dpak.getName())] = &dpak; + hecl::ProjectPath getWorking(class UniqueID32& id) { return m_pakRouter.getWorking(id); } - /* Assemble extract report */ - for (const std::pair& item : m_orderedPaks) - { - if (!item.second->m_doExtract) - continue; - rep.childOpts.emplace_back(); - ExtractReport& childRep = rep.childOpts.back(); - hecl::SystemStringConv nameView(item.first); - childRep.name = hecl::SystemString(nameView.sys_str()); - childRep.desc = item.second->getLevelString(); - } - } - - bool checkFromStandaloneDisc(nod::DiscBase& disc, - const hecl::SystemString& regstr, - const std::vector& args, - std::vector& reps) - { - nod::IPartition* partition = disc.getDataPartition(); - std::unique_ptr dolBuf = partition->getDOLBuf(); - const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19; - if (!buildInfo) - return false; - - /* Root Report */ - reps.emplace_back(); - ExtractReport& rep = reps.back(); - rep.name = _SYS_STR("MP2"); - rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr; - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); - rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); - - /* Iterate PAKs and build level options */ - nod::Node& root = partition->getFSTRoot(); - buildPaks(root, args, rep); + bool checkPathPrefix(const hecl::ProjectPath& path) const { + return path.getRelativePath().compare(0, 4, _SYS_STR("MP2/")) == 0; + } + bool validateYAMLDNAType(athena::io::IStreamReader& fp) const { + athena::io::YAMLDocReader reader; + yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)athena::io::YAMLAthenaReader, &fp); + return reader.ClassTypeOperation([](const char* classType) { + if (!strcmp(classType, DNAMP2::MLVL::DNAType())) return true; - } - - bool checkFromTrilogyDisc(nod::DiscBase& disc, - const hecl::SystemString& regstr, - const std::vector& args, - std::vector& reps) - { - std::vector mp2args; - bool doExtract = false; - if (args.size()) - { - /* Needs filter */ - for (const hecl::SystemString& arg : args) - { - hecl::SystemString lowerArg = arg; - hecl::ToLower(lowerArg); - if (!lowerArg.compare(0, 3, _SYS_STR("mp2"))) - { - doExtract = true; - mp2args.reserve(args.size()); - size_t slashPos = arg.find(_SYS_STR('/')); - if (slashPos == hecl::SystemString::npos) - slashPos = arg.find(_SYS_STR('\\')); - if (slashPos != hecl::SystemString::npos) - mp2args.emplace_back(hecl::SystemString(arg.begin() + slashPos + 1, arg.end())); - } - } - } - else - doExtract = true; - - if (!doExtract) - return false; - - nod::IPartition* partition = disc.getDataPartition(); - nod::Node& root = partition->getFSTRoot(); - nod::Node::DirectoryIterator dolIt = root.find("rs5mp2_p.dol"); - if (dolIt == root.end()) - { - dolIt = root.find("rs5mp2jpn_p.dol"); - if (dolIt == root.end()) - return false; - } - - std::unique_ptr dolBuf = dolIt->getBuf(); - const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; - - /* Root Report */ - reps.emplace_back(); - ExtractReport& rep = reps.back(); - rep.name = _SYS_STR("MP2"); - rep.desc = _SYS_STR("Metroid Prime 2 ") + regstr; - if (buildInfo) - { - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); - rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); - } - - /* Iterate PAKs and build level options */ - nod::Node::DirectoryIterator mp2It = root.find("MP2"); - if (mp2It == root.end()) - { - mp2It = root.find("MP2JPN"); - if (mp2It == root.end()) - return false; - } - buildPaks(*mp2It, mp2args, rep); - + else if (!strcmp(classType, DNAMP2::STRG::DNAType())) return true; - } - - bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) - { - nod::ExtractionContext ctx = {force, nullptr}; - - m_workPath.makeDir(); - - progress.startNewLine(); - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 0.0); - m_pakRouter.build(m_paks, [&progress](float factor) - { - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), factor); - }); - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 1.0); - - hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _SYS_STR("out")); - outPath.makeDir(); - disc.getDataPartition()->extractSysFiles(outPath.getAbsolutePath(), ctx); - hecl::ProjectPath mp2OutPath(outPath, m_standalone ? _SYS_STR("files") : _SYS_STR("files/MP2")); - mp2OutPath.makeDirChain(true); - - progress.startNewLine(); - progress.print(_SYS_STR("MP2 Root"), _SYS_STR(""), 0.0); - int prog = 0; - ctx.progressCB = [&prog, &progress](std::string_view name, float) { - hecl::SystemStringConv nameView(name); - progress.print(_SYS_STR("MP2 Root"), nameView.c_str(), prog); - }; - for (const nod::Node* node : m_nonPaks) - { - node->extractToDirectory(mp2OutPath.getAbsolutePath(), ctx); - prog++; - } - progress.print(_SYS_STR("MP2 Root"), _SYS_STR(""), 1.0); - - hecl::ClientProcess process; - progress.startNewLine(); - for (std::pair& pair : m_orderedPaks) - { - DNAMP2::PAKBridge& pak = *pair.second; - if (!pak.m_doExtract) - continue; - - auto name = pak.getName(); - hecl::SystemStringConv sysName(name); - - auto pakName = hecl::SystemString(sysName.sys_str()); - process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) - { - int threadIdx = hecl::ClientProcess::GetThreadWorkerIdx(); - m_pakRouter.extractResources(pak, force, btok, - [&progress, &pakName, threadIdx](const hecl::SystemChar* substr, float factor) - { - progress.print(pakName.c_str(), substr, factor, threadIdx); - }); - }); - } - - process.waitUntilComplete(); - - /* Generate original ID mapping for MLVL and SCAN entries - marks complete project */ - OriginalIDs::Generate(m_pakRouter, m_project); - + else if (!strcmp(classType, "ATBL")) return true; - } + return false; + }); + } - const hecl::Database::DataSpecEntry& getOriginalSpec() const - { - return SpecEntMP2; - } + urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { return {}; } - const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const - { - return SpecEntMP2ORIG; - } + void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - hecl::ProjectPath getWorking(class UniqueID32& id) - { - return m_pakRouter.getWorking(id); - } + void cookColMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - bool checkPathPrefix(const hecl::ProjectPath& path) const - { - return path.getRelativePath().compare(0, 4, _SYS_STR("MP2/")) == 0; - } + void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - bool validateYAMLDNAType(athena::io::IStreamReader& fp) const - { - athena::io::YAMLDocReader reader; - yaml_parser_set_input(reader.getParser(), (yaml_read_handler_t*)athena::io::YAMLAthenaReader, &fp); - return reader.ClassTypeOperation([](const char* classType) - { - if (!strcmp(classType, DNAMP2::MLVL::DNAType())) - return true; - else if (!strcmp(classType, DNAMP2::STRG::DNAType())) - return true; - else if (!strcmp(classType, "ATBL")) - return true; - return false; - }); - } + void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const - { - return {}; - } + void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookColMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin, + FCookProgress progress) {} - void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector& pathsOut) {} - void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void flattenDependenciesANCSYAML(athena::io::IStreamReader& fin, std::vector& pathsOut, + int charIdx) {} - void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) { + DNAMP2::AGSC::Cook(in, out); + progress(_SYS_STR("Done")); + } - void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) { + DNAMP1::CSNG::Cook(in, out); + progress(_SYS_STR("Done")); + } - void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - athena::io::IStreamReader& fin, FCookProgress progress) - { - } + void cookMapArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) { + hecl::blender::MapArea mapa = ds.compileMapArea(); + ds.close(); + DNAMP2::MAPA::Cook(mapa, out); + progress(_SYS_STR("Done")); + } - void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector& pathsOut) - { - } + void cookMapUniverse(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) { + hecl::blender::MapUniverse mapu = ds.compileMapUniverse(); + ds.close(); + DNAMAPU::MAPU::Cook(mapu, out); + progress(_SYS_STR("Done")); + } - void flattenDependenciesANCSYAML(athena::io::IStreamReader& fin, std::vector& pathsOut, int charIdx) - { - } + UniqueID32 newToOriginal(urde::CAssetId id) const { + if (UniqueID32 origId = m_idRestorer.newToOriginal({uint32_t(id.Value()), true})) + return {origId.toUint32(), true}; + return {uint32_t(id.Value()), true}; + } - void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - FCookProgress progress) - { - DNAMP2::AGSC::Cook(in, out); - progress(_SYS_STR("Done")); - } - - void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - FCookProgress progress) - { - DNAMP1::CSNG::Cook(in, out); - progress(_SYS_STR("Done")); - } - - void cookMapArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress) - { - hecl::blender::MapArea mapa = ds.compileMapArea(); - ds.close(); - DNAMP2::MAPA::Cook(mapa, out); - progress(_SYS_STR("Done")); - } - - void cookMapUniverse(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress) - { - hecl::blender::MapUniverse mapu = ds.compileMapUniverse(); - ds.close(); - DNAMAPU::MAPU::Cook(mapu, out); - progress(_SYS_STR("Done")); - } - - UniqueID32 newToOriginal(urde::CAssetId id) const - { - if (UniqueID32 origId = m_idRestorer.newToOriginal({uint32_t(id.Value()), true})) - return {origId.toUint32(), true}; - return {uint32_t(id.Value()), true}; - } - - urde::CAssetId originalToNew(UniqueID32 id) const - { - if (UniqueID32 newId = m_idRestorer.originalToNew(id)) - return newId.toUint32(); - return id.toUint32(); - } + urde::CAssetId originalToNew(UniqueID32 id) const { + if (UniqueID32 newId = m_idRestorer.originalToNew(id)) + return newId.toUint32(); + return id.toUint32(); + } }; -hecl::Database::DataSpecEntry SpecEntMP2 -( - _SYS_STR("MP2"sv), - _SYS_STR("Data specification for original Metroid Prime 2 engine"sv), _SYS_STR(".pak"sv), 2, - [](hecl::Database::Project& project, hecl::Database::DataSpecTool) - -> std::unique_ptr {return std::make_unique(&SpecEntMP2, project, false);} -); +hecl::Database::DataSpecEntry SpecEntMP2( + _SYS_STR("MP2"sv), _SYS_STR("Data specification for original Metroid Prime 2 engine"sv), _SYS_STR(".pak"sv), 2, + [](hecl::Database::Project& project, hecl::Database::DataSpecTool) -> std::unique_ptr { + return std::make_unique(&SpecEntMP2, project, false); + }); -hecl::Database::DataSpecEntry SpecEntMP2PC = -{ - _SYS_STR("MP2-PC"sv), - _SYS_STR("Data specification for PC-optimized Metroid Prime 2 engine"sv), _SYS_STR(".upak"sv), 2, - [](hecl::Database::Project& project, hecl::Database::DataSpecTool tool) - -> std::unique_ptr - { - if (tool != hecl::Database::DataSpecTool::Extract) - return std::make_unique(&SpecEntMP2PC, project, true); - return {}; - } -}; +hecl::Database::DataSpecEntry SpecEntMP2PC = { + _SYS_STR("MP2-PC"sv), _SYS_STR("Data specification for PC-optimized Metroid Prime 2 engine"sv), _SYS_STR(".upak"sv), + 2, + [](hecl::Database::Project& project, + hecl::Database::DataSpecTool tool) -> std::unique_ptr { + if (tool != hecl::Database::DataSpecTool::Extract) + return std::make_unique(&SpecEntMP2PC, project, true); + return {}; + }}; -hecl::Database::DataSpecEntry SpecEntMP2ORIG = -{ - _SYS_STR("MP2-ORIG"sv), - _SYS_STR("Data specification for unmodified Metroid Prime 2 resources"sv), - {}, 2, {} -}; +hecl::Database::DataSpecEntry SpecEntMP2ORIG = { + _SYS_STR("MP2-ORIG"sv), _SYS_STR("Data specification for unmodified Metroid Prime 2 resources"sv), {}, 2, {}}; -} +} // namespace DataSpec diff --git a/DataSpec/SpecMP3.cpp b/DataSpec/SpecMP3.cpp index 80448d28c..61ab13132 100644 --- a/DataSpec/SpecMP3.cpp +++ b/DataSpec/SpecMP3.cpp @@ -16,8 +16,7 @@ #include "Runtime/RetroTypes.hpp" #include "nod/nod.hpp" -namespace DataSpec -{ +namespace DataSpec { using namespace std::literals; @@ -25,719 +24,575 @@ static logvisor::Module Log("urde::SpecMP3"); extern hecl::Database::DataSpecEntry SpecEntMP3; extern hecl::Database::DataSpecEntry SpecEntMP3ORIG; -static const std::unordered_set IndividualOrigIDs = -{ +static const std::unordered_set IndividualOrigIDs = {}; + +struct OriginalIDs { + static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project) { + std::unordered_set addedIDs; + std::vector originalIDs; + + pakRouter.enumerateResources([&](const DNAMP3::PAK::Entry* ent) { + if (ent->type == FOURCC('MLVL') || ent->type == FOURCC('SCAN') || ent->type == FOURCC('MREA') || + IndividualOrigIDs.find(ent->id.toUint64()) != IndividualOrigIDs.end()) { + if (addedIDs.find(ent->id) == addedIDs.cend()) { + addedIDs.insert(ent->id); + originalIDs.push_back(ent->id); + } + } + return true; + }); + std::sort(originalIDs.begin(), originalIDs.end()); + + athena::io::YAMLDocWriter yamlW("MP3OriginalIDs"); + for (const UniqueID64& id : originalIDs) { + hecl::ProjectPath path = pakRouter.getWorking(id); + yamlW.writeString(id.toString().c_str(), path.getRelativePathUTF8()); + } + hecl::ProjectPath path(project.getProjectWorkingPath(), "MP3/!original_ids.yaml"); + path.makeDirChain(false); + athena::io::FileWriter fileW(path.getAbsolutePath()); + yamlW.finish(&fileW); + } + + static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) { + hecl::Database::Project& project = inPath.getProject(); + athena::io::YAMLDocReader r; + athena::io::FileReader fr(inPath.getAbsolutePath()); + if (!fr.isOpen() || !r.parse(&fr)) + return; + + std::vector> originalIDs; + originalIDs.reserve(r.getRootNode()->m_mapChildren.size()); + for (const auto& node : r.getRootNode()->m_mapChildren) { + char* end = const_cast(node.first.c_str()); + u32 id = strtoul(end, &end, 16); + if (end != node.first.c_str() + 8) + continue; + + hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str()); + originalIDs.push_back(std::make_pair(id, path.hash().val32())); + } + std::sort(originalIDs.begin(), originalIDs.end(), + [](const std::pair& a, const std::pair& b) { + return a.first < b.first; + }); + + athena::io::FileWriter w(outPath.getAbsolutePath()); + w.writeUint32Big(originalIDs.size()); + for (const auto& idPair : originalIDs) { + idPair.first.write(w); + idPair.second.write(w); + } + + std::sort(originalIDs.begin(), originalIDs.end(), + [](const std::pair& a, const std::pair& b) { + return a.second < b.second; + }); + for (const auto& idPair : originalIDs) { + idPair.second.write(w); + idPair.first.write(w); + } + } }; -struct OriginalIDs -{ - static void Generate(PAKRouter& pakRouter, hecl::Database::Project& project) - { - std::unordered_set addedIDs; - std::vector originalIDs; +struct SpecMP3 : SpecBase { + bool checkStandaloneID(const char* id) const { + if (!memcmp(id, "RM3", 3)) + return true; + return false; + } - pakRouter.enumerateResources([&](const DNAMP3::PAK::Entry* ent) { - if (ent->type == FOURCC('MLVL') || - ent->type == FOURCC('SCAN') || - ent->type == FOURCC('MREA') || - IndividualOrigIDs.find(ent->id.toUint64()) != IndividualOrigIDs.end()) - { - if (addedIDs.find(ent->id) == addedIDs.cend()) - { - addedIDs.insert(ent->id); - originalIDs.push_back(ent->id); - } + bool doMP3 = false; + std::vector m_nonPaks; + std::vector m_paks; + std::map m_orderedPaks; + + hecl::ProjectPath m_workPath; + hecl::ProjectPath m_cookPath; + PAKRouter m_pakRouter; + + /* These are populated when extracting MPT's frontend (uses MP3's DataSpec) */ + bool doMPTFE = false; + std::vector m_feNonPaks; + std::vector m_fePaks; + std::map m_feOrderedPaks; + + hecl::ProjectPath m_feWorkPath; + hecl::ProjectPath m_feCookPath; + PAKRouter m_fePakRouter; + IDRestorer m_idRestorer; + + void setThreadProject() { + SpecBase::setThreadProject(); + UniqueIDBridge::SetIDRestorer(&m_idRestorer); + } + + SpecMP3(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) + : SpecBase(specEntry, project, pc) + , m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP3")) + , m_cookPath(project.getProjectCookedPath(SpecEntMP3), _SYS_STR("MP3")) + , m_pakRouter(*this, m_workPath, m_cookPath) + , m_feWorkPath(project.getProjectWorkingPath(), _SYS_STR("fe")) + , m_feCookPath(project.getProjectCookedPath(SpecEntMP3), _SYS_STR("fe")) + , m_fePakRouter(*this, m_feWorkPath, m_feCookPath) + , m_idRestorer({project.getProjectWorkingPath(), "MP3/!original_ids.yaml"}, project) { + setThreadProject(); + } + + void buildPaks(nod::Node& root, const std::vector& args, ExtractReport& rep, bool fe) { + if (fe) { + m_feNonPaks.clear(); + m_fePaks.clear(); + } else { + m_nonPaks.clear(); + m_paks.clear(); + } + for (const nod::Node& child : root) { + bool isPak = false; + auto name = child.getName(); + std::string lowerName(name); + std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); + if (name.size() > 4) { + std::string::iterator extit = lowerName.end() - 4; + if (!std::string(extit, lowerName.end()).compare(".pak")) { + /* This is a pak */ + isPak = true; + std::string lowerBase(lowerName.begin(), extit); + + /* Needs filter */ + bool good = true; + if (args.size()) { + good = false; + if (!lowerName.compare(0, 7, "metroid")) { + hecl::SystemChar idxChar = lowerName[7]; + for (const hecl::SystemString& arg : args) { + if (arg.size() == 1 && iswdigit(arg[0])) + if (arg[0] == idxChar) + good = true; + } + } else + good = true; + + if (!good) { + for (const hecl::SystemString& arg : args) { + std::string lowerArg(hecl::SystemUTF8Conv(arg).str()); + std::transform(lowerArg.begin(), lowerArg.end(), lowerArg.begin(), tolower); + if (!lowerArg.compare(0, lowerBase.size(), lowerBase)) + good = true; + } } - return true; - }); - std::sort(originalIDs.begin(), originalIDs.end()); + } - athena::io::YAMLDocWriter yamlW("MP3OriginalIDs"); - for (const UniqueID64& id : originalIDs) - { - hecl::ProjectPath path = pakRouter.getWorking(id); - yamlW.writeString(id.toString().c_str(), path.getRelativePathUTF8()); + if (fe) + m_fePaks.emplace_back(child, good); + else + m_paks.emplace_back(child, good); } - hecl::ProjectPath path(project.getProjectWorkingPath(), "MP3/!original_ids.yaml"); - path.makeDirChain(false); - athena::io::FileWriter fileW(path.getAbsolutePath()); - yamlW.finish(&fileW); - } + } - static void Cook(const hecl::ProjectPath& inPath, const hecl::ProjectPath& outPath) - { - hecl::Database::Project& project = inPath.getProject(); - athena::io::YAMLDocReader r; - athena::io::FileReader fr(inPath.getAbsolutePath()); - if (!fr.isOpen() || !r.parse(&fr)) - return; - - std::vector> originalIDs; - originalIDs.reserve(r.getRootNode()->m_mapChildren.size()); - for (const auto& node : r.getRootNode()->m_mapChildren) - { - char* end = const_cast(node.first.c_str()); - u32 id = strtoul(end, &end, 16); - if (end != node.first.c_str() + 8) - continue; - - hecl::ProjectPath path(project.getProjectWorkingPath(), node.second->m_scalarString.c_str()); - originalIDs.push_back(std::make_pair(id, path.hash().val32())); - } - std::sort(originalIDs.begin(), originalIDs.end(), - [](const std::pair& a, const std::pair& b) { - return a.first < b.first; - }); - - athena::io::FileWriter w(outPath.getAbsolutePath()); - w.writeUint32Big(originalIDs.size()); - for (const auto& idPair : originalIDs) - { - idPair.first.write(w); - idPair.second.write(w); - } - - std::sort(originalIDs.begin(), originalIDs.end(), - [](const std::pair& a, const std::pair& b) { - return a.second < b.second; - }); - for (const auto& idPair : originalIDs) - { - idPair.second.write(w); - idPair.first.write(w); - } - } -}; - -struct SpecMP3 : SpecBase -{ - bool checkStandaloneID(const char* id) const - { - if (!memcmp(id, "RM3", 3)) - return true; - return false; - } - - bool doMP3 = false; - std::vector m_nonPaks; - std::vector m_paks; - std::map m_orderedPaks; - - hecl::ProjectPath m_workPath; - hecl::ProjectPath m_cookPath; - PAKRouter m_pakRouter; - - /* These are populated when extracting MPT's frontend (uses MP3's DataSpec) */ - bool doMPTFE = false; - std::vector m_feNonPaks; - std::vector m_fePaks; - std::map m_feOrderedPaks; - - hecl::ProjectPath m_feWorkPath; - hecl::ProjectPath m_feCookPath; - PAKRouter m_fePakRouter; - IDRestorer m_idRestorer; - - void setThreadProject() - { - SpecBase::setThreadProject(); - UniqueIDBridge::SetIDRestorer(&m_idRestorer); - } - - SpecMP3(const hecl::Database::DataSpecEntry* specEntry, hecl::Database::Project& project, bool pc) - : SpecBase(specEntry, project, pc), - m_workPath(project.getProjectWorkingPath(), _SYS_STR("MP3")), - m_cookPath(project.getProjectCookedPath(SpecEntMP3), _SYS_STR("MP3")), - m_pakRouter(*this, m_workPath, m_cookPath), - m_feWorkPath(project.getProjectWorkingPath(), _SYS_STR("fe")), - m_feCookPath(project.getProjectCookedPath(SpecEntMP3), _SYS_STR("fe")), - m_fePakRouter(*this, m_feWorkPath, m_feCookPath), - m_idRestorer({project.getProjectWorkingPath(), "MP3/!original_ids.yaml"}, project) - { - setThreadProject(); - } - - void buildPaks(nod::Node& root, - const std::vector& args, - ExtractReport& rep, - bool fe) - { + if (!isPak) { if (fe) - { - m_feNonPaks.clear(); - m_fePaks.clear(); - } + m_feNonPaks.push_back(&child); else - { - m_nonPaks.clear(); - m_paks.clear(); - } - for (const nod::Node& child : root) - { - bool isPak = false; - auto name = child.getName(); - std::string lowerName(name); - std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower); - if (name.size() > 4) - { - std::string::iterator extit = lowerName.end() - 4; - if (!std::string(extit, lowerName.end()).compare(".pak")) - { - /* This is a pak */ - isPak = true; - std::string lowerBase(lowerName.begin(), extit); - - /* Needs filter */ - bool good = true; - if (args.size()) - { - good = false; - if (!lowerName.compare(0, 7, "metroid")) - { - hecl::SystemChar idxChar = lowerName[7]; - for (const hecl::SystemString& arg : args) - { - if (arg.size() == 1 && iswdigit(arg[0])) - if (arg[0] == idxChar) - good = true; - } - } - else - good = true; - - if (!good) - { - for (const hecl::SystemString& arg : args) - { - std::string lowerArg(hecl::SystemUTF8Conv(arg).str()); - std::transform(lowerArg.begin(), lowerArg.end(), lowerArg.begin(), tolower); - if (!lowerArg.compare(0, lowerBase.size(), lowerBase)) - good = true; - } - } - } - - if (fe) - m_fePaks.emplace_back(child, good); - else - m_paks.emplace_back(child, good); - } - } - - if (!isPak) - { - if (fe) - m_feNonPaks.push_back(&child); - else - m_nonPaks.push_back(&child); - } - } - - /* Sort PAKs alphabetically */ - if (fe) - { - m_feOrderedPaks.clear(); - for (DNAMP3::PAKBridge& dpak : m_fePaks) - m_feOrderedPaks[std::string(dpak.getName())] = &dpak; - } - else - { - m_orderedPaks.clear(); - for (DNAMP3::PAKBridge& dpak : m_paks) - m_orderedPaks[std::string(dpak.getName())] = &dpak; - } - - /* Assemble extract report */ - for (const std::pair& item : fe ? m_feOrderedPaks : m_orderedPaks) - { - if (!item.second->m_doExtract) - continue; - rep.childOpts.emplace_back(); - ExtractReport& childRep = rep.childOpts.back(); - hecl::SystemStringConv nameView(item.first); - childRep.name = hecl::SystemString(nameView.sys_str()); - if (!item.first.compare("Worlds.pak")) - continue; - else if (!item.first.compare("Metroid6.pak")) - { - /* Phaaze doesn't have a world name D: */ - childRep.desc = _SYS_STR("Phaaze"); - continue; - } - else if (!item.first.compare("Metroid8.pak")) - { - /* Space world is misnamed */ - childRep.desc = _SYS_STR("Space"); - continue; - } - childRep.desc = item.second->getLevelString(); - } + m_nonPaks.push_back(&child); + } } - bool checkFromStandaloneDisc(nod::DiscBase& disc, - const hecl::SystemString& regstr, - const std::vector& args, - std::vector& reps) - { - doMP3 = true; - nod::IPartition* partition = disc.getDataPartition(); - std::unique_ptr dolBuf = partition->getDOLBuf(); - const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19; - if (!buildInfo) - return false; + /* Sort PAKs alphabetically */ + if (fe) { + m_feOrderedPaks.clear(); + for (DNAMP3::PAKBridge& dpak : m_fePaks) + m_feOrderedPaks[std::string(dpak.getName())] = &dpak; + } else { + m_orderedPaks.clear(); + for (DNAMP3::PAKBridge& dpak : m_paks) + m_orderedPaks[std::string(dpak.getName())] = &dpak; + } - /* We don't want no stinking demo dammit */ - if (!strcmp(buildInfo, "Build v3.068 3/2/2006 14:55:13")) - return false; + /* Assemble extract report */ + for (const std::pair& item : fe ? m_feOrderedPaks : m_orderedPaks) { + if (!item.second->m_doExtract) + continue; + rep.childOpts.emplace_back(); + ExtractReport& childRep = rep.childOpts.back(); + hecl::SystemStringConv nameView(item.first); + childRep.name = hecl::SystemString(nameView.sys_str()); + if (!item.first.compare("Worlds.pak")) + continue; + else if (!item.first.compare("Metroid6.pak")) { + /* Phaaze doesn't have a world name D: */ + childRep.desc = _SYS_STR("Phaaze"); + continue; + } else if (!item.first.compare("Metroid8.pak")) { + /* Space world is misnamed */ + childRep.desc = _SYS_STR("Space"); + continue; + } + childRep.desc = item.second->getLevelString(); + } + } - /* Root Report */ - reps.emplace_back(); - ExtractReport& rep = reps.back(); - rep.name = _SYS_STR("MP3"); - rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr; + bool checkFromStandaloneDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, + const std::vector& args, std::vector& reps) { + doMP3 = true; + nod::IPartition* partition = disc.getDataPartition(); + std::unique_ptr dolBuf = partition->getDOLBuf(); + const char* buildInfo = (char*)memmem(dolBuf.get(), partition->getDOLSize(), "MetroidBuildInfo", 16) + 19; + if (!buildInfo) + return false; + + /* We don't want no stinking demo dammit */ + if (!strcmp(buildInfo, "Build v3.068 3/2/2006 14:55:13")) + return false; + + /* Root Report */ + reps.emplace_back(); + ExtractReport& rep = reps.back(); + rep.name = _SYS_STR("MP3"); + rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr; + std::string buildStr(buildInfo); + hecl::SystemStringConv buildView(buildStr); + rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); + + /* Iterate PAKs and build level options */ + nod::Node& root = partition->getFSTRoot(); + buildPaks(root, args, rep, false); + + return true; + } + + bool checkFromTrilogyDisc(nod::DiscBase& disc, const hecl::SystemString& regstr, + const std::vector& args, std::vector& reps) { + std::vector mp3args; + std::vector feargs; + if (args.size()) { + /* Needs filter */ + for (const hecl::SystemString& arg : args) { + hecl::SystemString lowerArg = arg; + hecl::ToLower(lowerArg); + if (!lowerArg.compare(0, 3, _SYS_STR("mp3"))) { + doMP3 = true; + mp3args.reserve(args.size()); + size_t slashPos = arg.find(_SYS_STR('/')); + if (slashPos == hecl::SystemString::npos) + slashPos = arg.find(_SYS_STR('\\')); + if (slashPos != hecl::SystemString::npos) + mp3args.emplace_back(hecl::SystemString(arg.begin() + slashPos + 1, arg.end())); + } + } + + for (const hecl::SystemString& arg : args) { + hecl::SystemString lowerArg = arg; + hecl::ToLower(lowerArg); + if (!lowerArg.compare(0, 2, _SYS_STR("fe"))) { + doMPTFE = true; + feargs.reserve(args.size()); + size_t slashPos = arg.find(_SYS_STR('/')); + if (slashPos == hecl::SystemString::npos) + slashPos = arg.find(_SYS_STR('\\')); + if (slashPos != hecl::SystemString::npos) + feargs.emplace_back(hecl::SystemString(arg.begin() + slashPos + 1, arg.end())); + } + } + } else { + doMP3 = true; + doMPTFE = true; + } + + if (!doMP3 && !doMPTFE) + return false; + + nod::IPartition* partition = disc.getDataPartition(); + nod::Node& root = partition->getFSTRoot(); + + /* MP3 extract */ + while (doMP3) { + nod::Node::DirectoryIterator dolIt = root.find("rs5mp3_p.dol"); + if (dolIt == root.end()) { + doMP3 = false; + break; + } + + std::unique_ptr dolBuf = dolIt->getBuf(); + const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; + + if (!buildInfo) { + doMP3 = false; + break; + } + + /* We don't want no stinking demo dammit */ + if (!strcmp(buildInfo, "Build v3.068 3/2/2006 14:55:13")) { + doMP3 = false; + break; + } + + /* Root Report */ + reps.emplace_back(); + ExtractReport& rep = reps.back(); + rep.name = _SYS_STR("MP3"); + rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr; + + std::string buildStr(buildInfo); + hecl::SystemStringConv buildView(buildStr); + rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); + + /* Iterate PAKs and build level options */ + nod::Node::DirectoryIterator mp3It = root.find("MP3"); + if (mp3It == root.end()) { + doMP3 = false; + break; + } + buildPaks(*mp3It, mp3args, rep, false); + break; + } + + /* MPT Frontend extract */ + while (doMPTFE) { + nod::Node::DirectoryIterator dolIt = root.find("rs5fe_p.dol"); + if (dolIt == root.end()) { + doMPTFE = false; + break; + } + + std::unique_ptr dolBuf = dolIt->getBuf(); + const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; + + /* Root Report */ + reps.emplace_back(); + ExtractReport& rep = reps.back(); + rep.name = _SYS_STR("fe"); + rep.desc = _SYS_STR("Metroid Prime Trilogy Frontend ") + regstr; + if (buildInfo) { std::string buildStr(buildInfo); hecl::SystemStringConv buildView(buildStr); rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); + } - /* Iterate PAKs and build level options */ - nod::Node& root = partition->getFSTRoot(); - buildPaks(root, args, rep, false); - - return true; + /* Iterate PAKs and build level options */ + nod::Node::DirectoryIterator feIt = root.find("fe"); + if (feIt == root.end()) { + doMPTFE = false; + break; + } + buildPaks(*feIt, feargs, rep, true); + break; } - bool checkFromTrilogyDisc(nod::DiscBase& disc, - const hecl::SystemString& regstr, - const std::vector& args, - std::vector& reps) - { - std::vector mp3args; - std::vector feargs; - if (args.size()) - { - /* Needs filter */ - for (const hecl::SystemString& arg : args) - { - hecl::SystemString lowerArg = arg; - hecl::ToLower(lowerArg); - if (!lowerArg.compare(0, 3, _SYS_STR("mp3"))) - { - doMP3 = true; - mp3args.reserve(args.size()); - size_t slashPos = arg.find(_SYS_STR('/')); - if (slashPos == hecl::SystemString::npos) - slashPos = arg.find(_SYS_STR('\\')); - if (slashPos != hecl::SystemString::npos) - mp3args.emplace_back(hecl::SystemString(arg.begin() + slashPos + 1, arg.end())); - } - } + return doMP3 || doMPTFE; + } - for (const hecl::SystemString& arg : args) - { - hecl::SystemString lowerArg = arg; - hecl::ToLower(lowerArg); - if (!lowerArg.compare(0, 2, _SYS_STR("fe"))) - { - doMPTFE = true; - feargs.reserve(args.size()); - size_t slashPos = arg.find(_SYS_STR('/')); - if (slashPos == hecl::SystemString::npos) - slashPos = arg.find(_SYS_STR('\\')); - if (slashPos != hecl::SystemString::npos) - feargs.emplace_back(hecl::SystemString(arg.begin() + slashPos + 1, arg.end())); - } - } - } - else - { - doMP3 = true; - doMPTFE = true; - } + bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) { + hecl::SystemString currentTarget = _SYS_STR(""); + size_t nodeCount = 0; + int prog = 0; + nod::ExtractionContext ctx = {force, [&](std::string_view name, float) { + hecl::SystemStringConv nameView(name); + progress.print(currentTarget.c_str(), nameView.c_str(), prog / (float)nodeCount); + }}; + if (doMP3) { + m_workPath.makeDir(); - if (!doMP3 && !doMPTFE) - return false; + progress.startNewLine(); + progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 0.0); + m_pakRouter.build(m_paks, + [&progress](float factor) { progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), factor); }); + progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 1.0); + progress.startNewLine(); - nod::IPartition* partition = disc.getDataPartition(); - nod::Node& root = partition->getFSTRoot(); + hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _SYS_STR("out")); + outPath.makeDir(); + disc.getDataPartition()->extractSysFiles(outPath.getAbsolutePath(), ctx); + hecl::ProjectPath mp3OutPath(outPath, m_standalone ? _SYS_STR("files") : _SYS_STR("files/MP3")); + mp3OutPath.makeDirChain(true); - /* MP3 extract */ - while (doMP3) - { - nod::Node::DirectoryIterator dolIt = root.find("rs5mp3_p.dol"); - if (dolIt == root.end()) - { - doMP3 = false; - break; - } + currentTarget = _SYS_STR("MP3 Root"); + progress.print(currentTarget.c_str(), _SYS_STR(""), 0.0); + prog = 0; - std::unique_ptr dolBuf = dolIt->getBuf(); - const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; + nodeCount = m_nonPaks.size(); + // TODO: Make this more granular + for (const nod::Node* node : m_nonPaks) { + node->extractToDirectory(mp3OutPath.getAbsolutePath(), ctx); + prog++; + } + ctx.progressCB = nullptr; - if (!buildInfo) - { - doMP3 = false; - break; - } + progress.print(currentTarget.c_str(), _SYS_STR(""), 1.0); + progress.startNewLine(); - /* We don't want no stinking demo dammit */ - if (!strcmp(buildInfo, "Build v3.068 3/2/2006 14:55:13")) - { - doMP3 = false; - break; - } + hecl::ClientProcess process; + for (std::pair& pair : m_orderedPaks) { + DNAMP3::PAKBridge& pak = *pair.second; + if (!pak.m_doExtract) + continue; - /* Root Report */ - reps.emplace_back(); - ExtractReport& rep = reps.back(); - rep.name = _SYS_STR("MP3"); - rep.desc = _SYS_STR("Metroid Prime 3 ") + regstr; + auto name = pak.getName(); + hecl::SystemStringConv sysName(name); - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); - rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); + auto pakName = hecl::SystemString(sysName.sys_str()); + process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) { + m_pakRouter.extractResources(pak, force, btok, + [&progress, &pakName](const hecl::SystemChar* substr, float factor) { + progress.print(pakName.c_str(), substr, factor); + }); + }); + } + process.waitUntilComplete(); - /* Iterate PAKs and build level options */ - nod::Node::DirectoryIterator mp3It = root.find("MP3"); - if (mp3It == root.end()) - { - doMP3 = false; - break; - } - buildPaks(*mp3It, mp3args, rep, false); - break; - } - - /* MPT Frontend extract */ - while (doMPTFE) - { - nod::Node::DirectoryIterator dolIt = root.find("rs5fe_p.dol"); - if (dolIt == root.end()) - { - doMPTFE = false; - break; - } - - std::unique_ptr dolBuf = dolIt->getBuf(); - const char* buildInfo = (char*)memmem(dolBuf.get(), dolIt->size(), "MetroidBuildInfo", 16) + 19; - - /* Root Report */ - reps.emplace_back(); - ExtractReport& rep = reps.back(); - rep.name = _SYS_STR("fe"); - rep.desc = _SYS_STR("Metroid Prime Trilogy Frontend ") + regstr; - if (buildInfo) - { - std::string buildStr(buildInfo); - hecl::SystemStringConv buildView(buildStr); - rep.desc += _SYS_STR(" (") + buildView + _SYS_STR(")"); - } - - /* Iterate PAKs and build level options */ - nod::Node::DirectoryIterator feIt = root.find("fe"); - if (feIt == root.end()) - { - doMPTFE = false; - break; - } - buildPaks(*feIt, feargs, rep, true); - break; - } - - return doMP3 || doMPTFE; + /* Generate original ID mapping for MLVL and SCAN entries - marks complete project */ + OriginalIDs::Generate(m_pakRouter, m_project); } - bool extractFromDisc(nod::DiscBase& disc, bool force, const hecl::MultiProgressPrinter& progress) - { - hecl::SystemString currentTarget = _SYS_STR(""); - size_t nodeCount = 0; - int prog = 0; - nod::ExtractionContext ctx = {force, - [&](std::string_view name, float) - { - hecl::SystemStringConv nameView(name); - progress.print(currentTarget.c_str(), nameView.c_str(), prog / (float)nodeCount); - }}; - if (doMP3) - { - m_workPath.makeDir(); + if (doMPTFE) { + m_feWorkPath.makeDir(); - progress.startNewLine(); - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 0.0); - m_pakRouter.build(m_paks, [&progress](float factor) - { - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), factor); - }); - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 1.0); - progress.startNewLine(); + progress.startNewLine(); + progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 0.0); + m_fePakRouter.build( + m_fePaks, [&progress](float factor) { progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), factor); }); + progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 1.0); + progress.startNewLine(); - hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _SYS_STR("out")); - outPath.makeDir(); - disc.getDataPartition()->extractSysFiles(outPath.getAbsolutePath(), ctx); - hecl::ProjectPath mp3OutPath(outPath, m_standalone ? _SYS_STR("files") : _SYS_STR("files/MP3")); - mp3OutPath.makeDirChain(true); + hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _SYS_STR("out")); + outPath.makeDir(); + disc.getDataPartition()->extractSysFiles(outPath.getAbsolutePath(), ctx); + hecl::ProjectPath feOutPath(outPath, m_standalone ? _SYS_STR("files") : _SYS_STR("files/fe")); + feOutPath.makeDirChain(true); - currentTarget = _SYS_STR("MP3 Root"); - progress.print(currentTarget.c_str(), _SYS_STR(""), 0.0); - prog = 0; + currentTarget = _SYS_STR("fe Root"); + progress.print(currentTarget.c_str(), _SYS_STR(""), 0.0); + prog = 0; + nodeCount = m_feNonPaks.size(); - nodeCount = m_nonPaks.size(); - // TODO: Make this more granular - for (const nod::Node* node : m_nonPaks) - { - node->extractToDirectory(mp3OutPath.getAbsolutePath(), ctx); - prog++; - } - ctx.progressCB = nullptr; + // TODO: Make this more granular + for (const nod::Node* node : m_feNonPaks) { + node->extractToDirectory(feOutPath.getAbsolutePath(), ctx); + prog++; + } + progress.print(currentTarget.c_str(), _SYS_STR(""), 1.0); + progress.startNewLine(); - progress.print(currentTarget.c_str(), _SYS_STR(""), 1.0); - progress.startNewLine(); + hecl::ClientProcess process; + for (std::pair pair : m_feOrderedPaks) { + DNAMP3::PAKBridge& pak = *pair.second; + if (!pak.m_doExtract) + continue; - hecl::ClientProcess process; - for (std::pair& pair : m_orderedPaks) - { - DNAMP3::PAKBridge& pak = *pair.second; - if (!pak.m_doExtract) - continue; + auto name = pak.getName(); + hecl::SystemStringConv sysName(name); - auto name = pak.getName(); - hecl::SystemStringConv sysName(name); + hecl::SystemString pakName(sysName.sys_str()); + process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) { + m_fePakRouter.extractResources(pak, force, btok, + [&progress, &pakName](const hecl::SystemChar* substr, float factor) { + progress.print(pakName.c_str(), substr, factor); + }); + }); + } - auto pakName = hecl::SystemString(sysName.sys_str()); - process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) - { - m_pakRouter.extractResources(pak, force, btok, - [&progress, &pakName](const hecl::SystemChar* substr, float factor) - { - progress.print(pakName.c_str(), substr, factor); - }); - }); - } - - process.waitUntilComplete(); - - /* Generate original ID mapping for MLVL and SCAN entries - marks complete project */ - OriginalIDs::Generate(m_pakRouter, m_project); - } - - if (doMPTFE) - { - m_feWorkPath.makeDir(); - - progress.startNewLine(); - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 0.0); - m_fePakRouter.build(m_fePaks, [&progress](float factor) - { - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), factor); - }); - progress.print(_SYS_STR("Indexing PAKs"), _SYS_STR(""), 1.0); - progress.startNewLine(); - - hecl::ProjectPath outPath(m_project.getProjectWorkingPath(), _SYS_STR("out")); - outPath.makeDir(); - disc.getDataPartition()->extractSysFiles(outPath.getAbsolutePath(), ctx); - hecl::ProjectPath feOutPath(outPath, m_standalone ? _SYS_STR("files") : _SYS_STR("files/fe")); - feOutPath.makeDirChain(true); - - currentTarget = _SYS_STR("fe Root"); - progress.print(currentTarget.c_str(), _SYS_STR(""), 0.0); - prog = 0; - nodeCount = m_feNonPaks.size(); - - // TODO: Make this more granular - for (const nod::Node* node : m_feNonPaks) - { - node->extractToDirectory(feOutPath.getAbsolutePath(), ctx); - prog++; - } - progress.print(currentTarget.c_str(), _SYS_STR(""), 1.0); - progress.startNewLine(); - - hecl::ClientProcess process; - for (std::pair pair : m_feOrderedPaks) - { - DNAMP3::PAKBridge& pak = *pair.second; - if (!pak.m_doExtract) - continue; - - auto name = pak.getName(); - hecl::SystemStringConv sysName(name); - - hecl::SystemString pakName(sysName.sys_str()); - process.addLambdaTransaction([this, &progress, &pak, pakName, force](hecl::blender::Token& btok) - { - m_fePakRouter.extractResources(pak, force, btok, - [&progress, &pakName](const hecl::SystemChar* substr, float factor) - { - progress.print(pakName.c_str(), substr, factor); - }); - }); - } - - process.waitUntilComplete(); - } - return true; + process.waitUntilComplete(); } + return true; + } - const hecl::Database::DataSpecEntry& getOriginalSpec() const - { - return SpecEntMP3; - } + const hecl::Database::DataSpecEntry& getOriginalSpec() const { return SpecEntMP3; } - const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const - { - return SpecEntMP3ORIG; - } + const hecl::Database::DataSpecEntry& getUnmodifiedSpec() const { return SpecEntMP3ORIG; } - hecl::ProjectPath getWorking(class UniqueID64& id) - { - return m_pakRouter.getWorking(id); - } + hecl::ProjectPath getWorking(class UniqueID64& id) { return m_pakRouter.getWorking(id); } - bool checkPathPrefix(const hecl::ProjectPath& path) const - { - return path.getRelativePath().compare(0, 4, _SYS_STR("MP3/")) == 0; - } + bool checkPathPrefix(const hecl::ProjectPath& path) const { + return path.getRelativePath().compare(0, 4, _SYS_STR("MP3/")) == 0; + } - bool validateYAMLDNAType(athena::io::IStreamReader& fp) const - { - if (athena::io::ValidateFromYAMLStream(fp)) - return true; - if (athena::io::ValidateFromYAMLStream(fp)) - return true; - if (athena::io::ValidateFromYAMLStream(fp)) - return true; - return false; - } + bool validateYAMLDNAType(athena::io::IStreamReader& fp) const { + if (athena::io::ValidateFromYAMLStream(fp)) + return true; + if (athena::io::ValidateFromYAMLStream(fp)) + return true; + if (athena::io::ValidateFromYAMLStream(fp)) + return true; + return false; + } - urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const - { - return {}; - } + urde::SObjectTag buildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { return {}; } - void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookColMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookColMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookPathMesh(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookActor(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, bool fast, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookGuiFrame(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) {} - void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - athena::io::IStreamReader& fin, FCookProgress progress) - { - } + void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin, + FCookProgress progress) {} - void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector& pathsOut) - { - } + void flattenDependenciesYAML(athena::io::IStreamReader& fin, std::vector& pathsOut) {} - void flattenDependenciesANCSYAML(athena::io::IStreamReader& fin, std::vector& pathsOut, int charIdx) - { - } + void flattenDependenciesANCSYAML(athena::io::IStreamReader& fin, std::vector& pathsOut, + int charIdx) {} - void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - FCookProgress progress) - { - } + void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) {} - void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - FCookProgress progress) - { - } + void cookSong(const hecl::ProjectPath& out, const hecl::ProjectPath& in, FCookProgress progress) {} - void cookMapArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress) - { - hecl::blender::MapArea mapa = ds.compileMapArea(); - ds.close(); - DNAMP3::MAPA::Cook(mapa, out); - progress(_SYS_STR("Done")); - } + void cookMapArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) { + hecl::blender::MapArea mapa = ds.compileMapArea(); + ds.close(); + DNAMP3::MAPA::Cook(mapa, out); + progress(_SYS_STR("Done")); + } - void cookMapUniverse(const hecl::ProjectPath& out, const hecl::ProjectPath& in, - BlendStream& ds, hecl::blender::Token& btok, - FCookProgress progress) - { - } + void cookMapUniverse(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, + hecl::blender::Token& btok, FCookProgress progress) {} - UniqueID64 newToOriginal(urde::CAssetId id) const - { - if (UniqueID64 origId = m_idRestorer.newToOriginal({id.Value(), true})) - return {origId.toUint64(), true}; - return {uint32_t(id.Value()), true}; - } - - urde::CAssetId originalToNew(UniqueID64 id) const - { - if (UniqueID64 newId = m_idRestorer.originalToNew(id)) - return newId.toUint64(); - return id.toUint64(); - } + UniqueID64 newToOriginal(urde::CAssetId id) const { + if (UniqueID64 origId = m_idRestorer.newToOriginal({id.Value(), true})) + return {origId.toUint64(), true}; + return {uint32_t(id.Value()), true}; + } + urde::CAssetId originalToNew(UniqueID64 id) const { + if (UniqueID64 newId = m_idRestorer.originalToNew(id)) + return newId.toUint64(); + return id.toUint64(); + } }; -hecl::Database::DataSpecEntry SpecEntMP3 -( - _SYS_STR("MP3"sv), - _SYS_STR("Data specification for original Metroid Prime 3 engine"sv), _SYS_STR(".pak"sv), 2, - [](hecl::Database::Project& project, hecl::Database::DataSpecTool) - -> std::unique_ptr {return std::make_unique(&SpecEntMP3, project, false);} -); +hecl::Database::DataSpecEntry SpecEntMP3( + _SYS_STR("MP3"sv), _SYS_STR("Data specification for original Metroid Prime 3 engine"sv), _SYS_STR(".pak"sv), 2, + [](hecl::Database::Project& project, hecl::Database::DataSpecTool) -> std::unique_ptr { + return std::make_unique(&SpecEntMP3, project, false); + }); -hecl::Database::DataSpecEntry SpecEntMP3PC = -{ - _SYS_STR("MP3-PC"sv), - _SYS_STR("Data specification for PC-optimized Metroid Prime 3 engine"sv), _SYS_STR(".upak"sv), 2, - [](hecl::Database::Project& project, hecl::Database::DataSpecTool tool) - -> std::unique_ptr - { - if (tool != hecl::Database::DataSpecTool::Extract) - return std::make_unique(&SpecEntMP3PC, project, true); - return nullptr; - } -}; +hecl::Database::DataSpecEntry SpecEntMP3PC = { + _SYS_STR("MP3-PC"sv), _SYS_STR("Data specification for PC-optimized Metroid Prime 3 engine"sv), _SYS_STR(".upak"sv), + 2, + [](hecl::Database::Project& project, + hecl::Database::DataSpecTool tool) -> std::unique_ptr { + if (tool != hecl::Database::DataSpecTool::Extract) + return std::make_unique(&SpecEntMP3PC, project, true); + return nullptr; + }}; -hecl::Database::DataSpecEntry SpecEntMP3ORIG = -{ - _SYS_STR("MP3-ORIG"sv), - _SYS_STR("Data specification for unmodified Metroid Prime 3 resources"sv), - {}, 2, {} -}; +hecl::Database::DataSpecEntry SpecEntMP3ORIG = { + _SYS_STR("MP3-ORIG"sv), _SYS_STR("Data specification for unmodified Metroid Prime 3 resources"sv), {}, 2, {}}; -} +} // namespace DataSpec diff --git a/Editor/Camera.hpp b/Editor/Camera.hpp index ea7736cba..0a7b78468 100644 --- a/Editor/Camera.hpp +++ b/Editor/Camera.hpp @@ -6,25 +6,20 @@ #include "zeus/CVector3f.hpp" #include "zeus/Math.hpp" -namespace urde -{ -class Camera -{ - zeus::CFrustum m_frustum; - zeus::CProjection m_projection; - zeus::CVector3f m_position; - zeus::CQuaternion m_orientation; +namespace urde { +class Camera { + zeus::CFrustum m_frustum; + zeus::CProjection m_projection; + zeus::CVector3f m_position; + zeus::CQuaternion m_orientation; + public: + void setPosition(const zeus::CVector3f& position) { m_position = position; } + void setOrientation(const zeus::CQuaternion& orientation) { m_orientation = orientation; } - void setPosition(const zeus::CVector3f& position) { m_position = position; } - void setOrientation(const zeus::CQuaternion& orientation) { m_orientation = orientation; } + const zeus::CMatrix4f& projectionMatrix() const { return m_projection.getCachedMatrix(); } + const zeus::CProjection& projection() const { return m_projection; } - const zeus::CMatrix4f& projectionMatrix() const { return m_projection.getCachedMatrix(); } - const zeus::CProjection& projection() const { return m_projection; } - - virtual void think() - {} + virtual void think() {} }; -} - - +} // namespace urde diff --git a/Editor/GameMode.cpp b/Editor/GameMode.cpp index a4954e68d..b216c4505 100644 --- a/Editor/GameMode.cpp +++ b/Editor/GameMode.cpp @@ -1,16 +1,11 @@ #include "GameMode.hpp" -namespace urde -{ -void GameMode::think() -{ - ViewerSpace::think(); +namespace urde { +void GameMode::think() { ViewerSpace::think(); } + +void GameMode::View::draw(boo::IGraphicsCommandQueue* gfxQ) { + if (m_gMode.m_main) + m_gMode.m_main->Draw(); } -void GameMode::View::draw(boo::IGraphicsCommandQueue *gfxQ) -{ - if (m_gMode.m_main) - m_gMode.m_main->Draw(); -} - -} +} // namespace urde diff --git a/Editor/GameMode.hpp b/Editor/GameMode.hpp index ff59a6186..a283df946 100644 --- a/Editor/GameMode.hpp +++ b/Editor/GameMode.hpp @@ -4,72 +4,52 @@ #include "ViewManager.hpp" #include "Runtime/IMain.hpp" -namespace urde -{ -class GameMode : public ViewerSpace -{ - std::shared_ptr m_main; +namespace urde { +class GameMode : public ViewerSpace { + std::shared_ptr m_main; - struct State : Space::State - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value showToolbar = true; - } m_state; + struct State : Space::State { + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value showToolbar = true; + } m_state; - const Space::State& spaceState() const { return m_state; } + const Space::State& spaceState() const { return m_state; } - struct View : specter::View - { - GameMode& m_gMode; + struct View : specter::View { + GameMode& m_gMode; - View(GameMode& gMode, specter::ViewResources& res) - : specter::View(res, gMode.m_vm.rootView()), m_gMode(gMode) {} + View(GameMode& gMode, specter::ViewResources& res) : specter::View(res, gMode.m_vm.rootView()), m_gMode(gMode) {} - void draw(boo::IGraphicsCommandQueue *gfxQ); - }; + void draw(boo::IGraphicsCommandQueue* gfxQ); + }; - std::unique_ptr m_view; + std::unique_ptr m_view; public: - GameMode(ViewManager& vm, Space* parent) - : ViewerSpace(vm, Class::GameMode, parent) - { - reloadState(); - } + GameMode(ViewManager& vm, Space* parent) : ViewerSpace(vm, Class::GameMode, parent) { reloadState(); } - GameMode(ViewManager& vm, Space* parent, const GameMode& other) - : GameMode(vm, parent) - { - m_state = other.m_state; - reloadState(); - } + GameMode(ViewManager& vm, Space* parent, const GameMode& other) : GameMode(vm, parent) { + m_state = other.m_state; + reloadState(); + } - GameMode(ViewManager& vm, Space* parent, ConfigReader& r) - : GameMode(vm, parent) - { - m_state.read(r); - reloadState(); - } + GameMode(ViewManager& vm, Space* parent, ConfigReader& r) : GameMode(vm, parent) { + m_state.read(r); + reloadState(); + } - void reloadState() - { - } + void reloadState() {} - virtual specter::View* buildContentView(specter::ViewResources &res) - { - m_view.reset(new View(*this, res)); - return m_view.get(); - } + virtual specter::View* buildContentView(specter::ViewResources& res) { + m_view.reset(new View(*this, res)); + return m_view.get(); + } - void think(); + void think(); - Space* copy(Space *parent) const - { - return new GameMode(m_vm, parent, *this); - } + Space* copy(Space* parent) const { return new GameMode(m_vm, parent, *this); } - bool usesToolbar() const { return m_state.showToolbar; } + bool usesToolbar() const { return m_state.showToolbar; } }; -} - +} // namespace urde diff --git a/Editor/InformationCenter.cpp b/Editor/InformationCenter.cpp index 441085f2a..1193a814a 100644 --- a/Editor/InformationCenter.cpp +++ b/Editor/InformationCenter.cpp @@ -1,5 +1,3 @@ #include "InformationCenter.hpp" -namespace urde -{ -} +namespace urde {} diff --git a/Editor/InformationCenter.hpp b/Editor/InformationCenter.hpp index 1f578a143..d11e568f0 100644 --- a/Editor/InformationCenter.hpp +++ b/Editor/InformationCenter.hpp @@ -3,67 +3,49 @@ #include "Space.hpp" #include "ViewManager.hpp" -namespace urde -{ -class InformationCenter : public ViewerSpace -{ - struct State : Space::State - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value showLog; - } m_state; +namespace urde { +class InformationCenter : public ViewerSpace { + struct State : Space::State { + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value showLog; + } m_state; - const Space::State& spaceState() const { return m_state; } + const Space::State& spaceState() const { return m_state; } - struct View : specter::View - { - InformationCenter& m_ic; - std::vector m_log; + struct View : specter::View { + InformationCenter& m_ic; + std::vector m_log; - View(InformationCenter& ic, specter::ViewResources& res) - : specter::View(res, ic.m_vm.rootView()), m_ic(ic) {} - }; + View(InformationCenter& ic, specter::ViewResources& res) : specter::View(res, ic.m_vm.rootView()), m_ic(ic) {} + }; - std::unique_ptr m_view; + std::unique_ptr m_view; public: - InformationCenter(ViewManager& vm, Space* parent) - : ViewerSpace(vm, Class::InformationCenter, parent) - { - reloadState(); - } + InformationCenter(ViewManager& vm, Space* parent) : ViewerSpace(vm, Class::InformationCenter, parent) { + reloadState(); + } - InformationCenter(ViewManager& vm, Space* parent, const InformationCenter& other) - : InformationCenter(vm, parent) - { - m_state = other.m_state; - reloadState(); - } + InformationCenter(ViewManager& vm, Space* parent, const InformationCenter& other) : InformationCenter(vm, parent) { + m_state = other.m_state; + reloadState(); + } - InformationCenter(ViewManager& vm, Space* parent, ConfigReader& r) - : InformationCenter(vm, parent) - { - m_state.read(r); - reloadState(); - } + InformationCenter(ViewManager& vm, Space* parent, ConfigReader& r) : InformationCenter(vm, parent) { + m_state.read(r); + reloadState(); + } - void reloadState() - { - } + void reloadState() {} - virtual specter::View* buildContentView(specter::ViewResources& res) - { - m_view.reset(new View(*this, res)); - return m_view.get(); - } + virtual specter::View* buildContentView(specter::ViewResources& res) { + m_view.reset(new View(*this, res)); + return m_view.get(); + } - Space* copy(Space *parent) const - { - return new InformationCenter(m_vm, parent, *this); - } + Space* copy(Space* parent) const { return new InformationCenter(m_vm, parent, *this); } - bool usesToolbar() const { return true; } + bool usesToolbar() const { return true; } }; -} - +} // namespace urde diff --git a/Editor/ModelViewer.cpp b/Editor/ModelViewer.cpp index fe3b43d15..bb29fc736 100644 --- a/Editor/ModelViewer.cpp +++ b/Editor/ModelViewer.cpp @@ -1,14 +1,10 @@ #include "ModelViewer.hpp" -namespace urde -{ +namespace urde { -void ModelViewer::View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) -{ - specter::View::resized(root, sub); - m_scissorRect = sub; +void ModelViewer::View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) { + specter::View::resized(root, sub); + m_scissorRect = sub; } - - -} +} // namespace urde diff --git a/Editor/ModelViewer.hpp b/Editor/ModelViewer.hpp index cbc82bbde..a34ba8c90 100644 --- a/Editor/ModelViewer.hpp +++ b/Editor/ModelViewer.hpp @@ -4,84 +4,62 @@ #include "ViewManager.hpp" #include "Camera.hpp" -namespace urde -{ -class ModelViewer : public ViewerSpace -{ - struct State : Space::State - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - enum class Mode - { - Solid, - Material, - Wireframe - }; +namespace urde { +class ModelViewer : public ViewerSpace { + struct State : Space::State { + AT_DECL_DNA_YAML + AT_DECL_DNAV + enum class Mode { Solid, Material, Wireframe }; - Value renderMode = Mode::Material; - Value cameraPosition; - Value cameraOrientation; + Value renderMode = Mode::Material; + Value cameraPosition; + Value cameraOrientation; - } m_state; + } m_state; - const Space::State& spaceState() const { return m_state; } - std::unique_ptr m_lineRenderer; - struct View : specter::View - { - ModelViewer& m_mv; - boo::SWindowRect m_scissorRect; + const Space::State& spaceState() const { return m_state; } + std::unique_ptr m_lineRenderer; + struct View : specter::View { + ModelViewer& m_mv; + boo::SWindowRect m_scissorRect; - View(ModelViewer& mv, specter::ViewResources& res) - : specter::View(res, mv.m_vm.rootView()), m_mv(mv) {} + View(ModelViewer& mv, specter::ViewResources& res) : specter::View(res, mv.m_vm.rootView()), m_mv(mv) {} - void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); - }; + void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); + }; - Camera m_camera; - std::unique_ptr m_view; + Camera m_camera; + std::unique_ptr m_view; public: - ModelViewer(ViewManager& vm, Space* parent) - : ViewerSpace(vm, Class::ModelViewer, parent) - { - reloadState(); - m_lineRenderer.reset(new urde::CLineRenderer(urde::CLineRenderer::EPrimitiveMode::LineStrip, 4, nullptr, true)); - } + ModelViewer(ViewManager& vm, Space* parent) : ViewerSpace(vm, Class::ModelViewer, parent) { + reloadState(); + m_lineRenderer.reset(new urde::CLineRenderer(urde::CLineRenderer::EPrimitiveMode::LineStrip, 4, nullptr, true)); + } - ModelViewer(ViewManager& vm, Space* parent, const ModelViewer& other) - : ModelViewer(vm, parent) - { - m_state = other.m_state; - reloadState(); - } + ModelViewer(ViewManager& vm, Space* parent, const ModelViewer& other) : ModelViewer(vm, parent) { + m_state = other.m_state; + reloadState(); + } - ModelViewer(ViewManager& vm, Space* parent, ConfigReader& r) - : ModelViewer(vm, parent) - { - m_state.read(r); - reloadState(); - } + ModelViewer(ViewManager& vm, Space* parent, ConfigReader& r) : ModelViewer(vm, parent) { + m_state.read(r); + reloadState(); + } - void reloadState() - { - m_camera.setPosition(m_state.cameraPosition); - m_camera.setOrientation(m_state.cameraOrientation); - } + void reloadState() { + m_camera.setPosition(m_state.cameraPosition); + m_camera.setOrientation(m_state.cameraOrientation); + } - Space* copy(Space *parent) const - { - return new ModelViewer(m_vm, parent, *this); - } + Space* copy(Space* parent) const { return new ModelViewer(m_vm, parent, *this); } - virtual specter::View* buildContentView(specter::ViewResources& res) - { - m_view.reset(new View(*this, res)); - return m_view.get(); - } + virtual specter::View* buildContentView(specter::ViewResources& res) { + m_view.reset(new View(*this, res)); + return m_view.get(); + } - bool usesToolbar() const { return true; } + bool usesToolbar() const { return true; } }; -} - +} // namespace urde diff --git a/Editor/ParticleEditor.cpp b/Editor/ParticleEditor.cpp index 70a413753..06e8b04fe 100644 --- a/Editor/ParticleEditor.cpp +++ b/Editor/ParticleEditor.cpp @@ -1,6 +1,3 @@ #include "ParticleEditor.hpp" -namespace urde -{ - -} +namespace urde {} diff --git a/Editor/ParticleEditor.hpp b/Editor/ParticleEditor.hpp index ba229c49c..540fe1731 100644 --- a/Editor/ParticleEditor.hpp +++ b/Editor/ParticleEditor.hpp @@ -2,45 +2,32 @@ #include "Space.hpp" -namespace urde -{ +namespace urde { -class EffectEditor : public EditorSpace -{ - struct State : Space::State - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> path; - } m_state; - const Space::State& spaceState() const {return m_state;} +class EffectEditor : public EditorSpace { + struct State : Space::State { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> path; + } m_state; + const Space::State& spaceState() const { return m_state; } - struct View : specter::View - { - View(specter::ViewResources& res, specter::View& parent) - : specter::View(res, parent) {} - }; + struct View : specter::View { + View(specter::ViewResources& res, specter::View& parent) : specter::View(res, parent) {} + }; - specter::View* buildContentView(specter::ViewResources& res) - { - return nullptr; - } + specter::View* buildContentView(specter::ViewResources& res) { return nullptr; } public: - EffectEditor(ViewManager& vm, Space* parent) - : EditorSpace(vm, Class::EffectEditor, parent) {} - EffectEditor(ViewManager& vm, Space* parent, ConfigReader& r) - : EffectEditor(vm, parent) {m_state.read(r);} - EffectEditor(ViewManager& vm, Space* parent, const EffectEditor& other) - : EffectEditor(vm, parent) {m_state = other.m_state;} + EffectEditor(ViewManager& vm, Space* parent) : EditorSpace(vm, Class::EffectEditor, parent) {} + EffectEditor(ViewManager& vm, Space* parent, ConfigReader& r) : EffectEditor(vm, parent) { m_state.read(r); } + EffectEditor(ViewManager& vm, Space* parent, const EffectEditor& other) : EffectEditor(vm, parent) { + m_state = other.m_state; + } - Space* copy(Space* parent) const - { - return new EffectEditor(m_vm, parent, *this); - } + Space* copy(Space* parent) const { return new EffectEditor(m_vm, parent, *this); } - bool usesToolbar() const { return true; } + bool usesToolbar() const { return true; } }; -} - +} // namespace urde diff --git a/Editor/ProjectManager.cpp b/Editor/ProjectManager.cpp index 8db3441fa..9b1cdd680 100644 --- a/Editor/ProjectManager.cpp +++ b/Editor/ProjectManager.cpp @@ -3,224 +3,196 @@ #include "../DataSpecRegistry.hpp" #include "hecl/Blender/Connection.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("URDE::ProjectManager"); ProjectManager* ProjectManager::g_SharedManager = nullptr; -CToken ProjectResourcePool::GetObj(std::string_view name) -{ - CToken ret = CSimplePool::GetObj(name); - if (ret) - return ret; +CToken ProjectResourcePool::GetObj(std::string_view name) { + CToken ret = CSimplePool::GetObj(name); + if (ret) + return ret; - hecl::ProjectPath path(*m_parent.project(), name); - SObjectTag tag = static_cast(x18_factory). - TagFromPath(path, hecl::blender::SharedBlenderToken); - if (tag) - return CSimplePool::GetObj(tag); + hecl::ProjectPath path(*m_parent.project(), name); + SObjectTag tag = + static_cast(x18_factory).TagFromPath(path, hecl::blender::SharedBlenderToken); + if (tag) + return CSimplePool::GetObj(tag); - return {}; + return {}; } -CToken ProjectResourcePool::GetObj(std::string_view name, const CVParamTransfer& pvxfer) -{ - CToken ret = CSimplePool::GetObj(name, pvxfer); - if (ret) - return ret; +CToken ProjectResourcePool::GetObj(std::string_view name, const CVParamTransfer& pvxfer) { + CToken ret = CSimplePool::GetObj(name, pvxfer); + if (ret) + return ret; - hecl::ProjectPath path(*m_parent.project(), name); - SObjectTag tag = static_cast(x18_factory). - TagFromPath(path, hecl::blender::SharedBlenderToken); - if (tag) - return CSimplePool::GetObj(tag, pvxfer); + hecl::ProjectPath path(*m_parent.project(), name); + SObjectTag tag = + static_cast(x18_factory).TagFromPath(path, hecl::blender::SharedBlenderToken); + if (tag) + return CSimplePool::GetObj(tag, pvxfer); - return {}; + return {}; } bool ProjectManager::m_registeredSpecs = false; -ProjectManager::ProjectManager(ViewManager &vm) -: m_vm(vm), m_clientProc(nullptr), - m_factoryMP1(m_clientProc), m_objStore(m_factoryMP1, *this) -{ - if (!m_registeredSpecs) - { - HECLRegisterDataSpecs(); - m_registeredSpecs = true; - } - g_SharedManager = this; +ProjectManager::ProjectManager(ViewManager& vm) +: m_vm(vm), m_clientProc(nullptr), m_factoryMP1(m_clientProc), m_objStore(m_factoryMP1, *this) { + if (!m_registeredSpecs) { + HECLRegisterDataSpecs(); + m_registeredSpecs = true; + } + g_SharedManager = this; } -bool ProjectManager::newProject(hecl::SystemStringView path) -{ - hecl::ProjectRootPath projPath = hecl::SearchForProject(path); - if (projPath) - { - Log.report(logvisor::Warning, _SYS_STR("project already exists at '%s'"), path.data()); - return false; - } +bool ProjectManager::newProject(hecl::SystemStringView path) { + hecl::ProjectRootPath projPath = hecl::SearchForProject(path); + if (projPath) { + Log.report(logvisor::Warning, _SYS_STR("project already exists at '%s'"), path.data()); + return false; + } - hecl::MakeDir(path.data()); - m_proj.reset(new hecl::Database::Project(path)); - if (!*m_proj) - { - m_proj.reset(); - return false; - } + hecl::MakeDir(path.data()); + m_proj.reset(new hecl::Database::Project(path)); + if (!*m_proj) { + m_proj.reset(); + return false; + } - m_vm.ProjectChanged(*m_proj); + m_vm.ProjectChanged(*m_proj); + m_vm.SetupEditorView(); + saveProject(); + + hecl::SystemString windowTitle(m_proj->getProjectRootPath().getLastComponent()); + windowTitle += _SYS_STR(" - URDE [") + hecl::SystemString(m_vm.platformName()) + _SYS_STR("]"); + m_vm.m_mainWindow->setTitle(windowTitle.c_str()); + m_vm.DismissSplash(); + m_vm.FadeInEditors(); + + return true; +} + +bool ProjectManager::openProject(hecl::SystemStringView path) { + hecl::SystemString subPath; + hecl::ProjectRootPath projPath = hecl::SearchForProject(path, subPath); + if (!projPath) { + Log.report(logvisor::Warning, _SYS_STR("project doesn't exist at '%s'"), path.data()); + return false; + } + + m_proj.reset(new hecl::Database::Project(projPath)); + if (!*m_proj) { + m_proj.reset(); + return false; + } + + hecl::ProjectPath urdeSpacesPath(*m_proj, _SYS_STR(".hecl/urde_spaces.yaml")); + athena::io::FileReader reader(urdeSpacesPath.getAbsolutePath()); + + bool needsSave = false; + athena::io::YAMLDocReader r; + if (!reader.isOpen()) { + needsSave = true; + goto makeProj; + } + + yaml_parser_set_input(r.getParser(), (yaml_read_handler_t*)athena::io::YAMLAthenaReader, &reader); + if (!r.ValidateClassType("UrdeSpacesState")) { + needsSave = true; + goto makeProj; + } + + r.reset(); + reader.seek(0, athena::Begin); + if (!r.parse(&reader)) { + needsSave = true; + goto makeProj; + } + +makeProj: + m_vm.ProjectChanged(*m_proj); + + if (!needsSave) + m_vm.SetupEditorView(r); + else m_vm.SetupEditorView(); + + bool doRun = hecl::StringUtils::BeginsWith(subPath, _SYS_STR("out")); + if (doRun) { + m_mainMP1.emplace(nullptr, nullptr, m_vm.m_mainBooFactory, m_vm.m_mainCommandQueue, m_vm.m_renderTex); + m_vm.InitMP1(*m_mainMP1); + } + + if (needsSave) saveProject(); + { hecl::SystemString windowTitle(m_proj->getProjectRootPath().getLastComponent()); windowTitle += _SYS_STR(" - URDE [") + hecl::SystemString(m_vm.platformName()) + _SYS_STR("]"); m_vm.m_mainWindow->setTitle(windowTitle.c_str()); - m_vm.DismissSplash(); - m_vm.FadeInEditors(); - - return true; + } + m_vm.DismissSplash(); + m_vm.FadeInEditors(); + m_vm.pushRecentProject(m_proj->getProjectRootPath().getAbsolutePath()); + return true; } -bool ProjectManager::openProject(hecl::SystemStringView path) -{ - hecl::SystemString subPath; - hecl::ProjectRootPath projPath = hecl::SearchForProject(path, subPath); - if (!projPath) - { - Log.report(logvisor::Warning, _SYS_STR("project doesn't exist at '%s'"), path.data()); - return false; - } +bool ProjectManager::extractGame(hecl::SystemStringView path) { return false; } - m_proj.reset(new hecl::Database::Project(projPath)); - if (!*m_proj) - { - m_proj.reset(); - return false; - } - - hecl::ProjectPath urdeSpacesPath(*m_proj, _SYS_STR(".hecl/urde_spaces.yaml")); - athena::io::FileReader reader(urdeSpacesPath.getAbsolutePath()); - - bool needsSave = false; - athena::io::YAMLDocReader r; - if (!reader.isOpen()) - { - needsSave = true; - goto makeProj; - } - - yaml_parser_set_input(r.getParser(), (yaml_read_handler_t*)athena::io::YAMLAthenaReader, &reader); - if (!r.ValidateClassType("UrdeSpacesState")) - { - needsSave = true; - goto makeProj; - } - - r.reset(); - reader.seek(0, athena::Begin); - if (!r.parse(&reader)) - { - needsSave = true; - goto makeProj; - } - -makeProj: - m_vm.ProjectChanged(*m_proj); - - if (!needsSave) - m_vm.SetupEditorView(r); - else - m_vm.SetupEditorView(); - - bool doRun = hecl::StringUtils::BeginsWith(subPath, _SYS_STR("out")); - if (doRun) - { - m_mainMP1.emplace(nullptr, nullptr, m_vm.m_mainBooFactory, - m_vm.m_mainCommandQueue, m_vm.m_renderTex); - m_vm.InitMP1(*m_mainMP1); - } - - if (needsSave) - saveProject(); - - { - hecl::SystemString windowTitle(m_proj->getProjectRootPath().getLastComponent()); - windowTitle += _SYS_STR(" - URDE [") + hecl::SystemString(m_vm.platformName()) + _SYS_STR("]"); - m_vm.m_mainWindow->setTitle(windowTitle.c_str()); - } - m_vm.DismissSplash(); - m_vm.FadeInEditors(); - m_vm.pushRecentProject(m_proj->getProjectRootPath().getAbsolutePath()); - return true; -} - -bool ProjectManager::extractGame(hecl::SystemStringView path) -{ +bool ProjectManager::saveProject() { + if (!m_proj) return false; + + hecl::ProjectPath oldSpacesPath(*m_proj, _SYS_STR(".hecl/~urde_spaces.yaml")); + athena::io::FileWriter writer(oldSpacesPath.getAbsolutePath()); + if (!writer.isOpen()) + return false; + + athena::io::YAMLDocWriter w("UrdeSpacesState"); + m_vm.SaveEditorView(w); + if (!w.finish(&writer)) + return false; + + hecl::ProjectPath newSpacesPath(*m_proj, _SYS_STR(".hecl/urde_spaces.yaml")); + + hecl::Unlink(newSpacesPath.getAbsolutePath().data()); + hecl::Rename(oldSpacesPath.getAbsolutePath().data(), newSpacesPath.getAbsolutePath().data()); + + m_vm.pushRecentProject(m_proj->getProjectRootPath().getAbsolutePath()); + + return true; } -bool ProjectManager::saveProject() -{ - if (!m_proj) - return false; +void ProjectManager::mainUpdate() { + if (m_precooking) { + if (!m_factoryMP1.IsBusy()) + m_precooking = false; + else + return; + } - hecl::ProjectPath oldSpacesPath(*m_proj, _SYS_STR(".hecl/~urde_spaces.yaml")); - athena::io::FileWriter writer(oldSpacesPath.getAbsolutePath()); - if (!writer.isOpen()) - return false; - - athena::io::YAMLDocWriter w("UrdeSpacesState"); - m_vm.SaveEditorView(w); - if (!w.finish(&writer)) - return false; - - hecl::ProjectPath newSpacesPath(*m_proj, _SYS_STR(".hecl/urde_spaces.yaml")); - - hecl::Unlink(newSpacesPath.getAbsolutePath().data()); - hecl::Rename(oldSpacesPath.getAbsolutePath().data(), - newSpacesPath.getAbsolutePath().data()); - - m_vm.pushRecentProject(m_proj->getProjectRootPath().getAbsolutePath()); - - return true; -} - -void ProjectManager::mainUpdate() -{ - if (m_precooking) - { - if (!m_factoryMP1.IsBusy()) - m_precooking = false; - else - return; - } - - if (m_mainMP1) - { - if (m_mainMP1->Proc()) - { - m_mainMP1->Shutdown(); - m_mainMP1 = std::experimental::nullopt; - } + if (m_mainMP1) { + if (m_mainMP1->Proc()) { + m_mainMP1->Shutdown(); + m_mainMP1 = std::experimental::nullopt; } + } } -void ProjectManager::mainDraw() -{ - if (m_precooking) - return; +void ProjectManager::mainDraw() { + if (m_precooking) + return; - if (m_mainMP1) - m_mainMP1->Draw(); + if (m_mainMP1) + m_mainMP1->Draw(); } -void ProjectManager::shutdown() -{ - if (m_mainMP1) - m_mainMP1->Shutdown(); - m_clientProc.shutdown(); - m_factoryMP1.Shutdown(); - hecl::blender::Connection::Shutdown(); +void ProjectManager::shutdown() { + if (m_mainMP1) + m_mainMP1->Shutdown(); + m_clientProc.shutdown(); + m_factoryMP1.Shutdown(); + hecl::blender::Connection::Shutdown(); } -} +} // namespace urde diff --git a/Editor/ProjectManager.hpp b/Editor/ProjectManager.hpp index 268e90f6d..18ae50f28 100644 --- a/Editor/ProjectManager.hpp +++ b/Editor/ProjectManager.hpp @@ -7,55 +7,52 @@ #include "hecl/Runtime.hpp" #include "MP1/MP1.hpp" -namespace urde -{ +namespace urde { class ViewManager; using ConfigReader = athena::io::YAMLDocReader; using ConfigWriter = athena::io::YAMLDocWriter; -class ProjectResourcePool : public CSimplePool -{ - class ProjectManager& m_parent; -public: - ProjectResourcePool(IFactory& factory, ProjectManager& parent) - : CSimplePool(factory), m_parent(parent) {} - CToken GetObj(std::string_view); - CToken GetObj(std::string_view, const CVParamTransfer&); -}; - -class ProjectManager -{ - ViewManager& m_vm; - std::unique_ptr m_proj; - static bool m_registeredSpecs; - hecl::ClientProcess m_clientProc; - ProjectResourceFactoryMP1 m_factoryMP1; - ProjectResourcePool m_objStore; - std::experimental::optional m_mainMP1; - bool m_precooking = false; +class ProjectResourcePool : public CSimplePool { + class ProjectManager& m_parent; public: - static ProjectManager* g_SharedManager; - ProjectManager(ViewManager& vm); - operator bool() const {return m_proj.operator bool();} - - hecl::Database::Project* project() {return m_proj.get();} - ProjectResourcePool& objectStore() {return m_objStore;} - ProjectResourceFactoryMP1& resourceFactoryMP1() {return m_factoryMP1;} - MP1::CMain* gameMain() {return m_mainMP1 ? &*m_mainMP1 : nullptr;} - SObjectTag TagFromPath(hecl::SystemStringView path) const - { return m_factoryMP1.ProjectResourceFactoryBase::TagFromPath(path); } - - bool newProject(hecl::SystemStringView path); - bool openProject(hecl::SystemStringView path); - bool extractGame(hecl::SystemStringView path); - bool saveProject(); - - void mainUpdate(); - void mainDraw(); - void shutdown(); + ProjectResourcePool(IFactory& factory, ProjectManager& parent) : CSimplePool(factory), m_parent(parent) {} + CToken GetObj(std::string_view); + CToken GetObj(std::string_view, const CVParamTransfer&); }; -} +class ProjectManager { + ViewManager& m_vm; + std::unique_ptr m_proj; + static bool m_registeredSpecs; + hecl::ClientProcess m_clientProc; + ProjectResourceFactoryMP1 m_factoryMP1; + ProjectResourcePool m_objStore; + std::experimental::optional m_mainMP1; + bool m_precooking = false; +public: + static ProjectManager* g_SharedManager; + ProjectManager(ViewManager& vm); + operator bool() const { return m_proj.operator bool(); } + + hecl::Database::Project* project() { return m_proj.get(); } + ProjectResourcePool& objectStore() { return m_objStore; } + ProjectResourceFactoryMP1& resourceFactoryMP1() { return m_factoryMP1; } + MP1::CMain* gameMain() { return m_mainMP1 ? &*m_mainMP1 : nullptr; } + SObjectTag TagFromPath(hecl::SystemStringView path) const { + return m_factoryMP1.ProjectResourceFactoryBase::TagFromPath(path); + } + + bool newProject(hecl::SystemStringView path); + bool openProject(hecl::SystemStringView path); + bool extractGame(hecl::SystemStringView path); + bool saveProject(); + + void mainUpdate(); + void mainDraw(); + void shutdown(); +}; + +} // namespace urde diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index 530e9d495..f8bb5635d 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -4,575 +4,465 @@ #undef min #undef max -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::ProjectResourceFactoryBase"); -void ProjectResourceFactoryBase::BeginBackgroundIndex - (hecl::Database::Project& proj, - const hecl::Database::DataSpecEntry& origSpec, - const hecl::Database::DataSpecEntry& pcSpec) -{ - CancelBackgroundIndex(); - m_proj = &proj; - m_origSpec = &origSpec; - m_pcSpec = &pcSpec; - m_cookSpec = pcSpec.m_factory(proj, hecl::Database::DataSpecTool::Cook); - return static_cast(*m_cookSpec).beginBackgroundIndex(); +void ProjectResourceFactoryBase::BeginBackgroundIndex(hecl::Database::Project& proj, + const hecl::Database::DataSpecEntry& origSpec, + const hecl::Database::DataSpecEntry& pcSpec) { + CancelBackgroundIndex(); + m_proj = &proj; + m_origSpec = &origSpec; + m_pcSpec = &pcSpec; + m_cookSpec = pcSpec.m_factory(proj, hecl::Database::DataSpecTool::Cook); + return static_cast(*m_cookSpec).beginBackgroundIndex(); } -bool ProjectResourceFactoryBase::SyncCook(const hecl::ProjectPath& working) -{ - Log.report(logvisor::Warning, _SYS_STR("sync-cooking %s"), working.getRelativePath().data()); - return m_clientProc.syncCook(working, m_cookSpec.get(), hecl::blender::SharedBlenderToken, - false, false); +bool ProjectResourceFactoryBase::SyncCook(const hecl::ProjectPath& working) { + Log.report(logvisor::Warning, _SYS_STR("sync-cooking %s"), working.getRelativePath().data()); + return m_clientProc.syncCook(working, m_cookSpec.get(), hecl::blender::SharedBlenderToken, false, false); } -CFactoryFnReturn ProjectResourceFactoryBase::BuildSync(const SObjectTag& tag, - const hecl::ProjectPath& path, - const CVParamTransfer& paramXfer, - CObjectReference* selfRef) -{ - /* Ensure cooked rep is on the filesystem */ - std::experimental::optional fr; - if (!PrepForReadSync(tag, path, fr)) - return {}; +CFactoryFnReturn ProjectResourceFactoryBase::BuildSync(const SObjectTag& tag, const hecl::ProjectPath& path, + const CVParamTransfer& paramXfer, CObjectReference* selfRef) { + /* Ensure cooked rep is on the filesystem */ + std::experimental::optional fr; + if (!PrepForReadSync(tag, path, fr)) + return {}; - /* All good, build resource */ - if (m_factoryMgr.CanMakeMemory(tag)) - { - u32 length = fr->length(); - std::unique_ptr memBuf = fr->readUBytes(length); - CFactoryFnReturn ret = - m_factoryMgr.MakeObjectFromMemory(tag, std::move(memBuf), length, false, paramXfer, selfRef); - Log.report(logvisor::Info, "sync-built %.4s %08X", - tag.type.getChars(), u32(tag.id.Value())); - return ret; - } - - CFactoryFnReturn ret = m_factoryMgr.MakeObject(tag, *fr, paramXfer, selfRef); - Log.report(logvisor::Info, "sync-built %.4s %08X", - tag.type.getChars(), u32(tag.id.Value())); + /* All good, build resource */ + if (m_factoryMgr.CanMakeMemory(tag)) { + u32 length = fr->length(); + std::unique_ptr memBuf = fr->readUBytes(length); + CFactoryFnReturn ret = m_factoryMgr.MakeObjectFromMemory(tag, std::move(memBuf), length, false, paramXfer, selfRef); + Log.report(logvisor::Info, "sync-built %.4s %08X", tag.type.getChars(), u32(tag.id.Value())); return ret; + } + + CFactoryFnReturn ret = m_factoryMgr.MakeObject(tag, *fr, paramXfer, selfRef); + Log.report(logvisor::Info, "sync-built %.4s %08X", tag.type.getChars(), u32(tag.id.Value())); + return ret; } -void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& tag, - const hecl::ProjectPath& path) -{ - if (!m_workingPath) - { - m_workingPath = path; +void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& tag, const hecl::ProjectPath& path) { + if (!m_workingPath) { + m_workingPath = path; - /* Ensure requested resource is on the filesystem */ - if (!path.isFileOrGlob()) - { - Log.report(logvisor::Error, _SYS_STR("unable to find resource path '%s'"), - path.getRelativePath().data()); - m_failed = true; - return; - } - - /* Cached resolve (try PC first, then original) */ - m_cookedPath = path.getCookedPath(*m_parent.m_pcSpec); - if (!m_cookedPath.isFile()) - m_cookedPath = path.getCookedPath(*m_parent.m_origSpec); - if (!m_cookedPath.isFile() || - m_cookedPath.getModtime() < path.getModtime()) - { - /* Last chance type validation */ - urde::SObjectTag verifyTag = m_parent.TagFromPath(path, hecl::blender::SharedBlenderToken); - if (verifyTag.type != tag.type) - { - Log.report(logvisor::Error, _SYS_STR("%s: expected type '%.4s', found '%.4s'"), - path.getRelativePath().data(), - tag.type.getChars(), verifyTag.type.getChars()); - m_failed = true; - return; - } - - /* Get cooked representation path */ - m_cookedPath = m_parent.GetCookedPath(path, true); - - /* Perform mod-time comparison */ - if (!m_cookedPath.isFile() || - m_cookedPath.getModtime() < path.getModtime()) - { - /* Start a background cook here */ - m_cookTransaction = m_parent.m_clientProc. - addCookTransaction(path, false, false, m_parent.m_cookSpec.get()); - return; - } - } - - CookComplete(); + /* Ensure requested resource is on the filesystem */ + if (!path.isFileOrGlob()) { + Log.report(logvisor::Error, _SYS_STR("unable to find resource path '%s'"), path.getRelativePath().data()); + m_failed = true; + return; } -} -void ProjectResourceFactoryBase::AsyncTask::CookComplete() -{ - /* Ensure cooked rep is on the filesystem */ - athena::io::FileReader fr(m_cookedPath.getAbsolutePath(), 32 * 1024, false); - if (fr.hasError()) - { - Log.report(logvisor::Error, _SYS_STR("unable to open cooked resource path '%s'"), - m_cookedPath.getAbsolutePath().data()); + /* Cached resolve (try PC first, then original) */ + m_cookedPath = path.getCookedPath(*m_parent.m_pcSpec); + if (!m_cookedPath.isFile()) + m_cookedPath = path.getCookedPath(*m_parent.m_origSpec); + if (!m_cookedPath.isFile() || m_cookedPath.getModtime() < path.getModtime()) { + /* Last chance type validation */ + urde::SObjectTag verifyTag = m_parent.TagFromPath(path, hecl::blender::SharedBlenderToken); + if (verifyTag.type != tag.type) { + Log.report(logvisor::Error, _SYS_STR("%s: expected type '%.4s', found '%.4s'"), path.getRelativePath().data(), + tag.type.getChars(), verifyTag.type.getChars()); m_failed = true; return; - } + } - /* Ready for buffer transaction at this point */ - u32 availSz = std::max(0, s32(fr.length()) - s32(x14_resOffset)); - x14_resSize = std::min(x14_resSize, availSz); - if (xc_targetDataRawPtr) - { - m_bufTransaction = m_parent.m_clientProc.addBufferTransaction(m_cookedPath, - xc_targetDataRawPtr, - x14_resSize, x14_resOffset); - } - else if (xc_targetDataPtr || xc_targetObjPtr) - { - x10_loadBuffer.reset(new u8[x14_resSize]); - m_bufTransaction = m_parent.m_clientProc.addBufferTransaction(m_cookedPath, - x10_loadBuffer.get(), - x14_resSize, x14_resOffset); - } - else - { - /* Skip buffer transaction if no target pointers set */ - m_complete = true; - } -} + /* Get cooked representation path */ + m_cookedPath = m_parent.GetCookedPath(path, true); -bool ProjectResourceFactoryBase::AsyncTask::AsyncPump() -{ - if (m_failed || m_complete) - return true; - - if (m_bufTransaction) - { - if (m_bufTransaction->m_complete) - { - m_complete = true; - return true; - } - } - else if (m_cookTransaction) - { - if (m_cookTransaction->m_complete) - CookComplete(); - } - - return m_failed; -} - -void ProjectResourceFactoryBase::AsyncTask::WaitUntilComplete() -{ - using ItType = std::unordered_map>::iterator>::iterator; - ItType search = m_parent.m_asyncLoadMap.find(x0_tag); - if (search == m_parent.m_asyncLoadMap.end()) + /* Perform mod-time comparison */ + if (!m_cookedPath.isFile() || m_cookedPath.getModtime() < path.getModtime()) { + /* Start a background cook here */ + m_cookTransaction = m_parent.m_clientProc.addCookTransaction(path, false, false, m_parent.m_cookSpec.get()); return; - for (ItType tmp = search ; !m_parent.AsyncPumpTask(tmp) ; tmp = search) - {std::this_thread::sleep_for(std::chrono::milliseconds(2));} + } + } + + CookComplete(); + } +} + +void ProjectResourceFactoryBase::AsyncTask::CookComplete() { + /* Ensure cooked rep is on the filesystem */ + athena::io::FileReader fr(m_cookedPath.getAbsolutePath(), 32 * 1024, false); + if (fr.hasError()) { + Log.report(logvisor::Error, _SYS_STR("unable to open cooked resource path '%s'"), + m_cookedPath.getAbsolutePath().data()); + m_failed = true; + return; + } + + /* Ready for buffer transaction at this point */ + u32 availSz = std::max(0, s32(fr.length()) - s32(x14_resOffset)); + x14_resSize = std::min(x14_resSize, availSz); + if (xc_targetDataRawPtr) { + m_bufTransaction = + m_parent.m_clientProc.addBufferTransaction(m_cookedPath, xc_targetDataRawPtr, x14_resSize, x14_resOffset); + } else if (xc_targetDataPtr || xc_targetObjPtr) { + x10_loadBuffer.reset(new u8[x14_resSize]); + m_bufTransaction = + m_parent.m_clientProc.addBufferTransaction(m_cookedPath, x10_loadBuffer.get(), x14_resSize, x14_resOffset); + } else { + /* Skip buffer transaction if no target pointers set */ + m_complete = true; + } +} + +bool ProjectResourceFactoryBase::AsyncTask::AsyncPump() { + if (m_failed || m_complete) + return true; + + if (m_bufTransaction) { + if (m_bufTransaction->m_complete) { + m_complete = true; + return true; + } + } else if (m_cookTransaction) { + if (m_cookTransaction->m_complete) + CookComplete(); + } + + return m_failed; +} + +void ProjectResourceFactoryBase::AsyncTask::WaitUntilComplete() { + using ItType = std::unordered_map>::iterator>::iterator; + ItType search = m_parent.m_asyncLoadMap.find(x0_tag); + if (search == m_parent.m_asyncLoadMap.end()) + return; + for (ItType tmp = search; !m_parent.AsyncPumpTask(tmp); tmp = search) { + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + } } using AsyncTask = ProjectResourceFactoryBase::AsyncTask; -std::shared_ptr -ProjectResourceFactoryBase::_AddTask(const std::shared_ptr& ptr) -{ - m_asyncLoadMap.insert({ptr->x0_tag, m_asyncLoadList.insert(m_asyncLoadList.end(), ptr)}); - return ptr; +std::shared_ptr ProjectResourceFactoryBase::_AddTask(const std::shared_ptr& ptr) { + m_asyncLoadMap.insert({ptr->x0_tag, m_asyncLoadList.insert(m_asyncLoadList.end(), ptr)}); + return ptr; } std::list>::iterator -ProjectResourceFactoryBase::_RemoveTask(std::list>::iterator it) -{ - m_asyncLoadMap.erase((*it)->x0_tag); - return m_asyncLoadList.erase(it); +ProjectResourceFactoryBase::_RemoveTask(std::list>::iterator it) { + m_asyncLoadMap.erase((*it)->x0_tag); + return m_asyncLoadList.erase(it); } std::unordered_map>::iterator>::iterator -ProjectResourceFactoryBase::_RemoveTask(std::unordered_map>::iterator>::iterator it) -{ - if (it != m_asyncLoadMap.end()) - { - m_asyncLoadList.erase(it->second); - return m_asyncLoadMap.erase(it); - } - return it; +ProjectResourceFactoryBase::_RemoveTask( + std::unordered_map>::iterator>::iterator it) { + if (it != m_asyncLoadMap.end()) { + m_asyncLoadList.erase(it->second); + return m_asyncLoadMap.erase(it); + } + return it; }; std::unordered_map>::iterator>::iterator -ProjectResourceFactoryBase::_RemoveTask(const SObjectTag& tag) -{ - return _RemoveTask(m_asyncLoadMap.find(tag)); +ProjectResourceFactoryBase::_RemoveTask(const SObjectTag& tag) { + return _RemoveTask(m_asyncLoadMap.find(tag)); }; -bool -ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, - const hecl::ProjectPath& path, - std::experimental::optional& fr) -{ - /* Ensure requested resource is on the filesystem */ - if (!path.isFileOrGlob()) - { - Log.report(logvisor::Error, _SYS_STR("unable to find resource path '%s'"), - path.getAbsolutePath().data()); +bool ProjectResourceFactoryBase::PrepForReadSync(const SObjectTag& tag, const hecl::ProjectPath& path, + std::experimental::optional& fr) { + /* Ensure requested resource is on the filesystem */ + if (!path.isFileOrGlob()) { + Log.report(logvisor::Error, _SYS_STR("unable to find resource path '%s'"), path.getAbsolutePath().data()); + return false; + } + + /* Cached resolve (try PC first, then original) */ + hecl::ProjectPath cooked = path.getCookedPath(*m_pcSpec); + if (!cooked.isFile()) + cooked = path.getCookedPath(*m_origSpec); + if (!cooked.isFile() || cooked.getModtime() < path.getModtime()) { + /* Last chance type validation */ + urde::SObjectTag verifyTag = TagFromPath(path, hecl::blender::SharedBlenderToken); + if (verifyTag.type != tag.type) { + Log.report(logvisor::Error, _SYS_STR("%s: expected type '%.4s', found '%.4s'"), path.getRelativePath().data(), + tag.type.getChars(), verifyTag.type.getChars()); + return false; + } + + /* Get cooked representation path */ + cooked = GetCookedPath(path, true); + + /* Perform mod-time comparison */ + if (!cooked.isFile() || cooked.getModtime() < path.getModtime()) { + /* Do a blocking cook here */ + if (!SyncCook(path)) { + Log.report(logvisor::Error, _SYS_STR("unable to cook resource path '%s'"), path.getAbsolutePath().data()); return false; + } } + } - /* Cached resolve (try PC first, then original) */ - hecl::ProjectPath cooked = path.getCookedPath(*m_pcSpec); - if (!cooked.isFile()) - cooked = path.getCookedPath(*m_origSpec); - if (!cooked.isFile() || - cooked.getModtime() < path.getModtime()) - { - /* Last chance type validation */ - urde::SObjectTag verifyTag = TagFromPath(path, hecl::blender::SharedBlenderToken); - if (verifyTag.type != tag.type) - { - Log.report(logvisor::Error, _SYS_STR("%s: expected type '%.4s', found '%.4s'"), - path.getRelativePath().data(), - tag.type.getChars(), verifyTag.type.getChars()); - return false; - } + /* Ensure cooked rep is on the filesystem */ + fr.emplace(cooked.getAbsolutePath(), 32 * 1024, false); + if (fr->hasError()) { + Log.report(logvisor::Error, _SYS_STR("unable to open cooked resource path '%s'"), cooked.getAbsolutePath().data()); + return false; + } - /* Get cooked representation path */ - cooked = GetCookedPath(path, true); - - /* Perform mod-time comparison */ - if (!cooked.isFile() || - cooked.getModtime() < path.getModtime()) - { - /* Do a blocking cook here */ - if (!SyncCook(path)) - { - Log.report(logvisor::Error, _SYS_STR("unable to cook resource path '%s'"), - path.getAbsolutePath().data()); - return false; - } - } - } - - /* Ensure cooked rep is on the filesystem */ - fr.emplace(cooked.getAbsolutePath(), 32 * 1024, false); - if (fr->hasError()) - { - Log.report(logvisor::Error, _SYS_STR("unable to open cooked resource path '%s'"), - cooked.getAbsolutePath().data()); - return false; - } - - return true; + return true; } std::unique_ptr ProjectResourceFactoryBase::Build(const urde::SObjectTag& tag, const urde::CVParamTransfer& paramXfer, - CObjectReference* selfRef) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id on type '%.4s'", tag.type.getChars()); + CObjectReference* selfRef) { + if (!tag.id.IsValid()) + Log.report(logvisor::Fatal, "attempted to access null id on type '%.4s'", tag.type.getChars()); - const hecl::ProjectPath* resPath = nullptr; - if (!WaitForTagReady(tag, resPath)) - return {}; - auto asyncSearch = m_asyncLoadMap.find(tag); - if (asyncSearch != m_asyncLoadMap.end()) - { - /* Async spinloop */ - AsyncTask& task = **asyncSearch->second; - task.EnsurePath(task.x0_tag, *resPath); + const hecl::ProjectPath* resPath = nullptr; + if (!WaitForTagReady(tag, resPath)) + return {}; + auto asyncSearch = m_asyncLoadMap.find(tag); + if (asyncSearch != m_asyncLoadMap.end()) { + /* Async spinloop */ + AsyncTask& task = **asyncSearch->second; + task.EnsurePath(task.x0_tag, *resPath); - /* Pump load pipeline (cooking if needed) */ - while (!task.AsyncPump()) {std::this_thread::sleep_for(std::chrono::milliseconds(2));} - - if (task.m_complete && task.x10_loadBuffer) - { - /* Load complete, build resource */ - std::unique_ptr newObj; - if (m_factoryMgr.CanMakeMemory(task.x0_tag)) - { - newObj = m_factoryMgr.MakeObjectFromMemory(tag, std::move(task.x10_loadBuffer), - task.x14_resSize, false, task.x18_cvXfer, selfRef); - } - else - { - athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize); - newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer, selfRef); - } - - //*task.xc_targetObjPtr = newObj.get(); - Log.report(logvisor::Warning, "spin-built %.4s %08X", - task.x0_tag.type.getChars(), u32(task.x0_tag.id.Value())); - - _RemoveTask(asyncSearch); - return newObj; - } - else if (task.m_complete) - { - Log.report(logvisor::Error, "unable to spin-build %.4s %08X; Resource requested as cook-only", - task.x0_tag.type.getChars(), u32(task.x0_tag.id.Value())); - } - else - { - Log.report(logvisor::Error, "unable to spin-build %.4s %08X", - task.x0_tag.type.getChars(), u32(task.x0_tag.id.Value())); - } - - _RemoveTask(asyncSearch); - return {}; + /* Pump load pipeline (cooking if needed) */ + while (!task.AsyncPump()) { + std::this_thread::sleep_for(std::chrono::milliseconds(2)); } - /* Fall-back to sync build */ - return BuildSync(tag, *resPath, paramXfer, selfRef); + if (task.m_complete && task.x10_loadBuffer) { + /* Load complete, build resource */ + std::unique_ptr newObj; + if (m_factoryMgr.CanMakeMemory(task.x0_tag)) { + newObj = m_factoryMgr.MakeObjectFromMemory(tag, std::move(task.x10_loadBuffer), task.x14_resSize, false, + task.x18_cvXfer, selfRef); + } else { + athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize); + newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer, selfRef); + } + + //*task.xc_targetObjPtr = newObj.get(); + Log.report(logvisor::Warning, "spin-built %.4s %08X", task.x0_tag.type.getChars(), u32(task.x0_tag.id.Value())); + + _RemoveTask(asyncSearch); + return newObj; + } else if (task.m_complete) { + Log.report(logvisor::Error, "unable to spin-build %.4s %08X; Resource requested as cook-only", + task.x0_tag.type.getChars(), u32(task.x0_tag.id.Value())); + } else { + Log.report(logvisor::Error, "unable to spin-build %.4s %08X", task.x0_tag.type.getChars(), + u32(task.x0_tag.id.Value())); + } + + _RemoveTask(asyncSearch); + return {}; + } + + /* Fall-back to sync build */ + return BuildSync(tag, *resPath, paramXfer, selfRef); } -std::shared_ptr -ProjectResourceFactoryBase::BuildAsyncInternal(const urde::SObjectTag& tag, - const urde::CVParamTransfer& paramXfer, - std::unique_ptr* objOut, - CObjectReference* selfRef) -{ - if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) - return {}; - return _AddTask(std::make_unique(*this, tag, objOut, paramXfer, selfRef)); +std::shared_ptr ProjectResourceFactoryBase::BuildAsyncInternal(const urde::SObjectTag& tag, + const urde::CVParamTransfer& paramXfer, + std::unique_ptr* objOut, + CObjectReference* selfRef) { + if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) + return {}; + return _AddTask(std::make_unique(*this, tag, objOut, paramXfer, selfRef)); } -void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag, - const urde::CVParamTransfer& paramXfer, - std::unique_ptr* objOut, - CObjectReference* selfRef) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id on type '%.4s'", tag.type.getChars()); +void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag, const urde::CVParamTransfer& paramXfer, + std::unique_ptr* objOut, CObjectReference* selfRef) { + if (!tag.id.IsValid()) + Log.report(logvisor::Fatal, "attempted to access null id on type '%.4s'", tag.type.getChars()); - BuildAsyncInternal(tag, paramXfer, objOut, selfRef); + BuildAsyncInternal(tag, paramXfer, objOut, selfRef); } -u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id on type '%.4s'", tag.type.getChars()); +u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag) { + if (!tag.id.IsValid()) + Log.report(logvisor::Fatal, "attempted to access null id on type '%.4s'", tag.type.getChars()); - /* Ensure resource at requested path is indexed and not cooking */ - const hecl::ProjectPath* resPath = nullptr; - if (!WaitForTagReady(tag, resPath)) - return {}; + /* Ensure resource at requested path is indexed and not cooking */ + const hecl::ProjectPath* resPath = nullptr; + if (!WaitForTagReady(tag, resPath)) + return {}; - /* Ensure cooked rep is on the filesystem */ - std::experimental::optional fr; - if (!PrepForReadSync(tag, *resPath, fr)) - return {}; + /* Ensure cooked rep is on the filesystem */ + std::experimental::optional fr; + if (!PrepForReadSync(tag, *resPath, fr)) + return {}; - return fr->length(); + return fr->length(); } -std::shared_ptr -ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag, void* target) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id"); - if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) - return {}; - return std::static_pointer_cast(_AddTask(std::make_shared(*this, tag, reinterpret_cast(target)))); +std::shared_ptr ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag, + void* target) { + if (!tag.id.IsValid()) + Log.report(logvisor::Fatal, "attempted to access null id"); + if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) + return {}; + return std::static_pointer_cast( + _AddTask(std::make_shared(*this, tag, reinterpret_cast(target)))); } -std::shared_ptr -ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, - u32 off, u32 size, void* target) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id"); - if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) - return {}; - return std::static_pointer_cast(_AddTask(std::make_shared(*this, tag, reinterpret_cast(target), size, off))); +std::shared_ptr ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, + u32 off, u32 size, void* target) { + if (!tag.id.IsValid()) + Log.report(logvisor::Fatal, "attempted to access null id"); + if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) + return {}; + return std::static_pointer_cast( + _AddTask(std::make_shared(*this, tag, reinterpret_cast(target), size, off))); } -std::unique_ptr ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id"); +std::unique_ptr ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag) { + if (!tag.id.IsValid()) + Log.report(logvisor::Fatal, "attempted to access null id"); - /* Ensure resource at requested path is indexed and not cooking */ - const hecl::ProjectPath* resPath = nullptr; - if (!WaitForTagReady(tag, resPath)) - return {}; + /* Ensure resource at requested path is indexed and not cooking */ + const hecl::ProjectPath* resPath = nullptr; + if (!WaitForTagReady(tag, resPath)) + return {}; - /* Ensure cooked rep is on the filesystem */ - std::experimental::optional fr; - if (!PrepForReadSync(tag, *resPath, fr)) - return {}; + /* Ensure cooked rep is on the filesystem */ + std::experimental::optional fr; + if (!PrepForReadSync(tag, *resPath, fr)) + return {}; - return fr->readUBytes(fr->length()); + return fr->readUBytes(fr->length()); } -std::unique_ptr ProjectResourceFactoryBase::LoadNewResourcePartSync(const urde::SObjectTag& tag, - u32 off, u32 size) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id"); +std::unique_ptr ProjectResourceFactoryBase::LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, + u32 size) { + if (!tag.id.IsValid()) + Log.report(logvisor::Fatal, "attempted to access null id"); - /* Ensure resource at requested path is indexed and not cooking */ - const hecl::ProjectPath* resPath = nullptr; - if (!WaitForTagReady(tag, resPath)) - return {}; + /* Ensure resource at requested path is indexed and not cooking */ + const hecl::ProjectPath* resPath = nullptr; + if (!WaitForTagReady(tag, resPath)) + return {}; - /* Ensure cooked rep is on the filesystem */ - std::experimental::optional fr; - if (!PrepForReadSync(tag, *resPath, fr)) - return {}; + /* Ensure cooked rep is on the filesystem */ + std::experimental::optional fr; + if (!PrepForReadSync(tag, *resPath, fr)) + return {}; - s32 sz = std::min(s32(size), std::max(0, s32(fr->length()) - s32(off))); - fr->seek(off, athena::SeekOrigin::Begin); - return fr->readUBytes(sz); + s32 sz = std::min(s32(size), std::max(0, s32(fr->length()) - s32(off))); + fr->seek(off, athena::SeekOrigin::Begin); + return fr->readUBytes(sz); } -std::shared_ptr -ProjectResourceFactoryBase::CookResourceAsync(const urde::SObjectTag& tag) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id"); - if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) - return {}; - return _AddTask(std::make_shared(*this, tag)); +std::shared_ptr ProjectResourceFactoryBase::CookResourceAsync(const urde::SObjectTag& tag) { + if (!tag.id.IsValid()) + Log.report(logvisor::Fatal, "attempted to access null id"); + if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end()) + return {}; + return _AddTask(std::make_shared(*this, tag)); } -void ProjectResourceFactoryBase::CancelBuild(const urde::SObjectTag& tag) -{ - _RemoveTask(tag); -} +void ProjectResourceFactoryBase::CancelBuild(const urde::SObjectTag& tag) { _RemoveTask(tag); } -bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag) -{ - if (!tag.id.IsValid()) - Log.report(logvisor::Fatal, "attempted to access null id"); - - const hecl::ProjectPath* resPath = nullptr; - if (!WaitForTagReady(tag, resPath)) - return false; - - if (resPath->isFile()) - return true; +bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag) { + if (!tag.id.IsValid()) + Log.report(logvisor::Fatal, "attempted to access null id"); + const hecl::ProjectPath* resPath = nullptr; + if (!WaitForTagReady(tag, resPath)) return false; + + if (resPath->isFile()) + return true; + + return false; } -const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(std::string_view name) const -{ - return static_cast(*m_cookSpec).getResourceIdByName(name); +const urde::SObjectTag* ProjectResourceFactoryBase::GetResourceIdByName(std::string_view name) const { + return static_cast(*m_cookSpec).getResourceIdByName(name); } -FourCC ProjectResourceFactoryBase::GetResourceTypeById(CAssetId id) const -{ - return static_cast(*m_cookSpec).getResourceTypeById(id); +FourCC ProjectResourceFactoryBase::GetResourceTypeById(CAssetId id) const { + return static_cast(*m_cookSpec).getResourceTypeById(id); } -void ProjectResourceFactoryBase::EnumerateResources(const std::function& lambda) const -{ - return static_cast(*m_cookSpec).enumerateResources(lambda); +void ProjectResourceFactoryBase::EnumerateResources(const std::function& lambda) const { + return static_cast(*m_cookSpec).enumerateResources(lambda); } void ProjectResourceFactoryBase::EnumerateNamedResources( - const std::function& lambda) const -{ - return static_cast(*m_cookSpec).enumerateNamedResources(lambda); + const std::function& lambda) const { + return static_cast(*m_cookSpec).enumerateNamedResources(lambda); } template -bool ProjectResourceFactoryBase::AsyncPumpTask(ItType& it) -{ - /* Ensure requested resource is in the index */ - AsyncTask& task = _GetAsyncTask(it); - hecl::ProjectPath path = static_cast(*m_cookSpec).pathFromTag(task.x0_tag); - if (!path) - { - if (!static_cast(*m_cookSpec).backgroundIndexRunning()) - { - Log.report(logvisor::Error, _SYS_STR("unable to find async load resource (%.4s, %08X)"), - task.x0_tag.type.getChars(), task.x0_tag.id); - it = _RemoveTask(it); - } - return true; +bool ProjectResourceFactoryBase::AsyncPumpTask(ItType& it) { + /* Ensure requested resource is in the index */ + AsyncTask& task = _GetAsyncTask(it); + hecl::ProjectPath path = static_cast(*m_cookSpec).pathFromTag(task.x0_tag); + if (!path) { + if (!static_cast(*m_cookSpec).backgroundIndexRunning()) { + Log.report(logvisor::Error, _SYS_STR("unable to find async load resource (%.4s, %08X)"), + task.x0_tag.type.getChars(), task.x0_tag.id); + it = _RemoveTask(it); } - task.EnsurePath(task.x0_tag, path); + return true; + } + task.EnsurePath(task.x0_tag, path); - /* Pump load pipeline (cooking if needed) */ - if (task.AsyncPump()) - { - if (task.m_complete) - { - /* Load complete, build resource */ - if (task.xc_targetObjPtr) - { - /* Factory build */ - std::unique_ptr newObj; - if (m_factoryMgr.CanMakeMemory(task.x0_tag)) - { - newObj = m_factoryMgr.MakeObjectFromMemory(task.x0_tag, std::move(task.x10_loadBuffer), - task.x14_resSize, false, task.x18_cvXfer, - task.m_selfRef); - } - else - { - athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize); - newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer, task.m_selfRef); - } - - *task.xc_targetObjPtr = std::move(newObj); - Log.report(logvisor::Info, "async-built %.4s %08X", - task.x0_tag.type.getChars(), - u32(task.x0_tag.id.Value())); - } - else if (task.xc_targetDataPtr) - { - /* Buffer only */ - *task.xc_targetDataPtr = std::move(task.x10_loadBuffer); - Log.report(logvisor::Info, "async-loaded %.4s %08X", - task.x0_tag.type.getChars(), - u32(task.x0_tag.id.Value())); - } - else if (task.xc_targetDataRawPtr) - { - /* Buffer only raw */ - Log.report(logvisor::Info, "async-loaded %.4s %08X", - task.x0_tag.type.getChars(), - u32(task.x0_tag.id.Value())); - } + /* Pump load pipeline (cooking if needed) */ + if (task.AsyncPump()) { + if (task.m_complete) { + /* Load complete, build resource */ + if (task.xc_targetObjPtr) { + /* Factory build */ + std::unique_ptr newObj; + if (m_factoryMgr.CanMakeMemory(task.x0_tag)) { + newObj = m_factoryMgr.MakeObjectFromMemory(task.x0_tag, std::move(task.x10_loadBuffer), task.x14_resSize, + false, task.x18_cvXfer, task.m_selfRef); + } else { + athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize); + newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer, task.m_selfRef); } - it = _RemoveTask(it); - return true; + *task.xc_targetObjPtr = std::move(newObj); + Log.report(logvisor::Info, "async-built %.4s %08X", task.x0_tag.type.getChars(), u32(task.x0_tag.id.Value())); + } else if (task.xc_targetDataPtr) { + /* Buffer only */ + *task.xc_targetDataPtr = std::move(task.x10_loadBuffer); + Log.report(logvisor::Info, "async-loaded %.4s %08X", task.x0_tag.type.getChars(), u32(task.x0_tag.id.Value())); + } else if (task.xc_targetDataRawPtr) { + /* Buffer only raw */ + Log.report(logvisor::Info, "async-loaded %.4s %08X", task.x0_tag.type.getChars(), u32(task.x0_tag.id.Value())); + } } - ++it; - return false; + + it = _RemoveTask(it); + return true; + } + ++it; + return false; } template bool ProjectResourceFactoryBase::AsyncPumpTask>::iterator>( std::list>::iterator& it); -template bool ProjectResourceFactoryBase::AsyncPumpTask>::iterator>::iterator>( +template bool ProjectResourceFactoryBase::AsyncPumpTask< + std::unordered_map>::iterator>::iterator>( std::unordered_map>::iterator>::iterator& it); -void ProjectResourceFactoryBase::AsyncIdle() -{ - /* Consume completed transactions, they will be processed this cycle at the latest */ - std::list> completed; - m_clientProc.swapCompletedQueue(completed); +void ProjectResourceFactoryBase::AsyncIdle() { + /* Consume completed transactions, they will be processed this cycle at the latest */ + std::list> completed; + m_clientProc.swapCompletedQueue(completed); - /* Begin self-profiling loop */ - std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); - for (auto it=m_asyncLoadList.begin() ; it != m_asyncLoadList.end() ;) - { - /* Allow 8 milliseconds (roughly 1/2 frame-time) for each async build cycle */ - std::chrono::steady_clock::time_point resStart = std::chrono::steady_clock::now(); - if (std::chrono::duration_cast(resStart - start).count() > 8) - break; + /* Begin self-profiling loop */ + std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now(); + for (auto it = m_asyncLoadList.begin(); it != m_asyncLoadList.end();) { + /* Allow 8 milliseconds (roughly 1/2 frame-time) for each async build cycle */ + std::chrono::steady_clock::time_point resStart = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast(resStart - start).count() > 8) + break; - AsyncPumpTask(it); - } + AsyncPumpTask(it); + } } -} +} // namespace urde diff --git a/Editor/ProjectResourceFactoryBase.hpp b/Editor/ProjectResourceFactoryBase.hpp index b01c28295..6924fa677 100644 --- a/Editor/ProjectResourceFactoryBase.hpp +++ b/Editor/ProjectResourceFactoryBase.hpp @@ -11,176 +11,149 @@ #include #include -namespace urde -{ +namespace urde { -class ProjectResourceFactoryBase : public IFactory -{ - friend class ProjectResourcePool; - hecl::ClientProcess& m_clientProc; +class ProjectResourceFactoryBase : public IFactory { + friend class ProjectResourcePool; + hecl::ClientProcess& m_clientProc; public: - struct AsyncTask : urde::IDvdRequest - { - ProjectResourceFactoryBase& m_parent; + struct AsyncTask : urde::IDvdRequest { + ProjectResourceFactoryBase& m_parent; - SObjectTag x0_tag; - //IDvdRequest* x8_dvdReq = nullptr; - std::unique_ptr* xc_targetDataPtr = nullptr; - u8* xc_targetDataRawPtr = nullptr; - std::unique_ptr* xc_targetObjPtr = nullptr; - std::unique_ptr x10_loadBuffer; - u32 x14_resSize = UINT32_MAX; - u32 x14_resOffset = 0; - CVParamTransfer x18_cvXfer; - CObjectReference* m_selfRef = nullptr; + SObjectTag x0_tag; + // IDvdRequest* x8_dvdReq = nullptr; + std::unique_ptr* xc_targetDataPtr = nullptr; + u8* xc_targetDataRawPtr = nullptr; + std::unique_ptr* xc_targetObjPtr = nullptr; + std::unique_ptr x10_loadBuffer; + u32 x14_resSize = UINT32_MAX; + u32 x14_resOffset = 0; + CVParamTransfer x18_cvXfer; + CObjectReference* m_selfRef = nullptr; - hecl::ProjectPath m_workingPath; - hecl::ProjectPath m_cookedPath; - std::shared_ptr m_cookTransaction; - std::shared_ptr m_bufTransaction; - bool m_failed = false; - bool m_complete = false; + hecl::ProjectPath m_workingPath; + hecl::ProjectPath m_cookedPath; + std::shared_ptr m_cookTransaction; + std::shared_ptr m_bufTransaction; + bool m_failed = false; + bool m_complete = false; - AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, - std::unique_ptr& ptr) - : m_parent(parent), x0_tag(tag), xc_targetDataPtr(&ptr) {} + AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, std::unique_ptr& ptr) + : m_parent(parent), x0_tag(tag), xc_targetDataPtr(&ptr) {} - AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, - std::unique_ptr& ptr, u32 size, u32 off) - : m_parent(parent), x0_tag(tag), xc_targetDataPtr(&ptr), x14_resSize(size), - x14_resOffset(off) {} + AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, std::unique_ptr& ptr, u32 size, u32 off) + : m_parent(parent), x0_tag(tag), xc_targetDataPtr(&ptr), x14_resSize(size), x14_resOffset(off) {} - AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, - u8* ptr) - : m_parent(parent), x0_tag(tag), xc_targetDataRawPtr(ptr) {} + AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, u8* ptr) + : m_parent(parent), x0_tag(tag), xc_targetDataRawPtr(ptr) {} - AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, - u8* ptr, u32 size, u32 off) - : m_parent(parent), x0_tag(tag), xc_targetDataRawPtr(ptr), x14_resSize(size), - x14_resOffset(off) {} + AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, u8* ptr, u32 size, u32 off) + : m_parent(parent), x0_tag(tag), xc_targetDataRawPtr(ptr), x14_resSize(size), x14_resOffset(off) {} - AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, - std::unique_ptr* ptr, const CVParamTransfer& xfer, CObjectReference* selfRef) - : m_parent(parent), x0_tag(tag), xc_targetObjPtr(ptr), x18_cvXfer(xfer), m_selfRef(selfRef) {} + AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, std::unique_ptr* ptr, + const CVParamTransfer& xfer, CObjectReference* selfRef) + : m_parent(parent), x0_tag(tag), xc_targetObjPtr(ptr), x18_cvXfer(xfer), m_selfRef(selfRef) {} - /* Cook only */ - AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag) - : m_parent(parent), x0_tag(tag) {} + /* Cook only */ + AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag) : m_parent(parent), x0_tag(tag) {} - void EnsurePath(const urde::SObjectTag& tag, - const hecl::ProjectPath& path); - void CookComplete(); - bool AsyncPump(); - void WaitUntilComplete(); - bool IsComplete() { return m_complete; } - void PostCancelRequest() {} - EMediaType GetMediaType() const { return EMediaType::Real; } - }; + void EnsurePath(const urde::SObjectTag& tag, const hecl::ProjectPath& path); + void CookComplete(); + bool AsyncPump(); + void WaitUntilComplete(); + bool IsComplete() { return m_complete; } + void PostCancelRequest() {} + EMediaType GetMediaType() const { return EMediaType::Real; } + }; protected: - const hecl::Database::Project* m_proj = nullptr; - const hecl::Database::DataSpecEntry* m_origSpec = nullptr; - const hecl::Database::DataSpecEntry* m_pcSpec = nullptr; - /* Used to resolve cooked paths */ - std::unique_ptr m_cookSpec; - urde::CFactoryMgr m_factoryMgr; + const hecl::Database::Project* m_proj = nullptr; + const hecl::Database::DataSpecEntry* m_origSpec = nullptr; + const hecl::Database::DataSpecEntry* m_pcSpec = nullptr; + /* Used to resolve cooked paths */ + std::unique_ptr m_cookSpec; + urde::CFactoryMgr m_factoryMgr; - std::list> m_asyncLoadList; - std::unordered_map>::iterator> m_asyncLoadMap; - std::shared_ptr - _AddTask(const std::shared_ptr& ptr); - std::list>::iterator - _RemoveTask(std::list>::iterator it); - std::unordered_map>::iterator>::iterator - _RemoveTask(std::unordered_map>::iterator>::iterator it); - std::unordered_map>::iterator>::iterator - _RemoveTask(const SObjectTag& tag); + std::list> m_asyncLoadList; + std::unordered_map>::iterator> m_asyncLoadMap; + std::shared_ptr _AddTask(const std::shared_ptr& ptr); + std::list>::iterator _RemoveTask(std::list>::iterator it); + std::unordered_map>::iterator>::iterator + _RemoveTask(std::unordered_map>::iterator>::iterator it); + std::unordered_map>::iterator>::iterator + _RemoveTask(const SObjectTag& tag); - static AsyncTask& _GetAsyncTask(std::list>::iterator it) - { - return **it; - } - static AsyncTask& _GetAsyncTask( - std::unordered_map>::iterator>::iterator it) - { - return **it->second; - } + static AsyncTask& _GetAsyncTask(std::list>::iterator it) { return **it; } + static AsyncTask& + _GetAsyncTask(std::unordered_map>::iterator>::iterator it) { + return **it->second; + } - bool - PrepForReadSync(const SObjectTag& tag, - const hecl::ProjectPath& path, - std::experimental::optional& fr); + bool PrepForReadSync(const SObjectTag& tag, const hecl::ProjectPath& path, + std::experimental::optional& fr); - bool WaitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut) - { - return static_cast(*m_cookSpec).waitForTagReady(tag, pathOut); - } - SObjectTag TagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const - { - return static_cast(*m_cookSpec).tagFromPath(path, btok); - } - SObjectTag BuildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const - { - return static_cast(*m_cookSpec).buildTagFromPath(path, btok); - } - void GetTagListForFile(const char* pakName, std::vector& out) const - { - return static_cast(*m_cookSpec).getTagListForFile(pakName, out); - } - void CancelBackgroundIndex() - { - if (m_cookSpec) - return static_cast(*m_cookSpec).cancelBackgroundIndex(); - } - void BeginBackgroundIndex(hecl::Database::Project& proj, - const hecl::Database::DataSpecEntry& origSpec, - const hecl::Database::DataSpecEntry& pcSpec); + bool WaitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut) { + return static_cast(*m_cookSpec).waitForTagReady(tag, pathOut); + } + SObjectTag TagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { + return static_cast(*m_cookSpec).tagFromPath(path, btok); + } + SObjectTag BuildTagFromPath(const hecl::ProjectPath& path, hecl::blender::Token& btok) const { + return static_cast(*m_cookSpec).buildTagFromPath(path, btok); + } + void GetTagListForFile(const char* pakName, std::vector& out) const { + return static_cast(*m_cookSpec).getTagListForFile(pakName, out); + } + void CancelBackgroundIndex() { + if (m_cookSpec) + return static_cast(*m_cookSpec).cancelBackgroundIndex(); + } + void BeginBackgroundIndex(hecl::Database::Project& proj, const hecl::Database::DataSpecEntry& origSpec, + const hecl::Database::DataSpecEntry& pcSpec); - bool SyncCook(const hecl::ProjectPath& working); - CFactoryFnReturn BuildSync(const SObjectTag& tag, const hecl::ProjectPath& path, - const CVParamTransfer& paramXfer, CObjectReference* selfRef); - std::shared_ptr BuildAsyncInternal(const urde::SObjectTag&, const urde::CVParamTransfer&, std::unique_ptr*, CObjectReference* selfRef); + bool SyncCook(const hecl::ProjectPath& working); + CFactoryFnReturn BuildSync(const SObjectTag& tag, const hecl::ProjectPath& path, const CVParamTransfer& paramXfer, + CObjectReference* selfRef); + std::shared_ptr BuildAsyncInternal(const urde::SObjectTag&, const urde::CVParamTransfer&, + std::unique_ptr*, CObjectReference* selfRef); public: - ProjectResourceFactoryBase(hecl::ClientProcess& clientProc) : m_clientProc(clientProc) {} - std::unique_ptr Build(const urde::SObjectTag&, const urde::CVParamTransfer&, CObjectReference* selfRef); - void BuildAsync(const urde::SObjectTag&, const urde::CVParamTransfer&, std::unique_ptr*, CObjectReference* selfRef); - void CancelBuild(const urde::SObjectTag&); - bool CanBuild(const urde::SObjectTag&); - const urde::SObjectTag* GetResourceIdByName(std::string_view) const; - FourCC GetResourceTypeById(CAssetId id) const; - hecl::ProjectPath GetCookedPath(const hecl::ProjectPath& working, bool pcTarget) const - { - return static_cast(*m_cookSpec).getCookedPath(working, pcTarget); - } + ProjectResourceFactoryBase(hecl::ClientProcess& clientProc) : m_clientProc(clientProc) {} + std::unique_ptr Build(const urde::SObjectTag&, const urde::CVParamTransfer&, CObjectReference* selfRef); + void BuildAsync(const urde::SObjectTag&, const urde::CVParamTransfer&, std::unique_ptr*, + CObjectReference* selfRef); + void CancelBuild(const urde::SObjectTag&); + bool CanBuild(const urde::SObjectTag&); + const urde::SObjectTag* GetResourceIdByName(std::string_view) const; + FourCC GetResourceTypeById(CAssetId id) const; + hecl::ProjectPath GetCookedPath(const hecl::ProjectPath& working, bool pcTarget) const { + return static_cast(*m_cookSpec).getCookedPath(working, pcTarget); + } - void EnumerateResources(const std::function& lambda) const; - void EnumerateNamedResources(const std::function& lambda) const; + void EnumerateResources(const std::function& lambda) const; + void EnumerateNamedResources(const std::function& lambda) const; - u32 ResourceSize(const SObjectTag& tag); - std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target); - std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target); - std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); - std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size); + u32 ResourceSize(const SObjectTag& tag); + std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target); + std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, + void* target); + std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); + std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size); - std::shared_ptr CookResourceAsync(const urde::SObjectTag& tag); + std::shared_ptr CookResourceAsync(const urde::SObjectTag& tag); - template - bool AsyncPumpTask(ItType& it); - void AsyncIdle(); - void Shutdown() { CancelBackgroundIndex(); } - bool IsBusy() const { return m_asyncLoadMap.size() != 0; } + template + bool AsyncPumpTask(ItType& it); + void AsyncIdle(); + void Shutdown() { CancelBackgroundIndex(); } + bool IsBusy() const { return m_asyncLoadMap.size() != 0; } - SObjectTag TagFromPath(hecl::SystemStringView path) const - { - return TagFromPath(hecl::ProjectPath(*(hecl::Database::Project*)m_proj, path), - hecl::blender::SharedBlenderToken); - } + SObjectTag TagFromPath(hecl::SystemStringView path) const { + return TagFromPath(hecl::ProjectPath(*(hecl::Database::Project*)m_proj, path), hecl::blender::SharedBlenderToken); + } - ~ProjectResourceFactoryBase() {Shutdown();} + ~ProjectResourceFactoryBase() { Shutdown(); } }; -} - +} // namespace urde diff --git a/Editor/ProjectResourceFactoryMP1.cpp b/Editor/ProjectResourceFactoryMP1.cpp index 80c4c6475..8014be4a6 100644 --- a/Editor/ProjectResourceFactoryMP1.cpp +++ b/Editor/ProjectResourceFactoryMP1.cpp @@ -38,69 +38,62 @@ #include "MP1/MP1OriginalIDs.hpp" #include "GameGlobalObjects.hpp" -namespace DataSpec -{ +namespace DataSpec { extern hecl::Database::DataSpecEntry SpecEntMP1; extern hecl::Database::DataSpecEntry SpecEntMP1PC; -} +} // namespace DataSpec -namespace urde -{ +namespace urde { ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& clientProc) -: ProjectResourceFactoryBase(clientProc) -{ - m_factoryMgr.AddFactory(FOURCC('TXTR'), FMemFactoryFunc(FTextureFactory)); - m_factoryMgr.AddFactory(FOURCC('PART'), FFactoryFunc(FParticleFactory)); - m_factoryMgr.AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame)); - m_factoryMgr.AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory)); - m_factoryMgr.AddFactory(FOURCC('CMDL'), FMemFactoryFunc(FModelFactory)); - m_factoryMgr.AddFactory(FOURCC('CINF'), FFactoryFunc(FCharLayoutInfo)); - m_factoryMgr.AddFactory(FOURCC('CSKR'), FFactoryFunc(FSkinRulesFactory)); - m_factoryMgr.AddFactory(FOURCC('ANCS'), FFactoryFunc(FAnimCharacterSet)); - m_factoryMgr.AddFactory(FOURCC('ANIM'), FFactoryFunc(AnimSourceFactory)); - m_factoryMgr.AddFactory(FOURCC('EVNT'), FFactoryFunc(AnimPOIDataFactory)); - m_factoryMgr.AddFactory(FOURCC('DCLN'), FFactoryFunc(FCollidableOBBTreeGroupFactory)); - m_factoryMgr.AddFactory(FOURCC('DGRP'), FFactoryFunc(FDependencyGroupFactory)); - m_factoryMgr.AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory)); - m_factoryMgr.AddFactory(FOURCC('CSNG'), FFactoryFunc(FMidiDataFactory)); - m_factoryMgr.AddFactory(FOURCC('ATBL'), FFactoryFunc(FAudioTranslationTableFactory)); - m_factoryMgr.AddFactory(FOURCC('STRG'), FFactoryFunc(FStringTableFactory)); - m_factoryMgr.AddFactory(FOURCC('HINT'), FFactoryFunc(FHintFactory)); - m_factoryMgr.AddFactory(FOURCC('SAVW'), FFactoryFunc(FSaveWorldFactory)); - m_factoryMgr.AddFactory(FOURCC('MAPW'), FFactoryFunc(FMapWorldFactory)); - m_factoryMgr.AddFactory(FOURCC('OIDS'), FFactoryFunc(FMP1OriginalIDsFactory)); - m_factoryMgr.AddFactory(FOURCC('SCAN'), FFactoryFunc(FScannableObjectInfoFactory)); - m_factoryMgr.AddFactory(FOURCC('CRSC'), FFactoryFunc(FCollisionResponseDataFactory)); - m_factoryMgr.AddFactory(FOURCC('SWHC'), FFactoryFunc(FParticleSwooshDataFactory)); - m_factoryMgr.AddFactory(FOURCC('ELSC'), FFactoryFunc(FParticleElectricDataFactory)); - m_factoryMgr.AddFactory(FOURCC('WPSC'), FFactoryFunc(FProjectileWeaponDataFactory)); - m_factoryMgr.AddFactory(FOURCC('DPSC'), FFactoryFunc(FDecalDataFactory)); - m_factoryMgr.AddFactory(FOURCC('MAPA'), FFactoryFunc(FMapAreaFactory)); - m_factoryMgr.AddFactory(FOURCC('MAPU'), FFactoryFunc(FMapUniverseFactory)); - m_factoryMgr.AddFactory(FOURCC('PATH'), FMemFactoryFunc(FPathFindAreaFactory)); +: ProjectResourceFactoryBase(clientProc) { + m_factoryMgr.AddFactory(FOURCC('TXTR'), FMemFactoryFunc(FTextureFactory)); + m_factoryMgr.AddFactory(FOURCC('PART'), FFactoryFunc(FParticleFactory)); + m_factoryMgr.AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame)); + m_factoryMgr.AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory)); + m_factoryMgr.AddFactory(FOURCC('CMDL'), FMemFactoryFunc(FModelFactory)); + m_factoryMgr.AddFactory(FOURCC('CINF'), FFactoryFunc(FCharLayoutInfo)); + m_factoryMgr.AddFactory(FOURCC('CSKR'), FFactoryFunc(FSkinRulesFactory)); + m_factoryMgr.AddFactory(FOURCC('ANCS'), FFactoryFunc(FAnimCharacterSet)); + m_factoryMgr.AddFactory(FOURCC('ANIM'), FFactoryFunc(AnimSourceFactory)); + m_factoryMgr.AddFactory(FOURCC('EVNT'), FFactoryFunc(AnimPOIDataFactory)); + m_factoryMgr.AddFactory(FOURCC('DCLN'), FFactoryFunc(FCollidableOBBTreeGroupFactory)); + m_factoryMgr.AddFactory(FOURCC('DGRP'), FFactoryFunc(FDependencyGroupFactory)); + m_factoryMgr.AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory)); + m_factoryMgr.AddFactory(FOURCC('CSNG'), FFactoryFunc(FMidiDataFactory)); + m_factoryMgr.AddFactory(FOURCC('ATBL'), FFactoryFunc(FAudioTranslationTableFactory)); + m_factoryMgr.AddFactory(FOURCC('STRG'), FFactoryFunc(FStringTableFactory)); + m_factoryMgr.AddFactory(FOURCC('HINT'), FFactoryFunc(FHintFactory)); + m_factoryMgr.AddFactory(FOURCC('SAVW'), FFactoryFunc(FSaveWorldFactory)); + m_factoryMgr.AddFactory(FOURCC('MAPW'), FFactoryFunc(FMapWorldFactory)); + m_factoryMgr.AddFactory(FOURCC('OIDS'), FFactoryFunc(FMP1OriginalIDsFactory)); + m_factoryMgr.AddFactory(FOURCC('SCAN'), FFactoryFunc(FScannableObjectInfoFactory)); + m_factoryMgr.AddFactory(FOURCC('CRSC'), FFactoryFunc(FCollisionResponseDataFactory)); + m_factoryMgr.AddFactory(FOURCC('SWHC'), FFactoryFunc(FParticleSwooshDataFactory)); + m_factoryMgr.AddFactory(FOURCC('ELSC'), FFactoryFunc(FParticleElectricDataFactory)); + m_factoryMgr.AddFactory(FOURCC('WPSC'), FFactoryFunc(FProjectileWeaponDataFactory)); + m_factoryMgr.AddFactory(FOURCC('DPSC'), FFactoryFunc(FDecalDataFactory)); + m_factoryMgr.AddFactory(FOURCC('MAPA'), FFactoryFunc(FMapAreaFactory)); + m_factoryMgr.AddFactory(FOURCC('MAPU'), FFactoryFunc(FMapUniverseFactory)); + m_factoryMgr.AddFactory(FOURCC('PATH'), FMemFactoryFunc(FPathFindAreaFactory)); } -void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj, CSimplePool& sp) -{ - BeginBackgroundIndex(proj, DataSpec::SpecEntMP1, DataSpec::SpecEntMP1PC); - m_origIds = sp.GetObj("MP1OriginalIDs"); +void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj, CSimplePool& sp) { + BeginBackgroundIndex(proj, DataSpec::SpecEntMP1, DataSpec::SpecEntMP1PC); + m_origIds = sp.GetObj("MP1OriginalIDs"); } -void ProjectResourceFactoryMP1::Shutdown() -{ - m_origIds = TLockedToken(); - ProjectResourceFactoryBase::Shutdown(); +void ProjectResourceFactoryMP1::Shutdown() { + m_origIds = TLockedToken(); + ProjectResourceFactoryBase::Shutdown(); } -CAssetId ProjectResourceFactoryMP1::TranslateOriginalToNew(CAssetId id) const -{ - return m_origIds->TranslateOriginalToNew(id); +CAssetId ProjectResourceFactoryMP1::TranslateOriginalToNew(CAssetId id) const { + return m_origIds->TranslateOriginalToNew(id); } -CAssetId ProjectResourceFactoryMP1::TranslateNewToOriginal(CAssetId id) const -{ - return m_origIds->TranslateNewToOriginal(id); +CAssetId ProjectResourceFactoryMP1::TranslateNewToOriginal(CAssetId id) const { + return m_origIds->TranslateNewToOriginal(id); } -} +} // namespace urde diff --git a/Editor/ProjectResourceFactoryMP1.hpp b/Editor/ProjectResourceFactoryMP1.hpp index a2c95811f..27dcd7019 100644 --- a/Editor/ProjectResourceFactoryMP1.hpp +++ b/Editor/ProjectResourceFactoryMP1.hpp @@ -3,22 +3,20 @@ #include "ProjectResourceFactoryBase.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class MP1OriginalIDs; class CSimplePool; -class ProjectResourceFactoryMP1 : public ProjectResourceFactoryBase -{ - TLockedToken m_origIds; -public: - ProjectResourceFactoryMP1(hecl::ClientProcess& clientProc); - void IndexMP1Resources(hecl::Database::Project& proj, CSimplePool& sp); - void Shutdown(); +class ProjectResourceFactoryMP1 : public ProjectResourceFactoryBase { + TLockedToken m_origIds; - CAssetId TranslateOriginalToNew(CAssetId id) const; - CAssetId TranslateNewToOriginal(CAssetId id) const; +public: + ProjectResourceFactoryMP1(hecl::ClientProcess& clientProc); + void IndexMP1Resources(hecl::Database::Project& proj, CSimplePool& sp); + void Shutdown(); + + CAssetId TranslateOriginalToNew(CAssetId id) const; + CAssetId TranslateNewToOriginal(CAssetId id) const; }; -} - +} // namespace urde diff --git a/Editor/Resource.cpp b/Editor/Resource.cpp index 52d199a7f..22c0318b6 100644 --- a/Editor/Resource.cpp +++ b/Editor/Resource.cpp @@ -1,14 +1,12 @@ #include "Resource.hpp" -namespace urde -{ +namespace urde { -Space::Class Resource::DeduceDefaultSpaceClass(const hecl::ProjectPath& path) -{ - athena::io::FileReader r(path.getAbsolutePath(), 32*1024, false); - if (r.hasError()) - return Space::Class::None; +Space::Class Resource::DeduceDefaultSpaceClass(const hecl::ProjectPath& path) { + athena::io::FileReader r(path.getAbsolutePath(), 32 * 1024, false); + if (r.hasError()) return Space::Class::None; + return Space::Class::None; } -} +} // namespace urde diff --git a/Editor/Resource.hpp b/Editor/Resource.hpp index 04848ebec..62ab31e45 100644 --- a/Editor/Resource.hpp +++ b/Editor/Resource.hpp @@ -3,8 +3,7 @@ #include "hecl/Database.hpp" #include "Space.hpp" -namespace urde -{ +namespace urde { /** Combines a ProjectPath with actively used Space references * @@ -15,34 +14,33 @@ namespace urde * The key purpose of this class is to centrally register observer-nodes for resources that * are updated via editing, or external file changes. */ -class Resource -{ +class Resource { public: - using ProjectDataSpec = hecl::Database::Project::ProjectDataSpec; + using ProjectDataSpec = hecl::Database::Project::ProjectDataSpec; + private: - hecl::ProjectPath m_path; - Space::Class m_defaultClass = Space::Class::None; - //EditorSpace* m_editingSpace = nullptr; - std::vector m_viewingSpaces; + hecl::ProjectPath m_path; + Space::Class m_defaultClass = Space::Class::None; + // EditorSpace* m_editingSpace = nullptr; + std::vector m_viewingSpaces; + public: - static Space::Class DeduceDefaultSpaceClass(const hecl::ProjectPath& path); - explicit Resource(hecl::ProjectPath&& path) - : m_path(std::move(path)), m_defaultClass(DeduceDefaultSpaceClass(m_path)) {} - const hecl::ProjectPath& path() const {return m_path;} + static Space::Class DeduceDefaultSpaceClass(const hecl::ProjectPath& path); + explicit Resource(hecl::ProjectPath&& path) + : m_path(std::move(path)), m_defaultClass(DeduceDefaultSpaceClass(m_path)) {} + const hecl::ProjectPath& path() const { return m_path; } }; /** Provides centralized hierarchical lookup and ownership of Resource nodes */ -class ResourceTree -{ +class ResourceTree { public: - struct Node - { - std::map> m_subnodes; - std::map> m_resources; - }; + struct Node { + std::map> m_subnodes; + std::map> m_resources; + }; + private: - std::unique_ptr m_rootNode; + std::unique_ptr m_rootNode; }; -} - +} // namespace urde diff --git a/Editor/ResourceBrowser.cpp b/Editor/ResourceBrowser.cpp index fe2c723a4..3f1272a4a 100644 --- a/Editor/ResourceBrowser.cpp +++ b/Editor/ResourceBrowser.cpp @@ -1,87 +1,70 @@ #include "ResourceBrowser.hpp" -namespace urde -{ +namespace urde { #define BROWSER_MARGIN 8 -bool ResourceBrowser::navigateToPath(const hecl::ProjectPath& pathIn) -{ - if (pathIn.isFile()) - m_path = pathIn.getParentPath(); - else - m_path = pathIn; +bool ResourceBrowser::navigateToPath(const hecl::ProjectPath& pathIn) { + if (pathIn.isFile()) + m_path = pathIn.getParentPath(); + else + m_path = pathIn; - m_comps = m_path.getPathComponents(); + m_comps = m_path.getPathComponents(); - hecl::DirectoryEnumerator dEnum(m_path.getAbsolutePath(), - hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, - m_state.sortColumn==State::SortColumn::Size, - m_state.sortDir==specter::SortDirection::Descending && - (m_state.sortColumn == State::SortColumn::Name || m_state.sortColumn == State::SortColumn::Size), - true); - m_resListingBind.updateListing(dEnum); - if (m_pathButtons) - m_pathButtons->setButtons(m_comps); + hecl::DirectoryEnumerator dEnum( + m_path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, + m_state.sortColumn == State::SortColumn::Size, + m_state.sortDir == specter::SortDirection::Descending && + (m_state.sortColumn == State::SortColumn::Name || m_state.sortColumn == State::SortColumn::Size), + true); + m_resListingBind.updateListing(dEnum); + if (m_pathButtons) + m_pathButtons->setButtons(m_comps); - if (m_view) - { - m_view->m_resListing.m_view->selectRow(-1); - m_view->m_resListing.m_view->updateData(); - m_view->updateSize(); - } + if (m_view) { + m_view->m_resListing.m_view->selectRow(-1); + m_view->m_resListing.m_view->updateData(); + m_view->updateSize(); + } - return true; + return true; } -void ResourceBrowser::pathButtonActivated(size_t idx) -{ - if (idx >= m_comps.size()) - return; +void ResourceBrowser::pathButtonActivated(size_t idx) { + if (idx >= m_comps.size()) + return; - hecl::SystemString dir; - bool needSlash = false; - size_t i = 0; - for (const hecl::SystemString& d : m_comps) - { - if (needSlash) - dir += _SYS_STR('/'); - if (d.compare(_SYS_STR("/"))) - needSlash = true; - dir += d; - if (++i > idx) - break; - } - navigateToPath(hecl::ProjectPath(*m_vm.project(), dir)); + hecl::SystemString dir; + bool needSlash = false; + size_t i = 0; + for (const hecl::SystemString& d : m_comps) { + if (needSlash) + dir += _SYS_STR('/'); + if (d.compare(_SYS_STR("/"))) + needSlash = true; + dir += d; + if (++i > idx) + break; + } + navigateToPath(hecl::ProjectPath(*m_vm.project(), dir)); } -void ResourceBrowser::View::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) -{ - m_resListing.mouseDown(coord, button, mod); +void ResourceBrowser::View::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) { + m_resListing.mouseDown(coord, button, mod); } -void ResourceBrowser::View::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) -{ - m_resListing.mouseUp(coord, button, mod); +void ResourceBrowser::View::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) { + m_resListing.mouseUp(coord, button, mod); } -void ResourceBrowser::View::mouseMove(const boo::SWindowCoord& coord) -{ - m_resListing.mouseMove(coord); -} +void ResourceBrowser::View::mouseMove(const boo::SWindowCoord& coord) { m_resListing.mouseMove(coord); } -void ResourceBrowser::View::mouseLeave(const boo::SWindowCoord& coord) -{ - m_resListing.mouseLeave(coord); -} +void ResourceBrowser::View::mouseLeave(const boo::SWindowCoord& coord) { m_resListing.mouseLeave(coord); } -void ResourceBrowser::View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) -{ - specter::View::resized(root, sub); - m_resListing.m_view->resized(root, sub); -} -void ResourceBrowser::View::draw(boo::IGraphicsCommandQueue* gfxQ) -{ - m_resListing.m_view->draw(gfxQ); +void ResourceBrowser::View::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) { + specter::View::resized(root, sub); + m_resListing.m_view->resized(root, sub); } +void ResourceBrowser::View::draw(boo::IGraphicsCommandQueue* gfxQ) { m_resListing.m_view->draw(gfxQ); } -} +} // namespace urde diff --git a/Editor/ResourceBrowser.hpp b/Editor/ResourceBrowser.hpp index 8cd08a64b..75be68a1e 100644 --- a/Editor/ResourceBrowser.hpp +++ b/Editor/ResourceBrowser.hpp @@ -5,258 +5,202 @@ #include "specter/PathButtons.hpp" #include "specter/Table.hpp" -namespace urde -{ +namespace urde { -class ResourceBrowser : public Space, public specter::IPathButtonsBinding -{ - struct State : Space::State - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - String<-1> path; - Value columnSplits[3] = {0.0f, 0.7f, 0.9f}; - enum class SortColumn - { - Name, - Type, - Size - }; - Value sortColumn = SortColumn::Name; - Value sortDir = specter::SortDirection::Ascending; - } m_state; - const Space::State& spaceState() const {return m_state;} +class ResourceBrowser : public Space, public specter::IPathButtonsBinding { + struct State : Space::State { + AT_DECL_DNA_YAML + AT_DECL_DNAV + String<-1> path; + Value columnSplits[3] = {0.0f, 0.7f, 0.9f}; + enum class SortColumn { Name, Type, Size }; + Value sortColumn = SortColumn::Name; + Value sortDir = specter::SortDirection::Ascending; + } m_state; + const Space::State& spaceState() const { return m_state; } - hecl::ProjectPath m_path; - std::vector m_comps; + hecl::ProjectPath m_path; + std::vector m_comps; - void pathButtonActivated(size_t idx); + void pathButtonActivated(size_t idx); - struct ResListingDataBind : specter::ITableDataBinding, specter::ITableStateBinding - { - ResourceBrowser& m_rb; + struct ResListingDataBind : specter::ITableDataBinding, specter::ITableStateBinding { + ResourceBrowser& m_rb; - struct Entry - { - hecl::SystemString m_path; - std::string m_name; - std::string m_type; - std::string m_size; - }; - std::vector m_entries; - - std::string m_nameCol; - std::string m_typeCol; - std::string m_sizeCol; - - std::string m_dirStr; - std::string m_projStr; - std::string m_fileStr; - - size_t columnCount() const {return 3;} - size_t rowCount() const {return m_entries.size();} - - std::string_view header(size_t cIdx) const - { - switch (cIdx) - { - case 0: - return m_nameCol; - case 1: - return m_typeCol; - case 2: - return m_sizeCol; - default: break; - } - return {}; - } - - std::string_view cell(size_t cIdx, size_t rIdx) const - { - switch (cIdx) - { - case 0: - return m_entries.at(rIdx).m_name; - case 1: - return m_entries.at(rIdx).m_type; - case 2: - return m_entries.at(rIdx).m_size; - default: break; - } - return {}; - } - - bool columnSplitResizeAllowed() const {return true;} - - float getColumnSplit(size_t cIdx) const - { - return m_rb.m_state.columnSplits[cIdx]; - } - - void setColumnSplit(size_t cIdx, float split) - { - m_rb.m_state.columnSplits[cIdx] = split; - } - - void updateListing(const hecl::DirectoryEnumerator& dEnum) - { - m_entries.clear(); - m_entries.reserve(dEnum.size()); - - for (const hecl::DirectoryEnumerator::Entry& d : dEnum) - { - m_entries.emplace_back(); - Entry& ent = m_entries.back(); - ent.m_path = d.m_path; - hecl::SystemUTF8Conv nameUtf8(d.m_name); - ent.m_name = nameUtf8.str(); - if (d.m_isDir) - { - if (hecl::SearchForProject(d.m_path)) - ent.m_type = m_projStr; - else - ent.m_type = m_dirStr; - } - else - { - ent.m_type = m_fileStr; - ent.m_size = hecl::HumanizeNumber(d.m_fileSz, 7, nullptr, int(hecl::HNScale::AutoScale), - hecl::HNFlags::B | hecl::HNFlags::Decimal); - } - } - - m_needsUpdate = false; - } - - bool m_needsUpdate = false; - - specter::SortDirection getSort(size_t& cIdx) const - { - cIdx = size_t(m_rb.m_state.sortColumn); - if (cIdx > 2) - cIdx = 0; - return m_rb.m_state.sortDir; - } - - void setSort(size_t cIdx, specter::SortDirection dir) - { - m_rb.m_state.sortDir = dir; - m_rb.m_state.sortColumn = State::SortColumn(cIdx); - m_needsUpdate = true; - } - - void setSelectedRow(size_t rIdx) - { - } - - void rowActivated(size_t rIdx) - { - } - - ResListingDataBind(ResourceBrowser& rb, const specter::IViewManager& vm) - : m_rb(rb) - { - m_nameCol = vm.translateOr("name", "Name"); - m_typeCol = vm.translateOr("type", "Type"); - m_sizeCol = vm.translateOr("size", "Size"); - m_dirStr = vm.translateOr("directory", "Directory"); - m_projStr = vm.translateOr("hecl_project", "HECL Project"); - m_fileStr = vm.translateOr("file", "File"); - } - - } m_resListingBind; - - struct View : specter::View - { - ResourceBrowser& m_ro; - specter::ViewChild> m_resListing; - - View(ResourceBrowser& ro, specter::ViewResources& res) - : specter::View(res, ro.m_vm.rootView()), m_ro(ro) - { - m_resListing.m_view.reset(new specter::Table(res, *this, &ro.m_resListingBind, &ro.m_resListingBind, 3)); - } - - void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); - void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); - void mouseMove(const boo::SWindowCoord&); - void mouseLeave(const boo::SWindowCoord&); - - void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); - void draw(boo::IGraphicsCommandQueue* gfxQ); + struct Entry { + hecl::SystemString m_path; + std::string m_name; + std::string m_type; + std::string m_size; }; - std::unique_ptr m_view; + std::vector m_entries; - std::unique_ptr m_pathButtons; + std::string m_nameCol; + std::string m_typeCol; + std::string m_sizeCol; + + std::string m_dirStr; + std::string m_projStr; + std::string m_fileStr; + + size_t columnCount() const { return 3; } + size_t rowCount() const { return m_entries.size(); } + + std::string_view header(size_t cIdx) const { + switch (cIdx) { + case 0: + return m_nameCol; + case 1: + return m_typeCol; + case 2: + return m_sizeCol; + default: + break; + } + return {}; + } + + std::string_view cell(size_t cIdx, size_t rIdx) const { + switch (cIdx) { + case 0: + return m_entries.at(rIdx).m_name; + case 1: + return m_entries.at(rIdx).m_type; + case 2: + return m_entries.at(rIdx).m_size; + default: + break; + } + return {}; + } + + bool columnSplitResizeAllowed() const { return true; } + + float getColumnSplit(size_t cIdx) const { return m_rb.m_state.columnSplits[cIdx]; } + + void setColumnSplit(size_t cIdx, float split) { m_rb.m_state.columnSplits[cIdx] = split; } + + void updateListing(const hecl::DirectoryEnumerator& dEnum) { + m_entries.clear(); + m_entries.reserve(dEnum.size()); + + for (const hecl::DirectoryEnumerator::Entry& d : dEnum) { + m_entries.emplace_back(); + Entry& ent = m_entries.back(); + ent.m_path = d.m_path; + hecl::SystemUTF8Conv nameUtf8(d.m_name); + ent.m_name = nameUtf8.str(); + if (d.m_isDir) { + if (hecl::SearchForProject(d.m_path)) + ent.m_type = m_projStr; + else + ent.m_type = m_dirStr; + } else { + ent.m_type = m_fileStr; + ent.m_size = hecl::HumanizeNumber(d.m_fileSz, 7, nullptr, int(hecl::HNScale::AutoScale), + hecl::HNFlags::B | hecl::HNFlags::Decimal); + } + } + + m_needsUpdate = false; + } + + bool m_needsUpdate = false; + + specter::SortDirection getSort(size_t& cIdx) const { + cIdx = size_t(m_rb.m_state.sortColumn); + if (cIdx > 2) + cIdx = 0; + return m_rb.m_state.sortDir; + } + + void setSort(size_t cIdx, specter::SortDirection dir) { + m_rb.m_state.sortDir = dir; + m_rb.m_state.sortColumn = State::SortColumn(cIdx); + m_needsUpdate = true; + } + + void setSelectedRow(size_t rIdx) {} + + void rowActivated(size_t rIdx) {} + + ResListingDataBind(ResourceBrowser& rb, const specter::IViewManager& vm) : m_rb(rb) { + m_nameCol = vm.translateOr("name", "Name"); + m_typeCol = vm.translateOr("type", "Type"); + m_sizeCol = vm.translateOr("size", "Size"); + m_dirStr = vm.translateOr("directory", "Directory"); + m_projStr = vm.translateOr("hecl_project", "HECL Project"); + m_fileStr = vm.translateOr("file", "File"); + } + + } m_resListingBind; + + struct View : specter::View { + ResourceBrowser& m_ro; + specter::ViewChild> m_resListing; + + View(ResourceBrowser& ro, specter::ViewResources& res) : specter::View(res, ro.m_vm.rootView()), m_ro(ro) { + m_resListing.m_view.reset(new specter::Table(res, *this, &ro.m_resListingBind, &ro.m_resListingBind, 3)); + } + + void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); + void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); + void mouseMove(const boo::SWindowCoord&); + void mouseLeave(const boo::SWindowCoord&); + + void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); + void draw(boo::IGraphicsCommandQueue* gfxQ); + }; + std::unique_ptr m_view; + + std::unique_ptr m_pathButtons; public: - ResourceBrowser(ViewManager& vm, Space* parent) - : Space(vm, Class::ResourceBrowser, parent), - m_resListingBind(*this, vm) - { - reloadState(); - } - ResourceBrowser(ViewManager& vm, Space* parent, const ResourceBrowser& other) - : ResourceBrowser(vm, parent) - { - m_state = other.m_state; - reloadState(); - } - ResourceBrowser(ViewManager& vm, Space* parent, ConfigReader& r) - : ResourceBrowser(vm, parent) - { - m_state.read(r); - reloadState(); - } + ResourceBrowser(ViewManager& vm, Space* parent) + : Space(vm, Class::ResourceBrowser, parent), m_resListingBind(*this, vm) { + reloadState(); + } + ResourceBrowser(ViewManager& vm, Space* parent, const ResourceBrowser& other) : ResourceBrowser(vm, parent) { + m_state = other.m_state; + reloadState(); + } + ResourceBrowser(ViewManager& vm, Space* parent, ConfigReader& r) : ResourceBrowser(vm, parent) { + m_state.read(r); + reloadState(); + } - void reloadState() - { - hecl::ProjectPath pp(*m_vm.project(), m_state.path); - if (m_state.path.empty() || pp.isNone()) - { - m_state.path = m_vm.project()->getProjectWorkingPath().getRelativePathUTF8(); - navigateToPath(hecl::ProjectPath(*m_vm.project(), m_state.path)); - } - else - navigateToPath(pp); - } + void reloadState() { + hecl::ProjectPath pp(*m_vm.project(), m_state.path); + if (m_state.path.empty() || pp.isNone()) { + m_state.path = m_vm.project()->getProjectWorkingPath().getRelativePathUTF8(); + navigateToPath(hecl::ProjectPath(*m_vm.project(), m_state.path)); + } else + navigateToPath(pp); + } - void think() - { - if (m_resListingBind.m_needsUpdate) - reloadState(); - } + void think() { + if (m_resListingBind.m_needsUpdate) + reloadState(); + } - bool navigateToPath(const hecl::ProjectPath& path); + bool navigateToPath(const hecl::ProjectPath& path); - Space* copy(Space* parent) const - { - return new ResourceBrowser(m_vm, parent, *this); - } + Space* copy(Space* parent) const { return new ResourceBrowser(m_vm, parent, *this); } - void buildToolbarView(specter::ViewResources &res, specter::Toolbar &tb) - { - m_pathButtons.reset(new specter::PathButtons(res, tb, *this, true)); - tb.push_back(m_pathButtons.get(), 1); - reloadState(); - } + void buildToolbarView(specter::ViewResources& res, specter::Toolbar& tb) { + m_pathButtons.reset(new specter::PathButtons(res, tb, *this, true)); + tb.push_back(m_pathButtons.get(), 1); + reloadState(); + } - specter::View* buildContentView(specter::ViewResources& res) - { - m_view.reset(new View(*this, res)); - return m_view.get(); - } + specter::View* buildContentView(specter::ViewResources& res) { + m_view.reset(new View(*this, res)); + return m_view.get(); + } - bool usesToolbar() const - { - return true; - } + bool usesToolbar() const { return true; } - unsigned toolbarUnits() const - { - return 2; - } + unsigned toolbarUnits() const { return 2; } }; -} - +} // namespace urde diff --git a/Editor/Space.cpp b/Editor/Space.cpp index 208bf5b21..b2d5a07cd 100644 --- a/Editor/Space.cpp +++ b/Editor/Space.cpp @@ -8,273 +8,244 @@ #include "icons/icons.hpp" #include "specter/Menu.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("URDE::Space"); Space::Space(ViewManager& vm, Class cls, Space* parent) -: m_spaceMenuNode(*this), m_spaceSelectBind(*this), - m_vm(vm), m_class(cls), m_parent(parent) {} +: m_spaceMenuNode(*this), m_spaceSelectBind(*this), m_vm(vm), m_class(cls), m_parent(parent) {} -specter::View* Space::buildSpaceView(specter::ViewResources& res) -{ - if (usesToolbar()) - { - m_spaceView.reset(new specter::Space(res, *m_parent->basisView(), *this, specter::Toolbar::Position::Bottom, toolbarUnits())); - specter::View* sview = buildContentView(res); - m_spaceView->setContentView(sview); - specter::Toolbar& tb = *m_spaceView->toolbar(); - specter::Icon* classIcon = SpaceMenuNode::LookupClassIcon(m_class); - const zeus::CColor* classColor = SpaceMenuNode::LookupClassColor(m_class); - m_spaceSelectButton.reset(new specter::Button(res, tb, &m_spaceSelectBind, "", classIcon, - specter::Button::Style::Block, - classColor?*classColor:zeus::CColor::skWhite)); - tb.push_back(m_spaceSelectButton.get(), 0); - buildToolbarView(res, tb); - return m_spaceView.get(); - } - else - { - m_spaceView.reset(new specter::Space(res, *m_parent->basisView(), *this, specter::Toolbar::Position::None, 0)); - specter::View* sview = buildContentView(res); - m_spaceView->setContentView(sview); - return m_spaceView.get(); - } +specter::View* Space::buildSpaceView(specter::ViewResources& res) { + if (usesToolbar()) { + m_spaceView.reset( + new specter::Space(res, *m_parent->basisView(), *this, specter::Toolbar::Position::Bottom, toolbarUnits())); + specter::View* sview = buildContentView(res); + m_spaceView->setContentView(sview); + specter::Toolbar& tb = *m_spaceView->toolbar(); + specter::Icon* classIcon = SpaceMenuNode::LookupClassIcon(m_class); + const zeus::CColor* classColor = SpaceMenuNode::LookupClassColor(m_class); + m_spaceSelectButton.reset(new specter::Button(res, tb, &m_spaceSelectBind, "", classIcon, + specter::Button::Style::Block, + classColor ? *classColor : zeus::CColor::skWhite)); + tb.push_back(m_spaceSelectButton.get(), 0); + buildToolbarView(res, tb); + return m_spaceView.get(); + } else { + m_spaceView.reset(new specter::Space(res, *m_parent->basisView(), *this, specter::Toolbar::Position::None, 0)); + specter::View* sview = buildContentView(res); + m_spaceView->setContentView(sview); + return m_spaceView.get(); + } } -std::vector Space::SpaceMenuNode::s_subNodeDats = -{ - {Class::ResourceBrowser, "resource_browser", "Resource Browser", GetIcon(SpaceIcon::ResourceBrowser), {0.0f, 1.0f, 0.0f, 1.0f}}, - {Class::EffectEditor, "effect_editor", "Effect Editor", GetIcon(SpaceIcon::ParticleEditor), {1.0f, 0.5f, 0.0f, 1.0f}}, +std::vector Space::SpaceMenuNode::s_subNodeDats = { + {Class::ResourceBrowser, + "resource_browser", + "Resource Browser", + GetIcon(SpaceIcon::ResourceBrowser), + {0.0f, 1.0f, 0.0f, 1.0f}}, + {Class::EffectEditor, + "effect_editor", + "Effect Editor", + GetIcon(SpaceIcon::ParticleEditor), + {1.0f, 0.5f, 0.0f, 1.0f}}, {Class::ModelViewer, "model_viewer", "Model Viewer", GetIcon(SpaceIcon::ModelViewer), {0.95f, 0.95f, 0.95f, 1.0f}}, - {Class::InformationCenter, "information_center", "Information Center", GetIcon(SpaceIcon::InformationCenter), {0.0f, 1.0f, 1.0f, 1.0f}}, - {Class::GameMode, "game_mode", "Game Mode", GetIcon(SpaceIcon::GameMode), {}} -}; + {Class::InformationCenter, + "information_center", + "Information Center", + GetIcon(SpaceIcon::InformationCenter), + {0.0f, 1.0f, 1.0f, 1.0f}}, + {Class::GameMode, "game_mode", "Game Mode", GetIcon(SpaceIcon::GameMode), {}}}; std::string Space::SpaceMenuNode::s_text = "Space Types"; -void Space::SpaceMenuNode::InitializeStrings(ViewManager& vm) -{ - s_text = vm.translateOr("space_types", s_text.c_str()); - for (SubNodeData& sn : s_subNodeDats) - sn.m_text = vm.translateOr(sn.m_key, sn.m_text.c_str()); +void Space::SpaceMenuNode::InitializeStrings(ViewManager& vm) { + s_text = vm.translateOr("space_types", s_text.c_str()); + for (SubNodeData& sn : s_subNodeDats) + sn.m_text = vm.translateOr(sn.m_key, sn.m_text.c_str()); } -std::unique_ptr Space::SpaceSelectBind::buildMenu(const specter::Button* button) -{ - return std::unique_ptr(new specter::Menu(m_space.m_vm.rootView().viewRes(), - *m_space.m_spaceView, &m_space.m_spaceMenuNode)); +std::unique_ptr Space::SpaceSelectBind::buildMenu(const specter::Button* button) { + return std::unique_ptr( + new specter::Menu(m_space.m_vm.rootView().viewRes(), *m_space.m_spaceView, &m_space.m_spaceMenuNode)); } -specter::View* RootSpace::buildSpaceView(specter::ViewResources& res) -{ - specter::View* newRoot = buildContentView(res); - m_vm.RootSpaceViewBuilt(newRoot); - return newRoot; +specter::View* RootSpace::buildSpaceView(specter::ViewResources& res) { + specter::View* newRoot = buildContentView(res); + m_vm.RootSpaceViewBuilt(newRoot); + return newRoot; } -specter::View* RootSpace::basisView() {return &m_vm.rootView();} +specter::View* RootSpace::basisView() { return &m_vm.rootView(); } -specter::View* SplitSpace::buildContentView(specter::ViewResources& res) -{ - int clearance = res.pixelFactor() * SPECTER_TOOLBAR_GAUGE; - m_splitView.reset(new specter::SplitView(res, *m_parent->basisView(), this, m_state.axis, - m_state.split, clearance, clearance)); - if (m_slots[0]) - m_splitView->setContentView(0, m_slots[0]->buildSpaceView(res)); - if (m_slots[1]) - m_splitView->setContentView(1, m_slots[1]->buildSpaceView(res)); - return m_splitView.get(); +specter::View* SplitSpace::buildContentView(specter::ViewResources& res) { + int clearance = res.pixelFactor() * SPECTER_TOOLBAR_GAUGE; + m_splitView.reset( + new specter::SplitView(res, *m_parent->basisView(), this, m_state.axis, m_state.split, clearance, clearance)); + if (m_slots[0]) + m_splitView->setContentView(0, m_slots[0]->buildSpaceView(res)); + if (m_slots[1]) + m_splitView->setContentView(1, m_slots[1]->buildSpaceView(res)); + return m_splitView.get(); } -void SplitSpace::setChildSlot(unsigned slot, std::unique_ptr&& space) -{ - if (slot > 1) - Log.report(logvisor::Fatal, "invalid slot %u for SplitView", slot); - m_slots[slot] = std::move(space); - m_slots[slot]->m_parent = this; +void SplitSpace::setChildSlot(unsigned slot, std::unique_ptr&& space) { + if (slot > 1) + Log.report(logvisor::Fatal, "invalid slot %u for SplitView", slot); + m_slots[slot] = std::move(space); + m_slots[slot]->m_parent = this; } -void SplitSpace::joinViews(specter::SplitView* thisSplit, int thisSlot, specter::SplitView* otherSplit, int otherSlot) -{ - if (thisSplit == otherSplit) - { - SplitSpace* thisSS = m_slots[thisSlot]->castToSplitSpace(); - if (thisSS) - { - int ax = thisSS->m_state.axis == specter::SplitView::Axis::Horizontal ? 1 : 0; - const boo::SWindowRect& thisRect = m_splitView->subRect(); - const boo::SWindowRect& subRect = thisSS->m_splitView->subRect(); - int splitPx = subRect.location[ax] + subRect.size[ax] * thisSS->m_state.split - - thisRect.location[ax]; - thisSS->m_state.split = splitPx / float(thisRect.size[ax]); - } - m_parent->exchangeSpaceSplitJoin(this, std::move(m_slots[thisSlot])); +void SplitSpace::joinViews(specter::SplitView* thisSplit, int thisSlot, specter::SplitView* otherSplit, int otherSlot) { + if (thisSplit == otherSplit) { + SplitSpace* thisSS = m_slots[thisSlot]->castToSplitSpace(); + if (thisSS) { + int ax = thisSS->m_state.axis == specter::SplitView::Axis::Horizontal ? 1 : 0; + const boo::SWindowRect& thisRect = m_splitView->subRect(); + const boo::SWindowRect& subRect = thisSS->m_splitView->subRect(); + int splitPx = subRect.location[ax] + subRect.size[ax] * thisSS->m_state.split - thisRect.location[ax]; + thisSS->m_state.split = splitPx / float(thisRect.size[ax]); + } + m_parent->exchangeSpaceSplitJoin(this, std::move(m_slots[thisSlot])); + m_vm.BuildSpaceViews(); + } else { + for (int i = 0; i < 2; ++i) { + SplitSpace* otherSS = m_slots[i]->castToSplitSpace(); + if (otherSS && otherSS->m_splitView.get() == otherSplit) { + int ax = m_state.axis == specter::SplitView::Axis::Horizontal ? 1 : 0; + const boo::SWindowRect& thisRect = m_splitView->subRect(); + const boo::SWindowRect& subRect = otherSS->m_splitView->subRect(); + int splitPx = subRect.location[ax] + subRect.size[ax] * otherSS->m_state.split - thisRect.location[ax]; + m_state.split = splitPx / float(thisRect.size[ax]); + exchangeSpaceSplitJoin(otherSS, std::move(otherSS->m_slots[otherSlot ^ 1])); m_vm.BuildSpaceViews(); + break; + } } - else - { - for (int i=0 ; i<2 ; ++i) - { - SplitSpace* otherSS = m_slots[i]->castToSplitSpace(); - if (otherSS && otherSS->m_splitView.get() == otherSplit) - { - int ax = m_state.axis == specter::SplitView::Axis::Horizontal ? 1 : 0; - const boo::SWindowRect& thisRect = m_splitView->subRect(); - const boo::SWindowRect& subRect = otherSS->m_splitView->subRect(); - int splitPx = subRect.location[ax] + subRect.size[ax] * otherSS->m_state.split - - thisRect.location[ax]; - m_state.split = splitPx / float(thisRect.size[ax]); - exchangeSpaceSplitJoin(otherSS, std::move(otherSS->m_slots[otherSlot ^ 1])); - m_vm.BuildSpaceViews(); - break; - } - } - } + } } -specter::ISplitSpaceController* Space::spaceSplit(specter::SplitView::Axis axis, int thisSlot) -{ - if (m_parent) - { - /* Reject split operations with insufficient clearance */ - int clearance = m_vm.m_viewResources.pixelFactor() * SPECTER_TOOLBAR_GAUGE; - if (axis == specter::SplitView::Axis::Horizontal) - { - if (m_spaceView->subRect().size[1] <= clearance) - return nullptr; - } - else - { - if (m_spaceView->subRect().size[0] <= clearance) - return nullptr; - } - - SplitSpace* ss = new SplitSpace(m_vm, m_parent, axis); - ss->setChildSlot(thisSlot, m_parent->exchangeSpaceSplitJoin(this, std::unique_ptr(ss))); - ss->setChildSlot(thisSlot ^ 1, std::unique_ptr(copy(ss))); - m_vm.BuildSpaceViews(); - return ss; +specter::ISplitSpaceController* Space::spaceSplit(specter::SplitView::Axis axis, int thisSlot) { + if (m_parent) { + /* Reject split operations with insufficient clearance */ + int clearance = m_vm.m_viewResources.pixelFactor() * SPECTER_TOOLBAR_GAUGE; + if (axis == specter::SplitView::Axis::Horizontal) { + if (m_spaceView->subRect().size[1] <= clearance) + return nullptr; + } else { + if (m_spaceView->subRect().size[0] <= clearance) + return nullptr; } - return nullptr; + + SplitSpace* ss = new SplitSpace(m_vm, m_parent, axis); + ss->setChildSlot(thisSlot, m_parent->exchangeSpaceSplitJoin(this, std::unique_ptr(ss))); + ss->setChildSlot(thisSlot ^ 1, std::unique_ptr(copy(ss))); + m_vm.BuildSpaceViews(); + return ss; + } + return nullptr; } -std::unique_ptr RootSpace::exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace) -{ - std::unique_ptr ret = std::move(keepSpace); +std::unique_ptr RootSpace::exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace) { + std::unique_ptr ret = std::move(keepSpace); - if (removeSpace == m_spaceTree.get()) - { - m_spaceTree.swap(ret); - m_spaceTree->m_parent = this; - } - else - Log.report(logvisor::Fatal, "RootSpace::exchangeSpaceSplitJoin() failure"); + if (removeSpace == m_spaceTree.get()) { + m_spaceTree.swap(ret); + m_spaceTree->m_parent = this; + } else + Log.report(logvisor::Fatal, "RootSpace::exchangeSpaceSplitJoin() failure"); - return ret; + return ret; } -std::unique_ptr SplitSpace::exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace) -{ - std::unique_ptr ret = std::move(keepSpace); +std::unique_ptr SplitSpace::exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace) { + std::unique_ptr ret = std::move(keepSpace); - if (removeSpace == m_slots[0].get()) - { - m_slots[0].swap(ret); - m_slots[0]->m_parent = this; - } - else if (removeSpace == m_slots[1].get()) - { - m_slots[1].swap(ret); - m_slots[1]->m_parent = this; - } - else - Log.report(logvisor::Fatal, "SplitSpace::exchangeSpaceSplitJoin() failure"); + if (removeSpace == m_slots[0].get()) { + m_slots[0].swap(ret); + m_slots[0]->m_parent = this; + } else if (removeSpace == m_slots[1].get()) { + m_slots[1].swap(ret); + m_slots[1]->m_parent = this; + } else + Log.report(logvisor::Fatal, "SplitSpace::exchangeSpaceSplitJoin() failure"); - return ret; + return ret; } template -static Space* BuildNewSpace(ViewManager& vm, Space::Class cls, Space* parent, Reader& r) -{ - using Class = Space::Class; - switch (cls) - { - case Class::SplitSpace: - return new SplitSpace(vm, parent, r); - case Class::ResourceBrowser: - return new ResourceBrowser(vm, parent, r); - case Class::EffectEditor: - return new EffectEditor(vm, parent, r); - case Class::ModelViewer: - return new ModelViewer(vm, parent, r); - case Class::InformationCenter: - return new InformationCenter(vm, parent, r); - case Class::GameMode: - return new GameMode(vm, parent, r); - default: break; - } +static Space* BuildNewSpace(ViewManager& vm, Space::Class cls, Space* parent, Reader& r) { + using Class = Space::Class; + switch (cls) { + case Class::SplitSpace: + return new SplitSpace(vm, parent, r); + case Class::ResourceBrowser: + return new ResourceBrowser(vm, parent, r); + case Class::EffectEditor: + return new EffectEditor(vm, parent, r); + case Class::ModelViewer: + return new ModelViewer(vm, parent, r); + case Class::InformationCenter: + return new InformationCenter(vm, parent, r); + case Class::GameMode: + return new GameMode(vm, parent, r); + default: + break; + } + return nullptr; +} + +void Space::saveState(athena::io::IStreamWriter& w) const { + w.writeUint32Big(atUint32(m_class)); + spaceState().write(w); +} + +void Space::saveState(athena::io::YAMLDocWriter& w) const { + w.writeUint32("class", atUint32(m_class)); + spaceState().write(w); +} + +Space* Space::NewSpaceFromConfigStream(ViewManager& vm, Space* parent, ConfigReader& r) { + Class cls = Class(r.readUint32("class")); + return BuildNewSpace(vm, cls, parent, r); +} + +RootSpace* Space::NewRootSpaceFromConfigStream(ViewManager& vm, ConfigReader& r) { + Class cls = Class(r.readUint32("class")); + if (cls != Class::RootSpace) return nullptr; + return new RootSpace(vm, r); } -void Space::saveState(athena::io::IStreamWriter& w) const -{ - w.writeUint32Big(atUint32(m_class)); - spaceState().write(w); +void Space::SpaceMenuNode::SubNode::activated(const boo::SWindowCoord& coord) { + std::unique_ptr newSpace; + switch (m_data.m_cls) { + case Class::InformationCenter: + if (m_space.cls() == Class::InformationCenter) + newSpace.reset(new InformationCenter(m_space.m_parent->m_vm, m_space.m_parent)); + break; + case Class::EffectEditor: + if (m_space.cls() == Class::EffectEditor) + newSpace.reset(new EffectEditor(m_space.m_parent->m_vm, m_space.m_parent)); + break; + case Class::ResourceBrowser: + if (m_space.cls() == Class::ResourceBrowser) + newSpace.reset(new ResourceBrowser(m_space.m_parent->m_vm, m_space.m_parent)); + break; + case Class::ModelViewer: + if (m_space.cls() == Class::ModelViewer) + newSpace.reset(new ModelViewer(m_space.m_parent->m_vm, m_space.m_parent)); + break; + case Class::GameMode: + if (m_space.cls() == Class::GameMode) + newSpace.reset(new GameMode(m_space.m_parent->m_vm, m_space.m_parent)); + break; + default: + break; + } + if (newSpace) { + Space* parent = m_space.m_parent; + m_space.m_parent->exchangeSpaceSplitJoin(&m_space, std::move(newSpace)); + parent->m_vm.BuildSpaceViews(); + } } -void Space::saveState(athena::io::YAMLDocWriter& w) const -{ - w.writeUint32("class", atUint32(m_class)); - spaceState().write(w); -} - -Space* Space::NewSpaceFromConfigStream(ViewManager& vm, Space* parent, ConfigReader& r) -{ - Class cls = Class(r.readUint32("class")); - return BuildNewSpace(vm, cls, parent, r); -} - -RootSpace* Space::NewRootSpaceFromConfigStream(ViewManager& vm, ConfigReader& r) -{ - Class cls = Class(r.readUint32("class")); - if (cls != Class::RootSpace) - return nullptr; - return new RootSpace(vm, r); -} - -void Space::SpaceMenuNode::SubNode::activated(const boo::SWindowCoord &coord) -{ - std::unique_ptr newSpace; - switch(m_data.m_cls) - { - case Class::InformationCenter: - if (m_space.cls() == Class::InformationCenter) - newSpace.reset(new InformationCenter(m_space.m_parent->m_vm, m_space.m_parent)); - break; - case Class::EffectEditor: - if (m_space.cls() == Class::EffectEditor) - newSpace.reset(new EffectEditor(m_space.m_parent->m_vm, m_space.m_parent)); - break; - case Class::ResourceBrowser: - if (m_space.cls() == Class::ResourceBrowser) - newSpace.reset(new ResourceBrowser(m_space.m_parent->m_vm, m_space.m_parent)); - break; - case Class::ModelViewer: - if (m_space.cls() == Class::ModelViewer) - newSpace.reset(new ModelViewer(m_space.m_parent->m_vm, m_space.m_parent)); - break; - case Class::GameMode: - if (m_space.cls() == Class::GameMode) - newSpace.reset(new GameMode(m_space.m_parent->m_vm, m_space.m_parent)); - break; - default: break; - } - if (newSpace) - { - Space* parent = m_space.m_parent; - m_space.m_parent->exchangeSpaceSplitJoin(&m_space, std::move(newSpace)); - parent->m_vm.BuildSpaceViews(); - } -} - -} +} // namespace urde diff --git a/Editor/Space.hpp b/Editor/Space.hpp index dd588999b..76577be54 100644 --- a/Editor/Space.hpp +++ b/Editor/Space.hpp @@ -9,420 +9,370 @@ #include "specter/RootView.hpp" #include "ProjectManager.hpp" -namespace specter -{ +namespace specter { class View; class SplitView; class ViewResources; class Toolbar; struct Icon; -} -namespace urde -{ +} // namespace specter +namespace urde { class ViewManager; class RootSpace; class SplitSpace; -class Space : public specter::ISpaceController -{ - friend class SplitSpace; +class Space : public specter::ISpaceController { + friend class SplitSpace; + public: - virtual ~Space() = default; - Space(const Space& other) = delete; - Space& operator=(const Space& other) = delete; + virtual ~Space() = default; + Space(const Space& other) = delete; + Space& operator=(const Space& other) = delete; - /** Common encoded-enumeration for all space classes */ - enum class Class - { - None, - RootSpace, - SplitSpace, - TestSpace, - ResourceBrowser, - ModelViewer, - EffectEditor, - InformationCenter, - GameMode + /** Common encoded-enumeration for all space classes */ + enum class Class { + None, + RootSpace, + SplitSpace, + TestSpace, + ResourceBrowser, + ModelViewer, + EffectEditor, + InformationCenter, + GameMode + }; + + struct State : athena::io::DNAVYaml { + Delete _d; + }; + static Space* NewSpaceFromConfigStream(ViewManager& vm, Space* parent, ConfigReader& r); + static RootSpace* NewRootSpaceFromConfigStream(ViewManager& vm, ConfigReader& r); + + struct SpaceMenuNode final : specter::IMenuNode { + struct SubNodeData final : specter::IMenuNode { + Class m_cls; + std::string m_key; + std::string m_text; + specter::Icon& m_icon; + zeus::CColor m_color; + const std::string* text() const { return &m_text; } + void activated(const boo::SWindowCoord& coord) {} + + SubNodeData(Class cls, const char* key, const char* text, specter::Icon& icon, const zeus::CColor& color) + : m_cls(cls), m_key(key), m_text(text), m_icon(icon), m_color(color) {} }; + static std::vector s_subNodeDats; - struct State : athena::io::DNAVYaml {Delete _d;}; - static Space* NewSpaceFromConfigStream(ViewManager& vm, Space* parent, ConfigReader& r); - static RootSpace* NewRootSpaceFromConfigStream(ViewManager& vm, ConfigReader& r); + struct SubNode final : specter::IMenuNode { + Space& m_space; + const SubNodeData& m_data; + const std::string* text() const { return &m_data.m_text; } + void activated(const boo::SWindowCoord& coord); - struct SpaceMenuNode final : specter::IMenuNode - { - struct SubNodeData final : specter::IMenuNode - { - Class m_cls; - std::string m_key; - std::string m_text; - specter::Icon& m_icon; - zeus::CColor m_color; - const std::string* text() const {return &m_text;} - void activated(const boo::SWindowCoord& coord) {} + SubNode(Space& space, const SubNodeData& data) : m_space(space), m_data(data) {} + }; + std::vector m_subNodes; - SubNodeData(Class cls, const char* key, const char* text, specter::Icon& icon, const zeus::CColor& color) - : m_cls(cls), m_key(key), m_text(text), m_icon(icon), m_color(color) {} - }; - static std::vector s_subNodeDats; + SpaceMenuNode(Space& space) { + m_subNodes.reserve(s_subNodeDats.size()); + for (const SubNodeData& sn : s_subNodeDats) + m_subNodes.emplace_back(space, sn); + } - struct SubNode final : specter::IMenuNode - { - Space& m_space; - const SubNodeData& m_data; - const std::string* text() const {return &m_data.m_text;} - void activated(const boo::SWindowCoord& coord); + static std::string s_text; + const std::string* text() const { return &s_text; } - SubNode(Space& space, const SubNodeData& data) : m_space(space), m_data(data) {} - }; - std::vector m_subNodes; + size_t subNodeCount() const { return m_subNodes.size(); } + IMenuNode* subNode(size_t idx) { return &m_subNodes[idx]; } - SpaceMenuNode(Space& space) - { - m_subNodes.reserve(s_subNodeDats.size()); - for (const SubNodeData& sn : s_subNodeDats) - m_subNodes.emplace_back(space, sn); - } + static void InitializeStrings(ViewManager& vm); + static const std::string* LookupClassString(Class cls) { + for (const SubNodeData& sn : s_subNodeDats) + if (sn.m_cls == cls) + return &sn.m_text; + return nullptr; + } + static specter::Icon* LookupClassIcon(Class cls) { + for (SubNodeData& sn : s_subNodeDats) + if (sn.m_cls == cls) + return &sn.m_icon; + return nullptr; + } + static const zeus::CColor* LookupClassColor(Class cls) { + for (SubNodeData& sn : s_subNodeDats) + if (sn.m_cls == cls) + return &sn.m_color; + return nullptr; + } + } m_spaceMenuNode; - static std::string s_text; - const std::string* text() const {return &s_text;} + struct SpaceSelectBind : specter::IButtonBinding { + Space& m_space; + std::string_view name(const specter::Control* control) const { return SpaceMenuNode::s_text; } - size_t subNodeCount() const {return m_subNodes.size();} - IMenuNode* subNode(size_t idx) {return &m_subNodes[idx];} + MenuStyle menuStyle(const specter::Button* button) const { return MenuStyle::Primary; } + std::unique_ptr buildMenu(const specter::Button* button); - static void InitializeStrings(ViewManager& vm); - static const std::string* LookupClassString(Class cls) - { - for (const SubNodeData& sn : s_subNodeDats) - if (sn.m_cls == cls) - return &sn.m_text; - return nullptr; - } - static specter::Icon* LookupClassIcon(Class cls) - { - for (SubNodeData& sn : s_subNodeDats) - if (sn.m_cls == cls) - return &sn.m_icon; - return nullptr; - } - static const zeus::CColor* LookupClassColor(Class cls) - { - for (SubNodeData& sn : s_subNodeDats) - if (sn.m_cls == cls) - return &sn.m_color; - return nullptr; - } - } m_spaceMenuNode; - - struct SpaceSelectBind : specter::IButtonBinding - { - Space& m_space; - std::string_view name(const specter::Control* control) const {return SpaceMenuNode::s_text;} - - MenuStyle menuStyle(const specter::Button* button) const {return MenuStyle::Primary;} - std::unique_ptr buildMenu(const specter::Button* button); - - SpaceSelectBind(Space& space) : m_space(space) {} - } m_spaceSelectBind; - std::unique_ptr m_spaceSelectButton; + SpaceSelectBind(Space& space) : m_space(space) {} + } m_spaceSelectBind; + std::unique_ptr m_spaceSelectButton; protected: - friend class ViewManager; - friend class RootSpace; - ViewManager& m_vm; - Class m_class = Class::None; - Space* m_parent; - std::unique_ptr m_spaceView; - Space(ViewManager& vm, Class cls, Space* parent); + friend class ViewManager; + friend class RootSpace; + ViewManager& m_vm; + Class m_class = Class::None; + Space* m_parent; + std::unique_ptr m_spaceView; + Space(ViewManager& vm, Class cls, Space* parent); - /* Allows common Space code to access DNA-encoded state */ - virtual const Space::State& spaceState() const=0; + /* Allows common Space code to access DNA-encoded state */ + virtual const Space::State& spaceState() const = 0; - /* Structural control */ - virtual bool usesToolbar() const {return false;} - virtual unsigned toolbarUnits() const {return 1;} - virtual void buildToolbarView(specter::ViewResources& res, specter::Toolbar& tb) {} - virtual specter::View* buildContentView(specter::ViewResources& res)=0; - virtual specter::View* buildSpaceView(specter::ViewResources& res); + /* Structural control */ + virtual bool usesToolbar() const { return false; } + virtual unsigned toolbarUnits() const { return 1; } + virtual void buildToolbarView(specter::ViewResources& res, specter::Toolbar& tb) {} + virtual specter::View* buildContentView(specter::ViewResources& res) = 0; + virtual specter::View* buildSpaceView(specter::ViewResources& res); public: - virtual void saveState(athena::io::IStreamWriter& w) const; - virtual void saveState(athena::io::YAMLDocWriter& w) const; - virtual void reloadState() {} + virtual void saveState(athena::io::IStreamWriter& w) const; + virtual void saveState(athena::io::YAMLDocWriter& w) const; + virtual void reloadState() {} - virtual void think() {} + virtual void think() {} - virtual Space* copy(Space* parent) const=0; - bool spaceSplitAllowed() const {return true;} + virtual Space* copy(Space* parent) const = 0; + bool spaceSplitAllowed() const { return true; } - specter::ISplitSpaceController* spaceSplit(specter::SplitView::Axis axis, int thisSlot); - virtual std::unique_ptr exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace) - {return std::unique_ptr();} + specter::ISplitSpaceController* spaceSplit(specter::SplitView::Axis axis, int thisSlot); + virtual std::unique_ptr exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace) { + return std::unique_ptr(); + } - virtual specter::View* basisView() {return m_spaceView.get();} - Class cls() const { return m_class; } - SplitSpace* castToSplitSpace(); + virtual specter::View* basisView() { return m_spaceView.get(); } + Class cls() const { return m_class; } + SplitSpace* castToSplitSpace(); }; -class RootSpace : public Space -{ - friend class ViewManager; - std::unique_ptr m_rootView; - std::unique_ptr m_spaceTree; - struct State : Space::State - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - } m_state; - const Space::State& spaceState() const {return m_state;} +class RootSpace : public Space { + friend class ViewManager; + std::unique_ptr m_rootView; + std::unique_ptr m_spaceTree; + struct State : Space::State{AT_DECL_DNA_YAML AT_DECL_DNAV} m_state; + const Space::State& spaceState() const { return m_state; } public: - RootSpace(ViewManager& vm) : Space(vm, Class::RootSpace, nullptr) {} - RootSpace(ViewManager& vm, ConfigReader& r) - : RootSpace(vm) - { - m_state.read(r); - if (auto rec = r.enterSubRecord("spaceTree")) - m_spaceTree.reset(NewSpaceFromConfigStream(vm, this, r)); + RootSpace(ViewManager& vm) : Space(vm, Class::RootSpace, nullptr) {} + RootSpace(ViewManager& vm, ConfigReader& r) : RootSpace(vm) { + m_state.read(r); + if (auto rec = r.enterSubRecord("spaceTree")) + m_spaceTree.reset(NewSpaceFromConfigStream(vm, this, r)); + } + + void think() { + if (m_spaceTree) + m_spaceTree->think(); + } + + void saveState(athena::io::IStreamWriter& w) const { + w.writeUint32Big(atUint32(m_class)); + m_state.write(w); + + if (m_spaceTree) + m_spaceTree->saveState(w); + else + w.writeUint32Big(0); + } + + void saveState(athena::io::YAMLDocWriter& w) const { + w.writeUint32("class", atUint32(m_class)); + m_state.write(w); + + if (auto rec = w.enterSubRecord("spaceTree")) { + if (m_spaceTree) + m_spaceTree->saveState(w); + else + w.writeUint32("class", 0); } + } - void think() - { - if (m_spaceTree) - m_spaceTree->think(); - } + void setChild(std::unique_ptr&& space) { + m_spaceTree = std::move(space); + m_spaceTree->m_parent = this; + } - void saveState(athena::io::IStreamWriter& w) const - { - w.writeUint32Big(atUint32(m_class)); - m_state.write(w); + Space* copy(Space* parent) const { return nullptr; } + bool spaceSplitAllowed() const { return false; } - if (m_spaceTree) - m_spaceTree->saveState(w); - else - w.writeUint32Big(0); - } + specter::View* buildSpaceView(specter::ViewResources& res); + specter::View* buildContentView(specter::ViewResources& res) { return m_spaceTree->buildSpaceView(res); } - void saveState(athena::io::YAMLDocWriter& w) const - { - w.writeUint32("class", atUint32(m_class)); - m_state.write(w); + std::unique_ptr exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace); - if (auto rec = w.enterSubRecord("spaceTree")) - { - if (m_spaceTree) - m_spaceTree->saveState(w); - else - w.writeUint32("class", 0); - } - } - - void setChild(std::unique_ptr&& space) - { - m_spaceTree = std::move(space); - m_spaceTree->m_parent = this; - } - - Space* copy(Space* parent) const {return nullptr;} - bool spaceSplitAllowed() const {return false;} - - specter::View* buildSpaceView(specter::ViewResources& res); - specter::View* buildContentView(specter::ViewResources& res) {return m_spaceTree->buildSpaceView(res);} - - std::unique_ptr exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace); - - specter::View* basisView(); + specter::View* basisView(); }; -class SplitSpace : public Space, public specter::ISplitSpaceController -{ - friend class ViewManager; - std::unique_ptr m_slots[2]; - std::unique_ptr m_splitView; - struct State : Space::State - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - Value axis = specter::SplitView::Axis::Horizontal; - Value split = 0.5; - } m_state; - const Space::State& spaceState() const {return m_state;} +class SplitSpace : public Space, public specter::ISplitSpaceController { + friend class ViewManager; + std::unique_ptr m_slots[2]; + std::unique_ptr m_splitView; + struct State : Space::State { + AT_DECL_DNA_YAML + AT_DECL_DNAV + Value axis = specter::SplitView::Axis::Horizontal; + Value split = 0.5; + } m_state; + const Space::State& spaceState() const { return m_state; } public: - SplitSpace(ViewManager& vm, Space* parent, specter::SplitView::Axis axis) : Space(vm, Class::SplitSpace, parent) - { - m_state.axis = axis; - reloadState(); + SplitSpace(ViewManager& vm, Space* parent, specter::SplitView::Axis axis) : Space(vm, Class::SplitSpace, parent) { + m_state.axis = axis; + reloadState(); + } + SplitSpace(ViewManager& vm, Space* parent, ConfigReader& r) + : SplitSpace(vm, parent, specter::SplitView::Axis::Horizontal) { + m_state.read(r); + if (auto rec = r.enterSubRecord("slot0")) + m_slots[0].reset(NewSpaceFromConfigStream(vm, this, r)); + if (auto rec = r.enterSubRecord("slot1")) + m_slots[1].reset(NewSpaceFromConfigStream(vm, this, r)); + reloadState(); + } + + void reloadState() { + m_state.split = std::min(1.f, std::max(0.f, m_state.split)); + if (m_state.axis != specter::SplitView::Axis::Horizontal && m_state.axis != specter::SplitView::Axis::Vertical) + m_state.axis = specter::SplitView::Axis::Horizontal; + if (m_splitView) { + m_splitView->setSplit(m_state.split); + m_splitView->setAxis(m_state.axis); } - SplitSpace(ViewManager& vm, Space* parent, ConfigReader& r) - : SplitSpace(vm, parent, specter::SplitView::Axis::Horizontal) - { - m_state.read(r); - if (auto rec = r.enterSubRecord("slot0")) - m_slots[0].reset(NewSpaceFromConfigStream(vm, this, r)); - if (auto rec = r.enterSubRecord("slot1")) - m_slots[1].reset(NewSpaceFromConfigStream(vm, this, r)); - reloadState(); + } + + void think() { + if (m_slots[0]) + m_slots[0]->think(); + if (m_slots[1]) + m_slots[1]->think(); + } + + void saveState(athena::io::IStreamWriter& w) const { + w.writeUint32Big(atUint32(m_class)); + m_state.write(w); + + if (m_slots[0]) + m_slots[0]->saveState(w); + else + w.writeUint32Big(0); + + if (m_slots[1]) + m_slots[1]->saveState(w); + else + w.writeUint32Big(0); + } + + void saveState(athena::io::YAMLDocWriter& w) const { + w.writeUint32("class", atUint32(m_class)); + m_state.write(w); + + if (auto rec = w.enterSubRecord("slot0")) { + if (m_slots[0]) + m_slots[0]->saveState(w); + else + w.writeUint32("class", 0); } - void reloadState() - { - m_state.split = std::min(1.f, std::max(0.f, m_state.split)); - if (m_state.axis != specter::SplitView::Axis::Horizontal && - m_state.axis != specter::SplitView::Axis::Vertical) - m_state.axis = specter::SplitView::Axis::Horizontal; - if (m_splitView) - { - m_splitView->setSplit(m_state.split); - m_splitView->setAxis(m_state.axis); - } + if (auto rec = w.enterSubRecord("slot1")) { + if (m_slots[1]) + m_slots[1]->saveState(w); + else + w.writeUint32("class", 0); } + } - void think() - { - if (m_slots[0]) - m_slots[0]->think(); - if (m_slots[1]) - m_slots[1]->think(); + void setChildSlot(unsigned slot, std::unique_ptr&& space); + + specter::View* buildSpaceView(specter::ViewResources& res) { return buildContentView(res); } + specter::View* buildContentView(specter::ViewResources& res); + + Space* copy(Space* parent) const { return nullptr; } + bool spaceSplitAllowed() const { return false; } + + ISpaceController* spaceJoin(int keepSlot) { + if (m_parent) { + ISpaceController* ret = m_slots[keepSlot].get(); + m_parent->exchangeSpaceSplitJoin(this, std::move(m_slots[keepSlot])); + return ret; } + return nullptr; + } - void saveState(athena::io::IStreamWriter& w) const - { - w.writeUint32Big(atUint32(m_class)); - m_state.write(w); + std::unique_ptr exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace); - if (m_slots[0]) - m_slots[0]->saveState(w); - else - w.writeUint32Big(0); + specter::SplitView* splitView() { return m_splitView.get(); } + void updateSplit(float split) { m_state.split = split; } + void joinViews(specter::SplitView* thisSplit, int thisSlot, specter::SplitView* otherSplit, int otherSlot); + void setAxis(specter::SplitView::Axis axis) { + m_state.axis = axis; + reloadState(); + } - if (m_slots[1]) - m_slots[1]->saveState(w); - else - w.writeUint32Big(0); - } + specter::SplitView::Axis axis() const { return m_state.axis; } + float split() const { return m_state.split; } - void saveState(athena::io::YAMLDocWriter& w) const - { - w.writeUint32("class", atUint32(m_class)); - m_state.write(w); - - if (auto rec = w.enterSubRecord("slot0")) - { - if (m_slots[0]) - m_slots[0]->saveState(w); - else - w.writeUint32("class", 0); - } - - if (auto rec = w.enterSubRecord("slot1")) - { - if (m_slots[1]) - m_slots[1]->saveState(w); - else - w.writeUint32("class", 0); - } - } - - void setChildSlot(unsigned slot, std::unique_ptr&& space); - - specter::View* buildSpaceView(specter::ViewResources& res) {return buildContentView(res);} - specter::View* buildContentView(specter::ViewResources& res); - - Space* copy(Space* parent) const {return nullptr;} - bool spaceSplitAllowed() const {return false;} - - ISpaceController* spaceJoin(int keepSlot) - { - if (m_parent) - { - ISpaceController* ret = m_slots[keepSlot].get(); - m_parent->exchangeSpaceSplitJoin(this, std::move(m_slots[keepSlot])); - return ret; - } - return nullptr; - } - - std::unique_ptr exchangeSpaceSplitJoin(Space* removeSpace, std::unique_ptr&& keepSpace); - - specter::SplitView* splitView() {return m_splitView.get();} - void updateSplit(float split) {m_state.split = split;} - void joinViews(specter::SplitView* thisSplit, int thisSlot, specter::SplitView* otherSplit, int otherSlot); - - void setAxis(specter::SplitView::Axis axis) - { - m_state.axis = axis; - reloadState(); - } - - specter::SplitView::Axis axis() const {return m_state.axis;} - float split() const {return m_state.split;} - - specter::View* basisView() {return m_splitView.get();} + specter::View* basisView() { return m_splitView.get(); } }; -inline SplitSpace* Space::castToSplitSpace() -{ return cls() == Class::SplitSpace ? static_cast(this) : nullptr; } - -class ViewerSpace : public Space -{ -public: - ViewerSpace(ViewManager& vm, Class cls, Space* parent) - : Space(vm, cls, parent) {} -}; - -class EditorSpace : public Space -{ -public: - EditorSpace(ViewManager& vm, Class cls, Space* parent) - : Space(vm, cls, parent) {} -}; - -class GameSpace : public Space -{ -public: - GameSpace(ViewManager& vm, Class cls, Space* parent) - : Space(vm, cls, parent) {} -}; - -class TestSpace : public Space -{ - std::unique_ptr m_button; - std::unique_ptr m_textView; - - std::string m_contentStr; - std::string m_buttonStr; - - specter::IButtonBinding* m_binding; - -public: - TestSpace(ViewManager& vm, Space* parent, std::string_view content, std::string_view button, - specter::IButtonBinding* binding) - : Space(vm, Class::TestSpace, parent), m_contentStr(content), m_buttonStr(button), m_binding(binding) - {} - - struct State : Space::State - { - AT_DECL_DNA_YAML - AT_DECL_DNAV - } m_state; - const Space::State& spaceState() const {return m_state;} - - bool usesToolbar() const {return true;} - void buildToolbarView(specter::ViewResources& res, specter::Toolbar& tb) - { - m_button.reset(new specter::Button(res, tb, m_binding, m_buttonStr)); - tb.push_back(m_button.get(), 0); - } - - specter::View* buildContentView(specter::ViewResources& res) - { - m_textView.reset(new specter::MultiLineTextView(res, *m_spaceView, res.m_heading14)); - m_textView->setBackground(res.themeData().viewportBackground()); - m_textView->typesetGlyphs(m_contentStr, res.themeData().uiText()); - return m_textView.get(); - } -}; - +inline SplitSpace* Space::castToSplitSpace() { + return cls() == Class::SplitSpace ? static_cast(this) : nullptr; } +class ViewerSpace : public Space { +public: + ViewerSpace(ViewManager& vm, Class cls, Space* parent) : Space(vm, cls, parent) {} +}; + +class EditorSpace : public Space { +public: + EditorSpace(ViewManager& vm, Class cls, Space* parent) : Space(vm, cls, parent) {} +}; + +class GameSpace : public Space { +public: + GameSpace(ViewManager& vm, Class cls, Space* parent) : Space(vm, cls, parent) {} +}; + +class TestSpace : public Space { + std::unique_ptr m_button; + std::unique_ptr m_textView; + + std::string m_contentStr; + std::string m_buttonStr; + + specter::IButtonBinding* m_binding; + +public: + TestSpace(ViewManager& vm, Space* parent, std::string_view content, std::string_view button, + specter::IButtonBinding* binding) + : Space(vm, Class::TestSpace, parent), m_contentStr(content), m_buttonStr(button), m_binding(binding) {} + + struct State : Space::State{AT_DECL_DNA_YAML AT_DECL_DNAV} m_state; + const Space::State& spaceState() const { return m_state; } + + bool usesToolbar() const { return true; } + void buildToolbarView(specter::ViewResources& res, specter::Toolbar& tb) { + m_button.reset(new specter::Button(res, tb, m_binding, m_buttonStr)); + tb.push_back(m_button.get(), 0); + } + + specter::View* buildContentView(specter::ViewResources& res) { + m_textView.reset(new specter::MultiLineTextView(res, *m_spaceView, res.m_heading14)); + m_textView->setBackground(res.themeData().viewportBackground()); + m_textView->typesetGlyphs(m_contentStr, res.themeData().uiText()); + return m_textView.get(); + } +}; + +} // namespace urde diff --git a/Editor/SplashScreen.cpp b/Editor/SplashScreen.cpp index 44dc64778..b2521ba97 100644 --- a/Editor/SplashScreen.cpp +++ b/Editor/SplashScreen.cpp @@ -2,8 +2,7 @@ #include "version.h" #include "badging/Badging.hpp" -namespace urde -{ +namespace urde { #define SPLASH_WIDTH 555 #define SPLASH_HEIGHT 300 @@ -24,290 +23,255 @@ namespace urde SplashScreen::SplashScreen(ViewManager& vm, specter::ViewResources& res) : ModalWindow(res, vm.rootView(), - specter::RectangleConstraint(SPLASH_WIDTH * res.pixelFactor(), - SPLASH_HEIGHT * res.pixelFactor())), - m_vm(vm), - m_textColor(res.themeData().uiText()), - m_textColorClear(m_textColor), - m_newString(m_vm.translateOr("new_project", "New Project")), - m_openString(m_vm.translateOr("open_project", "Open Project")), - m_extractString(m_vm.translateOr("extract_game", "Extract Game")), - m_newProjBind(*this), - m_openProjBind(*this), - m_extractProjBind(*this) -{ - if (GIT_COMMIT_DATE[0] != '\0' && - GIT_COMMIT_HASH[0] != '\0' && - GIT_BRANCH[0] != '\0') - { + specter::RectangleConstraint(SPLASH_WIDTH * res.pixelFactor(), SPLASH_HEIGHT * res.pixelFactor())) +, m_vm(vm) +, m_textColor(res.themeData().uiText()) +, m_textColorClear(m_textColor) +, m_newString(m_vm.translateOr("new_project", "New Project")) +, m_openString(m_vm.translateOr("open_project", "Open Project")) +, m_extractString(m_vm.translateOr("extract_game", "Extract Game")) +, m_newProjBind(*this) +, m_openProjBind(*this) +, m_extractProjBind(*this) { + if (GIT_COMMIT_DATE[0] != '\0' && GIT_COMMIT_HASH[0] != '\0' && GIT_BRANCH[0] != '\0') { #ifdef URDE_DLPACKAGE - if ((URDE_DLPACKAGE)[0]) - m_buildInfoStr = hecl::Format("%s: %s\n%s: %s\n%s: %s", - vm.translateOr("release", "Release").data(), URDE_DLPACKAGE, - vm.translateOr("commit", "Commit").data(), GIT_COMMIT_HASH, - vm.translateOr("date", "Date").data(), GIT_COMMIT_DATE); - else + if ((URDE_DLPACKAGE)[0]) + m_buildInfoStr = hecl::Format("%s: %s\n%s: %s\n%s: %s", vm.translateOr("release", "Release").data(), + URDE_DLPACKAGE, vm.translateOr("commit", "Commit").data(), GIT_COMMIT_HASH, + vm.translateOr("date", "Date").data(), GIT_COMMIT_DATE); + else #endif - m_buildInfoStr = hecl::Format("%s: %s\n%s: %s\n%s: %s", - vm.translateOr("branch", "Branch").data(), GIT_BRANCH, - vm.translateOr("commit", "Commit").data(), GIT_COMMIT_HASH, - vm.translateOr("date", "Date").data(), GIT_COMMIT_DATE); - } + m_buildInfoStr = hecl::Format("%s: %s\n%s: %s\n%s: %s", vm.translateOr("branch", "Branch").data(), GIT_BRANCH, + vm.translateOr("commit", "Commit").data(), GIT_COMMIT_HASH, + vm.translateOr("date", "Date").data(), GIT_COMMIT_DATE); + } - m_openProjBind.m_openRecentMenuRoot.m_text = vm.translateOr("recent_projects", "Recent Projects"); - m_textColorClear[3] = 0.0; + m_openProjBind.m_openRecentMenuRoot.m_text = vm.translateOr("recent_projects", "Recent Projects"); + m_textColorClear[3] = 0.0; } -void SplashScreen::think() -{ - if (phase() == Phase::Done) - { - if (m_fileBrowser.m_view) - m_fileBrowser.m_view.reset(); - return; - } - - ModalWindow::think(); +void SplashScreen::think() { + if (phase() == Phase::Done) { if (m_fileBrowser.m_view) - m_fileBrowser.m_view->think(); + m_fileBrowser.m_view.reset(); + return; + } - if (m_openButt.m_view) - m_openButt.m_view->think(); + ModalWindow::think(); + if (m_fileBrowser.m_view) + m_fileBrowser.m_view->think(); - if (m_newProjBind.m_deferPath.size()) - { - Log.report(logvisor::Info, _SYS_STR("Making project '%s'"), m_newProjBind.m_deferPath.c_str()); - m_vm.projectManager().newProject(m_newProjBind.m_deferPath); - m_newProjBind.m_deferPath.clear(); - } - else if (m_openProjBind.m_deferPath.size()) - { - Log.report(logvisor::Info, _SYS_STR("Opening project '%s'"), m_openProjBind.m_deferPath.c_str()); - m_vm.projectManager().openProject(m_openProjBind.m_deferPath); - m_openProjBind.m_deferPath.clear(); - } - else if (m_extractProjBind.m_deferPath.size()) - { - Log.report(logvisor::Info, _SYS_STR("Extracting game '%s'"), m_extractProjBind.m_deferPath.c_str()); - m_vm.projectManager().extractGame(m_extractProjBind.m_deferPath); - m_extractProjBind.m_deferPath.clear(); - } + if (m_openButt.m_view) + m_openButt.m_view->think(); + + if (m_newProjBind.m_deferPath.size()) { + Log.report(logvisor::Info, _SYS_STR("Making project '%s'"), m_newProjBind.m_deferPath.c_str()); + m_vm.projectManager().newProject(m_newProjBind.m_deferPath); + m_newProjBind.m_deferPath.clear(); + } else if (m_openProjBind.m_deferPath.size()) { + Log.report(logvisor::Info, _SYS_STR("Opening project '%s'"), m_openProjBind.m_deferPath.c_str()); + m_vm.projectManager().openProject(m_openProjBind.m_deferPath); + m_openProjBind.m_deferPath.clear(); + } else if (m_extractProjBind.m_deferPath.size()) { + Log.report(logvisor::Info, _SYS_STR("Extracting game '%s'"), m_extractProjBind.m_deferPath.c_str()); + m_vm.projectManager().extractGame(m_extractProjBind.m_deferPath); + m_extractProjBind.m_deferPath.clear(); + } } -void SplashScreen::updateContentOpacity(float opacity) -{ - specter::ViewResources& res = rootView().viewRes(); - - if (!m_title && res.fontCacheReady()) - { - m_title.reset(new specter::TextView(res, *this, res.m_titleFont)); - zeus::CColor clearColor = res.themeData().uiText(); - clearColor[3] = 0.0; - m_title->typesetGlyphs("URDE", clearColor); - - m_buildInfo.reset(new specter::MultiLineTextView(res, *this, res.m_mainFont, specter::TextView::Alignment::Right)); - m_buildInfo->typesetGlyphs(m_buildInfoStr, clearColor); - - m_badgeIcon.reset(new specter::IconView(res, *this, GetBadge())); - m_badgeText.reset(new specter::TextView(res, *this, res.m_heading18, specter::TextView::Alignment::Right)); - m_badgeText->typesetGlyphs(BADGE_PHRASE, clearColor); - - m_newButt.m_view.reset(new specter::Button(res, *this, &m_newProjBind, m_newString, - nullptr, specter::Button::Style::Text)); - m_openButt.m_view.reset(new specter::Button(res, *this, &m_openProjBind, m_openString, - nullptr, specter::Button::Style::Text)); - m_extractButt.m_view.reset(new specter::Button(res, *this, &m_extractProjBind, m_extractString, - nullptr, specter::Button::Style::Text)); - - updateSize(); - } +void SplashScreen::updateContentOpacity(float opacity) { + specter::ViewResources& res = rootView().viewRes(); + if (!m_title && res.fontCacheReady()) { + m_title.reset(new specter::TextView(res, *this, res.m_titleFont)); zeus::CColor clearColor = res.themeData().uiText(); clearColor[3] = 0.0; - zeus::CColor color = zeus::CColor::lerp(clearColor, res.themeData().uiText(), opacity); - m_title->colorGlyphs(color); - m_buildInfo->colorGlyphs(color); - m_badgeIcon->setMultiplyColor({1.f, 1.f, 1.f, color.a()}); - m_badgeText->colorGlyphs(color); - m_newButt.m_view->colorGlyphs(color); - m_openButt.m_view->colorGlyphs(color); - m_extractButt.m_view->colorGlyphs(color); + m_title->typesetGlyphs("URDE", clearColor); + + m_buildInfo.reset(new specter::MultiLineTextView(res, *this, res.m_mainFont, specter::TextView::Alignment::Right)); + m_buildInfo->typesetGlyphs(m_buildInfoStr, clearColor); + + m_badgeIcon.reset(new specter::IconView(res, *this, GetBadge())); + m_badgeText.reset(new specter::TextView(res, *this, res.m_heading18, specter::TextView::Alignment::Right)); + m_badgeText->typesetGlyphs(BADGE_PHRASE, clearColor); + + m_newButt.m_view.reset( + new specter::Button(res, *this, &m_newProjBind, m_newString, nullptr, specter::Button::Style::Text)); + m_openButt.m_view.reset( + new specter::Button(res, *this, &m_openProjBind, m_openString, nullptr, specter::Button::Style::Text)); + m_extractButt.m_view.reset( + new specter::Button(res, *this, &m_extractProjBind, m_extractString, nullptr, specter::Button::Style::Text)); + + updateSize(); + } + + zeus::CColor clearColor = res.themeData().uiText(); + clearColor[3] = 0.0; + zeus::CColor color = zeus::CColor::lerp(clearColor, res.themeData().uiText(), opacity); + m_title->colorGlyphs(color); + m_buildInfo->colorGlyphs(color); + m_badgeIcon->setMultiplyColor({1.f, 1.f, 1.f, color.a()}); + m_badgeText->colorGlyphs(color); + m_newButt.m_view->colorGlyphs(color); + m_openButt.m_view->colorGlyphs(color); + m_extractButt.m_view->colorGlyphs(color); } -void SplashScreen::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) -{ - if (skipBuildInAnimation()) - return; - if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) - m_fileBrowser.m_view->mouseDown(coord, button, mod); - else - { - m_newButt.mouseDown(coord, button, mod); - m_openButt.mouseDown(coord, button, mod); - m_extractButt.mouseDown(coord, button, mod); - } +void SplashScreen::mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) { + if (skipBuildInAnimation()) + return; + if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) + m_fileBrowser.m_view->mouseDown(coord, button, mod); + else { + m_newButt.mouseDown(coord, button, mod); + m_openButt.mouseDown(coord, button, mod); + m_extractButt.mouseDown(coord, button, mod); + } } -void SplashScreen::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) -{ - if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) - m_fileBrowser.m_view->mouseUp(coord, button, mod); - else - { - m_newButt.mouseUp(coord, button, mod); - m_openButt.mouseUp(coord, button, mod); - m_extractButt.mouseUp(coord, button, mod); - } +void SplashScreen::mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mod) { + if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) + m_fileBrowser.m_view->mouseUp(coord, button, mod); + else { + m_newButt.mouseUp(coord, button, mod); + m_openButt.mouseUp(coord, button, mod); + m_extractButt.mouseUp(coord, button, mod); + } } -void SplashScreen::mouseMove(const boo::SWindowCoord& coord) -{ - if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) - m_fileBrowser.m_view->mouseMove(coord); - else - { - m_newButt.mouseMove(coord); - m_openButt.mouseMove(coord); - m_extractButt.mouseMove(coord); - } +void SplashScreen::mouseMove(const boo::SWindowCoord& coord) { + if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) + m_fileBrowser.m_view->mouseMove(coord); + else { + m_newButt.mouseMove(coord); + m_openButt.mouseMove(coord); + m_extractButt.mouseMove(coord); + } } -void SplashScreen::mouseEnter(const boo::SWindowCoord& coord) -{ - if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) - m_fileBrowser.m_view->mouseEnter(coord); - else - { - m_newButt.mouseEnter(coord); - m_openButt.mouseEnter(coord); - m_extractButt.mouseEnter(coord); - } +void SplashScreen::mouseEnter(const boo::SWindowCoord& coord) { + if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) + m_fileBrowser.m_view->mouseEnter(coord); + else { + m_newButt.mouseEnter(coord); + m_openButt.mouseEnter(coord); + m_extractButt.mouseEnter(coord); + } } -void SplashScreen::mouseLeave(const boo::SWindowCoord& coord) -{ - if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) - m_fileBrowser.m_view->mouseLeave(coord); - else - { - m_newButt.mouseLeave(coord); - m_openButt.mouseLeave(coord); - m_extractButt.mouseLeave(coord); - } +void SplashScreen::mouseLeave(const boo::SWindowCoord& coord) { + if (m_fileBrowser.m_view && !m_fileBrowser.m_view->closed()) + m_fileBrowser.m_view->mouseLeave(coord); + else { + m_newButt.mouseLeave(coord); + m_openButt.mouseLeave(coord); + m_extractButt.mouseLeave(coord); + } } -void SplashScreen::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) -{ - if (m_fileBrowser.m_view) - m_fileBrowser.m_view->scroll(coord, scroll); +void SplashScreen::scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) { + if (m_fileBrowser.m_view) + m_fileBrowser.m_view->scroll(coord, scroll); } -void SplashScreen::touchDown(const boo::STouchCoord& coord, uintptr_t tid) -{ - if (m_fileBrowser.m_view) - m_fileBrowser.m_view->touchDown(coord, tid); +void SplashScreen::touchDown(const boo::STouchCoord& coord, uintptr_t tid) { + if (m_fileBrowser.m_view) + m_fileBrowser.m_view->touchDown(coord, tid); } -void SplashScreen::touchUp(const boo::STouchCoord& coord, uintptr_t tid) -{ - if (m_fileBrowser.m_view) - m_fileBrowser.m_view->touchUp(coord, tid); +void SplashScreen::touchUp(const boo::STouchCoord& coord, uintptr_t tid) { + if (m_fileBrowser.m_view) + m_fileBrowser.m_view->touchUp(coord, tid); } -void SplashScreen::touchMove(const boo::STouchCoord& coord, uintptr_t tid) -{ - if (m_fileBrowser.m_view) - m_fileBrowser.m_view->touchMove(coord, tid); +void SplashScreen::touchMove(const boo::STouchCoord& coord, uintptr_t tid) { + if (m_fileBrowser.m_view) + m_fileBrowser.m_view->touchMove(coord, tid); } -void SplashScreen::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) -{ - if (skipBuildInAnimation()) - return; - if (m_fileBrowser.m_view) - m_fileBrowser.m_view->charKeyDown(charCode, mods, isRepeat); +void SplashScreen::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) { + if (skipBuildInAnimation()) + return; + if (m_fileBrowser.m_view) + m_fileBrowser.m_view->charKeyDown(charCode, mods, isRepeat); } -void SplashScreen::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) -{ - if (skipBuildInAnimation()) - return; - if (m_fileBrowser.m_view) - m_fileBrowser.m_view->specialKeyDown(key, mods, isRepeat); +void SplashScreen::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) { + if (skipBuildInAnimation()) + return; + if (m_fileBrowser.m_view) + m_fileBrowser.m_view->specialKeyDown(key, mods, isRepeat); } -void SplashScreen::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) -{ - ModalWindow::resized(root, sub); - float pf = rootView().viewRes().pixelFactor(); +void SplashScreen::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) { + ModalWindow::resized(root, sub); + float pf = rootView().viewRes().pixelFactor(); - boo::SWindowRect centerRect = subRect(); - centerRect.location[0] = root.size[0] / 2 - (SPLASH_WIDTH * pf / 2.0); - centerRect.location[1] = root.size[1] / 2 - (SPLASH_HEIGHT * pf / 2.0); + boo::SWindowRect centerRect = subRect(); + centerRect.location[0] = root.size[0] / 2 - (SPLASH_WIDTH * pf / 2.0); + centerRect.location[1] = root.size[1] / 2 - (SPLASH_HEIGHT * pf / 2.0); - boo::SWindowRect badgeRect = centerRect; - badgeRect.location[0] += LINE_WIDTH * pf; - badgeRect.location[1] += BADGE_MARGIN * pf; - badgeRect.size[0] = BADGE_WIDTH * pf; - badgeRect.size[1] = BADGE_HEIGHT * pf; + boo::SWindowRect badgeRect = centerRect; + badgeRect.location[0] += LINE_WIDTH * pf; + badgeRect.location[1] += BADGE_MARGIN * pf; + badgeRect.size[0] = BADGE_WIDTH * pf; + badgeRect.size[1] = BADGE_HEIGHT * pf; - boo::SWindowRect textRect = centerRect; - textRect.location[0] += TEXT_MARGIN * pf; - textRect.location[1] += (SPLASH_HEIGHT - 36) * pf; - if (m_title) - { - m_title->resized(root, textRect); - textRect.location[0] = centerRect.location[0] + (SPLASH_WIDTH - TEXT_MARGIN) * pf; - textRect.location[1] -= 5 * pf; - m_buildInfo->resized(root, textRect); + boo::SWindowRect textRect = centerRect; + textRect.location[0] += TEXT_MARGIN * pf; + textRect.location[1] += (SPLASH_HEIGHT - 36) * pf; + if (m_title) { + m_title->resized(root, textRect); + textRect.location[0] = centerRect.location[0] + (SPLASH_WIDTH - TEXT_MARGIN) * pf; + textRect.location[1] -= 5 * pf; + m_buildInfo->resized(root, textRect); - textRect.location[0] = centerRect.location[0] + (SPLASH_WIDTH - TEXT_MARGIN) * pf; - textRect.location[1] = centerRect.location[1] + (BADGE_MARGIN + TEXT_MARGIN) * pf; - m_badgeIcon->resized(root, badgeRect); - m_badgeText->resized(root, textRect); + textRect.location[0] = centerRect.location[0] + (SPLASH_WIDTH - TEXT_MARGIN) * pf; + textRect.location[1] = centerRect.location[1] + (BADGE_MARGIN + TEXT_MARGIN) * pf; + m_badgeIcon->resized(root, badgeRect); + m_badgeText->resized(root, textRect); - textRect.size[0] = m_newButt.m_view->nominalWidth(); - textRect.size[1] = m_newButt.m_view->nominalHeight(); - textRect.location[1] = centerRect.location[1] + 20 * pf; - textRect.location[0] = centerRect.location[0] + SPLASH_WIDTH / 4 * pf - m_newButt.m_view->nominalWidth() / 2; - m_newButt.m_view->resized(root, textRect); + textRect.size[0] = m_newButt.m_view->nominalWidth(); + textRect.size[1] = m_newButt.m_view->nominalHeight(); + textRect.location[1] = centerRect.location[1] + 20 * pf; + textRect.location[0] = centerRect.location[0] + SPLASH_WIDTH / 4 * pf - m_newButt.m_view->nominalWidth() / 2; + m_newButt.m_view->resized(root, textRect); - textRect.size[0] = m_openButt.m_view->nominalWidth(); - textRect.size[1] = m_openButt.m_view->nominalHeight(); - textRect.location[1] = centerRect.location[1] + 20 * pf; - textRect.location[0] = centerRect.location[0] + SPLASH_WIDTH * 2 / 4 * pf - m_openButt.m_view->nominalWidth() / 2; - m_openButt.m_view->resized(root, textRect); + textRect.size[0] = m_openButt.m_view->nominalWidth(); + textRect.size[1] = m_openButt.m_view->nominalHeight(); + textRect.location[1] = centerRect.location[1] + 20 * pf; + textRect.location[0] = centerRect.location[0] + SPLASH_WIDTH * 2 / 4 * pf - m_openButt.m_view->nominalWidth() / 2; + m_openButt.m_view->resized(root, textRect); - textRect.size[0] = m_extractButt.m_view->nominalWidth(); - textRect.size[1] = m_extractButt.m_view->nominalHeight(); - textRect.location[1] = centerRect.location[1] + 20 * pf; - textRect.location[0] = centerRect.location[0] + SPLASH_WIDTH * 3 / 4 * pf - m_extractButt.m_view->nominalWidth() / 2; - m_extractButt.m_view->resized(root, textRect); - } + textRect.size[0] = m_extractButt.m_view->nominalWidth(); + textRect.size[1] = m_extractButt.m_view->nominalHeight(); + textRect.location[1] = centerRect.location[1] + 20 * pf; + textRect.location[0] = + centerRect.location[0] + SPLASH_WIDTH * 3 / 4 * pf - m_extractButt.m_view->nominalWidth() / 2; + m_extractButt.m_view->resized(root, textRect); + } - if (m_fileBrowser.m_view) - m_fileBrowser.m_view->resized(root, root); + if (m_fileBrowser.m_view) + m_fileBrowser.m_view->resized(root, root); } -void SplashScreen::draw(boo::IGraphicsCommandQueue* gfxQ) -{ - if (phase() == Phase::Done) - return; - ModalWindow::draw(gfxQ); +void SplashScreen::draw(boo::IGraphicsCommandQueue* gfxQ) { + if (phase() == Phase::Done) + return; + ModalWindow::draw(gfxQ); - if (m_title) - { - m_title->draw(gfxQ); - m_buildInfo->draw(gfxQ); - m_badgeIcon->draw(gfxQ); - m_badgeText->draw(gfxQ); - m_newButt.m_view->draw(gfxQ); - m_openButt.m_view->draw(gfxQ); - m_extractButt.m_view->draw(gfxQ); - } + if (m_title) { + m_title->draw(gfxQ); + m_buildInfo->draw(gfxQ); + m_badgeIcon->draw(gfxQ); + m_badgeText->draw(gfxQ); + m_newButt.m_view->draw(gfxQ); + m_openButt.m_view->draw(gfxQ); + m_extractButt.m_view->draw(gfxQ); + } - if (m_fileBrowser.m_view) - m_fileBrowser.m_view->draw(gfxQ); + if (m_fileBrowser.m_view) + m_fileBrowser.m_view->draw(gfxQ); } -} +} // namespace urde diff --git a/Editor/SplashScreen.hpp b/Editor/SplashScreen.hpp index 8009d4627..44737a4de 100644 --- a/Editor/SplashScreen.hpp +++ b/Editor/SplashScreen.hpp @@ -9,177 +9,154 @@ #include "ViewManager.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("specter::SplashScreen"); -class SplashScreen : public specter::ModalWindow -{ - ViewManager& m_vm; +class SplashScreen : public specter::ModalWindow { + ViewManager& m_vm; - zeus::CColor m_textColor; - zeus::CColor m_textColorClear; + zeus::CColor m_textColor; + zeus::CColor m_textColorClear; - std::unique_ptr m_title; - std::string m_buildInfoStr; - std::unique_ptr m_buildInfo; - std::unique_ptr m_badgeIcon; - std::unique_ptr m_badgeText; + std::unique_ptr m_title; + std::string m_buildInfoStr; + std::unique_ptr m_buildInfo; + std::unique_ptr m_badgeIcon; + std::unique_ptr m_badgeText; - std::string m_newString; - specter::ViewChild> m_newButt; - std::string m_openString; - specter::ViewChild> m_openButt; - std::string m_extractString; - specter::ViewChild> m_extractButt; + std::string m_newString; + specter::ViewChild> m_newButt; + std::string m_openString; + specter::ViewChild> m_openButt; + std::string m_extractString; + specter::ViewChild> m_extractButt; - specter::ViewChild> m_fileBrowser; + specter::ViewChild> m_fileBrowser; - struct NewProjBinding : specter::IButtonBinding - { - SplashScreen& m_splash; - hecl::SystemString m_deferPath; - NewProjBinding(SplashScreen& splash) : m_splash(splash) {} - std::string_view name(const specter::Control* control) const {return m_splash.m_newString.c_str();} - std::string_view help(const specter::Control* control) const {return "Creates an empty project at selected path";} - void activated(const specter::Button* button, const boo::SWindowCoord& coord) - { - m_splash.m_fileBrowser.m_view.reset( - new specter::FileBrowser(m_splash.rootView().viewRes(), - m_splash, m_splash.m_newString, - specter::FileBrowser::Type::NewHECLProject, - [&](bool ok, hecl::SystemStringView path) - { - if (ok) - m_deferPath = path; - })); - m_splash.updateSize(); - m_splash.m_newButt.mouseLeave(coord); - } - } m_newProjBind; + struct NewProjBinding : specter::IButtonBinding { + SplashScreen& m_splash; + hecl::SystemString m_deferPath; + NewProjBinding(SplashScreen& splash) : m_splash(splash) {} + std::string_view name(const specter::Control* control) const { return m_splash.m_newString.c_str(); } + std::string_view help(const specter::Control* control) const { return "Creates an empty project at selected path"; } + void activated(const specter::Button* button, const boo::SWindowCoord& coord) { + m_splash.m_fileBrowser.m_view.reset(new specter::FileBrowser( + m_splash.rootView().viewRes(), m_splash, m_splash.m_newString, specter::FileBrowser::Type::NewHECLProject, + [&](bool ok, hecl::SystemStringView path) { + if (ok) + m_deferPath = path; + })); + m_splash.updateSize(); + m_splash.m_newButt.mouseLeave(coord); + } + } m_newProjBind; - struct OpenProjBinding : specter::IButtonBinding - { - SplashScreen& m_splash; - hecl::SystemString m_deferPath; - OpenProjBinding(SplashScreen& splash) : m_splash(splash), m_openRecentMenuRoot(*this) {} - std::string_view name(const specter::Control* control) const {return m_splash.m_openString.c_str();} - std::string_view help(const specter::Control* control) const {return "Opens an existing project at selected path";} - void activated(const specter::Button* button, const boo::SWindowCoord& coord) - { - m_splash.m_fileBrowser.m_view.reset( - new specter::FileBrowser(m_splash.rootView().viewRes(), - m_splash, m_splash.m_openString, - specter::FileBrowser::Type::OpenHECLProject, - [&](bool ok, hecl::SystemStringView path) - { - if (ok) - m_deferPath = path; - })); - m_splash.updateSize(); - m_splash.m_openButt.mouseLeave(coord); + struct OpenProjBinding : specter::IButtonBinding { + SplashScreen& m_splash; + hecl::SystemString m_deferPath; + OpenProjBinding(SplashScreen& splash) : m_splash(splash), m_openRecentMenuRoot(*this) {} + std::string_view name(const specter::Control* control) const { return m_splash.m_openString.c_str(); } + std::string_view help(const specter::Control* control) const { + return "Opens an existing project at selected path"; + } + void activated(const specter::Button* button, const boo::SWindowCoord& coord) { + m_splash.m_fileBrowser.m_view.reset(new specter::FileBrowser( + m_splash.rootView().viewRes(), m_splash, m_splash.m_openString, specter::FileBrowser::Type::OpenHECLProject, + [&](bool ok, hecl::SystemStringView path) { + if (ok) + m_deferPath = path; + })); + m_splash.updateSize(); + m_splash.m_openButt.mouseLeave(coord); + } + + struct OpenRecentMenuRoot : specter::IMenuNode { + OpenProjBinding& m_openProjBind; + OpenRecentMenuRoot(OpenProjBinding& openProjBind) : m_openProjBind(openProjBind) {} + + std::string m_text; + const std::string* text() const { return &m_text; } + + struct OpenRecentMenuItem final : specter::IMenuNode { + OpenRecentMenuRoot& m_parent; + + hecl::SystemString m_path; + std::string m_text; + + const std::string* text() const { return &m_text; } + void activated(const boo::SWindowCoord& coord) { + m_parent.m_openProjBind.m_deferPath = m_path; + m_parent.m_openProjBind.m_splash.m_openButt.m_view->closeMenu(coord); } - struct OpenRecentMenuRoot : specter::IMenuNode - { - OpenProjBinding& m_openProjBind; - OpenRecentMenuRoot(OpenProjBinding& openProjBind) : m_openProjBind(openProjBind) {} - - std::string m_text; - const std::string* text() const {return &m_text;} - - struct OpenRecentMenuItem final : specter::IMenuNode - { - OpenRecentMenuRoot& m_parent; - - hecl::SystemString m_path; - std::string m_text; - - const std::string* text() const {return &m_text;} - void activated(const boo::SWindowCoord& coord) - { - m_parent.m_openProjBind.m_deferPath = m_path; - m_parent.m_openProjBind.m_splash.m_openButt.m_view->closeMenu(coord); - } - - OpenRecentMenuItem(OpenRecentMenuRoot& parent, const hecl::SystemString& path) - : m_parent(parent), m_path(path) - { - std::vector pathComps = specter::FileBrowser::PathComponents(path); - if (pathComps.size()) - m_text = hecl::SystemUTF8Conv(pathComps.back()).str(); - } - }; - std::vector m_items; - - size_t subNodeCount() const {return m_items.size();} - specter::IMenuNode* subNode(size_t idx) {return &m_items[idx];} - - void buildNodes(const std::vector* recentProjects) - { - m_items.clear(); - if (recentProjects) - { - m_items.reserve(recentProjects->size()); - for (const hecl::SystemString& path : *recentProjects) - m_items.emplace_back(*this, path); - } - } - } m_openRecentMenuRoot; - - MenuStyle menuStyle(const specter::Button* button) const {return MenuStyle::Auxiliary;} - std::unique_ptr buildMenu(const specter::Button* button) - { - m_openRecentMenuRoot.buildNodes(m_splash.m_vm.recentProjects()); - return std::unique_ptr(new specter::Menu(m_splash.rootView().viewRes(), - m_splash, &m_openRecentMenuRoot)); + OpenRecentMenuItem(OpenRecentMenuRoot& parent, const hecl::SystemString& path) + : m_parent(parent), m_path(path) { + std::vector pathComps = specter::FileBrowser::PathComponents(path); + if (pathComps.size()) + m_text = hecl::SystemUTF8Conv(pathComps.back()).str(); } - } m_openProjBind; + }; + std::vector m_items; - struct ExtractProjBinding : specter::IButtonBinding - { - SplashScreen& m_splash; - hecl::SystemString m_deferPath; - ExtractProjBinding(SplashScreen& splash) : m_splash(splash) {} - std::string_view name(const specter::Control* control) const {return m_splash.m_extractString.c_str();} - std::string_view help(const specter::Control* control) const {return "Extracts game image as project at selected path";} - void activated(const specter::Button* button, const boo::SWindowCoord& coord) - { - m_splash.m_fileBrowser.m_view.reset( - new specter::FileBrowser(m_splash.rootView().viewRes(), - m_splash, m_splash.m_extractString, - specter::FileBrowser::Type::OpenFile, - [&](bool ok, hecl::SystemStringView path) - { - if (ok) - m_deferPath = path; - })); - m_splash.updateSize(); - m_splash.m_extractButt.mouseLeave(coord); + size_t subNodeCount() const { return m_items.size(); } + specter::IMenuNode* subNode(size_t idx) { return &m_items[idx]; } + + void buildNodes(const std::vector* recentProjects) { + m_items.clear(); + if (recentProjects) { + m_items.reserve(recentProjects->size()); + for (const hecl::SystemString& path : *recentProjects) + m_items.emplace_back(*this, path); } - } m_extractProjBind; + } + } m_openRecentMenuRoot; + + MenuStyle menuStyle(const specter::Button* button) const { return MenuStyle::Auxiliary; } + std::unique_ptr buildMenu(const specter::Button* button) { + m_openRecentMenuRoot.buildNodes(m_splash.m_vm.recentProjects()); + return std::unique_ptr(new specter::Menu(m_splash.rootView().viewRes(), m_splash, &m_openRecentMenuRoot)); + } + } m_openProjBind; + + struct ExtractProjBinding : specter::IButtonBinding { + SplashScreen& m_splash; + hecl::SystemString m_deferPath; + ExtractProjBinding(SplashScreen& splash) : m_splash(splash) {} + std::string_view name(const specter::Control* control) const { return m_splash.m_extractString.c_str(); } + std::string_view help(const specter::Control* control) const { + return "Extracts game image as project at selected path"; + } + void activated(const specter::Button* button, const boo::SWindowCoord& coord) { + m_splash.m_fileBrowser.m_view.reset( + new specter::FileBrowser(m_splash.rootView().viewRes(), m_splash, m_splash.m_extractString, + specter::FileBrowser::Type::OpenFile, [&](bool ok, hecl::SystemStringView path) { + if (ok) + m_deferPath = path; + })); + m_splash.updateSize(); + m_splash.m_extractButt.mouseLeave(coord); + } + } m_extractProjBind; public: - SplashScreen(ViewManager& vm, specter::ViewResources& res); - void think(); - void updateContentOpacity(float opacity); + SplashScreen(ViewManager& vm, specter::ViewResources& res); + void think(); + void updateContentOpacity(float opacity); - void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); - void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); - void mouseMove(const boo::SWindowCoord&); - void mouseEnter(const boo::SWindowCoord&); - void mouseLeave(const boo::SWindowCoord&); - void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&); - void touchDown(const boo::STouchCoord&, uintptr_t); - void touchUp(const boo::STouchCoord&, uintptr_t); - void touchMove(const boo::STouchCoord&, uintptr_t); - void charKeyDown(unsigned long, boo::EModifierKey, bool); - void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool); + void mouseDown(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); + void mouseUp(const boo::SWindowCoord&, boo::EMouseButton, boo::EModifierKey); + void mouseMove(const boo::SWindowCoord&); + void mouseEnter(const boo::SWindowCoord&); + void mouseLeave(const boo::SWindowCoord&); + void scroll(const boo::SWindowCoord&, const boo::SScrollDelta&); + void touchDown(const boo::STouchCoord&, uintptr_t); + void touchUp(const boo::STouchCoord&, uintptr_t); + void touchMove(const boo::STouchCoord&, uintptr_t); + void charKeyDown(unsigned long, boo::EModifierKey, bool); + void specialKeyDown(boo::ESpecialKey, boo::EModifierKey, bool); - void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); - void draw(boo::IGraphicsCommandQueue* gfxQ); + void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); + void draw(boo::IGraphicsCommandQueue* gfxQ); }; -} - - +} // namespace urde diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index ce2705f5b..5896d6d1e 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -27,187 +27,157 @@ using YAMLNode = athena::io::YAMLNode; extern hecl::SystemString ExeDir; -namespace urde -{ +namespace urde { -void ViewManager::InitMP1(MP1::CMain& main) -{ - main.Init(m_fileStoreManager, &m_cvarManager, m_mainWindow.get(), m_voiceEngine.get(), *m_amuseAllocWrapper); - if (!m_noShaderWarmup) - main.WarmupShaders(); +void ViewManager::InitMP1(MP1::CMain& main) { + main.Init(m_fileStoreManager, &m_cvarManager, m_mainWindow.get(), m_voiceEngine.get(), *m_amuseAllocWrapper); + if (!m_noShaderWarmup) + main.WarmupShaders(); - m_testGameView.reset(new TestGameView(*this, m_viewResources, *m_rootView)); + m_testGameView.reset(new TestGameView(*this, m_viewResources, *m_rootView)); - m_rootView->accessContentViews().clear(); - m_rootView->accessContentViews().push_back(m_testGameView.get()); - m_rootView->updateSize(); + m_rootView->accessContentViews().clear(); + m_rootView->accessContentViews().push_back(m_testGameView.get()); + m_rootView->updateSize(); } -void ViewManager::TestGameView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) -{ - specter::View::resized(root, sub); - urde::CGraphics::SetViewportResolution({sub.size[0], sub.size[1]}); - if (m_debugText) - { - boo::SWindowRect newSub = sub; - newSub.location[1] = 5 * m_vm.m_viewResources.pixelFactor(); - m_debugText->resized(root, newSub); +void ViewManager::TestGameView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub) { + specter::View::resized(root, sub); + urde::CGraphics::SetViewportResolution({sub.size[0], sub.size[1]}); + if (m_debugText) { + boo::SWindowRect newSub = sub; + newSub.location[1] = 5 * m_vm.m_viewResources.pixelFactor(); + m_debugText->resized(root, newSub); + } +} + +void ViewManager::TestGameView::draw(boo::IGraphicsCommandQueue* gfxQ) { + m_vm.m_projManager.mainDraw(); + if (m_debugText && g_StateManager && g_StateManager->Player()) + m_debugText->draw(gfxQ); +} + +void ViewManager::TestGameView::think() { + if (!m_debugText) { + m_debugText.reset(new specter::MultiLineTextView(m_vm.m_viewResources, *this, m_vm.m_viewResources.m_monoFont18)); + boo::SWindowRect sub = subRect(); + sub.location[1] = 5 * m_vm.m_viewResources.pixelFactor(); + m_debugText->resized(rootView().subRect(), sub); + } + + if (m_debugText && g_StateManager) { + std::string overlayText; + const hecl::CVar* showFrameIdx = hecl::CVarManager::instance()->findCVar("debugOverlay.showFrameCounter"); + const hecl::CVar* playerInfo = hecl::CVarManager::instance()->findCVar("debugOverlay.playerInfo"); + const hecl::CVar* worldInfo = hecl::CVarManager::instance()->findCVar("debugOverlay.worldInfo"); + const hecl::CVar* areaInfo = hecl::CVarManager::instance()->findCVar("debugOverlay.areaInfo"); + if (showFrameIdx && showFrameIdx->toBoolean()) + overlayText += hecl::Format("Frame: %d\n", g_StateManager->GetUpdateFrameIndex()); + + if (g_StateManager->Player() && playerInfo && playerInfo->toBoolean()) { + const CPlayer& pl = g_StateManager->GetPlayer(); + const zeus::CQuaternion plQ = zeus::CQuaternion(pl.GetTransform().getRotation().buildMatrix3f()); + const zeus::CTransform camXf = g_StateManager->GetCameraManager()->GetCurrentCameraTransform(*g_StateManager); + const zeus::CQuaternion camQ = zeus::CQuaternion(camXf.getRotation().buildMatrix3f()); + overlayText += hecl::Format( + "Player Position: x %f, y %f, z %f\n" + " Roll: %f, Pitch: %f, Yaw: %f\n" + "Camera Position: x %f, y %f, z %f\n" + " Roll: %f, Pitch: %f, Yaw: %f\n", + pl.GetTranslation().x(), pl.GetTranslation().y(), pl.GetTranslation().z(), plQ.roll(), plQ.pitch(), plQ.yaw(), + camXf.origin.x(), camXf.origin.y(), camXf.origin.z(), camQ.roll(), camQ.pitch(), camQ.yaw()); } -} - -void ViewManager::TestGameView::draw(boo::IGraphicsCommandQueue* gfxQ) -{ - m_vm.m_projManager.mainDraw(); - if (m_debugText && g_StateManager && g_StateManager->Player()) - m_debugText->draw(gfxQ); -} - -void ViewManager::TestGameView::think() -{ - if (!m_debugText) - { - m_debugText.reset( - new specter::MultiLineTextView(m_vm.m_viewResources, *this, m_vm.m_viewResources.m_monoFont18)); - boo::SWindowRect sub = subRect(); - sub.location[1] = 5 * m_vm.m_viewResources.pixelFactor(); - m_debugText->resized(rootView().subRect(), sub); + if (worldInfo && worldInfo->toBoolean()) { + TLockedToken tbl = + g_SimplePool->GetObj({FOURCC('STRG'), g_StateManager->GetWorld()->IGetStringTableAssetId()}); + const urde::TAreaId aId = g_GameState->CurrentWorldState().GetCurrentAreaId(); + overlayText += hecl::Format("World: 0x%08X%s, Area: %i\n", u32(g_GameState->CurrentWorldAssetId().Value()), + (tbl.IsLoaded() ? (" " + hecl::Char16ToUTF8(tbl->GetString(0))).c_str() : ""), aId); } - if (m_debugText && g_StateManager) - { - std::string overlayText; - const hecl::CVar* showFrameIdx = hecl::CVarManager::instance()->findCVar("debugOverlay.showFrameCounter"); - const hecl::CVar* playerInfo = hecl::CVarManager::instance()->findCVar("debugOverlay.playerInfo"); - const hecl::CVar* worldInfo = hecl::CVarManager::instance()->findCVar("debugOverlay.worldInfo"); - const hecl::CVar* areaInfo = hecl::CVarManager::instance()->findCVar("debugOverlay.areaInfo"); - if (showFrameIdx && showFrameIdx->toBoolean()) - overlayText += hecl::Format("Frame: %d\n", - g_StateManager->GetUpdateFrameIndex()); - - if (g_StateManager->Player() && playerInfo && playerInfo->toBoolean()) - { - const CPlayer& pl = g_StateManager->GetPlayer(); - const zeus::CQuaternion plQ = zeus::CQuaternion(pl.GetTransform().getRotation().buildMatrix3f()); - const zeus::CTransform camXf = g_StateManager->GetCameraManager()->GetCurrentCameraTransform(*g_StateManager); - const zeus::CQuaternion camQ = zeus::CQuaternion(camXf.getRotation().buildMatrix3f()); - overlayText += hecl::Format("Player Position: x %f, y %f, z %f\n" - " Quaternion: w %f, x %f, y %f, z %f\n" - " Roll: %f, Pitch: %f, Yaw: %f\n" - "Camera Position: x %f, y %f, z %f\n" - " Quaternion: w %f, x %f, y %f, z %f\n" - " Roll: %f, Pitch: %f, Yaw: %f\n", - pl.GetTranslation().x(), pl.GetTranslation().y(), pl.GetTranslation().z(), - plQ.w(), plQ.x(), plQ.y(), plQ.z(), - plQ.roll(), plQ.pitch(), plQ.yaw(), - camXf.origin.x(), camXf.origin.y(), camXf.origin.z(), - camQ.w(), camQ.x(), camQ.y(), camQ.z(), - camQ.roll(), camQ.pitch(), camQ.yaw()); - } - if (worldInfo && worldInfo->toBoolean()) - { - TLockedToken tbl = - g_SimplePool->GetObj({FOURCC('STRG'), g_StateManager->GetWorld()->IGetStringTableAssetId()}); - const urde::TAreaId aId = g_GameState->CurrentWorldState().GetCurrentAreaId(); - overlayText += hecl::Format("World: 0x%08X%s, Area: %i\n", - u32(g_GameState->CurrentWorldAssetId().Value()), - (tbl.IsLoaded() ? (" " + hecl::Char16ToUTF8(tbl->GetString(0))).c_str() : ""), aId); - } - - const urde::TAreaId aId = g_GameState->CurrentWorldState().GetCurrentAreaId(); - if (areaInfo && areaInfo->toBoolean() && g_StateManager->WorldNC() && g_StateManager->WorldNC()->DoesAreaExist(aId)) - { - const auto& layerStates = g_GameState->CurrentWorldState().GetLayerState(); - std::string layerBits; - u32 totalActive = 0; - for (u32 i = 0; i < layerStates->GetAreaLayerCount(aId); ++i) - { - if (layerStates->IsLayerActive(aId, i)) - { - ++totalActive; - layerBits += "1"; - } - else - layerBits += "0"; - } - overlayText += hecl::Format("Area AssetId: 0x%08X, Total Objects: %i, Total Layers: %i, Total Active Layers: %i\n" - "Active Layer bits: %s\n", - (unsigned int)g_StateManager->WorldNC()->GetArea(aId)->GetAreaAssetId().Value(), - g_StateManager->GetAllObjectList().size(), layerStates->GetAreaLayerCount(aId), - totalActive, layerBits.c_str()); - } - - if (!overlayText.empty()) - m_debugText->typesetGlyphs(overlayText); + const urde::TAreaId aId = g_GameState->CurrentWorldState().GetCurrentAreaId(); + if (areaInfo && areaInfo->toBoolean() && g_StateManager->WorldNC() && + g_StateManager->WorldNC()->DoesAreaExist(aId)) { + const auto& layerStates = g_GameState->CurrentWorldState().GetLayerState(); + std::string layerBits; + u32 totalActive = 0; + for (u32 i = 0; i < layerStates->GetAreaLayerCount(aId); ++i) { + if (layerStates->IsLayerActive(aId, i)) { + ++totalActive; + layerBits += "1"; + } else + layerBits += "0"; + } + overlayText += hecl::Format( + "Area AssetId: 0x%08X, Total Objects: %i\n" + "Active Layer bits: %s\n", + (unsigned int)g_StateManager->WorldNC()->GetArea(aId)->GetAreaAssetId().Value(), + g_StateManager->GetAllObjectList().size(), layerBits.c_str()); } + + if (!overlayText.empty()) + m_debugText->typesetGlyphs(overlayText); + } } -specter::View* ViewManager::BuildSpaceViews() -{ - m_rootSpaceView = m_rootSpace->buildSpaceView(m_viewResources); - return m_rootSpaceView; +specter::View* ViewManager::BuildSpaceViews() { + m_rootSpaceView = m_rootSpace->buildSpaceView(m_viewResources); + return m_rootSpaceView; } -specter::RootView* ViewManager::SetupRootView() -{ - m_rootView.reset(new specter::RootView(*this, m_viewResources, m_mainWindow.get())); - m_rootView->setBackground(zeus::CColor::skBlack); - return m_rootView.get(); +specter::RootView* ViewManager::SetupRootView() { + m_rootView.reset(new specter::RootView(*this, m_viewResources, m_mainWindow.get())); + m_rootView->setBackground(zeus::CColor::skBlack); + return m_rootView.get(); } -SplashScreen* ViewManager::SetupSplashView() -{ - m_splash.reset(new SplashScreen(*this, m_viewResources)); - if (!m_showSplash) - m_splash->close(true); - return m_splash.get(); +SplashScreen* ViewManager::SetupSplashView() { + m_splash.reset(new SplashScreen(*this, m_viewResources)); + if (!m_showSplash) + m_splash->close(true); + return m_splash.get(); } -void ViewManager::RootSpaceViewBuilt(specter::View* view) -{ - std::vector& cViews = m_rootView->accessContentViews(); - cViews.clear(); - cViews.push_back(view); - cViews.push_back(m_splash.get()); - m_rootView->updateSize(); +void ViewManager::RootSpaceViewBuilt(specter::View* view) { + std::vector& cViews = m_rootView->accessContentViews(); + cViews.clear(); + cViews.push_back(view); + cViews.push_back(m_splash.get()); + m_rootView->updateSize(); } -void ViewManager::ProjectChanged(hecl::Database::Project& proj) -{ - CDvdFile::Shutdown(); - CDvdFile::Initialize(hecl::ProjectPath(proj.getProjectWorkingPath(), _SYS_STR("out/files"))); +void ViewManager::ProjectChanged(hecl::Database::Project& proj) { + CDvdFile::Shutdown(); + CDvdFile::Initialize(hecl::ProjectPath(proj.getProjectWorkingPath(), _SYS_STR("out/files"))); } -void ViewManager::SetupEditorView() -{ - m_rootSpace.reset(new RootSpace(*this)); +void ViewManager::SetupEditorView() { + m_rootSpace.reset(new RootSpace(*this)); - SplitSpace* split = new SplitSpace(*this, nullptr, specter::SplitView::Axis::Horizontal); - m_rootSpace->setChild(std::unique_ptr(split)); - split->setChildSlot(0, std::make_unique(*this, split)); - split->setChildSlot(1, std::make_unique(*this, split)); + SplitSpace* split = new SplitSpace(*this, nullptr, specter::SplitView::Axis::Horizontal); + m_rootSpace->setChild(std::unique_ptr(split)); + split->setChildSlot(0, std::make_unique(*this, split)); + split->setChildSlot(1, std::make_unique(*this, split)); - BuildSpaceViews(); + BuildSpaceViews(); } -void ViewManager::SetupEditorView(ConfigReader& r) -{ - m_rootSpace.reset(Space::NewRootSpaceFromConfigStream(*this, r)); - BuildSpaceViews(); +void ViewManager::SetupEditorView(ConfigReader& r) { + m_rootSpace.reset(Space::NewRootSpaceFromConfigStream(*this, r)); + BuildSpaceViews(); } -void ViewManager::SaveEditorView(ConfigWriter& w) -{ - if (!m_rootSpace) - return; - m_rootSpace->saveState(w); +void ViewManager::SaveEditorView(ConfigWriter& w) { + if (!m_rootSpace) + return; + m_rootSpace->saveState(w); } -void ViewManager::DismissSplash() -{ - if (!m_showSplash) - return; - m_showSplash = false; - m_splash->close(); +void ViewManager::DismissSplash() { + if (!m_showSplash) + return; + m_showSplash = false; + m_splash->close(); } ViewManager::ViewManager(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr) @@ -217,205 +187,184 @@ ViewManager::ViewManager(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarMan , m_fontCache(fileMgr) , m_translator(urde::SystemLocaleOrEnglish()) , m_recentProjectsPath(hecl::SysFormat(_SYS_STR("%s/recent_projects.txt"), fileMgr.getStoreRoot().data())) -, m_recentFilesPath(hecl::SysFormat(_SYS_STR("%s/recent_files.txt"), fileMgr.getStoreRoot().data())) -{ - Space::SpaceMenuNode::InitializeStrings(*this); - char path[2048]; - hecl::Sstat theStat; +, m_recentFilesPath(hecl::SysFormat(_SYS_STR("%s/recent_files.txt"), fileMgr.getStoreRoot().data())) { + Space::SpaceMenuNode::InitializeStrings(*this); + char path[2048]; + hecl::Sstat theStat; - FILE* fp = hecl::Fopen(m_recentProjectsPath.c_str(), _SYS_STR("r"), hecl::FileLockType::Read); - if (fp) - { - while (fgets(path, 2048, fp)) - { - std::string pathStr(path); - pathStr.pop_back(); - hecl::SystemStringConv pathStrView(pathStr); - if (!hecl::Stat(pathStrView.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) - m_recentProjects.emplace_back(pathStrView.sys_str()); - } - fclose(fp); + FILE* fp = hecl::Fopen(m_recentProjectsPath.c_str(), _SYS_STR("r"), hecl::FileLockType::Read); + if (fp) { + while (fgets(path, 2048, fp)) { + std::string pathStr(path); + pathStr.pop_back(); + hecl::SystemStringConv pathStrView(pathStr); + if (!hecl::Stat(pathStrView.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) + m_recentProjects.emplace_back(pathStrView.sys_str()); } + fclose(fp); + } - fp = hecl::Fopen(m_recentFilesPath.c_str(), _SYS_STR("r"), hecl::FileLockType::Read); - if (fp) - { - while (fgets(path, 2048, fp)) - { - std::string pathStr(path); - pathStr.pop_back(); - hecl::SystemStringConv pathStrView(pathStr); - if (!hecl::Stat(pathStrView.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) - m_recentFiles.emplace_back(pathStrView.sys_str()); - } - fclose(fp); + fp = hecl::Fopen(m_recentFilesPath.c_str(), _SYS_STR("r"), hecl::FileLockType::Read); + if (fp) { + while (fgets(path, 2048, fp)) { + std::string pathStr(path); + pathStr.pop_back(); + hecl::SystemStringConv pathStrView(pathStr); + if (!hecl::Stat(pathStrView.c_str(), &theStat) && S_ISDIR(theStat.st_mode)) + m_recentFiles.emplace_back(pathStrView.sys_str()); } + fclose(fp); + } } ViewManager::~ViewManager() {} -void ViewManager::pushRecentProject(hecl::SystemStringView path) -{ - for (hecl::SystemString& testPath : m_recentProjects) - { - if (path == testPath) - return; - } - m_recentProjects.emplace_back(path); - FILE* fp = hecl::Fopen(m_recentProjectsPath.c_str(), _SYS_STR("w"), hecl::FileLockType::Write); - if (fp) - { - for (hecl::SystemString& pPath : m_recentProjects) - fprintf(fp, "%s\n", hecl::SystemUTF8Conv(pPath).c_str()); - fclose(fp); - } +void ViewManager::pushRecentProject(hecl::SystemStringView path) { + for (hecl::SystemString& testPath : m_recentProjects) { + if (path == testPath) + return; + } + m_recentProjects.emplace_back(path); + FILE* fp = hecl::Fopen(m_recentProjectsPath.c_str(), _SYS_STR("w"), hecl::FileLockType::Write); + if (fp) { + for (hecl::SystemString& pPath : m_recentProjects) + fprintf(fp, "%s\n", hecl::SystemUTF8Conv(pPath).c_str()); + fclose(fp); + } } -void ViewManager::pushRecentFile(hecl::SystemStringView path) -{ - for (hecl::SystemString& testPath : m_recentFiles) - { - if (path == testPath) - return; - } - m_recentFiles.emplace_back(path); - FILE* fp = hecl::Fopen(m_recentFilesPath.c_str(), _SYS_STR("w"), hecl::FileLockType::Write); - if (fp) - { - for (hecl::SystemString& pPath : m_recentFiles) - fprintf(fp, "%s\n", hecl::SystemUTF8Conv(pPath).c_str()); - fclose(fp); - } +void ViewManager::pushRecentFile(hecl::SystemStringView path) { + for (hecl::SystemString& testPath : m_recentFiles) { + if (path == testPath) + return; + } + m_recentFiles.emplace_back(path); + FILE* fp = hecl::Fopen(m_recentFilesPath.c_str(), _SYS_STR("w"), hecl::FileLockType::Write); + if (fp) { + for (hecl::SystemString& pPath : m_recentFiles) + fprintf(fp, "%s\n", hecl::SystemUTF8Conv(pPath).c_str()); + fclose(fp); + } } -void ViewManager::init(boo::IApplication* app) -{ - m_mainWindow = app->newWindow(_SYS_STR("URDE")); - m_mainWindow->showWindow(); - m_mainWindow->setWaitCursor(true); +void ViewManager::init(boo::IApplication* app) { + m_mainWindow = app->newWindow(_SYS_STR("URDE")); + m_mainWindow->showWindow(); + m_mainWindow->setWaitCursor(true); - float pixelFactor = m_mainWindow->getVirtualPixelFactor(); + float pixelFactor = m_mainWindow->getVirtualPixelFactor(); - m_mainBooFactory = m_mainWindow->getMainContextDataFactory(); - m_pipelineConv = hecl::NewPipelineConverter(m_mainBooFactory); - hecl::conv = m_pipelineConv.get(); - m_mainPlatformName = m_mainBooFactory->platformName(); - m_mainWindow->setTitle(_SYS_STR("URDE [") + hecl::SystemString(m_mainPlatformName) + _SYS_STR("]")); - m_mainCommandQueue = m_mainWindow->getCommandQueue(); - m_viewResources.init(m_mainBooFactory, &m_fontCache, &m_themeData, pixelFactor); - InitializeIcons(m_viewResources); - InitializeBadging(m_viewResources); - m_viewResources.prepFontCacheAsync(m_mainWindow.get()); + m_mainBooFactory = m_mainWindow->getMainContextDataFactory(); + m_pipelineConv = hecl::NewPipelineConverter(m_mainBooFactory); + hecl::conv = m_pipelineConv.get(); + m_mainPlatformName = m_mainBooFactory->platformName(); + m_mainWindow->setTitle(_SYS_STR("URDE [") + hecl::SystemString(m_mainPlatformName) + _SYS_STR("]")); + m_mainCommandQueue = m_mainWindow->getCommandQueue(); + m_viewResources.init(m_mainBooFactory, &m_fontCache, &m_themeData, pixelFactor); + InitializeIcons(m_viewResources); + InitializeBadging(m_viewResources); + m_viewResources.prepFontCacheAsync(m_mainWindow.get()); + specter::RootView* root = SetupRootView(); + m_showSplash = true; + root->accessContentViews().push_back(SetupSplashView()); + root->updateSize(); + m_renderTex = root->renderTex(); + m_mainWindow->setWaitCursor(false); + m_voiceEngine = boo::NewAudioVoiceEngine(); + m_voiceEngine->setVolume(0.7f); + m_amuseAllocWrapper.emplace(*m_voiceEngine); + + for (const auto& arg : app->getArgs()) { + if (m_deferedProject.empty() && hecl::SearchForProject(arg)) + m_deferedProject = arg; + if (arg == _SYS_STR("--no-shader-warmup")) + m_noShaderWarmup = true; + else if (arg == _SYS_STR("--no-sound")) + m_voiceEngine->setVolume(0.f); + } + + if (m_deferedProject.empty()) { + /* Default behavior - search upwards for packaged project containing the program */ + if (hecl::ProjectRootPath root = hecl::SearchForProject(ExeDir)) { + hecl::SystemString rootPath(root.getAbsolutePath()); + hecl::Sstat theStat; + if (!hecl::Stat((rootPath + _SYS_STR("/out/files/Metroid1.upak")).c_str(), &theStat) && S_ISREG(theStat.st_mode)) + m_deferedProject = rootPath + _SYS_STR("/out"); + } + } +} + +bool ViewManager::proc() { + if (!m_deferedProject.empty() && m_viewResources.fontCacheReady()) { + m_projManager.openProject(m_deferedProject); + m_deferedProject.clear(); + } + + boo::IGraphicsCommandQueue* gfxQ = m_mainWindow->getCommandQueue(); + if (m_rootView->isDestroyed()) + return false; + + if (m_updatePf) { + m_viewResources.resetPixelFactor(m_reqPf); specter::RootView* root = SetupRootView(); - m_showSplash = true; - root->accessContentViews().push_back(SetupSplashView()); - root->updateSize(); - m_renderTex = root->renderTex(); - m_mainWindow->setWaitCursor(false); - m_voiceEngine = boo::NewAudioVoiceEngine(); - m_voiceEngine->setVolume(0.7f); - m_amuseAllocWrapper.emplace(*m_voiceEngine); - - for (const auto& arg : app->getArgs()) - { - if (m_deferedProject.empty() && hecl::SearchForProject(arg)) - m_deferedProject = arg; - if (arg == _SYS_STR("--no-shader-warmup")) - m_noShaderWarmup = true; - else if (arg == _SYS_STR("--no-sound")) - m_voiceEngine->setVolume(0.f); - } - - if (m_deferedProject.empty()) - { - /* Default behavior - search upwards for packaged project containing the program */ - if (hecl::ProjectRootPath root = hecl::SearchForProject(ExeDir)) - { - hecl::SystemString rootPath(root.getAbsolutePath()); - hecl::Sstat theStat; - if (!hecl::Stat((rootPath + _SYS_STR("/out/files/Metroid1.upak")).c_str(), &theStat) && S_ISREG(theStat.st_mode)) - m_deferedProject = rootPath + _SYS_STR("/out"); - } - } -} - -bool ViewManager::proc() -{ - if (!m_deferedProject.empty() && m_viewResources.fontCacheReady()) - { - m_projManager.openProject(m_deferedProject); - m_deferedProject.clear(); - } - - boo::IGraphicsCommandQueue* gfxQ = m_mainWindow->getCommandQueue(); - if (m_rootView->isDestroyed()) - return false; - - if (m_updatePf) - { - m_viewResources.resetPixelFactor(m_reqPf); - specter::RootView* root = SetupRootView(); - if (m_rootSpace) - BuildSpaceViews(); - else - { - std::vector& cViews = m_rootView->accessContentViews(); - cViews.push_back(SetupSplashView()); - } - root->updateSize(); - m_updatePf = false; - } - - m_rootView->dispatchEvents(); - m_rootView->internalThink(); if (m_rootSpace) - m_rootSpace->think(); - if (m_splash) - m_splash->think(); - - if (m_deferSplit) - { - SplitSpace* ss = static_cast(m_deferSplit->spaceSplit(m_deferSplitAxis, m_deferSplitThisSlot)); - m_rootView->startSplitDrag(ss->splitView(), m_deferSplitCoord); - m_deferSplit = nullptr; + BuildSpaceViews(); + else { + std::vector& cViews = m_rootView->accessContentViews(); + cViews.push_back(SetupSplashView()); } + root->updateSize(); + m_updatePf = false; + } - ++m_editorFrames; - if (m_rootSpaceView && m_editorFrames <= 30) - m_rootSpaceView->setMultiplyColor(zeus::CColor::lerp({1, 1, 1, 0}, {1, 1, 1, 1}, m_editorFrames / 30.0)); + m_rootView->dispatchEvents(); + m_rootView->internalThink(); + if (m_rootSpace) + m_rootSpace->think(); + if (m_splash) + m_splash->think(); - m_projManager.mainUpdate(); + if (m_deferSplit) { + SplitSpace* ss = static_cast(m_deferSplit->spaceSplit(m_deferSplitAxis, m_deferSplitThisSlot)); + m_rootView->startSplitDrag(ss->splitView(), m_deferSplitCoord); + m_deferSplit = nullptr; + } - if (m_testGameView) - m_testGameView->think(); + ++m_editorFrames; + if (m_rootSpaceView && m_editorFrames <= 30) + m_rootSpaceView->setMultiplyColor(zeus::CColor::lerp({1, 1, 1, 0}, {1, 1, 1, 1}, m_editorFrames / 30.0)); - if (g_Renderer) - g_Renderer->BeginScene(); - m_rootView->draw(gfxQ); - if (g_Renderer) - g_Renderer->EndScene(); - gfxQ->execute(); - if (g_ResFactory) - g_ResFactory->AsyncIdle(); - m_voiceEngine->pumpAndMixVoices(); - if (!m_skipWait || !hecl::com_developer->toBoolean()) - m_mainWindow->waitForRetrace(); - CBooModel::ClearModelUniformCounters(); - CGraphics::TickRenderTimings(); - ++logvisor::FrameIndex; - return true; + m_projManager.mainUpdate(); + + if (m_testGameView) + m_testGameView->think(); + + if (g_Renderer) + g_Renderer->BeginScene(); + m_rootView->draw(gfxQ); + if (g_Renderer) + g_Renderer->EndScene(); + gfxQ->execute(); + if (g_ResFactory) + g_ResFactory->AsyncIdle(); + m_voiceEngine->pumpAndMixVoices(); + if (!m_skipWait || !hecl::com_developer->toBoolean()) + m_mainWindow->waitForRetrace(); + CBooModel::ClearModelUniformCounters(); + CGraphics::TickRenderTimings(); + ++logvisor::FrameIndex; + return true; } -void ViewManager::stop() -{ - m_videoVoice.reset(); - m_projManager.shutdown(); - CDvdFile::Shutdown(); - DestroyIcons(); - DestroyBadging(); - m_viewResources.destroyResData(); - m_fontCache.destroyAtlases(); - m_mainWindow->getCommandQueue()->stopRenderer(); +void ViewManager::stop() { + m_videoVoice.reset(); + m_projManager.shutdown(); + CDvdFile::Shutdown(); + DestroyIcons(); + DestroyBadging(); + m_viewResources.destroyResData(); + m_fontCache.destroyAtlases(); + m_mainWindow->getCommandQueue()->stopRenderer(); } } // namespace urde diff --git a/Editor/ViewManager.hpp b/Editor/ViewManager.hpp index 7685825dc..6ba7c0ec6 100644 --- a/Editor/ViewManager.hpp +++ b/Editor/ViewManager.hpp @@ -21,186 +21,174 @@ #include "Runtime/Graphics/Shaders/CCameraBlurFilter.hpp" #include "Runtime/Audio/CStaticAudioPlayer.hpp" -namespace hecl { class PipelineConverterBase; } - -namespace urde -{ -class SplashScreen; - -class ViewManager final : public specter::IViewManager -{ - friend class ProjectManager; - friend class Space; - friend class RootSpace; - friend class SplitSpace; - - std::shared_ptr m_mainWindow; - hecl::Runtime::FileStoreManager& m_fileStoreManager; - hecl::CVarManager& m_cvarManager; - ProjectManager m_projManager; - specter::FontCache m_fontCache; - specter::DefaultThemeData m_themeData; - specter::ViewResources m_viewResources; - specter::Translator m_translator; - boo::IGraphicsDataFactory* m_mainBooFactory = nullptr; - boo::IGraphicsCommandQueue* m_mainCommandQueue = nullptr; - std::unique_ptr m_pipelineConv; - boo::ObjToken m_renderTex; - const boo::SystemChar* m_mainPlatformName; - - std::unique_ptr m_rootView; - std::unique_ptr m_splash; - std::unique_ptr m_rootSpace; - specter::View* m_rootSpaceView = nullptr; - bool m_skipWait = false; - - class TestGameView : public specter::View - { - ViewManager& m_vm; - std::unique_ptr m_debugText; - public: - TestGameView(ViewManager& vm, specter::ViewResources& res, specter::View& parent) - : View(res, parent), m_vm(vm) {} - void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); - void draw(boo::IGraphicsCommandQueue* gfxQ); - void think(); - - void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mkey) - { - if (MP1::CMain* m = m_vm.m_projManager.gameMain()) - if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) - as->mouseDown(coord, button, mkey); - } - - void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mkey) - { - if (MP1::CMain* m = m_vm.m_projManager.gameMain()) - if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) - as->mouseUp(coord, button, mkey); - } - - void mouseMove(const boo::SWindowCoord& coord) - { - if (MP1::CMain* m = m_vm.m_projManager.gameMain()) - if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) - as->mouseMove(coord); - } - - void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& sd) - { - if (MP1::CMain* m = m_vm.m_projManager.gameMain()) - if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) - as->scroll(coord, sd); - } - - void charKeyDown(unsigned long cc, boo::EModifierKey mkey, bool repeat) - { - if (MP1::CMain* m = m_vm.m_projManager.gameMain()) - if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) - as->charKeyDown(cc, mkey, repeat); - } - - void charKeyUp(unsigned long cc, boo::EModifierKey mkey) - { - if (MP1::CMain* m = m_vm.m_projManager.gameMain()) - if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) - as->charKeyUp(cc, mkey); - } - - void specialKeyDown(boo::ESpecialKey skey, boo::EModifierKey mkey, bool repeat) - { - if (MP1::CMain* m = m_vm.m_projManager.gameMain()) - if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) - as->specialKeyDown(skey, mkey, repeat); - - if (skey == boo::ESpecialKey::F1) - m_vm.m_skipWait = true; - } - - void specialKeyUp(boo::ESpecialKey skey, boo::EModifierKey mkey) - { - if (MP1::CMain* m = m_vm.m_projManager.gameMain()) - if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) - as->specialKeyUp(skey, mkey); - - if (skey == boo::ESpecialKey::F1) - m_vm.m_skipWait = false; - } - }; - std::unique_ptr m_testGameView; - std::unique_ptr m_voiceEngine; - std::unique_ptr m_videoVoice; - std::experimental::optional m_amuseAllocWrapper; - - hecl::SystemString m_recentProjectsPath; - std::vector m_recentProjects; - hecl::SystemString m_recentFilesPath; - std::vector m_recentFiles; - - bool m_updatePf = false; - float m_reqPf; - - specter::View* BuildSpaceViews(); - specter::RootView* SetupRootView(); - SplashScreen* SetupSplashView(); - void RootSpaceViewBuilt(specter::View* view); - void ProjectChanged(hecl::Database::Project& proj); - void SetupEditorView(); - void SetupEditorView(ConfigReader& r); - void SaveEditorView(ConfigWriter& w); - - bool m_showSplash = false; - void DismissSplash(); - - unsigned m_editorFrames = 120; - void FadeInEditors() {m_editorFrames = 0;} - - void InitMP1(MP1::CMain& main); - - Space* m_deferSplit = nullptr; - specter::SplitView::Axis m_deferSplitAxis; - int m_deferSplitThisSlot; - boo::SWindowCoord m_deferSplitCoord; - hecl::SystemString m_deferedProject; - bool m_noShaderWarmup = false; - -public: - ViewManager(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr); - ~ViewManager(); - - specter::RootView& rootView() const {return *m_rootView;} - void requestPixelFactor(float pf) - { - m_reqPf = pf; - m_updatePf = true; - } - - ProjectManager& projectManager() {return m_projManager;} - hecl::Database::Project* project() {return m_projManager.project();} - const specter::Translator* getTranslator() const {return &m_translator;} - - void deferSpaceSplit(specter::ISpaceController* split, specter::SplitView::Axis axis, int thisSlot, - const boo::SWindowCoord& coord) - { - m_deferSplit = static_cast(split); - m_deferSplitAxis = axis; - m_deferSplitThisSlot = thisSlot; - m_deferSplitCoord = coord; - } - - const std::vector* recentProjects() const {return &m_recentProjects;} - void pushRecentProject(hecl::SystemStringView path); - - const std::vector* recentFiles() const {return &m_recentFiles;} - void pushRecentFile(hecl::SystemStringView path); - - void init(boo::IApplication* app); - const boo::SystemChar* platformName() { return m_mainPlatformName; } - bool proc(); - void stop(); - - void deferOpenProject(const hecl::SystemString& path) { m_deferedProject = path; } -}; - +namespace hecl { +class PipelineConverterBase; } +namespace urde { +class SplashScreen; + +class ViewManager final : public specter::IViewManager { + friend class ProjectManager; + friend class Space; + friend class RootSpace; + friend class SplitSpace; + + std::shared_ptr m_mainWindow; + hecl::Runtime::FileStoreManager& m_fileStoreManager; + hecl::CVarManager& m_cvarManager; + ProjectManager m_projManager; + specter::FontCache m_fontCache; + specter::DefaultThemeData m_themeData; + specter::ViewResources m_viewResources; + specter::Translator m_translator; + boo::IGraphicsDataFactory* m_mainBooFactory = nullptr; + boo::IGraphicsCommandQueue* m_mainCommandQueue = nullptr; + std::unique_ptr m_pipelineConv; + boo::ObjToken m_renderTex; + const boo::SystemChar* m_mainPlatformName; + + std::unique_ptr m_rootView; + std::unique_ptr m_splash; + std::unique_ptr m_rootSpace; + specter::View* m_rootSpaceView = nullptr; + bool m_skipWait = false; + + class TestGameView : public specter::View { + ViewManager& m_vm; + std::unique_ptr m_debugText; + + public: + TestGameView(ViewManager& vm, specter::ViewResources& res, specter::View& parent) : View(res, parent), m_vm(vm) {} + void resized(const boo::SWindowRect& root, const boo::SWindowRect& sub); + void draw(boo::IGraphicsCommandQueue* gfxQ); + void think(); + + void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mkey) { + if (MP1::CMain* m = m_vm.m_projManager.gameMain()) + if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) + as->mouseDown(coord, button, mkey); + } + + void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mkey) { + if (MP1::CMain* m = m_vm.m_projManager.gameMain()) + if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) + as->mouseUp(coord, button, mkey); + } + + void mouseMove(const boo::SWindowCoord& coord) { + if (MP1::CMain* m = m_vm.m_projManager.gameMain()) + if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) + as->mouseMove(coord); + } + + void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& sd) { + if (MP1::CMain* m = m_vm.m_projManager.gameMain()) + if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) + as->scroll(coord, sd); + } + + void charKeyDown(unsigned long cc, boo::EModifierKey mkey, bool repeat) { + if (MP1::CMain* m = m_vm.m_projManager.gameMain()) + if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) + as->charKeyDown(cc, mkey, repeat); + } + + void charKeyUp(unsigned long cc, boo::EModifierKey mkey) { + if (MP1::CMain* m = m_vm.m_projManager.gameMain()) + if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) + as->charKeyUp(cc, mkey); + } + + void specialKeyDown(boo::ESpecialKey skey, boo::EModifierKey mkey, bool repeat) { + if (MP1::CMain* m = m_vm.m_projManager.gameMain()) + if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) + as->specialKeyDown(skey, mkey, repeat); + + if (skey == boo::ESpecialKey::F1) + m_vm.m_skipWait = true; + } + + void specialKeyUp(boo::ESpecialKey skey, boo::EModifierKey mkey) { + if (MP1::CMain* m = m_vm.m_projManager.gameMain()) + if (MP1::CGameArchitectureSupport* as = m->GetArchSupport()) + as->specialKeyUp(skey, mkey); + + if (skey == boo::ESpecialKey::F1) + m_vm.m_skipWait = false; + } + }; + std::unique_ptr m_testGameView; + std::unique_ptr m_voiceEngine; + std::unique_ptr m_videoVoice; + std::experimental::optional m_amuseAllocWrapper; + + hecl::SystemString m_recentProjectsPath; + std::vector m_recentProjects; + hecl::SystemString m_recentFilesPath; + std::vector m_recentFiles; + + bool m_updatePf = false; + float m_reqPf; + + specter::View* BuildSpaceViews(); + specter::RootView* SetupRootView(); + SplashScreen* SetupSplashView(); + void RootSpaceViewBuilt(specter::View* view); + void ProjectChanged(hecl::Database::Project& proj); + void SetupEditorView(); + void SetupEditorView(ConfigReader& r); + void SaveEditorView(ConfigWriter& w); + + bool m_showSplash = false; + void DismissSplash(); + + unsigned m_editorFrames = 120; + void FadeInEditors() { m_editorFrames = 0; } + + void InitMP1(MP1::CMain& main); + + Space* m_deferSplit = nullptr; + specter::SplitView::Axis m_deferSplitAxis; + int m_deferSplitThisSlot; + boo::SWindowCoord m_deferSplitCoord; + hecl::SystemString m_deferedProject; + bool m_noShaderWarmup = false; + +public: + ViewManager(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr); + ~ViewManager(); + + specter::RootView& rootView() const { return *m_rootView; } + void requestPixelFactor(float pf) { + m_reqPf = pf; + m_updatePf = true; + } + + ProjectManager& projectManager() { return m_projManager; } + hecl::Database::Project* project() { return m_projManager.project(); } + const specter::Translator* getTranslator() const { return &m_translator; } + + void deferSpaceSplit(specter::ISpaceController* split, specter::SplitView::Axis axis, int thisSlot, + const boo::SWindowCoord& coord) { + m_deferSplit = static_cast(split); + m_deferSplitAxis = axis; + m_deferSplitThisSlot = thisSlot; + m_deferSplitCoord = coord; + } + + const std::vector* recentProjects() const { return &m_recentProjects; } + void pushRecentProject(hecl::SystemStringView path); + + const std::vector* recentFiles() const { return &m_recentFiles; } + void pushRecentFile(hecl::SystemStringView path); + + void init(boo::IApplication* app); + const boo::SystemChar* platformName() { return m_mainPlatformName; } + bool proc(); + void stop(); + + void deferOpenProject(const hecl::SystemString& path) { m_deferedProject = path; } +}; + +} // namespace urde diff --git a/Editor/badging/Badging.cpp b/Editor/badging/Badging.cpp index b1d1e0d1f..ce9db10b2 100644 --- a/Editor/badging/Badging.cpp +++ b/Editor/badging/Badging.cpp @@ -5,49 +5,39 @@ extern "C" uint8_t URDE_BADGE[]; extern "C" size_t URDE_BADGE_SZ; -namespace urde -{ +namespace urde { static logvisor::Module Log("URDE::badging"); static specter::Icon g_BadgeIcon; -void InitializeBadging(specter::ViewResources& viewRes) -{ - athena::io::MemoryReader r(URDE_BADGE, URDE_BADGE_SZ); +void InitializeBadging(specter::ViewResources& viewRes) { + athena::io::MemoryReader r(URDE_BADGE, URDE_BADGE_SZ); - size_t fmt = r.readUint32Big(); - if (fmt != 16) - Log.report(logvisor::Fatal, "incorrect icon texture format"); - size_t width = r.readUint16Big(); - size_t height = r.readUint16Big(); - size_t mips = r.readUint32Big(); - size_t decompSz = r.readUint32Big(); + size_t fmt = r.readUint32Big(); + if (fmt != 16) + Log.report(logvisor::Fatal, "incorrect icon texture format"); + size_t width = r.readUint16Big(); + size_t height = r.readUint16Big(); + size_t mips = r.readUint32Big(); + size_t decompSz = r.readUint32Big(); - std::unique_ptr texels(new uint8_t[decompSz]); - uLongf destSz = decompSz; - size_t pos = r.position(); - if (uncompress(texels.get(), &destSz, URDE_BADGE + pos, URDE_BADGE_SZ - pos) != Z_OK) - Log.report(logvisor::Fatal, "unable to decompress badge"); + std::unique_ptr texels(new uint8_t[decompSz]); + uLongf destSz = decompSz; + size_t pos = r.position(); + if (uncompress(texels.get(), &destSz, URDE_BADGE + pos, URDE_BADGE_SZ - pos) != Z_OK) + Log.report(logvisor::Fatal, "unable to decompress badge"); - viewRes.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) - { - specter::IconAtlas<1, 1> atlas; + viewRes.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) { + specter::IconAtlas<1, 1> atlas; - atlas.initializeAtlas(ctx.newStaticTexture(width, height, mips, - boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, - texels.get(), destSz)); - g_BadgeIcon = atlas.getIcon(0, 0); - return true; - } BooTrace); + atlas.initializeAtlas(ctx.newStaticTexture(width, height, mips, boo::TextureFormat::RGBA8, + boo::TextureClampMode::Repeat, texels.get(), destSz)); + g_BadgeIcon = atlas.getIcon(0, 0); + return true; + } BooTrace); } -void DestroyBadging() -{ - g_BadgeIcon.m_tex.reset(); -} +void DestroyBadging() { g_BadgeIcon.m_tex.reset(); } -specter::Icon& GetBadge() -{ - return g_BadgeIcon; -} +specter::Icon& GetBadge() { return g_BadgeIcon; } -} +} // namespace urde diff --git a/Editor/badging/Badging.hpp b/Editor/badging/Badging.hpp index 39c2a4d5f..f7dd6b7e4 100644 --- a/Editor/badging/Badging.hpp +++ b/Editor/badging/Badging.hpp @@ -2,15 +2,13 @@ #include "specter/ViewResources.hpp" -namespace urde -{ +namespace urde { void InitializeBadging(specter::ViewResources& viewRes); void DestroyBadging(); specter::Icon& GetBadge(); -} +} // namespace urde #ifndef BADGE_PHRASE #define BADGE_PHRASE "Prototype" #endif - diff --git a/Editor/icons/icons.cpp b/Editor/icons/icons.cpp index 272c10507..a981f4aaa 100644 --- a/Editor/icons/icons.cpp +++ b/Editor/icons/icons.cpp @@ -5,102 +5,90 @@ extern "C" uint8_t URDE_ICONS[]; extern "C" size_t URDE_ICONS_SZ; -namespace urde -{ +namespace urde { static logvisor::Module Log("URDE::icons"); -specter::IconAtlas<8,8> g_IconAtlas; +specter::IconAtlas<8, 8> g_IconAtlas; -void InitializeIcons(specter::ViewResources& viewRes) -{ - athena::io::MemoryReader r(URDE_ICONS, URDE_ICONS_SZ); - size_t fmt = r.readUint32Big(); - if (fmt != 16) - Log.report(logvisor::Fatal, "incorrect icon texture format"); - size_t width = r.readUint16Big(); - size_t height = r.readUint16Big(); - size_t mips = r.readUint32Big(); - size_t decompSz = r.readUint32Big(); +void InitializeIcons(specter::ViewResources& viewRes) { + athena::io::MemoryReader r(URDE_ICONS, URDE_ICONS_SZ); + size_t fmt = r.readUint32Big(); + if (fmt != 16) + Log.report(logvisor::Fatal, "incorrect icon texture format"); + size_t width = r.readUint16Big(); + size_t height = r.readUint16Big(); + size_t mips = r.readUint32Big(); + size_t decompSz = r.readUint32Big(); - std::unique_ptr texels(new uint8_t[decompSz]); - uLongf destSz = decompSz; - size_t pos = r.position(); - if (uncompress(texels.get(), &destSz, URDE_ICONS + pos, URDE_ICONS_SZ - pos) != Z_OK) - Log.report(logvisor::Fatal, "unable to decompress icons"); + std::unique_ptr texels(new uint8_t[decompSz]); + uLongf destSz = decompSz; + size_t pos = r.position(); + if (uncompress(texels.get(), &destSz, URDE_ICONS + pos, URDE_ICONS_SZ - pos) != Z_OK) + Log.report(logvisor::Fatal, "unable to decompress icons"); - viewRes.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) - { - g_IconAtlas.initializeAtlas(ctx.newStaticTexture(width, height, mips, - boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, - texels.get(), destSz)); - return true; - } BooTrace); + viewRes.m_factory->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) { + g_IconAtlas.initializeAtlas(ctx.newStaticTexture(width, height, mips, boo::TextureFormat::RGBA8, + boo::TextureClampMode::Repeat, texels.get(), destSz)); + return true; + } BooTrace); } -void DestroyIcons() -{ - g_IconAtlas.destroyAtlas(); +void DestroyIcons() { g_IconAtlas.destroyAtlas(); } + +specter::Icon& GetIcon(SpaceIcon icon) { + switch (icon) { + case SpaceIcon::ResourceBrowser: + return g_IconAtlas.getIcon(0, 0); + case SpaceIcon::ParticleEditor: + return g_IconAtlas.getIcon(0, 1); + case SpaceIcon::WorldEditor: + return g_IconAtlas.getIcon(0, 2); + case SpaceIcon::InformationCenter: + return g_IconAtlas.getIcon(0, 3); + case SpaceIcon::ModelViewer: + return g_IconAtlas.getIcon(0, 4); + case SpaceIcon::GameMode: + return g_IconAtlas.getIcon(0, 5); + default: + return g_IconAtlas.getIcon(6, 0); + } } -specter::Icon& GetIcon(SpaceIcon icon) -{ - switch (icon) - { - case SpaceIcon::ResourceBrowser: - return g_IconAtlas.getIcon(0, 0); - case SpaceIcon::ParticleEditor: - return g_IconAtlas.getIcon(0, 1); - case SpaceIcon::WorldEditor: - return g_IconAtlas.getIcon(0, 2); - case SpaceIcon::InformationCenter: - return g_IconAtlas.getIcon(0, 3); - case SpaceIcon::ModelViewer: - return g_IconAtlas.getIcon(0, 4); - case SpaceIcon::GameMode: - return g_IconAtlas.getIcon(0, 5); - default: - return g_IconAtlas.getIcon(6, 0); - } +specter::Icon& GetIcon(MonoIcon icon) { + switch (icon) { + case MonoIcon::Sync: + return g_IconAtlas.getIcon(7, 0); + case MonoIcon::Edit: + return g_IconAtlas.getIcon(7, 1); + case MonoIcon::Caution: + return g_IconAtlas.getIcon(7, 2); + case MonoIcon::Save: + return g_IconAtlas.getIcon(7, 3); + case MonoIcon::Filter: + return g_IconAtlas.getIcon(7, 4); + case MonoIcon::Document: + return g_IconAtlas.getIcon(7, 5); + case MonoIcon::ZoomOut: + return g_IconAtlas.getIcon(7, 6); + case MonoIcon::ZoomIn: + return g_IconAtlas.getIcon(7, 7); + case MonoIcon::Exclaim: + return g_IconAtlas.getIcon(6, 0); + case MonoIcon::Clock: + return g_IconAtlas.getIcon(6, 1); + case MonoIcon::Gamepad: + return g_IconAtlas.getIcon(6, 2); + case MonoIcon::Unlink: + return g_IconAtlas.getIcon(6, 3); + case MonoIcon::Link: + return g_IconAtlas.getIcon(6, 4); + case MonoIcon::Folder: + return g_IconAtlas.getIcon(6, 5); + case MonoIcon::Info: + return g_IconAtlas.getIcon(6, 6); + default: + return g_IconAtlas.getIcon(6, 0); + } } -specter::Icon& GetIcon(MonoIcon icon) -{ - switch (icon) - { - case MonoIcon::Sync: - return g_IconAtlas.getIcon(7, 0); - case MonoIcon::Edit: - return g_IconAtlas.getIcon(7, 1); - case MonoIcon::Caution: - return g_IconAtlas.getIcon(7, 2); - case MonoIcon::Save: - return g_IconAtlas.getIcon(7, 3); - case MonoIcon::Filter: - return g_IconAtlas.getIcon(7, 4); - case MonoIcon::Document: - return g_IconAtlas.getIcon(7, 5); - case MonoIcon::ZoomOut: - return g_IconAtlas.getIcon(7, 6); - case MonoIcon::ZoomIn: - return g_IconAtlas.getIcon(7, 7); - case MonoIcon::Exclaim: - return g_IconAtlas.getIcon(6, 0); - case MonoIcon::Clock: - return g_IconAtlas.getIcon(6, 1); - case MonoIcon::Gamepad: - return g_IconAtlas.getIcon(6, 2); - case MonoIcon::Unlink: - return g_IconAtlas.getIcon(6, 3); - case MonoIcon::Link: - return g_IconAtlas.getIcon(6, 4); - case MonoIcon::Folder: - return g_IconAtlas.getIcon(6, 5); - case MonoIcon::Info: - return g_IconAtlas.getIcon(6, 6); - default: - return g_IconAtlas.getIcon(6, 0); - } -} - -} +} // namespace urde diff --git a/Editor/icons/icons.hpp b/Editor/icons/icons.hpp index 0d7ad301a..f2ebd1a3b 100644 --- a/Editor/icons/icons.hpp +++ b/Editor/icons/icons.hpp @@ -3,42 +3,31 @@ #include "specter/Icon.hpp" #include "specter/ViewResources.hpp" -namespace urde -{ +namespace urde { void InitializeIcons(specter::ViewResources& viewRes); void DestroyIcons(); -enum class SpaceIcon -{ - ResourceBrowser, - ParticleEditor, - WorldEditor, - ModelViewer, - InformationCenter, - GameMode -}; +enum class SpaceIcon { ResourceBrowser, ParticleEditor, WorldEditor, ModelViewer, InformationCenter, GameMode }; specter::Icon& GetIcon(SpaceIcon icon); -enum class MonoIcon -{ - Sync, - Edit, - Caution, - Save, - Filter, - Document, - ZoomOut, - ZoomIn, +enum class MonoIcon { + Sync, + Edit, + Caution, + Save, + Filter, + Document, + ZoomOut, + ZoomIn, - Exclaim, - Clock, - Gamepad, - Unlink, - Link, - Folder, - Info + Exclaim, + Clock, + Gamepad, + Unlink, + Link, + Folder, + Info }; specter::Icon& GetIcon(MonoIcon icon); -} - +} // namespace urde diff --git a/Editor/locale b/Editor/locale index aa6705c84..c649fe216 160000 --- a/Editor/locale +++ b/Editor/locale @@ -1 +1 @@ -Subproject commit aa6705c84714ed9da49a8613d9f3bdc46328ea54 +Subproject commit c649fe216d3ca3c10c518812e61591316fe0ad22 diff --git a/Editor/main.cpp b/Editor/main.cpp index e7179cfbb..73abb7541 100644 --- a/Editor/main.cpp +++ b/Editor/main.cpp @@ -9,192 +9,160 @@ #include "hecl/Console.hpp" static logvisor::Module AthenaLog("Athena"); -static void AthenaExc(athena::error::Level level, const char* file, - const char*, int line, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - AthenaLog.report(logvisor::Level(level), fmt, ap); - va_end(ap); +static void AthenaExc(athena::error::Level level, const char* file, const char*, int line, const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + AthenaLog.report(logvisor::Level(level), fmt, ap); + va_end(ap); } -namespace urde -{ +namespace urde { static logvisor::Module Log{"URDE"}; -static hecl::SystemString CPUFeatureString(const zeus::CPUInfo& cpuInf) -{ - hecl::SystemString features; - auto AddFeature = [&features](const hecl::SystemChar* str) - { - if (!features.empty()) - features += _SYS_STR(", "); - features += str; - }; - if (cpuInf.AESNI) - AddFeature(_SYS_STR("AES-NI")); - if (cpuInf.SSE1) - AddFeature(_SYS_STR("SSE")); - if (cpuInf.SSE2) - AddFeature(_SYS_STR("SSE2")); - if (cpuInf.SSE3) - AddFeature(_SYS_STR("SSE3")); - if (cpuInf.SSSE3) - AddFeature(_SYS_STR("SSSE3")); - if (cpuInf.SSE4a) - AddFeature(_SYS_STR("SSE4a")); - if (cpuInf.SSE41) - AddFeature(_SYS_STR("SSE4.1")); - if (cpuInf.SSE42) - AddFeature(_SYS_STR("SSE4.2")); - if (cpuInf.AVX) - AddFeature(_SYS_STR("AVX")); - if (cpuInf.AVX2) - AddFeature(_SYS_STR("AVX2")); - return features; +static hecl::SystemString CPUFeatureString(const zeus::CPUInfo& cpuInf) { + hecl::SystemString features; + auto AddFeature = [&features](const hecl::SystemChar* str) { + if (!features.empty()) + features += _SYS_STR(", "); + features += str; + }; + if (cpuInf.AESNI) + AddFeature(_SYS_STR("AES-NI")); + if (cpuInf.SSE1) + AddFeature(_SYS_STR("SSE")); + if (cpuInf.SSE2) + AddFeature(_SYS_STR("SSE2")); + if (cpuInf.SSE3) + AddFeature(_SYS_STR("SSE3")); + if (cpuInf.SSSE3) + AddFeature(_SYS_STR("SSSE3")); + if (cpuInf.SSE4a) + AddFeature(_SYS_STR("SSE4a")); + if (cpuInf.SSE41) + AddFeature(_SYS_STR("SSE4.1")); + if (cpuInf.SSE42) + AddFeature(_SYS_STR("SSE4.2")); + if (cpuInf.AVX) + AddFeature(_SYS_STR("AVX")); + if (cpuInf.AVX2) + AddFeature(_SYS_STR("AVX2")); + return features; } -struct Application : boo::IApplicationCallback -{ - hecl::Runtime::FileStoreManager m_fileMgr; - hecl::CVarManager m_cvarManager; - hecl::CVarCommons m_cvarCommons; - std::unique_ptr m_viewManager; +struct Application : boo::IApplicationCallback { + hecl::Runtime::FileStoreManager m_fileMgr; + hecl::CVarManager m_cvarManager; + hecl::CVarCommons m_cvarCommons; + std::unique_ptr m_viewManager; - std::atomic_bool m_running = {true}; + std::atomic_bool m_running = {true}; - Application() : - m_fileMgr(_SYS_STR("urde")), - m_cvarManager(m_fileMgr), - m_cvarCommons(m_cvarManager) - { - m_viewManager = std::make_unique(m_fileMgr, m_cvarManager); + Application() : m_fileMgr(_SYS_STR("urde")), m_cvarManager(m_fileMgr), m_cvarCommons(m_cvarManager) { + m_viewManager = std::make_unique(m_fileMgr, m_cvarManager); + } + + virtual ~Application() = default; + + int appMain(boo::IApplication* app) { + initialize(app); + m_viewManager->init(app); + while (m_running.load()) { + if (!m_viewManager->proc()) + break; + } + m_viewManager->stop(); + m_viewManager->projectManager().saveProject(); + m_cvarManager.serialize(); + m_viewManager.reset(); + return 0; + } + void appQuitting(boo::IApplication*) { m_running.store(false); } + void appFilesOpen(boo::IApplication*, const std::vector& paths) { + for (const auto& path : paths) { + hecl::ProjectRootPath projPath = hecl::SearchForProject(path); + if (projPath) { + m_viewManager->deferOpenProject(path); + break; + } + } + } + + void initialize(boo::IApplication* app) { + zeus::detectCPU(); + createGlobalCVars(); + for (const boo::SystemString& arg : app->getArgs()) { + if (arg.find(_SYS_STR("--verbosity=")) == 0 || arg.find(_SYS_STR("-v=")) == 0) { + hecl::SystemUTF8Conv utf8Arg(arg.substr(arg.find_last_of('=') + 1)); + hecl::VerbosityLevel = atoi(utf8Arg.c_str()); + hecl::LogModule.report(logvisor::Info, "Set verbosity level to %i", hecl::VerbosityLevel); + } } - virtual ~Application() = default; + m_cvarManager.parseCommandLine(app->getArgs()); - int appMain(boo::IApplication* app) - { - initialize(app); - m_viewManager->init(app); - while (m_running.load()) - { - if (!m_viewManager->proc()) - break; - } - m_viewManager->stop(); - m_viewManager->projectManager().saveProject(); - m_cvarManager.serialize(); - m_viewManager.reset(); - return 0; - } - void appQuitting(boo::IApplication*) - { - m_running.store(false); - } - void appFilesOpen(boo::IApplication*, const std::vector& paths) - { - for (const auto& path : paths) - { - hecl::ProjectRootPath projPath = hecl::SearchForProject(path); - if (projPath) - { - m_viewManager->deferOpenProject(path); - break; - } - } - } + const zeus::CPUInfo& cpuInf = zeus::cpuFeatures(); + Log.report(logvisor::Info, "CPU Name: %s", cpuInf.cpuBrand); + Log.report(logvisor::Info, "CPU Vendor: %s", cpuInf.cpuVendor); + Log.report(logvisor::Info, _SYS_STR("CPU Features: %s"), CPUFeatureString(cpuInf).c_str()); + } - void initialize(boo::IApplication* app) - { - zeus::detectCPU(); - createGlobalCVars(); - for (const boo::SystemString& arg : app->getArgs()) - { - if (arg.find(_SYS_STR("--verbosity=")) == 0 || arg.find(_SYS_STR("-v=")) == 0) - { - hecl::SystemUTF8Conv utf8Arg(arg.substr(arg.find_last_of('=') + 1)); - hecl::VerbosityLevel = atoi(utf8Arg.c_str()); - hecl::LogModule.report(logvisor::Info, "Set verbosity level to %i", hecl::VerbosityLevel); - } - } + std::string getGraphicsApi() const { return m_cvarCommons.getGraphicsApi(); } - m_cvarManager.parseCommandLine(app->getArgs()); + uint32_t getSamples() const { return m_cvarCommons.getSamples(); } - const zeus::CPUInfo& cpuInf = zeus::cpuFeatures(); - Log.report(logvisor::Info, "CPU Name: %s", cpuInf.cpuBrand); - Log.report(logvisor::Info, "CPU Vendor: %s", cpuInf.cpuVendor); - Log.report(logvisor::Info, _SYS_STR("CPU Features: %s"), CPUFeatureString(cpuInf).c_str()); - } + uint32_t getAnisotropy() const { return m_cvarCommons.getAnisotropy(); } - std::string getGraphicsApi() const - { - return m_cvarCommons.getGraphicsApi(); - } + bool getDeepColor() const { return m_cvarCommons.getDeepColor(); } - uint32_t getSamples() const - { - return m_cvarCommons.getSamples(); - } - - uint32_t getAnisotropy() const - { - return m_cvarCommons.getAnisotropy(); - } - - bool getDeepColor() const - { - return m_cvarCommons.getDeepColor(); - } - - void createGlobalCVars() - { - m_cvarManager.findOrMakeCVar("debugOverlay.playerInfo"sv, "Displays information about the player, such as location and orientation"sv, false, - hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); - m_cvarManager.findOrMakeCVar("debugOverlay.worldInfo"sv, "Displays information about the current world, such as world asset ID, and areaId"sv, false, - hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); - m_cvarManager.findOrMakeCVar("debugOverlay.areaInfo"sv, "Displays information about the current area, such as asset ID, object/layer counts, and active layer bits"sv, false, - hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); - m_cvarManager.findOrMakeCVar("debugOverlay.showFrameCounter"sv, "Displays the current frame index"sv, false, - hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); - } + void createGlobalCVars() { + m_cvarManager.findOrMakeCVar("debugOverlay.playerInfo"sv, + "Displays information about the player, such as location and orientation"sv, false, + hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); + m_cvarManager.findOrMakeCVar("debugOverlay.worldInfo"sv, + "Displays information about the current world, such as world asset ID, and areaId"sv, + false, + hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); + m_cvarManager.findOrMakeCVar( + "debugOverlay.areaInfo"sv, + "Displays information about the current area, such as asset ID, object/layer counts, and active layer bits"sv, + false, hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); + m_cvarManager.findOrMakeCVar("debugOverlay.showFrameCounter"sv, "Displays the current frame index"sv, false, + hecl::CVar::EFlags::Game | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ReadOnly); + } }; -} +} // namespace urde static hecl::SystemChar CwdBuf[1024]; hecl::SystemString ExeDir; -static void SetupBasics(bool logging) -{ - auto result = zeus::validateCPU(); - if (!result.first) - { +static void SetupBasics(bool logging) { + auto result = zeus::validateCPU(); + if (!result.first) { #if _WIN32 && !WINDOWS_STORE - char* msg; - asprintf(&msg, "ERROR: This build of URDE requires the following CPU features:\n%s\n", - urde::CPUFeatureString(result.second).c_str()); - MessageBoxA(nullptr, msg, "CPU error", MB_OK | MB_ICONERROR); - free(msg); + char* msg; + asprintf(&msg, "ERROR: This build of URDE requires the following CPU features:\n%s\n", + urde::CPUFeatureString(result.second).c_str()); + MessageBoxA(nullptr, msg, "CPU error", MB_OK | MB_ICONERROR); + free(msg); #else - fprintf(stderr, "ERROR: This build of URDE requires the following CPU features:\n%s\n", - urde::CPUFeatureString(result.second).c_str()); + fprintf(stderr, "ERROR: This build of URDE requires the following CPU features:\n%s\n", + urde::CPUFeatureString(result.second).c_str()); #endif - exit(1); - } + exit(1); + } - logvisor::RegisterStandardExceptions(); - if (logging) - logvisor::RegisterConsoleLogger(); - atSetExceptionHandler(AthenaExc); + logvisor::RegisterStandardExceptions(); + if (logging) + logvisor::RegisterConsoleLogger(); + atSetExceptionHandler(AthenaExc); } -static bool IsClientLoggingEnabled(int argc, const boo::SystemChar** argv) -{ - for (int i = 1; i < argc; ++i) - if (!hecl::StrNCmp(argv[i], _SYS_STR("-l"), 2)) - return true; - return false; +static bool IsClientLoggingEnabled(int argc, const boo::SystemChar** argv) { + for (int i = 1; i < argc; ++i) + if (!hecl::StrNCmp(argv[i], _SYS_STR("-l"), 2)) + return true; + return false; } #if !WINDOWS_STORE @@ -204,30 +172,28 @@ int wmain(int argc, const boo::SystemChar** argv) int main(int argc, const boo::SystemChar** argv) #endif { - if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) - { - printf("%s\n", URDE_DLPACKAGE); - return 100; - } + if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) { + printf("%s\n", URDE_DLPACKAGE); + return 100; + } - SetupBasics(IsClientLoggingEnabled(argc, argv)); + SetupBasics(IsClientLoggingEnabled(argc, argv)); - if (hecl::SystemChar* cwd = hecl::Getcwd(CwdBuf, 1024)) - { - if (hecl::PathRelative(argv[0])) - ExeDir = hecl::SystemString(cwd) + _SYS_STR('/'); - hecl::SystemString Argv0(argv[0]); - hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_SYS_STR("/\\")); - if (lastIdx != hecl::SystemString::npos) - ExeDir.insert(ExeDir.end(), Argv0.begin(), Argv0.begin() + lastIdx); - } + if (hecl::SystemChar* cwd = hecl::Getcwd(CwdBuf, 1024)) { + if (hecl::PathRelative(argv[0])) + ExeDir = hecl::SystemString(cwd) + _SYS_STR('/'); + hecl::SystemString Argv0(argv[0]); + hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_SYS_STR("/\\")); + if (lastIdx != hecl::SystemString::npos) + ExeDir.insert(ExeDir.end(), Argv0.begin(), Argv0.begin() + lastIdx); + } - urde::Application appCb; - int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, - appCb, _SYS_STR("urde"), _SYS_STR("URDE"), argc, argv, appCb.getGraphicsApi(), - appCb.getSamples(), appCb.getAnisotropy(), appCb.getDeepColor(), false); - //printf("IM DYING!!\n"); - return ret; + urde::Application appCb; + int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, appCb, _SYS_STR("urde"), _SYS_STR("URDE"), argc, + argv, appCb.getGraphicsApi(), appCb.getSamples(), appCb.getAnisotropy(), + appCb.getDeepColor(), false); + // printf("IM DYING!!\n"); + return ret; } #endif @@ -235,33 +201,30 @@ int main(int argc, const boo::SystemChar** argv) #include "boo/UWPViewProvider.hpp" using namespace Windows::ApplicationModel::Core; -[Platform::MTAThread] -int WINAPIV main(Platform::Array^ params) -{ - SetupBasics(false); - urde::Application appCb; - auto viewProvider = ref new boo::ViewProvider(appCb, _SYS_STR("urde"), _SYS_STR("URDE"), _SYS_STR("urde"), params, false); - CoreApplication::Run(viewProvider); - return 0; +[Platform::MTAThread] int WINAPIV main(Platform::Array ^ params) { + SetupBasics(false); + urde::Application appCb; + auto viewProvider = + ref new boo::ViewProvider(appCb, _SYS_STR("urde"), _SYS_STR("URDE"), _SYS_STR("urde"), params, false); + CoreApplication::Run(viewProvider); + return 0; } #elif _WIN32 -int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) -{ - int argc = 0; - const boo::SystemChar** argv; - if (lpCmdLine[0]) - argv = (const wchar_t**)(CommandLineToArgvW(lpCmdLine, &argc)); - static boo::SystemChar selfPath[1024]; - GetModuleFileNameW(nullptr, selfPath, 1024); - static const boo::SystemChar* booArgv[32] = {}; - booArgv[0] = selfPath; - for (int i=0 ; i(std::chrono::steady_clock::now() - s_tp).count(); +static std::chrono::milliseconds::rep GetTickCount() { + return std::chrono::duration_cast(std::chrono::steady_clock::now() - s_tp).count(); } #endif -static const char *VERSION_STRING = "fixNES Alpha v1.0.5"; +static const char* VERSION_STRING = "fixNES Alpha v1.0.5"; static char window_title[256]; static char window_title_pause[256]; enum { - FTYPE_UNK = 0, - FTYPE_NES, - FTYPE_NSF, - FTYPE_FDS, - FTYPE_QD, + FTYPE_UNK = 0, + FTYPE_NES, + FTYPE_NSF, + FTYPE_FDS, + FTYPE_QD, #if ZIPSUPPORT - FTYPE_ZIP, + FTYPE_ZIP, #endif }; -//static void nesEmuFdsSetup(uint8_t *src, uint8_t *dst); +// static void nesEmuFdsSetup(uint8_t *src, uint8_t *dst); static int emuFileType = FTYPE_UNK; static char emuFileName[1024]; -static uint8_t *emuNesROM = NULL; +static uint8_t* emuNesROM = NULL; static uint32_t emuNesROMsize = 0; static char emuSaveName[1024]; -static uint8_t *emuPrgRAM = NULL; +static uint8_t* emuPrgRAM = NULL; static uint32_t emuPrgRAMsize = 0; -//used externally +// used externally uint32_t textureImage[0xF000]; bool nesPause = false; bool ppuDebugPauseFrame = false; @@ -82,11 +80,11 @@ bool doOverscan = false; bool nesPAL = false; bool nesEmuNSFPlayback = false; -//static bool inPause = false; -//static bool inOverscanToggle = false; -//static bool inResize = false; -//static bool inDiskSwitch = false; -//static bool inReset = false; +// static bool inPause = false; +// static bool inOverscanToggle = false; +// static bool inResize = false; +// static bool inDiskSwitch = false; +// static bool inReset = false; #if DEBUG_HZ static int emuFrameStart = 0; @@ -106,29 +104,29 @@ static int emuMainTotalElapsed = 0; #define VISIBLE_LINES 240 static uint32_t linesToDraw = VISIBLE_LINES; -static const uint32_t visibleImg = VISIBLE_DOTS*VISIBLE_LINES*4; -//static uint8_t scaleFactor = 2; +static const uint32_t visibleImg = VISIBLE_DOTS * VISIBLE_LINES * 4; +// static uint8_t scaleFactor = 2; static bool emuSaveEnabled = false; static bool emuFdsHasSideB = false; -//static uint16_t ppuCycleTimer; +// static uint16_t ppuCycleTimer; uint32_t cpuCycleTimer; uint32_t vrc7CycleTimer; -//from input.c +// from input.c extern uint8_t inValReads[8]; -//from mapper.c +// from mapper.c extern bool mapperUse78A; -//from m32.c +// from m32.c extern bool m32_singlescreen; static volatile bool emuRenderFrame = false; extern uint8_t audioExpansion; -//used externally +// used externally bool emuSkipVsync = false; bool emuSkipFrame = false; -//static uint32_t mCycles = 0; +// static uint32_t mCycles = 0; extern bool fdsSwitch; @@ -136,17 +134,14 @@ uint32_t apuGetMaxBufSize(); void apuResetPos(); uint8_t* ppuGetVRAM(); -int audioUpdate() -{ - if (!EmulatorInst) - return 0; - return EmulatorInst->audioUpdate(); +int audioUpdate() { + if (!EmulatorInst) + return 0; + return EmulatorInst->audioUpdate(); +} } -} - -namespace urde::MP1 -{ +namespace urde::MP1 { bool CNESEmulator::EmulatorConstructed = false; static logvisor::Module Log("CNESEmulator"); @@ -161,303 +156,270 @@ static logvisor::Module Log("CNESEmulator"); #define METROID_CHR_SIZE (0 * 0x2000) #define METROID_PRG_RAM_SIZE 0x2000 -CNESEmulator::CNESEmulator() -{ - if (EmulatorConstructed) - Log.report(logvisor::Fatal, "Attempted constructing more than 1 CNESEmulator"); - EmulatorConstructed = true; +CNESEmulator::CNESEmulator() { + if (EmulatorConstructed) + Log.report(logvisor::Fatal, "Attempted constructing more than 1 CNESEmulator"); + EmulatorConstructed = true; - CDvdFile NESEmuFile("NESemuP.rel"); - if (NESEmuFile) - { - m_nesEmuPBuf.reset(new u8[0x20000]); - m_dvdReq = NESEmuFile.AsyncSeekRead(m_nesEmuPBuf.get(), 0x20000, ESeekOrigin::Begin, NESEMUP_ROM_OFFSET); - } - else - { - Log.report(logvisor::Fatal, "Unable to open NESemuP.rel"); - } + CDvdFile NESEmuFile("NESemuP.rel"); + if (NESEmuFile) { + m_nesEmuPBuf.reset(new u8[0x20000]); + m_dvdReq = NESEmuFile.AsyncSeekRead(m_nesEmuPBuf.get(), 0x20000, ESeekOrigin::Begin, NESEMUP_ROM_OFFSET); + } else { + Log.report(logvisor::Fatal, "Unable to open NESemuP.rel"); + } } -void CNESEmulator::InitializeEmulator() -{ - nesPause = false; - ppuDebugPauseFrame = false; +void CNESEmulator::InitializeEmulator() { + nesPause = false; + ppuDebugPauseFrame = false; - puts(VERSION_STRING); - strcpy(window_title, VERSION_STRING); - memset(textureImage,0,visibleImg); - emuFileType = FTYPE_UNK; - memset(emuFileName,0,1024); - memset(emuSaveName,0,1024); + puts(VERSION_STRING); + strcpy(window_title, VERSION_STRING); + memset(textureImage, 0, visibleImg); + emuFileType = FTYPE_UNK; + memset(emuFileName, 0, 1024); + memset(emuSaveName, 0, 1024); - nesPAL = METROID_PAL; - uint8_t mapper = METROID_MAPPER; - emuSaveEnabled = METROID_SAVE_ENABLED; - bool trainer = METROID_TRAINER; - uint32_t prgROMsize = METROID_PRG_SIZE; - uint32_t chrROMsize = METROID_CHR_SIZE; - emuPrgRAMsize = METROID_PRG_RAM_SIZE; - emuPrgRAM = (uint8_t*)malloc(emuPrgRAMsize); - uint8_t *prgROM = emuNesROM; - if(trainer) - { - memcpy(emuPrgRAM+0x1000,prgROM,0x200); - prgROM += 512; - } - uint8_t *chrROM = NULL; - if(chrROMsize) - { - chrROM = emuNesROM+prgROMsize; - if(trainer) chrROM += 512; - } - apuInitBufs(); - cpuInit(); - ppuInit(); - memInit(); - apuInit(); - inputInit(); - ppuSetNameTblVertical(); + nesPAL = METROID_PAL; + uint8_t mapper = METROID_MAPPER; + emuSaveEnabled = METROID_SAVE_ENABLED; + bool trainer = METROID_TRAINER; + uint32_t prgROMsize = METROID_PRG_SIZE; + uint32_t chrROMsize = METROID_CHR_SIZE; + emuPrgRAMsize = METROID_PRG_RAM_SIZE; + emuPrgRAM = (uint8_t*)malloc(emuPrgRAMsize); + uint8_t* prgROM = emuNesROM; + if (trainer) { + memcpy(emuPrgRAM + 0x1000, prgROM, 0x200); + prgROM += 512; + } + uint8_t* chrROM = NULL; + if (chrROMsize) { + chrROM = emuNesROM + prgROMsize; + if (trainer) + chrROM += 512; + } + apuInitBufs(); + cpuInit(); + ppuInit(); + memInit(); + apuInit(); + inputInit(); + ppuSetNameTblVertical(); #if DEBUG_LOAD_INFO - printf("Used Mapper: %i\n", mapper); - printf("PRG: 0x%x bytes PRG RAM: 0x%x bytes CHR: 0x%x bytes\n", prgROMsize, emuPrgRAMsize, chrROMsize); + printf("Used Mapper: %i\n", mapper); + printf("PRG: 0x%x bytes PRG RAM: 0x%x bytes CHR: 0x%x bytes\n", prgROMsize, emuPrgRAMsize, chrROMsize); #endif - if(!mapperInit(mapper, prgROM, prgROMsize, emuPrgRAM, emuPrgRAMsize, chrROM, chrROMsize)) - { - printf("Mapper init failed!\n"); - return; - } + if (!mapperInit(mapper, prgROM, prgROMsize, emuPrgRAM, emuPrgRAMsize, chrROM, chrROMsize)) { + printf("Mapper init failed!\n"); + return; + } #if DEBUG_LOAD_INFO - printf("Trainer: %i Saving: %i VRAM Mode: Vertical\n", trainer, emuSaveEnabled); + printf("Trainer: %i Saving: %i VRAM Mode: Vertical\n", trainer, emuSaveEnabled); #endif - sprintf(window_title, "%s NES - %s\n", nesPAL ? "PAL" : "NTSC", VERSION_STRING); + sprintf(window_title, "%s NES - %s\n", nesPAL ? "PAL" : "NTSC", VERSION_STRING); - sprintf(window_title_pause, "%s (Pause)", window_title); - sprintf(window_title_pause, "%s (Pause)", window_title); - #if DEBUG_HZ - emuFrameStart = GetTickCount(); - #endif - #if DEBUG_MAIN_CALLS - emuMainFrameStart = GetTickCount(); - #endif - cpuCycleTimer = nesPAL ? 16 : 12; - vrc7CycleTimer = 432 / cpuCycleTimer; - //do one scanline per idle loop - //ppuCycleTimer = nesPAL ? 5 : 4; - //mainLoopRuns = nesPAL ? DOTS*ppuCycleTimer : DOTS*ppuCycleTimer; - //mainLoopPos = mainLoopRuns; + sprintf(window_title_pause, "%s (Pause)", window_title); + sprintf(window_title_pause, "%s (Pause)", window_title); +#if DEBUG_HZ + emuFrameStart = GetTickCount(); +#endif +#if DEBUG_MAIN_CALLS + emuMainFrameStart = GetTickCount(); +#endif + cpuCycleTimer = nesPAL ? 16 : 12; + vrc7CycleTimer = 432 / cpuCycleTimer; + // do one scanline per idle loop + // ppuCycleTimer = nesPAL ? 5 : 4; + // mainLoopRuns = nesPAL ? DOTS*ppuCycleTimer : DOTS*ppuCycleTimer; + // mainLoopPos = mainLoopRuns; - CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) - { - // Nearest-neighbor FTW! - m_texture = ctx.newDynamicTexture(VISIBLE_DOTS, linesToDraw, - boo::TextureFormat::RGBA8, - boo::TextureClampMode::ClampToEdgeNearest); - Vert verts[4] = - { - {{-1.f, -1.f, 0.f}, {0.f, 1.f}}, - {{-1.f, 1.f, 0.f}, {0.f, 0.f}}, - {{ 1.f, -1.f, 0.f}, {1.f, 1.f}}, - {{ 1.f, 1.f, 0.f}, {1.f, 0.f}}, - }; - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - m_shadBind = CNESShader::BuildShaderDataBinding(ctx, m_vbo, m_uniBuf, m_texture); - return true; - } BooTrace); + CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { + // Nearest-neighbor FTW! + m_texture = ctx.newDynamicTexture(VISIBLE_DOTS, linesToDraw, boo::TextureFormat::RGBA8, + boo::TextureClampMode::ClampToEdgeNearest); + Vert verts[4] = { + {{-1.f, -1.f, 0.f}, {0.f, 1.f}}, + {{-1.f, 1.f, 0.f}, {0.f, 0.f}}, + {{1.f, -1.f, 0.f}, {1.f, 1.f}}, + {{1.f, 1.f, 0.f}, {1.f, 0.f}}, + }; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + m_shadBind = CNESShader::BuildShaderDataBinding(ctx, m_vbo, m_uniBuf, m_texture); + return true; + } BooTrace); - //double useFreq = 223740; - double useFreq = apuGetFrequency(); - m_booVoice = CAudioSys::GetVoiceEngine()->allocateNewStereoVoice(useFreq, this); - m_booVoice->start(); + // double useFreq = 223740; + double useFreq = apuGetFrequency(); + m_booVoice = CAudioSys::GetVoiceEngine()->allocateNewStereoVoice(useFreq, this); + m_booVoice->start(); + uint32_t apuBufSz = apuGetMaxBufSize(); + m_audioBufBlock.reset(new u8[apuBufSz * NUM_AUDIO_BUFFERS]); + memset(m_audioBufBlock.get(), 0, apuBufSz * NUM_AUDIO_BUFFERS); + for (int i = 0; i < NUM_AUDIO_BUFFERS; ++i) + m_audioBufs[i] = m_audioBufBlock.get() + apuBufSz * i; + + EmulatorInst = this; +} + +void CNESEmulator::DeinitializeEmulator() { + // printf("\n"); + emuRenderFrame = false; + m_booVoice->stop(); + m_booVoice.reset(); + apuDeinitBufs(); + if (emuNesROM != NULL) { + if (!nesEmuNSFPlayback && (audioExpansion & EXP_FDS)) { + FILE* save = fopen(emuSaveName, "wb"); + if (save) { + if (emuFdsHasSideB) + fwrite(emuNesROM, 1, 0x20000, save); + else + fwrite(emuNesROM, 1, 0x10000, save); + fclose(save); + } + } + } + if (emuPrgRAM != NULL) { + if (emuSaveEnabled) { + FILE* save = fopen(emuSaveName, "wb"); + if (save) { + fwrite(emuPrgRAM, 1, emuPrgRAMsize, save); + fclose(save); + } + } + free(emuPrgRAM); + } + emuPrgRAM = NULL; + // printf("Bye!\n"); + + EmulatorInst = nullptr; +} + +CNESEmulator::~CNESEmulator() { + if (m_dvdReq) + m_dvdReq->PostCancelRequest(); + if (EmulatorInst) + DeinitializeEmulator(); + if (emuNesROM) { + free(emuNesROM); + emuNesROM = nullptr; + } + EmulatorConstructed = false; +} + +int CNESEmulator::audioUpdate() { + int origProcBufs = m_procBufs; + + uint8_t* data = apuGetBuf(); + if (data != NULL && m_procBufs) { uint32_t apuBufSz = apuGetMaxBufSize(); - m_audioBufBlock.reset(new u8[apuBufSz * NUM_AUDIO_BUFFERS]); - memset(m_audioBufBlock.get(), 0, apuBufSz * NUM_AUDIO_BUFFERS); - for (int i=0 ; istop(); - m_booVoice.reset(); - apuDeinitBufs(); - if(emuNesROM != NULL) - { - if(!nesEmuNSFPlayback && (audioExpansion&EXP_FDS)) - { - FILE *save = fopen(emuSaveName, "wb"); - if(save) - { - if(emuFdsHasSideB) - fwrite(emuNesROM,1,0x20000,save); - else - fwrite(emuNesROM,1,0x10000,save); - fclose(save); - } - } + uint32_t remBytes = apuGetBufSize(); + while (remBytes != 0) { + size_t thisBytes = std::min(remBytes, apuBufSz - m_posInHeadBuf); + memmove(m_audioBufs[m_headBuf] + m_posInHeadBuf, data, thisBytes); + data += thisBytes; + m_posInHeadBuf += thisBytes; + if (m_posInHeadBuf == apuBufSz) { + m_posInHeadBuf = 0; + --m_procBufs; + ++m_headBuf; + if (m_headBuf == NUM_AUDIO_BUFFERS) + m_headBuf = 0; + // printf("PUSH\n"); + } + remBytes -= thisBytes; } - if(emuPrgRAM != NULL) - { - if(emuSaveEnabled) - { - FILE *save = fopen(emuSaveName, "wb"); - if(save) - { - fwrite(emuPrgRAM,1,emuPrgRAMsize,save); - fclose(save); - } - } - free(emuPrgRAM); - } - emuPrgRAM = NULL; - //printf("Bye!\n"); + } - EmulatorInst = nullptr; -} + // if (!origProcBufs) + // printf("OVERRUN\n"); -CNESEmulator::~CNESEmulator() -{ - if (m_dvdReq) - m_dvdReq->PostCancelRequest(); - if (EmulatorInst) - DeinitializeEmulator(); - if (emuNesROM) - { - free(emuNesROM); - emuNesROM = nullptr; - } - EmulatorConstructed = false; -} - -int CNESEmulator::audioUpdate() -{ - int origProcBufs = m_procBufs; - - uint8_t *data = apuGetBuf(); - if(data != NULL && m_procBufs) - { - uint32_t apuBufSz = apuGetMaxBufSize(); - uint32_t remBytes = apuGetBufSize(); - while (remBytes != 0) - { - size_t thisBytes = std::min(remBytes, apuBufSz - m_posInHeadBuf); - memmove(m_audioBufs[m_headBuf] + m_posInHeadBuf, data, thisBytes); - data += thisBytes; - m_posInHeadBuf += thisBytes; - if (m_posInHeadBuf == apuBufSz) - { - m_posInHeadBuf = 0; - --m_procBufs; - ++m_headBuf; - if (m_headBuf == NUM_AUDIO_BUFFERS) - m_headBuf = 0; - //printf("PUSH\n"); - } - remBytes -= thisBytes; - } - } - - //if (!origProcBufs) - //printf("OVERRUN\n"); - - return origProcBufs; + return origProcBufs; } static constexpr uint32_t AudioFrameSz = 2 * sizeof(int16_t); -size_t CNESEmulator::supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data) -{ - uint32_t remFrames = uint32_t(frames); - while (remFrames) - { - if (m_posInTailBuf == apuGetMaxBufSize()) - { - ++m_tailBuf; - if (m_tailBuf == NUM_AUDIO_BUFFERS) - m_tailBuf = 0; - m_posInTailBuf = 0; - ++m_procBufs; - //printf("POP\n"); - } - - if (m_procBufs == NUM_AUDIO_BUFFERS) - { - memset(data, 0, remFrames * AudioFrameSz); - //printf("UNDERRUN\n"); - return frames; - } - - size_t copySz = std::min(apuGetMaxBufSize() - m_posInTailBuf, remFrames * AudioFrameSz); - memmove(data, m_audioBufs[m_tailBuf] + m_posInTailBuf, copySz); - data += copySz / sizeof(int16_t); - m_posInTailBuf += copySz; - remFrames -= copySz / AudioFrameSz; +size_t CNESEmulator::supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data) { + uint32_t remFrames = uint32_t(frames); + while (remFrames) { + if (m_posInTailBuf == apuGetMaxBufSize()) { + ++m_tailBuf; + if (m_tailBuf == NUM_AUDIO_BUFFERS) + m_tailBuf = 0; + m_posInTailBuf = 0; + ++m_procBufs; + // printf("POP\n"); } - return frames; + + if (m_procBufs == NUM_AUDIO_BUFFERS) { + memset(data, 0, remFrames * AudioFrameSz); + // printf("UNDERRUN\n"); + return frames; + } + + size_t copySz = std::min(apuGetMaxBufSize() - m_posInTailBuf, remFrames * AudioFrameSz); + memmove(data, m_audioBufs[m_tailBuf] + m_posInTailBuf, copySz); + data += copySz / sizeof(int16_t); + m_posInTailBuf += copySz; + remFrames -= copySz / AudioFrameSz; + } + return frames; } -void CNESEmulator::NesEmuMainLoop(bool forceDraw) -{ - //int start = GetTickCount(); - int loopCount = 0; - do - { - if(emuRenderFrame || nesPause) - { +void CNESEmulator::NesEmuMainLoop(bool forceDraw) { + // int start = GetTickCount(); + int loopCount = 0; + do { + if (emuRenderFrame || nesPause) { #if DEBUG_MAIN_CALLS - emuMainTimesSkipped++; + emuMainTimesSkipped++; #endif - //printf("LC RENDER: %d\n", loopCount); - m_texture->load(textureImage, visibleImg); - emuRenderFrame = false; - break; - } - ++loopCount; + // printf("LC RENDER: %d\n", loopCount); + m_texture->load(textureImage, visibleImg); + emuRenderFrame = false; + break; + } + ++loopCount; - //main CPU clock - if(!cpuCycle()) - exit(EXIT_SUCCESS); - //run graphics - ppuCycle(); - //run audio - apuCycle(); - //mapper related irqs - mapperCycle(); - //mCycles++; - if(ppuDrawDone()) - { - //printf("%i\n",mCycles); - //mCycles = 0; + // main CPU clock + if (!cpuCycle()) + exit(EXIT_SUCCESS); + // run graphics + ppuCycle(); + // run audio + apuCycle(); + // mapper related irqs + mapperCycle(); + // mCycles++; + if (ppuDrawDone()) { + // printf("%i\n",mCycles); + // mCycles = 0; #ifndef __LIBRETRO__ - emuRenderFrame = true; + emuRenderFrame = true; #if 0 if(fm2playRunning()) fm2playUpdate(); #endif #if DEBUG_HZ - emuTimesCalled++; - auto end = GetTickCount(); - emuTotalElapsed += end - emuFrameStart; - if(emuTotalElapsed >= 1000) - { - printf("\r%iHz ", emuTimesCalled); - emuTimesCalled = 0; - emuTotalElapsed = 0; - } - emuFrameStart = end; + emuTimesCalled++; + auto end = GetTickCount(); + emuTotalElapsed += end - emuFrameStart; + if (emuTotalElapsed >= 1000) { + printf("\r%iHz ", emuTimesCalled); + emuTimesCalled = 0; + emuTotalElapsed = 0; + } + emuFrameStart = end; #endif - //update audio before drawing - if(!apuUpdate()) - { - apuResetPos(); - break; - } - //glutPostRedisplay(); + // update audio before drawing + if (!apuUpdate()) { + apuResetPos(); + break; + } + // glutPostRedisplay(); #if 0 if(ppuDebugPauseFrame) { @@ -466,17 +428,16 @@ void CNESEmulator::NesEmuMainLoop(bool forceDraw) } #endif #endif - if(nesEmuNSFPlayback) - nsfVsync(); + if (nesEmuNSFPlayback) + nsfVsync(); - //keep processing frames if audio buffers are underrunning - if (emuSkipFrame) - emuRenderFrame = false; + // keep processing frames if audio buffers are underrunning + if (emuSkipFrame) + emuRenderFrame = false; - continue; - } + continue; } - while(true); + } while (true); #if 0 int end = GetTickCount(); @@ -484,19 +445,18 @@ void CNESEmulator::NesEmuMainLoop(bool forceDraw) #endif #if DEBUG_MAIN_CALLS - emuMainTimesCalled++; - int end = GetTickCount(); - //printf("%dms\n", end - start); - emuMainTotalElapsed += end - emuMainFrameStart; - if(emuMainTotalElapsed >= 1000) - { - printf("\r%i calls, %i skips ", emuMainTimesCalled, emuMainTimesSkipped); - fflush(stdout); - emuMainTimesCalled = 0; - emuMainTimesSkipped = 0; - emuMainTotalElapsed = 0; - } - emuMainFrameStart = end; + emuMainTimesCalled++; + int end = GetTickCount(); + // printf("%dms\n", end - start); + emuMainTotalElapsed += end - emuMainFrameStart; + if (emuMainTotalElapsed >= 1000) { + printf("\r%i calls, %i skips ", emuMainTimesCalled, emuMainTimesSkipped); + fflush(stdout); + emuMainTimesCalled = 0; + emuMainTimesSkipped = 0; + emuMainTotalElapsed = 0; + } + emuMainFrameStart = end; #endif } @@ -523,306 +483,267 @@ static void nesEmuFdsSetup(uint8_t *src, uint8_t *dst) } #endif -struct BitstreamState -{ - u8* rPos; - int position = 0; - int tmpBuf = 0; - int decBit = 0; - BitstreamState(u8* pos) : rPos(pos) {} - void resetDecBit() { decBit = 0; } - void runDecBit() - { - if(position == 0) - { - position = 8; - tmpBuf = *rPos++; - } - decBit <<= 1; - if(tmpBuf & 0x80) - decBit |= 1; - tmpBuf <<= 1; - position--; +struct BitstreamState { + u8* rPos; + int position = 0; + int tmpBuf = 0; + int decBit = 0; + BitstreamState(u8* pos) : rPos(pos) {} + void resetDecBit() { decBit = 0; } + void runDecBit() { + if (position == 0) { + position = 8; + tmpBuf = *rPos++; } + decBit <<= 1; + if (tmpBuf & 0x80) + decBit |= 1; + tmpBuf <<= 1; + position--; + } }; // Based on https://gist.github.com/FIX94/7593640c5cee6c37e3b23e7fcf8fe5b7 -void CNESEmulator::DecryptMetroid(u8* dataIn, u8* dataOut, u32 decLen, u8 decByte, - u32 xorLen, u32 xorVal) -{ - int i, j; - // simple add obfuscation - for(i = 0; i < 0x100; i++) - { - dataIn[i] += decByte; - decByte = dataIn[i]; - } - // flip the first 0x100 bytes around - for (i = 0; i < 128; ++i) - std::swap(dataIn[255 - i], dataIn[i]); - // set up buffer pointers - BitstreamState bState(dataIn + 0x100); - // unscramble buffer - for(i = 0; i < decLen; i++) - { +void CNESEmulator::DecryptMetroid(u8* dataIn, u8* dataOut, u32 decLen, u8 decByte, u32 xorLen, u32 xorVal) { + int i, j; + // simple add obfuscation + for (i = 0; i < 0x100; i++) { + dataIn[i] += decByte; + decByte = dataIn[i]; + } + // flip the first 0x100 bytes around + for (i = 0; i < 128; ++i) + std::swap(dataIn[255 - i], dataIn[i]); + // set up buffer pointers + BitstreamState bState(dataIn + 0x100); + // unscramble buffer + for (i = 0; i < decLen; i++) { + bState.resetDecBit(); + bState.runDecBit(); + if (bState.decBit) { + bState.resetDecBit(); + for (j = 0; j < 8; j++) + bState.runDecBit(); + dataOut[i] = dataIn[bState.decBit + 0x49]; + } else { + bState.resetDecBit(); + bState.runDecBit(); + if (bState.decBit) { + bState.resetDecBit(); + for (j = 0; j < 6; j++) + bState.runDecBit(); + dataOut[i] = dataIn[bState.decBit + 9]; + } else { bState.resetDecBit(); bState.runDecBit(); - if(bState.decBit) - { - bState.resetDecBit(); - for(j = 0; j < 8; j++) - bState.runDecBit(); - dataOut[i] = dataIn[bState.decBit + 0x49]; - } - else - { - bState.resetDecBit(); + if (bState.decBit) { + bState.resetDecBit(); + for (j = 0; j < 3; j++) bState.runDecBit(); - if(bState.decBit) - { - bState.resetDecBit(); - for(j = 0; j < 6; j++) - bState.runDecBit(); - dataOut[i] = dataIn[bState.decBit + 9]; - } - else - { - bState.resetDecBit(); - bState.runDecBit(); - if(bState.decBit) - { - bState.resetDecBit(); - for(j = 0; j < 3; j++) - bState.runDecBit(); - dataOut[i] = dataIn[bState.decBit + 1]; - } - else - dataOut[i] = dataIn[bState.decBit]; - } - } + dataOut[i] = dataIn[bState.decBit + 1]; + } else + dataOut[i] = dataIn[bState.decBit]; + } } - // do checksum fixups - unsigned int xorTmpVal = 0; - for(i = 0; i < xorLen; i++) - { - xorTmpVal ^= dataOut[i]; - for(j = 0; j < 8; j++) - { - if(xorTmpVal & 1) - { - xorTmpVal >>= 1; - xorTmpVal ^= xorVal; - } - else - xorTmpVal >>= 1; - } + } + // do checksum fixups + unsigned int xorTmpVal = 0; + for (i = 0; i < xorLen; i++) { + xorTmpVal ^= dataOut[i]; + for (j = 0; j < 8; j++) { + if (xorTmpVal & 1) { + xorTmpVal >>= 1; + xorTmpVal ^= xorVal; + } else + xorTmpVal >>= 1; } - // write in calculated checksum - dataOut[xorLen - 1] = u8((xorTmpVal >> 8) & 0xFF); - dataOut[xorLen - 2] = u8(xorTmpVal & 0xFF); + } + // write in calculated checksum + dataOut[xorLen - 1] = u8((xorTmpVal >> 8) & 0xFF); + dataOut[xorLen - 2] = u8(xorTmpVal & 0xFF); } -void CNESEmulator::ProcessUserInput(const CFinalInput& input, int) -{ - if (input.ControllerIdx() != 0) - return; +void CNESEmulator::ProcessUserInput(const CFinalInput& input, int) { + if (input.ControllerIdx() != 0) + return; - if (GetPasswordEntryState() != EPasswordEntryState::NotPasswordScreen) - { - // Don't swap A/B - inValReads[BUTTON_A] = input.DA(); - inValReads[BUTTON_B] = input.DB(); + if (GetPasswordEntryState() != EPasswordEntryState::NotPasswordScreen) { + // Don't swap A/B + inValReads[BUTTON_A] = input.DA(); + inValReads[BUTTON_B] = input.DB(); + } else { + // Prime controls (B jumps, A shoots) + inValReads[BUTTON_B] = input.DA() | input.DY(); + inValReads[BUTTON_A] = input.DB() | input.DX(); + } + + inValReads[BUTTON_UP] = input.DDPUp() | input.DLAUp(); + inValReads[BUTTON_DOWN] = input.DDPDown() | input.DLADown(); + inValReads[BUTTON_LEFT] = input.DDPLeft() | input.DLALeft(); + inValReads[BUTTON_RIGHT] = input.DDPRight() | input.DLARight(); + inValReads[BUTTON_SELECT] = input.DZ(); + inValReads[BUTTON_START] = input.DStart(); +} + +bool CNESEmulator::CheckForGameOver(const u8* vram, u8* passwordOut) { + // "PASS WORD" + if (memcmp(vram + 0x14B, "\x19\xa\x1c\x1c\xff\x20\x18\x1b\xd", 9)) + return false; + + int chOff = 0; + int encOff = 0; + u8 pwOut[18]; + for (int i = 0; i < 24; ++i) { + u8 chName = vram[0x1A9 + chOff]; + ++chOff; + if (chOff == 0x6 || chOff == 0x46) + ++chOff; // mid-line space + else if (chOff == 0xd) + chOff = 64; // 2nd line + + if (chName > 0x3f) + return false; + + switch (i & 0x3) { + case 0: + pwOut[encOff] = chName; + break; + case 1: + pwOut[encOff] |= chName << 6; + ++encOff; + pwOut[encOff] = chName >> 2; + break; + case 2: + pwOut[encOff] |= chName << 4; + ++encOff; + pwOut[encOff] = chName >> 4; + break; + case 3: + pwOut[encOff] |= chName << 2; + ++encOff; + break; + default: + break; } + } + + if (passwordOut) + memmove(passwordOut, pwOut, 18); + return true; +} + +CNESEmulator::EPasswordEntryState CNESEmulator::CheckForPasswordEntryScreen(const u8* vram) { + // "PASS WORD PLEASE" + if (memcmp(vram + 0x88, "\x19\xa\x1c\x1c\xff\x20\x18\x1b\xd\xff\x19\x15\xe\xa\x1c\xe", 16)) + return EPasswordEntryState::NotPasswordScreen; + + for (int i = 0; i < 13; ++i) + if (vram[0x109 + i] < 0x40 || vram[0x149 + i] < 0x40) + return EPasswordEntryState::Entered; + + return EPasswordEntryState::NotEntered; +} + +bool CNESEmulator::SetPasswordIntoEntryScreen(u8* vram, u8* wram, const u8* password) { + if (CheckForPasswordEntryScreen(vram) != EPasswordEntryState::NotEntered) + return false; + + int i; + for (i = 0; i < 18; ++i) + if (password[i]) + break; + if (i == 18) + return false; + + int encOff = 0; + int chOff = 0; + u32 lastWord = 0; + for (i = 0; i < 24; ++i) { + switch (i & 0x3) { + case 0: + lastWord = password[encOff]; + ++encOff; + break; + case 1: + lastWord = (lastWord >> 6) | (u32(password[encOff]) << 2); + ++encOff; + break; + case 2: + lastWord = (lastWord >> 6) | (u32(password[encOff]) << 4); + ++encOff; + break; + case 3: + lastWord = (lastWord >> 6); + break; + default: + break; + } + + u8 chName = u8(lastWord & 0x3f); + wram[0x99a + i] = chName; + vram[0x109 + chOff] = chName; + ++chOff; + if (chOff == 0x6 || chOff == 0x46) + ++chOff; // mid-line space + else if (chOff == 0xd) + chOff = 64; // 2nd line + } + + return true; +} + +void CNESEmulator::Update() { + if (!EmulatorInst) { + if (m_dvdReq && m_dvdReq->IsComplete()) { + m_dvdReq.reset(); + emuNesROMsize = 0x20000; + emuNesROM = (uint8_t*)malloc(emuNesROMsize); + DecryptMetroid(m_nesEmuPBuf.get(), emuNesROM); + m_nesEmuPBuf.reset(); + InitializeEmulator(); + } + } else { + if (nesPause) { + DeinitializeEmulator(); + InitializeEmulator(); + return; + } + + bool gameOver = CheckForGameOver(ppuGetVRAM(), x21_passwordFromNES); + x34_passwordEntryState = CheckForPasswordEntryScreen(ppuGetVRAM()); + if (x34_passwordEntryState == EPasswordEntryState::NotEntered && x38_passwordPending) { + SetPasswordIntoEntryScreen(ppuGetVRAM(), emuPrgRAM, x39_passwordToNES); + x38_passwordPending = false; + } + if (gameOver && !x20_gameOver) + for (int i = 0; i < 3; ++i) // Three draw loops to ensure password display + NesEmuMainLoop(true); else - { - // Prime controls (B jumps, A shoots) - inValReads[BUTTON_B] = input.DA() | input.DY(); - inValReads[BUTTON_A] = input.DB() | input.DX(); - } - - inValReads[BUTTON_UP] = input.DDPUp() | input.DLAUp(); - inValReads[BUTTON_DOWN] = input.DDPDown() | input.DLADown(); - inValReads[BUTTON_LEFT] = input.DDPLeft() | input.DLALeft(); - inValReads[BUTTON_RIGHT] = input.DDPRight() | input.DLARight(); - inValReads[BUTTON_SELECT] = input.DZ(); - inValReads[BUTTON_START] = input.DStart(); -} - -bool CNESEmulator::CheckForGameOver(const u8* vram, u8* passwordOut) -{ - // "PASS WORD" - if (memcmp(vram + 0x14B, "\x19\xa\x1c\x1c\xff\x20\x18\x1b\xd", 9)) - return false; - - int chOff = 0; - int encOff = 0; - u8 pwOut[18]; - for (int i=0 ; i<24 ; ++i) - { - u8 chName = vram[0x1A9 + chOff]; - ++chOff; - if (chOff == 0x6 || chOff == 0x46) - ++chOff; // mid-line space - else if (chOff == 0xd) - chOff = 64; // 2nd line - - if (chName > 0x3f) - return false; - - switch (i & 0x3) - { - case 0: - pwOut[encOff] = chName; - break; - case 1: - pwOut[encOff] |= chName << 6; - ++encOff; - pwOut[encOff] = chName >> 2; - break; - case 2: - pwOut[encOff] |= chName << 4; - ++encOff; - pwOut[encOff] = chName >> 4; - break; - case 3: - pwOut[encOff] |= chName << 2; - ++encOff; - break; - default: - break; - } - } - - if (passwordOut) - memmove(passwordOut, pwOut, 18); - return true; -} - -CNESEmulator::EPasswordEntryState CNESEmulator::CheckForPasswordEntryScreen(const u8* vram) -{ - // "PASS WORD PLEASE" - if (memcmp(vram + 0x88, "\x19\xa\x1c\x1c\xff\x20\x18\x1b\xd\xff\x19\x15\xe\xa\x1c\xe", 16)) - return EPasswordEntryState::NotPasswordScreen; - - for (int i=0 ; i<13 ; ++i) - if (vram[0x109 + i] < 0x40 || vram[0x149 + i] < 0x40) - return EPasswordEntryState::Entered; - - return EPasswordEntryState::NotEntered; -} - -bool CNESEmulator::SetPasswordIntoEntryScreen(u8* vram, u8* wram, const u8* password) -{ - if (CheckForPasswordEntryScreen(vram) != EPasswordEntryState::NotEntered) - return false; - - int i; - for (i=0 ; i<18 ; ++i) - if (password[i]) - break; - if (i == 18) - return false; - - int encOff = 0; - int chOff = 0; - u32 lastWord = 0; - for (i=0 ; i<24 ; ++i) - { - switch (i & 0x3) - { - case 0: - lastWord = password[encOff]; - ++encOff; - break; - case 1: - lastWord = (lastWord >> 6) | (u32(password[encOff]) << 2); - ++encOff; - break; - case 2: - lastWord = (lastWord >> 6) | (u32(password[encOff]) << 4); - ++encOff; - break; - case 3: - lastWord = (lastWord >> 6); - break; - default: - break; - } - - u8 chName = u8(lastWord & 0x3f); - wram[0x99a + i] = chName; - vram[0x109 + chOff] = chName; - ++chOff; - if (chOff == 0x6 || chOff == 0x46) - ++chOff; // mid-line space - else if (chOff == 0xd) - chOff = 64; // 2nd line - } - - return true; -} - -void CNESEmulator::Update() -{ - if (!EmulatorInst) - { - if (m_dvdReq && m_dvdReq->IsComplete()) - { - m_dvdReq.reset(); - emuNesROMsize = 0x20000; - emuNesROM = (uint8_t*)malloc(emuNesROMsize); - DecryptMetroid(m_nesEmuPBuf.get(), emuNesROM); - m_nesEmuPBuf.reset(); - InitializeEmulator(); - } - } - else - { - if (nesPause) - { - DeinitializeEmulator(); - InitializeEmulator(); - return; - } - - bool gameOver = CheckForGameOver(ppuGetVRAM(), x21_passwordFromNES); - x34_passwordEntryState = CheckForPasswordEntryScreen(ppuGetVRAM()); - if (x34_passwordEntryState == EPasswordEntryState::NotEntered && x38_passwordPending) - { - SetPasswordIntoEntryScreen(ppuGetVRAM(), emuPrgRAM, x39_passwordToNES); - x38_passwordPending = false; - } - if (gameOver && !x20_gameOver) - for (int i=0 ; i<3 ; ++i) // Three draw loops to ensure password display - NesEmuMainLoop(true); - else - NesEmuMainLoop(); - x20_gameOver = gameOver; - } + NesEmuMainLoop(); + x20_gameOver = gameOver; + } } static const float NESAspect = VISIBLE_DOTS / float(VISIBLE_LINES); -void CNESEmulator::Draw(const zeus::CColor& mulColor, bool filtering) -{ - if (!EmulatorInst) - return; +void CNESEmulator::Draw(const zeus::CColor& mulColor, bool filtering) { + if (!EmulatorInst) + return; - float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); - float widthFac = NESAspect / aspect; + float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); + float widthFac = NESAspect / aspect; - Uniform uniform = {zeus::CMatrix4f{}, mulColor}; - uniform.m_matrix[0][0] = widthFac; - m_uniBuf->load(&uniform, sizeof(Uniform)); + Uniform uniform = {zeus::CMatrix4f{}, mulColor}; + uniform.m_matrix[0][0] = widthFac; + m_uniBuf->load(&uniform, sizeof(Uniform)); - CGraphics::SetShaderDataBinding(m_shadBind); - CGraphics::DrawArray(0, 4); + CGraphics::SetShaderDataBinding(m_shadBind); + CGraphics::DrawArray(0, 4); } -void CNESEmulator::LoadPassword(const u8* state) -{ - memmove(x39_passwordToNES, state, 18); - x38_passwordPending = true; +void CNESEmulator::LoadPassword(const u8* state) { + memmove(x39_passwordToNES, state, 18); + x38_passwordPending = true; } -} +} // namespace urde::MP1 diff --git a/NESEmulator/CNESEmulator.hpp b/NESEmulator/CNESEmulator.hpp index 62fad206e..f1529be57 100644 --- a/NESEmulator/CNESEmulator.hpp +++ b/NESEmulator/CNESEmulator.hpp @@ -6,93 +6,84 @@ #include "boo/audiodev/IAudioVoice.hpp" #include "zeus/CMatrix4f.hpp" -namespace urde -{ +namespace urde { struct CFinalInput; class IDvdRequest; -namespace MP1 -{ +namespace MP1 { #define NUM_AUDIO_BUFFERS 4 -class CNESEmulator final : public boo::IAudioVoiceCallback -{ +class CNESEmulator final : public boo::IAudioVoiceCallback { public: - enum class EPasswordEntryState - { - NotPasswordScreen, - NotEntered, - Entered - }; + enum class EPasswordEntryState { NotPasswordScreen, NotEntered, Entered }; + private: - static bool EmulatorConstructed; + static bool EmulatorConstructed; - std::unique_ptr m_nesEmuPBuf; - std::shared_ptr m_dvdReq; + std::unique_ptr m_nesEmuPBuf; + std::shared_ptr m_dvdReq; - struct Vert - { - zeus::CVector3f m_pos; - zeus::CVector2f m_uv; - }; + struct Vert { + zeus::CVector3f m_pos; + zeus::CVector2f m_uv; + }; - struct Uniform - { - zeus::CMatrix4f m_matrix; - zeus::CColor m_color; - }; + struct Uniform { + zeus::CMatrix4f m_matrix; + zeus::CColor m_color; + }; - boo::ObjToken m_texture; - boo::ObjToken m_uniBuf; - boo::ObjToken m_vbo; - boo::ObjToken m_shadBind; + boo::ObjToken m_texture; + boo::ObjToken m_uniBuf; + boo::ObjToken m_vbo; + boo::ObjToken m_shadBind; - std::unique_ptr m_audioBufBlock; - u8* m_audioBufs[NUM_AUDIO_BUFFERS]; - uint32_t m_headBuf = 0; - uint32_t m_tailBuf = 0; - uint32_t m_procBufs = NUM_AUDIO_BUFFERS; - uint32_t m_posInHeadBuf = 0; - uint32_t m_posInTailBuf = 0; - boo::ObjToken m_booVoice; + std::unique_ptr m_audioBufBlock; + u8* m_audioBufs[NUM_AUDIO_BUFFERS]; + uint32_t m_headBuf = 0; + uint32_t m_tailBuf = 0; + uint32_t m_procBufs = NUM_AUDIO_BUFFERS; + uint32_t m_posInHeadBuf = 0; + uint32_t m_posInTailBuf = 0; + boo::ObjToken m_booVoice; + + // void* x4_loadBuf; + // void* x8_rom; + // void* xc_state; + // OSModuleInfo* x10_module = x4_loadBuf; + // void* x14_bss; + // void* x18_prgram; + // void* x1c_wram; + bool x20_gameOver = false; + u8 x21_passwordFromNES[18]; + EPasswordEntryState x34_passwordEntryState = EPasswordEntryState::NotPasswordScreen; + bool x38_passwordPending = false; + u8 x39_passwordToNES[18]; + static void DecryptMetroid(u8* dataIn, u8* dataOut, u32 decLen = 0x20000, u8 decByte = 0xe9, u32 xorLen = 0x1FFFC, + u32 xorVal = 0xA663); + void InitializeEmulator(); + void DeinitializeEmulator(); + void NesEmuMainLoop(bool forceDraw = false); + static bool CheckForGameOver(const u8* vram, u8* passwordOut = nullptr); + static EPasswordEntryState CheckForPasswordEntryScreen(const uint8_t* vram); + static bool SetPasswordIntoEntryScreen(u8* vram, u8* wram, const u8* password); - //void* x4_loadBuf; - //void* x8_rom; - //void* xc_state; - //OSModuleInfo* x10_module = x4_loadBuf; - //void* x14_bss; - //void* x18_prgram; - //void* x1c_wram; - bool x20_gameOver = false; - u8 x21_passwordFromNES[18]; - EPasswordEntryState x34_passwordEntryState = EPasswordEntryState::NotPasswordScreen; - bool x38_passwordPending = false; - u8 x39_passwordToNES[18]; - static void DecryptMetroid(u8* dataIn, u8* dataOut, u32 decLen = 0x20000, u8 decByte = 0xe9, - u32 xorLen = 0x1FFFC, u32 xorVal = 0xA663); - void InitializeEmulator(); - void DeinitializeEmulator(); - void NesEmuMainLoop(bool forceDraw = false); - static bool CheckForGameOver(const u8* vram, u8* passwordOut = nullptr); - static EPasswordEntryState CheckForPasswordEntryScreen(const uint8_t* vram); - static bool SetPasswordIntoEntryScreen(u8* vram, u8* wram, const u8* password); public: - CNESEmulator(); - ~CNESEmulator(); - void ProcessUserInput(const CFinalInput& input, int); - void Update(); - void Draw(const zeus::CColor& mulColor, bool filtering); - void LoadPassword(const u8* state); - const u8* GetPassword() const { return x21_passwordFromNES; } - bool IsGameOver() const { return x20_gameOver; } - EPasswordEntryState GetPasswordEntryState() const { return x34_passwordEntryState; } + CNESEmulator(); + ~CNESEmulator(); + void ProcessUserInput(const CFinalInput& input, int); + void Update(); + void Draw(const zeus::CColor& mulColor, bool filtering); + void LoadPassword(const u8* state); + const u8* GetPassword() const { return x21_passwordFromNES; } + bool IsGameOver() const { return x20_gameOver; } + EPasswordEntryState GetPasswordEntryState() const { return x34_passwordEntryState; } - int audioUpdate(); - void preSupplyAudio(boo::IAudioVoice& voice, double dt) {} - size_t supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data); + int audioUpdate(); + void preSupplyAudio(boo::IAudioVoice& voice, double dt) {} + size_t supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/NESEmulator/CNESShader.cpp b/NESEmulator/CNESShader.cpp index 5b13168c2..63c18e70f 100644 --- a/NESEmulator/CNESShader.cpp +++ b/NESEmulator/CNESShader.cpp @@ -2,31 +2,23 @@ #include "Graphics/CGraphics.hpp" #include "hecl/Pipeline.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { boo::ObjToken CNESShader::g_Pipeline; -void CNESShader::Initialize() -{ - g_Pipeline = hecl::conv->convert(Shader_CNESShader{}); -} +void CNESShader::Initialize() { g_Pipeline = hecl::conv->convert(Shader_CNESShader{}); } boo::ObjToken CNESShader::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, boo::ObjToken vbo, boo::ObjToken uniBuf, - boo::ObjToken tex) -{ - boo::ObjToken bufs[] = {uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {tex.get()}; - return ctx.newShaderDataBinding(g_Pipeline, vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 1, texs, nullptr, nullptr); + boo::ObjToken tex) { + boo::ObjToken bufs[] = {uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {tex.get()}; + return ctx.newShaderDataBinding(g_Pipeline, vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, nullptr, 1, texs, + nullptr, nullptr); } -void CNESShader::Shutdown() -{ - g_Pipeline.reset(); -} +void CNESShader::Shutdown() { g_Pipeline.reset(); } -} +} // namespace urde::MP1 diff --git a/NESEmulator/CNESShader.hpp b/NESEmulator/CNESShader.hpp index 56a5074cb..dc315ff17 100644 --- a/NESEmulator/CNESShader.hpp +++ b/NESEmulator/CNESShader.hpp @@ -2,22 +2,19 @@ #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class CNESShader -{ +class CNESShader { public: - static void Initialize(); - static void Shutdown(); + static void Initialize(); + static void Shutdown(); - static boo::ObjToken BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, - boo::ObjToken vbo, - boo::ObjToken uniBuf, - boo::ObjToken tex); + static boo::ObjToken BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, + boo::ObjToken vbo, + boo::ObjToken uniBuf, + boo::ObjToken tex); - static boo::ObjToken g_Pipeline; + static boo::ObjToken g_Pipeline; }; -} - +} // namespace urde::MP1 diff --git a/Runtime/Audio/CAudioGroupSet.cpp b/Runtime/Audio/CAudioGroupSet.cpp index edbf8476d..f6d6a7756 100644 --- a/Runtime/Audio/CAudioGroupSet.cpp +++ b/Runtime/Audio/CAudioGroupSet.cpp @@ -1,40 +1,33 @@ #include "CAudioGroupSet.hpp" -namespace urde -{ +namespace urde { -amuse::AudioGroupData CAudioGroupSet::LoadData() -{ - athena::io::MemoryReader r(m_buffer.get(), INT32_MAX); - x10_baseName = r.readString(); - x20_name = r.readString(); +amuse::AudioGroupData CAudioGroupSet::LoadData() { + athena::io::MemoryReader r(m_buffer.get(), INT32_MAX); + x10_baseName = r.readString(); + x20_name = r.readString(); - u8* buf = m_buffer.get() + r.position(); - uint32_t poolLen = hecl::SBig(*reinterpret_cast(buf)); - unsigned char* pool = buf + 4; - buf += poolLen + 4; - uint32_t projLen = hecl::SBig(*reinterpret_cast(buf)); - unsigned char* proj = buf + 4; - buf += projLen + 4; - uint32_t sampLen = hecl::SBig(*reinterpret_cast(buf)); - unsigned char* samp = buf + 4; - buf += sampLen + 4; - uint32_t sdirLen = hecl::SBig(*reinterpret_cast(buf)); - unsigned char* sdir = buf + 4; + u8* buf = m_buffer.get() + r.position(); + uint32_t poolLen = hecl::SBig(*reinterpret_cast(buf)); + unsigned char* pool = buf + 4; + buf += poolLen + 4; + uint32_t projLen = hecl::SBig(*reinterpret_cast(buf)); + unsigned char* proj = buf + 4; + buf += projLen + 4; + uint32_t sampLen = hecl::SBig(*reinterpret_cast(buf)); + unsigned char* samp = buf + 4; + buf += sampLen + 4; + uint32_t sdirLen = hecl::SBig(*reinterpret_cast(buf)); + unsigned char* sdir = buf + 4; - return {proj, projLen, pool, poolLen, sdir, sdirLen, samp, sampLen, amuse::GCNDataTag{}}; + return {proj, projLen, pool, poolLen, sdir, sdirLen, samp, sampLen, amuse::GCNDataTag{}}; } -CAudioGroupSet::CAudioGroupSet(std::unique_ptr&& in) -: m_buffer(std::move(in)), m_data(LoadData()) -{} +CAudioGroupSet::CAudioGroupSet(std::unique_ptr&& in) : m_buffer(std::move(in)), m_data(LoadData()) {} -CFactoryFnReturn FAudioGroupSetDataFactory(const urde::SObjectTag& tag, - std::unique_ptr&& in, u32 len, - const urde::CVParamTransfer& vparms, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(std::move(in))); +CFactoryFnReturn FAudioGroupSetDataFactory(const urde::SObjectTag& tag, std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms, CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(std::move(in))); } -} +} // namespace urde diff --git a/Runtime/Audio/CAudioGroupSet.hpp b/Runtime/Audio/CAudioGroupSet.hpp index 9482162d1..7f6e12b74 100644 --- a/Runtime/Audio/CAudioGroupSet.hpp +++ b/Runtime/Audio/CAudioGroupSet.hpp @@ -7,26 +7,22 @@ #include "IOStreams.hpp" #include "amuse/AudioGroupData.hpp" -namespace urde -{ +namespace urde { + +class CAudioGroupSet { + std::unique_ptr m_buffer; + std::string x10_baseName; + std::string x20_name; + amuse::AudioGroupData m_data; + amuse::AudioGroupData LoadData(); -class CAudioGroupSet -{ - std::unique_ptr m_buffer; - std::string x10_baseName; - std::string x20_name; - amuse::AudioGroupData m_data; - amuse::AudioGroupData LoadData(); public: - CAudioGroupSet(std::unique_ptr&& in); - const amuse::AudioGroupData& GetAudioGroupData() const {return m_data;} - std::string_view GetName() const { return x20_name; } + CAudioGroupSet(std::unique_ptr&& in); + const amuse::AudioGroupData& GetAudioGroupData() const { return m_data; } + std::string_view GetName() const { return x20_name; } }; -CFactoryFnReturn FAudioGroupSetDataFactory(const urde::SObjectTag& tag, - std::unique_ptr&& in, u32 len, - const urde::CVParamTransfer& vparms, - CObjectReference* selfRef); - -} +CFactoryFnReturn FAudioGroupSetDataFactory(const urde::SObjectTag& tag, std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms, CObjectReference* selfRef); +} // namespace urde diff --git a/Runtime/Audio/CAudioSys.cpp b/Runtime/Audio/CAudioSys.cpp index 614888470..a347209f9 100644 --- a/Runtime/Audio/CAudioSys.cpp +++ b/Runtime/Audio/CAudioSys.cpp @@ -2,121 +2,90 @@ #include "CSimplePool.hpp" #include "CAudioGroupSet.hpp" -namespace urde -{ +namespace urde { CAudioSys* CAudioSys::g_SharedSys = nullptr; static std::unordered_map> mpGroupSetDB; static std::unordered_map mpGroupSetResNameDB; static const std::string mpDefaultInvalidString = "NULL"; -TLockedToken CAudioSys::FindGroupSet(std::string_view name) -{ - auto search = mpGroupSetDB.find(name.data()); - if (search == mpGroupSetDB.cend()) - return {}; - return search->second; +TLockedToken CAudioSys::FindGroupSet(std::string_view name) { + auto search = mpGroupSetDB.find(name.data()); + if (search == mpGroupSetDB.cend()) + return {}; + return search->second; } -std::string_view CAudioSys::SysGetGroupSetName(CAssetId id) -{ - auto search = mpGroupSetResNameDB.find(id); - if (search == mpGroupSetResNameDB.cend()) - return mpDefaultInvalidString; - return search->second; +std::string_view CAudioSys::SysGetGroupSetName(CAssetId id) { + auto search = mpGroupSetResNameDB.find(id); + if (search == mpGroupSetResNameDB.cend()) + return mpDefaultInvalidString; + return search->second; } -bool CAudioSys::SysLoadGroupSet(CSimplePool* pool, CAssetId id) -{ - if (!FindGroupSet(SysGetGroupSetName(id))) - { - TLockedToken set = pool->GetObj(SObjectTag{FOURCC('AGSC'), id}); - mpGroupSetDB.emplace(std::make_pair(set->GetName(), set)); - mpGroupSetResNameDB.emplace(std::make_pair(id, set->GetName())); - return false; - } - else - { - return true; - } +bool CAudioSys::SysLoadGroupSet(CSimplePool* pool, CAssetId id) { + if (!FindGroupSet(SysGetGroupSetName(id))) { + TLockedToken set = pool->GetObj(SObjectTag{FOURCC('AGSC'), id}); + mpGroupSetDB.emplace(std::make_pair(set->GetName(), set)); + mpGroupSetResNameDB.emplace(std::make_pair(id, set->GetName())); + return false; + } else { + return true; + } } -bool CAudioSys::SysLoadGroupSet(const TLockedToken& set, std::string_view name, CAssetId id) -{ - if (!FindGroupSet(name)) - { - mpGroupSetDB.emplace(std::make_pair(set->GetName(), set)); - mpGroupSetResNameDB.emplace(std::make_pair(id, set->GetName())); - return false; - } - else - { - return true; - } +bool CAudioSys::SysLoadGroupSet(const TLockedToken& set, std::string_view name, CAssetId id) { + if (!FindGroupSet(name)) { + mpGroupSetDB.emplace(std::make_pair(set->GetName(), set)); + mpGroupSetResNameDB.emplace(std::make_pair(id, set->GetName())); + return false; + } else { + return true; + } } -void CAudioSys::SysUnloadAudioGroupSet(std::string_view name) -{ - auto set = FindGroupSet(name); - if (!set) - return; +void CAudioSys::SysUnloadAudioGroupSet(std::string_view name) { + auto set = FindGroupSet(name); + if (!set) + return; - mpGroupSetDB.erase(name.data()); - mpGroupSetResNameDB.erase(set.GetObjectTag()->id); + mpGroupSetDB.erase(name.data()); + mpGroupSetResNameDB.erase(set.GetObjectTag()->id); } -bool CAudioSys::SysIsGroupSetLoaded(std::string_view name) -{ - return FindGroupSet(name).operator bool(); +bool CAudioSys::SysIsGroupSetLoaded(std::string_view name) { return FindGroupSet(name).operator bool(); } + +void CAudioSys::SysAddGroupIntoAmuse(std::string_view name) { + if (auto set = FindGroupSet(name)) + AddAudioGroup(set->GetAudioGroupData()); } -void CAudioSys::SysAddGroupIntoAmuse(std::string_view name) -{ - if (auto set = FindGroupSet(name)) - AddAudioGroup(set->GetAudioGroupData()); -} - -void CAudioSys::SysRemoveGroupFromAmuse(std::string_view name) -{ - if (auto set = FindGroupSet(name)) - RemoveAudioGroup(set->GetAudioGroupData()); +void CAudioSys::SysRemoveGroupFromAmuse(std::string_view name) { + if (auto set = FindGroupSet(name)) + RemoveAudioGroup(set->GetAudioGroupData()); } static float s_MasterVol = 1.f; static float s_SfxVol = 1.f; -void CAudioSys::_UpdateVolume() -{ - GetAmuseEngine().setVolume(s_MasterVol * s_SfxVol); +void CAudioSys::_UpdateVolume() { GetAmuseEngine().setVolume(s_MasterVol * s_SfxVol); } + +void CAudioSys::SysSetVolume(u8 volume) { + s_MasterVol = volume / 127.f; + _UpdateVolume(); } -void CAudioSys::SysSetVolume(u8 volume) -{ - s_MasterVol = volume / 127.f; - _UpdateVolume(); -} - -void CAudioSys::SysSetSfxVolume(u8 volume, u16 time, bool music, bool fx) -{ - s_SfxVol = volume / 127.f; - _UpdateVolume(); +void CAudioSys::SysSetSfxVolume(u8 volume, u16 time, bool music, bool fx) { + s_SfxVol = volume / 127.f; + _UpdateVolume(); } static s16 s_VolumeScale = 0x7f; static s16 s_DefaultVolumeScale = 0x7f; -s16 CAudioSys::GetDefaultVolumeScale() -{ - return s_DefaultVolumeScale; -} +s16 CAudioSys::GetDefaultVolumeScale() { return s_DefaultVolumeScale; } -void CAudioSys::SetDefaultVolumeScale(s16 scale) -{ - s_DefaultVolumeScale = scale; -} +void CAudioSys::SetDefaultVolumeScale(s16 scale) { s_DefaultVolumeScale = scale; } -void CAudioSys::SetVolumeScale(s16 scale) -{ - s_VolumeScale = scale; -} +void CAudioSys::SetVolumeScale(s16 scale) { s_VolumeScale = scale; } -} +} // namespace urde diff --git a/Runtime/Audio/CAudioSys.hpp b/Runtime/Audio/CAudioSys.hpp index ba18c6bb5..f90733efa 100644 --- a/Runtime/Audio/CAudioSys.hpp +++ b/Runtime/Audio/CAudioSys.hpp @@ -7,91 +7,61 @@ #include "RetroTypes.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class CSimplePool; class CAudioGroupSet; -CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& vparms, +CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference* selfRef); -class CAudioSys -{ +class CAudioSys { public: - enum class ESurroundModes - { - Mono, - Stereo, - Surround - }; + enum class ESurroundModes { Mono, Stereo, Surround }; private: - static CAudioSys* g_SharedSys; - boo::IAudioVoiceEngine* m_voiceEngine; - amuse::Engine m_engine; - static void _UpdateVolume(); + static CAudioSys* g_SharedSys; + boo::IAudioVoiceEngine* m_voiceEngine; + amuse::Engine m_engine; + static void _UpdateVolume(); public: - struct C3DEmitterParmData - { - zeus::CVector3f x0_pos; - zeus::CVector3f xc_dir; - float x18_maxDist; - float x1c_distComp; - u32 x20_flags; - u16 x24_sfxId; - float x26_maxVol; - float x27_minVol; - bool x28_important; // Can't be allocated over, regardless of priority - u8 x29_prio; - }; - CAudioSys(boo::IAudioVoiceEngine* voiceEngine, - amuse::IBackendVoiceAllocator& backend, u8,u8,u8,u8,u32) - : m_voiceEngine(voiceEngine), m_engine(backend) - { - g_SharedSys = this; - } - ~CAudioSys() - { - g_SharedSys = nullptr; - } + struct C3DEmitterParmData { + zeus::CVector3f x0_pos; + zeus::CVector3f xc_dir; + float x18_maxDist; + float x1c_distComp; + u32 x20_flags; + u16 x24_sfxId; + float x26_maxVol; + float x27_minVol; + bool x28_important; // Can't be allocated over, regardless of priority + u8 x29_prio; + }; + CAudioSys(boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend, u8, u8, u8, u8, u32) + : m_voiceEngine(voiceEngine), m_engine(backend) { + g_SharedSys = this; + } + ~CAudioSys() { g_SharedSys = nullptr; } - static void AddAudioGroup(const amuse::AudioGroupData& data) - { - g_SharedSys->m_engine.addAudioGroup(data); - } - static void RemoveAudioGroup(const amuse::AudioGroupData& data) - { - g_SharedSys->m_engine.removeAudioGroup(data); - } - static boo::IAudioVoiceEngine* GetVoiceEngine() - { - return g_SharedSys->m_voiceEngine; - } - static amuse::Engine& GetAmuseEngine() - { - return g_SharedSys->m_engine; - } - static void SetSurroundMode(ESurroundModes mode) - { + static void AddAudioGroup(const amuse::AudioGroupData& data) { g_SharedSys->m_engine.addAudioGroup(data); } + static void RemoveAudioGroup(const amuse::AudioGroupData& data) { g_SharedSys->m_engine.removeAudioGroup(data); } + static boo::IAudioVoiceEngine* GetVoiceEngine() { return g_SharedSys->m_voiceEngine; } + static amuse::Engine& GetAmuseEngine() { return g_SharedSys->m_engine; } + static void SetSurroundMode(ESurroundModes mode) {} + static TLockedToken FindGroupSet(std::string_view name); + static std::string_view SysGetGroupSetName(CAssetId id); + static bool SysLoadGroupSet(CSimplePool* pool, CAssetId id); + static bool SysLoadGroupSet(const TLockedToken& set, std::string_view name, CAssetId id); + static void SysUnloadAudioGroupSet(std::string_view name); + static bool SysIsGroupSetLoaded(std::string_view name); + static void SysAddGroupIntoAmuse(std::string_view name); + static void SysRemoveGroupFromAmuse(std::string_view name); + static void SysSetVolume(u8 volume); + static void SysSetSfxVolume(u8 volume, u16 time, bool music, bool fx); - } - static TLockedToken FindGroupSet(std::string_view name); - static std::string_view SysGetGroupSetName(CAssetId id); - static bool SysLoadGroupSet(CSimplePool* pool, CAssetId id); - static bool SysLoadGroupSet(const TLockedToken& set, std::string_view name, CAssetId id); - static void SysUnloadAudioGroupSet(std::string_view name); - static bool SysIsGroupSetLoaded(std::string_view name); - static void SysAddGroupIntoAmuse(std::string_view name); - static void SysRemoveGroupFromAmuse(std::string_view name); - static void SysSetVolume(u8 volume); - static void SysSetSfxVolume(u8 volume, u16 time, bool music, bool fx); - - static s16 GetDefaultVolumeScale(); - static void SetDefaultVolumeScale(s16 scale); - static void SetVolumeScale(s16 scale); + static s16 GetDefaultVolumeScale(); + static void SetDefaultVolumeScale(s16 scale); + static void SetVolumeScale(s16 scale); }; -} - +} // namespace urde diff --git a/Runtime/Audio/CMidiManager.cpp b/Runtime/Audio/CMidiManager.cpp index f04e996cc..9962bce0d 100644 --- a/Runtime/Audio/CMidiManager.cpp +++ b/Runtime/Audio/CMidiManager.cpp @@ -1,60 +1,52 @@ #include "CMidiManager.hpp" -namespace urde -{ +namespace urde { std::unordered_set CMidiManager::m_MidiWrappers = {}; -void CMidiManager::StopAll() -{ - for (auto it = m_MidiWrappers.begin() ; it != m_MidiWrappers.end() ;) - it = Stop(it, 0.f); +void CMidiManager::StopAll() { + for (auto it = m_MidiWrappers.begin(); it != m_MidiWrappers.end();) + it = Stop(it, 0.f); } -void CMidiManager::Stop(const CMidiHandle& handle, float fadeTime) -{ - handle->GetAudioSysHandle()->stopSong(fadeTime); - m_MidiWrappers.erase(handle); +void CMidiManager::Stop(const CMidiHandle& handle, float fadeTime) { + handle->GetAudioSysHandle()->stopSong(fadeTime); + m_MidiWrappers.erase(handle); } -std::unordered_set::iterator -CMidiManager::Stop(std::unordered_set::iterator handle, float fadeTime) -{ - const CMidiHandle& h = *handle; - h->GetAudioSysHandle()->stopSong(fadeTime); - return m_MidiWrappers.erase(handle); +std::unordered_set::iterator CMidiManager::Stop(std::unordered_set::iterator handle, + float fadeTime) { + const CMidiHandle& h = *handle; + h->GetAudioSysHandle()->stopSong(fadeTime); + return m_MidiWrappers.erase(handle); } -CMidiHandle CMidiManager::Play(const CMidiData& data, float fadeTime, bool stopExisting, float volume) -{ - if (stopExisting) - for (auto it = m_MidiWrappers.begin() ; it != m_MidiWrappers.end() ;) - it = Stop(it, fadeTime); +CMidiHandle CMidiManager::Play(const CMidiData& data, float fadeTime, bool stopExisting, float volume) { + if (stopExisting) + for (auto it = m_MidiWrappers.begin(); it != m_MidiWrappers.end();) + it = Stop(it, fadeTime); - CMidiHandle handle = *m_MidiWrappers.insert(std::make_shared()).first; - handle->SetAudioSysHandle(CAudioSys::GetAmuseEngine().seqPlay( - data.GetGroupId(), data.GetSetupId(), data.GetArrData())); - handle->GetAudioSysHandle()->setVolume(volume, fadeTime); - handle->SetSongId(data.GetSetupId()); - return handle; + CMidiHandle handle = *m_MidiWrappers.insert(std::make_shared()).first; + handle->SetAudioSysHandle( + CAudioSys::GetAmuseEngine().seqPlay(data.GetGroupId(), data.GetSetupId(), data.GetArrData())); + handle->GetAudioSysHandle()->setVolume(volume, fadeTime); + handle->SetSongId(data.GetSetupId()); + return handle; } -CMidiManager::CMidiData::CMidiData(CInputStream& in) -{ - in.readUint32Big(); - x0_setupId = in.readUint32Big(); - x2_groupId = in.readUint32Big(); - x4_agscId = in.readUint32Big(); - u32 length = in.readUint32Big(); - x8_arrData.reset(new u8[length]); - in.readUBytesToBuf(x8_arrData.get(), length); +CMidiManager::CMidiData::CMidiData(CInputStream& in) { + in.readUint32Big(); + x0_setupId = in.readUint32Big(); + x2_groupId = in.readUint32Big(); + x4_agscId = in.readUint32Big(); + u32 length = in.readUint32Big(); + x8_arrData.reset(new u8[length]); + in.readUBytesToBuf(x8_arrData.get(), length); } -CFactoryFnReturn FMidiDataFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& parms, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); +CFactoryFnReturn FMidiDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& parms, + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/Audio/CMidiManager.hpp b/Runtime/Audio/CMidiManager.hpp index 815366531..278953f67 100644 --- a/Runtime/Audio/CMidiManager.hpp +++ b/Runtime/Audio/CMidiManager.hpp @@ -2,59 +2,55 @@ #include "CSfxManager.hpp" -namespace urde -{ +namespace urde { -class CMidiManager -{ +class CMidiManager { public: - class CMidiData - { - u16 x0_setupId; - u16 x2_groupId; - CAssetId x4_agscId; - std::unique_ptr x8_arrData; - public: - u16 GetSetupId() const { return x0_setupId; } - u16 GetGroupId() const { return x2_groupId; } - CAssetId GetAGSCAssetId() const { return x4_agscId; } - const u8* GetArrData() const { return x8_arrData.get(); } - CMidiData(CInputStream& in); - }; + class CMidiData { + u16 x0_setupId; + u16 x2_groupId; + CAssetId x4_agscId; + std::unique_ptr x8_arrData; - class CMidiWrapper - { - amuse::ObjToken x0_sequencer; - //CSfxHandle x4_handle; - u16 x8_songId; - bool xa_available = true; - public: - amuse::ObjToken GetAudioSysHandle() const { return x0_sequencer; } - void SetAudioSysHandle(amuse::ObjToken sequencer) { x0_sequencer = sequencer; } - //const CSfxHandle& GetManagerHandle() const { return x4_handle; } - //void SetMidiHandle(const CSfxHandle& handle) { x4_handle = handle; } - bool IsAvailable() const { return xa_available; } - void SetAvailable(bool available) { xa_available = available; } - u16 GetSongId() const { return x8_songId; } - void SetSongId(u16 songId) { x8_songId = songId; } - }; - using CMidiHandle = std::shared_ptr; + public: + u16 GetSetupId() const { return x0_setupId; } + u16 GetGroupId() const { return x2_groupId; } + CAssetId GetAGSCAssetId() const { return x4_agscId; } + const u8* GetArrData() const { return x8_arrData.get(); } + CMidiData(CInputStream& in); + }; - static void StopAll(); - static void Stop(const CMidiHandle& handle, float fadeTime); - static std::unordered_set::iterator - Stop(std::unordered_set::iterator handle, float fadeTime); - static CMidiHandle Play(const CMidiData& data, float fadeTime, bool stopExisting, float volume); + class CMidiWrapper { + amuse::ObjToken x0_sequencer; + // CSfxHandle x4_handle; + u16 x8_songId; + bool xa_available = true; + + public: + amuse::ObjToken GetAudioSysHandle() const { return x0_sequencer; } + void SetAudioSysHandle(amuse::ObjToken sequencer) { x0_sequencer = sequencer; } + // const CSfxHandle& GetManagerHandle() const { return x4_handle; } + // void SetMidiHandle(const CSfxHandle& handle) { x4_handle = handle; } + bool IsAvailable() const { return xa_available; } + void SetAvailable(bool available) { xa_available = available; } + u16 GetSongId() const { return x8_songId; } + void SetSongId(u16 songId) { x8_songId = songId; } + }; + using CMidiHandle = std::shared_ptr; + + static void StopAll(); + static void Stop(const CMidiHandle& handle, float fadeTime); + static std::unordered_set::iterator Stop(std::unordered_set::iterator handle, + float fadeTime); + static CMidiHandle Play(const CMidiData& data, float fadeTime, bool stopExisting, float volume); private: - static std::unordered_set m_MidiWrappers; + static std::unordered_set m_MidiWrappers; }; -CFactoryFnReturn FMidiDataFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& parms, +CFactoryFnReturn FMidiDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& parms, CObjectReference* selfRef); using CMidiHandle = CMidiManager::CMidiHandle; -} - +} // namespace urde diff --git a/Runtime/Audio/CSfxManager.cpp b/Runtime/Audio/CSfxManager.cpp index 7001f23ea..efabd2a22 100644 --- a/Runtime/Audio/CSfxManager.cpp +++ b/Runtime/Audio/CSfxManager.cpp @@ -1,8 +1,7 @@ #include "CSfxManager.hpp" #include "CSimplePool.hpp" -namespace urde -{ +namespace urde { static TLockedToken> mpSfxTranslationTableTok; std::vector* CSfxManager::mpSfxTranslationTable = nullptr; @@ -16,16 +15,14 @@ static amuse::EffectChorus* s_ChorusState = nullptr; static amuse::EffectReverbStd* s_ReverbStdState = nullptr; static amuse::EffectDelay* s_DelayState = nullptr; -CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& vparms, - CObjectReference* selfRef) -{ - std::unique_ptr> obj = std::make_unique>(); - u32 count = in.readUint32Big(); - obj->reserve(count); - for (u32 i=0 ; ipush_back(in.readUint16Big()); - return TToken>::GetIObjObjectFor(std::move(obj)); +CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, + CObjectReference* selfRef) { + std::unique_ptr> obj = std::make_unique>(); + u32 count = in.readUint32Big(); + obj->reserve(count); + for (u32 i = 0; i < count; ++i) + obj->push_back(in.readUint16Big()); + return TToken>::GetIObjObjectFor(std::move(obj)); } CSfxManager::CSfxChannel CSfxManager::m_channels[4]; @@ -44,728 +41,613 @@ u16 CSfxManager::kMedPriority; u16 CSfxManager::kInternalInvalidSfxId; u32 CSfxManager::kAllAreas; -bool CSfxManager::LoadTranslationTable(CSimplePool* pool, const SObjectTag* tag) -{ - if (!tag) - return false; - mpSfxTranslationTable = nullptr; - mpSfxTranslationTableTok = pool->GetObj(*tag); - if (!mpSfxTranslationTableTok) - return false; - return true; -} - -bool CSfxManager::CSfxWrapper::IsPlaying() const -{ - if (CBaseSfxWrapper::IsPlaying() && x1c_voiceHandle) - return x1c_voiceHandle->state() == amuse::VoiceState::Playing; +bool CSfxManager::LoadTranslationTable(CSimplePool* pool, const SObjectTag* tag) { + if (!tag) return false; -} - -void CSfxManager::CSfxWrapper::Play() -{ - x1c_voiceHandle = CAudioSys::GetAmuseEngine().fxStart(x18_sfxId, x20_vol, x22_pan); - if (x1c_voiceHandle) - { - if (CSfxManager::IsAuxProcessingEnabled() && UseAcoustics()) - x1c_voiceHandle->setReverbVol(m_reverbAmount); - SetPlaying(true); - } - x24_ready = false; -} - -void CSfxManager::CSfxWrapper::Stop() -{ - if (x1c_voiceHandle) - { - x1c_voiceHandle->keyOff(); - SetPlaying(false); - x1c_voiceHandle.reset(); - } -} - -bool CSfxManager::CSfxWrapper::Ready() -{ - if (IsLooped()) - return true; - return x24_ready; -} - -u16 CSfxManager::CSfxWrapper::GetSfxId() const -{ - return x18_sfxId; -} - -void CSfxManager::CSfxWrapper::UpdateEmitterSilent() -{ - if (x1c_voiceHandle) - x1c_voiceHandle->setVolume(1.f / 127.f); -} - -void CSfxManager::CSfxWrapper::UpdateEmitter() -{ - if (x1c_voiceHandle) - x1c_voiceHandle->setVolume(x20_vol); -} - -void CSfxManager::CSfxWrapper::SetReverb(float rev) -{ - if (x1c_voiceHandle && IsAuxProcessingEnabled() && UseAcoustics()) - x1c_voiceHandle->setReverbVol(rev); -} - -bool CSfxManager::CSfxEmitterWrapper::IsPlaying() const -{ - if (IsLooped()) - return CBaseSfxWrapper::IsPlaying(); - if (CBaseSfxWrapper::IsPlaying() && x50_emitterHandle) - return x50_emitterHandle->getVoice()->state() == amuse::VoiceState::Playing; + mpSfxTranslationTable = nullptr; + mpSfxTranslationTableTok = pool->GetObj(*tag); + if (!mpSfxTranslationTableTok) return false; + return true; } -void CSfxManager::CSfxEmitterWrapper::Play() -{ +bool CSfxManager::CSfxWrapper::IsPlaying() const { + if (CBaseSfxWrapper::IsPlaying() && x1c_voiceHandle) + return x1c_voiceHandle->state() == amuse::VoiceState::Playing; + return false; +} + +void CSfxManager::CSfxWrapper::Play() { + x1c_voiceHandle = CAudioSys::GetAmuseEngine().fxStart(x18_sfxId, x20_vol, x22_pan); + if (x1c_voiceHandle) { if (CSfxManager::IsAuxProcessingEnabled() && UseAcoustics()) - x1a_reverb = m_reverbAmount; - else - x1a_reverb = 0.f; + x1c_voiceHandle->setReverbVol(m_reverbAmount); + SetPlaying(true); + } + x24_ready = false; +} +void CSfxManager::CSfxWrapper::Stop() { + if (x1c_voiceHandle) { + x1c_voiceHandle->keyOff(); + SetPlaying(false); + x1c_voiceHandle.reset(); + } +} + +bool CSfxManager::CSfxWrapper::Ready() { + if (IsLooped()) + return true; + return x24_ready; +} + +u16 CSfxManager::CSfxWrapper::GetSfxId() const { return x18_sfxId; } + +void CSfxManager::CSfxWrapper::UpdateEmitterSilent() { + if (x1c_voiceHandle) + x1c_voiceHandle->setVolume(1.f / 127.f); +} + +void CSfxManager::CSfxWrapper::UpdateEmitter() { + if (x1c_voiceHandle) + x1c_voiceHandle->setVolume(x20_vol); +} + +void CSfxManager::CSfxWrapper::SetReverb(float rev) { + if (x1c_voiceHandle && IsAuxProcessingEnabled() && UseAcoustics()) + x1c_voiceHandle->setReverbVol(rev); +} + +bool CSfxManager::CSfxEmitterWrapper::IsPlaying() const { + if (IsLooped()) + return CBaseSfxWrapper::IsPlaying(); + if (CBaseSfxWrapper::IsPlaying() && x50_emitterHandle) + return x50_emitterHandle->getVoice()->state() == amuse::VoiceState::Playing; + return false; +} + +void CSfxManager::CSfxEmitterWrapper::Play() { + if (CSfxManager::IsAuxProcessingEnabled() && UseAcoustics()) + x1a_reverb = m_reverbAmount; + else + x1a_reverb = 0.f; + + zeus::simd_floats pos(x24_parmData.x0_pos.mSimd); + zeus::simd_floats dir(x24_parmData.xc_dir.mSimd); + x50_emitterHandle = CAudioSys::GetAmuseEngine().addEmitter( + pos.data(), dir.data(), x24_parmData.x18_maxDist, x24_parmData.x1c_distComp, x24_parmData.x24_sfxId, + x24_parmData.x27_minVol, x24_parmData.x26_maxVol, (x24_parmData.x20_flags & 0x8) != 0); + + if (x50_emitterHandle) + SetPlaying(true); + x54_ready = false; +} + +void CSfxManager::CSfxEmitterWrapper::Stop() { + if (x50_emitterHandle) { + x50_emitterHandle->getVoice()->keyOff(); + SetPlaying(false); + x50_emitterHandle.reset(); + } +} + +bool CSfxManager::CSfxEmitterWrapper::Ready() { + if (IsLooped()) + return true; + return x54_ready; +} + +CSfxManager::ESfxAudibility CSfxManager::CSfxEmitterWrapper::GetAudible(const zeus::CVector3f& vec) { + float magSq = (x24_parmData.x0_pos - vec).magSquared(); + float maxDist = x24_parmData.x18_maxDist * x24_parmData.x18_maxDist; + if (magSq < maxDist * 0.25f) + return ESfxAudibility::Aud3; + else if (magSq < maxDist * 0.5f) + return ESfxAudibility::Aud2; + else if (magSq < maxDist) + return ESfxAudibility::Aud1; + return ESfxAudibility::Aud0; +} + +u16 CSfxManager::CSfxEmitterWrapper::GetSfxId() const { return x24_parmData.x24_sfxId; } + +void CSfxManager::CSfxEmitterWrapper::UpdateEmitterSilent() { + if (x50_emitterHandle) { zeus::simd_floats pos(x24_parmData.x0_pos.mSimd); zeus::simd_floats dir(x24_parmData.xc_dir.mSimd); - x50_emitterHandle = CAudioSys::GetAmuseEngine().addEmitter( - pos.data(), dir.data(), - x24_parmData.x18_maxDist, x24_parmData.x1c_distComp, - x24_parmData.x24_sfxId, x24_parmData.x27_minVol, - x24_parmData.x26_maxVol, (x24_parmData.x20_flags & 0x8) != 0); - - if (x50_emitterHandle) - SetPlaying(true); - x54_ready = false; + x50_emitterHandle->setVectors(pos.data(), dir.data()); + x50_emitterHandle->setMaxVol(1.f / 127.f); + } + x55_cachedMaxVol = x24_parmData.x26_maxVol; } -void CSfxManager::CSfxEmitterWrapper::Stop() -{ - if (x50_emitterHandle) - { - x50_emitterHandle->getVoice()->keyOff(); - SetPlaying(false); - x50_emitterHandle.reset(); +void CSfxManager::CSfxEmitterWrapper::UpdateEmitter() { + if (x50_emitterHandle) { + zeus::simd_floats pos(x24_parmData.x0_pos.mSimd); + zeus::simd_floats dir(x24_parmData.xc_dir.mSimd); + x50_emitterHandle->setVectors(pos.data(), dir.data()); + x50_emitterHandle->setMaxVol(x55_cachedMaxVol); + } +} + +void CSfxManager::CSfxEmitterWrapper::SetReverb(float rev) { + if (IsAuxProcessingEnabled() && UseAcoustics()) + x1a_reverb = rev; +} + +void CSfxManager::SetChannel(ESfxChannels chan) { + if (m_currentChannel == chan) + return; + if (m_currentChannel != ESfxChannels::Invalid) + TurnOffChannel(m_currentChannel); + TurnOnChannel(chan); + m_currentChannel = chan; +} + +void CSfxManager::KillAll(ESfxChannels chan) { + CSfxChannel& chanObj = m_channels[int(chan)]; + for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) { + const CSfxHandle& handle = *it; + handle->Stop(); + handle->Release(); + handle->Close(); + it = chanObj.x48_handles.erase(it); + } +} + +void CSfxManager::TurnOnChannel(ESfxChannels chan) { + CSfxChannel& chanObj = m_channels[int(chan)]; + m_currentChannel = chan; + m_doUpdate = true; + if (chanObj.x44_listenerActive) { + for (const CSfxHandle& handle : chanObj.x48_handles) { + handle->UpdateEmitter(); } + } } -bool CSfxManager::CSfxEmitterWrapper::Ready() -{ - if (IsLooped()) - return true; - return x54_ready; -} - -CSfxManager::ESfxAudibility CSfxManager::CSfxEmitterWrapper::GetAudible(const zeus::CVector3f& vec) -{ - float magSq = (x24_parmData.x0_pos - vec).magSquared(); - float maxDist = x24_parmData.x18_maxDist * x24_parmData.x18_maxDist; - if (magSq < maxDist * 0.25f) - return ESfxAudibility::Aud3; - else if (magSq < maxDist * 0.5f) - return ESfxAudibility::Aud2; - else if (magSq < maxDist) - return ESfxAudibility::Aud1; - return ESfxAudibility::Aud0; -} - -u16 CSfxManager::CSfxEmitterWrapper::GetSfxId() const -{ - return x24_parmData.x24_sfxId; -} - -void CSfxManager::CSfxEmitterWrapper::UpdateEmitterSilent() -{ - if (x50_emitterHandle) - { - zeus::simd_floats pos(x24_parmData.x0_pos.mSimd); - zeus::simd_floats dir(x24_parmData.xc_dir.mSimd); - x50_emitterHandle->setVectors(pos.data(), dir.data()); - x50_emitterHandle->setMaxVol(1.f / 127.f); +void CSfxManager::TurnOffChannel(ESfxChannels chan) { + CSfxChannel& chanObj = m_channels[int(chan)]; + for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) { + const CSfxHandle& handle = *it; + if (handle->IsLooped()) { + handle->UpdateEmitterSilent(); + } else { + handle->Stop(); + handle->Close(); + it = chanObj.x48_handles.erase(it); + continue; } - x55_cachedMaxVol = x24_parmData.x26_maxVol; -} + ++it; + } -void CSfxManager::CSfxEmitterWrapper::UpdateEmitter() -{ - if (x50_emitterHandle) - { - zeus::simd_floats pos(x24_parmData.x0_pos.mSimd); - zeus::simd_floats dir(x24_parmData.xc_dir.mSimd); - x50_emitterHandle->setVectors(pos.data(), dir.data()); - x50_emitterHandle->setMaxVol(x55_cachedMaxVol); + for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) { + const CSfxHandle& handle = *it; + if (!handle->IsLooped()) { + handle->Release(); + handle->Close(); + it = chanObj.x48_handles.erase(it); + continue; } + ++it; + } } -void CSfxManager::CSfxEmitterWrapper::SetReverb(float rev) -{ - if (IsAuxProcessingEnabled() && UseAcoustics()) - x1a_reverb = rev; +void CSfxManager::AddListener(ESfxChannels channel, const zeus::CVector3f& pos, const zeus::CVector3f& dir, + const zeus::CVector3f& heading, const zeus::CVector3f& up, float frontRadius, + float surroundRadius, float soundSpeed, u32 flags /* 0x1 for doppler */, float vol) { + if (m_listener) + CAudioSys::GetAmuseEngine().removeListener(m_listener.get()); + zeus::simd_floats p(pos.mSimd); + zeus::simd_floats d(dir.mSimd); + zeus::simd_floats h(heading.mSimd); + zeus::simd_floats u(up.mSimd); + m_listener = CAudioSys::GetAmuseEngine().addListener(p.data(), d.data(), h.data(), u.data(), frontRadius, + surroundRadius, soundSpeed, vol); } -void CSfxManager::SetChannel(ESfxChannels chan) -{ - if (m_currentChannel == chan) - return; - if (m_currentChannel != ESfxChannels::Invalid) - TurnOffChannel(m_currentChannel); - TurnOnChannel(chan); - m_currentChannel = chan; -} - -void CSfxManager::KillAll(ESfxChannels chan) -{ - CSfxChannel& chanObj = m_channels[int(chan)]; - for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;) - { - const CSfxHandle& handle = *it; - handle->Stop(); - handle->Release(); - handle->Close(); - it = chanObj.x48_handles.erase(it); - } -} - -void CSfxManager::TurnOnChannel(ESfxChannels chan) -{ - CSfxChannel& chanObj = m_channels[int(chan)]; - m_currentChannel = chan; - m_doUpdate = true; - if (chanObj.x44_listenerActive) - { - for (const CSfxHandle& handle : chanObj.x48_handles) - { - handle->UpdateEmitter(); - } - } -} - -void CSfxManager::TurnOffChannel(ESfxChannels chan) -{ - CSfxChannel& chanObj = m_channels[int(chan)]; - for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;) - { - const CSfxHandle& handle = *it; - if (handle->IsLooped()) - { - handle->UpdateEmitterSilent(); - } - else - { - handle->Stop(); - handle->Close(); - it = chanObj.x48_handles.erase(it); - continue; - } - ++it; - } - - for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;) - { - const CSfxHandle& handle = *it; - if (!handle->IsLooped()) - { - handle->Release(); - handle->Close(); - it = chanObj.x48_handles.erase(it); - continue; - } - ++it; - } -} - -void CSfxManager::AddListener(ESfxChannels channel, - const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const zeus::CVector3f& heading, const zeus::CVector3f& up, - float frontRadius, float surroundRadius, float soundSpeed, - u32 flags /* 0x1 for doppler */, float vol) -{ - if (m_listener) - CAudioSys::GetAmuseEngine().removeListener(m_listener.get()); +void CSfxManager::UpdateListener(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CVector3f& heading, + const zeus::CVector3f& up, float vol) { + if (m_listener) { zeus::simd_floats p(pos.mSimd); zeus::simd_floats d(dir.mSimd); zeus::simd_floats h(heading.mSimd); zeus::simd_floats u(up.mSimd); - m_listener = CAudioSys::GetAmuseEngine().addListener(p.data(), d.data(), h.data(), u.data(), frontRadius, - surroundRadius, soundSpeed, vol); + m_listener->setVectors(p.data(), d.data(), h.data(), u.data()); + m_listener->setVolume(vol); + } } -void CSfxManager::UpdateListener(const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const zeus::CVector3f& heading, const zeus::CVector3f& up, - float vol) -{ - if (m_listener) - { - zeus::simd_floats p(pos.mSimd); - zeus::simd_floats d(dir.mSimd); - zeus::simd_floats h(heading.mSimd); - zeus::simd_floats u(up.mSimd); - m_listener->setVectors(p.data(), d.data(), h.data(), u.data()); - m_listener->setVolume(vol); - } +s16 CSfxManager::GetRank(CBaseSfxWrapper* sfx) { + CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; + if (!sfx->IsInArea()) + return 0; + + s16 rank = sfx->GetPriority() / 4; + if (sfx->IsPlaying()) + ++rank; + + if (sfx->IsLooped()) + rank -= 2; + + if (sfx->Ready() && !sfx->IsPlaying()) + rank += 3; + + if (chanObj.x44_listenerActive) { + ESfxAudibility aud = sfx->GetAudible(chanObj.x0_pos); + if (aud == ESfxAudibility::Aud0) + return 0; + rank += int(aud) / 2; + } + + return rank; } -s16 CSfxManager::GetRank(CBaseSfxWrapper* sfx) -{ - CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; - if (!sfx->IsInArea()) - return 0; - - s16 rank = sfx->GetPriority() / 4; - if (sfx->IsPlaying()) - ++rank; - - if (sfx->IsLooped()) - rank -= 2; - - if (sfx->Ready() && !sfx->IsPlaying()) - rank += 3; - - if (chanObj.x44_listenerActive) - { - ESfxAudibility aud = sfx->GetAudible(chanObj.x0_pos); - if (aud == ESfxAudibility::Aud0) - return 0; - rank += int(aud) / 2; - } - - return rank; +void CSfxManager::ApplyReverb() { + CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; + for (const CSfxHandle& handle : chanObj.x48_handles) { + handle->SetReverb(m_reverbAmount); + } } -void CSfxManager::ApplyReverb() -{ - CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; - for (const CSfxHandle& handle : chanObj.x48_handles) - { - handle->SetReverb(m_reverbAmount); - } +float CSfxManager::GetReverbAmount() { return m_reverbAmount; } + +void CSfxManager::PitchBend(const CSfxHandle& handle, float pitch) { + if (!handle) + return; + if (!handle->IsPlaying()) + CSfxManager::Update(0.f); + if (handle->IsPlaying()) { + m_doUpdate = true; + handle->GetVoice()->setPitchWheel(pitch); + } } -float CSfxManager::GetReverbAmount() -{ - return m_reverbAmount; +void CSfxManager::SfxVolume(const CSfxHandle& handle, float vol) { + if (!handle) + return; + if (handle->IsEmitter()) { + CSfxWrapper& wrapper = static_cast(*handle); + wrapper.SetVolume(vol); + } + if (handle->IsPlaying()) + handle->GetVoice()->setVolume(vol); } -void CSfxManager::PitchBend(const CSfxHandle& handle, float pitch) -{ - if (!handle) - return; - if (!handle->IsPlaying()) - CSfxManager::Update(0.f); - if (handle->IsPlaying()) - { - m_doUpdate = true; - handle->GetVoice()->setPitchWheel(pitch); - } +void CSfxManager::SfxSpan(const CSfxHandle& handle, float span) { + if (!handle) + return; + if (handle->IsPlaying()) + handle->GetVoice()->setSurroundPan(span); } -void CSfxManager::SfxVolume(const CSfxHandle& handle, float vol) -{ - if (!handle) - return; - if (handle->IsEmitter()) - { - CSfxWrapper& wrapper = static_cast(*handle); - wrapper.SetVolume(vol); - } - if (handle->IsPlaying()) - handle->GetVoice()->setVolume(vol); +u16 CSfxManager::TranslateSFXID(u16 id) { + if (mpSfxTranslationTable == nullptr) + return 0; + + u16 index = id; + if (index >= mpSfxTranslationTable->size()) + return 0; + + u16 ret = (*mpSfxTranslationTable)[index]; + if (ret == 0xffff) + return 0; + return ret; } -void CSfxManager::SfxSpan(const CSfxHandle& handle, float span) -{ - if (!handle) - return; - if (handle->IsPlaying()) - handle->GetVoice()->setSurroundPan(span); +bool CSfxManager::PlaySound(const CSfxManager::CSfxHandle& handle) { return false; } + +void CSfxManager::StopSound(const CSfxHandle& handle) { + if (!handle) + return; + m_doUpdate = true; + handle->Stop(); + handle->Release(); + CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; + handle->Close(); + chanObj.x48_handles.erase(handle); } -u16 CSfxManager::TranslateSFXID(u16 id) -{ - if (mpSfxTranslationTable == nullptr) - return 0; +void CSfxManager::SfxStop(const CSfxHandle& handle) { StopSound(handle); } - u16 index = id; - if (index >= mpSfxTranslationTable->size()) - return 0; +CSfxHandle CSfxManager::SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId) { + if (m_muted || id == 0xffff) + return {}; - u16 ret = (*mpSfxTranslationTable)[index]; - if (ret == 0xffff) - return 0; - return ret; + m_doUpdate = true; + CSfxHandle wrapper = std::make_shared(looped, prio, id, vol, pan, useAcoustics, areaId); + CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; + chanObj.x48_handles.insert(wrapper); + return wrapper; } -bool CSfxManager::PlaySound(const CSfxManager::CSfxHandle &handle) -{ +bool CSfxManager::IsPlaying(const CSfxHandle& handle) { + if (!handle) return false; + return handle->IsPlaying(); } -void CSfxManager::StopSound(const CSfxHandle& handle) -{ - if (!handle) - return; - m_doUpdate = true; - handle->Stop(); - handle->Release(); - CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; - handle->Close(); - chanObj.x48_handles.erase(handle); +void CSfxManager::RemoveEmitter(const CSfxHandle& handle) { StopSound(handle); } + +void CSfxManager::UpdateEmitter(const CSfxHandle& handle, const zeus::CVector3f& pos, const zeus::CVector3f& dir, + float maxVol) { + if (!handle || !handle->IsEmitter() || !handle->IsPlaying()) + return; + m_doUpdate = true; + CSfxEmitterWrapper& emitter = static_cast(*handle); + emitter.GetEmitterData().x0_pos = pos; + emitter.GetEmitterData().xc_dir = dir; + emitter.GetEmitterData().x26_maxVol = maxVol; + amuse::Emitter& h = *emitter.GetHandle(); + zeus::simd_floats p(pos.mSimd); + zeus::simd_floats d(dir.mSimd); + h.setVectors(p.data(), d.data()); + h.setMaxVol(maxVol); } -void CSfxManager::SfxStop(const CSfxHandle& handle) -{ - StopSound(handle); -} - -CSfxHandle CSfxManager::SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId) -{ - if (m_muted || id == 0xffff) - return {}; - - m_doUpdate = true; - CSfxHandle wrapper = std::make_shared(looped, prio, id, vol, pan, useAcoustics, areaId); - CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; - chanObj.x48_handles.insert(wrapper); - return wrapper; -} - -bool CSfxManager::IsPlaying(const CSfxHandle& handle) -{ - if (!handle) - return false; - return handle->IsPlaying(); -} - -void CSfxManager::RemoveEmitter(const CSfxHandle& handle) -{ - StopSound(handle); -} - -void CSfxManager::UpdateEmitter(const CSfxHandle& handle, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float maxVol) -{ - if (!handle || !handle->IsEmitter() || !handle->IsPlaying()) - return; - m_doUpdate = true; - CSfxEmitterWrapper& emitter = static_cast(*handle); - emitter.GetEmitterData().x0_pos = pos; - emitter.GetEmitterData().xc_dir = dir; - emitter.GetEmitterData().x26_maxVol = maxVol; - amuse::Emitter& h = *emitter.GetHandle(); - zeus::simd_floats p(pos.mSimd); - zeus::simd_floats d(dir.mSimd); - h.setVectors(p.data(), d.data()); - h.setMaxVol(maxVol); -} - -CSfxHandle CSfxManager::AddEmitter(u16 id, const zeus::CVector3f& pos, const zeus::CVector3f& dir, - bool useAcoustics, bool looped, s16 prio, s32 areaId) -{ - CAudioSys::C3DEmitterParmData parmData; - parmData.x0_pos = pos; - parmData.xc_dir = dir; - parmData.x18_maxDist = 150.f; - parmData.x1c_distComp = 0.1f; - parmData.x20_flags = 1; // Continuous parameter update - parmData.x24_sfxId = id; - parmData.x26_maxVol = 1.f; - parmData.x27_minVol = 0.165f; - parmData.x28_important = false; - parmData.x29_prio = 0x7f; - return AddEmitter(parmData, useAcoustics, prio, looped, areaId); +CSfxHandle CSfxManager::AddEmitter(u16 id, const zeus::CVector3f& pos, const zeus::CVector3f& dir, bool useAcoustics, + bool looped, s16 prio, s32 areaId) { + CAudioSys::C3DEmitterParmData parmData; + parmData.x0_pos = pos; + parmData.xc_dir = dir; + parmData.x18_maxDist = 150.f; + parmData.x1c_distComp = 0.1f; + parmData.x20_flags = 1; // Continuous parameter update + parmData.x24_sfxId = id; + parmData.x26_maxVol = 1.f; + parmData.x27_minVol = 0.165f; + parmData.x28_important = false; + parmData.x29_prio = 0x7f; + return AddEmitter(parmData, useAcoustics, prio, looped, areaId); } CSfxHandle CSfxManager::AddEmitter(u16 id, const zeus::CVector3f& pos, const zeus::CVector3f& dir, float vol, - bool useAcoustics, bool looped, s16 prio, s32 areaId) -{ - CAudioSys::C3DEmitterParmData parmData; - parmData.x0_pos = pos; - parmData.xc_dir = dir; - parmData.x18_maxDist = 150.f; - parmData.x1c_distComp = 0.1f; - parmData.x20_flags = 1; // Continuous parameter update - parmData.x24_sfxId = id; - parmData.x26_maxVol = std::max(vol, 0.165f); - parmData.x27_minVol = 0.165f; - parmData.x28_important = false; - parmData.x29_prio = 0x7f; - return AddEmitter(parmData, useAcoustics, prio, looped, areaId); + bool useAcoustics, bool looped, s16 prio, s32 areaId) { + CAudioSys::C3DEmitterParmData parmData; + parmData.x0_pos = pos; + parmData.xc_dir = dir; + parmData.x18_maxDist = 150.f; + parmData.x1c_distComp = 0.1f; + parmData.x20_flags = 1; // Continuous parameter update + parmData.x24_sfxId = id; + parmData.x26_maxVol = std::max(vol, 0.165f); + parmData.x27_minVol = 0.165f; + parmData.x28_important = false; + parmData.x29_prio = 0x7f; + return AddEmitter(parmData, useAcoustics, prio, looped, areaId); } -CSfxHandle CSfxManager::AddEmitter(const CAudioSys::C3DEmitterParmData& parmData, - bool useAcoustics, s16 prio, bool looped, s32 areaId) -{ - if (m_muted || parmData.x24_sfxId == 0xffff) - return {}; +CSfxHandle CSfxManager::AddEmitter(const CAudioSys::C3DEmitterParmData& parmData, bool useAcoustics, s16 prio, + bool looped, s32 areaId) { + if (m_muted || parmData.x24_sfxId == 0xffff) + return {}; - CAudioSys::C3DEmitterParmData data = parmData; - if (looped) - data.x20_flags |= 0x6; // Pausable/restartable when inaudible - m_doUpdate = true; - CSfxHandle wrapper = std::make_shared(looped, prio, data, useAcoustics, areaId); - CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; - chanObj.x48_handles.insert(wrapper); - return wrapper; + CAudioSys::C3DEmitterParmData data = parmData; + if (looped) + data.x20_flags |= 0x6; // Pausable/restartable when inaudible + m_doUpdate = true; + CSfxHandle wrapper = std::make_shared(looped, prio, data, useAcoustics, areaId); + CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; + chanObj.x48_handles.insert(wrapper); + return wrapper; } -void CSfxManager::StopAndRemoveAllEmitters() -{ - for (int i=0 ; i<4 ; ++i) - { - CSfxChannel& chanObj = m_channels[i]; - for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;) - { - const CSfxHandle& handle = *it; - handle->Stop(); - handle->Release(); - handle->Close(); - it = chanObj.x48_handles.erase(it); - } +void CSfxManager::StopAndRemoveAllEmitters() { + for (int i = 0; i < 4; ++i) { + CSfxChannel& chanObj = m_channels[i]; + for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) { + const CSfxHandle& handle = *it; + handle->Stop(); + handle->Release(); + handle->Close(); + it = chanObj.x48_handles.erase(it); } + } } -void CSfxManager::EnableAuxCallback() -{ - m_reverbAmount = 0.f; - ApplyReverb(); - if (m_activeEffect != EAuxEffect::None) - DisableAuxCallback(); - - auto studio = CAudioSys::GetAmuseEngine().getDefaultStudio(); - amuse::Submix& smix = studio->getAuxA(); - - m_activeEffect = m_nextEffect; - switch (m_activeEffect) - { - case EAuxEffect::ReverbHi: - s_ReverbHiState = &smix.makeReverbHi(s_ReverbHiQueued); - break; - case EAuxEffect::Chorus: - s_ChorusState = &smix.makeChorus(s_ChorusQueued); - break; - case EAuxEffect::ReverbStd: - s_ReverbStdState = &smix.makeReverbStd(s_ReverbStdQueued); - break; - case EAuxEffect::Delay: - s_DelayState = &smix.makeDelay(s_DelayQueued); - break; - default: break; - } - - m_auxProcessingEnabled = true; -} - -void CSfxManager::PrepareDelayCallback(const amuse::EffectDelayInfo& info) -{ - DisableAuxProcessing(); - s_DelayQueued = info; - m_nextEffect = EAuxEffect::Delay; - if (m_reverbAmount == 0.f) - EnableAuxCallback(); -} - -void CSfxManager::PrepareReverbStdCallback(const amuse::EffectReverbStdInfo& info) -{ - DisableAuxProcessing(); - s_ReverbStdQueued = info; - m_nextEffect = EAuxEffect::ReverbStd; - if (m_reverbAmount == 0.f) - EnableAuxCallback(); -} - -void CSfxManager::PrepareChorusCallback(const amuse::EffectChorusInfo& info) -{ - DisableAuxProcessing(); - s_ChorusQueued = info; - m_nextEffect = EAuxEffect::Chorus; - if (m_reverbAmount == 0.f) - EnableAuxCallback(); -} - -void CSfxManager::PrepareReverbHiCallback(const amuse::EffectReverbHiInfo& info) -{ - DisableAuxProcessing(); - s_ReverbHiQueued = info; - m_nextEffect = EAuxEffect::ReverbHi; - if (m_reverbAmount == 0.f) - EnableAuxCallback(); -} - -void CSfxManager::DisableAuxCallback() -{ - auto studio = CAudioSys::GetAmuseEngine().getDefaultStudio(); - studio->getAuxA().clearEffects(); - - switch (m_activeEffect) - { - case EAuxEffect::ReverbHi: - s_ReverbHiState = nullptr; - break; - case EAuxEffect::Chorus: - s_ChorusState = nullptr; - break; - case EAuxEffect::ReverbStd: - s_ReverbStdState = nullptr; - break; - case EAuxEffect::Delay: - s_DelayState = nullptr; - break; - default: break; - } - - m_activeEffect = EAuxEffect::None; -} - -void CSfxManager::DisableAuxProcessing() -{ - m_nextEffect = EAuxEffect::None; - m_auxProcessingEnabled = false; -} - -void CSfxManager::SetActiveAreas(const rstl::reserved_vector& areas) -{ - CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; - - for (const CSfxHandle& hnd : chanObj.x48_handles) - { - TAreaId sndArea = hnd->GetArea(); - if (sndArea == kInvalidAreaId) - { - hnd->SetInArea(true); - } - else - { - bool inArea = false; - for (TAreaId id : areas) - { - if (sndArea == id) - { - inArea = true; - break; - } - } - m_doUpdate = true; - hnd->SetInArea(inArea); - } - } -} - -void CSfxManager::Update(float dt) -{ - CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; - - for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;) - { - const CSfxHandle& handle = *it; - if (!handle->IsLooped()) - { - float timeRem = handle->GetTimeRemaining(); - handle->SetTimeRemaining(timeRem - dt); - if (timeRem < 0.f) - { - handle->Stop(); - m_doUpdate = true; - handle->Close(); - it = chanObj.x48_handles.erase(it); - continue; - } - } - ++it; - } - - if (m_doUpdate) - { - std::vector rankedSfx; - rankedSfx.reserve(chanObj.x48_handles.size()); - for (const CSfxHandle& handle : chanObj.x48_handles) - { - rankedSfx.push_back(handle); - handle->SetRank(GetRank(handle.get())); - } - - std::sort(rankedSfx.begin(), rankedSfx.end(), - [](const CSfxHandle& a, const CSfxHandle& b) -> bool - { - return a->GetRank() < b->GetRank(); - }); - - for (int i=48 ; iIsPlaying()) - { - handle->Stop(); - handle->Close(); - chanObj.x48_handles.erase(handle); - } - } - - for (const CSfxHandle& handle : rankedSfx) - { - if (handle->IsPlaying() && !handle->IsInArea()) - { - handle->Stop(); - handle->Close(); - chanObj.x48_handles.erase(handle); - } - } - - for (const CSfxHandle& handle : chanObj.x48_handles) - { - if (handle->IsPlaying()) - continue; - if (handle->Ready() && handle->IsInArea()) - handle->Play(); - } - - m_doUpdate = false; - } - - for (auto it = chanObj.x48_handles.begin() ; it != chanObj.x48_handles.end() ;) - { - const CSfxHandle& handle = *it; - if (!handle->IsPlaying() && !handle->IsLooped()) - { - handle->Stop(); - handle->Release(); - m_doUpdate = true; - handle->Close(); - it = chanObj.x48_handles.erase(it); - continue; - } - ++it; - } - - if (m_auxProcessingEnabled && m_reverbAmount < 1.f) - { - m_reverbAmount = std::min(1.f, dt / 0.1f + m_reverbAmount); - ApplyReverb(); - } - else if (!m_auxProcessingEnabled && m_reverbAmount > 0.f) - { - m_reverbAmount = std::max(0.f, m_reverbAmount - dt / (2.f * 0.1f)); - ApplyReverb(); - if (m_reverbAmount == 0.f) - { - DisableAuxCallback(); - EnableAuxCallback(); - } - } - - if (mpSfxTranslationTableTok.IsLoaded() && !mpSfxTranslationTable) - mpSfxTranslationTable = mpSfxTranslationTableTok.GetObj(); -} - -void CSfxManager::Shutdown() -{ - mpSfxTranslationTable = nullptr; - mpSfxTranslationTableTok = TLockedToken>{}; - StopAndRemoveAllEmitters(); +void CSfxManager::EnableAuxCallback() { + m_reverbAmount = 0.f; + ApplyReverb(); + if (m_activeEffect != EAuxEffect::None) DisableAuxCallback(); + + auto studio = CAudioSys::GetAmuseEngine().getDefaultStudio(); + amuse::Submix& smix = studio->getAuxA(); + + m_activeEffect = m_nextEffect; + switch (m_activeEffect) { + case EAuxEffect::ReverbHi: + s_ReverbHiState = &smix.makeReverbHi(s_ReverbHiQueued); + break; + case EAuxEffect::Chorus: + s_ChorusState = &smix.makeChorus(s_ChorusQueued); + break; + case EAuxEffect::ReverbStd: + s_ReverbStdState = &smix.makeReverbStd(s_ReverbStdQueued); + break; + case EAuxEffect::Delay: + s_DelayState = &smix.makeDelay(s_DelayQueued); + break; + default: + break; + } + + m_auxProcessingEnabled = true; } +void CSfxManager::PrepareDelayCallback(const amuse::EffectDelayInfo& info) { + DisableAuxProcessing(); + s_DelayQueued = info; + m_nextEffect = EAuxEffect::Delay; + if (m_reverbAmount == 0.f) + EnableAuxCallback(); } + +void CSfxManager::PrepareReverbStdCallback(const amuse::EffectReverbStdInfo& info) { + DisableAuxProcessing(); + s_ReverbStdQueued = info; + m_nextEffect = EAuxEffect::ReverbStd; + if (m_reverbAmount == 0.f) + EnableAuxCallback(); +} + +void CSfxManager::PrepareChorusCallback(const amuse::EffectChorusInfo& info) { + DisableAuxProcessing(); + s_ChorusQueued = info; + m_nextEffect = EAuxEffect::Chorus; + if (m_reverbAmount == 0.f) + EnableAuxCallback(); +} + +void CSfxManager::PrepareReverbHiCallback(const amuse::EffectReverbHiInfo& info) { + DisableAuxProcessing(); + s_ReverbHiQueued = info; + m_nextEffect = EAuxEffect::ReverbHi; + if (m_reverbAmount == 0.f) + EnableAuxCallback(); +} + +void CSfxManager::DisableAuxCallback() { + auto studio = CAudioSys::GetAmuseEngine().getDefaultStudio(); + studio->getAuxA().clearEffects(); + + switch (m_activeEffect) { + case EAuxEffect::ReverbHi: + s_ReverbHiState = nullptr; + break; + case EAuxEffect::Chorus: + s_ChorusState = nullptr; + break; + case EAuxEffect::ReverbStd: + s_ReverbStdState = nullptr; + break; + case EAuxEffect::Delay: + s_DelayState = nullptr; + break; + default: + break; + } + + m_activeEffect = EAuxEffect::None; +} + +void CSfxManager::DisableAuxProcessing() { + m_nextEffect = EAuxEffect::None; + m_auxProcessingEnabled = false; +} + +void CSfxManager::SetActiveAreas(const rstl::reserved_vector& areas) { + CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; + + for (const CSfxHandle& hnd : chanObj.x48_handles) { + TAreaId sndArea = hnd->GetArea(); + if (sndArea == kInvalidAreaId) { + hnd->SetInArea(true); + } else { + bool inArea = false; + for (TAreaId id : areas) { + if (sndArea == id) { + inArea = true; + break; + } + } + m_doUpdate = true; + hnd->SetInArea(inArea); + } + } +} + +void CSfxManager::Update(float dt) { + CSfxChannel& chanObj = m_channels[int(m_currentChannel)]; + + for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) { + const CSfxHandle& handle = *it; + if (!handle->IsLooped()) { + float timeRem = handle->GetTimeRemaining(); + handle->SetTimeRemaining(timeRem - dt); + if (timeRem < 0.f) { + handle->Stop(); + m_doUpdate = true; + handle->Close(); + it = chanObj.x48_handles.erase(it); + continue; + } + } + ++it; + } + + if (m_doUpdate) { + std::vector rankedSfx; + rankedSfx.reserve(chanObj.x48_handles.size()); + for (const CSfxHandle& handle : chanObj.x48_handles) { + rankedSfx.push_back(handle); + handle->SetRank(GetRank(handle.get())); + } + + std::sort(rankedSfx.begin(), rankedSfx.end(), + [](const CSfxHandle& a, const CSfxHandle& b) -> bool { return a->GetRank() < b->GetRank(); }); + + for (int i = 48; i < rankedSfx.size(); ++i) { + const CSfxHandle& handle = rankedSfx[i]; + if (handle->IsPlaying()) { + handle->Stop(); + handle->Close(); + chanObj.x48_handles.erase(handle); + } + } + + for (const CSfxHandle& handle : rankedSfx) { + if (handle->IsPlaying() && !handle->IsInArea()) { + handle->Stop(); + handle->Close(); + chanObj.x48_handles.erase(handle); + } + } + + for (const CSfxHandle& handle : chanObj.x48_handles) { + if (handle->IsPlaying()) + continue; + if (handle->Ready() && handle->IsInArea()) + handle->Play(); + } + + m_doUpdate = false; + } + + for (auto it = chanObj.x48_handles.begin(); it != chanObj.x48_handles.end();) { + const CSfxHandle& handle = *it; + if (!handle->IsPlaying() && !handle->IsLooped()) { + handle->Stop(); + handle->Release(); + m_doUpdate = true; + handle->Close(); + it = chanObj.x48_handles.erase(it); + continue; + } + ++it; + } + + if (m_auxProcessingEnabled && m_reverbAmount < 1.f) { + m_reverbAmount = std::min(1.f, dt / 0.1f + m_reverbAmount); + ApplyReverb(); + } else if (!m_auxProcessingEnabled && m_reverbAmount > 0.f) { + m_reverbAmount = std::max(0.f, m_reverbAmount - dt / (2.f * 0.1f)); + ApplyReverb(); + if (m_reverbAmount == 0.f) { + DisableAuxCallback(); + EnableAuxCallback(); + } + } + + if (mpSfxTranslationTableTok.IsLoaded() && !mpSfxTranslationTable) + mpSfxTranslationTable = mpSfxTranslationTableTok.GetObj(); +} + +void CSfxManager::Shutdown() { + mpSfxTranslationTable = nullptr; + mpSfxTranslationTableTok = TLockedToken>{}; + StopAndRemoveAllEmitters(); + DisableAuxCallback(); +} + +} // namespace urde diff --git a/Runtime/Audio/CSfxManager.hpp b/Runtime/Audio/CSfxManager.hpp index 5d1ba79c4..a2bffc775 100644 --- a/Runtime/Audio/CSfxManager.hpp +++ b/Runtime/Audio/CSfxManager.hpp @@ -6,256 +6,238 @@ #include "CAudioSys.hpp" #include "DNAMP1/SFX/SFX.h" -namespace urde -{ +namespace urde { + +class CSfxManager { + static std::vector* mpSfxTranslationTable; -class CSfxManager -{ - static std::vector* mpSfxTranslationTable; public: + enum class ESfxChannels { Invalid = -1, Default = 0, Game, PauseScreen }; - enum class ESfxChannels - { - Invalid = -1, - Default = 0, - Game, - PauseScreen - }; + enum class ESfxAudibility { Aud0, Aud1, Aud2, Aud3 }; - enum class ESfxAudibility - { - Aud0, - Aud1, - Aud2, - Aud3 - }; + enum class EAuxEffect { None = -1, ReverbHi = 0, Chorus, ReverbStd, Delay }; - enum class EAuxEffect - { - None = -1, - ReverbHi = 0, - Chorus, - ReverbStd, - Delay - }; + class CBaseSfxWrapper; + using CSfxHandle = std::shared_ptr; - class CBaseSfxWrapper; - using CSfxHandle = std::shared_ptr; + /* Original imp, kept for reference + class CSfxHandle + { + static u32 mRefCount; + u32 x0_idx; + public: + CSfxHandle(u32 id) + : x0_idx(++mRefCount << 14 | (id & 0xFFFF)) {} + }; + */ - /* Original imp, kept for reference - class CSfxHandle - { - static u32 mRefCount; - u32 x0_idx; - public: - CSfxHandle(u32 id) - : x0_idx(++mRefCount << 14 | (id & 0xFFFF)) {} - }; + class CSfxChannel { + friend class CSfxManager; + zeus::CVector3f x0_pos; + zeus::CVector3f xc_; + zeus::CVector3f x18_; + zeus::CVector3f x24_; + /* + float x30_ = 0.f; + float x34_ = 0.f; + float x38_ = 0.f; + u32 x3c_ = 0; + bool x40_ = false; */ + bool x44_listenerActive = false; + std::unordered_set x48_handles; + }; - class CSfxChannel - { - friend class CSfxManager; - zeus::CVector3f x0_pos; - zeus::CVector3f xc_; - zeus::CVector3f x18_; - zeus::CVector3f x24_; - /* - float x30_ = 0.f; - float x34_ = 0.f; - float x38_ = 0.f; - u32 x3c_ = 0; - bool x40_ = false; - */ - bool x44_listenerActive = false; - std::unordered_set x48_handles; - }; + class CBaseSfxWrapper : public std::enable_shared_from_this { + float x4_timeRemaining = 15.f; + s16 x8_rank = 0; + s16 xa_prio; + // CSfxHandle xc_handle; + TAreaId x10_area; + bool x14_24_isActive : 1; + bool x14_25_isPlaying : 1; + bool x14_26_looped : 1; + bool x14_27_inArea : 1; + bool x14_28_isReleased : 1; + bool x14_29_useAcoustics : 1; - class CBaseSfxWrapper : public std::enable_shared_from_this - { - float x4_timeRemaining = 15.f; - s16 x8_rank = 0; - s16 xa_prio; - //CSfxHandle xc_handle; - TAreaId x10_area; - bool x14_24_isActive:1; - bool x14_25_isPlaying:1; - bool x14_26_looped:1; - bool x14_27_inArea:1; - bool x14_28_isReleased:1; - bool x14_29_useAcoustics:1; - protected: - bool m_isEmitter:1; - bool m_isClosed:1; - public: - virtual ~CBaseSfxWrapper() = default; - virtual void SetActive(bool v) { x14_24_isActive = v; } - virtual void SetPlaying(bool v) { x14_25_isPlaying = v; } - virtual void SetRank(short v) { x8_rank = v; } - virtual void SetInArea(bool v) { x14_27_inArea = v; } - virtual bool IsInArea() const { return x14_27_inArea; } - virtual bool IsPlaying() const { return x14_25_isPlaying; } - virtual bool UseAcoustics() const { return x14_29_useAcoustics; } - virtual bool IsLooped() const { return x14_26_looped; } - virtual bool IsActive() const { return x14_24_isActive; } - virtual s16 GetRank() const { return x8_rank; } - virtual s16 GetPriority() const { return xa_prio; } - virtual TAreaId GetArea() const { return x10_area; } - virtual CSfxHandle GetSfxHandle() { return shared_from_this(); } - virtual void Play()=0; - virtual void Stop()=0; - virtual bool Ready()=0; - virtual ESfxAudibility GetAudible(const zeus::CVector3f&)=0; - virtual amuse::ObjToken GetVoice() const=0; - virtual u16 GetSfxId() const=0; - virtual void UpdateEmitterSilent()=0; - virtual void UpdateEmitter()=0; - virtual void SetReverb(float rev)=0; - bool IsEmitter() const { return m_isEmitter; } + protected: + bool m_isEmitter : 1; + bool m_isClosed : 1; - void Release() { x14_28_isReleased = true; x4_timeRemaining = 15.f; } - bool IsReleased() const { return x14_28_isReleased; } + public: + virtual ~CBaseSfxWrapper() = default; + virtual void SetActive(bool v) { x14_24_isActive = v; } + virtual void SetPlaying(bool v) { x14_25_isPlaying = v; } + virtual void SetRank(short v) { x8_rank = v; } + virtual void SetInArea(bool v) { x14_27_inArea = v; } + virtual bool IsInArea() const { return x14_27_inArea; } + virtual bool IsPlaying() const { return x14_25_isPlaying; } + virtual bool UseAcoustics() const { return x14_29_useAcoustics; } + virtual bool IsLooped() const { return x14_26_looped; } + virtual bool IsActive() const { return x14_24_isActive; } + virtual s16 GetRank() const { return x8_rank; } + virtual s16 GetPriority() const { return xa_prio; } + virtual TAreaId GetArea() const { return x10_area; } + virtual CSfxHandle GetSfxHandle() { return shared_from_this(); } + virtual void Play() = 0; + virtual void Stop() = 0; + virtual bool Ready() = 0; + virtual ESfxAudibility GetAudible(const zeus::CVector3f&) = 0; + virtual amuse::ObjToken GetVoice() const = 0; + virtual u16 GetSfxId() const = 0; + virtual void UpdateEmitterSilent() = 0; + virtual void UpdateEmitter() = 0; + virtual void SetReverb(float rev) = 0; + bool IsEmitter() const { return m_isEmitter; } - void Close() { m_isClosed = true; } - bool IsClosed() const { return m_isClosed; } + void Release() { + x14_28_isReleased = true; + x4_timeRemaining = 15.f; + } + bool IsReleased() const { return x14_28_isReleased; } - float GetTimeRemaining() const { return x4_timeRemaining; } - void SetTimeRemaining(float t) { x4_timeRemaining = t; } + void Close() { m_isClosed = true; } + bool IsClosed() const { return m_isClosed; } - CBaseSfxWrapper(bool looped, s16 prio, /*const CSfxHandle& handle,*/ bool useAcoustics, TAreaId area) - : x8_rank(0), xa_prio(prio), /*xc_handle(handle),*/ x10_area(area), x14_24_isActive(true), x14_25_isPlaying(false), - x14_26_looped(looped), x14_27_inArea(true), x14_28_isReleased(false), m_isClosed(false), - x14_29_useAcoustics(useAcoustics) {} - }; + float GetTimeRemaining() const { return x4_timeRemaining; } + void SetTimeRemaining(float t) { x4_timeRemaining = t; } - class CSfxEmitterWrapper : public CBaseSfxWrapper - { - float x1a_reverb; - CAudioSys::C3DEmitterParmData x24_parmData; - amuse::ObjToken x50_emitterHandle; - bool x54_ready = true; - float x55_cachedMaxVol; - public: - bool IsPlaying() const; - void Play(); - void Stop(); - bool Ready(); - ESfxAudibility GetAudible(const zeus::CVector3f&); - amuse::ObjToken GetVoice() const { return x50_emitterHandle->getVoice(); } - u16 GetSfxId() const; - void UpdateEmitterSilent(); - void UpdateEmitter(); - void SetReverb(float rev); - CAudioSys::C3DEmitterParmData& GetEmitterData() { return x24_parmData; } + CBaseSfxWrapper(bool looped, s16 prio, /*const CSfxHandle& handle,*/ bool useAcoustics, TAreaId area) + : x8_rank(0) + , xa_prio(prio) + , /*xc_handle(handle),*/ x10_area(area) + , x14_24_isActive(true) + , x14_25_isPlaying(false) + , x14_26_looped(looped) + , x14_27_inArea(true) + , x14_28_isReleased(false) + , m_isClosed(false) + , x14_29_useAcoustics(useAcoustics) {} + }; - amuse::ObjToken GetHandle() const { return x50_emitterHandle; } + class CSfxEmitterWrapper : public CBaseSfxWrapper { + float x1a_reverb; + CAudioSys::C3DEmitterParmData x24_parmData; + amuse::ObjToken x50_emitterHandle; + bool x54_ready = true; + float x55_cachedMaxVol; - CSfxEmitterWrapper(bool looped, s16 prio, const CAudioSys::C3DEmitterParmData& data, - /*const CSfxHandle& handle,*/ bool useAcoustics, TAreaId area) - : CBaseSfxWrapper(looped, prio, /*handle,*/ useAcoustics, area), x24_parmData(data) - { - m_isEmitter = true; - } - }; + public: + bool IsPlaying() const; + void Play(); + void Stop(); + bool Ready(); + ESfxAudibility GetAudible(const zeus::CVector3f&); + amuse::ObjToken GetVoice() const { return x50_emitterHandle->getVoice(); } + u16 GetSfxId() const; + void UpdateEmitterSilent(); + void UpdateEmitter(); + void SetReverb(float rev); + CAudioSys::C3DEmitterParmData& GetEmitterData() { return x24_parmData; } - class CSfxWrapper : public CBaseSfxWrapper - { - u16 x18_sfxId; - amuse::ObjToken x1c_voiceHandle; - float x20_vol; - float x22_pan; - bool x24_ready = true; - public: - bool IsPlaying() const; - void Play(); - void Stop(); - bool Ready(); - ESfxAudibility GetAudible(const zeus::CVector3f&) { return ESfxAudibility::Aud3; } - amuse::ObjToken GetVoice() const { return x1c_voiceHandle; } - u16 GetSfxId() const; - void UpdateEmitterSilent(); - void UpdateEmitter(); - void SetReverb(float rev); - void SetVolume(float vol) { x20_vol = vol; } + amuse::ObjToken GetHandle() const { return x50_emitterHandle; } - CSfxWrapper(bool looped, s16 prio, u16 sfxId, float vol, float pan, - /*const CSfxHandle& handle,*/ bool useAcoustics, TAreaId area) - : CBaseSfxWrapper(looped, prio, /*handle,*/ useAcoustics, area), - x18_sfxId(sfxId), x20_vol(vol), x22_pan(pan) - { - m_isEmitter = false; - } - }; + CSfxEmitterWrapper(bool looped, s16 prio, const CAudioSys::C3DEmitterParmData& data, + /*const CSfxHandle& handle,*/ bool useAcoustics, TAreaId area) + : CBaseSfxWrapper(looped, prio, /*handle,*/ useAcoustics, area), x24_parmData(data) { + m_isEmitter = true; + } + }; - static CSfxChannel m_channels[4]; - static ESfxChannels m_currentChannel; - static bool m_doUpdate; - static void* m_usedSounds; - static bool m_muted; - static bool m_auxProcessingEnabled; - static float m_reverbAmount; - static EAuxEffect m_activeEffect; - static EAuxEffect m_nextEffect; - static amuse::ObjToken m_listener; + class CSfxWrapper : public CBaseSfxWrapper { + u16 x18_sfxId; + amuse::ObjToken x1c_voiceHandle; + float x20_vol; + float x22_pan; + bool x24_ready = true; - static u16 kMaxPriority; - static u16 kMedPriority; - static u16 kInternalInvalidSfxId; - static u32 kAllAreas; + public: + bool IsPlaying() const; + void Play(); + void Stop(); + bool Ready(); + ESfxAudibility GetAudible(const zeus::CVector3f&) { return ESfxAudibility::Aud3; } + amuse::ObjToken GetVoice() const { return x1c_voiceHandle; } + u16 GetSfxId() const; + void UpdateEmitterSilent(); + void UpdateEmitter(); + void SetReverb(float rev); + void SetVolume(float vol) { x20_vol = vol; } - static bool LoadTranslationTable(CSimplePool* pool, const SObjectTag* tag); - static bool IsAuxProcessingEnabled() { return m_auxProcessingEnabled; } - static void SetChannel(ESfxChannels); - static void KillAll(ESfxChannels); - static void TurnOnChannel(ESfxChannels); - static void TurnOffChannel(ESfxChannels); - static ESfxChannels GetCurrentChannel() {return m_currentChannel;} - static void AddListener(ESfxChannels channel, - const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const zeus::CVector3f& heading, const zeus::CVector3f& up, - float frontRadius, float surroundRadius, float soundSpeed, - u32 flags /* 0x1 for doppler */, float vol); - static void UpdateListener(const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const zeus::CVector3f& heading, const zeus::CVector3f& up, - float vol); + CSfxWrapper(bool looped, s16 prio, u16 sfxId, float vol, float pan, + /*const CSfxHandle& handle,*/ bool useAcoustics, TAreaId area) + : CBaseSfxWrapper(looped, prio, /*handle,*/ useAcoustics, area), x18_sfxId(sfxId), x20_vol(vol), x22_pan(pan) { + m_isEmitter = false; + } + }; - static bool PlaySound(const CSfxHandle& handle); - static void StopSound(const CSfxHandle& handle); - static s16 GetRank(CBaseSfxWrapper* sfx); - static void ApplyReverb(); - static float GetReverbAmount(); - static void PitchBend(const CSfxHandle& handle, float pitch); - static void SfxVolume(const CSfxHandle& handle, float vol); - static void SfxSpan(const CSfxHandle& handle, float span); - static u16 TranslateSFXID(u16); - static void SfxStop(const CSfxHandle& handle); - static CSfxHandle SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId); - static bool IsPlaying(const CSfxHandle& handle); - static void RemoveEmitter(const CSfxHandle& handle); - static void UpdateEmitter(const CSfxHandle& handle, const zeus::CVector3f& pos, const zeus::CVector3f& dir, - float maxVol); - static CSfxHandle AddEmitter(u16 id, const zeus::CVector3f& pos, const zeus::CVector3f& dir, - bool useAcoustics, bool looped, s16 prio, s32 areaId); - static CSfxHandle AddEmitter(u16 id, const zeus::CVector3f& pos, const zeus::CVector3f& dir, float vol, - bool useAcoustics, bool looped, s16 prio, s32 areaId); - static CSfxHandle AddEmitter(const CAudioSys::C3DEmitterParmData& parmData, - bool useAcoustics, s16 prio, bool looped, s32 areaId); - static void StopAndRemoveAllEmitters(); - static void DisableAuxCallback(); - static void EnableAuxCallback(); - static void PrepareDelayCallback(const amuse::EffectDelayInfo& info); - static void PrepareReverbStdCallback(const amuse::EffectReverbStdInfo& info); - static void PrepareChorusCallback(const amuse::EffectChorusInfo& info); - static void PrepareReverbHiCallback(const amuse::EffectReverbHiInfo& info); - static void DisableAuxProcessing(); + static CSfxChannel m_channels[4]; + static ESfxChannels m_currentChannel; + static bool m_doUpdate; + static void* m_usedSounds; + static bool m_muted; + static bool m_auxProcessingEnabled; + static float m_reverbAmount; + static EAuxEffect m_activeEffect; + static EAuxEffect m_nextEffect; + static amuse::ObjToken m_listener; - static void SetActiveAreas(const rstl::reserved_vector& areas); + static u16 kMaxPriority; + static u16 kMedPriority; + static u16 kInternalInvalidSfxId; + static u32 kAllAreas; - static void Update(float dt); - static void Shutdown(); + static bool LoadTranslationTable(CSimplePool* pool, const SObjectTag* tag); + static bool IsAuxProcessingEnabled() { return m_auxProcessingEnabled; } + static void SetChannel(ESfxChannels); + static void KillAll(ESfxChannels); + static void TurnOnChannel(ESfxChannels); + static void TurnOffChannel(ESfxChannels); + static ESfxChannels GetCurrentChannel() { return m_currentChannel; } + static void AddListener(ESfxChannels channel, const zeus::CVector3f& pos, const zeus::CVector3f& dir, + const zeus::CVector3f& heading, const zeus::CVector3f& up, float frontRadius, + float surroundRadius, float soundSpeed, u32 flags /* 0x1 for doppler */, float vol); + static void UpdateListener(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CVector3f& heading, + const zeus::CVector3f& up, float vol); + + static bool PlaySound(const CSfxHandle& handle); + static void StopSound(const CSfxHandle& handle); + static s16 GetRank(CBaseSfxWrapper* sfx); + static void ApplyReverb(); + static float GetReverbAmount(); + static void PitchBend(const CSfxHandle& handle, float pitch); + static void SfxVolume(const CSfxHandle& handle, float vol); + static void SfxSpan(const CSfxHandle& handle, float span); + static u16 TranslateSFXID(u16); + static void SfxStop(const CSfxHandle& handle); + static CSfxHandle SfxStart(u16 id, float vol, float pan, bool useAcoustics, s16 prio, bool looped, s32 areaId); + static bool IsPlaying(const CSfxHandle& handle); + static void RemoveEmitter(const CSfxHandle& handle); + static void UpdateEmitter(const CSfxHandle& handle, const zeus::CVector3f& pos, const zeus::CVector3f& dir, + float maxVol); + static CSfxHandle AddEmitter(u16 id, const zeus::CVector3f& pos, const zeus::CVector3f& dir, bool useAcoustics, + bool looped, s16 prio, s32 areaId); + static CSfxHandle AddEmitter(u16 id, const zeus::CVector3f& pos, const zeus::CVector3f& dir, float vol, + bool useAcoustics, bool looped, s16 prio, s32 areaId); + static CSfxHandle AddEmitter(const CAudioSys::C3DEmitterParmData& parmData, bool useAcoustics, s16 prio, bool looped, + s32 areaId); + static void StopAndRemoveAllEmitters(); + static void DisableAuxCallback(); + static void EnableAuxCallback(); + static void PrepareDelayCallback(const amuse::EffectDelayInfo& info); + static void PrepareReverbStdCallback(const amuse::EffectReverbStdInfo& info); + static void PrepareChorusCallback(const amuse::EffectChorusInfo& info); + static void PrepareReverbHiCallback(const amuse::EffectReverbHiInfo& info); + static void DisableAuxProcessing(); + + static void SetActiveAreas(const rstl::reserved_vector& areas); + + static void Update(float dt); + static void Shutdown(); }; using CSfxHandle = CSfxManager::CSfxHandle; -} - +} // namespace urde diff --git a/Runtime/Audio/CStaticAudioPlayer.cpp b/Runtime/Audio/CStaticAudioPlayer.cpp index 3b015c56c..61bb440b8 100644 --- a/Runtime/Audio/CStaticAudioPlayer.cpp +++ b/Runtime/Audio/CStaticAudioPlayer.cpp @@ -2,110 +2,100 @@ #include "CDvdFile.hpp" #include "CDvdRequest.hpp" -namespace urde -{ +namespace urde { #define RSF_BUFFER_SIZE 0x20000 -CStaticAudioPlayer::CStaticAudioPlayer(boo::IAudioVoiceEngine& engine, std::string_view path, - int loopStart, int loopEnd) -: x0_path(path), x1c_loopStartSamp(loopStart & 0xfffffffe), x20_loopEndSamp(loopEnd & 0xfffffffe), - m_voiceCallback(*this), m_voice(engine.allocateNewStereoVoice(32000, &m_voiceCallback)) -{ - // These are mixed directly into boo voice engine instead - //x28_dmaLeft.reset(new u8[640]); - //x30_dmaRight.reset(new u8[640]); +CStaticAudioPlayer::CStaticAudioPlayer(boo::IAudioVoiceEngine& engine, std::string_view path, int loopStart, + int loopEnd) +: x0_path(path) +, x1c_loopStartSamp(loopStart & 0xfffffffe) +, x20_loopEndSamp(loopEnd & 0xfffffffe) +, m_voiceCallback(*this) +, m_voice(engine.allocateNewStereoVoice(32000, &m_voiceCallback)) { + // These are mixed directly into boo voice engine instead + // x28_dmaLeft.reset(new u8[640]); + // x30_dmaRight.reset(new u8[640]); - CDvdFile file(path); - x10_rsfRem = file.Length(); - x14_rsfLength = x10_rsfRem; + CDvdFile file(path); + x10_rsfRem = file.Length(); + x14_rsfLength = x10_rsfRem; - u32 bufCount = (x10_rsfRem + RSF_BUFFER_SIZE - 1) / RSF_BUFFER_SIZE; - x48_buffers.reserve(bufCount); - x38_dvdRequests.reserve(bufCount); + u32 bufCount = (x10_rsfRem + RSF_BUFFER_SIZE - 1) / RSF_BUFFER_SIZE; + x48_buffers.reserve(bufCount); + x38_dvdRequests.reserve(bufCount); - for (int remBytes = x10_rsfRem; remBytes > 0; remBytes -= RSF_BUFFER_SIZE) - { - u32 thisSz = RSF_BUFFER_SIZE; - if (remBytes < RSF_BUFFER_SIZE) - thisSz = ROUND_UP_32(remBytes); + for (int remBytes = x10_rsfRem; remBytes > 0; remBytes -= RSF_BUFFER_SIZE) { + u32 thisSz = RSF_BUFFER_SIZE; + if (remBytes < RSF_BUFFER_SIZE) + thisSz = ROUND_UP_32(remBytes); - x48_buffers.emplace_back(new u8[thisSz]); - x38_dvdRequests.push_back(file.AsyncRead(x48_buffers.back().get(), thisSz)); - } + x48_buffers.emplace_back(new u8[thisSz]); + x38_dvdRequests.push_back(file.AsyncRead(x48_buffers.back().get(), thisSz)); + } - g72x_init_state(&x58_leftState); - g72x_init_state(&x8c_rightState); + g72x_init_state(&x58_leftState); + g72x_init_state(&x8c_rightState); } -bool CStaticAudioPlayer::IsReady() -{ - if (x38_dvdRequests.size()) - return x38_dvdRequests.back()->IsComplete(); - return true; +bool CStaticAudioPlayer::IsReady() { + if (x38_dvdRequests.size()) + return x38_dvdRequests.back()->IsComplete(); + return true; } -void CStaticAudioPlayer::DecodeMonoAndMix(s16* bufOut, u32 numSamples, - u32 cur, u32 loopEndCur, u32 loopStartCur, +void CStaticAudioPlayer::DecodeMonoAndMix(s16* bufOut, u32 numSamples, u32 cur, u32 loopEndCur, u32 loopStartCur, int vol, g72x_state& state, - std::experimental::optional& loopState) const -{ - for (u32 remBytes = numSamples / 2; remBytes;) - { - u32 curBuf = cur / RSF_BUFFER_SIZE; - u32 thisBytes = (curBuf + 1) * RSF_BUFFER_SIZE - cur; - thisBytes = std::min(thisBytes, remBytes); - u32 remTillLoop = loopEndCur - cur; - remTillLoop = std::min(remTillLoop, thisBytes); + std::experimental::optional& loopState) const { + for (u32 remBytes = numSamples / 2; remBytes;) { + u32 curBuf = cur / RSF_BUFFER_SIZE; + u32 thisBytes = (curBuf + 1) * RSF_BUFFER_SIZE - cur; + thisBytes = std::min(thisBytes, remBytes); + u32 remTillLoop = loopEndCur - cur; + remTillLoop = std::min(remTillLoop, thisBytes); - const std::unique_ptr& buf = x48_buffers[curBuf]; - const u8* byte = &buf[cur - curBuf * RSF_BUFFER_SIZE]; + const std::unique_ptr& buf = x48_buffers[curBuf]; + const u8* byte = &buf[cur - curBuf * RSF_BUFFER_SIZE]; - for (u32 i=0; i> 15)); - bufOut += 2; + *bufOut = SampClamp(((g721_decoder(*byte & 0xf, &state) * vol) >> 15)); + bufOut += 2; - *bufOut = SampClamp(((g721_decoder(*byte >> 4 & 0xf, &state) * vol) >> 15)); - bufOut += 2; - } - - cur += remTillLoop; - remBytes -= remTillLoop; - if (cur == loopEndCur) - { - cur = loopStartCur; - if (loopState) - state = *loopState; - } + *bufOut = SampClamp(((g721_decoder(*byte >> 4 & 0xf, &state) * vol) >> 15)); + bufOut += 2; } -} -void CStaticAudioPlayer::Decode(s16* bufOut, u32 numSamples) -{ - DecodeMonoAndMix(bufOut, numSamples, x18_curSamp / 2, - x20_loopEndSamp / 2, x1c_loopStartSamp / 2, - xc0_volume, x58_leftState, m_leftStateLoop); - - u32 halfway = x14_rsfLength / 2; - DecodeMonoAndMix(bufOut + 1, numSamples, x18_curSamp / 2 + halfway, - x20_loopEndSamp / 2 + halfway, x1c_loopStartSamp / 2 + halfway, - xc0_volume, x8c_rightState, m_rightStateLoop); - - for (u32 remSamples = numSamples; remSamples;) - { - u32 remTillLoop = x20_loopEndSamp - x18_curSamp; - remTillLoop = std::min(remTillLoop, remSamples); - - x18_curSamp += remTillLoop; - remSamples -= remTillLoop; - - if (x18_curSamp == x20_loopEndSamp) - x18_curSamp = x1c_loopStartSamp; + cur += remTillLoop; + remBytes -= remTillLoop; + if (cur == loopEndCur) { + cur = loopStartCur; + if (loopState) + state = *loopState; } + } } +void CStaticAudioPlayer::Decode(s16* bufOut, u32 numSamples) { + DecodeMonoAndMix(bufOut, numSamples, x18_curSamp / 2, x20_loopEndSamp / 2, x1c_loopStartSamp / 2, xc0_volume, + x58_leftState, m_leftStateLoop); + + u32 halfway = x14_rsfLength / 2; + DecodeMonoAndMix(bufOut + 1, numSamples, x18_curSamp / 2 + halfway, x20_loopEndSamp / 2 + halfway, + x1c_loopStartSamp / 2 + halfway, xc0_volume, x8c_rightState, m_rightStateLoop); + + for (u32 remSamples = numSamples; remSamples;) { + u32 remTillLoop = x20_loopEndSamp - x18_curSamp; + remTillLoop = std::min(remTillLoop, remSamples); + + x18_curSamp += remTillLoop; + remSamples -= remTillLoop; + + if (x18_curSamp == x20_loopEndSamp) + x18_curSamp = x1c_loopStartSamp; + } } + +} // namespace urde diff --git a/Runtime/Audio/CStaticAudioPlayer.hpp b/Runtime/Audio/CStaticAudioPlayer.hpp index f3f878789..078d598e5 100644 --- a/Runtime/Audio/CStaticAudioPlayer.hpp +++ b/Runtime/Audio/CStaticAudioPlayer.hpp @@ -6,82 +6,63 @@ #include "boo/audiodev/IAudioVoice.hpp" #include "boo/audiodev/IAudioVoiceEngine.hpp" -namespace urde -{ +namespace urde { class IDvdRequest; -class CStaticAudioPlayer -{ - std::string x0_path; - u32 x10_rsfRem = -1; - u32 x14_rsfLength; - u32 x18_curSamp = 0; - u32 x1c_loopStartSamp; - u32 x20_loopEndSamp; - //u32 x24_ = 0; - //std::unique_ptr x28_dmaLeft; - //std::unique_ptr x30_dmaRight; - std::vector> x38_dvdRequests; - std::vector> x48_buffers; - g72x_state x58_leftState; - g72x_state x8c_rightState; - std::experimental::optional m_leftStateLoop; - std::experimental::optional m_rightStateLoop; - u32 xc0_volume = 32768; // Out of 32768 +class CStaticAudioPlayer { + std::string x0_path; + u32 x10_rsfRem = -1; + u32 x14_rsfLength; + u32 x18_curSamp = 0; + u32 x1c_loopStartSamp; + u32 x20_loopEndSamp; + // u32 x24_ = 0; + // std::unique_ptr x28_dmaLeft; + // std::unique_ptr x30_dmaRight; + std::vector> x38_dvdRequests; + std::vector> x48_buffers; + g72x_state x58_leftState; + g72x_state x8c_rightState; + std::experimental::optional m_leftStateLoop; + std::experimental::optional m_rightStateLoop; + u32 xc0_volume = 32768; // Out of 32768 - static int16_t SampClamp(int32_t val) - { - if (val < -32768) val = -32768; - else if (val > 32767) val = 32767; - return val; + static int16_t SampClamp(int32_t val) { + if (val < -32768) + val = -32768; + else if (val > 32767) + val = 32767; + return val; + } + + struct AudioVoiceCallback : boo::IAudioVoiceCallback { + CStaticAudioPlayer& m_parent; + void preSupplyAudio(boo::IAudioVoice&, double) {} + size_t supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data) { + if (m_parent.IsReady()) { + m_parent.x38_dvdRequests.clear(); + m_parent.Decode(data, frames); + } else + memset(data, 0, 4 * frames); + return frames; } - - struct AudioVoiceCallback : boo::IAudioVoiceCallback - { - CStaticAudioPlayer& m_parent; - void preSupplyAudio(boo::IAudioVoice&, double) {} - size_t supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t* data) - { - if (m_parent.IsReady()) - { - m_parent.x38_dvdRequests.clear(); - m_parent.Decode(data, frames); - } - else - memset(data, 0, 4 * frames); - return frames; - } - AudioVoiceCallback(CStaticAudioPlayer& p) : m_parent(p) {} - } m_voiceCallback; - boo::ObjToken m_voice; + AudioVoiceCallback(CStaticAudioPlayer& p) : m_parent(p) {} + } m_voiceCallback; + boo::ObjToken m_voice; public: - CStaticAudioPlayer(boo::IAudioVoiceEngine& engine, std::string_view path, - int loopStart, int loopEnd); - CStaticAudioPlayer(std::string_view path, - int loopStart, int loopEnd) - : CStaticAudioPlayer(*CAudioSys::GetVoiceEngine(), path, loopStart, loopEnd) {} + CStaticAudioPlayer(boo::IAudioVoiceEngine& engine, std::string_view path, int loopStart, int loopEnd); + CStaticAudioPlayer(std::string_view path, int loopStart, int loopEnd) + : CStaticAudioPlayer(*CAudioSys::GetVoiceEngine(), path, loopStart, loopEnd) {} - bool IsReady(); - void DecodeMonoAndMix(s16* bufOut, u32 numSamples, - u32 cur, u32 loopEndCur, u32 loopStartCur, - int vol, g72x_state& state, - std::experimental::optional& loopState) const; - void Decode(s16* bufOut, u32 numSamples); - void SetVolume(float vol) - { - xc0_volume = zeus::clamp(0.f, vol, 1.f) * 32768.f; - } + bool IsReady(); + void DecodeMonoAndMix(s16* bufOut, u32 numSamples, u32 cur, u32 loopEndCur, u32 loopStartCur, int vol, + g72x_state& state, std::experimental::optional& loopState) const; + void Decode(s16* bufOut, u32 numSamples); + void SetVolume(float vol) { xc0_volume = zeus::clamp(0.f, vol, 1.f) * 32768.f; } - void StartMixing() - { - m_voice->start(); - } - void StopMixing() - { - m_voice->stop(); - } + void StartMixing() { m_voice->start(); } + void StopMixing() { m_voice->stop(); } }; -} - +} // namespace urde diff --git a/Runtime/Audio/CStreamAudioManager.cpp b/Runtime/Audio/CStreamAudioManager.cpp index a54a8065b..eb43feaad 100644 --- a/Runtime/Audio/CStreamAudioManager.cpp +++ b/Runtime/Audio/CStreamAudioManager.cpp @@ -6,1241 +6,1031 @@ #include "amuse/DSPCodec.hpp" #include -namespace urde -{ +namespace urde { class CDSPStreamManager; static u32 s_HandleCounter = 0; static u32 s_HandleCounter2 = 0; /* Standard DSPADPCM header */ -struct dspadpcm_header -{ - u32 x0_num_samples; - u32 x4_num_nibbles; - u32 x8_sample_rate; - u16 xc_loop_flag; - u16 xe_format; /* 0 for ADPCM */ - u32 x10_loop_start_nibble; - u32 x14_loop_end_nibble; - u32 x18_ca; - s16 x1c_coef[8][2]; - s16 x3c_gain; - s16 x3e_ps; - s16 x40_hist1; - s16 x42_hist2; - s16 x44_loop_ps; - s16 x46_loop_hist1; - s16 x48_loop_hist2; - u16 x4a_pad[11]; +struct dspadpcm_header { + u32 x0_num_samples; + u32 x4_num_nibbles; + u32 x8_sample_rate; + u16 xc_loop_flag; + u16 xe_format; /* 0 for ADPCM */ + u32 x10_loop_start_nibble; + u32 x14_loop_end_nibble; + u32 x18_ca; + s16 x1c_coef[8][2]; + s16 x3c_gain; + s16 x3e_ps; + s16 x40_hist1; + s16 x42_hist2; + s16 x44_loop_ps; + s16 x46_loop_hist1; + s16 x48_loop_hist2; + u16 x4a_pad[11]; }; -struct SDSPStreamInfo -{ - const char* x0_fileName; - u32 x4_sampleRate; - u32 x8_headerSize = sizeof(dspadpcm_header); - u32 xc_adpcmBytes; - bool x10_loopFlag; - u32 x14_loopStartByte; - u32 x18_loopEndByte; - s16 x1c_coef[8][2]; +struct SDSPStreamInfo { + const char* x0_fileName; + u32 x4_sampleRate; + u32 x8_headerSize = sizeof(dspadpcm_header); + u32 xc_adpcmBytes; + bool x10_loopFlag; + u32 x14_loopStartByte; + u32 x18_loopEndByte; + s16 x1c_coef[8][2]; - SDSPStreamInfo() = default; - SDSPStreamInfo(const CDSPStreamManager& stream); + SDSPStreamInfo() = default; + SDSPStreamInfo(const CDSPStreamManager& stream); }; -struct SDSPStream : boo::IAudioVoiceCallback -{ - bool x0_active; - bool x1_oneshot; - s32 x4_ownerId; - SDSPStream* x8_stereoLeft; - SDSPStream* xc_companionRight; - SDSPStreamInfo x10_info; - float x4c_vol; - float m_leftgain, m_rightgain; - //DVDFileInfo x50_dvdHandle1; - //DVDFileInfo x8c_dvdHandle2; - //u32 xc8_streamId = -1; // MusyX stream handle - u32 xcc_fileCur = 0; - std::unique_ptr xd4_ringBuffer; - u32 xd8_ringBytes = 0x11DC0; // 73152 4sec in ADPCM bytes - u32 xdc_ringSamples = 0x1f410; // 128016 4sec in samples - s8 xe0_curBuffer = -1; - bool xe8_silent = true; - u8 xec_readState = 0; // 0: NoRead 1: Read 2: ReadWrap +struct SDSPStream : boo::IAudioVoiceCallback { + bool x0_active; + bool x1_oneshot; + s32 x4_ownerId; + SDSPStream* x8_stereoLeft; + SDSPStream* xc_companionRight; + SDSPStreamInfo x10_info; + float x4c_vol; + float m_leftgain, m_rightgain; + // DVDFileInfo x50_dvdHandle1; + // DVDFileInfo x8c_dvdHandle2; + // u32 xc8_streamId = -1; // MusyX stream handle + u32 xcc_fileCur = 0; + std::unique_ptr xd4_ringBuffer; + u32 xd8_ringBytes = 0x11DC0; // 73152 4sec in ADPCM bytes + u32 xdc_ringSamples = 0x1f410; // 128016 4sec in samples + s8 xe0_curBuffer = -1; + bool xe8_silent = true; + u8 xec_readState = 0; // 0: NoRead 1: Read 2: ReadWrap - std::experimental::optional m_file; - std::shared_ptr m_readReqs[2]; + std::experimental::optional m_file; + std::shared_ptr m_readReqs[2]; - void ReadBuffer(int buf) - { - u32 halfSize = xd8_ringBytes / 2; - u8* data = xd4_ringBuffer.get() + (buf ? halfSize : 0); + void ReadBuffer(int buf) { + u32 halfSize = xd8_ringBytes / 2; + u8* data = xd4_ringBuffer.get() + (buf ? halfSize : 0); - if (x10_info.x10_loopFlag) - { - u32 remFileBytes = x10_info.x18_loopEndByte - xcc_fileCur; + if (x10_info.x10_loopFlag) { + u32 remFileBytes = x10_info.x18_loopEndByte - xcc_fileCur; - if (remFileBytes < halfSize) - { - //printf("Buffering %d from %d into %d\n", remFileBytes, xcc_fileCur + x10_info.x8_headerSize, buf); - m_file->AsyncSeekRead(data, remFileBytes, - ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); - xcc_fileCur = x10_info.x14_loopStartByte; - u32 remBytes = halfSize - remFileBytes; - //printf("Loop Buffering %d from %d into %d\n", remBytes, xcc_fileCur + x10_info.x8_headerSize, buf); - m_readReqs[buf] = m_file->AsyncSeekRead(data + remFileBytes, remBytes, - ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); - xcc_fileCur += remBytes; - } - else - { - //printf("Buffering %d from %d into %d\n", halfSize, xcc_fileCur + x10_info.x8_headerSize, buf); - m_readReqs[buf] = m_file->AsyncSeekRead(data, halfSize, - ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); - xcc_fileCur += halfSize; - } - } - else - { - if (xcc_fileCur == x10_info.xc_adpcmBytes) - { - memset(data, 0, halfSize); - return; - } + if (remFileBytes < halfSize) { + // printf("Buffering %d from %d into %d\n", remFileBytes, xcc_fileCur + x10_info.x8_headerSize, buf); + m_file->AsyncSeekRead(data, remFileBytes, ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); + xcc_fileCur = x10_info.x14_loopStartByte; + u32 remBytes = halfSize - remFileBytes; + // printf("Loop Buffering %d from %d into %d\n", remBytes, xcc_fileCur + x10_info.x8_headerSize, buf); + m_readReqs[buf] = m_file->AsyncSeekRead(data + remFileBytes, remBytes, ESeekOrigin::Begin, + xcc_fileCur + x10_info.x8_headerSize); + xcc_fileCur += remBytes; + } else { + // printf("Buffering %d from %d into %d\n", halfSize, xcc_fileCur + x10_info.x8_headerSize, buf); + m_readReqs[buf] = + m_file->AsyncSeekRead(data, halfSize, ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); + xcc_fileCur += halfSize; + } + } else { + if (xcc_fileCur == x10_info.xc_adpcmBytes) { + memset(data, 0, halfSize); + return; + } - u32 remFileBytes = x10_info.xc_adpcmBytes - xcc_fileCur; + u32 remFileBytes = x10_info.xc_adpcmBytes - xcc_fileCur; - if (remFileBytes < halfSize) - { - //printf("Buffering %d from %d into %d\n", remFileBytes, xcc_fileCur + x10_info.x8_headerSize, buf); - m_readReqs[buf] = m_file->AsyncSeekRead(data, remFileBytes, - ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); - memset(data + remFileBytes, 0, halfSize - remFileBytes); - xcc_fileCur = x10_info.xc_adpcmBytes; - } - else - { - //printf("Buffering %d from %d into %d\n", halfSize, xcc_fileCur + x10_info.x8_headerSize, buf); - m_readReqs[buf] = m_file->AsyncSeekRead(data, halfSize, - ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); - xcc_fileCur += halfSize; - } - } + if (remFileBytes < halfSize) { + // printf("Buffering %d from %d into %d\n", remFileBytes, xcc_fileCur + x10_info.x8_headerSize, buf); + m_readReqs[buf] = + m_file->AsyncSeekRead(data, remFileBytes, ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); + memset(data + remFileBytes, 0, halfSize - remFileBytes); + xcc_fileCur = x10_info.xc_adpcmBytes; + } else { + // printf("Buffering %d from %d into %d\n", halfSize, xcc_fileCur + x10_info.x8_headerSize, buf); + m_readReqs[buf] = + m_file->AsyncSeekRead(data, halfSize, ESeekOrigin::Begin, xcc_fileCur + x10_info.x8_headerSize); + xcc_fileCur += halfSize; + } } + } - bool BufferStream() - { - if (xec_readState == 0) - { - ReadBuffer(0); - ReadBuffer(1); - xec_readState = 1; - return false; - } - else if (xec_readState == 1) - { - if (m_readReqs[0]->IsComplete()) - { - xe0_curBuffer = 0; - xec_readState = 2; - return true; - } - else - { - return false; - } - } - else if (xec_readState == 2) - { - if (xe0_curBuffer == 1 && m_readReqs[0]->IsComplete()) - { - xe0_curBuffer = 0; - ReadBuffer(1); - return true; - } - else if (xe0_curBuffer == 0 && m_readReqs[1]->IsComplete()) - { - xe0_curBuffer = 1; - ReadBuffer(0); - return true; - } - } + bool BufferStream() { + if (xec_readState == 0) { + ReadBuffer(0); + ReadBuffer(1); + xec_readState = 1; + return false; + } else if (xec_readState == 1) { + if (m_readReqs[0]->IsComplete()) { + xe0_curBuffer = 0; + xec_readState = 2; + return true; + } else { return false; + } + } else if (xec_readState == 2) { + if (xe0_curBuffer == 1 && m_readReqs[0]->IsComplete()) { + xe0_curBuffer = 0; + ReadBuffer(1); + return true; + } else if (xe0_curBuffer == 0 && m_readReqs[1]->IsComplete()) { + xe0_curBuffer = 1; + ReadBuffer(0); + return true; + } + } + return false; + } + + unsigned m_curSample = 0; + unsigned m_totalSamples = 0; + s16 m_prev1 = 0; + s16 m_prev2 = 0; + + void preSupplyAudio(boo::IAudioVoice&, double) {} + + unsigned decompressChunk(unsigned readToSample, int16_t*& data) { + unsigned startSamp = m_curSample; + + auto sampDiv = std::div(int(m_curSample), int(14)); + if (sampDiv.rem) { + unsigned samps = DSPDecompressFrameRanged(data, xd4_ringBuffer.get() + sampDiv.quot * 8, x10_info.x1c_coef, + &m_prev1, &m_prev2, unsigned(sampDiv.rem), readToSample - m_curSample); + m_curSample += samps; + data += samps; + ++sampDiv.quot; } - unsigned m_curSample = 0; - unsigned m_totalSamples = 0; - s16 m_prev1 = 0; - s16 m_prev2 = 0; + while (m_curSample < readToSample) { + unsigned samps = DSPDecompressFrame(data, xd4_ringBuffer.get() + sampDiv.quot * 8, x10_info.x1c_coef, &m_prev1, + &m_prev2, readToSample - m_curSample); + m_curSample += samps; + data += samps; + ++sampDiv.quot; + } - void preSupplyAudio(boo::IAudioVoice&, double) {} + return m_curSample - startSamp; + } - unsigned decompressChunk(unsigned readToSample, int16_t*& data) - { - unsigned startSamp = m_curSample; + size_t supplyAudio(boo::IAudioVoice&, size_t frames, int16_t* data) { + if (!x0_active) { + memset(data, 0, frames * 2); + return frames; + } - auto sampDiv = std::div(int(m_curSample), int(14)); - if (sampDiv.rem) - { - unsigned samps = DSPDecompressFrameRanged(data, xd4_ringBuffer.get() + sampDiv.quot * 8, - x10_info.x1c_coef, &m_prev1, &m_prev2, unsigned(sampDiv.rem), - readToSample - m_curSample); - m_curSample += samps; - data += samps; - ++sampDiv.quot; + if (xe8_silent) { + StopStream(); + memset(data, 0, frames * 2); + return frames; + } + + unsigned halfRingSamples = xdc_ringSamples / 2; + + size_t remFrames = frames; + while (remFrames) { + if (xec_readState != 2 || (xe0_curBuffer == 0 && m_curSample >= halfRingSamples)) { + if (!BufferStream()) { + memset(data, 0, remFrames * 2); + return frames; } + } - while (m_curSample < readToSample) - { - unsigned samps = DSPDecompressFrame(data, xd4_ringBuffer.get() + sampDiv.quot * 8, - x10_info.x1c_coef, &m_prev1, &m_prev2, - readToSample - m_curSample); - m_curSample += samps; - data += samps; - ++sampDiv.quot; + unsigned readToSample = + std::min(m_curSample + unsigned(remFrames), (m_curSample / halfRingSamples + 1) * halfRingSamples); + + if (!x10_info.x10_loopFlag) { + m_totalSamples += remFrames; + size_t fileSamples = x10_info.xc_adpcmBytes * 14 / 8; + if (m_totalSamples >= fileSamples) { + size_t leftover = m_totalSamples - fileSamples; + readToSample -= leftover; + remFrames -= leftover; + memset(data + remFrames, 0, leftover * 2); + StopStream(); } + } - return m_curSample - startSamp; - } + unsigned leftoverSamples = 0; + if (readToSample > xdc_ringSamples) { + leftoverSamples = readToSample - xdc_ringSamples; + readToSample = xdc_ringSamples; + } - size_t supplyAudio(boo::IAudioVoice&, size_t frames, int16_t* data) - { - if (!x0_active) - { - memset(data, 0, frames * 2); - return frames; - } + remFrames -= decompressChunk(readToSample, data); - if (xe8_silent) - { - StopStream(); - memset(data, 0, frames * 2); - return frames; - } - - unsigned halfRingSamples = xdc_ringSamples / 2; - - size_t remFrames = frames; - while (remFrames) - { - if (xec_readState != 2 || (xe0_curBuffer == 0 && m_curSample >= halfRingSamples)) - { - if (!BufferStream()) - { - memset(data, 0, remFrames * 2); - return frames; - } - } - - unsigned readToSample = std::min(m_curSample + unsigned(remFrames), - (m_curSample / halfRingSamples + 1) * halfRingSamples); - - if (!x10_info.x10_loopFlag) - { - m_totalSamples += remFrames; - size_t fileSamples = x10_info.xc_adpcmBytes * 14 / 8; - if (m_totalSamples >= fileSamples) - { - size_t leftover = m_totalSamples - fileSamples; - readToSample -= leftover; - remFrames -= leftover; - memset(data + remFrames, 0, leftover * 2); - StopStream(); - } - } - - unsigned leftoverSamples = 0; - if (readToSample > xdc_ringSamples) - { - leftoverSamples = readToSample - xdc_ringSamples; - readToSample = xdc_ringSamples; - } - - remFrames -= decompressChunk(readToSample, data); - - if (leftoverSamples) - { - BufferStream(); - m_curSample = 0; - remFrames -= decompressChunk(leftoverSamples, data); - } - } - - return frames; - } - boo::ObjToken m_booVoice; - - void DoAllocateStream() - { - xd4_ringBuffer.reset(new u8[0x11DC0]); - m_booVoice = CAudioSys::GetVoiceEngine()->allocateNewMonoVoice(32000.0, this); - } - - static void Initialize() - { - for (int i=0 ; i<4 ; ++i) - { - SDSPStream& stream = g_Streams[i]; - stream.x0_active = false; - stream.xd4_ringBuffer.reset(); - stream.xd8_ringBytes = 0x11DC0; - stream.xdc_ringSamples = 0x1f410; - if (i < 2) - { - stream.x1_oneshot = false; - stream.DoAllocateStream(); - } - else - { - stream.x1_oneshot = true; - } - } - } - - static void FreeAllStreams() - { - for (int i=0 ; i<4 ; ++i) - { - SDSPStream& stream = g_Streams[i]; - stream.m_booVoice.reset(); - stream.x0_active = false; - for (int j=0 ; j<2 ; ++j) - if (stream.m_readReqs[j]) - { - stream.m_readReqs[j]->PostCancelRequest(); - stream.m_readReqs[j].reset(); - } - stream.xd4_ringBuffer.reset(); - stream.m_file = std::experimental::nullopt; - } - } - - static s32 PickFreeStream(SDSPStream*& streamOut, bool oneshot) - { - for (int i=0 ; i<4 ; ++i) - { - SDSPStream& stream = g_Streams[i]; - if (stream.x0_active || stream.x1_oneshot != oneshot) - continue; - stream.x0_active = true; - stream.x4_ownerId = ++s_HandleCounter2; - if (stream.x4_ownerId == -1) - stream.x4_ownerId = ++s_HandleCounter2; - stream.x8_stereoLeft = nullptr; - stream.xc_companionRight = nullptr; - streamOut = &stream; - return stream.x4_ownerId; - } - return -1; - } - - static s32 FindStreamIdx(s32 id) - { - for (s32 i=0 ; i<4 ; ++i) - { - SDSPStream& stream = g_Streams[i]; - if (stream.x4_ownerId == id) - return i; - } - return -1; - } - - void UpdateStreamVolume(float vol) - { - x4c_vol = vol; - if (!x0_active || xe8_silent) - return; - float coefs[8] = {}; - coefs[int(boo::AudioChannel::FrontLeft)] = m_leftgain * vol; - coefs[int(boo::AudioChannel::FrontRight)] = m_rightgain * vol; - m_booVoice->setMonoChannelLevels(nullptr, coefs, true); - } - - static void UpdateVolume(s32 id, float vol) - { - s32 idx = FindStreamIdx(id); - if (idx == -1) - return; - - SDSPStream& stream = g_Streams[idx]; - stream.UpdateStreamVolume(vol); - if (SDSPStream* left = stream.x8_stereoLeft) - left->UpdateStreamVolume(vol); - if (SDSPStream* right = stream.xc_companionRight) - right->UpdateStreamVolume(vol); - } - - void SilenceStream() - { - if (!x0_active || xe8_silent) - return; - float coefs[8] = {}; - m_booVoice->setMonoChannelLevels(nullptr, coefs, true); - xe8_silent = true; - x0_active = false; - } - - static void Silence(s32 id) - { - s32 idx = FindStreamIdx(id); - if (idx == -1) - return; - - SDSPStream& stream = g_Streams[idx]; - stream.SilenceStream(); - if (SDSPStream* left = stream.x8_stereoLeft) - left->SilenceStream(); - if (SDSPStream* right = stream.xc_companionRight) - right->SilenceStream(); - } - - void StopStream() - { - x0_active = false; - m_booVoice->stop(); - m_file = std::experimental::nullopt; - } - - static bool IsStreamActive(s32 id) - { - s32 idx = FindStreamIdx(id); - if (idx == -1) - return false; - - SDSPStream& stream = g_Streams[idx]; - return stream.x0_active; - } - - static bool IsStreamAvailable(s32 id) - { - s32 idx = FindStreamIdx(id); - if (idx == -1) - return false; - - SDSPStream& stream = g_Streams[idx]; - return !stream.x0_active; - } - - static s32 AllocateMono(const SDSPStreamInfo& info, float vol, bool oneshot) - { - SDSPStream* stream; - s32 id = PickFreeStream(stream, oneshot); - if (id == -1) - return -1; - - /* -3dB pan law for mono */ - stream->AllocateStream(info, vol, 0.707f, 0.707f); - return id; - } - - static s32 AllocateStereo(const SDSPStreamInfo& linfo, - const SDSPStreamInfo& rinfo, - float vol, bool oneshot) - { - SDSPStream* lstream; - s32 lid = PickFreeStream(lstream, oneshot); - if (lid == -1) - return -1; - - SDSPStream* rstream; - if (PickFreeStream(rstream, oneshot) == -1) - return -1; - - rstream->x8_stereoLeft = lstream; - lstream->xc_companionRight = rstream; - - lstream->AllocateStream(linfo, vol, 1.f, 0.f); - rstream->AllocateStream(rinfo, vol, 0.f, 1.f); - return lid; - } - - void AllocateStream(const SDSPStreamInfo& info, float vol, float left, float right) - { - x10_info = info; - m_file.emplace(x10_info.x0_fileName); - if (!xd4_ringBuffer) - DoAllocateStream(); - for (int j=0 ; j<2 ; ++j) - if (m_readReqs[j]) - { - m_readReqs[j]->PostCancelRequest(); - m_readReqs[j].reset(); - } - x4c_vol = vol; - m_leftgain = left; - m_rightgain = right; - xe8_silent = false; - xec_readState = 0; - xe0_curBuffer = -1; - xd8_ringBytes = 0x11DC0; - xdc_ringSamples = 0x1f410; - xcc_fileCur = 0; + if (leftoverSamples) { + BufferStream(); m_curSample = 0; - m_totalSamples = 0; - m_prev1 = 0; - m_prev2 = 0; - memset(xd4_ringBuffer.get(), 0, 0x11DC0); - m_booVoice->resetSampleRate(info.x4_sampleRate); - m_booVoice->start(); - UpdateStreamVolume(vol); + remFrames -= decompressChunk(leftoverSamples, data); + } } - static SDSPStream g_Streams[4]; + return frames; + } + boo::ObjToken m_booVoice; + + void DoAllocateStream() { + xd4_ringBuffer.reset(new u8[0x11DC0]); + m_booVoice = CAudioSys::GetVoiceEngine()->allocateNewMonoVoice(32000.0, this); + } + + static void Initialize() { + for (int i = 0; i < 4; ++i) { + SDSPStream& stream = g_Streams[i]; + stream.x0_active = false; + stream.xd4_ringBuffer.reset(); + stream.xd8_ringBytes = 0x11DC0; + stream.xdc_ringSamples = 0x1f410; + if (i < 2) { + stream.x1_oneshot = false; + stream.DoAllocateStream(); + } else { + stream.x1_oneshot = true; + } + } + } + + static void FreeAllStreams() { + for (int i = 0; i < 4; ++i) { + SDSPStream& stream = g_Streams[i]; + stream.m_booVoice.reset(); + stream.x0_active = false; + for (int j = 0; j < 2; ++j) + if (stream.m_readReqs[j]) { + stream.m_readReqs[j]->PostCancelRequest(); + stream.m_readReqs[j].reset(); + } + stream.xd4_ringBuffer.reset(); + stream.m_file = std::experimental::nullopt; + } + } + + static s32 PickFreeStream(SDSPStream*& streamOut, bool oneshot) { + for (int i = 0; i < 4; ++i) { + SDSPStream& stream = g_Streams[i]; + if (stream.x0_active || stream.x1_oneshot != oneshot) + continue; + stream.x0_active = true; + stream.x4_ownerId = ++s_HandleCounter2; + if (stream.x4_ownerId == -1) + stream.x4_ownerId = ++s_HandleCounter2; + stream.x8_stereoLeft = nullptr; + stream.xc_companionRight = nullptr; + streamOut = &stream; + return stream.x4_ownerId; + } + return -1; + } + + static s32 FindStreamIdx(s32 id) { + for (s32 i = 0; i < 4; ++i) { + SDSPStream& stream = g_Streams[i]; + if (stream.x4_ownerId == id) + return i; + } + return -1; + } + + void UpdateStreamVolume(float vol) { + x4c_vol = vol; + if (!x0_active || xe8_silent) + return; + float coefs[8] = {}; + coefs[int(boo::AudioChannel::FrontLeft)] = m_leftgain * vol; + coefs[int(boo::AudioChannel::FrontRight)] = m_rightgain * vol; + m_booVoice->setMonoChannelLevels(nullptr, coefs, true); + } + + static void UpdateVolume(s32 id, float vol) { + s32 idx = FindStreamIdx(id); + if (idx == -1) + return; + + SDSPStream& stream = g_Streams[idx]; + stream.UpdateStreamVolume(vol); + if (SDSPStream* left = stream.x8_stereoLeft) + left->UpdateStreamVolume(vol); + if (SDSPStream* right = stream.xc_companionRight) + right->UpdateStreamVolume(vol); + } + + void SilenceStream() { + if (!x0_active || xe8_silent) + return; + float coefs[8] = {}; + m_booVoice->setMonoChannelLevels(nullptr, coefs, true); + xe8_silent = true; + x0_active = false; + } + + static void Silence(s32 id) { + s32 idx = FindStreamIdx(id); + if (idx == -1) + return; + + SDSPStream& stream = g_Streams[idx]; + stream.SilenceStream(); + if (SDSPStream* left = stream.x8_stereoLeft) + left->SilenceStream(); + if (SDSPStream* right = stream.xc_companionRight) + right->SilenceStream(); + } + + void StopStream() { + x0_active = false; + m_booVoice->stop(); + m_file = std::experimental::nullopt; + } + + static bool IsStreamActive(s32 id) { + s32 idx = FindStreamIdx(id); + if (idx == -1) + return false; + + SDSPStream& stream = g_Streams[idx]; + return stream.x0_active; + } + + static bool IsStreamAvailable(s32 id) { + s32 idx = FindStreamIdx(id); + if (idx == -1) + return false; + + SDSPStream& stream = g_Streams[idx]; + return !stream.x0_active; + } + + static s32 AllocateMono(const SDSPStreamInfo& info, float vol, bool oneshot) { + SDSPStream* stream; + s32 id = PickFreeStream(stream, oneshot); + if (id == -1) + return -1; + + /* -3dB pan law for mono */ + stream->AllocateStream(info, vol, 0.707f, 0.707f); + return id; + } + + static s32 AllocateStereo(const SDSPStreamInfo& linfo, const SDSPStreamInfo& rinfo, float vol, bool oneshot) { + SDSPStream* lstream; + s32 lid = PickFreeStream(lstream, oneshot); + if (lid == -1) + return -1; + + SDSPStream* rstream; + if (PickFreeStream(rstream, oneshot) == -1) + return -1; + + rstream->x8_stereoLeft = lstream; + lstream->xc_companionRight = rstream; + + lstream->AllocateStream(linfo, vol, 1.f, 0.f); + rstream->AllocateStream(rinfo, vol, 0.f, 1.f); + return lid; + } + + void AllocateStream(const SDSPStreamInfo& info, float vol, float left, float right) { + x10_info = info; + m_file.emplace(x10_info.x0_fileName); + if (!xd4_ringBuffer) + DoAllocateStream(); + for (int j = 0; j < 2; ++j) + if (m_readReqs[j]) { + m_readReqs[j]->PostCancelRequest(); + m_readReqs[j].reset(); + } + x4c_vol = vol; + m_leftgain = left; + m_rightgain = right; + xe8_silent = false; + xec_readState = 0; + xe0_curBuffer = -1; + xd8_ringBytes = 0x11DC0; + xdc_ringSamples = 0x1f410; + xcc_fileCur = 0; + m_curSample = 0; + m_totalSamples = 0; + m_prev1 = 0; + m_prev2 = 0; + memset(xd4_ringBuffer.get(), 0, 0x11DC0); + m_booVoice->resetSampleRate(info.x4_sampleRate); + m_booVoice->start(); + UpdateStreamVolume(vol); + } + + static SDSPStream g_Streams[4]; }; SDSPStream SDSPStream::g_Streams[4] = {}; -class CDSPStreamManager -{ - friend struct SDSPStreamInfo; +class CDSPStreamManager { + friend struct SDSPStreamInfo; + public: - enum class EState - { - Looping, - Oneshot, - Preparing - }; + enum class EState { Looping, Oneshot, Preparing }; private: - dspadpcm_header x0_header; - std::string x60_fileName; // arg1 - union - { - u32 dummy = 0; - struct - { - bool x70_24_unclaimed : 1; - bool x70_25_headerReadCancelled : 1; - u8 x70_26_headerReadState : 2; // 0: not read 1: reading 2: read - }; + dspadpcm_header x0_header; + std::string x60_fileName; // arg1 + union { + u32 dummy = 0; + struct { + bool x70_24_unclaimed : 1; + bool x70_25_headerReadCancelled : 1; + u8 x70_26_headerReadState : 2; // 0: not read 1: reading 2: read }; - s8 x71_companionRight = -1; - s8 x72_companionLeft = -1; - float x73_volume = 0.f; - bool x74_oneshot; - s32 x78_handleId = -1; // arg2 - s32 x7c_streamId = -1; - std::shared_ptr m_dvdReq; - //DVDFileInfo x80_dvdHandle; - static CDSPStreamManager g_Streams[4]; + }; + s8 x71_companionRight = -1; + s8 x72_companionLeft = -1; + float x73_volume = 0.f; + bool x74_oneshot; + s32 x78_handleId = -1; // arg2 + s32 x7c_streamId = -1; + std::shared_ptr m_dvdReq; + // DVDFileInfo x80_dvdHandle; + static CDSPStreamManager g_Streams[4]; public: - CDSPStreamManager() - { - x70_24_unclaimed = true; + CDSPStreamManager() { x70_24_unclaimed = true; } + + CDSPStreamManager(std::string_view fileName, s32 handle, float volume, bool oneshot) + : x60_fileName(fileName), x73_volume(volume), x74_oneshot(oneshot), x78_handleId(handle) { + if (!CDvdFile::FileExists(fileName)) + x70_24_unclaimed = true; + } + + static s32 FindUnclaimedStreamIdx() { + for (s32 i = 0; i < 4; ++i) { + CDSPStreamManager& stream = g_Streams[i]; + if (stream.x70_24_unclaimed) + return i; } + return -1; + } - CDSPStreamManager(std::string_view fileName, s32 handle, float volume, bool oneshot) - : x60_fileName(fileName), x73_volume(volume), x74_oneshot(oneshot), x78_handleId(handle) - { - if (!CDvdFile::FileExists(fileName)) - x70_24_unclaimed = true; - } + static bool FindUnclaimedStereoPair(s32& left, s32& right) { + s32 idx = FindUnclaimedStreamIdx(); - static s32 FindUnclaimedStreamIdx() - { - for (s32 i=0 ; i<4 ; ++i) - { - CDSPStreamManager& stream = g_Streams[i]; - if (stream.x70_24_unclaimed) - return i; - } - return -1; - } - - static bool FindUnclaimedStereoPair(s32& left, s32& right) - { - s32 idx = FindUnclaimedStreamIdx(); - - for (u32 i=0 ; i<4 ; ++i) - { - CDSPStreamManager& stream = g_Streams[i]; - if (stream.x70_24_unclaimed && idx != i) - { - left = idx; - right = i; - return true; - } - } - - return false; - } - - static s32 FindClaimedStreamIdx(s32 handle) - { - for (s32 i=0 ; i<4 ; ++i) - { - CDSPStreamManager& stream = g_Streams[i]; - if (!stream.x70_24_unclaimed && stream.x78_handleId == handle) - return i; - } - return -1; - } - - static s32 GetFreeHandleId() - { - s32 handle; - bool good; - do - { - good = true; - handle = ++s_HandleCounter; - if (handle == -1) - { - good = false; - continue; - } - - for (int i=0 ; i<4 ; ++i) - { - CDSPStreamManager& stream = g_Streams[i]; - if (!stream.x70_24_unclaimed && stream.x78_handleId == handle) - { - good = false; - break; - } - } - - } while(!good); - - return handle; - } - - static EState GetStreamState(s32 handle) - { - s32 idx = FindClaimedStreamIdx(handle); - if (idx == -1) - return EState::Oneshot; - - CDSPStreamManager& stream = g_Streams[idx]; - switch (stream.x70_26_headerReadState) - { - case 0: - return EState::Oneshot; - case 2: - return EState(!stream.x0_header.xc_loop_flag); - default: - return EState::Preparing; - } - } - - static bool CanStop(s32 handle) - { - s32 idx = FindClaimedStreamIdx(handle); - if (idx == -1) - return true; - - CDSPStreamManager& stream = g_Streams[idx]; - if (stream.x70_26_headerReadState == 1) - return false; - - if (stream.x7c_streamId == -1) - return true; - - return !SDSPStream::IsStreamActive(stream.x7c_streamId); - } - - static bool IsStreamAvailable(s32 handle) - { - s32 idx = FindClaimedStreamIdx(handle); - if (idx == -1) - return false; - - CDSPStreamManager& stream = g_Streams[idx]; - if (stream.x70_26_headerReadState == 1) - return false; - - if (stream.x7c_streamId == -1) - return false; - - return SDSPStream::IsStreamAvailable(stream.x7c_streamId); - } - - static void AllocateStream(s32 idx) - { - CDSPStreamManager& stream = g_Streams[idx]; - SDSPStreamInfo info(stream); - - if (stream.x71_companionRight == -1) - { - /* Mono */ - if (!stream.x70_25_headerReadCancelled) - stream.x7c_streamId = SDSPStream::AllocateMono(info, stream.x73_volume, stream.x74_oneshot); - if (stream.x7c_streamId == -1) - stream = CDSPStreamManager(); - } - else - { - /* Stereo */ - CDSPStreamManager& rstream = g_Streams[stream.x71_companionRight]; - SDSPStreamInfo rinfo(rstream); - - if (!stream.x70_25_headerReadCancelled) - stream.x7c_streamId = SDSPStream::AllocateStereo(info, rinfo, stream.x73_volume, stream.x74_oneshot); - if (stream.x7c_streamId == -1) - { - stream = CDSPStreamManager(); - rstream = CDSPStreamManager(); - } - } - } - - void HeaderReadComplete() - { - s32 selfIdx = -1; - for (int i=0 ; i<4 ; ++i) - { - if (this == &g_Streams[i]) - { - selfIdx = i; - break; - } - } - - if (x70_24_unclaimed || selfIdx == -1) - { - *this = CDSPStreamManager(); - return; - } - - x70_26_headerReadState = 2; - - s32 companion = -1; - if (x72_companionLeft != -1) - companion = x72_companionLeft; - else if (x71_companionRight != -1) - companion = x71_companionRight; - - if (companion != -1) - { - /* Stereo */ - CDSPStreamManager& companionStream = g_Streams[companion]; - if (companionStream.x70_24_unclaimed || - companionStream.x70_26_headerReadState == 0 || - (companionStream.x71_companionRight != selfIdx && - companionStream.x72_companionLeft != selfIdx)) - { - /* No consistent companion available */ - *this = CDSPStreamManager(); - return; - } - - /* Companion is pending; its completion will continue */ - if (companionStream.x70_26_headerReadState == 1) - return; - - /* Use whichever stream is the left channel */ - if (companionStream.x71_companionRight != -1) - AllocateStream(companion); - else - AllocateStream(selfIdx); - } - else - { - /* Mono */ - AllocateStream(selfIdx); - } - } - - static void PollHeaderReadCompletions() - { - for (int i=0 ; i<4 ; ++i) - { - CDSPStreamManager& stream = g_Streams[i]; - if (stream.m_dvdReq && stream.m_dvdReq->IsComplete()) - { - stream.m_dvdReq.reset(); - stream.HeaderReadComplete(); - } - } - } - - static bool StartMonoHeaderRead(CDSPStreamManager& stream) - { - if (stream.x70_26_headerReadState != 0 || stream.x70_24_unclaimed) - return false; - - CDvdFile file(stream.x60_fileName.c_str()); - if (!file) - return false; - - stream.x70_26_headerReadState = 1; - stream.m_dvdReq = file.AsyncRead(&stream.x0_header, sizeof(dspadpcm_header)); + for (u32 i = 0; i < 4; ++i) { + CDSPStreamManager& stream = g_Streams[i]; + if (stream.x70_24_unclaimed && idx != i) { + left = idx; + right = i; return true; + } } - static bool StartStereoHeaderRead(CDSPStreamManager& lstream, CDSPStreamManager& rstream) - { - if (lstream.x70_26_headerReadState != 0 || lstream.x70_24_unclaimed || - rstream.x70_26_headerReadState != 0 || rstream.x70_24_unclaimed) - return false; + return false; + } - CDvdFile lfile(lstream.x60_fileName.c_str()); - if (!lfile) - return false; - - CDvdFile rfile(rstream.x60_fileName.c_str()); - if (!rfile) - return false; - - lstream.x70_26_headerReadState = 1; - rstream.x70_26_headerReadState = 1; - - lstream.m_dvdReq = lfile.AsyncRead(&lstream.x0_header, sizeof(dspadpcm_header)); - rstream.m_dvdReq = rfile.AsyncRead(&rstream.x0_header, sizeof(dspadpcm_header)); - return true; + static s32 FindClaimedStreamIdx(s32 handle) { + for (s32 i = 0; i < 4; ++i) { + CDSPStreamManager& stream = g_Streams[i]; + if (!stream.x70_24_unclaimed && stream.x78_handleId == handle) + return i; } + return -1; + } - void WaitForReadCompletion() - { - if (std::shared_ptr req = m_dvdReq) - req->WaitUntilComplete(); - m_dvdReq.reset(); - } + static s32 GetFreeHandleId() { + s32 handle; + bool good; + do { + good = true; + handle = ++s_HandleCounter; + if (handle == -1) { + good = false; + continue; + } - static s32 StartStreaming(std::string_view fileName, float volume, bool oneshot) - { - auto pipePos = fileName.find('|'); - if (pipePos == std::string::npos) - { - /* Mono stream */ - s32 idx = FindUnclaimedStreamIdx(); - if (idx == -1) - return -1; - - s32 handle = GetFreeHandleId(); - CDSPStreamManager tmpStream(fileName, handle, volume, oneshot); - if (tmpStream.x70_24_unclaimed) - return -1; - - CDSPStreamManager& stream = g_Streams[idx]; - stream = tmpStream; - - if (!StartMonoHeaderRead(stream)) - { - stream.x70_25_headerReadCancelled = true; - stream.WaitForReadCompletion(); - stream = CDSPStreamManager(); - return -1; - } - - return handle; + for (int i = 0; i < 4; ++i) { + CDSPStreamManager& stream = g_Streams[i]; + if (!stream.x70_24_unclaimed && stream.x78_handleId == handle) { + good = false; + break; } - else - { - /* Stereo stream */ - s32 leftIdx = 0; - s32 rightIdx = 0; - if (!FindUnclaimedStereoPair(leftIdx, rightIdx)) - return -1; + } - std::string leftFile(fileName.begin(), fileName.begin() + pipePos); - std::string rightFile(fileName.begin() + pipePos + 1, fileName.end()); + } while (!good); - s32 leftHandle = GetFreeHandleId(); - s32 rightHandle = GetFreeHandleId(); - CDSPStreamManager tmpLeftStream(leftFile, leftHandle, volume, oneshot); - CDSPStreamManager tmpRightStream(rightFile, rightHandle, volume, oneshot); - if (tmpLeftStream.x70_24_unclaimed || tmpRightStream.x70_24_unclaimed) - return -1; + return handle; + } - tmpLeftStream.x71_companionRight = s8(rightIdx); - tmpRightStream.x72_companionLeft = s8(leftIdx); + static EState GetStreamState(s32 handle) { + s32 idx = FindClaimedStreamIdx(handle); + if (idx == -1) + return EState::Oneshot; - CDSPStreamManager& leftStream = g_Streams[leftIdx]; - CDSPStreamManager& rightStream = g_Streams[rightIdx]; - leftStream = tmpLeftStream; - rightStream = tmpRightStream; - - if (!StartStereoHeaderRead(leftStream, rightStream)) - { - leftStream.x70_25_headerReadCancelled = true; - rightStream.x70_25_headerReadCancelled = true; - leftStream.WaitForReadCompletion(); - leftStream.WaitForReadCompletion(); - leftStream = CDSPStreamManager(); - rightStream = CDSPStreamManager(); - return -1; - } - - return leftHandle; - } + CDSPStreamManager& stream = g_Streams[idx]; + switch (stream.x70_26_headerReadState) { + case 0: + return EState::Oneshot; + case 2: + return EState(!stream.x0_header.xc_loop_flag); + default: + return EState::Preparing; } + } - static void StopStreaming(s32 handle) - { - s32 idx = FindClaimedStreamIdx(handle); - if (idx == -1) - return; + static bool CanStop(s32 handle) { + s32 idx = FindClaimedStreamIdx(handle); + if (idx == -1) + return true; - CDSPStreamManager& stream = g_Streams[idx]; - if (stream.x70_24_unclaimed) - return; + CDSPStreamManager& stream = g_Streams[idx]; + if (stream.x70_26_headerReadState == 1) + return false; - if (stream.x70_26_headerReadState == 1) - { - stream.x70_25_headerReadCancelled = true; - return; - } + if (stream.x7c_streamId == -1) + return true; - if (stream.x71_companionRight != -1) - g_Streams[stream.x71_companionRight] = CDSPStreamManager(); + return !SDSPStream::IsStreamActive(stream.x7c_streamId); + } - SDSPStream::Silence(stream.x7c_streamId); + static bool IsStreamAvailable(s32 handle) { + s32 idx = FindClaimedStreamIdx(handle); + if (idx == -1) + return false; + CDSPStreamManager& stream = g_Streams[idx]; + if (stream.x70_26_headerReadState == 1) + return false; + + if (stream.x7c_streamId == -1) + return false; + + return SDSPStream::IsStreamAvailable(stream.x7c_streamId); + } + + static void AllocateStream(s32 idx) { + CDSPStreamManager& stream = g_Streams[idx]; + SDSPStreamInfo info(stream); + + if (stream.x71_companionRight == -1) { + /* Mono */ + if (!stream.x70_25_headerReadCancelled) + stream.x7c_streamId = SDSPStream::AllocateMono(info, stream.x73_volume, stream.x74_oneshot); + if (stream.x7c_streamId == -1) stream = CDSPStreamManager(); + } else { + /* Stereo */ + CDSPStreamManager& rstream = g_Streams[stream.x71_companionRight]; + SDSPStreamInfo rinfo(rstream); + + if (!stream.x70_25_headerReadCancelled) + stream.x7c_streamId = SDSPStream::AllocateStereo(info, rinfo, stream.x73_volume, stream.x74_oneshot); + if (stream.x7c_streamId == -1) { + stream = CDSPStreamManager(); + rstream = CDSPStreamManager(); + } + } + } + + void HeaderReadComplete() { + s32 selfIdx = -1; + for (int i = 0; i < 4; ++i) { + if (this == &g_Streams[i]) { + selfIdx = i; + break; + } } - static void UpdateVolume(s32 handle, float volume) - { - s32 idx = FindClaimedStreamIdx(handle); - if (idx == -1) - return; - - CDSPStreamManager& stream = g_Streams[idx]; - stream.x73_volume = volume; - if (stream.x7c_streamId == -1) - return; - - SDSPStream::UpdateVolume(stream.x7c_streamId, volume); + if (x70_24_unclaimed || selfIdx == -1) { + *this = CDSPStreamManager(); + return; } - static void Initialize() - { - SDSPStream::Initialize(); - for (int i=0 ; i<4 ; ++i) - { - CDSPStreamManager& stream = g_Streams[i]; - stream = CDSPStreamManager(); - } + x70_26_headerReadState = 2; + + s32 companion = -1; + if (x72_companionLeft != -1) + companion = x72_companionLeft; + else if (x71_companionRight != -1) + companion = x71_companionRight; + + if (companion != -1) { + /* Stereo */ + CDSPStreamManager& companionStream = g_Streams[companion]; + if (companionStream.x70_24_unclaimed || companionStream.x70_26_headerReadState == 0 || + (companionStream.x71_companionRight != selfIdx && companionStream.x72_companionLeft != selfIdx)) { + /* No consistent companion available */ + *this = CDSPStreamManager(); + return; + } + + /* Companion is pending; its completion will continue */ + if (companionStream.x70_26_headerReadState == 1) + return; + + /* Use whichever stream is the left channel */ + if (companionStream.x71_companionRight != -1) + AllocateStream(companion); + else + AllocateStream(selfIdx); + } else { + /* Mono */ + AllocateStream(selfIdx); + } + } + + static void PollHeaderReadCompletions() { + for (int i = 0; i < 4; ++i) { + CDSPStreamManager& stream = g_Streams[i]; + if (stream.m_dvdReq && stream.m_dvdReq->IsComplete()) { + stream.m_dvdReq.reset(); + stream.HeaderReadComplete(); + } + } + } + + static bool StartMonoHeaderRead(CDSPStreamManager& stream) { + if (stream.x70_26_headerReadState != 0 || stream.x70_24_unclaimed) + return false; + + CDvdFile file(stream.x60_fileName.c_str()); + if (!file) + return false; + + stream.x70_26_headerReadState = 1; + stream.m_dvdReq = file.AsyncRead(&stream.x0_header, sizeof(dspadpcm_header)); + return true; + } + + static bool StartStereoHeaderRead(CDSPStreamManager& lstream, CDSPStreamManager& rstream) { + if (lstream.x70_26_headerReadState != 0 || lstream.x70_24_unclaimed || rstream.x70_26_headerReadState != 0 || + rstream.x70_24_unclaimed) + return false; + + CDvdFile lfile(lstream.x60_fileName.c_str()); + if (!lfile) + return false; + + CDvdFile rfile(rstream.x60_fileName.c_str()); + if (!rfile) + return false; + + lstream.x70_26_headerReadState = 1; + rstream.x70_26_headerReadState = 1; + + lstream.m_dvdReq = lfile.AsyncRead(&lstream.x0_header, sizeof(dspadpcm_header)); + rstream.m_dvdReq = rfile.AsyncRead(&rstream.x0_header, sizeof(dspadpcm_header)); + return true; + } + + void WaitForReadCompletion() { + if (std::shared_ptr req = m_dvdReq) + req->WaitUntilComplete(); + m_dvdReq.reset(); + } + + static s32 StartStreaming(std::string_view fileName, float volume, bool oneshot) { + auto pipePos = fileName.find('|'); + if (pipePos == std::string::npos) { + /* Mono stream */ + s32 idx = FindUnclaimedStreamIdx(); + if (idx == -1) + return -1; + + s32 handle = GetFreeHandleId(); + CDSPStreamManager tmpStream(fileName, handle, volume, oneshot); + if (tmpStream.x70_24_unclaimed) + return -1; + + CDSPStreamManager& stream = g_Streams[idx]; + stream = tmpStream; + + if (!StartMonoHeaderRead(stream)) { + stream.x70_25_headerReadCancelled = true; + stream.WaitForReadCompletion(); + stream = CDSPStreamManager(); + return -1; + } + + return handle; + } else { + /* Stereo stream */ + s32 leftIdx = 0; + s32 rightIdx = 0; + if (!FindUnclaimedStereoPair(leftIdx, rightIdx)) + return -1; + + std::string leftFile(fileName.begin(), fileName.begin() + pipePos); + std::string rightFile(fileName.begin() + pipePos + 1, fileName.end()); + + s32 leftHandle = GetFreeHandleId(); + s32 rightHandle = GetFreeHandleId(); + CDSPStreamManager tmpLeftStream(leftFile, leftHandle, volume, oneshot); + CDSPStreamManager tmpRightStream(rightFile, rightHandle, volume, oneshot); + if (tmpLeftStream.x70_24_unclaimed || tmpRightStream.x70_24_unclaimed) + return -1; + + tmpLeftStream.x71_companionRight = s8(rightIdx); + tmpRightStream.x72_companionLeft = s8(leftIdx); + + CDSPStreamManager& leftStream = g_Streams[leftIdx]; + CDSPStreamManager& rightStream = g_Streams[rightIdx]; + leftStream = tmpLeftStream; + rightStream = tmpRightStream; + + if (!StartStereoHeaderRead(leftStream, rightStream)) { + leftStream.x70_25_headerReadCancelled = true; + rightStream.x70_25_headerReadCancelled = true; + leftStream.WaitForReadCompletion(); + leftStream.WaitForReadCompletion(); + leftStream = CDSPStreamManager(); + rightStream = CDSPStreamManager(); + return -1; + } + + return leftHandle; + } + } + + static void StopStreaming(s32 handle) { + s32 idx = FindClaimedStreamIdx(handle); + if (idx == -1) + return; + + CDSPStreamManager& stream = g_Streams[idx]; + if (stream.x70_24_unclaimed) + return; + + if (stream.x70_26_headerReadState == 1) { + stream.x70_25_headerReadCancelled = true; + return; } - static void Shutdown() - { - SDSPStream::FreeAllStreams(); - for (int i=0 ; i<4 ; ++i) - { - CDSPStreamManager& stream = g_Streams[i]; - stream = CDSPStreamManager(); - } + if (stream.x71_companionRight != -1) + g_Streams[stream.x71_companionRight] = CDSPStreamManager(); + + SDSPStream::Silence(stream.x7c_streamId); + + stream = CDSPStreamManager(); + } + + static void UpdateVolume(s32 handle, float volume) { + s32 idx = FindClaimedStreamIdx(handle); + if (idx == -1) + return; + + CDSPStreamManager& stream = g_Streams[idx]; + stream.x73_volume = volume; + if (stream.x7c_streamId == -1) + return; + + SDSPStream::UpdateVolume(stream.x7c_streamId, volume); + } + + static void Initialize() { + SDSPStream::Initialize(); + for (int i = 0; i < 4; ++i) { + CDSPStreamManager& stream = g_Streams[i]; + stream = CDSPStreamManager(); } + } + + static void Shutdown() { + SDSPStream::FreeAllStreams(); + for (int i = 0; i < 4; ++i) { + CDSPStreamManager& stream = g_Streams[i]; + stream = CDSPStreamManager(); + } + } }; CDSPStreamManager CDSPStreamManager::g_Streams[4] = {}; +SDSPStreamInfo::SDSPStreamInfo(const CDSPStreamManager& stream) { + x0_fileName = stream.x60_fileName.c_str(); + x4_sampleRate = hecl::SBig(stream.x0_header.x8_sample_rate); + xc_adpcmBytes = (hecl::SBig(stream.x0_header.x4_num_nibbles) / 2) & 0x7FFFFFE0; -SDSPStreamInfo::SDSPStreamInfo(const CDSPStreamManager& stream) -{ - x0_fileName = stream.x60_fileName.c_str(); - x4_sampleRate = hecl::SBig(stream.x0_header.x8_sample_rate); - xc_adpcmBytes = (hecl::SBig(stream.x0_header.x4_num_nibbles) / 2) & 0x7FFFFFE0; + if (stream.x0_header.xc_loop_flag) { + u32 loopStartNibble = hecl::SBig(stream.x0_header.x10_loop_start_nibble); + u32 loopEndNibble = hecl::SBig(stream.x0_header.x14_loop_end_nibble); + x10_loopFlag = true; + x14_loopStartByte = (loopStartNibble / 2) & 0x7FFFFFE0; + x18_loopEndByte = std::min((loopEndNibble / 2) & 0x7FFFFFE0, xc_adpcmBytes); + } else { + x10_loopFlag = false; + x14_loopStartByte = 0; + x18_loopEndByte = 0; + } - if (stream.x0_header.xc_loop_flag) - { - u32 loopStartNibble = hecl::SBig(stream.x0_header.x10_loop_start_nibble); - u32 loopEndNibble = hecl::SBig(stream.x0_header.x14_loop_end_nibble); - x10_loopFlag = true; - x14_loopStartByte = (loopStartNibble / 2) & 0x7FFFFFE0; - x18_loopEndByte = std::min((loopEndNibble / 2) & 0x7FFFFFE0, xc_adpcmBytes); - } - else - { - x10_loopFlag = false; - x14_loopStartByte = 0; - x18_loopEndByte = 0; - } - - for (int i=0 ; i<8 ; ++i) - { - x1c_coef[i][0] = hecl::SBig(stream.x0_header.x1c_coef[i][0]); - x1c_coef[i][1] = hecl::SBig(stream.x0_header.x1c_coef[i][1]); - } + for (int i = 0; i < 8; ++i) { + x1c_coef[i][0] = hecl::SBig(stream.x0_header.x1c_coef[i][0]); + x1c_coef[i][1] = hecl::SBig(stream.x0_header.x1c_coef[i][1]); + } } -enum class EPlayerState -{ - Stopped, - FadeIn, - Playing, - FadeOut, - FadeOutNoStop -}; +enum class EPlayerState { Stopped, FadeIn, Playing, FadeOut, FadeOutNoStop }; -struct SDSPPlayer -{ - std::string x0_fileName; - EPlayerState x10_playState = EPlayerState::Stopped; - float x14_volume = 0.f; - float x18_fadeIn = 0.f; - float x1c_fadeOut = 0.f; - s32 x20_internalHandle = -1; - float x24_fadeFactor = 0.f; - bool x28_music = true; +struct SDSPPlayer { + std::string x0_fileName; + EPlayerState x10_playState = EPlayerState::Stopped; + float x14_volume = 0.f; + float x18_fadeIn = 0.f; + float x1c_fadeOut = 0.f; + s32 x20_internalHandle = -1; + float x24_fadeFactor = 0.f; + bool x28_music = true; - SDSPPlayer() = default; - SDSPPlayer(EPlayerState playing, std::string_view fileName, float volume, - float fadeIn, float fadeOut, s32 handle, bool music) - : x0_fileName(fileName), x10_playState(playing), x14_volume(volume), - x18_fadeIn(fadeIn), x1c_fadeOut(fadeOut), x20_internalHandle(handle), x28_music(music) {} + SDSPPlayer() = default; + SDSPPlayer(EPlayerState playing, std::string_view fileName, float volume, float fadeIn, float fadeOut, s32 handle, + bool music) + : x0_fileName(fileName) + , x10_playState(playing) + , x14_volume(volume) + , x18_fadeIn(fadeIn) + , x1c_fadeOut(fadeOut) + , x20_internalHandle(handle) + , x28_music(music) {} }; -static SDSPPlayer s_Players[2]; // looping, oneshot +static SDSPPlayer s_Players[2]; // looping, oneshot static SDSPPlayer s_QueuedPlayers[2]; // looping, oneshot -float CStreamAudioManager::GetTargetDSPVolume(float fileVol, bool music) -{ - if (music) - return g_MusicUnmute ? (g_MusicVolume * fileVol / 127.f) : 0.f; - else - return g_SfxUnmute ? (g_SfxVolume * fileVol / 127.f) : 0.f; +float CStreamAudioManager::GetTargetDSPVolume(float fileVol, bool music) { + if (music) + return g_MusicUnmute ? (g_MusicVolume * fileVol / 127.f) : 0.f; + else + return g_SfxUnmute ? (g_SfxVolume * fileVol / 127.f) : 0.f; } -void CStreamAudioManager::Start(bool oneshot, std::string_view fileName, - float volume, bool music, float fadeIn, float fadeOut) -{ - SDSPPlayer& p = s_Players[oneshot]; - SDSPPlayer& qp = s_QueuedPlayers[oneshot]; +void CStreamAudioManager::Start(bool oneshot, std::string_view fileName, float volume, bool music, float fadeIn, + float fadeOut) { + SDSPPlayer& p = s_Players[oneshot]; + SDSPPlayer& qp = s_QueuedPlayers[oneshot]; - if (p.x10_playState != EPlayerState::Stopped && - CStringExtras::CompareCaseInsensitive(fileName, p.x0_fileName)) - { - /* Enque new stream */ - qp = SDSPPlayer(EPlayerState::FadeIn, fileName, volume, fadeIn, fadeOut, -1, music); - Stop(oneshot, p.x0_fileName); + if (p.x10_playState != EPlayerState::Stopped && CStringExtras::CompareCaseInsensitive(fileName, p.x0_fileName)) { + /* Enque new stream */ + qp = SDSPPlayer(EPlayerState::FadeIn, fileName, volume, fadeIn, fadeOut, -1, music); + Stop(oneshot, p.x0_fileName); + } else if (p.x10_playState != EPlayerState::Stopped) { + /* Fade existing stream back in */ + p.x18_fadeIn = fadeIn; + p.x1c_fadeOut = fadeOut; + p.x14_volume = volume; + if (p.x18_fadeIn <= FLT_EPSILON) { + CDSPStreamManager::UpdateVolume(p.x20_internalHandle, GetTargetDSPVolume(p.x14_volume, p.x28_music)); + p.x24_fadeFactor = 1.f; + p.x10_playState = EPlayerState::Playing; + } else { + p.x10_playState = EPlayerState::FadeIn; } - else if (p.x10_playState != EPlayerState::Stopped) - { - /* Fade existing stream back in */ - p.x18_fadeIn = fadeIn; - p.x1c_fadeOut = fadeOut; - p.x14_volume = volume; - if (p.x18_fadeIn <= FLT_EPSILON) - { - CDSPStreamManager::UpdateVolume(p.x20_internalHandle, - GetTargetDSPVolume(p.x14_volume, p.x28_music)); - p.x24_fadeFactor = 1.f; - p.x10_playState = EPlayerState::Playing; - } - else - { - p.x10_playState = EPlayerState::FadeIn; - } + } else { + /* Start new stream */ + EPlayerState state; + float vol; + if (fadeIn > 0.f) { + state = EPlayerState::FadeIn; + vol = 0.f; + } else { + state = EPlayerState::Playing; + vol = volume; } - else - { - /* Start new stream */ - EPlayerState state; - float vol; - if (fadeIn > 0.f) - { - state = EPlayerState::FadeIn; - vol = 0.f; - } - else - { - state = EPlayerState::Playing; - vol = volume; - } - s32 handle = CDSPStreamManager::StartStreaming(fileName, GetTargetDSPVolume(vol, music), oneshot); - if (handle != -1) - p = SDSPPlayer(state, fileName, volume, fadeIn, fadeOut, handle, music); - } + s32 handle = CDSPStreamManager::StartStreaming(fileName, GetTargetDSPVolume(vol, music), oneshot); + if (handle != -1) + p = SDSPPlayer(state, fileName, volume, fadeIn, fadeOut, handle, music); + } } -void CStreamAudioManager::Stop(bool oneshot, std::string_view fileName) -{ - SDSPPlayer& p = s_Players[oneshot]; - SDSPPlayer& qp = s_QueuedPlayers[oneshot]; +void CStreamAudioManager::Stop(bool oneshot, std::string_view fileName) { + SDSPPlayer& p = s_Players[oneshot]; + SDSPPlayer& qp = s_QueuedPlayers[oneshot]; - if (!CStringExtras::CompareCaseInsensitive(fileName, qp.x0_fileName)) - { - /* Cancel enqueued file */ - qp = SDSPPlayer(); - } - else if (!CStringExtras::CompareCaseInsensitive(fileName, p.x0_fileName) && - p.x20_internalHandle != -1 && p.x10_playState != EPlayerState::Stopped) - { - /* Fade out or stop */ - if (p.x1c_fadeOut <= FLT_EPSILON) - StopStreaming(oneshot); - else - p.x10_playState = EPlayerState::FadeOut; - } -} - -void CStreamAudioManager::FadeBackIn(bool oneshot, float fadeTime) -{ - SDSPPlayer& p = s_Players[oneshot]; - if (p.x10_playState == EPlayerState::Stopped || - p.x10_playState == EPlayerState::Playing) - return; - p.x18_fadeIn = fadeTime; - p.x10_playState = EPlayerState::FadeIn; -} - -void CStreamAudioManager::TemporaryFadeOut(bool oneshot, float fadeTime) -{ - SDSPPlayer& p = s_Players[oneshot]; - if (p.x10_playState == EPlayerState::FadeOut || - p.x10_playState == EPlayerState::Stopped) - return; - p.x1c_fadeOut = fadeTime; - p.x10_playState = EPlayerState::FadeOutNoStop; -} - -void CStreamAudioManager::StopStreaming(bool oneshot) -{ - SDSPPlayer& p = s_Players[oneshot]; - p.x10_playState = EPlayerState::Stopped; - CDSPStreamManager::StopStreaming(p.x20_internalHandle); - p.x24_fadeFactor = 0.f; - p.x20_internalHandle = -1; -} - -void CStreamAudioManager::UpdateDSP(bool oneshot, float dt) -{ - SDSPPlayer& p = s_Players[oneshot]; - - if (p.x10_playState == EPlayerState::Stopped) - { - SDSPPlayer& qp = s_QueuedPlayers[oneshot]; - if (qp.x10_playState != EPlayerState::Stopped) - { - Start(oneshot, qp.x0_fileName, qp.x14_volume, qp.x28_music, - qp.x18_fadeIn, qp.x1c_fadeOut); - qp = SDSPPlayer(); - } - } - else - { - if (p.x10_playState != EPlayerState::Stopped && - CDSPStreamManager::GetStreamState(p.x20_internalHandle) == CDSPStreamManager::EState::Oneshot && - CDSPStreamManager::CanStop(p.x20_internalHandle)) - { - StopStreaming(oneshot); - return; - } - - if ((p.x10_playState != EPlayerState::FadeIn && - p.x10_playState != EPlayerState::FadeOut && - p.x10_playState != EPlayerState::FadeOutNoStop)) - { - if (p.x10_playState == EPlayerState::Playing) - CDSPStreamManager::UpdateVolume(p.x20_internalHandle, - GetTargetDSPVolume(p.x14_volume, p.x28_music)); - return; - } - - if (p.x10_playState == EPlayerState::FadeIn) - { - float newFadeFactor = p.x24_fadeFactor + dt / p.x18_fadeIn; - if (newFadeFactor >= 1.f) - { - p.x24_fadeFactor = 1.f; - p.x10_playState = EPlayerState::Playing; - } - else - { - p.x24_fadeFactor = newFadeFactor; - } - } - else if (p.x10_playState == EPlayerState::FadeOut || - p.x10_playState == EPlayerState::FadeOutNoStop) - { - float newFadeFactor = p.x24_fadeFactor - dt / p.x1c_fadeOut; - if (newFadeFactor <= 0.f) - { - if (p.x10_playState == EPlayerState::FadeOutNoStop) - { - p.x24_fadeFactor = 0.f; - } - else - { - StopStreaming(oneshot); - return; - } - } - else - { - p.x24_fadeFactor = newFadeFactor; - } - } - - CDSPStreamManager::UpdateVolume(p.x20_internalHandle, - GetTargetDSPVolume(p.x14_volume * p.x24_fadeFactor, - p.x28_music)); - } -} - -void CStreamAudioManager::UpdateDSPStreamers(float dt) -{ - UpdateDSP(false, dt); - UpdateDSP(true, dt); -} - -void CStreamAudioManager::StopAllStreams() -{ - for (int i=0 ; i<2 ; ++i) - { - StopStreaming(bool(i)); - SDSPPlayer& p = s_Players[i]; - SDSPPlayer& qp = s_QueuedPlayers[i]; - p = SDSPPlayer(); - qp = SDSPPlayer(); - } -} - -void CStreamAudioManager::Update(float dt) -{ - CDSPStreamManager::PollHeaderReadCompletions(); - UpdateDSPStreamers(dt); -} - -void CStreamAudioManager::StopAll() -{ - StopAllStreams(); -} - -void CStreamAudioManager::SetMusicUnmute(bool unmute) -{ - g_MusicUnmute = unmute; -} - -void CStreamAudioManager::SetSfxVolume(u8 volume) -{ - g_SfxVolume = std::min(volume, u8(127)); -} - -void CStreamAudioManager::SetMusicVolume(u8 volume) -{ - g_MusicVolume = std::min(volume, u8(127)); -} - -void CStreamAudioManager::Initialize() -{ - CDSPStreamManager::Initialize(); -} - -void CStreamAudioManager::StopOneShot() -{ - CStreamAudioManager::StopStreaming(true); - SDSPPlayer& p = s_Players[1]; - p = SDSPPlayer(); - SDSPPlayer& qp = s_QueuedPlayers[1]; + if (!CStringExtras::CompareCaseInsensitive(fileName, qp.x0_fileName)) { + /* Cancel enqueued file */ qp = SDSPPlayer(); + } else if (!CStringExtras::CompareCaseInsensitive(fileName, p.x0_fileName) && p.x20_internalHandle != -1 && + p.x10_playState != EPlayerState::Stopped) { + /* Fade out or stop */ + if (p.x1c_fadeOut <= FLT_EPSILON) + StopStreaming(oneshot); + else + p.x10_playState = EPlayerState::FadeOut; + } } -void CStreamAudioManager::Shutdown() -{ - CDSPStreamManager::Shutdown(); +void CStreamAudioManager::FadeBackIn(bool oneshot, float fadeTime) { + SDSPPlayer& p = s_Players[oneshot]; + if (p.x10_playState == EPlayerState::Stopped || p.x10_playState == EPlayerState::Playing) + return; + p.x18_fadeIn = fadeTime; + p.x10_playState = EPlayerState::FadeIn; } +void CStreamAudioManager::TemporaryFadeOut(bool oneshot, float fadeTime) { + SDSPPlayer& p = s_Players[oneshot]; + if (p.x10_playState == EPlayerState::FadeOut || p.x10_playState == EPlayerState::Stopped) + return; + p.x1c_fadeOut = fadeTime; + p.x10_playState = EPlayerState::FadeOutNoStop; +} + +void CStreamAudioManager::StopStreaming(bool oneshot) { + SDSPPlayer& p = s_Players[oneshot]; + p.x10_playState = EPlayerState::Stopped; + CDSPStreamManager::StopStreaming(p.x20_internalHandle); + p.x24_fadeFactor = 0.f; + p.x20_internalHandle = -1; +} + +void CStreamAudioManager::UpdateDSP(bool oneshot, float dt) { + SDSPPlayer& p = s_Players[oneshot]; + + if (p.x10_playState == EPlayerState::Stopped) { + SDSPPlayer& qp = s_QueuedPlayers[oneshot]; + if (qp.x10_playState != EPlayerState::Stopped) { + Start(oneshot, qp.x0_fileName, qp.x14_volume, qp.x28_music, qp.x18_fadeIn, qp.x1c_fadeOut); + qp = SDSPPlayer(); + } + } else { + if (p.x10_playState != EPlayerState::Stopped && + CDSPStreamManager::GetStreamState(p.x20_internalHandle) == CDSPStreamManager::EState::Oneshot && + CDSPStreamManager::CanStop(p.x20_internalHandle)) { + StopStreaming(oneshot); + return; + } + + if ((p.x10_playState != EPlayerState::FadeIn && p.x10_playState != EPlayerState::FadeOut && + p.x10_playState != EPlayerState::FadeOutNoStop)) { + if (p.x10_playState == EPlayerState::Playing) + CDSPStreamManager::UpdateVolume(p.x20_internalHandle, GetTargetDSPVolume(p.x14_volume, p.x28_music)); + return; + } + + if (p.x10_playState == EPlayerState::FadeIn) { + float newFadeFactor = p.x24_fadeFactor + dt / p.x18_fadeIn; + if (newFadeFactor >= 1.f) { + p.x24_fadeFactor = 1.f; + p.x10_playState = EPlayerState::Playing; + } else { + p.x24_fadeFactor = newFadeFactor; + } + } else if (p.x10_playState == EPlayerState::FadeOut || p.x10_playState == EPlayerState::FadeOutNoStop) { + float newFadeFactor = p.x24_fadeFactor - dt / p.x1c_fadeOut; + if (newFadeFactor <= 0.f) { + if (p.x10_playState == EPlayerState::FadeOutNoStop) { + p.x24_fadeFactor = 0.f; + } else { + StopStreaming(oneshot); + return; + } + } else { + p.x24_fadeFactor = newFadeFactor; + } + } + + CDSPStreamManager::UpdateVolume(p.x20_internalHandle, + GetTargetDSPVolume(p.x14_volume * p.x24_fadeFactor, p.x28_music)); + } +} + +void CStreamAudioManager::UpdateDSPStreamers(float dt) { + UpdateDSP(false, dt); + UpdateDSP(true, dt); +} + +void CStreamAudioManager::StopAllStreams() { + for (int i = 0; i < 2; ++i) { + StopStreaming(bool(i)); + SDSPPlayer& p = s_Players[i]; + SDSPPlayer& qp = s_QueuedPlayers[i]; + p = SDSPPlayer(); + qp = SDSPPlayer(); + } +} + +void CStreamAudioManager::Update(float dt) { + CDSPStreamManager::PollHeaderReadCompletions(); + UpdateDSPStreamers(dt); +} + +void CStreamAudioManager::StopAll() { StopAllStreams(); } + +void CStreamAudioManager::SetMusicUnmute(bool unmute) { g_MusicUnmute = unmute; } + +void CStreamAudioManager::SetSfxVolume(u8 volume) { g_SfxVolume = std::min(volume, u8(127)); } + +void CStreamAudioManager::SetMusicVolume(u8 volume) { g_MusicVolume = std::min(volume, u8(127)); } + +void CStreamAudioManager::Initialize() { CDSPStreamManager::Initialize(); } + +void CStreamAudioManager::StopOneShot() { + CStreamAudioManager::StopStreaming(true); + SDSPPlayer& p = s_Players[1]; + p = SDSPPlayer(); + SDSPPlayer& qp = s_QueuedPlayers[1]; + qp = SDSPPlayer(); +} + +void CStreamAudioManager::Shutdown() { CDSPStreamManager::Shutdown(); } + u8 CStreamAudioManager::g_MusicVolume = 0x7f; u8 CStreamAudioManager::g_SfxVolume = 0x7f; bool CStreamAudioManager::g_MusicUnmute = true; bool CStreamAudioManager::g_SfxUnmute = true; -} +} // namespace urde diff --git a/Runtime/Audio/CStreamAudioManager.hpp b/Runtime/Audio/CStreamAudioManager.hpp index 7fbbdcc2d..056ecd31a 100644 --- a/Runtime/Audio/CStreamAudioManager.hpp +++ b/Runtime/Audio/CStreamAudioManager.hpp @@ -2,38 +2,34 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -class CStreamAudioManager -{ - static u8 g_MusicVolume; - static u8 g_SfxVolume; - static bool g_MusicUnmute; - static bool g_SfxUnmute; +class CStreamAudioManager { + static u8 g_MusicVolume; + static u8 g_SfxVolume; + static bool g_MusicUnmute; + static bool g_SfxUnmute; - static float GetTargetDSPVolume(float fileVol, bool music); - static void StopStreaming(bool oneshot); - static void UpdateDSP(bool oneshot, float dt); - static void UpdateDSPStreamers(float dt); - static void StopAllStreams(); + static float GetTargetDSPVolume(float fileVol, bool music); + static void StopStreaming(bool oneshot); + static void UpdateDSP(bool oneshot, float dt); + static void UpdateDSPStreamers(float dt); + static void StopAllStreams(); public: - static void Start(bool oneshot, std::string_view fileName, float volume, - bool music, float fadeIn, float fadeOut); - static void Stop(bool oneshot, std::string_view fileName); - static void FadeBackIn(bool oneshot, float fadeTime); - static void TemporaryFadeOut(bool oneshot, float fadeTime); - static void Update(float dt); - static void StopAll(); - static void SetMusicUnmute(bool unmute); - static void SetSfxVolume(u8 volume); - static void SetMusicVolume(u8 volume); + static void Start(bool oneshot, std::string_view fileName, float volume, bool music, float fadeIn, float fadeOut); + static void Stop(bool oneshot, std::string_view fileName); + static void FadeBackIn(bool oneshot, float fadeTime); + static void TemporaryFadeOut(bool oneshot, float fadeTime); + static void Update(float dt); + static void StopAll(); + static void SetMusicUnmute(bool unmute); + static void SetSfxVolume(u8 volume); + static void SetMusicVolume(u8 volume); - static void Initialize(); - static void StopOneShot(); - static void Shutdown(); + static void Initialize(); + static void StopOneShot(); + static void Shutdown(); }; -} - +} // namespace urde diff --git a/Runtime/AutoMapper/CAutoMapper.cpp b/Runtime/AutoMapper/CAutoMapper.cpp index 372a3bc76..73963e8a3 100644 --- a/Runtime/AutoMapper/CAutoMapper.cpp +++ b/Runtime/AutoMapper/CAutoMapper.cpp @@ -13,1811 +13,1542 @@ #include "GuiSys/CGuiTextPane.hpp" #include "GuiSys/CGuiWidgetDrawParms.hpp" -namespace urde -{ +namespace urde { void CAutoMapper::SAutoMapperRenderState::InterpolateWithClamp(const SAutoMapperRenderState& a, SAutoMapperRenderState& out, - const SAutoMapperRenderState& b, - float t) -{ - t = zeus::clamp(0.f, t, 1.f); - float easeIn = zeus::clamp(0.f, t * t * t, 1.f); - float omt = 1.f - t; - float easeOut = zeus::clamp(0.f, 1.f - omt * omt * omt, 1.f); + const SAutoMapperRenderState& b, float t) { + t = zeus::clamp(0.f, t, 1.f); + float easeIn = zeus::clamp(0.f, t * t * t, 1.f); + float omt = 1.f - t; + float easeOut = zeus::clamp(0.f, 1.f - omt * omt * omt, 1.f); - float easeInOut; - if (t >= 0.5f) - easeInOut = zeus::clamp(0.f, 0.5f * std::sqrt(2.f * t - 1.f) + 0.5f, 1.f); - else - easeInOut = zeus::clamp(0.f, 1.f - (0.5f * std::sqrt(2.f * omt - 1.f) + 0.5f), 1.f); + float easeInOut; + if (t >= 0.5f) + easeInOut = zeus::clamp(0.f, 0.5f * std::sqrt(2.f * t - 1.f) + 0.5f, 1.f); + else + easeInOut = zeus::clamp(0.f, 1.f - (0.5f * std::sqrt(2.f * omt - 1.f) + 0.5f), 1.f); - float eases[5] = {}; - eases[1] = t; - eases[2] = easeOut; - eases[3] = easeIn; - eases[4] = easeInOut; + float eases[5] = {}; + eases[1] = t; + eases[2] = easeOut; + eases[3] = easeIn; + eases[4] = easeInOut; - if (b.x44_viewportEase != Ease::None) - { - float easeB = eases[int(b.x44_viewportEase)]; - float easeA = 1.f - easeB; - zeus::CVector2i vpA = a.GetViewportSize(); - zeus::CVector2i vpB = b.GetViewportSize(); - out.x0_viewportSize = zeus::CVector2i(vpB.x * easeB + vpA.x * easeA, - vpB.y * easeB + vpA.y * easeA); - } - if (t == 1.f) - out.m_getViewportSize = b.m_getViewportSize; - else - out.m_getViewportSize = nullptr; + if (b.x44_viewportEase != Ease::None) { + float easeB = eases[int(b.x44_viewportEase)]; + float easeA = 1.f - easeB; + zeus::CVector2i vpA = a.GetViewportSize(); + zeus::CVector2i vpB = b.GetViewportSize(); + out.x0_viewportSize = zeus::CVector2i(vpB.x * easeB + vpA.x * easeA, vpB.y * easeB + vpA.y * easeA); + } + if (t == 1.f) + out.m_getViewportSize = b.m_getViewportSize; + else + out.m_getViewportSize = nullptr; - if (b.x48_camEase != Ease::None) - { - float easeB = eases[int(b.x48_camEase)]; - float easeA = 1.f - easeB; - out.x8_camOrientation = zeus::CQuaternion::slerp(a.x8_camOrientation, b.x8_camOrientation, easeB); - out.x18_camDist = b.x18_camDist * easeB + a.x18_camDist * easeA; - out.x1c_camAngle = b.x1c_camAngle * easeB + a.x1c_camAngle * easeA; - } + if (b.x48_camEase != Ease::None) { + float easeB = eases[int(b.x48_camEase)]; + float easeA = 1.f - easeB; + out.x8_camOrientation = zeus::CQuaternion::slerp(a.x8_camOrientation, b.x8_camOrientation, easeB); + out.x18_camDist = b.x18_camDist * easeB + a.x18_camDist * easeA; + out.x1c_camAngle = b.x1c_camAngle * easeB + a.x1c_camAngle * easeA; + } - if (b.x4c_pointEase != Ease::None) - { - float easeB = eases[int(b.x4c_pointEase)]; - float easeA = 1.f - easeB; - out.x20_areaPoint = b.x20_areaPoint * easeB + a.x20_areaPoint * easeA; - } + if (b.x4c_pointEase != Ease::None) { + float easeB = eases[int(b.x4c_pointEase)]; + float easeA = 1.f - easeB; + out.x20_areaPoint = b.x20_areaPoint * easeB + a.x20_areaPoint * easeA; + } - if (b.x50_depth1Ease != Ease::None) - { - float easeB = eases[int(b.x50_depth1Ease)]; - float easeA = 1.f - easeB; - out.x2c_drawDepth1 = b.x2c_drawDepth1 * easeB + a.x2c_drawDepth1 * easeA; - } + if (b.x50_depth1Ease != Ease::None) { + float easeB = eases[int(b.x50_depth1Ease)]; + float easeA = 1.f - easeB; + out.x2c_drawDepth1 = b.x2c_drawDepth1 * easeB + a.x2c_drawDepth1 * easeA; + } - if (b.x54_depth2Ease != Ease::None) - { - float easeB = eases[int(b.x54_depth2Ease)]; - float easeA = 1.f - easeB; - out.x30_drawDepth2 = b.x30_drawDepth2 * easeB + a.x30_drawDepth2 * easeA; - } + if (b.x54_depth2Ease != Ease::None) { + float easeB = eases[int(b.x54_depth2Ease)]; + float easeA = 1.f - easeB; + out.x30_drawDepth2 = b.x30_drawDepth2 * easeB + a.x30_drawDepth2 * easeA; + } - if (b.x58_alphaEase != Ease::None) - { - float easeB = eases[int(b.x58_alphaEase)]; - float easeA = 1.f - easeB; - out.x34_alphaSurfaceVisited = b.x34_alphaSurfaceVisited * easeB + a.x34_alphaSurfaceVisited * easeA; - out.x38_alphaOutlineVisited = b.x38_alphaOutlineVisited * easeB + a.x38_alphaOutlineVisited * easeA; - out.x3c_alphaSurfaceUnvisited = b.x3c_alphaSurfaceUnvisited * easeB + a.x3c_alphaSurfaceUnvisited * easeA; - out.x40_alphaOutlineUnvisited = b.x40_alphaOutlineUnvisited * easeB + a.x40_alphaOutlineUnvisited * easeA; - } + if (b.x58_alphaEase != Ease::None) { + float easeB = eases[int(b.x58_alphaEase)]; + float easeA = 1.f - easeB; + out.x34_alphaSurfaceVisited = b.x34_alphaSurfaceVisited * easeB + a.x34_alphaSurfaceVisited * easeA; + out.x38_alphaOutlineVisited = b.x38_alphaOutlineVisited * easeB + a.x38_alphaOutlineVisited * easeA; + out.x3c_alphaSurfaceUnvisited = b.x3c_alphaSurfaceUnvisited * easeB + a.x3c_alphaSurfaceUnvisited * easeA; + out.x40_alphaOutlineUnvisited = b.x40_alphaOutlineUnvisited * easeB + a.x40_alphaOutlineUnvisited * easeA; + } } -CAutoMapper::CAutoMapper(CStateManager& stateMgr) -: x24_world(stateMgr.GetWorld()) -{ - x8_mapu = g_SimplePool->GetObj("MAPU_MapUniverse"); - x30_miniMapSamus = g_SimplePool->GetObj("CMDL_MiniMapSamus"); - x3c_hintBeacon = g_SimplePool->GetObj("TXTR_HintBeacon"); +CAutoMapper::CAutoMapper(CStateManager& stateMgr) : x24_world(stateMgr.GetWorld()) { + x8_mapu = g_SimplePool->GetObj("MAPU_MapUniverse"); + x30_miniMapSamus = g_SimplePool->GetObj("CMDL_MiniMapSamus"); + x3c_hintBeacon = g_SimplePool->GetObj("TXTR_HintBeacon"); - xa0_curAreaId = xa4_otherAreaId = stateMgr.GetWorld()->IGetCurrentAreaId(); - zeus::CMatrix3f camRot = stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr)->GetTransform().buildMatrix3f(); - xa8_renderStates[0] = xa8_renderStates[1] = xa8_renderStates[2] = BuildMiniMapWorldRenderState(stateMgr, camRot, xa0_curAreaId); + xa0_curAreaId = xa4_otherAreaId = stateMgr.GetWorld()->IGetCurrentAreaId(); + zeus::CMatrix3f camRot = stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr)->GetTransform().buildMatrix3f(); + xa8_renderStates[0] = xa8_renderStates[1] = xa8_renderStates[2] = + BuildMiniMapWorldRenderState(stateMgr, camRot, xa0_curAreaId); - x48_mapIcons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x4_saveStationIcon})); - x48_mapIcons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x8_missileStationIcon})); - x48_mapIcons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->xc_elevatorIcon})); - x48_mapIcons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x10_minesBreakFirstTopIcon})); - x48_mapIcons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x14_minesBreakFirstBottomIcon})); + x48_mapIcons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x4_saveStationIcon})); + x48_mapIcons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x8_missileStationIcon})); + x48_mapIcons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->xc_elevatorIcon})); + x48_mapIcons.push_back( + g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x10_minesBreakFirstTopIcon})); + x48_mapIcons.push_back( + g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x14_minesBreakFirstBottomIcon})); - for (u32 i=0 ; i<9 ; ++i) - { - x210_lstick.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x24_lStick[i]})); - x25c_cstick.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x4c_cStick[i]})); - } + for (u32 i = 0; i < 9; ++i) { + x210_lstick.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x24_lStick[i]})); + x25c_cstick.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x4c_cStick[i]})); + } - for (u32 i=0 ; i<2 ; ++i) - { - x2a8_ltrigger.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x74_lTrigger[i]})); - x2bc_rtrigger.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x80_rTrigger[i]})); - x2d0_abutton.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x98_aButton[i]})); - } + for (u32 i = 0; i < 2; ++i) { + x2a8_ltrigger.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x74_lTrigger[i]})); + x2bc_rtrigger.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x80_rTrigger[i]})); + x2d0_abutton.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), g_tweakPlayerRes->x98_aButton[i]})); + } } -bool CAutoMapper::CheckLoadComplete() -{ - switch (x4_loadPhase) - { - case ELoadPhase::LoadResources: - for (TLockedToken& tex : x48_mapIcons) - if (!tex.IsLoaded()) - return false; - if (!x30_miniMapSamus.IsLoaded()) - return false; - if (!x3c_hintBeacon.IsLoaded()) - return false; - x4_loadPhase = ELoadPhase::LoadUniverse; - case ELoadPhase::LoadUniverse: - if (!x8_mapu.IsLoaded()) - return false; - x14_dummyWorlds.resize(x8_mapu->GetNumMapWorldDatas()); - SetCurWorldAssetId(x24_world->IGetWorldAssetId()); - x4_loadPhase = ELoadPhase::Done; - case ELoadPhase::Done: - return true; - default: break; - } - return false; -} - -bool CAutoMapper::NotHintNavigating() const -{ - return x1e0_hintSteps.empty(); -} - -bool CAutoMapper::CanLeaveMapScreenInternal(const CStateManager& mgr) const -{ - if (!NotHintNavigating()) +bool CAutoMapper::CheckLoadComplete() { + switch (x4_loadPhase) { + case ELoadPhase::LoadResources: + for (TLockedToken& tex : x48_mapIcons) + if (!tex.IsLoaded()) return false; - if (IsRenderStateInterpolating()) - return false; - if (IsInMapperState(EAutoMapperState::MapScreenUniverse)) - return true; - if (x24_world != mgr.GetWorld()) - return false; - if (IsInMapperState(EAutoMapperState::MapScreen)) - return true; - return false; -} - -void CAutoMapper::LeaveMapScreen(const CStateManager& mgr) -{ - if (x1c0_nextState == EAutoMapperState::MapScreenUniverse) - { - xa8_renderStates[1].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth(); - xa8_renderStates[1].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth(); - xa8_renderStates[0].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth(); - xa8_renderStates[0].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth(); - SetupMiniMapWorld(mgr); - } - else - { - x328_ = 2; - xa8_renderStates[1] = xa8_renderStates[0]; - xa8_renderStates[2] = xa8_renderStates[1]; - xa0_curAreaId = x24_world->IGetCurrentAreaId(); - xa8_renderStates[1].x20_areaPoint = GetAreaPointOfInterest(mgr, xa0_curAreaId); - xa8_renderStates[1].x4c_pointEase = SAutoMapperRenderState::Ease::Linear; - xa8_renderStates[1].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth(); - xa8_renderStates[1].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth(); - xa8_renderStates[1].x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; - xa8_renderStates[1].x54_depth2Ease = SAutoMapperRenderState::Ease::Linear; - ResetInterpolationTimer(0.25f); - } -} - -void CAutoMapper::SetupMiniMapWorld(const CStateManager& mgr) -{ - const CWorld& wld = *mgr.GetWorld(); - const_cast(wld.GetMapWorld())->SetWhichMapAreasLoaded(wld, wld.GetCurrentAreaId(), 3); - x328_ = 3; -} - -bool CAutoMapper::HasCurrentMapUniverseWorld() const -{ - CAssetId mlvlId = x24_world->IGetWorldAssetId(); - for (const CMapUniverse::CMapWorldData& wld : *x8_mapu) - if (wld.GetWorldAssetId() == mlvlId) - return true; - return false; -} - -bool CAutoMapper::CheckDummyWorldLoad(const CStateManager& mgr) -{ - const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx); - auto& dummyWorld = x14_dummyWorlds[x9c_worldIdx]; - if (!dummyWorld) - { - x32c_loadingDummyWorld = false; - return false; - } - - if (!dummyWorld->ICheckWorldComplete()) - return true; - - CWorldState& worldState = g_GameState->StateForWorld(dummyWorld->IGetWorldAssetId()); - CMapWorldInfo& mwInfo = *worldState.MapWorldInfo(); - zeus::CVector3f localPoint = mapuWld.GetWorldTransform().inverse() * xa8_renderStates[0].x20_areaPoint; - zeus::CMatrix3f camRot = xa8_renderStates[0].x8_camOrientation.toTransform().buildMatrix3f(); - TAreaId aid = FindClosestVisibleArea(localPoint, zeus::CUnitVector3f(camRot[1]), mgr, *dummyWorld, mwInfo); - if (aid == -1) - { - x32c_loadingDummyWorld = false; - return false; - } - xa0_curAreaId = aid; - - dummyWorld->IMapWorld()->RecalculateWorldSphere(mwInfo, *dummyWorld); - BeginMapperStateTransition(EAutoMapperState::MapScreen, mgr); - x32c_loadingDummyWorld = false; + if (!x30_miniMapSamus.IsLoaded()) + return false; + if (!x3c_hintBeacon.IsLoaded()) + return false; + x4_loadPhase = ELoadPhase::LoadUniverse; + case ELoadPhase::LoadUniverse: + if (!x8_mapu.IsLoaded()) + return false; + x14_dummyWorlds.resize(x8_mapu->GetNumMapWorldDatas()); + SetCurWorldAssetId(x24_world->IGetWorldAssetId()); + x4_loadPhase = ELoadPhase::Done; + case ELoadPhase::Done: return true; + default: + break; + } + return false; } -void CAutoMapper::UpdateHintNavigation(float dt, const CStateManager& mgr) -{ - SAutoMapperHintStep& nextStep = x1e0_hintSteps.front(); - bool oldProcessing = nextStep.x8_processing; - nextStep.x8_processing = true; - switch (nextStep.x0_type) - { - case SAutoMapperHintStep::Type::PanToArea: - { - if (x24_world->IGetMapWorld()->GetMapArea(nextStep.x4_areaId)) - { - xa8_renderStates[2] = xa8_renderStates[0]; - xa8_renderStates[1].x20_areaPoint = GetAreaPointOfInterest(mgr, nextStep.x4_areaId); - xa8_renderStates[1].ResetInterpolation(); - ResetInterpolationTimer(2.f * g_tweakAutoMapper->GetHintPanTime()); - x1e0_hintSteps.pop_front(); - } - break; - } - case SAutoMapperHintStep::Type::PanToWorld: - { - const CMapUniverse::CMapWorldData& mwData = x8_mapu->GetMapWorldDataByWorldId(nextStep.x4_worldId); - xa8_renderStates[2] = xa8_renderStates[0]; - xa8_renderStates[1].x20_areaPoint = mwData.GetWorldCenterPoint(); - xa8_renderStates[1].ResetInterpolation(); - ResetInterpolationTimer(2.f * g_tweakAutoMapper->GetHintPanTime()); - x1e0_hintSteps.pop_front(); - break; - } - case SAutoMapperHintStep::Type::SwitchToUniverse: - { - if (HasCurrentMapUniverseWorld()) - { - BeginMapperStateTransition(EAutoMapperState::MapScreenUniverse, mgr); - x1e0_hintSteps.pop_front(); - } - else - { - x1e0_hintSteps.clear(); - } - break; - } - case SAutoMapperHintStep::Type::SwitchToWorld: - { - x1e0_hintSteps.pop_front(); - x32c_loadingDummyWorld = true; - if (CheckDummyWorldLoad(mgr)) - break; - x1e0_hintSteps.clear(); - break; - } - case SAutoMapperHintStep::Type::ShowBeacon: - { - if (!oldProcessing) - { - if (xa0_curAreaId == mgr.GetNextAreaId() && x24_world == mgr.GetWorld()) - CSfxManager::SfxStart(SFXui_show_local_beacon, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - else - CSfxManager::SfxStart(SFXui_show_remote_beacon, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - nextStep.x4_float = std::max(0.f, nextStep.x4_float - dt); - for (SAutoMapperHintLocation& loc : x1f8_hintLocations) - { - if (x24_world->IGetWorldAssetId() == loc.x8_worldId && xa0_curAreaId == loc.xc_areaId) - { - nextStep.x4_float = 1.f - std::min(nextStep.x4_float / 0.5f, 1.f); - break; - } - } - if (nextStep.x4_float != 0.f) - break; - x1e0_hintSteps.pop_front(); - break; - } - case SAutoMapperHintStep::Type::ZoomOut: - { - xa8_renderStates[2] = xa8_renderStates[0]; - xa8_renderStates[1].x18_camDist = g_tweakAutoMapper->GetMaxCamDist(); - xa8_renderStates[1].ResetInterpolation(); - xa8_renderStates[1].x48_camEase = SAutoMapperRenderState::Ease::Linear; - ResetInterpolationTimer(0.5f); - x1e0_hintSteps.pop_front(); - break; - } - case SAutoMapperHintStep::Type::ZoomIn: - { - xa8_renderStates[2] = xa8_renderStates[0]; - xa8_renderStates[1].x18_camDist = g_tweakAutoMapper->GetCamDist(); - xa8_renderStates[1].ResetInterpolation(); - xa8_renderStates[1].x48_camEase = SAutoMapperRenderState::Ease::Linear; - ResetInterpolationTimer(0.5f); - x1e0_hintSteps.pop_front(); - break; - } - default: break; - } +bool CAutoMapper::NotHintNavigating() const { return x1e0_hintSteps.empty(); } + +bool CAutoMapper::CanLeaveMapScreenInternal(const CStateManager& mgr) const { + if (!NotHintNavigating()) + return false; + if (IsRenderStateInterpolating()) + return false; + if (IsInMapperState(EAutoMapperState::MapScreenUniverse)) + return true; + if (x24_world != mgr.GetWorld()) + return false; + if (IsInMapperState(EAutoMapperState::MapScreen)) + return true; + return false; } -bool CAutoMapper::CanLeaveMapScreen(const CStateManager& mgr) const -{ - return x328_ == 3 && CanLeaveMapScreenInternal(mgr); -} - -void CAutoMapper::SetCurWorldAssetId(CAssetId mlvlId) -{ - u32 numWorlds = x8_mapu->GetNumMapWorldDatas(); - for (u32 i=0 ; iGetMapWorldData(i).GetWorldAssetId() == mlvlId) - { - x9c_worldIdx = i; - break; - } -} - -void CAutoMapper::BeginMapperStateTransition(EAutoMapperState state, const CStateManager& mgr) -{ - if (state == x1c0_nextState) - return; - if ((state == EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) || - (state != EAutoMapperState::MiniMap && x1c0_nextState == EAutoMapperState::MiniMap)) - CSfxManager::KillAll(CSfxManager::ESfxChannels::PauseScreen); - - x1bc_state = x1c0_nextState; - x1c0_nextState = state; - xa8_renderStates[2] = xa8_renderStates[0]; +void CAutoMapper::LeaveMapScreen(const CStateManager& mgr) { + if (x1c0_nextState == EAutoMapperState::MapScreenUniverse) { + xa8_renderStates[1].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth(); + xa8_renderStates[1].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth(); + xa8_renderStates[0].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth(); + xa8_renderStates[0].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth(); + SetupMiniMapWorld(mgr); + } else { + x328_ = 2; xa8_renderStates[1] = xa8_renderStates[0]; - - if (x1bc_state == EAutoMapperState::MiniMap && state == EAutoMapperState::MapScreen) - { - xa8_renderStates[1] = BuildMapScreenWorldRenderState(mgr, - xa8_renderStates[0].x8_camOrientation, xa0_curAreaId, false); - ResetInterpolationTimer(g_tweakAutoMapper->GetOpenMapScreenTime()); - } - else if (x1bc_state == EAutoMapperState::MapScreen && state == EAutoMapperState::MiniMap) - { - xa0_curAreaId = x24_world->IGetCurrentAreaId(); - xa8_renderStates[1] = BuildMiniMapWorldRenderState(mgr, - xa8_renderStates[0].x8_camOrientation, xa0_curAreaId); - ResetInterpolationTimer(g_tweakAutoMapper->GetCloseMapScreenTime()); - x1f8_hintLocations.clear(); - } - else if (x1bc_state == EAutoMapperState::MapScreen && state == EAutoMapperState::MapScreenUniverse) - { - CSfxManager::SfxStart(SFXui_map_to_universe, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - xa8_renderStates[1] = BuildMapScreenUniverseRenderState(mgr, - xa8_renderStates[0].x8_camOrientation, xa0_curAreaId); - TransformRenderStatesWorldToUniverse(); - ResetInterpolationTimer(g_tweakAutoMapper->GetSwitchToFromUniverseTime()); - } - else if (x1bc_state == EAutoMapperState::MapScreenUniverse && state == EAutoMapperState::MapScreen) - { - CSfxManager::SfxStart(SFXui_map_from_universe, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - xa8_renderStates[1] = BuildMapScreenWorldRenderState(mgr, - xa8_renderStates[0].x8_camOrientation, xa0_curAreaId, x1e0_hintSteps.size()); - TransformRenderStateWorldToUniverse(xa8_renderStates[1]); - ResetInterpolationTimer(g_tweakAutoMapper->GetSwitchToFromUniverseTime()); - for (auto& wld : x14_dummyWorlds) - { - if (wld.get() != x24_world || x24_world == mgr.GetWorld()) - wld.reset(); - } - } - else if (x1bc_state == EAutoMapperState::MapScreenUniverse && state == EAutoMapperState::MiniMap) - { - x24_world = mgr.GetWorld(); - xa0_curAreaId = x24_world->IGetCurrentAreaId(); - xa8_renderStates[1] = BuildMiniMapWorldRenderState(mgr, - xa8_renderStates[0].x8_camOrientation, xa0_curAreaId); - SetCurWorldAssetId(x24_world->IGetWorldAssetId()); - TransformRenderStateWorldToUniverse(xa8_renderStates[1]); - ResetInterpolationTimer(g_tweakAutoMapper->GetCloseMapScreenTime()); - x1f8_hintLocations.clear(); - for (auto& wld : x14_dummyWorlds) - { - if (wld.get() != x24_world || x24_world == mgr.GetWorld()) - wld.reset(); - } - } + xa8_renderStates[2] = xa8_renderStates[1]; + xa0_curAreaId = x24_world->IGetCurrentAreaId(); + xa8_renderStates[1].x20_areaPoint = GetAreaPointOfInterest(mgr, xa0_curAreaId); + xa8_renderStates[1].x4c_pointEase = SAutoMapperRenderState::Ease::Linear; + xa8_renderStates[1].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth(); + xa8_renderStates[1].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth(); + xa8_renderStates[1].x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; + xa8_renderStates[1].x54_depth2Ease = SAutoMapperRenderState::Ease::Linear; + ResetInterpolationTimer(0.25f); + } } -void CAutoMapper::CompleteMapperStateTransition(const CStateManager& mgr) -{ - if (x1bc_state == EAutoMapperState::MapScreenUniverse) - TransformRenderStatesUniverseToWorld(); - - if (x1c0_nextState == EAutoMapperState::MapScreen) - { - const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); - x24_world->IGetMapWorld()->RecalculateWorldSphere(mwInfo, *x24_world); - x1d8_flashTimer = 0.f; - x1dc_playerFlashPulse = 0.f; - } - - if (x1c0_nextState == EAutoMapperState::MiniMap) - { - x28_frmeMapScreen = TLockedToken(); - m_frmeInitialized = false; - x2fc_textpane_hint = nullptr; - x300_textpane_instructions = nullptr; - x304_textpane_instructions1 = nullptr; - x308_textpane_instructions2 = nullptr; - x2f8_textpane_areaname = nullptr; - x30c_basewidget_leftPane = nullptr; - x310_basewidget_yButtonPane = nullptr; - x314_basewidget_bottomPane = nullptr; - SetResLockState(x210_lstick, false); - SetResLockState(x25c_cstick, false); - SetResLockState(x2a8_ltrigger, false); - SetResLockState(x2bc_rtrigger, false); - SetResLockState(x2d0_abutton, false); - } - - if (x1c0_nextState == EAutoMapperState::MapScreenUniverse && x328_ == 1) - LeaveMapScreen(mgr); - - x1bc_state = x1c0_nextState; +void CAutoMapper::SetupMiniMapWorld(const CStateManager& mgr) { + const CWorld& wld = *mgr.GetWorld(); + const_cast(wld.GetMapWorld())->SetWhichMapAreasLoaded(wld, wld.GetCurrentAreaId(), 3); + x328_ = 3; } -void CAutoMapper::ResetInterpolationTimer(float t) -{ - x1c4_interpDur = t; - x1c8_interpTime = 0.f; +bool CAutoMapper::HasCurrentMapUniverseWorld() const { + CAssetId mlvlId = x24_world->IGetWorldAssetId(); + for (const CMapUniverse::CMapWorldData& wld : *x8_mapu) + if (wld.GetWorldAssetId() == mlvlId) + return true; + return false; } -CAutoMapper::SAutoMapperRenderState -CAutoMapper::BuildMiniMapWorldRenderState(const CStateManager& stateMgr, - const zeus::CQuaternion& rot, - TAreaId area) const -{ - zeus::CQuaternion camOrient = GetMiniMapCameraOrientation(stateMgr); - zeus::CQuaternion useOrient = (camOrient.dot(rot) >= 0.f) ? camOrient : camOrient.buildEquivalent(); - SAutoMapperRenderState ret(GetMiniMapViewportSize, useOrient, g_tweakAutoMapper->GetMiniCamDist(), - g_tweakAutoMapper->GetMiniCamAngle(), GetAreaPointOfInterest(stateMgr, area), - GetMapAreaMiniMapDrawDepth(), GetMapAreaMiniMapDrawDepth(), - GetMapAreaMiniMapDrawAlphaSurfaceVisited(stateMgr), - GetMapAreaMiniMapDrawAlphaOutlineVisited(stateMgr), - GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(stateMgr), - GetMapAreaMiniMapDrawAlphaOutlineUnvisited(stateMgr)); - ret.x44_viewportEase = SAutoMapperRenderState::Ease::Out; - ret.x48_camEase = SAutoMapperRenderState::Ease::Out; - ret.x4c_pointEase = SAutoMapperRenderState::Ease::Out; - ret.x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; - ret.x54_depth2Ease = SAutoMapperRenderState::Ease::In; - ret.x58_alphaEase = SAutoMapperRenderState::Ease::Linear; - return ret; +bool CAutoMapper::CheckDummyWorldLoad(const CStateManager& mgr) { + const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx); + auto& dummyWorld = x14_dummyWorlds[x9c_worldIdx]; + if (!dummyWorld) { + x32c_loadingDummyWorld = false; + return false; + } + + if (!dummyWorld->ICheckWorldComplete()) + return true; + + CWorldState& worldState = g_GameState->StateForWorld(dummyWorld->IGetWorldAssetId()); + CMapWorldInfo& mwInfo = *worldState.MapWorldInfo(); + zeus::CVector3f localPoint = mapuWld.GetWorldTransform().inverse() * xa8_renderStates[0].x20_areaPoint; + zeus::CMatrix3f camRot = xa8_renderStates[0].x8_camOrientation.toTransform().buildMatrix3f(); + TAreaId aid = FindClosestVisibleArea(localPoint, zeus::CUnitVector3f(camRot[1]), mgr, *dummyWorld, mwInfo); + if (aid == -1) { + x32c_loadingDummyWorld = false; + return false; + } + xa0_curAreaId = aid; + + dummyWorld->IMapWorld()->RecalculateWorldSphere(mwInfo, *dummyWorld); + BeginMapperStateTransition(EAutoMapperState::MapScreen, mgr); + x32c_loadingDummyWorld = false; + return true; } -CAutoMapper::SAutoMapperRenderState -CAutoMapper::BuildMapScreenWorldRenderState(const CStateManager& mgr, - const zeus::CQuaternion& rot, - TAreaId area, bool doingHint) const -{ - float camDist = doingHint ? g_tweakAutoMapper->GetMaxCamDist() : g_tweakAutoMapper->GetCamDist(); - SAutoMapperRenderState ret(GetMapScreenViewportSize, rot, camDist, - g_tweakAutoMapper->GetCamAngle(), GetAreaPointOfInterest(mgr, area), - GetMapAreaMaxDrawDepth(mgr, area), - GetMapAreaMaxDrawDepth(mgr, area), - g_tweakAutoMapper->GetAlphaSurfaceVisited(), - g_tweakAutoMapper->GetAlphaOutlineVisited(), - g_tweakAutoMapper->GetAlphaSurfaceUnvisited(), - g_tweakAutoMapper->GetAlphaOutlineUnvisited()); - ret.x44_viewportEase = SAutoMapperRenderState::Ease::Out; - ret.x48_camEase = SAutoMapperRenderState::Ease::Linear; - ret.x4c_pointEase = SAutoMapperRenderState::Ease::Out; - ret.x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; - ret.x54_depth2Ease = SAutoMapperRenderState::Ease::Out; - ret.x58_alphaEase = SAutoMapperRenderState::Ease::Linear; - return ret; -} - -CAutoMapper::SAutoMapperRenderState -CAutoMapper::BuildMapScreenUniverseRenderState(const CStateManager& mgr, - const zeus::CQuaternion& rot, - TAreaId area) const -{ - SAutoMapperRenderState ret(GetMapScreenViewportSize, rot, g_tweakAutoMapper->GetUniverseCamDist(), - g_tweakAutoMapper->GetCamAngle(), GetAreaPointOfInterest(mgr, area), - GetMapAreaMaxDrawDepth(mgr, area), - GetMapAreaMaxDrawDepth(mgr, area), - 0.f, 0.f, 0.f, 0.f); - ret.x44_viewportEase = SAutoMapperRenderState::Ease::Out; - ret.x48_camEase = SAutoMapperRenderState::Ease::Linear; - ret.x4c_pointEase = SAutoMapperRenderState::Ease::Out; - ret.x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; - ret.x54_depth2Ease = SAutoMapperRenderState::Ease::Out; - ret.x58_alphaEase = SAutoMapperRenderState::Ease::Linear; - return ret; -} - -void CAutoMapper::LeaveMapScreenState() -{ - SetShouldPanningSoundBePlaying(false); - SetShouldZoomingSoundBePlaying(false); - SetShouldRotatingSoundBePlaying(false); -} - -float CAutoMapper::GetBaseMapScreenCameraMoveSpeed() -{ - return g_tweakAutoMapper->GetBaseMapScreenCameraMoveSpeed(); -} - -float CAutoMapper::GetFinalMapScreenCameraMoveSpeed() const -{ - float ret = GetBaseMapScreenCameraMoveSpeed(); - if (g_tweakAutoMapper->GetScaleMoveSpeedWithCamDist()) - ret = ret * xa8_renderStates[0].x18_camDist / g_tweakAutoMapper->GetCamDist(); - return ret; -} - -void CAutoMapper::ProcessMapRotateInput(const CFinalInput& input, const CStateManager& mgr) -{ - float up = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleUp, input); - float down = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleDown, input); - float left = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleLeft, input); - float right = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleRight, input); - int flags = 0x0; - if (up > 0.f) - flags |= 0x2; - if (down > 0.f) - flags |= 0x1; - if (left > 0.f) - flags |= 0x4; - if (right > 0.f) - flags |= 0x8; - - switch (flags) - { - case 1: // Down - x2e4_lStickPos = 1; - break; - case 2: // Up - x2e4_lStickPos = 5; - break; - case 4: // Left - x2e4_lStickPos = 3; - break; - case 5: // Down-Left - x2e4_lStickPos = 2; - break; - case 6: // Up-Left - x2e4_lStickPos = 4; - break; - case 8: // Right - x2e4_lStickPos = 7; - break; - case 9: // Down-Right - x2e4_lStickPos = 8; - break; - case 10: // Up-Right - x2e4_lStickPos = 6; - break; - default: break; +void CAutoMapper::UpdateHintNavigation(float dt, const CStateManager& mgr) { + SAutoMapperHintStep& nextStep = x1e0_hintSteps.front(); + bool oldProcessing = nextStep.x8_processing; + nextStep.x8_processing = true; + switch (nextStep.x0_type) { + case SAutoMapperHintStep::Type::PanToArea: { + if (x24_world->IGetMapWorld()->GetMapArea(nextStep.x4_areaId)) { + xa8_renderStates[2] = xa8_renderStates[0]; + xa8_renderStates[1].x20_areaPoint = GetAreaPointOfInterest(mgr, nextStep.x4_areaId); + xa8_renderStates[1].ResetInterpolation(); + ResetInterpolationTimer(2.f * g_tweakAutoMapper->GetHintPanTime()); + x1e0_hintSteps.pop_front(); } - - float maxMag = up; - int dirSlot = 0; - if (down > up) - { - maxMag = down; - dirSlot = 1; + break; + } + case SAutoMapperHintStep::Type::PanToWorld: { + const CMapUniverse::CMapWorldData& mwData = x8_mapu->GetMapWorldDataByWorldId(nextStep.x4_worldId); + xa8_renderStates[2] = xa8_renderStates[0]; + xa8_renderStates[1].x20_areaPoint = mwData.GetWorldCenterPoint(); + xa8_renderStates[1].ResetInterpolation(); + ResetInterpolationTimer(2.f * g_tweakAutoMapper->GetHintPanTime()); + x1e0_hintSteps.pop_front(); + break; + } + case SAutoMapperHintStep::Type::SwitchToUniverse: { + if (HasCurrentMapUniverseWorld()) { + BeginMapperStateTransition(EAutoMapperState::MapScreenUniverse, mgr); + x1e0_hintSteps.pop_front(); + } else { + x1e0_hintSteps.clear(); } - if (left > maxMag) - { - maxMag = left; - dirSlot = 2; - } - if (right > maxMag) - { - maxMag = right; - dirSlot = 3; - } - - float dirs[4] = {}; - dirs[dirSlot] = maxMag; - - if (dirs[0] > 0.f || dirs[1] > 0.f || dirs[2] > 0.f || dirs[3] > 0.f) - { - float deltaFrames = input.DeltaTime() * 60.f; - SetShouldRotatingSoundBePlaying(true); - zeus::CEulerAngles eulers(xa8_renderStates[0].x8_camOrientation); - zeus::CRelAngle angX(eulers.x()); - zeus::CRelAngle angZ(eulers.z()); - - float dt = deltaFrames * g_tweakAutoMapper->GetCamRotateDegreesPerFrame(); - - angZ -= zeus::degToRad(dt * dirs[2]); - angZ += zeus::degToRad(dt * dirs[3]); - - angX -= zeus::degToRad(dt * dirs[0]); - angX += zeus::degToRad(dt * dirs[1]); - - float angXDeg = angX.asDegrees(); - if (angXDeg > 180.f) - angXDeg -= 360.f; - angX = zeus::degToRad(zeus::clamp(g_tweakAutoMapper->GetMinCamRotateX(), angXDeg, - g_tweakAutoMapper->GetMaxCamRotateX())); - - zeus::CQuaternion quat; - quat.rotateZ(angZ); - quat.rotateX(angX); - quat.rotateY(0.f); - xa8_renderStates[0].x8_camOrientation = quat; - } - else - { - SetShouldRotatingSoundBePlaying(false); - } -} - -void CAutoMapper::ProcessMapZoomInput(const CFinalInput& input, const CStateManager& mgr) -{ - bool in = ControlMapper::GetDigitalInput(ControlMapper::ECommands::MapZoomIn, input); - bool out = ControlMapper::GetDigitalInput(ControlMapper::ECommands::MapZoomOut, input); - - EZoomState nextZoomState = EZoomState::None; - switch (x324_zoomState) - { - case EZoomState::None: - if (in) - nextZoomState = EZoomState::In; - else if (out) - nextZoomState = EZoomState::Out; - break; - case EZoomState::In: - if (in) - nextZoomState = EZoomState::In; - else if (out) - nextZoomState = EZoomState::Out; - break; - case EZoomState::Out: - if (in) - nextZoomState = EZoomState::In; - else if (out) - nextZoomState = EZoomState::Out; - break; - default: break; - } - - x324_zoomState = nextZoomState; - float delta = input.DeltaTime() * 60.f * (x1bc_state == EAutoMapperState::MapScreen ? 1.f : 4.f) * - g_tweakAutoMapper->GetCamZoomUnitsPerFrame(); - float oldDist = xa8_renderStates[0].x18_camDist; - if (x324_zoomState == EZoomState::In) - { - xa8_renderStates[0].x18_camDist = - GetClampedMapScreenCameraDistance(xa8_renderStates[0].x18_camDist - delta); - x2f0_rTriggerPos = 1; - x324_zoomState = EZoomState::In; - } - else if (x324_zoomState == EZoomState::Out) - { - xa8_renderStates[0].x18_camDist = - GetClampedMapScreenCameraDistance(xa8_renderStates[0].x18_camDist + delta); - x2ec_lTriggerPos = 1; - x324_zoomState = EZoomState::Out; - } - - if (oldDist == xa8_renderStates[0].x18_camDist) - SetShouldZoomingSoundBePlaying(false); - else - SetShouldZoomingSoundBePlaying(true); -} - -void CAutoMapper::ProcessMapPanInput(const CFinalInput& input, const CStateManager& mgr) -{ - float forward = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveForward, input); - float back = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveBack, input); - float left = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveLeft, input); - float right = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveRight, input); - zeus::CTransform camRot = xa8_renderStates[0].x8_camOrientation.toTransform(); - if (forward > 0.f || back > 0.f || left > 0.f || right > 0.f) - { - float deltaFrames = 60.f * input.DeltaTime(); - float speed = GetFinalMapScreenCameraMoveSpeed(); - int flags = 0x0; - if (forward > 0.f) - flags |= 0x1; - if (back > 0.f) - flags |= 0x2; - if (left > 0.f) - flags |= 0x4; - if (right > 0.f) - flags |= 0x8; - - switch (flags) - { - case 1: // Forward - x2e8_rStickPos = 1; - break; - case 2: // Back - x2e8_rStickPos = 5; - break; - case 4: // Left - x2e8_rStickPos = 3; - break; - case 5: // Forward-Left - x2e8_rStickPos = 2; - break; - case 6: // Back-Left - x2e8_rStickPos = 4; - break; - case 8: // Right - x2e8_rStickPos = 7; - break; - case 9: // Forward-Right - x2e8_rStickPos = 8; - break; - case 10: // Back-Right - x2e8_rStickPos = 6; - break; - default: break; - } - - zeus::CVector3f dirVec(right - left, 0.f, forward - back); - zeus::CVector3f deltaVec = camRot * (dirVec * deltaFrames * speed); - zeus::CVector3f newPoint = xa8_renderStates[0].x20_areaPoint + deltaVec; - if (deltaVec.magnitude() > input.DeltaTime()) - SetShouldPanningSoundBePlaying(true); - else - SetShouldPanningSoundBePlaying(false); - - if (x1bc_state == EAutoMapperState::MapScreen) - { - xa8_renderStates[0].x20_areaPoint = - x24_world->IGetMapWorld()->ConstrainToWorldVolume(newPoint, camRot.basis[1]); - } - else - { - zeus::CVector3f localPoint = newPoint - x8_mapu->GetMapUniverseCenterPoint(); - if (localPoint.magnitude() > x8_mapu->GetMapUniverseRadius()) - newPoint = x8_mapu->GetMapUniverseCenterPoint() + localPoint.normalized() * x8_mapu->GetMapUniverseRadius(); - xa8_renderStates[0].x20_areaPoint = newPoint; - } - } - else - { - SetShouldPanningSoundBePlaying(false); - float speed = g_tweakAutoMapper->GetCamPanUnitsPerFrame() * GetBaseMapScreenCameraMoveSpeed(); - if (x1bc_state == EAutoMapperState::MapScreen) - { - const CMapArea* area = x24_world->IGetMapWorld()->GetMapArea(xa0_curAreaId); - zeus::CVector3f worldPoint = area->GetAreaPostTransform(*x24_world, xa0_curAreaId) * area->GetAreaCenterPoint(); - zeus::CVector3f viewPoint = worldPoint - xa8_renderStates[0].x20_areaPoint; - if (viewPoint.magnitude() < speed) - xa8_renderStates[0].x20_areaPoint = worldPoint; - else - xa8_renderStates[0].x20_areaPoint += viewPoint.normalized() * speed; - } - else - { - std::pair areas = FindClosestVisibleWorld(xa8_renderStates[0].x20_areaPoint, camRot.basis[1], mgr); - const zeus::CTransform& hex = x8_mapu->GetMapWorldData(areas.first).GetMapAreaData(areas.second); - zeus::CVector3f areaToHex = hex.origin - xa8_renderStates[0].x20_areaPoint; - if (areaToHex.magnitude() < speed) - xa8_renderStates[0].x20_areaPoint = hex.origin; - else - xa8_renderStates[0].x20_areaPoint += areaToHex.normalized() * speed; - } - } -} - -void CAutoMapper::SetShouldPanningSoundBePlaying(bool b) -{ - if (b) - { - if (!x1cc_panningSfx) - x1cc_panningSfx = CSfxManager::SfxStart(SFXui_map_pan, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(x1cc_panningSfx); - x1cc_panningSfx.reset(); - } -} - -void CAutoMapper::SetShouldZoomingSoundBePlaying(bool b) -{ - if (b) - { - if (!x1d4_zoomingSfx) - x1d4_zoomingSfx = CSfxManager::SfxStart(SFXui_map_zoom, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(x1d4_zoomingSfx); - x1d4_zoomingSfx.reset(); - } -} - -void CAutoMapper::SetShouldRotatingSoundBePlaying(bool b) -{ - if (b) - { - if (!x1d0_rotatingSfx) - x1d0_rotatingSfx = CSfxManager::SfxStart(SFXui_map_rotate, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(x1d0_rotatingSfx); - x1d0_rotatingSfx.reset(); - } -} - -void CAutoMapper::ProcessMapScreenInput(const CFinalInput& input, const CStateManager& mgr) -{ - zeus::CMatrix3f camRot = xa8_renderStates[0].x8_camOrientation.toTransform().buildMatrix3f(); - if (x1bc_state == EAutoMapperState::MapScreen) - { - if (input.PA() && x328_ == 0 && HasCurrentMapUniverseWorld()) - BeginMapperStateTransition(EAutoMapperState::MapScreenUniverse, mgr); - } - else if (x1bc_state == EAutoMapperState::MapScreenUniverse && input.PA()) - { - const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx); - zeus::CVector3f pointLocal = mapuWld.GetWorldTransform().inverse() * xa8_renderStates[0].x20_areaPoint; - if (mapuWld.GetWorldAssetId() != g_GameState->CurrentWorldAssetId()) - { - x32c_loadingDummyWorld = true; - CheckDummyWorldLoad(mgr); - } - else - { - x24_world = mgr.GetWorld(); - CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); - xa0_curAreaId = FindClosestVisibleArea(pointLocal, zeus::CUnitVector3f(camRot[1]), mgr, *x24_world, mwInfo); - BeginMapperStateTransition(EAutoMapperState::MapScreen, mgr); - } - } - - x2f4_aButtonPos = 0; - if (input.PA()) - x2f4_aButtonPos = 1; - - if (IsInMapperState(EAutoMapperState::MapScreen) || IsInMapperState(EAutoMapperState::MapScreenUniverse)) - { - x2e4_lStickPos = 0; - x2e8_rStickPos = 0; - x2ec_lTriggerPos = 0; - x2f0_rTriggerPos = 0; - ProcessMapRotateInput(input, mgr); - ProcessMapZoomInput(input, mgr); - ProcessMapPanInput(input, mgr); - } -} - -zeus::CQuaternion CAutoMapper::GetMiniMapCameraOrientation(const CStateManager& stateMgr) const -{ - const CGameCamera* cam = stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr); - zeus::CEulerAngles camAngles(zeus::CQuaternion(cam->GetTransform().buildMatrix3f())); - float rotMod = -(std::floor(camAngles.z() / (2.f * M_PIF)) * 2.f * M_PIF - camAngles.z()); - if (rotMod < 0.f) - rotMod += 2.f * M_PIF; - - zeus::CQuaternion ret; - ret.rotateZ(rotMod); - ret.rotateX(zeus::degToRad(g_tweakAutoMapper->GetMiniCamXAngle())); - return ret; -} - -zeus::CVector3f CAutoMapper::GetAreaPointOfInterest(const CStateManager&, TAreaId aid) const -{ - const CMapArea* mapa = x24_world->IGetMapWorld()->GetMapArea(aid); - return mapa->GetAreaPostTransform(*x24_world, aid) * mapa->GetAreaCenterPoint(); -} - -TAreaId CAutoMapper::FindClosestVisibleArea(const zeus::CVector3f& point, - const zeus::CUnitVector3f& camDir, const CStateManager& mgr, - const IWorld& wld, const CMapWorldInfo& mwInfo) const -{ - float minDist = 9999.f; - TAreaId closestArea = xa0_curAreaId; - const CMapWorld* mw = wld.IGetMapWorld(); - std::vector areas = mw->GetVisibleAreas(wld, mwInfo); - for (TAreaId areaId : areas) - { - const CMapArea* mapa = mw->GetMapArea(areaId); - zeus::CVector3f xfPoint = mapa->GetAreaPostTransform(wld, areaId) * mapa->GetAreaCenterPoint(); - zeus::CVector3f pointToArea = xfPoint - point; - pointToArea = pointToArea.canBeNormalized() ? - point + (pointToArea.normalized().dot(camDir) * pointToArea.magnitude()) * camDir : point; - pointToArea -= xfPoint; - float dist = pointToArea.magnitude(); - if (dist < minDist) - { - minDist = dist; - closestArea = areaId; - } - } - return closestArea; -} - -std::pair -CAutoMapper::FindClosestVisibleWorld(const zeus::CVector3f& point, - const zeus::CUnitVector3f& camDir, - const CStateManager& mgr) const -{ - float minDist = 29999.f; - std::pair closestWorld = {x9c_worldIdx, xa0_curAreaId}; - for (u32 w=0 ; wGetNumMapWorldDatas() ; ++w) - { - const CMapUniverse::CMapWorldData& mwData = x8_mapu->GetMapWorldData(w); - const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(mwData.GetWorldAssetId()).MapWorldInfo(); - if (!mwInfo.IsAnythingSet()) - continue; - for (u32 i=0 ; iGetMiniMapViewportWidth()), - int(scaleY * g_tweakAutoMapper->GetMiniMapViewportHeight())}; -} - -zeus::CVector2i CAutoMapper::GetMapScreenViewportSize() -{ - return {int(g_Viewport.x8_width), int(g_Viewport.xc_height)}; -} - -float CAutoMapper::GetMapAreaMaxDrawDepth(const CStateManager&, TAreaId aid) const -{ - return x24_world->IGetMapWorld()->GetCurrentMapAreaDepth(*x24_world, aid); -} - -float CAutoMapper::GetMapAreaMiniMapDrawAlphaSurfaceVisited(const CStateManager& stateMgr) -{ - float mapAlphaInterp = g_tweakGui->GetMapAlphaInterpolant(); - return g_tweakAutoMapper->GetMiniAlphaSurfaceVisited() * (1.f - mapAlphaInterp) * - stateMgr.Player()->GetGunAlpha() + mapAlphaInterp; -} - -float CAutoMapper::GetMapAreaMiniMapDrawAlphaOutlineVisited(const CStateManager& stateMgr) -{ - float mapAlphaInterp = g_tweakGui->GetMapAlphaInterpolant(); - return g_tweakAutoMapper->GetMiniAlphaOutlineVisited() * (1.f - mapAlphaInterp) * - stateMgr.Player()->GetGunAlpha() + mapAlphaInterp; -} - -float CAutoMapper::GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(const CStateManager& stateMgr) -{ - float mapAlphaInterp = g_tweakGui->GetMapAlphaInterpolant(); - return g_tweakAutoMapper->GetMiniAlphaSurfaceUnvisited() * (1.f - mapAlphaInterp) * - stateMgr.Player()->GetGunAlpha() + mapAlphaInterp; -} - -float CAutoMapper::GetMapAreaMiniMapDrawAlphaOutlineUnvisited(const CStateManager& stateMgr) -{ - float mapAlphaInterp = g_tweakGui->GetMapAlphaInterpolant(); - return g_tweakAutoMapper->GetMiniAlphaOutlineUnvisited() * (1.f - mapAlphaInterp) * - stateMgr.Player()->GetGunAlpha() + mapAlphaInterp; -} - -float CAutoMapper::GetDesiredMiniMapCameraDistance(const CStateManager& mgr) const -{ - const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); - const CMapWorld* mw = x24_world->IGetMapWorld(); - zeus::CAABox aabb; - const IGameArea* area = x24_world->IGetAreaAlways(xa0_curAreaId); - const CMapArea* mapa = mw->GetMapArea(xa0_curAreaId); - bool oneMiniMapArea = g_tweakAutoMapper->GetShowOneMiniMapArea(); - for (int i = -1 ; i < (oneMiniMapArea ? 0 : int(area->IGetNumAttachedAreas())) ; ++i) - { - TAreaId aid = i == -1 ? xa0_curAreaId : area->IGetAttachedAreaId(i); - const CMapArea* attMapa = mw->GetMapArea(aid); - if (attMapa->GetIsVisibleToAutoMapper(mwInfo.IsWorldVisible(aid), mwInfo.IsAreaVisible(aid))) - { - zeus::CAABox areaAABB = - attMapa->GetBoundingBox().getTransformedAABox(attMapa->GetAreaPostTransform(*x24_world, aid)); - aabb.accumulateBounds(areaAABB.min); - aabb.accumulateBounds(areaAABB.max); - } - } - - zeus::CVector3f xfPoint = mapa->GetAreaPostTransform(*x24_world, xa0_curAreaId) * mapa->GetAreaCenterPoint(); - zeus::CVector3f maxMargin; - maxMargin.x() = std::max(xfPoint.x() - aabb.min.x(), aabb.max.x() - xfPoint.x()); - maxMargin.y() = std::max(xfPoint.y() - aabb.min.y(), aabb.max.y() - xfPoint.y()); - maxMargin.z() = std::max(xfPoint.z() - aabb.min.z(), aabb.max.z() - xfPoint.z()); - zeus::CVector3f extent = mapa->GetBoundingBox().max - mapa->GetBoundingBox().min; - - return (0.5f * (0.5f * extent.magnitude()) + 0.5f * maxMargin.magnitude()) * - g_tweakAutoMapper->GetMiniMapCamDistScale() * - std::tan(M_PIF / 2.f - 0.5f * 2.f * M_PIF * (xa8_renderStates[0].x1c_camAngle / 360.f)); -} - -float CAutoMapper::GetClampedMapScreenCameraDistance(float v) -{ - if (x1bc_state == EAutoMapperState::MapScreenUniverse) - return zeus::clamp(g_tweakAutoMapper->GetMinUniverseCamDist(), v, - g_tweakAutoMapper->GetMaxUniverseCamDist()); - return zeus::clamp(g_tweakAutoMapper->GetMinCamDist(), v, - g_tweakAutoMapper->GetMaxCamDist()); -} - -void CAutoMapper::UnmuteAllLoopedSounds() -{ - CSfxManager::SfxVolume(x1cc_panningSfx, 1.f); - CSfxManager::SfxVolume(x1d0_rotatingSfx, 1.f); - CSfxManager::SfxVolume(x1d4_zoomingSfx, 1.f); -} - -void CAutoMapper::ProcessControllerInput(const CFinalInput& input, CStateManager& mgr) -{ - if (!IsRenderStateInterpolating()) - { - if (IsInMapperState(EAutoMapperState::MapScreen) || IsInMapperState(EAutoMapperState::MapScreenUniverse)) - { - if (x32c_loadingDummyWorld) - CheckDummyWorldLoad(mgr); - else if (x1e0_hintSteps.size()) - UpdateHintNavigation(input.DeltaTime(), mgr); - else if (x328_ == 0) - ProcessMapScreenInput(input, mgr); - } - } - - zeus::CMatrix3f camRot = xa8_renderStates[0].x8_camOrientation.toTransform().buildMatrix3f(); - if (IsInMapperState(EAutoMapperState::MapScreen)) - { - CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); - TAreaId aid = FindClosestVisibleArea(xa8_renderStates[0].x20_areaPoint, camRot[1], mgr, *x24_world, mwInfo); - if (aid != xa0_curAreaId) - { - xa0_curAreaId = aid; - xa8_renderStates[0].x2c_drawDepth1 = GetMapAreaMaxDrawDepth(mgr, xa0_curAreaId); - xa8_renderStates[0].x30_drawDepth2 = GetMapAreaMaxDrawDepth(mgr, xa0_curAreaId); - } - } - else if (IsInMapperState(EAutoMapperState::MapScreenUniverse)) - { - u32 oldWldIdx = x9c_worldIdx; - if (x1e0_hintSteps.size()) - { - SAutoMapperHintStep& nextStep = x1e0_hintSteps.front(); - if (nextStep.x0_type == SAutoMapperHintStep::Type::PanToWorld || - nextStep.x0_type == SAutoMapperHintStep::Type::SwitchToWorld) - { - SetCurWorldAssetId(nextStep.x4_worldId); - } - else - { - std::pair wld = FindClosestVisibleWorld(xa8_renderStates[0].x20_areaPoint, - camRot[1], mgr); - x9c_worldIdx = wld.first; - } - } - else - { - std::pair wld = FindClosestVisibleWorld(xa8_renderStates[0].x20_areaPoint, - camRot[1], mgr); - x9c_worldIdx = wld.first; - } - - if (x9c_worldIdx != oldWldIdx) - { - CAssetId curMlvl = g_GameState->CurrentWorldAssetId(); - for (u32 i=0 ; iGetMapWorldData(i); - if (i == x9c_worldIdx && curMlvl != mwData.GetWorldAssetId()) - { - if (g_ResFactory->CanBuild(SObjectTag{FOURCC('MLVL'), mwData.GetWorldAssetId()})) - wld = std::make_unique(mwData.GetWorldAssetId(), true); - } - else - { - wld.reset(); - } - } - x24_world = (curMlvl == x8_mapu->GetMapWorldData(x9c_worldIdx).GetWorldAssetId()) ? mgr.GetWorld() : nullptr; - } - } - - if (x300_textpane_instructions) - { - if (x78_areaHintDesc.IsLoaded()) - { - x2fc_textpane_hint->TextSupport().SetText(x78_areaHintDesc->GetString(0)); - x304_textpane_instructions1->TextSupport().SetText(u""); - x300_textpane_instructions->TextSupport().SetText(u""); - x308_textpane_instructions2->TextSupport().SetText(u""); - } - else - { - x2fc_textpane_hint->TextSupport().SetText(u""); - std::u16string str = hecl::UTF8ToChar16( - hecl::Format("&image=SI,0.6,1.0,%8.8X;", u32(g_tweakPlayerRes->x24_lStick[x2e4_lStickPos].Value()))); - str += g_MainStringTable->GetString(46); // Rotate - x300_textpane_instructions->TextSupport().SetText(str); - str = hecl::UTF8ToChar16( - hecl::Format("&image=SI,0.6,1.0,%8.8X;", u32(g_tweakPlayerRes->x4c_cStick[x2e8_rStickPos].Value()))); - str += g_MainStringTable->GetString(47); // Move - x304_textpane_instructions1->TextSupport().SetText(str); - str = hecl::UTF8ToChar16( - hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x74_lTrigger[x2ec_lTriggerPos].Value()))); - str += g_MainStringTable->GetString(48); // Zoom - str += hecl::UTF8ToChar16( - hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x80_rTrigger[x2f0_rTriggerPos].Value()))); - x308_textpane_instructions2->TextSupport().SetText(str); - } - } - - if (input.PY()) - { - CPersistentOptions& sysOpts = g_GameState->SystemOptions(); - switch (sysOpts.GetAutoMapperKeyState()) - { - case 0: - sysOpts.SetAutoMapperKeyState(1); - CSfxManager::SfxStart(SFXui_map_screen_key1, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - break; - case 1: - sysOpts.SetAutoMapperKeyState(2); - CSfxManager::SfxStart(SFXui_map_screen_key2, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - break; - case 2: - sysOpts.SetAutoMapperKeyState(0); - CSfxManager::SfxStart(SFXui_map_screen_key0, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - break; - default: break; - } - } - - if (input.PZ() || input.PB()) - { - if (x328_ == 0) - { - if (CanLeaveMapScreenInternal(mgr)) - LeaveMapScreen(mgr); - if (NotHintNavigating()) - { - BeginMapperStateTransition(EAutoMapperState::MapScreenUniverse, mgr); - x328_ = 1; - } - } - } -} - -void CAutoMapper::Update(float dt, const CStateManager& mgr) -{ - if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) - { - x1d8_flashTimer = std::fmod(x1d8_flashTimer + dt, 0.75f); - x1dc_playerFlashPulse = x1d8_flashTimer < 0.375f ? x1d8_flashTimer / 0.375f : (0.75f - x1d8_flashTimer) / 0.375f; - } - - if (!m_frmeInitialized && x28_frmeMapScreen.IsLoaded()) - { - x28_frmeMapScreen->SetMaxAspect(1.78f); - m_frmeInitialized = true; - static_cast(x28_frmeMapScreen->FindWidget("textpane_left"))->TextSupport(). - SetText(g_MainStringTable->GetString(42)); - static_cast(x28_frmeMapScreen->FindWidget("textpane_yicon"))->TextSupport(). - SetText(g_MainStringTable->GetString(43)); - x2fc_textpane_hint = static_cast(x28_frmeMapScreen->FindWidget("textpane_hint")); - x300_textpane_instructions = static_cast(x28_frmeMapScreen->FindWidget("textpane_instructions")); - x304_textpane_instructions1 = static_cast(x28_frmeMapScreen->FindWidget("textpane_instructions1")); - x308_textpane_instructions2 = static_cast(x28_frmeMapScreen->FindWidget("textpane_instructions2")); - CGuiTextPane* mapLegend = static_cast(x28_frmeMapScreen->FindWidget("textpane_mapLegend")); - mapLegend->TextSupport().ClearRenderBuffer(); - mapLegend->TextSupport().SetImageBaseline(true); - mapLegend->TextSupport().SetText(g_MainStringTable->GetString(49)); - x30c_basewidget_leftPane = x28_frmeMapScreen->FindWidget("basewidget_leftPane"); - x310_basewidget_yButtonPane = x28_frmeMapScreen->FindWidget("basewidget_yButtonPane"); - x314_basewidget_bottomPane = x28_frmeMapScreen->FindWidget("basewidget_bottomPane"); - x2f8_textpane_areaname = static_cast(x28_frmeMapScreen->FindWidget("textpane_areaname")); - x2f8_textpane_areaname->SetDepthTest(false); - } - - if (m_frmeInitialized) - { - x28_frmeMapScreen->Update(dt); - CGuiTextPane* right1 = static_cast(x28_frmeMapScreen->FindWidget("textpane_right1")); - std::u16string string; - if (x1bc_state == EAutoMapperState::MapScreenUniverse || - (x1bc_state == EAutoMapperState::MapScreen && HasCurrentMapUniverseWorld())) - string = hecl::UTF8ToChar16(hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x98_aButton[x2f4_aButtonPos].Value()))); - right1->TextSupport().SetText(string); - CGuiTextPane* right = static_cast(x28_frmeMapScreen->FindWidget("textpane_right")); - if (x1bc_state == EAutoMapperState::MapScreenUniverse) - string = g_MainStringTable->GetString(45); - else if (x1bc_state == EAutoMapperState::MapScreen && HasCurrentMapUniverseWorld()) - string = g_MainStringTable->GetString(44); - else - string = std::u16string(); - right->TextSupport().SetText(string); - } - - float dt2 = 2.f * dt; - switch (g_GameState->SystemOptions().GetAutoMapperKeyState()) - { - case 0: // All shown - x318_leftPanePos -= dt2; - x31c_yButtonPanePos -= dt2; - x320_bottomPanePos -= dt2; - break; - case 1: // Left shown - x318_leftPanePos += dt2; - x31c_yButtonPanePos -= dt2; - x320_bottomPanePos -= dt2; - break; - case 2: // All hidden - x318_leftPanePos += dt2; - x31c_yButtonPanePos += dt2; - x320_bottomPanePos += dt2; - break; - default: break; - } - - x318_leftPanePos = std::max(0.f, std::min(x318_leftPanePos, 1.f)); - x31c_yButtonPanePos = std::max(0.f, std::min(x31c_yButtonPanePos, 1.f)); - x320_bottomPanePos = std::max(0.f, std::min(x320_bottomPanePos, 1.f)); - - if (x30c_basewidget_leftPane) - { - float vpAspectRatio = std::max(1.78f, g_Viewport.x8_width / float(g_Viewport.xc_height)); - x30c_basewidget_leftPane->SetLocalTransform( - zeus::CTransform::Translate(x318_leftPanePos * vpAspectRatio * -9.f, 0.f, 0.f) * - x30c_basewidget_leftPane->GetTransform()); - } - - if (x310_basewidget_yButtonPane) - { - x310_basewidget_yButtonPane->SetLocalTransform( - zeus::CTransform::Translate(0.f, 0.f, x31c_yButtonPanePos * -3.5f) * - x310_basewidget_yButtonPane->GetTransform()); - } - - if (x314_basewidget_bottomPane) - { - x314_basewidget_bottomPane->SetLocalTransform( - zeus::CTransform::Translate(0.f, 0.f, x320_bottomPanePos * -7.f) * - x314_basewidget_bottomPane->GetTransform()); - } - - if (IsInMapperState(EAutoMapperState::MiniMap)) - { - xa8_renderStates[0].x8_camOrientation = GetMiniMapCameraOrientation(mgr); - float desiredDist = GetDesiredMiniMapCameraDistance(mgr); - if (std::fabs(xa8_renderStates[0].x18_camDist - desiredDist) < 3.f) - xa8_renderStates[0].x18_camDist = desiredDist; - else if (xa8_renderStates[0].x18_camDist < desiredDist) - xa8_renderStates[0].x18_camDist += 3.f; - else - xa8_renderStates[0].x18_camDist -= 3.f; - TAreaId curAid = x24_world->IGetCurrentAreaId(); - if (curAid != xa0_curAreaId) - { - xa8_renderStates[2] = xa8_renderStates[0]; - xa8_renderStates[1] = xa8_renderStates[0]; - xa4_otherAreaId = xa0_curAreaId; - xa0_curAreaId = curAid; - xa8_renderStates[1].x20_areaPoint = GetAreaPointOfInterest(mgr, xa0_curAreaId); - xa8_renderStates[1].x44_viewportEase = SAutoMapperRenderState::Ease::None; - xa8_renderStates[1].x48_camEase = SAutoMapperRenderState::Ease::None; - xa8_renderStates[1].x4c_pointEase = SAutoMapperRenderState::Ease::InOut; - xa8_renderStates[1].x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; - xa8_renderStates[1].x54_depth2Ease = SAutoMapperRenderState::Ease::Linear; - xa8_renderStates[1].x58_alphaEase = SAutoMapperRenderState::Ease::None; - xa8_renderStates[1].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth(); - xa8_renderStates[1].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth(); - xa8_renderStates[2].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth() - 1.f; - xa8_renderStates[2].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth() - 1.f; - ResetInterpolationTimer(g_tweakAutoMapper->GetHintPanTime()); - } - xa8_renderStates[1].x34_alphaSurfaceVisited = GetMapAreaMiniMapDrawAlphaSurfaceVisited(mgr); - xa8_renderStates[1].x38_alphaOutlineVisited = GetMapAreaMiniMapDrawAlphaOutlineVisited(mgr); - xa8_renderStates[1].x3c_alphaSurfaceUnvisited = GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(mgr); - xa8_renderStates[1].x40_alphaOutlineUnvisited = GetMapAreaMiniMapDrawAlphaOutlineUnvisited(mgr); - } - else - { - if (x1c0_nextState == EAutoMapperState::MiniMap) - { - float desiredDist = GetDesiredMiniMapCameraDistance(mgr); - if (std::fabs(xa8_renderStates[1].x18_camDist - desiredDist) < 3.f) - xa8_renderStates[0].x18_camDist = desiredDist; - else if (xa8_renderStates[1].x18_camDist < desiredDist) - xa8_renderStates[1].x18_camDist += 3.f; - else - xa8_renderStates[1].x18_camDist -= 3.f; - } - else if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap && x24_world) - { - x24_world->IGetMapWorld()->RecalculateWorldSphere( - *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(), *x24_world); - } - } - - if (IsRenderStateInterpolating()) - { - x1c8_interpTime = std::min(x1c8_interpTime + dt, x1c4_interpDur); - SAutoMapperRenderState::InterpolateWithClamp(xa8_renderStates[2], xa8_renderStates[0], xa8_renderStates[1], - x1c8_interpTime / x1c4_interpDur); - if (x1c8_interpTime == x1c4_interpDur && x328_ == 2) - SetupMiniMapWorld(mgr); - } - else if (IsInMapperStateTransition()) - { - CompleteMapperStateTransition(mgr); - } - - CAssetId stringId = x88_mapAreaStringId; - if (IsInMapperState(EAutoMapperState::MapScreenUniverse)) - { - IWorld* wld = x14_dummyWorlds[x9c_worldIdx].get(); - if (wld && wld->ICheckWorldComplete()) - stringId = wld->IGetStringTableAssetId(); - else if (x24_world) - stringId = x24_world->IGetStringTableAssetId(); - } - else if (x24_world) - { - const IGameArea* area = x24_world->IGetAreaAlways(xa0_curAreaId); - const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); - if (mwInfo.IsMapped(xa0_curAreaId) || mwInfo.IsAreaVisted(xa0_curAreaId)) - stringId = area->IGetStringTableAssetId(); - else - stringId = {}; - } - - if (x88_mapAreaStringId != stringId) - { - x88_mapAreaStringId = stringId; - if (x88_mapAreaStringId.IsValid()) - x8c_mapAreaString = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), x88_mapAreaStringId}); - else - x8c_mapAreaString = TLockedToken(); - } - - if (x2f8_textpane_areaname) - { - if (x8c_mapAreaString) - { - if (x8c_mapAreaString.IsLoaded()) - x2f8_textpane_areaname->TextSupport().SetText(x8c_mapAreaString->GetString(0)); - } - else - { - x2f8_textpane_areaname->TextSupport().SetText(u""); - } - } - - if (IsInMapperState(EAutoMapperState::MapScreen)) - { - CAssetId hintDesc = GetAreaHintDescriptionString(x24_world->IGetAreaAlways(xa0_curAreaId)->IGetAreaAssetId()); - if (hintDesc != x74_areaHintDescId) - { - x74_areaHintDescId = hintDesc; - if (x74_areaHintDescId.IsValid()) - x78_areaHintDesc = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), x74_areaHintDescId}); - else - x78_areaHintDesc = TLockedToken(); - } - } - - for (auto& wld : x14_dummyWorlds) - if (wld) - wld->ICheckWorldComplete(); -} - -void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, float alpha) const -{ - alpha *= g_GameState->GameOptions().GetHUDAlpha() / 255.f; - // Blend mode alpha - // Backface cull - float alphaInterp; - if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) - { - alphaInterp = 1.f; - } - else if (IsInMapperState(EAutoMapperState::MiniMap)) - { - alphaInterp = alpha; - } - else if (x1c0_nextState == EAutoMapperState::MiniMap) - { - float t = GetInterp(); - alphaInterp = alpha * t + (1.f - t); - } - else if (x1bc_state == EAutoMapperState::MiniMap) - { - float t = GetInterp(); - alphaInterp = alpha * (1.f - t) + t; - } - else - { - alphaInterp = 1.f; - } - - zeus::CVector2i vp = xa8_renderStates[0].GetViewportSize(); - float aspect = vp.x / float(vp.y); - if (aspect > 1.78f) - aspect = 1.78f; - float yScale = xa8_renderStates[0].x18_camDist / - std::tan(M_PIF / 2.f - 0.5f * 2.f * M_PIF * (xa8_renderStates[0].x1c_camAngle / 360.f)); - float xScale = yScale * aspect; - zeus::CTransform camXf(xa8_renderStates[0].x8_camOrientation, xa8_renderStates[0].x20_areaPoint); - zeus::CTransform distScale = zeus::CTransform::Scale(1.f / xScale, 0.001f, 1.f / yScale); - zeus::CTransform tweakScale = zeus::CTransform::Scale(g_tweakAutoMapper->GetMapPlaneScaleX(), 0.f, - g_tweakAutoMapper->GetMapPlaneScaleZ()); - zeus::CTransform planeXf = xf * tweakScale * distScale * camXf.inverse(); - - float universeInterp = 0.f; - if (x1c0_nextState == EAutoMapperState::MapScreenUniverse) - { - if (x1bc_state == EAutoMapperState::MapScreenUniverse) - universeInterp = 1.f; - else - universeInterp = GetInterp(); - } - else if (x1bc_state == EAutoMapperState::MapScreenUniverse) - { - universeInterp = 1.f - GetInterp(); - } - - zeus::CTransform preXf; - if (x1bc_state == EAutoMapperState::MapScreenUniverse || x1c0_nextState == EAutoMapperState::MapScreenUniverse) - preXf = x8_mapu->GetMapWorldData(x9c_worldIdx).GetWorldTransform(); - - float objectScale = xa8_renderStates[0].x18_camDist / g_tweakAutoMapper->GetMinCamDist(); - float mapAlpha = alphaInterp * (1.f - universeInterp); - - if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) - { - if (universeInterp < 1.f && x24_world) - { - const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); - const CMapWorld* mw = x24_world->IGetMapWorld(); - float hintFlash = 0.f; - if (x1e0_hintSteps.size() && x1e0_hintSteps.front().x0_type == SAutoMapperHintStep::Type::ShowBeacon) - { - if (xa0_curAreaId == mgr.GetNextAreaId() && x24_world == mgr.GetWorld()) - { - float pulseTime = std::fmod(x1e0_hintSteps.front().x4_float * 8.f, 1.f); - hintFlash = 2.f * (pulseTime < 0.5f ? pulseTime : 1.f - pulseTime); - } - else - { - for (const SAutoMapperHintLocation& loc : x1f8_hintLocations) - { - if (x24_world->IGetWorldAssetId() != loc.x8_worldId) - continue; - if (xa0_curAreaId != loc.xc_areaId) - continue; - float pulseTime = std::fmod((1.f - std::max(0.f, (x1e0_hintSteps.front().x4_float - 0.5f) / 0.5f)) * 4.f, 1.f); - hintFlash = 2.f * (pulseTime < 0.5f ? pulseTime : 1.f - pulseTime); - break; - } - } - } - zeus::CTransform modelXf = planeXf * preXf; - CMapWorld::CMapWorldDrawParms parms( - xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp, - xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp, - xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp, - xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, - mapAlpha, 2.f, mgr, modelXf, camXf, *x24_world, - mwInfo, x1dc_playerFlashPulse, hintFlash, objectScale, true); - mw->Draw(parms, xa0_curAreaId, xa0_curAreaId, - xa8_renderStates[0].x2c_drawDepth1, - xa8_renderStates[0].x30_drawDepth2, true); - } - } - else if (IsInMapperState(EAutoMapperState::MiniMap)) - { - const CMapWorld* mw = x24_world->IGetMapWorld(); - const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); - CMapWorld::CMapWorldDrawParms parms( - xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp, - xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp, - xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp, - xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, - mapAlpha, 1.f, mgr, planeXf, camXf, *x24_world, - mwInfo, 0.f, 0.f, objectScale, false); - mw->Draw(parms, xa0_curAreaId, xa4_otherAreaId, - xa8_renderStates[0].x2c_drawDepth1, - xa8_renderStates[0].x30_drawDepth2, false); - } - else - { - const CMapWorld* mw = x24_world->IGetMapWorld(); - const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); - zeus::CTransform modelXf = planeXf * preXf; - CMapWorld::CMapWorldDrawParms parms( - xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp, - xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp, - xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp, - xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, - mapAlpha, 2.f, mgr, modelXf, camXf, *x24_world, - mwInfo, 0.f, 0.f, objectScale, true); - mw->Draw(parms, xa0_curAreaId, xa0_curAreaId, - xa8_renderStates[0].x2c_drawDepth1, - xa8_renderStates[0].x30_drawDepth2, false); - } - - if (universeInterp > 0.f) - { - zeus::CTransform areaXf = mgr.GetWorld()->GetMapWorld()->GetMapArea(mgr.GetNextAreaId())-> - GetAreaPostTransform(*mgr.GetWorld(), mgr.GetNextAreaId()); - const CMapUniverse::CMapWorldData& mwData = - x8_mapu->GetMapWorldDataByWorldId(g_GameState->CurrentWorldAssetId()); - zeus::CTransform universeAreaXf = mwData.GetWorldTransform() * areaXf; - float minMag = FLT_MAX; - int hexIdx = -1; - for (u32 i=0 ; iCurrentWorldAssetId(), - hexIdx, x1dc_playerFlashPulse, mgr, planeXf, camXf); - x8_mapu->Draw(parms, zeus::CVector3f::skZero, 0.f, 0.f); - } - - if (!IsInMapperState(EAutoMapperState::MapScreenUniverse)) - { - zeus::CTransform mapXf = planeXf * preXf; - if (x24_world == mgr.GetWorld()) - { - float func = zeus::clamp(0.f, 0.5f * (1.f + std::sin(5.f * CGraphics::GetSecondsMod900() - (M_PIF / 2.f))), 1.f); - float scale = std::min(0.6f * g_tweakAutoMapper->GetMaxCamDist() / g_tweakAutoMapper->GetMinCamDist(), objectScale); - zeus::CEulerAngles eulers(mgr.GetCameraManager()->GetCurrentCameraTransform(mgr)); - zeus::CRelAngle angle(eulers.z()); - zeus::CTransform playerXf(zeus::CMatrix3f::RotateZ(angle), - CMapArea::GetAreaPostTranslate(*x24_world, mgr.GetNextAreaId()) + mgr.GetPlayer().GetTranslation()); - CGraphics::SetModelMatrix(mapXf * playerXf * zeus::CTransform::Scale(scale * (0.25f * func + 0.75f))); - float alpha; - if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) - alpha = 1.f; - else - alpha = xa8_renderStates[0].x34_alphaSurfaceVisited; - alpha *= mapAlpha; - zeus::CColor modColor = g_tweakAutoMapper->GetMiniMapSamusModColor(); - modColor.a() *= alpha; - CModelFlags flags(5, 0, 8 | 1, modColor); /* Depth GEqual */ - flags.m_extendedShader = EExtendedShader::DepthGEqualNoZWrite; - x30_miniMapSamus->Draw(flags); - } - if (IsInMapperState(EAutoMapperState::MapScreen)) - { - CAssetId wldMlvl = x24_world->IGetWorldAssetId(); - const CMapWorld* mw = x24_world->IGetMapWorld(); - std::vector& hintBeaconFilters = const_cast(*this).m_hintBeaconFilters; - if (hintBeaconFilters.size() < x1f8_hintLocations.size()) - { - hintBeaconFilters.reserve(x1f8_hintLocations.size()); - for (u32 i=hintBeaconFilters.size() ; iGetMapArea(loc.xc_areaId); - if (!mapa) - continue; - zeus::CTransform camRot(camXf.buildMatrix3f(), zeus::CVector3f::skZero); - CGraphics::SetModelMatrix(mapXf * - zeus::CTransform::Translate(mapa->GetAreaPostTransform(*x24_world, loc.xc_areaId).origin) * - zeus::CTransform::Translate(mapa->GetAreaCenterPoint()) * - zeus::CTransform::Scale(objectScale) * camRot); - float beaconAlpha = 0.f; - if (loc.x0_showBeacon == 1) - beaconAlpha = loc.x4_beaconAlpha; - if (beaconAlpha > 0.f) - { - CTexturedQuadFilter::Vert verts[4] = - { - {{-4.f, -8.f, 8.f}, {0.f, 1.f}}, - {{-4.f, -8.f, 0.f}, {0.f, 0.f}}, - {{4.f, -8.f, 8.f}, {1.f, 1.f}}, - {{4.f, -8.f, 0.f}, {1.f, 0.f}} - }; - float alpha = beaconAlpha; - if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) - {} - else - alpha *= xa8_renderStates[0].x34_alphaSurfaceVisited; - alpha *= mapAlpha; - zeus::CColor color = zeus::CColor::skWhite; - color.a() = alpha; - filter.drawVerts(color, verts); - } - } - } - } - - // No zread, no zwrite - // Ambient color white - // Disable all lights - if (m_frmeInitialized) - { - float frmeAlpha = 0.f; - if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) - { - frmeAlpha = 1.f; - } - else - { - if (x1c0_nextState != EAutoMapperState::MiniMap) - { - if (x1c4_interpDur > 0.f) - frmeAlpha = x1c8_interpTime / x1c4_interpDur; - } - else - { - if (x1c4_interpDur > 0.f) - frmeAlpha = x1c8_interpTime / x1c4_interpDur; - frmeAlpha = 1.f - frmeAlpha; - } - } - CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_NEAR); - CGuiWidgetDrawParms parms(frmeAlpha, zeus::CVector3f::skZero); - x28_frmeMapScreen->Draw(parms); - CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_HUD); - } -} - -void CAutoMapper::TransformRenderStatesWorldToUniverse() -{ - const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx); - zeus::CQuaternion rot = zeus::CQuaternion(mapuWld.GetWorldTransform().buildMatrix3f()); - xa8_renderStates[2].x8_camOrientation *= rot; - xa8_renderStates[2].x20_areaPoint = mapuWld.GetWorldTransform() * xa8_renderStates[2].x20_areaPoint; - xa8_renderStates[0].x8_camOrientation *= rot; - xa8_renderStates[0].x20_areaPoint = mapuWld.GetWorldTransform() * xa8_renderStates[0].x20_areaPoint; - xa8_renderStates[1].x8_camOrientation *= rot; - xa8_renderStates[1].x20_areaPoint = mapuWld.GetWorldTransform() * xa8_renderStates[1].x20_areaPoint; -} - -void CAutoMapper::TransformRenderStatesUniverseToWorld() -{ - const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx); - zeus::CTransform inv = mapuWld.GetWorldTransform().inverse(); - zeus::CQuaternion invRot = zeus::CQuaternion(inv.buildMatrix3f()); - xa8_renderStates[2].x8_camOrientation *= invRot; - xa8_renderStates[2].x20_areaPoint = inv * xa8_renderStates[2].x20_areaPoint; - xa8_renderStates[0].x8_camOrientation *= invRot; - xa8_renderStates[0].x20_areaPoint = inv * xa8_renderStates[0].x20_areaPoint; - xa8_renderStates[1].x8_camOrientation *= invRot; - xa8_renderStates[1].x20_areaPoint = inv * xa8_renderStates[1].x20_areaPoint; -} - -void CAutoMapper::TransformRenderStateWorldToUniverse(SAutoMapperRenderState& state) -{ - state.x20_areaPoint = x8_mapu->GetMapWorldData(x9c_worldIdx).GetWorldTransform() * - xa8_renderStates[1].x20_areaPoint; -} - -void CAutoMapper::SetupHintNavigation() -{ - if (!g_GameState->GameOptions().GetIsHintSystemEnabled()) - return; + break; + } + case SAutoMapperHintStep::Type::SwitchToWorld: { + x1e0_hintSteps.pop_front(); + x32c_loadingDummyWorld = true; + if (CheckDummyWorldLoad(mgr)) + break; x1e0_hintSteps.clear(); + break; + } + case SAutoMapperHintStep::Type::ShowBeacon: { + if (!oldProcessing) { + if (xa0_curAreaId == mgr.GetNextAreaId() && x24_world == mgr.GetWorld()) + CSfxManager::SfxStart(SFXui_show_local_beacon, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + else + CSfxManager::SfxStart(SFXui_show_remote_beacon, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + nextStep.x4_float = std::max(0.f, nextStep.x4_float - dt); + for (SAutoMapperHintLocation& loc : x1f8_hintLocations) { + if (x24_world->IGetWorldAssetId() == loc.x8_worldId && xa0_curAreaId == loc.xc_areaId) { + nextStep.x4_float = 1.f - std::min(nextStep.x4_float / 0.5f, 1.f); + break; + } + } + if (nextStep.x4_float != 0.f) + break; + x1e0_hintSteps.pop_front(); + break; + } + case SAutoMapperHintStep::Type::ZoomOut: { + xa8_renderStates[2] = xa8_renderStates[0]; + xa8_renderStates[1].x18_camDist = g_tweakAutoMapper->GetMaxCamDist(); + xa8_renderStates[1].ResetInterpolation(); + xa8_renderStates[1].x48_camEase = SAutoMapperRenderState::Ease::Linear; + ResetInterpolationTimer(0.5f); + x1e0_hintSteps.pop_front(); + break; + } + case SAutoMapperHintStep::Type::ZoomIn: { + xa8_renderStates[2] = xa8_renderStates[0]; + xa8_renderStates[1].x18_camDist = g_tweakAutoMapper->GetCamDist(); + xa8_renderStates[1].ResetInterpolation(); + xa8_renderStates[1].x48_camEase = SAutoMapperRenderState::Ease::Linear; + ResetInterpolationTimer(0.5f); + x1e0_hintSteps.pop_front(); + break; + } + default: + break; + } +} + +bool CAutoMapper::CanLeaveMapScreen(const CStateManager& mgr) const { + return x328_ == 3 && CanLeaveMapScreenInternal(mgr); +} + +void CAutoMapper::SetCurWorldAssetId(CAssetId mlvlId) { + u32 numWorlds = x8_mapu->GetNumMapWorldDatas(); + for (u32 i = 0; i < numWorlds; ++i) + if (x8_mapu->GetMapWorldData(i).GetWorldAssetId() == mlvlId) { + x9c_worldIdx = i; + break; + } +} + +void CAutoMapper::BeginMapperStateTransition(EAutoMapperState state, const CStateManager& mgr) { + if (state == x1c0_nextState) + return; + if ((state == EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) || + (state != EAutoMapperState::MiniMap && x1c0_nextState == EAutoMapperState::MiniMap)) + CSfxManager::KillAll(CSfxManager::ESfxChannels::PauseScreen); + + x1bc_state = x1c0_nextState; + x1c0_nextState = state; + xa8_renderStates[2] = xa8_renderStates[0]; + xa8_renderStates[1] = xa8_renderStates[0]; + + if (x1bc_state == EAutoMapperState::MiniMap && state == EAutoMapperState::MapScreen) { + xa8_renderStates[1] = + BuildMapScreenWorldRenderState(mgr, xa8_renderStates[0].x8_camOrientation, xa0_curAreaId, false); + ResetInterpolationTimer(g_tweakAutoMapper->GetOpenMapScreenTime()); + } else if (x1bc_state == EAutoMapperState::MapScreen && state == EAutoMapperState::MiniMap) { + xa0_curAreaId = x24_world->IGetCurrentAreaId(); + xa8_renderStates[1] = BuildMiniMapWorldRenderState(mgr, xa8_renderStates[0].x8_camOrientation, xa0_curAreaId); + ResetInterpolationTimer(g_tweakAutoMapper->GetCloseMapScreenTime()); x1f8_hintLocations.clear(); - CHintOptions& hintOpts = g_GameState->HintOptions(); - const CHintOptions::SHintState* curHint = hintOpts.GetCurrentDisplayedHint(); - bool navigating = false; - if (curHint && curHint->CanContinue()) - { - navigating = true; - x1e0_hintSteps.push_back({SAutoMapperHintStep::ShowBeacon{}, 0.75f}); - const CGameHintInfo::CGameHint& nextHint = g_MemoryCardSys->GetHints()[hintOpts.GetNextHintIdx()]; - CAssetId curMlvl = x24_world->IGetWorldAssetId(); - for (const CGameHintInfo::SHintLocation& loc : nextHint.GetLocations()) - { - if (loc.x0_mlvlId != curMlvl) - { - x1e0_hintSteps.push_back({SAutoMapperHintStep::SwitchToUniverse{}}); - x1e0_hintSteps.push_back({SAutoMapperHintStep::PanToWorld{}, curMlvl}); - x1e0_hintSteps.push_back({SAutoMapperHintStep::SwitchToWorld{}, curMlvl}); - } - else - { - x1e0_hintSteps.push_back({SAutoMapperHintStep::ZoomOut{}}); - } - x1e0_hintSteps.push_back({SAutoMapperHintStep::PanToArea{}, loc.x8_areaId}); - x1e0_hintSteps.push_back({SAutoMapperHintStep::ZoomIn{}}); - x1e0_hintSteps.push_back({SAutoMapperHintStep::ShowBeacon{}, 1.f}); - x1f8_hintLocations.push_back({0, 0.f, loc.x0_mlvlId, loc.x8_areaId}); - } + } else if (x1bc_state == EAutoMapperState::MapScreen && state == EAutoMapperState::MapScreenUniverse) { + CSfxManager::SfxStart(SFXui_map_to_universe, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + xa8_renderStates[1] = BuildMapScreenUniverseRenderState(mgr, xa8_renderStates[0].x8_camOrientation, xa0_curAreaId); + TransformRenderStatesWorldToUniverse(); + ResetInterpolationTimer(g_tweakAutoMapper->GetSwitchToFromUniverseTime()); + } else if (x1bc_state == EAutoMapperState::MapScreenUniverse && state == EAutoMapperState::MapScreen) { + CSfxManager::SfxStart(SFXui_map_from_universe, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + xa8_renderStates[1] = BuildMapScreenWorldRenderState(mgr, xa8_renderStates[0].x8_camOrientation, xa0_curAreaId, + x1e0_hintSteps.size()); + TransformRenderStateWorldToUniverse(xa8_renderStates[1]); + ResetInterpolationTimer(g_tweakAutoMapper->GetSwitchToFromUniverseTime()); + for (auto& wld : x14_dummyWorlds) { + if (wld.get() != x24_world || x24_world == mgr.GetWorld()) + wld.reset(); } - - for (u32 i=0 ; iGetHints()[i]; - for (const CGameHintInfo::SHintLocation& loc : hint.GetLocations()) - x1f8_hintLocations.push_back({1, 1.f, loc.x0_mlvlId, loc.x8_areaId}); + } else if (x1bc_state == EAutoMapperState::MapScreenUniverse && state == EAutoMapperState::MiniMap) { + x24_world = mgr.GetWorld(); + xa0_curAreaId = x24_world->IGetCurrentAreaId(); + xa8_renderStates[1] = BuildMiniMapWorldRenderState(mgr, xa8_renderStates[0].x8_camOrientation, xa0_curAreaId); + SetCurWorldAssetId(x24_world->IGetWorldAssetId()); + TransformRenderStateWorldToUniverse(xa8_renderStates[1]); + ResetInterpolationTimer(g_tweakAutoMapper->GetCloseMapScreenTime()); + x1f8_hintLocations.clear(); + for (auto& wld : x14_dummyWorlds) { + if (wld.get() != x24_world || x24_world == mgr.GetWorld()) + wld.reset(); } + } } -CAssetId CAutoMapper::GetAreaHintDescriptionString(CAssetId mreaId) -{ - const CHintOptions& hintOpts = g_GameState->HintOptions(); - for (u32 i=0 ; iGetHints()[i]; - for (const CGameHintInfo::SHintLocation& loc : memHint.GetLocations()) - { - if (loc.x4_mreaId != mreaId) - continue; - for (const SAutoMapperHintLocation& hintLoc : x1f8_hintLocations) - { - if (hintLoc.xc_areaId != loc.x8_areaId) - continue; - if (hintLoc.x4_beaconAlpha > 0.f) - return loc.xc_stringId; - } - } - } - return -1; +void CAutoMapper::CompleteMapperStateTransition(const CStateManager& mgr) { + if (x1bc_state == EAutoMapperState::MapScreenUniverse) + TransformRenderStatesUniverseToWorld(); + + if (x1c0_nextState == EAutoMapperState::MapScreen) { + const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); + x24_world->IGetMapWorld()->RecalculateWorldSphere(mwInfo, *x24_world); + x1d8_flashTimer = 0.f; + x1dc_playerFlashPulse = 0.f; + } + + if (x1c0_nextState == EAutoMapperState::MiniMap) { + x28_frmeMapScreen = TLockedToken(); + m_frmeInitialized = false; + x2fc_textpane_hint = nullptr; + x300_textpane_instructions = nullptr; + x304_textpane_instructions1 = nullptr; + x308_textpane_instructions2 = nullptr; + x2f8_textpane_areaname = nullptr; + x30c_basewidget_leftPane = nullptr; + x310_basewidget_yButtonPane = nullptr; + x314_basewidget_bottomPane = nullptr; + SetResLockState(x210_lstick, false); + SetResLockState(x25c_cstick, false); + SetResLockState(x2a8_ltrigger, false); + SetResLockState(x2bc_rtrigger, false); + SetResLockState(x2d0_abutton, false); + } + + if (x1c0_nextState == EAutoMapperState::MapScreenUniverse && x328_ == 1) + LeaveMapScreen(mgr); + + x1bc_state = x1c0_nextState; } -void CAutoMapper::OnNewInGameGuiState(EInGameGuiState state, const CStateManager& mgr) -{ - if (state == EInGameGuiState::MapScreen) - { - MP1::CMain::EnsureWorldPaksReady(); - const CWorld& wld = *mgr.GetWorld(); - const_cast(wld.GetMapWorld())->SetWhichMapAreasLoaded(wld, 0, 9999); - SetupHintNavigation(); - BeginMapperStateTransition(EAutoMapperState::MapScreen, mgr); - x28_frmeMapScreen = g_SimplePool->GetObj("FRME_MapScreen"); - SetResLockState(x210_lstick, true); - SetResLockState(x25c_cstick, true); - SetResLockState(x2a8_ltrigger, true); - SetResLockState(x2bc_rtrigger, true); - SetResLockState(x2d0_abutton, true); +void CAutoMapper::ResetInterpolationTimer(float t) { + x1c4_interpDur = t; + x1c8_interpTime = 0.f; +} + +CAutoMapper::SAutoMapperRenderState CAutoMapper::BuildMiniMapWorldRenderState(const CStateManager& stateMgr, + const zeus::CQuaternion& rot, + TAreaId area) const { + zeus::CQuaternion camOrient = GetMiniMapCameraOrientation(stateMgr); + zeus::CQuaternion useOrient = (camOrient.dot(rot) >= 0.f) ? camOrient : camOrient.buildEquivalent(); + SAutoMapperRenderState ret( + GetMiniMapViewportSize, useOrient, g_tweakAutoMapper->GetMiniCamDist(), g_tweakAutoMapper->GetMiniCamAngle(), + GetAreaPointOfInterest(stateMgr, area), GetMapAreaMiniMapDrawDepth(), GetMapAreaMiniMapDrawDepth(), + GetMapAreaMiniMapDrawAlphaSurfaceVisited(stateMgr), GetMapAreaMiniMapDrawAlphaOutlineVisited(stateMgr), + GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(stateMgr), GetMapAreaMiniMapDrawAlphaOutlineUnvisited(stateMgr)); + ret.x44_viewportEase = SAutoMapperRenderState::Ease::Out; + ret.x48_camEase = SAutoMapperRenderState::Ease::Out; + ret.x4c_pointEase = SAutoMapperRenderState::Ease::Out; + ret.x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; + ret.x54_depth2Ease = SAutoMapperRenderState::Ease::In; + ret.x58_alphaEase = SAutoMapperRenderState::Ease::Linear; + return ret; +} + +CAutoMapper::SAutoMapperRenderState CAutoMapper::BuildMapScreenWorldRenderState(const CStateManager& mgr, + const zeus::CQuaternion& rot, + TAreaId area, bool doingHint) const { + float camDist = doingHint ? g_tweakAutoMapper->GetMaxCamDist() : g_tweakAutoMapper->GetCamDist(); + SAutoMapperRenderState ret(GetMapScreenViewportSize, rot, camDist, g_tweakAutoMapper->GetCamAngle(), + GetAreaPointOfInterest(mgr, area), GetMapAreaMaxDrawDepth(mgr, area), + GetMapAreaMaxDrawDepth(mgr, area), g_tweakAutoMapper->GetAlphaSurfaceVisited(), + g_tweakAutoMapper->GetAlphaOutlineVisited(), g_tweakAutoMapper->GetAlphaSurfaceUnvisited(), + g_tweakAutoMapper->GetAlphaOutlineUnvisited()); + ret.x44_viewportEase = SAutoMapperRenderState::Ease::Out; + ret.x48_camEase = SAutoMapperRenderState::Ease::Linear; + ret.x4c_pointEase = SAutoMapperRenderState::Ease::Out; + ret.x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; + ret.x54_depth2Ease = SAutoMapperRenderState::Ease::Out; + ret.x58_alphaEase = SAutoMapperRenderState::Ease::Linear; + return ret; +} + +CAutoMapper::SAutoMapperRenderState CAutoMapper::BuildMapScreenUniverseRenderState(const CStateManager& mgr, + const zeus::CQuaternion& rot, + TAreaId area) const { + SAutoMapperRenderState ret(GetMapScreenViewportSize, rot, g_tweakAutoMapper->GetUniverseCamDist(), + g_tweakAutoMapper->GetCamAngle(), GetAreaPointOfInterest(mgr, area), + GetMapAreaMaxDrawDepth(mgr, area), GetMapAreaMaxDrawDepth(mgr, area), 0.f, 0.f, 0.f, 0.f); + ret.x44_viewportEase = SAutoMapperRenderState::Ease::Out; + ret.x48_camEase = SAutoMapperRenderState::Ease::Linear; + ret.x4c_pointEase = SAutoMapperRenderState::Ease::Out; + ret.x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; + ret.x54_depth2Ease = SAutoMapperRenderState::Ease::Out; + ret.x58_alphaEase = SAutoMapperRenderState::Ease::Linear; + return ret; +} + +void CAutoMapper::LeaveMapScreenState() { + SetShouldPanningSoundBePlaying(false); + SetShouldZoomingSoundBePlaying(false); + SetShouldRotatingSoundBePlaying(false); +} + +float CAutoMapper::GetBaseMapScreenCameraMoveSpeed() { return g_tweakAutoMapper->GetBaseMapScreenCameraMoveSpeed(); } + +float CAutoMapper::GetFinalMapScreenCameraMoveSpeed() const { + float ret = GetBaseMapScreenCameraMoveSpeed(); + if (g_tweakAutoMapper->GetScaleMoveSpeedWithCamDist()) + ret = ret * xa8_renderStates[0].x18_camDist / g_tweakAutoMapper->GetCamDist(); + return ret; +} + +void CAutoMapper::ProcessMapRotateInput(const CFinalInput& input, const CStateManager& mgr) { + float up = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleUp, input); + float down = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleDown, input); + float left = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleLeft, input); + float right = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleRight, input); + int flags = 0x0; + if (up > 0.f) + flags |= 0x2; + if (down > 0.f) + flags |= 0x1; + if (left > 0.f) + flags |= 0x4; + if (right > 0.f) + flags |= 0x8; + + switch (flags) { + case 1: // Down + x2e4_lStickPos = 1; + break; + case 2: // Up + x2e4_lStickPos = 5; + break; + case 4: // Left + x2e4_lStickPos = 3; + break; + case 5: // Down-Left + x2e4_lStickPos = 2; + break; + case 6: // Up-Left + x2e4_lStickPos = 4; + break; + case 8: // Right + x2e4_lStickPos = 7; + break; + case 9: // Down-Right + x2e4_lStickPos = 8; + break; + case 10: // Up-Right + x2e4_lStickPos = 6; + break; + default: + break; + } + + float maxMag = up; + int dirSlot = 0; + if (down > up) { + maxMag = down; + dirSlot = 1; + } + if (left > maxMag) { + maxMag = left; + dirSlot = 2; + } + if (right > maxMag) { + maxMag = right; + dirSlot = 3; + } + + float dirs[4] = {}; + dirs[dirSlot] = maxMag; + + if (dirs[0] > 0.f || dirs[1] > 0.f || dirs[2] > 0.f || dirs[3] > 0.f) { + float deltaFrames = input.DeltaTime() * 60.f; + SetShouldRotatingSoundBePlaying(true); + zeus::CEulerAngles eulers(xa8_renderStates[0].x8_camOrientation); + zeus::CRelAngle angX(eulers.x()); + zeus::CRelAngle angZ(eulers.z()); + + float dt = deltaFrames * g_tweakAutoMapper->GetCamRotateDegreesPerFrame(); + + angZ -= zeus::degToRad(dt * dirs[2]); + angZ += zeus::degToRad(dt * dirs[3]); + + angX -= zeus::degToRad(dt * dirs[0]); + angX += zeus::degToRad(dt * dirs[1]); + + float angXDeg = angX.asDegrees(); + if (angXDeg > 180.f) + angXDeg -= 360.f; + angX = zeus::degToRad( + zeus::clamp(g_tweakAutoMapper->GetMinCamRotateX(), angXDeg, g_tweakAutoMapper->GetMaxCamRotateX())); + + zeus::CQuaternion quat; + quat.rotateZ(angZ); + quat.rotateX(angX); + quat.rotateY(0.f); + xa8_renderStates[0].x8_camOrientation = quat; + } else { + SetShouldRotatingSoundBePlaying(false); + } +} + +void CAutoMapper::ProcessMapZoomInput(const CFinalInput& input, const CStateManager& mgr) { + bool in = ControlMapper::GetDigitalInput(ControlMapper::ECommands::MapZoomIn, input); + bool out = ControlMapper::GetDigitalInput(ControlMapper::ECommands::MapZoomOut, input); + + EZoomState nextZoomState = EZoomState::None; + switch (x324_zoomState) { + case EZoomState::None: + if (in) + nextZoomState = EZoomState::In; + else if (out) + nextZoomState = EZoomState::Out; + break; + case EZoomState::In: + if (in) + nextZoomState = EZoomState::In; + else if (out) + nextZoomState = EZoomState::Out; + break; + case EZoomState::Out: + if (in) + nextZoomState = EZoomState::In; + else if (out) + nextZoomState = EZoomState::Out; + break; + default: + break; + } + + x324_zoomState = nextZoomState; + float delta = input.DeltaTime() * 60.f * (x1bc_state == EAutoMapperState::MapScreen ? 1.f : 4.f) * + g_tweakAutoMapper->GetCamZoomUnitsPerFrame(); + float oldDist = xa8_renderStates[0].x18_camDist; + if (x324_zoomState == EZoomState::In) { + xa8_renderStates[0].x18_camDist = GetClampedMapScreenCameraDistance(xa8_renderStates[0].x18_camDist - delta); + x2f0_rTriggerPos = 1; + x324_zoomState = EZoomState::In; + } else if (x324_zoomState == EZoomState::Out) { + xa8_renderStates[0].x18_camDist = GetClampedMapScreenCameraDistance(xa8_renderStates[0].x18_camDist + delta); + x2ec_lTriggerPos = 1; + x324_zoomState = EZoomState::Out; + } + + if (oldDist == xa8_renderStates[0].x18_camDist) + SetShouldZoomingSoundBePlaying(false); + else + SetShouldZoomingSoundBePlaying(true); +} + +void CAutoMapper::ProcessMapPanInput(const CFinalInput& input, const CStateManager& mgr) { + float forward = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveForward, input); + float back = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveBack, input); + float left = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveLeft, input); + float right = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveRight, input); + zeus::CTransform camRot = xa8_renderStates[0].x8_camOrientation.toTransform(); + if (forward > 0.f || back > 0.f || left > 0.f || right > 0.f) { + float deltaFrames = 60.f * input.DeltaTime(); + float speed = GetFinalMapScreenCameraMoveSpeed(); + int flags = 0x0; + if (forward > 0.f) + flags |= 0x1; + if (back > 0.f) + flags |= 0x2; + if (left > 0.f) + flags |= 0x4; + if (right > 0.f) + flags |= 0x8; + + switch (flags) { + case 1: // Forward + x2e8_rStickPos = 1; + break; + case 2: // Back + x2e8_rStickPos = 5; + break; + case 4: // Left + x2e8_rStickPos = 3; + break; + case 5: // Forward-Left + x2e8_rStickPos = 2; + break; + case 6: // Back-Left + x2e8_rStickPos = 4; + break; + case 8: // Right + x2e8_rStickPos = 7; + break; + case 9: // Forward-Right + x2e8_rStickPos = 8; + break; + case 10: // Back-Right + x2e8_rStickPos = 6; + break; + default: + break; } + + zeus::CVector3f dirVec(right - left, 0.f, forward - back); + zeus::CVector3f deltaVec = camRot * (dirVec * deltaFrames * speed); + zeus::CVector3f newPoint = xa8_renderStates[0].x20_areaPoint + deltaVec; + if (deltaVec.magnitude() > input.DeltaTime()) + SetShouldPanningSoundBePlaying(true); else - { - MP1::CMain::EnsureWorldPakReady(g_GameState->CurrentWorldAssetId()); - if (x1bc_state == EAutoMapperState::MapScreenUniverse || x24_world == mgr.GetWorld()) - { - BeginMapperStateTransition(EAutoMapperState::MiniMap, mgr); - x328_ = 0; - } - LeaveMapScreenState(); + SetShouldPanningSoundBePlaying(false); + + if (x1bc_state == EAutoMapperState::MapScreen) { + xa8_renderStates[0].x20_areaPoint = x24_world->IGetMapWorld()->ConstrainToWorldVolume(newPoint, camRot.basis[1]); + } else { + zeus::CVector3f localPoint = newPoint - x8_mapu->GetMapUniverseCenterPoint(); + if (localPoint.magnitude() > x8_mapu->GetMapUniverseRadius()) + newPoint = x8_mapu->GetMapUniverseCenterPoint() + localPoint.normalized() * x8_mapu->GetMapUniverseRadius(); + xa8_renderStates[0].x20_areaPoint = newPoint; } + } else { + SetShouldPanningSoundBePlaying(false); + float speed = g_tweakAutoMapper->GetCamPanUnitsPerFrame() * GetBaseMapScreenCameraMoveSpeed(); + if (x1bc_state == EAutoMapperState::MapScreen) { + const CMapArea* area = x24_world->IGetMapWorld()->GetMapArea(xa0_curAreaId); + zeus::CVector3f worldPoint = area->GetAreaPostTransform(*x24_world, xa0_curAreaId) * area->GetAreaCenterPoint(); + zeus::CVector3f viewPoint = worldPoint - xa8_renderStates[0].x20_areaPoint; + if (viewPoint.magnitude() < speed) + xa8_renderStates[0].x20_areaPoint = worldPoint; + else + xa8_renderStates[0].x20_areaPoint += viewPoint.normalized() * speed; + } else { + std::pair areas = FindClosestVisibleWorld(xa8_renderStates[0].x20_areaPoint, camRot.basis[1], mgr); + const zeus::CTransform& hex = x8_mapu->GetMapWorldData(areas.first).GetMapAreaData(areas.second); + zeus::CVector3f areaToHex = hex.origin - xa8_renderStates[0].x20_areaPoint; + if (areaToHex.magnitude() < speed) + xa8_renderStates[0].x20_areaPoint = hex.origin; + else + xa8_renderStates[0].x20_areaPoint += areaToHex.normalized() * speed; + } + } } +void CAutoMapper::SetShouldPanningSoundBePlaying(bool b) { + if (b) { + if (!x1cc_panningSfx) + x1cc_panningSfx = CSfxManager::SfxStart(SFXui_map_pan, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } else { + CSfxManager::SfxStop(x1cc_panningSfx); + x1cc_panningSfx.reset(); + } } + +void CAutoMapper::SetShouldZoomingSoundBePlaying(bool b) { + if (b) { + if (!x1d4_zoomingSfx) + x1d4_zoomingSfx = CSfxManager::SfxStart(SFXui_map_zoom, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } else { + CSfxManager::SfxStop(x1d4_zoomingSfx); + x1d4_zoomingSfx.reset(); + } +} + +void CAutoMapper::SetShouldRotatingSoundBePlaying(bool b) { + if (b) { + if (!x1d0_rotatingSfx) + x1d0_rotatingSfx = CSfxManager::SfxStart(SFXui_map_rotate, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } else { + CSfxManager::SfxStop(x1d0_rotatingSfx); + x1d0_rotatingSfx.reset(); + } +} + +void CAutoMapper::ProcessMapScreenInput(const CFinalInput& input, const CStateManager& mgr) { + zeus::CMatrix3f camRot = xa8_renderStates[0].x8_camOrientation.toTransform().buildMatrix3f(); + if (x1bc_state == EAutoMapperState::MapScreen) { + if (input.PA() && x328_ == 0 && HasCurrentMapUniverseWorld()) + BeginMapperStateTransition(EAutoMapperState::MapScreenUniverse, mgr); + } else if (x1bc_state == EAutoMapperState::MapScreenUniverse && input.PA()) { + const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx); + zeus::CVector3f pointLocal = mapuWld.GetWorldTransform().inverse() * xa8_renderStates[0].x20_areaPoint; + if (mapuWld.GetWorldAssetId() != g_GameState->CurrentWorldAssetId()) { + x32c_loadingDummyWorld = true; + CheckDummyWorldLoad(mgr); + } else { + x24_world = mgr.GetWorld(); + CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); + xa0_curAreaId = FindClosestVisibleArea(pointLocal, zeus::CUnitVector3f(camRot[1]), mgr, *x24_world, mwInfo); + BeginMapperStateTransition(EAutoMapperState::MapScreen, mgr); + } + } + + x2f4_aButtonPos = 0; + if (input.PA()) + x2f4_aButtonPos = 1; + + if (IsInMapperState(EAutoMapperState::MapScreen) || IsInMapperState(EAutoMapperState::MapScreenUniverse)) { + x2e4_lStickPos = 0; + x2e8_rStickPos = 0; + x2ec_lTriggerPos = 0; + x2f0_rTriggerPos = 0; + ProcessMapRotateInput(input, mgr); + ProcessMapZoomInput(input, mgr); + ProcessMapPanInput(input, mgr); + } +} + +zeus::CQuaternion CAutoMapper::GetMiniMapCameraOrientation(const CStateManager& stateMgr) const { + const CGameCamera* cam = stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr); + zeus::CEulerAngles camAngles(zeus::CQuaternion(cam->GetTransform().buildMatrix3f())); + float rotMod = -(std::floor(camAngles.z() / (2.f * M_PIF)) * 2.f * M_PIF - camAngles.z()); + if (rotMod < 0.f) + rotMod += 2.f * M_PIF; + + zeus::CQuaternion ret; + ret.rotateZ(rotMod); + ret.rotateX(zeus::degToRad(g_tweakAutoMapper->GetMiniCamXAngle())); + return ret; +} + +zeus::CVector3f CAutoMapper::GetAreaPointOfInterest(const CStateManager&, TAreaId aid) const { + const CMapArea* mapa = x24_world->IGetMapWorld()->GetMapArea(aid); + return mapa->GetAreaPostTransform(*x24_world, aid) * mapa->GetAreaCenterPoint(); +} + +TAreaId CAutoMapper::FindClosestVisibleArea(const zeus::CVector3f& point, const zeus::CUnitVector3f& camDir, + const CStateManager& mgr, const IWorld& wld, + const CMapWorldInfo& mwInfo) const { + float minDist = 9999.f; + TAreaId closestArea = xa0_curAreaId; + const CMapWorld* mw = wld.IGetMapWorld(); + std::vector areas = mw->GetVisibleAreas(wld, mwInfo); + for (TAreaId areaId : areas) { + const CMapArea* mapa = mw->GetMapArea(areaId); + zeus::CVector3f xfPoint = mapa->GetAreaPostTransform(wld, areaId) * mapa->GetAreaCenterPoint(); + zeus::CVector3f pointToArea = xfPoint - point; + pointToArea = pointToArea.canBeNormalized() + ? point + (pointToArea.normalized().dot(camDir) * pointToArea.magnitude()) * camDir + : point; + pointToArea -= xfPoint; + float dist = pointToArea.magnitude(); + if (dist < minDist) { + minDist = dist; + closestArea = areaId; + } + } + return closestArea; +} + +std::pair CAutoMapper::FindClosestVisibleWorld(const zeus::CVector3f& point, + const zeus::CUnitVector3f& camDir, + const CStateManager& mgr) const { + float minDist = 29999.f; + std::pair closestWorld = {x9c_worldIdx, xa0_curAreaId}; + for (u32 w = 0; w < x8_mapu->GetNumMapWorldDatas(); ++w) { + const CMapUniverse::CMapWorldData& mwData = x8_mapu->GetMapWorldData(w); + const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(mwData.GetWorldAssetId()).MapWorldInfo(); + if (!mwInfo.IsAnythingSet()) + continue; + for (u32 i = 0; i < mwData.GetNumMapAreaDatas(); ++i) { + const zeus::CVector3f& mwOrigin = mwData.GetMapAreaData(i).origin; + zeus::CVector3f pointToArea = mwOrigin - point; + pointToArea = pointToArea.canBeNormalized() + ? point + (pointToArea.normalized().dot(camDir) * pointToArea.magnitude()) * camDir + : point; + pointToArea -= mwOrigin; + float dist = pointToArea.magnitude(); + if (dist < minDist) { + minDist = dist; + closestWorld.first = w; + closestWorld.second = i; + } + } + } + return closestWorld; +} + +zeus::CVector2i CAutoMapper::GetMiniMapViewportSize() { + float scaleX = g_Viewport.x8_width / 640.f; + float scaleY = g_Viewport.xc_height / 480.f; + return {int(scaleX * g_tweakAutoMapper->GetMiniMapViewportWidth()), + int(scaleY * g_tweakAutoMapper->GetMiniMapViewportHeight())}; +} + +zeus::CVector2i CAutoMapper::GetMapScreenViewportSize() { + return {int(g_Viewport.x8_width), int(g_Viewport.xc_height)}; +} + +float CAutoMapper::GetMapAreaMaxDrawDepth(const CStateManager&, TAreaId aid) const { + return x24_world->IGetMapWorld()->GetCurrentMapAreaDepth(*x24_world, aid); +} + +float CAutoMapper::GetMapAreaMiniMapDrawAlphaSurfaceVisited(const CStateManager& stateMgr) { + float mapAlphaInterp = g_tweakGui->GetMapAlphaInterpolant(); + return g_tweakAutoMapper->GetMiniAlphaSurfaceVisited() * (1.f - mapAlphaInterp) * stateMgr.Player()->GetGunAlpha() + + mapAlphaInterp; +} + +float CAutoMapper::GetMapAreaMiniMapDrawAlphaOutlineVisited(const CStateManager& stateMgr) { + float mapAlphaInterp = g_tweakGui->GetMapAlphaInterpolant(); + return g_tweakAutoMapper->GetMiniAlphaOutlineVisited() * (1.f - mapAlphaInterp) * stateMgr.Player()->GetGunAlpha() + + mapAlphaInterp; +} + +float CAutoMapper::GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(const CStateManager& stateMgr) { + float mapAlphaInterp = g_tweakGui->GetMapAlphaInterpolant(); + return g_tweakAutoMapper->GetMiniAlphaSurfaceUnvisited() * (1.f - mapAlphaInterp) * stateMgr.Player()->GetGunAlpha() + + mapAlphaInterp; +} + +float CAutoMapper::GetMapAreaMiniMapDrawAlphaOutlineUnvisited(const CStateManager& stateMgr) { + float mapAlphaInterp = g_tweakGui->GetMapAlphaInterpolant(); + return g_tweakAutoMapper->GetMiniAlphaOutlineUnvisited() * (1.f - mapAlphaInterp) * stateMgr.Player()->GetGunAlpha() + + mapAlphaInterp; +} + +float CAutoMapper::GetDesiredMiniMapCameraDistance(const CStateManager& mgr) const { + const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); + const CMapWorld* mw = x24_world->IGetMapWorld(); + zeus::CAABox aabb; + const IGameArea* area = x24_world->IGetAreaAlways(xa0_curAreaId); + const CMapArea* mapa = mw->GetMapArea(xa0_curAreaId); + bool oneMiniMapArea = g_tweakAutoMapper->GetShowOneMiniMapArea(); + for (int i = -1; i < (oneMiniMapArea ? 0 : int(area->IGetNumAttachedAreas())); ++i) { + TAreaId aid = i == -1 ? xa0_curAreaId : area->IGetAttachedAreaId(i); + const CMapArea* attMapa = mw->GetMapArea(aid); + if (attMapa->GetIsVisibleToAutoMapper(mwInfo.IsWorldVisible(aid), mwInfo.IsAreaVisible(aid))) { + zeus::CAABox areaAABB = + attMapa->GetBoundingBox().getTransformedAABox(attMapa->GetAreaPostTransform(*x24_world, aid)); + aabb.accumulateBounds(areaAABB.min); + aabb.accumulateBounds(areaAABB.max); + } + } + + zeus::CVector3f xfPoint = mapa->GetAreaPostTransform(*x24_world, xa0_curAreaId) * mapa->GetAreaCenterPoint(); + zeus::CVector3f maxMargin; + maxMargin.x() = std::max(xfPoint.x() - aabb.min.x(), aabb.max.x() - xfPoint.x()); + maxMargin.y() = std::max(xfPoint.y() - aabb.min.y(), aabb.max.y() - xfPoint.y()); + maxMargin.z() = std::max(xfPoint.z() - aabb.min.z(), aabb.max.z() - xfPoint.z()); + zeus::CVector3f extent = mapa->GetBoundingBox().max - mapa->GetBoundingBox().min; + + return (0.5f * (0.5f * extent.magnitude()) + 0.5f * maxMargin.magnitude()) * + g_tweakAutoMapper->GetMiniMapCamDistScale() * + std::tan(M_PIF / 2.f - 0.5f * 2.f * M_PIF * (xa8_renderStates[0].x1c_camAngle / 360.f)); +} + +float CAutoMapper::GetClampedMapScreenCameraDistance(float v) { + if (x1bc_state == EAutoMapperState::MapScreenUniverse) + return zeus::clamp(g_tweakAutoMapper->GetMinUniverseCamDist(), v, g_tweakAutoMapper->GetMaxUniverseCamDist()); + return zeus::clamp(g_tweakAutoMapper->GetMinCamDist(), v, g_tweakAutoMapper->GetMaxCamDist()); +} + +void CAutoMapper::UnmuteAllLoopedSounds() { + CSfxManager::SfxVolume(x1cc_panningSfx, 1.f); + CSfxManager::SfxVolume(x1d0_rotatingSfx, 1.f); + CSfxManager::SfxVolume(x1d4_zoomingSfx, 1.f); +} + +void CAutoMapper::ProcessControllerInput(const CFinalInput& input, CStateManager& mgr) { + if (!IsRenderStateInterpolating()) { + if (IsInMapperState(EAutoMapperState::MapScreen) || IsInMapperState(EAutoMapperState::MapScreenUniverse)) { + if (x32c_loadingDummyWorld) + CheckDummyWorldLoad(mgr); + else if (x1e0_hintSteps.size()) + UpdateHintNavigation(input.DeltaTime(), mgr); + else if (x328_ == 0) + ProcessMapScreenInput(input, mgr); + } + } + + zeus::CMatrix3f camRot = xa8_renderStates[0].x8_camOrientation.toTransform().buildMatrix3f(); + if (IsInMapperState(EAutoMapperState::MapScreen)) { + CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); + TAreaId aid = FindClosestVisibleArea(xa8_renderStates[0].x20_areaPoint, camRot[1], mgr, *x24_world, mwInfo); + if (aid != xa0_curAreaId) { + xa0_curAreaId = aid; + xa8_renderStates[0].x2c_drawDepth1 = GetMapAreaMaxDrawDepth(mgr, xa0_curAreaId); + xa8_renderStates[0].x30_drawDepth2 = GetMapAreaMaxDrawDepth(mgr, xa0_curAreaId); + } + } else if (IsInMapperState(EAutoMapperState::MapScreenUniverse)) { + u32 oldWldIdx = x9c_worldIdx; + if (x1e0_hintSteps.size()) { + SAutoMapperHintStep& nextStep = x1e0_hintSteps.front(); + if (nextStep.x0_type == SAutoMapperHintStep::Type::PanToWorld || + nextStep.x0_type == SAutoMapperHintStep::Type::SwitchToWorld) { + SetCurWorldAssetId(nextStep.x4_worldId); + } else { + std::pair wld = FindClosestVisibleWorld(xa8_renderStates[0].x20_areaPoint, camRot[1], mgr); + x9c_worldIdx = wld.first; + } + } else { + std::pair wld = FindClosestVisibleWorld(xa8_renderStates[0].x20_areaPoint, camRot[1], mgr); + x9c_worldIdx = wld.first; + } + + if (x9c_worldIdx != oldWldIdx) { + CAssetId curMlvl = g_GameState->CurrentWorldAssetId(); + for (u32 i = 0; i < x14_dummyWorlds.size(); ++i) { + auto& wld = x14_dummyWorlds[i]; + const CMapUniverse::CMapWorldData& mwData = x8_mapu->GetMapWorldData(i); + if (i == x9c_worldIdx && curMlvl != mwData.GetWorldAssetId()) { + if (g_ResFactory->CanBuild(SObjectTag{FOURCC('MLVL'), mwData.GetWorldAssetId()})) + wld = std::make_unique(mwData.GetWorldAssetId(), true); + } else { + wld.reset(); + } + } + x24_world = (curMlvl == x8_mapu->GetMapWorldData(x9c_worldIdx).GetWorldAssetId()) ? mgr.GetWorld() : nullptr; + } + } + + if (x300_textpane_instructions) { + if (x78_areaHintDesc.IsLoaded()) { + x2fc_textpane_hint->TextSupport().SetText(x78_areaHintDesc->GetString(0)); + x304_textpane_instructions1->TextSupport().SetText(u""); + x300_textpane_instructions->TextSupport().SetText(u""); + x308_textpane_instructions2->TextSupport().SetText(u""); + } else { + x2fc_textpane_hint->TextSupport().SetText(u""); + std::u16string str = hecl::UTF8ToChar16( + hecl::Format("&image=SI,0.6,1.0,%8.8X;", u32(g_tweakPlayerRes->x24_lStick[x2e4_lStickPos].Value()))); + str += g_MainStringTable->GetString(46); // Rotate + x300_textpane_instructions->TextSupport().SetText(str); + str = hecl::UTF8ToChar16( + hecl::Format("&image=SI,0.6,1.0,%8.8X;", u32(g_tweakPlayerRes->x4c_cStick[x2e8_rStickPos].Value()))); + str += g_MainStringTable->GetString(47); // Move + x304_textpane_instructions1->TextSupport().SetText(str); + str = hecl::UTF8ToChar16( + hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x74_lTrigger[x2ec_lTriggerPos].Value()))); + str += g_MainStringTable->GetString(48); // Zoom + str += hecl::UTF8ToChar16( + hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x80_rTrigger[x2f0_rTriggerPos].Value()))); + x308_textpane_instructions2->TextSupport().SetText(str); + } + } + + if (input.PY()) { + CPersistentOptions& sysOpts = g_GameState->SystemOptions(); + switch (sysOpts.GetAutoMapperKeyState()) { + case 0: + sysOpts.SetAutoMapperKeyState(1); + CSfxManager::SfxStart(SFXui_map_screen_key1, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + case 1: + sysOpts.SetAutoMapperKeyState(2); + CSfxManager::SfxStart(SFXui_map_screen_key2, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + case 2: + sysOpts.SetAutoMapperKeyState(0); + CSfxManager::SfxStart(SFXui_map_screen_key0, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + default: + break; + } + } + + if (input.PZ() || input.PB()) { + if (x328_ == 0) { + if (CanLeaveMapScreenInternal(mgr)) + LeaveMapScreen(mgr); + if (NotHintNavigating()) { + BeginMapperStateTransition(EAutoMapperState::MapScreenUniverse, mgr); + x328_ = 1; + } + } + } +} + +void CAutoMapper::Update(float dt, const CStateManager& mgr) { + if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) { + x1d8_flashTimer = std::fmod(x1d8_flashTimer + dt, 0.75f); + x1dc_playerFlashPulse = x1d8_flashTimer < 0.375f ? x1d8_flashTimer / 0.375f : (0.75f - x1d8_flashTimer) / 0.375f; + } + + if (!m_frmeInitialized && x28_frmeMapScreen.IsLoaded()) { + x28_frmeMapScreen->SetMaxAspect(1.78f); + m_frmeInitialized = true; + static_cast(x28_frmeMapScreen->FindWidget("textpane_left")) + ->TextSupport() + .SetText(g_MainStringTable->GetString(42)); + static_cast(x28_frmeMapScreen->FindWidget("textpane_yicon")) + ->TextSupport() + .SetText(g_MainStringTable->GetString(43)); + x2fc_textpane_hint = static_cast(x28_frmeMapScreen->FindWidget("textpane_hint")); + x300_textpane_instructions = static_cast(x28_frmeMapScreen->FindWidget("textpane_instructions")); + x304_textpane_instructions1 = static_cast(x28_frmeMapScreen->FindWidget("textpane_instructions1")); + x308_textpane_instructions2 = static_cast(x28_frmeMapScreen->FindWidget("textpane_instructions2")); + CGuiTextPane* mapLegend = static_cast(x28_frmeMapScreen->FindWidget("textpane_mapLegend")); + mapLegend->TextSupport().ClearRenderBuffer(); + mapLegend->TextSupport().SetImageBaseline(true); + mapLegend->TextSupport().SetText(g_MainStringTable->GetString(49)); + x30c_basewidget_leftPane = x28_frmeMapScreen->FindWidget("basewidget_leftPane"); + x310_basewidget_yButtonPane = x28_frmeMapScreen->FindWidget("basewidget_yButtonPane"); + x314_basewidget_bottomPane = x28_frmeMapScreen->FindWidget("basewidget_bottomPane"); + x2f8_textpane_areaname = static_cast(x28_frmeMapScreen->FindWidget("textpane_areaname")); + x2f8_textpane_areaname->SetDepthTest(false); + } + + if (m_frmeInitialized) { + x28_frmeMapScreen->Update(dt); + CGuiTextPane* right1 = static_cast(x28_frmeMapScreen->FindWidget("textpane_right1")); + std::u16string string; + if (x1bc_state == EAutoMapperState::MapScreenUniverse || + (x1bc_state == EAutoMapperState::MapScreen && HasCurrentMapUniverseWorld())) + string = hecl::UTF8ToChar16( + hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x98_aButton[x2f4_aButtonPos].Value()))); + right1->TextSupport().SetText(string); + CGuiTextPane* right = static_cast(x28_frmeMapScreen->FindWidget("textpane_right")); + if (x1bc_state == EAutoMapperState::MapScreenUniverse) + string = g_MainStringTable->GetString(45); + else if (x1bc_state == EAutoMapperState::MapScreen && HasCurrentMapUniverseWorld()) + string = g_MainStringTable->GetString(44); + else + string = std::u16string(); + right->TextSupport().SetText(string); + } + + float dt2 = 2.f * dt; + switch (g_GameState->SystemOptions().GetAutoMapperKeyState()) { + case 0: // All shown + x318_leftPanePos -= dt2; + x31c_yButtonPanePos -= dt2; + x320_bottomPanePos -= dt2; + break; + case 1: // Left shown + x318_leftPanePos += dt2; + x31c_yButtonPanePos -= dt2; + x320_bottomPanePos -= dt2; + break; + case 2: // All hidden + x318_leftPanePos += dt2; + x31c_yButtonPanePos += dt2; + x320_bottomPanePos += dt2; + break; + default: + break; + } + + x318_leftPanePos = std::max(0.f, std::min(x318_leftPanePos, 1.f)); + x31c_yButtonPanePos = std::max(0.f, std::min(x31c_yButtonPanePos, 1.f)); + x320_bottomPanePos = std::max(0.f, std::min(x320_bottomPanePos, 1.f)); + + if (x30c_basewidget_leftPane) { + float vpAspectRatio = std::max(1.78f, g_Viewport.x8_width / float(g_Viewport.xc_height)); + x30c_basewidget_leftPane->SetLocalTransform( + zeus::CTransform::Translate(x318_leftPanePos * vpAspectRatio * -9.f, 0.f, 0.f) * + x30c_basewidget_leftPane->GetTransform()); + } + + if (x310_basewidget_yButtonPane) { + x310_basewidget_yButtonPane->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, x31c_yButtonPanePos * -3.5f) * + x310_basewidget_yButtonPane->GetTransform()); + } + + if (x314_basewidget_bottomPane) { + x314_basewidget_bottomPane->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, x320_bottomPanePos * -7.f) * + x314_basewidget_bottomPane->GetTransform()); + } + + if (IsInMapperState(EAutoMapperState::MiniMap)) { + xa8_renderStates[0].x8_camOrientation = GetMiniMapCameraOrientation(mgr); + float desiredDist = GetDesiredMiniMapCameraDistance(mgr); + if (std::fabs(xa8_renderStates[0].x18_camDist - desiredDist) < 3.f) + xa8_renderStates[0].x18_camDist = desiredDist; + else if (xa8_renderStates[0].x18_camDist < desiredDist) + xa8_renderStates[0].x18_camDist += 3.f; + else + xa8_renderStates[0].x18_camDist -= 3.f; + TAreaId curAid = x24_world->IGetCurrentAreaId(); + if (curAid != xa0_curAreaId) { + xa8_renderStates[2] = xa8_renderStates[0]; + xa8_renderStates[1] = xa8_renderStates[0]; + xa4_otherAreaId = xa0_curAreaId; + xa0_curAreaId = curAid; + xa8_renderStates[1].x20_areaPoint = GetAreaPointOfInterest(mgr, xa0_curAreaId); + xa8_renderStates[1].x44_viewportEase = SAutoMapperRenderState::Ease::None; + xa8_renderStates[1].x48_camEase = SAutoMapperRenderState::Ease::None; + xa8_renderStates[1].x4c_pointEase = SAutoMapperRenderState::Ease::InOut; + xa8_renderStates[1].x50_depth1Ease = SAutoMapperRenderState::Ease::Linear; + xa8_renderStates[1].x54_depth2Ease = SAutoMapperRenderState::Ease::Linear; + xa8_renderStates[1].x58_alphaEase = SAutoMapperRenderState::Ease::None; + xa8_renderStates[1].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth(); + xa8_renderStates[1].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth(); + xa8_renderStates[2].x2c_drawDepth1 = GetMapAreaMiniMapDrawDepth() - 1.f; + xa8_renderStates[2].x30_drawDepth2 = GetMapAreaMiniMapDrawDepth() - 1.f; + ResetInterpolationTimer(g_tweakAutoMapper->GetHintPanTime()); + } + xa8_renderStates[1].x34_alphaSurfaceVisited = GetMapAreaMiniMapDrawAlphaSurfaceVisited(mgr); + xa8_renderStates[1].x38_alphaOutlineVisited = GetMapAreaMiniMapDrawAlphaOutlineVisited(mgr); + xa8_renderStates[1].x3c_alphaSurfaceUnvisited = GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(mgr); + xa8_renderStates[1].x40_alphaOutlineUnvisited = GetMapAreaMiniMapDrawAlphaOutlineUnvisited(mgr); + } else { + if (x1c0_nextState == EAutoMapperState::MiniMap) { + float desiredDist = GetDesiredMiniMapCameraDistance(mgr); + if (std::fabs(xa8_renderStates[1].x18_camDist - desiredDist) < 3.f) + xa8_renderStates[0].x18_camDist = desiredDist; + else if (xa8_renderStates[1].x18_camDist < desiredDist) + xa8_renderStates[1].x18_camDist += 3.f; + else + xa8_renderStates[1].x18_camDist -= 3.f; + } else if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap && x24_world) { + x24_world->IGetMapWorld()->RecalculateWorldSphere( + *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(), *x24_world); + } + } + + if (IsRenderStateInterpolating()) { + x1c8_interpTime = std::min(x1c8_interpTime + dt, x1c4_interpDur); + SAutoMapperRenderState::InterpolateWithClamp(xa8_renderStates[2], xa8_renderStates[0], xa8_renderStates[1], + x1c8_interpTime / x1c4_interpDur); + if (x1c8_interpTime == x1c4_interpDur && x328_ == 2) + SetupMiniMapWorld(mgr); + } else if (IsInMapperStateTransition()) { + CompleteMapperStateTransition(mgr); + } + + CAssetId stringId = x88_mapAreaStringId; + if (IsInMapperState(EAutoMapperState::MapScreenUniverse)) { + IWorld* wld = x14_dummyWorlds[x9c_worldIdx].get(); + if (wld && wld->ICheckWorldComplete()) + stringId = wld->IGetStringTableAssetId(); + else if (x24_world) + stringId = x24_world->IGetStringTableAssetId(); + } else if (x24_world) { + const IGameArea* area = x24_world->IGetAreaAlways(xa0_curAreaId); + const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); + if (mwInfo.IsMapped(xa0_curAreaId) || mwInfo.IsAreaVisted(xa0_curAreaId)) + stringId = area->IGetStringTableAssetId(); + else + stringId = {}; + } + + if (x88_mapAreaStringId != stringId) { + x88_mapAreaStringId = stringId; + if (x88_mapAreaStringId.IsValid()) + x8c_mapAreaString = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), x88_mapAreaStringId}); + else + x8c_mapAreaString = TLockedToken(); + } + + if (x2f8_textpane_areaname) { + if (x8c_mapAreaString) { + if (x8c_mapAreaString.IsLoaded()) + x2f8_textpane_areaname->TextSupport().SetText(x8c_mapAreaString->GetString(0)); + } else { + x2f8_textpane_areaname->TextSupport().SetText(u""); + } + } + + if (IsInMapperState(EAutoMapperState::MapScreen)) { + CAssetId hintDesc = GetAreaHintDescriptionString(x24_world->IGetAreaAlways(xa0_curAreaId)->IGetAreaAssetId()); + if (hintDesc != x74_areaHintDescId) { + x74_areaHintDescId = hintDesc; + if (x74_areaHintDescId.IsValid()) + x78_areaHintDesc = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), x74_areaHintDescId}); + else + x78_areaHintDesc = TLockedToken(); + } + } + + for (auto& wld : x14_dummyWorlds) + if (wld) + wld->ICheckWorldComplete(); +} + +void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, float alpha) const { + alpha *= g_GameState->GameOptions().GetHUDAlpha() / 255.f; + // Blend mode alpha + // Backface cull + float alphaInterp; + if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) { + alphaInterp = 1.f; + } else if (IsInMapperState(EAutoMapperState::MiniMap)) { + alphaInterp = alpha; + } else if (x1c0_nextState == EAutoMapperState::MiniMap) { + float t = GetInterp(); + alphaInterp = alpha * t + (1.f - t); + } else if (x1bc_state == EAutoMapperState::MiniMap) { + float t = GetInterp(); + alphaInterp = alpha * (1.f - t) + t; + } else { + alphaInterp = 1.f; + } + + zeus::CVector2i vp = xa8_renderStates[0].GetViewportSize(); + float aspect = vp.x / float(vp.y); + if (aspect > 1.78f) + aspect = 1.78f; + float yScale = xa8_renderStates[0].x18_camDist / + std::tan(M_PIF / 2.f - 0.5f * 2.f * M_PIF * (xa8_renderStates[0].x1c_camAngle / 360.f)); + float xScale = yScale * aspect; + zeus::CTransform camXf(xa8_renderStates[0].x8_camOrientation, xa8_renderStates[0].x20_areaPoint); + zeus::CTransform distScale = zeus::CTransform::Scale(1.f / xScale, 0.001f, 1.f / yScale); + zeus::CTransform tweakScale = + zeus::CTransform::Scale(g_tweakAutoMapper->GetMapPlaneScaleX(), 0.f, g_tweakAutoMapper->GetMapPlaneScaleZ()); + zeus::CTransform planeXf = xf * tweakScale * distScale * camXf.inverse(); + + float universeInterp = 0.f; + if (x1c0_nextState == EAutoMapperState::MapScreenUniverse) { + if (x1bc_state == EAutoMapperState::MapScreenUniverse) + universeInterp = 1.f; + else + universeInterp = GetInterp(); + } else if (x1bc_state == EAutoMapperState::MapScreenUniverse) { + universeInterp = 1.f - GetInterp(); + } + + zeus::CTransform preXf; + if (x1bc_state == EAutoMapperState::MapScreenUniverse || x1c0_nextState == EAutoMapperState::MapScreenUniverse) + preXf = x8_mapu->GetMapWorldData(x9c_worldIdx).GetWorldTransform(); + + float objectScale = xa8_renderStates[0].x18_camDist / g_tweakAutoMapper->GetMinCamDist(); + float mapAlpha = alphaInterp * (1.f - universeInterp); + + if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) { + if (universeInterp < 1.f && x24_world) { + const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); + const CMapWorld* mw = x24_world->IGetMapWorld(); + float hintFlash = 0.f; + if (x1e0_hintSteps.size() && x1e0_hintSteps.front().x0_type == SAutoMapperHintStep::Type::ShowBeacon) { + if (xa0_curAreaId == mgr.GetNextAreaId() && x24_world == mgr.GetWorld()) { + float pulseTime = std::fmod(x1e0_hintSteps.front().x4_float * 8.f, 1.f); + hintFlash = 2.f * (pulseTime < 0.5f ? pulseTime : 1.f - pulseTime); + } else { + for (const SAutoMapperHintLocation& loc : x1f8_hintLocations) { + if (x24_world->IGetWorldAssetId() != loc.x8_worldId) + continue; + if (xa0_curAreaId != loc.xc_areaId) + continue; + float pulseTime = + std::fmod((1.f - std::max(0.f, (x1e0_hintSteps.front().x4_float - 0.5f) / 0.5f)) * 4.f, 1.f); + hintFlash = 2.f * (pulseTime < 0.5f ? pulseTime : 1.f - pulseTime); + break; + } + } + } + zeus::CTransform modelXf = planeXf * preXf; + CMapWorld::CMapWorldDrawParms parms(xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp, + xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp, + xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp, + xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, mapAlpha, 2.f, + mgr, modelXf, camXf, *x24_world, mwInfo, x1dc_playerFlashPulse, hintFlash, + objectScale, true); + mw->Draw(parms, xa0_curAreaId, xa0_curAreaId, xa8_renderStates[0].x2c_drawDepth1, + xa8_renderStates[0].x30_drawDepth2, true); + } + } else if (IsInMapperState(EAutoMapperState::MiniMap)) { + const CMapWorld* mw = x24_world->IGetMapWorld(); + const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); + CMapWorld::CMapWorldDrawParms parms(xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp, + xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp, + xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp, + xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, mapAlpha, 1.f, mgr, + planeXf, camXf, *x24_world, mwInfo, 0.f, 0.f, objectScale, false); + mw->Draw(parms, xa0_curAreaId, xa4_otherAreaId, xa8_renderStates[0].x2c_drawDepth1, + xa8_renderStates[0].x30_drawDepth2, false); + } else { + const CMapWorld* mw = x24_world->IGetMapWorld(); + const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(x24_world->IGetWorldAssetId()).MapWorldInfo(); + zeus::CTransform modelXf = planeXf * preXf; + CMapWorld::CMapWorldDrawParms parms(xa8_renderStates[0].x34_alphaSurfaceVisited * alphaInterp, + xa8_renderStates[0].x38_alphaOutlineVisited * alphaInterp, + xa8_renderStates[0].x3c_alphaSurfaceUnvisited * alphaInterp, + xa8_renderStates[0].x40_alphaOutlineUnvisited * alphaInterp, mapAlpha, 2.f, mgr, + modelXf, camXf, *x24_world, mwInfo, 0.f, 0.f, objectScale, true); + mw->Draw(parms, xa0_curAreaId, xa0_curAreaId, xa8_renderStates[0].x2c_drawDepth1, + xa8_renderStates[0].x30_drawDepth2, false); + } + + if (universeInterp > 0.f) { + zeus::CTransform areaXf = mgr.GetWorld() + ->GetMapWorld() + ->GetMapArea(mgr.GetNextAreaId()) + ->GetAreaPostTransform(*mgr.GetWorld(), mgr.GetNextAreaId()); + const CMapUniverse::CMapWorldData& mwData = x8_mapu->GetMapWorldDataByWorldId(g_GameState->CurrentWorldAssetId()); + zeus::CTransform universeAreaXf = mwData.GetWorldTransform() * areaXf; + float minMag = FLT_MAX; + int hexIdx = -1; + for (u32 i = 0; i < mwData.GetNumMapAreaDatas(); ++i) { + float mag = (universeAreaXf.origin - mwData.GetMapAreaData(i).origin).magnitude(); + if (mag < minMag) { + hexIdx = i; + minMag = mag; + } + } + + CMapUniverse::CMapUniverseDrawParms parms(universeInterp, x9c_worldIdx, g_GameState->CurrentWorldAssetId(), hexIdx, + x1dc_playerFlashPulse, mgr, planeXf, camXf); + x8_mapu->Draw(parms, zeus::CVector3f::skZero, 0.f, 0.f); + } + + if (!IsInMapperState(EAutoMapperState::MapScreenUniverse)) { + zeus::CTransform mapXf = planeXf * preXf; + if (x24_world == mgr.GetWorld()) { + float func = zeus::clamp(0.f, 0.5f * (1.f + std::sin(5.f * CGraphics::GetSecondsMod900() - (M_PIF / 2.f))), 1.f); + float scale = + std::min(0.6f * g_tweakAutoMapper->GetMaxCamDist() / g_tweakAutoMapper->GetMinCamDist(), objectScale); + zeus::CEulerAngles eulers(mgr.GetCameraManager()->GetCurrentCameraTransform(mgr)); + zeus::CRelAngle angle(eulers.z()); + zeus::CTransform playerXf(zeus::CMatrix3f::RotateZ(angle), + CMapArea::GetAreaPostTranslate(*x24_world, mgr.GetNextAreaId()) + + mgr.GetPlayer().GetTranslation()); + CGraphics::SetModelMatrix(mapXf * playerXf * zeus::CTransform::Scale(scale * (0.25f * func + 0.75f))); + float alpha; + if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) + alpha = 1.f; + else + alpha = xa8_renderStates[0].x34_alphaSurfaceVisited; + alpha *= mapAlpha; + zeus::CColor modColor = g_tweakAutoMapper->GetMiniMapSamusModColor(); + modColor.a() *= alpha; + CModelFlags flags(5, 0, 8 | 1, modColor); /* Depth GEqual */ + flags.m_extendedShader = EExtendedShader::DepthGEqualNoZWrite; + x30_miniMapSamus->Draw(flags); + } + if (IsInMapperState(EAutoMapperState::MapScreen)) { + CAssetId wldMlvl = x24_world->IGetWorldAssetId(); + const CMapWorld* mw = x24_world->IGetMapWorld(); + std::vector& hintBeaconFilters = const_cast(*this).m_hintBeaconFilters; + if (hintBeaconFilters.size() < x1f8_hintLocations.size()) { + hintBeaconFilters.reserve(x1f8_hintLocations.size()); + for (u32 i = hintBeaconFilters.size(); i < x1f8_hintLocations.size(); ++i) + hintBeaconFilters.emplace_back(EFilterType::Add, x3c_hintBeacon); + } + auto locIt = x1f8_hintLocations.cbegin(); + auto filterIt = hintBeaconFilters.begin(); + for (; locIt != x1f8_hintLocations.cend(); ++locIt, ++filterIt) { + const SAutoMapperHintLocation& loc = *locIt; + CTexturedQuadFilter& filter = *filterIt; + if (loc.x8_worldId != wldMlvl) + continue; + const CMapArea* mapa = mw->GetMapArea(loc.xc_areaId); + if (!mapa) + continue; + zeus::CTransform camRot(camXf.buildMatrix3f(), zeus::CVector3f::skZero); + CGraphics::SetModelMatrix( + mapXf * zeus::CTransform::Translate(mapa->GetAreaPostTransform(*x24_world, loc.xc_areaId).origin) * + zeus::CTransform::Translate(mapa->GetAreaCenterPoint()) * zeus::CTransform::Scale(objectScale) * camRot); + float beaconAlpha = 0.f; + if (loc.x0_showBeacon == 1) + beaconAlpha = loc.x4_beaconAlpha; + if (beaconAlpha > 0.f) { + CTexturedQuadFilter::Vert verts[4] = {{{-4.f, -8.f, 8.f}, {0.f, 1.f}}, + {{-4.f, -8.f, 0.f}, {0.f, 0.f}}, + {{4.f, -8.f, 8.f}, {1.f, 1.f}}, + {{4.f, -8.f, 0.f}, {1.f, 0.f}}}; + float alpha = beaconAlpha; + if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) { + } else + alpha *= xa8_renderStates[0].x34_alphaSurfaceVisited; + alpha *= mapAlpha; + zeus::CColor color = zeus::CColor::skWhite; + color.a() = alpha; + filter.drawVerts(color, verts); + } + } + } + } + + // No zread, no zwrite + // Ambient color white + // Disable all lights + if (m_frmeInitialized) { + float frmeAlpha = 0.f; + if (x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap) { + frmeAlpha = 1.f; + } else { + if (x1c0_nextState != EAutoMapperState::MiniMap) { + if (x1c4_interpDur > 0.f) + frmeAlpha = x1c8_interpTime / x1c4_interpDur; + } else { + if (x1c4_interpDur > 0.f) + frmeAlpha = x1c8_interpTime / x1c4_interpDur; + frmeAlpha = 1.f - frmeAlpha; + } + } + CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_NEAR); + CGuiWidgetDrawParms parms(frmeAlpha, zeus::CVector3f::skZero); + x28_frmeMapScreen->Draw(parms); + CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_HUD); + } +} + +void CAutoMapper::TransformRenderStatesWorldToUniverse() { + const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx); + zeus::CQuaternion rot = zeus::CQuaternion(mapuWld.GetWorldTransform().buildMatrix3f()); + xa8_renderStates[2].x8_camOrientation *= rot; + xa8_renderStates[2].x20_areaPoint = mapuWld.GetWorldTransform() * xa8_renderStates[2].x20_areaPoint; + xa8_renderStates[0].x8_camOrientation *= rot; + xa8_renderStates[0].x20_areaPoint = mapuWld.GetWorldTransform() * xa8_renderStates[0].x20_areaPoint; + xa8_renderStates[1].x8_camOrientation *= rot; + xa8_renderStates[1].x20_areaPoint = mapuWld.GetWorldTransform() * xa8_renderStates[1].x20_areaPoint; +} + +void CAutoMapper::TransformRenderStatesUniverseToWorld() { + const CMapUniverse::CMapWorldData& mapuWld = x8_mapu->GetMapWorldData(x9c_worldIdx); + zeus::CTransform inv = mapuWld.GetWorldTransform().inverse(); + zeus::CQuaternion invRot = zeus::CQuaternion(inv.buildMatrix3f()); + xa8_renderStates[2].x8_camOrientation *= invRot; + xa8_renderStates[2].x20_areaPoint = inv * xa8_renderStates[2].x20_areaPoint; + xa8_renderStates[0].x8_camOrientation *= invRot; + xa8_renderStates[0].x20_areaPoint = inv * xa8_renderStates[0].x20_areaPoint; + xa8_renderStates[1].x8_camOrientation *= invRot; + xa8_renderStates[1].x20_areaPoint = inv * xa8_renderStates[1].x20_areaPoint; +} + +void CAutoMapper::TransformRenderStateWorldToUniverse(SAutoMapperRenderState& state) { + state.x20_areaPoint = x8_mapu->GetMapWorldData(x9c_worldIdx).GetWorldTransform() * xa8_renderStates[1].x20_areaPoint; +} + +void CAutoMapper::SetupHintNavigation() { + if (!g_GameState->GameOptions().GetIsHintSystemEnabled()) + return; + x1e0_hintSteps.clear(); + x1f8_hintLocations.clear(); + CHintOptions& hintOpts = g_GameState->HintOptions(); + const CHintOptions::SHintState* curHint = hintOpts.GetCurrentDisplayedHint(); + bool navigating = false; + if (curHint && curHint->CanContinue()) { + navigating = true; + x1e0_hintSteps.push_back({SAutoMapperHintStep::ShowBeacon{}, 0.75f}); + const CGameHintInfo::CGameHint& nextHint = g_MemoryCardSys->GetHints()[hintOpts.GetNextHintIdx()]; + CAssetId curMlvl = x24_world->IGetWorldAssetId(); + for (const CGameHintInfo::SHintLocation& loc : nextHint.GetLocations()) { + if (loc.x0_mlvlId != curMlvl) { + x1e0_hintSteps.push_back({SAutoMapperHintStep::SwitchToUniverse{}}); + x1e0_hintSteps.push_back({SAutoMapperHintStep::PanToWorld{}, curMlvl}); + x1e0_hintSteps.push_back({SAutoMapperHintStep::SwitchToWorld{}, curMlvl}); + } else { + x1e0_hintSteps.push_back({SAutoMapperHintStep::ZoomOut{}}); + } + x1e0_hintSteps.push_back({SAutoMapperHintStep::PanToArea{}, loc.x8_areaId}); + x1e0_hintSteps.push_back({SAutoMapperHintStep::ZoomIn{}}); + x1e0_hintSteps.push_back({SAutoMapperHintStep::ShowBeacon{}, 1.f}); + x1f8_hintLocations.push_back({0, 0.f, loc.x0_mlvlId, loc.x8_areaId}); + } + } + + for (u32 i = 0; i < hintOpts.GetHintStates().size(); ++i) { + const CHintOptions::SHintState& state = hintOpts.GetHintStates()[i]; + if (navigating && hintOpts.GetNextHintIdx() == i) + continue; + if (state.x0_state != CHintOptions::EHintState::Displaying) + continue; + const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[i]; + for (const CGameHintInfo::SHintLocation& loc : hint.GetLocations()) + x1f8_hintLocations.push_back({1, 1.f, loc.x0_mlvlId, loc.x8_areaId}); + } +} + +CAssetId CAutoMapper::GetAreaHintDescriptionString(CAssetId mreaId) { + const CHintOptions& hintOpts = g_GameState->HintOptions(); + for (u32 i = 0; i < hintOpts.GetHintStates().size(); ++i) { + const CHintOptions::SHintState& state = hintOpts.GetHintStates()[i]; + if (state.x0_state != CHintOptions::EHintState::Displaying) + continue; + const CGameHintInfo::CGameHint& memHint = g_MemoryCardSys->GetHints()[i]; + for (const CGameHintInfo::SHintLocation& loc : memHint.GetLocations()) { + if (loc.x4_mreaId != mreaId) + continue; + for (const SAutoMapperHintLocation& hintLoc : x1f8_hintLocations) { + if (hintLoc.xc_areaId != loc.x8_areaId) + continue; + if (hintLoc.x4_beaconAlpha > 0.f) + return loc.xc_stringId; + } + } + } + return -1; +} + +void CAutoMapper::OnNewInGameGuiState(EInGameGuiState state, const CStateManager& mgr) { + if (state == EInGameGuiState::MapScreen) { + MP1::CMain::EnsureWorldPaksReady(); + const CWorld& wld = *mgr.GetWorld(); + const_cast(wld.GetMapWorld())->SetWhichMapAreasLoaded(wld, 0, 9999); + SetupHintNavigation(); + BeginMapperStateTransition(EAutoMapperState::MapScreen, mgr); + x28_frmeMapScreen = g_SimplePool->GetObj("FRME_MapScreen"); + SetResLockState(x210_lstick, true); + SetResLockState(x25c_cstick, true); + SetResLockState(x2a8_ltrigger, true); + SetResLockState(x2bc_rtrigger, true); + SetResLockState(x2d0_abutton, true); + } else { + MP1::CMain::EnsureWorldPakReady(g_GameState->CurrentWorldAssetId()); + if (x1bc_state == EAutoMapperState::MapScreenUniverse || x24_world == mgr.GetWorld()) { + BeginMapperStateTransition(EAutoMapperState::MiniMap, mgr); + x328_ = 0; + } + LeaveMapScreenState(); + } +} + +} // namespace urde diff --git a/Runtime/AutoMapper/CAutoMapper.hpp b/Runtime/AutoMapper/CAutoMapper.hpp index 0c019b75d..1005420d6 100644 --- a/Runtime/AutoMapper/CAutoMapper.hpp +++ b/Runtime/AutoMapper/CAutoMapper.hpp @@ -7,298 +7,259 @@ #include "zeus/CVector3f.hpp" #include "MP1/CInGameGuiManager.hpp" -namespace urde -{ +namespace urde { struct CFinalInput; class IWorld; class CMapWorldInfo; class CStateManager; class CMapUniverse; -class CAutoMapper -{ +class CAutoMapper { public: - using EInGameGuiState = MP1::EInGameGuiState; - enum class ELoadPhase - { - LoadResources, - LoadUniverse, - Done + using EInGameGuiState = MP1::EInGameGuiState; + enum class ELoadPhase { LoadResources, LoadUniverse, Done }; + enum class EAutoMapperState { MiniMap, MapScreen, MapScreenUniverse }; + struct SAutoMapperRenderState { + enum class Ease { None, Linear, Out, In, InOut }; + typedef zeus::CVector2i (*FGetViewportSize)(); + FGetViewportSize m_getViewportSize; + zeus::CVector2i x0_viewportSize; + zeus::CQuaternion x8_camOrientation; + float x18_camDist; + float x1c_camAngle; + zeus::CVector3f x20_areaPoint; + float x2c_drawDepth1; + float x30_drawDepth2; + float x34_alphaSurfaceVisited; + float x38_alphaOutlineVisited; + float x3c_alphaSurfaceUnvisited; + float x40_alphaOutlineUnvisited; + Ease x44_viewportEase; + Ease x48_camEase; + Ease x4c_pointEase; + Ease x50_depth1Ease; + Ease x54_depth2Ease; + Ease x58_alphaEase; + SAutoMapperRenderState() = default; + SAutoMapperRenderState(FGetViewportSize v1, const zeus::CQuaternion& rot, float f1, float f2, + const zeus::CVector3f& v2, float f3, float f4, float f5, float f6, float f7, float f8) + : m_getViewportSize(v1) + , x0_viewportSize(v1()) + , x8_camOrientation(rot) + , x18_camDist(f1) + , x1c_camAngle(f2) + , x20_areaPoint(v2) + , x2c_drawDepth1(f3) + , x30_drawDepth2(f4) + , x34_alphaSurfaceVisited(f5) + , x38_alphaOutlineVisited(f6) + , x3c_alphaSurfaceUnvisited(f7) + , x40_alphaOutlineUnvisited(f8) + , x44_viewportEase(Ease::None) + , x48_camEase(Ease::None) + , x4c_pointEase(Ease::None) + , x50_depth1Ease(Ease::None) + , x54_depth2Ease(Ease::None) + , x58_alphaEase(Ease::None) {} + + static void InterpolateWithClamp(const SAutoMapperRenderState& a, SAutoMapperRenderState& out, + const SAutoMapperRenderState& b, float t); + void ResetInterpolation() { + x44_viewportEase = Ease::None; + x48_camEase = Ease::None; + x4c_pointEase = Ease::None; + x50_depth1Ease = Ease::None; + x54_depth2Ease = Ease::None; + x58_alphaEase = Ease::None; + } + + zeus::CVector2i GetViewportSize() const { + if (m_getViewportSize) + return m_getViewportSize(); + else + return x0_viewportSize; + } + }; + + struct SAutoMapperHintStep { + enum class Type { PanToArea, PanToWorld, SwitchToUniverse, SwitchToWorld, ShowBeacon, ZoomIn, ZoomOut }; + struct PanToArea {}; + struct PanToWorld {}; + struct SwitchToUniverse {}; + struct SwitchToWorld {}; + struct ShowBeacon {}; + struct ZoomIn {}; + struct ZoomOut {}; + + Type x0_type; + union { + CAssetId x4_worldId; + TAreaId x4_areaId; + float x4_float; }; - enum class EAutoMapperState - { - MiniMap, - MapScreen, - MapScreenUniverse - }; - struct SAutoMapperRenderState - { - enum class Ease - { - None, - Linear, - Out, - In, - InOut - }; - typedef zeus::CVector2i(*FGetViewportSize)(); - FGetViewportSize m_getViewportSize; - zeus::CVector2i x0_viewportSize; - zeus::CQuaternion x8_camOrientation; - float x18_camDist; - float x1c_camAngle; - zeus::CVector3f x20_areaPoint; - float x2c_drawDepth1; - float x30_drawDepth2; - float x34_alphaSurfaceVisited; - float x38_alphaOutlineVisited; - float x3c_alphaSurfaceUnvisited; - float x40_alphaOutlineUnvisited; - Ease x44_viewportEase; - Ease x48_camEase; - Ease x4c_pointEase; - Ease x50_depth1Ease; - Ease x54_depth2Ease; - Ease x58_alphaEase; - SAutoMapperRenderState() = default; - SAutoMapperRenderState(FGetViewportSize v1, const zeus::CQuaternion& rot, - float f1, float f2, const zeus::CVector3f& v2, float f3, float f4, - float f5, float f6, float f7, float f8) - : m_getViewportSize(v1), x0_viewportSize(v1()), x8_camOrientation(rot), x18_camDist(f1), x1c_camAngle(f2), - x20_areaPoint(v2), x2c_drawDepth1(f3), x30_drawDepth2(f4), - x34_alphaSurfaceVisited(f5), x38_alphaOutlineVisited(f6), - x3c_alphaSurfaceUnvisited(f7), x40_alphaOutlineUnvisited(f8), - x44_viewportEase(Ease::None), x48_camEase(Ease::None), x4c_pointEase(Ease::None), - x50_depth1Ease(Ease::None), x54_depth2Ease(Ease::None), x58_alphaEase(Ease::None) {} + bool x8_processing = false; - static void InterpolateWithClamp(const SAutoMapperRenderState& a, - SAutoMapperRenderState& out, - const SAutoMapperRenderState& b, - float t); - void ResetInterpolation() - { - x44_viewportEase = Ease::None; - x48_camEase = Ease::None; - x4c_pointEase = Ease::None; - x50_depth1Ease = Ease::None; - x54_depth2Ease = Ease::None; - x58_alphaEase = Ease::None; - } + SAutoMapperHintStep(PanToArea, TAreaId areaId) : x0_type(Type::PanToArea), x4_areaId(areaId) {} + SAutoMapperHintStep(PanToWorld, CAssetId worldId) : x0_type(Type::PanToWorld), x4_worldId(worldId) {} + SAutoMapperHintStep(SwitchToUniverse) : x0_type(Type::SwitchToUniverse), x4_worldId(0) {} + SAutoMapperHintStep(SwitchToWorld, CAssetId worldId) : x0_type(Type::SwitchToWorld), x4_worldId(worldId) {} + SAutoMapperHintStep(ShowBeacon, float val) : x0_type(Type::ShowBeacon), x4_float(val) {} + SAutoMapperHintStep(ZoomIn) : x0_type(Type::ZoomIn), x4_worldId(0) {} + SAutoMapperHintStep(ZoomOut) : x0_type(Type::ZoomOut), x4_worldId(0) {} + }; - zeus::CVector2i GetViewportSize() const - { - if (m_getViewportSize) - return m_getViewportSize(); - else - return x0_viewportSize; - } - }; - - struct SAutoMapperHintStep - { - enum class Type - { - PanToArea, - PanToWorld, - SwitchToUniverse, - SwitchToWorld, - ShowBeacon, - ZoomIn, - ZoomOut - }; - struct PanToArea {}; - struct PanToWorld {}; - struct SwitchToUniverse {}; - struct SwitchToWorld {}; - struct ShowBeacon {}; - struct ZoomIn {}; - struct ZoomOut {}; - - Type x0_type; - union - { - CAssetId x4_worldId; - TAreaId x4_areaId; - float x4_float; - }; - bool x8_processing = false; - - SAutoMapperHintStep(PanToArea, TAreaId areaId) : x0_type(Type::PanToArea), x4_areaId(areaId) {} - SAutoMapperHintStep(PanToWorld, CAssetId worldId) : x0_type(Type::PanToWorld), x4_worldId(worldId) {} - SAutoMapperHintStep(SwitchToUniverse) : x0_type(Type::SwitchToUniverse), x4_worldId(0) {} - SAutoMapperHintStep(SwitchToWorld, CAssetId worldId) : x0_type(Type::SwitchToWorld), x4_worldId(worldId) {} - SAutoMapperHintStep(ShowBeacon, float val) : x0_type(Type::ShowBeacon), x4_float(val) {} - SAutoMapperHintStep(ZoomIn) : x0_type(Type::ZoomIn), x4_worldId(0) {} - SAutoMapperHintStep(ZoomOut) : x0_type(Type::ZoomOut), x4_worldId(0) {} - }; - - struct SAutoMapperHintLocation - { - u32 x0_showBeacon; - float x4_beaconAlpha; - CAssetId x8_worldId; - TAreaId xc_areaId; - }; + struct SAutoMapperHintLocation { + u32 x0_showBeacon; + float x4_beaconAlpha; + CAssetId x8_worldId; + TAreaId xc_areaId; + }; private: - enum class EZoomState - { - None, - In, - Out - }; + enum class EZoomState { None, In, Out }; - ELoadPhase x4_loadPhase = ELoadPhase::LoadResources; - TLockedToken x8_mapu; - std::vector> x14_dummyWorlds; - const CWorld* x24_world; - TLockedToken x28_frmeMapScreen; // Used to be ptr - bool m_frmeInitialized = false; - TLockedToken x30_miniMapSamus; - TLockedToken x3c_hintBeacon; - std::vector m_hintBeaconFilters; - rstl::reserved_vector, 5> x48_mapIcons; - CAssetId x74_areaHintDescId; - TLockedToken x78_areaHintDesc; - CAssetId x88_mapAreaStringId; - TLockedToken x8c_mapAreaString; // Used to be optional - u32 x9c_worldIdx = 0; - TAreaId xa0_curAreaId; - TAreaId xa4_otherAreaId; - SAutoMapperRenderState xa8_renderStates[3]; // xa8, x104, x160; current, next, prev - EAutoMapperState x1bc_state = EAutoMapperState::MiniMap; - EAutoMapperState x1c0_nextState = EAutoMapperState::MiniMap; - float x1c4_interpDur = 0.f; - float x1c8_interpTime = 0.f; - CSfxHandle x1cc_panningSfx; - CSfxHandle x1d0_rotatingSfx; - CSfxHandle x1d4_zoomingSfx; - float x1d8_flashTimer = 0.f; - float x1dc_playerFlashPulse = 0.f; - std::list x1e0_hintSteps; - std::list x1f8_hintLocations; - rstl::reserved_vector, 9> x210_lstick; - rstl::reserved_vector, 9> x25c_cstick; - rstl::reserved_vector, 2> x2a8_ltrigger; - rstl::reserved_vector, 2> x2bc_rtrigger; - rstl::reserved_vector, 2> x2d0_abutton; - u32 x2e4_lStickPos = 0; - u32 x2e8_rStickPos = 0; - u32 x2ec_lTriggerPos = 0; - u32 x2f0_rTriggerPos = 0; - u32 x2f4_aButtonPos = 0; - CGuiTextPane* x2f8_textpane_areaname = nullptr; - CGuiTextPane* x2fc_textpane_hint = nullptr; - CGuiTextPane* x300_textpane_instructions = nullptr; - CGuiTextPane* x304_textpane_instructions1 = nullptr; - CGuiTextPane* x308_textpane_instructions2 = nullptr; - CGuiWidget* x30c_basewidget_leftPane = nullptr; - CGuiWidget* x310_basewidget_yButtonPane = nullptr; - CGuiWidget* x314_basewidget_bottomPane = nullptr; - float x318_leftPanePos = 0.f; - float x31c_yButtonPanePos = 0.f; - float x320_bottomPanePos = 0.f; - EZoomState x324_zoomState = EZoomState::None; - u32 x328_ = 0; - bool x32c_loadingDummyWorld = false; + ELoadPhase x4_loadPhase = ELoadPhase::LoadResources; + TLockedToken x8_mapu; + std::vector> x14_dummyWorlds; + const CWorld* x24_world; + TLockedToken x28_frmeMapScreen; // Used to be ptr + bool m_frmeInitialized = false; + TLockedToken x30_miniMapSamus; + TLockedToken x3c_hintBeacon; + std::vector m_hintBeaconFilters; + rstl::reserved_vector, 5> x48_mapIcons; + CAssetId x74_areaHintDescId; + TLockedToken x78_areaHintDesc; + CAssetId x88_mapAreaStringId; + TLockedToken x8c_mapAreaString; // Used to be optional + u32 x9c_worldIdx = 0; + TAreaId xa0_curAreaId; + TAreaId xa4_otherAreaId; + SAutoMapperRenderState xa8_renderStates[3]; // xa8, x104, x160; current, next, prev + EAutoMapperState x1bc_state = EAutoMapperState::MiniMap; + EAutoMapperState x1c0_nextState = EAutoMapperState::MiniMap; + float x1c4_interpDur = 0.f; + float x1c8_interpTime = 0.f; + CSfxHandle x1cc_panningSfx; + CSfxHandle x1d0_rotatingSfx; + CSfxHandle x1d4_zoomingSfx; + float x1d8_flashTimer = 0.f; + float x1dc_playerFlashPulse = 0.f; + std::list x1e0_hintSteps; + std::list x1f8_hintLocations; + rstl::reserved_vector, 9> x210_lstick; + rstl::reserved_vector, 9> x25c_cstick; + rstl::reserved_vector, 2> x2a8_ltrigger; + rstl::reserved_vector, 2> x2bc_rtrigger; + rstl::reserved_vector, 2> x2d0_abutton; + u32 x2e4_lStickPos = 0; + u32 x2e8_rStickPos = 0; + u32 x2ec_lTriggerPos = 0; + u32 x2f0_rTriggerPos = 0; + u32 x2f4_aButtonPos = 0; + CGuiTextPane* x2f8_textpane_areaname = nullptr; + CGuiTextPane* x2fc_textpane_hint = nullptr; + CGuiTextPane* x300_textpane_instructions = nullptr; + CGuiTextPane* x304_textpane_instructions1 = nullptr; + CGuiTextPane* x308_textpane_instructions2 = nullptr; + CGuiWidget* x30c_basewidget_leftPane = nullptr; + CGuiWidget* x310_basewidget_yButtonPane = nullptr; + CGuiWidget* x314_basewidget_bottomPane = nullptr; + float x318_leftPanePos = 0.f; + float x31c_yButtonPanePos = 0.f; + float x320_bottomPanePos = 0.f; + EZoomState x324_zoomState = EZoomState::None; + u32 x328_ = 0; + bool x32c_loadingDummyWorld = false; - template - static void SetResLockState(T& list, bool lock) - { - for (auto& res : list) - if (lock) - res.Lock(); - else - res.Unlock(); - } - bool NotHintNavigating() const; - bool CanLeaveMapScreenInternal(const CStateManager& mgr) const; - void LeaveMapScreen(const CStateManager& mgr); - void SetupMiniMapWorld(const CStateManager& mgr); - bool HasCurrentMapUniverseWorld() const; - bool CheckDummyWorldLoad(const CStateManager& mgr); - void UpdateHintNavigation(float dt, const CStateManager& mgr); - static zeus::CVector2i GetMiniMapViewportSize(); - static zeus::CVector2i GetMapScreenViewportSize(); - static float GetMapAreaMiniMapDrawDepth() { return 2.f; } - float GetMapAreaMaxDrawDepth(const CStateManager&, TAreaId) const; - static float GetMapAreaMiniMapDrawAlphaSurfaceVisited(const CStateManager&); - static float GetMapAreaMiniMapDrawAlphaOutlineVisited(const CStateManager&); - static float GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(const CStateManager&); - static float GetMapAreaMiniMapDrawAlphaOutlineUnvisited(const CStateManager&); - float GetDesiredMiniMapCameraDistance(const CStateManager&) const; - static float GetBaseMapScreenCameraMoveSpeed(); - float GetClampedMapScreenCameraDistance(float); - float GetFinalMapScreenCameraMoveSpeed() const; - void ProcessMapRotateInput(const CFinalInput& input, const CStateManager& mgr); - void ProcessMapZoomInput(const CFinalInput& input, const CStateManager& mgr); - void ProcessMapPanInput(const CFinalInput& input, const CStateManager& mgr); - void SetShouldPanningSoundBePlaying(bool); - void SetShouldZoomingSoundBePlaying(bool); - void SetShouldRotatingSoundBePlaying(bool); - void TransformRenderStatesWorldToUniverse(); - void TransformRenderStatesUniverseToWorld(); - void TransformRenderStateWorldToUniverse(SAutoMapperRenderState&); - void SetupHintNavigation(); - CAssetId GetAreaHintDescriptionString(CAssetId mreaId); + template + static void SetResLockState(T& list, bool lock) { + for (auto& res : list) + if (lock) + res.Lock(); + else + res.Unlock(); + } + bool NotHintNavigating() const; + bool CanLeaveMapScreenInternal(const CStateManager& mgr) const; + void LeaveMapScreen(const CStateManager& mgr); + void SetupMiniMapWorld(const CStateManager& mgr); + bool HasCurrentMapUniverseWorld() const; + bool CheckDummyWorldLoad(const CStateManager& mgr); + void UpdateHintNavigation(float dt, const CStateManager& mgr); + static zeus::CVector2i GetMiniMapViewportSize(); + static zeus::CVector2i GetMapScreenViewportSize(); + static float GetMapAreaMiniMapDrawDepth() { return 2.f; } + float GetMapAreaMaxDrawDepth(const CStateManager&, TAreaId) const; + static float GetMapAreaMiniMapDrawAlphaSurfaceVisited(const CStateManager&); + static float GetMapAreaMiniMapDrawAlphaOutlineVisited(const CStateManager&); + static float GetMapAreaMiniMapDrawAlphaSurfaceUnvisited(const CStateManager&); + static float GetMapAreaMiniMapDrawAlphaOutlineUnvisited(const CStateManager&); + float GetDesiredMiniMapCameraDistance(const CStateManager&) const; + static float GetBaseMapScreenCameraMoveSpeed(); + float GetClampedMapScreenCameraDistance(float); + float GetFinalMapScreenCameraMoveSpeed() const; + void ProcessMapRotateInput(const CFinalInput& input, const CStateManager& mgr); + void ProcessMapZoomInput(const CFinalInput& input, const CStateManager& mgr); + void ProcessMapPanInput(const CFinalInput& input, const CStateManager& mgr); + void SetShouldPanningSoundBePlaying(bool); + void SetShouldZoomingSoundBePlaying(bool); + void SetShouldRotatingSoundBePlaying(bool); + void TransformRenderStatesWorldToUniverse(); + void TransformRenderStatesUniverseToWorld(); + void TransformRenderStateWorldToUniverse(SAutoMapperRenderState&); + void SetupHintNavigation(); + CAssetId GetAreaHintDescriptionString(CAssetId mreaId); public: - CAutoMapper(CStateManager& stateMgr); - bool CheckLoadComplete(); - bool CanLeaveMapScreen(const CStateManager&) const; - float GetMapRotationX() const; - float GetMapRotationZ() const; - u32 GetFocusAreaIndex() const; - CAssetId GetCurrWorldAssetId() const; - void SetCurWorldAssetId(CAssetId mlvlId); - void MuteAllLoopedSounds(); - void UnmuteAllLoopedSounds(); - void ProcessControllerInput(const CFinalInput&, CStateManager&); - bool IsInPlayerControlState() const; - void Update(float dt, const CStateManager& mgr); - void Draw(const CStateManager&, const zeus::CTransform&, float) const; - bool IsInOrTransitioningToMapScreenState() const; - float GetTimeIntoInterpolation() const; - bool IsFullyInMapScreenState() const; - void BeginMapperStateTransition(EAutoMapperState, const CStateManager&); - void CompleteMapperStateTransition(const CStateManager&); - void ResetInterpolationTimer(float); - SAutoMapperRenderState BuildMiniMapWorldRenderState(const CStateManager&, const zeus::CQuaternion&, TAreaId) const; - SAutoMapperRenderState BuildMapScreenWorldRenderState(const CStateManager&, const zeus::CQuaternion&, TAreaId, bool) const; - SAutoMapperRenderState BuildMapScreenUniverseRenderState(const CStateManager&, const zeus::CQuaternion&, TAreaId) const; - void LeaveMapScreenState(); - void ProcessMapScreenInput(const CFinalInput& input, const CStateManager& mgr); - zeus::CQuaternion GetMiniMapCameraOrientation(const CStateManager&) const; - zeus::CVector3f GetAreaPointOfInterest(const CStateManager&, TAreaId) const; - TAreaId FindClosestVisibleArea(const zeus::CVector3f&, const zeus::CUnitVector3f&, const CStateManager&, - const IWorld&, const CMapWorldInfo&) const; - std::pair - FindClosestVisibleWorld(const zeus::CVector3f&, const zeus::CUnitVector3f&, const CStateManager&) const; + CAutoMapper(CStateManager& stateMgr); + bool CheckLoadComplete(); + bool CanLeaveMapScreen(const CStateManager&) const; + float GetMapRotationX() const; + float GetMapRotationZ() const; + u32 GetFocusAreaIndex() const; + CAssetId GetCurrWorldAssetId() const; + void SetCurWorldAssetId(CAssetId mlvlId); + void MuteAllLoopedSounds(); + void UnmuteAllLoopedSounds(); + void ProcessControllerInput(const CFinalInput&, CStateManager&); + bool IsInPlayerControlState() const; + void Update(float dt, const CStateManager& mgr); + void Draw(const CStateManager&, const zeus::CTransform&, float) const; + bool IsInOrTransitioningToMapScreenState() const; + float GetTimeIntoInterpolation() const; + bool IsFullyInMapScreenState() const; + void BeginMapperStateTransition(EAutoMapperState, const CStateManager&); + void CompleteMapperStateTransition(const CStateManager&); + void ResetInterpolationTimer(float); + SAutoMapperRenderState BuildMiniMapWorldRenderState(const CStateManager&, const zeus::CQuaternion&, TAreaId) const; + SAutoMapperRenderState BuildMapScreenWorldRenderState(const CStateManager&, const zeus::CQuaternion&, TAreaId, + bool) const; + SAutoMapperRenderState BuildMapScreenUniverseRenderState(const CStateManager&, const zeus::CQuaternion&, + TAreaId) const; + void LeaveMapScreenState(); + void ProcessMapScreenInput(const CFinalInput& input, const CStateManager& mgr); + zeus::CQuaternion GetMiniMapCameraOrientation(const CStateManager&) const; + zeus::CVector3f GetAreaPointOfInterest(const CStateManager&, TAreaId) const; + TAreaId FindClosestVisibleArea(const zeus::CVector3f&, const zeus::CUnitVector3f&, const CStateManager&, + const IWorld&, const CMapWorldInfo&) const; + std::pair FindClosestVisibleWorld(const zeus::CVector3f&, const zeus::CUnitVector3f&, + const CStateManager&) const; - EAutoMapperState GetNextState() const { return x1c0_nextState; } - bool IsInMapperState(EAutoMapperState state) const - { - return state == x1bc_state && state == x1c0_nextState; - } - bool IsInMapperStateTransition() const - { - return x1c0_nextState != x1bc_state; - } - bool IsRenderStateInterpolating() const - { - return x1c8_interpTime < x1c4_interpDur; - } - bool IsStateTransitioning() const { return x1bc_state != x1c0_nextState; } - bool IsFullyInMiniMapState() const { return IsInMapperState(EAutoMapperState::MiniMap); } - bool IsFullyOutOfMiniMapState() const { return x1bc_state != EAutoMapperState::MiniMap && - x1c0_nextState != EAutoMapperState::MiniMap; } - void OnNewInGameGuiState(EInGameGuiState, const CStateManager&); - float GetInterp() const - { - if (x1c4_interpDur > 0.f) - return x1c8_interpTime / x1c4_interpDur; - return 0.f; - } + EAutoMapperState GetNextState() const { return x1c0_nextState; } + bool IsInMapperState(EAutoMapperState state) const { return state == x1bc_state && state == x1c0_nextState; } + bool IsInMapperStateTransition() const { return x1c0_nextState != x1bc_state; } + bool IsRenderStateInterpolating() const { return x1c8_interpTime < x1c4_interpDur; } + bool IsStateTransitioning() const { return x1bc_state != x1c0_nextState; } + bool IsFullyInMiniMapState() const { return IsInMapperState(EAutoMapperState::MiniMap); } + bool IsFullyOutOfMiniMapState() const { + return x1bc_state != EAutoMapperState::MiniMap && x1c0_nextState != EAutoMapperState::MiniMap; + } + void OnNewInGameGuiState(EInGameGuiState, const CStateManager&); + float GetInterp() const { + if (x1c4_interpDur > 0.f) + return x1c8_interpTime / x1c4_interpDur; + return 0.f; + } }; -} - +} // namespace urde diff --git a/Runtime/AutoMapper/CMapArea.cpp b/Runtime/AutoMapper/CMapArea.cpp index 23282230c..81f1ae75e 100644 --- a/Runtime/AutoMapper/CMapArea.cpp +++ b/Runtime/AutoMapper/CMapArea.cpp @@ -6,126 +6,105 @@ #include "World/CGameArea.hpp" #include "CResFactory.hpp" -namespace urde -{ +namespace urde { CMapArea::CMapArea(CInputStream& in, u32 size) - : x0_magic(in.readUint32()), - x4_version(in.readUint32Big()), - x8_(in.readUint32Big()), - xc_visibilityMode(EVisMode(in.readUint32Big())), - x10_box(zeus::CAABox::ReadBoundingBoxBig(in)), - x28_mappableObjCount(in.readUint32Big()), - x2c_vertexCount(in.readUint32Big()), - x30_surfaceCount(in.readUint32Big()), - x34_size(size - 52) -{ - x44_buf.reset(new u8[x34_size]); - in.readUBytesToBuf(x44_buf.get(), x34_size); - PostConstruct(); +: x0_magic(in.readUint32()) +, x4_version(in.readUint32Big()) +, x8_(in.readUint32Big()) +, xc_visibilityMode(EVisMode(in.readUint32Big())) +, x10_box(zeus::CAABox::ReadBoundingBoxBig(in)) +, x28_mappableObjCount(in.readUint32Big()) +, x2c_vertexCount(in.readUint32Big()) +, x30_surfaceCount(in.readUint32Big()) +, x34_size(size - 52) { + x44_buf.reset(new u8[x34_size]); + in.readUBytesToBuf(x44_buf.get(), x34_size); + PostConstruct(); } -void CMapArea::PostConstruct() -{ - x38_moStart = x44_buf.get(); - x3c_vertexStart = x38_moStart + (x28_mappableObjCount * 0x50); - x40_surfaceStart = x3c_vertexStart + (x2c_vertexCount * 12); +void CMapArea::PostConstruct() { + x38_moStart = x44_buf.get(); + x3c_vertexStart = x38_moStart + (x28_mappableObjCount * 0x50); + x40_surfaceStart = x3c_vertexStart + (x2c_vertexCount * 12); - m_mappableObjects.reserve(x28_mappableObjCount); - for (u32 i = 0, j=0 ; i(tmp); - m_verts.emplace_back(hecl::SBig(fl[0]), hecl::SBig(fl[1]), hecl::SBig(fl[2])); - tmp += 12; - } + u8* tmp = x3c_vertexStart; + m_verts.reserve(x2c_vertexCount); + for (u32 i = 0; i < x2c_vertexCount; ++i) { + float* fl = reinterpret_cast(tmp); + m_verts.emplace_back(hecl::SBig(fl[0]), hecl::SBig(fl[1]), hecl::SBig(fl[2])); + tmp += 12; + } - std::vector index; - m_surfaces.reserve(x30_surfaceCount); - for (u32 i = 0, j = 0 ; i index; + m_surfaces.reserve(x30_surfaceCount); + for (u32 i = 0, j = 0; i < x30_surfaceCount; ++i, j += 32) { + m_surfaces.emplace_back(x40_surfaceStart + j); + m_surfaces.back().PostConstruct(x44_buf.get(), index); + } - CGraphics::CommitResources([this, &index](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, m_verts.data(), 16, m_verts.size()); - m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, index.data(), 4, index.size()); + CGraphics::CommitResources([this, &index](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, m_verts.data(), 16, m_verts.size()); + m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, index.data(), 4, index.size()); - /* Only the map universe specifies Always; it draws a maximum of 1016 instances */ - size_t instCount = (xc_visibilityMode == EVisMode::Always) ? 1024 : 1; + /* Only the map universe specifies Always; it draws a maximum of 1016 instances */ + size_t instCount = (xc_visibilityMode == EVisMode::Always) ? 1024 : 1; - for (u32 i = 0 ; i& linePrims = instance.m_linePrims; - linePrims.reserve(outlineCount * 2); - for (u32 j=0 ; j<2 ; ++j) - { - r.seek(4, athena::SeekOrigin::Begin); - for (u32 i=0 ; i& linePrims = instance.m_linePrims; + linePrims.reserve(outlineCount * 2); + for (u32 j = 0; j < 2; ++j) { + r.seek(4, athena::SeekOrigin::Begin); + for (u32 i = 0; i < outlineCount; ++i) { + u32 count = r.readUint32Big(); + r.seek(count); + r.seekAlign4(); + linePrims.emplace_back(ctx, CLineRenderer::EPrimitiveMode::LineStrip, count, nullptr, false, false, true); + } } - - for (u32 i = 0 ; iTranslateOriginalToNew(0xB1AC4D65)) // Phazon Mines - { - const zeus::CTransform& areaXf = world.IGetAreaAlways(aid)->IGetTM(); - const zeus::CVector3f& postVec = MinesPostTransforms[MinesPostTransformIndices[aid]]; - return zeus::CTransform::Translate(postVec) * areaXf; - } - else - { - return world.IGetAreaAlways(aid)->IGetTM(); - } +zeus::CTransform CMapArea::GetAreaPostTransform(const IWorld& world, TAreaId aid) const { + if (world.IGetWorldAssetId() == g_ResFactory->TranslateOriginalToNew(0xB1AC4D65)) // Phazon Mines + { + const zeus::CTransform& areaXf = world.IGetAreaAlways(aid)->IGetTM(); + const zeus::CVector3f& postVec = MinesPostTransforms[MinesPostTransformIndices[aid]]; + return zeus::CTransform::Translate(postVec) * areaXf; + } else { + return world.IGetAreaAlways(aid)->IGetTM(); + } } -const zeus::CVector3f& CMapArea::GetAreaPostTranslate(const IWorld& world, TAreaId aid) -{ - if (world.IGetWorldAssetId() == g_ResFactory->TranslateOriginalToNew(0xB1AC4D65)) // Phazon Mines - return MinesPostTransforms[MinesPostTransformIndices[aid]]; - else - return zeus::CVector3f::skZero; +const zeus::CVector3f& CMapArea::GetAreaPostTranslate(const IWorld& world, TAreaId aid) { + if (world.IGetWorldAssetId() == g_ResFactory->TranslateOriginalToNew(0xB1AC4D65)) // Phazon Mines + return MinesPostTransforms[MinesPostTransformIndices[aid]]; + else + return zeus::CVector3f::skZero; } -CMapArea::CMapAreaSurface::CMapAreaSurface(const void* surfBuf) -{ - athena::io::MemoryReader r(surfBuf, 32); - x0_normal = r.readVec3fBig(); - xc_centroid = r.readVec3fBig(); - x18_surfOffset = reinterpret_cast(uintptr_t(r.readUint32Big())); - x1c_outlineOffset = reinterpret_cast(uintptr_t(r.readUint32Big())); +CMapArea::CMapAreaSurface::CMapAreaSurface(const void* surfBuf) { + athena::io::MemoryReader r(surfBuf, 32); + x0_normal = r.readVec3fBig(); + xc_centroid = r.readVec3fBig(); + x18_surfOffset = reinterpret_cast(uintptr_t(r.readUint32Big())); + x1c_outlineOffset = reinterpret_cast(uintptr_t(r.readUint32Big())); } -void CMapArea::CMapAreaSurface::PostConstruct(const u8* buf, std::vector& index) -{ - x18_surfOffset = buf + reinterpret_cast(x18_surfOffset); - x1c_outlineOffset = buf + reinterpret_cast(x1c_outlineOffset); +void CMapArea::CMapAreaSurface::PostConstruct(const u8* buf, std::vector& index) { + x18_surfOffset = buf + reinterpret_cast(x18_surfOffset); + x1c_outlineOffset = buf + reinterpret_cast(x1c_outlineOffset); - m_primStart = index.size(); - bool start = true; - { - athena::io::MemoryReader r(x18_surfOffset, INT_MAX); - u32 primCount = r.readUint32Big(); - for (u32 i=0 ; i= m_instances.size()) - return; + const zeus::CColor& lineColor, float lineWidth, int instIdx) const { + if (instIdx >= m_instances.size()) + return; - Instance& instance = const_cast(m_instances[instIdx]); + Instance& instance = const_cast(m_instances[instIdx]); - if (surfColor.a()) - instance.m_surfacePrims.draw(surfColor, m_primStart, m_primCount); + if (surfColor.a()) + instance.m_surfacePrims.draw(surfColor, m_primStart, m_primCount); - if (lineColor.a()) - { - bool draw2 = lineWidth > 1.f; - athena::io::MemoryReader r(x1c_outlineOffset, INT_MAX); - u32 outlineCount = r.readUint32Big(); + if (lineColor.a()) { + bool draw2 = lineWidth > 1.f; + athena::io::MemoryReader r(x1c_outlineOffset, INT_MAX); + u32 outlineCount = r.readUint32Big(); - std::vector& linePrims = instance.m_linePrims; - zeus::CColor color = lineColor; - if (draw2) - color.a() *= 0.5f; - float width = lineWidth; + std::vector& linePrims = instance.m_linePrims; + zeus::CColor color = lineColor; + if (draw2) + color.a() *= 0.5f; + float width = lineWidth; - auto primIt = linePrims.begin(); - for (u32 j=0 ; j<=u32(draw2) ; ++j) - { - r.seek(4, athena::SeekOrigin::Begin); - for (u32 i=0 ; iResourceSize(objTag); - return TToken::GetIObjObjectFor(std::make_unique(in, size)); + CObjectReference*) { + u32 size = g_ResFactory->ResourceSize(objTag); + return TToken::GetIObjObjectFor(std::make_unique(in, size)); } -} +} // namespace urde diff --git a/Runtime/AutoMapper/CMapArea.hpp b/Runtime/AutoMapper/CMapArea.hpp index 1aaac6e60..a452a9113 100644 --- a/Runtime/AutoMapper/CMapArea.hpp +++ b/Runtime/AutoMapper/CMapArea.hpp @@ -9,85 +9,74 @@ #include "Graphics/Shaders/CMapSurfaceShader.hpp" #include "CMappableObject.hpp" -namespace urde -{ +namespace urde { class IWorld; -class CMapArea -{ +class CMapArea { public: - class CMapAreaSurface - { - friend class CMapArea; - zeus::CVector3f x0_normal; - zeus::CVector3f xc_centroid; - const u8* x18_surfOffset; - const u8* x1c_outlineOffset; - u32 m_primStart; - u32 m_primCount; - struct Instance - { - CMapSurfaceShader m_surfacePrims; - std::vector m_linePrims; - Instance(boo::IGraphicsDataFactory::Context& ctx, - const boo::ObjToken& vbo, - const boo::ObjToken& ibo) - : m_surfacePrims(ctx, vbo, ibo) {} - Instance(Instance&&) = default; - Instance& operator=(Instance&&) = default; - }; - std::vector m_instances; - public: - CMapAreaSurface(const void* surfBuf); - CMapAreaSurface(CMapAreaSurface&&) = default; - void PostConstruct(const u8* buf, std::vector& index); - void Draw(const zeus::CVector3f* verts, const zeus::CColor& surfColor, - const zeus::CColor& lineColor, float lineWidth, int instIdx=0) const; - const zeus::CVector3f& GetNormal() const { return x0_normal; } - const zeus::CVector3f& GetCenterPosition() const { return xc_centroid; } - }; - enum class EVisMode - { - Always, - MapStationOrVisit, - Visit, - Never + class CMapAreaSurface { + friend class CMapArea; + zeus::CVector3f x0_normal; + zeus::CVector3f xc_centroid; + const u8* x18_surfOffset; + const u8* x1c_outlineOffset; + u32 m_primStart; + u32 m_primCount; + struct Instance { + CMapSurfaceShader m_surfacePrims; + std::vector m_linePrims; + Instance(boo::IGraphicsDataFactory::Context& ctx, const boo::ObjToken& vbo, + const boo::ObjToken& ibo) + : m_surfacePrims(ctx, vbo, ibo) {} + Instance(Instance&&) = default; + Instance& operator=(Instance&&) = default; }; + std::vector m_instances; + + public: + CMapAreaSurface(const void* surfBuf); + CMapAreaSurface(CMapAreaSurface&&) = default; + void PostConstruct(const u8* buf, std::vector& index); + void Draw(const zeus::CVector3f* verts, const zeus::CColor& surfColor, const zeus::CColor& lineColor, + float lineWidth, int instIdx = 0) const; + const zeus::CVector3f& GetNormal() const { return x0_normal; } + const zeus::CVector3f& GetCenterPosition() const { return xc_centroid; } + }; + enum class EVisMode { Always, MapStationOrVisit, Visit, Never }; private: - u32 x0_magic; - u32 x4_version; - u32 x8_; - EVisMode xc_visibilityMode; - zeus::CAABox x10_box; - u32 x28_mappableObjCount; - u32 x2c_vertexCount; - u32 x30_surfaceCount; - u32 x34_size; - u8* x38_moStart; - std::vector m_mappableObjects; - u8* x3c_vertexStart; - std::vector m_verts; - u8* x40_surfaceStart; - std::vector m_surfaces; - std::unique_ptr x44_buf; - boo::ObjToken m_vbo; - boo::ObjToken m_ibo; + u32 x0_magic; + u32 x4_version; + u32 x8_; + EVisMode xc_visibilityMode; + zeus::CAABox x10_box; + u32 x28_mappableObjCount; + u32 x2c_vertexCount; + u32 x30_surfaceCount; + u32 x34_size; + u8* x38_moStart; + std::vector m_mappableObjects; + u8* x3c_vertexStart; + std::vector m_verts; + u8* x40_surfaceStart; + std::vector m_surfaces; + std::unique_ptr x44_buf; + boo::ObjToken m_vbo; + boo::ObjToken m_ibo; public: - CMapArea(CInputStream& in, u32 size); - void PostConstruct(); - bool GetIsVisibleToAutoMapper(bool worldVis, bool areaVis) const; - zeus::CVector3f GetAreaCenterPoint() const { return x10_box.center(); } - const zeus::CAABox& GetBoundingBox() const { return x10_box; } - const CMappableObject& GetMappableObject(int idx) const { return m_mappableObjects[idx]; } - const CMapAreaSurface& GetSurface(int idx) const { return m_surfaces[idx]; } - u32 GetNumMappableObjects() const { return m_mappableObjects.size(); } - u32 GetNumSurfaces() const { return m_surfaces.size(); } - zeus::CTransform GetAreaPostTransform(const IWorld& world, TAreaId aid) const; - static const zeus::CVector3f& GetAreaPostTranslate(const IWorld& world, TAreaId aid); - const zeus::CVector3f* GetVertices() const { return m_verts.data(); } + CMapArea(CInputStream& in, u32 size); + void PostConstruct(); + bool GetIsVisibleToAutoMapper(bool worldVis, bool areaVis) const; + zeus::CVector3f GetAreaCenterPoint() const { return x10_box.center(); } + const zeus::CAABox& GetBoundingBox() const { return x10_box; } + const CMappableObject& GetMappableObject(int idx) const { return m_mappableObjects[idx]; } + const CMapAreaSurface& GetSurface(int idx) const { return m_surfaces[idx]; } + u32 GetNumMappableObjects() const { return m_mappableObjects.size(); } + u32 GetNumSurfaces() const { return m_surfaces.size(); } + zeus::CTransform GetAreaPostTransform(const IWorld& world, TAreaId aid) const; + static const zeus::CVector3f& GetAreaPostTranslate(const IWorld& world, TAreaId aid); + const zeus::CVector3f* GetVertices() const { return m_verts.data(); } }; -CFactoryFnReturn FMapAreaFactory(const SObjectTag& objTag, CInputStream& in, const CVParamTransfer&, - CObjectReference*); -} +CFactoryFnReturn FMapAreaFactory(const SObjectTag& objTag, CInputStream& in, const CVParamTransfer&, CObjectReference*); +} // namespace urde diff --git a/Runtime/AutoMapper/CMapUniverse.cpp b/Runtime/AutoMapper/CMapUniverse.cpp index 790dc968a..024e95316 100644 --- a/Runtime/AutoMapper/CMapUniverse.cpp +++ b/Runtime/AutoMapper/CMapUniverse.cpp @@ -3,140 +3,120 @@ #include "CSimplePool.hpp" #include "CGameState.hpp" -namespace urde -{ +namespace urde { -CMapUniverse::CMapUniverse(CInputStream& in, u32 version) - : x0_hexagonId(in.readUint32Big()) -{ - x4_hexagonToken = g_SimplePool->GetObj({FOURCC('MAPA'), x0_hexagonId}); - u32 count = in.readUint32Big(); - x10_worldDatas.reserve(count); - for (u32 i = 0 ; iGetObj({FOURCC('MAPA'), x0_hexagonId}); + u32 count = in.readUint32Big(); + x10_worldDatas.reserve(count); + for (u32 i = 0; i < count; ++i) + x10_worldDatas.emplace_back(in, version); } CMapUniverse::CMapWorldData::CMapWorldData(CInputStream& in, u32 version) - : x0_label(in.readString()), - x10_worldAssetId(in.readUint32Big()) -{ - x14_transform.read34RowMajor(in); - u32 worldCount = in.readUint32Big(); - x44_hexagonXfs.reserve(worldCount); - for (u32 i = 0 ; iGetNumSurfaces(); + + std::vector sortInfos; + sortInfos.reserve(totalSurfaceCount); + + for (int w = 0; w < x10_worldDatas.size(); ++w) { + const CMapWorldData& data = x10_worldDatas[w]; + const CMapWorldInfo& mwInfo = *g_GameState->StateForWorld(data.GetWorldAssetId()).MapWorldInfo(); + if (!mwInfo.IsAnythingSet()) + continue; + zeus::CColor surfColor, outlineColor; + if (w == parms.GetFocusWorldIndex()) { + surfColor = data.GetSurfaceColorSelected(); + surfColor.a() *= parms.GetAlpha(); + outlineColor = data.GetOutlineColorSelected(); + outlineColor.a() *= parms.GetAlpha(); + } else { + surfColor = data.GetSurfaceColorUnselected(); + surfColor.a() *= parms.GetAlpha(); + outlineColor = data.GetSurfaceColorUnselected(); + outlineColor.a() *= parms.GetAlpha(); } - if (version != 0) - x54_surfColorSelected.readRGBABig(in); - else - x54_surfColorSelected.fromRGBA32(255 | (u32(x10_worldAssetId.Value()) & 0xFFFFFF00)); + for (int h = 0; h < data.GetNumMapAreaDatas(); ++h) { + zeus::CTransform hexXf = parms.GetCameraTransform().inverse() * data.GetMapAreaData(h); + for (int s = 0; s < x4_hexagonToken->GetNumSurfaces(); ++s) { + const CMapArea::CMapAreaSurface& surf = x4_hexagonToken->GetSurface(s); + zeus::CVector3f centerPos = hexXf * surf.GetCenterPosition(); + sortInfos.emplace_back(centerPos.y(), w, h, s, surfColor, outlineColor); + } + } + } - x58_outlineColorSelected = zeus::CColor::lerp(zeus::CColor::skWhite, x54_surfColorSelected, 0.5f); - x5c_surfColorUnselected = zeus::CColor::lerp(zeus::CColor::skBlack, x54_surfColorSelected, 0.5f); - x60_outlineColorUnselected = zeus::CColor::lerp(zeus::CColor::skWhite, x5c_surfColorUnselected, 0.5f); + std::sort(sortInfos.begin(), sortInfos.end(), [](const CMapObjectSortInfo& a, const CMapObjectSortInfo& b) { + return a.GetZDistance() > b.GetZDistance(); + }); - for (const zeus::CTransform& xf : x44_hexagonXfs) - x64_centerPoint += xf.origin; - - x64_centerPoint *= zeus::CVector3f(1.0f / float(x44_hexagonXfs.size())); -} - -void CMapUniverse::Draw(const CMapUniverseDrawParms& parms, const zeus::CVector3f&, float, float) const -{ - if (!x4_hexagonToken.IsLoaded()) - return; - - u32 totalSurfaceCount = 0; - for (const CMapWorldData& data : x10_worldDatas) - totalSurfaceCount += data.GetNumMapAreaDatas() * x4_hexagonToken->GetNumSurfaces(); - - std::vector sortInfos; - sortInfos.reserve(totalSurfaceCount); - - for (int w=0 ; wStateForWorld(data.GetWorldAssetId()).MapWorldInfo(); - if (!mwInfo.IsAnythingSet()) - continue; - zeus::CColor surfColor, outlineColor; - if (w == parms.GetFocusWorldIndex()) - { - surfColor = data.GetSurfaceColorSelected(); - surfColor.a() *= parms.GetAlpha(); - outlineColor = data.GetOutlineColorSelected(); - outlineColor.a() *= parms.GetAlpha(); - } - else - { - surfColor = data.GetSurfaceColorUnselected(); - surfColor.a() *= parms.GetAlpha(); - outlineColor = data.GetSurfaceColorUnselected(); - outlineColor.a() *= parms.GetAlpha(); - } - - for (int h=0 ; hGetNumSurfaces() ; ++s) - { - const CMapArea::CMapAreaSurface& surf = x4_hexagonToken->GetSurface(s); - zeus::CVector3f centerPos = hexXf * surf.GetCenterPosition(); - sortInfos.emplace_back(centerPos.y(), w, h, s, surfColor, outlineColor); - } - } + int lastWldIdx = -1; + int lastHexIdx = -1; + int instIdx = 0; + for (const CMapObjectSortInfo& info : sortInfos) { + const CMapWorldData& mwData = x10_worldDatas[info.GetWorldIndex()]; + zeus::CColor surfColor = info.GetSurfaceColor(); + zeus::CColor outlineColor = info.GetOutlineColor(); + if (parms.GetWorldAssetId() == mwData.GetWorldAssetId() && parms.GetClosestArea() == info.GetAreaIndex()) { + surfColor = zeus::CColor::lerp(g_tweakAutoMapper->GetSurfaceSelectVisitedColor(), + g_tweakAutoMapper->GetAreaFlashPulseColor(), parms.GetFlashPulse()); + surfColor.a() = info.GetSurfaceColor().a(); + outlineColor = zeus::CColor::lerp(g_tweakAutoMapper->GetOutlineSelectVisitedColor(), + g_tweakAutoMapper->GetAreaFlashPulseColor(), parms.GetFlashPulse()); + outlineColor.a() = info.GetOutlineColor().a(); } - std::sort(sortInfos.begin(), sortInfos.end(), - [](const CMapObjectSortInfo& a, const CMapObjectSortInfo& b) - { - return a.GetZDistance() > b.GetZDistance(); - }); + zeus::CTransform hexXf = mwData.GetMapAreaData(info.GetAreaIndex()); + hexXf.orthonormalize(); + const CMapArea::CMapAreaSurface& surf = x4_hexagonToken->GetSurface(info.GetObjectIndex()); + zeus::CColor color(std::max(0.f, (-parms.GetCameraTransform().basis[1]).dot(hexXf.rotate(surf.GetNormal()))) * + g_tweakAutoMapper->GetMapSurfaceNormColorLinear() + + g_tweakAutoMapper->GetMapSurfaceNormColorConstant()); + surfColor *= color; - int lastWldIdx = -1; - int lastHexIdx = -1; - int instIdx = 0; - for (const CMapObjectSortInfo& info : sortInfos) - { - const CMapWorldData& mwData = x10_worldDatas[info.GetWorldIndex()]; - zeus::CColor surfColor = info.GetSurfaceColor(); - zeus::CColor outlineColor = info.GetOutlineColor(); - if (parms.GetWorldAssetId() == mwData.GetWorldAssetId() && parms.GetClosestArea() == info.GetAreaIndex()) - { - surfColor = zeus::CColor::lerp(g_tweakAutoMapper->GetSurfaceSelectVisitedColor(), - g_tweakAutoMapper->GetAreaFlashPulseColor(), - parms.GetFlashPulse()); - surfColor.a() = info.GetSurfaceColor().a(); - outlineColor = zeus::CColor::lerp(g_tweakAutoMapper->GetOutlineSelectVisitedColor(), - g_tweakAutoMapper->GetAreaFlashPulseColor(), - parms.GetFlashPulse()); - outlineColor.a() = info.GetOutlineColor().a(); - } + if (info.GetAreaIndex() != lastHexIdx || info.GetWorldIndex() != lastWldIdx) + CGraphics::SetModelMatrix(parms.GetPaneProjectionTransform() * mwData.GetMapAreaData(info.GetAreaIndex())); - zeus::CTransform hexXf = mwData.GetMapAreaData(info.GetAreaIndex()); - hexXf.orthonormalize(); - const CMapArea::CMapAreaSurface& surf = x4_hexagonToken->GetSurface(info.GetObjectIndex()); - zeus::CColor color(std::max(0.f, (-parms.GetCameraTransform().basis[1]).dot(hexXf.rotate(surf.GetNormal()))) * - g_tweakAutoMapper->GetMapSurfaceNormColorLinear() + g_tweakAutoMapper->GetMapSurfaceNormColorConstant()); - surfColor *= color; - - if (info.GetAreaIndex() != lastHexIdx || info.GetWorldIndex() != lastWldIdx) - CGraphics::SetModelMatrix(parms.GetPaneProjectionTransform() * mwData.GetMapAreaData(info.GetAreaIndex())); - - surf.Draw(x4_hexagonToken->GetVertices(), surfColor, outlineColor, 2.f, instIdx++); - } + surf.Draw(x4_hexagonToken->GetVertices(), surfColor, outlineColor, 2.f, instIdx++); + } } -CFactoryFnReturn FMapUniverseFactory(const SObjectTag&, CInputStream& in, const CVParamTransfer&, - CObjectReference*) -{ - in.readUint32Big(); - u32 version = in.readUint32Big(); +CFactoryFnReturn FMapUniverseFactory(const SObjectTag&, CInputStream& in, const CVParamTransfer&, CObjectReference*) { + in.readUint32Big(); + u32 version = in.readUint32Big(); - return TToken::GetIObjObjectFor(std::make_unique(in, version)); + return TToken::GetIObjObjectFor(std::make_unique(in, version)); } -} +} // namespace urde diff --git a/Runtime/AutoMapper/CMapUniverse.hpp b/Runtime/AutoMapper/CMapUniverse.hpp index b43b608a0..3a9595822 100644 --- a/Runtime/AutoMapper/CMapUniverse.hpp +++ b/Runtime/AutoMapper/CMapUniverse.hpp @@ -8,115 +8,116 @@ #include "CToken.hpp" #include "CMapArea.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class CMapUniverse -{ +class CMapUniverse { public: - class CMapUniverseDrawParms - { - float x0_alpha; - int x4_wldIdx; - CAssetId x8_wldRes; - int xc_closestHex; - float x10_flashPulse; - //const CStateManager& x14_mgr; - const zeus::CTransform& x18_model; - const zeus::CTransform& x1c_view; - public: - CMapUniverseDrawParms(float alpha, int wldIdx, CAssetId wldRes, int closestHex, - float flashPulse, const CStateManager& mgr, - const zeus::CTransform& model, const zeus::CTransform& view) - : x0_alpha(alpha), - x4_wldIdx(wldIdx), - x8_wldRes(wldRes), - xc_closestHex(closestHex), - x10_flashPulse(flashPulse), - //x14_mgr(mgr), - x18_model(model), - x1c_view(view) - {} - int GetFocusWorldIndex() const { return x4_wldIdx; } - const zeus::CTransform& GetCameraTransform() const { return x1c_view; } - const zeus::CTransform& GetPaneProjectionTransform() const { return x18_model; } - float GetAlpha() const { return x0_alpha; } - CAssetId GetWorldAssetId() const { return x8_wldRes; } - int GetClosestArea() const { return xc_closestHex; } - float GetFlashPulse() const { return x10_flashPulse; } - }; + class CMapUniverseDrawParms { + float x0_alpha; + int x4_wldIdx; + CAssetId x8_wldRes; + int xc_closestHex; + float x10_flashPulse; + // const CStateManager& x14_mgr; + const zeus::CTransform& x18_model; + const zeus::CTransform& x1c_view; - class CMapObjectSortInfo - { - float x0_zDist; - int x4_wldIdx; - int x8_hexIdx; - int xc_surfIdx; - zeus::CColor x10_surfColor; - zeus::CColor x14_outlineColor; - public: - CMapObjectSortInfo(float zDist, int wldIdx, int hexIdx, int surfIdx, - const zeus::CColor& surf, const zeus::CColor& outline) - : x0_zDist(zDist), x4_wldIdx(wldIdx), x8_hexIdx(hexIdx), xc_surfIdx(surfIdx), - x10_surfColor(surf), x14_outlineColor(outline) {} - const zeus::CColor& GetOutlineColor() const { return x14_outlineColor; } - const zeus::CColor& GetSurfaceColor() const { return x10_surfColor; } - int GetObjectIndex() const { return xc_surfIdx; } - int GetAreaIndex() const { return x8_hexIdx; } - int GetWorldIndex() const { return x4_wldIdx; } - float GetZDistance() const { return x0_zDist; } - }; + public: + CMapUniverseDrawParms(float alpha, int wldIdx, CAssetId wldRes, int closestHex, float flashPulse, + const CStateManager& mgr, const zeus::CTransform& model, const zeus::CTransform& view) + : x0_alpha(alpha) + , x4_wldIdx(wldIdx) + , x8_wldRes(wldRes) + , xc_closestHex(closestHex) + , x10_flashPulse(flashPulse) + , + // x14_mgr(mgr), + x18_model(model) + , x1c_view(view) {} + int GetFocusWorldIndex() const { return x4_wldIdx; } + const zeus::CTransform& GetCameraTransform() const { return x1c_view; } + const zeus::CTransform& GetPaneProjectionTransform() const { return x18_model; } + float GetAlpha() const { return x0_alpha; } + CAssetId GetWorldAssetId() const { return x8_wldRes; } + int GetClosestArea() const { return xc_closestHex; } + float GetFlashPulse() const { return x10_flashPulse; } + }; - class CMapWorldData - { - std::string x0_label; - CAssetId x10_worldAssetId; - zeus::CTransform x14_transform; - std::vector x44_hexagonXfs; - zeus::CColor x54_surfColorSelected; - zeus::CColor x58_outlineColorSelected = zeus::CColor(1.0f, 0.0f, 1.0f); - zeus::CColor x5c_surfColorUnselected = zeus::CColor(1.0f, 0.0f, 1.0f); - zeus::CColor x60_outlineColorUnselected = zeus::CColor(1.0f, 0.0f, 1.0f); - zeus::CVector3f x64_centerPoint = zeus::CVector3f::skZero; - public: - CMapWorldData(CInputStream& in, u32 version); - CAssetId GetWorldAssetId() const { return x10_worldAssetId; } - const zeus::CVector3f& GetWorldCenterPoint() const { return x64_centerPoint; } - std::string_view GetWorldLabel() const { return x0_label; } - const zeus::CTransform& GetWorldTransform() const { return x14_transform; } - const zeus::CTransform& GetMapAreaData(s32 idx) const { return x44_hexagonXfs[idx]; } - u32 GetNumMapAreaDatas() const { return x44_hexagonXfs.size(); } - const zeus::CColor& GetOutlineColorUnselected() const { return x60_outlineColorUnselected; } - const zeus::CColor& GetOutlineColorSelected() const { return x58_outlineColorSelected; } - const zeus::CColor& GetSurfaceColorUnselected() const { return x5c_surfColorUnselected; } - const zeus::CColor& GetSurfaceColorSelected() const { return x54_surfColorSelected; } - }; + class CMapObjectSortInfo { + float x0_zDist; + int x4_wldIdx; + int x8_hexIdx; + int xc_surfIdx; + zeus::CColor x10_surfColor; + zeus::CColor x14_outlineColor; + + public: + CMapObjectSortInfo(float zDist, int wldIdx, int hexIdx, int surfIdx, const zeus::CColor& surf, + const zeus::CColor& outline) + : x0_zDist(zDist) + , x4_wldIdx(wldIdx) + , x8_hexIdx(hexIdx) + , xc_surfIdx(surfIdx) + , x10_surfColor(surf) + , x14_outlineColor(outline) {} + const zeus::CColor& GetOutlineColor() const { return x14_outlineColor; } + const zeus::CColor& GetSurfaceColor() const { return x10_surfColor; } + int GetObjectIndex() const { return xc_surfIdx; } + int GetAreaIndex() const { return x8_hexIdx; } + int GetWorldIndex() const { return x4_wldIdx; } + float GetZDistance() const { return x0_zDist; } + }; + + class CMapWorldData { + std::string x0_label; + CAssetId x10_worldAssetId; + zeus::CTransform x14_transform; + std::vector x44_hexagonXfs; + zeus::CColor x54_surfColorSelected; + zeus::CColor x58_outlineColorSelected = zeus::CColor(1.0f, 0.0f, 1.0f); + zeus::CColor x5c_surfColorUnselected = zeus::CColor(1.0f, 0.0f, 1.0f); + zeus::CColor x60_outlineColorUnselected = zeus::CColor(1.0f, 0.0f, 1.0f); + zeus::CVector3f x64_centerPoint = zeus::CVector3f::skZero; + + public: + CMapWorldData(CInputStream& in, u32 version); + CAssetId GetWorldAssetId() const { return x10_worldAssetId; } + const zeus::CVector3f& GetWorldCenterPoint() const { return x64_centerPoint; } + std::string_view GetWorldLabel() const { return x0_label; } + const zeus::CTransform& GetWorldTransform() const { return x14_transform; } + const zeus::CTransform& GetMapAreaData(s32 idx) const { return x44_hexagonXfs[idx]; } + u32 GetNumMapAreaDatas() const { return x44_hexagonXfs.size(); } + const zeus::CColor& GetOutlineColorUnselected() const { return x60_outlineColorUnselected; } + const zeus::CColor& GetOutlineColorSelected() const { return x58_outlineColorSelected; } + const zeus::CColor& GetSurfaceColorUnselected() const { return x5c_surfColorUnselected; } + const zeus::CColor& GetSurfaceColorSelected() const { return x54_surfColorSelected; } + }; private: - CAssetId x0_hexagonId; - TLockedToken x4_hexagonToken; - std::vector x10_worldDatas; - zeus::CVector3f x20_universeCenter = zeus::CVector3f::skZero; - float x2c_universeRadius = 1600.f; + CAssetId x0_hexagonId; + TLockedToken x4_hexagonToken; + std::vector x10_worldDatas; + zeus::CVector3f x20_universeCenter = zeus::CVector3f::skZero; + float x2c_universeRadius = 1600.f; + public: - CMapUniverse(CInputStream&, u32); - const CMapWorldData& GetMapWorldData(s32 idx) const { return x10_worldDatas[idx]; } - const CMapWorldData& GetMapWorldDataByWorldId(CAssetId id) const - { - for (const CMapWorldData& data : x10_worldDatas) - if (data.GetWorldAssetId() == id) - return data; - return x10_worldDatas.front(); - } - u32 GetNumMapWorldDatas() const { return x10_worldDatas.size(); } - float GetMapUniverseRadius() const { return x2c_universeRadius; } - const zeus::CVector3f& GetMapUniverseCenterPoint() const { return x20_universeCenter; } - void Draw(const CMapUniverseDrawParms&, const zeus::CVector3f&, float, float) const; - std::vector::const_iterator begin() const { return x10_worldDatas.cbegin(); } - std::vector::const_iterator end() const { return x10_worldDatas.cend(); } + CMapUniverse(CInputStream&, u32); + const CMapWorldData& GetMapWorldData(s32 idx) const { return x10_worldDatas[idx]; } + const CMapWorldData& GetMapWorldDataByWorldId(CAssetId id) const { + for (const CMapWorldData& data : x10_worldDatas) + if (data.GetWorldAssetId() == id) + return data; + return x10_worldDatas.front(); + } + u32 GetNumMapWorldDatas() const { return x10_worldDatas.size(); } + float GetMapUniverseRadius() const { return x2c_universeRadius; } + const zeus::CVector3f& GetMapUniverseCenterPoint() const { return x20_universeCenter; } + void Draw(const CMapUniverseDrawParms&, const zeus::CVector3f&, float, float) const; + std::vector::const_iterator begin() const { return x10_worldDatas.cbegin(); } + std::vector::const_iterator end() const { return x10_worldDatas.cend(); } }; CFactoryFnReturn FMapUniverseFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference*); -} +} // namespace urde diff --git a/Runtime/AutoMapper/CMapWorld.cpp b/Runtime/AutoMapper/CMapWorld.cpp index caff8b7a6..7f6f612ad 100644 --- a/Runtime/AutoMapper/CMapWorld.cpp +++ b/Runtime/AutoMapper/CMapWorld.cpp @@ -5,818 +5,679 @@ #include "World/CWorld.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { CMapWorld::CMapAreaData::CMapAreaData(CAssetId areaRes, EMapAreaList list, CMapAreaData* next) -: x0_area(g_SimplePool->GetObj(SObjectTag{FOURCC('MAPA'), areaRes})), x10_list(list), x14_next(next) -{} +: x0_area(g_SimplePool->GetObj(SObjectTag{FOURCC('MAPA'), areaRes})), x10_list(list), x14_next(next) {} -CMapWorld::CMapWorld(CInputStream& in) -{ - x10_listHeads.resize(3); - in.readUint32Big(); - in.readUint32Big(); - u32 areaCount = in.readUint32Big(); - x0_areas.reserve(areaCount); - x20_traversed.resize(areaCount); - for (u32 i=0 ; i& vec) const -{ - for (const CMapWorld::CMapAreaBFSInfo& bfs : vec) - { - if (&x0_areas[bfs.GetAreaIndex()] == area) - return true; - } - return false; + const std::vector& vec) const { + for (const CMapWorld::CMapAreaBFSInfo& bfs : vec) { + if (&x0_areas[bfs.GetAreaIndex()] == area) + return true; + } + return false; } -void CMapWorld::SetWhichMapAreasLoaded(const IWorld& wld, int start, int count) -{ - ClearTraversedFlags(); +void CMapWorld::SetWhichMapAreasLoaded(const IWorld& wld, int start, int count) { + ClearTraversedFlags(); - std::vector bfsInfos; - bfsInfos.reserve(x0_areas.size()); - DoBFS(wld, start, count, 9999.f, 9999.f, false, bfsInfos); + std::vector bfsInfos; + bfsInfos.reserve(x0_areas.size()); + DoBFS(wld, start, count, 9999.f, 9999.f, false, bfsInfos); - for (int i=0 ; i<2 ; ++i) - { - for (CMapAreaData* data = x10_listHeads[i] ; data ;) - { - CMapAreaData* nextData = data->NextMapAreaData(); - if (!IsMapAreaInBFSInfoVector(data, bfsInfos)) - { - data->Unlock(); - MoveMapAreaToList(data, EMapAreaList::Unloaded); - } - data = nextData; - } + for (int i = 0; i < 2; ++i) { + for (CMapAreaData* data = x10_listHeads[i]; data;) { + CMapAreaData* nextData = data->NextMapAreaData(); + if (!IsMapAreaInBFSInfoVector(data, bfsInfos)) { + data->Unlock(); + MoveMapAreaToList(data, EMapAreaList::Unloaded); + } + data = nextData; } + } - for (CMapAreaBFSInfo& bfs : bfsInfos) - { - CMapAreaData& data = x0_areas[bfs.GetAreaIndex()]; - data.Lock(); - if (data.GetContainingList() == EMapAreaList::Unloaded) - MoveMapAreaToList(&data, EMapAreaList::Loading); - } + for (CMapAreaBFSInfo& bfs : bfsInfos) { + CMapAreaData& data = x0_areas[bfs.GetAreaIndex()]; + data.Lock(); + if (data.GetContainingList() == EMapAreaList::Unloaded) + MoveMapAreaToList(&data, EMapAreaList::Loading); + } } -bool CMapWorld::IsMapAreasStreaming() const -{ - bool ret = false; - CMapAreaData* data = x10_listHeads[1]; - while (data != nullptr) - { - if (data->IsLoaded()) - { - CMapAreaData* next = data->NextMapAreaData(); - const_cast(this)->MoveMapAreaToList(data, EMapAreaList::Loaded); - data = next; - } - else - { - data = data->NextMapAreaData(); - ret = true; - } +bool CMapWorld::IsMapAreasStreaming() const { + bool ret = false; + CMapAreaData* data = x10_listHeads[1]; + while (data != nullptr) { + if (data->IsLoaded()) { + CMapAreaData* next = data->NextMapAreaData(); + const_cast(this)->MoveMapAreaToList(data, EMapAreaList::Loaded); + data = next; + } else { + data = data->NextMapAreaData(); + ret = true; } - return ret; + } + return ret; } -void CMapWorld::MoveMapAreaToList(CMapWorld::CMapAreaData* data, CMapWorld::EMapAreaList list) -{ - CMapAreaData* last = nullptr; - for (CMapAreaData* head = x10_listHeads[int(data->GetContainingList())] ;; - last = head, head = head->NextMapAreaData()) - { - if (head != data) - continue; - if (!last) - x10_listHeads[int(data->GetContainingList())] = head->NextMapAreaData(); - else - last->SetNextMapArea(head->NextMapAreaData()); - break; - } - data->SetNextMapArea(x10_listHeads[int(list)]); - data->SetContainingList(list); - x10_listHeads[int(list)] = data; -} - -s32 CMapWorld::GetCurrentMapAreaDepth(const IWorld& wld, TAreaId aid) const -{ - ClearTraversedFlags(); - std::vector info; - info.reserve(x0_areas.size()); - DoBFS(wld, aid, 9999, 9999.f, 9999.f, false, info); - if (info.empty()) - return 0; - return info.back().GetDepth(); -} - -std::vector CMapWorld::GetVisibleAreas(const IWorld& wld, const CMapWorldInfo& mwInfo) const -{ - std::vector ret; - ret.reserve(x0_areas.size()); - for (int i=0 ; iGetIsVisibleToAutoMapper(worldVis, areaVis)) - ret.push_back(i); - } - return ret; -} - -void CMapWorld::Draw(const CMapWorld::CMapWorldDrawParms& parms, int curArea, int otherArea, - float depth1, float depth2, bool inMapScreen) const -{ - if (depth1 == 0.f && depth2 == 0.f) - return; - - ClearTraversedFlags(); - int areaDepth = std::ceil(std::max(depth1, depth2)); - - std::vector bfsInfos; - bfsInfos.reserve(x0_areas.size()); - if (curArea != otherArea) - { - const_cast(this)->x20_traversed[otherArea] = true; - DoBFS(parms.GetWorld(), curArea, areaDepth, depth1, depth2, true, bfsInfos); - - float lowD1 = std::ceil(depth1 - 1.f); - float tmp; - if (depth1 == std::floor(depth1)) - tmp = 0.f; - else - tmp = 1.f - std::fmod(depth1, 1.f); - float newD1 = lowD1 + tmp; - - float lowD2 = std::ceil(depth2 - 1.f); - if (depth2 == std::floor(depth2)) - tmp = 0.f; - else - tmp = 1.f - std::fmod(depth2, 1.f); - float newD2 = lowD2 + tmp; - - int otherDepth = std::ceil(std::max(newD1, newD2)); - if (parms.GetWorld().IGetAreaAlways(otherArea)->IIsActive()) - { - const_cast(this)->x20_traversed[otherArea] = false; - DoBFS(parms.GetWorld(), otherArea, otherDepth, newD1, newD2, true, bfsInfos); - } - } +void CMapWorld::MoveMapAreaToList(CMapWorld::CMapAreaData* data, CMapWorld::EMapAreaList list) { + CMapAreaData* last = nullptr; + for (CMapAreaData* head = x10_listHeads[int(data->GetContainingList())];; + last = head, head = head->NextMapAreaData()) { + if (head != data) + continue; + if (!last) + x10_listHeads[int(data->GetContainingList())] = head->NextMapAreaData(); else - { - DoBFS(parms.GetWorld(), curArea, areaDepth, depth1, depth2, true, bfsInfos); - } - - DrawAreas(parms, curArea, bfsInfos, inMapScreen); + last->SetNextMapArea(head->NextMapAreaData()); + break; + } + data->SetNextMapArea(x10_listHeads[int(list)]); + data->SetContainingList(list); + x10_listHeads[int(list)] = data; } -void CMapWorld::DoBFS(const IWorld& wld, int startArea, int areaCount, - float surfDepth, float outlineDepth, - bool checkLoad, std::vector& bfsInfos) const -{ - if (areaCount <= 0 || !IsMapAreaValid(wld, startArea, checkLoad)) - return; - - int size = bfsInfos.size(); - bfsInfos.emplace_back(startArea, 1, surfDepth, outlineDepth); - const_cast(this)->x20_traversed[startArea] = true; - - for (; size != bfsInfos.size() ; ++size) - { - CMapAreaBFSInfo& testInfo = bfsInfos[size]; - if (testInfo.GetDepth() == areaCount) - continue; - - surfDepth = testInfo.GetSurfaceDrawDepth() - 1.f; - outlineDepth = testInfo.GetOutlineDrawDepth() - 1.f; - - const IGameArea* area = wld.IGetAreaAlways(testInfo.GetAreaIndex()); - for (int i=0 ; iIGetNumAttachedAreas() ; ++i) - { - TAreaId attId = area->IGetAttachedAreaId(i); - if (IsMapAreaValid(wld, attId, checkLoad) && !x20_traversed[attId]) - { - bfsInfos.emplace_back(attId, testInfo.GetDepth() + 1, surfDepth, outlineDepth); - const_cast(this)->x20_traversed[attId] = true; - } - } - } +s32 CMapWorld::GetCurrentMapAreaDepth(const IWorld& wld, TAreaId aid) const { + ClearTraversedFlags(); + std::vector info; + info.reserve(x0_areas.size()); + DoBFS(wld, aid, 9999, 9999.f, 9999.f, false, info); + if (info.empty()) + return 0; + return info.back().GetDepth(); } -bool CMapWorld::IsMapAreaValid(const IWorld& wld, int areaIdx, bool checkLoad) const -{ - if (!wld.IGetAreaAlways(areaIdx)->IIsActive()) - return false; - const CMapArea* mapa = GetMapArea(areaIdx); - if (checkLoad) - return mapa != nullptr; - return true; +std::vector CMapWorld::GetVisibleAreas(const IWorld& wld, const CMapWorldInfo& mwInfo) const { + std::vector ret; + ret.reserve(x0_areas.size()); + for (int i = 0; i < x0_areas.size(); ++i) { + if (!IsMapAreaValid(wld, i, true)) + continue; + const CMapArea* area = GetMapArea(i); + bool areaVis = mwInfo.IsAreaVisible(i); + bool worldVis = mwInfo.IsWorldVisible(i); + if (area->GetIsVisibleToAutoMapper(worldVis, areaVis)) + ret.push_back(i); + } + return ret; +} + +void CMapWorld::Draw(const CMapWorld::CMapWorldDrawParms& parms, int curArea, int otherArea, float depth1, float depth2, + bool inMapScreen) const { + if (depth1 == 0.f && depth2 == 0.f) + return; + + ClearTraversedFlags(); + int areaDepth = std::ceil(std::max(depth1, depth2)); + + std::vector bfsInfos; + bfsInfos.reserve(x0_areas.size()); + if (curArea != otherArea) { + const_cast(this)->x20_traversed[otherArea] = true; + DoBFS(parms.GetWorld(), curArea, areaDepth, depth1, depth2, true, bfsInfos); + + float lowD1 = std::ceil(depth1 - 1.f); + float tmp; + if (depth1 == std::floor(depth1)) + tmp = 0.f; + else + tmp = 1.f - std::fmod(depth1, 1.f); + float newD1 = lowD1 + tmp; + + float lowD2 = std::ceil(depth2 - 1.f); + if (depth2 == std::floor(depth2)) + tmp = 0.f; + else + tmp = 1.f - std::fmod(depth2, 1.f); + float newD2 = lowD2 + tmp; + + int otherDepth = std::ceil(std::max(newD1, newD2)); + if (parms.GetWorld().IGetAreaAlways(otherArea)->IIsActive()) { + const_cast(this)->x20_traversed[otherArea] = false; + DoBFS(parms.GetWorld(), otherArea, otherDepth, newD1, newD2, true, bfsInfos); + } + } else { + DoBFS(parms.GetWorld(), curArea, areaDepth, depth1, depth2, true, bfsInfos); + } + + DrawAreas(parms, curArea, bfsInfos, inMapScreen); +} + +void CMapWorld::DoBFS(const IWorld& wld, int startArea, int areaCount, float surfDepth, float outlineDepth, + bool checkLoad, std::vector& bfsInfos) const { + if (areaCount <= 0 || !IsMapAreaValid(wld, startArea, checkLoad)) + return; + + int size = bfsInfos.size(); + bfsInfos.emplace_back(startArea, 1, surfDepth, outlineDepth); + const_cast(this)->x20_traversed[startArea] = true; + + for (; size != bfsInfos.size(); ++size) { + CMapAreaBFSInfo& testInfo = bfsInfos[size]; + if (testInfo.GetDepth() == areaCount) + continue; + + surfDepth = testInfo.GetSurfaceDrawDepth() - 1.f; + outlineDepth = testInfo.GetOutlineDrawDepth() - 1.f; + + const IGameArea* area = wld.IGetAreaAlways(testInfo.GetAreaIndex()); + for (int i = 0; i < area->IGetNumAttachedAreas(); ++i) { + TAreaId attId = area->IGetAttachedAreaId(i); + if (IsMapAreaValid(wld, attId, checkLoad) && !x20_traversed[attId]) { + bfsInfos.emplace_back(attId, testInfo.GetDepth() + 1, surfDepth, outlineDepth); + const_cast(this)->x20_traversed[attId] = true; + } + } + } +} + +bool CMapWorld::IsMapAreaValid(const IWorld& wld, int areaIdx, bool checkLoad) const { + if (!wld.IGetAreaAlways(areaIdx)->IIsActive()) + return false; + const CMapArea* mapa = GetMapArea(areaIdx); + if (checkLoad) + return mapa != nullptr; + return true; } void CMapWorld::DrawAreas(const CMapWorld::CMapWorldDrawParms& parms, int selArea, - const std::vector& bfsInfos, bool inMapScreen) const -{ - // Alpha blend - // Line width 1 + const std::vector& bfsInfos, bool inMapScreen) const { + // Alpha blend + // Line width 1 - int surfCount = 0; - int objCount = 0; - for (const CMapAreaBFSInfo& bfsInfo : bfsInfos) - { - const CMapArea* mapa = GetMapArea(bfsInfo.GetAreaIndex()); - surfCount += mapa->GetNumSurfaces(); - objCount += mapa->GetNumMappableObjects(); - } + int surfCount = 0; + int objCount = 0; + for (const CMapAreaBFSInfo& bfsInfo : bfsInfos) { + const CMapArea* mapa = GetMapArea(bfsInfo.GetAreaIndex()); + surfCount += mapa->GetNumSurfaces(); + objCount += mapa->GetNumMappableObjects(); + } - std::vector sortInfos; - sortInfos.reserve(surfCount + objCount + (parms.GetIsSortDoorSurfaces() ? objCount * 6 : 0)); + std::vector sortInfos; + sortInfos.reserve(surfCount + objCount + (parms.GetIsSortDoorSurfaces() ? objCount * 6 : 0)); - int playerArea = parms.GetStateManager().GetNextAreaId(); - const CMapWorldInfo& mwInfo = parms.GetMapWorldInfo(); - for (const CMapAreaBFSInfo& bfsInfo : bfsInfos) - { - int thisArea = bfsInfo.GetAreaIndex(); - const CMapArea* mapa = GetMapArea(thisArea); - if (!mapa->GetIsVisibleToAutoMapper(mwInfo.IsWorldVisible(thisArea), - mwInfo.IsAreaVisible(thisArea))) - continue; + int playerArea = parms.GetStateManager().GetNextAreaId(); + const CMapWorldInfo& mwInfo = parms.GetMapWorldInfo(); + for (const CMapAreaBFSInfo& bfsInfo : bfsInfos) { + int thisArea = bfsInfo.GetAreaIndex(); + const CMapArea* mapa = GetMapArea(thisArea); + if (!mapa->GetIsVisibleToAutoMapper(mwInfo.IsWorldVisible(thisArea), mwInfo.IsAreaVisible(thisArea))) + continue; - float surfDepth = bfsInfo.GetSurfaceDrawDepth(); - float outlineDepth = bfsInfo.GetOutlineDrawDepth(); + float surfDepth = bfsInfo.GetSurfaceDrawDepth(); + float outlineDepth = bfsInfo.GetOutlineDrawDepth(); - if (surfDepth >= 1.f) - surfDepth = 1.f; - else if (surfDepth < 0.f) - surfDepth = 0.f; - else - surfDepth -= std::floor(surfDepth); - - if (outlineDepth >= 1.f) - outlineDepth = 1.f; - else if (outlineDepth < 0.f) - outlineDepth = 0.f; - else - outlineDepth -= std::floor(outlineDepth); - - float alphaSurf; - float alphaOutline; - const zeus::CColor* surfaceColor; - const zeus::CColor* outlineColor; - const zeus::CColor* surfacePlayerColor; - const zeus::CColor* outlinePlayerColor; - if (mwInfo.IsAreaVisted(thisArea)) - { - alphaSurf = parms.GetAlphaSurfaceVisited(); - alphaOutline = parms.GetAlphaOutlineVisited(); - surfaceColor = &g_tweakAutoMapper->GetSurfaceVisitedColor(); - outlineColor = &g_tweakAutoMapper->GetOutlineVisitedColor(); - surfacePlayerColor = &g_tweakAutoMapper->GetSurfaceSelectVisitedColor(); - outlinePlayerColor = &g_tweakAutoMapper->GetOutlineSelectVisitedColor(); - } - else - { - alphaSurf = parms.GetAlphaSurfaceUnvisited(); - alphaOutline = parms.GetAlphaOutlineUnvisited(); - surfaceColor = &g_tweakAutoMapper->GetSurfaceUnvisitedColor(); - outlineColor = &g_tweakAutoMapper->GetOutlineUnvisitedColor(); - surfacePlayerColor = &g_tweakAutoMapper->GetSurfaceSelectUnvisitedColor(); - outlinePlayerColor = &g_tweakAutoMapper->GetOutlineSelectUnvisitedColor(); - } - - zeus::CColor hintFlashColor = - zeus::CColor::lerp(zeus::CColor::skClear, zeus::CColor{1.f, 1.f, 1.f, 0.f}, - parms.GetHintAreaFlashIntensity()); - - zeus::CColor finalSurfColor, finalOutlineColor; - if (thisArea == selArea && inMapScreen) - { - finalSurfColor = *surfacePlayerColor + hintFlashColor; - finalOutlineColor = *outlinePlayerColor + hintFlashColor; - } - else - { - finalSurfColor = *surfaceColor; - finalSurfColor.a() = surfDepth * alphaSurf; - finalOutlineColor = *outlineColor; - finalOutlineColor.a() = outlineDepth * alphaOutline; - } - - if ((selArea != playerArea || parms.GetHintAreaFlashIntensity() == 0.f) && - playerArea == thisArea && this == parms.GetStateManager().GetWorld()->GetMapWorld()) - { - float pulse = parms.GetPlayerAreaFlashIntensity(); - const zeus::CColor& flashCol = g_tweakAutoMapper->GetAreaFlashPulseColor(); - finalSurfColor = zeus::CColor::lerp(finalSurfColor, flashCol, pulse); - finalOutlineColor = zeus::CColor::lerp(finalOutlineColor, flashCol, pulse); - } - - zeus::CTransform modelView = parms.GetCameraTransform().inverse() * - mapa->GetAreaPostTransform(parms.GetWorld(), thisArea); - for (int i=0 ; iGetNumSurfaces() ; ++i) - { - const CMapArea::CMapAreaSurface& surf = mapa->GetSurface(i); - zeus::CVector3f pos = modelView * surf.GetCenterPosition(); - sortInfos.emplace_back(pos.y(), thisArea, CMapObjectSortInfo::EObjectCode::Surface, i, - finalSurfColor, finalOutlineColor); - } - - int i = 0; - int si = 0; - for (; iGetNumMappableObjects() ; ++i, si+=6) - { - const CMappableObject& obj = mapa->GetMappableObject(i); - if (!obj.IsVisibleToAutoMapper(mwInfo.IsWorldVisible(thisArea), mwInfo)) - continue; - - bool doorType = CMappableObject::IsDoorType(obj.GetType()); - if (doorType) - { - if (!mwInfo.IsAreaVisible(thisArea)) - continue; - if (parms.GetIsSortDoorSurfaces()) - { - for (int s=0 ; s<6 ; ++s) - { - zeus::CVector3f center = obj.BuildSurfaceCenterPoint(s); - zeus::CVector3f pos = modelView * - (CMapArea::GetAreaPostTranslate(parms.GetWorld(), thisArea) + center); - sortInfos.emplace_back(pos.y(), thisArea, CMapObjectSortInfo::EObjectCode::DoorSurface, si+s, - zeus::CColor{1.f, 0.f, 1.f, 1.f}, zeus::CColor{1.f, 0.f, 1.f, 1.f}); - } - continue; - } - } - - zeus::CVector3f pos = modelView * (obj.GetTransform().origin + - CMapArea::GetAreaPostTranslate(parms.GetWorld(), thisArea)); - sortInfos.emplace_back(pos.y(), thisArea, doorType ? CMapObjectSortInfo::EObjectCode::Door : - CMapObjectSortInfo::EObjectCode::Object, - i, zeus::CColor{1.f, 0.f, 1.f, 1.f}, zeus::CColor{1.f, 0.f, 1.f, 1.f}); - } - } - - std::sort(sortInfos.begin(), sortInfos.end(), - [](const CMapObjectSortInfo& a, const CMapObjectSortInfo& b) - { - return a.GetZDistance() > b.GetZDistance(); - }); - - int lastAreaIdx = -1; - CMapObjectSortInfo::EObjectCode lastType = CMapObjectSortInfo::EObjectCode::Invalid; - for (const CMapObjectSortInfo& info : sortInfos) - { - const CMapArea* mapa = GetMapArea(info.GetAreaIndex()); - zeus::CTransform areaPostXf = mapa->GetAreaPostTransform(parms.GetWorld(), info.GetAreaIndex()); - if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Surface) - { - const CMapArea::CMapAreaSurface& surf = mapa->GetSurface(info.GetLocalObjectIndex()); - zeus::CColor color(std::max(0.f, (-parms.GetCameraTransform().basis[1]).dot( - areaPostXf.rotate(surf.GetNormal()))) * g_tweakAutoMapper->GetMapSurfaceNormColorLinear() + - g_tweakAutoMapper->GetMapSurfaceNormColorConstant()); - color *= info.GetSurfaceColor(); - if (lastAreaIdx != info.GetAreaIndex() || lastType != CMapObjectSortInfo::EObjectCode::Surface) - CGraphics::SetModelMatrix(parms.GetPlaneProjectionTransform() * areaPostXf); - surf.Draw(mapa->GetVertices(), color, info.GetOutlineColor(), parms.GetOutlineWidthScale()); - - lastAreaIdx = info.GetAreaIndex(); - lastType = info.GetObjectCode(); - } - } - for (const CMapObjectSortInfo& info : sortInfos) - { - const CMapArea* mapa = GetMapArea(info.GetAreaIndex()); - if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Door || - info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Object) - { - const CMappableObject& mapObj = mapa->GetMappableObject(info.GetLocalObjectIndex()); - zeus::CTransform objXf = - zeus::CTransform::Translate(CMapArea::GetAreaPostTranslate(parms.GetWorld(), info.GetAreaIndex())) * - mapObj.GetTransform(); - if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Door) - { - CGraphics::SetModelMatrix(parms.GetPlaneProjectionTransform() * objXf); - } - else - { - CGraphics::SetModelMatrix(parms.GetPlaneProjectionTransform() * objXf * - zeus::CTransform(parms.GetCameraTransform().buildMatrix3f() * - zeus::CMatrix3f(parms.GetObjectScale()))); - } - mapObj.Draw(selArea, mwInfo, parms.GetAlpha(), lastType != info.GetObjectCode()); - lastType = info.GetObjectCode(); - } - else if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::DoorSurface) - { - const CMappableObject& mapObj = mapa->GetMappableObject(info.GetLocalObjectIndex() / 6); - zeus::CTransform objXf = parms.GetPlaneProjectionTransform() * - zeus::CTransform::Translate(CMapArea::GetAreaPostTranslate( - parms.GetWorld(), info.GetAreaIndex())) * mapObj.GetTransform(); - CGraphics::SetModelMatrix(objXf); - mapObj.DrawDoorSurface(selArea, mwInfo, parms.GetAlpha(), info.GetLocalObjectIndex() % 6, - lastType != info.GetObjectCode()); - lastType = info.GetObjectCode(); - } - } -} - -struct Support -{ - int x0_; - int x4_[3]; -}; - -struct Circle2 -{ - zeus::CVector2f x0_point; - float x8_radiusSq; -}; - -struct Circle -{ - zeus::CVector2f x0_point; - float x8_radius; - Circle(const Circle2& circ2) - : x0_point(circ2.x0_point), x8_radius(std::sqrt(circ2.x8_radiusSq)) {} -}; - -static Circle2 ExactCircle1(const zeus::CVector2f* a) -{ - return {*a, 0.f}; -} - -static Circle2 ExactCircle2(const zeus::CVector2f* a, const zeus::CVector2f* b) -{ - Circle2 ret = {}; - ret.x0_point = 0.5f * (*a + *b); - ret.x8_radiusSq = (*b - *a).magSquared() * 0.25f; - return ret; -} - -static Circle2 ExactCircle3(const zeus::CVector2f* a, const zeus::CVector2f* b, const zeus::CVector2f* c) -{ - Circle2 ret = {}; - zeus::CVector2f d1 = *b - *a; - zeus::CVector2f d2 = *c - *a; - float cross = d1.cross(d2); - zeus::CVector2f magVec(d1.magSquared() * 0.5f, d2.magSquared() * 0.5f); - if (std::fabs(cross) > 0.01f) - { - zeus::CVector2f tmp((d2.y() * magVec.x() - d1.y() * magVec.y()) / cross, - (d1.x() * magVec.y() - d2.x() * magVec.x()) / cross); - ret.x0_point = *a + tmp; - ret.x8_radiusSq = tmp.magSquared(); - } + if (surfDepth >= 1.f) + surfDepth = 1.f; + else if (surfDepth < 0.f) + surfDepth = 0.f; else - { - ret.x8_radiusSq = FLT_MAX; + surfDepth -= std::floor(surfDepth); + + if (outlineDepth >= 1.f) + outlineDepth = 1.f; + else if (outlineDepth < 0.f) + outlineDepth = 0.f; + else + outlineDepth -= std::floor(outlineDepth); + + float alphaSurf; + float alphaOutline; + const zeus::CColor* surfaceColor; + const zeus::CColor* outlineColor; + const zeus::CColor* surfacePlayerColor; + const zeus::CColor* outlinePlayerColor; + if (mwInfo.IsAreaVisted(thisArea)) { + alphaSurf = parms.GetAlphaSurfaceVisited(); + alphaOutline = parms.GetAlphaOutlineVisited(); + surfaceColor = &g_tweakAutoMapper->GetSurfaceVisitedColor(); + outlineColor = &g_tweakAutoMapper->GetOutlineVisitedColor(); + surfacePlayerColor = &g_tweakAutoMapper->GetSurfaceSelectVisitedColor(); + outlinePlayerColor = &g_tweakAutoMapper->GetOutlineSelectVisitedColor(); + } else { + alphaSurf = parms.GetAlphaSurfaceUnvisited(); + alphaOutline = parms.GetAlphaOutlineUnvisited(); + surfaceColor = &g_tweakAutoMapper->GetSurfaceUnvisitedColor(); + outlineColor = &g_tweakAutoMapper->GetOutlineUnvisitedColor(); + surfacePlayerColor = &g_tweakAutoMapper->GetSurfaceSelectUnvisitedColor(); + outlinePlayerColor = &g_tweakAutoMapper->GetOutlineSelectUnvisitedColor(); } - return ret; + + zeus::CColor hintFlashColor = + zeus::CColor::lerp(zeus::CColor::skClear, zeus::CColor{1.f, 1.f, 1.f, 0.f}, parms.GetHintAreaFlashIntensity()); + + zeus::CColor finalSurfColor, finalOutlineColor; + if (thisArea == selArea && inMapScreen) { + finalSurfColor = *surfacePlayerColor + hintFlashColor; + finalOutlineColor = *outlinePlayerColor + hintFlashColor; + } else { + finalSurfColor = *surfaceColor; + finalSurfColor.a() = surfDepth * alphaSurf; + finalOutlineColor = *outlineColor; + finalOutlineColor.a() = outlineDepth * alphaOutline; + } + + if ((selArea != playerArea || parms.GetHintAreaFlashIntensity() == 0.f) && playerArea == thisArea && + this == parms.GetStateManager().GetWorld()->GetMapWorld()) { + float pulse = parms.GetPlayerAreaFlashIntensity(); + const zeus::CColor& flashCol = g_tweakAutoMapper->GetAreaFlashPulseColor(); + finalSurfColor = zeus::CColor::lerp(finalSurfColor, flashCol, pulse); + finalOutlineColor = zeus::CColor::lerp(finalOutlineColor, flashCol, pulse); + } + + zeus::CTransform modelView = + parms.GetCameraTransform().inverse() * mapa->GetAreaPostTransform(parms.GetWorld(), thisArea); + for (int i = 0; i < mapa->GetNumSurfaces(); ++i) { + const CMapArea::CMapAreaSurface& surf = mapa->GetSurface(i); + zeus::CVector3f pos = modelView * surf.GetCenterPosition(); + sortInfos.emplace_back(pos.y(), thisArea, CMapObjectSortInfo::EObjectCode::Surface, i, finalSurfColor, + finalOutlineColor); + } + + int i = 0; + int si = 0; + for (; i < mapa->GetNumMappableObjects(); ++i, si += 6) { + const CMappableObject& obj = mapa->GetMappableObject(i); + if (!obj.IsVisibleToAutoMapper(mwInfo.IsWorldVisible(thisArea), mwInfo)) + continue; + + bool doorType = CMappableObject::IsDoorType(obj.GetType()); + if (doorType) { + if (!mwInfo.IsAreaVisible(thisArea)) + continue; + if (parms.GetIsSortDoorSurfaces()) { + for (int s = 0; s < 6; ++s) { + zeus::CVector3f center = obj.BuildSurfaceCenterPoint(s); + zeus::CVector3f pos = modelView * (CMapArea::GetAreaPostTranslate(parms.GetWorld(), thisArea) + center); + sortInfos.emplace_back(pos.y(), thisArea, CMapObjectSortInfo::EObjectCode::DoorSurface, si + s, + zeus::CColor{1.f, 0.f, 1.f, 1.f}, zeus::CColor{1.f, 0.f, 1.f, 1.f}); + } + continue; + } + } + + zeus::CVector3f pos = + modelView * (obj.GetTransform().origin + CMapArea::GetAreaPostTranslate(parms.GetWorld(), thisArea)); + sortInfos.emplace_back(pos.y(), thisArea, + doorType ? CMapObjectSortInfo::EObjectCode::Door : CMapObjectSortInfo::EObjectCode::Object, + i, zeus::CColor{1.f, 0.f, 1.f, 1.f}, zeus::CColor{1.f, 0.f, 1.f, 1.f}); + } + } + + std::sort(sortInfos.begin(), sortInfos.end(), [](const CMapObjectSortInfo& a, const CMapObjectSortInfo& b) { + return a.GetZDistance() > b.GetZDistance(); + }); + + int lastAreaIdx = -1; + CMapObjectSortInfo::EObjectCode lastType = CMapObjectSortInfo::EObjectCode::Invalid; + for (const CMapObjectSortInfo& info : sortInfos) { + const CMapArea* mapa = GetMapArea(info.GetAreaIndex()); + zeus::CTransform areaPostXf = mapa->GetAreaPostTransform(parms.GetWorld(), info.GetAreaIndex()); + if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Surface) { + const CMapArea::CMapAreaSurface& surf = mapa->GetSurface(info.GetLocalObjectIndex()); + zeus::CColor color( + std::max(0.f, (-parms.GetCameraTransform().basis[1]).dot(areaPostXf.rotate(surf.GetNormal()))) * + g_tweakAutoMapper->GetMapSurfaceNormColorLinear() + + g_tweakAutoMapper->GetMapSurfaceNormColorConstant()); + color *= info.GetSurfaceColor(); + if (lastAreaIdx != info.GetAreaIndex() || lastType != CMapObjectSortInfo::EObjectCode::Surface) + CGraphics::SetModelMatrix(parms.GetPlaneProjectionTransform() * areaPostXf); + surf.Draw(mapa->GetVertices(), color, info.GetOutlineColor(), parms.GetOutlineWidthScale()); + + lastAreaIdx = info.GetAreaIndex(); + lastType = info.GetObjectCode(); + } + } + for (const CMapObjectSortInfo& info : sortInfos) { + const CMapArea* mapa = GetMapArea(info.GetAreaIndex()); + if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Door || + info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Object) { + const CMappableObject& mapObj = mapa->GetMappableObject(info.GetLocalObjectIndex()); + zeus::CTransform objXf = + zeus::CTransform::Translate(CMapArea::GetAreaPostTranslate(parms.GetWorld(), info.GetAreaIndex())) * + mapObj.GetTransform(); + if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::Door) { + CGraphics::SetModelMatrix(parms.GetPlaneProjectionTransform() * objXf); + } else { + CGraphics::SetModelMatrix( + parms.GetPlaneProjectionTransform() * objXf * + zeus::CTransform(parms.GetCameraTransform().buildMatrix3f() * zeus::CMatrix3f(parms.GetObjectScale()))); + } + mapObj.Draw(selArea, mwInfo, parms.GetAlpha(), lastType != info.GetObjectCode()); + lastType = info.GetObjectCode(); + } else if (info.GetObjectCode() == CMapObjectSortInfo::EObjectCode::DoorSurface) { + const CMappableObject& mapObj = mapa->GetMappableObject(info.GetLocalObjectIndex() / 6); + zeus::CTransform objXf = + parms.GetPlaneProjectionTransform() * + zeus::CTransform::Translate(CMapArea::GetAreaPostTranslate(parms.GetWorld(), info.GetAreaIndex())) * + mapObj.GetTransform(); + CGraphics::SetModelMatrix(objXf); + mapObj.DrawDoorSurface(selArea, mwInfo, parms.GetAlpha(), info.GetLocalObjectIndex() % 6, + lastType != info.GetObjectCode()); + lastType = info.GetObjectCode(); + } + } } -static bool PointInsideCircle(const zeus::CVector2f& point, const Circle2& circ, float& intersect) -{ - intersect = (point - circ.x0_point).magSquared() - circ.x8_radiusSq; - return intersect <= 0.f; +struct Support { + int x0_; + int x4_[3]; +}; + +struct Circle2 { + zeus::CVector2f x0_point; + float x8_radiusSq; +}; + +struct Circle { + zeus::CVector2f x0_point; + float x8_radius; + Circle(const Circle2& circ2) : x0_point(circ2.x0_point), x8_radius(std::sqrt(circ2.x8_radiusSq)) {} +}; + +static Circle2 ExactCircle1(const zeus::CVector2f* a) { return {*a, 0.f}; } + +static Circle2 ExactCircle2(const zeus::CVector2f* a, const zeus::CVector2f* b) { + Circle2 ret = {}; + ret.x0_point = 0.5f * (*a + *b); + ret.x8_radiusSq = (*b - *a).magSquared() * 0.25f; + return ret; } -static Circle2 UpdateSupport1(int idx, zeus::CVector2f** list, Support& support) -{ - Circle2 ret = ExactCircle2(list[support.x4_[0]], list[idx]); +static Circle2 ExactCircle3(const zeus::CVector2f* a, const zeus::CVector2f* b, const zeus::CVector2f* c) { + Circle2 ret = {}; + zeus::CVector2f d1 = *b - *a; + zeus::CVector2f d2 = *c - *a; + float cross = d1.cross(d2); + zeus::CVector2f magVec(d1.magSquared() * 0.5f, d2.magSquared() * 0.5f); + if (std::fabs(cross) > 0.01f) { + zeus::CVector2f tmp((d2.y() * magVec.x() - d1.y() * magVec.y()) / cross, + (d1.x() * magVec.y() - d2.x() * magVec.x()) / cross); + ret.x0_point = *a + tmp; + ret.x8_radiusSq = tmp.magSquared(); + } else { + ret.x8_radiusSq = FLT_MAX; + } + return ret; +} + +static bool PointInsideCircle(const zeus::CVector2f& point, const Circle2& circ, float& intersect) { + intersect = (point - circ.x0_point).magSquared() - circ.x8_radiusSq; + return intersect <= 0.f; +} + +static Circle2 UpdateSupport1(int idx, zeus::CVector2f** list, Support& support) { + Circle2 ret = ExactCircle2(list[support.x4_[0]], list[idx]); + support.x0_ = 2; + support.x4_[1] = idx; + return ret; +} + +static Circle2 UpdateSupport2(int idx, zeus::CVector2f** list, Support& support) { + Circle2 circs[3] = {}; + float intersect; + int circIdx = -1; + float minRad = FLT_MAX; + + circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]); + if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) { + minRad = circs[0].x8_radiusSq; + circIdx = 0; + } + + circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]); + if (circs[1].x8_radiusSq < minRad && PointInsideCircle(*list[support.x4_[1]], circs[1], intersect)) { + minRad = circs[1].x8_radiusSq; + circIdx = 1; + } + + Circle2 ret = {}; + if (circIdx != -1) { + ret = circs[circIdx]; + support.x4_[1 - circIdx] = idx; + } else { + ret = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]); + support.x0_ = 3; + support.x4_[2] = idx; + } + return ret; +} + +static Circle2 UpdateSupport3(int idx, zeus::CVector2f** list, Support& support) { + Circle2 circs[6] = {}; + float intersect; + int circIdxA = -1; + int circIdxB = -1; + float minRadA = FLT_MAX; + float minRadB = FLT_MAX; + + circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]); + if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) { + if (PointInsideCircle(*list[support.x4_[2]], circs[0], intersect)) { + minRadA = circs[0].x8_radiusSq; + circIdxA = 0; + } else { + minRadB = intersect; + circIdxB = 0; + } + } else { + minRadB = intersect; + circIdxB = 0; + } + + circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]); + if (circs[1].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) { + if (PointInsideCircle(*list[support.x4_[2]], circs[1], intersect)) { + minRadA = circs[1].x8_radiusSq; + circIdxA = 1; + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 1; + } + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 1; + } + } + + circs[2] = ExactCircle2(list[support.x4_[2]], list[idx]); + if (circs[2].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[0]], circs[2], intersect)) { + if (PointInsideCircle(*list[support.x4_[1]], circs[2], intersect)) { + minRadA = circs[2].x8_radiusSq; + circIdxA = 2; + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 2; + } + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 2; + } + } + + circs[3] = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]); + if (circs[3].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[2]], circs[3], intersect)) { + minRadA = circs[3].x8_radiusSq; + circIdxA = 3; + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 3; + } + } + + circs[4] = ExactCircle3(list[support.x4_[0]], list[support.x4_[2]], list[idx]); + if (circs[4].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[1]], circs[4], intersect)) { + minRadA = circs[4].x8_radiusSq; + circIdxA = 4; + } else if (intersect < minRadB) { + minRadB = intersect; + circIdxB = 4; + } + } + + circs[5] = ExactCircle3(list[support.x4_[1]], list[support.x4_[2]], list[idx]); + if (circs[5].x8_radiusSq < minRadA) { + if (PointInsideCircle(*list[support.x4_[0]], circs[5], intersect)) { + circIdxA = 5; + } else if (intersect < minRadB) { + circIdxB = 5; + } + } + + if (circIdxA == -1) + circIdxA = circIdxB; + + switch (circIdxA) { + case 0: support.x0_ = 2; support.x4_[1] = idx; - return ret; + break; + case 1: + support.x0_ = 2; + support.x4_[0] = idx; + break; + case 2: + support.x0_ = 2; + support.x4_[0] = support.x4_[2]; + support.x4_[1] = idx; + break; + case 3: + support.x4_[2] = idx; + break; + case 4: + support.x4_[1] = idx; + break; + case 5: + support.x4_[0] = idx; + break; + default: + break; + } + + return circs[circIdxA]; } -static Circle2 UpdateSupport2(int idx, zeus::CVector2f** list, Support& support) -{ - Circle2 circs[3] = {}; - float intersect; - int circIdx = -1; - float minRad = FLT_MAX; +typedef Circle2 (*FSupport)(int idx, zeus::CVector2f** list, Support& support); +static const FSupport SupportFuncs[] = {nullptr, UpdateSupport1, UpdateSupport2, UpdateSupport3}; - circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]); - if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) - { - minRad = circs[0].x8_radiusSq; - circIdx = 0; +static Circle MinCircle(const std::vector& coords) { + Circle2 ret = {}; + if (coords.size() >= 1) { + std::unique_ptr randArr(new zeus::CVector2f*[coords.size()]); + for (int i = 0; i < coords.size(); ++i) + randArr[i] = const_cast(&coords[i]); + for (int i = coords.size() - 1; i >= 0; --i) { + int shuf = rand() % (i + 1); + if (shuf != i) + std::swap(randArr[i], randArr[shuf]); } + ret = ExactCircle1(randArr[0]); - circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]); - if (circs[1].x8_radiusSq < minRad && PointInsideCircle(*list[support.x4_[1]], circs[1], intersect)) - { - minRad = circs[1].x8_radiusSq; - circIdx = 1; + Support support = {}; + support.x0_ = 1; + for (int i = 1; i < coords.size();) { + bool broke = false; + for (int j = 0; j < support.x0_; ++j) { + if ((*randArr[i] - *randArr[support.x4_[j]]).magSquared() < 0.01f) { + broke = true; + break; + } + } + float intersect; + if (!broke && !PointInsideCircle(*randArr[i], ret, intersect)) { + Circle2 circ = SupportFuncs[support.x0_](i, randArr.get(), support); + if (circ.x8_radiusSq > ret.x8_radiusSq) { + i = 0; + ret = circ; + continue; + } + } + ++i; } - - Circle2 ret = {}; - if (circIdx != -1) - { - ret = circs[circIdx]; - support.x4_[1 - circIdx] = idx; - } - else - { - ret = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]); - support.x0_ = 3; - support.x4_[2] = idx; - } - return ret; + } + return ret; } -static Circle2 UpdateSupport3(int idx, zeus::CVector2f** list, Support& support) -{ - Circle2 circs[6] = {}; - float intersect; - int circIdxA = -1; - int circIdxB = -1; - float minRadA = FLT_MAX; - float minRadB = FLT_MAX; - - circs[0] = ExactCircle2(list[support.x4_[0]], list[idx]); - if (PointInsideCircle(*list[support.x4_[1]], circs[0], intersect)) - { - if (PointInsideCircle(*list[support.x4_[2]], circs[0], intersect)) - { - minRadA = circs[0].x8_radiusSq; - circIdxA = 0; - } - else - { - minRadB = intersect; - circIdxB = 0; +void CMapWorld::RecalculateWorldSphere(const CMapWorldInfo& mwInfo, const IWorld& wld) const { + std::vector coords; + coords.reserve(x0_areas.size() * 8); + float zMin = FLT_MAX; + float zMax = -FLT_MAX; + for (int i = 0; i < x0_areas.size(); ++i) { + if (IsMapAreaValid(wld, i, true)) { + const CMapArea* mapa = GetMapArea(i); + if (mapa->GetIsVisibleToAutoMapper(mwInfo.IsWorldVisible(i), mwInfo.IsAreaVisible(i))) { + zeus::CAABox aabb = mapa->GetBoundingBox().getTransformedAABox(mapa->GetAreaPostTransform(wld, i)); + for (int j = 0; j < 8; ++j) { + const zeus::CVector3f point = aabb.getPoint(j); + coords.push_back(point.toVec2f()); + zMin = std::min(point.z(), zMin); + zMax = std::max(point.z(), zMax); } + } } - else - { - minRadB = intersect; - circIdxB = 0; - } + } - circs[1] = ExactCircle2(list[support.x4_[1]], list[idx]); - if (circs[1].x8_radiusSq < minRadA) - { - if (PointInsideCircle(*list[support.x4_[0]], circs[1], intersect)) - { - if (PointInsideCircle(*list[support.x4_[2]], circs[1], intersect)) - { - minRadA = circs[1].x8_radiusSq; - circIdxA = 1; - } - else if (intersect < minRadB) - { - minRadB = intersect; - circIdxB = 1; - } - } - else if (intersect < minRadB) - { - minRadB = intersect; - circIdxB = 1; - } - } - - circs[2] = ExactCircle2(list[support.x4_[2]], list[idx]); - if (circs[2].x8_radiusSq < minRadA) - { - if (PointInsideCircle(*list[support.x4_[0]], circs[2], intersect)) - { - if (PointInsideCircle(*list[support.x4_[1]], circs[2], intersect)) - { - minRadA = circs[2].x8_radiusSq; - circIdxA = 2; - } - else if (intersect < minRadB) - { - minRadB = intersect; - circIdxB = 2; - } - } - else if (intersect < minRadB) - { - minRadB = intersect; - circIdxB = 2; - } - } - - circs[3] = ExactCircle3(list[support.x4_[0]], list[support.x4_[1]], list[idx]); - if (circs[3].x8_radiusSq < minRadA) - { - if (PointInsideCircle(*list[support.x4_[2]], circs[3], intersect)) - { - minRadA = circs[3].x8_radiusSq; - circIdxA = 3; - } - else if (intersect < minRadB) - { - minRadB = intersect; - circIdxB = 3; - } - } - - circs[4] = ExactCircle3(list[support.x4_[0]], list[support.x4_[2]], list[idx]); - if (circs[4].x8_radiusSq < minRadA) - { - if (PointInsideCircle(*list[support.x4_[1]], circs[4], intersect)) - { - minRadA = circs[4].x8_radiusSq; - circIdxA = 4; - } - else if (intersect < minRadB) - { - minRadB = intersect; - circIdxB = 4; - } - } - - circs[5] = ExactCircle3(list[support.x4_[1]], list[support.x4_[2]], list[idx]); - if (circs[5].x8_radiusSq < minRadA) - { - if (PointInsideCircle(*list[support.x4_[0]], circs[5], intersect)) - { - circIdxA = 5; - } - else if (intersect < minRadB) - { - circIdxB = 5; - } - } - - if (circIdxA == -1) - circIdxA = circIdxB; - - switch (circIdxA) - { - case 0: - support.x0_ = 2; - support.x4_[1] = idx; - break; - case 1: - support.x0_ = 2; - support.x4_[0] = idx; - break; - case 2: - support.x0_ = 2; - support.x4_[0] = support.x4_[2]; - support.x4_[1] = idx; - break; - case 3: - support.x4_[2] = idx; - break; - case 4: - support.x4_[1] = idx; - break; - case 5: - support.x4_[0] = idx; - break; - default: break; - } - - return circs[circIdxA]; + Circle circle = MinCircle(coords); + const_cast(this)->x3c_worldSphereRadius = circle.x8_radius; + const_cast(this)->x30_worldSpherePoint = + zeus::CVector3f(circle.x0_point.x(), circle.x0_point.y(), (zMin + zMax) * 0.5f); + const_cast(this)->x40_worldSphereHalfDepth = (zMax - zMin) * 0.5f; } -typedef Circle2(*FSupport)(int idx, zeus::CVector2f** list, Support& support); -static const FSupport SupportFuncs[] = -{ - nullptr, - UpdateSupport1, - UpdateSupport2, - UpdateSupport3 -}; +zeus::CVector3f CMapWorld::ConstrainToWorldVolume(const zeus::CVector3f& point, const zeus::CVector3f& lookVec) const { + zeus::CVector3f ret = point; + if (std::fabs(lookVec.z()) > FLT_EPSILON) { + float f2 = point.z() - (x40_worldSphereHalfDepth + x30_worldSpherePoint.z()); + float f1 = point.z() - (x30_worldSpherePoint.z() - x40_worldSphereHalfDepth); + if (f2 > 0.f) + ret = point + lookVec * (-f2 / lookVec.z()); + else if (f1 < 0.f) + ret = point + lookVec * (-f1 / lookVec.z()); + } else { + ret.z() = zeus::clamp(x30_worldSpherePoint.z() - x40_worldSphereHalfDepth, float(ret.z()), + x40_worldSphereHalfDepth + x30_worldSpherePoint.z()); + } -static Circle MinCircle(const std::vector& coords) -{ - Circle2 ret = {}; - if (coords.size() >= 1) - { - std::unique_ptr randArr(new zeus::CVector2f*[coords.size()]); - for (int i=0 ; i(&coords[i]); - for (int i=coords.size()-1 ; i>=0 ; --i) - { - int shuf = rand() % (i+1); - if (shuf != i) - std::swap(randArr[i], randArr[shuf]); - } - ret = ExactCircle1(randArr[0]); + zeus::CVector2f tmp = x30_worldSpherePoint.toVec2f(); + zeus::CVector2f vec2 = point.toVec2f() - tmp; + if (vec2.magnitude() > x3c_worldSphereRadius) { + tmp += vec2.normalized() * x3c_worldSphereRadius; + ret.x() = float(tmp.x()); + ret.y() = float(tmp.y()); + } - Support support = {}; - support.x0_ = 1; - for (int i=1 ; i ret.x8_radiusSq) - { - i = 0; - ret = circ; - continue; - } - } - ++i; - } - } - return ret; + return ret; } -void CMapWorld::RecalculateWorldSphere(const CMapWorldInfo& mwInfo, const IWorld& wld) const -{ - std::vector coords; - coords.reserve(x0_areas.size() * 8); - float zMin = FLT_MAX; - float zMax = -FLT_MAX; - for (int i=0 ; iGetIsVisibleToAutoMapper(mwInfo.IsWorldVisible(i), mwInfo.IsAreaVisible(i))) - { - zeus::CAABox aabb = mapa->GetBoundingBox().getTransformedAABox(mapa->GetAreaPostTransform(wld, i)); - for (int j=0 ; j<8 ; ++j) - { - const zeus::CVector3f point = aabb.getPoint(j); - coords.push_back(point.toVec2f()); - zMin = std::min(point.z(), zMin); - zMax = std::max(point.z(), zMax); - } - } - } - } - - Circle circle = MinCircle(coords); - const_cast(this)->x3c_worldSphereRadius = circle.x8_radius; - const_cast(this)->x30_worldSpherePoint = - zeus::CVector3f(circle.x0_point.x(), circle.x0_point.y(), (zMin + zMax) * 0.5f); - const_cast(this)->x40_worldSphereHalfDepth = (zMax - zMin) * 0.5f; -} - -zeus::CVector3f CMapWorld::ConstrainToWorldVolume(const zeus::CVector3f& point, const zeus::CVector3f& lookVec) const -{ - zeus::CVector3f ret = point; - if (std::fabs(lookVec.z()) > FLT_EPSILON) - { - float f2 = point.z() - (x40_worldSphereHalfDepth + x30_worldSpherePoint.z()); - float f1 = point.z() - (x30_worldSpherePoint.z() - x40_worldSphereHalfDepth); - if (f2 > 0.f) - ret = point + lookVec * (-f2 / lookVec.z()); - else if (f1 < 0.f) - ret = point + lookVec * (-f1 / lookVec.z()); - } - else - { - ret.z() = zeus::clamp(x30_worldSpherePoint.z() - x40_worldSphereHalfDepth, float(ret.z()), - x40_worldSphereHalfDepth + x30_worldSpherePoint.z()); - } - - zeus::CVector2f tmp = x30_worldSpherePoint.toVec2f(); - zeus::CVector2f vec2 = point.toVec2f() - tmp; - if (vec2.magnitude() > x3c_worldSphereRadius) - { - tmp += vec2.normalized() * x3c_worldSphereRadius; - ret.x() = float(tmp.x()); - ret.y() = float(tmp.y()); - } - - return ret; -} - -void CMapWorld::ClearTraversedFlags() const -{ - std::vector& flags = const_cast(this)->x20_traversed; - for (int i=0 ; i& flags = const_cast(this)->x20_traversed; + for (int i = 0; i < flags.size(); ++i) + flags[i] = false; } CFactoryFnReturn FMapWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/AutoMapper/CMapWorld.hpp b/Runtime/AutoMapper/CMapWorld.hpp index b91eaff85..38a49ab47 100644 --- a/Runtime/AutoMapper/CMapWorld.hpp +++ b/Runtime/AutoMapper/CMapWorld.hpp @@ -7,169 +7,155 @@ #include "zeus/CTransform.hpp" #include "CMapArea.hpp" -namespace urde -{ +namespace urde { class IWorld; class CMapWorldInfo; class CStateManager; -class CMapWorld -{ +class CMapWorld { public: - /* skDrawProfileItemNames; */ - enum class EMapAreaList - { - Loaded, - Loading, - Unloaded - }; + /* skDrawProfileItemNames; */ + enum class EMapAreaList { Loaded, Loading, Unloaded }; - class CMapAreaBFSInfo - { - int x0_areaIdx; - int x4_depth; - float x8_surfDrawDepth; - float xc_outlineDrawDepth; - public: - CMapAreaBFSInfo(int areaIdx, int depth, float a, float b) - : x0_areaIdx(areaIdx), x4_depth(depth), x8_surfDrawDepth(a), xc_outlineDrawDepth(b) {} - int GetAreaIndex() const { return x0_areaIdx; } - int GetDepth() const { return x4_depth; } - float GetOutlineDrawDepth() const { return x8_surfDrawDepth; } - float GetSurfaceDrawDepth() const { return xc_outlineDrawDepth; } - }; + class CMapAreaBFSInfo { + int x0_areaIdx; + int x4_depth; + float x8_surfDrawDepth; + float xc_outlineDrawDepth; - class CMapObjectSortInfo - { - float x0_zDist; - int x4_areaIdx; - int x8_typeAndIdx; - zeus::CColor xc_surfColor; - zeus::CColor x10_outlineColor; - public: - enum class EObjectCode - { - Invalid = -1, - Object = 1 << 16, - DoorSurface = 2 << 16, - Door = 3 << 16, - Surface = 4 << 16 - }; + public: + CMapAreaBFSInfo(int areaIdx, int depth, float a, float b) + : x0_areaIdx(areaIdx), x4_depth(depth), x8_surfDrawDepth(a), xc_outlineDrawDepth(b) {} + int GetAreaIndex() const { return x0_areaIdx; } + int GetDepth() const { return x4_depth; } + float GetOutlineDrawDepth() const { return x8_surfDrawDepth; } + float GetSurfaceDrawDepth() const { return xc_outlineDrawDepth; } + }; - CMapObjectSortInfo(float zDist, int areaIdx, EObjectCode type, int idx, - const zeus::CColor& surfColor, const zeus::CColor& outlineColor) - : x0_zDist(zDist), x4_areaIdx(areaIdx), x8_typeAndIdx(int(type) | idx), - xc_surfColor(surfColor), x10_outlineColor(outlineColor) {} - const zeus::CColor& GetOutlineColor() const { return x10_outlineColor; } - const zeus::CColor& GetSurfaceColor() const { return xc_surfColor; } - u32 GetLocalObjectIndex() const { return x8_typeAndIdx & 0xffff; } - EObjectCode GetObjectCode() const { return EObjectCode(x8_typeAndIdx & 0xffff0000); } - u32 GetAreaIndex() const { return x4_areaIdx; } - float GetZDistance() const { return x0_zDist; } - }; + class CMapObjectSortInfo { + float x0_zDist; + int x4_areaIdx; + int x8_typeAndIdx; + zeus::CColor xc_surfColor; + zeus::CColor x10_outlineColor; - class CMapAreaData - { - TCachedToken x0_area; - EMapAreaList x10_list; - CMapAreaData* x14_next = nullptr; - public: - CMapAreaData(CAssetId areaRes, EMapAreaList list, CMapAreaData* next); - void Lock() { x0_area.Lock(); } - void Unlock() { x0_area.Unlock(); } - bool IsLoaded() const { return x0_area.IsLoaded(); } - const CMapArea* GetMapArea() const { return x0_area.GetObj(); } - const CMapAreaData* GetNextMapAreaData() const { return x14_next; } - EMapAreaList GetContainingList() const { return x10_list; } - CMapAreaData* NextMapAreaData() { return x14_next; } - void SetContainingList(EMapAreaList list) { x10_list = list; } - void SetNextMapArea(CMapAreaData* next) { x14_next = next; } - }; + public: + enum class EObjectCode { Invalid = -1, Object = 1 << 16, DoorSurface = 2 << 16, Door = 3 << 16, Surface = 4 << 16 }; - class CMapWorldDrawParms - { - float x0_alphaSurfVisited; - float x4_alphaOlVisited; - float x8_alphaSurfUnvisited; - float xc_alphaOlUnvisited; - float x10_alpha; - float x14_outlineWidthScale; - const CStateManager& x18_mgr; - const zeus::CTransform& x1c_modelXf; - const zeus::CTransform& x20_viewXf; - const IWorld& x24_wld; - const CMapWorldInfo& x28_mwInfo; - float x2c_playerFlashIntensity; - float x30_hintFlashIntensity; - float x34_objectScale; - bool x38_sortDoorSurfs; - public: - CMapWorldDrawParms(float alphaSurfVisited, float alphaOlVisited, - float alphaSurfUnvisited, float alphaOlUnvisited, - float alpha, float outlineWidthScale, const CStateManager& mgr, - const zeus::CTransform& modelXf, const zeus::CTransform& viewXf, - const IWorld& wld, const CMapWorldInfo& mwInfo, float playerFlash, - float hintFlash, float objectScale, bool sortDoorSurfs) - : x0_alphaSurfVisited(alphaSurfVisited), - x4_alphaOlVisited(alphaOlVisited), - x8_alphaSurfUnvisited(alphaSurfUnvisited), - xc_alphaOlUnvisited(alphaOlUnvisited), - x10_alpha(alpha), - x14_outlineWidthScale(outlineWidthScale), - x18_mgr(mgr), - x1c_modelXf(modelXf), - x20_viewXf(viewXf), - x24_wld(wld), - x28_mwInfo(mwInfo), - x2c_playerFlashIntensity(playerFlash), - x30_hintFlashIntensity(hintFlash), - x34_objectScale(objectScale), - x38_sortDoorSurfs(sortDoorSurfs) - {} - const IWorld& GetWorld() const { return x24_wld; } - float GetOutlineWidthScale() const { return x14_outlineWidthScale; } - const zeus::CTransform& GetPlaneProjectionTransform() const { return x1c_modelXf; } - float GetHintAreaFlashIntensity() const { return x30_hintFlashIntensity; } - float GetPlayerAreaFlashIntensity() const { return x2c_playerFlashIntensity; } - const zeus::CTransform& GetCameraTransform() const { return x20_viewXf; } - float GetAlphaOutlineUnvisited() const { return xc_alphaOlUnvisited; } - float GetAlphaSurfaceUnvisited() const { return x8_alphaSurfUnvisited; } - float GetAlphaOutlineVisited() const { return x4_alphaOlVisited; } - float GetAlphaSurfaceVisited() const { return x0_alphaSurfVisited; } - float GetAlpha() const { return x10_alpha; } - const CMapWorldInfo& GetMapWorldInfo() const { return x28_mwInfo; } - const CStateManager& GetStateManager() const { return x18_mgr; } - bool GetIsSortDoorSurfaces() const { return x38_sortDoorSurfs; } - float GetObjectScale() const { return x34_objectScale; } - }; + CMapObjectSortInfo(float zDist, int areaIdx, EObjectCode type, int idx, const zeus::CColor& surfColor, + const zeus::CColor& outlineColor) + : x0_zDist(zDist) + , x4_areaIdx(areaIdx) + , x8_typeAndIdx(int(type) | idx) + , xc_surfColor(surfColor) + , x10_outlineColor(outlineColor) {} + const zeus::CColor& GetOutlineColor() const { return x10_outlineColor; } + const zeus::CColor& GetSurfaceColor() const { return xc_surfColor; } + u32 GetLocalObjectIndex() const { return x8_typeAndIdx & 0xffff; } + EObjectCode GetObjectCode() const { return EObjectCode(x8_typeAndIdx & 0xffff0000); } + u32 GetAreaIndex() const { return x4_areaIdx; } + float GetZDistance() const { return x0_zDist; } + }; + + class CMapAreaData { + TCachedToken x0_area; + EMapAreaList x10_list; + CMapAreaData* x14_next = nullptr; + + public: + CMapAreaData(CAssetId areaRes, EMapAreaList list, CMapAreaData* next); + void Lock() { x0_area.Lock(); } + void Unlock() { x0_area.Unlock(); } + bool IsLoaded() const { return x0_area.IsLoaded(); } + const CMapArea* GetMapArea() const { return x0_area.GetObj(); } + const CMapAreaData* GetNextMapAreaData() const { return x14_next; } + EMapAreaList GetContainingList() const { return x10_list; } + CMapAreaData* NextMapAreaData() { return x14_next; } + void SetContainingList(EMapAreaList list) { x10_list = list; } + void SetNextMapArea(CMapAreaData* next) { x14_next = next; } + }; + + class CMapWorldDrawParms { + float x0_alphaSurfVisited; + float x4_alphaOlVisited; + float x8_alphaSurfUnvisited; + float xc_alphaOlUnvisited; + float x10_alpha; + float x14_outlineWidthScale; + const CStateManager& x18_mgr; + const zeus::CTransform& x1c_modelXf; + const zeus::CTransform& x20_viewXf; + const IWorld& x24_wld; + const CMapWorldInfo& x28_mwInfo; + float x2c_playerFlashIntensity; + float x30_hintFlashIntensity; + float x34_objectScale; + bool x38_sortDoorSurfs; + + public: + CMapWorldDrawParms(float alphaSurfVisited, float alphaOlVisited, float alphaSurfUnvisited, float alphaOlUnvisited, + float alpha, float outlineWidthScale, const CStateManager& mgr, const zeus::CTransform& modelXf, + const zeus::CTransform& viewXf, const IWorld& wld, const CMapWorldInfo& mwInfo, + float playerFlash, float hintFlash, float objectScale, bool sortDoorSurfs) + : x0_alphaSurfVisited(alphaSurfVisited) + , x4_alphaOlVisited(alphaOlVisited) + , x8_alphaSurfUnvisited(alphaSurfUnvisited) + , xc_alphaOlUnvisited(alphaOlUnvisited) + , x10_alpha(alpha) + , x14_outlineWidthScale(outlineWidthScale) + , x18_mgr(mgr) + , x1c_modelXf(modelXf) + , x20_viewXf(viewXf) + , x24_wld(wld) + , x28_mwInfo(mwInfo) + , x2c_playerFlashIntensity(playerFlash) + , x30_hintFlashIntensity(hintFlash) + , x34_objectScale(objectScale) + , x38_sortDoorSurfs(sortDoorSurfs) {} + const IWorld& GetWorld() const { return x24_wld; } + float GetOutlineWidthScale() const { return x14_outlineWidthScale; } + const zeus::CTransform& GetPlaneProjectionTransform() const { return x1c_modelXf; } + float GetHintAreaFlashIntensity() const { return x30_hintFlashIntensity; } + float GetPlayerAreaFlashIntensity() const { return x2c_playerFlashIntensity; } + const zeus::CTransform& GetCameraTransform() const { return x20_viewXf; } + float GetAlphaOutlineUnvisited() const { return xc_alphaOlUnvisited; } + float GetAlphaSurfaceUnvisited() const { return x8_alphaSurfUnvisited; } + float GetAlphaOutlineVisited() const { return x4_alphaOlVisited; } + float GetAlphaSurfaceVisited() const { return x0_alphaSurfVisited; } + float GetAlpha() const { return x10_alpha; } + const CMapWorldInfo& GetMapWorldInfo() const { return x28_mwInfo; } + const CStateManager& GetStateManager() const { return x18_mgr; } + bool GetIsSortDoorSurfaces() const { return x38_sortDoorSurfs; } + float GetObjectScale() const { return x34_objectScale; } + }; private: - std::vector x0_areas; - rstl::reserved_vector x10_listHeads; - std::vector x20_traversed; - zeus::CVector3f x30_worldSpherePoint; - float x3c_worldSphereRadius = 0.f; - float x40_worldSphereHalfDepth = 0.f; + std::vector x0_areas; + rstl::reserved_vector x10_listHeads; + std::vector x20_traversed; + zeus::CVector3f x30_worldSpherePoint; + float x3c_worldSphereRadius = 0.f; + float x40_worldSphereHalfDepth = 0.f; + public: - CMapWorld(CInputStream&); - u32 GetNumAreas() const { return x0_areas.size(); } - const CMapArea* GetMapArea(int aid) const { return x0_areas[aid].GetMapArea(); } - bool IsMapAreaInBFSInfoVector(const CMapAreaData*, const std::vector&) const; - void SetWhichMapAreasLoaded(const IWorld&, int start, int count); - bool IsMapAreasStreaming() const; - void MoveMapAreaToList(CMapAreaData*, EMapAreaList); - s32 GetCurrentMapAreaDepth(const IWorld&, int areaIdx) const; - std::vector GetVisibleAreas(const IWorld&, const CMapWorldInfo&) const; - void Draw(const CMapWorldDrawParms&, int, int, float, float, bool) const; - void DoBFS(const IWorld&, int, int, float, float, bool, std::vector&) const; - bool IsMapAreaValid(const IWorld&, int, bool) const; - void DrawAreas(const CMapWorldDrawParms&, int, const std::vector&, bool) const; - void RecalculateWorldSphere(const CMapWorldInfo&, const IWorld&) const; - zeus::CVector3f ConstrainToWorldVolume(const zeus::CVector3f&, const zeus::CVector3f&) const; - void ClearTraversedFlags() const; + CMapWorld(CInputStream&); + u32 GetNumAreas() const { return x0_areas.size(); } + const CMapArea* GetMapArea(int aid) const { return x0_areas[aid].GetMapArea(); } + bool IsMapAreaInBFSInfoVector(const CMapAreaData*, const std::vector&) const; + void SetWhichMapAreasLoaded(const IWorld&, int start, int count); + bool IsMapAreasStreaming() const; + void MoveMapAreaToList(CMapAreaData*, EMapAreaList); + s32 GetCurrentMapAreaDepth(const IWorld&, int areaIdx) const; + std::vector GetVisibleAreas(const IWorld&, const CMapWorldInfo&) const; + void Draw(const CMapWorldDrawParms&, int, int, float, float, bool) const; + void DoBFS(const IWorld&, int, int, float, float, bool, std::vector&) const; + bool IsMapAreaValid(const IWorld&, int, bool) const; + void DrawAreas(const CMapWorldDrawParms&, int, const std::vector&, bool) const; + void RecalculateWorldSphere(const CMapWorldInfo&, const IWorld&) const; + zeus::CVector3f ConstrainToWorldVolume(const zeus::CVector3f&, const zeus::CVector3f&) const; + void ClearTraversedFlags() const; }; CFactoryFnReturn FMapWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/AutoMapper/CMapWorldInfo.cpp b/Runtime/AutoMapper/CMapWorldInfo.cpp index 7c8c0670b..5831a3e61 100644 --- a/Runtime/AutoMapper/CMapWorldInfo.cpp +++ b/Runtime/AutoMapper/CMapWorldInfo.cpp @@ -2,136 +2,110 @@ #include "GameGlobalObjects.hpp" #include "CMemoryCardSys.hpp" -namespace urde -{ +namespace urde { -CMapWorldInfo::CMapWorldInfo(CBitStreamReader& reader, const CSaveWorld& savw, CAssetId mlvlId) -{ - const CSaveWorldMemory& worldMem = g_MemoryCardSys->GetSaveWorldMemory(mlvlId); +CMapWorldInfo::CMapWorldInfo(CBitStreamReader& reader, const CSaveWorld& savw, CAssetId mlvlId) { + const CSaveWorldMemory& worldMem = g_MemoryCardSys->GetSaveWorldMemory(mlvlId); - x4_visitedAreas.reserve((worldMem.GetAreaCount() + 31) / 32); - for (int i=0 ; iGetSaveWorldMemory(mlvlId); +void CMapWorldInfo::PutTo(CBitStreamWriter& writer, const CSaveWorld& savw, CAssetId mlvlId) const { + const CSaveWorldMemory& worldMem = g_MemoryCardSys->GetSaveWorldMemory(mlvlId); - for (int i=0 ; i x0_visitedAreasAllocated) - { - const_cast(*this).x4_visitedAreas.resize((aid + 32) / 32); - const_cast(*this).x0_visitedAreasAllocated = aid + 1; - } - return (x4_visitedAreas[aid / 32] >> (aid % 32)) & 0x1; -} - -void CMapWorldInfo::SetAreaVisited(TAreaId aid, bool visited) -{ - if (aid + 1 > x0_visitedAreasAllocated) - { - x4_visitedAreas.resize((aid + 32) / 32); - x0_visitedAreasAllocated = aid + 1; - } - if (visited) - x4_visitedAreas[aid / 32] |= 1 << (aid % 32); + for (int i = 0; i < worldMem.GetAreaCount(); ++i) { + if (i < x0_visitedAreasAllocated) + writer.WriteEncoded(IsAreaVisted(i), 1); else - x4_visitedAreas[aid / 32] &= ~(1 << (aid % 32)); -} + writer.WriteEncoded(0, 1); + } -bool CMapWorldInfo::IsMapped(TAreaId aid) const -{ - if (aid + 1 > x14_mappedAreasAllocated) - { - const_cast(*this).x18_mappedAreas.resize((aid + 32) / 32); - const_cast(*this).x14_mappedAreasAllocated = aid + 1; - } - return (x18_mappedAreas[aid / 32] >> (aid % 32)) & 0x1; -} - -void CMapWorldInfo::SetIsMapped(TAreaId aid, bool mapped) -{ - if (aid + 1 > x14_mappedAreasAllocated) - { - x18_mappedAreas.resize((aid + 32) / 32); - x14_mappedAreasAllocated = aid + 1; - } - if (mapped) - x18_mappedAreas[aid / 32] |= 1 << (aid % 32); + for (int i = 0; i < worldMem.GetAreaCount(); ++i) { + if (i < x14_mappedAreasAllocated) + writer.WriteEncoded(IsMapped(i), 1); else - x18_mappedAreas[aid / 32] &= ~(1 << (aid % 32)); + writer.WriteEncoded(0, 1); + } + + for (TEditorId doorId : savw.GetDoors()) + writer.WriteEncoded(IsDoorVisited(doorId), 1); + + writer.WriteEncoded(x38_mapStationUsed, 1); } -bool CMapWorldInfo::IsWorldVisible(TAreaId aid) const -{ - return x38_mapStationUsed || IsMapped(aid); +void CMapWorldInfo::SetDoorVisited(TEditorId eid, bool visited) { x28_visitedDoors[eid] = visited; } + +bool CMapWorldInfo::IsDoorVisited(TEditorId eid) const { return x28_visitedDoors.find(eid) != x28_visitedDoors.end(); } + +bool CMapWorldInfo::IsAreaVisted(TAreaId aid) const { + if (aid + 1 > x0_visitedAreasAllocated) { + const_cast(*this).x4_visitedAreas.resize((aid + 32) / 32); + const_cast(*this).x0_visitedAreasAllocated = aid + 1; + } + return (x4_visitedAreas[aid / 32] >> (aid % 32)) & 0x1; } -bool CMapWorldInfo::IsAreaVisible(TAreaId aid) const -{ - if (IsAreaVisted(aid) || IsMapped(aid)) - return true; - return false; +void CMapWorldInfo::SetAreaVisited(TAreaId aid, bool visited) { + if (aid + 1 > x0_visitedAreasAllocated) { + x4_visitedAreas.resize((aid + 32) / 32); + x0_visitedAreasAllocated = aid + 1; + } + if (visited) + x4_visitedAreas[aid / 32] |= 1 << (aid % 32); + else + x4_visitedAreas[aid / 32] &= ~(1 << (aid % 32)); } -bool CMapWorldInfo::IsAnythingSet() const -{ - for (int i=0 ; i x14_mappedAreasAllocated) { + const_cast(*this).x18_mappedAreas.resize((aid + 32) / 32); + const_cast(*this).x14_mappedAreasAllocated = aid + 1; + } + return (x18_mappedAreas[aid / 32] >> (aid % 32)) & 0x1; } +void CMapWorldInfo::SetIsMapped(TAreaId aid, bool mapped) { + if (aid + 1 > x14_mappedAreasAllocated) { + x18_mappedAreas.resize((aid + 32) / 32); + x14_mappedAreasAllocated = aid + 1; + } + if (mapped) + x18_mappedAreas[aid / 32] |= 1 << (aid % 32); + else + x18_mappedAreas[aid / 32] &= ~(1 << (aid % 32)); } + +bool CMapWorldInfo::IsWorldVisible(TAreaId aid) const { return x38_mapStationUsed || IsMapped(aid); } + +bool CMapWorldInfo::IsAreaVisible(TAreaId aid) const { + if (IsAreaVisted(aid) || IsMapped(aid)) + return true; + return false; +} + +bool CMapWorldInfo::IsAnythingSet() const { + for (int i = 0; i < x0_visitedAreasAllocated; ++i) + if (x4_visitedAreas[i / 32] & (1 << (i % 32))) + return true; + for (int i = 0; i < x14_mappedAreasAllocated; ++i) + if (x18_mappedAreas[i / 32] & (1 << (i % 32))) + return true; + return x38_mapStationUsed; +} + +} // namespace urde diff --git a/Runtime/AutoMapper/CMapWorldInfo.hpp b/Runtime/AutoMapper/CMapWorldInfo.hpp index 531974cf2..6306a1982 100644 --- a/Runtime/AutoMapper/CMapWorldInfo.hpp +++ b/Runtime/AutoMapper/CMapWorldInfo.hpp @@ -2,32 +2,30 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CSaveWorld; -class CMapWorldInfo -{ - u32 x0_visitedAreasAllocated = 0; - std::vector x4_visitedAreas; - u32 x14_mappedAreasAllocated = 0; - std::vector x18_mappedAreas; - std::map x28_visitedDoors; - bool x38_mapStationUsed = false; -public: - CMapWorldInfo()=default; - CMapWorldInfo(CBitStreamReader&, const CSaveWorld& saveWorld, CAssetId mlvlId); - void PutTo(CBitStreamWriter& writer, const CSaveWorld& savw, CAssetId mlvlId) const; - bool IsMapped(TAreaId) const; - void SetIsMapped(TAreaId, bool); - void SetDoorVisited(TEditorId eid, bool val); - bool IsDoorVisited(TEditorId eid) const; - bool IsAreaVisted(TAreaId) const; - void SetAreaVisited(TAreaId, bool); - bool IsWorldVisible(TAreaId) const; - bool IsAreaVisible(TAreaId) const; - bool IsAnythingSet() const; - void SetMapStationUsed(bool val) { x38_mapStationUsed = val; } -}; -} +class CMapWorldInfo { + u32 x0_visitedAreasAllocated = 0; + std::vector x4_visitedAreas; + u32 x14_mappedAreasAllocated = 0; + std::vector x18_mappedAreas; + std::map x28_visitedDoors; + bool x38_mapStationUsed = false; +public: + CMapWorldInfo() = default; + CMapWorldInfo(CBitStreamReader&, const CSaveWorld& saveWorld, CAssetId mlvlId); + void PutTo(CBitStreamWriter& writer, const CSaveWorld& savw, CAssetId mlvlId) const; + bool IsMapped(TAreaId) const; + void SetIsMapped(TAreaId, bool); + void SetDoorVisited(TEditorId eid, bool val); + bool IsDoorVisited(TEditorId eid) const; + bool IsAreaVisted(TAreaId) const; + void SetAreaVisited(TAreaId, bool); + bool IsWorldVisible(TAreaId) const; + bool IsAreaVisible(TAreaId) const; + bool IsAnythingSet() const; + void SetMapStationUsed(bool val) { x38_mapStationUsed = val; } +}; +} // namespace urde diff --git a/Runtime/AutoMapper/CMappableObject.cpp b/Runtime/AutoMapper/CMappableObject.cpp index 9c9ace08c..adc975a1e 100644 --- a/Runtime/AutoMapper/CMappableObject.cpp +++ b/Runtime/AutoMapper/CMappableObject.cpp @@ -5,308 +5,255 @@ #include "CToken.hpp" #include "Graphics/CTexture.hpp" -namespace urde -{ +namespace urde { const zeus::CVector3f CMappableObject::skDoorVerts[8] = {}; -static const u32 DoorIndices[] = -{ - 6, 4, 2, 0, - 3, 1, 7, 5, - 1, 0, 5, 4, - 7, 6, 3, 2, - 3, 2, 1, 0, - 5, 4, 7, 6 -}; +static const u32 DoorIndices[] = {6, 4, 2, 0, 3, 1, 7, 5, 1, 0, 5, 4, 7, 6, 3, 2, 3, 2, 1, 0, 5, 4, 7, 6}; -CMappableObject::CMappableObject(const void* buf) -{ - athena::io::MemoryReader r(buf, 64); - x0_type = EMappableObjectType(r.readUint32Big()); - x4_visibilityMode = EVisMode(r.readUint32Big()); - x8_objId = r.readUint32Big(); - xc_ = r.readUint32Big(); - x10_transform.read34RowMajor(r); +CMappableObject::CMappableObject(const void* buf) { + athena::io::MemoryReader r(buf, 64); + x0_type = EMappableObjectType(r.readUint32Big()); + x4_visibilityMode = EVisMode(r.readUint32Big()); + x8_objId = r.readUint32Big(); + xc_ = r.readUint32Big(); + x10_transform.read34RowMajor(r); } -zeus::CTransform CMappableObject::AdjustTransformForType() -{ - const float doorCenterX = g_tweakAutoMapper->GetDoorCenter().x(); - const float doorCenterZ = g_tweakAutoMapper->GetDoorCenter().z(); - if (x0_type == EMappableObjectType::BigDoor1) - { - zeus::CTransform orientation; - orientation.origin = {-1.4f*doorCenterX, 0.0f, 0.0f}; - orientation.rotateLocalZ(zeus::degToRad(90.0f)); - return (x10_transform * orientation) * zeus::CTransform::Scale(zeus::CVector3f{1.5f}); - } - else if (x0_type == EMappableObjectType::BigDoor2) - { - zeus::CTransform orientation; - orientation.origin = {0.f, -2.0f * doorCenterZ, -1.4f * doorCenterX}; - orientation.rotateLocalZ(zeus::degToRad(-90.f)); - return (x10_transform * orientation) * zeus::CTransform::Scale(zeus::CVector3f{1.5f}); - } - else if (x0_type == EMappableObjectType::IceDoorCeiling || x0_type == EMappableObjectType::WaveDoorCeiling - || x0_type == EMappableObjectType::PlasmaDoorCeiling) - { - zeus::CTransform orientation; - orientation.origin = {-1.65f * doorCenterX, 0.f, -1.5f * doorCenterZ}; - orientation.rotateLocalY(zeus::degToRad(90.f)); - return x10_transform * orientation; - } - else if (x0_type == EMappableObjectType::IceDoorFloor || x0_type == EMappableObjectType::WaveDoorFloor - || x0_type == EMappableObjectType::PlasmaDoorFloor) - { - zeus::CTransform orientation; - orientation.origin = {-1.65f * doorCenterX, 0.f, -1.f * doorCenterZ}; - orientation.rotateLocalY(zeus::degToRad(90.f)); - return x10_transform * orientation; - } - else if ((u32(x0_type) - u32(EMappableObjectType::IceDoorFloor2)) <= u32(EMappableObjectType::ShieldDoor) - || x0_type == EMappableObjectType::PlasmaDoorFloor2) - { - zeus::CTransform orientation; - orientation.origin = {-0.49f * doorCenterX, 0.f, -1.f * doorCenterZ}; - orientation.rotateLocalY(zeus::degToRad(90.f)); - return x10_transform * orientation; - } - else if (x0_type >= EMappableObjectType::BlueDoor || x0_type <= EMappableObjectType::PlasmaDoorFloor2) - { - return x10_transform; - } - return zeus::CTransform::Translate(x10_transform.origin); +zeus::CTransform CMappableObject::AdjustTransformForType() { + const float doorCenterX = g_tweakAutoMapper->GetDoorCenter().x(); + const float doorCenterZ = g_tweakAutoMapper->GetDoorCenter().z(); + if (x0_type == EMappableObjectType::BigDoor1) { + zeus::CTransform orientation; + orientation.origin = {-1.4f * doorCenterX, 0.0f, 0.0f}; + orientation.rotateLocalZ(zeus::degToRad(90.0f)); + return (x10_transform * orientation) * zeus::CTransform::Scale(zeus::CVector3f{1.5f}); + } else if (x0_type == EMappableObjectType::BigDoor2) { + zeus::CTransform orientation; + orientation.origin = {0.f, -2.0f * doorCenterZ, -1.4f * doorCenterX}; + orientation.rotateLocalZ(zeus::degToRad(-90.f)); + return (x10_transform * orientation) * zeus::CTransform::Scale(zeus::CVector3f{1.5f}); + } else if (x0_type == EMappableObjectType::IceDoorCeiling || x0_type == EMappableObjectType::WaveDoorCeiling || + x0_type == EMappableObjectType::PlasmaDoorCeiling) { + zeus::CTransform orientation; + orientation.origin = {-1.65f * doorCenterX, 0.f, -1.5f * doorCenterZ}; + orientation.rotateLocalY(zeus::degToRad(90.f)); + return x10_transform * orientation; + } else if (x0_type == EMappableObjectType::IceDoorFloor || x0_type == EMappableObjectType::WaveDoorFloor || + x0_type == EMappableObjectType::PlasmaDoorFloor) { + zeus::CTransform orientation; + orientation.origin = {-1.65f * doorCenterX, 0.f, -1.f * doorCenterZ}; + orientation.rotateLocalY(zeus::degToRad(90.f)); + return x10_transform * orientation; + } else if ((u32(x0_type) - u32(EMappableObjectType::IceDoorFloor2)) <= u32(EMappableObjectType::ShieldDoor) || + x0_type == EMappableObjectType::PlasmaDoorFloor2) { + zeus::CTransform orientation; + orientation.origin = {-0.49f * doorCenterX, 0.f, -1.f * doorCenterZ}; + orientation.rotateLocalY(zeus::degToRad(90.f)); + return x10_transform * orientation; + } else if (x0_type >= EMappableObjectType::BlueDoor || x0_type <= EMappableObjectType::PlasmaDoorFloor2) { + return x10_transform; + } + return zeus::CTransform::Translate(x10_transform.origin); } -std::pair -CMappableObject::GetDoorColors(int curAreaId, const CMapWorldInfo& mwInfo, float alpha) const -{ - zeus::CColor color = {1.f, 0.f, 1.f, 1.f}; - if (x8_objId.AreaNum() == curAreaId) - { - if (mwInfo.IsDoorVisited(x8_objId) && x0_type == EMappableObjectType::ShieldDoor) - { - color = g_tweakAutoMapper->GetDoorColor(0); - } - else - { - int colorIdx = 0; - switch (x0_type) - { - case EMappableObjectType::ShieldDoor: - colorIdx = 1; - break; - case EMappableObjectType::IceDoor: - case EMappableObjectType::IceDoorCeiling: - case EMappableObjectType::IceDoorFloor: - case EMappableObjectType::IceDoorFloor2: - colorIdx = 2; - break; - case EMappableObjectType::WaveDoor: - case EMappableObjectType::WaveDoorCeiling: - case EMappableObjectType::WaveDoorFloor: - case EMappableObjectType::WaveDoorFloor2: - colorIdx = 3; - break; - case EMappableObjectType::PlasmaDoor: - case EMappableObjectType::PlasmaDoorCeiling: - case EMappableObjectType::PlasmaDoorFloor: - case EMappableObjectType::PlasmaDoorFloor2: - colorIdx = 4; - default: break; - } - color = g_tweakAutoMapper->GetDoorColor(colorIdx); - } - } - else if (mwInfo.IsDoorVisited(x8_objId)) - { - color = g_tweakAutoMapper->GetOpenDoorColor(); - } - else - { - color = zeus::CColor::skClear; +std::pair CMappableObject::GetDoorColors(int curAreaId, const CMapWorldInfo& mwInfo, + float alpha) const { + zeus::CColor color = {1.f, 0.f, 1.f, 1.f}; + if (x8_objId.AreaNum() == curAreaId) { + if (mwInfo.IsDoorVisited(x8_objId) && x0_type == EMappableObjectType::ShieldDoor) { + color = g_tweakAutoMapper->GetDoorColor(0); + } else { + int colorIdx = 0; + switch (x0_type) { + case EMappableObjectType::ShieldDoor: + colorIdx = 1; + break; + case EMappableObjectType::IceDoor: + case EMappableObjectType::IceDoorCeiling: + case EMappableObjectType::IceDoorFloor: + case EMappableObjectType::IceDoorFloor2: + colorIdx = 2; + break; + case EMappableObjectType::WaveDoor: + case EMappableObjectType::WaveDoorCeiling: + case EMappableObjectType::WaveDoorFloor: + case EMappableObjectType::WaveDoorFloor2: + colorIdx = 3; + break; + case EMappableObjectType::PlasmaDoor: + case EMappableObjectType::PlasmaDoorCeiling: + case EMappableObjectType::PlasmaDoorFloor: + case EMappableObjectType::PlasmaDoorFloor2: + colorIdx = 4; + default: + break; + } + color = g_tweakAutoMapper->GetDoorColor(colorIdx); } + } else if (mwInfo.IsDoorVisited(x8_objId)) { + color = g_tweakAutoMapper->GetOpenDoorColor(); + } else { + color = zeus::CColor::skClear; + } - color.a() *= alpha; - return {color, zeus::CColor(std::min(1.4f * color.r(), 1.f), - std::min(1.4f * color.g(), 1.f), - std::min(1.4f * color.b(), 1.f), - std::min(1.4f * color.a(), 1.f))}; + color.a() *= alpha; + return {color, zeus::CColor(std::min(1.4f * color.r(), 1.f), std::min(1.4f * color.g(), 1.f), + std::min(1.4f * color.b(), 1.f), std::min(1.4f * color.a(), 1.f))}; } -void CMappableObject::PostConstruct(const void *) -{ - x10_transform = AdjustTransformForType(); -} +void CMappableObject::PostConstruct(const void*) { x10_transform = AdjustTransformForType(); } -void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo, - float alpha, bool needsVtxLoad) const -{ - if (IsDoorType(x0_type)) - { - std::pair colors = GetDoorColors(curArea, mwInfo, alpha); - for (int s=0 ; s<6 ; ++s) - { - DoorSurface& ds = const_cast(*m_doorSurface); - ds.m_surface.draw(colors.first, s * 4, 4); - CLineRenderer& line = ds.m_outline; - const u32* baseIdx = &DoorIndices[s * 4]; - line.Reset(); - line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f); - line.Render(); - } - } - else - { - CAssetId iconRes; - zeus::CColor iconColor = zeus::CColor::skWhite; - switch (x0_type) - { - case EMappableObjectType::DownArrowYellow: - iconRes = g_tweakPlayerRes->x10_minesBreakFirstTopIcon; - iconColor = zeus::CColor{1.f, 1.f, 0.588f, 1.f}; - break; - case EMappableObjectType::UpArrowYellow: - iconRes = g_tweakPlayerRes->x14_minesBreakFirstBottomIcon; - iconColor = zeus::CColor{1.f, 1.f, 0.588f, 1.f}; - break; - case EMappableObjectType::DownArrowGreen: - iconRes = g_tweakPlayerRes->x10_minesBreakFirstTopIcon; - iconColor = zeus::CColor{0.392f, 1.f, 0.588f, 1.f}; - break; - case EMappableObjectType::UpArrowGreen: - iconRes = g_tweakPlayerRes->x14_minesBreakFirstBottomIcon; - iconColor = zeus::CColor{0.392f, 1.f, 0.588f, 1.f}; - break; - case EMappableObjectType::DownArrowRed: - iconRes = g_tweakPlayerRes->x10_minesBreakFirstTopIcon; - iconColor = zeus::CColor{1.f, 0.392f, 0.588f, 1.f}; - break; - case EMappableObjectType::UpArrowRed: - iconRes = g_tweakPlayerRes->x14_minesBreakFirstBottomIcon; - iconColor = zeus::CColor{1.f, 0.392f, 0.588f, 1.f}; - break; - case EMappableObjectType::SaveStation: - iconRes = g_tweakPlayerRes->x4_saveStationIcon; - break; - case EMappableObjectType::MissileStation: - iconRes = g_tweakPlayerRes->x8_missileStationIcon; - break; - default: - iconRes = g_tweakPlayerRes->xc_elevatorIcon; - break; - } - - iconColor.a() *= alpha; - - TLockedToken tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), iconRes}); - if (!m_texQuadFilter || m_texQuadFilter->GetTex().GetObj() != tex.GetObj()) - const_cast(this)->m_texQuadFilter.emplace(EFilterType::Add, tex, - CTexturedQuadFilter::ZTest::GEqual); - - CTexturedQuadFilter::Vert verts[4] = - { - {{-2.6f, 0.f, 2.6f}, {0.f, 1.f}}, - {{-2.6f, 0.f, -2.6f}, {0.f, 0.f}}, - {{2.6f, 0.f, 2.6f}, {1.f, 1.f}}, - {{2.6f, 0.f, -2.6f}, {1.f, 0.f}} - }; - const_cast(this)->m_texQuadFilter->drawVerts(iconColor, verts); - } -} - -void CMappableObject::DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo, - float alpha, int surfIdx, bool needsVtxLoad) const -{ +void CMappableObject::Draw(int curArea, const CMapWorldInfo& mwInfo, float alpha, bool needsVtxLoad) const { + if (IsDoorType(x0_type)) { std::pair colors = GetDoorColors(curArea, mwInfo, alpha); - DoorSurface& ds = const_cast(*m_doorSurface); - ds.m_surface.draw(colors.first, surfIdx * 4, 4); - CLineRenderer& line = ds.m_outline; - const u32* baseIdx = &DoorIndices[surfIdx * 4]; - line.Reset(); - line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f); - line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f); - line.Render(); -} - -zeus::CVector3f CMappableObject::BuildSurfaceCenterPoint(int surfIdx) const -{ - const zeus::CVector3f& doorCenter = g_tweakAutoMapper->GetDoorCenter(); - - switch (surfIdx) - { - case 0: - return x10_transform * zeus::CVector3f::skZero; - case 1: - return x10_transform * zeus::CVector3f{0.f, 0.f, 2.f * doorCenter.x()}; - case 2: - return x10_transform * zeus::CVector3f{0.f, -doorCenter.y(), 0.f}; - case 3: - return x10_transform * zeus::CVector3f{0.f, doorCenter.y(), 0.f}; - case 4: - return x10_transform * zeus::CVector3f{-doorCenter.x(), 0.f, 0.f}; - case 5: - return x10_transform * zeus::CVector3f{doorCenter.x(), 0.f, 0.f}; - default: break; + for (int s = 0; s < 6; ++s) { + DoorSurface& ds = const_cast(*m_doorSurface); + ds.m_surface.draw(colors.first, s * 4, 4); + CLineRenderer& line = ds.m_outline; + const u32* baseIdx = &DoorIndices[s * 4]; + line.Reset(); + line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f); + line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f); + line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f); + line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f); + line.Render(); } - - return {}; -} - -bool CMappableObject::IsVisibleToAutoMapper(bool worldVis, const CMapWorldInfo& mwInfo) const -{ - bool areaVis = mwInfo.IsAreaVisible(x8_objId.AreaNum()); - switch (x4_visibilityMode) - { - case EVisMode::Always: + } else { + CAssetId iconRes; + zeus::CColor iconColor = zeus::CColor::skWhite; + switch (x0_type) { + case EMappableObjectType::DownArrowYellow: + iconRes = g_tweakPlayerRes->x10_minesBreakFirstTopIcon; + iconColor = zeus::CColor{1.f, 1.f, 0.588f, 1.f}; + break; + case EMappableObjectType::UpArrowYellow: + iconRes = g_tweakPlayerRes->x14_minesBreakFirstBottomIcon; + iconColor = zeus::CColor{1.f, 1.f, 0.588f, 1.f}; + break; + case EMappableObjectType::DownArrowGreen: + iconRes = g_tweakPlayerRes->x10_minesBreakFirstTopIcon; + iconColor = zeus::CColor{0.392f, 1.f, 0.588f, 1.f}; + break; + case EMappableObjectType::UpArrowGreen: + iconRes = g_tweakPlayerRes->x14_minesBreakFirstBottomIcon; + iconColor = zeus::CColor{0.392f, 1.f, 0.588f, 1.f}; + break; + case EMappableObjectType::DownArrowRed: + iconRes = g_tweakPlayerRes->x10_minesBreakFirstTopIcon; + iconColor = zeus::CColor{1.f, 0.392f, 0.588f, 1.f}; + break; + case EMappableObjectType::UpArrowRed: + iconRes = g_tweakPlayerRes->x14_minesBreakFirstBottomIcon; + iconColor = zeus::CColor{1.f, 0.392f, 0.588f, 1.f}; + break; + case EMappableObjectType::SaveStation: + iconRes = g_tweakPlayerRes->x4_saveStationIcon; + break; + case EMappableObjectType::MissileStation: + iconRes = g_tweakPlayerRes->x8_missileStationIcon; + break; default: - return true; - case EVisMode::MapStationOrVisit: - case EVisMode::MapStationOrVisit2: - return worldVis || areaVis; - case EVisMode::Visit: - if (IsDoorType(x0_type)) - return mwInfo.IsDoorVisited(x8_objId); - return areaVis; - case EVisMode::Never: - return false; + iconRes = g_tweakPlayerRes->xc_elevatorIcon; + break; } + + iconColor.a() *= alpha; + + TLockedToken tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), iconRes}); + if (!m_texQuadFilter || m_texQuadFilter->GetTex().GetObj() != tex.GetObj()) + const_cast(this)->m_texQuadFilter.emplace(EFilterType::Add, tex, + CTexturedQuadFilter::ZTest::GEqual); + + CTexturedQuadFilter::Vert verts[4] = {{{-2.6f, 0.f, 2.6f}, {0.f, 1.f}}, + {{-2.6f, 0.f, -2.6f}, {0.f, 0.f}}, + {{2.6f, 0.f, 2.6f}, {1.f, 1.f}}, + {{2.6f, 0.f, -2.6f}, {1.f, 0.f}}}; + const_cast(this)->m_texQuadFilter->drawVerts(iconColor, verts); + } +} + +void CMappableObject::DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo, float alpha, int surfIdx, + bool needsVtxLoad) const { + std::pair colors = GetDoorColors(curArea, mwInfo, alpha); + DoorSurface& ds = const_cast(*m_doorSurface); + ds.m_surface.draw(colors.first, surfIdx * 4, 4); + CLineRenderer& line = ds.m_outline; + const u32* baseIdx = &DoorIndices[surfIdx * 4]; + line.Reset(); + line.AddVertex(skDoorVerts[baseIdx[0]], colors.second, 1.f); + line.AddVertex(skDoorVerts[baseIdx[1]], colors.second, 1.f); + line.AddVertex(skDoorVerts[baseIdx[3]], colors.second, 1.f); + line.AddVertex(skDoorVerts[baseIdx[2]], colors.second, 1.f); + line.Render(); +} + +zeus::CVector3f CMappableObject::BuildSurfaceCenterPoint(int surfIdx) const { + const zeus::CVector3f& doorCenter = g_tweakAutoMapper->GetDoorCenter(); + + switch (surfIdx) { + case 0: + return x10_transform * zeus::CVector3f::skZero; + case 1: + return x10_transform * zeus::CVector3f{0.f, 0.f, 2.f * doorCenter.x()}; + case 2: + return x10_transform * zeus::CVector3f{0.f, -doorCenter.y(), 0.f}; + case 3: + return x10_transform * zeus::CVector3f{0.f, doorCenter.y(), 0.f}; + case 4: + return x10_transform * zeus::CVector3f{-doorCenter.x(), 0.f, 0.f}; + case 5: + return x10_transform * zeus::CVector3f{doorCenter.x(), 0.f, 0.f}; + default: + break; + } + + return {}; +} + +bool CMappableObject::IsVisibleToAutoMapper(bool worldVis, const CMapWorldInfo& mwInfo) const { + bool areaVis = mwInfo.IsAreaVisible(x8_objId.AreaNum()); + switch (x4_visibilityMode) { + case EVisMode::Always: + default: + return true; + case EVisMode::MapStationOrVisit: + case EVisMode::MapStationOrVisit2: + return worldVis || areaVis; + case EVisMode::Visit: + if (IsDoorType(x0_type)) + return mwInfo.IsDoorVisited(x8_objId); + return areaVis; + case EVisMode::Never: + return false; + } } boo::ObjToken CMappableObject::g_doorVbo; boo::ObjToken CMappableObject::g_doorIbo; -void CMappableObject::ReadAutoMapperTweaks(const ITweakAutoMapper& tweaks) -{ - const zeus::CVector3f& center = tweaks.GetDoorCenter(); - zeus::simd_floats centerF(center.mSimd); - zeus::CVector3f* doorVerts = const_cast(&CMappableObject::skDoorVerts[0]); - /* Wrap door verts around -Z to build surface */ - doorVerts[0].assign( -centerF[2], -centerF[1], 0.f); - doorVerts[1].assign( -centerF[2], -centerF[1], 2.f * centerF[0]); - doorVerts[2].assign( -centerF[2], centerF[1], 0.f); - doorVerts[3].assign( -centerF[2], centerF[1], 2.f * centerF[0]); - doorVerts[4].assign(.2f * -centerF[2], -centerF[1], 0.f); - doorVerts[5].assign(.2f * -centerF[2], -centerF[1], 2.f * centerF[0]); - doorVerts[6].assign(.2f * -centerF[2], centerF[1], 0.f); - doorVerts[7].assign(.2f * -centerF[2], centerF[1], 2.f * centerF[0]); +void CMappableObject::ReadAutoMapperTweaks(const ITweakAutoMapper& tweaks) { + const zeus::CVector3f& center = tweaks.GetDoorCenter(); + zeus::simd_floats centerF(center.mSimd); + zeus::CVector3f* doorVerts = const_cast(&CMappableObject::skDoorVerts[0]); + /* Wrap door verts around -Z to build surface */ + doorVerts[0].assign(-centerF[2], -centerF[1], 0.f); + doorVerts[1].assign(-centerF[2], -centerF[1], 2.f * centerF[0]); + doorVerts[2].assign(-centerF[2], centerF[1], 0.f); + doorVerts[3].assign(-centerF[2], centerF[1], 2.f * centerF[0]); + doorVerts[4].assign(.2f * -centerF[2], -centerF[1], 0.f); + doorVerts[5].assign(.2f * -centerF[2], -centerF[1], 2.f * centerF[0]); + doorVerts[6].assign(.2f * -centerF[2], centerF[1], 0.f); + doorVerts[7].assign(.2f * -centerF[2], centerF[1], 2.f * centerF[0]); - CGraphics::CommitResources([](boo::IGraphicsDataFactory::Context& ctx) - { - g_doorVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, skDoorVerts, 16, 8); - g_doorIbo = ctx.newStaticBuffer(boo::BufferUse::Index, DoorIndices, 4, 24); - return true; - } BooTrace); + CGraphics::CommitResources([](boo::IGraphicsDataFactory::Context& ctx) { + g_doorVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, skDoorVerts, 16, 8); + g_doorIbo = ctx.newStaticBuffer(boo::BufferUse::Index, DoorIndices, 4, 24); + return true; + } BooTrace); } -void CMappableObject::Shutdown() -{ - g_doorVbo.reset(); - g_doorIbo.reset(); -} +void CMappableObject::Shutdown() { + g_doorVbo.reset(); + g_doorIbo.reset(); } +} // namespace urde diff --git a/Runtime/AutoMapper/CMappableObject.hpp b/Runtime/AutoMapper/CMappableObject.hpp index f834d7d85..bc219c1fc 100644 --- a/Runtime/AutoMapper/CMappableObject.hpp +++ b/Runtime/AutoMapper/CMappableObject.hpp @@ -8,98 +8,87 @@ #include "Graphics/Shaders/CTexturedQuadFilter.hpp" #include "Graphics/CLineRenderer.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CMapWorldInfo; -class CMappableObject -{ - friend class CMapArea; - static boo::ObjToken g_doorVbo; - static boo::ObjToken g_doorIbo; +class CMappableObject { + friend class CMapArea; + static boo::ObjToken g_doorVbo; + static boo::ObjToken g_doorIbo; public: - enum class EMappableObjectType - { - BlueDoor = 0, - ShieldDoor = 1, - IceDoor = 2, - WaveDoor = 3, - PlasmaDoor = 4, - BigDoor1 = 5, - BigDoor2 = 6, - IceDoorCeiling = 7, - IceDoorFloor = 8, - WaveDoorCeiling = 9, - WaveDoorFloor = 10, - PlasmaDoorCeiling= 11, - PlasmaDoorFloor = 12, - IceDoorFloor2 = 13, - WaveDoorFloor2 = 14, - PlasmaDoorFloor2 = 15, - DownArrowYellow = 27, /* Maintenance Tunnel */ - UpArrowYellow = 28, /* Phazon Processing Center */ - DownArrowGreen = 29, /* Elevator A */ - UpArrowGreen = 30, /* Elite Control Access */ - DownArrowRed = 31, /* Elevator B */ - UpArrowRed = 32, /* Fungal Hall Access */ - TransportLift = 33, - SaveStation = 34, - MissileStation = 37 - }; + enum class EMappableObjectType { + BlueDoor = 0, + ShieldDoor = 1, + IceDoor = 2, + WaveDoor = 3, + PlasmaDoor = 4, + BigDoor1 = 5, + BigDoor2 = 6, + IceDoorCeiling = 7, + IceDoorFloor = 8, + WaveDoorCeiling = 9, + WaveDoorFloor = 10, + PlasmaDoorCeiling = 11, + PlasmaDoorFloor = 12, + IceDoorFloor2 = 13, + WaveDoorFloor2 = 14, + PlasmaDoorFloor2 = 15, + DownArrowYellow = 27, /* Maintenance Tunnel */ + UpArrowYellow = 28, /* Phazon Processing Center */ + DownArrowGreen = 29, /* Elevator A */ + UpArrowGreen = 30, /* Elite Control Access */ + DownArrowRed = 31, /* Elevator B */ + UpArrowRed = 32, /* Fungal Hall Access */ + TransportLift = 33, + SaveStation = 34, + MissileStation = 37 + }; - enum class EVisMode - { - Always, - MapStationOrVisit, - Visit, - Never, - MapStationOrVisit2 - }; + enum class EVisMode { Always, MapStationOrVisit, Visit, Never, MapStationOrVisit2 }; private: - static const zeus::CVector3f skDoorVerts[8]; + static const zeus::CVector3f skDoorVerts[8]; - EMappableObjectType x0_type; - EVisMode x4_visibilityMode; - TEditorId x8_objId; - u32 xc_; - zeus::CTransform x10_transform; + EMappableObjectType x0_type; + EVisMode x4_visibilityMode; + TEditorId x8_objId; + u32 xc_; + zeus::CTransform x10_transform; - struct DoorSurface - { - CMapSurfaceShader m_surface; - CLineRenderer m_outline; - DoorSurface(boo::IGraphicsDataFactory::Context& ctx) - : m_surface(ctx, g_doorVbo, g_doorIbo), - m_outline(ctx, CLineRenderer::EPrimitiveMode::LineLoop, 5, nullptr, false, false, true) - {} - }; - std::experimental::optional m_doorSurface; - std::experimental::optional m_texQuadFilter; + struct DoorSurface { + CMapSurfaceShader m_surface; + CLineRenderer m_outline; + DoorSurface(boo::IGraphicsDataFactory::Context& ctx) + : m_surface(ctx, g_doorVbo, g_doorIbo) + , m_outline(ctx, CLineRenderer::EPrimitiveMode::LineLoop, 5, nullptr, false, false, true) {} + }; + std::experimental::optional m_doorSurface; + std::experimental::optional m_texQuadFilter; + + zeus::CTransform AdjustTransformForType(); + std::pair GetDoorColors(int idx, const CMapWorldInfo& mwInfo, float alpha) const; - zeus::CTransform AdjustTransformForType(); - std::pair GetDoorColors(int idx, const CMapWorldInfo& mwInfo, float alpha) const; public: - CMappableObject(const void* buf); - CMappableObject(CMappableObject&&) = default; - void PostConstruct(const void*); - const zeus::CTransform& GetTransform() const { return x10_transform; } - EMappableObjectType GetType() const { return x0_type; } - void Draw(int, const CMapWorldInfo&, float, bool) const; - void DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo, float alpha, - int surfIdx, bool needsVtxLoad) const; - zeus::CVector3f BuildSurfaceCenterPoint(int surfIdx) const; - bool IsDoorConnectedToArea(int idx, const CStateManager&) const; - bool IsDoorConnectedToVisitedArea(const CStateManager&) const; - bool IsVisibleToAutoMapper(bool worldVis, const CMapWorldInfo& mwInfo) const; - bool GetIsSeen() const; + CMappableObject(const void* buf); + CMappableObject(CMappableObject&&) = default; + void PostConstruct(const void*); + const zeus::CTransform& GetTransform() const { return x10_transform; } + EMappableObjectType GetType() const { return x0_type; } + void Draw(int, const CMapWorldInfo&, float, bool) const; + void DrawDoorSurface(int curArea, const CMapWorldInfo& mwInfo, float alpha, int surfIdx, bool needsVtxLoad) const; + zeus::CVector3f BuildSurfaceCenterPoint(int surfIdx) const; + bool IsDoorConnectedToArea(int idx, const CStateManager&) const; + bool IsDoorConnectedToVisitedArea(const CStateManager&) const; + bool IsVisibleToAutoMapper(bool worldVis, const CMapWorldInfo& mwInfo) const; + bool GetIsSeen() const; - static void ReadAutoMapperTweaks(const ITweakAutoMapper&); - static bool GetTweakIsMapVisibilityCheat(); - static bool IsDoorType(EMappableObjectType type) { return type >= EMappableObjectType::BlueDoor && - type <= EMappableObjectType::PlasmaDoorFloor2; } - static void Shutdown(); + static void ReadAutoMapperTweaks(const ITweakAutoMapper&); + static bool GetTweakIsMapVisibilityCheat(); + static bool IsDoorType(EMappableObjectType type) { + return type >= EMappableObjectType::BlueDoor && type <= EMappableObjectType::PlasmaDoorFloor2; + } + static void Shutdown(); }; -} +} // namespace urde diff --git a/Runtime/CArchitectureMessage.hpp b/Runtime/CArchitectureMessage.hpp index e1f0cc069..a1776752e 100644 --- a/Runtime/CArchitectureMessage.hpp +++ b/Runtime/CArchitectureMessage.hpp @@ -4,178 +4,140 @@ #include "Input/CFinalInput.hpp" #include "rstl.hpp" -namespace urde -{ +namespace urde { class CIOWin; -enum class EArchMsgTarget -{ - IOWinManager = 0, - Game = 1, +enum class EArchMsgTarget { + IOWinManager = 0, + Game = 1, }; -enum class EArchMsgType -{ - RemoveIOWin = 0, - CreateIOWin = 1, - ChangeIOWinPriority = 2, - RemoveAllIOWins = 3, - TimerTick = 4, - UserInput = 5, - SetGameState = 6, - ControllerStatus = 7, - QuitGameplay = 8, - FrameBegin = 10, - FrameEnd = 11, +enum class EArchMsgType { + RemoveIOWin = 0, + CreateIOWin = 1, + ChangeIOWinPriority = 2, + RemoveAllIOWins = 3, + TimerTick = 4, + UserInput = 5, + SetGameState = 6, + ControllerStatus = 7, + QuitGameplay = 8, + FrameBegin = 10, + FrameEnd = 11, }; -struct IArchMsgParm -{ - virtual ~IArchMsgParm() = default; +struct IArchMsgParm { + virtual ~IArchMsgParm() = default; }; -struct CArchMsgParmInt32 : IArchMsgParm -{ - u32 x4_parm; - CArchMsgParmInt32(u32 parm) : x4_parm(parm) {} +struct CArchMsgParmInt32 : IArchMsgParm { + u32 x4_parm; + CArchMsgParmInt32(u32 parm) : x4_parm(parm) {} }; -struct CArchMsgParmVoidPtr : IArchMsgParm -{ - void* x4_parm1; - CArchMsgParmVoidPtr(void* parm1) : x4_parm1(parm1) {} +struct CArchMsgParmVoidPtr : IArchMsgParm { + void* x4_parm1; + CArchMsgParmVoidPtr(void* parm1) : x4_parm1(parm1) {} }; -struct CArchMsgParmInt32Int32VoidPtr : IArchMsgParm -{ - u32 x4_parm1; - u32 x8_parm2; - void* xc_parm3; - CArchMsgParmInt32Int32VoidPtr(u32 parm1, u32 parm2, void* parm3) - : x4_parm1(parm1), x8_parm2(parm2), xc_parm3(parm3) {} +struct CArchMsgParmInt32Int32VoidPtr : IArchMsgParm { + u32 x4_parm1; + u32 x8_parm2; + void* xc_parm3; + CArchMsgParmInt32Int32VoidPtr(u32 parm1, u32 parm2, void* parm3) + : x4_parm1(parm1), x8_parm2(parm2), xc_parm3(parm3) {} }; -struct CArchMsgParmInt32Int32IOWin : IArchMsgParm -{ - u32 x4_parm1; - u32 x8_parm2; - std::shared_ptr xc_parm3; - CArchMsgParmInt32Int32IOWin(u32 parm1, u32 parm2, std::shared_ptr&& parm3) - : x4_parm1(parm1), x8_parm2(parm2), xc_parm3(std::move(parm3)) {} +struct CArchMsgParmInt32Int32IOWin : IArchMsgParm { + u32 x4_parm1; + u32 x8_parm2; + std::shared_ptr xc_parm3; + CArchMsgParmInt32Int32IOWin(u32 parm1, u32 parm2, std::shared_ptr&& parm3) + : x4_parm1(parm1), x8_parm2(parm2), xc_parm3(std::move(parm3)) {} }; -struct CArchMsgParmNull : IArchMsgParm -{ +struct CArchMsgParmNull : IArchMsgParm {}; + +struct CArchMsgParmReal32 : IArchMsgParm { + float x4_parm; + CArchMsgParmReal32(float parm) : x4_parm(parm) {} }; -struct CArchMsgParmReal32 : IArchMsgParm -{ - float x4_parm; - CArchMsgParmReal32(float parm) : x4_parm(parm) {} +struct CArchMsgParmUserInput : IArchMsgParm { + CFinalInput x4_parm; + CArchMsgParmUserInput(const CFinalInput& parm) : x4_parm(parm) {} }; -struct CArchMsgParmUserInput : IArchMsgParm -{ - CFinalInput x4_parm; - CArchMsgParmUserInput(const CFinalInput& parm) : x4_parm(parm) {} +struct CArchMsgParmControllerStatus : IArchMsgParm { + u16 x4_parm1; + bool x6_parm2; + CArchMsgParmControllerStatus(u16 a, bool b) : x4_parm1(a), x6_parm2(b) {} }; -struct CArchMsgParmControllerStatus : IArchMsgParm -{ - u16 x4_parm1; - bool x6_parm2; - CArchMsgParmControllerStatus(u16 a, bool b) : x4_parm1(a), x6_parm2(b) {} -}; - -class CArchitectureMessage -{ - EArchMsgTarget x0_target; - EArchMsgType x4_type; - std::shared_ptr x8_parm; +class CArchitectureMessage { + EArchMsgTarget x0_target; + EArchMsgType x4_type; + std::shared_ptr x8_parm; public: - CArchitectureMessage(EArchMsgTarget target, EArchMsgType type, - std::shared_ptr&& parm) - : x0_target(target), x4_type(type), x8_parm(std::move(parm)) {} + CArchitectureMessage(EArchMsgTarget target, EArchMsgType type, std::shared_ptr&& parm) + : x0_target(target), x4_type(type), x8_parm(std::move(parm)) {} - EArchMsgTarget GetTarget() const { return x0_target; } - EArchMsgType GetType() const { return x4_type; } - template - const T* GetParm() const - { - return static_cast(x8_parm.get()); - } + EArchMsgTarget GetTarget() const { return x0_target; } + EArchMsgType GetType() const { return x4_type; } + template + const T* GetParm() const { + return static_cast(x8_parm.get()); + } }; -class MakeMsg -{ +class MakeMsg { public: - static CArchitectureMessage CreateQuitGameplay(EArchMsgTarget target) - { - return CArchitectureMessage(target, EArchMsgType::QuitGameplay, - std::make_shared()); - } - static CArchitectureMessage CreateControllerStatus(EArchMsgTarget target, u16 a, bool b) - { - return CArchitectureMessage(target, EArchMsgType::ControllerStatus, - std::make_shared(a, b)); - } - static const CArchMsgParmInt32& GetParmNewGameflowState(const CArchitectureMessage& msg) - { - return *msg.GetParm(); - } - static const CArchMsgParmUserInput& GetParmUserInput(const CArchitectureMessage& msg) - { - return *msg.GetParm(); - } - static CArchitectureMessage CreateUserInput(EArchMsgTarget target, const CFinalInput& input) - { - return CArchitectureMessage(target, EArchMsgType::UserInput, - std::make_shared(input)); - } - static const CArchMsgParmReal32& GetParmTimerTick(const CArchitectureMessage& msg) - { - return *msg.GetParm(); - } - static CArchitectureMessage CreateTimerTick(EArchMsgTarget target, float val) - { - return CArchitectureMessage(target, EArchMsgType::TimerTick, - std::make_shared(val)); - } - static const CArchMsgParmInt32Int32VoidPtr& GetParmChangeIOWinPriority(const CArchitectureMessage& msg) - { - return *msg.GetParm(); - } - static const CArchMsgParmInt32Int32IOWin& GetParmCreateIOWin(const CArchitectureMessage& msg) - { - return *msg.GetParm(); - } - static CArchitectureMessage CreateCreateIOWin(EArchMsgTarget target, int pmin, int pmax, - std::shared_ptr&& iowin) - { - return CArchitectureMessage(target, EArchMsgType::CreateIOWin, - std::make_shared(pmin, pmax, std::move(iowin))); - } - static const CArchMsgParmVoidPtr& GetParmDeleteIOWin(const CArchitectureMessage& msg) - { - return *msg.GetParm(); - } - static CArchitectureMessage CreateFrameBegin(EArchMsgTarget target, const s32& a) - { - return CArchitectureMessage(target, EArchMsgType::FrameBegin, - std::make_shared(a)); - } - static CArchitectureMessage CreateFrameEnd(EArchMsgTarget target, const s32& a) - { - return CArchitectureMessage(target, EArchMsgType::FrameEnd, - std::make_shared(a)); - } - /* URDE Messages */ - static CArchitectureMessage CreateRemoveAllIOWins(EArchMsgTarget target) - { - return CArchitectureMessage(target, EArchMsgType::RemoveAllIOWins, - std::make_shared()); - } + static CArchitectureMessage CreateQuitGameplay(EArchMsgTarget target) { + return CArchitectureMessage(target, EArchMsgType::QuitGameplay, std::make_shared()); + } + static CArchitectureMessage CreateControllerStatus(EArchMsgTarget target, u16 a, bool b) { + return CArchitectureMessage(target, EArchMsgType::ControllerStatus, + std::make_shared(a, b)); + } + static const CArchMsgParmInt32& GetParmNewGameflowState(const CArchitectureMessage& msg) { + return *msg.GetParm(); + } + static const CArchMsgParmUserInput& GetParmUserInput(const CArchitectureMessage& msg) { + return *msg.GetParm(); + } + static CArchitectureMessage CreateUserInput(EArchMsgTarget target, const CFinalInput& input) { + return CArchitectureMessage(target, EArchMsgType::UserInput, std::make_shared(input)); + } + static const CArchMsgParmReal32& GetParmTimerTick(const CArchitectureMessage& msg) { + return *msg.GetParm(); + } + static CArchitectureMessage CreateTimerTick(EArchMsgTarget target, float val) { + return CArchitectureMessage(target, EArchMsgType::TimerTick, std::make_shared(val)); + } + static const CArchMsgParmInt32Int32VoidPtr& GetParmChangeIOWinPriority(const CArchitectureMessage& msg) { + return *msg.GetParm(); + } + static const CArchMsgParmInt32Int32IOWin& GetParmCreateIOWin(const CArchitectureMessage& msg) { + return *msg.GetParm(); + } + static CArchitectureMessage CreateCreateIOWin(EArchMsgTarget target, int pmin, int pmax, + std::shared_ptr&& iowin) { + return CArchitectureMessage(target, EArchMsgType::CreateIOWin, + std::make_shared(pmin, pmax, std::move(iowin))); + } + static const CArchMsgParmVoidPtr& GetParmDeleteIOWin(const CArchitectureMessage& msg) { + return *msg.GetParm(); + } + static CArchitectureMessage CreateFrameBegin(EArchMsgTarget target, const s32& a) { + return CArchitectureMessage(target, EArchMsgType::FrameBegin, std::make_shared(a)); + } + static CArchitectureMessage CreateFrameEnd(EArchMsgTarget target, const s32& a) { + return CArchitectureMessage(target, EArchMsgType::FrameEnd, std::make_shared(a)); + } + /* URDE Messages */ + static CArchitectureMessage CreateRemoveAllIOWins(EArchMsgTarget target) { + return CArchitectureMessage(target, EArchMsgType::RemoveAllIOWins, std::make_shared()); + } }; -} - +} // namespace urde diff --git a/Runtime/CArchitectureQueue.hpp b/Runtime/CArchitectureQueue.hpp index 2fb70c480..bceb8c2a5 100644 --- a/Runtime/CArchitectureQueue.hpp +++ b/Runtime/CArchitectureQueue.hpp @@ -3,26 +3,20 @@ #include #include "CArchitectureMessage.hpp" -namespace urde -{ +namespace urde { + +class CArchitectureQueue { + std::list m_list; -class CArchitectureQueue -{ - std::list m_list; public: - void Push(CArchitectureMessage&& msg) - { - m_list.push_back(std::move(msg)); - } - CArchitectureMessage Pop() - { - CArchitectureMessage msg = std::move(m_list.front()); - m_list.pop_front(); - return msg; - } - void Clear() {m_list.clear();} - operator bool() {return m_list.size() != 0;} + void Push(CArchitectureMessage&& msg) { m_list.push_back(std::move(msg)); } + CArchitectureMessage Pop() { + CArchitectureMessage msg = std::move(m_list.front()); + m_list.pop_front(); + return msg; + } + void Clear() { m_list.clear(); } + operator bool() { return m_list.size() != 0; } }; -} - +} // namespace urde diff --git a/Runtime/CBasics.hpp b/Runtime/CBasics.hpp index 31b1c01cd..e001d8699 100644 --- a/Runtime/CBasics.hpp +++ b/Runtime/CBasics.hpp @@ -6,44 +6,40 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { using OSTime = s64; -struct OSCalendarTime -{ - int x0_sec; // seconds after the minute [0, 61] - int x4_min; // minutes after the hour [0, 59] - int x8_hour; // hours since midnight [0, 23] - int xc_mday; // day of the month [1, 31] - int x10_mon; // month since January [0, 11] - int x14_year; // years in AD [1, ...] - int x18_wday; // days since Sunday [0, 6] - int x1c_yday; // days since January 1 [0, 365] +struct OSCalendarTime { + int x0_sec; // seconds after the minute [0, 61] + int x4_min; // minutes after the hour [0, 59] + int x8_hour; // hours since midnight [0, 23] + int xc_mday; // day of the month [1, 31] + int x10_mon; // month since January [0, 11] + int x14_year; // years in AD [1, ...] + int x18_wday; // days since Sunday [0, 6] + int x1c_yday; // days since January 1 [0, 365] - int x20_msec; // milliseconds after the second [0,999] - int x24_usec; // microseconds after the millisecond [0,999] + int x20_msec; // milliseconds after the second [0,999] + int x24_usec; // microseconds after the millisecond [0,999] }; -class CBasics -{ +class CBasics { public: - static void Initialize(); - static const char* Stringize(const char* fmt, ...); + static void Initialize(); + static const char* Stringize(const char* fmt, ...); - static const u64 SECONDS_TO_2000; - static const u64 TICKS_PER_SECOND; + static const u64 SECONDS_TO_2000; + static const u64 TICKS_PER_SECOND; - static OSTime ToWiiTime(std::chrono::system_clock::time_point time); - static std::chrono::system_clock::time_point FromWiiTime(OSTime wiiTime); + static OSTime ToWiiTime(std::chrono::system_clock::time_point time); + static std::chrono::system_clock::time_point FromWiiTime(OSTime wiiTime); - static u64 GetGCTicks(); - static constexpr u64 GetGCTicksPerSec() { return 486000000ull; } + static u64 GetGCTicks(); + static constexpr u64 GetGCTicksPerSec() { return 486000000ull; } - static OSCalendarTime ToCalendarTime(OSTime time) { return ToCalendarTime(FromWiiTime(time)); } - static OSCalendarTime ToCalendarTime(std::chrono::system_clock::time_point time); + static OSCalendarTime ToCalendarTime(OSTime time) { return ToCalendarTime(FromWiiTime(time)); } + static OSCalendarTime ToCalendarTime(std::chrono::system_clock::time_point time); }; -} - +} // namespace urde diff --git a/Runtime/CBasicsPC.cpp b/Runtime/CBasicsPC.cpp index 8ed40ae03..750c1316f 100644 --- a/Runtime/CBasicsPC.cpp +++ b/Runtime/CBasicsPC.cpp @@ -24,48 +24,44 @@ static u64 MachToDolphinDenom; static LARGE_INTEGER PerfFrequency; #endif -namespace urde -{ +namespace urde { -void CBasics::Initialize() -{ +void CBasics::Initialize() { #if __APPLE__ - mach_timebase_info_data_t timebase; - mach_timebase_info(&timebase); - MachToDolphinNum = GetGCTicksPerSec() * timebase.numer; - MachToDolphinDenom = 1000000000ull * timebase.denom; + mach_timebase_info_data_t timebase; + mach_timebase_info(&timebase); + MachToDolphinNum = GetGCTicksPerSec() * timebase.numer; + MachToDolphinDenom = 1000000000ull * timebase.denom; #elif _WIN32 - QueryPerformanceFrequency(&PerfFrequency); + QueryPerformanceFrequency(&PerfFrequency); #endif } -const char* CBasics::Stringize(const char* fmt, ...) -{ - static char STRINGIZE_STR[2048] = {0}; - va_list ap; - va_start(ap, fmt); - vsnprintf(STRINGIZE_STR, 2048, fmt, ap); - va_end(ap); - return STRINGIZE_STR; +const char* CBasics::Stringize(const char* fmt, ...) { + static char STRINGIZE_STR[2048] = {0}; + va_list ap; + va_start(ap, fmt); + vsnprintf(STRINGIZE_STR, 2048, fmt, ap); + va_end(ap); + return STRINGIZE_STR; } -u64 CBasics::GetGCTicks() -{ +u64 CBasics::GetGCTicks() { #if __APPLE__ - return mach_absolute_time() * MachToDolphinNum / MachToDolphinDenom; + return mach_absolute_time() * MachToDolphinNum / MachToDolphinDenom; #elif __linux__ || __FreeBSD__ - struct timespec tp; - clock_gettime(CLOCK_MONOTONIC, &tp); + struct timespec tp; + clock_gettime(CLOCK_MONOTONIC, &tp); - return u64((tp.tv_sec * 1000000000ull) + tp.tv_nsec) * GetGCTicksPerSec() / 1000000000ull; + return u64((tp.tv_sec * 1000000000ull) + tp.tv_nsec) * GetGCTicksPerSec() / 1000000000ull; #elif _WIN32 - LARGE_INTEGER perf; - QueryPerformanceCounter(&perf); - perf.QuadPart *= GetGCTicksPerSec(); - perf.QuadPart /= PerfFrequency.QuadPart; - return perf.QuadPart; + LARGE_INTEGER perf; + QueryPerformanceCounter(&perf); + perf.QuadPart *= GetGCTicksPerSec(); + perf.QuadPart /= PerfFrequency.QuadPart; + return perf.QuadPart; #else - return 0; + return 0; #endif } @@ -73,88 +69,82 @@ const u64 CBasics::SECONDS_TO_2000 = 946684800LL; const u64 CBasics::TICKS_PER_SECOND = 60750000LL; #ifndef _WIN32 -static struct tm* localtime_r(const time_t& time, struct tm& timeSt, long& gmtOff) -{ - auto ret = ::localtime_r(&time, &timeSt); - if (!ret) - return nullptr; - gmtOff = ret->tm_gmtoff; - return ret; +static struct tm* localtime_r(const time_t& time, struct tm& timeSt, long& gmtOff) { + auto ret = ::localtime_r(&time, &timeSt); + if (!ret) + return nullptr; + gmtOff = ret->tm_gmtoff; + return ret; } #else -static struct tm* localtime_r(const time_t& time, struct tm& timeSt, long& gmtOff) -{ - struct tm _gmSt; - auto reta = localtime_s(&timeSt, &time); - auto retb = gmtime_s(&_gmSt, &time); - if (reta || retb) - return nullptr; - gmtOff = mktime(&timeSt) - mktime(&_gmSt); - return &timeSt; +static struct tm* localtime_r(const time_t& time, struct tm& timeSt, long& gmtOff) { + struct tm _gmSt; + auto reta = localtime_s(&timeSt, &time); + auto retb = gmtime_s(&_gmSt, &time); + if (reta || retb) + return nullptr; + gmtOff = mktime(&timeSt) - mktime(&_gmSt); + return &timeSt; } #endif -OSTime CBasics::ToWiiTime(std::chrono::system_clock::time_point time) -{ - auto sec = std::chrono::time_point_cast(time); - auto us = std::chrono::duration_cast((time - sec)).count(); - time_t sysTime = std::chrono::system_clock::to_time_t(sec); +OSTime CBasics::ToWiiTime(std::chrono::system_clock::time_point time) { + auto sec = std::chrono::time_point_cast(time); + auto us = std::chrono::duration_cast((time - sec)).count(); + time_t sysTime = std::chrono::system_clock::to_time_t(sec); - struct tm _timeSt; - long gmtOff; - struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff); - if (!timeSt) - return 0; + struct tm _timeSt; + long gmtOff; + struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff); + if (!timeSt) + return 0; - /* Returning local */ - return OSTime(TICKS_PER_SECOND * ((sysTime + gmtOff) - SECONDS_TO_2000) + - us * TICKS_PER_SECOND / 1000000); + /* Returning local */ + return OSTime(TICKS_PER_SECOND * ((sysTime + gmtOff) - SECONDS_TO_2000) + us * TICKS_PER_SECOND / 1000000); } -std::chrono::system_clock::time_point CBasics::FromWiiTime(OSTime wiiTime) -{ - auto div = std::lldiv(SECONDS_TO_2000 + wiiTime, TICKS_PER_SECOND); - time_t time = time_t(div.quot); +std::chrono::system_clock::time_point CBasics::FromWiiTime(OSTime wiiTime) { + auto div = std::lldiv(SECONDS_TO_2000 + wiiTime, TICKS_PER_SECOND); + time_t time = time_t(div.quot); - time_t sysTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); - struct tm _timeSt; - long gmtOff; - struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff); - if (!timeSt) - return std::chrono::system_clock::from_time_t(0); + time_t sysTime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + struct tm _timeSt; + long gmtOff; + struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff); + if (!timeSt) + return std::chrono::system_clock::from_time_t(0); - /* Returning GMT */ - return std::chrono::system_clock::from_time_t(time - gmtOff) + - std::chrono::microseconds(div.rem * 1000000 / TICKS_PER_SECOND); + /* Returning GMT */ + return std::chrono::system_clock::from_time_t(time - gmtOff) + + std::chrono::microseconds(div.rem * 1000000 / TICKS_PER_SECOND); } -OSCalendarTime CBasics::ToCalendarTime(std::chrono::system_clock::time_point time) -{ - OSCalendarTime ret; +OSCalendarTime CBasics::ToCalendarTime(std::chrono::system_clock::time_point time) { + OSCalendarTime ret; - auto sec = std::chrono::time_point_cast(time); - auto us = std::chrono::duration_cast((time - sec)).count(); - time_t sysTime = std::chrono::system_clock::to_time_t(sec); - struct tm _timeSt; - long gmtOff; - struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff); - if (!timeSt) - return {}; + auto sec = std::chrono::time_point_cast(time); + auto us = std::chrono::duration_cast((time - sec)).count(); + time_t sysTime = std::chrono::system_clock::to_time_t(sec); + struct tm _timeSt; + long gmtOff; + struct tm* timeSt = localtime_r(sysTime, _timeSt, gmtOff); + if (!timeSt) + return {}; - ret.x0_sec = timeSt->tm_sec; - ret.x4_min = timeSt->tm_min; - ret.x8_hour = timeSt->tm_hour; - ret.xc_mday = timeSt->tm_mday; - ret.x10_mon = timeSt->tm_mon; - ret.x14_year = timeSt->tm_year + 1900; - ret.x18_wday = timeSt->tm_wday; - ret.x1c_yday = timeSt->tm_yday; + ret.x0_sec = timeSt->tm_sec; + ret.x4_min = timeSt->tm_min; + ret.x8_hour = timeSt->tm_hour; + ret.xc_mday = timeSt->tm_mday; + ret.x10_mon = timeSt->tm_mon; + ret.x14_year = timeSt->tm_year + 1900; + ret.x18_wday = timeSt->tm_wday; + ret.x1c_yday = timeSt->tm_yday; - auto div = std::ldiv(us, 1000); - ret.x20_msec = div.quot; - ret.x24_usec = div.rem; + auto div = std::ldiv(us, 1000); + ret.x20_msec = div.quot; + ret.x24_usec = div.rem; - return ret; + return ret; } -} +} // namespace urde diff --git a/Runtime/CCRC32.cpp b/Runtime/CCRC32.cpp index caaf38be0..28952d1ca 100644 --- a/Runtime/CCRC32.cpp +++ b/Runtime/CCRC32.cpp @@ -1,65 +1,57 @@ #include "CCRC32.hpp" -namespace urde -{ +namespace urde { -const uint32_t CCRC32::crc32Table[256] = -{ - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -}; +const uint32_t CCRC32::crc32Table[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, + 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, + 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, + 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, + 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, + 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, + 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, + 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, + 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, + 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, + 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, + 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, + 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, + 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, + 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D}; -uint32_t CCRC32::Calculate(const void* data, uint32_t length) -{ - if (!data || length == 0) - return 0; +uint32_t CCRC32::Calculate(const void* data, uint32_t length) { + if (!data || length == 0) + return 0; - uint32_t checksum = 0xFFFFFFFF; - const uint8_t* buf = reinterpret_cast(data); - uint32_t words = length / 4; - while ((words--) > 0) - { - checksum = permute(checksum, *buf++); - checksum = permute(checksum, *buf++); - checksum = permute(checksum, *buf++); - checksum = permute(checksum, *buf++); - } + uint32_t checksum = 0xFFFFFFFF; + const uint8_t* buf = reinterpret_cast(data); + uint32_t words = length / 4; + while ((words--) > 0) { + checksum = permute(checksum, *buf++); + checksum = permute(checksum, *buf++); + checksum = permute(checksum, *buf++); + checksum = permute(checksum, *buf++); + } - uint32_t rem = length % 4; - while ((rem--) > 0) - checksum = permute(checksum, *buf++); + uint32_t rem = length % 4; + while ((rem--) > 0) + checksum = permute(checksum, *buf++); - return checksum; + return checksum; } -} +} // namespace urde diff --git a/Runtime/CCRC32.hpp b/Runtime/CCRC32.hpp index 1f58a743f..1bf1dcc43 100644 --- a/Runtime/CCRC32.hpp +++ b/Runtime/CCRC32.hpp @@ -1,18 +1,16 @@ #pragma once #include -namespace urde -{ +namespace urde { -class CCRC32 -{ - static const uint32_t crc32Table[256]; - static inline uint32_t permute(uint32_t checksum, uint8_t b) - { return (checksum >> 8) ^ crc32Table[(checksum & 0xFF) ^ b]; } +class CCRC32 { + static const uint32_t crc32Table[256]; + static inline uint32_t permute(uint32_t checksum, uint8_t b) { + return (checksum >> 8) ^ crc32Table[(checksum & 0xFF) ^ b]; + } public: - static uint32_t Calculate(const void* data, uint32_t length); + static uint32_t Calculate(const void* data, uint32_t length); }; -} - +} // namespace urde diff --git a/Runtime/CDependencyGroup.cpp b/Runtime/CDependencyGroup.cpp index d6ee285fc..f5b8ad9d8 100644 --- a/Runtime/CDependencyGroup.cpp +++ b/Runtime/CDependencyGroup.cpp @@ -1,25 +1,19 @@ #include "CDependencyGroup.hpp" #include "CToken.hpp" -namespace urde -{ -CDependencyGroup::CDependencyGroup(CInputStream& in) -{ - ReadFromStream(in); -} +namespace urde { +CDependencyGroup::CDependencyGroup(CInputStream& in) { ReadFromStream(in); } -void CDependencyGroup::ReadFromStream(CInputStream& in) -{ - u32 depCount = in.readUint32Big(); - x0_objectTags.reserve(depCount); - for (u32 i = 0 ; i < depCount ; i++) - x0_objectTags.emplace_back(in); +void CDependencyGroup::ReadFromStream(CInputStream& in) { + u32 depCount = in.readUint32Big(); + x0_objectTags.reserve(depCount); + for (u32 i = 0; i < depCount; i++) + x0_objectTags.emplace_back(in); } CFactoryFnReturn FDependencyGroupFactory(const SObjectTag& /*tag*/, CInputStream& in, const CVParamTransfer& /*param*/, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/CDependencyGroup.hpp b/Runtime/CDependencyGroup.hpp index 976d368eb..08e63d2b7 100644 --- a/Runtime/CDependencyGroup.hpp +++ b/Runtime/CDependencyGroup.hpp @@ -2,18 +2,16 @@ #include "CFactoryMgr.hpp" -namespace urde -{ -class CDependencyGroup -{ - std::vector x0_objectTags; +namespace urde { +class CDependencyGroup { + std::vector x0_objectTags; + public: - CDependencyGroup(CInputStream& in); - void ReadFromStream(CInputStream& in); - const std::vector& GetObjectTagVector() const { return x0_objectTags; } + CDependencyGroup(CInputStream& in); + void ReadFromStream(CInputStream& in); + const std::vector& GetObjectTagVector() const { return x0_objectTags; } }; CFactoryFnReturn FDependencyGroupFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/CDvdFile.cpp b/Runtime/CDvdFile.cpp index 5a066c485..c0a9a8282 100644 --- a/Runtime/CDvdFile.cpp +++ b/Runtime/CDvdFile.cpp @@ -2,67 +2,53 @@ #include "CDvdRequest.hpp" #include "CStopwatch.hpp" -namespace urde -{ +namespace urde { hecl::ProjectPath CDvdFile::m_DvdRoot; -class CFileDvdRequest : public IDvdRequest -{ - std::shared_ptr m_reader; - void* m_buf; - u32 m_len; - ESeekOrigin m_whence; - int m_offset; - std::atomic_bool m_cancel = {false}; - std::atomic_bool m_complete = {false}; - std::function m_callback; +class CFileDvdRequest : public IDvdRequest { + std::shared_ptr m_reader; + void* m_buf; + u32 m_len; + ESeekOrigin m_whence; + int m_offset; + std::atomic_bool m_cancel = {false}; + std::atomic_bool m_complete = {false}; + std::function m_callback; + public: - ~CFileDvdRequest() - { - PostCancelRequest(); - } + ~CFileDvdRequest() { PostCancelRequest(); } - void WaitUntilComplete() - { - while (!m_complete.load() && !m_cancel.load()) - { - std::unique_lock lk(CDvdFile::m_WaitMutex); - } - } - bool IsComplete() {return m_complete.load();} - void PostCancelRequest() - { - std::unique_lock waitlk(CDvdFile::m_WaitMutex); - m_cancel.store(true); + void WaitUntilComplete() { + while (!m_complete.load() && !m_cancel.load()) { + std::unique_lock lk(CDvdFile::m_WaitMutex); } + } + bool IsComplete() { return m_complete.load(); } + void PostCancelRequest() { + std::unique_lock waitlk(CDvdFile::m_WaitMutex); + m_cancel.store(true); + } - EMediaType GetMediaType() const - { - return EMediaType::File; - } + EMediaType GetMediaType() const { return EMediaType::File; } - CFileDvdRequest(CDvdFile& file, void* buf, u32 len, ESeekOrigin whence, int off, std::function&& cb) - : m_reader(file.m_reader), m_buf(buf), m_len(len), m_whence(whence), m_offset(off), m_callback(std::move(cb)) {} + CFileDvdRequest(CDvdFile& file, void* buf, u32 len, ESeekOrigin whence, int off, std::function&& cb) + : m_reader(file.m_reader), m_buf(buf), m_len(len), m_whence(whence), m_offset(off), m_callback(std::move(cb)) {} - void DoRequest() - { - if (m_cancel.load()) - return; - u32 readLen; - if (m_whence == ESeekOrigin::Cur && m_offset == 0) - { - readLen = m_reader->readBytesToBuf(m_buf, m_len); - } - else - { - m_reader->seek(m_offset, athena::SeekOrigin(m_whence)); - readLen = m_reader->readBytesToBuf(m_buf, m_len); - } - if (m_callback) - m_callback(readLen); - m_complete.store(true); + void DoRequest() { + if (m_cancel.load()) + return; + u32 readLen; + if (m_whence == ESeekOrigin::Cur && m_offset == 0) { + readLen = m_reader->readBytesToBuf(m_buf, m_len); + } else { + m_reader->seek(m_offset, athena::SeekOrigin(m_whence)); + readLen = m_reader->readBytesToBuf(m_buf, m_len); } + if (m_callback) + m_callback(readLen); + m_complete.store(true); + } }; std::thread CDvdFile::m_WorkerThread; @@ -71,63 +57,55 @@ std::condition_variable CDvdFile::m_WorkerCV; std::mutex CDvdFile::m_WaitMutex; std::atomic_bool CDvdFile::m_WorkerRun = {false}; std::vector> CDvdFile::m_RequestQueue; -void CDvdFile::WorkerProc() -{ - logvisor::RegisterThreadName("CDvdFile"); - while (m_WorkerRun.load()) - { - std::unique_lock lk(CDvdFile::m_WorkerMutex); - while (CDvdFile::m_RequestQueue.size()) - { - std::vector> swapQueue; - swapQueue.swap(CDvdFile::m_RequestQueue); - lk.unlock(); - std::unique_lock waitlk(CDvdFile::m_WaitMutex); - for (std::shared_ptr& req : swapQueue) - { - CFileDvdRequest& concreteReq = static_cast(*req); - concreteReq.DoRequest(); - } - waitlk.unlock(); - swapQueue.clear(); - lk.lock(); - } - if (!m_WorkerRun.load()) - break; - m_WorkerCV.wait(lk); - } -} - -std::shared_ptr CDvdFile::AsyncSeekRead(void* buf, u32 len, ESeekOrigin whence, - int off, std::function&& cb) -{ - std::shared_ptr ret = - std::make_shared(*this, buf, len, whence, off, std::move(cb)); +void CDvdFile::WorkerProc() { + logvisor::RegisterThreadName("CDvdFile"); + while (m_WorkerRun.load()) { std::unique_lock lk(CDvdFile::m_WorkerMutex); - m_RequestQueue.emplace_back(ret); - lk.unlock(); - m_WorkerCV.notify_one(); - return ret; -} - -void CDvdFile::Initialize(const hecl::ProjectPath& path) -{ - m_DvdRoot = path; - if (m_WorkerRun.load()) - return; - m_WorkerRun.store(true); - m_WorkerThread = std::thread(WorkerProc); -} - -void CDvdFile::Shutdown() -{ + while (CDvdFile::m_RequestQueue.size()) { + std::vector> swapQueue; + swapQueue.swap(CDvdFile::m_RequestQueue); + lk.unlock(); + std::unique_lock waitlk(CDvdFile::m_WaitMutex); + for (std::shared_ptr& req : swapQueue) { + CFileDvdRequest& concreteReq = static_cast(*req); + concreteReq.DoRequest(); + } + waitlk.unlock(); + swapQueue.clear(); + lk.lock(); + } if (!m_WorkerRun.load()) - return; - m_WorkerRun.store(false); - m_WorkerCV.notify_one(); - if (m_WorkerThread.joinable()) - m_WorkerThread.join(); - m_RequestQueue.clear(); + break; + m_WorkerCV.wait(lk); + } } +std::shared_ptr CDvdFile::AsyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int off, + std::function&& cb) { + std::shared_ptr ret = std::make_shared(*this, buf, len, whence, off, std::move(cb)); + std::unique_lock lk(CDvdFile::m_WorkerMutex); + m_RequestQueue.emplace_back(ret); + lk.unlock(); + m_WorkerCV.notify_one(); + return ret; } + +void CDvdFile::Initialize(const hecl::ProjectPath& path) { + m_DvdRoot = path; + if (m_WorkerRun.load()) + return; + m_WorkerRun.store(true); + m_WorkerThread = std::thread(WorkerProc); +} + +void CDvdFile::Shutdown() { + if (!m_WorkerRun.load()) + return; + m_WorkerRun.store(false); + m_WorkerCV.notify_one(); + if (m_WorkerThread.joinable()) + m_WorkerThread.join(); + m_RequestQueue.clear(); +} + +} // namespace urde diff --git a/Runtime/CDvdFile.hpp b/Runtime/CDvdFile.hpp index 748e5424c..accfbe68c 100644 --- a/Runtime/CDvdFile.hpp +++ b/Runtime/CDvdFile.hpp @@ -7,73 +7,50 @@ #include #include -namespace urde -{ +namespace urde { -enum class ESeekOrigin -{ - Begin = 0, - Cur = 1, - End = 2 -}; +enum class ESeekOrigin { Begin = 0, Cur = 1, End = 2 }; struct DVDFileInfo; class IDvdRequest; -class CDvdFile -{ - friend class CResLoader; - friend class CFileDvdRequest; - static hecl::ProjectPath m_DvdRoot; - static std::thread m_WorkerThread; - static std::mutex m_WorkerMutex; - static std::condition_variable m_WorkerCV; - static std::mutex m_WaitMutex; - static std::atomic_bool m_WorkerRun; - static std::vector> m_RequestQueue; - static void WorkerProc(); +class CDvdFile { + friend class CResLoader; + friend class CFileDvdRequest; + static hecl::ProjectPath m_DvdRoot; + static std::thread m_WorkerThread; + static std::mutex m_WorkerMutex; + static std::condition_variable m_WorkerCV; + static std::mutex m_WaitMutex; + static std::atomic_bool m_WorkerRun; + static std::vector> m_RequestQueue; + static void WorkerProc(); - std::string x18_path; - std::shared_ptr m_reader; + std::string x18_path; + std::shared_ptr m_reader; public: - static void Initialize(const hecl::ProjectPath& path); - static void Shutdown(); + static void Initialize(const hecl::ProjectPath& path); + static void Shutdown(); - CDvdFile(std::string_view path) - : x18_path(path), - m_reader(std::make_shared( - hecl::ProjectPath(m_DvdRoot, path).getAbsolutePath())) {} - operator bool() const { return m_reader->isOpen(); } - void UpdateFilePos(int pos) - { - m_reader->seek(pos, athena::SeekOrigin::Begin); - } - static bool FileExists(std::string_view path) - { - return hecl::ProjectPath(m_DvdRoot, path).isFile(); - } - void CloseFile() - { - m_reader->close(); - } - std::shared_ptr AsyncSeekRead(void* buf, u32 len, ESeekOrigin whence, - int off, std::function&& cb = {}); - u32 SyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int offset) - { - m_reader->seek(offset, athena::SeekOrigin(whence)); - return m_reader->readBytesToBuf(buf, len); - } - std::shared_ptr AsyncRead(void* buf, u32 len, std::function&& cb = {}) - { - return AsyncSeekRead(buf, len, ESeekOrigin::Cur, 0, std::move(cb)); - } - u32 SyncRead(void* buf, u32 len) - { - return m_reader->readBytesToBuf(buf, len); - } - u64 Length() {return m_reader->length();} - std::string_view GetPath() const { return x18_path; } + CDvdFile(std::string_view path) + : x18_path(path) + , m_reader(std::make_shared(hecl::ProjectPath(m_DvdRoot, path).getAbsolutePath())) {} + operator bool() const { return m_reader->isOpen(); } + void UpdateFilePos(int pos) { m_reader->seek(pos, athena::SeekOrigin::Begin); } + static bool FileExists(std::string_view path) { return hecl::ProjectPath(m_DvdRoot, path).isFile(); } + void CloseFile() { m_reader->close(); } + std::shared_ptr AsyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int off, + std::function&& cb = {}); + u32 SyncSeekRead(void* buf, u32 len, ESeekOrigin whence, int offset) { + m_reader->seek(offset, athena::SeekOrigin(whence)); + return m_reader->readBytesToBuf(buf, len); + } + std::shared_ptr AsyncRead(void* buf, u32 len, std::function&& cb = {}) { + return AsyncSeekRead(buf, len, ESeekOrigin::Cur, 0, std::move(cb)); + } + u32 SyncRead(void* buf, u32 len) { return m_reader->readBytesToBuf(buf, len); } + u64 Length() { return m_reader->length(); } + std::string_view GetPath() const { return x18_path; } }; -} - +} // namespace urde diff --git a/Runtime/CDvdRequest.hpp b/Runtime/CDvdRequest.hpp index 728bc428a..6b34d5373 100644 --- a/Runtime/CDvdRequest.hpp +++ b/Runtime/CDvdRequest.hpp @@ -1,26 +1,17 @@ #pragma once -namespace urde -{ +namespace urde { -class IDvdRequest -{ +class IDvdRequest { public: - virtual ~IDvdRequest() = default; + virtual ~IDvdRequest() = default; - virtual void WaitUntilComplete()=0; - virtual bool IsComplete()=0; - virtual void PostCancelRequest()=0; + virtual void WaitUntilComplete() = 0; + virtual bool IsComplete() = 0; + virtual void PostCancelRequest() = 0; - enum class EMediaType - { - ARAM = 0, - Real = 1, - File = 2, - NOD = 3 - }; - virtual EMediaType GetMediaType() const=0; + enum class EMediaType { ARAM = 0, Real = 1, File = 2, NOD = 3 }; + virtual EMediaType GetMediaType() const = 0; }; -} - +} // namespace urde diff --git a/Runtime/CFactoryMgr.cpp b/Runtime/CFactoryMgr.cpp index c6b20c60f..344318605 100644 --- a/Runtime/CFactoryMgr.cpp +++ b/Runtime/CFactoryMgr.cpp @@ -2,95 +2,73 @@ #include "IObj.hpp" #include "CStopwatch.hpp" -namespace urde -{ +namespace urde { CFactoryFnReturn CFactoryMgr::MakeObject(const SObjectTag& tag, urde::CInputStream& in, - const CVParamTransfer& paramXfer, CObjectReference* selfRef) -{ - auto search = m_factories.find(tag.type); - if (search == m_factories.end()) - return {}; + const CVParamTransfer& paramXfer, CObjectReference* selfRef) { + auto search = m_factories.find(tag.type); + if (search == m_factories.end()) + return {}; - return search->second(tag, in, paramXfer, selfRef); + return search->second(tag, in, paramXfer, selfRef); } -bool CFactoryMgr::CanMakeMemory(const urde::SObjectTag& tag) const -{ - auto search = m_memFactories.find(tag.type); - return search != m_memFactories.cend(); +bool CFactoryMgr::CanMakeMemory(const urde::SObjectTag& tag) const { + auto search = m_memFactories.find(tag.type); + return search != m_memFactories.cend(); } CFactoryFnReturn CFactoryMgr::MakeObjectFromMemory(const SObjectTag& tag, std::unique_ptr&& buf, int size, bool compressed, const CVParamTransfer& paramXfer, - CObjectReference* selfRef) -{ - std::unique_ptr localBuf = std::move(buf); + CObjectReference* selfRef) { + std::unique_ptr localBuf = std::move(buf); - auto search = m_memFactories.find(tag.type); - if (search != m_memFactories.cend()) - { - if (compressed) - { - std::unique_ptr compRead = - std::make_unique(localBuf.get(), size); - u32 decompLen = compRead->readUint32Big(); - CZipInputStream r(std::move(compRead)); - std::unique_ptr decompBuf = r.readUBytes(decompLen); - return search->second(tag, std::move(decompBuf), decompLen, paramXfer, selfRef); - } - else - { - return search->second(tag, std::move(localBuf), size, paramXfer, selfRef); - } + auto search = m_memFactories.find(tag.type); + if (search != m_memFactories.cend()) { + if (compressed) { + std::unique_ptr compRead = std::make_unique(localBuf.get(), size); + u32 decompLen = compRead->readUint32Big(); + CZipInputStream r(std::move(compRead)); + std::unique_ptr decompBuf = r.readUBytes(decompLen); + return search->second(tag, std::move(decompBuf), decompLen, paramXfer, selfRef); + } else { + return search->second(tag, std::move(localBuf), size, paramXfer, selfRef); } - else - { - auto search = m_factories.find(tag.type); - if (search == m_factories.end()) - return {}; + } else { + auto search = m_factories.find(tag.type); + if (search == m_factories.end()) + return {}; - if (compressed) - { - std::unique_ptr compRead = - std::make_unique(localBuf.get(), size); - compRead->readUint32Big(); - CZipInputStream r(std::move(compRead)); - return search->second(tag, r, paramXfer, selfRef); - } - else - { - CMemoryInStream r(localBuf.get(), size); - return search->second(tag, r, paramXfer, selfRef); - } + if (compressed) { + std::unique_ptr compRead = std::make_unique(localBuf.get(), size); + compRead->readUint32Big(); + CZipInputStream r(std::move(compRead)); + return search->second(tag, r, paramXfer, selfRef); + } else { + CMemoryInStream r(localBuf.get(), size); + return search->second(tag, r, paramXfer, selfRef); } + } } -static const FourCC TypeTable[] = -{ - FOURCC('CLSN'), FOURCC('CMDL'), FOURCC('CSKR'), FOURCC('ANIM'), FOURCC('CINF'), FOURCC('TXTR'), - FOURCC('PLTT'), FOURCC('FONT'), FOURCC('ANCS'), FOURCC('EVNT'), FOURCC('MADF'), FOURCC('MLVL'), - FOURCC('MREA'), FOURCC('MAPW'), FOURCC('MAPA'), FOURCC('SAVW'), FOURCC('SAVA'), FOURCC('PART'), - FOURCC('WPSC'), FOURCC('SWHC'), FOURCC('DPSC'), FOURCC('ELSC'), FOURCC('CRSC'), FOURCC('AFSM'), - FOURCC('DCLN'), FOURCC('AGSC'), FOURCC('ATBL'), FOURCC('CSNG'), FOURCC('STRG'), FOURCC('SCAN'), - FOURCC('PATH'), FOURCC('DGRP'), FOURCC('HMAP'), FOURCC('CTWK'), FOURCC('FRME'), FOURCC('HINT'), - FOURCC('MAPU'), FOURCC('DUMB'), FOURCC('OIDS') -}; +static const FourCC TypeTable[] = { + FOURCC('CLSN'), FOURCC('CMDL'), FOURCC('CSKR'), FOURCC('ANIM'), FOURCC('CINF'), FOURCC('TXTR'), FOURCC('PLTT'), + FOURCC('FONT'), FOURCC('ANCS'), FOURCC('EVNT'), FOURCC('MADF'), FOURCC('MLVL'), FOURCC('MREA'), FOURCC('MAPW'), + FOURCC('MAPA'), FOURCC('SAVW'), FOURCC('SAVA'), FOURCC('PART'), FOURCC('WPSC'), FOURCC('SWHC'), FOURCC('DPSC'), + FOURCC('ELSC'), FOURCC('CRSC'), FOURCC('AFSM'), FOURCC('DCLN'), FOURCC('AGSC'), FOURCC('ATBL'), FOURCC('CSNG'), + FOURCC('STRG'), FOURCC('SCAN'), FOURCC('PATH'), FOURCC('DGRP'), FOURCC('HMAP'), FOURCC('CTWK'), FOURCC('FRME'), + FOURCC('HINT'), FOURCC('MAPU'), FOURCC('DUMB'), FOURCC('OIDS')}; -CFactoryMgr::ETypeTable CFactoryMgr::FourCCToTypeIdx(FourCC fcc) -{ - for (int i=0 ; i<4 ; ++i) - fcc.getChars()[i] = char(toupper(fcc.getChars()[i])); - auto search = std::find_if(std::begin(TypeTable), std::end(TypeTable), - [fcc](const FourCC& test) { return test == fcc; }); - if (search == std::end(TypeTable)) - return ETypeTable::Invalid; - return ETypeTable(search - std::begin(TypeTable)); +CFactoryMgr::ETypeTable CFactoryMgr::FourCCToTypeIdx(FourCC fcc) { + for (int i = 0; i < 4; ++i) + fcc.getChars()[i] = char(toupper(fcc.getChars()[i])); + auto search = + std::find_if(std::begin(TypeTable), std::end(TypeTable), [fcc](const FourCC& test) { return test == fcc; }); + if (search == std::end(TypeTable)) + return ETypeTable::Invalid; + return ETypeTable(search - std::begin(TypeTable)); } -FourCC CFactoryMgr::TypeIdxToFourCC(ETypeTable fcc) -{ - return TypeTable[int(fcc)]; -} +FourCC CFactoryMgr::TypeIdxToFourCC(ETypeTable fcc) { return TypeTable[int(fcc)]; } -} +} // namespace urde diff --git a/Runtime/CFactoryMgr.hpp b/Runtime/CFactoryMgr.hpp index 555b1454f..ec29fd9b2 100644 --- a/Runtime/CFactoryMgr.hpp +++ b/Runtime/CFactoryMgr.hpp @@ -5,43 +5,69 @@ #include "IOStreams.hpp" #include "IFactory.hpp" -namespace urde -{ +namespace urde { struct SObjectTag; class CVParamTransfer; class IObj; -class CFactoryMgr -{ - std::unordered_map m_factories; - std::unordered_map m_memFactories; +class CFactoryMgr { + std::unordered_map m_factories; + std::unordered_map m_memFactories; + public: - CFactoryFnReturn MakeObject(const SObjectTag& tag, urde::CInputStream& in, - const CVParamTransfer& paramXfer, CObjectReference* selfRef); - bool CanMakeMemory(const urde::SObjectTag& tag) const; - CFactoryFnReturn MakeObjectFromMemory(const SObjectTag& tag, - std::unique_ptr&& buf, - int size, bool compressed, - const CVParamTransfer& paramXfer, - CObjectReference* selfRef); - void AddFactory(FourCC key, FFactoryFunc func) {m_factories[key] = func;} - void AddFactory(FourCC key, FMemFactoryFunc func) {m_memFactories[key] = func;} + CFactoryFnReturn MakeObject(const SObjectTag& tag, urde::CInputStream& in, const CVParamTransfer& paramXfer, + CObjectReference* selfRef); + bool CanMakeMemory(const urde::SObjectTag& tag) const; + CFactoryFnReturn MakeObjectFromMemory(const SObjectTag& tag, std::unique_ptr&& buf, int size, bool compressed, + const CVParamTransfer& paramXfer, CObjectReference* selfRef); + void AddFactory(FourCC key, FFactoryFunc func) { m_factories[key] = func; } + void AddFactory(FourCC key, FMemFactoryFunc func) { m_memFactories[key] = func; } - enum class ETypeTable : u8 - { - CLSN, CMDL, CSKR, ANIM, CINF, TXTR, - PLTT, FONT, ANCS, EVNT, MADF, MLVL, - MREA, MAPW, MAPA, SAVW, SAVA, PART, - WPSC, SWHC, DPSC, ELSC, CRSC, AFSM, - DCLN, AGSC, ATBL, CSNG, STRG, SCAN, - PATH, DGRP, HMAP, CTWK, FRME, HINT, - MAPU, DUMB, OIDS, - Invalid = 127 - }; + enum class ETypeTable : u8 { + CLSN, + CMDL, + CSKR, + ANIM, + CINF, + TXTR, + PLTT, + FONT, + ANCS, + EVNT, + MADF, + MLVL, + MREA, + MAPW, + MAPA, + SAVW, + SAVA, + PART, + WPSC, + SWHC, + DPSC, + ELSC, + CRSC, + AFSM, + DCLN, + AGSC, + ATBL, + CSNG, + STRG, + SCAN, + PATH, + DGRP, + HMAP, + CTWK, + FRME, + HINT, + MAPU, + DUMB, + OIDS, + Invalid = 127 + }; - static ETypeTable FourCCToTypeIdx(FourCC fcc); - static FourCC TypeIdxToFourCC(ETypeTable fcc); + static ETypeTable FourCCToTypeIdx(FourCC fcc); + static FourCC TypeIdxToFourCC(ETypeTable fcc); }; -} - +} // namespace urde diff --git a/Runtime/CGameAllocator.cpp b/Runtime/CGameAllocator.cpp index 38a542a77..1e3de19ec 100644 --- a/Runtime/CGameAllocator.cpp +++ b/Runtime/CGameAllocator.cpp @@ -1,61 +1,55 @@ #include "CGameAllocator.hpp" -namespace urde -{ +namespace urde { logvisor::Module AllocLog("urde::CGameAllocator"); std::vector CGameAllocator::m_allocations; -u8* CGameAllocator::Alloc(size_t len) -{ - size_t roundedLen = ROUND_UP_64(len + sizeof(SChunkDescription)); - for (SAllocationDescription& alloc : m_allocations) - { - /* We need to supply enough room for allocation information */ - if (alloc.freeOffset + roundedLen < alloc.allocSize) - { - u8* ptr = alloc.memptr.get() + alloc.freeOffset; - SChunkDescription* chunkInfo = reinterpret_cast(ptr); - *chunkInfo = SChunkDescription(); - chunkInfo->parent = &alloc; - chunkInfo->len = len; - alloc.freeOffset += roundedLen; - return ptr + sizeof(SChunkDescription); - } +u8* CGameAllocator::Alloc(size_t len) { + size_t roundedLen = ROUND_UP_64(len + sizeof(SChunkDescription)); + for (SAllocationDescription& alloc : m_allocations) { + /* We need to supply enough room for allocation information */ + if (alloc.freeOffset + roundedLen < alloc.allocSize) { + u8* ptr = alloc.memptr.get() + alloc.freeOffset; + SChunkDescription* chunkInfo = reinterpret_cast(ptr); + *chunkInfo = SChunkDescription(); + chunkInfo->parent = &alloc; + chunkInfo->len = len; + alloc.freeOffset += roundedLen; + return ptr + sizeof(SChunkDescription); } + } - /* 1MiB minimum allocation to prevent constantly allocating small amounts of memory */ - size_t allocSz = len; - if (allocSz < (1 * 1024 * 1024 * 1024)) - allocSz = 1 * 1024 * 1024 * 1024; + /* 1MiB minimum allocation to prevent constantly allocating small amounts of memory */ + size_t allocSz = len; + if (allocSz < (1 * 1024 * 1024 * 1024)) + allocSz = 1 * 1024 * 1024 * 1024; - /* Pad size to allow for allocation information */ - allocSz = ROUND_UP_64(allocSz + sizeof(SChunkDescription)); - m_allocations.emplace_back(); - m_allocations.back().memptr.reset(new u8[allocSz]); - u8* ptr = m_allocations.back().memptr.get(); - m_allocations.back().allocSize = allocSz; - m_allocations.back().freeOffset += roundedLen; - SChunkDescription* chunkInfo = reinterpret_cast(ptr); - *chunkInfo = SChunkDescription(); - chunkInfo->parent = &m_allocations.back(); - chunkInfo->len = len; - return ptr + sizeof(SChunkDescription); + /* Pad size to allow for allocation information */ + allocSz = ROUND_UP_64(allocSz + sizeof(SChunkDescription)); + m_allocations.emplace_back(); + m_allocations.back().memptr.reset(new u8[allocSz]); + u8* ptr = m_allocations.back().memptr.get(); + m_allocations.back().allocSize = allocSz; + m_allocations.back().freeOffset += roundedLen; + SChunkDescription* chunkInfo = reinterpret_cast(ptr); + *chunkInfo = SChunkDescription(); + chunkInfo->parent = &m_allocations.back(); + chunkInfo->len = len; + return ptr + sizeof(SChunkDescription); } -void CGameAllocator::Free(u8* ptr) -{ - SChunkDescription* info = reinterpret_cast(ptr - sizeof(SChunkDescription)); - if (info->magic != 0xE8E8E8E8 || info->sentinal != 0xEFEFEFEF) - { - AllocLog.report(logvisor::Fatal, _SYS_STR("Invalid chunk description, memory corruption!")); - return; - } +void CGameAllocator::Free(u8* ptr) { + SChunkDescription* info = reinterpret_cast(ptr - sizeof(SChunkDescription)); + if (info->magic != 0xE8E8E8E8 || info->sentinal != 0xEFEFEFEF) { + AllocLog.report(logvisor::Fatal, _SYS_STR("Invalid chunk description, memory corruption!")); + return; + } - SAllocationDescription& alloc = *info->parent; - size_t roundedLen = ROUND_UP_32(info->len + sizeof(SChunkDescription)); - alloc.freeOffset -= roundedLen; - /* Invalidate chunk allocation descriptor */ - memset(info, 0, ROUND_UP_64(info->len + sizeof(SChunkDescription))); -} + SAllocationDescription& alloc = *info->parent; + size_t roundedLen = ROUND_UP_32(info->len + sizeof(SChunkDescription)); + alloc.freeOffset -= roundedLen; + /* Invalidate chunk allocation descriptor */ + memset(info, 0, ROUND_UP_64(info->len + sizeof(SChunkDescription))); } +} // namespace urde diff --git a/Runtime/CGameAllocator.hpp b/Runtime/CGameAllocator.hpp index d52f58e48..46bcfaabf 100644 --- a/Runtime/CGameAllocator.hpp +++ b/Runtime/CGameAllocator.hpp @@ -2,31 +2,25 @@ #include "RetroTypes.hpp" -namespace urde -{ -class CGameAllocator -{ - struct SAllocationDescription - { - std::unique_ptr memptr; - size_t allocSize = 0; - ptrdiff_t freeOffset = 0; - }; +namespace urde { +class CGameAllocator { + struct SAllocationDescription { + std::unique_ptr memptr; + size_t allocSize = 0; + ptrdiff_t freeOffset = 0; + }; - struct SChunkDescription - { - u32 magic = 0xE8E8E8E8; - SAllocationDescription* parent; - size_t len = 0; - u32 sentinal = 0xEFEFEFEF; - }; + struct SChunkDescription { + u32 magic = 0xE8E8E8E8; + SAllocationDescription* parent; + size_t len = 0; + u32 sentinal = 0xEFEFEFEF; + }; - static std::vector m_allocations; + static std::vector m_allocations; public: - - static u8* Alloc(size_t len); - static void Free(u8* ptr); + static u8* Alloc(size_t len); + static void Free(u8* ptr); }; -} - +} // namespace urde diff --git a/Runtime/CGameDebug.hpp b/Runtime/CGameDebug.hpp index 7afbf892d..0a94ffbfa 100644 --- a/Runtime/CGameDebug.hpp +++ b/Runtime/CGameDebug.hpp @@ -2,53 +2,41 @@ #include -namespace urde -{ +namespace urde { struct CFinalInput; const char* StringForControlOption(int); -enum class EDebugMenu -{ -}; +enum class EDebugMenu {}; -enum class EDebugOptions -{ -}; +enum class EDebugOptions {}; -enum class EDebugMainMenu -{ -}; +enum class EDebugMainMenu {}; -class CDebugOption -{ +class CDebugOption { public: - CDebugOption(EDebugMenu, EDebugOptions, const std::string&, bool); - CDebugOption(EDebugMenu, EDebugOptions, const std::string&, float, float, float, float); + CDebugOption(EDebugMenu, EDebugOptions, const std::string&, bool); + CDebugOption(EDebugMenu, EDebugOptions, const std::string&, float, float, float, float); }; -class CGameDebug -{ +class CGameDebug { public: - enum class EReturnValue - { - }; + enum class EReturnValue {}; - void DeactivateMenu(); - void AddDebugOption(EDebugMenu, EDebugOptions, const char*, bool); - void AddDebugOption(EDebugMenu, EDebugOptions, const char*, float, float, float, float); - void SetCaptureMovieTimeLeft(float); - const std::string& GetCaptureMovieName(); - void SetCaptureMovieName(const std::string&); - void AddDebugOptions(); - void CopyDebugToTweaks(); - void CopyTweaksToDebug(); - void ProcessControllerInput(const CFinalInput&); - void Update(float); - void Draw(void) const; - void ActivateMenu(EDebugMainMenu, int); - void AddDebugOption(const CDebugOption&); + void DeactivateMenu(); + void AddDebugOption(EDebugMenu, EDebugOptions, const char*, bool); + void AddDebugOption(EDebugMenu, EDebugOptions, const char*, float, float, float, float); + void SetCaptureMovieTimeLeft(float); + const std::string& GetCaptureMovieName(); + void SetCaptureMovieName(const std::string&); + void AddDebugOptions(); + void CopyDebugToTweaks(); + void CopyTweaksToDebug(); + void ProcessControllerInput(const CFinalInput&); + void Update(float); + void Draw(void) const; + void ActivateMenu(EDebugMainMenu, int); + void AddDebugOption(const CDebugOption&); }; -} - +} // namespace urde diff --git a/Runtime/CGameHintInfo.cpp b/Runtime/CGameHintInfo.cpp index 0400b93b2..ad0f3c917 100644 --- a/Runtime/CGameHintInfo.cpp +++ b/Runtime/CGameHintInfo.cpp @@ -3,15 +3,13 @@ #include "CMemoryCardSys.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { -CGameHintInfo::CGameHintInfo(CInputStream& in, s32 version) -{ - u32 hintCount = in.readUint32Big(); - x0_hints.reserve(hintCount); - for (u32 i = 0; i < hintCount; ++i) - x0_hints.emplace_back(in, version); +CGameHintInfo::CGameHintInfo(CInputStream& in, s32 version) { + u32 hintCount = in.readUint32Big(); + x0_hints.reserve(hintCount); + for (u32 i = 0; i < hintCount; ++i) + x0_hints.emplace_back(in, version); } CGameHintInfo::CGameHint::CGameHint(CInputStream& in, s32 version) @@ -19,37 +17,31 @@ CGameHintInfo::CGameHint::CGameHint(CInputStream& in, s32 version) , x10_immediateTime(in.readFloatBig()) , x14_normalTime(in.readFloatBig()) , x18_stringId(in.readUint32Big()) -, x1c_textTime(3.f * float(version <= 0 ? 1 : in.readUint32Big())) -{ - u32 locationCount = in.readUint32Big(); - x20_locations.reserve(locationCount); - for (u32 i = 0; i < locationCount; ++i) - x20_locations.emplace_back(in, version); +, x1c_textTime(3.f * float(version <= 0 ? 1 : in.readUint32Big())) { + u32 locationCount = in.readUint32Big(); + x20_locations.reserve(locationCount); + for (u32 i = 0; i < locationCount; ++i) + x20_locations.emplace_back(in, version); } CGameHintInfo::SHintLocation::SHintLocation(CInputStream& in, s32) : x0_mlvlId(in.readUint32Big()) , x4_mreaId(in.readUint32Big()) , x8_areaId(in.readUint32Big()) -, xc_stringId(in.readUint32Big()) -{ +, xc_stringId(in.readUint32Big()) {} + +int CGameHintInfo::FindHintIndex(const char* str) { + const std::vector& gameHints = g_MemoryCardSys->GetHints(); + const auto& it = std::find_if(gameHints.begin(), gameHints.end(), + [&str](const CGameHint& gh) -> bool { return !gh.GetName().compare(str); }); + + return (it != gameHints.end() ? it - gameHints.begin() : -1); } -int CGameHintInfo::FindHintIndex(const char* str) -{ - const std::vector& gameHints = g_MemoryCardSys->GetHints(); - const auto& it = std::find_if(gameHints.begin(), gameHints.end(), [&str](const CGameHint& gh) -> bool { - return !gh.GetName().compare(str); - }); +CFactoryFnReturn FHintFactory(const SObjectTag&, CInputStream& in, const CVParamTransfer, CObjectReference*) { + in.readUint32Big(); + s32 version = in.readInt32Big(); - return (it != gameHints.end() ? it - gameHints.begin() : -1); -} - -CFactoryFnReturn FHintFactory(const SObjectTag&, CInputStream& in, const CVParamTransfer, CObjectReference*) -{ - in.readUint32Big(); - s32 version = in.readInt32Big(); - - return TToken::GetIObjObjectFor(std::make_unique(in, version)); -} + return TToken::GetIObjObjectFor(std::make_unique(in, version)); } +} // namespace urde diff --git a/Runtime/CGameHintInfo.hpp b/Runtime/CGameHintInfo.hpp index 571b49c5b..9cfca51a7 100644 --- a/Runtime/CGameHintInfo.hpp +++ b/Runtime/CGameHintInfo.hpp @@ -3,46 +3,44 @@ #include "RetroTypes.hpp" #include "IFactory.hpp" -namespace urde -{ -class CGameHintInfo -{ +namespace urde { +class CGameHintInfo { public: - struct SHintLocation - { - CAssetId x0_mlvlId; - CAssetId x4_mreaId; - TAreaId x8_areaId = kInvalidAreaId; - CAssetId xc_stringId; - SHintLocation(CInputStream&, s32); - }; + struct SHintLocation { + CAssetId x0_mlvlId; + CAssetId x4_mreaId; + TAreaId x8_areaId = kInvalidAreaId; + CAssetId xc_stringId; + SHintLocation(CInputStream&, s32); + }; - class CGameHint - { - std::string x0_name; - float x10_immediateTime; - float x14_normalTime; - CAssetId x18_stringId; - float x1c_textTime; - std::vector x20_locations; - public: - CGameHint(CInputStream&, s32); + class CGameHint { + std::string x0_name; + float x10_immediateTime; + float x14_normalTime; + CAssetId x18_stringId; + float x1c_textTime; + std::vector x20_locations; - float GetNormalTime() const { return x14_normalTime; } - float GetImmediateTime() const { return x10_immediateTime; } - float GetTextTime() const { return x1c_textTime; } - std::string_view GetName() const { return x0_name; } - CAssetId GetStringID() const { return x18_stringId; } - const std::vector& GetLocations() const { return x20_locations; } - }; + public: + CGameHint(CInputStream&, s32); + + float GetNormalTime() const { return x14_normalTime; } + float GetImmediateTime() const { return x10_immediateTime; } + float GetTextTime() const { return x1c_textTime; } + std::string_view GetName() const { return x0_name; } + CAssetId GetStringID() const { return x18_stringId; } + const std::vector& GetLocations() const { return x20_locations; } + }; private: - std::vector x0_hints; + std::vector x0_hints; + public: - CGameHintInfo(CInputStream&, s32); - const std::vector& GetHints() const { return x0_hints; } - static int FindHintIndex(const char* str); + CGameHintInfo(CInputStream&, s32); + const std::vector& GetHints() const { return x0_hints; } + static int FindHintIndex(const char* str); }; CFactoryFnReturn FHintFactory(const SObjectTag&, CInputStream&, const CVParamTransfer, CObjectReference*); -} +} // namespace urde diff --git a/Runtime/CGameOptions.cpp b/Runtime/CGameOptions.cpp index d42ed6ff7..830583318 100644 --- a/Runtime/CGameOptions.cpp +++ b/Runtime/CGameOptions.cpp @@ -13,766 +13,654 @@ #include "CStateManager.hpp" #include "hecl/CVarManager.hpp" -namespace urde -{ +namespace urde { -static const SGameOption VisorOpts[] = -{ +static const SGameOption VisorOpts[] = { {EGameOption::VisorOpacity, 21, 0.f, 255.f, 1.f, EOptionType::Float}, {EGameOption::HelmetOpacity, 22, 0.f, 255.f, 1.f, EOptionType::Float}, {EGameOption::HUDLag, 23, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, {EGameOption::HintSystem, 24, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, - {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults} -}; + {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults}}; -static const SGameOption DisplayOpts[] = -{ +static const SGameOption DisplayOpts[] = { //{EGameOption::ScreenBrightness, 25, 0.f, 8.f, 1.f, EOptionType::Float}, {EGameOption::ScreenBrightness, 25, -100.f, 100.f, 1.f, EOptionType::Float}, {EGameOption::ScreenOffsetX, 26, -30.f, 30.f, 1.f, EOptionType::Float}, {EGameOption::ScreenOffsetY, 27, -30.f, 30.f, 1.f, EOptionType::Float}, {EGameOption::ScreenStretch, 28, -10.f, 10.f, 1.f, EOptionType::Float}, - {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults} -}; + {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults}}; -static const SGameOption SoundOpts[] = -{ +static const SGameOption SoundOpts[] = { {EGameOption::SFXVolume, 29, 0.f, 127.f, 1.f, EOptionType::Float}, {EGameOption::MusicVolume, 30, 0.f, 127.f, 1.f, EOptionType::Float}, {EGameOption::SoundMode, 31, 0.f, 1.f, 1.f, EOptionType::TripleEnum}, - {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults} -}; + {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults}}; -static const SGameOption ControllerOpts[] = -{ +static const SGameOption ControllerOpts[] = { {EGameOption::ReverseYAxis, 32, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, {EGameOption::Rumble, 33, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, {EGameOption::SwapBeamControls, 34, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, - {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults} -}; + {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults}}; -const std::pair GameOptionsRegistry[] = -{ - {5, VisorOpts}, - {5, DisplayOpts}, - {4, SoundOpts}, - {4, ControllerOpts}, - {0, nullptr} -}; +const std::pair GameOptionsRegistry[] = { + {5, VisorOpts}, {5, DisplayOpts}, {4, SoundOpts}, {4, ControllerOpts}, {0, nullptr}}; -CPersistentOptions::CPersistentOptions(CBitStreamReader& stream) -{ - for (int b=0 ; b<98 ; ++b) - x0_nesState[b] = stream.ReadEncoded(8); +CPersistentOptions::CPersistentOptions(CBitStreamReader& stream) { + for (int b = 0; b < 98; ++b) + x0_nesState[b] = stream.ReadEncoded(8); - for (int b=0 ; b<64 ; ++b) - x68_[b] = stream.ReadEncoded(8); + for (int b = 0; b < 64; ++b) + x68_[b] = stream.ReadEncoded(8); - xc0_frozenFpsCount = stream.ReadEncoded(2); - xc4_frozenBallCount = stream.ReadEncoded(2); - xc8_powerBombAmmoCount = stream.ReadEncoded(1); - xcc_logScanPercent = stream.ReadEncoded(7); - xd0_24_fusionLinked = stream.ReadEncoded(1); - xd0_25_normalModeBeat = stream.ReadEncoded(1); - xd0_26_hardModeBeat = stream.ReadEncoded(1); - xd0_27_fusionBeat = stream.ReadEncoded(1); - xd0_28_fusionSuitActive = false; - xd0_29_allItemsCollected = stream.ReadEncoded(1); - xbc_autoMapperKeyState = stream.ReadEncoded(2); + xc0_frozenFpsCount = stream.ReadEncoded(2); + xc4_frozenBallCount = stream.ReadEncoded(2); + xc8_powerBombAmmoCount = stream.ReadEncoded(1); + xcc_logScanPercent = stream.ReadEncoded(7); + xd0_24_fusionLinked = stream.ReadEncoded(1); + xd0_25_normalModeBeat = stream.ReadEncoded(1); + xd0_26_hardModeBeat = stream.ReadEncoded(1); + xd0_27_fusionBeat = stream.ReadEncoded(1); + xd0_28_fusionSuitActive = false; + xd0_29_allItemsCollected = stream.ReadEncoded(1); + xbc_autoMapperKeyState = stream.ReadEncoded(2); - auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); - size_t cinematicCount = 0; - for (const auto& world : memWorlds) - { - TLockedToken saveWorld = - g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.second.GetSaveWorldAssetId()}); - cinematicCount += saveWorld->GetCinematicCount(); - } + auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); + size_t cinematicCount = 0; + for (const auto& world : memWorlds) { + TLockedToken saveWorld = + g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.second.GetSaveWorldAssetId()}); + cinematicCount += saveWorld->GetCinematicCount(); + } - std::vector cinematicStates; - cinematicStates.reserve(cinematicCount); - for (size_t i=0 ; i cinematicStates; + cinematicStates.reserve(cinematicCount); + for (size_t i = 0; i < cinematicCount; ++i) + cinematicStates.push_back(stream.ReadEncoded(1)); - for (const auto& world : memWorlds) - { - TLockedToken saveWorld = - g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.second.GetSaveWorldAssetId()}); + for (const auto& world : memWorlds) { + TLockedToken saveWorld = + g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.second.GetSaveWorldAssetId()}); - auto stateIt = cinematicStates.cbegin(); - for (TEditorId cineId : saveWorld->GetCinematics()) - if (*stateIt++) - SetCinematicState(world.first, cineId, true); - } + auto stateIt = cinematicStates.cbegin(); + for (TEditorId cineId : saveWorld->GetCinematics()) + if (*stateIt++) + SetCinematicState(world.first, cineId, true); + } } -void CPersistentOptions::PutTo(CBitStreamWriter& w) const -{ - for (int b=0 ; b<98 ; ++b) - w.WriteEncoded(x0_nesState[b], 8); +void CPersistentOptions::PutTo(CBitStreamWriter& w) const { + for (int b = 0; b < 98; ++b) + w.WriteEncoded(x0_nesState[b], 8); - for (int b=0 ; b<64 ; ++b) - w.WriteEncoded(x68_[b], 8); + for (int b = 0; b < 64; ++b) + w.WriteEncoded(x68_[b], 8); - w.WriteEncoded(xc0_frozenFpsCount, 2); - w.WriteEncoded(xc4_frozenBallCount, 2); - w.WriteEncoded(xc8_powerBombAmmoCount, 1); - w.WriteEncoded(xcc_logScanPercent, 7); - w.WriteEncoded(xd0_24_fusionLinked, 1); - w.WriteEncoded(xd0_25_normalModeBeat, 1); - w.WriteEncoded(xd0_26_hardModeBeat, 1); - w.WriteEncoded(xd0_27_fusionBeat, 1); - w.WriteEncoded(xd0_29_allItemsCollected, 1); - w.WriteEncoded(xbc_autoMapperKeyState, 2); + w.WriteEncoded(xc0_frozenFpsCount, 2); + w.WriteEncoded(xc4_frozenBallCount, 2); + w.WriteEncoded(xc8_powerBombAmmoCount, 1); + w.WriteEncoded(xcc_logScanPercent, 7); + w.WriteEncoded(xd0_24_fusionLinked, 1); + w.WriteEncoded(xd0_25_normalModeBeat, 1); + w.WriteEncoded(xd0_26_hardModeBeat, 1); + w.WriteEncoded(xd0_27_fusionBeat, 1); + w.WriteEncoded(xd0_29_allItemsCollected, 1); + w.WriteEncoded(xbc_autoMapperKeyState, 2); - auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); - for (const auto& world : memWorlds) - { - TLockedToken saveWorld = - g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.second.GetSaveWorldAssetId()}); + auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); + for (const auto& world : memWorlds) { + TLockedToken saveWorld = + g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.second.GetSaveWorldAssetId()}); - for (TEditorId cineId : saveWorld->GetCinematics()) - w.WriteEncoded(GetCinematicState(world.first, cineId), 1); - } + for (TEditorId cineId : saveWorld->GetCinematics()) + w.WriteEncoded(GetCinematicState(world.first, cineId), 1); + } } -bool CPersistentOptions::GetCinematicState(CAssetId mlvlId, TEditorId cineId) const -{ - auto existing = std::find_if(xac_cinematicStates.cbegin(), xac_cinematicStates.cend(), - [&](const std::pair& pair) -> bool - { - return pair.first == mlvlId && pair.second == cineId; - }); +bool CPersistentOptions::GetCinematicState(CAssetId mlvlId, TEditorId cineId) const { + auto existing = std::find_if(xac_cinematicStates.cbegin(), xac_cinematicStates.cend(), + [&](const std::pair& pair) -> bool { + return pair.first == mlvlId && pair.second == cineId; + }); - return existing != xac_cinematicStates.cend(); + return existing != xac_cinematicStates.cend(); } -void CPersistentOptions::SetCinematicState(CAssetId mlvlId, TEditorId cineId, bool state) -{ - auto existing = std::find_if(xac_cinematicStates.cbegin(), xac_cinematicStates.cend(), - [&](const std::pair& pair) -> bool - { - return pair.first == mlvlId && pair.second == cineId; - }); +void CPersistentOptions::SetCinematicState(CAssetId mlvlId, TEditorId cineId, bool state) { + auto existing = std::find_if(xac_cinematicStates.cbegin(), xac_cinematicStates.cend(), + [&](const std::pair& pair) -> bool { + return pair.first == mlvlId && pair.second == cineId; + }); - if (state && existing == xac_cinematicStates.cend()) - xac_cinematicStates.emplace_back(mlvlId, cineId); - else if (!state && existing != xac_cinematicStates.cend()) - xac_cinematicStates.erase(existing); + if (state && existing == xac_cinematicStates.cend()) + xac_cinematicStates.emplace_back(mlvlId, cineId); + else if (!state && existing != xac_cinematicStates.cend()) + xac_cinematicStates.erase(existing); } -CGameOptions::CGameOptions(CBitStreamReader& stream) -{ - for (int b=0 ; b<64 ; ++b) - x0_[b] = stream.ReadEncoded(8); +CGameOptions::CGameOptions(CBitStreamReader& stream) { + for (int b = 0; b < 64; ++b) + x0_[b] = stream.ReadEncoded(8); - x44_soundMode = CAudioSys::ESurroundModes(stream.ReadEncoded(2)); - x48_screenBrightness = stream.ReadEncoded(4); + x44_soundMode = CAudioSys::ESurroundModes(stream.ReadEncoded(2)); + x48_screenBrightness = stream.ReadEncoded(4); - x4c_screenXOffset = stream.ReadEncoded(6) - 30; - x50_screenYOffset = stream.ReadEncoded(6) - 30; - x54_screenStretch = stream.ReadEncoded(5) - 10; - x58_sfxVol = stream.ReadEncoded(7); - x5c_musicVol = stream.ReadEncoded(7); - x60_hudAlpha = stream.ReadEncoded(8); - x64_helmetAlpha = stream.ReadEncoded(8); + x4c_screenXOffset = stream.ReadEncoded(6) - 30; + x50_screenYOffset = stream.ReadEncoded(6) - 30; + x54_screenStretch = stream.ReadEncoded(5) - 10; + x58_sfxVol = stream.ReadEncoded(7); + x5c_musicVol = stream.ReadEncoded(7); + x60_hudAlpha = stream.ReadEncoded(8); + x64_helmetAlpha = stream.ReadEncoded(8); - x68_24_hudLag = stream.ReadEncoded(1); - x68_28_hintSystem = stream.ReadEncoded(1); - x68_25_invertY = stream.ReadEncoded(1); - x68_26_rumble = stream.ReadEncoded(1); - x68_27_swapBeamsControls = stream.ReadEncoded(1); + x68_24_hudLag = stream.ReadEncoded(1); + x68_28_hintSystem = stream.ReadEncoded(1); + x68_25_invertY = stream.ReadEncoded(1); + x68_26_rumble = stream.ReadEncoded(1); + x68_27_swapBeamsControls = stream.ReadEncoded(1); } -void CGameOptions::ResetToDefaults() -{ - x48_screenBrightness = 4; - x4c_screenXOffset = 0; - x50_screenYOffset = 0; - x54_screenStretch = 0; - x58_sfxVol = 0x7f; - x5c_musicVol = 0x7f; - x44_soundMode = CAudioSys::ESurroundModes::Stereo; - x60_hudAlpha = 0xFF; - x64_helmetAlpha = 0xFF; - x68_24_hudLag = true; - x68_25_invertY = false; - x68_26_rumble = true; - x68_27_swapBeamsControls = false; - x68_28_hintSystem = true; - InitSoundMode(); - EnsureSettings(); +void CGameOptions::ResetToDefaults() { + x48_screenBrightness = 4; + x4c_screenXOffset = 0; + x50_screenYOffset = 0; + x54_screenStretch = 0; + x58_sfxVol = 0x7f; + x5c_musicVol = 0x7f; + x44_soundMode = CAudioSys::ESurroundModes::Stereo; + x60_hudAlpha = 0xFF; + x64_helmetAlpha = 0xFF; + x68_24_hudLag = true; + x68_25_invertY = false; + x68_26_rumble = true; + x68_27_swapBeamsControls = false; + x68_28_hintSystem = true; + InitSoundMode(); + EnsureSettings(); } -void CGameOptions::PutTo(CBitStreamWriter& writer) const -{ - for (int b=0 ; b<64 ; ++b) - writer.WriteEncoded(x0_[b], 8); +void CGameOptions::PutTo(CBitStreamWriter& writer) const { + for (int b = 0; b < 64; ++b) + writer.WriteEncoded(x0_[b], 8); - writer.WriteEncoded(u32(x44_soundMode), 2); - writer.WriteEncoded(x48_screenBrightness, 4); + writer.WriteEncoded(u32(x44_soundMode), 2); + writer.WriteEncoded(x48_screenBrightness, 4); - writer.WriteEncoded(x4c_screenXOffset + 30, 6); - writer.WriteEncoded(x50_screenYOffset + 30, 6); - writer.WriteEncoded(x54_screenStretch + 10, 5); - writer.WriteEncoded(x58_sfxVol, 7); - writer.WriteEncoded(x5c_musicVol, 7); - writer.WriteEncoded(x60_hudAlpha, 8); - writer.WriteEncoded(x64_helmetAlpha, 8); + writer.WriteEncoded(x4c_screenXOffset + 30, 6); + writer.WriteEncoded(x50_screenYOffset + 30, 6); + writer.WriteEncoded(x54_screenStretch + 10, 5); + writer.WriteEncoded(x58_sfxVol, 7); + writer.WriteEncoded(x5c_musicVol, 7); + writer.WriteEncoded(x60_hudAlpha, 8); + writer.WriteEncoded(x64_helmetAlpha, 8); - writer.WriteEncoded(x68_24_hudLag, 1); - writer.WriteEncoded(x68_28_hintSystem, 1); - writer.WriteEncoded(x68_25_invertY, 1); - writer.WriteEncoded(x68_26_rumble, 1); - writer.WriteEncoded(x68_27_swapBeamsControls, 1); + writer.WriteEncoded(x68_24_hudLag, 1); + writer.WriteEncoded(x68_28_hintSystem, 1); + writer.WriteEncoded(x68_25_invertY, 1); + writer.WriteEncoded(x68_26_rumble, 1); + writer.WriteEncoded(x68_27_swapBeamsControls, 1); } -CGameOptions::CGameOptions() -{ - x68_24_hudLag = true; - x68_26_rumble = true; - x68_28_hintSystem = true; - InitSoundMode(); +CGameOptions::CGameOptions() { + x68_24_hudLag = true; + x68_26_rumble = true; + x68_28_hintSystem = true; + InitSoundMode(); } -float CGameOptions::TuneScreenBrightness() -{ - return (0.375f * 1.f) + (float(x48_screenBrightness) * 0.25f); -} +float CGameOptions::TuneScreenBrightness() { return (0.375f * 1.f) + (float(x48_screenBrightness) * 0.25f); } -void CGameOptions::InitSoundMode() -{ - /* If system is mono, force x44 to mono, otherwise honor user preference */ -} +void CGameOptions::InitSoundMode() { /* If system is mono, force x44 to mono, otherwise honor user preference */ } static float BrightnessCopyFilter = 0.f; -void CGameOptions::SetScreenBrightness(s32 val, bool apply) -{ - x48_screenBrightness = zeus::clamp(0, val, 8); +void CGameOptions::SetScreenBrightness(s32 val, bool apply) { + x48_screenBrightness = zeus::clamp(0, val, 8); - if (apply) - BrightnessCopyFilter = TuneScreenBrightness(); + if (apply) + BrightnessCopyFilter = TuneScreenBrightness(); } -void CGameOptions::ApplyGamma() -{ - float gammaT = -m_gamma / 100.f + 1.f; - if (gammaT < 1.f) - gammaT = gammaT * 0.5f + 0.5f; - if (zeus::close_enough(gammaT, 1.f, 0.05f)) - gammaT = 1.f; - CGraphics::g_BooFactory->setDisplayGamma(gammaT); +void CGameOptions::ApplyGamma() { + float gammaT = -m_gamma / 100.f + 1.f; + if (gammaT < 1.f) + gammaT = gammaT * 0.5f + 0.5f; + if (zeus::close_enough(gammaT, 1.f, 0.05f)) + gammaT = 1.f; + CGraphics::g_BooFactory->setDisplayGamma(gammaT); } -void CGameOptions::SetGamma(s32 val, bool apply) -{ - m_gamma = zeus::clamp(-100, val, 100); +void CGameOptions::SetGamma(s32 val, bool apply) { + m_gamma = zeus::clamp(-100, val, 100); - if (apply) - ApplyGamma(); + if (apply) + ApplyGamma(); } -void CGameOptions::SetScreenPositionX(s32 pos, bool apply) -{ - x4c_screenXOffset = zeus::clamp(-30, pos, 30); +void CGameOptions::SetScreenPositionX(s32 pos, bool apply) { + x4c_screenXOffset = zeus::clamp(-30, pos, 30); - if (apply) - { - /* TOOD: CGraphics related funcs */ - } + if (apply) { + /* TOOD: CGraphics related funcs */ + } } -void CGameOptions::SetScreenPositionY(s32 pos, bool apply) -{ - x50_screenYOffset = zeus::clamp(-30, pos, 30); +void CGameOptions::SetScreenPositionY(s32 pos, bool apply) { + x50_screenYOffset = zeus::clamp(-30, pos, 30); - if (apply) - { - /* TOOD: CGraphics related funcs */ - } + if (apply) { + /* TOOD: CGraphics related funcs */ + } } -void CGameOptions::SetScreenStretch(s32 st, bool apply) -{ - x54_screenStretch = zeus::clamp(-10, st, 10); +void CGameOptions::SetScreenStretch(s32 st, bool apply) { + x54_screenStretch = zeus::clamp(-10, st, 10); - if (apply) - { - /* TOOD: CGraphics related funcs */ - } + if (apply) { + /* TOOD: CGraphics related funcs */ + } } -void CGameOptions::SetSfxVolume(s32 vol, bool apply) -{ - x58_sfxVol = zeus::clamp(0, vol, 0x7f); +void CGameOptions::SetSfxVolume(s32 vol, bool apply) { + x58_sfxVol = zeus::clamp(0, vol, 0x7f); - if (apply) - { - CAudioSys::SysSetSfxVolume(x58_sfxVol, 1, 1, 1); - CStreamAudioManager::SetSfxVolume(x58_sfxVol); - CMoviePlayer::SetSfxVolume(x58_sfxVol); - } + if (apply) { + CAudioSys::SysSetSfxVolume(x58_sfxVol, 1, 1, 1); + CStreamAudioManager::SetSfxVolume(x58_sfxVol); + CMoviePlayer::SetSfxVolume(x58_sfxVol); + } } -void CGameOptions::SetMusicVolume(s32 vol, bool apply) -{ - x5c_musicVol = zeus::clamp(0, vol, 0x7f); - if (apply) - CStreamAudioManager::SetMusicVolume(x5c_musicVol); +void CGameOptions::SetMusicVolume(s32 vol, bool apply) { + x5c_musicVol = zeus::clamp(0, vol, 0x7f); + if (apply) + CStreamAudioManager::SetMusicVolume(x5c_musicVol); } -void CGameOptions::SetHUDAlpha(u32 alpha) -{ - x60_hudAlpha = alpha; +void CGameOptions::SetHUDAlpha(u32 alpha) { x60_hudAlpha = alpha; } + +void CGameOptions::SetHelmetAlpha(u32 alpha) { x64_helmetAlpha = alpha; } + +void CGameOptions::SetHUDLag(bool lag) { x68_24_hudLag = lag; } + +void CGameOptions::SetSurroundMode(int mode, bool apply) { + x44_soundMode = CAudioSys::ESurroundModes(zeus::clamp(0, mode, 2)); + if (apply) + CAudioSys::SetSurroundMode(x44_soundMode); } -void CGameOptions::SetHelmetAlpha(u32 alpha) -{ - x64_helmetAlpha = alpha; +CAudioSys::ESurroundModes CGameOptions::GetSurroundMode() const { return x44_soundMode; } + +void CGameOptions::SetInvertYAxis(bool invert) { x68_25_invertY = invert; } + +void CGameOptions::SetIsRumbleEnabled(bool rumble) { x68_26_rumble = rumble; } + +void CGameOptions::SetSwapBeamControls(bool swap) { + x68_27_swapBeamsControls = swap; + if (!swap) + SetControls(0); + else + SetControls(1); } -void CGameOptions::SetHUDLag(bool lag) -{ - x68_24_hudLag = lag; +void CGameOptions::SetIsHintSystemEnabled(bool hints) { x68_28_hintSystem = hints; } + +void CGameOptions::SetControls(int controls) { + if (controls == 0) + g_currentPlayerControl = g_tweakPlayerControl; + else + g_currentPlayerControl = g_tweakPlayerControlAlt; + + ResetControllerAssets(controls); } -void CGameOptions::SetSurroundMode(int mode, bool apply) -{ - x44_soundMode = CAudioSys::ESurroundModes(zeus::clamp(0, mode, 2)); - if (apply) - CAudioSys::SetSurroundMode(x44_soundMode); -} - -CAudioSys::ESurroundModes CGameOptions::GetSurroundMode() const -{ - return x44_soundMode; -} - -void CGameOptions::SetInvertYAxis(bool invert) -{ - x68_25_invertY = invert; -} - -void CGameOptions::SetIsRumbleEnabled(bool rumble) -{ - x68_26_rumble = rumble; -} - -void CGameOptions::SetSwapBeamControls(bool swap) -{ - x68_27_swapBeamsControls = swap; - if (!swap) - SetControls(0); - else - SetControls(1); -} - -void CGameOptions::SetIsHintSystemEnabled(bool hints) -{ - x68_28_hintSystem = hints; -} - -void CGameOptions::SetControls(int controls) -{ - if (controls == 0) - g_currentPlayerControl = g_tweakPlayerControl; - else - g_currentPlayerControl = g_tweakPlayerControlAlt; - - ResetControllerAssets(controls); -} - -static const std::pair CStickToDPadRemap[] = -{ - {0x2A13C23E, 0xF13452F8}, - {0xA91A7703, 0xC042EC91}, - {0x12A12131, 0x5F556002}, - {0xA9798329, 0xB306E26F}, - {0xCD7B1ACA, 0x8ADA8184}, +static const std::pair CStickToDPadRemap[] = { + {0x2A13C23E, 0xF13452F8}, {0xA91A7703, 0xC042EC91}, {0x12A12131, 0x5F556002}, + {0xA9798329, 0xB306E26F}, {0xCD7B1ACA, 0x8ADA8184}, }; -static const std::pair CStickOutlineToDPadRemap[] = -{ - {0x1A29C0E6, 0xF13452F8}, - {0x5D9F9796, 0xC042EC91}, - {0x951546A8, 0x5F556002}, - {0x7946C4C5, 0xB306E26F}, - {0x409AA72E, 0x8ADA8184}, +static const std::pair CStickOutlineToDPadRemap[] = { + {0x1A29C0E6, 0xF13452F8}, {0x5D9F9796, 0xC042EC91}, {0x951546A8, 0x5F556002}, + {0x7946C4C5, 0xB306E26F}, {0x409AA72E, 0x8ADA8184}, }; -static std::pair TranslatePairToNew(const std::pair& p) -{ - return {g_ResFactory->TranslateOriginalToNew(p.first), - g_ResFactory->TranslateOriginalToNew(p.second)}; +static std::pair TranslatePairToNew(const std::pair& p) { + return {g_ResFactory->TranslateOriginalToNew(p.first), g_ResFactory->TranslateOriginalToNew(p.second)}; } -void CGameOptions::ResetControllerAssets(int controls) -{ - if (controls != 1) - { - x6c_controlTxtrMap.clear(); - } - else if (x6c_controlTxtrMap.empty()) - { - x6c_controlTxtrMap.reserve(15); +void CGameOptions::ResetControllerAssets(int controls) { + if (controls != 1) { + x6c_controlTxtrMap.clear(); + } else if (x6c_controlTxtrMap.empty()) { + x6c_controlTxtrMap.reserve(15); - for (int i=0 ; i<5 ; ++i) - { - x6c_controlTxtrMap.push_back(TranslatePairToNew(CStickToDPadRemap[i])); - x6c_controlTxtrMap.push_back({x6c_controlTxtrMap.back().second, - x6c_controlTxtrMap.back().first}); - } - - for (int i=0 ; i<5 ; ++i) - x6c_controlTxtrMap.push_back(TranslatePairToNew(CStickOutlineToDPadRemap[i])); - - std::sort(x6c_controlTxtrMap.begin(), x6c_controlTxtrMap.end(), - [](const std::pair& a, const std::pair& b) - { return a.first < b.first; }); - } -} - -void CGameOptions::EnsureSettings() -{ - SetScreenBrightness(x48_screenBrightness, true); - SetGamma(m_gamma, true); - SetScreenPositionX(x4c_screenXOffset, true); - SetScreenPositionY(x50_screenYOffset, true); - SetScreenStretch(x54_screenStretch, true); - SetSfxVolume(x58_sfxVol, true); - SetMusicVolume(x5c_musicVol, true); - SetSurroundMode(int(x44_soundMode), true); - SetHelmetAlpha(x64_helmetAlpha); - SetHUDLag(x68_24_hudLag); - SetInvertYAxis(x68_25_invertY); - SetIsRumbleEnabled(x68_26_rumble); - SetIsHintSystemEnabled(x68_28_hintSystem); - SetSwapBeamControls(x68_27_swapBeamsControls); -} - -void CGameOptions::TryRestoreDefaults(const CFinalInput& input, int category, - int option, bool frontend, bool forceRestore) -{ - const std::pair& options = GameOptionsRegistry[category]; - if (!options.first) - return; - - if (options.second[option].option != EGameOption::RestoreDefaults) - return; - - if (!forceRestore && !input.PA()) - return; - - if (frontend) - { - CSfxManager::SfxStart(SFXfnt_advance_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - CSfxManager::SfxStart(SFXfnt_advance_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - else - { - CSfxManager::SfxStart(SFXui_advance, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + for (int i = 0; i < 5; ++i) { + x6c_controlTxtrMap.push_back(TranslatePairToNew(CStickToDPadRemap[i])); + x6c_controlTxtrMap.push_back({x6c_controlTxtrMap.back().second, x6c_controlTxtrMap.back().first}); } - CGameOptions& gameOptions = g_GameState->GameOptions(); - switch (category) - { - case 0: - gameOptions.SetHelmetAlpha(0xff); - gameOptions.SetHUDLag(true); - gameOptions.SetIsHintSystemEnabled(true); - break; + for (int i = 0; i < 5; ++i) + x6c_controlTxtrMap.push_back(TranslatePairToNew(CStickOutlineToDPadRemap[i])); - case 1: - gameOptions.SetScreenBrightness(4, true); - gameOptions.SetGamma(0, true); - gameOptions.SetScreenPositionX(0, true); - gameOptions.SetScreenPositionY(0, true); - gameOptions.SetScreenStretch(0, true); - break; - - case 2: - gameOptions.SetSfxVolume(0x7f, true); - gameOptions.SetMusicVolume(0x7f, true); - gameOptions.SetSurroundMode(1, true); - break; - - case 3: - gameOptions.SetInvertYAxis(false); - gameOptions.SetIsRumbleEnabled(true); - gameOptions.SetSwapBeamControls(false); - break; - - default: break; - } + std::sort(x6c_controlTxtrMap.begin(), x6c_controlTxtrMap.end(), + [](const std::pair& a, const std::pair& b) { + return a.first < b.first; + }); + } } -void CGameOptions::SetOption(EGameOption option, int value) -{ - CGameOptions& options = g_GameState->GameOptions(); - - switch (option) - { - case EGameOption::VisorOpacity: - options.SetHUDAlpha(value); - break; - case EGameOption::HelmetOpacity: - options.SetHelmetAlpha(value); - break; - case EGameOption::HUDLag: - options.SetHUDLag(value); - break; - case EGameOption::HintSystem: - options.SetIsHintSystemEnabled(value); - break; - case EGameOption::ScreenBrightness: - options.SetGamma(value, true); - break; - case EGameOption::ScreenOffsetX: - options.SetScreenPositionX(value, true); - break; - case EGameOption::ScreenOffsetY: - options.SetScreenPositionY(value, true); - break; - case EGameOption::ScreenStretch: - options.SetScreenStretch(value, true); - break; - case EGameOption::SFXVolume: - options.SetSfxVolume(value, true); - break; - case EGameOption::MusicVolume: - options.SetMusicVolume(value, true); - break; - case EGameOption::SoundMode: - options.SetSurroundMode(value, true); - break; - case EGameOption::ReverseYAxis: - options.SetInvertYAxis(value); - break; - case EGameOption::Rumble: - options.SetIsRumbleEnabled(value); - break; - case EGameOption::SwapBeamControls: - options.SetSwapBeamControls(value); - break; - default: break; - } +void CGameOptions::EnsureSettings() { + SetScreenBrightness(x48_screenBrightness, true); + SetGamma(m_gamma, true); + SetScreenPositionX(x4c_screenXOffset, true); + SetScreenPositionY(x50_screenYOffset, true); + SetScreenStretch(x54_screenStretch, true); + SetSfxVolume(x58_sfxVol, true); + SetMusicVolume(x5c_musicVol, true); + SetSurroundMode(int(x44_soundMode), true); + SetHelmetAlpha(x64_helmetAlpha); + SetHUDLag(x68_24_hudLag); + SetInvertYAxis(x68_25_invertY); + SetIsRumbleEnabled(x68_26_rumble); + SetIsHintSystemEnabled(x68_28_hintSystem); + SetSwapBeamControls(x68_27_swapBeamsControls); } -int CGameOptions::GetOption(EGameOption option) -{ - const CGameOptions& options = g_GameState->GameOptions(); +void CGameOptions::TryRestoreDefaults(const CFinalInput& input, int category, int option, bool frontend, + bool forceRestore) { + const std::pair& options = GameOptionsRegistry[category]; + if (!options.first) + return; - switch (option) - { - case EGameOption::VisorOpacity: - return options.GetHUDAlpha(); - case EGameOption::HelmetOpacity: - return options.GetHelmetAlpha(); - case EGameOption::HUDLag: - return options.GetHUDLag(); - case EGameOption::HintSystem: - return options.GetIsHintSystemEnabled(); - case EGameOption::ScreenBrightness: - return options.GetGamma(); - case EGameOption::ScreenOffsetX: - return options.GetScreenPositionX(); - case EGameOption::ScreenOffsetY: - return options.GetScreenPositionY(); - case EGameOption::ScreenStretch: - return options.GetScreenStretch(); - case EGameOption::SFXVolume: - return options.GetSfxVolume(); - case EGameOption::MusicVolume: - return options.GetMusicVolume(); - case EGameOption::SoundMode: - return int(options.GetSurroundMode()); - case EGameOption::ReverseYAxis: - return options.GetInvertYAxis(); - case EGameOption::Rumble: - return options.GetIsRumbleEnabled(); - case EGameOption::SwapBeamControls: - return options.GetSwapBeamControls(); - default: break; - } + if (options.second[option].option != EGameOption::RestoreDefaults) + return; - return 0; + if (!forceRestore && !input.PA()) + return; + + if (frontend) { + CSfxManager::SfxStart(SFXfnt_advance_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(SFXfnt_advance_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else { + CSfxManager::SfxStart(SFXui_advance, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + + CGameOptions& gameOptions = g_GameState->GameOptions(); + switch (category) { + case 0: + gameOptions.SetHelmetAlpha(0xff); + gameOptions.SetHUDLag(true); + gameOptions.SetIsHintSystemEnabled(true); + break; + + case 1: + gameOptions.SetScreenBrightness(4, true); + gameOptions.SetGamma(0, true); + gameOptions.SetScreenPositionX(0, true); + gameOptions.SetScreenPositionY(0, true); + gameOptions.SetScreenStretch(0, true); + break; + + case 2: + gameOptions.SetSfxVolume(0x7f, true); + gameOptions.SetMusicVolume(0x7f, true); + gameOptions.SetSurroundMode(1, true); + break; + + case 3: + gameOptions.SetInvertYAxis(false); + gameOptions.SetIsRumbleEnabled(true); + gameOptions.SetSwapBeamControls(false); + break; + + default: + break; + } } -CHintOptions::CHintOptions(CBitStreamReader& stream) -{ - const auto& hints = g_MemoryCardSys->GetHints(); - x0_hintStates.reserve(hints.size()); +void CGameOptions::SetOption(EGameOption option, int value) { + CGameOptions& options = g_GameState->GameOptions(); - u32 hintIdx = 0; - for (const auto& hint : hints) - { - (void)hint; - EHintState state = EHintState(stream.ReadEncoded(2)); - u32 timeBits = stream.ReadEncoded(32); - float time = reinterpret_cast(timeBits); - if (state == EHintState::Zero) - time = 0.f; - - x0_hintStates.emplace_back(state, time, false); - - if (x10_nextHintIdx == -1 && state == EHintState::Displaying) - x10_nextHintIdx = hintIdx; - ++hintIdx; - } + switch (option) { + case EGameOption::VisorOpacity: + options.SetHUDAlpha(value); + break; + case EGameOption::HelmetOpacity: + options.SetHelmetAlpha(value); + break; + case EGameOption::HUDLag: + options.SetHUDLag(value); + break; + case EGameOption::HintSystem: + options.SetIsHintSystemEnabled(value); + break; + case EGameOption::ScreenBrightness: + options.SetGamma(value, true); + break; + case EGameOption::ScreenOffsetX: + options.SetScreenPositionX(value, true); + break; + case EGameOption::ScreenOffsetY: + options.SetScreenPositionY(value, true); + break; + case EGameOption::ScreenStretch: + options.SetScreenStretch(value, true); + break; + case EGameOption::SFXVolume: + options.SetSfxVolume(value, true); + break; + case EGameOption::MusicVolume: + options.SetMusicVolume(value, true); + break; + case EGameOption::SoundMode: + options.SetSurroundMode(value, true); + break; + case EGameOption::ReverseYAxis: + options.SetInvertYAxis(value); + break; + case EGameOption::Rumble: + options.SetIsRumbleEnabled(value); + break; + case EGameOption::SwapBeamControls: + options.SetSwapBeamControls(value); + break; + default: + break; + } } -void CHintOptions::PutTo(CBitStreamWriter& writer) const -{ - for (const SHintState& hint : x0_hintStates) - { - writer.WriteEncoded(u32(hint.x0_state), 2); - writer.WriteEncoded(reinterpret_cast(hint.x4_time), 32); - } +int CGameOptions::GetOption(EGameOption option) { + const CGameOptions& options = g_GameState->GameOptions(); + + switch (option) { + case EGameOption::VisorOpacity: + return options.GetHUDAlpha(); + case EGameOption::HelmetOpacity: + return options.GetHelmetAlpha(); + case EGameOption::HUDLag: + return options.GetHUDLag(); + case EGameOption::HintSystem: + return options.GetIsHintSystemEnabled(); + case EGameOption::ScreenBrightness: + return options.GetGamma(); + case EGameOption::ScreenOffsetX: + return options.GetScreenPositionX(); + case EGameOption::ScreenOffsetY: + return options.GetScreenPositionY(); + case EGameOption::ScreenStretch: + return options.GetScreenStretch(); + case EGameOption::SFXVolume: + return options.GetSfxVolume(); + case EGameOption::MusicVolume: + return options.GetMusicVolume(); + case EGameOption::SoundMode: + return int(options.GetSurroundMode()); + case EGameOption::ReverseYAxis: + return options.GetInvertYAxis(); + case EGameOption::Rumble: + return options.GetIsRumbleEnabled(); + case EGameOption::SwapBeamControls: + return options.GetSwapBeamControls(); + default: + break; + } + + return 0; } -void CHintOptions::SetNextHintTime() -{ - if (x10_nextHintIdx == -1) - return; - x0_hintStates[x10_nextHintIdx].x4_time = - g_MemoryCardSys->GetHints()[x10_nextHintIdx].GetTextTime() + 5.f; +CHintOptions::CHintOptions(CBitStreamReader& stream) { + const auto& hints = g_MemoryCardSys->GetHints(); + x0_hintStates.reserve(hints.size()); + + u32 hintIdx = 0; + for (const auto& hint : hints) { + (void)hint; + EHintState state = EHintState(stream.ReadEncoded(2)); + u32 timeBits = stream.ReadEncoded(32); + float time = reinterpret_cast(timeBits); + if (state == EHintState::Zero) + time = 0.f; + + x0_hintStates.emplace_back(state, time, false); + + if (x10_nextHintIdx == -1 && state == EHintState::Displaying) + x10_nextHintIdx = hintIdx; + ++hintIdx; + } } -void CHintOptions::InitializeMemoryState() -{ - const auto& hints = g_MemoryCardSys->GetHints(); - x0_hintStates.resize(hints.size()); +void CHintOptions::PutTo(CBitStreamWriter& writer) const { + for (const SHintState& hint : x0_hintStates) { + writer.WriteEncoded(u32(hint.x0_state), 2); + writer.WriteEncoded(reinterpret_cast(hint.x4_time), 32); + } } -const CHintOptions::SHintState* CHintOptions::GetCurrentDisplayedHint() const -{ - if (!g_GameState->GameOptions().GetIsHintSystemEnabled()) - return nullptr; +void CHintOptions::SetNextHintTime() { + if (x10_nextHintIdx == -1) + return; + x0_hintStates[x10_nextHintIdx].x4_time = g_MemoryCardSys->GetHints()[x10_nextHintIdx].GetTextTime() + 5.f; +} - if (x10_nextHintIdx == -1) - return nullptr; - - const SHintState& hintState = x0_hintStates[x10_nextHintIdx]; - const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[x10_nextHintIdx]; - if (hintState.x4_time >= hint.GetTextTime()) - return nullptr; - - if (hintState.x4_time < 3.f) - return &hintState; - - if (!hintState.x8_dismissed) - return &hintState; +void CHintOptions::InitializeMemoryState() { + const auto& hints = g_MemoryCardSys->GetHints(); + x0_hintStates.resize(hints.size()); +} +const CHintOptions::SHintState* CHintOptions::GetCurrentDisplayedHint() const { + if (!g_GameState->GameOptions().GetIsHintSystemEnabled()) return nullptr; + + if (x10_nextHintIdx == -1) + return nullptr; + + const SHintState& hintState = x0_hintStates[x10_nextHintIdx]; + const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[x10_nextHintIdx]; + if (hintState.x4_time >= hint.GetTextTime()) + return nullptr; + + if (hintState.x4_time < 3.f) + return &hintState; + + if (!hintState.x8_dismissed) + return &hintState; + + return nullptr; } -void CHintOptions::DelayHint(const char* name) -{ - int idx = CGameHintInfo::FindHintIndex(name); - if (idx == -1) - return; +void CHintOptions::DelayHint(const char* name) { + int idx = CGameHintInfo::FindHintIndex(name); + if (idx == -1) + return; - if (x10_nextHintIdx == idx) - for (SHintState& state : x0_hintStates) - state.x4_time += 60.f; - - x0_hintStates[idx].x0_state = EHintState::Delayed; -} - -void CHintOptions::ActivateImmediateHintTimer(const char* name) -{ - int idx = CGameHintInfo::FindHintIndex(name); - if (idx == -1) - return; - - SHintState& hintState = x0_hintStates[idx]; - const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[idx]; - if (hintState.x0_state != EHintState::Zero) - return; - - hintState.x0_state = EHintState::Waiting; - hintState.x4_time = hint.GetImmediateTime(); -} - -void CHintOptions::ActivateContinueDelayHintTimer(const char* name) -{ - int idx = x10_nextHintIdx; - if (idx != 0) - idx = CGameHintInfo::FindHintIndex(name); - if (idx == -1) - return; - - SHintState& hintState = x0_hintStates[idx]; - const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[idx]; - if (hintState.x0_state != EHintState::Displaying) - return; - - hintState.x4_time = hint.GetTextTime(); -} - -void CHintOptions::DismissDisplayedHint() -{ - if (x10_nextHintIdx == -1) - return; - const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[x10_nextHintIdx]; - SHintState& hintState = x0_hintStates[x10_nextHintIdx]; - if (hintState.x4_time >= hint.GetTextTime()) - return; - hintState.x4_time = hint.GetNormalTime(); - hintState.x8_dismissed = true; -} - -u32 CHintOptions::GetNextHintIdx() const -{ - if (g_GameState->GameOptions().GetIsHintSystemEnabled()) - return x10_nextHintIdx; - return -1; -} - -void CHintOptions::Update(float dt, const CStateManager& stateMgr) -{ - x10_nextHintIdx = -1; - int idx = 0; - auto memIt = g_MemoryCardSys->GetHints().begin(); + if (x10_nextHintIdx == idx) for (SHintState& state : x0_hintStates) - { - switch (state.x0_state) - { - case EHintState::Waiting: - state.x4_time -= dt; - if (state.x4_time <= 0.f) - { - state.x0_state = EHintState::Displaying; - state.x4_time = memIt->GetTextTime(); - } - break; - case EHintState::Displaying: - if (x10_nextHintIdx == -1) - x10_nextHintIdx = idx; - default: break; - } - ++memIt; - ++idx; - } + state.x4_time += 60.f; - if (x10_nextHintIdx == -1) - return; - - SHintState& state = x0_hintStates[x10_nextHintIdx]; - const CGameHintInfo::CGameHint& data = g_MemoryCardSys->GetHints()[x10_nextHintIdx]; - - state.x4_time = std::max(0.f, state.x4_time - dt); - if (state.x4_time < data.GetTextTime()) - { - for (const CGameHintInfo::SHintLocation& loc : data.GetLocations()) - { - if (loc.x0_mlvlId == stateMgr.GetWorld()->IGetWorldAssetId() && - loc.x8_areaId == stateMgr.GetNextAreaId()) - { - state.x4_time = data.GetNormalTime(); - state.x8_dismissed = true; - } - } - } + x0_hintStates[idx].x0_state = EHintState::Delayed; } +void CHintOptions::ActivateImmediateHintTimer(const char* name) { + int idx = CGameHintInfo::FindHintIndex(name); + if (idx == -1) + return; + + SHintState& hintState = x0_hintStates[idx]; + const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[idx]; + if (hintState.x0_state != EHintState::Zero) + return; + + hintState.x0_state = EHintState::Waiting; + hintState.x4_time = hint.GetImmediateTime(); } + +void CHintOptions::ActivateContinueDelayHintTimer(const char* name) { + int idx = x10_nextHintIdx; + if (idx != 0) + idx = CGameHintInfo::FindHintIndex(name); + if (idx == -1) + return; + + SHintState& hintState = x0_hintStates[idx]; + const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[idx]; + if (hintState.x0_state != EHintState::Displaying) + return; + + hintState.x4_time = hint.GetTextTime(); +} + +void CHintOptions::DismissDisplayedHint() { + if (x10_nextHintIdx == -1) + return; + const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[x10_nextHintIdx]; + SHintState& hintState = x0_hintStates[x10_nextHintIdx]; + if (hintState.x4_time >= hint.GetTextTime()) + return; + hintState.x4_time = hint.GetNormalTime(); + hintState.x8_dismissed = true; +} + +u32 CHintOptions::GetNextHintIdx() const { + if (g_GameState->GameOptions().GetIsHintSystemEnabled()) + return x10_nextHintIdx; + return -1; +} + +void CHintOptions::Update(float dt, const CStateManager& stateMgr) { + x10_nextHintIdx = -1; + int idx = 0; + auto memIt = g_MemoryCardSys->GetHints().begin(); + for (SHintState& state : x0_hintStates) { + switch (state.x0_state) { + case EHintState::Waiting: + state.x4_time -= dt; + if (state.x4_time <= 0.f) { + state.x0_state = EHintState::Displaying; + state.x4_time = memIt->GetTextTime(); + } + break; + case EHintState::Displaying: + if (x10_nextHintIdx == -1) + x10_nextHintIdx = idx; + default: + break; + } + ++memIt; + ++idx; + } + + if (x10_nextHintIdx == -1) + return; + + SHintState& state = x0_hintStates[x10_nextHintIdx]; + const CGameHintInfo::CGameHint& data = g_MemoryCardSys->GetHints()[x10_nextHintIdx]; + + state.x4_time = std::max(0.f, state.x4_time - dt); + if (state.x4_time < data.GetTextTime()) { + for (const CGameHintInfo::SHintLocation& loc : data.GetLocations()) { + if (loc.x0_mlvlId == stateMgr.GetWorld()->IGetWorldAssetId() && loc.x8_areaId == stateMgr.GetNextAreaId()) { + state.x4_time = data.GetNormalTime(); + state.x8_dismissed = true; + } + } + } +} + +} // namespace urde diff --git a/Runtime/CGameOptions.hpp b/Runtime/CGameOptions.hpp index 206200594..52cd17f3f 100644 --- a/Runtime/CGameOptions.hpp +++ b/Runtime/CGameOptions.hpp @@ -4,237 +4,210 @@ #include "Audio/CAudioSys.hpp" #include "CSaveWorld.hpp" -namespace urde -{ +namespace urde { struct CFinalInput; class CStateManager; /** Options presented in UI */ -enum class EGameOption -{ - VisorOpacity, - HelmetOpacity, - HUDLag, - HintSystem, - ScreenBrightness, - ScreenOffsetX, - ScreenOffsetY, - ScreenStretch, - SFXVolume, - MusicVolume, - SoundMode, - ReverseYAxis, - Rumble, - SwapBeamControls, - RestoreDefaults +enum class EGameOption { + VisorOpacity, + HelmetOpacity, + HUDLag, + HintSystem, + ScreenBrightness, + ScreenOffsetX, + ScreenOffsetY, + ScreenStretch, + SFXVolume, + MusicVolume, + SoundMode, + ReverseYAxis, + Rumble, + SwapBeamControls, + RestoreDefaults }; /** Option UI type */ -enum class EOptionType -{ - Float, - DoubleEnum, - TripleEnum, - RestoreDefaults -}; +enum class EOptionType { Float, DoubleEnum, TripleEnum, RestoreDefaults }; /** Option UI presentation information */ -struct SGameOption -{ - EGameOption option; - u32 stringId; - float minVal, maxVal, increment; - EOptionType type; +struct SGameOption { + EGameOption option; + u32 stringId; + float minVal, maxVal, increment; + EOptionType type; }; /** Static registry of Option UI presentation information */ extern const std::pair GameOptionsRegistry[]; /** Options tracked persistently between game sessions */ -class CPersistentOptions -{ - friend class CGameState; - u8 x0_nesState[98] = {}; - bool x68_[64] = {}; - std::vector> xac_cinematicStates; /* (MLVL, Cinematic) */ - u32 xbc_autoMapperKeyState = 0; - u32 xc0_frozenFpsCount = 0; - u32 xc4_frozenBallCount = 0; - u32 xc8_powerBombAmmoCount = 0; - u32 xcc_logScanPercent = 0; +class CPersistentOptions { + friend class CGameState; + u8 x0_nesState[98] = {}; + bool x68_[64] = {}; + std::vector> xac_cinematicStates; /* (MLVL, Cinematic) */ + u32 xbc_autoMapperKeyState = 0; + u32 xc0_frozenFpsCount = 0; + u32 xc4_frozenBallCount = 0; + u32 xc8_powerBombAmmoCount = 0; + u32 xcc_logScanPercent = 0; - union - { - struct - { - bool xd0_24_fusionLinked : 1; - bool xd0_25_normalModeBeat : 1; - bool xd0_26_hardModeBeat : 1; - bool xd0_27_fusionBeat : 1; - bool xd0_28_fusionSuitActive : 1; - bool xd0_29_allItemsCollected : 1; - }; - u16 _dummy = 0; + union { + struct { + bool xd0_24_fusionLinked : 1; + bool xd0_25_normalModeBeat : 1; + bool xd0_26_hardModeBeat : 1; + bool xd0_27_fusionBeat : 1; + bool xd0_28_fusionSuitActive : 1; + bool xd0_29_allItemsCollected : 1; }; + u16 _dummy = 0; + }; public: - CPersistentOptions() = default; - CPersistentOptions(CBitStreamReader& stream); + CPersistentOptions() = default; + CPersistentOptions(CBitStreamReader& stream); - bool GetCinematicState(CAssetId mlvlId, TEditorId cineId) const; - void SetCinematicState(CAssetId mlvlId, TEditorId cineId, bool state); - u32 GetAutoMapperKeyState() const { return xbc_autoMapperKeyState; } - void SetAutoMapperKeyState(u32 s) { xbc_autoMapperKeyState = s; } - bool GetPlayerLinkedFusion() const { return xd0_24_fusionLinked; } - void SetPlayerLinkedFusion(bool v) { xd0_24_fusionLinked = v; } - bool GetPlayerBeatNormalMode() const { return xd0_25_normalModeBeat; } - void SetPlayerBeatNormalMode(bool v) { xd0_25_normalModeBeat = v; } - bool GetPlayerBeatHardMode() const { return xd0_26_hardModeBeat; } - void SetPlayerBeatHardMode(bool v) { xd0_26_hardModeBeat = v; } - bool GetPlayerBeatFusion() const { return xd0_27_fusionBeat; } - void SetPlayerBeatFusion(bool v) { xd0_27_fusionBeat = v; } - bool GetPlayerFusionSuitActive() const { return xd0_28_fusionSuitActive; } - void SetPlayerFusionSuitActive(bool v) { xd0_28_fusionSuitActive = v; } - bool GetAllItemsCollected() const { return xd0_29_allItemsCollected; } - void SetAllItemsCollected(bool v) { xd0_29_allItemsCollected = v; } - u32 GetLogScanPercent() const { return xcc_logScanPercent; } - void SetLogScanPercent(u32 v) { xcc_logScanPercent = v; } - void IncrementFrozenFpsCount() { xc0_frozenFpsCount = std::min(int(xc0_frozenFpsCount + 1), 3); } - bool GetShowFrozenFpsMessage() const { return xc0_frozenFpsCount != 3; } - void IncrementFrozenBallCount() { xc4_frozenBallCount = std::min(int(xc4_frozenBallCount + 1), 3); } - bool GetShowFrozenBallMessage() const { return xc4_frozenBallCount != 3; } - bool GetShowPowerBombAmmoMessage() const { return xc8_powerBombAmmoCount != 1; } - void IncrementPowerBombAmmoCount() - { - xc8_powerBombAmmoCount = std::min(1, xc8_powerBombAmmoCount + 1); - } + bool GetCinematicState(CAssetId mlvlId, TEditorId cineId) const; + void SetCinematicState(CAssetId mlvlId, TEditorId cineId, bool state); + u32 GetAutoMapperKeyState() const { return xbc_autoMapperKeyState; } + void SetAutoMapperKeyState(u32 s) { xbc_autoMapperKeyState = s; } + bool GetPlayerLinkedFusion() const { return xd0_24_fusionLinked; } + void SetPlayerLinkedFusion(bool v) { xd0_24_fusionLinked = v; } + bool GetPlayerBeatNormalMode() const { return xd0_25_normalModeBeat; } + void SetPlayerBeatNormalMode(bool v) { xd0_25_normalModeBeat = v; } + bool GetPlayerBeatHardMode() const { return xd0_26_hardModeBeat; } + void SetPlayerBeatHardMode(bool v) { xd0_26_hardModeBeat = v; } + bool GetPlayerBeatFusion() const { return xd0_27_fusionBeat; } + void SetPlayerBeatFusion(bool v) { xd0_27_fusionBeat = v; } + bool GetPlayerFusionSuitActive() const { return xd0_28_fusionSuitActive; } + void SetPlayerFusionSuitActive(bool v) { xd0_28_fusionSuitActive = v; } + bool GetAllItemsCollected() const { return xd0_29_allItemsCollected; } + void SetAllItemsCollected(bool v) { xd0_29_allItemsCollected = v; } + u32 GetLogScanPercent() const { return xcc_logScanPercent; } + void SetLogScanPercent(u32 v) { xcc_logScanPercent = v; } + void IncrementFrozenFpsCount() { xc0_frozenFpsCount = std::min(int(xc0_frozenFpsCount + 1), 3); } + bool GetShowFrozenFpsMessage() const { return xc0_frozenFpsCount != 3; } + void IncrementFrozenBallCount() { xc4_frozenBallCount = std::min(int(xc4_frozenBallCount + 1), 3); } + bool GetShowFrozenBallMessage() const { return xc4_frozenBallCount != 3; } + bool GetShowPowerBombAmmoMessage() const { return xc8_powerBombAmmoCount != 1; } + void IncrementPowerBombAmmoCount() { xc8_powerBombAmmoCount = std::min(1, xc8_powerBombAmmoCount + 1); } - void PutTo(CBitStreamWriter& w) const; + void PutTo(CBitStreamWriter& w) const; - u8* GetNESState() { return x0_nesState; } + u8* GetNESState() { return x0_nesState; } }; /** Options tracked per game session */ -class CGameOptions -{ - u8 x0_[64] = {}; - CAudioSys::ESurroundModes x44_soundMode = CAudioSys::ESurroundModes::Stereo; - u32 x48_screenBrightness = 4; - s32 x4c_screenXOffset = 0; - s32 x50_screenYOffset = 0; - s32 x54_screenStretch = 0; - u32 x58_sfxVol = 0x7f; - u32 x5c_musicVol = 0x7f; - u32 x60_hudAlpha = 0xff; - u32 x64_helmetAlpha = 0xff; +class CGameOptions { + u8 x0_[64] = {}; + CAudioSys::ESurroundModes x44_soundMode = CAudioSys::ESurroundModes::Stereo; + u32 x48_screenBrightness = 4; + s32 x4c_screenXOffset = 0; + s32 x50_screenYOffset = 0; + s32 x54_screenStretch = 0; + u32 x58_sfxVol = 0x7f; + u32 x5c_musicVol = 0x7f; + u32 x60_hudAlpha = 0xff; + u32 x64_helmetAlpha = 0xff; - s32 m_gamma = 0; + s32 m_gamma = 0; - union - { - struct - { - bool x68_24_hudLag : 1; - bool x68_25_invertY : 1; - bool x68_26_rumble : 1; - bool x68_27_swapBeamsControls : 1; - bool x68_28_hintSystem : 1; - }; - u16 _dummy = 0; + union { + struct { + bool x68_24_hudLag : 1; + bool x68_25_invertY : 1; + bool x68_26_rumble : 1; + bool x68_27_swapBeamsControls : 1; + bool x68_28_hintSystem : 1; }; + u16 _dummy = 0; + }; - std::vector> x6c_controlTxtrMap; + std::vector> x6c_controlTxtrMap; public: - CGameOptions(); - CGameOptions(CBitStreamReader& stream); - void ResetToDefaults(); - void InitSoundMode(); - void EnsureSettings(); - void PutTo(CBitStreamWriter& writer) const; + CGameOptions(); + CGameOptions(CBitStreamReader& stream); + void ResetToDefaults(); + void InitSoundMode(); + void EnsureSettings(); + void PutTo(CBitStreamWriter& writer) const; - float TuneScreenBrightness(); - void SetScreenBrightness(s32, bool); - s32 GetScreenBrightness() const { return x48_screenBrightness; } - void ApplyGamma(); - void SetGamma(s32, bool); - s32 GetGamma() const { return m_gamma; } - void SetScreenPositionX(s32, bool); - s32 GetScreenPositionX() const { return x4c_screenXOffset; } - void SetScreenPositionY(s32, bool); - s32 GetScreenPositionY() const { return x50_screenYOffset; } - void SetScreenStretch(s32, bool); - s32 GetScreenStretch() const { return x54_screenStretch; } - void SetSfxVolume(s32, bool); - s32 GetSfxVolume() const { return x58_sfxVol; } - void SetMusicVolume(s32, bool); - s32 GetMusicVolume() const { return x5c_musicVol; } - void SetHUDAlpha(u32); - u32 GetHUDAlpha() const { return x60_hudAlpha; } - void SetHelmetAlpha(u32); - u32 GetHelmetAlpha() const { return x64_helmetAlpha; } - void SetHUDLag(bool); - bool GetHUDLag() const { return x68_24_hudLag; } - void SetSurroundMode(int mode, bool apply); - CAudioSys::ESurroundModes GetSurroundMode() const; - void SetInvertYAxis(bool); - bool GetInvertYAxis() const { return x68_25_invertY; } - void SetIsRumbleEnabled(bool); - bool GetIsRumbleEnabled() const { return x68_26_rumble; } - void SetSwapBeamControls(bool); - bool GetSwapBeamControls() const { return x68_27_swapBeamsControls; } - void SetIsHintSystemEnabled(bool); - bool GetIsHintSystemEnabled() const { return x68_28_hintSystem; } - void SetControls(int controls); - void ResetControllerAssets(int controls); - const std::vector>& GetControlTXTRMap() const { return x6c_controlTxtrMap; } + float TuneScreenBrightness(); + void SetScreenBrightness(s32, bool); + s32 GetScreenBrightness() const { return x48_screenBrightness; } + void ApplyGamma(); + void SetGamma(s32, bool); + s32 GetGamma() const { return m_gamma; } + void SetScreenPositionX(s32, bool); + s32 GetScreenPositionX() const { return x4c_screenXOffset; } + void SetScreenPositionY(s32, bool); + s32 GetScreenPositionY() const { return x50_screenYOffset; } + void SetScreenStretch(s32, bool); + s32 GetScreenStretch() const { return x54_screenStretch; } + void SetSfxVolume(s32, bool); + s32 GetSfxVolume() const { return x58_sfxVol; } + void SetMusicVolume(s32, bool); + s32 GetMusicVolume() const { return x5c_musicVol; } + void SetHUDAlpha(u32); + u32 GetHUDAlpha() const { return x60_hudAlpha; } + void SetHelmetAlpha(u32); + u32 GetHelmetAlpha() const { return x64_helmetAlpha; } + void SetHUDLag(bool); + bool GetHUDLag() const { return x68_24_hudLag; } + void SetSurroundMode(int mode, bool apply); + CAudioSys::ESurroundModes GetSurroundMode() const; + void SetInvertYAxis(bool); + bool GetInvertYAxis() const { return x68_25_invertY; } + void SetIsRumbleEnabled(bool); + bool GetIsRumbleEnabled() const { return x68_26_rumble; } + void SetSwapBeamControls(bool); + bool GetSwapBeamControls() const { return x68_27_swapBeamsControls; } + void SetIsHintSystemEnabled(bool); + bool GetIsHintSystemEnabled() const { return x68_28_hintSystem; } + void SetControls(int controls); + void ResetControllerAssets(int controls); + const std::vector>& GetControlTXTRMap() const { return x6c_controlTxtrMap; } - static void TryRestoreDefaults(const CFinalInput& input, int category, - int option, bool frontend, bool forceRestore); - static void SetOption(EGameOption option, int value); - static int GetOption(EGameOption option); + static void TryRestoreDefaults(const CFinalInput& input, int category, int option, bool frontend, bool forceRestore); + static void SetOption(EGameOption option, int value); + static int GetOption(EGameOption option); }; -class CHintOptions -{ +class CHintOptions { public: - enum class EHintState - { - Zero, - Waiting, - Displaying, - Delayed - }; - struct SHintState - { - EHintState x0_state = EHintState::Zero; - float x4_time = 0.f; - bool x8_dismissed = false; + enum class EHintState { Zero, Waiting, Displaying, Delayed }; + struct SHintState { + EHintState x0_state = EHintState::Zero; + float x4_time = 0.f; + bool x8_dismissed = false; - SHintState() = default; - SHintState(EHintState state, float time, bool flag) - : x0_state(state), x4_time(time), x8_dismissed(flag) {} + SHintState() = default; + SHintState(EHintState state, float time, bool flag) : x0_state(state), x4_time(time), x8_dismissed(flag) {} + + bool CanContinue() const { return x4_time / 3.f <= 1.f; } + }; - bool CanContinue() const { return x4_time / 3.f <= 1.f; } - }; private: - std::vector x0_hintStates; - u32 x10_nextHintIdx = -1; + std::vector x0_hintStates; + u32 x10_nextHintIdx = -1; + public: - CHintOptions() = default; - CHintOptions(CBitStreamReader& stream); - void PutTo(CBitStreamWriter& writer) const; - void SetNextHintTime(); - void InitializeMemoryState(); - const SHintState* GetCurrentDisplayedHint() const; - void DelayHint(const char* name); - void ActivateImmediateHintTimer(const char* name); - void ActivateContinueDelayHintTimer(const char* name); - void DismissDisplayedHint(); - u32 GetNextHintIdx() const; - const std::vector& GetHintStates() const { return x0_hintStates; } - void Update(float dt, const CStateManager& stateMgr); + CHintOptions() = default; + CHintOptions(CBitStreamReader& stream); + void PutTo(CBitStreamWriter& writer) const; + void SetNextHintTime(); + void InitializeMemoryState(); + const SHintState* GetCurrentDisplayedHint() const; + void DelayHint(const char* name); + void ActivateImmediateHintTimer(const char* name); + void ActivateContinueDelayHintTimer(const char* name); + void DismissDisplayedHint(); + u32 GetNextHintIdx() const; + const std::vector& GetHintStates() const { return x0_hintStates; } + void Update(float dt, const CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/CGameOptionsTouchBar.cpp b/Runtime/CGameOptionsTouchBar.cpp index 49ac1dddc..68b75992a 100644 --- a/Runtime/CGameOptionsTouchBar.cpp +++ b/Runtime/CGameOptionsTouchBar.cpp @@ -1,19 +1,13 @@ #include "CGameOptionsTouchBar.hpp" -namespace urde -{ +namespace urde { -CGameOptionsTouchBar::EAction CGameOptionsTouchBar::PopAction() -{ return EAction::None; } -void CGameOptionsTouchBar::GetSelection(int& left, int& right, int& value) -{ left = -1, right = -1, value = -1; } +CGameOptionsTouchBar::EAction CGameOptionsTouchBar::PopAction() { return EAction::None; } +void CGameOptionsTouchBar::GetSelection(int& left, int& right, int& value) { left = -1, right = -1, value = -1; } void CGameOptionsTouchBar::SetSelection(int left, int right, int value) {} #ifndef __APPLE__ -std::unique_ptr NewGameOptionsTouchBar() -{ - return std::make_unique(); -} +std::unique_ptr NewGameOptionsTouchBar() { return std::make_unique(); } #endif -} +} // namespace urde diff --git a/Runtime/CGameOptionsTouchBar.hpp b/Runtime/CGameOptionsTouchBar.hpp index 8e3ba4a39..361c4ea7f 100644 --- a/Runtime/CGameOptionsTouchBar.hpp +++ b/Runtime/CGameOptionsTouchBar.hpp @@ -3,27 +3,18 @@ #include #include -namespace urde -{ +namespace urde { -class CGameOptionsTouchBar -{ +class CGameOptionsTouchBar { public: - enum class EAction - { - None, - Back, - Advance, - ValueChange - }; + enum class EAction { None, Back, Advance, ValueChange }; - virtual ~CGameOptionsTouchBar() = default; - virtual EAction PopAction(); - virtual void GetSelection(int& left, int& right, int& value); - virtual void SetSelection(int left, int right, int value); + virtual ~CGameOptionsTouchBar() = default; + virtual EAction PopAction(); + virtual void GetSelection(int& left, int& right, int& value); + virtual void SetSelection(int left, int right, int value); }; std::unique_ptr NewGameOptionsTouchBar(); -} - +} // namespace urde diff --git a/Runtime/CGameState.cpp b/Runtime/CGameState.cpp index d6cb2390a..9f5c8856e 100644 --- a/Runtime/CGameState.cpp +++ b/Runtime/CGameState.cpp @@ -7,310 +7,267 @@ #include "CSaveWorld.hpp" #include "MP1/MP1.hpp" -namespace urde -{ -union BitsToDouble -{ - struct - { +namespace urde { +union BitsToDouble { + struct { #if BYTE_ORDER == __LITTLE_ENDIAN - u32 high; - u32 low; + u32 high; + u32 low; #else - u32 low; - u32 high; + u32 low; + u32 high; #endif - }; - double doub; + }; + double doub; }; -CWorldLayerState::CWorldLayerState(CBitStreamReader& reader, const CSaveWorld& saveWorld) -{ - u32 bitCount = reader.ReadEncoded(10); - x10_saveLayers.reserve(bitCount); +CWorldLayerState::CWorldLayerState(CBitStreamReader& reader, const CSaveWorld& saveWorld) { + u32 bitCount = reader.ReadEncoded(10); + x10_saveLayers.reserve(bitCount); - for (u32 i=0 ; i& layers) -{ - if (x0_areaLayers.size()) - return; - x0_areaLayers = layers; - if (x10_saveLayers.getBitCount() == 0) - return; - - u32 a = 0; - u32 b = 0; - for (const CWorldLayers::Area& area : x0_areaLayers) - { - for (u32 l=1 ; l(); - xc_mapWorldInfo = std::make_shared(); - x10_desiredAreaAssetId = {}; - x14_layerState = std::make_shared(); -} - -CWorldState::CWorldState(CBitStreamReader& reader, CAssetId mlvlId, const CSaveWorld& saveWorld) -: x0_mlvlId(mlvlId) -{ - x4_areaId = reader.ReadEncoded(32); - x10_desiredAreaAssetId = u32(reader.ReadEncoded(32)); - x8_relayTracker = std::make_shared(reader, saveWorld); - xc_mapWorldInfo = std::make_shared(reader, saveWorld, mlvlId); - x14_layerState = std::make_shared(reader, saveWorld); -} - -void CWorldState::PutTo(CBitStreamWriter& writer, const CSaveWorld& savw) const -{ - writer.WriteEncoded(x4_areaId, 32); - writer.WriteEncoded(x10_desiredAreaAssetId.Value(), 32); - x8_relayTracker->PutTo(writer, savw); - xc_mapWorldInfo->PutTo(writer, savw, x0_mlvlId); - x14_layerState->PutTo(writer); -} - -CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data) -{ - CBitStreamReader stream(data, 4096); - GameFileStateInfo ret; - - for (u32 i = 0; i < 128; i++) - stream.ReadEncoded(8); - ret.x14_timestamp = stream.ReadEncoded(32); - - ret.x20_hardMode = stream.ReadEncoded(1); - stream.ReadEncoded(1); - CAssetId origMLVL = stream.ReadEncoded(32); - ret.x8_mlvlId = g_ResFactory->TranslateOriginalToNew(origMLVL); - - BitsToDouble conv; - conv.low = stream.ReadEncoded(32); - conv.high = stream.ReadEncoded(32); - ret.x0_playTime = conv.doub; - - CPlayerState playerState(stream); - ret.x10_energyTanks = playerState.GetItemCapacity(CPlayerState::EItemType::EnergyTanks); - - u32 itemPercent; - if (origMLVL == 0x158EFE17) - itemPercent = 0; + for (u32 i = 0; i < bitCount; ++i) { + bool bit = reader.ReadEncoded(1); + if (bit) + x10_saveLayers.setBit(i); else - itemPercent = playerState.CalculateItemCollectionRate() * 100 / playerState.GetPickupTotal(); - - ret.x18_itemPercent = itemPercent; - - float scanPercent; - if (playerState.GetTotalLogScans() == 0) - scanPercent = 0.f; - else - scanPercent = 100.f * playerState.GetLogScans() / float(playerState.GetTotalLogScans()); - ret.x1c_scanPercent = scanPercent; - - return ret; + x10_saveLayers.unsetBit(i); + } } -CGameState::CGameState() -{ - x98_playerState = std::make_shared(); - x9c_transManager = std::make_shared(); - x228_25_initPowerupsAtFirstSpawn = true; - if (g_MemoryCardSys) - InitializeMemoryStates(); +void CWorldLayerState::PutTo(CBitStreamWriter& writer) const { + u32 totalLayerCount = 0; + for (int i = 0; i < x0_areaLayers.size(); ++i) + totalLayerCount += GetAreaLayerCount(i) - 1; + + writer.WriteEncoded(totalLayerCount, 10); + + for (int i = 0; i < x0_areaLayers.size(); ++i) { + u32 count = GetAreaLayerCount(i); + for (u32 l = 1; l < count; ++l) + writer.WriteEncoded(IsLayerActive(i, l), 1); + } } -CGameState::CGameState(CBitStreamReader& stream, u32 saveIdx) -: x20c_saveFileIdx(saveIdx) -{ - x9c_transManager = std::make_shared(); - x228_25_initPowerupsAtFirstSpawn = true; +void CWorldLayerState::InitializeWorldLayers(const std::vector& layers) { + if (x0_areaLayers.size()) + return; + x0_areaLayers = layers; + if (x10_saveLayers.getBitCount() == 0) + return; - for (u32 i = 0; i < 128; i++) - x0_[i] = stream.ReadEncoded(8); - stream.ReadEncoded(32); + u32 a = 0; + u32 b = 0; + for (const CWorldLayers::Area& area : x0_areaLayers) { + for (u32 l = 1; l < area.m_layerCount; ++l) + SetLayerActive(a, l, x10_saveLayers.getBit(b++)); + ++a; + } - x228_24_hardMode = stream.ReadEncoded(1); - x228_25_initPowerupsAtFirstSpawn = stream.ReadEncoded(1); - x84_mlvlId = g_ResFactory->TranslateOriginalToNew(stream.ReadEncoded(32)); - MP1::CMain::EnsureWorldPakReady(x84_mlvlId); - - BitsToDouble conv; - conv.low = stream.ReadEncoded(32); - conv.high = stream.ReadEncoded(32); - xa0_playTime = conv.doub; - - x98_playerState = std::make_shared(stream); - - x17c_gameOptions = CGameOptions(stream); - x1f8_hintOptions = CHintOptions(stream); - - const auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); - x88_worldStates.reserve(memWorlds.size()); - for (const auto& memWorld : memWorlds) - { - TLockedToken saveWorld = - g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), memWorld.second.GetSaveWorldAssetId()}); - x88_worldStates.emplace_back(stream, memWorld.first, *saveWorld); - } - - InitializeMemoryWorlds(); - WriteBackupBuf(); + x10_saveLayers.clear(); } -void CGameState::ReadPersistentOptions(CBitStreamReader& r) -{ - xa8_systemOptions = CPersistentOptions(r); +CWorldState::CWorldState(CAssetId id) : x0_mlvlId(id), x4_areaId(0) { + x8_relayTracker = std::make_shared(); + xc_mapWorldInfo = std::make_shared(); + x10_desiredAreaAssetId = {}; + x14_layerState = std::make_shared(); } -void CGameState::ImportPersistentOptions(const CPersistentOptions& opts) -{ - if (opts.xd0_24_fusionLinked) - xa8_systemOptions.xd0_24_fusionLinked = true; - if (opts.xd0_27_fusionBeat) - xa8_systemOptions.xd0_27_fusionBeat = true; - if (&opts != &xa8_systemOptions) - memcpy(xa8_systemOptions.x0_nesState, opts.x0_nesState, 98); - xa8_systemOptions.SetLogScanPercent(opts.GetLogScanPercent()); - xa8_systemOptions.SetAllItemsCollected(opts.GetAllItemsCollected()); - xa8_systemOptions.SetPlayerBeatNormalMode(opts.GetPlayerBeatNormalMode()); - xa8_systemOptions.SetPlayerBeatHardMode(opts.GetPlayerBeatHardMode()); +CWorldState::CWorldState(CBitStreamReader& reader, CAssetId mlvlId, const CSaveWorld& saveWorld) : x0_mlvlId(mlvlId) { + x4_areaId = reader.ReadEncoded(32); + x10_desiredAreaAssetId = u32(reader.ReadEncoded(32)); + x8_relayTracker = std::make_shared(reader, saveWorld); + xc_mapWorldInfo = std::make_shared(reader, saveWorld, mlvlId); + x14_layerState = std::make_shared(reader, saveWorld); } -void CGameState::ExportPersistentOptions(CPersistentOptions& opts) const -{ - if (xa8_systemOptions.xd0_24_fusionLinked) - opts.xd0_24_fusionLinked = true; - if (xa8_systemOptions.xd0_27_fusionBeat) - opts.xd0_27_fusionBeat = true; - if (&opts != &xa8_systemOptions) - memcpy(opts.x0_nesState, xa8_systemOptions.x0_nesState, 98); - opts.SetPlayerFusionSuitActive(xa8_systemOptions.GetPlayerFusionSuitActive()); +void CWorldState::PutTo(CBitStreamWriter& writer, const CSaveWorld& savw) const { + writer.WriteEncoded(x4_areaId, 32); + writer.WriteEncoded(x10_desiredAreaAssetId.Value(), 32); + x8_relayTracker->PutTo(writer, savw); + xc_mapWorldInfo->PutTo(writer, savw, x0_mlvlId); + x14_layerState->PutTo(writer); } -void CGameState::WriteBackupBuf() -{ - x218_backupBuf.resize(940); - CBitStreamWriter w(x218_backupBuf.data(), 940); - PutTo(w); +CGameState::GameFileStateInfo CGameState::LoadGameFileState(const u8* data) { + CBitStreamReader stream(data, 4096); + GameFileStateInfo ret; + + for (u32 i = 0; i < 128; i++) + stream.ReadEncoded(8); + ret.x14_timestamp = stream.ReadEncoded(32); + + ret.x20_hardMode = stream.ReadEncoded(1); + stream.ReadEncoded(1); + CAssetId origMLVL = stream.ReadEncoded(32); + ret.x8_mlvlId = g_ResFactory->TranslateOriginalToNew(origMLVL); + + BitsToDouble conv; + conv.low = stream.ReadEncoded(32); + conv.high = stream.ReadEncoded(32); + ret.x0_playTime = conv.doub; + + CPlayerState playerState(stream); + ret.x10_energyTanks = playerState.GetItemCapacity(CPlayerState::EItemType::EnergyTanks); + + u32 itemPercent; + if (origMLVL == 0x158EFE17) + itemPercent = 0; + else + itemPercent = playerState.CalculateItemCollectionRate() * 100 / playerState.GetPickupTotal(); + + ret.x18_itemPercent = itemPercent; + + float scanPercent; + if (playerState.GetTotalLogScans() == 0) + scanPercent = 0.f; + else + scanPercent = 100.f * playerState.GetLogScans() / float(playerState.GetTotalLogScans()); + ret.x1c_scanPercent = scanPercent; + + return ret; } -void CGameState::PutTo(CBitStreamWriter& writer) const -{ - for (u32 i = 0; i < 128; i++) - writer.WriteEncoded(x0_[i], 8); - - writer.WriteEncoded(CBasics::ToWiiTime(std::chrono::system_clock::now()) / CBasics::TICKS_PER_SECOND, 32); - writer.WriteEncoded(x228_24_hardMode, 1); - writer.WriteEncoded(x228_25_initPowerupsAtFirstSpawn, 1); - writer.WriteEncoded(g_ResFactory->TranslateNewToOriginal(x84_mlvlId).Value(), 32); - - BitsToDouble conv; - conv.doub = xa0_playTime; - writer.WriteEncoded(conv.low, 32); - writer.WriteEncoded(conv.high, 32); - - x98_playerState->PutTo(writer); - x17c_gameOptions.PutTo(writer); - x1f8_hintOptions.PutTo(writer); - - const auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); - for (const auto& memWorld : memWorlds) - { - TLockedToken saveWorld = - g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), memWorld.second.GetSaveWorldAssetId()}); - const CWorldState& wld = const_cast(*this).StateForWorld(memWorld.first); - wld.PutTo(writer, *saveWorld); - } +CGameState::CGameState() { + x98_playerState = std::make_shared(); + x9c_transManager = std::make_shared(); + x228_25_initPowerupsAtFirstSpawn = true; + if (g_MemoryCardSys) + InitializeMemoryStates(); } -void CGameState::SetCurrentWorldId(CAssetId id) -{ - StateForWorld(id); - x84_mlvlId = id; - MP1::CMain::EnsureWorldPakReady(x84_mlvlId); +CGameState::CGameState(CBitStreamReader& stream, u32 saveIdx) : x20c_saveFileIdx(saveIdx) { + x9c_transManager = std::make_shared(); + x228_25_initPowerupsAtFirstSpawn = true; + + for (u32 i = 0; i < 128; i++) + x0_[i] = stream.ReadEncoded(8); + stream.ReadEncoded(32); + + x228_24_hardMode = stream.ReadEncoded(1); + x228_25_initPowerupsAtFirstSpawn = stream.ReadEncoded(1); + x84_mlvlId = g_ResFactory->TranslateOriginalToNew(stream.ReadEncoded(32)); + MP1::CMain::EnsureWorldPakReady(x84_mlvlId); + + BitsToDouble conv; + conv.low = stream.ReadEncoded(32); + conv.high = stream.ReadEncoded(32); + xa0_playTime = conv.doub; + + x98_playerState = std::make_shared(stream); + + x17c_gameOptions = CGameOptions(stream); + x1f8_hintOptions = CHintOptions(stream); + + const auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); + x88_worldStates.reserve(memWorlds.size()); + for (const auto& memWorld : memWorlds) { + TLockedToken saveWorld = + g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), memWorld.second.GetSaveWorldAssetId()}); + x88_worldStates.emplace_back(stream, memWorld.first, *saveWorld); + } + + InitializeMemoryWorlds(); + WriteBackupBuf(); } -void CGameState::SetTotalPlayTime(float time) -{ - xa0_playTime = zeus::clamp(0.0, time, 359999.0); +void CGameState::ReadPersistentOptions(CBitStreamReader& r) { xa8_systemOptions = CPersistentOptions(r); } + +void CGameState::ImportPersistentOptions(const CPersistentOptions& opts) { + if (opts.xd0_24_fusionLinked) + xa8_systemOptions.xd0_24_fusionLinked = true; + if (opts.xd0_27_fusionBeat) + xa8_systemOptions.xd0_27_fusionBeat = true; + if (&opts != &xa8_systemOptions) + memcpy(xa8_systemOptions.x0_nesState, opts.x0_nesState, 98); + xa8_systemOptions.SetLogScanPercent(opts.GetLogScanPercent()); + xa8_systemOptions.SetAllItemsCollected(opts.GetAllItemsCollected()); + xa8_systemOptions.SetPlayerBeatNormalMode(opts.GetPlayerBeatNormalMode()); + xa8_systemOptions.SetPlayerBeatHardMode(opts.GetPlayerBeatHardMode()); } -CWorldState& CGameState::StateForWorld(CAssetId mlvlId) -{ - auto it = x88_worldStates.begin(); - for (; it != x88_worldStates.end() ; ++it) - { - if (it->GetWorldAssetId() == mlvlId) - break; - } - - if (it == x88_worldStates.end()) - { - x88_worldStates.emplace_back(mlvlId); - return x88_worldStates.back(); - } - return *it; +void CGameState::ExportPersistentOptions(CPersistentOptions& opts) const { + if (xa8_systemOptions.xd0_24_fusionLinked) + opts.xd0_24_fusionLinked = true; + if (xa8_systemOptions.xd0_27_fusionBeat) + opts.xd0_27_fusionBeat = true; + if (&opts != &xa8_systemOptions) + memcpy(opts.x0_nesState, xa8_systemOptions.x0_nesState, 98); + opts.SetPlayerFusionSuitActive(xa8_systemOptions.GetPlayerFusionSuitActive()); } -float CGameState::GetHardModeDamageMultiplier() const -{ - return g_tweakGame->GetHardModeDamageMultiplier(); +void CGameState::WriteBackupBuf() { + x218_backupBuf.resize(940); + CBitStreamWriter w(x218_backupBuf.data(), 940); + PutTo(w); } -float CGameState::GetHardModeWeaponMultiplier() const -{ - return g_tweakGame->GetHardModeWeaponMultiplier(); +void CGameState::PutTo(CBitStreamWriter& writer) const { + for (u32 i = 0; i < 128; i++) + writer.WriteEncoded(x0_[i], 8); + + writer.WriteEncoded(CBasics::ToWiiTime(std::chrono::system_clock::now()) / CBasics::TICKS_PER_SECOND, 32); + writer.WriteEncoded(x228_24_hardMode, 1); + writer.WriteEncoded(x228_25_initPowerupsAtFirstSpawn, 1); + writer.WriteEncoded(g_ResFactory->TranslateNewToOriginal(x84_mlvlId).Value(), 32); + + BitsToDouble conv; + conv.doub = xa0_playTime; + writer.WriteEncoded(conv.low, 32); + writer.WriteEncoded(conv.high, 32); + + x98_playerState->PutTo(writer); + x17c_gameOptions.PutTo(writer); + x1f8_hintOptions.PutTo(writer); + + const auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); + for (const auto& memWorld : memWorlds) { + TLockedToken saveWorld = + g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), memWorld.second.GetSaveWorldAssetId()}); + const CWorldState& wld = const_cast(*this).StateForWorld(memWorld.first); + wld.PutTo(writer, *saveWorld); + } } -void CGameState::InitializeMemoryWorlds() -{ - const auto& memoryWorlds = g_MemoryCardSys->GetMemoryWorlds(); - for (const auto& wld : memoryWorlds) - { - const auto& layerState = StateForWorld(wld.first).GetLayerState(); - layerState->InitializeWorldLayers(wld.second.GetDefaultLayerStates()); - } +void CGameState::SetCurrentWorldId(CAssetId id) { + StateForWorld(id); + x84_mlvlId = id; + MP1::CMain::EnsureWorldPakReady(x84_mlvlId); } -void CGameState::InitializeMemoryStates() -{ - x98_playerState->InitializeScanTimes(); - x1f8_hintOptions.InitializeMemoryState(); - InitializeMemoryWorlds(); - WriteBackupBuf(); +void CGameState::SetTotalPlayTime(float time) { xa0_playTime = zeus::clamp(0.0, time, 359999.0); } + +CWorldState& CGameState::StateForWorld(CAssetId mlvlId) { + auto it = x88_worldStates.begin(); + for (; it != x88_worldStates.end(); ++it) { + if (it->GetWorldAssetId() == mlvlId) + break; + } + + if (it == x88_worldStates.end()) { + x88_worldStates.emplace_back(mlvlId); + return x88_worldStates.back(); + } + return *it; } +float CGameState::GetHardModeDamageMultiplier() const { return g_tweakGame->GetHardModeDamageMultiplier(); } + +float CGameState::GetHardModeWeaponMultiplier() const { return g_tweakGame->GetHardModeWeaponMultiplier(); } + +void CGameState::InitializeMemoryWorlds() { + const auto& memoryWorlds = g_MemoryCardSys->GetMemoryWorlds(); + for (const auto& wld : memoryWorlds) { + const auto& layerState = StateForWorld(wld.first).GetLayerState(); + layerState->InitializeWorldLayers(wld.second.GetDefaultLayerStates()); + } } + +void CGameState::InitializeMemoryStates() { + x98_playerState->InitializeScanTimes(); + x1f8_hintOptions.InitializeMemoryState(); + InitializeMemoryWorlds(); + WriteBackupBuf(); +} + +} // namespace urde diff --git a/Runtime/CGameState.hpp b/Runtime/CGameState.hpp index f62098e73..760c75f33 100644 --- a/Runtime/CGameState.hpp +++ b/Runtime/CGameState.hpp @@ -10,135 +10,124 @@ #include "World/CWorld.hpp" #include "DataSpec/DNACommon/DNACommon.hpp" -namespace urde -{ +namespace urde { class CSaveWorldMemory; -class CWorldLayerState -{ - friend class CSaveWorldIntermediate; - std::vector x0_areaLayers; - DataSpec::WordBitmap x10_saveLayers; +class CWorldLayerState { + friend class CSaveWorldIntermediate; + std::vector x0_areaLayers; + DataSpec::WordBitmap x10_saveLayers; public: - CWorldLayerState() = default; - CWorldLayerState(CBitStreamReader& reader, const CSaveWorld& saveWorld); + CWorldLayerState() = default; + CWorldLayerState(CBitStreamReader& reader, const CSaveWorld& saveWorld); - bool IsLayerActive(int areaIdx, int layerIdx) const - { - return ((x0_areaLayers[areaIdx].m_layerBits >> layerIdx) & 1); - } + bool IsLayerActive(int areaIdx, int layerIdx) const { return ((x0_areaLayers[areaIdx].m_layerBits >> layerIdx) & 1); } - void SetLayerActive(int areaIdx, int layerIdx, bool active) - { - if (active) - x0_areaLayers[areaIdx].m_layerBits |= uint64_t(1) << layerIdx; - else - x0_areaLayers[areaIdx].m_layerBits &= ~(uint64_t(1) << layerIdx); - } + void SetLayerActive(int areaIdx, int layerIdx, bool active) { + if (active) + x0_areaLayers[areaIdx].m_layerBits |= uint64_t(1) << layerIdx; + else + x0_areaLayers[areaIdx].m_layerBits &= ~(uint64_t(1) << layerIdx); + } - void InitializeWorldLayers(const std::vector& layers); + void InitializeWorldLayers(const std::vector& layers); - u32 GetAreaLayerCount(int areaIdx) const { return x0_areaLayers[areaIdx].m_layerCount; } - u32 GetAreaCount() const { return x0_areaLayers.size(); } + u32 GetAreaLayerCount(int areaIdx) const { return x0_areaLayers[areaIdx].m_layerCount; } + u32 GetAreaCount() const { return x0_areaLayers.size(); } - void PutTo(CBitStreamWriter& writer) const; + void PutTo(CBitStreamWriter& writer) const; }; -class CWorldState -{ - CAssetId x0_mlvlId; - TAreaId x4_areaId = kInvalidAreaId; - std::shared_ptr x8_relayTracker; - std::shared_ptr xc_mapWorldInfo; - CAssetId x10_desiredAreaAssetId; - std::shared_ptr x14_layerState; +class CWorldState { + CAssetId x0_mlvlId; + TAreaId x4_areaId = kInvalidAreaId; + std::shared_ptr x8_relayTracker; + std::shared_ptr xc_mapWorldInfo; + CAssetId x10_desiredAreaAssetId; + std::shared_ptr x14_layerState; public: - explicit CWorldState(CAssetId id); - CWorldState(CBitStreamReader& reader, CAssetId mlvlId, const CSaveWorld& saveWorld); - CAssetId GetWorldAssetId() const { return x0_mlvlId; } - void SetAreaId(TAreaId aid) { x4_areaId = aid; } - TAreaId GetCurrentAreaId() const { return x4_areaId; } - CAssetId GetDesiredAreaAssetId() const { return x10_desiredAreaAssetId; } - void SetDesiredAreaAssetId(CAssetId id) { x10_desiredAreaAssetId = id; } - const std::shared_ptr& RelayTracker() const { return x8_relayTracker; } - const std::shared_ptr& MapWorldInfo() const { return xc_mapWorldInfo; } - const std::shared_ptr& GetLayerState() const { return x14_layerState; } - void PutTo(CBitStreamWriter& writer, const CSaveWorld& savw) const; + explicit CWorldState(CAssetId id); + CWorldState(CBitStreamReader& reader, CAssetId mlvlId, const CSaveWorld& saveWorld); + CAssetId GetWorldAssetId() const { return x0_mlvlId; } + void SetAreaId(TAreaId aid) { x4_areaId = aid; } + TAreaId GetCurrentAreaId() const { return x4_areaId; } + CAssetId GetDesiredAreaAssetId() const { return x10_desiredAreaAssetId; } + void SetDesiredAreaAssetId(CAssetId id) { x10_desiredAreaAssetId = id; } + const std::shared_ptr& RelayTracker() const { return x8_relayTracker; } + const std::shared_ptr& MapWorldInfo() const { return xc_mapWorldInfo; } + const std::shared_ptr& GetLayerState() const { return x14_layerState; } + void PutTo(CBitStreamWriter& writer, const CSaveWorld& savw) const; }; -class CGameState -{ - friend class CStateManager; +class CGameState { + friend class CStateManager; - bool x0_[128] = {}; - u32 x80_; - CAssetId x84_mlvlId; - std::vector x88_worldStates; - std::shared_ptr x98_playerState; - std::shared_ptr x9c_transManager; - double xa0_playTime = 0.0; - CPersistentOptions xa8_systemOptions; - CGameOptions x17c_gameOptions; - CHintOptions x1f8_hintOptions; - u32 x20c_saveFileIdx = 0; - u64 x210_cardSerial = 0; - std::vector x218_backupBuf; + bool x0_[128] = {}; + u32 x80_; + CAssetId x84_mlvlId; + std::vector x88_worldStates; + std::shared_ptr x98_playerState; + std::shared_ptr x9c_transManager; + double xa0_playTime = 0.0; + CPersistentOptions xa8_systemOptions; + CGameOptions x17c_gameOptions; + CHintOptions x1f8_hintOptions; + u32 x20c_saveFileIdx = 0; + u64 x210_cardSerial = 0; + std::vector x218_backupBuf; - union { - struct - { - bool x228_24_hardMode : 1; - bool x228_25_initPowerupsAtFirstSpawn : 1; - }; - u8 _dummy = 0; + union { + struct { + bool x228_24_hardMode : 1; + bool x228_25_initPowerupsAtFirstSpawn : 1; }; + u8 _dummy = 0; + }; public: - CGameState(); - CGameState(CBitStreamReader& stream, u32 saveIdx); - void SetCurrentWorldId(CAssetId id); - std::shared_ptr GetPlayerState() { return x98_playerState; } - std::shared_ptr GetWorldTransitionManager() { return x9c_transManager; } - void SetTotalPlayTime(float time); - CPersistentOptions& SystemOptions() { return xa8_systemOptions; } - CGameOptions& GameOptions() { return x17c_gameOptions; } - CHintOptions& HintOptions() { return x1f8_hintOptions; } - CWorldState& StateForWorld(CAssetId mlvlId); - CWorldState& CurrentWorldState() { return StateForWorld(x84_mlvlId); } - CAssetId CurrentWorldAssetId() const { return x84_mlvlId; } - void SetHardMode(bool v) { x228_24_hardMode = v; } - bool GetHardMode() const { return x228_24_hardMode; } - void ReadPersistentOptions(CBitStreamReader& r); - void SetPersistentOptions(const CPersistentOptions& opts) { xa8_systemOptions = opts; } - void ImportPersistentOptions(const CPersistentOptions& opts); - void ExportPersistentOptions(CPersistentOptions& opts) const; - void SetGameOptions(const CGameOptions& opts) { x17c_gameOptions = opts; } - void WriteBackupBuf(); - std::vector& BackupBuf() { return x218_backupBuf; } - u32 GetFileIdx() const { return x20c_saveFileIdx; } - void SetFileIdx(u32 idx) { x20c_saveFileIdx = idx; } - void SetCardSerial(u64 serial) { x210_cardSerial = serial; } - u64 GetCardSerial() const { return x210_cardSerial; } - void PutTo(CBitStreamWriter& writer) const; - float GetHardModeDamageMultiplier() const; - float GetHardModeWeaponMultiplier() const; - void InitializeMemoryWorlds(); - void InitializeMemoryStates(); + CGameState(); + CGameState(CBitStreamReader& stream, u32 saveIdx); + void SetCurrentWorldId(CAssetId id); + std::shared_ptr GetPlayerState() { return x98_playerState; } + std::shared_ptr GetWorldTransitionManager() { return x9c_transManager; } + void SetTotalPlayTime(float time); + CPersistentOptions& SystemOptions() { return xa8_systemOptions; } + CGameOptions& GameOptions() { return x17c_gameOptions; } + CHintOptions& HintOptions() { return x1f8_hintOptions; } + CWorldState& StateForWorld(CAssetId mlvlId); + CWorldState& CurrentWorldState() { return StateForWorld(x84_mlvlId); } + CAssetId CurrentWorldAssetId() const { return x84_mlvlId; } + void SetHardMode(bool v) { x228_24_hardMode = v; } + bool GetHardMode() const { return x228_24_hardMode; } + void ReadPersistentOptions(CBitStreamReader& r); + void SetPersistentOptions(const CPersistentOptions& opts) { xa8_systemOptions = opts; } + void ImportPersistentOptions(const CPersistentOptions& opts); + void ExportPersistentOptions(CPersistentOptions& opts) const; + void SetGameOptions(const CGameOptions& opts) { x17c_gameOptions = opts; } + void WriteBackupBuf(); + std::vector& BackupBuf() { return x218_backupBuf; } + u32 GetFileIdx() const { return x20c_saveFileIdx; } + void SetFileIdx(u32 idx) { x20c_saveFileIdx = idx; } + void SetCardSerial(u64 serial) { x210_cardSerial = serial; } + u64 GetCardSerial() const { return x210_cardSerial; } + void PutTo(CBitStreamWriter& writer) const; + float GetHardModeDamageMultiplier() const; + float GetHardModeWeaponMultiplier() const; + void InitializeMemoryWorlds(); + void InitializeMemoryStates(); - struct GameFileStateInfo - { - double x0_playTime; - CAssetId x8_mlvlId; - float xc_health; - u32 x10_energyTanks; - u32 x14_timestamp; - u32 x18_itemPercent; - float x1c_scanPercent; - bool x20_hardMode; - }; - static GameFileStateInfo LoadGameFileState(const u8* data); + struct GameFileStateInfo { + double x0_playTime; + CAssetId x8_mlvlId; + float xc_health; + u32 x10_energyTanks; + u32 x14_timestamp; + u32 x18_itemPercent; + float x1c_scanPercent; + bool x20_hardMode; + }; + static GameFileStateInfo LoadGameFileState(const u8* data); }; } // namespace urde - diff --git a/Runtime/CIOWin.hpp b/Runtime/CIOWin.hpp index f7fc26449..14b69b75e 100644 --- a/Runtime/CIOWin.hpp +++ b/Runtime/CIOWin.hpp @@ -5,32 +5,24 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CArchitectureMessage; class CArchitectureQueue; -class CIOWin -{ - std::string x4_name; - size_t m_nameHash; +class CIOWin { + std::string x4_name; + size_t m_nameHash; + public: - enum class EMessageReturn - { - Normal = 0, - Exit = 1, - RemoveIOWinAndExit = 2, - RemoveIOWin = 3 - }; - virtual ~CIOWin() {} - CIOWin(std::string_view name) : x4_name(name) { m_nameHash = std::hash()(name); } - virtual EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&)=0; - virtual bool GetIsContinueDraw() const { return true; } - virtual void Draw() const {} - virtual void PreDraw() const {} - std::string_view GetName() const { return x4_name; } - size_t GetNameHash() const { return m_nameHash; } + enum class EMessageReturn { Normal = 0, Exit = 1, RemoveIOWinAndExit = 2, RemoveIOWin = 3 }; + virtual ~CIOWin() {} + CIOWin(std::string_view name) : x4_name(name) { m_nameHash = std::hash()(name); } + virtual EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&) = 0; + virtual bool GetIsContinueDraw() const { return true; } + virtual void Draw() const {} + virtual void PreDraw() const {} + std::string_view GetName() const { return x4_name; } + size_t GetNameHash() const { return m_nameHash; } }; -} - +} // namespace urde diff --git a/Runtime/CIOWinManager.cpp b/Runtime/CIOWinManager.cpp index aaa0e4ec6..dde1e8a4c 100644 --- a/Runtime/CIOWinManager.cpp +++ b/Runtime/CIOWinManager.cpp @@ -2,291 +2,251 @@ #include "CArchitectureMessage.hpp" #include "CIOWin.hpp" -namespace urde -{ +namespace urde { -bool CIOWinManager::OnIOWinMessage(const CArchitectureMessage& msg) -{ - switch (msg.GetType()) - { - case EArchMsgType::RemoveIOWin: - { - const CArchMsgParmVoidPtr& parm = MakeMsg::GetParmDeleteIOWin(msg); - CIOWin* iow = FindIOWin(*static_cast(parm.x4_parm1)); - if (iow) - RemoveIOWin(iow); - return false; - } - case EArchMsgType::CreateIOWin: - { - const CArchMsgParmInt32Int32IOWin& parm = MakeMsg::GetParmCreateIOWin(msg); - AddIOWin(parm.xc_parm3, parm.x4_parm1, parm.x8_parm2); - return false; - } - case EArchMsgType::ChangeIOWinPriority: - { - const CArchMsgParmInt32Int32VoidPtr& parm = MakeMsg::GetParmChangeIOWinPriority(msg); - CIOWin* iow = FindIOWin(*static_cast(parm.xc_parm3)); - if (iow) - ChangeIOWinPriority(iow, parm.x4_parm1, parm.x8_parm2); - return false; - } - case EArchMsgType::RemoveAllIOWins: - { - RemoveAllIOWins(); - return true; - } - default: break; - } +bool CIOWinManager::OnIOWinMessage(const CArchitectureMessage& msg) { + switch (msg.GetType()) { + case EArchMsgType::RemoveIOWin: { + const CArchMsgParmVoidPtr& parm = MakeMsg::GetParmDeleteIOWin(msg); + CIOWin* iow = FindIOWin(*static_cast(parm.x4_parm1)); + if (iow) + RemoveIOWin(iow); return false; -} - -void CIOWinManager::Draw() const -{ - for (IOWinPQNode* node = x0_drawRoot ; node ; node = node->x8_next) - { - CIOWin* iow = node->GetIOWin(); - iow->PreDraw(); - if (!iow->GetIsContinueDraw()) - break; - } - for (IOWinPQNode* node = x0_drawRoot ; node ; node = node->x8_next) - { - CIOWin* iow = node->GetIOWin(); - iow->Draw(); - if (!iow->GetIsContinueDraw()) - break; - } -} - -bool CIOWinManager::DistributeOneMessage(const CArchitectureMessage& msg, - CArchitectureQueue& queue) -{ - CArchitectureMessage tmpMsg = msg; - for (IOWinPQNode* node = x4_pumpRoot ; node ;) - { - IOWinPQNode* next = node->x8_next; - CIOWin* iow = node->GetIOWin(); - CIOWin::EMessageReturn mret = iow->OnMessage(tmpMsg, x8_localGatherQueue); - - while (x8_localGatherQueue) - { - tmpMsg = x8_localGatherQueue.Pop(); - if (tmpMsg.GetTarget() == EArchMsgTarget::IOWinManager) - { - if (OnIOWinMessage(tmpMsg)) - { - x8_localGatherQueue.Clear(); - queue.Clear(); - return true; - } - } - else - queue.Push(std::move(tmpMsg)); - } - - switch (mret) - { - case CIOWin::EMessageReturn::RemoveIOWinAndExit: - case CIOWin::EMessageReturn::RemoveIOWin: - RemoveIOWin(iow); - default: break; - } - - switch (mret) - { - case CIOWin::EMessageReturn::Exit: - case CIOWin::EMessageReturn::RemoveIOWinAndExit: - return false; - default: break; - } - - node = next; - } - + } + case EArchMsgType::CreateIOWin: { + const CArchMsgParmInt32Int32IOWin& parm = MakeMsg::GetParmCreateIOWin(msg); + AddIOWin(parm.xc_parm3, parm.x4_parm1, parm.x8_parm2); return false; + } + case EArchMsgType::ChangeIOWinPriority: { + const CArchMsgParmInt32Int32VoidPtr& parm = MakeMsg::GetParmChangeIOWinPriority(msg); + CIOWin* iow = FindIOWin(*static_cast(parm.xc_parm3)); + if (iow) + ChangeIOWinPriority(iow, parm.x4_parm1, parm.x8_parm2); + return false; + } + case EArchMsgType::RemoveAllIOWins: { + RemoveAllIOWins(); + return true; + } + default: + break; + } + return false; } -void CIOWinManager::PumpMessages(CArchitectureQueue& queue) -{ - while (queue) - { - CArchitectureMessage msg = queue.Pop(); - if (DistributeOneMessage(msg, queue)) - break; - } +void CIOWinManager::Draw() const { + for (IOWinPQNode* node = x0_drawRoot; node; node = node->x8_next) { + CIOWin* iow = node->GetIOWin(); + iow->PreDraw(); + if (!iow->GetIsContinueDraw()) + break; + } + for (IOWinPQNode* node = x0_drawRoot; node; node = node->x8_next) { + CIOWin* iow = node->GetIOWin(); + iow->Draw(); + if (!iow->GetIsContinueDraw()) + break; + } } -CIOWin* CIOWinManager::FindIOWin(std::string_view name) -{ - size_t findHash = std::hash()(name); +bool CIOWinManager::DistributeOneMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + CArchitectureMessage tmpMsg = msg; + for (IOWinPQNode* node = x4_pumpRoot; node;) { + IOWinPQNode* next = node->x8_next; + CIOWin* iow = node->GetIOWin(); + CIOWin::EMessageReturn mret = iow->OnMessage(tmpMsg, x8_localGatherQueue); - for (IOWinPQNode* node = x4_pumpRoot ; node ; node = node->x8_next) - { - CIOWin* iow = node->GetIOWin(); - if (iow->GetNameHash() == findHash) - return iow; - } - - for (IOWinPQNode* node = x0_drawRoot ; node ; node = node->x8_next) - { - CIOWin* iow = node->GetIOWin(); - if (iow->GetNameHash() == findHash) - return iow; - } - - return nullptr; -} - -std::shared_ptr CIOWinManager::FindAndShareIOWin(std::string_view name) -{ - size_t findHash = std::hash()(name); - - for (IOWinPQNode* node = x4_pumpRoot ; node ; node = node->x8_next) - { - std::shared_ptr iow = node->ShareIOWin(); - if (iow->GetNameHash() == findHash) - return iow; - } - - for (IOWinPQNode* node = x0_drawRoot ; node ; node = node->x8_next) - { - std::shared_ptr iow = node->ShareIOWin(); - if (iow->GetNameHash() == findHash) - return iow; - } - - return std::shared_ptr(); -} - -void CIOWinManager::ChangeIOWinPriority(CIOWin* toChange, int pumpPrio, int drawPrio) -{ - IOWinPQNode* prevNode = nullptr; - for (IOWinPQNode* node = x4_pumpRoot ; node ; node = node->x8_next) - { - CIOWin* iow = node->GetIOWin(); - if (iow == toChange) - { - if (prevNode) - prevNode->x8_next = node->x8_next; - node->x4_prio = pumpPrio; - IOWinPQNode* testNode = x4_pumpRoot; - IOWinPQNode* testPrevNode = nullptr; - while (testNode->x4_prio > pumpPrio) - { - testPrevNode = testNode; - testNode = testNode->x8_next; - } - node->x8_next = testNode; - if (testPrevNode) - testPrevNode->x8_next = node; - else - x4_pumpRoot = node; - break; + while (x8_localGatherQueue) { + tmpMsg = x8_localGatherQueue.Pop(); + if (tmpMsg.GetTarget() == EArchMsgTarget::IOWinManager) { + if (OnIOWinMessage(tmpMsg)) { + x8_localGatherQueue.Clear(); + queue.Clear(); + return true; } - prevNode = node; + } else + queue.Push(std::move(tmpMsg)); } - prevNode = nullptr; - for (IOWinPQNode* node = x0_drawRoot ; node ; node = node->x8_next) - { - CIOWin* iow = node->GetIOWin(); - if (iow == toChange) - { - if (prevNode) - prevNode->x8_next = node->x8_next; - node->x4_prio = drawPrio; - IOWinPQNode* testNode = x0_drawRoot; - IOWinPQNode* testPrevNode = nullptr; - while (testNode->x4_prio > drawPrio) - { - testPrevNode = testNode; - testNode = testNode->x8_next; - } - node->x8_next = testNode; - if (testPrevNode) - testPrevNode->x8_next = node; - else - x0_drawRoot = node; - break; - } - prevNode = node; + switch (mret) { + case CIOWin::EMessageReturn::RemoveIOWinAndExit: + case CIOWin::EMessageReturn::RemoveIOWin: + RemoveIOWin(iow); + default: + break; } + + switch (mret) { + case CIOWin::EMessageReturn::Exit: + case CIOWin::EMessageReturn::RemoveIOWinAndExit: + return false; + default: + break; + } + + node = next; + } + + return false; } -void CIOWinManager::RemoveAllIOWins() -{ - for (IOWinPQNode* node = x0_drawRoot ; node ;) - { - IOWinPQNode* n = node; - node = n->x8_next; - delete n; - } - x0_drawRoot = nullptr; - for (IOWinPQNode* node = x4_pumpRoot ; node ;) - { - IOWinPQNode* n = node; - node = n->x8_next; - delete n; - } - x4_pumpRoot = nullptr; +void CIOWinManager::PumpMessages(CArchitectureQueue& queue) { + while (queue) { + CArchitectureMessage msg = queue.Pop(); + if (DistributeOneMessage(msg, queue)) + break; + } } -void CIOWinManager::RemoveIOWin(CIOWin* chIow) -{ - IOWinPQNode* prevNode = nullptr; - for (IOWinPQNode* node = x4_pumpRoot ; node ; node = node->x8_next) - { - CIOWin* iow = node->GetIOWin(); - if (iow == chIow) - { - if (prevNode) - prevNode->x8_next = node->x8_next; - else - x4_pumpRoot = node->x8_next; - delete node; - break; - } - prevNode = node; +CIOWin* CIOWinManager::FindIOWin(std::string_view name) { + size_t findHash = std::hash()(name); + + for (IOWinPQNode* node = x4_pumpRoot; node; node = node->x8_next) { + CIOWin* iow = node->GetIOWin(); + if (iow->GetNameHash() == findHash) + return iow; + } + + for (IOWinPQNode* node = x0_drawRoot; node; node = node->x8_next) { + CIOWin* iow = node->GetIOWin(); + if (iow->GetNameHash() == findHash) + return iow; + } + + return nullptr; +} + +std::shared_ptr CIOWinManager::FindAndShareIOWin(std::string_view name) { + size_t findHash = std::hash()(name); + + for (IOWinPQNode* node = x4_pumpRoot; node; node = node->x8_next) { + std::shared_ptr iow = node->ShareIOWin(); + if (iow->GetNameHash() == findHash) + return iow; + } + + for (IOWinPQNode* node = x0_drawRoot; node; node = node->x8_next) { + std::shared_ptr iow = node->ShareIOWin(); + if (iow->GetNameHash() == findHash) + return iow; + } + + return std::shared_ptr(); +} + +void CIOWinManager::ChangeIOWinPriority(CIOWin* toChange, int pumpPrio, int drawPrio) { + IOWinPQNode* prevNode = nullptr; + for (IOWinPQNode* node = x4_pumpRoot; node; node = node->x8_next) { + CIOWin* iow = node->GetIOWin(); + if (iow == toChange) { + if (prevNode) + prevNode->x8_next = node->x8_next; + node->x4_prio = pumpPrio; + IOWinPQNode* testNode = x4_pumpRoot; + IOWinPQNode* testPrevNode = nullptr; + while (testNode->x4_prio > pumpPrio) { + testPrevNode = testNode; + testNode = testNode->x8_next; + } + node->x8_next = testNode; + if (testPrevNode) + testPrevNode->x8_next = node; + else + x4_pumpRoot = node; + break; } + prevNode = node; + } - prevNode = nullptr; - for (IOWinPQNode* node = x0_drawRoot ; node ; node = node->x8_next) - { - CIOWin* iow = node->GetIOWin(); - if (iow == chIow) - { - if (prevNode) - prevNode->x8_next = node->x8_next; - else - x0_drawRoot = node->x8_next; - delete node; - break; - } - prevNode = node; + prevNode = nullptr; + for (IOWinPQNode* node = x0_drawRoot; node; node = node->x8_next) { + CIOWin* iow = node->GetIOWin(); + if (iow == toChange) { + if (prevNode) + prevNode->x8_next = node->x8_next; + node->x4_prio = drawPrio; + IOWinPQNode* testNode = x0_drawRoot; + IOWinPQNode* testPrevNode = nullptr; + while (testNode->x4_prio > drawPrio) { + testPrevNode = testNode; + testNode = testNode->x8_next; + } + node->x8_next = testNode; + if (testPrevNode) + testPrevNode->x8_next = node; + else + x0_drawRoot = node; + break; } + prevNode = node; + } } -void CIOWinManager::AddIOWin(std::weak_ptr chIow, int pumpPrio, int drawPrio) -{ - IOWinPQNode* node; - IOWinPQNode* prevNode = nullptr; - for (node = x4_pumpRoot ; node && pumpPrio < node->x4_prio ; node = node->x8_next) - prevNode = node; - IOWinPQNode* newNode = new IOWinPQNode(chIow, pumpPrio, node); - if (prevNode) - prevNode->x8_next = newNode; - else - x4_pumpRoot = newNode; - - prevNode = nullptr; - for (node = x0_drawRoot ; node && drawPrio < node->x4_prio ; node = node->x8_next) - prevNode = node; - newNode = new IOWinPQNode(chIow, drawPrio, node); - if (prevNode) - prevNode->x8_next = newNode; - else - x0_drawRoot = newNode; +void CIOWinManager::RemoveAllIOWins() { + for (IOWinPQNode* node = x0_drawRoot; node;) { + IOWinPQNode* n = node; + node = n->x8_next; + delete n; + } + x0_drawRoot = nullptr; + for (IOWinPQNode* node = x4_pumpRoot; node;) { + IOWinPQNode* n = node; + node = n->x8_next; + delete n; + } + x4_pumpRoot = nullptr; } +void CIOWinManager::RemoveIOWin(CIOWin* chIow) { + IOWinPQNode* prevNode = nullptr; + for (IOWinPQNode* node = x4_pumpRoot; node; node = node->x8_next) { + CIOWin* iow = node->GetIOWin(); + if (iow == chIow) { + if (prevNode) + prevNode->x8_next = node->x8_next; + else + x4_pumpRoot = node->x8_next; + delete node; + break; + } + prevNode = node; + } + + prevNode = nullptr; + for (IOWinPQNode* node = x0_drawRoot; node; node = node->x8_next) { + CIOWin* iow = node->GetIOWin(); + if (iow == chIow) { + if (prevNode) + prevNode->x8_next = node->x8_next; + else + x0_drawRoot = node->x8_next; + delete node; + break; + } + prevNode = node; + } } + +void CIOWinManager::AddIOWin(std::weak_ptr chIow, int pumpPrio, int drawPrio) { + IOWinPQNode* node; + IOWinPQNode* prevNode = nullptr; + for (node = x4_pumpRoot; node && pumpPrio < node->x4_prio; node = node->x8_next) + prevNode = node; + IOWinPQNode* newNode = new IOWinPQNode(chIow, pumpPrio, node); + if (prevNode) + prevNode->x8_next = newNode; + else + x4_pumpRoot = newNode; + + prevNode = nullptr; + for (node = x0_drawRoot; node && drawPrio < node->x4_prio; node = node->x8_next) + prevNode = node; + newNode = new IOWinPQNode(chIow, drawPrio, node); + if (prevNode) + prevNode->x8_next = newNode; + else + x0_drawRoot = newNode; +} + +} // namespace urde diff --git a/Runtime/CIOWinManager.hpp b/Runtime/CIOWinManager.hpp index 18e435586..b2b645995 100644 --- a/Runtime/CIOWinManager.hpp +++ b/Runtime/CIOWinManager.hpp @@ -6,38 +6,34 @@ #include "rstl.hpp" #include "CArchitectureQueue.hpp" -namespace urde -{ +namespace urde { + +class CIOWinManager { + struct IOWinPQNode { + std::shared_ptr x0_iowin; + int x4_prio; + CIOWinManager::IOWinPQNode* x8_next = nullptr; + IOWinPQNode(std::weak_ptr iowin, int prio, CIOWinManager::IOWinPQNode* next) + : x0_iowin(iowin), x4_prio(prio), x8_next(next) {} + std::shared_ptr ShareIOWin() const { return std::shared_ptr(x0_iowin); } + CIOWin* GetIOWin() const { return x0_iowin.get(); } + }; + IOWinPQNode* x0_drawRoot = nullptr; + IOWinPQNode* x4_pumpRoot = nullptr; + CArchitectureQueue x8_localGatherQueue; -class CIOWinManager -{ - struct IOWinPQNode - { - std::shared_ptr x0_iowin; - int x4_prio; - CIOWinManager::IOWinPQNode* x8_next = nullptr; - IOWinPQNode(std::weak_ptr iowin, int prio, - CIOWinManager::IOWinPQNode* next) - : x0_iowin(iowin), x4_prio(prio), x8_next(next) {} - std::shared_ptr ShareIOWin() const {return std::shared_ptr(x0_iowin);} - CIOWin* GetIOWin() const {return x0_iowin.get();} - }; - IOWinPQNode* x0_drawRoot = nullptr; - IOWinPQNode* x4_pumpRoot = nullptr; - CArchitectureQueue x8_localGatherQueue; public: - bool OnIOWinMessage(const CArchitectureMessage& msg); - void Draw() const; - bool DistributeOneMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); - void PumpMessages(CArchitectureQueue& queue); - CIOWin* FindIOWin(std::string_view name); - std::shared_ptr FindAndShareIOWin(std::string_view name); - void ChangeIOWinPriority(CIOWin* toChange, int pumpPrio, int drawPrio); - void RemoveAllIOWins(); - void RemoveIOWin(CIOWin* toRemove); - void AddIOWin(std::weak_ptr toAdd, int pumpPrio, int drawPrio); - bool IsEmpty() const { return x0_drawRoot == nullptr && x4_pumpRoot == nullptr; } + bool OnIOWinMessage(const CArchitectureMessage& msg); + void Draw() const; + bool DistributeOneMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); + void PumpMessages(CArchitectureQueue& queue); + CIOWin* FindIOWin(std::string_view name); + std::shared_ptr FindAndShareIOWin(std::string_view name); + void ChangeIOWinPriority(CIOWin* toChange, int pumpPrio, int drawPrio); + void RemoveAllIOWins(); + void RemoveIOWin(CIOWin* toRemove); + void AddIOWin(std::weak_ptr toAdd, int pumpPrio, int drawPrio); + bool IsEmpty() const { return x0_drawRoot == nullptr && x4_pumpRoot == nullptr; } }; -} - +} // namespace urde diff --git a/Runtime/CInGameTweakManagerBase.hpp b/Runtime/CInGameTweakManagerBase.hpp index 8b3e00fb2..e73ec3275 100644 --- a/Runtime/CInGameTweakManagerBase.hpp +++ b/Runtime/CInGameTweakManagerBase.hpp @@ -5,84 +5,69 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -class CTweakValue -{ +class CTweakValue { public: - struct Audio - { - float x0_fadeIn, x4_fadeOut, x8_volume; - std::string xc_fileName; - CAssetId x1c_res; - Audio(float fadeIn, float fadeOut, float vol, std::string_view fileName, u32 handle) - : x0_fadeIn(fadeIn), x4_fadeOut(fadeOut), x8_volume(vol), xc_fileName(fileName), x1c_res(handle) {} - float GetFadeIn() const { return x0_fadeIn; } - float GetFadeOut() const { return x4_fadeOut; } - float GetVolume() const { return x8_volume; } - std::string_view GetFileName() const { return xc_fileName; } - CAssetId GetResId() const { return x1c_res; } - static Audio None() { return Audio{0.f, 0.f, 0.f, "", 0}; } - }; - enum class EType - { - }; + struct Audio { + float x0_fadeIn, x4_fadeOut, x8_volume; + std::string xc_fileName; + CAssetId x1c_res; + Audio(float fadeIn, float fadeOut, float vol, std::string_view fileName, u32 handle) + : x0_fadeIn(fadeIn), x4_fadeOut(fadeOut), x8_volume(vol), xc_fileName(fileName), x1c_res(handle) {} + float GetFadeIn() const { return x0_fadeIn; } + float GetFadeOut() const { return x4_fadeOut; } + float GetVolume() const { return x8_volume; } + std::string_view GetFileName() const { return xc_fileName; } + CAssetId GetResId() const { return x1c_res; } + static Audio None() { return Audio{0.f, 0.f, 0.f, "", 0}; } + }; + enum class EType {}; + EType x0_type; + std::string x4_key; + std::string x14_str; + Audio x24_audio; + union { + u32 x44_int; + float x44_flt; + }; - EType x0_type; - std::string x4_key; - std::string x14_str; - Audio x24_audio; - union - { - u32 x44_int; - float x44_flt; - }; public: - CTweakValue()=default; - //CTweakValue(CTextInputStream&); - //void PutTo(CTextOutStream&); - std::string_view GetName() const { return x4_key; } - std::string_view GetValueAsString() const; - void SetValueFromString(std::string_view); - const Audio& GetAudio() const { return x24_audio; } - EType GetType() const { return x0_type; } + CTweakValue() = default; + // CTweakValue(CTextInputStream&); + // void PutTo(CTextOutStream&); + std::string_view GetName() const { return x4_key; } + std::string_view GetValueAsString() const; + void SetValueFromString(std::string_view); + const Audio& GetAudio() const { return x24_audio; } + EType GetType() const { return x0_type; } }; -class CInGameTweakManagerBase -{ +class CInGameTweakManagerBase { protected: - std::vector x0_values; + std::vector x0_values; + public: - bool HasTweakValue(std::string_view name) const - { - for (const CTweakValue& val : x0_values) - if (val.GetName() == name) - return true; - return false; - } - - const CTweakValue* GetTweakValue(std::string_view name) const - { - for (const CTweakValue& val : x0_values) - if (val.GetName() == name) - return &val; - return nullptr; - } - - bool ReadFromMemoryCard(std::string_view name) - { + bool HasTweakValue(std::string_view name) const { + for (const CTweakValue& val : x0_values) + if (val.GetName() == name) return true; - } + return false; + } - static std::string GetIdentifierForMidiEvent(CAssetId world, CAssetId area, - std::string_view midiObj) - { - return hecl::Format("World %8.8x Area %8.8x MidiObject: %s", - u32(world.Value()), u32(area.Value()), midiObj.data()); - } + const CTweakValue* GetTweakValue(std::string_view name) const { + for (const CTweakValue& val : x0_values) + if (val.GetName() == name) + return &val; + return nullptr; + } + + bool ReadFromMemoryCard(std::string_view name) { return true; } + + static std::string GetIdentifierForMidiEvent(CAssetId world, CAssetId area, std::string_view midiObj) { + return hecl::Format("World %8.8x Area %8.8x MidiObject: %s", u32(world.Value()), u32(area.Value()), midiObj.data()); + } }; -} - +} // namespace urde diff --git a/Runtime/CMFGameBase.hpp b/Runtime/CMFGameBase.hpp index f41a5b3b1..9599e0f31 100644 --- a/Runtime/CMFGameBase.hpp +++ b/Runtime/CMFGameBase.hpp @@ -2,20 +2,16 @@ #include "CIOWin.hpp" -namespace urde -{ +namespace urde { -class CMFGameBase : public CIOWin -{ +class CMFGameBase : public CIOWin { public: - CMFGameBase(const char* name) : CIOWin(name) {} + CMFGameBase(const char* name) : CIOWin(name) {} }; -class CMFGameLoaderBase : public CIOWin -{ +class CMFGameLoaderBase : public CIOWin { public: - CMFGameLoaderBase(const char* name) : CIOWin(name) {} + CMFGameLoaderBase(const char* name) : CIOWin(name) {} }; -} - +} // namespace urde diff --git a/Runtime/CMainFlowBase.cpp b/Runtime/CMainFlowBase.cpp index 50bbf2c14..45f64c5a9 100644 --- a/Runtime/CMainFlowBase.cpp +++ b/Runtime/CMainFlowBase.cpp @@ -1,26 +1,23 @@ #include "CMainFlowBase.hpp" #include "CArchitectureMessage.hpp" -namespace urde -{ +namespace urde { -CIOWin::EMessageReturn CMainFlowBase::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - switch (msg.GetType()) - { - case EArchMsgType::TimerTick: - AdvanceGameState(queue); - break; - case EArchMsgType::SetGameState: - { - const CArchMsgParmInt32& state = MakeMsg::GetParmNewGameflowState(msg); - x14_gameState = EClientFlowStates(state.x4_parm); - SetGameState(x14_gameState, queue); - return EMessageReturn::Exit; - } - default: break; - } - return EMessageReturn::Normal; +CIOWin::EMessageReturn CMainFlowBase::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + switch (msg.GetType()) { + case EArchMsgType::TimerTick: + AdvanceGameState(queue); + break; + case EArchMsgType::SetGameState: { + const CArchMsgParmInt32& state = MakeMsg::GetParmNewGameflowState(msg); + x14_gameState = EClientFlowStates(state.x4_parm); + SetGameState(x14_gameState, queue); + return EMessageReturn::Exit; + } + default: + break; + } + return EMessageReturn::Normal; } -} +} // namespace urde diff --git a/Runtime/CMainFlowBase.hpp b/Runtime/CMainFlowBase.hpp index 036687a0f..e88d22c3f 100644 --- a/Runtime/CMainFlowBase.hpp +++ b/Runtime/CMainFlowBase.hpp @@ -2,28 +2,19 @@ #include "CIOWin.hpp" -namespace urde -{ +namespace urde { -enum class EClientFlowStates -{ - Unspecified = -1, - PreFrontEnd = 7, - FrontEnd = 8, - Game = 14, - GameExit = 15 -}; +enum class EClientFlowStates { Unspecified = -1, PreFrontEnd = 7, FrontEnd = 8, Game = 14, GameExit = 15 }; -class CMainFlowBase : public CIOWin -{ +class CMainFlowBase : public CIOWin { protected: - EClientFlowStates x14_gameState = EClientFlowStates::Unspecified; + EClientFlowStates x14_gameState = EClientFlowStates::Unspecified; + public: - CMainFlowBase(const char* name) : CIOWin(name) {} - EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); - virtual void AdvanceGameState(CArchitectureQueue& queue)=0; - virtual void SetGameState(EClientFlowStates state, CArchitectureQueue& queue)=0; + CMainFlowBase(const char* name) : CIOWin(name) {} + EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); + virtual void AdvanceGameState(CArchitectureQueue& queue) = 0; + virtual void SetGameState(EClientFlowStates state, CArchitectureQueue& queue) = 0; }; -} - +} // namespace urde diff --git a/Runtime/CMemoryCardSys.cpp b/Runtime/CMemoryCardSys.cpp index 7cc0d583a..2aa3ce533 100644 --- a/Runtime/CMemoryCardSys.cpp +++ b/Runtime/CMemoryCardSys.cpp @@ -6,634 +6,540 @@ #include "CCRC32.hpp" #include "Graphics/CTexture.hpp" -namespace urde -{ +namespace urde { using ECardResult = kabufuda::ECardResult; static kabufuda::SystemString g_CardImagePaths[2] = {}; static kabufuda::Card g_CardStates[2] = {{"GM8E", "01"}, {"GM8E", "01"}}; -//static kabufuda::ECardResult g_OpResults[2] = {}; +// static kabufuda::ECardResult g_OpResults[2] = {}; -CSaveWorldIntermediate::CSaveWorldIntermediate(CAssetId mlvl, CAssetId savw) -: x0_mlvlId(mlvl), x8_savwId(savw) -{ - if (!savw.IsValid()) - x2c_dummyWorld = std::make_unique(mlvl, false); - else - x34_saveWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), savw}); +CSaveWorldIntermediate::CSaveWorldIntermediate(CAssetId mlvl, CAssetId savw) : x0_mlvlId(mlvl), x8_savwId(savw) { + if (!savw.IsValid()) + x2c_dummyWorld = std::make_unique(mlvl, false); + else + x34_saveWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), savw}); } -bool CSaveWorldIntermediate::InitializePump() -{ - if (x2c_dummyWorld) - { - CDummyWorld& wld = *x2c_dummyWorld; - if (!wld.ICheckWorldComplete()) - return false; +bool CSaveWorldIntermediate::InitializePump() { + if (x2c_dummyWorld) { + CDummyWorld& wld = *x2c_dummyWorld; + if (!wld.ICheckWorldComplete()) + return false; - x4_strgId = wld.IGetStringTableAssetId(); - x8_savwId = wld.IGetSaveWorldAssetId(); - u32 areaCount = wld.IGetAreaCount(); + x4_strgId = wld.IGetStringTableAssetId(); + x8_savwId = wld.IGetSaveWorldAssetId(); + u32 areaCount = wld.IGetAreaCount(); - xc_areaIds.reserve(areaCount); - for (u32 i=0 ; iIGetAreaId()); - } - - CAssetId mlvlId = wld.IGetWorldAssetId(); - CWorldState& mlvlState = g_GameState->StateForWorld(mlvlId); - x1c_defaultLayerStates = mlvlState.GetLayerState()->x0_areaLayers; - - x34_saveWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), x8_savwId}); - x2c_dummyWorld.reset(); - } - else - { - if (!x34_saveWorld) - return true; - if (x34_saveWorld.IsLoaded() && x34_saveWorld.GetObj()) - return true; + xc_areaIds.reserve(areaCount); + for (u32 i = 0; i < areaCount; ++i) { + const IGameArea* area = wld.IGetAreaAlways(i); + xc_areaIds.push_back(area->IGetAreaId()); } - return false; + CAssetId mlvlId = wld.IGetWorldAssetId(); + CWorldState& mlvlState = g_GameState->StateForWorld(mlvlId); + x1c_defaultLayerStates = mlvlState.GetLayerState()->x0_areaLayers; + + x34_saveWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), x8_savwId}); + x2c_dummyWorld.reset(); + } else { + if (!x34_saveWorld) + return true; + if (x34_saveWorld.IsLoaded() && x34_saveWorld.GetObj()) + return true; + } + + return false; } -bool CMemoryCardSys::HasSaveWorldMemory(CAssetId wldId) const -{ - auto existingSearch = - std::find_if(xc_memoryWorlds.cbegin(), xc_memoryWorlds.cend(), [&](const auto& wld) - { return wld.first == wldId; }); - return existingSearch != xc_memoryWorlds.cend(); +bool CMemoryCardSys::HasSaveWorldMemory(CAssetId wldId) const { + auto existingSearch = std::find_if(xc_memoryWorlds.cbegin(), xc_memoryWorlds.cend(), + [&](const auto& wld) { return wld.first == wldId; }); + return existingSearch != xc_memoryWorlds.cend(); } -const CSaveWorldMemory& CMemoryCardSys::GetSaveWorldMemory(CAssetId wldId) const -{ - auto existingSearch = - std::find_if(xc_memoryWorlds.cbegin(), xc_memoryWorlds.cend(), [&](const auto& wld) - { return wld.first == wldId; }); - return existingSearch->second; +const CSaveWorldMemory& CMemoryCardSys::GetSaveWorldMemory(CAssetId wldId) const { + auto existingSearch = std::find_if(xc_memoryWorlds.cbegin(), xc_memoryWorlds.cend(), + [&](const auto& wld) { return wld.first == wldId; }); + return existingSearch->second; } -CMemoryCardSys::CMemoryCardSys() -{ - x0_hints = g_SimplePool->GetObj("HINT_Hints"); - xc_memoryWorlds.reserve(16); - x1c_worldInter.emplace(); - x1c_worldInter->reserve(16); +CMemoryCardSys::CMemoryCardSys() { + x0_hints = g_SimplePool->GetObj("HINT_Hints"); + xc_memoryWorlds.reserve(16); + x1c_worldInter.emplace(); + x1c_worldInter->reserve(16); - std::vector> orderedMLVLs; - orderedMLVLs.reserve(16); - g_ResFactory->EnumerateNamedResources([&](std::string_view name, const SObjectTag& tag) -> bool - { - if (tag.type == FOURCC('MLVL')) - { - CAssetId origId = g_ResFactory->TranslateNewToOriginal(tag.id); - orderedMLVLs.emplace_back(origId, tag.id); - } - return true; - }); - std::sort(orderedMLVLs.begin(), orderedMLVLs.end(), - [](const auto& a, const auto& b) -> bool { return a.first < b.first; }); - - for (const auto& mlvl : orderedMLVLs) - { - if (!HasSaveWorldMemory(mlvl.second)) - { - xc_memoryWorlds.emplace_back(mlvl.second, CSaveWorldMemory{}); - x1c_worldInter->emplace_back(mlvl.second, -1); - } + std::vector> orderedMLVLs; + orderedMLVLs.reserve(16); + g_ResFactory->EnumerateNamedResources([&](std::string_view name, const SObjectTag& tag) -> bool { + if (tag.type == FOURCC('MLVL')) { + CAssetId origId = g_ResFactory->TranslateNewToOriginal(tag.id); + orderedMLVLs.emplace_back(origId, tag.id); } + return true; + }); + std::sort(orderedMLVLs.begin(), orderedMLVLs.end(), + [](const auto& a, const auto& b) -> bool { return a.first < b.first; }); - x30_scanCategoryCounts.resize(6); + for (const auto& mlvl : orderedMLVLs) { + if (!HasSaveWorldMemory(mlvl.second)) { + xc_memoryWorlds.emplace_back(mlvl.second, CSaveWorldMemory{}); + x1c_worldInter->emplace_back(mlvl.second, -1); + } + } + + x30_scanCategoryCounts.resize(6); } -bool CMemoryCardSys::InitializePump() -{ - if (!x1c_worldInter) - { - for (const auto& world : xc_memoryWorlds) - { - const CSaveWorldMemory& wld = world.second; - if (!wld.GetWorldName()) - continue; - if (!wld.GetWorldName().IsLoaded() || - !wld.GetWorldName().GetObj()) - return false; - } - - if (!x0_hints.IsLoaded() || !x0_hints.GetObj()) - return false; - return true; +bool CMemoryCardSys::InitializePump() { + if (!x1c_worldInter) { + for (const auto& world : xc_memoryWorlds) { + const CSaveWorldMemory& wld = world.second; + if (!wld.GetWorldName()) + continue; + if (!wld.GetWorldName().IsLoaded() || !wld.GetWorldName().GetObj()) + return false; } - bool done = true; - for (CSaveWorldIntermediate& world : *x1c_worldInter) - { - if (world.InitializePump()) - { - if (!world.x34_saveWorld) - continue; + if (!x0_hints.IsLoaded() || !x0_hints.GetObj()) + return false; + return true; + } - auto existingSearch = - std::find_if(xc_memoryWorlds.begin(), xc_memoryWorlds.end(), [&](const auto& test) - { return test.first == world.x0_mlvlId; }); - CSaveWorldMemory& wldMemOut = existingSearch->second; - wldMemOut.x4_savwId = world.x8_savwId; - wldMemOut.x0_strgId = world.x4_strgId; - wldMemOut.xc_areaIds = world.xc_areaIds; - wldMemOut.x1c_defaultLayerStates = world.x1c_defaultLayerStates; + bool done = true; + for (CSaveWorldIntermediate& world : *x1c_worldInter) { + if (world.InitializePump()) { + if (!world.x34_saveWorld) + continue; - CSaveWorld& savw = *world.x34_saveWorld; - wldMemOut.x8_areaCount = savw.GetAreaCount(); + auto existingSearch = std::find_if(xc_memoryWorlds.begin(), xc_memoryWorlds.end(), + [&](const auto& test) { return test.first == world.x0_mlvlId; }); + CSaveWorldMemory& wldMemOut = existingSearch->second; + wldMemOut.x4_savwId = world.x8_savwId; + wldMemOut.x0_strgId = world.x4_strgId; + wldMemOut.xc_areaIds = world.xc_areaIds; + wldMemOut.x1c_defaultLayerStates = world.x1c_defaultLayerStates; - x20_scanStates.reserve(x20_scanStates.size() + savw.GetScans().size()); - for (const CSaveWorld::SScanState& scan : savw.GetScans()) - { - auto existingSearch = - std::find_if(x20_scanStates.begin(), x20_scanStates.end(), [&](const auto& test) - { return test.first == scan.x0_id && test.second == scan.x4_category; }); - if (existingSearch == x20_scanStates.end()) - { - x20_scanStates.emplace_back(scan.x0_id, scan.x4_category); - ++x30_scanCategoryCounts[int(scan.x4_category)]; - } - } + CSaveWorld& savw = *world.x34_saveWorld; + wldMemOut.x8_areaCount = savw.GetAreaCount(); - wldMemOut.x3c_saveWorld = std::move(world.x34_saveWorld); - wldMemOut.x2c_worldName = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), wldMemOut.x0_strgId}); - } - else - done = false; - } - - if (done) - { - std::sort(x20_scanStates.begin(), x20_scanStates.end(), [&](const auto& a, const auto& b) ->bool{ - return g_ResFactory->TranslateNewToOriginal(a.first) < g_ResFactory->TranslateNewToOriginal(b.first); + x20_scanStates.reserve(x20_scanStates.size() + savw.GetScans().size()); + for (const CSaveWorld::SScanState& scan : savw.GetScans()) { + auto existingSearch = std::find_if(x20_scanStates.begin(), x20_scanStates.end(), [&](const auto& test) { + return test.first == scan.x0_id && test.second == scan.x4_category; }); - x1c_worldInter = std::experimental::nullopt; - } + if (existingSearch == x20_scanStates.end()) { + x20_scanStates.emplace_back(scan.x0_id, scan.x4_category); + ++x30_scanCategoryCounts[int(scan.x4_category)]; + } + } - return false; + wldMemOut.x3c_saveWorld = std::move(world.x34_saveWorld); + wldMemOut.x2c_worldName = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), wldMemOut.x0_strgId}); + } else + done = false; + } + + if (done) { + std::sort(x20_scanStates.begin(), x20_scanStates.end(), [&](const auto& a, const auto& b) -> bool { + return g_ResFactory->TranslateNewToOriginal(a.first) < g_ResFactory->TranslateNewToOriginal(b.first); + }); + x1c_worldInter = std::experimental::nullopt; + } + + return false; } -std::pair CMemoryCardSys::GetAreaAndWorldIdForSaveId(s32 saveId) const -{ - return {kInvalidAreaId, -1}; +std::pair CMemoryCardSys::GetAreaAndWorldIdForSaveId(s32 saveId) const { return {kInvalidAreaId, -1}; } + +void CMemoryCardSys::CCardFileInfo::LockBannerToken(CAssetId bannerTxtr, CSimplePool& sp) { + x3c_bannerTex = bannerTxtr; + x40_bannerTok.emplace(sp.GetObj({FOURCC('TXTR'), bannerTxtr}, m_texParam)); } -void CMemoryCardSys::CCardFileInfo::LockBannerToken(CAssetId bannerTxtr, CSimplePool& sp) -{ - x3c_bannerTex = bannerTxtr; - x40_bannerTok.emplace(sp.GetObj({FOURCC('TXTR'), bannerTxtr}, m_texParam)); -} - -CMemoryCardSys::CCardFileInfo::Icon::Icon(CAssetId id, kabufuda::EAnimationSpeed speed, - CSimplePool& sp, const CVParamTransfer& cv) +CMemoryCardSys::CCardFileInfo::Icon::Icon(CAssetId id, kabufuda::EAnimationSpeed speed, CSimplePool& sp, + const CVParamTransfer& cv) : x0_id(id), x4_speed(speed), x8_tex(sp.GetObj({FOURCC('TXTR'), id}, cv)) {} -void CMemoryCardSys::CCardFileInfo::LockIconToken(CAssetId iconTxtr, kabufuda::EAnimationSpeed speed, CSimplePool& sp) -{ - x50_iconToks.emplace_back(iconTxtr, speed, sp, m_texParam); +void CMemoryCardSys::CCardFileInfo::LockIconToken(CAssetId iconTxtr, kabufuda::EAnimationSpeed speed, CSimplePool& sp) { + x50_iconToks.emplace_back(iconTxtr, speed, sp, m_texParam); } -u32 CMemoryCardSys::CCardFileInfo::CalculateBannerDataSize() const -{ - u32 ret = 68; - if (x3c_bannerTex.IsValid()) - { - if ((*x40_bannerTok)->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3) - ret = 6212; - else - ret = 3652; +u32 CMemoryCardSys::CCardFileInfo::CalculateBannerDataSize() const { + u32 ret = 68; + if (x3c_bannerTex.IsValid()) { + if ((*x40_bannerTok)->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3) + ret = 6212; + else + ret = 3652; + } + + bool paletteTex = false; + for (const Icon& icon : x50_iconToks) { + if (icon.x8_tex->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3) + ret += 2048; + else { + ret += 1024; + paletteTex = true; } + } - bool paletteTex = false; - for (const Icon& icon : x50_iconToks) - { - if (icon.x8_tex->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3) - ret += 2048; - else - { - ret += 1024; - paletteTex = true; - } - } + if (paletteTex) + ret += 512; - if (paletteTex) - ret += 512; - - return ret; + return ret; } -u32 CMemoryCardSys::CCardFileInfo::CalculateTotalDataSize() const -{ - return (CalculateBannerDataSize() + xf4_saveBuffer.size() + 8191) & ~8191; +u32 CMemoryCardSys::CCardFileInfo::CalculateTotalDataSize() const { + return (CalculateBannerDataSize() + xf4_saveBuffer.size() + 8191) & ~8191; } -void CMemoryCardSys::CCardFileInfo::BuildCardBuffer() -{ - u32 bannerSz = CalculateBannerDataSize(); - x104_cardBuffer.resize((bannerSz + xf4_saveBuffer.size() + 8191) & ~8191); +void CMemoryCardSys::CCardFileInfo::BuildCardBuffer() { + u32 bannerSz = CalculateBannerDataSize(); + x104_cardBuffer.resize((bannerSz + xf4_saveBuffer.size() + 8191) & ~8191); - CMemoryOutStream w(x104_cardBuffer.data(), x104_cardBuffer.size()); - w.writeUint32Big(0); - char comment[64]; - strncpy(comment, x28_comment.data(), 64); - w.writeBytes(comment, 64); - WriteBannerData(w); - WriteIconData(w); - memmove(x104_cardBuffer.data() + bannerSz, xf4_saveBuffer.data(), xf4_saveBuffer.size()); - reinterpret_cast(*x104_cardBuffer.data()) = - hecl::SBig(CCRC32::Calculate(x104_cardBuffer.data() + 4, x104_cardBuffer.size() - 4)); + CMemoryOutStream w(x104_cardBuffer.data(), x104_cardBuffer.size()); + w.writeUint32Big(0); + char comment[64]; + strncpy(comment, x28_comment.data(), 64); + w.writeBytes(comment, 64); + WriteBannerData(w); + WriteIconData(w); + memmove(x104_cardBuffer.data() + bannerSz, xf4_saveBuffer.data(), xf4_saveBuffer.size()); + reinterpret_cast(*x104_cardBuffer.data()) = + hecl::SBig(CCRC32::Calculate(x104_cardBuffer.data() + 4, x104_cardBuffer.size() - 4)); - xf4_saveBuffer.clear(); + xf4_saveBuffer.clear(); } -void CMemoryCardSys::CCardFileInfo::WriteBannerData(CMemoryOutStream& out) const -{ - if (x3c_bannerTex.IsValid()) - { - const TLockedToken& tex = *x40_bannerTok; - u32 bufSz; - ETexelFormat fmt; - std::unique_ptr palette; - std::unique_ptr texels = tex->BuildMemoryCardTex(bufSz, fmt, palette); - - if (fmt == ETexelFormat::RGB5A3) - out.writeBytes(texels.get(), 6144); - else - out.writeBytes(texels.get(), 3072); - - if (fmt == ETexelFormat::C8) - out.writeBytes(palette.get(), 512); - } -} - -void CMemoryCardSys::CCardFileInfo::WriteIconData(CMemoryOutStream& out) const -{ +void CMemoryCardSys::CCardFileInfo::WriteBannerData(CMemoryOutStream& out) const { + if (x3c_bannerTex.IsValid()) { + const TLockedToken& tex = *x40_bannerTok; + u32 bufSz; + ETexelFormat fmt; std::unique_ptr palette; - for (const Icon& icon : x50_iconToks) - { - u32 bufSz; - ETexelFormat fmt; - std::unique_ptr texels = icon.x8_tex->BuildMemoryCardTex(bufSz, fmt, palette); + std::unique_ptr texels = tex->BuildMemoryCardTex(bufSz, fmt, palette); - if (fmt == ETexelFormat::RGB5A3) - out.writeBytes(texels.get(), 2048); - else - out.writeBytes(texels.get(), 1024); - } - if (palette) - out.writeBytes(palette.get(), 512); -} - -ECardResult CMemoryCardSys::CCardFileInfo::PumpCardTransfer() -{ - if (x0_status == EStatus::Standby) - return ECardResult::READY; - else if (x0_status == EStatus::Transferring) - { - ECardResult result = CMemoryCardSys::GetResultCode(GetCardPort()); - if (result != ECardResult::BUSY) - x104_cardBuffer.clear(); - if (result != ECardResult::READY) - return result; - x0_status = EStatus::Done; - kabufuda::CardStat stat = {}; - result = GetStatus(stat); - if (result != ECardResult::READY) - return result; - result = CMemoryCardSys::SetStatus(m_handle.slot, m_handle.getFileNo(), stat); - if (result != ECardResult::READY) - return result; - return ECardResult::BUSY; - } + if (fmt == ETexelFormat::RGB5A3) + out.writeBytes(texels.get(), 6144); else - { - ECardResult result = CMemoryCardSys::GetResultCode(GetCardPort()); - if (result == ECardResult::READY) - x0_status = EStatus::Standby; - return result; - } + out.writeBytes(texels.get(), 3072); + + if (fmt == ETexelFormat::C8) + out.writeBytes(palette.get(), 512); + } } -ECardResult CMemoryCardSys::CCardFileInfo::GetStatus(kabufuda::CardStat& stat) const -{ - ECardResult result = CMemoryCardSys::GetStatus(m_handle.slot, m_handle.getFileNo(), stat); +void CMemoryCardSys::CCardFileInfo::WriteIconData(CMemoryOutStream& out) const { + std::unique_ptr palette; + for (const Icon& icon : x50_iconToks) { + u32 bufSz; + ETexelFormat fmt; + std::unique_ptr texels = icon.x8_tex->BuildMemoryCardTex(bufSz, fmt, palette); + + if (fmt == ETexelFormat::RGB5A3) + out.writeBytes(texels.get(), 2048); + else + out.writeBytes(texels.get(), 1024); + } + if (palette) + out.writeBytes(palette.get(), 512); +} + +ECardResult CMemoryCardSys::CCardFileInfo::PumpCardTransfer() { + if (x0_status == EStatus::Standby) + return ECardResult::READY; + else if (x0_status == EStatus::Transferring) { + ECardResult result = CMemoryCardSys::GetResultCode(GetCardPort()); + if (result != ECardResult::BUSY) + x104_cardBuffer.clear(); if (result != ECardResult::READY) - return result; - - stat.SetCommentAddr(4); - stat.SetIconAddr(68); - - kabufuda::EImageFormat bannerFmt; - if (x3c_bannerTex.IsValid()) - { - if ((*x40_bannerTok)->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3) - bannerFmt = kabufuda::EImageFormat::RGB5A3; - else - bannerFmt = kabufuda::EImageFormat::C8; - } - else - bannerFmt = kabufuda::EImageFormat::None; - stat.SetBannerFormat(bannerFmt); - - int idx = 0; - for (const Icon& icon : x50_iconToks) - { - stat.SetIconFormat(icon.x8_tex->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3 ? - kabufuda::EImageFormat::RGB5A3 : kabufuda::EImageFormat::C8, idx); - stat.SetIconSpeed(icon.x4_speed, idx); - ++idx; - } - if (idx < 8) - { - stat.SetIconFormat(kabufuda::EImageFormat::None, idx); - stat.SetIconSpeed(kabufuda::EAnimationSpeed::End, idx); - } - - return ECardResult::READY; -} - -ECardResult CMemoryCardSys::CCardFileInfo::CreateFile() -{ - return CMemoryCardSys::CreateFile(m_handle.slot, x18_fileName.c_str(), - CalculateTotalDataSize(), m_handle); -} - -ECardResult CMemoryCardSys::CCardFileInfo::WriteFile() -{ - BuildCardBuffer(); - //DCStoreRange(x104_cardBuffer.data(), x104_cardBuffer.size()); - x0_status = EStatus::Transferring; - return CMemoryCardSys::WriteFile(m_handle, x104_cardBuffer.data(), x104_cardBuffer.size(), 0); -} - -ECardResult CMemoryCardSys::CCardFileInfo::CloseFile() -{ - return CMemoryCardSys::CloseFile(m_handle); -} - -kabufuda::ProbeResults CMemoryCardSys::CardProbe(kabufuda::ECardSlot port) -{ - g_CardImagePaths[0] = ResolveDolphinCardPath(kabufuda::ECardSlot::SlotA); - g_CardImagePaths[1] = ResolveDolphinCardPath(kabufuda::ECardSlot::SlotB); - - kabufuda::ProbeResults res = kabufuda::Card::probeCardFile(g_CardImagePaths[int(port)]); - //g_OpResults[int(port)] = res.x0_error; - return res; -} - -ECardResult CMemoryCardSys::MountCard(kabufuda::ECardSlot port) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (!card.open(g_CardImagePaths[int(port)])) - return ECardResult::NOCARD; - ECardResult result = card.getError(); - //g_OpResults[int(port)] = result; + return result; + x0_status = EStatus::Done; + kabufuda::CardStat stat = {}; + result = GetStatus(stat); + if (result != ECardResult::READY) + return result; + result = CMemoryCardSys::SetStatus(m_handle.slot, m_handle.getFileNo(), stat); + if (result != ECardResult::READY) + return result; + return ECardResult::BUSY; + } else { + ECardResult result = CMemoryCardSys::GetResultCode(GetCardPort()); if (result == ECardResult::READY) - return ECardResult::READY; + x0_status = EStatus::Standby; return result; + } } -ECardResult CMemoryCardSys::UnmountCard(kabufuda::ECardSlot port) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - card.commit(); - //g_OpResults[int(port)] = ECardResult::READY; +ECardResult CMemoryCardSys::CCardFileInfo::GetStatus(kabufuda::CardStat& stat) const { + ECardResult result = CMemoryCardSys::GetStatus(m_handle.slot, m_handle.getFileNo(), stat); + if (result != ECardResult::READY) + return result; + + stat.SetCommentAddr(4); + stat.SetIconAddr(68); + + kabufuda::EImageFormat bannerFmt; + if (x3c_bannerTex.IsValid()) { + if ((*x40_bannerTok)->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3) + bannerFmt = kabufuda::EImageFormat::RGB5A3; + else + bannerFmt = kabufuda::EImageFormat::C8; + } else + bannerFmt = kabufuda::EImageFormat::None; + stat.SetBannerFormat(bannerFmt); + + int idx = 0; + for (const Icon& icon : x50_iconToks) { + stat.SetIconFormat(icon.x8_tex->GetMemoryCardTexelFormat() == ETexelFormat::RGB5A3 ? kabufuda::EImageFormat::RGB5A3 + : kabufuda::EImageFormat::C8, + idx); + stat.SetIconSpeed(icon.x4_speed, idx); + ++idx; + } + if (idx < 8) { + stat.SetIconFormat(kabufuda::EImageFormat::None, idx); + stat.SetIconSpeed(kabufuda::EAnimationSpeed::End, idx); + } + + return ECardResult::READY; +} + +ECardResult CMemoryCardSys::CCardFileInfo::CreateFile() { + return CMemoryCardSys::CreateFile(m_handle.slot, x18_fileName.c_str(), CalculateTotalDataSize(), m_handle); +} + +ECardResult CMemoryCardSys::CCardFileInfo::WriteFile() { + BuildCardBuffer(); + // DCStoreRange(x104_cardBuffer.data(), x104_cardBuffer.size()); + x0_status = EStatus::Transferring; + return CMemoryCardSys::WriteFile(m_handle, x104_cardBuffer.data(), x104_cardBuffer.size(), 0); +} + +ECardResult CMemoryCardSys::CCardFileInfo::CloseFile() { return CMemoryCardSys::CloseFile(m_handle); } + +kabufuda::ProbeResults CMemoryCardSys::CardProbe(kabufuda::ECardSlot port) { + g_CardImagePaths[0] = ResolveDolphinCardPath(kabufuda::ECardSlot::SlotA); + g_CardImagePaths[1] = ResolveDolphinCardPath(kabufuda::ECardSlot::SlotB); + + kabufuda::ProbeResults res = kabufuda::Card::probeCardFile(g_CardImagePaths[int(port)]); + // g_OpResults[int(port)] = res.x0_error; + return res; +} + +ECardResult CMemoryCardSys::MountCard(kabufuda::ECardSlot port) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (!card.open(g_CardImagePaths[int(port)])) + return ECardResult::NOCARD; + ECardResult result = card.getError(); + // g_OpResults[int(port)] = result; + if (result == ECardResult::READY) return ECardResult::READY; + return result; } -ECardResult CMemoryCardSys::CheckCard(kabufuda::ECardSlot port) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - ECardResult result = card.getError(); - //g_OpResults[int(port)] = result; - return result; +ECardResult CMemoryCardSys::UnmountCard(kabufuda::ECardSlot port) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + card.commit(); + // g_OpResults[int(port)] = ECardResult::READY; + return ECardResult::READY; } -ECardResult CMemoryCardSys::CreateFile(kabufuda::ECardSlot port, const char* name, u32 size, CardFileHandle& info) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - info.slot = port; - ECardResult result = card.createFile(name, size, info.handle); - //g_OpResults[int(port)] = result; - return result; +ECardResult CMemoryCardSys::CheckCard(kabufuda::ECardSlot port) { + kabufuda::Card& card = g_CardStates[int(port)]; + ECardResult result = card.getError(); + // g_OpResults[int(port)] = result; + return result; } -ECardResult CMemoryCardSys::OpenFile(kabufuda::ECardSlot port, const char* name, CardFileHandle& info) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - info.slot = port; - ECardResult result = card.openFile(name, info.handle); - //g_OpResults[int(port)] = result; - return result; +ECardResult CMemoryCardSys::CreateFile(kabufuda::ECardSlot port, const char* name, u32 size, CardFileHandle& info) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + info.slot = port; + ECardResult result = card.createFile(name, size, info.handle); + // g_OpResults[int(port)] = result; + return result; } -ECardResult CMemoryCardSys::FastOpenFile(kabufuda::ECardSlot port, int fileNo, CardFileHandle& info) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - info.slot = port; - ECardResult result = card.openFile(fileNo, info.handle); - //g_OpResults[int(port)] = result; - return result; +ECardResult CMemoryCardSys::OpenFile(kabufuda::ECardSlot port, const char* name, CardFileHandle& info) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + info.slot = port; + ECardResult result = card.openFile(name, info.handle); + // g_OpResults[int(port)] = result; + return result; } -ECardResult CMemoryCardSys::CloseFile(CardFileHandle& info) -{ - kabufuda::Card& card = g_CardStates[int(info.slot)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(info.slot)] = err; - return err; - } - card.closeFile(info.handle); - return ECardResult::READY; +ECardResult CMemoryCardSys::FastOpenFile(kabufuda::ECardSlot port, int fileNo, CardFileHandle& info) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + info.slot = port; + ECardResult result = card.openFile(fileNo, info.handle); + // g_OpResults[int(port)] = result; + return result; } -ECardResult CMemoryCardSys::ReadFile(CardFileHandle& info, void* buf, s32 length, s32 offset) -{ - kabufuda::Card& card = g_CardStates[int(info.slot)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(info.slot)] = err; - return err; - } - card.seek(info.handle, offset, kabufuda::SeekOrigin::Begin); - card.asyncRead(info.handle, buf, length); - //g_OpResults[int(info.slot)] = ECardResult::READY; - return ECardResult::READY; +ECardResult CMemoryCardSys::CloseFile(CardFileHandle& info) { + kabufuda::Card& card = g_CardStates[int(info.slot)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(info.slot)] = err; + return err; + } + card.closeFile(info.handle); + return ECardResult::READY; } -ECardResult CMemoryCardSys::WriteFile(CardFileHandle& info, const void* buf, s32 length, s32 offset) -{ - kabufuda::Card& card = g_CardStates[int(info.slot)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(info.slot)] = err; - return err; - } - card.seek(info.handle, offset, kabufuda::SeekOrigin::Begin); - card.asyncWrite(info.handle, buf, length); - //g_OpResults[int(info.slot)] = ECardResult::READY; - return ECardResult::READY; +ECardResult CMemoryCardSys::ReadFile(CardFileHandle& info, void* buf, s32 length, s32 offset) { + kabufuda::Card& card = g_CardStates[int(info.slot)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(info.slot)] = err; + return err; + } + card.seek(info.handle, offset, kabufuda::SeekOrigin::Begin); + card.asyncRead(info.handle, buf, length); + // g_OpResults[int(info.slot)] = ECardResult::READY; + return ECardResult::READY; } -ECardResult CMemoryCardSys::GetNumFreeBytes(kabufuda::ECardSlot port, s32& freeBytes, s32& freeFiles) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - card.getFreeBlocks(freeBytes, freeFiles); - //g_OpResults[int(port)] = ECardResult::READY; - return ECardResult::READY; +ECardResult CMemoryCardSys::WriteFile(CardFileHandle& info, const void* buf, s32 length, s32 offset) { + kabufuda::Card& card = g_CardStates[int(info.slot)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(info.slot)] = err; + return err; + } + card.seek(info.handle, offset, kabufuda::SeekOrigin::Begin); + card.asyncWrite(info.handle, buf, length); + // g_OpResults[int(info.slot)] = ECardResult::READY; + return ECardResult::READY; } -ECardResult CMemoryCardSys::GetSerialNo(kabufuda::ECardSlot port, u64& serialOut) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - card.getSerial(serialOut); - //g_OpResults[int(port)] = ECardResult::READY; - return ECardResult::READY; +ECardResult CMemoryCardSys::GetNumFreeBytes(kabufuda::ECardSlot port, s32& freeBytes, s32& freeFiles) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + card.getFreeBlocks(freeBytes, freeFiles); + // g_OpResults[int(port)] = ECardResult::READY; + return ECardResult::READY; } -ECardResult CMemoryCardSys::GetResultCode(kabufuda::ECardSlot port) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - return card.getError(); +ECardResult CMemoryCardSys::GetSerialNo(kabufuda::ECardSlot port, u64& serialOut) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + card.getSerial(serialOut); + // g_OpResults[int(port)] = ECardResult::READY; + return ECardResult::READY; } -ECardResult CMemoryCardSys::GetStatus(kabufuda::ECardSlot port, int fileNo, CardStat& statOut) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - ECardResult result = card.getStatus(fileNo, statOut); - //g_OpResults[int(port)] = result; - return result; +ECardResult CMemoryCardSys::GetResultCode(kabufuda::ECardSlot port) { + kabufuda::Card& card = g_CardStates[int(port)]; + return card.getError(); } -ECardResult CMemoryCardSys::SetStatus(kabufuda::ECardSlot port, int fileNo, const CardStat& stat) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - ECardResult result = card.setStatus(fileNo, stat); - //g_OpResults[int(port)] = result; - return result; +ECardResult CMemoryCardSys::GetStatus(kabufuda::ECardSlot port, int fileNo, CardStat& statOut) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + ECardResult result = card.getStatus(fileNo, statOut); + // g_OpResults[int(port)] = result; + return result; } -ECardResult CMemoryCardSys::DeleteFile(kabufuda::ECardSlot port, const char* name) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - ECardResult result = card.deleteFile(name); - //g_OpResults[int(port)] = result; - return result; +ECardResult CMemoryCardSys::SetStatus(kabufuda::ECardSlot port, int fileNo, const CardStat& stat) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + ECardResult result = card.setStatus(fileNo, stat); + // g_OpResults[int(port)] = result; + return result; } -ECardResult CMemoryCardSys::FastDeleteFile(kabufuda::ECardSlot port, int fileNo) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - ECardResult result = card.deleteFile(fileNo); - //g_OpResults[int(port)] = result; - return result; +ECardResult CMemoryCardSys::DeleteFile(kabufuda::ECardSlot port, const char* name) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + ECardResult result = card.deleteFile(name); + // g_OpResults[int(port)] = result; + return result; } -ECardResult CMemoryCardSys::Rename(kabufuda::ECardSlot port, const char* oldName, const char* newName) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - ECardResult result = card.renameFile(oldName, newName); - //g_OpResults[int(port)] = result; - return result; +ECardResult CMemoryCardSys::FastDeleteFile(kabufuda::ECardSlot port, int fileNo) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + ECardResult result = card.deleteFile(fileNo); + // g_OpResults[int(port)] = result; + return result; } -ECardResult CMemoryCardSys::FormatCard(kabufuda::ECardSlot port) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - card.format(port); - if (CardResult err = card.getError()) - { - //g_OpResults[int(port)] = err; - return err; - } - //g_OpResults[int(port)] = ECardResult::READY; - return ECardResult::READY; +ECardResult CMemoryCardSys::Rename(kabufuda::ECardSlot port, const char* oldName, const char* newName) { + kabufuda::Card& card = g_CardStates[int(port)]; + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + ECardResult result = card.renameFile(oldName, newName); + // g_OpResults[int(port)] = result; + return result; } -void CMemoryCardSys::CommitToDisk(kabufuda::ECardSlot port) -{ - kabufuda::Card& card = g_CardStates[int(port)]; - card.commit(); +ECardResult CMemoryCardSys::FormatCard(kabufuda::ECardSlot port) { + kabufuda::Card& card = g_CardStates[int(port)]; + card.format(port); + if (CardResult err = card.getError()) { + // g_OpResults[int(port)] = err; + return err; + } + // g_OpResults[int(port)] = ECardResult::READY; + return ECardResult::READY; } -kabufuda::SystemString CMemoryCardSys::CreateDolphinCard(kabufuda::ECardSlot slot) -{ - kabufuda::SystemString path = _CreateDolphinCard(slot); - CardProbe(slot); - MountCard(slot); - FormatCard(slot); - kabufuda::Card& card = g_CardStates[int(slot)]; - card.waitForCompletion(); - return path; +void CMemoryCardSys::CommitToDisk(kabufuda::ECardSlot port) { + kabufuda::Card& card = g_CardStates[int(port)]; + card.commit(); } -void CMemoryCardSys::Shutdown() -{ - UnmountCard(kabufuda::ECardSlot::SlotA); - UnmountCard(kabufuda::ECardSlot::SlotB); +kabufuda::SystemString CMemoryCardSys::CreateDolphinCard(kabufuda::ECardSlot slot) { + kabufuda::SystemString path = _CreateDolphinCard(slot); + CardProbe(slot); + MountCard(slot); + FormatCard(slot); + kabufuda::Card& card = g_CardStates[int(slot)]; + card.waitForCompletion(); + return path; } +void CMemoryCardSys::Shutdown() { + UnmountCard(kabufuda::ECardSlot::SlotA); + UnmountCard(kabufuda::ECardSlot::SlotB); } + +} // namespace urde diff --git a/Runtime/CMemoryCardSys.hpp b/Runtime/CMemoryCardSys.hpp index ed5fb0d85..5d4f38a70 100644 --- a/Runtime/CMemoryCardSys.hpp +++ b/Runtime/CMemoryCardSys.hpp @@ -8,185 +8,166 @@ #include "kabufuda/Card.hpp" #include -namespace urde -{ +namespace urde { class CDummyWorld; class CStringTable; class CSimplePool; -class CSaveWorldMemory -{ - friend class CMemoryCardSys; - CAssetId x0_strgId; - CAssetId x4_savwId; - u32 x8_areaCount; - std::vector xc_areaIds; - std::vector x1c_defaultLayerStates; - TLockedToken x2c_worldName; /* used to be optional */ - TLockedToken x3c_saveWorld; /* used to be optional */ +class CSaveWorldMemory { + friend class CMemoryCardSys; + CAssetId x0_strgId; + CAssetId x4_savwId; + u32 x8_areaCount; + std::vector xc_areaIds; + std::vector x1c_defaultLayerStates; + TLockedToken x2c_worldName; /* used to be optional */ + TLockedToken x3c_saveWorld; /* used to be optional */ public: - CAssetId GetWorldNameId() const { return x0_strgId; } - CAssetId GetSaveWorldAssetId() const { return x4_savwId; } - u32 GetAreaCount() const { return x8_areaCount; } - const std::vector& GetDefaultLayerStates() const { return x1c_defaultLayerStates; } - const TLockedToken& GetWorldName() const { return x2c_worldName; } - const TLockedToken& GetSaveWorld() const { return x3c_saveWorld; } - const char16_t* GetFrontEndName() const - { - if (!x2c_worldName) - return u""; - return x2c_worldName->GetString(0); + CAssetId GetWorldNameId() const { return x0_strgId; } + CAssetId GetSaveWorldAssetId() const { return x4_savwId; } + u32 GetAreaCount() const { return x8_areaCount; } + const std::vector& GetDefaultLayerStates() const { return x1c_defaultLayerStates; } + const TLockedToken& GetWorldName() const { return x2c_worldName; } + const TLockedToken& GetSaveWorld() const { return x3c_saveWorld; } + const char16_t* GetFrontEndName() const { + if (!x2c_worldName) + return u""; + return x2c_worldName->GetString(0); + } +}; + +class CSaveWorldIntermediate { + friend class CMemoryCardSys; + CAssetId x0_mlvlId; + CAssetId x4_strgId; + CAssetId x8_savwId; + std::vector xc_areaIds; + std::vector x1c_defaultLayerStates; + std::unique_ptr x2c_dummyWorld; + TLockedToken x34_saveWorld; /* Used to be auto_ptr */ + +public: + CSaveWorldIntermediate(CAssetId mlvl, CAssetId savw); + + bool InitializePump(); +}; + +class CMemoryCardSys { + TLockedToken x0_hints; + std::vector> xc_memoryWorlds; /* MLVL as key */ + std::experimental::optional> x1c_worldInter; /* used to be auto_ptr of vector */ + std::vector> x20_scanStates; + rstl::reserved_vector x30_scanCategoryCounts; + +public: + static kabufuda::SystemString ResolveDolphinCardPath(kabufuda::ECardSlot slot); + static kabufuda::SystemString CreateDolphinCard(kabufuda::ECardSlot slot); + static kabufuda::SystemString _CreateDolphinCard(kabufuda::ECardSlot slot); + + using ECardResult = kabufuda::ECardResult; + struct CardResult { + ECardResult result; + CardResult(ECardResult res) : result(res) {} + operator ECardResult() const { return result; } + operator bool() const { return result != ECardResult::READY; } + }; + + struct CardFileHandle { + kabufuda::ECardSlot slot; + kabufuda::FileHandle handle; + CardFileHandle(kabufuda::ECardSlot slot) : slot(slot) {} + int getFileNo() const { return handle.getFileNo(); } + }; + + using CardStat = kabufuda::CardStat; + const std::vector& GetHints() const { return x0_hints->GetHints(); } + const std::vector>& GetMemoryWorlds() const { return xc_memoryWorlds; } + const std::vector>& GetScanStates() const { return x20_scanStates; } + u32 GetScanCategoryCount(CSaveWorld::EScanCategory cat) const { return x30_scanCategoryCounts[int(cat)]; } + + std::vector>::const_iterator LookupScanState(CAssetId id) const { + return rstl::binary_find(x20_scanStates.cbegin(), x20_scanStates.cend(), id, + [](const std::pair& p) { return p.first; }); + } + + bool HasSaveWorldMemory(CAssetId wldId) const; + const CSaveWorldMemory& GetSaveWorldMemory(CAssetId wldId) const; + + CMemoryCardSys(); + bool InitializePump(); + + struct CCardFileInfo { + struct Icon { + CAssetId x0_id; + kabufuda::EAnimationSpeed x4_speed; + TLockedToken x8_tex; + Icon(CAssetId id, kabufuda::EAnimationSpeed speed, CSimplePool& sp, const CVParamTransfer& cv); + }; + + enum class EStatus { Standby, Transferring, Done }; + + EStatus x0_status = EStatus::Standby; + // CARDFileInfo x4_info; + CardFileHandle m_handle; + std::string x18_fileName; + std::string x28_comment; + CAssetId x3c_bannerTex; + std::experimental::optional> x40_bannerTok; + rstl::reserved_vector x50_iconToks; + std::vector xf4_saveBuffer; + std::vector x104_cardBuffer; + + CVParamTransfer m_texParam = {new TObjOwnerParam(SBIG('OTEX'))}; + + CCardFileInfo(kabufuda::ECardSlot port, std::string_view name) : m_handle(port), x18_fileName(name) {} + + void LockBannerToken(CAssetId bannerTxtr, CSimplePool& sp); + void LockIconToken(CAssetId iconTxtr, kabufuda::EAnimationSpeed speed, CSimplePool& sp); + + kabufuda::ECardSlot GetCardPort() const { return m_handle.slot; } + int GetFileNo() const { return m_handle.getFileNo(); } + u32 CalculateBannerDataSize() const; + u32 CalculateTotalDataSize() const; + void BuildCardBuffer(); + void WriteBannerData(CMemoryOutStream& out) const; + void WriteIconData(CMemoryOutStream& out) const; + void SetComment(const std::string& c) { x28_comment = c; } + ECardResult PumpCardTransfer(); + ECardResult GetStatus(CardStat& stat) const; + ECardResult CreateFile(); + ECardResult WriteFile(); + ECardResult CloseFile(); + + CMemoryOutStream BeginMemoryOut(u32 sz) { + xf4_saveBuffer.resize(sz); + return CMemoryOutStream(xf4_saveBuffer.data(), sz); } + }; + + std::pair GetAreaAndWorldIdForSaveId(s32 saveId) const; + static kabufuda::ProbeResults CardProbe(kabufuda::ECardSlot port); + static ECardResult MountCard(kabufuda::ECardSlot port); + static ECardResult UnmountCard(kabufuda::ECardSlot port); + static ECardResult CheckCard(kabufuda::ECardSlot port); + static ECardResult CreateFile(kabufuda::ECardSlot port, const char* name, u32 size, CardFileHandle& info); + static ECardResult OpenFile(kabufuda::ECardSlot port, const char* name, CardFileHandle& info); + static ECardResult FastOpenFile(kabufuda::ECardSlot port, int fileNo, CardFileHandle& info); + static ECardResult CloseFile(CardFileHandle& info); + static ECardResult ReadFile(CardFileHandle& info, void* buf, s32 length, s32 offset); + static ECardResult WriteFile(CardFileHandle& info, const void* buf, s32 length, s32 offset); + static ECardResult GetNumFreeBytes(kabufuda::ECardSlot port, s32& freeBytes, s32& freeFiles); + static ECardResult GetSerialNo(kabufuda::ECardSlot port, u64& serialOut); + static ECardResult GetResultCode(kabufuda::ECardSlot port); + static ECardResult GetStatus(kabufuda::ECardSlot port, int fileNo, CardStat& statOut); + static ECardResult SetStatus(kabufuda::ECardSlot port, int fileNo, const CardStat& stat); + static ECardResult DeleteFile(kabufuda::ECardSlot port, const char* name); + static ECardResult FastDeleteFile(kabufuda::ECardSlot port, int fileNo); + static ECardResult Rename(kabufuda::ECardSlot port, const char* oldName, const char* newName); + static ECardResult FormatCard(kabufuda::ECardSlot port); + + static void CommitToDisk(kabufuda::ECardSlot port); + static void Shutdown(); }; -class CSaveWorldIntermediate -{ - friend class CMemoryCardSys; - CAssetId x0_mlvlId; - CAssetId x4_strgId; - CAssetId x8_savwId; - std::vector xc_areaIds; - std::vector x1c_defaultLayerStates; - std::unique_ptr x2c_dummyWorld; - TLockedToken x34_saveWorld; /* Used to be auto_ptr */ - -public: - CSaveWorldIntermediate(CAssetId mlvl, CAssetId savw); - - bool InitializePump(); -}; - -class CMemoryCardSys -{ - TLockedToken x0_hints; - std::vector> xc_memoryWorlds; /* MLVL as key */ - std::experimental::optional> x1c_worldInter; /* used to be auto_ptr of vector */ - std::vector> x20_scanStates; - rstl::reserved_vector x30_scanCategoryCounts; - -public: - static kabufuda::SystemString ResolveDolphinCardPath(kabufuda::ECardSlot slot); - static kabufuda::SystemString CreateDolphinCard(kabufuda::ECardSlot slot); - static kabufuda::SystemString _CreateDolphinCard(kabufuda::ECardSlot slot); - - using ECardResult = kabufuda::ECardResult; - struct CardResult - { - ECardResult result; - CardResult(ECardResult res) : result(res) {} - operator ECardResult() const { return result; } - operator bool() const { return result != ECardResult::READY; } - }; - - struct CardFileHandle - { - kabufuda::ECardSlot slot; - kabufuda::FileHandle handle; - CardFileHandle(kabufuda::ECardSlot slot) : slot(slot) {} - int getFileNo() const { return handle.getFileNo(); } - }; - - using CardStat = kabufuda::CardStat; - const std::vector& GetHints() const { return x0_hints->GetHints(); } - const std::vector>& GetMemoryWorlds() const { return xc_memoryWorlds; } - const std::vector>& GetScanStates() const { return x20_scanStates; } - u32 GetScanCategoryCount(CSaveWorld::EScanCategory cat) const { return x30_scanCategoryCounts[int(cat)]; } - - std::vector>::const_iterator LookupScanState(CAssetId id) const - { - return - rstl::binary_find(x20_scanStates.cbegin(), x20_scanStates.cend(), id, - [](const std::pair& p) { return p.first; }); - } - - bool HasSaveWorldMemory(CAssetId wldId) const; - const CSaveWorldMemory& GetSaveWorldMemory(CAssetId wldId) const; - - CMemoryCardSys(); - bool InitializePump(); - - struct CCardFileInfo - { - struct Icon - { - CAssetId x0_id; - kabufuda::EAnimationSpeed x4_speed; - TLockedToken x8_tex; - Icon(CAssetId id, kabufuda::EAnimationSpeed speed, CSimplePool& sp, const CVParamTransfer& cv); - }; - - enum class EStatus - { - Standby, - Transferring, - Done - }; - - EStatus x0_status = EStatus::Standby; - //CARDFileInfo x4_info; - CardFileHandle m_handle; - std::string x18_fileName; - std::string x28_comment; - CAssetId x3c_bannerTex; - std::experimental::optional> x40_bannerTok; - rstl::reserved_vector x50_iconToks; - std::vector xf4_saveBuffer; - std::vector x104_cardBuffer; - - CVParamTransfer m_texParam = {new TObjOwnerParam(SBIG('OTEX'))}; - - CCardFileInfo(kabufuda::ECardSlot port, std::string_view name) - : m_handle(port), x18_fileName(name) {} - - void LockBannerToken(CAssetId bannerTxtr, CSimplePool& sp); - void LockIconToken(CAssetId iconTxtr, kabufuda::EAnimationSpeed speed, CSimplePool& sp); - - kabufuda::ECardSlot GetCardPort() const { return m_handle.slot; } - int GetFileNo() const { return m_handle.getFileNo(); } - u32 CalculateBannerDataSize() const; - u32 CalculateTotalDataSize() const; - void BuildCardBuffer(); - void WriteBannerData(CMemoryOutStream& out) const; - void WriteIconData(CMemoryOutStream& out) const; - void SetComment(const std::string& c) { x28_comment = c; } - ECardResult PumpCardTransfer(); - ECardResult GetStatus(CardStat& stat) const; - ECardResult CreateFile(); - ECardResult WriteFile(); - ECardResult CloseFile(); - - CMemoryOutStream BeginMemoryOut(u32 sz) - { - xf4_saveBuffer.resize(sz); - return CMemoryOutStream(xf4_saveBuffer.data(), sz); - } - }; - - std::pair GetAreaAndWorldIdForSaveId(s32 saveId) const; - static kabufuda::ProbeResults CardProbe(kabufuda::ECardSlot port); - static ECardResult MountCard(kabufuda::ECardSlot port); - static ECardResult UnmountCard(kabufuda::ECardSlot port); - static ECardResult CheckCard(kabufuda::ECardSlot port); - static ECardResult CreateFile(kabufuda::ECardSlot port, const char* name, u32 size, CardFileHandle& info); - static ECardResult OpenFile(kabufuda::ECardSlot port, const char* name, CardFileHandle& info); - static ECardResult FastOpenFile(kabufuda::ECardSlot port, int fileNo, CardFileHandle& info); - static ECardResult CloseFile(CardFileHandle& info); - static ECardResult ReadFile(CardFileHandle& info, void* buf, s32 length, s32 offset); - static ECardResult WriteFile(CardFileHandle& info, const void* buf, s32 length, s32 offset); - static ECardResult GetNumFreeBytes(kabufuda::ECardSlot port, s32& freeBytes, s32& freeFiles); - static ECardResult GetSerialNo(kabufuda::ECardSlot port, u64& serialOut); - static ECardResult GetResultCode(kabufuda::ECardSlot port); - static ECardResult GetStatus(kabufuda::ECardSlot port, int fileNo, CardStat& statOut); - static ECardResult SetStatus(kabufuda::ECardSlot port, int fileNo, const CardStat& stat); - static ECardResult DeleteFile(kabufuda::ECardSlot port, const char* name); - static ECardResult FastDeleteFile(kabufuda::ECardSlot port, int fileNo); - static ECardResult Rename(kabufuda::ECardSlot port, const char* oldName, const char* newName); - static ECardResult FormatCard(kabufuda::ECardSlot port); - - static void CommitToDisk(kabufuda::ECardSlot port); - static void Shutdown(); -}; - -} - +} // namespace urde diff --git a/Runtime/CMemoryCardSysNix.cpp b/Runtime/CMemoryCardSysNix.cpp index ffe2bab64..7cb461eae 100644 --- a/Runtime/CMemoryCardSysNix.cpp +++ b/Runtime/CMemoryCardSysNix.cpp @@ -1,57 +1,50 @@ #include "CMemoryCardSys.hpp" -namespace urde -{ +namespace urde { -kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot) -{ - const char* home = getenv("HOME"); - if (!home || home[0] != '/') - return {}; - const char* dataHome = getenv("XDG_DATA_HOME"); +kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot) { + const char* home = getenv("HOME"); + if (!home || home[0] != '/') + return {}; + const char* dataHome = getenv("XDG_DATA_HOME"); - /* XDG-selected data path */ - kabufuda::SystemString path = - ((dataHome && dataHome[0] == '/') ? dataHome : hecl::SystemString(home)) + "/.local/share/dolphin-emu"; - path += hecl::Format("/GC/MemoryCard%c.USA.raw", - slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); + /* XDG-selected data path */ + kabufuda::SystemString path = + ((dataHome && dataHome[0] == '/') ? dataHome : hecl::SystemString(home)) + "/.local/share/dolphin-emu"; + path += hecl::Format("/GC/MemoryCard%c.USA.raw", slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); - hecl::Sstat theStat; + hecl::Sstat theStat; + if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode)) { + /* legacy case for older dolphin versions */ + path = home; + path += hecl::Format("/.dolphin-emu/GC/MemoryCard%c.USA.raw", slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode)) - { - /* legacy case for older dolphin versions */ - path = home; - path += hecl::Format("/.dolphin-emu/GC/MemoryCard%c.USA.raw", - slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); - if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode)) - return {}; - } + return {}; + } - return path; + return path; } -kabufuda::SystemString CMemoryCardSys::_CreateDolphinCard(kabufuda::ECardSlot slot) -{ - const char* home = getenv("HOME"); - if (!home || home[0] != '/') - return {}; - const char* dataHome = getenv("XDG_DATA_HOME"); +kabufuda::SystemString CMemoryCardSys::_CreateDolphinCard(kabufuda::ECardSlot slot) { + const char* home = getenv("HOME"); + if (!home || home[0] != '/') + return {}; + const char* dataHome = getenv("XDG_DATA_HOME"); - /* XDG-selected data path */ - kabufuda::SystemString path = - ((dataHome && dataHome[0] == '/') ? dataHome : hecl::SystemString(home)) + "/.local/share/dolphin-emu/GC"; + /* XDG-selected data path */ + kabufuda::SystemString path = + ((dataHome && dataHome[0] == '/') ? dataHome : hecl::SystemString(home)) + "/.local/share/dolphin-emu/GC"; - if (hecl::RecursiveMakeDir(path.c_str()) < 0) - return {}; + if (hecl::RecursiveMakeDir(path.c_str()) < 0) + return {}; - path += hecl::Format("/MemoryCard%c.USA.raw", - slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); - FILE* fp = hecl::Fopen(path.c_str(), "wb"); - if (!fp) - return {}; - fclose(fp); + path += hecl::Format("/MemoryCard%c.USA.raw", slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); + FILE* fp = hecl::Fopen(path.c_str(), "wb"); + if (!fp) + return {}; + fclose(fp); - return path; + return path; } -} +} // namespace urde diff --git a/Runtime/CMemoryCardSysOSX.cpp b/Runtime/CMemoryCardSysOSX.cpp index b8390fe56..eba648502 100644 --- a/Runtime/CMemoryCardSysOSX.cpp +++ b/Runtime/CMemoryCardSysOSX.cpp @@ -1,44 +1,40 @@ #include "CMemoryCardSys.hpp" -namespace urde -{ +namespace urde { -kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot) -{ - const char* home = getenv("HOME"); - if (!home) - return {}; +kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot) { + const char* home = getenv("HOME"); + if (!home) + return {}; - kabufuda::SystemString path = home; - path += hecl::Format("/Library/Application Support/Dolphin/GC/MemoryCard%c.USA.raw", - slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); + kabufuda::SystemString path = home; + path += hecl::Format("/Library/Application Support/Dolphin/GC/MemoryCard%c.USA.raw", + slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); - hecl::Sstat theStat; - if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode)) - return {}; + hecl::Sstat theStat; + if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode)) + return {}; - return path; + return path; } -kabufuda::SystemString CMemoryCardSys::_CreateDolphinCard(kabufuda::ECardSlot slot) -{ - const char* home = getenv("HOME"); - if (!home) - return {}; +kabufuda::SystemString CMemoryCardSys::_CreateDolphinCard(kabufuda::ECardSlot slot) { + const char* home = getenv("HOME"); + if (!home) + return {}; - kabufuda::SystemString path = home; - path += "/Library/Application Support/Dolphin/GC"; - if (hecl::RecursiveMakeDir(path.c_str()) < 0) - return {}; + kabufuda::SystemString path = home; + path += "/Library/Application Support/Dolphin/GC"; + if (hecl::RecursiveMakeDir(path.c_str()) < 0) + return {}; - path += hecl::Format("/MemoryCard%c.USA.raw", - slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); - FILE* fp = hecl::Fopen(path.c_str(), "wb"); - if (!fp) - return {}; - fclose(fp); + path += hecl::Format("/MemoryCard%c.USA.raw", slot == kabufuda::ECardSlot::SlotA ? 'A' : 'B'); + FILE* fp = hecl::Fopen(path.c_str(), "wb"); + if (!fp) + return {}; + fclose(fp); - return path; + return path; } -} +} // namespace urde diff --git a/Runtime/CMemoryCardSysWin.cpp b/Runtime/CMemoryCardSysWin.cpp index 3a205db70..bc7e906f0 100644 --- a/Runtime/CMemoryCardSysWin.cpp +++ b/Runtime/CMemoryCardSysWin.cpp @@ -1,8 +1,7 @@ #include "CMemoryCardSys.hpp" #include -namespace urde -{ +namespace urde { #if WINDOWS_STORE using namespace Windows::Storage; @@ -11,108 +10,102 @@ using namespace Windows::Storage; /* Partial path-selection logic from * https://github.com/dolphin-emu/dolphin/blob/master/Source/Core/UICommon/UICommon.cpp * Modified to not use dolphin-binary-relative paths. */ -kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot) -{ +kabufuda::SystemString CMemoryCardSys::ResolveDolphinCardPath(kabufuda::ECardSlot slot) { #if !WINDOWS_STORE - /* Detect where the User directory is. There are two different cases - * 1. HKCU\Software\Dolphin Emulator\UserConfigPath exists - * -> Use this as the user directory path - * 2. My Documents exists - * -> Use My Documents\Dolphin Emulator as the User directory path - */ + /* Detect where the User directory is. There are two different cases + * 1. HKCU\Software\Dolphin Emulator\UserConfigPath exists + * -> Use this as the user directory path + * 2. My Documents exists + * -> Use My Documents\Dolphin Emulator as the User directory path + */ - /* Check our registry keys */ - HKEY hkey; - kabufuda::SystemChar configPath[MAX_PATH] = {0}; - if (RegOpenKeyEx(HKEY_CURRENT_USER, _SYS_STR("Software\\Dolphin Emulator"), 0, KEY_QUERY_VALUE, - &hkey) == ERROR_SUCCESS) - { - DWORD size = MAX_PATH; - if (RegQueryValueEx(hkey, _SYS_STR("UserConfigPath"), nullptr, nullptr, (LPBYTE)configPath, - &size) != ERROR_SUCCESS) - configPath[0] = 0; - RegCloseKey(hkey); - } + /* Check our registry keys */ + HKEY hkey; + kabufuda::SystemChar configPath[MAX_PATH] = {0}; + if (RegOpenKeyEx(HKEY_CURRENT_USER, _SYS_STR("Software\\Dolphin Emulator"), 0, KEY_QUERY_VALUE, &hkey) == + ERROR_SUCCESS) { + DWORD size = MAX_PATH; + if (RegQueryValueEx(hkey, _SYS_STR("UserConfigPath"), nullptr, nullptr, (LPBYTE)configPath, &size) != ERROR_SUCCESS) + configPath[0] = 0; + RegCloseKey(hkey); + } - /* Get My Documents path in case we need it. */ - kabufuda::SystemChar my_documents[MAX_PATH]; - bool my_documents_found = SUCCEEDED( - SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, my_documents)); + /* Get My Documents path in case we need it. */ + kabufuda::SystemChar my_documents[MAX_PATH]; + bool my_documents_found = + SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, my_documents)); - kabufuda::SystemString path; - if (configPath[0]) /* Case 1 */ - path = configPath; - else if (my_documents_found) /* Case 2 */ - path = kabufuda::SystemString(my_documents) + _SYS_STR("/Dolphin Emulator"); - else /* Unable to find */ - return {}; + kabufuda::SystemString path; + if (configPath[0]) /* Case 1 */ + path = configPath; + else if (my_documents_found) /* Case 2 */ + path = kabufuda::SystemString(my_documents) + _SYS_STR("/Dolphin Emulator"); + else /* Unable to find */ + return {}; #else - StorageFolder^ localFolder = ApplicationData::Current->LocalFolder; - kabufuda::SystemString path(localFolder->Path->Data()); + StorageFolder ^ localFolder = ApplicationData::Current->LocalFolder; + kabufuda::SystemString path(localFolder->Path->Data()); #endif - path += hecl::SysFormat(_SYS_STR("/GC/MemoryCard%c.USA.raw"), - slot == kabufuda::ECardSlot::SlotA ? _SYS_STR('A') : _SYS_STR('B')); + path += hecl::SysFormat(_SYS_STR("/GC/MemoryCard%c.USA.raw"), + slot == kabufuda::ECardSlot::SlotA ? _SYS_STR('A') : _SYS_STR('B')); - hecl::Sstat theStat; - if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode)) - return {}; + hecl::Sstat theStat; + if (hecl::Stat(path.c_str(), &theStat) || !S_ISREG(theStat.st_mode)) + return {}; - return path; + return path; } -kabufuda::SystemString CMemoryCardSys::_CreateDolphinCard(kabufuda::ECardSlot slot) -{ +kabufuda::SystemString CMemoryCardSys::_CreateDolphinCard(kabufuda::ECardSlot slot) { #if !WINDOWS_STORE - /* Detect where the User directory is. There are two different cases - * 1. HKCU\Software\Dolphin Emulator\UserConfigPath exists - * -> Use this as the user directory path - * 2. My Documents exists - * -> Use My Documents\Dolphin Emulator as the User directory path - */ + /* Detect where the User directory is. There are two different cases + * 1. HKCU\Software\Dolphin Emulator\UserConfigPath exists + * -> Use this as the user directory path + * 2. My Documents exists + * -> Use My Documents\Dolphin Emulator as the User directory path + */ - /* Check our registry keys */ - HKEY hkey; - kabufuda::SystemChar configPath[MAX_PATH] = {0}; - if (RegOpenKeyEx(HKEY_CURRENT_USER, _SYS_STR("Software\\Dolphin Emulator"), 0, KEY_QUERY_VALUE, - &hkey) == ERROR_SUCCESS) - { - DWORD size = MAX_PATH; - if (RegQueryValueEx(hkey, _SYS_STR("UserConfigPath"), nullptr, nullptr, (LPBYTE)configPath, - &size) != ERROR_SUCCESS) - configPath[0] = 0; - RegCloseKey(hkey); - } + /* Check our registry keys */ + HKEY hkey; + kabufuda::SystemChar configPath[MAX_PATH] = {0}; + if (RegOpenKeyEx(HKEY_CURRENT_USER, _SYS_STR("Software\\Dolphin Emulator"), 0, KEY_QUERY_VALUE, &hkey) == + ERROR_SUCCESS) { + DWORD size = MAX_PATH; + if (RegQueryValueEx(hkey, _SYS_STR("UserConfigPath"), nullptr, nullptr, (LPBYTE)configPath, &size) != ERROR_SUCCESS) + configPath[0] = 0; + RegCloseKey(hkey); + } - /* Get My Documents path in case we need it. */ - kabufuda::SystemChar my_documents[MAX_PATH]; - bool my_documents_found = SUCCEEDED( - SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, my_documents)); + /* Get My Documents path in case we need it. */ + kabufuda::SystemChar my_documents[MAX_PATH]; + bool my_documents_found = + SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_MYDOCUMENTS, nullptr, SHGFP_TYPE_CURRENT, my_documents)); - kabufuda::SystemString path; - if (configPath[0]) /* Case 1 */ - path = configPath; - else if (my_documents_found) /* Case 2 */ - path = kabufuda::SystemString(my_documents) + _SYS_STR("/Dolphin Emulator"); - else /* Unable to find */ - return {}; + kabufuda::SystemString path; + if (configPath[0]) /* Case 1 */ + path = configPath; + else if (my_documents_found) /* Case 2 */ + path = kabufuda::SystemString(my_documents) + _SYS_STR("/Dolphin Emulator"); + else /* Unable to find */ + return {}; #else - StorageFolder^ localFolder = ApplicationData::Current->LocalFolder; - kabufuda::SystemString path(localFolder->Path->Data()); + StorageFolder ^ localFolder = ApplicationData::Current->LocalFolder; + kabufuda::SystemString path(localFolder->Path->Data()); #endif - path += _SYS_STR("/GC"); - if (hecl::RecursiveMakeDir(path.c_str()) < 0) - return {}; + path += _SYS_STR("/GC"); + if (hecl::RecursiveMakeDir(path.c_str()) < 0) + return {}; - path += hecl::SysFormat(_SYS_STR("/MemoryCard%c.USA.raw"), - slot == kabufuda::ECardSlot::SlotA ? _SYS_STR('A') : _SYS_STR('B')); - FILE* fp = hecl::Fopen(path.c_str(), _SYS_STR("wb")); - if (!fp) - return {}; - fclose(fp); + path += hecl::SysFormat(_SYS_STR("/MemoryCard%c.USA.raw"), + slot == kabufuda::ECardSlot::SlotA ? _SYS_STR('A') : _SYS_STR('B')); + FILE* fp = hecl::Fopen(path.c_str(), _SYS_STR("wb")); + if (!fp) + return {}; + fclose(fp); - return path; + return path; } -} +} // namespace urde diff --git a/Runtime/CObjectList.cpp b/Runtime/CObjectList.cpp index ba139dfd6..21d63de49 100644 --- a/Runtime/CObjectList.cpp +++ b/Runtime/CObjectList.cpp @@ -1,111 +1,96 @@ #include "CObjectList.hpp" -namespace urde -{ +namespace urde { -CObjectList::CObjectList(EGameObjectList listEnum) -: x2004_listEnum(listEnum) -{} +CObjectList::CObjectList(EGameObjectList listEnum) : x2004_listEnum(listEnum) {} -void CObjectList::AddObject(CEntity& entity) -{ - if (IsQualified(entity)) - { - if (x2008_firstId != -1) - x0_list[x2008_firstId].prev = entity.GetUniqueId().Value(); - s16 prevFirst = x2008_firstId; - x2008_firstId = entity.GetUniqueId().Value(); - SObjectListEntry& newEnt = x0_list[x2008_firstId]; - newEnt.entity = &entity; - newEnt.next = prevFirst; - newEnt.prev = -1; - ++x200a_count; - } +void CObjectList::AddObject(CEntity& entity) { + if (IsQualified(entity)) { + if (x2008_firstId != -1) + x0_list[x2008_firstId].prev = entity.GetUniqueId().Value(); + s16 prevFirst = x2008_firstId; + x2008_firstId = entity.GetUniqueId().Value(); + SObjectListEntry& newEnt = x0_list[x2008_firstId]; + newEnt.entity = &entity; + newEnt.next = prevFirst; + newEnt.prev = -1; + ++x200a_count; + } } -void CObjectList::RemoveObject(TUniqueId uid) -{ - SObjectListEntry& ent = x0_list[uid.Value()]; - if (!ent.entity || ent.entity->GetUniqueId() != uid) - return; - if (uid.Value() == x2008_firstId) - { - x2008_firstId = ent.next; - if (ent.next != -1) - x0_list[ent.next].prev = -1; - } - else - { - x0_list[ent.prev].next = ent.next; - if (ent.next != -1) - x0_list[ent.next].prev = ent.prev; - } - ent.entity = nullptr; - ent.next = -1; - ent.prev = -1; - --x200a_count; +void CObjectList::RemoveObject(TUniqueId uid) { + SObjectListEntry& ent = x0_list[uid.Value()]; + if (!ent.entity || ent.entity->GetUniqueId() != uid) + return; + if (uid.Value() == x2008_firstId) { + x2008_firstId = ent.next; + if (ent.next != -1) + x0_list[ent.next].prev = -1; + } else { + x0_list[ent.prev].next = ent.next; + if (ent.next != -1) + x0_list[ent.next].prev = ent.prev; + } + ent.entity = nullptr; + ent.next = -1; + ent.prev = -1; + --x200a_count; } -const CEntity* CObjectList::operator[](size_t i) const -{ - const SObjectListEntry& ent = x0_list[i]; - if (!ent.entity || ent.entity->x30_26_scriptingBlocked) - return nullptr; - return ent.entity; +const CEntity* CObjectList::operator[](size_t i) const { + const SObjectListEntry& ent = x0_list[i]; + if (!ent.entity || ent.entity->x30_26_scriptingBlocked) + return nullptr; + return ent.entity; } -CEntity* CObjectList::operator[](size_t i) -{ - SObjectListEntry& ent = x0_list[i]; - if (!ent.entity || ent.entity->x30_26_scriptingBlocked) - return nullptr; - return ent.entity; +CEntity* CObjectList::operator[](size_t i) { + SObjectListEntry& ent = x0_list[i]; + if (!ent.entity || ent.entity->x30_26_scriptingBlocked) + return nullptr; + return ent.entity; } -const CEntity* CObjectList::GetObjectById(TUniqueId uid) const -{ - if (uid == kInvalidUniqueId) - return nullptr; - const SObjectListEntry& ent = x0_list[uid.Value()]; - if (!ent.entity || ent.entity->x30_26_scriptingBlocked) - return nullptr; - return ent.entity; +const CEntity* CObjectList::GetObjectById(TUniqueId uid) const { + if (uid == kInvalidUniqueId) + return nullptr; + const SObjectListEntry& ent = x0_list[uid.Value()]; + if (!ent.entity || ent.entity->x30_26_scriptingBlocked) + return nullptr; + return ent.entity; } -CEntity* CObjectList::GetObjectById(TUniqueId uid) -{ - if (uid == kInvalidUniqueId) - return nullptr; - SObjectListEntry& ent = x0_list[uid.Value()]; - if (!ent.entity || ent.entity->x30_26_scriptingBlocked) - return nullptr; - return ent.entity; +CEntity* CObjectList::GetObjectById(TUniqueId uid) { + if (uid == kInvalidUniqueId) + return nullptr; + SObjectListEntry& ent = x0_list[uid.Value()]; + if (!ent.entity || ent.entity->x30_26_scriptingBlocked) + return nullptr; + return ent.entity; } -const CEntity* CObjectList::GetValidObjectById(TUniqueId uid) const -{ - if (uid == kInvalidUniqueId) - return nullptr; - const SObjectListEntry& ent = x0_list[uid.Value()]; - if (!ent.entity) - return nullptr; - if (ent.entity->GetUniqueId() != uid) - return nullptr; - return ent.entity; +const CEntity* CObjectList::GetValidObjectById(TUniqueId uid) const { + if (uid == kInvalidUniqueId) + return nullptr; + const SObjectListEntry& ent = x0_list[uid.Value()]; + if (!ent.entity) + return nullptr; + if (ent.entity->GetUniqueId() != uid) + return nullptr; + return ent.entity; } -CEntity* CObjectList::GetValidObjectById(TUniqueId uid) -{ - if (uid == kInvalidUniqueId) - return nullptr; - SObjectListEntry& ent = x0_list[uid.Value()]; - if (!ent.entity) - return nullptr; - if (ent.entity->GetUniqueId() != uid) - return nullptr; - return ent.entity; +CEntity* CObjectList::GetValidObjectById(TUniqueId uid) { + if (uid == kInvalidUniqueId) + return nullptr; + SObjectListEntry& ent = x0_list[uid.Value()]; + if (!ent.entity) + return nullptr; + if (ent.entity->GetUniqueId() != uid) + return nullptr; + return ent.entity; } -bool CObjectList::IsQualified(const CEntity&) {return true;} +bool CObjectList::IsQualified(const CEntity&) { return true; } -} +} // namespace urde diff --git a/Runtime/CObjectList.hpp b/Runtime/CObjectList.hpp index c602b2ce0..aa92513bb 100644 --- a/Runtime/CObjectList.hpp +++ b/Runtime/CObjectList.hpp @@ -3,83 +3,85 @@ #include "World/CEntity.hpp" #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -enum class EGameObjectList -{ - Invalid = -1, - All, - Actor, - PhysicsActor, - GameCamera, - GameLight, - ListeningAi, - AiWaypoint, - PlatformAndDoor, +enum class EGameObjectList { + Invalid = -1, + All, + Actor, + PhysicsActor, + GameCamera, + GameLight, + ListeningAi, + AiWaypoint, + PlatformAndDoor, }; -class CObjectList -{ - friend class CGameArea; +class CObjectList { + friend class CGameArea; + + struct SObjectListEntry { + CEntity* entity = nullptr; + s16 next = -1; + s16 prev = -1; + }; + SObjectListEntry x0_list[1024]; // was an rstl::prereserved_vector + EGameObjectList x2004_listEnum; + s16 x2008_firstId = -1; + u16 x200a_count = 0; - struct SObjectListEntry - { - CEntity* entity = nullptr; - s16 next = -1; - s16 prev = -1; - }; - SObjectListEntry x0_list[1024]; // was an rstl::prereserved_vector - EGameObjectList x2004_listEnum; - s16 x2008_firstId = -1; - u16 x200a_count = 0; public: - class iterator - { - friend class CObjectList; - CObjectList& m_list; - s16 m_id; - iterator(CObjectList& list, s16 id) : m_list(list), m_id(id) {} - public: - iterator& operator++() { m_id = m_list.GetNextObjectIndex(m_id); return *this; } - bool operator!=(const iterator& other) const { return m_id != other.m_id; } - CEntity* operator*() const { return m_list.GetObjectByIndex(m_id); } - }; - iterator begin() { return iterator(*this, x2008_firstId); } - iterator end() { return iterator(*this, -1); } + class iterator { + friend class CObjectList; + CObjectList& m_list; + s16 m_id; + iterator(CObjectList& list, s16 id) : m_list(list), m_id(id) {} - class const_iterator - { - friend class CObjectList; - const CObjectList& m_list; - s16 m_id; - const_iterator(const CObjectList& list, s16 id) : m_list(list), m_id(id) {} - public: - const_iterator& operator++() { m_id = m_list.GetNextObjectIndex(m_id); return *this; } - bool operator!=(const iterator& other) const { return m_id != other.m_id; } - const CEntity* operator*() const { return m_list.GetObjectByIndex(m_id); } - }; - const_iterator cbegin() const { return const_iterator(*this, x2008_firstId); } - const_iterator cend() const { return const_iterator(*this, -1); } + public: + iterator& operator++() { + m_id = m_list.GetNextObjectIndex(m_id); + return *this; + } + bool operator!=(const iterator& other) const { return m_id != other.m_id; } + CEntity* operator*() const { return m_list.GetObjectByIndex(m_id); } + }; + iterator begin() { return iterator(*this, x2008_firstId); } + iterator end() { return iterator(*this, -1); } - CObjectList(EGameObjectList listEnum); - virtual ~CObjectList() = default; + class const_iterator { + friend class CObjectList; + const CObjectList& m_list; + s16 m_id; + const_iterator(const CObjectList& list, s16 id) : m_list(list), m_id(id) {} - void AddObject(CEntity& entity); - void RemoveObject(TUniqueId uid); - const CEntity* operator[](size_t i) const; - CEntity* operator[](size_t i); - const CEntity* GetObjectById(TUniqueId uid) const; - const CEntity* GetObjectByIndex(s16 index) const { return x0_list[index].entity; } - CEntity* GetObjectByIndex(s16 index) { return x0_list[index].entity; } - CEntity* GetObjectById(TUniqueId uid); - const CEntity* GetValidObjectById(TUniqueId uid) const; - CEntity* GetValidObjectById(TUniqueId uid); - s16 GetFirstObjectIndex() const { return x2008_firstId; } - s16 GetNextObjectIndex(s16 prev) const { return x0_list[prev].next; } - virtual bool IsQualified(const CEntity&); - u16 size() const { return x200a_count; } + public: + const_iterator& operator++() { + m_id = m_list.GetNextObjectIndex(m_id); + return *this; + } + bool operator!=(const iterator& other) const { return m_id != other.m_id; } + const CEntity* operator*() const { return m_list.GetObjectByIndex(m_id); } + }; + const_iterator cbegin() const { return const_iterator(*this, x2008_firstId); } + const_iterator cend() const { return const_iterator(*this, -1); } + + CObjectList(EGameObjectList listEnum); + virtual ~CObjectList() = default; + + void AddObject(CEntity& entity); + void RemoveObject(TUniqueId uid); + const CEntity* operator[](size_t i) const; + CEntity* operator[](size_t i); + const CEntity* GetObjectById(TUniqueId uid) const; + const CEntity* GetObjectByIndex(s16 index) const { return x0_list[index].entity; } + CEntity* GetObjectByIndex(s16 index) { return x0_list[index].entity; } + CEntity* GetObjectById(TUniqueId uid); + const CEntity* GetValidObjectById(TUniqueId uid) const; + CEntity* GetValidObjectById(TUniqueId uid); + s16 GetFirstObjectIndex() const { return x2008_firstId; } + s16 GetNextObjectIndex(s16 prev) const { return x0_list[prev].next; } + virtual bool IsQualified(const CEntity&); + u16 size() const { return x200a_count; } }; -} - +} // namespace urde diff --git a/Runtime/CPakFile.cpp b/Runtime/CPakFile.cpp index 9be1834b0..38374113f 100644 --- a/Runtime/CPakFile.cpp +++ b/Runtime/CPakFile.cpp @@ -1,203 +1,180 @@ #include "CPakFile.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CPakFile"); -CPakFile::CPakFile(std::string_view filename, bool buildDepList, bool worldPak) -: CDvdFile(filename) -{ - if (!CDvdFile::operator bool()) - Log.report(logvisor::Fatal, "%s: Unable to open", GetPath().data()); - x28_24_buildDepList = buildDepList; - x28_24_buildDepList = true; // Always do this so URDE can rapidly pre-warm shaders - x28_26_worldPak = worldPak; - x28_27_stashedInARAM = false; +CPakFile::CPakFile(std::string_view filename, bool buildDepList, bool worldPak) : CDvdFile(filename) { + if (!CDvdFile::operator bool()) + Log.report(logvisor::Fatal, "%s: Unable to open", GetPath().data()); + x28_24_buildDepList = buildDepList; + x28_24_buildDepList = true; // Always do this so URDE can rapidly pre-warm shaders + x28_26_worldPak = worldPak; + x28_27_stashedInARAM = false; } -CPakFile::~CPakFile() -{ - if (x30_dvdReq) - x30_dvdReq->PostCancelRequest(); +CPakFile::~CPakFile() { + if (x30_dvdReq) + x30_dvdReq->PostCancelRequest(); } -const SObjectTag* CPakFile::GetResIdByName(std::string_view name) const -{ - for (const std::pair& p : x54_nameList) - if (!CStringExtras::CompareCaseInsensitive(p.first.c_str(), name)) - return &p.second; - return nullptr; +const SObjectTag* CPakFile::GetResIdByName(std::string_view name) const { + for (const std::pair& p : x54_nameList) + if (!CStringExtras::CompareCaseInsensitive(p.first.c_str(), name)) + return &p.second; + return nullptr; } -void CPakFile::LoadResourceTable(athena::io::MemoryReader& r) -{ - x74_resList.reserve(std::max(size_t(64), size_t(ROUND_UP_32(x4c_resTableCount * sizeof(SResInfo)) + - sizeof(SResInfo) - 1)) / sizeof(SResInfo)); +void CPakFile::LoadResourceTable(athena::io::MemoryReader& r) { + x74_resList.reserve( + std::max(size_t(64), size_t(ROUND_UP_32(x4c_resTableCount * sizeof(SResInfo)) + sizeof(SResInfo) - 1)) / + sizeof(SResInfo)); + if (x28_24_buildDepList) + x64_depList.reserve(x4c_resTableCount); + for (u32 i = 0; i < x4c_resTableCount; ++i) { + u32 flags = r.readUint32Big(); + FourCC fcc; + r.readBytesToBuf(&fcc, 4); + CAssetId id = r.readUint32Big(); + u32 size = r.readUint32Big(); + u32 offset = r.readUint32Big(); + if (fcc == FOURCC('MLVL')) + m_mlvlId = id; + x74_resList.emplace_back(id, fcc, offset, size, flags); if (x28_24_buildDepList) - x64_depList.reserve(x4c_resTableCount); - for (u32 i=0 ; i origSize) - { - x38_headerData.resize(newSize); - x30_dvdReq = AsyncSeekRead(x38_headerData.data() + origSize, u32(x38_headerData.size() - origSize), - ESeekOrigin::Begin, origSize); - } - else - { - DataLoad(); - } + x4c_resTableCount = r.readUint32Big(); + x48_resTableOffset = u32(r.position()); + x2c_asyncLoadPhase = EAsyncPhase::DataLoad; + u32 newSize = ROUND_UP_32(x4c_resTableCount * 20 + x48_resTableOffset); + u32 origSize = u32(x38_headerData.size()); + if (newSize > origSize) { + x38_headerData.resize(newSize); + x30_dvdReq = AsyncSeekRead(x38_headerData.data() + origSize, u32(x38_headerData.size() - origSize), + ESeekOrigin::Begin, origSize); + } else { + DataLoad(); + } }; -void CPakFile::Warmup() -{ - u32 length = std::min(u32(Length()), u32(8192)); - x38_headerData.resize(length); - x30_dvdReq = AsyncSeekRead(x38_headerData.data(), length, ESeekOrigin::Cur, 0); - x2c_asyncLoadPhase = EAsyncPhase::InitialHeader; +void CPakFile::Warmup() { + u32 length = std::min(u32(Length()), u32(8192)); + x38_headerData.resize(length); + x30_dvdReq = AsyncSeekRead(x38_headerData.data(), length, ESeekOrigin::Cur, 0); + x2c_asyncLoadPhase = EAsyncPhase::InitialHeader; } -const CPakFile::SResInfo* CPakFile::GetResInfoForLoadPreferForward(CAssetId id) const -{ - if (x28_27_stashedInARAM) - return nullptr; - auto search = rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, - [](const SResInfo& test) { return test.x0_id; }); - if (search == x74_resList.end()) - return nullptr; - const SResInfo* bestInfo = &*search; - s32 bestDelta = x84_currentSeek - bestInfo->GetOffset(); - while (++search != x74_resList.end()) - { - const SResInfo* thisInfo = &*search; - if (thisInfo->x0_id != id) - break; - s32 thisDelta = x84_currentSeek - bestInfo->GetOffset(); - if ((bestDelta < 0 && (thisDelta > 0 || thisDelta > bestDelta)) || - (bestDelta >= 0 && thisDelta > 0 && thisDelta < bestDelta)) - { - bestDelta = thisDelta; - bestInfo = thisInfo; - } +const CPakFile::SResInfo* CPakFile::GetResInfoForLoadPreferForward(CAssetId id) const { + if (x28_27_stashedInARAM) + return nullptr; + auto search = + rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, [](const SResInfo& test) { return test.x0_id; }); + if (search == x74_resList.end()) + return nullptr; + const SResInfo* bestInfo = &*search; + s32 bestDelta = x84_currentSeek - bestInfo->GetOffset(); + while (++search != x74_resList.end()) { + const SResInfo* thisInfo = &*search; + if (thisInfo->x0_id != id) + break; + s32 thisDelta = x84_currentSeek - bestInfo->GetOffset(); + if ((bestDelta < 0 && (thisDelta > 0 || thisDelta > bestDelta)) || + (bestDelta >= 0 && thisDelta > 0 && thisDelta < bestDelta)) { + bestDelta = thisDelta; + bestInfo = thisInfo; } - x84_currentSeek = bestInfo->GetOffset() + bestInfo->GetSize(); - return bestInfo; + } + x84_currentSeek = bestInfo->GetOffset() + bestInfo->GetSize(); + return bestInfo; } -const CPakFile::SResInfo* CPakFile::GetResInfoForLoadDirectionless(CAssetId id) const -{ - if (x28_27_stashedInARAM) - return nullptr; - auto search = rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, - [](const SResInfo& test) { return test.x0_id; }); - if (search == x74_resList.end()) - return nullptr; - const SResInfo* bestInfo = &*search; - s32 bestDelta = std::abs(s32(x84_currentSeek - bestInfo->GetOffset())); - while (++search != x74_resList.end()) - { - const SResInfo* thisInfo = &*search; - if (thisInfo->x0_id != id) - break; - s32 thisDelta = std::abs(s32(x84_currentSeek - bestInfo->GetOffset())); - if (thisDelta < bestDelta) - { - bestDelta = thisDelta; - bestInfo = thisInfo; - } +const CPakFile::SResInfo* CPakFile::GetResInfoForLoadDirectionless(CAssetId id) const { + if (x28_27_stashedInARAM) + return nullptr; + auto search = + rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, [](const SResInfo& test) { return test.x0_id; }); + if (search == x74_resList.end()) + return nullptr; + const SResInfo* bestInfo = &*search; + s32 bestDelta = std::abs(s32(x84_currentSeek - bestInfo->GetOffset())); + while (++search != x74_resList.end()) { + const SResInfo* thisInfo = &*search; + if (thisInfo->x0_id != id) + break; + s32 thisDelta = std::abs(s32(x84_currentSeek - bestInfo->GetOffset())); + if (thisDelta < bestDelta) { + bestDelta = thisDelta; + bestInfo = thisInfo; } - x84_currentSeek = bestInfo->GetOffset() + bestInfo->GetSize(); - return bestInfo; + } + x84_currentSeek = bestInfo->GetOffset() + bestInfo->GetSize(); + return bestInfo; } -const CPakFile::SResInfo* CPakFile::GetResInfo(CAssetId id) const -{ - if (x2c_asyncLoadPhase != EAsyncPhase::Loaded) - return nullptr; - if (x28_27_stashedInARAM) - return nullptr; - auto search = rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, - [](const SResInfo& i) { return i.x0_id; }); - if (search == x74_resList.end()) - return nullptr; - return &*search; +const CPakFile::SResInfo* CPakFile::GetResInfo(CAssetId id) const { + if (x2c_asyncLoadPhase != EAsyncPhase::Loaded) + return nullptr; + if (x28_27_stashedInARAM) + return nullptr; + auto search = + rstl::binary_find(x74_resList.begin(), x74_resList.end(), id, [](const SResInfo& i) { return i.x0_id; }); + if (search == x74_resList.end()) + return nullptr; + return &*search; } -void CPakFile::AsyncIdle() -{ - if (x2c_asyncLoadPhase == EAsyncPhase::Loaded) - return; - if (x30_dvdReq && !x30_dvdReq->IsComplete()) - return; - switch (x2c_asyncLoadPhase) - { - case EAsyncPhase::Warmup: - Warmup(); - break; - case EAsyncPhase::InitialHeader: - InitialHeaderLoad(); - break; - case EAsyncPhase::DataLoad: - DataLoad(); - break; - default: break; - } +void CPakFile::AsyncIdle() { + if (x2c_asyncLoadPhase == EAsyncPhase::Loaded) + return; + if (x30_dvdReq && !x30_dvdReq->IsComplete()) + return; + switch (x2c_asyncLoadPhase) { + case EAsyncPhase::Warmup: + Warmup(); + break; + case EAsyncPhase::InitialHeader: + InitialHeaderLoad(); + break; + case EAsyncPhase::DataLoad: + DataLoad(); + break; + default: + break; + } } -} +} // namespace urde diff --git a/Runtime/CPakFile.hpp b/Runtime/CPakFile.hpp index 761a5bfd8..d5fbd37e9 100644 --- a/Runtime/CPakFile.hpp +++ b/Runtime/CPakFile.hpp @@ -7,81 +7,75 @@ #include "CDvdRequest.hpp" #include "CFactoryMgr.hpp" -namespace urde -{ +namespace urde { + +class CPakFile : public CDvdFile { + friend class CResLoader; -class CPakFile : public CDvdFile -{ - friend class CResLoader; public: - struct SResInfo - { - CAssetId x0_id; - bool x4_compressed : 1; - CFactoryMgr::ETypeTable x4_typeIdx : 7; - u32 x5_offsetDiv32 : 27; - u32 x7_sizeDiv32 : 27; - SResInfo(CAssetId id, FourCC fcc, u32 offset, u32 size, u32 flags) - : x0_id(id) - { - x4_compressed = flags != 0; - x4_typeIdx = CFactoryMgr::FourCCToTypeIdx(fcc); - x5_offsetDiv32 = offset / 32; - x7_sizeDiv32 = size / 32; - } - u32 GetOffset() const { return x5_offsetDiv32 * 32; } - u32 GetSize() const { return x7_sizeDiv32 * 32; } - FourCC GetType() const { return CFactoryMgr::TypeIdxToFourCC(x4_typeIdx); } - bool IsCompressed() const { return x4_compressed; } - CAssetId GetId() const { return x0_id; } - }; + struct SResInfo { + CAssetId x0_id; + bool x4_compressed : 1; + CFactoryMgr::ETypeTable x4_typeIdx : 7; + u32 x5_offsetDiv32 : 27; + u32 x7_sizeDiv32 : 27; + SResInfo(CAssetId id, FourCC fcc, u32 offset, u32 size, u32 flags) : x0_id(id) { + x4_compressed = flags != 0; + x4_typeIdx = CFactoryMgr::FourCCToTypeIdx(fcc); + x5_offsetDiv32 = offset / 32; + x7_sizeDiv32 = size / 32; + } + u32 GetOffset() const { return x5_offsetDiv32 * 32; } + u32 GetSize() const { return x7_sizeDiv32 * 32; } + FourCC GetType() const { return CFactoryMgr::TypeIdxToFourCC(x4_typeIdx); } + bool IsCompressed() const { return x4_compressed; } + CAssetId GetId() const { return x0_id; } + }; + private: - union - { - struct - { - bool x28_24_buildDepList; - bool x28_25_aramFile; - bool x28_26_worldPak; - bool x28_27_stashedInARAM; - }; - u32 _dummy = 0; + union { + struct { + bool x28_24_buildDepList; + bool x28_25_aramFile; + bool x28_26_worldPak; + bool x28_27_stashedInARAM; }; - enum class EAsyncPhase - { - Warmup = 0, - InitialHeader = 1, - DataLoad = 2, - Loaded = 3 - } x2c_asyncLoadPhase = EAsyncPhase::Warmup; - std::shared_ptr x30_dvdReq; // Used to be auto_ptr - std::vector x38_headerData; - u32 x48_resTableOffset = 0; - u32 x4c_resTableCount = 0; - int x50_aramBase = -1; - std::vector> x54_nameList; - std::vector x64_depList; - std::vector x74_resList; - mutable s32 x84_currentSeek = -1; - CAssetId m_mlvlId; - void LoadResourceTable(athena::io::MemoryReader& r); - void DataLoad(); - void InitialHeaderLoad(); - void Warmup(); + u32 _dummy = 0; + }; + enum class EAsyncPhase { + Warmup = 0, + InitialHeader = 1, + DataLoad = 2, + Loaded = 3 + } x2c_asyncLoadPhase = EAsyncPhase::Warmup; + std::shared_ptr x30_dvdReq; // Used to be auto_ptr + std::vector x38_headerData; + u32 x48_resTableOffset = 0; + u32 x4c_resTableCount = 0; + int x50_aramBase = -1; + std::vector> x54_nameList; + std::vector x64_depList; + std::vector x74_resList; + mutable s32 x84_currentSeek = -1; + CAssetId m_mlvlId; + void LoadResourceTable(athena::io::MemoryReader& r); + void DataLoad(); + void InitialHeaderLoad(); + void Warmup(); + public: - CPakFile(std::string_view filename, bool buildDepList, bool worldPak); - ~CPakFile(); - const std::vector>& GetNameList() const { return x54_nameList; } - const std::vector& GetDepList() const { return x64_depList; } - const SObjectTag* GetResIdByName(std::string_view name) const; - const SResInfo* GetResInfoForLoadPreferForward(CAssetId id) const; - const SResInfo* GetResInfoForLoadDirectionless(CAssetId id) const; - const SResInfo* GetResInfo(CAssetId id) const; - bool IsWorldPak() const { return x28_26_worldPak; } - u32 GetFakeStaticSize() const { return 0; } - void AsyncIdle(); - CAssetId GetMLVLId() const { return m_mlvlId; } + CPakFile(std::string_view filename, bool buildDepList, bool worldPak); + ~CPakFile(); + const std::vector>& GetNameList() const { return x54_nameList; } + const std::vector& GetDepList() const { return x64_depList; } + const SObjectTag* GetResIdByName(std::string_view name) const; + const SResInfo* GetResInfoForLoadPreferForward(CAssetId id) const; + const SResInfo* GetResInfoForLoadDirectionless(CAssetId id) const; + const SResInfo* GetResInfo(CAssetId id) const; + bool IsWorldPak() const { return x28_26_worldPak; } + u32 GetFakeStaticSize() const { return 0; } + void AsyncIdle(); + CAssetId GetMLVLId() const { return m_mlvlId; } }; -} - +} // namespace urde diff --git a/Runtime/CPlayMovieBase.hpp b/Runtime/CPlayMovieBase.hpp index 4f7e457da..a4dec0946 100644 --- a/Runtime/CPlayMovieBase.hpp +++ b/Runtime/CPlayMovieBase.hpp @@ -3,18 +3,15 @@ #include "CIOWin.hpp" #include "Graphics/CMoviePlayer.hpp" -namespace urde -{ +namespace urde { + +class CPlayMovieBase : public CIOWin { + CMoviePlayer x18_moviePlayer; -class CPlayMovieBase : public CIOWin -{ - CMoviePlayer x18_moviePlayer; public: - CPlayMovieBase(const char* iowName, const char* path) - : CIOWin(iowName), x18_moviePlayer(path, 0.0, false, false) {} - EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&) {return EMessageReturn::Normal;} - void Draw() const {} + CPlayMovieBase(const char* iowName, const char* path) : CIOWin(iowName), x18_moviePlayer(path, 0.0, false, false) {} + EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&) { return EMessageReturn::Normal; } + void Draw() const {} }; -} - +} // namespace urde diff --git a/Runtime/CPlayerState.cpp b/Runtime/CPlayerState.cpp index 853954c8a..300e475a0 100644 --- a/Runtime/CPlayerState.cpp +++ b/Runtime/CPlayerState.cpp @@ -7,15 +7,11 @@ #include "CMemoryCardSys.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ -const u32 CPlayerState::PowerUpMaxValues[41] = -{ 1, 1, 1, 1, 250, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 14, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -}; +namespace urde { +const u32 CPlayerState::PowerUpMaxValues[41] = {1, 1, 1, 1, 250, 1, 1, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 14, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; -const char* CPlayerState::PowerUpNames[41]= -{ +const char* CPlayerState::PowerUpNames[41] = { "Power Beam", "Ice Beam", "Wave Beam", @@ -59,392 +55,320 @@ const char* CPlayerState::PowerUpNames[41]= "Artifact of Newborn", }; -CPlayerState::CPlayerState() -: x188_staticIntf(5) -{ - x0_24_alive = true; - x24_powerups.resize(41); +CPlayerState::CPlayerState() : x188_staticIntf(5) { + x0_24_alive = true; + x24_powerups.resize(41); } -CPlayerState::CPlayerState(CBitStreamReader& stream) -: x188_staticIntf(5) -{ - x0_24_alive = true; - x4_enabledItems = u32(stream.ReadEncoded(32)); - union - { - float fHP; - u32 iHP; - } hp; - hp.iHP = u32(stream.ReadEncoded(32)); - xc_health.SetHP(hp.fHP); - x8_currentBeam = EBeamId(stream.ReadEncoded(CBitStreamReader::GetBitCount(5))); - x20_currentSuit = EPlayerSuit(stream.ReadEncoded(CBitStreamReader::GetBitCount(4))); - x24_powerups.resize(41); - for (u32 i = 0; i < x24_powerups.size(); ++i) - { - if (PowerUpMaxValues[i] == 0) - continue; +CPlayerState::CPlayerState(CBitStreamReader& stream) : x188_staticIntf(5) { + x0_24_alive = true; + x4_enabledItems = u32(stream.ReadEncoded(32)); + union { + float fHP; + u32 iHP; + } hp; + hp.iHP = u32(stream.ReadEncoded(32)); + xc_health.SetHP(hp.fHP); + x8_currentBeam = EBeamId(stream.ReadEncoded(CBitStreamReader::GetBitCount(5))); + x20_currentSuit = EPlayerSuit(stream.ReadEncoded(CBitStreamReader::GetBitCount(4))); + x24_powerups.resize(41); + for (u32 i = 0; i < x24_powerups.size(); ++i) { + if (PowerUpMaxValues[i] == 0) + continue; - u32 a = u32(stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i]))); - u32 b = u32(stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i]))); - x24_powerups[i] = CPowerUp(a, b); - } + u32 a = u32(stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i]))); + u32 b = u32(stream.ReadEncoded(CBitStreamReader::GetBitCount(PowerUpMaxValues[i]))); + x24_powerups[i] = CPowerUp(a, b); + } - const auto& scanStates = g_MemoryCardSys->GetScanStates(); - x170_scanTimes.reserve(scanStates.size()); - for (const auto& state : scanStates) - { - float time = stream.ReadEncoded(1) ? 1.f : 0.f; - x170_scanTimes.emplace_back(state.first, time); - } + const auto& scanStates = g_MemoryCardSys->GetScanStates(); + x170_scanTimes.reserve(scanStates.size()); + for (const auto& state : scanStates) { + float time = stream.ReadEncoded(1) ? 1.f : 0.f; + x170_scanTimes.emplace_back(state.first, time); + } - x180_scanCompletionRate.first = u32(stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100u))); - x180_scanCompletionRate.second = u32(stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100u))); + x180_scanCompletionRate.first = u32(stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100u))); + x180_scanCompletionRate.second = u32(stream.ReadEncoded(CBitStreamReader::GetBitCount(0x100u))); } -void CPlayerState::PutTo(CBitStreamWriter& stream) -{ - stream.WriteEncoded(x4_enabledItems, 32); - union - { - float fHP; - u32 iHP; - } hp; - hp.fHP = xc_health.GetHP(); - stream.WriteEncoded(hp.iHP, 32); - stream.WriteEncoded(u32(x8_currentBeam), CBitStreamWriter::GetBitCount(5)); - stream.WriteEncoded(u32(x20_currentSuit), CBitStreamWriter::GetBitCount(4)); - for (u32 i = 0; i < x24_powerups.size(); ++i) - { - const CPowerUp& pup = x24_powerups[i]; - stream.WriteEncoded(pup.x0_amount, CBitStreamWriter::GetBitCount(PowerUpMaxValues[i])); - stream.WriteEncoded(pup.x4_capacity, CBitStreamWriter::GetBitCount(PowerUpMaxValues[i])); - } +void CPlayerState::PutTo(CBitStreamWriter& stream) { + stream.WriteEncoded(x4_enabledItems, 32); + union { + float fHP; + u32 iHP; + } hp; + hp.fHP = xc_health.GetHP(); + stream.WriteEncoded(hp.iHP, 32); + stream.WriteEncoded(u32(x8_currentBeam), CBitStreamWriter::GetBitCount(5)); + stream.WriteEncoded(u32(x20_currentSuit), CBitStreamWriter::GetBitCount(4)); + for (u32 i = 0; i < x24_powerups.size(); ++i) { + const CPowerUp& pup = x24_powerups[i]; + stream.WriteEncoded(pup.x0_amount, CBitStreamWriter::GetBitCount(PowerUpMaxValues[i])); + stream.WriteEncoded(pup.x4_capacity, CBitStreamWriter::GetBitCount(PowerUpMaxValues[i])); + } - for (const auto& scanTime : x170_scanTimes) - { - if (scanTime.second >= 1.f) - stream.WriteEncoded(true, 1); - else - stream.WriteEncoded(false, 1); - } - - stream.WriteEncoded(x180_scanCompletionRate.first, CBitStreamWriter::GetBitCount(0x100)); - stream.WriteEncoded(x180_scanCompletionRate.second, CBitStreamWriter::GetBitCount(0x100)); -} - -static const u32 costs[] = -{ - 5, 10, 10, 10, 1 -}; - -u32 CPlayerState::GetMissileCostForAltAttack() const -{ - return costs[u32(x8_currentBeam)]; -} - -static const float ComboAmmoPeriods[] = -{ - 0.2f, 0.1f, 0.2f, 0.2f, 1.f -}; - -float CPlayerState::GetComboFireAmmoPeriod() const -{ - return ComboAmmoPeriods[u32(x8_currentBeam)]; -} - -u32 CPlayerState::CalculateItemCollectionRate() const -{ - u32 total = GetItemCapacity(EItemType::PowerBombs); - - if (total >= 4) - total -= 3; - total += GetItemCapacity(EItemType::WaveBeam); - total += GetItemCapacity(EItemType::IceBeam); - total += GetItemCapacity(EItemType::PlasmaBeam); - total += GetItemCapacity(EItemType::Missiles) / 5; - total += GetItemCapacity(EItemType::MorphBallBombs); - total += GetItemCapacity(EItemType::Flamethrower); - total += GetItemCapacity(EItemType::ThermalVisor); - total += GetItemCapacity(EItemType::ChargeBeam); - total += GetItemCapacity(EItemType::SuperMissile); - total += GetItemCapacity(EItemType::GrappleBeam); - total += GetItemCapacity(EItemType::XRayVisor); - total += GetItemCapacity(EItemType::IceSpreader); - total += GetItemCapacity(EItemType::SpaceJumpBoots); - total += GetItemCapacity(EItemType::MorphBall); - total += GetItemCapacity(EItemType::BoostBall); - total += GetItemCapacity(EItemType::SpiderBall); - total += GetItemCapacity(EItemType::GravitySuit); - total += GetItemCapacity(EItemType::VariaSuit); - total += GetItemCapacity(EItemType::EnergyTanks); - total += GetItemCapacity(EItemType::Truth); - total += GetItemCapacity(EItemType::Strength); - total += GetItemCapacity(EItemType::Elder); - total += GetItemCapacity(EItemType::Wild); - total += GetItemCapacity(EItemType::Lifegiver); - total += GetItemCapacity(EItemType::Warrior); - total += GetItemCapacity(EItemType::Chozo); - total += GetItemCapacity(EItemType::Nature); - total += GetItemCapacity(EItemType::Sun); - total += GetItemCapacity(EItemType::World); - total += GetItemCapacity(EItemType::Spirit); - total += GetItemCapacity(EItemType::Newborn); - return total + GetItemCapacity(EItemType::Wavebuster); -} - -CHealthInfo& CPlayerState::HealthInfo() -{ - return xc_health; -} - -const CHealthInfo& CPlayerState::GetHealthInfo() const -{ - return xc_health; -} - -CPlayerState::EPlayerSuit CPlayerState::GetCurrentSuit() const -{ - if (IsFusionEnabled()) - return EPlayerSuit::FusionPower; - - return x20_currentSuit; -} - -bool CPlayerState::CanVisorSeeFog(const CStateManager& stateMgr) const -{ - EPlayerVisor activeVisor = GetActiveVisor(stateMgr); - if (activeVisor == EPlayerVisor::Combat || activeVisor == EPlayerVisor::Scan) - return true; - return true; -} - -CPlayerState::EPlayerVisor CPlayerState::GetActiveVisor(const CStateManager& stateMgr) const -{ - const CFirstPersonCamera* cam = - static_cast( - stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr)); - return (cam ? x14_currentVisor : EPlayerVisor::Combat); -} - -void CPlayerState::UpdateStaticInterference(CStateManager& stateMgr, float dt) -{ - x188_staticIntf.Update(stateMgr, dt); -} - -void CPlayerState::SetScanTime(CAssetId res, float time) -{ - auto it = std::find_if(x170_scanTimes.begin(), x170_scanTimes.end(), [&](const auto& test) -> bool{ - return test.first == res; - }); - - if (it != x170_scanTimes.end()) - it->second = time; -} - -float CPlayerState::GetScanTime(CAssetId res) const -{ - const auto it = std::find_if(x170_scanTimes.cbegin(), x170_scanTimes.cend(), [&](const auto& test) -> bool{ - return test.first == res; - }); - - if (it == x170_scanTimes.end()) - return 0.f; - - return it->second; -} - -bool CPlayerState::GetIsVisorTransitioning() const -{ - return x14_currentVisor != x18_transitioningVisor || x1c_visorTransitionFactor < 0.2f; -} - -float CPlayerState::GetVisorTransitionFactor() const -{ - return x1c_visorTransitionFactor / 0.2f; -} - -void CPlayerState::UpdateVisorTransition(float dt) -{ - if (!GetIsVisorTransitioning()) - return; - - if (x14_currentVisor == x18_transitioningVisor) - { - x1c_visorTransitionFactor += dt; - if (x1c_visorTransitionFactor > 0.2f) - x1c_visorTransitionFactor = 0.2f; - } + for (const auto& scanTime : x170_scanTimes) { + if (scanTime.second >= 1.f) + stream.WriteEncoded(true, 1); else - { - x1c_visorTransitionFactor -= dt; - if (x1c_visorTransitionFactor < 0.f) - { - x14_currentVisor = x18_transitioningVisor; - x1c_visorTransitionFactor = std::fabs(x1c_visorTransitionFactor); - if (x1c_visorTransitionFactor > 0.19999f) - x1c_visorTransitionFactor = 0.19999f; - } + stream.WriteEncoded(false, 1); + } + + stream.WriteEncoded(x180_scanCompletionRate.first, CBitStreamWriter::GetBitCount(0x100)); + stream.WriteEncoded(x180_scanCompletionRate.second, CBitStreamWriter::GetBitCount(0x100)); +} + +static const u32 costs[] = {5, 10, 10, 10, 1}; + +u32 CPlayerState::GetMissileCostForAltAttack() const { return costs[u32(x8_currentBeam)]; } + +static const float ComboAmmoPeriods[] = {0.2f, 0.1f, 0.2f, 0.2f, 1.f}; + +float CPlayerState::GetComboFireAmmoPeriod() const { return ComboAmmoPeriods[u32(x8_currentBeam)]; } + +u32 CPlayerState::CalculateItemCollectionRate() const { + u32 total = GetItemCapacity(EItemType::PowerBombs); + + if (total >= 4) + total -= 3; + total += GetItemCapacity(EItemType::WaveBeam); + total += GetItemCapacity(EItemType::IceBeam); + total += GetItemCapacity(EItemType::PlasmaBeam); + total += GetItemCapacity(EItemType::Missiles) / 5; + total += GetItemCapacity(EItemType::MorphBallBombs); + total += GetItemCapacity(EItemType::Flamethrower); + total += GetItemCapacity(EItemType::ThermalVisor); + total += GetItemCapacity(EItemType::ChargeBeam); + total += GetItemCapacity(EItemType::SuperMissile); + total += GetItemCapacity(EItemType::GrappleBeam); + total += GetItemCapacity(EItemType::XRayVisor); + total += GetItemCapacity(EItemType::IceSpreader); + total += GetItemCapacity(EItemType::SpaceJumpBoots); + total += GetItemCapacity(EItemType::MorphBall); + total += GetItemCapacity(EItemType::BoostBall); + total += GetItemCapacity(EItemType::SpiderBall); + total += GetItemCapacity(EItemType::GravitySuit); + total += GetItemCapacity(EItemType::VariaSuit); + total += GetItemCapacity(EItemType::EnergyTanks); + total += GetItemCapacity(EItemType::Truth); + total += GetItemCapacity(EItemType::Strength); + total += GetItemCapacity(EItemType::Elder); + total += GetItemCapacity(EItemType::Wild); + total += GetItemCapacity(EItemType::Lifegiver); + total += GetItemCapacity(EItemType::Warrior); + total += GetItemCapacity(EItemType::Chozo); + total += GetItemCapacity(EItemType::Nature); + total += GetItemCapacity(EItemType::Sun); + total += GetItemCapacity(EItemType::World); + total += GetItemCapacity(EItemType::Spirit); + total += GetItemCapacity(EItemType::Newborn); + return total + GetItemCapacity(EItemType::Wavebuster); +} + +CHealthInfo& CPlayerState::HealthInfo() { return xc_health; } + +const CHealthInfo& CPlayerState::GetHealthInfo() const { return xc_health; } + +CPlayerState::EPlayerSuit CPlayerState::GetCurrentSuit() const { + if (IsFusionEnabled()) + return EPlayerSuit::FusionPower; + + return x20_currentSuit; +} + +bool CPlayerState::CanVisorSeeFog(const CStateManager& stateMgr) const { + EPlayerVisor activeVisor = GetActiveVisor(stateMgr); + if (activeVisor == EPlayerVisor::Combat || activeVisor == EPlayerVisor::Scan) + return true; + return true; +} + +CPlayerState::EPlayerVisor CPlayerState::GetActiveVisor(const CStateManager& stateMgr) const { + const CFirstPersonCamera* cam = + static_cast(stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr)); + return (cam ? x14_currentVisor : EPlayerVisor::Combat); +} + +void CPlayerState::UpdateStaticInterference(CStateManager& stateMgr, float dt) { x188_staticIntf.Update(stateMgr, dt); } + +void CPlayerState::SetScanTime(CAssetId res, float time) { + auto it = std::find_if(x170_scanTimes.begin(), x170_scanTimes.end(), + [&](const auto& test) -> bool { return test.first == res; }); + + if (it != x170_scanTimes.end()) + it->second = time; +} + +float CPlayerState::GetScanTime(CAssetId res) const { + const auto it = std::find_if(x170_scanTimes.cbegin(), x170_scanTimes.cend(), + [&](const auto& test) -> bool { return test.first == res; }); + + if (it == x170_scanTimes.end()) + return 0.f; + + return it->second; +} + +bool CPlayerState::GetIsVisorTransitioning() const { + return x14_currentVisor != x18_transitioningVisor || x1c_visorTransitionFactor < 0.2f; +} + +float CPlayerState::GetVisorTransitionFactor() const { return x1c_visorTransitionFactor / 0.2f; } + +void CPlayerState::UpdateVisorTransition(float dt) { + if (!GetIsVisorTransitioning()) + return; + + if (x14_currentVisor == x18_transitioningVisor) { + x1c_visorTransitionFactor += dt; + if (x1c_visorTransitionFactor > 0.2f) + x1c_visorTransitionFactor = 0.2f; + } else { + x1c_visorTransitionFactor -= dt; + if (x1c_visorTransitionFactor < 0.f) { + x14_currentVisor = x18_transitioningVisor; + x1c_visorTransitionFactor = std::fabs(x1c_visorTransitionFactor); + if (x1c_visorTransitionFactor > 0.19999f) + x1c_visorTransitionFactor = 0.19999f; } + } } -bool CPlayerState::StartVisorTransition(CPlayerState::EPlayerVisor visor) -{ - x18_transitioningVisor = visor; - return x14_currentVisor == x18_transitioningVisor; +bool CPlayerState::StartVisorTransition(CPlayerState::EPlayerVisor visor) { + x18_transitioningVisor = visor; + return x14_currentVisor == x18_transitioningVisor; } -void CPlayerState::ResetVisor() -{ - x18_transitioningVisor = x14_currentVisor = EPlayerVisor::Combat; - x1c_visorTransitionFactor = 0.0f; +void CPlayerState::ResetVisor() { + x18_transitioningVisor = x14_currentVisor = EPlayerVisor::Combat; + x1c_visorTransitionFactor = 0.0f; } -bool CPlayerState::ItemEnabled(CPlayerState::EItemType type) const -{ - if (HasPowerUp(type)) - return (x4_enabledItems & (1 << u32(type))); - return false; +bool CPlayerState::ItemEnabled(CPlayerState::EItemType type) const { + if (HasPowerUp(type)) + return (x4_enabledItems & (1 << u32(type))); + return false; } -void CPlayerState::EnableItem(CPlayerState::EItemType type) -{ - if (HasPowerUp(type)) - x4_enabledItems |= (1 << u32(type)); +void CPlayerState::EnableItem(CPlayerState::EItemType type) { + if (HasPowerUp(type)) + x4_enabledItems |= (1 << u32(type)); } -void CPlayerState::DisableItem(CPlayerState::EItemType type) -{ - if (HasPowerUp(type)) - x4_enabledItems &= ~(1 << u32(type)); +void CPlayerState::DisableItem(CPlayerState::EItemType type) { + if (HasPowerUp(type)) + x4_enabledItems &= ~(1 << u32(type)); } -bool CPlayerState::HasPowerUp(CPlayerState::EItemType type) const -{ - if (type < EItemType::Max) - return x24_powerups[u32(type)].x4_capacity != 0; - return false; +bool CPlayerState::HasPowerUp(CPlayerState::EItemType type) const { + if (type < EItemType::Max) + return x24_powerups[u32(type)].x4_capacity != 0; + return false; } -u32 CPlayerState::GetItemCapacity(CPlayerState::EItemType type) const -{ - if (type < EItemType::Max) - return x24_powerups[u32(type)].x4_capacity; - return 0; +u32 CPlayerState::GetItemCapacity(CPlayerState::EItemType type) const { + if (type < EItemType::Max) + return x24_powerups[u32(type)].x4_capacity; + return 0; } -u32 CPlayerState::GetItemAmount(CPlayerState::EItemType type) const -{ - if (type == EItemType::SpaceJumpBoots || - type == EItemType::PowerBombs || - type == EItemType::Flamethrower || - type == EItemType::EnergyTanks || - type == EItemType::Missiles || - (type >= EItemType::Truth && type <= EItemType::Newborn)) - { - return x24_powerups[u32(type)].x0_amount; - } +u32 CPlayerState::GetItemAmount(CPlayerState::EItemType type) const { + if (type == EItemType::SpaceJumpBoots || type == EItemType::PowerBombs || type == EItemType::Flamethrower || + type == EItemType::EnergyTanks || type == EItemType::Missiles || + (type >= EItemType::Truth && type <= EItemType::Newborn)) { + return x24_powerups[u32(type)].x0_amount; + } - return 0; + return 0; } -void CPlayerState::DecrPickup(CPlayerState::EItemType type, u32 amount) -{ - if (type >= EItemType::Max) - return; +void CPlayerState::DecrPickup(CPlayerState::EItemType type, u32 amount) { + if (type >= EItemType::Max) + return; - if ((type == EItemType::Missiles || type >= EItemType::PowerBombs) && type < EItemType::ThermalVisor) - x24_powerups[u32(type)].x0_amount -= amount; + if ((type == EItemType::Missiles || type >= EItemType::PowerBombs) && type < EItemType::ThermalVisor) + x24_powerups[u32(type)].x0_amount -= amount; } -void CPlayerState::IncrPickup(EItemType type, u32 amount) -{ - if (type >= EItemType::Max) - return; - - switch(type) - { - case EItemType::Missiles: - case EItemType::PowerBombs: - case EItemType::ChargeBeam: - case EItemType::SpaceJumpBoots: - case EItemType::EnergyTanks: - case EItemType::Truth: - case EItemType::Strength: - case EItemType::Elder: - case EItemType::Wild: - case EItemType::Lifegiver: - case EItemType::Warrior: - case EItemType::Chozo: - case EItemType::Nature: - case EItemType::Sun: - case EItemType::World: - case EItemType::Spirit: - case EItemType::Newborn: - { - CPowerUp& pup = x24_powerups[u32(type)]; - pup.x0_amount = std::min(pup.x0_amount + u32(amount), pup.x4_capacity); - - if (type == EItemType::EnergyTanks) - IncrPickup(EItemType::HealthRefill, 9999); - break; - } - case EItemType::HealthRefill: - xc_health.SetHP(std::min(amount + xc_health.GetHP(), CalculateHealth())); - [[fallthrough]]; - default: - break; - } -} - -void CPlayerState::ResetAndIncrPickUp(CPlayerState::EItemType type, u32 amount) -{ - x24_powerups[u32(type)].x0_amount = 0; - IncrPickup(type, amount); -} - -float CPlayerState::CalculateHealth() -{ - return (GetEnergyTankCapacity() * x24_powerups[u32(EItemType::EnergyTanks)].x0_amount) + GetBaseHealthCapacity(); -} - -void CPlayerState::InitializePowerUp(CPlayerState::EItemType type, u32 capacity) -{ - if (type >= EItemType::Max) - return; +void CPlayerState::IncrPickup(EItemType type, u32 amount) { + if (type >= EItemType::Max) + return; + switch (type) { + case EItemType::Missiles: + case EItemType::PowerBombs: + case EItemType::ChargeBeam: + case EItemType::SpaceJumpBoots: + case EItemType::EnergyTanks: + case EItemType::Truth: + case EItemType::Strength: + case EItemType::Elder: + case EItemType::Wild: + case EItemType::Lifegiver: + case EItemType::Warrior: + case EItemType::Chozo: + case EItemType::Nature: + case EItemType::Sun: + case EItemType::World: + case EItemType::Spirit: + case EItemType::Newborn: { CPowerUp& pup = x24_powerups[u32(type)]; - pup.x4_capacity = zeus::clamp(0u, pup.x4_capacity + capacity, PowerUpMaxValues[u32(type)]); - pup.x0_amount = std::min(pup.x0_amount, pup.x4_capacity); - if (type >= EItemType::PowerSuit && type <= EItemType::PhazonSuit) - { - if (HasPowerUp(EItemType::PhazonSuit)) - x20_currentSuit = EPlayerSuit::Phazon; - else if (HasPowerUp(EItemType::GravitySuit)) - x20_currentSuit = EPlayerSuit::Gravity; - else if (HasPowerUp(EItemType::VariaSuit)) - x20_currentSuit = EPlayerSuit::Varia; - else - x20_currentSuit = EPlayerSuit::Power; - } + pup.x0_amount = std::min(pup.x0_amount + u32(amount), pup.x4_capacity); + + if (type == EItemType::EnergyTanks) + IncrPickup(EItemType::HealthRefill, 9999); + break; + } + case EItemType::HealthRefill: + xc_health.SetHP(std::min(amount + xc_health.GetHP(), CalculateHealth())); + [[fallthrough]]; + default: + break; + } } -void CPlayerState::ReInitalizePowerUp(CPlayerState::EItemType type, u32 capacity) -{ - x24_powerups[u32(type)].x4_capacity = 0; - InitializePowerUp(type, capacity); +void CPlayerState::ResetAndIncrPickUp(CPlayerState::EItemType type, u32 amount) { + x24_powerups[u32(type)].x0_amount = 0; + IncrPickup(type, amount); } -void CPlayerState::InitializeScanTimes() -{ - if (x170_scanTimes.size()) - return; +float CPlayerState::CalculateHealth() { + return (GetEnergyTankCapacity() * x24_powerups[u32(EItemType::EnergyTanks)].x0_amount) + GetBaseHealthCapacity(); +} - const auto& scanStates = g_MemoryCardSys->GetScanStates(); - x170_scanTimes.reserve(scanStates.size()); - for (const auto& state : scanStates) - x170_scanTimes.emplace_back(state.first, 0.f); +void CPlayerState::InitializePowerUp(CPlayerState::EItemType type, u32 capacity) { + if (type >= EItemType::Max) + return; + + CPowerUp& pup = x24_powerups[u32(type)]; + pup.x4_capacity = zeus::clamp(0u, pup.x4_capacity + capacity, PowerUpMaxValues[u32(type)]); + pup.x0_amount = std::min(pup.x0_amount, pup.x4_capacity); + if (type >= EItemType::PowerSuit && type <= EItemType::PhazonSuit) { + if (HasPowerUp(EItemType::PhazonSuit)) + x20_currentSuit = EPlayerSuit::Phazon; + else if (HasPowerUp(EItemType::GravitySuit)) + x20_currentSuit = EPlayerSuit::Gravity; + else if (HasPowerUp(EItemType::VariaSuit)) + x20_currentSuit = EPlayerSuit::Varia; + else + x20_currentSuit = EPlayerSuit::Power; + } +} + +void CPlayerState::ReInitalizePowerUp(CPlayerState::EItemType type, u32 capacity) { + x24_powerups[u32(type)].x4_capacity = 0; + InitializePowerUp(type, capacity); +} + +void CPlayerState::InitializeScanTimes() { + if (x170_scanTimes.size()) + return; + + const auto& scanStates = g_MemoryCardSys->GetScanStates(); + x170_scanTimes.reserve(scanStates.size()); + for (const auto& state : scanStates) + x170_scanTimes.emplace_back(state.first, 0.f); } const std::unordered_map CPlayerState::g_TypeNameMap = { @@ -494,14 +418,13 @@ const std::unordered_map CPlayerState {"newborn"sv, EItemType::Newborn}, }; -CPlayerState::EItemType CPlayerState::ItemNameToType(std::string_view name) -{ - std::string lowName = name.data(); - athena::utility::tolower(lowName); - if (g_TypeNameMap.find(lowName) == g_TypeNameMap.end()) - return EItemType::Invalid; +CPlayerState::EItemType CPlayerState::ItemNameToType(std::string_view name) { + std::string lowName = name.data(); + athena::utility::tolower(lowName); + if (g_TypeNameMap.find(lowName) == g_TypeNameMap.end()) + return EItemType::Invalid; - return g_TypeNameMap.find(lowName)->second; + return g_TypeNameMap.find(lowName)->second; } -} +} // namespace urde diff --git a/Runtime/CPlayerState.hpp b/Runtime/CPlayerState.hpp index cee0837dd..3e555a7f1 100644 --- a/Runtime/CPlayerState.hpp +++ b/Runtime/CPlayerState.hpp @@ -8,187 +8,175 @@ #include "World/CHealthInfo.hpp" #include -namespace urde -{ +namespace urde { + +class CPlayerState { + friend class CWorldTransManager; -class CPlayerState -{ - friend class CWorldTransManager; public: - enum class EItemType : s32 - { - Invalid = -1, - PowerBeam = 0, - IceBeam = 1, - WaveBeam = 2, - PlasmaBeam = 3, - Missiles = 4, - ScanVisor = 5, - MorphBallBombs = 6, - PowerBombs = 7, - Flamethrower = 8, - ThermalVisor = 9, - ChargeBeam = 10, - SuperMissile = 11, - GrappleBeam = 12, - XRayVisor = 13, - IceSpreader = 14, - SpaceJumpBoots = 15, - MorphBall = 16, - CombatVisor = 17, - BoostBall = 18, - SpiderBall = 19, - PowerSuit = 20, - GravitySuit = 21, - VariaSuit = 22, - PhazonSuit = 23, - EnergyTanks = 24, - UnknownItem1 = 25, - HealthRefill = 26, - UnknownItem2 = 27, - Wavebuster = 28, - Truth = 29, - Strength = 30, - Elder = 31, - Wild = 32, - Lifegiver = 33, - Warrior = 34, - Chozo = 35, - Nature = 36, - Sun = 37, - World = 38, - Spirit = 39, - Newborn = 40, + enum class EItemType : s32 { + Invalid = -1, + PowerBeam = 0, + IceBeam = 1, + WaveBeam = 2, + PlasmaBeam = 3, + Missiles = 4, + ScanVisor = 5, + MorphBallBombs = 6, + PowerBombs = 7, + Flamethrower = 8, + ThermalVisor = 9, + ChargeBeam = 10, + SuperMissile = 11, + GrappleBeam = 12, + XRayVisor = 13, + IceSpreader = 14, + SpaceJumpBoots = 15, + MorphBall = 16, + CombatVisor = 17, + BoostBall = 18, + SpiderBall = 19, + PowerSuit = 20, + GravitySuit = 21, + VariaSuit = 22, + PhazonSuit = 23, + EnergyTanks = 24, + UnknownItem1 = 25, + HealthRefill = 26, + UnknownItem2 = 27, + Wavebuster = 28, + Truth = 29, + Strength = 30, + Elder = 31, + Wild = 32, + Lifegiver = 33, + Warrior = 34, + Chozo = 35, + Nature = 36, + Sun = 37, + World = 38, + Spirit = 39, + Newborn = 40, - /* This must remain at the end of the list */ - Max - }; + /* This must remain at the end of the list */ + Max + }; - enum class EPlayerVisor : u32 - { - Combat, - XRay, - Scan, - Thermal, + enum class EPlayerVisor : u32 { + Combat, + XRay, + Scan, + Thermal, - /* This must remain at the end of the list */ - Max - }; + /* This must remain at the end of the list */ + Max + }; - enum class EPlayerSuit : s32 - { - Invalid = -1, - Power, - Gravity, - Varia, - Phazon, - FusionPower, - FusionGravity, - FusionVaria, - FusionPhazon - }; + enum class EPlayerSuit : s32 { + Invalid = -1, + Power, + Gravity, + Varia, + Phazon, + FusionPower, + FusionGravity, + FusionVaria, + FusionPhazon + }; - enum class EBeamId : s32 - { - Invalid = -1, - Power, - Ice, - Wave, - Plasma, - Phazon, - Phazon2 = 27 - }; + enum class EBeamId : s32 { Invalid = -1, Power, Ice, Wave, Plasma, Phazon, Phazon2 = 27 }; private: - static const std::unordered_map g_TypeNameMap; - static const u32 PowerUpMaxValues[41]; - static const char* PowerUpNames[41]; - struct CPowerUp - { - u32 x0_amount = 0; - u32 x4_capacity = 0; - CPowerUp() {} - CPowerUp(u32 amount, u32 capacity) : x0_amount(amount), x4_capacity(capacity) {} - }; - union - { - struct { bool x0_24_alive : 1; bool x0_25_firingComboBeam : 1; bool x0_26_fusion : 1; }; - u32 dummy = 0; + static const std::unordered_map g_TypeNameMap; + static const u32 PowerUpMaxValues[41]; + static const char* PowerUpNames[41]; + struct CPowerUp { + u32 x0_amount = 0; + u32 x4_capacity = 0; + CPowerUp() {} + CPowerUp(u32 amount, u32 capacity) : x0_amount(amount), x4_capacity(capacity) {} + }; + union { + struct { + bool x0_24_alive : 1; + bool x0_25_firingComboBeam : 1; + bool x0_26_fusion : 1; }; + u32 dummy = 0; + }; - u32 x4_enabledItems = 0; - EBeamId x8_currentBeam = EBeamId::Power; - CHealthInfo xc_health = {99.f, 50.f}; - EPlayerVisor x14_currentVisor = EPlayerVisor::Combat; - EPlayerVisor x18_transitioningVisor = x14_currentVisor; - float x1c_visorTransitionFactor = 0.2f; - EPlayerSuit x20_currentSuit = EPlayerSuit::Power; - rstl::reserved_vector x24_powerups; - std::vector> x170_scanTimes; - std::pair x180_scanCompletionRate = {}; - CStaticInterference x188_staticIntf; + u32 x4_enabledItems = 0; + EBeamId x8_currentBeam = EBeamId::Power; + CHealthInfo xc_health = {99.f, 50.f}; + EPlayerVisor x14_currentVisor = EPlayerVisor::Combat; + EPlayerVisor x18_transitioningVisor = x14_currentVisor; + float x1c_visorTransitionFactor = 0.2f; + EPlayerSuit x20_currentSuit = EPlayerSuit::Power; + rstl::reserved_vector x24_powerups; + std::vector> x170_scanTimes; + std::pair x180_scanCompletionRate = {}; + CStaticInterference x188_staticIntf; + + bool m_canTakeDamage = true; - bool m_canTakeDamage = true; public: + u32 GetMissileCostForAltAttack() const; + float GetComboFireAmmoPeriod() const; + static constexpr float GetMissileComboChargeFactor() { return 1.8f; } + u32 CalculateItemCollectionRate() const; - u32 GetMissileCostForAltAttack() const; - float GetComboFireAmmoPeriod() const; - static constexpr float GetMissileComboChargeFactor() { return 1.8f; } - u32 CalculateItemCollectionRate() const; - - CHealthInfo& HealthInfo(); - const CHealthInfo &GetHealthInfo() const; - u32 GetPickupTotal() { return 99; } - void SetIsFusionEnabled(bool val) { x0_26_fusion = val; } - bool IsFusionEnabled() const { return x0_26_fusion; } - EPlayerSuit GetCurrentSuit() const; - EPlayerSuit GetCurrentSuitRaw() const { return x20_currentSuit; } - EBeamId GetCurrentBeam() const { return x8_currentBeam; } - void SetCurrentBeam(EBeamId beam) { x8_currentBeam = beam; } - bool CanVisorSeeFog(const CStateManager& stateMgr) const; - EPlayerVisor GetCurrentVisor() const { return x14_currentVisor; } - EPlayerVisor GetTransitioningVisor() const { return x18_transitioningVisor; } - EPlayerVisor GetActiveVisor(const CStateManager& stateMgr) const; - void UpdateStaticInterference(CStateManager& stateMgr, float dt); - void IncreaseScanTime(u32 time, float val); - void SetScanTime(CAssetId res, float time); - float GetScanTime(CAssetId time) const; - bool GetIsVisorTransitioning() const; - float GetVisorTransitionFactor() const; - void UpdateVisorTransition(float dt); - bool StartVisorTransition(EPlayerVisor visor); - void ResetVisor(); - bool ItemEnabled(EItemType type) const; - void DisableItem(EItemType type); - void EnableItem(EItemType type); - bool HasPowerUp(EItemType type) const; - u32 GetItemCapacity(EItemType type) const; - u32 GetItemAmount(EItemType type) const; - void DecrPickup(EItemType type, u32 amount); - void IncrPickup(EItemType type, u32 amount); - void ResetAndIncrPickUp(EItemType type, u32 amount); - static float GetEnergyTankCapacity() { return 100.f; } - static float GetBaseHealthCapacity() { return 99.f; } - float CalculateHealth(); - void ReInitalizePowerUp(EItemType type, u32 capacity); - void InitializePowerUp(EItemType type, u32 capacity); - u32 GetLogScans() const { return x180_scanCompletionRate.first; } - u32 GetTotalLogScans() const { return x180_scanCompletionRate.second; } - void SetScanCompletionRate(const std::pair& p) { x180_scanCompletionRate = p; } - bool IsPlayerAlive() const { return x0_24_alive; } - void SetPlayerAlive(bool alive) { x0_24_alive = alive; } - bool IsFiringComboBeam() const { return x0_25_firingComboBeam; } - void SetFiringComboBeam(bool f) { x0_25_firingComboBeam = f; } - void InitializeScanTimes(); - CStaticInterference& GetStaticInterference() { return x188_staticIntf; } - const std::vector>& GetScanTimes() const { return x170_scanTimes; } - CPlayerState(); - CPlayerState(CBitStreamReader& stream); - void PutTo(CBitStreamWriter& stream); - static u32 GetPowerUpMaxValue(EItemType type) { return PowerUpMaxValues[u32(type)]; } - static EItemType ItemNameToType(std::string_view name); - bool CanTakeDamage() const { return m_canTakeDamage; } - void SetCanTakeDamage(bool c) { m_canTakeDamage = c; } + CHealthInfo& HealthInfo(); + const CHealthInfo& GetHealthInfo() const; + u32 GetPickupTotal() { return 99; } + void SetIsFusionEnabled(bool val) { x0_26_fusion = val; } + bool IsFusionEnabled() const { return x0_26_fusion; } + EPlayerSuit GetCurrentSuit() const; + EPlayerSuit GetCurrentSuitRaw() const { return x20_currentSuit; } + EBeamId GetCurrentBeam() const { return x8_currentBeam; } + void SetCurrentBeam(EBeamId beam) { x8_currentBeam = beam; } + bool CanVisorSeeFog(const CStateManager& stateMgr) const; + EPlayerVisor GetCurrentVisor() const { return x14_currentVisor; } + EPlayerVisor GetTransitioningVisor() const { return x18_transitioningVisor; } + EPlayerVisor GetActiveVisor(const CStateManager& stateMgr) const; + void UpdateStaticInterference(CStateManager& stateMgr, float dt); + void IncreaseScanTime(u32 time, float val); + void SetScanTime(CAssetId res, float time); + float GetScanTime(CAssetId time) const; + bool GetIsVisorTransitioning() const; + float GetVisorTransitionFactor() const; + void UpdateVisorTransition(float dt); + bool StartVisorTransition(EPlayerVisor visor); + void ResetVisor(); + bool ItemEnabled(EItemType type) const; + void DisableItem(EItemType type); + void EnableItem(EItemType type); + bool HasPowerUp(EItemType type) const; + u32 GetItemCapacity(EItemType type) const; + u32 GetItemAmount(EItemType type) const; + void DecrPickup(EItemType type, u32 amount); + void IncrPickup(EItemType type, u32 amount); + void ResetAndIncrPickUp(EItemType type, u32 amount); + static float GetEnergyTankCapacity() { return 100.f; } + static float GetBaseHealthCapacity() { return 99.f; } + float CalculateHealth(); + void ReInitalizePowerUp(EItemType type, u32 capacity); + void InitializePowerUp(EItemType type, u32 capacity); + u32 GetLogScans() const { return x180_scanCompletionRate.first; } + u32 GetTotalLogScans() const { return x180_scanCompletionRate.second; } + void SetScanCompletionRate(const std::pair& p) { x180_scanCompletionRate = p; } + bool IsPlayerAlive() const { return x0_24_alive; } + void SetPlayerAlive(bool alive) { x0_24_alive = alive; } + bool IsFiringComboBeam() const { return x0_25_firingComboBeam; } + void SetFiringComboBeam(bool f) { x0_25_firingComboBeam = f; } + void InitializeScanTimes(); + CStaticInterference& GetStaticInterference() { return x188_staticIntf; } + const std::vector>& GetScanTimes() const { return x170_scanTimes; } + CPlayerState(); + CPlayerState(CBitStreamReader& stream); + void PutTo(CBitStreamWriter& stream); + static u32 GetPowerUpMaxValue(EItemType type) { return PowerUpMaxValues[u32(type)]; } + static EItemType ItemNameToType(std::string_view name); + bool CanTakeDamage() const { return m_canTakeDamage; } + void SetCanTakeDamage(bool c) { m_canTakeDamage = c; } }; -} - +} // namespace urde diff --git a/Runtime/CRandom16.cpp b/Runtime/CRandom16.cpp index 836e9e7fd..b2eddbdca 100644 --- a/Runtime/CRandom16.cpp +++ b/Runtime/CRandom16.cpp @@ -1,9 +1,8 @@ #include "CRandom16.hpp" -namespace urde -{ +namespace urde { -CRandom16* CRandom16::g_randomNumber = nullptr;// &DefaultRandom; -CGlobalRandom* CGlobalRandom::g_currentGlobalRandom = nullptr;//&DefaultGlobalRandom; +CRandom16* CRandom16::g_randomNumber = nullptr; // &DefaultRandom; +CGlobalRandom* CGlobalRandom::g_currentGlobalRandom = nullptr; //&DefaultGlobalRandom; -} +} // namespace urde diff --git a/Runtime/CRandom16.hpp b/Runtime/CRandom16.hpp index 692771cc7..75e1dd5c0 100644 --- a/Runtime/CRandom16.hpp +++ b/Runtime/CRandom16.hpp @@ -2,72 +2,51 @@ #include "GCNTypes.hpp" -namespace urde -{ +namespace urde { + +class CRandom16 { + u32 m_seed; + static CRandom16* g_randomNumber; -class CRandom16 -{ - u32 m_seed; - static CRandom16* g_randomNumber; public: - CRandom16(u32 p = 99) : m_seed(p) {} + CRandom16(u32 p = 99) : m_seed(p) {} - inline u32 Next() - { - m_seed = (m_seed * 0x41c64e6d) + 0x00003039; - return m_seed >> 16; - } + inline u32 Next() { + m_seed = (m_seed * 0x41c64e6d) + 0x00003039; + return m_seed >> 16; + } - inline u32 GetSeed() const - { - return m_seed; - } + inline u32 GetSeed() const { return m_seed; } - inline void SetSeed(u32 p) - { - m_seed = p; - } + inline void SetSeed(u32 p) { m_seed = p; } - inline float Float() - { - return Next() * 0.000015259022f; - } + inline float Float() { return Next() * 0.000015259022f; } - inline float Range(float min, float max) - { - return min + Float() * (max - min); - } + inline float Range(float min, float max) { return min + Float() * (max - min); } - inline s32 Range(s32 min, s32 max) - { - return min + (Next() % ((max - min) + 1)); - } + inline s32 Range(s32 min, s32 max) { return min + (Next() % ((max - min) + 1)); } - static CRandom16* GetRandomNumber() {return g_randomNumber;} - static void SetRandomNumber(CRandom16* rnd) {g_randomNumber = rnd;} + static CRandom16* GetRandomNumber() { return g_randomNumber; } + static void SetRandomNumber(CRandom16* rnd) { g_randomNumber = rnd; } }; -class CGlobalRandom -{ - CRandom16& m_random; - CGlobalRandom* m_prev; - static CGlobalRandom* g_currentGlobalRandom; +class CGlobalRandom { + CRandom16& m_random; + CGlobalRandom* m_prev; + static CGlobalRandom* g_currentGlobalRandom; + public: - CGlobalRandom(CRandom16& rand) - : m_random(rand), m_prev(g_currentGlobalRandom) - { - g_currentGlobalRandom = this; - CRandom16::SetRandomNumber(&m_random); - } - ~CGlobalRandom() - { - g_currentGlobalRandom = m_prev; - if (m_prev) - CRandom16::SetRandomNumber(&m_prev->m_random); - else - CRandom16::SetRandomNumber(nullptr); - } + CGlobalRandom(CRandom16& rand) : m_random(rand), m_prev(g_currentGlobalRandom) { + g_currentGlobalRandom = this; + CRandom16::SetRandomNumber(&m_random); + } + ~CGlobalRandom() { + g_currentGlobalRandom = m_prev; + if (m_prev) + CRandom16::SetRandomNumber(&m_prev->m_random); + else + CRandom16::SetRandomNumber(nullptr); + } }; -} - +} // namespace urde diff --git a/Runtime/CRelayTracker.cpp b/Runtime/CRelayTracker.cpp index a6df258f6..083830cf2 100644 --- a/Runtime/CRelayTracker.cpp +++ b/Runtime/CRelayTracker.cpp @@ -4,91 +4,80 @@ #include "World/CWorld.hpp" #include -namespace urde -{ +namespace urde { -CRelayTracker::CRelayTracker(CBitStreamReader& in, const CSaveWorld& saveworld) -{ - u32 relayCount = saveworld.GetRelayCount(); - if (saveworld.GetRelayCount()) - { - std::vector relayStates(saveworld.GetRelayCount()); - for (u32 i=0 ; i relayStates(saveworld.GetRelayCount()); + for (u32 i = 0; i < relayCount; ++i) + relayStates[i] = in.ReadEncoded(1); - for (u32 i=0 ; iGetRelayCount(); +void CRelayTracker::SendMsgs(const TAreaId& areaId, CStateManager& stateMgr) { + const CWorld* world = stateMgr.WorldNC(); + u32 relayCount = world->GetRelayCount(); - bool hasActiveRelays = false; - for (u32 i=0 ; iGetRelay(i); - if (relay.GetTargetId().AreaNum() != areaId) - continue; + bool hasActiveRelays = false; + for (u32 i = 0; i < relayCount; ++i) { + const CWorld::CRelay& relay = world->GetRelay(i); + if (relay.GetTargetId().AreaNum() != areaId) + continue; - if (!HasRelay(relay.GetRelayId())) - continue; + if (!HasRelay(relay.GetRelayId())) + continue; - stateMgr.SendScriptMsg(kInvalidUniqueId, relay.GetTargetId(), EScriptObjectMessage(relay.GetMessage()), - EScriptObjectState::Any); - if (relay.GetActive()) - hasActiveRelays = true; - } + stateMgr.SendScriptMsg(kInvalidUniqueId, relay.GetTargetId(), EScriptObjectMessage(relay.GetMessage()), + EScriptObjectState::Any); + if (relay.GetActive()) + hasActiveRelays = true; + } - if (!hasActiveRelays) - return; + if (!hasActiveRelays) + return; - for (u32 i=0 ; iGetRelay(i); - if (relay.GetTargetId().AreaNum() != areaId) - continue; + for (u32 i = 0; i < relayCount; ++i) { + const CWorld::CRelay& relay = world->GetRelay(i); + if (relay.GetTargetId().AreaNum() != areaId) + continue; - if (!HasRelay(relay.GetRelayId()) || !relay.GetActive()) - continue; + if (!HasRelay(relay.GetRelayId()) || !relay.GetActive()) + continue; - RemoveRelay(relay.GetRelayId()); - } + RemoveRelay(relay.GetRelayId()); + } } -void CRelayTracker::PutTo(CBitStreamWriter& out, const CSaveWorld& saveworld) -{ - u32 relayCount = saveworld.GetRelayCount(); - std::vector relays(relayCount); +void CRelayTracker::PutTo(CBitStreamWriter& out, const CSaveWorld& saveworld) { + u32 relayCount = saveworld.GetRelayCount(); + std::vector relays(relayCount); - for (const TEditorId& id : x0_relayStates) - relays[saveworld.GetRelayIndex(id)] = true; + for (const TEditorId& id : x0_relayStates) + relays[saveworld.GetRelayIndex(id)] = true; - for (u32 i=0 ; i x0_relayStates; -class CRelayTracker -{ - std::vector x0_relayStates; public: - CRelayTracker() = default; - CRelayTracker(CBitStreamReader&, const CSaveWorld&); + CRelayTracker() = default; + CRelayTracker(CBitStreamReader&, const CSaveWorld&); - bool HasRelay(TEditorId); - void AddRelay(TEditorId); - void RemoveRelay(TEditorId); - void SendMsgs(const TAreaId&, CStateManager&); - void PutTo(CBitStreamWriter&, const CSaveWorld&); + bool HasRelay(TEditorId); + void AddRelay(TEditorId); + void RemoveRelay(TEditorId); + void SendMsgs(const TAreaId&, CStateManager&); + void PutTo(CBitStreamWriter&, const CSaveWorld&); }; -} - +} // namespace urde diff --git a/Runtime/CResFactory.cpp b/Runtime/CResFactory.cpp index 097371414..76ce35a1c 100644 --- a/Runtime/CResFactory.cpp +++ b/Runtime/CResFactory.cpp @@ -2,146 +2,123 @@ #include "CSimplePool.hpp" #include "CStopwatch.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("CResFactory"); -void CResFactory::AddToLoadList(SLoadingData&& data) -{ - m_loadMap[data.x0_tag] = m_loadList.insert(m_loadList.end(), std::move(data)); +void CResFactory::AddToLoadList(SLoadingData&& data) { + m_loadMap[data.x0_tag] = m_loadList.insert(m_loadList.end(), std::move(data)); } -CFactoryFnReturn CResFactory::BuildSync(const SObjectTag& tag, const CVParamTransfer& xfer, CObjectReference* selfRef) -{ - CFactoryFnReturn ret; - if (x5c_factoryMgr.CanMakeMemory(tag)) - { - std::unique_ptr data; - int size = 0; - x4_loader.LoadMemResourceSync(tag, data, &size); - if (size) - ret = x5c_factoryMgr.MakeObjectFromMemory(tag, std::move(data), size, - x4_loader.GetResourceCompression(tag), xfer, selfRef); - else - ret = std::make_unique(nullptr); - } +CFactoryFnReturn CResFactory::BuildSync(const SObjectTag& tag, const CVParamTransfer& xfer, CObjectReference* selfRef) { + CFactoryFnReturn ret; + if (x5c_factoryMgr.CanMakeMemory(tag)) { + std::unique_ptr data; + int size = 0; + x4_loader.LoadMemResourceSync(tag, data, &size); + if (size) + ret = x5c_factoryMgr.MakeObjectFromMemory(tag, std::move(data), size, x4_loader.GetResourceCompression(tag), xfer, + selfRef); else - { - if (auto rp = x4_loader.LoadNewResourceSync(tag, nullptr)) - ret = x5c_factoryMgr.MakeObject(tag, *rp, xfer, selfRef); - else - ret = std::make_unique(nullptr); - } - Log.report(logvisor::Warning, "sync-built %.4s %08X", tag.type.getChars(), tag.id.Value()); + ret = std::make_unique(nullptr); + } else { + if (auto rp = x4_loader.LoadNewResourceSync(tag, nullptr)) + ret = x5c_factoryMgr.MakeObject(tag, *rp, xfer, selfRef); + else + ret = std::make_unique(nullptr); + } + Log.report(logvisor::Warning, "sync-built %.4s %08X", tag.type.getChars(), tag.id.Value()); + return ret; +} + +bool CResFactory::PumpResource(SLoadingData& data) { + if (data.x8_dvdReq && data.x8_dvdReq->IsComplete()) { + data.x8_dvdReq.reset(); + *data.xc_targetPtr = + x5c_factoryMgr.MakeObjectFromMemory(data.x0_tag, std::move(data.x10_loadBuffer), data.x14_resSize, + data.m_compressed, data.x18_cvXfer, data.m_selfRef); + Log.report(logvisor::Info, "async-built %.4s %08X", data.x0_tag.type.getChars(), data.x0_tag.id.Value()); + return true; + } + return false; +} + +std::unique_ptr CResFactory::Build(const SObjectTag& tag, const CVParamTransfer& xfer, + CObjectReference* selfRef) { + auto search = m_loadMap.find(tag); + if (search != m_loadMap.end()) { + while (!PumpResource(*search->second) || !search->second->xc_targetPtr) {} + std::unique_ptr ret = std::move(*search->second->xc_targetPtr); + m_loadList.erase(search->second); + m_loadMap.erase(search); return ret; -} - -bool CResFactory::PumpResource(SLoadingData& data) -{ - if (data.x8_dvdReq && data.x8_dvdReq->IsComplete()) - { - data.x8_dvdReq.reset(); - *data.xc_targetPtr = - x5c_factoryMgr.MakeObjectFromMemory(data.x0_tag, std::move(data.x10_loadBuffer), - data.x14_resSize, data.m_compressed, data.x18_cvXfer, - data.m_selfRef); - Log.report(logvisor::Info, "async-built %.4s %08X", data.x0_tag.type.getChars(), data.x0_tag.id.Value()); - return true; - } - return false; -} - -std::unique_ptr CResFactory::Build(const SObjectTag& tag, const CVParamTransfer& xfer, CObjectReference* selfRef) -{ - auto search = m_loadMap.find(tag); - if (search != m_loadMap.end()) - { - while (!PumpResource(*search->second) || !search->second->xc_targetPtr) {} - std::unique_ptr ret = std::move(*search->second->xc_targetPtr); - m_loadList.erase(search->second); - m_loadMap.erase(search); - return ret; - } - return BuildSync(tag, xfer, selfRef); + } + return BuildSync(tag, xfer, selfRef); } void CResFactory::BuildAsync(const SObjectTag& tag, const CVParamTransfer& xfer, std::unique_ptr* target, - CObjectReference* selfRef) -{ - auto search = m_loadMap.find(tag); - if (search == m_loadMap.end()) - { - SLoadingData data(tag, target, xfer, x4_loader.GetResourceCompression(tag), selfRef); - data.x14_resSize = x4_loader.ResourceSize(tag); - if (data.x14_resSize) - { - data.x10_loadBuffer = std::unique_ptr(new u8[data.x14_resSize]); - data.x8_dvdReq = x4_loader.LoadResourceAsync(tag, data.x10_loadBuffer.get()); - AddToLoadList(std::move(data)); - } - else - { - *target = std::make_unique(nullptr); - } + CObjectReference* selfRef) { + auto search = m_loadMap.find(tag); + if (search == m_loadMap.end()) { + SLoadingData data(tag, target, xfer, x4_loader.GetResourceCompression(tag), selfRef); + data.x14_resSize = x4_loader.ResourceSize(tag); + if (data.x14_resSize) { + data.x10_loadBuffer = std::unique_ptr(new u8[data.x14_resSize]); + data.x8_dvdReq = x4_loader.LoadResourceAsync(tag, data.x10_loadBuffer.get()); + AddToLoadList(std::move(data)); + } else { + *target = std::make_unique(nullptr); } + } } -void CResFactory::AsyncIdle() -{ - if (m_loadList.empty()) +void CResFactory::AsyncIdle() { + if (m_loadList.empty()) + return; + auto startTime = std::chrono::steady_clock::now(); + while (std::chrono::duration_cast(std::chrono::steady_clock::now() - startTime).count() < + 2) { + auto& task = m_loadList.front(); + if (PumpResource(task)) { + m_loadMap.erase(task.x0_tag); + m_loadList.pop_front(); + if (m_loadList.empty()) return; - auto startTime = std::chrono::steady_clock::now(); - while (std::chrono::duration_cast( - std::chrono::steady_clock::now() - startTime).count() < 2) - { - auto& task = m_loadList.front(); - if (PumpResource(task)) - { - m_loadMap.erase(task.x0_tag); - m_loadList.pop_front(); - if (m_loadList.empty()) - return; - } } + } } -void CResFactory::CancelBuild(const SObjectTag& tag) -{ - auto search = m_loadMap.find(tag); - if (search != m_loadMap.end()) - { - if (search->second->x8_dvdReq) - search->second->x8_dvdReq->PostCancelRequest(); - m_loadList.erase(search->second); - m_loadMap.erase(search); - } +void CResFactory::CancelBuild(const SObjectTag& tag) { + auto search = m_loadMap.find(tag); + if (search != m_loadMap.end()) { + if (search->second->x8_dvdReq) + search->second->x8_dvdReq->PostCancelRequest(); + m_loadList.erase(search->second); + m_loadMap.erase(search); + } } -void CResFactory::LoadOriginalIDs(CSimplePool& sp) -{ +void CResFactory::LoadOriginalIDs(CSimplePool& sp) { #if RUNTIME_ORIGINAL_IDS - m_origIds = sp.GetObj("MP1OriginalIDs"); + m_origIds = sp.GetObj("MP1OriginalIDs"); #endif } -CAssetId CResFactory::TranslateOriginalToNew(CAssetId id) const -{ +CAssetId CResFactory::TranslateOriginalToNew(CAssetId id) const { #if RUNTIME_ORIGINAL_IDS - return m_origIds->TranslateOriginalToNew(id); + return m_origIds->TranslateOriginalToNew(id); #else - /* The packager will have restored these ahead of time */ - return id; + /* The packager will have restored these ahead of time */ + return id; #endif } -CAssetId CResFactory::TranslateNewToOriginal(CAssetId id) const -{ +CAssetId CResFactory::TranslateNewToOriginal(CAssetId id) const { #if RUNTIME_ORIGINAL_IDS - return m_origIds->TranslateNewToOriginal(id); + return m_origIds->TranslateNewToOriginal(id); #else - /* The packager will have restored these ahead of time */ - return id; + /* The packager will have restored these ahead of time */ + return id; #endif } -} +} // namespace urde diff --git a/Runtime/CResFactory.hpp b/Runtime/CResFactory.hpp index 43206074b..6da47676a 100644 --- a/Runtime/CResFactory.hpp +++ b/Runtime/CResFactory.hpp @@ -7,116 +7,92 @@ #include "MP1/MP1OriginalIDs.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class IDvdRequest; class CSimplePool; -class CResFactory : public IFactory -{ - CResLoader x4_loader; - CFactoryMgr x5c_factoryMgr; +class CResFactory : public IFactory { + CResLoader x4_loader; + CFactoryMgr x5c_factoryMgr; #if RUNTIME_ORIGINAL_IDS - TLockedToken m_origIds; + TLockedToken m_origIds; #endif public: - struct SLoadingData - { - SObjectTag x0_tag; - std::shared_ptr x8_dvdReq; - std::unique_ptr* xc_targetPtr = nullptr; - std::unique_ptr x10_loadBuffer; - u32 x14_resSize = 0; - CVParamTransfer x18_cvXfer; - bool m_compressed = false; - CObjectReference* m_selfRef = nullptr; + struct SLoadingData { + SObjectTag x0_tag; + std::shared_ptr x8_dvdReq; + std::unique_ptr* xc_targetPtr = nullptr; + std::unique_ptr x10_loadBuffer; + u32 x14_resSize = 0; + CVParamTransfer x18_cvXfer; + bool m_compressed = false; + CObjectReference* m_selfRef = nullptr; + + SLoadingData() = default; + SLoadingData(const SObjectTag& tag, std::unique_ptr* ptr, const CVParamTransfer& xfer, bool compressed, + CObjectReference* selfRef) + : x0_tag(tag), xc_targetPtr(ptr), x18_cvXfer(xfer), m_compressed(compressed), m_selfRef(selfRef) {} + }; - SLoadingData() = default; - SLoadingData(const SObjectTag& tag, std::unique_ptr* ptr, const CVParamTransfer& xfer, - bool compressed, CObjectReference* selfRef) - : x0_tag(tag), xc_targetPtr(ptr), x18_cvXfer(xfer), m_compressed(compressed), m_selfRef(selfRef) {} - }; private: - std::list m_loadList; - std::unordered_map::iterator> m_loadMap; - void AddToLoadList(SLoadingData&& data); - CFactoryFnReturn BuildSync(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef); - bool PumpResource(SLoadingData& data); + std::list m_loadList; + std::unordered_map::iterator> m_loadMap; + void AddToLoadList(SLoadingData&& data); + CFactoryFnReturn BuildSync(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef); + bool PumpResource(SLoadingData& data); + public: - CResLoader& GetLoader() {return x4_loader;} - std::unique_ptr Build(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef); - void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr*, CObjectReference* selfRef); - void AsyncIdle(); - void CancelBuild(const SObjectTag&); + CResLoader& GetLoader() { return x4_loader; } + std::unique_ptr Build(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef); + void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr*, CObjectReference* selfRef); + void AsyncIdle(); + void CancelBuild(const SObjectTag&); - bool CanBuild(const SObjectTag& tag) - { - return x4_loader.ResourceExists(tag); - } + bool CanBuild(const SObjectTag& tag) { return x4_loader.ResourceExists(tag); } - u32 ResourceSize(const urde::SObjectTag& tag) - { - return x4_loader.ResourceSize(tag); - } + u32 ResourceSize(const urde::SObjectTag& tag) { return x4_loader.ResourceSize(tag); } - std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag) - { - return x4_loader.LoadResourceSync(tag); - } + std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag) { return x4_loader.LoadResourceSync(tag); } - std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size) - { - return x4_loader.LoadNewResourcePartSync(tag, off, size); - } + std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size) { + return x4_loader.LoadNewResourcePartSync(tag, off, size); + } - void GetTagListForFile(const char* pakName, std::vector& out) const - { - return x4_loader.GetTagListForFile(pakName, out); - } + void GetTagListForFile(const char* pakName, std::vector& out) const { + return x4_loader.GetTagListForFile(pakName, out); + } - std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target) - { - return x4_loader.LoadResourceAsync(tag, target); - } + std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target) { + return x4_loader.LoadResourceAsync(tag, target); + } - std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target) - { - return x4_loader.LoadResourcePartAsync(tag, off, size, target); - } + std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target) { + return x4_loader.LoadResourcePartAsync(tag, off, size, target); + } - const SObjectTag* GetResourceIdByName(std::string_view name) const - { - return x4_loader.GetResourceIdByName(name); - } + const SObjectTag* GetResourceIdByName(std::string_view name) const { return x4_loader.GetResourceIdByName(name); } - FourCC GetResourceTypeById(CAssetId id) const - { - return x4_loader.GetResourceTypeById(id); - } + FourCC GetResourceTypeById(CAssetId id) const { return x4_loader.GetResourceTypeById(id); } - std::vector> GetResourceIdToNameList() const - { - return x4_loader.GetResourceIdToNameList(); - } + std::vector> GetResourceIdToNameList() const { + return x4_loader.GetResourceIdToNameList(); + } - void EnumerateResources(const std::function& lambda) const - { - return x4_loader.EnumerateResources(lambda); - } + void EnumerateResources(const std::function& lambda) const { + return x4_loader.EnumerateResources(lambda); + } - void EnumerateNamedResources(const std::function& lambda) const - { - return x4_loader.EnumerateNamedResources(lambda); - } + void EnumerateNamedResources(const std::function& lambda) const { + return x4_loader.EnumerateNamedResources(lambda); + } - void LoadOriginalIDs(CSimplePool& sp); - CAssetId TranslateOriginalToNew(CAssetId id) const; - CAssetId TranslateNewToOriginal(CAssetId id) const; + void LoadOriginalIDs(CSimplePool& sp); + CAssetId TranslateOriginalToNew(CAssetId id) const; + CAssetId TranslateNewToOriginal(CAssetId id) const; - CResLoader* GetResLoader() { return &x4_loader; } - CFactoryMgr* GetFactoryMgr() { return &x5c_factoryMgr; } + CResLoader* GetResLoader() { return &x4_loader; } + CFactoryMgr* GetFactoryMgr() { return &x5c_factoryMgr; } }; -} - +} // namespace urde diff --git a/Runtime/CResLoader.cpp b/Runtime/CResLoader.cpp index a230bc3e6..691426d13 100644 --- a/Runtime/CResLoader.cpp +++ b/Runtime/CResLoader.cpp @@ -1,317 +1,257 @@ #include "CResLoader.hpp" #include "CPakFile.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("CResLoader"); -CResLoader::CResLoader() -{ - x48_curPak = x18_pakLoadedList.end(); +CResLoader::CResLoader() { x48_curPak = x18_pakLoadedList.end(); } + +const std::vector* CResLoader::GetTagListForFile(std::string_view name) const { + std::string namePak = std::string(name) + ".upak"; + for (const std::unique_ptr& pak : x18_pakLoadedList) + if (!CStringExtras::CompareCaseInsensitive(namePak, pak->x18_path)) + return &pak->GetDepList(); + return nullptr; } -const std::vector* CResLoader::GetTagListForFile(std::string_view name) const -{ - std::string namePak = std::string(name) + ".upak"; - for (const std::unique_ptr& pak : x18_pakLoadedList) - if (!CStringExtras::CompareCaseInsensitive(namePak, pak->x18_path)) - return &pak->GetDepList(); - return nullptr; +void CResLoader::AddPakFileAsync(std::string_view name, bool buildDepList, bool worldPak) { + std::string namePak = std::string(name) + ".upak"; + if (CDvdFile::FileExists(namePak.c_str())) { + x30_pakLoadingList.emplace_back(new CPakFile(namePak, buildDepList, worldPak)); + ++x44_pakLoadingCount; + } } -void CResLoader::AddPakFileAsync(std::string_view name, bool buildDepList, bool worldPak) -{ - std::string namePak = std::string(name) + ".upak"; - if (CDvdFile::FileExists(namePak.c_str())) - { - x30_pakLoadingList.emplace_back(new CPakFile(namePak, buildDepList, worldPak)); - ++x44_pakLoadingCount; - } +void CResLoader::AddPakFile(std::string_view name, bool samusPak, bool worldPak) { + AddPakFileAsync(name, samusPak, worldPak); + WaitForPakFileLoadingComplete(); } -void CResLoader::AddPakFile(std::string_view name, bool samusPak, bool worldPak) -{ - AddPakFileAsync(name, samusPak, worldPak); - WaitForPakFileLoadingComplete(); +void CResLoader::WaitForPakFileLoadingComplete() { + while (x44_pakLoadingCount) + AsyncIdlePakLoading(); } -void CResLoader::WaitForPakFileLoadingComplete() -{ - while (x44_pakLoadingCount) - AsyncIdlePakLoading(); +std::unique_ptr CResLoader::LoadNewResourcePartSync(const SObjectTag& tag, u32 length, u32 offset, + void* extBuf) { + void* buf = extBuf; + CPakFile* file = FindResourceForLoad(tag); + if (!buf) + buf = new u8[length]; + file->SyncSeekRead(buf, length, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + offset); + return std::unique_ptr(new athena::io::MemoryReader((atUint8*)buf, length, !extBuf)); } -std::unique_ptr CResLoader::LoadNewResourcePartSync(const SObjectTag& tag, u32 length, u32 offset, void* extBuf) -{ - void* buf = extBuf; - CPakFile* file = FindResourceForLoad(tag); +void CResLoader::LoadMemResourceSync(const SObjectTag& tag, std::unique_ptr& bufOut, int* sizeOut) { + if (CPakFile* file = FindResourceForLoad(tag)) { + bufOut = std::unique_ptr(new u8[x50_cachedResInfo->GetSize()]); + file->SyncSeekRead(bufOut.get(), x50_cachedResInfo->GetSize(), ESeekOrigin::Begin, x50_cachedResInfo->GetOffset()); + *sizeOut = x50_cachedResInfo->GetSize(); + } +} + +std::unique_ptr CResLoader::LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf) { + FindResourceForLoad(tag); + CInputStream* newStrm = new athena::io::MemoryReader((atUint8*)buf, x50_cachedResInfo->GetSize()); + if (x50_cachedResInfo->IsCompressed()) { + newStrm->readUint32Big(); + newStrm = new CZipInputStream(std::unique_ptr(newStrm)); + } + return std::unique_ptr(newStrm); +} + +std::unique_ptr CResLoader::LoadNewResourceSync(const SObjectTag& tag, void* extBuf) { + void* buf = extBuf; + if (CPakFile* file = FindResourceForLoad(tag)) { + size_t resSz = ROUND_UP_32(x50_cachedResInfo->GetSize()); if (!buf) - buf = new u8[length]; - file->SyncSeekRead(buf, length, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + offset); - return std::unique_ptr(new athena::io::MemoryReader((atUint8*)buf, length, !extBuf)); -} - -void CResLoader::LoadMemResourceSync(const SObjectTag& tag, std::unique_ptr& bufOut, int* sizeOut) -{ - if (CPakFile* file = FindResourceForLoad(tag)) - { - bufOut = std::unique_ptr(new u8[x50_cachedResInfo->GetSize()]); - file->SyncSeekRead(bufOut.get(), x50_cachedResInfo->GetSize(), ESeekOrigin::Begin, - x50_cachedResInfo->GetOffset()); - *sizeOut = x50_cachedResInfo->GetSize(); - } -} - -std::unique_ptr CResLoader::LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf) -{ - FindResourceForLoad(tag); - CInputStream* newStrm = new athena::io::MemoryReader((atUint8*)buf, x50_cachedResInfo->GetSize()); - if (x50_cachedResInfo->IsCompressed()) - { - newStrm->readUint32Big(); - newStrm = new CZipInputStream(std::unique_ptr(newStrm)); + buf = new u8[resSz]; + file->SyncSeekRead(buf, resSz, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset()); + CInputStream* newStrm = new athena::io::MemoryReader((atUint8*)buf, resSz, !extBuf); + if (x50_cachedResInfo->IsCompressed()) { + newStrm->readUint32Big(); + newStrm = new CZipInputStream(std::unique_ptr(newStrm)); } return std::unique_ptr(newStrm); + } + return {}; } -std::unique_ptr CResLoader::LoadNewResourceSync(const SObjectTag& tag, void* extBuf) -{ - void* buf = extBuf; - if (CPakFile* file = FindResourceForLoad(tag)) - { - size_t resSz = ROUND_UP_32(x50_cachedResInfo->GetSize()); - if (!buf) - buf = new u8[resSz]; - file->SyncSeekRead(buf, resSz, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset()); - CInputStream* newStrm = new athena::io::MemoryReader((atUint8*) buf, resSz, !extBuf); - if (x50_cachedResInfo->IsCompressed()) - { - newStrm->readUint32Big(); - newStrm = new CZipInputStream(std::unique_ptr(newStrm)); - } - return std::unique_ptr(newStrm); +std::shared_ptr CResLoader::LoadResourcePartAsync(const SObjectTag& tag, u32 off, u32 size, void* buf) { + CPakFile* file = FindResourceForLoad(tag.id); + return file->AsyncSeekRead(buf, size, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + off); +} + +std::shared_ptr CResLoader::LoadResourceAsync(const SObjectTag& tag, void* buf) { + CPakFile* file = FindResourceForLoad(tag.id); + return file->AsyncSeekRead(buf, ROUND_UP_32(x50_cachedResInfo->GetSize()), ESeekOrigin::Begin, + x50_cachedResInfo->GetOffset()); +} + +std::unique_ptr CResLoader::LoadResourceSync(const urde::SObjectTag& tag) { + CPakFile* file = FindResourceForLoad(tag.id); + u32 size = ROUND_UP_32(x50_cachedResInfo->GetSize()); + std::unique_ptr ret(new u8[size]); + file->SyncSeekRead(ret.get(), size, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset()); + return ret; +} + +std::unique_ptr CResLoader::LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size) { + CPakFile* file = FindResourceForLoad(tag.id); + std::unique_ptr ret(new u8[size]); + file->SyncSeekRead(ret.get(), size, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + off); + return ret; +} + +void CResLoader::GetTagListForFile(const char* pakName, std::vector& out) const { + std::string path = std::string(pakName) + ".upak"; + for (const std::unique_ptr& file : x18_pakLoadedList) { + if (!CStringExtras::CompareCaseInsensitive(file->GetPath(), path)) { + auto& depList = file->GetDepList(); + out.reserve(depList.size()); + for (const auto& dep : depList) { + auto resInfo = file->GetResInfo(dep); + out.emplace_back(resInfo->GetType(), dep); + } + return; } - return {}; + } } -std::shared_ptr CResLoader::LoadResourcePartAsync(const SObjectTag& tag, u32 off, u32 size, void* buf) -{ - CPakFile* file = FindResourceForLoad(tag.id); - return file->AsyncSeekRead(buf, size, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + off); +bool CResLoader::GetResourceCompression(const SObjectTag& tag) { + if (FindResource(tag.id)) + return x50_cachedResInfo->IsCompressed(); + return false; } -std::shared_ptr CResLoader::LoadResourceAsync(const SObjectTag& tag, void* buf) -{ - CPakFile* file = FindResourceForLoad(tag.id); - return file->AsyncSeekRead(buf, ROUND_UP_32(x50_cachedResInfo->GetSize()), - ESeekOrigin::Begin, x50_cachedResInfo->GetOffset()); +u32 CResLoader::ResourceSize(const SObjectTag& tag) { + if (FindResource(tag.id)) + return x50_cachedResInfo->GetSize(); + return 0; } -std::unique_ptr CResLoader::LoadResourceSync(const urde::SObjectTag& tag) -{ - CPakFile* file = FindResourceForLoad(tag.id); - u32 size = ROUND_UP_32(x50_cachedResInfo->GetSize()); - std::unique_ptr ret(new u8[size]); - file->SyncSeekRead(ret.get(), size, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset()); - return ret; +bool CResLoader::ResourceExists(const SObjectTag& tag) { return FindResource(tag.id); } + +FourCC CResLoader::GetResourceTypeById(CAssetId id) const { + if (id.IsValid() && FindResource(id)) + return x50_cachedResInfo->GetType(); + return {}; } -std::unique_ptr CResLoader::LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size) -{ - CPakFile* file = FindResourceForLoad(tag.id); - std::unique_ptr ret(new u8[size]); - file->SyncSeekRead(ret.get(), size, ESeekOrigin::Begin, x50_cachedResInfo->GetOffset() + off); - return ret; +const SObjectTag* CResLoader::GetResourceIdByName(std::string_view name) const { + for (const std::unique_ptr& file : x18_pakLoadedList) + if (const SObjectTag* id = file->GetResIdByName(name)) + return id; + return nullptr; } -void CResLoader::GetTagListForFile(const char* pakName, std::vector& out) const -{ - std::string path = std::string(pakName) + ".upak"; - for (const std::unique_ptr& file : x18_pakLoadedList) - { - if (!CStringExtras::CompareCaseInsensitive(file->GetPath(), path)) - { - auto& depList = file->GetDepList(); - out.reserve(depList.size()); - for (const auto& dep : depList) - { - auto resInfo = file->GetResInfo(dep); - out.emplace_back(resInfo->GetType(), dep); - } - return; - } +bool CResLoader::AreAllPaksLoaded() const { return x44_pakLoadingCount == 0; } + +void CResLoader::AsyncIdlePakLoading() { + for (auto it = x30_pakLoadingList.begin(); it != x30_pakLoadingList.end();) { + (*it)->AsyncIdle(); + if ((*it)->x2c_asyncLoadPhase == CPakFile::EAsyncPhase::Loaded) { + MoveToCorrectLoadedList(std::move(*it)); + it = x30_pakLoadingList.erase(it); + --x44_pakLoadingCount; + continue; } + ++it; + } } -bool CResLoader::GetResourceCompression(const SObjectTag& tag) -{ - if (FindResource(tag.id)) - return x50_cachedResInfo->IsCompressed(); - return false; +bool CResLoader::FindResource(CAssetId id) const { + if (x4c_cachedResId == id) + return true; + + if (x48_curPak != x18_pakLoadedList.end()) + if (CacheFromPak(**x48_curPak, id)) + return true; + + for (auto it = x18_pakLoadedList.begin(); it != x18_pakLoadedList.end(); ++it) { + if (it == x48_curPak) + continue; + if (CacheFromPak(**it, id)) + return true; + } + + Log.report(logvisor::Warning, "Unable to find asset %08X", id); + return false; } -u32 CResLoader::ResourceSize(const SObjectTag& tag) -{ - if (FindResource(tag.id)) - return x50_cachedResInfo->GetSize(); - return 0; -} +CPakFile* CResLoader::FindResourceForLoad(CAssetId id) { + if (x48_curPak != x18_pakLoadedList.end()) + if (CacheFromPakForLoad(**x48_curPak, id)) + return &**x48_curPak; -bool CResLoader::ResourceExists(const SObjectTag& tag) -{ - return FindResource(tag.id); -} - -FourCC CResLoader::GetResourceTypeById(CAssetId id) const -{ - if (id.IsValid() && FindResource(id)) - return x50_cachedResInfo->GetType(); - return {}; -} - -const SObjectTag* CResLoader::GetResourceIdByName(std::string_view name) const -{ - for (const std::unique_ptr& file : x18_pakLoadedList) - if (const SObjectTag* id = file->GetResIdByName(name)) - return id; - return nullptr; -} - -bool CResLoader::AreAllPaksLoaded() const -{ - return x44_pakLoadingCount == 0; -} - -void CResLoader::AsyncIdlePakLoading() -{ - for (auto it=x30_pakLoadingList.begin(); - it != x30_pakLoadingList.end();) - { - (*it)->AsyncIdle(); - if ((*it)->x2c_asyncLoadPhase == CPakFile::EAsyncPhase::Loaded) - { - MoveToCorrectLoadedList(std::move(*it)); - it = x30_pakLoadingList.erase(it); - --x44_pakLoadingCount; - continue; - } - ++it; + for (auto it = x18_pakLoadedList.begin(); it != x18_pakLoadedList.end(); ++it) { + if (it == x48_curPak) + continue; + if (CacheFromPakForLoad(**it, id)) { + x48_curPak = it; + return &**it; } + } + + Log.report(logvisor::Error, "Unable to find asset %08X", id); + return nullptr; } -bool CResLoader::FindResource(CAssetId id) const -{ - if (x4c_cachedResId == id) - return true; +CPakFile* CResLoader::FindResourceForLoad(const SObjectTag& tag) { return FindResourceForLoad(tag.id); } - if (x48_curPak != x18_pakLoadedList.end()) - if (CacheFromPak(**x48_curPak, id)) - return true; +bool CResLoader::CacheFromPakForLoad(CPakFile& file, CAssetId id) { + const CPakFile::SResInfo* info; + if (x54_forwardSeek) { + info = file.GetResInfoForLoadPreferForward(id); + x54_forwardSeek = false; + } else { + info = file.GetResInfoForLoadDirectionless(id); + } + if (info) { + x4c_cachedResId = id; + x50_cachedResInfo = info; + return true; + } + return false; +} - for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it) - { - if (it == x48_curPak) - continue; - if (CacheFromPak(**it, id)) - return true; +bool CResLoader::CacheFromPak(const CPakFile& file, CAssetId id) const { + const CPakFile::SResInfo* info = file.GetResInfo(id); + if (info) { + x4c_cachedResId = id; + x50_cachedResInfo = info; + return true; + } + return false; +} + +void CResLoader::MoveToCorrectLoadedList(std::unique_ptr&& file) { + x18_pakLoadedList.push_back(std::move(file)); +} + +std::vector> CResLoader::GetResourceIdToNameList() const { + std::vector> ret; + for (auto it = x18_pakLoadedList.begin(); it != x18_pakLoadedList.end(); ++it) + for (const auto& name : (*it)->GetNameList()) + ret.push_back(name); + return ret; +} + +void CResLoader::EnumerateResources(const std::function& lambda) const { + for (auto it = x18_pakLoadedList.begin(); it != x18_pakLoadedList.end(); ++it) { + for (const CAssetId& id : (*it)->GetDepList()) { + SObjectTag fcc(GetResourceTypeById(id), id); + if (!lambda(fcc)) + return; } - - Log.report(logvisor::Warning, "Unable to find asset %08X", id); - return false; + } } -CPakFile* CResLoader::FindResourceForLoad(CAssetId id) -{ - if (x48_curPak != x18_pakLoadedList.end()) - if (CacheFromPakForLoad(**x48_curPak, id)) - return &**x48_curPak; - - for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it) - { - if (it == x48_curPak) - continue; - if (CacheFromPakForLoad(**it, id)) - { - x48_curPak = it; - return &**it; - } - } - - Log.report(logvisor::Error, "Unable to find asset %08X", id); - return nullptr; +void CResLoader::EnumerateNamedResources(const std::function& lambda) const { + for (auto it = x18_pakLoadedList.begin(); it != x18_pakLoadedList.end(); ++it) + for (const auto& name : (*it)->GetNameList()) + if (!lambda(name.first, name.second)) + return; } -CPakFile* CResLoader::FindResourceForLoad(const SObjectTag& tag) -{ - return FindResourceForLoad(tag.id); -} - -bool CResLoader::CacheFromPakForLoad(CPakFile& file, CAssetId id) -{ - const CPakFile::SResInfo* info; - if (x54_forwardSeek) - { - info = file.GetResInfoForLoadPreferForward(id); - x54_forwardSeek = false; - } - else - { - info = file.GetResInfoForLoadDirectionless(id); - } - if (info) - { - x4c_cachedResId = id; - x50_cachedResInfo = info; - return true; - } - return false; -} - -bool CResLoader::CacheFromPak(const CPakFile& file, CAssetId id) const -{ - const CPakFile::SResInfo* info = file.GetResInfo(id); - if (info) - { - x4c_cachedResId = id; - x50_cachedResInfo = info; - return true; - } - return false; -} - -void CResLoader::MoveToCorrectLoadedList(std::unique_ptr&& file) -{ - x18_pakLoadedList.push_back(std::move(file)); -} - -std::vector> CResLoader::GetResourceIdToNameList() const -{ - std::vector> ret; - for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it) - for (const auto& name : (*it)->GetNameList()) - ret.push_back(name); - return ret; -} - -void CResLoader::EnumerateResources(const std::function& lambda) const -{ - for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it) - { - for (const CAssetId& id : (*it)->GetDepList()) - { - SObjectTag fcc(GetResourceTypeById(id), id); - if (!lambda(fcc)) - return; - } - } -} - -void CResLoader::EnumerateNamedResources(const std::function& lambda) const -{ - for (auto it = x18_pakLoadedList.begin() ; it != x18_pakLoadedList.end() ; ++it) - for (const auto& name : (*it)->GetNameList()) - if (!lambda(name.first, name.second)) - return; -} - -} +} // namespace urde diff --git a/Runtime/CResLoader.hpp b/Runtime/CResLoader.hpp index f7ed6b087..618cfc884 100644 --- a/Runtime/CResLoader.hpp +++ b/Runtime/CResLoader.hpp @@ -6,55 +6,53 @@ #include "CPakFile.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { struct SObjectTag; class IDvdRequest; -class CResLoader -{ - std::string m_loaderPath; - //std::list> x0_aramList; - std::list> x18_pakLoadedList; - std::list> x30_pakLoadingList; - u32 x44_pakLoadingCount = 0; - std::list>::iterator x48_curPak; - mutable CAssetId x4c_cachedResId; - mutable const CPakFile::SResInfo* x50_cachedResInfo = nullptr; - bool x54_forwardSeek = false; +class CResLoader { + std::string m_loaderPath; + // std::list> x0_aramList; + std::list> x18_pakLoadedList; + std::list> x30_pakLoadingList; + u32 x44_pakLoadingCount = 0; + std::list>::iterator x48_curPak; + mutable CAssetId x4c_cachedResId; + mutable const CPakFile::SResInfo* x50_cachedResInfo = nullptr; + bool x54_forwardSeek = false; + public: - CResLoader(); - const std::vector* GetTagListForFile(std::string_view name) const; - void AddPakFileAsync(std::string_view name, bool buildDepList, bool worldPak); - void AddPakFile(std::string_view name, bool samusPak, bool worldPak); - void WaitForPakFileLoadingComplete(); - std::unique_ptr LoadNewResourcePartSync(const SObjectTag& tag, u32 length, u32 offset, void* extBuf); - void LoadMemResourceSync(const SObjectTag& tag, std::unique_ptr& bufOut, int* sizeOut); - std::unique_ptr LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf); - std::unique_ptr LoadNewResourceSync(const SObjectTag& tag, void* extBuf=nullptr); - std::shared_ptr LoadResourcePartAsync(const SObjectTag& tag, u32 off, u32 size, void* buf); - std::shared_ptr LoadResourceAsync(const SObjectTag& tag, void* buf); - std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); - std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size); - void GetTagListForFile(const char* pakName, std::vector& out) const; - bool GetResourceCompression(const SObjectTag& tag); - u32 ResourceSize(const SObjectTag& tag); - bool ResourceExists(const SObjectTag& tag); - FourCC GetResourceTypeById(CAssetId id) const; - const SObjectTag* GetResourceIdByName(std::string_view name) const; - bool AreAllPaksLoaded() const; - void AsyncIdlePakLoading(); - bool FindResource(CAssetId id) const; - CPakFile* FindResourceForLoad(CAssetId id); - CPakFile* FindResourceForLoad(const SObjectTag& tag); - bool CacheFromPakForLoad(CPakFile& file, CAssetId id); - bool CacheFromPak(const CPakFile& file, CAssetId id) const; - void MoveToCorrectLoadedList(std::unique_ptr&& file); - std::vector> GetResourceIdToNameList() const; - void EnumerateResources(const std::function& lambda) const; - void EnumerateNamedResources(const std::function& lambda) const; - const std::list>& GetPaks() const { return x18_pakLoadedList; } + CResLoader(); + const std::vector* GetTagListForFile(std::string_view name) const; + void AddPakFileAsync(std::string_view name, bool buildDepList, bool worldPak); + void AddPakFile(std::string_view name, bool samusPak, bool worldPak); + void WaitForPakFileLoadingComplete(); + std::unique_ptr LoadNewResourcePartSync(const SObjectTag& tag, u32 length, u32 offset, void* extBuf); + void LoadMemResourceSync(const SObjectTag& tag, std::unique_ptr& bufOut, int* sizeOut); + std::unique_ptr LoadResourceFromMemorySync(const SObjectTag& tag, const void* buf); + std::unique_ptr LoadNewResourceSync(const SObjectTag& tag, void* extBuf = nullptr); + std::shared_ptr LoadResourcePartAsync(const SObjectTag& tag, u32 off, u32 size, void* buf); + std::shared_ptr LoadResourceAsync(const SObjectTag& tag, void* buf); + std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); + std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size); + void GetTagListForFile(const char* pakName, std::vector& out) const; + bool GetResourceCompression(const SObjectTag& tag); + u32 ResourceSize(const SObjectTag& tag); + bool ResourceExists(const SObjectTag& tag); + FourCC GetResourceTypeById(CAssetId id) const; + const SObjectTag* GetResourceIdByName(std::string_view name) const; + bool AreAllPaksLoaded() const; + void AsyncIdlePakLoading(); + bool FindResource(CAssetId id) const; + CPakFile* FindResourceForLoad(CAssetId id); + CPakFile* FindResourceForLoad(const SObjectTag& tag); + bool CacheFromPakForLoad(CPakFile& file, CAssetId id); + bool CacheFromPak(const CPakFile& file, CAssetId id) const; + void MoveToCorrectLoadedList(std::unique_ptr&& file); + std::vector> GetResourceIdToNameList() const; + void EnumerateResources(const std::function& lambda) const; + void EnumerateNamedResources(const std::function& lambda) const; + const std::list>& GetPaks() const { return x18_pakLoadedList; } }; -} - +} // namespace urde diff --git a/Runtime/CSaveWorld.cpp b/Runtime/CSaveWorld.cpp index 9aa3f1ca6..4051bc827 100644 --- a/Runtime/CSaveWorld.cpp +++ b/Runtime/CSaveWorld.cpp @@ -1,108 +1,83 @@ #include "CSaveWorld.hpp" #include "CToken.hpp" -namespace urde -{ -CSaveWorld::CSaveWorld(CInputStream &in) -{ - in.readUint32Big(); - u32 version = in.readUint32Big(); - if (version > 1) - x0_areaCount = in.readUint32Big(); - if (version > 2) - { - u32 cinematicCount = in.readUint32Big(); - x4_cinematics.reserve(cinematicCount); - for (u32 i=0 ; i 1) + x0_areaCount = in.readUint32Big(); + if (version > 2) { + u32 cinematicCount = in.readUint32Big(); + x4_cinematics.reserve(cinematicCount); + for (u32 i = 0; i < cinematicCount; ++i) + x4_cinematics.push_back(in.readUint32Big()); - u32 relayCount = in.readUint32Big(); - x14_relays.reserve(relayCount); - for (u32 i=0 ; i 0) - { - u32 scanCount = in.readUint32Big(); - x44_scans.reserve(scanCount); - for (u32 i=0 ; i 0) { + u32 scanCount = in.readUint32Big(); + x44_scans.reserve(scanCount); + for (u32 i = 0; i < scanCount; ++i) { + x44_scans.emplace_back(); + SScanState& st = x44_scans.back(); + st.x0_id = in.readUint32Big(); + st.x4_category = EScanCategory(in.readUint32Big()); } + } } -u32 CSaveWorld::GetAreaCount() const -{ - return x0_areaCount; +u32 CSaveWorld::GetAreaCount() const { return x0_areaCount; } + +u32 CSaveWorld::GetCinematicCount() const { return x4_cinematics.size(); } + +s32 CSaveWorld::GetCinematicIndex(const TEditorId& id) const { + auto it = std::find(x4_cinematics.begin(), x4_cinematics.end(), id); + if (it == x4_cinematics.end()) + return -1; + return it - x4_cinematics.begin(); } -u32 CSaveWorld::GetCinematicCount() const -{ - return x4_cinematics.size(); +u32 CSaveWorld::GetRelayCount() const { return x14_relays.size(); } + +s32 CSaveWorld::GetRelayIndex(const TEditorId& id) const { + auto it = std::find(x14_relays.begin(), x14_relays.end(), id); + if (it == x14_relays.end()) + return -1; + return it - x14_relays.begin(); } -s32 CSaveWorld::GetCinematicIndex(const TEditorId &id) const -{ - auto it = std::find(x4_cinematics.begin(), x4_cinematics.end(), id); - if (it == x4_cinematics.end()) - return -1; - return it - x4_cinematics.begin(); -} +TEditorId CSaveWorld::GetRelayEditorId(u32 idx) const { return x14_relays[idx]; } -u32 CSaveWorld::GetRelayCount() const -{ - return x14_relays.size(); -} +u32 CSaveWorld::GetDoorCount() const { return x34_doors.size(); } -s32 CSaveWorld::GetRelayIndex(const TEditorId &id) const -{ - auto it = std::find(x14_relays.begin(), x14_relays.end(), id); - if (it == x14_relays.end()) - return -1; - return it - x14_relays.begin(); -} - -TEditorId CSaveWorld::GetRelayEditorId(u32 idx) const -{ - return x14_relays[idx]; -} - -u32 CSaveWorld::GetDoorCount() const -{ - return x34_doors.size(); -} - -s32 CSaveWorld::GetDoorIndex(const TEditorId &id) const -{ - auto it = std::find(x34_doors.begin(), x34_doors.end(), id); - if (it == x34_doors.end()) - return -1; - return it - x34_doors.begin(); +s32 CSaveWorld::GetDoorIndex(const TEditorId& id) const { + auto it = std::find(x34_doors.begin(), x34_doors.end(), id); + if (it == x34_doors.end()) + return -1; + return it - x34_doors.begin(); } CFactoryFnReturn FSaveWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/CSaveWorld.hpp b/Runtime/CSaveWorld.hpp index ca5b2f592..030e84341 100644 --- a/Runtime/CSaveWorld.hpp +++ b/Runtime/CSaveWorld.hpp @@ -4,49 +4,45 @@ #include "DNACommon/SAVWCommon.hpp" #include "CFactoryMgr.hpp" -namespace urde -{ +namespace urde { -class CSaveWorld -{ +class CSaveWorld { public: - using EScanCategory = DataSpec::SAVWCommon::EScanCategory; - struct SScanState - { - CAssetId x0_id; - EScanCategory x4_category; - }; + using EScanCategory = DataSpec::SAVWCommon::EScanCategory; + struct SScanState { + CAssetId x0_id; + EScanCategory x4_category; + }; - struct SLayerState - { - TAreaId x0_area; - u32 x4_layer; - }; + struct SLayerState { + TAreaId x0_area; + u32 x4_layer; + }; private: - u32 x0_areaCount; - std::vector x4_cinematics; - std::vector x14_relays; - std::vector x24_layers; - std::vector x34_doors; - std::vector x44_scans; + u32 x0_areaCount; + std::vector x4_cinematics; + std::vector x14_relays; + std::vector x24_layers; + std::vector x34_doors; + std::vector x44_scans; + public: - CSaveWorld(CInputStream& in); - u32 GetAreaCount() const; - u32 GetCinematicCount() const; - s32 GetCinematicIndex(const TEditorId& id) const; - const std::vector& GetCinematics() const { return x4_cinematics; } - const std::vector& GetDoors() const { return x34_doors; } - const std::vector& GetScans() const { return x44_scans; } - u32 GetRelayCount() const; - s32 GetRelayIndex(const TEditorId& id) const; - TEditorId GetRelayEditorId(u32 idx) const; - u32 GetDoorCount() const; - s32 GetDoorIndex(const TEditorId &id) const; + CSaveWorld(CInputStream& in); + u32 GetAreaCount() const; + u32 GetCinematicCount() const; + s32 GetCinematicIndex(const TEditorId& id) const; + const std::vector& GetCinematics() const { return x4_cinematics; } + const std::vector& GetDoors() const { return x34_doors; } + const std::vector& GetScans() const { return x44_scans; } + u32 GetRelayCount() const; + s32 GetRelayIndex(const TEditorId& id) const; + TEditorId GetRelayEditorId(u32 idx) const; + u32 GetDoorCount() const; + s32 GetDoorIndex(const TEditorId& id) const; }; CFactoryFnReturn FSaveWorldFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/CScannableObjectInfo.cpp b/Runtime/CScannableObjectInfo.cpp index 5c32a3cd0..214ae8644 100644 --- a/Runtime/CScannableObjectInfo.cpp +++ b/Runtime/CScannableObjectInfo.cpp @@ -1,77 +1,65 @@ #include "CScannableObjectInfo.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ -CScannableObjectInfo::CScannableObjectInfo(CInputStream& in, CAssetId resId) : x0_scannableObjectId(resId) -{ - u32 version = in.readUint32Big(); - Load(in, version); +namespace urde { +CScannableObjectInfo::CScannableObjectInfo(CInputStream& in, CAssetId resId) : x0_scannableObjectId(resId) { + u32 version = in.readUint32Big(); + Load(in, version); - for (u32 i = 0 ; i < x14_buckets.size(); ++i) - { - x14_buckets[i].x4_appearanceRange *= x8_totalDownloadTime; - } + for (u32 i = 0; i < x14_buckets.size(); ++i) { + x14_buckets[i].x4_appearanceRange *= x8_totalDownloadTime; + } - float appearanceOffset = g_tweakGui->GetScanAppearanceDuration(); - for (u32 i = 0 ; i < x14_buckets.size(); ++i) - { - if (x14_buckets[i].x8_imagePos != -1) - { - x8_totalDownloadTime += appearanceOffset; - for (u32 j = i; j < x14_buckets.size(); j++) - x14_buckets[j].x4_appearanceRange += appearanceOffset; - } + float appearanceOffset = g_tweakGui->GetScanAppearanceDuration(); + for (u32 i = 0; i < x14_buckets.size(); ++i) { + if (x14_buckets[i].x8_imagePos != -1) { + x8_totalDownloadTime += appearanceOffset; + for (u32 j = i; j < x14_buckets.size(); j++) + x14_buckets[j].x4_appearanceRange += appearanceOffset; } + } - for (u32 i = 0; i < x14_buckets.size() - 1; ++i) - { - for (u32 j = i + 1; j < x14_buckets.size(); ++j) - { - if (x14_buckets[i].x8_imagePos == x14_buckets[j].x8_imagePos && x14_buckets[i].x8_imagePos != -1) - x14_buckets[j].x8_imagePos = -1; - } + for (u32 i = 0; i < x14_buckets.size() - 1; ++i) { + for (u32 j = i + 1; j < x14_buckets.size(); ++j) { + if (x14_buckets[i].x8_imagePos == x14_buckets[j].x8_imagePos && x14_buckets[i].x8_imagePos != -1) + x14_buckets[j].x8_imagePos = -1; } + } } -void CScannableObjectInfo::Load(CInputStream& in, u32 version) -{ - in.readUint32Big(); - in.readUint32Big(); - x4_stringId = in.readUint32Big(); - if (version < 4) - x8_totalDownloadTime = in.readFloatBig(); - else - { - u32 scanSpeed = in.readUint32Big(); - x8_totalDownloadTime = g_tweakGui->GetScanSpeed(scanSpeed); - } - xc_category = in.readUint32Big(); - if (version > 4) - x10_important = in.readBool(); +void CScannableObjectInfo::Load(CInputStream& in, u32 version) { + in.readUint32Big(); + in.readUint32Big(); + x4_stringId = in.readUint32Big(); + if (version < 4) + x8_totalDownloadTime = in.readFloatBig(); + else { + u32 scanSpeed = in.readUint32Big(); + x8_totalDownloadTime = g_tweakGui->GetScanSpeed(scanSpeed); + } + xc_category = in.readUint32Big(); + if (version > 4) + x10_important = in.readBool(); - for (u32 i = 0; i < 4; i++) - x14_buckets.emplace_back(in, version); + for (u32 i = 0; i < 4; i++) + x14_buckets.emplace_back(in, version); } -CScannableObjectInfo::SBucket::SBucket(CInputStream& in, u32 version) -{ - x0_texture = in.readUint32Big(); - x4_appearanceRange = in.readFloatBig(); - x8_imagePos = in.readUint32Big(); - if (version > 1) - { - xc_size.x = in.readUint32Big(); - xc_size.y = in.readUint32Big(); - x14_interval = in.readFloatBig(); - if (version >= 3) - x18_fadeDuration = in.readFloatBig(); - } +CScannableObjectInfo::SBucket::SBucket(CInputStream& in, u32 version) { + x0_texture = in.readUint32Big(); + x4_appearanceRange = in.readFloatBig(); + x8_imagePos = in.readUint32Big(); + if (version > 1) { + xc_size.x = in.readUint32Big(); + xc_size.y = in.readUint32Big(); + x14_interval = in.readFloatBig(); + if (version >= 3) + x18_fadeDuration = in.readFloatBig(); + } } CFactoryFnReturn FScannableObjectInfoFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer&, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in, tag.id)); -} + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in, tag.id)); } +} // namespace urde diff --git a/Runtime/CScannableObjectInfo.hpp b/Runtime/CScannableObjectInfo.hpp index 2c784860e..424720951 100644 --- a/Runtime/CScannableObjectInfo.hpp +++ b/Runtime/CScannableObjectInfo.hpp @@ -5,45 +5,40 @@ #include "CToken.hpp" #include "zeus/CVector2i.hpp" -namespace urde -{ -class CScannableObjectInfo -{ +namespace urde { +class CScannableObjectInfo { public: - enum class EPanelType - { - }; + enum class EPanelType {}; - struct SBucket - { - CAssetId x0_texture; - float x4_appearanceRange = 0.f; - u32 x8_imagePos = 0; - zeus::CVector2i xc_size; - float x14_interval = 0.f; - float x18_fadeDuration = 0.f; - SBucket(CInputStream&, u32 version); - }; + struct SBucket { + CAssetId x0_texture; + float x4_appearanceRange = 0.f; + u32 x8_imagePos = 0; + zeus::CVector2i xc_size; + float x14_interval = 0.f; + float x18_fadeDuration = 0.f; + SBucket(CInputStream&, u32 version); + }; private: - void Load(CInputStream&, u32); - CAssetId x0_scannableObjectId; - CAssetId x4_stringId; - float x8_totalDownloadTime = 0.f; - u32 xc_category = 0; - bool x10_important = false; - rstl::reserved_vector x14_buckets; + void Load(CInputStream&, u32); + CAssetId x0_scannableObjectId; + CAssetId x4_stringId; + float x8_totalDownloadTime = 0.f; + u32 xc_category = 0; + bool x10_important = false; + rstl::reserved_vector x14_buckets; public: - CScannableObjectInfo(CInputStream&, CAssetId); - CAssetId GetScannableObjectId() const { return x0_scannableObjectId; } - CAssetId GetStringTableId() const { return x4_stringId; } - float GetTotalDownloadTime() const { return x8_totalDownloadTime; } - const SBucket& GetBucket(s32 idx) const { return x14_buckets[idx]; } - u32 GetCategory() const { return xc_category; } - bool IsImportant() const { return x10_important; } + CScannableObjectInfo(CInputStream&, CAssetId); + CAssetId GetScannableObjectId() const { return x0_scannableObjectId; } + CAssetId GetStringTableId() const { return x4_stringId; } + float GetTotalDownloadTime() const { return x8_totalDownloadTime; } + const SBucket& GetBucket(s32 idx) const { return x14_buckets[idx]; } + u32 GetCategory() const { return xc_category; } + bool IsImportant() const { return x10_important; } }; CFactoryFnReturn FScannableObjectInfoFactory(const SObjectTag&, CInputStream&, const CVParamTransfer&, CObjectReference* selfRef); -} +} // namespace urde diff --git a/Runtime/CSimplePool.cpp b/Runtime/CSimplePool.cpp index 61c368b77..382182df3 100644 --- a/Runtime/CSimplePool.cpp +++ b/Runtime/CSimplePool.cpp @@ -2,84 +2,65 @@ #include "IVParamObj.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { CSimplePool::CSimplePool(IFactory& factory) -: x18_factory(factory), x1c_paramXfer(new TObjOwnerParam(this)) -{} +: x18_factory(factory), x1c_paramXfer(new TObjOwnerParam(this)) {} -CSimplePool::~CSimplePool() -{ - assert(x8_resources.empty() && "Dangling CSimplePool resources detected"); +CSimplePool::~CSimplePool() { assert(x8_resources.empty() && "Dangling CSimplePool resources detected"); } + +CToken CSimplePool::GetObj(const SObjectTag& tag, const CVParamTransfer& paramXfer) { + if (!tag) + return {}; + + auto iter = x8_resources.find(tag); + if (iter != x8_resources.end()) + return CToken(iter->second); + + CObjectReference* ret = new CObjectReference(*this, std::unique_ptr(), tag, paramXfer); + x8_resources.emplace(std::make_pair((SObjectTag)tag, std::move(ret))); + return CToken(ret); } -CToken CSimplePool::GetObj(const SObjectTag& tag, const CVParamTransfer& paramXfer) -{ - if (!tag) - return {}; +CToken CSimplePool::GetObj(const SObjectTag& tag) { return GetObj(tag, x1c_paramXfer); } - auto iter = x8_resources.find(tag); - if (iter != x8_resources.end()) - return CToken(iter->second); +CToken CSimplePool::GetObj(std::string_view resourceName) { return GetObj(resourceName, x1c_paramXfer); } - CObjectReference* ret = new CObjectReference(*this, std::unique_ptr(), tag, paramXfer); - x8_resources.emplace(std::make_pair((SObjectTag)tag, std::move(ret))); - return CToken(ret); +CToken CSimplePool::GetObj(std::string_view resourceName, const CVParamTransfer& paramXfer) { + const SObjectTag* tag = x18_factory.GetResourceIdByName(resourceName); + if (!tag) + return {}; + return GetObj(*tag, paramXfer); } -CToken CSimplePool::GetObj(const SObjectTag& tag) -{ - return GetObj(tag, x1c_paramXfer); +bool CSimplePool::HasObject(const SObjectTag& tag) const { + auto iter = x8_resources.find(tag); + if (iter != x8_resources.cend()) + return true; + return x18_factory.CanBuild(tag); } -CToken CSimplePool::GetObj(std::string_view resourceName) -{ - return GetObj(resourceName, x1c_paramXfer); +bool CSimplePool::ObjectIsLive(const SObjectTag& tag) const { + auto iter = x8_resources.find(tag); + if (iter == x8_resources.cend()) + return false; + return iter->second->IsLoaded(); } -CToken CSimplePool::GetObj(std::string_view resourceName, const CVParamTransfer& paramXfer) -{ - const SObjectTag* tag = x18_factory.GetResourceIdByName(resourceName); - if (!tag) - return {}; - return GetObj(*tag, paramXfer); +void CSimplePool::Flush() {} + +void CSimplePool::ObjectUnreferenced(const SObjectTag& tag) { + auto iter = x8_resources.find(tag); + if (iter != x8_resources.end()) + x8_resources.erase(iter); } -bool CSimplePool::HasObject(const SObjectTag& tag) const -{ - auto iter = x8_resources.find(tag); - if (iter != x8_resources.cend()) - return true; - return x18_factory.CanBuild(tag); +std::vector CSimplePool::GetReferencedTags() const { + std::vector ret; + ret.reserve(x8_resources.size()); + for (const auto& obj : x8_resources) + ret.push_back(obj.first); + return ret; } -bool CSimplePool::ObjectIsLive(const SObjectTag& tag) const -{ - auto iter = x8_resources.find(tag); - if (iter == x8_resources.cend()) - return false; - return iter->second->IsLoaded(); -} - -void CSimplePool::Flush() -{ -} - -void CSimplePool::ObjectUnreferenced(const SObjectTag& tag) -{ - auto iter = x8_resources.find(tag); - if (iter != x8_resources.end()) - x8_resources.erase(iter); -} - -std::vector CSimplePool::GetReferencedTags() const -{ - std::vector ret; - ret.reserve(x8_resources.size()); - for (const auto& obj : x8_resources) - ret.push_back(obj.first); - return ret; -} - -} +} // namespace urde diff --git a/Runtime/CSimplePool.hpp b/Runtime/CSimplePool.hpp index 758382717..6f1cf544f 100644 --- a/Runtime/CSimplePool.hpp +++ b/Runtime/CSimplePool.hpp @@ -5,33 +5,31 @@ #include "IVParamObj.hpp" #include -namespace urde -{ +namespace urde { class IFactory; class CObjectReference; -class CSimplePool : public IObjectStore -{ +class CSimplePool : public IObjectStore { protected: - u8 x4_; - u8 x5_; - std::unordered_map x8_resources; - IFactory& x18_factory; - CVParamTransfer x1c_paramXfer; + u8 x4_; + u8 x5_; + std::unordered_map x8_resources; + IFactory& x18_factory; + CVParamTransfer x1c_paramXfer; + public: - CSimplePool(IFactory& factory); - ~CSimplePool(); - CToken GetObj(const SObjectTag&, const CVParamTransfer&); - CToken GetObj(const SObjectTag&); - CToken GetObj(std::string_view); - CToken GetObj(std::string_view, const CVParamTransfer&); - bool HasObject(const SObjectTag&) const; - bool ObjectIsLive(const SObjectTag&) const; - IFactory& GetFactory() const {return x18_factory;} - void Flush(); - void ObjectUnreferenced(const SObjectTag&); - std::vector GetReferencedTags() const; + CSimplePool(IFactory& factory); + ~CSimplePool(); + CToken GetObj(const SObjectTag&, const CVParamTransfer&); + CToken GetObj(const SObjectTag&); + CToken GetObj(std::string_view); + CToken GetObj(std::string_view, const CVParamTransfer&); + bool HasObject(const SObjectTag&) const; + bool ObjectIsLive(const SObjectTag&) const; + IFactory& GetFactory() const { return x18_factory; } + void Flush(); + void ObjectUnreferenced(const SObjectTag&); + std::vector GetReferencedTags() const; }; -} - +} // namespace urde diff --git a/Runtime/CSortedLists.cpp b/Runtime/CSortedLists.cpp index a79d591c3..65f73da09 100644 --- a/Runtime/CSortedLists.cpp +++ b/Runtime/CSortedLists.cpp @@ -1,349 +1,289 @@ #include "CSortedLists.hpp" #include "World/CActor.hpp" -namespace urde -{ +namespace urde { template -static std::remove_reference_t()[0])>& AccessElement(T& arr, S idx) -{ - assert(std::extent::value > idx && idx >= 0); - return arr[idx]; +static std::remove_reference_t()[0])>& AccessElement(T& arr, S idx) { + assert(std::extent::value > idx && idx >= 0); + return arr[idx]; } -CSortedListManager::CSortedListManager() -{ - Reset(); +CSortedListManager::CSortedListManager() { Reset(); } + +void CSortedListManager::Reset() { + std::fill(std::begin(x0_nodes), std::end(x0_nodes), SNode()); + for (int i = 0; i < 6; ++i) + xb000_sortedLists[i].Reset(); } -void CSortedListManager::Reset() -{ - std::fill(std::begin(x0_nodes), std::end(x0_nodes), SNode()); - for (int i=0 ; i<6 ; ++i) - xb000_sortedLists[i].Reset(); +void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) const { + if (headId == -1) { + const_cast(AccessElement(x0_nodes, nodeId)).x28_next = headId; + headId = nodeId; + tailId = nodeId; + } else { + if (AccessElement(x0_nodes, nodeId).x28_next != -1) + return; + if (tailId == nodeId) + return; + const_cast(AccessElement(x0_nodes, nodeId)).x28_next = headId; + headId = nodeId; + } } -void CSortedListManager::AddToLinkedList(s16 nodeId, s16& headId, s16& tailId) const -{ - if (headId == -1) - { - const_cast(AccessElement(x0_nodes, nodeId)).x28_next = headId; - headId = nodeId; - tailId = nodeId; - } - else - { - if (AccessElement(x0_nodes, nodeId).x28_next != -1) - return; - if (tailId == nodeId) - return; - const_cast(AccessElement(x0_nodes, nodeId)).x28_next = headId; - headId = nodeId; - } +void CSortedListManager::RemoveFromList(ESortedList list, s16 idx) { + SSortedList& sl = xb000_sortedLists[u32(list)]; + while (idx < sl.x800_size - 1) { + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx; + AccessElement(sl.x0_ids, idx) = AccessElement(sl.x0_ids, idx + 1); + ++idx; + } + --sl.x800_size; } -void CSortedListManager::RemoveFromList(ESortedList list, s16 idx) -{ - SSortedList& sl = xb000_sortedLists[u32(list)]; - while (idx < sl.x800_size - 1) - { - AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx; - AccessElement(sl.x0_ids, idx) = AccessElement(sl.x0_ids, idx + 1); - ++idx; +void CSortedListManager::MoveInList(ESortedList list, s16 idx) { + SSortedList& sl = xb000_sortedLists[int(list)]; + while (true) { + if (idx > 0 && AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x4_box[int(list)] > + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[int(list)]) { + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x1c_selfIdxs[int(list)] = idx; + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[int(list)] = idx - 1; + std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx - 1)); + --idx; + } else { + if (idx >= sl.x800_size - 1) + return; + if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x4_box[int(list)] >= + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[int(list)]) + return; + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx; + AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[int(list)] = idx + 1; + std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx + 1)); + ++idx; } - --sl.x800_size; + } } -void CSortedListManager::MoveInList(ESortedList list, s16 idx) -{ - SSortedList& sl = xb000_sortedLists[int(list)]; - while (true) - { - if (idx > 0 && - AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x4_box[int(list)] > - AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[int(list)]) - { - AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx - 1)).x1c_selfIdxs[int(list)] = idx; - AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[int(list)] = idx - 1; - std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx - 1)); - --idx; - } - else - { - if (idx >= sl.x800_size - 1) - return; - if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x4_box[int(list)] >= - AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x4_box[int(list)]) - return; - AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + 1)).x1c_selfIdxs[int(list)] = idx; - AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx)).x1c_selfIdxs[int(list)] = idx + 1; - std::swap(AccessElement(sl.x0_ids, idx), AccessElement(sl.x0_ids, idx + 1)); - ++idx; - } +void CSortedListManager::InsertInList(ESortedList list, SNode& node) { + SSortedList& sl = xb000_sortedLists[int(list)]; + int insIdx = 0; + for (int i = sl.x800_size; i > 0;) { + /* Binary search cycle to find insert index */ + if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, insIdx + i / 2)).x4_box[int(list)] < node.x4_box[int(list)]) { + /* Upper */ + insIdx = insIdx + i / 2 + 1; + i = i - i / 2 - 1; + } else { + /* Lower */ + i /= 2; } + } + + /* Shift ids for insert */ + for (int i = sl.x800_size; i > insIdx; --i) { + AccessElement(x0_nodes, AccessElement(sl.x0_ids, i - 1)).x1c_selfIdxs[int(list)] = i; + AccessElement(sl.x0_ids, i) = AccessElement(sl.x0_ids, i - 1); + } + + /* Do insert */ + AccessElement(sl.x0_ids, insIdx) = node.x0_actor->GetUniqueId().Value(); + node.x1c_selfIdxs[int(list)] = s16(insIdx); + ++sl.x800_size; } -void CSortedListManager::InsertInList(ESortedList list, SNode& node) -{ - SSortedList& sl = xb000_sortedLists[int(list)]; - int insIdx = 0; - for (int i = sl.x800_size ; i > 0 ;) - { - /* Binary search cycle to find insert index */ - if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, insIdx + i / 2)).x4_box[int(list)] < node.x4_box[int(list)]) - { - /* Upper */ - insIdx = insIdx + i / 2 + 1; - i = i - i / 2 - 1; - } - else - { - /* Lower */ - i /= 2; - } +s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const { + const SSortedList& sl = xb000_sortedLists[int(list)]; + int idx = 0; + for (int i = sl.x800_size; i > 0;) { + /* Binary search cycle to find index */ + if (!(val < AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[int(list)])) { + /* Upper */ + idx = idx + i / 2 + 1; + i = i - i / 2 - 1; + } else { + /* Lower */ + i /= 2; } - - /* Shift ids for insert */ - for (int i = sl.x800_size ; i > insIdx ; --i) - { - AccessElement(x0_nodes, AccessElement(sl.x0_ids, i - 1)).x1c_selfIdxs[int(list)] = i; - AccessElement(sl.x0_ids, i) = AccessElement(sl.x0_ids, i - 1); - } - - /* Do insert */ - AccessElement(sl.x0_ids, insIdx) = node.x0_actor->GetUniqueId().Value(); - node.x1c_selfIdxs[int(list)] = s16(insIdx); - ++sl.x800_size; + } + return idx; } -s16 CSortedListManager::FindInListUpper(ESortedList list, float val) const -{ - const SSortedList& sl = xb000_sortedLists[int(list)]; - int idx = 0; - for (int i = sl.x800_size ; i > 0 ;) - { - /* Binary search cycle to find index */ - if (!(val < AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[int(list)])) - { - /* Upper */ - idx = idx + i / 2 + 1; - i = i - i / 2 - 1; - } - else - { - /* Lower */ - i /= 2; - } +s16 CSortedListManager::FindInListLower(ESortedList list, float val) const { + const SSortedList& sl = xb000_sortedLists[int(list)]; + int idx = 0; + for (int i = sl.x800_size; i > 0;) { + /* Binary search cycle to find index */ + if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[int(list)] < val) { + /* Upper */ + idx = idx + i / 2 + 1; + i = i - i / 2 - 1; + } else { + /* Lower */ + i /= 2; } - return idx; + } + return idx; } -s16 CSortedListManager::FindInListLower(ESortedList list, float val) const -{ - const SSortedList& sl = xb000_sortedLists[int(list)]; - int idx = 0; - for (int i = sl.x800_size ; i > 0 ;) - { - /* Binary search cycle to find index */ - if (AccessElement(x0_nodes, AccessElement(sl.x0_ids, idx + i / 2)).x4_box[int(list)] < val) - { - /* Upper */ - idx = idx + i / 2 + 1; - i = i - i / 2 - 1; - } - else - { - /* Lower */ - i /= 2; - } - } - return idx; -} +s16 CSortedListManager::ConstructIntersectionArray(const zeus::CAABox& aabb) { + int minXa = FindInListLower(ESortedList::MinX, aabb.min.x()); + int maxXa = FindInListUpper(ESortedList::MinX, aabb.max.x()); + int minXb = FindInListLower(ESortedList::MaxX, aabb.min.x()); + int maxXb = FindInListUpper(ESortedList::MaxX, aabb.max.x()); + int xEnd = std::min(int(xb000_sortedLists[3].x800_size) - maxXb, minXa) + (maxXb + (maxXa - minXa) - minXb) / 2; -s16 CSortedListManager::ConstructIntersectionArray(const zeus::CAABox& aabb) -{ - int minXa = FindInListLower(ESortedList::MinX, aabb.min.x()); - int maxXa = FindInListUpper(ESortedList::MinX, aabb.max.x()); - int minXb = FindInListLower(ESortedList::MaxX, aabb.min.x()); - int maxXb = FindInListUpper(ESortedList::MaxX, aabb.max.x()); - int xEnd = std::min(int(xb000_sortedLists[3].x800_size) - maxXb, minXa) + (maxXb + (maxXa - minXa) - minXb) / 2; + int minYa = FindInListLower(ESortedList::MinY, aabb.min.y()); + int maxYa = FindInListUpper(ESortedList::MinY, aabb.max.y()); + int minYb = FindInListLower(ESortedList::MaxY, aabb.min.y()); + int maxYb = FindInListUpper(ESortedList::MaxY, aabb.max.y()); + int yEnd = std::min(int(xb000_sortedLists[4].x800_size) - maxYb, minYa) + (maxYb + (maxYa - minYa) - minYb) / 2; - int minYa = FindInListLower(ESortedList::MinY, aabb.min.y()); - int maxYa = FindInListUpper(ESortedList::MinY, aabb.max.y()); - int minYb = FindInListLower(ESortedList::MaxY, aabb.min.y()); - int maxYb = FindInListUpper(ESortedList::MaxY, aabb.max.y()); - int yEnd = std::min(int(xb000_sortedLists[4].x800_size) - maxYb, minYa) + (maxYb + (maxYa - minYa) - minYb) / 2; + int minZa = FindInListLower(ESortedList::MinZ, aabb.min.z()); + int maxZa = FindInListUpper(ESortedList::MinZ, aabb.max.z()); + int minZb = FindInListLower(ESortedList::MaxZ, aabb.min.z()); + int maxZb = FindInListUpper(ESortedList::MaxZ, aabb.max.z()); + int zEnd = std::min(int(xb000_sortedLists[5].x800_size) - maxZb, minZa) + (maxZb + (maxZa - minZa) - minZb) / 2; - int minZa = FindInListLower(ESortedList::MinZ, aabb.min.z()); - int maxZa = FindInListUpper(ESortedList::MinZ, aabb.max.z()); - int minZb = FindInListLower(ESortedList::MaxZ, aabb.min.z()); - int maxZb = FindInListUpper(ESortedList::MaxZ, aabb.max.z()); - int zEnd = std::min(int(xb000_sortedLists[5].x800_size) - maxZb, minZa) + (maxZb + (maxZa - minZa) - minZb) / 2; - - if (xEnd < yEnd && xEnd < zEnd) - { - return CalculateIntersections(ESortedList::MinX, ESortedList::MaxX, minXa, maxXa, minXb, maxXb, - ESortedList::MinY, ESortedList::MaxY, ESortedList::MinZ, ESortedList::MaxZ, aabb); - } - else if (yEnd < zEnd) - { - return CalculateIntersections(ESortedList::MinY, ESortedList::MaxY, minYa, maxYa, minYb, maxYb, - ESortedList::MinX, ESortedList::MaxX, ESortedList::MinZ, ESortedList::MaxZ, aabb); - } - else - { - return CalculateIntersections(ESortedList::MinZ, ESortedList::MaxZ, minZa, maxZa, minZb, maxZb, - ESortedList::MinX, ESortedList::MaxX, ESortedList::MinY, ESortedList::MaxY, aabb); - } + if (xEnd < yEnd && xEnd < zEnd) { + return CalculateIntersections(ESortedList::MinX, ESortedList::MaxX, minXa, maxXa, minXb, maxXb, ESortedList::MinY, + ESortedList::MaxY, ESortedList::MinZ, ESortedList::MaxZ, aabb); + } else if (yEnd < zEnd) { + return CalculateIntersections(ESortedList::MinY, ESortedList::MaxY, minYa, maxYa, minYb, maxYb, ESortedList::MinX, + ESortedList::MaxX, ESortedList::MinZ, ESortedList::MaxZ, aabb); + } else { + return CalculateIntersections(ESortedList::MinZ, ESortedList::MaxZ, minZa, maxZa, minZb, maxZb, ESortedList::MinX, + ESortedList::MaxX, ESortedList::MinY, ESortedList::MaxY, aabb); + } } s16 CSortedListManager::CalculateIntersections(ESortedList la, ESortedList lb, s16 a, s16 b, s16 c, s16 d, ESortedList slA, ESortedList slB, ESortedList slC, ESortedList slD, - const zeus::CAABox& aabb) -{ - s16 headId = -1; - s16 tailId = -1; - for (int i=a ; i aabb[int(lb)]) - AddToLinkedList(id, headId, tailId); - } + if (a < xb000_sortedLists[int(lb)].x800_size - d) { + for (int i = 0; i < a; ++i) { + s16 id = AccessElement(xb000_sortedLists[int(la)].x0_ids, i); + if (AccessElement(x0_nodes, id).x4_box[int(lb)] > aabb[int(lb)]) + AddToLinkedList(id, headId, tailId); } - else - { - for (int i=d ; i aabb[int(slB)] || - node.x4_box[int(slB)] < aabb[int(slA)] || - node.x4_box[int(slC)] > aabb[int(slD)] || - node.x4_box[int(slD)] < aabb[int(slC)]) - { - /* Not intersecting; remove from chain */ - *id = node.x28_next; - node.x28_next = -1; - continue; - } - id = &node.x28_next; + for (s16* id = &headId; *id != -1;) { + SNode& node = AccessElement(x0_nodes, *id); + if (node.x4_box[int(slA)] > aabb[int(slB)] || node.x4_box[int(slB)] < aabb[int(slA)] || + node.x4_box[int(slC)] > aabb[int(slD)] || node.x4_box[int(slD)] < aabb[int(slC)]) { + /* Not intersecting; remove from chain */ + *id = node.x28_next; + node.x28_next = -1; + continue; } + id = &node.x28_next; + } - return headId; + return headId; } void CSortedListManager::BuildNearList(rstl::reserved_vector& out, const zeus::CVector3f& pos, const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter, - const CActor* actor) const -{ - if (mag == 0.f) - mag = 8000.f; - const zeus::CVector3f ray = dir * mag; - const zeus::CVector3f sum = ray + pos; - zeus::CVector3f maxs(std::max(pos.x(), sum.x()), std::max(pos.y(), sum.y()), std::max(pos.z(), sum.z())); - zeus::CVector3f mins(std::min(sum.x(), pos.x()), std::min(sum.y(), pos.y()), std::min(sum.z(), pos.z())); - BuildNearList(out, zeus::CAABox(mins, maxs), filter, actor); + const CActor* actor) const { + if (mag == 0.f) + mag = 8000.f; + const zeus::CVector3f ray = dir * mag; + const zeus::CVector3f sum = ray + pos; + zeus::CVector3f maxs(std::max(pos.x(), sum.x()), std::max(pos.y(), sum.y()), std::max(pos.z(), sum.z())); + zeus::CVector3f mins(std::min(sum.x(), pos.x()), std::min(sum.y(), pos.y()), std::min(sum.z(), pos.z())); + BuildNearList(out, zeus::CAABox(mins, maxs), filter, actor); } void CSortedListManager::BuildNearList(rstl::reserved_vector& out, const CActor& actor, - const zeus::CAABox& aabb) const -{ - const CMaterialFilter& filter = actor.GetMaterialFilter(); - s16 id = const_cast(*this).ConstructIntersectionArray(aabb); - while (id != -1) - { - const SNode& node = AccessElement(x0_nodes, id); - if (&actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList()) && - node.x0_actor->GetMaterialFilter().Passes(actor.GetMaterialList())) - out.push_back(node.x0_actor->GetUniqueId()); + const zeus::CAABox& aabb) const { + const CMaterialFilter& filter = actor.GetMaterialFilter(); + s16 id = const_cast(*this).ConstructIntersectionArray(aabb); + while (id != -1) { + const SNode& node = AccessElement(x0_nodes, id); + if (&actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList()) && + node.x0_actor->GetMaterialFilter().Passes(actor.GetMaterialList())) + out.push_back(node.x0_actor->GetUniqueId()); - id = node.x28_next; - const_cast(node).x28_next = -1; - } + id = node.x28_next; + const_cast(node).x28_next = -1; + } } void CSortedListManager::BuildNearList(rstl::reserved_vector& out, const zeus::CAABox& aabb, - const CMaterialFilter& filter, const CActor* actor) const -{ - s16 id = const_cast(*this).ConstructIntersectionArray(aabb); - while (id != -1) - { - const SNode& node = AccessElement(x0_nodes, id); - if (actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList())) - out.push_back(node.x0_actor->GetUniqueId()); + const CMaterialFilter& filter, const CActor* actor) const { + s16 id = const_cast(*this).ConstructIntersectionArray(aabb); + while (id != -1) { + const SNode& node = AccessElement(x0_nodes, id); + if (actor != node.x0_actor && filter.Passes(node.x0_actor->GetMaterialList())) + out.push_back(node.x0_actor->GetUniqueId()); - id = node.x28_next; - const_cast(node).x28_next = -1; - } + id = node.x28_next; + const_cast(node).x28_next = -1; + } } -void CSortedListManager::Remove(const CActor* act) -{ - SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); - if (!node.x2a_populated) - return; +void CSortedListManager::Remove(const CActor* act) { + SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); + if (!node.x2a_populated) + return; - RemoveFromList(ESortedList::MinX, node.x1c_selfIdxs[0]); - RemoveFromList(ESortedList::MaxX, node.x1c_selfIdxs[3]); - RemoveFromList(ESortedList::MinY, node.x1c_selfIdxs[1]); - RemoveFromList(ESortedList::MaxY, node.x1c_selfIdxs[4]); - RemoveFromList(ESortedList::MinZ, node.x1c_selfIdxs[2]); - RemoveFromList(ESortedList::MaxZ, node.x1c_selfIdxs[5]); - node.x2a_populated = false; + RemoveFromList(ESortedList::MinX, node.x1c_selfIdxs[0]); + RemoveFromList(ESortedList::MaxX, node.x1c_selfIdxs[3]); + RemoveFromList(ESortedList::MinY, node.x1c_selfIdxs[1]); + RemoveFromList(ESortedList::MaxY, node.x1c_selfIdxs[4]); + RemoveFromList(ESortedList::MinZ, node.x1c_selfIdxs[2]); + RemoveFromList(ESortedList::MaxZ, node.x1c_selfIdxs[5]); + node.x2a_populated = false; } -void CSortedListManager::Move(const CActor* act, const zeus::CAABox& aabb) -{ - SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); - node.x4_box = aabb; +void CSortedListManager::Move(const CActor* act, const zeus::CAABox& aabb) { + SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); + node.x4_box = aabb; - MoveInList(ESortedList::MinX, node.x1c_selfIdxs[0]); - MoveInList(ESortedList::MaxX, node.x1c_selfIdxs[3]); - MoveInList(ESortedList::MinY, node.x1c_selfIdxs[1]); - MoveInList(ESortedList::MaxY, node.x1c_selfIdxs[4]); - MoveInList(ESortedList::MinZ, node.x1c_selfIdxs[2]); - MoveInList(ESortedList::MaxZ, node.x1c_selfIdxs[5]); + MoveInList(ESortedList::MinX, node.x1c_selfIdxs[0]); + MoveInList(ESortedList::MaxX, node.x1c_selfIdxs[3]); + MoveInList(ESortedList::MinY, node.x1c_selfIdxs[1]); + MoveInList(ESortedList::MaxY, node.x1c_selfIdxs[4]); + MoveInList(ESortedList::MinZ, node.x1c_selfIdxs[2]); + MoveInList(ESortedList::MaxZ, node.x1c_selfIdxs[5]); } -void CSortedListManager::Insert(const CActor* act, const zeus::CAABox& aabb) -{ - SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); - if (node.x2a_populated) - { - Move(act, aabb); - return; - } +void CSortedListManager::Insert(const CActor* act, const zeus::CAABox& aabb) { + SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); + if (node.x2a_populated) { + Move(act, aabb); + return; + } - SNode newNode(act, aabb); - InsertInList(ESortedList::MinX, newNode); - InsertInList(ESortedList::MaxX, newNode); - InsertInList(ESortedList::MinY, newNode); - InsertInList(ESortedList::MaxY, newNode); - InsertInList(ESortedList::MinZ, newNode); - InsertInList(ESortedList::MaxZ, newNode); - node = newNode; + SNode newNode(act, aabb); + InsertInList(ESortedList::MinX, newNode); + InsertInList(ESortedList::MaxX, newNode); + InsertInList(ESortedList::MinY, newNode); + InsertInList(ESortedList::MaxY, newNode); + InsertInList(ESortedList::MinZ, newNode); + InsertInList(ESortedList::MaxZ, newNode); + node = newNode; } -bool CSortedListManager::ActorInLists(const CActor* act) const -{ - if (!act) - return false; - const SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); - return node.x2a_populated; +bool CSortedListManager::ActorInLists(const CActor* act) const { + if (!act) + return false; + const SNode& node = AccessElement(x0_nodes, act->GetUniqueId().Value()); + return node.x2a_populated; } -} +} // namespace urde diff --git a/Runtime/CSortedLists.hpp b/Runtime/CSortedLists.hpp index 4a145d289..d4ee80689 100644 --- a/Runtime/CSortedLists.hpp +++ b/Runtime/CSortedLists.hpp @@ -4,64 +4,51 @@ #include "zeus/CAABox.hpp" #include "Collision/CMaterialFilter.hpp" -namespace urde -{ -enum ESortedList -{ - MinX, - MinY, - MinZ, - MaxX, - MaxY, - MaxZ -}; +namespace urde { +enum ESortedList { MinX, MinY, MinZ, MaxX, MaxY, MaxZ }; -struct SSortedList -{ - s16 x0_ids[1024]; - u32 x800_size = 0; - void Reset() {std::fill(std::begin(x0_ids), std::end(x0_ids), -1);} - SSortedList() {Reset();} +struct SSortedList { + s16 x0_ids[1024]; + u32 x800_size = 0; + void Reset() { std::fill(std::begin(x0_ids), std::end(x0_ids), -1); } + SSortedList() { Reset(); } }; class CActor; -class CSortedListManager -{ - struct SNode - { - const CActor* x0_actor = nullptr; - zeus::CAABox x4_box = zeus::CAABox::skNullBox; - s16 x1c_selfIdxs[6] = {-1, -1, -1, -1, -1, -1}; - s16 x28_next = -1; - bool x2a_populated = false; - SNode() = default; - SNode(const CActor* act, const zeus::CAABox& aabb) - : x0_actor(act), x4_box(aabb), x2a_populated(true) {} - }; - SNode x0_nodes[1024]; - SSortedList xb000_sortedLists[6]; - void Reset(); - void AddToLinkedList(s16 a, s16& b, s16& c) const; - void RemoveFromList(ESortedList, s16); - void MoveInList(ESortedList, s16); - void InsertInList(ESortedList, SNode& node); - s16 FindInListUpper(ESortedList, float) const; - s16 FindInListLower(ESortedList, float) const; - s16 ConstructIntersectionArray(const zeus::CAABox&); - s16 CalculateIntersections(ESortedList, ESortedList, s16, s16, s16, s16, - ESortedList, ESortedList, ESortedList, ESortedList, const zeus::CAABox&); +class CSortedListManager { + struct SNode { + const CActor* x0_actor = nullptr; + zeus::CAABox x4_box = zeus::CAABox::skNullBox; + s16 x1c_selfIdxs[6] = {-1, -1, -1, -1, -1, -1}; + s16 x28_next = -1; + bool x2a_populated = false; + SNode() = default; + SNode(const CActor* act, const zeus::CAABox& aabb) : x0_actor(act), x4_box(aabb), x2a_populated(true) {} + }; + SNode x0_nodes[1024]; + SSortedList xb000_sortedLists[6]; + void Reset(); + void AddToLinkedList(s16 a, s16& b, s16& c) const; + void RemoveFromList(ESortedList, s16); + void MoveInList(ESortedList, s16); + void InsertInList(ESortedList, SNode& node); + s16 FindInListUpper(ESortedList, float) const; + s16 FindInListLower(ESortedList, float) const; + s16 ConstructIntersectionArray(const zeus::CAABox&); + s16 CalculateIntersections(ESortedList, ESortedList, s16, s16, s16, s16, ESortedList, ESortedList, ESortedList, + ESortedList, const zeus::CAABox&); + public: - CSortedListManager(); - void BuildNearList(rstl::reserved_vector&, const zeus::CVector3f&, const zeus::CVector3f&, - float, const CMaterialFilter&, const CActor*) const; - void BuildNearList(rstl::reserved_vector&, const CActor&, const zeus::CAABox&) const; - void BuildNearList(rstl::reserved_vector&, const zeus::CAABox&, - const CMaterialFilter&, const CActor*) const; - void Remove(const CActor*); - void Move(const CActor* act, const zeus::CAABox& aabb); - void Insert(const CActor* act, const zeus::CAABox& aabb); - bool ActorInLists(const CActor* act) const; + CSortedListManager(); + void BuildNearList(rstl::reserved_vector&, const zeus::CVector3f&, const zeus::CVector3f&, float, + const CMaterialFilter&, const CActor*) const; + void BuildNearList(rstl::reserved_vector&, const CActor&, const zeus::CAABox&) const; + void BuildNearList(rstl::reserved_vector&, const zeus::CAABox&, const CMaterialFilter&, + const CActor*) const; + void Remove(const CActor*); + void Move(const CActor* act, const zeus::CAABox& aabb); + void Insert(const CActor* act, const zeus::CAABox& aabb); + bool ActorInLists(const CActor* act) const; }; -} - +} // namespace urde diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index ece27c25d..f64b8dc2b 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -58,2681 +58,2304 @@ #include "World/CDestroyableRock.hpp" #include -namespace urde -{ +namespace urde { hecl::CVar* sm_logScripting = nullptr; logvisor::Module LogModule("urde::CStateManager"); CStateManager::CStateManager(const std::weak_ptr& relayTracker, - const std::weak_ptr& mwInfo, - const std::weak_ptr& playerState, + const std::weak_ptr& mwInfo, const std::weak_ptr& playerState, const std::weak_ptr& wtMgr, const std::weak_ptr& layerState) : x8b8_playerState(playerState) , x8bc_relayTracker(relayTracker) , x8c0_mapWorldInfo(mwInfo) , x8c4_worldTransManager(wtMgr) -, x8c8_worldLayerState(layerState) -{ - x86c_stateManagerContainer.reset(new CStateManagerContainer); - x870_cameraManager = &x86c_stateManagerContainer->x0_cameraManager; - x874_sortedListManager = &x86c_stateManagerContainer->x3c0_sortedListManager; - x878_weaponManager = &x86c_stateManagerContainer->xe3d8_weaponManager; - x87c_fluidPlaneManager = &x86c_stateManagerContainer->xe3ec_fluidPlaneManager; - x880_envFxManager = &x86c_stateManagerContainer->xe510_envFxManager; - x884_actorModelParticles = &x86c_stateManagerContainer->xf168_actorModelParticles; - x88c_rumbleManager = &x86c_stateManagerContainer->xf250_rumbleManager; +, x8c8_worldLayerState(layerState) { + x86c_stateManagerContainer.reset(new CStateManagerContainer); + x870_cameraManager = &x86c_stateManagerContainer->x0_cameraManager; + x874_sortedListManager = &x86c_stateManagerContainer->x3c0_sortedListManager; + x878_weaponManager = &x86c_stateManagerContainer->xe3d8_weaponManager; + x87c_fluidPlaneManager = &x86c_stateManagerContainer->xe3ec_fluidPlaneManager; + x880_envFxManager = &x86c_stateManagerContainer->xe510_envFxManager; + x884_actorModelParticles = &x86c_stateManagerContainer->xf168_actorModelParticles; + x88c_rumbleManager = &x86c_stateManagerContainer->xf250_rumbleManager; - g_Renderer->SetDrawableCallback(&CStateManager::RendererDrawCallback, this); - x908_loaderCount = int(EScriptObjectType::ScriptObjectTypeMAX); - x90c_loaderFuncs[int(EScriptObjectType::Actor)] = ScriptLoader::LoadActor; - x90c_loaderFuncs[int(EScriptObjectType::Waypoint)] = ScriptLoader::LoadWaypoint; - x90c_loaderFuncs[int(EScriptObjectType::Door)] = ScriptLoader::LoadDoor; - x90c_loaderFuncs[int(EScriptObjectType::Trigger)] = ScriptLoader::LoadTrigger; - x90c_loaderFuncs[int(EScriptObjectType::Timer)] = ScriptLoader::LoadTimer; - x90c_loaderFuncs[int(EScriptObjectType::Counter)] = ScriptLoader::LoadCounter; - x90c_loaderFuncs[int(EScriptObjectType::Effect)] = ScriptLoader::LoadEffect; - x90c_loaderFuncs[int(EScriptObjectType::Platform)] = ScriptLoader::LoadPlatform; - x90c_loaderFuncs[int(EScriptObjectType::Sound)] = ScriptLoader::LoadSound; - x90c_loaderFuncs[int(EScriptObjectType::Generator)] = ScriptLoader::LoadGenerator; - x90c_loaderFuncs[int(EScriptObjectType::Dock)] = ScriptLoader::LoadDock; - x90c_loaderFuncs[int(EScriptObjectType::Camera)] = ScriptLoader::LoadCamera; - x90c_loaderFuncs[int(EScriptObjectType::CameraWaypoint)] = ScriptLoader::LoadCameraWaypoint; - x90c_loaderFuncs[int(EScriptObjectType::NewIntroBoss)] = ScriptLoader::LoadNewIntroBoss; - x90c_loaderFuncs[int(EScriptObjectType::SpawnPoint)] = ScriptLoader::LoadSpawnPoint; - x90c_loaderFuncs[int(EScriptObjectType::CameraHint)] = ScriptLoader::LoadCameraHint; - x90c_loaderFuncs[int(EScriptObjectType::Pickup)] = ScriptLoader::LoadPickup; - x90c_loaderFuncs[int(EScriptObjectType::MemoryRelay)] = ScriptLoader::LoadMemoryRelay; - x90c_loaderFuncs[int(EScriptObjectType::RandomRelay)] = ScriptLoader::LoadRandomRelay; - x90c_loaderFuncs[int(EScriptObjectType::Relay)] = ScriptLoader::LoadRelay; - x90c_loaderFuncs[int(EScriptObjectType::Beetle)] = ScriptLoader::LoadBeetle; - x90c_loaderFuncs[int(EScriptObjectType::HUDMemo)] = ScriptLoader::LoadHUDMemo; - x90c_loaderFuncs[int(EScriptObjectType::CameraFilterKeyframe)] = ScriptLoader::LoadCameraFilterKeyframe; - x90c_loaderFuncs[int(EScriptObjectType::CameraBlurKeyframe)] = ScriptLoader::LoadCameraBlurKeyframe; - x90c_loaderFuncs[int(EScriptObjectType::DamageableTrigger)] = ScriptLoader::LoadDamageableTrigger; - x90c_loaderFuncs[int(EScriptObjectType::Debris)] = ScriptLoader::LoadDebris; - x90c_loaderFuncs[int(EScriptObjectType::CameraShaker)] = ScriptLoader::LoadCameraShaker; - x90c_loaderFuncs[int(EScriptObjectType::ActorKeyframe)] = ScriptLoader::LoadActorKeyframe; - x90c_loaderFuncs[int(EScriptObjectType::Water)] = ScriptLoader::LoadWater; - x90c_loaderFuncs[int(EScriptObjectType::Warwasp)] = ScriptLoader::LoadWarWasp; - x90c_loaderFuncs[int(EScriptObjectType::SpacePirate)] = ScriptLoader::LoadSpacePirate; - x90c_loaderFuncs[int(EScriptObjectType::FlyingPirate)] = ScriptLoader::LoadFlyingPirate; - x90c_loaderFuncs[int(EScriptObjectType::ElitePirate)] = ScriptLoader::LoadElitePirate; - x90c_loaderFuncs[int(EScriptObjectType::MetroidBeta)] = ScriptLoader::LoadMetroidBeta; - x90c_loaderFuncs[int(EScriptObjectType::ChozoGhost)] = ScriptLoader::LoadChozoGhost; - x90c_loaderFuncs[int(EScriptObjectType::CoverPoint)] = ScriptLoader::LoadCoverPoint; - x90c_loaderFuncs[int(EScriptObjectType::SpiderBallWaypoint)] = ScriptLoader::LoadSpiderBallWaypoint; - x90c_loaderFuncs[int(EScriptObjectType::BloodFlower)] = ScriptLoader::LoadBloodFlower; - x90c_loaderFuncs[int(EScriptObjectType::FlickerBat)] = ScriptLoader::LoadFlickerBat; - x90c_loaderFuncs[int(EScriptObjectType::PathCamera)] = ScriptLoader::LoadPathCamera; - x90c_loaderFuncs[int(EScriptObjectType::GrapplePoint)] = ScriptLoader::LoadGrapplePoint; - x90c_loaderFuncs[int(EScriptObjectType::PuddleSpore)] = ScriptLoader::LoadPuddleSpore; - x90c_loaderFuncs[int(EScriptObjectType::DebugCameraWaypoint)] = ScriptLoader::LoadDebugCameraWaypoint; - x90c_loaderFuncs[int(EScriptObjectType::SpiderBallAttractionSurface)] = - ScriptLoader::LoadSpiderBallAttractionSurface; - x90c_loaderFuncs[int(EScriptObjectType::PuddleToadGamma)] = ScriptLoader::LoadPuddleToadGamma; - x90c_loaderFuncs[int(EScriptObjectType::DistanceFog)] = ScriptLoader::LoadDistanceFog; - x90c_loaderFuncs[int(EScriptObjectType::FireFlea)] = ScriptLoader::LoadFireFlea; - x90c_loaderFuncs[int(EScriptObjectType::Metaree)] = ScriptLoader::LoadMetaree; - x90c_loaderFuncs[int(EScriptObjectType::DockAreaChange)] = ScriptLoader::LoadDockAreaChange; - x90c_loaderFuncs[int(EScriptObjectType::ActorRotate)] = ScriptLoader::LoadActorRotate; - x90c_loaderFuncs[int(EScriptObjectType::SpecialFunction)] = ScriptLoader::LoadSpecialFunction; - x90c_loaderFuncs[int(EScriptObjectType::SpankWeed)] = ScriptLoader::LoadSpankWeed; - x90c_loaderFuncs[int(EScriptObjectType::Parasite)] = ScriptLoader::LoadParasite; - x90c_loaderFuncs[int(EScriptObjectType::PlayerHint)] = ScriptLoader::LoadPlayerHint; - x90c_loaderFuncs[int(EScriptObjectType::Ripper)] = ScriptLoader::LoadRipper; - x90c_loaderFuncs[int(EScriptObjectType::PickupGenerator)] = ScriptLoader::LoadPickupGenerator; - x90c_loaderFuncs[int(EScriptObjectType::AIKeyframe)] = ScriptLoader::LoadAIKeyframe; - x90c_loaderFuncs[int(EScriptObjectType::PointOfInterest)] = ScriptLoader::LoadPointOfInterest; - x90c_loaderFuncs[int(EScriptObjectType::Drone)] = ScriptLoader::LoadDrone; - x90c_loaderFuncs[int(EScriptObjectType::MetroidAlpha)] = ScriptLoader::LoadMetroidAlpha; - x90c_loaderFuncs[int(EScriptObjectType::DebrisExtended)] = ScriptLoader::LoadDebrisExtended; - x90c_loaderFuncs[int(EScriptObjectType::Steam)] = ScriptLoader::LoadSteam; - x90c_loaderFuncs[int(EScriptObjectType::Ripple)] = ScriptLoader::LoadRipple; - x90c_loaderFuncs[int(EScriptObjectType::BallTrigger)] = ScriptLoader::LoadBallTrigger; - x90c_loaderFuncs[int(EScriptObjectType::TargetingPoint)] = ScriptLoader::LoadTargetingPoint; - x90c_loaderFuncs[int(EScriptObjectType::EMPulse)] = ScriptLoader::LoadEMPulse; - x90c_loaderFuncs[int(EScriptObjectType::IceSheegoth)] = ScriptLoader::LoadIceSheegoth; - x90c_loaderFuncs[int(EScriptObjectType::PlayerActor)] = ScriptLoader::LoadPlayerActor; - x90c_loaderFuncs[int(EScriptObjectType::Flaahgra)] = ScriptLoader::LoadFlaahgra; - x90c_loaderFuncs[int(EScriptObjectType::AreaAttributes)] = ScriptLoader::LoadAreaAttributes; - x90c_loaderFuncs[int(EScriptObjectType::FishCloud)] = ScriptLoader::LoadFishCloud; - x90c_loaderFuncs[int(EScriptObjectType::FishCloudModifier)] = ScriptLoader::LoadFishCloudModifier; - x90c_loaderFuncs[int(EScriptObjectType::VisorFlare)] = ScriptLoader::LoadVisorFlare; - x90c_loaderFuncs[int(EScriptObjectType::WorldTeleporter)] = ScriptLoader::LoadWorldTeleporter; - x90c_loaderFuncs[int(EScriptObjectType::VisorGoo)] = ScriptLoader::LoadVisorGoo; - x90c_loaderFuncs[int(EScriptObjectType::JellyZap)] = ScriptLoader::LoadJellyZap; - x90c_loaderFuncs[int(EScriptObjectType::ControllerAction)] = ScriptLoader::LoadControllerAction; - x90c_loaderFuncs[int(EScriptObjectType::Switch)] = ScriptLoader::LoadSwitch; - x90c_loaderFuncs[int(EScriptObjectType::PlayerStateChange)] = ScriptLoader::LoadPlayerStateChange; - x90c_loaderFuncs[int(EScriptObjectType::Thardus)] = ScriptLoader::LoadThardus; - x90c_loaderFuncs[int(EScriptObjectType::WallCrawlerSwarm)] = ScriptLoader::LoadWallCrawlerSwarm; - x90c_loaderFuncs[int(EScriptObjectType::AIJumpPoint)] = ScriptLoader::LoadAiJumpPoint; - x90c_loaderFuncs[int(EScriptObjectType::FlaahgraTentacle)] = ScriptLoader::LoadFlaahgraTentacle; - x90c_loaderFuncs[int(EScriptObjectType::RoomAcoustics)] = ScriptLoader::LoadRoomAcoustics; - x90c_loaderFuncs[int(EScriptObjectType::ColorModulate)] = ScriptLoader::LoadColorModulate; - x90c_loaderFuncs[int(EScriptObjectType::ThardusRockProjectile)] = ScriptLoader::LoadThardusRockProjectile; - x90c_loaderFuncs[int(EScriptObjectType::Midi)] = ScriptLoader::LoadMidi; - x90c_loaderFuncs[int(EScriptObjectType::StreamedAudio)] = ScriptLoader::LoadStreamedAudio; - x90c_loaderFuncs[int(EScriptObjectType::WorldTeleporterToo)] = ScriptLoader::LoadWorldTeleporter; - x90c_loaderFuncs[int(EScriptObjectType::Repulsor)] = ScriptLoader::LoadRepulsor; - x90c_loaderFuncs[int(EScriptObjectType::GunTurret)] = ScriptLoader::LoadGunTurret; - x90c_loaderFuncs[int(EScriptObjectType::FogVolume)] = ScriptLoader::LoadFogVolume; - x90c_loaderFuncs[int(EScriptObjectType::Babygoth)] = ScriptLoader::LoadBabygoth; - x90c_loaderFuncs[int(EScriptObjectType::Eyeball)] = ScriptLoader::LoadEyeball; - x90c_loaderFuncs[int(EScriptObjectType::RadialDamage)] = ScriptLoader::LoadRadialDamage; - x90c_loaderFuncs[int(EScriptObjectType::CameraPitchVolume)] = ScriptLoader::LoadCameraPitchVolume; - x90c_loaderFuncs[int(EScriptObjectType::EnvFxDensityController)] = ScriptLoader::LoadEnvFxDensityController; - x90c_loaderFuncs[int(EScriptObjectType::Magdolite)] = ScriptLoader::LoadMagdolite; - x90c_loaderFuncs[int(EScriptObjectType::TeamAIMgr)] = ScriptLoader::LoadTeamAIMgr; - x90c_loaderFuncs[int(EScriptObjectType::SnakeWeedSwarm)] = ScriptLoader::LoadSnakeWeedSwarm; - x90c_loaderFuncs[int(EScriptObjectType::ActorContraption)] = ScriptLoader::LoadActorContraption; - x90c_loaderFuncs[int(EScriptObjectType::Oculus)] = ScriptLoader::LoadOculus; - x90c_loaderFuncs[int(EScriptObjectType::Geemer)] = ScriptLoader::LoadGeemer; - x90c_loaderFuncs[int(EScriptObjectType::SpindleCamera)] = ScriptLoader::LoadSpindleCamera; - x90c_loaderFuncs[int(EScriptObjectType::AtomicAlpha)] = ScriptLoader::LoadAtomicAlpha; - x90c_loaderFuncs[int(EScriptObjectType::CameraHintTrigger)] = ScriptLoader::LoadCameraHintTrigger; - x90c_loaderFuncs[int(EScriptObjectType::RumbleEffect)] = ScriptLoader::LoadRumbleEffect; - x90c_loaderFuncs[int(EScriptObjectType::AmbientAI)] = ScriptLoader::LoadAmbientAI; - x90c_loaderFuncs[int(EScriptObjectType::AtomicBeta)] = ScriptLoader::LoadAtomicBeta; - x90c_loaderFuncs[int(EScriptObjectType::IceZoomer)] = ScriptLoader::LoadIceZoomer; - x90c_loaderFuncs[int(EScriptObjectType::Puffer)] = ScriptLoader::LoadPuffer; - x90c_loaderFuncs[int(EScriptObjectType::Tryclops)] = ScriptLoader::LoadTryclops; - x90c_loaderFuncs[int(EScriptObjectType::Ridley)] = ScriptLoader::LoadRidley; - x90c_loaderFuncs[int(EScriptObjectType::Seedling)] = ScriptLoader::LoadSeedling; - x90c_loaderFuncs[int(EScriptObjectType::ThermalHeatFader)] = ScriptLoader::LoadThermalHeatFader; - x90c_loaderFuncs[int(EScriptObjectType::Burrower)] = ScriptLoader::LoadBurrower; - x90c_loaderFuncs[int(EScriptObjectType::ScriptBeam)] = ScriptLoader::LoadBeam; - x90c_loaderFuncs[int(EScriptObjectType::WorldLightFader)] = ScriptLoader::LoadWorldLightFader; - x90c_loaderFuncs[int(EScriptObjectType::MetroidPrimeStage2)] = ScriptLoader::LoadMetroidPrimeStage2; - x90c_loaderFuncs[int(EScriptObjectType::MetroidPrimeStage1)] = ScriptLoader::LoadMetroidPrimeStage1; - x90c_loaderFuncs[int(EScriptObjectType::MazeNode)] = ScriptLoader::LoadMazeNode; - x90c_loaderFuncs[int(EScriptObjectType::OmegaPirate)] = ScriptLoader::LoadOmegaPirate; - x90c_loaderFuncs[int(EScriptObjectType::PhazonPool)] = ScriptLoader::LoadPhazonPool; - x90c_loaderFuncs[int(EScriptObjectType::PhazonHealingNodule)] = ScriptLoader::LoadPhazonHealingNodule; - x90c_loaderFuncs[int(EScriptObjectType::NewCameraShaker)] = ScriptLoader::LoadNewCameraShaker; - x90c_loaderFuncs[int(EScriptObjectType::ShadowProjector)] = ScriptLoader::LoadShadowProjector; - x90c_loaderFuncs[int(EScriptObjectType::EnergyBall)] = ScriptLoader::LoadEnergyBall; + g_Renderer->SetDrawableCallback(&CStateManager::RendererDrawCallback, this); + x908_loaderCount = int(EScriptObjectType::ScriptObjectTypeMAX); + x90c_loaderFuncs[int(EScriptObjectType::Actor)] = ScriptLoader::LoadActor; + x90c_loaderFuncs[int(EScriptObjectType::Waypoint)] = ScriptLoader::LoadWaypoint; + x90c_loaderFuncs[int(EScriptObjectType::Door)] = ScriptLoader::LoadDoor; + x90c_loaderFuncs[int(EScriptObjectType::Trigger)] = ScriptLoader::LoadTrigger; + x90c_loaderFuncs[int(EScriptObjectType::Timer)] = ScriptLoader::LoadTimer; + x90c_loaderFuncs[int(EScriptObjectType::Counter)] = ScriptLoader::LoadCounter; + x90c_loaderFuncs[int(EScriptObjectType::Effect)] = ScriptLoader::LoadEffect; + x90c_loaderFuncs[int(EScriptObjectType::Platform)] = ScriptLoader::LoadPlatform; + x90c_loaderFuncs[int(EScriptObjectType::Sound)] = ScriptLoader::LoadSound; + x90c_loaderFuncs[int(EScriptObjectType::Generator)] = ScriptLoader::LoadGenerator; + x90c_loaderFuncs[int(EScriptObjectType::Dock)] = ScriptLoader::LoadDock; + x90c_loaderFuncs[int(EScriptObjectType::Camera)] = ScriptLoader::LoadCamera; + x90c_loaderFuncs[int(EScriptObjectType::CameraWaypoint)] = ScriptLoader::LoadCameraWaypoint; + x90c_loaderFuncs[int(EScriptObjectType::NewIntroBoss)] = ScriptLoader::LoadNewIntroBoss; + x90c_loaderFuncs[int(EScriptObjectType::SpawnPoint)] = ScriptLoader::LoadSpawnPoint; + x90c_loaderFuncs[int(EScriptObjectType::CameraHint)] = ScriptLoader::LoadCameraHint; + x90c_loaderFuncs[int(EScriptObjectType::Pickup)] = ScriptLoader::LoadPickup; + x90c_loaderFuncs[int(EScriptObjectType::MemoryRelay)] = ScriptLoader::LoadMemoryRelay; + x90c_loaderFuncs[int(EScriptObjectType::RandomRelay)] = ScriptLoader::LoadRandomRelay; + x90c_loaderFuncs[int(EScriptObjectType::Relay)] = ScriptLoader::LoadRelay; + x90c_loaderFuncs[int(EScriptObjectType::Beetle)] = ScriptLoader::LoadBeetle; + x90c_loaderFuncs[int(EScriptObjectType::HUDMemo)] = ScriptLoader::LoadHUDMemo; + x90c_loaderFuncs[int(EScriptObjectType::CameraFilterKeyframe)] = ScriptLoader::LoadCameraFilterKeyframe; + x90c_loaderFuncs[int(EScriptObjectType::CameraBlurKeyframe)] = ScriptLoader::LoadCameraBlurKeyframe; + x90c_loaderFuncs[int(EScriptObjectType::DamageableTrigger)] = ScriptLoader::LoadDamageableTrigger; + x90c_loaderFuncs[int(EScriptObjectType::Debris)] = ScriptLoader::LoadDebris; + x90c_loaderFuncs[int(EScriptObjectType::CameraShaker)] = ScriptLoader::LoadCameraShaker; + x90c_loaderFuncs[int(EScriptObjectType::ActorKeyframe)] = ScriptLoader::LoadActorKeyframe; + x90c_loaderFuncs[int(EScriptObjectType::Water)] = ScriptLoader::LoadWater; + x90c_loaderFuncs[int(EScriptObjectType::Warwasp)] = ScriptLoader::LoadWarWasp; + x90c_loaderFuncs[int(EScriptObjectType::SpacePirate)] = ScriptLoader::LoadSpacePirate; + x90c_loaderFuncs[int(EScriptObjectType::FlyingPirate)] = ScriptLoader::LoadFlyingPirate; + x90c_loaderFuncs[int(EScriptObjectType::ElitePirate)] = ScriptLoader::LoadElitePirate; + x90c_loaderFuncs[int(EScriptObjectType::MetroidBeta)] = ScriptLoader::LoadMetroidBeta; + x90c_loaderFuncs[int(EScriptObjectType::ChozoGhost)] = ScriptLoader::LoadChozoGhost; + x90c_loaderFuncs[int(EScriptObjectType::CoverPoint)] = ScriptLoader::LoadCoverPoint; + x90c_loaderFuncs[int(EScriptObjectType::SpiderBallWaypoint)] = ScriptLoader::LoadSpiderBallWaypoint; + x90c_loaderFuncs[int(EScriptObjectType::BloodFlower)] = ScriptLoader::LoadBloodFlower; + x90c_loaderFuncs[int(EScriptObjectType::FlickerBat)] = ScriptLoader::LoadFlickerBat; + x90c_loaderFuncs[int(EScriptObjectType::PathCamera)] = ScriptLoader::LoadPathCamera; + x90c_loaderFuncs[int(EScriptObjectType::GrapplePoint)] = ScriptLoader::LoadGrapplePoint; + x90c_loaderFuncs[int(EScriptObjectType::PuddleSpore)] = ScriptLoader::LoadPuddleSpore; + x90c_loaderFuncs[int(EScriptObjectType::DebugCameraWaypoint)] = ScriptLoader::LoadDebugCameraWaypoint; + x90c_loaderFuncs[int(EScriptObjectType::SpiderBallAttractionSurface)] = ScriptLoader::LoadSpiderBallAttractionSurface; + x90c_loaderFuncs[int(EScriptObjectType::PuddleToadGamma)] = ScriptLoader::LoadPuddleToadGamma; + x90c_loaderFuncs[int(EScriptObjectType::DistanceFog)] = ScriptLoader::LoadDistanceFog; + x90c_loaderFuncs[int(EScriptObjectType::FireFlea)] = ScriptLoader::LoadFireFlea; + x90c_loaderFuncs[int(EScriptObjectType::Metaree)] = ScriptLoader::LoadMetaree; + x90c_loaderFuncs[int(EScriptObjectType::DockAreaChange)] = ScriptLoader::LoadDockAreaChange; + x90c_loaderFuncs[int(EScriptObjectType::ActorRotate)] = ScriptLoader::LoadActorRotate; + x90c_loaderFuncs[int(EScriptObjectType::SpecialFunction)] = ScriptLoader::LoadSpecialFunction; + x90c_loaderFuncs[int(EScriptObjectType::SpankWeed)] = ScriptLoader::LoadSpankWeed; + x90c_loaderFuncs[int(EScriptObjectType::Parasite)] = ScriptLoader::LoadParasite; + x90c_loaderFuncs[int(EScriptObjectType::PlayerHint)] = ScriptLoader::LoadPlayerHint; + x90c_loaderFuncs[int(EScriptObjectType::Ripper)] = ScriptLoader::LoadRipper; + x90c_loaderFuncs[int(EScriptObjectType::PickupGenerator)] = ScriptLoader::LoadPickupGenerator; + x90c_loaderFuncs[int(EScriptObjectType::AIKeyframe)] = ScriptLoader::LoadAIKeyframe; + x90c_loaderFuncs[int(EScriptObjectType::PointOfInterest)] = ScriptLoader::LoadPointOfInterest; + x90c_loaderFuncs[int(EScriptObjectType::Drone)] = ScriptLoader::LoadDrone; + x90c_loaderFuncs[int(EScriptObjectType::MetroidAlpha)] = ScriptLoader::LoadMetroidAlpha; + x90c_loaderFuncs[int(EScriptObjectType::DebrisExtended)] = ScriptLoader::LoadDebrisExtended; + x90c_loaderFuncs[int(EScriptObjectType::Steam)] = ScriptLoader::LoadSteam; + x90c_loaderFuncs[int(EScriptObjectType::Ripple)] = ScriptLoader::LoadRipple; + x90c_loaderFuncs[int(EScriptObjectType::BallTrigger)] = ScriptLoader::LoadBallTrigger; + x90c_loaderFuncs[int(EScriptObjectType::TargetingPoint)] = ScriptLoader::LoadTargetingPoint; + x90c_loaderFuncs[int(EScriptObjectType::EMPulse)] = ScriptLoader::LoadEMPulse; + x90c_loaderFuncs[int(EScriptObjectType::IceSheegoth)] = ScriptLoader::LoadIceSheegoth; + x90c_loaderFuncs[int(EScriptObjectType::PlayerActor)] = ScriptLoader::LoadPlayerActor; + x90c_loaderFuncs[int(EScriptObjectType::Flaahgra)] = ScriptLoader::LoadFlaahgra; + x90c_loaderFuncs[int(EScriptObjectType::AreaAttributes)] = ScriptLoader::LoadAreaAttributes; + x90c_loaderFuncs[int(EScriptObjectType::FishCloud)] = ScriptLoader::LoadFishCloud; + x90c_loaderFuncs[int(EScriptObjectType::FishCloudModifier)] = ScriptLoader::LoadFishCloudModifier; + x90c_loaderFuncs[int(EScriptObjectType::VisorFlare)] = ScriptLoader::LoadVisorFlare; + x90c_loaderFuncs[int(EScriptObjectType::WorldTeleporter)] = ScriptLoader::LoadWorldTeleporter; + x90c_loaderFuncs[int(EScriptObjectType::VisorGoo)] = ScriptLoader::LoadVisorGoo; + x90c_loaderFuncs[int(EScriptObjectType::JellyZap)] = ScriptLoader::LoadJellyZap; + x90c_loaderFuncs[int(EScriptObjectType::ControllerAction)] = ScriptLoader::LoadControllerAction; + x90c_loaderFuncs[int(EScriptObjectType::Switch)] = ScriptLoader::LoadSwitch; + x90c_loaderFuncs[int(EScriptObjectType::PlayerStateChange)] = ScriptLoader::LoadPlayerStateChange; + x90c_loaderFuncs[int(EScriptObjectType::Thardus)] = ScriptLoader::LoadThardus; + x90c_loaderFuncs[int(EScriptObjectType::WallCrawlerSwarm)] = ScriptLoader::LoadWallCrawlerSwarm; + x90c_loaderFuncs[int(EScriptObjectType::AIJumpPoint)] = ScriptLoader::LoadAiJumpPoint; + x90c_loaderFuncs[int(EScriptObjectType::FlaahgraTentacle)] = ScriptLoader::LoadFlaahgraTentacle; + x90c_loaderFuncs[int(EScriptObjectType::RoomAcoustics)] = ScriptLoader::LoadRoomAcoustics; + x90c_loaderFuncs[int(EScriptObjectType::ColorModulate)] = ScriptLoader::LoadColorModulate; + x90c_loaderFuncs[int(EScriptObjectType::ThardusRockProjectile)] = ScriptLoader::LoadThardusRockProjectile; + x90c_loaderFuncs[int(EScriptObjectType::Midi)] = ScriptLoader::LoadMidi; + x90c_loaderFuncs[int(EScriptObjectType::StreamedAudio)] = ScriptLoader::LoadStreamedAudio; + x90c_loaderFuncs[int(EScriptObjectType::WorldTeleporterToo)] = ScriptLoader::LoadWorldTeleporter; + x90c_loaderFuncs[int(EScriptObjectType::Repulsor)] = ScriptLoader::LoadRepulsor; + x90c_loaderFuncs[int(EScriptObjectType::GunTurret)] = ScriptLoader::LoadGunTurret; + x90c_loaderFuncs[int(EScriptObjectType::FogVolume)] = ScriptLoader::LoadFogVolume; + x90c_loaderFuncs[int(EScriptObjectType::Babygoth)] = ScriptLoader::LoadBabygoth; + x90c_loaderFuncs[int(EScriptObjectType::Eyeball)] = ScriptLoader::LoadEyeball; + x90c_loaderFuncs[int(EScriptObjectType::RadialDamage)] = ScriptLoader::LoadRadialDamage; + x90c_loaderFuncs[int(EScriptObjectType::CameraPitchVolume)] = ScriptLoader::LoadCameraPitchVolume; + x90c_loaderFuncs[int(EScriptObjectType::EnvFxDensityController)] = ScriptLoader::LoadEnvFxDensityController; + x90c_loaderFuncs[int(EScriptObjectType::Magdolite)] = ScriptLoader::LoadMagdolite; + x90c_loaderFuncs[int(EScriptObjectType::TeamAIMgr)] = ScriptLoader::LoadTeamAIMgr; + x90c_loaderFuncs[int(EScriptObjectType::SnakeWeedSwarm)] = ScriptLoader::LoadSnakeWeedSwarm; + x90c_loaderFuncs[int(EScriptObjectType::ActorContraption)] = ScriptLoader::LoadActorContraption; + x90c_loaderFuncs[int(EScriptObjectType::Oculus)] = ScriptLoader::LoadOculus; + x90c_loaderFuncs[int(EScriptObjectType::Geemer)] = ScriptLoader::LoadGeemer; + x90c_loaderFuncs[int(EScriptObjectType::SpindleCamera)] = ScriptLoader::LoadSpindleCamera; + x90c_loaderFuncs[int(EScriptObjectType::AtomicAlpha)] = ScriptLoader::LoadAtomicAlpha; + x90c_loaderFuncs[int(EScriptObjectType::CameraHintTrigger)] = ScriptLoader::LoadCameraHintTrigger; + x90c_loaderFuncs[int(EScriptObjectType::RumbleEffect)] = ScriptLoader::LoadRumbleEffect; + x90c_loaderFuncs[int(EScriptObjectType::AmbientAI)] = ScriptLoader::LoadAmbientAI; + x90c_loaderFuncs[int(EScriptObjectType::AtomicBeta)] = ScriptLoader::LoadAtomicBeta; + x90c_loaderFuncs[int(EScriptObjectType::IceZoomer)] = ScriptLoader::LoadIceZoomer; + x90c_loaderFuncs[int(EScriptObjectType::Puffer)] = ScriptLoader::LoadPuffer; + x90c_loaderFuncs[int(EScriptObjectType::Tryclops)] = ScriptLoader::LoadTryclops; + x90c_loaderFuncs[int(EScriptObjectType::Ridley)] = ScriptLoader::LoadRidley; + x90c_loaderFuncs[int(EScriptObjectType::Seedling)] = ScriptLoader::LoadSeedling; + x90c_loaderFuncs[int(EScriptObjectType::ThermalHeatFader)] = ScriptLoader::LoadThermalHeatFader; + x90c_loaderFuncs[int(EScriptObjectType::Burrower)] = ScriptLoader::LoadBurrower; + x90c_loaderFuncs[int(EScriptObjectType::ScriptBeam)] = ScriptLoader::LoadBeam; + x90c_loaderFuncs[int(EScriptObjectType::WorldLightFader)] = ScriptLoader::LoadWorldLightFader; + x90c_loaderFuncs[int(EScriptObjectType::MetroidPrimeStage2)] = ScriptLoader::LoadMetroidPrimeStage2; + x90c_loaderFuncs[int(EScriptObjectType::MetroidPrimeStage1)] = ScriptLoader::LoadMetroidPrimeStage1; + x90c_loaderFuncs[int(EScriptObjectType::MazeNode)] = ScriptLoader::LoadMazeNode; + x90c_loaderFuncs[int(EScriptObjectType::OmegaPirate)] = ScriptLoader::LoadOmegaPirate; + x90c_loaderFuncs[int(EScriptObjectType::PhazonPool)] = ScriptLoader::LoadPhazonPool; + x90c_loaderFuncs[int(EScriptObjectType::PhazonHealingNodule)] = ScriptLoader::LoadPhazonHealingNodule; + x90c_loaderFuncs[int(EScriptObjectType::NewCameraShaker)] = ScriptLoader::LoadNewCameraShaker; + x90c_loaderFuncs[int(EScriptObjectType::ShadowProjector)] = ScriptLoader::LoadShadowProjector; + x90c_loaderFuncs[int(EScriptObjectType::EnergyBall)] = ScriptLoader::LoadEnergyBall; - CGameCollision::InitCollision(); - ControlMapper::ResetCommandFilters(); - x8f0_shadowTex = g_SimplePool->GetObj("DefaultShadow"); - g_StateManager = this; + CGameCollision::InitCollision(); + ControlMapper::ResetCommandFilters(); + x8f0_shadowTex = g_SimplePool->GetObj("DefaultShadow"); + g_StateManager = this; - sm_logScripting = hecl::CVarManager::instance()->findOrMakeCVar("stateManager.logScripting"sv, "Prints object communication to the console", false, hecl::CVar::EFlags::ReadOnly | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::Game); + sm_logScripting = hecl::CVarManager::instance()->findOrMakeCVar( + "stateManager.logScripting"sv, "Prints object communication to the console", false, + hecl::CVar::EFlags::ReadOnly | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::Game); } -CStateManager::~CStateManager() -{ - x88c_rumbleManager->HardStopAll(); - x880_envFxManager->Cleanup(); - x900_activeRandom = &x8fc_random; - ClearGraveyard(); - for (auto it = x808_objLists[0]->begin() ; it != x808_objLists[0]->end() ;) - { - CEntity* ent = *it; - ++it; - if (ent == x84c_player.get()) - continue; - ent->AcceptScriptMsg(EScriptObjectMessage::Deleted, kInvalidUniqueId, *this); - RemoveObject(ent->GetUniqueId()); - std::default_delete()(ent); - } - ClearGraveyard(); - x84c_player->AcceptScriptMsg(EScriptObjectMessage::Deleted, kInvalidUniqueId, *this); - RemoveObject(x84c_player->GetUniqueId()); - x84c_player.reset(); - CCollisionPrimitive::Uninitialize(); - g_StateManager = nullptr; +CStateManager::~CStateManager() { + x88c_rumbleManager->HardStopAll(); + x880_envFxManager->Cleanup(); + x900_activeRandom = &x8fc_random; + ClearGraveyard(); + for (auto it = x808_objLists[0]->begin(); it != x808_objLists[0]->end();) { + CEntity* ent = *it; + ++it; + if (ent == x84c_player.get()) + continue; + ent->AcceptScriptMsg(EScriptObjectMessage::Deleted, kInvalidUniqueId, *this); + RemoveObject(ent->GetUniqueId()); + std::default_delete()(ent); + } + ClearGraveyard(); + x84c_player->AcceptScriptMsg(EScriptObjectMessage::Deleted, kInvalidUniqueId, *this); + RemoveObject(x84c_player->GetUniqueId()); + x84c_player.reset(); + CCollisionPrimitive::Uninitialize(); + g_StateManager = nullptr; } -void CStateManager::UpdateThermalVisor() -{ - xf28_thermColdScale2 = 0.f; - xf24_thermColdScale1 = 0.f; - CPlayerState::EPlayerVisor visor = x8b8_playerState->GetActiveVisor(*this); - if (visor == CPlayerState::EPlayerVisor::Thermal && x8cc_nextAreaId != kInvalidAreaId) - { - CGameArea* area = x850_world->GetArea(x8cc_nextAreaId); - const zeus::CTransform& playerXf = x84c_player->GetTransform(); - zeus::CVector3f playerXYPos(playerXf.origin.x(), playerXf.origin.y(), 0.f); - CGameArea* lastArea = nullptr; - float closestDist = FLT_MAX; - for (const CGameArea::Dock& dock : area->GetDocks()) - { - zeus::CVector3f dockCenter = (dock.GetPlaneVertices()[0] + dock.GetPlaneVertices()[1] + - dock.GetPlaneVertices()[2] + dock.GetPlaneVertices()[3]) * - 0.25f; - dockCenter.z() = 0.f; - float dist = (playerXYPos - dockCenter).magSquared(); - if (dist < closestDist) - { - TAreaId connAreaId = dock.GetConnectedAreaId(0); - if (connAreaId != kInvalidAreaId) - { - CGameArea* connArea = x850_world->GetArea(x8cc_nextAreaId); - if (connArea->IsPostConstructed()) - { - CGameArea::EOcclusionState occState = connArea->GetPostConstructed()->x10dc_occlusionState; - if (occState == CGameArea::EOcclusionState::Visible) - { - closestDist = dist; - lastArea = connArea; - } - } - } +void CStateManager::UpdateThermalVisor() { + xf28_thermColdScale2 = 0.f; + xf24_thermColdScale1 = 0.f; + CPlayerState::EPlayerVisor visor = x8b8_playerState->GetActiveVisor(*this); + if (visor == CPlayerState::EPlayerVisor::Thermal && x8cc_nextAreaId != kInvalidAreaId) { + CGameArea* area = x850_world->GetArea(x8cc_nextAreaId); + const zeus::CTransform& playerXf = x84c_player->GetTransform(); + zeus::CVector3f playerXYPos(playerXf.origin.x(), playerXf.origin.y(), 0.f); + CGameArea* lastArea = nullptr; + float closestDist = FLT_MAX; + for (const CGameArea::Dock& dock : area->GetDocks()) { + zeus::CVector3f dockCenter = (dock.GetPlaneVertices()[0] + dock.GetPlaneVertices()[1] + + dock.GetPlaneVertices()[2] + dock.GetPlaneVertices()[3]) * + 0.25f; + dockCenter.z() = 0.f; + float dist = (playerXYPos - dockCenter).magSquared(); + if (dist < closestDist) { + TAreaId connAreaId = dock.GetConnectedAreaId(0); + if (connAreaId != kInvalidAreaId) { + CGameArea* connArea = x850_world->GetArea(x8cc_nextAreaId); + if (connArea->IsPostConstructed()) { + CGameArea::EOcclusionState occState = connArea->GetPostConstructed()->x10dc_occlusionState; + if (occState == CGameArea::EOcclusionState::Visible) { + closestDist = dist; + lastArea = connArea; } + } } - - if (lastArea != nullptr) - { - if (closestDist != 0.f) - closestDist /= std::sqrt(closestDist); - closestDist -= 2.f; - if (closestDist < 8.f) - { - if (closestDist > 0.f) - closestDist = (closestDist / 8.f) * 0.5f + 0.5f; - else - closestDist = 0.5f; - - xf24_thermColdScale1 = (1.f - closestDist) * lastArea->GetPostConstructed()->x111c_thermalCurrent + - closestDist * area->GetPostConstructed()->x111c_thermalCurrent; - return; - } - } - - xf24_thermColdScale1 = area->GetPostConstructed()->x111c_thermalCurrent; + } } + + if (lastArea != nullptr) { + if (closestDist != 0.f) + closestDist /= std::sqrt(closestDist); + closestDist -= 2.f; + if (closestDist < 8.f) { + if (closestDist > 0.f) + closestDist = (closestDist / 8.f) * 0.5f + 0.5f; + else + closestDist = 0.5f; + + xf24_thermColdScale1 = (1.f - closestDist) * lastArea->GetPostConstructed()->x111c_thermalCurrent + + closestDist * area->GetPostConstructed()->x111c_thermalCurrent; + return; + } + } + + xf24_thermColdScale1 = area->GetPostConstructed()->x111c_thermalCurrent; + } } -void CStateManager::RendererDrawCallback(const void* drawable, const void* ctx, int type) -{ - const CStateManager& mgr = *reinterpret_cast(ctx); - switch (type) - { - case 0: - { - const CActor& actor = *reinterpret_cast(drawable); - if (actor.xc8_drawnToken == mgr.x8dc_objectDrawToken) - break; - if (actor.xc6_nextDrawNode != kInvalidUniqueId) - mgr.RecursiveDrawTree(actor.xc6_nextDrawNode); - actor.Render(mgr); - const_cast(actor).xc8_drawnToken = mgr.x8dc_objectDrawToken; - break; - } - case 1: - reinterpret_cast(drawable)->Render(mgr.x8f0_shadowTex); - break; - case 2: - reinterpret_cast(drawable)->Render(); - break; - default: break; - } +void CStateManager::RendererDrawCallback(const void* drawable, const void* ctx, int type) { + const CStateManager& mgr = *reinterpret_cast(ctx); + switch (type) { + case 0: { + const CActor& actor = *reinterpret_cast(drawable); + if (actor.xc8_drawnToken == mgr.x8dc_objectDrawToken) + break; + if (actor.xc6_nextDrawNode != kInvalidUniqueId) + mgr.RecursiveDrawTree(actor.xc6_nextDrawNode); + actor.Render(mgr); + const_cast(actor).xc8_drawnToken = mgr.x8dc_objectDrawToken; + break; + } + case 1: + reinterpret_cast(drawable)->Render(mgr.x8f0_shadowTex); + break; + case 2: + reinterpret_cast(drawable)->Render(); + break; + default: + break; + } } -bool CStateManager::RenderLast(TUniqueId uid) -{ - if (x86c_stateManagerContainer->xf39c_renderLast.size() == 20) - return false; - x86c_stateManagerContainer->xf39c_renderLast.push_back(uid); - return true; +bool CStateManager::RenderLast(TUniqueId uid) { + if (x86c_stateManagerContainer->xf39c_renderLast.size() == 20) + return false; + x86c_stateManagerContainer->xf39c_renderLast.push_back(uid); + return true; } void CStateManager::AddDrawableActorPlane(const CActor& actor, const zeus::CPlane& plane, - const zeus::CAABox& aabb) const -{ - const_cast(actor).SetAddedToken(x8dc_objectDrawToken + 1); - g_Renderer->AddPlaneObject(static_cast(&actor), aabb, plane, 0); + const zeus::CAABox& aabb) const { + const_cast(actor).SetAddedToken(x8dc_objectDrawToken + 1); + g_Renderer->AddPlaneObject(static_cast(&actor), aabb, plane, 0); } -void CStateManager::AddDrawableActor(const CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const -{ - const_cast(actor).SetAddedToken(x8dc_objectDrawToken + 1); - g_Renderer->AddDrawable(static_cast(&actor), vec, aabb, 0, - IRenderer::EDrawableSorting::SortedCallback); +void CStateManager::AddDrawableActor(const CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const { + const_cast(actor).SetAddedToken(x8dc_objectDrawToken + 1); + g_Renderer->AddDrawable(static_cast(&actor), vec, aabb, 0, IRenderer::EDrawableSorting::SortedCallback); } -bool CStateManager::SpecialSkipCinematic() -{ - if (xf38_skipCineSpecialFunc == kInvalidUniqueId) - return false; +bool CStateManager::SpecialSkipCinematic() { + if (xf38_skipCineSpecialFunc == kInvalidUniqueId) + return false; - CScriptSpecialFunction* ent = static_cast(ObjectById(xf38_skipCineSpecialFunc)); - if (!ent || !ent->ShouldSkipCinematic(*this)) - return false; + CScriptSpecialFunction* ent = static_cast(ObjectById(xf38_skipCineSpecialFunc)); + if (!ent || !ent->ShouldSkipCinematic(*this)) + return false; - bool hadRandom = x900_activeRandom != nullptr; - SetActiveRandomToDefault(); - x870_cameraManager->SkipCinematic(*this); - ent->SkipCinematic(*this); - x900_activeRandom = hadRandom ? &x8fc_random : nullptr; + bool hadRandom = x900_activeRandom != nullptr; + SetActiveRandomToDefault(); + x870_cameraManager->SkipCinematic(*this); + ent->SkipCinematic(*this); + x900_activeRandom = hadRandom ? &x8fc_random : nullptr; - return true; + return true; } -TAreaId CStateManager::GetVisAreaId() const -{ - const CGameCamera* cam = static_cast(x870_cameraManager->GetCurrentCamera(*this)); - const CBallCamera* ballCam = x870_cameraManager->GetBallCamera(); - TAreaId curArea = x850_world->x68_curAreaId; - if (cam != ballCam) - return curArea; - - const zeus::CVector3f& camTranslation = ballCam->GetTranslation(); - zeus::CAABox camAABB(camTranslation, camTranslation); - camAABB.accumulateBounds(x84c_player->GetTranslation()); - rstl::reserved_vector nearList; - BuildNearList(nearList, camAABB, CMaterialFilter(EMaterialTypes::AIBlock, CMaterialList(), - CMaterialFilter::EFilterType::Include), nullptr); - for (TUniqueId id : nearList) - if (TCastToConstPtr dock = GetObjectById(id)) - if (dock->GetAreaId() == curArea && dock->HasPointCrossedDock(*this, camTranslation)) - return dock->GetCurrentConnectedAreaId(*this); - +TAreaId CStateManager::GetVisAreaId() const { + const CGameCamera* cam = static_cast(x870_cameraManager->GetCurrentCamera(*this)); + const CBallCamera* ballCam = x870_cameraManager->GetBallCamera(); + TAreaId curArea = x850_world->x68_curAreaId; + if (cam != ballCam) return curArea; + + const zeus::CVector3f& camTranslation = ballCam->GetTranslation(); + zeus::CAABox camAABB(camTranslation, camTranslation); + camAABB.accumulateBounds(x84c_player->GetTranslation()); + rstl::reserved_vector nearList; + BuildNearList(nearList, camAABB, + CMaterialFilter(EMaterialTypes::AIBlock, CMaterialList(), CMaterialFilter::EFilterType::Include), + nullptr); + for (TUniqueId id : nearList) + if (TCastToConstPtr dock = GetObjectById(id)) + if (dock->GetAreaId() == curArea && dock->HasPointCrossedDock(*this, camTranslation)) + return dock->GetCurrentConnectedAreaId(*this); + + return curArea; } -s32 CStateManager::GetWeaponIdCount(TUniqueId uid, EWeaponType type) -{ - return x878_weaponManager->GetNumActive(uid, type); +s32 CStateManager::GetWeaponIdCount(TUniqueId uid, EWeaponType type) { + return x878_weaponManager->GetNumActive(uid, type); } -void CStateManager::RemoveWeaponId(TUniqueId uid, EWeaponType type) -{ - x878_weaponManager->DecrCount(uid, type); +void CStateManager::RemoveWeaponId(TUniqueId uid, EWeaponType type) { x878_weaponManager->DecrCount(uid, type); } + +void CStateManager::AddWeaponId(TUniqueId uid, EWeaponType type) { x878_weaponManager->IncrCount(uid, type); } + +void CStateManager::UpdateEscapeSequenceTimer(float dt) { + if (xf0c_escapeTimer <= 0.f) + return; + xf0c_escapeTimer = std::max(FLT_EPSILON, xf0c_escapeTimer - dt); + if (xf0c_escapeTimer <= FLT_EPSILON) + x8b8_playerState->SetPlayerAlive(false); + + if (!g_EscapeShakeCountdownInit) { + g_EscapeShakeCountdown = 0.f; + g_EscapeShakeCountdownInit = true; + } + + g_EscapeShakeCountdown -= dt; + if (g_EscapeShakeCountdown < 0.f) { + float factor = 1.f - xf0c_escapeTimer / xf10_escapeTotalTime; + float factor2 = factor * factor; + CCameraShakeData shakeData(1.f, factor2 * 0.2f * x900_activeRandom->Range(0.5f, 1.f)); + x870_cameraManager->AddCameraShaker(shakeData, true); + x88c_rumbleManager->Rumble(*this, ERumbleFxId::EscapeSequenceShake, 0.75f, ERumblePriority::One); + g_EscapeShakeCountdown = -12.f * factor2 + 15.f; + } } -void CStateManager::AddWeaponId(TUniqueId uid, EWeaponType type) -{ - x878_weaponManager->IncrCount(uid, type); +void CStateManager::ResetEscapeSequenceTimer(float time) { + xf0c_escapeTimer = time; + xf10_escapeTotalTime = time; } -void CStateManager::UpdateEscapeSequenceTimer(float dt) -{ - if (xf0c_escapeTimer <= 0.f) - return; - xf0c_escapeTimer = std::max(FLT_EPSILON, xf0c_escapeTimer - dt); - if (xf0c_escapeTimer <= FLT_EPSILON) - x8b8_playerState->SetPlayerAlive(false); - - if (!g_EscapeShakeCountdownInit) - { - g_EscapeShakeCountdown = 0.f; - g_EscapeShakeCountdownInit = true; - } - - g_EscapeShakeCountdown -= dt; - if (g_EscapeShakeCountdown < 0.f) - { - float factor = 1.f - xf0c_escapeTimer / xf10_escapeTotalTime; - float factor2 = factor * factor; - CCameraShakeData shakeData(1.f, factor2 * 0.2f * x900_activeRandom->Range(0.5f, 1.f)); - x870_cameraManager->AddCameraShaker(shakeData, true); - x88c_rumbleManager->Rumble(*this, ERumbleFxId::EscapeSequenceShake, 0.75f, ERumblePriority::One); - g_EscapeShakeCountdown = -12.f * factor2 + 15.f; - } +void CStateManager::SetupParticleHook(const CActor& actor) const { + x884_actorModelParticles->SetupHook(actor.GetUniqueId()); } -void CStateManager::ResetEscapeSequenceTimer(float time) -{ - xf0c_escapeTimer = time; - xf10_escapeTotalTime = time; -} +void CStateManager::MurderScriptInstanceNames() { xb40_uniqueInstanceNames.clear(); } -void CStateManager::SetupParticleHook(const CActor& actor) const -{ - x884_actorModelParticles->SetupHook(actor.GetUniqueId()); -} - -void CStateManager::MurderScriptInstanceNames() -{ - xb40_uniqueInstanceNames.clear(); -} - -std::string CStateManager::HashInstanceName(CInputStream& in) -{ +std::string CStateManager::HashInstanceName(CInputStream& in) { #ifdef NDEBUG - while (in.readByte() != 0) {}; - return ""; + while (in.readByte() != 0) {}; + return ""; #else - return in.readString(); + return in.readString(); #endif } -void CStateManager::SetActorAreaId(CActor& actor, TAreaId aid) -{ - TAreaId actorAid = actor.GetAreaIdAlways(); - if (actorAid == aid) - return; +void CStateManager::SetActorAreaId(CActor& actor, TAreaId aid) { + TAreaId actorAid = actor.GetAreaIdAlways(); + if (actorAid == aid) + return; - if (actorAid != kInvalidAreaId) - { - CGameArea* area = x850_world->GetArea(actorAid); - if (area->IsPostConstructed()) - area->GetAreaObjects()->RemoveObject(actor.GetUniqueId()); - } + if (actorAid != kInvalidAreaId) { + CGameArea* area = x850_world->GetArea(actorAid); + if (area->IsPostConstructed()) + area->GetAreaObjects()->RemoveObject(actor.GetUniqueId()); + } - actor.x4_areaId = aid; + actor.x4_areaId = aid; - if (aid == kInvalidAreaId) - return; - CGameArea* area = x850_world->GetArea(aid); - if (!area->IsPostConstructed() || area->GetAreaObjects()->GetValidObjectById(actor.GetUniqueId())) - return; + if (aid == kInvalidAreaId) + return; + CGameArea* area = x850_world->GetArea(aid); + if (!area->IsPostConstructed() || area->GetAreaObjects()->GetValidObjectById(actor.GetUniqueId())) + return; - area->GetAreaObjects()->AddObject(actor); + area->GetAreaObjects()->AddObject(actor); } -void CStateManager::TouchSky() const -{ - x850_world->TouchSky(); +void CStateManager::TouchSky() const { x850_world->TouchSky(); } + +void CStateManager::TouchPlayerActor() { + if (xf6c_playerActorHead == kInvalidUniqueId) + return; + if (CEntity* ent = ObjectById(xf6c_playerActorHead)) + static_cast(ent)->TouchModels(*this); } -void CStateManager::TouchPlayerActor() -{ - if (xf6c_playerActorHead == kInvalidUniqueId) - return; - if (CEntity* ent = ObjectById(xf6c_playerActorHead)) - static_cast(ent)->TouchModels(*this); +void CStateManager::DrawSpaceWarp(const zeus::CVector3f& v, float strength) const { + CPlayerState::EPlayerVisor visor = x8b8_playerState->GetActiveVisor(*this); + if (visor == CPlayerState::EPlayerVisor::Scan || visor == CPlayerState::EPlayerVisor::Combat) { + zeus::CVector3f screenV = + TCastToConstPtr(x870_cameraManager->GetCurrentCamera(*this))->ConvertToScreenSpace(v); + g_Renderer->DrawSpaceWarp(screenV, strength); + } } -void CStateManager::DrawSpaceWarp(const zeus::CVector3f& v, float strength) const -{ - CPlayerState::EPlayerVisor visor = x8b8_playerState->GetActiveVisor(*this); - if (visor == CPlayerState::EPlayerVisor::Scan || visor == CPlayerState::EPlayerVisor::Combat) - { - zeus::CVector3f screenV = TCastToConstPtr(x870_cameraManager->GetCurrentCamera(*this))->ConvertToScreenSpace(v); - g_Renderer->DrawSpaceWarp(screenV, strength); - } +void CStateManager::DrawReflection(const zeus::CVector3f& reflectPoint) { + zeus::CAABox aabb = x84c_player->GetBoundingBox(); + zeus::CVector3f playerPos = aabb.center(); + zeus::CVector3f surfToPlayer = playerPos - reflectPoint; + surfToPlayer.z() = 0.f; + zeus::CVector3f viewPos = playerPos - surfToPlayer.normalized() * 3.5f; + zeus::CTransform look = zeus::lookAt(viewPos, playerPos, {0.f, 0.f, -1.f}); + + zeus::CTransform backupView = CGraphics::g_ViewMatrix; + CGraphics::SetViewPointMatrix(look); + CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState(); + CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); + g_Renderer->SetPerspective(cam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, cam->GetNearClipDistance(), + cam->GetFarClipDistance()); + + x84c_player->RenderReflectedPlayer(*this); + + CGraphics::SetViewPointMatrix(backupView); + CGraphics::SetProjectionState(backupProj); } -void CStateManager::DrawReflection(const zeus::CVector3f& reflectPoint) -{ - zeus::CAABox aabb = x84c_player->GetBoundingBox(); - zeus::CVector3f playerPos = aabb.center(); - zeus::CVector3f surfToPlayer = playerPos - reflectPoint; - surfToPlayer.z() = 0.f; - zeus::CVector3f viewPos = playerPos - surfToPlayer.normalized() * 3.5f; - zeus::CTransform look = zeus::lookAt(viewPos, playerPos, {0.f, 0.f, -1.f}); - - zeus::CTransform backupView = CGraphics::g_ViewMatrix; - CGraphics::SetViewPointMatrix(look); - CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState(); - CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); - g_Renderer->SetPerspective(cam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, - cam->GetNearClipDistance(), cam->GetFarClipDistance()); - - x84c_player->RenderReflectedPlayer(*this); - - CGraphics::SetViewPointMatrix(backupView); - CGraphics::SetProjectionState(backupProj); +void CStateManager::ReflectionDrawer(void* ctx, const zeus::CVector3f& vec) { + reinterpret_cast(ctx)->DrawReflection(vec); } -void CStateManager::ReflectionDrawer(void* ctx, const zeus::CVector3f& vec) -{ - reinterpret_cast(ctx)->DrawReflection(vec); +void CStateManager::CacheReflection() { g_Renderer->CacheReflection(ReflectionDrawer, this, true); } + +bool CStateManager::CanCreateProjectile(TUniqueId uid, EWeaponType type, int maxAllowed) const { + return x878_weaponManager->GetNumActive(uid, type) < maxAllowed; } -void CStateManager::CacheReflection() -{ - g_Renderer->CacheReflection(ReflectionDrawer, this, true); -} - -bool CStateManager::CanCreateProjectile(TUniqueId uid, EWeaponType type, int maxAllowed) const -{ - return x878_weaponManager->GetNumActive(uid, type) < maxAllowed; -} - -void CStateManager::BuildDynamicLightListForWorld() -{ - if (x8b8_playerState->GetActiveVisor(*this) == CPlayerState::EPlayerVisor::Thermal) - { - x8e0_dynamicLights.clear(); - return; - } - - if (GetLightObjectList().size() == 0) - return; - +void CStateManager::BuildDynamicLightListForWorld() { + if (x8b8_playerState->GetActiveVisor(*this) == CPlayerState::EPlayerVisor::Thermal) { x8e0_dynamicLights.clear(); - for (CEntity* ent : GetLightObjectList()) - { - CGameLight& light = static_cast(*ent); - if (light.GetActive()) - { - CLight l = light.GetLight(); - if (l.GetIntensity() > FLT_EPSILON && l.GetRadius() > FLT_EPSILON) - x8e0_dynamicLights.push_back(l); - } + return; + } + + if (GetLightObjectList().size() == 0) + return; + + x8e0_dynamicLights.clear(); + for (CEntity* ent : GetLightObjectList()) { + CGameLight& light = static_cast(*ent); + if (light.GetActive()) { + CLight l = light.GetLight(); + if (l.GetIntensity() > FLT_EPSILON && l.GetRadius() > FLT_EPSILON) + x8e0_dynamicLights.push_back(l); } + } } void CStateManager::DrawDebugStuff() const {} -void CStateManager::RenderCamerasAndAreaLights() const -{ - x870_cameraManager->RenderCameras(*this); - for (const CCameraFilterPassPoly& filter : xb84_camFilterPasses) - filter.Draw(); +void CStateManager::RenderCamerasAndAreaLights() const { + x870_cameraManager->RenderCameras(*this); + for (const CCameraFilterPassPoly& filter : xb84_camFilterPasses) + filter.Draw(); } -void CStateManager::DrawE3DeathEffect() const -{ - CPlayer& player = *x84c_player; - if (player.x9f4_deathTime > 0.f) - { - if (player.x2f8_morphBallState != CPlayer::EPlayerMorphBallState::Unmorphed) - { - float blurAmt = zeus::clamp(0.f, (player.x9f4_deathTime - 1.f) / (6.f - 1.f), 1.f); - if (blurAmt > 0.f) - { - CCameraBlurPass blur; - blur.SetBlur(EBlurType::HiBlur, 7.f * blurAmt, 0.f); - blur.Draw(); - } - } - float whiteAmt = zeus::clamp(0.f, 1.f - player.x9f4_deathTime / (0.05f * 6.f), 1.f); - zeus::CColor color = zeus::CColor::skWhite; - color.a() = whiteAmt; - const_cast(m_deathWhiteout).draw(color); +void CStateManager::DrawE3DeathEffect() const { + CPlayer& player = *x84c_player; + if (player.x9f4_deathTime > 0.f) { + if (player.x2f8_morphBallState != CPlayer::EPlayerMorphBallState::Unmorphed) { + float blurAmt = zeus::clamp(0.f, (player.x9f4_deathTime - 1.f) / (6.f - 1.f), 1.f); + if (blurAmt > 0.f) { + CCameraBlurPass blur; + blur.SetBlur(EBlurType::HiBlur, 7.f * blurAmt, 0.f); + blur.Draw(); + } } + float whiteAmt = zeus::clamp(0.f, 1.f - player.x9f4_deathTime / (0.05f * 6.f), 1.f); + zeus::CColor color = zeus::CColor::skWhite; + color.a() = whiteAmt; + const_cast(m_deathWhiteout).draw(color); + } } -void CStateManager::DrawAdditionalFilters() const -{ - if (xf0c_escapeTimer < 1.f && xf0c_escapeTimer > 0.f && - !x870_cameraManager->IsInCinematicCamera()) - { - zeus::CColor color = zeus::CColor::skWhite; - color.a() = 1.f - xf0c_escapeTimer; - const_cast(m_escapeWhiteout).draw(color); - } +void CStateManager::DrawAdditionalFilters() const { + if (xf0c_escapeTimer < 1.f && xf0c_escapeTimer > 0.f && !x870_cameraManager->IsInCinematicCamera()) { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = 1.f - xf0c_escapeTimer; + const_cast(m_escapeWhiteout).draw(color); + } } -zeus::CFrustum CStateManager::SetupDrawFrustum(const SViewport& vp) const -{ - zeus::CFrustum ret; - const CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); - zeus::CTransform camXf = x870_cameraManager->GetCurrentCameraTransform(*this); - int vpWidth = xf2c_viewportScale.x() * vp.x8_width; - int vpHeight = xf2c_viewportScale.y() * vp.xc_height; - int vpLeft = (vp.x8_width - vpWidth) / 2 + vp.x0_left; - int vpTop = (vp.xc_height - vpHeight) / 2 + vp.x4_top; - g_Renderer->SetViewport(vpLeft, vpTop, vpWidth, vpHeight); - float fov = std::atan(std::tan(zeus::degToRad(cam->GetFov()) * 0.5f) * xf2c_viewportScale.y()) * 2.f; - float width = xf2c_viewportScale.x() * vp.x8_width; - float height = xf2c_viewportScale.y() * vp.xc_height; - zeus::CProjection proj; - proj.setPersp(zeus::SProjPersp{fov, width / height, cam->GetNearClipDistance(), cam->GetFarClipDistance()}); - ret.updatePlanes(camXf, proj); - return ret; +zeus::CFrustum CStateManager::SetupDrawFrustum(const SViewport& vp) const { + zeus::CFrustum ret; + const CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); + zeus::CTransform camXf = x870_cameraManager->GetCurrentCameraTransform(*this); + int vpWidth = xf2c_viewportScale.x() * vp.x8_width; + int vpHeight = xf2c_viewportScale.y() * vp.xc_height; + int vpLeft = (vp.x8_width - vpWidth) / 2 + vp.x0_left; + int vpTop = (vp.xc_height - vpHeight) / 2 + vp.x4_top; + g_Renderer->SetViewport(vpLeft, vpTop, vpWidth, vpHeight); + float fov = std::atan(std::tan(zeus::degToRad(cam->GetFov()) * 0.5f) * xf2c_viewportScale.y()) * 2.f; + float width = xf2c_viewportScale.x() * vp.x8_width; + float height = xf2c_viewportScale.y() * vp.xc_height; + zeus::CProjection proj; + proj.setPersp(zeus::SProjPersp{fov, width / height, cam->GetNearClipDistance(), cam->GetFarClipDistance()}); + ret.updatePlanes(camXf, proj); + return ret; } -zeus::CFrustum CStateManager::SetupViewForDraw(const SViewport& vp) const -{ - const CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); - zeus::CTransform camXf = x870_cameraManager->GetCurrentCameraTransform(*this); - g_Renderer->SetWorldViewpoint(camXf); - CBooModel::SetNewPlayerPositionAndTime(x84c_player->GetTranslation()); - int vpWidth = xf2c_viewportScale.x() * vp.x8_width; - int vpHeight = xf2c_viewportScale.y() * vp.xc_height; - int vpLeft = (vp.x8_width - vpWidth) / 2 + vp.x0_left; - int vpTop = (vp.xc_height - vpHeight) / 2 + vp.x4_top; - g_Renderer->SetViewport(vpLeft, vpTop, vpWidth, vpHeight); - CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); - float fov = std::atan(std::tan(zeus::degToRad(cam->GetFov()) * 0.5f) * xf2c_viewportScale.y()) * 2.f; - float width = xf2c_viewportScale.x() * vp.x8_width; - float height = xf2c_viewportScale.y() * vp.xc_height; - g_Renderer->SetPerspective(zeus::radToDeg(fov), width, height, - cam->GetNearClipDistance(), cam->GetFarClipDistance()); - zeus::CFrustum frustum; - zeus::CProjection proj; - proj.setPersp(zeus::SProjPersp{fov, width / height, cam->GetNearClipDistance(), cam->GetFarClipDistance()}); - frustum.updatePlanes(camXf, proj); - g_Renderer->SetClippingPlanes(frustum); - //g_Renderer->PrimColor(zeus::CColor::skWhite); - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - x87c_fluidPlaneManager->StartFrame(false); - g_Renderer->SetDebugOption(IRenderer::EDebugOption::One, 1); - return frustum; +zeus::CFrustum CStateManager::SetupViewForDraw(const SViewport& vp) const { + const CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); + zeus::CTransform camXf = x870_cameraManager->GetCurrentCameraTransform(*this); + g_Renderer->SetWorldViewpoint(camXf); + CBooModel::SetNewPlayerPositionAndTime(x84c_player->GetTranslation()); + int vpWidth = xf2c_viewportScale.x() * vp.x8_width; + int vpHeight = xf2c_viewportScale.y() * vp.xc_height; + int vpLeft = (vp.x8_width - vpWidth) / 2 + vp.x0_left; + int vpTop = (vp.xc_height - vpHeight) / 2 + vp.x4_top; + g_Renderer->SetViewport(vpLeft, vpTop, vpWidth, vpHeight); + CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); + float fov = std::atan(std::tan(zeus::degToRad(cam->GetFov()) * 0.5f) * xf2c_viewportScale.y()) * 2.f; + float width = xf2c_viewportScale.x() * vp.x8_width; + float height = xf2c_viewportScale.y() * vp.xc_height; + g_Renderer->SetPerspective(zeus::radToDeg(fov), width, height, cam->GetNearClipDistance(), cam->GetFarClipDistance()); + zeus::CFrustum frustum; + zeus::CProjection proj; + proj.setPersp(zeus::SProjPersp{fov, width / height, cam->GetNearClipDistance(), cam->GetFarClipDistance()}); + frustum.updatePlanes(camXf, proj); + g_Renderer->SetClippingPlanes(frustum); + // g_Renderer->PrimColor(zeus::CColor::skWhite); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + x87c_fluidPlaneManager->StartFrame(false); + g_Renderer->SetDebugOption(IRenderer::EDebugOption::One, 1); + return frustum; } void CStateManager::ResetViewAfterDraw(const SViewport& backupViewport, - const zeus::CTransform& backupViewMatrix) const -{ - g_Renderer->SetViewport(backupViewport.x0_left, backupViewport.x4_top, - backupViewport.x8_width, backupViewport.xc_height); - const CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); + const zeus::CTransform& backupViewMatrix) const { + g_Renderer->SetViewport(backupViewport.x0_left, backupViewport.x4_top, backupViewport.x8_width, + backupViewport.xc_height); + const CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); - zeus::CFrustum frustum; - frustum.updatePlanes(backupViewMatrix, zeus::SProjPersp(zeus::degToRad(cam->GetFov()), - g_Viewport.x8_width / float(g_Viewport.xc_height), - cam->GetNearClipDistance(), - cam->GetFarClipDistance())); - g_Renderer->SetClippingPlanes(frustum); + zeus::CFrustum frustum; + frustum.updatePlanes(backupViewMatrix, zeus::SProjPersp(zeus::degToRad(cam->GetFov()), + g_Viewport.x8_width / float(g_Viewport.xc_height), + cam->GetNearClipDistance(), cam->GetFarClipDistance())); + g_Renderer->SetClippingPlanes(frustum); - g_Renderer->SetPerspective(cam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, - cam->GetNearClipDistance(), cam->GetFarClipDistance()); + g_Renderer->SetPerspective(cam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, cam->GetNearClipDistance(), + cam->GetFarClipDistance()); } -void CStateManager::DrawWorld() const -{ - CTimeProvider timeProvider(xf14_curTimeMod900); - SViewport backupViewport = g_Viewport; - zeus::CFrustum frustum = SetupViewForDraw(g_Viewport); - zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix; +void CStateManager::DrawWorld() const { + CTimeProvider timeProvider(xf14_curTimeMod900); + SViewport backupViewport = g_Viewport; + zeus::CFrustum frustum = SetupViewForDraw(g_Viewport); + zeus::CTransform backupViewMatrix = CGraphics::g_ViewMatrix; - /* Area camera is in (not necessarily player) */ - TAreaId visAreaId = GetVisAreaId(); + /* Area camera is in (not necessarily player) */ + TAreaId visAreaId = GetVisAreaId(); - x850_world->TouchSky(); + x850_world->TouchSky(); - int areaCount = 0; - const CGameArea* areaArr[10]; - for (const CGameArea& area : *x850_world) - { - if (areaCount == 10) - break; - CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; - if (area.IsPostConstructed()) - occState = area.GetOcclusionState(); - if (occState == CGameArea::EOcclusionState::Visible) - areaArr[areaCount++] = &area; + int areaCount = 0; + const CGameArea* areaArr[10]; + for (const CGameArea& area : *x850_world) { + if (areaCount == 10) + break; + CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; + if (area.IsPostConstructed()) + occState = area.GetOcclusionState(); + if (occState == CGameArea::EOcclusionState::Visible) + areaArr[areaCount++] = &area; + } + + std::sort(std::begin(areaArr), std::begin(areaArr) + areaCount, + [visAreaId](const CGameArea* a, const CGameArea* b) -> bool { + if (a->x4_selfIdx == b->x4_selfIdx) + return false; + if (visAreaId == a->x4_selfIdx) + return false; + if (visAreaId == b->x4_selfIdx) + return true; + return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) > + CGraphics::g_ViewPoint.dot(b->GetAABB().center()); + }); + + int pvsCount = 0; + CPVSVisSet pvsArr[10]; + for (const CGameArea** area = areaArr; area != areaArr + areaCount; ++area) { + const CGameArea* areaPtr = *area; + CPVSVisSet& pvsSet = pvsArr[pvsCount++]; + pvsSet.Reset(EPVSVisSetState::OutOfBounds); + GetVisSetForArea(areaPtr->x4_selfIdx, visAreaId, pvsSet); + } + + int mask; + int targetMask; + CPlayerState::EPlayerVisor visor = x8b8_playerState->GetActiveVisor(*this); + bool thermal = visor == CPlayerState::EPlayerVisor::Thermal; + if (thermal) { + const_cast(*this).xf34_thermalFlag = EThermalDrawFlag::Cold; + mask = 0x34; + targetMask = 0; + } else { + const_cast(*this).xf34_thermalFlag = EThermalDrawFlag::Bypass; + mask = 1 << (visor == CPlayerState::EPlayerVisor::XRay ? 3 : 1); + targetMask = 0; + } + + g_Renderer->SetThermal(thermal, g_tweakGui->GetThermalVisorLevel(), g_tweakGui->GetThermalVisorColor()); + g_Renderer->SetThermalColdScale(xf28_thermColdScale2 + xf24_thermColdScale1); + + for (int i = areaCount - 1; i >= 0; --i) { + const CGameArea& area = *areaArr[i]; + SetupFogForArea(area); + g_Renderer->EnablePVS(pvsArr[i], area.x4_selfIdx); + g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel); + g_Renderer->UpdateAreaUniforms(area.x4_selfIdx); + g_Renderer->DrawUnsortedGeometry(area.x4_selfIdx, mask, targetMask); + } + + if (!SetupFogForDraw()) + g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::CColor::skBlack); + + x850_world->DrawSky(zeus::CTransform::Translate(CGraphics::g_ViewPoint)); + + if (areaCount) + SetupFogForArea(*areaArr[areaCount - 1]); + + for (TUniqueId id : x86c_stateManagerContainer->xf370_) + if (const CActor* ent = static_cast(GetObjectById(id))) + if (!thermal || ent->xe6_27_thermalVisorFlags & 0x1) + ent->Render(*this); + + bool morphingPlayerVisible = false; + int thermalActorCount = 0; + CActor* thermalActorArr[1024]; + for (int i = 0; i < areaCount; ++i) { + const CGameArea& area = *areaArr[i]; + CPVSVisSet& pvs = pvsArr[i]; + bool isVisArea = area.x4_selfIdx == visAreaId; + SetupFogForArea(area); + g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel); + for (CEntity* ent : *area.GetAreaObjects()) { + if (TCastToPtr actor = ent) { + if (!actor->IsDrawEnabled()) + continue; + TUniqueId actorId = actor->GetUniqueId(); + if (!thermal && area.LookupPVSUniqueID(actorId) == actorId) + if (pvs.GetVisible(area.LookupPVSID(actorId)) == EPVSVisSetState::EndOfTree) + continue; + if (x84c_player.get() == actor.GetPtr()) { + if (thermal) + continue; + switch (x84c_player->GetMorphballTransitionState()) { + case CPlayer::EPlayerMorphBallState::Unmorphed: + case CPlayer::EPlayerMorphBallState::Morphed: + x84c_player->AddToRenderer(frustum, *this); + continue; + default: + morphingPlayerVisible = true; + continue; + } + } + if (!thermal || actor->xe6_27_thermalVisorFlags & 0x1) + actor->AddToRenderer(frustum, *this); + if (thermal && actor->xe6_27_thermalVisorFlags & 0x2) + thermalActorArr[thermalActorCount++] = actor.GetPtr(); + } } - std::sort(std::begin(areaArr), std::begin(areaArr) + areaCount, - [visAreaId](const CGameArea* a, const CGameArea* b) -> bool - { - if (a->x4_selfIdx == b->x4_selfIdx) - return false; - if (visAreaId == a->x4_selfIdx) - return false; - if (visAreaId == b->x4_selfIdx) - return true; - return CGraphics::g_ViewPoint.dot(a->GetAABB().center()) > - CGraphics::g_ViewPoint.dot(b->GetAABB().center()); - }); - - int pvsCount = 0; - CPVSVisSet pvsArr[10]; - for (const CGameArea** area = areaArr; - area != areaArr + areaCount; - ++area) - { - const CGameArea* areaPtr = *area; - CPVSVisSet& pvsSet = pvsArr[pvsCount++]; - pvsSet.Reset(EPVSVisSetState::OutOfBounds); - GetVisSetForArea(areaPtr->x4_selfIdx, visAreaId, pvsSet); + if (isVisArea && !thermal) { + CDecalManager::AddToRenderer(frustum, *this); + x884_actorModelParticles->AddStragglersToRenderer(*this); } - int mask; - int targetMask; - CPlayerState::EPlayerVisor visor = x8b8_playerState->GetActiveVisor(*this); - bool thermal = visor == CPlayerState::EPlayerVisor::Thermal; - if (thermal) - { - const_cast(*this).xf34_thermalFlag = EThermalDrawFlag::Cold; - mask = 0x34; - targetMask = 0; + ++const_cast(*this).x8dc_objectDrawToken; + + x84c_player->GetMorphBall()->DrawBallShadow(*this); + + if (xf7c_projectedShadow) + xf7c_projectedShadow->Render(*this); + + g_Renderer->EnablePVS(pvs, area.x4_selfIdx); + g_Renderer->DrawSortedGeometry(area.x4_selfIdx, mask, targetMask); + } + + x880_envFxManager->Render(*this); + + if (morphingPlayerVisible) + x84c_player->Render(*this); + + g_Renderer->PostRenderFogs(); + + if (thermal) { + if (x86c_stateManagerContainer->xf39c_renderLast.size()) { + CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); + for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) + if (const CActor* actor = static_cast(GetObjectById(id))) + if (actor->xe6_27_thermalVisorFlags & 0x1) + actor->Render(*this); + CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); } - else - { - const_cast(*this).xf34_thermalFlag = EThermalDrawFlag::Bypass; - mask = 1 << (visor == CPlayerState::EPlayerVisor::XRay ? 3 : 1); - targetMask = 0; - } - - g_Renderer->SetThermal(thermal, g_tweakGui->GetThermalVisorLevel(), g_tweakGui->GetThermalVisorColor()); - g_Renderer->SetThermalColdScale(xf28_thermColdScale2 + xf24_thermColdScale1); - - for (int i=areaCount-1 ; i>=0 ; --i) - { - const CGameArea& area = *areaArr[i]; - SetupFogForArea(area); - g_Renderer->EnablePVS(pvsArr[i], area.x4_selfIdx); - g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel); - g_Renderer->UpdateAreaUniforms(area.x4_selfIdx); - g_Renderer->DrawUnsortedGeometry(area.x4_selfIdx, mask, targetMask); - } - - if (!SetupFogForDraw()) - g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::CColor::skBlack); - - x850_world->DrawSky(zeus::CTransform::Translate(CGraphics::g_ViewPoint)); - - if (areaCount) - SetupFogForArea(*areaArr[areaCount-1]); + g_Renderer->DoThermalBlendCold(); + const_cast(*this).xf34_thermalFlag = EThermalDrawFlag::Hot; for (TUniqueId id : x86c_stateManagerContainer->xf370_) - if (const CActor* ent = static_cast(GetObjectById(id))) - if (!thermal || ent->xe6_27_thermalVisorFlags & 0x1) - ent->Render(*this); + if (const CActor* actor = static_cast(GetObjectById(id))) + if (actor->xe6_27_thermalVisorFlags & 0x2) + actor->Render(*this); - bool morphingPlayerVisible = false; - int thermalActorCount = 0; - CActor* thermalActorArr[1024]; - for (int i=0 ; iSetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel); - for (CEntity* ent : *area.GetAreaObjects()) - { - if (TCastToPtr actor = ent) - { - if (!actor->IsDrawEnabled()) - continue; - TUniqueId actorId = actor->GetUniqueId(); - if (!thermal && area.LookupPVSUniqueID(actorId) == actorId) - if (pvs.GetVisible(area.LookupPVSID(actorId)) == EPVSVisSetState::EndOfTree) - continue; - if (x84c_player.get() == actor.GetPtr()) - { - if (thermal) - continue; - switch (x84c_player->GetMorphballTransitionState()) - { - case CPlayer::EPlayerMorphBallState::Unmorphed: - case CPlayer::EPlayerMorphBallState::Morphed: - x84c_player->AddToRenderer(frustum, *this); - continue; - default: - morphingPlayerVisible = true; - continue; - } - } - if (!thermal || actor->xe6_27_thermalVisorFlags & 0x1) - actor->AddToRenderer(frustum, *this); - if (thermal && actor->xe6_27_thermalVisorFlags & 0x2) - thermalActorArr[thermalActorCount++] = actor.GetPtr(); - } - } + for (int i = areaCount - 1; i >= 0; --i) { + const CGameArea& area = *areaArr[i]; + CPVSVisSet& pvs = pvsArr[i]; - if (isVisArea && !thermal) - { - CDecalManager::AddToRenderer(frustum, *this); - x884_actorModelParticles->AddStragglersToRenderer(*this); - } - - ++const_cast(*this).x8dc_objectDrawToken; - - x84c_player->GetMorphBall()->DrawBallShadow(*this); - - if (xf7c_projectedShadow) - xf7c_projectedShadow->Render(*this); - - g_Renderer->EnablePVS(pvs, area.x4_selfIdx); - g_Renderer->DrawSortedGeometry(area.x4_selfIdx, mask, targetMask); + g_Renderer->EnablePVS(pvs, area.x4_selfIdx); + g_Renderer->DrawUnsortedGeometry(area.x4_selfIdx, mask, 0x20); + g_Renderer->DrawAreaGeometry(area.x4_selfIdx, mask, 0x10); } - x880_envFxManager->Render(*this); + ++const_cast(*this).x8dc_objectDrawToken; - if (morphingPlayerVisible) - x84c_player->Render(*this); + for (int i = 0; i < areaCount; ++i) { + const CGameArea& area = *areaArr[i]; + CPVSVisSet& pvs = pvsArr[i]; + + for (int j = 0; j < thermalActorCount; ++j) { + CActor* actor = thermalActorArr[j]; + if (actor->GetAreaIdAlways() != area.x4_selfIdx) + if (actor->GetAreaIdAlways() != kInvalidAreaId || area.x4_selfIdx != visAreaId) + continue; + actor->AddToRenderer(frustum, *this); + } + + if (areaCount - 1 == i) { + x884_actorModelParticles->AddStragglersToRenderer(*this); + CDecalManager::AddToRenderer(frustum, *this); + if (x84c_player) + x84c_player->AddToRenderer(frustum, *this); + } + + ++const_cast(*this).x8dc_objectDrawToken; + + g_Renderer->EnablePVS(pvs, area.x4_selfIdx); + g_Renderer->DrawSortedGeometry(area.x4_selfIdx, mask, 0x10); + } g_Renderer->PostRenderFogs(); + } - if (thermal) - { - if (x86c_stateManagerContainer->xf39c_renderLast.size()) - { - CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); - for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) - if (const CActor* actor = static_cast(GetObjectById(id))) - if (actor->xe6_27_thermalVisorFlags & 0x1) - actor->Render(*this); - CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); - } - g_Renderer->DoThermalBlendCold(); - const_cast(*this).xf34_thermalFlag = EThermalDrawFlag::Hot; + x87c_fluidPlaneManager->EndFrame(); - for (TUniqueId id : x86c_stateManagerContainer->xf370_) - if (const CActor* actor = static_cast(GetObjectById(id))) - if (actor->xe6_27_thermalVisorFlags & 0x2) - actor->Render(*this); - - for (int i=areaCount-1 ; i>=0 ; --i) - { - const CGameArea& area = *areaArr[i]; - CPVSVisSet& pvs = pvsArr[i]; - - g_Renderer->EnablePVS(pvs, area.x4_selfIdx); - g_Renderer->DrawUnsortedGeometry(area.x4_selfIdx, mask, 0x20); - g_Renderer->DrawAreaGeometry(area.x4_selfIdx, mask, 0x10); - } - - ++const_cast(*this).x8dc_objectDrawToken; - - for (int i=0 ; iGetAreaIdAlways() != area.x4_selfIdx) - if (actor->GetAreaIdAlways() != kInvalidAreaId || area.x4_selfIdx != visAreaId) - continue; - actor->AddToRenderer(frustum, *this); - } - - if (areaCount - 1 == i) - { - x884_actorModelParticles->AddStragglersToRenderer(*this); - CDecalManager::AddToRenderer(frustum, *this); - if (x84c_player) - x84c_player->AddToRenderer(frustum, *this); - } - - ++const_cast(*this).x8dc_objectDrawToken; - - g_Renderer->EnablePVS(pvs, area.x4_selfIdx); - g_Renderer->DrawSortedGeometry(area.x4_selfIdx, mask, 0x10); - } - - g_Renderer->PostRenderFogs(); - } - - x87c_fluidPlaneManager->EndFrame(); - - g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::CColor::skBlack); + g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::CColor::skBlack); #if 0 if (false) CacheReflection(); #endif - if (x84c_player) - x84c_player->RenderGun(*this, x870_cameraManager->GetGlobalCameraTranslation(*this)); + if (x84c_player) + x84c_player->RenderGun(*this, x870_cameraManager->GetGlobalCameraTranslation(*this)); - if (x86c_stateManagerContainer->xf39c_renderLast.size()) - { - CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); - for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) - if (const CActor* actor = static_cast(GetObjectById(id))) - if (!thermal || actor->xe6_27_thermalVisorFlags & 0x2) - actor->Render(*this); - CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); - } + if (x86c_stateManagerContainer->xf39c_renderLast.size()) { + CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); + for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) + if (const CActor* actor = static_cast(GetObjectById(id))) + if (!thermal || actor->xe6_27_thermalVisorFlags & 0x2) + actor->Render(*this); + CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); + } - if (thermal) - { - g_Renderer->DoThermalBlendHot(); - g_Renderer->SetThermal(false, 0.f, zeus::CColor::skBlack); - const_cast(*this).xf34_thermalFlag = EThermalDrawFlag::Bypass; - } + if (thermal) { + g_Renderer->DoThermalBlendHot(); + g_Renderer->SetThermal(false, 0.f, zeus::CColor::skBlack); + const_cast(*this).xf34_thermalFlag = EThermalDrawFlag::Bypass; + } - DrawDebugStuff(); - RenderCamerasAndAreaLights(); - ResetViewAfterDraw(backupViewport, backupViewMatrix); - DrawE3DeathEffect(); - DrawAdditionalFilters(); + DrawDebugStuff(); + RenderCamerasAndAreaLights(); + ResetViewAfterDraw(backupViewport, backupViewMatrix); + DrawE3DeathEffect(); + DrawAdditionalFilters(); } -void CStateManager::SetupFogForArea(TAreaId area) const -{ - if (area == kInvalidAreaId) - area = x8cc_nextAreaId; - const CGameArea* areaObj = x850_world->GetAreaAlways(area); - if (areaObj->IsPostConstructed()) - SetupFogForArea(*areaObj); +void CStateManager::SetupFogForArea(TAreaId area) const { + if (area == kInvalidAreaId) + area = x8cc_nextAreaId; + const CGameArea* areaObj = x850_world->GetAreaAlways(area); + if (areaObj->IsPostConstructed()) + SetupFogForArea(*areaObj); } -void CStateManager::SetupFogForArea(const CGameArea& area) const -{ - if (SetupFogForDraw()) - return; +void CStateManager::SetupFogForArea(const CGameArea& area) const { + if (SetupFogForDraw()) + return; - if (x8b8_playerState->GetActiveVisor(*this) == CPlayerState::EPlayerVisor::XRay) - { - float fogDist = area.GetXRayFogDistance(); - float farz = g_tweakGui->GetXRayFogNearZ() * (1.f - fogDist) + - g_tweakGui->GetXRayFogFarZ() * fogDist; - g_Renderer->SetWorldFog(ERglFogMode(g_tweakGui->GetXRayFogMode()), - g_tweakGui->GetXRayFogNearZ(), - farz, g_tweakGui->GetXRayFogColor()); - } - else - { - area.GetAreaFog()->SetCurrent(); - } + if (x8b8_playerState->GetActiveVisor(*this) == CPlayerState::EPlayerVisor::XRay) { + float fogDist = area.GetXRayFogDistance(); + float farz = g_tweakGui->GetXRayFogNearZ() * (1.f - fogDist) + g_tweakGui->GetXRayFogFarZ() * fogDist; + g_Renderer->SetWorldFog(ERglFogMode(g_tweakGui->GetXRayFogMode()), g_tweakGui->GetXRayFogNearZ(), farz, + g_tweakGui->GetXRayFogColor()); + } else { + area.GetAreaFog()->SetCurrent(); + } } -bool CStateManager::SetupFogForDraw() const -{ - switch (x8b8_playerState->GetActiveVisor(*this)) - { - case CPlayerState::EPlayerVisor::Thermal: - g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::CColor::skBlack); - return true; - case CPlayerState::EPlayerVisor::XRay: - default: - return false; - case CPlayerState::EPlayerVisor::Combat: - case CPlayerState::EPlayerVisor::Scan: - auto& fog = x870_cameraManager->Fog(); - if (fog.IsFogDisabled()) - return false; - fog.SetCurrent(); - return true; - } -} - -void CStateManager::PreRender() -{ - if (xf94_24_readyToRender) - { - zeus::CFrustum frustum = SetupDrawFrustum(g_Viewport); - x86c_stateManagerContainer->xf370_.clear(); - x86c_stateManagerContainer->xf39c_renderLast.clear(); - xf7c_projectedShadow = nullptr; - x850_world->PreRender(); - BuildDynamicLightListForWorld(); - for (const CGameArea& area : *x850_world) - { - CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; - if (area.IsPostConstructed()) - occState = area.GetOcclusionState(); - if (occState == CGameArea::EOcclusionState::Visible) - { - for (CEntity* ent : *area.GetPostConstructed()->x10c0_areaObjs) - { - if (TCastToPtr act = ent) - { - if (act->IsDrawEnabled()) - { - act->CalculateRenderBounds(); - act->PreRender(*this, frustum); - } - } - } - } - } - - CacheReflection(); - g_Renderer->PrepareDynamicLights(x8e0_dynamicLights); - } -} - -void CStateManager::GetCharacterRenderMaskAndTarget(bool thawed, int& mask, int& target) const -{ - switch (x8b8_playerState->GetActiveVisor(*this)) - { - case CPlayerState::EPlayerVisor::Combat: - case CPlayerState::EPlayerVisor::Scan: - mask = 0x1000; - target = 0x0; - break; - case CPlayerState::EPlayerVisor::XRay: - mask = 0x800; - target = 0x0; - break; - case CPlayerState::EPlayerVisor::Thermal: - if (thawed) - { - if (xf34_thermalFlag == EThermalDrawFlag::Hot) - { - mask = 0x600; - target = 0x0; - } - else - { - mask = 0x600; - target = 0x200; - } - } - else - { - if (xf34_thermalFlag == EThermalDrawFlag::Cold) - { - mask = 0x500; - target = 0x0; - } - else - { - mask = 0x500; - target = 0x100; - } - } - break; - default: - mask = 0x0; - target = 0x0; - break; - } -} - -bool CStateManager::GetVisSetForArea(TAreaId a, TAreaId b, CPVSVisSet& setOut) const -{ - if (b == kInvalidAreaId) - return false; - - zeus::CVector3f viewPoint = CGraphics::g_ViewMatrix.origin; - zeus::CVector3f closestDockPoint = viewPoint; - bool hasClosestDock = false; - if (a != b) - { - CGameArea& area = *x850_world->GetGameAreas()[b]; - if (area.IsPostConstructed()) - { - for (const CGameArea::Dock& dock : area.GetDocks()) - { - for (int i=0 ; i= - (closestDockPoint - viewPoint).magSquared()) - continue; - closestDockPoint = dockCenter; - hasClosestDock = true; - } - } - } - } - } - else - { - hasClosestDock = true; - } - - if (hasClosestDock) - { - if (CPVSAreaSet* pvs = x850_world->GetGameAreas()[a]->GetPostConstructed()->xa0_pvs.get()) - { - const CPVSVisOctree& octree = pvs->GetVisOctree(); - zeus::CVector3f closestDockLocal = - x850_world->GetGameAreas()[a]->GetInverseTransform() * closestDockPoint; - CPVSVisSet set; - set.SetTestPoint(octree, closestDockLocal); - - if (set.GetState() == EPVSVisSetState::NodeFound) - { - setOut = set; - return true; - } - } - } - +bool CStateManager::SetupFogForDraw() const { + switch (x8b8_playerState->GetActiveVisor(*this)) { + case CPlayerState::EPlayerVisor::Thermal: + g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::CColor::skBlack); + return true; + case CPlayerState::EPlayerVisor::XRay: + default: return false; + case CPlayerState::EPlayerVisor::Combat: + case CPlayerState::EPlayerVisor::Scan: + auto& fog = x870_cameraManager->Fog(); + if (fog.IsFogDisabled()) + return false; + fog.SetCurrent(); + return true; + } } -void CStateManager::RecursiveDrawTree(TUniqueId node) const -{ - if (TCastToConstPtr actor = GetObjectById(node)) - { - if (x8dc_objectDrawToken != actor->xc8_drawnToken) - { - if (actor->xc6_nextDrawNode != kInvalidUniqueId) - RecursiveDrawTree(actor->xc6_nextDrawNode); - if (x8dc_objectDrawToken == actor->xcc_addedToken) - actor->Render(*this); - const_cast(actor.GetPtr())->xc8_drawnToken = x8dc_objectDrawToken; +void CStateManager::PreRender() { + if (xf94_24_readyToRender) { + zeus::CFrustum frustum = SetupDrawFrustum(g_Viewport); + x86c_stateManagerContainer->xf370_.clear(); + x86c_stateManagerContainer->xf39c_renderLast.clear(); + xf7c_projectedShadow = nullptr; + x850_world->PreRender(); + BuildDynamicLightListForWorld(); + for (const CGameArea& area : *x850_world) { + CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; + if (area.IsPostConstructed()) + occState = area.GetOcclusionState(); + if (occState == CGameArea::EOcclusionState::Visible) { + for (CEntity* ent : *area.GetPostConstructed()->x10c0_areaObjs) { + if (TCastToPtr act = ent) { + if (act->IsDrawEnabled()) { + act->CalculateRenderBounds(); + act->PreRender(*this, frustum); + } + } } + } } + + CacheReflection(); + g_Renderer->PrepareDynamicLights(x8e0_dynamicLights); + } } -void CStateManager::SendScriptMsg(CEntity* dest, TUniqueId src, EScriptObjectMessage msg) -{ - if (dest && !dest->x30_26_scriptingBlocked) - { - if (sm_logScripting && sm_logScripting->toBoolean()) - LogModule.report(logvisor::Info, "Sending '%s' to '%s' id= 0x%.4X", - ScriptObjectMessageToStr(msg).data(), dest->GetName().data(), dest->GetUniqueId().id); - dest->AcceptScriptMsg(msg, src, *this); +void CStateManager::GetCharacterRenderMaskAndTarget(bool thawed, int& mask, int& target) const { + switch (x8b8_playerState->GetActiveVisor(*this)) { + case CPlayerState::EPlayerVisor::Combat: + case CPlayerState::EPlayerVisor::Scan: + mask = 0x1000; + target = 0x0; + break; + case CPlayerState::EPlayerVisor::XRay: + mask = 0x800; + target = 0x0; + break; + case CPlayerState::EPlayerVisor::Thermal: + if (thawed) { + if (xf34_thermalFlag == EThermalDrawFlag::Hot) { + mask = 0x600; + target = 0x0; + } else { + mask = 0x600; + target = 0x200; + } + } else { + if (xf34_thermalFlag == EThermalDrawFlag::Cold) { + mask = 0x500; + target = 0x0; + } else { + mask = 0x500; + target = 0x100; + } } + break; + default: + mask = 0x0; + target = 0x0; + break; + } } -void CStateManager::SendScriptMsg(TUniqueId dest, TUniqueId src, EScriptObjectMessage msg) -{ - CEntity* ent = ObjectById(dest); - SendScriptMsg(ent, src, msg); -} +bool CStateManager::GetVisSetForArea(TAreaId a, TAreaId b, CPVSVisSet& setOut) const { + if (b == kInvalidAreaId) + return false; -void CStateManager::SendScriptMsgAlways(TUniqueId dest, TUniqueId src, EScriptObjectMessage msg) -{ - CEntity* dst = ObjectById(dest); - if (dst) - { - if (sm_logScripting && sm_logScripting->toBoolean()) - LogModule.report(logvisor::Info, "Sending '%s' to '%s' id= 0x%.4X", - ScriptObjectMessageToStr(msg).data(), dst->GetName().data(), dst->GetUniqueId().id); - dst->AcceptScriptMsg(msg, src, *this); - } -} - -void CStateManager::SendScriptMsg(TUniqueId src, TEditorId dest, EScriptObjectMessage msg, EScriptObjectState state) -{ - CEntity* ent = ObjectById(src); - auto search = GetIdListForScript(dest); - if (search.first != x890_scriptIdMap.cend()) - { - for (auto it = search.first; it != search.second; ++it) - { - TUniqueId id = it->second; - CEntity* dobj = GetAllObjectList().GetObjectById(id); - SendScriptMsg(dobj, src, msg); + zeus::CVector3f viewPoint = CGraphics::g_ViewMatrix.origin; + zeus::CVector3f closestDockPoint = viewPoint; + bool hasClosestDock = false; + if (a != b) { + CGameArea& area = *x850_world->GetGameAreas()[b]; + if (area.IsPostConstructed()) { + for (const CGameArea::Dock& dock : area.GetDocks()) { + for (int i = 0; i < dock.GetDockRefs().size(); ++i) { + TAreaId connArea = dock.GetConnectedAreaId(i); + if (connArea == a) { + const auto& verts = dock.GetPlaneVertices(); + zeus::CVector3f dockCenter = (verts[0] + verts[1] + verts[2] + verts[4]) * 0.25f; + if (hasClosestDock) + if ((dockCenter - viewPoint).magSquared() >= (closestDockPoint - viewPoint).magSquared()) + continue; + closestDockPoint = dockCenter; + hasClosestDock = true; + } } + } } + } else { + hasClosestDock = true; + } + + if (hasClosestDock) { + if (CPVSAreaSet* pvs = x850_world->GetGameAreas()[a]->GetPostConstructed()->xa0_pvs.get()) { + const CPVSVisOctree& octree = pvs->GetVisOctree(); + zeus::CVector3f closestDockLocal = x850_world->GetGameAreas()[a]->GetInverseTransform() * closestDockPoint; + CPVSVisSet set; + set.SetTestPoint(octree, closestDockLocal); + + if (set.GetState() == EPVSVisSetState::NodeFound) { + setOut = set; + return true; + } + } + } + + return false; } -void CStateManager::FreeScriptObjects(TAreaId aid) -{ - for (const auto& p : x890_scriptIdMap) - if (p.first.AreaNum() == aid) - FreeScriptObject(p.second); - - for (auto it = x8a4_loadedScriptObjects.begin() ; it != x8a4_loadedScriptObjects.end() ;) - { - if (it->first.AreaNum() == aid) - { - it = x8a4_loadedScriptObjects.erase(it); - continue; - } - ++it; - } - - CGameArea* area = x850_world->GetGameAreas()[aid].get(); - if (area->IsPostConstructed()) - { - const CGameArea::CPostConstructed* pc = area->GetPostConstructed(); - for (CEntity* ent : *pc->x10c0_areaObjs) - if (ent && !ent->IsInUse()) - FreeScriptObject(ent->GetUniqueId()); +void CStateManager::RecursiveDrawTree(TUniqueId node) const { + if (TCastToConstPtr actor = GetObjectById(node)) { + if (x8dc_objectDrawToken != actor->xc8_drawnToken) { + if (actor->xc6_nextDrawNode != kInvalidUniqueId) + RecursiveDrawTree(actor->xc6_nextDrawNode); + if (x8dc_objectDrawToken == actor->xcc_addedToken) + actor->Render(*this); + const_cast(actor.GetPtr())->xc8_drawnToken = x8dc_objectDrawToken; } + } } -void CStateManager::FreeScriptObject(TUniqueId id) -{ - CEntity* ent = ObjectById(id); - if (!ent || ent->IsInGraveyard()) - return; - - ent->SetIsInGraveyard(true); - x854_objectGraveyard.push_back(id); - ent->AcceptScriptMsg(EScriptObjectMessage::Deleted, kInvalidUniqueId, *this); - ent->SetIsScriptingBlocked(true); - - if (TCastToPtr act = ent) - { - x874_sortedListManager->Remove(act.GetPtr()); - act->SetUseInSortedLists(false); - } - +void CStateManager::SendScriptMsg(CEntity* dest, TUniqueId src, EScriptObjectMessage msg) { + if (dest && !dest->x30_26_scriptingBlocked) { if (sm_logScripting && sm_logScripting->toBoolean()) - LogModule.report(logvisor::Info, "Removed '%s'", ent->GetName().data()); + LogModule.report(logvisor::Info, "Sending '%s' to '%s' id= 0x%.4X", ScriptObjectMessageToStr(msg).data(), + dest->GetName().data(), dest->GetUniqueId().id); + dest->AcceptScriptMsg(msg, src, *this); + } } -std::pair CStateManager::GetBuildForScript(TEditorId id) const -{ - auto search = x8a4_loadedScriptObjects.find(id); - if (search == x8a4_loadedScriptObjects.cend()) - return {nullptr, kInvalidEditorId}; - return {&search->second, search->first}; +void CStateManager::SendScriptMsg(TUniqueId dest, TUniqueId src, EScriptObjectMessage msg) { + CEntity* ent = ObjectById(dest); + SendScriptMsg(ent, src, msg); } -TEditorId CStateManager::GetEditorIdForUniqueId(TUniqueId id) const -{ - const CEntity* ent = GetObjectById(id); - if (ent) - return ent->GetEditorId(); - return kInvalidEditorId; +void CStateManager::SendScriptMsgAlways(TUniqueId dest, TUniqueId src, EScriptObjectMessage msg) { + CEntity* dst = ObjectById(dest); + if (dst) { + if (sm_logScripting && sm_logScripting->toBoolean()) + LogModule.report(logvisor::Info, "Sending '%s' to '%s' id= 0x%.4X", ScriptObjectMessageToStr(msg).data(), + dst->GetName().data(), dst->GetUniqueId().id); + dst->AcceptScriptMsg(msg, src, *this); + } } -TUniqueId CStateManager::GetIdForScript(TEditorId id) const -{ - auto search = x890_scriptIdMap.find(id); - if (search == x890_scriptIdMap.cend()) - return kInvalidUniqueId; - return search->second; +void CStateManager::SendScriptMsg(TUniqueId src, TEditorId dest, EScriptObjectMessage msg, EScriptObjectState state) { + CEntity* ent = ObjectById(src); + auto search = GetIdListForScript(dest); + if (search.first != x890_scriptIdMap.cend()) { + for (auto it = search.first; it != search.second; ++it) { + TUniqueId id = it->second; + CEntity* dobj = GetAllObjectList().GetObjectById(id); + SendScriptMsg(dobj, src, msg); + } + } +} + +void CStateManager::FreeScriptObjects(TAreaId aid) { + for (const auto& p : x890_scriptIdMap) + if (p.first.AreaNum() == aid) + FreeScriptObject(p.second); + + for (auto it = x8a4_loadedScriptObjects.begin(); it != x8a4_loadedScriptObjects.end();) { + if (it->first.AreaNum() == aid) { + it = x8a4_loadedScriptObjects.erase(it); + continue; + } + ++it; + } + + CGameArea* area = x850_world->GetGameAreas()[aid].get(); + if (area->IsPostConstructed()) { + const CGameArea::CPostConstructed* pc = area->GetPostConstructed(); + for (CEntity* ent : *pc->x10c0_areaObjs) + if (ent && !ent->IsInUse()) + FreeScriptObject(ent->GetUniqueId()); + } +} + +void CStateManager::FreeScriptObject(TUniqueId id) { + CEntity* ent = ObjectById(id); + if (!ent || ent->IsInGraveyard()) + return; + + ent->SetIsInGraveyard(true); + x854_objectGraveyard.push_back(id); + ent->AcceptScriptMsg(EScriptObjectMessage::Deleted, kInvalidUniqueId, *this); + ent->SetIsScriptingBlocked(true); + + if (TCastToPtr act = ent) { + x874_sortedListManager->Remove(act.GetPtr()); + act->SetUseInSortedLists(false); + } + + if (sm_logScripting && sm_logScripting->toBoolean()) + LogModule.report(logvisor::Info, "Removed '%s'", ent->GetName().data()); +} + +std::pair CStateManager::GetBuildForScript(TEditorId id) const { + auto search = x8a4_loadedScriptObjects.find(id); + if (search == x8a4_loadedScriptObjects.cend()) + return {nullptr, kInvalidEditorId}; + return {&search->second, search->first}; +} + +TEditorId CStateManager::GetEditorIdForUniqueId(TUniqueId id) const { + const CEntity* ent = GetObjectById(id); + if (ent) + return ent->GetEditorId(); + return kInvalidEditorId; +} + +TUniqueId CStateManager::GetIdForScript(TEditorId id) const { + auto search = x890_scriptIdMap.find(id); + if (search == x890_scriptIdMap.cend()) + return kInvalidUniqueId; + return search->second; } std::pair::const_iterator, std::multimap::const_iterator> -CStateManager::GetIdListForScript(TEditorId id) const -{ - auto ret = x890_scriptIdMap.equal_range(id); - if (ret.first != x890_scriptIdMap.cend() && ret.first->first != id) - { - ret.first = x890_scriptIdMap.cend(); - ret.second = x890_scriptIdMap.cend(); - } - return ret; +CStateManager::GetIdListForScript(TEditorId id) const { + auto ret = x890_scriptIdMap.equal_range(id); + if (ret.first != x890_scriptIdMap.cend() && ret.first->first != id) { + ret.first = x890_scriptIdMap.cend(); + ret.second = x890_scriptIdMap.cend(); + } + return ret; } -void CStateManager::LoadScriptObjects(TAreaId aid, CInputStream& in, std::vector& idsOut) -{ - in.readUByte(); - int objCount = in.readUint32Big(); - idsOut.reserve(idsOut.size() + objCount); - for (int i=0 ; i CStateManager::LoadScriptObject(TAreaId aid, EScriptObjectType type, - u32 length, CInputStream& in) -{ - TEditorId id = in.readUint32Big(); - u32 connCount = in.readUint32Big(); - length -= 8; - std::vector conns; - conns.reserve(connCount); - for (int i=0 ; i= EScriptObjectType::Actor) - loader = x90c_loaderFuncs[int(type)]; - - CEntity* ent = nullptr; - if (loader) - { - CEntityInfo info(aid, conns, id); - ent = loader(*this, in, propCount, info); - } - else - { - error = true; - } - - if (ent) - AddObject(ent); - else - error = true; - - u32 readAmt = in.position() - startPos; - if (readAmt > length) - LogModule.report(logvisor::Fatal, "Script object overread while reading %s", ScriptObjectTypeToStr(type).data()); - u32 leftover = length - readAmt; - for (u32 i=0 ; iGetUniqueId()}; -} - -std::pair CStateManager::GenerateObject(TEditorId eid) -{ - std::pair build = GetBuildForScript(eid); +void CStateManager::LoadScriptObjects(TAreaId aid, CInputStream& in, std::vector& idsOut) { + in.readUByte(); + int objCount = in.readUint32Big(); + idsOut.reserve(idsOut.size() + objCount); + for (int i = 0; i < objCount; ++i) { + EScriptObjectType objType = EScriptObjectType(in.readUByte()); + u32 objSize = in.readUint32Big(); + u32 pos = in.position(); + auto id = LoadScriptObject(aid, objType, objSize, in); + if (id.first == kInvalidEditorId) + continue; + auto build = GetBuildForScript(id.first); if (build.first) - { - CGameArea* area = x850_world->GetArea(build.second.AreaNum()); - if (area->IsPostConstructed()) - { - std::pair buf = area->GetLayerScriptBuffer(build.second.LayerNum()); - CMemoryInStream stream(buf.first + build.first->x4_position, build.first->x8_length); - return LoadScriptObject(build.second.AreaNum(), build.first->x0_type, build.first->x8_length, stream); - } - } + continue; + x8a4_loadedScriptObjects[id.first] = SScriptObjectStream{objType, pos, objSize}; + idsOut.push_back(id.first); + } +} + +std::pair CStateManager::LoadScriptObject(TAreaId aid, EScriptObjectType type, u32 length, + CInputStream& in) { + TEditorId id = in.readUint32Big(); + u32 connCount = in.readUint32Big(); + length -= 8; + std::vector conns; + conns.reserve(connCount); + for (int i = 0; i < connCount; ++i) { + EScriptObjectState state = EScriptObjectState(in.readUint32Big()); + EScriptObjectMessage msg = EScriptObjectMessage(in.readUint32Big()); + TEditorId target = in.readUint32Big(); + length -= 12; + conns.push_back(SConnection{state, msg, target}); + } + u32 propCount = in.readUint32Big(); + length -= 4; + auto startPos = in.position(); + + bool error = false; + FScriptLoader loader = {}; + if (type < EScriptObjectType::ScriptObjectTypeMAX && type >= EScriptObjectType::Actor) + loader = x90c_loaderFuncs[int(type)]; + + CEntity* ent = nullptr; + if (loader) { + CEntityInfo info(aid, conns, id); + ent = loader(*this, in, propCount, info); + } else { + error = true; + } + + if (ent) + AddObject(ent); + else + error = true; + + u32 readAmt = in.position() - startPos; + if (readAmt > length) + LogModule.report(logvisor::Fatal, "Script object overread while reading %s", ScriptObjectTypeToStr(type).data()); + u32 leftover = length - readAmt; + for (u32 i = 0; i < leftover; ++i) + in.readByte(); + + if (error || ent == nullptr) { + LogModule.report(logvisor::Error, "Script load error while loading %s", ScriptObjectTypeToStr(type).data()); return {kInvalidEditorId, kInvalidUniqueId}; + } else + return {id, ent->GetUniqueId()}; } -void CStateManager::InitScriptObjects(const std::vector& ids) -{ - for (TEditorId id : ids) - { - if (id == kInvalidEditorId) - continue; - TUniqueId uid = GetIdForScript(id); - SendScriptMsg(uid, kInvalidUniqueId, EScriptObjectMessage::InitializedInArea); +std::pair CStateManager::GenerateObject(TEditorId eid) { + std::pair build = GetBuildForScript(eid); + if (build.first) { + CGameArea* area = x850_world->GetArea(build.second.AreaNum()); + if (area->IsPostConstructed()) { + std::pair buf = area->GetLayerScriptBuffer(build.second.LayerNum()); + CMemoryInStream stream(buf.first + build.first->x4_position, build.first->x8_length); + return LoadScriptObject(build.second.AreaNum(), build.first->x0_type, build.first->x8_length, stream); } - MurderScriptInstanceNames(); + } + return {kInvalidEditorId, kInvalidUniqueId}; } -void CStateManager::InformListeners(const zeus::CVector3f& pos, EListenNoiseType type) -{ - for (CEntity* ent : GetListeningAiObjectList()) - { - if (TCastToPtr ai = ent) - { - if (!ai->GetActive()) - continue; - CGameArea* area = x850_world->GetArea(ai->GetAreaIdAlways()); - CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; - if (area->IsPostConstructed()) - occState = area->GetPostConstructed()->x10dc_occlusionState; - if (occState != CGameArea::EOcclusionState::Occluded) - ai->Listen(pos, type); - } +void CStateManager::InitScriptObjects(const std::vector& ids) { + for (TEditorId id : ids) { + if (id == kInvalidEditorId) + continue; + TUniqueId uid = GetIdForScript(id); + SendScriptMsg(uid, kInvalidUniqueId, EScriptObjectMessage::InitializedInArea); + } + MurderScriptInstanceNames(); +} + +void CStateManager::InformListeners(const zeus::CVector3f& pos, EListenNoiseType type) { + for (CEntity* ent : GetListeningAiObjectList()) { + if (TCastToPtr ai = ent) { + if (!ai->GetActive()) + continue; + CGameArea* area = x850_world->GetArea(ai->GetAreaIdAlways()); + CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; + if (area->IsPostConstructed()) + occState = area->GetPostConstructed()->x10dc_occlusionState; + if (occState != CGameArea::EOcclusionState::Occluded) + ai->Listen(pos, type); } + } } void CStateManager::ApplyKnockBack(CActor& actor, const CDamageInfo& info, const CDamageVulnerability& vuln, - const zeus::CVector3f& pos, float dampen) -{ - if (vuln.GetVulnerability(info.GetWeaponMode(), false) == EVulnerability::Deflect) - return; - CHealthInfo* hInfo = actor.HealthInfo(*this); - if (!hInfo) - return; + const zeus::CVector3f& pos, float dampen) { + if (vuln.GetVulnerability(info.GetWeaponMode(), false) == EVulnerability::Deflect) + return; + CHealthInfo* hInfo = actor.HealthInfo(*this); + if (!hInfo) + return; - float dampedPower = (1.f - dampen) * info.GetKnockBackPower(); - if (TCastToPtr player = actor) - { - KnockBackPlayer(*player, pos, dampedPower, hInfo->GetKnockbackResistance()); + float dampedPower = (1.f - dampen) * info.GetKnockBackPower(); + if (TCastToPtr player = actor) { + KnockBackPlayer(*player, pos, dampedPower, hInfo->GetKnockbackResistance()); + return; + } + + TCastToPtr ai = actor; + if (!ai && hInfo->GetHP() <= 0.f) { + if (dampedPower > hInfo->GetKnockbackResistance()) { + if (TCastToPtr physActor = actor) { + zeus::CVector3f kbVec = pos * (dampedPower - hInfo->GetKnockbackResistance()) * physActor->GetMass() * 1.5f; + if (physActor->GetMaterialList().HasMaterial(EMaterialTypes::Immovable) || + !physActor->GetMaterialList().HasMaterial(EMaterialTypes::Grass)) + return; + physActor->ApplyImpulseWR(kbVec, zeus::CAxisAngle::sIdentity); return; + } } + } - TCastToPtr ai = actor; - if (!ai && hInfo->GetHP() <= 0.f) - { - if (dampedPower > hInfo->GetKnockbackResistance()) - { - if (TCastToPtr physActor = actor) - { - zeus::CVector3f kbVec = pos * - (dampedPower - hInfo->GetKnockbackResistance()) * physActor->GetMass() * 1.5f; - if (physActor->GetMaterialList().HasMaterial(EMaterialTypes::Immovable) || - !physActor->GetMaterialList().HasMaterial(EMaterialTypes::Grass)) - return; - physActor->ApplyImpulseWR(kbVec, zeus::CAxisAngle::sIdentity); - return; - } - } - } - - if (ai) - ai->KnockBack(pos, *this, info, dampen == 0.f ? EKnockBackType::Direct : EKnockBackType::Radius, - false, dampedPower); + if (ai) + ai->KnockBack(pos, *this, info, dampen == 0.f ? EKnockBackType::Direct : EKnockBackType::Radius, false, + dampedPower); } -void CStateManager::KnockBackPlayer(CPlayer& player, const zeus::CVector3f& pos, float power, float resistance) -{ - if (player.GetMaterialList().HasMaterial(EMaterialTypes::Immovable)) - return; +void CStateManager::KnockBackPlayer(CPlayer& player, const zeus::CVector3f& pos, float power, float resistance) { + if (player.GetMaterialList().HasMaterial(EMaterialTypes::Immovable)) + return; - float usePower; - if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) - { - usePower = power * 1000.f; - CPlayer::ESurfaceRestraints surface = - player.x2b0_outOfWaterTicks == 2 ? player.x2ac_surfaceRestraint : CPlayer::ESurfaceRestraints::Water; - if (surface != CPlayer::ESurfaceRestraints::Normal && - player.GetOrbitState() == CPlayer::EPlayerOrbitState::NoOrbit) - usePower /= 7.f; - } - else - { - usePower = power * 500.f; - } + float usePower; + if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) { + usePower = power * 1000.f; + CPlayer::ESurfaceRestraints surface = + player.x2b0_outOfWaterTicks == 2 ? player.x2ac_surfaceRestraint : CPlayer::ESurfaceRestraints::Water; + if (surface != CPlayer::ESurfaceRestraints::Normal && player.GetOrbitState() == CPlayer::EPlayerOrbitState::NoOrbit) + usePower /= 7.f; + } else { + usePower = power * 500.f; + } - float minVel = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed ? 35.f : 70.f; - float playerVel = player.x138_velocity.magnitude(); - float maxVel = std::max(playerVel, minVel); - zeus::CVector3f negVel = -player.x138_velocity; - usePower *= (1.f - 0.5f * zeus::CVector3f::getAngleDiff(pos, negVel) / M_PIF); - player.ApplyImpulseWR(pos * usePower, zeus::CAxisAngle::sIdentity); - player.UseCollisionImpulses(); - player.x2d4_accelerationChangeTimer = 0.25f; + float minVel = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed ? 35.f : 70.f; + float playerVel = player.x138_velocity.magnitude(); + float maxVel = std::max(playerVel, minVel); + zeus::CVector3f negVel = -player.x138_velocity; + usePower *= (1.f - 0.5f * zeus::CVector3f::getAngleDiff(pos, negVel) / M_PIF); + player.ApplyImpulseWR(pos * usePower, zeus::CAxisAngle::sIdentity); + player.UseCollisionImpulses(); + player.x2d4_accelerationChangeTimer = 0.25f; - float newVel = player.x138_velocity.magnitude(); - if (newVel > maxVel) - { - zeus::CVector3f vel = (1.f / newVel) * player.x138_velocity * maxVel; - player.SetVelocityWR(vel); - } + float newVel = player.x138_velocity.magnitude(); + if (newVel > maxVel) { + zeus::CVector3f vel = (1.f / newVel) * player.x138_velocity * maxVel; + player.SetVelocityWR(vel); + } } void CStateManager::ApplyDamageToWorld(TUniqueId damager, const CActor& actor, const zeus::CVector3f& pos, - const CDamageInfo& info, const CMaterialFilter& filter) -{ - zeus::CAABox aabb(pos - info.GetRadius(), pos + info.GetRadius()); + const CDamageInfo& info, const CMaterialFilter& filter) { + zeus::CAABox aabb(pos - info.GetRadius(), pos + info.GetRadius()); - bool bomb = false; - TCastToPtr weapon = const_cast(actor); - if (weapon) - bomb = (weapon->GetAttribField() & (EProjectileAttrib::Bombs | - EProjectileAttrib::PowerBombs)) != EProjectileAttrib::None; + bool bomb = false; + TCastToPtr weapon = const_cast(actor); + if (weapon) + bomb = (weapon->GetAttribField() & (EProjectileAttrib::Bombs | EProjectileAttrib::PowerBombs)) != + EProjectileAttrib::None; - rstl::reserved_vector nearList; - BuildNearList(nearList, aabb, filter, &actor); - for (TUniqueId id : nearList) - { - CEntity* ent = ObjectById(id); - if (!ent) - continue; + rstl::reserved_vector nearList; + BuildNearList(nearList, aabb, filter, &actor); + for (TUniqueId id : nearList) { + CEntity* ent = ObjectById(id); + if (!ent) + continue; - TCastToPtr player = ent; - if (bomb && player) - { - if (player->GetFrozenState()) - { - g_GameState->SystemOptions().IncrementFrozenBallCount(); - CHUDMemoParms info = {0.f, true, true, true}; - MP1::CSamusHud::DisplayHudMemo(u"", info); - player->UnFreeze(*this); - } - else - { - if ((weapon->GetAttribField() & EProjectileAttrib::Bombs) == EProjectileAttrib::Bombs) - player->BombJump(pos, *this); - } - } - else if (ent->GetUniqueId() != damager) - { - TestBombHittingWater(actor, pos, static_cast(*ent)); - if (TestRayDamage(pos, static_cast(*ent), nearList)) - ApplyRadiusDamage(actor, pos, static_cast(*ent), info); - } - - if (TCastToPtr swarm = ent) - swarm->ApplyRadiusDamage(pos, info, *this); - - if (TCastToPtr swarm = ent) - swarm->ApplyRadiusDamage(pos, info, *this); + TCastToPtr player = ent; + if (bomb && player) { + if (player->GetFrozenState()) { + g_GameState->SystemOptions().IncrementFrozenBallCount(); + CHUDMemoParms info = {0.f, true, true, true}; + MP1::CSamusHud::DisplayHudMemo(u"", info); + player->UnFreeze(*this); + } else { + if ((weapon->GetAttribField() & EProjectileAttrib::Bombs) == EProjectileAttrib::Bombs) + player->BombJump(pos, *this); + } + } else if (ent->GetUniqueId() != damager) { + TestBombHittingWater(actor, pos, static_cast(*ent)); + if (TestRayDamage(pos, static_cast(*ent), nearList)) + ApplyRadiusDamage(actor, pos, static_cast(*ent), info); } + + if (TCastToPtr swarm = ent) + swarm->ApplyRadiusDamage(pos, info, *this); + + if (TCastToPtr swarm = ent) + swarm->ApplyRadiusDamage(pos, info, *this); + } } -void CStateManager::ProcessRadiusDamage(const CActor& damager, CActor& damagee, - TUniqueId senderId, const CDamageInfo& info, - const CMaterialFilter& filter) -{ - zeus::CAABox aabb(damager.GetTranslation() - info.GetRadius(), damager.GetTranslation() + info.GetRadius()); - rstl::reserved_vector nearList; - BuildNearList(nearList, aabb, filter, nullptr); - for (TUniqueId id : nearList) - { - CEntity* ent = ObjectById(id); - if (!ent || ent->GetUniqueId() == damager.GetUniqueId() || - ent->GetUniqueId() == senderId || - ent->GetUniqueId() == damagee.GetUniqueId()) - continue; +void CStateManager::ProcessRadiusDamage(const CActor& damager, CActor& damagee, TUniqueId senderId, + const CDamageInfo& info, const CMaterialFilter& filter) { + zeus::CAABox aabb(damager.GetTranslation() - info.GetRadius(), damager.GetTranslation() + info.GetRadius()); + rstl::reserved_vector nearList; + BuildNearList(nearList, aabb, filter, nullptr); + for (TUniqueId id : nearList) { + CEntity* ent = ObjectById(id); + if (!ent || ent->GetUniqueId() == damager.GetUniqueId() || ent->GetUniqueId() == senderId || + ent->GetUniqueId() == damagee.GetUniqueId()) + continue; - TestBombHittingWater(damager, damager.GetTranslation(), static_cast(*ent)); - if (TestRayDamage(damager.GetTranslation(), static_cast(*ent), nearList)) - ApplyRadiusDamage(damager, damager.GetTranslation(), static_cast(*ent), info); - } + TestBombHittingWater(damager, damager.GetTranslation(), static_cast(*ent)); + if (TestRayDamage(damager.GetTranslation(), static_cast(*ent), nearList)) + ApplyRadiusDamage(damager, damager.GetTranslation(), static_cast(*ent), info); + } } -void CStateManager::ApplyRadiusDamage(const CActor& a1, const zeus::CVector3f& pos, - CActor& a2, const CDamageInfo& info) -{ - zeus::CVector3f delta = a2.GetTranslation() - pos; - if (delta.magSquared() >= info.GetRadius() * info.GetRadius()) - { - std::experimental::optional bounds = a2.GetTouchBounds(); - if (!bounds) - return; - if (CCollidableSphere::Sphere_AABox_Bool(zeus::CSphere{pos, info.GetRadius()}, *bounds)) - { - float rad = info.GetRadius(); - if (rad > FLT_EPSILON) - rad = delta.magnitude() / rad; - else - rad = 0.f; - if (rad > 0.f) - delta.normalize(); +void CStateManager::ApplyRadiusDamage(const CActor& a1, const zeus::CVector3f& pos, CActor& a2, + const CDamageInfo& info) { + zeus::CVector3f delta = a2.GetTranslation() - pos; + if (delta.magSquared() >= info.GetRadius() * info.GetRadius()) { + std::experimental::optional bounds = a2.GetTouchBounds(); + if (!bounds) + return; + if (CCollidableSphere::Sphere_AABox_Bool(zeus::CSphere{pos, info.GetRadius()}, *bounds)) { + float rad = info.GetRadius(); + if (rad > FLT_EPSILON) + rad = delta.magnitude() / rad; + else + rad = 0.f; + if (rad > 0.f) + delta.normalize(); - bool alive = false; - if (CHealthInfo* hInfo = a2.HealthInfo(*this)) - if (hInfo->GetHP() > 0.f) - alive = true; + bool alive = false; + if (CHealthInfo* hInfo = a2.HealthInfo(*this)) + if (hInfo->GetHP() > 0.f) + alive = true; - const CDamageVulnerability* vuln; - if (rad > 0.f) - vuln = a2.GetDamageVulnerability(pos, delta, info); - else - vuln = a2.GetDamageVulnerability(); + const CDamageVulnerability* vuln; + if (rad > 0.f) + vuln = a2.GetDamageVulnerability(pos, delta, info); + else + vuln = a2.GetDamageVulnerability(); - if (vuln->WeaponHurts(info.GetWeaponMode(), true)) - { - float dam = info.GetRadiusDamage(*vuln); - if (dam > 0.f) - ApplyLocalDamage(pos, delta, a2, dam, info.GetWeaponMode()); - a2.SendScriptMsgs(EScriptObjectState::Damage, *this, EScriptObjectMessage::None); - SendScriptMsg(&a2, a1.GetUniqueId(), EScriptObjectMessage::Damage); - } - else - { - a2.SendScriptMsgs(EScriptObjectState::InvulnDamage, *this, EScriptObjectMessage::None); - SendScriptMsg(&a2, a1.GetUniqueId(), EScriptObjectMessage::InvulnDamage); - } + if (vuln->WeaponHurts(info.GetWeaponMode(), true)) { + float dam = info.GetRadiusDamage(*vuln); + if (dam > 0.f) + ApplyLocalDamage(pos, delta, a2, dam, info.GetWeaponMode()); + a2.SendScriptMsgs(EScriptObjectState::Damage, *this, EScriptObjectMessage::None); + SendScriptMsg(&a2, a1.GetUniqueId(), EScriptObjectMessage::Damage); + } else { + a2.SendScriptMsgs(EScriptObjectState::InvulnDamage, *this, EScriptObjectMessage::None); + SendScriptMsg(&a2, a1.GetUniqueId(), EScriptObjectMessage::InvulnDamage); + } - if (alive && info.GetKnockBackPower() > 0.f) - ApplyKnockBack(a2, info, *vuln, (a2.GetTranslation() - a1.GetTranslation()).normalized(), rad); - } + if (alive && info.GetKnockBackPower() > 0.f) + ApplyKnockBack(a2, info, *vuln, (a2.GetTranslation() - a1.GetTranslation()).normalized(), rad); } + } } bool CStateManager::TestRayDamage(const zeus::CVector3f& pos, const CActor& damagee, - const rstl::reserved_vector& nearList) const -{ - const CHealthInfo* hInfo = const_cast(damagee).HealthInfo(const_cast(*this)); - if (!hInfo) - return false; + const rstl::reserved_vector& nearList) const { + const CHealthInfo* hInfo = const_cast(damagee).HealthInfo(const_cast(*this)); + if (!hInfo) + return false; - static const CMaterialList incList(EMaterialTypes::Solid); - static const CMaterialList exList(EMaterialTypes::ProjectilePassthrough, - EMaterialTypes::Player, - EMaterialTypes::Occluder, - EMaterialTypes::Character); - static const CMaterialFilter filter(incList, exList, CMaterialFilter::EFilterType::IncludeExclude); + static const CMaterialList incList(EMaterialTypes::Solid); + static const CMaterialList exList(EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, + EMaterialTypes::Occluder, EMaterialTypes::Character); + static const CMaterialFilter filter(incList, exList, CMaterialFilter::EFilterType::IncludeExclude); - std::experimental::optional bounds = damagee.GetTouchBounds(); - if (!bounds) - return false; + std::experimental::optional bounds = damagee.GetTouchBounds(); + if (!bounds) + return false; - zeus::CVector3f center = bounds->center(); - zeus::CVector3f dir = center - pos; + zeus::CVector3f center = bounds->center(); + zeus::CVector3f dir = center - pos; - if (!dir.canBeNormalized()) - return true; - float origMag = dir.magnitude(); - dir = dir * (1.f / origMag); + if (!dir.canBeNormalized()) + return true; + float origMag = dir.magnitude(); + dir = dir * (1.f / origMag); - if (RayCollideWorld(pos, center, nearList, filter, &damagee)) - return true; + if (RayCollideWorld(pos, center, nearList, filter, &damagee)) + return true; - zeus::CMRay ray(pos, dir, origMag); - if (!MultiRayCollideWorld(ray, filter)) - return false; + zeus::CMRay ray(pos, dir, origMag); + if (!MultiRayCollideWorld(ray, filter)) + return false; - float depth; - zeus::CVector3f norm; - u32 count = CollisionUtil::RayAABoxIntersection(ray, *bounds, norm, depth); - if (count == 0 || count == 1) - return true; + float depth; + zeus::CVector3f norm; + u32 count = CollisionUtil::RayAABoxIntersection(ray, *bounds, norm, depth); + if (count == 0 || count == 1) + return true; - return CGameCollision::RayDynamicIntersectionBool(*this, pos, dir, filter, nearList, &damagee, depth * origMag); + return CGameCollision::RayDynamicIntersectionBool(*this, pos, dir, filter, nearList, &damagee, depth * origMag); } bool CStateManager::RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end, - const CMaterialFilter& filter, const CActor* damagee) const -{ - zeus::CVector3f delta = end - start; - float mag = delta.magnitude(); - delta = delta / mag; - rstl::reserved_vector nearList; - BuildNearList(nearList, start, delta, mag, filter, damagee); - return RayCollideWorldInternal(start, end, filter, nearList, damagee); + const CMaterialFilter& filter, const CActor* damagee) const { + zeus::CVector3f delta = end - start; + float mag = delta.magnitude(); + delta = delta / mag; + rstl::reserved_vector nearList; + BuildNearList(nearList, start, delta, mag, filter, damagee); + return RayCollideWorldInternal(start, end, filter, nearList, damagee); } bool CStateManager::RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end, const rstl::reserved_vector& nearList, - const CMaterialFilter& filter, const CActor* damagee) const -{ - return RayCollideWorldInternal(start, end, filter, nearList, damagee); + const CMaterialFilter& filter, const CActor* damagee) const { + return RayCollideWorldInternal(start, end, filter, nearList, damagee); } bool CStateManager::RayCollideWorldInternal(const zeus::CVector3f& start, const zeus::CVector3f& end, const CMaterialFilter& filter, const rstl::reserved_vector& nearList, - const CActor* damagee) const -{ - zeus::CVector3f delta = end - start; - if (!delta.canBeNormalized()) - return true; - - float mag = delta.magnitude(); - zeus::CVector3f dir = delta * (1.f / mag); - if (!CGameCollision::RayStaticIntersectionBool(*this, start, dir, mag, filter)) - return false; - return CGameCollision::RayDynamicIntersectionBool(*this, start, dir, filter, nearList, damagee, mag); -} - -bool CStateManager::MultiRayCollideWorld(const zeus::CMRay& ray, const CMaterialFilter& filter) const -{ - zeus::CVector3f crossed = - { - -ray.dir.z() * ray.dir.z() - ray.dir.y() * ray.dir.x(), - ray.dir.x() * ray.dir.x() - ray.dir.z() * ray.dir.y(), - ray.dir.y() * ray.dir.y() - ray.dir.x() * -ray.dir.z() - }; - - crossed.normalize(); - zeus::CVector3f crossed2 = ray.dir.cross(crossed) * 0.35355338f; - zeus::CVector3f negCrossed2 = -crossed2; - zeus::CVector3f rms = crossed * 0.35355338f; - zeus::CVector3f negRms = -rms; - - for (int i=0 ; i<4 ; ++i) - { - zeus::CVector3f& useCrossed = (i & 2) ? negCrossed2 : crossed2; - zeus::CVector3f& useRms = (i & 1) ? rms : negRms; - if (CGameCollision::RayStaticIntersectionBool(*this, ray.start + useCrossed + useRms, - ray.dir, ray.length, filter)) - return true; - } + const CActor* damagee) const { + zeus::CVector3f delta = end - start; + if (!delta.canBeNormalized()) + return true; + float mag = delta.magnitude(); + zeus::CVector3f dir = delta * (1.f / mag); + if (!CGameCollision::RayStaticIntersectionBool(*this, start, dir, mag, filter)) return false; + return CGameCollision::RayDynamicIntersectionBool(*this, start, dir, filter, nearList, damagee, mag); } -void CStateManager::TestBombHittingWater(const CActor& damager, const zeus::CVector3f& pos, CActor& damagee) -{ - if (TCastToPtr wpn = const_cast(damager)) - { - if ((wpn->GetAttribField() & (EProjectileAttrib::Bombs | - EProjectileAttrib::PowerBombs)) != EProjectileAttrib::None) - { - bool powerBomb = (wpn->GetAttribField() & EProjectileAttrib::PowerBombs) == EProjectileAttrib::PowerBombs; - if (TCastToPtr water = damagee) - { - zeus::CAABox bounds = water->GetTriggerBoundsWR(); - zeus::CVector3f hitPos(pos.x(), pos.y(), bounds.max.z()); - float bombRad = powerBomb ? 4.f : 2.f; - float delta = bounds.max.z() - pos.dot(zeus::CVector3f::skUp); - if (delta <= bombRad && delta > 0.f) - { - // Below surface - float rippleFactor = 1.f - delta / bombRad; - if (x87c_fluidPlaneManager->GetLastRippleDeltaTime(damager.GetUniqueId()) >= 0.15f) - { - float bombMag = powerBomb ? 1.f : 0.75f; - float mag = 0.6f * bombMag + 0.4f * bombMag * std::sin(2.f * M_PIF * rippleFactor * 0.25f); - water->GetFluidPlane().AddRipple(mag, damager.GetUniqueId(), hitPos, *water, *this); - } - if (!powerBomb) - x87c_fluidPlaneManager->CreateSplash(damager.GetUniqueId(), *this, *water, hitPos, - rippleFactor, true); - } - else - { - // Above surface - float bombMag = powerBomb ? 2.f : 1.f; - if (delta <= -bombMag || delta >= 0.f) - return; - CRayCastResult res = RayStaticIntersection(pos, zeus::CVector3f::skDown, -delta, - CMaterialFilter::skPassEverything); - if (res.IsInvalid() && - x87c_fluidPlaneManager->GetLastRippleDeltaTime(damager.GetUniqueId()) >= 0.15f) - { - // Not blocked by static geometry - float mag = 0.6f * bombMag + 0.4f * bombMag * std::sin(2.f * M_PIF * -delta / bombMag * 0.25f); - water->GetFluidPlane().AddRipple(mag, damager.GetUniqueId(), hitPos, *water, *this); - } - } - } +bool CStateManager::MultiRayCollideWorld(const zeus::CMRay& ray, const CMaterialFilter& filter) const { + zeus::CVector3f crossed = {-ray.dir.z() * ray.dir.z() - ray.dir.y() * ray.dir.x(), + ray.dir.x() * ray.dir.x() - ray.dir.z() * ray.dir.y(), + ray.dir.y() * ray.dir.y() - ray.dir.x() * -ray.dir.z()}; + + crossed.normalize(); + zeus::CVector3f crossed2 = ray.dir.cross(crossed) * 0.35355338f; + zeus::CVector3f negCrossed2 = -crossed2; + zeus::CVector3f rms = crossed * 0.35355338f; + zeus::CVector3f negRms = -rms; + + for (int i = 0; i < 4; ++i) { + zeus::CVector3f& useCrossed = (i & 2) ? negCrossed2 : crossed2; + zeus::CVector3f& useRms = (i & 1) ? rms : negRms; + if (CGameCollision::RayStaticIntersectionBool(*this, ray.start + useCrossed + useRms, ray.dir, ray.length, filter)) + return true; + } + + return false; +} + +void CStateManager::TestBombHittingWater(const CActor& damager, const zeus::CVector3f& pos, CActor& damagee) { + if (TCastToPtr wpn = const_cast(damager)) { + if ((wpn->GetAttribField() & (EProjectileAttrib::Bombs | EProjectileAttrib::PowerBombs)) != + EProjectileAttrib::None) { + bool powerBomb = (wpn->GetAttribField() & EProjectileAttrib::PowerBombs) == EProjectileAttrib::PowerBombs; + if (TCastToPtr water = damagee) { + zeus::CAABox bounds = water->GetTriggerBoundsWR(); + zeus::CVector3f hitPos(pos.x(), pos.y(), bounds.max.z()); + float bombRad = powerBomb ? 4.f : 2.f; + float delta = bounds.max.z() - pos.dot(zeus::CVector3f::skUp); + if (delta <= bombRad && delta > 0.f) { + // Below surface + float rippleFactor = 1.f - delta / bombRad; + if (x87c_fluidPlaneManager->GetLastRippleDeltaTime(damager.GetUniqueId()) >= 0.15f) { + float bombMag = powerBomb ? 1.f : 0.75f; + float mag = 0.6f * bombMag + 0.4f * bombMag * std::sin(2.f * M_PIF * rippleFactor * 0.25f); + water->GetFluidPlane().AddRipple(mag, damager.GetUniqueId(), hitPos, *water, *this); + } + if (!powerBomb) + x87c_fluidPlaneManager->CreateSplash(damager.GetUniqueId(), *this, *water, hitPos, rippleFactor, true); + } else { + // Above surface + float bombMag = powerBomb ? 2.f : 1.f; + if (delta <= -bombMag || delta >= 0.f) + return; + CRayCastResult res = + RayStaticIntersection(pos, zeus::CVector3f::skDown, -delta, CMaterialFilter::skPassEverything); + if (res.IsInvalid() && x87c_fluidPlaneManager->GetLastRippleDeltaTime(damager.GetUniqueId()) >= 0.15f) { + // Not blocked by static geometry + float mag = 0.6f * bombMag + 0.4f * bombMag * std::sin(2.f * M_PIF * -delta / bombMag * 0.25f); + water->GetFluidPlane().AddRipple(mag, damager.GetUniqueId(), hitPos, *water, *this); + } } + } } + } } -bool CStateManager::ApplyLocalDamage(const zeus::CVector3f& pos, const zeus::CVector3f& dir, CActor& damagee, - float dam, const CWeaponMode& weapMode) -{ - CHealthInfo* hInfo = damagee.HealthInfo(*this); - if (!hInfo || dam < 0.f) +bool CStateManager::ApplyLocalDamage(const zeus::CVector3f& pos, const zeus::CVector3f& dir, CActor& damagee, float dam, + const CWeaponMode& weapMode) { + CHealthInfo* hInfo = damagee.HealthInfo(*this); + if (!hInfo || dam < 0.f) + return false; + + if (hInfo->GetHP() <= 0.f) + return true; + + float mulDam = dam; + + TCastToPtr player = damagee; + CAi* ai = TCastToPtr(damagee).GetPtr(); + if (!ai) + ai = TCastToPtr(damagee).GetPtr(); + + if (player) { + if (GetPlayerState()->CanTakeDamage()) { + if (x870_cameraManager->IsInCinematicCamera() || + (weapMode.GetType() == EWeaponType::Phazon && + x8b8_playerState->HasPowerUp(CPlayerState::EItemType::PhazonSuit))) return false; - if (hInfo->GetHP() <= 0.f) - return true; + if (g_GameState->GetHardMode()) + mulDam *= g_GameState->GetHardModeDamageMultiplier(); - float mulDam = dam; + float damReduction = 0.f; + if (x8b8_playerState->HasPowerUp(CPlayerState::EItemType::VariaSuit)) + damReduction = g_tweakPlayer->GetVariaDamageReduction(); + if (x8b8_playerState->HasPowerUp(CPlayerState::EItemType::GravitySuit)) + damReduction = std::max(g_tweakPlayer->GetGravityDamageReduction(), damReduction); + if (x8b8_playerState->HasPowerUp(CPlayerState::EItemType::PhazonSuit)) + damReduction = std::max(g_tweakPlayer->GetPhazonDamageReduction(), damReduction); - TCastToPtr player = damagee; - CAi* ai = TCastToPtr(damagee).GetPtr(); - if (!ai) - ai = TCastToPtr(damagee).GetPtr(); + mulDam = -(damReduction * mulDam - mulDam); + } else + mulDam = 0.f; + } - if (player) - { - if (GetPlayerState()->CanTakeDamage()) - { - if (x870_cameraManager->IsInCinematicCamera() || - (weapMode.GetType() == EWeaponType::Phazon && - x8b8_playerState->HasPowerUp(CPlayerState::EItemType::PhazonSuit))) - return false; + float newHp = hInfo->GetHP() - mulDam; + hInfo->SetHP(newHp); + bool significant = std::fabs(newHp - hInfo->GetHP()) >= 0.00001; - if (g_GameState->GetHardMode()) - mulDam *= g_GameState->GetHardModeDamageMultiplier(); + if (player && GetPlayerState()->CanTakeDamage()) { + player->TakeDamage(significant, pos, mulDam, weapMode.GetType(), *this); + if (newHp <= 0.f) + x8b8_playerState->SetPlayerAlive(false); + } - float damReduction = 0.f; - if (x8b8_playerState->HasPowerUp(CPlayerState::EItemType::VariaSuit)) - damReduction = g_tweakPlayer->GetVariaDamageReduction(); - if (x8b8_playerState->HasPowerUp(CPlayerState::EItemType::GravitySuit)) - damReduction = std::max(g_tweakPlayer->GetGravityDamageReduction(), damReduction); - if (x8b8_playerState->HasPowerUp(CPlayerState::EItemType::PhazonSuit)) - damReduction = std::max(g_tweakPlayer->GetPhazonDamageReduction(), damReduction); + if (ai) { + if (significant) + ai->TakeDamage(dir, mulDam); + if (newHp <= 0.f) + ai->Death(*this, dir, EScriptObjectState::DeathRattle); + } - mulDam = -(damReduction * mulDam - mulDam); - } - else - mulDam = 0.f; - } - - float newHp = hInfo->GetHP() - mulDam; - hInfo->SetHP(newHp); - bool significant = std::fabs(newHp - hInfo->GetHP()) >= 0.00001; - - if (player && GetPlayerState()->CanTakeDamage()) - { - player->TakeDamage(significant, pos, mulDam, weapMode.GetType(), *this); - if (newHp <= 0.f) - x8b8_playerState->SetPlayerAlive(false); - } - - if (ai) - { - if (significant) - ai->TakeDamage(dir, mulDam); - if (newHp <= 0.f) - ai->Death(*this, dir, EScriptObjectState::DeathRattle); - } - - return significant; + return significant; } bool CStateManager::ApplyDamage(TUniqueId damagerId, TUniqueId damageeId, TUniqueId radiusSender, const CDamageInfo& info, const CMaterialFilter& filter, - const zeus::CVector3f& knockbackVec) -{ - CEntity* ent0 = ObjectById(damagerId); - CEntity* ent1 = ObjectById(damageeId); - TCastToPtr damager = ent0; - TCastToPtr damagee = ent1; - bool isPlayer = TCastToPtr(ent1); + const zeus::CVector3f& knockbackVec) { + CEntity* ent0 = ObjectById(damagerId); + CEntity* ent1 = ObjectById(damageeId); + TCastToPtr damager = ent0; + TCastToPtr damagee = ent1; + bool isPlayer = TCastToPtr(ent1); - if (damagee) - { - if (CHealthInfo* hInfo = damagee->HealthInfo(*this)) - { - zeus::CVector3f position; - zeus::CVector3f direction = zeus::CVector3f::skRight; - bool alive = hInfo->GetHP() > 0.f; - if (damager) - { - position = damager->GetTranslation(); - direction = damager->GetTransform().basis[1]; - } + if (damagee) { + if (CHealthInfo* hInfo = damagee->HealthInfo(*this)) { + zeus::CVector3f position; + zeus::CVector3f direction = zeus::CVector3f::skRight; + bool alive = hInfo->GetHP() > 0.f; + if (damager) { + position = damager->GetTranslation(); + direction = damager->GetTransform().basis[1]; + } - const CDamageVulnerability* dVuln; - if (damager || isPlayer) - dVuln = damagee->GetDamageVulnerability(position, direction, info); - else - dVuln = damagee->GetDamageVulnerability(); + const CDamageVulnerability* dVuln; + if (damager || isPlayer) + dVuln = damagee->GetDamageVulnerability(position, direction, info); + else + dVuln = damagee->GetDamageVulnerability(); - if (info.GetWeaponMode().GetType() == EWeaponType::None || - dVuln->WeaponHurts(info.GetWeaponMode(), false)) - { - if (info.GetDamage() > 0.f) - ApplyLocalDamage(position, direction, *damagee, info.GetDamage(), info.GetWeaponMode()); - damagee->SendScriptMsgs(EScriptObjectState::Damage, *this, EScriptObjectMessage::None); - SendScriptMsg(damagee.GetPtr(), damagerId, EScriptObjectMessage::Damage); - } - else - { - damagee->SendScriptMsgs(EScriptObjectState::InvulnDamage, *this, EScriptObjectMessage::None); - SendScriptMsg(damagee.GetPtr(), damagerId, EScriptObjectMessage::InvulnDamage); - } + if (info.GetWeaponMode().GetType() == EWeaponType::None || dVuln->WeaponHurts(info.GetWeaponMode(), false)) { + if (info.GetDamage() > 0.f) + ApplyLocalDamage(position, direction, *damagee, info.GetDamage(), info.GetWeaponMode()); + damagee->SendScriptMsgs(EScriptObjectState::Damage, *this, EScriptObjectMessage::None); + SendScriptMsg(damagee.GetPtr(), damagerId, EScriptObjectMessage::Damage); + } else { + damagee->SendScriptMsgs(EScriptObjectState::InvulnDamage, *this, EScriptObjectMessage::None); + SendScriptMsg(damagee.GetPtr(), damagerId, EScriptObjectMessage::InvulnDamage); + } - if (alive && damager && info.GetKnockBackPower() > 0.f) - { - zeus::CVector3f delta = knockbackVec.isZero() ? - (damagee->GetTranslation() - damager->GetTranslation()) : knockbackVec; - ApplyKnockBack(*damagee, info, *dVuln, delta.normalized(), 0.f); - } - } - - if (damager && info.GetRadius() > 0.f) - ProcessRadiusDamage(*damager, *damagee, radiusSender, info, filter); - - if (TCastToPtr swarm = ent1) - if (damager) - swarm->ApplyRadiusDamage(damager->GetTranslation(), info, *this); + if (alive && damager && info.GetKnockBackPower() > 0.f) { + zeus::CVector3f delta = + knockbackVec.isZero() ? (damagee->GetTranslation() - damager->GetTranslation()) : knockbackVec; + ApplyKnockBack(*damagee, info, *dVuln, delta.normalized(), 0.f); + } } - return false; + if (damager && info.GetRadius() > 0.f) + ProcessRadiusDamage(*damager, *damagee, radiusSender, info, filter); + + if (TCastToPtr swarm = ent1) + if (damager) + swarm->ApplyRadiusDamage(damager->GetTranslation(), info, *this); + } + + return false; } -void CStateManager::UpdateAreaSounds() -{ - rstl::reserved_vector areas; - for (CGameArea& area : *x850_world) - { - CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; - if (area.IsPostConstructed()) - occState = area.GetOcclusionState(); - if (occState == CGameArea::EOcclusionState::Visible) - areas.push_back(area.GetAreaId()); - } - CSfxManager::SetActiveAreas(areas); +void CStateManager::UpdateAreaSounds() { + rstl::reserved_vector areas; + for (CGameArea& area : *x850_world) { + CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; + if (area.IsPostConstructed()) + occState = area.GetOcclusionState(); + if (occState == CGameArea::EOcclusionState::Visible) + areas.push_back(area.GetAreaId()); + } + CSfxManager::SetActiveAreas(areas); } -void CStateManager::FrameEnd() -{ - g_SimplePool->Flush(); +void CStateManager::FrameEnd() { g_SimplePool->Flush(); } + +void CStateManager::ProcessPlayerInput() { + if (x84c_player) + x84c_player->ProcessInput(xb54_finalInput, *this); } -void CStateManager::ProcessPlayerInput() -{ - if (x84c_player) - x84c_player->ProcessInput(xb54_finalInput, *this); -} +void CStateManager::SetGameState(EGameState state) { + if (x904_gameState == state) + return; -void CStateManager::SetGameState(EGameState state) -{ - if (x904_gameState == state) - return; + if (x904_gameState == EGameState::SoftPaused) + x850_world->SetLoadPauseState(false); - if (x904_gameState == EGameState::SoftPaused) - x850_world->SetLoadPauseState(false); + switch (state) { + case EGameState::Running: + if (x88c_rumbleManager->IsDisabled()) + x88c_rumbleManager->SetDisabled(false); + break; + case EGameState::SoftPaused: + if (!x88c_rumbleManager->IsDisabled()) + x88c_rumbleManager->SetDisabled(true); + x850_world->SetLoadPauseState(true); + default: + break; + } - switch (state) - { - case EGameState::Running: - if (x88c_rumbleManager->IsDisabled()) - x88c_rumbleManager->SetDisabled(false); - break; - case EGameState::SoftPaused: - if (!x88c_rumbleManager->IsDisabled()) - x88c_rumbleManager->SetDisabled(true); - x850_world->SetLoadPauseState(true); - default: break; - } - - x904_gameState = state; + x904_gameState = state; } static const CFinalInput s_DisabledFinalInput = {}; -void CStateManager::ProcessInput(const CFinalInput& input) -{ - if (input.ControllerIdx() == 0) - { - CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); - bool disableInput = cam->x170_25_disablesInput; - if (x84c_player->x9c6_29_disableInput) - disableInput = true; - if (disableInput) - { - xb54_finalInput = s_DisabledFinalInput; - xb54_finalInput.x0_dt = input.DeltaTime(); - } - else - { - xb54_finalInput = input; - } +void CStateManager::ProcessInput(const CFinalInput& input) { + if (input.ControllerIdx() == 0) { + CGameCamera* cam = x870_cameraManager->GetCurrentCamera(*this); + bool disableInput = cam->x170_25_disablesInput; + if (x84c_player->x9c6_29_disableInput) + disableInput = true; + if (disableInput) { + xb54_finalInput = s_DisabledFinalInput; + xb54_finalInput.x0_dt = input.DeltaTime(); + } else { + xb54_finalInput = input; } - x870_cameraManager->ProcessInput(input, *this); + } + x870_cameraManager->ProcessInput(input, *this); } -void CStateManager::UpdateGraphicsTiming(float dt) -{ - xf14_curTimeMod900 += dt; - if (xf14_curTimeMod900 > 900.f) - xf14_curTimeMod900 -= 900.f; +void CStateManager::UpdateGraphicsTiming(float dt) { + xf14_curTimeMod900 += dt; + if (xf14_curTimeMod900 > 900.f) + xf14_curTimeMod900 -= 900.f; } -void CStateManager::Update(float dt) -{ - MP1::CMain::UpdateDiscordPresence(GetWorld()->IGetStringTableAssetId()); +void CStateManager::Update(float dt) { + MP1::CMain::UpdateDiscordPresence(GetWorld()->IGetStringTableAssetId()); - CElementGen::SetGlobalSeed(x8d8_updateFrameIdx); - CParticleElectric::SetGlobalSeed(x8d8_updateFrameIdx); - CDecal::SetGlobalSeed(x8d8_updateFrameIdx); - CProjectileWeapon::SetGlobalSeed(x8d8_updateFrameIdx); + CElementGen::SetGlobalSeed(x8d8_updateFrameIdx); + CParticleElectric::SetGlobalSeed(x8d8_updateFrameIdx); + CDecal::SetGlobalSeed(x8d8_updateFrameIdx); + CProjectileWeapon::SetGlobalSeed(x8d8_updateFrameIdx); - xf08_pauseHudMessage = {}; + xf08_pauseHudMessage = {}; - CScriptEffect::ResetParticleCounts(); - UpdateThermalVisor(); - UpdateGameState(); + CScriptEffect::ResetParticleCounts(); + UpdateThermalVisor(); + UpdateGameState(); - bool dying = x84c_player->x9f4_deathTime > 0.f; + bool dying = x84c_player->x9f4_deathTime > 0.f; - if (x904_gameState == EGameState::Running) - { - if (!TCastToPtr(x870_cameraManager->GetCurrentCamera(*this))) - { - g_GameState->SetTotalPlayTime(g_GameState->xa0_playTime + dt); - UpdateHintState(dt); - } - - for (int i=0 ; i<9 ; ++i) - { - xb84_camFilterPasses[i].Update(dt); - xd14_camBlurPasses[i].Update(dt); - } + if (x904_gameState == EGameState::Running) { + if (!TCastToPtr(x870_cameraManager->GetCurrentCamera(*this))) { + g_GameState->SetTotalPlayTime(g_GameState->xa0_playTime + dt); + UpdateHintState(dt); } - if (x904_gameState != EGameState::Paused) - { - PreThinkObjects(dt); - x87c_fluidPlaneManager->Update(dt); + for (int i = 0; i < 9; ++i) { + xb84_camFilterPasses[i].Update(dt); + xd14_camBlurPasses[i].Update(dt); } + } - if (x904_gameState == EGameState::Running) - { - if (!dying) - CDecalManager::Update(dt, *this); - UpdateSortedLists(); - if (!dying) - { - MovePlatforms(dt); - MoveActors(dt); - } - ProcessPlayerInput(); - if (x904_gameState != EGameState::SoftPaused) - CGameCollision::Move(*this, *x84c_player, dt, nullptr); - UpdateSortedLists(); - if (!dying) - CrossTouchActors(); - } - else - { - ProcessPlayerInput(); - } - - if (!dying && x904_gameState == EGameState::Running) - x884_actorModelParticles->Update(dt, *this); - - if (x904_gameState == EGameState::Running || x904_gameState == EGameState::SoftPaused) - Think(dt); - - if (x904_gameState != EGameState::SoftPaused) - x870_cameraManager->Update(dt, *this); - - while (xf76_lastRelay != kInvalidUniqueId) - { - if (CEntity* ent = ObjectById(xf76_lastRelay)) - { - ent->Think(dt, *this); - } - else - { - xf76_lastRelay = kInvalidUniqueId; - break; - } - } - - if (x904_gameState != EGameState::Paused) - PostUpdatePlayer(dt); - - if (xf84_ == xf80_hudMessageFrameCount) - { - ShowPausedHUDMemo(xf88_, xf8c_); - --xf84_; - xf88_.Reset(); - } - - if (!dying && x904_gameState == EGameState::Running && !x870_cameraManager->IsInCinematicCamera()) - UpdateEscapeSequenceTimer(dt); - - x850_world->Update(dt); - x88c_rumbleManager->Update(dt); + if (x904_gameState != EGameState::Paused) { + PreThinkObjects(dt); + x87c_fluidPlaneManager->Update(dt); + } + if (x904_gameState == EGameState::Running) { if (!dying) - x880_envFxManager->Update(dt, *this); - - UpdateAreaSounds(); - - xf94_24_readyToRender = true; - - if (xf94_27_inMapScreen) - { - if (const CHintOptions::SHintState* hint = g_GameState->HintOptions().GetCurrentDisplayedHint()) - { - if (hint->CanContinue()) - g_GameState->HintOptions().DismissDisplayedHint(); - } - xf94_27_inMapScreen = false; + CDecalManager::Update(dt, *this); + UpdateSortedLists(); + if (!dying) { + MovePlatforms(dt); + MoveActors(dt); } + ProcessPlayerInput(); + if (x904_gameState != EGameState::SoftPaused) + CGameCollision::Move(*this, *x84c_player, dt, nullptr); + UpdateSortedLists(); + if (!dying) + CrossTouchActors(); + } else { + ProcessPlayerInput(); + } - if (!m_warping) - { - g_GameState->CurrentWorldState().SetAreaId(x8cc_nextAreaId); - x850_world->TravelToArea(x8cc_nextAreaId, *this, false); + if (!dying && x904_gameState == EGameState::Running) + x884_actorModelParticles->Update(dt, *this); + + if (x904_gameState == EGameState::Running || x904_gameState == EGameState::SoftPaused) + Think(dt); + + if (x904_gameState != EGameState::SoftPaused) + x870_cameraManager->Update(dt, *this); + + while (xf76_lastRelay != kInvalidUniqueId) { + if (CEntity* ent = ObjectById(xf76_lastRelay)) { + ent->Think(dt, *this); + } else { + xf76_lastRelay = kInvalidUniqueId; + break; } + } - ClearGraveyard(); - ++x8d8_updateFrameIdx; + if (x904_gameState != EGameState::Paused) + PostUpdatePlayer(dt); + + if (xf84_ == xf80_hudMessageFrameCount) { + ShowPausedHUDMemo(xf88_, xf8c_); + --xf84_; + xf88_.Reset(); + } + + if (!dying && x904_gameState == EGameState::Running && !x870_cameraManager->IsInCinematicCamera()) + UpdateEscapeSequenceTimer(dt); + + x850_world->Update(dt); + x88c_rumbleManager->Update(dt); + + if (!dying) + x880_envFxManager->Update(dt, *this); + + UpdateAreaSounds(); + + xf94_24_readyToRender = true; + + if (xf94_27_inMapScreen) { + if (const CHintOptions::SHintState* hint = g_GameState->HintOptions().GetCurrentDisplayedHint()) { + if (hint->CanContinue()) + g_GameState->HintOptions().DismissDisplayedHint(); + } + xf94_27_inMapScreen = false; + } + + if (!m_warping) { + g_GameState->CurrentWorldState().SetAreaId(x8cc_nextAreaId); + x850_world->TravelToArea(x8cc_nextAreaId, *this, false); + } + + ClearGraveyard(); + ++x8d8_updateFrameIdx; } -void CStateManager::UpdateGameState() -{ - // Intentionally empty +void CStateManager::UpdateGameState() { + // Intentionally empty } -void CStateManager::UpdateHintState(float dt) -{ - CHintOptions& ho = g_GameState->HintOptions(); - ho.Update(dt, *this); - u32 nextHintIdx = -1; - u32 pageIdx = -1; - if (const CHintOptions::SHintState* state = ho.GetCurrentDisplayedHint()) - { - const CGameHintInfo::CGameHint& next = g_MemoryCardSys->GetHints()[ho.GetNextHintIdx()]; - for (const CGameHintInfo::SHintLocation& loc : next.GetLocations()) - { - const auto& mwInfo = g_GameState->StateForWorld(loc.x0_mlvlId).MapWorldInfo(); - mwInfo->SetIsMapped(loc.x8_areaId, true); - } - if (state->x4_time < next.GetTextTime()) - { - nextHintIdx = ho.GetNextHintIdx(); - pageIdx = state->x4_time / 3.f; - } +void CStateManager::UpdateHintState(float dt) { + CHintOptions& ho = g_GameState->HintOptions(); + ho.Update(dt, *this); + u32 nextHintIdx = -1; + u32 pageIdx = -1; + if (const CHintOptions::SHintState* state = ho.GetCurrentDisplayedHint()) { + const CGameHintInfo::CGameHint& next = g_MemoryCardSys->GetHints()[ho.GetNextHintIdx()]; + for (const CGameHintInfo::SHintLocation& loc : next.GetLocations()) { + const auto& mwInfo = g_GameState->StateForWorld(loc.x0_mlvlId).MapWorldInfo(); + mwInfo->SetIsMapped(loc.x8_areaId, true); } + if (state->x4_time < next.GetTextTime()) { + nextHintIdx = ho.GetNextHintIdx(); + pageIdx = state->x4_time / 3.f; + } + } - if (xeec_hintIdx != nextHintIdx || xef0_hintPeriods != pageIdx) - { - if (nextHintIdx == -1) - { - CHUDMemoParms memoInfo = {0.f, true, true, true}; - MP1::CSamusHud::DisplayHudMemo(u"", memoInfo); - } - else - { - const CGameHintInfo::CGameHint& data = g_MemoryCardSys->GetHints()[nextHintIdx]; - CHUDMemoParms memoInfo = {0.f, true, false, true}; - MP1::CSamusHud::DeferHintMemo(data.GetStringID(), pageIdx, memoInfo); - } - xeec_hintIdx = nextHintIdx; - xef0_hintPeriods = pageIdx; + if (xeec_hintIdx != nextHintIdx || xef0_hintPeriods != pageIdx) { + if (nextHintIdx == -1) { + CHUDMemoParms memoInfo = {0.f, true, true, true}; + MP1::CSamusHud::DisplayHudMemo(u"", memoInfo); + } else { + const CGameHintInfo::CGameHint& data = g_MemoryCardSys->GetHints()[nextHintIdx]; + CHUDMemoParms memoInfo = {0.f, true, false, true}; + MP1::CSamusHud::DeferHintMemo(data.GetStringID(), pageIdx, memoInfo); } + xeec_hintIdx = nextHintIdx; + xef0_hintPeriods = pageIdx; + } } -void CStateManager::PreThinkObjects(float dt) -{ - if (x84c_player->x9f4_deathTime > 0.f) - { - x84c_player->DoPreThink(dt, *this); - return; - } - - if (x904_gameState == EGameState::SoftPaused) - for (CEntity* ent : GetAllObjectList()) - if (TCastToPtr effect = ent) - effect->PreThink(dt, *this); +void CStateManager::PreThinkObjects(float dt) { + if (x84c_player->x9f4_deathTime > 0.f) { + x84c_player->DoPreThink(dt, *this); + return; + } + if (x904_gameState == EGameState::SoftPaused) for (CEntity* ent : GetAllObjectList()) - if (ent && !GetCameraObjectList().GetObjectById(ent->GetUniqueId())) - ent->PreThink(dt, *this); + if (TCastToPtr effect = ent) + effect->PreThink(dt, *this); + + for (CEntity* ent : GetAllObjectList()) + if (ent && !GetCameraObjectList().GetObjectById(ent->GetUniqueId())) + ent->PreThink(dt, *this); } -void CStateManager::MovePlatforms(float dt) -{ - for (CEntity* ent : GetPlatformAndDoorObjectList()) - { - if (!ent || !GetPlatformAndDoorObjectList().IsPlatform(*ent)) - continue; - CScriptPlatform& plat = static_cast(*ent); - if (!plat.GetActive() || plat.GetMass() == 0.f) - continue; - CGameCollision::Move(*this, plat, dt, nullptr); +void CStateManager::MovePlatforms(float dt) { + for (CEntity* ent : GetPlatformAndDoorObjectList()) { + if (!ent || !GetPlatformAndDoorObjectList().IsPlatform(*ent)) + continue; + CScriptPlatform& plat = static_cast(*ent); + if (!plat.GetActive() || plat.GetMass() == 0.f) + continue; + CGameCollision::Move(*this, plat, dt, nullptr); + } +} + +void CStateManager::MoveActors(float dt) { + for (CEntity* ent : GetPhysicsActorObjectList()) { + if (!ent || !ent->GetActive()) + continue; + CPhysicsActor& physActor = static_cast(*ent); + if (physActor.GetMass() == 0.f) + continue; + + if (TCastToPtr ai = physActor) { + bool doThink = !xf94_29_cinematicPause; + if (doThink && ai->GetAreaIdAlways() != kInvalidAreaId) { + const CGameArea* area = x850_world->GetAreaAlways(ai->GetAreaIdAlways()); + float occTime; + if (area->IsPostConstructed()) + occTime = area->GetPostConstructed()->x10e4_occludedTime; + else + occTime = 0.f; + if (occTime > 5.f) + doThink = false; + } + if (!doThink) { + SendScriptMsgAlways(ai->GetUniqueId(), kInvalidUniqueId, EScriptObjectMessage::SuspendedMove); + continue; + } } + + if (x84c_player.get() != ent) + if (!GetPlatformAndDoorObjectList().IsPlatform(*ent)) + CGameCollision::Move(*this, physActor, dt, nullptr); + } } -void CStateManager::MoveActors(float dt) -{ - for (CEntity* ent : GetPhysicsActorObjectList()) - { - if (!ent || !ent->GetActive()) - continue; - CPhysicsActor& physActor = static_cast(*ent); - if (physActor.GetMass() == 0.f) - continue; +void CStateManager::CrossTouchActors() { + bool visits[1024] = {}; + for (CEntity* ent : GetActorObjectList()) { + if (!ent) + continue; + CActor& actor = static_cast(*ent); + if (!actor.GetActive() || !actor.GetCallTouch()) + continue; + std::experimental::optional touchAABB = actor.GetTouchBounds(); + if (!touchAABB) + continue; - if (TCastToPtr ai = physActor) - { - bool doThink = !xf94_29_cinematicPause; - if (doThink && ai->GetAreaIdAlways() != kInvalidAreaId) - { - const CGameArea* area = x850_world->GetAreaAlways(ai->GetAreaIdAlways()); - float occTime; - if (area->IsPostConstructed()) - occTime = area->GetPostConstructed()->x10e4_occludedTime; - else - occTime = 0.f; - if (occTime > 5.f) - doThink = false; - } - if (!doThink) - { - SendScriptMsgAlways(ai->GetUniqueId(), kInvalidUniqueId, - EScriptObjectMessage::SuspendedMove); - continue; - } + CMaterialFilter filter = CMaterialFilter::skPassEverything; + if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Trigger)) + filter = CMaterialFilter::MakeExclude(EMaterialTypes::Trigger); + + rstl::reserved_vector nearList; + BuildNearList(nearList, *touchAABB, filter, &actor); + + for (TUniqueId id : nearList) { + CActor* ent2 = static_cast(ObjectById(id)); + if (!ent2) + continue; + + std::experimental::optional touchAABB2 = ent2->GetTouchBounds(); + if (!ent2->GetActive() || !touchAABB2) + continue; + + if (visits[ent2->GetUniqueId().Value()]) + continue; + + if (touchAABB->intersects(*touchAABB2)) { + actor.Touch(*ent2, *this); + ent2->Touch(actor, *this); + } + + visits[actor.GetUniqueId().Value()] = true; + } + } +} + +void CStateManager::Think(float dt) { + if (x84c_player->x9f4_deathTime > 0.f) { + x84c_player->DoThink(dt, *this); + return; + } + + if (x904_gameState == EGameState::SoftPaused) { + for (CEntity* ent : GetAllObjectList()) + if (TCastToPtr effect = ent) + effect->Think(dt, *this); + } else { + for (CEntity* ent : GetAllObjectList()) { + if (TCastToPtr ai = ent) { + bool doThink = !xf94_29_cinematicPause; + if (doThink && ai->GetAreaIdAlways() != kInvalidAreaId) { + const CGameArea* area = x850_world->GetAreaAlways(ai->GetAreaIdAlways()); + float occTime; + if (area->IsPostConstructed()) + occTime = area->GetPostConstructed()->x10e4_occludedTime; + else + occTime = 0.f; + if (occTime > 5.f) + doThink = false; } - - if (x84c_player.get() != ent) - if (!GetPlatformAndDoorObjectList().IsPlatform(*ent)) - CGameCollision::Move(*this, physActor, dt, nullptr); + if (!doThink) + continue; + } + if (!GetCameraObjectList().GetObjectById(ent->GetUniqueId())) + ent->Think(dt, *this); } + } } -void CStateManager::CrossTouchActors() -{ - bool visits[1024] = {}; - for (CEntity* ent : GetActorObjectList()) - { - if (!ent) - continue; - CActor& actor = static_cast(*ent); - if (!actor.GetActive() || !actor.GetCallTouch()) - continue; - std::experimental::optional touchAABB = actor.GetTouchBounds(); - if (!touchAABB) - continue; +void CStateManager::PostUpdatePlayer(float dt) { x84c_player->PostUpdate(dt, *this); } - CMaterialFilter filter = CMaterialFilter::skPassEverything; - if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Trigger)) - filter = CMaterialFilter::MakeExclude(EMaterialTypes::Trigger); +void CStateManager::ShowPausedHUDMemo(CAssetId strg, float time) { + xf78_hudMessageTime = time; + xf08_pauseHudMessage = strg; + DeferStateTransition(EStateManagerTransition::MessageScreen); +} - rstl::reserved_vector nearList; - BuildNearList(nearList, *touchAABB, filter, &actor); +void CStateManager::ClearGraveyard() { + for (TUniqueId id : x854_objectGraveyard) { + CEntity* ent = GetAllObjectList().GetValidObjectById(id); + RemoveObject(id); + std::default_delete()(ent); + } + x854_objectGraveyard.clear(); +} - for (TUniqueId id : nearList) - { - CActor* ent2 = static_cast(ObjectById(id)); - if (!ent2) - continue; +void CStateManager::FrameBegin(s32 frameCount) { x8d4_inputFrameIdx = frameCount; } - std::experimental::optional touchAABB2 = ent2->GetTouchBounds(); - if (!ent2->GetActive() || !touchAABB2) - continue; +void CStateManager::InitializeState(CAssetId mlvlId, TAreaId aid, CAssetId mreaId) { + bool hadRandom = x900_activeRandom != nullptr; + SetActiveRandomToDefault(); - if (visits[ent2->GetUniqueId().Value()]) - continue; + if (xb3c_initPhase == EInitPhase::LoadWorld) { + CreateStandardGameObjects(); + x850_world.reset(new CWorld(*g_SimplePool, *g_ResFactory, mlvlId)); + xb3c_initPhase = EInitPhase::LoadFirstArea; + } - if (touchAABB->intersects(*touchAABB2)) - { - actor.Touch(*ent2, *this); - ent2->Touch(actor, *this); - } + if (xb3c_initPhase == EInitPhase::LoadFirstArea) { + if (!x8f0_shadowTex.IsLoaded()) + return; + x8f0_shadowTex.GetObj(); - visits[actor.GetUniqueId().Value()] = true; - } + if (!x850_world->CheckWorldComplete(this, aid, mreaId)) + return; + x8cc_nextAreaId = x850_world->x68_curAreaId; + CGameArea* area = x850_world->x18_areas[x8cc_nextAreaId].get(); + if (x850_world->ScheduleAreaToLoad(area, *this)) { + area->StartStreamIn(*this); + return; } -} + xb3c_initPhase = EInitPhase::Done; + } -void CStateManager::Think(float dt) -{ - if (x84c_player->x9f4_deathTime > 0.f) - { - x84c_player->DoThink(dt, *this); - return; + SetCurrentAreaId(x8cc_nextAreaId); + g_GameState->CurrentWorldState().SetAreaId(x8cc_nextAreaId); + x850_world->TravelToArea(x8cc_nextAreaId, *this, true); + UpdateRoomAcoustics(x8cc_nextAreaId); + + for (CEntity* ent : GetAllObjectList()) + SendScriptMsg(ent, kInvalidUniqueId, EScriptObjectMessage::WorldInitialized); + + for (CEntity* ent : GetAllObjectList()) { + CScriptSpawnPoint* sp = TCastToPtr(ent); + if (sp && sp->x30_24_active && sp->FirstSpawn()) { + const zeus::CTransform& xf = sp->GetTransform(); + zeus::CVector3f lookVec = xf.frontVector(); + if (lookVec.canBeNormalized()) { + auto lookXf = zeus::lookAt(xf.origin, xf.origin + lookVec); + x84c_player->Teleport(lookXf, *this, true); + } + + if (!g_GameState->x228_25_initPowerupsAtFirstSpawn) + break; + + g_GameState->x228_25_initPowerupsAtFirstSpawn = false; + for (int i = 0; i < int(CPlayerState::EItemType::Max); ++i) { + CPlayerState::EItemType iType = CPlayerState::EItemType(i); + + u32 spawnPu = sp->GetPowerup(iType); + u32 statePu = x8b8_playerState->GetItemAmount(iType); + if (statePu < spawnPu) + x8b8_playerState->InitializePowerUp(iType, spawnPu - statePu); + + spawnPu = sp->GetPowerup(iType); + statePu = x8b8_playerState->GetItemAmount(iType); + if (statePu < spawnPu) + x8b8_playerState->IncrPickup(iType, spawnPu - statePu); + } } + } - if (x904_gameState == EGameState::SoftPaused) - { - for (CEntity* ent : GetAllObjectList()) - if (TCastToPtr effect = ent) - effect->Think(dt, *this); - } - else - { - for (CEntity* ent : GetAllObjectList()) - { - if (TCastToPtr ai = ent) - { - bool doThink = !xf94_29_cinematicPause; - if (doThink && ai->GetAreaIdAlways() != kInvalidAreaId) - { - const CGameArea* area = x850_world->GetAreaAlways(ai->GetAreaIdAlways()); - float occTime; - if (area->IsPostConstructed()) - occTime = area->GetPostConstructed()->x10e4_occludedTime; - else - occTime = 0.f; - if (occTime > 5.f) - doThink = false; - } - if (!doThink) - continue; - } - if (!GetCameraObjectList().GetObjectById(ent->GetUniqueId())) - ent->Think(dt, *this); - } - } -} + x84c_player->AsyncLoadSuit(*this); + x870_cameraManager->ResetCameras(*this); -void CStateManager::PostUpdatePlayer(float dt) -{ - x84c_player->PostUpdate(dt, *this); -} - -void CStateManager::ShowPausedHUDMemo(CAssetId strg, float time) -{ - xf78_hudMessageTime = time; - xf08_pauseHudMessage = strg; - DeferStateTransition(EStateManagerTransition::MessageScreen); -} - -void CStateManager::ClearGraveyard() -{ - for (TUniqueId id : x854_objectGraveyard) - { - CEntity* ent = GetAllObjectList().GetValidObjectById(id); - RemoveObject(id); - std::default_delete()(ent); - } - x854_objectGraveyard.clear(); -} - -void CStateManager::FrameBegin(s32 frameCount) -{ - x8d4_inputFrameIdx = frameCount; -} - -void CStateManager::InitializeState(CAssetId mlvlId, TAreaId aid, CAssetId mreaId) -{ - bool hadRandom = x900_activeRandom != nullptr; + if (!hadRandom) + ClearActiveRandom(); + else SetActiveRandomToDefault(); - if (xb3c_initPhase == EInitPhase::LoadWorld) - { - CreateStandardGameObjects(); - x850_world.reset(new CWorld(*g_SimplePool, *g_ResFactory, mlvlId)); - xb3c_initPhase = EInitPhase::LoadFirstArea; - } + x880_envFxManager->AsyncLoadResources(*this); +} - if (xb3c_initPhase == EInitPhase::LoadFirstArea) - { - if (!x8f0_shadowTex.IsLoaded()) - return; - x8f0_shadowTex.GetObj(); +void CStateManager::CreateStandardGameObjects() { + float height = g_tweakPlayer->GetPlayerHeight(); + float xyHe = g_tweakPlayer->GetPlayerXYHalfExtent(); + float stepUp = g_tweakPlayer->GetStepUpHeight(); + float stepDown = g_tweakPlayer->GetStepDownHeight(); + float ballRadius = g_tweakPlayer->GetPlayerBallHalfExtent(); + zeus::CAABox pBounds = {{-xyHe, -xyHe, 0.f}, {xyHe, xyHe, height}}; + auto q = zeus::CQuaternion::fromAxisAngle(zeus::CVector3f{0.f, 0.f, 1.f}, zeus::degToRad(129.6f)); + x84c_player.reset( + new CPlayer(AllocateUniqueId(), zeus::CTransform(q), pBounds, g_tweakPlayerRes->xc4_ballTransitionsANCS, + zeus::CVector3f{1.65f, 1.65f, 1.65f}, 200.f, stepUp, stepDown, ballRadius, + CMaterialList(EMaterialTypes::Player, EMaterialTypes::Solid, EMaterialTypes::GroundCollider))); + AddObject(*x84c_player); + x870_cameraManager->CreateStandardCameras(*this); +} - if (!x850_world->CheckWorldComplete(this, aid, mreaId)) - return; - x8cc_nextAreaId = x850_world->x68_curAreaId; - CGameArea* area = x850_world->x18_areas[x8cc_nextAreaId].get(); - if (x850_world->ScheduleAreaToLoad(area, *this)) - { - area->StartStreamIn(*this); - return; +CObjectList* CStateManager::ObjectListById(EGameObjectList type) { + if (type == EGameObjectList::Invalid) + return nullptr; + return x808_objLists[int(type)].get(); +} + +const CObjectList* CStateManager::GetObjectListById(EGameObjectList type) const { + if (type == EGameObjectList::Invalid) + return nullptr; + return x808_objLists[int(type)].get(); +} + +void CStateManager::RemoveObject(TUniqueId uid) { + if (CEntity* ent = GetAllObjectList().GetValidObjectById(uid)) { + if (ent->GetEditorId() != kInvalidEditorId) { + auto search = x890_scriptIdMap.equal_range(ent->GetEditorId()); + for (auto it = search.first; it != search.second;) { + if (it->second == uid) { + it = x890_scriptIdMap.erase(it); + continue; } - xb3c_initPhase = EInitPhase::Done; + ++it; + } } - - SetCurrentAreaId(x8cc_nextAreaId); - g_GameState->CurrentWorldState().SetAreaId(x8cc_nextAreaId); - x850_world->TravelToArea(x8cc_nextAreaId, *this, true); - UpdateRoomAcoustics(x8cc_nextAreaId); - - for (CEntity* ent : GetAllObjectList()) - SendScriptMsg(ent, kInvalidUniqueId, EScriptObjectMessage::WorldInitialized); - - for (CEntity* ent : GetAllObjectList()) - { - CScriptSpawnPoint* sp = TCastToPtr(ent); - if (sp && sp->x30_24_active && sp->FirstSpawn()) - { - const zeus::CTransform& xf = sp->GetTransform(); - zeus::CVector3f lookVec = xf.frontVector(); - if (lookVec.canBeNormalized()) - { - auto lookXf = zeus::lookAt(xf.origin, xf.origin + lookVec); - x84c_player->Teleport(lookXf, *this, true); - } - - if (!g_GameState->x228_25_initPowerupsAtFirstSpawn) - break; - - g_GameState->x228_25_initPowerupsAtFirstSpawn = false; - for (int i = 0; i < int(CPlayerState::EItemType::Max); ++i) - { - CPlayerState::EItemType iType = CPlayerState::EItemType(i); - - u32 spawnPu = sp->GetPowerup(iType); - u32 statePu = x8b8_playerState->GetItemAmount(iType); - if (statePu < spawnPu) - x8b8_playerState->InitializePowerUp(iType, spawnPu - statePu); - - spawnPu = sp->GetPowerup(iType); - statePu = x8b8_playerState->GetItemAmount(iType); - if (statePu < spawnPu) - x8b8_playerState->IncrPickup(iType, spawnPu - statePu); - } - } + if (ent->GetAreaIdAlways() != kInvalidAreaId) { + CGameArea* area = x850_world->GetArea(ent->GetAreaIdAlways()); + if (area->IsPostConstructed()) + area->GetAreaObjects()->RemoveObject(uid); } - - x84c_player->AsyncLoadSuit(*this); - x870_cameraManager->ResetCameras(*this); - - if (!hadRandom) - ClearActiveRandom(); - else - SetActiveRandomToDefault(); - - x880_envFxManager->AsyncLoadResources(*this); + if (TCastToPtr act = ent) + x874_sortedListManager->Remove(act.GetPtr()); + } + for (auto& list : x808_objLists) + list->RemoveObject(uid); } -void CStateManager::CreateStandardGameObjects() -{ - float height = g_tweakPlayer->GetPlayerHeight(); - float xyHe = g_tweakPlayer->GetPlayerXYHalfExtent(); - float stepUp = g_tweakPlayer->GetStepUpHeight(); - float stepDown = g_tweakPlayer->GetStepDownHeight(); - float ballRadius = g_tweakPlayer->GetPlayerBallHalfExtent(); - zeus::CAABox pBounds = {{-xyHe, -xyHe, 0.f}, {xyHe, xyHe, height}}; - auto q = zeus::CQuaternion::fromAxisAngle(zeus::CVector3f{0.f, 0.f, 1.f}, zeus::degToRad(129.6f)); - x84c_player.reset(new CPlayer( - AllocateUniqueId(), zeus::CTransform(q), pBounds, - g_tweakPlayerRes->xc4_ballTransitionsANCS, - zeus::CVector3f{1.65f, 1.65f, 1.65f}, 200.f, stepUp, stepDown, - ballRadius, CMaterialList(EMaterialTypes::Player, - EMaterialTypes::Solid, EMaterialTypes::GroundCollider))); - AddObject(*x84c_player); - x870_cameraManager->CreateStandardCameras(*this); -} - -CObjectList* CStateManager::ObjectListById(EGameObjectList type) -{ - if (type == EGameObjectList::Invalid) - return nullptr; - return x808_objLists[int(type)].get(); -} - -const CObjectList* CStateManager::GetObjectListById(EGameObjectList type) const -{ - if (type == EGameObjectList::Invalid) - return nullptr; - return x808_objLists[int(type)].get(); -} - -void CStateManager::RemoveObject(TUniqueId uid) -{ - if (CEntity* ent = GetAllObjectList().GetValidObjectById(uid)) - { - if (ent->GetEditorId() != kInvalidEditorId) - { - auto search = x890_scriptIdMap.equal_range(ent->GetEditorId()); - for (auto it = search.first; it != search.second;) - { - if (it->second == uid) - { - it = x890_scriptIdMap.erase(it); - continue; - } - ++it; - } - } - if (ent->GetAreaIdAlways() != kInvalidAreaId) - { - CGameArea* area = x850_world->GetArea(ent->GetAreaIdAlways()); - if (area->IsPostConstructed()) - area->GetAreaObjects()->RemoveObject(uid); - } - if (TCastToPtr act = ent) - x874_sortedListManager->Remove(act.GetPtr()); +void CStateManager::UpdateRoomAcoustics(TAreaId aid) { + u32 updateCount = 0; + CScriptRoomAcoustics* updates[10]; + for (CEntity* ent : GetAllObjectList()) { + if (TCastToPtr acoustics = ent) { + if (acoustics->GetAreaIdAlways() != aid || !acoustics->GetActive()) + continue; + updates[updateCount++] = acoustics.GetPtr(); } - for (auto& list : x808_objLists) - list->RemoveObject(uid); + if (updateCount >= 10) + break; + } + + if (!updateCount) { + CScriptRoomAcoustics::DisableAuxCallbacks(); + return; + } + + auto idx = int(updateCount * x900_activeRandom->Float() * 0.99f); + updates[idx]->EnableAuxCallbacks(); } -void CStateManager::UpdateRoomAcoustics(TAreaId aid) -{ - u32 updateCount = 0; - CScriptRoomAcoustics* updates[10]; - for (CEntity* ent : GetAllObjectList()) - { - if (TCastToPtr acoustics = ent) - { - if (acoustics->GetAreaIdAlways() != aid || !acoustics->GetActive()) - continue; - updates[updateCount++] = acoustics.GetPtr(); - } - if (updateCount >= 10) - break; - } +void CStateManager::SetCurrentAreaId(TAreaId aid) { + if (aid != x8cc_nextAreaId) { + x8d0_prevAreaId = x8cc_nextAreaId; + UpdateRoomAcoustics(aid); + x8cc_nextAreaId = aid; + } - if (!updateCount) - { - CScriptRoomAcoustics::DisableAuxCallbacks(); - return; - } - - auto idx = int(updateCount * x900_activeRandom->Float() * 0.99f); - updates[idx]->EnableAuxCallbacks(); + if (aid == kInvalidAreaId) + return; + if (x8c0_mapWorldInfo->IsAreaVisted(aid)) + return; + x8c0_mapWorldInfo->SetAreaVisited(aid, true); + x850_world->GetMapWorld()->RecalculateWorldSphere(*x8c0_mapWorldInfo, *x850_world); } -void CStateManager::SetCurrentAreaId(TAreaId aid) -{ - if (aid != x8cc_nextAreaId) - { - x8d0_prevAreaId = x8cc_nextAreaId; - UpdateRoomAcoustics(aid); - x8cc_nextAreaId = aid; - } - - if (aid == kInvalidAreaId) - return; - if (x8c0_mapWorldInfo->IsAreaVisted(aid)) - return; - x8c0_mapWorldInfo->SetAreaVisited(aid, true); - x850_world->GetMapWorld()->RecalculateWorldSphere(*x8c0_mapWorldInfo, *x850_world); +void CStateManager::AreaUnloaded(TAreaId) { + // Intentionally empty } -void CStateManager::AreaUnloaded(TAreaId) -{ - // Intentionally empty +void CStateManager::PrepareAreaUnload(TAreaId aid) { + for (CEntity* ent : GetAllObjectList()) { + if (TCastToPtr door = ent) + if (door->IsConnectedToArea(*this, aid)) + door->ForceClosed(*this); + } + FreeScriptObjects(aid); } -void CStateManager::PrepareAreaUnload(TAreaId aid) -{ - for (CEntity* ent : GetAllObjectList()) - { - if (TCastToPtr door = ent) - if (door->IsConnectedToArea(*this, aid)) - door->ForceClosed(*this); - } - FreeScriptObjects(aid); -} - -void CStateManager::AreaLoaded(TAreaId aid) -{ - x8bc_relayTracker->SendMsgs(aid, *this); - x880_envFxManager->AreaLoaded(); +void CStateManager::AreaLoaded(TAreaId aid) { + x8bc_relayTracker->SendMsgs(aid, *this); + x880_envFxManager->AreaLoaded(); } void CStateManager::BuildNearList(rstl::reserved_vector& listOut, const zeus::CVector3f& v1, const zeus::CVector3f& v2, float f1, const CMaterialFilter& filter, - const CActor* actor) const -{ - x874_sortedListManager->BuildNearList(listOut, v1, v2, f1, filter, actor); + const CActor* actor) const { + x874_sortedListManager->BuildNearList(listOut, v1, v2, f1, filter, actor); } void CStateManager::BuildColliderList(rstl::reserved_vector& listOut, const CActor& actor, - const zeus::CAABox& aabb) const -{ - x874_sortedListManager->BuildNearList(listOut, actor, aabb); + const zeus::CAABox& aabb) const { + x874_sortedListManager->BuildNearList(listOut, actor, aabb); } void CStateManager::BuildNearList(rstl::reserved_vector& listOut, const zeus::CAABox& aabb, - const CMaterialFilter& filter, const CActor* actor) const -{ - x874_sortedListManager->BuildNearList(listOut, aabb, filter, actor); + const CMaterialFilter& filter, const CActor* actor) const { + x874_sortedListManager->BuildNearList(listOut, aabb, filter, actor); } -void CStateManager::UpdateActorInSortedLists(CActor& act) -{ - if (!act.GetUseInSortedLists() || !act.xe4_27_notInSortedLists) - return; +void CStateManager::UpdateActorInSortedLists(CActor& act) { + if (!act.GetUseInSortedLists() || !act.xe4_27_notInSortedLists) + return; - std::experimental::optional aabb = CalculateObjectBounds(act); - bool actorInLists = x874_sortedListManager->ActorInLists(&act); - if (actorInLists || aabb) - { - act.xe4_27_notInSortedLists = false; - if (actorInLists) - { - if (!act.GetActive() || !aabb) - { - x874_sortedListManager->Remove(&act); - } - else - { - x874_sortedListManager->Move(&act, *aabb); - } - } - else if (act.GetActive() && aabb) - { - x874_sortedListManager->Insert(&act, *aabb); - } + std::experimental::optional aabb = CalculateObjectBounds(act); + bool actorInLists = x874_sortedListManager->ActorInLists(&act); + if (actorInLists || aabb) { + act.xe4_27_notInSortedLists = false; + if (actorInLists) { + if (!act.GetActive() || !aabb) { + x874_sortedListManager->Remove(&act); + } else { + x874_sortedListManager->Move(&act, *aabb); + } + } else if (act.GetActive() && aabb) { + x874_sortedListManager->Insert(&act, *aabb); } + } } -void CStateManager::UpdateSortedLists() -{ - if (!x850_world) - return; - for (CEntity* actor : GetActorObjectList()) - UpdateActorInSortedLists(static_cast(*actor)); +void CStateManager::UpdateSortedLists() { + if (!x850_world) + return; + for (CEntity* actor : GetActorObjectList()) + UpdateActorInSortedLists(static_cast(*actor)); } -std::experimental::optional CStateManager::CalculateObjectBounds(const CActor& actor) -{ - std::experimental::optional bounds = actor.GetTouchBounds(); - if (bounds) - { - zeus::CAABox aabb; - aabb.accumulateBounds(bounds->min); - aabb.accumulateBounds(bounds->max); - if (TCastToConstPtr physAct = actor) - { - zeus::CAABox physAabb = physAct->GetBoundingBox(); - aabb.accumulateBounds(physAabb.min); - aabb.accumulateBounds(physAabb.max); - } - return {aabb}; +std::experimental::optional CStateManager::CalculateObjectBounds(const CActor& actor) { + std::experimental::optional bounds = actor.GetTouchBounds(); + if (bounds) { + zeus::CAABox aabb; + aabb.accumulateBounds(bounds->min); + aabb.accumulateBounds(bounds->max); + if (TCastToConstPtr physAct = actor) { + zeus::CAABox physAabb = physAct->GetBoundingBox(); + aabb.accumulateBounds(physAabb.min); + aabb.accumulateBounds(physAabb.max); } - else - { - if (TCastToConstPtr physAct = actor) - return {physAct->GetBoundingBox()}; - } - return {}; + return {aabb}; + } else { + if (TCastToConstPtr physAct = actor) + return {physAct->GetBoundingBox()}; + } + return {}; } -void CStateManager::AddObject(CEntity& ent) -{ - if (ent.GetEditorId() != kInvalidEditorId) - x890_scriptIdMap.insert(std::make_pair(ent.GetEditorId(), ent.GetUniqueId())); - for (auto& list : x808_objLists) - list->AddObject(ent); +void CStateManager::AddObject(CEntity& ent) { + if (ent.GetEditorId() != kInvalidEditorId) + x890_scriptIdMap.insert(std::make_pair(ent.GetEditorId(), ent.GetUniqueId())); + for (auto& list : x808_objLists) + list->AddObject(ent); - if (ent.GetAreaIdAlways() == kInvalidAreaId && x84c_player && - ent.GetUniqueId() != x84c_player->GetUniqueId()) - ent.x4_areaId = x84c_player->GetAreaIdAlways(); - if (ent.GetAreaIdAlways() != kInvalidAreaId) - { - CGameArea* area = x850_world->GetArea(ent.GetAreaIdAlways()); - if (area->IsPostConstructed()) - area->GetAreaObjects()->AddObject(ent); - } + if (ent.GetAreaIdAlways() == kInvalidAreaId && x84c_player && ent.GetUniqueId() != x84c_player->GetUniqueId()) + ent.x4_areaId = x84c_player->GetAreaIdAlways(); + if (ent.GetAreaIdAlways() != kInvalidAreaId) { + CGameArea* area = x850_world->GetArea(ent.GetAreaIdAlways()); + if (area->IsPostConstructed()) + area->GetAreaObjects()->AddObject(ent); + } - if (TCastToPtr act = ent) - UpdateActorInSortedLists(*act.GetPtr()); + if (TCastToPtr act = ent) + UpdateActorInSortedLists(*act.GetPtr()); - ent.AcceptScriptMsg(EScriptObjectMessage::Registered, kInvalidUniqueId, *this); + ent.AcceptScriptMsg(EScriptObjectMessage::Registered, kInvalidUniqueId, *this); - if (ent.GetAreaIdAlways() != kInvalidAreaId && x850_world) - { - CGameArea* area = x850_world->GetArea(ent.GetAreaIdAlways()); - if (area->IsValidated()) - SendScriptMsg(&ent, kInvalidUniqueId, EScriptObjectMessage::InitializedInArea); - } + if (ent.GetAreaIdAlways() != kInvalidAreaId && x850_world) { + CGameArea* area = x850_world->GetArea(ent.GetAreaIdAlways()); + if (area->IsValidated()) + SendScriptMsg(&ent, kInvalidUniqueId, EScriptObjectMessage::InitializedInArea); + } - - if (sm_logScripting && sm_logScripting->toBoolean()) - LogModule.report(logvisor::Info, "Added '%s'", ent.GetName().data()); + if (sm_logScripting && sm_logScripting->toBoolean()) + LogModule.report(logvisor::Info, "Added '%s'", ent.GetName().data()); } -void CStateManager::AddObject(CEntity* ent) -{ - if (ent) - AddObject(*ent); +void CStateManager::AddObject(CEntity* ent) { + if (ent) + AddObject(*ent); } -CRayCastResult CStateManager::RayStaticIntersection(const zeus::CVector3f& pos, const zeus::CVector3f& dir, float length, - const CMaterialFilter& filter) const -{ - return CGameCollision::RayStaticIntersection(*this, pos, dir, length, filter); +CRayCastResult CStateManager::RayStaticIntersection(const zeus::CVector3f& pos, const zeus::CVector3f& dir, + float length, const CMaterialFilter& filter) const { + return CGameCollision::RayStaticIntersection(*this, pos, dir, length, filter); } CRayCastResult CStateManager::RayWorldIntersection(TUniqueId& idOut, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float length, const CMaterialFilter& filter, - const rstl::reserved_vector& list) const -{ - return CGameCollision::RayWorldIntersection(*this, idOut, pos, dir, length, filter, list); + const zeus::CVector3f& dir, float length, + const CMaterialFilter& filter, + const rstl::reserved_vector& list) const { + return CGameCollision::RayWorldIntersection(*this, idOut, pos, dir, length, filter, list); } -void CStateManager::UpdateObjectInLists(CEntity& ent) -{ - for (auto& list : x808_objLists) - { - if (list->GetValidObjectById(ent.GetUniqueId())) - if (!list->IsQualified(ent)) - list->RemoveObject(ent.GetUniqueId()); - if (!list->GetValidObjectById(ent.GetUniqueId())) - list->AddObject(ent); +void CStateManager::UpdateObjectInLists(CEntity& ent) { + for (auto& list : x808_objLists) { + if (list->GetValidObjectById(ent.GetUniqueId())) + if (!list->IsQualified(ent)) + list->RemoveObject(ent.GetUniqueId()); + if (!list->GetValidObjectById(ent.GetUniqueId())) + list->AddObject(ent); + } +} + +TUniqueId CStateManager::AllocateUniqueId() { + const s16 lastIndex = x0_nextFreeIndex; + s16 ourIndex; + do { + ourIndex = x0_nextFreeIndex; + x0_nextFreeIndex = (x0_nextFreeIndex + 1) & 0x3ff; + if (x0_nextFreeIndex == lastIndex) + LogModule.report(logvisor::Fatal, "Object List Full!"); + } while (GetAllObjectList().GetObjectByIndex(ourIndex) != nullptr); + + x8_idArr[ourIndex] = (x8_idArr[ourIndex] + 1) & 0x3f; + if (TUniqueId(ourIndex, x8_idArr[ourIndex]) == kInvalidUniqueId) + x8_idArr[ourIndex] = 0; + + return TUniqueId(ourIndex, x8_idArr[ourIndex]); +} + +void CStateManager::DeferStateTransition(EStateManagerTransition t) { + if (t == EStateManagerTransition::InGame) { + if (xf90_deferredTransition != EStateManagerTransition::InGame) { + x850_world->SetLoadPauseState(false); + xf90_deferredTransition = EStateManagerTransition::InGame; } -} - -TUniqueId CStateManager::AllocateUniqueId() -{ - const s16 lastIndex = x0_nextFreeIndex; - s16 ourIndex; - do - { - ourIndex = x0_nextFreeIndex; - x0_nextFreeIndex = (x0_nextFreeIndex + 1) & 0x3ff; - if (x0_nextFreeIndex == lastIndex) - LogModule.report(logvisor::Fatal, "Object List Full!"); + } else { + if (xf90_deferredTransition == EStateManagerTransition::InGame) { + x850_world->SetLoadPauseState(true); + xf90_deferredTransition = t; } - while (GetAllObjectList().GetObjectByIndex(ourIndex) != nullptr); - - x8_idArr[ourIndex] = (x8_idArr[ourIndex] + 1) & 0x3f; - if (TUniqueId(ourIndex, x8_idArr[ourIndex]) == kInvalidUniqueId) - x8_idArr[ourIndex] = 0; - - return TUniqueId(ourIndex, x8_idArr[ourIndex]); + } } -void CStateManager::DeferStateTransition(EStateManagerTransition t) -{ - if (t == EStateManagerTransition::InGame) - { - if (xf90_deferredTransition != EStateManagerTransition::InGame) - { - x850_world->SetLoadPauseState(false); - xf90_deferredTransition = EStateManagerTransition::InGame; - } - } - else - { - if (xf90_deferredTransition == EStateManagerTransition::InGame) - { - x850_world->SetLoadPauseState(true); - xf90_deferredTransition = t; - } +bool CStateManager::CanShowMapScreen() const { + const CHintOptions::SHintState* curDispHint = g_GameState->HintOptions().GetCurrentDisplayedHint(); + if (!curDispHint || curDispHint->CanContinue()) + return true; + return false; +} + +std::pair CStateManager::CalculateScanCompletionRate() const { + u32 num = 0; + u32 denom = 0; + int idx = 0; + for (const std::pair& scan : x8b8_playerState->GetScanTimes()) { + CSaveWorld::EScanCategory category = g_MemoryCardSys->GetScanStates()[idx++].second; + if (category != CSaveWorld::EScanCategory::None && category != CSaveWorld::EScanCategory::Research) { + ++denom; + if (scan.second == 1.f) + ++num; } + } + return {num, denom}; } -bool CStateManager::CanShowMapScreen() const -{ - const CHintOptions::SHintState* curDispHint = g_GameState->HintOptions().GetCurrentDisplayedHint(); - if (!curDispHint || curDispHint->CanContinue()) - return true; - return false; +void CStateManager::SetBossParams(TUniqueId bossId, float maxEnergy, u32 stringIdx) { + xf18_bossId = bossId; + xf1c_totalBossEnergy = maxEnergy; + xf20_bossStringIdx = stringIdx; } -std::pair CStateManager::CalculateScanCompletionRate() const -{ - u32 num = 0; - u32 denom = 0; - int idx = 0; - for (const std::pair& scan : x8b8_playerState->GetScanTimes()) - { - CSaveWorld::EScanCategory category = g_MemoryCardSys->GetScanStates()[idx++].second; - if (category != CSaveWorld::EScanCategory::None && category != CSaveWorld::EScanCategory::Research) - { - ++denom; - if (scan.second == 1.f) - ++num; - } - } - return {num, denom}; -} - -void CStateManager::SetBossParams(TUniqueId bossId, float maxEnergy, u32 stringIdx) -{ - xf18_bossId = bossId; - xf1c_totalBossEnergy = maxEnergy; - xf20_bossStringIdx = stringIdx; -} - -float CStateManager::IntegrateVisorFog(float f) const -{ - if (x8b8_playerState->GetActiveVisor(*this) == CPlayerState::EPlayerVisor::Scan) - return (1.f - x8b8_playerState->GetVisorTransitionFactor()) * f; - return f; +float CStateManager::IntegrateVisorFog(float f) const { + if (x8b8_playerState->GetActiveVisor(*this) == CPlayerState::EPlayerVisor::Scan) + return (1.f - x8b8_playerState->GetVisorTransitionFactor()) * f; + return f; } float CStateManager::g_EscapeShakeCountdown; bool CStateManager::g_EscapeShakeCountdownInit = false; -} +} // namespace urde diff --git a/Runtime/CStateManager.hpp b/Runtime/CStateManager.hpp index 4574fbbb4..a7f804829 100644 --- a/Runtime/CStateManager.hpp +++ b/Runtime/CStateManager.hpp @@ -22,8 +22,7 @@ #include "Camera/CCameraShakeData.hpp" #include "Graphics/Shaders/CColoredQuadFilter.hpp" -namespace urde -{ +namespace urde { class CRelayTracker; class CMapWorldInfo; class CPlayerState; @@ -46,437 +45,394 @@ class CTexture; class CWorldLayerState; class CProjectedShadow; -namespace MP1 -{ +namespace MP1 { class CMFGameLoader; } -struct SScriptObjectStream -{ - //CEntity* x0_obj; - EScriptObjectType x0_type; - u32 x4_position; - u32 x8_length; +struct SScriptObjectStream { + // CEntity* x0_obj; + EScriptObjectType x0_type; + u32 x4_position; + u32 x8_length; }; -struct SOnScreenTex -{ - CAssetId x0_id; - zeus::CVector2i x4_origin; - zeus::CVector2i xc_extent; +struct SOnScreenTex { + CAssetId x0_id; + zeus::CVector2i x4_origin; + zeus::CVector2i xc_extent; }; -enum class EStateManagerTransition -{ - InGame, - MapScreen, - PauseGame, - LogBook, - SaveGame, - MessageScreen -}; +enum class EStateManagerTransition { InGame, MapScreen, PauseGame, LogBook, SaveGame, MessageScreen }; -enum class EThermalDrawFlag -{ - Hot, - Cold, - Bypass -}; +enum class EThermalDrawFlag { Hot, Cold, Bypass }; + +class CStateManager { + friend class MP1::CMFGameLoader; -class CStateManager -{ - friend class MP1::CMFGameLoader; public: - enum class EGameState - { - Running, - SoftPaused, - Paused - }; + enum class EGameState { Running, SoftPaused, Paused }; private: - s16 x0_nextFreeIndex = 0; - u16 x8_idArr[1024] = {}; + s16 x0_nextFreeIndex = 0; + u16 x8_idArr[1024] = {}; - /* - std::unique_ptr x80c_allObjs; - std::unique_ptr x814_actorObjs; - std::unique_ptr x81c_physActorObjs; - std::unique_ptr x824_cameraObjs; - std::unique_ptr x82c_lightObjs; - std::unique_ptr x834_listenAiObjs; - std::unique_ptr x83c_aiWaypointObjs; - std::unique_ptr x844_platformAndDoorObjs; - */ - std::unique_ptr x808_objLists[8] = - {std::make_unique(EGameObjectList::All), - std::make_unique(), - std::make_unique(), - std::make_unique(), - std::make_unique(), - std::make_unique(), - std::make_unique(), - std::make_unique()}; + /* + std::unique_ptr x80c_allObjs; + std::unique_ptr x814_actorObjs; + std::unique_ptr x81c_physActorObjs; + std::unique_ptr x824_cameraObjs; + std::unique_ptr x82c_lightObjs; + std::unique_ptr x834_listenAiObjs; + std::unique_ptr x83c_aiWaypointObjs; + std::unique_ptr x844_platformAndDoorObjs; + */ + std::unique_ptr x808_objLists[8] = {std::make_unique(EGameObjectList::All), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique(), + std::make_unique()}; - std::unique_ptr x84c_player; - std::unique_ptr x850_world; + std::unique_ptr x84c_player; + std::unique_ptr x850_world; - /* Used to be a list of 32-element reserved_vectors */ - std::vector x854_objectGraveyard; + /* Used to be a list of 32-element reserved_vectors */ + std::vector x854_objectGraveyard; - struct CStateManagerContainer - { - CCameraManager x0_cameraManager; - CSortedListManager x3c0_sortedListManager; - CWeaponMgr xe3d8_weaponManager; - CFluidPlaneManager xe3ec_fluidPlaneManager; - CEnvFxManager xe510_envFxManager; - CActorModelParticles xf168_actorModelParticles; - CRumbleManager xf250_rumbleManager; - u32 xf344_ = 0; - rstl::reserved_vector xf370_; - rstl::reserved_vector xf39c_renderLast; + struct CStateManagerContainer { + CCameraManager x0_cameraManager; + CSortedListManager x3c0_sortedListManager; + CWeaponMgr xe3d8_weaponManager; + CFluidPlaneManager xe3ec_fluidPlaneManager; + CEnvFxManager xe510_envFxManager; + CActorModelParticles xf168_actorModelParticles; + CRumbleManager xf250_rumbleManager; + u32 xf344_ = 0; + rstl::reserved_vector xf370_; + rstl::reserved_vector xf39c_renderLast; + }; + std::unique_ptr x86c_stateManagerContainer; + CCameraManager* x870_cameraManager = nullptr; + CSortedListManager* x874_sortedListManager = nullptr; + CWeaponMgr* x878_weaponManager = nullptr; + CFluidPlaneManager* x87c_fluidPlaneManager = nullptr; + CEnvFxManager* x880_envFxManager = nullptr; + CActorModelParticles* x884_actorModelParticles = nullptr; + CRumbleManager* x88c_rumbleManager = nullptr; + + std::multimap x890_scriptIdMap; + std::map x8a4_loadedScriptObjects; + + std::shared_ptr x8b8_playerState; + std::shared_ptr x8bc_relayTracker; + std::shared_ptr x8c0_mapWorldInfo; + std::shared_ptr x8c4_worldTransManager; + std::shared_ptr x8c8_worldLayerState; + + TAreaId x8cc_nextAreaId = 0; + TAreaId x8d0_prevAreaId = kInvalidAreaId; + // u32 x8d0_extFrameIdx = 0; + u32 x8d4_inputFrameIdx = 0; + u32 x8d8_updateFrameIdx = 0; + u32 x8dc_objectDrawToken = 0; + + std::vector x8e0_dynamicLights; + + TLockedToken x8f0_shadowTex; /* DefaultShadow in MiscData */ + CRandom16 x8fc_random; + CRandom16* x900_activeRandom = nullptr; + EGameState x904_gameState = EGameState::Running; + u32 x908_loaderCount = 0; + FScriptLoader x90c_loaderFuncs[int(EScriptObjectType::ScriptObjectTypeMAX)] = {}; + + bool xab0_worldLoaded = false; + + enum class EInitPhase { LoadWorld, LoadFirstArea, Done } xb3c_initPhase = EInitPhase::LoadWorld; + + std::set xb40_uniqueInstanceNames; + + CFinalInput xb54_finalInput; + CCameraFilterPassPoly xb84_camFilterPasses[9]; // size: 0x2c + CCameraBlurPass xd14_camBlurPasses[9]; // size: 0x34 + + s32 xeec_hintIdx = -1; + u32 xef0_hintPeriods = 0; + SOnScreenTex xef4_pendingScreenTex; + CAssetId xf08_pauseHudMessage; + float xf0c_escapeTimer = 0.f; + float xf10_escapeTotalTime = 0.f; + float xf14_curTimeMod900 = 0.f; + TUniqueId xf18_bossId = kInvalidUniqueId; + float xf1c_totalBossEnergy = 0.f; + u32 xf20_bossStringIdx = 0; + float xf24_thermColdScale1 = 0.f; + float xf28_thermColdScale2 = 0.f; + zeus::CVector2f xf2c_viewportScale = {1.f, 1.f}; + EThermalDrawFlag xf34_thermalFlag = EThermalDrawFlag::Bypass; + TUniqueId xf38_skipCineSpecialFunc = kInvalidUniqueId; + std::list xf3c_; + std::list xf54_activeParasites; + TUniqueId xf6c_playerActorHead = kInvalidUniqueId; + u32 xf70_ = 0; + + TUniqueId xf74_lastTrigger = kInvalidUniqueId; + TUniqueId xf76_lastRelay = kInvalidUniqueId; + + float xf78_hudMessageTime = 0.f; + CProjectedShadow* xf7c_projectedShadow = nullptr; + u32 xf80_hudMessageFrameCount = 0; + s32 xf84_ = -1; + CAssetId xf88_; + float xf8c_ = 0.f; + EStateManagerTransition xf90_deferredTransition = EStateManagerTransition::InGame; + + union { + struct { + bool xf94_24_readyToRender : 1; + bool xf94_25_quitGame : 1; + bool xf94_26_generatingObject : 1; + bool xf94_27_inMapScreen : 1; + bool xf94_28_inSaveUI : 1; + bool xf94_29_cinematicPause : 1; + bool xf94_30_fullThreat : 1; }; - std::unique_ptr x86c_stateManagerContainer; - CCameraManager* x870_cameraManager = nullptr; - CSortedListManager* x874_sortedListManager = nullptr; - CWeaponMgr* x878_weaponManager = nullptr; - CFluidPlaneManager* x87c_fluidPlaneManager = nullptr; - CEnvFxManager* x880_envFxManager = nullptr; - CActorModelParticles* x884_actorModelParticles = nullptr; - CRumbleManager* x88c_rumbleManager = nullptr; + u32 xf94_ = 0; + }; - std::multimap x890_scriptIdMap; - std::map x8a4_loadedScriptObjects; + CColoredQuadFilter m_deathWhiteout = {EFilterType::Add}; + CColoredQuadFilter m_escapeWhiteout = {EFilterType::Add}; + bool m_warping = false; - std::shared_ptr x8b8_playerState; - std::shared_ptr x8bc_relayTracker; - std::shared_ptr x8c0_mapWorldInfo; - std::shared_ptr x8c4_worldTransManager; - std::shared_ptr x8c8_worldLayerState; - - TAreaId x8cc_nextAreaId = 0; - TAreaId x8d0_prevAreaId = kInvalidAreaId; - //u32 x8d0_extFrameIdx = 0; - u32 x8d4_inputFrameIdx = 0; - u32 x8d8_updateFrameIdx = 0; - u32 x8dc_objectDrawToken = 0; - - std::vector x8e0_dynamicLights; - - TLockedToken x8f0_shadowTex; /* DefaultShadow in MiscData */ - CRandom16 x8fc_random; - CRandom16* x900_activeRandom = nullptr; - EGameState x904_gameState = EGameState::Running; - u32 x908_loaderCount = 0; - FScriptLoader x90c_loaderFuncs[int(EScriptObjectType::ScriptObjectTypeMAX)] = {}; - - bool xab0_worldLoaded = false; - - enum class EInitPhase - { - LoadWorld, - LoadFirstArea, - Done - } xb3c_initPhase = EInitPhase::LoadWorld; - - std::set xb40_uniqueInstanceNames; - - CFinalInput xb54_finalInput; - CCameraFilterPassPoly xb84_camFilterPasses[9]; // size: 0x2c - CCameraBlurPass xd14_camBlurPasses[9]; // size: 0x34 - - s32 xeec_hintIdx = -1; - u32 xef0_hintPeriods = 0; - SOnScreenTex xef4_pendingScreenTex; - CAssetId xf08_pauseHudMessage; - float xf0c_escapeTimer = 0.f; - float xf10_escapeTotalTime = 0.f; - float xf14_curTimeMod900 = 0.f; - TUniqueId xf18_bossId = kInvalidUniqueId; - float xf1c_totalBossEnergy = 0.f; - u32 xf20_bossStringIdx = 0; - float xf24_thermColdScale1 = 0.f; - float xf28_thermColdScale2 = 0.f; - zeus::CVector2f xf2c_viewportScale = {1.f, 1.f}; - EThermalDrawFlag xf34_thermalFlag = EThermalDrawFlag::Bypass; - TUniqueId xf38_skipCineSpecialFunc = kInvalidUniqueId; - std::list xf3c_; - std::list xf54_activeParasites; - TUniqueId xf6c_playerActorHead = kInvalidUniqueId; - u32 xf70_ = 0; - - TUniqueId xf74_lastTrigger = kInvalidUniqueId; - TUniqueId xf76_lastRelay = kInvalidUniqueId; - - float xf78_hudMessageTime = 0.f; - CProjectedShadow* xf7c_projectedShadow = nullptr; - u32 xf80_hudMessageFrameCount = 0; - s32 xf84_ = -1; - CAssetId xf88_; - float xf8c_ = 0.f; - EStateManagerTransition xf90_deferredTransition = EStateManagerTransition::InGame; - - union - { - struct - { - bool xf94_24_readyToRender : 1; - bool xf94_25_quitGame : 1; - bool xf94_26_generatingObject : 1; - bool xf94_27_inMapScreen : 1; - bool xf94_28_inSaveUI : 1; - bool xf94_29_cinematicPause : 1; - bool xf94_30_fullThreat : 1; - }; - u32 xf94_ = 0; - }; - - CColoredQuadFilter m_deathWhiteout = { EFilterType::Add }; - CColoredQuadFilter m_escapeWhiteout = { EFilterType::Add }; - bool m_warping = false; - - void UpdateThermalVisor(); - static void RendererDrawCallback(const void*, const void*, int); + void UpdateThermalVisor(); + static void RendererDrawCallback(const void*, const void*, int); public: - CStateManager(const std::weak_ptr&, - const std::weak_ptr&, - const std::weak_ptr&, - const std::weak_ptr&, - const std::weak_ptr&); - ~CStateManager(); + CStateManager(const std::weak_ptr&, const std::weak_ptr&, + const std::weak_ptr&, const std::weak_ptr&, + const std::weak_ptr&); + ~CStateManager(); - u32 GetInputFrameIdx() const { return x8d4_inputFrameIdx; } - bool RenderLast(TUniqueId); - void AddDrawableActorPlane(const CActor& actor, const zeus::CPlane&, const zeus::CAABox& aabb) const; - void AddDrawableActor(const CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const; - bool SpecialSkipCinematic(); - TAreaId GetVisAreaId() const; - s32 GetWeaponIdCount(TUniqueId, EWeaponType); - void RemoveWeaponId(TUniqueId, EWeaponType); - void AddWeaponId(TUniqueId, EWeaponType); - void UpdateEscapeSequenceTimer(float); - float GetEscapeSequenceTimer() const { return xf0c_escapeTimer; } - void ResetEscapeSequenceTimer(float); - void SetupParticleHook(const CActor& actor) const; - void MurderScriptInstanceNames(); - std::string HashInstanceName(CInputStream& in); - void SetActorAreaId(CActor& actor, TAreaId); - void TouchSky() const; - void TouchPlayerActor(); - void DrawSpaceWarp(const zeus::CVector3f&, float) const; - void DrawReflection(const zeus::CVector3f&); - static void ReflectionDrawer(void*, const zeus::CVector3f&); - void CacheReflection(); - bool CanCreateProjectile(TUniqueId, EWeaponType, int) const; - const std::vector& GetDynamicLightList() const { return x8e0_dynamicLights; } - void BuildDynamicLightListForWorld(); - void DrawDebugStuff() const; - void RenderCamerasAndAreaLights() const; - void DrawE3DeathEffect() const; - void DrawAdditionalFilters() const; - zeus::CFrustum SetupDrawFrustum(const SViewport& vp) const; - zeus::CFrustum SetupViewForDraw(const SViewport& vp) const; - void ResetViewAfterDraw(const SViewport& backupViewport, const zeus::CTransform& backupViewMatrix) const; - void DrawWorld() const; - void SetupFogForArea(TAreaId area) const; - void SetupFogForArea(const CGameArea& area) const; - bool SetupFogForDraw() const; - void PreRender(); - void GetCharacterRenderMaskAndTarget(bool thawed, int& mask, int& target) const; - bool GetVisSetForArea(TAreaId, TAreaId, CPVSVisSet& setOut) const; - void RecursiveDrawTree(TUniqueId) const; - void SendScriptMsg(CEntity* dest, TUniqueId src, EScriptObjectMessage msg); - void SendScriptMsg(TUniqueId dest, TUniqueId src, EScriptObjectMessage msg); - void SendScriptMsg(TUniqueId src, TEditorId dest, - EScriptObjectMessage msg, EScriptObjectState state); - void SendScriptMsgAlways(TUniqueId dest, TUniqueId src, EScriptObjectMessage); - void FreeScriptObjects(TAreaId); - void FreeScriptObject(TUniqueId); - std::pair GetBuildForScript(TEditorId) const; - TEditorId GetEditorIdForUniqueId(TUniqueId) const; - TUniqueId GetIdForScript(TEditorId) const; - std::pair::const_iterator, - std::multimap::const_iterator> - GetIdListForScript(TEditorId) const; - std::multimap::const_iterator GetIdListEnd() const { return x890_scriptIdMap.cend(); }; - void LoadScriptObjects(TAreaId, CInputStream& in, std::vector& idsOut); - void InitializeScriptObjects(const std::vector& objIds); - std::pair LoadScriptObject(TAreaId, EScriptObjectType, u32, CInputStream& in); - std::pair GenerateObject(TEditorId); - void InitScriptObjects(const std::vector& ids); - void InformListeners(const zeus::CVector3f&, EListenNoiseType); - void ApplyKnockBack(CActor& actor, const CDamageInfo& info, - const CDamageVulnerability&, const zeus::CVector3f&, float); - void KnockBackPlayer(CPlayer& player, const zeus::CVector3f& pos, float power, float resistance); - void ApplyDamageToWorld(TUniqueId, const CActor&, const zeus::CVector3f&, - const CDamageInfo& info, const CMaterialFilter&); - void ProcessRadiusDamage(const CActor&, CActor&, TUniqueId senderId, - const CDamageInfo& info, const CMaterialFilter&); - void ApplyRadiusDamage(const CActor&, const zeus::CVector3f&, CActor&, - const CDamageInfo& info); - bool TestRayDamage(const zeus::CVector3f& pos, const CActor& damagee, - const rstl::reserved_vector& nearList) const; - bool RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end, - const CMaterialFilter& filter, const CActor* damagee) const; - bool RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end, - const rstl::reserved_vector& nearList, - const CMaterialFilter& filter, const CActor* damagee) const; - bool RayCollideWorldInternal(const zeus::CVector3f& start, const zeus::CVector3f& end, - const CMaterialFilter& filter, - const rstl::reserved_vector& nearList, - const CActor* damagee) const; - bool MultiRayCollideWorld(const zeus::CMRay& ray, const CMaterialFilter& filter) const; - void TestBombHittingWater(const CActor& damager, const zeus::CVector3f& pos, CActor& damagee); - bool ApplyLocalDamage(const zeus::CVector3f&, const zeus::CVector3f&, CActor&, float, - const CWeaponMode&); - bool ApplyDamage(TUniqueId damagerId, TUniqueId damageeId, TUniqueId radiusSender, - const CDamageInfo& info, const CMaterialFilter& filter, - const zeus::CVector3f& knockbackVec); - void UpdateAreaSounds(); - void FrameEnd(); - void ProcessPlayerInput(); - void SetGameState(EGameState state); - EGameState GetGameState() const { return x904_gameState; } - void ProcessInput(const CFinalInput& input); - void UpdateGraphicsTiming(float dt); - void Update(float dt); - void UpdateGameState(); - void UpdateHintState(float dt); - void PreThinkObjects(float dt); - void MovePlatforms(float dt); - void MoveActors(float dt); - void CrossTouchActors(); - void Think(float dt); - void PostUpdatePlayer(float dt); - void ShowPausedHUDMemo(CAssetId strg, float time); - void ClearGraveyard(); - void FrameBegin(s32 frameCount); - void InitializeState(CAssetId mlvlId, TAreaId aid, CAssetId mreaId); - void CreateStandardGameObjects(); - const std::unique_ptr& GetObjectList() const { return x808_objLists[0]; } - CObjectList* ObjectListById(EGameObjectList type); - const CObjectList* GetObjectListById(EGameObjectList type) const; - void RemoveObject(TUniqueId); - void UpdateRoomAcoustics(TAreaId); - TAreaId GetNextAreaId() const { return x8cc_nextAreaId; } - void SetCurrentAreaId(TAreaId); - CEntity* ObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); } - const CEntity* GetObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); } - void AreaUnloaded(TAreaId); - void PrepareAreaUnload(TAreaId); - void AreaLoaded(TAreaId); - void BuildNearList(rstl::reserved_vector& listOut, - const zeus::CVector3f&, const zeus::CVector3f&, float, - const CMaterialFilter&, const CActor*) const; - void BuildColliderList(rstl::reserved_vector& listOut, - const CActor&, const zeus::CAABox&) const; - void BuildNearList(rstl::reserved_vector& listOut, - const zeus::CAABox&, const CMaterialFilter&, const CActor*) const; - void UpdateActorInSortedLists(CActor&); - void UpdateSortedLists(); - std::experimental::optional CalculateObjectBounds(const CActor&); - void AddObject(CEntity&); - void AddObject(CEntity*); - CRayCastResult RayStaticIntersection(const zeus::CVector3f& pos, const zeus::CVector3f& dir, float length, - const CMaterialFilter& filter) const; - CRayCastResult RayWorldIntersection(TUniqueId& idOut, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float length, const CMaterialFilter& filter, - const rstl::reserved_vector& list) const; - void UpdateObjectInLists(CEntity&); - TUniqueId AllocateUniqueId(); - void DeferStateTransition(EStateManagerTransition t); - EStateManagerTransition GetDeferredStateTransition() const { return xf90_deferredTransition; } - bool CanShowMapScreen() const; - TUniqueId GetSkipCinematicSpecialFunction() const { return xf38_skipCineSpecialFunc; } - void SetSkipCinematicSpecialFunction(TUniqueId id) { xf38_skipCineSpecialFunc = id; } - float GetHUDMessageTime() const { return xf78_hudMessageTime; } - u32 GetHUDMessageFrameCount() const { return xf80_hudMessageFrameCount; } - CAssetId GetPauseHUDMessage() const { return xf08_pauseHudMessage; } - void IncrementHUDMessageFrameCounter() { ++xf80_hudMessageFrameCount; } - bool ShouldQuitGame() const { return xf94_25_quitGame; } - void SetShouldQuitGame(bool should) { xf94_25_quitGame = should; } - void SetInSaveUI(bool b) { xf94_28_inSaveUI = b; } - bool GetInSaveUI() const { return xf94_28_inSaveUI; } - void SetInMapScreen(bool b) { xf94_27_inMapScreen = b; } - bool GetInMapScreen() const { return xf94_27_inMapScreen; } - bool IsFullThreat() const { return xf94_30_fullThreat; } - void SetIsFullThreat(bool v) { xf94_30_fullThreat = v; } + u32 GetInputFrameIdx() const { return x8d4_inputFrameIdx; } + bool RenderLast(TUniqueId); + void AddDrawableActorPlane(const CActor& actor, const zeus::CPlane&, const zeus::CAABox& aabb) const; + void AddDrawableActor(const CActor& actor, const zeus::CVector3f& vec, const zeus::CAABox& aabb) const; + bool SpecialSkipCinematic(); + TAreaId GetVisAreaId() const; + s32 GetWeaponIdCount(TUniqueId, EWeaponType); + void RemoveWeaponId(TUniqueId, EWeaponType); + void AddWeaponId(TUniqueId, EWeaponType); + void UpdateEscapeSequenceTimer(float); + float GetEscapeSequenceTimer() const { return xf0c_escapeTimer; } + void ResetEscapeSequenceTimer(float); + void SetupParticleHook(const CActor& actor) const; + void MurderScriptInstanceNames(); + std::string HashInstanceName(CInputStream& in); + void SetActorAreaId(CActor& actor, TAreaId); + void TouchSky() const; + void TouchPlayerActor(); + void DrawSpaceWarp(const zeus::CVector3f&, float) const; + void DrawReflection(const zeus::CVector3f&); + static void ReflectionDrawer(void*, const zeus::CVector3f&); + void CacheReflection(); + bool CanCreateProjectile(TUniqueId, EWeaponType, int) const; + const std::vector& GetDynamicLightList() const { return x8e0_dynamicLights; } + void BuildDynamicLightListForWorld(); + void DrawDebugStuff() const; + void RenderCamerasAndAreaLights() const; + void DrawE3DeathEffect() const; + void DrawAdditionalFilters() const; + zeus::CFrustum SetupDrawFrustum(const SViewport& vp) const; + zeus::CFrustum SetupViewForDraw(const SViewport& vp) const; + void ResetViewAfterDraw(const SViewport& backupViewport, const zeus::CTransform& backupViewMatrix) const; + void DrawWorld() const; + void SetupFogForArea(TAreaId area) const; + void SetupFogForArea(const CGameArea& area) const; + bool SetupFogForDraw() const; + void PreRender(); + void GetCharacterRenderMaskAndTarget(bool thawed, int& mask, int& target) const; + bool GetVisSetForArea(TAreaId, TAreaId, CPVSVisSet& setOut) const; + void RecursiveDrawTree(TUniqueId) const; + void SendScriptMsg(CEntity* dest, TUniqueId src, EScriptObjectMessage msg); + void SendScriptMsg(TUniqueId dest, TUniqueId src, EScriptObjectMessage msg); + void SendScriptMsg(TUniqueId src, TEditorId dest, EScriptObjectMessage msg, EScriptObjectState state); + void SendScriptMsgAlways(TUniqueId dest, TUniqueId src, EScriptObjectMessage); + void FreeScriptObjects(TAreaId); + void FreeScriptObject(TUniqueId); + std::pair GetBuildForScript(TEditorId) const; + TEditorId GetEditorIdForUniqueId(TUniqueId) const; + TUniqueId GetIdForScript(TEditorId) const; + std::pair::const_iterator, std::multimap::const_iterator> + GetIdListForScript(TEditorId) const; + std::multimap::const_iterator GetIdListEnd() const { return x890_scriptIdMap.cend(); }; + void LoadScriptObjects(TAreaId, CInputStream& in, std::vector& idsOut); + void InitializeScriptObjects(const std::vector& objIds); + std::pair LoadScriptObject(TAreaId, EScriptObjectType, u32, CInputStream& in); + std::pair GenerateObject(TEditorId); + void InitScriptObjects(const std::vector& ids); + void InformListeners(const zeus::CVector3f&, EListenNoiseType); + void ApplyKnockBack(CActor& actor, const CDamageInfo& info, const CDamageVulnerability&, const zeus::CVector3f&, + float); + void KnockBackPlayer(CPlayer& player, const zeus::CVector3f& pos, float power, float resistance); + void ApplyDamageToWorld(TUniqueId, const CActor&, const zeus::CVector3f&, const CDamageInfo& info, + const CMaterialFilter&); + void ProcessRadiusDamage(const CActor&, CActor&, TUniqueId senderId, const CDamageInfo& info, const CMaterialFilter&); + void ApplyRadiusDamage(const CActor&, const zeus::CVector3f&, CActor&, const CDamageInfo& info); + bool TestRayDamage(const zeus::CVector3f& pos, const CActor& damagee, + const rstl::reserved_vector& nearList) const; + bool RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end, const CMaterialFilter& filter, + const CActor* damagee) const; + bool RayCollideWorld(const zeus::CVector3f& start, const zeus::CVector3f& end, + const rstl::reserved_vector& nearList, const CMaterialFilter& filter, + const CActor* damagee) const; + bool RayCollideWorldInternal(const zeus::CVector3f& start, const zeus::CVector3f& end, const CMaterialFilter& filter, + const rstl::reserved_vector& nearList, const CActor* damagee) const; + bool MultiRayCollideWorld(const zeus::CMRay& ray, const CMaterialFilter& filter) const; + void TestBombHittingWater(const CActor& damager, const zeus::CVector3f& pos, CActor& damagee); + bool ApplyLocalDamage(const zeus::CVector3f&, const zeus::CVector3f&, CActor&, float, const CWeaponMode&); + bool ApplyDamage(TUniqueId damagerId, TUniqueId damageeId, TUniqueId radiusSender, const CDamageInfo& info, + const CMaterialFilter& filter, const zeus::CVector3f& knockbackVec); + void UpdateAreaSounds(); + void FrameEnd(); + void ProcessPlayerInput(); + void SetGameState(EGameState state); + EGameState GetGameState() const { return x904_gameState; } + void ProcessInput(const CFinalInput& input); + void UpdateGraphicsTiming(float dt); + void Update(float dt); + void UpdateGameState(); + void UpdateHintState(float dt); + void PreThinkObjects(float dt); + void MovePlatforms(float dt); + void MoveActors(float dt); + void CrossTouchActors(); + void Think(float dt); + void PostUpdatePlayer(float dt); + void ShowPausedHUDMemo(CAssetId strg, float time); + void ClearGraveyard(); + void FrameBegin(s32 frameCount); + void InitializeState(CAssetId mlvlId, TAreaId aid, CAssetId mreaId); + void CreateStandardGameObjects(); + const std::unique_ptr& GetObjectList() const { return x808_objLists[0]; } + CObjectList* ObjectListById(EGameObjectList type); + const CObjectList* GetObjectListById(EGameObjectList type) const; + void RemoveObject(TUniqueId); + void UpdateRoomAcoustics(TAreaId); + TAreaId GetNextAreaId() const { return x8cc_nextAreaId; } + void SetCurrentAreaId(TAreaId); + CEntity* ObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); } + const CEntity* GetObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); } + void AreaUnloaded(TAreaId); + void PrepareAreaUnload(TAreaId); + void AreaLoaded(TAreaId); + void BuildNearList(rstl::reserved_vector& listOut, const zeus::CVector3f&, const zeus::CVector3f&, + float, const CMaterialFilter&, const CActor*) const; + void BuildColliderList(rstl::reserved_vector& listOut, const CActor&, const zeus::CAABox&) const; + void BuildNearList(rstl::reserved_vector& listOut, const zeus::CAABox&, const CMaterialFilter&, + const CActor*) const; + void UpdateActorInSortedLists(CActor&); + void UpdateSortedLists(); + std::experimental::optional CalculateObjectBounds(const CActor&); + void AddObject(CEntity&); + void AddObject(CEntity*); + CRayCastResult RayStaticIntersection(const zeus::CVector3f& pos, const zeus::CVector3f& dir, float length, + const CMaterialFilter& filter) const; + CRayCastResult RayWorldIntersection(TUniqueId& idOut, const zeus::CVector3f& pos, const zeus::CVector3f& dir, + float length, const CMaterialFilter& filter, + const rstl::reserved_vector& list) const; + void UpdateObjectInLists(CEntity&); + TUniqueId AllocateUniqueId(); + void DeferStateTransition(EStateManagerTransition t); + EStateManagerTransition GetDeferredStateTransition() const { return xf90_deferredTransition; } + bool CanShowMapScreen() const; + TUniqueId GetSkipCinematicSpecialFunction() const { return xf38_skipCineSpecialFunc; } + void SetSkipCinematicSpecialFunction(TUniqueId id) { xf38_skipCineSpecialFunc = id; } + float GetHUDMessageTime() const { return xf78_hudMessageTime; } + u32 GetHUDMessageFrameCount() const { return xf80_hudMessageFrameCount; } + CAssetId GetPauseHUDMessage() const { return xf08_pauseHudMessage; } + void IncrementHUDMessageFrameCounter() { ++xf80_hudMessageFrameCount; } + bool ShouldQuitGame() const { return xf94_25_quitGame; } + void SetShouldQuitGame(bool should) { xf94_25_quitGame = should; } + void SetInSaveUI(bool b) { xf94_28_inSaveUI = b; } + bool GetInSaveUI() const { return xf94_28_inSaveUI; } + void SetInMapScreen(bool b) { xf94_27_inMapScreen = b; } + bool GetInMapScreen() const { return xf94_27_inMapScreen; } + bool IsFullThreat() const { return xf94_30_fullThreat; } + void SetIsFullThreat(bool v) { xf94_30_fullThreat = v; } - const std::shared_ptr& GetPlayerState() const {return x8b8_playerState;} - CRandom16* GetActiveRandom() {return x900_activeRandom;} - void SetActiveRandomToDefault() { x900_activeRandom = &x8fc_random; } - void ClearActiveRandom() { x900_activeRandom = nullptr; } - CRumbleManager& GetRumbleManager() {return *x88c_rumbleManager;} - CCameraFilterPassPoly& GetCameraFilterPass(int idx) {return xb84_camFilterPasses[idx];} - CCameraBlurPass& GetCameraBlurPass(int idx) {return xd14_camBlurPasses[idx];} + const std::shared_ptr& GetPlayerState() const { return x8b8_playerState; } + CRandom16* GetActiveRandom() { return x900_activeRandom; } + void SetActiveRandomToDefault() { x900_activeRandom = &x8fc_random; } + void ClearActiveRandom() { x900_activeRandom = nullptr; } + CRumbleManager& GetRumbleManager() { return *x88c_rumbleManager; } + CCameraFilterPassPoly& GetCameraFilterPass(int idx) { return xb84_camFilterPasses[idx]; } + CCameraBlurPass& GetCameraBlurPass(int idx) { return xd14_camBlurPasses[idx]; } - CEnvFxManager* GetEnvFxManager() { return x880_envFxManager; } - CWorld* WorldNC() {return x850_world.get();} - const CWorld* GetWorld() const { return x850_world.get(); } - CRelayTracker* GetRelayTracker() { return x8bc_relayTracker.get(); } - CCameraManager* GetCameraManager() const { return x870_cameraManager; } - CFluidPlaneManager* GetFluidPlaneManager() const { return x87c_fluidPlaneManager; } - CActorModelParticles* GetActorModelParticles() const { return x884_actorModelParticles; } + CEnvFxManager* GetEnvFxManager() { return x880_envFxManager; } + CWorld* WorldNC() { return x850_world.get(); } + const CWorld* GetWorld() const { return x850_world.get(); } + CRelayTracker* GetRelayTracker() { return x8bc_relayTracker.get(); } + CCameraManager* GetCameraManager() const { return x870_cameraManager; } + CFluidPlaneManager* GetFluidPlaneManager() const { return x87c_fluidPlaneManager; } + CActorModelParticles* GetActorModelParticles() const { return x884_actorModelParticles; } - const std::shared_ptr& MapWorldInfo() const { return x8c0_mapWorldInfo; } - const std::shared_ptr& WorldTransManager() const { return x8c4_worldTransManager; } - const std::shared_ptr& LayerState() const { return x8c8_worldLayerState; } + const std::shared_ptr& MapWorldInfo() const { return x8c0_mapWorldInfo; } + const std::shared_ptr& WorldTransManager() const { return x8c4_worldTransManager; } + const std::shared_ptr& LayerState() const { return x8c8_worldLayerState; } - CPlayer& GetPlayer() const { return *x84c_player; } - CPlayer* Player() const { return x84c_player.get(); } + CPlayer& GetPlayer() const { return *x84c_player; } + CPlayer* Player() const { return x84c_player.get(); } - CObjectList& GetAllObjectList() const { return *x808_objLists[0]; } - CActorList& GetActorObjectList() const { return static_cast(*x808_objLists[1]); } - CPhysicsActorList& GetPhysicsActorObjectList() const { return static_cast(*x808_objLists[2]); } - CGameCameraList& GetCameraObjectList() const { return static_cast(*x808_objLists[3]); } - CGameLightList& GetLightObjectList() const { return static_cast(*x808_objLists[4]); } - CListeningAiList& GetListeningAiObjectList() const { return static_cast(*x808_objLists[5]); } - CAiWaypointList& GetAiWaypointObjectList() const { return static_cast(*x808_objLists[6]); } - CPlatformAndDoorList& GetPlatformAndDoorObjectList() const { return static_cast(*x808_objLists[7]); } - std::pair CalculateScanCompletionRate() const; - void SetLastTriggerId(TUniqueId uid) { xf74_lastTrigger = uid; } - TUniqueId GetLastTriggerId() const { return xf74_lastTrigger; } - void SetLastRelayId(TUniqueId uid) { xf76_lastRelay = uid; } - TUniqueId* GetLastRelayIdPtr() { return &xf76_lastRelay; } - TUniqueId GetLastRelayId() const { return xf76_lastRelay; } - bool GetIsGeneratingObject() const { return xf94_26_generatingObject; } - void SetIsGeneratingObject(bool gen) { xf94_26_generatingObject = gen; } - EThermalDrawFlag GetThermalDrawFlag() const { return xf34_thermalFlag; } - const CFinalInput& GetFinalInput() const { return xb54_finalInput; } - void SetBossParams(TUniqueId bossId, float maxEnergy, u32 stringIdx); - TUniqueId GetBossId() const { return xf18_bossId; } - float GetTotalBossEnergy() const { return xf1c_totalBossEnergy; } - u32 GetBossStringIdx() const { return xf20_bossStringIdx; } - void SetPendingOnScreenTex(CAssetId texId, const zeus::CVector2i& origin, const zeus::CVector2i& extent) - { - xef4_pendingScreenTex.x0_id = texId; - xef4_pendingScreenTex.x4_origin = origin; - xef4_pendingScreenTex.xc_extent = extent; - } - const SOnScreenTex& GetPendingScreenTex() const { return xef4_pendingScreenTex; } - void SetViewportScale(const zeus::CVector2f& scale) { xf2c_viewportScale = scale; } - float GetThermalColdScale1() const { return xf24_thermColdScale1; } - float GetThermalColdScale2() const { return xf28_thermColdScale2; } - void SetThermalColdScale2(float s) { xf28_thermColdScale2 = s; } - float IntegrateVisorFog(float f) const; - u32 GetUpdateFrameIndex() const { return x8d8_updateFrameIdx; } - void SetCinematicPause(bool p) { xf94_29_cinematicPause = p; } - void QueueMessage(u32 frameCount, CAssetId msg, float f1) - { - xf84_ = frameCount; - xf88_ = msg; - xf8c_ = f1; - } - TUniqueId GetPlayerActorHead() const { return xf6c_playerActorHead; } - void SetPlayerActorHead(TUniqueId id) { xf6c_playerActorHead = id; } - std::list& GetActiveParasites() { return xf54_activeParasites; } - std::shared_ptr& WorldLayerStateNC() { return x8c8_worldLayerState; } - static float g_EscapeShakeCountdown; - static bool g_EscapeShakeCountdownInit; + CObjectList& GetAllObjectList() const { return *x808_objLists[0]; } + CActorList& GetActorObjectList() const { return static_cast(*x808_objLists[1]); } + CPhysicsActorList& GetPhysicsActorObjectList() const { return static_cast(*x808_objLists[2]); } + CGameCameraList& GetCameraObjectList() const { return static_cast(*x808_objLists[3]); } + CGameLightList& GetLightObjectList() const { return static_cast(*x808_objLists[4]); } + CListeningAiList& GetListeningAiObjectList() const { return static_cast(*x808_objLists[5]); } + CAiWaypointList& GetAiWaypointObjectList() const { return static_cast(*x808_objLists[6]); } + CPlatformAndDoorList& GetPlatformAndDoorObjectList() const { + return static_cast(*x808_objLists[7]); + } + std::pair CalculateScanCompletionRate() const; + void SetLastTriggerId(TUniqueId uid) { xf74_lastTrigger = uid; } + TUniqueId GetLastTriggerId() const { return xf74_lastTrigger; } + void SetLastRelayId(TUniqueId uid) { xf76_lastRelay = uid; } + TUniqueId* GetLastRelayIdPtr() { return &xf76_lastRelay; } + TUniqueId GetLastRelayId() const { return xf76_lastRelay; } + bool GetIsGeneratingObject() const { return xf94_26_generatingObject; } + void SetIsGeneratingObject(bool gen) { xf94_26_generatingObject = gen; } + EThermalDrawFlag GetThermalDrawFlag() const { return xf34_thermalFlag; } + const CFinalInput& GetFinalInput() const { return xb54_finalInput; } + void SetBossParams(TUniqueId bossId, float maxEnergy, u32 stringIdx); + TUniqueId GetBossId() const { return xf18_bossId; } + float GetTotalBossEnergy() const { return xf1c_totalBossEnergy; } + u32 GetBossStringIdx() const { return xf20_bossStringIdx; } + void SetPendingOnScreenTex(CAssetId texId, const zeus::CVector2i& origin, const zeus::CVector2i& extent) { + xef4_pendingScreenTex.x0_id = texId; + xef4_pendingScreenTex.x4_origin = origin; + xef4_pendingScreenTex.xc_extent = extent; + } + const SOnScreenTex& GetPendingScreenTex() const { return xef4_pendingScreenTex; } + void SetViewportScale(const zeus::CVector2f& scale) { xf2c_viewportScale = scale; } + float GetThermalColdScale1() const { return xf24_thermColdScale1; } + float GetThermalColdScale2() const { return xf28_thermColdScale2; } + void SetThermalColdScale2(float s) { xf28_thermColdScale2 = s; } + float IntegrateVisorFog(float f) const; + u32 GetUpdateFrameIndex() const { return x8d8_updateFrameIdx; } + void SetCinematicPause(bool p) { xf94_29_cinematicPause = p; } + void QueueMessage(u32 frameCount, CAssetId msg, float f1) { + xf84_ = frameCount; + xf88_ = msg; + xf8c_ = f1; + } + TUniqueId GetPlayerActorHead() const { return xf6c_playerActorHead; } + void SetPlayerActorHead(TUniqueId id) { xf6c_playerActorHead = id; } + std::list& GetActiveParasites() { return xf54_activeParasites; } + std::shared_ptr& WorldLayerStateNC() { return x8c8_worldLayerState; } + static float g_EscapeShakeCountdown; + static bool g_EscapeShakeCountdownInit; - void SetWarping(bool v) { m_warping = true; } + void SetWarping(bool v) { m_warping = true; } }; -} - +} // namespace urde diff --git a/Runtime/CStaticInterference.cpp b/Runtime/CStaticInterference.cpp index 1a65c5b63..a9d40e5b2 100644 --- a/Runtime/CStaticInterference.cpp +++ b/Runtime/CStaticInterference.cpp @@ -1,71 +1,57 @@ #include "CStaticInterference.hpp" #include "zeus/Math.hpp" -namespace urde -{ +namespace urde { -CStaticInterference::CStaticInterference(int sourceCount) -{ - m_sources.reserve(sourceCount); +CStaticInterference::CStaticInterference(int sourceCount) { m_sources.reserve(sourceCount); } + +void CStaticInterference::RemoveSource(TUniqueId id) { + auto iter = std::find_if(m_sources.begin(), m_sources.end(), + [id](const CStaticInterferenceSource& src) -> bool { return src.id == id; }); + if (iter != m_sources.end()) + m_sources.erase(iter); } -void CStaticInterference::RemoveSource(TUniqueId id) -{ - auto iter = std::find_if(m_sources.begin(), m_sources.end(), - [id](const CStaticInterferenceSource& src)->bool{ - return src.id == id; - }); - if (iter != m_sources.end()) - m_sources.erase(iter); -} - -void CStaticInterference::Update(CStateManager&, float dt) -{ - std::vector newSources; - newSources.reserve(m_sources.size()); - for (CStaticInterferenceSource& src : m_sources) - { - if (src.timeLeft >= 0.f) - { - src.timeLeft -= dt; - newSources.push_back(src); - } +void CStaticInterference::Update(CStateManager&, float dt) { + std::vector newSources; + newSources.reserve(m_sources.size()); + for (CStaticInterferenceSource& src : m_sources) { + if (src.timeLeft >= 0.f) { + src.timeLeft -= dt; + newSources.push_back(src); } - m_sources = std::move(newSources); + } + m_sources = std::move(newSources); } -float CStaticInterference::GetTotalInterference() const -{ - float validAccum = 0.f; - float invalidAccum = 0.f; - for (const CStaticInterferenceSource& src : m_sources) - { - if (src.id == kInvalidUniqueId) - invalidAccum += src.magnitude; - else - validAccum += src.magnitude; - } - if (validAccum > 0.80000001f) - validAccum = 0.80000001f; - validAccum += invalidAccum; - if (validAccum > 1.f) - return 1.f; - return validAccum; +float CStaticInterference::GetTotalInterference() const { + float validAccum = 0.f; + float invalidAccum = 0.f; + for (const CStaticInterferenceSource& src : m_sources) { + if (src.id == kInvalidUniqueId) + invalidAccum += src.magnitude; + else + validAccum += src.magnitude; + } + if (validAccum > 0.80000001f) + validAccum = 0.80000001f; + validAccum += invalidAccum; + if (validAccum > 1.f) + return 1.f; + return validAccum; } -void CStaticInterference::AddSource(TUniqueId id, float magnitude, float duration) -{ - magnitude = zeus::clamp(0.f, magnitude, 1.f); - auto search = std::find_if(m_sources.begin(), m_sources.end(), - [id](CStaticInterferenceSource& source) { return source.id == id; }); - if (search != m_sources.end()) - { - search->magnitude = magnitude; - search->timeLeft = duration; - return; - } - if (m_sources.size() < m_sources.capacity()) - m_sources.push_back({id, magnitude, duration}); +void CStaticInterference::AddSource(TUniqueId id, float magnitude, float duration) { + magnitude = zeus::clamp(0.f, magnitude, 1.f); + auto search = std::find_if(m_sources.begin(), m_sources.end(), + [id](CStaticInterferenceSource& source) { return source.id == id; }); + if (search != m_sources.end()) { + search->magnitude = magnitude; + search->timeLeft = duration; + return; + } + if (m_sources.size() < m_sources.capacity()) + m_sources.push_back({id, magnitude, duration}); } -} +} // namespace urde diff --git a/Runtime/CStaticInterference.hpp b/Runtime/CStaticInterference.hpp index de38ec174..dce04963d 100644 --- a/Runtime/CStaticInterference.hpp +++ b/Runtime/CStaticInterference.hpp @@ -3,27 +3,24 @@ #include #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CStateManager; -struct CStaticInterferenceSource -{ - TUniqueId id; - float magnitude; - float timeLeft; +struct CStaticInterferenceSource { + TUniqueId id; + float magnitude; + float timeLeft; }; -class CStaticInterference -{ - std::vector m_sources; +class CStaticInterference { + std::vector m_sources; + public: - CStaticInterference(int sourceCount); - void RemoveSource(TUniqueId id); - void Update(CStateManager&, float dt); - float GetTotalInterference() const; - void AddSource(TUniqueId id, float magnitude, float duration); + CStaticInterference(int sourceCount); + void RemoveSource(TUniqueId id); + void Update(CStateManager&, float dt); + float GetTotalInterference() const; + void AddSource(TUniqueId id, float magnitude, float duration); }; -} - +} // namespace urde diff --git a/Runtime/CStopwatch.hpp b/Runtime/CStopwatch.hpp index 53937ae92..d127bf711 100644 --- a/Runtime/CStopwatch.hpp +++ b/Runtime/CStopwatch.hpp @@ -2,25 +2,21 @@ #include -namespace urde -{ -class CStopwatch -{ - std::chrono::steady_clock::time_point m_start; -public: - CStopwatch() : m_start(std::chrono::steady_clock::now()) {} - void report(const char* name) const - { - printf("%s %f\n", name, std::chrono::duration_cast( - std::chrono::steady_clock::now() - m_start).count() / 1000000.f); - } - void reportReset(const char* name) - { - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); - printf("%s %f\n", name, std::chrono::duration_cast - (now - m_start).count() / 1000000.f); - m_start = now; - } -}; -} +namespace urde { +class CStopwatch { + std::chrono::steady_clock::time_point m_start; +public: + CStopwatch() : m_start(std::chrono::steady_clock::now()) {} + void report(const char* name) const { + printf("%s %f\n", name, + std::chrono::duration_cast(std::chrono::steady_clock::now() - m_start).count() / + 1000000.f); + } + void reportReset(const char* name) { + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + printf("%s %f\n", name, std::chrono::duration_cast(now - m_start).count() / 1000000.f); + m_start = now; + } +}; +} // namespace urde diff --git a/Runtime/CStringExtras.hpp b/Runtime/CStringExtras.hpp index 3c50c0e8d..2c7d30363 100644 --- a/Runtime/CStringExtras.hpp +++ b/Runtime/CStringExtras.hpp @@ -3,35 +3,29 @@ #include #include -namespace urde -{ +namespace urde { -class CStringExtras -{ +class CStringExtras { public: - static int CompareCaseInsensitive(const char* a, const char* b) - { + static int CompareCaseInsensitive(const char* a, const char* b) { #if _WIN32 - return _stricmp(a, b); + return _stricmp(a, b); #else - return strcasecmp(a, b); + return strcasecmp(a, b); #endif - } - static int CompareCaseInsensitive(std::string_view a, std::string_view b) - { - return CompareCaseInsensitive(a.data(), b.data()); - } + } + static int CompareCaseInsensitive(std::string_view a, std::string_view b) { + return CompareCaseInsensitive(a.data(), b.data()); + } - static int IndexOfSubstring(std::string_view haystack, std::string_view needle) - { - std::string str(haystack); - std::transform(str.begin(), str.end(), str.begin(), tolower); - std::string::size_type s = str.find(needle); - if (s == std::string::npos) - return -1; - return s; - } + static int IndexOfSubstring(std::string_view haystack, std::string_view needle) { + std::string str(haystack); + std::transform(str.begin(), str.end(), str.begin(), tolower); + std::string::size_type s = str.find(needle); + if (s == std::string::npos) + return -1; + return s; + } }; -} - +} // namespace urde diff --git a/Runtime/CTimeProvider.cpp b/Runtime/CTimeProvider.cpp index bc7e37c8c..e71ba448d 100644 --- a/Runtime/CTimeProvider.cpp +++ b/Runtime/CTimeProvider.cpp @@ -1,26 +1,22 @@ #include "CTimeProvider.hpp" #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { CTimeProvider* CTimeProvider::g_currentTimeProvider = nullptr; -CTimeProvider::CTimeProvider(const float& time) - : x0_currentTime(time), x8_lastProvider(g_currentTimeProvider) -{ - if (x8_lastProvider != nullptr) - x8_lastProvider->x4_first = false; +CTimeProvider::CTimeProvider(const float& time) : x0_currentTime(time), x8_lastProvider(g_currentTimeProvider) { + if (x8_lastProvider != nullptr) + x8_lastProvider->x4_first = false; - g_currentTimeProvider = this; + g_currentTimeProvider = this; - CGraphics::SetExternalTimeProvider(this); + CGraphics::SetExternalTimeProvider(this); } -CTimeProvider::~CTimeProvider() -{ - g_currentTimeProvider = x8_lastProvider; - if (g_currentTimeProvider) - g_currentTimeProvider->x4_first = true; - CGraphics::SetExternalTimeProvider(g_currentTimeProvider); +CTimeProvider::~CTimeProvider() { + g_currentTimeProvider = x8_lastProvider; + if (g_currentTimeProvider) + g_currentTimeProvider->x4_first = true; + CGraphics::SetExternalTimeProvider(g_currentTimeProvider); } -} +} // namespace urde diff --git a/Runtime/CTimeProvider.hpp b/Runtime/CTimeProvider.hpp index f33bb7b06..d710108b8 100644 --- a/Runtime/CTimeProvider.hpp +++ b/Runtime/CTimeProvider.hpp @@ -1,17 +1,14 @@ #pragma once -namespace urde -{ +namespace urde { class CTimeProvider; -class CTimeProvider -{ +class CTimeProvider { public: - static CTimeProvider* g_currentTimeProvider; - const float& x0_currentTime; // in seconds - bool x4_first = true; - CTimeProvider* x8_lastProvider = nullptr; + static CTimeProvider* g_currentTimeProvider; + const float& x0_currentTime; // in seconds + bool x4_first = true; + CTimeProvider* x8_lastProvider = nullptr; - CTimeProvider(const float& time); - ~CTimeProvider(); + CTimeProvider(const float& time); + ~CTimeProvider(); }; -} - +} // namespace urde diff --git a/Runtime/CToken.cpp b/Runtime/CToken.cpp index 40eb24ea3..87290b93f 100644 --- a/Runtime/CToken.cpp +++ b/Runtime/CToken.cpp @@ -1,194 +1,158 @@ #include "CToken.hpp" -namespace urde -{ -u16 CObjectReference::RemoveReference() -{ - --x0_refCount; - if (x0_refCount == 0) - { - if (x10_object) - Unload(); - if (IsLoading()) - CancelLoad(); - if (xC_objectStore) - xC_objectStore->ObjectUnreferenced(x4_objTag); - } - return x0_refCount; -} - -CObjectReference::CObjectReference(IObjectStore& objStore, std::unique_ptr&& obj, - const SObjectTag& objTag, CVParamTransfer buildParams) -: x4_objTag(objTag), xC_objectStore(&objStore), - x10_object(std::move(obj)), x14_params(buildParams) {} -CObjectReference::CObjectReference(std::unique_ptr&& obj) -: x10_object(std::move(obj)) {} - -void CObjectReference::Unlock() -{ - --x2_lockCount; - if (x2_lockCount) - return; - if (x10_object && xC_objectStore) - Unload(); - else if (IsLoading()) - CancelLoad(); -} - -void CObjectReference::Lock() -{ - ++x2_lockCount; - if (!x10_object && !x3_loading) - { - IFactory& fac = xC_objectStore->GetFactory(); - fac.BuildAsync(x4_objTag, x14_params, &x10_object, this); - x3_loading = !x10_object.operator bool(); - } -} - -void CObjectReference::CancelLoad() -{ - if (xC_objectStore && IsLoading()) - { - xC_objectStore->GetFactory().CancelBuild(x4_objTag); - x3_loading = false; - } -} - -void CObjectReference::Unload() -{ - x10_object.reset(); - x3_loading = false; -} - -IObj* CObjectReference::GetObject() -{ - if (!x10_object) - { - IFactory& factory = xC_objectStore->GetFactory(); - x10_object = factory.Build(x4_objTag, x14_params, this); - } - x3_loading = false; - return x10_object.get(); -} - -CObjectReference::~CObjectReference() -{ +namespace urde { +u16 CObjectReference::RemoveReference() { + --x0_refCount; + if (x0_refCount == 0) { if (x10_object) - x10_object.reset(); - else if (x3_loading) - xC_objectStore->GetFactory().CancelBuild(x4_objTag); + Unload(); + if (IsLoading()) + CancelLoad(); + if (xC_objectStore) + xC_objectStore->ObjectUnreferenced(x4_objTag); + } + return x0_refCount; } -void CToken::RemoveRef() -{ - if (x0_objRef && x0_objRef->RemoveReference() == 0) - { - std::default_delete()(x0_objRef); - x0_objRef = nullptr; - } +CObjectReference::CObjectReference(IObjectStore& objStore, std::unique_ptr&& obj, const SObjectTag& objTag, + CVParamTransfer buildParams) +: x4_objTag(objTag), xC_objectStore(&objStore), x10_object(std::move(obj)), x14_params(buildParams) {} +CObjectReference::CObjectReference(std::unique_ptr&& obj) : x10_object(std::move(obj)) {} + +void CObjectReference::Unlock() { + --x2_lockCount; + if (x2_lockCount) + return; + if (x10_object && xC_objectStore) + Unload(); + else if (IsLoading()) + CancelLoad(); } -CToken::CToken(CObjectReference* obj) -{ - x0_objRef = obj; +void CObjectReference::Lock() { + ++x2_lockCount; + if (!x10_object && !x3_loading) { + IFactory& fac = xC_objectStore->GetFactory(); + fac.BuildAsync(x4_objTag, x14_params, &x10_object, this); + x3_loading = !x10_object.operator bool(); + } +} + +void CObjectReference::CancelLoad() { + if (xC_objectStore && IsLoading()) { + xC_objectStore->GetFactory().CancelBuild(x4_objTag); + x3_loading = false; + } +} + +void CObjectReference::Unload() { + x10_object.reset(); + x3_loading = false; +} + +IObj* CObjectReference::GetObject() { + if (!x10_object) { + IFactory& factory = xC_objectStore->GetFactory(); + x10_object = factory.Build(x4_objTag, x14_params, this); + } + x3_loading = false; + return x10_object.get(); +} + +CObjectReference::~CObjectReference() { + if (x10_object) + x10_object.reset(); + else if (x3_loading) + xC_objectStore->GetFactory().CancelBuild(x4_objTag); +} + +void CToken::RemoveRef() { + if (x0_objRef && x0_objRef->RemoveReference() == 0) { + std::default_delete()(x0_objRef); + x0_objRef = nullptr; + } +} + +CToken::CToken(CObjectReference* obj) { + x0_objRef = obj; + ++x0_objRef->x0_refCount; +} + +void CToken::Unlock() { + if (x0_objRef && x4_lockHeld) { + x0_objRef->Unlock(); + x4_lockHeld = false; + } +} +void CToken::Lock() { + if (x0_objRef && !x4_lockHeld) { + x0_objRef->Lock(); + x4_lockHeld = true; + } +} +bool CToken::IsLoaded() const { + if (!x0_objRef) + return false; + return x0_objRef->IsLoaded(); +} +IObj* CToken::GetObj() { + if (!x0_objRef) + return nullptr; + Lock(); + return x0_objRef->GetObject(); +} +CToken& CToken::operator=(const CToken& other) { + Unlock(); + RemoveRef(); + x0_objRef = other.x0_objRef; + if (x0_objRef) { ++x0_objRef->x0_refCount; + if (other.x4_lockHeld) + Lock(); + } + return *this; } - -void CToken::Unlock() -{ - if (x0_objRef && x4_lockHeld) - { - x0_objRef->Unlock(); - x4_lockHeld = false; - } +CToken& CToken::operator=(CToken&& other) { + Unlock(); + RemoveRef(); + x0_objRef = other.x0_objRef; + other.x0_objRef = nullptr; + x4_lockHeld = other.x4_lockHeld; + other.x4_lockHeld = false; + return *this; } -void CToken::Lock() -{ - if (x0_objRef && !x4_lockHeld) - { - x0_objRef->Lock(); - x4_lockHeld = true; - } +CToken::CToken(const CToken& other) : x0_objRef(other.x0_objRef) { + if (x0_objRef) { + ++x0_objRef->x0_refCount; + if (other.x4_lockHeld) + Lock(); + } } -bool CToken::IsLoaded() const -{ - if (!x0_objRef) - return false; - return x0_objRef->IsLoaded(); +CToken::CToken(CToken&& other) : x0_objRef(other.x0_objRef), x4_lockHeld(other.x4_lockHeld) { + other.x0_objRef = nullptr; + other.x4_lockHeld = false; } -IObj* CToken::GetObj() -{ - if (!x0_objRef) - return nullptr; - Lock(); - return x0_objRef->GetObject(); +CToken::CToken(IObj* obj) { + x0_objRef = new CObjectReference(std::unique_ptr(obj)); + ++x0_objRef->x0_refCount; + Lock(); } -CToken& CToken::operator=(const CToken& other) -{ - Unlock(); +CToken::CToken(std::unique_ptr&& obj) { + x0_objRef = new CObjectReference(std::move(obj)); + ++x0_objRef->x0_refCount; + Lock(); +} +const SObjectTag* CToken::GetObjectTag() const { + if (!x0_objRef) + return nullptr; + return &x0_objRef->GetObjectTag(); +} +CToken::~CToken() { + if (x0_objRef) { + if (x4_lockHeld) + x0_objRef->Unlock(); RemoveRef(); - x0_objRef = other.x0_objRef; - if (x0_objRef) - { - ++x0_objRef->x0_refCount; - if (other.x4_lockHeld) - Lock(); - } - return *this; -} -CToken& CToken::operator=(CToken&& other) -{ - Unlock(); - RemoveRef(); - x0_objRef = other.x0_objRef; - other.x0_objRef = nullptr; - x4_lockHeld = other.x4_lockHeld; - other.x4_lockHeld = false; - return *this; -} -CToken::CToken(const CToken& other) -: x0_objRef(other.x0_objRef) -{ - if (x0_objRef) - { - ++x0_objRef->x0_refCount; - if (other.x4_lockHeld) - Lock(); - } -} -CToken::CToken(CToken&& other) -: x0_objRef(other.x0_objRef), x4_lockHeld(other.x4_lockHeld) -{ - other.x0_objRef = nullptr; - other.x4_lockHeld = false; -} -CToken::CToken(IObj* obj) -{ - x0_objRef = new CObjectReference(std::unique_ptr(obj)); - ++x0_objRef->x0_refCount; - Lock(); -} -CToken::CToken(std::unique_ptr&& obj) -{ - x0_objRef = new CObjectReference(std::move(obj)); - ++x0_objRef->x0_refCount; - Lock(); -} -const SObjectTag* CToken::GetObjectTag() const -{ - if (!x0_objRef) - return nullptr; - return &x0_objRef->GetObjectTag(); -} -CToken::~CToken() -{ - if (x0_objRef) - { - if (x4_lockHeld) - x0_objRef->Unlock(); - RemoveRef(); - } + } } -} +} // namespace urde diff --git a/Runtime/CToken.hpp b/Runtime/CToken.hpp index b6ddcebaa..ac5921532 100644 --- a/Runtime/CToken.hpp +++ b/Runtime/CToken.hpp @@ -7,183 +7,172 @@ #include "IObjectStore.hpp" #include "IFactory.hpp" -namespace urde -{ +namespace urde { class IObjectStore; /** Shared data-structure for CToken references, analogous to std::shared_ptr */ -class CObjectReference -{ - friend class CToken; - friend class CSimplePool; - u16 x0_refCount = 0; - u16 x2_lockCount = 0; - bool x3_loading = false; /* Rightmost bit of lockCount */ - SObjectTag x4_objTag; - IObjectStore* xC_objectStore = nullptr; - std::unique_ptr x10_object; - CVParamTransfer x14_params; +class CObjectReference { + friend class CToken; + friend class CSimplePool; + u16 x0_refCount = 0; + u16 x2_lockCount = 0; + bool x3_loading = false; /* Rightmost bit of lockCount */ + SObjectTag x4_objTag; + IObjectStore* xC_objectStore = nullptr; + std::unique_ptr x10_object; + CVParamTransfer x14_params; - /** Mechanism by which CToken decrements 1st ref-count, indicating CToken invalidation or reset. - * Reaching 0 indicates the CToken should delete the CObjectReference */ - u16 RemoveReference(); + /** Mechanism by which CToken decrements 1st ref-count, indicating CToken invalidation or reset. + * Reaching 0 indicates the CToken should delete the CObjectReference */ + u16 RemoveReference(); - CObjectReference(IObjectStore& objStore, std::unique_ptr&& obj, - const SObjectTag& objTag, CVParamTransfer buildParams); - CObjectReference(std::unique_ptr&& obj); + CObjectReference(IObjectStore& objStore, std::unique_ptr&& obj, const SObjectTag& objTag, + CVParamTransfer buildParams); + CObjectReference(std::unique_ptr&& obj); - /** Indicates an asynchronous load transaction has been submitted and is not yet finished */ - bool IsLoading() const {return x3_loading;} + /** Indicates an asynchronous load transaction has been submitted and is not yet finished */ + bool IsLoading() const { return x3_loading; } - /** Indicates an asynchronous load transaction has finished and object is completely loaded */ - bool IsLoaded() const {return x10_object.operator bool();} + /** Indicates an asynchronous load transaction has finished and object is completely loaded */ + bool IsLoaded() const { return x10_object.operator bool(); } - /** Decrements 2nd ref-count, performing unload or async-load-cancel if 0 reached */ - void Unlock(); + /** Decrements 2nd ref-count, performing unload or async-load-cancel if 0 reached */ + void Unlock(); - /** Increments 2nd ref-count, performing async-factory-load if needed */ - void Lock(); + /** Increments 2nd ref-count, performing async-factory-load if needed */ + void Lock(); - void CancelLoad(); + void CancelLoad(); - /** Pointer-synchronized object-destructor, another building Lock cycle may be performed after */ - void Unload(); + /** Pointer-synchronized object-destructor, another building Lock cycle may be performed after */ + void Unload(); - /** Synchronous object-fetch, guaranteed to return complete object on-demand, blocking build if not ready */ - IObj* GetObject(); + /** Synchronous object-fetch, guaranteed to return complete object on-demand, blocking build if not ready */ + IObj* GetObject(); public: - const SObjectTag& GetObjectTag() const { return x4_objTag; } + const SObjectTag& GetObjectTag() const { return x4_objTag; } - ~CObjectReference(); + ~CObjectReference(); }; /** Counted meta-object, reference-counting against a shared CObjectReference * This class is analogous to std::shared_ptr and C++11 rvalues have been implemented accordingly * (default/empty constructor, move constructor/assign) */ -class CToken -{ - friend class CSimplePool; - friend class CModel; - CObjectReference* x0_objRef = nullptr; - bool x4_lockHeld = false; +class CToken { + friend class CSimplePool; + friend class CModel; + CObjectReference* x0_objRef = nullptr; + bool x4_lockHeld = false; - void RemoveRef(); + void RemoveRef(); - CToken(CObjectReference* obj); + CToken(CObjectReference* obj); public: - /* Added to test for non-null state */ - operator bool() const {return x0_objRef != nullptr;} - void Unlock(); - void Lock(); - bool IsLocked() const {return x4_lockHeld;} - bool IsLoaded() const; - IObj* GetObj(); - const IObj* GetObj() const - { - return const_cast(this)->GetObj(); - } - CToken& operator=(const CToken& other); - CToken& operator=(CToken&& other); - CToken() = default; - CToken(const CToken& other); - CToken(CToken&& other); - CToken(IObj* obj); - CToken(std::unique_ptr&& obj); - const SObjectTag* GetObjectTag() const; - ~CToken(); + /* Added to test for non-null state */ + operator bool() const { return x0_objRef != nullptr; } + void Unlock(); + void Lock(); + bool IsLocked() const { return x4_lockHeld; } + bool IsLoaded() const; + IObj* GetObj(); + const IObj* GetObj() const { return const_cast(this)->GetObj(); } + CToken& operator=(const CToken& other); + CToken& operator=(CToken&& other); + CToken() = default; + CToken(const CToken& other); + CToken(CToken&& other); + CToken(IObj* obj); + CToken(std::unique_ptr&& obj); + const SObjectTag* GetObjectTag() const; + ~CToken(); }; template -class TToken : public CToken -{ +class TToken : public CToken { public: - static std::unique_ptr> GetIObjObjectFor(std::unique_ptr&& obj) - { - return TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::move(obj)); - } - TToken() = default; - TToken(const CToken& other) : CToken(other) {} - TToken(CToken&& other) : CToken(std::move(other)) {} - TToken(std::unique_ptr&& obj) : CToken(GetIObjObjectFor(std::move(obj))) {} - TToken& operator=(std::unique_ptr&& obj) - { - *this = CToken(GetIObjObjectFor(std::move(obj))); - return this; - } - T* GetObj() - { - TObjOwnerDerivedFromIObj* owner = static_cast*>(CToken::GetObj()); - if (owner) - return owner->GetObj(); - return nullptr; - } - const T* GetObj() const - { - return const_cast*>(this)->GetObj(); - } - T* operator->() {return GetObj();} - const T* operator->() const {return GetObj();} - T& operator*() {return *GetObj();} - const T& operator*() const {return *GetObj();} + static std::unique_ptr> GetIObjObjectFor(std::unique_ptr&& obj) { + return TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::move(obj)); + } + TToken() = default; + TToken(const CToken& other) : CToken(other) {} + TToken(CToken&& other) : CToken(std::move(other)) {} + TToken(std::unique_ptr&& obj) : CToken(GetIObjObjectFor(std::move(obj))) {} + TToken& operator=(std::unique_ptr&& obj) { + *this = CToken(GetIObjObjectFor(std::move(obj))); + return this; + } + T* GetObj() { + TObjOwnerDerivedFromIObj* owner = static_cast*>(CToken::GetObj()); + if (owner) + return owner->GetObj(); + return nullptr; + } + const T* GetObj() const { return const_cast*>(this)->GetObj(); } + T* operator->() { return GetObj(); } + const T* operator->() const { return GetObj(); } + T& operator*() { return *GetObj(); } + const T& operator*() const { return *GetObj(); } }; template -class TCachedToken : public TToken -{ +class TCachedToken : public TToken { protected: - T* m_obj = nullptr; -public: - TCachedToken() = default; - TCachedToken(const CToken& other) : TToken(other) {} - TCachedToken(CToken&& other) : TToken(std::move(other)) {} - T* GetObj() - { - if (!m_obj) - m_obj = TToken::GetObj(); - return m_obj; - } - const T* GetObj() const - { - return const_cast*>(this)->GetObj(); - } - T* operator->() {return GetObj();} - const T* operator->() const {return GetObj();} - void Unlock() {TToken::Unlock(); m_obj = nullptr;} + T* m_obj = nullptr; - TCachedToken& operator=(const TCachedToken& other) { CToken::operator=(other); m_obj = nullptr; return *this; } - TCachedToken& operator=(const CToken& other) { CToken::operator=(other); m_obj = nullptr; return *this; } +public: + TCachedToken() = default; + TCachedToken(const CToken& other) : TToken(other) {} + TCachedToken(CToken&& other) : TToken(std::move(other)) {} + T* GetObj() { + if (!m_obj) + m_obj = TToken::GetObj(); + return m_obj; + } + const T* GetObj() const { return const_cast*>(this)->GetObj(); } + T* operator->() { return GetObj(); } + const T* operator->() const { return GetObj(); } + void Unlock() { + TToken::Unlock(); + m_obj = nullptr; + } + + TCachedToken& operator=(const TCachedToken& other) { + CToken::operator=(other); + m_obj = nullptr; + return *this; + } + TCachedToken& operator=(const CToken& other) { + CToken::operator=(other); + m_obj = nullptr; + return *this; + } }; template -class TLockedToken : public TCachedToken -{ +class TLockedToken : public TCachedToken { public: - TLockedToken() = default; - TLockedToken(const TLockedToken& other) : TCachedToken(other) { CToken::Lock(); } - TLockedToken& operator=(const TLockedToken& other) - { - CToken oldTok = std::move(*this); - TCachedToken::operator=(other); - CToken::Lock(); - return *this; - } - TLockedToken(const CToken& other) : TCachedToken(other) { CToken::Lock(); } - TLockedToken& operator=(const CToken& other) - { - CToken oldTok = std::move(*this); - TCachedToken::operator=(other); - CToken::Lock(); - return *this; - } - TLockedToken(CToken&& other) - { - CToken oldTok = std::move(*this); - *this = TCachedToken(std::move(other)); - CToken::Lock(); - } + TLockedToken() = default; + TLockedToken(const TLockedToken& other) : TCachedToken(other) { CToken::Lock(); } + TLockedToken& operator=(const TLockedToken& other) { + CToken oldTok = std::move(*this); + TCachedToken::operator=(other); + CToken::Lock(); + return *this; + } + TLockedToken(const CToken& other) : TCachedToken(other) { CToken::Lock(); } + TLockedToken& operator=(const CToken& other) { + CToken oldTok = std::move(*this); + TCachedToken::operator=(other); + CToken::Lock(); + return *this; + } + TLockedToken(CToken&& other) { + CToken oldTok = std::move(*this); + *this = TCachedToken(std::move(other)); + CToken::Lock(); + } }; -} - +} // namespace urde diff --git a/Runtime/Camera/CBallCamera.cpp b/Runtime/Camera/CBallCamera.cpp index 2d2f678a6..4e6c963db 100644 --- a/Runtime/Camera/CBallCamera.cpp +++ b/Runtime/Camera/CBallCamera.cpp @@ -14,2502 +14,2178 @@ #include "World/CScriptDock.hpp" #include "Collision/CGameCollision.hpp" -namespace urde -{ +namespace urde { -void CCameraSpring::Reset() -{ - x4_k2Sqrt = 2.f * std::sqrt(x0_k); - x10_dx = 0.f; +void CCameraSpring::Reset() { + x4_k2Sqrt = 2.f * std::sqrt(x0_k); + x10_dx = 0.f; } -float CCameraSpring::ApplyDistanceSpringNoMax(float targetX, float curX, float dt) -{ - float useX = xc_tardis * x10_dx * dt + curX; - x10_dx += xc_tardis * (x0_k * (targetX - curX) - x4_k2Sqrt * x10_dx) * dt; - return std::max(useX, targetX); +float CCameraSpring::ApplyDistanceSpringNoMax(float targetX, float curX, float dt) { + float useX = xc_tardis * x10_dx * dt + curX; + x10_dx += xc_tardis * (x0_k * (targetX - curX) - x4_k2Sqrt * x10_dx) * dt; + return std::max(useX, targetX); } -float CCameraSpring::ApplyDistanceSpring(float targetX, float curX, float dt) -{ - float useX = xc_tardis * x10_dx * dt + curX; - x10_dx += xc_tardis * (x0_k * (targetX - curX) - x4_k2Sqrt * x10_dx) * dt; - useX = std::max(useX, targetX); - if (useX - targetX > x8_max) - useX = targetX + x8_max; - return useX; +float CCameraSpring::ApplyDistanceSpring(float targetX, float curX, float dt) { + float useX = xc_tardis * x10_dx * dt + curX; + x10_dx += xc_tardis * (x0_k * (targetX - curX) - x4_k2Sqrt * x10_dx) * dt; + useX = std::max(useX, targetX); + if (useX - targetX > x8_max) + useX = targetX + x8_max; + return useX; } -CBallCamera::CBallCamera(TUniqueId uid, TUniqueId watchedId, const zeus::CTransform& xf, - float fovy, float znear, float zfar, float aspect) -: CGameCamera(uid, true, "Ball Camera", - CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList), - xf, fovy, znear, zfar, aspect, watchedId, false, 0), - x214_ballCameraSpring(g_tweakBall->GetBallCameraSpringConstant(), - g_tweakBall->GetBallCameraSpringMax(), - g_tweakBall->GetBallCameraSpringTardis()), - x228_ballCameraCentroidSpring(g_tweakBall->GetBallCameraCentroidSpringConstant(), +CBallCamera::CBallCamera(TUniqueId uid, TUniqueId watchedId, const zeus::CTransform& xf, float fovy, float znear, + float zfar, float aspect) +: CGameCamera(uid, true, "Ball Camera", CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList), xf, fovy, znear, zfar, + aspect, watchedId, false, 0) +, x214_ballCameraSpring(g_tweakBall->GetBallCameraSpringConstant(), g_tweakBall->GetBallCameraSpringMax(), + g_tweakBall->GetBallCameraSpringTardis()) +, x228_ballCameraCentroidSpring(g_tweakBall->GetBallCameraCentroidSpringConstant(), g_tweakBall->GetBallCameraCentroidSpringMax(), - g_tweakBall->GetBallCameraCentroidSpringTardis()), - x23c_ballCameraLookAtSpring(g_tweakBall->GetBallCameraLookAtSpringConstant(), + g_tweakBall->GetBallCameraCentroidSpringTardis()) +, x23c_ballCameraLookAtSpring(g_tweakBall->GetBallCameraLookAtSpringConstant(), g_tweakBall->GetBallCameraLookAtSpringMax(), - g_tweakBall->GetBallCameraLookAtSpringTardis()), - x250_ballCameraCentroidDistanceSpring(g_tweakBall->GetBallCameraCentroidDistanceSpringConstant(), + g_tweakBall->GetBallCameraLookAtSpringTardis()) +, x250_ballCameraCentroidDistanceSpring(g_tweakBall->GetBallCameraCentroidDistanceSpringConstant(), g_tweakBall->GetBallCameraCentroidDistanceSpringMax(), - g_tweakBall->GetBallCameraCentroidDistanceSpringTardis()), - x37c_camSpline(false), - x41c_ballCameraChaseSpring(g_tweakBall->GetBallCameraChaseSpringConstant(), - g_tweakBall->GetBallCameraChaseSpringMax(), - g_tweakBall->GetBallCameraChaseSpringTardis()), - x448_ballCameraBoostSpring(g_tweakBall->GetBallCameraBoostSpringConstant(), + g_tweakBall->GetBallCameraCentroidDistanceSpringTardis()) +, x37c_camSpline(false) +, x41c_ballCameraChaseSpring(g_tweakBall->GetBallCameraChaseSpringConstant(), + g_tweakBall->GetBallCameraChaseSpringMax(), g_tweakBall->GetBallCameraChaseSpringTardis()) +, x448_ballCameraBoostSpring(g_tweakBall->GetBallCameraBoostSpringConstant(), g_tweakBall->GetBallCameraBoostSpringMax(), - g_tweakBall->GetBallCameraBoostSpringTardis()) -{ - x18c_24_ = true; - x18c_25_chaseAllowed = true; - x18c_26_boostAllowed = true; - x18c_27_obscureAvoidance = true; - x18c_28_volumeCollider = true; - x18c_29_clampAttitude = false; - x18c_30_clampAzimuth = false; - x18c_31_clearLOS = true; - x18d_24_prevClearLOS = true; - x18d_25_avoidGeometryFull = false; - x18d_26_lookAtBall = false; - x18d_27_forceProcessing = false; - x18d_28_obtuseDirection = false; - x18d_29_noElevationInterp = false; - x18d_30_directElevation = false; - x18d_31_overrideLookDir = false; - x18e_24_noElevationVelClamp = false; - x18e_25_noSpline = false; - x18e_26_ = false; - x18e_27_nearbyDoorClosed = false; - x18e_28_nearbyDoorClosing = false; + g_tweakBall->GetBallCameraBoostSpringTardis()) { + x18c_24_ = true; + x18c_25_chaseAllowed = true; + x18c_26_boostAllowed = true; + x18c_27_obscureAvoidance = true; + x18c_28_volumeCollider = true; + x18c_29_clampAttitude = false; + x18c_30_clampAzimuth = false; + x18c_31_clearLOS = true; + x18d_24_prevClearLOS = true; + x18d_25_avoidGeometryFull = false; + x18d_26_lookAtBall = false; + x18d_27_forceProcessing = false; + x18d_28_obtuseDirection = false; + x18d_29_noElevationInterp = false; + x18d_30_directElevation = false; + x18d_31_overrideLookDir = false; + x18e_24_noElevationVelClamp = false; + x18e_25_noSpline = false; + x18e_26_ = false; + x18e_27_nearbyDoorClosed = false; + x18e_28_nearbyDoorClosing = false; - x190_curMinDistance = g_tweakBall->GetBallCameraMinSpeedDistance(); - x194_targetMinDistance = g_tweakBall->GetBallCameraMinSpeedDistance(); - x198_maxDistance = g_tweakBall->GetBallCameraMaxSpeedDistance(); - x19c_backwardsDistance = g_tweakBall->GetBallCameraBackwardsDistance(); + x190_curMinDistance = g_tweakBall->GetBallCameraMinSpeedDistance(); + x194_targetMinDistance = g_tweakBall->GetBallCameraMinSpeedDistance(); + x198_maxDistance = g_tweakBall->GetBallCameraMaxSpeedDistance(); + x19c_backwardsDistance = g_tweakBall->GetBallCameraBackwardsDistance(); - x1a0_elevation = g_tweakBall->GetBallCameraElevation(); - x1a4_curAnglePerSecond = g_tweakBall->GetBallCameraAnglePerSecond(); - x1a8_targetAnglePerSecond = g_tweakBall->GetBallCameraAnglePerSecond(); - x1b4_lookAtOffset = g_tweakBall->GetBallCameraOffset(); + x1a0_elevation = g_tweakBall->GetBallCameraElevation(); + x1a4_curAnglePerSecond = g_tweakBall->GetBallCameraAnglePerSecond(); + x1a8_targetAnglePerSecond = g_tweakBall->GetBallCameraAnglePerSecond(); + x1b4_lookAtOffset = g_tweakBall->GetBallCameraOffset(); - x404_chaseElevation = g_tweakBall->GetBallCameraChaseElevation(); - x408_chaseDistance = g_tweakBall->GetBallCameraChaseDistance(); - x40c_chaseAnglePerSecond = g_tweakBall->GetBallCameraChaseAnglePerSecond(); - x410_chaseLookAtOffset = g_tweakBall->GetBallCameraChaseLookAtOffset(); + x404_chaseElevation = g_tweakBall->GetBallCameraChaseElevation(); + x408_chaseDistance = g_tweakBall->GetBallCameraChaseDistance(); + x40c_chaseAnglePerSecond = g_tweakBall->GetBallCameraChaseAnglePerSecond(); + x410_chaseLookAtOffset = g_tweakBall->GetBallCameraChaseLookAtOffset(); - x430_boostElevation = g_tweakBall->GetBallCameraBoostElevation(); - x434_boostDistance = g_tweakBall->GetBallCameraBoostDistance(); - x438_boostAnglePerSecond = g_tweakBall->GetBallCameraBoostAnglePerSecond(); - x43c_boostLookAtOffset = g_tweakBall->GetBallCameraBoostLookAtOffset(); + x430_boostElevation = g_tweakBall->GetBallCameraBoostElevation(); + x434_boostDistance = g_tweakBall->GetBallCameraBoostDistance(); + x438_boostAnglePerSecond = g_tweakBall->GetBallCameraBoostAnglePerSecond(); + x43c_boostLookAtOffset = g_tweakBall->GetBallCameraBoostLookAtOffset(); - x468_conservativeDoorCamDistance = g_tweakBall->GetConservativeDoorCameraDistance(); + x468_conservativeDoorCamDistance = g_tweakBall->GetConservativeDoorCameraDistance(); - x47c_failsafeState = std::make_unique(); - x480_ = std::make_unique(); + x47c_failsafeState = std::make_unique(); + x480_ = std::make_unique(); - SetupColliders(x264_smallColliders, 2.31f, 2.31f, 0.1f, 3, 2.f, 0.5f, -M_PIF / 2.f); - SetupColliders(x274_mediumColliders, 4.62f, 4.62f, 0.1f, 6, 2.f, 0.5f, -M_PIF / 2.f); - SetupColliders(x284_largeColliders, 7.f, 7.f, 0.1f, 12, 2.f, 0.5f, -M_PIF / 2.f); + SetupColliders(x264_smallColliders, 2.31f, 2.31f, 0.1f, 3, 2.f, 0.5f, -M_PIF / 2.f); + SetupColliders(x274_mediumColliders, 4.62f, 4.62f, 0.1f, 6, 2.f, 0.5f, -M_PIF / 2.f); + SetupColliders(x284_largeColliders, 7.f, 7.f, 0.1f, 12, 2.f, 0.5f, -M_PIF / 2.f); } void CBallCamera::SetupColliders(std::vector& out, float xMag, float zMag, float radius, int count, - float k, float max, float startAngle) -{ - out.reserve(count); - float theta = startAngle; - for (int i=0 ; i M_PIF / 2.f) - z *= 0.25f; - out.emplace_back(radius, zeus::CVector3f{std::sin(theta) * xMag, 0.f, z}, CCameraSpring{k, max, 1.f}, 1.f); - theta += 2.f * M_PIF / float(count); - } + float k, float max, float startAngle) { + out.reserve(count); + float theta = startAngle; + for (int i = 0; i < count; ++i) { + float z = std::cos(theta) * zMag; + if (theta > M_PIF / 2.f) + z *= 0.25f; + out.emplace_back(radius, zeus::CVector3f{std::sin(theta) * xMag, 0.f, z}, CCameraSpring{k, max, 1.f}, 1.f); + theta += 2.f * M_PIF / float(count); + } } -void CBallCamera::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CBallCamera::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CBallCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CGameCamera::AcceptScriptMsg(msg, objId, stateMgr); + switch (msg) { + case EScriptObjectMessage::Registered: { + x46c_collisionActorId = stateMgr.AllocateUniqueId(); + CCollisionActor* colAct = + new CCollisionActor(x46c_collisionActorId, GetAreaId(), kInvalidUniqueId, true, 0.3f, 1.f); + colAct->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, {EMaterialTypes::Player, EMaterialTypes::CameraPassthrough})); + colAct->SetMaterialList({EMaterialTypes::ProjectilePassthrough, EMaterialTypes::ScanPassthrough, + EMaterialTypes::SeeThrough, EMaterialTypes::CameraPassthrough}); + colAct->SetTranslation(GetTranslation()); + stateMgr.AddObject(colAct); + colAct->SetMovable(false); + CMotionState mState(GetTranslation(), zeus::CNUQuaternion::fromAxisAngle(zeus::CVector3f::skForward, 0.f), + zeus::CVector3f::skZero, zeus::CAxisAngle::sIdentity); + colAct->SetLastNonCollidingState(mState); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {}, {EMaterialTypes::Solid, EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, + EMaterialTypes::Character, EMaterialTypes::CameraPassthrough})); + RemoveMaterial(EMaterialTypes::Solid, stateMgr); + break; + } + case EScriptObjectMessage::Deleted: + stateMgr.FreeScriptObject(x46c_collisionActorId); + x46c_collisionActorId = kInvalidUniqueId; + break; + default: + break; + } } -void CBallCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CGameCamera::AcceptScriptMsg(msg, objId, stateMgr); - switch (msg) - { - case EScriptObjectMessage::Registered: - { - x46c_collisionActorId = stateMgr.AllocateUniqueId(); - CCollisionActor* colAct = new CCollisionActor(x46c_collisionActorId, GetAreaId(), kInvalidUniqueId, - true, 0.3f, 1.f); - colAct->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::Player, - EMaterialTypes::CameraPassthrough})); - colAct->SetMaterialList({EMaterialTypes::ProjectilePassthrough, EMaterialTypes::ScanPassthrough, - EMaterialTypes::SeeThrough, EMaterialTypes::CameraPassthrough}); - colAct->SetTranslation(GetTranslation()); - stateMgr.AddObject(colAct); - colAct->SetMovable(false); - CMotionState mState(GetTranslation(), zeus::CNUQuaternion::fromAxisAngle(zeus::CVector3f::skForward, 0.f), - zeus::CVector3f::skZero, zeus::CAxisAngle::sIdentity); - colAct->SetLastNonCollidingState(mState); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude({}, - {EMaterialTypes::Solid, - EMaterialTypes::ProjectilePassthrough, - EMaterialTypes::Player, - EMaterialTypes::Character, - EMaterialTypes::CameraPassthrough})); - RemoveMaterial(EMaterialTypes::Solid, stateMgr); +void CBallCamera::ProcessInput(const CFinalInput& input, CStateManager& mgr) { + if (input.ControllerIdx() != 0) + return; + + if (TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject)) { + if (player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { + switch (x400_state) { + case EBallCameraState::Chase: + if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::ChaseCamera, input) || player->IsInFreeLook()) + SetState(EBallCameraState::Default, mgr); break; - } - case EScriptObjectMessage::Deleted: - stateMgr.FreeScriptObject(x46c_collisionActorId); - x46c_collisionActorId = kInvalidUniqueId; + case EBallCameraState::Boost: + if (!player->GetMorphBall()->IsInBoost()) + SetState(EBallCameraState::Default, mgr); break; - default: + case EBallCameraState::Default: + if (x18c_25_chaseAllowed && ControlMapper::GetPressInput(ControlMapper::ECommands::ChaseCamera, input)) + SetState(EBallCameraState::Chase, mgr); break; - } -} - -void CBallCamera::ProcessInput(const CFinalInput& input, CStateManager& mgr) -{ - if (input.ControllerIdx() != 0) - return; - - if (TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject)) - { - if (player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) - { - switch (x400_state) - { - case EBallCameraState::Chase: - if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::ChaseCamera, input) || - player->IsInFreeLook()) - SetState(EBallCameraState::Default, mgr); - break; - case EBallCameraState::Boost: - if (!player->GetMorphBall()->IsInBoost()) - SetState(EBallCameraState::Default, mgr); - break; - case EBallCameraState::Default: - if (x18c_25_chaseAllowed && - ControlMapper::GetPressInput(ControlMapper::ECommands::ChaseCamera, input)) - SetState(EBallCameraState::Chase, mgr); - break; - default: - break; - } - - if (x18c_26_boostAllowed && x400_state != EBallCameraState::Boost && - (player->GetMorphBall()->IsInBoost() || player->GetMorphBall()->GetBoostChargeTime() > 0.f)) - SetState(EBallCameraState::Boost, mgr); - } - } -} - -void CBallCamera::Reset(const zeus::CTransform& xf, CStateManager& mgr) -{ - x214_ballCameraSpring.Reset(); - x228_ballCameraCentroidSpring.Reset(); - x23c_ballCameraLookAtSpring.Reset(); - x250_ballCameraCentroidDistanceSpring.Reset(); - x41c_ballCameraChaseSpring.Reset(); - x448_ballCameraBoostSpring.Reset(); - - zeus::CVector3f desiredPos = FindDesiredPosition(x190_curMinDistance, x1a0_elevation, xf.basis[1], mgr, false); - - if (TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject)) - { - ResetPosition(mgr); - x310_idealLookVec = x1b4_lookAtOffset; - x31c_predictedLookPos = x1d8_lookPos; - if ((x1d8_lookPos - desiredPos).canBeNormalized()) - { - TeleportCamera(zeus::lookAt(desiredPos, x1d8_lookPos), mgr); - } - else - { - zeus::CTransform camXf = player->CreateTransformFromMovementDirection(); - camXf.origin = desiredPos; - TeleportCamera(camXf, mgr); - mgr.GetCameraManager()->SetPlayerCamera(mgr, GetUniqueId()); - } - - x2e8_ballVelFlat = 0.f; - x2ec_maxBallVel = 0.f; - x190_curMinDistance = x194_targetMinDistance; - x2fc_ballDeltaFlat = zeus::CVector3f::skZero; - x2f0_ballDelta = zeus::CVector3f::skZero; - x18d_28_obtuseDirection = false; - x308_speedFactor = 0.f; - x2dc_prevBallPos = player->GetBallPosition(); - x294_dampedPos = GetTranslation(); - x2a0_smallCentroid = zeus::CVector3f::skZero; - x2ac_mediumCentroid = zeus::CVector3f::skZero; - x2b8_largeCentroid = zeus::CVector3f::skZero; - x2c4_smallCollidersObsCount = 0; - x2c8_mediumCollidersObsCount = 0; - x2cc_largeCollidersObsCount = 0; - x2d0_smallColliderIt = 0; - x2d4_mediumColliderIt = 0; - x2d8_largeColliderIt = 0; - x32c_colliderMag = 1.f; - x18d_25_avoidGeometryFull = true; - x18d_27_forceProcessing = true; - Think(0.1f, mgr); - x18d_25_avoidGeometryFull = false; - x18d_27_forceProcessing = false; - } -} - -void CBallCamera::Render(const CStateManager& mgr) const -{ - // Empty -} - -void CBallCamera::SetState(EBallCameraState state, CStateManager& mgr) -{ - switch (state) - { - case EBallCameraState::ToBall: - { - zeus::CTransform xf = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform(); - SetTransform(xf); - TeleportCamera(xf.origin, mgr); - SetFovInterpolation(mgr.GetCameraManager()->GetFirstPersonCamera()->GetFov(), - CCameraManager::ThirdPersonFOV(), 1.f, 0.f); - x36c_splineState = ESplineState::Invalid; - } - case EBallCameraState::Default: - case EBallCameraState::Chase: - case EBallCameraState::Boost: - mgr.SetGameState(CStateManager::EGameState::Running); + default: break; - case EBallCameraState::FromBall: - mgr.GetCameraManager()->SetPlayerCamera(mgr, GetUniqueId()); - mgr.SetGameState(CStateManager::EGameState::Running); - SetFovInterpolation(GetFov(), CCameraManager::FirstPersonFOV(), 1.f, 0.f); - x36c_splineState = ESplineState::Invalid; - break; - default: - break; - } + } - x400_state = state; + if (x18c_26_boostAllowed && x400_state != EBallCameraState::Boost && + (player->GetMorphBall()->IsInBoost() || player->GetMorphBall()->GetBoostChargeTime() > 0.f)) + SetState(EBallCameraState::Boost, mgr); + } + } } -static const CMaterialFilter BallCameraFilter = - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, EMaterialTypes::Character, - EMaterialTypes::CameraPassthrough}); +void CBallCamera::Reset(const zeus::CTransform& xf, CStateManager& mgr) { + x214_ballCameraSpring.Reset(); + x228_ballCameraCentroidSpring.Reset(); + x23c_ballCameraLookAtSpring.Reset(); + x250_ballCameraCentroidDistanceSpring.Reset(); + x41c_ballCameraChaseSpring.Reset(); + x448_ballCameraBoostSpring.Reset(); -void CBallCamera::BuildSplineNav(CStateManager& mgr) -{ - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - TUniqueId intersectId = kInvalidUniqueId; - rstl::reserved_vector nearList; - CRayCastResult result = mgr.RayWorldIntersection(intersectId, ballPos, zeus::CVector3f::skDown, 20.f, - BallCameraFilter, nearList); - float downFactor = result.IsValid() ? zeus::clamp(0.f, result.GetT() / 20.f, 1.f) : 1.f; - x36c_splineState = ESplineState::Nav; - x370_24_reevalSplineEnd = true; - x3d0_24_camBehindFloorOrWall = false; - x37c_camSpline.Reset(4); - x37c_camSpline.AddKnot(GetTranslation(), zeus::CVector3f::skForward); - float elevation = x1a0_elevation; - float distance = x190_curMinDistance; - ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); - zeus::CVector3f pt1(x35c_splineIntermediatePos.x(), x35c_splineIntermediatePos.y(), GetTranslation().z()); - x37c_camSpline.AddKnot(pt1, zeus::CVector3f::skForward); - zeus::CVector3f pt2 = pt1 + (x35c_splineIntermediatePos - GetTranslation()) * (0.5f + downFactor); - x37c_camSpline.AddKnot(pt2, zeus::CVector3f::skForward); - zeus::CVector3f pt2Ball = ballPos - pt2; - if (pt2Ball.canBeNormalized()) - pt2Ball.normalize(); - else - pt2Ball = mgr.GetPlayer().GetMoveDir(); - zeus::CVector3f desiredPosition = FindDesiredPosition(distance, elevation, pt2Ball, mgr, false); - x37c_camSpline.AddKnot(desiredPosition, zeus::CVector3f::skForward); - x37c_camSpline.UpdateSplineLength(); - x3d0_24_camBehindFloorOrWall = false; - CMaterialList intersectMat; - x3c8_collisionExcludeList = CMaterialList(EMaterialTypes::Floor, EMaterialTypes::Ceiling); - if (!SplineIntersectTest(intersectMat, mgr)) - { - if (intersectMat.HasMaterial(EMaterialTypes::Floor) || intersectMat.HasMaterial(EMaterialTypes::Wall)) - { - x3d0_24_camBehindFloorOrWall = true; - x3c8_collisionExcludeList = CMaterialList(); - } + zeus::CVector3f desiredPos = FindDesiredPosition(x190_curMinDistance, x1a0_elevation, xf.basis[1], mgr, false); + + if (TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject)) { + ResetPosition(mgr); + x310_idealLookVec = x1b4_lookAtOffset; + x31c_predictedLookPos = x1d8_lookPos; + if ((x1d8_lookPos - desiredPos).canBeNormalized()) { + TeleportCamera(zeus::lookAt(desiredPos, x1d8_lookPos), mgr); + } else { + zeus::CTransform camXf = player->CreateTransformFromMovementDirection(); + camXf.origin = desiredPos; + TeleportCamera(camXf, mgr); + mgr.GetCameraManager()->SetPlayerCamera(mgr, GetUniqueId()); } - x374_splineCtrl = 0.5f * downFactor + 2.f; - x378_splineCtrlRange = 2.5f; -} -void CBallCamera::BuildSplineArc(CStateManager& mgr) -{ - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - x36c_splineState = ESplineState::Arc; - x370_24_reevalSplineEnd = false; - x37c_camSpline.Reset(4); - x37c_camSpline.AddKnot(GetTranslation(), zeus::CVector3f::skForward); - float elevation = x1a0_elevation; - float distance = x190_curMinDistance; - ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); - zeus::CVector3f halfwayPoint = (ballPos.toVec2f() - GetTranslation().toVec2f()) * 0.5f + GetTranslation().toVec2f(); - halfwayPoint.z() = GetTranslation().z(); - zeus::CVector3f delta = GetTranslation() - halfwayPoint; - zeus::CQuaternion rot; - rot.rotateZ(zeus::degToRad(45.f)); - if (mgr.GetPlayer().GetMoveDir().cross(x34_transform.basis[1]).z() >= 0.f) - { - rot = zeus::CQuaternion(); - rot.rotateZ(zeus::degToRad(-45.f)); - } - delta = rot.transform(delta); - zeus::CVector3f pt1 = halfwayPoint + delta; - TUniqueId intersectId = kInvalidUniqueId; - rstl::reserved_vector nearList; - CRayCastResult result = - mgr.RayWorldIntersection(intersectId, pt1, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); - if (result.IsValid()) - pt1 = delta.normalized() * 1.5f + result.GetPoint(); - else - pt1 = halfwayPoint + delta; - x37c_camSpline.AddKnot(pt1, zeus::CVector3f::skForward); - FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, false); - delta = rot.transform(delta); - zeus::CVector3f pt2 = halfwayPoint + delta; - result = - mgr.RayWorldIntersection(intersectId, pt2, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); - if (result.IsValid()) - pt2 = delta.normalized() * 2.f + result.GetPoint(); - else - pt2 = halfwayPoint + delta; - x37c_camSpline.AddKnot(pt2, zeus::CVector3f::skForward); - delta = rot.transform(delta); - zeus::CVector3f pt3 = delta + halfwayPoint; - result = - mgr.RayWorldIntersection(intersectId, pt3, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); - if (result.IsValid()) - pt3 = delta.normalized() * 2.f + result.GetPoint(); - else - pt3 = halfwayPoint + delta; - x37c_camSpline.AddKnot(pt3, zeus::CVector3f::skForward); - CMaterialList intersectMat; - if (!SplineIntersectTest(intersectMat, mgr) && intersectMat.HasMaterial(EMaterialTypes::Wall)) - { - delta = pt1 - halfwayPoint; - result = - mgr.RayWorldIntersection(intersectId, pt1, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); - if (result.IsValid() && !result.GetMaterial().HasMaterial(EMaterialTypes::Pillar)) - x37c_camSpline.SetKnotPosition(1, result.GetPoint() - delta.normalized() * 0.3f * 1.25f); - delta = pt2 - halfwayPoint; - result = - mgr.RayWorldIntersection(intersectId, pt2, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); - if (result.IsValid() && !result.GetMaterial().HasMaterial(EMaterialTypes::Pillar)) - x37c_camSpline.SetKnotPosition(2, result.GetPoint() - delta.normalized() * 0.3f * 1.25f); - x37c_camSpline.UpdateSplineLength(); - if (!SplineIntersectTest(intersectMat, mgr)) - { - x36c_splineState = ESplineState::Invalid; - return; - } - } - x374_splineCtrl = 0.5f; - x378_splineCtrlRange = 0.5f; - x37c_camSpline.UpdateSplineLength(); - x3c8_collisionExcludeList = CMaterialList(); -} - -bool CBallCamera::ShouldResetSpline(CStateManager& mgr) const -{ - return x400_state != EBallCameraState::ToBall && !mgr.GetCameraManager()->IsInterpolationCameraActive() && - mgr.GetPlayer().GetMorphBall()->GetSpiderBallState() != CMorphBall::ESpiderBallState::Active && - x36c_splineState == ESplineState::Invalid && - (x188_behaviour > EBallCameraBehaviour::SpindleCamera || - x188_behaviour < EBallCameraBehaviour::HintFixedPosition); -} - -void CBallCamera::UpdatePlayerMovement(float dt, CStateManager& mgr) -{ - x2ec_maxBallVel = std::fabs(mgr.GetPlayer().GetActualBallMaxVelocity(dt)); - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - x2f0_ballDelta = ballPos - x2dc_prevBallPos; - x2fc_ballDeltaFlat = x2f0_ballDelta; - x2fc_ballDeltaFlat.z() = 0.f; - if (x2fc_ballDeltaFlat.canBeNormalized()) - x2e8_ballVelFlat = x2fc_ballDeltaFlat.magnitude() / dt; - else - x2e8_ballVelFlat = 0.f; - x2dc_prevBallPos = ballPos; + x2e8_ballVelFlat = 0.f; + x2ec_maxBallVel = 0.f; + x190_curMinDistance = x194_targetMinDistance; + x2fc_ballDeltaFlat = zeus::CVector3f::skZero; + x2f0_ballDelta = zeus::CVector3f::skZero; x18d_28_obtuseDirection = false; - zeus::CVector3f camToBallFlat = ballPos - GetTranslation(); - camToBallFlat.z() = 0.f; - if (camToBallFlat.canBeNormalized()) - { - camToBallFlat.normalize(); - if (std::fabs(std::acos(zeus::clamp(-1.f, camToBallFlat.dot(mgr.GetPlayer().GetMoveDir()), 1.f))) > - zeus::degToRad(100.f)) - x18d_28_obtuseDirection = true; - } x308_speedFactor = 0.f; - float tmpVel = x2e8_ballVelFlat - 4.f; - if (tmpVel > 0.f) - x308_speedFactor = zeus::clamp(-1.f, - std::fabs(std::sin(zeus::degToRad(tmpVel / (x2ec_maxBallVel - 4.f) * 90.f))), 1.f); - x190_curMinDistance = x308_speedFactor * (x198_maxDistance - x194_targetMinDistance) + x194_targetMinDistance; - if (x308_speedFactor > 0.5f && mgr.GetPlayer().GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround) - x30c_speedingTime += dt * x308_speedFactor; - else - x30c_speedingTime = 0.f; - x30c_speedingTime = zeus::clamp(0.f, x30c_speedingTime, 3.f); + x2dc_prevBallPos = player->GetBallPosition(); + x294_dampedPos = GetTranslation(); + x2a0_smallCentroid = zeus::CVector3f::skZero; + x2ac_mediumCentroid = zeus::CVector3f::skZero; + x2b8_largeCentroid = zeus::CVector3f::skZero; + x2c4_smallCollidersObsCount = 0; + x2c8_mediumCollidersObsCount = 0; + x2cc_largeCollidersObsCount = 0; + x2d0_smallColliderIt = 0; + x2d4_mediumColliderIt = 0; + x2d8_largeColliderIt = 0; + x32c_colliderMag = 1.f; + x18d_25_avoidGeometryFull = true; + x18d_27_forceProcessing = true; + Think(0.1f, mgr); + x18d_25_avoidGeometryFull = false; + x18d_27_forceProcessing = false; + } } -void CBallCamera::UpdateTransform(const zeus::CVector3f& lookDir, const zeus::CVector3f& pos, - float dt, CStateManager& mgr) -{ - zeus::CVector3f useLookDir = lookDir; - if (x18d_31_overrideLookDir) - if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) - useLookDir = hint->GetTransform().basis[1]; - zeus::CVector3f lookDirFlat = useLookDir; - lookDirFlat.z() = 0.f; - if (!lookDirFlat.canBeNormalized()) - { - SetTranslation(pos); - return; +void CBallCamera::Render(const CStateManager& mgr) const { + // Empty +} + +void CBallCamera::SetState(EBallCameraState state, CStateManager& mgr) { + switch (state) { + case EBallCameraState::ToBall: { + zeus::CTransform xf = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform(); + SetTransform(xf); + TeleportCamera(xf.origin, mgr); + SetFovInterpolation(mgr.GetCameraManager()->GetFirstPersonCamera()->GetFov(), CCameraManager::ThirdPersonFOV(), 1.f, + 0.f); + x36c_splineState = ESplineState::Invalid; + } + case EBallCameraState::Default: + case EBallCameraState::Chase: + case EBallCameraState::Boost: + mgr.SetGameState(CStateManager::EGameState::Running); + break; + case EBallCameraState::FromBall: + mgr.GetCameraManager()->SetPlayerCamera(mgr, GetUniqueId()); + mgr.SetGameState(CStateManager::EGameState::Running); + SetFovInterpolation(GetFov(), CCameraManager::FirstPersonFOV(), 1.f, 0.f); + x36c_splineState = ESplineState::Invalid; + break; + default: + break; + } + + x400_state = state; +} + +static const CMaterialFilter BallCameraFilter = CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, EMaterialTypes::Character, + EMaterialTypes::CameraPassthrough}); + +void CBallCamera::BuildSplineNav(CStateManager& mgr) { + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + TUniqueId intersectId = kInvalidUniqueId; + rstl::reserved_vector nearList; + CRayCastResult result = + mgr.RayWorldIntersection(intersectId, ballPos, zeus::CVector3f::skDown, 20.f, BallCameraFilter, nearList); + float downFactor = result.IsValid() ? zeus::clamp(0.f, result.GetT() / 20.f, 1.f) : 1.f; + x36c_splineState = ESplineState::Nav; + x370_24_reevalSplineEnd = true; + x3d0_24_camBehindFloorOrWall = false; + x37c_camSpline.Reset(4); + x37c_camSpline.AddKnot(GetTranslation(), zeus::CVector3f::skForward); + float elevation = x1a0_elevation; + float distance = x190_curMinDistance; + ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); + zeus::CVector3f pt1(x35c_splineIntermediatePos.x(), x35c_splineIntermediatePos.y(), GetTranslation().z()); + x37c_camSpline.AddKnot(pt1, zeus::CVector3f::skForward); + zeus::CVector3f pt2 = pt1 + (x35c_splineIntermediatePos - GetTranslation()) * (0.5f + downFactor); + x37c_camSpline.AddKnot(pt2, zeus::CVector3f::skForward); + zeus::CVector3f pt2Ball = ballPos - pt2; + if (pt2Ball.canBeNormalized()) + pt2Ball.normalize(); + else + pt2Ball = mgr.GetPlayer().GetMoveDir(); + zeus::CVector3f desiredPosition = FindDesiredPosition(distance, elevation, pt2Ball, mgr, false); + x37c_camSpline.AddKnot(desiredPosition, zeus::CVector3f::skForward); + x37c_camSpline.UpdateSplineLength(); + x3d0_24_camBehindFloorOrWall = false; + CMaterialList intersectMat; + x3c8_collisionExcludeList = CMaterialList(EMaterialTypes::Floor, EMaterialTypes::Ceiling); + if (!SplineIntersectTest(intersectMat, mgr)) { + if (intersectMat.HasMaterial(EMaterialTypes::Floor) || intersectMat.HasMaterial(EMaterialTypes::Wall)) { + x3d0_24_camBehindFloorOrWall = true; + x3c8_collisionExcludeList = CMaterialList(); } - zeus::CVector3f curLookDir = x34_transform.basis[1]; - if (curLookDir.canBeNormalized()) - { - curLookDir.normalize(); - } - else - { - SetTransform(zeus::lookAt(pos, pos + useLookDir)); - return; - } - float lookDirDot = zeus::clamp(-1.f, curLookDir.dot(useLookDir), 1.f); - if (std::fabs(lookDirDot) >= 1.f) - { - SetTransform(zeus::lookAt(pos, pos + useLookDir)); - } - else - { - float angleSpeedMul = zeus::clamp(0.f, std::acos(lookDirDot) / (zeus::degToRad(60.f) * dt), 1.f); - float angleDelta = dt * x1a4_curAnglePerSecond * angleSpeedMul; - float lookUpDot = std::fabs(zeus::clamp(-1.f, useLookDir.dot(zeus::CVector3f::skUp), 1.f)); - float maxAngleDelta = (1.f - lookUpDot) * zeus::degToRad(720.f) * dt; - if (x36c_splineState == ESplineState::Nav) - { - maxAngleDelta = zeus::degToRad(240.f) * dt; - if (angleDelta > maxAngleDelta) - angleDelta = maxAngleDelta; - } - if (angleDelta > maxAngleDelta && !mgr.GetPlayer().IsMorphBallTransitioning() && lookUpDot > 0.999f) - angleDelta = maxAngleDelta; - switch (x400_state) - { - case EBallCameraState::Chase: - if (x18c_25_chaseAllowed) - angleDelta = dt * x40c_chaseAnglePerSecond * angleSpeedMul; - break; - case EBallCameraState::Boost: - angleDelta = dt * x438_boostAnglePerSecond * angleSpeedMul; - break; - default: - break; - } - if (x18d_26_lookAtBall || mgr.GetCameraManager()->IsInterpolationCameraActive()) - { - x18d_26_lookAtBall = false; - SetTransform(zeus::CQuaternion::lookAt(curLookDir, useLookDir, 2.f * M_PIF).toTransform() * - x34_transform.getRotation()); - } - else - { - SetTransform(zeus::CQuaternion::lookAt(curLookDir, useLookDir, angleDelta).toTransform() * - x34_transform.getRotation()); - } + } + x374_splineCtrl = 0.5f * downFactor + 2.f; + x378_splineCtrlRange = 2.5f; +} + +void CBallCamera::BuildSplineArc(CStateManager& mgr) { + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + x36c_splineState = ESplineState::Arc; + x370_24_reevalSplineEnd = false; + x37c_camSpline.Reset(4); + x37c_camSpline.AddKnot(GetTranslation(), zeus::CVector3f::skForward); + float elevation = x1a0_elevation; + float distance = x190_curMinDistance; + ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); + zeus::CVector3f halfwayPoint = (ballPos.toVec2f() - GetTranslation().toVec2f()) * 0.5f + GetTranslation().toVec2f(); + halfwayPoint.z() = GetTranslation().z(); + zeus::CVector3f delta = GetTranslation() - halfwayPoint; + zeus::CQuaternion rot; + rot.rotateZ(zeus::degToRad(45.f)); + if (mgr.GetPlayer().GetMoveDir().cross(x34_transform.basis[1]).z() >= 0.f) { + rot = zeus::CQuaternion(); + rot.rotateZ(zeus::degToRad(-45.f)); + } + delta = rot.transform(delta); + zeus::CVector3f pt1 = halfwayPoint + delta; + TUniqueId intersectId = kInvalidUniqueId; + rstl::reserved_vector nearList; + CRayCastResult result = + mgr.RayWorldIntersection(intersectId, pt1, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); + if (result.IsValid()) + pt1 = delta.normalized() * 1.5f + result.GetPoint(); + else + pt1 = halfwayPoint + delta; + x37c_camSpline.AddKnot(pt1, zeus::CVector3f::skForward); + FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, false); + delta = rot.transform(delta); + zeus::CVector3f pt2 = halfwayPoint + delta; + result = + mgr.RayWorldIntersection(intersectId, pt2, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); + if (result.IsValid()) + pt2 = delta.normalized() * 2.f + result.GetPoint(); + else + pt2 = halfwayPoint + delta; + x37c_camSpline.AddKnot(pt2, zeus::CVector3f::skForward); + delta = rot.transform(delta); + zeus::CVector3f pt3 = delta + halfwayPoint; + result = + mgr.RayWorldIntersection(intersectId, pt3, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); + if (result.IsValid()) + pt3 = delta.normalized() * 2.f + result.GetPoint(); + else + pt3 = halfwayPoint + delta; + x37c_camSpline.AddKnot(pt3, zeus::CVector3f::skForward); + CMaterialList intersectMat; + if (!SplineIntersectTest(intersectMat, mgr) && intersectMat.HasMaterial(EMaterialTypes::Wall)) { + delta = pt1 - halfwayPoint; + result = + mgr.RayWorldIntersection(intersectId, pt1, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); + if (result.IsValid() && !result.GetMaterial().HasMaterial(EMaterialTypes::Pillar)) + x37c_camSpline.SetKnotPosition(1, result.GetPoint() - delta.normalized() * 0.3f * 1.25f); + delta = pt2 - halfwayPoint; + result = + mgr.RayWorldIntersection(intersectId, pt2, -delta.normalized(), delta.magnitude(), BallCameraFilter, nearList); + if (result.IsValid() && !result.GetMaterial().HasMaterial(EMaterialTypes::Pillar)) + x37c_camSpline.SetKnotPosition(2, result.GetPoint() - delta.normalized() * 0.3f * 1.25f); + x37c_camSpline.UpdateSplineLength(); + if (!SplineIntersectTest(intersectMat, mgr)) { + x36c_splineState = ESplineState::Invalid; + return; } + } + x374_splineCtrl = 0.5f; + x378_splineCtrlRange = 0.5f; + x37c_camSpline.UpdateSplineLength(); + x3c8_collisionExcludeList = CMaterialList(); +} + +bool CBallCamera::ShouldResetSpline(CStateManager& mgr) const { + return x400_state != EBallCameraState::ToBall && !mgr.GetCameraManager()->IsInterpolationCameraActive() && + mgr.GetPlayer().GetMorphBall()->GetSpiderBallState() != CMorphBall::ESpiderBallState::Active && + x36c_splineState == ESplineState::Invalid && + (x188_behaviour > EBallCameraBehaviour::SpindleCamera || + x188_behaviour < EBallCameraBehaviour::HintFixedPosition); +} + +void CBallCamera::UpdatePlayerMovement(float dt, CStateManager& mgr) { + x2ec_maxBallVel = std::fabs(mgr.GetPlayer().GetActualBallMaxVelocity(dt)); + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + x2f0_ballDelta = ballPos - x2dc_prevBallPos; + x2fc_ballDeltaFlat = x2f0_ballDelta; + x2fc_ballDeltaFlat.z() = 0.f; + if (x2fc_ballDeltaFlat.canBeNormalized()) + x2e8_ballVelFlat = x2fc_ballDeltaFlat.magnitude() / dt; + else + x2e8_ballVelFlat = 0.f; + x2dc_prevBallPos = ballPos; + x18d_28_obtuseDirection = false; + zeus::CVector3f camToBallFlat = ballPos - GetTranslation(); + camToBallFlat.z() = 0.f; + if (camToBallFlat.canBeNormalized()) { + camToBallFlat.normalize(); + if (std::fabs(std::acos(zeus::clamp(-1.f, camToBallFlat.dot(mgr.GetPlayer().GetMoveDir()), 1.f))) > + zeus::degToRad(100.f)) + x18d_28_obtuseDirection = true; + } + x308_speedFactor = 0.f; + float tmpVel = x2e8_ballVelFlat - 4.f; + if (tmpVel > 0.f) + x308_speedFactor = + zeus::clamp(-1.f, std::fabs(std::sin(zeus::degToRad(tmpVel / (x2ec_maxBallVel - 4.f) * 90.f))), 1.f); + x190_curMinDistance = x308_speedFactor * (x198_maxDistance - x194_targetMinDistance) + x194_targetMinDistance; + if (x308_speedFactor > 0.5f && mgr.GetPlayer().GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround) + x30c_speedingTime += dt * x308_speedFactor; + else + x30c_speedingTime = 0.f; + x30c_speedingTime = zeus::clamp(0.f, x30c_speedingTime, 3.f); +} + +void CBallCamera::UpdateTransform(const zeus::CVector3f& lookDir, const zeus::CVector3f& pos, float dt, + CStateManager& mgr) { + zeus::CVector3f useLookDir = lookDir; + if (x18d_31_overrideLookDir) + if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) + useLookDir = hint->GetTransform().basis[1]; + zeus::CVector3f lookDirFlat = useLookDir; + lookDirFlat.z() = 0.f; + if (!lookDirFlat.canBeNormalized()) { SetTranslation(pos); + return; + } + zeus::CVector3f curLookDir = x34_transform.basis[1]; + if (curLookDir.canBeNormalized()) { + curLookDir.normalize(); + } else { + SetTransform(zeus::lookAt(pos, pos + useLookDir)); + return; + } + float lookDirDot = zeus::clamp(-1.f, curLookDir.dot(useLookDir), 1.f); + if (std::fabs(lookDirDot) >= 1.f) { + SetTransform(zeus::lookAt(pos, pos + useLookDir)); + } else { + float angleSpeedMul = zeus::clamp(0.f, std::acos(lookDirDot) / (zeus::degToRad(60.f) * dt), 1.f); + float angleDelta = dt * x1a4_curAnglePerSecond * angleSpeedMul; + float lookUpDot = std::fabs(zeus::clamp(-1.f, useLookDir.dot(zeus::CVector3f::skUp), 1.f)); + float maxAngleDelta = (1.f - lookUpDot) * zeus::degToRad(720.f) * dt; + if (x36c_splineState == ESplineState::Nav) { + maxAngleDelta = zeus::degToRad(240.f) * dt; + if (angleDelta > maxAngleDelta) + angleDelta = maxAngleDelta; + } + if (angleDelta > maxAngleDelta && !mgr.GetPlayer().IsMorphBallTransitioning() && lookUpDot > 0.999f) + angleDelta = maxAngleDelta; + switch (x400_state) { + case EBallCameraState::Chase: + if (x18c_25_chaseAllowed) + angleDelta = dt * x40c_chaseAnglePerSecond * angleSpeedMul; + break; + case EBallCameraState::Boost: + angleDelta = dt * x438_boostAnglePerSecond * angleSpeedMul; + break; + default: + break; + } + if (x18d_26_lookAtBall || mgr.GetCameraManager()->IsInterpolationCameraActive()) { + x18d_26_lookAtBall = false; + SetTransform(zeus::CQuaternion::lookAt(curLookDir, useLookDir, 2.f * M_PIF).toTransform() * + x34_transform.getRotation()); + } else { + SetTransform(zeus::CQuaternion::lookAt(curLookDir, useLookDir, angleDelta).toTransform() * + x34_transform.getRotation()); + } + } + SetTranslation(pos); } zeus::CVector3f CBallCamera::ConstrainYawAngle(const CPlayer& player, float distance, float yawSpeed, float dt, - CStateManager& mgr) const -{ - zeus::CVector3f playerToCamFlat = GetTranslation() - player.GetTranslation(); - playerToCamFlat.z() = 0.f; - zeus::CVector3f lookDir = player.GetTransform().basis[1]; - if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) - { - lookDir = player.GetMoveDir(); - TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId); - if ((!door || !door->x2a8_26_isOpen) && - (x400_state == EBallCameraState::Boost || x400_state == EBallCameraState::Chase)) - lookDir = player.GetLeaveMorphDir(); - } - if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphing) - lookDir = player.GetLeaveMorphDir(); - if (lookDir.canBeNormalized()) - lookDir.normalize(); - else - lookDir = -playerToCamFlat; - if (playerToCamFlat.canBeNormalized()) - playerToCamFlat.normalize(); - else - return -lookDir; - float angleProj = zeus::clamp(-1.f, playerToCamFlat.dot(-lookDir), 1.f); - if (angleProj >= 1.f) - return -lookDir; - return zeus::CQuaternion::lookAt(playerToCamFlat, -lookDir, distance * dt * - zeus::clamp(0.f, std::acos(angleProj) / yawSpeed, 1.f)).transform(playerToCamFlat); + CStateManager& mgr) const { + zeus::CVector3f playerToCamFlat = GetTranslation() - player.GetTranslation(); + playerToCamFlat.z() = 0.f; + zeus::CVector3f lookDir = player.GetTransform().basis[1]; + if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { + lookDir = player.GetMoveDir(); + TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId); + if ((!door || !door->x2a8_26_isOpen) && + (x400_state == EBallCameraState::Boost || x400_state == EBallCameraState::Chase)) + lookDir = player.GetLeaveMorphDir(); + } + if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphing) + lookDir = player.GetLeaveMorphDir(); + if (lookDir.canBeNormalized()) + lookDir.normalize(); + else + lookDir = -playerToCamFlat; + if (playerToCamFlat.canBeNormalized()) + playerToCamFlat.normalize(); + else + return -lookDir; + float angleProj = zeus::clamp(-1.f, playerToCamFlat.dot(-lookDir), 1.f); + if (angleProj >= 1.f) + return -lookDir; + return zeus::CQuaternion::lookAt(playerToCamFlat, -lookDir, + distance * dt * zeus::clamp(0.f, std::acos(angleProj) / yawSpeed, 1.f)) + .transform(playerToCamFlat); } -void CBallCamera::CheckFailsafe(float dt, CStateManager& mgr) -{ - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - x18d_24_prevClearLOS = x18c_31_clearLOS; - zeus::CVector3f camToBall = ballPos - GetTranslation(); - float camToBallMag = camToBall.magnitude(); - camToBall.normalize(); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, GetTranslation(), camToBall, camToBallMag, BallCameraFilter, nullptr); - CRayCastResult result = - mgr.RayWorldIntersection(x368_obscuringObjectId, GetTranslation(), camToBall, - camToBallMag, BallCameraFilter, nearList); +void CBallCamera::CheckFailsafe(float dt, CStateManager& mgr) { + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + x18d_24_prevClearLOS = x18c_31_clearLOS; + zeus::CVector3f camToBall = ballPos - GetTranslation(); + float camToBallMag = camToBall.magnitude(); + camToBall.normalize(); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, GetTranslation(), camToBall, camToBallMag, BallCameraFilter, nullptr); + CRayCastResult result = mgr.RayWorldIntersection(x368_obscuringObjectId, GetTranslation(), camToBall, camToBallMag, + BallCameraFilter, nearList); + if (result.IsValid()) { + x350_obscuringMaterial = result.GetMaterial(); + if (!mgr.RayCollideWorld(GetTranslation(), ballPos, nearList, BallCameraFilter, &mgr.GetPlayer()) && + !mgr.RayCollideWorld(GetTranslation(), mgr.GetPlayer().GetTranslation(), nearList, BallCameraFilter, + &mgr.GetPlayer())) { + x18c_31_clearLOS = false; + if (x18d_24_prevClearLOS) { + x35c_splineIntermediatePos = ballPos; + if (ShouldResetSpline(mgr) && !x18e_25_noSpline && x350_obscuringMaterial.HasMaterial(EMaterialTypes::Floor) && + mgr.RayCollideWorld(ballPos, ballPos + zeus::CVector3f(0.f, 0.f, -2.5f), nearList, BallCameraFilter, + nullptr)) + BuildSplineNav(mgr); + } + } + } else { + x18c_31_clearLOS = true; + x350_obscuringMaterial = CMaterialList(EMaterialTypes::NoStepLogic); + } + + if (!x18c_31_clearLOS) { + x34c_obscuredTime += dt; + if (ShouldResetSpline(mgr) && !x18e_25_noSpline && x350_obscuringMaterial.HasMaterial(EMaterialTypes::Pillar)) + BuildSplineArc(mgr); + } else { + x34c_obscuredTime = 0.f; + } + + x358_unobscureMag = zeus::clamp(0.f, x34c_obscuredTime * 0.5f, 1.f); + + x3e4_pendingFailsafe = + x18c_27_obscureAvoidance && + (x34c_obscuredTime > 2.f || (x3dc_tooCloseActorId != kInvalidUniqueId && x34c_obscuredTime > 1.f)) && + !x18c_31_clearLOS && x36c_splineState == ESplineState::Invalid; + + bool doFailsafe = x3e4_pendingFailsafe; + if ((GetTranslation() - ballPos).magnitude() < 0.3f + g_tweakPlayer->GetPlayerBallHalfExtent()) + doFailsafe = true; + + if (x18e_27_nearbyDoorClosed) { + x18e_27_nearbyDoorClosed = false; if (result.IsValid()) - { - x350_obscuringMaterial = result.GetMaterial(); - if (!mgr.RayCollideWorld(GetTranslation(), ballPos, nearList, BallCameraFilter, &mgr.GetPlayer()) && - !mgr.RayCollideWorld(GetTranslation(), mgr.GetPlayer().GetTranslation(), nearList, - BallCameraFilter, &mgr.GetPlayer())) - { - x18c_31_clearLOS = false; - if (x18d_24_prevClearLOS) - { - x35c_splineIntermediatePos = ballPos; - if (ShouldResetSpline(mgr) && !x18e_25_noSpline && - x350_obscuringMaterial.HasMaterial(EMaterialTypes::Floor) && - mgr.RayCollideWorld(ballPos, ballPos + zeus::CVector3f(0.f, 0.f, -2.5f), - nearList, BallCameraFilter, nullptr)) - BuildSplineNav(mgr); - } + doFailsafe = true; + } + + if (x18e_28_nearbyDoorClosing) { + x18e_28_nearbyDoorClosing = false; + if (IsBallNearDoor(GetTranslation(), mgr)) + doFailsafe = true; + } + + if (doFailsafe) + ActivateFailsafe(dt, mgr); +} + +void CBallCamera::UpdateObjectTooCloseId(CStateManager& mgr) { + x3e0_tooCloseActorDist = 1000000.f; + x3dc_tooCloseActorId = kInvalidUniqueId; + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) { + if (TCastToPtr door = ent) { + if (mgr.GetPlayer().GetAreaIdAlways() == door->GetAreaIdAlways()) { + door->GetBoundingBox(); + float minMag = std::min((door->GetTranslation() - GetTranslation()).magnitude(), + (door->GetTranslation() - ballPos).magnitude()); + if (minMag < 30.f && minMag < x3e0_tooCloseActorDist) { + x3dc_tooCloseActorId = door->GetUniqueId(); + x3e0_tooCloseActorDist = minMag; } + } } - else - { - x18c_31_clearLOS = true; - x350_obscuringMaterial = CMaterialList(EMaterialTypes::NoStepLogic); - } - - if (!x18c_31_clearLOS) - { - x34c_obscuredTime += dt; - if (ShouldResetSpline(mgr) && !x18e_25_noSpline && x350_obscuringMaterial.HasMaterial(EMaterialTypes::Pillar)) - BuildSplineArc(mgr); - } - else - { - x34c_obscuredTime = 0.f; - } - - x358_unobscureMag = zeus::clamp(0.f, x34c_obscuredTime * 0.5f, 1.f); - - x3e4_pendingFailsafe = x18c_27_obscureAvoidance && (x34c_obscuredTime > 2.f || - (x3dc_tooCloseActorId != kInvalidUniqueId && x34c_obscuredTime > 1.f)) && - !x18c_31_clearLOS && x36c_splineState == ESplineState::Invalid; - - bool doFailsafe = x3e4_pendingFailsafe; - if ((GetTranslation() - ballPos).magnitude() < 0.3f + g_tweakPlayer->GetPlayerBallHalfExtent()) - doFailsafe = true; - - if (x18e_27_nearbyDoorClosed) - { - x18e_27_nearbyDoorClosed = false; - if (result.IsValid()) - doFailsafe = true; - } - - if (x18e_28_nearbyDoorClosing) - { - x18e_28_nearbyDoorClosing = false; - if (IsBallNearDoor(GetTranslation(), mgr)) - doFailsafe = true; - } - - if (doFailsafe) - ActivateFailsafe(dt, mgr); + } } -void CBallCamera::UpdateObjectTooCloseId(CStateManager& mgr) -{ - x3e0_tooCloseActorDist = 1000000.f; - x3dc_tooCloseActorId = kInvalidUniqueId; - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) - { - if (TCastToPtr door = ent) - { - if (mgr.GetPlayer().GetAreaIdAlways() == door->GetAreaIdAlways()) - { - door->GetBoundingBox(); - float minMag = std::min((door->GetTranslation() - GetTranslation()).magnitude(), - (door->GetTranslation() - ballPos).magnitude()); - if (minMag < 30.f && minMag < x3e0_tooCloseActorDist) - { - x3dc_tooCloseActorId = door->GetUniqueId(); - x3e0_tooCloseActorDist = minMag; - } - } - } - } +void CBallCamera::UpdateAnglePerSecond(float dt) { + float delta = x1a8_targetAnglePerSecond - x1a4_curAnglePerSecond; + if (std::fabs(delta) >= M_PIF / 1800.f) + x1a4_curAnglePerSecond += zeus::clamp(-1.f, delta / M_PIF, 1.f) * (10.471975f * dt); + else + x1a4_curAnglePerSecond = x1a8_targetAnglePerSecond; } -void CBallCamera::UpdateAnglePerSecond(float dt) -{ - float delta = x1a8_targetAnglePerSecond - x1a4_curAnglePerSecond; - if (std::fabs(delta) >= M_PIF / 1800.f) - x1a4_curAnglePerSecond += zeus::clamp(-1.f, delta / M_PIF, 1.f) * (10.471975f * dt); - else - x1a4_curAnglePerSecond = x1a8_targetAnglePerSecond; +void CBallCamera::UpdateUsingPathCameras(float dt, CStateManager& mgr) { + if (TCastToPtr cam = mgr.ObjectById(mgr.GetCameraManager()->GetPathCameraId())) { + TeleportCamera(cam->GetTransform(), mgr); + x18d_26_lookAtBall = true; + } } -void CBallCamera::UpdateUsingPathCameras(float dt, CStateManager& mgr) -{ - if (TCastToPtr cam = mgr.ObjectById(mgr.GetCameraManager()->GetPathCameraId())) - { - TeleportCamera(cam->GetTransform(), mgr); - x18d_26_lookAtBall = true; - } +zeus::CVector3f CBallCamera::GetFixedLookTarget(const zeus::CVector3f& hintToLookDir, CStateManager& mgr) const { + const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr); + if (!hint) + return hintToLookDir; + zeus::CVector3f hintDir = hint->GetTransform().basis[1]; + zeus::CVector3f hintDirFlat = hintDir; + hintDirFlat.z() = 0.f; + if (hintDir.canBeNormalized() && hintDirFlat.canBeNormalized()) { + hintDir.normalize(); + hintDirFlat.normalize(); + } else { + hintDir = zeus::CVector3f::skForward; + hintDirFlat = zeus::CVector3f::skForward; + } + + zeus::CVector3f hintToLookDirFlat = hintToLookDir; + hintToLookDirFlat.z() = 0.f; + if (hintToLookDir.canBeNormalized() && hintToLookDirFlat.canBeNormalized()) + hintToLookDirFlat.normalize(); + else + hintToLookDirFlat = hintDirFlat; + + float attitude = std::acos(zeus::clamp(-1.f, hintToLookDir.dot(hintToLookDirFlat), 1.f)); + if (x18c_29_clampAttitude) { + float refAttitude = std::acos(zeus::clamp(-1.f, hintDir.dot(hintDirFlat), 1.f)); + attitude = refAttitude + zeus::clamp(-x1ac_attitudeRange, attitude - refAttitude, x1ac_attitudeRange); + } + + if (hintToLookDir.z() >= 0.f) + attitude = -attitude; + + float azimuth = std::acos(zeus::clamp(-1.f, hintToLookDirFlat.dot(hintDirFlat), 1.f)); + if (x18c_30_clampAzimuth) + azimuth = zeus::clamp(-x1b0_azimuthRange, azimuth, x1b0_azimuthRange); + + if (hintToLookDirFlat.x() * hintDirFlat.y() - hintDirFlat.x() * hintToLookDirFlat.y() >= 0.f) + azimuth = -azimuth; + + zeus::CQuaternion quat; + quat.rotateZ(azimuth); + zeus::CVector3f aziLookDirFlat = quat.transform(hintDirFlat); + zeus::CVector3f attitudeAxis(aziLookDirFlat.y(), -aziLookDirFlat.x(), 0.f); + attitudeAxis.normalize(); + return zeus::CQuaternion::fromAxisAngle(attitudeAxis, -attitude).transform(aziLookDirFlat); } -zeus::CVector3f CBallCamera::GetFixedLookTarget(const zeus::CVector3f& hintToLookDir, CStateManager& mgr) const -{ - const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr); - if (!hint) - return hintToLookDir; - zeus::CVector3f hintDir = hint->GetTransform().basis[1]; - zeus::CVector3f hintDirFlat = hintDir; - hintDirFlat.z() = 0.f; - if (hintDir.canBeNormalized() && hintDirFlat.canBeNormalized()) - { - hintDir.normalize(); - hintDirFlat.normalize(); +void CBallCamera::UpdateUsingFixedCameras(float dt, CStateManager& mgr) { + if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) { + switch (x188_behaviour) { + case EBallCameraBehaviour::HintFixedPosition: { + zeus::CVector3f hintToLookPos = x1d8_lookPos - hint->GetTranslation(); + if (hintToLookPos.canBeNormalized()) { + hintToLookPos = GetFixedLookTarget(hintToLookPos.normalized(), mgr); + if ((hint->GetHint().GetOverrideFlags() & 0x40) != 0) + x18d_26_lookAtBall = true; + UpdateTransform(hintToLookPos, hint->GetTranslation(), dt, mgr); + } + break; } - else - { - hintDir = zeus::CVector3f::skForward; - hintDirFlat = zeus::CVector3f::skForward; + case EBallCameraBehaviour::HintFixedTransform: + SetTransform(hint->GetTransform()); + break; + default: + break; } - - zeus::CVector3f hintToLookDirFlat = hintToLookDir; - hintToLookDirFlat.z() = 0.f; - if (hintToLookDir.canBeNormalized() && hintToLookDirFlat.canBeNormalized()) - hintToLookDirFlat.normalize(); - else - hintToLookDirFlat = hintDirFlat; - - float attitude = std::acos(zeus::clamp(-1.f, hintToLookDir.dot(hintToLookDirFlat), 1.f)); - if (x18c_29_clampAttitude) - { - float refAttitude = std::acos(zeus::clamp(-1.f, hintDir.dot(hintDirFlat), 1.f)); - attitude = refAttitude + zeus::clamp(-x1ac_attitudeRange, attitude - refAttitude, x1ac_attitudeRange); - } - - if (hintToLookDir.z() >= 0.f) - attitude = -attitude; - - float azimuth = std::acos(zeus::clamp(-1.f, hintToLookDirFlat.dot(hintDirFlat), 1.f)); - if (x18c_30_clampAzimuth) - azimuth = zeus::clamp(-x1b0_azimuthRange, azimuth, x1b0_azimuthRange); - - if (hintToLookDirFlat.x() * hintDirFlat.y() - hintDirFlat.x() * hintToLookDirFlat.y() >= 0.f) - azimuth = -azimuth; - - zeus::CQuaternion quat; - quat.rotateZ(azimuth); - zeus::CVector3f aziLookDirFlat = quat.transform(hintDirFlat); - zeus::CVector3f attitudeAxis(aziLookDirFlat.y(), -aziLookDirFlat.x(), 0.f); - attitudeAxis.normalize(); - return zeus::CQuaternion::fromAxisAngle(attitudeAxis, -attitude).transform(aziLookDirFlat); + TeleportCamera(GetTranslation(), mgr); + } } -void CBallCamera::UpdateUsingFixedCameras(float dt, CStateManager& mgr) -{ - if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) - { - switch (x188_behaviour) - { - case EBallCameraBehaviour::HintFixedPosition: - { - zeus::CVector3f hintToLookPos = x1d8_lookPos - hint->GetTranslation(); - if (hintToLookPos.canBeNormalized()) - { - hintToLookPos = GetFixedLookTarget(hintToLookPos.normalized(), mgr); - if ((hint->GetHint().GetOverrideFlags() & 0x40) != 0) - x18d_26_lookAtBall = true; - UpdateTransform(hintToLookPos, hint->GetTranslation(), dt, mgr); - } - break; - } - case EBallCameraBehaviour::HintFixedTransform: - SetTransform(hint->GetTransform()); - break; - default: - break; - } - TeleportCamera(GetTranslation(), mgr); - } +zeus::CVector3f CBallCamera::ComputeVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& posDelta) const { + zeus::CVector3f ret = posDelta; + if (x470_clampVelTimer > 0.f && ret.canBeNormalized() && !x18d_28_obtuseDirection) { + float mag = ret.magnitude(); + mag = zeus::clamp(-x474_clampVelRange, mag, x474_clampVelRange); + ret = ret.normalized() * mag; + } + return ret; } -zeus::CVector3f CBallCamera::ComputeVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& posDelta) const -{ - zeus::CVector3f ret = posDelta; - if (x470_clampVelTimer > 0.f && ret.canBeNormalized() && !x18d_28_obtuseDirection) - { - float mag = ret.magnitude(); - mag = zeus::clamp(-x474_clampVelRange, mag, x474_clampVelRange); - ret = ret.normalized() * mag; - } - return ret; +zeus::CVector3f CBallCamera::TweenVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& newVel, float rate, + float dt) { + zeus::CVector3f velDelta = newVel - curVel; + if (velDelta.canBeNormalized()) { + float t = zeus::clamp(-1.f, velDelta.magnitude() / (rate * dt), 1.f); + return velDelta.normalized() * rate * dt * t + curVel; + } + return newVel; } -zeus::CVector3f CBallCamera::TweenVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& newVel, - float rate, float dt) -{ - zeus::CVector3f velDelta = newVel - curVel; - if (velDelta.canBeNormalized()) - { - float t = zeus::clamp(-1.f, velDelta.magnitude() / (rate * dt), 1.f); - return velDelta.normalized() * rate * dt * t + curVel; +zeus::CVector3f CBallCamera::MoveCollisionActor(const zeus::CVector3f& pos, float dt, CStateManager& mgr) { + if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) { + zeus::CVector3f posDelta = pos - act->GetTranslation(); + if (!posDelta.canBeNormalized() || posDelta.magnitude() < 0.01f) { + act->Stop(); + return act->GetTranslation(); } - return newVel; + zeus::CVector3f oldTranslation = act->GetTranslation(); + zeus::CVector3f oldVel = act->GetVelocity(); + zeus::CVector3f newVel = ComputeVelocity(oldVel, posDelta * (1.f / dt)); + act->SetVelocityWR(newVel); + act->SetMovable(true); + act->AddMaterial(EMaterialTypes::Solid, mgr); + CGameCollision::Move(mgr, *act, dt, nullptr); + zeus::CVector3f posDelta2 = act->GetTranslation() - pos; + if (posDelta2.canBeNormalized() && posDelta2.magnitude() > 0.1f) { + act->SetTranslation(oldTranslation); + act->SetVelocityWR(TweenVelocity(oldVel, newVel, 50.f, dt)); + CGameCollision::Move(mgr, *act, dt, nullptr); + posDelta2 = act->GetTranslation() - pos; + if (posDelta2.magnitude() > 0.1f) + x478_shortMoveCount += 1; + else + x478_shortMoveCount = 0; + } else { + act->Stop(); + x478_shortMoveCount = 0; + } + act->SetMovable(false); + act->RemoveMaterial(EMaterialTypes::Solid, mgr); + return act->GetTranslation(); + } + return pos; } -zeus::CVector3f CBallCamera::MoveCollisionActor(const zeus::CVector3f& pos, float dt, CStateManager& mgr) -{ - if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) - { - zeus::CVector3f posDelta = pos - act->GetTranslation(); - if (!posDelta.canBeNormalized() || posDelta.magnitude() < 0.01f) - { - act->Stop(); - return act->GetTranslation(); - } - zeus::CVector3f oldTranslation = act->GetTranslation(); - zeus::CVector3f oldVel = act->GetVelocity(); - zeus::CVector3f newVel = ComputeVelocity(oldVel, posDelta * (1.f / dt)); - act->SetVelocityWR(newVel); - act->SetMovable(true); - act->AddMaterial(EMaterialTypes::Solid, mgr); - CGameCollision::Move(mgr, *act, dt, nullptr); - zeus::CVector3f posDelta2 = act->GetTranslation() - pos; - if (posDelta2.canBeNormalized() && posDelta2.magnitude() > 0.1f) - { - act->SetTranslation(oldTranslation); - act->SetVelocityWR(TweenVelocity(oldVel, newVel, 50.f, dt)); - CGameCollision::Move(mgr, *act, dt, nullptr); - posDelta2 = act->GetTranslation() - pos; - if (posDelta2.magnitude() > 0.1f) - x478_shortMoveCount += 1; - else - x478_shortMoveCount = 0; - } - else - { - act->Stop(); - x478_shortMoveCount = 0; - } - act->SetMovable(false); - act->RemoveMaterial(EMaterialTypes::Solid, mgr); - return act->GetTranslation(); - } - return pos; -} +void CBallCamera::UpdateUsingFreeLook(float dt, CStateManager& mgr) { + if (x400_state == EBallCameraState::ToBall || x400_state == EBallCameraState::FromBall) { + x36c_splineState = ESplineState::Invalid; + return; + } -void CBallCamera::UpdateUsingFreeLook(float dt, CStateManager& mgr) -{ - if (x400_state == EBallCameraState::ToBall || x400_state == EBallCameraState::FromBall) - { + if (x36c_splineState == ESplineState::Nav && x188_behaviour <= EBallCameraBehaviour::SpindleCamera && + x188_behaviour >= EBallCameraBehaviour::HintFixedPosition) { + x36c_splineState = ESplineState::Invalid; + return; + } + + float elevation = x1a0_elevation; + float distance = x190_curMinDistance; + ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); + + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + zeus::CVector3f knotToBall = ballPos - x37c_camSpline.GetKnotPosition(2); + if (knotToBall.canBeNormalized()) + knotToBall.normalize(); + else + knotToBall = mgr.GetPlayer().GetMoveDir(); + zeus::CVector3f knot3 = x37c_camSpline.GetKnotPosition(3); + zeus::CVector3f desiredPos = FindDesiredPosition(distance, elevation, knotToBall, mgr, false); + + if (x370_24_reevalSplineEnd) + x37c_camSpline.SetKnotPosition(3, desiredPos); + + x374_splineCtrl -= dt; + + float splineT = 1.f - zeus::clamp(0.f, x374_splineCtrl / x378_splineCtrlRange, 1.f); + if (x36c_splineState == ESplineState::Nav) { + CMaterialList intersectMat; + if (!SplineIntersectTest(intersectMat, mgr)) { + x37c_camSpline.SetKnotPosition(3, knot3); + if (intersectMat.HasMaterial(EMaterialTypes::Floor)) { x36c_splineState = ESplineState::Invalid; return; + } } + } - if (x36c_splineState == ESplineState::Nav && x188_behaviour <= EBallCameraBehaviour::SpindleCamera && - x188_behaviour >= EBallCameraBehaviour::HintFixedPosition) - { + if (x374_splineCtrl <= 0.f || (splineT > 0.75f && x18c_31_clearLOS)) { + if (x36c_splineState == ESplineState::Arc && !x18c_31_clearLOS) { + CMaterialList intersectMat; + if (!SplineIntersectTest(intersectMat, mgr)) { x36c_splineState = ESplineState::Invalid; - return; + } else { + zeus::CVector3f oldKnot2 = x37c_camSpline.GetKnotPosition(2); + zeus::CVector3f oldKnot1 = x37c_camSpline.GetKnotPosition(1); + BuildSplineArc(mgr); + x37c_camSpline.SetKnotPosition(3, x37c_camSpline.GetKnotPosition(1)); + x37c_camSpline.SetKnotPosition(2, x37c_camSpline.GetKnotPosition(0)); + x37c_camSpline.SetKnotPosition(1, oldKnot2); + x37c_camSpline.SetKnotPosition(0, oldKnot1); + x37c_camSpline.UpdateSplineLength(); + x374_splineCtrl = + x378_splineCtrlRange - x378_splineCtrlRange * (x37c_camSpline.GetKnotT(2) / x37c_camSpline.x44_length); + x374_splineCtrl -= dt; + splineT = zeus::clamp(0.f, x374_splineCtrl / x378_splineCtrlRange, 1.f); + } + } else { + x36c_splineState = ESplineState::Invalid; } + } - float elevation = x1a0_elevation; - float distance = x190_curMinDistance; - ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); + x37c_camSpline.UpdateSplineLength(); + zeus::CVector3f pos = x37c_camSpline.GetInterpolatedSplinePointByLength(splineT * x37c_camSpline.x44_length).origin; + if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) { + CMaterialFilter filter = act->GetMaterialFilter(); + CMaterialFilter tmpFilter = filter; + tmpFilter.IncludeList().Add(EMaterialTypes::Wall); + tmpFilter.ExcludeList().Add(x3c8_collisionExcludeList); + act->SetMaterialFilter(tmpFilter); + MoveCollisionActor(pos, dt, mgr); + act->SetMaterialFilter(filter); + } - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - zeus::CVector3f knotToBall = ballPos - x37c_camSpline.GetKnotPosition(2); - if (knotToBall.canBeNormalized()) - knotToBall.normalize(); - else - knotToBall = mgr.GetPlayer().GetMoveDir(); - zeus::CVector3f knot3 = x37c_camSpline.GetKnotPosition(3); - zeus::CVector3f desiredPos = FindDesiredPosition(distance, elevation, knotToBall, mgr, false); + zeus::CVector3f lookDir = x1d8_lookPos - desiredPos; + if (x18d_26_lookAtBall) + lookDir = ballPos - desiredPos; - if (x370_24_reevalSplineEnd) - x37c_camSpline.SetKnotPosition(3, desiredPos); + if (lookDir.canBeNormalized()) { + lookDir.normalize(); + UpdateTransform(lookDir, desiredPos, dt, mgr); + } - x374_splineCtrl -= dt; + TeleportCamera(desiredPos, mgr); - float splineT = 1.f - zeus::clamp(0.f, x374_splineCtrl / x378_splineCtrlRange, 1.f); - if (x36c_splineState == ESplineState::Nav) - { - CMaterialList intersectMat; - if (!SplineIntersectTest(intersectMat, mgr)) - { - x37c_camSpline.SetKnotPosition(3, knot3); - if (intersectMat.HasMaterial(EMaterialTypes::Floor)) - { - x36c_splineState = ESplineState::Invalid; - return; - } - } - } - - if (x374_splineCtrl <= 0.f || (splineT > 0.75f && x18c_31_clearLOS)) - { - if (x36c_splineState == ESplineState::Arc && !x18c_31_clearLOS) - { - CMaterialList intersectMat; - if (!SplineIntersectTest(intersectMat, mgr)) - { - x36c_splineState = ESplineState::Invalid; - } - else - { - zeus::CVector3f oldKnot2 = x37c_camSpline.GetKnotPosition(2); - zeus::CVector3f oldKnot1 = x37c_camSpline.GetKnotPosition(1); - BuildSplineArc(mgr); - x37c_camSpline.SetKnotPosition(3, x37c_camSpline.GetKnotPosition(1)); - x37c_camSpline.SetKnotPosition(2, x37c_camSpline.GetKnotPosition(0)); - x37c_camSpline.SetKnotPosition(1, oldKnot2); - x37c_camSpline.SetKnotPosition(0, oldKnot1); - x37c_camSpline.UpdateSplineLength(); - x374_splineCtrl = x378_splineCtrlRange - x378_splineCtrlRange * - (x37c_camSpline.GetKnotT(2) / x37c_camSpline.x44_length); - x374_splineCtrl -= dt; - splineT = zeus::clamp(0.f, x374_splineCtrl / x378_splineCtrlRange, 1.f); - } - } - else - { - x36c_splineState = ESplineState::Invalid; - } - } - - x37c_camSpline.UpdateSplineLength(); - zeus::CVector3f pos = x37c_camSpline.GetInterpolatedSplinePointByLength(splineT * - x37c_camSpline.x44_length).origin; - if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) - { - CMaterialFilter filter = act->GetMaterialFilter(); - CMaterialFilter tmpFilter = filter; - tmpFilter.IncludeList().Add(EMaterialTypes::Wall); - tmpFilter.ExcludeList().Add(x3c8_collisionExcludeList); - act->SetMaterialFilter(tmpFilter); - MoveCollisionActor(pos, dt, mgr); - act->SetMaterialFilter(filter); - } - - zeus::CVector3f lookDir = x1d8_lookPos - desiredPos; - if (x18d_26_lookAtBall) - lookDir = ballPos - desiredPos; - - if (lookDir.canBeNormalized()) - { - lookDir.normalize(); - UpdateTransform(lookDir, desiredPos, dt, mgr); - } - - TeleportCamera(desiredPos, mgr); - - if (x3d0_24_camBehindFloorOrWall && x374_splineCtrl / x378_splineCtrlRange < 0.5f) - x36c_splineState = ESplineState::Invalid; + if (x3d0_24_camBehindFloorOrWall && x374_splineCtrl / x378_splineCtrlRange < 0.5f) + x36c_splineState = ESplineState::Invalid; } -zeus::CVector3f CBallCamera::InterpolateCameraElevation(const zeus::CVector3f& camPos, float dt) -{ - if (x1a0_elevation < 2.f) - return camPos; +zeus::CVector3f CBallCamera::InterpolateCameraElevation(const zeus::CVector3f& camPos, float dt) { + if (x1a0_elevation < 2.f) + return camPos; - zeus::CVector3f ret = camPos; - if (!x18c_31_clearLOS && x350_obscuringMaterial.HasMaterial(EMaterialTypes::Floor)) - { - x3d4_elevInterpTimer = 1.f; - ret.z() = x3d8_elevInterpStart = GetTranslation().z(); - } - else if (x3d4_elevInterpTimer > 0.f) - { - x3d4_elevInterpTimer -= dt; - ret.z() = (camPos.z() - x3d8_elevInterpStart) * (1.f - zeus::clamp(0.f, x3d4_elevInterpTimer, 1.f)) + - x3d8_elevInterpStart; - } + zeus::CVector3f ret = camPos; + if (!x18c_31_clearLOS && x350_obscuringMaterial.HasMaterial(EMaterialTypes::Floor)) { + x3d4_elevInterpTimer = 1.f; + ret.z() = x3d8_elevInterpStart = GetTranslation().z(); + } else if (x3d4_elevInterpTimer > 0.f) { + x3d4_elevInterpTimer -= dt; + ret.z() = (camPos.z() - x3d8_elevInterpStart) * (1.f - zeus::clamp(0.f, x3d4_elevInterpTimer, 1.f)) + + x3d8_elevInterpStart; + } - return ret; + return ret; } zeus::CVector3f CBallCamera::CalculateCollidersCentroid(const std::vector& colliderList, - int numObscured) const -{ - if (colliderList.size() < 3) - return zeus::CVector3f::skForward; + int numObscured) const { + if (colliderList.size() < 3) + return zeus::CVector3f::skForward; - int clearColliders = 0; - const CCameraCollider* prevCol = &colliderList.back(); - float accumCross = 0.f; - float accumX = 0.f; - float accumZ = 0.f; - for (const CCameraCollider& col : colliderList) - { - if (prevCol->x4c_occlusionCount < 2 && col.x4c_occlusionCount < 2) - { - float z0 = prevCol->x50_scale * prevCol->x8_lastLocalPos.z(); - float x1 = prevCol->x50_scale * col.x8_lastLocalPos.x(); - float x0 = prevCol->x50_scale * prevCol->x8_lastLocalPos.x(); - float z1 = prevCol->x50_scale * col.x8_lastLocalPos.z(); + int clearColliders = 0; + const CCameraCollider* prevCol = &colliderList.back(); + float accumCross = 0.f; + float accumX = 0.f; + float accumZ = 0.f; + for (const CCameraCollider& col : colliderList) { + if (prevCol->x4c_occlusionCount < 2 && col.x4c_occlusionCount < 2) { + float z0 = prevCol->x50_scale * prevCol->x8_lastLocalPos.z(); + float x1 = prevCol->x50_scale * col.x8_lastLocalPos.x(); + float x0 = prevCol->x50_scale * prevCol->x8_lastLocalPos.x(); + float z1 = prevCol->x50_scale * col.x8_lastLocalPos.z(); - float cross = x0 * z1 - x1 * z0; - accumCross += cross; - accumX += cross * (x1 + x0); - accumZ += cross * (z1 + z0); - } - else - { - clearColliders += 1; - } - prevCol = &col; + float cross = x0 * z1 - x1 * z0; + accumCross += cross; + accumX += cross * (x1 + x0); + accumZ += cross * (z1 + z0); + } else { + clearColliders += 1; } + prevCol = &col; + } - if (clearColliders / float(colliderList.size()) <= x330_clearColliderThreshold) - { - return zeus::CVector3f::skForward; - } - else if (0.f != accumCross) - { - float baryCross = 3.f * accumCross; - return {accumX / baryCross, 0.f, accumZ / baryCross}; - } + if (clearColliders / float(colliderList.size()) <= x330_clearColliderThreshold) { + return zeus::CVector3f::skForward; + } else if (0.f != accumCross) { + float baryCross = 3.f * accumCross; + return {accumX / baryCross, 0.f, accumZ / baryCross}; + } - return {0.f, 2.f, 0.f}; + return {0.f, 2.f, 0.f}; } -zeus::CVector3f CBallCamera::ApplyColliders() -{ - zeus::CVector3f smallCentroid = CalculateCollidersCentroid(x264_smallColliders, x2c4_smallCollidersObsCount); - zeus::CVector3f mediumCentroid = CalculateCollidersCentroid(x274_mediumColliders, x2c8_mediumCollidersObsCount); - zeus::CVector3f largeCentroid = CalculateCollidersCentroid(x284_largeColliders, x2cc_largeCollidersObsCount); +zeus::CVector3f CBallCamera::ApplyColliders() { + zeus::CVector3f smallCentroid = CalculateCollidersCentroid(x264_smallColliders, x2c4_smallCollidersObsCount); + zeus::CVector3f mediumCentroid = CalculateCollidersCentroid(x274_mediumColliders, x2c8_mediumCollidersObsCount); + zeus::CVector3f largeCentroid = CalculateCollidersCentroid(x284_largeColliders, x2cc_largeCollidersObsCount); - if (smallCentroid.y() == 0.f) - x2a0_smallCentroid = smallCentroid; - else - x2a0_smallCentroid = zeus::CVector3f::skZero; + if (smallCentroid.y() == 0.f) + x2a0_smallCentroid = smallCentroid; + else + x2a0_smallCentroid = zeus::CVector3f::skZero; - float centroidX = x2a0_smallCentroid.x(); - float centroidZ = x2a0_smallCentroid.z(); + float centroidX = x2a0_smallCentroid.x(); + float centroidZ = x2a0_smallCentroid.z(); - if (mediumCentroid.y() == 0.f) - x2ac_mediumCentroid = mediumCentroid; - else - x2ac_mediumCentroid = zeus::CVector3f::skZero; + if (mediumCentroid.y() == 0.f) + x2ac_mediumCentroid = mediumCentroid; + else + x2ac_mediumCentroid = zeus::CVector3f::skZero; - centroidX += x2ac_mediumCentroid.x(); - centroidZ += x2ac_mediumCentroid.z(); + centroidX += x2ac_mediumCentroid.x(); + centroidZ += x2ac_mediumCentroid.z(); - if (largeCentroid.y() == 0.f) - x2b8_largeCentroid = largeCentroid; - else - x2b8_largeCentroid = zeus::CVector3f::skZero; + if (largeCentroid.y() == 0.f) + x2b8_largeCentroid = largeCentroid; + else + x2b8_largeCentroid = zeus::CVector3f::skZero; - centroidX += x2b8_largeCentroid.x(); - centroidZ += x2b8_largeCentroid.z(); + centroidX += x2b8_largeCentroid.x(); + centroidZ += x2b8_largeCentroid.z(); - if (x18c_31_clearLOS) - centroidX /= 1.5f; - centroidZ /= 3.f; + if (x18c_31_clearLOS) + centroidX /= 1.5f; + centroidZ /= 3.f; - if (!x18c_31_clearLOS && x368_obscuringObjectId == kInvalidUniqueId) - { - float xMul = 1.5f; - float zMul = 1.f; - if (x350_obscuringMaterial.HasMaterial(EMaterialTypes::Floor)) - zMul += 2.f * x358_unobscureMag; - if (x350_obscuringMaterial.HasMaterial(EMaterialTypes::Wall)) - xMul += 3.f * zeus::clamp(0.f, x358_unobscureMag - 0.25f, 1.f); - centroidX *= xMul; - centroidZ *= zMul; - } + if (!x18c_31_clearLOS && x368_obscuringObjectId == kInvalidUniqueId) { + float xMul = 1.5f; + float zMul = 1.f; + if (x350_obscuringMaterial.HasMaterial(EMaterialTypes::Floor)) + zMul += 2.f * x358_unobscureMag; + if (x350_obscuringMaterial.HasMaterial(EMaterialTypes::Wall)) + xMul += 3.f * zeus::clamp(0.f, x358_unobscureMag - 0.25f, 1.f); + centroidX *= xMul; + centroidZ *= zMul; + } - if (!x18c_28_volumeCollider) - return zeus::CVector3f::skZero; + if (!x18c_28_volumeCollider) + return zeus::CVector3f::skZero; - if (std::fabs(centroidX) < 0.05f) - centroidX = 0.f; - if (std::fabs(centroidZ) < 0.05f) - centroidZ = 0.f; + if (std::fabs(centroidX) < 0.05f) + centroidX = 0.f; + if (std::fabs(centroidZ) < 0.05f) + centroidZ = 0.f; - if (x18c_31_clearLOS) - centroidZ *= 0.5f; + if (x18c_31_clearLOS) + centroidZ *= 0.5f; - return {centroidX, 0.f, centroidZ}; + return {centroidX, 0.f, centroidZ}; } void CBallCamera::UpdateColliders(const zeus::CTransform& xf, std::vector& colliderList, int& it, int count, float tolerance, const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr) -{ - if (it < colliderList.size()) - { - x310_idealLookVec = {0.f, g_tweakBall->GetBallCameraOffset().y(), g_tweakPlayer->GetPlayerBallHalfExtent()}; - x310_idealLookVec.y() *= x308_speedFactor; - x31c_predictedLookPos = mgr.GetPlayer().GetMoveDir() * x310_idealLookVec.y(); - x31c_predictedLookPos.z() = float(x310_idealLookVec.z()); - x31c_predictedLookPos += mgr.GetPlayer().GetTranslation(); - zeus::CTransform predictedLookXf = zeus::lookAt(xf.origin, x31c_predictedLookPos); - float toleranceRecip = 1.f / tolerance; - for (int i=0 ; iGetBallCameraOffset().y(), g_tweakPlayer->GetPlayerBallHalfExtent()}; + x310_idealLookVec.y() *= x308_speedFactor; + x31c_predictedLookPos = mgr.GetPlayer().GetMoveDir() * x310_idealLookVec.y(); + x31c_predictedLookPos.z() = float(x310_idealLookVec.z()); + x31c_predictedLookPos += mgr.GetPlayer().GetTranslation(); + zeus::CTransform predictedLookXf = zeus::lookAt(xf.origin, x31c_predictedLookPos); + float toleranceRecip = 1.f / tolerance; + for (int i = 0; i < count; ++i) { + zeus::CVector3f localPos = colliderList[it].x14_localPos; + zeus::CVector3f worldPos = predictedLookXf.rotate(localPos) + predictedLookXf.origin; + if ((colliderList[it].x2c_lastWorldPos - worldPos).magnitude() < 0.1f) { + localPos = colliderList[it].x8_lastLocalPos; + worldPos = colliderList[it].x2c_lastWorldPos; + } + zeus::CVector3f centerToCollider = worldPos - predictedLookXf.origin; + float mag = centerToCollider.magnitude(); + if (centerToCollider.canBeNormalized()) { + centerToCollider.normalize(); + TUniqueId intersectId = kInvalidUniqueId; + CRayCastResult result = mgr.RayWorldIntersection(intersectId, predictedLookXf.origin, centerToCollider, + mag + colliderList[it].x4_radius, BallCameraFilter, nearList); + if (result.IsValid()) { + zeus::CVector3f centerToPoint = centerToCollider * (result.GetT() - colliderList[it].x4_radius); + worldPos = centerToPoint + predictedLookXf.origin; + localPos = predictedLookXf.getRotation().inverse() * centerToPoint; } + } + colliderList[it].x2c_lastWorldPos = worldPos; + colliderList[it].x8_lastLocalPos = localPos; + zeus::CVector3f scaledWorldColliderPos = centerToCollider * mag * toleranceRecip; + scaledWorldColliderPos = scaledWorldColliderPos * x308_speedFactor + x31c_predictedLookPos; + colliderList[it].x20_scaledWorldPos = scaledWorldColliderPos; + if (mgr.RayCollideWorld(worldPos, scaledWorldColliderPos, nearList, BallCameraFilter, nullptr)) + colliderList[it].x4c_occlusionCount = 0; + else + colliderList[it].x4c_occlusionCount += 1; + it += 1; + if (it == colliderList.size()) + it = 0; } + } } zeus::CVector3f CBallCamera::AvoidGeometry(const zeus::CTransform& xf, - const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr) -{ - switch (x328_avoidGeomCycle) - { - case 0: - UpdateColliders(xf, x264_smallColliders, x2d0_smallColliderIt, 1, 4.f, nearList, dt, mgr); - break; - case 1: - UpdateColliders(xf, x274_mediumColliders, x2d4_mediumColliderIt, 3, 4.f, nearList, dt, mgr); - break; - case 2: - UpdateColliders(xf, x284_largeColliders, x2d8_largeColliderIt, 4, 4.f, nearList, dt, mgr); - break; - case 3: - UpdateColliders(xf, x284_largeColliders, x2d8_largeColliderIt, 4, 4.f, nearList, dt, mgr); - break; - default: - break; - } + const rstl::reserved_vector& nearList, float dt, + CStateManager& mgr) { + switch (x328_avoidGeomCycle) { + case 0: + UpdateColliders(xf, x264_smallColliders, x2d0_smallColliderIt, 1, 4.f, nearList, dt, mgr); + break; + case 1: + UpdateColliders(xf, x274_mediumColliders, x2d4_mediumColliderIt, 3, 4.f, nearList, dt, mgr); + break; + case 2: + UpdateColliders(xf, x284_largeColliders, x2d8_largeColliderIt, 4, 4.f, nearList, dt, mgr); + break; + case 3: + UpdateColliders(xf, x284_largeColliders, x2d8_largeColliderIt, 4, 4.f, nearList, dt, mgr); + break; + default: + break; + } - x328_avoidGeomCycle += 1; - if (x328_avoidGeomCycle >= 4) - x328_avoidGeomCycle = 0; + x328_avoidGeomCycle += 1; + if (x328_avoidGeomCycle >= 4) + x328_avoidGeomCycle = 0; - return ApplyColliders(); + return ApplyColliders(); } zeus::CVector3f CBallCamera::AvoidGeometryFull(const zeus::CTransform& xf, - const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr) -{ - UpdateColliders(xf, x264_smallColliders, x2d0_smallColliderIt, - x264_smallColliders.size(), 4.f, nearList, dt, mgr); - UpdateColliders(xf, x274_mediumColliders, x2d4_mediumColliderIt, - x274_mediumColliders.size(), 4.f, nearList, dt, mgr); - UpdateColliders(xf, x284_largeColliders, x2d8_largeColliderIt, - x284_largeColliders.size(), 4.f, nearList, dt, mgr); - return ApplyColliders(); + const rstl::reserved_vector& nearList, float dt, + CStateManager& mgr) { + UpdateColliders(xf, x264_smallColliders, x2d0_smallColliderIt, x264_smallColliders.size(), 4.f, nearList, dt, mgr); + UpdateColliders(xf, x274_mediumColliders, x2d4_mediumColliderIt, x274_mediumColliders.size(), 4.f, nearList, dt, mgr); + UpdateColliders(xf, x284_largeColliders, x2d8_largeColliderIt, x284_largeColliders.size(), 4.f, nearList, dt, mgr); + return ApplyColliders(); } zeus::CAABox CBallCamera::CalculateCollidersBoundingBox(const std::vector& colliderList, - CStateManager& mgr) const -{ - zeus::CAABox aabb; - for (const CCameraCollider& col : colliderList) - aabb.accumulateBounds(col.x2c_lastWorldPos); - aabb.accumulateBounds(mgr.GetPlayer().GetTranslation()); - return aabb; + CStateManager& mgr) const { + zeus::CAABox aabb; + for (const CCameraCollider& col : colliderList) + aabb.accumulateBounds(col.x2c_lastWorldPos); + aabb.accumulateBounds(mgr.GetPlayer().GetTranslation()); + return aabb; } -int CBallCamera::CountObscuredColliders(const std::vector& colliderList) const -{ - int ret = 0; - for (const CCameraCollider& c : colliderList) - if (c.x4c_occlusionCount >= 2) - ++ret; - return ret; +int CBallCamera::CountObscuredColliders(const std::vector& colliderList) const { + int ret = 0; + for (const CCameraCollider& c : colliderList) + if (c.x4c_occlusionCount >= 2) + ++ret; + return ret; } -void CBallCamera::UpdateCollidersDistances(std::vector& colliderList, - float xMag, float zMag, float angOffset) -{ - float theta = angOffset; - for (CCameraCollider& col : colliderList) - { - float z = std::cos(theta) * zMag; - if (theta > M_PIF / 2.f) - z *= 0.25f; - col.x14_localPos = {std::sin(theta) * xMag, 0.f, z}; - theta += 2.f * M_PIF / float(colliderList.size()); - } +void CBallCamera::UpdateCollidersDistances(std::vector& colliderList, float xMag, float zMag, + float angOffset) { + float theta = angOffset; + for (CCameraCollider& col : colliderList) { + float z = std::cos(theta) * zMag; + if (theta > M_PIF / 2.f) + z *= 0.25f; + col.x14_localPos = {std::sin(theta) * xMag, 0.f, z}; + theta += 2.f * M_PIF / float(colliderList.size()); + } } -void CBallCamera::UpdateUsingColliders(float dt, CStateManager& mgr) -{ - if (mgr.GetPlayer().GetBombJumpCount() == 1) - return; +void CBallCamera::UpdateUsingColliders(float dt, CStateManager& mgr) { + if (mgr.GetPlayer().GetBombJumpCount() == 1) + return; - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - if (mgr.GetPlayer().GetBombJumpCount() == 2) - { - zeus::CVector3f camToLookDir = x1d8_lookPos - GetTranslation(); - if (x18d_26_lookAtBall) - camToLookDir = ballPos - GetTranslation(); + if (mgr.GetPlayer().GetBombJumpCount() == 2) { + zeus::CVector3f camToLookDir = x1d8_lookPos - GetTranslation(); + if (x18d_26_lookAtBall) + camToLookDir = ballPos - GetTranslation(); - if (camToLookDir.canBeNormalized()) - { - camToLookDir.normalize(); - UpdateTransform(camToLookDir, GetTranslation(), dt, mgr); - } - } - else if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed || - x18d_25_avoidGeometryFull) - { - zeus::CTransform oldXf = x34_transform; - zeus::CVector3f oldPos = GetTranslation(); - x2c4_smallCollidersObsCount = CountObscuredColliders(x264_smallColliders); - x2c8_mediumCollidersObsCount = CountObscuredColliders(x274_mediumColliders); - x2cc_largeCollidersObsCount = CountObscuredColliders(x284_largeColliders); - zeus::CVector3f posAtBallLevel = {0.f, 0.f, GetTranslation().z() - ballPos.z()}; - zeus::CVector3f ballToCamFlat = GetTranslation() - ballPos; - ballToCamFlat.z() = 0.f; - float ballToCamFlatMag = 0.f; - if (ballToCamFlat.canBeNormalized()) - ballToCamFlatMag = ballToCamFlat.magnitude(); - else - ballToCamFlat = -mgr.GetPlayer().GetMoveDir(); - posAtBallLevel = GetTranslation() - posAtBallLevel; - zeus::CTransform ballToUnderCamLook; - if ((posAtBallLevel - ballPos).canBeNormalized()) - ballToUnderCamLook = zeus::lookAt(ballPos, posAtBallLevel); - float distance = x214_ballCameraSpring.ApplyDistanceSpring(x190_curMinDistance, ballToCamFlatMag, - (3.f + x308_speedFactor) * dt); - zeus::CVector3f camToBall = ballPos - GetTranslation(); - camToBall.z() = 0.f; - if (camToBall.canBeNormalized()) - { - camToBall.normalize(); - if (std::fabs(std::acos(zeus::clamp(-1.f, camToBall.dot(mgr.GetPlayer().GetMoveDir()), 1.f))) > - zeus::degToRad(150.f) && mgr.GetPlayer().GetVelocity().canBeNormalized()) - { - distance = x214_ballCameraSpring. - ApplyDistanceSpring(x308_speedFactor * (x19c_backwardsDistance -x190_curMinDistance) + - x190_curMinDistance, ballToCamFlatMag, 3.f * dt); - } - } - x334_collidersAABB = CalculateCollidersBoundingBox(x284_largeColliders, mgr); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, x334_collidersAABB, BallCameraFilter, - TCastToConstPtr(mgr.GetObjectById(x46c_collisionActorId)).GetPtr()); - if (!x18c_31_clearLOS && x368_obscuringObjectId == kInvalidUniqueId) - { - if (x34c_obscuredTime > 0.f || x350_obscuringMaterial.HasMaterial(EMaterialTypes::Floor) || - x350_obscuringMaterial.HasMaterial(EMaterialTypes::Wall)) - { - x32c_colliderMag += 2.f * dt; - if (x32c_colliderMag < 2.f) - x32c_colliderMag = 2.f; - if (x32c_colliderMag > 2.f) - x32c_colliderMag = 2.f; - UpdateCollidersDistances(x264_smallColliders, 2.31f * x32c_colliderMag, - 2.31f * x32c_colliderMag * 0.5f, -M_PIF / 2.f); - UpdateCollidersDistances(x274_mediumColliders, 4.62f * x32c_colliderMag, - 4.62f * x32c_colliderMag * 0.5f, -M_PIF / 2.f); - UpdateCollidersDistances(x284_largeColliders, 7.f * x32c_colliderMag, - 7.f * x32c_colliderMag * 0.5f, -M_PIF / 2.f); - } - } - else - { - float targetColliderMag = 1.f; - if (x18d_24_prevClearLOS && mgr.GetPlayer().GetMoveSpeed() < 1.f) - targetColliderMag = 0.25f; - x32c_colliderMag += (targetColliderMag - x32c_colliderMag) * dt * 2.f; - UpdateCollidersDistances(x264_smallColliders, x32c_colliderMag * 2.31f, - x32c_colliderMag * 2.31f, -M_PIF / 2.f); - UpdateCollidersDistances(x274_mediumColliders, x32c_colliderMag * 4.62f, - x32c_colliderMag * 4.62f, -M_PIF / 2.f); - UpdateCollidersDistances(x284_largeColliders, x32c_colliderMag * 7.f, - x32c_colliderMag * 7.f, -M_PIF / 2.f); - } - - float elevation = x1a0_elevation; - bool noDoor = !ConstrainElevationAndDistance(elevation, distance, dt, mgr); - zeus::CVector3f desiredBallToCam = ballToUnderCamLook.rotate({0.f, distance, elevation}); - - if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) - { - if (!door->x2a8_26_isOpen) - { - if (x400_state == EBallCameraState::Boost) - { - zeus::CVector3f ballToCam = GetTranslation() - ballPos; - if (ballToCam.canBeNormalized()) - ballToCam.normalize(); - else - ballToCam = GetTransform().basis[1]; - if (std::fabs(ballToCamFlatMag - x430_boostElevation) < 1.f) - { - ballToCam = ConstrainYawAngle(mgr.GetPlayer(), g_tweakBall->GetBallCameraBoostDistance(), - g_tweakBall->GetBallCameraBoostYawSpeed(), dt, mgr); - } - ballToCam.normalize(); - ballToCam.z() = 0.f; - ballToCam = ballToCam * distance; - ballToCam.z() = 1.f; - desiredBallToCam = ballToCam; - noDoor = false; - } - if (x18c_25_chaseAllowed && (x400_state == EBallCameraState::Chase || - x188_behaviour == EBallCameraBehaviour::FreezeLookPosition)) - { - zeus::CVector3f ballToCam = GetTranslation() - ballPos; - if (ballToCam.canBeNormalized()) - ballToCam.normalize(); - else - ballToCam = GetTransform().basis[1]; - if (std::fabs(ballToCamFlatMag - x404_chaseElevation) < 3.f) - { - ballToCam = ConstrainYawAngle(mgr.GetPlayer(), g_tweakBall->GetBallCameraChaseDistance(), - g_tweakBall->GetBallCameraChaseYawSpeed(), dt, mgr); - } - ballToCam.z() = 0.f; - ballToCam.normalize(); - ballToCam = ballToCam * distance; - ballToCam.z() = g_tweakBall->GetBallCameraElevation(); - desiredBallToCam = ballToCam; - noDoor = false; - } - } - } - - if (x188_behaviour == EBallCameraBehaviour::HintBallToCam) - { - desiredBallToCam = x45c_overrideBallToCam; - if (x18c_27_obscureAvoidance) - { - zeus::CVector3f ballToCamDir = x45c_overrideBallToCam; - if (ballToCamDir.canBeNormalized()) - ballToCamDir.normalize(); - else - ballToCamDir = -mgr.GetPlayer().GetMoveDir(); - TUniqueId intersectId = kInvalidUniqueId; - CRayCastResult result = - mgr.RayWorldIntersection(intersectId, ballPos, ballToCamDir, distance, BallCameraFilter, nearList); - if (result.IsValid()) - desiredBallToCam = ballToCamDir * result.GetT() * 0.9f; - } - noDoor = false; - } - - distance = desiredBallToCam.magnitude(); - zeus::CVector3f desiredCamPos = ballPos + desiredBallToCam; - float d = 0.f; - if (DetectCollision(ballPos, desiredCamPos, 0.3f, d, mgr)) - { - if (d >= 1.f) - { - desiredBallToCam = desiredBallToCam.normalized() * d; - desiredCamPos = ballPos + desiredBallToCam; - } - else - { - desiredBallToCam = ballPos + GetTranslation(); - desiredCamPos = GetTranslation(); - } - } - - zeus::CTransform lookXf = zeus::lookAt(desiredCamPos, x1d8_lookPos); - zeus::CTransform oldLookXf = zeus::lookAt(GetTranslation(), x1d8_lookPos); - x1e4_nextLookXf = lookXf; - lookXf = oldLookXf; - zeus::CVector3f colliderPointLocal; - if (x18d_25_avoidGeometryFull || !x18c_31_clearLOS) - colliderPointLocal = AvoidGeometryFull(lookXf, nearList, dt, mgr); - else - colliderPointLocal = AvoidGeometry(lookXf, nearList, dt, mgr); - - zeus::CVector3f ballToCam2 = GetTranslation() - ballPos; - ballToCam2.z() = 0.f; - if (ballToCam2.magnitude() < 2.f) - { - if (x18c_31_clearLOS && x478_shortMoveCount > 2) - colliderPointLocal = colliderPointLocal / float(x478_shortMoveCount); - if (d < 3.f) - { - colliderPointLocal = colliderPointLocal * 0.25f; - if (x18c_31_clearLOS && x478_shortMoveCount > 0) - colliderPointLocal = colliderPointLocal * x308_speedFactor; - } - if (d < 1.f) - colliderPointLocal = zeus::CVector3f::skZero; - } - - zeus::CVector3f camDelta = lookXf.rotate(colliderPointLocal) + desiredCamPos - ballPos; - if (camDelta.canBeNormalized()) - camDelta.normalize(); - zeus::CVector3f desiredPos = camDelta * distance + ballPos; - - if (x188_behaviour == EBallCameraBehaviour::PathCameraDesiredPos) - if (TCastToConstPtr cam = mgr.GetObjectById(mgr.GetCameraManager()->GetPathCameraId())) - desiredPos = cam->GetTranslation(); - - camDelta = x294_dampedPos - desiredPos; - float camDeltaMag = camDelta.magnitude(); - if (camDelta.canBeNormalized()) - camDelta.normalize(); - - x294_dampedPos = camDelta * x228_ballCameraCentroidSpring. - ApplyDistanceSpring(0.f, camDeltaMag, dt) + desiredPos; - zeus::CVector3f posDelta = oldPos - x294_dampedPos; - camDeltaMag = posDelta.magnitude(); - if (posDelta.canBeNormalized()) - posDelta.normalize(); - - float cDistSpringMag = x250_ballCameraCentroidDistanceSpring. - ApplyDistanceSpring(0.f, camDeltaMag, (x18d_28_obtuseDirection ? 3.f : 1.f) * dt); - if (x400_state == EBallCameraState::Boost) - cDistSpringMag = x448_ballCameraBoostSpring.ApplyDistanceSpring(0.f, camDeltaMag, dt); - else if (x18c_25_chaseAllowed && (x400_state == EBallCameraState::Chase || - x188_behaviour == EBallCameraBehaviour::FreezeLookPosition)) - cDistSpringMag = x41c_ballCameraChaseSpring.ApplyDistanceSpring(0.f, camDeltaMag, dt); - - zeus::CVector3f finalPos = posDelta * cDistSpringMag + x294_dampedPos; - if (mgr.GetPlayer().GetMorphBall()->GetSpiderBallState() != CMorphBall::ESpiderBallState::Active && - !x18e_24_noElevationVelClamp && mgr.GetPlayer().GetVelocity().z() > 8.f) - { - zeus::CVector3f delta = finalPos - oldPos; - delta.z() = zeus::clamp(-0.1f * dt, float(delta.z()), 0.1f * dt); - finalPos = oldPos + delta; - } - - if (noDoor && x400_state != EBallCameraState::ToBall) - finalPos = InterpolateCameraElevation(finalPos, dt); - - if (x18d_29_noElevationInterp) - finalPos.z() = elevation + ballPos.z(); - - if (ballToCam2.magnitude() < 2.f) - { - if (finalPos.z() < 2.f + ballPos.z()) - finalPos.z() = 2.f + ballPos.z(); - x214_ballCameraSpring.Reset(); - } - - finalPos = ClampElevationToWater(finalPos, mgr); - if (ballToCam2.magnitude() < 2.f && x3dc_tooCloseActorId != kInvalidUniqueId && x3e0_tooCloseActorDist < 5.f) - if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) - if (!door->x2a8_26_isOpen) - finalPos = GetTranslation(); - - float backupZ = finalPos.z(); - finalPos = MoveCollisionActor(finalPos, dt, mgr); - - if (x18c_31_clearLOS && x478_shortMoveCount > 0) - { - finalPos.z() = backupZ; - finalPos = MoveCollisionActor(finalPos, dt, mgr); - } - - zeus::CVector3f lookDir = x1d8_lookPos - finalPos; - if (x18d_26_lookAtBall) - lookDir = ballPos - finalPos; - if (lookDir.canBeNormalized()) - { - lookDir.normalize(); - UpdateTransform(lookDir, finalPos, dt, mgr); - } - - if (x470_clampVelTimer > 0.f) - x470_clampVelTimer -= dt; - } -} - -void CBallCamera::UpdateUsingSpindleCameras(float dt, CStateManager& mgr) -{ - if (TCastToPtr cam = mgr.ObjectById(mgr.GetCameraManager()->GetSpindleCameraId())) - { - TeleportCamera(cam->GetTransform(), mgr); - x18d_26_lookAtBall = true; - } -} - -zeus::CVector3f CBallCamera::ClampElevationToWater(zeus::CVector3f& pos, CStateManager& mgr) const -{ - zeus::CVector3f ret = pos; - if (TCastToConstPtr water = mgr.GetObjectById(mgr.GetPlayer().GetFluidId())) - { - float waterZ = water->GetTriggerBoundsWR().max.z(); - if (pos.z() >= waterZ && pos.z() - waterZ <= 0.25f) - ret.z() = 0.25f + waterZ; - else if (pos.z() < waterZ && pos.z() - waterZ >= -0.12f) - ret.z() = waterZ - 0.12f; - } - return ret; -} - -void CBallCamera::UpdateTransitionFromBallCamera(CStateManager& mgr) -{ - float morphFactor = mgr.GetPlayer().GetMorphFactor(); - zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); - zeus::CVector3f delta = mgr.GetPlayer().GetTranslation() - x47c_failsafeState->x84_playerPos; - x47c_failsafeState->x90_splinePoints[1] += delta; - x47c_failsafeState->x90_splinePoints[2] += delta; - x47c_failsafeState->x90_splinePoints[3] += delta; - zeus::CVector3f splinePoint = GetFailsafeSplinePoint(x47c_failsafeState->x90_splinePoints, morphFactor); - splinePoint.z() = (splinePoint.z() - eyePos.z()) * zeus::clamp(0.f, 1.f - 1.5f * morphFactor, 1.f) + eyePos.z(); - zeus::CVector3f deltaFlat = eyePos - splinePoint; - deltaFlat.z() = 0.f; - if (deltaFlat.magnitude() > 0.001f) - { - SetTransform(zeus::lookAt(splinePoint, zeus::CVector3f::lerp(x1d8_lookPos, eyePos, morphFactor))); + if (camToLookDir.canBeNormalized()) { + camToLookDir.normalize(); + UpdateTransform(camToLookDir, GetTranslation(), dt, mgr); } + } else if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed || + x18d_25_avoidGeometryFull) { + zeus::CTransform oldXf = x34_transform; + zeus::CVector3f oldPos = GetTranslation(); + x2c4_smallCollidersObsCount = CountObscuredColliders(x264_smallColliders); + x2c8_mediumCollidersObsCount = CountObscuredColliders(x274_mediumColliders); + x2cc_largeCollidersObsCount = CountObscuredColliders(x284_largeColliders); + zeus::CVector3f posAtBallLevel = {0.f, 0.f, GetTranslation().z() - ballPos.z()}; + zeus::CVector3f ballToCamFlat = GetTranslation() - ballPos; + ballToCamFlat.z() = 0.f; + float ballToCamFlatMag = 0.f; + if (ballToCamFlat.canBeNormalized()) + ballToCamFlatMag = ballToCamFlat.magnitude(); else - { - SetTransform(mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform()); - SetTranslation(splinePoint); + ballToCamFlat = -mgr.GetPlayer().GetMoveDir(); + posAtBallLevel = GetTranslation() - posAtBallLevel; + zeus::CTransform ballToUnderCamLook; + if ((posAtBallLevel - ballPos).canBeNormalized()) + ballToUnderCamLook = zeus::lookAt(ballPos, posAtBallLevel); + float distance = + x214_ballCameraSpring.ApplyDistanceSpring(x190_curMinDistance, ballToCamFlatMag, (3.f + x308_speedFactor) * dt); + zeus::CVector3f camToBall = ballPos - GetTranslation(); + camToBall.z() = 0.f; + if (camToBall.canBeNormalized()) { + camToBall.normalize(); + if (std::fabs(std::acos(zeus::clamp(-1.f, camToBall.dot(mgr.GetPlayer().GetMoveDir()), 1.f))) > + zeus::degToRad(150.f) && + mgr.GetPlayer().GetVelocity().canBeNormalized()) { + distance = x214_ballCameraSpring.ApplyDistanceSpring( + x308_speedFactor * (x19c_backwardsDistance - x190_curMinDistance) + x190_curMinDistance, ballToCamFlatMag, + 3.f * dt); + } } - mgr.GetCameraManager()->GetFirstPersonCamera()->Reset(x34_transform, mgr); - x47c_failsafeState->x84_playerPos = mgr.GetPlayer().GetTranslation(); -} - -void CBallCamera::UpdateUsingTransitions(float dt, CStateManager& mgr) -{ - if (x400_state == EBallCameraState::FromBall) - { - UpdateTransitionFromBallCamera(mgr); - return; - } - - x18d_26_lookAtBall = false; - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); - ballPos.z() += x1b4_lookAtOffset.z(); - - zeus::CVector3f lookDir = x34_transform.basis[1]; - zeus::CTransform xe8 = x34_transform; - - switch (x400_state) - { - case EBallCameraState::ToBall: - { - float elevation = x1a0_elevation; - float distance = x194_targetMinDistance; - ConstrainElevationAndDistance(elevation, distance, dt, mgr); - distance = x194_targetMinDistance; - bool r28 = IsBallNearDoor(GetTranslation(), mgr) || x478_shortMoveCount > 2; - zeus::CVector3f toDesired = - FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, r28) - eyePos; - zeus::CVector3f finalPos = toDesired * mgr.GetPlayer().GetMorphFactor() + eyePos; - if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) - { - act->SetTranslation(GetTranslation()); - finalPos = ClampElevationToWater(finalPos, mgr); - finalPos = MoveCollisionActor(finalPos, dt, mgr); - zeus::CVector3f camToLookDir = x1d8_lookPos - finalPos; - if (camToLookDir.canBeNormalized()) - { - camToLookDir.normalize(); - float devDot = std::fabs(zeus::clamp(-1.f, lookDir.dot(camToLookDir), 1.f)); - float devAngle = zeus::clamp(-1.f, mgr.GetPlayer().GetMorphFactor() * 0.5f, 1.f) * std::acos(devDot); - if (devDot < 1.f) - SetTransform(zeus::CQuaternion::lookAt(xe8.basis[1], camToLookDir, devAngle). - toTransform() * xe8.getRotation()); - else - SetTransform(zeus::lookAt(zeus::CVector3f::skZero, camToLookDir)); - } - } - SetTransform(ValidateCameraTransform(x34_transform, xe8)); - SetTranslation(finalPos); - TeleportCamera(finalPos, mgr); - break; - } - case EBallCameraState::FromBall: - { - if (std::fabs(mgr.GetPlayer().GetMorphFactor() - 1.f) < 0.00001f) - { - SetTransform(mgr.GetPlayer().GetTransform()); - SetTranslation(mgr.GetPlayer().GetEyePosition()); - } - else - { - float morphT = zeus::clamp(-1.f, mgr.GetPlayer().GetMorphFactor() / 0.9f, 1.f); - zeus::CVector3f finalPos = GetTranslation(); - zeus::CVector3f eyeToCam = GetTranslation() - eyePos; - if (eyeToCam.canBeNormalized()) - { - float distance = eyeToCam.magnitude(); - distance = std::min(distance, (1.f - mgr.GetPlayer().GetMorphFactor()) * x190_curMinDistance); - float yawSpeed = M_PIF; - zeus::CVector3f playerToCamDir = GetTranslation() - mgr.GetPlayer().GetTranslation(); - zeus::CVector3f moveDir = mgr.GetPlayer().GetMoveDir(); - if (playerToCamDir.canBeNormalized()) - playerToCamDir.normalize(); - else - playerToCamDir = -moveDir; - if (moveDir.canBeNormalized()) - { - moveDir.normalize(); - yawSpeed = std::fabs(std::acos(zeus::clamp(-1.f, playerToCamDir.dot(-moveDir), 1.f))) * morphT / dt; - } - zeus::CVector3f useLookDir = ConstrainYawAngle(mgr.GetPlayer(), yawSpeed, zeus::degToRad(10.f), dt, mgr); - useLookDir.z() = 0.f; - useLookDir.normalize(); - zeus::CVector3f camPos = useLookDir * distance + eyePos; - camPos.z() = (GetTranslation().z() - eyePos.z()) * morphT + eyePos.z(); - finalPos = ClampElevationToWater(camPos, mgr); - finalPos = MoveCollisionActor(finalPos, dt, mgr); - zeus::CVector3f finalToBall = ballPos - finalPos; - finalToBall.z() = 0.f; - zeus::CVector3f lookPos = ballPos; - lookPos.z() = morphT * (eyePos.z() - ballPos.z()) + ballPos.z(); - if (finalToBall.canBeNormalized()) - SetTransform(zeus::lookAt(finalPos, lookPos)); - else - SetTransform(mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform()); - } - else - { - SetTransform(mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform()); - } - SetTranslation(finalPos); - } - break; - } - default: - break; - } - - mgr.GetCameraManager()->GetFirstPersonCamera()->Reset(x34_transform, mgr); -} - -zeus::CTransform CBallCamera::UpdateCameraPositions(float dt, const zeus::CTransform& oldXf, - const zeus::CTransform& newXf) -{ - zeus::CTransform useXf = newXf; - if (std::fabs(oldXf.basis[1].z()) > 0.9f && std::fabs(newXf.basis[1].z()) > 0.9f && - oldXf.basis[0].dot(newXf.basis[0]) <= 0.999f) - { - zeus::CVector3f newRight = zeus::CQuaternion::clampedRotateTo(oldXf.basis[0], newXf.basis[0], - zeus::degToRad(2.f * dt)).toTransform() * oldXf.basis[0]; - if (newRight.dot(newXf.basis[1]) <= 0.999f) - { - zeus::CVector3f newUp = newXf.basis[1].cross(newRight).normalized(); - zeus::CVector3f newForward = newXf.basis[1].normalized(); - useXf = {newUp.cross(newForward), newXf.basis[1], newUp, newXf.origin}; - } - } - return useXf; -} - -zeus::CVector3f CBallCamera::GetFailsafeSplinePoint(const std::vector& points, float t) -{ - t *= (points.size() - 3); - int baseIdx = 0; - while (t > 1.f) - { - t -= 1.f; - baseIdx += 1; - } - return zeus::getBezierPoint(points[baseIdx], points[baseIdx+1], points[baseIdx+2], points[baseIdx+3], t); -} - -bool CBallCamera::CheckFailsafeFromMorphBallState(CStateManager& mgr) const -{ - TUniqueId xbb8 = kInvalidUniqueId; - float curT = 0.f; + x334_collidersAABB = CalculateCollidersBoundingBox(x284_largeColliders, mgr); rstl::reserved_vector nearList; - rstl::reserved_vector resultsA; - rstl::reserved_vector resultsB; - while (curT < 6.f) - { - zeus::CVector3f pointA = GetFailsafeSplinePoint(x47c_failsafeState->x90_splinePoints, curT / 6.f); - zeus::CVector3f pointB = GetFailsafeSplinePoint(x47c_failsafeState->x90_splinePoints, (1.f + curT) / 6.f); - zeus::CVector3f pointDelta = pointB - pointA; - if (pointDelta.magnitude() > 0.1f) - { - resultsA.push_back( - mgr.RayWorldIntersection(xbb8, pointA, pointDelta.normalized(), pointDelta.magnitude(), - BallCameraFilter, nearList)); - resultsB.push_back( - mgr.RayWorldIntersection(xbb8, pointB, -pointDelta.normalized(), pointDelta.magnitude(), - BallCameraFilter, nearList)); + mgr.BuildNearList(nearList, x334_collidersAABB, BallCameraFilter, + TCastToConstPtr(mgr.GetObjectById(x46c_collisionActorId)).GetPtr()); + if (!x18c_31_clearLOS && x368_obscuringObjectId == kInvalidUniqueId) { + if (x34c_obscuredTime > 0.f || x350_obscuringMaterial.HasMaterial(EMaterialTypes::Floor) || + x350_obscuringMaterial.HasMaterial(EMaterialTypes::Wall)) { + x32c_colliderMag += 2.f * dt; + if (x32c_colliderMag < 2.f) + x32c_colliderMag = 2.f; + if (x32c_colliderMag > 2.f) + x32c_colliderMag = 2.f; + UpdateCollidersDistances(x264_smallColliders, 2.31f * x32c_colliderMag, 2.31f * x32c_colliderMag * 0.5f, + -M_PIF / 2.f); + UpdateCollidersDistances(x274_mediumColliders, 4.62f * x32c_colliderMag, 4.62f * x32c_colliderMag * 0.5f, + -M_PIF / 2.f); + UpdateCollidersDistances(x284_largeColliders, 7.f * x32c_colliderMag, 7.f * x32c_colliderMag * 0.5f, + -M_PIF / 2.f); + } + } else { + float targetColliderMag = 1.f; + if (x18d_24_prevClearLOS && mgr.GetPlayer().GetMoveSpeed() < 1.f) + targetColliderMag = 0.25f; + x32c_colliderMag += (targetColliderMag - x32c_colliderMag) * dt * 2.f; + UpdateCollidersDistances(x264_smallColliders, x32c_colliderMag * 2.31f, x32c_colliderMag * 2.31f, -M_PIF / 2.f); + UpdateCollidersDistances(x274_mediumColliders, x32c_colliderMag * 4.62f, x32c_colliderMag * 4.62f, -M_PIF / 2.f); + UpdateCollidersDistances(x284_largeColliders, x32c_colliderMag * 7.f, x32c_colliderMag * 7.f, -M_PIF / 2.f); + } + + float elevation = x1a0_elevation; + bool noDoor = !ConstrainElevationAndDistance(elevation, distance, dt, mgr); + zeus::CVector3f desiredBallToCam = ballToUnderCamLook.rotate({0.f, distance, elevation}); + + if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) { + if (!door->x2a8_26_isOpen) { + if (x400_state == EBallCameraState::Boost) { + zeus::CVector3f ballToCam = GetTranslation() - ballPos; + if (ballToCam.canBeNormalized()) + ballToCam.normalize(); + else + ballToCam = GetTransform().basis[1]; + if (std::fabs(ballToCamFlatMag - x430_boostElevation) < 1.f) { + ballToCam = ConstrainYawAngle(mgr.GetPlayer(), g_tweakBall->GetBallCameraBoostDistance(), + g_tweakBall->GetBallCameraBoostYawSpeed(), dt, mgr); + } + ballToCam.normalize(); + ballToCam.z() = 0.f; + ballToCam = ballToCam * distance; + ballToCam.z() = 1.f; + desiredBallToCam = ballToCam; + noDoor = false; } + if (x18c_25_chaseAllowed && + (x400_state == EBallCameraState::Chase || x188_behaviour == EBallCameraBehaviour::FreezeLookPosition)) { + zeus::CVector3f ballToCam = GetTranslation() - ballPos; + if (ballToCam.canBeNormalized()) + ballToCam.normalize(); + else + ballToCam = GetTransform().basis[1]; + if (std::fabs(ballToCamFlatMag - x404_chaseElevation) < 3.f) { + ballToCam = ConstrainYawAngle(mgr.GetPlayer(), g_tweakBall->GetBallCameraChaseDistance(), + g_tweakBall->GetBallCameraChaseYawSpeed(), dt, mgr); + } + ballToCam.z() = 0.f; + ballToCam.normalize(); + ballToCam = ballToCam * distance; + ballToCam.z() = g_tweakBall->GetBallCameraElevation(); + desiredBallToCam = ballToCam; + noDoor = false; + } + } + } + + if (x188_behaviour == EBallCameraBehaviour::HintBallToCam) { + desiredBallToCam = x45c_overrideBallToCam; + if (x18c_27_obscureAvoidance) { + zeus::CVector3f ballToCamDir = x45c_overrideBallToCam; + if (ballToCamDir.canBeNormalized()) + ballToCamDir.normalize(); else - { - resultsA.push_back({}); - resultsB.push_back({}); - } - curT += 1.f; + ballToCamDir = -mgr.GetPlayer().GetMoveDir(); + TUniqueId intersectId = kInvalidUniqueId; + CRayCastResult result = + mgr.RayWorldIntersection(intersectId, ballPos, ballToCamDir, distance, BallCameraFilter, nearList); + if (result.IsValid()) + desiredBallToCam = ballToCamDir * result.GetT() * 0.9f; + } + noDoor = false; } - for (int i=0 ; ix90_splinePoints, - (1.f + i) / 6.f) - resA.GetPoint(); - if (separation.magnitude() > 0.3f) - return false; - } + + distance = desiredBallToCam.magnitude(); + zeus::CVector3f desiredCamPos = ballPos + desiredBallToCam; + float d = 0.f; + if (DetectCollision(ballPos, desiredCamPos, 0.3f, d, mgr)) { + if (d >= 1.f) { + desiredBallToCam = desiredBallToCam.normalized() * d; + desiredCamPos = ballPos + desiredBallToCam; + } else { + desiredBallToCam = ballPos + GetTranslation(); + desiredCamPos = GetTranslation(); + } } - return true; + + zeus::CTransform lookXf = zeus::lookAt(desiredCamPos, x1d8_lookPos); + zeus::CTransform oldLookXf = zeus::lookAt(GetTranslation(), x1d8_lookPos); + x1e4_nextLookXf = lookXf; + lookXf = oldLookXf; + zeus::CVector3f colliderPointLocal; + if (x18d_25_avoidGeometryFull || !x18c_31_clearLOS) + colliderPointLocal = AvoidGeometryFull(lookXf, nearList, dt, mgr); + else + colliderPointLocal = AvoidGeometry(lookXf, nearList, dt, mgr); + + zeus::CVector3f ballToCam2 = GetTranslation() - ballPos; + ballToCam2.z() = 0.f; + if (ballToCam2.magnitude() < 2.f) { + if (x18c_31_clearLOS && x478_shortMoveCount > 2) + colliderPointLocal = colliderPointLocal / float(x478_shortMoveCount); + if (d < 3.f) { + colliderPointLocal = colliderPointLocal * 0.25f; + if (x18c_31_clearLOS && x478_shortMoveCount > 0) + colliderPointLocal = colliderPointLocal * x308_speedFactor; + } + if (d < 1.f) + colliderPointLocal = zeus::CVector3f::skZero; + } + + zeus::CVector3f camDelta = lookXf.rotate(colliderPointLocal) + desiredCamPos - ballPos; + if (camDelta.canBeNormalized()) + camDelta.normalize(); + zeus::CVector3f desiredPos = camDelta * distance + ballPos; + + if (x188_behaviour == EBallCameraBehaviour::PathCameraDesiredPos) + if (TCastToConstPtr cam = mgr.GetObjectById(mgr.GetCameraManager()->GetPathCameraId())) + desiredPos = cam->GetTranslation(); + + camDelta = x294_dampedPos - desiredPos; + float camDeltaMag = camDelta.magnitude(); + if (camDelta.canBeNormalized()) + camDelta.normalize(); + + x294_dampedPos = camDelta * x228_ballCameraCentroidSpring.ApplyDistanceSpring(0.f, camDeltaMag, dt) + desiredPos; + zeus::CVector3f posDelta = oldPos - x294_dampedPos; + camDeltaMag = posDelta.magnitude(); + if (posDelta.canBeNormalized()) + posDelta.normalize(); + + float cDistSpringMag = x250_ballCameraCentroidDistanceSpring.ApplyDistanceSpring( + 0.f, camDeltaMag, (x18d_28_obtuseDirection ? 3.f : 1.f) * dt); + if (x400_state == EBallCameraState::Boost) + cDistSpringMag = x448_ballCameraBoostSpring.ApplyDistanceSpring(0.f, camDeltaMag, dt); + else if (x18c_25_chaseAllowed && + (x400_state == EBallCameraState::Chase || x188_behaviour == EBallCameraBehaviour::FreezeLookPosition)) + cDistSpringMag = x41c_ballCameraChaseSpring.ApplyDistanceSpring(0.f, camDeltaMag, dt); + + zeus::CVector3f finalPos = posDelta * cDistSpringMag + x294_dampedPos; + if (mgr.GetPlayer().GetMorphBall()->GetSpiderBallState() != CMorphBall::ESpiderBallState::Active && + !x18e_24_noElevationVelClamp && mgr.GetPlayer().GetVelocity().z() > 8.f) { + zeus::CVector3f delta = finalPos - oldPos; + delta.z() = zeus::clamp(-0.1f * dt, float(delta.z()), 0.1f * dt); + finalPos = oldPos + delta; + } + + if (noDoor && x400_state != EBallCameraState::ToBall) + finalPos = InterpolateCameraElevation(finalPos, dt); + + if (x18d_29_noElevationInterp) + finalPos.z() = elevation + ballPos.z(); + + if (ballToCam2.magnitude() < 2.f) { + if (finalPos.z() < 2.f + ballPos.z()) + finalPos.z() = 2.f + ballPos.z(); + x214_ballCameraSpring.Reset(); + } + + finalPos = ClampElevationToWater(finalPos, mgr); + if (ballToCam2.magnitude() < 2.f && x3dc_tooCloseActorId != kInvalidUniqueId && x3e0_tooCloseActorDist < 5.f) + if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) + if (!door->x2a8_26_isOpen) + finalPos = GetTranslation(); + + float backupZ = finalPos.z(); + finalPos = MoveCollisionActor(finalPos, dt, mgr); + + if (x18c_31_clearLOS && x478_shortMoveCount > 0) { + finalPos.z() = backupZ; + finalPos = MoveCollisionActor(finalPos, dt, mgr); + } + + zeus::CVector3f lookDir = x1d8_lookPos - finalPos; + if (x18d_26_lookAtBall) + lookDir = ballPos - finalPos; + if (lookDir.canBeNormalized()) { + lookDir.normalize(); + UpdateTransform(lookDir, finalPos, dt, mgr); + } + + if (x470_clampVelTimer > 0.f) + x470_clampVelTimer -= dt; + } } -bool CBallCamera::SplineIntersectTest(CMaterialList& intersectMat, CStateManager& mgr) const -{ - rstl::reserved_vector nearList; - TUniqueId xe38 = kInvalidUniqueId; - rstl::reserved_vector xacc; - rstl::reserved_vector xd10; - CMaterialFilter filter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, - EMaterialTypes::Floor, - EMaterialTypes::Wall}, - {EMaterialTypes::ProjectilePassthrough, - EMaterialTypes::Player, - EMaterialTypes::Character, - EMaterialTypes::CameraPassthrough}); - float curT = 0.f; - while (curT < 12.f) - { - zeus::CVector3f xdb0 = x37c_camSpline.GetInterpolatedSplinePointByTime(curT, 12.f); - zeus::CVector3f xdbc = x37c_camSpline.GetInterpolatedSplinePointByTime(curT, 12.f); - zeus::CVector3f xdc8 = xdbc - xdb0; - if (xdc8.magnitude() > 0.1f) - { - xacc.push_back( - mgr.RayWorldIntersection(xe38, xdb0, xdc8.normalized(), xdc8.magnitude(), filter, nearList)); - xd10.push_back( - mgr.RayWorldIntersection(xe38, xdbc, -xdc8.normalized(), xdc8.magnitude(), filter, nearList)); - } - else - { - xacc.push_back({}); - xd10.push_back({}); - } - curT += 1.f; - } - for (int i=0 ; i 0.3f) - { - intersectMat = resA.GetMaterial(); - return false; - } - } - } - return true; +void CBallCamera::UpdateUsingSpindleCameras(float dt, CStateManager& mgr) { + if (TCastToPtr cam = mgr.ObjectById(mgr.GetCameraManager()->GetSpindleCameraId())) { + TeleportCamera(cam->GetTransform(), mgr); + x18d_26_lookAtBall = true; + } } -bool CBallCamera::IsBallNearDoor(const zeus::CVector3f& pos, CStateManager& mgr) -{ - TCastToConstPtr door = - mgr.GetObjectById(mgr.GetCameraManager()->GetBallCamera()->x3dc_tooCloseActorId); - if (!door || door->x2a8_26_isOpen) - return false; - - auto tb = door->GetTouchBounds(); - zeus::CAABox testAABB(pos - 0.3f, pos + 0.3f); - if (!tb || !tb->intersects(testAABB)) - return false; - - if (TCastToConstPtr dock = mgr.GetObjectById(door->x282_dockId)) - if (std::fabs(dock->GetPlane(mgr).pointToPlaneDist(pos)) < 1.15f) - return true; - - return false; +zeus::CVector3f CBallCamera::ClampElevationToWater(zeus::CVector3f& pos, CStateManager& mgr) const { + zeus::CVector3f ret = pos; + if (TCastToConstPtr water = mgr.GetObjectById(mgr.GetPlayer().GetFluidId())) { + float waterZ = water->GetTriggerBoundsWR().max.z(); + if (pos.z() >= waterZ && pos.z() - waterZ <= 0.25f) + ret.z() = 0.25f + waterZ; + else if (pos.z() < waterZ && pos.z() - waterZ >= -0.12f) + ret.z() = waterZ - 0.12f; + } + return ret; } -void CBallCamera::ActivateFailsafe(float dt, CStateManager& mgr) -{ +void CBallCamera::UpdateTransitionFromBallCamera(CStateManager& mgr) { + float morphFactor = mgr.GetPlayer().GetMorphFactor(); + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + zeus::CVector3f delta = mgr.GetPlayer().GetTranslation() - x47c_failsafeState->x84_playerPos; + x47c_failsafeState->x90_splinePoints[1] += delta; + x47c_failsafeState->x90_splinePoints[2] += delta; + x47c_failsafeState->x90_splinePoints[3] += delta; + zeus::CVector3f splinePoint = GetFailsafeSplinePoint(x47c_failsafeState->x90_splinePoints, morphFactor); + splinePoint.z() = (splinePoint.z() - eyePos.z()) * zeus::clamp(0.f, 1.f - 1.5f * morphFactor, 1.f) + eyePos.z(); + zeus::CVector3f deltaFlat = eyePos - splinePoint; + deltaFlat.z() = 0.f; + if (deltaFlat.magnitude() > 0.001f) { + SetTransform(zeus::lookAt(splinePoint, zeus::CVector3f::lerp(x1d8_lookPos, eyePos, morphFactor))); + } else { + SetTransform(mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform()); + SetTranslation(splinePoint); + } + mgr.GetCameraManager()->GetFirstPersonCamera()->Reset(x34_transform, mgr); + x47c_failsafeState->x84_playerPos = mgr.GetPlayer().GetTranslation(); +} + +void CBallCamera::UpdateUsingTransitions(float dt, CStateManager& mgr) { + if (x400_state == EBallCameraState::FromBall) { + UpdateTransitionFromBallCamera(mgr); + return; + } + + x18d_26_lookAtBall = false; + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + ballPos.z() += x1b4_lookAtOffset.z(); + + zeus::CVector3f lookDir = x34_transform.basis[1]; + zeus::CTransform xe8 = x34_transform; + + switch (x400_state) { + case EBallCameraState::ToBall: { float elevation = x1a0_elevation; float distance = x194_targetMinDistance; ConstrainElevationAndDistance(elevation, distance, dt, mgr); - zeus::CVector3f desiredPos = FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, true); - SetTranslation(desiredPos); - ResetPosition(mgr); - TeleportCamera(zeus::lookAt(desiredPos, x1d8_lookPos), mgr); - mgr.GetCameraManager()->SetPlayerCamera(mgr, GetUniqueId()); - x3e4_pendingFailsafe = false; - x34c_obscuredTime = 0.f; -} - -bool CBallCamera::ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr) -{ - zeus::CVector3f ballToCam = GetTranslation() - mgr.GetPlayer().GetBallPosition(); - float ballToCamMag = 0.f; - if (ballToCam.canBeNormalized()) - ballToCamMag = ballToCam.toVec2f().magnitude(); - else - ballToCam = -mgr.GetPlayer().GetMoveDir(); - - bool doorClose = false; - float stretchFac = 1.f; - float newDistance = distance; - float baseElevation = elevation; - float springSpeed = 1.f; - if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) - { - if (!door->x2a8_29_ballDoor) - { - stretchFac = zeus::clamp(-1.f, std::fabs(x3e0_tooCloseActorDist / (3.f * distance)), 1.f); - if (x3e0_tooCloseActorDist < 3.f * distance) - doorClose = true; - if (door->x2a8_26_isOpen) - newDistance = stretchFac * (distance - x468_conservativeDoorCamDistance) + - x468_conservativeDoorCamDistance; - else - newDistance = stretchFac * (distance - 5.f) + 5.f; - if (x18d_28_obtuseDirection) - newDistance *= 1.f + x308_speedFactor; - baseElevation = door->x2a8_26_isOpen ? 0.75f : 1.5f; - springSpeed = 4.f; - } - } - - x214_ballCameraSpring.ApplyDistanceSpring(newDistance, ballToCamMag, dt * springSpeed); - distance = newDistance; - elevation = (elevation - baseElevation) * stretchFac + baseElevation; - - return doorClose; -} - -zeus::CVector3f CBallCamera::FindDesiredPosition(float distance, float elevation, - const zeus::CVector3f& dir, CStateManager& mgr, bool fullTest) -{ - TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject); - if (!player) - return {}; - - zeus::CVector3f useDir = dir; - if (!dir.canBeNormalized()) - useDir = zeus::CVector3f::skForward; - - zeus::CTransform lookDirXf = zeus::lookAt(zeus::CVector3f::skZero, useDir); - zeus::CVector3f ballPos = player->GetBallPosition(); - float elev = elevation; - float dist = distance; - ConstrainElevationAndDistance(elev, dist, 0.f, mgr); - zeus::CVector3f eyePos = player->GetEyePosition(); - if (!mgr.RayCollideWorld(ballPos, eyePos, BallCameraFilter, nullptr)) - eyePos = ballPos; - - zeus::CVector3f idealLookVec(0.f, -dist, elev - (eyePos.z() - ballPos.z())); - idealLookVec = lookDirXf.getRotation() * idealLookVec; - zeus::CVector3f lookVec(0.f, distance, elev - (eyePos.z() - ballPos.z())); - float idealLookDist = idealLookVec.magnitude(); - float resolveLOSIntervalAng = zeus::degToRad(30.f); - bool foundClear = false; - bool clear = !DetectCollision(eyePos, eyePos + idealLookVec, 0.3f, idealLookDist, mgr); - if (!clear && idealLookDist <= 0.f) - { - zeus::CAABox x13ac(ballPos - distance, ballPos + distance); - x13ac.min.z() = float(ballPos.z()); - x13ac.max.z() = elev + ballPos.z(); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, x13ac, BallCameraFilter, - TCastToConstPtr(mgr.GetObjectById(x46c_collisionActorId)).GetPtr()); - zeus::CQuaternion rotNeg; - rotNeg.rotateZ(-resolveLOSIntervalAng); - zeus::CTransform xfNeg = rotNeg.toTransform(); - zeus::CQuaternion rotPos; - rotPos.rotateZ(resolveLOSIntervalAng); - zeus::CTransform xfPos = rotPos.toTransform(); - while (!foundClear && idealLookDist > dist) - { - idealLookVec.normalize(); - idealLookVec = idealLookVec * idealLookDist; - zeus::CVector3f lookVecNeg = xfNeg.rotate(idealLookVec); - zeus::CVector3f lookVecPos = xfPos.rotate(idealLookVec); - for (int i=0 ; float(i) < 180.f / zeus::radToDeg(resolveLOSIntervalAng) ; ++i) - { - if (mgr.RayCollideWorld(eyePos, eyePos + lookVecNeg, nearList, BallCameraFilter, nullptr)) - { - foundClear = true; - lookVec = lookVecNeg; - break; - } - else if (mgr.RayCollideWorld(eyePos, eyePos + lookVecPos, nearList, BallCameraFilter, nullptr)) - { - foundClear = true; - lookVec = lookVecPos; - break; - } - else - { - lookVecNeg = xfNeg * lookVecNeg; - lookVecPos = xfPos * lookVecPos; - } - } - idealLookDist -= 0.3f; - } - } - else - { - if (idealLookDist < 2.f) - { - idealLookVec.normalize(); - idealLookVec = idealLookVec * 2.f; - } - zeus::CQuaternion rotNeg; - rotNeg.rotateZ(-resolveLOSIntervalAng); - zeus::CTransform xfNeg = rotNeg.toTransform(); - zeus::CVector3f lookVecNeg = xfNeg * idealLookVec; - zeus::CQuaternion rotPos; - rotPos.rotateZ(resolveLOSIntervalAng); - zeus::CTransform xfPos = rotPos.toTransform(); - zeus::CVector3f lookVecPos = xfPos * idealLookVec; - if (clear || (!fullTest && (idealLookDist > 2.f || x2e8_ballVelFlat > 1.25f))) - { - idealLookVec.normalize(); - lookVec = idealLookVec * idealLookDist; - foundClear = true; - } + distance = x194_targetMinDistance; + bool r28 = IsBallNearDoor(GetTranslation(), mgr) || x478_shortMoveCount > 2; + zeus::CVector3f toDesired = + FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, r28) - eyePos; + zeus::CVector3f finalPos = toDesired * mgr.GetPlayer().GetMorphFactor() + eyePos; + if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) { + act->SetTranslation(GetTranslation()); + finalPos = ClampElevationToWater(finalPos, mgr); + finalPos = MoveCollisionActor(finalPos, dt, mgr); + zeus::CVector3f camToLookDir = x1d8_lookPos - finalPos; + if (camToLookDir.canBeNormalized()) { + camToLookDir.normalize(); + float devDot = std::fabs(zeus::clamp(-1.f, lookDir.dot(camToLookDir), 1.f)); + float devAngle = zeus::clamp(-1.f, mgr.GetPlayer().GetMorphFactor() * 0.5f, 1.f) * std::acos(devDot); + if (devDot < 1.f) + SetTransform(zeus::CQuaternion::lookAt(xe8.basis[1], camToLookDir, devAngle).toTransform() * + xe8.getRotation()); else - { - for (int i=0 ; float(i) < 180.f / zeus::radToDeg(resolveLOSIntervalAng) ; ++i) - { - idealLookDist = lookVecNeg.magnitude(); - if (!DetectCollision(eyePos, eyePos + lookVecNeg, 0.3f, idealLookDist, mgr) || idealLookDist > 2.f) - { - lookVecNeg.normalize(); - lookVec = lookVecNeg * idealLookDist; - foundClear = true; - break; - } - idealLookDist = lookVecPos.magnitude(); - if (!DetectCollision(eyePos, eyePos + lookVecPos, 0.3f, idealLookDist, mgr) || idealLookDist > 2.f) - { - lookVecPos.normalize(); - lookVec = lookVecPos * idealLookDist; - foundClear = true; - break; - } - lookVecNeg = xfNeg * lookVecNeg; - lookVecPos = xfPos * lookVecPos; - } - if (!foundClear) - { - zeus::CAABox findBounds(ballPos - distance, ballPos + distance); - findBounds.min.z() = float(ballPos.z()); - findBounds.max.z() = elev + ballPos.z(); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, findBounds, BallCameraFilter, - TCastToConstPtr(mgr.GetObjectById(x46c_collisionActorId)).GetPtr()); - zeus::CQuaternion rotNeg2; - rotNeg2.rotateZ(-resolveLOSIntervalAng); - zeus::CTransform xfNeg2 = rotNeg2.toTransform(); - zeus::CQuaternion rotPos2; - rotPos2.rotateZ(resolveLOSIntervalAng); - zeus::CTransform xfPos2 = rotPos2.toTransform(); - while (!foundClear && idealLookDist > dist) - { - idealLookVec.normalize(); - idealLookVec = idealLookVec * idealLookDist; - zeus::CVector3f lookVecNeg2 = xfNeg2.rotate(idealLookVec); - zeus::CVector3f lookVecPos2 = xfPos2.rotate(idealLookVec); - for (int i=0 ; float(i) < 180.f / zeus::radToDeg(resolveLOSIntervalAng) ; ++i) - { - if (mgr.RayCollideWorld(eyePos, eyePos + lookVecNeg2, nearList, BallCameraFilter, nullptr)) - { - foundClear = true; - lookVec = lookVecNeg2; - break; - } - else if (mgr.RayCollideWorld(eyePos, eyePos + lookVecPos2, nearList, BallCameraFilter, nullptr)) - { - foundClear = true; - lookVec = lookVecPos2; - break; - } - else - { - lookVecNeg2 = xfNeg2 * lookVecNeg2; - lookVecPos2 = xfPos2 * lookVecPos2; - } - } - idealLookDist -= 0.3f; - } - } - } + SetTransform(zeus::lookAt(zeus::CVector3f::skZero, camToLookDir)); + } } + SetTransform(ValidateCameraTransform(x34_transform, xe8)); + SetTranslation(finalPos); + TeleportCamera(finalPos, mgr); + break; + } + case EBallCameraState::FromBall: { + if (std::fabs(mgr.GetPlayer().GetMorphFactor() - 1.f) < 0.00001f) { + SetTransform(mgr.GetPlayer().GetTransform()); + SetTranslation(mgr.GetPlayer().GetEyePosition()); + } else { + float morphT = zeus::clamp(-1.f, mgr.GetPlayer().GetMorphFactor() / 0.9f, 1.f); + zeus::CVector3f finalPos = GetTranslation(); + zeus::CVector3f eyeToCam = GetTranslation() - eyePos; + if (eyeToCam.canBeNormalized()) { + float distance = eyeToCam.magnitude(); + distance = std::min(distance, (1.f - mgr.GetPlayer().GetMorphFactor()) * x190_curMinDistance); + float yawSpeed = M_PIF; + zeus::CVector3f playerToCamDir = GetTranslation() - mgr.GetPlayer().GetTranslation(); + zeus::CVector3f moveDir = mgr.GetPlayer().GetMoveDir(); + if (playerToCamDir.canBeNormalized()) + playerToCamDir.normalize(); + else + playerToCamDir = -moveDir; + if (moveDir.canBeNormalized()) { + moveDir.normalize(); + yawSpeed = std::fabs(std::acos(zeus::clamp(-1.f, playerToCamDir.dot(-moveDir), 1.f))) * morphT / dt; + } + zeus::CVector3f useLookDir = ConstrainYawAngle(mgr.GetPlayer(), yawSpeed, zeus::degToRad(10.f), dt, mgr); + useLookDir.z() = 0.f; + useLookDir.normalize(); + zeus::CVector3f camPos = useLookDir * distance + eyePos; + camPos.z() = (GetTranslation().z() - eyePos.z()) * morphT + eyePos.z(); + finalPos = ClampElevationToWater(camPos, mgr); + finalPos = MoveCollisionActor(finalPos, dt, mgr); + zeus::CVector3f finalToBall = ballPos - finalPos; + finalToBall.z() = 0.f; + zeus::CVector3f lookPos = ballPos; + lookPos.z() = morphT * (eyePos.z() - ballPos.z()) + ballPos.z(); + if (finalToBall.canBeNormalized()) + SetTransform(zeus::lookAt(finalPos, lookPos)); + else + SetTransform(mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform()); + } else { + SetTransform(mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform()); + } + SetTranslation(finalPos); + } + break; + } + default: + break; + } - if (!foundClear) - return GetTranslation(); - else - return eyePos + lookVec; + mgr.GetCameraManager()->GetFirstPersonCamera()->Reset(x34_transform, mgr); } -bool CBallCamera::DetectCollision(const zeus::CVector3f& from, const zeus::CVector3f& to, float radius, - float& d, CStateManager& mgr) -{ - zeus::CVector3f delta = to - from; - float deltaMag = delta.magnitude(); - zeus::CVector3f deltaNorm = delta * (1.f / deltaMag); - float clear = true; - if (deltaMag > 0.000001f) - { - float margin = 2.f * radius; - zeus::CAABox aabb; - aabb.accumulateBounds(from); - aabb.accumulateBounds(to); - aabb = zeus::CAABox(aabb.min - margin, aabb.max + margin); +zeus::CTransform CBallCamera::UpdateCameraPositions(float dt, const zeus::CTransform& oldXf, + const zeus::CTransform& newXf) { + zeus::CTransform useXf = newXf; + if (std::fabs(oldXf.basis[1].z()) > 0.9f && std::fabs(newXf.basis[1].z()) > 0.9f && + oldXf.basis[0].dot(newXf.basis[0]) <= 0.999f) { + zeus::CVector3f newRight = + zeus::CQuaternion::clampedRotateTo(oldXf.basis[0], newXf.basis[0], zeus::degToRad(2.f * dt)).toTransform() * + oldXf.basis[0]; + if (newRight.dot(newXf.basis[1]) <= 0.999f) { + zeus::CVector3f newUp = newXf.basis[1].cross(newRight).normalized(); + zeus::CVector3f newForward = newXf.basis[1].normalized(); + useXf = {newUp.cross(newForward), newXf.basis[1], newUp, newXf.origin}; + } + } + return useXf; +} + +zeus::CVector3f CBallCamera::GetFailsafeSplinePoint(const std::vector& points, float t) { + t *= (points.size() - 3); + int baseIdx = 0; + while (t > 1.f) { + t -= 1.f; + baseIdx += 1; + } + return zeus::getBezierPoint(points[baseIdx], points[baseIdx + 1], points[baseIdx + 2], points[baseIdx + 3], t); +} + +bool CBallCamera::CheckFailsafeFromMorphBallState(CStateManager& mgr) const { + TUniqueId xbb8 = kInvalidUniqueId; + float curT = 0.f; + rstl::reserved_vector nearList; + rstl::reserved_vector resultsA; + rstl::reserved_vector resultsB; + while (curT < 6.f) { + zeus::CVector3f pointA = GetFailsafeSplinePoint(x47c_failsafeState->x90_splinePoints, curT / 6.f); + zeus::CVector3f pointB = GetFailsafeSplinePoint(x47c_failsafeState->x90_splinePoints, (1.f + curT) / 6.f); + zeus::CVector3f pointDelta = pointB - pointA; + if (pointDelta.magnitude() > 0.1f) { + resultsA.push_back(mgr.RayWorldIntersection(xbb8, pointA, pointDelta.normalized(), pointDelta.magnitude(), + BallCameraFilter, nearList)); + resultsB.push_back(mgr.RayWorldIntersection(xbb8, pointB, -pointDelta.normalized(), pointDelta.magnitude(), + BallCameraFilter, nearList)); + } else { + resultsA.push_back({}); + resultsB.push_back({}); + } + curT += 1.f; + } + for (int i = 0; i < resultsA.size(); ++i) { + const CRayCastResult& resA = resultsA[i]; + const CRayCastResult& resB = resultsB[i]; + if (resA.IsValid()) { + zeus::CVector3f separation = resA.GetPoint() - resB.GetPoint(); + if (separation.magnitude() < 0.00001f) + separation = GetFailsafeSplinePoint(x47c_failsafeState->x90_splinePoints, (1.f + i) / 6.f) - resA.GetPoint(); + if (separation.magnitude() > 0.3f) + return false; + } + } + return true; +} + +bool CBallCamera::SplineIntersectTest(CMaterialList& intersectMat, CStateManager& mgr) const { + rstl::reserved_vector nearList; + TUniqueId xe38 = kInvalidUniqueId; + rstl::reserved_vector xacc; + rstl::reserved_vector xd10; + CMaterialFilter filter = + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Floor, EMaterialTypes::Wall}, + {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, + EMaterialTypes::Character, EMaterialTypes::CameraPassthrough}); + float curT = 0.f; + while (curT < 12.f) { + zeus::CVector3f xdb0 = x37c_camSpline.GetInterpolatedSplinePointByTime(curT, 12.f); + zeus::CVector3f xdbc = x37c_camSpline.GetInterpolatedSplinePointByTime(curT, 12.f); + zeus::CVector3f xdc8 = xdbc - xdb0; + if (xdc8.magnitude() > 0.1f) { + xacc.push_back(mgr.RayWorldIntersection(xe38, xdb0, xdc8.normalized(), xdc8.magnitude(), filter, nearList)); + xd10.push_back(mgr.RayWorldIntersection(xe38, xdbc, -xdc8.normalized(), xdc8.magnitude(), filter, nearList)); + } else { + xacc.push_back({}); + xd10.push_back({}); + } + curT += 1.f; + } + for (int i = 0; i < xacc.size(); ++i) { + const CRayCastResult& resA = xacc[i]; + const CRayCastResult& resB = xd10[i]; + if (resA.IsValid()) { + zeus::CVector3f xdd4 = resA.GetPoint() - resB.GetPoint(); + if (xdd4.magnitude() < 0.00001f) + xdd4 = x37c_camSpline.GetInterpolatedSplinePointByTime(1.f + i, 12.f) - resA.GetPoint(); + if (xdd4.magnitude() > 0.3f) { + intersectMat = resA.GetMaterial(); + return false; + } + } + } + return true; +} + +bool CBallCamera::IsBallNearDoor(const zeus::CVector3f& pos, CStateManager& mgr) { + TCastToConstPtr door = mgr.GetObjectById(mgr.GetCameraManager()->GetBallCamera()->x3dc_tooCloseActorId); + if (!door || door->x2a8_26_isOpen) + return false; + + auto tb = door->GetTouchBounds(); + zeus::CAABox testAABB(pos - 0.3f, pos + 0.3f); + if (!tb || !tb->intersects(testAABB)) + return false; + + if (TCastToConstPtr dock = mgr.GetObjectById(door->x282_dockId)) + if (std::fabs(dock->GetPlane(mgr).pointToPlaneDist(pos)) < 1.15f) + return true; + + return false; +} + +void CBallCamera::ActivateFailsafe(float dt, CStateManager& mgr) { + float elevation = x1a0_elevation; + float distance = x194_targetMinDistance; + ConstrainElevationAndDistance(elevation, distance, dt, mgr); + zeus::CVector3f desiredPos = FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, true); + SetTranslation(desiredPos); + ResetPosition(mgr); + TeleportCamera(zeus::lookAt(desiredPos, x1d8_lookPos), mgr); + mgr.GetCameraManager()->SetPlayerCamera(mgr, GetUniqueId()); + x3e4_pendingFailsafe = false; + x34c_obscuredTime = 0.f; +} + +bool CBallCamera::ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr) { + zeus::CVector3f ballToCam = GetTranslation() - mgr.GetPlayer().GetBallPosition(); + float ballToCamMag = 0.f; + if (ballToCam.canBeNormalized()) + ballToCamMag = ballToCam.toVec2f().magnitude(); + else + ballToCam = -mgr.GetPlayer().GetMoveDir(); + + bool doorClose = false; + float stretchFac = 1.f; + float newDistance = distance; + float baseElevation = elevation; + float springSpeed = 1.f; + if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) { + if (!door->x2a8_29_ballDoor) { + stretchFac = zeus::clamp(-1.f, std::fabs(x3e0_tooCloseActorDist / (3.f * distance)), 1.f); + if (x3e0_tooCloseActorDist < 3.f * distance) + doorClose = true; + if (door->x2a8_26_isOpen) + newDistance = stretchFac * (distance - x468_conservativeDoorCamDistance) + x468_conservativeDoorCamDistance; + else + newDistance = stretchFac * (distance - 5.f) + 5.f; + if (x18d_28_obtuseDirection) + newDistance *= 1.f + x308_speedFactor; + baseElevation = door->x2a8_26_isOpen ? 0.75f : 1.5f; + springSpeed = 4.f; + } + } + + x214_ballCameraSpring.ApplyDistanceSpring(newDistance, ballToCamMag, dt * springSpeed); + distance = newDistance; + elevation = (elevation - baseElevation) * stretchFac + baseElevation; + + return doorClose; +} + +zeus::CVector3f CBallCamera::FindDesiredPosition(float distance, float elevation, const zeus::CVector3f& dir, + CStateManager& mgr, bool fullTest) { + TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject); + if (!player) + return {}; + + zeus::CVector3f useDir = dir; + if (!dir.canBeNormalized()) + useDir = zeus::CVector3f::skForward; + + zeus::CTransform lookDirXf = zeus::lookAt(zeus::CVector3f::skZero, useDir); + zeus::CVector3f ballPos = player->GetBallPosition(); + float elev = elevation; + float dist = distance; + ConstrainElevationAndDistance(elev, dist, 0.f, mgr); + zeus::CVector3f eyePos = player->GetEyePosition(); + if (!mgr.RayCollideWorld(ballPos, eyePos, BallCameraFilter, nullptr)) + eyePos = ballPos; + + zeus::CVector3f idealLookVec(0.f, -dist, elev - (eyePos.z() - ballPos.z())); + idealLookVec = lookDirXf.getRotation() * idealLookVec; + zeus::CVector3f lookVec(0.f, distance, elev - (eyePos.z() - ballPos.z())); + float idealLookDist = idealLookVec.magnitude(); + float resolveLOSIntervalAng = zeus::degToRad(30.f); + bool foundClear = false; + bool clear = !DetectCollision(eyePos, eyePos + idealLookVec, 0.3f, idealLookDist, mgr); + if (!clear && idealLookDist <= 0.f) { + zeus::CAABox x13ac(ballPos - distance, ballPos + distance); + x13ac.min.z() = float(ballPos.z()); + x13ac.max.z() = elev + ballPos.z(); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, x13ac, BallCameraFilter, + TCastToConstPtr(mgr.GetObjectById(x46c_collisionActorId)).GetPtr()); + zeus::CQuaternion rotNeg; + rotNeg.rotateZ(-resolveLOSIntervalAng); + zeus::CTransform xfNeg = rotNeg.toTransform(); + zeus::CQuaternion rotPos; + rotPos.rotateZ(resolveLOSIntervalAng); + zeus::CTransform xfPos = rotPos.toTransform(); + while (!foundClear && idealLookDist > dist) { + idealLookVec.normalize(); + idealLookVec = idealLookVec * idealLookDist; + zeus::CVector3f lookVecNeg = xfNeg.rotate(idealLookVec); + zeus::CVector3f lookVecPos = xfPos.rotate(idealLookVec); + for (int i = 0; float(i) < 180.f / zeus::radToDeg(resolveLOSIntervalAng); ++i) { + if (mgr.RayCollideWorld(eyePos, eyePos + lookVecNeg, nearList, BallCameraFilter, nullptr)) { + foundClear = true; + lookVec = lookVecNeg; + break; + } else if (mgr.RayCollideWorld(eyePos, eyePos + lookVecPos, nearList, BallCameraFilter, nullptr)) { + foundClear = true; + lookVec = lookVecPos; + break; + } else { + lookVecNeg = xfNeg * lookVecNeg; + lookVecPos = xfPos * lookVecPos; + } + } + idealLookDist -= 0.3f; + } + } else { + if (idealLookDist < 2.f) { + idealLookVec.normalize(); + idealLookVec = idealLookVec * 2.f; + } + zeus::CQuaternion rotNeg; + rotNeg.rotateZ(-resolveLOSIntervalAng); + zeus::CTransform xfNeg = rotNeg.toTransform(); + zeus::CVector3f lookVecNeg = xfNeg * idealLookVec; + zeus::CQuaternion rotPos; + rotPos.rotateZ(resolveLOSIntervalAng); + zeus::CTransform xfPos = rotPos.toTransform(); + zeus::CVector3f lookVecPos = xfPos * idealLookVec; + if (clear || (!fullTest && (idealLookDist > 2.f || x2e8_ballVelFlat > 1.25f))) { + idealLookVec.normalize(); + lookVec = idealLookVec * idealLookDist; + foundClear = true; + } else { + for (int i = 0; float(i) < 180.f / zeus::radToDeg(resolveLOSIntervalAng); ++i) { + idealLookDist = lookVecNeg.magnitude(); + if (!DetectCollision(eyePos, eyePos + lookVecNeg, 0.3f, idealLookDist, mgr) || idealLookDist > 2.f) { + lookVecNeg.normalize(); + lookVec = lookVecNeg * idealLookDist; + foundClear = true; + break; + } + idealLookDist = lookVecPos.magnitude(); + if (!DetectCollision(eyePos, eyePos + lookVecPos, 0.3f, idealLookDist, mgr) || idealLookDist > 2.f) { + lookVecPos.normalize(); + lookVec = lookVecPos * idealLookDist; + foundClear = true; + break; + } + lookVecNeg = xfNeg * lookVecNeg; + lookVecPos = xfPos * lookVecPos; + } + if (!foundClear) { + zeus::CAABox findBounds(ballPos - distance, ballPos + distance); + findBounds.min.z() = float(ballPos.z()); + findBounds.max.z() = elev + ballPos.z(); rstl::reserved_vector nearList; - mgr.BuildColliderList(nearList, mgr.GetPlayer(), aabb); - CAreaCollisionCache cache(aabb); - CGameCollision::BuildAreaCollisionCache(mgr, cache); - if (cache.HasCacheOverflowed()) - clear = false; - CCollidableSphere cSphere({zeus::CVector3f::skZero, radius}, {EMaterialTypes::Solid}); - if (CGameCollision::DetectCollisionBoolean_Cached(mgr, cache, cSphere, zeus::CTransform::Translate(from), - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::ProjectilePassthrough, - EMaterialTypes::Player, - EMaterialTypes::Character, - EMaterialTypes::CameraPassthrough}), nearList)) - { - d = -1.f; - return true; - } - if (clear) - { - TUniqueId intersectId = kInvalidUniqueId; - CCollisionInfo info; - double dTmp = deltaMag; - if (CGameCollision::DetectCollision_Cached_Moving(mgr, cache, cSphere, zeus::CTransform::Translate(from), - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::ProjectilePassthrough, - EMaterialTypes::Player, - EMaterialTypes::Character, - EMaterialTypes::CameraPassthrough}), - nearList, deltaNorm, intersectId, info, dTmp)) - { - d = float(dTmp); - clear = false; + mgr.BuildNearList(nearList, findBounds, BallCameraFilter, + TCastToConstPtr(mgr.GetObjectById(x46c_collisionActorId)).GetPtr()); + zeus::CQuaternion rotNeg2; + rotNeg2.rotateZ(-resolveLOSIntervalAng); + zeus::CTransform xfNeg2 = rotNeg2.toTransform(); + zeus::CQuaternion rotPos2; + rotPos2.rotateZ(resolveLOSIntervalAng); + zeus::CTransform xfPos2 = rotPos2.toTransform(); + while (!foundClear && idealLookDist > dist) { + idealLookVec.normalize(); + idealLookVec = idealLookVec * idealLookDist; + zeus::CVector3f lookVecNeg2 = xfNeg2.rotate(idealLookVec); + zeus::CVector3f lookVecPos2 = xfPos2.rotate(idealLookVec); + for (int i = 0; float(i) < 180.f / zeus::radToDeg(resolveLOSIntervalAng); ++i) { + if (mgr.RayCollideWorld(eyePos, eyePos + lookVecNeg2, nearList, BallCameraFilter, nullptr)) { + foundClear = true; + lookVec = lookVecNeg2; + break; + } else if (mgr.RayCollideWorld(eyePos, eyePos + lookVecPos2, nearList, BallCameraFilter, nullptr)) { + foundClear = true; + lookVec = lookVecPos2; + break; + } else { + lookVecNeg2 = xfNeg2 * lookVecNeg2; + lookVecPos2 = xfPos2 * lookVecPos2; } + } + idealLookDist -= 0.3f; } + } } - return !clear; + } + + if (!foundClear) + return GetTranslation(); + else + return eyePos + lookVec; } -void CBallCamera::Think(float dt, CStateManager& mgr) -{ - mgr.SetActorAreaId(*this, mgr.GetNextAreaId()); - UpdatePlayerMovement(dt, mgr); - TCastToPtr colAct = mgr.ObjectById(x46c_collisionActorId); +bool CBallCamera::DetectCollision(const zeus::CVector3f& from, const zeus::CVector3f& to, float radius, float& d, + CStateManager& mgr) { + zeus::CVector3f delta = to - from; + float deltaMag = delta.magnitude(); + zeus::CVector3f deltaNorm = delta * (1.f / deltaMag); + float clear = true; + if (deltaMag > 0.000001f) { + float margin = 2.f * radius; + zeus::CAABox aabb; + aabb.accumulateBounds(from); + aabb.accumulateBounds(to); + aabb = zeus::CAABox(aabb.min - margin, aabb.max + margin); + rstl::reserved_vector nearList; + mgr.BuildColliderList(nearList, mgr.GetPlayer(), aabb); + CAreaCollisionCache cache(aabb); + CGameCollision::BuildAreaCollisionCache(mgr, cache); + if (cache.HasCacheOverflowed()) + clear = false; + CCollidableSphere cSphere({zeus::CVector3f::skZero, radius}, {EMaterialTypes::Solid}); + if (CGameCollision::DetectCollisionBoolean_Cached( + mgr, cache, cSphere, zeus::CTransform::Translate(from), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, + {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, + EMaterialTypes::Character, EMaterialTypes::CameraPassthrough}), + nearList)) { + d = -1.f; + return true; + } + if (clear) { + TUniqueId intersectId = kInvalidUniqueId; + CCollisionInfo info; + double dTmp = deltaMag; + if (CGameCollision::DetectCollision_Cached_Moving( + mgr, cache, cSphere, zeus::CTransform::Translate(from), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, + {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, + EMaterialTypes::Character, EMaterialTypes::CameraPassthrough}), + nearList, deltaNorm, intersectId, info, dTmp)) { + d = float(dTmp); + clear = false; + } + } + } + return !clear; +} + +void CBallCamera::Think(float dt, CStateManager& mgr) { + mgr.SetActorAreaId(*this, mgr.GetNextAreaId()); + UpdatePlayerMovement(dt, mgr); + TCastToPtr colAct = mgr.ObjectById(x46c_collisionActorId); + if (colAct) + mgr.SetActorAreaId(*colAct, mgr.GetNextAreaId()); + + switch (mgr.GetPlayer().GetCameraState()) { + default: + if (!x18d_27_forceProcessing) { + if (colAct) + colAct->SetActive(false); + return; + } + case CPlayer::EPlayerCameraState::Ball: + case CPlayer::EPlayerCameraState::Transitioning: + case CPlayer::EPlayerCameraState::Two: { if (colAct) - mgr.SetActorAreaId(*colAct, mgr.GetNextAreaId()); - - switch (mgr.GetPlayer().GetCameraState()) - { - default: - if (!x18d_27_forceProcessing) - { - if (colAct) - colAct->SetActive(false); - return; - } - case CPlayer::EPlayerCameraState::Ball: - case CPlayer::EPlayerCameraState::Transitioning: - case CPlayer::EPlayerCameraState::Two: - { - if (colAct) - colAct->SetActive(true); - zeus::CTransform oldXf = x34_transform; - if (mgr.GetPlayer().GetBombJumpCount() != 1) - UpdateLookAtPosition(dt, mgr); - CheckFailsafe(dt, mgr); - UpdateObjectTooCloseId(mgr); - UpdateAnglePerSecond(dt); - switch (x400_state) - { - case EBallCameraState::Default: - case EBallCameraState::Chase: - case EBallCameraState::Boost: - switch (x188_behaviour) - { - case EBallCameraBehaviour::PathCamera: - UpdateUsingPathCameras(dt, mgr); - break; - case EBallCameraBehaviour::HintFixedPosition: - case EBallCameraBehaviour::HintFixedTransform: - UpdateUsingFixedCameras(dt, mgr); - break; - case EBallCameraBehaviour::PathCameraDesiredPos: - case EBallCameraBehaviour::Default: - case EBallCameraBehaviour::FreezeLookPosition: - case EBallCameraBehaviour::HintBallToCam: - if (x36c_splineState != ESplineState::Invalid) - UpdateUsingFreeLook(dt, mgr); - else - UpdateUsingColliders(dt, mgr); - break; - case EBallCameraBehaviour::SpindleCamera: - UpdateUsingSpindleCameras(dt, mgr); - break; - default: - break; - } - break; - case EBallCameraState::ToBall: - case EBallCameraState::FromBall: - UpdateUsingTransitions(dt, mgr); - break; - default: - break; - } - - SetTransform(ValidateCameraTransform(UpdateCameraPositions(dt, oldXf, x34_transform), oldXf)); + colAct->SetActive(true); + zeus::CTransform oldXf = x34_transform; + if (mgr.GetPlayer().GetBombJumpCount() != 1) + UpdateLookAtPosition(dt, mgr); + CheckFailsafe(dt, mgr); + UpdateObjectTooCloseId(mgr); + UpdateAnglePerSecond(dt); + switch (x400_state) { + case EBallCameraState::Default: + case EBallCameraState::Chase: + case EBallCameraState::Boost: + switch (x188_behaviour) { + case EBallCameraBehaviour::PathCamera: + UpdateUsingPathCameras(dt, mgr); break; + case EBallCameraBehaviour::HintFixedPosition: + case EBallCameraBehaviour::HintFixedTransform: + UpdateUsingFixedCameras(dt, mgr); + break; + case EBallCameraBehaviour::PathCameraDesiredPos: + case EBallCameraBehaviour::Default: + case EBallCameraBehaviour::FreezeLookPosition: + case EBallCameraBehaviour::HintBallToCam: + if (x36c_splineState != ESplineState::Invalid) + UpdateUsingFreeLook(dt, mgr); + else + UpdateUsingColliders(dt, mgr); + break; + case EBallCameraBehaviour::SpindleCamera: + UpdateUsingSpindleCameras(dt, mgr); + break; + default: + break; + } + break; + case EBallCameraState::ToBall: + case EBallCameraState::FromBall: + UpdateUsingTransitions(dt, mgr); + break; + default: + break; } - } + + SetTransform(ValidateCameraTransform(UpdateCameraPositions(dt, oldXf, x34_transform), oldXf)); + break; + } + } } bool CBallCamera::CheckTransitionLineOfSight(const zeus::CVector3f& eyePos, const zeus::CVector3f& behindPos, - float& eyeToOccDist, float colRadius, CStateManager& mgr) -{ - zeus::CVector3f eyeToBehind = behindPos - eyePos; - float eyeToBehindMag = eyeToBehind.magnitude(); - zeus::CVector3f eyeToBehindNorm = eyeToBehind * (1.f / eyeToBehindMag); - bool clear = true; - if (eyeToBehindMag > 0.000001f) - { - float margin = 2.f * colRadius; - zeus::CAABox aabb; - aabb.accumulateBounds(eyePos); - aabb.accumulateBounds(behindPos); - aabb = zeus::CAABox(aabb.min - margin, aabb.max + margin); - rstl::reserved_vector nearList; - mgr.BuildColliderList(nearList, mgr.GetPlayer(), aabb); - CAreaCollisionCache cache(aabb); - CGameCollision::BuildAreaCollisionCache(mgr, cache); - if (cache.HasCacheOverflowed()) - clear = false; - if (clear) - { - CCollisionInfo cinfo; - double d = eyeToBehindMag; - TUniqueId intersectId = kInvalidUniqueId; - CCollidableSphere cSphere({zeus::CVector3f::skZero, colRadius}, {EMaterialTypes::Solid}); - if (CGameCollision::DetectCollision_Cached_Moving(mgr, cache, cSphere, zeus::CTransform::Translate(eyePos), - CMaterialFilter::MakeIncludeExclude( - {EMaterialTypes::Solid}, - {EMaterialTypes::ProjectilePassthrough, - EMaterialTypes::Player, - EMaterialTypes::Character, - EMaterialTypes::CameraPassthrough}), - nearList, eyeToBehindNorm, intersectId, cinfo, d)) - { - eyeToOccDist = float(d); - clear = false; - } - } + float& eyeToOccDist, float colRadius, CStateManager& mgr) { + zeus::CVector3f eyeToBehind = behindPos - eyePos; + float eyeToBehindMag = eyeToBehind.magnitude(); + zeus::CVector3f eyeToBehindNorm = eyeToBehind * (1.f / eyeToBehindMag); + bool clear = true; + if (eyeToBehindMag > 0.000001f) { + float margin = 2.f * colRadius; + zeus::CAABox aabb; + aabb.accumulateBounds(eyePos); + aabb.accumulateBounds(behindPos); + aabb = zeus::CAABox(aabb.min - margin, aabb.max + margin); + rstl::reserved_vector nearList; + mgr.BuildColliderList(nearList, mgr.GetPlayer(), aabb); + CAreaCollisionCache cache(aabb); + CGameCollision::BuildAreaCollisionCache(mgr, cache); + if (cache.HasCacheOverflowed()) + clear = false; + if (clear) { + CCollisionInfo cinfo; + double d = eyeToBehindMag; + TUniqueId intersectId = kInvalidUniqueId; + CCollidableSphere cSphere({zeus::CVector3f::skZero, colRadius}, {EMaterialTypes::Solid}); + if (CGameCollision::DetectCollision_Cached_Moving( + mgr, cache, cSphere, zeus::CTransform::Translate(eyePos), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, + {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, + EMaterialTypes::Character, EMaterialTypes::CameraPassthrough}), + nearList, eyeToBehindNorm, intersectId, cinfo, d)) { + eyeToOccDist = float(d); + clear = false; + } } - return !clear; + } + return !clear; } -bool CBallCamera::TransitionFromMorphBallState(CStateManager& mgr) -{ - x47c_failsafeState->x0_playerXf = mgr.GetPlayer().GetTransform(); - x47c_failsafeState->x30_camXf = GetTransform(); - x47c_failsafeState->x60_lookPos = x1d8_lookPos; - x47c_failsafeState->x84_playerPos = x47c_failsafeState->x0_playerXf.origin; - zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); - float lookDist = (x47c_failsafeState->x60_lookPos - x47c_failsafeState->x30_camXf.origin).magnitude(); - zeus::CVector3f behindPos = x47c_failsafeState->x0_playerXf.basis[1] * (0.6f * -lookDist) + eyePos; - float eyeToOccDist; - if (CheckTransitionLineOfSight(eyePos, behindPos, eyeToOccDist, 0.6f, mgr)) - x47c_failsafeState->x6c_behindPos = x47c_failsafeState->x0_playerXf.basis[1] * -eyeToOccDist + eyePos; +bool CBallCamera::TransitionFromMorphBallState(CStateManager& mgr) { + x47c_failsafeState->x0_playerXf = mgr.GetPlayer().GetTransform(); + x47c_failsafeState->x30_camXf = GetTransform(); + x47c_failsafeState->x60_lookPos = x1d8_lookPos; + x47c_failsafeState->x84_playerPos = x47c_failsafeState->x0_playerXf.origin; + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + float lookDist = (x47c_failsafeState->x60_lookPos - x47c_failsafeState->x30_camXf.origin).magnitude(); + zeus::CVector3f behindPos = x47c_failsafeState->x0_playerXf.basis[1] * (0.6f * -lookDist) + eyePos; + float eyeToOccDist; + if (CheckTransitionLineOfSight(eyePos, behindPos, eyeToOccDist, 0.6f, mgr)) + x47c_failsafeState->x6c_behindPos = x47c_failsafeState->x0_playerXf.basis[1] * -eyeToOccDist + eyePos; + else + x47c_failsafeState->x6c_behindPos = behindPos; + x47c_failsafeState->x90_splinePoints.clear(); + x47c_failsafeState->x90_splinePoints.reserve(4); + x47c_failsafeState->x90_splinePoints.push_back(x47c_failsafeState->x30_camXf.origin); + x47c_failsafeState->x90_splinePoints.push_back(x47c_failsafeState->x6c_behindPos); + x47c_failsafeState->x90_splinePoints.push_back(x47c_failsafeState->x6c_behindPos); + x47c_failsafeState->x90_splinePoints.push_back(eyePos); + return CheckFailsafeFromMorphBallState(mgr); +} + +void CBallCamera::TeleportColliders(std::vector& colliderList, const zeus::CVector3f& pos) { + for (CCameraCollider& collider : colliderList) { + collider.x2c_lastWorldPos = pos; + collider.x14_localPos = pos; + collider.x20_scaledWorldPos = pos; + } +} + +void CBallCamera::TeleportCamera(const zeus::CVector3f& pos, CStateManager& mgr) { + x294_dampedPos = pos; + TeleportColliders(x264_smallColliders, pos); + TeleportColliders(x274_mediumColliders, pos); + TeleportColliders(x284_largeColliders, pos); + if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) + act->SetTranslation(pos); +} + +void CBallCamera::TeleportCamera(const zeus::CTransform& xf, CStateManager& mgr) { + SetTransform(xf); + TeleportCamera(xf.origin, mgr); +} + +void CBallCamera::ResetToTweaks(CStateManager& mgr) { + x188_behaviour = EBallCameraBehaviour::Default; + x18c_25_chaseAllowed = true; + x18c_26_boostAllowed = true; + x18c_27_obscureAvoidance = true; + x18c_28_volumeCollider = true; + x18c_29_clampAttitude = false; + x18c_30_clampAzimuth = false; + x194_targetMinDistance = g_tweakBall->GetBallCameraMinSpeedDistance(); + x198_maxDistance = g_tweakBall->GetBallCameraMaxSpeedDistance(); + x19c_backwardsDistance = g_tweakBall->GetBallCameraBackwardsDistance(); + x214_ballCameraSpring = + CCameraSpring(g_tweakBall->GetBallCameraSpringConstant(), g_tweakBall->GetBallCameraSpringMax(), + g_tweakBall->GetBallCameraSpringTardis()); + x250_ballCameraCentroidDistanceSpring = CCameraSpring(g_tweakBall->GetBallCameraCentroidDistanceSpringConstant(), + g_tweakBall->GetBallCameraCentroidDistanceSpringMax(), + g_tweakBall->GetBallCameraCentroidDistanceSpringTardis()); + x1b4_lookAtOffset = g_tweakBall->GetBallCameraOffset(); + x410_chaseLookAtOffset = g_tweakBall->GetBallCameraChaseLookAtOffset(); + x1a0_elevation = g_tweakBall->GetBallCameraElevation(); + x1ac_attitudeRange = M_PIF / 2.f; + x1b0_azimuthRange = M_PIF / 2.f; + SetFovInterpolation(x15c_currentFov, CCameraManager::ThirdPersonFOV(), 1.f, 0.f); + x1a8_targetAnglePerSecond = g_tweakBall->GetBallCameraAnglePerSecond(); + x18d_29_noElevationInterp = false; + x18d_30_directElevation = false; + x18d_31_overrideLookDir = false; + x18e_24_noElevationVelClamp = false; + x18e_25_noSpline = false; + x18e_26_ = false; +} + +void CBallCamera::UpdateLookAtPosition(float dt, CStateManager& mgr) { + if (TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject)) { + zeus::CVector3f ballPos = player->GetBallPosition(); + if (player->IsMorphBallTransitioning()) { + x1d8_lookPos = ballPos; + x1d8_lookPos.z() += x1b4_lookAtOffset.z(); + x1c0_lookPosAhead = x1d8_lookPos; + x1cc_fixedLookPos = x1d8_lookPos; + } else { + zeus::CVector3f dirNorm = player->GetMoveDir(); + dirNorm.normalize(); + zeus::CVector3f lookAtOffsetAhead(x308_speedFactor * x1b4_lookAtOffset.x(), + x308_speedFactor * x1b4_lookAtOffset.y(), x1b4_lookAtOffset.z()); + if (x18c_25_chaseAllowed && (x400_state == EBallCameraState::Chase || x400_state == EBallCameraState::One)) + lookAtOffsetAhead = zeus::CVector3f(x308_speedFactor * x410_chaseLookAtOffset.x(), + x308_speedFactor * x410_chaseLookAtOffset.y(), x410_chaseLookAtOffset.z()); + if (mgr.GetCameraManager()->IsInterpolationCameraActive()) + lookAtOffsetAhead = zeus::CVector3f(0.f, 0.f, x1b4_lookAtOffset.z()); + zeus::CTransform moveXf = player->CreateTransformFromMovementDirection().getRotation(); + if (x2fc_ballDeltaFlat.canBeNormalized()) + lookAtOffsetAhead = moveXf * lookAtOffsetAhead; + zeus::CVector3f lookAtPosAhead = ballPos + lookAtOffsetAhead; + x1c0_lookPosAhead = lookAtPosAhead; + x1cc_fixedLookPos = ballPos + zeus::CVector3f(0.f, 0.f, lookAtOffsetAhead.z()); + zeus::CVector3f aheadToCurrentLookDelta = x1d8_lookPos - lookAtPosAhead; + float aheadToCurrentLookMag = aheadToCurrentLookDelta.magnitude(); + if (aheadToCurrentLookDelta.canBeNormalized()) + aheadToCurrentLookDelta.normalize(); + float lookAtSpringMag = x23c_ballCameraLookAtSpring.ApplyDistanceSpringNoMax( + 0.f, aheadToCurrentLookMag, (2.f * zeus::clamp(0.f, x30c_speedingTime / 3.f, 1.f) + 1.f) * dt); + if (lookAtSpringMag > 0.0001f) + lookAtPosAhead += aheadToCurrentLookDelta * lookAtSpringMag; + aheadToCurrentLookDelta = lookAtPosAhead - x1d8_lookPos; + if (x18d_26_lookAtBall) { + x1d8_lookPos = ballPos; + x1d8_lookPos.z() += x1b4_lookAtOffset.z(); + } else { + x1d8_lookPos = lookAtPosAhead; + } + switch (x188_behaviour) { + case EBallCameraBehaviour::Default: + case EBallCameraBehaviour::FreezeLookPosition: + case EBallCameraBehaviour::HintBallToCam: + case EBallCameraBehaviour::HintInitializePosition: + case EBallCameraBehaviour::PathCameraDesiredPos: + case EBallCameraBehaviour::PathCamera: + if (mgr.GetCameraManager()->IsInterpolationCameraActive()) { + x1d8_lookPos = x1c0_lookPosAhead; + x1cc_fixedLookPos = x1c0_lookPosAhead; + } + break; + case EBallCameraBehaviour::HintFixedPosition: + x1d8_lookPos = x1cc_fixedLookPos; + x1c0_lookPosAhead = x1d8_lookPos; + break; + case EBallCameraBehaviour::HintFixedTransform: + case EBallCameraBehaviour::SpindleCamera: + x1d8_lookPos = x1cc_fixedLookPos; + x1c0_lookPosAhead = x1cc_fixedLookPos; + break; + } + if (x18d_30_directElevation) { + x1d8_lookPos.z() = ballPos.z() + x1b4_lookAtOffset.z(); + x1c0_lookPosAhead.z() = float(x1d8_lookPos.z()); + x1cc_fixedLookPos.z() = float(x1d8_lookPos.z()); + } + if (x18d_31_overrideLookDir) { + if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) { + x1d8_lookPos = hint->GetTransform().basis[1] * 10.f + GetTranslation(); + x1c0_lookPosAhead = x1d8_lookPos; + x1cc_fixedLookPos = x1d8_lookPos; + } + } + } + } +} + +zeus::CTransform CBallCamera::UpdateLookDirection(const zeus::CVector3f& dir, CStateManager& mgr) { + zeus::CVector3f useDir = dir; + if (!dir.canBeNormalized()) + useDir = zeus::CVector3f::skForward; + float elevation = x1a0_elevation; + float distance = x190_curMinDistance; + ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); + zeus::CVector3f pos = FindDesiredPosition(distance, elevation, useDir, mgr, false); + UpdateLookAtPosition(0.f, mgr); + return zeus::lookAt(pos, x1d8_lookPos); +} + +void CBallCamera::ApplyCameraHint(CStateManager& mgr) { + if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) { + ResetToTweaks(mgr); + x188_behaviour = hint->GetHint().GetBehaviourType(); + x18c_25_chaseAllowed = (hint->GetHint().GetOverrideFlags() & 0x2) != 0; + x18c_26_boostAllowed = (hint->GetHint().GetOverrideFlags() & 0x4) != 0; + x18c_27_obscureAvoidance = (hint->GetHint().GetOverrideFlags() & 0x8) != 0; + x18c_28_volumeCollider = (hint->GetHint().GetOverrideFlags() & 0x10) != 0; + if ((hint->GetHint().GetOverrideFlags() & 0x40) != 0) + x18d_26_lookAtBall = true; + x18d_29_noElevationInterp = (hint->GetHint().GetOverrideFlags() & 0x4000) != 0; + x18d_30_directElevation = (hint->GetHint().GetOverrideFlags() & 0x8000) != 0; + x18d_31_overrideLookDir = (hint->GetHint().GetOverrideFlags() & 0x10000) != 0; + x18e_24_noElevationVelClamp = (hint->GetHint().GetOverrideFlags() & 0x20000) != 0; + x18e_25_noSpline = x18e_26_ = (hint->GetHint().GetOverrideFlags() & 0x80000) != 0; + if ((hint->GetHint().GetOverrideFlags() & 0x400000) != 0) + x194_targetMinDistance = hint->GetHint().GetMinDist(); + if ((hint->GetHint().GetOverrideFlags() & 0x800000) != 0) + x198_maxDistance = hint->GetHint().GetMaxDist(); + if ((hint->GetHint().GetOverrideFlags() & 0x1000000) != 0) + x19c_backwardsDistance = hint->GetHint().GetBackwardsDist(); + if ((hint->GetHint().GetOverrideFlags() & 0x80000000) != 0) + x1a0_elevation = hint->GetHint().GetElevation(); + if ((hint->GetHint().GetOverrideFlags() & 0x2000000) != 0) + x1b4_lookAtOffset = hint->GetHint().GetLookAtOffset(); + if ((hint->GetHint().GetOverrideFlags() & 0x4000000) != 0) + x410_chaseLookAtOffset = hint->GetHint().GetChaseLookAtOffset(); + if ((hint->GetHint().GetOverrideFlags() & 0x10000000) != 0) { + x18c_29_clampAttitude = true; + x1ac_attitudeRange = hint->GetHint().GetAttitudeRange(); + } else { + x18c_29_clampAttitude = false; + } + if ((hint->GetHint().GetOverrideFlags() & 0x20000000) != 0) { + x18c_30_clampAzimuth = true; + x1b0_azimuthRange = hint->GetHint().GetAzimuthRange(); + } else { + x18c_30_clampAzimuth = false; + } + if ((hint->GetHint().GetOverrideFlags() & 0x8000000) != 0) + SetFovInterpolation(x15c_currentFov, hint->GetHint().GetFov(), 1.f, 0.f); + if ((hint->GetHint().GetOverrideFlags() & 0x40000000) != 0) + x1a8_targetAnglePerSecond = hint->GetHint().GetAnglePerSecond(); + if ((hint->GetHint().GetOverrideFlags() & 0x200) != 0) + mgr.GetPlayer().SetControlDirectionInterpolation(hint->GetHint().GetControlInterpDur()); else - x47c_failsafeState->x6c_behindPos = behindPos; - x47c_failsafeState->x90_splinePoints.clear(); - x47c_failsafeState->x90_splinePoints.reserve(4); - x47c_failsafeState->x90_splinePoints.push_back(x47c_failsafeState->x30_camXf.origin); - x47c_failsafeState->x90_splinePoints.push_back(x47c_failsafeState->x6c_behindPos); - x47c_failsafeState->x90_splinePoints.push_back(x47c_failsafeState->x6c_behindPos); - x47c_failsafeState->x90_splinePoints.push_back(eyePos); - return CheckFailsafeFromMorphBallState(mgr); -} - -void CBallCamera::TeleportColliders(std::vector& colliderList, const zeus::CVector3f& pos) -{ - for (CCameraCollider& collider : colliderList) - { - collider.x2c_lastWorldPos = pos; - collider.x14_localPos = pos; - collider.x20_scaledWorldPos = pos; + mgr.GetPlayer().ResetControlDirectionInterpolation(); + switch (hint->GetHint().GetBehaviourType()) { + case EBallCameraBehaviour::HintBallToCam: { + x45c_overrideBallToCam = hint->GetHint().GetBallToCam(); + ResetPosition(mgr); + zeus::CVector3f camPos = mgr.GetPlayer().GetBallPosition() + hint->GetHint().GetBallToCam(); + if ((hint->GetHint().GetOverrideFlags() & 0x1) != 0) { + float distance = hint->GetHint().GetBallToCam().toVec2f().magnitude(); + zeus::CVector3f camToBall = -zeus::CVector3f(hint->GetHint().GetBallToCam().toVec2f()).normalized(); + camPos = FindDesiredPosition(distance, hint->GetHint().GetBallToCam().z(), camToBall, mgr, false); + } + TeleportCamera(zeus::lookAt(camPos, x1d8_lookPos), mgr); + break; } -} - -void CBallCamera::TeleportCamera(const zeus::CVector3f& pos, CStateManager& mgr) -{ - x294_dampedPos = pos; - TeleportColliders(x264_smallColliders, pos); - TeleportColliders(x274_mediumColliders, pos); - TeleportColliders(x284_largeColliders, pos); - if (TCastToPtr act = mgr.ObjectById(x46c_collisionActorId)) - act->SetTranslation(pos); -} - -void CBallCamera::TeleportCamera(const zeus::CTransform& xf, CStateManager& mgr) -{ - SetTransform(xf); - TeleportCamera(xf.origin, mgr); -} - -void CBallCamera::ResetToTweaks(CStateManager& mgr) -{ - x188_behaviour = EBallCameraBehaviour::Default; - x18c_25_chaseAllowed = true; - x18c_26_boostAllowed = true; - x18c_27_obscureAvoidance = true; - x18c_28_volumeCollider = true; - x18c_29_clampAttitude = false; - x18c_30_clampAzimuth = false; - x194_targetMinDistance = g_tweakBall->GetBallCameraMinSpeedDistance(); - x198_maxDistance = g_tweakBall->GetBallCameraMaxSpeedDistance(); - x19c_backwardsDistance = g_tweakBall->GetBallCameraBackwardsDistance(); - x214_ballCameraSpring = CCameraSpring(g_tweakBall->GetBallCameraSpringConstant(), - g_tweakBall->GetBallCameraSpringMax(), - g_tweakBall->GetBallCameraSpringTardis()); - x250_ballCameraCentroidDistanceSpring = CCameraSpring(g_tweakBall->GetBallCameraCentroidDistanceSpringConstant(), - g_tweakBall->GetBallCameraCentroidDistanceSpringMax(), - g_tweakBall->GetBallCameraCentroidDistanceSpringTardis()); - x1b4_lookAtOffset = g_tweakBall->GetBallCameraOffset(); - x410_chaseLookAtOffset = g_tweakBall->GetBallCameraChaseLookAtOffset(); - x1a0_elevation = g_tweakBall->GetBallCameraElevation(); - x1ac_attitudeRange = M_PIF / 2.f; - x1b0_azimuthRange = M_PIF / 2.f; - SetFovInterpolation(x15c_currentFov, CCameraManager::ThirdPersonFOV(), 1.f, 0.f); - x1a8_targetAnglePerSecond = g_tweakBall->GetBallCameraAnglePerSecond(); - x18d_29_noElevationInterp = false; - x18d_30_directElevation = false; - x18d_31_overrideLookDir = false; - x18e_24_noElevationVelClamp = false; - x18e_25_noSpline = false; - x18e_26_ = false; -} - -void CBallCamera::UpdateLookAtPosition(float dt, CStateManager& mgr) -{ - if (TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject)) - { - zeus::CVector3f ballPos = player->GetBallPosition(); - if (player->IsMorphBallTransitioning()) - { - x1d8_lookPos = ballPos; - x1d8_lookPos.z() += x1b4_lookAtOffset.z(); - x1c0_lookPosAhead = x1d8_lookPos; - x1cc_fixedLookPos = x1d8_lookPos; - } - else - { - zeus::CVector3f dirNorm = player->GetMoveDir(); - dirNorm.normalize(); - zeus::CVector3f lookAtOffsetAhead(x308_speedFactor * x1b4_lookAtOffset.x(), - x308_speedFactor * x1b4_lookAtOffset.y(), - x1b4_lookAtOffset.z()); - if (x18c_25_chaseAllowed && (x400_state == EBallCameraState::Chase || x400_state == EBallCameraState::One)) - lookAtOffsetAhead = zeus::CVector3f(x308_speedFactor * x410_chaseLookAtOffset.x(), - x308_speedFactor * x410_chaseLookAtOffset.y(), - x410_chaseLookAtOffset.z()); - if (mgr.GetCameraManager()->IsInterpolationCameraActive()) - lookAtOffsetAhead = zeus::CVector3f(0.f, 0.f, x1b4_lookAtOffset.z()); - zeus::CTransform moveXf = player->CreateTransformFromMovementDirection().getRotation(); - if (x2fc_ballDeltaFlat.canBeNormalized()) - lookAtOffsetAhead = moveXf * lookAtOffsetAhead; - zeus::CVector3f lookAtPosAhead = ballPos + lookAtOffsetAhead; - x1c0_lookPosAhead = lookAtPosAhead; - x1cc_fixedLookPos = ballPos + zeus::CVector3f(0.f, 0.f, lookAtOffsetAhead.z()); - zeus::CVector3f aheadToCurrentLookDelta = x1d8_lookPos - lookAtPosAhead; - float aheadToCurrentLookMag = aheadToCurrentLookDelta.magnitude(); - if (aheadToCurrentLookDelta.canBeNormalized()) - aheadToCurrentLookDelta.normalize(); - float lookAtSpringMag = x23c_ballCameraLookAtSpring.ApplyDistanceSpringNoMax(0.f, aheadToCurrentLookMag, - (2.f * zeus::clamp(0.f, x30c_speedingTime / 3.f, 1.f) + 1.f) * dt); - if (lookAtSpringMag > 0.0001f) - lookAtPosAhead += aheadToCurrentLookDelta * lookAtSpringMag; - aheadToCurrentLookDelta = lookAtPosAhead - x1d8_lookPos; - if (x18d_26_lookAtBall) - { - x1d8_lookPos = ballPos; - x1d8_lookPos.z() += x1b4_lookAtOffset.z(); - } - else - { - x1d8_lookPos = lookAtPosAhead; - } - switch (x188_behaviour) - { - case EBallCameraBehaviour::Default: - case EBallCameraBehaviour::FreezeLookPosition: - case EBallCameraBehaviour::HintBallToCam: - case EBallCameraBehaviour::HintInitializePosition: - case EBallCameraBehaviour::PathCameraDesiredPos: - case EBallCameraBehaviour::PathCamera: - if (mgr.GetCameraManager()->IsInterpolationCameraActive()) - { - x1d8_lookPos = x1c0_lookPosAhead; - x1cc_fixedLookPos = x1c0_lookPosAhead; - } - break; - case EBallCameraBehaviour::HintFixedPosition: - x1d8_lookPos = x1cc_fixedLookPos; - x1c0_lookPosAhead = x1d8_lookPos; - break; - case EBallCameraBehaviour::HintFixedTransform: - case EBallCameraBehaviour::SpindleCamera: - x1d8_lookPos = x1cc_fixedLookPos; - x1c0_lookPosAhead = x1cc_fixedLookPos; - break; - } - if (x18d_30_directElevation) - { - x1d8_lookPos.z() = ballPos.z() + x1b4_lookAtOffset.z(); - x1c0_lookPosAhead.z() = float(x1d8_lookPos.z()); - x1cc_fixedLookPos.z() = float(x1d8_lookPos.z()); - } - if (x18d_31_overrideLookDir) - { - if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) - { - x1d8_lookPos = hint->GetTransform().basis[1] * 10.f + GetTranslation(); - x1c0_lookPosAhead = x1d8_lookPos; - x1cc_fixedLookPos = x1d8_lookPos; - } - } - } + case EBallCameraBehaviour::HintFixedTransform: { + ResetPosition(mgr); + TeleportCamera(hint->GetTransform(), mgr); + break; } -} - -zeus::CTransform CBallCamera::UpdateLookDirection(const zeus::CVector3f& dir, CStateManager& mgr) -{ - zeus::CVector3f useDir = dir; - if (!dir.canBeNormalized()) - useDir = zeus::CVector3f::skForward; - float elevation = x1a0_elevation; - float distance = x190_curMinDistance; - ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); - zeus::CVector3f pos = FindDesiredPosition(distance, elevation, useDir, mgr, false); - UpdateLookAtPosition(0.f, mgr); - return zeus::lookAt(pos, x1d8_lookPos); -} - -void CBallCamera::ApplyCameraHint(CStateManager& mgr) -{ - if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) - { - ResetToTweaks(mgr); - x188_behaviour = hint->GetHint().GetBehaviourType(); - x18c_25_chaseAllowed = (hint->GetHint().GetOverrideFlags() & 0x2) != 0; - x18c_26_boostAllowed = (hint->GetHint().GetOverrideFlags() & 0x4) != 0; - x18c_27_obscureAvoidance = (hint->GetHint().GetOverrideFlags() & 0x8) != 0; - x18c_28_volumeCollider = (hint->GetHint().GetOverrideFlags() & 0x10) != 0; - if ((hint->GetHint().GetOverrideFlags() & 0x40) != 0) - x18d_26_lookAtBall = true; - x18d_29_noElevationInterp = (hint->GetHint().GetOverrideFlags() & 0x4000) != 0; - x18d_30_directElevation = (hint->GetHint().GetOverrideFlags() & 0x8000) != 0; - x18d_31_overrideLookDir = (hint->GetHint().GetOverrideFlags() & 0x10000) != 0; - x18e_24_noElevationVelClamp = (hint->GetHint().GetOverrideFlags() & 0x20000) != 0; - x18e_25_noSpline = x18e_26_ = (hint->GetHint().GetOverrideFlags() & 0x80000) != 0; - if ((hint->GetHint().GetOverrideFlags() & 0x400000) != 0) - x194_targetMinDistance = hint->GetHint().GetMinDist(); - if ((hint->GetHint().GetOverrideFlags() & 0x800000) != 0) - x198_maxDistance = hint->GetHint().GetMaxDist(); - if ((hint->GetHint().GetOverrideFlags() & 0x1000000) != 0) - x19c_backwardsDistance = hint->GetHint().GetBackwardsDist(); - if ((hint->GetHint().GetOverrideFlags() & 0x80000000) != 0) - x1a0_elevation = hint->GetHint().GetElevation(); - if ((hint->GetHint().GetOverrideFlags() & 0x2000000) != 0) - x1b4_lookAtOffset = hint->GetHint().GetLookAtOffset(); - if ((hint->GetHint().GetOverrideFlags() & 0x4000000) != 0) - x410_chaseLookAtOffset = hint->GetHint().GetChaseLookAtOffset(); - if ((hint->GetHint().GetOverrideFlags() & 0x10000000) != 0) - { - x18c_29_clampAttitude = true; - x1ac_attitudeRange = hint->GetHint().GetAttitudeRange(); + case EBallCameraBehaviour::Default: { + if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0) { + ResetPosition(mgr); + if ((hint->GetHint().GetOverrideFlags() & 0x40000) != 0) { + zeus::CVector3f lookDir = + mgr.GetPlayer().GetTranslation() - mgr.GetCameraManager()->GetCurrentCameraTransform(mgr).origin; + lookDir.z() = 0.f; + if (lookDir.canBeNormalized()) + lookDir.normalize(); + else + lookDir = mgr.GetPlayer().GetMoveDir(); + TeleportCamera(UpdateLookDirection(lookDir, mgr), mgr); + } else { + TeleportCamera(zeus::lookAt(hint->GetTranslation(), x1d8_lookPos), mgr); } - else - { - x18c_29_clampAttitude = false; - } - if ((hint->GetHint().GetOverrideFlags() & 0x20000000) != 0) - { - x18c_30_clampAzimuth = true; - x1b0_azimuthRange = hint->GetHint().GetAzimuthRange(); - } - else - { - x18c_30_clampAzimuth = false; - } - if ((hint->GetHint().GetOverrideFlags() & 0x8000000) != 0) - SetFovInterpolation(x15c_currentFov, hint->GetHint().GetFov(), 1.f, 0.f); - if ((hint->GetHint().GetOverrideFlags() & 0x40000000) != 0) - x1a8_targetAnglePerSecond = hint->GetHint().GetAnglePerSecond(); - if ((hint->GetHint().GetOverrideFlags() & 0x200) != 0) - mgr.GetPlayer().SetControlDirectionInterpolation(hint->GetHint().GetControlInterpDur()); - else - mgr.GetPlayer().ResetControlDirectionInterpolation(); - switch (hint->GetHint().GetBehaviourType()) - { - case EBallCameraBehaviour::HintBallToCam: - { - x45c_overrideBallToCam = hint->GetHint().GetBallToCam(); - ResetPosition(mgr); - zeus::CVector3f camPos = mgr.GetPlayer().GetBallPosition() + hint->GetHint().GetBallToCam(); - if ((hint->GetHint().GetOverrideFlags() & 0x1) != 0) - { - float distance = hint->GetHint().GetBallToCam().toVec2f().magnitude(); - zeus::CVector3f camToBall = -zeus::CVector3f(hint->GetHint().GetBallToCam().toVec2f()).normalized(); - camPos = FindDesiredPosition(distance, hint->GetHint().GetBallToCam().z(), camToBall, mgr, false); - } - TeleportCamera(zeus::lookAt(camPos, x1d8_lookPos), mgr); - break; - } - case EBallCameraBehaviour::HintFixedTransform: - { - ResetPosition(mgr); - TeleportCamera(hint->GetTransform(), mgr); - break; - } - case EBallCameraBehaviour::Default: - { - if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0) - { - ResetPosition(mgr); - if ((hint->GetHint().GetOverrideFlags() & 0x40000) != 0) - { - zeus::CVector3f lookDir = mgr.GetPlayer().GetTranslation() - - mgr.GetCameraManager()->GetCurrentCameraTransform(mgr).origin; - lookDir.z() = 0.f; - if (lookDir.canBeNormalized()) - lookDir.normalize(); - else - lookDir = mgr.GetPlayer().GetMoveDir(); - TeleportCamera(UpdateLookDirection(lookDir, mgr), mgr); - } - else - { - TeleportCamera(zeus::lookAt(hint->GetTranslation(), x1d8_lookPos), mgr); - } - } - break; - } - case EBallCameraBehaviour::HintFixedPosition: - { - ResetPosition(mgr); - TeleportCamera(zeus::lookAt(hint->GetTranslation(), x1d8_lookPos), mgr); - break; - } - case EBallCameraBehaviour::FreezeLookPosition: - case EBallCameraBehaviour::HintInitializePosition: - { - if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0) - { - ResetPosition(mgr); - float elevation = x1a0_elevation; - float distance = x190_curMinDistance; - ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); - TeleportCamera(zeus::lookAt( - FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, false), - x1cc_fixedLookPos), mgr); - } - break; - } - default: - break; - } - - if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0) - mgr.GetCameraManager()->SetPlayerCamera(mgr, GetUniqueId()); + } + break; } + case EBallCameraBehaviour::HintFixedPosition: { + ResetPosition(mgr); + TeleportCamera(zeus::lookAt(hint->GetTranslation(), x1d8_lookPos), mgr); + break; + } + case EBallCameraBehaviour::FreezeLookPosition: + case EBallCameraBehaviour::HintInitializePosition: { + if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0) { + ResetPosition(mgr); + float elevation = x1a0_elevation; + float distance = x190_curMinDistance; + ConstrainElevationAndDistance(elevation, distance, 0.f, mgr); + TeleportCamera(zeus::lookAt(FindDesiredPosition(distance, elevation, mgr.GetPlayer().GetMoveDir(), mgr, false), + x1cc_fixedLookPos), + mgr); + } + break; + } + default: + break; + } + + if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0) + mgr.GetCameraManager()->SetPlayerCamera(mgr, GetUniqueId()); + } } -void CBallCamera::ResetPosition(CStateManager& mgr) -{ - x1d8_lookPos = mgr.GetPlayer().GetBallPosition(); - x1d8_lookPos.z() += x1b4_lookAtOffset.z(); - x1c0_lookPosAhead = x1d8_lookPos; - x1cc_fixedLookPos = x1d8_lookPos; +void CBallCamera::ResetPosition(CStateManager& mgr) { + x1d8_lookPos = mgr.GetPlayer().GetBallPosition(); + x1d8_lookPos.z() += x1b4_lookAtOffset.z(); + x1c0_lookPosAhead = x1d8_lookPos; + x1cc_fixedLookPos = x1d8_lookPos; } -void CBallCamera::DoorClosed(TUniqueId doorId) -{ - if (doorId != x3dc_tooCloseActorId) - return; - x18e_27_nearbyDoorClosed = true; +void CBallCamera::DoorClosed(TUniqueId doorId) { + if (doorId != x3dc_tooCloseActorId) + return; + x18e_27_nearbyDoorClosed = true; } -void CBallCamera::DoorClosing(TUniqueId doorId) -{ - if (doorId != x3dc_tooCloseActorId) - return; - x18e_28_nearbyDoorClosing = true; +void CBallCamera::DoorClosing(TUniqueId doorId) { + if (doorId != x3dc_tooCloseActorId) + return; + x18e_28_nearbyDoorClosing = true; } -} +} // namespace urde diff --git a/Runtime/Camera/CBallCamera.hpp b/Runtime/Camera/CBallCamera.hpp index 2046f8724..40e6553da 100644 --- a/Runtime/Camera/CBallCamera.hpp +++ b/Runtime/Camera/CBallCamera.hpp @@ -3,278 +3,265 @@ #include "CGameCamera.hpp" #include "CCameraSpline.hpp" -namespace urde -{ +namespace urde { class CPlayer; -class CCameraSpring -{ - float x0_k; - float x4_k2Sqrt; - float x8_max; - float xc_tardis; - float x10_dx = 0.f; +class CCameraSpring { + float x0_k; + float x4_k2Sqrt; + float x8_max; + float xc_tardis; + float x10_dx = 0.f; + public: - CCameraSpring(float k, float max, float tardis) - : x0_k(k), x4_k2Sqrt(2.f * std::sqrt(k)), x8_max(max), xc_tardis(tardis) {} - void Reset(); - float ApplyDistanceSpringNoMax(float targetX, float curX, float dt); - float ApplyDistanceSpring(float targetX, float curX, float dt); + CCameraSpring(float k, float max, float tardis) + : x0_k(k), x4_k2Sqrt(2.f * std::sqrt(k)), x8_max(max), xc_tardis(tardis) {} + void Reset(); + float ApplyDistanceSpringNoMax(float targetX, float curX, float dt); + float ApplyDistanceSpring(float targetX, float curX, float dt); }; -class CCameraCollider -{ - friend class CBallCamera; - float x4_radius; - zeus::CVector3f x8_lastLocalPos; - zeus::CVector3f x14_localPos; - zeus::CVector3f x20_scaledWorldPos; - zeus::CVector3f x2c_lastWorldPos; - CCameraSpring x38_spring; - u32 x4c_occlusionCount = 0; - float x50_scale; +class CCameraCollider { + friend class CBallCamera; + float x4_radius; + zeus::CVector3f x8_lastLocalPos; + zeus::CVector3f x14_localPos; + zeus::CVector3f x20_scaledWorldPos; + zeus::CVector3f x2c_lastWorldPos; + CCameraSpring x38_spring; + u32 x4c_occlusionCount = 0; + float x50_scale; + public: - CCameraCollider(float radius, const zeus::CVector3f& vec, const CCameraSpring& spring, float scale) - : x4_radius(radius), x8_lastLocalPos(vec), x14_localPos(vec), x20_scaledWorldPos(vec), - x2c_lastWorldPos(vec), x38_spring(spring), x50_scale(scale) {} + CCameraCollider(float radius, const zeus::CVector3f& vec, const CCameraSpring& spring, float scale) + : x4_radius(radius) + , x8_lastLocalPos(vec) + , x14_localPos(vec) + , x20_scaledWorldPos(vec) + , x2c_lastWorldPos(vec) + , x38_spring(spring) + , x50_scale(scale) {} }; -class CBallCamera : public CGameCamera -{ +class CBallCamera : public CGameCamera { public: - enum class EBallCameraState - { - Default, - One, - Chase, - Boost, - ToBall, - FromBall - }; - enum class EBallCameraBehaviour - { - Default, - FreezeLookPosition, // Unused - HintBallToCam, - HintInitializePosition, - HintFixedPosition, - HintFixedTransform, - PathCameraDesiredPos, // Unused - PathCamera, - SpindleCamera - }; - enum class ESplineState - { - Invalid, - Nav, - Arc - }; + enum class EBallCameraState { Default, One, Chase, Boost, ToBall, FromBall }; + enum class EBallCameraBehaviour { + Default, + FreezeLookPosition, // Unused + HintBallToCam, + HintInitializePosition, + HintFixedPosition, + HintFixedTransform, + PathCameraDesiredPos, // Unused + PathCamera, + SpindleCamera + }; + enum class ESplineState { Invalid, Nav, Arc }; + private: - struct SFailsafeState - { - zeus::CTransform x0_playerXf; - zeus::CTransform x30_camXf; - zeus::CVector3f x60_lookPos; - zeus::CVector3f x6c_behindPos; - zeus::CVector3f x78_; - zeus::CVector3f x84_playerPos; - std::vector x90_splinePoints; - }; + struct SFailsafeState { + zeus::CTransform x0_playerXf; + zeus::CTransform x30_camXf; + zeus::CVector3f x60_lookPos; + zeus::CVector3f x6c_behindPos; + zeus::CVector3f x78_; + zeus::CVector3f x84_playerPos; + std::vector x90_splinePoints; + }; - EBallCameraBehaviour x188_behaviour = EBallCameraBehaviour::Default; - bool x18c_24_ : 1; - bool x18c_25_chaseAllowed : 1; - bool x18c_26_boostAllowed : 1; - bool x18c_27_obscureAvoidance : 1; - bool x18c_28_volumeCollider : 1; - bool x18c_29_clampAttitude : 1; - bool x18c_30_clampAzimuth : 1; - bool x18c_31_clearLOS : 1; - bool x18d_24_prevClearLOS : 1; - bool x18d_25_avoidGeometryFull : 1; - bool x18d_26_lookAtBall : 1; - bool x18d_27_forceProcessing : 1; - bool x18d_28_obtuseDirection : 1; - bool x18d_29_noElevationInterp : 1; - bool x18d_30_directElevation : 1; - bool x18d_31_overrideLookDir : 1; - bool x18e_24_noElevationVelClamp : 1; - bool x18e_25_noSpline : 1; - bool x18e_26_ : 1; - bool x18e_27_nearbyDoorClosed : 1; - bool x18e_28_nearbyDoorClosing : 1; - float x190_curMinDistance; - float x194_targetMinDistance; - float x198_maxDistance; - float x19c_backwardsDistance; - float x1a0_elevation; - float x1a4_curAnglePerSecond; - float x1a8_targetAnglePerSecond; - float x1ac_attitudeRange = zeus::degToRad(89.f); - float x1b0_azimuthRange = zeus::degToRad(89.f); - zeus::CVector3f x1b4_lookAtOffset; - zeus::CVector3f x1c0_lookPosAhead; - zeus::CVector3f x1cc_fixedLookPos; - zeus::CVector3f x1d8_lookPos; - zeus::CTransform x1e4_nextLookXf; - CCameraSpring x214_ballCameraSpring; - CCameraSpring x228_ballCameraCentroidSpring; - CCameraSpring x23c_ballCameraLookAtSpring; - CCameraSpring x250_ballCameraCentroidDistanceSpring; - std::vector x264_smallColliders; - std::vector x274_mediumColliders; - std::vector x284_largeColliders; - zeus::CVector3f x294_dampedPos; - zeus::CVector3f x2a0_smallCentroid = zeus::CVector3f::skUp; - zeus::CVector3f x2ac_mediumCentroid = zeus::CVector3f::skUp; - zeus::CVector3f x2b8_largeCentroid = zeus::CVector3f::skUp; - int x2c4_smallCollidersObsCount = 0; - int x2c8_mediumCollidersObsCount = 0; - int x2cc_largeCollidersObsCount = 0; - int x2d0_smallColliderIt = 0; - int x2d4_mediumColliderIt = 0; - int x2d8_largeColliderIt = 0; - zeus::CVector3f x2dc_prevBallPos; - float x2e8_ballVelFlat = 0.f; - float x2ec_maxBallVel = 0.f; - zeus::CVector3f x2f0_ballDelta; - zeus::CVector3f x2fc_ballDeltaFlat; - float x308_speedFactor = 0.f; - float x30c_speedingTime = 0.f; - zeus::CVector3f x310_idealLookVec; - zeus::CVector3f x31c_predictedLookPos; - u32 x328_avoidGeomCycle = 0; - float x32c_colliderMag = 1.f; - float x330_clearColliderThreshold = 0.2f; - zeus::CAABox x334_collidersAABB = zeus::CAABox::skNullBox; - float x34c_obscuredTime = 0.f; - CMaterialList x350_obscuringMaterial = {EMaterialTypes::NoStepLogic}; - float x358_unobscureMag = 0.f; - zeus::CVector3f x35c_splineIntermediatePos; - TUniqueId x368_obscuringObjectId = kInvalidUniqueId; - ESplineState x36c_splineState = ESplineState::Invalid; - bool x370_24_reevalSplineEnd : 1; - float x374_splineCtrl = 0.f; - float x378_splineCtrlRange; - CCameraSpline x37c_camSpline; - CMaterialList x3c8_collisionExcludeList = {EMaterialTypes::NoStepLogic}; - bool x3d0_24_camBehindFloorOrWall : 1; - float x3d4_elevInterpTimer = 0.f; - float x3d8_elevInterpStart = 0.f; - TUniqueId x3dc_tooCloseActorId = kInvalidUniqueId; - float x3e0_tooCloseActorDist = 10000.f; - bool x3e4_pendingFailsafe = false; - float x3e8_ = 0.f; - float x3ec_ = 0.f; - float x3f0_ = 0.f; - float x3f4_ = 2.f; - float x3f8_ = 0.f; - float x3fc_ = 0.f; - EBallCameraState x400_state = EBallCameraState::Default; - float x404_chaseElevation; - float x408_chaseDistance; - float x40c_chaseAnglePerSecond; - zeus::CVector3f x410_chaseLookAtOffset; - CCameraSpring x41c_ballCameraChaseSpring; - float x430_boostElevation; - float x434_boostDistance; - float x438_boostAnglePerSecond; - zeus::CVector3f x43c_boostLookAtOffset; - CCameraSpring x448_ballCameraBoostSpring; - zeus::CVector3f x45c_overrideBallToCam; - float x468_conservativeDoorCamDistance; - TUniqueId x46c_collisionActorId = kInvalidUniqueId; - float x470_clampVelTimer = 0.f; - float x474_clampVelRange = 0.f; - u32 x478_shortMoveCount = 0; - std::unique_ptr x47c_failsafeState; - std::unique_ptr x480_; + EBallCameraBehaviour x188_behaviour = EBallCameraBehaviour::Default; + bool x18c_24_ : 1; + bool x18c_25_chaseAllowed : 1; + bool x18c_26_boostAllowed : 1; + bool x18c_27_obscureAvoidance : 1; + bool x18c_28_volumeCollider : 1; + bool x18c_29_clampAttitude : 1; + bool x18c_30_clampAzimuth : 1; + bool x18c_31_clearLOS : 1; + bool x18d_24_prevClearLOS : 1; + bool x18d_25_avoidGeometryFull : 1; + bool x18d_26_lookAtBall : 1; + bool x18d_27_forceProcessing : 1; + bool x18d_28_obtuseDirection : 1; + bool x18d_29_noElevationInterp : 1; + bool x18d_30_directElevation : 1; + bool x18d_31_overrideLookDir : 1; + bool x18e_24_noElevationVelClamp : 1; + bool x18e_25_noSpline : 1; + bool x18e_26_ : 1; + bool x18e_27_nearbyDoorClosed : 1; + bool x18e_28_nearbyDoorClosing : 1; + float x190_curMinDistance; + float x194_targetMinDistance; + float x198_maxDistance; + float x19c_backwardsDistance; + float x1a0_elevation; + float x1a4_curAnglePerSecond; + float x1a8_targetAnglePerSecond; + float x1ac_attitudeRange = zeus::degToRad(89.f); + float x1b0_azimuthRange = zeus::degToRad(89.f); + zeus::CVector3f x1b4_lookAtOffset; + zeus::CVector3f x1c0_lookPosAhead; + zeus::CVector3f x1cc_fixedLookPos; + zeus::CVector3f x1d8_lookPos; + zeus::CTransform x1e4_nextLookXf; + CCameraSpring x214_ballCameraSpring; + CCameraSpring x228_ballCameraCentroidSpring; + CCameraSpring x23c_ballCameraLookAtSpring; + CCameraSpring x250_ballCameraCentroidDistanceSpring; + std::vector x264_smallColliders; + std::vector x274_mediumColliders; + std::vector x284_largeColliders; + zeus::CVector3f x294_dampedPos; + zeus::CVector3f x2a0_smallCentroid = zeus::CVector3f::skUp; + zeus::CVector3f x2ac_mediumCentroid = zeus::CVector3f::skUp; + zeus::CVector3f x2b8_largeCentroid = zeus::CVector3f::skUp; + int x2c4_smallCollidersObsCount = 0; + int x2c8_mediumCollidersObsCount = 0; + int x2cc_largeCollidersObsCount = 0; + int x2d0_smallColliderIt = 0; + int x2d4_mediumColliderIt = 0; + int x2d8_largeColliderIt = 0; + zeus::CVector3f x2dc_prevBallPos; + float x2e8_ballVelFlat = 0.f; + float x2ec_maxBallVel = 0.f; + zeus::CVector3f x2f0_ballDelta; + zeus::CVector3f x2fc_ballDeltaFlat; + float x308_speedFactor = 0.f; + float x30c_speedingTime = 0.f; + zeus::CVector3f x310_idealLookVec; + zeus::CVector3f x31c_predictedLookPos; + u32 x328_avoidGeomCycle = 0; + float x32c_colliderMag = 1.f; + float x330_clearColliderThreshold = 0.2f; + zeus::CAABox x334_collidersAABB = zeus::CAABox::skNullBox; + float x34c_obscuredTime = 0.f; + CMaterialList x350_obscuringMaterial = {EMaterialTypes::NoStepLogic}; + float x358_unobscureMag = 0.f; + zeus::CVector3f x35c_splineIntermediatePos; + TUniqueId x368_obscuringObjectId = kInvalidUniqueId; + ESplineState x36c_splineState = ESplineState::Invalid; + bool x370_24_reevalSplineEnd : 1; + float x374_splineCtrl = 0.f; + float x378_splineCtrlRange; + CCameraSpline x37c_camSpline; + CMaterialList x3c8_collisionExcludeList = {EMaterialTypes::NoStepLogic}; + bool x3d0_24_camBehindFloorOrWall : 1; + float x3d4_elevInterpTimer = 0.f; + float x3d8_elevInterpStart = 0.f; + TUniqueId x3dc_tooCloseActorId = kInvalidUniqueId; + float x3e0_tooCloseActorDist = 10000.f; + bool x3e4_pendingFailsafe = false; + float x3e8_ = 0.f; + float x3ec_ = 0.f; + float x3f0_ = 0.f; + float x3f4_ = 2.f; + float x3f8_ = 0.f; + float x3fc_ = 0.f; + EBallCameraState x400_state = EBallCameraState::Default; + float x404_chaseElevation; + float x408_chaseDistance; + float x40c_chaseAnglePerSecond; + zeus::CVector3f x410_chaseLookAtOffset; + CCameraSpring x41c_ballCameraChaseSpring; + float x430_boostElevation; + float x434_boostDistance; + float x438_boostAnglePerSecond; + zeus::CVector3f x43c_boostLookAtOffset; + CCameraSpring x448_ballCameraBoostSpring; + zeus::CVector3f x45c_overrideBallToCam; + float x468_conservativeDoorCamDistance; + TUniqueId x46c_collisionActorId = kInvalidUniqueId; + float x470_clampVelTimer = 0.f; + float x474_clampVelRange = 0.f; + u32 x478_shortMoveCount = 0; + std::unique_ptr x47c_failsafeState; + std::unique_ptr x480_; - void SetupColliders(std::vector& out, float xMag, float zMag, float radius, int count, - float k, float max, float startAngle); - void BuildSplineNav(CStateManager& mgr); - void BuildSplineArc(CStateManager& mgr); - bool ShouldResetSpline(CStateManager& mgr) const; - void UpdatePlayerMovement(float dt, CStateManager& mgr); - void UpdateTransform(const zeus::CVector3f& lookDir, const zeus::CVector3f& pos, float dt, CStateManager& mgr); - zeus::CVector3f ConstrainYawAngle(const CPlayer& player, float distance, float yawSpeed, float dt, - CStateManager& mgr) const; - void CheckFailsafe(float dt, CStateManager& mgr); - void UpdateObjectTooCloseId(CStateManager& mgr); - void UpdateAnglePerSecond(float dt); - void UpdateUsingPathCameras(float dt, CStateManager& mgr); - zeus::CVector3f GetFixedLookTarget(const zeus::CVector3f& hintToLookDir, CStateManager& mgr) const; - void UpdateUsingFixedCameras(float dt, CStateManager& mgr); - zeus::CVector3f ComputeVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& posDelta) const; - zeus::CVector3f TweenVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& newVel, float rate, float dt); - zeus::CVector3f MoveCollisionActor(const zeus::CVector3f& pos, float dt, CStateManager& mgr); - void UpdateUsingFreeLook(float dt, CStateManager& mgr); - zeus::CVector3f InterpolateCameraElevation(const zeus::CVector3f& camPos, float dt); - zeus::CVector3f CalculateCollidersCentroid(const std::vector& colliderList, int numObscured) const; - zeus::CVector3f ApplyColliders(); - void UpdateColliders(const zeus::CTransform& xf, std::vector& colliderList, int& it, int count, - float tolerance, const rstl::reserved_vector& nearList, float dt, - CStateManager& mgr); - zeus::CVector3f AvoidGeometry(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr); - zeus::CVector3f AvoidGeometryFull(const zeus::CTransform& xf, - const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr); - zeus::CAABox CalculateCollidersBoundingBox(const std::vector& colliderList, - CStateManager& mgr) const; - int CountObscuredColliders(const std::vector& colliderList) const; - void UpdateCollidersDistances(std::vector& colliderList, float xMag, float zMag, float angOffset); - void UpdateUsingColliders(float dt, CStateManager& mgr); - void UpdateUsingSpindleCameras(float dt, CStateManager& mgr); - zeus::CVector3f ClampElevationToWater(zeus::CVector3f& pos, CStateManager& mgr) const; - void UpdateTransitionFromBallCamera(CStateManager& mgr); - void UpdateUsingTransitions(float dt, CStateManager& mgr); - zeus::CTransform UpdateCameraPositions(float dt, const zeus::CTransform& oldXf, const zeus::CTransform& newXf); - static zeus::CVector3f GetFailsafeSplinePoint(const std::vector& points, float t); - bool CheckFailsafeFromMorphBallState(CStateManager& mgr) const; - bool SplineIntersectTest(CMaterialList& intersectMat, CStateManager& mgr) const; - void ActivateFailsafe(float dt, CStateManager& mgr); - bool ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr); - zeus::CVector3f FindDesiredPosition(float distance, float elevation, const zeus::CVector3f& dir, - CStateManager& mgr, bool fullTest); - static bool DetectCollision(const zeus::CVector3f& from, const zeus::CVector3f& to, float radius, - float& d, CStateManager& mgr); - void TeleportColliders(std::vector& colliderList, const zeus::CVector3f& pos); - static bool CheckTransitionLineOfSight(const zeus::CVector3f& eyePos, const zeus::CVector3f& behindPos, - float& eyeToOccDist, float colRadius, CStateManager& mgr); + void SetupColliders(std::vector& out, float xMag, float zMag, float radius, int count, float k, + float max, float startAngle); + void BuildSplineNav(CStateManager& mgr); + void BuildSplineArc(CStateManager& mgr); + bool ShouldResetSpline(CStateManager& mgr) const; + void UpdatePlayerMovement(float dt, CStateManager& mgr); + void UpdateTransform(const zeus::CVector3f& lookDir, const zeus::CVector3f& pos, float dt, CStateManager& mgr); + zeus::CVector3f ConstrainYawAngle(const CPlayer& player, float distance, float yawSpeed, float dt, + CStateManager& mgr) const; + void CheckFailsafe(float dt, CStateManager& mgr); + void UpdateObjectTooCloseId(CStateManager& mgr); + void UpdateAnglePerSecond(float dt); + void UpdateUsingPathCameras(float dt, CStateManager& mgr); + zeus::CVector3f GetFixedLookTarget(const zeus::CVector3f& hintToLookDir, CStateManager& mgr) const; + void UpdateUsingFixedCameras(float dt, CStateManager& mgr); + zeus::CVector3f ComputeVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& posDelta) const; + zeus::CVector3f TweenVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& newVel, float rate, float dt); + zeus::CVector3f MoveCollisionActor(const zeus::CVector3f& pos, float dt, CStateManager& mgr); + void UpdateUsingFreeLook(float dt, CStateManager& mgr); + zeus::CVector3f InterpolateCameraElevation(const zeus::CVector3f& camPos, float dt); + zeus::CVector3f CalculateCollidersCentroid(const std::vector& colliderList, int numObscured) const; + zeus::CVector3f ApplyColliders(); + void UpdateColliders(const zeus::CTransform& xf, std::vector& colliderList, int& it, int count, + float tolerance, const rstl::reserved_vector& nearList, float dt, + CStateManager& mgr); + zeus::CVector3f AvoidGeometry(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr); + zeus::CVector3f AvoidGeometryFull(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr); + zeus::CAABox CalculateCollidersBoundingBox(const std::vector& colliderList, + CStateManager& mgr) const; + int CountObscuredColliders(const std::vector& colliderList) const; + void UpdateCollidersDistances(std::vector& colliderList, float xMag, float zMag, float angOffset); + void UpdateUsingColliders(float dt, CStateManager& mgr); + void UpdateUsingSpindleCameras(float dt, CStateManager& mgr); + zeus::CVector3f ClampElevationToWater(zeus::CVector3f& pos, CStateManager& mgr) const; + void UpdateTransitionFromBallCamera(CStateManager& mgr); + void UpdateUsingTransitions(float dt, CStateManager& mgr); + zeus::CTransform UpdateCameraPositions(float dt, const zeus::CTransform& oldXf, const zeus::CTransform& newXf); + static zeus::CVector3f GetFailsafeSplinePoint(const std::vector& points, float t); + bool CheckFailsafeFromMorphBallState(CStateManager& mgr) const; + bool SplineIntersectTest(CMaterialList& intersectMat, CStateManager& mgr) const; + void ActivateFailsafe(float dt, CStateManager& mgr); + bool ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr); + zeus::CVector3f FindDesiredPosition(float distance, float elevation, const zeus::CVector3f& dir, CStateManager& mgr, + bool fullTest); + static bool DetectCollision(const zeus::CVector3f& from, const zeus::CVector3f& to, float radius, float& d, + CStateManager& mgr); + void TeleportColliders(std::vector& colliderList, const zeus::CVector3f& pos); + static bool CheckTransitionLineOfSight(const zeus::CVector3f& eyePos, const zeus::CVector3f& behindPos, + float& eyeToOccDist, float colRadius, CStateManager& mgr); public: - CBallCamera(TUniqueId uid, TUniqueId watchedId, const zeus::CTransform& xf, - float fovy, float znear, float zfar, float aspect); + CBallCamera(TUniqueId uid, TUniqueId watchedId, const zeus::CTransform& xf, float fovy, float znear, float zfar, + float aspect); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); - void ProcessInput(const CFinalInput& input, CStateManager& mgr); - void Reset(const zeus::CTransform&, CStateManager& mgr); - void Render(const CStateManager& mgr) const; - EBallCameraBehaviour GetBehaviour() const { return x188_behaviour; } - EBallCameraState GetState() const { return x400_state; } - void SetState(EBallCameraState state, CStateManager& mgr); - void Think(float dt, CStateManager& mgr); - bool TransitionFromMorphBallState(CStateManager& mgr); - TUniqueId GetTooCloseActorId() const { return x3dc_tooCloseActorId; } - float GetTooCloseActorDistance() const { return x3e0_tooCloseActorDist; } - void TeleportCamera(const zeus::CVector3f& pos, CStateManager& mgr); - void TeleportCamera(const zeus::CTransform& xf, CStateManager& mgr); - const zeus::CVector3f& GetLookPos() const { return x1d8_lookPos; } - void ResetToTweaks(CStateManager& mgr); - void UpdateLookAtPosition(float dt, CStateManager& mgr); - zeus::CTransform UpdateLookDirection(const zeus::CVector3f& dir, CStateManager& mgr); - void SetClampVelTimer(float f) { x470_clampVelTimer = f; } - void SetClampVelRange(float f) { x474_clampVelRange = f; } - void ApplyCameraHint(CStateManager& mgr); - void ResetPosition(CStateManager& mgr); - void DoorClosed(TUniqueId doorId); - void DoorClosing(TUniqueId doorId); - const zeus::CVector3f& GetFixedLookPos() const { return x1cc_fixedLookPos; } + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void ProcessInput(const CFinalInput& input, CStateManager& mgr); + void Reset(const zeus::CTransform&, CStateManager& mgr); + void Render(const CStateManager& mgr) const; + EBallCameraBehaviour GetBehaviour() const { return x188_behaviour; } + EBallCameraState GetState() const { return x400_state; } + void SetState(EBallCameraState state, CStateManager& mgr); + void Think(float dt, CStateManager& mgr); + bool TransitionFromMorphBallState(CStateManager& mgr); + TUniqueId GetTooCloseActorId() const { return x3dc_tooCloseActorId; } + float GetTooCloseActorDistance() const { return x3e0_tooCloseActorDist; } + void TeleportCamera(const zeus::CVector3f& pos, CStateManager& mgr); + void TeleportCamera(const zeus::CTransform& xf, CStateManager& mgr); + const zeus::CVector3f& GetLookPos() const { return x1d8_lookPos; } + void ResetToTweaks(CStateManager& mgr); + void UpdateLookAtPosition(float dt, CStateManager& mgr); + zeus::CTransform UpdateLookDirection(const zeus::CVector3f& dir, CStateManager& mgr); + void SetClampVelTimer(float f) { x470_clampVelTimer = f; } + void SetClampVelRange(float f) { x474_clampVelRange = f; } + void ApplyCameraHint(CStateManager& mgr); + void ResetPosition(CStateManager& mgr); + void DoorClosed(TUniqueId doorId); + void DoorClosing(TUniqueId doorId); + const zeus::CVector3f& GetFixedLookPos() const { return x1cc_fixedLookPos; } - static bool IsBallNearDoor(const zeus::CVector3f& pos, CStateManager& mgr); + static bool IsBallNearDoor(const zeus::CVector3f& pos, CStateManager& mgr); }; -} - +} // namespace urde diff --git a/Runtime/Camera/CCameraFilter.cpp b/Runtime/Camera/CCameraFilter.cpp index 5e267da64..3b21c8a88 100644 --- a/Runtime/Camera/CCameraFilter.cpp +++ b/Runtime/Camera/CCameraFilter.cpp @@ -8,251 +8,214 @@ #include "Graphics/Shaders/CScanLinesFilter.hpp" #include "Graphics/Shaders/CRandomStaticFilter.hpp" -namespace urde -{ +namespace urde { template -void CCameraFilterPass::Update(float dt) -{ - if (x10_remTime <= 0.f) - return; +void CCameraFilterPass::Update(float dt) { + if (x10_remTime <= 0.f) + return; + EFilterType origType = x0_curType; + + x10_remTime = std::max(0.f, x10_remTime - dt); + x18_curColor = zeus::CColor::lerp(x1c_nextColor, x14_prevColor, x10_remTime / xc_duration); + + if (x10_remTime == 0.f) { + x0_curType = x4_nextType; + if (x0_curType == EFilterType::Passthru) { + x24_texObj = TLockedToken(); + x20_nextTxtr = {}; + } + } + + if (x0_curType == EFilterType::Passthru) + m_shader = std::experimental::nullopt; + else if (x0_curType != origType) + m_shader.emplace(x0_curType, x24_texObj); +} + +template +void CCameraFilterPass::SetFilter(EFilterType type, EFilterShape shape, float time, const zeus::CColor& color, + CAssetId txtr) { + if (time == 0.f) { + xc_duration = 0.f; + x10_remTime = 0.f; + + if (txtr.IsValid()) + x24_texObj = g_SimplePool->GetObj({FOURCC('TXTR'), txtr}); + if (type == EFilterType::Passthru) + m_shader = std::experimental::nullopt; + else if (x0_curType != type || (x20_nextTxtr != txtr && txtr.IsValid())) + m_shader.emplace(type, x24_texObj); + + x4_nextType = type; + x0_curType = type; + x8_shape = shape; + x1c_nextColor = color; + x18_curColor = color; + x14_prevColor = color; + x20_nextTxtr = txtr; + } else { EFilterType origType = x0_curType; + CAssetId origTxtr = x20_nextTxtr; - x10_remTime = std::max(0.f, x10_remTime - dt); - x18_curColor = zeus::CColor::lerp(x1c_nextColor, x14_prevColor, x10_remTime / xc_duration); - - if (x10_remTime == 0.f) - { - x0_curType = x4_nextType; - if (x0_curType == EFilterType::Passthru) - { - x24_texObj = TLockedToken(); - x20_nextTxtr = {}; + x1c_nextColor = color; + x14_prevColor = x18_curColor; + x8_shape = shape; + x20_nextTxtr = txtr; + if (txtr.IsValid()) + x24_texObj = g_SimplePool->GetObj({FOURCC('TXTR'), txtr}); + x10_remTime = time; + xc_duration = time; + x0_curType = x4_nextType; + x4_nextType = type; + if (type == EFilterType::Passthru) { + if (x0_curType == EFilterType::Multiply) + x1c_nextColor = zeus::CColor::skWhite; + else if (x0_curType == EFilterType::Add || x0_curType == EFilterType::Blend) + x1c_nextColor.a() = 0.f; + } else { + if (x0_curType == EFilterType::Passthru) { + if (type == EFilterType::Multiply) { + x18_curColor = zeus::CColor::skWhite; + } else if (type == EFilterType::Add || type == EFilterType::Blend) { + x18_curColor = x1c_nextColor; + x18_curColor.a() = 0.f; + x14_prevColor = x18_curColor; } + } + x0_curType = x4_nextType; } if (x0_curType == EFilterType::Passthru) - m_shader = std::experimental::nullopt; - else if (x0_curType != origType) - m_shader.emplace(x0_curType, x24_texObj); + m_shader = std::experimental::nullopt; + else if (x0_curType != origType || (x20_nextTxtr != origTxtr && x20_nextTxtr.IsValid())) + m_shader.emplace(x0_curType, x24_texObj); + } } template -void CCameraFilterPass::SetFilter(EFilterType type, EFilterShape shape, - float time, const zeus::CColor& color, CAssetId txtr) -{ - if (time == 0.f) - { - xc_duration = 0.f; - x10_remTime = 0.f; - - if (txtr.IsValid()) - x24_texObj = g_SimplePool->GetObj({FOURCC('TXTR'), txtr}); - if (type == EFilterType::Passthru) - m_shader = std::experimental::nullopt; - else if (x0_curType != type || (x20_nextTxtr != txtr && txtr.IsValid())) - m_shader.emplace(type, x24_texObj); - - x4_nextType = type; - x0_curType = type; - x8_shape = shape; - x1c_nextColor = color; - x18_curColor = color; - x14_prevColor = color; - x20_nextTxtr = txtr; - } - else - { - EFilterType origType = x0_curType; - CAssetId origTxtr = x20_nextTxtr; - - x1c_nextColor = color; - x14_prevColor = x18_curColor; - x8_shape = shape; - x20_nextTxtr = txtr; - if (txtr.IsValid()) - x24_texObj = g_SimplePool->GetObj({FOURCC('TXTR'), txtr}); - x10_remTime = time; - xc_duration = time; - x0_curType = x4_nextType; - x4_nextType = type; - if (type == EFilterType::Passthru) - { - if (x0_curType == EFilterType::Multiply) - x1c_nextColor = zeus::CColor::skWhite; - else if (x0_curType == EFilterType::Add || x0_curType == EFilterType::Blend) - x1c_nextColor.a() = 0.f; - } - else - { - if (x0_curType == EFilterType::Passthru) - { - if (type == EFilterType::Multiply) - { - x18_curColor = zeus::CColor::skWhite; - } - else if (type == EFilterType::Add || type == EFilterType::Blend) - { - x18_curColor = x1c_nextColor; - x18_curColor.a() = 0.f; - x14_prevColor = x18_curColor; - } - } - x0_curType = x4_nextType; - } - - if (x0_curType == EFilterType::Passthru) - m_shader = std::experimental::nullopt; - else if (x0_curType != origType || (x20_nextTxtr != origTxtr && x20_nextTxtr.IsValid())) - m_shader.emplace(x0_curType, x24_texObj); - } +void CCameraFilterPass::DisableFilter(float time) { + SetFilter(EFilterType::Passthru, x8_shape, time, zeus::CColor::skWhite, -1); } template -void CCameraFilterPass::DisableFilter(float time) -{ - SetFilter(EFilterType::Passthru, x8_shape, time, zeus::CColor::skWhite, -1); +void CCameraFilterPass::Draw() const { + if (m_shader) + const_cast(*m_shader).DrawFilter(x8_shape, x18_curColor, GetT(x4_nextType == EFilterType::Passthru)); } -template -void CCameraFilterPass::Draw() const -{ - if (m_shader) - const_cast(*m_shader).DrawFilter(x8_shape, x18_curColor, - GetT(x4_nextType == EFilterType::Passthru)); +float CCameraFilterPassBase::GetT(bool invert) const { + float tmp; + if (xc_duration == 0.f) + tmp = 1.f; + else + tmp = 1.f - x10_remTime / xc_duration; + if (invert) + return 1.f - tmp; + return tmp; } -float CCameraFilterPassBase::GetT(bool invert) const -{ - float tmp; - if (xc_duration == 0.f) - tmp = 1.f; - else - tmp = 1.f - x10_remTime / xc_duration; - if (invert) - return 1.f - tmp; - return tmp; -} - -void CCameraFilterPassPoly::SetFilter(EFilterType type, EFilterShape shape, - float time, const zeus::CColor& color, CAssetId txtr) -{ - if (!m_filter || m_shape != shape) - { - m_shape = shape; - switch (shape) - { - case EFilterShape::Fullscreen: - case EFilterShape::FullscreenHalvesLeftRight: - case EFilterShape::FullscreenHalvesTopBottom: - case EFilterShape::FullscreenQuarters: - if (txtr.IsValid()) - m_filter = std::make_unique>(); - else - m_filter = std::make_unique>(); - break; - case EFilterShape::CinemaBars: - m_filter = std::make_unique>(); - break; - case EFilterShape::ScanLinesEven: - m_filter = std::make_unique>(); - break; - case EFilterShape::ScanLinesOdd: - m_filter = std::make_unique>(); - break; - case EFilterShape::RandomStatic: - m_filter = std::make_unique>(); - break; - case EFilterShape::CookieCutterDepthRandomStatic: - m_filter = std::make_unique>(); - break; - default: break; - } +void CCameraFilterPassPoly::SetFilter(EFilterType type, EFilterShape shape, float time, const zeus::CColor& color, + CAssetId txtr) { + if (!m_filter || m_shape != shape) { + m_shape = shape; + switch (shape) { + case EFilterShape::Fullscreen: + case EFilterShape::FullscreenHalvesLeftRight: + case EFilterShape::FullscreenHalvesTopBottom: + case EFilterShape::FullscreenQuarters: + if (txtr.IsValid()) + m_filter = std::make_unique>(); + else + m_filter = std::make_unique>(); + break; + case EFilterShape::CinemaBars: + m_filter = std::make_unique>(); + break; + case EFilterShape::ScanLinesEven: + m_filter = std::make_unique>(); + break; + case EFilterShape::ScanLinesOdd: + m_filter = std::make_unique>(); + break; + case EFilterShape::RandomStatic: + m_filter = std::make_unique>(); + break; + case EFilterShape::CookieCutterDepthRandomStatic: + m_filter = std::make_unique>(); + break; + default: + break; } - if (m_filter) - m_filter->SetFilter(type, shape, time, color, txtr); + } + if (m_filter) + m_filter->SetFilter(type, shape, time, color, txtr); } -void CCameraBlurPass::Draw(bool clearDepth) -{ - if (x10_curType == EBlurType::NoBlur) - return; +void CCameraBlurPass::Draw(bool clearDepth) { + if (x10_curType == EBlurType::NoBlur) + return; - if (x10_curType == EBlurType::Xray) - { - if (!m_xrayShader) - m_xrayShader.emplace(x0_paletteTex); - m_xrayShader->draw(x1c_curValue); - } - else - { - if (!m_shader) - m_shader.emplace(); - m_shader->draw(x1c_curValue, clearDepth); - if (clearDepth) - CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR); - } + if (x10_curType == EBlurType::Xray) { + if (!m_xrayShader) + m_xrayShader.emplace(x0_paletteTex); + m_xrayShader->draw(x1c_curValue); + } else { + if (!m_shader) + m_shader.emplace(); + m_shader->draw(x1c_curValue, clearDepth); + if (clearDepth) + CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR); + } } -void CCameraBlurPass::Update(float dt) -{ - if (x28_remainingTime > 0.f) - { - x28_remainingTime = std::max(x28_remainingTime - dt, 0.f); - x1c_curValue = x18_endValue + (x20_startValue - x18_endValue) * x28_remainingTime / x24_totalTime; +void CCameraBlurPass::Update(float dt) { + if (x28_remainingTime > 0.f) { + x28_remainingTime = std::max(x28_remainingTime - dt, 0.f); + x1c_curValue = x18_endValue + (x20_startValue - x18_endValue) * x28_remainingTime / x24_totalTime; - if (x28_remainingTime != 0.f) - return; + if (x28_remainingTime != 0.f) + return; - x10_curType = x14_endType; - } + x10_curType = x14_endType; + } } -void CCameraBlurPass::SetBlur(EBlurType type, float amount, float duration) -{ - if (duration == 0.f) - { - x24_totalTime = 0.f; - x28_remainingTime = 0.f; - x18_endValue = amount; - x1c_curValue = amount; - x20_startValue = amount; +void CCameraBlurPass::SetBlur(EBlurType type, float amount, float duration) { + if (duration == 0.f) { + x24_totalTime = 0.f; + x28_remainingTime = 0.f; + x18_endValue = amount; + x1c_curValue = amount; + x20_startValue = amount; - if (x10_curType == EBlurType::NoBlur) - { - if (type == EBlurType::Xray) - x0_paletteTex = g_SimplePool->GetObj("TXTR_XRayPalette"); - } + if (x10_curType == EBlurType::NoBlur) { + if (type == EBlurType::Xray) + x0_paletteTex = g_SimplePool->GetObj("TXTR_XRayPalette"); + } - x14_endType = type; + x14_endType = type; + x10_curType = type; + // x2c_usePersistent = b1; + } else { + // x2c_usePersistent = b1; + x24_totalTime = duration; + x28_remainingTime = duration; + x18_endValue = x1c_curValue; + x20_startValue = amount; + + if (type != x14_endType) { + if (x10_curType == EBlurType::NoBlur) { + if (type == EBlurType::Xray) + x0_paletteTex = g_SimplePool->GetObj("TXTR_XRayPalette"); x10_curType = type; - //x2c_usePersistent = b1; - } - else - { - //x2c_usePersistent = b1; - x24_totalTime = duration; - x28_remainingTime = duration; - x18_endValue = x1c_curValue; - x20_startValue = amount; - - if (type != x14_endType) - { - if (x10_curType == EBlurType::NoBlur) - { - if (type == EBlurType::Xray) - x0_paletteTex = g_SimplePool->GetObj("TXTR_XRayPalette"); - x10_curType = type; - } - x14_endType = type; - } + } + x14_endType = type; } + } } -void CCameraBlurPass::DisableBlur(float duration) -{ - SetBlur(EBlurType::NoBlur, 0.f, duration); -} +void CCameraBlurPass::DisableBlur(float duration) { SetBlur(EBlurType::NoBlur, 0.f, duration); } -} +} // namespace urde diff --git a/Runtime/Camera/CCameraFilter.hpp b/Runtime/Camera/CCameraFilter.hpp index 265c921bb..f03ec53aa 100644 --- a/Runtime/Camera/CCameraFilter.hpp +++ b/Runtime/Camera/CCameraFilter.hpp @@ -6,116 +6,112 @@ #include "Graphics/Shaders/CCameraBlurFilter.hpp" #include "Graphics/Shaders/CXRayBlurFilter.hpp" -namespace urde -{ +namespace urde { class CTexture; -enum class EFilterType -{ - Passthru, - Multiply, - Invert, - Add, - Subtract, - Blend, - Widescreen, - SceneAdd, - NoColor, - InvDstMultiply +enum class EFilterType { + Passthru, + Multiply, + Invert, + Add, + Subtract, + Blend, + Widescreen, + SceneAdd, + NoColor, + InvDstMultiply }; -enum class EFilterShape -{ - Fullscreen, - FullscreenHalvesLeftRight, - FullscreenHalvesTopBottom, - FullscreenQuarters, - CinemaBars, - ScanLinesEven, - ScanLinesOdd, - RandomStatic, - CookieCutterDepthRandomStatic +enum class EFilterShape { + Fullscreen, + FullscreenHalvesLeftRight, + FullscreenHalvesTopBottom, + FullscreenQuarters, + CinemaBars, + ScanLinesEven, + ScanLinesOdd, + RandomStatic, + CookieCutterDepthRandomStatic }; -class CCameraFilterPassBase -{ +class CCameraFilterPassBase { protected: - EFilterType x0_curType = EFilterType::Passthru; - EFilterType x4_nextType = EFilterType::Passthru; - EFilterShape x8_shape = EFilterShape::Fullscreen; - float xc_duration = 0.f; - float x10_remTime = 0.f; - zeus::CColor x14_prevColor; - zeus::CColor x18_curColor; - zeus::CColor x1c_nextColor; - CAssetId x20_nextTxtr; - TLockedToken x24_texObj; // Used to be auto_ptr - float GetT(bool invert) const; + EFilterType x0_curType = EFilterType::Passthru; + EFilterType x4_nextType = EFilterType::Passthru; + EFilterShape x8_shape = EFilterShape::Fullscreen; + float xc_duration = 0.f; + float x10_remTime = 0.f; + zeus::CColor x14_prevColor; + zeus::CColor x18_curColor; + zeus::CColor x1c_nextColor; + CAssetId x20_nextTxtr; + TLockedToken x24_texObj; // Used to be auto_ptr + float GetT(bool invert) const; + public: - virtual ~CCameraFilterPassBase() = default; - virtual void Update(float dt)=0; - virtual void SetFilter(EFilterType type, EFilterShape shape, - float time, const zeus::CColor& color, CAssetId txtr)=0; - virtual void DisableFilter(float time)=0; - virtual void Draw() const=0; + virtual ~CCameraFilterPassBase() = default; + virtual void Update(float dt) = 0; + virtual void SetFilter(EFilterType type, EFilterShape shape, float time, const zeus::CColor& color, + CAssetId txtr) = 0; + virtual void DisableFilter(float time) = 0; + virtual void Draw() const = 0; }; template -class CCameraFilterPass final : public CCameraFilterPassBase -{ - std::experimental::optional m_shader; -public: - void Update(float dt); - void SetFilter(EFilterType type, EFilterShape shape, - float time, const zeus::CColor& color, CAssetId txtr); - void DisableFilter(float time); - void Draw() const; -}; - -class CCameraFilterPassPoly -{ - EFilterShape m_shape; - std::unique_ptr m_filter; -public: - void Update(float dt) { if (m_filter) m_filter->Update(dt); } - void SetFilter(EFilterType type, EFilterShape shape, - float time, const zeus::CColor& color, CAssetId txtr); - void DisableFilter(float time) { if (m_filter) m_filter->DisableFilter(time); } - void Draw() const { if (m_filter) m_filter->Draw(); } -}; - -enum class EBlurType -{ - NoBlur, - LoBlur, - HiBlur, - Xray -}; - -class CCameraBlurPass -{ - TLockedToken x0_paletteTex; - EBlurType x10_curType = EBlurType::NoBlur; - EBlurType x14_endType = EBlurType::NoBlur; - float x18_endValue = 0.f; - float x1c_curValue = 0.f; - float x20_startValue = 0.f; - float x24_totalTime = 0.f; - float x28_remainingTime = 0.f; - //bool x2c_usePersistent = false; - //bool x2d_noPersistentCopy = false; - //u32 x30_persistentBuf = 0; - - mutable std::experimental::optional m_shader; - mutable std::experimental::optional m_xrayShader; +class CCameraFilterPass final : public CCameraFilterPassBase { + std::experimental::optional m_shader; public: - void Draw(bool clearDepth=false); - void Update(float dt); - void SetBlur(EBlurType type, float amount, float duration); - void DisableBlur(float duration); - EBlurType GetCurrType() const { return x10_curType; } + void Update(float dt); + void SetFilter(EFilterType type, EFilterShape shape, float time, const zeus::CColor& color, CAssetId txtr); + void DisableFilter(float time); + void Draw() const; }; -} +class CCameraFilterPassPoly { + EFilterShape m_shape; + std::unique_ptr m_filter; +public: + void Update(float dt) { + if (m_filter) + m_filter->Update(dt); + } + void SetFilter(EFilterType type, EFilterShape shape, float time, const zeus::CColor& color, CAssetId txtr); + void DisableFilter(float time) { + if (m_filter) + m_filter->DisableFilter(time); + } + void Draw() const { + if (m_filter) + m_filter->Draw(); + } +}; + +enum class EBlurType { NoBlur, LoBlur, HiBlur, Xray }; + +class CCameraBlurPass { + TLockedToken x0_paletteTex; + EBlurType x10_curType = EBlurType::NoBlur; + EBlurType x14_endType = EBlurType::NoBlur; + float x18_endValue = 0.f; + float x1c_curValue = 0.f; + float x20_startValue = 0.f; + float x24_totalTime = 0.f; + float x28_remainingTime = 0.f; + // bool x2c_usePersistent = false; + // bool x2d_noPersistentCopy = false; + // u32 x30_persistentBuf = 0; + + mutable std::experimental::optional m_shader; + mutable std::experimental::optional m_xrayShader; + +public: + void Draw(bool clearDepth = false); + void Update(float dt); + void SetBlur(EBlurType type, float amount, float duration); + void DisableBlur(float duration); + EBlurType GetCurrType() const { return x10_curType; } +}; + +} // namespace urde diff --git a/Runtime/Camera/CCameraManager.cpp b/Runtime/Camera/CCameraManager.cpp index 50a46dd26..880434d4d 100644 --- a/Runtime/Camera/CCameraManager.cpp +++ b/Runtime/Camera/CCameraManager.cpp @@ -14,826 +14,674 @@ #include "World/CScriptSpindleCamera.hpp" #include "World/CExplosion.hpp" -namespace urde -{ +namespace urde { float CCameraManager::sAspect = 1.42f; float CCameraManager::sFarPlane = 750.f; float CCameraManager::sNearPlane = 0.2f; float CCameraManager::sFirstPersonFOV = 55.f; float CCameraManager::sThirdPersonFOV = 60.f; -CCameraManager::CCameraManager(TUniqueId curCameraId) : x0_curCameraId(curCameraId) -{ - CSfxManager::AddListener(CSfxManager::ESfxChannels::Game, zeus::CVector3f::skZero, zeus::CVector3f::skZero, - {1.f, 0.f, 0.f}, {0.f, 0.f, 1.f}, 50.f, 50.f, 1000.f, 1, 1.f); - sFirstPersonFOV = g_tweakGame->GetFirstPersonFOV(); +CCameraManager::CCameraManager(TUniqueId curCameraId) : x0_curCameraId(curCameraId) { + CSfxManager::AddListener(CSfxManager::ESfxChannels::Game, zeus::CVector3f::skZero, zeus::CVector3f::skZero, + {1.f, 0.f, 0.f}, {0.f, 0.f, 1.f}, 50.f, 50.f, 1000.f, 1, 1.f); + sFirstPersonFOV = g_tweakGame->GetFirstPersonFOV(); } -bool CCameraManager::IsInFirstPersonCamera() const -{ - return x7c_fpCamera->GetUniqueId() == x0_curCameraId; +bool CCameraManager::IsInFirstPersonCamera() const { return x7c_fpCamera->GetUniqueId() == x0_curCameraId; } + +zeus::CVector3f CCameraManager::GetGlobalCameraTranslation(const CStateManager& stateMgr) const { + const CGameCamera* camera = GetCurrentCamera(stateMgr); + return camera->GetTransform().rotate(x30_shakeOffset); } -zeus::CVector3f CCameraManager::GetGlobalCameraTranslation(const CStateManager& stateMgr) const -{ - const CGameCamera* camera = GetCurrentCamera(stateMgr); - return camera->GetTransform().rotate(x30_shakeOffset); +zeus::CTransform CCameraManager::GetCurrentCameraTransform(const CStateManager& stateMgr) const { + const CGameCamera* camera = GetCurrentCamera(stateMgr); + return camera->GetTransform() * zeus::CTransform::Translate(x30_shakeOffset); } -zeus::CTransform CCameraManager::GetCurrentCameraTransform(const CStateManager& stateMgr) const -{ - const CGameCamera* camera = GetCurrentCamera(stateMgr); - return camera->GetTransform() * zeus::CTransform::Translate(x30_shakeOffset); -} - -void CCameraManager::RemoveCameraShaker(int id) -{ - for (auto it = x14_shakers.begin(); it != x14_shakers.end(); ++it) - if (it->xbc_shakerId == id) - { - x14_shakers.erase(it); - break; - } -} - -int CCameraManager::AddCameraShaker(const CCameraShakeData& data, bool sfx) -{ - x14_shakers.emplace_back(data); - x14_shakers.back().xbc_shakerId = ++x2c_lastShakeId; - if (!xa0_24_pendingRumble) - { - xa0_24_pendingRumble = true; - x90_rumbleCooldown = 0.5f; - } - if (sfx && data.x0_duration > 0.f) - { - float vol = - zeus::clamp(100.f, std::max(data.GetMaxAMComponent(), data.GetMaxFMComponent()) * 9.f + 100.f, 127.f); - CSfxHandle sfxHandle; - if (data.xc0_flags & 0x1) - sfxHandle = CSfxManager::AddEmitter(SFXamb_x_rumble_lp_00, data.xc4_sfxPos, zeus::CVector3f::skZero, - vol / 127.f, false, false, 0x7f, kInvalidAreaId); - else - sfxHandle = CSfxManager::SfxStart(SFXamb_x_rumble_lp_00, vol / 127.f, 0.f, false, 0x7f, false, kInvalidAreaId); - sfxHandle->SetTimeRemaining(data.x0_duration); - } - return x2c_lastShakeId; -} - -void CCameraManager::EnterCinematic(CStateManager& mgr) -{ - mgr.GetPlayer().GetPlayerGun()->CancelFiring(mgr); - mgr.GetPlayer().UnFreeze(mgr); - - for (CEntity* ent : mgr.GetAllObjectList()) - { - if (TCastToPtr explo = ent) - { - mgr.FreeScriptObject(explo->GetUniqueId()); - } - else if (TCastToPtr weap = ent) - { - if (weap->GetActive()) - { - if ((weap->GetAttribField() & EProjectileAttrib::KeepInCinematic) == - EProjectileAttrib::None) - { - if (TCastToConstPtr(mgr.GetObjectById(weap->GetOwnerId())) || - TCastToConstPtr(mgr.GetObjectById(weap->GetOwnerId()))) - mgr.FreeScriptObject(weap->GetUniqueId()); - } - } - } +void CCameraManager::RemoveCameraShaker(int id) { + for (auto it = x14_shakers.begin(); it != x14_shakers.end(); ++it) + if (it->xbc_shakerId == id) { + x14_shakers.erase(it); + break; } } -void CCameraManager::AddCinemaCamera(TUniqueId id, CStateManager& stateMgr) -{ - if (x4_cineCameras.empty()) - EnterCinematic(stateMgr); - RemoveCinemaCamera(id, stateMgr); - x4_cineCameras.push_back(id); - if (TCastToPtr cam = stateMgr.ObjectById(id)) - { - if (cam->GetFlags() & 0x4) // into player eye - { - float time = 4.f; - float delayTime = cam->GetDuration() - 4.f; - if (delayTime < 0.f) - { - delayTime = 0.f; - time = cam->GetDuration(); - } - cam->SetFovInterpolation(cam->GetFov(), 55.f, time, delayTime); - } - } -} - -void CCameraManager::SetInsideFluid(bool val, TUniqueId fluidId) -{ - if (val) - { - ++x74_fluidCounter; - x78_fluidId = fluidId; - } +int CCameraManager::AddCameraShaker(const CCameraShakeData& data, bool sfx) { + x14_shakers.emplace_back(data); + x14_shakers.back().xbc_shakerId = ++x2c_lastShakeId; + if (!xa0_24_pendingRumble) { + xa0_24_pendingRumble = true; + x90_rumbleCooldown = 0.5f; + } + if (sfx && data.x0_duration > 0.f) { + float vol = zeus::clamp(100.f, std::max(data.GetMaxAMComponent(), data.GetMaxFMComponent()) * 9.f + 100.f, 127.f); + CSfxHandle sfxHandle; + if (data.xc0_flags & 0x1) + sfxHandle = CSfxManager::AddEmitter(SFXamb_x_rumble_lp_00, data.xc4_sfxPos, zeus::CVector3f::skZero, vol / 127.f, + false, false, 0x7f, kInvalidAreaId); else - --x74_fluidCounter; + sfxHandle = CSfxManager::SfxStart(SFXamb_x_rumble_lp_00, vol / 127.f, 0.f, false, 0x7f, false, kInvalidAreaId); + sfxHandle->SetTimeRemaining(data.x0_duration); + } + return x2c_lastShakeId; } -void CCameraManager::Update(float dt, CStateManager& stateMgr) -{ - UpdateCameraHints(dt, stateMgr); - ThinkCameras(dt, stateMgr); - UpdateListener(stateMgr); - UpdateRumble(dt, stateMgr); - UpdateFog(dt, stateMgr); -} +void CCameraManager::EnterCinematic(CStateManager& mgr) { + mgr.GetPlayer().GetPlayerGun()->CancelFiring(mgr); + mgr.GetPlayer().UnFreeze(mgr); -CGameCamera* CCameraManager::GetCurrentCamera(CStateManager& stateMgr) const -{ - CObjectList* camList = stateMgr.ObjectListById(EGameObjectList::GameCamera); - return static_cast(camList->GetObjectById(GetCurrentCameraId())); -} - -const CGameCamera* CCameraManager::GetCurrentCamera(const CStateManager& stateMgr) const -{ - const CObjectList* camList = stateMgr.GetObjectListById(EGameObjectList::GameCamera); - return static_cast(camList->GetObjectById(GetCurrentCameraId())); -} - -void CCameraManager::CreateStandardCameras(CStateManager& stateMgr) -{ - TUniqueId fpId = stateMgr.AllocateUniqueId(); - x7c_fpCamera = new CFirstPersonCamera(fpId, zeus::CTransform::Identity(), - stateMgr.Player()->GetUniqueId(), g_tweakPlayer->GetOrbitCameraSpeed(), - sFirstPersonFOV, sNearPlane, sFarPlane, sAspect); - stateMgr.AddObject(x7c_fpCamera); - stateMgr.Player()->SetCameraState(CPlayer::EPlayerCameraState::FirstPerson, stateMgr); - SetCurrentCameraId(fpId, stateMgr); - - x80_ballCamera = new CBallCamera(stateMgr.AllocateUniqueId(), stateMgr.Player()->GetUniqueId(), - zeus::CTransform::Identity(), sThirdPersonFOV, - sNearPlane, sFarPlane, sAspect); - stateMgr.AddObject(x80_ballCamera); - - x88_interpCamera = new CInterpolationCamera(stateMgr.AllocateUniqueId(), zeus::CTransform::Identity()); - stateMgr.AddObject(x88_interpCamera); -} - -void CCameraManager::SkipCinematic(CStateManager& stateMgr) -{ - TUniqueId camId = GetCurrentCameraId(); - CCinematicCamera* ent = static_cast(stateMgr.ObjectById(camId)); - while (ent) - { - ent->SetActive(false); - ent->WasDeactivated(stateMgr); - ent = TCastToPtr(GetCurrentCamera(stateMgr)).GetPtr(); + for (CEntity* ent : mgr.GetAllObjectList()) { + if (TCastToPtr explo = ent) { + mgr.FreeScriptObject(explo->GetUniqueId()); + } else if (TCastToPtr weap = ent) { + if (weap->GetActive()) { + if ((weap->GetAttribField() & EProjectileAttrib::KeepInCinematic) == EProjectileAttrib::None) { + if (TCastToConstPtr(mgr.GetObjectById(weap->GetOwnerId())) || + TCastToConstPtr(mgr.GetObjectById(weap->GetOwnerId()))) + mgr.FreeScriptObject(weap->GetUniqueId()); + } + } } - stateMgr.GetPlayer().UpdateCinematicState(stateMgr); - x7c_fpCamera->SkipCinematic(); + } } -void CCameraManager::SetPathCamera(TUniqueId id, CStateManager& mgr) -{ - xa4_pathCamId = id; - if (TCastToPtr cam = mgr.ObjectById(id)) +void CCameraManager::AddCinemaCamera(TUniqueId id, CStateManager& stateMgr) { + if (x4_cineCameras.empty()) + EnterCinematic(stateMgr); + RemoveCinemaCamera(id, stateMgr); + x4_cineCameras.push_back(id); + if (TCastToPtr cam = stateMgr.ObjectById(id)) { + if (cam->GetFlags() & 0x4) // into player eye { - cam->Reset(GetCurrentCameraTransform(mgr), mgr); - x80_ballCamera->TeleportCamera(cam->GetTransform(), mgr); + float time = 4.f; + float delayTime = cam->GetDuration() - 4.f; + if (delayTime < 0.f) { + delayTime = 0.f; + time = cam->GetDuration(); + } + cam->SetFovInterpolation(cam->GetFov(), 55.f, time, delayTime); } + } } -void CCameraManager::SetSpindleCamera(TUniqueId id, CStateManager& mgr) -{ - xa2_spindleCamId = id; - if (TCastToPtr cam = mgr.ObjectById(id)) - { - cam->Reset(GetCurrentCameraTransform(mgr), mgr); - x80_ballCamera->TeleportCamera(cam->GetTransform(), mgr); - } +void CCameraManager::SetInsideFluid(bool val, TUniqueId fluidId) { + if (val) { + ++x74_fluidCounter; + x78_fluidId = fluidId; + } else + --x74_fluidCounter; +} + +void CCameraManager::Update(float dt, CStateManager& stateMgr) { + UpdateCameraHints(dt, stateMgr); + ThinkCameras(dt, stateMgr); + UpdateListener(stateMgr); + UpdateRumble(dt, stateMgr); + UpdateFog(dt, stateMgr); +} + +CGameCamera* CCameraManager::GetCurrentCamera(CStateManager& stateMgr) const { + CObjectList* camList = stateMgr.ObjectListById(EGameObjectList::GameCamera); + return static_cast(camList->GetObjectById(GetCurrentCameraId())); +} + +const CGameCamera* CCameraManager::GetCurrentCamera(const CStateManager& stateMgr) const { + const CObjectList* camList = stateMgr.GetObjectListById(EGameObjectList::GameCamera); + return static_cast(camList->GetObjectById(GetCurrentCameraId())); +} + +void CCameraManager::CreateStandardCameras(CStateManager& stateMgr) { + TUniqueId fpId = stateMgr.AllocateUniqueId(); + x7c_fpCamera = + new CFirstPersonCamera(fpId, zeus::CTransform::Identity(), stateMgr.Player()->GetUniqueId(), + g_tweakPlayer->GetOrbitCameraSpeed(), sFirstPersonFOV, sNearPlane, sFarPlane, sAspect); + stateMgr.AddObject(x7c_fpCamera); + stateMgr.Player()->SetCameraState(CPlayer::EPlayerCameraState::FirstPerson, stateMgr); + SetCurrentCameraId(fpId, stateMgr); + + x80_ballCamera = new CBallCamera(stateMgr.AllocateUniqueId(), stateMgr.Player()->GetUniqueId(), + zeus::CTransform::Identity(), sThirdPersonFOV, sNearPlane, sFarPlane, sAspect); + stateMgr.AddObject(x80_ballCamera); + + x88_interpCamera = new CInterpolationCamera(stateMgr.AllocateUniqueId(), zeus::CTransform::Identity()); + stateMgr.AddObject(x88_interpCamera); +} + +void CCameraManager::SkipCinematic(CStateManager& stateMgr) { + TUniqueId camId = GetCurrentCameraId(); + CCinematicCamera* ent = static_cast(stateMgr.ObjectById(camId)); + while (ent) { + ent->SetActive(false); + ent->WasDeactivated(stateMgr); + ent = TCastToPtr(GetCurrentCamera(stateMgr)).GetPtr(); + } + stateMgr.GetPlayer().UpdateCinematicState(stateMgr); + x7c_fpCamera->SkipCinematic(); +} + +void CCameraManager::SetPathCamera(TUniqueId id, CStateManager& mgr) { + xa4_pathCamId = id; + if (TCastToPtr cam = mgr.ObjectById(id)) { + cam->Reset(GetCurrentCameraTransform(mgr), mgr); + x80_ballCamera->TeleportCamera(cam->GetTransform(), mgr); + } +} + +void CCameraManager::SetSpindleCamera(TUniqueId id, CStateManager& mgr) { + xa2_spindleCamId = id; + if (TCastToPtr cam = mgr.ObjectById(id)) { + cam->Reset(GetCurrentCameraTransform(mgr), mgr); + x80_ballCamera->TeleportCamera(cam->GetTransform(), mgr); + } } void CCameraManager::InterpolateToBallCamera(const zeus::CTransform& xf, TUniqueId camId, const zeus::CVector3f& lookPos, float maxTime, float positionSpeed, - float rotationSpeed, bool sinusoidal, CStateManager& mgr) -{ - if (!IsInFirstPersonCamera()) - { - x88_interpCamera->SetInterpolation(xf, lookPos, maxTime, positionSpeed, rotationSpeed, camId, sinusoidal, mgr); - if (!ShouldBypassInterpolation()) - SetCurrentCameraId(x88_interpCamera->GetUniqueId(), mgr); - } + float rotationSpeed, bool sinusoidal, CStateManager& mgr) { + if (!IsInFirstPersonCamera()) { + x88_interpCamera->SetInterpolation(xf, lookPos, maxTime, positionSpeed, rotationSpeed, camId, sinusoidal, mgr); + if (!ShouldBypassInterpolation()) + SetCurrentCameraId(x88_interpCamera->GetUniqueId(), mgr); + } } -void CCameraManager::RestoreHintlessCamera(CStateManager& mgr) -{ - TCastToPtr hint = mgr.ObjectById(xa6_camHintId); - zeus::CTransform ballCamXf = x80_ballCamera->GetTransform(); - xa6_camHintId = kInvalidUniqueId; - xa8_hintPriority = 1000; - if (hint) - { - zeus::CVector3f camToPlayerFlat = mgr.GetPlayer().GetTranslation() - ballCamXf.origin; - camToPlayerFlat.z() = 0.f; - if (camToPlayerFlat.canBeNormalized()) - camToPlayerFlat.normalize(); - else - camToPlayerFlat = mgr.GetPlayer().GetMoveDir(); - - x80_ballCamera->ResetToTweaks(mgr); - x80_ballCamera->UpdateLookAtPosition(0.f, mgr); - if (!mgr.GetPlayer().IsMorphBallTransitioning() && - hint->GetHint().GetBehaviourType() != CBallCamera::EBallCameraBehaviour::Default) - { - if ((hint->GetHint().GetOverrideFlags() & 0x1000) != 0) - { - x80_ballCamera->SetClampVelRange(hint->GetHint().GetClampVelRange()); - x80_ballCamera->SetClampVelTimer(hint->GetHint().GetClampVelTime()); - } - else - { - x80_ballCamera->TeleportCamera(x80_ballCamera->UpdateLookDirection(camToPlayerFlat, mgr), mgr); - InterpolateToBallCamera(ballCamXf, x80_ballCamera->GetUniqueId(), x80_ballCamera->GetLookPos(), - hint->GetHint().GetClampVelTime(), hint->GetHint().GetClampVelRange(), - hint->GetHint().GetClampRotRange(), - (hint->GetHint().GetOverrideFlags() & 0x800) != 0, mgr); - } - } - } -} - -void CCameraManager::SkipBallCameraCinematic(CStateManager& mgr) -{ - if (IsInCinematicCamera()) - { - x80_ballCamera->TeleportCamera(GetLastCineCamera(mgr)->GetTransform(), mgr); - x80_ballCamera->SetFovInterpolation(GetLastCineCamera(mgr)->GetFov(), x80_ballCamera->GetFov(), 1.f, 0.f); - SkipCinematic(mgr); - SetCurrentCameraId(x80_ballCamera->GetUniqueId(), mgr); - } -} - -void CCameraManager::ApplyCameraHint(const CScriptCameraHint& hint, CStateManager& mgr) -{ - if (x80_ballCamera->GetState() == CBallCamera::EBallCameraState::ToBall) - { - x80_ballCamera->SetState(CBallCamera::EBallCameraState::Default, mgr); - mgr.GetPlayer().SetCameraState(CPlayer::EPlayerCameraState::Ball, mgr); - } - - TCastToPtr oldHint = mgr.ObjectById(xa6_camHintId); - xa6_camHintId = hint.GetUniqueId(); - xa8_hintPriority = hint.GetPriority(); - - zeus::CTransform camXf = GetCurrentCameraTransform(mgr); - x80_ballCamera->ApplyCameraHint(mgr); - - if ((hint.GetHint().GetOverrideFlags() & 0x20) != 0) - x80_ballCamera->ResetPosition(mgr); - - switch (hint.GetHint().GetBehaviourType()) - { - case CBallCamera::EBallCameraBehaviour::PathCameraDesiredPos: - case CBallCamera::EBallCameraBehaviour::PathCamera: - SetPathCamera(hint.GetDelegatedCamera(), mgr); - break; - case CBallCamera::EBallCameraBehaviour::SpindleCamera: - SetSpindleCamera(hint.GetDelegatedCamera(), mgr); - break; - default: - SetPathCamera(kInvalidUniqueId, mgr); - SetSpindleCamera(kInvalidUniqueId, mgr); - break; - } - - if ((hint.GetHint().GetOverrideFlags() & 0x2000) != 0) - SkipBallCameraCinematic(mgr); - - x80_ballCamera->UpdateLookAtPosition(0.f, mgr); - - if ((hint.GetHint().GetOverrideFlags() & 0x20) == 0 && - (hint.GetHint().GetBehaviourType() != CBallCamera::EBallCameraBehaviour::Default || - (oldHint && oldHint->GetHint().GetBehaviourType() != CBallCamera::EBallCameraBehaviour::Default))) - { - InterpolateToBallCamera(camXf, x80_ballCamera->GetUniqueId(), x80_ballCamera->GetLookPos(), - hint.GetHint().GetInterpolateTime(), hint.GetHint().GetClampVelRange(), - hint.GetHint().GetClampRotRange(), - (hint.GetHint().GetOverrideFlags() & 0x400) != 0, mgr); - } -} - -void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) -{ - bool invalidHintRemoved = false; - for (auto it = xac_cameraHints.begin() ; it != xac_cameraHints.end() ;) - { - if (!TCastToPtr(mgr.ObjectById(it->second))) - { - invalidHintRemoved = true; - it = xac_cameraHints.erase(it); - continue; - } - ++it; - } - - bool inactiveHintRemoved = false; - for (TUniqueId id : x2b0_inactiveCameraHints) - { - if (TCastToConstPtr hint = mgr.GetObjectById(id)) - { - if (hint->GetHelperCount() == 0 || hint->GetInactive()) - { - for (auto it = xac_cameraHints.begin() ; it != xac_cameraHints.end() ; ++it) - { - if (it->second == id) - { - xac_cameraHints.erase(it); - if (xa6_camHintId == id) - { - inactiveHintRemoved = true; - SetPathCamera(kInvalidUniqueId, mgr); - SetSpindleCamera(kInvalidUniqueId, mgr); - } - break; - } - } - } - } - } - x2b0_inactiveCameraHints.clear(); - - bool activeHintAdded = false; - for (TUniqueId id : x334_activeCameraHints) - { - if (TCastToConstPtr hint = mgr.GetObjectById(id)) - { - bool activeHintPresent = false; - for (auto it = xac_cameraHints.begin() ; it != xac_cameraHints.end() ; ++it) - { - if (it->second == id) - { - activeHintPresent = true; - break; - } - } - - if (!activeHintPresent) - { - activeHintAdded = true; - xac_cameraHints.emplace_back(hint->GetPriority(), id); - } - } - } - x334_activeCameraHints.clear(); - - if (inactiveHintRemoved || activeHintAdded || invalidHintRemoved) - { - std::sort(xac_cameraHints.begin(), xac_cameraHints.end(), - [](const auto& a, const auto& b) { return a.first < b.first; }); - zeus::CTransform ballCamXf = x80_ballCamera->GetTransform(); - if ((inactiveHintRemoved || invalidHintRemoved) && xac_cameraHints.empty()) - { - RestoreHintlessCamera(mgr); - return; - } - bool foundHint = false; - CScriptCameraHint* bestHint = nullptr; - for (auto& h : xac_cameraHints) - { - if (TCastToPtr hint = mgr.ObjectById(h.second)) - { - bestHint = hint.GetPtr(); - foundHint = true; - break; - } - } - if (!foundHint) - RestoreHintlessCamera(mgr); - - bool changeHint = false; - if (bestHint && foundHint) - { - if ((bestHint->GetHint().GetOverrideFlags() & 0x80) != 0 && xac_cameraHints.size() > 1) - { - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - if ((bestHint->GetHint().GetOverrideFlags() & 0x100) != 0) - { - zeus::CVector3f camToBall = ballPos - ballCamXf.origin; - if (camToBall.canBeNormalized()) - camToBall.normalize(); - else - camToBall = ballCamXf.basis[1]; - - for (auto it = xac_cameraHints.begin() + 1 ; it != xac_cameraHints.end() ; ++it) - { - if (TCastToPtr hint = mgr.ObjectById(it->second)) - { - if ((hint->GetHint().GetOverrideFlags() & 0x80) != 0 && hint->GetPriority() == - bestHint->GetPriority() && - hint->GetAreaIdAlways() == bestHint->GetAreaIdAlways()) - { - zeus::CVector3f hintToBall = ballPos - bestHint->GetTranslation(); - if (hintToBall.canBeNormalized()) - hintToBall.normalize(); - else - hintToBall = bestHint->GetTransform().basis[1]; - - float camHintDot = zeus::clamp(-1.f, camToBall.dot(hintToBall), 1.f); - - zeus::CVector3f thisHintToBall = ballPos - hint->GetTranslation(); - if (thisHintToBall.canBeNormalized()) - thisHintToBall.normalize(); - else - thisHintToBall = hint->GetTransform().basis[1]; - - float camThisHintDot = zeus::clamp(-1.f, camToBall.dot(thisHintToBall), 1.f); - - if (camThisHintDot > camHintDot) - bestHint = hint.GetPtr(); - } - else - { - break; - } - } - else - { - break; - } - } - } - else - { - if (TCastToConstPtr act = mgr.GetObjectById(bestHint->GetFirstHelper())) - { - zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); - zeus::CVector3f f26 = act->GetTranslation() - ballPos; - zeus::CVector3f ballToHelper = f26; - if (ballToHelper.canBeNormalized()) - ballToHelper.normalize(); - else - ballToHelper = bestHint->GetTransform().basis[1]; - - for (auto it = xac_cameraHints.begin() + 1 ; it != xac_cameraHints.end() ; ++it) - { - if (TCastToPtr hint = mgr.ObjectById(it->second)) - { - if ((hint->GetHint().GetOverrideFlags() & 0x80) != 0 && hint->GetPriority() == - bestHint->GetPriority() && - hint->GetAreaIdAlways() == bestHint->GetAreaIdAlways()) - { - zeus::CVector3f hintToHelper = act->GetTranslation() - bestHint->GetTranslation(); - if (hintToHelper.canBeNormalized()) - hintToHelper.normalize(); - else - hintToHelper = bestHint->GetTransform().basis[1]; - - float ballHintDot = zeus::clamp(-1.f, ballToHelper.dot(hintToHelper), 1.f); - - zeus::CVector3f thisBallToHelper = f26; - if (thisBallToHelper.canBeNormalized()) - thisBallToHelper.normalize(); - else - thisBallToHelper = hint->GetTransform().basis[1]; - - zeus::CVector3f thisHintToHelper = act->GetTranslation() - hint->GetTranslation(); - if (thisHintToHelper.canBeNormalized()) - thisHintToHelper.normalize(); - else - thisHintToHelper = hint->GetTransform().basis[1]; - - float thisBallHintDot = - zeus::clamp(-1.f, thisBallToHelper.dot(thisHintToHelper), 1.f); - - if (thisBallHintDot > ballHintDot) - bestHint = hint.GetPtr(); - } - else - { - break; - } - } - else - { - break; - } - } - } - } - - if (bestHint->GetUniqueId() != xa6_camHintId) - changeHint = true; - } - else if (xa6_camHintId != bestHint->GetUniqueId()) - { - if (bestHint->GetHint().GetBehaviourType() == CBallCamera::EBallCameraBehaviour::HintInitializePosition) - { - if ((bestHint->GetHint().GetOverrideFlags() & 0x20) != 0) - { - x80_ballCamera->TeleportCamera( - zeus::lookAt(bestHint->GetTranslation(), x80_ballCamera->GetLookPos()), mgr); - } - DeleteCameraHint(bestHint->GetUniqueId(), mgr); - if ((bestHint->GetHint().GetOverrideFlags() & 0x2000) != 0) - SkipBallCameraCinematic(mgr); - changeHint = false; - } - else - { - changeHint = true; - } - } - - if (changeHint) - ApplyCameraHint(*bestHint, mgr); - } - } -} - -void CCameraManager::ThinkCameras(float dt, CStateManager& mgr) -{ - CGameCameraList gcList = mgr.GetCameraObjectList(); - - for (CEntity* ent : gcList) - { - if (TCastToPtr gc = ent) - { - gc->Think(dt, mgr); - gc->UpdatePerspective(dt); - } - } - - if (IsInCinematicCamera()) - return; - - TUniqueId camId = GetLastCameraId(); - if (const CGameCamera* cam = TCastToConstPtr(mgr.GetObjectById(camId))) - x3bc_curFov = cam->GetFov(); -} - -void CCameraManager::UpdateFog(float dt, CStateManager& mgr) -{ - if (x98_fogDensitySpeed != 0.f) - { - x94_fogDensityFactor += dt * x98_fogDensitySpeed; - if ((x98_fogDensitySpeed > 0.f) ? x94_fogDensityFactor > x9c_fogDensityFactorTarget : - x94_fogDensityFactor < x9c_fogDensityFactorTarget) - { - x94_fogDensityFactor = x9c_fogDensityFactorTarget; - x98_fogDensitySpeed = 0.f; - } - } - - if (x74_fluidCounter) - { - if (TCastToConstPtr water = mgr.GetObjectById(x78_fluidId)) - { - zeus::CVector2f zRange(GetCurrentCamera(mgr)->GetNearClipDistance(), - CalculateFogDensity(mgr, water.GetPtr())); - x3c_fog.SetFogExplicit(ERglFogMode::PerspExp, water->GetInsideFogColor(), zRange); - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) - mgr.GetCameraFilterPass(4).DisableFilter(0.f); - else - mgr.GetCameraFilterPass(4).SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, - 0.f, water->GetInsideFogColor(), {}); - } - xa0_26_inWater = true; - } - else if (xa0_26_inWater) - { - mgr.GetCameraManager()->x3c_fog.DisableFog(); - mgr.GetCameraFilterPass(4).DisableFilter(0.f); - xa0_26_inWater = false; - } - - x3c_fog.Update(dt); -} - -void CCameraManager::UpdateRumble(float dt, CStateManager& mgr) -{ - x30_shakeOffset = zeus::CVector3f::skZero; - for (auto it = x14_shakers.begin() ; it != x14_shakers.end() ;) - { - CCameraShakeData& shaker = *it; - shaker.Update(dt, mgr); - if (shaker.x4_curTime >= shaker.x0_duration) - { - it = x14_shakers.erase(it); - continue; - } - x30_shakeOffset += shaker.GetPoint(); - ++it; - } - - if (!x14_shakers.empty() && !xa0_25_rumbling && xa0_24_pendingRumble) - { - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::CameraShake, 1.f, ERumblePriority::Two); - xa0_25_rumbling = true; - } - - if (x90_rumbleCooldown > 0.f) - { - x90_rumbleCooldown -= dt; - } - else if (xa0_25_rumbling) - { - xa0_24_pendingRumble = false; - xa0_25_rumbling = false; - } - - if (mgr.GetPlayer().GetCameraState() != CPlayer::EPlayerCameraState::FirstPerson && - !IsInCinematicCamera()) - x30_shakeOffset = zeus::CVector3f::skZero; -} - -void CCameraManager::UpdateListener(CStateManager& mgr) -{ - const zeus::CTransform xf = GetCurrentCameraTransform(mgr); - CSfxManager::UpdateListener(xf.origin, zeus::CVector3f::skZero, xf.frontVector(), xf.upVector(), 1.f); -} - -float CCameraManager::CalculateFogDensity(CStateManager& mgr, const CScriptWater* water) -{ - float distanceFactor = 1.f - water->GetFluidPlane().GetAlpha(); - float distance = 0; - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) - distance = g_tweakGame->GetGravityWaterFogDistanceRange() * distanceFactor + - g_tweakGame->GetGravityWaterFogDistanceBase(); +void CCameraManager::RestoreHintlessCamera(CStateManager& mgr) { + TCastToPtr hint = mgr.ObjectById(xa6_camHintId); + zeus::CTransform ballCamXf = x80_ballCamera->GetTransform(); + xa6_camHintId = kInvalidUniqueId; + xa8_hintPriority = 1000; + if (hint) { + zeus::CVector3f camToPlayerFlat = mgr.GetPlayer().GetTranslation() - ballCamXf.origin; + camToPlayerFlat.z() = 0.f; + if (camToPlayerFlat.canBeNormalized()) + camToPlayerFlat.normalize(); else - distance = g_tweakGame->GetWaterFogDistanceRange() * distanceFactor + - g_tweakGame->GetWaterFogDistanceBase(); + camToPlayerFlat = mgr.GetPlayer().GetMoveDir(); - return distance * x94_fogDensityFactor; -} - -void CCameraManager::ResetCameras(CStateManager& mgr) -{ - zeus::CTransform xf = mgr.GetPlayer().CreateTransformFromMovementDirection(); - xf.origin = mgr.GetPlayer().GetEyePosition(); - - for (CEntity* ent : mgr.GetCameraObjectList()) - { - TCastToPtr camObj(ent); - camObj->Reset(xf, mgr); + x80_ballCamera->ResetToTweaks(mgr); + x80_ballCamera->UpdateLookAtPosition(0.f, mgr); + if (!mgr.GetPlayer().IsMorphBallTransitioning() && + hint->GetHint().GetBehaviourType() != CBallCamera::EBallCameraBehaviour::Default) { + if ((hint->GetHint().GetOverrideFlags() & 0x1000) != 0) { + x80_ballCamera->SetClampVelRange(hint->GetHint().GetClampVelRange()); + x80_ballCamera->SetClampVelTimer(hint->GetHint().GetClampVelTime()); + } else { + x80_ballCamera->TeleportCamera(x80_ballCamera->UpdateLookDirection(camToPlayerFlat, mgr), mgr); + InterpolateToBallCamera(ballCamXf, x80_ballCamera->GetUniqueId(), x80_ballCamera->GetLookPos(), + hint->GetHint().GetClampVelTime(), hint->GetHint().GetClampVelRange(), + hint->GetHint().GetClampRotRange(), (hint->GetHint().GetOverrideFlags() & 0x800) != 0, + mgr); + } } + } } -void CCameraManager::SetSpecialCameras(CFirstPersonCamera& fp, CBallCamera& ball) -{ - x7c_fpCamera = &fp; - x80_ballCamera = &ball; +void CCameraManager::SkipBallCameraCinematic(CStateManager& mgr) { + if (IsInCinematicCamera()) { + x80_ballCamera->TeleportCamera(GetLastCineCamera(mgr)->GetTransform(), mgr); + x80_ballCamera->SetFovInterpolation(GetLastCineCamera(mgr)->GetFov(), x80_ballCamera->GetFov(), 1.f, 0.f); + SkipCinematic(mgr); + SetCurrentCameraId(x80_ballCamera->GetUniqueId(), mgr); + } } -void CCameraManager::ProcessInput(const CFinalInput& input, CStateManager& stateMgr) -{ - for (CEntity* ent : stateMgr.GetCameraObjectList()) - { - if (ent == nullptr) - continue; - auto& cam = static_cast(*ent); - if (input.ControllerIdx() != cam.x16c_controllerIdx) - continue; - cam.ProcessInput(input, stateMgr); +void CCameraManager::ApplyCameraHint(const CScriptCameraHint& hint, CStateManager& mgr) { + if (x80_ballCamera->GetState() == CBallCamera::EBallCameraState::ToBall) { + x80_ballCamera->SetState(CBallCamera::EBallCameraState::Default, mgr); + mgr.GetPlayer().SetCameraState(CPlayer::EPlayerCameraState::Ball, mgr); + } + + TCastToPtr oldHint = mgr.ObjectById(xa6_camHintId); + xa6_camHintId = hint.GetUniqueId(); + xa8_hintPriority = hint.GetPriority(); + + zeus::CTransform camXf = GetCurrentCameraTransform(mgr); + x80_ballCamera->ApplyCameraHint(mgr); + + if ((hint.GetHint().GetOverrideFlags() & 0x20) != 0) + x80_ballCamera->ResetPosition(mgr); + + switch (hint.GetHint().GetBehaviourType()) { + case CBallCamera::EBallCameraBehaviour::PathCameraDesiredPos: + case CBallCamera::EBallCameraBehaviour::PathCamera: + SetPathCamera(hint.GetDelegatedCamera(), mgr); + break; + case CBallCamera::EBallCameraBehaviour::SpindleCamera: + SetSpindleCamera(hint.GetDelegatedCamera(), mgr); + break; + default: + SetPathCamera(kInvalidUniqueId, mgr); + SetSpindleCamera(kInvalidUniqueId, mgr); + break; + } + + if ((hint.GetHint().GetOverrideFlags() & 0x2000) != 0) + SkipBallCameraCinematic(mgr); + + x80_ballCamera->UpdateLookAtPosition(0.f, mgr); + + if ((hint.GetHint().GetOverrideFlags() & 0x20) == 0 && + (hint.GetHint().GetBehaviourType() != CBallCamera::EBallCameraBehaviour::Default || + (oldHint && oldHint->GetHint().GetBehaviourType() != CBallCamera::EBallCameraBehaviour::Default))) { + InterpolateToBallCamera(camXf, x80_ballCamera->GetUniqueId(), x80_ballCamera->GetLookPos(), + hint.GetHint().GetInterpolateTime(), hint.GetHint().GetClampVelRange(), + hint.GetHint().GetClampRotRange(), (hint.GetHint().GetOverrideFlags() & 0x400) != 0, mgr); + } +} + +void CCameraManager::UpdateCameraHints(float, CStateManager& mgr) { + bool invalidHintRemoved = false; + for (auto it = xac_cameraHints.begin(); it != xac_cameraHints.end();) { + if (!TCastToPtr(mgr.ObjectById(it->second))) { + invalidHintRemoved = true; + it = xac_cameraHints.erase(it); + continue; } -} + ++it; + } -void CCameraManager::RenderCameras(const CStateManager& mgr) -{ - for (CEntity* cam : mgr.GetCameraObjectList()) - static_cast(cam)->Render(mgr); -} - -void CCameraManager::SetupBallCamera(CStateManager& mgr) -{ - if (TCastToPtr hint = mgr.ObjectById(xa6_camHintId)) - { - if (hint->GetHint().GetBehaviourType() == CBallCamera::EBallCameraBehaviour::HintInitializePosition) - { - if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0) - x80_ballCamera->TeleportCamera(hint->GetTransform(), mgr); - AddInactiveCameraHint(xa6_camHintId, mgr); + bool inactiveHintRemoved = false; + for (TUniqueId id : x2b0_inactiveCameraHints) { + if (TCastToConstPtr hint = mgr.GetObjectById(id)) { + if (hint->GetHelperCount() == 0 || hint->GetInactive()) { + for (auto it = xac_cameraHints.begin(); it != xac_cameraHints.end(); ++it) { + if (it->second == id) { + xac_cameraHints.erase(it); + if (xa6_camHintId == id) { + inactiveHintRemoved = true; + SetPathCamera(kInvalidUniqueId, mgr); + SetSpindleCamera(kInvalidUniqueId, mgr); + } + break; + } } - else - { - ApplyCameraHint(*hint, mgr); + } + } + } + x2b0_inactiveCameraHints.clear(); + + bool activeHintAdded = false; + for (TUniqueId id : x334_activeCameraHints) { + if (TCastToConstPtr hint = mgr.GetObjectById(id)) { + bool activeHintPresent = false; + for (auto it = xac_cameraHints.begin(); it != xac_cameraHints.end(); ++it) { + if (it->second == id) { + activeHintPresent = true; + break; } + } + + if (!activeHintPresent) { + activeHintAdded = true; + xac_cameraHints.emplace_back(hint->GetPriority(), id); + } } -} + } + x334_activeCameraHints.clear(); -void CCameraManager::SetPlayerCamera(CStateManager& mgr, TUniqueId newCamId) -{ - if (x88_interpCamera->GetActive()) - { - x88_interpCamera->SetActive(false); - x80_ballCamera->SkipFovInterpolation(); - if (!ShouldBypassInterpolation()) - SetCurrentCameraId(newCamId, mgr); + if (inactiveHintRemoved || activeHintAdded || invalidHintRemoved) { + std::sort(xac_cameraHints.begin(), xac_cameraHints.end(), + [](const auto& a, const auto& b) { return a.first < b.first; }); + zeus::CTransform ballCamXf = x80_ballCamera->GetTransform(); + if ((inactiveHintRemoved || invalidHintRemoved) && xac_cameraHints.empty()) { + RestoreHintlessCamera(mgr); + return; } -} + bool foundHint = false; + CScriptCameraHint* bestHint = nullptr; + for (auto& h : xac_cameraHints) { + if (TCastToPtr hint = mgr.ObjectById(h.second)) { + bestHint = hint.GetPtr(); + foundHint = true; + break; + } + } + if (!foundHint) + RestoreHintlessCamera(mgr); -float CCameraManager::GetCameraBobMagnitude() const -{ - return 1.f - zeus::clamp(-1.f, std::fabs(zeus::clamp(-1.f, - x7c_fpCamera->GetTransform().basis[1].dot(zeus::CVector3f::skUp), 1.f)) / - std::cos(2.f * M_PIF / 12.f), 1.f); -} + bool changeHint = false; + if (bestHint && foundHint) { + if ((bestHint->GetHint().GetOverrideFlags() & 0x80) != 0 && xac_cameraHints.size() > 1) { + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + if ((bestHint->GetHint().GetOverrideFlags() & 0x100) != 0) { + zeus::CVector3f camToBall = ballPos - ballCamXf.origin; + if (camToBall.canBeNormalized()) + camToBall.normalize(); + else + camToBall = ballCamXf.basis[1]; -bool CCameraManager::HasBallCameraInitialPositionHint(CStateManager& mgr) const -{ - if (HasCameraHint(mgr)) - { - switch (mgr.GetCameraManager()->GetCameraHint(mgr)->GetHint().GetBehaviourType()) - { - case CBallCamera::EBallCameraBehaviour::HintBallToCam: - case CBallCamera::EBallCameraBehaviour::HintFixedPosition: - case CBallCamera::EBallCameraBehaviour::HintFixedTransform: - case CBallCamera::EBallCameraBehaviour::PathCamera: - case CBallCamera::EBallCameraBehaviour::SpindleCamera: - return true; - default: - return false; + for (auto it = xac_cameraHints.begin() + 1; it != xac_cameraHints.end(); ++it) { + if (TCastToPtr hint = mgr.ObjectById(it->second)) { + if ((hint->GetHint().GetOverrideFlags() & 0x80) != 0 && hint->GetPriority() == bestHint->GetPriority() && + hint->GetAreaIdAlways() == bestHint->GetAreaIdAlways()) { + zeus::CVector3f hintToBall = ballPos - bestHint->GetTranslation(); + if (hintToBall.canBeNormalized()) + hintToBall.normalize(); + else + hintToBall = bestHint->GetTransform().basis[1]; + + float camHintDot = zeus::clamp(-1.f, camToBall.dot(hintToBall), 1.f); + + zeus::CVector3f thisHintToBall = ballPos - hint->GetTranslation(); + if (thisHintToBall.canBeNormalized()) + thisHintToBall.normalize(); + else + thisHintToBall = hint->GetTransform().basis[1]; + + float camThisHintDot = zeus::clamp(-1.f, camToBall.dot(thisHintToBall), 1.f); + + if (camThisHintDot > camHintDot) + bestHint = hint.GetPtr(); + } else { + break; + } + } else { + break; + } + } + } else { + if (TCastToConstPtr act = mgr.GetObjectById(bestHint->GetFirstHelper())) { + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + zeus::CVector3f f26 = act->GetTranslation() - ballPos; + zeus::CVector3f ballToHelper = f26; + if (ballToHelper.canBeNormalized()) + ballToHelper.normalize(); + else + ballToHelper = bestHint->GetTransform().basis[1]; + + for (auto it = xac_cameraHints.begin() + 1; it != xac_cameraHints.end(); ++it) { + if (TCastToPtr hint = mgr.ObjectById(it->second)) { + if ((hint->GetHint().GetOverrideFlags() & 0x80) != 0 && + hint->GetPriority() == bestHint->GetPriority() && + hint->GetAreaIdAlways() == bestHint->GetAreaIdAlways()) { + zeus::CVector3f hintToHelper = act->GetTranslation() - bestHint->GetTranslation(); + if (hintToHelper.canBeNormalized()) + hintToHelper.normalize(); + else + hintToHelper = bestHint->GetTransform().basis[1]; + + float ballHintDot = zeus::clamp(-1.f, ballToHelper.dot(hintToHelper), 1.f); + + zeus::CVector3f thisBallToHelper = f26; + if (thisBallToHelper.canBeNormalized()) + thisBallToHelper.normalize(); + else + thisBallToHelper = hint->GetTransform().basis[1]; + + zeus::CVector3f thisHintToHelper = act->GetTranslation() - hint->GetTranslation(); + if (thisHintToHelper.canBeNormalized()) + thisHintToHelper.normalize(); + else + thisHintToHelper = hint->GetTransform().basis[1]; + + float thisBallHintDot = zeus::clamp(-1.f, thisBallToHelper.dot(thisHintToHelper), 1.f); + + if (thisBallHintDot > ballHintDot) + bestHint = hint.GetPtr(); + } else { + break; + } + } else { + break; + } + } + } } + + if (bestHint->GetUniqueId() != xa6_camHintId) + changeHint = true; + } else if (xa6_camHintId != bestHint->GetUniqueId()) { + if (bestHint->GetHint().GetBehaviourType() == CBallCamera::EBallCameraBehaviour::HintInitializePosition) { + if ((bestHint->GetHint().GetOverrideFlags() & 0x20) != 0) { + x80_ballCamera->TeleportCamera(zeus::lookAt(bestHint->GetTranslation(), x80_ballCamera->GetLookPos()), mgr); + } + DeleteCameraHint(bestHint->GetUniqueId(), mgr); + if ((bestHint->GetHint().GetOverrideFlags() & 0x2000) != 0) + SkipBallCameraCinematic(mgr); + changeHint = false; + } else { + changeHint = true; + } + } + + if (changeHint) + ApplyCameraHint(*bestHint, mgr); } + } +} + +void CCameraManager::ThinkCameras(float dt, CStateManager& mgr) { + CGameCameraList gcList = mgr.GetCameraObjectList(); + + for (CEntity* ent : gcList) { + if (TCastToPtr gc = ent) { + gc->Think(dt, mgr); + gc->UpdatePerspective(dt); + } + } + + if (IsInCinematicCamera()) + return; + + TUniqueId camId = GetLastCameraId(); + if (const CGameCamera* cam = TCastToConstPtr(mgr.GetObjectById(camId))) + x3bc_curFov = cam->GetFov(); +} + +void CCameraManager::UpdateFog(float dt, CStateManager& mgr) { + if (x98_fogDensitySpeed != 0.f) { + x94_fogDensityFactor += dt * x98_fogDensitySpeed; + if ((x98_fogDensitySpeed > 0.f) ? x94_fogDensityFactor > x9c_fogDensityFactorTarget + : x94_fogDensityFactor < x9c_fogDensityFactorTarget) { + x94_fogDensityFactor = x9c_fogDensityFactorTarget; + x98_fogDensitySpeed = 0.f; + } + } + + if (x74_fluidCounter) { + if (TCastToConstPtr water = mgr.GetObjectById(x78_fluidId)) { + zeus::CVector2f zRange(GetCurrentCamera(mgr)->GetNearClipDistance(), CalculateFogDensity(mgr, water.GetPtr())); + x3c_fog.SetFogExplicit(ERglFogMode::PerspExp, water->GetInsideFogColor(), zRange); + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) + mgr.GetCameraFilterPass(4).DisableFilter(0.f); + else + mgr.GetCameraFilterPass(4).SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, + water->GetInsideFogColor(), {}); + } + xa0_26_inWater = true; + } else if (xa0_26_inWater) { + mgr.GetCameraManager()->x3c_fog.DisableFog(); + mgr.GetCameraFilterPass(4).DisableFilter(0.f); + xa0_26_inWater = false; + } + + x3c_fog.Update(dt); +} + +void CCameraManager::UpdateRumble(float dt, CStateManager& mgr) { + x30_shakeOffset = zeus::CVector3f::skZero; + for (auto it = x14_shakers.begin(); it != x14_shakers.end();) { + CCameraShakeData& shaker = *it; + shaker.Update(dt, mgr); + if (shaker.x4_curTime >= shaker.x0_duration) { + it = x14_shakers.erase(it); + continue; + } + x30_shakeOffset += shaker.GetPoint(); + ++it; + } + + if (!x14_shakers.empty() && !xa0_25_rumbling && xa0_24_pendingRumble) { + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::CameraShake, 1.f, ERumblePriority::Two); + xa0_25_rumbling = true; + } + + if (x90_rumbleCooldown > 0.f) { + x90_rumbleCooldown -= dt; + } else if (xa0_25_rumbling) { + xa0_24_pendingRumble = false; + xa0_25_rumbling = false; + } + + if (mgr.GetPlayer().GetCameraState() != CPlayer::EPlayerCameraState::FirstPerson && !IsInCinematicCamera()) + x30_shakeOffset = zeus::CVector3f::skZero; +} + +void CCameraManager::UpdateListener(CStateManager& mgr) { + const zeus::CTransform xf = GetCurrentCameraTransform(mgr); + CSfxManager::UpdateListener(xf.origin, zeus::CVector3f::skZero, xf.frontVector(), xf.upVector(), 1.f); +} + +float CCameraManager::CalculateFogDensity(CStateManager& mgr, const CScriptWater* water) { + float distanceFactor = 1.f - water->GetFluidPlane().GetAlpha(); + float distance = 0; + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) + distance = + g_tweakGame->GetGravityWaterFogDistanceRange() * distanceFactor + g_tweakGame->GetGravityWaterFogDistanceBase(); + else + distance = g_tweakGame->GetWaterFogDistanceRange() * distanceFactor + g_tweakGame->GetWaterFogDistanceBase(); + + return distance * x94_fogDensityFactor; +} + +void CCameraManager::ResetCameras(CStateManager& mgr) { + zeus::CTransform xf = mgr.GetPlayer().CreateTransformFromMovementDirection(); + xf.origin = mgr.GetPlayer().GetEyePosition(); + + for (CEntity* ent : mgr.GetCameraObjectList()) { + TCastToPtr camObj(ent); + camObj->Reset(xf, mgr); + } +} + +void CCameraManager::SetSpecialCameras(CFirstPersonCamera& fp, CBallCamera& ball) { + x7c_fpCamera = &fp; + x80_ballCamera = &ball; +} + +void CCameraManager::ProcessInput(const CFinalInput& input, CStateManager& stateMgr) { + for (CEntity* ent : stateMgr.GetCameraObjectList()) { + if (ent == nullptr) + continue; + auto& cam = static_cast(*ent); + if (input.ControllerIdx() != cam.x16c_controllerIdx) + continue; + cam.ProcessInput(input, stateMgr); + } +} + +void CCameraManager::RenderCameras(const CStateManager& mgr) { + for (CEntity* cam : mgr.GetCameraObjectList()) + static_cast(cam)->Render(mgr); +} + +void CCameraManager::SetupBallCamera(CStateManager& mgr) { + if (TCastToPtr hint = mgr.ObjectById(xa6_camHintId)) { + if (hint->GetHint().GetBehaviourType() == CBallCamera::EBallCameraBehaviour::HintInitializePosition) { + if ((hint->GetHint().GetOverrideFlags() & 0x20) != 0) + x80_ballCamera->TeleportCamera(hint->GetTransform(), mgr); + AddInactiveCameraHint(xa6_camHintId, mgr); + } else { + ApplyCameraHint(*hint, mgr); + } + } +} + +void CCameraManager::SetPlayerCamera(CStateManager& mgr, TUniqueId newCamId) { + if (x88_interpCamera->GetActive()) { + x88_interpCamera->SetActive(false); + x80_ballCamera->SkipFovInterpolation(); + if (!ShouldBypassInterpolation()) + SetCurrentCameraId(newCamId, mgr); + } +} + +float CCameraManager::GetCameraBobMagnitude() const { + return 1.f - zeus::clamp( + -1.f, + std::fabs(zeus::clamp(-1.f, x7c_fpCamera->GetTransform().basis[1].dot(zeus::CVector3f::skUp), 1.f)) / + std::cos(2.f * M_PIF / 12.f), + 1.f); +} + +bool CCameraManager::HasBallCameraInitialPositionHint(CStateManager& mgr) const { + if (HasCameraHint(mgr)) { + switch (mgr.GetCameraManager()->GetCameraHint(mgr)->GetHint().GetBehaviourType()) { + case CBallCamera::EBallCameraBehaviour::HintBallToCam: + case CBallCamera::EBallCameraBehaviour::HintFixedPosition: + case CBallCamera::EBallCameraBehaviour::HintFixedTransform: + case CBallCamera::EBallCameraBehaviour::PathCamera: + case CBallCamera::EBallCameraBehaviour::SpindleCamera: + return true; + default: + return false; + } + } + return false; +} + +void CCameraManager::RemoveCinemaCamera(TUniqueId uid, CStateManager& mgr) { + auto search = std::find(x4_cineCameras.begin(), x4_cineCameras.end(), uid); + if (search != x4_cineCameras.end()) + x4_cineCameras.erase(search); +} + +void CCameraManager::DeleteCameraHint(TUniqueId id, CStateManager& mgr) { + if (TCastToPtr hint = mgr.ObjectById(id)) { + auto search = std::find_if(x2b0_inactiveCameraHints.begin(), x2b0_inactiveCameraHints.end(), + [id](TUniqueId tid) { return tid == id; }); + if (search == x2b0_inactiveCameraHints.end()) { + hint->ClearIdList(); + hint->SetInactive(true); + if (x2b0_inactiveCameraHints.size() != 64) + x2b0_inactiveCameraHints.push_back(id); + } + } +} + +void CCameraManager::AddInactiveCameraHint(TUniqueId id, CStateManager& mgr) { + if (TCastToPtr hint = mgr.ObjectById(id)) { + auto search = std::find_if(x2b0_inactiveCameraHints.begin(), x2b0_inactiveCameraHints.end(), + [id](TUniqueId tid) { return tid == id; }); + if (search == x2b0_inactiveCameraHints.end() && x2b0_inactiveCameraHints.size() != 64) + x2b0_inactiveCameraHints.push_back(id); + } +} + +void CCameraManager::AddActiveCameraHint(TUniqueId id, CStateManager& mgr) { + if (TCastToPtr hint = mgr.ObjectById(id)) { + auto search = std::find_if(x334_activeCameraHints.begin(), x334_activeCameraHints.end(), + [id](TUniqueId tid) { return tid == id; }); + if (search == x334_activeCameraHints.end() && xac_cameraHints.size() != 64 && x334_activeCameraHints.size() != 64) + x334_activeCameraHints.push_back(id); + } +} + +TUniqueId CCameraManager::GetLastCineCameraId() const { + if (x4_cineCameras.empty()) + return kInvalidUniqueId; + return x4_cineCameras.back(); +} + +const CCinematicCamera* CCameraManager::GetLastCineCamera(CStateManager& mgr) const { + return static_cast(mgr.GetObjectById(GetLastCineCameraId())); +} + +const CScriptCameraHint* CCameraManager::GetCameraHint(CStateManager& mgr) const { + return TCastToConstPtr(mgr.GetObjectById(xa6_camHintId)).GetPtr(); +} + +bool CCameraManager::HasCameraHint(CStateManager& mgr) const { + if (xac_cameraHints.empty() || xa6_camHintId == kInvalidUniqueId) return false; -} - -void CCameraManager::RemoveCinemaCamera(TUniqueId uid, CStateManager& mgr) -{ - auto search = std::find(x4_cineCameras.begin(), x4_cineCameras.end(), uid); - if (search != x4_cineCameras.end()) - x4_cineCameras.erase(search); -} - -void CCameraManager::DeleteCameraHint(TUniqueId id, CStateManager& mgr) -{ - if (TCastToPtr hint = mgr.ObjectById(id)) - { - auto search = std::find_if(x2b0_inactiveCameraHints.begin(), x2b0_inactiveCameraHints.end(), - [id](TUniqueId tid) { return tid == id; }); - if (search == x2b0_inactiveCameraHints.end()) - { - hint->ClearIdList(); - hint->SetInactive(true); - if (x2b0_inactiveCameraHints.size() != 64) - x2b0_inactiveCameraHints.push_back(id); - } - } -} - -void CCameraManager::AddInactiveCameraHint(TUniqueId id, CStateManager& mgr) -{ - if (TCastToPtr hint = mgr.ObjectById(id)) - { - auto search = std::find_if(x2b0_inactiveCameraHints.begin(), x2b0_inactiveCameraHints.end(), - [id](TUniqueId tid) { return tid == id; }); - if (search == x2b0_inactiveCameraHints.end() && - x2b0_inactiveCameraHints.size() != 64) - x2b0_inactiveCameraHints.push_back(id); - } -} - -void CCameraManager::AddActiveCameraHint(TUniqueId id, CStateManager& mgr) -{ - if (TCastToPtr hint = mgr.ObjectById(id)) - { - auto search = std::find_if(x334_activeCameraHints.begin(), x334_activeCameraHints.end(), - [id](TUniqueId tid) { return tid == id; }); - if (search == x334_activeCameraHints.end() && xac_cameraHints.size() != 64 && - x334_activeCameraHints.size() != 64) - x334_activeCameraHints.push_back(id); - } -} - -TUniqueId CCameraManager::GetLastCineCameraId() const -{ - if (x4_cineCameras.empty()) - return kInvalidUniqueId; - return x4_cineCameras.back(); -} - -const CCinematicCamera* CCameraManager::GetLastCineCamera(CStateManager& mgr) const -{ - return static_cast(mgr.GetObjectById(GetLastCineCameraId())); -} - -const CScriptCameraHint* CCameraManager::GetCameraHint(CStateManager& mgr) const -{ - return TCastToConstPtr(mgr.GetObjectById(xa6_camHintId)).GetPtr(); -} - -bool CCameraManager::HasCameraHint(CStateManager& mgr) const -{ - if (xac_cameraHints.empty() || xa6_camHintId == kInvalidUniqueId) - return false; - return mgr.GetObjectById(xa6_camHintId) != nullptr; + return mgr.GetObjectById(xa6_camHintId) != nullptr; } bool CCameraManager::IsInterpolationCameraActive() const { return x88_interpCamera->GetActive(); } -void CCameraManager::SetFogDensity(float fogDensityTarget, float fogDensitySpeed) -{ - x9c_fogDensityFactorTarget = fogDensityTarget; - x98_fogDensitySpeed = (x9c_fogDensityFactorTarget >= x94_fogDensityFactor ? fogDensitySpeed : -fogDensitySpeed); -} +void CCameraManager::SetFogDensity(float fogDensityTarget, float fogDensitySpeed) { + x9c_fogDensityFactorTarget = fogDensityTarget; + x98_fogDensitySpeed = (x9c_fogDensityFactorTarget >= x94_fogDensityFactor ? fogDensitySpeed : -fogDensitySpeed); } +} // namespace urde diff --git a/Runtime/Camera/CCameraManager.hpp b/Runtime/Camera/CCameraManager.hpp index dbb5af48e..873919645 100644 --- a/Runtime/Camera/CCameraManager.hpp +++ b/Runtime/Camera/CCameraManager.hpp @@ -4,8 +4,7 @@ #include "zeus/CVector3f.hpp" #include "World/CGameArea.hpp" -namespace urde -{ +namespace urde { class CFirstPersonCamera; class CBallCamera; class CStateManager; @@ -17,149 +16,141 @@ struct CFinalInput; class CScriptCameraHint; class CCinematicCamera; -class CCameraManager -{ - static float sAspect; - static float sFarPlane; - static float sNearPlane; - static float sFirstPersonFOV; - static float sThirdPersonFOV; - TUniqueId x0_curCameraId; - std::vector x4_cineCameras; - std::list x14_shakers; - u32 x2c_lastShakeId = 0; - zeus::CVector3f x30_shakeOffset; - CGameArea::CAreaFog x3c_fog; - int x74_fluidCounter = 0; - TUniqueId x78_fluidId = kInvalidUniqueId; - CFirstPersonCamera* x7c_fpCamera = nullptr; - CBallCamera* x80_ballCamera = nullptr; - s16 x84_rumbleId = -1; - CInterpolationCamera* x88_interpCamera = nullptr; - float x90_rumbleCooldown = 0.f; - float x94_fogDensityFactor = 1.f; - float x98_fogDensitySpeed = 0.f; - float x9c_fogDensityFactorTarget = 1.f; +class CCameraManager { + static float sAspect; + static float sFarPlane; + static float sNearPlane; + static float sFirstPersonFOV; + static float sThirdPersonFOV; + TUniqueId x0_curCameraId; + std::vector x4_cineCameras; + std::list x14_shakers; + u32 x2c_lastShakeId = 0; + zeus::CVector3f x30_shakeOffset; + CGameArea::CAreaFog x3c_fog; + int x74_fluidCounter = 0; + TUniqueId x78_fluidId = kInvalidUniqueId; + CFirstPersonCamera* x7c_fpCamera = nullptr; + CBallCamera* x80_ballCamera = nullptr; + s16 x84_rumbleId = -1; + CInterpolationCamera* x88_interpCamera = nullptr; + float x90_rumbleCooldown = 0.f; + float x94_fogDensityFactor = 1.f; + float x98_fogDensitySpeed = 0.f; + float x9c_fogDensityFactorTarget = 1.f; - union - { - struct - { - bool xa0_24_pendingRumble : 1; - bool xa0_25_rumbling : 1; - bool xa0_26_inWater : 1; - }; - u8 _dummy1 = 0; + union { + struct { + bool xa0_24_pendingRumble : 1; + bool xa0_25_rumbling : 1; + bool xa0_26_inWater : 1; }; + u8 _dummy1 = 0; + }; - TUniqueId xa2_spindleCamId = kInvalidUniqueId; - TUniqueId xa4_pathCamId = kInvalidUniqueId; - TUniqueId xa6_camHintId = kInvalidUniqueId; - s32 xa8_hintPriority = 1000; - rstl::reserved_vector, 64> xac_cameraHints; - rstl::reserved_vector x2b0_inactiveCameraHints; - rstl::reserved_vector x334_activeCameraHints; + TUniqueId xa2_spindleCamId = kInvalidUniqueId; + TUniqueId xa4_pathCamId = kInvalidUniqueId; + TUniqueId xa6_camHintId = kInvalidUniqueId; + s32 xa8_hintPriority = 1000; + rstl::reserved_vector, 64> xac_cameraHints; + rstl::reserved_vector x2b0_inactiveCameraHints; + rstl::reserved_vector x334_activeCameraHints; - union - { - struct - { - bool x3b8_24_ : 1; - bool x3b8_25_ : 1; - }; - u8 _dummy2; + union { + struct { + bool x3b8_24_ : 1; + bool x3b8_25_ : 1; }; + u8 _dummy2; + }; - float x3bc_curFov = 60.f; + float x3bc_curFov = 60.f; - void SetPathCamera(TUniqueId id, CStateManager& mgr); - void SetSpindleCamera(TUniqueId id, CStateManager& mgr); - void RestoreHintlessCamera(CStateManager& mgr); - void InterpolateToBallCamera(const zeus::CTransform& xf, TUniqueId camId, - const zeus::CVector3f& lookPos, float maxTime, float positionSpeed, - float rotationSpeed, bool sinusoidal, CStateManager& mgr); - void SkipBallCameraCinematic(CStateManager& mgr); - void ApplyCameraHint(const CScriptCameraHint& hint, CStateManager& mgr); + void SetPathCamera(TUniqueId id, CStateManager& mgr); + void SetSpindleCamera(TUniqueId id, CStateManager& mgr); + void RestoreHintlessCamera(CStateManager& mgr); + void InterpolateToBallCamera(const zeus::CTransform& xf, TUniqueId camId, const zeus::CVector3f& lookPos, + float maxTime, float positionSpeed, float rotationSpeed, bool sinusoidal, + CStateManager& mgr); + void SkipBallCameraCinematic(CStateManager& mgr); + void ApplyCameraHint(const CScriptCameraHint& hint, CStateManager& mgr); - void EnterCinematic(CStateManager& mgr); + void EnterCinematic(CStateManager& mgr); public: - CCameraManager(TUniqueId curCameraId=kInvalidUniqueId); + CCameraManager(TUniqueId curCameraId = kInvalidUniqueId); - static float Aspect() {return sAspect;} - static float FarPlane() {return sFarPlane;} - static float NearPlane() {return sNearPlane;} - static float FirstPersonFOV() {return sFirstPersonFOV;} - static float ThirdPersonFOV() {return sThirdPersonFOV;} + static float Aspect() { return sAspect; } + static float FarPlane() { return sFarPlane; } + static float NearPlane() { return sNearPlane; } + static float FirstPersonFOV() { return sFirstPersonFOV; } + static float ThirdPersonFOV() { return sThirdPersonFOV; } - void ResetCameras(CStateManager& mgr); - void SetSpecialCameras(CFirstPersonCamera& fp, CBallCamera& ball); - bool IsInCinematicCamera() const {return x4_cineCameras.size() != 0;} - bool IsInFirstPersonCamera() const; - zeus::CVector3f GetGlobalCameraTranslation(const CStateManager& stateMgr) const; - zeus::CTransform GetCurrentCameraTransform(const CStateManager& stateMgr) const; - void RemoveCameraShaker(int id); - int AddCameraShaker(const CCameraShakeData& data, bool sfx); - void AddCinemaCamera(TUniqueId, CStateManager& stateMgr); - void RemoveCinemaCamera(TUniqueId, CStateManager&); - void SetInsideFluid(bool, TUniqueId); - void Update(float dt, CStateManager& stateMgr); - CGameCamera* GetCurrentCamera(CStateManager& stateMgr) const; - const CGameCamera* GetCurrentCamera(const CStateManager& stateMgr) const; - void SetCurrentCameraId(TUniqueId id, CStateManager& stateMgr) {x0_curCameraId = id;} - void CreateStandardCameras(CStateManager& stateMgr); - TUniqueId GetCurrentCameraId() const - { - if (x4_cineCameras.size()) - return x4_cineCameras.back(); - return x0_curCameraId; - } - TUniqueId GetLastCameraId() const - { - if (x4_cineCameras.size()) - return x4_cineCameras.back(); - return kInvalidUniqueId; - } + void ResetCameras(CStateManager& mgr); + void SetSpecialCameras(CFirstPersonCamera& fp, CBallCamera& ball); + bool IsInCinematicCamera() const { return x4_cineCameras.size() != 0; } + bool IsInFirstPersonCamera() const; + zeus::CVector3f GetGlobalCameraTranslation(const CStateManager& stateMgr) const; + zeus::CTransform GetCurrentCameraTransform(const CStateManager& stateMgr) const; + void RemoveCameraShaker(int id); + int AddCameraShaker(const CCameraShakeData& data, bool sfx); + void AddCinemaCamera(TUniqueId, CStateManager& stateMgr); + void RemoveCinemaCamera(TUniqueId, CStateManager&); + void SetInsideFluid(bool, TUniqueId); + void Update(float dt, CStateManager& stateMgr); + CGameCamera* GetCurrentCamera(CStateManager& stateMgr) const; + const CGameCamera* GetCurrentCamera(const CStateManager& stateMgr) const; + void SetCurrentCameraId(TUniqueId id, CStateManager& stateMgr) { x0_curCameraId = id; } + void CreateStandardCameras(CStateManager& stateMgr); + TUniqueId GetCurrentCameraId() const { + if (x4_cineCameras.size()) + return x4_cineCameras.back(); + return x0_curCameraId; + } + TUniqueId GetLastCameraId() const { + if (x4_cineCameras.size()) + return x4_cineCameras.back(); + return kInvalidUniqueId; + } - void SkipCinematic(CStateManager& stateMgr); + void SkipCinematic(CStateManager& stateMgr); - CFirstPersonCamera* GetFirstPersonCamera() { return x7c_fpCamera; } - CBallCamera* GetBallCamera() { return x80_ballCamera; } - CGameArea::CAreaFog& Fog() { return x3c_fog; } + CFirstPersonCamera* GetFirstPersonCamera() { return x7c_fpCamera; } + CBallCamera* GetBallCamera() { return x80_ballCamera; } + CGameArea::CAreaFog& Fog() { return x3c_fog; } - float GetCameraBobMagnitude() const; + float GetCameraBobMagnitude() const; - void UpdateCameraHints(float dt, CStateManager& mgr); - void ThinkCameras(float dt, CStateManager& mgr); - void UpdateFog(float dt, CStateManager& mgr); - void UpdateRumble(float dt, CStateManager& mgr); - void UpdateListener(CStateManager& mgr); + void UpdateCameraHints(float dt, CStateManager& mgr); + void ThinkCameras(float dt, CStateManager& mgr); + void UpdateFog(float dt, CStateManager& mgr); + void UpdateRumble(float dt, CStateManager& mgr); + void UpdateListener(CStateManager& mgr); - float CalculateFogDensity(CStateManager&, const CScriptWater*); - void SetFogDensity(float, float); + float CalculateFogDensity(CStateManager&, const CScriptWater*); + void SetFogDensity(float, float); - void ProcessInput(const CFinalInput& input, CStateManager& stateMgr); + void ProcessInput(const CFinalInput& input, CStateManager& stateMgr); - void RenderCameras(const CStateManager& mgr); - void SetupBallCamera(CStateManager& mgr); - void SetPlayerCamera(CStateManager& mgr, TUniqueId newCamId); - int GetFluidCounter() const { return x74_fluidCounter; } - bool HasBallCameraInitialPositionHint(CStateManager& mgr) const; + void RenderCameras(const CStateManager& mgr); + void SetupBallCamera(CStateManager& mgr); + void SetPlayerCamera(CStateManager& mgr, TUniqueId newCamId); + int GetFluidCounter() const { return x74_fluidCounter; } + bool HasBallCameraInitialPositionHint(CStateManager& mgr) const; - void DeleteCameraHint(TUniqueId id, CStateManager& mgr); - void AddInactiveCameraHint(TUniqueId id, CStateManager& mgr); - void AddActiveCameraHint(TUniqueId id, CStateManager& mgr); + void DeleteCameraHint(TUniqueId id, CStateManager& mgr); + void AddInactiveCameraHint(TUniqueId id, CStateManager& mgr); + void AddActiveCameraHint(TUniqueId id, CStateManager& mgr); - TUniqueId GetLastCineCameraId() const; - TUniqueId GetSpindleCameraId() const { return xa2_spindleCamId; } - TUniqueId GetPathCameraId() const { return xa4_pathCamId; } - const CCinematicCamera* GetLastCineCamera(CStateManager& mgr) const; - const CScriptCameraHint* GetCameraHint(CStateManager& mgr) const; - bool HasCameraHint(CStateManager& mgr) const; - bool IsInterpolationCameraActive() const; + TUniqueId GetLastCineCameraId() const; + TUniqueId GetSpindleCameraId() const { return xa2_spindleCamId; } + TUniqueId GetPathCameraId() const { return xa4_pathCamId; } + const CCinematicCamera* GetLastCineCamera(CStateManager& mgr) const; + const CScriptCameraHint* GetCameraHint(CStateManager& mgr) const; + bool HasCameraHint(CStateManager& mgr) const; + bool IsInterpolationCameraActive() const; - bool ShouldBypassInterpolation() { return false; } + bool ShouldBypassInterpolation() { return false; } }; -} - +} // namespace urde diff --git a/Runtime/Camera/CCameraShakeData.cpp b/Runtime/Camera/CCameraShakeData.cpp index e1a67223b..b00ec2104 100644 --- a/Runtime/Camera/CCameraShakeData.cpp +++ b/Runtime/Camera/CCameraShakeData.cpp @@ -3,207 +3,201 @@ #include "CStateManager.hpp" #include "World/CPlayer.hpp" -namespace urde -{ +namespace urde { -SCameraShakePoint SCameraShakePoint::LoadCameraShakePoint(CInputStream& in) -{ - u32 useEnvelope = ScriptLoader::LoadParameterFlags(in); - float attackTime = in.readFloatBig(); - float sustainTime = in.readFloatBig(); - float duration = in.readFloatBig(); - float magnitude = in.readFloatBig(); - return {useEnvelope != 0, attackTime, sustainTime, duration, magnitude}; +SCameraShakePoint SCameraShakePoint::LoadCameraShakePoint(CInputStream& in) { + u32 useEnvelope = ScriptLoader::LoadParameterFlags(in); + float attackTime = in.readFloatBig(); + float sustainTime = in.readFloatBig(); + float duration = in.readFloatBig(); + float magnitude = in.readFloatBig(); + return {useEnvelope != 0, attackTime, sustainTime, duration, magnitude}; } -CCameraShakerComponent CCameraShakerComponent::LoadNewCameraShakerComponent(CInputStream& in) -{ - u32 useModulation = ScriptLoader::LoadParameterFlags(in); - SCameraShakePoint am = SCameraShakePoint::LoadCameraShakePoint(in); - SCameraShakePoint fm = SCameraShakePoint::LoadCameraShakePoint(in); - return {useModulation != 0, am, fm}; +CCameraShakerComponent CCameraShakerComponent::LoadNewCameraShakerComponent(CInputStream& in) { + u32 useModulation = ScriptLoader::LoadParameterFlags(in); + SCameraShakePoint am = SCameraShakePoint::LoadCameraShakePoint(in); + SCameraShakePoint fm = SCameraShakePoint::LoadCameraShakePoint(in); + return {useModulation != 0, am, fm}; } CCameraShakeData::CCameraShakeData(float duration, float sfxDist, u32 flags, const zeus::CVector3f& sfxPos, const CCameraShakerComponent& shaker1, const CCameraShakerComponent& shaker2, const CCameraShakerComponent& shaker3) -: x0_duration(duration), x8_shakerX(shaker1), x44_shakerY(shaker2), x80_shakerZ(shaker3), - xc0_flags(flags), xc4_sfxPos(sfxPos), xd0_sfxDist(sfxDist) -{} +: x0_duration(duration) +, x8_shakerX(shaker1) +, x44_shakerY(shaker2) +, x80_shakerZ(shaker3) +, xc0_flags(flags) +, xc4_sfxPos(sfxPos) +, xd0_sfxDist(sfxDist) {} CCameraShakeData::CCameraShakeData(float duration, float magnitude) : CCameraShakeData(duration, 100.f, 0, zeus::CVector3f::skZero, CCameraShakerComponent{}, CCameraShakerComponent{}, - CCameraShakerComponent{1, - SCameraShakePoint{0, 0.25f * duration, 0.f, 0.75f * duration, magnitude}, - SCameraShakePoint{1, 0.f, 0.f, 0.5f * duration, 2.f}}) -{} + CCameraShakerComponent{1, SCameraShakePoint{0, 0.25f * duration, 0.f, 0.75f * duration, magnitude}, + SCameraShakePoint{1, 0.f, 0.f, 0.5f * duration, 2.f}}) {} -CCameraShakeData::CCameraShakeData(CInputStream& in) -{ - in.readUint32Big(); - in.readFloatBig(); - in.readFloatBig(); - in.readFloatBig(); - in.readFloatBig(); - in.readFloatBig(); - in.readFloatBig(); - in.readBool(); - BuildProjectileCameraShake(0.5f, 0.75f); +CCameraShakeData::CCameraShakeData(CInputStream& in) { + in.readUint32Big(); + in.readFloatBig(); + in.readFloatBig(); + in.readFloatBig(); + in.readFloatBig(); + in.readFloatBig(); + in.readFloatBig(); + in.readBool(); + BuildProjectileCameraShake(0.5f, 0.75f); } -CCameraShakeData CCameraShakeData::BuildLandingCameraShakeData(float duration, float magnitude) -{ - return {duration, 100.f, 0, zeus::CVector3f::skZero, - CCameraShakerComponent(1, - SCameraShakePoint(0, 0.15f * duration, 0.f, 0.85f * duration, magnitude), - SCameraShakePoint(1, 0.f, 0.f, 0.4f * duration, 1.5f)), - CCameraShakerComponent(), - CCameraShakerComponent(1, - SCameraShakePoint(0, 0.25f * duration, 0.f, 0.75f * duration, magnitude), - SCameraShakePoint(1, 0.f, 0.f, 0.5f * duration, 2.f))}; +CCameraShakeData CCameraShakeData::BuildLandingCameraShakeData(float duration, float magnitude) { + return {duration, + 100.f, + 0, + zeus::CVector3f::skZero, + CCameraShakerComponent(1, SCameraShakePoint(0, 0.15f * duration, 0.f, 0.85f * duration, magnitude), + SCameraShakePoint(1, 0.f, 0.f, 0.4f * duration, 1.5f)), + CCameraShakerComponent(), + CCameraShakerComponent(1, SCameraShakePoint(0, 0.25f * duration, 0.f, 0.75f * duration, magnitude), + SCameraShakePoint(1, 0.f, 0.f, 0.5f * duration, 2.f))}; } -CCameraShakeData CCameraShakeData::BuildProjectileCameraShake(float duration, float magnitude) -{ - return {duration, 100.f, 0, zeus::CVector3f::skZero, - CCameraShakerComponent(1, - SCameraShakePoint(0, 0.f, 0.f, duration, magnitude), - SCameraShakePoint(1, 0.f, 0.f, 0.5f * duration, 3.f)), - CCameraShakerComponent(), - CCameraShakerComponent()}; +CCameraShakeData CCameraShakeData::BuildProjectileCameraShake(float duration, float magnitude) { + return {duration, + 100.f, + 0, + zeus::CVector3f::skZero, + CCameraShakerComponent(1, SCameraShakePoint(0, 0.f, 0.f, duration, magnitude), + SCameraShakePoint(1, 0.f, 0.f, 0.5f * duration, 3.f)), + CCameraShakerComponent(), + CCameraShakerComponent()}; } CCameraShakeData CCameraShakeData::BuildMissileCameraShake(float duration, float magnitude, float sfxDistance, - const zeus::CVector3f& sfxPos) -{ - CCameraShakeData ret(duration, magnitude); - ret.SetSfxPositionAndDistance(sfxPos, sfxDistance); - return ret; + const zeus::CVector3f& sfxPos) { + CCameraShakeData ret(duration, magnitude); + ret.SetSfxPositionAndDistance(sfxPos, sfxDistance); + return ret; } -CCameraShakeData CCameraShakeData::BuildPhazonCameraShakeData(float duration, float magnitude) -{ - return {duration, 100.f, 0, zeus::CVector3f::skZero, - CCameraShakerComponent(1, - SCameraShakePoint(0, 0.15f * duration, 0.f, 0.25f * duration, magnitude), - SCameraShakePoint(1, 0.f, 0.f, 0.4f * duration, 0.3f)), - CCameraShakerComponent(), - CCameraShakerComponent(1, - SCameraShakePoint(0, 0.25f * duration, 0.f, 0.25f * duration, magnitude), - SCameraShakePoint(1, 0.f, 0.f, 0.5f * duration, 0.5f))}; +CCameraShakeData CCameraShakeData::BuildPhazonCameraShakeData(float duration, float magnitude) { + return {duration, + 100.f, + 0, + zeus::CVector3f::skZero, + CCameraShakerComponent(1, SCameraShakePoint(0, 0.15f * duration, 0.f, 0.25f * duration, magnitude), + SCameraShakePoint(1, 0.f, 0.f, 0.4f * duration, 0.3f)), + CCameraShakerComponent(), + CCameraShakerComponent(1, SCameraShakePoint(0, 0.25f * duration, 0.f, 0.25f * duration, magnitude), + SCameraShakePoint(1, 0.f, 0.f, 0.5f * duration, 0.5f))}; } -CCameraShakeData CCameraShakeData::BuildPatternedExplodeShakeData(float duration, float magnitude) -{ - return {duration, 100.f, 0, zeus::CVector3f::skZero, - CCameraShakerComponent(1, - SCameraShakePoint(0, 0.25f * duration, 0.f, 0.75f * duration, magnitude), - SCameraShakePoint(1, 0.f, 0.f, 0.5f * duration, 2.0f)), - CCameraShakerComponent(), - CCameraShakerComponent()}; +CCameraShakeData CCameraShakeData::BuildPatternedExplodeShakeData(float duration, float magnitude) { + return {duration, + 100.f, + 0, + zeus::CVector3f::skZero, + CCameraShakerComponent(1, SCameraShakePoint(0, 0.25f * duration, 0.f, 0.75f * duration, magnitude), + SCameraShakePoint(1, 0.f, 0.f, 0.5f * duration, 2.0f)), + CCameraShakerComponent(), + CCameraShakerComponent()}; } CCameraShakeData CCameraShakeData::BuildPatternedExplodeShakeData(const zeus::CVector3f& pos, float duration, - float magnitude, float distance) -{ - CCameraShakeData shakeData = CCameraShakeData::BuildPatternedExplodeShakeData(duration, magnitude); - shakeData.SetSfxPositionAndDistance(pos, distance); - return shakeData; + float magnitude, float distance) { + CCameraShakeData shakeData = CCameraShakeData::BuildPatternedExplodeShakeData(duration, magnitude); + shakeData.SetSfxPositionAndDistance(pos, distance); + return shakeData; } -void SCameraShakePoint::Update(float curTime) -{ - float offTimePoint = xc_attackTime + x10_sustainTime; - float factor = 1.f; - if (curTime < xc_attackTime && xc_attackTime > 0.f) - factor = zeus::clamp(0.f, curTime / xc_attackTime, 1.f); - if (curTime >= offTimePoint && x14_duration > 0.f) - factor = 1.f - (curTime - offTimePoint) / x14_duration; - x4_value = x8_magnitude * factor; +void SCameraShakePoint::Update(float curTime) { + float offTimePoint = xc_attackTime + x10_sustainTime; + float factor = 1.f; + if (curTime < xc_attackTime && xc_attackTime > 0.f) + factor = zeus::clamp(0.f, curTime / xc_attackTime, 1.f); + if (curTime >= offTimePoint && x14_duration > 0.f) + factor = 1.f - (curTime - offTimePoint) / x14_duration; + x4_value = x8_magnitude * factor; } -void CCameraShakerComponent::Update(float curTime, float duration, float distAtt) -{ - if (std::fabs(duration) < 0.00001f || !x4_useModulation) - { - x38_value = 0.f; - return; - } +void CCameraShakerComponent::Update(float curTime, float duration, float distAtt) { + if (std::fabs(duration) < 0.00001f || !x4_useModulation) { + x38_value = 0.f; + return; + } - x20_fm.Update(curTime); - float freq = 1.f + x20_fm.GetValue(); - x8_am.Update(curTime); - x38_value = x8_am.GetValue() * std::sin(2.f * M_PIF * (duration - curTime) * freq); - x38_value *= distAtt; + x20_fm.Update(curTime); + float freq = 1.f + x20_fm.GetValue(); + x8_am.Update(curTime); + x38_value = x8_am.GetValue() * std::sin(2.f * M_PIF * (duration - curTime) * freq); + x38_value *= distAtt; } -void CCameraShakeData::Update(float dt, CStateManager& mgr) -{ - x4_curTime += dt; - float distAtt = 1.f; - if (xc0_flags & 0x1) - distAtt = 1.f - zeus::clamp(0.f, (xc4_sfxPos - mgr.GetPlayer().GetTranslation()).magnitude() / xd0_sfxDist, 1.f); - x8_shakerX.Update(x4_curTime, x0_duration, distAtt); - x44_shakerY.Update(x4_curTime, x0_duration, distAtt); - x80_shakerZ.Update(x4_curTime, x0_duration, distAtt); +void CCameraShakeData::Update(float dt, CStateManager& mgr) { + x4_curTime += dt; + float distAtt = 1.f; + if (xc0_flags & 0x1) + distAtt = 1.f - zeus::clamp(0.f, (xc4_sfxPos - mgr.GetPlayer().GetTranslation()).magnitude() / xd0_sfxDist, 1.f); + x8_shakerX.Update(x4_curTime, x0_duration, distAtt); + x44_shakerY.Update(x4_curTime, x0_duration, distAtt); + x80_shakerZ.Update(x4_curTime, x0_duration, distAtt); } -zeus::CVector3f CCameraShakeData::GetPoint() const -{ - return {x8_shakerX.GetValue(), x44_shakerY.GetValue(), x80_shakerZ.GetValue()}; +zeus::CVector3f CCameraShakeData::GetPoint() const { + return {x8_shakerX.GetValue(), x44_shakerY.GetValue(), x80_shakerZ.GetValue()}; } -float CCameraShakeData::GetMaxAMComponent() const -{ - float ret = 0.f; - if (x8_shakerX.x4_useModulation) - ret = x8_shakerX.x8_am.GetValue(); - if (x44_shakerY.x4_useModulation) - ret = std::max(ret, x44_shakerY.x8_am.GetValue()); - if (x80_shakerZ.x4_useModulation) - ret = std::max(ret, x80_shakerZ.x8_am.GetValue()); - return ret; +float CCameraShakeData::GetMaxAMComponent() const { + float ret = 0.f; + if (x8_shakerX.x4_useModulation) + ret = x8_shakerX.x8_am.GetValue(); + if (x44_shakerY.x4_useModulation) + ret = std::max(ret, x44_shakerY.x8_am.GetValue()); + if (x80_shakerZ.x4_useModulation) + ret = std::max(ret, x80_shakerZ.x8_am.GetValue()); + return ret; } -float CCameraShakeData::GetMaxFMComponent() const -{ - float ret = 0.f; - if (x8_shakerX.x4_useModulation) - ret = x8_shakerX.x20_fm.GetValue(); - if (x44_shakerY.x4_useModulation) - ret = std::max(ret, x44_shakerY.x20_fm.GetValue()); - if (x80_shakerZ.x4_useModulation) - ret = std::max(ret, x80_shakerZ.x20_fm.GetValue()); - return ret; +float CCameraShakeData::GetMaxFMComponent() const { + float ret = 0.f; + if (x8_shakerX.x4_useModulation) + ret = x8_shakerX.x20_fm.GetValue(); + if (x44_shakerY.x4_useModulation) + ret = std::max(ret, x44_shakerY.x20_fm.GetValue()); + if (x80_shakerZ.x4_useModulation) + ret = std::max(ret, x80_shakerZ.x20_fm.GetValue()); + return ret; } -CCameraShakeData CCameraShakeData::LoadCameraShakeData(CInputStream& in) -{ - float xMag = in.readFloatBig(); - in.readFloatBig(); - float yMag = in.readFloatBig(); - in.readFloatBig(); - float zMag = in.readFloatBig(); - in.readFloatBig(); - float duration = in.readFloatBig(); +CCameraShakeData CCameraShakeData::LoadCameraShakeData(CInputStream& in) { + float xMag = in.readFloatBig(); + in.readFloatBig(); + float yMag = in.readFloatBig(); + in.readFloatBig(); + float zMag = in.readFloatBig(); + in.readFloatBig(); + float duration = in.readFloatBig(); - SCameraShakePoint xAM(0, 0.f, 0.f, duration, 2.f * xMag); - SCameraShakePoint yAM(0, 0.f, 0.f, duration, 2.f * yMag); - SCameraShakePoint zAM(0, 0.f, 0.f, duration, 2.f * zMag); - SCameraShakePoint xFM(0, 0.f, 0.f, 0.5f * duration, 3.f); - SCameraShakePoint yFM(0, 0.f, 0.f, 0.5f * duration, 0.f); - SCameraShakePoint zFM(0, 0.f, 0.f, 0.5f * duration, 3.f); + SCameraShakePoint xAM(0, 0.f, 0.f, duration, 2.f * xMag); + SCameraShakePoint yAM(0, 0.f, 0.f, duration, 2.f * yMag); + SCameraShakePoint zAM(0, 0.f, 0.f, duration, 2.f * zMag); + SCameraShakePoint xFM(0, 0.f, 0.f, 0.5f * duration, 3.f); + SCameraShakePoint yFM(0, 0.f, 0.f, 0.5f * duration, 0.f); + SCameraShakePoint zFM(0, 0.f, 0.f, 0.5f * duration, 3.f); - CCameraShakerComponent shakerX(1, xAM, xFM); - CCameraShakerComponent shakerY; - CCameraShakerComponent shakerZ(1, zAM, zFM); + CCameraShakerComponent shakerX(1, xAM, xFM); + CCameraShakerComponent shakerY; + CCameraShakerComponent shakerZ(1, zAM, zFM); - return {duration, 100.f, 0, zeus::CVector3f::skZero, shakerX, shakerY, shakerZ}; + return {duration, 100.f, 0, zeus::CVector3f::skZero, shakerX, shakerY, shakerZ}; } -const CCameraShakeData CCameraShakeData::skChargedShotCameraShakeData = - {0.3f, 100.f, 0, zeus::CVector3f::skZero, CCameraShakerComponent(), - CCameraShakerComponent(1, {0, 0.f, 0.f, 0.3f, -1.f}, {1, 0.f, 0.f, 0.05f, 0.3f}), - CCameraShakerComponent()}; +const CCameraShakeData CCameraShakeData::skChargedShotCameraShakeData = { + 0.3f, + 100.f, + 0, + zeus::CVector3f::skZero, + CCameraShakerComponent(), + CCameraShakerComponent(1, {0, 0.f, 0.f, 0.3f, -1.f}, {1, 0.f, 0.f, 0.05f, 0.3f}), + CCameraShakerComponent()}; -} +} // namespace urde diff --git a/Runtime/Camera/CCameraShakeData.hpp b/Runtime/Camera/CCameraShakeData.hpp index ed128312d..d7d1fa20a 100644 --- a/Runtime/Camera/CCameraShakeData.hpp +++ b/Runtime/Camera/CCameraShakeData.hpp @@ -3,82 +3,84 @@ #include "zeus/CVector3f.hpp" #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CRandom16; class CStateManager; -struct SCameraShakePoint -{ - friend class CCameraShakeData; - bool x0_useEnvelope = false; - float x4_value = 0.f; - float x8_magnitude = 0.f; - float xc_attackTime = 0.f; - float x10_sustainTime = 0.f; - float x14_duration = 0.f; - SCameraShakePoint() = default; - SCameraShakePoint(bool useEnvelope, float attackTime, float sustainTime, float duration, float magnitude) - : x0_useEnvelope(useEnvelope), x8_magnitude(magnitude), xc_attackTime(attackTime), - x10_sustainTime(sustainTime), x14_duration(duration) {} - float GetValue() const { return x0_useEnvelope ? x8_magnitude : x4_value; } - static SCameraShakePoint LoadCameraShakePoint(CInputStream& in); - void Update(float curTime); +struct SCameraShakePoint { + friend class CCameraShakeData; + bool x0_useEnvelope = false; + float x4_value = 0.f; + float x8_magnitude = 0.f; + float xc_attackTime = 0.f; + float x10_sustainTime = 0.f; + float x14_duration = 0.f; + SCameraShakePoint() = default; + SCameraShakePoint(bool useEnvelope, float attackTime, float sustainTime, float duration, float magnitude) + : x0_useEnvelope(useEnvelope) + , x8_magnitude(magnitude) + , xc_attackTime(attackTime) + , x10_sustainTime(sustainTime) + , x14_duration(duration) {} + float GetValue() const { return x0_useEnvelope ? x8_magnitude : x4_value; } + static SCameraShakePoint LoadCameraShakePoint(CInputStream& in); + void Update(float curTime); }; -class CCameraShakerComponent -{ - friend class CCameraShakeData; - bool x4_useModulation = false; - SCameraShakePoint x8_am, x20_fm; - float x38_value = 0.f; -public: - CCameraShakerComponent() = default; - CCameraShakerComponent(bool useModulation, const SCameraShakePoint& am, const SCameraShakePoint& fm) - : x4_useModulation(useModulation), x8_am(am), x20_fm(fm) {} - static CCameraShakerComponent LoadNewCameraShakerComponent(CInputStream& in); - void Update(float curTime, float duration, float distAtt); - float GetValue() const { return x38_value; } -}; - -class CCameraShakeData -{ - friend class CCameraManager; - float x0_duration; - float x4_curTime = 0.f; - CCameraShakerComponent x8_shakerX; - CCameraShakerComponent x44_shakerY; - CCameraShakerComponent x80_shakerZ; - u32 xbc_shakerId = 0; - u32 xc0_flags; // 0x1: positional sfx - zeus::CVector3f xc4_sfxPos; - float xd0_sfxDist; +class CCameraShakerComponent { + friend class CCameraShakeData; + bool x4_useModulation = false; + SCameraShakePoint x8_am, x20_fm; + float x38_value = 0.f; public: - static const CCameraShakeData skChargedShotCameraShakeData; - CCameraShakeData(float duration, float sfxDist, u32 flags, const zeus::CVector3f& sfxPos, - const CCameraShakerComponent& shaker1, const CCameraShakerComponent& shaker2, - const CCameraShakerComponent& shaker3); - CCameraShakeData(float duration, float magnitude); - CCameraShakeData(CInputStream&); - static CCameraShakeData BuildLandingCameraShakeData(float duration, float magnitude); - static CCameraShakeData BuildProjectileCameraShake(float duration, float magnitude); - static CCameraShakeData BuildMissileCameraShake(float duration, float magnitude, float sfxDistance, - const zeus::CVector3f& sfxPos); - static CCameraShakeData BuildPhazonCameraShakeData(float duration, float magnitude); - static CCameraShakeData BuildPatternedExplodeShakeData(float duration, float magnitude); - static CCameraShakeData BuildPatternedExplodeShakeData(const zeus::CVector3f& pos, float duration, - float magnitude, float distance); - void Update(float dt, CStateManager& mgr); - zeus::CVector3f GetPoint() const; - float GetMaxAMComponent() const; - float GetMaxFMComponent() const; - void SetShakerId(u32 id) { xbc_shakerId = id; } - u32 GetShakerId() const { return xbc_shakerId; } - static CCameraShakeData LoadCameraShakeData(CInputStream& in); - void SetSfxPositionAndDistance(const zeus::CVector3f& pos, float f2) - { xc0_flags |= 0x1; xc4_sfxPos = pos; xd0_sfxDist = f2; } + CCameraShakerComponent() = default; + CCameraShakerComponent(bool useModulation, const SCameraShakePoint& am, const SCameraShakePoint& fm) + : x4_useModulation(useModulation), x8_am(am), x20_fm(fm) {} + static CCameraShakerComponent LoadNewCameraShakerComponent(CInputStream& in); + void Update(float curTime, float duration, float distAtt); + float GetValue() const { return x38_value; } }; -} +class CCameraShakeData { + friend class CCameraManager; + float x0_duration; + float x4_curTime = 0.f; + CCameraShakerComponent x8_shakerX; + CCameraShakerComponent x44_shakerY; + CCameraShakerComponent x80_shakerZ; + u32 xbc_shakerId = 0; + u32 xc0_flags; // 0x1: positional sfx + zeus::CVector3f xc4_sfxPos; + float xd0_sfxDist; +public: + static const CCameraShakeData skChargedShotCameraShakeData; + CCameraShakeData(float duration, float sfxDist, u32 flags, const zeus::CVector3f& sfxPos, + const CCameraShakerComponent& shaker1, const CCameraShakerComponent& shaker2, + const CCameraShakerComponent& shaker3); + CCameraShakeData(float duration, float magnitude); + CCameraShakeData(CInputStream&); + static CCameraShakeData BuildLandingCameraShakeData(float duration, float magnitude); + static CCameraShakeData BuildProjectileCameraShake(float duration, float magnitude); + static CCameraShakeData BuildMissileCameraShake(float duration, float magnitude, float sfxDistance, + const zeus::CVector3f& sfxPos); + static CCameraShakeData BuildPhazonCameraShakeData(float duration, float magnitude); + static CCameraShakeData BuildPatternedExplodeShakeData(float duration, float magnitude); + static CCameraShakeData BuildPatternedExplodeShakeData(const zeus::CVector3f& pos, float duration, float magnitude, + float distance); + void Update(float dt, CStateManager& mgr); + zeus::CVector3f GetPoint() const; + float GetMaxAMComponent() const; + float GetMaxFMComponent() const; + void SetShakerId(u32 id) { xbc_shakerId = id; } + u32 GetShakerId() const { return xbc_shakerId; } + static CCameraShakeData LoadCameraShakeData(CInputStream& in); + void SetSfxPositionAndDistance(const zeus::CVector3f& pos, float f2) { + xc0_flags |= 0x1; + xc4_sfxPos = pos; + xd0_sfxDist = f2; + } +}; + +} // namespace urde diff --git a/Runtime/Camera/CCameraSpline.cpp b/Runtime/Camera/CCameraSpline.cpp index 00921923d..f83fbfbef 100644 --- a/Runtime/Camera/CCameraSpline.cpp +++ b/Runtime/Camera/CCameraSpline.cpp @@ -3,465 +3,386 @@ #include "World/CScriptCameraWaypoint.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CCameraSpline::CCameraSpline(bool closedLoop) : x48_closedLoop(closedLoop) {} -void CCameraSpline::CalculateKnots(TUniqueId cameraId, const std::vector& connections, CStateManager& mgr) -{ - const SConnection* lastConn = nullptr; +void CCameraSpline::CalculateKnots(TUniqueId cameraId, const std::vector& connections, + CStateManager& mgr) { + const SConnection* lastConn = nullptr; - for (const SConnection& conn : connections) - { - if (conn.x0_state == EScriptObjectState::CameraPath && conn.x4_msg == EScriptObjectMessage::Follow) - lastConn = &conn; + for (const SConnection& conn : connections) { + if (conn.x0_state == EScriptObjectState::CameraPath && conn.x4_msg == EScriptObjectMessage::Follow) + lastConn = &conn; + } + + if (lastConn) { + TCastToPtr waypoint = mgr.ObjectById(mgr.GetIdForScript(lastConn->x8_objId)); + x14_wpTracker.clear(); + x14_wpTracker.reserve(4); + while (waypoint) { + auto search = std::find_if(x14_wpTracker.begin(), x14_wpTracker.end(), + [&waypoint](const auto& a) { return a == waypoint->GetUniqueId(); }); + if (search == x14_wpTracker.end()) { + x14_wpTracker.push_back(waypoint->GetUniqueId()); + waypoint = mgr.ObjectById(waypoint->GetRandomNextWaypointId(mgr)); + } } + Reset(x14_wpTracker.size()); + x14_wpTracker.clear(); - if (lastConn) - { - TCastToPtr waypoint = mgr.ObjectById(mgr.GetIdForScript(lastConn->x8_objId)); - x14_wpTracker.clear(); - x14_wpTracker.reserve(4); - while (waypoint) - { - auto search = std::find_if(x14_wpTracker.begin(), x14_wpTracker.end(), - [&waypoint](const auto& a) { return a == waypoint->GetUniqueId(); }); - if (search == x14_wpTracker.end()) - { - x14_wpTracker.push_back(waypoint->GetUniqueId()); - waypoint = mgr.ObjectById(waypoint->GetRandomNextWaypointId(mgr)); - } - } - Reset(x14_wpTracker.size()); - x14_wpTracker.clear(); - - waypoint = mgr.ObjectById(mgr.GetIdForScript(lastConn->x8_objId)); - while (waypoint) - { - auto search = std::find_if(x14_wpTracker.begin(), x14_wpTracker.end(), - [&waypoint](const auto& a) { return a == waypoint->GetUniqueId(); }); - if (search == x14_wpTracker.end()) - { - x14_wpTracker.push_back(waypoint->GetUniqueId()); - AddKnot(waypoint->GetTranslation(), waypoint->GetTransform().basis[1]); - waypoint = mgr.ObjectById(waypoint->GetRandomNextWaypointId(mgr)); - } - } + waypoint = mgr.ObjectById(mgr.GetIdForScript(lastConn->x8_objId)); + while (waypoint) { + auto search = std::find_if(x14_wpTracker.begin(), x14_wpTracker.end(), + [&waypoint](const auto& a) { return a == waypoint->GetUniqueId(); }); + if (search == x14_wpTracker.end()) { + x14_wpTracker.push_back(waypoint->GetUniqueId()); + AddKnot(waypoint->GetTranslation(), waypoint->GetTransform().basis[1]); + waypoint = mgr.ObjectById(waypoint->GetRandomNextWaypointId(mgr)); + } } + } } -void CCameraSpline::Initialize(TUniqueId camId, const std::vector& connections, CStateManager& mgr) -{ - CalculateKnots(camId, connections, mgr); - x44_length = CalculateSplineLength(); +void CCameraSpline::Initialize(TUniqueId camId, const std::vector& connections, CStateManager& mgr) { + CalculateKnots(camId, connections, mgr); + x44_length = CalculateSplineLength(); } -void CCameraSpline::Reset(int size) -{ - x4_positions.clear(); - x24_t.clear(); - x34_directions.clear(); - if (size != 0) - { - x4_positions.reserve(size); - x24_t.reserve(size); - x34_directions.reserve(size); - } +void CCameraSpline::Reset(int size) { + x4_positions.clear(); + x24_t.clear(); + x34_directions.clear(); + if (size != 0) { + x4_positions.reserve(size); + x24_t.reserve(size); + x34_directions.reserve(size); + } } -void CCameraSpline::AddKnot(const zeus::CVector3f& pos, const zeus::CVector3f& dir) -{ - x4_positions.push_back(pos); - x34_directions.push_back(dir); +void CCameraSpline::AddKnot(const zeus::CVector3f& pos, const zeus::CVector3f& dir) { + x4_positions.push_back(pos); + x34_directions.push_back(dir); } -void CCameraSpline::SetKnotPosition(int idx, const zeus::CVector3f& pos) -{ - if (idx >= x4_positions.size()) - return; - x4_positions[idx] = pos; +void CCameraSpline::SetKnotPosition(int idx, const zeus::CVector3f& pos) { + if (idx >= x4_positions.size()) + return; + x4_positions[idx] = pos; } -const zeus::CVector3f& CCameraSpline::GetKnotPosition(int idx) const -{ - if (idx >= x4_positions.size()) - return zeus::CVector3f::skZero; - return x4_positions[idx]; +const zeus::CVector3f& CCameraSpline::GetKnotPosition(int idx) const { + if (idx >= x4_positions.size()) + return zeus::CVector3f::skZero; + return x4_positions[idx]; } -float CCameraSpline::GetKnotT(int idx) const -{ - if (idx >= x4_positions.size()) - return 0.f; - return x24_t[idx]; -} - -float CCameraSpline::CalculateSplineLength() -{ - float ret = 0.f; - x24_t.clear(); - if (x4_positions.size() > 0) - { - zeus::CVector3f prevPoint = x4_positions[0]; - float tDiv = 1.f / float(x4_positions.size() - 1); - for (int i=0 ; i= x4_positions.size()) return 0.f; + return x24_t[idx]; +} + +float CCameraSpline::CalculateSplineLength() { + float ret = 0.f; + x24_t.clear(); + if (x4_positions.size() > 0) { + zeus::CVector3f prevPoint = x4_positions[0]; + float tDiv = 1.f / float(x4_positions.size() - 1); + for (int i = 0; i < x4_positions.size(); ++i) { + float subT = 0.f; + float baseT = i * tDiv; + x24_t.push_back(ret); + while (subT <= tDiv) { + subT += tDiv * 0.03125f; + zeus::CVector3f nextPoint = GetInterpolatedSplinePointByTime(baseT + subT, 1.f); + zeus::CVector3f delta = nextPoint - prevPoint; + if (delta.canBeNormalized()) { + prevPoint = nextPoint; + ret += delta.magnitude(); + } + } + } + + x24_t.push_back(ret); + if (x48_closedLoop) { + zeus::CVector3f delta = x4_positions[0] - x4_positions[x4_positions.size() - 1]; + if (delta.canBeNormalized()) + ret += delta.magnitude(); + } + + return ret; + } + return 0.f; } bool CCameraSpline::GetSurroundingPoints(int idx, rstl::reserved_vector& positions, - rstl::reserved_vector& directions) const -{ - if (x4_positions.size() <= 3 || idx < 0 || idx >= x4_positions.size()) - return false; + rstl::reserved_vector& directions) const { + if (x4_positions.size() <= 3 || idx < 0 || idx >= x4_positions.size()) + return false; - if (idx > 0) - { - positions.push_back(x4_positions[idx - 1]); - directions.push_back(x34_directions[idx - 1]); - } - else if (x48_closedLoop) - { - positions.push_back(x4_positions[x4_positions.size() - 1]); - directions.push_back(x34_directions[x4_positions.size() - 1]); - } - else - { - positions.push_back(x4_positions[0] - (x4_positions[1] - x4_positions[0])); - directions.push_back(x34_directions[0]); - } + if (idx > 0) { + positions.push_back(x4_positions[idx - 1]); + directions.push_back(x34_directions[idx - 1]); + } else if (x48_closedLoop) { + positions.push_back(x4_positions[x4_positions.size() - 1]); + directions.push_back(x34_directions[x4_positions.size() - 1]); + } else { + positions.push_back(x4_positions[0] - (x4_positions[1] - x4_positions[0])); + directions.push_back(x34_directions[0]); + } - positions.push_back(x4_positions[idx]); - directions.push_back(x34_directions[idx]); + positions.push_back(x4_positions[idx]); + directions.push_back(x34_directions[idx]); - if (idx + 1 >= x4_positions.size()) - { - if (x48_closedLoop) - { - positions.push_back(x4_positions[idx - x4_positions.size()]); - directions.push_back(x34_directions[idx - x4_positions.size()]); - } - else - { - positions.push_back(x4_positions[x4_positions.size() - 1] - - (x4_positions[x4_positions.size() - 2] - x4_positions[x4_positions.size() - 1])); - directions.push_back(x34_directions[x4_positions.size() - 1]); - } - } - else - { - positions.push_back(x4_positions[idx + 1]); - directions.push_back(x34_directions[idx + 1]); + if (idx + 1 >= x4_positions.size()) { + if (x48_closedLoop) { + positions.push_back(x4_positions[idx - x4_positions.size()]); + directions.push_back(x34_directions[idx - x4_positions.size()]); + } else { + positions.push_back(x4_positions[x4_positions.size() - 1] - + (x4_positions[x4_positions.size() - 2] - x4_positions[x4_positions.size() - 1])); + directions.push_back(x34_directions[x4_positions.size() - 1]); } + } else { + positions.push_back(x4_positions[idx + 1]); + directions.push_back(x34_directions[idx + 1]); + } - if (idx + 2 >= x4_positions.size()) - { - if (x48_closedLoop) - { - positions.push_back(x4_positions[idx + 2 - x4_positions.size()]); - directions.push_back(x34_directions[idx + 2 - x4_positions.size()]); - } - else - { - positions.push_back(x4_positions[x4_positions.size() - 1] - - (x4_positions[x4_positions.size() - 2] - x4_positions[x4_positions.size() - 1])); - directions.push_back(x34_directions[x4_positions.size() - 1]); - } - } - else - { - positions.push_back(x4_positions[idx + 2]); - directions.push_back(x34_directions[idx + 2]); + if (idx + 2 >= x4_positions.size()) { + if (x48_closedLoop) { + positions.push_back(x4_positions[idx + 2 - x4_positions.size()]); + directions.push_back(x34_directions[idx + 2 - x4_positions.size()]); + } else { + positions.push_back(x4_positions[x4_positions.size() - 1] - + (x4_positions[x4_positions.size() - 2] - x4_positions[x4_positions.size() - 1])); + directions.push_back(x34_directions[x4_positions.size() - 1]); } + } else { + positions.push_back(x4_positions[idx + 2]); + directions.push_back(x34_directions[idx + 2]); + } - return true; + return true; } -zeus::CTransform CCameraSpline::GetInterpolatedSplinePointByLength(float pos) const -{ - if (x4_positions.empty()) - return zeus::CTransform(); - - int baseIdx = 0; - int i; - for (i=1 ; i pos) - { - baseIdx = i - 1; - break; - } - } - - if (i == x4_positions.size()) - baseIdx = i - 1; - - if (pos < 0.f) - baseIdx = 0; - - if (pos >= x44_length) - { - if (x48_closedLoop) - { - pos -= x44_length; - baseIdx = 0; - } - else - { - baseIdx = x4_positions.size() - 2; - pos = x44_length; - } - } - - float range; - if (baseIdx == x4_positions.size() - 1) - { - if (x48_closedLoop) - range = x44_length - x24_t[baseIdx]; - else - range = x44_length - x24_t[x4_positions.size() - 2]; - } - else - { - range = x24_t[baseIdx + 1] - x24_t[baseIdx]; - } - - float t = zeus::clamp(0.f, (pos - x24_t[baseIdx]) / range, 1.f); - - rstl::reserved_vector positions; - rstl::reserved_vector directions; - if (GetSurroundingPoints(baseIdx, positions, directions)) - { - float f1 = zeus::clamp(-1.f, directions[1].dot(directions[2]), 1.f); - if (f1 >= 1.f) - { - zeus::CTransform ret = zeus::lookAt(zeus::CVector3f::skZero, directions[2]); - ret.origin = zeus::getCatmullRomSplinePoint(positions[0], positions[1], positions[2], positions[3], t); - return ret; - } - else - { - zeus::CTransform ret = zeus::lookAt(zeus::CVector3f::skZero, - zeus::CQuaternion::lookAt(directions[1], directions[2], std::acos(f1) * t).transform(directions[1])); - ret.origin = zeus::getCatmullRomSplinePoint(positions[0], positions[1], positions[2], positions[3], t); - return ret; - } - } - +zeus::CTransform CCameraSpline::GetInterpolatedSplinePointByLength(float pos) const { + if (x4_positions.empty()) return zeus::CTransform(); + + int baseIdx = 0; + int i; + for (i = 1; i < x4_positions.size(); ++i) { + if (x24_t[i] > pos) { + baseIdx = i - 1; + break; + } + } + + if (i == x4_positions.size()) + baseIdx = i - 1; + + if (pos < 0.f) + baseIdx = 0; + + if (pos >= x44_length) { + if (x48_closedLoop) { + pos -= x44_length; + baseIdx = 0; + } else { + baseIdx = x4_positions.size() - 2; + pos = x44_length; + } + } + + float range; + if (baseIdx == x4_positions.size() - 1) { + if (x48_closedLoop) + range = x44_length - x24_t[baseIdx]; + else + range = x44_length - x24_t[x4_positions.size() - 2]; + } else { + range = x24_t[baseIdx + 1] - x24_t[baseIdx]; + } + + float t = zeus::clamp(0.f, (pos - x24_t[baseIdx]) / range, 1.f); + + rstl::reserved_vector positions; + rstl::reserved_vector directions; + if (GetSurroundingPoints(baseIdx, positions, directions)) { + float f1 = zeus::clamp(-1.f, directions[1].dot(directions[2]), 1.f); + if (f1 >= 1.f) { + zeus::CTransform ret = zeus::lookAt(zeus::CVector3f::skZero, directions[2]); + ret.origin = zeus::getCatmullRomSplinePoint(positions[0], positions[1], positions[2], positions[3], t); + return ret; + } else { + zeus::CTransform ret = zeus::lookAt( + zeus::CVector3f::skZero, + zeus::CQuaternion::lookAt(directions[1], directions[2], std::acos(f1) * t).transform(directions[1])); + ret.origin = zeus::getCatmullRomSplinePoint(positions[0], positions[1], positions[2], positions[3], t); + return ret; + } + } + + return zeus::CTransform(); } -zeus::CVector3f CCameraSpline::GetInterpolatedSplinePointByTime(float time, float range) const -{ - if (x4_positions.empty()) - return {}; - - rstl::reserved_vector positions; - rstl::reserved_vector directions; - float rangeFac = range / float(x4_positions.size() - 1); - int baseIdx = std::min(int(x4_positions.size() - 1), int(time / rangeFac)); - if (GetSurroundingPoints(baseIdx, positions, directions)) - return zeus::getCatmullRomSplinePoint(positions[0], positions[1], positions[2], positions[3], - (time - float(baseIdx) * rangeFac) / rangeFac); - +zeus::CVector3f CCameraSpline::GetInterpolatedSplinePointByTime(float time, float range) const { + if (x4_positions.empty()) return {}; + + rstl::reserved_vector positions; + rstl::reserved_vector directions; + float rangeFac = range / float(x4_positions.size() - 1); + int baseIdx = std::min(int(x4_positions.size() - 1), int(time / rangeFac)); + if (GetSurroundingPoints(baseIdx, positions, directions)) + return zeus::getCatmullRomSplinePoint(positions[0], positions[1], positions[2], positions[3], + (time - float(baseIdx) * rangeFac) / rangeFac); + + return {}; } -float CCameraSpline::FindClosestLengthOnSpline(float time, const zeus::CVector3f& p) const -{ - float ret = -1.f; - float minLenDelta = 10000.f; - float minMag = 10000.f; +float CCameraSpline::FindClosestLengthOnSpline(float time, const zeus::CVector3f& p) const { + float ret = -1.f; + float minLenDelta = 10000.f; + float minMag = 10000.f; - size_t iterations = x4_positions.size() - 1; - if (x48_closedLoop) - iterations += 1; + size_t iterations = x4_positions.size() - 1; + if (x48_closedLoop) + iterations += 1; - for (size_t i=0 ; i 1.f) - t = 1.f; - } - - if (t >= 0.f && t <= 1.f) - { - float tLen; - if (i == x4_positions.size() - 1) - tLen = x44_length - x24_t[i]; - else - tLen = x24_t[i + 1] - x24_t[i]; - - float lenT = t * tLen + x24_t[i]; - zeus::CVector3f pointDelta = p - GetInterpolatedSplinePointByLength(lenT).origin; - float mag = 0.f; - if (pointDelta.canBeNormalized()) - mag = pointDelta.magnitude(); - float lenDelta = std::fabs(lenT - time); - if (x48_closedLoop && lenDelta > x44_length - lenDelta) - lenDelta = x44_length - lenDelta; - if (zeus::close_enough(std::fabs(mag - minMag), 0.f)) - { - if (lenDelta < minLenDelta) - { - ret = lenT; - minLenDelta = lenDelta; - } - } - else - { - if (mag < minMag) - { - ret = lenT; - minLenDelta = lenDelta; - minMag = mag; - } - } - } + if (!x48_closedLoop) { + if (i == 0 && t < 0.f) + t = 0.f; + if (i == x4_positions.size() - 2 && t > 1.f) + t = 1.f; } - return std::max(ret, 0.f); -} + if (t >= 0.f && t <= 1.f) { + float tLen; + if (i == x4_positions.size() - 1) + tLen = x44_length - x24_t[i]; + else + tLen = x24_t[i + 1] - x24_t[i]; -float CCameraSpline::ValidateLength(float t) const -{ - if (x48_closedLoop) - { - while (t >= x44_length) - t -= x44_length; - while (t < 0.f) - t += x44_length; - return t; - } - else - { - return zeus::clamp(0.f, t, x44_length); + float lenT = t * tLen + x24_t[i]; + zeus::CVector3f pointDelta = p - GetInterpolatedSplinePointByLength(lenT).origin; + float mag = 0.f; + if (pointDelta.canBeNormalized()) + mag = pointDelta.magnitude(); + float lenDelta = std::fabs(lenT - time); + if (x48_closedLoop && lenDelta > x44_length - lenDelta) + lenDelta = x44_length - lenDelta; + if (zeus::close_enough(std::fabs(mag - minMag), 0.f)) { + if (lenDelta < minLenDelta) { + ret = lenT; + minLenDelta = lenDelta; + } + } else { + if (mag < minMag) { + ret = lenT; + minLenDelta = lenDelta; + minMag = mag; + } + } } + } + + return std::max(ret, 0.f); } -float CCameraSpline::ClampLength(const zeus::CVector3f& pos, bool collide, - const CMaterialFilter& filter, const CStateManager& mgr) const -{ - if (x4_positions.empty()) - return 0.f; - - if (x48_closedLoop) - return 0.f; - - zeus::CVector3f deltaA = pos - x4_positions.front(); - zeus::CVector3f deltaB = pos - x4_positions.back(); - float magA = deltaA.magnitude(); - float magB = deltaB.magnitude(); - if (!deltaA.canBeNormalized()) - return 0.f; - if (!deltaB.canBeNormalized()) - return x44_length; - - if (collide) - { - bool collideA = mgr.RayStaticIntersection(x4_positions.front(), deltaA.normalized(), magA, filter).IsValid(); - bool collideB = mgr.RayStaticIntersection(x4_positions.back(), deltaB.normalized(), magB, filter).IsValid(); - if (collideA) - return x44_length; - if (collideB) - return 0.f; - } - - if (magA < magB) - return 0.f; - else - return x44_length; +float CCameraSpline::ValidateLength(float t) const { + if (x48_closedLoop) { + while (t >= x44_length) + t -= x44_length; + while (t < 0.f) + t += x44_length; + return t; + } else { + return zeus::clamp(0.f, t, x44_length); + } } +float CCameraSpline::ClampLength(const zeus::CVector3f& pos, bool collide, const CMaterialFilter& filter, + const CStateManager& mgr) const { + if (x4_positions.empty()) + return 0.f; + + if (x48_closedLoop) + return 0.f; + + zeus::CVector3f deltaA = pos - x4_positions.front(); + zeus::CVector3f deltaB = pos - x4_positions.back(); + float magA = deltaA.magnitude(); + float magB = deltaB.magnitude(); + if (!deltaA.canBeNormalized()) + return 0.f; + if (!deltaB.canBeNormalized()) + return x44_length; + + if (collide) { + bool collideA = mgr.RayStaticIntersection(x4_positions.front(), deltaA.normalized(), magA, filter).IsValid(); + bool collideB = mgr.RayStaticIntersection(x4_positions.back(), deltaB.normalized(), magB, filter).IsValid(); + if (collideA) + return x44_length; + if (collideB) + return 0.f; + } + + if (magA < magB) + return 0.f; + else + return x44_length; } + +} // namespace urde diff --git a/Runtime/Camera/CCameraSpline.hpp b/Runtime/Camera/CCameraSpline.hpp index cdeb21073..400d063bc 100644 --- a/Runtime/Camera/CCameraSpline.hpp +++ b/Runtime/Camera/CCameraSpline.hpp @@ -3,43 +3,41 @@ #include "World/CEntityInfo.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CMaterialFilter; -class CCameraSpline -{ - friend class CBallCamera; - std::vector x4_positions; - std::vector x14_wpTracker; - std::vector x24_t; - std::vector x34_directions; - float x44_length = 0.f; - bool x48_closedLoop = false; - bool GetSurroundingPoints(int idx, rstl::reserved_vector& positions, - rstl::reserved_vector& directions) const; +class CCameraSpline { + friend class CBallCamera; + std::vector x4_positions; + std::vector x14_wpTracker; + std::vector x24_t; + std::vector x34_directions; + float x44_length = 0.f; + bool x48_closedLoop = false; + bool GetSurroundingPoints(int idx, rstl::reserved_vector& positions, + rstl::reserved_vector& directions) const; + public: - CCameraSpline(bool closedLoop); - void CalculateKnots(TUniqueId, const std::vector&, CStateManager&); - void Initialize(TUniqueId, const std::vector&, CStateManager&); - void Reset(int size); - void AddKnot(const zeus::CVector3f& pos, const zeus::CVector3f& dir); - void SetKnotPosition(int idx, const zeus::CVector3f& pos); - const zeus::CVector3f& GetKnotPosition(int idx) const; - float GetKnotT(int idx) const; - float CalculateSplineLength(); - void UpdateSplineLength() { x44_length = CalculateSplineLength(); } - zeus::CTransform GetInterpolatedSplinePointByLength(float pos) const; - zeus::CVector3f GetInterpolatedSplinePointByTime(float time, float range) const; - float FindClosestLengthOnSpline(float time, const zeus::CVector3f& p) const; - float ValidateLength(float t) const; - float ClampLength(const zeus::CVector3f& pos, bool collide, - const CMaterialFilter& filter, const CStateManager& mgr) const; - s32 GetSize() const { return x4_positions.size(); } - float GetLength() const { return x44_length; } - bool IsClosedLoop() const { return x48_closedLoop; } + CCameraSpline(bool closedLoop); + void CalculateKnots(TUniqueId, const std::vector&, CStateManager&); + void Initialize(TUniqueId, const std::vector&, CStateManager&); + void Reset(int size); + void AddKnot(const zeus::CVector3f& pos, const zeus::CVector3f& dir); + void SetKnotPosition(int idx, const zeus::CVector3f& pos); + const zeus::CVector3f& GetKnotPosition(int idx) const; + float GetKnotT(int idx) const; + float CalculateSplineLength(); + void UpdateSplineLength() { x44_length = CalculateSplineLength(); } + zeus::CTransform GetInterpolatedSplinePointByLength(float pos) const; + zeus::CVector3f GetInterpolatedSplinePointByTime(float time, float range) const; + float FindClosestLengthOnSpline(float time, const zeus::CVector3f& p) const; + float ValidateLength(float t) const; + float ClampLength(const zeus::CVector3f& pos, bool collide, const CMaterialFilter& filter, + const CStateManager& mgr) const; + s32 GetSize() const { return x4_positions.size(); } + float GetLength() const { return x44_length; } + bool IsClosedLoop() const { return x48_closedLoop; } }; -} - +} // namespace urde diff --git a/Runtime/Camera/CCinematicCamera.cpp b/Runtime/Camera/CCinematicCamera.cpp index b1dd06b3f..bd534e6f8 100644 --- a/Runtime/Camera/CCinematicCamera.cpp +++ b/Runtime/Camera/CCinematicCamera.cpp @@ -7,468 +7,403 @@ #include "GameGlobalObjects.hpp" #include "Character/CAnimTreeNode.hpp" -namespace urde -{ +namespace urde { CCinematicCamera::CCinematicCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, float shotDuration, - float fovy, float znear, float zfar, float aspect, u32 flags) -: CGameCamera(uid, active, name, info, xf, fovy, znear, zfar, aspect, kInvalidUniqueId, flags & 0x20, 0), - x1e8_duration(shotDuration), x1f0_origFovy(fovy), x1fc_origOrientation(zeus::CQuaternion(xf.basis)), x21c_flags(flags) -{ - x220_24_ = false; + const zeus::CTransform& xf, bool active, float shotDuration, float fovy, float znear, + float zfar, float aspect, u32 flags) +: CGameCamera(uid, active, name, info, xf, fovy, znear, zfar, aspect, kInvalidUniqueId, flags & 0x20, 0) +, x1e8_duration(shotDuration) +, x1f0_origFovy(fovy) +, x1fc_origOrientation(zeus::CQuaternion(xf.basis)) +, x21c_flags(flags) { + x220_24_ = false; } -void CCinematicCamera::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CCinematicCamera::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CCinematicCamera::ProcessInput(const CFinalInput&, CStateManager& mgr) { + // Empty } -void CCinematicCamera::ProcessInput(const CFinalInput&, CStateManager& mgr) -{ - // Empty +void CCinematicCamera::Reset(const zeus::CTransform&, CStateManager& mgr) { + // Empty } -void CCinematicCamera::Reset(const zeus::CTransform&, CStateManager& mgr) -{ - // Empty +void CCinematicCamera::WasDeactivated(CStateManager& mgr) { + mgr.GetCameraManager()->RemoveCinemaCamera(GetUniqueId(), mgr); + mgr.GetPlayer().GetMorphBall()->LoadMorphBallModel(mgr); + if (x21c_flags & 0x100) + mgr.SetCinematicPause(false); + x188_viewPoints.clear(); + x198_viewOrientations.clear(); + x1a8_viewPointArrivals.clear(); + x1b8_targets.clear(); + x1c8_targetArrivals.clear(); + x1d8_viewHFovs.clear(); } -void CCinematicCamera::WasDeactivated(CStateManager& mgr) -{ - mgr.GetCameraManager()->RemoveCinemaCamera(GetUniqueId(), mgr); - mgr.GetPlayer().GetMorphBall()->LoadMorphBallModel(mgr); - if (x21c_flags & 0x100) - mgr.SetCinematicPause(false); - x188_viewPoints.clear(); - x198_viewOrientations.clear(); - x1a8_viewPointArrivals.clear(); - x1b8_targets.clear(); - x1c8_targetArrivals.clear(); - x1d8_viewHFovs.clear(); -} - -zeus::CVector3f -CCinematicCamera::GetInterpolatedSplinePoint(const std::vector& points, int& idxOut, float tin) const -{ - if (points.size() > 0) - { - float cycleT = std::fmod(tin, x1e8_duration); - float durPerPoint = x1e8_duration / float(points.size() - 1); - idxOut = int(cycleT / durPerPoint); - float t = (cycleT - idxOut * durPerPoint) / durPerPoint; - - if (points.size() == 1) - return points.front(); - else if (points.size() == 2) - return (points[1] - points[0]) * t + points[0]; - - zeus::CVector3f ptA; - if (idxOut > 0) - ptA = points[idxOut - 1]; - else - ptA = points[0] - (points[1] - points[0]); - - zeus::CVector3f ptB = points[idxOut]; - zeus::CVector3f ptC; - if (idxOut + 1 >= points.size()) - { - const zeus::CVector3f& tmpA = points[points.size() - 1]; - const zeus::CVector3f& tmpB = points[points.size() - 2]; - ptC = tmpA - (tmpB - tmpA); - } - else - { - ptC = points[idxOut + 1]; - } - - zeus::CVector3f ptD; - if (idxOut + 2 >= points.size()) - { - const zeus::CVector3f& tmpA = points[points.size() - 1]; - const zeus::CVector3f& tmpB = points[points.size() - 2]; - ptD = tmpA - (tmpB - tmpA); - } - else - { - ptD = points[idxOut + 2]; - } - - return zeus::getCatmullRomSplinePoint(ptA, ptB, ptC, ptD, t); - } - - return {}; -} - -zeus::CQuaternion -CCinematicCamera::GetInterpolatedOrientation(const std::vector& rotations, float tin) const -{ - if (rotations.size() == 0) - return x1fc_origOrientation; - else if (rotations.size() == 1) - return rotations.front(); - +zeus::CVector3f CCinematicCamera::GetInterpolatedSplinePoint(const std::vector& points, int& idxOut, + float tin) const { + if (points.size() > 0) { float cycleT = std::fmod(tin, x1e8_duration); - float durPerPoint = x1e8_duration / float(rotations.size() - 1); - int idx = int(cycleT / durPerPoint); - float t = (cycleT - idx * durPerPoint) / durPerPoint; - return zeus::CQuaternion::slerp(rotations[idx], rotations[idx + 1], t); + float durPerPoint = x1e8_duration / float(points.size() - 1); + idxOut = int(cycleT / durPerPoint); + float t = (cycleT - idxOut * durPerPoint) / durPerPoint; + + if (points.size() == 1) + return points.front(); + else if (points.size() == 2) + return (points[1] - points[0]) * t + points[0]; + + zeus::CVector3f ptA; + if (idxOut > 0) + ptA = points[idxOut - 1]; + else + ptA = points[0] - (points[1] - points[0]); + + zeus::CVector3f ptB = points[idxOut]; + zeus::CVector3f ptC; + if (idxOut + 1 >= points.size()) { + const zeus::CVector3f& tmpA = points[points.size() - 1]; + const zeus::CVector3f& tmpB = points[points.size() - 2]; + ptC = tmpA - (tmpB - tmpA); + } else { + ptC = points[idxOut + 1]; + } + + zeus::CVector3f ptD; + if (idxOut + 2 >= points.size()) { + const zeus::CVector3f& tmpA = points[points.size() - 1]; + const zeus::CVector3f& tmpB = points[points.size() - 2]; + ptD = tmpA - (tmpB - tmpA); + } else { + ptD = points[idxOut + 2]; + } + + return zeus::getCatmullRomSplinePoint(ptA, ptB, ptC, ptD, t); + } + + return {}; } -float CCinematicCamera::GetInterpolatedHFov(const std::vector& fovs, float tin) const -{ - if (fovs.size() == 0) - return x1f0_origFovy; - else if (fovs.size() == 1) - return fovs.front(); +zeus::CQuaternion CCinematicCamera::GetInterpolatedOrientation(const std::vector& rotations, + float tin) const { + if (rotations.size() == 0) + return x1fc_origOrientation; + else if (rotations.size() == 1) + return rotations.front(); - float cycleT = std::fmod(tin, x1e8_duration); - float durPerPoint = x1e8_duration / float(fovs.size() - 1); - int idx = int(cycleT / durPerPoint); - float t = (cycleT - idx * durPerPoint) / durPerPoint; - return (fovs[idx + 1] - fovs[idx]) * t + fovs[idx]; + float cycleT = std::fmod(tin, x1e8_duration); + float durPerPoint = x1e8_duration / float(rotations.size() - 1); + int idx = int(cycleT / durPerPoint); + float t = (cycleT - idx * durPerPoint) / durPerPoint; + return zeus::CQuaternion::slerp(rotations[idx], rotations[idx + 1], t); } -float CCinematicCamera::GetMoveOutofIntoAlpha() const -{ - float startDist = 0.25f + x160_znear; - float endDist = 1.f * startDist; - float deltaMag = (GetTranslation() - x210_moveIntoEyePos).magnitude(); - if (deltaMag >= startDist && deltaMag <= endDist) - return (deltaMag - startDist) / (endDist - startDist); - if (deltaMag > endDist) - return 1.f; - return 0.f; +float CCinematicCamera::GetInterpolatedHFov(const std::vector& fovs, float tin) const { + if (fovs.size() == 0) + return x1f0_origFovy; + else if (fovs.size() == 1) + return fovs.front(); + + float cycleT = std::fmod(tin, x1e8_duration); + float durPerPoint = x1e8_duration / float(fovs.size() - 1); + int idx = int(cycleT / durPerPoint); + float t = (cycleT - idx * durPerPoint) / durPerPoint; + return (fovs[idx + 1] - fovs[idx]) * t + fovs[idx]; } -void CCinematicCamera::DeactivateSelf(CStateManager& mgr) -{ - SetActive(false); - SendScriptMsgs(EScriptObjectState::Inactive, mgr, EScriptObjectMessage::None); - WasDeactivated(mgr); +float CCinematicCamera::GetMoveOutofIntoAlpha() const { + float startDist = 0.25f + x160_znear; + float endDist = 1.f * startDist; + float deltaMag = (GetTranslation() - x210_moveIntoEyePos).magnitude(); + if (deltaMag >= startDist && deltaMag <= endDist) + return (deltaMag - startDist) / (endDist - startDist); + if (deltaMag > endDist) + return 1.f; + return 0.f; } -void CCinematicCamera::Think(float dt, CStateManager& mgr) -{ - if (GetActive()) - { - zeus::CVector3f viewPoint = GetTranslation(); - if (x188_viewPoints.size() > 0) - { - int idx = 0; - viewPoint = GetInterpolatedSplinePoint(x188_viewPoints, idx, x1ec_t); - if (idx > x1f4_passedViewPoint) - { - x1f4_passedViewPoint = idx; - SendArrivedMsg(x1a8_viewPointArrivals[x1f4_passedViewPoint], mgr); - } +void CCinematicCamera::DeactivateSelf(CStateManager& mgr) { + SetActive(false); + SendScriptMsgs(EScriptObjectState::Inactive, mgr, EScriptObjectMessage::None); + WasDeactivated(mgr); +} + +void CCinematicCamera::Think(float dt, CStateManager& mgr) { + if (GetActive()) { + zeus::CVector3f viewPoint = GetTranslation(); + if (x188_viewPoints.size() > 0) { + int idx = 0; + viewPoint = GetInterpolatedSplinePoint(x188_viewPoints, idx, x1ec_t); + if (idx > x1f4_passedViewPoint) { + x1f4_passedViewPoint = idx; + SendArrivedMsg(x1a8_viewPointArrivals[x1f4_passedViewPoint], mgr); + } + } + + zeus::CQuaternion orientation = GetInterpolatedOrientation(x198_viewOrientations, x1ec_t); + + if ((x21c_flags & 0x1) == 0) { + if (x1b8_targets.size() > 0) { + int idx = 0; + zeus::CVector3f target = GetInterpolatedSplinePoint(x1b8_targets, idx, x1ec_t); + if (x1b8_targets.size() == 1) { + if (TCastToConstPtr act = mgr.GetObjectById(x1c8_targetArrivals.front())) + target = act->GetTranslation(); + else + x1ec_t = x1e8_duration; } - - zeus::CQuaternion orientation = GetInterpolatedOrientation(x198_viewOrientations, x1ec_t); - - if ((x21c_flags & 0x1) == 0) - { - if (x1b8_targets.size() > 0) - { - int idx = 0; - zeus::CVector3f target = GetInterpolatedSplinePoint(x1b8_targets, idx, x1ec_t); - if (x1b8_targets.size() == 1) - { - if (TCastToConstPtr act = mgr.GetObjectById(x1c8_targetArrivals.front())) - target = act->GetTranslation(); - else - x1ec_t = x1e8_duration; - } - if (idx > x1f8_passedTarget) - { - x1f8_passedTarget = idx; - SendArrivedMsg(x1c8_targetArrivals[x1f8_passedTarget], mgr); - } - zeus::CVector3f upVec = orientation.transform(zeus::CVector3f::skUp); - if ((target - viewPoint).toVec2f().magnitude() < 0.0011920929f) - SetTranslation(target); - else - SetTransform(zeus::lookAt(viewPoint, target, upVec)); - } - else - { - SetTransform(zeus::CTransform(orientation, viewPoint)); - } + if (idx > x1f8_passedTarget) { + x1f8_passedTarget = idx; + SendArrivedMsg(x1c8_targetArrivals[x1f8_passedTarget], mgr); } + zeus::CVector3f upVec = orientation.transform(zeus::CVector3f::skUp); + if ((target - viewPoint).toVec2f().magnitude() < 0.0011920929f) + SetTranslation(target); else - { - zeus::CVector3f target = mgr.GetPlayer().GetTranslation(); - if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) - target.z() += mgr.GetPlayer().GetMorphBall()->GetBallRadius(); - else - target.z() += mgr.GetPlayer().GetEyeHeight(); + SetTransform(zeus::lookAt(viewPoint, target, upVec)); + } else { + SetTransform(zeus::CTransform(orientation, viewPoint)); + } + } else { + zeus::CVector3f target = mgr.GetPlayer().GetTranslation(); + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) + target.z() += mgr.GetPlayer().GetMorphBall()->GetBallRadius(); + else + target.z() += mgr.GetPlayer().GetEyeHeight(); - zeus::CVector3f upVec = orientation.transform(zeus::CVector3f::skUp); - if ((target - viewPoint).toVec2f().magnitude() < 0.0011920929f) - SetTranslation(target); - else - SetTransform(zeus::lookAt(viewPoint, target, upVec)); - } - - x15c_currentFov = GetInterpolatedHFov(x1d8_viewHFovs, x1ec_t) / x168_aspect; - x170_24_perspDirty = true; - - if (x20c_lookAtId != kInvalidUniqueId) - if (TCastToPtr act = mgr.ObjectById(x20c_lookAtId)) - if (act->IsPlayerActor()) - act->SetDrawFlags({5, 0, 3, zeus::CColor(1.f, GetMoveOutofIntoAlpha())}); - - x1ec_t += dt; - if (x1ec_t > x1e8_duration) - { - for (int i = x1f4_passedViewPoint + 1; i < x1a8_viewPointArrivals.size() ; ++i) - SendArrivedMsg(x1a8_viewPointArrivals[i], mgr); - for (int i = x1f8_passedTarget + 1; i < x1c8_targetArrivals.size() ; ++i) - SendArrivedMsg(x1c8_targetArrivals[i], mgr); - DeactivateSelf(mgr); - } + zeus::CVector3f upVec = orientation.transform(zeus::CVector3f::skUp); + if ((target - viewPoint).toVec2f().magnitude() < 0.0011920929f) + SetTranslation(target); + else + SetTransform(zeus::lookAt(viewPoint, target, upVec)); } -} -void CCinematicCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CGameCamera::AcceptScriptMsg(msg, uid, mgr); - switch (msg) - { - case EScriptObjectMessage::InitializedInArea: - if (x21c_flags & 0x4 || x21c_flags & 0x2) - { - for (const SConnection& conn : x20_conns) - { - TUniqueId id = mgr.GetIdForScript(conn.x8_objId); - if (TCastToPtr act = mgr.ObjectById(id)) - { - if (act->IsPlayerActor()) - { - x20c_lookAtId = id; - if (conn.x4_msg != EScriptObjectMessage::Deactivate && - conn.x4_msg != EScriptObjectMessage::Reset) - break; - } - } - } - } - break; - case EScriptObjectMessage::Activate: - CalculateWaypoints(mgr); - if ((x21c_flags & 1) == 0 && x220_24_ && x1b8_targets.empty()) - break; - x1ec_t = 0.f; - Think(0.f, mgr); - mgr.GetCameraManager()->AddCinemaCamera(GetUniqueId(), mgr); - x1f4_passedViewPoint = 0; - if (x1a8_viewPointArrivals.size() > 0) - SendArrivedMsg(x1a8_viewPointArrivals[x1f4_passedViewPoint], mgr); - x1f8_passedTarget = 0; - if (x1c8_targetArrivals.size() > 0) - SendArrivedMsg(x1c8_targetArrivals[x1f8_passedTarget], mgr); - if (x21c_flags & 0x100) - mgr.SetCinematicPause(true); - break; - case EScriptObjectMessage::Deactivate: - WasDeactivated(mgr); - break; - default: - break; - } -} + x15c_currentFov = GetInterpolatedHFov(x1d8_viewHFovs, x1ec_t) / x168_aspect; + x170_24_perspDirty = true; -void CCinematicCamera::CalculateMoveOutofIntoEyePosition(bool outOfEye, CStateManager& mgr) -{ - zeus::CQuaternion q(mgr.GetPlayer().GetTransform().basis); - zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); if (x20c_lookAtId != kInvalidUniqueId) - { - if (TCastToConstPtr act = mgr.GetObjectById(x20c_lookAtId)) - { - if (act->IsPlayerActor()) - { - if (const CModelData* mData = act->GetModelData()) - { - if (const CAnimData* aData = mData->GetAnimationData()) - { - if (const CAnimTreeNode* root = aData->GetRootAnimationTree().get()) - { - CSegId lEye = aData->GetLocatorSegId("L_eye"sv); - CSegId rEye = aData->GetLocatorSegId("R_eye"sv); - if (lEye != 0xff && rEye != 0xff) - { - CCharAnimTime time = - outOfEye ? CCharAnimTime(0.f) : root->VGetSteadyStateAnimInfo().GetDuration(); - CCharAnimTime* pTime = outOfEye ? nullptr : &time; - eyePos = - ((act->GetTransform() * mData->GetScaledLocatorTransformDynamic("L_eye"sv, pTime)).origin + - (act->GetTransform() * mData->GetScaledLocatorTransformDynamic("R_eye"sv, pTime)).origin) * 0.5f; - q = zeus::CQuaternion(act->GetTransform().basis); - } - } - } - } - } + if (TCastToPtr act = mgr.ObjectById(x20c_lookAtId)) + if (act->IsPlayerActor()) + act->SetDrawFlags({5, 0, 3, zeus::CColor(1.f, GetMoveOutofIntoAlpha())}); + + x1ec_t += dt; + if (x1ec_t > x1e8_duration) { + for (int i = x1f4_passedViewPoint + 1; i < x1a8_viewPointArrivals.size(); ++i) + SendArrivedMsg(x1a8_viewPointArrivals[i], mgr); + for (int i = x1f8_passedTarget + 1; i < x1c8_targetArrivals.size(); ++i) + SendArrivedMsg(x1c8_targetArrivals[i], mgr); + DeactivateSelf(mgr); + } + } +} + +void CCinematicCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CGameCamera::AcceptScriptMsg(msg, uid, mgr); + switch (msg) { + case EScriptObjectMessage::InitializedInArea: + if (x21c_flags & 0x4 || x21c_flags & 0x2) { + for (const SConnection& conn : x20_conns) { + TUniqueId id = mgr.GetIdForScript(conn.x8_objId); + if (TCastToPtr act = mgr.ObjectById(id)) { + if (act->IsPlayerActor()) { + x20c_lookAtId = id; + if (conn.x4_msg != EScriptObjectMessage::Deactivate && conn.x4_msg != EScriptObjectMessage::Reset) + break; + } } + } } - - zeus::CVector3f behindPos = eyePos; - zeus::CVector3f behindDelta = q.transform({0.f, -g_tweakPlayerRes->xf0_cinematicMoveOutofIntoPlayerDistance, 0.f}); - if (!outOfEye) - { - behindPos += behindDelta; - behindDelta = -behindDelta; - } - - for (int i=0 ; i<2 ; ++i) - { - x188_viewPoints[outOfEye ? i : x188_viewPoints.size() - (2 - i)] = behindPos; - x198_viewOrientations[outOfEye ? i : x198_viewOrientations.size() - (2 - i)] = q; - x1b8_targets[outOfEye ? i : x1b8_targets.size() - (2 - i)] = eyePos; - behindPos += behindDelta; - } - - x210_moveIntoEyePos = eyePos; + break; + case EScriptObjectMessage::Activate: + CalculateWaypoints(mgr); + if ((x21c_flags & 1) == 0 && x220_24_ && x1b8_targets.empty()) + break; + x1ec_t = 0.f; + Think(0.f, mgr); + mgr.GetCameraManager()->AddCinemaCamera(GetUniqueId(), mgr); + x1f4_passedViewPoint = 0; + if (x1a8_viewPointArrivals.size() > 0) + SendArrivedMsg(x1a8_viewPointArrivals[x1f4_passedViewPoint], mgr); + x1f8_passedTarget = 0; + if (x1c8_targetArrivals.size() > 0) + SendArrivedMsg(x1c8_targetArrivals[x1f8_passedTarget], mgr); + if (x21c_flags & 0x100) + mgr.SetCinematicPause(true); + break; + case EScriptObjectMessage::Deactivate: + WasDeactivated(mgr); + break; + default: + break; + } } -void CCinematicCamera::GenerateMoveOutofIntoPoints(bool outOfEye, CStateManager& mgr) -{ - zeus::CQuaternion q(mgr.GetPlayer().GetTransform().basis); - zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); - zeus::CVector3f behindDelta = q.transform({0.f, -g_tweakPlayerRes->xf0_cinematicMoveOutofIntoPlayerDistance, 0.f}); - zeus::CVector3f behindPos = eyePos; - if (!outOfEye) - { - behindPos += behindDelta; - behindDelta = -behindDelta; - } - for (int i=0 ; i<2 ; ++i) - { - x188_viewPoints.push_back(behindPos); - x198_viewOrientations.push_back(q); - x1a8_viewPointArrivals.push_back(mgr.GetPlayer().GetUniqueId()); - x1b8_targets.push_back(eyePos); - x1c8_targetArrivals.push_back(kInvalidUniqueId); - behindPos += behindDelta; - } - CalculateMoveOutofIntoEyePosition(outOfEye, mgr); -} - -bool CCinematicCamera::PickRandomActiveConnection(const std::vector& conns, - SConnection& randConn, CStateManager& mgr) -{ - int count = 0; - for (const SConnection& conn : conns) - if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) - if (TCastToConstPtr act = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) - if (act->GetActive()) - ++count; - - if (!count) - return false; - - int randIdx = mgr.GetActiveRandom()->Next() % count; - int idx = 0; - for (const SConnection& conn : conns) - if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) - if (TCastToConstPtr act = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) - if (act->GetActive()) - { - if (randIdx == idx) - { - randConn = conn; - break; - } - ++idx; - } - - return true; -} - -void CCinematicCamera::CalculateWaypoints(CStateManager& mgr) -{ - const SConnection* firstVP = nullptr; - const SConnection* firstTarget = nullptr; - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state == EScriptObjectState::CameraPath && conn.x4_msg == EScriptObjectMessage::Activate) - firstVP = &conn; - else if (conn.x0_state == EScriptObjectState::CameraTarget && conn.x4_msg == EScriptObjectMessage::Activate) - firstTarget = &conn; - } - - x188_viewPoints.clear(); - x188_viewPoints.reserve(3); - x198_viewOrientations.clear(); - x198_viewOrientations.reserve(3); - x1a8_viewPointArrivals.clear(); - x1a8_viewPointArrivals.reserve(3); - x1b8_targets.clear(); - x1b8_targets.reserve(3); - x1c8_targetArrivals.clear(); - x1c8_targetArrivals.reserve(3); - x1d8_viewHFovs.clear(); - x1d8_viewHFovs.reserve(3); - - x220_24_ = false; - - if ((x21c_flags & 0x2) != 0 && (x21c_flags & 0x200) == 0) - GenerateMoveOutofIntoPoints(true, mgr); - - if (firstVP) - { - TCastToConstPtr wp = mgr.GetObjectById(mgr.GetIdForScript(firstVP->x8_objId)); - while (wp) - { - x188_viewPoints.push_back(wp->GetTranslation()); - x198_viewOrientations.emplace_back(wp->GetTransform().basis); - if (TCastToConstPtr cwp = wp.GetPtr()) - x1d8_viewHFovs.push_back(cwp->GetHFov()); - auto search = std::find_if(x1a8_viewPointArrivals.begin(), x1a8_viewPointArrivals.end(), - [&](TUniqueId id) { return id == wp->GetUniqueId(); }); - if (search == x1a8_viewPointArrivals.end()) - { - x1a8_viewPointArrivals.push_back(wp->GetUniqueId()); - SConnection randConn; - if (PickRandomActiveConnection(wp->GetConnectionList(), randConn, mgr)) - wp = mgr.GetObjectById(mgr.GetIdForScript(randConn.x8_objId)); - else - break; +void CCinematicCamera::CalculateMoveOutofIntoEyePosition(bool outOfEye, CStateManager& mgr) { + zeus::CQuaternion q(mgr.GetPlayer().GetTransform().basis); + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + if (x20c_lookAtId != kInvalidUniqueId) { + if (TCastToConstPtr act = mgr.GetObjectById(x20c_lookAtId)) { + if (act->IsPlayerActor()) { + if (const CModelData* mData = act->GetModelData()) { + if (const CAnimData* aData = mData->GetAnimationData()) { + if (const CAnimTreeNode* root = aData->GetRootAnimationTree().get()) { + CSegId lEye = aData->GetLocatorSegId("L_eye"sv); + CSegId rEye = aData->GetLocatorSegId("R_eye"sv); + if (lEye != 0xff && rEye != 0xff) { + CCharAnimTime time = outOfEye ? CCharAnimTime(0.f) : root->VGetSteadyStateAnimInfo().GetDuration(); + CCharAnimTime* pTime = outOfEye ? nullptr : &time; + eyePos = ((act->GetTransform() * mData->GetScaledLocatorTransformDynamic("L_eye"sv, pTime)).origin + + (act->GetTransform() * mData->GetScaledLocatorTransformDynamic("R_eye"sv, pTime)).origin) * + 0.5f; + q = zeus::CQuaternion(act->GetTransform().basis); + } } - else - break; + } } + } } + } - if (firstTarget) - { - TCastToConstPtr tgt = mgr.GetObjectById(mgr.GetIdForScript(firstTarget->x8_objId)); - while (tgt) - { - x1b8_targets.push_back(tgt->GetTranslation()); - auto search = std::find_if(x1c8_targetArrivals.begin(), x1c8_targetArrivals.end(), - [&](TUniqueId id) { return id == tgt->GetUniqueId(); }); - if (search == x1c8_targetArrivals.end()) - { - x1c8_targetArrivals.push_back(tgt->GetUniqueId()); - SConnection randConn; - if (PickRandomActiveConnection(tgt->GetConnectionList(), randConn, mgr)) - tgt = mgr.GetObjectById(mgr.GetIdForScript(randConn.x8_objId)); - else - break; - } - else - break; + zeus::CVector3f behindPos = eyePos; + zeus::CVector3f behindDelta = q.transform({0.f, -g_tweakPlayerRes->xf0_cinematicMoveOutofIntoPlayerDistance, 0.f}); + if (!outOfEye) { + behindPos += behindDelta; + behindDelta = -behindDelta; + } + + for (int i = 0; i < 2; ++i) { + x188_viewPoints[outOfEye ? i : x188_viewPoints.size() - (2 - i)] = behindPos; + x198_viewOrientations[outOfEye ? i : x198_viewOrientations.size() - (2 - i)] = q; + x1b8_targets[outOfEye ? i : x1b8_targets.size() - (2 - i)] = eyePos; + behindPos += behindDelta; + } + + x210_moveIntoEyePos = eyePos; +} + +void CCinematicCamera::GenerateMoveOutofIntoPoints(bool outOfEye, CStateManager& mgr) { + zeus::CQuaternion q(mgr.GetPlayer().GetTransform().basis); + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + zeus::CVector3f behindDelta = q.transform({0.f, -g_tweakPlayerRes->xf0_cinematicMoveOutofIntoPlayerDistance, 0.f}); + zeus::CVector3f behindPos = eyePos; + if (!outOfEye) { + behindPos += behindDelta; + behindDelta = -behindDelta; + } + for (int i = 0; i < 2; ++i) { + x188_viewPoints.push_back(behindPos); + x198_viewOrientations.push_back(q); + x1a8_viewPointArrivals.push_back(mgr.GetPlayer().GetUniqueId()); + x1b8_targets.push_back(eyePos); + x1c8_targetArrivals.push_back(kInvalidUniqueId); + behindPos += behindDelta; + } + CalculateMoveOutofIntoEyePosition(outOfEye, mgr); +} + +bool CCinematicCamera::PickRandomActiveConnection(const std::vector& conns, SConnection& randConn, + CStateManager& mgr) { + int count = 0; + for (const SConnection& conn : conns) + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) + if (TCastToConstPtr act = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) + if (act->GetActive()) + ++count; + + if (!count) + return false; + + int randIdx = mgr.GetActiveRandom()->Next() % count; + int idx = 0; + for (const SConnection& conn : conns) + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) + if (TCastToConstPtr act = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) + if (act->GetActive()) { + if (randIdx == idx) { + randConn = conn; + break; + } + ++idx; } + + return true; +} + +void CCinematicCamera::CalculateWaypoints(CStateManager& mgr) { + const SConnection* firstVP = nullptr; + const SConnection* firstTarget = nullptr; + for (const SConnection& conn : x20_conns) { + if (conn.x0_state == EScriptObjectState::CameraPath && conn.x4_msg == EScriptObjectMessage::Activate) + firstVP = &conn; + else if (conn.x0_state == EScriptObjectState::CameraTarget && conn.x4_msg == EScriptObjectMessage::Activate) + firstTarget = &conn; + } + + x188_viewPoints.clear(); + x188_viewPoints.reserve(3); + x198_viewOrientations.clear(); + x198_viewOrientations.reserve(3); + x1a8_viewPointArrivals.clear(); + x1a8_viewPointArrivals.reserve(3); + x1b8_targets.clear(); + x1b8_targets.reserve(3); + x1c8_targetArrivals.clear(); + x1c8_targetArrivals.reserve(3); + x1d8_viewHFovs.clear(); + x1d8_viewHFovs.reserve(3); + + x220_24_ = false; + + if ((x21c_flags & 0x2) != 0 && (x21c_flags & 0x200) == 0) + GenerateMoveOutofIntoPoints(true, mgr); + + if (firstVP) { + TCastToConstPtr wp = mgr.GetObjectById(mgr.GetIdForScript(firstVP->x8_objId)); + while (wp) { + x188_viewPoints.push_back(wp->GetTranslation()); + x198_viewOrientations.emplace_back(wp->GetTransform().basis); + if (TCastToConstPtr cwp = wp.GetPtr()) + x1d8_viewHFovs.push_back(cwp->GetHFov()); + auto search = std::find_if(x1a8_viewPointArrivals.begin(), x1a8_viewPointArrivals.end(), + [&](TUniqueId id) { return id == wp->GetUniqueId(); }); + if (search == x1a8_viewPointArrivals.end()) { + x1a8_viewPointArrivals.push_back(wp->GetUniqueId()); + SConnection randConn; + if (PickRandomActiveConnection(wp->GetConnectionList(), randConn, mgr)) + wp = mgr.GetObjectById(mgr.GetIdForScript(randConn.x8_objId)); + else + break; + } else + break; } + } - if ((x21c_flags & 0x4) != 0 && (x21c_flags & 0x200) == 0) - GenerateMoveOutofIntoPoints(false, mgr); + if (firstTarget) { + TCastToConstPtr tgt = mgr.GetObjectById(mgr.GetIdForScript(firstTarget->x8_objId)); + while (tgt) { + x1b8_targets.push_back(tgt->GetTranslation()); + auto search = std::find_if(x1c8_targetArrivals.begin(), x1c8_targetArrivals.end(), + [&](TUniqueId id) { return id == tgt->GetUniqueId(); }); + if (search == x1c8_targetArrivals.end()) { + x1c8_targetArrivals.push_back(tgt->GetUniqueId()); + SConnection randConn; + if (PickRandomActiveConnection(tgt->GetConnectionList(), randConn, mgr)) + tgt = mgr.GetObjectById(mgr.GetIdForScript(randConn.x8_objId)); + else + break; + } else + break; + } + } + + if ((x21c_flags & 0x4) != 0 && (x21c_flags & 0x200) == 0) + GenerateMoveOutofIntoPoints(false, mgr); } -void CCinematicCamera::SendArrivedMsg(TUniqueId reciever, CStateManager& mgr) -{ - mgr.SendScriptMsgAlways(reciever, GetUniqueId(), EScriptObjectMessage::Arrived); -} +void CCinematicCamera::SendArrivedMsg(TUniqueId reciever, CStateManager& mgr) { + mgr.SendScriptMsgAlways(reciever, GetUniqueId(), EScriptObjectMessage::Arrived); } +} // namespace urde diff --git a/Runtime/Camera/CCinematicCamera.hpp b/Runtime/Camera/CCinematicCamera.hpp index 1172306ef..b22b9bad9 100644 --- a/Runtime/Camera/CCinematicCamera.hpp +++ b/Runtime/Camera/CCinematicCamera.hpp @@ -2,54 +2,51 @@ #include "CGameCamera.hpp" -namespace urde -{ +namespace urde { + +class CCinematicCamera : public CGameCamera { + std::vector x188_viewPoints; + std::vector x198_viewOrientations; + std::vector x1a8_viewPointArrivals; + std::vector x1b8_targets; + std::vector x1c8_targetArrivals; + std::vector x1d8_viewHFovs; + float x1e8_duration; + float x1ec_t = 0.f; + float x1f0_origFovy; + int x1f4_passedViewPoint = 0; + int x1f8_passedTarget = 0; + zeus::CQuaternion x1fc_origOrientation; + TUniqueId x20c_lookAtId = kInvalidUniqueId; + zeus::CVector3f x210_moveIntoEyePos; + u32 x21c_flags; // 0x1: look at player, 0x2: out of player eye, 0x4: into player eye, 0x10: finish cine skip, + // 0x20: disable input, 0x40: draw player, 0x80: check failsafe, 0x100: cinematic pause, + // 0x200: disable out of into + bool x220_24_; + zeus::CVector3f GetInterpolatedSplinePoint(const std::vector& points, int& idxOut, float t) const; + zeus::CQuaternion GetInterpolatedOrientation(const std::vector& rotations, float t) const; + float GetInterpolatedHFov(const std::vector& fovs, float t) const; + float GetMoveOutofIntoAlpha() const; + void DeactivateSelf(CStateManager& mgr); + void CalculateMoveOutofIntoEyePosition(bool outOfEye, CStateManager& mgr); + void GenerateMoveOutofIntoPoints(bool outOfEye, CStateManager& mgr); + static bool PickRandomActiveConnection(const std::vector& conns, SConnection& randConn, + CStateManager& mgr); + void CalculateWaypoints(CStateManager& mgr); -class CCinematicCamera : public CGameCamera -{ - std::vector x188_viewPoints; - std::vector x198_viewOrientations; - std::vector x1a8_viewPointArrivals; - std::vector x1b8_targets; - std::vector x1c8_targetArrivals; - std::vector x1d8_viewHFovs; - float x1e8_duration; - float x1ec_t = 0.f; - float x1f0_origFovy; - int x1f4_passedViewPoint = 0; - int x1f8_passedTarget = 0; - zeus::CQuaternion x1fc_origOrientation; - TUniqueId x20c_lookAtId = kInvalidUniqueId; - zeus::CVector3f x210_moveIntoEyePos; - u32 x21c_flags; // 0x1: look at player, 0x2: out of player eye, 0x4: into player eye, 0x10: finish cine skip, - // 0x20: disable input, 0x40: draw player, 0x80: check failsafe, 0x100: cinematic pause, - // 0x200: disable out of into - bool x220_24_; - zeus::CVector3f GetInterpolatedSplinePoint(const std::vector& points, int& idxOut, float t) const; - zeus::CQuaternion GetInterpolatedOrientation(const std::vector& rotations, float t) const; - float GetInterpolatedHFov(const std::vector& fovs, float t) const; - float GetMoveOutofIntoAlpha() const; - void DeactivateSelf(CStateManager& mgr); - void CalculateMoveOutofIntoEyePosition(bool outOfEye, CStateManager& mgr); - void GenerateMoveOutofIntoPoints(bool outOfEye, CStateManager& mgr); - static bool PickRandomActiveConnection(const std::vector& conns, - SConnection& randConn, CStateManager& mgr); - void CalculateWaypoints(CStateManager& mgr); public: - CCinematicCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, float shotDuration, - float fovy, float znear, float zfar, float aspect, u32 flags); + CCinematicCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + bool active, float shotDuration, float fovy, float znear, float zfar, float aspect, u32 flags); - void Accept(IVisitor& visitor); - void Think(float dt, CStateManager& mgr); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); - void ProcessInput(const CFinalInput&, CStateManager& mgr); - void Reset(const zeus::CTransform&, CStateManager& mgr); - u32 GetFlags() const { return x21c_flags; } - void WasDeactivated(CStateManager& mgr); - void SendArrivedMsg(TUniqueId reciever, CStateManager& mgr); - float GetDuration() const { return x1e8_duration; } + void Accept(IVisitor& visitor); + void Think(float dt, CStateManager& mgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); + void ProcessInput(const CFinalInput&, CStateManager& mgr); + void Reset(const zeus::CTransform&, CStateManager& mgr); + u32 GetFlags() const { return x21c_flags; } + void WasDeactivated(CStateManager& mgr); + void SendArrivedMsg(TUniqueId reciever, CStateManager& mgr); + float GetDuration() const { return x1e8_duration; } }; -} - +} // namespace urde diff --git a/Runtime/Camera/CFirstPersonCamera.cpp b/Runtime/Camera/CFirstPersonCamera.cpp index 38b08caee..0f749a2ee 100644 --- a/Runtime/Camera/CFirstPersonCamera.cpp +++ b/Runtime/Camera/CFirstPersonCamera.cpp @@ -6,373 +6,323 @@ #include "World/CScriptCameraPitchVolume.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CFirstPersonCamera::CFirstPersonCamera(TUniqueId uid, const zeus::CTransform& xf, TUniqueId watchedObj, float orbitCameraSpeed, float fov, float nearz, float farz, float aspect) : CGameCamera(uid, true, "First Person Camera", CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList), xf, fov, - nearz, farz, aspect, watchedObj, false, 0), x188_orbitCameraSpeed(orbitCameraSpeed), - x190_gunFollowXf(xf) -{ - x1c6_24_deferBallTransitionProcessing = false; + nearz, farz, aspect, watchedObj, false, 0) +, x188_orbitCameraSpeed(orbitCameraSpeed) +, x190_gunFollowXf(xf) { + x1c6_24_deferBallTransitionProcessing = false; } -void CFirstPersonCamera::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CFirstPersonCamera::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CFirstPersonCamera::PreThink(float dt, CStateManager& mgr) { + // Empty } -void CFirstPersonCamera::PreThink(float dt, CStateManager& mgr) -{ - // Empty -} - -void CFirstPersonCamera::Think(float dt, CStateManager& mgr) -{ - if (TCastToPtr player = mgr.ObjectById(xe8_watchedObject)) - { - if (!x1c6_24_deferBallTransitionProcessing) - { - if (player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) - { - if (player->GetCameraState() != CPlayer::EPlayerCameraState::Spawned) - return; - SetTransform(player->CreateTransformFromMovementDirection()); - SetTranslation(player->GetEyePosition()); - return; - } - if (player->GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed) - { - if (player->GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphing) - return; - if (std::fabs(player->GetMorphFactor() - 1.f) >= 0.00001f) - return; - } - } - else - { - x1c6_24_deferBallTransitionProcessing = false; - } - zeus::CTransform backupXf = x34_transform; - UpdateElevation(mgr); - UpdateTransform(mgr, dt); - SetTransform(ValidateCameraTransform(x34_transform, backupXf)); - if (x1d4_closeInTimer > 0.f) - x1d4_closeInTimer -= dt; +void CFirstPersonCamera::Think(float dt, CStateManager& mgr) { + if (TCastToPtr player = mgr.ObjectById(xe8_watchedObject)) { + if (!x1c6_24_deferBallTransitionProcessing) { + if (player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { + if (player->GetCameraState() != CPlayer::EPlayerCameraState::Spawned) + return; + SetTransform(player->CreateTransformFromMovementDirection()); + SetTranslation(player->GetEyePosition()); + return; + } + if (player->GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed) { + if (player->GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphing) + return; + if (std::fabs(player->GetMorphFactor() - 1.f) >= 0.00001f) + return; + } + } else { + x1c6_24_deferBallTransitionProcessing = false; } + zeus::CTransform backupXf = x34_transform; + UpdateElevation(mgr); + UpdateTransform(mgr, dt); + SetTransform(ValidateCameraTransform(x34_transform, backupXf)); + if (x1d4_closeInTimer > 0.f) + x1d4_closeInTimer -= dt; + } } -void CFirstPersonCamera::ProcessInput(const CFinalInput&, CStateManager& mgr) -{ - // Empty +void CFirstPersonCamera::ProcessInput(const CFinalInput&, CStateManager& mgr) { + // Empty } -void CFirstPersonCamera::Reset(const zeus::CTransform& xf, CStateManager& mgr) -{ - SetTransform(xf); - SetTranslation(mgr.GetPlayer().GetEyePosition()); - x190_gunFollowXf = x34_transform; +void CFirstPersonCamera::Reset(const zeus::CTransform& xf, CStateManager& mgr) { + SetTransform(xf); + SetTranslation(mgr.GetPlayer().GetEyePosition()); + x190_gunFollowXf = x34_transform; } -void CFirstPersonCamera::SkipCinematic() -{ - x1c8_closeInVec = zeus::CVector3f::skZero; - x1d4_closeInTimer = 0.f; +void CFirstPersonCamera::SkipCinematic() { + x1c8_closeInVec = zeus::CVector3f::skZero; + x1d4_closeInTimer = 0.f; } void CFirstPersonCamera::CalculateGunFollowOrientationAndTransform(zeus::CTransform& gunXf, zeus::CQuaternion& gunQ, - float dt, zeus::CVector3f& rVec) -{ - zeus::CVector3f gunFrontVec = x190_gunFollowXf.frontVector(); - gunFrontVec.z() = 0.f; - if (gunFrontVec.canBeNormalized()) - gunFrontVec.normalize(); + float dt, zeus::CVector3f& rVec) { + zeus::CVector3f gunFrontVec = x190_gunFollowXf.frontVector(); + gunFrontVec.z() = 0.f; + if (gunFrontVec.canBeNormalized()) + gunFrontVec.normalize(); - zeus::CVector3f rVecNoZ = rVec; - rVecNoZ.z() = 0.f; - if (rVecNoZ.canBeNormalized()) - rVecNoZ.normalize(); + zeus::CVector3f rVecNoZ = rVec; + rVecNoZ.z() = 0.f; + if (rVecNoZ.canBeNormalized()) + rVecNoZ.normalize(); - gunXf = zeus::CQuaternion::lookAt(gunFrontVec, rVecNoZ, 2.f * M_PIF).toTransform() * - x190_gunFollowXf.getRotation(); + gunXf = zeus::CQuaternion::lookAt(gunFrontVec, rVecNoZ, 2.f * M_PIF).toTransform() * x190_gunFollowXf.getRotation(); - zeus::CVector3f newgunFront = gunXf.frontVector(); - if (newgunFront.canBeNormalized()) - newgunFront.normalize(); + zeus::CVector3f newgunFront = gunXf.frontVector(); + if (newgunFront.canBeNormalized()) + newgunFront.normalize(); - float angle = newgunFront.dot(rVec); - angle = zeus::clamp(-1.f, angle, 1.f); - gunQ = zeus::CQuaternion::lookAt(newgunFront, rVec, zeus::clamp(0.f, std::acos(angle) / dt, 1.f) * dt); + float angle = newgunFront.dot(rVec); + angle = zeus::clamp(-1.f, angle, 1.f); + gunQ = zeus::CQuaternion::lookAt(newgunFront, rVec, zeus::clamp(0.f, std::acos(angle) / dt, 1.f) * dt); } -void CFirstPersonCamera::UpdateTransform(CStateManager& mgr, float dt) -{ - TCastToPtr player(mgr.ObjectById(GetWatchedObject())); - if (!player) - { - SetTransform(zeus::CTransform::Identity()); - return; +void CFirstPersonCamera::UpdateTransform(CStateManager& mgr, float dt) { + TCastToPtr player(mgr.ObjectById(GetWatchedObject())); + if (!player) { + SetTransform(zeus::CTransform::Identity()); + return; + } + + zeus::CTransform playerXf = player->GetTransform(); + zeus::CVector3f rVec = playerXf.rotate( + {0.f, std::min(std::fabs(std::cos(x1c0_pitch)), 1.0f), std::min(std::fabs(std::sin(x1c0_pitch)), 1.0f)}); + if (player->x3dc_inFreeLook) { + float angle = player->x3ec_freeLookPitchAngle; + float angleClamp = g_tweakPlayer->GetVerticalFreeLookAngleVel() - std::fabs(x1c0_pitch); + angle = zeus::clamp(-angleClamp, angle, angleClamp); + zeus::CVector3f vec; + vec.z() = std::sin(angle); + vec.y() = std::cos(-player->x3e4_freeLookYawAngle) * std::cos(angle); + vec.x() = std::sin(-player->x3e4_freeLookYawAngle) * std::cos(angle); + if (g_tweakPlayer->GetFreeLookTurnsPlayer()) { + vec.x() = 0.f; + if (!zeus::close_enough(vec, zeus::CVector3f::skZero)) + vec.normalize(); } - zeus::CTransform playerXf = player->GetTransform(); - zeus::CVector3f rVec = - playerXf.rotate({0.f, std::min(std::fabs(std::cos(x1c0_pitch)), 1.0f), std::min(std::fabs(std::sin(x1c0_pitch)), 1.0f)}); - if (player->x3dc_inFreeLook) - { - float angle = player->x3ec_freeLookPitchAngle; - float angleClamp = g_tweakPlayer->GetVerticalFreeLookAngleVel() - std::fabs(x1c0_pitch); - angle = zeus::clamp(-angleClamp, angle, angleClamp); - zeus::CVector3f vec; - vec.z() = std::sin(angle); - vec.y() = std::cos(-player->x3e4_freeLookYawAngle) * std::cos(angle); - vec.x() = std::sin(-player->x3e4_freeLookYawAngle) * std::cos(angle); - if (g_tweakPlayer->GetFreeLookTurnsPlayer()) - { - vec.x() = 0.f; - if (!zeus::close_enough(vec, zeus::CVector3f::skZero)) - vec.normalize(); - } + rVec = zeus::CQuaternion::lookAt({0.f, 1.f, 0.f}, rVec, 2.f * M_PIF).transform(vec); + } - rVec = zeus::CQuaternion::lookAt({0.f, 1.f, 0.f}, rVec, 2.f * M_PIF).transform(vec); + zeus::CVector3f eyePos = player->GetEyePosition(); + if (x1d4_closeInTimer > 0.f) { + eyePos += zeus::clamp(0.f, 0.5f * x1d4_closeInTimer, 1.f) * x1c8_closeInVec; + player->GetCameraBob()->ResetCameraBobTime(); + player->GetCameraBob()->SetCameraBobTransform(zeus::CTransform::Identity()); + } + + switch (player->GetOrbitState()) { + case CPlayer::EPlayerOrbitState::ForcedOrbitObject: + case CPlayer::EPlayerOrbitState::OrbitObject: { + const CActor* act = TCastToConstPtr(mgr.GetObjectById(player->x310_orbitTargetId)); + if (act && act->GetMaterialList().HasMaterial(EMaterialTypes::Orbit)) { + zeus::CVector3f v = player->x314_orbitPoint - eyePos; + if (v.canBeNormalized()) + v.normalize(); + + rVec = v; + } else { + rVec = player->x314_orbitPoint - eyePos; } - - zeus::CVector3f eyePos = player->GetEyePosition(); - if (x1d4_closeInTimer > 0.f) - { - eyePos += zeus::clamp(0.f, 0.5f * x1d4_closeInTimer, 1.f) * x1c8_closeInVec; - player->GetCameraBob()->ResetCameraBobTime(); - player->GetCameraBob()->SetCameraBobTransform(zeus::CTransform::Identity()); + break; + } + case CPlayer::EPlayerOrbitState::OrbitPoint: + case CPlayer::EPlayerOrbitState::OrbitCarcass: { + if (!player->x3dd_lookButtonHeld) { + rVec = player->x314_orbitPoint - eyePos; } + break; + } + case CPlayer::EPlayerOrbitState::NoOrbit: { + if (player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && + !player->x3dc_inFreeLook && x1c4_pitchId == kInvalidUniqueId) { + if (player->x294_jumpCameraTimer > 0.f) { + float angle = zeus::clamp(0.f, + (player->x294_jumpCameraTimer - g_tweakPlayer->GetJumpCameraPitchDownStart()) / + g_tweakPlayer->GetJumpCameraPitchDownFull(), + 1.f) * + g_tweakPlayer->GetJumpCameraPitchDownAngle(); + angle += x1c0_pitch; + rVec.x() = 0.f; + rVec.y() = std::cos(angle); + rVec.z() = -std::sin(angle); - switch (player->GetOrbitState()) - { - case CPlayer::EPlayerOrbitState::ForcedOrbitObject: - case CPlayer::EPlayerOrbitState::OrbitObject: - { - const CActor* act = TCastToConstPtr(mgr.GetObjectById(player->x310_orbitTargetId)); - if (act && act->GetMaterialList().HasMaterial(EMaterialTypes::Orbit)) - { - zeus::CVector3f v = player->x314_orbitPoint - eyePos; - if (v.canBeNormalized()) - v.normalize(); + rVec = playerXf.rotate(rVec); + } else if (player->x29c_fallCameraTimer > 0.f) { + float angle = zeus::clamp(0.f, + (player->x29c_fallCameraTimer - g_tweakPlayer->GetFallCameraPitchDownStart()) / + g_tweakPlayer->GetFallCameraPitchDownFull(), + 1.f) * + g_tweakPlayer->GetFallCameraPitchDownAngle(); + rVec.x() = 0.f; + rVec.y() = std::cos(angle); + rVec.z() = -std::sin(angle); - rVec = v; - } - else - { - rVec = player->x314_orbitPoint - eyePos; - } - break; + rVec = playerXf.rotate(rVec); + } + } + break; + } + default: + break; + } + + if (rVec.canBeNormalized()) + rVec.normalize(); + + zeus::CTransform gunXf = x190_gunFollowXf; + zeus::CQuaternion qGun = zeus::CQuaternion::skNoRotation; + + if (!player->x3dc_inFreeLook) { + switch (player->GetOrbitState()) { + default: { + CalculateGunFollowOrientationAndTransform(gunXf, qGun, dt * g_tweakPlayer->GetFirstPersonCameraSpeed(), rVec); + break; + } + case CPlayer::EPlayerOrbitState::Grapple: { + CalculateGunFollowOrientationAndTransform(gunXf, qGun, dt * g_tweakPlayer->GetGrappleCameraSpeed(), rVec); + break; } case CPlayer::EPlayerOrbitState::OrbitPoint: - case CPlayer::EPlayerOrbitState::OrbitCarcass: - { - if (!player->x3dd_lookButtonHeld) - { - rVec = player->x314_orbitPoint - eyePos; - } - break; + case CPlayer::EPlayerOrbitState::OrbitCarcass: { + CalculateGunFollowOrientationAndTransform(gunXf, qGun, dt * g_tweakPlayer->GetOrbitCameraSpeed() * 0.25f, rVec); + break; } - case CPlayer::EPlayerOrbitState::NoOrbit: - { - if (player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && - !player->x3dc_inFreeLook && x1c4_pitchId == kInvalidUniqueId) - { - if (player->x294_jumpCameraTimer > 0.f) - { - float angle = zeus::clamp(0.f, (player->x294_jumpCameraTimer - g_tweakPlayer->GetJumpCameraPitchDownStart()) / - g_tweakPlayer->GetJumpCameraPitchDownFull(), 1.f) * - g_tweakPlayer->GetJumpCameraPitchDownAngle(); - angle += x1c0_pitch; - rVec.x() = 0.f; - rVec.y() = std::cos(angle); - rVec.z() = -std::sin(angle); + case CPlayer::EPlayerOrbitState::ForcedOrbitObject: + case CPlayer::EPlayerOrbitState::OrbitObject: { + zeus::CVector3f gunFrontVec = x190_gunFollowXf.frontVector(); - rVec = playerXf.rotate(rVec); - } - else if (player->x29c_fallCameraTimer > 0.f) - { - float angle = zeus::clamp(0.f, (player->x29c_fallCameraTimer - g_tweakPlayer->GetFallCameraPitchDownStart()) / - g_tweakPlayer->GetFallCameraPitchDownFull(), 1.f) * - g_tweakPlayer->GetFallCameraPitchDownAngle(); - rVec.x() = 0.f; - rVec.y() = std::cos(angle); - rVec.z() = -std::sin(angle); + if (gunFrontVec.canBeNormalized()) + gunFrontVec.normalize(); - rVec = playerXf.rotate(rVec); - } - } - break; - } - default: - break; - } + float scaledDt = (dt * g_tweakPlayer->GetOrbitCameraSpeed()); + float angle = gunFrontVec.dot(rVec); + angle = zeus::clamp(-1.f, angle, 1.f); + float clampedAngle = zeus::clamp(0.f, std::acos(angle) / scaledDt, 1.f); + if (angle > 0.999f || x18c_lockCamera || player->x374_orbitLockEstablished) + qGun = zeus::CQuaternion::lookAt(gunFrontVec, rVec, 2.f * M_PIF); + else + qGun = zeus::CQuaternion::lookAt(gunFrontVec, rVec, scaledDt * clampedAngle); - if (rVec.canBeNormalized()) - rVec.normalize(); - - zeus::CTransform gunXf = x190_gunFollowXf; - zeus::CQuaternion qGun = zeus::CQuaternion::skNoRotation; - - if (!player->x3dc_inFreeLook) - { - switch (player->GetOrbitState()) - { - default: - { - CalculateGunFollowOrientationAndTransform(gunXf, qGun, - dt * g_tweakPlayer->GetFirstPersonCameraSpeed(), rVec); - break; - } - case CPlayer::EPlayerOrbitState::Grapple: - { - CalculateGunFollowOrientationAndTransform(gunXf, qGun, - dt * g_tweakPlayer->GetGrappleCameraSpeed(), rVec); - break; - } - case CPlayer::EPlayerOrbitState::OrbitPoint: - case CPlayer::EPlayerOrbitState::OrbitCarcass: - { - CalculateGunFollowOrientationAndTransform(gunXf, qGun, - dt * g_tweakPlayer->GetOrbitCameraSpeed() * 0.25f, rVec); - break; - } - case CPlayer::EPlayerOrbitState::ForcedOrbitObject: - case CPlayer::EPlayerOrbitState::OrbitObject: - { - zeus::CVector3f gunFrontVec = x190_gunFollowXf.frontVector(); - - if (gunFrontVec.canBeNormalized()) - gunFrontVec.normalize(); - - float scaledDt = (dt * g_tweakPlayer->GetOrbitCameraSpeed()); - float angle = gunFrontVec.dot(rVec); - angle = zeus::clamp(-1.f, angle, 1.f); - float clampedAngle = zeus::clamp(0.f, std::acos(angle) / scaledDt, 1.f); - if (angle > 0.999f || x18c_lockCamera || player->x374_orbitLockEstablished) - qGun = zeus::CQuaternion::lookAt(gunFrontVec, rVec, 2.f * M_PIF); - else - qGun = zeus::CQuaternion::lookAt(gunFrontVec, rVec, scaledDt * clampedAngle); - - const CScriptGrapplePoint* gPoint = - TCastToConstPtr(mgr.GetObjectById(player->x310_orbitTargetId)); - if (gPoint && player->x29c_fallCameraTimer > 0.f) - { - gunFrontVec = x190_gunFollowXf.frontVector(); - if (gunFrontVec.canBeNormalized()) - gunFrontVec.normalize(); - - zeus::CVector3f rVecCpy = rVec; - rVecCpy.z() = 0.f; - if (rVecCpy.canBeNormalized()) - rVecCpy.normalize(); - - gunXf = - zeus::CQuaternion::lookAt(gunFrontVec, rVecCpy, 2.f * M_PIF).toTransform() * - x190_gunFollowXf.getRotation(); - - gunFrontVec = gunXf.frontVector(); - if (gunFrontVec.canBeNormalized()) - gunFrontVec.normalize(); - - //float angle = gunFrontVec.dot(rVec); - //float sdt = dt * g_tweakPlayer->GetGrappleCameraSpeed(); - - //angle = zeus::clamp(-1.f, angle, 1.f); - //angle = zeus::clamp(0.f, std::acos(angle) / sdt, 1.f); - qGun = zeus::CQuaternion::lookAt(gunFrontVec, rVecCpy, 2.f * M_PIF); - } - break; - } - } - } - else - { - zeus::CVector3f gunFront = x190_gunFollowXf.frontVector(); - gunFront.z() = 0.f; - if (gunFront.canBeNormalized()) - gunFront.normalize(); + const CScriptGrapplePoint* gPoint = + TCastToConstPtr(mgr.GetObjectById(player->x310_orbitTargetId)); + if (gPoint && player->x29c_fallCameraTimer > 0.f) { + gunFrontVec = x190_gunFollowXf.frontVector(); + if (gunFrontVec.canBeNormalized()) + gunFrontVec.normalize(); zeus::CVector3f rVecCpy = rVec; rVecCpy.z() = 0.f; if (rVecCpy.canBeNormalized()) - rVecCpy.normalize(); + rVecCpy.normalize(); - gunXf = zeus::CQuaternion::lookAt(gunFront, rVecCpy, 2.f * M_PIF).toTransform() * - x190_gunFollowXf.getRotation(); - gunFront = gunXf.frontVector(); - if (gunFront.canBeNormalized()) - gunFront.normalize(); + gunXf = + zeus::CQuaternion::lookAt(gunFrontVec, rVecCpy, 2.f * M_PIF).toTransform() * x190_gunFollowXf.getRotation(); - float angle = gunFront.dot(rVec); - angle = zeus::clamp(-1.f, angle, 1.f); - float sdt = dt * g_tweakPlayer->GetFreeLookSpeed(); - qGun = zeus::CQuaternion::lookAt( - gunFront, rVec, sdt * zeus::clamp(0.f, g_tweakPlayer->GetFreeLookDampenFactor() * - (std::acos(angle) / sdt), 1.f)); + gunFrontVec = gunXf.frontVector(); + if (gunFrontVec.canBeNormalized()) + gunFrontVec.normalize(); + + // float angle = gunFrontVec.dot(rVec); + // float sdt = dt * g_tweakPlayer->GetGrappleCameraSpeed(); + + // angle = zeus::clamp(-1.f, angle, 1.f); + // angle = zeus::clamp(0.f, std::acos(angle) / sdt, 1.f); + qGun = zeus::CQuaternion::lookAt(gunFrontVec, rVecCpy, 2.f * M_PIF); + } + break; } - zeus::CTransform bobXf = player->GetCameraBob()->GetCameraBobTransformation(); - - if (player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed || - player->GetOrbitState() == CPlayer::EPlayerOrbitState::Grapple || - player->GetGrappleState() != CPlayer::EGrappleState::None || - mgr.GetGameState() == CStateManager::EGameState::SoftPaused || - mgr.GetCameraManager()->IsInCinematicCamera() || - x1d4_closeInTimer > 0.f) - { - bobXf = zeus::CTransform::Identity(); - player->GetCameraBob()->SetCameraBobTransform(bobXf); } + } else { + zeus::CVector3f gunFront = x190_gunFollowXf.frontVector(); + gunFront.z() = 0.f; + if (gunFront.canBeNormalized()) + gunFront.normalize(); - x190_gunFollowXf = qGun.toTransform() * gunXf; - SetTransform(x190_gunFollowXf * bobXf.getRotation()); - x190_gunFollowXf.origin = eyePos; - CActor::SetTranslation(eyePos + player->GetTransform().rotate(bobXf.origin)); - x190_gunFollowXf.orthonormalize(); + zeus::CVector3f rVecCpy = rVec; + rVecCpy.z() = 0.f; + if (rVecCpy.canBeNormalized()) + rVecCpy.normalize(); + + gunXf = zeus::CQuaternion::lookAt(gunFront, rVecCpy, 2.f * M_PIF).toTransform() * x190_gunFollowXf.getRotation(); + gunFront = gunXf.frontVector(); + if (gunFront.canBeNormalized()) + gunFront.normalize(); + + float angle = gunFront.dot(rVec); + angle = zeus::clamp(-1.f, angle, 1.f); + float sdt = dt * g_tweakPlayer->GetFreeLookSpeed(); + qGun = zeus::CQuaternion::lookAt( + gunFront, rVec, + sdt * zeus::clamp(0.f, g_tweakPlayer->GetFreeLookDampenFactor() * (std::acos(angle) / sdt), 1.f)); + } + zeus::CTransform bobXf = player->GetCameraBob()->GetCameraBobTransformation(); + + if (player->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed || + player->GetOrbitState() == CPlayer::EPlayerOrbitState::Grapple || + player->GetGrappleState() != CPlayer::EGrappleState::None || + mgr.GetGameState() == CStateManager::EGameState::SoftPaused || mgr.GetCameraManager()->IsInCinematicCamera() || + x1d4_closeInTimer > 0.f) { + bobXf = zeus::CTransform::Identity(); + player->GetCameraBob()->SetCameraBobTransform(bobXf); + } + + x190_gunFollowXf = qGun.toTransform() * gunXf; + SetTransform(x190_gunFollowXf * bobXf.getRotation()); + x190_gunFollowXf.origin = eyePos; + CActor::SetTranslation(eyePos + player->GetTransform().rotate(bobXf.origin)); + x190_gunFollowXf.orthonormalize(); } -void CFirstPersonCamera::UpdateElevation(CStateManager& mgr) -{ - x1c0_pitch = 0.f; - if (TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject)) - { - if (x1c4_pitchId != kInvalidUniqueId) - { - if (TCastToConstPtr pvol = mgr.GetObjectById(x1c4_pitchId)) - { - zeus::CVector3f pitchDirFlat = pvol->GetTransform().basis[1]; - pitchDirFlat.z() = 0.f; - if (!pitchDirFlat.canBeNormalized()) - pitchDirFlat = zeus::CVector3f::skForward; +void CFirstPersonCamera::UpdateElevation(CStateManager& mgr) { + x1c0_pitch = 0.f; + if (TCastToConstPtr player = mgr.GetObjectById(xe8_watchedObject)) { + if (x1c4_pitchId != kInvalidUniqueId) { + if (TCastToConstPtr pvol = mgr.GetObjectById(x1c4_pitchId)) { + zeus::CVector3f pitchDirFlat = pvol->GetTransform().basis[1]; + pitchDirFlat.z() = 0.f; + if (!pitchDirFlat.canBeNormalized()) + pitchDirFlat = zeus::CVector3f::skForward; - zeus::CVector3f playerDirFlat = player->GetTransform().basis[1]; - playerDirFlat.z() = 0.f; - playerDirFlat.normalize(); + zeus::CVector3f playerDirFlat = player->GetTransform().basis[1]; + playerDirFlat.z() = 0.f; + playerDirFlat.normalize(); - float pitchDot = zeus::clamp(-1.f, pitchDirFlat.dot(playerDirFlat), 1.f); - if (pitchDot < 0.f) - x1c0_pitch = pvol->GetDownPitch() * -pitchDot; - else - x1c0_pitch = pvol->GetUpPitch() * -pitchDot; + float pitchDot = zeus::clamp(-1.f, pitchDirFlat.dot(playerDirFlat), 1.f); + if (pitchDot < 0.f) + x1c0_pitch = pvol->GetDownPitch() * -pitchDot; + else + x1c0_pitch = pvol->GetUpPitch() * -pitchDot; - zeus::CVector3f pvolToPlayerFlat = player->GetTranslation() - pvol->GetTranslation(); - pvolToPlayerFlat.z() = 0.f; - float pitchMul = 0.f; - if (pvolToPlayerFlat.canBeNormalized()) - { - float pvolPlayerProj = - std::fabs(zeus::clamp(-1.f, pvolToPlayerFlat.dot(pitchDirFlat), 1.f)) * - pvolToPlayerFlat.magnitude(); - if (pvolPlayerProj <= pvol->GetMaxInterpolationDistance()) - pitchMul = 1.f; - else - pitchMul = 1.f - zeus::clamp(-1.f, (pvolPlayerProj - pvol->GetMaxInterpolationDistance()) / - (pvol->GetScale().y() - pvol->GetMaxInterpolationDistance()), 1.f); - } - x1c0_pitch *= pitchMul; - } + zeus::CVector3f pvolToPlayerFlat = player->GetTranslation() - pvol->GetTranslation(); + pvolToPlayerFlat.z() = 0.f; + float pitchMul = 0.f; + if (pvolToPlayerFlat.canBeNormalized()) { + float pvolPlayerProj = + std::fabs(zeus::clamp(-1.f, pvolToPlayerFlat.dot(pitchDirFlat), 1.f)) * pvolToPlayerFlat.magnitude(); + if (pvolPlayerProj <= pvol->GetMaxInterpolationDistance()) + pitchMul = 1.f; + else + pitchMul = 1.f - zeus::clamp(-1.f, + (pvolPlayerProj - pvol->GetMaxInterpolationDistance()) / + (pvol->GetScale().y() - pvol->GetMaxInterpolationDistance()), + 1.f); } + x1c0_pitch *= pitchMul; + } } + } } -} +} // namespace urde diff --git a/Runtime/Camera/CFirstPersonCamera.hpp b/Runtime/Camera/CFirstPersonCamera.hpp index b10376ade..c5e6746b2 100644 --- a/Runtime/Camera/CFirstPersonCamera.hpp +++ b/Runtime/Camera/CFirstPersonCamera.hpp @@ -2,38 +2,35 @@ #include "CGameCamera.hpp" -namespace urde -{ +namespace urde { -class CFirstPersonCamera : public CGameCamera -{ - float x188_orbitCameraSpeed; - bool x18c_lockCamera = false; - zeus::CTransform x190_gunFollowXf; - float x1c0_pitch = 0.f; - TUniqueId x1c4_pitchId = kInvalidUniqueId; - bool x1c6_24_deferBallTransitionProcessing : 1; - zeus::CVector3f x1c8_closeInVec; - float x1d4_closeInTimer = 0.f; +class CFirstPersonCamera : public CGameCamera { + float x188_orbitCameraSpeed; + bool x18c_lockCamera = false; + zeus::CTransform x190_gunFollowXf; + float x1c0_pitch = 0.f; + TUniqueId x1c4_pitchId = kInvalidUniqueId; + bool x1c6_24_deferBallTransitionProcessing : 1; + zeus::CVector3f x1c8_closeInVec; + float x1d4_closeInTimer = 0.f; public: - CFirstPersonCamera(TUniqueId, const zeus::CTransform& xf, TUniqueId, float orbitCameraSpeed, - float fov, float nearplane, float farplane, float aspect); + CFirstPersonCamera(TUniqueId, const zeus::CTransform& xf, TUniqueId, float orbitCameraSpeed, float fov, + float nearplane, float farplane, float aspect); - void Accept(IVisitor& visitor); - void PreThink(float dt, CStateManager& mgr); - void Think(float dt, CStateManager& mgr); - void ProcessInput(const CFinalInput&, CStateManager& mgr); - void Reset(const zeus::CTransform&, CStateManager& mgr); + void Accept(IVisitor& visitor); + void PreThink(float dt, CStateManager& mgr); + void Think(float dt, CStateManager& mgr); + void ProcessInput(const CFinalInput&, CStateManager& mgr); + void Reset(const zeus::CTransform&, CStateManager& mgr); - void SkipCinematic(); - const zeus::CTransform& GetGunFollowTransform() const { return x190_gunFollowXf; } - void UpdateTransform(CStateManager& mgr, float dt); - void UpdateElevation(CStateManager& mgr); - void CalculateGunFollowOrientationAndTransform(zeus::CTransform&, zeus::CQuaternion&, float, zeus::CVector3f&); - void SetScriptPitchId(TUniqueId uid) { x1c4_pitchId = uid; } - void SetLockCamera(bool v) { x18c_lockCamera = v; } - void DeferBallTransitionProcessing() { x1c6_24_deferBallTransitionProcessing = true; } + void SkipCinematic(); + const zeus::CTransform& GetGunFollowTransform() const { return x190_gunFollowXf; } + void UpdateTransform(CStateManager& mgr, float dt); + void UpdateElevation(CStateManager& mgr); + void CalculateGunFollowOrientationAndTransform(zeus::CTransform&, zeus::CQuaternion&, float, zeus::CVector3f&); + void SetScriptPitchId(TUniqueId uid) { x1c4_pitchId = uid; } + void SetLockCamera(bool v) { x18c_lockCamera = v; } + void DeferBallTransitionProcessing() { x1c6_24_deferBallTransitionProcessing = true; } }; -} - +} // namespace urde diff --git a/Runtime/Camera/CGameCamera.cpp b/Runtime/Camera/CGameCamera.cpp index 0a9d38d4a..1ea10eaa8 100644 --- a/Runtime/Camera/CGameCamera.cpp +++ b/Runtime/Camera/CGameCamera.cpp @@ -3,8 +3,7 @@ #include "Camera/CCameraManager.hpp" #include "World/CActorParameters.hpp" -namespace urde -{ +namespace urde { CGameCamera::CGameCamera(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, float fovy, float znear, float zfar, float aspect, @@ -21,139 +20,117 @@ CGameCamera::CGameCamera(TUniqueId uid, bool active, std::string_view name, cons , x170_24_perspDirty(true) , x170_25_disablesInput(disableInput) , x180_perspInterpStartFov(fovy) -, x184_perspInterpEndFov(fovy) -{ +, x184_perspInterpEndFov(fovy) { - xe7_29_drawEnabled = false; + xe7_29_drawEnabled = false; } -void CGameCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::AddSplashInhabitant) - { - mgr.GetCameraManager()->SetInsideFluid(true, uid); - return; - } - else if (msg == EScriptObjectMessage::RemoveSplashInhabitant) - { - mgr.GetCameraManager()->SetInsideFluid(false, kInvalidUniqueId); - return; - } +void CGameCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::AddSplashInhabitant) { + mgr.GetCameraManager()->SetInsideFluid(true, uid); + return; + } else if (msg == EScriptObjectMessage::RemoveSplashInhabitant) { + mgr.GetCameraManager()->SetInsideFluid(false, kInvalidUniqueId); + return; + } - CActor::AcceptScriptMsg(msg, uid, mgr); + CActor::AcceptScriptMsg(msg, uid, mgr); } -void CGameCamera::SetActive(bool active) -{ - CActor::SetActive(active); - xe7_29_drawEnabled = false; +void CGameCamera::SetActive(bool active) { + CActor::SetActive(active); + xe7_29_drawEnabled = false; } -zeus::CMatrix4f CGameCamera::GetPerspectiveMatrix() const -{ - if (x170_24_perspDirty) - { - const_cast(this)->xec_perspectiveMatrix = - CGraphics::CalculatePerspectiveMatrix(x15c_currentFov, x168_aspect, x160_znear, x164_zfar, false); - const_cast(this)->x170_24_perspDirty = false; - } +zeus::CMatrix4f CGameCamera::GetPerspectiveMatrix() const { + if (x170_24_perspDirty) { + const_cast(this)->xec_perspectiveMatrix = + CGraphics::CalculatePerspectiveMatrix(x15c_currentFov, x168_aspect, x160_znear, x164_zfar, false); + const_cast(this)->x170_24_perspDirty = false; + } - return xec_perspectiveMatrix; + return xec_perspectiveMatrix; } -zeus::CVector3f CGameCamera::ConvertToScreenSpace(const zeus::CVector3f& v) const -{ - zeus::CVector3f rVec = x34_transform.transposeRotate(v - x34_transform.origin); +zeus::CVector3f CGameCamera::ConvertToScreenSpace(const zeus::CVector3f& v) const { + zeus::CVector3f rVec = x34_transform.transposeRotate(v - x34_transform.origin); - if (rVec.isZero()) - return {-1.f, -1.f, 1.f}; + if (rVec.isZero()) + return {-1.f, -1.f, 1.f}; - rVec = zeus::CVector3f(rVec.x(), rVec.z(), -rVec.y()); - zeus::CMatrix4f mtx = GetPerspectiveMatrix(); - return mtx.multiplyOneOverW(rVec); + rVec = zeus::CVector3f(rVec.x(), rVec.z(), -rVec.y()); + zeus::CMatrix4f mtx = GetPerspectiveMatrix(); + return mtx.multiplyOneOverW(rVec); } -zeus::CTransform CGameCamera::ValidateCameraTransform(const zeus::CTransform& newXf, const zeus::CTransform& oldXf) -{ - zeus::CTransform xfCpy(newXf); - if (!zeus::close_enough(newXf.rightVector().magnitude(), 1.f) || - !zeus::close_enough(newXf.frontVector().magnitude(), 1.f) || - !zeus::close_enough(newXf.upVector().magnitude(), 1.f)) - xfCpy.orthonormalize(); - float f2 = zeus::clamp(-1.f, newXf.frontVector().dot(zeus::CVector3f::skUp), 1.f); - if (std::fabs(f2) > 0.999f) - xfCpy = oldXf; +zeus::CTransform CGameCamera::ValidateCameraTransform(const zeus::CTransform& newXf, const zeus::CTransform& oldXf) { + zeus::CTransform xfCpy(newXf); + if (!zeus::close_enough(newXf.rightVector().magnitude(), 1.f) || + !zeus::close_enough(newXf.frontVector().magnitude(), 1.f) || + !zeus::close_enough(newXf.upVector().magnitude(), 1.f)) + xfCpy.orthonormalize(); + float f2 = zeus::clamp(-1.f, newXf.frontVector().dot(zeus::CVector3f::skUp), 1.f); + if (std::fabs(f2) > 0.999f) + xfCpy = oldXf; - if (xfCpy.upVector().z() < -0.2f) - xfCpy = zeus::CQuaternion::fromAxisAngle(xfCpy.frontVector(), M_PIF).toTransform() * xfCpy; + if (xfCpy.upVector().z() < -0.2f) + xfCpy = zeus::CQuaternion::fromAxisAngle(xfCpy.frontVector(), M_PIF).toTransform() * xfCpy; - if (!zeus::close_enough(xfCpy.rightVector().z(), 0.f) && - !zeus::close_enough(xfCpy.upVector().z(), 0.f)) - { - if (xfCpy.frontVector().canBeNormalized()) - xfCpy = zeus::lookAt(zeus::CVector3f::skZero, xfCpy.frontVector()); - else - xfCpy = oldXf; - } - - xfCpy.origin = newXf.origin; - return xfCpy; -} - -void CGameCamera::UpdatePerspective(float dt) -{ - if (x174_delayTime > 0.f) - { - x174_delayTime -= dt; - return; - } - - if (x178_perspInterpRemTime <= 0.f) - return; - - x178_perspInterpRemTime -= dt; - if (x178_perspInterpRemTime <= 0.f) - { - x15c_currentFov = x184_perspInterpEndFov; - x170_24_perspDirty = true; - } + if (!zeus::close_enough(xfCpy.rightVector().z(), 0.f) && !zeus::close_enough(xfCpy.upVector().z(), 0.f)) { + if (xfCpy.frontVector().canBeNormalized()) + xfCpy = zeus::lookAt(zeus::CVector3f::skZero, xfCpy.frontVector()); else - { - x15c_currentFov = zeus::clamp(0.f, (x178_perspInterpRemTime / x17c_perspInterpDur), 1.f) * - (x180_perspInterpStartFov - x184_perspInterpEndFov) + x184_perspInterpEndFov; - x170_24_perspDirty = true; - } + xfCpy = oldXf; + } + + xfCpy.origin = newXf.origin; + return xfCpy; } -void CGameCamera::SetFovInterpolation(float start, float fov, float time, float delayTime) -{ - if (time < 0.f) - { - x15c_currentFov = fov; - x170_24_perspDirty = true; - x184_perspInterpEndFov = fov; - x178_perspInterpRemTime = x174_delayTime = 0.f; - } - else - { - x174_delayTime = std::max(0.f, delayTime); - x17c_perspInterpDur = time; - x178_perspInterpRemTime = time; - x180_perspInterpStartFov = start; - x184_perspInterpEndFov = fov; - x15c_currentFov = start; - x170_24_perspDirty = true; - } +void CGameCamera::UpdatePerspective(float dt) { + if (x174_delayTime > 0.f) { + x174_delayTime -= dt; + return; + } + + if (x178_perspInterpRemTime <= 0.f) + return; + + x178_perspInterpRemTime -= dt; + if (x178_perspInterpRemTime <= 0.f) { + x15c_currentFov = x184_perspInterpEndFov; + x170_24_perspDirty = true; + } else { + x15c_currentFov = zeus::clamp(0.f, (x178_perspInterpRemTime / x17c_perspInterpDur), 1.f) * + (x180_perspInterpStartFov - x184_perspInterpEndFov) + + x184_perspInterpEndFov; + x170_24_perspDirty = true; + } } -void CGameCamera::SkipFovInterpolation() -{ - if (x178_perspInterpRemTime > 0) - { - x15c_currentFov = x184_perspInterpEndFov; - x170_24_perspDirty = true; - } - +void CGameCamera::SetFovInterpolation(float start, float fov, float time, float delayTime) { + if (time < 0.f) { + x15c_currentFov = fov; + x170_24_perspDirty = true; + x184_perspInterpEndFov = fov; x178_perspInterpRemTime = x174_delayTime = 0.f; + } else { + x174_delayTime = std::max(0.f, delayTime); + x17c_perspInterpDur = time; + x178_perspInterpRemTime = time; + x180_perspInterpStartFov = start; + x184_perspInterpEndFov = fov; + x15c_currentFov = start; + x170_24_perspDirty = true; + } } + +void CGameCamera::SkipFovInterpolation() { + if (x178_perspInterpRemTime > 0) { + x15c_currentFov = x184_perspInterpEndFov; + x170_24_perspDirty = true; + } + + x178_perspInterpRemTime = x174_delayTime = 0.f; } +} // namespace urde diff --git a/Runtime/Camera/CGameCamera.hpp b/Runtime/Camera/CGameCamera.hpp index 33681cc8c..f486092b1 100644 --- a/Runtime/Camera/CGameCamera.hpp +++ b/Runtime/Camera/CGameCamera.hpp @@ -3,54 +3,52 @@ #include "World/CActor.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { struct CFinalInput; -class CGameCamera : public CActor -{ - friend class CStateManager; - friend class CCameraManager; +class CGameCamera : public CActor { + friend class CStateManager; + friend class CCameraManager; protected: - TUniqueId xe8_watchedObject; - zeus::CMatrix4f xec_perspectiveMatrix; - zeus::CTransform x12c_origXf; - float x15c_currentFov; - float x160_znear; - float x164_zfar; - float x168_aspect; - u32 x16c_controllerIdx; - bool x170_24_perspDirty : 1; - bool x170_25_disablesInput : 1; - float x174_delayTime = 0.f; - float x178_perspInterpRemTime = 0.f; - float x17c_perspInterpDur = 0.f; - float x180_perspInterpStartFov; - float x184_perspInterpEndFov; + TUniqueId xe8_watchedObject; + zeus::CMatrix4f xec_perspectiveMatrix; + zeus::CTransform x12c_origXf; + float x15c_currentFov; + float x160_znear; + float x164_zfar; + float x168_aspect; + u32 x16c_controllerIdx; + bool x170_24_perspDirty : 1; + bool x170_25_disablesInput : 1; + float x174_delayTime = 0.f; + float x178_perspInterpRemTime = 0.f; + float x17c_perspInterpDur = 0.f; + float x180_perspInterpStartFov; + float x184_perspInterpEndFov; + public: - CGameCamera(TUniqueId, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - float fov, float nearz, float farz, float aspect, TUniqueId watchedId, bool disableInput, - u32 controllerIdx); + CGameCamera(TUniqueId, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + float fov, float nearz, float farz, float aspect, TUniqueId watchedId, bool disableInput, + u32 controllerIdx); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void SetActive(bool active); - virtual void ProcessInput(const CFinalInput&, CStateManager& mgr) = 0; - virtual void Reset(const zeus::CTransform&, CStateManager& mgr) = 0; + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void SetActive(bool active); + virtual void ProcessInput(const CFinalInput&, CStateManager& mgr) = 0; + virtual void Reset(const zeus::CTransform&, CStateManager& mgr) = 0; - zeus::CMatrix4f GetPerspectiveMatrix() const; - zeus::CVector3f ConvertToScreenSpace(const zeus::CVector3f&) const; - zeus::CTransform ValidateCameraTransform(const zeus::CTransform&, const zeus::CTransform&); - float GetNearClipDistance() const { return x160_znear; } - float GetFarClipDistance() const { return x164_zfar; } - float GetAspectRatio() const { return x168_aspect; } - TUniqueId GetWatchedObject() const { return xe8_watchedObject; } - float GetFov() const { return x15c_currentFov; } - void GetControllerNumber() const; - bool DisablesInput() const; - void UpdatePerspective(float); - void SetFovInterpolation(float start, float end, float time, float delayTime); - void SkipFovInterpolation(); + zeus::CMatrix4f GetPerspectiveMatrix() const; + zeus::CVector3f ConvertToScreenSpace(const zeus::CVector3f&) const; + zeus::CTransform ValidateCameraTransform(const zeus::CTransform&, const zeus::CTransform&); + float GetNearClipDistance() const { return x160_znear; } + float GetFarClipDistance() const { return x164_zfar; } + float GetAspectRatio() const { return x168_aspect; } + TUniqueId GetWatchedObject() const { return xe8_watchedObject; } + float GetFov() const { return x15c_currentFov; } + void GetControllerNumber() const; + bool DisablesInput() const; + void UpdatePerspective(float); + void SetFovInterpolation(float start, float end, float time, float delayTime); + void SkipFovInterpolation(); }; -} - +} // namespace urde diff --git a/Runtime/Camera/CInterpolationCamera.cpp b/Runtime/Camera/CInterpolationCamera.cpp index c3cdee0b5..e31ec8882 100644 --- a/Runtime/Camera/CInterpolationCamera.cpp +++ b/Runtime/Camera/CInterpolationCamera.cpp @@ -6,235 +6,201 @@ #include "World/CScriptSpindleCamera.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CInterpolationCamera::CInterpolationCamera(TUniqueId uid, const zeus::CTransform& xf) : CGameCamera(uid, false, "Interpolation Camera", - CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList, kInvalidEditorId), - xf, CCameraManager::ThirdPersonFOV(), CCameraManager::NearPlane(), - CCameraManager::FarPlane(), CCameraManager::Aspect(), kInvalidUniqueId, false, 0) -{ + CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList, kInvalidEditorId), xf, + CCameraManager::ThirdPersonFOV(), CCameraManager::NearPlane(), CCameraManager::FarPlane(), + CCameraManager::Aspect(), kInvalidUniqueId, false, 0) {} + +void CInterpolationCamera::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CInterpolationCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + CGameCamera::AcceptScriptMsg(msg, sender, mgr); } -void CInterpolationCamera::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CInterpolationCamera::ProcessInput(const CFinalInput& input, CStateManager& mgr) { + // Empty } -void CInterpolationCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - CGameCamera::AcceptScriptMsg(msg, sender, mgr); +void CInterpolationCamera::Render(const CStateManager& mgr) const { + // Empty } -void CInterpolationCamera::ProcessInput(const CFinalInput& input, CStateManager& mgr) -{ - // Empty +void CInterpolationCamera::Reset(const zeus::CTransform&, CStateManager& mgr) { + // Empty } -void CInterpolationCamera::Render(const CStateManager& mgr) const -{ - // Empty -} +void CInterpolationCamera::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; -void CInterpolationCamera::Reset(const zeus::CTransform&, CStateManager& mgr) -{ - // Empty -} + x15c_currentFov = mgr.GetCameraManager()->GetBallCamera()->GetFov(); + x170_24_perspDirty = true; + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphing) + DeactivateInterpCamera(mgr); -void CInterpolationCamera::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; + x18c_time += dt; + if (x18c_time > x190_maxTime) + x18c_time = x190_maxTime; - x15c_currentFov = mgr.GetCameraManager()->GetBallCamera()->GetFov(); - x170_24_perspDirty = true; - if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphing) - DeactivateInterpCamera(mgr); + zeus::CTransform xf = GetTransform(); - x18c_time += dt; - if (x18c_time > x190_maxTime) - x18c_time = x190_maxTime; - - zeus::CTransform xf = GetTransform(); - - if (TCastToConstPtr cam = mgr.GetObjectById(x188_targetId)) - { - zeus::CVector3f targetOrigin = cam->GetTranslation(); - zeus::CVector3f ballLookPos = mgr.GetCameraManager()->GetBallCamera()->GetLookPos(); - if (mgr.GetCameraManager()->GetBallCamera()->GetBehaviour() == CBallCamera::EBallCameraBehaviour::SpindleCamera) - { - if (TCastToConstPtr spindle = mgr.GetObjectById(mgr.GetCameraManager()->GetSpindleCameraId())) - { - float mag = (mgr.GetPlayer().GetTranslation() - spindle->GetTranslation()).magnitude(); - ballLookPos = spindle->GetTranslation() + (mag * spindle->GetTransform().frontVector()); - } - } - bool deactivate = false; - - if (x1d8_24_sinusoidal) - deactivate = InterpolateSinusoidal(xf, targetOrigin, ballLookPos, x190_maxTime, x18c_time); - else - deactivate = InterpolateWithDistance(xf, targetOrigin, ballLookPos, - x1d0_positionSpeed, x1d4_rotationSpeed, dt, x190_maxTime, x18c_time); - - SetTransform(xf); - if (deactivate) - DeactivateInterpCamera(mgr); + if (TCastToConstPtr cam = mgr.GetObjectById(x188_targetId)) { + zeus::CVector3f targetOrigin = cam->GetTranslation(); + zeus::CVector3f ballLookPos = mgr.GetCameraManager()->GetBallCamera()->GetLookPos(); + if (mgr.GetCameraManager()->GetBallCamera()->GetBehaviour() == CBallCamera::EBallCameraBehaviour::SpindleCamera) { + if (TCastToConstPtr spindle = + mgr.GetObjectById(mgr.GetCameraManager()->GetSpindleCameraId())) { + float mag = (mgr.GetPlayer().GetTranslation() - spindle->GetTranslation()).magnitude(); + ballLookPos = spindle->GetTranslation() + (mag * spindle->GetTransform().frontVector()); + } } + bool deactivate = false; + + if (x1d8_24_sinusoidal) + deactivate = InterpolateSinusoidal(xf, targetOrigin, ballLookPos, x190_maxTime, x18c_time); else - DeactivateInterpCamera(mgr); -} + deactivate = InterpolateWithDistance(xf, targetOrigin, ballLookPos, x1d0_positionSpeed, x1d4_rotationSpeed, dt, + x190_maxTime, x18c_time); -void CInterpolationCamera::SetInterpolation(const zeus::CTransform& xf, const zeus::CVector3f& lookPos, - float maxTime, float positionSpeed, float rotationSpeed, - TUniqueId camId, bool sinusoidal, CStateManager& mgr) -{ - SetActive(true); SetTransform(xf); - x1c4_lookPos = lookPos; - x188_targetId = camId; - x1d8_24_sinusoidal = sinusoidal; - x190_maxTime = maxTime; - x1d0_positionSpeed = positionSpeed; - x1d4_rotationSpeed = rotationSpeed; - x1dc_closeInAngle = 2.f * M_PIF; - x18c_time = 0.f; - - if (TCastToConstPtr cam = (mgr.GetObjectById(camId))) - { - x15c_currentFov = cam->GetFov(); - x170_24_perspDirty = true; - } + if (deactivate) + DeactivateInterpCamera(mgr); + } else + DeactivateInterpCamera(mgr); } -void CInterpolationCamera::DeactivateInterpCamera(CStateManager& mgr) -{ - SetActive(false); - if (!mgr.GetCameraManager()->ShouldBypassInterpolation()) - mgr.GetCameraManager()->SetCurrentCameraId(x188_targetId, mgr); +void CInterpolationCamera::SetInterpolation(const zeus::CTransform& xf, const zeus::CVector3f& lookPos, float maxTime, + float positionSpeed, float rotationSpeed, TUniqueId camId, bool sinusoidal, + CStateManager& mgr) { + SetActive(true); + SetTransform(xf); + x1c4_lookPos = lookPos; + x188_targetId = camId; + x1d8_24_sinusoidal = sinusoidal; + x190_maxTime = maxTime; + x1d0_positionSpeed = positionSpeed; + x1d4_rotationSpeed = rotationSpeed; + x1dc_closeInAngle = 2.f * M_PIF; + x18c_time = 0.f; + + if (TCastToConstPtr cam = (mgr.GetObjectById(camId))) { + x15c_currentFov = cam->GetFov(); + x170_24_perspDirty = true; + } +} + +void CInterpolationCamera::DeactivateInterpCamera(CStateManager& mgr) { + SetActive(false); + if (!mgr.GetCameraManager()->ShouldBypassInterpolation()) + mgr.GetCameraManager()->SetCurrentCameraId(x188_targetId, mgr); } bool CInterpolationCamera::InterpolateSinusoidal(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin, - const zeus::CVector3f& lookPos, float maxTime, float curTime) -{ - if (curTime > maxTime) - curTime = maxTime; + const zeus::CVector3f& lookPos, float maxTime, float curTime) { + if (curTime > maxTime) + curTime = maxTime; - float t = zeus::clamp(-1.f, curTime / maxTime, 1.f); - float sinT = std::sin(t * (M_PIF / 2.f)); - t *= 2.f; - zeus::CVector3f interpOrigin = (1.f - (t - sinT)) * (GetTranslation() - targetOrigin) + targetOrigin; - zeus::CVector3f lookDir = lookPos - interpOrigin; - if (lookDir.canBeNormalized()) - lookDir.normalize(); + float t = zeus::clamp(-1.f, curTime / maxTime, 1.f); + float sinT = std::sin(t * (M_PIF / 2.f)); + t *= 2.f; + zeus::CVector3f interpOrigin = (1.f - (t - sinT)) * (GetTranslation() - targetOrigin) + targetOrigin; + zeus::CVector3f lookDir = lookPos - interpOrigin; + if (lookDir.canBeNormalized()) + lookDir.normalize(); + else + lookDir = x34_transform.basis[1]; + zeus::CVector3f lookDirFlat = lookDir; + lookDirFlat.z() = 0.f; + if (lookDirFlat.canBeNormalized()) { + t = zeus::clamp(-1.f, t, 1.f); + float lookProj = zeus::clamp(-1.f, x34_transform.basis[1].dot(lookDir), 1.f); + float ang = (1.f - t) * std::acos(lookProj); + if (ang > x1dc_closeInAngle) + ang = x1dc_closeInAngle; else - lookDir = x34_transform.basis[1]; - zeus::CVector3f lookDirFlat = lookDir; - lookDirFlat.z() = 0.f; - if (lookDirFlat.canBeNormalized()) - { - t = zeus::clamp(-1.f, t, 1.f); - float lookProj = zeus::clamp(-1.f, x34_transform.basis[1].dot(lookDir), 1.f); - float ang = (1.f - t) * std::acos(lookProj); - if (ang > x1dc_closeInAngle) - ang = x1dc_closeInAngle; - else - x1dc_closeInAngle = ang; - zeus::CTransform lookXf = zeus::lookAt(interpOrigin, interpOrigin + lookDir); - if (std::fabs(lookProj) < 0.999999f) - { - zeus::CVector3f xfLookDir = - zeus::CQuaternion::lookAt(lookDir, x34_transform.basis[1], ang).transform(lookDir); - lookXf = zeus::lookAt(interpOrigin, interpOrigin + xfLookDir); - } - xf = lookXf; - } - else - { - xf = x34_transform; - xf.origin = interpOrigin; + x1dc_closeInAngle = ang; + zeus::CTransform lookXf = zeus::lookAt(interpOrigin, interpOrigin + lookDir); + if (std::fabs(lookProj) < 0.999999f) { + zeus::CVector3f xfLookDir = zeus::CQuaternion::lookAt(lookDir, x34_transform.basis[1], ang).transform(lookDir); + lookXf = zeus::lookAt(interpOrigin, interpOrigin + xfLookDir); } + xf = lookXf; + } else { + xf = x34_transform; + xf.origin = interpOrigin; + } - return curTime >= maxTime; + return curTime >= maxTime; } bool CInterpolationCamera::InterpolateWithDistance(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin, const zeus::CVector3f& lookPos, float positionSpeed, - float rotationSpeed, float dt, float maxTime, float curTime) -{ - zeus::CVector3f interpOrigin = xf.origin; - zeus::CVector3f originDir = targetOrigin - interpOrigin; - float sdt = positionSpeed * dt; - bool ret = false; - bool positionFail = false; - if (originDir.canBeNormalized() && originDir.magnitude() > sdt) - { - float lookDist = originDir.magnitude(); - originDir.normalize(); - float scale = zeus::clamp(-1.f, lookDist / 0.5f, 1.f) * sdt; - interpOrigin += originDir * scale; - if (lookDist < scale) - { - interpOrigin = targetOrigin; - positionFail = true; - } + float rotationSpeed, float dt, float maxTime, float curTime) { + zeus::CVector3f interpOrigin = xf.origin; + zeus::CVector3f originDir = targetOrigin - interpOrigin; + float sdt = positionSpeed * dt; + bool ret = false; + bool positionFail = false; + if (originDir.canBeNormalized() && originDir.magnitude() > sdt) { + float lookDist = originDir.magnitude(); + originDir.normalize(); + float scale = zeus::clamp(-1.f, lookDist / 0.5f, 1.f) * sdt; + interpOrigin += originDir * scale; + if (lookDist < scale) { + interpOrigin = targetOrigin; + positionFail = true; } + } else { + interpOrigin = targetOrigin; + positionFail = true; + } + + zeus::CVector3f lookPosDelta = lookPos - x1c4_lookPos; + if (lookPosDelta.magnitude() > sdt) { + float deltaMag = lookPosDelta.magnitude(); + lookPosDelta.normalize(); + float scale = zeus::clamp(-1.f, deltaMag / 0.5f, 1.f) * sdt; + x1c4_lookPos += lookPosDelta * scale; + } else { + x1c4_lookPos = lookPos; + } + + zeus::CVector3f lookDir = x1c4_lookPos - interpOrigin; + if (lookDir.canBeNormalized()) + lookDir.normalize(); + else + lookDir = x34_transform.basis[1]; + + float lookProj = zeus::clamp(-1.f, xf.basis[1].dot(lookDir), 1.f); + float ang = zeus::clamp(-1.f, std::acos(lookProj) / (M_PIF / 6.f), 1.f) * rotationSpeed * dt; + + zeus::CVector3f lookDirFlat = lookDir; + lookDirFlat.z() = 0.f; + bool rotationFail = false; + if (lookDirFlat.canBeNormalized()) { + zeus::CTransform lookXf = zeus::lookAt(interpOrigin, interpOrigin + lookDir); + if (lookProj < 0.999999f) + lookXf = zeus::CQuaternion::lookAt(xf.basis[1], lookDir, ang).toTransform() * xf.getRotation(); else - { - interpOrigin = targetOrigin; - positionFail = true; - } + rotationFail = true; + lookXf.origin = interpOrigin; + xf = lookXf; + } else { + xf = x34_transform; + xf.origin = interpOrigin; + rotationFail = true; + } - zeus::CVector3f lookPosDelta = lookPos - x1c4_lookPos; - if (lookPosDelta.magnitude() > sdt) - { - float deltaMag = lookPosDelta.magnitude(); - lookPosDelta.normalize(); - float scale = zeus::clamp(-1.f, deltaMag / 0.5f, 1.f) * sdt; - x1c4_lookPos += lookPosDelta * scale; - } - else - { - x1c4_lookPos = lookPos; - } + if (positionFail && rotationFail) + ret = true; - zeus::CVector3f lookDir = x1c4_lookPos - interpOrigin; - if (lookDir.canBeNormalized()) - lookDir.normalize(); - else - lookDir = x34_transform.basis[1]; + if (curTime >= maxTime && lookProj >= 0.9999f) + ret = true; - float lookProj = zeus::clamp(-1.f, xf.basis[1].dot(lookDir), 1.f); - float ang = zeus::clamp(-1.f, std::acos(lookProj) / (M_PIF / 6.f), 1.f) * rotationSpeed * dt; - - zeus::CVector3f lookDirFlat = lookDir; - lookDirFlat.z() = 0.f; - bool rotationFail = false; - if (lookDirFlat.canBeNormalized()) - { - zeus::CTransform lookXf = zeus::lookAt(interpOrigin, interpOrigin + lookDir); - if (lookProj < 0.999999f) - lookXf = zeus::CQuaternion::lookAt(xf.basis[1], lookDir, ang).toTransform() * xf.getRotation(); - else - rotationFail = true; - lookXf.origin = interpOrigin; - xf = lookXf; - } - else - { - xf = x34_transform; - xf.origin = interpOrigin; - rotationFail = true; - } - - if (positionFail && rotationFail) - ret = true; - - if (curTime >= maxTime && lookProj >= 0.9999f) - ret = true; - - return ret; + return ret; } -} +} // namespace urde diff --git a/Runtime/Camera/CInterpolationCamera.hpp b/Runtime/Camera/CInterpolationCamera.hpp index c47eeb2b9..a3463cfaf 100644 --- a/Runtime/Camera/CInterpolationCamera.hpp +++ b/Runtime/Camera/CInterpolationCamera.hpp @@ -2,40 +2,37 @@ #include "CGameCamera.hpp" -namespace urde -{ +namespace urde { -class CInterpolationCamera : public CGameCamera -{ - TUniqueId x188_targetId = kInvalidUniqueId; - float x18c_time = 0.f; - float x190_maxTime = 0.f; - zeus::CTransform x194_; - zeus::CVector3f x1c4_lookPos; - float x1d0_positionSpeed = 0.f; - float x1d4_rotationSpeed = 0.f; - float x1d8_ = 0.f; - bool x1d8_24_sinusoidal : 1; - float x1dc_closeInAngle = M_PIF * 2.f; +class CInterpolationCamera : public CGameCamera { + TUniqueId x188_targetId = kInvalidUniqueId; + float x18c_time = 0.f; + float x190_maxTime = 0.f; + zeus::CTransform x194_; + zeus::CVector3f x1c4_lookPos; + float x1d0_positionSpeed = 0.f; + float x1d4_rotationSpeed = 0.f; + float x1d8_ = 0.f; + bool x1d8_24_sinusoidal : 1; + float x1dc_closeInAngle = M_PIF * 2.f; + + bool InterpolateSinusoidal(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin, const zeus::CVector3f& lookPos, + float maxTime, float curTime); + bool InterpolateWithDistance(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin, + const zeus::CVector3f& lookPos, float positionSpeed, float rotationSpeed, float dt, + float maxTime, float curTime); - bool InterpolateSinusoidal(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin, - const zeus::CVector3f& lookPos, float maxTime, float curTime); - bool InterpolateWithDistance(zeus::CTransform& xf, const zeus::CVector3f& targetOrigin, - const zeus::CVector3f& lookPos, float positionSpeed, - float rotationSpeed, float dt, float maxTime, float curTime); public: - CInterpolationCamera(TUniqueId uid, const zeus::CTransform& xf); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void ProcessInput(const CFinalInput&, CStateManager& mgr); - void Render(const CStateManager&) const; - void Reset(const zeus::CTransform&, CStateManager& mgr); - void Think(float, CStateManager &); - void SetInterpolation(const zeus::CTransform& xf, const zeus::CVector3f& lookPos, - float maxTime, float positionSpeed, float rotationSpeed, - TUniqueId camId, bool sinusoidal, CStateManager& mgr); - void DeactivateInterpCamera(CStateManager&); + CInterpolationCamera(TUniqueId uid, const zeus::CTransform& xf); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void ProcessInput(const CFinalInput&, CStateManager& mgr); + void Render(const CStateManager&) const; + void Reset(const zeus::CTransform&, CStateManager& mgr); + void Think(float, CStateManager&); + void SetInterpolation(const zeus::CTransform& xf, const zeus::CVector3f& lookPos, float maxTime, float positionSpeed, + float rotationSpeed, TUniqueId camId, bool sinusoidal, CStateManager& mgr); + void DeactivateInterpCamera(CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/Camera/CPathCamera.cpp b/Runtime/Camera/CPathCamera.cpp index fffd210f8..d5abd0da2 100644 --- a/Runtime/Camera/CPathCamera.cpp +++ b/Runtime/Camera/CPathCamera.cpp @@ -8,119 +8,104 @@ #include "GameGlobalObjects.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CPathCamera::CPathCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, float lengthExtent, float filterMag, - float filterProportion, float minEaseDist, float maxEaseDist, u32 flags, - EInitialSplinePosition initPos) -: CGameCamera(uid, active, name, info, xf, - CCameraManager::ThirdPersonFOV(), - CCameraManager::NearPlane(), - CCameraManager::FarPlane(), - CCameraManager::Aspect(), kInvalidUniqueId, 0, 0) -, x188_spline(flags & 1), x1dc_lengthExtent(lengthExtent), x1e0_filterMag(filterMag) -, x1e4_filterProportion(filterProportion), x1e8_initPos(initPos), x1ec_flags(flags) -, x1f0_minEaseDist(minEaseDist), x1f4_maxEaseDist(maxEaseDist) -{ +CPathCamera::CPathCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + bool active, float lengthExtent, float filterMag, float filterProportion, float minEaseDist, + float maxEaseDist, u32 flags, EInitialSplinePosition initPos) +: CGameCamera(uid, active, name, info, xf, CCameraManager::ThirdPersonFOV(), CCameraManager::NearPlane(), + CCameraManager::FarPlane(), CCameraManager::Aspect(), kInvalidUniqueId, 0, 0) +, x188_spline(flags & 1) +, x1dc_lengthExtent(lengthExtent) +, x1e0_filterMag(filterMag) +, x1e4_filterProportion(filterProportion) +, x1e8_initPos(initPos) +, x1ec_flags(flags) +, x1f0_minEaseDist(minEaseDist) +, x1f4_maxEaseDist(maxEaseDist) {} + +void CPathCamera::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CPathCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CGameCamera::AcceptScriptMsg(msg, uid, mgr); + + if (GetActive() && msg == EScriptObjectMessage::InitializedInArea) + x188_spline.Initialize(GetUniqueId(), GetConnectionList(), mgr); } -void CPathCamera::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CPathCamera::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; -void CPathCamera::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CGameCamera::AcceptScriptMsg(msg, uid, mgr); + if (mgr.GetCameraManager()->GetPathCameraId() != GetUniqueId()) + return; - if (GetActive() && msg == EScriptObjectMessage::InitializedInArea) - x188_spline.Initialize(GetUniqueId(), GetConnectionList(), mgr); -} + if (x188_spline.GetSize() <= 0) + return; -void CPathCamera::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; - - if (mgr.GetCameraManager()->GetPathCameraId() != GetUniqueId()) - return; - - if (x188_spline.GetSize() <= 0) - return; - - zeus::CTransform xf = GetTransform(); - zeus::CVector3f ballLook = mgr.GetCameraManager()->GetBallCamera()->GetLookPos(); - if ((x1ec_flags & 0x10)) - { - if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) - ballLook.z() = hint->GetTranslation().z(); - } - - if (!mgr.GetPlayer().GetVelocity().canBeNormalized() && (ballLook - GetTranslation()).canBeNormalized()) - { - if (x1ec_flags & 4) - SetTransform(x188_spline.GetInterpolatedSplinePointByLength(x1d4_pos)); - else - SetTransform(zeus::lookAt(GetTranslation(), ballLook)); - return; - } - - xf = MoveAlongSpline(dt, mgr); - SetTranslation(xf.origin); - - if (x1ec_flags & 0x20) - ClampToClosedDoor(mgr); - - zeus::CVector3f tmp = ballLook - GetTranslation(); - tmp.z() = 0.f; - if (tmp.canBeNormalized()) - SetTransform(zeus::lookAt(GetTranslation(), ballLook)); + zeus::CTransform xf = GetTransform(); + zeus::CVector3f ballLook = mgr.GetCameraManager()->GetBallCamera()->GetLookPos(); + if ((x1ec_flags & 0x10)) { + if (const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr)) + ballLook.z() = hint->GetTranslation().z(); + } + if (!mgr.GetPlayer().GetVelocity().canBeNormalized() && (ballLook - GetTranslation()).canBeNormalized()) { if (x1ec_flags & 4) - SetTransform(xf); + SetTransform(x188_spline.GetInterpolatedSplinePointByLength(x1d4_pos)); + else + SetTransform(zeus::lookAt(GetTranslation(), ballLook)); + return; + } + + xf = MoveAlongSpline(dt, mgr); + SetTranslation(xf.origin); + + if (x1ec_flags & 0x20) + ClampToClosedDoor(mgr); + + zeus::CVector3f tmp = ballLook - GetTranslation(); + tmp.z() = 0.f; + if (tmp.canBeNormalized()) + SetTransform(zeus::lookAt(GetTranslation(), ballLook)); + + if (x1ec_flags & 4) + SetTransform(xf); } -void CPathCamera::ProcessInput(const CFinalInput&, CStateManager& mgr) -{ - // Empty +void CPathCamera::ProcessInput(const CFinalInput&, CStateManager& mgr) { + // Empty } static const CMaterialFilter kLineOfSightFilter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough}); -void CPathCamera::Reset(const zeus::CTransform&, CStateManager& mgr) -{ - CPlayer& player = mgr.GetPlayer(); - zeus::CVector3f playerPt = player.GetTranslation() + - zeus::CVector3f(0.f, 0.f, g_tweakPlayer->GetPlayerBallHalfExtent()); - float closestLength = x188_spline.FindClosestLengthOnSpline(0.f, playerPt); +void CPathCamera::Reset(const zeus::CTransform&, CStateManager& mgr) { + CPlayer& player = mgr.GetPlayer(); + zeus::CVector3f playerPt = + player.GetTranslation() + zeus::CVector3f(0.f, 0.f, g_tweakPlayer->GetPlayerBallHalfExtent()); + float closestLength = x188_spline.FindClosestLengthOnSpline(0.f, playerPt); - float negLength = std::max(0.f, closestLength - x1dc_lengthExtent); - zeus::CVector3f negPoint = x188_spline.GetInterpolatedSplinePointByLength(negLength).origin; + float negLength = std::max(0.f, closestLength - x1dc_lengthExtent); + zeus::CVector3f negPoint = x188_spline.GetInterpolatedSplinePointByLength(negLength).origin; - float posLength = std::min(x188_spline.GetLength(), closestLength + x1dc_lengthExtent); - zeus::CVector3f posPoint = x188_spline.GetInterpolatedSplinePointByLength(posLength).origin; + float posLength = std::min(x188_spline.GetLength(), closestLength + x1dc_lengthExtent); + zeus::CVector3f posPoint = x188_spline.GetInterpolatedSplinePointByLength(posLength).origin; - zeus::CTransform camXf = mgr.GetCameraManager()->GetBallCamera()->GetTransform(); - if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) - camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + zeus::CTransform camXf = mgr.GetCameraManager()->GetBallCamera()->GetTransform(); + if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) + camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - bool neg = false; - if (x1e8_initPos == EInitialSplinePosition::BallCamBasis) - { - zeus::CVector3f tmp = playerPt - negPoint; - if (tmp.canBeNormalized()) - { - if (tmp.normalized().dot(camXf.basis[1]) > 0.f) - neg = true; - } - } - else - { - neg = x1e8_initPos == EInitialSplinePosition::Negative; + bool neg = false; + if (x1e8_initPos == EInitialSplinePosition::BallCamBasis) { + zeus::CVector3f tmp = playerPt - negPoint; + if (tmp.canBeNormalized()) { + if (tmp.normalized().dot(camXf.basis[1]) > 0.f) + neg = true; } + } else { + neg = x1e8_initPos == EInitialSplinePosition::Negative; + } #if 0 zeus::CVector3f camToSpline = splinePt - camXf.origin; @@ -129,127 +114,99 @@ void CPathCamera::Reset(const zeus::CTransform&, CStateManager& mgr) mgr.RayStaticIntersection(camXf.origin, camToSpline2.normalized(), camToSpline2.magnitude(), kLineOfSightFilter); #endif - zeus::CVector3f viewPoint; - if (neg) - { - x1d4_pos = negLength; - viewPoint = negPoint; + zeus::CVector3f viewPoint; + if (neg) { + x1d4_pos = negLength; + viewPoint = negPoint; + } else { + x1d4_pos = posLength; + viewPoint = posPoint; + } + + if (x1e8_initPos == EInitialSplinePosition::ClampBasis) { + if (x188_spline.ClampLength(playerPt, false, kLineOfSightFilter, mgr) <= negLength) { + x1d4_pos = negLength; + viewPoint = negPoint; + } else { + x1d4_pos = posLength; + viewPoint = posPoint; } + } + + SetTransform(zeus::lookAt(viewPoint, mgr.GetCameraManager()->GetBallCamera()->GetFixedLookPos())); +} + +zeus::CTransform CPathCamera::MoveAlongSpline(float t, CStateManager& mgr) { + zeus::CTransform ret = x34_transform; + x1d8_time = x188_spline.FindClosestLengthOnSpline(x1d8_time, mgr.GetPlayer().GetTranslation()); + float f30 = x1dc_lengthExtent; + if (x1ec_flags & 0x8) { + zeus::CVector3f splineToPlayer = + mgr.GetPlayer().GetTranslation() - x188_spline.GetInterpolatedSplinePointByLength(x1d8_time).origin; + float distToPlayer = 0.f; + splineToPlayer.z() = 0.f; + if (splineToPlayer.canBeNormalized()) + distToPlayer = splineToPlayer.magnitude(); + float easedDistT = (distToPlayer - x1f0_minEaseDist) / (x1f4_maxEaseDist - x1f0_minEaseDist); + f30 *= 1.f - std::sin(zeus::degToRad(zeus::clamp(0.f, easedDistT, 1.f) * 90.f)); + } + + float newPos; + if (x188_spline.IsClosedLoop()) { + float lenA = x188_spline.ValidateLength(x1d8_time + f30); + newPos = x188_spline.ValidateLength(x1d8_time - f30); + float disp = std::fabs(x1d4_pos - x1d8_time); + float remLen = x188_spline.GetLength() - disp; + if (x1d4_pos > x1d8_time) { + if (disp <= remLen) + newPos = lenA; + } else { + if (disp > remLen) + newPos = lenA; + } + } else { + if (x1d4_pos > x1d8_time) + newPos = x188_spline.ValidateLength(x1d8_time + f30); else - { - x1d4_pos = posLength; - viewPoint = posPoint; - } + newPos = x188_spline.ValidateLength(x1d8_time - f30); + } - if (x1e8_initPos == EInitialSplinePosition::ClampBasis) - { - if (x188_spline.ClampLength(playerPt, false, kLineOfSightFilter, mgr) <= negLength) - { - x1d4_pos = negLength; - viewPoint = negPoint; - } - else - { - x1d4_pos = posLength; - viewPoint = posPoint; - } + if (x1ec_flags & 0x2) { + x1d4_pos = newPos; + ret = x188_spline.GetInterpolatedSplinePointByLength(x1d4_pos); + } else { + if (x188_spline.IsClosedLoop()) { + float absDelta = std::fabs(newPos - x1d4_pos); + absDelta = std::min(absDelta, x188_spline.GetLength() - absDelta); + float tBias = zeus::clamp(-1.f, absDelta / x1e4_filterProportion, 1.f) * x1e0_filterMag * t; + float tmpAbs = std::fabs(x1d4_pos - newPos); + float absDelta2 = x188_spline.GetLength() - tmpAbs; + if (x1d4_pos > newPos) { + if (tmpAbs <= absDelta2) + tBias *= -1.f; + } else { + if (tmpAbs > absDelta2) + tBias *= -1.f; + } + x1d4_pos = x188_spline.ValidateLength(x1d4_pos + tBias); + } else { + x1d4_pos = x188_spline.ValidateLength( + zeus::clamp(-1.f, (newPos - x1d4_pos) / x1e4_filterProportion, 1.f) * x1e0_filterMag * t + x1d4_pos); } + ret = x188_spline.GetInterpolatedSplinePointByLength(x1d4_pos); + } - SetTransform(zeus::lookAt(viewPoint, mgr.GetCameraManager()->GetBallCamera()->GetFixedLookPos())); + return ret; } -zeus::CTransform CPathCamera::MoveAlongSpline(float t, CStateManager& mgr) -{ - zeus::CTransform ret = x34_transform; - x1d8_time = x188_spline.FindClosestLengthOnSpline(x1d8_time, mgr.GetPlayer().GetTranslation()); - float f30 = x1dc_lengthExtent; - if (x1ec_flags & 0x8) - { - zeus::CVector3f splineToPlayer = mgr.GetPlayer().GetTranslation() - - x188_spline.GetInterpolatedSplinePointByLength(x1d8_time).origin; - float distToPlayer = 0.f; - splineToPlayer.z() = 0.f; - if (splineToPlayer.canBeNormalized()) - distToPlayer = splineToPlayer.magnitude(); - float easedDistT = (distToPlayer - x1f0_minEaseDist) / (x1f4_maxEaseDist - x1f0_minEaseDist); - f30 *= 1.f - std::sin(zeus::degToRad(zeus::clamp(0.f, easedDistT, 1.f) * 90.f)); +void CPathCamera::ClampToClosedDoor(CStateManager& mgr) { + if (TCastToConstPtr door = + mgr.GetObjectById(mgr.GetCameraManager()->GetBallCamera()->GetTooCloseActorId())) { + if (!door->IsOpen() && CBallCamera::IsBallNearDoor(GetTranslation(), mgr)) { + x1d4_pos = (x1d4_pos > x1d8_time) ? x1d8_time - x1dc_lengthExtent : x1d8_time + x1dc_lengthExtent; + SetTranslation(x188_spline.GetInterpolatedSplinePointByLength(x1d4_pos).origin); } - - float newPos; - if (x188_spline.IsClosedLoop()) - { - float lenA = x188_spline.ValidateLength(x1d8_time + f30); - newPos = x188_spline.ValidateLength(x1d8_time - f30); - float disp = std::fabs(x1d4_pos - x1d8_time); - float remLen = x188_spline.GetLength() - disp; - if (x1d4_pos > x1d8_time) - { - if (disp <= remLen) - newPos = lenA; - } - else - { - if (disp > remLen) - newPos = lenA; - } - } - else - { - if (x1d4_pos > x1d8_time) - newPos = x188_spline.ValidateLength(x1d8_time + f30); - else - newPos = x188_spline.ValidateLength(x1d8_time - f30); - } - - if (x1ec_flags & 0x2) - { - x1d4_pos = newPos; - ret = x188_spline.GetInterpolatedSplinePointByLength(x1d4_pos); - } - else - { - if (x188_spline.IsClosedLoop()) - { - float absDelta = std::fabs(newPos - x1d4_pos); - absDelta = std::min(absDelta, x188_spline.GetLength() - absDelta); - float tBias = zeus::clamp(-1.f, absDelta / x1e4_filterProportion, 1.f) * x1e0_filterMag * t; - float tmpAbs = std::fabs(x1d4_pos - newPos); - float absDelta2 = x188_spline.GetLength() - tmpAbs; - if (x1d4_pos > newPos) - { - if (tmpAbs <= absDelta2) - tBias *= -1.f; - } - else - { - if (tmpAbs > absDelta2) - tBias *= -1.f; - } - x1d4_pos = x188_spline.ValidateLength(x1d4_pos + tBias); - } - else - { - x1d4_pos = x188_spline.ValidateLength( - zeus::clamp(-1.f, (newPos - x1d4_pos) / x1e4_filterProportion, 1.f) * x1e0_filterMag * t + x1d4_pos); - } - ret = x188_spline.GetInterpolatedSplinePointByLength(x1d4_pos); - } - - return ret; + } } -void CPathCamera::ClampToClosedDoor(CStateManager& mgr) -{ - if (TCastToConstPtr door = - mgr.GetObjectById(mgr.GetCameraManager()->GetBallCamera()->GetTooCloseActorId())) - { - if (!door->IsOpen() && CBallCamera::IsBallNearDoor(GetTranslation(), mgr)) - { - x1d4_pos = (x1d4_pos > x1d8_time) ? - x1d8_time - x1dc_lengthExtent : x1d8_time + x1dc_lengthExtent; - SetTranslation(x188_spline.GetInterpolatedSplinePointByLength(x1d4_pos).origin); - } - } -} - -} +} // namespace urde diff --git a/Runtime/Camera/CPathCamera.hpp b/Runtime/Camera/CPathCamera.hpp index 7eb81f653..281d9fb8e 100644 --- a/Runtime/Camera/CPathCamera.hpp +++ b/Runtime/Camera/CPathCamera.hpp @@ -3,47 +3,37 @@ #include "CGameCamera.hpp" #include "CCameraSpline.hpp" -namespace urde -{ +namespace urde { -class CPathCamera : public CGameCamera -{ +class CPathCamera : public CGameCamera { public: - enum class EInitialSplinePosition - { - BallCamBasis, - Negative, - Positive, - ClampBasis - }; + enum class EInitialSplinePosition { BallCamBasis, Negative, Positive, ClampBasis }; + private: + CCameraSpline x188_spline; + float x1d4_pos = 0.f; + float x1d8_time = 0.f; + float x1dc_lengthExtent; + float x1e0_filterMag; + float x1e4_filterProportion; + EInitialSplinePosition x1e8_initPos; + u32 x1ec_flags; + float x1f0_minEaseDist; + float x1f4_maxEaseDist; - CCameraSpline x188_spline; - float x1d4_pos = 0.f; - float x1d8_time = 0.f; - float x1dc_lengthExtent; - float x1e0_filterMag; - float x1e4_filterProportion; - EInitialSplinePosition x1e8_initPos; - u32 x1ec_flags; - float x1f0_minEaseDist; - float x1f4_maxEaseDist; public: + CPathCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, + float lengthExtent, float filterMag, float filterProportion, float minEaseDist, float maxEaseDist, + u32 flags, EInitialSplinePosition initPos); - CPathCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, float lengthExtent, float filterMag, - float filterProportion, float minEaseDist, float maxEaseDist, u32 flags, - EInitialSplinePosition initPos); - - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - void Render(const CStateManager&) const {} - void ProcessInput(const CFinalInput&, CStateManager& mgr); - void Reset(const zeus::CTransform&, CStateManager& mgr); - zeus::CTransform MoveAlongSpline(float, CStateManager&); - void ClampToClosedDoor(CStateManager&); + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void Render(const CStateManager&) const {} + void ProcessInput(const CFinalInput&, CStateManager& mgr); + void Reset(const zeus::CTransform&, CStateManager& mgr); + zeus::CTransform MoveAlongSpline(float, CStateManager&); + void ClampToClosedDoor(CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/Character/CActorLights.cpp b/Runtime/Character/CActorLights.cpp index cf5b7a9b7..41df80e9e 100644 --- a/Runtime/Character/CActorLights.cpp +++ b/Runtime/Character/CActorLights.cpp @@ -10,584 +10,502 @@ #include "World/CExplosion.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { s32 CActorLights::sFrameSchedulerCount = 0; -CActorLights::CActorLights(u32 areaUpdateFramePeriod, const zeus::CVector3f& actorPosBias, - int maxDynamicLights, int maxAreaLights, bool ambientChannelOverflow, - bool layer2, bool disableWorldLights, float positionUpdateThreshold) -: x2a8_areaUpdateFramePeriod(areaUpdateFramePeriod), x2ac_actorPosBias(actorPosBias), - x2b8_maxAreaLights(maxAreaLights), x2bc_maxDynamicLights(maxDynamicLights), - x2cc_actorPositionDeltaUpdateThreshold(positionUpdateThreshold * positionUpdateThreshold) -{ - x298_24_dirty = true; - x298_25_castShadows = true; +CActorLights::CActorLights(u32 areaUpdateFramePeriod, const zeus::CVector3f& actorPosBias, int maxDynamicLights, + int maxAreaLights, bool ambientChannelOverflow, bool layer2, bool disableWorldLights, + float positionUpdateThreshold) +: x2a8_areaUpdateFramePeriod(areaUpdateFramePeriod) +, x2ac_actorPosBias(actorPosBias) +, x2b8_maxAreaLights(maxAreaLights) +, x2bc_maxDynamicLights(maxDynamicLights) +, x2cc_actorPositionDeltaUpdateThreshold(positionUpdateThreshold * positionUpdateThreshold) { + x298_24_dirty = true; + x298_25_castShadows = true; - x298_28_inArea = (!disableWorldLights && maxAreaLights > 0) ? true : false; - x298_29_ambienceGenerated = ambientChannelOverflow; - x298_30_layer2 = layer2; - x298_31_disableWorldLights = disableWorldLights; - x299_24_inBrightLight = true; + x298_28_inArea = (!disableWorldLights && maxAreaLights > 0) ? true : false; + x298_29_ambienceGenerated = ambientChannelOverflow; + x298_30_layer2 = layer2; + x298_31_disableWorldLights = disableWorldLights; + x299_24_inBrightLight = true; - sFrameSchedulerCount++; - sFrameSchedulerCount &= 7; + sFrameSchedulerCount++; + sFrameSchedulerCount &= 7; } -void CActorLights::BuildConstantAmbientLighting() -{ - x299_26_ambientOnly = true; - x298_24_dirty = true; - x29c_shadowLightArrIdx = -1; - x2a0_shadowLightIdx = -1; +void CActorLights::BuildConstantAmbientLighting() { + x299_26_ambientOnly = true; + x298_24_dirty = true; + x29c_shadowLightArrIdx = -1; + x2a0_shadowLightIdx = -1; } -void CActorLights::BuildConstantAmbientLighting(const zeus::CColor& color) -{ - x299_26_ambientOnly = false; - x288_ambientColor = color; - x294_aid = kInvalidAreaId; - x298_24_dirty = true; - x298_26_hasAreaLights = true; - x29c_shadowLightArrIdx = -1; - x2a0_shadowLightIdx = -1; +void CActorLights::BuildConstantAmbientLighting(const zeus::CColor& color) { + x299_26_ambientOnly = false; + x288_ambientColor = color; + x294_aid = kInvalidAreaId; + x298_24_dirty = true; + x298_26_hasAreaLights = true; + x29c_shadowLightArrIdx = -1; + x2a0_shadowLightIdx = -1; } -void CActorLights::BuildFakeLightList(const std::vector& lights, const zeus::CColor& color) -{ - BuildConstantAmbientLighting(color); - x0_areaLights.clear(); - x144_dynamicLights = lights; +void CActorLights::BuildFakeLightList(const std::vector& lights, const zeus::CColor& color) { + BuildConstantAmbientLighting(color); + x0_areaLights.clear(); + x144_dynamicLights = lights; } -void CActorLights::BuildFaceLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb) -{ - zeus::CTransform fpTransform = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform(); - x288_ambientColor = zeus::CColor::skBlack; - x144_dynamicLights.clear(); - zeus::CColor accumColor = zeus::CColor::skBlack; - for (CEntity* light : mgr.GetLightObjectList()) - { - if (!light || !light->GetActive()) - continue; - CGameLight* castLight = static_cast(light); - if (TCastToConstPtr explosion = mgr.GetObjectById(castLight->GetParentId())) - { - CLight originalLight = castLight->GetLight(); - CLight explosionLight = originalLight; - explosionLight.SetAttenuation(explosionLight.GetAttenuationConstant() * g_tweakGui->GetExplosionLightFalloffMultConstant(), - explosionLight.GetAttenuationLinear() * g_tweakGui->GetExplosionLightFalloffMultLinear(), - explosionLight.GetAttenuationQuadratic() * g_tweakGui->GetExplosionLightFalloffMultQuadratic()); - zeus::CVector3f camToExplo = explosion->GetTranslation() - fpTransform.origin; - if (fpTransform.transposeRotate(camToExplo).dot(zeus::CVector3f::skForward) >= 0.f) - { - camToExplo.y() = -camToExplo.y() + ITweakGui::FaceReflectionDistanceDebugValueToActualValue( - g_tweakGui->GetFaceReflectionDistance()); - camToExplo.z() = -camToExplo.z() + ITweakGui::FaceReflectionHeightDebugValueToActualValue( - g_tweakGui->GetFaceReflectionHeight()); - explosionLight.SetPosition(fpTransform * camToExplo); - zeus::CSphere sphere(originalLight.GetPosition(), originalLight.GetRadius()); - if (aabb.intersects(sphere)) - { - accumColor += explosionLight.GetNormalIndependentLightingAtPoint(fpTransform.origin); - if (originalLight.GetIntensity() > FLT_EPSILON && originalLight.GetRadius() > FLT_EPSILON) - x144_dynamicLights.push_back(explosionLight); - } - } +void CActorLights::BuildFaceLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb) { + zeus::CTransform fpTransform = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform(); + x288_ambientColor = zeus::CColor::skBlack; + x144_dynamicLights.clear(); + zeus::CColor accumColor = zeus::CColor::skBlack; + for (CEntity* light : mgr.GetLightObjectList()) { + if (!light || !light->GetActive()) + continue; + CGameLight* castLight = static_cast(light); + if (TCastToConstPtr explosion = mgr.GetObjectById(castLight->GetParentId())) { + CLight originalLight = castLight->GetLight(); + CLight explosionLight = originalLight; + explosionLight.SetAttenuation( + explosionLight.GetAttenuationConstant() * g_tweakGui->GetExplosionLightFalloffMultConstant(), + explosionLight.GetAttenuationLinear() * g_tweakGui->GetExplosionLightFalloffMultLinear(), + explosionLight.GetAttenuationQuadratic() * g_tweakGui->GetExplosionLightFalloffMultQuadratic()); + zeus::CVector3f camToExplo = explosion->GetTranslation() - fpTransform.origin; + if (fpTransform.transposeRotate(camToExplo).dot(zeus::CVector3f::skForward) >= 0.f) { + camToExplo.y() = -camToExplo.y() + ITweakGui::FaceReflectionDistanceDebugValueToActualValue( + g_tweakGui->GetFaceReflectionDistance()); + camToExplo.z() = -camToExplo.z() + + ITweakGui::FaceReflectionHeightDebugValueToActualValue(g_tweakGui->GetFaceReflectionHeight()); + explosionLight.SetPosition(fpTransform * camToExplo); + zeus::CSphere sphere(originalLight.GetPosition(), originalLight.GetRadius()); + if (aabb.intersects(sphere)) { + accumColor += explosionLight.GetNormalIndependentLightingAtPoint(fpTransform.origin); + if (originalLight.GetIntensity() > FLT_EPSILON && originalLight.GetRadius() > FLT_EPSILON) + x144_dynamicLights.push_back(explosionLight); } + } } + } - float greyscale = accumColor.rgbDot(zeus::CColor(0.3f, 0.6f, 0.1f)); - if (greyscale < 0.012f) - x144_dynamicLights.clear(); + float greyscale = accumColor.rgbDot(zeus::CColor(0.3f, 0.6f, 0.1f)); + if (greyscale < 0.012f) + x144_dynamicLights.clear(); - if (greyscale > 0.03f) - { - float attMul = 1.f / (0.03f / greyscale); - for (CLight& light : x144_dynamicLights) - light.SetAttenuation(light.GetAttenuationConstant() * attMul, - light.GetAttenuationLinear() * attMul, - light.GetAttenuationQuadratic() * attMul); - } + if (greyscale > 0.03f) { + float attMul = 1.f / (0.03f / greyscale); + for (CLight& light : x144_dynamicLights) + light.SetAttenuation(light.GetAttenuationConstant() * attMul, light.GetAttenuationLinear() * attMul, + light.GetAttenuationQuadratic() * attMul); + } } -struct SLightValue -{ - u32 x0_areaLightIdx; - zeus::CColor x4_color; - float x10_colorMag; - float x14_accumulatedMag = 0.f; - EPVSVisSetState x18_visiblity; +struct SLightValue { + u32 x0_areaLightIdx; + zeus::CColor x4_color; + float x10_colorMag; + float x14_accumulatedMag = 0.f; + EPVSVisSetState x18_visiblity; }; -void CActorLights::MergeOverflowLight(CLight& out, zeus::CColor& color, const CLight& in, float colorMag) -{ - color += in.GetColor() * colorMag; - out.SetAngleAttenuation(in.GetAngleAttenuationConstant() * colorMag + out.GetAngleAttenuationConstant(), - in.GetAngleAttenuationLinear() * colorMag + out.GetAngleAttenuationLinear(), - in.GetAngleAttenuationQuadratic() * colorMag + out.GetAngleAttenuationQuadratic()); - out.SetAttenuation(in.GetAttenuationConstant() * colorMag + out.GetAttenuationConstant(), - in.GetAttenuationLinear() * colorMag + out.GetAttenuationLinear(), - in.GetAttenuationQuadratic() * colorMag + out.GetAttenuationQuadratic()); - out.SetPosition(in.GetPosition() * colorMag + out.GetPosition()); - out.SetDirection(in.GetDirection() * colorMag + out.GetDirection()); +void CActorLights::MergeOverflowLight(CLight& out, zeus::CColor& color, const CLight& in, float colorMag) { + color += in.GetColor() * colorMag; + out.SetAngleAttenuation(in.GetAngleAttenuationConstant() * colorMag + out.GetAngleAttenuationConstant(), + in.GetAngleAttenuationLinear() * colorMag + out.GetAngleAttenuationLinear(), + in.GetAngleAttenuationQuadratic() * colorMag + out.GetAngleAttenuationQuadratic()); + out.SetAttenuation(in.GetAttenuationConstant() * colorMag + out.GetAttenuationConstant(), + in.GetAttenuationLinear() * colorMag + out.GetAttenuationLinear(), + in.GetAttenuationQuadratic() * colorMag + out.GetAttenuationQuadratic()); + out.SetPosition(in.GetPosition() * colorMag + out.GetPosition()); + out.SetDirection(in.GetDirection() * colorMag + out.GetDirection()); } -void CActorLights::AddOverflowToLights(const CLight& light, const zeus::CColor& color, float mag) -{ - if (mag < 0.001f || x2b8_maxAreaLights < 1) - return; +void CActorLights::AddOverflowToLights(const CLight& light, const zeus::CColor& color, float mag) { + if (mag < 0.001f || x2b8_maxAreaLights < 1) + return; - mag = 1.f / mag; - zeus::CColor useColor = color * mag; - useColor.a() = 1.f; - x0_areaLights.push_back(CLight::BuildCustom(light.GetPosition() * mag, light.GetDirection() * mag, useColor, - light.GetAttenuationConstant() * mag, - light.GetAttenuationLinear() * mag, - light.GetAttenuationQuadratic() * mag, - light.GetAngleAttenuationConstant() * mag, - light.GetAngleAttenuationLinear() * mag, - light.GetAngleAttenuationQuadratic() * mag)); + mag = 1.f / mag; + zeus::CColor useColor = color * mag; + useColor.a() = 1.f; + x0_areaLights.push_back( + CLight::BuildCustom(light.GetPosition() * mag, light.GetDirection() * mag, useColor, + light.GetAttenuationConstant() * mag, light.GetAttenuationLinear() * mag, + light.GetAttenuationQuadratic() * mag, light.GetAngleAttenuationConstant() * mag, + light.GetAngleAttenuationLinear() * mag, light.GetAngleAttenuationQuadratic() * mag)); } -void CActorLights::MoveAmbienceToLights(const zeus::CColor& color) -{ - if (x298_29_ambienceGenerated) - { - x288_ambientColor += color * 0.333333f; - x288_ambientColor.a() = 1.f; - return; - } - - zeus::CColor useColor = x0_areaLights[0].GetColor() + color; - float maxComponent = std::max(useColor.r(), std::max(useColor.g(), useColor.b())); - if (maxComponent > FLT_EPSILON) - useColor *= (1.f / maxComponent); - useColor.a() = 1.f; - x0_areaLights[0].SetColor(useColor); -} - -void CActorLights::MultiplyLightingLevels(float level) -{ - x288_ambientColor *= level; - for (CLight& light : x0_areaLights) - { - zeus::CColor color = light.GetColor(); - color *= level; - color.a() = 1.f; - light.SetColor(color); - } -} - -void CActorLights::UpdateBrightLight() -{ - if (x2dc_brightLightLag > 0 && x299_24_inBrightLight) - --x2dc_brightLightLag; - else if (x2dc_brightLightLag < 15 && !x299_24_inBrightLight) - ++x2dc_brightLightLag; - x299_25_useBrightLightLag = true; -} - -bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb) -{ - const std::vector& lightList = x298_30_layer2 ? area.GetPostConstructed()->x80_lightsB : - area.GetPostConstructed()->x60_lightsA; - const std::vector& gfxLightList = x298_30_layer2 ? area.GetPostConstructed()->x90_gfxLightsB : - area.GetPostConstructed()->x70_gfxLightsA; - float worldLightingLevel = area.GetPostConstructed()->x1128_worldLightingLevel; - x298_26_hasAreaLights = lightList.size() != 0; - if (!x298_26_hasAreaLights || !x298_28_inArea) - { - /* World lights disabled */ - if (x298_31_disableWorldLights) - x2d4_worldLightingLevel = worldLightingLevel; - x29c_shadowLightArrIdx = -1; - return true; - } - - zeus::CVector3f vec; - if (!x298_24_dirty && x294_aid == area.GetAreaId()) - { - /* Early return if not ready for update */ - if (mgr.GetInputFrameIdx() - x2a4_lastUpdateFrame < x2a8_areaUpdateFramePeriod) - return false; - vec = aabb.center() + x2ac_actorPosBias; - if (x2d4_worldLightingLevel == worldLightingLevel) - if ((x2c0_lastActorPos - vec).magSquared() < x2cc_actorPositionDeltaUpdateThreshold) - return false; - x2c0_lastActorPos = vec; - } - else - { - if (x294_aid != area.GetAreaId()) - x2d8_brightLightIdx = -1; - x2a4_lastUpdateFrame = sFrameSchedulerCount + mgr.GetInputFrameIdx(); - vec = aabb.center() + x2ac_actorPosBias; - x2c0_lastActorPos = vec; - } - - /* Reset lighting state */ - x2d4_worldLightingLevel = worldLightingLevel; - x298_24_dirty = false; - x294_aid = area.GetAreaId(); - x29c_shadowLightArrIdx = -1; - x288_ambientColor = zeus::CColor::skClear; - - /* Find candidate lights via PVS */ - bool use2ndLayer; - if (x298_30_layer2) - { - if (const CPVSAreaSet* pvs = area.GetAreaVisSet()) - use2ndLayer = pvs->Has2ndLayerLights(); - else - use2ndLayer = true; - } - else - { - use2ndLayer = false; - } - - CPVSVisSet sets[3]; - sets[0].Reset(EPVSVisSetState::OutOfBounds); - sets[1].Reset(EPVSVisSetState::OutOfBounds); - sets[2].Reset(EPVSVisSetState::OutOfBounds); - - if (const CPVSAreaSet* pvs = area.GetAreaVisSet()) - { - zeus::CVector3f localVec = area.GetInverseTransform() * vec; - sets[0].SetTestPoint(pvs->GetVisOctree(), localVec); - localVec = area.GetInverseTransform() * aabb.max; - sets[1].SetTestPoint(pvs->GetVisOctree(), localVec); - localVec = area.GetInverseTransform() * aabb.min; - sets[2].SetTestPoint(pvs->GetVisOctree(), localVec); - } - - std::vector valList; - valList.reserve(lightList.size()); - - auto lightIt = lightList.begin(); - int lightIdx = 0; - for (const CLight& light : gfxLightList) - { - if (light.GetType() == ELightType::LocalAmbient) - { - /* Take ambient here */ - x288_ambientColor = light.GetNormalIndependentLightingAtPoint(vec); - } - else - { - EPVSVisSetState visible = EPVSVisSetState::OutOfBounds; - if (area.GetAreaVisSet()) - { - if (lightIt->DoesCastShadows()) - { - u32 pvsIdx; - if (use2ndLayer) - pvsIdx = area.Get2ndPVSLightFeature(lightIdx); - else - pvsIdx = area.Get1stPVSLightFeature(lightIdx); - visible = sets[0].GetVisible(pvsIdx); - if (visible != EPVSVisSetState::OutOfBounds) - visible = std::max(visible, sets[1].GetVisible(pvsIdx)); - if (visible != EPVSVisSetState::OutOfBounds) - visible = std::max(visible, sets[2].GetVisible(pvsIdx)); - } - } - if (visible != EPVSVisSetState::EndOfTree) - { - zeus::CSphere sphere(light.GetPosition(), light.GetRadius() * 2.f); - if (aabb.intersects(sphere)) - { - /* Light passes as candidate */ - valList.emplace_back(); - SLightValue& value = valList.back(); - value.x0_areaLightIdx = lightIdx; - value.x4_color = light.GetNormalIndependentLightingAtPoint(vec); - value.x4_color.a() = 0.f; - value.x10_colorMag = value.x4_color.magnitude(); - value.x18_visiblity = visible; - } - } - } - ++lightIt; - ++lightIdx; - } - - /* Sort lights most intense to least intense */ - std::sort(valList.begin(), valList.end(), - [](const SLightValue& a, const SLightValue& b) - { - return a.x10_colorMag > b.x10_colorMag; - }); - - if (x298_27_findShadowLight) - { - /* Accumulate magnitudes up to most intense for shadow dynamic range check */ - x288_ambientColor.a() = 0.f; - float mag = x288_ambientColor.magnitude(); - for (auto it = valList.rbegin() ; it != valList.rend() ; ++it) - { - mag += it->x10_colorMag; - it->x14_accumulatedMag = mag; - } - } - - /* Ambient color for overflow area lights */ - zeus::CColor overflowAmbColor = zeus::CColor::skClear; - - /* Averaged light for overflow area lights */ - CLight overflowLight = CLight::BuildCustom(zeus::CVector3f::skZero, zeus::CVector3f::skZero, zeus::CColor::skBlack, - 0.f, 0.f, 0.f, 0.f, 0.f, 0.f); - zeus::CColor overflowLightColor = zeus::CColor::skClear; - float overflowMag = 0.f; - - /* Max significant lights */ - int maxAreaLights = !x298_29_ambienceGenerated ? x2b8_maxAreaLights - 1 : x2b8_maxAreaLights; - x0_areaLights.clear(); - - /* Filter for performing final light visibility test */ - CMaterialFilter filter = - CMaterialFilter::MakeIncludeExclude(CMaterialList(EMaterialTypes::Solid), - CMaterialList(EMaterialTypes::Projectile, EMaterialTypes::ProjectilePassthrough, - EMaterialTypes::SeeThrough)); - u32 mostSigLightIdx = 0; - - /* Narrowphase test candidates starting with most intense */ - for (int i=0 ; i 2.f && !aabb.pointInside(light.GetPosition())) - { - /* Perform shadow dynamic range check */ - if (!x0_areaLights.size() || - (x0_areaLights.size() == 1 && value.x10_colorMag / valList[mostSigLightIdx].x10_colorMag > 0.5f)) - { - useShadow = value.x10_colorMag / value.x14_accumulatedMag > - x2d0_shadowDynamicRangeThreshold / (1.f + x2d0_shadowDynamicRangeThreshold); - } - } - if (useShadow) - { - /* Note shadow light */ - x29c_shadowLightArrIdx = x0_areaLights.size(); - x2a0_shadowLightIdx = value.x0_areaLightIdx; - } - else if (!outOfBounds) - { - /* Note brightest light contact */ - delta = delta * 1.f / deltaMag; - actorToLightContact = CGameCollision::RayStaticIntersectionArea(area, vec, delta, deltaMag, filter); - if (i == 0) - { - x299_24_inBrightLight = actorToLightContact; - if (x2d8_brightLightIdx != value.x0_areaLightIdx) - { - x2dc_brightLightLag = actorToLightContact ? 0 : 15; - x2d8_brightLightIdx = value.x0_areaLightIdx; - } - x299_25_useBrightLightLag = false; - actorToLightContact = true; - } - } - } - if (actorToLightContact) - { - /* Add to final list */ - if (x0_areaLights.size() == 0) - mostSigLightIdx = i; - x0_areaLights.push_back(light); - } - } - else - { - /* Overflow light */ - if (!x298_29_ambienceGenerated && value.x10_colorMag > 0.001f) - { - /* Average parameters into final light */ - MergeOverflowLight(overflowLight, overflowLightColor, light, value.x10_colorMag); - overflowMag += value.x10_colorMag; - } - else - { - /* Average color into ambient channel */ - overflowAmbColor += value.x4_color; - } - } - } - - /* Finalize overflow lights */ - if (!x298_29_ambienceGenerated) - AddOverflowToLights(overflowLight, overflowLightColor, overflowMag); - else - MoveAmbienceToLights(overflowAmbColor); - - /* Clamp ambient color */ - if (x288_ambientColor.r() > 1.f) - x288_ambientColor.r() = 1.f; - if (x288_ambientColor.g() > 1.f) - x288_ambientColor.g() = 1.f; - if (x288_ambientColor.b() > 1.f) - x288_ambientColor.b() = 1.f; +void CActorLights::MoveAmbienceToLights(const zeus::CColor& color) { + if (x298_29_ambienceGenerated) { + x288_ambientColor += color * 0.333333f; x288_ambientColor.a() = 1.f; + return; + } - /* Multiply down lighting with world fader level */ - if (worldLightingLevel < 1.f) - MultiplyLightingLevels(worldLightingLevel); - - return true; + zeus::CColor useColor = x0_areaLights[0].GetColor() + color; + float maxComponent = std::max(useColor.r(), std::max(useColor.g(), useColor.b())); + if (maxComponent > FLT_EPSILON) + useColor *= (1.f / maxComponent); + useColor.a() = 1.f; + x0_areaLights[0].SetColor(useColor); } -void CActorLights::BuildDynamicLightList(const CStateManager& mgr, const zeus::CAABox& aabb) -{ - UpdateBrightLight(); - x299_26_ambientOnly = false; - x144_dynamicLights.clear(); - - if (!x29a_findNearestDynamicLights) - { - for (const CLight& light : mgr.GetDynamicLightList()) - { - zeus::CSphere sphere(light.GetPosition(), light.GetRadius()); - if (aabb.intersects(sphere)) - x144_dynamicLights.push_back(light); - if (x144_dynamicLights.size() >= x2bc_maxDynamicLights) - break; - } - } - else - { - const CLight* addedLights[8] = {}; - for (int i=0 ; i= 0.f && intRadius < minRad) - { - bool alreadyIn = false; - for (int j=0 ; j= x2bc_maxDynamicLights) - break; - } - } +void CActorLights::MultiplyLightingLevels(float level) { + x288_ambientColor *= level; + for (CLight& light : x0_areaLights) { + zeus::CColor color = light.GetColor(); + color *= level; + color.a() = 1.f; + light.SetColor(color); + } } -std::vector CActorLights::BuildLightVector() const -{ - std::vector lights; - - if (x0_areaLights.size()) - { - if (x2dc_brightLightLag && x299_25_useBrightLightLag) - { - CLight overrideLight = x0_areaLights[0]; - overrideLight.SetColor(overrideLight.GetColor() * (1.f - x2dc_brightLightLag / 15.f)); - lights.push_back(overrideLight); - } - else - lights.push_back(x0_areaLights[0]); - - for (auto it = x0_areaLights.begin() + 1 ; it != x0_areaLights.end() ; ++it) - { - lights.push_back(*it); - } - - if (x29c_shadowLightArrIdx > 0) - { - /* Ensure shadow light comes first for shader extension */ - std::swap(lights[0], lights[x29c_shadowLightArrIdx]); - } - } - - for (const CLight& light : x144_dynamicLights) - lights.push_back(light); - - zeus::CColor ambColor = x288_ambientColor; - ambColor.a() = 1.f; - lights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, ambColor)); - - return lights; +void CActorLights::UpdateBrightLight() { + if (x2dc_brightLightLag > 0 && x299_24_inBrightLight) + --x2dc_brightLightLag; + else if (x2dc_brightLightLag < 15 && !x299_24_inBrightLight) + ++x2dc_brightLightLag; + x299_25_useBrightLightLag = true; } -void CActorLights::ActivateLights(CBooModel& model) const -{ - std::vector lights; - - if (x298_28_inArea) - { - if (!x298_26_hasAreaLights || x299_26_ambientOnly) - { - //g_Renderer->SetAmbientColor(zeus::CColor::skWhite); - lights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, zeus::CColor::skWhite)); - model.ActivateLights(lights); - return; - } - } - - lights = BuildLightVector(); - model.ActivateLights(lights); - +bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb) { + const std::vector& lightList = + x298_30_layer2 ? area.GetPostConstructed()->x80_lightsB : area.GetPostConstructed()->x60_lightsA; + const std::vector& gfxLightList = + x298_30_layer2 ? area.GetPostConstructed()->x90_gfxLightsB : area.GetPostConstructed()->x70_gfxLightsA; + float worldLightingLevel = area.GetPostConstructed()->x1128_worldLightingLevel; + x298_26_hasAreaLights = lightList.size() != 0; + if (!x298_26_hasAreaLights || !x298_28_inArea) { + /* World lights disabled */ if (x298_31_disableWorldLights) - { - zeus::CColor color(x2d4_worldLightingLevel); - g_Renderer->SetGXRegister1Color(color); + x2d4_worldLightingLevel = worldLightingLevel; + x29c_shadowLightArrIdx = -1; + return true; + } + + zeus::CVector3f vec; + if (!x298_24_dirty && x294_aid == area.GetAreaId()) { + /* Early return if not ready for update */ + if (mgr.GetInputFrameIdx() - x2a4_lastUpdateFrame < x2a8_areaUpdateFramePeriod) + return false; + vec = aabb.center() + x2ac_actorPosBias; + if (x2d4_worldLightingLevel == worldLightingLevel) + if ((x2c0_lastActorPos - vec).magSquared() < x2cc_actorPositionDeltaUpdateThreshold) + return false; + x2c0_lastActorPos = vec; + } else { + if (x294_aid != area.GetAreaId()) + x2d8_brightLightIdx = -1; + x2a4_lastUpdateFrame = sFrameSchedulerCount + mgr.GetInputFrameIdx(); + vec = aabb.center() + x2ac_actorPosBias; + x2c0_lastActorPos = vec; + } + + /* Reset lighting state */ + x2d4_worldLightingLevel = worldLightingLevel; + x298_24_dirty = false; + x294_aid = area.GetAreaId(); + x29c_shadowLightArrIdx = -1; + x288_ambientColor = zeus::CColor::skClear; + + /* Find candidate lights via PVS */ + bool use2ndLayer; + if (x298_30_layer2) { + if (const CPVSAreaSet* pvs = area.GetAreaVisSet()) + use2ndLayer = pvs->Has2ndLayerLights(); + else + use2ndLayer = true; + } else { + use2ndLayer = false; + } + + CPVSVisSet sets[3]; + sets[0].Reset(EPVSVisSetState::OutOfBounds); + sets[1].Reset(EPVSVisSetState::OutOfBounds); + sets[2].Reset(EPVSVisSetState::OutOfBounds); + + if (const CPVSAreaSet* pvs = area.GetAreaVisSet()) { + zeus::CVector3f localVec = area.GetInverseTransform() * vec; + sets[0].SetTestPoint(pvs->GetVisOctree(), localVec); + localVec = area.GetInverseTransform() * aabb.max; + sets[1].SetTestPoint(pvs->GetVisOctree(), localVec); + localVec = area.GetInverseTransform() * aabb.min; + sets[2].SetTestPoint(pvs->GetVisOctree(), localVec); + } + + std::vector valList; + valList.reserve(lightList.size()); + + auto lightIt = lightList.begin(); + int lightIdx = 0; + for (const CLight& light : gfxLightList) { + if (light.GetType() == ELightType::LocalAmbient) { + /* Take ambient here */ + x288_ambientColor = light.GetNormalIndependentLightingAtPoint(vec); + } else { + EPVSVisSetState visible = EPVSVisSetState::OutOfBounds; + if (area.GetAreaVisSet()) { + if (lightIt->DoesCastShadows()) { + u32 pvsIdx; + if (use2ndLayer) + pvsIdx = area.Get2ndPVSLightFeature(lightIdx); + else + pvsIdx = area.Get1stPVSLightFeature(lightIdx); + visible = sets[0].GetVisible(pvsIdx); + if (visible != EPVSVisSetState::OutOfBounds) + visible = std::max(visible, sets[1].GetVisible(pvsIdx)); + if (visible != EPVSVisSetState::OutOfBounds) + visible = std::max(visible, sets[2].GetVisible(pvsIdx)); + } + } + if (visible != EPVSVisSetState::EndOfTree) { + zeus::CSphere sphere(light.GetPosition(), light.GetRadius() * 2.f); + if (aabb.intersects(sphere)) { + /* Light passes as candidate */ + valList.emplace_back(); + SLightValue& value = valList.back(); + value.x0_areaLightIdx = lightIdx; + value.x4_color = light.GetNormalIndependentLightingAtPoint(vec); + value.x4_color.a() = 0.f; + value.x10_colorMag = value.x4_color.magnitude(); + value.x18_visiblity = visible; + } + } } -} + ++lightIt; + ++lightIdx; + } -void CActorLights::DisableAreaLights() -{ - x2b8_maxAreaLights = 0; - x298_26_hasAreaLights = false; - x298_28_inArea = false; -} + /* Sort lights most intense to least intense */ + std::sort(valList.begin(), valList.end(), + [](const SLightValue& a, const SLightValue& b) { return a.x10_colorMag > b.x10_colorMag; }); -const CLight& CActorLights::GetLight(u32 idx) const -{ - if (x298_28_inArea) - { - if (idx < x0_areaLights.size()) - return x0_areaLights[idx]; - return x144_dynamicLights[idx - x0_areaLights.size()]; + if (x298_27_findShadowLight) { + /* Accumulate magnitudes up to most intense for shadow dynamic range check */ + x288_ambientColor.a() = 0.f; + float mag = x288_ambientColor.magnitude(); + for (auto it = valList.rbegin(); it != valList.rend(); ++it) { + mag += it->x10_colorMag; + it->x14_accumulatedMag = mag; } - return x144_dynamicLights[idx]; + } + + /* Ambient color for overflow area lights */ + zeus::CColor overflowAmbColor = zeus::CColor::skClear; + + /* Averaged light for overflow area lights */ + CLight overflowLight = CLight::BuildCustom(zeus::CVector3f::skZero, zeus::CVector3f::skZero, zeus::CColor::skBlack, + 0.f, 0.f, 0.f, 0.f, 0.f, 0.f); + zeus::CColor overflowLightColor = zeus::CColor::skClear; + float overflowMag = 0.f; + + /* Max significant lights */ + int maxAreaLights = !x298_29_ambienceGenerated ? x2b8_maxAreaLights - 1 : x2b8_maxAreaLights; + x0_areaLights.clear(); + + /* Filter for performing final light visibility test */ + CMaterialFilter filter = CMaterialFilter::MakeIncludeExclude( + CMaterialList(EMaterialTypes::Solid), + CMaterialList(EMaterialTypes::Projectile, EMaterialTypes::ProjectilePassthrough, EMaterialTypes::SeeThrough)); + u32 mostSigLightIdx = 0; + + /* Narrowphase test candidates starting with most intense */ + for (int i = 0; i < valList.size(); ++i) { + const SLightValue& value = valList[i]; + const CLight& light = gfxLightList[value.x0_areaLightIdx]; + if (x0_areaLights.size() < maxAreaLights) { + /* Significant light */ + bool actorToLightContact = true; + bool castShadows = lightList[value.x0_areaLightIdx].DoesCastShadows() && x298_25_castShadows; + bool outOfBounds = area.GetAreaVisSet() && value.x18_visiblity == EPVSVisSetState::OutOfBounds; + if (castShadows) { + /* Process shadow cast */ + zeus::CVector3f delta = light.GetPosition() - vec; + float deltaMag = delta.magnitude(); + bool useShadow = false; + if (x298_27_findShadowLight && x29c_shadowLightArrIdx == -1 && light.GetType() != ELightType::LocalAmbient && + deltaMag > 2.f && !aabb.pointInside(light.GetPosition())) { + /* Perform shadow dynamic range check */ + if (!x0_areaLights.size() || + (x0_areaLights.size() == 1 && value.x10_colorMag / valList[mostSigLightIdx].x10_colorMag > 0.5f)) { + useShadow = value.x10_colorMag / value.x14_accumulatedMag > + x2d0_shadowDynamicRangeThreshold / (1.f + x2d0_shadowDynamicRangeThreshold); + } + } + if (useShadow) { + /* Note shadow light */ + x29c_shadowLightArrIdx = x0_areaLights.size(); + x2a0_shadowLightIdx = value.x0_areaLightIdx; + } else if (!outOfBounds) { + /* Note brightest light contact */ + delta = delta * 1.f / deltaMag; + actorToLightContact = CGameCollision::RayStaticIntersectionArea(area, vec, delta, deltaMag, filter); + if (i == 0) { + x299_24_inBrightLight = actorToLightContact; + if (x2d8_brightLightIdx != value.x0_areaLightIdx) { + x2dc_brightLightLag = actorToLightContact ? 0 : 15; + x2d8_brightLightIdx = value.x0_areaLightIdx; + } + x299_25_useBrightLightLag = false; + actorToLightContact = true; + } + } + } + if (actorToLightContact) { + /* Add to final list */ + if (x0_areaLights.size() == 0) + mostSigLightIdx = i; + x0_areaLights.push_back(light); + } + } else { + /* Overflow light */ + if (!x298_29_ambienceGenerated && value.x10_colorMag > 0.001f) { + /* Average parameters into final light */ + MergeOverflowLight(overflowLight, overflowLightColor, light, value.x10_colorMag); + overflowMag += value.x10_colorMag; + } else { + /* Average color into ambient channel */ + overflowAmbColor += value.x4_color; + } + } + } + + /* Finalize overflow lights */ + if (!x298_29_ambienceGenerated) + AddOverflowToLights(overflowLight, overflowLightColor, overflowMag); + else + MoveAmbienceToLights(overflowAmbColor); + + /* Clamp ambient color */ + if (x288_ambientColor.r() > 1.f) + x288_ambientColor.r() = 1.f; + if (x288_ambientColor.g() > 1.f) + x288_ambientColor.g() = 1.f; + if (x288_ambientColor.b() > 1.f) + x288_ambientColor.b() = 1.f; + x288_ambientColor.a() = 1.f; + + /* Multiply down lighting with world fader level */ + if (worldLightingLevel < 1.f) + MultiplyLightingLevels(worldLightingLevel); + + return true; } -u32 CActorLights::GetActiveLightCount() const -{ - if (x298_28_inArea) - return x0_areaLights.size() + x144_dynamicLights.size(); - return x144_dynamicLights.size(); +void CActorLights::BuildDynamicLightList(const CStateManager& mgr, const zeus::CAABox& aabb) { + UpdateBrightLight(); + x299_26_ambientOnly = false; + x144_dynamicLights.clear(); + + if (!x29a_findNearestDynamicLights) { + for (const CLight& light : mgr.GetDynamicLightList()) { + zeus::CSphere sphere(light.GetPosition(), light.GetRadius()); + if (aabb.intersects(sphere)) + x144_dynamicLights.push_back(light); + if (x144_dynamicLights.size() >= x2bc_maxDynamicLights) + break; + } + } else { + const CLight* addedLights[8] = {}; + for (int i = 0; i < x2bc_maxDynamicLights && i < 8; ++i) { + float minRad = FLT_MAX; + for (const CLight& light : mgr.GetDynamicLightList()) { + zeus::CSphere sphere(light.GetPosition(), light.GetRadius()); + float intRadius = aabb.intersectionRadius(sphere); + if (intRadius >= 0.f && intRadius < minRad) { + bool alreadyIn = false; + for (int j = 0; j < i; ++j) { + if (&light == addedLights[j]) { + alreadyIn = true; + break; + } + } + if (alreadyIn) + continue; + addedLights[i] = &light; + minRad = intRadius; + } + } + if (addedLights[i]) + x144_dynamicLights.push_back(*addedLights[i]); + if (x144_dynamicLights.size() >= x2bc_maxDynamicLights) + break; + } + } } +std::vector CActorLights::BuildLightVector() const { + std::vector lights; + + if (x0_areaLights.size()) { + if (x2dc_brightLightLag && x299_25_useBrightLightLag) { + CLight overrideLight = x0_areaLights[0]; + overrideLight.SetColor(overrideLight.GetColor() * (1.f - x2dc_brightLightLag / 15.f)); + lights.push_back(overrideLight); + } else + lights.push_back(x0_areaLights[0]); + + for (auto it = x0_areaLights.begin() + 1; it != x0_areaLights.end(); ++it) { + lights.push_back(*it); + } + + if (x29c_shadowLightArrIdx > 0) { + /* Ensure shadow light comes first for shader extension */ + std::swap(lights[0], lights[x29c_shadowLightArrIdx]); + } + } + + for (const CLight& light : x144_dynamicLights) + lights.push_back(light); + + zeus::CColor ambColor = x288_ambientColor; + ambColor.a() = 1.f; + lights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, ambColor)); + + return lights; } + +void CActorLights::ActivateLights(CBooModel& model) const { + std::vector lights; + + if (x298_28_inArea) { + if (!x298_26_hasAreaLights || x299_26_ambientOnly) { + // g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + lights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, zeus::CColor::skWhite)); + model.ActivateLights(lights); + return; + } + } + + lights = BuildLightVector(); + model.ActivateLights(lights); + + if (x298_31_disableWorldLights) { + zeus::CColor color(x2d4_worldLightingLevel); + g_Renderer->SetGXRegister1Color(color); + } +} + +void CActorLights::DisableAreaLights() { + x2b8_maxAreaLights = 0; + x298_26_hasAreaLights = false; + x298_28_inArea = false; +} + +const CLight& CActorLights::GetLight(u32 idx) const { + if (x298_28_inArea) { + if (idx < x0_areaLights.size()) + return x0_areaLights[idx]; + return x144_dynamicLights[idx - x0_areaLights.size()]; + } + return x144_dynamicLights[idx]; +} + +u32 CActorLights::GetActiveLightCount() const { + if (x298_28_inArea) + return x0_areaLights.size() + x144_dynamicLights.size(); + return x144_dynamicLights.size(); +} + +} // namespace urde diff --git a/Runtime/Character/CActorLights.hpp b/Runtime/Character/CActorLights.hpp index 2cc8d4665..c4fdcf3c3 100644 --- a/Runtime/Character/CActorLights.hpp +++ b/Runtime/Character/CActorLights.hpp @@ -6,96 +6,90 @@ #include "zeus/CAABox.hpp" #include "Graphics/CLight.hpp" -namespace urde -{ +namespace urde { class CBooModel; class CStateManager; class CGameArea; -class CActorLights -{ - static s32 sFrameSchedulerCount; - std::vector x0_areaLights; - std::vector x144_dynamicLights; - zeus::CColor x288_ambientColor = zeus::CColor::skBlack; - TAreaId x294_aid = kInvalidAreaId; +class CActorLights { + static s32 sFrameSchedulerCount; + std::vector x0_areaLights; + std::vector x144_dynamicLights; + zeus::CColor x288_ambientColor = zeus::CColor::skBlack; + TAreaId x294_aid = kInvalidAreaId; - union - { - struct - { - bool x298_24_dirty : 1; - bool x298_25_castShadows : 1; - bool x298_26_hasAreaLights : 1; - bool x298_27_findShadowLight : 1; - bool x298_28_inArea : 1; - bool x298_29_ambienceGenerated : 1; - bool x298_30_layer2 : 1; - bool x298_31_disableWorldLights : 1; - bool x299_24_inBrightLight : 1; - bool x299_25_useBrightLightLag : 1; - bool x299_26_ambientOnly : 1; - }; - u16 _dummy = 0; + union { + struct { + bool x298_24_dirty : 1; + bool x298_25_castShadows : 1; + bool x298_26_hasAreaLights : 1; + bool x298_27_findShadowLight : 1; + bool x298_28_inArea : 1; + bool x298_29_ambienceGenerated : 1; + bool x298_30_layer2 : 1; + bool x298_31_disableWorldLights : 1; + bool x299_24_inBrightLight : 1; + bool x299_25_useBrightLightLag : 1; + bool x299_26_ambientOnly : 1; }; - bool x29a_findNearestDynamicLights = false; - s32 x29c_shadowLightArrIdx = -1; - s32 x2a0_shadowLightIdx = -1; - u32 x2a4_lastUpdateFrame = 0; - u32 x2a8_areaUpdateFramePeriod; - zeus::CVector3f x2ac_actorPosBias; - int x2b8_maxAreaLights; - int x2bc_maxDynamicLights; - zeus::CVector3f x2c0_lastActorPos; - float x2cc_actorPositionDeltaUpdateThreshold; - float x2d0_shadowDynamicRangeThreshold = 0.f; - float x2d4_worldLightingLevel = 1.f; - s32 x2d8_brightLightIdx = -1; - u32 x2dc_brightLightLag = 0; + u16 _dummy = 0; + }; + bool x29a_findNearestDynamicLights = false; + s32 x29c_shadowLightArrIdx = -1; + s32 x2a0_shadowLightIdx = -1; + u32 x2a4_lastUpdateFrame = 0; + u32 x2a8_areaUpdateFramePeriod; + zeus::CVector3f x2ac_actorPosBias; + int x2b8_maxAreaLights; + int x2bc_maxDynamicLights; + zeus::CVector3f x2c0_lastActorPos; + float x2cc_actorPositionDeltaUpdateThreshold; + float x2d0_shadowDynamicRangeThreshold = 0.f; + float x2d4_worldLightingLevel = 1.f; + s32 x2d8_brightLightIdx = -1; + u32 x2dc_brightLightLag = 0; - static void MergeOverflowLight(CLight& out, zeus::CColor& color, const CLight& in, float colorMag); - void AddOverflowToLights(const CLight& light, const zeus::CColor& color, float mag); - void MoveAmbienceToLights(const zeus::CColor& color); - void MultiplyLightingLevels(float level); - void UpdateBrightLight(); + static void MergeOverflowLight(CLight& out, zeus::CColor& color, const CLight& in, float colorMag); + void AddOverflowToLights(const CLight& light, const zeus::CColor& color, float mag); + void MoveAmbienceToLights(const zeus::CColor& color); + void MultiplyLightingLevels(float level); + void UpdateBrightLight(); public: - CActorLights(u32 areaUpdateFramePeriod, const zeus::CVector3f& actorPosBias, - int maxDynamicLights, int maxAreaLights, bool ambientChannelOverflow, - bool layer2, bool disableWorldLights, float positionUpdateThreshold); + CActorLights(u32 areaUpdateFramePeriod, const zeus::CVector3f& actorPosBias, int maxDynamicLights, int maxAreaLights, + bool ambientChannelOverflow, bool layer2, bool disableWorldLights, float positionUpdateThreshold); - void BuildConstantAmbientLighting(); - void BuildConstantAmbientLighting(const zeus::CColor& color); - void BuildFakeLightList(const std::vector& lights, const zeus::CColor& color); - void BuildFaceLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb); - bool BuildAreaLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb); - void BuildDynamicLightList(const CStateManager& mgr, const zeus::CAABox& aabb); - std::vector BuildLightVector() const; - void ActivateLights(CBooModel& model) const; - void SetCastShadows(bool v) { x298_25_castShadows = v; } - void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; } - void SetShadowDynamicRangeThreshold(float t) { x2d0_shadowDynamicRangeThreshold = t; } - void SetAmbienceGenerated(bool v) { x298_29_ambienceGenerated = v; } - void DisableAreaLights(); - void SetMaxDynamicLights(int l) { x2bc_maxDynamicLights = l; } - void SetFindNearestDynamicLights(bool v) { x29a_findNearestDynamicLights = v; } - void SetAmbientColor(const zeus::CColor& color) { x288_ambientColor = color; } - const zeus::CColor& GetAmbientColor() const { return x288_ambientColor; } - const CLight& GetLight(u32 idx) const; - u32 GetActiveLightCount() const; - int GetMaxAreaLights() const { return x2b8_maxAreaLights; } - const std::vector& GetAreaLights() const { return x0_areaLights; } - const std::vector& GetDynamicLights() const { return x144_dynamicLights; } - bool GetIsDirty() const { return x298_24_dirty; } - void SetDirty() { x298_24_dirty = true; } - bool HasShadowLight() const { return x29c_shadowLightArrIdx != -1; } - s32 GetShadowLightArrIndex() const { return x29c_shadowLightArrIdx; } - s32 GetShadowLightIndex() const { return x2a0_shadowLightIdx; } - u32 GetAreaUpdateFramePeriod() const { return x2a8_areaUpdateFramePeriod; } - void SetAreaUpdateFramePeriod(u32 p) { x2a8_areaUpdateFramePeriod = p; } - zeus::CVector3f GetActorPositionBias() const { return x2ac_actorPosBias; } - void SetActorPositionBias(const zeus::CVector3f& bias) { x2ac_actorPosBias = bias; } + void BuildConstantAmbientLighting(); + void BuildConstantAmbientLighting(const zeus::CColor& color); + void BuildFakeLightList(const std::vector& lights, const zeus::CColor& color); + void BuildFaceLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb); + bool BuildAreaLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb); + void BuildDynamicLightList(const CStateManager& mgr, const zeus::CAABox& aabb); + std::vector BuildLightVector() const; + void ActivateLights(CBooModel& model) const; + void SetCastShadows(bool v) { x298_25_castShadows = v; } + void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; } + void SetShadowDynamicRangeThreshold(float t) { x2d0_shadowDynamicRangeThreshold = t; } + void SetAmbienceGenerated(bool v) { x298_29_ambienceGenerated = v; } + void DisableAreaLights(); + void SetMaxDynamicLights(int l) { x2bc_maxDynamicLights = l; } + void SetFindNearestDynamicLights(bool v) { x29a_findNearestDynamicLights = v; } + void SetAmbientColor(const zeus::CColor& color) { x288_ambientColor = color; } + const zeus::CColor& GetAmbientColor() const { return x288_ambientColor; } + const CLight& GetLight(u32 idx) const; + u32 GetActiveLightCount() const; + int GetMaxAreaLights() const { return x2b8_maxAreaLights; } + const std::vector& GetAreaLights() const { return x0_areaLights; } + const std::vector& GetDynamicLights() const { return x144_dynamicLights; } + bool GetIsDirty() const { return x298_24_dirty; } + void SetDirty() { x298_24_dirty = true; } + bool HasShadowLight() const { return x29c_shadowLightArrIdx != -1; } + s32 GetShadowLightArrIndex() const { return x29c_shadowLightArrIdx; } + s32 GetShadowLightIndex() const { return x2a0_shadowLightIdx; } + u32 GetAreaUpdateFramePeriod() const { return x2a8_areaUpdateFramePeriod; } + void SetAreaUpdateFramePeriod(u32 p) { x2a8_areaUpdateFramePeriod = p; } + zeus::CVector3f GetActorPositionBias() const { return x2ac_actorPosBias; } + void SetActorPositionBias(const zeus::CVector3f& bias) { x2ac_actorPosBias = bias; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAdditiveAnimPlayback.cpp b/Runtime/Character/CAdditiveAnimPlayback.cpp index b643bbfef..91e1fe619 100644 --- a/Runtime/Character/CAdditiveAnimPlayback.cpp +++ b/Runtime/Character/CAdditiveAnimPlayback.cpp @@ -3,113 +3,99 @@ #include "CCharLayoutInfo.hpp" #include "CAnimTreeNode.hpp" -namespace urde -{ +namespace urde { -CAdditiveAnimPlayback::CAdditiveAnimPlayback(const std::weak_ptr& anim, - float weight, bool active, const CAdditiveAnimationInfo& info, - bool fadeOut) -: x0_info(info), x8_anim(anim.lock()), xc_targetWeight(weight), x14_active(active) -{ - if (!active && fadeOut) - x20_needsFadeOut = true; +CAdditiveAnimPlayback::CAdditiveAnimPlayback(const std::weak_ptr& anim, float weight, bool active, + const CAdditiveAnimationInfo& info, bool fadeOut) +: x0_info(info), x8_anim(anim.lock()), xc_targetWeight(weight), x14_active(active) { + if (!active && fadeOut) + x20_needsFadeOut = true; } -void CAdditiveAnimPlayback::AddToSegStatementSet(const CSegIdList& list, - const CCharLayoutInfo& layout, - CSegStatementSet& setOut) const -{ - CSegStatementSet stackSet; - x8_anim->VGetSegStatementSet(list, stackSet); - for (const CSegId& id : list.GetList()) - { - CAnimPerSegmentData& data = stackSet.x4_segData[id]; - data.x10_offset = layout.GetFromParentUnrotated(id); - data.x1c_hasOffset = true; - } - setOut.Add(list, layout, stackSet, x10_curWeight); +void CAdditiveAnimPlayback::AddToSegStatementSet(const CSegIdList& list, const CCharLayoutInfo& layout, + CSegStatementSet& setOut) const { + CSegStatementSet stackSet; + x8_anim->VGetSegStatementSet(list, stackSet); + for (const CSegId& id : list.GetList()) { + CAnimPerSegmentData& data = stackSet.x4_segData[id]; + data.x10_offset = layout.GetFromParentUnrotated(id); + data.x1c_hasOffset = true; + } + setOut.Add(list, layout, stackSet, x10_curWeight); } -void CAdditiveAnimPlayback::Update(float dt) -{ - switch (x1c_phase) - { - case EAdditivePlaybackPhase::FadingIn: - { - float a = x0_info.GetFadeInDuration(); - float b = x18_weightTimer + dt; - x18_weightTimer = std::min(b, a); - if (a > 0.f) - x10_curWeight = x18_weightTimer / a * xc_targetWeight; - else - x10_curWeight = xc_targetWeight; - - if (std::fabs(x10_curWeight - xc_targetWeight) < 0.00001f) - x1c_phase = EAdditivePlaybackPhase::FadedIn; - - break; - } - case EAdditivePlaybackPhase::FadingOut: - { - float a = x18_weightTimer - dt; - x18_weightTimer = std::max(a, 0.f); - if (x0_info.GetFadeOutDuration() > 0.f) - x10_curWeight = x18_weightTimer / x0_info.GetFadeOutDuration() * xc_targetWeight; - else - x10_curWeight = 0.f; - - if (std::fabs(x10_curWeight) < 0.00001f) - x1c_phase = EAdditivePlaybackPhase::FadedOut; - } - default: break; - } -} - -void CAdditiveAnimPlayback::FadeOut() -{ - switch (x1c_phase) - { - case EAdditivePlaybackPhase::FadedOut: - case EAdditivePlaybackPhase::FadedIn: - x18_weightTimer = x0_info.GetFadeOutDuration(); - break; - case EAdditivePlaybackPhase::FadingIn: - x18_weightTimer = x18_weightTimer / x0_info.GetFadeInDuration() * x0_info.GetFadeOutDuration(); - default: break; - } - - if (x0_info.GetFadeOutDuration() > 0.f) - x1c_phase = EAdditivePlaybackPhase::FadingOut; +void CAdditiveAnimPlayback::Update(float dt) { + switch (x1c_phase) { + case EAdditivePlaybackPhase::FadingIn: { + float a = x0_info.GetFadeInDuration(); + float b = x18_weightTimer + dt; + x18_weightTimer = std::min(b, a); + if (a > 0.f) + x10_curWeight = x18_weightTimer / a * xc_targetWeight; else - x1c_phase = EAdditivePlaybackPhase::FadedOut; - x10_curWeight = 0.f; + x10_curWeight = xc_targetWeight; + + if (std::fabs(x10_curWeight - xc_targetWeight) < 0.00001f) + x1c_phase = EAdditivePlaybackPhase::FadedIn; + + break; + } + case EAdditivePlaybackPhase::FadingOut: { + float a = x18_weightTimer - dt; + x18_weightTimer = std::max(a, 0.f); + if (x0_info.GetFadeOutDuration() > 0.f) + x10_curWeight = x18_weightTimer / x0_info.GetFadeOutDuration() * xc_targetWeight; + else + x10_curWeight = 0.f; + + if (std::fabs(x10_curWeight) < 0.00001f) + x1c_phase = EAdditivePlaybackPhase::FadedOut; + } + default: + break; + } } -void CAdditiveAnimPlayback::SetWeight(float w) -{ - xc_targetWeight = w; - switch (x1c_phase) - { - case EAdditivePlaybackPhase::FadingIn: - { - if (x0_info.GetFadeInDuration() > 0.f) - x10_curWeight = x18_weightTimer / x0_info.GetFadeInDuration() * xc_targetWeight; - else - x10_curWeight = xc_targetWeight; - break; - } - case EAdditivePlaybackPhase::FadingOut: - { - if (x0_info.GetFadeOutDuration() > 0.f) - x10_curWeight = x18_weightTimer / x0_info.GetFadeOutDuration() * xc_targetWeight; - else - x10_curWeight = xc_targetWeight; - break; - } - default: - x10_curWeight = xc_targetWeight; - break; - } +void CAdditiveAnimPlayback::FadeOut() { + switch (x1c_phase) { + case EAdditivePlaybackPhase::FadedOut: + case EAdditivePlaybackPhase::FadedIn: + x18_weightTimer = x0_info.GetFadeOutDuration(); + break; + case EAdditivePlaybackPhase::FadingIn: + x18_weightTimer = x18_weightTimer / x0_info.GetFadeInDuration() * x0_info.GetFadeOutDuration(); + default: + break; + } + + if (x0_info.GetFadeOutDuration() > 0.f) + x1c_phase = EAdditivePlaybackPhase::FadingOut; + else + x1c_phase = EAdditivePlaybackPhase::FadedOut; + x10_curWeight = 0.f; } +void CAdditiveAnimPlayback::SetWeight(float w) { + xc_targetWeight = w; + switch (x1c_phase) { + case EAdditivePlaybackPhase::FadingIn: { + if (x0_info.GetFadeInDuration() > 0.f) + x10_curWeight = x18_weightTimer / x0_info.GetFadeInDuration() * xc_targetWeight; + else + x10_curWeight = xc_targetWeight; + break; + } + case EAdditivePlaybackPhase::FadingOut: { + if (x0_info.GetFadeOutDuration() > 0.f) + x10_curWeight = x18_weightTimer / x0_info.GetFadeOutDuration() * xc_targetWeight; + else + x10_curWeight = xc_targetWeight; + break; + } + default: + x10_curWeight = xc_targetWeight; + break; + } } + +} // namespace urde diff --git a/Runtime/Character/CAdditiveAnimPlayback.hpp b/Runtime/Character/CAdditiveAnimPlayback.hpp index df5a2de1a..b0a5872a8 100644 --- a/Runtime/Character/CAdditiveAnimPlayback.hpp +++ b/Runtime/Character/CAdditiveAnimPlayback.hpp @@ -2,66 +2,56 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CAnimTreeNode; class CAdditiveAnimationInfo; class CSegIdList; class CCharLayoutInfo; class CSegStatementSet; -class CAdditiveAnimationInfo -{ - float x0_fadeInDur = 0.f; - float x4_fadeOutDur = 0.f; +class CAdditiveAnimationInfo { + float x0_fadeInDur = 0.f; + float x4_fadeOutDur = 0.f; + public: - void read(CInputStream& in) - { - x0_fadeInDur = in.readFloatBig(); - x4_fadeOutDur = in.readFloatBig(); - } - CAdditiveAnimationInfo() = default; - CAdditiveAnimationInfo(CInputStream& in) {read(in);} - float GetFadeInDuration() const {return x0_fadeInDur;} - float GetFadeOutDuration() const {return x4_fadeOutDur;} + void read(CInputStream& in) { + x0_fadeInDur = in.readFloatBig(); + x4_fadeOutDur = in.readFloatBig(); + } + CAdditiveAnimationInfo() = default; + CAdditiveAnimationInfo(CInputStream& in) { read(in); } + float GetFadeInDuration() const { return x0_fadeInDur; } + float GetFadeOutDuration() const { return x4_fadeOutDur; } }; -enum class EAdditivePlaybackPhase -{ - None, - FadingIn, - FadingOut, - FadedIn, - FadedOut -}; +enum class EAdditivePlaybackPhase { None, FadingIn, FadingOut, FadedIn, FadedOut }; + +class CAdditiveAnimPlayback { + CAdditiveAnimationInfo x0_info; + std::shared_ptr x8_anim; + float xc_targetWeight; + float x10_curWeight = 0.f; + bool x14_active; + float x18_weightTimer = 0.f; + EAdditivePlaybackPhase x1c_phase = EAdditivePlaybackPhase::FadingIn; + bool x20_needsFadeOut = false; -class CAdditiveAnimPlayback -{ - CAdditiveAnimationInfo x0_info; - std::shared_ptr x8_anim; - float xc_targetWeight; - float x10_curWeight = 0.f; - bool x14_active; - float x18_weightTimer = 0.f; - EAdditivePlaybackPhase x1c_phase = EAdditivePlaybackPhase::FadingIn; - bool x20_needsFadeOut = false; public: - CAdditiveAnimPlayback(const std::weak_ptr& anim, float weight, bool active, - const CAdditiveAnimationInfo& info, bool fadeOut); + CAdditiveAnimPlayback(const std::weak_ptr& anim, float weight, bool active, + const CAdditiveAnimationInfo& info, bool fadeOut); - void AddToSegStatementSet(const CSegIdList& list, const CCharLayoutInfo&, CSegStatementSet&) const; - void Update(float dt); - void FadeOut(); - void SetWeight(float w); - float GetTargetWeight() const {return xc_targetWeight;} - bool IsActive() const {return x14_active;} - void SetActive(bool active) {x14_active = active;} - const std::shared_ptr& GetAnim() const {return x8_anim;} - std::shared_ptr& GetAnim() {return x8_anim;} - EAdditivePlaybackPhase GetPhase() const {return x1c_phase;} - void SetNeedsFadeOut(bool b) {x20_needsFadeOut = b;} - bool NeedsFadeOut() const {return x20_needsFadeOut;} + void AddToSegStatementSet(const CSegIdList& list, const CCharLayoutInfo&, CSegStatementSet&) const; + void Update(float dt); + void FadeOut(); + void SetWeight(float w); + float GetTargetWeight() const { return xc_targetWeight; } + bool IsActive() const { return x14_active; } + void SetActive(bool active) { x14_active = active; } + const std::shared_ptr& GetAnim() const { return x8_anim; } + std::shared_ptr& GetAnim() { return x8_anim; } + EAdditivePlaybackPhase GetPhase() const { return x1c_phase; } + void SetNeedsFadeOut(bool b) { x20_needsFadeOut = b; } + bool NeedsFadeOut() const { return x20_needsFadeOut; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAdditiveBodyState.cpp b/Runtime/Character/CAdditiveBodyState.cpp index 61302e2aa..61f09953f 100644 --- a/Runtime/Character/CAdditiveBodyState.cpp +++ b/Runtime/Character/CAdditiveBodyState.cpp @@ -5,227 +5,195 @@ #include "CAnimTreeNode.hpp" #include "CPASAnimParmData.hpp" -namespace urde -{ +namespace urde { -void CABSAim::Start(CBodyController& bc, CStateManager& mgr) -{ - //const CBCAdditiveAimCmd* cmd = - // static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim)); - const CPASAnimState* aimState = bc.GetPASDatabase().GetAnimState(22); +void CABSAim::Start(CBodyController& bc, CStateManager& mgr) { + // const CBCAdditiveAimCmd* cmd = + // static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim)); + const CPASAnimState* aimState = bc.GetPASDatabase().GetAnimState(22); - // Left, Right, Up, Down - for (int i=0 ; i<4 ; ++i) - { - CPASAnimParmData parms(22, CPASAnimParm::FromEnum(i)); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - x8_anims[i] = best.second; - x18_angles[i] = zeus::degToRad(aimState->GetAnimParmData(x8_anims[i], 1).GetReal32Value()); - } + // Left, Right, Up, Down + for (int i = 0; i < 4; ++i) { + CPASAnimParmData parms(22, CPASAnimParm::FromEnum(i)); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + x8_anims[i] = best.second; + x18_angles[i] = zeus::degToRad(aimState->GetAnimParmData(x8_anims[i], 1).GetReal32Value()); + } - const CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData(); - x28_hWeight = -animData.GetAdditiveAnimationWeight(x8_anims[0]); - x28_hWeight += animData.GetAdditiveAnimationWeight(x8_anims[1]); - x30_vWeight = -animData.GetAdditiveAnimationWeight(x8_anims[2]); - x30_vWeight += animData.GetAdditiveAnimationWeight(x8_anims[3]); + const CAnimData& animData = *bc.GetOwner().GetModelData()->GetAnimationData(); + x28_hWeight = -animData.GetAdditiveAnimationWeight(x8_anims[0]); + x28_hWeight += animData.GetAdditiveAnimationWeight(x8_anims[1]); + x30_vWeight = -animData.GetAdditiveAnimationWeight(x8_anims[2]); + x30_vWeight += animData.GetAdditiveAnimationWeight(x8_anims[3]); - x4_needsIdle = false; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle)) - x4_needsIdle = true; + x4_needsIdle = false; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle)) + x4_needsIdle = true; } -pas::EAnimationState CABSAim::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction)) - return pas::EAnimationState::AdditiveReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch)) - return pas::EAnimationState::AdditiveFlinch; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle) || x4_needsIdle) +pas::EAnimationState CABSAim::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction)) + return pas::EAnimationState::AdditiveReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch)) + return pas::EAnimationState::AdditiveFlinch; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveIdle) || x4_needsIdle) + return pas::EAnimationState::AdditiveIdle; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CABSAim::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + const zeus::CVector3f& target = bc.GetCommandMgr().GetAdditiveTargetVector(); + if (target.canBeNormalized()) { + CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); + + float hAngle = zeus::clamp(-x18_angles[0], std::atan2(target.x(), target.y()), x18_angles[1]); + hAngle *= 0.63661975f; + hAngle = zeus::clamp(-3.f, (hAngle - x28_hWeight) * 0.25f / dt, 3.f); + x2c_hWeightVel += dt * zeus::clamp(-10.f, (hAngle - x2c_hWeightVel) / dt, 10.f); + + float hypotenuse = std::sqrt(target.y() * target.y() + target.x() * target.x()); + float vAngle = zeus::clamp(-x18_angles[3], std::atan2(target.z(), hypotenuse), x18_angles[2]); + vAngle *= 0.63661975f; + vAngle = zeus::clamp(-3.f, (vAngle - x30_vWeight) * 0.25f / dt, 3.f); + x34_vWeightVel += dt * zeus::clamp(-10.f, (vAngle - x34_vWeightVel) / dt, 10.f); + + float newHWeight = dt * x2c_hWeightVel + x28_hWeight; + if (newHWeight != x28_hWeight) { + if (std::fabs(x28_hWeight) > 0.f && x28_hWeight * newHWeight <= 0.f) + animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]); + float absWeight = std::fabs(newHWeight); + if (absWeight > 0.f) + animData.AddAdditiveAnimation(x8_anims[newHWeight < 0.f ? 0 : 1], absWeight, false, false); + } + + float newVWeight = dt * x34_vWeightVel + x30_vWeight; + if (newVWeight != x30_vWeight) { + if (std::fabs(x30_vWeight) > 0.f && x30_vWeight * newVWeight <= 0.f) + animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]); + float absWeight = std::fabs(newVWeight); + if (absWeight > 0.f) + animData.AddAdditiveAnimation(x8_anims[newVWeight > 0.f ? 2 : 3], absWeight, false, false); + } + + x28_hWeight = newHWeight; + x30_vWeight = newVWeight; + } + } + return st; +} + +void CABSAim::Shutdown(CBodyController& bc) { + CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); + + if (x28_hWeight != 0.f) + animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]); + if (x30_vWeight != 0.f) + animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]); +} + +void CABSFlinch::Start(CBodyController& bc, CStateManager& mgr) { + const CBCAdditiveFlinchCmd* cmd = + static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch)); + x4_weight = cmd->GetWeight(); + + CPASAnimParmData parms(23); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + x8_anim = best.second; + + CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); + animData.AddAdditiveAnimation(x8_anim, x4_weight, false, true); +} + +pas::EAnimationState CABSFlinch::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction)) + return pas::EAnimationState::AdditiveReaction; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CABSFlinch::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); + CCharAnimTime rem = animData.GetAdditiveAnimationTree(x8_anim)->VGetTimeRemaining(); + if (std::fabs(rem.GetSeconds()) < 0.00001f) + return pas::EAnimationState::AdditiveIdle; + } + return st; +} + +pas::EAnimationState CABSIdle::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction)) + return pas::EAnimationState::AdditiveReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch)) + return pas::EAnimationState::AdditiveFlinch; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim)) + return pas::EAnimationState::AdditiveAim; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CABSIdle::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + return GetBodyStateTransition(dt, bc); +} + +void CABSReaction::Start(CBodyController& bc, CStateManager& mgr) { + const CBCAdditiveReactionCmd* cmd = + static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction)); + x4_weight = cmd->GetWeight(); + xc_type = cmd->GetType(); + x10_active = cmd->GetIsActive(); + + CPASAnimParmData parms(24, CPASAnimParm::FromEnum(s32(xc_type))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + x8_anim = best.second; + + if (x8_anim != -1) { + CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); + animData.AddAdditiveAnimation(x8_anim, x4_weight, x10_active, false); + } +} + +pas::EAnimationState CABSReaction::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction) && xc_type == pas::EAdditiveReactionType::IceBreakout) + return pas::EAnimationState::AdditiveReaction; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CABSReaction::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + if (x8_anim == -1) + return pas::EAnimationState::AdditiveIdle; + + CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); + if (x10_active) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::StopReaction)) { + StopAnimation(bc); + bc.GetOwner().RemoveEmitter(); return pas::EAnimationState::AdditiveIdle; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CABSAim::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - const zeus::CVector3f& target = bc.GetCommandMgr().GetAdditiveTargetVector(); - if (target.canBeNormalized()) - { - CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); - - float hAngle = zeus::clamp(-x18_angles[0], std::atan2(target.x(), target.y()), x18_angles[1]); - hAngle *= 0.63661975f; - hAngle = zeus::clamp(-3.f, (hAngle - x28_hWeight) * 0.25f / dt, 3.f); - x2c_hWeightVel += dt * zeus::clamp(-10.f, (hAngle - x2c_hWeightVel) / dt, 10.f); - - float hypotenuse = std::sqrt(target.y() * target.y() + target.x() * target.x()); - float vAngle = zeus::clamp(-x18_angles[3], std::atan2(target.z(), hypotenuse), x18_angles[2]); - vAngle *= 0.63661975f; - vAngle = zeus::clamp(-3.f, (vAngle - x30_vWeight) * 0.25f / dt, 3.f); - x34_vWeightVel += dt * zeus::clamp(-10.f, (vAngle - x34_vWeightVel) / dt, 10.f); - - float newHWeight = dt * x2c_hWeightVel + x28_hWeight; - if (newHWeight != x28_hWeight) - { - if (std::fabs(x28_hWeight) > 0.f && x28_hWeight * newHWeight <= 0.f) - animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]); - float absWeight = std::fabs(newHWeight); - if (absWeight > 0.f) - animData.AddAdditiveAnimation(x8_anims[newHWeight < 0.f ? 0 : 1], absWeight, false, false); - } - - float newVWeight = dt * x34_vWeightVel + x30_vWeight; - if (newVWeight != x30_vWeight) - { - if (std::fabs(x30_vWeight) > 0.f && x30_vWeight * newVWeight <= 0.f) - animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]); - float absWeight = std::fabs(newVWeight); - if (absWeight > 0.f) - animData.AddAdditiveAnimation(x8_anims[newVWeight > 0.f ? 2 : 3], absWeight, false, false); - } - - x28_hWeight = newHWeight; - x30_vWeight = newVWeight; - } - } - return st; -} - -void CABSAim::Shutdown(CBodyController& bc) -{ - CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); - - if (x28_hWeight != 0.f) - animData.DelAdditiveAnimation(x8_anims[x28_hWeight < 0.f ? 0 : 1]); - if (x30_vWeight != 0.f) - animData.DelAdditiveAnimation(x8_anims[x30_vWeight > 0.f ? 2 : 3]); -} - -void CABSFlinch::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCAdditiveFlinchCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch)); - x4_weight = cmd->GetWeight(); - - CPASAnimParmData parms(23); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - x8_anim = best.second; - - CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); - animData.AddAdditiveAnimation(x8_anim, x4_weight, false, true); -} - -pas::EAnimationState CABSFlinch::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction)) - return pas::EAnimationState::AdditiveReaction; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CABSFlinch::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); + } + } else { + if (animData.IsAdditiveAnimationAdded(x8_anim)) { CCharAnimTime rem = animData.GetAdditiveAnimationTree(x8_anim)->VGetTimeRemaining(); - if (std::fabs(rem.GetSeconds()) < 0.00001f) - return pas::EAnimationState::AdditiveIdle; - } - return st; -} - -pas::EAnimationState CABSIdle::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction)) - return pas::EAnimationState::AdditiveReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveFlinch)) - return pas::EAnimationState::AdditiveFlinch; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveAim)) - return pas::EAnimationState::AdditiveAim; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CABSIdle::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - return GetBodyStateTransition(dt, bc); -} - -void CABSReaction::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCAdditiveReactionCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction)); - x4_weight = cmd->GetWeight(); - xc_type = cmd->GetType(); - x10_active = cmd->GetIsActive(); - - CPASAnimParmData parms(24, CPASAnimParm::FromEnum(s32(xc_type))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - x8_anim = best.second; - - if (x8_anim != -1) - { - CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); - animData.AddAdditiveAnimation(x8_anim, x4_weight, x10_active, false); - } -} - -pas::EAnimationState CABSReaction::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::AdditiveReaction) && - xc_type == pas::EAdditiveReactionType::IceBreakout) - return pas::EAnimationState::AdditiveReaction; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CABSReaction::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - if (x8_anim == -1) - return pas::EAnimationState::AdditiveIdle; - - CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); - if (x10_active) - { - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::StopReaction)) - { - StopAnimation(bc); - bc.GetOwner().RemoveEmitter(); - return pas::EAnimationState::AdditiveIdle; - } - } - else - { - if (animData.IsAdditiveAnimationAdded(x8_anim)) - { - CCharAnimTime rem = animData.GetAdditiveAnimationTree(x8_anim)->VGetTimeRemaining(); - if (std::fabs(rem.GetSeconds()) < 0.00001f) - { - StopAnimation(bc); - return pas::EAnimationState::AdditiveIdle; - } - } - else - { - return pas::EAnimationState::AdditiveIdle; - } + if (std::fabs(rem.GetSeconds()) < 0.00001f) { + StopAnimation(bc); + return pas::EAnimationState::AdditiveIdle; } + } else { + return pas::EAnimationState::AdditiveIdle; + } } - return st; + } + return st; } -void CABSReaction::StopAnimation(CBodyController& bc) -{ - if (x8_anim != -1) - { - CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); - animData.DelAdditiveAnimation(x8_anim); - x8_anim = -1; - } +void CABSReaction::StopAnimation(CBodyController& bc) { + if (x8_anim != -1) { + CAnimData& animData = *bc.GetOwner().ModelData()->AnimationData(); + animData.DelAdditiveAnimation(x8_anim); + x8_anim = -1; + } } -} +} // namespace urde diff --git a/Runtime/Character/CAdditiveBodyState.hpp b/Runtime/Character/CAdditiveBodyState.hpp index 23b27e8aa..24bc2d286 100644 --- a/Runtime/Character/CAdditiveBodyState.hpp +++ b/Runtime/Character/CAdditiveBodyState.hpp @@ -4,71 +4,68 @@ #include "CharacterCommon.hpp" #include "CBodyStateCmdMgr.hpp" -namespace urde -{ +namespace urde { class CBodyController; class CStateManager; class CActor; -class CAdditiveBodyState -{ +class CAdditiveBodyState { public: - virtual ~CAdditiveBodyState() = default; - virtual bool ApplyHeadTracking() const { return true; } - virtual bool CanShoot() const { return true; } - virtual void Start(CBodyController& bc, CStateManager& mgr) = 0; - virtual pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) = 0; - virtual void Shutdown(CBodyController& bc) = 0; + virtual ~CAdditiveBodyState() = default; + virtual bool ApplyHeadTracking() const { return true; } + virtual bool CanShoot() const { return true; } + virtual void Start(CBodyController& bc, CStateManager& mgr) = 0; + virtual pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) = 0; + virtual void Shutdown(CBodyController& bc) = 0; }; -class CABSAim : public CAdditiveBodyState -{ - bool x4_needsIdle = false; - s32 x8_anims[4]; - float x18_angles[4]; - float x28_hWeight = 0.f; - float x2c_hWeightVel = 0.f; - float x30_vWeight = 0.f; - float x34_vWeightVel = 0.f; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CABSAim : public CAdditiveBodyState { + bool x4_needsIdle = false; + s32 x8_anims[4]; + float x18_angles[4]; + float x28_hWeight = 0.f; + float x2c_hWeightVel = 0.f; + float x30_vWeight = 0.f; + float x34_vWeightVel = 0.f; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController& bc); + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController& bc); }; -class CABSFlinch : public CAdditiveBodyState -{ - float x4_weight = 1.f; - u32 x8_anim = 0; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CABSFlinch : public CAdditiveBodyState { + float x4_weight = 1.f; + u32 x8_anim = 0; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController& bc) {} + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController& bc) {} }; -class CABSIdle : public CAdditiveBodyState -{ - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CABSIdle : public CAdditiveBodyState { + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - void Start(CBodyController& bc, CStateManager& mgr) {} - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController& bc) {} + void Start(CBodyController& bc, CStateManager& mgr) {} + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController& bc) {} }; -class CABSReaction : public CAdditiveBodyState -{ - float x4_weight = 1.f; - s32 x8_anim = -1; - pas::EAdditiveReactionType xc_type = pas::EAdditiveReactionType::Invalid; - bool x10_active = false; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); - void StopAnimation(CBodyController& bc); +class CABSReaction : public CAdditiveBodyState { + float x4_weight = 1.f; + s32 x8_anim = -1; + pas::EAdditiveReactionType xc_type = pas::EAdditiveReactionType::Invalid; + bool x10_active = false; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + void StopAnimation(CBodyController& bc); + public: - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController& bc) { StopAnimation(bc); } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController& bc) { StopAnimation(bc); } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAllFormatsAnimSource.cpp b/Runtime/Character/CAllFormatsAnimSource.cpp index a33fb580a..bf129efa2 100644 --- a/Runtime/Character/CAllFormatsAnimSource.cpp +++ b/Runtime/Character/CAllFormatsAnimSource.cpp @@ -4,77 +4,64 @@ #include "CAnimSourceReader.hpp" #include "CFBStreamedAnimReader.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CAllFormatsAnimSource"); -void CAnimFormatUnion::SubConstruct(u8* storage, EAnimFormat fmt, - CInputStream& in, IObjectStore& store) -{ - switch (fmt) - { - case EAnimFormat::Uncompressed: - new (storage) CAnimSource(in, store); - break; - case EAnimFormat::BitstreamCompressed: - new (storage) CFBStreamedCompression(in, store, false); - break; - case EAnimFormat::BitstreamCompressed24: - new (storage) CFBStreamedCompression(in, store, true); - break; - default: - Log.report(logvisor::Fatal, "unable to read ANIM format %d", int(fmt)); - } +void CAnimFormatUnion::SubConstruct(u8* storage, EAnimFormat fmt, CInputStream& in, IObjectStore& store) { + switch (fmt) { + case EAnimFormat::Uncompressed: + new (storage) CAnimSource(in, store); + break; + case EAnimFormat::BitstreamCompressed: + new (storage) CFBStreamedCompression(in, store, false); + break; + case EAnimFormat::BitstreamCompressed24: + new (storage) CFBStreamedCompression(in, store, true); + break; + default: + Log.report(logvisor::Fatal, "unable to read ANIM format %d", int(fmt)); + } } -CAnimFormatUnion::CAnimFormatUnion(CInputStream& in, IObjectStore& store) -{ - x0_format = EAnimFormat(in.readUint32Big()); - SubConstruct(x4_storage, x0_format, in, store); +CAnimFormatUnion::CAnimFormatUnion(CInputStream& in, IObjectStore& store) { + x0_format = EAnimFormat(in.readUint32Big()); + SubConstruct(x4_storage, x0_format, in, store); } -CAnimFormatUnion::~CAnimFormatUnion() -{ - switch (x0_format) - { - case EAnimFormat::Uncompressed: - reinterpret_cast(x4_storage)->~CAnimSource(); - break; - case EAnimFormat::BitstreamCompressed: - case EAnimFormat::BitstreamCompressed24: - reinterpret_cast(x4_storage)->~CFBStreamedCompression(); - default: break; - } +CAnimFormatUnion::~CAnimFormatUnion() { + switch (x0_format) { + case EAnimFormat::Uncompressed: + reinterpret_cast(x4_storage)->~CAnimSource(); + break; + case EAnimFormat::BitstreamCompressed: + case EAnimFormat::BitstreamCompressed24: + reinterpret_cast(x4_storage)->~CFBStreamedCompression(); + default: + break; + } } -std::shared_ptr -CAllFormatsAnimSource::GetNewReader(const TLockedToken& tok, - const CCharAnimTime& startTime) -{ - switch (tok->x0_format) - { - case EAnimFormat::Uncompressed: - return std::make_shared(tok, startTime); - case EAnimFormat::BitstreamCompressed: - case EAnimFormat::BitstreamCompressed24: - return std::make_shared(tok, startTime); - default: break; - } - return {}; +std::shared_ptr CAllFormatsAnimSource::GetNewReader(const TLockedToken& tok, + const CCharAnimTime& startTime) { + switch (tok->x0_format) { + case EAnimFormat::Uncompressed: + return std::make_shared(tok, startTime); + case EAnimFormat::BitstreamCompressed: + case EAnimFormat::BitstreamCompressed24: + return std::make_shared(tok, startTime); + default: + break; + } + return {}; } -CAllFormatsAnimSource::CAllFormatsAnimSource(CInputStream& in, - IObjectStore& store, - const SObjectTag& tag) +CAllFormatsAnimSource::CAllFormatsAnimSource(CInputStream& in, IObjectStore& store, const SObjectTag& tag) : CAnimFormatUnion(in, store), x74_tag(tag) {} -CFactoryFnReturn AnimSourceFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& params, - CObjectReference* selfRef) -{ - CSimplePool* sp = params.GetOwnedObj(); - return TToken::GetIObjObjectFor( - std::make_unique(in, *sp, tag)); +CFactoryFnReturn AnimSourceFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params, + CObjectReference* selfRef) { + CSimplePool* sp = params.GetOwnedObj(); + return TToken::GetIObjObjectFor(std::make_unique(in, *sp, tag)); } -} +} // namespace urde diff --git a/Runtime/Character/CAllFormatsAnimSource.hpp b/Runtime/Character/CAllFormatsAnimSource.hpp index 8c627f31d..b7ed79913 100644 --- a/Runtime/Character/CAllFormatsAnimSource.hpp +++ b/Runtime/Character/CAllFormatsAnimSource.hpp @@ -6,50 +6,42 @@ #include "CFBStreamedCompression.hpp" #include "CFactoryMgr.hpp" -namespace urde -{ +namespace urde { class IObjectStore; class IAnimReader; -enum class EAnimFormat -{ - Uncompressed, - Unknown, - BitstreamCompressed, - BitstreamCompressed24 +enum class EAnimFormat { Uncompressed, Unknown, BitstreamCompressed, BitstreamCompressed24 }; + +class CAnimFormatUnion { + friend class CAllFormatsAnimSource; + union { + EAnimFormat x0_format; + u8 _align[16]; + }; + u8 x4_storage[std::max(sizeof(CAnimSource), sizeof(CFBStreamedCompression))]; + static void SubConstruct(u8* storage, EAnimFormat fmt, CInputStream& in, IObjectStore& store); + +public: + CAnimFormatUnion(CInputStream& in, IObjectStore& store); + ~CAnimFormatUnion(); + EAnimFormat GetFormat() const { return x0_format; } + const CAnimSource& GetAsCAnimSource() const { return *reinterpret_cast(x4_storage); } + const CFBStreamedCompression& GetAsCFBStreamedCompression() const { + return *reinterpret_cast(x4_storage); + } }; -class CAnimFormatUnion -{ - friend class CAllFormatsAnimSource; - union - { - EAnimFormat x0_format; - u8 _align[16]; - }; - u8 x4_storage[std::max(sizeof(CAnimSource), sizeof(CFBStreamedCompression))]; - static void SubConstruct(u8* storage, EAnimFormat fmt, - CInputStream& in, IObjectStore& store); -public: - CAnimFormatUnion(CInputStream& in, IObjectStore& store); - ~CAnimFormatUnion(); - EAnimFormat GetFormat() const { return x0_format; } - const CAnimSource& GetAsCAnimSource() const { return *reinterpret_cast(x4_storage); } - const CFBStreamedCompression& GetAsCFBStreamedCompression() const { return *reinterpret_cast(x4_storage); } -}; +class CAllFormatsAnimSource : public CAnimFormatUnion { + zeus::CVector3f x68_; + SObjectTag x74_tag; -class CAllFormatsAnimSource : public CAnimFormatUnion -{ - zeus::CVector3f x68_; - SObjectTag x74_tag; public: - CAllFormatsAnimSource(CInputStream& in, IObjectStore& store, const SObjectTag& tag); - static std::shared_ptr GetNewReader(const TLockedToken& tok, - const CCharAnimTime& startTime); + CAllFormatsAnimSource(CInputStream& in, IObjectStore& store, const SObjectTag& tag); + static std::shared_ptr GetNewReader(const TLockedToken& tok, + const CCharAnimTime& startTime); }; CFactoryFnReturn AnimSourceFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/Character/CAnimCharacterSet.cpp b/Runtime/Character/CAnimCharacterSet.cpp index 6866d712f..5a817cc23 100644 --- a/Runtime/Character/CAnimCharacterSet.cpp +++ b/Runtime/Character/CAnimCharacterSet.cpp @@ -1,16 +1,14 @@ #include "CAnimCharacterSet.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { CAnimCharacterSet::CAnimCharacterSet(CInputStream& in) : x0_version(in.readUint16Big()), x4_characterSet(in), x1c_animationSet(in) {} CFactoryFnReturn FAnimCharacterSet(const SObjectTag&, CInputStream& in, const CVParamTransfer&, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/Character/CAnimCharacterSet.hpp b/Runtime/Character/CAnimCharacterSet.hpp index 709382531..558ae5bd7 100644 --- a/Runtime/Character/CAnimCharacterSet.hpp +++ b/Runtime/Character/CAnimCharacterSet.hpp @@ -4,22 +4,19 @@ #include "CCharacterSet.hpp" #include "CAnimationSet.hpp" -namespace urde -{ +namespace urde { + +class CAnimCharacterSet { + u16 x0_version; + CCharacterSet x4_characterSet; + CAnimationSet x1c_animationSet; -class CAnimCharacterSet -{ - u16 x0_version; - CCharacterSet x4_characterSet; - CAnimationSet x1c_animationSet; public: - CAnimCharacterSet(CInputStream& in); - const CCharacterSet& GetCharacterSet() const {return x4_characterSet;} - const CAnimationSet& GetAnimationSet() const {return x1c_animationSet;} + CAnimCharacterSet(CInputStream& in); + const CCharacterSet& GetCharacterSet() const { return x4_characterSet; } + const CAnimationSet& GetAnimationSet() const { return x1c_animationSet; } }; -CFactoryFnReturn FAnimCharacterSet(const SObjectTag&, CInputStream&, const CVParamTransfer&, - CObjectReference* selfRef); - -} +CFactoryFnReturn FAnimCharacterSet(const SObjectTag&, CInputStream&, const CVParamTransfer&, CObjectReference* selfRef); +} // namespace urde diff --git a/Runtime/Character/CAnimData.cpp b/Runtime/Character/CAnimData.cpp index 3d6d9b38e..4faa6625b 100644 --- a/Runtime/Character/CAnimData.cpp +++ b/Runtime/Character/CAnimData.cpp @@ -22,1048 +22,868 @@ #include "CAllFormatsAnimSource.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("CAnimData"); -rstl::reserved_vectorCAnimData::g_BoolPOINodes; +rstl::reserved_vector CAnimData::g_BoolPOINodes; rstl::reserved_vector CAnimData::g_Int32POINodes; rstl::reserved_vector CAnimData::g_ParticlePOINodes; rstl::reserved_vector CAnimData::g_SoundPOINodes; rstl::reserved_vector CAnimData::g_TransientInt32POINodes; -void CAnimData::FreeCache() -{ -} +void CAnimData::FreeCache() {} -void CAnimData::InitializeCache() -{ -} +void CAnimData::InitializeCache() {} -CAnimData::CAnimData(CAssetId id, - const CCharacterInfo& character, - int defaultAnim, int charIdx, bool loop, - const TLockedToken& layout, - const TToken& model, +CAnimData::CAnimData(CAssetId id, const CCharacterInfo& character, int defaultAnim, int charIdx, bool loop, + const TLockedToken& layout, const TToken& model, const std::experimental::optional>& iceModel, - const std::weak_ptr& ctx, - const std::shared_ptr& animMgr, + const std::weak_ptr& ctx, const std::shared_ptr& animMgr, const std::shared_ptr& transMgr, - const TLockedToken& charFactory, - int drawInstCount) -: x0_charFactory(charFactory), - xc_charInfo(character), - xcc_layoutData(layout), - xd8_modelData(model), - xfc_animCtx(ctx.lock()), - x100_animMgr(animMgr), - x1d8_selfId(id), - x1fc_transMgr(transMgr), - x204_charIdx(charIdx), - x208_defaultAnim(defaultAnim), - x224_pose(layout->GetSegIdList().GetList().size()), - x2fc_poseBuilder(layout), - m_drawInstCount(drawInstCount) -{ - x220_25_loop = loop; + const TLockedToken& charFactory, int drawInstCount) +: x0_charFactory(charFactory) +, xc_charInfo(character) +, xcc_layoutData(layout) +, xd8_modelData(model) +, xfc_animCtx(ctx.lock()) +, x100_animMgr(animMgr) +, x1d8_selfId(id) +, x1fc_transMgr(transMgr) +, x204_charIdx(charIdx) +, x208_defaultAnim(defaultAnim) +, x224_pose(layout->GetSegIdList().GetList().size()) +, x2fc_poseBuilder(layout) +, m_drawInstCount(drawInstCount) { + x220_25_loop = loop; - if (iceModel) - xe4_iceModelData = *iceModel; + if (iceModel) + xe4_iceModelData = *iceModel; - g_BoolPOINodes.resize(8); - g_Int32POINodes.resize(16); - g_ParticlePOINodes.resize(20); - g_SoundPOINodes.resize(20); - g_TransientInt32POINodes.resize(16); + g_BoolPOINodes.resize(8); + g_Int32POINodes.resize(16); + g_ParticlePOINodes.resize(20); + g_SoundPOINodes.resize(20); + g_TransientInt32POINodes.resize(16); - x108_aabb = xd8_modelData->GetModel()->GetAABB(); - x120_particleDB.CacheParticleDesc(xc_charInfo.GetParticleResData()); + x108_aabb = xd8_modelData->GetModel()->GetAABB(); + x120_particleDB.CacheParticleDesc(xc_charInfo.GetParticleResData()); - CHierarchyPoseBuilder pb(xcc_layoutData); - pb.BuildNoScale(x224_pose); - x220_30_poseBuilt = true; + CHierarchyPoseBuilder pb(xcc_layoutData); + pb.BuildNoScale(x224_pose); + x220_30_poseBuilt = true; - if (defaultAnim == -1) - { - defaultAnim = 0; - Log.report(logvisor::Warning, "Character %s has invalid initial animation, so defaulting to first.", - character.GetCharacterName().data()); + if (defaultAnim == -1) { + defaultAnim = 0; + Log.report(logvisor::Warning, "Character %s has invalid initial animation, so defaulting to first.", + character.GetCharacterName().data()); + } + + std::shared_ptr treeNode = GetAnimationManager()->GetAnimationTree( + character.GetAnimationIndex(defaultAnim), CMetaAnimTreeBuildOrders::NoSpecialOrders()); + if (treeNode != x1f8_animRoot) + x1f8_animRoot = treeNode; +} + +void CAnimData::SetParticleEffectState(std::string_view effectName, bool active, CStateManager& mgr) { + auto search = std::find_if(xc_charInfo.x98_effects.begin(), xc_charInfo.x98_effects.end(), + [effectName](const auto& v) { return v.first == effectName; }); + if (search != xc_charInfo.x98_effects.end()) + for (const auto& p : search->second) + x120_particleDB.SetParticleEffectState(p.GetComponentName(), active, mgr); +} + +void CAnimData::InitializeEffects(CStateManager& mgr, TAreaId aId, const zeus::CVector3f& scale) { + for (const auto& effects : xc_charInfo.GetEffectList()) { + for (const auto& effect : effects.second) { + x120_particleDB.CacheParticleDesc(effect.GetParticleTag()); + x120_particleDB.AddParticleEffect(effect.GetSegmentName(), effect.GetFlags(), CParticleData(), scale, mgr, aId, + true, x21c_particleLightIdx); + x120_particleDB.SetParticleEffectState(effect.GetComponentName(), false, mgr); } - - std::shared_ptr treeNode = - GetAnimationManager()->GetAnimationTree(character.GetAnimationIndex(defaultAnim), - CMetaAnimTreeBuildOrders::NoSpecialOrders()); - if (treeNode != x1f8_animRoot) - x1f8_animRoot = treeNode; + } } -void CAnimData::SetParticleEffectState(std::string_view effectName, bool active, CStateManager& mgr) -{ - auto search = std::find_if(xc_charInfo.x98_effects.begin(), xc_charInfo.x98_effects.end(), - [effectName](const auto& v) { return v.first == effectName; }); - if (search != xc_charInfo.x98_effects.end()) - for (const auto& p : search->second) - x120_particleDB.SetParticleEffectState(p.GetComponentName(), active, mgr); +CAssetId CAnimData::GetEventResourceIdForAnimResourceId(CAssetId id) const { + return x0_charFactory->GetEventResourceIdForAnimResourceId(id); } -void CAnimData::InitializeEffects(CStateManager& mgr, TAreaId aId, const zeus::CVector3f& scale) -{ - for (const auto& effects : xc_charInfo.GetEffectList()) - { - for (const auto& effect : effects.second) - { - x120_particleDB.CacheParticleDesc(effect.GetParticleTag()); - x120_particleDB.AddParticleEffect(effect.GetSegmentName(), effect.GetFlags(), CParticleData(), scale, mgr, - aId, true, x21c_particleLightIdx); - x120_particleDB.SetParticleEffectState(effect.GetComponentName(), false, mgr); - } - } +void CAnimData::AddAdditiveSegData(const CSegIdList& list, CSegStatementSet& stSet) { + for (std::pair& additive : x434_additiveAnims) + if (additive.second.GetTargetWeight() > 0.00001f) + additive.second.AddToSegStatementSet(list, *xcc_layoutData.GetObj(), stSet); } -CAssetId CAnimData::GetEventResourceIdForAnimResourceId(CAssetId id) const -{ - return x0_charFactory->GetEventResourceIdForAnimResourceId(id); +SAdvancementResults CAnimData::AdvanceAdditiveAnim(std::shared_ptr& anim, const CCharAnimTime& time) { + SAdvancementResults ret = anim->VAdvanceView(time); + auto simplified = anim->Simplified(); + if (simplified) + anim = CAnimTreeNode::Cast(std::move(*simplified)); + return ret; } -void CAnimData::AddAdditiveSegData(const CSegIdList& list, CSegStatementSet& stSet) -{ - for (std::pair& additive : x434_additiveAnims) - if (additive.second.GetTargetWeight() > 0.00001f) - additive.second.AddToSegStatementSet(list, *xcc_layoutData.GetObj(), stSet); -} +SAdvancementDeltas CAnimData::AdvanceAdditiveAnims(float dt) { + CCharAnimTime time(dt); -SAdvancementResults CAnimData::AdvanceAdditiveAnim(std::shared_ptr& anim, const CCharAnimTime& time) -{ - SAdvancementResults ret = anim->VAdvanceView(time); - auto simplified = anim->Simplified(); - if (simplified) - anim = CAnimTreeNode::Cast(std::move(*simplified)); - return ret; -} + SAdvancementDeltas deltas = {}; -SAdvancementDeltas CAnimData::AdvanceAdditiveAnims(float dt) -{ - CCharAnimTime time(dt); + for (std::pair& additive : x434_additiveAnims) { + std::shared_ptr& anim = additive.second.GetAnim(); + if (additive.second.IsActive()) { + while (time.GreaterThanZero() && std::fabs(time.GetSeconds()) >= 0.00001f) { + x210_passedIntCount += anim->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); + x20c_passedBoolCount += anim->GetBoolPOIList(time, g_BoolPOINodes.data(), 8, x20c_passedBoolCount, 0); + x214_passedParticleCount += + anim->GetParticlePOIList(time, g_ParticlePOINodes.data(), 8, x214_passedParticleCount, 0); + x218_passedSoundCount += anim->GetSoundPOIList(time, g_SoundPOINodes.data(), 8, x218_passedSoundCount, 0); - SAdvancementDeltas deltas = {}; + SAdvancementResults results = AdvanceAdditiveAnim(anim, time); + deltas.x0_posDelta += results.x8_deltas.x0_posDelta; + deltas.xc_rotDelta *= results.x8_deltas.xc_rotDelta; + time = results.x0_remTime; + } + } else { + CCharAnimTime remTime = anim->VGetTimeRemaining(); + while (remTime.GreaterThanZero() && std::fabs(remTime.GetSeconds()) >= 0.00001f) { + x210_passedIntCount += anim->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); + x20c_passedBoolCount += anim->GetBoolPOIList(time, g_BoolPOINodes.data(), 8, x20c_passedBoolCount, 0); + x214_passedParticleCount += + anim->GetParticlePOIList(time, g_ParticlePOINodes.data(), 8, x214_passedParticleCount, 0); + x218_passedSoundCount += anim->GetSoundPOIList(time, g_SoundPOINodes.data(), 8, x218_passedSoundCount, 0); - for (std::pair& additive : x434_additiveAnims) - { - std::shared_ptr& anim = additive.second.GetAnim(); - if (additive.second.IsActive()) - { - while (time.GreaterThanZero() && std::fabs(time.GetSeconds()) >= 0.00001f) - { - x210_passedIntCount += anim->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); - x20c_passedBoolCount += anim->GetBoolPOIList(time, g_BoolPOINodes.data(), 8, x20c_passedBoolCount, 0); - x214_passedParticleCount += anim->GetParticlePOIList(time, g_ParticlePOINodes.data(), 8, x214_passedParticleCount, 0); - x218_passedSoundCount += anim->GetSoundPOIList(time, g_SoundPOINodes.data(), 8, x218_passedSoundCount, 0); - - SAdvancementResults results = AdvanceAdditiveAnim(anim, time); - deltas.x0_posDelta += results.x8_deltas.x0_posDelta; - deltas.xc_rotDelta *= results.x8_deltas.xc_rotDelta; - time = results.x0_remTime; - } - } + SAdvancementResults results = AdvanceAdditiveAnim(anim, time); + deltas.x0_posDelta += results.x8_deltas.x0_posDelta; + deltas.xc_rotDelta *= results.x8_deltas.xc_rotDelta; + CCharAnimTime tmpTime = anim->VGetTimeRemaining(); + if (tmpTime < results.x0_remTime) + remTime = tmpTime; else - { - CCharAnimTime remTime = anim->VGetTimeRemaining(); - while (remTime.GreaterThanZero() && std::fabs(remTime.GetSeconds()) >= 0.00001f) - { - x210_passedIntCount += anim->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); - x20c_passedBoolCount += anim->GetBoolPOIList(time, g_BoolPOINodes.data(), 8, x20c_passedBoolCount, 0); - x214_passedParticleCount += anim->GetParticlePOIList(time, g_ParticlePOINodes.data(), 8, x214_passedParticleCount, 0); - x218_passedSoundCount += anim->GetSoundPOIList(time, g_SoundPOINodes.data(), 8, x218_passedSoundCount, 0); - - SAdvancementResults results = AdvanceAdditiveAnim(anim, time); - deltas.x0_posDelta += results.x8_deltas.x0_posDelta; - deltas.xc_rotDelta *= results.x8_deltas.xc_rotDelta; - CCharAnimTime tmpTime = anim->VGetTimeRemaining(); - if (tmpTime < results.x0_remTime) - remTime = tmpTime; - else - remTime = results.x0_remTime; - } - } + remTime = results.x0_remTime; + } } + } - return deltas; + return deltas; } -SAdvancementDeltas CAnimData::UpdateAdditiveAnims(float dt) -{ - for (auto it = x434_additiveAnims.begin() ; it != x434_additiveAnims.end() ;) - { - it->second.Update(dt); - CCharAnimTime timeRem = it->second.GetAnim()->VGetTimeRemaining(); - if (timeRem.EpsilonZero() && it->second.NeedsFadeOut()) - it->second.FadeOut(); - if (it->second.GetPhase() == EAdditivePlaybackPhase::FadedOut) - { - it = x434_additiveAnims.erase(it); - continue; - } - ++it; +SAdvancementDeltas CAnimData::UpdateAdditiveAnims(float dt) { + for (auto it = x434_additiveAnims.begin(); it != x434_additiveAnims.end();) { + it->second.Update(dt); + CCharAnimTime timeRem = it->second.GetAnim()->VGetTimeRemaining(); + if (timeRem.EpsilonZero() && it->second.NeedsFadeOut()) + it->second.FadeOut(); + if (it->second.GetPhase() == EAdditivePlaybackPhase::FadedOut) { + it = x434_additiveAnims.erase(it); + continue; } + ++it; + } - return AdvanceAdditiveAnims(dt); + return AdvanceAdditiveAnims(dt); } -bool CAnimData::IsAdditiveAnimation(u32 idx) const -{ - u32 animIdx = xc_charInfo.GetAnimationIndex(idx); - return x0_charFactory->HasAdditiveInfo(animIdx); +bool CAnimData::IsAdditiveAnimation(u32 idx) const { + u32 animIdx = xc_charInfo.GetAnimationIndex(idx); + return x0_charFactory->HasAdditiveInfo(animIdx); } -bool CAnimData::IsAdditiveAnimationAdded(u32 idx) const -{ - auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), - [&](const std::pair& pair) -> bool { - return pair.first == idx; - }); - if (search == x434_additiveAnims.cend()) - return false; - return true; +bool CAnimData::IsAdditiveAnimationAdded(u32 idx) const { + auto search = + std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), + [&](const std::pair& pair) -> bool { return pair.first == idx; }); + if (search == x434_additiveAnims.cend()) + return false; + return true; } -const std::shared_ptr& CAnimData::GetAdditiveAnimationTree(u32 idx) const -{ - auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), - [&](const std::pair& pair) -> bool { - return pair.first == idx; - }); - return search->second.GetAnim(); +const std::shared_ptr& CAnimData::GetAdditiveAnimationTree(u32 idx) const { + auto search = + std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), + [&](const std::pair& pair) -> bool { return pair.first == idx; }); + return search->second.GetAnim(); } -bool CAnimData::IsAdditiveAnimationActive(u32 idx) const -{ - auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), - [&](const std::pair& pair) -> bool { - return pair.first == idx; - }); - if (search == x434_additiveAnims.cend()) - return false; - return search->second.IsActive(); +bool CAnimData::IsAdditiveAnimationActive(u32 idx) const { + auto search = + std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(), + [&](const std::pair& pair) -> bool { return pair.first == idx; }); + if (search == x434_additiveAnims.cend()) + return false; + return search->second.IsActive(); } -void CAnimData::DelAdditiveAnimation(s32 idx) -{ - u32 animIdx = xc_charInfo.GetAnimationIndex(idx); - for (std::pair& anim : x434_additiveAnims) - { - if (anim.first == animIdx && - anim.second.GetPhase() != EAdditivePlaybackPhase::FadingOut && - anim.second.GetPhase() != EAdditivePlaybackPhase::FadedOut) - { - anim.second.FadeOut(); - return; - } +void CAnimData::DelAdditiveAnimation(s32 idx) { + u32 animIdx = xc_charInfo.GetAnimationIndex(idx); + for (std::pair& anim : x434_additiveAnims) { + if (anim.first == animIdx && anim.second.GetPhase() != EAdditivePlaybackPhase::FadingOut && + anim.second.GetPhase() != EAdditivePlaybackPhase::FadedOut) { + anim.second.FadeOut(); + return; } + } } -void CAnimData::AddAdditiveAnimation(s32 idx, float weight, bool active, bool fadeOut) -{ - u32 animIdx = xc_charInfo.GetAnimationIndex(idx); - for (std::pair& anim : x434_additiveAnims) - { - if (anim.first == animIdx && - anim.second.GetPhase() != EAdditivePlaybackPhase::FadingOut && - anim.second.GetPhase() != EAdditivePlaybackPhase::FadedOut) - { - anim.second.SetActive(active); - anim.second.SetWeight(weight); - anim.second.SetNeedsFadeOut(!anim.second.IsActive() && fadeOut); - return; - } +void CAnimData::AddAdditiveAnimation(s32 idx, float weight, bool active, bool fadeOut) { + u32 animIdx = xc_charInfo.GetAnimationIndex(idx); + for (std::pair& anim : x434_additiveAnims) { + if (anim.first == animIdx && anim.second.GetPhase() != EAdditivePlaybackPhase::FadingOut && + anim.second.GetPhase() != EAdditivePlaybackPhase::FadedOut) { + anim.second.SetActive(active); + anim.second.SetWeight(weight); + anim.second.SetNeedsFadeOut(!anim.second.IsActive() && fadeOut); + return; } + } - std::shared_ptr node = - GetAnimationManager()->GetAnimationTree(animIdx, CMetaAnimTreeBuildOrders::NoSpecialOrders()); + std::shared_ptr node = + GetAnimationManager()->GetAnimationTree(animIdx, CMetaAnimTreeBuildOrders::NoSpecialOrders()); - const CAdditiveAnimationInfo& info = x0_charFactory->FindAdditiveInfo(animIdx); - x434_additiveAnims.emplace_back(std::make_pair(idx, CAdditiveAnimPlayback(node, weight, active, info, fadeOut))); + const CAdditiveAnimationInfo& info = x0_charFactory->FindAdditiveInfo(animIdx); + x434_additiveAnims.emplace_back(std::make_pair(idx, CAdditiveAnimPlayback(node, weight, active, info, fadeOut))); } -float CAnimData::GetAdditiveAnimationWeight(u32 idx) const -{ - u32 animIdx = xc_charInfo.GetAnimationIndex(idx); - for (const std::pair& anim : x434_additiveAnims) - { - if (anim.first == animIdx) - return anim.second.GetTargetWeight(); +float CAnimData::GetAdditiveAnimationWeight(u32 idx) const { + u32 animIdx = xc_charInfo.GetAnimationIndex(idx); + for (const std::pair& anim : x434_additiveAnims) { + if (anim.first == animIdx) + return anim.second.GetTargetWeight(); + } + return 0.f; +} + +std::shared_ptr CAnimData::GetAnimationManager() { return x100_animMgr; } + +void CAnimData::SetPhase(float ph) { x1f8_animRoot->VSetPhase(ph); } + +void CAnimData::Touch(const CSkinnedModel& model, int shadIdx) const { + const_cast(*model.GetModelInst()).Touch(shadIdx); +} + +SAdvancementDeltas CAnimData::GetAdvancementDeltas(const CCharAnimTime& a, const CCharAnimTime& b) const { + return x1f8_animRoot->VGetAdvancementResults(a, b).x8_deltas; +} + +CCharAnimTime CAnimData::GetTimeOfUserEvent(EUserEventType type, const CCharAnimTime& time) const { + u32 count = x1f8_animRoot->GetInt32POIList(time, g_TransientInt32POINodes.data(), 16, 0, 64); + for (int i = 0; i < count; ++i) { + CInt32POINode& poi = g_TransientInt32POINodes[i]; + if (poi.GetPoiType() == EPOIType::UserEvent && EUserEventType(poi.GetValue()) == type) { + for (; i < count; ++i) + g_TransientInt32POINodes[i] = CInt32POINode(); + return poi.GetTime(); + } else { + poi = CInt32POINode(); } - return 0.f; + } + return CCharAnimTime::Infinity(); } -std::shared_ptr CAnimData::GetAnimationManager() -{ - return x100_animMgr; -} +void CAnimData::MultiplyPlaybackRate(float mul) { x200_speedScale *= mul; } -void CAnimData::SetPhase(float ph) -{ - x1f8_animRoot->VSetPhase(ph); -} +void CAnimData::SetPlaybackRate(float set) { x200_speedScale = set; } -void CAnimData::Touch(const CSkinnedModel& model, int shadIdx) const -{ - const_cast(*model.GetModelInst()).Touch(shadIdx); -} - -SAdvancementDeltas CAnimData::GetAdvancementDeltas(const CCharAnimTime& a, - const CCharAnimTime& b) const -{ - return x1f8_animRoot->VGetAdvancementResults(a, b).x8_deltas; -} - -CCharAnimTime CAnimData::GetTimeOfUserEvent(EUserEventType type, const CCharAnimTime& time) const -{ - u32 count = x1f8_animRoot->GetInt32POIList(time, g_TransientInt32POINodes.data(), 16, 0, 64); - for (int i=0 ; i& node) -{ - zeus::CQuaternion orient; - x1e8_alignRot = zeus::CQuaternion::skNoRotation; + const std::shared_ptr& node) { + zeus::CQuaternion orient; + x1e8_alignRot = zeus::CQuaternion::skNoRotation; - x220_27_ = false; - if (parms.GetDeltaOrient() && parms.GetObjectXform()) - { - ResetPOILists(); - x210_passedIntCount += node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), - 16, x210_passedIntCount, 64); - for (int i=0 ; iVGetAdvancementResults(poi.GetTime(), 0.f); - orient = zeus::CQuaternion::slerp(zeus::CQuaternion::skNoRotation, - *parms.GetDeltaOrient() * - zeus::CQuaternion(parms.GetObjectXform()->buildMatrix3f().inverted()) * - res.x8_deltas.xc_rotDelta.inverse(), - 1.f / (60.f * poi.GetTime().GetSeconds())); - x1e8_alignRot = orient; - x220_27_ = true; - } + x220_27_ = false; + if (parms.GetDeltaOrient() && parms.GetObjectXform()) { + ResetPOILists(); + x210_passedIntCount += + node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), 16, x210_passedIntCount, 64); + for (int i = 0; i < x210_passedIntCount; ++i) { + CInt32POINode& poi = g_Int32POINodes[i]; + if (poi.GetPoiType() == EPOIType::UserEvent && EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetRot) { + SAdvancementResults res = node->VGetAdvancementResults(poi.GetTime(), 0.f); + orient = zeus::CQuaternion::slerp(zeus::CQuaternion::skNoRotation, + *parms.GetDeltaOrient() * + zeus::CQuaternion(parms.GetObjectXform()->buildMatrix3f().inverted()) * + res.x8_deltas.xc_rotDelta.inverse(), + 1.f / (60.f * poi.GetTime().GetSeconds())); + x1e8_alignRot = orient; + x220_27_ = true; + } + } + } + + if (!x220_27_) { + bool didAlign = false; + bool didStart = false; + zeus::CVector3f posStart, posAlign; + CCharAnimTime timeStart, timeAlign; + if (parms.GetTargetPos() && parms.GetObjectXform()) { + ResetPOILists(); + x210_passedIntCount += + node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), 16, x210_passedIntCount, 64); + for (int i = 0; i < x210_passedIntCount; ++i) { + CInt32POINode& poi = g_Int32POINodes[i]; + if (poi.GetPoiType() == EPOIType::UserEvent) { + if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPosStart) { + didStart = true; + SAdvancementResults res = node->VGetAdvancementResults(poi.GetTime(), 0.f); + posStart = res.x8_deltas.x0_posDelta; + timeStart = poi.GetTime(); + + if (parms.GetIsUseLocator()) + posStart += GetLocatorTransform(poi.GetLocatorName(), &poi.GetTime()).origin; + + if (didAlign) + break; + } else if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPos) { + didAlign = true; + SAdvancementResults res = node->VGetAdvancementResults(poi.GetTime(), 0.f); + posAlign = res.x8_deltas.x0_posDelta; + timeAlign = poi.GetTime(); + + if (parms.GetIsUseLocator()) + posAlign += GetLocatorTransform(poi.GetLocatorName(), &poi.GetTime()).origin; + + if (didStart) + break; + } } + } + + if (didAlign && didStart) { + zeus::CVector3f scaleStart = *parms.GetObjectScale() * posStart; + zeus::CVector3f scaleAlign = *parms.GetObjectScale() * posAlign; + x1dc_alignPos = + (parms.GetObjectXform()->inverse() * *parms.GetTargetPos() - scaleStart - (scaleAlign - scaleStart)) / + *parms.GetObjectScale() * (1.f / (timeAlign.GetSeconds() - timeStart.GetSeconds())); + x220_28_ = true; + x220_26_aligningPos = false; + } else { + x1dc_alignPos = zeus::CVector3f::skZero; + x220_28_ = false; + x220_26_aligningPos = false; + } + } + } else { + bool didStart = false; + bool didAlign = false; + CCharAnimTime timeStart, timeAlign; + zeus::CVector3f startPos; + if (parms.GetTargetPos() && parms.GetObjectXform()) { + ResetPOILists(); + x210_passedIntCount += + node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), 16, x210_passedIntCount, 64); + for (int i = 0; i < x210_passedIntCount; ++i) { + CInt32POINode& poi = g_Int32POINodes[i]; + if (poi.GetPoiType() == EPOIType::UserEvent) { + if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPosStart) { + didStart = true; + timeStart = poi.GetTime(); + if (didAlign) + break; + } else if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPos) { + didAlign = true; + timeAlign = poi.GetTime(); + if (didStart) + break; + } + } + } + + if (didAlign && didStart) { + CCharAnimTime frameInterval(1.f / 60.f); + orient = zeus::CQuaternion::skNoRotation; + x1e8_alignRot = zeus::CQuaternion::skNoRotation; + x220_27_ = true; + CCharAnimTime time; + zeus::CVector3f pos; + zeus::CQuaternion quat; + bool foundStartPos = false; + while (time < timeAlign) { + SAdvancementResults res = node->VGetAdvancementResults(frameInterval, time); + pos += quat.toTransform() * res.x8_deltas.x0_posDelta; + quat *= (res.x8_deltas.xc_rotDelta * orient); + if (!foundStartPos && time >= timeStart) { + startPos = pos; + foundStartPos = true; + } + time += frameInterval; + } + zeus::CVector3f scaleStart = startPos * *parms.GetObjectScale(); + zeus::CVector3f scaleAlign = pos * *parms.GetObjectScale(); + x1dc_alignPos = + (parms.GetObjectXform()->inverse() * *parms.GetTargetPos() - scaleStart - (scaleAlign - scaleStart)) / + *parms.GetObjectScale() * (1.f / (timeAlign.GetSeconds() - timeStart.GetSeconds())); + x220_28_ = true; + x220_26_aligningPos = false; + } else { + x1dc_alignPos = zeus::CVector3f::skZero; + x220_28_ = false; + x220_26_aligningPos = false; + } + } else { + x1dc_alignPos = zeus::CVector3f::skZero; + x220_28_ = false; + x220_26_aligningPos = false; + } + } +} + +zeus::CTransform CAnimData::GetLocatorTransform(CSegId id, const CCharAnimTime* time) const { + if (id == 0xFF) + return {}; + + zeus::CTransform ret; + if (time || !x220_31_poseCached) { + const_cast(this)->RecalcPoseBuilder(time); + const_cast(this)->x220_31_poseCached = time == nullptr; + } + + if (!x220_30_poseBuilt) + x2fc_poseBuilder.BuildTransform(id, ret); + else { + ret.setRotation(x224_pose.GetTransformMinusOffset(id)); + ret.origin = x224_pose.GetOffset(id); + } + return ret; +} + +zeus::CTransform CAnimData::GetLocatorTransform(std::string_view name, const CCharAnimTime* time) const { + return GetLocatorTransform(xcc_layoutData->GetSegIdFromString(name), time); +} + +bool CAnimData::IsAnimTimeRemaining(float rem, std::string_view name) const { + if (!x1f8_animRoot) + return false; + return x1f8_animRoot->VGetTimeRemaining().GetSeconds() >= rem; +} + +float CAnimData::GetAnimTimeRemaining(std::string_view name) const { + float rem = x1f8_animRoot->VGetTimeRemaining().GetSeconds(); + if (x200_speedScale) + return rem / x200_speedScale; + return rem; +} + +float CAnimData::GetAnimationDuration(int animIn) const { + std::shared_ptr anim = x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(animIn)); + std::set prims; + anim->GetUniquePrimitives(prims); + + SObjectTag tag{FOURCC('ANIM'), 0}; + float durAccum = 0.f; + for (const CPrimitive& prim : prims) { + tag.id = prim.GetAnimResId(); + TLockedToken animRes = xfc_animCtx->xc_store.GetObj(tag); + + CCharAnimTime dur; + switch (animRes->GetFormat()) { + case EAnimFormat::Uncompressed: + default: { + const CAnimSource& src = animRes->GetAsCAnimSource(); + dur = src.GetDuration(); + break; + } + case EAnimFormat::BitstreamCompressed: + case EAnimFormat::BitstreamCompressed24: { + const CFBStreamedCompression& src = animRes->GetAsCFBStreamedCompression(); + dur = src.GetAnimationDuration(); + break; + } } - if (!x220_27_) - { - bool didAlign = false; - bool didStart = false; - zeus::CVector3f posStart, posAlign; - CCharAnimTime timeStart, timeAlign; - if (parms.GetTargetPos() && parms.GetObjectXform()) - { - ResetPOILists(); - x210_passedIntCount += node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), - 16, x210_passedIntCount, 64); - for (int i=0 ; iVGetAdvancementResults(poi.GetTime(), 0.f); - posStart = res.x8_deltas.x0_posDelta; - timeStart = poi.GetTime(); + durAccum += dur.GetSeconds(); + } - if (parms.GetIsUseLocator()) - posStart += GetLocatorTransform(poi.GetLocatorName(), &poi.GetTime()).origin; + if (anim->GetType() == EMetaAnimType::Random) + return durAccum / float(prims.size()); + return durAccum; +} - if (didAlign) - break; - } - else if (EUserEventType(poi.GetValue()) == EUserEventType::AlignTargetPos) - { - didAlign = true; - SAdvancementResults res = node->VGetAdvancementResults(poi.GetTime(), 0.f); - posAlign = res.x8_deltas.x0_posDelta; - timeAlign = poi.GetTime(); +std::shared_ptr CAnimData::GetAnimSysContext() const { return xfc_animCtx; } - if (parms.GetIsUseLocator()) - posAlign += GetLocatorTransform(poi.GetLocatorName(), &poi.GetTime()).origin; +std::shared_ptr CAnimData::GetAnimationManager() const { return x100_animMgr; } - if (didStart) - break; - } - } - } +void CAnimData::RecalcPoseBuilder(const CCharAnimTime* time) { + if (!x1f8_animRoot) + return; - if (didAlign && didStart) - { - zeus::CVector3f scaleStart = *parms.GetObjectScale() * posStart; - zeus::CVector3f scaleAlign = *parms.GetObjectScale() * posAlign; - x1dc_alignPos = (parms.GetObjectXform()->inverse() * *parms.GetTargetPos() - scaleStart - - (scaleAlign - scaleStart)) / *parms.GetObjectScale() * - (1.f / (timeAlign.GetSeconds() - timeStart.GetSeconds())); - x220_28_ = true; - x220_26_aligningPos = false; - } - else - { - x1dc_alignPos = zeus::CVector3f::skZero; - x220_28_ = false; - x220_26_aligningPos = false; - } - } - } + const CSegIdList& segIdList = GetCharLayoutInfo().GetSegIdList(); + CSegStatementSet segSet; + if (time) + x1f8_animRoot->VGetSegStatementSet(segIdList, segSet, *time); + else + x1f8_animRoot->VGetSegStatementSet(segIdList, segSet); + + AddAdditiveSegData(segIdList, segSet); + + for (const CSegId& id : segIdList.GetList()) { + if (id == 3) + continue; + CAnimPerSegmentData& segData = segSet[id]; + if (segData.x1c_hasOffset) + x2fc_poseBuilder.Insert(id, segData.x0_rotation, segData.x10_offset); else - { - bool didStart = false; - bool didAlign = false; - CCharAnimTime timeStart, timeAlign; - zeus::CVector3f startPos; - if (parms.GetTargetPos() && parms.GetObjectXform()) - { - ResetPOILists(); - x210_passedIntCount += node->GetInt32POIList(CCharAnimTime::Infinity(), g_Int32POINodes.data(), - 16, x210_passedIntCount, 64); - for (int i=0 ; iVGetAdvancementResults(frameInterval, time); - pos += quat.toTransform() * res.x8_deltas.x0_posDelta; - quat *= (res.x8_deltas.xc_rotDelta * orient); - if (!foundStartPos && time >= timeStart) - { - startPos = pos; - foundStartPos = true; - } - time += frameInterval; - } - zeus::CVector3f scaleStart = startPos * *parms.GetObjectScale(); - zeus::CVector3f scaleAlign = pos * *parms.GetObjectScale(); - x1dc_alignPos = (parms.GetObjectXform()->inverse() * *parms.GetTargetPos() - scaleStart - - (scaleAlign - scaleStart)) / *parms.GetObjectScale() * - (1.f / (timeAlign.GetSeconds() - timeStart.GetSeconds())); - x220_28_ = true; - x220_26_aligningPos = false; - } - else - { - x1dc_alignPos = zeus::CVector3f::skZero; - x220_28_ = false; - x220_26_aligningPos = false; - } - } - else - { - x1dc_alignPos = zeus::CVector3f::skZero; - x220_28_ = false; - x220_26_aligningPos = false; - } - } + x2fc_poseBuilder.Insert(id, segData.x0_rotation); + } } -zeus::CTransform CAnimData::GetLocatorTransform(CSegId id, const CCharAnimTime* time) const -{ - if (id == 0xFF) - return {}; - - zeus::CTransform ret; - if (time || !x220_31_poseCached) - { - const_cast(this)->RecalcPoseBuilder(time); - const_cast(this)->x220_31_poseCached = time == nullptr; - } - - if (!x220_30_poseBuilt) - x2fc_poseBuilder.BuildTransform(id, ret); - else - { - ret.setRotation(x224_pose.GetTransformMinusOffset(id)); - ret.origin = x224_pose.GetOffset(id); - } - return ret; -} - -zeus::CTransform CAnimData::GetLocatorTransform(std::string_view name, const CCharAnimTime* time) const -{ - return GetLocatorTransform(xcc_layoutData->GetSegIdFromString(name), time); -} - -bool CAnimData::IsAnimTimeRemaining(float rem, std::string_view name) const -{ - if (!x1f8_animRoot) - return false; - return x1f8_animRoot->VGetTimeRemaining().GetSeconds() >= rem; -} - -float CAnimData::GetAnimTimeRemaining(std::string_view name) const -{ - float rem = x1f8_animRoot->VGetTimeRemaining().GetSeconds(); - if (x200_speedScale) - return rem / x200_speedScale; - return rem; -} - -float CAnimData::GetAnimationDuration(int animIn) const -{ - std::shared_ptr anim = x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(animIn)); - std::set prims; - anim->GetUniquePrimitives(prims); - - SObjectTag tag{FOURCC('ANIM'), 0}; - float durAccum = 0.f; - for (const CPrimitive& prim : prims) - { - tag.id = prim.GetAnimResId(); - TLockedToken animRes = xfc_animCtx->xc_store.GetObj(tag); - - CCharAnimTime dur; - switch (animRes->GetFormat()) - { - case EAnimFormat::Uncompressed: - default: - { - const CAnimSource& src = animRes->GetAsCAnimSource(); - dur = src.GetDuration(); - break; - } - case EAnimFormat::BitstreamCompressed: - case EAnimFormat::BitstreamCompressed24: - { - const CFBStreamedCompression& src = animRes->GetAsCFBStreamedCompression(); - dur = src.GetAnimationDuration(); - break; - } - } - - durAccum += dur.GetSeconds(); - } - - if (anim->GetType() == EMetaAnimType::Random) - return durAccum / float(prims.size()); - return durAccum; -} - -std::shared_ptr CAnimData::GetAnimSysContext() const -{ - return xfc_animCtx; -} - -std::shared_ptr CAnimData::GetAnimationManager() const -{ - return x100_animMgr; -} - -void CAnimData::RecalcPoseBuilder(const CCharAnimTime* time) -{ - if (!x1f8_animRoot) - return; - - const CSegIdList& segIdList = GetCharLayoutInfo().GetSegIdList(); - CSegStatementSet segSet; - if (time) - x1f8_animRoot->VGetSegStatementSet(segIdList, segSet, *time); - else - x1f8_animRoot->VGetSegStatementSet(segIdList, segSet); - - AddAdditiveSegData(segIdList, segSet); - - for (const CSegId& id : segIdList.GetList()) - { - if (id == 3) - continue; - CAnimPerSegmentData& segData = segSet[id]; - if (segData.x1c_hasOffset) - x2fc_poseBuilder.Insert(id, segData.x0_rotation, segData.x10_offset); - else - x2fc_poseBuilder.Insert(id, segData.x0_rotation); - } -} - -void CAnimData::RenderAuxiliary(const zeus::CFrustum& frustum) const -{ - x120_particleDB.AddToRendererClipped(frustum); -} +void CAnimData::RenderAuxiliary(const zeus::CFrustum& frustum) const { x120_particleDB.AddToRendererClipped(frustum); } void CAnimData::Render(CSkinnedModel& model, const CModelFlags& drawFlags, const std::experimental::optional& morphEffect, - const float* morphMagnitudes) -{ - SetupRender(model, drawFlags, morphEffect, morphMagnitudes); - DrawSkinnedModel(model, drawFlags); + const float* morphMagnitudes) { + SetupRender(model, drawFlags, morphEffect, morphMagnitudes); + DrawSkinnedModel(model, drawFlags); } -void CAnimData::SetupRender(CSkinnedModel& model, - const CModelFlags& drawFlags, +void CAnimData::SetupRender(CSkinnedModel& model, const CModelFlags& drawFlags, const std::experimental::optional& morphEffect, - const float* morphMagnitudes) -{ - if (!x220_30_poseBuilt) - { - x2fc_poseBuilder.BuildNoScale(x224_pose); - x220_30_poseBuilt = true; - } - PoseSkinnedModel(model, x224_pose, drawFlags, morphEffect, morphMagnitudes); + const float* morphMagnitudes) { + if (!x220_30_poseBuilt) { + x2fc_poseBuilder.BuildNoScale(x224_pose); + x220_30_poseBuilt = true; + } + PoseSkinnedModel(model, x224_pose, drawFlags, morphEffect, morphMagnitudes); } -void CAnimData::DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags) -{ - model.Draw(flags); +void CAnimData::DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags) { model.Draw(flags); } + +void CAnimData::PreRender() { + if (!x220_31_poseCached) { + RecalcPoseBuilder(nullptr); + x220_31_poseCached = true; + x220_30_poseBuilt = false; + } } -void CAnimData::PreRender() -{ - if (!x220_31_poseCached) - { - RecalcPoseBuilder(nullptr); - x220_31_poseCached = true; - x220_30_poseBuilt = false; - } +void CAnimData::BuildPose() { + if (!x220_31_poseCached) { + RecalcPoseBuilder(nullptr); + x220_31_poseCached = true; + x220_30_poseBuilt = false; + } + + if (!x220_30_poseBuilt) { + x2fc_poseBuilder.BuildNoScale(x224_pose); + x220_30_poseBuilt = true; + } } -void CAnimData::BuildPose() -{ - if (!x220_31_poseCached) - { - RecalcPoseBuilder(nullptr); - x220_31_poseCached = true; - x220_30_poseBuilt = false; - } +void CAnimData::PrimitiveSetToTokenVector(const std::set& primSet, std::vector& tokensOut, + bool preLock) { + tokensOut.reserve(primSet.size()); - if (!x220_30_poseBuilt) - { - x2fc_poseBuilder.BuildNoScale(x224_pose); - x220_30_poseBuilt = true; - } + SObjectTag tag{FOURCC('ANIM'), 0}; + for (const CPrimitive& prim : primSet) { + tag.id = prim.GetAnimResId(); + tokensOut.push_back(g_SimplePool->GetObj(tag)); + if (preLock) + tokensOut.back().Lock(); + } } -void CAnimData::PrimitiveSetToTokenVector(const std::set& primSet, - std::vector& tokensOut, bool preLock) -{ - tokensOut.reserve(primSet.size()); +void CAnimData::GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set& primsOut) const { + std::shared_ptr animA = + x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(parms.GetAnimationId())); + animA->GetUniquePrimitives(primsOut); - SObjectTag tag{FOURCC('ANIM'), 0}; - for (const CPrimitive& prim : primSet) - { - tag.id = prim.GetAnimResId(); - tokensOut.push_back(g_SimplePool->GetObj(tag)); - if (preLock) - tokensOut.back().Lock(); - } + if (parms.GetSecondAnimationId() != -1) { + std::shared_ptr animB = + x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(parms.GetSecondAnimationId())); + animB->GetUniquePrimitives(primsOut); + } } -void CAnimData::GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set& primsOut) const -{ - std::shared_ptr animA = - x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(parms.GetAnimationId())); - animA->GetUniquePrimitives(primsOut); - - if (parms.GetSecondAnimationId() != -1) - { - std::shared_ptr animB = - x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(parms.GetSecondAnimationId())); - animB->GetUniquePrimitives(primsOut); - } -} - -void CAnimData::SetAnimation(const CAnimPlaybackParms& parms, bool noTrans) -{ - if (parms.GetAnimationId() == x40c_playbackParms.GetAnimationId() || - (parms.GetSecondAnimationId() == x40c_playbackParms.GetSecondAnimationId() && - parms.GetSecondAnimationId() != -1) || - (parms.GetBlendFactor() == x40c_playbackParms.GetBlendFactor() && - parms.GetBlendFactor() != 1.f)) - { - if (x220_29_animationJustStarted) - return; - } - - x40c_playbackParms.SetAnimationId(parms.GetAnimationId()); - x40c_playbackParms.SetSecondAnimationId(parms.GetSecondAnimationId()); - x40c_playbackParms.SetBlendFactor(parms.GetBlendFactor()); - x200_speedScale = 1.f; - x208_defaultAnim = parms.GetAnimationId(); - - u32 animIdxA = xc_charInfo.GetAnimationIndex(parms.GetAnimationId()); - - ResetPOILists(); - - std::shared_ptr blendNode; - if (parms.GetSecondAnimationId() != -1) - { - u32 animIdxB = xc_charInfo.GetAnimationIndex(parms.GetSecondAnimationId()); - - std::shared_ptr treeA = - x100_animMgr->GetAnimationTree(animIdxA, CMetaAnimTreeBuildOrders::NoSpecialOrders()); - std::shared_ptr treeB = - x100_animMgr->GetAnimationTree(animIdxB, CMetaAnimTreeBuildOrders::NoSpecialOrders()); - - blendNode = std::make_shared(false, treeA, treeB, parms.GetBlendFactor(), - CAnimTreeBlend::CreatePrimitiveName(treeA, treeB, - parms.GetBlendFactor())); - } - else - { - blendNode = x100_animMgr->GetAnimationTree(animIdxA, CMetaAnimTreeBuildOrders::NoSpecialOrders()); - } - - if (!noTrans && x1f8_animRoot) - x1f8_animRoot = x1fc_transMgr->GetTransitionTree(x1f8_animRoot, blendNode); - else - x1f8_animRoot = blendNode; - - x220_24_animating = parms.GetIsPlayAnimation(); - CalcPlaybackAlignmentParms(parms, blendNode); - ResetPOILists(); - x220_29_animationJustStarted = true; -} - -SAdvancementDeltas CAnimData::DoAdvance(float dt, bool& suspendParticles, CRandom16& random, bool advTree) -{ - suspendParticles = false; - - zeus::CVector3f offsetPre, offsetPost; - zeus::CQuaternion quatPre, quatPost; - - ResetPOILists(); - float scaleDt = dt * x200_speedScale; - if (x2fc_poseBuilder.HasRoot()) - { - SAdvancementDeltas deltas = UpdateAdditiveAnims(scaleDt); - offsetPre = deltas.x0_posDelta; - quatPre = deltas.xc_rotDelta; - } - - if (!x220_24_animating) - { - suspendParticles = true; - return {}; - } - +void CAnimData::SetAnimation(const CAnimPlaybackParms& parms, bool noTrans) { + if (parms.GetAnimationId() == x40c_playbackParms.GetAnimationId() || + (parms.GetSecondAnimationId() == x40c_playbackParms.GetSecondAnimationId() && + parms.GetSecondAnimationId() != -1) || + (parms.GetBlendFactor() == x40c_playbackParms.GetBlendFactor() && parms.GetBlendFactor() != 1.f)) { if (x220_29_animationJustStarted) - { - x220_29_animationJustStarted = false; - suspendParticles = true; - } + return; + } - if (advTree && x1f8_animRoot) - { - SetRandomPlaybackRate(random); - CCharAnimTime time(scaleDt); - if (x220_25_loop) - { - while (time.GreaterThanZero() && !time.EpsilonZero()) - { - x210_passedIntCount += x1f8_animRoot->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); - x20c_passedBoolCount += x1f8_animRoot->GetBoolPOIList(time, g_BoolPOINodes.data(), 16, x20c_passedBoolCount, 0); - x214_passedParticleCount += x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0); - x218_passedSoundCount += x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0); - AdvanceAnim(time, offsetPost, quatPost); - } + x40c_playbackParms.SetAnimationId(parms.GetAnimationId()); + x40c_playbackParms.SetSecondAnimationId(parms.GetSecondAnimationId()); + x40c_playbackParms.SetBlendFactor(parms.GetBlendFactor()); + x200_speedScale = 1.f; + x208_defaultAnim = parms.GetAnimationId(); + + u32 animIdxA = xc_charInfo.GetAnimationIndex(parms.GetAnimationId()); + + ResetPOILists(); + + std::shared_ptr blendNode; + if (parms.GetSecondAnimationId() != -1) { + u32 animIdxB = xc_charInfo.GetAnimationIndex(parms.GetSecondAnimationId()); + + std::shared_ptr treeA = + x100_animMgr->GetAnimationTree(animIdxA, CMetaAnimTreeBuildOrders::NoSpecialOrders()); + std::shared_ptr treeB = + x100_animMgr->GetAnimationTree(animIdxB, CMetaAnimTreeBuildOrders::NoSpecialOrders()); + + blendNode = + std::make_shared(false, treeA, treeB, parms.GetBlendFactor(), + CAnimTreeBlend::CreatePrimitiveName(treeA, treeB, parms.GetBlendFactor())); + } else { + blendNode = x100_animMgr->GetAnimationTree(animIdxA, CMetaAnimTreeBuildOrders::NoSpecialOrders()); + } + + if (!noTrans && x1f8_animRoot) + x1f8_animRoot = x1fc_transMgr->GetTransitionTree(x1f8_animRoot, blendNode); + else + x1f8_animRoot = blendNode; + + x220_24_animating = parms.GetIsPlayAnimation(); + CalcPlaybackAlignmentParms(parms, blendNode); + ResetPOILists(); + x220_29_animationJustStarted = true; +} + +SAdvancementDeltas CAnimData::DoAdvance(float dt, bool& suspendParticles, CRandom16& random, bool advTree) { + suspendParticles = false; + + zeus::CVector3f offsetPre, offsetPost; + zeus::CQuaternion quatPre, quatPost; + + ResetPOILists(); + float scaleDt = dt * x200_speedScale; + if (x2fc_poseBuilder.HasRoot()) { + SAdvancementDeltas deltas = UpdateAdditiveAnims(scaleDt); + offsetPre = deltas.x0_posDelta; + quatPre = deltas.xc_rotDelta; + } + + if (!x220_24_animating) { + suspendParticles = true; + return {}; + } + + if (x220_29_animationJustStarted) { + x220_29_animationJustStarted = false; + suspendParticles = true; + } + + if (advTree && x1f8_animRoot) { + SetRandomPlaybackRate(random); + CCharAnimTime time(scaleDt); + if (x220_25_loop) { + while (time.GreaterThanZero() && !time.EpsilonZero()) { + x210_passedIntCount += x1f8_animRoot->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); + x20c_passedBoolCount += x1f8_animRoot->GetBoolPOIList(time, g_BoolPOINodes.data(), 16, x20c_passedBoolCount, 0); + x214_passedParticleCount += + x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0); + x218_passedSoundCount += + x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0); + AdvanceAnim(time, offsetPost, quatPost); + } + } else { + CCharAnimTime remTime = x1f8_animRoot->VGetTimeRemaining(); + while (!remTime.EpsilonZero() && !time.EpsilonZero()) { + x210_passedIntCount += x1f8_animRoot->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); + x20c_passedBoolCount += x1f8_animRoot->GetBoolPOIList(time, g_BoolPOINodes.data(), 16, x20c_passedBoolCount, 0); + x214_passedParticleCount += + x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0); + x218_passedSoundCount += + x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0); + AdvanceAnim(time, offsetPost, quatPost); + remTime = x1f8_animRoot->VGetTimeRemaining(); + time = std::max(0.f, std::min(remTime.GetSeconds(), time.GetSeconds())); + if (remTime.EpsilonZero()) { + x220_24_animating = false; + x1dc_alignPos = zeus::CVector3f::skZero; + x220_28_ = false; + x220_26_aligningPos = false; } - else - { - CCharAnimTime remTime = x1f8_animRoot->VGetTimeRemaining(); - while (!remTime.EpsilonZero() && !time.EpsilonZero()) - { - x210_passedIntCount += x1f8_animRoot->GetInt32POIList(time, g_Int32POINodes.data(), 16, x210_passedIntCount, 0); - x20c_passedBoolCount += x1f8_animRoot->GetBoolPOIList(time, g_BoolPOINodes.data(), 16, x20c_passedBoolCount, 0); - x214_passedParticleCount += x1f8_animRoot->GetParticlePOIList(time, g_ParticlePOINodes.data(), 16, x214_passedParticleCount, 0); - x218_passedSoundCount += x1f8_animRoot->GetSoundPOIList(time, g_SoundPOINodes.data(), 16, x218_passedSoundCount, 0); - AdvanceAnim(time, offsetPost, quatPost); - remTime = x1f8_animRoot->VGetTimeRemaining(); - time = std::max(0.f, std::min(remTime.GetSeconds(), time.GetSeconds())); - if (remTime.EpsilonZero()) - { - x220_24_animating = false; - x1dc_alignPos = zeus::CVector3f::skZero; - x220_28_ = false; - x220_26_aligningPos = false; - } - } + } + } + + x220_31_poseCached = false; + x220_30_poseBuilt = false; + } + + return {offsetPost + offsetPre, quatPost * quatPre}; +} + +SAdvancementDeltas CAnimData::Advance(float dt, const zeus::CVector3f& scale, CStateManager& stateMgr, TAreaId aid, + bool advTree) { + bool suspendParticles; + SAdvancementDeltas deltas = DoAdvance(dt, suspendParticles, *stateMgr.GetActiveRandom(), advTree); + if (suspendParticles) + x120_particleDB.SuspendAllActiveEffects(stateMgr); + + for (int i = 0; i < x214_passedParticleCount; ++i) { + CParticlePOINode& node = g_ParticlePOINodes[i]; + if (node.GetCharacterIndex() == -1 || node.GetCharacterIndex() == x204_charIdx) { + x120_particleDB.AddParticleEffect(node.GetString(), node.GetFlags(), node.GetParticleData(), scale, stateMgr, aid, + false, x21c_particleLightIdx); + } + } + + return deltas; +} + +SAdvancementDeltas CAnimData::AdvanceIgnoreParticles(float dt, CRandom16& random, bool advTree) { + bool suspendParticles; + return DoAdvance(dt, suspendParticles, random, advTree); +} + +void CAnimData::AdvanceAnim(CCharAnimTime& time, zeus::CVector3f& offset, zeus::CQuaternion& quat) { + SAdvancementResults results; + std::experimental::optional> simplified; + + if (x104_animDir == EAnimDir::Forward) { + results = x1f8_animRoot->VAdvanceView(time); + simplified = x1f8_animRoot->Simplified(); + } + + if (simplified) + x1f8_animRoot = CAnimTreeNode::Cast(std::move(*simplified)); + + if ((x220_28_ || x220_27_) && x210_passedIntCount > 0) { + for (int i = 0; i < x210_passedIntCount; ++i) { + CInt32POINode& node = g_Int32POINodes[i]; + if (node.GetPoiType() == EPOIType::UserEvent) { + switch (EUserEventType(node.GetValue())) { + case EUserEventType::AlignTargetPosStart: { + x220_26_aligningPos = true; + break; } - - x220_31_poseCached = false; - x220_30_poseBuilt = false; - } - - return {offsetPost + offsetPre, quatPost * quatPre}; -} - -SAdvancementDeltas CAnimData::Advance(float dt, const zeus::CVector3f& scale, - CStateManager& stateMgr, TAreaId aid, bool advTree) -{ - bool suspendParticles; - SAdvancementDeltas deltas = DoAdvance(dt, suspendParticles, *stateMgr.GetActiveRandom(), advTree); - if (suspendParticles) - x120_particleDB.SuspendAllActiveEffects(stateMgr); - - for (int i=0 ; i> simplified; - - if (x104_animDir == EAnimDir::Forward) - { - results = x1f8_animRoot->VAdvanceView(time); - simplified = x1f8_animRoot->Simplified(); - } - - if (simplified) - x1f8_animRoot = CAnimTreeNode::Cast(std::move(*simplified)); - - if ((x220_28_ || x220_27_) && x210_passedIntCount > 0) - { - for (int i=0 ; i& model, const TLockedToken& skinRules) -{ - xf4_xrayModel = std::make_shared(model, skinRules, xd8_modelData->GetLayoutInfo(), 0, m_drawInstCount); -} - -void CAnimData::SetInfraModel(const TLockedToken& model, const TLockedToken& skinRules) -{ - xf8_infraModel = std::make_shared(model, skinRules, xd8_modelData->GetLayoutInfo(), 0, m_drawInstCount); -} - -void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, - const CModelFlags& drawFlags, - const std::experimental::optional& morphEffect, - const float* morphMagnitudes) -{ - model.Calculate(pose, drawFlags, morphEffect, morphMagnitudes); -} - -void CAnimData::AdvanceParticles(const zeus::CTransform& xf, float dt, - const zeus::CVector3f& vec, CStateManager& stateMgr) -{ - x120_particleDB.Update(dt, x224_pose, *xcc_layoutData, xf, vec, stateMgr); -} - -float CAnimData::GetAverageVelocity(int animIn) const -{ - std::shared_ptr anim = x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(animIn)); - std::set prims; - anim->GetUniquePrimitives(prims); - - SObjectTag tag{FOURCC('ANIM'), 0}; - float velAccum = 0.f; - float durAccum = 0.f; - for (const CPrimitive& prim : prims) - { - tag.id = prim.GetAnimResId(); - TLockedToken animRes = xfc_animCtx->xc_store.GetObj(tag); - - CCharAnimTime dur; - float avgVel; - switch (animRes->GetFormat()) - { - case EAnimFormat::Uncompressed: default: - { - const CAnimSource& src = animRes->GetAsCAnimSource(); - dur = src.GetDuration(); - avgVel = src.GetAverageVelocity(); - break; - } - case EAnimFormat::BitstreamCompressed: - case EAnimFormat::BitstreamCompressed24: - { - const CFBStreamedCompression& src = animRes->GetAsCFBStreamedCompression(); - dur = src.GetAnimationDuration(); - avgVel = src.GetAverageVelocity(); - break; - } + break; } + } + } + } - velAccum += dur.GetSeconds() * avgVel; - durAccum += dur.GetSeconds(); + offset += results.x8_deltas.x0_posDelta; + if (x220_26_aligningPos) + offset += x1dc_alignPos * time.GetSeconds(); + + zeus::CQuaternion rot = results.x8_deltas.xc_rotDelta * x1e8_alignRot; + quat = quat * rot; + x1dc_alignPos = rot.transform(x1dc_alignPos); + time = results.x0_remTime; +} + +void CAnimData::SetXRayModel(const TLockedToken& model, const TLockedToken& skinRules) { + xf4_xrayModel = std::make_shared(model, skinRules, xd8_modelData->GetLayoutInfo(), 0, m_drawInstCount); +} + +void CAnimData::SetInfraModel(const TLockedToken& model, const TLockedToken& skinRules) { + xf8_infraModel = + std::make_shared(model, skinRules, xd8_modelData->GetLayoutInfo(), 0, m_drawInstCount); +} + +void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, const CModelFlags& drawFlags, + const std::experimental::optional& morphEffect, + const float* morphMagnitudes) { + model.Calculate(pose, drawFlags, morphEffect, morphMagnitudes); +} + +void CAnimData::AdvanceParticles(const zeus::CTransform& xf, float dt, const zeus::CVector3f& vec, + CStateManager& stateMgr) { + x120_particleDB.Update(dt, x224_pose, *xcc_layoutData, xf, vec, stateMgr); +} + +float CAnimData::GetAverageVelocity(int animIn) const { + std::shared_ptr anim = x100_animMgr->GetMetaAnimation(xc_charInfo.GetAnimationIndex(animIn)); + std::set prims; + anim->GetUniquePrimitives(prims); + + SObjectTag tag{FOURCC('ANIM'), 0}; + float velAccum = 0.f; + float durAccum = 0.f; + for (const CPrimitive& prim : prims) { + tag.id = prim.GetAnimResId(); + TLockedToken animRes = xfc_animCtx->xc_store.GetObj(tag); + + CCharAnimTime dur; + float avgVel; + switch (animRes->GetFormat()) { + case EAnimFormat::Uncompressed: + default: { + const CAnimSource& src = animRes->GetAsCAnimSource(); + dur = src.GetDuration(); + avgVel = src.GetAverageVelocity(); + break; + } + case EAnimFormat::BitstreamCompressed: + case EAnimFormat::BitstreamCompressed24: { + const CFBStreamedCompression& src = animRes->GetAsCFBStreamedCompression(); + dur = src.GetAnimationDuration(); + avgVel = src.GetAverageVelocity(); + break; + } } - if (durAccum > 0.f) - return velAccum / durAccum; - return 0.f; + velAccum += dur.GetSeconds() * avgVel; + durAccum += dur.GetSeconds(); + } + + if (durAccum > 0.f) + return velAccum / durAccum; + return 0.f; } -void CAnimData::ResetPOILists() -{ - x20c_passedBoolCount = 0; - x210_passedIntCount = 0; - x214_passedParticleCount = 0; - x218_passedSoundCount = 0; +void CAnimData::ResetPOILists() { + x20c_passedBoolCount = 0; + x210_passedIntCount = 0; + x214_passedParticleCount = 0; + x218_passedSoundCount = 0; } -CSegId CAnimData::GetLocatorSegId(std::string_view name) const -{ - return xcc_layoutData->GetSegIdFromString(name); +CSegId CAnimData::GetLocatorSegId(std::string_view name) const { return xcc_layoutData->GetSegIdFromString(name); } + +zeus::CAABox CAnimData::GetBoundingBox(const zeus::CTransform& xf) const { + return GetBoundingBox().getTransformedAABox(xf); } -zeus::CAABox CAnimData::GetBoundingBox(const zeus::CTransform& xf) const -{ - return GetBoundingBox().getTransformedAABox(xf); +zeus::CAABox CAnimData::GetBoundingBox() const { + auto aabbList = xc_charInfo.GetAnimBBoxList(); + if (aabbList.empty()) + return x108_aabb; + + CAnimTreeEffectiveContribution contrib = x1f8_animRoot->GetContributionOfHighestInfluence(); + auto search = rstl::binary_find( + aabbList.cbegin(), aabbList.cend(), contrib.x4_name, + [](const std::pair& other) -> const std::string& { return other.first; }); + if (search == aabbList.cend()) + return x108_aabb; + + return search->second; } -zeus::CAABox CAnimData::GetBoundingBox() const -{ - auto aabbList = xc_charInfo.GetAnimBBoxList(); - if (aabbList.empty()) - return x108_aabb; - - CAnimTreeEffectiveContribution contrib = x1f8_animRoot->GetContributionOfHighestInfluence(); - auto search = - rstl::binary_find(aabbList.cbegin(), aabbList.cend(), contrib.x4_name, - [](const std::pair& other) -> - const std::string& { return other.first; }); - if (search == aabbList.cend()) - return x108_aabb; - - return search->second; +void CAnimData::SubstituteModelData(const TCachedToken& model) { + xd8_modelData = model; + x108_aabb = xd8_modelData->GetModel()->GetAABB(); } -void CAnimData::SubstituteModelData(const TCachedToken& model) -{ - xd8_modelData = model; - x108_aabb = xd8_modelData->GetModel()->GetAABB(); +void CAnimData::SetParticleCEXTValue(std::string_view name, int idx, float value) { + auto search = std::find_if(xc_charInfo.x98_effects.begin(), xc_charInfo.x98_effects.end(), + [&name](const auto& v) { return v.first == name; }); + if (search != xc_charInfo.x98_effects.end() && search->second.size()) + x120_particleDB.SetCEXTValue(search->second.front().GetComponentName(), idx, value); } -void CAnimData::SetParticleCEXTValue(std::string_view name, int idx, float value) -{ - auto search = std::find_if(xc_charInfo.x98_effects.begin(), xc_charInfo.x98_effects.end(), - [&name](const auto& v) { return v.first == name; }); - if (search != xc_charInfo.x98_effects.end() && search->second.size()) - x120_particleDB.SetCEXTValue(search->second.front().GetComponentName(), idx, value); -} - -} +} // namespace urde diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index 12e1d8659..37eed161a 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -12,47 +12,45 @@ #include "IAnimReader.hpp" #include -enum class EUserEventType -{ - Projectile = 0, - EggLay = 1, - LoopedSoundStop = 2, - AlignTargetPos = 3, - AlignTargetRot = 4, - ChangeMaterial = 5, - Delete = 6, - GenerateEnd = 7, - DamageOn = 8, - DamageOff = 9, - AlignTargetPosStart = 10, - DeGenerate = 11, - Landing = 12, - TakeOff = 13, - FadeIn = 14, - FadeOut = 15, - ScreenShake = 16, - BeginAction = 17, - EndAction = 18, - BecomeRagDoll = 19, - IkLock = 20, - IkRelease = 21, - BreakLockOn = 22, - BecomeShootThrough = 23, - RemoveCollision = 24, - ObjectPickUp = 25, - ObjectDrop = 26, - EventStart = 27, - EventStop = 28, - Activate = 29, - Deactivate = 30, - SoundPlay = 31, - SoundStop = 32, - EffectOn = 33, - EffectOff = 34 +enum class EUserEventType { + Projectile = 0, + EggLay = 1, + LoopedSoundStop = 2, + AlignTargetPos = 3, + AlignTargetRot = 4, + ChangeMaterial = 5, + Delete = 6, + GenerateEnd = 7, + DamageOn = 8, + DamageOff = 9, + AlignTargetPosStart = 10, + DeGenerate = 11, + Landing = 12, + TakeOff = 13, + FadeIn = 14, + FadeOut = 15, + ScreenShake = 16, + BeginAction = 17, + EndAction = 18, + BecomeRagDoll = 19, + IkLock = 20, + IkRelease = 21, + BreakLockOn = 22, + BecomeShootThrough = 23, + RemoveCollision = 24, + ObjectPickUp = 25, + ObjectDrop = 26, + EventStart = 27, + EventStop = 28, + Activate = 29, + Deactivate = 30, + SoundPlay = 31, + SoundStop = 32, + EffectOn = 33, + EffectOff = 34 }; -namespace urde -{ +namespace urde { class CCharLayoutInfo; class CSkinnedModel; class CMorphableSkinnedModel; @@ -80,188 +78,173 @@ class IAnimReader; struct SAdvancementDeltas; struct SAdvancementResults; -class CAnimData -{ - friend class CModelData; - friend class CActor; - friend class CPlayerGun; - friend class CGrappleArm; +class CAnimData { + friend class CModelData; + friend class CActor; + friend class CPlayerGun; + friend class CGrappleArm; + public: - enum class EAnimDir - { - Forward, - Backward - }; + enum class EAnimDir { Forward, Backward }; + private: + TLockedToken x0_charFactory; + CCharacterInfo xc_charInfo; + TLockedToken xcc_layoutData; + TCachedToken xd8_modelData; + TLockedToken xe4_iceModelData; + std::shared_ptr xf4_xrayModel; + std::shared_ptr xf8_infraModel; + std::shared_ptr xfc_animCtx; + std::shared_ptr x100_animMgr; + EAnimDir x104_animDir = EAnimDir::Forward; + zeus::CAABox x108_aabb; + CParticleDatabase x120_particleDB; + CAssetId x1d8_selfId; + zeus::CVector3f x1dc_alignPos; + zeus::CQuaternion x1e8_alignRot; + std::shared_ptr x1f8_animRoot; + std::shared_ptr x1fc_transMgr; - TLockedToken x0_charFactory; - CCharacterInfo xc_charInfo; - TLockedToken xcc_layoutData; - TCachedToken xd8_modelData; - TLockedToken xe4_iceModelData; - std::shared_ptr xf4_xrayModel; - std::shared_ptr xf8_infraModel; - std::shared_ptr xfc_animCtx; - std::shared_ptr x100_animMgr; - EAnimDir x104_animDir = EAnimDir::Forward; - zeus::CAABox x108_aabb; - CParticleDatabase x120_particleDB; - CAssetId x1d8_selfId; - zeus::CVector3f x1dc_alignPos; - zeus::CQuaternion x1e8_alignRot; - std::shared_ptr x1f8_animRoot; - std::shared_ptr x1fc_transMgr; + float x200_speedScale = 1.f; + s32 x204_charIdx; + u16 x208_defaultAnim; + u32 x20c_passedBoolCount = 0; + u32 x210_passedIntCount = 0; + u32 x214_passedParticleCount = 0; + u32 x218_passedSoundCount = 0; + s32 x21c_particleLightIdx = 0; - float x200_speedScale = 1.f; - s32 x204_charIdx; - u16 x208_defaultAnim; - u32 x20c_passedBoolCount = 0; - u32 x210_passedIntCount = 0; - u32 x214_passedParticleCount = 0; - u32 x218_passedSoundCount = 0; - s32 x21c_particleLightIdx = 0; - - union - { - u32 x220_flags = 0; - struct - { - bool x220_24_animating : 1; - bool x220_25_loop : 1; - bool x220_26_aligningPos : 1; - bool x220_27_ : 1; - bool x220_28_ : 1; - bool x220_29_animationJustStarted : 1; - bool x220_30_poseBuilt : 1; - bool x220_31_poseCached : 1; - }; + union { + u32 x220_flags = 0; + struct { + bool x220_24_animating : 1; + bool x220_25_loop : 1; + bool x220_26_aligningPos : 1; + bool x220_27_ : 1; + bool x220_28_ : 1; + bool x220_29_animationJustStarted : 1; + bool x220_30_poseBuilt : 1; + bool x220_31_poseCached : 1; }; + }; - CPoseAsTransforms x224_pose; - CHierarchyPoseBuilder x2fc_poseBuilder; + CPoseAsTransforms x224_pose; + CHierarchyPoseBuilder x2fc_poseBuilder; - CAnimPlaybackParms x40c_playbackParms; - rstl::reserved_vector, 8> x434_additiveAnims; + CAnimPlaybackParms x40c_playbackParms; + rstl::reserved_vector, 8> x434_additiveAnims; - static rstl::reserved_vector g_BoolPOINodes; - static rstl::reserved_vector g_Int32POINodes; - static rstl::reserved_vector g_ParticlePOINodes; - static rstl::reserved_vector g_SoundPOINodes; - static rstl::reserved_vector g_TransientInt32POINodes; + static rstl::reserved_vector g_BoolPOINodes; + static rstl::reserved_vector g_Int32POINodes; + static rstl::reserved_vector g_ParticlePOINodes; + static rstl::reserved_vector g_SoundPOINodes; + static rstl::reserved_vector g_TransientInt32POINodes; - int m_drawInstCount; + int m_drawInstCount; public: - CAnimData(CAssetId, - const CCharacterInfo& character, - int defaultAnim, int charIdx, bool loop, - const TLockedToken& layout, - const TToken& model, - const std::experimental::optional>& iceModel, - const std::weak_ptr& ctx, - const std::shared_ptr& animMgr, - const std::shared_ptr& transMgr, - const TLockedToken& charFactory, - int drawInstCount); + CAnimData(CAssetId, const CCharacterInfo& character, int defaultAnim, int charIdx, bool loop, + const TLockedToken& layout, const TToken& model, + const std::experimental::optional>& iceModel, + const std::weak_ptr& ctx, const std::shared_ptr& animMgr, + const std::shared_ptr& transMgr, const TLockedToken& charFactory, + int drawInstCount); - void SetParticleEffectState(std::string_view effectName, bool active, CStateManager& mgr); - void InitializeEffects(CStateManager&, TAreaId, const zeus::CVector3f&); - CAssetId GetEventResourceIdForAnimResourceId(CAssetId) const; - void AddAdditiveSegData(const CSegIdList& list, CSegStatementSet& stSet); - static SAdvancementResults AdvanceAdditiveAnim(std::shared_ptr& anim, const CCharAnimTime& time); - SAdvancementDeltas AdvanceAdditiveAnims(float); - SAdvancementDeltas UpdateAdditiveAnims(float); - bool IsAdditiveAnimation(u32) const; - bool IsAdditiveAnimationAdded(u32) const; - const std::shared_ptr& GetRootAnimationTree() const { return x1f8_animRoot; } - const std::shared_ptr& GetAdditiveAnimationTree(u32) const; - bool IsAdditiveAnimationActive(u32) const; - void DelAdditiveAnimation(s32); - void AddAdditiveAnimation(s32, float, bool, bool); - float GetAdditiveAnimationWeight(u32 idx) const; - std::shared_ptr GetAnimationManager(); - const CCharacterInfo& GetCharacterInfo() const { return xc_charInfo; } - const CCharLayoutInfo& GetCharLayoutInfo() const { return *xcc_layoutData.GetObj(); } - void SetPhase(float); - void Touch(const CSkinnedModel& model, int shaderIdx) const; - SAdvancementDeltas GetAdvancementDeltas(const CCharAnimTime& a, const CCharAnimTime& b) const; - CCharAnimTime GetTimeOfUserEvent(EUserEventType, const CCharAnimTime& time) const; - void MultiplyPlaybackRate(float); - void SetPlaybackRate(float); - void SetRandomPlaybackRate(CRandom16&); - void CalcPlaybackAlignmentParms(const CAnimPlaybackParms& parms, - const std::shared_ptr& node); - zeus::CTransform GetLocatorTransform(CSegId id, const CCharAnimTime* time) const; - zeus::CTransform GetLocatorTransform(std::string_view name, const CCharAnimTime* time) const; - bool IsAnimTimeRemaining(float, std::string_view name) const; - float GetAnimTimeRemaining(std::string_view name) const; - float GetAnimationDuration(int) const; - bool GetIsLoop() const {return x220_25_loop;} - void EnableLooping(bool val) {x220_25_loop = val; x220_24_animating = true;} - void EnableAnimation(bool val) {x220_24_animating = val;} - bool IsAnimating() const {return x220_24_animating;} - void SetAnimDir(EAnimDir dir) { x104_animDir = dir; } - std::shared_ptr GetAnimSysContext() const; - std::shared_ptr GetAnimationManager() const; - void RecalcPoseBuilder(const CCharAnimTime*); - void RenderAuxiliary(const zeus::CFrustum& frustum) const; - void Render(CSkinnedModel& model, const CModelFlags& drawFlags, - const std::experimental::optional& morphEffect, - const float* morphMagnitudes); - void SetupRender(CSkinnedModel& model, - const CModelFlags& drawFlags, - const std::experimental::optional& morphEffect, - const float* morphMagnitudes); - static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags); - void PreRender(); - void BuildPose(); - const CPoseAsTransforms& GetPose() const { return x224_pose; } - static void PrimitiveSetToTokenVector(const std::set& primSet, - std::vector& tokensOut, bool preLock); - void GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set& primsOut) const; - void SetAnimation(const CAnimPlaybackParms& parms, bool); - SAdvancementDeltas DoAdvance(float, bool& suspendParticles, CRandom16&, bool advTree); - SAdvancementDeltas Advance(float, const zeus::CVector3f&, CStateManager& stateMgr, TAreaId aid, bool advTree); - SAdvancementDeltas AdvanceIgnoreParticles(float, CRandom16&, bool advTree); - void AdvanceAnim(CCharAnimTime& time, zeus::CVector3f&, zeus::CQuaternion&); - void SetXRayModel(const TLockedToken& model, const TLockedToken& skinRules); - std::shared_ptr GetXRayModel() const { return xf4_xrayModel; } - void SetInfraModel(const TLockedToken& model, const TLockedToken& skinRules); - std::shared_ptr GetInfraModel() const { return xf8_infraModel; } - const TCachedToken& GetModelData() const { return xd8_modelData; } + void SetParticleEffectState(std::string_view effectName, bool active, CStateManager& mgr); + void InitializeEffects(CStateManager&, TAreaId, const zeus::CVector3f&); + CAssetId GetEventResourceIdForAnimResourceId(CAssetId) const; + void AddAdditiveSegData(const CSegIdList& list, CSegStatementSet& stSet); + static SAdvancementResults AdvanceAdditiveAnim(std::shared_ptr& anim, const CCharAnimTime& time); + SAdvancementDeltas AdvanceAdditiveAnims(float); + SAdvancementDeltas UpdateAdditiveAnims(float); + bool IsAdditiveAnimation(u32) const; + bool IsAdditiveAnimationAdded(u32) const; + const std::shared_ptr& GetRootAnimationTree() const { return x1f8_animRoot; } + const std::shared_ptr& GetAdditiveAnimationTree(u32) const; + bool IsAdditiveAnimationActive(u32) const; + void DelAdditiveAnimation(s32); + void AddAdditiveAnimation(s32, float, bool, bool); + float GetAdditiveAnimationWeight(u32 idx) const; + std::shared_ptr GetAnimationManager(); + const CCharacterInfo& GetCharacterInfo() const { return xc_charInfo; } + const CCharLayoutInfo& GetCharLayoutInfo() const { return *xcc_layoutData.GetObj(); } + void SetPhase(float); + void Touch(const CSkinnedModel& model, int shaderIdx) const; + SAdvancementDeltas GetAdvancementDeltas(const CCharAnimTime& a, const CCharAnimTime& b) const; + CCharAnimTime GetTimeOfUserEvent(EUserEventType, const CCharAnimTime& time) const; + void MultiplyPlaybackRate(float); + void SetPlaybackRate(float); + void SetRandomPlaybackRate(CRandom16&); + void CalcPlaybackAlignmentParms(const CAnimPlaybackParms& parms, const std::shared_ptr& node); + zeus::CTransform GetLocatorTransform(CSegId id, const CCharAnimTime* time) const; + zeus::CTransform GetLocatorTransform(std::string_view name, const CCharAnimTime* time) const; + bool IsAnimTimeRemaining(float, std::string_view name) const; + float GetAnimTimeRemaining(std::string_view name) const; + float GetAnimationDuration(int) const; + bool GetIsLoop() const { return x220_25_loop; } + void EnableLooping(bool val) { + x220_25_loop = val; + x220_24_animating = true; + } + void EnableAnimation(bool val) { x220_24_animating = val; } + bool IsAnimating() const { return x220_24_animating; } + void SetAnimDir(EAnimDir dir) { x104_animDir = dir; } + std::shared_ptr GetAnimSysContext() const; + std::shared_ptr GetAnimationManager() const; + void RecalcPoseBuilder(const CCharAnimTime*); + void RenderAuxiliary(const zeus::CFrustum& frustum) const; + void Render(CSkinnedModel& model, const CModelFlags& drawFlags, + const std::experimental::optional& morphEffect, const float* morphMagnitudes); + void SetupRender(CSkinnedModel& model, const CModelFlags& drawFlags, + const std::experimental::optional& morphEffect, const float* morphMagnitudes); + static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags); + void PreRender(); + void BuildPose(); + const CPoseAsTransforms& GetPose() const { return x224_pose; } + static void PrimitiveSetToTokenVector(const std::set& primSet, std::vector& tokensOut, + bool preLock); + void GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set& primsOut) const; + void SetAnimation(const CAnimPlaybackParms& parms, bool); + SAdvancementDeltas DoAdvance(float, bool& suspendParticles, CRandom16&, bool advTree); + SAdvancementDeltas Advance(float, const zeus::CVector3f&, CStateManager& stateMgr, TAreaId aid, bool advTree); + SAdvancementDeltas AdvanceIgnoreParticles(float, CRandom16&, bool advTree); + void AdvanceAnim(CCharAnimTime& time, zeus::CVector3f&, zeus::CQuaternion&); + void SetXRayModel(const TLockedToken& model, const TLockedToken& skinRules); + std::shared_ptr GetXRayModel() const { return xf4_xrayModel; } + void SetInfraModel(const TLockedToken& model, const TLockedToken& skinRules); + std::shared_ptr GetInfraModel() const { return xf8_infraModel; } + const TCachedToken& GetModelData() const { return xd8_modelData; } - static void PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, - const CModelFlags& drawFlags, - const std::experimental::optional& morphEffect, - const float* morphMagnitudes); - void AdvanceParticles(const zeus::CTransform& xf, float dt, - const zeus::CVector3f&, CStateManager& stateMgr); - float GetAverageVelocity(int animIn) const; - void ResetPOILists(); - CSegId GetLocatorSegId(std::string_view name) const; - zeus::CAABox GetBoundingBox(const zeus::CTransform& xf) const; - zeus::CAABox GetBoundingBox() const; - void SubstituteModelData(const TCachedToken& model); - static void FreeCache(); - static void InitializeCache(); - CHierarchyPoseBuilder& PoseBuilder() { return x2fc_poseBuilder; } - const CParticleDatabase& GetParticleDB() const { return x120_particleDB; } - CParticleDatabase& GetParticleDB() { return x120_particleDB; } - void SetParticleCEXTValue(std::string_view name, int idx, float value); + static void PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, const CModelFlags& drawFlags, + const std::experimental::optional& morphEffect, + const float* morphMagnitudes); + void AdvanceParticles(const zeus::CTransform& xf, float dt, const zeus::CVector3f&, CStateManager& stateMgr); + float GetAverageVelocity(int animIn) const; + void ResetPOILists(); + CSegId GetLocatorSegId(std::string_view name) const; + zeus::CAABox GetBoundingBox(const zeus::CTransform& xf) const; + zeus::CAABox GetBoundingBox() const; + void SubstituteModelData(const TCachedToken& model); + static void FreeCache(); + static void InitializeCache(); + CHierarchyPoseBuilder& PoseBuilder() { return x2fc_poseBuilder; } + const CParticleDatabase& GetParticleDB() const { return x120_particleDB; } + CParticleDatabase& GetParticleDB() { return x120_particleDB; } + void SetParticleCEXTValue(std::string_view name, int idx, float value); - u32 GetPassedBoolPOICount() const { return x20c_passedBoolCount; } - u32 GetPassedIntPOICount() const { return x210_passedIntCount; } - u32 GetPassedParticlePOICount() const { return x214_passedParticleCount; } - u32 GetPassedSoundPOICount() const { return x218_passedSoundCount; } + u32 GetPassedBoolPOICount() const { return x20c_passedBoolCount; } + u32 GetPassedIntPOICount() const { return x210_passedIntCount; } + u32 GetPassedParticlePOICount() const { return x214_passedParticleCount; } + u32 GetPassedSoundPOICount() const { return x218_passedSoundCount; } - s32 GetCharacterIndex() const { return x204_charIdx; } - u16 GetDefaultAnimation() const { return x208_defaultAnim; } - TLockedToken& IceModel() { return xe4_iceModelData; } - const TLockedToken& GetIceModel() const { return xe4_iceModelData; } - void SetParticleLightIdx(s32 idx) { x21c_particleLightIdx = idx; } + s32 GetCharacterIndex() const { return x204_charIdx; } + u16 GetDefaultAnimation() const { return x208_defaultAnim; } + TLockedToken& IceModel() { return xe4_iceModelData; } + const TLockedToken& GetIceModel() const { return xe4_iceModelData; } + void SetParticleLightIdx(s32 idx) { x21c_particleLightIdx = idx; } - void MarkPoseDirty() { x220_30_poseBuilt = false; } + void MarkPoseDirty() { x220_30_poseBuilt = false; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimPOIData.cpp b/Runtime/Character/CAnimPOIData.cpp index daa01e8a4..5d93e0c5c 100644 --- a/Runtime/Character/CAnimPOIData.cpp +++ b/Runtime/Character/CAnimPOIData.cpp @@ -1,41 +1,35 @@ #include "CAnimPOIData.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { -CAnimPOIData::CAnimPOIData(CInputStream& in) -: x0_version(in.readUint32Big()) -{ - u32 boolCount = in.readUint32Big(); - x4_boolNodes.reserve(boolCount); - for (u32 i=0 ; i= 2) - { - u32 soundCount = in.readUint32Big(); - x34_soundNodes.reserve(soundCount); - for (u32 i=0 ; i= 2) { + u32 soundCount = in.readUint32Big(); + x34_soundNodes.reserve(soundCount); + for (u32 i = 0; i < soundCount; ++i) + x34_soundNodes.emplace_back(in); + } } -CFactoryFnReturn AnimPOIDataFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& parms, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); +CFactoryFnReturn AnimPOIDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& parms, + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/Character/CAnimPOIData.hpp b/Runtime/Character/CAnimPOIData.hpp index 2203e7d06..c866ffe65 100644 --- a/Runtime/Character/CAnimPOIData.hpp +++ b/Runtime/Character/CAnimPOIData.hpp @@ -6,28 +6,25 @@ #include "CParticlePOINode.hpp" #include "CSoundPOINode.hpp" -namespace urde -{ +namespace urde { + +class CAnimPOIData { + u32 x0_version; + std::vector x4_boolNodes; + std::vector x14_int32Nodes; + std::vector x24_particleNodes; + std::vector x34_soundNodes; -class CAnimPOIData -{ - u32 x0_version; - std::vector x4_boolNodes; - std::vector x14_int32Nodes; - std::vector x24_particleNodes; - std::vector x34_soundNodes; public: - CAnimPOIData(CInputStream& in); + CAnimPOIData(CInputStream& in); - const std::vector& GetBoolPOIStream() const {return x4_boolNodes;} - const std::vector& GetInt32POIStream() const {return x14_int32Nodes;} - const std::vector& GetParticlePOIStream() const {return x24_particleNodes;} - const std::vector& GetSoundPOIStream() const {return x34_soundNodes;} + const std::vector& GetBoolPOIStream() const { return x4_boolNodes; } + const std::vector& GetInt32POIStream() const { return x14_int32Nodes; } + const std::vector& GetParticlePOIStream() const { return x24_particleNodes; } + const std::vector& GetSoundPOIStream() const { return x34_soundNodes; } }; -CFactoryFnReturn AnimPOIDataFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& parms, +CFactoryFnReturn AnimPOIDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& parms, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/Character/CAnimPerSegmentData.hpp b/Runtime/Character/CAnimPerSegmentData.hpp index b1ee2beae..805ff7ab7 100644 --- a/Runtime/Character/CAnimPerSegmentData.hpp +++ b/Runtime/Character/CAnimPerSegmentData.hpp @@ -3,15 +3,12 @@ #include "zeus/CQuaternion.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { -struct CAnimPerSegmentData -{ - zeus::CQuaternion x0_rotation; - zeus::CVector3f x10_offset; - bool x1c_hasOffset = false; +struct CAnimPerSegmentData { + zeus::CQuaternion x0_rotation; + zeus::CVector3f x10_offset; + bool x1c_hasOffset = false; }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimPlaybackParms.hpp b/Runtime/Character/CAnimPlaybackParms.hpp index b5fd6815c..6380ca4ce 100644 --- a/Runtime/Character/CAnimPlaybackParms.hpp +++ b/Runtime/Character/CAnimPlaybackParms.hpp @@ -3,40 +3,42 @@ #include "RetroTypes.hpp" #include "zeus/CQuaternion.hpp" -namespace urde -{ -class CAnimPlaybackParms -{ - s32 x0_animA = -1; - s32 x4_animB = -1; - float x8_blendWeight = 1.f; - bool xc_animating = true; - //s32 x10_ = 0; - const zeus::CVector3f* x14_targetPos = nullptr; - bool x18_useLocator = false; - const zeus::CQuaternion* x1c_deltaOrient = nullptr; - const zeus::CTransform* x20_objectXf = nullptr; - const zeus::CVector3f* x24_objectScale = nullptr; -public: - CAnimPlaybackParms() = default; - CAnimPlaybackParms(s32 animA, s32 animB, float blendWeight, bool animating) - : x0_animA(animA), x4_animB(animB), x8_blendWeight(blendWeight), xc_animating(animating) {} - CAnimPlaybackParms(s32 anim, const zeus::CQuaternion* deltaOrient, const zeus::CVector3f* targetPos, - const zeus::CTransform* xf, const zeus::CVector3f* scale, bool useLocator) - : x0_animA(anim), x14_targetPos(targetPos), x18_useLocator(useLocator), x1c_deltaOrient(deltaOrient), - x20_objectXf(xf), x24_objectScale(scale) {} - const zeus::CTransform* GetObjectXform() const { return x20_objectXf; } - const zeus::CQuaternion* GetDeltaOrient() const { return x1c_deltaOrient; } - const zeus::CVector3f* GetTargetPos() const { return x14_targetPos; } - bool GetIsUseLocator() const { return x18_useLocator; } - const zeus::CVector3f* GetObjectScale() const { return x24_objectScale; } - s32 GetAnimationId() const { return x0_animA; } - s32 GetSecondAnimationId() const { return x4_animB; } - float GetBlendFactor() const { return x8_blendWeight; } - void SetAnimationId(s32 id) { x0_animA = id; } - void SetSecondAnimationId(s32 id) { x4_animB = id; } - void SetBlendFactor(float f) { x8_blendWeight = f; } - bool GetIsPlayAnimation() const { return xc_animating; } -}; -} +namespace urde { +class CAnimPlaybackParms { + s32 x0_animA = -1; + s32 x4_animB = -1; + float x8_blendWeight = 1.f; + bool xc_animating = true; + // s32 x10_ = 0; + const zeus::CVector3f* x14_targetPos = nullptr; + bool x18_useLocator = false; + const zeus::CQuaternion* x1c_deltaOrient = nullptr; + const zeus::CTransform* x20_objectXf = nullptr; + const zeus::CVector3f* x24_objectScale = nullptr; +public: + CAnimPlaybackParms() = default; + CAnimPlaybackParms(s32 animA, s32 animB, float blendWeight, bool animating) + : x0_animA(animA), x4_animB(animB), x8_blendWeight(blendWeight), xc_animating(animating) {} + CAnimPlaybackParms(s32 anim, const zeus::CQuaternion* deltaOrient, const zeus::CVector3f* targetPos, + const zeus::CTransform* xf, const zeus::CVector3f* scale, bool useLocator) + : x0_animA(anim) + , x14_targetPos(targetPos) + , x18_useLocator(useLocator) + , x1c_deltaOrient(deltaOrient) + , x20_objectXf(xf) + , x24_objectScale(scale) {} + const zeus::CTransform* GetObjectXform() const { return x20_objectXf; } + const zeus::CQuaternion* GetDeltaOrient() const { return x1c_deltaOrient; } + const zeus::CVector3f* GetTargetPos() const { return x14_targetPos; } + bool GetIsUseLocator() const { return x18_useLocator; } + const zeus::CVector3f* GetObjectScale() const { return x24_objectScale; } + s32 GetAnimationId() const { return x0_animA; } + s32 GetSecondAnimationId() const { return x4_animB; } + float GetBlendFactor() const { return x8_blendWeight; } + void SetAnimationId(s32 id) { x0_animA = id; } + void SetSecondAnimationId(s32 id) { x4_animB = id; } + void SetBlendFactor(float f) { x8_blendWeight = f; } + bool GetIsPlayAnimation() const { return xc_animating; } +}; +} // namespace urde diff --git a/Runtime/Character/CAnimSource.cpp b/Runtime/Character/CAnimSource.cpp index 4cc96e5ba..5c98916c4 100644 --- a/Runtime/Character/CAnimSource.cpp +++ b/Runtime/Character/CAnimSource.cpp @@ -4,270 +4,212 @@ #include "CSegIdList.hpp" #include "CSegStatementSet.hpp" -namespace urde -{ +namespace urde { -static float ClampZeroToOne(float in) -{ - return std::max(0.f, std::min(1.f, in)); -} +static float ClampZeroToOne(float in) { return std::max(0.f, std::min(1.f, in)); } -u32 RotationAndOffsetStorage::DataSizeInBytes(u32 rotPerFrame, u32 transPerFrame, u32 frameCount) -{ - return (transPerFrame * 12 + rotPerFrame * 16) * frameCount; +u32 RotationAndOffsetStorage::DataSizeInBytes(u32 rotPerFrame, u32 transPerFrame, u32 frameCount) { + return (transPerFrame * 12 + rotPerFrame * 16) * frameCount; } void RotationAndOffsetStorage::CopyRotationsAndOffsets(const std::vector& rots, - const std::vector& offs, - u32 frameCount, float* arrOut) -{ - std::vector::const_iterator rit = rots.cbegin(); - std::vector::const_iterator oit = offs.cbegin(); - u32 rotsPerFrame = rots.size() / frameCount; - u32 offsPerFrame = offs.size() / frameCount; - for (u32 i=0 ; i& offs, u32 frameCount, + float* arrOut) { + std::vector::const_iterator rit = rots.cbegin(); + std::vector::const_iterator oit = offs.cbegin(); + u32 rotsPerFrame = rots.size() / frameCount; + u32 offsPerFrame = offs.size() / frameCount; + for (u32 i = 0; i < frameCount; ++i) { + for (u32 j = 0; j < rotsPerFrame; ++j) { + const zeus::CQuaternion& rot = *rit++; + arrOut[0] = rot.w(); + arrOut[1] = rot.x(); + arrOut[2] = rot.y(); + arrOut[3] = rot.z(); + arrOut += 4; } -} - -std::unique_ptr -RotationAndOffsetStorage::GetRotationsAndOffsets(const std::vector& rots, - const std::vector& offs, - u32 frameCount) -{ - u32 size = DataSizeInBytes(rots.size() / frameCount, offs.size() / frameCount, frameCount); - std::unique_ptr ret(new float[(size / 4 + 1) * 4]); - CopyRotationsAndOffsets(rots, offs, frameCount, ret.get()); - return ret; -} - -RotationAndOffsetStorage::CRotationAndOffsetVectors::CRotationAndOffsetVectors(CInputStream& in) -{ - u32 quatCount = in.readUint32Big(); - x0_rotations.reserve(quatCount); - for (u32 i=0 ; i RotationAndOffsetStorage::GetRotationsAndOffsets(const std::vector& rots, + const std::vector& offs, + u32 frameCount) { + u32 size = DataSizeInBytes(rots.size() / frameCount, offs.size() / frameCount, frameCount); + std::unique_ptr ret(new float[(size / 4 + 1) * 4]); + CopyRotationsAndOffsets(rots, offs, frameCount, ret.get()); + return ret; } -RotationAndOffsetStorage::RotationAndOffsetStorage(const CRotationAndOffsetVectors& vectors, - u32 frameCount) -{ - x0_storage = GetRotationsAndOffsets(vectors.x0_rotations, vectors.x10_offsets, frameCount); - x8_frameCount = frameCount; - xc_rotPerFrame = vectors.x0_rotations.size() / frameCount; - x10_transPerFrame = vectors.x10_offsets.size() / frameCount; +RotationAndOffsetStorage::CRotationAndOffsetVectors::CRotationAndOffsetVectors(CInputStream& in) { + u32 quatCount = in.readUint32Big(); + x0_rotations.reserve(quatCount); + for (u32 i = 0; i < quatCount; ++i) { + x0_rotations.emplace_back(); + x0_rotations.back().readBig(in); + } + + u32 vecCount = in.readUint32Big(); + x10_offsets.reserve(vecCount); + for (u32 i = 0; i < vecCount; ++i) { + x10_offsets.emplace_back(); + x10_offsets.back().readBig(in); + } } -static std::vector ReadIndexTable(CInputStream& in) -{ - std::vector ret; - u32 count = in.readUint32Big(); - ret.reserve(count); - for (u32 i=0 ; i 0.00001f) - accum += frameVel; - } - x60_averageVelocity = accum / x0_duration.GetSeconds(); +static std::vector ReadIndexTable(CInputStream& in) { + std::vector ret; + u32 count = in.readUint32Big(); + ret.reserve(count); + for (u32 i = 0; i < count; ++i) + ret.push_back(in.readUByte()); + return ret; +} + +void CAnimSource::CalcAverageVelocity() { + u8 rootIdx = x20_rotationChannels[3]; + u8 rootTransIdx = x30_translationChannels[rootIdx]; + float accum = 0.f; + const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4; + const u32 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4; + for (u32 i = 1; i < x10_frameCount; ++i) { + const float* frameDataA = &x40_data.x0_storage[(i - 1) * floatsPerFrame + rotFloatsPerFrame + rootTransIdx * 3]; + const float* frameDataB = &x40_data.x0_storage[i * floatsPerFrame + rotFloatsPerFrame + rootTransIdx * 3]; + zeus::CVector3f vecA(frameDataA[0], frameDataA[1], frameDataA[2]); + zeus::CVector3f vecB(frameDataB[0], frameDataB[1], frameDataB[2]); + float frameVel = (vecB - vecA).magnitude(); + if (frameVel > 0.00001f) + accum += frameVel; + } + x60_averageVelocity = accum / x0_duration.GetSeconds(); } CAnimSource::CAnimSource(CInputStream& in, IObjectStore& store) -: x0_duration(in), - x8_interval(in), - x10_frameCount(in.readUint32Big()), - x1c_rootBone(in), - x20_rotationChannels(ReadIndexTable(in)), - x30_translationChannels(ReadIndexTable(in)), - x40_data(RotationAndOffsetStorage::CRotationAndOffsetVectors(in), x10_frameCount), - x54_evntId(in.readUint32Big()) -{ - if (x54_evntId.IsValid()) - { - x58_evntData = store.GetObj({SBIG('EVNT'), x54_evntId}); - x58_evntData.GetObj(); - } - CalcAverageVelocity(); +: x0_duration(in) +, x8_interval(in) +, x10_frameCount(in.readUint32Big()) +, x1c_rootBone(in) +, x20_rotationChannels(ReadIndexTable(in)) +, x30_translationChannels(ReadIndexTable(in)) +, x40_data(RotationAndOffsetStorage::CRotationAndOffsetVectors(in), x10_frameCount) +, x54_evntId(in.readUint32Big()) { + if (x54_evntId.IsValid()) { + x58_evntData = store.GetObj({SBIG('EVNT'), x54_evntId}); + x58_evntData.GetObj(); + } + CalcAverageVelocity(); } -void CAnimSource::GetSegStatementSet(const CSegIdList& list, - CSegStatementSet& set, - const CCharAnimTime& time) const -{ +void CAnimSource::GetSegStatementSet(const CSegIdList& list, CSegStatementSet& set, const CCharAnimTime& time) const { + u32 frameIdx = unsigned(time / x8_interval); + float remTime = time.GetSeconds() - frameIdx * x8_interval.GetSeconds(); + if (std::fabs(remTime) < 0.00001f) + remTime = 0.f; + float t = ClampZeroToOne(remTime / x8_interval.GetSeconds()); + const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4; + const u32 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4; + + for (const CSegId& id : list.GetList()) { + u8 rotIdx = x20_rotationChannels[id]; + if (rotIdx != 0xff) { + const float* frameDataA = &x40_data.x0_storage[frameIdx * floatsPerFrame + rotIdx * 4]; + const float* frameDataB = &x40_data.x0_storage[(frameIdx + 1) * floatsPerFrame + rotIdx * 4]; + + zeus::CQuaternion quatA(frameDataA[0], frameDataA[1], frameDataA[2], frameDataA[3]); + zeus::CQuaternion quatB(frameDataB[0], frameDataB[1], frameDataB[2], frameDataB[3]); + set.x4_segData[id].x0_rotation = zeus::CQuaternion::slerp(quatA, quatB, t); + + u8 transIdx = x30_translationChannels[rotIdx]; + if (transIdx != 0xff) { + const float* frameDataA = &x40_data.x0_storage[frameIdx * floatsPerFrame + rotFloatsPerFrame + transIdx * 3]; + const float* frameDataB = + &x40_data.x0_storage[(frameIdx - 1) * floatsPerFrame + rotFloatsPerFrame + transIdx * 3]; + zeus::CVector3f vecA(frameDataA[0], frameDataA[1], frameDataA[2]); + zeus::CVector3f vecB(frameDataB[0], frameDataB[1], frameDataB[2]); + set.x4_segData[id].x10_offset = zeus::CVector3f::lerp(vecA, vecB, t); + set.x4_segData[id].x1c_hasOffset = true; + } + } + } +} + +const std::vector& CAnimSource::GetSoundPOIStream() const { return x58_evntData->GetSoundPOIStream(); } + +const std::vector& CAnimSource::GetParticlePOIStream() const { + return x58_evntData->GetParticlePOIStream(); +} + +const std::vector& CAnimSource::GetInt32POIStream() const { return x58_evntData->GetInt32POIStream(); } + +const std::vector& CAnimSource::GetBoolPOIStream() const { return x58_evntData->GetBoolPOIStream(); } + +zeus::CQuaternion CAnimSource::GetRotation(const CSegId& seg, const CCharAnimTime& time) const { + u8 rotIdx = x20_rotationChannels[seg]; + if (rotIdx != 0xff) { u32 frameIdx = unsigned(time / x8_interval); float remTime = time.GetSeconds() - frameIdx * x8_interval.GetSeconds(); if (std::fabs(remTime) < 0.00001f) - remTime = 0.f; + remTime = 0.f; float t = ClampZeroToOne(remTime / x8_interval.GetSeconds()); + + const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4; + const float* frameDataA = &x40_data.x0_storage[frameIdx * floatsPerFrame + rotIdx * 4]; + const float* frameDataB = &x40_data.x0_storage[(frameIdx + 1) * floatsPerFrame + rotIdx * 4]; + + zeus::CQuaternion quatA(frameDataA[0], frameDataA[1], frameDataA[2], frameDataA[3]); + zeus::CQuaternion quatB(frameDataB[0], frameDataB[1], frameDataB[2], frameDataB[3]); + return zeus::CQuaternion::slerp(quatA, quatB, t); + } else { + return {}; + } +} + +zeus::CVector3f CAnimSource::GetOffset(const CSegId& seg, const CCharAnimTime& time) const { + u8 rotIdx = x20_rotationChannels[seg]; + if (rotIdx != 0xff) { + u8 transIdx = x30_translationChannels[rotIdx]; + if (transIdx == 0xff) + return {}; + + u32 frameIdx = unsigned(time / x8_interval); + float remTime = time.GetSeconds() - frameIdx * x8_interval.GetSeconds(); + if (std::fabs(remTime) < 0.00001f) + remTime = 0.f; + float t = ClampZeroToOne(remTime / x8_interval.GetSeconds()); + const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4; const u32 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4; - - for (const CSegId& id : list.GetList()) - { - u8 rotIdx = x20_rotationChannels[id]; - if (rotIdx != 0xff) - { - const float* frameDataA = - &x40_data.x0_storage[frameIdx*floatsPerFrame+rotIdx*4]; - const float* frameDataB = - &x40_data.x0_storage[(frameIdx+1)*floatsPerFrame+rotIdx*4]; - - zeus::CQuaternion quatA(frameDataA[0], frameDataA[1], frameDataA[2], frameDataA[3]); - zeus::CQuaternion quatB(frameDataB[0], frameDataB[1], frameDataB[2], frameDataB[3]); - set.x4_segData[id].x0_rotation = zeus::CQuaternion::slerp(quatA, quatB, t); - - u8 transIdx = x30_translationChannels[rotIdx]; - if (transIdx != 0xff) - { - const float* frameDataA = - &x40_data.x0_storage[frameIdx*floatsPerFrame+rotFloatsPerFrame+transIdx*3]; - const float* frameDataB = - &x40_data.x0_storage[(frameIdx-1)*floatsPerFrame+rotFloatsPerFrame+transIdx*3]; - zeus::CVector3f vecA(frameDataA[0], frameDataA[1], frameDataA[2]); - zeus::CVector3f vecB(frameDataB[0], frameDataB[1], frameDataB[2]); - set.x4_segData[id].x10_offset = zeus::CVector3f::lerp(vecA, vecB, t); - set.x4_segData[id].x1c_hasOffset = true; - } - } - } + const float* frameDataA = &x40_data.x0_storage[frameIdx * floatsPerFrame + rotFloatsPerFrame + transIdx * 3]; + const float* frameDataB = &x40_data.x0_storage[(frameIdx - 1) * floatsPerFrame + rotFloatsPerFrame + transIdx * 3]; + zeus::CVector3f vecA(frameDataA[0], frameDataA[1], frameDataA[2]); + zeus::CVector3f vecB(frameDataB[0], frameDataB[1], frameDataB[2]); + return zeus::CVector3f::lerp(vecA, vecB, t); + } else { + return {}; + } } -const std::vector& CAnimSource::GetSoundPOIStream() const -{ - return x58_evntData->GetSoundPOIStream(); +bool CAnimSource::HasOffset(const CSegId& seg) const { + u8 rotIdx = x20_rotationChannels[seg]; + if (rotIdx == 0xff) + return false; + u8 transIdx = x30_translationChannels[rotIdx]; + return transIdx != 0xff; } -const std::vector& CAnimSource::GetParticlePOIStream() const -{ - return x58_evntData->GetParticlePOIStream(); -} - -const std::vector& CAnimSource::GetInt32POIStream() const -{ - return x58_evntData->GetInt32POIStream(); -} - -const std::vector& CAnimSource::GetBoolPOIStream() const -{ - return x58_evntData->GetBoolPOIStream(); -} - -zeus::CQuaternion CAnimSource::GetRotation(const CSegId& seg, const CCharAnimTime& time) const -{ - u8 rotIdx = x20_rotationChannels[seg]; - if (rotIdx != 0xff) - { - u32 frameIdx = unsigned(time / x8_interval); - float remTime = time.GetSeconds() - frameIdx * x8_interval.GetSeconds(); - if (std::fabs(remTime) < 0.00001f) - remTime = 0.f; - float t = ClampZeroToOne(remTime / x8_interval.GetSeconds()); - - const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4; - const float* frameDataA = - &x40_data.x0_storage[frameIdx*floatsPerFrame+rotIdx*4]; - const float* frameDataB = - &x40_data.x0_storage[(frameIdx+1)*floatsPerFrame+rotIdx*4]; - - zeus::CQuaternion quatA(frameDataA[0], frameDataA[1], frameDataA[2], frameDataA[3]); - zeus::CQuaternion quatB(frameDataB[0], frameDataB[1], frameDataB[2], frameDataB[3]); - return zeus::CQuaternion::slerp(quatA, quatB, t); - } - else - { - return {}; - } -} - -zeus::CVector3f CAnimSource::GetOffset(const CSegId& seg, const CCharAnimTime& time) const -{ - u8 rotIdx = x20_rotationChannels[seg]; - if (rotIdx != 0xff) - { - u8 transIdx = x30_translationChannels[rotIdx]; - if (transIdx == 0xff) - return {}; - - u32 frameIdx = unsigned(time / x8_interval); - float remTime = time.GetSeconds() - frameIdx * x8_interval.GetSeconds(); - if (std::fabs(remTime) < 0.00001f) - remTime = 0.f; - float t = ClampZeroToOne(remTime / x8_interval.GetSeconds()); - - const u32 floatsPerFrame = x40_data.x10_transPerFrame * 3 + x40_data.xc_rotPerFrame * 4; - const u32 rotFloatsPerFrame = x40_data.xc_rotPerFrame * 4; - const float* frameDataA = - &x40_data.x0_storage[frameIdx*floatsPerFrame+rotFloatsPerFrame+transIdx*3]; - const float* frameDataB = - &x40_data.x0_storage[(frameIdx-1)*floatsPerFrame+rotFloatsPerFrame+transIdx*3]; - zeus::CVector3f vecA(frameDataA[0], frameDataA[1], frameDataA[2]); - zeus::CVector3f vecB(frameDataB[0], frameDataB[1], frameDataB[2]); - return zeus::CVector3f::lerp(vecA, vecB, t); - } - else - { - return {}; - } -} - -bool CAnimSource::HasOffset(const CSegId& seg) const -{ - u8 rotIdx = x20_rotationChannels[seg]; - if (rotIdx == 0xff) - return false; - u8 transIdx = x30_translationChannels[rotIdx]; - return transIdx != 0xff; -} - -} +} // namespace urde diff --git a/Runtime/Character/CAnimSource.hpp b/Runtime/Character/CAnimSource.hpp index 2d6099fe2..4183e0c04 100644 --- a/Runtime/Character/CAnimSource.hpp +++ b/Runtime/Character/CAnimSource.hpp @@ -7,8 +7,7 @@ #include "CSegId.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class IObjectStore; class CSegIdList; class CSegStatementSet; @@ -19,68 +18,60 @@ class CInt32POINode; class CParticlePOINode; class CSoundPOINode; -class RotationAndOffsetStorage -{ - friend class CAnimSource; - std::unique_ptr x0_storage; - u32 x8_frameCount; - u32 xc_rotPerFrame; - u32 x10_transPerFrame; +class RotationAndOffsetStorage { + friend class CAnimSource; + std::unique_ptr x0_storage; + u32 x8_frameCount; + u32 xc_rotPerFrame; + u32 x10_transPerFrame; - std::unique_ptr GetRotationsAndOffsets(const std::vector& rots, - const std::vector& offs, - u32 frameCount); - static void CopyRotationsAndOffsets(const std::vector& rots, - const std::vector& offs, - u32 frameCount, float*); - static u32 DataSizeInBytes(u32 rotPerFrame, u32 transPerFrame, u32 frameCount); + std::unique_ptr GetRotationsAndOffsets(const std::vector& rots, + const std::vector& offs, u32 frameCount); + static void CopyRotationsAndOffsets(const std::vector& rots, + const std::vector& offs, u32 frameCount, float*); + static u32 DataSizeInBytes(u32 rotPerFrame, u32 transPerFrame, u32 frameCount); public: - struct CRotationAndOffsetVectors - { - std::vector x0_rotations; - std::vector x10_offsets; - CRotationAndOffsetVectors(CInputStream& in); - }; - u32 GetFrameSizeInBytes() const; - RotationAndOffsetStorage(const CRotationAndOffsetVectors& vectors, u32 frameCount); + struct CRotationAndOffsetVectors { + std::vector x0_rotations; + std::vector x10_offsets; + CRotationAndOffsetVectors(CInputStream& in); + }; + u32 GetFrameSizeInBytes() const; + RotationAndOffsetStorage(const CRotationAndOffsetVectors& vectors, u32 frameCount); }; -class CAnimSource -{ - friend class CAnimSourceInfo; - CCharAnimTime x0_duration; - CCharAnimTime x8_interval; - u32 x10_frameCount; - CSegId x1c_rootBone; - std::vector x20_rotationChannels; - std::vector x30_translationChannels; - RotationAndOffsetStorage x40_data; - CAssetId x54_evntId; - TCachedToken x58_evntData; - float x60_averageVelocity; +class CAnimSource { + friend class CAnimSourceInfo; + CCharAnimTime x0_duration; + CCharAnimTime x8_interval; + u32 x10_frameCount; + CSegId x1c_rootBone; + std::vector x20_rotationChannels; + std::vector x30_translationChannels; + RotationAndOffsetStorage x40_data; + CAssetId x54_evntId; + TCachedToken x58_evntData; + float x60_averageVelocity; - void CalcAverageVelocity(); + void CalcAverageVelocity(); public: - CAnimSource(CInputStream& in, IObjectStore& store); + CAnimSource(CInputStream& in, IObjectStore& store); - void GetSegStatementSet(const CSegIdList& list, - CSegStatementSet& set, - const CCharAnimTime& time) const; + void GetSegStatementSet(const CSegIdList& list, CSegStatementSet& set, const CCharAnimTime& time) const; - const std::vector& GetSoundPOIStream() const; - const std::vector& GetParticlePOIStream() const; - const std::vector& GetInt32POIStream() const; - const std::vector& GetBoolPOIStream() const; - const TCachedToken& GetPOIData() const {return x58_evntData;} - float GetAverageVelocity() const { return x60_averageVelocity; } - zeus::CQuaternion GetRotation(const CSegId& seg, const CCharAnimTime& time) const; - zeus::CVector3f GetOffset(const CSegId& seg, const CCharAnimTime& time) const; - bool HasOffset(const CSegId& seg) const; - const CCharAnimTime& GetDuration() const {return x0_duration;} - const CSegId& GetRootBoneId() const {return x1c_rootBone;} + const std::vector& GetSoundPOIStream() const; + const std::vector& GetParticlePOIStream() const; + const std::vector& GetInt32POIStream() const; + const std::vector& GetBoolPOIStream() const; + const TCachedToken& GetPOIData() const { return x58_evntData; } + float GetAverageVelocity() const { return x60_averageVelocity; } + zeus::CQuaternion GetRotation(const CSegId& seg, const CCharAnimTime& time) const; + zeus::CVector3f GetOffset(const CSegId& seg, const CCharAnimTime& time) const; + bool HasOffset(const CSegId& seg) const; + const CCharAnimTime& GetDuration() const { return x0_duration; } + const CSegId& GetRootBoneId() const { return x1c_rootBone; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimSourceReader.cpp b/Runtime/Character/CAnimSourceReader.cpp index 760461b44..b2def6a76 100644 --- a/Runtime/Character/CAnimSourceReader.cpp +++ b/Runtime/Character/CAnimSourceReader.cpp @@ -5,463 +5,356 @@ #include "CSoundPOINode.hpp" #include "CFBStreamedAnimReader.hpp" -namespace urde -{ +namespace urde { -CAnimSourceInfo::CAnimSourceInfo(const TSubAnimTypeToken& token) -: x4_token(token) {} +CAnimSourceInfo::CAnimSourceInfo(const TSubAnimTypeToken& token) : x4_token(token) {} -bool CAnimSourceInfo::HasPOIData() const -{ - return x4_token->x58_evntData; +bool CAnimSourceInfo::HasPOIData() const { return x4_token->x58_evntData; } + +const std::vector& CAnimSourceInfo::GetBoolPOIStream() const { return x4_token->GetBoolPOIStream(); } + +const std::vector& CAnimSourceInfo::GetInt32POIStream() const { return x4_token->GetInt32POIStream(); } + +const std::vector& CAnimSourceInfo::GetParticlePOIStream() const { + return x4_token->GetParticlePOIStream(); } -const std::vector& CAnimSourceInfo::GetBoolPOIStream() const -{ - return x4_token->GetBoolPOIStream(); +const std::vector& CAnimSourceInfo::GetSoundPOIStream() const { return x4_token->GetSoundPOIStream(); } + +CCharAnimTime CAnimSourceInfo::GetAnimationDuration() const { return x4_token->GetDuration(); } + +std::set> CAnimSourceReaderBase::GetUniqueParticlePOIs() const { + const std::vector& particleNodes = x4_sourceInfo->GetParticlePOIStream(); + std::set> ret; + for (const CParticlePOINode& node : particleNodes) + if (node.GetUnique()) + ret.insert(std::make_pair(std::string(node.GetString()), node.GetIndex())); + return ret; } -const std::vector& CAnimSourceInfo::GetInt32POIStream() const -{ - return x4_token->GetInt32POIStream(); +std::set> CAnimSourceReaderBase::GetUniqueInt32POIs() const { + const std::vector& int32Nodes = x4_sourceInfo->GetInt32POIStream(); + std::set> ret; + for (const CInt32POINode& node : int32Nodes) + if (node.GetUnique()) + ret.insert(std::make_pair(std::string(node.GetString()), node.GetIndex())); + return ret; } -const std::vector& CAnimSourceInfo::GetParticlePOIStream() const -{ - return x4_token->GetParticlePOIStream(); +std::set> CAnimSourceReaderBase::GetUniqueBoolPOIs() const { + const std::vector& boolNodes = x4_sourceInfo->GetBoolPOIStream(); + std::set> ret; + for (const CBoolPOINode& node : boolNodes) + if (node.GetUnique()) + ret.insert(std::make_pair(std::string(node.GetString()), node.GetIndex())); + return ret; } -const std::vector& CAnimSourceInfo::GetSoundPOIStream() const -{ - return x4_token->GetSoundPOIStream(); +void CAnimSourceReaderBase::PostConstruct(const CCharAnimTime& time) { + x14_passedBoolCount = 0; + x18_passedIntCount = 0; + x1c_passedParticleCount = 0; + x20_passedSoundCount = 0; + + if (x4_sourceInfo->HasPOIData()) { + std::set> boolPOIs = GetUniqueBoolPOIs(); + std::set> int32POIs = GetUniqueInt32POIs(); + std::set> particlePOIs = GetUniqueParticlePOIs(); + + x24_boolStates.resize(boolPOIs.size()); + x34_int32States.resize(int32POIs.size()); + x44_particleStates.resize(particlePOIs.size()); + + for (const auto& poi : boolPOIs) + x24_boolStates[poi.second] = std::make_pair(poi.first, false); + for (const auto& poi : int32POIs) + x34_int32States[poi.second] = std::make_pair(poi.first, 0); + for (const auto& poi : particlePOIs) + x44_particleStates[poi.second] = std::make_pair(poi.first, CParticleData::EParentedMode::Initial); + } + + CCharAnimTime tmpTime = time; + if (tmpTime.GreaterThanZero()) { + while (tmpTime.GreaterThanZero()) { + SAdvancementResults res = VAdvanceView(tmpTime); + tmpTime = res.x0_remTime; + } + } else if (x4_sourceInfo->HasPOIData()) { + UpdatePOIStates(); + if (!time.GreaterThanZero()) { + x14_passedBoolCount = 0; + x18_passedIntCount = 0; + x1c_passedParticleCount = 0; + x20_passedSoundCount = 0; + } + } } -CCharAnimTime CAnimSourceInfo::GetAnimationDuration() const -{ - return x4_token->GetDuration(); +void CAnimSourceReaderBase::UpdatePOIStates() { + const std::vector& boolNodes = x4_sourceInfo->GetBoolPOIStream(); + const std::vector& int32Nodes = x4_sourceInfo->GetInt32POIStream(); + const std::vector& particleNodes = x4_sourceInfo->GetParticlePOIStream(); + const std::vector& soundNodes = x4_sourceInfo->GetSoundPOIStream(); + + while (x14_passedBoolCount < boolNodes.size() && boolNodes[x14_passedBoolCount].GetTime() <= xc_curTime) { + auto& node = boolNodes[x14_passedBoolCount]; + if (node.GetIndex() >= 0) + x24_boolStates[node.GetIndex()].second = node.GetValue(); + ++x14_passedBoolCount; + } + + while (x18_passedIntCount < int32Nodes.size() && int32Nodes[x18_passedIntCount].GetTime() <= xc_curTime) { + auto& node = int32Nodes[x18_passedIntCount]; + if (node.GetIndex() >= 0) + x34_int32States[node.GetIndex()].second = node.GetValue(); + ++x18_passedIntCount; + } + + while (x1c_passedParticleCount < particleNodes.size() && + particleNodes[x1c_passedParticleCount].GetTime() <= xc_curTime) { + auto& node = particleNodes[x1c_passedParticleCount]; + if (node.GetIndex() >= 0) + x44_particleStates[node.GetIndex()].second = node.GetParticleData().GetParentedMode(); + ++x1c_passedParticleCount; + } + + while (x20_passedSoundCount < soundNodes.size() && soundNodes[x20_passedSoundCount].GetTime() <= xc_curTime) { + ++x20_passedSoundCount; + } } -std::set> -CAnimSourceReaderBase::GetUniqueParticlePOIs() const -{ - const std::vector& particleNodes = x4_sourceInfo->GetParticlePOIStream(); - std::set> ret; - for (const CParticlePOINode& node : particleNodes) - if (node.GetUnique()) - ret.insert(std::make_pair(std::string(node.GetString()), node.GetIndex())); - return ret; -} - -std::set> -CAnimSourceReaderBase::GetUniqueInt32POIs() const -{ - const std::vector& int32Nodes = x4_sourceInfo->GetInt32POIStream(); - std::set> ret; - for (const CInt32POINode& node : int32Nodes) - if (node.GetUnique()) - ret.insert(std::make_pair(std::string(node.GetString()), node.GetIndex())); - return ret; -} - -std::set> -CAnimSourceReaderBase::GetUniqueBoolPOIs() const -{ +u32 CAnimSourceReaderBase::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + if (x4_sourceInfo->HasPOIData()) { const std::vector& boolNodes = x4_sourceInfo->GetBoolPOIStream(); - std::set> ret; - for (const CBoolPOINode& node : boolNodes) - if (node.GetUnique()) - ret.insert(std::make_pair(std::string(node.GetString()), node.GetIndex())); - return ret; + return _getPOIList(time, listOut, capacity, iterator, unk, boolNodes, xc_curTime, *x4_sourceInfo, + x14_passedBoolCount); + } + return 0; } -void CAnimSourceReaderBase::PostConstruct(const CCharAnimTime& time) -{ - x14_passedBoolCount = 0; - x18_passedIntCount = 0; - x1c_passedParticleCount = 0; - x20_passedSoundCount = 0; - - if (x4_sourceInfo->HasPOIData()) - { - std::set> boolPOIs = GetUniqueBoolPOIs(); - std::set> int32POIs = GetUniqueInt32POIs(); - std::set> particlePOIs = GetUniqueParticlePOIs(); - - x24_boolStates.resize(boolPOIs.size()); - x34_int32States.resize(int32POIs.size()); - x44_particleStates.resize(particlePOIs.size()); - - for (const auto& poi : boolPOIs) - x24_boolStates[poi.second] = std::make_pair(poi.first, false); - for (const auto& poi : int32POIs) - x34_int32States[poi.second] = std::make_pair(poi.first, 0); - for (const auto& poi : particlePOIs) - x44_particleStates[poi.second] = std::make_pair(poi.first, CParticleData::EParentedMode::Initial); - } - - CCharAnimTime tmpTime = time; - if (tmpTime.GreaterThanZero()) - { - while (tmpTime.GreaterThanZero()) - { - SAdvancementResults res = VAdvanceView(tmpTime); - tmpTime = res.x0_remTime; - } - } - else if (x4_sourceInfo->HasPOIData()) - { - UpdatePOIStates(); - if (!time.GreaterThanZero()) - { - x14_passedBoolCount = 0; - x18_passedIntCount = 0; - x1c_passedParticleCount = 0; - x20_passedSoundCount = 0; - } - } -} - -void CAnimSourceReaderBase::UpdatePOIStates() -{ - const std::vector& boolNodes = x4_sourceInfo->GetBoolPOIStream(); +u32 CAnimSourceReaderBase::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + if (x4_sourceInfo->HasPOIData()) { const std::vector& int32Nodes = x4_sourceInfo->GetInt32POIStream(); + return _getPOIList(time, listOut, capacity, iterator, unk, int32Nodes, xc_curTime, *x4_sourceInfo, + x18_passedIntCount); + } + return 0; +} + +u32 CAnimSourceReaderBase::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + if (x4_sourceInfo->HasPOIData()) { const std::vector& particleNodes = x4_sourceInfo->GetParticlePOIStream(); + return _getPOIList(time, listOut, capacity, iterator, unk, particleNodes, xc_curTime, *x4_sourceInfo, + x1c_passedParticleCount); + } + return 0; +} + +u32 CAnimSourceReaderBase::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + if (x4_sourceInfo->HasPOIData()) { const std::vector& soundNodes = x4_sourceInfo->GetSoundPOIStream(); - - while (x14_passedBoolCount < boolNodes.size() && - boolNodes[x14_passedBoolCount].GetTime() <= xc_curTime) - { - auto& node = boolNodes[x14_passedBoolCount]; - if (node.GetIndex() >= 0) - x24_boolStates[node.GetIndex()].second = node.GetValue(); - ++x14_passedBoolCount; - } - - while (x18_passedIntCount < int32Nodes.size() && - int32Nodes[x18_passedIntCount].GetTime() <= xc_curTime) - { - auto& node = int32Nodes[x18_passedIntCount]; - if (node.GetIndex() >= 0) - x34_int32States[node.GetIndex()].second = node.GetValue(); - ++x18_passedIntCount; - } - - while (x1c_passedParticleCount < particleNodes.size() && - particleNodes[x1c_passedParticleCount].GetTime() <= xc_curTime) - { - auto& node = particleNodes[x1c_passedParticleCount]; - if (node.GetIndex() >= 0) - x44_particleStates[node.GetIndex()].second = node.GetParticleData().GetParentedMode(); - ++x1c_passedParticleCount; - } - - while (x20_passedSoundCount < soundNodes.size() && - soundNodes[x20_passedSoundCount].GetTime() <= xc_curTime) - { - ++x20_passedSoundCount; - } + return _getPOIList(time, listOut, capacity, iterator, unk, soundNodes, xc_curTime, *x4_sourceInfo, + x20_passedSoundCount); + } + return 0; } -u32 CAnimSourceReaderBase::VGetBoolPOIList(const CCharAnimTime& time, - CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - if (x4_sourceInfo->HasPOIData()) - { - const std::vector& boolNodes = x4_sourceInfo->GetBoolPOIStream(); - return _getPOIList(time, listOut, capacity, iterator, unk, boolNodes, - xc_curTime, *x4_sourceInfo, x14_passedBoolCount); - } - return 0; +bool CAnimSourceReaderBase::VGetBoolPOIState(const char* name) const { + for (const auto& node : x24_boolStates) + if (!node.first.compare(name)) + return node.second; + return false; } -u32 CAnimSourceReaderBase::VGetInt32POIList(const CCharAnimTime& time, - CInt32POINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - if (x4_sourceInfo->HasPOIData()) - { - const std::vector& int32Nodes = x4_sourceInfo->GetInt32POIStream(); - return _getPOIList(time, listOut, capacity, iterator, unk, int32Nodes, - xc_curTime, *x4_sourceInfo, x18_passedIntCount); - } - return 0; +s32 CAnimSourceReaderBase::VGetInt32POIState(const char* name) const { + for (const auto& node : x34_int32States) + if (!node.first.compare(name)) + return node.second; + return 0; } -u32 CAnimSourceReaderBase::VGetParticlePOIList(const CCharAnimTime& time, - CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - if (x4_sourceInfo->HasPOIData()) - { - const std::vector& particleNodes = x4_sourceInfo->GetParticlePOIStream(); - return _getPOIList(time, listOut, capacity, iterator, unk, particleNodes, - xc_curTime, *x4_sourceInfo, x1c_passedParticleCount); - } - return 0; +CParticleData::EParentedMode CAnimSourceReaderBase::VGetParticlePOIState(const char* name) const { + for (const auto& node : x44_particleStates) + if (!node.first.compare(name)) + return node.second; + return CParticleData::EParentedMode::Initial; } -u32 CAnimSourceReaderBase::VGetSoundPOIList(const CCharAnimTime& time, - CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - if (x4_sourceInfo->HasPOIData()) - { - const std::vector& soundNodes = x4_sourceInfo->GetSoundPOIStream(); - return _getPOIList(time, listOut, capacity, iterator, unk, soundNodes, - xc_curTime, *x4_sourceInfo, x20_passedSoundCount); - } - return 0; -} - -bool CAnimSourceReaderBase::VGetBoolPOIState(const char* name) const -{ - for (const auto& node : x24_boolStates) - if (!node.first.compare(name)) - return node.second; - return false; -} - -s32 CAnimSourceReaderBase::VGetInt32POIState(const char* name) const -{ - for (const auto& node : x34_int32States) - if (!node.first.compare(name)) - return node.second; - return 0; -} - -CParticleData::EParentedMode -CAnimSourceReaderBase::VGetParticlePOIState(const char* name) const -{ - for (const auto& node : x44_particleStates) - if (!node.first.compare(name)) - return node.second; - return CParticleData::EParentedMode::Initial; -} - -CAnimSourceReaderBase::CAnimSourceReaderBase(std::unique_ptr&& sourceInfo, - const CCharAnimTime& time) +CAnimSourceReaderBase::CAnimSourceReaderBase(std::unique_ptr&& sourceInfo, const CCharAnimTime& time) : x4_sourceInfo(std::move(sourceInfo)), xc_curTime(time) {} CAnimSourceReaderBase::CAnimSourceReaderBase(std::unique_ptr&& sourceInfo, const CAnimSourceReaderBase& other) -: x4_sourceInfo(std::move(sourceInfo)), - xc_curTime(other.xc_curTime), - x14_passedBoolCount(other.x14_passedBoolCount), - x18_passedIntCount(other.x18_passedIntCount), - x1c_passedParticleCount(other.x1c_passedParticleCount), - x20_passedSoundCount(other.x20_passedSoundCount), - x24_boolStates(other.x24_boolStates), - x34_int32States(other.x34_int32States), - x44_particleStates(other.x44_particleStates) -{} +: x4_sourceInfo(std::move(sourceInfo)) +, xc_curTime(other.xc_curTime) +, x14_passedBoolCount(other.x14_passedBoolCount) +, x18_passedIntCount(other.x18_passedIntCount) +, x1c_passedParticleCount(other.x1c_passedParticleCount) +, x20_passedSoundCount(other.x20_passedSoundCount) +, x24_boolStates(other.x24_boolStates) +, x34_int32States(other.x34_int32States) +, x44_particleStates(other.x44_particleStates) {} SAdvancementResults CAnimSourceReader::VGetAdvancementResults(const CCharAnimTime& dt, - const CCharAnimTime& startOff) const -{ - SAdvancementResults ret; - CCharAnimTime accum = xc_curTime + startOff; + const CCharAnimTime& startOff) const { + SAdvancementResults ret; + CCharAnimTime accum = xc_curTime + startOff; - if (xc_curTime + startOff >= x54_source->GetDuration()) - { - ret.x0_remTime = dt; - return ret; + if (xc_curTime + startOff >= x54_source->GetDuration()) { + ret.x0_remTime = dt; + return ret; + } else if (dt.EqualsZero()) { + return ret; + } else { + CCharAnimTime prevTime = accum; + accum += dt; + CCharAnimTime remTime; + if (accum > x54_source->GetDuration()) { + remTime = accum - x54_source->GetDuration(); + accum = x54_source->GetDuration(); } - else if (dt.EqualsZero()) - { - return ret; + + zeus::CQuaternion ra = x54_source->GetRotation(3, prevTime).inverse(); + zeus::CQuaternion rb = x54_source->GetRotation(3, accum); + ret.x0_remTime = remTime; + ret.x8_deltas.xc_rotDelta = rb * ra; + + if (x54_source->HasOffset(3)) { + zeus::CVector3f ta = x54_source->GetOffset(3, prevTime); + zeus::CVector3f tb = x54_source->GetOffset(3, accum); + ret.x8_deltas.x0_posDelta = zeus::CMatrix3f(rb) * (tb - ta); } - else - { - CCharAnimTime prevTime = accum; - accum += dt; - CCharAnimTime remTime; - if (accum > x54_source->GetDuration()) - { - remTime = accum - x54_source->GetDuration(); - accum = x54_source->GetDuration(); - } - zeus::CQuaternion ra = x54_source->GetRotation(3, prevTime).inverse(); - zeus::CQuaternion rb = x54_source->GetRotation(3, accum); - ret.x0_remTime = remTime; - ret.x8_deltas.xc_rotDelta = rb * ra; - - if (x54_source->HasOffset(3)) - { - zeus::CVector3f ta = x54_source->GetOffset(3, prevTime); - zeus::CVector3f tb = x54_source->GetOffset(3, accum); - ret.x8_deltas.x0_posDelta = zeus::CMatrix3f(rb) * (tb - ta); - } - - return ret; - } + return ret; + } } -void CAnimSourceReader::VSetPhase(float phase) -{ - xc_curTime = phase * x54_source->GetDuration().GetSeconds(); +void CAnimSourceReader::VSetPhase(float phase) { + xc_curTime = phase * x54_source->GetDuration().GetSeconds(); + if (x54_source->GetPOIData()) { + UpdatePOIStates(); + if (!xc_curTime.GreaterThanZero()) { + x14_passedBoolCount = 0; + x18_passedIntCount = 0; + x1c_passedParticleCount = 0; + x20_passedSoundCount = 0; + } + } +} + +SAdvancementResults CAnimSourceReader::VReverseView(const CCharAnimTime& dt) { + SAdvancementResults ret; + + if (xc_curTime.EqualsZero()) { + ret.x0_remTime = dt; + return ret; + } else if (dt.EqualsZero()) { + return ret; + } else { + CCharAnimTime prevTime = xc_curTime; + xc_curTime -= dt; + CCharAnimTime remTime; + if (xc_curTime < CCharAnimTime()) { + remTime = CCharAnimTime() - xc_curTime; + xc_curTime = CCharAnimTime(); + } + if (x54_source->GetPOIData()) - { - UpdatePOIStates(); - if (!xc_curTime.GreaterThanZero()) - { - x14_passedBoolCount = 0; - x18_passedIntCount = 0; - x1c_passedParticleCount = 0; - x20_passedSoundCount = 0; - } + UpdatePOIStates(); + + zeus::CQuaternion ra = x54_source->GetRotation(3, prevTime).inverse(); + zeus::CQuaternion rb = x54_source->GetRotation(3, xc_curTime); + ret.x0_remTime = remTime; + ret.x8_deltas.xc_rotDelta = rb * ra; + + if (x54_source->HasOffset(3)) { + zeus::CVector3f ta = x54_source->GetOffset(3, prevTime); + zeus::CVector3f tb = x54_source->GetOffset(3, xc_curTime); + ret.x8_deltas.x0_posDelta = zeus::CMatrix3f(rb) * (tb - ta); } + + return ret; + } } -SAdvancementResults CAnimSourceReader::VReverseView(const CCharAnimTime& dt) -{ - SAdvancementResults ret; +std::unique_ptr CAnimSourceReader::VClone() const { return std::make_unique(*this); } - if (xc_curTime.EqualsZero()) - { - ret.x0_remTime = dt; - return ret; +void CAnimSourceReader::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const { + x54_source->GetSegStatementSet(list, setOut, xc_curTime); +} + +void CAnimSourceReader::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, + const CCharAnimTime& time) const { + x54_source->GetSegStatementSet(list, setOut, time); +} + +SAdvancementResults CAnimSourceReader::VAdvanceView(const CCharAnimTime& dt) { + SAdvancementResults ret; + + if (xc_curTime >= x54_source->GetDuration()) { + ret.x0_remTime = dt; + return ret; + } else if (dt.EqualsZero()) { + return ret; + } else { + CCharAnimTime prevTime = xc_curTime; + xc_curTime += dt; + CCharAnimTime remTime; + if (xc_curTime > x54_source->GetDuration()) { + remTime = xc_curTime - x54_source->GetDuration(); + xc_curTime = x54_source->GetDuration(); } - else if (dt.EqualsZero()) - { - return ret; + + if (x54_source->GetPOIData()) + UpdatePOIStates(); + + zeus::CQuaternion ra = x54_source->GetRotation(3, prevTime).inverse(); + zeus::CQuaternion rb = x54_source->GetRotation(3, xc_curTime); + ret.x0_remTime = remTime; + ret.x8_deltas.xc_rotDelta = rb * ra; + + if (x54_source->HasOffset(3)) { + zeus::CVector3f ta = x54_source->GetOffset(3, prevTime); + zeus::CVector3f tb = x54_source->GetOffset(3, xc_curTime); + ret.x8_deltas.x0_posDelta = zeus::CMatrix3f(rb) * (tb - ta); } - else - { - CCharAnimTime prevTime = xc_curTime; - xc_curTime -= dt; - CCharAnimTime remTime; - if (xc_curTime < CCharAnimTime()) - { - remTime = CCharAnimTime() - xc_curTime; - xc_curTime = CCharAnimTime(); - } - if (x54_source->GetPOIData()) - UpdatePOIStates(); - - zeus::CQuaternion ra = x54_source->GetRotation(3, prevTime).inverse(); - zeus::CQuaternion rb = x54_source->GetRotation(3, xc_curTime); - ret.x0_remTime = remTime; - ret.x8_deltas.xc_rotDelta = rb * ra; - - if (x54_source->HasOffset(3)) - { - zeus::CVector3f ta = x54_source->GetOffset(3, prevTime); - zeus::CVector3f tb = x54_source->GetOffset(3, xc_curTime); - ret.x8_deltas.x0_posDelta = zeus::CMatrix3f(rb) * (tb - ta); - } - - return ret; - } + return ret; + } } -std::unique_ptr CAnimSourceReader::VClone() const -{ - return std::make_unique(*this); +CCharAnimTime CAnimSourceReader::VGetTimeRemaining() const { return x54_source->GetDuration() - xc_curTime; } + +CSteadyStateAnimInfo CAnimSourceReader::VGetSteadyStateAnimInfo() const { return x64_steadyStateInfo; } + +bool CAnimSourceReader::VHasOffset(const CSegId& seg) const { return x54_source->HasOffset(seg); } + +zeus::CVector3f CAnimSourceReader::VGetOffset(const CSegId& seg) const { + return x54_source->GetOffset(seg, xc_curTime); } -void CAnimSourceReader::VGetSegStatementSet(const CSegIdList& list, - CSegStatementSet& setOut) const -{ - x54_source->GetSegStatementSet(list, setOut, xc_curTime); +zeus::CVector3f CAnimSourceReader::VGetOffset(const CSegId& seg, const CCharAnimTime& time) const { + return x54_source->GetOffset(seg, time); } -void CAnimSourceReader::VGetSegStatementSet(const CSegIdList& list, - CSegStatementSet& setOut, - const CCharAnimTime& time) const -{ - x54_source->GetSegStatementSet(list, setOut, time); +zeus::CQuaternion CAnimSourceReader::VGetRotation(const CSegId& seg) const { + return x54_source->GetRotation(seg, xc_curTime); } -SAdvancementResults CAnimSourceReader::VAdvanceView(const CCharAnimTime& dt) -{ - SAdvancementResults ret; - - if (xc_curTime >= x54_source->GetDuration()) - { - ret.x0_remTime = dt; - return ret; - } - else if (dt.EqualsZero()) - { - return ret; - } - else - { - CCharAnimTime prevTime = xc_curTime; - xc_curTime += dt; - CCharAnimTime remTime; - if (xc_curTime > x54_source->GetDuration()) - { - remTime = xc_curTime - x54_source->GetDuration(); - xc_curTime = x54_source->GetDuration(); - } - - if (x54_source->GetPOIData()) - UpdatePOIStates(); - - zeus::CQuaternion ra = x54_source->GetRotation(3, prevTime).inverse(); - zeus::CQuaternion rb = x54_source->GetRotation(3, xc_curTime); - ret.x0_remTime = remTime; - ret.x8_deltas.xc_rotDelta = rb * ra; - - if (x54_source->HasOffset(3)) - { - zeus::CVector3f ta = x54_source->GetOffset(3, prevTime); - zeus::CVector3f tb = x54_source->GetOffset(3, xc_curTime); - ret.x8_deltas.x0_posDelta = zeus::CMatrix3f(rb) * (tb - ta); - } - - return ret; - } -} - -CCharAnimTime CAnimSourceReader::VGetTimeRemaining() const -{ - return x54_source->GetDuration() - xc_curTime; -} - -CSteadyStateAnimInfo CAnimSourceReader::VGetSteadyStateAnimInfo() const -{ - return x64_steadyStateInfo; -} - -bool CAnimSourceReader::VHasOffset(const CSegId& seg) const -{ - return x54_source->HasOffset(seg); -} - -zeus::CVector3f CAnimSourceReader::VGetOffset(const CSegId& seg) const -{ - return x54_source->GetOffset(seg, xc_curTime); -} - -zeus::CVector3f CAnimSourceReader::VGetOffset(const CSegId& seg, - const CCharAnimTime& time) const -{ - return x54_source->GetOffset(seg, time); -} - -zeus::CQuaternion CAnimSourceReader::VGetRotation(const CSegId& seg) const -{ - return x54_source->GetRotation(seg, xc_curTime); -} - -CAnimSourceReader::CAnimSourceReader(const TSubAnimTypeToken& source, - const CCharAnimTime& time) -: CAnimSourceReaderBase(std::make_unique(source), {}), - x54_source(source), x64_steadyStateInfo(false, source->GetDuration(), - source->GetOffset(source->GetRootBoneId(), time)) -{ - PostConstruct(time); +CAnimSourceReader::CAnimSourceReader(const TSubAnimTypeToken& source, const CCharAnimTime& time) +: CAnimSourceReaderBase(std::make_unique(source), {}) +, x54_source(source) +, x64_steadyStateInfo(false, source->GetDuration(), source->GetOffset(source->GetRootBoneId(), time)) { + PostConstruct(time); } CAnimSourceReader::CAnimSourceReader(const CAnimSourceReader& other) -: CAnimSourceReaderBase(std::make_unique(other.x54_source), other), - x54_source(other.x54_source), x64_steadyStateInfo(other.x64_steadyStateInfo) -{} +: CAnimSourceReaderBase(std::make_unique(other.x54_source), other) +, x54_source(other.x54_source) +, x64_steadyStateInfo(other.x64_steadyStateInfo) {} - -} +} // namespace urde diff --git a/Runtime/Character/CAnimSourceReader.hpp b/Runtime/Character/CAnimSourceReader.hpp index 752dd7d8c..ef20458b4 100644 --- a/Runtime/Character/CAnimSourceReader.hpp +++ b/Runtime/Character/CAnimSourceReader.hpp @@ -5,99 +5,94 @@ #include "CAnimSource.hpp" #include "CParticleData.hpp" -namespace urde -{ +namespace urde { -class IAnimSourceInfo -{ +class IAnimSourceInfo { public: - virtual ~IAnimSourceInfo() = default; - virtual bool HasPOIData() const=0; - virtual const std::vector& GetBoolPOIStream() const=0; - virtual const std::vector& GetInt32POIStream() const=0; - virtual const std::vector& GetParticlePOIStream() const=0; - virtual const std::vector& GetSoundPOIStream() const=0; - virtual CCharAnimTime GetAnimationDuration() const=0; + virtual ~IAnimSourceInfo() = default; + virtual bool HasPOIData() const = 0; + virtual const std::vector& GetBoolPOIStream() const = 0; + virtual const std::vector& GetInt32POIStream() const = 0; + virtual const std::vector& GetParticlePOIStream() const = 0; + virtual const std::vector& GetSoundPOIStream() const = 0; + virtual CCharAnimTime GetAnimationDuration() const = 0; }; -class CAnimSourceInfo : public IAnimSourceInfo -{ - TSubAnimTypeToken x4_token; +class CAnimSourceInfo : public IAnimSourceInfo { + TSubAnimTypeToken x4_token; + public: - CAnimSourceInfo(const TSubAnimTypeToken& token); - bool HasPOIData() const; - const std::vector& GetBoolPOIStream() const; - const std::vector& GetInt32POIStream() const; - const std::vector& GetParticlePOIStream() const; - const std::vector& GetSoundPOIStream() const; - CCharAnimTime GetAnimationDuration() const; + CAnimSourceInfo(const TSubAnimTypeToken& token); + bool HasPOIData() const; + const std::vector& GetBoolPOIStream() const; + const std::vector& GetInt32POIStream() const; + const std::vector& GetParticlePOIStream() const; + const std::vector& GetSoundPOIStream() const; + CCharAnimTime GetAnimationDuration() const; }; -class CAnimSourceReaderBase : public IAnimReader -{ +class CAnimSourceReaderBase : public IAnimReader { protected: - std::unique_ptr x4_sourceInfo; - CCharAnimTime xc_curTime; - u32 x14_passedBoolCount = 0; - u32 x18_passedIntCount = 0; - u32 x1c_passedParticleCount = 0; - u32 x20_passedSoundCount = 0; - std::vector> x24_boolStates; - std::vector> x34_int32States; - std::vector> x44_particleStates; + std::unique_ptr x4_sourceInfo; + CCharAnimTime xc_curTime; + u32 x14_passedBoolCount = 0; + u32 x18_passedIntCount = 0; + u32 x1c_passedParticleCount = 0; + u32 x20_passedSoundCount = 0; + std::vector> x24_boolStates; + std::vector> x34_int32States; + std::vector> x44_particleStates; - std::set> GetUniqueParticlePOIs() const; - std::set> GetUniqueInt32POIs() const; - std::set> GetUniqueBoolPOIs() const; + std::set> GetUniqueParticlePOIs() const; + std::set> GetUniqueInt32POIs() const; + std::set> GetUniqueBoolPOIs() const; protected: - void PostConstruct(const CCharAnimTime& time); - void UpdatePOIStates(); - CAnimSourceReaderBase(std::unique_ptr&& sourceInfo, - const CAnimSourceReaderBase& other); + void PostConstruct(const CCharAnimTime& time); + void UpdatePOIStates(); + CAnimSourceReaderBase(std::unique_ptr&& sourceInfo, const CAnimSourceReaderBase& other); + public: - CAnimSourceReaderBase(std::unique_ptr&& sourceInfo, - const CCharAnimTime& time); + CAnimSourceReaderBase(std::unique_ptr&& sourceInfo, const CCharAnimTime& time); - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; - bool VGetBoolPOIState(const char* name) const; - s32 VGetInt32POIState(const char* name) const; - CParticleData::EParentedMode VGetParticlePOIState(const char* name) const; + u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + bool VGetBoolPOIState(const char* name) const; + s32 VGetInt32POIState(const char* name) const; + CParticleData::EParentedMode VGetParticlePOIState(const char* name) const; - using IAnimReader::VGetOffset; - virtual zeus::CVector3f VGetOffset(const CSegId& seg, const CCharAnimTime& b) const=0; - virtual bool VSupportsReverseView() const=0; - virtual SAdvancementResults VReverseView(const CCharAnimTime& time)=0; + using IAnimReader::VGetOffset; + virtual zeus::CVector3f VGetOffset(const CSegId& seg, const CCharAnimTime& b) const = 0; + virtual bool VSupportsReverseView() const = 0; + virtual SAdvancementResults VReverseView(const CCharAnimTime& time) = 0; - const CCharAnimTime& GetCurTime() const { return xc_curTime; } + const CCharAnimTime& GetCurTime() const { return xc_curTime; } }; -class CAnimSourceReader : public CAnimSourceReaderBase -{ - TSubAnimTypeToken x54_source; - CSteadyStateAnimInfo x64_steadyStateInfo; -public: - CAnimSourceReader(const TSubAnimTypeToken& source, const CCharAnimTime& time); - CAnimSourceReader(const CAnimSourceReader& other); +class CAnimSourceReader : public CAnimSourceReaderBase { + TSubAnimTypeToken x54_source; + CSteadyStateAnimInfo x64_steadyStateInfo; - SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; - bool VSupportsReverseView() const {return true;} - void VSetPhase(float); - SAdvancementResults VReverseView(const CCharAnimTime& time); - std::unique_ptr VClone() const; - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; - SAdvancementResults VAdvanceView(const CCharAnimTime& a); - CCharAnimTime VGetTimeRemaining() const; - CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; - bool VHasOffset(const CSegId& seg) const; - zeus::CVector3f VGetOffset(const CSegId& seg) const; - zeus::CVector3f VGetOffset(const CSegId& seg, const CCharAnimTime& time) const; - zeus::CQuaternion VGetRotation(const CSegId& seg) const; +public: + CAnimSourceReader(const TSubAnimTypeToken& source, const CCharAnimTime& time); + CAnimSourceReader(const CAnimSourceReader& other); + + SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; + bool VSupportsReverseView() const { return true; } + void VSetPhase(float); + SAdvancementResults VReverseView(const CCharAnimTime& time); + std::unique_ptr VClone() const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; + SAdvancementResults VAdvanceView(const CCharAnimTime& a); + CCharAnimTime VGetTimeRemaining() const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + bool VHasOffset(const CSegId& seg) const; + zeus::CVector3f VGetOffset(const CSegId& seg) const; + zeus::CVector3f VGetOffset(const CSegId& seg, const CCharAnimTime& time) const; + zeus::CQuaternion VGetRotation(const CSegId& seg) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimSysContext.hpp b/Runtime/Character/CAnimSysContext.hpp index 2a8d8a623..28bfb4472 100644 --- a/Runtime/Character/CAnimSysContext.hpp +++ b/Runtime/Character/CAnimSysContext.hpp @@ -3,23 +3,17 @@ #include "CToken.hpp" #include "CRandom16.hpp" -namespace urde -{ +namespace urde { class CTransitionDatabaseGame; class CSimplePool; -struct CAnimSysContext -{ - TToken x0_transDB; - std::shared_ptr x8_random; - CSimplePool& xc_store; +struct CAnimSysContext { + TToken x0_transDB; + std::shared_ptr x8_random; + CSimplePool& xc_store; - CAnimSysContext(const TToken& transDB, - u32 randomSeed, CSimplePool& store) - : x0_transDB(transDB), - x8_random(std::make_shared(randomSeed)), - xc_store(store) {} + CAnimSysContext(const TToken& transDB, u32 randomSeed, CSimplePool& store) + : x0_transDB(transDB), x8_random(std::make_shared(randomSeed)), xc_store(store) {} }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeAnimReaderContainer.cpp b/Runtime/Character/CAnimTreeAnimReaderContainer.cpp index 3cd704d93..bb1556df2 100644 --- a/Runtime/Character/CAnimTreeAnimReaderContainer.cpp +++ b/Runtime/Character/CAnimTreeAnimReaderContainer.cpp @@ -1,139 +1,99 @@ #include "CAnimTreeAnimReaderContainer.hpp" #include "CFBStreamedAnimReader.hpp" -namespace urde -{ +namespace urde { -CAnimTreeAnimReaderContainer::CAnimTreeAnimReaderContainer(std::string_view name, - std::shared_ptr reader, +CAnimTreeAnimReaderContainer::CAnimTreeAnimReaderContainer(std::string_view name, std::shared_ptr reader, u32 dbIdx) -: CAnimTreeNode(name), x14_reader(reader), x1c_animDbIdx(dbIdx) -{ +: CAnimTreeNode(name), x14_reader(reader), x1c_animDbIdx(dbIdx) {} + +u32 CAnimTreeAnimReaderContainer::Depth() const { return 1; } + +CAnimTreeEffectiveContribution CAnimTreeAnimReaderContainer::VGetContributionOfHighestInfluence() const { + return {1.f, x4_name, VGetSteadyStateAnimInfo(), VGetTimeRemaining(), x1c_animDbIdx}; } -u32 CAnimTreeAnimReaderContainer::Depth() const -{ - return 1; +u32 CAnimTreeAnimReaderContainer::VGetNumChildren() const { return 0; } + +std::shared_ptr CAnimTreeAnimReaderContainer::VGetBestUnblendedChild() const { return {}; } + +SAdvancementResults CAnimTreeAnimReaderContainer::VAdvanceView(const CCharAnimTime& dt) { + return x14_reader->VAdvanceView(dt); } -CAnimTreeEffectiveContribution CAnimTreeAnimReaderContainer::VGetContributionOfHighestInfluence() const -{ - return {1.f, x4_name, VGetSteadyStateAnimInfo(), VGetTimeRemaining(), x1c_animDbIdx}; +CCharAnimTime CAnimTreeAnimReaderContainer::VGetTimeRemaining() const { return x14_reader->VGetTimeRemaining(); } + +CSteadyStateAnimInfo CAnimTreeAnimReaderContainer::VGetSteadyStateAnimInfo() const { + return x14_reader->VGetSteadyStateAnimInfo(); } -u32 CAnimTreeAnimReaderContainer::VGetNumChildren() const -{ - return 0; +bool CAnimTreeAnimReaderContainer::VHasOffset(const CSegId& seg) const { return x14_reader->VHasOffset(seg); } + +zeus::CVector3f CAnimTreeAnimReaderContainer::VGetOffset(const CSegId& seg) const { + return x14_reader->VGetOffset(seg); } -std::shared_ptr CAnimTreeAnimReaderContainer::VGetBestUnblendedChild() const -{ - return {}; +zeus::CQuaternion CAnimTreeAnimReaderContainer::VGetRotation(const CSegId& seg) const { + return x14_reader->VGetRotation(seg); } -SAdvancementResults CAnimTreeAnimReaderContainer::VAdvanceView(const CCharAnimTime& dt) -{ - return x14_reader->VAdvanceView(dt); +u32 CAnimTreeAnimReaderContainer::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + return x14_reader->GetBoolPOIList(time, listOut, capacity, iterator, unk); } -CCharAnimTime CAnimTreeAnimReaderContainer::VGetTimeRemaining() const -{ - return x14_reader->VGetTimeRemaining(); -} - -CSteadyStateAnimInfo CAnimTreeAnimReaderContainer::VGetSteadyStateAnimInfo() const -{ - return x14_reader->VGetSteadyStateAnimInfo(); -} - -bool CAnimTreeAnimReaderContainer::VHasOffset(const CSegId& seg) const -{ - return x14_reader->VHasOffset(seg); -} - -zeus::CVector3f CAnimTreeAnimReaderContainer::VGetOffset(const CSegId& seg) const -{ - return x14_reader->VGetOffset(seg); -} - -zeus::CQuaternion CAnimTreeAnimReaderContainer::VGetRotation(const CSegId& seg) const -{ - return x14_reader->VGetRotation(seg); -} - -u32 CAnimTreeAnimReaderContainer::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return x14_reader->GetBoolPOIList(time, listOut, capacity, iterator, unk); -} - -u32 CAnimTreeAnimReaderContainer::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return x14_reader->GetInt32POIList(time, listOut, capacity, iterator, unk); +u32 CAnimTreeAnimReaderContainer::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + return x14_reader->GetInt32POIList(time, listOut, capacity, iterator, unk); } u32 CAnimTreeAnimReaderContainer::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return x14_reader->GetParticlePOIList(time, listOut, capacity, iterator, unk); + u32 capacity, u32 iterator, u32 unk) const { + return x14_reader->GetParticlePOIList(time, listOut, capacity, iterator, unk); } -u32 CAnimTreeAnimReaderContainer::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return x14_reader->GetSoundPOIList(time, listOut, capacity, iterator, unk); +u32 CAnimTreeAnimReaderContainer::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + return x14_reader->GetSoundPOIList(time, listOut, capacity, iterator, unk); } -bool CAnimTreeAnimReaderContainer::VGetBoolPOIState(const char* name) const -{ - return x14_reader->VGetBoolPOIState(name); +bool CAnimTreeAnimReaderContainer::VGetBoolPOIState(const char* name) const { + return x14_reader->VGetBoolPOIState(name); } -s32 CAnimTreeAnimReaderContainer::VGetInt32POIState(const char* name) const -{ - return x14_reader->VGetBoolPOIState(name); +s32 CAnimTreeAnimReaderContainer::VGetInt32POIState(const char* name) const { + return x14_reader->VGetBoolPOIState(name); } -CParticleData::EParentedMode CAnimTreeAnimReaderContainer::VGetParticlePOIState(const char* name) const -{ - return x14_reader->VGetParticlePOIState(name); +CParticleData::EParentedMode CAnimTreeAnimReaderContainer::VGetParticlePOIState(const char* name) const { + return x14_reader->VGetParticlePOIState(name); } -void CAnimTreeAnimReaderContainer::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const -{ - return x14_reader->VGetSegStatementSet(list, setOut); +void CAnimTreeAnimReaderContainer::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const { + return x14_reader->VGetSegStatementSet(list, setOut); } -void CAnimTreeAnimReaderContainer::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const -{ - return x14_reader->VGetSegStatementSet(list, setOut, time); +void CAnimTreeAnimReaderContainer::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, + const CCharAnimTime& time) const { + return x14_reader->VGetSegStatementSet(list, setOut, time); } -std::unique_ptr CAnimTreeAnimReaderContainer::VClone() const -{ - return std::make_unique(x4_name, x14_reader->Clone(), x1c_animDbIdx); +std::unique_ptr CAnimTreeAnimReaderContainer::VClone() const { + return std::make_unique(x4_name, x14_reader->Clone(), x1c_animDbIdx); } -std::experimental::optional> CAnimTreeAnimReaderContainer::VSimplified() -{ - return {}; -} +std::experimental::optional> CAnimTreeAnimReaderContainer::VSimplified() { return {}; } -void CAnimTreeAnimReaderContainer::VSetPhase(float ph) -{ - x14_reader->VSetPhase(ph); -} +void CAnimTreeAnimReaderContainer::VSetPhase(float ph) { x14_reader->VSetPhase(ph); } -SAdvancementResults CAnimTreeAnimReaderContainer::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const -{ - return x14_reader->VGetAdvancementResults(a, b); +SAdvancementResults CAnimTreeAnimReaderContainer::VGetAdvancementResults(const CCharAnimTime& a, + const CCharAnimTime& b) const { + return x14_reader->VGetAdvancementResults(a, b); } void CAnimTreeAnimReaderContainer::VGetWeightedReaders( - rstl::reserved_vector>, 16>& out, float w) const -{ - out.emplace_back(std::make_pair(w, x14_reader)); + rstl::reserved_vector>, 16>& out, float w) const { + out.emplace_back(std::make_pair(w, x14_reader)); } -} +} // namespace urde diff --git a/Runtime/Character/CAnimTreeAnimReaderContainer.hpp b/Runtime/Character/CAnimTreeAnimReaderContainer.hpp index 01f08168e..a139840a5 100644 --- a/Runtime/Character/CAnimTreeAnimReaderContainer.hpp +++ b/Runtime/Character/CAnimTreeAnimReaderContainer.hpp @@ -2,44 +2,40 @@ #include "CAnimTreeNode.hpp" -namespace urde -{ +namespace urde { + +class CAnimTreeAnimReaderContainer : public CAnimTreeNode { + std::shared_ptr x14_reader; + u32 x1c_animDbIdx; -class CAnimTreeAnimReaderContainer : public CAnimTreeNode -{ - std::shared_ptr x14_reader; - u32 x1c_animDbIdx; public: - CAnimTreeAnimReaderContainer(std::string_view name, - std::shared_ptr reader, - u32 animDbIdx); + CAnimTreeAnimReaderContainer(std::string_view name, std::shared_ptr reader, u32 animDbIdx); - u32 Depth() const; - CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; - u32 VGetNumChildren() const; - std::shared_ptr VGetBestUnblendedChild() const; - void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const; + u32 Depth() const; + CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; + u32 VGetNumChildren() const; + std::shared_ptr VGetBestUnblendedChild() const; + void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const; - SAdvancementResults VAdvanceView(const CCharAnimTime& a); - CCharAnimTime VGetTimeRemaining() const; - CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; - bool VHasOffset(const CSegId& seg) const; - zeus::CVector3f VGetOffset(const CSegId& seg) const; - zeus::CQuaternion VGetRotation(const CSegId& seg) const; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; - bool VGetBoolPOIState(const char*) const; - s32 VGetInt32POIState(const char*) const; - CParticleData::EParentedMode VGetParticlePOIState(const char*) const; - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; - std::unique_ptr VClone() const; - std::experimental::optional> VSimplified(); - void VSetPhase(float); - SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; + SAdvancementResults VAdvanceView(const CCharAnimTime& a); + CCharAnimTime VGetTimeRemaining() const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + bool VHasOffset(const CSegId& seg) const; + zeus::CVector3f VGetOffset(const CSegId& seg) const; + zeus::CQuaternion VGetRotation(const CSegId& seg) const; + u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + bool VGetBoolPOIState(const char*) const; + s32 VGetInt32POIState(const char*) const; + CParticleData::EParentedMode VGetParticlePOIState(const char*) const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; + std::unique_ptr VClone() const; + std::experimental::optional> VSimplified(); + void VSetPhase(float); + SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeBlend.cpp b/Runtime/Character/CAnimTreeBlend.cpp index e82b85063..620476b67 100644 --- a/Runtime/Character/CAnimTreeBlend.cpp +++ b/Runtime/Character/CAnimTreeBlend.cpp @@ -1,98 +1,66 @@ #include "CAnimTreeBlend.hpp" -namespace urde -{ +namespace urde { std::string CAnimTreeBlend::CreatePrimitiveName(const std::shared_ptr& a, - const std::shared_ptr& b, - float scale) -{ - return ""; + const std::shared_ptr& b, float scale) { + return ""; } -CAnimTreeBlend::CAnimTreeBlend(bool b1, - const std::shared_ptr& a, - const std::shared_ptr& b, - float blendWeight, std::string_view name) -: CAnimTreeTweenBase(b1, a, b, 1 | 2, name), x24_blendWeight(blendWeight) -{ +CAnimTreeBlend::CAnimTreeBlend(bool b1, const std::shared_ptr& a, + const std::shared_ptr& b, float blendWeight, std::string_view name) +: CAnimTreeTweenBase(b1, a, b, 1 | 2, name), x24_blendWeight(blendWeight) {} -} - -SAdvancementResults CAnimTreeBlend::VAdvanceView(const CCharAnimTime& dt) -{ - IncAdvancementDepth(); - SAdvancementResults resA = x14_a->VAdvanceView(dt); - SAdvancementResults resB = x18_b->VAdvanceView(dt); - DecAdvancementDepth(); - if (ShouldCullTree()) - { - if (GetBlendingWeight() < 0.5f) - x20_25_cullSelector = 1; - else - x20_25_cullSelector = 2; - } - - const SAdvancementResults& maxRemTime = (resA.x0_remTime < resB.x0_remTime) ? resB : resA; - if (x1c_flags & 0x1) - { - return {maxRemTime.x0_remTime, SAdvancementDeltas::Blend(resA.x8_deltas, resB.x8_deltas, - GetBlendingWeight())}; - } +SAdvancementResults CAnimTreeBlend::VAdvanceView(const CCharAnimTime& dt) { + IncAdvancementDepth(); + SAdvancementResults resA = x14_a->VAdvanceView(dt); + SAdvancementResults resB = x18_b->VAdvanceView(dt); + DecAdvancementDepth(); + if (ShouldCullTree()) { + if (GetBlendingWeight() < 0.5f) + x20_25_cullSelector = 1; else - { - return resB; - } + x20_25_cullSelector = 2; + } + + const SAdvancementResults& maxRemTime = (resA.x0_remTime < resB.x0_remTime) ? resB : resA; + if (x1c_flags & 0x1) { + return {maxRemTime.x0_remTime, SAdvancementDeltas::Blend(resA.x8_deltas, resB.x8_deltas, GetBlendingWeight())}; + } else { + return resB; + } } -CCharAnimTime CAnimTreeBlend::VGetTimeRemaining() const -{ - CCharAnimTime remA = x14_a->VGetTimeRemaining(); - CCharAnimTime remB = x18_b->VGetTimeRemaining(); - return (remA < remB) ? remB : remA; +CCharAnimTime CAnimTreeBlend::VGetTimeRemaining() const { + CCharAnimTime remA = x14_a->VGetTimeRemaining(); + CCharAnimTime remB = x18_b->VGetTimeRemaining(); + return (remA < remB) ? remB : remA; } -CSteadyStateAnimInfo CAnimTreeBlend::VGetSteadyStateAnimInfo() const -{ - CSteadyStateAnimInfo ssA = x14_a->VGetSteadyStateAnimInfo(); - CSteadyStateAnimInfo ssB = x18_b->VGetSteadyStateAnimInfo(); - zeus::CVector3f resOffset; - if (ssA.GetDuration() < ssB.GetDuration()) - { - resOffset = ssA.GetOffset() * (ssB.GetDuration() / ssA.GetDuration()) * x24_blendWeight + - ssB.GetOffset() * (1.f - x24_blendWeight); - } - else if (ssB.GetDuration() < ssA.GetDuration()) - { - resOffset = ssA.GetOffset() * x24_blendWeight + - ssB.GetOffset() * (ssA.GetDuration() / ssB.GetDuration()) * (1.f - x24_blendWeight); - } - else - { - resOffset = ssA.GetOffset() + ssB.GetOffset(); - } +CSteadyStateAnimInfo CAnimTreeBlend::VGetSteadyStateAnimInfo() const { + CSteadyStateAnimInfo ssA = x14_a->VGetSteadyStateAnimInfo(); + CSteadyStateAnimInfo ssB = x18_b->VGetSteadyStateAnimInfo(); + zeus::CVector3f resOffset; + if (ssA.GetDuration() < ssB.GetDuration()) { + resOffset = ssA.GetOffset() * (ssB.GetDuration() / ssA.GetDuration()) * x24_blendWeight + + ssB.GetOffset() * (1.f - x24_blendWeight); + } else if (ssB.GetDuration() < ssA.GetDuration()) { + resOffset = ssA.GetOffset() * x24_blendWeight + + ssB.GetOffset() * (ssA.GetDuration() / ssB.GetDuration()) * (1.f - x24_blendWeight); + } else { + resOffset = ssA.GetOffset() + ssB.GetOffset(); + } - return {ssA.IsLooping(), - (ssA.GetDuration() < ssB.GetDuration()) ? ssB.GetDuration() : ssA.GetDuration(), - resOffset}; + return {ssA.IsLooping(), (ssA.GetDuration() < ssB.GetDuration()) ? ssB.GetDuration() : ssA.GetDuration(), resOffset}; } -std::unique_ptr CAnimTreeBlend::VClone() const -{ - return std::make_unique(x20_24_b1, - CAnimTreeNode::Cast(x14_a->Clone()), - CAnimTreeNode::Cast(x18_b->Clone()), - x24_blendWeight, x4_name); +std::unique_ptr CAnimTreeBlend::VClone() const { + return std::make_unique(x20_24_b1, CAnimTreeNode::Cast(x14_a->Clone()), + CAnimTreeNode::Cast(x18_b->Clone()), x24_blendWeight, x4_name); } -void CAnimTreeBlend::SetBlendingWeight(float w) -{ - x24_blendWeight = w; -} +void CAnimTreeBlend::SetBlendingWeight(float w) { x24_blendWeight = w; } -float CAnimTreeBlend::VGetBlendingWeight() const -{ - return x24_blendWeight; -} +float CAnimTreeBlend::VGetBlendingWeight() const { return x24_blendWeight; } -} +} // namespace urde diff --git a/Runtime/Character/CAnimTreeBlend.hpp b/Runtime/Character/CAnimTreeBlend.hpp index d036afd3c..fb0a8a4b5 100644 --- a/Runtime/Character/CAnimTreeBlend.hpp +++ b/Runtime/Character/CAnimTreeBlend.hpp @@ -2,29 +2,24 @@ #include "CAnimTreeTweenBase.hpp" -namespace urde -{ +namespace urde { + +class CAnimTreeBlend : public CAnimTreeTweenBase { + float x24_blendWeight; -class CAnimTreeBlend : public CAnimTreeTweenBase -{ - float x24_blendWeight; public: - static std::string CreatePrimitiveName(const std::shared_ptr& a, - const std::shared_ptr& b, - float scale); + static std::string CreatePrimitiveName(const std::shared_ptr& a, + const std::shared_ptr& b, float scale); - CAnimTreeBlend(bool, - const std::shared_ptr& a, - const std::shared_ptr& b, - float blendWeight, std::string_view name); + CAnimTreeBlend(bool, const std::shared_ptr& a, const std::shared_ptr& b, + float blendWeight, std::string_view name); - SAdvancementResults VAdvanceView(const CCharAnimTime& dt); - CCharAnimTime VGetTimeRemaining() const; - CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; - std::unique_ptr VClone() const; - void SetBlendingWeight(float w); - float VGetBlendingWeight() const; + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); + CCharAnimTime VGetTimeRemaining() const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + std::unique_ptr VClone() const; + void SetBlendingWeight(float w); + float VGetBlendingWeight() const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeDoubleChild.cpp b/Runtime/Character/CAnimTreeDoubleChild.cpp index 1d07d1f1e..77c9fd84e 100644 --- a/Runtime/Character/CAnimTreeDoubleChild.cpp +++ b/Runtime/Character/CAnimTreeDoubleChild.cpp @@ -1,190 +1,156 @@ #include "CAnimTreeDoubleChild.hpp" -namespace urde -{ +namespace urde { -CAnimTreeDoubleChild::CAnimTreeDoubleChild(const std::weak_ptr& a, - const std::weak_ptr& b, +CAnimTreeDoubleChild::CAnimTreeDoubleChild(const std::weak_ptr& a, const std::weak_ptr& b, std::string_view name) -: CAnimTreeNode(name), x14_a(a.lock()), x18_b(b.lock()) -{ -} +: CAnimTreeNode(name), x14_a(a.lock()), x18_b(b.lock()) {} CAnimTreeDoubleChild::CDoubleChildAdvancementResult -CAnimTreeDoubleChild::AdvanceViewBothChildren(const CCharAnimTime& time, bool runLeft, bool loopLeft) -{ - CCharAnimTime lRemTime = time; - CCharAnimTime totalTime; - if (!runLeft) - totalTime = CCharAnimTime(); - else if (loopLeft) - totalTime = CCharAnimTime::Infinity(); - else +CAnimTreeDoubleChild::AdvanceViewBothChildren(const CCharAnimTime& time, bool runLeft, bool loopLeft) { + CCharAnimTime lRemTime = time; + CCharAnimTime totalTime; + if (!runLeft) + totalTime = CCharAnimTime(); + else if (loopLeft) + totalTime = CCharAnimTime::Infinity(); + else + totalTime = x14_a->VGetTimeRemaining(); + + SAdvancementDeltas leftDeltas, rightDeltas; + CCharAnimTime rRemTime = time; + if (time.GreaterThanZero()) { + while (lRemTime.GreaterThanZero() && !lRemTime.EpsilonZero() && totalTime.GreaterThanZero() && + (loopLeft || !totalTime.EpsilonZero())) { + SAdvancementResults res = x14_a->VAdvanceView(lRemTime); + auto simp = x14_a->Simplified(); + if (simp) + x14_a = CAnimTreeNode::Cast(std::move(*simp)); + leftDeltas.x0_posDelta += res.x8_deltas.x0_posDelta; + leftDeltas.xc_rotDelta = leftDeltas.xc_rotDelta * res.x8_deltas.xc_rotDelta; + if (!loopLeft) totalTime = x14_a->VGetTimeRemaining(); - - SAdvancementDeltas leftDeltas, rightDeltas; - CCharAnimTime rRemTime = time; - if (time.GreaterThanZero()) - { - while (lRemTime.GreaterThanZero() && !lRemTime.EpsilonZero() && - totalTime.GreaterThanZero() && (loopLeft || !totalTime.EpsilonZero())) - { - SAdvancementResults res = x14_a->VAdvanceView(lRemTime); - auto simp = x14_a->Simplified(); - if (simp) - x14_a = CAnimTreeNode::Cast(std::move(*simp)); - leftDeltas.x0_posDelta += res.x8_deltas.x0_posDelta; - leftDeltas.xc_rotDelta = leftDeltas.xc_rotDelta * res.x8_deltas.xc_rotDelta; - if (!loopLeft) - totalTime = x14_a->VGetTimeRemaining(); - lRemTime = res.x0_remTime; - } - - while (rRemTime.GreaterThanZero() && !rRemTime.EpsilonZero()) - { - SAdvancementResults res = x18_b->VAdvanceView(rRemTime); - auto simp = x18_b->Simplified(); - if (simp) - x18_b = CAnimTreeNode::Cast(std::move(*simp)); - rightDeltas.x0_posDelta += res.x8_deltas.x0_posDelta; - rightDeltas.xc_rotDelta = rightDeltas.xc_rotDelta * res.x8_deltas.xc_rotDelta; - rRemTime = res.x0_remTime; - } + lRemTime = res.x0_remTime; } - return {time, leftDeltas, rightDeltas}; -} - -SAdvancementResults CAnimTreeDoubleChild::VAdvanceView(const CCharAnimTime& a) -{ - SAdvancementResults resA = x14_a->VAdvanceView(a); - SAdvancementResults resB = x14_a->VAdvanceView(a); - return (resA.x0_remTime > resB.x0_remTime) ? resA : resB; -} - -u32 CAnimTreeDoubleChild::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - u32 newCapacity = x14_a->GetBoolPOIList(time, listOut, capacity, iterator, unk); - newCapacity += x18_b->GetBoolPOIList(time, listOut, capacity, newCapacity + iterator, unk); - if (newCapacity > capacity) - newCapacity = capacity; - - std::sort(listOut, listOut + newCapacity); - - return newCapacity; -} - -u32 CAnimTreeDoubleChild::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - u32 newCapacity = x14_a->GetInt32POIList(time, listOut, capacity, iterator, unk); - newCapacity += x18_b->GetInt32POIList(time, listOut, capacity, newCapacity + iterator, unk); - if (newCapacity > capacity) - newCapacity = capacity; - - std::sort(listOut, listOut + newCapacity); - - return newCapacity; -} - -u32 CAnimTreeDoubleChild::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - u32 newCapacity = x14_a->GetParticlePOIList(time, listOut, capacity, iterator, unk); - newCapacity += x18_b->GetParticlePOIList(time, listOut, capacity, newCapacity + iterator, unk); - if (newCapacity > capacity) - newCapacity = capacity; - - std::sort(listOut, listOut + newCapacity); - - return newCapacity; -} - -u32 CAnimTreeDoubleChild::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - u32 newCapacity = x14_a->GetSoundPOIList(time, listOut, capacity, iterator, unk); - newCapacity += x18_b->GetSoundPOIList(time, listOut, capacity, newCapacity + iterator, unk); - if (newCapacity > capacity) - newCapacity = capacity; - - std::sort(listOut, listOut + newCapacity); - - return newCapacity; -} - -bool CAnimTreeDoubleChild::VGetBoolPOIState(const char* name) const -{ - return x18_b->VGetBoolPOIState(name); -} - -s32 CAnimTreeDoubleChild::VGetInt32POIState(const char* name) const -{ - return x18_b->VGetBoolPOIState(name); -} - -CParticleData::EParentedMode CAnimTreeDoubleChild::VGetParticlePOIState(const char* name) const -{ - return x18_b->VGetParticlePOIState(name); -} - -void CAnimTreeDoubleChild::VSetPhase(float phase) -{ - x14_a->VSetPhase(phase); - x18_b->VSetPhase(phase); -} - -SAdvancementResults CAnimTreeDoubleChild::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const -{ - SAdvancementResults resA = x14_a->VGetAdvancementResults(a, b); - SAdvancementResults resB = x18_b->VGetAdvancementResults(a, b); - return (resA.x0_remTime > resB.x0_remTime) ? resA : resB; -} - -u32 CAnimTreeDoubleChild::Depth() const -{ - return std::max(x14_a->Depth(), x18_b->Depth()) + 1; -} - -CAnimTreeEffectiveContribution CAnimTreeDoubleChild::VGetContributionOfHighestInfluence() const -{ - CAnimTreeEffectiveContribution cA = x14_a->GetContributionOfHighestInfluence(); - CAnimTreeEffectiveContribution cB = x18_b->GetContributionOfHighestInfluence(); - - float leftWeight = (1.f - VGetRightChildWeight()) * cA.GetContributionWeight(); - float rightWeight = VGetRightChildWeight() * cB.GetContributionWeight(); - - if (leftWeight > rightWeight) - { - return {leftWeight, cA.GetPrimitiveName(), cA.GetSteadyStateAnimInfo(), - cA.GetTimeRemaining(), cA.GetAnimDatabaseIndex()}; - } - else - { - return {rightWeight, cB.GetPrimitiveName(), cB.GetSteadyStateAnimInfo(), - cB.GetTimeRemaining(), cB.GetAnimDatabaseIndex()}; + while (rRemTime.GreaterThanZero() && !rRemTime.EpsilonZero()) { + SAdvancementResults res = x18_b->VAdvanceView(rRemTime); + auto simp = x18_b->Simplified(); + if (simp) + x18_b = CAnimTreeNode::Cast(std::move(*simp)); + rightDeltas.x0_posDelta += res.x8_deltas.x0_posDelta; + rightDeltas.xc_rotDelta = rightDeltas.xc_rotDelta * res.x8_deltas.xc_rotDelta; + rRemTime = res.x0_remTime; } + } + + return {time, leftDeltas, rightDeltas}; } -u32 CAnimTreeDoubleChild::VGetNumChildren() const -{ - return x14_a->VGetNumChildren() + x18_b->VGetNumChildren() + 2; +SAdvancementResults CAnimTreeDoubleChild::VAdvanceView(const CCharAnimTime& a) { + SAdvancementResults resA = x14_a->VAdvanceView(a); + SAdvancementResults resB = x14_a->VAdvanceView(a); + return (resA.x0_remTime > resB.x0_remTime) ? resA : resB; } -std::shared_ptr CAnimTreeDoubleChild::VGetBestUnblendedChild() const -{ - std::shared_ptr bestChild = (VGetRightChildWeight() > 0.5f) ? x18_b : x14_a; - if (!bestChild) - return {}; - return bestChild->GetBestUnblendedChild(); +u32 CAnimTreeDoubleChild::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + u32 newCapacity = x14_a->GetBoolPOIList(time, listOut, capacity, iterator, unk); + newCapacity += x18_b->GetBoolPOIList(time, listOut, capacity, newCapacity + iterator, unk); + if (newCapacity > capacity) + newCapacity = capacity; + + std::sort(listOut, listOut + newCapacity); + + return newCapacity; +} + +u32 CAnimTreeDoubleChild::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + u32 newCapacity = x14_a->GetInt32POIList(time, listOut, capacity, iterator, unk); + newCapacity += x18_b->GetInt32POIList(time, listOut, capacity, newCapacity + iterator, unk); + if (newCapacity > capacity) + newCapacity = capacity; + + std::sort(listOut, listOut + newCapacity); + + return newCapacity; +} + +u32 CAnimTreeDoubleChild::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + u32 newCapacity = x14_a->GetParticlePOIList(time, listOut, capacity, iterator, unk); + newCapacity += x18_b->GetParticlePOIList(time, listOut, capacity, newCapacity + iterator, unk); + if (newCapacity > capacity) + newCapacity = capacity; + + std::sort(listOut, listOut + newCapacity); + + return newCapacity; +} + +u32 CAnimTreeDoubleChild::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + u32 newCapacity = x14_a->GetSoundPOIList(time, listOut, capacity, iterator, unk); + newCapacity += x18_b->GetSoundPOIList(time, listOut, capacity, newCapacity + iterator, unk); + if (newCapacity > capacity) + newCapacity = capacity; + + std::sort(listOut, listOut + newCapacity); + + return newCapacity; +} + +bool CAnimTreeDoubleChild::VGetBoolPOIState(const char* name) const { return x18_b->VGetBoolPOIState(name); } + +s32 CAnimTreeDoubleChild::VGetInt32POIState(const char* name) const { return x18_b->VGetBoolPOIState(name); } + +CParticleData::EParentedMode CAnimTreeDoubleChild::VGetParticlePOIState(const char* name) const { + return x18_b->VGetParticlePOIState(name); +} + +void CAnimTreeDoubleChild::VSetPhase(float phase) { + x14_a->VSetPhase(phase); + x18_b->VSetPhase(phase); +} + +SAdvancementResults CAnimTreeDoubleChild::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const { + SAdvancementResults resA = x14_a->VGetAdvancementResults(a, b); + SAdvancementResults resB = x18_b->VGetAdvancementResults(a, b); + return (resA.x0_remTime > resB.x0_remTime) ? resA : resB; +} + +u32 CAnimTreeDoubleChild::Depth() const { return std::max(x14_a->Depth(), x18_b->Depth()) + 1; } + +CAnimTreeEffectiveContribution CAnimTreeDoubleChild::VGetContributionOfHighestInfluence() const { + CAnimTreeEffectiveContribution cA = x14_a->GetContributionOfHighestInfluence(); + CAnimTreeEffectiveContribution cB = x18_b->GetContributionOfHighestInfluence(); + + float leftWeight = (1.f - VGetRightChildWeight()) * cA.GetContributionWeight(); + float rightWeight = VGetRightChildWeight() * cB.GetContributionWeight(); + + if (leftWeight > rightWeight) { + return {leftWeight, cA.GetPrimitiveName(), cA.GetSteadyStateAnimInfo(), cA.GetTimeRemaining(), + cA.GetAnimDatabaseIndex()}; + } else { + return {rightWeight, cB.GetPrimitiveName(), cB.GetSteadyStateAnimInfo(), cB.GetTimeRemaining(), + cB.GetAnimDatabaseIndex()}; + } +} + +u32 CAnimTreeDoubleChild::VGetNumChildren() const { return x14_a->VGetNumChildren() + x18_b->VGetNumChildren() + 2; } + +std::shared_ptr CAnimTreeDoubleChild::VGetBestUnblendedChild() const { + std::shared_ptr bestChild = (VGetRightChildWeight() > 0.5f) ? x18_b : x14_a; + if (!bestChild) + return {}; + return bestChild->GetBestUnblendedChild(); } void CAnimTreeDoubleChild::VGetWeightedReaders( - rstl::reserved_vector>, 16>& out, float w) const -{ - x14_a->VGetWeightedReaders(out, w); - x18_b->VGetWeightedReaders(out, w); + rstl::reserved_vector>, 16>& out, float w) const { + x14_a->VGetWeightedReaders(out, w); + x18_b->VGetWeightedReaders(out, w); } -} +} // namespace urde diff --git a/Runtime/Character/CAnimTreeDoubleChild.hpp b/Runtime/Character/CAnimTreeDoubleChild.hpp index 481c693f9..7e1135a28 100644 --- a/Runtime/Character/CAnimTreeDoubleChild.hpp +++ b/Runtime/Character/CAnimTreeDoubleChild.hpp @@ -2,56 +2,53 @@ #include "CAnimTreeNode.hpp" -namespace urde -{ +namespace urde { -class CAnimTreeDoubleChild : public CAnimTreeNode -{ +class CAnimTreeDoubleChild : public CAnimTreeNode { public: - class CDoubleChildAdvancementResult - { - CCharAnimTime x0_trueAdvancement; - SAdvancementDeltas x8_leftDeltas; - SAdvancementDeltas x24_rightDeltas; - public: - CDoubleChildAdvancementResult(const CCharAnimTime& trueAdvancement, const SAdvancementDeltas& leftDeltas, - const SAdvancementDeltas& rightDeltas) - : x0_trueAdvancement(trueAdvancement), x8_leftDeltas(leftDeltas), x24_rightDeltas(rightDeltas) {} - const SAdvancementDeltas& GetLeftAdvancementDeltas() const { return x8_leftDeltas; } - const SAdvancementDeltas& GetRightAdvancementDeltas() const { return x24_rightDeltas; } - const CCharAnimTime& GetTrueAdvancement() const { return x0_trueAdvancement; } - }; + class CDoubleChildAdvancementResult { + CCharAnimTime x0_trueAdvancement; + SAdvancementDeltas x8_leftDeltas; + SAdvancementDeltas x24_rightDeltas; + + public: + CDoubleChildAdvancementResult(const CCharAnimTime& trueAdvancement, const SAdvancementDeltas& leftDeltas, + const SAdvancementDeltas& rightDeltas) + : x0_trueAdvancement(trueAdvancement), x8_leftDeltas(leftDeltas), x24_rightDeltas(rightDeltas) {} + const SAdvancementDeltas& GetLeftAdvancementDeltas() const { return x8_leftDeltas; } + const SAdvancementDeltas& GetRightAdvancementDeltas() const { return x24_rightDeltas; } + const CCharAnimTime& GetTrueAdvancement() const { return x0_trueAdvancement; } + }; + protected: - std::shared_ptr x14_a; - std::shared_ptr x18_b; + std::shared_ptr x14_a; + std::shared_ptr x18_b; - CDoubleChildAdvancementResult AdvanceViewBothChildren(const CCharAnimTime& time, bool runLeft, bool loopLeft); + CDoubleChildAdvancementResult AdvanceViewBothChildren(const CCharAnimTime& time, bool runLeft, bool loopLeft); public: - CAnimTreeDoubleChild(const std::weak_ptr& a, const std::weak_ptr& b, - std::string_view name); - SAdvancementResults VAdvanceView(const CCharAnimTime& a); - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, - u32) const; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; - bool VGetBoolPOIState(const char* name) const; - s32 VGetInt32POIState(const char* name) const; - CParticleData::EParentedMode VGetParticlePOIState(const char* name) const; - void VSetPhase(float); - SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; - u32 Depth() const; - CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; - u32 VGetNumChildren() const; - std::shared_ptr VGetBestUnblendedChild() const; - void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const; + CAnimTreeDoubleChild(const std::weak_ptr& a, const std::weak_ptr& b, + std::string_view name); + SAdvancementResults VAdvanceView(const CCharAnimTime& a); + u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + bool VGetBoolPOIState(const char* name) const; + s32 VGetInt32POIState(const char* name) const; + CParticleData::EParentedMode VGetParticlePOIState(const char* name) const; + void VSetPhase(float); + SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; + u32 Depth() const; + CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; + u32 VGetNumChildren() const; + std::shared_ptr VGetBestUnblendedChild() const; + void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const; - virtual float VGetRightChildWeight() const = 0; - float GetRightChildWeight() const { return VGetRightChildWeight(); } + virtual float VGetRightChildWeight() const = 0; + float GetRightChildWeight() const { return VGetRightChildWeight(); } - const std::shared_ptr& GetLeftChild() const { return x14_a; } - const std::shared_ptr& GetRightChild() const { return x18_b; } + const std::shared_ptr& GetLeftChild() const { return x14_a; } + const std::shared_ptr& GetRightChild() const { return x18_b; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeLoopIn.cpp b/Runtime/Character/CAnimTreeLoopIn.cpp index b7ab4a112..7917588df 100644 --- a/Runtime/Character/CAnimTreeLoopIn.cpp +++ b/Runtime/Character/CAnimTreeLoopIn.cpp @@ -1,128 +1,103 @@ #include "CAnimTreeLoopIn.hpp" #include "CTreeUtils.hpp" -namespace urde -{ +namespace urde { std::string CAnimTreeLoopIn::CreatePrimitiveName(const std::weak_ptr& a, const std::weak_ptr& b, - const std::weak_ptr& c) -{ - return {}; + const std::weak_ptr& c) { + return {}; } -CAnimTreeLoopIn::CAnimTreeLoopIn(const std::weak_ptr& a, - const std::weak_ptr& b, - const std::weak_ptr& c, - const CAnimSysContext& animCtx, +CAnimTreeLoopIn::CAnimTreeLoopIn(const std::weak_ptr& a, const std::weak_ptr& b, + const std::weak_ptr& c, const CAnimSysContext& animCtx, std::string_view name) -: CAnimTreeSingleChild(CTreeUtils::GetTransitionTree(a, c, animCtx), name), - x18_nextAnim(b.lock()), x20_animCtx(animCtx), - x30_fundamentals(CSequenceHelper(x14_child, x18_nextAnim, animCtx).ComputeSequenceFundamentals()) -{ +: CAnimTreeSingleChild(CTreeUtils::GetTransitionTree(a, c, animCtx), name) +, x18_nextAnim(b.lock()) +, x20_animCtx(animCtx) +, x30_fundamentals(CSequenceHelper(x14_child, x18_nextAnim, animCtx).ComputeSequenceFundamentals()) {} + +CAnimTreeLoopIn::CAnimTreeLoopIn(const std::weak_ptr& a, const std::weak_ptr& b, + bool didLoopIn, const CAnimSysContext& animCtx, std::string_view name, + const CSequenceFundamentals& fundamentals, const CCharAnimTime& time) +: CAnimTreeSingleChild(a, name) +, x18_nextAnim(b.lock()) +, x1c_didLoopIn(didLoopIn) +, x20_animCtx(animCtx) +, x30_fundamentals(fundamentals) +, x88_curTime(time) {} + +CAnimTreeEffectiveContribution CAnimTreeLoopIn::VGetContributionOfHighestInfluence() const { + return x14_child->GetContributionOfHighestInfluence(); } -CAnimTreeLoopIn::CAnimTreeLoopIn(const std::weak_ptr& a, - const std::weak_ptr& b, - bool didLoopIn, - const CAnimSysContext& animCtx, - std::string_view name, - const CSequenceFundamentals& fundamentals, - const CCharAnimTime& time) -: CAnimTreeSingleChild(a, name), x18_nextAnim(b.lock()), x1c_didLoopIn(didLoopIn), x20_animCtx(animCtx), - x30_fundamentals(fundamentals), x88_curTime(time) -{ +std::experimental::optional> CAnimTreeLoopIn::VSimplified() { + CCharAnimTime remTime = x14_child->VGetTimeRemaining(); + if (remTime.GreaterThanZero() && !remTime.EpsilonZero()) { + auto simp = x14_child->Simplified(); + if (simp) + x14_child = CAnimTreeNode::Cast(std::move(*simp)); + } else if (x1c_didLoopIn && x14_child->VGetTimeRemaining().EqualsZero()) { + return x14_child->Clone(); + } + return {}; } -CAnimTreeEffectiveContribution CAnimTreeLoopIn::VGetContributionOfHighestInfluence() const -{ - return x14_child->GetContributionOfHighestInfluence(); +std::shared_ptr CAnimTreeLoopIn::VGetBestUnblendedChild() const { + if (std::shared_ptr bestChild = x14_child->GetBestUnblendedChild()) { + return std::make_shared(CAnimTreeNode::Cast(bestChild->Clone()), x18_nextAnim, x1c_didLoopIn, + x20_animCtx, x4_name, x30_fundamentals, x88_curTime); + } + return {}; } -std::experimental::optional> CAnimTreeLoopIn::VSimplified() -{ - CCharAnimTime remTime = x14_child->VGetTimeRemaining(); - if (remTime.GreaterThanZero() && !remTime.EpsilonZero()) - { - auto simp = x14_child->Simplified(); - if (simp) - x14_child = CAnimTreeNode::Cast(std::move(*simp)); - } - else if (x1c_didLoopIn && x14_child->VGetTimeRemaining().EqualsZero()) - { - return x14_child->Clone(); - } - return {}; +std::unique_ptr CAnimTreeLoopIn::VClone() const { + return std::make_unique(CAnimTreeNode::Cast(x14_child->Clone()), x18_nextAnim, x1c_didLoopIn, + x20_animCtx, x4_name, x30_fundamentals, x88_curTime); } -std::shared_ptr CAnimTreeLoopIn::VGetBestUnblendedChild() const -{ - if (std::shared_ptr bestChild = x14_child->GetBestUnblendedChild()) - { - return std::make_shared(CAnimTreeNode::Cast(bestChild->Clone()), - x18_nextAnim, x1c_didLoopIn, x20_animCtx, x4_name, - x30_fundamentals, x88_curTime); - } - return {}; +u32 CAnimTreeLoopIn::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + return _getPOIList(time, listOut, capacity, iterator, unk, x30_fundamentals.GetBoolPointsOfInterest(), + x88_curTime); } -std::unique_ptr CAnimTreeLoopIn::VClone() const -{ - return std::make_unique(CAnimTreeNode::Cast(x14_child->Clone()), - x18_nextAnim, x1c_didLoopIn, x20_animCtx, x4_name, - x30_fundamentals, x88_curTime); +u32 CAnimTreeLoopIn::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + return _getPOIList(time, listOut, capacity, iterator, unk, x30_fundamentals.GetInt32PointsOfInterest(), + x88_curTime); } -u32 CAnimTreeLoopIn::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return _getPOIList(time, listOut, capacity, iterator, unk, - x30_fundamentals.GetBoolPointsOfInterest(), x88_curTime); +u32 CAnimTreeLoopIn::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + return _getPOIList(time, listOut, capacity, iterator, unk, + x30_fundamentals.GetParticlePointsOfInterest(), x88_curTime); } -u32 CAnimTreeLoopIn::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return _getPOIList(time, listOut, capacity, iterator, unk, - x30_fundamentals.GetInt32PointsOfInterest(), x88_curTime); +u32 CAnimTreeLoopIn::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + return _getPOIList(time, listOut, capacity, iterator, unk, x30_fundamentals.GetSoundPointsOfInterest(), + x88_curTime); } -u32 CAnimTreeLoopIn::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return _getPOIList(time, listOut, capacity, iterator, unk, - x30_fundamentals.GetParticlePointsOfInterest(), x88_curTime); +CSteadyStateAnimInfo CAnimTreeLoopIn::VGetSteadyStateAnimInfo() const { + return x30_fundamentals.GetSteadyStateAnimInfo(); } -u32 CAnimTreeLoopIn::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return _getPOIList(time, listOut, capacity, iterator, unk, - x30_fundamentals.GetSoundPointsOfInterest(), x88_curTime); +CCharAnimTime CAnimTreeLoopIn::VGetTimeRemaining() const { + return x30_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x88_curTime; } -CSteadyStateAnimInfo CAnimTreeLoopIn::VGetSteadyStateAnimInfo() const -{ - return x30_fundamentals.GetSteadyStateAnimInfo(); +SAdvancementResults CAnimTreeLoopIn::VAdvanceView(const CCharAnimTime& dt) { + std::shared_ptr origChild = x14_child; + SAdvancementResults res = origChild->VAdvanceView(dt); + x88_curTime += dt - res.x0_remTime; + CCharAnimTime remTime = origChild->VGetTimeRemaining(); + if ((remTime.EpsilonZero() || (dt - res.x0_remTime).EpsilonZero()) && !x1c_didLoopIn) { + x14_child = CTreeUtils::GetTransitionTree(origChild, x18_nextAnim, x20_animCtx); + x1c_didLoopIn = true; + } + return res; } -CCharAnimTime CAnimTreeLoopIn::VGetTimeRemaining() const -{ - return x30_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x88_curTime; -} - -SAdvancementResults CAnimTreeLoopIn::VAdvanceView(const CCharAnimTime& dt) -{ - std::shared_ptr origChild = x14_child; - SAdvancementResults res = origChild->VAdvanceView(dt); - x88_curTime += dt - res.x0_remTime; - CCharAnimTime remTime = origChild->VGetTimeRemaining(); - if ((remTime.EpsilonZero() || (dt - res.x0_remTime).EpsilonZero()) && !x1c_didLoopIn) - { - x14_child = CTreeUtils::GetTransitionTree(origChild, x18_nextAnim, x20_animCtx); - x1c_didLoopIn = true; - } - return res; -} - -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/Character/CAnimTreeLoopIn.hpp b/Runtime/Character/CAnimTreeLoopIn.hpp index e604eba83..c30df4234 100644 --- a/Runtime/Character/CAnimTreeLoopIn.hpp +++ b/Runtime/Character/CAnimTreeLoopIn.hpp @@ -4,45 +4,35 @@ #include "CAnimSysContext.hpp" #include "CSequenceHelper.hpp" -namespace urde -{ +namespace urde { + +class CAnimTreeLoopIn : public CAnimTreeSingleChild { + std::shared_ptr x18_nextAnim; + bool x1c_didLoopIn = false; + CAnimSysContext x20_animCtx; + CSequenceFundamentals x30_fundamentals; + CCharAnimTime x88_curTime; -class CAnimTreeLoopIn : public CAnimTreeSingleChild -{ - std::shared_ptr x18_nextAnim; - bool x1c_didLoopIn = false; - CAnimSysContext x20_animCtx; - CSequenceFundamentals x30_fundamentals; - CCharAnimTime x88_curTime; public: - static std::string CreatePrimitiveName(const std::weak_ptr& a, - const std::weak_ptr& b, - const std::weak_ptr& c); - CAnimTreeLoopIn(const std::weak_ptr& a, - const std::weak_ptr& b, - const std::weak_ptr& c, - const CAnimSysContext& animCtx, - std::string_view name); - CAnimTreeLoopIn(const std::weak_ptr& a, - const std::weak_ptr& b, - bool didLoopIn, - const CAnimSysContext& animCtx, - std::string_view name, - const CSequenceFundamentals& fundamentals, - const CCharAnimTime& time); - CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; - bool VSupportsReverseView() const { return false; } - std::experimental::optional> VSimplified(); - std::shared_ptr VGetBestUnblendedChild() const; - std::unique_ptr VClone() const; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; - CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; - CCharAnimTime VGetTimeRemaining() const; - SAdvancementResults VAdvanceView(const CCharAnimTime& dt); + static std::string CreatePrimitiveName(const std::weak_ptr& a, const std::weak_ptr& b, + const std::weak_ptr& c); + CAnimTreeLoopIn(const std::weak_ptr& a, const std::weak_ptr& b, + const std::weak_ptr& c, const CAnimSysContext& animCtx, std::string_view name); + CAnimTreeLoopIn(const std::weak_ptr& a, const std::weak_ptr& b, bool didLoopIn, + const CAnimSysContext& animCtx, std::string_view name, const CSequenceFundamentals& fundamentals, + const CCharAnimTime& time); + CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; + bool VSupportsReverseView() const { return false; } + std::experimental::optional> VSimplified(); + std::shared_ptr VGetBestUnblendedChild() const; + std::unique_ptr VClone() const; + u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + CCharAnimTime VGetTimeRemaining() const; + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeNode.cpp b/Runtime/Character/CAnimTreeNode.cpp index 284d811da..3b28b26fa 100644 --- a/Runtime/Character/CAnimTreeNode.cpp +++ b/Runtime/Character/CAnimTreeNode.cpp @@ -1,21 +1,13 @@ #include "CAnimTreeNode.hpp" -namespace urde -{ +namespace urde { -CAnimTreeEffectiveContribution CAnimTreeNode::GetContributionOfHighestInfluence() const -{ - return VGetContributionOfHighestInfluence(); +CAnimTreeEffectiveContribution CAnimTreeNode::GetContributionOfHighestInfluence() const { + return VGetContributionOfHighestInfluence(); } -u32 CAnimTreeNode::GetNumChildren() const -{ - return VGetNumChildren(); -} +u32 CAnimTreeNode::GetNumChildren() const { return VGetNumChildren(); } -std::shared_ptr CAnimTreeNode::GetBestUnblendedChild() const -{ - return VGetBestUnblendedChild(); -} +std::shared_ptr CAnimTreeNode::GetBestUnblendedChild() const { return VGetBestUnblendedChild(); } -} +} // namespace urde diff --git a/Runtime/Character/CAnimTreeNode.hpp b/Runtime/Character/CAnimTreeNode.hpp index 3b8172b28..3b8c93edf 100644 --- a/Runtime/Character/CAnimTreeNode.hpp +++ b/Runtime/Character/CAnimTreeNode.hpp @@ -2,37 +2,36 @@ #include "IAnimReader.hpp" -namespace urde -{ +namespace urde { -class CAnimTreeNode : public IAnimReader -{ +class CAnimTreeNode : public IAnimReader { protected: - std::string x4_name; + std::string x4_name; + public: - CAnimTreeNode(std::string_view name) : x4_name(name) {} - bool IsCAnimTreeNode() const {return true;} - static std::shared_ptr Cast(std::unique_ptr&& ptr) - { - if (ptr->IsCAnimTreeNode()) - return std::static_pointer_cast(std::shared_ptr(std::move(ptr))); - return {}; - } + CAnimTreeNode(std::string_view name) : x4_name(name) {} + bool IsCAnimTreeNode() const { return true; } + static std::shared_ptr Cast(std::unique_ptr&& ptr) { + if (ptr->IsCAnimTreeNode()) + return std::static_pointer_cast(std::shared_ptr(std::move(ptr))); + return {}; + } - virtual u32 Depth() const=0; - virtual CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const=0; - virtual u32 VGetNumChildren() const=0; - virtual std::shared_ptr VGetBestUnblendedChild() const=0; - virtual void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const=0; - void GetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const - { VGetWeightedReaders(out, w); } + virtual u32 Depth() const = 0; + virtual CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const = 0; + virtual u32 VGetNumChildren() const = 0; + virtual std::shared_ptr VGetBestUnblendedChild() const = 0; + virtual void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, + float w) const = 0; + void GetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const { + VGetWeightedReaders(out, w); + } - CAnimTreeEffectiveContribution GetContributionOfHighestInfluence() const; - u32 GetNumChildren() const; - std::shared_ptr GetBestUnblendedChild() const; + CAnimTreeEffectiveContribution GetContributionOfHighestInfluence() const; + u32 GetNumChildren() const; + std::shared_ptr GetBestUnblendedChild() const; - std::string_view GetName() const { return x4_name; } + std::string_view GetName() const { return x4_name; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeSequence.cpp b/Runtime/Character/CAnimTreeSequence.cpp index ac5df458d..a7b020705 100644 --- a/Runtime/Character/CAnimTreeSequence.cpp +++ b/Runtime/Character/CAnimTreeSequence.cpp @@ -3,139 +3,120 @@ #include "CAnimSysContext.hpp" #include "CTreeUtils.hpp" -namespace urde -{ +namespace urde { -CAnimTreeSequence::CAnimTreeSequence(const std::vector>& seq, - const CAnimSysContext& animSys, +CAnimTreeSequence::CAnimTreeSequence(const std::vector>& seq, const CAnimSysContext& animSys, std::string_view name) -: CAnimTreeSingleChild(seq[0]->GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()), name), - x18_animCtx(animSys), x28_sequence(seq), - x3c_fundamentals(CSequenceHelper(seq, animSys).ComputeSequenceFundamentals()), x94_curTime(0.f) -{ -} +: CAnimTreeSingleChild(seq[0]->GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()), name) +, x18_animCtx(animSys) +, x28_sequence(seq) +, x3c_fundamentals(CSequenceHelper(seq, animSys).ComputeSequenceFundamentals()) +, x94_curTime(0.f) {} CAnimTreeSequence::CAnimTreeSequence(const std::shared_ptr& curNode, const std::vector>& metaAnims, - const CAnimSysContext& animSys, - std::string_view name, - const CSequenceFundamentals& fundamentals, - const CCharAnimTime& time) -: CAnimTreeSingleChild(curNode, name), x18_animCtx(animSys), x28_sequence(metaAnims), - x3c_fundamentals(fundamentals), x94_curTime(time) -{ + const CAnimSysContext& animSys, std::string_view name, + const CSequenceFundamentals& fundamentals, const CCharAnimTime& time) +: CAnimTreeSingleChild(curNode, name) +, x18_animCtx(animSys) +, x28_sequence(metaAnims) +, x3c_fundamentals(fundamentals) +, x94_curTime(time) {} + +CAnimTreeEffectiveContribution CAnimTreeSequence::VGetContributionOfHighestInfluence() const { + return x14_child->GetContributionOfHighestInfluence(); } -CAnimTreeEffectiveContribution CAnimTreeSequence::VGetContributionOfHighestInfluence() const -{ - return x14_child->GetContributionOfHighestInfluence(); +std::shared_ptr CAnimTreeSequence::VGetBestUnblendedChild() const { + std::shared_ptr ch = x14_child->GetBestUnblendedChild(); + if (!ch) + return ch; + return std::make_shared( + std::static_pointer_cast(std::shared_ptr(ch->Clone())), x28_sequence, x18_animCtx, + x4_name, x3c_fundamentals, x94_curTime); } -std::shared_ptr CAnimTreeSequence::VGetBestUnblendedChild() const -{ - std::shared_ptr ch = x14_child->GetBestUnblendedChild(); - if (!ch) - return ch; - return std::make_shared(std::static_pointer_cast( - std::shared_ptr(ch->Clone())), - x28_sequence, x18_animCtx, x4_name, x3c_fundamentals, x94_curTime); -} +SAdvancementResults CAnimTreeSequence::VAdvanceView(const CCharAnimTime& dt) { + CCharAnimTime totalDelta; + zeus::CVector3f posDelta; + zeus::CQuaternion rotDelta; -SAdvancementResults CAnimTreeSequence::VAdvanceView(const CCharAnimTime& dt) -{ - CCharAnimTime totalDelta; - zeus::CVector3f posDelta; - zeus::CQuaternion rotDelta; + std::shared_ptr curChild = x14_child; + if (x38_curIdx >= x28_sequence.size() && curChild->VGetTimeRemaining().EqualsZero()) { + x3c_fundamentals = CSequenceHelper(x28_sequence, x18_animCtx).ComputeSequenceFundamentals(); + x38_curIdx = 0; + x14_child = CTreeUtils::GetTransitionTree( + curChild, x28_sequence[x38_curIdx]->GetAnimationTree(x18_animCtx, CMetaAnimTreeBuildOrders::NoSpecialOrders()), + x18_animCtx); + curChild = x14_child; + } - std::shared_ptr curChild = x14_child; - if (x38_curIdx >= x28_sequence.size() && curChild->VGetTimeRemaining().EqualsZero()) - { - x3c_fundamentals = CSequenceHelper(x28_sequence, x18_animCtx).ComputeSequenceFundamentals(); - x38_curIdx = 0; - x14_child = CTreeUtils::GetTransitionTree(curChild, x28_sequence[x38_curIdx]->GetAnimationTree( - x18_animCtx, CMetaAnimTreeBuildOrders::NoSpecialOrders()), x18_animCtx); - curChild = x14_child; + CCharAnimTime remTime = dt; + while (remTime.GreaterThanZero() && x38_curIdx < x28_sequence.size()) { + CCharAnimTime chRem = curChild->VGetTimeRemaining(); + if (chRem.EqualsZero()) { + ++x38_curIdx; + if (x38_curIdx < x28_sequence.size()) { + x14_child = CTreeUtils::GetTransitionTree( + curChild, + x28_sequence[x38_curIdx]->GetAnimationTree(x18_animCtx, CMetaAnimTreeBuildOrders::NoSpecialOrders()), + x18_animCtx); + } } - - CCharAnimTime remTime = dt; - while (remTime.GreaterThanZero() && x38_curIdx < x28_sequence.size()) - { - CCharAnimTime chRem = curChild->VGetTimeRemaining(); - if (chRem.EqualsZero()) - { - ++x38_curIdx; - if (x38_curIdx < x28_sequence.size()) - { - x14_child = CTreeUtils::GetTransitionTree(curChild, x28_sequence[x38_curIdx]->GetAnimationTree( - x18_animCtx, CMetaAnimTreeBuildOrders::NoSpecialOrders()), x18_animCtx); - } - } - curChild = x14_child; - if (x38_curIdx < x28_sequence.size()) - { - SAdvancementResults res = curChild->VAdvanceView(remTime); - if (auto simp = curChild->Simplified()) - { - curChild = CAnimTreeNode::Cast(std::move(*simp)); - x14_child = curChild; - } - CCharAnimTime prevRemTime = remTime; - remTime = res.x0_remTime; - totalDelta += prevRemTime - remTime; - posDelta += res.x8_deltas.x0_posDelta; - rotDelta = rotDelta * res.x8_deltas.xc_rotDelta; - } + curChild = x14_child; + if (x38_curIdx < x28_sequence.size()) { + SAdvancementResults res = curChild->VAdvanceView(remTime); + if (auto simp = curChild->Simplified()) { + curChild = CAnimTreeNode::Cast(std::move(*simp)); + x14_child = curChild; + } + CCharAnimTime prevRemTime = remTime; + remTime = res.x0_remTime; + totalDelta += prevRemTime - remTime; + posDelta += res.x8_deltas.x0_posDelta; + rotDelta = rotDelta * res.x8_deltas.xc_rotDelta; } + } - x94_curTime += totalDelta; - return {dt - totalDelta, {posDelta, rotDelta}}; + x94_curTime += totalDelta; + return {dt - totalDelta, {posDelta, rotDelta}}; } -CCharAnimTime CAnimTreeSequence::VGetTimeRemaining() const -{ - if (x38_curIdx == x28_sequence.size() - 1) - return x14_child->VGetTimeRemaining(); - return x3c_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x94_curTime.GetSeconds(); +CCharAnimTime CAnimTreeSequence::VGetTimeRemaining() const { + if (x38_curIdx == x28_sequence.size() - 1) + return x14_child->VGetTimeRemaining(); + return x3c_fundamentals.GetSteadyStateAnimInfo().GetDuration() - x94_curTime.GetSeconds(); } -CSteadyStateAnimInfo CAnimTreeSequence::VGetSteadyStateAnimInfo() const -{ - return x3c_fundamentals.GetSteadyStateAnimInfo(); +CSteadyStateAnimInfo CAnimTreeSequence::VGetSteadyStateAnimInfo() const { + return x3c_fundamentals.GetSteadyStateAnimInfo(); } -u32 CAnimTreeSequence::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return _getPOIList(time, listOut, capacity, iterator, unk, - x3c_fundamentals.GetBoolPointsOfInterest(), x94_curTime); +u32 CAnimTreeSequence::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + return _getPOIList(time, listOut, capacity, iterator, unk, x3c_fundamentals.GetBoolPointsOfInterest(), x94_curTime); } -u32 CAnimTreeSequence::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return _getPOIList(time, listOut, capacity, iterator, unk, - x3c_fundamentals.GetInt32PointsOfInterest(), x94_curTime); +u32 CAnimTreeSequence::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + return _getPOIList(time, listOut, capacity, iterator, unk, x3c_fundamentals.GetInt32PointsOfInterest(), x94_curTime); } -u32 CAnimTreeSequence::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return _getPOIList(time, listOut, capacity, iterator, unk, - x3c_fundamentals.GetParticlePointsOfInterest(), x94_curTime); +u32 CAnimTreeSequence::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + return _getPOIList(time, listOut, capacity, iterator, unk, x3c_fundamentals.GetParticlePointsOfInterest(), + x94_curTime); } -u32 CAnimTreeSequence::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return _getPOIList(time, listOut, capacity, iterator, unk, - x3c_fundamentals.GetSoundPointsOfInterest(), x94_curTime); +u32 CAnimTreeSequence::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + return _getPOIList(time, listOut, capacity, iterator, unk, x3c_fundamentals.GetSoundPointsOfInterest(), x94_curTime); } -std::unique_ptr CAnimTreeSequence::VClone() const -{ - return std::make_unique(std::static_pointer_cast( - std::shared_ptr(x14_child->Clone())), - x28_sequence, x18_animCtx, x4_name, x3c_fundamentals, x94_curTime); +std::unique_ptr CAnimTreeSequence::VClone() const { + return std::make_unique( + std::static_pointer_cast(std::shared_ptr(x14_child->Clone())), x28_sequence, + x18_animCtx, x4_name, x3c_fundamentals, x94_curTime); } -} +} // namespace urde diff --git a/Runtime/Character/CAnimTreeSequence.hpp b/Runtime/Character/CAnimTreeSequence.hpp index 8375571ea..8941f8356 100644 --- a/Runtime/Character/CAnimTreeSequence.hpp +++ b/Runtime/Character/CAnimTreeSequence.hpp @@ -4,42 +4,36 @@ #include "CAnimSysContext.hpp" #include "CSequenceHelper.hpp" -namespace urde -{ +namespace urde { class IMetaAnim; class CTransitionDatabaseGame; -class CAnimTreeSequence : public CAnimTreeSingleChild -{ - CAnimSysContext x18_animCtx; - std::vector> x28_sequence; - u32 x38_curIdx = 0; - CSequenceFundamentals x3c_fundamentals; - CCharAnimTime x94_curTime; +class CAnimTreeSequence : public CAnimTreeSingleChild { + CAnimSysContext x18_animCtx; + std::vector> x28_sequence; + u32 x38_curIdx = 0; + CSequenceFundamentals x3c_fundamentals; + CCharAnimTime x94_curTime; + public: - CAnimTreeSequence(const std::vector>& seq, - const CAnimSysContext& animSys, - std::string_view name); - CAnimTreeSequence(const std::shared_ptr& curNode, - const std::vector>& metaAnims, - const CAnimSysContext& animSys, - std::string_view name, - const CSequenceFundamentals& fundamentals, - const CCharAnimTime& time); + CAnimTreeSequence(const std::vector>& seq, const CAnimSysContext& animSys, + std::string_view name); + CAnimTreeSequence(const std::shared_ptr& curNode, + const std::vector>& metaAnims, const CAnimSysContext& animSys, + std::string_view name, const CSequenceFundamentals& fundamentals, const CCharAnimTime& time); - CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; - std::shared_ptr VGetBestUnblendedChild() const; - bool VSupportsReverseView() const { return false; } + CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; + std::shared_ptr VGetBestUnblendedChild() const; + bool VSupportsReverseView() const { return false; } - SAdvancementResults VAdvanceView(const CCharAnimTime& dt); - CCharAnimTime VGetTimeRemaining() const; - CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; - std::unique_ptr VClone() const; + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); + CCharAnimTime VGetTimeRemaining() const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + std::unique_ptr VClone() const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeSingleChild.cpp b/Runtime/Character/CAnimTreeSingleChild.cpp index 8a3d4e8a6..f13d3f896 100644 --- a/Runtime/Character/CAnimTreeSingleChild.cpp +++ b/Runtime/Character/CAnimTreeSingleChild.cpp @@ -1,115 +1,65 @@ #include "CAnimTreeSingleChild.hpp" -namespace urde -{ +namespace urde { CAnimTreeSingleChild::CAnimTreeSingleChild(const std::weak_ptr& node, std::string_view name) -: CAnimTreeNode(name) -, x14_child(node.lock()) -{ +: CAnimTreeNode(name), x14_child(node.lock()) {} + +SAdvancementResults CAnimTreeSingleChild::VAdvanceView(const CCharAnimTime& dt) { return x14_child->VAdvanceView(dt); } + +CCharAnimTime CAnimTreeSingleChild::VGetTimeRemaining() const { return x14_child->VGetTimeRemaining(); } + +bool CAnimTreeSingleChild::VHasOffset(const CSegId& seg) const { return x14_child->VHasOffset(seg); } + +zeus::CVector3f CAnimTreeSingleChild::VGetOffset(const CSegId& seg) const { return x14_child->VGetOffset(seg); } + +zeus::CQuaternion CAnimTreeSingleChild::VGetRotation(const CSegId& seg) const { return x14_child->VGetRotation(seg); } + +u32 CAnimTreeSingleChild::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + return x14_child->GetBoolPOIList(time, listOut, capacity, iterator, unk); } -SAdvancementResults CAnimTreeSingleChild::VAdvanceView(const CCharAnimTime& dt) -{ - return x14_child->VAdvanceView(dt); +u32 CAnimTreeSingleChild::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + return x14_child->GetInt32POIList(time, listOut, capacity, iterator, unk); } -CCharAnimTime CAnimTreeSingleChild::VGetTimeRemaining() const -{ - return x14_child->VGetTimeRemaining(); +u32 CAnimTreeSingleChild::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + return x14_child->GetParticlePOIList(time, listOut, capacity, iterator, unk); } -bool CAnimTreeSingleChild::VHasOffset(const CSegId& seg) const -{ - return x14_child->VHasOffset(seg); +u32 CAnimTreeSingleChild::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + return x14_child->GetSoundPOIList(time, listOut, capacity, iterator, unk); } -zeus::CVector3f CAnimTreeSingleChild::VGetOffset(const CSegId& seg) const -{ - return x14_child->VGetOffset(seg); +bool CAnimTreeSingleChild::VGetBoolPOIState(const char* name) const { return x14_child->VGetBoolPOIState(name); } + +s32 CAnimTreeSingleChild::VGetInt32POIState(const char* name) const { return x14_child->VGetInt32POIState(name); } + +CParticleData::EParentedMode CAnimTreeSingleChild::VGetParticlePOIState(const char* name) const { + return x14_child->VGetParticlePOIState(name); } -zeus::CQuaternion CAnimTreeSingleChild::VGetRotation(const CSegId& seg) const -{ - return x14_child->VGetRotation(seg); +void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const { + x14_child->VGetSegStatementSet(list, setOut); } -u32 CAnimTreeSingleChild::VGetBoolPOIList(const CCharAnimTime& time, - CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return x14_child->GetBoolPOIList(time, listOut, capacity, iterator, unk); +void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, + const CCharAnimTime& time) const { + x14_child->VGetSegStatementSet(list, setOut, time); } -u32 CAnimTreeSingleChild::VGetInt32POIList(const CCharAnimTime& time, - CInt32POINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return x14_child->GetInt32POIList(time, listOut, capacity, iterator, unk); +void CAnimTreeSingleChild::VSetPhase(float phase) { x14_child->VSetPhase(phase); } + +SAdvancementResults CAnimTreeSingleChild::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const { + return x14_child->VGetAdvancementResults(a, b); } -u32 CAnimTreeSingleChild::VGetParticlePOIList(const CCharAnimTime& time, - CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return x14_child->GetParticlePOIList(time, listOut, capacity, iterator, unk); -} +u32 CAnimTreeSingleChild::Depth() const { return x14_child->Depth() + 1; } -u32 CAnimTreeSingleChild::VGetSoundPOIList(const CCharAnimTime& time, - CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - return x14_child->GetSoundPOIList(time, listOut, capacity, iterator, unk); -} +u32 CAnimTreeSingleChild::VGetNumChildren() const { return x14_child->VGetNumChildren() + 1; } -bool CAnimTreeSingleChild::VGetBoolPOIState(const char* name) const -{ - return x14_child->VGetBoolPOIState(name); -} - -s32 CAnimTreeSingleChild::VGetInt32POIState(const char* name) const -{ - return x14_child->VGetInt32POIState(name); -} - -CParticleData::EParentedMode CAnimTreeSingleChild::VGetParticlePOIState(const char* name) const -{ - return x14_child->VGetParticlePOIState(name); -} - -void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list, - CSegStatementSet& setOut) const -{ - x14_child->VGetSegStatementSet(list, setOut); -} - -void CAnimTreeSingleChild::VGetSegStatementSet(const CSegIdList& list, - CSegStatementSet& setOut, - const CCharAnimTime& time) const -{ - x14_child->VGetSegStatementSet(list, setOut, time); -} - -void CAnimTreeSingleChild::VSetPhase(float phase) -{ - x14_child->VSetPhase(phase); -} - -SAdvancementResults -CAnimTreeSingleChild::VGetAdvancementResults(const CCharAnimTime& a, - const CCharAnimTime& b) const -{ - return x14_child->VGetAdvancementResults(a, b); -} - -u32 CAnimTreeSingleChild::Depth() const -{ - return x14_child->Depth() + 1; -} - -u32 CAnimTreeSingleChild::VGetNumChildren() const -{ - return x14_child->VGetNumChildren() + 1; -} - -} +} // namespace urde diff --git a/Runtime/Character/CAnimTreeSingleChild.hpp b/Runtime/Character/CAnimTreeSingleChild.hpp index a3647578d..2340528dc 100644 --- a/Runtime/Character/CAnimTreeSingleChild.hpp +++ b/Runtime/Character/CAnimTreeSingleChild.hpp @@ -2,37 +2,37 @@ #include "CAnimTreeNode.hpp" -namespace urde -{ +namespace urde { -class CAnimTreeSingleChild : public CAnimTreeNode -{ +class CAnimTreeSingleChild : public CAnimTreeNode { protected: - std::shared_ptr x14_child; -public: - CAnimTreeSingleChild(const std::weak_ptr& node, std::string_view name); + std::shared_ptr x14_child; - SAdvancementResults VAdvanceView(const CCharAnimTime& dt); - CCharAnimTime VGetTimeRemaining() const; - bool VHasOffset(const CSegId& seg) const; - zeus::CVector3f VGetOffset(const CSegId& seg) const; - zeus::CQuaternion VGetRotation(const CSegId& seg) const; - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; - bool VGetBoolPOIState(const char* name) const; - s32 VGetInt32POIState(const char* name) const; - CParticleData::EParentedMode VGetParticlePOIState(const char* name) const; - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; - void VSetPhase(float); - SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; - u32 Depth() const; - u32 VGetNumChildren() const; - void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const - { x14_child->VGetWeightedReaders(out, w); } +public: + CAnimTreeSingleChild(const std::weak_ptr& node, std::string_view name); + + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); + CCharAnimTime VGetTimeRemaining() const; + bool VHasOffset(const CSegId& seg) const; + zeus::CVector3f VGetOffset(const CSegId& seg) const; + zeus::CQuaternion VGetRotation(const CSegId& seg) const; + u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + bool VGetBoolPOIState(const char* name) const; + s32 VGetInt32POIState(const char* name) const; + CParticleData::EParentedMode VGetParticlePOIState(const char* name) const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; + void VSetPhase(float); + SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; + u32 Depth() const; + u32 VGetNumChildren() const; + void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, + float w) const { + x14_child->VGetWeightedReaders(out, w); + } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeTimeScale.cpp b/Runtime/Character/CAnimTreeTimeScale.cpp index 14317abc4..6238eb60c 100644 --- a/Runtime/Character/CAnimTreeTimeScale.cpp +++ b/Runtime/Character/CAnimTreeTimeScale.cpp @@ -1,234 +1,184 @@ #include "CAnimTreeTimeScale.hpp" -namespace urde -{ +namespace urde { -CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr& node, float scale, - std::string_view name) +CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr& node, float scale, std::string_view name) : CAnimTreeSingleChild(node, name) , x18_timeScale(new CConstantAnimationTimeScale(scale)) -, x28_targetAccelTime(CCharAnimTime::Infinity()) -{ -} +, x28_targetAccelTime(CCharAnimTime::Infinity()) {} CAnimTreeTimeScale::CAnimTreeTimeScale(const std::weak_ptr& node, std::unique_ptr&& timeScale, const CCharAnimTime& time, std::string_view name) -: CAnimTreeSingleChild(node, name) -, x18_timeScale(std::move(timeScale)) -, x28_targetAccelTime(time) -{ - x30_initialTime = x14_child->VGetSteadyStateAnimInfo().GetDuration() - x14_child->VGetTimeRemaining(); +: CAnimTreeSingleChild(node, name), x18_timeScale(std::move(timeScale)), x28_targetAccelTime(time) { + x30_initialTime = x14_child->VGetSteadyStateAnimInfo().GetDuration() - x14_child->VGetTimeRemaining(); } -std::string CAnimTreeTimeScale::CreatePrimitiveName(const std::weak_ptr&, float, - const CCharAnimTime&, float) -{ - return {}; +std::string CAnimTreeTimeScale::CreatePrimitiveName(const std::weak_ptr&, float, const CCharAnimTime&, + float) { + return {}; } -CCharAnimTime CAnimTreeTimeScale::GetRealLifeTime(const CCharAnimTime& time) const -{ - CCharAnimTime timeRem = x14_child->VGetTimeRemaining(); +CCharAnimTime CAnimTreeTimeScale::GetRealLifeTime(const CCharAnimTime& time) const { + CCharAnimTime timeRem = x14_child->VGetTimeRemaining(); - CCharAnimTime ret = std::min(timeRem, time); - if (x28_targetAccelTime > CCharAnimTime()) - { - if (ret < CCharAnimTime(x28_targetAccelTime - x20_curAccelTime)) - return x18_timeScale->VTimeScaleIntegral(x20_curAccelTime.GetSeconds(), - (x20_curAccelTime + ret).GetSeconds()); - else - { - CCharAnimTime integral = - x18_timeScale->VTimeScaleIntegral(x20_curAccelTime.GetSeconds(), x28_targetAccelTime.GetSeconds()); + CCharAnimTime ret = std::min(timeRem, time); + if (x28_targetAccelTime > CCharAnimTime()) { + if (ret < CCharAnimTime(x28_targetAccelTime - x20_curAccelTime)) + return x18_timeScale->VTimeScaleIntegral(x20_curAccelTime.GetSeconds(), (x20_curAccelTime + ret).GetSeconds()); + else { + CCharAnimTime integral = + x18_timeScale->VTimeScaleIntegral(x20_curAccelTime.GetSeconds(), x28_targetAccelTime.GetSeconds()); - if (integral > ret) - return x18_timeScale->VFindUpperLimit(x20_curAccelTime.GetSeconds(), ret.GetSeconds()) - - x20_curAccelTime.GetSeconds(); - else - return integral + (ret - integral); - } + if (integral > ret) + return x18_timeScale->VFindUpperLimit(x20_curAccelTime.GetSeconds(), ret.GetSeconds()) - + x20_curAccelTime.GetSeconds(); + else + return integral + (ret - integral); } + } - return ret; + return ret; } -void CAnimTreeTimeScale::VSetPhase(float phase) -{ - x14_child->VSetPhase(phase); -} +void CAnimTreeTimeScale::VSetPhase(float phase) { x14_child->VSetPhase(phase); } -std::experimental::optional> CAnimTreeTimeScale::VSimplified() -{ - if (auto simp = x14_child->Simplified()) - { - CAnimTreeTimeScale* newNode = new CAnimTreeTimeScale(CAnimTreeNode::Cast(std::move(*simp)), - x18_timeScale->Clone(), x28_targetAccelTime, x4_name); - newNode->x20_curAccelTime = x20_curAccelTime; - newNode->x30_initialTime = x30_initialTime; - return {std::unique_ptr(newNode)}; - } - else if (x20_curAccelTime == x28_targetAccelTime) - { - return {x14_child->Clone()}; - } - return {}; -} - -u32 CAnimTreeTimeScale::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - CCharAnimTime useTime = (time == CCharAnimTime::Infinity()) ? - x14_child->VGetTimeRemaining() : GetRealLifeTime(time); - u32 ret = x14_child->GetBoolPOIList(useTime, listOut, capacity, iterator, unk); - if (x28_targetAccelTime > CCharAnimTime()) - for (int i=0 ; iVGetTimeRemaining() : GetRealLifeTime(time); - u32 ret = x14_child->GetInt32POIList(useTime, listOut, capacity, iterator, unk); - if (x28_targetAccelTime > CCharAnimTime()) - for (int i=0 ; iVGetTimeRemaining() : GetRealLifeTime(time); - u32 ret = x14_child->GetParticlePOIList(useTime, listOut, capacity, iterator, unk); - if (x28_targetAccelTime > CCharAnimTime()) - for (int i=0 ; iVGetTimeRemaining() : GetRealLifeTime(time); - u32 ret = x14_child->GetSoundPOIList(useTime, listOut, capacity, iterator, unk); - if (x28_targetAccelTime > CCharAnimTime()) - for (int i=0 ; iVGetBoolPOIState(name); -} - -s32 CAnimTreeTimeScale::VGetInt32POIState(const char* name) const -{ - return x14_child->VGetInt32POIState(name); -} - -CParticleData::EParentedMode CAnimTreeTimeScale::VGetParticlePOIState(const char* name) const -{ - return x14_child->VGetParticlePOIState(name); -} - -CAnimTreeEffectiveContribution CAnimTreeTimeScale::VGetContributionOfHighestInfluence() const -{ - CAnimTreeEffectiveContribution c = x14_child->VGetContributionOfHighestInfluence(); - return {c.GetContributionWeight(), c.GetPrimitiveName(), VGetSteadyStateAnimInfo(), - VGetTimeRemaining(), c.GetAnimDatabaseIndex()}; -} - -std::shared_ptr CAnimTreeTimeScale::VGetBestUnblendedChild() const -{ - if (std::shared_ptr bestChild = x14_child->VGetBestUnblendedChild()) - { - CAnimTreeTimeScale* newNode = new CAnimTreeTimeScale(CAnimTreeNode::Cast(bestChild->Clone()), - x18_timeScale->Clone(), x28_targetAccelTime, x4_name); - newNode->x20_curAccelTime = x20_curAccelTime; - newNode->x30_initialTime = x30_initialTime; - return {std::shared_ptr(newNode)}; - } - return {}; -} - -std::unique_ptr CAnimTreeTimeScale::VClone() const -{ - CAnimTreeTimeScale* newNode = new CAnimTreeTimeScale(CAnimTreeNode::Cast(x14_child->Clone()), - x18_timeScale->Clone(), x28_targetAccelTime, x4_name); +std::experimental::optional> CAnimTreeTimeScale::VSimplified() { + if (auto simp = x14_child->Simplified()) { + CAnimTreeTimeScale* newNode = new CAnimTreeTimeScale(CAnimTreeNode::Cast(std::move(*simp)), x18_timeScale->Clone(), + x28_targetAccelTime, x4_name); newNode->x20_curAccelTime = x20_curAccelTime; newNode->x30_initialTime = x30_initialTime; return {std::unique_ptr(newNode)}; + } else if (x20_curAccelTime == x28_targetAccelTime) { + return {x14_child->Clone()}; + } + return {}; } -CSteadyStateAnimInfo CAnimTreeTimeScale::VGetSteadyStateAnimInfo() const -{ - CSteadyStateAnimInfo ssInfo = x14_child->VGetSteadyStateAnimInfo(); - if (x28_targetAccelTime == CCharAnimTime::Infinity()) - { - return {ssInfo.IsLooping(), - x18_timeScale->VFindUpperLimit(0.f, ssInfo.GetDuration().GetSeconds()), ssInfo.GetOffset()}; - } - else - { - CCharAnimTime time; - if (x20_curAccelTime.GreaterThanZero()) - time = x18_timeScale->VTimeScaleIntegral(0.f, x20_curAccelTime.GetSeconds()); - return {ssInfo.IsLooping(), x30_initialTime + time + VGetTimeRemaining(), ssInfo.GetOffset()}; +u32 CAnimTreeTimeScale::VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + CCharAnimTime useTime = (time == CCharAnimTime::Infinity()) ? x14_child->VGetTimeRemaining() : GetRealLifeTime(time); + u32 ret = x14_child->GetBoolPOIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) + for (int i = 0; i < ret; ++i) + listOut[iterator + i].SetTime(GetRealLifeTime(listOut[i].GetTime())); + return ret; +} + +u32 CAnimTreeTimeScale::VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + CCharAnimTime useTime = (time == CCharAnimTime::Infinity()) ? x14_child->VGetTimeRemaining() : GetRealLifeTime(time); + u32 ret = x14_child->GetInt32POIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) + for (int i = 0; i < ret; ++i) + listOut[iterator + i].SetTime(GetRealLifeTime(listOut[i].GetTime())); + return ret; +} + +u32 CAnimTreeTimeScale::VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, + u32 iterator, u32 unk) const { + CCharAnimTime useTime = (time == CCharAnimTime::Infinity()) ? x14_child->VGetTimeRemaining() : GetRealLifeTime(time); + u32 ret = x14_child->GetParticlePOIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) + for (int i = 0; i < ret; ++i) + listOut[iterator + i].SetTime(GetRealLifeTime(listOut[i].GetTime())); + return ret; +} + +u32 CAnimTreeTimeScale::VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + CCharAnimTime useTime = (time == CCharAnimTime::Infinity()) ? x14_child->VGetTimeRemaining() : GetRealLifeTime(time); + u32 ret = x14_child->GetSoundPOIList(useTime, listOut, capacity, iterator, unk); + if (x28_targetAccelTime > CCharAnimTime()) + for (int i = 0; i < ret; ++i) + listOut[iterator + i].SetTime(GetRealLifeTime(listOut[i].GetTime())); + return ret; +} + +bool CAnimTreeTimeScale::VGetBoolPOIState(const char* name) const { return x14_child->VGetBoolPOIState(name); } + +s32 CAnimTreeTimeScale::VGetInt32POIState(const char* name) const { return x14_child->VGetInt32POIState(name); } + +CParticleData::EParentedMode CAnimTreeTimeScale::VGetParticlePOIState(const char* name) const { + return x14_child->VGetParticlePOIState(name); +} + +CAnimTreeEffectiveContribution CAnimTreeTimeScale::VGetContributionOfHighestInfluence() const { + CAnimTreeEffectiveContribution c = x14_child->VGetContributionOfHighestInfluence(); + return {c.GetContributionWeight(), c.GetPrimitiveName(), VGetSteadyStateAnimInfo(), VGetTimeRemaining(), + c.GetAnimDatabaseIndex()}; +} + +std::shared_ptr CAnimTreeTimeScale::VGetBestUnblendedChild() const { + if (std::shared_ptr bestChild = x14_child->VGetBestUnblendedChild()) { + CAnimTreeTimeScale* newNode = new CAnimTreeTimeScale(CAnimTreeNode::Cast(bestChild->Clone()), + x18_timeScale->Clone(), x28_targetAccelTime, x4_name); + newNode->x20_curAccelTime = x20_curAccelTime; + newNode->x30_initialTime = x30_initialTime; + return {std::shared_ptr(newNode)}; + } + return {}; +} + +std::unique_ptr CAnimTreeTimeScale::VClone() const { + CAnimTreeTimeScale* newNode = new CAnimTreeTimeScale(CAnimTreeNode::Cast(x14_child->Clone()), x18_timeScale->Clone(), + x28_targetAccelTime, x4_name); + newNode->x20_curAccelTime = x20_curAccelTime; + newNode->x30_initialTime = x30_initialTime; + return {std::unique_ptr(newNode)}; +} + +CSteadyStateAnimInfo CAnimTreeTimeScale::VGetSteadyStateAnimInfo() const { + CSteadyStateAnimInfo ssInfo = x14_child->VGetSteadyStateAnimInfo(); + if (x28_targetAccelTime == CCharAnimTime::Infinity()) { + return {ssInfo.IsLooping(), x18_timeScale->VFindUpperLimit(0.f, ssInfo.GetDuration().GetSeconds()), + ssInfo.GetOffset()}; + } else { + CCharAnimTime time; + if (x20_curAccelTime.GreaterThanZero()) + time = x18_timeScale->VTimeScaleIntegral(0.f, x20_curAccelTime.GetSeconds()); + return {ssInfo.IsLooping(), x30_initialTime + time + VGetTimeRemaining(), ssInfo.GetOffset()}; + } +} + +CCharAnimTime CAnimTreeTimeScale::VGetTimeRemaining() const { + CCharAnimTime timeRem = x14_child->VGetTimeRemaining(); + if (x28_targetAccelTime == CCharAnimTime::Infinity()) + return CCharAnimTime(x18_timeScale->VFindUpperLimit(x20_curAccelTime.GetSeconds(), timeRem.GetSeconds())) - + x20_curAccelTime; + else + return GetRealLifeTime(timeRem); +} + +SAdvancementResults CAnimTreeTimeScale::VAdvanceView(const CCharAnimTime& dt) { + if (dt.EqualsZero() && dt > CCharAnimTime()) + return x14_child->VAdvanceView(dt); + + CCharAnimTime origAccelTime = x20_curAccelTime; + CCharAnimTime newTime = x20_curAccelTime + dt; + if (newTime < x28_targetAccelTime) { + SAdvancementResults res = + x14_child->VAdvanceView(x18_timeScale->VTimeScaleIntegral(origAccelTime.GetSeconds(), newTime.GetSeconds())); + if (res.x0_remTime.EqualsZero()) { + x20_curAccelTime = newTime; + res.x0_remTime = CCharAnimTime(); + return res; + } else { + x20_curAccelTime = + x18_timeScale->VFindUpperLimit(origAccelTime.GetSeconds(), (newTime - res.x0_remTime).GetSeconds()); + res.x0_remTime = dt - (x20_curAccelTime - origAccelTime); + return res; } + } else { + CCharAnimTime newDt( + x18_timeScale->VTimeScaleIntegral(origAccelTime.GetSeconds(), x28_targetAccelTime.GetSeconds())); + SAdvancementResults res2; + if (newDt.GreaterThanZero()) + res2 = x14_child->VAdvanceView(newDt); + res2.x0_remTime = res2.x0_remTime + (newTime - x28_targetAccelTime); + return res2; + } } -CCharAnimTime CAnimTreeTimeScale::VGetTimeRemaining() const -{ - CCharAnimTime timeRem = x14_child->VGetTimeRemaining(); - if (x28_targetAccelTime == CCharAnimTime::Infinity()) - return CCharAnimTime(x18_timeScale->VFindUpperLimit(x20_curAccelTime.GetSeconds(), - timeRem.GetSeconds())) - x20_curAccelTime; - else - return GetRealLifeTime(timeRem); -} - -SAdvancementResults CAnimTreeTimeScale::VAdvanceView(const CCharAnimTime& dt) -{ - if (dt.EqualsZero() && dt > CCharAnimTime()) - return x14_child->VAdvanceView(dt); - - CCharAnimTime origAccelTime = x20_curAccelTime; - CCharAnimTime newTime = x20_curAccelTime + dt; - if (newTime < x28_targetAccelTime) - { - SAdvancementResults res = x14_child->VAdvanceView( - x18_timeScale->VTimeScaleIntegral(origAccelTime.GetSeconds(), newTime.GetSeconds())); - if (res.x0_remTime.EqualsZero()) - { - x20_curAccelTime = newTime; - res.x0_remTime = CCharAnimTime(); - return res; - } - else - { - x20_curAccelTime = x18_timeScale->VFindUpperLimit(origAccelTime.GetSeconds(), - (newTime - res.x0_remTime).GetSeconds()); - res.x0_remTime = dt - (x20_curAccelTime - origAccelTime); - return res; - } - } - else - { - CCharAnimTime newDt(x18_timeScale->VTimeScaleIntegral(origAccelTime.GetSeconds(), - x28_targetAccelTime.GetSeconds())); - SAdvancementResults res2; - if (newDt.GreaterThanZero()) - res2 = x14_child->VAdvanceView(newDt); - res2.x0_remTime = res2.x0_remTime + (newTime - x28_targetAccelTime); - return res2; - } -} - -} +} // namespace urde diff --git a/Runtime/Character/CAnimTreeTimeScale.hpp b/Runtime/Character/CAnimTreeTimeScale.hpp index 209f638df..3d21d918f 100644 --- a/Runtime/Character/CAnimTreeTimeScale.hpp +++ b/Runtime/Character/CAnimTreeTimeScale.hpp @@ -3,42 +3,39 @@ #include "CAnimTreeSingleChild.hpp" #include "CTimeScaleFunctions.hpp" -namespace urde -{ +namespace urde { + +class CAnimTreeTimeScale : public CAnimTreeSingleChild { + std::unique_ptr x18_timeScale; + CCharAnimTime x20_curAccelTime; + CCharAnimTime x28_targetAccelTime; + CCharAnimTime x30_initialTime; -class CAnimTreeTimeScale : public CAnimTreeSingleChild -{ - std::unique_ptr x18_timeScale; - CCharAnimTime x20_curAccelTime; - CCharAnimTime x28_targetAccelTime; - CCharAnimTime x30_initialTime; public: - CAnimTreeTimeScale(const std::weak_ptr& node, float timeScale, std::string_view name); - CAnimTreeTimeScale(const std::weak_ptr& node, - std::unique_ptr&& timeScale, - const CCharAnimTime& time, std::string_view name); + CAnimTreeTimeScale(const std::weak_ptr& node, float timeScale, std::string_view name); + CAnimTreeTimeScale(const std::weak_ptr& node, std::unique_ptr&& timeScale, + const CCharAnimTime& time, std::string_view name); - static std::string CreatePrimitiveName(const std::weak_ptr&, float, const CCharAnimTime&, float); + static std::string CreatePrimitiveName(const std::weak_ptr&, float, const CCharAnimTime&, float); - CCharAnimTime GetRealLifeTime(const CCharAnimTime&) const; - void VSetPhase(float); - std::experimental::optional> VSimplified(); + CCharAnimTime GetRealLifeTime(const CCharAnimTime&) const; + void VSetPhase(float); + std::experimental::optional> VSimplified(); - u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; - bool VGetBoolPOIState(const char* name) const; - s32 VGetInt32POIState(const char* name) const; - CParticleData::EParentedMode VGetParticlePOIState(const char* name) const; + u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + bool VGetBoolPOIState(const char* name) const; + s32 VGetInt32POIState(const char* name) const; + CParticleData::EParentedMode VGetParticlePOIState(const char* name) const; - CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; - std::shared_ptr VGetBestUnblendedChild() const; - std::unique_ptr VClone() const; - CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; - CCharAnimTime VGetTimeRemaining() const; - SAdvancementResults VAdvanceView(const CCharAnimTime& dt); + CAnimTreeEffectiveContribution VGetContributionOfHighestInfluence() const; + std::shared_ptr VGetBestUnblendedChild() const; + std::unique_ptr VClone() const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + CCharAnimTime VGetTimeRemaining() const; + SAdvancementResults VAdvanceView(const CCharAnimTime& dt); }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeTransition.cpp b/Runtime/Character/CAnimTreeTransition.cpp index 4d74dfaa7..620f314a7 100644 --- a/Runtime/Character/CAnimTreeTransition.cpp +++ b/Runtime/Character/CAnimTreeTransition.cpp @@ -1,164 +1,139 @@ #include "CAnimTreeTransition.hpp" -namespace urde -{ +namespace urde { std::string CAnimTreeTransition::CreatePrimitiveName(const std::weak_ptr&, - const std::weak_ptr&, float) -{ - return {}; + const std::weak_ptr&, float) { + return {}; } CAnimTreeTransition::CAnimTreeTransition(bool b1, const std::weak_ptr& a, const std::weak_ptr& b, const CCharAnimTime& transDur, const CCharAnimTime& timeInTrans, bool runA, bool loopA, int flags, std::string_view name, bool initialized) -: CAnimTreeTweenBase(b1, a, b, flags, name), x24_transDur(transDur), x2c_timeInTrans(timeInTrans), - x34_runA(runA), x35_loopA(loopA), x36_initialized(initialized) -{ -} +: CAnimTreeTweenBase(b1, a, b, flags, name) +, x24_transDur(transDur) +, x2c_timeInTrans(timeInTrans) +, x34_runA(runA) +, x35_loopA(loopA) +, x36_initialized(initialized) {} CAnimTreeTransition::CAnimTreeTransition(bool b1, const std::weak_ptr& a, - const std::weak_ptr& b, - const CCharAnimTime& transDur, bool runA, - int flags, std::string_view name) -: CAnimTreeTweenBase(b1, a, b, flags, name), x24_transDur(transDur), x34_runA(runA), - x35_loopA(a.lock()->VGetBoolPOIState("Loop")) -{ + const std::weak_ptr& b, const CCharAnimTime& transDur, + bool runA, int flags, std::string_view name) +: CAnimTreeTweenBase(b1, a, b, flags, name) +, x24_transDur(transDur) +, x34_runA(runA) +, x35_loopA(a.lock()->VGetBoolPOIState("Loop")) {} + +std::shared_ptr CAnimTreeTransition::VGetBestUnblendedChild() const { + std::shared_ptr child = x18_b->GetBestUnblendedChild(); + return (child ? child : x18_b); } -std::shared_ptr CAnimTreeTransition::VGetBestUnblendedChild() const -{ - std::shared_ptr child = x18_b->GetBestUnblendedChild(); - return (child ? child : x18_b); +CCharAnimTime CAnimTreeTransition::VGetTimeRemaining() const { + CCharAnimTime transTimeRem = x24_transDur - x2c_timeInTrans; + CCharAnimTime rightTimeRem = x18_b->VGetTimeRemaining(); + return (rightTimeRem < transTimeRem) ? transTimeRem : rightTimeRem; } -CCharAnimTime CAnimTreeTransition::VGetTimeRemaining() const -{ - CCharAnimTime transTimeRem = x24_transDur - x2c_timeInTrans; - CCharAnimTime rightTimeRem = x18_b->VGetTimeRemaining(); - return (rightTimeRem < transTimeRem) ? transTimeRem : rightTimeRem; +CSteadyStateAnimInfo CAnimTreeTransition::VGetSteadyStateAnimInfo() const { + CSteadyStateAnimInfo bInfo = x18_b->VGetSteadyStateAnimInfo(); + + if (x24_transDur < bInfo.GetDuration()) + return CSteadyStateAnimInfo(bInfo.IsLooping(), bInfo.GetDuration(), bInfo.GetOffset()); + return CSteadyStateAnimInfo(bInfo.IsLooping(), x24_transDur, bInfo.GetOffset()); } -CSteadyStateAnimInfo CAnimTreeTransition::VGetSteadyStateAnimInfo() const -{ - CSteadyStateAnimInfo bInfo = x18_b->VGetSteadyStateAnimInfo(); - - if (x24_transDur < bInfo.GetDuration()) - return CSteadyStateAnimInfo(bInfo.IsLooping(), bInfo.GetDuration(), bInfo.GetOffset()); - return CSteadyStateAnimInfo(bInfo.IsLooping(), x24_transDur, bInfo.GetOffset()); +std::unique_ptr CAnimTreeTransition::VClone() const { + return std::make_unique( + x20_24_b1, std::static_pointer_cast(std::shared_ptr(x14_a->Clone())), + std::static_pointer_cast(std::shared_ptr(x18_b->Clone())), x24_transDur, + x2c_timeInTrans, x34_runA, x35_loopA, x1c_flags, x4_name, x36_initialized); } -std::unique_ptr CAnimTreeTransition::VClone() const -{ - return std::make_unique(x20_24_b1, std::static_pointer_cast( - std::shared_ptr(x14_a->Clone())), - std::static_pointer_cast( - std::shared_ptr(x18_b->Clone())), - x24_transDur, x2c_timeInTrans, x34_runA, - x35_loopA, x1c_flags, x4_name, x36_initialized); +std::experimental::optional> CAnimTreeTransition::VSimplified() { + if (zeus::close_enough(GetBlendingWeight(), 1.f)) { + if (auto simp = x18_b->Simplified()) + return simp; + return {x18_b->Clone()}; + } + return CAnimTreeTweenBase::VSimplified(); } -std::experimental::optional> CAnimTreeTransition::VSimplified() -{ - if (zeus::close_enough(GetBlendingWeight(), 1.f)) - { - if (auto simp = x18_b->Simplified()) - return simp; - return {x18_b->Clone()}; - } - return CAnimTreeTweenBase::VSimplified(); +std::experimental::optional> CAnimTreeTransition::VReverseSimplified() { + if (zeus::close_enough(GetBlendingWeight(), 0.f)) + return {x14_a->Clone()}; + return CAnimTreeTweenBase::VReverseSimplified(); } -std::experimental::optional> CAnimTreeTransition::VReverseSimplified() -{ - if (zeus::close_enough(GetBlendingWeight(), 0.f)) - return {x14_a->Clone()}; - return CAnimTreeTweenBase::VReverseSimplified(); +SAdvancementResults CAnimTreeTransition::AdvanceViewForTransitionalPeriod(const CCharAnimTime& time) { + IncAdvancementDepth(); + CDoubleChildAdvancementResult res = AdvanceViewBothChildren(time, x34_runA, x35_loopA); + DecAdvancementDepth(); + if (res.GetTrueAdvancement().EqualsZero()) + return {}; + + float oldWeight = GetBlendingWeight(); + x2c_timeInTrans += res.GetTrueAdvancement(); + float newWeight = GetBlendingWeight(); + + if (ShouldCullTree()) { + if (newWeight < 0.5f) + x20_25_cullSelector = 1; + else + x20_25_cullSelector = 2; + } + + if (x1c_flags & 0x1) { + return {res.GetTrueAdvancement(), + SAdvancementDeltas::Interpolate(res.GetLeftAdvancementDeltas(), res.GetRightAdvancementDeltas(), oldWeight, + newWeight)}; + } + + return {res.GetTrueAdvancement(), res.GetRightAdvancementDeltas()}; } -SAdvancementResults CAnimTreeTransition::AdvanceViewForTransitionalPeriod(const CCharAnimTime& time) -{ +SAdvancementResults CAnimTreeTransition::VAdvanceView(const CCharAnimTime& time) { + if (time.EqualsZero()) { IncAdvancementDepth(); - CDoubleChildAdvancementResult res = AdvanceViewBothChildren(time, x34_runA, x35_loopA); + x18_b->VAdvanceView(time); + if (x34_runA) + x14_a->VAdvanceView(time); DecAdvancementDepth(); - if (res.GetTrueAdvancement().EqualsZero()) - return {}; - - float oldWeight = GetBlendingWeight(); - x2c_timeInTrans += res.GetTrueAdvancement(); - float newWeight = GetBlendingWeight(); - if (ShouldCullTree()) - { - if (newWeight < 0.5f) - x20_25_cullSelector = 1; - else - x20_25_cullSelector = 2; - } + x20_25_cullSelector = 1; + return {}; + } - if (x1c_flags & 0x1) - { - return { - res.GetTrueAdvancement(), - SAdvancementDeltas::Interpolate(res.GetLeftAdvancementDeltas(), - res.GetRightAdvancementDeltas(), - oldWeight, newWeight) - }; - } + if (!x36_initialized) + x36_initialized = true; - return { - res.GetTrueAdvancement(), - res.GetRightAdvancementDeltas() - }; -} - -SAdvancementResults CAnimTreeTransition::VAdvanceView(const CCharAnimTime& time) -{ - if (time.EqualsZero()) - { - IncAdvancementDepth(); - x18_b->VAdvanceView(time); - if (x34_runA) - x14_a->VAdvanceView(time); - DecAdvancementDepth(); - if (ShouldCullTree()) - x20_25_cullSelector = 1; - return {}; - } - - if (!x36_initialized) - x36_initialized = true; - - if (x2c_timeInTrans + time < x24_transDur) - { - SAdvancementResults res = AdvanceViewForTransitionalPeriod(time); - res.x0_remTime = time - res.x0_remTime; - return res; - } - - CCharAnimTime transTimeRem = x24_transDur - x2c_timeInTrans; - SAdvancementResults res; - if (transTimeRem.GreaterThanZero()) - { - res = AdvanceViewForTransitionalPeriod(transTimeRem); - if (res.x0_remTime != transTimeRem) - return res; - } - - res.x0_remTime = time - transTimeRem; + if (x2c_timeInTrans + time < x24_transDur) { + SAdvancementResults res = AdvanceViewForTransitionalPeriod(time); + res.x0_remTime = time - res.x0_remTime; return res; + } + + CCharAnimTime transTimeRem = x24_transDur - x2c_timeInTrans; + SAdvancementResults res; + if (transTimeRem.GreaterThanZero()) { + res = AdvanceViewForTransitionalPeriod(transTimeRem); + if (res.x0_remTime != transTimeRem) + return res; + } + + res.x0_remTime = time - transTimeRem; + return res; } -void CAnimTreeTransition::SetBlendingWeight(float w) -{ - std::static_pointer_cast(x18_b)->SetBlendingWeight(w); +void CAnimTreeTransition::SetBlendingWeight(float w) { + std::static_pointer_cast(x18_b)->SetBlendingWeight(w); } -float CAnimTreeTransition::VGetBlendingWeight() const -{ - if (x24_transDur.GreaterThanZero()) - return x2c_timeInTrans.GetSeconds() / x24_transDur.GetSeconds(); - return 0.f; -} +float CAnimTreeTransition::VGetBlendingWeight() const { + if (x24_transDur.GreaterThanZero()) + return x2c_timeInTrans.GetSeconds() / x24_transDur.GetSeconds(); + return 0.f; } +} // namespace urde diff --git a/Runtime/Character/CAnimTreeTransition.hpp b/Runtime/Character/CAnimTreeTransition.hpp index fcc527c42..2c407bf65 100644 --- a/Runtime/Character/CAnimTreeTransition.hpp +++ b/Runtime/Character/CAnimTreeTransition.hpp @@ -3,40 +3,34 @@ #include "RetroTypes.hpp" #include "CAnimTreeTweenBase.hpp" -namespace urde -{ +namespace urde { -class CAnimTreeTransition : public CAnimTreeTweenBase -{ +class CAnimTreeTransition : public CAnimTreeTweenBase { protected: - CCharAnimTime x24_transDur; - CCharAnimTime x2c_timeInTrans; - bool x34_runA; - bool x35_loopA; - bool x36_initialized = false; - SAdvancementResults AdvanceViewForTransitionalPeriod(const CCharAnimTime& time); + CCharAnimTime x24_transDur; + CCharAnimTime x2c_timeInTrans; + bool x34_runA; + bool x35_loopA; + bool x36_initialized = false; + SAdvancementResults AdvanceViewForTransitionalPeriod(const CCharAnimTime& time); + public: - static std::string CreatePrimitiveName(const std::weak_ptr&, - const std::weak_ptr&, - float); + static std::string CreatePrimitiveName(const std::weak_ptr&, const std::weak_ptr&, + float); - CAnimTreeTransition(bool b1, const std::weak_ptr& a, - const std::weak_ptr& b, const CCharAnimTime& transDur, - const CCharAnimTime& timeInTrans, bool runA, bool loopA, int flags, - std::string_view name, bool initialized); - CAnimTreeTransition(bool b1, const std::weak_ptr& a, - const std::weak_ptr& b, - const CCharAnimTime& transDur, bool runA, - int flags, std::string_view name); - std::shared_ptr VGetBestUnblendedChild() const; - CCharAnimTime VGetTimeRemaining() const; - CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; - std::unique_ptr VClone() const; - std::experimental::optional> VSimplified(); - std::experimental::optional> VReverseSimplified(); - SAdvancementResults VAdvanceView(const CCharAnimTime& a); - void SetBlendingWeight(float w); - float VGetBlendingWeight() const; + CAnimTreeTransition(bool b1, const std::weak_ptr& a, const std::weak_ptr& b, + const CCharAnimTime& transDur, const CCharAnimTime& timeInTrans, bool runA, bool loopA, int flags, + std::string_view name, bool initialized); + CAnimTreeTransition(bool b1, const std::weak_ptr& a, const std::weak_ptr& b, + const CCharAnimTime& transDur, bool runA, int flags, std::string_view name); + std::shared_ptr VGetBestUnblendedChild() const; + CCharAnimTime VGetTimeRemaining() const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + std::unique_ptr VClone() const; + std::experimental::optional> VSimplified(); + std::experimental::optional> VReverseSimplified(); + SAdvancementResults VAdvanceView(const CCharAnimTime& a); + void SetBlendingWeight(float w); + float VGetBlendingWeight() const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimTreeTweenBase.cpp b/Runtime/Character/CAnimTreeTweenBase.cpp index d11df2781..6781c343b 100644 --- a/Runtime/Character/CAnimTreeTweenBase.cpp +++ b/Runtime/Character/CAnimTreeTweenBase.cpp @@ -2,157 +2,127 @@ #include "CSegStatementSet.hpp" #include "CSegIdList.hpp" -namespace urde -{ +namespace urde { s32 CAnimTreeTweenBase::sAdvancementDepth = 0; CAnimTreeTweenBase::CAnimTreeTweenBase(bool b1, const std::weak_ptr& a, const std::weak_ptr& b, int flags, std::string_view name) -: CAnimTreeDoubleChild(a, b, name), x1c_flags(flags) -{ - x20_24_b1 = b1; - x20_25_cullSelector = 0; +: CAnimTreeDoubleChild(a, b, name), x1c_flags(flags) { + x20_24_b1 = b1; + x20_25_cullSelector = 0; } void CAnimTreeTweenBase::VGetWeightedReaders( - rstl::reserved_vector>, 16>& out, float w) const -{ - float weight = GetBlendingWeight(); - x14_a->VGetWeightedReaders(out, (1.f - weight) * w); - x18_b->VGetWeightedReaders(out, weight * w); + rstl::reserved_vector>, 16>& out, float w) const { + float weight = GetBlendingWeight(); + x14_a->VGetWeightedReaders(out, (1.f - weight) * w); + x18_b->VGetWeightedReaders(out, weight * w); } -void CAnimTreeTweenBase::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const -{ - float w = GetBlendingWeight(); - static int sStack = 0; - ++sStack; - if (w >= 1.f) - { - x18_b->VGetSegStatementSet(list, setOut); - } - else if (sStack > 3) - { - auto& n = w > 0.5f ? x18_b : x14_a; - auto ptr = n->GetBestUnblendedChild(); - if (!ptr) - ptr = n; - ptr->VGetSegStatementSet(list, setOut); - } - else - { - CSegStatementSet setA, setB; - x14_a->VGetSegStatementSet(list, setA); - x18_b->VGetSegStatementSet(list, setB); - for (CSegId id : list.GetList()) - { - if (w < 0.0001f) - { - setOut[id].x0_rotation = setA[id].x0_rotation; - if (setA[id].x1c_hasOffset) - { - setOut[id].x10_offset = setA[id].x10_offset; - setOut[id].x1c_hasOffset = true; - } - } - else - { - setOut[id].x0_rotation = zeus::CQuaternion::slerpShort(setA[id].x0_rotation, setB[id].x0_rotation, w); - if (setA[id].x1c_hasOffset && setB[id].x1c_hasOffset) - { - setOut[id].x10_offset = zeus::CVector3f::lerp(setA[id].x10_offset, setB[id].x10_offset, w); - setOut[id].x1c_hasOffset = true; - } - } +void CAnimTreeTweenBase::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const { + float w = GetBlendingWeight(); + static int sStack = 0; + ++sStack; + if (w >= 1.f) { + x18_b->VGetSegStatementSet(list, setOut); + } else if (sStack > 3) { + auto& n = w > 0.5f ? x18_b : x14_a; + auto ptr = n->GetBestUnblendedChild(); + if (!ptr) + ptr = n; + ptr->VGetSegStatementSet(list, setOut); + } else { + CSegStatementSet setA, setB; + x14_a->VGetSegStatementSet(list, setA); + x18_b->VGetSegStatementSet(list, setB); + for (CSegId id : list.GetList()) { + if (w < 0.0001f) { + setOut[id].x0_rotation = setA[id].x0_rotation; + if (setA[id].x1c_hasOffset) { + setOut[id].x10_offset = setA[id].x10_offset; + setOut[id].x1c_hasOffset = true; } + } else { + setOut[id].x0_rotation = zeus::CQuaternion::slerpShort(setA[id].x0_rotation, setB[id].x0_rotation, w); + if (setA[id].x1c_hasOffset && setB[id].x1c_hasOffset) { + setOut[id].x10_offset = zeus::CVector3f::lerp(setA[id].x10_offset, setB[id].x10_offset, w); + setOut[id].x1c_hasOffset = true; + } + } } - --sStack; + } + --sStack; } void CAnimTreeTweenBase::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, - const CCharAnimTime& time) const -{ - float w = GetBlendingWeight(); - static int sStack = 0; - ++sStack; - if (w >= 1.f) - { - x18_b->VGetSegStatementSet(list, setOut, time); - } - else if (sStack > 3) - { - auto& n = w > 0.5f ? x18_b : x14_a; - n->GetBestUnblendedChild()->VGetSegStatementSet(list, setOut, time); + const CCharAnimTime& time) const { + float w = GetBlendingWeight(); + static int sStack = 0; + ++sStack; + if (w >= 1.f) { + x18_b->VGetSegStatementSet(list, setOut, time); + } else if (sStack > 3) { + auto& n = w > 0.5f ? x18_b : x14_a; + n->GetBestUnblendedChild()->VGetSegStatementSet(list, setOut, time); + } else { + CSegStatementSet setA, setB; + x14_a->VGetSegStatementSet(list, setA, time); + x18_b->VGetSegStatementSet(list, setB, time); + for (CSegId id : list.GetList()) { + setOut[id].x0_rotation = zeus::CQuaternion::slerpShort(setA[id].x0_rotation, setB[id].x0_rotation, w); + if (setA[id].x1c_hasOffset && setB[id].x1c_hasOffset) { + setOut[id].x10_offset = zeus::CVector3f::lerp(setA[id].x10_offset, setB[id].x10_offset, w); + setOut[id].x1c_hasOffset = true; + } } + } + --sStack; +} + +bool CAnimTreeTweenBase::VHasOffset(const CSegId& seg) const { + return (x14_a->VHasOffset(seg) && x18_b->VHasOffset(seg)); +} + +zeus::CVector3f CAnimTreeTweenBase::VGetOffset(const CSegId& seg) const { + const float weight = GetBlendingWeight(); + if (weight >= 1.0f) + return x18_b->VGetOffset(seg); + + const zeus::CVector3f oA = x14_a->VGetOffset(seg); + const zeus::CVector3f oB = x18_b->VGetOffset(seg); + return zeus::CVector3f::lerp(oA, oB, weight); +} + +zeus::CQuaternion CAnimTreeTweenBase::VGetRotation(const CSegId& seg) const { + const float weight = GetBlendingWeight(); + if (weight >= 1.0f) + return x18_b->VGetRotation(seg); + + const zeus::CQuaternion qA = x14_a->VGetRotation(seg); + const zeus::CQuaternion qB = x18_b->VGetRotation(seg); + return zeus::CQuaternion::slerp(qA, qB, weight); +} + +std::experimental::optional> CAnimTreeTweenBase::VSimplified() { + if (x20_25_cullSelector == 0) { + auto simpA = x14_a->Simplified(); + auto simpB = x18_b->Simplified(); + if (!simpA && !simpB) + return {}; + auto clone = Clone(); + if (simpA) + static_cast(*clone).x14_a = CAnimTreeNode::Cast(std::move(*simpA)); + if (simpB) + static_cast(*clone).x18_b = CAnimTreeNode::Cast(std::move(*simpB)); + return {std::move(clone)}; + } else { + auto tmp = (x20_25_cullSelector == 1) ? x18_b : x14_a; + auto tmpUnblended = tmp->GetBestUnblendedChild(); + if (!tmpUnblended) + return {tmp->Clone()}; else - { - CSegStatementSet setA, setB; - x14_a->VGetSegStatementSet(list, setA, time); - x18_b->VGetSegStatementSet(list, setB, time); - for (CSegId id : list.GetList()) - { - setOut[id].x0_rotation = zeus::CQuaternion::slerpShort(setA[id].x0_rotation, setB[id].x0_rotation, w); - if (setA[id].x1c_hasOffset && setB[id].x1c_hasOffset) - { - setOut[id].x10_offset = zeus::CVector3f::lerp(setA[id].x10_offset, setB[id].x10_offset, w); - setOut[id].x1c_hasOffset = true; - } - } - } - --sStack; -} - -bool CAnimTreeTweenBase::VHasOffset(const CSegId& seg) const -{ - return (x14_a->VHasOffset(seg) && x18_b->VHasOffset(seg)); -} - -zeus::CVector3f CAnimTreeTweenBase::VGetOffset(const CSegId& seg) const -{ - const float weight = GetBlendingWeight(); - if (weight >= 1.0f) - return x18_b->VGetOffset(seg); - - const zeus::CVector3f oA = x14_a->VGetOffset(seg); - const zeus::CVector3f oB = x18_b->VGetOffset(seg); - return zeus::CVector3f::lerp(oA, oB, weight); -} - -zeus::CQuaternion CAnimTreeTweenBase::VGetRotation(const CSegId& seg) const -{ - const float weight = GetBlendingWeight(); - if (weight >= 1.0f) - return x18_b->VGetRotation(seg); - - const zeus::CQuaternion qA = x14_a->VGetRotation(seg); - const zeus::CQuaternion qB = x18_b->VGetRotation(seg); - return zeus::CQuaternion::slerp(qA, qB, weight); -} - -std::experimental::optional> CAnimTreeTweenBase::VSimplified() -{ - if (x20_25_cullSelector == 0) - { - auto simpA = x14_a->Simplified(); - auto simpB = x18_b->Simplified(); - if (!simpA && !simpB) - return {}; - auto clone = Clone(); - if (simpA) - static_cast(*clone).x14_a = CAnimTreeNode::Cast(std::move(*simpA)); - if (simpB) - static_cast(*clone).x18_b = CAnimTreeNode::Cast(std::move(*simpB)); - return {std::move(clone)}; - } - else - { - auto tmp = (x20_25_cullSelector == 1) ? x18_b : x14_a; - auto tmpUnblended = tmp->GetBestUnblendedChild(); - if (!tmpUnblended) - return {tmp->Clone()}; - else - return {tmpUnblended->Clone()}; - } -} + return {tmpUnblended->Clone()}; + } } +} // namespace urde diff --git a/Runtime/Character/CAnimTreeTweenBase.hpp b/Runtime/Character/CAnimTreeTweenBase.hpp index 0ddddd260..cde1c5f54 100644 --- a/Runtime/Character/CAnimTreeTweenBase.hpp +++ b/Runtime/Character/CAnimTreeTweenBase.hpp @@ -2,44 +2,42 @@ #include "CAnimTreeDoubleChild.hpp" -namespace urde -{ +namespace urde { + +class CAnimTreeTweenBase : public CAnimTreeDoubleChild { + static s32 sAdvancementDepth; -class CAnimTreeTweenBase : public CAnimTreeDoubleChild -{ - static s32 sAdvancementDepth; protected: - int x1c_flags; - bool x20_24_b1 : 1; - u8 x20_25_cullSelector : 2; + int x1c_flags; + bool x20_24_b1 : 1; + u8 x20_25_cullSelector : 2; + public: - CAnimTreeTweenBase(bool, - const std::weak_ptr& a, - const std::weak_ptr& b, - int, std::string_view name); + CAnimTreeTweenBase(bool, const std::weak_ptr& a, const std::weak_ptr& b, int, + std::string_view name); - virtual void SetBlendingWeight(float w)=0; - virtual float VGetBlendingWeight() const=0; + virtual void SetBlendingWeight(float w) = 0; + virtual float VGetBlendingWeight() const = 0; - float GetBlendingWeight() const { return VGetBlendingWeight(); } + float GetBlendingWeight() const { return VGetBlendingWeight(); } - void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const; - float VGetRightChildWeight() const { return GetBlendingWeight(); } + void VGetWeightedReaders(rstl::reserved_vector>, 16>& out, float w) const; + float VGetRightChildWeight() const { return GetBlendingWeight(); } - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; - bool VHasOffset(const CSegId& seg) const; - zeus::CVector3f VGetOffset(const CSegId& seg) const; - zeus::CQuaternion VGetRotation(const CSegId& seg) const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; + bool VHasOffset(const CSegId& seg) const; + zeus::CVector3f VGetOffset(const CSegId& seg) const; + zeus::CQuaternion VGetRotation(const CSegId& seg) const; - std::experimental::optional> VSimplified(); - virtual std::experimental::optional> VReverseSimplified() - { return CAnimTreeTweenBase::VSimplified(); } + std::experimental::optional> VSimplified(); + virtual std::experimental::optional> VReverseSimplified() { + return CAnimTreeTweenBase::VSimplified(); + } - static bool ShouldCullTree() { return 3 <= sAdvancementDepth; } - static void IncAdvancementDepth() { sAdvancementDepth++; } - static void DecAdvancementDepth() { sAdvancementDepth--; } + static bool ShouldCullTree() { return 3 <= sAdvancementDepth; } + static void IncAdvancementDepth() { sAdvancementDepth++; } + static void DecAdvancementDepth() { sAdvancementDepth--; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimation.cpp b/Runtime/Character/CAnimation.cpp index 280a463a1..ebdf8b2c4 100644 --- a/Runtime/Character/CAnimation.cpp +++ b/Runtime/Character/CAnimation.cpp @@ -1,13 +1,11 @@ #include "CAnimation.hpp" #include "CMetaAnimFactory.hpp" -namespace urde -{ +namespace urde { -CAnimation::CAnimation(CInputStream& in) -{ - x0_name = in.readString(); - x10_anim = CMetaAnimFactory::CreateMetaAnim(in); +CAnimation::CAnimation(CInputStream& in) { + x0_name = in.readString(); + x10_anim = CMetaAnimFactory::CreateMetaAnim(in); } -} +} // namespace urde diff --git a/Runtime/Character/CAnimation.hpp b/Runtime/Character/CAnimation.hpp index 5492e59c5..589c2814b 100644 --- a/Runtime/Character/CAnimation.hpp +++ b/Runtime/Character/CAnimation.hpp @@ -3,19 +3,17 @@ #include "IOStreams.hpp" #include "CMetaAnimFactory.hpp" -namespace urde -{ +namespace urde { class IMetaAnim; -class CAnimation -{ - std::string x0_name; - std::shared_ptr x10_anim; +class CAnimation { + std::string x0_name; + std::shared_ptr x10_anim; + public: - CAnimation(CInputStream& in); - const std::shared_ptr& GetMetaAnim() const {return x10_anim;} - std::string_view GetMetaAnimName() const { return x0_name; } + CAnimation(CInputStream& in); + const std::shared_ptr& GetMetaAnim() const { return x10_anim; } + std::string_view GetMetaAnimName() const { return x0_name; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimationDatabase.hpp b/Runtime/Character/CAnimationDatabase.hpp index 436a3a72c..52d9f477a 100644 --- a/Runtime/Character/CAnimationDatabase.hpp +++ b/Runtime/Character/CAnimationDatabase.hpp @@ -5,20 +5,17 @@ #include #include -namespace urde -{ +namespace urde { class IMetaAnim; class CPrimitive; -class CAnimationDatabase -{ +class CAnimationDatabase { public: - virtual const std::shared_ptr& GetMetaAnim(u32) const=0; - virtual u32 GetNumMetaAnims() const=0; - virtual const char* GetMetaAnimName(u32) const=0; - virtual void GetAllUniquePrimitives(std::vector&) const=0; - virtual void GetUniquePrimitivesFromMetaAnim(std::set&, std::string_view) const=0; + virtual const std::shared_ptr& GetMetaAnim(u32) const = 0; + virtual u32 GetNumMetaAnims() const = 0; + virtual const char* GetMetaAnimName(u32) const = 0; + virtual void GetAllUniquePrimitives(std::vector&) const = 0; + virtual void GetUniquePrimitivesFromMetaAnim(std::set&, std::string_view) const = 0; }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimationDatabaseGame.cpp b/Runtime/Character/CAnimationDatabaseGame.cpp index 0a3884616..701f1fdef 100644 --- a/Runtime/Character/CAnimationDatabaseGame.cpp +++ b/Runtime/Character/CAnimationDatabaseGame.cpp @@ -3,45 +3,34 @@ #include "CPrimitive.hpp" #include "CAnimation.hpp" -namespace urde -{ +namespace urde { -CAnimationDatabaseGame::CAnimationDatabaseGame(const std::vector& anims) -{ - x10_anims.reserve(anims.size()); - for (const CAnimation& anim : anims) - x10_anims.emplace_back(anim.GetMetaAnim()); +CAnimationDatabaseGame::CAnimationDatabaseGame(const std::vector& anims) { + x10_anims.reserve(anims.size()); + for (const CAnimation& anim : anims) + x10_anims.emplace_back(anim.GetMetaAnim()); } -const std::shared_ptr& CAnimationDatabaseGame::GetMetaAnim(u32 idx) const -{ - return x10_anims[idx]; +const std::shared_ptr& CAnimationDatabaseGame::GetMetaAnim(u32 idx) const { return x10_anims[idx]; } + +u32 CAnimationDatabaseGame::GetNumMetaAnims() const { return x10_anims.size(); } + +const char* CAnimationDatabaseGame::GetMetaAnimName(u32 idx) const { + return "Meta-animation name unavailable in Release mode."; } -u32 CAnimationDatabaseGame::GetNumMetaAnims() const -{ - return x10_anims.size(); -} - -const char* CAnimationDatabaseGame::GetMetaAnimName(u32 idx) const -{ - return "Meta-animation name unavailable in Release mode."; -} - -void CAnimationDatabaseGame::GetAllUniquePrimitives(std::vector& primsOut) const -{ - std::set primitives; - for (const std::shared_ptr& anim : x10_anims) - anim->GetUniquePrimitives(primitives); - primsOut.reserve(primitives.size()); - for (const CPrimitive& prim : primitives) - primsOut.push_back(prim); +void CAnimationDatabaseGame::GetAllUniquePrimitives(std::vector& primsOut) const { + std::set primitives; + for (const std::shared_ptr& anim : x10_anims) + anim->GetUniquePrimitives(primitives); + primsOut.reserve(primitives.size()); + for (const CPrimitive& prim : primitives) + primsOut.push_back(prim); } void CAnimationDatabaseGame::GetUniquePrimitivesFromMetaAnim(std::set& primsOut, - std::string_view name) const -{ - // Empty + std::string_view name) const { + // Empty } -} +} // namespace urde diff --git a/Runtime/Character/CAnimationDatabaseGame.hpp b/Runtime/Character/CAnimationDatabaseGame.hpp index 4a59f53a7..cc4dbce07 100644 --- a/Runtime/Character/CAnimationDatabaseGame.hpp +++ b/Runtime/Character/CAnimationDatabaseGame.hpp @@ -2,21 +2,19 @@ #include "CAnimationDatabase.hpp" -namespace urde -{ +namespace urde { class CAnimation; -class CAnimationDatabaseGame final : public CAnimationDatabase -{ - std::vector> x10_anims; +class CAnimationDatabaseGame final : public CAnimationDatabase { + std::vector> x10_anims; + public: - CAnimationDatabaseGame(const std::vector& anims); - const std::shared_ptr& GetMetaAnim(u32 idx) const; - u32 GetNumMetaAnims() const; - const char* GetMetaAnimName(u32 idx) const; - void GetAllUniquePrimitives(std::vector& primsOut) const; - void GetUniquePrimitivesFromMetaAnim(std::set& primsOut, std::string_view name) const; + CAnimationDatabaseGame(const std::vector& anims); + const std::shared_ptr& GetMetaAnim(u32 idx) const; + u32 GetNumMetaAnims() const; + const char* GetMetaAnimName(u32 idx) const; + void GetAllUniquePrimitives(std::vector& primsOut) const; + void GetUniquePrimitivesFromMetaAnim(std::set& primsOut, std::string_view name) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimationManager.cpp b/Runtime/Character/CAnimationManager.cpp index bb6f3df0e..a215ccf84 100644 --- a/Runtime/Character/CAnimationManager.cpp +++ b/Runtime/Character/CAnimationManager.cpp @@ -3,24 +3,18 @@ #include "CTransitionDatabaseGame.hpp" #include "IMetaAnim.hpp" -namespace urde -{ +namespace urde { -const CAnimationDatabaseGame* CAnimationManager::GetAnimationDatabase() const -{ - return x0_animDB.GetObj(); +const CAnimationDatabaseGame* CAnimationManager::GetAnimationDatabase() const { return x0_animDB.GetObj(); } + +std::shared_ptr CAnimationManager::GetAnimationTree(u32 animIdx, + const CMetaAnimTreeBuildOrders& orders) const { + const std::shared_ptr& anim = x0_animDB->GetMetaAnim(animIdx); + return anim->GetAnimationTree(x8_sysCtx, orders); } -std::shared_ptr -CAnimationManager::GetAnimationTree(u32 animIdx, const CMetaAnimTreeBuildOrders& orders) const -{ - const std::shared_ptr& anim = x0_animDB->GetMetaAnim(animIdx); - return anim->GetAnimationTree(x8_sysCtx, orders); +const std::shared_ptr& CAnimationManager::GetMetaAnimation(u32 idx) const { + return x0_animDB->GetMetaAnim(idx); } -const std::shared_ptr& CAnimationManager::GetMetaAnimation(u32 idx) const -{ - return x0_animDB->GetMetaAnim(idx); -} - -} +} // namespace urde diff --git a/Runtime/Character/CAnimationManager.hpp b/Runtime/Character/CAnimationManager.hpp index c9aef6f06..7288af8fb 100644 --- a/Runtime/Character/CAnimationManager.hpp +++ b/Runtime/Character/CAnimationManager.hpp @@ -3,8 +3,7 @@ #include "CToken.hpp" #include "CAnimSysContext.hpp" -namespace urde -{ +namespace urde { class CAnimationDatabaseGame; class CTransitionDatabaseGame; class CSimplePool; @@ -12,19 +11,17 @@ class CAnimTreeNode; struct CMetaAnimTreeBuildOrders; class IMetaAnim; -class CAnimationManager -{ - TToken x0_animDB; - CAnimSysContext x8_sysCtx; -public: - CAnimationManager(const TToken& animDB, - const CAnimSysContext& sysCtx) - : x0_animDB(animDB), x8_sysCtx(sysCtx) {} +class CAnimationManager { + TToken x0_animDB; + CAnimSysContext x8_sysCtx; - const CAnimationDatabaseGame* GetAnimationDatabase() const; - std::shared_ptr GetAnimationTree(u32, const CMetaAnimTreeBuildOrders& orders) const; - const std::shared_ptr& GetMetaAnimation(u32) const; +public: + CAnimationManager(const TToken& animDB, const CAnimSysContext& sysCtx) + : x0_animDB(animDB), x8_sysCtx(sysCtx) {} + + const CAnimationDatabaseGame* GetAnimationDatabase() const; + std::shared_ptr GetAnimationTree(u32, const CMetaAnimTreeBuildOrders& orders) const; + const std::shared_ptr& GetMetaAnimation(u32) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CAnimationSet.cpp b/Runtime/Character/CAnimationSet.cpp index 3ab071581..bf8a83c38 100644 --- a/Runtime/Character/CAnimationSet.cpp +++ b/Runtime/Character/CAnimationSet.cpp @@ -1,55 +1,47 @@ #include "CAnimationSet.hpp" #include "CMetaTransFactory.hpp" -namespace urde -{ +namespace urde { -CAnimationSet::CAnimationSet(CInputStream& in) -: x0_tableCount(in.readUint16Big()) -{ - u32 animationCount = in.readUint32Big(); - x4_animations.reserve(animationCount); - for (u32 i=0 ; i 1) - { - u32 additiveAnimCount = in.readUint32Big(); - x28_additiveInfo.reserve(additiveAnimCount); - for (u32 i=0 ; i 1) { + u32 additiveAnimCount = in.readUint32Big(); + x28_additiveInfo.reserve(additiveAnimCount); + for (u32 i = 0; i < additiveAnimCount; ++i) { + u32 id = in.readUint32Big(); + x28_additiveInfo.emplace_back(id, in); } + x38_defaultAdditiveInfo.read(in); + } - if (x0_tableCount > 2) - { - u32 halfTransitionCount = in.readUint32Big(); - x40_halfTransitions.reserve(halfTransitionCount); - for (u32 i=0 ; i 2) { + u32 halfTransitionCount = in.readUint32Big(); + x40_halfTransitions.reserve(halfTransitionCount); + for (u32 i = 0; i < halfTransitionCount; ++i) + x40_halfTransitions.emplace_back(in); + } - if (x0_tableCount > 3) - { - u32 animResourcesCount = in.readUint32Big(); - x50_animRes.reserve(animResourcesCount); - for (u32 i=0 ; i 3) { + u32 animResourcesCount = in.readUint32Big(); + x50_animRes.reserve(animResourcesCount); + for (u32 i = 0; i < animResourcesCount; ++i) { + CAssetId anim = in.readUint32Big(); + CAssetId evnt = in.readUint32Big(); + x50_animRes.emplace_back(anim, evnt); } + } } -} +} // namespace urde diff --git a/Runtime/Character/CAnimationSet.hpp b/Runtime/Character/CAnimationSet.hpp index 29d306008..d8924c906 100644 --- a/Runtime/Character/CAnimationSet.hpp +++ b/Runtime/Character/CAnimationSet.hpp @@ -6,30 +6,27 @@ #include "CHalfTransition.hpp" #include "CAdditiveAnimPlayback.hpp" -namespace urde -{ +namespace urde { -class CAnimationSet -{ - u16 x0_tableCount; - std::vector x4_animations; - std::vector x14_transitions; - std::shared_ptr x24_defaultTransition; - std::vector> x28_additiveInfo; - CAdditiveAnimationInfo x38_defaultAdditiveInfo; - std::vector x40_halfTransitions; - std::vector> x50_animRes; +class CAnimationSet { + u16 x0_tableCount; + std::vector x4_animations; + std::vector x14_transitions; + std::shared_ptr x24_defaultTransition; + std::vector> x28_additiveInfo; + CAdditiveAnimationInfo x38_defaultAdditiveInfo; + std::vector x40_halfTransitions; + std::vector> x50_animRes; public: - CAnimationSet(CInputStream& in); + CAnimationSet(CInputStream& in); - const std::vector& GetAnimations() const { return x4_animations; } - const std::vector& GetTransitions() const { return x14_transitions; } - const std::shared_ptr& GetDefaultTransition() const { return x24_defaultTransition; } - const std::vector& GetHalfTransitions() const { return x40_halfTransitions; } - const std::vector>& GetAdditiveInfo() const { return x28_additiveInfo; } - const CAdditiveAnimationInfo& GetDefaultAdditiveInfo() const { return x38_defaultAdditiveInfo; } - const std::vector>& GetAnimResIds() const { return x50_animRes; } + const std::vector& GetAnimations() const { return x4_animations; } + const std::vector& GetTransitions() const { return x14_transitions; } + const std::shared_ptr& GetDefaultTransition() const { return x24_defaultTransition; } + const std::vector& GetHalfTransitions() const { return x40_halfTransitions; } + const std::vector>& GetAdditiveInfo() const { return x28_additiveInfo; } + const CAdditiveAnimationInfo& GetDefaultAdditiveInfo() const { return x38_defaultAdditiveInfo; } + const std::vector>& GetAnimResIds() const { return x50_animRes; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CAssetFactory.cpp b/Runtime/Character/CAssetFactory.cpp index 93768908d..69d92d79a 100644 --- a/Runtime/Character/CAssetFactory.cpp +++ b/Runtime/Character/CAssetFactory.cpp @@ -5,90 +5,62 @@ #include "CModelData.hpp" #include "Character/CCharLayoutInfo.hpp" -namespace urde -{ +namespace urde { -CFactoryFnReturn CCharacterFactoryBuilder::CDummyFactory::Build(const SObjectTag& tag, - const CVParamTransfer&, - CObjectReference* selfRef) -{ - TLockedToken ancs = - g_SimplePool->GetObj({SBIG('ANCS'), tag.id}); - return TToken::GetIObjObjectFor( - std::make_unique(*g_SimplePool, *ancs.GetObj(), tag.id)); +CFactoryFnReturn CCharacterFactoryBuilder::CDummyFactory::Build(const SObjectTag& tag, const CVParamTransfer&, + CObjectReference* selfRef) { + TLockedToken ancs = g_SimplePool->GetObj({SBIG('ANCS'), tag.id}); + return TToken::GetIObjObjectFor( + std::make_unique(*g_SimplePool, *ancs.GetObj(), tag.id)); } -void CCharacterFactoryBuilder::CDummyFactory::BuildAsync(const SObjectTag& tag, - const CVParamTransfer& parms, - std::unique_ptr* objOut, - CObjectReference* selfRef) -{ - *objOut = Build(tag, parms, selfRef); +void CCharacterFactoryBuilder::CDummyFactory::BuildAsync(const SObjectTag& tag, const CVParamTransfer& parms, + std::unique_ptr* objOut, CObjectReference* selfRef) { + *objOut = Build(tag, parms, selfRef); } -void CCharacterFactoryBuilder::CDummyFactory::CancelBuild(const SObjectTag&) -{ +void CCharacterFactoryBuilder::CDummyFactory::CancelBuild(const SObjectTag&) {} + +bool CCharacterFactoryBuilder::CDummyFactory::CanBuild(const SObjectTag&) { return true; } + +const SObjectTag* CCharacterFactoryBuilder::CDummyFactory::GetResourceIdByName(std::string_view) const { + return nullptr; } -bool CCharacterFactoryBuilder::CDummyFactory::CanBuild(const SObjectTag&) -{ - return true; -} - -const SObjectTag* CCharacterFactoryBuilder::CDummyFactory::GetResourceIdByName(std::string_view) const -{ - return nullptr; -} - -FourCC CCharacterFactoryBuilder::CDummyFactory::GetResourceTypeById(CAssetId id) const -{ - return {}; -} +FourCC CCharacterFactoryBuilder::CDummyFactory::GetResourceTypeById(CAssetId id) const { return {}; } void CCharacterFactoryBuilder::CDummyFactory::EnumerateResources( - const std::function& lambda) const -{ -} + const std::function& lambda) const {} void CCharacterFactoryBuilder::CDummyFactory::EnumerateNamedResources( - const std::function& lambda) const -{ -} + const std::function& lambda) const {} -u32 CCharacterFactoryBuilder::CDummyFactory::ResourceSize(const urde::SObjectTag& tag) -{ - return 0; -} +u32 CCharacterFactoryBuilder::CDummyFactory::ResourceSize(const urde::SObjectTag& tag) { return 0; } std::shared_ptr CCharacterFactoryBuilder::CDummyFactory::LoadResourceAsync(const urde::SObjectTag& tag, - void* target) -{ - return {}; + void* target) { + return {}; } std::shared_ptr CCharacterFactoryBuilder::CDummyFactory::LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, - void* target) -{ - return {}; + void* target) { + return {}; } -std::unique_ptr CCharacterFactoryBuilder::CDummyFactory::LoadResourceSync(const urde::SObjectTag& tag) -{ - return {}; +std::unique_ptr CCharacterFactoryBuilder::CDummyFactory::LoadResourceSync(const urde::SObjectTag& tag) { + return {}; } std::unique_ptr CCharacterFactoryBuilder::CDummyFactory::LoadNewResourcePartSync(const urde::SObjectTag& tag, - u32 off, u32 size) -{ - return {}; + u32 off, u32 size) { + return {}; } CCharacterFactoryBuilder::CCharacterFactoryBuilder() : x4_dummyStore(x0_dummyFactory) {} -TToken CCharacterFactoryBuilder::GetFactory(const CAnimRes& res) -{ - return x4_dummyStore.GetObj({SBIG('ANCS'), res.GetId()}); +TToken CCharacterFactoryBuilder::GetFactory(const CAnimRes& res) { + return x4_dummyStore.GetObj({SBIG('ANCS'), res.GetId()}); } -} +} // namespace urde diff --git a/Runtime/Character/CAssetFactory.hpp b/Runtime/Character/CAssetFactory.hpp index 73972c1a9..f542e9227 100644 --- a/Runtime/Character/CAssetFactory.hpp +++ b/Runtime/Character/CAssetFactory.hpp @@ -5,42 +5,38 @@ #include "CToken.hpp" #include "CSimplePool.hpp" -namespace urde -{ +namespace urde { class CCharacterFactory; class CAnimRes; -class CCharacterFactoryBuilder -{ +class CCharacterFactoryBuilder { public: - class CDummyFactory : public IFactory - { - public: - CFactoryFnReturn Build(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef); - void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr*, CObjectReference* selfRef); - void CancelBuild(const SObjectTag&); - bool CanBuild(const SObjectTag&); - const SObjectTag* GetResourceIdByName(std::string_view) const; - FourCC GetResourceTypeById(CAssetId id) const; + class CDummyFactory : public IFactory { + public: + CFactoryFnReturn Build(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef); + void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr*, CObjectReference* selfRef); + void CancelBuild(const SObjectTag&); + bool CanBuild(const SObjectTag&); + const SObjectTag* GetResourceIdByName(std::string_view) const; + FourCC GetResourceTypeById(CAssetId id) const; - void EnumerateResources(const std::function& lambda) const; - void EnumerateNamedResources(const std::function& lambda) const; + void EnumerateResources(const std::function& lambda) const; + void EnumerateNamedResources(const std::function& lambda) const; - u32 ResourceSize(const urde::SObjectTag& tag); - std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target); - std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target); - std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); - std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size); - }; + u32 ResourceSize(const urde::SObjectTag& tag); + std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target); + std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target); + std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); + std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size); + }; private: - CDummyFactory x0_dummyFactory; - CSimplePool x4_dummyStore; + CDummyFactory x0_dummyFactory; + CSimplePool x4_dummyStore; public: - CCharacterFactoryBuilder(); - TToken GetFactory(const CAnimRes& res); + CCharacterFactoryBuilder(); + TToken GetFactory(const CAnimRes& res); }; -} - +} // namespace urde diff --git a/Runtime/Character/CBodyController.cpp b/Runtime/Character/CBodyController.cpp index 2f3473b3d..8ca09bd35 100644 --- a/Runtime/Character/CBodyController.cpp +++ b/Runtime/Character/CBodyController.cpp @@ -7,347 +7,274 @@ #include "Character/CPASAnimParmData.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { CBodyController::CBodyController(CActor& actor, float turnSpeed, EBodyType bodyType) -: x0_actor(actor), x2a4_bodyStateInfo(actor, bodyType), - x2f4_bodyType(bodyType), x2fc_turnSpeed(turnSpeed) -{ - x300_28_playDeathAnims = true; - x2a4_bodyStateInfo.x18_bodyController = this; +: x0_actor(actor), x2a4_bodyStateInfo(actor, bodyType), x2f4_bodyType(bodyType), x2fc_turnSpeed(turnSpeed) { + x300_28_playDeathAnims = true; + x2a4_bodyStateInfo.x18_bodyController = this; } -void CBodyController::EnableAnimation(bool e) -{ - x0_actor.ModelData()->AnimationData()->EnableAnimation(e); +void CBodyController::EnableAnimation(bool e) { x0_actor.ModelData()->AnimationData()->EnableAnimation(e); } + +void CBodyController::Activate(CStateManager& mgr) { + x300_25_active = true; + x2a4_bodyStateInfo.SetState(pas::EAnimationState(GetPASDatabase().GetDefaultState())); + x2a4_bodyStateInfo.GetCurrentState()->Start(*this, mgr); + x2a4_bodyStateInfo.GetCurrentAdditiveState()->Start(*this, mgr); } -void CBodyController::Activate(CStateManager& mgr) -{ - x300_25_active = true; - x2a4_bodyStateInfo.SetState(pas::EAnimationState(GetPASDatabase().GetDefaultState())); - x2a4_bodyStateInfo.GetCurrentState()->Start(*this, mgr); - x2a4_bodyStateInfo.GetCurrentAdditiveState()->Start(*this, mgr); -} - -void CBodyController::UpdateBody(float dt, CStateManager& mgr) -{ - UpdateFrozenInfo(dt, mgr); - if (x320_fireDur > 0.f) - { - if (x328_timeOnFire > x320_fireDur) - { - x328_timeOnFire = 0.f; - x320_fireDur = 0.f; - } - else - { - x328_timeOnFire += dt; - } +void CBodyController::UpdateBody(float dt, CStateManager& mgr) { + UpdateFrozenInfo(dt, mgr); + if (x320_fireDur > 0.f) { + if (x328_timeOnFire > x320_fireDur) { + x328_timeOnFire = 0.f; + x320_fireDur = 0.f; + } else { + x328_timeOnFire += dt; } - else if (x324_electrocutionDur > 0.f) - { - if (x32c_timeElectrocuting > x324_electrocutionDur) - { - x32c_timeElectrocuting = 0.f; - x324_electrocutionDur = 0.f; - } - else - { - x32c_timeElectrocuting += dt; - } + } else if (x324_electrocutionDur > 0.f) { + if (x32c_timeElectrocuting > x324_electrocutionDur) { + x32c_timeElectrocuting = 0.f; + x324_electrocutionDur = 0.f; + } else { + x32c_timeElectrocuting += dt; + } + } + + if (GetPercentageFrozen() < 1.f && x300_28_playDeathAnims) { + pas::EAnimationState nextState = x2a4_bodyStateInfo.GetCurrentState()->UpdateBody(dt, *this, mgr); + if (nextState != pas::EAnimationState::Invalid) { + x2a4_bodyStateInfo.GetCurrentState()->Shutdown(*this); + x2a4_bodyStateInfo.SetState(nextState); + x2a4_bodyStateInfo.GetCurrentState()->Start(*this, mgr); } - if (GetPercentageFrozen() < 1.f && x300_28_playDeathAnims) - { - pas::EAnimationState nextState = x2a4_bodyStateInfo.GetCurrentState()->UpdateBody(dt, *this, mgr); - if (nextState != pas::EAnimationState::Invalid) - { - x2a4_bodyStateInfo.GetCurrentState()->Shutdown(*this); - x2a4_bodyStateInfo.SetState(nextState); - x2a4_bodyStateInfo.GetCurrentState()->Start(*this, mgr); - } - - nextState = x2a4_bodyStateInfo.GetCurrentAdditiveState()->UpdateBody(dt, *this, mgr); - if (nextState != pas::EAnimationState::Invalid) - { - x2a4_bodyStateInfo.GetCurrentAdditiveState()->Shutdown(*this); - x2a4_bodyStateInfo.SetAdditiveState(nextState); - x2a4_bodyStateInfo.GetCurrentAdditiveState()->Start(*this, mgr); - } + nextState = x2a4_bodyStateInfo.GetCurrentAdditiveState()->UpdateBody(dt, *this, mgr); + if (nextState != pas::EAnimationState::Invalid) { + x2a4_bodyStateInfo.GetCurrentAdditiveState()->Shutdown(*this); + x2a4_bodyStateInfo.SetAdditiveState(nextState); + x2a4_bodyStateInfo.GetCurrentAdditiveState()->Start(*this, mgr); } + } } -void CBodyController::SetTurnSpeed(float s) -{ - x2fc_turnSpeed = std::max(0.f, s); -} - -void CBodyController::Update(float dt, CStateManager& mgr) -{ - SetPlaybackRate(1.f); - if (x300_25_active) - { - x300_24_animationOver = - !x0_actor.GetModelData()->GetAnimationData()->IsAnimTimeRemaining(dt, "Whole Body"sv); - x4_cmdMgr.BlendSteeringCmds(); - x2dc_rot = zeus::CQuaternion::skNoRotation; - UpdateBody(dt, mgr); - if (TCastToPtr act = x0_actor) - act->RotateInOneFrameOR(x2dc_rot, dt); - x4_cmdMgr.Reset(); - } -} - -bool CBodyController::HasBodyState(pas::EAnimationState s) const -{ - return GetPASDatabase().HasState(s32(s)); -} - -void CBodyController::SetCurrentAnimation(const CAnimPlaybackParms& parms, bool loop, bool noTrans) -{ - x0_actor.ModelData()->AnimationData()->SetAnimation(parms, noTrans); - x0_actor.ModelData()->EnableLooping(loop); - x2f8_curAnim = parms.GetAnimationId(); -} - -float CBodyController::GetAnimTimeRemaining() const -{ - return x0_actor.GetModelData()->GetAnimationData()->GetAnimTimeRemaining("Whole Body"); -} - -void CBodyController::SetPlaybackRate(float r) -{ - x0_actor.ModelData()->AnimationData()->SetPlaybackRate(r); -} - -const CPASDatabase& CBodyController::GetPASDatabase() const -{ - return x0_actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); -} - -void CBodyController::MultiplyPlaybackRate(float r) -{ - x0_actor.ModelData()->AnimationData()->MultiplyPlaybackRate(r); -} - -void CBodyController::FaceDirection(const zeus::CVector3f& v0, float dt) -{ - if (x300_26_frozen) - return; - zeus::CVector3f noZ = v0; - noZ.z() = 0.f; - if (noZ.canBeNormalized()) - { - if (TCastToPtr act = x0_actor) - { - zeus::CQuaternion rot = - zeus::CQuaternion::lookAt(act->GetTransform().basis[1], - noZ.normalized(), zeus::degToRad(dt * x2fc_turnSpeed)); - rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary())); - act->RotateInOneFrameOR(rot, dt); - } - } -} - -void CBodyController::FaceDirection3D(const zeus::CVector3f& v0, const zeus::CVector3f& v1, float dt) -{ - if (x300_26_frozen) - return; - if (v0.canBeNormalized() && v1.canBeNormalized()) - { - if (TCastToPtr act = x0_actor) - { - zeus::CUnitVector3f uv0 = v0; - zeus::CUnitVector3f uv1 = v1; - float dot = uv0.dot(uv1); - if (std::fabs(dot - 1.f) > 0.00001f) - { - if (dot < -0.9999f) - { - zeus::CQuaternion rot = - zeus::CQuaternion::fromAxisAngle(act->GetTransform().basis[2], - zeus::degToRad(dt * x2fc_turnSpeed)); - rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary())); - act->RotateInOneFrameOR(rot, dt); - } - else - { - zeus::CQuaternion rot = - zeus::CQuaternion::clampedRotateTo(uv1, uv0, zeus::degToRad(dt * x2fc_turnSpeed)); - rot.setImaginary(x0_actor.GetTransform().transposeRotate(rot.getImaginary())); - act->RotateInOneFrameOR(rot, dt); - } - } - } - } -} - -bool CBodyController::HasBodyInfo(CActor& act) -{ - return act.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase().GetNumAnimStates() != 0; -} - -void CBodyController::PlayBestAnimation(const CPASAnimParmData& parms, CRandom16& r) -{ - std::pair best = GetPASDatabase().FindBestAnimation(parms, r, -1); - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - SetCurrentAnimation(playParms, false, false); -} - -void CBodyController::LoopBestAnimation(const CPASAnimParmData& parms, CRandom16& r) -{ - std::pair best = GetPASDatabase().FindBestAnimation(parms, r, -1); - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - SetCurrentAnimation(playParms, true, false); -} - -void CBodyController::Freeze(float intoFreezeDur, float frozenDur, float breakoutDur) -{ - x304_intoFreezeDur = intoFreezeDur; - x308_frozenDur = frozenDur; - x30c_breakoutDur = breakoutDur; - x300_26_frozen = true; - x300_27_hasBeenFrozen = true; +void CBodyController::SetTurnSpeed(float s) { x2fc_turnSpeed = std::max(0.f, s); } +void CBodyController::Update(float dt, CStateManager& mgr) { + SetPlaybackRate(1.f); + if (x300_25_active) { + x300_24_animationOver = !x0_actor.GetModelData()->GetAnimationData()->IsAnimTimeRemaining(dt, "Whole Body"sv); + x4_cmdMgr.BlendSteeringCmds(); + x2dc_rot = zeus::CQuaternion::skNoRotation; + UpdateBody(dt, mgr); if (TCastToPtr act = x0_actor) - { - x314_backedUpForce = act->GetConstantForce(); - act->SetConstantForce(zeus::CVector3f::skZero); - act->SetMomentumWR(zeus::CVector3f::skZero); + act->RotateInOneFrameOR(x2dc_rot, dt); + x4_cmdMgr.Reset(); + } +} + +bool CBodyController::HasBodyState(pas::EAnimationState s) const { return GetPASDatabase().HasState(s32(s)); } + +void CBodyController::SetCurrentAnimation(const CAnimPlaybackParms& parms, bool loop, bool noTrans) { + x0_actor.ModelData()->AnimationData()->SetAnimation(parms, noTrans); + x0_actor.ModelData()->EnableLooping(loop); + x2f8_curAnim = parms.GetAnimationId(); +} + +float CBodyController::GetAnimTimeRemaining() const { + return x0_actor.GetModelData()->GetAnimationData()->GetAnimTimeRemaining("Whole Body"); +} + +void CBodyController::SetPlaybackRate(float r) { x0_actor.ModelData()->AnimationData()->SetPlaybackRate(r); } + +const CPASDatabase& CBodyController::GetPASDatabase() const { + return x0_actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); +} + +void CBodyController::MultiplyPlaybackRate(float r) { x0_actor.ModelData()->AnimationData()->MultiplyPlaybackRate(r); } + +void CBodyController::FaceDirection(const zeus::CVector3f& v0, float dt) { + if (x300_26_frozen) + return; + zeus::CVector3f noZ = v0; + noZ.z() = 0.f; + if (noZ.canBeNormalized()) { + if (TCastToPtr act = x0_actor) { + zeus::CQuaternion rot = zeus::CQuaternion::lookAt(act->GetTransform().basis[1], noZ.normalized(), + zeus::degToRad(dt * x2fc_turnSpeed)); + rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary())); + act->RotateInOneFrameOR(rot, dt); } - - x320_fireDur = 0.f; - x328_timeOnFire = 0.f; - x310_timeFrozen = 0.f; + } } -void CBodyController::UnFreeze() -{ - SetPlaybackRate(1.f); - x300_26_frozen = false; - x304_intoFreezeDur = 0.f; - x308_frozenDur = 0.f; - x30c_breakoutDur = 0.f; - x310_timeFrozen = 0.f; - x0_actor.SetVolume(1.f); - - if (TCastToPtr act = x0_actor) - { - act->SetConstantForce(x314_backedUpForce); - act->SetVelocityWR(x314_backedUpForce * (1.f / act->GetMass())); - } -} - -float CBodyController::GetPercentageFrozen() const -{ - float sum = x304_intoFreezeDur + x308_frozenDur + x30c_breakoutDur; - if (x310_timeFrozen == 0.f || sum == 0.f) - return 0.f; - - if (x310_timeFrozen <= x304_intoFreezeDur && x304_intoFreezeDur > 0.f) - return x310_timeFrozen / x304_intoFreezeDur; - - if (x310_timeFrozen < sum - x30c_breakoutDur) - return 1.f; - if (x30c_breakoutDur <= 0.f) - return 1.f; - - return 1.f - (x310_timeFrozen - (x308_frozenDur + x304_intoFreezeDur)) / x30c_breakoutDur; -} - -void CBodyController::SetOnFire(float dur) -{ - x320_fireDur = dur; - x328_timeOnFire = 0.f; - if (IsFrozen()) - UnFreeze(); -} - -void CBodyController::DouseFlames() -{ - if (x320_fireDur <= 0.f) - return; - x320_fireDur = 0.f; - x328_timeOnFire = 0.f; -} - -void CBodyController::SetElectrocuting(float dur) -{ - if (!IsElectrocuting()) - { - CBCAdditiveReactionCmd reaction(pas::EAdditiveReactionType::Electrocution, 1.f, true); - x4_cmdMgr.DeliverCmd(reaction); - } - x324_electrocutionDur = dur; - x32c_timeElectrocuting = 0.f; - if (IsFrozen()) - UnFreeze(); - else if (IsOnFire()) - DouseFlames(); -} - -void CBodyController::DouseElectrocuting() -{ - x324_electrocutionDur = 0.f; - x32c_timeElectrocuting = 0.f; - CBodyStateCmd cmd(EBodyStateCmd::StopReaction); - x4_cmdMgr.DeliverCmd(cmd); -} - -void CBodyController::UpdateFrozenInfo(float dt, CStateManager& mgr) -{ - if (x300_26_frozen) - { - float totalTime = x304_intoFreezeDur + x308_frozenDur + x30c_breakoutDur; - if (x310_timeFrozen > totalTime && - x2a4_bodyStateInfo.GetCurrentAdditiveStateId() != pas::EAnimationState::AdditiveReaction) - { - UnFreeze(); - x0_actor.SendScriptMsgs(EScriptObjectState::UnFrozen, mgr, EScriptObjectMessage::None); - mgr.GetActorModelParticles()->StartIce(x0_actor); - return; - } - if (x310_timeFrozen <= totalTime) - { - float percUnfrozen = 1.f; - if (x310_timeFrozen < totalTime - x30c_breakoutDur) - percUnfrozen = 1.f - GetPercentageFrozen(); - MultiplyPlaybackRate(percUnfrozen); - x310_timeFrozen += dt; - x0_actor.SetVolume(percUnfrozen); - if (x310_timeFrozen > totalTime && HasIceBreakoutState()) - { - CBCAdditiveReactionCmd cmd(pas::EAdditiveReactionType::IceBreakout, 1.f, false); - x4_cmdMgr.DeliverCmd(cmd); - } +void CBodyController::FaceDirection3D(const zeus::CVector3f& v0, const zeus::CVector3f& v1, float dt) { + if (x300_26_frozen) + return; + if (v0.canBeNormalized() && v1.canBeNormalized()) { + if (TCastToPtr act = x0_actor) { + zeus::CUnitVector3f uv0 = v0; + zeus::CUnitVector3f uv1 = v1; + float dot = uv0.dot(uv1); + if (std::fabs(dot - 1.f) > 0.00001f) { + if (dot < -0.9999f) { + zeus::CQuaternion rot = + zeus::CQuaternion::fromAxisAngle(act->GetTransform().basis[2], zeus::degToRad(dt * x2fc_turnSpeed)); + rot.setImaginary(act->GetTransform().transposeRotate(rot.getImaginary())); + act->RotateInOneFrameOR(rot, dt); + } else { + zeus::CQuaternion rot = zeus::CQuaternion::clampedRotateTo(uv1, uv0, zeus::degToRad(dt * x2fc_turnSpeed)); + rot.setImaginary(x0_actor.GetTransform().transposeRotate(rot.getImaginary())); + act->RotateInOneFrameOR(rot, dt); } + } } + } } -bool CBodyController::HasIceBreakoutState() const -{ - CPASAnimParmData parms(24, CPASAnimParm::FromEnum(3)); - std::pair best = GetPASDatabase().FindBestAnimation(parms, -1); - return best.first > 0.f; +bool CBodyController::HasBodyInfo(CActor& act) { + return act.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase().GetNumAnimStates() != 0; } -void CBodyController::StopElectrocution() -{ - x324_electrocutionDur = 0.f; - x32c_timeElectrocuting = 0.f; - x4_cmdMgr.DeliverCmd(CBodyStateCmd(EBodyStateCmd::StopReaction)); +void CBodyController::PlayBestAnimation(const CPASAnimParmData& parms, CRandom16& r) { + std::pair best = GetPASDatabase().FindBestAnimation(parms, r, -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + SetCurrentAnimation(playParms, false, false); } -void CBodyController::FrozenBreakout() -{ - if (x300_26_frozen) - { - float timeToBreakout = x304_intoFreezeDur + x308_frozenDur; - if (x310_timeFrozen < timeToBreakout) - x310_timeFrozen = timeToBreakout; +void CBodyController::LoopBestAnimation(const CPASAnimParmData& parms, CRandom16& r) { + std::pair best = GetPASDatabase().FindBestAnimation(parms, r, -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + SetCurrentAnimation(playParms, true, false); +} + +void CBodyController::Freeze(float intoFreezeDur, float frozenDur, float breakoutDur) { + x304_intoFreezeDur = intoFreezeDur; + x308_frozenDur = frozenDur; + x30c_breakoutDur = breakoutDur; + x300_26_frozen = true; + x300_27_hasBeenFrozen = true; + + if (TCastToPtr act = x0_actor) { + x314_backedUpForce = act->GetConstantForce(); + act->SetConstantForce(zeus::CVector3f::skZero); + act->SetMomentumWR(zeus::CVector3f::skZero); + } + + x320_fireDur = 0.f; + x328_timeOnFire = 0.f; + x310_timeFrozen = 0.f; +} + +void CBodyController::UnFreeze() { + SetPlaybackRate(1.f); + x300_26_frozen = false; + x304_intoFreezeDur = 0.f; + x308_frozenDur = 0.f; + x30c_breakoutDur = 0.f; + x310_timeFrozen = 0.f; + x0_actor.SetVolume(1.f); + + if (TCastToPtr act = x0_actor) { + act->SetConstantForce(x314_backedUpForce); + act->SetVelocityWR(x314_backedUpForce * (1.f / act->GetMass())); + } +} + +float CBodyController::GetPercentageFrozen() const { + float sum = x304_intoFreezeDur + x308_frozenDur + x30c_breakoutDur; + if (x310_timeFrozen == 0.f || sum == 0.f) + return 0.f; + + if (x310_timeFrozen <= x304_intoFreezeDur && x304_intoFreezeDur > 0.f) + return x310_timeFrozen / x304_intoFreezeDur; + + if (x310_timeFrozen < sum - x30c_breakoutDur) + return 1.f; + if (x30c_breakoutDur <= 0.f) + return 1.f; + + return 1.f - (x310_timeFrozen - (x308_frozenDur + x304_intoFreezeDur)) / x30c_breakoutDur; +} + +void CBodyController::SetOnFire(float dur) { + x320_fireDur = dur; + x328_timeOnFire = 0.f; + if (IsFrozen()) + UnFreeze(); +} + +void CBodyController::DouseFlames() { + if (x320_fireDur <= 0.f) + return; + x320_fireDur = 0.f; + x328_timeOnFire = 0.f; +} + +void CBodyController::SetElectrocuting(float dur) { + if (!IsElectrocuting()) { + CBCAdditiveReactionCmd reaction(pas::EAdditiveReactionType::Electrocution, 1.f, true); + x4_cmdMgr.DeliverCmd(reaction); + } + x324_electrocutionDur = dur; + x32c_timeElectrocuting = 0.f; + if (IsFrozen()) + UnFreeze(); + else if (IsOnFire()) + DouseFlames(); +} + +void CBodyController::DouseElectrocuting() { + x324_electrocutionDur = 0.f; + x32c_timeElectrocuting = 0.f; + CBodyStateCmd cmd(EBodyStateCmd::StopReaction); + x4_cmdMgr.DeliverCmd(cmd); +} + +void CBodyController::UpdateFrozenInfo(float dt, CStateManager& mgr) { + if (x300_26_frozen) { + float totalTime = x304_intoFreezeDur + x308_frozenDur + x30c_breakoutDur; + if (x310_timeFrozen > totalTime && + x2a4_bodyStateInfo.GetCurrentAdditiveStateId() != pas::EAnimationState::AdditiveReaction) { + UnFreeze(); + x0_actor.SendScriptMsgs(EScriptObjectState::UnFrozen, mgr, EScriptObjectMessage::None); + mgr.GetActorModelParticles()->StartIce(x0_actor); + return; } + if (x310_timeFrozen <= totalTime) { + float percUnfrozen = 1.f; + if (x310_timeFrozen < totalTime - x30c_breakoutDur) + percUnfrozen = 1.f - GetPercentageFrozen(); + MultiplyPlaybackRate(percUnfrozen); + x310_timeFrozen += dt; + x0_actor.SetVolume(percUnfrozen); + if (x310_timeFrozen > totalTime && HasIceBreakoutState()) { + CBCAdditiveReactionCmd cmd(pas::EAdditiveReactionType::IceBreakout, 1.f, false); + x4_cmdMgr.DeliverCmd(cmd); + } + } + } } +bool CBodyController::HasIceBreakoutState() const { + CPASAnimParmData parms(24, CPASAnimParm::FromEnum(3)); + std::pair best = GetPASDatabase().FindBestAnimation(parms, -1); + return best.first > 0.f; } + +void CBodyController::StopElectrocution() { + x324_electrocutionDur = 0.f; + x32c_timeElectrocuting = 0.f; + x4_cmdMgr.DeliverCmd(CBodyStateCmd(EBodyStateCmd::StopReaction)); +} + +void CBodyController::FrozenBreakout() { + if (x300_26_frozen) { + float timeToBreakout = x304_intoFreezeDur + x308_frozenDur; + if (x310_timeFrozen < timeToBreakout) + x310_timeFrozen = timeToBreakout; + } +} + +} // namespace urde diff --git a/Runtime/Character/CBodyController.hpp b/Runtime/Character/CBodyController.hpp index 5ca834374..1a217be95 100644 --- a/Runtime/Character/CBodyController.hpp +++ b/Runtime/Character/CBodyController.hpp @@ -6,8 +6,7 @@ #include "CBodyStateCmdMgr.hpp" #include "CBodyStateInfo.hpp" -namespace urde -{ +namespace urde { class CActor; class CAnimPlaybackParms; @@ -17,98 +16,93 @@ class CRandom16; class CStateManager; class CPASDatabase; -class CBodyController -{ - CActor& x0_actor; - CBodyStateCmdMgr x4_cmdMgr; - CBodyStateInfo x2a4_bodyStateInfo; - zeus::CQuaternion x2dc_rot; - pas::ELocomotionType x2ec_locomotionType = pas::ELocomotionType::Relaxed; - pas::EFallState x2f0_fallState = pas::EFallState::Zero; - EBodyType x2f4_bodyType; - s32 x2f8_curAnim = -1; - float x2fc_turnSpeed; - union - { - struct - { - bool x300_24_animationOver : 1; - bool x300_25_active : 1; - bool x300_26_frozen : 1; - bool x300_27_hasBeenFrozen : 1; - bool x300_28_playDeathAnims : 1; - }; - u32 _dummy = 0; +class CBodyController { + CActor& x0_actor; + CBodyStateCmdMgr x4_cmdMgr; + CBodyStateInfo x2a4_bodyStateInfo; + zeus::CQuaternion x2dc_rot; + pas::ELocomotionType x2ec_locomotionType = pas::ELocomotionType::Relaxed; + pas::EFallState x2f0_fallState = pas::EFallState::Zero; + EBodyType x2f4_bodyType; + s32 x2f8_curAnim = -1; + float x2fc_turnSpeed; + union { + struct { + bool x300_24_animationOver : 1; + bool x300_25_active : 1; + bool x300_26_frozen : 1; + bool x300_27_hasBeenFrozen : 1; + bool x300_28_playDeathAnims : 1; }; - float x304_intoFreezeDur = 0.f; - float x308_frozenDur = 0.f; - float x30c_breakoutDur = 0.f; - float x310_timeFrozen = 0.f; - zeus::CVector3f x314_backedUpForce; - float x320_fireDur = 0.f; - float x324_electrocutionDur = 0.f; - float x328_timeOnFire = 0.f; - float x32c_timeElectrocuting = 0.f; - float x330_restrictedFlyerMoveSpeed = 0.f; -public: - CBodyController(CActor& owner, float turnSpeed, EBodyType bodyType); - pas::EAnimationState GetCurrentStateId() const { return x2a4_bodyStateInfo.GetCurrentStateId(); } - CBodyStateCmdMgr& GetCommandMgr() { return x4_cmdMgr; } - const CBodyStateCmdMgr& GetCommandMgr() const { return x4_cmdMgr; } - void SetDoDeathAnims(bool d) { x300_28_playDeathAnims = d; } - bool IsElectrocuting() const { return x324_electrocutionDur > 0.f; } - bool IsOnFire() const { return x320_fireDur > 0.f; } - bool IsFrozen() const { return x300_26_frozen; } - const CBodyStateInfo& GetBodyStateInfo() const { return x2a4_bodyStateInfo; } - CBodyStateInfo& BodyStateInfo() { return x2a4_bodyStateInfo; } - float GetTurnSpeed() const { return x2fc_turnSpeed; } - void SetLocomotionType(pas::ELocomotionType type) { x2ec_locomotionType = type; } - pas::ELocomotionType GetLocomotionType() const { return x2ec_locomotionType; } - CActor& GetOwner() const { return x0_actor; } - bool IsAnimationOver() const { return x300_24_animationOver; } - void EnableAnimation(bool e); - bool ShouldPlayDeathAnims() const { return x300_28_playDeathAnims; } - s32 GetCurrentAnimId() const { return x2f8_curAnim; } - void Activate(CStateManager&); - CAdditiveBodyState* GetCurrentAdditiveState() - { return x2a4_bodyStateInfo.GetCurrentAdditiveState(); } - void SetState(pas::EAnimationState s) { x2a4_bodyStateInfo.SetState(s); } - void Update(float, CStateManager&); - bool ShouldBeHurled() const { return HasBodyState(pas::EAnimationState::Hurled); } - bool HasBodyState(pas::EAnimationState s) const; - pas::EFallState GetFallState() const { return x2f0_fallState; } - void SetFallState(pas::EFallState s) { x2f0_fallState = s; } - void UpdateBody(float, CStateManager&); - void SetAdditiveState(pas::EAnimationState s) { x2a4_bodyStateInfo.SetAdditiveState(s); } - void SetTurnSpeed(float s); - void SetCurrentAnimation(const CAnimPlaybackParms& parms, bool loop, bool noTrans); - float GetAnimTimeRemaining() const; - void SetPlaybackRate(float); - void MultiplyPlaybackRate(float); - void SetDeltaRotation(const zeus::CQuaternion& q) { x2dc_rot *= q; } - void FaceDirection(const zeus::CVector3f&, float); - void FaceDirection3D(const zeus::CVector3f&, const zeus::CVector3f&, float); - static bool HasBodyInfo(CActor& act); - const CPASDatabase& GetPASDatabase() const; - void PlayBestAnimation(const CPASAnimParmData&, CRandom16&); - void LoopBestAnimation(const CPASAnimParmData&, CRandom16&); - void Freeze(float intoFreezeDur, float frozenDur, float breakoutDur); - void UnFreeze(); - float GetPercentageFrozen() const; - void SetOnFire(float); - void DouseFlames(); - void SetElectrocuting(float dur); - void DouseElectrocuting(); - void UpdateFrozenInfo(float, CStateManager&); - bool HasIceBreakoutState() const; - void StopElectrocution(); - void FrozenBreakout(); - pas::EAnimationState GetCurrentAdditiveStateId() const - { return x2a4_bodyStateInfo.GetCurrentAdditiveStateId(); } - EBodyType GetBodyType() const { return x2f4_bodyType; } - bool HasBeenFrozen() const { return x300_27_hasBeenFrozen; } - float GetRestrictedFlyerMoveSpeed() const { return x330_restrictedFlyerMoveSpeed; } - bool GetActive() const { return x300_25_active; } -}; -} + u32 _dummy = 0; + }; + float x304_intoFreezeDur = 0.f; + float x308_frozenDur = 0.f; + float x30c_breakoutDur = 0.f; + float x310_timeFrozen = 0.f; + zeus::CVector3f x314_backedUpForce; + float x320_fireDur = 0.f; + float x324_electrocutionDur = 0.f; + float x328_timeOnFire = 0.f; + float x32c_timeElectrocuting = 0.f; + float x330_restrictedFlyerMoveSpeed = 0.f; +public: + CBodyController(CActor& owner, float turnSpeed, EBodyType bodyType); + pas::EAnimationState GetCurrentStateId() const { return x2a4_bodyStateInfo.GetCurrentStateId(); } + CBodyStateCmdMgr& GetCommandMgr() { return x4_cmdMgr; } + const CBodyStateCmdMgr& GetCommandMgr() const { return x4_cmdMgr; } + void SetDoDeathAnims(bool d) { x300_28_playDeathAnims = d; } + bool IsElectrocuting() const { return x324_electrocutionDur > 0.f; } + bool IsOnFire() const { return x320_fireDur > 0.f; } + bool IsFrozen() const { return x300_26_frozen; } + const CBodyStateInfo& GetBodyStateInfo() const { return x2a4_bodyStateInfo; } + CBodyStateInfo& BodyStateInfo() { return x2a4_bodyStateInfo; } + float GetTurnSpeed() const { return x2fc_turnSpeed; } + void SetLocomotionType(pas::ELocomotionType type) { x2ec_locomotionType = type; } + pas::ELocomotionType GetLocomotionType() const { return x2ec_locomotionType; } + CActor& GetOwner() const { return x0_actor; } + bool IsAnimationOver() const { return x300_24_animationOver; } + void EnableAnimation(bool e); + bool ShouldPlayDeathAnims() const { return x300_28_playDeathAnims; } + s32 GetCurrentAnimId() const { return x2f8_curAnim; } + void Activate(CStateManager&); + CAdditiveBodyState* GetCurrentAdditiveState() { return x2a4_bodyStateInfo.GetCurrentAdditiveState(); } + void SetState(pas::EAnimationState s) { x2a4_bodyStateInfo.SetState(s); } + void Update(float, CStateManager&); + bool ShouldBeHurled() const { return HasBodyState(pas::EAnimationState::Hurled); } + bool HasBodyState(pas::EAnimationState s) const; + pas::EFallState GetFallState() const { return x2f0_fallState; } + void SetFallState(pas::EFallState s) { x2f0_fallState = s; } + void UpdateBody(float, CStateManager&); + void SetAdditiveState(pas::EAnimationState s) { x2a4_bodyStateInfo.SetAdditiveState(s); } + void SetTurnSpeed(float s); + void SetCurrentAnimation(const CAnimPlaybackParms& parms, bool loop, bool noTrans); + float GetAnimTimeRemaining() const; + void SetPlaybackRate(float); + void MultiplyPlaybackRate(float); + void SetDeltaRotation(const zeus::CQuaternion& q) { x2dc_rot *= q; } + void FaceDirection(const zeus::CVector3f&, float); + void FaceDirection3D(const zeus::CVector3f&, const zeus::CVector3f&, float); + static bool HasBodyInfo(CActor& act); + const CPASDatabase& GetPASDatabase() const; + void PlayBestAnimation(const CPASAnimParmData&, CRandom16&); + void LoopBestAnimation(const CPASAnimParmData&, CRandom16&); + void Freeze(float intoFreezeDur, float frozenDur, float breakoutDur); + void UnFreeze(); + float GetPercentageFrozen() const; + void SetOnFire(float); + void DouseFlames(); + void SetElectrocuting(float dur); + void DouseElectrocuting(); + void UpdateFrozenInfo(float, CStateManager&); + bool HasIceBreakoutState() const; + void StopElectrocution(); + void FrozenBreakout(); + pas::EAnimationState GetCurrentAdditiveStateId() const { return x2a4_bodyStateInfo.GetCurrentAdditiveStateId(); } + EBodyType GetBodyType() const { return x2f4_bodyType; } + bool HasBeenFrozen() const { return x300_27_hasBeenFrozen; } + float GetRestrictedFlyerMoveSpeed() const { return x330_restrictedFlyerMoveSpeed; } + bool GetActive() const { return x300_25_active; } +}; +} // namespace urde diff --git a/Runtime/Character/CBodyState.cpp b/Runtime/Character/CBodyState.cpp index 6f84175d3..b6bcff990 100644 --- a/Runtime/Character/CBodyState.cpp +++ b/Runtime/Character/CBodyState.cpp @@ -6,2410 +6,1959 @@ #include "CPASAnimParmData.hpp" #include "World/CPatterned.hpp" -namespace urde -{ +namespace urde { -void CBSAttack::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCMeleeAttackCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)); - const CPASDatabase& pasDatabase = bc.GetPASDatabase(); - CPASAnimParmData parms(7, CPASAnimParm::FromEnum(s32(cmd->GetAttackSeverity())), - CPASAnimParm::FromEnum(s32(bc.GetLocomotionType()))); - std::pair best = pasDatabase.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - if (cmd->HasAttackTargetPos()) - { - x20_targetPos = cmd->GetAttackTargetPos(); +void CBSAttack::Start(CBodyController& bc, CStateManager& mgr) { + const CBCMeleeAttackCmd* cmd = + static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)); + const CPASDatabase& pasDatabase = bc.GetPASDatabase(); + CPASAnimParmData parms(7, CPASAnimParm::FromEnum(s32(cmd->GetAttackSeverity())), + CPASAnimParm::FromEnum(s32(bc.GetLocomotionType()))); + std::pair best = pasDatabase.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + if (cmd->HasAttackTargetPos()) { + x20_targetPos = cmd->GetAttackTargetPos(); - CCharAnimTime evTime = bc.GetOwner().GetModelData()->GetAnimationData()->GetTimeOfUserEvent( - EUserEventType::AlignTargetPosStart, CCharAnimTime::Infinity()); - x2c_alignTargetPosStartTime = (evTime != CCharAnimTime::Infinity()) ? evTime.GetSeconds() : 0.f; + CCharAnimTime evTime = bc.GetOwner().GetModelData()->GetAnimationData()->GetTimeOfUserEvent( + EUserEventType::AlignTargetPosStart, CCharAnimTime::Infinity()); + x2c_alignTargetPosStartTime = (evTime != CCharAnimTime::Infinity()) ? evTime.GetSeconds() : 0.f; - evTime = bc.GetOwner().GetModelData()->GetAnimationData()->GetTimeOfUserEvent( - EUserEventType::AlignTargetPos, CCharAnimTime::Infinity()); - x30_alignTargetPosTime = (evTime != CCharAnimTime::Infinity()) ? - evTime.GetSeconds() : bc.GetAnimTimeRemaining(); - } - else - { - x20_targetPos = zeus::CVector3f::skZero; - x2c_alignTargetPosStartTime = -1.f; - x30_alignTargetPosTime = -1.f; - } + evTime = bc.GetOwner().GetModelData()->GetAnimationData()->GetTimeOfUserEvent(EUserEventType::AlignTargetPos, + CCharAnimTime::Infinity()); + x30_alignTargetPosTime = (evTime != CCharAnimTime::Infinity()) ? evTime.GetSeconds() : bc.GetAnimTimeRemaining(); + } else { + x20_targetPos = zeus::CVector3f::skZero; + x2c_alignTargetPosStartTime = -1.f; + x30_alignTargetPosTime = -1.f; + } - x4_nextState = pas::EAnimationState::Locomotion; - x34_curTime = 0.f; + x4_nextState = pas::EAnimationState::Locomotion; + x34_curTime = 0.f; } -pas::EAnimationState CBSAttack::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) - return pas::EAnimationState::Locomotion; - if (const CBCSlideCmd* cmd = static_cast( - bc.GetCommandMgr().GetCmd(EBodyStateCmd::Slide))) - { - x8_slide = *cmd; - x4_nextState = pas::EAnimationState::Slide; - } - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) - return pas::EAnimationState::Generate; - if (bc.IsAnimationOver()) - { - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) - return pas::EAnimationState::MeleeAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) - return pas::EAnimationState::ProjectileAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) - return pas::EAnimationState::LoopAttack; - return x4_nextState; - } - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) - return x4_nextState; - return pas::EAnimationState::Invalid; -} - -void CBSAttack::UpdatePhysicsActor(CBodyController& bc, float dt) -{ - if (x20_targetPos.isZero()) - return; - if (x34_curTime >= x2c_alignTargetPosStartTime && x34_curTime <= x30_alignTargetPosTime) - { - if (TCastToPtr act = bc.GetOwner()) - { - zeus::CVector3f delta = x20_targetPos - act->GetTranslation(); - float td = x30_alignTargetPosTime - x2c_alignTargetPosStartTime; - if (dt > 0.f) - delta *= zeus::CVector3f(dt / td); - zeus::CVector3f localDelta = act->GetTransform().transposeRotate(delta); - act->ApplyImpulseWR(act->GetMoveToORImpulseWR(localDelta, dt), zeus::CAxisAngle::sIdentity); - } - } -} - -pas::EAnimationState CBSAttack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - x34_curTime += dt; - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - if (!bc.GetCommandMgr().GetTargetVector().isZero()) - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - UpdatePhysicsActor(bc, dt); - } - else if (st == pas::EAnimationState::Slide) - { - bc.GetCommandMgr().DeliverCmd(x8_slide); - } - return st; -} - -void CBSProjectileAttack::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCProjectileAttackCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)); - zeus::CVector3f localDelta = - bc.GetOwner().GetTransform().transposeRotate(cmd->GetTargetPosition() - - bc.GetOwner().GetTranslation()); - zeus::CRelAngle angle = std::atan2(localDelta.y(), localDelta.x()); - float attackAngle = angle.asDegrees(); - CPASAnimParmData parms(18, CPASAnimParm::FromEnum(s32(cmd->GetAttackSeverity())), - CPASAnimParm::FromReal32(angle.asDegrees()), - CPASAnimParm::FromEnum(s32(bc.GetLocomotionType()))); - std::pair best1 = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (cmd->BlendTwoClosest()) - { - std::pair best2 = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), - best1.second); - const CPASAnimState* projAttackState = bc.GetPASDatabase().GetAnimState(18); - float angle1 = projAttackState->GetAnimParmData(best1.second, 1).GetReal32Value(); - float angle2 = projAttackState->GetAnimParmData(best2.second, 1).GetReal32Value(); - if (angle1 - angle2 > 180.f) - angle2 += 360.f; - else if (angle2 - angle1 > 180.f) - angle1 += 360.f; - CAnimPlaybackParms playParms(best1.second, best2.second, - (angle1 - attackAngle) / (angle1 - angle2), true); - bc.SetCurrentAnimation(playParms, false, false); - } - else - { - CAnimPlaybackParms playParms(best1.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - } -} - -pas::EAnimationState CBSProjectileAttack::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) - return pas::EAnimationState::Locomotion; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) - return pas::EAnimationState::Generate; - if (bc.IsAnimationOver() || bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSProjectileAttack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - if (!bc.GetCommandMgr().GetTargetVector().isZero()) - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - return st; -} - -void CBSDie::Start(CBodyController& bc, CStateManager& mgr) -{ - bool shouldReset = true; - if (bc.ShouldPlayDeathAnims()) - { - CPASAnimParmData parms(4, CPASAnimParm::FromEnum(s32(bc.GetFallState()))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > 0.f) - { - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - x4_remTime = bc.GetAnimTimeRemaining(); - shouldReset = false; - } - } - - if (shouldReset) - { - bc.EnableAnimation(false); - x4_remTime = bc.ShouldPlayDeathAnims() ? 3.f : 4.f; - } - - x8_isDead = false; -} - -pas::EAnimationState CBSDie::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - x4_remTime -= dt; - if (x4_remTime <= 0.f) - { - bc.EnableAnimation(false); - x8_isDead = true; - } - return pas::EAnimationState::Invalid; -} - -void CBSFall::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCKnockDownCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)); - zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetHitDirection()); - zeus::CRelAngle angle = std::atan2(localDir.y(), localDir.z()); - CPASAnimParmData parms(0, CPASAnimParm::FromReal32(angle.asDegrees()), - CPASAnimParm::FromEnum(s32(cmd->GetHitSeverity()))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - const CPASAnimState* knockdownState = bc.GetPASDatabase().GetAnimState(0); - if (!knockdownState->GetAnimParmData(best.second, 2).GetBoolValue()) - { - float animAngle = zeus::degToRad(knockdownState->GetAnimParmData(best.second, 0).GetReal32Value()); - zeus::CRelAngle delta1 = angle - animAngle; - zeus::CRelAngle delta2 = animAngle - angle; - float minAngle = std::min(float(delta1), float(delta2)); - x8_remTime = 0.15f * bc.GetAnimTimeRemaining(); - float flippedAngle = (delta1 > M_PIF) ? -minAngle : minAngle; - x4_rotateSpeed = (x8_remTime > FLT_EPSILON) ? flippedAngle / x8_remTime : flippedAngle; - } - else - { - x8_remTime = 0.f; - x4_rotateSpeed = 0.f; - } - xc_fallState = pas::EFallState(knockdownState->GetAnimParmData(best.second, 3).GetEnumValue()); -} - -pas::EAnimationState CBSFall::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.IsAnimationOver()) - return pas::EAnimationState::LieOnGround; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSFall::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid && x8_remTime > 0.f) - { - zeus::CQuaternion quat; - quat.rotateZ(x4_rotateSpeed * dt); - bc.SetDeltaRotation(quat); - x8_remTime -= dt; - } - return st; -} - -void CBSFall::Shutdown(CBodyController& bc) -{ - bc.SetFallState(xc_fallState); -} - -void CBSGetup::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCGetupCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Getup)); - CPASAnimParmData parms(1, CPASAnimParm::FromEnum(s32(bc.GetFallState())), - CPASAnimParm::FromEnum(s32(cmd->GetGetupType()))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > FLT_EPSILON) - { - if (best.second != bc.GetCurrentAnimId()) - { - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - } - x4_fallState = - pas::EFallState(bc.GetPASDatabase().GetAnimState(1)->GetAnimParmData(best.second, 2).GetEnumValue()); - } - else - { - x4_fallState = pas::EFallState::Zero; - } -} - -pas::EAnimationState CBSGetup::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.IsAnimationOver()) - { - if (x4_fallState == pas::EFallState::Zero) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Getup; - } - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSGetup::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - return GetBodyStateTransition(dt, bc); -} - -void CBSGetup::Shutdown(CBodyController& bc) -{ - bc.SetFallState(x4_fallState); -} - -void CBSKnockBack::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCKnockBackCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)); - zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetHitDirection()); - zeus::CRelAngle angle = std::atan2(localDir.y(), localDir.x()); - CPASAnimParmData parms(6, CPASAnimParm::FromReal32(angle.asDegrees()), - CPASAnimParm::FromEnum(s32(cmd->GetHitSeverity()))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - const CPASAnimState* knockbackState = bc.GetPASDatabase().GetAnimState(6); - if (!knockbackState->GetAnimParmData(best.second, 2).GetBoolValue()) - { - float animAngle = zeus::degToRad(knockbackState->GetAnimParmData(best.second, 0).GetReal32Value()); - zeus::CRelAngle delta1 = angle - animAngle; - zeus::CRelAngle delta2 = animAngle - angle; - float minAngle = std::min(float(delta1), float(delta2)); - float flippedAngle = (delta1 > M_PIF) ? -minAngle : minAngle; - xc_remTime = 0.15f * bc.GetAnimTimeRemaining(); - x8_rotateSpeed = (xc_remTime > FLT_EPSILON) ? flippedAngle / xc_remTime : flippedAngle; - } - else - { - xc_remTime = 0.f; - x8_rotateSpeed = 0.f; - } - x4_curTime = 0.f; -} - -pas::EAnimationState CBSKnockBack::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack) && x4_curTime > 0.2f) - return pas::EAnimationState::KnockBack; - if (bc.IsAnimationOver()) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSKnockBack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - x4_curTime += dt; - if (xc_remTime > 0.f) - { - zeus::CQuaternion quat; - quat.rotateZ(x8_rotateSpeed * dt); - bc.SetDeltaRotation(quat); - xc_remTime -= dt; - } - } - return st; -} - -CBSLieOnGround::CBSLieOnGround(CActor& actor) -{ - x4_24_hasGroundHit = - actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase().HasState(11); -} - -void CBSLieOnGround::Start(CBodyController& bc, CStateManager& mgr) -{ - CPASAnimParmData parms(2, CPASAnimParm::FromEnum(s32(bc.GetFallState()))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > 0.f) - { - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, true, false); - } - else - { - bc.EnableAnimation(false); - } -} - -pas::EAnimationState CBSLieOnGround::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Die)) - return pas::EAnimationState::Death; - if (x4_24_hasGroundHit && bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::GroundHit; - if (!bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion) && - bc.GetCommandMgr().GetCmd(EBodyStateCmd::Getup)) - return pas::EAnimationState::Getup; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSLieOnGround::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - return GetBodyStateTransition(dt, bc); -} - -void CBSLieOnGround::Shutdown(CBodyController& bc) -{ - bc.EnableAnimation(true); -} - -void CBSStep::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCStepCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)); - CPASAnimParmData parms(3, CPASAnimParm::FromEnum(s32(cmd->GetStepDirection())), - CPASAnimParm::FromEnum(s32(cmd->GetStepType()))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); -} - -pas::EAnimationState CBSStep::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) - return pas::EAnimationState::Locomotion; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) - return pas::EAnimationState::Generate; +pas::EAnimationState CBSAttack::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) + return pas::EAnimationState::Locomotion; + if (const CBCSlideCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Slide))) { + x8_slide = *cmd; + x4_nextState = pas::EAnimationState::Slide; + } + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) + return pas::EAnimationState::Generate; + if (bc.IsAnimationOver()) { if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) - return pas::EAnimationState::MeleeAttack; + return pas::EAnimationState::MeleeAttack; if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) - return pas::EAnimationState::ProjectileAttack; + return pas::EAnimationState::ProjectileAttack; if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) - return pas::EAnimationState::LoopAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump)) - return pas::EAnimationState::Jump; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)) - return pas::EAnimationState::Scripted; - if (bc.IsAnimationOver() || bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; + return pas::EAnimationState::LoopAttack; + return x4_nextState; + } + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) + return x4_nextState; + return pas::EAnimationState::Invalid; } -pas::EAnimationState CBSStep::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid && !bc.GetCommandMgr().GetTargetVector().isZero()) - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - return st; +void CBSAttack::UpdatePhysicsActor(CBodyController& bc, float dt) { + if (x20_targetPos.isZero()) + return; + if (x34_curTime >= x2c_alignTargetPosStartTime && x34_curTime <= x30_alignTargetPosTime) { + if (TCastToPtr act = bc.GetOwner()) { + zeus::CVector3f delta = x20_targetPos - act->GetTranslation(); + float td = x30_alignTargetPosTime - x2c_alignTargetPosStartTime; + if (dt > 0.f) + delta *= zeus::CVector3f(dt / td); + zeus::CVector3f localDelta = act->GetTransform().transposeRotate(delta); + act->ApplyImpulseWR(act->GetMoveToORImpulseWR(localDelta, dt), zeus::CAxisAngle::sIdentity); + } + } } -void CBSTurn::Start(CBodyController& bc, CStateManager& mgr) -{ - const zeus::CVector3f& lookDir = bc.GetOwner().GetTransform().basis[1]; - zeus::CVector2f lookDir2d(lookDir.toVec2f()); +pas::EAnimationState CBSAttack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + x34_curTime += dt; + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + if (!bc.GetCommandMgr().GetTargetVector().isZero()) + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + UpdatePhysicsActor(bc, dt); + } else if (st == pas::EAnimationState::Slide) { + bc.GetCommandMgr().DeliverCmd(x8_slide); + } + return st; +} + +void CBSProjectileAttack::Start(CBodyController& bc, CStateManager& mgr) { + const CBCProjectileAttackCmd* cmd = + static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)); + zeus::CVector3f localDelta = + bc.GetOwner().GetTransform().transposeRotate(cmd->GetTargetPosition() - bc.GetOwner().GetTranslation()); + zeus::CRelAngle angle = std::atan2(localDelta.y(), localDelta.x()); + float attackAngle = angle.asDegrees(); + CPASAnimParmData parms(18, CPASAnimParm::FromEnum(s32(cmd->GetAttackSeverity())), + CPASAnimParm::FromReal32(angle.asDegrees()), + CPASAnimParm::FromEnum(s32(bc.GetLocomotionType()))); + std::pair best1 = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (cmd->BlendTwoClosest()) { + std::pair best2 = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), best1.second); + const CPASAnimState* projAttackState = bc.GetPASDatabase().GetAnimState(18); + float angle1 = projAttackState->GetAnimParmData(best1.second, 1).GetReal32Value(); + float angle2 = projAttackState->GetAnimParmData(best2.second, 1).GetReal32Value(); + if (angle1 - angle2 > 180.f) + angle2 += 360.f; + else if (angle2 - angle1 > 180.f) + angle1 += 360.f; + CAnimPlaybackParms playParms(best1.second, best2.second, (angle1 - attackAngle) / (angle1 - angle2), true); + bc.SetCurrentAnimation(playParms, false, false); + } else { + CAnimPlaybackParms playParms(best1.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + } +} + +pas::EAnimationState CBSProjectileAttack::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) + return pas::EAnimationState::Locomotion; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) + return pas::EAnimationState::Generate; + if (bc.IsAnimationOver() || bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSProjectileAttack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) + if (!bc.GetCommandMgr().GetTargetVector().isZero()) + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + return st; +} + +void CBSDie::Start(CBodyController& bc, CStateManager& mgr) { + bool shouldReset = true; + if (bc.ShouldPlayDeathAnims()) { + CPASAnimParmData parms(4, CPASAnimParm::FromEnum(s32(bc.GetFallState()))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > 0.f) { + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + x4_remTime = bc.GetAnimTimeRemaining(); + shouldReset = false; + } + } + + if (shouldReset) { + bc.EnableAnimation(false); + x4_remTime = bc.ShouldPlayDeathAnims() ? 3.f : 4.f; + } + + x8_isDead = false; +} + +pas::EAnimationState CBSDie::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + x4_remTime -= dt; + if (x4_remTime <= 0.f) { + bc.EnableAnimation(false); + x8_isDead = true; + } + return pas::EAnimationState::Invalid; +} + +void CBSFall::Start(CBodyController& bc, CStateManager& mgr) { + const CBCKnockDownCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)); + zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetHitDirection()); + zeus::CRelAngle angle = std::atan2(localDir.y(), localDir.z()); + CPASAnimParmData parms(0, CPASAnimParm::FromReal32(angle.asDegrees()), + CPASAnimParm::FromEnum(s32(cmd->GetHitSeverity()))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + const CPASAnimState* knockdownState = bc.GetPASDatabase().GetAnimState(0); + if (!knockdownState->GetAnimParmData(best.second, 2).GetBoolValue()) { + float animAngle = zeus::degToRad(knockdownState->GetAnimParmData(best.second, 0).GetReal32Value()); + zeus::CRelAngle delta1 = angle - animAngle; + zeus::CRelAngle delta2 = animAngle - angle; + float minAngle = std::min(float(delta1), float(delta2)); + x8_remTime = 0.15f * bc.GetAnimTimeRemaining(); + float flippedAngle = (delta1 > M_PIF) ? -minAngle : minAngle; + x4_rotateSpeed = (x8_remTime > FLT_EPSILON) ? flippedAngle / x8_remTime : flippedAngle; + } else { + x8_remTime = 0.f; + x4_rotateSpeed = 0.f; + } + xc_fallState = pas::EFallState(knockdownState->GetAnimParmData(best.second, 3).GetEnumValue()); +} + +pas::EAnimationState CBSFall::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.IsAnimationOver()) + return pas::EAnimationState::LieOnGround; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSFall::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid && x8_remTime > 0.f) { + zeus::CQuaternion quat; + quat.rotateZ(x4_rotateSpeed * dt); + bc.SetDeltaRotation(quat); + x8_remTime -= dt; + } + return st; +} + +void CBSFall::Shutdown(CBodyController& bc) { bc.SetFallState(xc_fallState); } + +void CBSGetup::Start(CBodyController& bc, CStateManager& mgr) { + const CBCGetupCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Getup)); + CPASAnimParmData parms(1, CPASAnimParm::FromEnum(s32(bc.GetFallState())), + CPASAnimParm::FromEnum(s32(cmd->GetGetupType()))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > FLT_EPSILON) { + if (best.second != bc.GetCurrentAnimId()) { + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + } + x4_fallState = pas::EFallState(bc.GetPASDatabase().GetAnimState(1)->GetAnimParmData(best.second, 2).GetEnumValue()); + } else { + x4_fallState = pas::EFallState::Zero; + } +} + +pas::EAnimationState CBSGetup::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.IsAnimationOver()) { + if (x4_fallState == pas::EFallState::Zero) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Getup; + } + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSGetup::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + return GetBodyStateTransition(dt, bc); +} + +void CBSGetup::Shutdown(CBodyController& bc) { bc.SetFallState(x4_fallState); } + +void CBSKnockBack::Start(CBodyController& bc, CStateManager& mgr) { + const CBCKnockBackCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)); + zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetHitDirection()); + zeus::CRelAngle angle = std::atan2(localDir.y(), localDir.x()); + CPASAnimParmData parms(6, CPASAnimParm::FromReal32(angle.asDegrees()), + CPASAnimParm::FromEnum(s32(cmd->GetHitSeverity()))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + const CPASAnimState* knockbackState = bc.GetPASDatabase().GetAnimState(6); + if (!knockbackState->GetAnimParmData(best.second, 2).GetBoolValue()) { + float animAngle = zeus::degToRad(knockbackState->GetAnimParmData(best.second, 0).GetReal32Value()); + zeus::CRelAngle delta1 = angle - animAngle; + zeus::CRelAngle delta2 = animAngle - angle; + float minAngle = std::min(float(delta1), float(delta2)); + float flippedAngle = (delta1 > M_PIF) ? -minAngle : minAngle; + xc_remTime = 0.15f * bc.GetAnimTimeRemaining(); + x8_rotateSpeed = (xc_remTime > FLT_EPSILON) ? flippedAngle / xc_remTime : flippedAngle; + } else { + xc_remTime = 0.f; + x8_rotateSpeed = 0.f; + } + x4_curTime = 0.f; +} + +pas::EAnimationState CBSKnockBack::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack) && x4_curTime > 0.2f) + return pas::EAnimationState::KnockBack; + if (bc.IsAnimationOver()) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSKnockBack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + x4_curTime += dt; + if (xc_remTime > 0.f) { + zeus::CQuaternion quat; + quat.rotateZ(x8_rotateSpeed * dt); + bc.SetDeltaRotation(quat); + xc_remTime -= dt; + } + } + return st; +} + +CBSLieOnGround::CBSLieOnGround(CActor& actor) { + x4_24_hasGroundHit = actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase().HasState(11); +} + +void CBSLieOnGround::Start(CBodyController& bc, CStateManager& mgr) { + CPASAnimParmData parms(2, CPASAnimParm::FromEnum(s32(bc.GetFallState()))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > 0.f) { + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, true, false); + } else { + bc.EnableAnimation(false); + } +} + +pas::EAnimationState CBSLieOnGround::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Die)) + return pas::EAnimationState::Death; + if (x4_24_hasGroundHit && bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::GroundHit; + if (!bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion) && bc.GetCommandMgr().GetCmd(EBodyStateCmd::Getup)) + return pas::EAnimationState::Getup; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSLieOnGround::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + return GetBodyStateTransition(dt, bc); +} + +void CBSLieOnGround::Shutdown(CBodyController& bc) { bc.EnableAnimation(true); } + +void CBSStep::Start(CBodyController& bc, CStateManager& mgr) { + const CBCStepCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)); + CPASAnimParmData parms(3, CPASAnimParm::FromEnum(s32(cmd->GetStepDirection())), + CPASAnimParm::FromEnum(s32(cmd->GetStepType()))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); +} + +pas::EAnimationState CBSStep::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) + return pas::EAnimationState::Locomotion; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) + return pas::EAnimationState::Generate; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) + return pas::EAnimationState::MeleeAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) + return pas::EAnimationState::ProjectileAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) + return pas::EAnimationState::LoopAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump)) + return pas::EAnimationState::Jump; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)) + return pas::EAnimationState::Scripted; + if (bc.IsAnimationOver() || bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSStep::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid && !bc.GetCommandMgr().GetTargetVector().isZero()) + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + return st; +} + +void CBSTurn::Start(CBodyController& bc, CStateManager& mgr) { + const zeus::CVector3f& lookDir = bc.GetOwner().GetTransform().basis[1]; + zeus::CVector2f lookDir2d(lookDir.toVec2f()); + x8_dest = zeus::CVector2f(bc.GetCommandMgr().GetFaceVector().toVec2f()); + float deltaAngle = zeus::radToDeg(zeus::CVector2f::getAngleDiff(lookDir2d, x8_dest)); + x10_turnDir = pas::ETurnDirection(zeus::CVector2f(lookDir2d.y(), -lookDir2d.x()).dot(x8_dest) > 0.f); + CPASAnimParmData parms(8, CPASAnimParm::FromEnum(s32(x10_turnDir)), CPASAnimParm::FromReal32(deltaAngle), + CPASAnimParm::FromEnum(s32(bc.GetLocomotionType()))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + float animAngle = bc.GetPASDatabase().GetAnimState(8)->GetAnimParmData(best.second, 1).GetReal32Value(); + x4_rotateSpeed = + zeus::degToRad((x10_turnDir == pas::ETurnDirection::Left) ? animAngle - deltaAngle : deltaAngle - animAngle); + float timeRem = bc.GetAnimTimeRemaining(); + if (timeRem > 0.f) + x4_rotateSpeed /= timeRem; +} + +bool CBSTurn::FacingDest(CBodyController& bc) const { + const zeus::CVector3f& lookDir = bc.GetOwner().GetTransform().basis[1]; + zeus::CVector2f lookDir2d(lookDir.toVec2f()); + zeus::CVector2f leftDir(lookDir2d.y(), -lookDir2d.x()); + if (x10_turnDir == pas::ETurnDirection::Left) { + if (leftDir.dot(x8_dest) < 0.f) + return true; + } else { + if (leftDir.dot(x8_dest) > 0.f) + return true; + } + return false; +} + +pas::EAnimationState CBSTurn::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) + return pas::EAnimationState::Locomotion; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) + return pas::EAnimationState::Generate; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) + return pas::EAnimationState::MeleeAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) + return pas::EAnimationState::ProjectileAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) + return pas::EAnimationState::LoopAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump)) + return pas::EAnimationState::Jump; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)) + return pas::EAnimationState::Step; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)) + return pas::EAnimationState::Scripted; + if (bc.IsAnimationOver() || FacingDest(bc) || !bc.GetCommandMgr().GetMoveVector().isZero()) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSTurn::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + zeus::CQuaternion quat; + quat.rotateZ(x4_rotateSpeed * dt); + bc.SetDeltaRotation(quat); + } + return st; +} + +void CBSFlyerTurn::Start(CBodyController& bc, CStateManager& mgr) { + if (bc.GetPASDatabase().GetAnimState(8)->GetNumAnims()) { + CBSTurn::Start(bc, mgr); + } else { x8_dest = zeus::CVector2f(bc.GetCommandMgr().GetFaceVector().toVec2f()); - float deltaAngle = zeus::radToDeg(zeus::CVector2f::getAngleDiff(lookDir2d, x8_dest)); - x10_turnDir = pas::ETurnDirection(zeus::CVector2f(lookDir2d.y(), -lookDir2d.x()).dot(x8_dest) > 0.f); - CPASAnimParmData parms(8, CPASAnimParm::FromEnum(s32(x10_turnDir)), - CPASAnimParm::FromReal32(deltaAngle), - CPASAnimParm::FromEnum(s32(bc.GetLocomotionType()))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - float animAngle = bc.GetPASDatabase().GetAnimState(8)->GetAnimParmData(best.second, 1).GetReal32Value(); - x4_rotateSpeed = zeus::degToRad((x10_turnDir == pas::ETurnDirection::Left) ? - animAngle - deltaAngle : deltaAngle - animAngle); - float timeRem = bc.GetAnimTimeRemaining(); - if (timeRem > 0.f) - x4_rotateSpeed /= timeRem; -} - -bool CBSTurn::FacingDest(CBodyController& bc) const -{ const zeus::CVector3f& lookDir = bc.GetOwner().GetTransform().basis[1]; zeus::CVector2f lookDir2d(lookDir.toVec2f()); - zeus::CVector2f leftDir(lookDir2d.y(), -lookDir2d.x()); - if (x10_turnDir == pas::ETurnDirection::Left) - { - if (leftDir.dot(x8_dest) < 0.f) - return true; + x10_turnDir = pas::ETurnDirection(zeus::CVector2f(lookDir2d.y(), -lookDir2d.x()).dot(x8_dest) > 0.f); + CPASAnimParmData parms(5, CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(s32(bc.GetLocomotionType()))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.second != bc.GetCurrentAnimId()) { + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, true, false); } - else - { - if (leftDir.dot(x8_dest) > 0.f) - return true; - } - return false; + } } -pas::EAnimationState CBSTurn::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) - return pas::EAnimationState::Locomotion; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) - return pas::EAnimationState::Generate; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) - return pas::EAnimationState::MeleeAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) - return pas::EAnimationState::ProjectileAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) - return pas::EAnimationState::LoopAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump)) - return pas::EAnimationState::Jump; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)) - return pas::EAnimationState::Step; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)) - return pas::EAnimationState::Scripted; - if (bc.IsAnimationOver() || FacingDest(bc) || !bc.GetCommandMgr().GetMoveVector().isZero()) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSTurn::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ +pas::EAnimationState CBSFlyerTurn::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + if (bc.GetPASDatabase().GetAnimState(8)->GetNumAnims()) { + return CBSTurn::UpdateBody(dt, bc, mgr); + } else { pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - zeus::CQuaternion quat; - quat.rotateZ(x4_rotateSpeed * dt); - bc.SetDeltaRotation(quat); - } - return st; -} - -void CBSFlyerTurn::Start(CBodyController& bc, CStateManager& mgr) -{ - if (bc.GetPASDatabase().GetAnimState(8)->GetNumAnims()) - { - CBSTurn::Start(bc, mgr); - } - else - { + if (st == pas::EAnimationState::Invalid) { + if (!bc.GetCommandMgr().GetFaceVector().isZero()) { x8_dest = zeus::CVector2f(bc.GetCommandMgr().GetFaceVector().toVec2f()); const zeus::CVector3f& lookDir = bc.GetOwner().GetTransform().basis[1]; zeus::CVector2f lookDir2d(lookDir.toVec2f()); x10_turnDir = pas::ETurnDirection(zeus::CVector2f(lookDir2d.y(), -lookDir2d.x()).dot(x8_dest) > 0.f); - CPASAnimParmData parms(5, CPASAnimParm::FromEnum(0), - CPASAnimParm::FromEnum(s32(bc.GetLocomotionType()))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.second != bc.GetCurrentAnimId()) - { - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, true, false); - } - } -} - -pas::EAnimationState CBSFlyerTurn::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - if (bc.GetPASDatabase().GetAnimState(8)->GetNumAnims()) - { - return CBSTurn::UpdateBody(dt, bc, mgr); - } - else - { - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - if (!bc.GetCommandMgr().GetFaceVector().isZero()) - { - x8_dest = zeus::CVector2f(bc.GetCommandMgr().GetFaceVector().toVec2f()); - const zeus::CVector3f& lookDir = bc.GetOwner().GetTransform().basis[1]; - zeus::CVector2f lookDir2d(lookDir.toVec2f()); - x10_turnDir = pas::ETurnDirection(zeus::CVector2f(lookDir2d.y(), -lookDir2d.x()).dot(x8_dest) > 0.f); - } - bc.FaceDirection(zeus::CVector3f(x8_dest.x(), x8_dest.y(), 0.f), dt); - } - return st; - } -} - -void CBSLoopAttack::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCLoopAttackCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)); - x8_loopAttackType = cmd->GetAttackType(); - xc_24_waitForAnimOver = cmd->WaitForAnimOver(); - xc_25_advance = false; - if (bc.GetLocomotionType() == pas::ELocomotionType::Crouch) - { - CPASAnimParmData parms(9, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_loopAttackType))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - else - { - x4_state = pas::ELoopState::Begin; - CPASAnimParmData parms(9, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_loopAttackType))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > FLT_EPSILON) - { - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - } - else - { - x4_state = pas::ELoopState::Loop; - CPASAnimParmData parms(9, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_loopAttackType))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - } -} - -pas::EAnimationState CBSLoopAttack::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) - return pas::EAnimationState::Locomotion; - if (x4_state == pas::ELoopState::End) - { - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) - return pas::EAnimationState::MeleeAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) - return pas::EAnimationState::ProjectileAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) - return pas::EAnimationState::LoopAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)) - return pas::EAnimationState::Step; - if (!bc.GetCommandMgr().GetMoveVector().isZero()) - return pas::EAnimationState::Locomotion; - if (!bc.GetCommandMgr().GetFaceVector().isZero()) - return pas::EAnimationState::Turn; - } - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSLoopAttack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - xc_25_advance |= bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState) != nullptr; - switch (x4_state) - { - case pas::ELoopState::Begin: - if (xc_25_advance && (!xc_24_waitForAnimOver || bc.IsAnimationOver())) - { - x4_state = pas::ELoopState::Invalid; - return pas::EAnimationState::Locomotion; - } - if (bc.IsAnimationOver()) - { - CPASAnimParmData parms(9, CPASAnimParm::FromEnum(1), - CPASAnimParm::FromEnum(s32(x8_loopAttackType))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - x4_state = pas::ELoopState::Loop; - } - else if (!bc.GetCommandMgr().GetTargetVector().isZero()) - { - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - } - break; - case pas::ELoopState::Loop: - if (xc_25_advance && (!xc_24_waitForAnimOver || bc.IsAnimationOver())) - { - if (bc.GetLocomotionType() != pas::ELocomotionType::Crouch) - { - CPASAnimParmData parms(9, CPASAnimParm::FromEnum(2), - CPASAnimParm::FromEnum(s32(x8_loopAttackType))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); - x4_state = pas::ELoopState::End; - } - else - { - x4_state = pas::ELoopState::Invalid; - return pas::EAnimationState::Locomotion; - } - } - break; - case pas::ELoopState::End: - if (bc.IsAnimationOver()) - { - x4_state = pas::ELoopState::Invalid; - return pas::EAnimationState::Locomotion; - } - break; - default: break; - } + } + bc.FaceDirection(zeus::CVector3f(x8_dest.x(), x8_dest.y(), 0.f), dt); } return st; + } } -void CBSLoopReaction::Start(CBodyController& bc, CStateManager& mgr) -{ - if (const CBCLoopReactionCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopReaction))) - { - x8_reactionType = cmd->GetReactionType(); - xc_24_loopHit = false; - } - else - { - const CBCLoopHitReactionCmd* hcmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)); - x8_reactionType = hcmd->GetReactionType(); - xc_24_loopHit = true; - } - +void CBSLoopAttack::Start(CBodyController& bc, CStateManager& mgr) { + const CBCLoopAttackCmd* cmd = + static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)); + x8_loopAttackType = cmd->GetAttackType(); + xc_24_waitForAnimOver = cmd->WaitForAnimOver(); + xc_25_advance = false; + if (bc.GetLocomotionType() == pas::ELocomotionType::Crouch) { + CPASAnimParmData parms(9, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_loopAttackType))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } else { x4_state = pas::ELoopState::Begin; - CPASAnimParmData parms(10, CPASAnimParm::FromEnum(s32(x8_reactionType)), - CPASAnimParm::FromEnum(s32(x4_state))); + CPASAnimParmData parms(9, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_loopAttackType))); std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > FLT_EPSILON) - { - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); + if (best.first > FLT_EPSILON) { + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + } else { + x4_state = pas::ELoopState::Loop; + CPASAnimParmData parms(9, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_loopAttackType))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); } - else - { + } +} + +pas::EAnimationState CBSLoopAttack::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) + return pas::EAnimationState::Locomotion; + if (x4_state == pas::ELoopState::End) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) + return pas::EAnimationState::MeleeAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) + return pas::EAnimationState::ProjectileAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) + return pas::EAnimationState::LoopAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)) + return pas::EAnimationState::Step; + if (!bc.GetCommandMgr().GetMoveVector().isZero()) + return pas::EAnimationState::Locomotion; + if (!bc.GetCommandMgr().GetFaceVector().isZero()) + return pas::EAnimationState::Turn; + } + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSLoopAttack::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + xc_25_advance |= bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState) != nullptr; + switch (x4_state) { + case pas::ELoopState::Begin: + if (xc_25_advance && (!xc_24_waitForAnimOver || bc.IsAnimationOver())) { + x4_state = pas::ELoopState::Invalid; + return pas::EAnimationState::Locomotion; + } + if (bc.IsAnimationOver()) { + CPASAnimParmData parms(9, CPASAnimParm::FromEnum(1), CPASAnimParm::FromEnum(s32(x8_loopAttackType))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); x4_state = pas::ELoopState::Loop; - CPASAnimParmData parms(10, CPASAnimParm::FromEnum(s32(x8_reactionType)), - CPASAnimParm::FromEnum(s32(x4_state))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } -} - -pas::EAnimationState CBSLoopReaction::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (!xc_24_loopHit && bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) - return pas::EAnimationState::Locomotion; - if (x4_state == pas::ELoopState::End) - { - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) - return pas::EAnimationState::MeleeAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) - return pas::EAnimationState::ProjectileAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) - return pas::EAnimationState::LoopAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)) - return pas::EAnimationState::Step; - if (!bc.GetCommandMgr().GetMoveVector().isZero()) - return pas::EAnimationState::Locomotion; - if (!bc.GetCommandMgr().GetFaceVector().isZero()) - return pas::EAnimationState::Turn; - } - return pas::EAnimationState::Invalid; -} - -bool CBSLoopReaction::PlayExitAnimation(CBodyController& bc, CStateManager& mgr) const -{ - CPASAnimParmData parms(10, CPASAnimParm::FromEnum(int(x8_reactionType)), - CPASAnimParm::FromEnum(2)); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > 0.f) - { - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - return true; - } - return false; -} - -pas::EAnimationState CBSLoopReaction::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - switch (x4_state) - { - case pas::ELoopState::Begin: - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) - { - if (PlayExitAnimation(bc, mgr)) - { - x4_state = pas::ELoopState::End; - } - else - { - x4_state = pas::ELoopState::Invalid; - return pas::EAnimationState::Locomotion; - } - } - else - { - if (bc.IsAnimationOver()) - { - CPASAnimParmData parms(10, CPASAnimParm::FromEnum(s32(x8_reactionType)), - CPASAnimParm::FromEnum(1)); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - x4_state = pas::ELoopState::Loop; - } - else if (!bc.GetCommandMgr().GetTargetVector().isZero()) - { - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - } - } - break; - case pas::ELoopState::Loop: - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) - { - if (PlayExitAnimation(bc, mgr)) - { - x4_state = pas::ELoopState::End; - } - else - { - x4_state = pas::ELoopState::Invalid; - return pas::EAnimationState::Locomotion; - } - } - else if (!bc.GetCommandMgr().GetTargetVector().isZero()) - { - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - } - break; - case pas::ELoopState::End: - if (bc.IsAnimationOver()) - { - x4_state = pas::ELoopState::Invalid; - return pas::EAnimationState::Locomotion; - } - break; - default: break; + } else if (!bc.GetCommandMgr().GetTargetVector().isZero()) { + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + } + break; + case pas::ELoopState::Loop: + if (xc_25_advance && (!xc_24_waitForAnimOver || bc.IsAnimationOver())) { + if (bc.GetLocomotionType() != pas::ELocomotionType::Crouch) { + CPASAnimParmData parms(9, CPASAnimParm::FromEnum(2), CPASAnimParm::FromEnum(s32(x8_loopAttackType))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); + x4_state = pas::ELoopState::End; + } else { + x4_state = pas::ELoopState::Invalid; + return pas::EAnimationState::Locomotion; } + } + break; + case pas::ELoopState::End: + if (bc.IsAnimationOver()) { + x4_state = pas::ELoopState::Invalid; + return pas::EAnimationState::Locomotion; + } + break; + default: + break; } - return st; + } + return st; } -void CBSGroundHit::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCKnockBackCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)); - zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetHitDirection()); - zeus::CRelAngle angle = std::atan2(localDir.y(), localDir.x()); - CPASAnimParmData parms(11, CPASAnimParm::FromEnum(s32(bc.GetFallState())), - CPASAnimParm::FromReal32(angle.asDegrees())); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); +void CBSLoopReaction::Start(CBodyController& bc, CStateManager& mgr) { + if (const CBCLoopReactionCmd* cmd = + static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopReaction))) { + x8_reactionType = cmd->GetReactionType(); + xc_24_loopHit = false; + } else { + const CBCLoopHitReactionCmd* hcmd = + static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)); + x8_reactionType = hcmd->GetReactionType(); + xc_24_loopHit = true; + } + + x4_state = pas::ELoopState::Begin; + CPASAnimParmData parms(10, CPASAnimParm::FromEnum(s32(x8_reactionType)), CPASAnimParm::FromEnum(s32(x4_state))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > FLT_EPSILON) { CAnimPlaybackParms playParms(best.second, -1, 1.f, true); bc.SetCurrentAnimation(playParms, false, false); - const CPASAnimState* groundHitState = bc.GetPASDatabase().GetAnimState(11); - if (!groundHitState->GetAnimParmData(best.second, 2).GetBoolValue()) - { - float animAngle = zeus::degToRad(groundHitState->GetAnimParmData(best.second, 1).GetReal32Value()); - zeus::CRelAngle delta1 = angle - animAngle; - zeus::CRelAngle delta2 = animAngle - angle; - float minAngle = std::min(float(delta1), float(delta2)); - float flippedAngle = (delta1 > M_PIF) ? -minAngle : minAngle; - x8_remTime = 0.15f * bc.GetAnimTimeRemaining(); - x4_rotateSpeed = (x8_remTime > FLT_EPSILON) ? flippedAngle / x8_remTime : flippedAngle; - } - else - { - x8_remTime = 0.f; - x4_rotateSpeed = 0.f; - } - xc_fallState = pas::EFallState(groundHitState->GetAnimParmData(best.second, 3).GetEnumValue()); + } else { + x4_state = pas::ELoopState::Loop; + CPASAnimParmData parms(10, CPASAnimParm::FromEnum(s32(x8_reactionType)), CPASAnimParm::FromEnum(s32(x4_state))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } } -pas::EAnimationState CBSGroundHit::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.IsAnimationOver()) - { - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Die)) - return pas::EAnimationState::Death; - return pas::EAnimationState::LieOnGround; - } - return pas::EAnimationState::Invalid; +pas::EAnimationState CBSLoopReaction::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (!xc_24_loopHit && bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) + return pas::EAnimationState::Locomotion; + if (x4_state == pas::ELoopState::End) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) + return pas::EAnimationState::MeleeAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) + return pas::EAnimationState::ProjectileAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) + return pas::EAnimationState::LoopAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)) + return pas::EAnimationState::Step; + if (!bc.GetCommandMgr().GetMoveVector().isZero()) + return pas::EAnimationState::Locomotion; + if (!bc.GetCommandMgr().GetFaceVector().isZero()) + return pas::EAnimationState::Turn; + } + return pas::EAnimationState::Invalid; } -pas::EAnimationState CBSGroundHit::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid && x8_remTime > 0.f) - { - zeus::CQuaternion quat; - quat.rotateZ(x4_rotateSpeed * dt); - bc.SetDeltaRotation(quat); - x8_remTime -= dt; - } - return st; -} - -void CBSGroundHit::Shutdown(CBodyController& bc) -{ - bc.SetFallState(xc_fallState); -} - -void CBSGenerate::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCGenerateCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)); - s32 anim; - if (!cmd->UseSpecialAnimId()) - { - CPASAnimParmData parms(12, CPASAnimParm::FromEnum(s32(cmd->GetGenerateType()))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - anim = best.second; - } - else - { - anim = cmd->GetSpecialAnimId(); - } - - if (cmd->HasExitTargetPos()) - { - CAnimPlaybackParms playParms(anim, nullptr, &cmd->GetExitTargetPos(), &bc.GetOwner().GetTransform(), - &bc.GetOwner().GetModelData()->GetScale(), false); - bc.SetCurrentAnimation(playParms, false, false); - } - else - { - CAnimPlaybackParms playParms(anim, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - } -} - -pas::EAnimationState CBSGenerate::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) - return pas::EAnimationState::Generate; - if (bc.IsAnimationOver() || bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSGenerate::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - if (!bc.GetCommandMgr().GetTargetVector().isZero()) - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - return st; -} - -void CBSJump::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCJumpCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump)); - x8_jumpType = cmd->GetJumpType(); - xc_waypoint1 = cmd->GetJumpTarget(); - x24_waypoint2 = cmd->GetSecondJumpTarget(); - x30_25_wallJump = cmd->IsWallJump(); - x30_28_startInJumpLoop = cmd->StartInJumpLoop(); - x30_24_bodyForceSet = false; - x30_27_wallBounceComplete = false; - if (x30_25_wallJump) - x30_26_wallBounceRight = - (xc_waypoint1 - bc.GetOwner().GetTranslation()).cross(zeus::CVector3f::skUp). - dot(x24_waypoint2 - xc_waypoint1) < 0.f; - if (!cmd->StartInJumpLoop()) - { - x4_state = pas::EJumpState::IntoJump; - CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_jumpType))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); - } - else - { - PlayJumpLoop(mgr, bc); - } -} - -pas::EAnimationState CBSJump::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump) && - bc.GetBodyType() == EBodyType::WallWalker) - return pas::EAnimationState::Jump; - return pas::EAnimationState::Invalid; -} - -bool CBSJump::CheckForWallJump(CBodyController& bc, CStateManager& mgr) -{ - if (x30_25_wallJump && !x30_27_wallBounceComplete) - { - if (TCastToPtr act = bc.GetOwner()) - { - float distToWall = (xc_waypoint1 - act->GetTranslation()).magnitude(); - zeus::CAABox aabb = act->GetBoundingBox(); - float xExtent = (aabb.max.x() - aabb.min.x()) * 0.5f; - if (distToWall < 1.414f * xExtent || (act->CanLongJump() && distToWall < 3.f * xExtent)) - { - x4_state = x30_26_wallBounceRight ? pas::EJumpState::WallBounceRight : pas::EJumpState::WallBounceLeft; - CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_jumpType))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); - mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); - return true; - } - } - } - return false; -} - -void CBSJump::CheckForLand(CBodyController& bc, CStateManager& mgr) -{ - if (TCastToPtr act = bc.GetOwner()) - { - if (act->CanLongJump() || act->IsOnGround()) - { - x4_state = pas::EJumpState::OutOfJump; - CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_jumpType))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); - mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); - } - } -} - -void CBSJump::PlayJumpLoop(CStateManager& mgr, CBodyController& bc) -{ - CPASAnimParmData parms(13, CPASAnimParm::FromEnum(1), - CPASAnimParm::FromEnum(s32(x8_jumpType))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > 99.f) - { - x4_state = pas::EJumpState::AmbushJump; - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - } - else - { - x4_state = pas::EJumpState::Loop; - CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_jumpType))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - - if (TCastToPtr act = bc.GetOwner()) - { - mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Falling); - mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Jumped); - x30_24_bodyForceSet = false; - x18_velocity = act->GetVelocity(); - } -} - -pas::EAnimationState CBSJump::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - switch (x4_state) - { - case pas::EJumpState::IntoJump: - if (bc.IsAnimationOver()) - PlayJumpLoop(mgr, bc); - break; - case pas::EJumpState::AmbushJump: - if (!x30_24_bodyForceSet) - { - if (TCastToPtr act = bc.GetOwner()) - act->SetConstantForce(act->GetMass() * x18_velocity); - x30_24_bodyForceSet = true; - } - if (!bc.GetCommandMgr().GetTargetVector().isZero()) - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - if (bc.IsAnimationOver()) - { - x4_state = pas::EJumpState::Loop; - CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_jumpType))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - else - { - if (!CheckForWallJump(bc, mgr)) - CheckForLand(bc, mgr); - } - break; - case pas::EJumpState::Loop: - if (!x30_24_bodyForceSet) - { - if (TCastToPtr act = bc.GetOwner()) - act->SetConstantForce(act->GetMass() * x18_velocity); - x30_24_bodyForceSet = true; - } - if (!bc.GetCommandMgr().GetTargetVector().isZero()) - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - if (!CheckForWallJump(bc, mgr)) - CheckForLand(bc, mgr); - break; - case pas::EJumpState::WallBounceLeft: - case pas::EJumpState::WallBounceRight: - if (TCastToPtr act = bc.GetOwner()) - { - act->Stop(); - act->SetMomentumWR(zeus::CVector3f::skZero); - } - if (bc.IsAnimationOver()) - { - mgr.SendScriptMsg(&bc.GetOwner(), kInvalidUniqueId, EScriptObjectMessage::Falling); - x4_state = pas::EJumpState::Loop; - CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_jumpType))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - x30_27_wallBounceComplete = true; - if (TCastToPtr act = bc.GetOwner()) - { - zeus::CVector3f toFinal = x24_waypoint2 - act->GetTranslation(); - float tmp = std::sqrt(act->GetGravityConstant() / (2.f * toFinal.z())); - act->SetVelocityWR(zeus::CVector3f(tmp * toFinal.x(), tmp * toFinal.y(), 0.f)); - } - } - break; - case pas::EJumpState::OutOfJump: - if (bc.IsAnimationOver()) - { - x4_state = pas::EJumpState::Invalid; - return pas::EAnimationState::Locomotion; - } - break; - default: break; - } - } - return st; -} - -bool CBSJump::ApplyAnimationDeltas() const -{ - if (x4_state == pas::EJumpState::AmbushJump || x4_state == pas::EJumpState::Loop) - return false; +bool CBSLoopReaction::PlayExitAnimation(CBodyController& bc, CStateManager& mgr) const { + CPASAnimParmData parms(10, CPASAnimParm::FromEnum(int(x8_reactionType)), CPASAnimParm::FromEnum(2)); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > 0.f) { + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); return true; + } + return false; } -bool CBSJump::IsInAir(const CBodyController& bc) const -{ - return x4_state == pas::EJumpState::AmbushJump || x4_state == pas::EJumpState::Loop; +pas::EAnimationState CBSLoopReaction::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + switch (x4_state) { + case pas::ELoopState::Begin: + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) { + if (PlayExitAnimation(bc, mgr)) { + x4_state = pas::ELoopState::End; + } else { + x4_state = pas::ELoopState::Invalid; + return pas::EAnimationState::Locomotion; + } + } else { + if (bc.IsAnimationOver()) { + CPASAnimParmData parms(10, CPASAnimParm::FromEnum(s32(x8_reactionType)), CPASAnimParm::FromEnum(1)); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + x4_state = pas::ELoopState::Loop; + } else if (!bc.GetCommandMgr().GetTargetVector().isZero()) { + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + } + } + break; + case pas::ELoopState::Loop: + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) { + if (PlayExitAnimation(bc, mgr)) { + x4_state = pas::ELoopState::End; + } else { + x4_state = pas::ELoopState::Invalid; + return pas::EAnimationState::Locomotion; + } + } else if (!bc.GetCommandMgr().GetTargetVector().isZero()) { + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + } + break; + case pas::ELoopState::End: + if (bc.IsAnimationOver()) { + x4_state = pas::ELoopState::Invalid; + return pas::EAnimationState::Locomotion; + } + break; + default: + break; + } + } + return st; } -bool CBSJump::CanShoot() const -{ - return x4_state == pas::EJumpState::AmbushJump || x4_state == pas::EJumpState::Loop; -} - -void CBSHurled::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCHurledCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)); - x4_state = pas::EHurledState(cmd->GetSkipLaunchState()); - zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetHitDirection()); - zeus::CRelAngle angle = std::atan2(localDir.y(), localDir.x()); - x8_knockAngle = angle.asDegrees(); - CPASAnimParmData parms(14, CPASAnimParm::FromInt32(-1), - CPASAnimParm::FromReal32(x8_knockAngle), - CPASAnimParm::FromEnum(s32(x4_state))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - const CPASAnimState* hurledState = bc.GetPASDatabase().GetAnimState(14); - xc_animSeries = hurledState->GetAnimParmData(best.second, 0).GetInt32Value(); - mgr.SendScriptMsg(&bc.GetOwner(), kInvalidUniqueId, EScriptObjectMessage::Falling); - mgr.SendScriptMsg(&bc.GetOwner(), kInvalidUniqueId, EScriptObjectMessage::Jumped); - if (!zeus::close_enough(cmd->GetLaunchVelocity(), zeus::CVector3f::skZero, 0.0001f)) - if (TCastToPtr act = bc.GetOwner()) - act->SetConstantForce(act->GetMass() * cmd->GetLaunchVelocity()); - float animAngle = zeus::degToRad(hurledState->GetAnimParmData(best.second, 1).GetReal32Value()); +void CBSGroundHit::Start(CBodyController& bc, CStateManager& mgr) { + const CBCKnockBackCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)); + zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetHitDirection()); + zeus::CRelAngle angle = std::atan2(localDir.y(), localDir.x()); + CPASAnimParmData parms(11, CPASAnimParm::FromEnum(s32(bc.GetFallState())), + CPASAnimParm::FromReal32(angle.asDegrees())); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + const CPASAnimState* groundHitState = bc.GetPASDatabase().GetAnimState(11); + if (!groundHitState->GetAnimParmData(best.second, 2).GetBoolValue()) { + float animAngle = zeus::degToRad(groundHitState->GetAnimParmData(best.second, 1).GetReal32Value()); zeus::CRelAngle delta1 = angle - animAngle; zeus::CRelAngle delta2 = animAngle - angle; float minAngle = std::min(float(delta1), float(delta2)); - x14_remTime = 0.15f * bc.GetAnimTimeRemaining(); float flippedAngle = (delta1 > M_PIF) ? -minAngle : minAngle; - x10_rotateSpeed = (x14_remTime > FLT_EPSILON) ? flippedAngle / x14_remTime : flippedAngle; - x18_curTime = 0.f; - x2c_24_needsRecover = false; + x8_remTime = 0.15f * bc.GetAnimTimeRemaining(); + x4_rotateSpeed = (x8_remTime > FLT_EPSILON) ? flippedAngle / x8_remTime : flippedAngle; + } else { + x8_remTime = 0.f; + x4_rotateSpeed = 0.f; + } + xc_fallState = pas::EFallState(groundHitState->GetAnimParmData(best.second, 3).GetEnumValue()); } -pas::EAnimationState CBSHurled::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) - return pas::EAnimationState::LieOnGround; - if (x18_curTime > 0.25f) - { - if (const CBCHurledCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled))) - { - const_cast(cmd)->SetSkipLaunchState(true); - return pas::EAnimationState::Hurled; - } - } - return pas::EAnimationState::Invalid; +pas::EAnimationState CBSGroundHit::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.IsAnimationOver()) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Die)) + return pas::EAnimationState::Death; + return pas::EAnimationState::LieOnGround; + } + return pas::EAnimationState::Invalid; } -void CBSHurled::Recover(CStateManager& mgr, CBodyController& bc, pas::EHurledState state) -{ - CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), - CPASAnimParm::FromReal32(x8_knockAngle), - CPASAnimParm::FromEnum(s32(state))); +pas::EAnimationState CBSGroundHit::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid && x8_remTime > 0.f) { + zeus::CQuaternion quat; + quat.rotateZ(x4_rotateSpeed * dt); + bc.SetDeltaRotation(quat); + x8_remTime -= dt; + } + return st; +} + +void CBSGroundHit::Shutdown(CBodyController& bc) { bc.SetFallState(xc_fallState); } + +void CBSGenerate::Start(CBodyController& bc, CStateManager& mgr) { + const CBCGenerateCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)); + s32 anim; + if (!cmd->UseSpecialAnimId()) { + CPASAnimParmData parms(12, CPASAnimParm::FromEnum(s32(cmd->GetGenerateType()))); std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > FLT_EPSILON) - { - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - x4_state = state; - if (TCastToPtr act = bc.GetOwner()) - act->SetMomentumWR(zeus::CVector3f::skZero); - } - x2c_24_needsRecover = false; -} + anim = best.second; + } else { + anim = cmd->GetSpecialAnimId(); + } -void CBSHurled::PlayStrikeWallAnimation(CBodyController& bc, CStateManager& mgr) -{ - CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), - CPASAnimParm::FromReal32(x8_knockAngle), - CPASAnimParm::FromEnum(3)); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > FLT_EPSILON) - { - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - x4_state = pas::EHurledState::StrikeWall; - } -} - -void CBSHurled::PlayLandAnimation(CBodyController& bc, CStateManager& mgr) -{ - CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), - CPASAnimParm::FromReal32(x8_knockAngle), - CPASAnimParm::FromEnum(s32(x4_state))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - const CPASAnimState* hurledState = bc.GetPASDatabase().GetAnimState(14); - bc.SetFallState(pas::EFallState(hurledState->GetAnimParmData(best.second, 3).GetEnumValue())); - if (TCastToPtr act = bc.GetOwner()) - mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); -} - -bool CBSHurled::ShouldStartStrikeWall(CBodyController& bc) const -{ - if (TCastToPtr ai = bc.GetOwner()) - { - if (ai->CanLongJump()) - if (!ai->IsOnGround()) - return true; - } - return false; -} - -bool CBSHurled::ShouldStartLand(float dt, CBodyController& bc) const -{ - bool ret = true; - if (TCastToPtr ai = bc.GetOwner()) - { - ret = false; - if (ai->IsOnGround()) - return true; - if (zeus::close_enough(ai->GetTranslation(), x1c_lastTranslation, 0.0001f) && - ai->GetVelocity().z() < 0.f) - { - x28_landedDur += dt; - if (x28_landedDur >= 0.25f) - ret = true; - } - else - { - x28_landedDur = 0.f; - } - x1c_lastTranslation = ai->GetTranslation(); - } - return ret; -} - -pas::EAnimationState CBSHurled::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - x18_curTime += dt; - if (x14_remTime > 0.f) - { - zeus::CQuaternion quat; - quat.rotateZ(x10_rotateSpeed * dt); - bc.SetDeltaRotation(quat); - x14_remTime -= dt; - } - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) - x2c_24_needsRecover = true; - switch (x4_state) - { - case pas::EHurledState::KnockIntoAir: - { - if (bc.IsAnimationOver()) - { - CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), - CPASAnimParm::FromReal32(x8_knockAngle), - CPASAnimParm::FromEnum(1)); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - x4_state = pas::EHurledState::KnockLoop; - x28_landedDur = 0.f; - } - break; - } - case pas::EHurledState::KnockLoop: - if (ShouldStartLand(dt, bc)) - { - x4_state = pas::EHurledState::KnockDown; - PlayLandAnimation(bc, mgr); - } - else if (ShouldStartStrikeWall(bc)) - { - PlayStrikeWallAnimation(bc, mgr); - if (TCastToPtr ai = bc.GetOwner()) - ai->SetVelocityWR(zeus::CVector3f::skDown * (2.f * dt * ai->GetGravityConstant())); - } - else if (x2c_24_needsRecover) - { - Recover(mgr, bc, pas::EHurledState::Six); - } - break; - case pas::EHurledState::StrikeWall: - if (bc.IsAnimationOver()) - { - x4_state = pas::EHurledState::StrikeWallFallLoop; - CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), - CPASAnimParm::FromReal32(x8_knockAngle), - CPASAnimParm::FromEnum(s32(x4_state))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - x28_landedDur = 0.f; - } - break; - case pas::EHurledState::StrikeWallFallLoop: - if (ShouldStartLand(dt, bc)) - { - x4_state = pas::EHurledState::OutOfStrikeWall; - PlayLandAnimation(bc, mgr); - } - else if (x2c_24_needsRecover) - { - Recover(mgr, bc, pas::EHurledState::Seven); - } - break; - case pas::EHurledState::Six: - case pas::EHurledState::Seven: - if (TCastToPtr act = bc.GetOwner()) - act->SetVelocityWR(act->GetVelocity() * std::pow(0.9, 60.0 * dt)); - if (bc.IsAnimationOver()) - { - x4_state = pas::EHurledState::Invalid; - return pas::EAnimationState::Locomotion; - } - break; - case pas::EHurledState::KnockDown: - case pas::EHurledState::OutOfStrikeWall: - if (bc.IsAnimationOver()) - { - x4_state = pas::EHurledState::Invalid; - if (bc.GetFallState() == pas::EFallState::Zero) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::LieOnGround; - } - break; - default: break; - } - } - return st; -} - -void CBSSlide::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCSlideCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Slide)); - zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetSlideDirection()); - float angle = std::atan2(localDir.y(), localDir.x()); - CPASAnimParmData parms(15, CPASAnimParm::FromEnum(s32(cmd->GetSlideType())), - CPASAnimParm::FromReal32(zeus::radToDeg(angle))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - float timeRem = bc.GetAnimTimeRemaining(); - if (timeRem > FLT_EPSILON) - { - const CPASAnimState* slideState = bc.GetPASDatabase().GetAnimState(15); - float animAngle = zeus::degToRad(slideState->GetAnimParmData(best.second, 1).GetReal32Value()); - float delta1 = zeus::CRelAngle(angle - animAngle); - float flippedAngle = (delta1 > M_PIF) ? delta1 - 2.f * M_PIF : delta1; - x4_rotateSpeed = flippedAngle / timeRem; - } - else - { - x4_rotateSpeed = 0.f; - } -} - -pas::EAnimationState CBSSlide::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.IsAnimationOver()) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSSlide::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid && x4_rotateSpeed != 0.f) - { - zeus::CQuaternion quat; - quat.rotateZ(x4_rotateSpeed * dt); - bc.SetDeltaRotation(quat); - } - return st; -} - -void CBSTaunt::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCTauntCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Taunt)); - CPASAnimParmData parms(16, CPASAnimParm::FromEnum(s32(cmd->GetTauntType()))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); -} - -pas::EAnimationState CBSTaunt::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) - return pas::EAnimationState::Locomotion; - if (bc.IsAnimationOver()) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSTaunt::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid && !bc.GetCommandMgr().GetTargetVector().isZero()) - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - return st; -} - -void CBSScripted::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCScriptedCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)); - x4_24_loopAnim = cmd->IsLooped(); - x4_25_timedLoop = cmd->GetUseLoopDuration(); - x8_remTime = cmd->GetLoopDuration(); - CAnimPlaybackParms playParms(cmd->GetAnimId(), -1, 1.f, true); - bc.SetCurrentAnimation(playParms, cmd->IsLooped(), false); -} - -pas::EAnimationState CBSScripted::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)) - return pas::EAnimationState::Scripted; - if (x4_24_loopAnim && bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) - return pas::EAnimationState::Locomotion; - if (bc.IsAnimationOver()) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; -} - -pas::EAnimationState CBSScripted::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - if (!bc.GetCommandMgr().GetTargetVector().isZero()) - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - if (x4_24_loopAnim && x4_25_timedLoop) - { - x8_remTime -= dt; - if (x8_remTime <= 0.f) - return pas::EAnimationState::Locomotion; - } - } - return st; -} - -void CBSCover::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCCoverCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Cover)); - x8_coverDirection = cmd->GetDirection(); - x4_state = pas::ECoverState::IntoCover; - CPASAnimParmData parms(19, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_coverDirection))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - zeus::CQuaternion orientDelta = - zeus::CQuaternion::lookAt(zeus::CVector3f::skForward, cmd->GetAlignDirection(), 2.f * M_PIF); - CAnimPlaybackParms playParms(best.second, &orientDelta, &cmd->GetTarget(), &bc.GetOwner().GetTransform(), + if (cmd->HasExitTargetPos()) { + CAnimPlaybackParms playParms(anim, nullptr, &cmd->GetExitTargetPos(), &bc.GetOwner().GetTransform(), &bc.GetOwner().GetModelData()->GetScale(), false); bc.SetCurrentAnimation(playParms, false, false); - xc_needsExit = false; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) - xc_needsExit = true; + } else { + CAnimPlaybackParms playParms(anim, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + } } -pas::EAnimationState CBSCover::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) - return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; +pas::EAnimationState CBSGenerate::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) + return pas::EAnimationState::Generate; + if (bc.IsAnimationOver() || bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; } -pas::EAnimationState CBSCover::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - switch (x4_state) - { - case pas::ECoverState::Lean: - case pas::ECoverState::IntoCover: - if (bc.IsAnimationOver()) - { - x4_state = pas::ECoverState::Cover; - CPASAnimParmData parms(19, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_coverDirection))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) - xc_needsExit = true; - break; - case pas::ECoverState::Cover: - if (!bc.GetCommandMgr().GetTargetVector().isZero()) - bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState) || xc_needsExit) - { - xc_needsExit = false; - x4_state = pas::ECoverState::OutOfCover; - CPASAnimParmData parms(19, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_coverDirection))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); - } - else if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LeanFromCover)) - { - x4_state = pas::ECoverState::Lean; - CPASAnimParmData parms(19, CPASAnimParm::FromEnum(s32(x4_state)), - CPASAnimParm::FromEnum(s32(x8_coverDirection))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); - } - break; - case pas::ECoverState::OutOfCover: - if (bc.IsAnimationOver()) - { - x4_state = pas::ECoverState::Invalid; - return pas::EAnimationState::Locomotion; - } - break; - default: break; - } - } - return st; +pas::EAnimationState CBSGenerate::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) + if (!bc.GetCommandMgr().GetTargetVector().isZero()) + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + return st; } -void CBSWallHang::Start(CBodyController& bc, CStateManager& mgr) -{ - const CBCWallHangCmd* cmd = - static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::WallHang)); - x4_state = pas::EWallHangState::IntoJump; - x8_wpId = cmd->GetTarget(); - x18_25_needsExit = false; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); +void CBSJump::Start(CBodyController& bc, CStateManager& mgr) { + const CBCJumpCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump)); + x8_jumpType = cmd->GetJumpType(); + xc_waypoint1 = cmd->GetJumpTarget(); + x24_waypoint2 = cmd->GetSecondJumpTarget(); + x30_25_wallJump = cmd->IsWallJump(); + x30_28_startInJumpLoop = cmd->StartInJumpLoop(); + x30_24_bodyForceSet = false; + x30_27_wallBounceComplete = false; + if (x30_25_wallJump) + x30_26_wallBounceRight = + (xc_waypoint1 - bc.GetOwner().GetTranslation()).cross(zeus::CVector3f::skUp).dot(x24_waypoint2 - xc_waypoint1) < + 0.f; + if (!cmd->StartInJumpLoop()) { + x4_state = pas::EJumpState::IntoJump; + CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType))); bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); + } else { + PlayJumpLoop(mgr, bc); + } } -pas::EAnimationState CBSWallHang::GetBodyStateTransition(float dt, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - return pas::EAnimationState::Invalid; +pas::EAnimationState CBSJump::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump) && bc.GetBodyType() == EBodyType::WallWalker) + return pas::EAnimationState::Jump; + return pas::EAnimationState::Invalid; } -void CBSWallHang::FixInPlace(CBodyController& bc) -{ - if (TCastToPtr ai = bc.GetOwner()) - { - ai->SetConstantForce(zeus::CVector3f::skZero); - ai->SetVelocityWR(zeus::CVector3f::skZero); +bool CBSJump::CheckForWallJump(CBodyController& bc, CStateManager& mgr) { + if (x30_25_wallJump && !x30_27_wallBounceComplete) { + if (TCastToPtr act = bc.GetOwner()) { + float distToWall = (xc_waypoint1 - act->GetTranslation()).magnitude(); + zeus::CAABox aabb = act->GetBoundingBox(); + float xExtent = (aabb.max.x() - aabb.min.x()) * 0.5f; + if (distToWall < 1.414f * xExtent || (act->CanLongJump() && distToWall < 3.f * xExtent)) { + x4_state = x30_26_wallBounceRight ? pas::EJumpState::WallBounceRight : pas::EJumpState::WallBounceLeft; + CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); + mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); + return true; + } } + } + return false; } -bool CBSWallHang::CheckForLand(CBodyController& bc, CStateManager& mgr) -{ - if (TCastToPtr ai = bc.GetOwner()) - { - if (ai->CanLongJump() || ai->IsOnGround()) - { - x4_state = pas::EWallHangState::DetachOutOfJump; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); - mgr.SendScriptMsg(ai.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); - return true; - } +void CBSJump::CheckForLand(CBodyController& bc, CStateManager& mgr) { + if (TCastToPtr act = bc.GetOwner()) { + if (act->CanLongJump() || act->IsOnGround()) { + x4_state = pas::EJumpState::OutOfJump; + CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); + mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); } - return false; + } } -bool CBSWallHang::CheckForWall(CBodyController& bc, CStateManager& mgr) -{ - if (TCastToPtr ai = bc.GetOwner()) - { - float magSq = 10.f; - TCastToPtr wp = mgr.ObjectById(x8_wpId); - if (wp) - magSq = (wp->GetTranslation() - ai->GetTranslation()).magSquared(); +void CBSJump::PlayJumpLoop(CStateManager& mgr, CBodyController& bc) { + CPASAnimParmData parms(13, CPASAnimParm::FromEnum(1), CPASAnimParm::FromEnum(s32(x8_jumpType))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > 99.f) { + x4_state = pas::EJumpState::AmbushJump; + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + } else { + x4_state = pas::EJumpState::Loop; + CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } - if (magSq < 1.f || ai->CanLongJump()) - { - x4_state = pas::EWallHangState::IntoWallHang; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - const zeus::CVector3f& target = wp ? wp->GetTranslation() : ai->GetTranslation(); - CAnimPlaybackParms playParms(best.second, nullptr, &target, &bc.GetOwner().GetTransform(), - &bc.GetOwner().GetModelData()->GetScale(), false); - bc.SetCurrentAnimation(playParms, false, false); - ai->SetVelocityWR(zeus::CVector3f::skZero); - ai->SetMomentumWR(zeus::CVector3f::skZero); - mgr.SendScriptMsg(ai.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); - return true; - } - } - return false; + if (TCastToPtr act = bc.GetOwner()) { + mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Falling); + mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Jumped); + x30_24_bodyForceSet = false; + x18_velocity = act->GetVelocity(); + } } -void CBSWallHang::SetLaunchVelocity(CBodyController& bc) -{ - if (!x18_24_launched) - { +pas::EAnimationState CBSJump::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + switch (x4_state) { + case pas::EJumpState::IntoJump: + if (bc.IsAnimationOver()) + PlayJumpLoop(mgr, bc); + break; + case pas::EJumpState::AmbushJump: + if (!x30_24_bodyForceSet) { if (TCastToPtr act = bc.GetOwner()) - { - act->SetVelocityWR(xc_launchVel); - act->SetConstantForce(xc_launchVel * act->GetMass()); + act->SetConstantForce(act->GetMass() * x18_velocity); + x30_24_bodyForceSet = true; + } + if (!bc.GetCommandMgr().GetTargetVector().isZero()) + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + if (bc.IsAnimationOver()) { + x4_state = pas::EJumpState::Loop; + CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } else { + if (!CheckForWallJump(bc, mgr)) + CheckForLand(bc, mgr); + } + break; + case pas::EJumpState::Loop: + if (!x30_24_bodyForceSet) { + if (TCastToPtr act = bc.GetOwner()) + act->SetConstantForce(act->GetMass() * x18_velocity); + x30_24_bodyForceSet = true; + } + if (!bc.GetCommandMgr().GetTargetVector().isZero()) + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + if (!CheckForWallJump(bc, mgr)) + CheckForLand(bc, mgr); + break; + case pas::EJumpState::WallBounceLeft: + case pas::EJumpState::WallBounceRight: + if (TCastToPtr act = bc.GetOwner()) { + act->Stop(); + act->SetMomentumWR(zeus::CVector3f::skZero); + } + if (bc.IsAnimationOver()) { + mgr.SendScriptMsg(&bc.GetOwner(), kInvalidUniqueId, EScriptObjectMessage::Falling); + x4_state = pas::EJumpState::Loop; + CPASAnimParmData parms(13, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_jumpType))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + x30_27_wallBounceComplete = true; + if (TCastToPtr act = bc.GetOwner()) { + zeus::CVector3f toFinal = x24_waypoint2 - act->GetTranslation(); + float tmp = std::sqrt(act->GetGravityConstant() / (2.f * toFinal.z())); + act->SetVelocityWR(zeus::CVector3f(tmp * toFinal.x(), tmp * toFinal.y(), 0.f)); } - x18_24_launched = true; - } -} - -pas::EAnimationState CBSWallHang::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - { - switch (x4_state) - { - case pas::EWallHangState::IntoJump: - { - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(1)); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > 0.f) - { - x4_state = pas::EWallHangState::JumpArc; - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - } - else - { - x4_state = pas::EWallHangState::JumpAirLoop; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - if (TCastToPtr act = bc.GetOwner()) - { - mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Jumped); - if (TCastToPtr wp = mgr.ObjectById(x8_wpId)) - { - zeus::CVector3f toWp = wp->GetTranslation() - act->GetTranslation(); - if (toWp.z() > 0.f) - { - float tmp = -act->GetMomentum().z() / act->GetMass(); - float tmp2 = std::sqrt(tmp * 2.f * toWp.z()); - tmp = 1.f / (tmp2 / tmp); - xc_launchVel = zeus::CVector3f(tmp * toWp.x(), tmp * toWp.y(), tmp2); - x18_24_launched = false; - } - } - } - break; - } - case pas::EWallHangState::JumpArc: - { - SetLaunchVelocity(bc); - if (bc.IsAnimationOver()) - { - x4_state = pas::EWallHangState::JumpAirLoop; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - else - { - CheckForWall(bc, mgr); - } - break; - } - case pas::EWallHangState::JumpAirLoop: - { - SetLaunchVelocity(bc); - if (!CheckForWall(bc, mgr)) - CheckForLand(bc, mgr); - break; - } - case pas::EWallHangState::IntoWallHang: - { - if (bc.IsAnimationOver()) - { - x4_state = pas::EWallHangState::WallHang; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - else if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) - { - x18_25_needsExit = true; - } - break; - } - case pas::EWallHangState::WallHang: - { - if (!bc.GetCommandMgr().GetTargetVector().isZero()) - { - if (TCastToPtr wp = mgr.ObjectById(x8_wpId)) - { - if (TCastToPtr act = bc.GetOwner()) - { - zeus::CVector3f lookDir = bc.GetCommandMgr().GetTargetVector().normalized(); - float actorDotWp = act->GetTransform().basis[1].dot(wp->GetTransform().basis[1]); - float lookDotWp = lookDir.dot(wp->GetTransform().basis[1]); - if (actorDotWp < -0.5f || lookDotWp > 0.5f) - bc.FaceDirection(lookDir, dt); - } - } - } - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState) || x18_25_needsExit) - { - x4_state = pas::EWallHangState::OutOfWallHang; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); - bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); - } - FixInPlace(bc); - break; - } - case pas::EWallHangState::Five: - { - if (bc.IsAnimationOver()) - { - x4_state = pas::EWallHangState::WallHang; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - FixInPlace(bc); - break; - } - case pas::EWallHangState::OutOfWallHang: - { - if (bc.IsAnimationOver()) - { - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(7)); - std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (best.first > 0.f) - { - x4_state = pas::EWallHangState::OutOfWallHangTurn; - CAnimPlaybackParms playParms(best.second, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, false, false); - } - else - { - x4_state = pas::EWallHangState::DetachJumpLoop; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - if (TCastToPtr act = bc.GetOwner()) - { - mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Jumped); - x18_24_launched = false; - if (TCastToPtr wp = mgr.ObjectById(x8_wpId)) - { - xc_launchVel = 15.f * wp->GetTransform().basis[1]; - xc_launchVel.z() = 5.f; - } - else - { - xc_launchVel = -15.f * act->GetTransform().basis[1]; - } - act->SetAngularMomentum(zeus::CAxisAngle::sIdentity); - } - } - break; - } - case pas::EWallHangState::OutOfWallHangTurn: - { - SetLaunchVelocity(bc); - if (bc.IsAnimationOver()) - { - x4_state = pas::EWallHangState::DetachJumpLoop; - CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); - bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); - } - else - { - CheckForLand(bc, mgr); - } - break; - } - case pas::EWallHangState::DetachJumpLoop: - { - SetLaunchVelocity(bc); - CheckForLand(bc, mgr); - break; - } - case pas::EWallHangState::DetachOutOfJump: - { - if (bc.IsAnimationOver()) - { - x4_state = pas::EWallHangState::Invalid; - return pas::EAnimationState::Locomotion; - } - break; - } - default: break; - } - } - return st; -} - -bool CBSWallHang::IsInAir(const CBodyController& bc) const -{ - switch (x4_state) - { - case pas::EWallHangState::JumpArc: - case pas::EWallHangState::JumpAirLoop: - case pas::EWallHangState::OutOfWallHangTurn: - case pas::EWallHangState::DetachJumpLoop: - return true; - default: - return false; - } -} - -bool CBSWallHang::ApplyAnimationDeltas() const -{ - switch (x4_state) - { - case pas::EWallHangState::IntoJump: - case pas::EWallHangState::IntoWallHang: - case pas::EWallHangState::WallHang: - case pas::EWallHangState::Five: - case pas::EWallHangState::OutOfWallHang: - case pas::EWallHangState::DetachOutOfJump: - return true; - default: - return false; - } -} - -bool CBSWallHang::ApplyHeadTracking() const -{ - switch (x4_state) - { - case pas::EWallHangState::WallHang: - case pas::EWallHangState::Five: - return true; - default: - return false; - } -} - -bool CBSWallHang::ApplyGravity() const -{ - switch (x4_state) - { - case pas::EWallHangState::WallHang: - case pas::EWallHangState::IntoWallHang: - case pas::EWallHangState::OutOfWallHang: - return false; - default: - return true; - } -} - -float CBSLocomotion::GetStartVelocityMagnitude(CBodyController& bc) -{ - if (TCastToPtr act = bc.GetOwner()) - { - float maxSpeed = bc.GetBodyStateInfo().GetMaxSpeed(); - float ret = 0.f; - if (maxSpeed > 0.f) - ret = act->GetVelocity().magnitude() / maxSpeed; - return std::min(1.f, ret); - } - return 0.f; -} - -void CBSLocomotion::ReStartBodyState(CBodyController& bc, bool maintainVel) -{ - UpdateLocomotionAnimation(0.f, maintainVel ? GetStartVelocityMagnitude(bc) : 0.f, bc, true); -} - -float CBSLocomotion::ComputeWeightPercentage(const std::pair& a, - const std::pair& b, float f) const -{ - float range = b.second - a.second; - if (range > FLT_EPSILON) - return std::max(0.f, std::min(1.f, (f - a.second) / range)); - return 0.f; -} - -void CBSLocomotion::Start(CBodyController& bc, CStateManager& mgr) -{ - x4_locomotionType = bc.GetLocomotionType(); - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MaintainVelocity)) - ReStartBodyState(bc, true); - else - ReStartBodyState(bc, false); -} - -pas::EAnimationState CBSLocomotion::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - pas::EAnimationState st = GetBodyStateTransition(dt, bc); - if (st == pas::EAnimationState::Invalid) - UpdateLocomotionAnimation(dt, ApplyLocomotionPhysics(dt, bc), bc, false); - return st; -} - -void CBSLocomotion::Shutdown(CBodyController& bc) -{ - bc.MultiplyPlaybackRate(1.f); -} - -float CBSLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) -{ - if (TCastToPtr act = bc.GetOwner()) - { - zeus::CVector3f vec = - (zeus::close_enough(bc.GetCommandMgr().GetFaceVector(), zeus::CVector3f::skZero, 0.0001f)) ? - bc.GetCommandMgr().GetMoveVector() : bc.GetCommandMgr().GetFaceVector(); - if (vec.canBeNormalized()) - { - if (IsPitchable()) - { - zeus::CVector3f tmp = vec; - tmp.z() = 0.f; - zeus::CVector3f lookVec = act->GetTransform().basis[1]; - lookVec.z() = 0.f; - lookVec.normalize(); - bc.FaceDirection3D(tmp, lookVec, dt); - zeus::CVector3f lookVec2 = act->GetTransform().basis[1]; - lookVec2.z() = float(vec.z()); - lookVec2.normalize(); - if (!zeus::close_enough(lookVec, lookVec2, 0.0001f)) - { - zeus::CRelAngle pitchAngle = std::min(bc.GetBodyStateInfo().GetMaximumPitch(), - zeus::CVector3f::getAngleDiff(vec, tmp)); - lookVec2 = zeus::CVector3f::slerp(lookVec, lookVec2, pitchAngle); - } - bc.FaceDirection3D(lookVec2, act->GetTransform().basis[1], dt); - zeus::CVector3f lookVec3 = act->GetTransform().basis[1]; - lookVec3.z() = 0.f; - bc.FaceDirection3D(lookVec3, act->GetTransform().basis[1], dt); - } - else - { - bc.FaceDirection(vec.normalized(), dt); - } - } - return std::min(1.f, bc.GetCommandMgr().GetMoveVector().magnitude()); - } - return 0.f; -} - -pas::EAnimationState CBSLocomotion::GetBodyStateTransition(float, CBodyController& bc) -{ - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) - return pas::EAnimationState::Hurled; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) - return pas::EAnimationState::Fall; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) - return pas::EAnimationState::KnockBack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) - { - bc.GetCommandMgr().ClearLocomotionCmds(); - return pas::EAnimationState::Invalid; - } - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Slide)) - return pas::EAnimationState::Slide; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) - return pas::EAnimationState::Generate; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) - return pas::EAnimationState::MeleeAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) - return pas::EAnimationState::ProjectileAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) - return pas::EAnimationState::LoopAttack; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopReaction)) - return pas::EAnimationState::LoopReaction; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump)) - return pas::EAnimationState::Jump; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Taunt)) - return pas::EAnimationState::Taunt; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)) - return pas::EAnimationState::Step; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Cover)) - return pas::EAnimationState::Cover; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::WallHang)) - return pas::EAnimationState::WallHang; - if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)) - return pas::EAnimationState::Scripted; - if (bc.GetCommandMgr().GetMoveVector().isZero()) - { - if (!bc.GetCommandMgr().GetFaceVector().isZero()) - if (!IsMoving()) - return pas::EAnimationState::Turn; - } - if (x4_locomotionType != bc.GetLocomotionType()) + } + break; + case pas::EJumpState::OutOfJump: + if (bc.IsAnimationOver()) { + x4_state = pas::EJumpState::Invalid; return pas::EAnimationState::Locomotion; - return pas::EAnimationState::Invalid; -} - -CBSBiPedLocomotion::CBSBiPedLocomotion(CActor& actor) -{ - const CPASDatabase& pasDatabase = - actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); - for (int i=0 ; i<14 ; ++i) - { - x8_anims.emplace_back(); - rstl::reserved_vector, 8>& innerVec = x8_anims.back(); - for (int j=0 ; j<8 ; ++j) - { - CPASAnimParmData parms(5, CPASAnimParm::FromEnum(j), CPASAnimParm::FromEnum(i)); - std::pair best = pasDatabase.FindBestAnimation(parms, -1); - float avgVel = 0.f; - if (best.second != -1) - { - avgVel = actor.GetAverageAnimVelocity(best.second); - if (j == 0) - avgVel = 0.f; - } - innerVec.push_back({best.second, avgVel}); - } + } + break; + default: + break; } + } + return st; } -void CBSBiPedLocomotion::Start(CBodyController& bc, CStateManager& mgr) -{ - x3c8_primeTime = 0.f; - CBSLocomotion::Start(bc, mgr); -} - -pas::EAnimationState CBSBiPedLocomotion::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) -{ - if (x3c8_primeTime < 0.2f) - x3c8_primeTime += dt; - return CBSLocomotion::UpdateBody(dt, bc, mgr); -} - -float CBSBiPedLocomotion::GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const -{ - return GetLocoAnimation(type, anim).second; -} - -float CBSBiPedLocomotion::UpdateRun(float vel, CBodyController& bc, pas::ELocomotionAnim anim) -{ - const std::pair& walk = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Walk); - const std::pair& run = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Run); - float perc = ComputeWeightPercentage(walk, run, vel); - - if (perc < 0.4f) - { - float rate = walk.second > 0.f ? vel / walk.second : 1.f; - if (anim != pas::ELocomotionAnim::Walk && bc.GetCurrentAnimId() != walk.first) - { - CAnimPlaybackParms playParms(walk.first, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, true, false); - x3c8_primeTime = 0.f; - } - bc.MultiplyPlaybackRate(rate); - x3c4_anim = pas::ELocomotionAnim::Walk; - return rate; - } - else - { - float rate = std::min(1.f, vel / run.second); - if (anim != pas::ELocomotionAnim::Run && bc.GetCurrentAnimId() != run.first) - { - CAnimPlaybackParms playParms(run.first, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, true, false); - x3c8_primeTime = 0.f; - } - bc.MultiplyPlaybackRate(rate); - x3c4_anim = pas::ELocomotionAnim::Run; - return rate; - } -} - -float CBSBiPedLocomotion::UpdateWalk(float vel, CBodyController& bc, pas::ELocomotionAnim anim) -{ - if (anim != pas::ELocomotionAnim::Walk) - { - const std::pair& walk = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Walk); - if (bc.GetCurrentAnimId() != walk.first) - { - CAnimPlaybackParms playParms(walk.first, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, true, false); - x3c8_primeTime = 0.f; - } - x3c4_anim = pas::ELocomotionAnim::Walk; - } - - const std::pair& idle = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Idle); - const std::pair& walk = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Walk); - float perc = std::max(0.5f, ComputeWeightPercentage(idle, walk, vel)); - bc.MultiplyPlaybackRate(perc); - return perc; -} - -static const pas::ELocomotionAnim Strafes[] = -{ - pas::ELocomotionAnim::StrafeRight, - pas::ELocomotionAnim::StrafeLeft, - pas::ELocomotionAnim::Walk, - pas::ELocomotionAnim::BackUp, - pas::ELocomotionAnim::StrafeUp, - pas::ELocomotionAnim::StrafeDown -}; - -float CBSBiPedLocomotion::UpdateStrafe(float vel, CBodyController& bc, pas::ELocomotionAnim anim) -{ - if (TCastToPtr act = bc.GetOwner()) - { - zeus::CVector3f localVec = act->GetTransform().transposeRotate(bc.GetCommandMgr().GetMoveVector()); - zeus::CVector3f localVecSq = localVec * localVec; - int maxComp = 0; - for (int i=0 ; i<3 ; ++i) - if (localVecSq[i] >= localVecSq[maxComp]) - maxComp = i; - int strafeKey = maxComp * 2 + localVec[maxComp] > 0.f ? 0 : 1; - pas::ELocomotionAnim strafeType = Strafes[strafeKey]; - float rate = vel * GetLocomotionSpeed(x4_locomotionType, strafeType); - if (anim != strafeType) - { - const std::pair& strafe = - GetLocoAnimation(x4_locomotionType, strafeType); - if (bc.GetCurrentAnimId() != strafe.first) - { - CAnimPlaybackParms playParms(strafe.first, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, true, false); - x3c8_primeTime = 0.f; - } - x3c4_anim = strafeType; - } - const std::pair& idle = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Idle); - const std::pair& strafe = GetLocoAnimation(x4_locomotionType, strafeType); - float perc = std::max(0.5f, ComputeWeightPercentage(idle, strafe, rate)); - bc.MultiplyPlaybackRate(perc); - } - return 1.f; -} - -float CBSBiPedLocomotion::UpdateLocomotionAnimation(float dt, float velMag, - CBodyController& bc, bool init) -{ - float ret = 1.f; - if (init || x3c8_primeTime >= 0.2f) - { - pas::ELocomotionAnim anim = init ? pas::ELocomotionAnim::Invalid : x3c4_anim; - float maxSpeed = velMag * GetLocomotionSpeed(x4_locomotionType, pas::ELocomotionAnim::Run); - if (IsStrafing(bc) && velMag >= 0.01f) - return UpdateStrafe(velMag, bc, anim); - - if (maxSpeed < 0.01f) - { - if (anim != pas::ELocomotionAnim::Idle || init) - { - if (!bc.GetBodyStateInfo().GetLocoAnimChangeAtEndOfAnimOnly() || - bc.GetAnimTimeRemaining() <= dt || init) - { - const std::pair& best = - GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Idle); - if (bc.GetCurrentAnimId() != best.first) - { - CAnimPlaybackParms playParms(best.first, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, true, false); - x3c8_primeTime = 0.f; - } - x3c4_anim = pas::ELocomotionAnim::Idle; - } - } - } - else - { - const std::pair& best = - GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Walk); - if (maxSpeed < best.second) - return UpdateWalk(maxSpeed, bc, anim); - return UpdateRun(maxSpeed, bc, anim); - } - } - return ret; -} - -bool CBSBiPedLocomotion::IsStrafing(const CBodyController& bc) const -{ - if (!zeus::close_enough(bc.GetCommandMgr().GetMoveVector(), zeus::CVector3f::skZero, 0.0001f)) - if (!zeus::close_enough(bc.GetCommandMgr().GetFaceVector(), zeus::CVector3f::skZero, 0.0001f)) - return true; +bool CBSJump::ApplyAnimationDeltas() const { + if (x4_state == pas::EJumpState::AmbushJump || x4_state == pas::EJumpState::Loop) return false; + return true; +} + +bool CBSJump::IsInAir(const CBodyController& bc) const { + return x4_state == pas::EJumpState::AmbushJump || x4_state == pas::EJumpState::Loop; +} + +bool CBSJump::CanShoot() const { return x4_state == pas::EJumpState::AmbushJump || x4_state == pas::EJumpState::Loop; } + +void CBSHurled::Start(CBodyController& bc, CStateManager& mgr) { + const CBCHurledCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)); + x4_state = pas::EHurledState(cmd->GetSkipLaunchState()); + zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetHitDirection()); + zeus::CRelAngle angle = std::atan2(localDir.y(), localDir.x()); + x8_knockAngle = angle.asDegrees(); + CPASAnimParmData parms(14, CPASAnimParm::FromInt32(-1), CPASAnimParm::FromReal32(x8_knockAngle), + CPASAnimParm::FromEnum(s32(x4_state))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + const CPASAnimState* hurledState = bc.GetPASDatabase().GetAnimState(14); + xc_animSeries = hurledState->GetAnimParmData(best.second, 0).GetInt32Value(); + mgr.SendScriptMsg(&bc.GetOwner(), kInvalidUniqueId, EScriptObjectMessage::Falling); + mgr.SendScriptMsg(&bc.GetOwner(), kInvalidUniqueId, EScriptObjectMessage::Jumped); + if (!zeus::close_enough(cmd->GetLaunchVelocity(), zeus::CVector3f::skZero, 0.0001f)) + if (TCastToPtr act = bc.GetOwner()) + act->SetConstantForce(act->GetMass() * cmd->GetLaunchVelocity()); + float animAngle = zeus::degToRad(hurledState->GetAnimParmData(best.second, 1).GetReal32Value()); + zeus::CRelAngle delta1 = angle - animAngle; + zeus::CRelAngle delta2 = animAngle - angle; + float minAngle = std::min(float(delta1), float(delta2)); + x14_remTime = 0.15f * bc.GetAnimTimeRemaining(); + float flippedAngle = (delta1 > M_PIF) ? -minAngle : minAngle; + x10_rotateSpeed = (x14_remTime > FLT_EPSILON) ? flippedAngle / x14_remTime : flippedAngle; + x18_curTime = 0.f; + x2c_24_needsRecover = false; +} + +pas::EAnimationState CBSHurled::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::NextState)) + return pas::EAnimationState::LieOnGround; + if (x18_curTime > 0.25f) { + if (const CBCHurledCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled))) { + const_cast(cmd)->SetSkipLaunchState(true); + return pas::EAnimationState::Hurled; + } + } + return pas::EAnimationState::Invalid; +} + +void CBSHurled::Recover(CStateManager& mgr, CBodyController& bc, pas::EHurledState state) { + CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), CPASAnimParm::FromReal32(x8_knockAngle), + CPASAnimParm::FromEnum(s32(state))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > FLT_EPSILON) { + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + x4_state = state; + if (TCastToPtr act = bc.GetOwner()) + act->SetMomentumWR(zeus::CVector3f::skZero); + } + x2c_24_needsRecover = false; +} + +void CBSHurled::PlayStrikeWallAnimation(CBodyController& bc, CStateManager& mgr) { + CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), CPASAnimParm::FromReal32(x8_knockAngle), + CPASAnimParm::FromEnum(3)); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > FLT_EPSILON) { + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + x4_state = pas::EHurledState::StrikeWall; + } +} + +void CBSHurled::PlayLandAnimation(CBodyController& bc, CStateManager& mgr) { + CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), CPASAnimParm::FromReal32(x8_knockAngle), + CPASAnimParm::FromEnum(s32(x4_state))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + const CPASAnimState* hurledState = bc.GetPASDatabase().GetAnimState(14); + bc.SetFallState(pas::EFallState(hurledState->GetAnimParmData(best.second, 3).GetEnumValue())); + if (TCastToPtr act = bc.GetOwner()) + mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); +} + +bool CBSHurled::ShouldStartStrikeWall(CBodyController& bc) const { + if (TCastToPtr ai = bc.GetOwner()) { + if (ai->CanLongJump()) + if (!ai->IsOnGround()) + return true; + } + return false; +} + +bool CBSHurled::ShouldStartLand(float dt, CBodyController& bc) const { + bool ret = true; + if (TCastToPtr ai = bc.GetOwner()) { + ret = false; + if (ai->IsOnGround()) + return true; + if (zeus::close_enough(ai->GetTranslation(), x1c_lastTranslation, 0.0001f) && ai->GetVelocity().z() < 0.f) { + x28_landedDur += dt; + if (x28_landedDur >= 0.25f) + ret = true; + } else { + x28_landedDur = 0.f; + } + x1c_lastTranslation = ai->GetTranslation(); + } + return ret; +} + +pas::EAnimationState CBSHurled::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + x18_curTime += dt; + if (x14_remTime > 0.f) { + zeus::CQuaternion quat; + quat.rotateZ(x10_rotateSpeed * dt); + bc.SetDeltaRotation(quat); + x14_remTime -= dt; + } + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) + x2c_24_needsRecover = true; + switch (x4_state) { + case pas::EHurledState::KnockIntoAir: { + if (bc.IsAnimationOver()) { + CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), CPASAnimParm::FromReal32(x8_knockAngle), + CPASAnimParm::FromEnum(1)); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + x4_state = pas::EHurledState::KnockLoop; + x28_landedDur = 0.f; + } + break; + } + case pas::EHurledState::KnockLoop: + if (ShouldStartLand(dt, bc)) { + x4_state = pas::EHurledState::KnockDown; + PlayLandAnimation(bc, mgr); + } else if (ShouldStartStrikeWall(bc)) { + PlayStrikeWallAnimation(bc, mgr); + if (TCastToPtr ai = bc.GetOwner()) + ai->SetVelocityWR(zeus::CVector3f::skDown * (2.f * dt * ai->GetGravityConstant())); + } else if (x2c_24_needsRecover) { + Recover(mgr, bc, pas::EHurledState::Six); + } + break; + case pas::EHurledState::StrikeWall: + if (bc.IsAnimationOver()) { + x4_state = pas::EHurledState::StrikeWallFallLoop; + CPASAnimParmData parms(14, CPASAnimParm::FromInt32(xc_animSeries), CPASAnimParm::FromReal32(x8_knockAngle), + CPASAnimParm::FromEnum(s32(x4_state))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + x28_landedDur = 0.f; + } + break; + case pas::EHurledState::StrikeWallFallLoop: + if (ShouldStartLand(dt, bc)) { + x4_state = pas::EHurledState::OutOfStrikeWall; + PlayLandAnimation(bc, mgr); + } else if (x2c_24_needsRecover) { + Recover(mgr, bc, pas::EHurledState::Seven); + } + break; + case pas::EHurledState::Six: + case pas::EHurledState::Seven: + if (TCastToPtr act = bc.GetOwner()) + act->SetVelocityWR(act->GetVelocity() * std::pow(0.9, 60.0 * dt)); + if (bc.IsAnimationOver()) { + x4_state = pas::EHurledState::Invalid; + return pas::EAnimationState::Locomotion; + } + break; + case pas::EHurledState::KnockDown: + case pas::EHurledState::OutOfStrikeWall: + if (bc.IsAnimationOver()) { + x4_state = pas::EHurledState::Invalid; + if (bc.GetFallState() == pas::EFallState::Zero) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::LieOnGround; + } + break; + default: + break; + } + } + return st; +} + +void CBSSlide::Start(CBodyController& bc, CStateManager& mgr) { + const CBCSlideCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Slide)); + zeus::CVector3f localDir = bc.GetOwner().GetTransform().transposeRotate(cmd->GetSlideDirection()); + float angle = std::atan2(localDir.y(), localDir.x()); + CPASAnimParmData parms(15, CPASAnimParm::FromEnum(s32(cmd->GetSlideType())), + CPASAnimParm::FromReal32(zeus::radToDeg(angle))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + float timeRem = bc.GetAnimTimeRemaining(); + if (timeRem > FLT_EPSILON) { + const CPASAnimState* slideState = bc.GetPASDatabase().GetAnimState(15); + float animAngle = zeus::degToRad(slideState->GetAnimParmData(best.second, 1).GetReal32Value()); + float delta1 = zeus::CRelAngle(angle - animAngle); + float flippedAngle = (delta1 > M_PIF) ? delta1 - 2.f * M_PIF : delta1; + x4_rotateSpeed = flippedAngle / timeRem; + } else { + x4_rotateSpeed = 0.f; + } +} + +pas::EAnimationState CBSSlide::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.IsAnimationOver()) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSSlide::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid && x4_rotateSpeed != 0.f) { + zeus::CQuaternion quat; + quat.rotateZ(x4_rotateSpeed * dt); + bc.SetDeltaRotation(quat); + } + return st; +} + +void CBSTaunt::Start(CBodyController& bc, CStateManager& mgr) { + const CBCTauntCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Taunt)); + CPASAnimParmData parms(16, CPASAnimParm::FromEnum(s32(cmd->GetTauntType()))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); +} + +pas::EAnimationState CBSTaunt::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) + return pas::EAnimationState::Locomotion; + if (bc.IsAnimationOver()) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSTaunt::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid && !bc.GetCommandMgr().GetTargetVector().isZero()) + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + return st; +} + +void CBSScripted::Start(CBodyController& bc, CStateManager& mgr) { + const CBCScriptedCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)); + x4_24_loopAnim = cmd->IsLooped(); + x4_25_timedLoop = cmd->GetUseLoopDuration(); + x8_remTime = cmd->GetLoopDuration(); + CAnimPlaybackParms playParms(cmd->GetAnimId(), -1, 1.f, true); + bc.SetCurrentAnimation(playParms, cmd->IsLooped(), false); +} + +pas::EAnimationState CBSScripted::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)) + return pas::EAnimationState::Scripted; + if (x4_24_loopAnim && bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) + return pas::EAnimationState::Locomotion; + if (bc.IsAnimationOver()) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSScripted::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + if (!bc.GetCommandMgr().GetTargetVector().isZero()) + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + if (x4_24_loopAnim && x4_25_timedLoop) { + x8_remTime -= dt; + if (x8_remTime <= 0.f) + return pas::EAnimationState::Locomotion; + } + } + return st; +} + +void CBSCover::Start(CBodyController& bc, CStateManager& mgr) { + const CBCCoverCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::Cover)); + x8_coverDirection = cmd->GetDirection(); + x4_state = pas::ECoverState::IntoCover; + CPASAnimParmData parms(19, CPASAnimParm::FromEnum(s32(x4_state)), CPASAnimParm::FromEnum(s32(x8_coverDirection))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + zeus::CQuaternion orientDelta = + zeus::CQuaternion::lookAt(zeus::CVector3f::skForward, cmd->GetAlignDirection(), 2.f * M_PIF); + CAnimPlaybackParms playParms(best.second, &orientDelta, &cmd->GetTarget(), &bc.GetOwner().GetTransform(), + &bc.GetOwner().GetModelData()->GetScale(), false); + bc.SetCurrentAnimation(playParms, false, false); + xc_needsExit = false; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) + xc_needsExit = true; +} + +pas::EAnimationState CBSCover::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; +} + +pas::EAnimationState CBSCover::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + switch (x4_state) { + case pas::ECoverState::Lean: + case pas::ECoverState::IntoCover: + if (bc.IsAnimationOver()) { + x4_state = pas::ECoverState::Cover; + CPASAnimParmData parms(19, CPASAnimParm::FromEnum(s32(x4_state)), + CPASAnimParm::FromEnum(s32(x8_coverDirection))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) + xc_needsExit = true; + break; + case pas::ECoverState::Cover: + if (!bc.GetCommandMgr().GetTargetVector().isZero()) + bc.FaceDirection(bc.GetCommandMgr().GetTargetVector(), dt); + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState) || xc_needsExit) { + xc_needsExit = false; + x4_state = pas::ECoverState::OutOfCover; + CPASAnimParmData parms(19, CPASAnimParm::FromEnum(s32(x4_state)), + CPASAnimParm::FromEnum(s32(x8_coverDirection))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); + } else if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LeanFromCover)) { + x4_state = pas::ECoverState::Lean; + CPASAnimParmData parms(19, CPASAnimParm::FromEnum(s32(x4_state)), + CPASAnimParm::FromEnum(s32(x8_coverDirection))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); + } + break; + case pas::ECoverState::OutOfCover: + if (bc.IsAnimationOver()) { + x4_state = pas::ECoverState::Invalid; + return pas::EAnimationState::Locomotion; + } + break; + default: + break; + } + } + return st; +} + +void CBSWallHang::Start(CBodyController& bc, CStateManager& mgr) { + const CBCWallHangCmd* cmd = static_cast(bc.GetCommandMgr().GetCmd(EBodyStateCmd::WallHang)); + x4_state = pas::EWallHangState::IntoJump; + x8_wpId = cmd->GetTarget(); + x18_25_needsExit = false; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); +} + +pas::EAnimationState CBSWallHang::GetBodyStateTransition(float dt, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + return pas::EAnimationState::Invalid; +} + +void CBSWallHang::FixInPlace(CBodyController& bc) { + if (TCastToPtr ai = bc.GetOwner()) { + ai->SetConstantForce(zeus::CVector3f::skZero); + ai->SetVelocityWR(zeus::CVector3f::skZero); + } +} + +bool CBSWallHang::CheckForLand(CBodyController& bc, CStateManager& mgr) { + if (TCastToPtr ai = bc.GetOwner()) { + if (ai->CanLongJump() || ai->IsOnGround()) { + x4_state = pas::EWallHangState::DetachOutOfJump; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); + mgr.SendScriptMsg(ai.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); + return true; + } + } + return false; +} + +bool CBSWallHang::CheckForWall(CBodyController& bc, CStateManager& mgr) { + if (TCastToPtr ai = bc.GetOwner()) { + float magSq = 10.f; + TCastToPtr wp = mgr.ObjectById(x8_wpId); + if (wp) + magSq = (wp->GetTranslation() - ai->GetTranslation()).magSquared(); + + if (magSq < 1.f || ai->CanLongJump()) { + x4_state = pas::EWallHangState::IntoWallHang; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + const zeus::CVector3f& target = wp ? wp->GetTranslation() : ai->GetTranslation(); + CAnimPlaybackParms playParms(best.second, nullptr, &target, &bc.GetOwner().GetTransform(), + &bc.GetOwner().GetModelData()->GetScale(), false); + bc.SetCurrentAnimation(playParms, false, false); + ai->SetVelocityWR(zeus::CVector3f::skZero); + ai->SetMomentumWR(zeus::CVector3f::skZero); + mgr.SendScriptMsg(ai.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::OnFloor); + return true; + } + } + return false; +} + +void CBSWallHang::SetLaunchVelocity(CBodyController& bc) { + if (!x18_24_launched) { + if (TCastToPtr act = bc.GetOwner()) { + act->SetVelocityWR(xc_launchVel); + act->SetConstantForce(xc_launchVel * act->GetMass()); + } + x18_24_launched = true; + } +} + +pas::EAnimationState CBSWallHang::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) { + switch (x4_state) { + case pas::EWallHangState::IntoJump: { + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(1)); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > 0.f) { + x4_state = pas::EWallHangState::JumpArc; + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + } else { + x4_state = pas::EWallHangState::JumpAirLoop; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } + if (TCastToPtr act = bc.GetOwner()) { + mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Jumped); + if (TCastToPtr wp = mgr.ObjectById(x8_wpId)) { + zeus::CVector3f toWp = wp->GetTranslation() - act->GetTranslation(); + if (toWp.z() > 0.f) { + float tmp = -act->GetMomentum().z() / act->GetMass(); + float tmp2 = std::sqrt(tmp * 2.f * toWp.z()); + tmp = 1.f / (tmp2 / tmp); + xc_launchVel = zeus::CVector3f(tmp * toWp.x(), tmp * toWp.y(), tmp2); + x18_24_launched = false; + } + } + } + break; + } + case pas::EWallHangState::JumpArc: { + SetLaunchVelocity(bc); + if (bc.IsAnimationOver()) { + x4_state = pas::EWallHangState::JumpAirLoop; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } else { + CheckForWall(bc, mgr); + } + break; + } + case pas::EWallHangState::JumpAirLoop: { + SetLaunchVelocity(bc); + if (!CheckForWall(bc, mgr)) + CheckForLand(bc, mgr); + break; + } + case pas::EWallHangState::IntoWallHang: { + if (bc.IsAnimationOver()) { + x4_state = pas::EWallHangState::WallHang; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } else if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState)) { + x18_25_needsExit = true; + } + break; + } + case pas::EWallHangState::WallHang: { + if (!bc.GetCommandMgr().GetTargetVector().isZero()) { + if (TCastToPtr wp = mgr.ObjectById(x8_wpId)) { + if (TCastToPtr act = bc.GetOwner()) { + zeus::CVector3f lookDir = bc.GetCommandMgr().GetTargetVector().normalized(); + float actorDotWp = act->GetTransform().basis[1].dot(wp->GetTransform().basis[1]); + float lookDotWp = lookDir.dot(wp->GetTransform().basis[1]); + if (actorDotWp < -0.5f || lookDotWp > 0.5f) + bc.FaceDirection(lookDir, dt); + } + } + } + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ExitState) || x18_25_needsExit) { + x4_state = pas::EWallHangState::OutOfWallHang; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + bc.PlayBestAnimation(parms, *mgr.GetActiveRandom()); + } + FixInPlace(bc); + break; + } + case pas::EWallHangState::Five: { + if (bc.IsAnimationOver()) { + x4_state = pas::EWallHangState::WallHang; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } + FixInPlace(bc); + break; + } + case pas::EWallHangState::OutOfWallHang: { + if (bc.IsAnimationOver()) { + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(7)); + std::pair best = bc.GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (best.first > 0.f) { + x4_state = pas::EWallHangState::OutOfWallHangTurn; + CAnimPlaybackParms playParms(best.second, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, false, false); + } else { + x4_state = pas::EWallHangState::DetachJumpLoop; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } + if (TCastToPtr act = bc.GetOwner()) { + mgr.SendScriptMsg(act.GetPtr(), kInvalidUniqueId, EScriptObjectMessage::Jumped); + x18_24_launched = false; + if (TCastToPtr wp = mgr.ObjectById(x8_wpId)) { + xc_launchVel = 15.f * wp->GetTransform().basis[1]; + xc_launchVel.z() = 5.f; + } else { + xc_launchVel = -15.f * act->GetTransform().basis[1]; + } + act->SetAngularMomentum(zeus::CAxisAngle::sIdentity); + } + } + break; + } + case pas::EWallHangState::OutOfWallHangTurn: { + SetLaunchVelocity(bc); + if (bc.IsAnimationOver()) { + x4_state = pas::EWallHangState::DetachJumpLoop; + CPASAnimParmData parms(20, CPASAnimParm::FromEnum(s32(x4_state))); + bc.LoopBestAnimation(parms, *mgr.GetActiveRandom()); + } else { + CheckForLand(bc, mgr); + } + break; + } + case pas::EWallHangState::DetachJumpLoop: { + SetLaunchVelocity(bc); + CheckForLand(bc, mgr); + break; + } + case pas::EWallHangState::DetachOutOfJump: { + if (bc.IsAnimationOver()) { + x4_state = pas::EWallHangState::Invalid; + return pas::EAnimationState::Locomotion; + } + break; + } + default: + break; + } + } + return st; +} + +bool CBSWallHang::IsInAir(const CBodyController& bc) const { + switch (x4_state) { + case pas::EWallHangState::JumpArc: + case pas::EWallHangState::JumpAirLoop: + case pas::EWallHangState::OutOfWallHangTurn: + case pas::EWallHangState::DetachJumpLoop: + return true; + default: + return false; + } +} + +bool CBSWallHang::ApplyAnimationDeltas() const { + switch (x4_state) { + case pas::EWallHangState::IntoJump: + case pas::EWallHangState::IntoWallHang: + case pas::EWallHangState::WallHang: + case pas::EWallHangState::Five: + case pas::EWallHangState::OutOfWallHang: + case pas::EWallHangState::DetachOutOfJump: + return true; + default: + return false; + } +} + +bool CBSWallHang::ApplyHeadTracking() const { + switch (x4_state) { + case pas::EWallHangState::WallHang: + case pas::EWallHangState::Five: + return true; + default: + return false; + } +} + +bool CBSWallHang::ApplyGravity() const { + switch (x4_state) { + case pas::EWallHangState::WallHang: + case pas::EWallHangState::IntoWallHang: + case pas::EWallHangState::OutOfWallHang: + return false; + default: + return true; + } +} + +float CBSLocomotion::GetStartVelocityMagnitude(CBodyController& bc) { + if (TCastToPtr act = bc.GetOwner()) { + float maxSpeed = bc.GetBodyStateInfo().GetMaxSpeed(); + float ret = 0.f; + if (maxSpeed > 0.f) + ret = act->GetVelocity().magnitude() / maxSpeed; + return std::min(1.f, ret); + } + return 0.f; +} + +void CBSLocomotion::ReStartBodyState(CBodyController& bc, bool maintainVel) { + UpdateLocomotionAnimation(0.f, maintainVel ? GetStartVelocityMagnitude(bc) : 0.f, bc, true); +} + +float CBSLocomotion::ComputeWeightPercentage(const std::pair& a, const std::pair& b, + float f) const { + float range = b.second - a.second; + if (range > FLT_EPSILON) + return std::max(0.f, std::min(1.f, (f - a.second) / range)); + return 0.f; +} + +void CBSLocomotion::Start(CBodyController& bc, CStateManager& mgr) { + x4_locomotionType = bc.GetLocomotionType(); + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MaintainVelocity)) + ReStartBodyState(bc, true); + else + ReStartBodyState(bc, false); +} + +pas::EAnimationState CBSLocomotion::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + pas::EAnimationState st = GetBodyStateTransition(dt, bc); + if (st == pas::EAnimationState::Invalid) + UpdateLocomotionAnimation(dt, ApplyLocomotionPhysics(dt, bc), bc, false); + return st; +} + +void CBSLocomotion::Shutdown(CBodyController& bc) { bc.MultiplyPlaybackRate(1.f); } + +float CBSLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) { + if (TCastToPtr act = bc.GetOwner()) { + zeus::CVector3f vec = (zeus::close_enough(bc.GetCommandMgr().GetFaceVector(), zeus::CVector3f::skZero, 0.0001f)) + ? bc.GetCommandMgr().GetMoveVector() + : bc.GetCommandMgr().GetFaceVector(); + if (vec.canBeNormalized()) { + if (IsPitchable()) { + zeus::CVector3f tmp = vec; + tmp.z() = 0.f; + zeus::CVector3f lookVec = act->GetTransform().basis[1]; + lookVec.z() = 0.f; + lookVec.normalize(); + bc.FaceDirection3D(tmp, lookVec, dt); + zeus::CVector3f lookVec2 = act->GetTransform().basis[1]; + lookVec2.z() = float(vec.z()); + lookVec2.normalize(); + if (!zeus::close_enough(lookVec, lookVec2, 0.0001f)) { + zeus::CRelAngle pitchAngle = + std::min(bc.GetBodyStateInfo().GetMaximumPitch(), zeus::CVector3f::getAngleDiff(vec, tmp)); + lookVec2 = zeus::CVector3f::slerp(lookVec, lookVec2, pitchAngle); + } + bc.FaceDirection3D(lookVec2, act->GetTransform().basis[1], dt); + zeus::CVector3f lookVec3 = act->GetTransform().basis[1]; + lookVec3.z() = 0.f; + bc.FaceDirection3D(lookVec3, act->GetTransform().basis[1], dt); + } else { + bc.FaceDirection(vec.normalized(), dt); + } + } + return std::min(1.f, bc.GetCommandMgr().GetMoveVector().magnitude()); + } + return 0.f; +} + +pas::EAnimationState CBSLocomotion::GetBodyStateTransition(float, CBodyController& bc) { + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Hurled)) + return pas::EAnimationState::Hurled; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockDown)) + return pas::EAnimationState::Fall; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopHitReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::KnockBack)) + return pas::EAnimationState::KnockBack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Locomotion)) { + bc.GetCommandMgr().ClearLocomotionCmds(); + return pas::EAnimationState::Invalid; + } + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Slide)) + return pas::EAnimationState::Slide; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Generate)) + return pas::EAnimationState::Generate; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::MeleeAttack)) + return pas::EAnimationState::MeleeAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::ProjectileAttack)) + return pas::EAnimationState::ProjectileAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopAttack)) + return pas::EAnimationState::LoopAttack; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::LoopReaction)) + return pas::EAnimationState::LoopReaction; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Jump)) + return pas::EAnimationState::Jump; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Taunt)) + return pas::EAnimationState::Taunt; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Step)) + return pas::EAnimationState::Step; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Cover)) + return pas::EAnimationState::Cover; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::WallHang)) + return pas::EAnimationState::WallHang; + if (bc.GetCommandMgr().GetCmd(EBodyStateCmd::Scripted)) + return pas::EAnimationState::Scripted; + if (bc.GetCommandMgr().GetMoveVector().isZero()) { + if (!bc.GetCommandMgr().GetFaceVector().isZero()) + if (!IsMoving()) + return pas::EAnimationState::Turn; + } + if (x4_locomotionType != bc.GetLocomotionType()) + return pas::EAnimationState::Locomotion; + return pas::EAnimationState::Invalid; +} + +CBSBiPedLocomotion::CBSBiPedLocomotion(CActor& actor) { + const CPASDatabase& pasDatabase = actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); + for (int i = 0; i < 14; ++i) { + x8_anims.emplace_back(); + rstl::reserved_vector, 8>& innerVec = x8_anims.back(); + for (int j = 0; j < 8; ++j) { + CPASAnimParmData parms(5, CPASAnimParm::FromEnum(j), CPASAnimParm::FromEnum(i)); + std::pair best = pasDatabase.FindBestAnimation(parms, -1); + float avgVel = 0.f; + if (best.second != -1) { + avgVel = actor.GetAverageAnimVelocity(best.second); + if (j == 0) + avgVel = 0.f; + } + innerVec.push_back({best.second, avgVel}); + } + } +} + +void CBSBiPedLocomotion::Start(CBodyController& bc, CStateManager& mgr) { + x3c8_primeTime = 0.f; + CBSLocomotion::Start(bc, mgr); +} + +pas::EAnimationState CBSBiPedLocomotion::UpdateBody(float dt, CBodyController& bc, CStateManager& mgr) { + if (x3c8_primeTime < 0.2f) + x3c8_primeTime += dt; + return CBSLocomotion::UpdateBody(dt, bc, mgr); +} + +float CBSBiPedLocomotion::GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const { + return GetLocoAnimation(type, anim).second; +} + +float CBSBiPedLocomotion::UpdateRun(float vel, CBodyController& bc, pas::ELocomotionAnim anim) { + const std::pair& walk = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Walk); + const std::pair& run = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Run); + float perc = ComputeWeightPercentage(walk, run, vel); + + if (perc < 0.4f) { + float rate = walk.second > 0.f ? vel / walk.second : 1.f; + if (anim != pas::ELocomotionAnim::Walk && bc.GetCurrentAnimId() != walk.first) { + CAnimPlaybackParms playParms(walk.first, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, true, false); + x3c8_primeTime = 0.f; + } + bc.MultiplyPlaybackRate(rate); + x3c4_anim = pas::ELocomotionAnim::Walk; + return rate; + } else { + float rate = std::min(1.f, vel / run.second); + if (anim != pas::ELocomotionAnim::Run && bc.GetCurrentAnimId() != run.first) { + CAnimPlaybackParms playParms(run.first, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, true, false); + x3c8_primeTime = 0.f; + } + bc.MultiplyPlaybackRate(rate); + x3c4_anim = pas::ELocomotionAnim::Run; + return rate; + } +} + +float CBSBiPedLocomotion::UpdateWalk(float vel, CBodyController& bc, pas::ELocomotionAnim anim) { + if (anim != pas::ELocomotionAnim::Walk) { + const std::pair& walk = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Walk); + if (bc.GetCurrentAnimId() != walk.first) { + CAnimPlaybackParms playParms(walk.first, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, true, false); + x3c8_primeTime = 0.f; + } + x3c4_anim = pas::ELocomotionAnim::Walk; + } + + const std::pair& idle = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Idle); + const std::pair& walk = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Walk); + float perc = std::max(0.5f, ComputeWeightPercentage(idle, walk, vel)); + bc.MultiplyPlaybackRate(perc); + return perc; +} + +static const pas::ELocomotionAnim Strafes[] = {pas::ELocomotionAnim::StrafeRight, pas::ELocomotionAnim::StrafeLeft, + pas::ELocomotionAnim::Walk, pas::ELocomotionAnim::BackUp, + pas::ELocomotionAnim::StrafeUp, pas::ELocomotionAnim::StrafeDown}; + +float CBSBiPedLocomotion::UpdateStrafe(float vel, CBodyController& bc, pas::ELocomotionAnim anim) { + if (TCastToPtr act = bc.GetOwner()) { + zeus::CVector3f localVec = act->GetTransform().transposeRotate(bc.GetCommandMgr().GetMoveVector()); + zeus::CVector3f localVecSq = localVec * localVec; + int maxComp = 0; + for (int i = 0; i < 3; ++i) + if (localVecSq[i] >= localVecSq[maxComp]) + maxComp = i; + int strafeKey = maxComp * 2 + localVec[maxComp] > 0.f ? 0 : 1; + pas::ELocomotionAnim strafeType = Strafes[strafeKey]; + float rate = vel * GetLocomotionSpeed(x4_locomotionType, strafeType); + if (anim != strafeType) { + const std::pair& strafe = GetLocoAnimation(x4_locomotionType, strafeType); + if (bc.GetCurrentAnimId() != strafe.first) { + CAnimPlaybackParms playParms(strafe.first, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, true, false); + x3c8_primeTime = 0.f; + } + x3c4_anim = strafeType; + } + const std::pair& idle = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Idle); + const std::pair& strafe = GetLocoAnimation(x4_locomotionType, strafeType); + float perc = std::max(0.5f, ComputeWeightPercentage(idle, strafe, rate)); + bc.MultiplyPlaybackRate(perc); + } + return 1.f; +} + +float CBSBiPedLocomotion::UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init) { + float ret = 1.f; + if (init || x3c8_primeTime >= 0.2f) { + pas::ELocomotionAnim anim = init ? pas::ELocomotionAnim::Invalid : x3c4_anim; + float maxSpeed = velMag * GetLocomotionSpeed(x4_locomotionType, pas::ELocomotionAnim::Run); + if (IsStrafing(bc) && velMag >= 0.01f) + return UpdateStrafe(velMag, bc, anim); + + if (maxSpeed < 0.01f) { + if (anim != pas::ELocomotionAnim::Idle || init) { + if (!bc.GetBodyStateInfo().GetLocoAnimChangeAtEndOfAnimOnly() || bc.GetAnimTimeRemaining() <= dt || init) { + const std::pair& best = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Idle); + if (bc.GetCurrentAnimId() != best.first) { + CAnimPlaybackParms playParms(best.first, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, true, false); + x3c8_primeTime = 0.f; + } + x3c4_anim = pas::ELocomotionAnim::Idle; + } + } + } else { + const std::pair& best = GetLocoAnimation(x4_locomotionType, pas::ELocomotionAnim::Walk); + if (maxSpeed < best.second) + return UpdateWalk(maxSpeed, bc, anim); + return UpdateRun(maxSpeed, bc, anim); + } + } + return ret; +} + +bool CBSBiPedLocomotion::IsStrafing(const CBodyController& bc) const { + if (!zeus::close_enough(bc.GetCommandMgr().GetMoveVector(), zeus::CVector3f::skZero, 0.0001f)) + if (!zeus::close_enough(bc.GetCommandMgr().GetFaceVector(), zeus::CVector3f::skZero, 0.0001f)) + return true; + return false; } CBSFlyerLocomotion::CBSFlyerLocomotion(CActor& actor, bool pitchable) -: CBSBiPedLocomotion(actor), x3cc_pitchable(pitchable) -{} +: CBSBiPedLocomotion(actor), x3cc_pitchable(pitchable) {} -float CBSFlyerLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) -{ - float ret = CBSLocomotion::ApplyLocomotionPhysics(dt, bc); - if (TCastToPtr act = bc.GetOwner()) - { - if (std::fabs(bc.GetCommandMgr().GetMoveVector().z()) > 0.01f && - (!x3cc_pitchable || bc.GetBodyStateInfo().GetMaximumPitch() < 0.17453292f)) - { - zeus::CVector3f dir; - dir.z() = dt * bc.GetBodyStateInfo().GetMaxSpeed() * bc.GetCommandMgr().GetMoveVector().z(); - act->ApplyImpulseWR(act->GetMoveToORImpulseWR(dir, dt), zeus::CAxisAngle::sIdentity); - } +float CBSFlyerLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) { + float ret = CBSLocomotion::ApplyLocomotionPhysics(dt, bc); + if (TCastToPtr act = bc.GetOwner()) { + if (std::fabs(bc.GetCommandMgr().GetMoveVector().z()) > 0.01f && + (!x3cc_pitchable || bc.GetBodyStateInfo().GetMaximumPitch() < 0.17453292f)) { + zeus::CVector3f dir; + dir.z() = dt * bc.GetBodyStateInfo().GetMaxSpeed() * bc.GetCommandMgr().GetMoveVector().z(); + act->ApplyImpulseWR(act->GetMoveToORImpulseWR(dir, dt), zeus::CAxisAngle::sIdentity); } - return ret; + } + return ret; } -CBSWallWalkerLocomotion::CBSWallWalkerLocomotion(CActor& actor) -: CBSBiPedLocomotion(actor) -{} +CBSWallWalkerLocomotion::CBSWallWalkerLocomotion(CActor& actor) : CBSBiPedLocomotion(actor) {} -float CBSWallWalkerLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) -{ - if (TCastToPtr act = bc.GetOwner()) - { - float maxSpeed = bc.GetBodyStateInfo().GetMaxSpeed(); - zeus::CVector3f x40 = bc.GetCommandMgr().GetMoveVector() * maxSpeed; - if ((zeus::CVector3f::getAngleDiff(bc.GetCommandMgr().GetFaceVector(), x40) < (M_PIF / 2.f) ? - x40 : bc.GetCommandMgr().GetFaceVector()).canBeNormalized()) - bc.FaceDirection3D(x40.normalized(), act->GetTransform().basis[1], dt); - zeus::CVector3f impulse = - act->GetMoveToORImpulseWR(act->GetTransform().transposeRotate(x40 * dt), dt); - impulse = act->GetMass() > FLT_EPSILON ? impulse / act->GetMass() : - zeus::CVector3f(0.f, act->GetVelocity().magnitude(), 0.f); - if (maxSpeed > FLT_EPSILON) - return std::min(1.f, impulse.magnitude() / maxSpeed); +float CBSWallWalkerLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) { + if (TCastToPtr act = bc.GetOwner()) { + float maxSpeed = bc.GetBodyStateInfo().GetMaxSpeed(); + zeus::CVector3f x40 = bc.GetCommandMgr().GetMoveVector() * maxSpeed; + if ((zeus::CVector3f::getAngleDiff(bc.GetCommandMgr().GetFaceVector(), x40) < (M_PIF / 2.f) + ? x40 + : bc.GetCommandMgr().GetFaceVector()) + .canBeNormalized()) + bc.FaceDirection3D(x40.normalized(), act->GetTransform().basis[1], dt); + zeus::CVector3f impulse = act->GetMoveToORImpulseWR(act->GetTransform().transposeRotate(x40 * dt), dt); + impulse = act->GetMass() > FLT_EPSILON ? impulse / act->GetMass() + : zeus::CVector3f(0.f, act->GetVelocity().magnitude(), 0.f); + if (maxSpeed > FLT_EPSILON) + return std::min(1.f, impulse.magnitude() / maxSpeed); + } + return 0.f; +} + +CBSNewFlyerLocomotion::CBSNewFlyerLocomotion(CActor& actor) : CBSBiPedLocomotion(actor) {} + +float CBSNewFlyerLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) { + if (TCastToPtr(bc.GetOwner())) + bc.FaceDirection(bc.GetCommandMgr().GetFaceVector(), dt); + return 0.f; +} + +static const pas::ELocomotionAnim RunStrafes[] = {pas::ELocomotionAnim::StrafeRight, pas::ELocomotionAnim::StrafeLeft, + pas::ELocomotionAnim::Run, pas::ELocomotionAnim::BackUp, + pas::ELocomotionAnim::StrafeUp, pas::ELocomotionAnim::StrafeDown}; + +float CBSNewFlyerLocomotion::UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init) { + if (TCastToPtr act = bc.GetOwner()) { + pas::ELocomotionAnim strafeType = pas::ELocomotionAnim::Idle; + if (bc.GetCommandMgr().GetMoveVector().canBeNormalized()) { + zeus::CVector3f localVec = act->GetTransform().transposeRotate(bc.GetCommandMgr().GetMoveVector()); + zeus::CVector3f localVecSq = localVec * localVec; + int maxComp = 0; + for (int i = 0; i < 3; ++i) + if (localVecSq[i] >= localVecSq[maxComp]) + maxComp = i; + int strafeKey = maxComp * 2 + localVec[maxComp] > 0.f ? 0 : 1; + strafeType = RunStrafes[strafeKey]; } - return 0.f; -} -CBSNewFlyerLocomotion::CBSNewFlyerLocomotion(CActor& actor) -: CBSBiPedLocomotion(actor) -{} - -float CBSNewFlyerLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) -{ - if (TCastToPtr(bc.GetOwner())) - bc.FaceDirection(bc.GetCommandMgr().GetFaceVector(), dt); - return 0.f; -} - -static const pas::ELocomotionAnim RunStrafes[] = -{ - pas::ELocomotionAnim::StrafeRight, - pas::ELocomotionAnim::StrafeLeft, - pas::ELocomotionAnim::Run, - pas::ELocomotionAnim::BackUp, - pas::ELocomotionAnim::StrafeUp, - pas::ELocomotionAnim::StrafeDown -}; - -float CBSNewFlyerLocomotion::UpdateLocomotionAnimation(float dt, float velMag, - CBodyController& bc, bool init) -{ - if (TCastToPtr act = bc.GetOwner()) - { - pas::ELocomotionAnim strafeType = pas::ELocomotionAnim::Idle; - if (bc.GetCommandMgr().GetMoveVector().canBeNormalized()) - { - zeus::CVector3f localVec = act->GetTransform().transposeRotate(bc.GetCommandMgr().GetMoveVector()); - zeus::CVector3f localVecSq = localVec * localVec; - int maxComp = 0; - for (int i=0 ; i<3 ; ++i) - if (localVecSq[i] >= localVecSq[maxComp]) - maxComp = i; - int strafeKey = maxComp * 2 + localVec[maxComp] > 0.f ? 0 : 1; - strafeType = RunStrafes[strafeKey]; - } - - if (init || strafeType != x3c4_anim) - { - const std::pair& strafe = GetLocoAnimation(x4_locomotionType, strafeType); - if (init || bc.GetCurrentAnimId() != strafe.first) - { - CAnimPlaybackParms playParms(strafe.first, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, true, false); - } - x3c4_anim = strafeType; - } + if (init || strafeType != x3c4_anim) { + const std::pair& strafe = GetLocoAnimation(x4_locomotionType, strafeType); + if (init || bc.GetCurrentAnimId() != strafe.first) { + CAnimPlaybackParms playParms(strafe.first, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, true, false); + } + x3c4_anim = strafeType; } - return 1.f; + } + return 1.f; } -CBSRestrictedLocomotion::CBSRestrictedLocomotion(CActor& actor) -{ - const CPASDatabase& pasDatabase = - actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); - for (int i=0 ; i<14 ; ++i) - { - CPASAnimParmData parms(5, CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(i)); - std::pair best = pasDatabase.FindBestAnimation(parms, -1); - x8_anims.push_back(best.second); +CBSRestrictedLocomotion::CBSRestrictedLocomotion(CActor& actor) { + const CPASDatabase& pasDatabase = actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); + for (int i = 0; i < 14; ++i) { + CPASAnimParmData parms(5, CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(i)); + std::pair best = pasDatabase.FindBestAnimation(parms, -1); + x8_anims.push_back(best.second); + } +} + +float CBSRestrictedLocomotion::UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init) { + pas::ELocomotionAnim anim = init ? pas::ELocomotionAnim::Invalid : x44_anim; + if (anim != pas::ELocomotionAnim::Idle) { + s32 newAnim = x8_anims[int(x4_locomotionType)]; + if (newAnim != bc.GetCurrentAnimId()) { + CAnimPlaybackParms playParms(newAnim, -1, 1.f, true); + bc.SetCurrentAnimation(playParms, true, false); } + x44_anim = pas::ELocomotionAnim::Idle; + } + return 1.f; } -float CBSRestrictedLocomotion::UpdateLocomotionAnimation(float dt, float velMag, - CBodyController& bc, bool init) -{ - pas::ELocomotionAnim anim = init ? pas::ELocomotionAnim::Invalid : x44_anim; - if (anim != pas::ELocomotionAnim::Idle) - { - s32 newAnim = x8_anims[int(x4_locomotionType)]; - if (newAnim != bc.GetCurrentAnimId()) - { - CAnimPlaybackParms playParms(newAnim, -1, 1.f, true); - bc.SetCurrentAnimation(playParms, true, false); - } - x44_anim = pas::ELocomotionAnim::Idle; - } - return 1.f; +CBSRestrictedFlyerLocomotion::CBSRestrictedFlyerLocomotion(CActor& actor) : CBSRestrictedLocomotion(actor) {} + +float CBSRestrictedFlyerLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) { + if (TCastToPtr act = bc.GetOwner()) { + bc.FaceDirection(bc.GetCommandMgr().GetFaceVector(), dt); + act->ApplyImpulseWR(bc.GetCommandMgr().GetMoveVector() * bc.GetRestrictedFlyerMoveSpeed() * act->GetMass(), + zeus::CAxisAngle::sIdentity); + } + return 0.f; } -CBSRestrictedFlyerLocomotion::CBSRestrictedFlyerLocomotion(CActor& actor) -: CBSRestrictedLocomotion(actor) -{} - -float CBSRestrictedFlyerLocomotion::ApplyLocomotionPhysics(float dt, CBodyController& bc) -{ - if (TCastToPtr act = bc.GetOwner()) - { - bc.FaceDirection(bc.GetCommandMgr().GetFaceVector(), dt); - act->ApplyImpulseWR(bc.GetCommandMgr().GetMoveVector() * - bc.GetRestrictedFlyerMoveSpeed() * act->GetMass(), - zeus::CAxisAngle::sIdentity); - } - return 0.f; -} - -} +} // namespace urde diff --git a/Runtime/Character/CBodyState.hpp b/Runtime/Character/CBodyState.hpp index 3fd7a6b4b..05d7e2048 100644 --- a/Runtime/Character/CBodyState.hpp +++ b/Runtime/Character/CBodyState.hpp @@ -4,427 +4,417 @@ #include "CharacterCommon.hpp" #include "CBodyStateCmdMgr.hpp" -namespace urde -{ +namespace urde { class CBodyController; class CStateManager; class CActor; -class CBodyState -{ +class CBodyState { public: - virtual ~CBodyState() = default; - virtual bool IsInAir(const CBodyController&) const { return false; } - virtual bool IsDead() const { return false; } - virtual bool IsDying() const { return false; } - virtual bool IsMoving() const { return false; } - virtual bool ApplyGravity() const { return true; } - virtual bool ApplyHeadTracking() const { return true; } - virtual bool ApplyAnimationDeltas() const { return true; } - virtual bool CanShoot() const { return false; } - virtual void Start(CBodyController&, CStateManager&) = 0; - virtual pas::EAnimationState UpdateBody(float, CBodyController&, CStateManager&) = 0; - virtual void Shutdown(CBodyController&)=0; + virtual ~CBodyState() = default; + virtual bool IsInAir(const CBodyController&) const { return false; } + virtual bool IsDead() const { return false; } + virtual bool IsDying() const { return false; } + virtual bool IsMoving() const { return false; } + virtual bool ApplyGravity() const { return true; } + virtual bool ApplyHeadTracking() const { return true; } + virtual bool ApplyAnimationDeltas() const { return true; } + virtual bool CanShoot() const { return false; } + virtual void Start(CBodyController&, CStateManager&) = 0; + virtual pas::EAnimationState UpdateBody(float, CBodyController&, CStateManager&) = 0; + virtual void Shutdown(CBodyController&) = 0; }; -class CBSAttack : public CBodyState -{ - pas::EAnimationState x4_nextState = pas::EAnimationState::Invalid; - CBCSlideCmd x8_slide; - zeus::CVector3f x20_targetPos; - float x2c_alignTargetPosStartTime = -1.f; - float x30_alignTargetPosTime = -1.f; - float x34_curTime = 0.f; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); - void UpdatePhysicsActor(CBodyController& bc, float dt); +class CBSAttack : public CBodyState { + pas::EAnimationState x4_nextState = pas::EAnimationState::Invalid; + CBCSlideCmd x8_slide; + zeus::CVector3f x20_targetPos; + float x2c_alignTargetPosStartTime = -1.f; + float x30_alignTargetPosTime = -1.f; + float x34_curTime = 0.f; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + void UpdatePhysicsActor(CBodyController& bc, float dt); + public: - bool CanShoot() const { return false; } - void Start(CBodyController& bc, CStateManager & mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + bool CanShoot() const { return false; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSProjectileAttack : public CBodyState -{ - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSProjectileAttack : public CBodyState { + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - bool CanShoot() const { return true; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + bool CanShoot() const { return true; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSDie : public CBodyState -{ - float x4_remTime = 0.f; - bool x8_isDead = false; +class CBSDie : public CBodyState { + float x4_remTime = 0.f; + bool x8_isDead = false; + public: - bool IsDead() const { return x8_isDead; } - bool IsDying() const { return true; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + bool IsDead() const { return x8_isDead; } + bool IsDying() const { return true; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSFall : public CBodyState -{ - float x4_rotateSpeed = 0.f; - float x8_remTime = 0.f; - pas::EFallState xc_fallState = pas::EFallState::Invalid; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSFall : public CBodyState { + float x4_rotateSpeed = 0.f; + float x8_remTime = 0.f; + pas::EFallState xc_fallState = pas::EFallState::Invalid; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController& bc); + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController& bc); }; -class CBSGetup : public CBodyState -{ - pas::EFallState x4_fallState = pas::EFallState::Invalid; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSGetup : public CBodyState { + pas::EFallState x4_fallState = pas::EFallState::Invalid; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController& bc); + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController& bc); }; -class CBSKnockBack : public CBodyState -{ - float x4_curTime = 0.f; - float x8_rotateSpeed = 0.f; - float xc_remTime = 0.f; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSKnockBack : public CBodyState { + float x4_curTime = 0.f; + float x8_rotateSpeed = 0.f; + float xc_remTime = 0.f; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - bool IsMoving() const { return true; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + bool IsMoving() const { return true; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSLieOnGround : public CBodyState -{ - bool x4_24_hasGroundHit : 1; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSLieOnGround : public CBodyState { + bool x4_24_hasGroundHit : 1; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - CBSLieOnGround(CActor& actor); - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController& bc); + CBSLieOnGround(CActor& actor); + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController& bc); }; -class CBSStep : public CBodyState -{ - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSStep : public CBodyState { + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - bool IsMoving() const { return true; } - bool CanShoot() const { return true; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + bool IsMoving() const { return true; } + bool CanShoot() const { return true; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSTurn : public CBodyState -{ +class CBSTurn : public CBodyState { protected: - float x4_rotateSpeed = 0.f; - zeus::CVector2f x8_dest; - pas::ETurnDirection x10_turnDir = pas::ETurnDirection::Invalid; - bool FacingDest(CBodyController& bc) const; + float x4_rotateSpeed = 0.f; + zeus::CVector2f x8_dest; + pas::ETurnDirection x10_turnDir = pas::ETurnDirection::Invalid; + bool FacingDest(CBodyController& bc) const; + public: - bool CanShoot() const { return true; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} - virtual pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + bool CanShoot() const { return true; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} + virtual pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); }; -class CBSFlyerTurn : public CBSTurn -{ +class CBSFlyerTurn : public CBSTurn { public: - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); }; -class CBSLoopAttack : public CBodyState -{ - pas::ELoopState x4_state = pas::ELoopState::Invalid; - pas::ELoopAttackType x8_loopAttackType = pas::ELoopAttackType::Invalid; - bool xc_24_waitForAnimOver : 1; - bool xc_25_advance : 1; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSLoopAttack : public CBodyState { + pas::ELoopState x4_state = pas::ELoopState::Invalid; + pas::ELoopAttackType x8_loopAttackType = pas::ELoopAttackType::Invalid; + bool xc_24_waitForAnimOver : 1; + bool xc_25_advance : 1; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - CBSLoopAttack() { xc_24_waitForAnimOver = false; xc_25_advance = false; } - bool CanShoot() const { return true; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + CBSLoopAttack() { + xc_24_waitForAnimOver = false; + xc_25_advance = false; + } + bool CanShoot() const { return true; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSLoopReaction : public CBodyState -{ - pas::ELoopState x4_state = pas::ELoopState::Invalid; - pas::EReactionType x8_reactionType = pas::EReactionType::Invalid; - bool xc_24_loopHit : 1; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); - bool PlayExitAnimation(CBodyController& bc, CStateManager& mgr) const; +class CBSLoopReaction : public CBodyState { + pas::ELoopState x4_state = pas::ELoopState::Invalid; + pas::EReactionType x8_reactionType = pas::EReactionType::Invalid; + bool xc_24_loopHit : 1; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + bool PlayExitAnimation(CBodyController& bc, CStateManager& mgr) const; + public: - CBSLoopReaction() { xc_24_loopHit = false; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + CBSLoopReaction() { xc_24_loopHit = false; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSGroundHit : public CBodyState -{ - float x4_rotateSpeed = 0.f; - float x8_remTime = 0.f; - pas::EFallState xc_fallState = pas::EFallState::Invalid; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSGroundHit : public CBodyState { + float x4_rotateSpeed = 0.f; + float x8_remTime = 0.f; + pas::EFallState xc_fallState = pas::EFallState::Invalid; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController& bc); + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController& bc); }; -class CBSGenerate : public CBodyState -{ - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSGenerate : public CBodyState { + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSJump : public CBodyState -{ - pas::EJumpState x4_state = pas::EJumpState::Invalid; - pas::EJumpType x8_jumpType; - zeus::CVector3f xc_waypoint1; - zeus::CVector3f x18_velocity; - zeus::CVector3f x24_waypoint2; - union - { - struct - { - bool x30_24_bodyForceSet : 1; - bool x30_25_wallJump : 1; - bool x30_26_wallBounceRight : 1; - bool x30_27_wallBounceComplete : 1; - bool x30_28_startInJumpLoop : 1; - }; - u32 _dummy = 0; +class CBSJump : public CBodyState { + pas::EJumpState x4_state = pas::EJumpState::Invalid; + pas::EJumpType x8_jumpType; + zeus::CVector3f xc_waypoint1; + zeus::CVector3f x18_velocity; + zeus::CVector3f x24_waypoint2; + union { + struct { + bool x30_24_bodyForceSet : 1; + bool x30_25_wallJump : 1; + bool x30_26_wallBounceRight : 1; + bool x30_27_wallBounceComplete : 1; + bool x30_28_startInJumpLoop : 1; }; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); - bool CheckForWallJump(CBodyController& bc, CStateManager& mgr); - void CheckForLand(CBodyController& bc, CStateManager& mgr); - void PlayJumpLoop(CStateManager& mgr, CBodyController& bc); + u32 _dummy = 0; + }; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + bool CheckForWallJump(CBodyController& bc, CStateManager& mgr); + void CheckForLand(CBodyController& bc, CStateManager& mgr); + void PlayJumpLoop(CStateManager& mgr, CBodyController& bc); + public: - bool IsMoving() const { return true; } - bool ApplyHeadTracking() const { return false; } - bool CanShoot() const; - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - bool ApplyAnimationDeltas() const; - bool IsInAir(const CBodyController& bc) const; - void Shutdown(CBodyController&) {} + bool IsMoving() const { return true; } + bool ApplyHeadTracking() const { return false; } + bool CanShoot() const; + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + bool ApplyAnimationDeltas() const; + bool IsInAir(const CBodyController& bc) const; + void Shutdown(CBodyController&) {} }; -class CBSHurled : public CBodyState -{ - pas::EHurledState x4_state = pas::EHurledState::Invalid; - float x8_knockAngle = 0.f; - int xc_animSeries = -1; - float x10_rotateSpeed = 0.f; - float x14_remTime = 0.f; - float x18_curTime = 0.f; - mutable zeus::CVector3f x1c_lastTranslation; - mutable float x28_landedDur = 0.f; - bool x2c_24_needsRecover : 1; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); - void Recover(CStateManager& mgr, CBodyController& bc, pas::EHurledState state); - void PlayStrikeWallAnimation(CBodyController& bc, CStateManager& mgr); - void PlayLandAnimation(CBodyController& bc, CStateManager& mgr); - bool ShouldStartStrikeWall(CBodyController& bc) const; - bool ShouldStartLand(float dt, CBodyController& bc) const; +class CBSHurled : public CBodyState { + pas::EHurledState x4_state = pas::EHurledState::Invalid; + float x8_knockAngle = 0.f; + int xc_animSeries = -1; + float x10_rotateSpeed = 0.f; + float x14_remTime = 0.f; + float x18_curTime = 0.f; + mutable zeus::CVector3f x1c_lastTranslation; + mutable float x28_landedDur = 0.f; + bool x2c_24_needsRecover : 1; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + void Recover(CStateManager& mgr, CBodyController& bc, pas::EHurledState state); + void PlayStrikeWallAnimation(CBodyController& bc, CStateManager& mgr); + void PlayLandAnimation(CBodyController& bc, CStateManager& mgr); + bool ShouldStartStrikeWall(CBodyController& bc) const; + bool ShouldStartLand(float dt, CBodyController& bc) const; + public: - CBSHurled() { x2c_24_needsRecover = false; } - bool IsMoving() const { return true; } - bool IsInAir(const CBodyController&) const { return true; } - bool ApplyHeadTracking() const { return false; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + CBSHurled() { x2c_24_needsRecover = false; } + bool IsMoving() const { return true; } + bool IsInAir(const CBodyController&) const { return true; } + bool ApplyHeadTracking() const { return false; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSSlide : public CBodyState -{ - float x4_rotateSpeed = 0.f; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSSlide : public CBodyState { + float x4_rotateSpeed = 0.f; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - bool ApplyHeadTracking() const { return false; } - bool IsMoving() const { return true; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + bool ApplyHeadTracking() const { return false; } + bool IsMoving() const { return true; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSTaunt : public CBodyState -{ - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSTaunt : public CBodyState { + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSScripted : public CBodyState -{ - union - { - struct - { - bool x4_24_loopAnim : 1; - bool x4_25_timedLoop : 1; - }; - u32 _dummy = 0; +class CBSScripted : public CBodyState { + union { + struct { + bool x4_24_loopAnim : 1; + bool x4_25_timedLoop : 1; }; - float x8_remTime = 0.f; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + u32 _dummy = 0; + }; + float x8_remTime = 0.f; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - bool ApplyHeadTracking() const { return false; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + bool ApplyHeadTracking() const { return false; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSCover : public CBodyState -{ - pas::ECoverState x4_state = pas::ECoverState::Invalid; - pas::ECoverDirection x8_coverDirection = pas::ECoverDirection::Invalid; - bool xc_needsExit = false; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); +class CBSCover : public CBodyState { + pas::ECoverState x4_state = pas::ECoverState::Invalid; + pas::ECoverDirection x8_coverDirection = pas::ECoverDirection::Invalid; + bool xc_needsExit = false; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + public: - bool ApplyHeadTracking() const { return false; } - bool IsMoving() const { return true; } - bool CanShoot() const { return x4_state == pas::ECoverState::Lean; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + bool ApplyHeadTracking() const { return false; } + bool IsMoving() const { return true; } + bool CanShoot() const { return x4_state == pas::ECoverState::Lean; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSWallHang : public CBodyState -{ - pas::EWallHangState x4_state = pas::EWallHangState::Invalid; - TUniqueId x8_wpId = kInvalidUniqueId; - zeus::CVector3f xc_launchVel; - union - { - struct - { - bool x18_24_launched : 1; - bool x18_25_needsExit : 1; - }; - u32 _dummy = 0; +class CBSWallHang : public CBodyState { + pas::EWallHangState x4_state = pas::EWallHangState::Invalid; + TUniqueId x8_wpId = kInvalidUniqueId; + zeus::CVector3f xc_launchVel; + union { + struct { + bool x18_24_launched : 1; + bool x18_25_needsExit : 1; }; - pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); - void FixInPlace(CBodyController& bc); - bool CheckForLand(CBodyController& bc, CStateManager& mgr); - bool CheckForWall(CBodyController& bc, CStateManager& mgr); - void SetLaunchVelocity(CBodyController& bc); + u32 _dummy = 0; + }; + pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + void FixInPlace(CBodyController& bc); + bool CheckForLand(CBodyController& bc, CStateManager& mgr); + bool CheckForWall(CBodyController& bc, CStateManager& mgr); + void SetLaunchVelocity(CBodyController& bc); + public: - bool IsMoving() const { return true; } - bool CanShoot() const { return x4_state == pas::EWallHangState::WallHang; } - bool IsInAir(const CBodyController& bc) const; - bool ApplyGravity() const; - bool ApplyHeadTracking() const; - bool ApplyAnimationDeltas() const; - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController&) {} + bool IsMoving() const { return true; } + bool CanShoot() const { return x4_state == pas::EWallHangState::WallHang; } + bool IsInAir(const CBodyController& bc) const; + bool ApplyGravity() const; + bool ApplyHeadTracking() const; + bool ApplyAnimationDeltas() const; + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController&) {} }; -class CBSLocomotion : public CBodyState -{ +class CBSLocomotion : public CBodyState { protected: - pas::ELocomotionType x4_locomotionType = pas::ELocomotionType::Invalid; - float GetStartVelocityMagnitude(CBodyController& bc); - void ReStartBodyState(CBodyController& bc, bool maintainVel); - float ComputeWeightPercentage(const std::pair& a, - const std::pair& b, float f) const; + pas::ELocomotionType x4_locomotionType = pas::ELocomotionType::Invalid; + float GetStartVelocityMagnitude(CBodyController& bc); + void ReStartBodyState(CBodyController& bc, bool maintainVel); + float ComputeWeightPercentage(const std::pair& a, const std::pair& b, float f) const; + public: - bool IsMoving() const = 0; - bool CanShoot() const { return true; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - void Shutdown(CBodyController& bc); - virtual bool IsPitchable() const { return false; } - virtual float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const = 0; - virtual float ApplyLocomotionPhysics(float dt, CBodyController& bc); - virtual float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init) = 0; - virtual pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); + bool IsMoving() const = 0; + bool CanShoot() const { return true; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + void Shutdown(CBodyController& bc); + virtual bool IsPitchable() const { return false; } + virtual float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const = 0; + virtual float ApplyLocomotionPhysics(float dt, CBodyController& bc); + virtual float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init) = 0; + virtual pas::EAnimationState GetBodyStateTransition(float dt, CBodyController& bc); }; -class CBSBiPedLocomotion : public CBSLocomotion -{ +class CBSBiPedLocomotion : public CBSLocomotion { protected: - rstl::reserved_vector, 8>, 14> x8_anims; - pas::ELocomotionAnim x3c4_anim = pas::ELocomotionAnim::Invalid; - float x3c8_primeTime; - float UpdateRun(float vel, CBodyController& bc, pas::ELocomotionAnim anim); - float UpdateWalk(float vel, CBodyController& bc, pas::ELocomotionAnim anim); - float UpdateStrafe(float vel, CBodyController& bc, pas::ELocomotionAnim anim); - const std::pair& - GetLocoAnimation(pas::ELocomotionType type, pas::ELocomotionAnim anim) const - { return x8_anims[int(type)][int(anim)]; } + rstl::reserved_vector, 8>, 14> x8_anims; + pas::ELocomotionAnim x3c4_anim = pas::ELocomotionAnim::Invalid; + float x3c8_primeTime; + float UpdateRun(float vel, CBodyController& bc, pas::ELocomotionAnim anim); + float UpdateWalk(float vel, CBodyController& bc, pas::ELocomotionAnim anim); + float UpdateStrafe(float vel, CBodyController& bc, pas::ELocomotionAnim anim); + const std::pair& GetLocoAnimation(pas::ELocomotionType type, pas::ELocomotionAnim anim) const { + return x8_anims[int(type)][int(anim)]; + } + public: - CBSBiPedLocomotion(CActor& actor); - bool IsMoving() const { return x3c4_anim != pas::ELocomotionAnim::Idle; } - void Start(CBodyController& bc, CStateManager& mgr); - pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); - float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const; - float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init); - virtual bool IsStrafing(const CBodyController& bc) const; + CBSBiPedLocomotion(CActor& actor); + bool IsMoving() const { return x3c4_anim != pas::ELocomotionAnim::Idle; } + void Start(CBodyController& bc, CStateManager& mgr); + pas::EAnimationState UpdateBody(float dt, CBodyController& bc, CStateManager& mgr); + float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const; + float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init); + virtual bool IsStrafing(const CBodyController& bc) const; }; -class CBSFlyerLocomotion : public CBSBiPedLocomotion -{ - bool x3cc_pitchable; +class CBSFlyerLocomotion : public CBSBiPedLocomotion { + bool x3cc_pitchable; + public: - CBSFlyerLocomotion(CActor& actor, bool pitchable); - bool IsPitchable() const { return x3cc_pitchable; } - float ApplyLocomotionPhysics(float dt, CBodyController& bc); - virtual bool IsBackPedal(CBodyController& bc) const { return false; } + CBSFlyerLocomotion(CActor& actor, bool pitchable); + bool IsPitchable() const { return x3cc_pitchable; } + float ApplyLocomotionPhysics(float dt, CBodyController& bc); + virtual bool IsBackPedal(CBodyController& bc) const { return false; } }; -class CBSWallWalkerLocomotion : public CBSBiPedLocomotion -{ +class CBSWallWalkerLocomotion : public CBSBiPedLocomotion { public: - CBSWallWalkerLocomotion(CActor& actor); - float ApplyLocomotionPhysics(float dt, CBodyController& bc); + CBSWallWalkerLocomotion(CActor& actor); + float ApplyLocomotionPhysics(float dt, CBodyController& bc); }; -class CBSNewFlyerLocomotion : public CBSBiPedLocomotion -{ +class CBSNewFlyerLocomotion : public CBSBiPedLocomotion { public: - CBSNewFlyerLocomotion(CActor& actor); - float ApplyLocomotionPhysics(float dt, CBodyController& bc); - float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init); + CBSNewFlyerLocomotion(CActor& actor); + float ApplyLocomotionPhysics(float dt, CBodyController& bc); + float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init); }; -class CBSRestrictedLocomotion : public CBSLocomotion -{ - rstl::reserved_vector x8_anims; - pas::ELocomotionAnim x44_anim = pas::ELocomotionAnim::Invalid; +class CBSRestrictedLocomotion : public CBSLocomotion { + rstl::reserved_vector x8_anims; + pas::ELocomotionAnim x44_anim = pas::ELocomotionAnim::Invalid; + public: - CBSRestrictedLocomotion(CActor& actor); - bool IsMoving() const { return false; } - float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const { return 0.f; } - float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init); + CBSRestrictedLocomotion(CActor& actor); + bool IsMoving() const { return false; } + float GetLocomotionSpeed(pas::ELocomotionType type, pas::ELocomotionAnim anim) const { return 0.f; } + float UpdateLocomotionAnimation(float dt, float velMag, CBodyController& bc, bool init); }; -class CBSRestrictedFlyerLocomotion : public CBSRestrictedLocomotion -{ +class CBSRestrictedFlyerLocomotion : public CBSRestrictedLocomotion { public: - CBSRestrictedFlyerLocomotion(CActor& actor); - float ApplyLocomotionPhysics(float dt, CBodyController& bc); + CBSRestrictedFlyerLocomotion(CActor& actor); + float ApplyLocomotionPhysics(float dt, CBodyController& bc); }; -} +} // namespace urde diff --git a/Runtime/Character/CBodyStateCmdMgr.cpp b/Runtime/Character/CBodyStateCmdMgr.cpp index 086b971da..fca8ee106 100644 --- a/Runtime/Character/CBodyStateCmdMgr.cpp +++ b/Runtime/Character/CBodyStateCmdMgr.cpp @@ -1,98 +1,89 @@ #include "CBodyStateCmdMgr.hpp" #include -namespace urde -{ +namespace urde { -CBodyStateCmdMgr::CBodyStateCmdMgr() -{ - x40_commandTable.push_back(&xb8_getup); - x40_commandTable.push_back(&xc4_step); - x40_commandTable.push_back(&xd4_); - x40_commandTable.push_back(&xdc_knockDown); - x40_commandTable.push_back(&xf4_knockBack); - x40_commandTable.push_back(&x10c_meleeAttack); - x40_commandTable.push_back(&x128_projectileAttack); - x40_commandTable.push_back(&x144_loopAttack); - x40_commandTable.push_back(&x154_loopReaction); - x40_commandTable.push_back(&x160_loopHitReaction); - x40_commandTable.push_back(&x16c_); - x40_commandTable.push_back(&x174_); - x40_commandTable.push_back(&x17c_); - x40_commandTable.push_back(&x184_); - x40_commandTable.push_back(&x18c_generate); - x40_commandTable.push_back(&x1ac_hurled); - x40_commandTable.push_back(&x1d0_jump); - x40_commandTable.push_back(&x1f8_slide); - x40_commandTable.push_back(&x210_taunt); - x40_commandTable.push_back(&x21c_scripted); - x40_commandTable.push_back(&x230_cover); - x40_commandTable.push_back(&x254_wallHang); - x40_commandTable.push_back(&x260_); - x40_commandTable.push_back(&x268_); - x40_commandTable.push_back(&x270_additiveAim); - x40_commandTable.push_back(&x278_additiveFlinch); - x40_commandTable.push_back(&x284_additiveReaction); - x40_commandTable.push_back(&x298_); +CBodyStateCmdMgr::CBodyStateCmdMgr() { + x40_commandTable.push_back(&xb8_getup); + x40_commandTable.push_back(&xc4_step); + x40_commandTable.push_back(&xd4_); + x40_commandTable.push_back(&xdc_knockDown); + x40_commandTable.push_back(&xf4_knockBack); + x40_commandTable.push_back(&x10c_meleeAttack); + x40_commandTable.push_back(&x128_projectileAttack); + x40_commandTable.push_back(&x144_loopAttack); + x40_commandTable.push_back(&x154_loopReaction); + x40_commandTable.push_back(&x160_loopHitReaction); + x40_commandTable.push_back(&x16c_); + x40_commandTable.push_back(&x174_); + x40_commandTable.push_back(&x17c_); + x40_commandTable.push_back(&x184_); + x40_commandTable.push_back(&x18c_generate); + x40_commandTable.push_back(&x1ac_hurled); + x40_commandTable.push_back(&x1d0_jump); + x40_commandTable.push_back(&x1f8_slide); + x40_commandTable.push_back(&x210_taunt); + x40_commandTable.push_back(&x21c_scripted); + x40_commandTable.push_back(&x230_cover); + x40_commandTable.push_back(&x254_wallHang); + x40_commandTable.push_back(&x260_); + x40_commandTable.push_back(&x268_); + x40_commandTable.push_back(&x270_additiveAim); + x40_commandTable.push_back(&x278_additiveFlinch); + x40_commandTable.push_back(&x284_additiveReaction); + x40_commandTable.push_back(&x298_); } -void CBodyStateCmdMgr::DeliverCmd(const CBCLocomotionCmd& cmd) -{ - if (cmd.GetWeight() <= FLT_EPSILON) - return; - x3c_steeringSpeed += cmd.GetWeight(); - x0_move += cmd.GetMoveVector() * cmd.GetWeight(); - xc_face += cmd.GetFaceVector() * cmd.GetWeight(); +void CBodyStateCmdMgr::DeliverCmd(const CBCLocomotionCmd& cmd) { + if (cmd.GetWeight() <= FLT_EPSILON) + return; + x3c_steeringSpeed += cmd.GetWeight(); + x0_move += cmd.GetMoveVector() * cmd.GetWeight(); + xc_face += cmd.GetFaceVector() * cmd.GetWeight(); } -void CBodyStateCmdMgr::BlendSteeringCmds() -{ - if (x3c_steeringSpeed > FLT_EPSILON) - { - float stepMul = 1.f / x3c_steeringSpeed; - xc_face *= zeus::CVector3f(stepMul); +void CBodyStateCmdMgr::BlendSteeringCmds() { + if (x3c_steeringSpeed > FLT_EPSILON) { + float stepMul = 1.f / x3c_steeringSpeed; + xc_face *= zeus::CVector3f(stepMul); - switch (x30_steeringMode) - { - case ESteeringBlendMode::Normal: - x0_move *= zeus::CVector3f(stepMul); - break; - case ESteeringBlendMode::FullSpeed: - if (!zeus::close_enough(x0_move, zeus::CVector3f::skZero, 0.0001f)) - { - x0_move.normalize(); - x0_move *= zeus::CVector3f(x38_steeringSpeedMax); - } - break; - case ESteeringBlendMode::Clamped: - x0_move *= zeus::CVector3f(stepMul); - if (!zeus::close_enough(x0_move, zeus::CVector3f::skZero, 0.0001f)) - { - if (x0_move.magnitude() < x34_steeringSpeedMin) - x0_move = x0_move.normalized() * x34_steeringSpeedMin; - else if (x0_move.magnitude() > x38_steeringSpeedMax) - x0_move = x0_move.normalized() * x38_steeringSpeedMax; - } - break; - default: break; - } + switch (x30_steeringMode) { + case ESteeringBlendMode::Normal: + x0_move *= zeus::CVector3f(stepMul); + break; + case ESteeringBlendMode::FullSpeed: + if (!zeus::close_enough(x0_move, zeus::CVector3f::skZero, 0.0001f)) { + x0_move.normalize(); + x0_move *= zeus::CVector3f(x38_steeringSpeedMax); + } + break; + case ESteeringBlendMode::Clamped: + x0_move *= zeus::CVector3f(stepMul); + if (!zeus::close_enough(x0_move, zeus::CVector3f::skZero, 0.0001f)) { + if (x0_move.magnitude() < x34_steeringSpeedMin) + x0_move = x0_move.normalized() * x34_steeringSpeedMin; + else if (x0_move.magnitude() > x38_steeringSpeedMax) + x0_move = x0_move.normalized() * x38_steeringSpeedMax; + } + break; + default: + break; } + } } -void CBodyStateCmdMgr::Reset() -{ - x0_move = zeus::CVector3f::skZero; - xc_face = zeus::CVector3f::skZero; - x18_target = zeus::CVector3f::skZero; - x3c_steeringSpeed = 0.f; - xb4_deliveredCmdMask = 0; +void CBodyStateCmdMgr::Reset() { + x0_move = zeus::CVector3f::skZero; + xc_face = zeus::CVector3f::skZero; + x18_target = zeus::CVector3f::skZero; + x3c_steeringSpeed = 0.f; + xb4_deliveredCmdMask = 0; } -void CBodyStateCmdMgr::ClearLocomotionCmds() -{ - x0_move = zeus::CVector3f::skZero; - xc_face = zeus::CVector3f::skZero; - x3c_steeringSpeed = 0.f; +void CBodyStateCmdMgr::ClearLocomotionCmds() { + x0_move = zeus::CVector3f::skZero; + xc_face = zeus::CVector3f::skZero; + x3c_steeringSpeed = 0.f; } -} +} // namespace urde diff --git a/Runtime/Character/CBodyStateCmdMgr.hpp b/Runtime/Character/CBodyStateCmdMgr.hpp index 5feeffa2b..43e53d46d 100644 --- a/Runtime/Character/CBodyStateCmdMgr.hpp +++ b/Runtime/Character/CBodyStateCmdMgr.hpp @@ -4,469 +4,453 @@ #include "CharacterCommon.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { + +class CBodyStateCmd { + EBodyStateCmd x4_cmd; -class CBodyStateCmd -{ - EBodyStateCmd x4_cmd; public: - virtual ~CBodyStateCmd() = default; - CBodyStateCmd(EBodyStateCmd cmd) : x4_cmd(cmd) {} - EBodyStateCmd GetCommandId() const { return x4_cmd; } + virtual ~CBodyStateCmd() = default; + CBodyStateCmd(EBodyStateCmd cmd) : x4_cmd(cmd) {} + EBodyStateCmd GetCommandId() const { return x4_cmd; } }; -class CBCMeleeAttackCmd : public CBodyStateCmd -{ - pas::ESeverity x8_severity = pas::ESeverity::Invalid; - zeus::CVector3f xc_targetPos; - bool x18_hasTargetPos = false; +class CBCMeleeAttackCmd : public CBodyStateCmd { + pas::ESeverity x8_severity = pas::ESeverity::Invalid; + zeus::CVector3f xc_targetPos; + bool x18_hasTargetPos = false; + public: - CBCMeleeAttackCmd() : CBodyStateCmd(EBodyStateCmd::MeleeAttack) {} - CBCMeleeAttackCmd(pas::ESeverity severity) - : CBodyStateCmd(EBodyStateCmd::MeleeAttack), x8_severity(severity) {} - pas::ESeverity GetAttackSeverity() const { return x8_severity; } - bool HasAttackTargetPos() const { return x18_hasTargetPos; } - const zeus::CVector3f& GetAttackTargetPos() const { return xc_targetPos; } + CBCMeleeAttackCmd() : CBodyStateCmd(EBodyStateCmd::MeleeAttack) {} + CBCMeleeAttackCmd(pas::ESeverity severity) : CBodyStateCmd(EBodyStateCmd::MeleeAttack), x8_severity(severity) {} + pas::ESeverity GetAttackSeverity() const { return x8_severity; } + bool HasAttackTargetPos() const { return x18_hasTargetPos; } + const zeus::CVector3f& GetAttackTargetPos() const { return xc_targetPos; } }; -class CBCProjectileAttackCmd : public CBodyStateCmd -{ - pas::ESeverity x8_severity = pas::ESeverity::Invalid; - zeus::CVector3f xc_target; - bool x18_blendAnims = false; +class CBCProjectileAttackCmd : public CBodyStateCmd { + pas::ESeverity x8_severity = pas::ESeverity::Invalid; + zeus::CVector3f xc_target; + bool x18_blendAnims = false; + public: - CBCProjectileAttackCmd() : CBodyStateCmd(EBodyStateCmd::ProjectileAttack) {} - CBCProjectileAttackCmd(pas::ESeverity severity, const zeus::CVector3f& vec, bool b) - : CBodyStateCmd(EBodyStateCmd::ProjectileAttack), x8_severity(severity), xc_target(vec), x18_blendAnims(b) {} - pas::ESeverity GetAttackSeverity() const { return x8_severity; } - const zeus::CVector3f& GetTargetPosition() const { return xc_target; } - bool BlendTwoClosest() const { return x18_blendAnims; } + CBCProjectileAttackCmd() : CBodyStateCmd(EBodyStateCmd::ProjectileAttack) {} + CBCProjectileAttackCmd(pas::ESeverity severity, const zeus::CVector3f& vec, bool b) + : CBodyStateCmd(EBodyStateCmd::ProjectileAttack), x8_severity(severity), xc_target(vec), x18_blendAnims(b) {} + pas::ESeverity GetAttackSeverity() const { return x8_severity; } + const zeus::CVector3f& GetTargetPosition() const { return xc_target; } + bool BlendTwoClosest() const { return x18_blendAnims; } }; -class CBCStepCmd : public CBodyStateCmd -{ - pas::EStepDirection x8_dir = pas::EStepDirection::Invalid; - pas::EStepType xc_type = pas::EStepType::Normal; +class CBCStepCmd : public CBodyStateCmd { + pas::EStepDirection x8_dir = pas::EStepDirection::Invalid; + pas::EStepType xc_type = pas::EStepType::Normal; + public: - CBCStepCmd() : CBodyStateCmd(EBodyStateCmd::Step) {} - CBCStepCmd(pas::EStepDirection dir, pas::EStepType type) - : CBodyStateCmd(EBodyStateCmd::Step), x8_dir(dir), xc_type(type) {} - pas::EStepDirection GetStepDirection() const { return x8_dir; } - pas::EStepType GetStepType() const { return xc_type; } + CBCStepCmd() : CBodyStateCmd(EBodyStateCmd::Step) {} + CBCStepCmd(pas::EStepDirection dir, pas::EStepType type) + : CBodyStateCmd(EBodyStateCmd::Step), x8_dir(dir), xc_type(type) {} + pas::EStepDirection GetStepDirection() const { return x8_dir; } + pas::EStepType GetStepType() const { return xc_type; } }; -class CBCJumpCmd : public CBodyStateCmd -{ - pas::EJumpType x8_type = pas::EJumpType::Normal; - zeus::CVector3f xc_waypoint1; - zeus::CVector3f x18_waypoint2; - bool x24_24_wallJump : 1; - bool x24_25_startInJumpLoop : 1; +class CBCJumpCmd : public CBodyStateCmd { + pas::EJumpType x8_type = pas::EJumpType::Normal; + zeus::CVector3f xc_waypoint1; + zeus::CVector3f x18_waypoint2; + bool x24_24_wallJump : 1; + bool x24_25_startInJumpLoop : 1; + public: - CBCJumpCmd() - : CBodyStateCmd(EBodyStateCmd::Jump) { x24_24_wallJump = false; x24_25_startInJumpLoop = false; } - CBCJumpCmd(const zeus::CVector3f& wp1, pas::EJumpType type, bool startInLoop = false) - : CBodyStateCmd(EBodyStateCmd::Jump), x8_type(type), xc_waypoint1(wp1) - { x24_24_wallJump = false; x24_25_startInJumpLoop = startInLoop; } - CBCJumpCmd(const zeus::CVector3f& wp1, const zeus::CVector3f& wp2, pas::EJumpType type) - : CBodyStateCmd(EBodyStateCmd::Jump), x8_type(type), xc_waypoint1(wp1), x18_waypoint2(wp2) - { x24_24_wallJump = true; x24_25_startInJumpLoop = false; } - pas::EJumpType GetJumpType() const { return x8_type; } - const zeus::CVector3f& GetJumpTarget() const { return xc_waypoint1; } - const zeus::CVector3f& GetSecondJumpTarget() const { return x18_waypoint2; } - bool IsWallJump() const { return x24_24_wallJump; } - bool StartInJumpLoop() const { return x24_25_startInJumpLoop; } + CBCJumpCmd() : CBodyStateCmd(EBodyStateCmd::Jump) { + x24_24_wallJump = false; + x24_25_startInJumpLoop = false; + } + CBCJumpCmd(const zeus::CVector3f& wp1, pas::EJumpType type, bool startInLoop = false) + : CBodyStateCmd(EBodyStateCmd::Jump), x8_type(type), xc_waypoint1(wp1) { + x24_24_wallJump = false; + x24_25_startInJumpLoop = startInLoop; + } + CBCJumpCmd(const zeus::CVector3f& wp1, const zeus::CVector3f& wp2, pas::EJumpType type) + : CBodyStateCmd(EBodyStateCmd::Jump), x8_type(type), xc_waypoint1(wp1), x18_waypoint2(wp2) { + x24_24_wallJump = true; + x24_25_startInJumpLoop = false; + } + pas::EJumpType GetJumpType() const { return x8_type; } + const zeus::CVector3f& GetJumpTarget() const { return xc_waypoint1; } + const zeus::CVector3f& GetSecondJumpTarget() const { return x18_waypoint2; } + bool IsWallJump() const { return x24_24_wallJump; } + bool StartInJumpLoop() const { return x24_25_startInJumpLoop; } }; -class CBCGenerateCmd : public CBodyStateCmd -{ - pas::EGenerateType x8_type = pas::EGenerateType::Invalid; - zeus::CVector3f xc_targetPos; - s32 x18_animId = -1; - bool x1c_24_targetTransform : 1; - bool x1c_25_overrideAnim : 1; +class CBCGenerateCmd : public CBodyStateCmd { + pas::EGenerateType x8_type = pas::EGenerateType::Invalid; + zeus::CVector3f xc_targetPos; + s32 x18_animId = -1; + bool x1c_24_targetTransform : 1; + bool x1c_25_overrideAnim : 1; + public: - CBCGenerateCmd() : CBodyStateCmd(EBodyStateCmd::Generate) { x1c_24_targetTransform = false; x1c_25_overrideAnim = false; } - CBCGenerateCmd(pas::EGenerateType type, s32 animId = -1) - : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), x18_animId(animId) - { x1c_24_targetTransform = false; x1c_25_overrideAnim = false; } - CBCGenerateCmd(pas::EGenerateType type, const zeus::CVector3f& vec, bool targetTransform = false, bool overrideAnim = false) - : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), xc_targetPos(vec) - { x1c_24_targetTransform = targetTransform; x1c_25_overrideAnim = overrideAnim; } - pas::EGenerateType GetGenerateType() const { return x8_type; } - const zeus::CVector3f& GetExitTargetPos() const { return xc_targetPos; } - bool HasExitTargetPos() const { return x1c_24_targetTransform; } - s32 GetSpecialAnimId() const { return x18_animId; } - bool UseSpecialAnimId() const { return x1c_25_overrideAnim; } + CBCGenerateCmd() : CBodyStateCmd(EBodyStateCmd::Generate) { + x1c_24_targetTransform = false; + x1c_25_overrideAnim = false; + } + CBCGenerateCmd(pas::EGenerateType type, s32 animId = -1) + : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), x18_animId(animId) { + x1c_24_targetTransform = false; + x1c_25_overrideAnim = false; + } + CBCGenerateCmd(pas::EGenerateType type, const zeus::CVector3f& vec, bool targetTransform = false, + bool overrideAnim = false) + : CBodyStateCmd(EBodyStateCmd::Generate), x8_type(type), xc_targetPos(vec) { + x1c_24_targetTransform = targetTransform; + x1c_25_overrideAnim = overrideAnim; + } + pas::EGenerateType GetGenerateType() const { return x8_type; } + const zeus::CVector3f& GetExitTargetPos() const { return xc_targetPos; } + bool HasExitTargetPos() const { return x1c_24_targetTransform; } + s32 GetSpecialAnimId() const { return x18_animId; } + bool UseSpecialAnimId() const { return x1c_25_overrideAnim; } }; -class CBCKnockBackCmd : public CBodyStateCmd -{ - zeus::CVector3f x8_dir; - pas::ESeverity x14_severity = pas::ESeverity::Invalid; +class CBCKnockBackCmd : public CBodyStateCmd { + zeus::CVector3f x8_dir; + pas::ESeverity x14_severity = pas::ESeverity::Invalid; + public: - CBCKnockBackCmd() : CBodyStateCmd(EBodyStateCmd::KnockBack) {} - CBCKnockBackCmd(const zeus::CVector3f& vec, pas::ESeverity severity) - : CBodyStateCmd(EBodyStateCmd::KnockBack), x8_dir(vec), x14_severity(severity) {} - const zeus::CVector3f& GetHitDirection() const { return x8_dir; } - pas::ESeverity GetHitSeverity() const { return x14_severity; } + CBCKnockBackCmd() : CBodyStateCmd(EBodyStateCmd::KnockBack) {} + CBCKnockBackCmd(const zeus::CVector3f& vec, pas::ESeverity severity) + : CBodyStateCmd(EBodyStateCmd::KnockBack), x8_dir(vec), x14_severity(severity) {} + const zeus::CVector3f& GetHitDirection() const { return x8_dir; } + pas::ESeverity GetHitSeverity() const { return x14_severity; } }; -class CBCHurledCmd : public CBodyStateCmd -{ - zeus::CVector3f x8_direction; - zeus::CVector3f x14_launchVel; - bool x20_startInKnockLoop = false; +class CBCHurledCmd : public CBodyStateCmd { + zeus::CVector3f x8_direction; + zeus::CVector3f x14_launchVel; + bool x20_startInKnockLoop = false; + public: - CBCHurledCmd() : CBodyStateCmd(EBodyStateCmd::Hurled) {} - CBCHurledCmd(const zeus::CVector3f& dir, const zeus::CVector3f& launchVel, - bool startInLoop = false) - : CBodyStateCmd(EBodyStateCmd::Hurled), x8_direction(dir), x14_launchVel(launchVel), - x20_startInKnockLoop(startInLoop) {} - const zeus::CVector3f& GetHitDirection() const { return x8_direction; } - const zeus::CVector3f& GetLaunchVelocity() const { return x14_launchVel; } - bool GetSkipLaunchState() const { return x20_startInKnockLoop; } - void SetSkipLaunchState(bool s) { x20_startInKnockLoop = s; } + CBCHurledCmd() : CBodyStateCmd(EBodyStateCmd::Hurled) {} + CBCHurledCmd(const zeus::CVector3f& dir, const zeus::CVector3f& launchVel, bool startInLoop = false) + : CBodyStateCmd(EBodyStateCmd::Hurled) + , x8_direction(dir) + , x14_launchVel(launchVel) + , x20_startInKnockLoop(startInLoop) {} + const zeus::CVector3f& GetHitDirection() const { return x8_direction; } + const zeus::CVector3f& GetLaunchVelocity() const { return x14_launchVel; } + bool GetSkipLaunchState() const { return x20_startInKnockLoop; } + void SetSkipLaunchState(bool s) { x20_startInKnockLoop = s; } }; -class CBCGetupCmd : public CBodyStateCmd -{ - pas::EGetupType x8_type = pas::EGetupType::Invalid; +class CBCGetupCmd : public CBodyStateCmd { + pas::EGetupType x8_type = pas::EGetupType::Invalid; + public: - CBCGetupCmd() : CBodyStateCmd(EBodyStateCmd::Getup) {} - CBCGetupCmd(pas::EGetupType type) - : CBodyStateCmd(EBodyStateCmd::Getup), x8_type(type) {} - pas::EGetupType GetGetupType() const { return x8_type; } + CBCGetupCmd() : CBodyStateCmd(EBodyStateCmd::Getup) {} + CBCGetupCmd(pas::EGetupType type) : CBodyStateCmd(EBodyStateCmd::Getup), x8_type(type) {} + pas::EGetupType GetGetupType() const { return x8_type; } }; -class CBCLoopReactionCmd : public CBodyStateCmd -{ - pas::EReactionType x8_type = pas::EReactionType::Invalid; +class CBCLoopReactionCmd : public CBodyStateCmd { + pas::EReactionType x8_type = pas::EReactionType::Invalid; + public: - CBCLoopReactionCmd() : CBodyStateCmd(EBodyStateCmd::LoopReaction) {} - CBCLoopReactionCmd(pas::EReactionType type) - : CBodyStateCmd(EBodyStateCmd::LoopReaction), x8_type(type) {} - pas::EReactionType GetReactionType() const { return x8_type; } + CBCLoopReactionCmd() : CBodyStateCmd(EBodyStateCmd::LoopReaction) {} + CBCLoopReactionCmd(pas::EReactionType type) : CBodyStateCmd(EBodyStateCmd::LoopReaction), x8_type(type) {} + pas::EReactionType GetReactionType() const { return x8_type; } }; -class CBCLoopHitReactionCmd : public CBodyStateCmd -{ - pas::EReactionType x8_type = pas::EReactionType::Invalid; +class CBCLoopHitReactionCmd : public CBodyStateCmd { + pas::EReactionType x8_type = pas::EReactionType::Invalid; + public: - CBCLoopHitReactionCmd() : CBodyStateCmd(EBodyStateCmd::LoopHitReaction) {} - CBCLoopHitReactionCmd(pas::EReactionType type) - : CBodyStateCmd(EBodyStateCmd::LoopHitReaction), x8_type(type) {} - pas::EReactionType GetReactionType() const { return x8_type; } + CBCLoopHitReactionCmd() : CBodyStateCmd(EBodyStateCmd::LoopHitReaction) {} + CBCLoopHitReactionCmd(pas::EReactionType type) : CBodyStateCmd(EBodyStateCmd::LoopHitReaction), x8_type(type) {} + pas::EReactionType GetReactionType() const { return x8_type; } }; -class CBCKnockDownCmd : public CBodyStateCmd -{ - zeus::CVector3f x8_dir; - pas::ESeverity x14_severity = pas::ESeverity::Invalid; +class CBCKnockDownCmd : public CBodyStateCmd { + zeus::CVector3f x8_dir; + pas::ESeverity x14_severity = pas::ESeverity::Invalid; + public: - CBCKnockDownCmd() : CBodyStateCmd(EBodyStateCmd::KnockDown) {} - CBCKnockDownCmd(const zeus::CVector3f& vec, pas::ESeverity severity) - : CBodyStateCmd(EBodyStateCmd::KnockDown), x8_dir(vec), x14_severity(severity) {} - const zeus::CVector3f& GetHitDirection() const { return x8_dir; } - pas::ESeverity GetHitSeverity() const { return x14_severity; } + CBCKnockDownCmd() : CBodyStateCmd(EBodyStateCmd::KnockDown) {} + CBCKnockDownCmd(const zeus::CVector3f& vec, pas::ESeverity severity) + : CBodyStateCmd(EBodyStateCmd::KnockDown), x8_dir(vec), x14_severity(severity) {} + const zeus::CVector3f& GetHitDirection() const { return x8_dir; } + pas::ESeverity GetHitSeverity() const { return x14_severity; } }; -class CBCSlideCmd : public CBodyStateCmd -{ - pas::ESlideType x8_type = pas::ESlideType::Invalid; - zeus::CVector3f xc_dir; +class CBCSlideCmd : public CBodyStateCmd { + pas::ESlideType x8_type = pas::ESlideType::Invalid; + zeus::CVector3f xc_dir; + public: - CBCSlideCmd() : CBodyStateCmd(EBodyStateCmd::Slide) {} - CBCSlideCmd(pas::ESlideType type, const zeus::CVector3f& dir) - : CBodyStateCmd(EBodyStateCmd::Slide), x8_type(type), xc_dir(dir) {} - pas::ESlideType GetSlideType() const { return x8_type; } - const zeus::CVector3f& GetSlideDirection() const { return xc_dir; } + CBCSlideCmd() : CBodyStateCmd(EBodyStateCmd::Slide) {} + CBCSlideCmd(pas::ESlideType type, const zeus::CVector3f& dir) + : CBodyStateCmd(EBodyStateCmd::Slide), x8_type(type), xc_dir(dir) {} + pas::ESlideType GetSlideType() const { return x8_type; } + const zeus::CVector3f& GetSlideDirection() const { return xc_dir; } }; -class CBCScriptedCmd : public CBodyStateCmd -{ - s32 x8_anim = -1; - bool xc_24_loopAnim : 1; - bool xc_25_timedLoop : 1; - float x10_loopDur = 0.f; +class CBCScriptedCmd : public CBodyStateCmd { + s32 x8_anim = -1; + bool xc_24_loopAnim : 1; + bool xc_25_timedLoop : 1; + float x10_loopDur = 0.f; + public: - CBCScriptedCmd() : CBodyStateCmd(EBodyStateCmd::Scripted) - { xc_24_loopAnim = false; xc_25_timedLoop = false; } - CBCScriptedCmd(int i, bool b1, bool b2, float f) - : CBodyStateCmd(EBodyStateCmd::Scripted), - x8_anim(i), x10_loopDur(f) { xc_24_loopAnim = b1; xc_25_timedLoop = b2; } - s32 GetAnimId() const { return x8_anim; } - bool IsLooped() const { return xc_24_loopAnim; } - bool GetUseLoopDuration() const { return xc_25_timedLoop; } - float GetLoopDuration() const { return x10_loopDur; } + CBCScriptedCmd() : CBodyStateCmd(EBodyStateCmd::Scripted) { + xc_24_loopAnim = false; + xc_25_timedLoop = false; + } + CBCScriptedCmd(int i, bool b1, bool b2, float f) + : CBodyStateCmd(EBodyStateCmd::Scripted), x8_anim(i), x10_loopDur(f) { + xc_24_loopAnim = b1; + xc_25_timedLoop = b2; + } + s32 GetAnimId() const { return x8_anim; } + bool IsLooped() const { return xc_24_loopAnim; } + bool GetUseLoopDuration() const { return xc_25_timedLoop; } + float GetLoopDuration() const { return x10_loopDur; } }; -class CBCCoverCmd : public CBodyStateCmd -{ - pas::ECoverDirection x8_dir = pas::ECoverDirection::Invalid; - zeus::CVector3f xc_targetPos; - zeus::CVector3f x18_alignDir; +class CBCCoverCmd : public CBodyStateCmd { + pas::ECoverDirection x8_dir = pas::ECoverDirection::Invalid; + zeus::CVector3f xc_targetPos; + zeus::CVector3f x18_alignDir; + public: - CBCCoverCmd() : CBodyStateCmd(EBodyStateCmd::Cover) {} - CBCCoverCmd(pas::ECoverDirection dir, const zeus::CVector3f& v1, const zeus::CVector3f& v2) : - CBodyStateCmd(EBodyStateCmd::Cover), x8_dir(dir), xc_targetPos(v1), x18_alignDir(v2) {} - pas::ECoverDirection GetDirection() const { return x8_dir; } - const zeus::CVector3f& GetTarget() const { return xc_targetPos; } - const zeus::CVector3f& GetAlignDirection() const { return x18_alignDir; } + CBCCoverCmd() : CBodyStateCmd(EBodyStateCmd::Cover) {} + CBCCoverCmd(pas::ECoverDirection dir, const zeus::CVector3f& v1, const zeus::CVector3f& v2) + : CBodyStateCmd(EBodyStateCmd::Cover), x8_dir(dir), xc_targetPos(v1), x18_alignDir(v2) {} + pas::ECoverDirection GetDirection() const { return x8_dir; } + const zeus::CVector3f& GetTarget() const { return xc_targetPos; } + const zeus::CVector3f& GetAlignDirection() const { return x18_alignDir; } }; -class CBCWallHangCmd : public CBodyStateCmd -{ - TUniqueId x8_wpId = kInvalidUniqueId; +class CBCWallHangCmd : public CBodyStateCmd { + TUniqueId x8_wpId = kInvalidUniqueId; + public: - CBCWallHangCmd() : CBodyStateCmd(EBodyStateCmd::WallHang) {} - CBCWallHangCmd(TUniqueId uid) : - CBodyStateCmd(EBodyStateCmd::WallHang), x8_wpId(uid) {} - TUniqueId GetTarget() const { return x8_wpId; } + CBCWallHangCmd() : CBodyStateCmd(EBodyStateCmd::WallHang) {} + CBCWallHangCmd(TUniqueId uid) : CBodyStateCmd(EBodyStateCmd::WallHang), x8_wpId(uid) {} + TUniqueId GetTarget() const { return x8_wpId; } }; -class CBCAdditiveAimCmd : public CBodyStateCmd -{ +class CBCAdditiveAimCmd : public CBodyStateCmd { public: - CBCAdditiveAimCmd() : CBodyStateCmd(EBodyStateCmd::AdditiveAim) {} + CBCAdditiveAimCmd() : CBodyStateCmd(EBodyStateCmd::AdditiveAim) {} }; -class CBCAdditiveFlinchCmd : public CBodyStateCmd -{ - float x8_weight = 1.f; +class CBCAdditiveFlinchCmd : public CBodyStateCmd { + float x8_weight = 1.f; + public: - CBCAdditiveFlinchCmd() : CBodyStateCmd(EBodyStateCmd::AdditiveFlinch) {} - CBCAdditiveFlinchCmd(float f) : CBodyStateCmd(EBodyStateCmd::AdditiveFlinch), x8_weight(f) {} - float GetWeight() const { return x8_weight; } + CBCAdditiveFlinchCmd() : CBodyStateCmd(EBodyStateCmd::AdditiveFlinch) {} + CBCAdditiveFlinchCmd(float f) : CBodyStateCmd(EBodyStateCmd::AdditiveFlinch), x8_weight(f) {} + float GetWeight() const { return x8_weight; } }; -class CBCAdditiveReactionCmd : public CBodyStateCmd -{ - float x8_weight = 1.f; - pas::EAdditiveReactionType xc_type = pas::EAdditiveReactionType::Invalid; - bool x10_active = false; +class CBCAdditiveReactionCmd : public CBodyStateCmd { + float x8_weight = 1.f; + pas::EAdditiveReactionType xc_type = pas::EAdditiveReactionType::Invalid; + bool x10_active = false; + public: - CBCAdditiveReactionCmd() : CBodyStateCmd(EBodyStateCmd::AdditiveReaction) {} - CBCAdditiveReactionCmd(pas::EAdditiveReactionType type, float f, bool active) - : CBodyStateCmd(EBodyStateCmd::AdditiveReaction), x8_weight(f), - xc_type(type), x10_active(active) {} - pas::EAdditiveReactionType GetType() const { return xc_type; } - float GetWeight() const { return x8_weight; } - bool GetIsActive() const { return x10_active; } + CBCAdditiveReactionCmd() : CBodyStateCmd(EBodyStateCmd::AdditiveReaction) {} + CBCAdditiveReactionCmd(pas::EAdditiveReactionType type, float f, bool active) + : CBodyStateCmd(EBodyStateCmd::AdditiveReaction), x8_weight(f), xc_type(type), x10_active(active) {} + pas::EAdditiveReactionType GetType() const { return xc_type; } + float GetWeight() const { return x8_weight; } + bool GetIsActive() const { return x10_active; } }; -class CBCLoopAttackCmd : public CBodyStateCmd -{ - pas::ELoopAttackType x8_type = pas::ELoopAttackType::Invalid; - u32 xc_waitForAnimOver = 0; +class CBCLoopAttackCmd : public CBodyStateCmd { + pas::ELoopAttackType x8_type = pas::ELoopAttackType::Invalid; + u32 xc_waitForAnimOver = 0; + public: - CBCLoopAttackCmd() : CBodyStateCmd(EBodyStateCmd::LoopAttack) {} - CBCLoopAttackCmd(pas::ELoopAttackType type) - : CBodyStateCmd(EBodyStateCmd::LoopAttack), x8_type(type) {} - pas::ELoopAttackType GetAttackType() const { return x8_type; } - bool WaitForAnimOver() const { return xc_waitForAnimOver == 1; } + CBCLoopAttackCmd() : CBodyStateCmd(EBodyStateCmd::LoopAttack) {} + CBCLoopAttackCmd(pas::ELoopAttackType type) : CBodyStateCmd(EBodyStateCmd::LoopAttack), x8_type(type) {} + pas::ELoopAttackType GetAttackType() const { return x8_type; } + bool WaitForAnimOver() const { return xc_waitForAnimOver == 1; } }; -class CBCTauntCmd : public CBodyStateCmd -{ - pas::ETauntType x8_type = pas::ETauntType::Invalid; +class CBCTauntCmd : public CBodyStateCmd { + pas::ETauntType x8_type = pas::ETauntType::Invalid; + public: - CBCTauntCmd() : CBodyStateCmd(EBodyStateCmd::Taunt) {} - CBCTauntCmd(pas::ETauntType type) - : CBodyStateCmd(EBodyStateCmd::Taunt), x8_type(type) {} - pas::ETauntType GetTauntType() const { return x8_type; } + CBCTauntCmd() : CBodyStateCmd(EBodyStateCmd::Taunt) {} + CBCTauntCmd(pas::ETauntType type) : CBodyStateCmd(EBodyStateCmd::Taunt), x8_type(type) {} + pas::ETauntType GetTauntType() const { return x8_type; } }; -class CBCLocomotionCmd -{ - zeus::CVector3f x0_move; - zeus::CVector3f xc_face; - float x18_weight; +class CBCLocomotionCmd { + zeus::CVector3f x0_move; + zeus::CVector3f xc_face; + float x18_weight; + public: - CBCLocomotionCmd(const zeus::CVector3f& move, const zeus::CVector3f& face, float weight) - : x0_move(move), xc_face(face), x18_weight(weight) {} - const zeus::CVector3f& GetMoveVector() const { return x0_move; } - const zeus::CVector3f& GetFaceVector() const { return xc_face; } - float GetWeight() const { return x18_weight; } + CBCLocomotionCmd(const zeus::CVector3f& move, const zeus::CVector3f& face, float weight) + : x0_move(move), xc_face(face), x18_weight(weight) {} + const zeus::CVector3f& GetMoveVector() const { return x0_move; } + const zeus::CVector3f& GetFaceVector() const { return xc_face; } + float GetWeight() const { return x18_weight; } }; -enum class ESteeringBlendMode -{ - Normal, - FullSpeed, - Clamped -}; +enum class ESteeringBlendMode { Normal, FullSpeed, Clamped }; + +class CBodyStateCmdMgr { + zeus::CVector3f x0_move; + zeus::CVector3f xc_face; + zeus::CVector3f x18_target; + zeus::CVector3f x24_additiveTarget; + ESteeringBlendMode x30_steeringMode = ESteeringBlendMode::Normal; + float x34_steeringSpeedMin = 0.f; + float x38_steeringSpeedMax = 1.f; + float x3c_steeringSpeed = 0.f; + rstl::reserved_vector x40_commandTable; + u32 xb4_deliveredCmdMask = 0; + CBCGetupCmd xb8_getup; + CBCStepCmd xc4_step; + CBodyStateCmd xd4_ = {EBodyStateCmd::Die}; + CBCKnockDownCmd xdc_knockDown; + CBCKnockBackCmd xf4_knockBack; + CBCMeleeAttackCmd x10c_meleeAttack; + CBCProjectileAttackCmd x128_projectileAttack; + CBCLoopAttackCmd x144_loopAttack; + CBCLoopReactionCmd x154_loopReaction; + CBCLoopHitReactionCmd x160_loopHitReaction; + CBodyStateCmd x16c_ = {EBodyStateCmd::ExitState}; + CBodyStateCmd x174_ = {EBodyStateCmd::LeanFromCover}; + CBodyStateCmd x17c_ = {EBodyStateCmd::NextState}; + CBodyStateCmd x184_ = {EBodyStateCmd::MaintainVelocity}; + CBCGenerateCmd x18c_generate; + CBCHurledCmd x1ac_hurled; + CBCJumpCmd x1d0_jump; + CBCSlideCmd x1f8_slide; + CBCTauntCmd x210_taunt; + CBCScriptedCmd x21c_scripted; + CBCCoverCmd x230_cover; + CBCWallHangCmd x254_wallHang; + CBodyStateCmd x260_ = {EBodyStateCmd::Locomotion}; + CBodyStateCmd x268_ = {EBodyStateCmd::AdditiveIdle}; + CBCAdditiveAimCmd x270_additiveAim; + CBCAdditiveFlinchCmd x278_additiveFlinch; + CBCAdditiveReactionCmd x284_additiveReaction; + CBodyStateCmd x298_ = {EBodyStateCmd::StopReaction}; + void DeliverCmd(EBodyStateCmd cmd) { xb4_deliveredCmdMask |= (1 << int(cmd)); } -class CBodyStateCmdMgr -{ - zeus::CVector3f x0_move; - zeus::CVector3f xc_face; - zeus::CVector3f x18_target; - zeus::CVector3f x24_additiveTarget; - ESteeringBlendMode x30_steeringMode = ESteeringBlendMode::Normal; - float x34_steeringSpeedMin = 0.f; - float x38_steeringSpeedMax = 1.f; - float x3c_steeringSpeed = 0.f; - rstl::reserved_vector x40_commandTable; - u32 xb4_deliveredCmdMask = 0; - CBCGetupCmd xb8_getup; - CBCStepCmd xc4_step; - CBodyStateCmd xd4_ = {EBodyStateCmd::Die}; - CBCKnockDownCmd xdc_knockDown; - CBCKnockBackCmd xf4_knockBack; - CBCMeleeAttackCmd x10c_meleeAttack; - CBCProjectileAttackCmd x128_projectileAttack; - CBCLoopAttackCmd x144_loopAttack; - CBCLoopReactionCmd x154_loopReaction; - CBCLoopHitReactionCmd x160_loopHitReaction; - CBodyStateCmd x16c_ = {EBodyStateCmd::ExitState}; - CBodyStateCmd x174_ = {EBodyStateCmd::LeanFromCover}; - CBodyStateCmd x17c_ = {EBodyStateCmd::NextState}; - CBodyStateCmd x184_ = {EBodyStateCmd::MaintainVelocity}; - CBCGenerateCmd x18c_generate; - CBCHurledCmd x1ac_hurled; - CBCJumpCmd x1d0_jump; - CBCSlideCmd x1f8_slide; - CBCTauntCmd x210_taunt; - CBCScriptedCmd x21c_scripted; - CBCCoverCmd x230_cover; - CBCWallHangCmd x254_wallHang; - CBodyStateCmd x260_ = {EBodyStateCmd::Locomotion}; - CBodyStateCmd x268_ = {EBodyStateCmd::AdditiveIdle}; - CBCAdditiveAimCmd x270_additiveAim; - CBCAdditiveFlinchCmd x278_additiveFlinch; - CBCAdditiveReactionCmd x284_additiveReaction; - CBodyStateCmd x298_ = {EBodyStateCmd::StopReaction}; - void DeliverCmd(EBodyStateCmd cmd) { xb4_deliveredCmdMask |= (1 << int(cmd)); } public: - CBodyStateCmdMgr(); - void DeliverCmd(const CBodyStateCmd& cmd) - { - *x40_commandTable[int(cmd.GetCommandId())] = cmd; - DeliverCmd(cmd.GetCommandId()); - } - void DeliverCmd(const CBCGetupCmd& cmd) - { - xb8_getup = cmd; - DeliverCmd(EBodyStateCmd::Getup); - } - void DeliverCmd(const CBCStepCmd& cmd) - { - xc4_step = cmd; - DeliverCmd(EBodyStateCmd::Step); - } - void DeliverCmd(const CBCKnockDownCmd& cmd) - { - xdc_knockDown = cmd; - DeliverCmd(EBodyStateCmd::KnockDown); - } - void DeliverCmd(const CBCKnockBackCmd& cmd) - { - xf4_knockBack = cmd; - DeliverCmd(EBodyStateCmd::KnockBack); - } - void DeliverCmd(const CBCMeleeAttackCmd& cmd) - { - x10c_meleeAttack = cmd; - DeliverCmd(EBodyStateCmd::MeleeAttack); - } - void DeliverCmd(const CBCProjectileAttackCmd& cmd) - { - x128_projectileAttack = cmd; - DeliverCmd(EBodyStateCmd::ProjectileAttack); - } - void DeliverCmd(const CBCLoopAttackCmd& cmd) - { - x144_loopAttack = cmd; - DeliverCmd(EBodyStateCmd::LoopAttack); - } - void DeliverCmd(const CBCLoopReactionCmd& cmd) - { - x154_loopReaction = cmd; - DeliverCmd(EBodyStateCmd::LoopReaction); - } - void DeliverCmd(const CBCLoopHitReactionCmd& cmd) - { - x160_loopHitReaction = cmd; - DeliverCmd(EBodyStateCmd::LoopHitReaction); - } - void DeliverCmd(const CBCGenerateCmd& cmd) - { - x18c_generate = cmd; - DeliverCmd(EBodyStateCmd::Generate); - } - void DeliverCmd(const CBCHurledCmd& cmd) - { - x1ac_hurled = cmd; - DeliverCmd(EBodyStateCmd::Hurled); - } - void DeliverCmd(const CBCJumpCmd& cmd) - { - x1d0_jump = cmd; - DeliverCmd(EBodyStateCmd::Jump); - } - void DeliverCmd(const CBCSlideCmd& cmd) - { - x1f8_slide = cmd; - DeliverCmd(EBodyStateCmd::Slide); - } - void DeliverCmd(const CBCTauntCmd& cmd) - { - x210_taunt = cmd; - DeliverCmd(EBodyStateCmd::Taunt); - } - void DeliverCmd(const CBCScriptedCmd& cmd) - { - x21c_scripted = cmd; - DeliverCmd(EBodyStateCmd::Scripted); - } - void DeliverCmd(const CBCCoverCmd& cmd) - { - x230_cover = cmd; - DeliverCmd(EBodyStateCmd::Cover); - } - void DeliverCmd(const CBCWallHangCmd& cmd) - { - x254_wallHang = cmd; - DeliverCmd(EBodyStateCmd::WallHang); - } - void DeliverCmd(const CBCAdditiveAimCmd& cmd) - { - x270_additiveAim = cmd; - DeliverCmd(EBodyStateCmd::AdditiveAim); - } - void DeliverCmd(const CBCAdditiveFlinchCmd& cmd) - { - x278_additiveFlinch = cmd; - DeliverCmd(EBodyStateCmd::AdditiveFlinch); - } - void DeliverCmd(const CBCAdditiveReactionCmd& cmd) - { - x284_additiveReaction = cmd; - DeliverCmd(EBodyStateCmd::AdditiveReaction); - } - void DeliverCmd(const CBCLocomotionCmd& cmd); - void DeliverTargetVector(const zeus::CVector3f& t) { x18_target = t; } - void DeliverAdditiveTargetVector(const zeus::CVector3f& t) { x24_additiveTarget = t; } - void SetSteeringBlendSpeed(float s) { x3c_steeringSpeed = s; } - void SetSteeringBlendMode(ESteeringBlendMode m) { x30_steeringMode = m; } - void SetSteeringSpeedRange(float rmin, float rmax) - { x34_steeringSpeedMin = rmin; x38_steeringSpeedMax = rmax; } - void BlendSteeringCmds(); - void Reset(); - void ClearLocomotionCmds(); - const CBodyStateCmd* GetCmd(EBodyStateCmd cmd) const - { - if (xb4_deliveredCmdMask & (1 << int(cmd))) - return x40_commandTable[int(cmd)]; - return nullptr; - } - const zeus::CVector3f& GetMoveVector() const { return x0_move; } - const zeus::CVector3f& GetFaceVector() const { return xc_face; } - const zeus::CVector3f& GetTargetVector() const { return x18_target; } - void SetTargetVector(const zeus::CVector3f& target) { x18_target = target; } - const zeus::CVector3f& GetAdditiveTargetVector() const { return x24_additiveTarget; } + CBodyStateCmdMgr(); + void DeliverCmd(const CBodyStateCmd& cmd) { + *x40_commandTable[int(cmd.GetCommandId())] = cmd; + DeliverCmd(cmd.GetCommandId()); + } + void DeliverCmd(const CBCGetupCmd& cmd) { + xb8_getup = cmd; + DeliverCmd(EBodyStateCmd::Getup); + } + void DeliverCmd(const CBCStepCmd& cmd) { + xc4_step = cmd; + DeliverCmd(EBodyStateCmd::Step); + } + void DeliverCmd(const CBCKnockDownCmd& cmd) { + xdc_knockDown = cmd; + DeliverCmd(EBodyStateCmd::KnockDown); + } + void DeliverCmd(const CBCKnockBackCmd& cmd) { + xf4_knockBack = cmd; + DeliverCmd(EBodyStateCmd::KnockBack); + } + void DeliverCmd(const CBCMeleeAttackCmd& cmd) { + x10c_meleeAttack = cmd; + DeliverCmd(EBodyStateCmd::MeleeAttack); + } + void DeliverCmd(const CBCProjectileAttackCmd& cmd) { + x128_projectileAttack = cmd; + DeliverCmd(EBodyStateCmd::ProjectileAttack); + } + void DeliverCmd(const CBCLoopAttackCmd& cmd) { + x144_loopAttack = cmd; + DeliverCmd(EBodyStateCmd::LoopAttack); + } + void DeliverCmd(const CBCLoopReactionCmd& cmd) { + x154_loopReaction = cmd; + DeliverCmd(EBodyStateCmd::LoopReaction); + } + void DeliverCmd(const CBCLoopHitReactionCmd& cmd) { + x160_loopHitReaction = cmd; + DeliverCmd(EBodyStateCmd::LoopHitReaction); + } + void DeliverCmd(const CBCGenerateCmd& cmd) { + x18c_generate = cmd; + DeliverCmd(EBodyStateCmd::Generate); + } + void DeliverCmd(const CBCHurledCmd& cmd) { + x1ac_hurled = cmd; + DeliverCmd(EBodyStateCmd::Hurled); + } + void DeliverCmd(const CBCJumpCmd& cmd) { + x1d0_jump = cmd; + DeliverCmd(EBodyStateCmd::Jump); + } + void DeliverCmd(const CBCSlideCmd& cmd) { + x1f8_slide = cmd; + DeliverCmd(EBodyStateCmd::Slide); + } + void DeliverCmd(const CBCTauntCmd& cmd) { + x210_taunt = cmd; + DeliverCmd(EBodyStateCmd::Taunt); + } + void DeliverCmd(const CBCScriptedCmd& cmd) { + x21c_scripted = cmd; + DeliverCmd(EBodyStateCmd::Scripted); + } + void DeliverCmd(const CBCCoverCmd& cmd) { + x230_cover = cmd; + DeliverCmd(EBodyStateCmd::Cover); + } + void DeliverCmd(const CBCWallHangCmd& cmd) { + x254_wallHang = cmd; + DeliverCmd(EBodyStateCmd::WallHang); + } + void DeliverCmd(const CBCAdditiveAimCmd& cmd) { + x270_additiveAim = cmd; + DeliverCmd(EBodyStateCmd::AdditiveAim); + } + void DeliverCmd(const CBCAdditiveFlinchCmd& cmd) { + x278_additiveFlinch = cmd; + DeliverCmd(EBodyStateCmd::AdditiveFlinch); + } + void DeliverCmd(const CBCAdditiveReactionCmd& cmd) { + x284_additiveReaction = cmd; + DeliverCmd(EBodyStateCmd::AdditiveReaction); + } + void DeliverCmd(const CBCLocomotionCmd& cmd); + void DeliverTargetVector(const zeus::CVector3f& t) { x18_target = t; } + void DeliverAdditiveTargetVector(const zeus::CVector3f& t) { x24_additiveTarget = t; } + void SetSteeringBlendSpeed(float s) { x3c_steeringSpeed = s; } + void SetSteeringBlendMode(ESteeringBlendMode m) { x30_steeringMode = m; } + void SetSteeringSpeedRange(float rmin, float rmax) { + x34_steeringSpeedMin = rmin; + x38_steeringSpeedMax = rmax; + } + void BlendSteeringCmds(); + void Reset(); + void ClearLocomotionCmds(); + const CBodyStateCmd* GetCmd(EBodyStateCmd cmd) const { + if (xb4_deliveredCmdMask & (1 << int(cmd))) + return x40_commandTable[int(cmd)]; + return nullptr; + } + const zeus::CVector3f& GetMoveVector() const { return x0_move; } + const zeus::CVector3f& GetFaceVector() const { return xc_face; } + const zeus::CVector3f& GetTargetVector() const { return x18_target; } + void SetTargetVector(const zeus::CVector3f& target) { x18_target = target; } + const zeus::CVector3f& GetAdditiveTargetVector() const { return x24_additiveTarget; } }; -} +} // namespace urde diff --git a/Runtime/Character/CBodyStateInfo.cpp b/Runtime/Character/CBodyStateInfo.cpp index 59ea3adc7..d9fdfb335 100644 --- a/Runtime/Character/CBodyStateInfo.cpp +++ b/Runtime/Character/CBodyStateInfo.cpp @@ -2,468 +2,435 @@ #include "World/CActor.hpp" #include "CBodyController.hpp" -namespace urde -{ +namespace urde { -CBodyStateInfo::CBodyStateInfo(CActor& actor, EBodyType type) -{ - x34_24_changeLocoAtEndOfAnimOnly = false; - const CPASDatabase& pasDatabase = - actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); - for (int i=0 ; i bs; +CBodyStateInfo::CBodyStateInfo(CActor& actor, EBodyType type) { + x34_24_changeLocoAtEndOfAnimOnly = false; + const CPASDatabase& pasDatabase = actor.GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase(); + for (int i = 0; i < pasDatabase.GetNumAnimStates(); ++i) { + const CPASAnimState* state = pasDatabase.GetAnimStateByIndex(i); + std::unique_ptr bs; - switch (type) - { - case EBodyType::BiPedal: - bs = SetupBiPedalBodyStates(state->GetStateId(), actor); - break; - case EBodyType::Restricted: - default: - bs = SetupRestrictedBodyStates(state->GetStateId(), actor); - break; - case EBodyType::Flyer: - bs = SetupFlyerBodyStates(state->GetStateId(), actor); - break; - case EBodyType::Pitchable: - bs = SetupPitchableBodyStates(state->GetStateId(), actor); - break; - case EBodyType::WallWalker: - bs = SetupWallWalkerBodyStates(state->GetStateId(), actor); - break; - case EBodyType::NewFlyer: - bs = SetupNewFlyerBodyStates(state->GetStateId(), actor); - break; - case EBodyType::RestrictedFlyer: - bs = SetupRestrictedFlyerBodyStates(state->GetStateId(), actor); - break; - } - - if (bs) - x0_stateMap[pas::EAnimationState(state->GetStateId())] = std::move(bs); - } - - x1c_additiveStates.reserve(4); - x1c_additiveStates.push_back({pas::EAnimationState::AdditiveIdle, std::make_unique()}); - x1c_additiveStates.push_back({pas::EAnimationState::AdditiveAim, std::make_unique()}); - x1c_additiveStates.push_back({pas::EAnimationState::AdditiveFlinch, std::make_unique()}); - x1c_additiveStates.push_back({pas::EAnimationState::AdditiveReaction, std::make_unique()}); -} - -std::unique_ptr CBodyStateInfo::SetupRestrictedFlyerBodyStates(int stateId, CActor& actor) -{ - switch (stateId) - { - case 0: - return std::make_unique(); - case 1: - return std::make_unique(); - case 2: - return std::make_unique(actor); - case 3: - return std::make_unique(); - case 4: - return std::make_unique(); - case 5: - return std::make_unique(actor); - case 6: - return std::make_unique(); - case 7: - return std::make_unique(); - case 18: - return std::make_unique(); - case 9: - return std::make_unique(); - case 8: - return std::make_unique(); - case 10: - return std::make_unique(); - case 11: - return std::make_unique(); - case 12: - return std::make_unique(); - case 13: - return std::make_unique(); - case 14: - return std::make_unique(); - case 15: - return std::make_unique(); - case 16: - return std::make_unique(); - case 17: - return std::make_unique(); + switch (type) { + case EBodyType::BiPedal: + bs = SetupBiPedalBodyStates(state->GetStateId(), actor); + break; + case EBodyType::Restricted: default: - return {}; + bs = SetupRestrictedBodyStates(state->GetStateId(), actor); + break; + case EBodyType::Flyer: + bs = SetupFlyerBodyStates(state->GetStateId(), actor); + break; + case EBodyType::Pitchable: + bs = SetupPitchableBodyStates(state->GetStateId(), actor); + break; + case EBodyType::WallWalker: + bs = SetupWallWalkerBodyStates(state->GetStateId(), actor); + break; + case EBodyType::NewFlyer: + bs = SetupNewFlyerBodyStates(state->GetStateId(), actor); + break; + case EBodyType::RestrictedFlyer: + bs = SetupRestrictedFlyerBodyStates(state->GetStateId(), actor); + break; } + + if (bs) + x0_stateMap[pas::EAnimationState(state->GetStateId())] = std::move(bs); + } + + x1c_additiveStates.reserve(4); + x1c_additiveStates.push_back({pas::EAnimationState::AdditiveIdle, std::make_unique()}); + x1c_additiveStates.push_back({pas::EAnimationState::AdditiveAim, std::make_unique()}); + x1c_additiveStates.push_back({pas::EAnimationState::AdditiveFlinch, std::make_unique()}); + x1c_additiveStates.push_back({pas::EAnimationState::AdditiveReaction, std::make_unique()}); } -std::unique_ptr CBodyStateInfo::SetupNewFlyerBodyStates(int stateId, CActor& actor) -{ - switch (stateId) - { - case 0: - return std::make_unique(); - case 1: - return std::make_unique(); - case 2: - return std::make_unique(actor); - case 3: - return std::make_unique(); - case 4: - return std::make_unique(); - case 5: - return std::make_unique(actor); - case 6: - return std::make_unique(); - case 7: - return std::make_unique(); - case 18: - return std::make_unique(); - case 9: - return std::make_unique(); - case 8: - return std::make_unique(); - case 10: - return std::make_unique(); - case 11: - return std::make_unique(); - case 12: - return std::make_unique(); - case 13: - return std::make_unique(); - case 14: - return std::make_unique(); - case 15: - return std::make_unique(); - case 16: - return std::make_unique(); - case 17: - return std::make_unique(); - default: - return {}; +std::unique_ptr CBodyStateInfo::SetupRestrictedFlyerBodyStates(int stateId, CActor& actor) { + switch (stateId) { + case 0: + return std::make_unique(); + case 1: + return std::make_unique(); + case 2: + return std::make_unique(actor); + case 3: + return std::make_unique(); + case 4: + return std::make_unique(); + case 5: + return std::make_unique(actor); + case 6: + return std::make_unique(); + case 7: + return std::make_unique(); + case 18: + return std::make_unique(); + case 9: + return std::make_unique(); + case 8: + return std::make_unique(); + case 10: + return std::make_unique(); + case 11: + return std::make_unique(); + case 12: + return std::make_unique(); + case 13: + return std::make_unique(); + case 14: + return std::make_unique(); + case 15: + return std::make_unique(); + case 16: + return std::make_unique(); + case 17: + return std::make_unique(); + default: + return {}; + } +} + +std::unique_ptr CBodyStateInfo::SetupNewFlyerBodyStates(int stateId, CActor& actor) { + switch (stateId) { + case 0: + return std::make_unique(); + case 1: + return std::make_unique(); + case 2: + return std::make_unique(actor); + case 3: + return std::make_unique(); + case 4: + return std::make_unique(); + case 5: + return std::make_unique(actor); + case 6: + return std::make_unique(); + case 7: + return std::make_unique(); + case 18: + return std::make_unique(); + case 9: + return std::make_unique(); + case 8: + return std::make_unique(); + case 10: + return std::make_unique(); + case 11: + return std::make_unique(); + case 12: + return std::make_unique(); + case 13: + return std::make_unique(); + case 14: + return std::make_unique(); + case 15: + return std::make_unique(); + case 16: + return std::make_unique(); + case 17: + return std::make_unique(); + default: + return {}; + } +} + +std::unique_ptr CBodyStateInfo::SetupWallWalkerBodyStates(int stateId, CActor& actor) { + switch (stateId) { + case 0: + return std::make_unique(); + case 1: + return std::make_unique(); + case 2: + return std::make_unique(actor); + case 3: + return std::make_unique(); + case 4: + return std::make_unique(); + case 5: + return std::make_unique(actor); + case 6: + return std::make_unique(); + case 7: + return std::make_unique(); + case 18: + return std::make_unique(); + case 9: + return std::make_unique(); + case 8: + return std::make_unique(); + case 10: + return std::make_unique(); + case 11: + return std::make_unique(); + case 12: + return std::make_unique(); + case 13: + return std::make_unique(); + case 14: + return std::make_unique(); + case 15: + return std::make_unique(); + case 16: + return std::make_unique(); + case 17: + return std::make_unique(); + default: + return {}; + } +} + +std::unique_ptr CBodyStateInfo::SetupPitchableBodyStates(int stateId, CActor& actor) { + switch (stateId) { + case 0: + return std::make_unique(); + case 1: + return std::make_unique(); + case 2: + return std::make_unique(actor); + case 3: + return std::make_unique(); + case 4: + return std::make_unique(); + case 5: + return std::make_unique(actor, true); + case 6: + return std::make_unique(); + case 7: + return std::make_unique(); + case 18: + return std::make_unique(); + case 9: + return std::make_unique(); + case 8: + return std::make_unique(); + case 10: + return std::make_unique(); + case 11: + return std::make_unique(); + case 12: + return std::make_unique(); + case 13: + return std::make_unique(); + case 14: + return std::make_unique(); + case 15: + return std::make_unique(); + case 16: + return std::make_unique(); + case 17: + return std::make_unique(); + default: + return {}; + } +} + +std::unique_ptr CBodyStateInfo::SetupFlyerBodyStates(int stateId, CActor& actor) { + switch (stateId) { + case 0: + return std::make_unique(); + case 1: + return std::make_unique(); + case 2: + return std::make_unique(actor); + case 3: + return std::make_unique(); + case 4: + return std::make_unique(); + case 5: + return std::make_unique(actor, false); + case 6: + return std::make_unique(); + case 7: + return std::make_unique(); + case 18: + return std::make_unique(); + case 9: + return std::make_unique(); + case 8: + return std::make_unique(); + case 10: + return std::make_unique(); + case 11: + return std::make_unique(); + case 12: + return std::make_unique(); + case 13: + return std::make_unique(); + case 14: + return std::make_unique(); + case 15: + return std::make_unique(); + case 16: + return std::make_unique(); + case 17: + return std::make_unique(); + default: + return {}; + } +} + +std::unique_ptr CBodyStateInfo::SetupRestrictedBodyStates(int stateId, CActor& actor) { + switch (stateId) { + case 0: + return std::make_unique(); + case 1: + return std::make_unique(); + case 2: + return std::make_unique(actor); + case 3: + return std::make_unique(); + case 4: + return std::make_unique(); + case 5: + return std::make_unique(actor); + case 6: + return std::make_unique(); + case 7: + return std::make_unique(); + case 18: + return std::make_unique(); + case 9: + return std::make_unique(); + case 8: + return std::make_unique(); + case 10: + return std::make_unique(); + case 11: + return std::make_unique(); + case 12: + return std::make_unique(); + case 13: + return std::make_unique(); + case 14: + return std::make_unique(); + case 15: + return std::make_unique(); + case 16: + return std::make_unique(); + case 17: + return std::make_unique(); + case 19: + return std::make_unique(); + default: + return {}; + } +} + +std::unique_ptr CBodyStateInfo::SetupBiPedalBodyStates(int stateId, CActor& actor) { + switch (stateId) { + case 0: + return std::make_unique(); + case 1: + return std::make_unique(); + case 2: + return std::make_unique(actor); + case 3: + return std::make_unique(); + case 4: + return std::make_unique(); + case 5: + return std::make_unique(actor); + case 6: + return std::make_unique(); + case 7: + return std::make_unique(); + case 18: + return std::make_unique(); + case 9: + return std::make_unique(); + case 8: + return std::make_unique(); + case 10: + return std::make_unique(); + case 11: + return std::make_unique(); + case 12: + return std::make_unique(); + case 13: + return std::make_unique(); + case 14: + return std::make_unique(); + case 15: + return std::make_unique(); + case 16: + return std::make_unique(); + case 17: + return std::make_unique(); + case 19: + return std::make_unique(); + case 20: + return std::make_unique(); + default: + return {}; + } +} + +float CBodyStateInfo::GetLocomotionSpeed(pas::ELocomotionAnim anim) const { + auto search = x0_stateMap.find(pas::EAnimationState::Locomotion); + if (search != x0_stateMap.cend() && search->second && x18_bodyController) { + const CBSLocomotion& bs = static_cast(*search->second); + return bs.GetLocomotionSpeed(x18_bodyController->GetLocomotionType(), anim); + } + return 0.f; +} + +float CBodyStateInfo::GetMaxSpeed() const { + float ret = GetLocomotionSpeed(pas::ELocomotionAnim::Run); + if (std::fabs(ret) < 0.00001f) { + for (int i = 0; i < 8; ++i) { + float tmp = GetLocomotionSpeed(pas::ELocomotionAnim(i)); + if (tmp > ret) + ret = tmp; } + } + return ret; } -std::unique_ptr CBodyStateInfo::SetupWallWalkerBodyStates(int stateId, CActor& actor) -{ - switch (stateId) - { - case 0: - return std::make_unique(); - case 1: - return std::make_unique(); - case 2: - return std::make_unique(actor); - case 3: - return std::make_unique(); - case 4: - return std::make_unique(); - case 5: - return std::make_unique(actor); - case 6: - return std::make_unique(); - case 7: - return std::make_unique(); - case 18: - return std::make_unique(); - case 9: - return std::make_unique(); - case 8: - return std::make_unique(); - case 10: - return std::make_unique(); - case 11: - return std::make_unique(); - case 12: - return std::make_unique(); - case 13: - return std::make_unique(); - case 14: - return std::make_unique(); - case 15: - return std::make_unique(); - case 16: - return std::make_unique(); - case 17: - return std::make_unique(); - default: - return {}; - } -} - -std::unique_ptr CBodyStateInfo::SetupPitchableBodyStates(int stateId, CActor& actor) -{ - switch (stateId) - { - case 0: - return std::make_unique(); - case 1: - return std::make_unique(); - case 2: - return std::make_unique(actor); - case 3: - return std::make_unique(); - case 4: - return std::make_unique(); - case 5: - return std::make_unique(actor, true); - case 6: - return std::make_unique(); - case 7: - return std::make_unique(); - case 18: - return std::make_unique(); - case 9: - return std::make_unique(); - case 8: - return std::make_unique(); - case 10: - return std::make_unique(); - case 11: - return std::make_unique(); - case 12: - return std::make_unique(); - case 13: - return std::make_unique(); - case 14: - return std::make_unique(); - case 15: - return std::make_unique(); - case 16: - return std::make_unique(); - case 17: - return std::make_unique(); - default: - return {}; - } -} - -std::unique_ptr CBodyStateInfo::SetupFlyerBodyStates(int stateId, CActor& actor) -{ - switch (stateId) - { - case 0: - return std::make_unique(); - case 1: - return std::make_unique(); - case 2: - return std::make_unique(actor); - case 3: - return std::make_unique(); - case 4: - return std::make_unique(); - case 5: - return std::make_unique(actor, false); - case 6: - return std::make_unique(); - case 7: - return std::make_unique(); - case 18: - return std::make_unique(); - case 9: - return std::make_unique(); - case 8: - return std::make_unique(); - case 10: - return std::make_unique(); - case 11: - return std::make_unique(); - case 12: - return std::make_unique(); - case 13: - return std::make_unique(); - case 14: - return std::make_unique(); - case 15: - return std::make_unique(); - case 16: - return std::make_unique(); - case 17: - return std::make_unique(); - default: - return {}; - } -} - -std::unique_ptr CBodyStateInfo::SetupRestrictedBodyStates(int stateId, CActor& actor) -{ - switch (stateId) - { - case 0: - return std::make_unique(); - case 1: - return std::make_unique(); - case 2: - return std::make_unique(actor); - case 3: - return std::make_unique(); - case 4: - return std::make_unique(); - case 5: - return std::make_unique(actor); - case 6: - return std::make_unique(); - case 7: - return std::make_unique(); - case 18: - return std::make_unique(); - case 9: - return std::make_unique(); - case 8: - return std::make_unique(); - case 10: - return std::make_unique(); - case 11: - return std::make_unique(); - case 12: - return std::make_unique(); - case 13: - return std::make_unique(); - case 14: - return std::make_unique(); - case 15: - return std::make_unique(); - case 16: - return std::make_unique(); - case 17: - return std::make_unique(); - case 19: - return std::make_unique(); - default: - return {}; - } -} - -std::unique_ptr CBodyStateInfo::SetupBiPedalBodyStates(int stateId, CActor& actor) -{ - switch (stateId) - { - case 0: - return std::make_unique(); - case 1: - return std::make_unique(); - case 2: - return std::make_unique(actor); - case 3: - return std::make_unique(); - case 4: - return std::make_unique(); - case 5: - return std::make_unique(actor); - case 6: - return std::make_unique(); - case 7: - return std::make_unique(); - case 18: - return std::make_unique(); - case 9: - return std::make_unique(); - case 8: - return std::make_unique(); - case 10: - return std::make_unique(); - case 11: - return std::make_unique(); - case 12: - return std::make_unique(); - case 13: - return std::make_unique(); - case 14: - return std::make_unique(); - case 15: - return std::make_unique(); - case 16: - return std::make_unique(); - case 17: - return std::make_unique(); - case 19: - return std::make_unique(); - case 20: - return std::make_unique(); - default: - return {}; - } -} - -float CBodyStateInfo::GetLocomotionSpeed(pas::ELocomotionAnim anim) const -{ - auto search = x0_stateMap.find(pas::EAnimationState::Locomotion); - if (search != x0_stateMap.cend() && search->second && x18_bodyController) - { - const CBSLocomotion& bs = static_cast(*search->second); - return bs.GetLocomotionSpeed(x18_bodyController->GetLocomotionType(), anim); - } - return 0.f; -} - -float CBodyStateInfo::GetMaxSpeed() const -{ - float ret = GetLocomotionSpeed(pas::ELocomotionAnim::Run); - if (std::fabs(ret) < 0.00001f) - { - for (int i=0 ; i<8 ; ++i) - { - float tmp = GetLocomotionSpeed(pas::ELocomotionAnim(i)); - if (tmp > ret) - ret = tmp; - } - } - return ret; -} - -CBodyState* CBodyStateInfo::GetCurrentState() -{ - auto search = x0_stateMap.find(x14_state); - if (search == x0_stateMap.end()) - return nullptr; - return search->second.get(); -} - -const CBodyState* CBodyStateInfo::GetCurrentState() const -{ - auto search = x0_stateMap.find(x14_state); - if (search == x0_stateMap.end()) - return nullptr; - return search->second.get(); -} - -void CBodyStateInfo::SetState(pas::EAnimationState s) -{ - auto search = x0_stateMap.find(s); - if (search == x0_stateMap.end()) - return; - x14_state = s; -} - -CAdditiveBodyState* CBodyStateInfo::GetCurrentAdditiveState() -{ - for (auto& state : x1c_additiveStates) - { - if (x2c_additiveState == state.first) - return state.second.get(); - } +CBodyState* CBodyStateInfo::GetCurrentState() { + auto search = x0_stateMap.find(x14_state); + if (search == x0_stateMap.end()) return nullptr; + return search->second.get(); } -void CBodyStateInfo::SetAdditiveState(pas::EAnimationState s) -{ - for (auto& state : x1c_additiveStates) - { - if (s == state.first) - { - x2c_additiveState = s; - return; - } +const CBodyState* CBodyStateInfo::GetCurrentState() const { + auto search = x0_stateMap.find(x14_state); + if (search == x0_stateMap.end()) + return nullptr; + return search->second.get(); +} + +void CBodyStateInfo::SetState(pas::EAnimationState s) { + auto search = x0_stateMap.find(s); + if (search == x0_stateMap.end()) + return; + x14_state = s; +} + +CAdditiveBodyState* CBodyStateInfo::GetCurrentAdditiveState() { + for (auto& state : x1c_additiveStates) { + if (x2c_additiveState == state.first) + return state.second.get(); + } + return nullptr; +} + +void CBodyStateInfo::SetAdditiveState(pas::EAnimationState s) { + for (auto& state : x1c_additiveStates) { + if (s == state.first) { + x2c_additiveState = s; + return; } + } } -bool CBodyStateInfo::ApplyHeadTracking() const -{ - if (x14_state == pas::EAnimationState::Invalid) - return false; - return GetCurrentState()->ApplyHeadTracking(); +bool CBodyStateInfo::ApplyHeadTracking() const { + if (x14_state == pas::EAnimationState::Invalid) + return false; + return GetCurrentState()->ApplyHeadTracking(); } -} +} // namespace urde diff --git a/Runtime/Character/CBodyStateInfo.hpp b/Runtime/Character/CBodyStateInfo.hpp index b83da0227..fad5e8554 100644 --- a/Runtime/Character/CBodyStateInfo.hpp +++ b/Runtime/Character/CBodyStateInfo.hpp @@ -5,44 +5,42 @@ #include "CBodyState.hpp" #include "CAdditiveBodyState.hpp" -namespace urde -{ +namespace urde { class CActor; -class CBodyStateInfo -{ - friend class CBodyController; - std::map> x0_stateMap; - pas::EAnimationState x14_state = pas::EAnimationState::Invalid; - CBodyController* x18_bodyController = nullptr; - std::vector>> x1c_additiveStates; - pas::EAnimationState x2c_additiveState = pas::EAnimationState::AdditiveIdle; - float x30_maxPitch = 0.f; - bool x34_24_changeLocoAtEndOfAnimOnly; - std::unique_ptr SetupRestrictedFlyerBodyStates(int stateId, CActor& actor); - std::unique_ptr SetupNewFlyerBodyStates(int stateId, CActor& actor); - std::unique_ptr SetupWallWalkerBodyStates(int stateId, CActor& actor); - std::unique_ptr SetupPitchableBodyStates(int stateId, CActor& actor); - std::unique_ptr SetupFlyerBodyStates(int stateId, CActor& actor); - std::unique_ptr SetupRestrictedBodyStates(int stateId, CActor& actor); - std::unique_ptr SetupBiPedalBodyStates(int stateId, CActor& actor); +class CBodyStateInfo { + friend class CBodyController; + std::map> x0_stateMap; + pas::EAnimationState x14_state = pas::EAnimationState::Invalid; + CBodyController* x18_bodyController = nullptr; + std::vector>> x1c_additiveStates; + pas::EAnimationState x2c_additiveState = pas::EAnimationState::AdditiveIdle; + float x30_maxPitch = 0.f; + bool x34_24_changeLocoAtEndOfAnimOnly; + std::unique_ptr SetupRestrictedFlyerBodyStates(int stateId, CActor& actor); + std::unique_ptr SetupNewFlyerBodyStates(int stateId, CActor& actor); + std::unique_ptr SetupWallWalkerBodyStates(int stateId, CActor& actor); + std::unique_ptr SetupPitchableBodyStates(int stateId, CActor& actor); + std::unique_ptr SetupFlyerBodyStates(int stateId, CActor& actor); + std::unique_ptr SetupRestrictedBodyStates(int stateId, CActor& actor); + std::unique_ptr SetupBiPedalBodyStates(int stateId, CActor& actor); + public: - CBodyStateInfo(CActor& actor, EBodyType type); - float GetLocomotionSpeed(pas::ELocomotionAnim anim) const; - float GetMaxSpeed() const; - float GetMaximumPitch() const { return x30_maxPitch; } - void SetMaximumPitch(float pitch) { x30_maxPitch = pitch; } - bool GetLocoAnimChangeAtEndOfAnimOnly() const { return x34_24_changeLocoAtEndOfAnimOnly; } - void SetLocoAnimChangeAtEndOfAnimOnly(bool s) { x34_24_changeLocoAtEndOfAnimOnly = s; } - CBodyState* GetCurrentState(); - const CBodyState* GetCurrentState() const; - pas::EAnimationState GetCurrentStateId() const { return x14_state; } - void SetState(pas::EAnimationState s); - CAdditiveBodyState* GetCurrentAdditiveState(); - pas::EAnimationState GetCurrentAdditiveStateId() const { return x2c_additiveState; } - void SetAdditiveState(pas::EAnimationState s); - bool ApplyHeadTracking() const; + CBodyStateInfo(CActor& actor, EBodyType type); + float GetLocomotionSpeed(pas::ELocomotionAnim anim) const; + float GetMaxSpeed() const; + float GetMaximumPitch() const { return x30_maxPitch; } + void SetMaximumPitch(float pitch) { x30_maxPitch = pitch; } + bool GetLocoAnimChangeAtEndOfAnimOnly() const { return x34_24_changeLocoAtEndOfAnimOnly; } + void SetLocoAnimChangeAtEndOfAnimOnly(bool s) { x34_24_changeLocoAtEndOfAnimOnly = s; } + CBodyState* GetCurrentState(); + const CBodyState* GetCurrentState() const; + pas::EAnimationState GetCurrentStateId() const { return x14_state; } + void SetState(pas::EAnimationState s); + CAdditiveBodyState* GetCurrentAdditiveState(); + pas::EAnimationState GetCurrentAdditiveStateId() const { return x2c_additiveState; } + void SetAdditiveState(pas::EAnimationState s); + bool ApplyHeadTracking() const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CBoneTracking.cpp b/Runtime/Character/CBoneTracking.cpp index 0a3da4a9b..f5d8c20c0 100644 --- a/Runtime/Character/CBoneTracking.cpp +++ b/Runtime/Character/CBoneTracking.cpp @@ -7,53 +7,40 @@ #include "TCastTo.hpp" - -namespace urde -{ +namespace urde { CBoneTracking::CBoneTracking(const CAnimData& animData, std::string_view bone, float f1, float f2, bool b1) - : x14_segId(animData.GetCharLayoutInfo().GetSegIdFromString(bone)), x1c_(f1), x20_(f2), x36_24_active(false), - x36_25_(false), x36_26_(b1), x36_27_(b1), x36_28_(b1), x36_29_(b1) -{ -} +: x14_segId(animData.GetCharLayoutInfo().GetSegIdFromString(bone)) +, x1c_(f1) +, x20_(f2) +, x36_24_active(false) +, x36_25_(false) +, x36_26_(b1) +, x36_27_(b1) +, x36_28_(b1) +, x36_29_(b1) {} -void CBoneTracking::Update(float dt) -{ - x18_time += dt; +void CBoneTracking::Update(float dt) { x18_time += dt; } +void CBoneTracking::PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& xf, + const zeus::CVector3f& vec, const CBodyController& bodyController) { + TCastToPtr patterned = bodyController.GetOwner(); + + PreRender(mgr, animData, xf, vec, + (bodyController.GetBodyStateInfo().ApplyHeadTracking() && patterned && patterned->ApplyBoneTracking())); } void CBoneTracking::PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& xf, - const zeus::CVector3f& vec, const CBodyController& bodyController) -{ - TCastToPtr patterned = bodyController.GetOwner(); + const zeus::CVector3f& vec, bool b) { + if (x14_segId == 0) + return; - PreRender(mgr, animData, xf, vec, - (bodyController.GetBodyStateInfo().ApplyHeadTracking() && patterned && patterned->ApplyBoneTracking())); + x18_time = 0.f; } -void CBoneTracking::PreRender(const CStateManager& mgr, CAnimData& animData, const zeus::CTransform& xf, - const zeus::CVector3f& vec, bool b) -{ - if (x14_segId == 0) - return; +void CBoneTracking::SetActive(bool) { x36_24_active = true; } - - x18_time = 0.f; -} +void CBoneTracking::SetTarget(TUniqueId target) { x34_target = target; } -void CBoneTracking::SetActive(bool) -{ - x36_24_active = true; -} - -void CBoneTracking::SetTarget(TUniqueId target) -{ - x34_target = target; -} - -void CBoneTracking::SetTargetPosition(const zeus::CVector3f& targetPos) -{ - x24_targetPosition = targetPos; -} -} \ No newline at end of file +void CBoneTracking::SetTargetPosition(const zeus::CVector3f& targetPos) { x24_targetPosition = targetPos; } +} // namespace urde \ No newline at end of file diff --git a/Runtime/Character/CBoneTracking.hpp b/Runtime/Character/CBoneTracking.hpp index 5e7917845..bf7bfddb4 100644 --- a/Runtime/Character/CBoneTracking.hpp +++ b/Runtime/Character/CBoneTracking.hpp @@ -7,33 +7,33 @@ #include "zeus/CVector3f.hpp" #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CAnimData; class CStateManager; class CBodyController; -class CBoneTracking -{ - zeus::CQuaternion x0_ = zeus::CQuaternion::skNoRotation; - CSegId x14_segId; - float x18_time = 0.f; - float x1c_; - float x20_; - std::experimental::optional x24_targetPosition; - TUniqueId x34_target = kInvalidUniqueId; - bool x36_24_active : 1; - bool x36_25_ : 1; - bool x36_26_ : 1; - bool x36_27_ : 1; - bool x36_28_ : 1; - bool x36_29_ : 1; +class CBoneTracking { + zeus::CQuaternion x0_ = zeus::CQuaternion::skNoRotation; + CSegId x14_segId; + float x18_time = 0.f; + float x1c_; + float x20_; + std::experimental::optional x24_targetPosition; + TUniqueId x34_target = kInvalidUniqueId; + bool x36_24_active : 1; + bool x36_25_ : 1; + bool x36_26_ : 1; + bool x36_27_ : 1; + bool x36_28_ : 1; + bool x36_29_ : 1; + public: - CBoneTracking(const CAnimData&, std::string_view, float, float, bool); - void Update(float dt); - void PreRender(const CStateManager&, CAnimData&, const zeus::CTransform&, const zeus::CVector3f&, const CBodyController&); - void PreRender(const CStateManager&, CAnimData&, const zeus::CTransform&, const zeus::CVector3f&, bool); - void SetActive(bool); - void SetTarget(TUniqueId); - void SetTargetPosition(const zeus::CVector3f&); + CBoneTracking(const CAnimData&, std::string_view, float, float, bool); + void Update(float dt); + void PreRender(const CStateManager&, CAnimData&, const zeus::CTransform&, const zeus::CVector3f&, + const CBodyController&); + void PreRender(const CStateManager&, CAnimData&, const zeus::CTransform&, const zeus::CVector3f&, bool); + void SetActive(bool); + void SetTarget(TUniqueId); + void SetTargetPosition(const zeus::CVector3f&); }; -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/Character/CBoolPOINode.cpp b/Runtime/Character/CBoolPOINode.cpp index ea6b716db..29caa8a58 100644 --- a/Runtime/Character/CBoolPOINode.cpp +++ b/Runtime/Character/CBoolPOINode.cpp @@ -1,21 +1,16 @@ #include "CBoolPOINode.hpp" #include "CAnimSourceReader.hpp" -namespace urde -{ +namespace urde { -CBoolPOINode::CBoolPOINode() -: CPOINode("root", EPOIType::EmptyBool, CCharAnimTime(), -1, false, 1.f, -1, 0) {} +CBoolPOINode::CBoolPOINode() : CPOINode("root", EPOIType::EmptyBool, CCharAnimTime(), -1, false, 1.f, -1, 0) {} -CBoolPOINode::CBoolPOINode(CInputStream& in) -: CPOINode(in), x38_val(in.readBool()) {} +CBoolPOINode::CBoolPOINode(CInputStream& in) : CPOINode(in), x38_val(in.readBool()) {} -CBoolPOINode CBoolPOINode::CopyNodeMinusStartTime(const CBoolPOINode& node, - const CCharAnimTime& startTime) -{ - CBoolPOINode ret = node; - ret.x1c_time -= startTime; - return ret; +CBoolPOINode CBoolPOINode::CopyNodeMinusStartTime(const CBoolPOINode& node, const CCharAnimTime& startTime) { + CBoolPOINode ret = node; + ret.x1c_time -= startTime; + return ret; } -} +} // namespace urde diff --git a/Runtime/Character/CBoolPOINode.hpp b/Runtime/Character/CBoolPOINode.hpp index d86f74a71..d738eff68 100644 --- a/Runtime/Character/CBoolPOINode.hpp +++ b/Runtime/Character/CBoolPOINode.hpp @@ -2,20 +2,17 @@ #include "CPOINode.hpp" -namespace urde -{ +namespace urde { class IAnimSourceInfo; -class CBoolPOINode : public CPOINode -{ - bool x38_val = false; +class CBoolPOINode : public CPOINode { + bool x38_val = false; + public: - CBoolPOINode(); - CBoolPOINode(CInputStream& in); - bool GetValue() const {return x38_val;} - static CBoolPOINode CopyNodeMinusStartTime(const CBoolPOINode& node, - const CCharAnimTime& startTime); + CBoolPOINode(); + CBoolPOINode(CInputStream& in); + bool GetValue() const { return x38_val; } + static CBoolPOINode CopyNodeMinusStartTime(const CBoolPOINode& node, const CCharAnimTime& startTime); }; -} - +} // namespace urde diff --git a/Runtime/Character/CCharAnimTime.cpp b/Runtime/Character/CCharAnimTime.cpp index 38bb748c1..fafd5f705 100644 --- a/Runtime/Character/CCharAnimTime.cpp +++ b/Runtime/Character/CCharAnimTime.cpp @@ -3,340 +3,290 @@ #include #include -namespace urde -{ +namespace urde { -CCharAnimTime CCharAnimTime::Infinity() -{ - CCharAnimTime ret(1.f); +CCharAnimTime CCharAnimTime::Infinity() { + CCharAnimTime ret(1.f); + ret.x4_type = EType::Infinity; + return ret; +} + +bool CCharAnimTime::EqualsZero() const { + if (x4_type == EType::ZeroIncreasing || x4_type == EType::ZeroSteady || x4_type == EType::ZeroDecreasing) + return true; + + return (x0_time == 0.f); +} + +bool CCharAnimTime::EpsilonZero() const { return (std::fabs(x0_time) < 0.00001f); } + +bool CCharAnimTime::GreaterThanZero() const { + if (EqualsZero()) + return false; + return (x0_time > 0.f); +} + +bool CCharAnimTime::operator==(const CCharAnimTime& other) const { + if (x4_type == EType::NonZero) { + if (other.x4_type == EType::NonZero) + return x0_time == other.x0_time; + return !other.EqualsZero(); + } + + if (EqualsZero()) { + if (other.EqualsZero()) { + int type = -1; + if (x4_type != EType::ZeroDecreasing) { + if (x4_type != EType::ZeroSteady) + type = 1; + else + type = 0; + } + + int otherType = -1; + if (other.x4_type != EType::ZeroDecreasing) { + if (other.x4_type != EType::ZeroSteady) + otherType = 1; + else + otherType = 0; + } + + return type == otherType; + } + return false; + } + + if (other.x4_type == EType::Infinity) + return x0_time * other.x0_time < 0.f; + + return false; +} + +bool CCharAnimTime::operator!=(const CCharAnimTime& other) const { return !(*this == other); } + +bool CCharAnimTime::operator>=(const CCharAnimTime& other) const { + if (*this == other) + return true; + + return (*this > other); +} + +bool CCharAnimTime::operator<=(const CCharAnimTime& other) const { + if (*this == other) + return true; + + return (*this < other); +} + +bool CCharAnimTime::operator>(const CCharAnimTime& other) const { return (!(*this == other) && !(*this < other)); } + +bool CCharAnimTime::operator<(const CCharAnimTime& other) const { + if (x4_type == EType::NonZero) { + if (other.x4_type == EType::NonZero) + return x0_time < other.x0_time; + if (other.EqualsZero()) + return x0_time < 0.f; + else + return other.x0_time > 0.f; + } + + if (EqualsZero()) { + if (other.EqualsZero()) { + int type = -1; + if (x4_type != EType::ZeroDecreasing) { + if (x4_type != EType::ZeroSteady) + type = 1; + else + type = 0; + } + + int otherType = -1; + if (other.x4_type != EType::ZeroDecreasing) { + if (other.x4_type != EType::ZeroSteady) + otherType = 1; + else + otherType = 0; + } + + return type < otherType; + } + + if (other.x4_type == EType::NonZero) + return other.x0_time > 0.f; + return other.x0_time < 0.f; + } else { + if (x4_type == EType::Infinity) + return x0_time < 0.f && other.x0_time > 0.f; + return x0_time < other.x0_time; + } +} + +CCharAnimTime& CCharAnimTime::operator*=(const CCharAnimTime& other) { + *this = *this * other; + return *this; +} + +CCharAnimTime& CCharAnimTime::operator+=(const CCharAnimTime& other) { + *this = *this + other; + return *this; +} + +CCharAnimTime CCharAnimTime::operator+(const CCharAnimTime& other) const { + if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) { + if (other.x0_time != x0_time) + return CCharAnimTime(); + return *this; + } else if (x4_type == EType::Infinity) + return *this; + else if (other.x4_type == EType::Infinity) + return other; + + if (!EqualsZero() || !other.EqualsZero()) + return CCharAnimTime(x0_time + other.x0_time); + + int type = -1; + if (x4_type != EType::ZeroDecreasing) { + if (x4_type != EType::ZeroSteady) + type = 1; + else + type = 0; + } + + int otherType = -1; + if (other.x4_type != EType::ZeroDecreasing) { + if (other.x4_type != EType::ZeroSteady) + otherType = 1; + else + otherType = 0; + } + + type += otherType; + otherType = std::max(-1, std::min(type, 1)); + + CCharAnimTime ret; + if (otherType == -1) + ret.x4_type = EType::ZeroDecreasing; + else if (otherType == 0) + ret.x4_type = EType::ZeroSteady; + else + ret.x4_type = EType::ZeroIncreasing; + + return ret; +} + +CCharAnimTime& CCharAnimTime::operator-=(const CCharAnimTime& other) { + *this = *this - other; + return *this; +} + +CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other) const { + if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) { + if (other.x0_time == x0_time) + return CCharAnimTime(); + return *this; + } else if (x4_type == EType::Infinity) + return *this; + else if (other.x4_type == EType::Infinity) { + CCharAnimTime ret(-other.x0_time); ret.x4_type = EType::Infinity; return ret; -} + } -bool CCharAnimTime::EqualsZero() const -{ - if (x4_type == EType::ZeroIncreasing || x4_type == EType::ZeroSteady || x4_type == EType::ZeroDecreasing) - return true; + if (!EqualsZero() || !other.EqualsZero()) + return CCharAnimTime(x0_time - other.x0_time); - return (x0_time == 0.f); -} - -bool CCharAnimTime::EpsilonZero() const -{ - return (std::fabs(x0_time) < 0.00001f); -} - -bool CCharAnimTime::GreaterThanZero() const -{ - if (EqualsZero()) - return false; - return (x0_time > 0.f); -} - -bool CCharAnimTime::operator ==(const CCharAnimTime& other) const -{ - if (x4_type == EType::NonZero) - { - if (other.x4_type == EType::NonZero) - return x0_time == other.x0_time; - return !other.EqualsZero(); - } - - if (EqualsZero()) - { - if (other.EqualsZero()) - { - int type = -1; - if (x4_type != EType::ZeroDecreasing) - { - if (x4_type != EType::ZeroSteady) - type = 1; - else - type = 0; - } - - int otherType = -1; - if (other.x4_type != EType::ZeroDecreasing) - { - if (other.x4_type != EType::ZeroSteady) - otherType = 1; - else - otherType = 0; - } - - return type == otherType; - } - return false; - } - - if (other.x4_type == EType::Infinity) - return x0_time * other.x0_time < 0.f; - - return false; -} - -bool CCharAnimTime::operator !=(const CCharAnimTime& other) const -{ - return !(*this == other); -} - -bool CCharAnimTime::operator>=(const CCharAnimTime& other) const -{ - if (*this == other) - return true; - - return (*this > other); -} - -bool CCharAnimTime::operator<=(const CCharAnimTime& other) const -{ - if (*this == other) - return true; - - return (*this < other); -} - -bool CCharAnimTime::operator >(const CCharAnimTime& other) const -{ - return (!(*this == other) && !(*this < other)); -} - -bool CCharAnimTime::operator <(const CCharAnimTime& other) const -{ - if (x4_type == EType::NonZero) - { - if (other.x4_type == EType::NonZero) - return x0_time < other.x0_time; - if (other.EqualsZero()) - return x0_time < 0.f; - else - return other.x0_time > 0.f; - } - - if (EqualsZero()) - { - if (other.EqualsZero()) - { - int type = -1; - if (x4_type != EType::ZeroDecreasing) - { - if (x4_type != EType::ZeroSteady) - type = 1; - else - type = 0; - } - - int otherType = -1; - if (other.x4_type != EType::ZeroDecreasing) - { - if (other.x4_type != EType::ZeroSteady) - otherType = 1; - else - otherType = 0; - } - - return type < otherType; - } - - if (other.x4_type == EType::NonZero) - return other.x0_time > 0.f; - return other.x0_time < 0.f; - } + int type = -1; + if (x4_type != EType::ZeroDecreasing) { + if (x4_type != EType::ZeroSteady) + type = 1; else - { - if (x4_type == EType::Infinity) - return x0_time < 0.f && other.x0_time > 0.f; - return x0_time < other.x0_time; - } + type = 0; + } + + int otherType = -1; + if (other.x4_type != EType::ZeroDecreasing) { + if (other.x4_type != EType::ZeroSteady) + otherType = 1; + else + otherType = 0; + } + + CCharAnimTime ret; + type -= otherType; + if (type == -1) + ret.x4_type = EType::ZeroDecreasing; + else if (type == 0) + ret.x4_type = EType::ZeroSteady; + else + ret.x4_type = EType::ZeroIncreasing; + + return ret; } -CCharAnimTime& CCharAnimTime::operator*=(const CCharAnimTime& other) -{ - *this = *this * other; +CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) const { + if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) { + if (other.x0_time != x0_time) + return CCharAnimTime(); return *this; -} - -CCharAnimTime& CCharAnimTime::operator+=(const CCharAnimTime& other) -{ - *this = *this + other; + } else if (x4_type == EType::Infinity) return *this; -} + else if (other.x4_type == EType::Infinity) + return other; -CCharAnimTime CCharAnimTime::operator+(const CCharAnimTime& other) const -{ - if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) - { - if (other.x0_time != x0_time) - return CCharAnimTime(); - return *this; - } - else if (x4_type == EType::Infinity) - return *this; - else if (other.x4_type == EType::Infinity) - return other; + if (!EqualsZero() || !other.EqualsZero()) + return CCharAnimTime(x0_time * other.x0_time); - if (!EqualsZero() || !other.EqualsZero()) - return CCharAnimTime(x0_time + other.x0_time); - - int type = -1; - if (x4_type != EType::ZeroDecreasing) - { - if (x4_type != EType::ZeroSteady) - type = 1; - else - type = 0; - } - - int otherType = -1; - if (other.x4_type != EType::ZeroDecreasing) - { - if (other.x4_type != EType::ZeroSteady) - otherType = 1; - else - otherType = 0; - } - - type += otherType; - otherType = std::max(-1, std::min(type, 1)); - - CCharAnimTime ret; - if (otherType == -1) - ret.x4_type = EType::ZeroDecreasing; - else if (otherType == 0) - ret.x4_type = EType::ZeroSteady; + int type = -1; + if (x4_type != EType::ZeroDecreasing) { + if (x4_type != EType::ZeroSteady) + type = 1; else - ret.x4_type = EType::ZeroIncreasing; + type = 0; + } - return ret; + int otherType = -1; + if (other.x4_type != EType::ZeroDecreasing) { + if (other.x4_type != EType::ZeroSteady) + otherType = 1; + else + otherType = 0; + } + + type += otherType; + otherType = std::max(-1, std::min(type, 1)); + + CCharAnimTime ret; + if (otherType == -1) + ret.x4_type = EType::ZeroDecreasing; + else if (otherType == 0) + ret.x4_type = EType::ZeroSteady; + else + ret.x4_type = EType::ZeroIncreasing; + return ret; } -CCharAnimTime& CCharAnimTime::operator-=(const CCharAnimTime& other) -{ - *this = *this - other; +CCharAnimTime CCharAnimTime::operator*(const float& other) const { + CCharAnimTime ret; + if (other == 0.f) + return ret; + + if (!EqualsZero()) + return CCharAnimTime(x0_time * other); + + if (other > 0.f) return *this; -} - -CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other) const -{ - if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) - { - if (other.x0_time == x0_time) - return CCharAnimTime(); - return *this; - } - else if (x4_type == EType::Infinity) - return *this; - else if (other.x4_type == EType::Infinity) - { - CCharAnimTime ret(-other.x0_time); - ret.x4_type = EType::Infinity; - return ret; - } - - if (!EqualsZero() || !other.EqualsZero()) - return CCharAnimTime(x0_time - other.x0_time); - - int type = -1; - if (x4_type != EType::ZeroDecreasing) - { - if (x4_type != EType::ZeroSteady) - type = 1; - else - type = 0; - } - - int otherType = -1; - if (other.x4_type != EType::ZeroDecreasing) - { - if (other.x4_type != EType::ZeroSteady) - otherType = 1; - else - otherType = 0; - } - - CCharAnimTime ret; - type -= otherType; - if (type == -1) - ret.x4_type = EType::ZeroDecreasing; - else if (type == 0) - ret.x4_type = EType::ZeroSteady; - else - ret.x4_type = EType::ZeroIncreasing; - + else if (other == 0.f) return ret; + + ret.x4_type = x4_type; + return ret; } -CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) const -{ - if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) - { - if (other.x0_time != x0_time) - return CCharAnimTime(); - return *this; - } - else if (x4_type == EType::Infinity) - return *this; - else if (other.x4_type == EType::Infinity) - return other; +float CCharAnimTime::operator/(const CCharAnimTime& other) const { + if (other.EqualsZero()) + return 0.f; - if (!EqualsZero() || !other.EqualsZero()) - return CCharAnimTime(x0_time * other.x0_time); - - int type = -1; - if (x4_type != EType::ZeroDecreasing) - { - if (x4_type != EType::ZeroSteady) - type = 1; - else - type = 0; - } - - int otherType = -1; - if (other.x4_type != EType::ZeroDecreasing) - { - if (other.x4_type != EType::ZeroSteady) - otherType = 1; - else - otherType = 0; - } - - type += otherType; - otherType = std::max(-1, std::min(type, 1)); - - CCharAnimTime ret; - if (otherType == -1) - ret.x4_type = EType::ZeroDecreasing; - else if (otherType == 0) - ret.x4_type = EType::ZeroSteady; - else - ret.x4_type = EType::ZeroIncreasing; - return ret; + return x0_time / other.x0_time; } -CCharAnimTime CCharAnimTime::operator*(const float& other) const -{ - CCharAnimTime ret; - if (other == 0.f) - return ret; - - if (!EqualsZero()) - return CCharAnimTime(x0_time * other); - - if (other > 0.f) - return *this; - else if (other == 0.f) - return ret; - - ret.x4_type = x4_type; - return ret; -} - -float CCharAnimTime::operator/(const CCharAnimTime& other) const -{ - if (other.EqualsZero()) - return 0.f; - - return x0_time / other.x0_time; -} - -} +} // namespace urde diff --git a/Runtime/Character/CCharAnimTime.hpp b/Runtime/Character/CCharAnimTime.hpp index 344d2c227..71d4caddf 100644 --- a/Runtime/Character/CCharAnimTime.hpp +++ b/Runtime/Character/CCharAnimTime.hpp @@ -5,59 +5,42 @@ #undef min #undef max -namespace urde -{ +namespace urde { -class CCharAnimTime -{ +class CCharAnimTime { public: - enum class EType - { - NonZero, - ZeroIncreasing, - ZeroSteady, - ZeroDecreasing, - Infinity - }; + enum class EType { NonZero, ZeroIncreasing, ZeroSteady, ZeroDecreasing, Infinity }; + private: - float x0_time = 0.f; - EType x4_type = EType::ZeroSteady; + float x0_time = 0.f; + EType x4_type = EType::ZeroSteady; + public: - CCharAnimTime() = default; - CCharAnimTime(CInputStream& in) - : x0_time(in.readFloatBig()), - x4_type(EType(in.readUint32Big())) {} - CCharAnimTime(float time) - : x0_time(time), - x4_type(x0_time != 0.f ? EType::NonZero : EType::ZeroSteady) {} + CCharAnimTime() = default; + CCharAnimTime(CInputStream& in) : x0_time(in.readFloatBig()), x4_type(EType(in.readUint32Big())) {} + CCharAnimTime(float time) : x0_time(time), x4_type(x0_time != 0.f ? EType::NonZero : EType::ZeroSteady) {} - CCharAnimTime(EType type, const float& t) - : x0_time(t) - , x4_type(type) - { - } + CCharAnimTime(EType type, const float& t) : x0_time(t), x4_type(type) {} - static CCharAnimTime Infinity(); - float GetSeconds() const { return x0_time; } - - bool EqualsZero() const; - bool EpsilonZero() const; - bool GreaterThanZero() const; - bool operator ==(const CCharAnimTime& other) const; - bool operator !=(const CCharAnimTime& other) const; - bool operator>=(const CCharAnimTime& other) const; - bool operator<=(const CCharAnimTime& other) const; - bool operator >(const CCharAnimTime& other) const; - bool operator <(const CCharAnimTime& other) const; - CCharAnimTime& operator*=(const CCharAnimTime& other); - CCharAnimTime& operator+=(const CCharAnimTime& other); - CCharAnimTime operator+(const CCharAnimTime& other) const; - CCharAnimTime& operator-=(const CCharAnimTime& other); - CCharAnimTime operator-(const CCharAnimTime& other) const; - CCharAnimTime operator*(const CCharAnimTime& other) const; - CCharAnimTime operator*(const float& other) const; - float operator/(const CCharAnimTime& other) const; + static CCharAnimTime Infinity(); + float GetSeconds() const { return x0_time; } + bool EqualsZero() const; + bool EpsilonZero() const; + bool GreaterThanZero() const; + bool operator==(const CCharAnimTime& other) const; + bool operator!=(const CCharAnimTime& other) const; + bool operator>=(const CCharAnimTime& other) const; + bool operator<=(const CCharAnimTime& other) const; + bool operator>(const CCharAnimTime& other) const; + bool operator<(const CCharAnimTime& other) const; + CCharAnimTime& operator*=(const CCharAnimTime& other); + CCharAnimTime& operator+=(const CCharAnimTime& other); + CCharAnimTime operator+(const CCharAnimTime& other) const; + CCharAnimTime& operator-=(const CCharAnimTime& other); + CCharAnimTime operator-(const CCharAnimTime& other) const; + CCharAnimTime operator*(const CCharAnimTime& other) const; + CCharAnimTime operator*(const float& other) const; + float operator/(const CCharAnimTime& other) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CCharLayoutInfo.cpp b/Runtime/Character/CCharLayoutInfo.cpp index 126a499f1..2e0a8b610 100644 --- a/Runtime/Character/CCharLayoutInfo.cpp +++ b/Runtime/Character/CCharLayoutInfo.cpp @@ -1,75 +1,61 @@ #include "CCharLayoutInfo.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { -zeus::CVector3f CCharLayoutInfo::GetFromParentUnrotated(const CSegId& id) const -{ - const CCharLayoutNode::Bone& bone = x0_node->GetBoneMap()[id]; - if (!x0_node->GetBoneMap().HasElement(bone.x0_parentId)) - return bone.x4_origin; - else - { - const CCharLayoutNode::Bone& pBone = x0_node->GetBoneMap()[bone.x0_parentId]; - return bone.x4_origin - pBone.x4_origin; - } -} - -zeus::CVector3f CCharLayoutInfo::GetFromRootUnrotated(const CSegId& id) const -{ - const CCharLayoutNode::Bone& bone = x0_node->GetBoneMap()[id]; +zeus::CVector3f CCharLayoutInfo::GetFromParentUnrotated(const CSegId& id) const { + const CCharLayoutNode::Bone& bone = x0_node->GetBoneMap()[id]; + if (!x0_node->GetBoneMap().HasElement(bone.x0_parentId)) return bone.x4_origin; + else { + const CCharLayoutNode::Bone& pBone = x0_node->GetBoneMap()[bone.x0_parentId]; + return bone.x4_origin - pBone.x4_origin; + } } -CSegId CCharLayoutInfo::GetSegIdFromString(std::string_view name) const -{ - auto it = x18_segIdMap.find(name.data()); - if (it == x18_segIdMap.end()) - return {}; - - return it->second; +zeus::CVector3f CCharLayoutInfo::GetFromRootUnrotated(const CSegId& id) const { + const CCharLayoutNode::Bone& bone = x0_node->GetBoneMap()[id]; + return bone.x4_origin; } -void CCharLayoutNode::Bone::read(CInputStream& in) -{ - x0_parentId = CSegId(in); - x4_origin.readBig(in); +CSegId CCharLayoutInfo::GetSegIdFromString(std::string_view name) const { + auto it = x18_segIdMap.find(name.data()); + if (it == x18_segIdMap.end()) + return {}; - u32 chCount = in.readUint32Big(); - x10_children.reserve(chCount); - for (u32 i=0 ; isecond; } -CCharLayoutNode::CCharLayoutNode(CInputStream& in) -: x0_boneMap(in.readUint32Big()) -{ - u32 cap = x0_boneMap.GetCapacity(); - for (u32 i=0 ; i(in)), - x8_segIdList(in) -{ - atUint32 mapCount = in.readUint32Big(); - for (atUint32 i=0 ; i(in)), x8_segIdList(in) { + atUint32 mapCount = in.readUint32Big(); + for (atUint32 i = 0; i < mapCount; ++i) { + std::string key = in.readString(); + x18_segIdMap.emplace(key, in); + } } CFactoryFnReturn FCharLayoutInfo(const SObjectTag&, CInputStream& in, const CVParamTransfer&, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/Character/CCharLayoutInfo.hpp b/Runtime/Character/CCharLayoutInfo.hpp index 3b0d4b195..16f931b0b 100644 --- a/Runtime/Character/CCharLayoutInfo.hpp +++ b/Runtime/Character/CCharLayoutInfo.hpp @@ -6,42 +6,39 @@ #include "CSegId.hpp" #include "TSegIdMap.hpp" -namespace urde -{ +namespace urde { -class CCharLayoutNode -{ +class CCharLayoutNode { public: - struct Bone - { - CSegId x0_parentId; - zeus::CVector3f x4_origin; - std::vector x10_children; - void read(CInputStream& in); - }; + struct Bone { + CSegId x0_parentId; + zeus::CVector3f x4_origin; + std::vector x10_children; + void read(CInputStream& in); + }; + private: - TSegIdMap x0_boneMap; + TSegIdMap x0_boneMap; + public: - CCharLayoutNode(CInputStream& in); - const TSegIdMap& GetBoneMap() const {return x0_boneMap;} + CCharLayoutNode(CInputStream& in); + const TSegIdMap& GetBoneMap() const { return x0_boneMap; } }; -class CCharLayoutInfo -{ - std::shared_ptr x0_node; - CSegIdList x8_segIdList; - std::map x18_segIdMap; +class CCharLayoutInfo { + std::shared_ptr x0_node; + CSegIdList x8_segIdList; + std::map x18_segIdMap; + public: - CCharLayoutInfo(CInputStream& in); - const std::shared_ptr& GetRootNode() const {return x0_node;} - const CSegIdList& GetSegIdList() const {return x8_segIdList;} - zeus::CVector3f GetFromParentUnrotated(const CSegId& id) const; - zeus::CVector3f GetFromRootUnrotated(const CSegId& id) const; - CSegId GetSegIdFromString(std::string_view name) const; + CCharLayoutInfo(CInputStream& in); + const std::shared_ptr& GetRootNode() const { return x0_node; } + const CSegIdList& GetSegIdList() const { return x8_segIdList; } + zeus::CVector3f GetFromParentUnrotated(const CSegId& id) const; + zeus::CVector3f GetFromRootUnrotated(const CSegId& id) const; + CSegId GetSegIdFromString(std::string_view name) const; }; -CFactoryFnReturn FCharLayoutInfo(const SObjectTag&, CInputStream&, const CVParamTransfer&, - CObjectReference* selfRef); - -} +CFactoryFnReturn FCharLayoutInfo(const SObjectTag&, CInputStream&, const CVParamTransfer&, CObjectReference* selfRef); +} // namespace urde diff --git a/Runtime/Character/CCharacterFactory.cpp b/Runtime/Character/CCharacterFactory.cpp index 436ca9e12..e9cfd1dc3 100644 --- a/Runtime/Character/CCharacterFactory.cpp +++ b/Runtime/Character/CCharacterFactory.cpp @@ -14,206 +14,147 @@ #include "Graphics/CSkinnedModel.hpp" #include "Character/CCharLayoutInfo.hpp" -namespace urde -{ +namespace urde { -CFactoryFnReturn CCharacterFactory::CDummyFactory::Build(const SObjectTag& tag, - const CVParamTransfer& params, - CObjectReference* selfRef) -{ +CFactoryFnReturn CCharacterFactory::CDummyFactory::Build(const SObjectTag& tag, const CVParamTransfer& params, + CObjectReference* selfRef) { - const CCharacterInfo& charInfo = *params.GetOwnedObj(); + const CCharacterInfo& charInfo = *params.GetOwnedObj(); - switch (tag.type.toUint32() & 0x1) - { - case 0: - return TToken::GetIObjObjectFor( - std::make_unique(*g_SimplePool, - charInfo.GetModelId(), - charInfo.GetSkinRulesId(), - charInfo.GetCharLayoutInfoId(), - 0, tag.type.toUint32() >> 16)); - case 1: - return TToken::GetIObjObjectFor( - std::make_unique(*g_SimplePool, - charInfo.GetIceModelId(), - charInfo.GetIceSkinRulesId(), - charInfo.GetCharLayoutInfoId(), - 0, tag.type.toUint32() >> 16)); - default: - break; - } + switch (tag.type.toUint32() & 0x1) { + case 0: + return TToken::GetIObjObjectFor( + std::make_unique(*g_SimplePool, charInfo.GetModelId(), charInfo.GetSkinRulesId(), + charInfo.GetCharLayoutInfoId(), 0, tag.type.toUint32() >> 16)); + case 1: + return TToken::GetIObjObjectFor( + std::make_unique(*g_SimplePool, charInfo.GetIceModelId(), charInfo.GetIceSkinRulesId(), + charInfo.GetCharLayoutInfoId(), 0, tag.type.toUint32() >> 16)); + default: + break; + } - return {}; + return {}; } -void CCharacterFactory::CDummyFactory::BuildAsync(const SObjectTag& tag, - const CVParamTransfer& parms, - std::unique_ptr* objOut, - CObjectReference* selfRef) -{ - *objOut = Build(tag, parms, selfRef); +void CCharacterFactory::CDummyFactory::BuildAsync(const SObjectTag& tag, const CVParamTransfer& parms, + std::unique_ptr* objOut, CObjectReference* selfRef) { + *objOut = Build(tag, parms, selfRef); } -void CCharacterFactory::CDummyFactory::CancelBuild(const SObjectTag&) -{ -} +void CCharacterFactory::CDummyFactory::CancelBuild(const SObjectTag&) {} -bool CCharacterFactory::CDummyFactory::CanBuild(const SObjectTag&) -{ - return true; -} +bool CCharacterFactory::CDummyFactory::CanBuild(const SObjectTag&) { return true; } -const SObjectTag* CCharacterFactory::CDummyFactory::GetResourceIdByName(std::string_view) const -{ - return nullptr; -} +const SObjectTag* CCharacterFactory::CDummyFactory::GetResourceIdByName(std::string_view) const { return nullptr; } -FourCC CCharacterFactory::CDummyFactory::GetResourceTypeById(CAssetId id) const -{ - return {}; -} +FourCC CCharacterFactory::CDummyFactory::GetResourceTypeById(CAssetId id) const { return {}; } -void CCharacterFactory::CDummyFactory::EnumerateResources( - const std::function& lambda) const -{ -} +void CCharacterFactory::CDummyFactory::EnumerateResources(const std::function& lambda) const {} void CCharacterFactory::CDummyFactory::EnumerateNamedResources( - const std::function& lambda) const -{ -} + const std::function& lambda) const {} -u32 CCharacterFactory::CDummyFactory::ResourceSize(const urde::SObjectTag& tag) -{ - return 0; -} +u32 CCharacterFactory::CDummyFactory::ResourceSize(const urde::SObjectTag& tag) { return 0; } std::shared_ptr CCharacterFactory::CDummyFactory::LoadResourceAsync(const urde::SObjectTag& tag, - void* target) -{ - return {}; + void* target) { + return {}; } std::shared_ptr CCharacterFactory::CDummyFactory::LoadResourcePartAsync(const urde::SObjectTag& tag, - u32 off, u32 size, - void* target) -{ - return {}; + u32 off, u32 size, void* target) { + return {}; } -std::unique_ptr CCharacterFactory::CDummyFactory::LoadResourceSync(const urde::SObjectTag& tag) -{ - return {}; +std::unique_ptr CCharacterFactory::CDummyFactory::LoadResourceSync(const urde::SObjectTag& tag) { return {}; } + +std::unique_ptr CCharacterFactory::CDummyFactory::LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, + u32 size) { + return {}; } -std::unique_ptr CCharacterFactory::CDummyFactory::LoadNewResourcePartSync(const urde::SObjectTag& tag, - u32 off, u32 size) -{ - return {}; +std::unique_ptr CCharacterFactory::CreateCharacter(int charIdx, bool loop, + const TLockedToken& factory, + int defaultAnim, int drawInsts) const { + const CCharacterInfo& charInfo = x4_charInfoDB[charIdx]; + CVParamTransfer charParm(new TObjOwnerParam(&charInfo)); + + TToken skinnedModel = const_cast(this)->x70_cacheResPool.GetObj( + {FourCC(drawInsts << 16), charInfo.GetModelId()}, charParm); + + std::experimental::optional> iceModel; + if (charInfo.GetIceModelId().IsValid() && charInfo.GetIceSkinRulesId().IsValid()) + iceModel.emplace(const_cast(this)->x70_cacheResPool.GetObj( + {FourCC((drawInsts << 16) | 1), charInfo.GetIceModelId()}, charParm)); + + return std::make_unique(x68_selfId, charInfo, defaultAnim, charIdx, loop, x14_charLayoutInfoDB[charIdx], + skinnedModel, iceModel, x24_sysContext, x28_animMgr, x2c_transMgr, factory, + drawInsts); } -std::unique_ptr -CCharacterFactory::CreateCharacter(int charIdx, bool loop, - const TLockedToken& factory, - int defaultAnim, int drawInsts) const -{ - const CCharacterInfo& charInfo = x4_charInfoDB[charIdx]; - CVParamTransfer charParm(new TObjOwnerParam(&charInfo)); - - TToken skinnedModel = - const_cast(this)->x70_cacheResPool.GetObj - ({FourCC(drawInsts << 16), charInfo.GetModelId()}, charParm); - - std::experimental::optional> iceModel; - if (charInfo.GetIceModelId().IsValid() && - charInfo.GetIceSkinRulesId().IsValid()) - iceModel.emplace(const_cast(this)->x70_cacheResPool.GetObj - ({FourCC((drawInsts << 16) | 1), charInfo.GetIceModelId()}, charParm)); - - return std::make_unique(x68_selfId, charInfo, defaultAnim, charIdx, loop, - x14_charLayoutInfoDB[charIdx], skinnedModel, - iceModel, x24_sysContext, x28_animMgr, x2c_transMgr, - factory, drawInsts); +CAssetId CCharacterFactory::GetEventResourceIdForAnimResourceId(CAssetId id) const { + auto search = std::find_if(x58_animResources.cbegin(), x58_animResources.cend(), + [&](const std::pair& elem) -> bool { return id == elem.first; }); + if (search == x58_animResources.cend()) + return CAssetId(); + return search->second; } -CAssetId CCharacterFactory::GetEventResourceIdForAnimResourceId(CAssetId id) const -{ - auto search = std::find_if(x58_animResources.cbegin(), x58_animResources.cend(), - [&](const std::pair& elem) -> bool - { - return id == elem.first; - }); - if (search == x58_animResources.cend()) - return CAssetId(); - return search->second; +const CAdditiveAnimationInfo& CCharacterFactory::FindAdditiveInfo(u32 idx) const { + auto search = rstl::binary_find(x40_additiveInfo.cbegin(), x40_additiveInfo.cend(), idx, + [](const auto& anim) { return anim.first; }); + + if (search == x40_additiveInfo.cend()) + return x50_defaultAdditiveInfo; + return search->second; } -const CAdditiveAnimationInfo& CCharacterFactory::FindAdditiveInfo(u32 idx) const -{ - auto search = rstl::binary_find(x40_additiveInfo.cbegin(), x40_additiveInfo.cend(), idx, - [](const auto& anim) { return anim.first; }); - - if (search == x40_additiveInfo.cend()) - return x50_defaultAdditiveInfo; - return search->second; +bool CCharacterFactory::HasAdditiveInfo(u32 idx) const { + auto search = rstl::binary_find(x40_additiveInfo.cbegin(), x40_additiveInfo.cend(), idx, + [](const auto& anim) { return anim.first; }); + return search != x40_additiveInfo.cend(); } -bool CCharacterFactory::HasAdditiveInfo(u32 idx) const -{ - auto search = rstl::binary_find(x40_additiveInfo.cbegin(), x40_additiveInfo.cend(), idx, - [](const auto& anim) { return anim.first; }); - return search != x40_additiveInfo.cend(); -} - -std::vector -CCharacterFactory::GetCharacterInfoDB(const CAnimCharacterSet& ancs) -{ - std::vector ret; - const std::map& charInfoMap = ancs.GetCharacterSet().GetCharacterInfoMap(); - ret.reserve(charInfoMap.size()); - for (const auto& charInfo : charInfoMap) - ret.push_back(charInfo.second); - return ret; +std::vector CCharacterFactory::GetCharacterInfoDB(const CAnimCharacterSet& ancs) { + std::vector ret; + const std::map& charInfoMap = ancs.GetCharacterSet().GetCharacterInfoMap(); + ret.reserve(charInfoMap.size()); + for (const auto& charInfo : charInfoMap) + ret.push_back(charInfo.second); + return ret; } std::vector> -CCharacterFactory::GetCharLayoutInfoDB(CSimplePool& store, - const std::vector& chars) -{ - std::vector> ret; - ret.reserve(chars.size()); - for (const CCharacterInfo& charInfo : chars) - ret.push_back(store.GetObj({SBIG('CINF'), charInfo.GetCharLayoutInfoId()})); - return ret; +CCharacterFactory::GetCharLayoutInfoDB(CSimplePool& store, const std::vector& chars) { + std::vector> ret; + ret.reserve(chars.size()); + for (const CCharacterInfo& charInfo : chars) + ret.push_back(store.GetObj({SBIG('CINF'), charInfo.GetCharLayoutInfoId()})); + return ret; } -CCharacterFactory::CCharacterFactory(CSimplePool& store, - const CAnimCharacterSet& ancs, - CAssetId selfId) -: x4_charInfoDB(GetCharacterInfoDB(ancs)), - x14_charLayoutInfoDB(GetCharLayoutInfoDB(store, x4_charInfoDB)), - x24_sysContext(std::make_shared( - TToken( - std::make_unique(ancs.GetAnimationSet().GetTransitions(), - ancs.GetAnimationSet().GetHalfTransitions(), - ancs.GetAnimationSet().GetDefaultTransition())), - 2334, store)), - x28_animMgr(std::make_shared( - TToken( - std::make_unique( - ancs.GetAnimationSet().GetAnimations())), *x24_sysContext)), - x2c_transMgr(std::make_shared(*x24_sysContext)), - x40_additiveInfo(ancs.GetAnimationSet().GetAdditiveInfo()), - x50_defaultAdditiveInfo(ancs.GetAnimationSet().GetDefaultAdditiveInfo()), - x58_animResources(ancs.GetAnimationSet().GetAnimResIds()), - x68_selfId(selfId), - x70_cacheResPool(x6c_dummyFactory) -{ - std::vector primitives; - x28_animMgr->GetAnimationDatabase()->GetAllUniquePrimitives(primitives); - x30_animSourceDB.reserve(primitives.size()); - for (const CPrimitive& prim : primitives) - x30_animSourceDB.push_back(store.GetObj({SBIG('ANIM'), prim.GetAnimResId()})); +CCharacterFactory::CCharacterFactory(CSimplePool& store, const CAnimCharacterSet& ancs, CAssetId selfId) +: x4_charInfoDB(GetCharacterInfoDB(ancs)) +, x14_charLayoutInfoDB(GetCharLayoutInfoDB(store, x4_charInfoDB)) +, x24_sysContext(std::make_shared( + TToken(std::make_unique( + ancs.GetAnimationSet().GetTransitions(), ancs.GetAnimationSet().GetHalfTransitions(), + ancs.GetAnimationSet().GetDefaultTransition())), + 2334, store)) +, x28_animMgr(std::make_shared( + TToken(std::make_unique(ancs.GetAnimationSet().GetAnimations())), + *x24_sysContext)) +, x2c_transMgr(std::make_shared(*x24_sysContext)) +, x40_additiveInfo(ancs.GetAnimationSet().GetAdditiveInfo()) +, x50_defaultAdditiveInfo(ancs.GetAnimationSet().GetDefaultAdditiveInfo()) +, x58_animResources(ancs.GetAnimationSet().GetAnimResIds()) +, x68_selfId(selfId) +, x70_cacheResPool(x6c_dummyFactory) { + std::vector primitives; + x28_animMgr->GetAnimationDatabase()->GetAllUniquePrimitives(primitives); + x30_animSourceDB.reserve(primitives.size()); + for (const CPrimitive& prim : primitives) + x30_animSourceDB.push_back(store.GetObj({SBIG('ANIM'), prim.GetAnimResId()})); } -} +} // namespace urde diff --git a/Runtime/Character/CCharacterFactory.hpp b/Runtime/Character/CCharacterFactory.hpp index 0d106f9b1..b6d8a4a7e 100644 --- a/Runtime/Character/CCharacterFactory.hpp +++ b/Runtime/Character/CCharacterFactory.hpp @@ -6,8 +6,7 @@ #include "CSimplePool.hpp" #include "CAnimationSet.hpp" -namespace urde -{ +namespace urde { class CSimplePool; class CAnimCharacterSet; class CCharacterInfo; @@ -19,60 +18,55 @@ class CTransitionManager; class CAllFormatsAnimSource; class CAnimData; -class CCharacterFactory : public IObjFactory -{ +class CCharacterFactory : public IObjFactory { public: - class CDummyFactory : public IFactory - { - public: - CFactoryFnReturn Build(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef); - void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr*, CObjectReference* selfRef); - void CancelBuild(const SObjectTag&); - bool CanBuild(const SObjectTag&); - const SObjectTag* GetResourceIdByName(std::string_view) const; - FourCC GetResourceTypeById(CAssetId id) const; + class CDummyFactory : public IFactory { + public: + CFactoryFnReturn Build(const SObjectTag&, const CVParamTransfer&, CObjectReference* selfRef); + void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr*, CObjectReference* selfRef); + void CancelBuild(const SObjectTag&); + bool CanBuild(const SObjectTag&); + const SObjectTag* GetResourceIdByName(std::string_view) const; + FourCC GetResourceTypeById(CAssetId id) const; - void EnumerateResources(const std::function& lambda) const; - void EnumerateNamedResources(const std::function& lambda) const; + void EnumerateResources(const std::function& lambda) const; + void EnumerateNamedResources(const std::function& lambda) const; - u32 ResourceSize(const urde::SObjectTag& tag); - std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target); - std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target); - std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); - std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size); - }; + u32 ResourceSize(const urde::SObjectTag& tag); + std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target); + std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target); + std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag); + std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size); + }; private: - std::vector x4_charInfoDB; - std::vector> x14_charLayoutInfoDB; - std::shared_ptr x24_sysContext; - std::shared_ptr x28_animMgr; - std::shared_ptr x2c_transMgr; - std::vector> x30_animSourceDB; - std::vector> x40_additiveInfo; - CAdditiveAnimationInfo x50_defaultAdditiveInfo; - std::vector> x58_animResources; - CAssetId x68_selfId; - CDummyFactory x6c_dummyFactory; - CSimplePool x70_cacheResPool; + std::vector x4_charInfoDB; + std::vector> x14_charLayoutInfoDB; + std::shared_ptr x24_sysContext; + std::shared_ptr x28_animMgr; + std::shared_ptr x2c_transMgr; + std::vector> x30_animSourceDB; + std::vector> x40_additiveInfo; + CAdditiveAnimationInfo x50_defaultAdditiveInfo; + std::vector> x58_animResources; + CAssetId x68_selfId; + CDummyFactory x6c_dummyFactory; + CSimplePool x70_cacheResPool; - static std::vector GetCharacterInfoDB(const CAnimCharacterSet& ancs); - static std::vector> - GetCharLayoutInfoDB(CSimplePool& store, - const std::vector& chars); + static std::vector GetCharacterInfoDB(const CAnimCharacterSet& ancs); + static std::vector> GetCharLayoutInfoDB(CSimplePool& store, + const std::vector& chars); public: - CCharacterFactory(CSimplePool& store, const CAnimCharacterSet& ancs, CAssetId); + CCharacterFactory(CSimplePool& store, const CAnimCharacterSet& ancs, CAssetId); - std::unique_ptr CreateCharacter(int charIdx, bool loop, - const TLockedToken& factory, - int defaultAnim, int drawInsts) const; - CAssetId GetEventResourceIdForAnimResourceId(CAssetId animId) const; + std::unique_ptr CreateCharacter(int charIdx, bool loop, const TLockedToken& factory, + int defaultAnim, int drawInsts) const; + CAssetId GetEventResourceIdForAnimResourceId(CAssetId animId) const; - const CCharacterInfo& GetCharInfo(int charIdx) const { return x4_charInfoDB[charIdx]; } - const CAdditiveAnimationInfo& FindAdditiveInfo(u32 idx) const; - bool HasAdditiveInfo(u32 idx) const; + const CCharacterInfo& GetCharInfo(int charIdx) const { return x4_charInfoDB[charIdx]; } + const CAdditiveAnimationInfo& FindAdditiveInfo(u32 idx) const; + bool HasAdditiveInfo(u32 idx) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CCharacterInfo.cpp b/Runtime/Character/CCharacterInfo.cpp index 4c72fa0cb..6b7eddb5e 100644 --- a/Runtime/Character/CCharacterInfo.cpp +++ b/Runtime/Character/CCharacterInfo.cpp @@ -1,113 +1,98 @@ #include "CCharacterInfo.hpp" -namespace urde -{ +namespace urde { -CCharacterInfo::CParticleResData::CParticleResData(CInputStream& in, u16 tableCount) -{ - u32 partCount = in.readUint32Big(); - x0_part.reserve(partCount); - for (u32 i=0 ; i 5) - { - u32 elscCount = in.readUint32Big(); - x30_elsc.reserve(elscCount); - for (u32 i=0 ; i 5) { + u32 elscCount = in.readUint32Big(); + x30_elsc.reserve(elscCount); + for (u32 i = 0; i < elscCount; ++i) + x30_elsc.push_back(in.readUint32Big()); + } } -static std::vector>> -MakeAnimInfoVector(CInputStream& in) -{ - std::vector>> ret; - u32 animInfoCount = in.readUint32Big(); - ret.reserve(animInfoCount); - for (u32 i=0 ; i>> MakeAnimInfoVector(CInputStream& in) { + std::vector>> ret; + u32 animInfoCount = in.readUint32Big(); + ret.reserve(animInfoCount); + for (u32 i = 0; i < animInfoCount; ++i) { + s32 idx = in.readInt32Big(); + std::string a = in.readString(); + std::string b = in.readString(); + ret.emplace_back(idx, std::make_pair(a, b)); + } + return ret; } CCharacterInfo::CCharacterInfo(CInputStream& in) -: x0_tableCount(in.readUint16Big()), - x4_name(in.readString()), - x14_cmdl(in.readUint32Big()), - x18_cskr(in.readUint32Big()), - x1c_cinf(in.readUint32Big()), - x20_animInfo(MakeAnimInfoVector(in)), - x30_pasDatabase(in), - x44_partRes(in, x0_tableCount), - x84_unk(in.readUint32Big()) -{ - if (x0_tableCount > 1) - { - u32 aabbCount = in.readUint32Big(); - x88_aabbs.reserve(aabbCount); - for (u32 i=0 ; i 1) { + u32 aabbCount = in.readUint32Big(); + x88_aabbs.reserve(aabbCount); + for (u32 i = 0; i < aabbCount; ++i) { + std::string name = in.readString(); + x88_aabbs.emplace_back(name, zeus::CAABox()); + x88_aabbs.back().second.readBoundingBoxBig(in); } + } - if (x0_tableCount > 2) - { - u32 effectCount = in.readUint32Big(); - x98_effects.reserve(effectCount); - for (u32 i=0 ; i()); - std::vector& comps = x98_effects.back().second; - u32 compCount = in.readUint32Big(); - comps.reserve(compCount); - for (u32 j=0 ; j 2) { + u32 effectCount = in.readUint32Big(); + x98_effects.reserve(effectCount); + for (u32 i = 0; i < effectCount; ++i) { + std::string name = in.readString(); + x98_effects.emplace_back(name, std::vector()); + std::vector& comps = x98_effects.back().second; + u32 compCount = in.readUint32Big(); + comps.reserve(compCount); + for (u32 j = 0; j < compCount; ++j) + comps.emplace_back(in); } + } - if (x0_tableCount > 3) - { - xa8_cmdlOverlay = in.readUint32Big(); - xac_cskrOverlay = in.readUint32Big(); - } + if (x0_tableCount > 3) { + xa8_cmdlOverlay = in.readUint32Big(); + xac_cskrOverlay = in.readUint32Big(); + } - if (x0_tableCount > 4) - { - u32 aidxCount = in.readUint32Big(); - xb0_animIdxs.reserve(aidxCount); - for (u32 i=0 ; i 4) { + u32 aidxCount = in.readUint32Big(); + xb0_animIdxs.reserve(aidxCount); + for (u32 i = 0; i < aidxCount; ++i) + xb0_animIdxs.push_back(in.readInt32Big()); + } } -const s32 CCharacterInfo::GetAnimationIndex(std::string_view name) const -{ - for (const auto& pair : x20_animInfo) - { - if (pair.second.second.compare(name.data()) == 0) - return pair.first; - } +const s32 CCharacterInfo::GetAnimationIndex(std::string_view name) const { + for (const auto& pair : x20_animInfo) { + if (pair.second.second.compare(name.data()) == 0) + return pair.first; + } - return -1; + return -1; } -} +} // namespace urde diff --git a/Runtime/Character/CCharacterInfo.hpp b/Runtime/Character/CCharacterInfo.hpp index 4f06738e8..e94c6e214 100644 --- a/Runtime/Character/CCharacterInfo.hpp +++ b/Runtime/Character/CCharacterInfo.hpp @@ -5,63 +5,58 @@ #include "zeus/CAABox.hpp" #include "CEffectComponent.hpp" -namespace urde -{ +namespace urde { -class CCharacterInfo -{ - friend class CAnimData; +class CCharacterInfo { + friend class CAnimData; public: - struct CParticleResData - { - std::vector x0_part; - std::vector x10_swhc; - std::vector x20_elsc; - std::vector x30_elsc; - CParticleResData(CInputStream& in, u16 tableCount); - }; + struct CParticleResData { + std::vector x0_part; + std::vector x10_swhc; + std::vector x20_elsc; + std::vector x30_elsc; + CParticleResData(CInputStream& in, u16 tableCount); + }; private: - u16 x0_tableCount; - std::string x4_name; - CAssetId x14_cmdl; - CAssetId x18_cskr; - CAssetId x1c_cinf; - std::vector>> x20_animInfo; - CPASDatabase x30_pasDatabase; - CParticleResData x44_partRes; - u32 x84_unk; - std::vector> x88_aabbs; - std::vector>> x98_effects; + u16 x0_tableCount; + std::string x4_name; + CAssetId x14_cmdl; + CAssetId x18_cskr; + CAssetId x1c_cinf; + std::vector>> x20_animInfo; + CPASDatabase x30_pasDatabase; + CParticleResData x44_partRes; + u32 x84_unk; + std::vector> x88_aabbs; + std::vector>> x98_effects; - CAssetId xa8_cmdlOverlay = 0; - CAssetId xac_cskrOverlay = 0; + CAssetId xa8_cmdlOverlay = 0; + CAssetId xac_cskrOverlay = 0; - std::vector xb0_animIdxs; + std::vector xb0_animIdxs; public: - CCharacterInfo(CInputStream& in); + CCharacterInfo(CInputStream& in); - std::string_view GetCharacterName() const { return x4_name; } - CAssetId GetModelId() const { return x14_cmdl; } - CAssetId GetSkinRulesId() const { return x18_cskr; } - CAssetId GetCharLayoutInfoId() const { return x1c_cinf; } + std::string_view GetCharacterName() const { return x4_name; } + CAssetId GetModelId() const { return x14_cmdl; } + CAssetId GetSkinRulesId() const { return x18_cskr; } + CAssetId GetCharLayoutInfoId() const { return x1c_cinf; } - const std::vector>& GetAnimBBoxList() const { return x88_aabbs; } - const std::vector>>& GetEffectList() const - { - return x98_effects; - } + const std::vector>& GetAnimBBoxList() const { return x88_aabbs; } + const std::vector>>& GetEffectList() const { + return x98_effects; + } - CAssetId GetIceModelId() const { return xa8_cmdlOverlay; } - CAssetId GetIceSkinRulesId() const { return xac_cskrOverlay; } + CAssetId GetIceModelId() const { return xa8_cmdlOverlay; } + CAssetId GetIceSkinRulesId() const { return xac_cskrOverlay; } - const CParticleResData& GetParticleResData() const { return x44_partRes; } - s32 GetAnimationIndex(s32 idx) const { return xb0_animIdxs.at(idx); } - const CPASDatabase& GetPASDatabase() const { return x30_pasDatabase; } + const CParticleResData& GetParticleResData() const { return x44_partRes; } + s32 GetAnimationIndex(s32 idx) const { return xb0_animIdxs.at(idx); } + const CPASDatabase& GetPASDatabase() const { return x30_pasDatabase; } - const s32 GetAnimationIndex(std::string_view) const; + const s32 GetAnimationIndex(std::string_view) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CCharacterSet.cpp b/Runtime/Character/CCharacterSet.cpp index 229a1c9ec..1ae8be46f 100644 --- a/Runtime/Character/CCharacterSet.cpp +++ b/Runtime/Character/CCharacterSet.cpp @@ -1,17 +1,13 @@ #include "CCharacterSet.hpp" -namespace urde -{ +namespace urde { -CCharacterSet::CCharacterSet(CInputStream& in) -: x0_version(in.readUint16Big()) -{ - u32 charCount = in.readUint32Big(); - for (u32 i=0 ; i x4_characters; -class CCharacterSet -{ - u16 x0_version; - std::map x4_characters; public: - CCharacterSet(CInputStream& in); - const std::map& GetCharacterInfoMap() const {return x4_characters;} + CCharacterSet(CInputStream& in); + const std::map& GetCharacterInfoMap() const { return x4_characters; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CEffectComponent.cpp b/Runtime/Character/CEffectComponent.cpp index 1250abdb0..c96795e30 100644 --- a/Runtime/Character/CEffectComponent.cpp +++ b/Runtime/Character/CEffectComponent.cpp @@ -1,18 +1,16 @@ #include "CEffectComponent.hpp" -namespace urde -{ +namespace urde { SObjectTag CEffectComponent::GetSObjectTagFromStream(CInputStream& in) { return SObjectTag(in); } -CEffectComponent::CEffectComponent(CInputStream& in) -{ - x0_name = in.readString(); - x10_tag = GetSObjectTagFromStream(in); - x18_boneName = in.readString(); - x28_scale = in.readFloatBig(); - x2c_parentedMode = CParticleData::EParentedMode(in.readUint32Big()); - x30_flags = in.readUint32Big(); +CEffectComponent::CEffectComponent(CInputStream& in) { + x0_name = in.readString(); + x10_tag = GetSObjectTagFromStream(in); + x18_boneName = in.readString(); + x28_scale = in.readFloatBig(); + x2c_parentedMode = CParticleData::EParentedMode(in.readUint32Big()); + x30_flags = in.readUint32Big(); } -} +} // namespace urde diff --git a/Runtime/Character/CEffectComponent.hpp b/Runtime/Character/CEffectComponent.hpp index f2e4e4acf..06e8b992a 100644 --- a/Runtime/Character/CEffectComponent.hpp +++ b/Runtime/Character/CEffectComponent.hpp @@ -4,28 +4,26 @@ #include "RetroTypes.hpp" #include "CParticleData.hpp" -namespace urde -{ +namespace urde { + +class CEffectComponent { + std::string x0_name; + SObjectTag x10_tag; + std::string x18_boneName; + float x28_scale; + CParticleData::EParentedMode x2c_parentedMode; + u32 x30_flags; + static SObjectTag GetSObjectTagFromStream(CInputStream& in); -class CEffectComponent -{ - std::string x0_name; - SObjectTag x10_tag; - std::string x18_boneName; - float x28_scale; - CParticleData::EParentedMode x2c_parentedMode; - u32 x30_flags; - static SObjectTag GetSObjectTagFromStream(CInputStream& in); public: - CEffectComponent(CInputStream& in); + CEffectComponent(CInputStream& in); - std::string_view GetComponentName() const { return x0_name; } - const SObjectTag& GetParticleTag() const { return x10_tag; } - std::string_view GetSegmentName() const { return x18_boneName; } - float GetScale() const { return x28_scale; } - CParticleData::EParentedMode GetParentedMode() const { return x2c_parentedMode; } - u32 GetFlags() const { return x30_flags; } + std::string_view GetComponentName() const { return x0_name; } + const SObjectTag& GetParticleTag() const { return x10_tag; } + std::string_view GetSegmentName() const { return x18_boneName; } + float GetScale() const { return x28_scale; } + CParticleData::EParentedMode GetParentedMode() const { return x2c_parentedMode; } + u32 GetFlags() const { return x30_flags; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CFBStreamedAnimReader.cpp b/Runtime/Character/CFBStreamedAnimReader.cpp index e0a68c9cc..9e2c26b7d 100644 --- a/Runtime/Character/CFBStreamedAnimReader.cpp +++ b/Runtime/Character/CFBStreamedAnimReader.cpp @@ -2,571 +2,497 @@ #include "CSegIdList.hpp" #include "CSegStatementSet.hpp" -namespace urde -{ +namespace urde { -void CFBStreamedAnimReaderTotals::Allocate(u32 chanCount) -{ - u32 chan2 = chanCount * 2; - u32 chan32 = chanCount * 32; +void CFBStreamedAnimReaderTotals::Allocate(u32 chanCount) { + u32 chan2 = chanCount * 2; + u32 chan32 = chanCount * 32; - size_t sz = chan32 + chanCount + chan2 + chan32; - x0_buffer.reset(new u8[sz]); - memset(x0_buffer.get(), 0, sz); - x4_cumulativeInts32 = reinterpret_cast(x0_buffer.get()); - x8_hasTrans1 = reinterpret_cast(x4_cumulativeInts32 + chanCount * 8); - xc_segIds2 = reinterpret_cast(x8_hasTrans1 + chanCount); - x10_computedFloats32 = reinterpret_cast(xc_segIds2 + chanCount); + size_t sz = chan32 + chanCount + chan2 + chan32; + x0_buffer.reset(new u8[sz]); + memset(x0_buffer.get(), 0, sz); + x4_cumulativeInts32 = reinterpret_cast(x0_buffer.get()); + x8_hasTrans1 = reinterpret_cast(x4_cumulativeInts32 + chanCount * 8); + xc_segIds2 = reinterpret_cast(x8_hasTrans1 + chanCount); + x10_computedFloats32 = reinterpret_cast(xc_segIds2 + chanCount); } -void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& source) -{ - x1c_curKey = 0; - x20_calculated = false; - const u8* chans = source.GetPerChannelHeaders(); - u32 boneChanCount = *reinterpret_cast(chans); - chans += 4; +void CFBStreamedAnimReaderTotals::Initialize(const CFBStreamedCompression& source) { + x1c_curKey = 0; + x20_calculated = false; + const u8* chans = source.GetPerChannelHeaders(); + u32 boneChanCount = *reinterpret_cast(chans); + chans += 4; - if (source.m_pc) - { - for (unsigned b=0 ; b(chans); - chans += 8; + if (source.m_pc) { + for (unsigned b = 0; b < boneChanCount; ++b) { + xc_segIds2[b] = *reinterpret_cast(chans); + chans += 8; - s32* cumulativesOut = &x4_cumulativeInts32[8*b]; - const s32* cumulativesIn = reinterpret_cast(chans); - cumulativesOut[0] = 0; - cumulativesOut[1] = cumulativesIn[0] >> 8; - cumulativesOut[2] = cumulativesIn[1] >> 8; - cumulativesOut[3] = cumulativesIn[2] >> 8; - chans += 12; + s32* cumulativesOut = &x4_cumulativeInts32[8 * b]; + const s32* cumulativesIn = reinterpret_cast(chans); + cumulativesOut[0] = 0; + cumulativesOut[1] = cumulativesIn[0] >> 8; + cumulativesOut[2] = cumulativesIn[1] >> 8; + cumulativesOut[3] = cumulativesIn[2] >> 8; + chans += 12; - u32 tCount = *reinterpret_cast(chans); - chans += 4; - if (tCount) - { - x8_hasTrans1[b] = true; - const s32* cumulativesIn = reinterpret_cast(chans); - cumulativesOut[4] = cumulativesIn[0] >> 8; - cumulativesOut[5] = cumulativesIn[1] >> 8; - cumulativesOut[6] = cumulativesIn[2] >> 8; - chans += 12; - } - else - x8_hasTrans1[b] = false; - } + u32 tCount = *reinterpret_cast(chans); + chans += 4; + if (tCount) { + x8_hasTrans1[b] = true; + const s32* cumulativesIn = reinterpret_cast(chans); + cumulativesOut[4] = cumulativesIn[0] >> 8; + cumulativesOut[5] = cumulativesIn[1] >> 8; + cumulativesOut[6] = cumulativesIn[2] >> 8; + chans += 12; + } else + x8_hasTrans1[b] = false; } - else - { - for (unsigned b=0 ; b(chans); - chans += 6; + } else { + for (unsigned b = 0; b < boneChanCount; ++b) { + xc_segIds2[b] = *reinterpret_cast(chans); + chans += 6; - s32* cumulativesOut = &x4_cumulativeInts32[8*b]; - cumulativesOut[0] = 0; - cumulativesOut[1] = *reinterpret_cast(chans); - cumulativesOut[2] = *reinterpret_cast(chans + 3); - cumulativesOut[3] = *reinterpret_cast(chans + 6); - chans += 9; + s32* cumulativesOut = &x4_cumulativeInts32[8 * b]; + cumulativesOut[0] = 0; + cumulativesOut[1] = *reinterpret_cast(chans); + cumulativesOut[2] = *reinterpret_cast(chans + 3); + cumulativesOut[3] = *reinterpret_cast(chans + 6); + chans += 9; - u16 tCount = *reinterpret_cast(chans); - chans += 2; - if (tCount) - { - x8_hasTrans1[b] = true; - cumulativesOut[4] = *reinterpret_cast(chans); - cumulativesOut[5] = *reinterpret_cast(chans + 3); - cumulativesOut[6] = *reinterpret_cast(chans + 6); - chans += 9; - } - else - x8_hasTrans1[b] = false; - } + u16 tCount = *reinterpret_cast(chans); + chans += 2; + if (tCount) { + x8_hasTrans1[b] = true; + cumulativesOut[4] = *reinterpret_cast(chans); + cumulativesOut[5] = *reinterpret_cast(chans + 3); + cumulativesOut[6] = *reinterpret_cast(chans + 6); + chans += 9; + } else + x8_hasTrans1[b] = false; } + } } -CFBStreamedAnimReaderTotals::CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source) -{ - const CFBStreamedCompression::Header& header = source.MainHeader(); - x14_rotDiv = header.rotDiv; - x18_transMult = header.translationMult; +CFBStreamedAnimReaderTotals::CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source) { + const CFBStreamedCompression::Header& header = source.MainHeader(); + x14_rotDiv = header.rotDiv; + x18_transMult = header.translationMult; - const u8* chans = source.GetPerChannelHeaders(); - x24_boneChanCount = *reinterpret_cast(chans); - Allocate(x24_boneChanCount); - Initialize(source); + const u8* chans = source.GetPerChannelHeaders(); + x24_boneChanCount = *reinterpret_cast(chans); + Allocate(x24_boneChanCount); + Initialize(source); } -void CFBStreamedAnimReaderTotals::IncrementInto(CBitLevelLoader& loader, - const CFBStreamedCompression& source, - CFBStreamedAnimReaderTotals& dest) -{ - dest.x20_calculated = false; +void CFBStreamedAnimReaderTotals::IncrementInto(CBitLevelLoader& loader, const CFBStreamedCompression& source, + CFBStreamedAnimReaderTotals& dest) { + dest.x20_calculated = false; - const u8* chans = source.GetPerChannelHeaders(); - u32 boneChanCount = *reinterpret_cast(chans); - chans += 4; + const u8* chans = source.GetPerChannelHeaders(); + u32 boneChanCount = *reinterpret_cast(chans); + chans += 4; - if (source.m_pc) - { - for (unsigned b=0 ; b(chans); - cumulativesOut[0] = loader.LoadBool(); - cumulativesOut[1] = cumulativesIn[1] + loader.LoadSigned(qsIn[0] & 0xff); - cumulativesOut[2] = cumulativesIn[2] + loader.LoadSigned(qsIn[1] & 0xff); - cumulativesOut[3] = cumulativesIn[3] + loader.LoadSigned(qsIn[2] & 0xff); - chans += 12; + const s32* cumulativesIn = &x4_cumulativeInts32[8 * b]; + s32* cumulativesOut = &dest.x4_cumulativeInts32[8 * b]; + const s32* qsIn = reinterpret_cast(chans); + cumulativesOut[0] = loader.LoadBool(); + cumulativesOut[1] = cumulativesIn[1] + loader.LoadSigned(qsIn[0] & 0xff); + cumulativesOut[2] = cumulativesIn[2] + loader.LoadSigned(qsIn[1] & 0xff); + cumulativesOut[3] = cumulativesIn[3] + loader.LoadSigned(qsIn[2] & 0xff); + chans += 12; - u32 tCount = *reinterpret_cast(chans); - chans += 4; - if (tCount) - { - const s32* qsIn = reinterpret_cast(chans); - cumulativesOut[4] = cumulativesIn[4] + loader.LoadSigned(qsIn[0] & 0xff); - cumulativesOut[5] = cumulativesIn[5] + loader.LoadSigned(qsIn[1] & 0xff); - cumulativesOut[6] = cumulativesIn[6] + loader.LoadSigned(qsIn[2] & 0xff); - chans += 12; - } - } + u32 tCount = *reinterpret_cast(chans); + chans += 4; + if (tCount) { + const s32* qsIn = reinterpret_cast(chans); + cumulativesOut[4] = cumulativesIn[4] + loader.LoadSigned(qsIn[0] & 0xff); + cumulativesOut[5] = cumulativesIn[5] + loader.LoadSigned(qsIn[1] & 0xff); + cumulativesOut[6] = cumulativesIn[6] + loader.LoadSigned(qsIn[2] & 0xff); + chans += 12; + } } - else - { - for (unsigned b=0 ; b(chans + 2)); - cumulativesOut[2] = cumulativesIn[2] + loader.LoadSigned(*reinterpret_cast(chans + 5)); - cumulativesOut[3] = cumulativesIn[3] + loader.LoadSigned(*reinterpret_cast(chans + 8)); - chans += 9; + const s32* cumulativesIn = &x4_cumulativeInts32[8 * b]; + s32* cumulativesOut = &dest.x4_cumulativeInts32[8 * b]; + cumulativesOut[0] = loader.LoadBool(); + cumulativesOut[1] = cumulativesIn[1] + loader.LoadSigned(*reinterpret_cast(chans + 2)); + cumulativesOut[2] = cumulativesIn[2] + loader.LoadSigned(*reinterpret_cast(chans + 5)); + cumulativesOut[3] = cumulativesIn[3] + loader.LoadSigned(*reinterpret_cast(chans + 8)); + chans += 9; - u16 tCount = *reinterpret_cast(chans); - chans += 2; - if (tCount) - { - cumulativesOut[4] = cumulativesIn[4] + loader.LoadSigned(*reinterpret_cast(chans + 2)); - cumulativesOut[5] = cumulativesIn[5] + loader.LoadSigned(*reinterpret_cast(chans + 5)); - cumulativesOut[6] = cumulativesIn[5] + loader.LoadSigned(*reinterpret_cast(chans + 8)); - chans += 9; - } - } + u16 tCount = *reinterpret_cast(chans); + chans += 2; + if (tCount) { + cumulativesOut[4] = cumulativesIn[4] + loader.LoadSigned(*reinterpret_cast(chans + 2)); + cumulativesOut[5] = cumulativesIn[5] + loader.LoadSigned(*reinterpret_cast(chans + 5)); + cumulativesOut[6] = cumulativesIn[5] + loader.LoadSigned(*reinterpret_cast(chans + 8)); + chans += 9; + } } + } - dest.x1c_curKey = x1c_curKey + 1; + dest.x1c_curKey = x1c_curKey + 1; } -void CFBStreamedAnimReaderTotals::CalculateDown() -{ - for (unsigned b=0 ; b& source) -: x0_source(source), xc_rotsAndOffs(source->xc_rotsAndOffs.get()), x14_a(*source), x3c_b(*source) -{ -} +: x0_source(source), xc_rotsAndOffs(source->xc_rotsAndOffs.get()), x14_a(*source), x3c_b(*source) {} -void CFBStreamedPairOfTotals::SetTime(CBitLevelLoader& loader, const CCharAnimTime& time) -{ - /* Implementation is a bit different than original; - * T evaluated pre-emptively with key indices. - * CalculateDown is also called here as needed. */ +void CFBStreamedPairOfTotals::SetTime(CBitLevelLoader& loader, const CCharAnimTime& time) { + /* Implementation is a bit different than original; + * T evaluated pre-emptively with key indices. + * CalculateDown is also called here as needed. */ - const CFBStreamedCompression::Header& header = x0_source->MainHeader(); - CCharAnimTime interval(header.interval); - const u32* timeBitmap = x0_source->GetTimes(); - CCharAnimTime priorTime(0); - CCharAnimTime curTime(0); + const CFBStreamedCompression::Header& header = x0_source->MainHeader(); + CCharAnimTime interval(header.interval); + const u32* timeBitmap = x0_source->GetTimes(); + CCharAnimTime priorTime(0); + CCharAnimTime curTime(0); - int prior = -1; - int next = -1; - int cur = 0; - for (unsigned b=0 ; b> bit) & 1) - { - if (curTime <= time) - { - prior = cur; - priorTime = curTime; - } - else if (curTime > time) - { - next = cur; - if (prior == -1) - { - prior = cur; - priorTime = curTime; - x78_t = 0.f; - } - else - x78_t = (time - priorTime) / (curTime - priorTime); + int prior = -1; + int next = -1; + int cur = 0; + for (unsigned b = 0; b < timeBitmap[0]; ++b) { + int word = b / 32; + int bit = b % 32; + if ((timeBitmap[word + 1] >> bit) & 1) { + if (curTime <= time) { + prior = cur; + priorTime = curTime; + } else if (curTime > time) { + next = cur; + if (prior == -1) { + prior = cur; + priorTime = curTime; + x78_t = 0.f; + } else + x78_t = (time - priorTime) / (curTime - priorTime); - break; - } - ++cur; - } - curTime += interval; + break; + } + ++cur; } + curTime += interval; + } - if (prior != -1 && u32(prior) < Prior().x1c_curKey) - { - Prior().Initialize(*x0_source); - Next().Initialize(*x0_source); - loader.Reset(); - } + if (prior != -1 && u32(prior) < Prior().x1c_curKey) { + Prior().Initialize(*x0_source); + Next().Initialize(*x0_source); + loader.Reset(); + } - if (next != -1) - while (u32(next) > Next().x1c_curKey) - DoIncrement(loader); + if (next != -1) + while (u32(next) > Next().x1c_curKey) + DoIncrement(loader); - if (!Prior().IsCalculated()) - Prior().CalculateDown(); - if (!Next().IsCalculated()) - Next().CalculateDown(); + if (!Prior().IsCalculated()) + Prior().CalculateDown(); + if (!Next().IsCalculated()) + Next().CalculateDown(); } -void CFBStreamedPairOfTotals::DoIncrement(CBitLevelLoader& loader) -{ - x10_nextSel ^= 1; - Prior().IncrementInto(loader, *x0_source, Next()); +void CFBStreamedPairOfTotals::DoIncrement(CBitLevelLoader& loader) { + x10_nextSel ^= 1; + Prior().IncrementInto(loader, *x0_source, Next()); } -u32 CBitLevelLoader::LoadUnsigned(u8 q) -{ - u32 byteCur = (m_bitIdx / 32) * 4; - u32 bitRem = m_bitIdx % 32; +u32 CBitLevelLoader::LoadUnsigned(u8 q) { + u32 byteCur = (m_bitIdx / 32) * 4; + u32 bitRem = m_bitIdx % 32; - /* Fill 32 bit buffer with region containing bits */ - /* Make them least significant */ - u32 tempBuf = *reinterpret_cast(m_data + byteCur) >> bitRem; + /* Fill 32 bit buffer with region containing bits */ + /* Make them least significant */ + u32 tempBuf = *reinterpret_cast(m_data + byteCur) >> bitRem; - /* If this shift underflows the value, buffer the next 32 bits */ - /* And tack onto shifted buffer */ - if ((bitRem + q) > 32) - { - u32 tempBuf2 = *reinterpret_cast(m_data + byteCur + 4); - tempBuf |= (tempBuf2 << (32 - bitRem)); - } + /* If this shift underflows the value, buffer the next 32 bits */ + /* And tack onto shifted buffer */ + if ((bitRem + q) > 32) { + u32 tempBuf2 = *reinterpret_cast(m_data + byteCur + 4); + tempBuf |= (tempBuf2 << (32 - bitRem)); + } - /* Mask it */ - u32 mask = (1 << q) - 1; - tempBuf &= mask; + /* Mask it */ + u32 mask = (1 << q) - 1; + tempBuf &= mask; - /* Return delta value */ - m_bitIdx += q; - return tempBuf; + /* Return delta value */ + m_bitIdx += q; + return tempBuf; } -s32 CBitLevelLoader::LoadSigned(u8 q) -{ - u32 byteCur = (m_bitIdx / 32) * 4; - u32 bitRem = m_bitIdx % 32; +s32 CBitLevelLoader::LoadSigned(u8 q) { + u32 byteCur = (m_bitIdx / 32) * 4; + u32 bitRem = m_bitIdx % 32; - /* Fill 32 bit buffer with region containing bits */ - /* Make them least significant */ - u32 tempBuf = *reinterpret_cast(m_data + byteCur) >> bitRem; + /* Fill 32 bit buffer with region containing bits */ + /* Make them least significant */ + u32 tempBuf = *reinterpret_cast(m_data + byteCur) >> bitRem; - /* If this shift underflows the value, buffer the next 32 bits */ - /* And tack onto shifted buffer */ - if ((bitRem + q) > 32) - { - u32 tempBuf2 = *reinterpret_cast(m_data + byteCur + 4); - tempBuf |= (tempBuf2 << (32 - bitRem)); - } + /* If this shift underflows the value, buffer the next 32 bits */ + /* And tack onto shifted buffer */ + if ((bitRem + q) > 32) { + u32 tempBuf2 = *reinterpret_cast(m_data + byteCur + 4); + tempBuf |= (tempBuf2 << (32 - bitRem)); + } - /* Mask it */ - u32 mask = (1 << q) - 1; - tempBuf &= mask; + /* Mask it */ + u32 mask = (1 << q) - 1; + tempBuf &= mask; - /* Sign extend */ - u32 sign = (tempBuf >> (q - 1)) & 0x1; - if (sign) - tempBuf |= ~0u << q; + /* Sign extend */ + u32 sign = (tempBuf >> (q - 1)) & 0x1; + if (sign) + tempBuf |= ~0u << q; - /* Return delta value */ - m_bitIdx += q; - return s32(tempBuf); + /* Return delta value */ + m_bitIdx += q; + return s32(tempBuf); } -bool CBitLevelLoader::LoadBool() -{ - u32 byteCur = (m_bitIdx / 32) * 4; - u32 bitRem = m_bitIdx % 32; +bool CBitLevelLoader::LoadBool() { + u32 byteCur = (m_bitIdx / 32) * 4; + u32 bitRem = m_bitIdx % 32; - /* Fill 32 bit buffer with region containing bits */ - /* Make them least significant */ - u32 tempBuf = *reinterpret_cast(m_data + byteCur) >> bitRem; + /* Fill 32 bit buffer with region containing bits */ + /* Make them least significant */ + u32 tempBuf = *reinterpret_cast(m_data + byteCur) >> bitRem; - /* That's it */ - m_bitIdx += 1; - return tempBuf & 0x1; + /* That's it */ + m_bitIdx += 1; + return tempBuf & 0x1; } -CSegIdToIndexConverter::CSegIdToIndexConverter(const CFBStreamedAnimReaderTotals& totals) -{ - std::fill(std::begin(x0_indices), std::end(x0_indices), -1); - for (u32 b=0 ; b= 96) - continue; - x0_indices[segId] = b; - } +CSegIdToIndexConverter::CSegIdToIndexConverter(const CFBStreamedAnimReaderTotals& totals) { + std::fill(std::begin(x0_indices), std::end(x0_indices), -1); + for (u32 b = 0; b < totals.x24_boneChanCount; ++b) { + u16 segId = totals.xc_segIds2[b]; + if (segId >= 96) + continue; + x0_indices[segId] = b; + } } -CFBStreamedAnimReader::CFBStreamedAnimReader(const TSubAnimTypeToken& source, const CCharAnimTime& time) -: CAnimSourceReaderBase(std::make_unique>(source), {}), x54_source(source), - x64_steadyStateInfo(source->IsLooping(), source->GetAnimationDuration(), source->GetRootOffset()), - x7c_totals(source), x104_bitstreamData(source->GetBitstreamPointer()), x108_bitLoader(x104_bitstreamData), - x114_segIdToIndex(x7c_totals.x10_nextSel ? x7c_totals.x14_a : x7c_totals.x3c_b) -{ - x7c_totals.SetTime(x108_bitLoader, CCharAnimTime()); - PostConstruct(time); +CFBStreamedAnimReader::CFBStreamedAnimReader(const TSubAnimTypeToken& source, + const CCharAnimTime& time) +: CAnimSourceReaderBase(std::make_unique>(source), {}) +, x54_source(source) +, x64_steadyStateInfo(source->IsLooping(), source->GetAnimationDuration(), source->GetRootOffset()) +, x7c_totals(source) +, x104_bitstreamData(source->GetBitstreamPointer()) +, x108_bitLoader(x104_bitstreamData) +, x114_segIdToIndex(x7c_totals.x10_nextSel ? x7c_totals.x14_a : x7c_totals.x3c_b) { + x7c_totals.SetTime(x108_bitLoader, CCharAnimTime()); + PostConstruct(time); } -bool CFBStreamedAnimReader::HasOffset(const CSegId& seg) const -{ - s32 idx = x114_segIdToIndex.SegIdToIndex(seg); - if (idx == -1) - return false; - return x7c_totals.Prior().x8_hasTrans1[idx]; +bool CFBStreamedAnimReader::HasOffset(const CSegId& seg) const { + s32 idx = x114_segIdToIndex.SegIdToIndex(seg); + if (idx == -1) + return false; + return x7c_totals.Prior().x8_hasTrans1[idx]; } -zeus::CVector3f CFBStreamedAnimReader::GetOffset(const CSegId& seg) const -{ - s32 idx = x114_segIdToIndex.SegIdToIndex(seg); - if (idx == -1) - return {}; - const float* af = x7c_totals.Prior().GetFloats(idx); - const float* bf = x7c_totals.Next().GetFloats(idx); - zeus::CVector3f a(af[4], af[5], af[6]); - zeus::CVector3f b(bf[4], bf[5], bf[6]); - return zeus::CVector3f::lerp(a, b, x7c_totals.GetT()); +zeus::CVector3f CFBStreamedAnimReader::GetOffset(const CSegId& seg) const { + s32 idx = x114_segIdToIndex.SegIdToIndex(seg); + if (idx == -1) + return {}; + const float* af = x7c_totals.Prior().GetFloats(idx); + const float* bf = x7c_totals.Next().GetFloats(idx); + zeus::CVector3f a(af[4], af[5], af[6]); + zeus::CVector3f b(bf[4], bf[5], bf[6]); + return zeus::CVector3f::lerp(a, b, x7c_totals.GetT()); } -zeus::CQuaternion CFBStreamedAnimReader::GetRotation(const CSegId& seg) const -{ - s32 idx = x114_segIdToIndex.SegIdToIndex(seg); - if (idx == -1) - return {}; - const float* af = x7c_totals.Prior().GetFloats(idx); - const float* bf = x7c_totals.Next().GetFloats(idx); - zeus::CQuaternion a(af[0], af[1], af[2], af[3]); - zeus::CQuaternion b(bf[0], bf[1], bf[2], bf[3]); - return zeus::CQuaternion::slerp(a, b, x7c_totals.GetT()); +zeus::CQuaternion CFBStreamedAnimReader::GetRotation(const CSegId& seg) const { + s32 idx = x114_segIdToIndex.SegIdToIndex(seg); + if (idx == -1) + return {}; + const float* af = x7c_totals.Prior().GetFloats(idx); + const float* bf = x7c_totals.Next().GetFloats(idx); + zeus::CQuaternion a(af[0], af[1], af[2], af[3]); + zeus::CQuaternion b(bf[0], bf[1], bf[2], bf[3]); + return zeus::CQuaternion::slerp(a, b, x7c_totals.GetT()); } SAdvancementResults CFBStreamedAnimReader::VGetAdvancementResults(const CCharAnimTime& dt, - const CCharAnimTime& startOff) const -{ - SAdvancementResults res = {}; - - CCharAnimTime resolveTime = xc_curTime + startOff; - CCharAnimTime animDur = x54_source->GetAnimationDuration(); - if (resolveTime >= animDur || dt.EqualsZero()) - return res; - - const_cast(this)->x7c_totals.SetTime - (const_cast(this)->x108_bitLoader, resolveTime); - zeus::CQuaternion priorQ = GetRotation(3); - zeus::CVector3f priorV = GetOffset(3); - - CCharAnimTime nextTime = resolveTime + dt; - if (nextTime > animDur) - { - nextTime = animDur; - res.x0_remTime = nextTime - animDur; - } - - const_cast(this)->x7c_totals.SetTime - (const_cast(this)->x108_bitLoader, nextTime); - zeus::CQuaternion nextQ = GetRotation(3); - zeus::CVector3f nextV = GetOffset(3); - - res.x8_deltas.xc_rotDelta = priorQ.inverse() * nextQ; - if (HasOffset(3)) - res.x8_deltas.x0_posDelta = res.x8_deltas.xc_rotDelta.transform(nextV - priorV); + const CCharAnimTime& startOff) const { + SAdvancementResults res = {}; + CCharAnimTime resolveTime = xc_curTime + startOff; + CCharAnimTime animDur = x54_source->GetAnimationDuration(); + if (resolveTime >= animDur || dt.EqualsZero()) return res; + + const_cast(this)->x7c_totals.SetTime(const_cast(this)->x108_bitLoader, + resolveTime); + zeus::CQuaternion priorQ = GetRotation(3); + zeus::CVector3f priorV = GetOffset(3); + + CCharAnimTime nextTime = resolveTime + dt; + if (nextTime > animDur) { + nextTime = animDur; + res.x0_remTime = nextTime - animDur; + } + + const_cast(this)->x7c_totals.SetTime(const_cast(this)->x108_bitLoader, + nextTime); + zeus::CQuaternion nextQ = GetRotation(3); + zeus::CVector3f nextV = GetOffset(3); + + res.x8_deltas.xc_rotDelta = priorQ.inverse() * nextQ; + if (HasOffset(3)) + res.x8_deltas.x0_posDelta = res.x8_deltas.xc_rotDelta.transform(nextV - priorV); + + return res; } -void CFBStreamedAnimReader::VSetPhase(float ph) -{ - xc_curTime = x64_steadyStateInfo.GetDuration() * ph; +void CFBStreamedAnimReader::VSetPhase(float ph) { + xc_curTime = x64_steadyStateInfo.GetDuration() * ph; + x7c_totals.SetTime(x108_bitLoader, xc_curTime); + if (x54_source->HasPOIData()) { + UpdatePOIStates(); + if (!xc_curTime.GreaterThanZero()) { + x14_passedBoolCount = 0; + x18_passedIntCount = 0; + x1c_passedParticleCount = 0; + x20_passedSoundCount = 0; + } + } +} + +SAdvancementResults CFBStreamedAnimReader::VReverseView(const CCharAnimTime& time) { return {}; } + +std::unique_ptr CFBStreamedAnimReader::VClone() const { + return std::make_unique(x54_source, xc_curTime); +} + +void CFBStreamedAnimReader::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const { + const_cast(this)->x7c_totals.SetTime(const_cast(this)->x108_bitLoader, + xc_curTime); + + for (const CSegId& id : list.GetList()) { + CAnimPerSegmentData& out = setOut[id]; + out.x0_rotation = GetRotation(id); + out.x1c_hasOffset = HasOffset(id); + if (out.x1c_hasOffset) + out.x10_offset = GetOffset(id); + } +} + +void CFBStreamedAnimReader::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, + const CCharAnimTime& time) const { + const_cast(this)->x7c_totals.SetTime(const_cast(this)->x108_bitLoader, + time); + + for (const CSegId& id : list.GetList()) { + CAnimPerSegmentData& out = setOut[id]; + out.x0_rotation = GetRotation(id); + out.x1c_hasOffset = HasOffset(id); + if (out.x1c_hasOffset) + out.x10_offset = GetOffset(id); + } +} + +SAdvancementResults CFBStreamedAnimReader::VAdvanceView(const CCharAnimTime& dt) { + SAdvancementResults res = {}; + + CCharAnimTime animDur = x54_source->GetAnimationDuration(); + if (xc_curTime == animDur) { + xc_curTime = CCharAnimTime(); x7c_totals.SetTime(x108_bitLoader, xc_curTime); - if (x54_source->HasPOIData()) - { - UpdatePOIStates(); - if (!xc_curTime.GreaterThanZero()) - { - x14_passedBoolCount = 0; - x18_passedIntCount = 0; - x1c_passedParticleCount = 0; - x20_passedSoundCount = 0; - } - } -} - -SAdvancementResults CFBStreamedAnimReader::VReverseView(const CCharAnimTime& time) -{ - return {}; -} - -std::unique_ptr CFBStreamedAnimReader::VClone() const -{ - return std::make_unique(x54_source, xc_curTime); -} - -void CFBStreamedAnimReader::VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const -{ - const_cast(this)->x7c_totals.SetTime - (const_cast(this)->x108_bitLoader, xc_curTime); - - for (const CSegId& id : list.GetList()) - { - CAnimPerSegmentData& out = setOut[id]; - out.x0_rotation = GetRotation(id); - out.x1c_hasOffset = HasOffset(id); - if (out.x1c_hasOffset) - out.x10_offset = GetOffset(id); - } -} - -void CFBStreamedAnimReader::VGetSegStatementSet(const CSegIdList& list, - CSegStatementSet& setOut, - const CCharAnimTime& time) const -{ - const_cast(this)->x7c_totals.SetTime - (const_cast(this)->x108_bitLoader, time); - - for (const CSegId& id : list.GetList()) - { - CAnimPerSegmentData& out = setOut[id]; - out.x0_rotation = GetRotation(id); - out.x1c_hasOffset = HasOffset(id); - if (out.x1c_hasOffset) - out.x10_offset = GetOffset(id); - } -} - -SAdvancementResults CFBStreamedAnimReader::VAdvanceView(const CCharAnimTime& dt) -{ - SAdvancementResults res = {}; - - CCharAnimTime animDur = x54_source->GetAnimationDuration(); - if (xc_curTime == animDur) - { - xc_curTime = CCharAnimTime(); - x7c_totals.SetTime(x108_bitLoader, xc_curTime); - x14_passedBoolCount = 0; - x18_passedIntCount = 0; - x1c_passedParticleCount = 0; - x20_passedSoundCount = 0; - res.x0_remTime = dt; - return res; - } - else if (dt.EqualsZero()) - { - return res; - } - - zeus::CQuaternion priorQ = GetRotation(3); - zeus::CVector3f priorV = GetOffset(3); - - xc_curTime += dt; - CCharAnimTime overTime; - if (xc_curTime > animDur) - { - overTime = xc_curTime - animDur; - xc_curTime = animDur; - } - - x7c_totals.SetTime(x108_bitLoader, xc_curTime); - if (x54_source->HasPOIData()) - UpdatePOIStates(); - - zeus::CQuaternion nextQ = GetRotation(3); - zeus::CVector3f nextV = GetOffset(3); - - res.x0_remTime = overTime; - res.x8_deltas.xc_rotDelta = nextQ * priorQ.inverse(); - if (HasOffset(3)) - res.x8_deltas.x0_posDelta = nextQ.inverse().transform(nextV - priorV); - + x14_passedBoolCount = 0; + x18_passedIntCount = 0; + x1c_passedParticleCount = 0; + x20_passedSoundCount = 0; + res.x0_remTime = dt; return res; + } else if (dt.EqualsZero()) { + return res; + } + + zeus::CQuaternion priorQ = GetRotation(3); + zeus::CVector3f priorV = GetOffset(3); + + xc_curTime += dt; + CCharAnimTime overTime; + if (xc_curTime > animDur) { + overTime = xc_curTime - animDur; + xc_curTime = animDur; + } + + x7c_totals.SetTime(x108_bitLoader, xc_curTime); + if (x54_source->HasPOIData()) + UpdatePOIStates(); + + zeus::CQuaternion nextQ = GetRotation(3); + zeus::CVector3f nextV = GetOffset(3); + + res.x0_remTime = overTime; + res.x8_deltas.xc_rotDelta = nextQ * priorQ.inverse(); + if (HasOffset(3)) + res.x8_deltas.x0_posDelta = nextQ.inverse().transform(nextV - priorV); + + return res; } -CCharAnimTime CFBStreamedAnimReader::VGetTimeRemaining() const -{ - return x54_source->GetAnimationDuration() - xc_curTime; +CCharAnimTime CFBStreamedAnimReader::VGetTimeRemaining() const { + return x54_source->GetAnimationDuration() - xc_curTime; } -CSteadyStateAnimInfo CFBStreamedAnimReader::VGetSteadyStateAnimInfo() const -{ - return x64_steadyStateInfo; +CSteadyStateAnimInfo CFBStreamedAnimReader::VGetSteadyStateAnimInfo() const { return x64_steadyStateInfo; } + +bool CFBStreamedAnimReader::VHasOffset(const CSegId& seg) const { return HasOffset(seg); } + +zeus::CVector3f CFBStreamedAnimReader::VGetOffset(const CSegId& seg) const { + const_cast(this)->x7c_totals.SetTime(const_cast(this)->x108_bitLoader, + xc_curTime); + return GetOffset(seg); } -bool CFBStreamedAnimReader::VHasOffset(const CSegId& seg) const -{ - return HasOffset(seg); +zeus::CVector3f CFBStreamedAnimReader::VGetOffset(const CSegId& seg, const CCharAnimTime& time) const { + const_cast(this)->x7c_totals.SetTime(const_cast(this)->x108_bitLoader, + time); + return GetOffset(seg); } -zeus::CVector3f CFBStreamedAnimReader::VGetOffset(const CSegId& seg) const -{ - const_cast(this)->x7c_totals.SetTime - (const_cast(this)->x108_bitLoader, xc_curTime); - return GetOffset(seg); -} - -zeus::CVector3f CFBStreamedAnimReader::VGetOffset(const CSegId& seg, const CCharAnimTime& time) const -{ - const_cast(this)->x7c_totals.SetTime - (const_cast(this)->x108_bitLoader, time); - return GetOffset(seg); -} - -zeus::CQuaternion CFBStreamedAnimReader::VGetRotation(const CSegId& seg) const -{ - const_cast(this)->x7c_totals.SetTime - (const_cast(this)->x108_bitLoader, xc_curTime); - return GetRotation(seg); +zeus::CQuaternion CFBStreamedAnimReader::VGetRotation(const CSegId& seg) const { + const_cast(this)->x7c_totals.SetTime(const_cast(this)->x108_bitLoader, + xc_curTime); + return GetRotation(seg); } template class TAnimSourceInfo; -} +} // namespace urde diff --git a/Runtime/Character/CFBStreamedAnimReader.hpp b/Runtime/Character/CFBStreamedAnimReader.hpp index 9a6544a65..cf12d4eed 100644 --- a/Runtime/Character/CFBStreamedAnimReader.hpp +++ b/Runtime/Character/CFBStreamedAnimReader.hpp @@ -3,122 +3,118 @@ #include "CAnimSourceReader.hpp" #include "CFBStreamedCompression.hpp" -namespace urde -{ +namespace urde { class CBitLevelLoader; template -class TAnimSourceInfo : public IAnimSourceInfo -{ - TSubAnimTypeToken x4_token; +class TAnimSourceInfo : public IAnimSourceInfo { + TSubAnimTypeToken x4_token; + public: - TAnimSourceInfo(const TSubAnimTypeToken& token) : x4_token(token) {} - bool HasPOIData() const { return x4_token->HasPOIData(); } - const std::vector& GetBoolPOIStream() const { return x4_token->GetBoolPOIStream(); } - const std::vector& GetInt32POIStream() const { return x4_token->GetInt32POIStream(); } - const std::vector& GetParticlePOIStream() const { return x4_token->GetParticlePOIStream(); } - const std::vector& GetSoundPOIStream() const { return x4_token->GetSoundPOIStream(); } - CCharAnimTime GetAnimationDuration() const { return x4_token->GetAnimationDuration(); } + TAnimSourceInfo(const TSubAnimTypeToken& token) : x4_token(token) {} + bool HasPOIData() const { return x4_token->HasPOIData(); } + const std::vector& GetBoolPOIStream() const { return x4_token->GetBoolPOIStream(); } + const std::vector& GetInt32POIStream() const { return x4_token->GetInt32POIStream(); } + const std::vector& GetParticlePOIStream() const { return x4_token->GetParticlePOIStream(); } + const std::vector& GetSoundPOIStream() const { return x4_token->GetSoundPOIStream(); } + CCharAnimTime GetAnimationDuration() const { return x4_token->GetAnimationDuration(); } }; -class CFBStreamedAnimReaderTotals -{ - friend class CSegIdToIndexConverter; - friend class CFBStreamedPairOfTotals; - friend class CFBStreamedAnimReader; - std::unique_ptr x0_buffer; - s32* x4_cumulativeInts32; /* Used to be 16 per channel */ - u8* x8_hasTrans1; - u16* xc_segIds2; - float* x10_computedFloats32; - u32 x14_rotDiv; - float x18_transMult; - u32 x1c_curKey = 0; - bool x20_calculated = false; - u32 x24_boneChanCount; - void Allocate(u32 chanCount); +class CFBStreamedAnimReaderTotals { + friend class CSegIdToIndexConverter; + friend class CFBStreamedPairOfTotals; + friend class CFBStreamedAnimReader; + std::unique_ptr x0_buffer; + s32* x4_cumulativeInts32; /* Used to be 16 per channel */ + u8* x8_hasTrans1; + u16* xc_segIds2; + float* x10_computedFloats32; + u32 x14_rotDiv; + float x18_transMult; + u32 x1c_curKey = 0; + bool x20_calculated = false; + u32 x24_boneChanCount; + void Allocate(u32 chanCount); + public: - CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source); - void Initialize(const CFBStreamedCompression& source); - void IncrementInto(CBitLevelLoader& loader, const CFBStreamedCompression& source, - CFBStreamedAnimReaderTotals& dest); - void CalculateDown(); - bool IsCalculated() const { return x20_calculated; } - const float* GetFloats(int chanIdx) const { return &x10_computedFloats32[chanIdx*8]; } + CFBStreamedAnimReaderTotals(const CFBStreamedCompression& source); + void Initialize(const CFBStreamedCompression& source); + void IncrementInto(CBitLevelLoader& loader, const CFBStreamedCompression& source, CFBStreamedAnimReaderTotals& dest); + void CalculateDown(); + bool IsCalculated() const { return x20_calculated; } + const float* GetFloats(int chanIdx) const { return &x10_computedFloats32[chanIdx * 8]; } }; -class CFBStreamedPairOfTotals -{ - friend class CFBStreamedAnimReader; +class CFBStreamedPairOfTotals { + friend class CFBStreamedAnimReader; + + TSubAnimTypeToken x0_source; + u32* xc_rotsAndOffs; + bool x10_nextSel = true; + CFBStreamedAnimReaderTotals x14_a; + CFBStreamedAnimReaderTotals x3c_b; + float x78_t = 0.f; - TSubAnimTypeToken x0_source; - u32* xc_rotsAndOffs; - bool x10_nextSel = true; - CFBStreamedAnimReaderTotals x14_a; - CFBStreamedAnimReaderTotals x3c_b; - float x78_t = 0.f; public: - CFBStreamedPairOfTotals(const TSubAnimTypeToken& source); - void SetTime(CBitLevelLoader& loader, const CCharAnimTime& time); - void DoIncrement(CBitLevelLoader& loader); - float GetT() const { return x78_t; } - CFBStreamedAnimReaderTotals& Next() { return x10_nextSel ? x3c_b : x14_a; } - CFBStreamedAnimReaderTotals& Prior() { return x10_nextSel ? x14_a : x3c_b; } - const CFBStreamedAnimReaderTotals& Next() const { return x10_nextSel ? x3c_b : x14_a; } - const CFBStreamedAnimReaderTotals& Prior() const { return x10_nextSel ? x14_a : x3c_b; } + CFBStreamedPairOfTotals(const TSubAnimTypeToken& source); + void SetTime(CBitLevelLoader& loader, const CCharAnimTime& time); + void DoIncrement(CBitLevelLoader& loader); + float GetT() const { return x78_t; } + CFBStreamedAnimReaderTotals& Next() { return x10_nextSel ? x3c_b : x14_a; } + CFBStreamedAnimReaderTotals& Prior() { return x10_nextSel ? x14_a : x3c_b; } + const CFBStreamedAnimReaderTotals& Next() const { return x10_nextSel ? x3c_b : x14_a; } + const CFBStreamedAnimReaderTotals& Prior() const { return x10_nextSel ? x14_a : x3c_b; } }; -class CBitLevelLoader -{ - const u8* m_data; - size_t m_bitIdx = 0; +class CBitLevelLoader { + const u8* m_data; + size_t m_bitIdx = 0; + public: - CBitLevelLoader(const void* data) - : m_data(reinterpret_cast(data)) {} - void Reset() { m_bitIdx = 0; } - u32 LoadUnsigned(u8 q); - s32 LoadSigned(u8 q); - bool LoadBool(); - size_t GetCurBit() const { return m_bitIdx; } + CBitLevelLoader(const void* data) : m_data(reinterpret_cast(data)) {} + void Reset() { m_bitIdx = 0; } + u32 LoadUnsigned(u8 q); + s32 LoadSigned(u8 q); + bool LoadBool(); + size_t GetCurBit() const { return m_bitIdx; } }; -class CSegIdToIndexConverter -{ - s32 x0_indices[96]; +class CSegIdToIndexConverter { + s32 x0_indices[96]; + public: - CSegIdToIndexConverter(const CFBStreamedAnimReaderTotals& totals); - s32 SegIdToIndex(const CSegId& id) const { return x0_indices[id]; } + CSegIdToIndexConverter(const CFBStreamedAnimReaderTotals& totals); + s32 SegIdToIndex(const CSegId& id) const { return x0_indices[id]; } }; -class CFBStreamedAnimReader : public CAnimSourceReaderBase -{ - TSubAnimTypeToken x54_source; - CSteadyStateAnimInfo x64_steadyStateInfo; - CFBStreamedPairOfTotals x7c_totals; - const u8* x104_bitstreamData; - CBitLevelLoader x108_bitLoader; - CSegIdToIndexConverter x114_segIdToIndex; - bool HasOffset(const CSegId& seg) const; - zeus::CVector3f GetOffset(const CSegId& seg) const; - zeus::CQuaternion GetRotation(const CSegId& seg) const; -public: - CFBStreamedAnimReader(const TSubAnimTypeToken& source, const CCharAnimTime& time); +class CFBStreamedAnimReader : public CAnimSourceReaderBase { + TSubAnimTypeToken x54_source; + CSteadyStateAnimInfo x64_steadyStateInfo; + CFBStreamedPairOfTotals x7c_totals; + const u8* x104_bitstreamData; + CBitLevelLoader x108_bitLoader; + CSegIdToIndexConverter x114_segIdToIndex; + bool HasOffset(const CSegId& seg) const; + zeus::CVector3f GetOffset(const CSegId& seg) const; + zeus::CQuaternion GetRotation(const CSegId& seg) const; - SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; - bool VSupportsReverseView() const {return false;} - void VSetPhase(float); - SAdvancementResults VReverseView(const CCharAnimTime& time); - std::unique_ptr VClone() const; - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; - void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; - SAdvancementResults VAdvanceView(const CCharAnimTime& a); - CCharAnimTime VGetTimeRemaining() const; - CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; - bool VHasOffset(const CSegId& seg) const; - zeus::CVector3f VGetOffset(const CSegId& seg) const; - zeus::CVector3f VGetOffset(const CSegId& seg, const CCharAnimTime& time) const; - zeus::CQuaternion VGetRotation(const CSegId& seg) const; +public: + CFBStreamedAnimReader(const TSubAnimTypeToken& source, const CCharAnimTime& time); + + SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; + bool VSupportsReverseView() const { return false; } + void VSetPhase(float); + SAdvancementResults VReverseView(const CCharAnimTime& time); + std::unique_ptr VClone() const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const; + void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const; + SAdvancementResults VAdvanceView(const CCharAnimTime& a); + CCharAnimTime VGetTimeRemaining() const; + CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const; + bool VHasOffset(const CSegId& seg) const; + zeus::CVector3f VGetOffset(const CSegId& seg) const; + zeus::CVector3f VGetOffset(const CSegId& seg, const CCharAnimTime& time) const; + zeus::CQuaternion VGetRotation(const CSegId& seg) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CFBStreamedCompression.cpp b/Runtime/Character/CFBStreamedCompression.cpp index f7c9874ae..b85a02654 100644 --- a/Runtime/Character/CFBStreamedCompression.cpp +++ b/Runtime/Character/CFBStreamedCompression.cpp @@ -1,286 +1,245 @@ #include "CFBStreamedCompression.hpp" #include "CFBStreamedAnimReader.hpp" -namespace urde -{ +namespace urde { -CFBStreamedCompression::CFBStreamedCompression(CInputStream& in, IObjectStore& objStore, bool pc) -: m_pc(pc) -{ - x0_scratchSize = in.readUint32Big(); - x4_evnt = in.readUint32Big(); +CFBStreamedCompression::CFBStreamedCompression(CInputStream& in, IObjectStore& objStore, bool pc) : m_pc(pc) { + x0_scratchSize = in.readUint32Big(); + x4_evnt = in.readUint32Big(); - xc_rotsAndOffs = GetRotationsAndOffsets(x0_scratchSize / 4 + 1, in); + xc_rotsAndOffs = GetRotationsAndOffsets(x0_scratchSize / 4 + 1, in); - if (x4_evnt.IsValid()) - x8_evntToken = objStore.GetObj(SObjectTag{FOURCC('EVNT'), x4_evnt}); + if (x4_evnt.IsValid()) + x8_evntToken = objStore.GetObj(SObjectTag{FOURCC('EVNT'), x4_evnt}); - x10_averageVelocity = CalculateAverageVelocity(GetPerChannelHeaders()); + x10_averageVelocity = CalculateAverageVelocity(GetPerChannelHeaders()); } -const u32* CFBStreamedCompression::GetTimes() const -{ - return reinterpret_cast(xc_rotsAndOffs.get() + 9); +const u32* CFBStreamedCompression::GetTimes() const { return reinterpret_cast(xc_rotsAndOffs.get() + 9); } + +const u8* CFBStreamedCompression::GetPerChannelHeaders() const { + const u32* bitmap = reinterpret_cast(xc_rotsAndOffs.get() + 9); + u32 bitmapWordCount = (bitmap[0] + 31) / 32; + return reinterpret_cast(bitmap + bitmapWordCount + 1); } -const u8* CFBStreamedCompression::GetPerChannelHeaders() const -{ - const u32* bitmap = reinterpret_cast(xc_rotsAndOffs.get() + 9); - u32 bitmapWordCount = (bitmap[0] + 31) / 32; - return reinterpret_cast(bitmap + bitmapWordCount + 1); +const u8* CFBStreamedCompression::GetBitstreamPointer() const { + const u32* bitmap = reinterpret_cast(xc_rotsAndOffs.get() + 9); + u32 bitmapWordCount = (bitmap[0] + 31) / 32; + + const u8* chans = reinterpret_cast(bitmap + bitmapWordCount + 1); + u32 boneChanCount = *reinterpret_cast(chans); + chans += 4; + + if (m_pc) { + for (unsigned b = 0; b < boneChanCount; ++b) { + chans += 20; + + u32 tCount = *reinterpret_cast(chans); + chans += 4; + if (tCount) + chans += 12; + } + } else { + for (unsigned b = 0; b < boneChanCount; ++b) { + chans += 15; + + u16 tCount = *reinterpret_cast(chans); + chans += 2; + if (tCount) + chans += 9; + } + } + + return chans; } -const u8* CFBStreamedCompression::GetBitstreamPointer() const -{ - const u32* bitmap = reinterpret_cast(xc_rotsAndOffs.get() + 9); - u32 bitmapWordCount = (bitmap[0] + 31) / 32; +std::unique_ptr CFBStreamedCompression::GetRotationsAndOffsets(u32 words, CInputStream& in) { + std::unique_ptr ret(new u32[words]); - const u8* chans = reinterpret_cast(bitmap + bitmapWordCount + 1); - u32 boneChanCount = *reinterpret_cast(chans); - chans += 4; + Header head; + head.read(in); + *reinterpret_cast(ret.get()) = head; - if (m_pc) - { - for (unsigned b=0 ; b(chans); - chans += 4; - if (tCount) - chans += 12; - } - } - else - { - for (unsigned b=0 ; b(bitmapOut + bitmapWordCount + 1); + u8* bs = ReadBoneChannelDescriptors(chans, in); + u32 bsWords = ComputeBitstreamWords(chans); - u16 tCount = *reinterpret_cast(chans); - chans += 2; - if (tCount) - chans += 9; - } - } + u32* bsPtr = reinterpret_cast(bs); + for (u32 w = 0; w < bsWords; ++w) + bsPtr[w] = in.readUint32Big(); - return chans; + return ret; } -std::unique_ptr CFBStreamedCompression::GetRotationsAndOffsets(u32 words, CInputStream& in) -{ - std::unique_ptr ret(new u32[words]); +u8* CFBStreamedCompression::ReadBoneChannelDescriptors(u8* out, CInputStream& in) { + u32 boneChanCount = in.readUint32Big(); + *reinterpret_cast(out) = boneChanCount; + out += 4; - Header head; - head.read(in); - *reinterpret_cast(ret.get()) = head; + if (m_pc) { + for (unsigned b = 0; b < boneChanCount; ++b) { + *reinterpret_cast(out) = in.readUint32Big(); + out += 4; - u32* bitmapOut = &ret[9]; - u32 bitmapBitCount = in.readUint32Big(); - bitmapOut[0] = bitmapBitCount; - u32 bitmapWordCount = (bitmapBitCount + 31) / 32; - for (u32 i=0 ; i(out) = in.readUint32Big(); + out += 4; - in.readUint32Big(); - u8* chans = reinterpret_cast(bitmapOut + bitmapWordCount + 1); - u8* bs = ReadBoneChannelDescriptors(chans, in); - u32 bsWords = ComputeBitstreamWords(chans); + for (int i = 0; i < 3; ++i) { + *reinterpret_cast(out) = in.readUint32Big(); + out += 4; + } - u32* bsPtr = reinterpret_cast(bs); - for (u32 w=0 ; w(out) = tCount; + out += 4; - return ret; + if (tCount) { + for (int i = 0; i < 3; ++i) { + *reinterpret_cast(out) = in.readUint32Big(); + out += 4; + } + } + } + } else { + for (unsigned b = 0; b < boneChanCount; ++b) { + *reinterpret_cast(out) = in.readUint32Big(); + out += 4; + + *reinterpret_cast(out) = in.readUint16Big(); + out += 2; + + for (int i = 0; i < 3; ++i) { + *reinterpret_cast(out) = in.readInt16Big(); + out += 2; + *reinterpret_cast(out) = in.readUByte(); + out += 1; + } + + u16 tCount = in.readUint16Big(); + *reinterpret_cast(out) = tCount; + out += 2; + + if (tCount) { + for (int i = 0; i < 3; ++i) { + *reinterpret_cast(out) = in.readInt16Big(); + out += 2; + *reinterpret_cast(out) = in.readUByte(); + out += 1; + } + } + } + } + + return out; } -u8* CFBStreamedCompression::ReadBoneChannelDescriptors(u8* out, CInputStream& in) -{ - u32 boneChanCount = in.readUint32Big(); - *reinterpret_cast(out) = boneChanCount; - out += 4; +u32 CFBStreamedCompression::ComputeBitstreamWords(const u8* chans) { + u32 boneChanCount = *reinterpret_cast(chans); + chans += 4; - if (m_pc) - { - for (unsigned b=0 ; b(out) = in.readUint32Big(); - out += 4; + u32 keyCount; - *reinterpret_cast(out) = in.readUint32Big(); - out += 4; - - for (int i=0 ; i<3 ; ++i) - { - *reinterpret_cast(out) = in.readUint32Big(); - out += 4; - } - - u32 tCount = in.readUint32Big(); - *reinterpret_cast(out) = tCount; - out += 4; - - if (tCount) - { - for (int i=0 ; i<3 ; ++i) - { - *reinterpret_cast(out) = in.readUint32Big(); - out += 4; - } - } - } + u32 totalBits = 0; + if (m_pc) { + keyCount = *reinterpret_cast(chans + 0x4); + for (u32 c = 0; c < boneChanCount; ++c) { + chans += 0x8; + totalBits += 1; + totalBits += *reinterpret_cast(chans) & 0xff; + totalBits += *reinterpret_cast(chans + 0x4) & 0xff; + totalBits += *reinterpret_cast(chans + 0x8) & 0xff; + u32 tKeyCount = *reinterpret_cast(chans + 0xc); + chans += 0x10; + if (tKeyCount) { + totalBits += *reinterpret_cast(chans) & 0xff; + totalBits += *reinterpret_cast(chans + 0x4) & 0xff; + totalBits += *reinterpret_cast(chans + 0x8) & 0xff; + chans += 0xc; + } } - else - { - for (unsigned b=0 ; b(out) = in.readUint32Big(); - out += 4; - - *reinterpret_cast(out) = in.readUint16Big(); - out += 2; - - for (int i=0 ; i<3 ; ++i) - { - *reinterpret_cast(out) = in.readInt16Big(); - out += 2; - *reinterpret_cast(out) = in.readUByte(); - out += 1; - } - - u16 tCount = in.readUint16Big(); - *reinterpret_cast(out) = tCount; - out += 2; - - if (tCount) - { - for (int i=0 ; i<3 ; ++i) - { - *reinterpret_cast(out) = in.readInt16Big(); - out += 2; - *reinterpret_cast(out) = in.readUByte(); - out += 1; - } - } - } + } else { + keyCount = *reinterpret_cast(chans + 0x4); + for (u32 c = 0; c < boneChanCount; ++c) { + chans += 0x6; + totalBits += 1; + totalBits += *reinterpret_cast(chans + 0x2); + totalBits += *reinterpret_cast(chans + 0x5); + totalBits += *reinterpret_cast(chans + 0x8); + u16 tKeyCount = *reinterpret_cast(chans + 0x9); + chans += 0xb; + if (tKeyCount) { + totalBits += *reinterpret_cast(chans + 0x2); + totalBits += *reinterpret_cast(chans + 0x5); + totalBits += *reinterpret_cast(chans + 0x8); + chans += 0x9; + } } + } - return out; + return (totalBits * keyCount + 31) / 32; } -u32 CFBStreamedCompression::ComputeBitstreamWords(const u8* chans) -{ - u32 boneChanCount = *reinterpret_cast(chans); - chans += 4; +float CFBStreamedCompression::CalculateAverageVelocity(const u8* chans) { + u32 boneChanCount = *reinterpret_cast(chans); + chans += 4; - u32 keyCount; + u32 keyCount; + u32 rootIdx = 0; + if (m_pc) { + keyCount = *reinterpret_cast(chans + 0x4); + for (u32 c = 0; c < boneChanCount; ++c) { + u32 boneId = *reinterpret_cast(chans); + if (boneId == 3) + break; + ++rootIdx; - u32 totalBits = 0; - if (m_pc) - { - keyCount = *reinterpret_cast(chans + 0x4); - for (u32 c=0 ; c(chans) & 0xff; - totalBits += *reinterpret_cast(chans + 0x4) & 0xff; - totalBits += *reinterpret_cast(chans + 0x8) & 0xff; - u32 tKeyCount = *reinterpret_cast(chans + 0xc); - chans += 0x10; - if (tKeyCount) - { - totalBits += *reinterpret_cast(chans) & 0xff; - totalBits += *reinterpret_cast(chans + 0x4) & 0xff; - totalBits += *reinterpret_cast(chans + 0x8) & 0xff; - chans += 0xc; - } - } + chans += 0x8; + u32 tKeyCount = *reinterpret_cast(chans + 0xc); + chans += 0x10; + if (tKeyCount) + chans += 0xc; } - else - { - keyCount = *reinterpret_cast(chans + 0x4); - for (u32 c=0 ; c(chans + 0x2); - totalBits += *reinterpret_cast(chans + 0x5); - totalBits += *reinterpret_cast(chans + 0x8); - u16 tKeyCount = *reinterpret_cast(chans + 0x9); - chans += 0xb; - if (tKeyCount) - { - totalBits += *reinterpret_cast(chans + 0x2); - totalBits += *reinterpret_cast(chans + 0x5); - totalBits += *reinterpret_cast(chans + 0x8); - chans += 0x9; - } - } + } else { + keyCount = *reinterpret_cast(chans + 0x4); + for (u32 c = 0; c < boneChanCount; ++c) { + u32 boneId = *reinterpret_cast(chans); + if (boneId == 3) + break; + ++rootIdx; + + chans += 0x6; + u16 tKeyCount = *reinterpret_cast(chans + 0x9); + chans += 0xb; + if (tKeyCount) + chans += 0x9; } + } - return (totalBits * keyCount + 31) / 32; -} + CBitLevelLoader loader(GetBitstreamPointer()); + CFBStreamedAnimReaderTotals tempTotals(*this); + tempTotals.CalculateDown(); + const float* floats = tempTotals.GetFloats(rootIdx); + zeus::CVector3f transCompA(floats[4], floats[5], floats[6]); -float CFBStreamedCompression::CalculateAverageVelocity(const u8* chans) -{ - u32 boneChanCount = *reinterpret_cast(chans); - chans += 4; - - u32 keyCount; - u32 rootIdx = 0; - if (m_pc) - { - keyCount = *reinterpret_cast(chans + 0x4); - for (u32 c=0 ; c(chans); - if (boneId == 3) - break; - ++rootIdx; - - chans += 0x8; - u32 tKeyCount = *reinterpret_cast(chans + 0xc); - chans += 0x10; - if (tKeyCount) - chans += 0xc; - } - } - else - { - keyCount = *reinterpret_cast(chans + 0x4); - for (u32 c=0 ; c(chans); - if (boneId == 3) - break; - ++rootIdx; - - chans += 0x6; - u16 tKeyCount = *reinterpret_cast(chans + 0x9); - chans += 0xb; - if (tKeyCount) - chans += 0x9; - } - } - - CBitLevelLoader loader(GetBitstreamPointer()); - CFBStreamedAnimReaderTotals tempTotals(*this); + float accumMag = 0.f; + for (u32 i = 0; i < keyCount; ++i) { + tempTotals.IncrementInto(loader, *this, tempTotals); tempTotals.CalculateDown(); - const float* floats = tempTotals.GetFloats(rootIdx); - zeus::CVector3f transCompA(floats[4], floats[5], floats[6]); + zeus::CVector3f transCompB(floats[4], floats[5], floats[6]); + accumMag += (transCompB - transCompA).magnitude(); + transCompA = transCompB; + } - float accumMag = 0.f; - for (u32 i=0 ; i x8_evntToken; - std::unique_ptr xc_rotsAndOffs; - float x10_averageVelocity; - zeus::CVector3f x14_rootOffset; + bool m_pc; + u32 x0_scratchSize; + CAssetId x4_evnt; + TLockedToken x8_evntToken; + std::unique_ptr xc_rotsAndOffs; + float x10_averageVelocity; + zeus::CVector3f x14_rootOffset; - u8* ReadBoneChannelDescriptors(u8* out, CInputStream& in); - u32 ComputeBitstreamWords(const u8* chans); - std::unique_ptr GetRotationsAndOffsets(u32 words, CInputStream& in); - float CalculateAverageVelocity(const u8* chans); + u8* ReadBoneChannelDescriptors(u8* out, CInputStream& in); + u32 ComputeBitstreamWords(const u8* chans); + std::unique_ptr GetRotationsAndOffsets(u32 words, CInputStream& in); + float CalculateAverageVelocity(const u8* chans); public: - CFBStreamedCompression(CInputStream& in, IObjectStore& objStore, bool pc); - const Header& MainHeader() const { return *reinterpret_cast(xc_rotsAndOffs.get()); } - const u32* GetTimes() const; - const u8* GetPerChannelHeaders() const; - const u8* GetBitstreamPointer() const; - bool IsLooping() const { return MainHeader().looping; } - CCharAnimTime GetAnimationDuration() const { return MainHeader().duration; } - float GetAverageVelocity() const { return x10_averageVelocity; } - const zeus::CVector3f& GetRootOffset() const { return x14_rootOffset; } - bool HasPOIData() const { return x8_evntToken; } - const std::vector& GetBoolPOIStream() const { return x8_evntToken->GetBoolPOIStream(); } - const std::vector& GetInt32POIStream() const { return x8_evntToken->GetInt32POIStream(); } - const std::vector& GetParticlePOIStream() const { return x8_evntToken->GetParticlePOIStream(); } - const std::vector& GetSoundPOIStream() const { return x8_evntToken->GetSoundPOIStream(); } + CFBStreamedCompression(CInputStream& in, IObjectStore& objStore, bool pc); + const Header& MainHeader() const { return *reinterpret_cast(xc_rotsAndOffs.get()); } + const u32* GetTimes() const; + const u8* GetPerChannelHeaders() const; + const u8* GetBitstreamPointer() const; + bool IsLooping() const { return MainHeader().looping; } + CCharAnimTime GetAnimationDuration() const { return MainHeader().duration; } + float GetAverageVelocity() const { return x10_averageVelocity; } + const zeus::CVector3f& GetRootOffset() const { return x14_rootOffset; } + bool HasPOIData() const { return x8_evntToken; } + const std::vector& GetBoolPOIStream() const { return x8_evntToken->GetBoolPOIStream(); } + const std::vector& GetInt32POIStream() const { return x8_evntToken->GetInt32POIStream(); } + const std::vector& GetParticlePOIStream() const { return x8_evntToken->GetParticlePOIStream(); } + const std::vector& GetSoundPOIStream() const { return x8_evntToken->GetSoundPOIStream(); } }; -} - +} // namespace urde diff --git a/Runtime/Character/CGroundMovement.cpp b/Runtime/Character/CGroundMovement.cpp index bda4a435a..083871956 100644 --- a/Runtime/Character/CGroundMovement.cpp +++ b/Runtime/Character/CGroundMovement.cpp @@ -10,847 +10,730 @@ #include "World/CWorld.hpp" #include "World/CPlayer.hpp" -namespace urde -{ +namespace urde { -void CGroundMovement::CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float) -{ - bool oob = true; - for (const CGameArea& area : *mgr.GetWorld()) - { - if (area.GetAABB().intersects(*actor.GetTouchBounds())) - { - oob = false; - break; - } +void CGroundMovement::CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float) { + bool oob = true; + for (const CGameArea& area : *mgr.GetWorld()) { + if (area.GetAABB().intersects(*actor.GetTouchBounds())) { + oob = false; + break; } + } - if (!oob) - { - mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling); - } - else - { - mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor); - actor.SetAngularVelocityWR(actor.GetAngularVelocityWR() * 0.98f); - zeus::CVector3f vel = actor.GetTransform().transposeRotate(actor.GetVelocity()); - vel.z() = 0.f; - actor.SetVelocityOR(vel); - actor.SetMomentumWR(zeus::CVector3f::skZero); - } + if (!oob) { + mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling); + } else { + mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor); + actor.SetAngularVelocityWR(actor.GetAngularVelocityWR() * 0.98f); + zeus::CVector3f vel = actor.GetTransform().transposeRotate(actor.GetVelocity()); + vel.z() = 0.f; + actor.SetVelocityOR(vel); + actor.SetMomentumWR(zeus::CVector3f::skZero); + } } void CGroundMovement::MoveGroundCollider(CStateManager& mgr, CPhysicsActor& actor, float dt, - const rstl::reserved_vector* nearList) -{ - CMotionState oldState = actor.GetMotionState(); - CMotionState newState = actor.PredictMotion_Internal(dt); - float deltaMag = newState.x0_translation.magnitude(); - TUniqueId idDetect = kInvalidUniqueId; - CCollisionInfoList collisionList; - zeus::CAABox motionVol = actor.GetMotionVolume(dt); - rstl::reserved_vector useColliderList; - if (nearList) - useColliderList = *nearList; - mgr.BuildColliderList(useColliderList, actor, motionVol); - CAreaCollisionCache cache(motionVol); - float collideDt = dt; - if (actor.GetCollisionPrimitive()->GetPrimType() == FOURCC('OBTG')) - { - CGameCollision::BuildAreaCollisionCache(mgr, cache); - if (deltaMag > 0.5f * CGameCollision::GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive())) - { - zeus::CVector3f point = - actor.GetCollisionPrimitive()->CalculateAABox(actor.GetPrimitiveTransform()).center(); - TUniqueId intersectId = kInvalidUniqueId; - CMaterialFilter filter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid}); - CRayCastResult result = - mgr.RayWorldIntersection(intersectId, point, newState.x0_translation.normalized(), deltaMag, - filter, useColliderList); - if (result.IsValid()) - { - collideDt = dt * (result.GetT() / deltaMag); - newState = actor.PredictMotion_Internal(collideDt); - } - actor.MoveCollisionPrimitive(newState.x0_translation); - if (CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetPrimitiveTransform(), actor.GetMaterialFilter(), - useColliderList, idDetect, collisionList)) - { - actor.AddMotionState(newState); - float resolved = 0.f; - if (ResolveUpDown(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList, - actor.GetStepUpHeight(), 0.f, resolved, collisionList)) - { - actor.SetMotionState(oldState); - MoveGroundColliderXY(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList, collideDt); - } - - } - else - { - actor.AddMotionState(newState); - } - - float stepDown = actor.GetStepDownHeight(); - float resolved = 0.f; - collisionList.Clear(); - TUniqueId stepZId = kInvalidUniqueId; - if (stepDown >= 0.f) - { - if (MoveGroundColliderZ(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList, - -stepDown, resolved, collisionList, stepZId)) - { - if (collisionList.GetCount() > 0) - { - CCollisionInfoList filteredList; - CollisionUtil::FilterByClosestNormal(zeus::CVector3f{0.f, 0.f, 1.f}, collisionList, filteredList); - if (filteredList.GetCount() > 0) - { - if (CGameCollision::IsFloor(filteredList.Front().GetMaterialLeft(), - filteredList.Front().GetNormalLeft())) - { - if (TCastToPtr plat = mgr.ObjectById(stepZId)) - mgr.SendScriptMsg(plat.GetPtr(), actor.GetUniqueId(), - EScriptObjectMessage::AddPlatformRider); - CGameCollision::SendMaterialMessage(mgr, filteredList.Front().GetMaterialLeft(), actor); - mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor); - } - else - { - CheckFalling(actor, mgr, dt); - } - } - } - } - } - else - { - CheckFalling(actor, mgr, dt); - } - - actor.ClearForcesAndTorques(); - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); - if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Player)) - { - CGameCollision::CollisionFailsafe(mgr, cache, actor, *actor.GetCollisionPrimitive(), - useColliderList, 0.f, 1); - } + const rstl::reserved_vector* nearList) { + CMotionState oldState = actor.GetMotionState(); + CMotionState newState = actor.PredictMotion_Internal(dt); + float deltaMag = newState.x0_translation.magnitude(); + TUniqueId idDetect = kInvalidUniqueId; + CCollisionInfoList collisionList; + zeus::CAABox motionVol = actor.GetMotionVolume(dt); + rstl::reserved_vector useColliderList; + if (nearList) + useColliderList = *nearList; + mgr.BuildColliderList(useColliderList, actor, motionVol); + CAreaCollisionCache cache(motionVol); + float collideDt = dt; + if (actor.GetCollisionPrimitive()->GetPrimType() == FOURCC('OBTG')) { + CGameCollision::BuildAreaCollisionCache(mgr, cache); + if (deltaMag > 0.5f * CGameCollision::GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive())) { + zeus::CVector3f point = actor.GetCollisionPrimitive()->CalculateAABox(actor.GetPrimitiveTransform()).center(); + TUniqueId intersectId = kInvalidUniqueId; + CMaterialFilter filter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid}); + CRayCastResult result = mgr.RayWorldIntersection(intersectId, point, newState.x0_translation.normalized(), + deltaMag, filter, useColliderList); + if (result.IsValid()) { + collideDt = dt * (result.GetT() / deltaMag); + newState = actor.PredictMotion_Internal(collideDt); + } + actor.MoveCollisionPrimitive(newState.x0_translation); + if (CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), + actor.GetPrimitiveTransform(), actor.GetMaterialFilter(), + useColliderList, idDetect, collisionList)) { + actor.AddMotionState(newState); + float resolved = 0.f; + if (ResolveUpDown(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList, actor.GetStepUpHeight(), 0.f, + resolved, collisionList)) { + actor.SetMotionState(oldState); + MoveGroundColliderXY(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList, collideDt); } + + } else { + actor.AddMotionState(newState); + } + + float stepDown = actor.GetStepDownHeight(); + float resolved = 0.f; + collisionList.Clear(); + TUniqueId stepZId = kInvalidUniqueId; + if (stepDown >= 0.f) { + if (MoveGroundColliderZ(cache, mgr, actor, actor.GetMaterialFilter(), useColliderList, -stepDown, resolved, + collisionList, stepZId)) { + if (collisionList.GetCount() > 0) { + CCollisionInfoList filteredList; + CollisionUtil::FilterByClosestNormal(zeus::CVector3f{0.f, 0.f, 1.f}, collisionList, filteredList); + if (filteredList.GetCount() > 0) { + if (CGameCollision::IsFloor(filteredList.Front().GetMaterialLeft(), + filteredList.Front().GetNormalLeft())) { + if (TCastToPtr plat = mgr.ObjectById(stepZId)) + mgr.SendScriptMsg(plat.GetPtr(), actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider); + CGameCollision::SendMaterialMessage(mgr, filteredList.Front().GetMaterialLeft(), actor); + mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor); + } else { + CheckFalling(actor, mgr, dt); + } + } + } + } + } else { + CheckFalling(actor, mgr, dt); + } + + actor.ClearForcesAndTorques(); + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); + if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Player)) { + CGameCollision::CollisionFailsafe(mgr, cache, actor, *actor.GetCollisionPrimitive(), useColliderList, 0.f, 1); + } } + } } bool CGroundMovement::ResolveUpDown(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, const CMaterialFilter& filter, rstl::reserved_vector& nearList, - float stepUp, float stepDown, float& fOut, CCollisionInfoList& list) -{ - float zextent = stepDown; - if (list.GetCount() <= 0) - return true; + float stepUp, float stepDown, float& fOut, CCollisionInfoList& list) { + float zextent = stepDown; + if (list.GetCount() <= 0) + return true; - zeus::CAABox aabb = zeus::CAABox::skInvertedBox; - zeus::CVector3f normAccum = zeus::CVector3f::skZero; - for (CCollisionInfo& info : list) - { - if (CGameCollision::IsFloor(info.GetMaterialLeft(), info.GetNormalLeft())) - { - aabb.accumulateBounds(info.GetPoint()); - aabb.accumulateBounds(info.GetExtreme()); - normAccum += info.GetNormalLeft(); - } + zeus::CAABox aabb = zeus::CAABox::skInvertedBox; + zeus::CVector3f normAccum = zeus::CVector3f::skZero; + for (CCollisionInfo& info : list) { + if (CGameCollision::IsFloor(info.GetMaterialLeft(), info.GetNormalLeft())) { + aabb.accumulateBounds(info.GetPoint()); + aabb.accumulateBounds(info.GetExtreme()); + normAccum += info.GetNormalLeft(); + } + } + + if (normAccum.canBeNormalized()) + normAccum.normalize(); + else + return true; + + zeus::CAABox actorAABB = actor.GetBoundingBox(); + if (normAccum.z() >= 0.f) { + zextent = aabb.max.z() - actorAABB.min.z() + 0.02f; + if (zextent > stepUp) + return true; + } else { + zextent = aabb.min.z() - actorAABB.max.z() - 0.02f; + if (zextent < -stepDown) + return true; + } + + actor.MoveCollisionPrimitive({0.f, 0.f, zextent}); + + if (!CGameCollision::DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(), + actor.GetPrimitiveTransform(), filter, nearList)) { + fOut = zextent; + actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, zextent)); + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); + + bool floor = false; + for (CCollisionInfo& info : list) { + if (CGameCollision::IsFloor(info.GetMaterialLeft(), info.GetNormalLeft())) { + floor = true; + break; + } } - if (normAccum.canBeNormalized()) - normAccum.normalize(); - else - return true; + if (!floor) + mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor); + + return false; + } + + return true; +} + +bool CGroundMovement::MoveGroundColliderZ(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, + const CMaterialFilter& filter, + rstl::reserved_vector& nearList, float amt, float&, + CCollisionInfoList& list, TUniqueId& idOut) { + actor.MoveCollisionPrimitive({0.f, 0.f, amt}); + + zeus::CAABox aabb = zeus::CAABox::skInvertedBox; + if (CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), actor.GetPrimitiveTransform(), + filter, nearList, idOut, list)) { + for (CCollisionInfo& info : list) { + aabb.accumulateBounds(info.GetPoint()); + aabb.accumulateBounds(info.GetExtreme()); + } zeus::CAABox actorAABB = actor.GetBoundingBox(); - if (normAccum.z() >= 0.f) - { - zextent = aabb.max.z() - actorAABB.min.z() + 0.02f; - if (zextent > stepUp) - return true; - } + float zextent; + if (amt > 0.f) + zextent = aabb.min.z() - actorAABB.max.z() - 0.02f + amt; else - { - zextent = aabb.min.z() - actorAABB.max.z() - 0.02f; - if (zextent < -stepDown) - return true; - } + zextent = aabb.max.z() - actorAABB.min.z() + 0.02f + amt; actor.MoveCollisionPrimitive({0.f, 0.f, zextent}); if (!CGameCollision::DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetPrimitiveTransform(), filter, nearList)) - { - fOut = zextent; - actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, zextent)); - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); - - bool floor = false; - for (CCollisionInfo& info : list) - { - if (CGameCollision::IsFloor(info.GetMaterialLeft(), info.GetNormalLeft())) - { - floor = true; - break; - } - } - - if (!floor) - mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor); - - return false; + actor.GetPrimitiveTransform(), filter, nearList)) { + actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, zextent)); + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); } + bool floor = false; + for (CCollisionInfo& info : list) { + if (CGameCollision::IsFloor(info.GetMaterialLeft(), info.GetNormalLeft())) { + floor = true; + break; + } + } + + if (!floor) + mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor); + + CCollisionInfoList filteredList; + if (amt > 0.f) + CollisionUtil::FilterByClosestNormal({0.f, 0.f, -1.f}, list, filteredList); + else + CollisionUtil::FilterByClosestNormal({0.f, 0.f, 1.f}, list, filteredList); + + if (filteredList.GetCount() > 0) + CGameCollision::MakeCollisionCallbacks(mgr, actor, idOut, filteredList); + return true; -} + } -bool CGroundMovement::MoveGroundColliderZ(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, - const CMaterialFilter& filter, rstl::reserved_vector& nearList, - float amt, float&, CCollisionInfoList& list, TUniqueId& idOut) -{ - actor.MoveCollisionPrimitive({0.f, 0.f, amt}); - - zeus::CAABox aabb = zeus::CAABox::skInvertedBox; - if (CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetPrimitiveTransform(), filter, nearList, idOut, list)) - { - for (CCollisionInfo& info : list) - { - aabb.accumulateBounds(info.GetPoint()); - aabb.accumulateBounds(info.GetExtreme()); - } - - zeus::CAABox actorAABB = actor.GetBoundingBox(); - float zextent; - if (amt > 0.f) - zextent = aabb.min.z() - actorAABB.max.z() - 0.02f + amt; - else - zextent = aabb.max.z() - actorAABB.min.z() + 0.02f + amt; - - actor.MoveCollisionPrimitive({0.f, 0.f, zextent}); - - if (!CGameCollision::DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetPrimitiveTransform(), filter, nearList)) - { - actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, zextent)); - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); - } - - bool floor = false; - for (CCollisionInfo& info : list) - { - if (CGameCollision::IsFloor(info.GetMaterialLeft(), info.GetNormalLeft())) - { - floor = true; - break; - } - } - - if (!floor) - mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::LandOnNotFloor); - - CCollisionInfoList filteredList; - if (amt > 0.f) - CollisionUtil::FilterByClosestNormal({0.f, 0.f, -1.f}, list, filteredList); - else - CollisionUtil::FilterByClosestNormal({0.f, 0.f, 1.f}, list, filteredList); - - if (filteredList.GetCount() > 0) - CGameCollision::MakeCollisionCallbacks(mgr, actor, idOut, filteredList); - - return true; - } - - return false; + return false; } void CGroundMovement::MoveGroundColliderXY(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, - const CMaterialFilter& filter, rstl::reserved_vector& nearList, - float dt) -{ - bool didCollide = false; - bool isPlayer = actor.GetMaterialList().HasMaterial(EMaterialTypes::Player); - float remDt = dt; - float originalDt = dt; - TCastToPtr otherActor; - CCollisionInfoList collisionList; - CMotionState newMState = actor.PredictMotion_Internal(dt); - float transMag = newMState.x0_translation.magnitude(); - float divMag; - if (isPlayer) - divMag = std::max(transMag / 5.f, 0.005f); - else - divMag = std::max(transMag / 3.f, 0.02f); + const CMaterialFilter& filter, + rstl::reserved_vector& nearList, float dt) { + bool didCollide = false; + bool isPlayer = actor.GetMaterialList().HasMaterial(EMaterialTypes::Player); + float remDt = dt; + float originalDt = dt; + TCastToPtr otherActor; + CCollisionInfoList collisionList; + CMotionState newMState = actor.PredictMotion_Internal(dt); + float transMag = newMState.x0_translation.magnitude(); + float divMag; + if (isPlayer) + divMag = std::max(transMag / 5.f, 0.005f); + else + divMag = std::max(transMag / 3.f, 0.02f); - float minExtent = 0.5f * CGameCollision::GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive()); - if (transMag > minExtent) - { - dt = minExtent * (dt / transMag); - originalDt = dt; - newMState = actor.PredictMotion_Internal(dt); - divMag = std::min(divMag, minExtent); + float minExtent = 0.5f * CGameCollision::GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive()); + if (transMag > minExtent) { + dt = minExtent * (dt / transMag); + originalDt = dt; + newMState = actor.PredictMotion_Internal(dt); + divMag = std::min(divMag, minExtent); + } + + float nonCollideDt = dt; + do { + actor.MoveCollisionPrimitive(newMState.x0_translation); + collisionList.Clear(); + TUniqueId otherId = kInvalidUniqueId; + bool collided = + CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), + actor.GetPrimitiveTransform(), filter, nearList, otherId, collisionList); + if (collided) + otherActor = mgr.ObjectById(otherId); + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); + if (collided) { + didCollide = true; + if (newMState.x0_translation.magnitude() < divMag) { + CCollisionInfoList backfaceFilteredList, floorFilteredList; + zeus::CVector3f deltaVel = actor.GetVelocity(); + if (otherActor) + deltaVel -= otherActor->GetVelocity(); + CollisionUtil::FilterOutBackfaces(deltaVel, collisionList, backfaceFilteredList); + CAABoxFilter::FilterBoxFloorCollisions(backfaceFilteredList, floorFilteredList); + CGameCollision::MakeCollisionCallbacks(mgr, actor, otherId, floorFilteredList); + if (floorFilteredList.GetCount() == 0 && isPlayer) { + CMotionState lastNonCollideState = actor.GetLastNonCollidingState(); + lastNonCollideState.x1c_velocity *= zeus::CVector3f(0.5f); + lastNonCollideState.x28_angularMomentum *= zeus::CVector3f(0.5f); + actor.SetMotionState(lastNonCollideState); + } + for (const CCollisionInfo& info : floorFilteredList) { + CCollisionInfo infoCopy = info; + float restitution = + CGameCollision::GetCoefficientOfRestitution(infoCopy) + actor.GetCoefficientOfRestitutionModifier(); + if (otherActor) + CGameCollision::CollideWithDynamicBodyNoRot(actor, *otherActor, infoCopy, restitution, true); + else + CGameCollision::CollideWithStaticBodyNoRot(actor, infoCopy.GetMaterialLeft(), infoCopy.GetMaterialRight(), + infoCopy.GetNormalLeft(), restitution, true); + } + remDt -= dt; + nonCollideDt = std::min(originalDt, remDt); + dt = nonCollideDt; + } else { + nonCollideDt *= 0.5f; + dt *= 0.5f; + } + } else { + actor.AddMotionState(newMState); + remDt -= dt; + dt = nonCollideDt; + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); } - float nonCollideDt = dt; - do - { - actor.MoveCollisionPrimitive(newMState.x0_translation); - collisionList.Clear(); - TUniqueId otherId = kInvalidUniqueId; - bool collided = CGameCollision::DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetPrimitiveTransform(), filter, nearList, - otherId, collisionList); - if (collided) - otherActor = mgr.ObjectById(otherId); - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); - if (collided) - { - didCollide = true; - if (newMState.x0_translation.magnitude() < divMag) - { - CCollisionInfoList backfaceFilteredList, floorFilteredList; - zeus::CVector3f deltaVel = actor.GetVelocity(); - if (otherActor) - deltaVel -= otherActor->GetVelocity(); - CollisionUtil::FilterOutBackfaces(deltaVel, collisionList, backfaceFilteredList); - CAABoxFilter::FilterBoxFloorCollisions(backfaceFilteredList, floorFilteredList); - CGameCollision::MakeCollisionCallbacks(mgr, actor, otherId, floorFilteredList); - if (floorFilteredList.GetCount() == 0 && isPlayer) - { - CMotionState lastNonCollideState = actor.GetLastNonCollidingState(); - lastNonCollideState.x1c_velocity *= zeus::CVector3f(0.5f); - lastNonCollideState.x28_angularMomentum *= zeus::CVector3f(0.5f); - actor.SetMotionState(lastNonCollideState); - } - for (const CCollisionInfo& info : floorFilteredList) - { - CCollisionInfo infoCopy = info; - float restitution = CGameCollision::GetCoefficientOfRestitution(infoCopy) + - actor.GetCoefficientOfRestitutionModifier(); - if (otherActor) - CGameCollision::CollideWithDynamicBodyNoRot(actor, *otherActor, infoCopy, restitution, true); - else - CGameCollision::CollideWithStaticBodyNoRot(actor, infoCopy.GetMaterialLeft(), infoCopy.GetMaterialRight(), - infoCopy.GetNormalLeft(), restitution, true); - } - remDt -= dt; - nonCollideDt = std::min(originalDt, remDt); - dt = nonCollideDt; - } - else - { - nonCollideDt *= 0.5f; - dt *= 0.5f; - } - } - else - { - actor.AddMotionState(newMState); - remDt -= dt; - dt = nonCollideDt; - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); - } + newMState = actor.PredictMotion_Internal(dt); + } while (remDt > 0.f); - newMState = actor.PredictMotion_Internal(dt); - } while (remDt > 0.f); + if (!didCollide && !actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) + mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling); - if (!didCollide && !actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) - mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling); - - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); } zeus::CVector3f CGroundMovement::CollisionDamping(const zeus::CVector3f& vel, const zeus::CVector3f& dir, - const zeus::CVector3f& cNorm, float normCoeff, float deltaCoeff) -{ - zeus::CVector3f dampedDir = (cNorm * -2.f * cNorm.dot(dir) + dir).normalized(); - zeus::CVector3f dampedNorm = cNorm * cNorm.dot(dampedDir); - return (dampedDir - dampedNorm) * vel.magnitude() * deltaCoeff + normCoeff * vel.magnitude() * dampedNorm; + const zeus::CVector3f& cNorm, float normCoeff, float deltaCoeff) { + zeus::CVector3f dampedDir = (cNorm * -2.f * cNorm.dot(dir) + dir).normalized(); + zeus::CVector3f dampedNorm = cNorm * cNorm.dot(dampedDir); + return (dampedDir - dampedNorm) * vel.magnitude() * deltaCoeff + normCoeff * vel.magnitude() * dampedNorm; } void CGroundMovement::MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float dt, - const rstl::reserved_vector* nearList) -{ - zeus::CAABox motionVol = actor.GetMotionVolume(dt); - rstl::reserved_vector useNearList; - if (nearList) - useNearList = *nearList; - else - mgr.BuildColliderList(useNearList, actor, motionVol); + const rstl::reserved_vector* nearList) { + zeus::CAABox motionVol = actor.GetMotionVolume(dt); + rstl::reserved_vector useNearList; + if (nearList) + useNearList = *nearList; + else + mgr.BuildColliderList(useNearList, actor, motionVol); - CAreaCollisionCache cache(motionVol); - CGameCollision::BuildAreaCollisionCache(mgr, cache); - CPlayer& player = static_cast(actor); - player.x9c5_28_slidingOnWall = false; - bool applyJump = player.x258_movementState == CPlayer::EPlayerMovementState::ApplyJump; - bool dampUnderwater = false; - if (player.x9c4_31_dampUnderwaterMotion) - if (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) - dampUnderwater = true; + CAreaCollisionCache cache(motionVol); + CGameCollision::BuildAreaCollisionCache(mgr, cache); + CPlayer& player = static_cast(actor); + player.x9c5_28_slidingOnWall = false; + bool applyJump = player.x258_movementState == CPlayer::EPlayerMovementState::ApplyJump; + bool dampUnderwater = false; + if (player.x9c4_31_dampUnderwaterMotion) + if (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) + dampUnderwater = true; - bool noJump = (player.x258_movementState != CPlayer::EPlayerMovementState::ApplyJump && - player.x258_movementState != CPlayer::EPlayerMovementState::Jump); + bool noJump = (player.x258_movementState != CPlayer::EPlayerMovementState::ApplyJump && + player.x258_movementState != CPlayer::EPlayerMovementState::Jump); - float stepDown = player.GetStepDownHeight(); - float stepUp = player.GetStepUpHeight(); + float stepDown = player.GetStepDownHeight(); + float stepUp = player.GetStepUpHeight(); - bool doStepDown = true; - CMaterialList material(EMaterialTypes::NoStepLogic); - SMoveObjectResult result; + bool doStepDown = true; + CMaterialList material(EMaterialTypes::NoStepLogic); + SMoveObjectResult result; - if (!applyJump) - { - SMovementOptions opts; - opts.x0_setWaterLandingForce = false; - opts.x4_waterLandingForceCoefficient = 0.f; - opts.x8_minimumWaterLandingForce = 0.f; - opts.xc_anyZThreshold = 0.37f; - opts.x10_downwardZThreshold = 0.25f; - opts.x14_waterLandingVelocityReduction = 0.f; - opts.x18_dampForceAndMomentum = true; - opts.x19_alwaysClip = false; - opts.x1a_disableClipForFloorOnly = noJump; - opts.x1c_maxCollisionCycles = 4; - opts.x20_minimumTranslationDelta = 0.002f; - opts.x24_dampedNormalCoefficient = 0.f; - opts.x28_dampedDeltaCoefficient = 1.f; - opts.x2c_floorElasticForce = 0.f; - opts.x30_wallElasticConstant = 0.02f; - opts.x3c_floorPlaneNormal = player.GetLastFloorPlaneNormal(); - opts.x34_wallElasticLinear = 0.2f; - opts.x38_maxPositiveVerticalVelocity = player.GetMaximumPlayerPositiveVerticalVelocity(mgr); + if (!applyJump) { + SMovementOptions opts; + opts.x0_setWaterLandingForce = false; + opts.x4_waterLandingForceCoefficient = 0.f; + opts.x8_minimumWaterLandingForce = 0.f; + opts.xc_anyZThreshold = 0.37f; + opts.x10_downwardZThreshold = 0.25f; + opts.x14_waterLandingVelocityReduction = 0.f; + opts.x18_dampForceAndMomentum = true; + opts.x19_alwaysClip = false; + opts.x1a_disableClipForFloorOnly = noJump; + opts.x1c_maxCollisionCycles = 4; + opts.x20_minimumTranslationDelta = 0.002f; + opts.x24_dampedNormalCoefficient = 0.f; + opts.x28_dampedDeltaCoefficient = 1.f; + opts.x2c_floorElasticForce = 0.f; + opts.x30_wallElasticConstant = 0.02f; + opts.x3c_floorPlaneNormal = player.GetLastFloorPlaneNormal(); + opts.x34_wallElasticLinear = 0.2f; + opts.x38_maxPositiveVerticalVelocity = player.GetMaximumPlayerPositiveVerticalVelocity(mgr); - if (noJump) - { - zeus::CVector3f vel = player.GetVelocity(); - vel.z() = 0.f; - actor.SetVelocityWR(vel); - actor.x15c_force.z() = 0.f; - actor.x150_momentum.z() = 0.f; - actor.x168_impulse.z() = 0.f; - } - - CPhysicsState physStatePre = actor.GetPhysicsState(); - CMaterialList material2 = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, opts, result); - CPhysicsState physStatePost = actor.GetPhysicsState(); - - /* NoStepLogic must be the only set material bit to bypass step logic */ - if (material2.XOR({EMaterialTypes::NoStepLogic})) - { - SMovementOptions optsCopy = opts; - zeus::CVector3f postToPre = physStatePre.GetTranslation() - physStatePost.GetTranslation(); - float postToPreMag = postToPre.magSquared(); - optsCopy.x19_alwaysClip = noJump; - float quarterStepUp = 0.25f * stepUp; - rstl::reserved_vector physStateList; - rstl::reserved_vector stepDeltaList; - rstl::reserved_vector collisionInfoList; - rstl::reserved_vector uniqueIdList; - rstl::reserved_vector materialListList; - bool done = false; - for (int i=0 ; i < 2 && !done ; ++i) - { - double useStepUp = (i == 0) ? quarterStepUp : stepUp; - actor.SetPhysicsState(physStatePre); - CCollisionInfo collisionInfo; - TUniqueId id = kInvalidUniqueId; - CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetTransform(), actor.GetMaterialFilter(), - useNearList, {0.f, 0.f, 1.f}, id, collisionInfo, - useStepUp); - if (collisionInfo.IsValid()) - { - useStepUp = std::max(0.0, useStepUp - optsCopy.x20_minimumTranslationDelta); - done = true; - } - - if (useStepUp > 0.0005) - { - actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, useStepUp)); - - SMoveObjectResult result2; - CMaterialList material3 = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, optsCopy, result2); - CCollisionInfo collisionInfo2; - double useStepDown2 = useStepUp + stepDown; - TUniqueId id2 = kInvalidUniqueId; - if (useStepDown2 > 0.0) - { - CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetTransform(), actor.GetMaterialFilter(), - useNearList, {0.f, 0.f, -1.f}, id2, collisionInfo2, - useStepDown2); - } - else - { - useStepDown2 = 0.0; - } - - float minStep = std::min(useStepUp, useStepDown2); - zeus::CVector3f offsetStep = actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, minStep); - bool floor = (collisionInfo2.IsValid() && - CGameCollision::CanBlock(collisionInfo2.GetMaterialLeft(), collisionInfo2.GetNormalLeft())); - zeus::CVector3f postToPre2 = physStatePre.GetTranslation() - offsetStep; - float stepDelta = postToPre2.magSquared(); - if (floor && postToPreMag < stepDelta) - { - useStepDown2 = std::max(0.0, useStepDown2 - 0.0005); - actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, useStepDown2)); - physStateList.push_back(actor.GetPhysicsState()); - stepDeltaList.push_back(stepDelta); - collisionInfoList.push_back(collisionInfo2); - uniqueIdList.push_back(id2); - materialListList.push_back(material3); - } - } - } - - if (physStateList.size() == 0) - { - actor.SetPhysicsState(physStatePost); - material = material2; - } - else - { - float maxFloat = -1.0e10f; - int maxIdx = -1; - for (int i=0 ; i(ent)) - mgr.SendScriptMsg(ent, actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider); - } - - CCollisionInfo& cInfo = collisionInfoList[maxIdx]; - CGameCollision::SendMaterialMessage(mgr, cInfo.GetMaterialLeft(), actor); - doStepDown = false; - actor.SetLastFloorPlaneNormal({cInfo.GetNormalLeft()}); - } - } - } - else - { - SMovementOptions opts; - opts.x0_setWaterLandingForce = true; - opts.x4_waterLandingForceCoefficient = dampUnderwater ? 35.f : 1.f; - opts.x8_minimumWaterLandingForce = dampUnderwater ? 5.f : 0.f; - opts.xc_anyZThreshold = dampUnderwater ? 0.05f : 0.37f; - opts.x10_downwardZThreshold = dampUnderwater ? 0.01f : 0.25f; - opts.x14_waterLandingVelocityReduction = dampUnderwater ? 0.2f : 0.f; - opts.x18_dampForceAndMomentum = false; - opts.x19_alwaysClip = false; - opts.x1a_disableClipForFloorOnly = false; - opts.x1c_maxCollisionCycles = 4; - opts.x20_minimumTranslationDelta = 0.002f; - opts.x24_dampedNormalCoefficient = 0.f; - opts.x28_dampedDeltaCoefficient = 1.f; - opts.x2c_floorElasticForce = 0.1f; - opts.x30_wallElasticConstant = dampUnderwater ? 0.2f : 0.2f; - opts.x3c_floorPlaneNormal = player.GetLastFloorPlaneNormal(); - opts.x38_maxPositiveVerticalVelocity = player.GetMaximumPlayerPositiveVerticalVelocity(mgr); - - material = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, opts, result); + if (noJump) { + zeus::CVector3f vel = player.GetVelocity(); + vel.z() = 0.f; + actor.SetVelocityWR(vel); + actor.x15c_force.z() = 0.f; + actor.x150_momentum.z() = 0.f; + actor.x168_impulse.z() = 0.f; } - if (doStepDown) - { + CPhysicsState physStatePre = actor.GetPhysicsState(); + CMaterialList material2 = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, opts, result); + CPhysicsState physStatePost = actor.GetPhysicsState(); + + /* NoStepLogic must be the only set material bit to bypass step logic */ + if (material2.XOR({EMaterialTypes::NoStepLogic})) { + SMovementOptions optsCopy = opts; + zeus::CVector3f postToPre = physStatePre.GetTranslation() - physStatePost.GetTranslation(); + float postToPreMag = postToPre.magSquared(); + optsCopy.x19_alwaysClip = noJump; + float quarterStepUp = 0.25f * stepUp; + rstl::reserved_vector physStateList; + rstl::reserved_vector stepDeltaList; + rstl::reserved_vector collisionInfoList; + rstl::reserved_vector uniqueIdList; + rstl::reserved_vector materialListList; + bool done = false; + for (int i = 0; i < 2 && !done; ++i) { + double useStepUp = (i == 0) ? quarterStepUp : stepUp; + actor.SetPhysicsState(physStatePre); CCollisionInfo collisionInfo; - double stepDown2 = actor.GetStepDownHeight(); - float zOffset = 0.f; TUniqueId id = kInvalidUniqueId; - if (stepDown2 > FLT_EPSILON) - { - zeus::CTransform xf = actor.GetTransform(); - xf.origin += zeus::CVector3f(0.f, 0.f, 0.0005f); - if (!CGameCollision::DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(), - xf, actor.GetMaterialFilter(), useNearList)) - { - actor.SetTranslation(xf.origin); - zOffset = 0.0005f; - stepDown2 += 0.0005; - } + CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(), actor.GetTransform(), + actor.GetMaterialFilter(), useNearList, {0.f, 0.f, 1.f}, id, + collisionInfo, useStepUp); + if (collisionInfo.IsValid()) { + useStepUp = std::max(0.0, useStepUp - optsCopy.x20_minimumTranslationDelta); + done = true; + } + if (useStepUp > 0.0005) { + actor.SetTranslation(actor.GetTranslation() + zeus::CVector3f(0.f, 0.f, useStepUp)); + + SMoveObjectResult result2; + CMaterialList material3 = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, optsCopy, result2); + CCollisionInfo collisionInfo2; + double useStepDown2 = useStepUp + stepDown; + TUniqueId id2 = kInvalidUniqueId; + if (useStepDown2 > 0.0) { CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetTransform(), actor.GetMaterialFilter(), - useNearList, {0.f, 0.f, -1.f}, id, collisionInfo, - stepDown2); + actor.GetTransform(), actor.GetMaterialFilter(), useNearList, + {0.f, 0.f, -1.f}, id2, collisionInfo2, useStepDown2); + } else { + useStepDown2 = 0.0; + } + + float minStep = std::min(useStepUp, useStepDown2); + zeus::CVector3f offsetStep = actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, minStep); + bool floor = (collisionInfo2.IsValid() && + CGameCollision::CanBlock(collisionInfo2.GetMaterialLeft(), collisionInfo2.GetNormalLeft())); + zeus::CVector3f postToPre2 = physStatePre.GetTranslation() - offsetStep; + float stepDelta = postToPre2.magSquared(); + if (floor && postToPreMag < stepDelta) { + useStepDown2 = std::max(0.0, useStepDown2 - 0.0005); + actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, useStepDown2)); + physStateList.push_back(actor.GetPhysicsState()); + stepDeltaList.push_back(stepDelta); + collisionInfoList.push_back(collisionInfo2); + uniqueIdList.push_back(id2); + materialListList.push_back(material3); + } + } + } + + if (physStateList.size() == 0) { + actor.SetPhysicsState(physStatePost); + material = material2; + } else { + float maxFloat = -1.0e10f; + int maxIdx = -1; + for (int i = 0; i < physStateList.size(); ++i) { + if (maxFloat < stepDeltaList[i]) { + maxFloat = stepDeltaList[i]; + maxIdx = i; + } } - if (id != kInvalidUniqueId) - { - result.x0_id.emplace(id); - result.x8_collision.emplace(collisionInfo); + actor.SetPhysicsState(physStateList[maxIdx]); + mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor); + if (CEntity* ent = mgr.ObjectById(uniqueIdList[maxIdx])) { + result.x0_id.emplace(uniqueIdList[maxIdx]); + result.x8_collision.emplace(collisionInfoList[maxIdx]); + if (TCastToPtr(ent)) + mgr.SendScriptMsg(ent, actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider); } - if (!collisionInfo.IsValid() || - !CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionInfo.GetNormalLeft())) - { - if (zOffset > 0.f) - { - zeus::CTransform xf = actor.GetTransform(); - xf.origin -= zeus::CVector3f(0.f, 0.f, zOffset); - } + CCollisionInfo& cInfo = collisionInfoList[maxIdx]; + CGameCollision::SendMaterialMessage(mgr, cInfo.GetMaterialLeft(), actor); + doStepDown = false; + actor.SetLastFloorPlaneNormal({cInfo.GetNormalLeft()}); + } + } + } else { + SMovementOptions opts; + opts.x0_setWaterLandingForce = true; + opts.x4_waterLandingForceCoefficient = dampUnderwater ? 35.f : 1.f; + opts.x8_minimumWaterLandingForce = dampUnderwater ? 5.f : 0.f; + opts.xc_anyZThreshold = dampUnderwater ? 0.05f : 0.37f; + opts.x10_downwardZThreshold = dampUnderwater ? 0.01f : 0.25f; + opts.x14_waterLandingVelocityReduction = dampUnderwater ? 0.2f : 0.f; + opts.x18_dampForceAndMomentum = false; + opts.x19_alwaysClip = false; + opts.x1a_disableClipForFloorOnly = false; + opts.x1c_maxCollisionCycles = 4; + opts.x20_minimumTranslationDelta = 0.002f; + opts.x24_dampedNormalCoefficient = 0.f; + opts.x28_dampedDeltaCoefficient = 1.f; + opts.x2c_floorElasticForce = 0.1f; + opts.x30_wallElasticConstant = dampUnderwater ? 0.2f : 0.2f; + opts.x3c_floorPlaneNormal = player.GetLastFloorPlaneNormal(); + opts.x38_maxPositiveVerticalVelocity = player.GetMaximumPlayerPositiveVerticalVelocity(mgr); - if (collisionInfo.IsValid()) - player.x9c5_28_slidingOnWall = true; - CheckFalling(actor, mgr, dt); - player.SetLastFloorPlaneNormal({}); - } - else - { - mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor); - stepDown2 = std::max(0.0, stepDown2 - 0.0005); - actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, stepDown2)); - if (TCastToPtr plat = mgr.ObjectById(id)) - mgr.SendScriptMsg(plat.GetPtr(), actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider); - CGameCollision::SendMaterialMessage(mgr, collisionInfo.GetMaterialLeft(), actor); - actor.SetLastFloorPlaneNormal({collisionInfo.GetNormalLeft()}); - } + material = MoveObjectAnalytical(mgr, actor, dt, useNearList, cache, opts, result); + } + + if (doStepDown) { + CCollisionInfo collisionInfo; + double stepDown2 = actor.GetStepDownHeight(); + float zOffset = 0.f; + TUniqueId id = kInvalidUniqueId; + if (stepDown2 > FLT_EPSILON) { + zeus::CTransform xf = actor.GetTransform(); + xf.origin += zeus::CVector3f(0.f, 0.f, 0.0005f); + if (!CGameCollision::DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(), xf, + actor.GetMaterialFilter(), useNearList)) { + actor.SetTranslation(xf.origin); + zOffset = 0.0005f; + stepDown2 += 0.0005; + } + + CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(), actor.GetTransform(), + actor.GetMaterialFilter(), useNearList, {0.f, 0.f, -1.f}, id, + collisionInfo, stepDown2); } - actor.ClearForcesAndTorques(); - if (material.HasMaterial(EMaterialTypes::Wall)) - player.SetPlayerHitWallDuringMove(); - - if (result.x0_id) - { - CCollisionInfoList list; - list.Add(*result.x8_collision, false); - CGameCollision::MakeCollisionCallbacks(mgr, actor, *result.x0_id, list); + if (id != kInvalidUniqueId) { + result.x0_id.emplace(id); + result.x8_collision.emplace(collisionInfo); } - CMotionState mState = actor.GetMotionState(); - mState.x0_translation = actor.GetLastNonCollidingState().x0_translation; - mState.x1c_velocity = actor.GetLastNonCollidingState().x1c_velocity; - actor.SetLastNonCollidingState(mState); + if (!collisionInfo.IsValid() || + !CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionInfo.GetNormalLeft())) { + if (zOffset > 0.f) { + zeus::CTransform xf = actor.GetTransform(); + xf.origin -= zeus::CVector3f(0.f, 0.f, zOffset); + } - const CCollisionPrimitive* usePrim = actor.GetCollisionPrimitive(); - std::unique_ptr prim; - if (usePrim->GetPrimType() == FOURCC('AABX')) - { - const CCollidableAABox& existingAABB = static_cast(*usePrim); - prim.reset(new CCollidableAABox(zeus::CAABox(existingAABB.GetAABB().min + 0.0001f, - existingAABB.GetAABB().max - 0.0001f), - usePrim->GetMaterial())); - usePrim = prim.get(); - } - else if (usePrim->GetPrimType() == FOURCC('SPHR')) - { - const CCollidableSphere& existingSphere = static_cast(*usePrim); - prim.reset(new CCollidableSphere(zeus::CSphere(existingSphere.GetSphere().position, - existingSphere.GetSphere().radius - 0.0001f), - usePrim->GetMaterial())); - usePrim = prim.get(); + if (collisionInfo.IsValid()) + player.x9c5_28_slidingOnWall = true; + CheckFalling(actor, mgr, dt); + player.SetLastFloorPlaneNormal({}); + } else { + mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::OnFloor); + stepDown2 = std::max(0.0, stepDown2 - 0.0005); + actor.SetTranslation(actor.GetTranslation() - zeus::CVector3f(0.f, 0.f, stepDown2)); + if (TCastToPtr plat = mgr.ObjectById(id)) + mgr.SendScriptMsg(plat.GetPtr(), actor.GetUniqueId(), EScriptObjectMessage::AddPlatformRider); + CGameCollision::SendMaterialMessage(mgr, collisionInfo.GetMaterialLeft(), actor); + actor.SetLastFloorPlaneNormal({collisionInfo.GetNormalLeft()}); } + } - CGameCollision::CollisionFailsafe(mgr, cache, actor, *usePrim, useNearList, 0.f, 1); + actor.ClearForcesAndTorques(); + if (material.HasMaterial(EMaterialTypes::Wall)) + player.SetPlayerHitWallDuringMove(); + + if (result.x0_id) { + CCollisionInfoList list; + list.Add(*result.x8_collision, false); + CGameCollision::MakeCollisionCallbacks(mgr, actor, *result.x0_id, list); + } + + CMotionState mState = actor.GetMotionState(); + mState.x0_translation = actor.GetLastNonCollidingState().x0_translation; + mState.x1c_velocity = actor.GetLastNonCollidingState().x1c_velocity; + actor.SetLastNonCollidingState(mState); + + const CCollisionPrimitive* usePrim = actor.GetCollisionPrimitive(); + std::unique_ptr prim; + if (usePrim->GetPrimType() == FOURCC('AABX')) { + const CCollidableAABox& existingAABB = static_cast(*usePrim); + prim.reset( + new CCollidableAABox(zeus::CAABox(existingAABB.GetAABB().min + 0.0001f, existingAABB.GetAABB().max - 0.0001f), + usePrim->GetMaterial())); + usePrim = prim.get(); + } else if (usePrim->GetPrimType() == FOURCC('SPHR')) { + const CCollidableSphere& existingSphere = static_cast(*usePrim); + prim.reset(new CCollidableSphere( + zeus::CSphere(existingSphere.GetSphere().position, existingSphere.GetSphere().radius - 0.0001f), + usePrim->GetMaterial())); + usePrim = prim.get(); + } + + CGameCollision::CollisionFailsafe(mgr, cache, actor, *usePrim, useNearList, 0.f, 1); } -bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, const zeus::CVector3f& b, - zeus::CVector3f& c, float& d) -{ - float dot = a.dot(c); - if (std::fabs(dot) > 0.99f) - return false; - float dot2 = b.dot(c); - float dot3 = b.dot((c - a * dot).normalized()); - if (dot2 > 0.f && dot3 < 0.f) - return false; - if (std::fabs(dot2) > 0.01f && std::fabs(dot3 / dot2) > 4.f) - return false; - c -= dot * a; - d = dot; - return true; -} - -bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, zeus::CVector3f& b) -{ - float dot = a.dot(b); - if (std::fabs(dot) > 0.99f) - return false; - b -= a * dot; - return true; -} - -static bool RemovePositiveZComponentFromNormal(zeus::CVector3f& vec) -{ - if (vec.z() > 0.f && vec.z() < 0.99f) - { - vec.z() = 0.f; - vec.normalize(); - return true; - } +bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, const zeus::CVector3f& b, zeus::CVector3f& c, + float& d) { + float dot = a.dot(c); + if (std::fabs(dot) > 0.99f) return false; + float dot2 = b.dot(c); + float dot3 = b.dot((c - a * dot).normalized()); + if (dot2 > 0.f && dot3 < 0.f) + return false; + if (std::fabs(dot2) > 0.01f && std::fabs(dot3 / dot2) > 4.f) + return false; + c -= dot * a; + d = dot; + return true; +} + +bool CGroundMovement::RemoveNormalComponent(const zeus::CVector3f& a, zeus::CVector3f& b) { + float dot = a.dot(b); + if (std::fabs(dot) > 0.99f) + return false; + b -= a * dot; + return true; +} + +static bool RemovePositiveZComponentFromNormal(zeus::CVector3f& vec) { + if (vec.z() > 0.f && vec.z() < 0.99f) { + vec.z() = 0.f; + vec.normalize(); + return true; + } + return false; } CMaterialList CGroundMovement::MoveObjectAnalytical(CStateManager& mgr, CPhysicsActor& actor, float dt, rstl::reserved_vector& nearList, CAreaCollisionCache& cache, const SMovementOptions& opts, - SMoveObjectResult& result) -{ - result.x6c_processedCollisions = 0; - CMaterialList ret; - zeus::CVector3f floorPlaneNormal = opts.x3c_floorPlaneNormal ? - *opts.x3c_floorPlaneNormal : zeus::CVector3f::skZero; - bool floorCollision = opts.x3c_floorPlaneNormal.operator bool(); - float remDt = dt; - for (int i=0 ; remDt > 0.f ; ++i) - { - float collideDt = remDt; + SMoveObjectResult& result) { + result.x6c_processedCollisions = 0; + CMaterialList ret; + zeus::CVector3f floorPlaneNormal = opts.x3c_floorPlaneNormal ? *opts.x3c_floorPlaneNormal : zeus::CVector3f::skZero; + bool floorCollision = opts.x3c_floorPlaneNormal.operator bool(); + float remDt = dt; + for (int i = 0; remDt > 0.f; ++i) { + float collideDt = remDt; - CMotionState mState = actor.PredictMotion_Internal(remDt); - double mag = mState.x0_translation.magnitude(); - zeus::CVector3f normTrans = (1.f / ((float(mag) > FLT_EPSILON) ? float(mag) : 1.f)) * mState.x0_translation; - TUniqueId id = kInvalidUniqueId; - CCollisionInfo collisionInfo; + CMotionState mState = actor.PredictMotion_Internal(remDt); + double mag = mState.x0_translation.magnitude(); + zeus::CVector3f normTrans = (1.f / ((float(mag) > FLT_EPSILON) ? float(mag) : 1.f)) * mState.x0_translation; + TUniqueId id = kInvalidUniqueId; + CCollisionInfo collisionInfo; - if (mag > opts.x20_minimumTranslationDelta) - { - double oldMag = mag; - CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetPrimitiveTransform(), actor.GetMaterialFilter(), - nearList, normTrans, id, collisionInfo, mag); - if (id != kInvalidUniqueId) - { - result.x0_id.emplace(id); - result.x8_collision.emplace(collisionInfo); - } - collideDt = mag / oldMag * remDt; - } - - mag = std::max(0.f, float(mag) - opts.x20_minimumTranslationDelta); - - zeus::CVector3f collisionNorm = collisionInfo.GetNormalLeft(); - bool floor = CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionNorm); - bool clipCollision = true; - if (!opts.x19_alwaysClip) - { - if (!opts.x1a_disableClipForFloorOnly || floor) - clipCollision = false; - } - - float collisionFloorDot = 0.f; - - if (collisionInfo.IsValid()) - { - result.x6c_processedCollisions += 1; - if (floor) - { - ret.Add(EMaterialTypes::Floor); - floorPlaneNormal = collisionInfo.GetNormalLeft(); - floorCollision = true; - } - else - { - ret.Add(EMaterialTypes::Wall); - } - - if (clipCollision) - { - if (floorCollision) - { - if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, normTrans, - collisionNorm, collisionFloorDot)) - RemovePositiveZComponentFromNormal(collisionNorm); - else - collisionNorm.normalize(); - } - else - { - RemovePositiveZComponentFromNormal(collisionNorm); - } - } - - mState = actor.PredictMotion_Internal(collideDt); - } - - mState.x0_translation = normTrans * mag; - actor.AddMotionState(mState); - - if (collisionInfo.IsValid()) - { - zeus::CVector3f vel = actor.GetVelocity().canBeNormalized() ? - CGroundMovement::CollisionDamping(actor.GetVelocity(), actor.GetVelocity().normalized(), - collisionNorm, opts.x24_dampedNormalCoefficient, - opts.x28_dampedDeltaCoefficient) : - zeus::CVector3f::skZero; - float elasticForce = floor ? opts.x2c_floorElasticForce : - opts.x34_wallElasticLinear * collisionFloorDot + opts.x30_wallElasticConstant; - float dot = collisionNorm.dot(vel); - if (dot < elasticForce) - vel += (elasticForce - dot) * collisionNorm; - if (clipCollision && floorCollision) - if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, vel)) - vel.z() = 0.f; - if (vel.z() > opts.x38_maxPositiveVerticalVelocity) - vel *= zeus::CVector3f(opts.x38_maxPositiveVerticalVelocity / vel.z()); - - if (opts.x18_dampForceAndMomentum) - { - if (actor.x15c_force.canBeNormalized()) - { - //zeus::CVector3f prevForce = actor.x15c_force; - actor.x15c_force = CGroundMovement::CollisionDamping(actor.x15c_force, - actor.x15c_force.normalized(), - collisionNorm, 0.f, 1.f); - } - if (actor.x150_momentum.canBeNormalized()) - { - actor.x150_momentum = CGroundMovement::CollisionDamping(actor.x150_momentum, - actor.x150_momentum.normalized(), - collisionNorm, 0.f, 1.f); - } - } - - if (opts.x0_setWaterLandingForce && !floor) - { - if (collisionInfo.GetNormalLeft().z() < -0.1f && vel.z() > 0.f) - vel.z() *= 0.5f; - - float zNormAbs = std::fabs(collisionInfo.GetNormalLeft().z()); - if ((zNormAbs > opts.x10_downwardZThreshold && vel.z() < 0.f) || zNormAbs > opts.xc_anyZThreshold) - { - actor.x15c_force = zeus::CVector3f(0.f, 0.f, - -(1.f + std::max(opts.x4_waterLandingForceCoefficient * zNormAbs, - opts.x8_minimumWaterLandingForce)) * actor.GetWeight()); - vel *= zeus::CVector3f(1.f - opts.x14_waterLandingVelocityReduction); - } - } - - actor.SetVelocityWR(vel); - } - else - { - zeus::CVector3f vel = actor.x138_velocity; - if (actor.x138_velocity.z() > opts.x38_maxPositiveVerticalVelocity) - vel *= zeus::CVector3f(opts.x38_maxPositiveVerticalVelocity / vel.z()); - - actor.SetVelocityWR(vel); - } - - actor.ClearImpulses(); - - remDt -= collideDt; - if (i >= opts.x1c_maxCollisionCycles) - break; + if (mag > opts.x20_minimumTranslationDelta) { + double oldMag = mag; + CGameCollision::DetectCollision_Cached_Moving(mgr, cache, *actor.GetCollisionPrimitive(), + actor.GetPrimitiveTransform(), actor.GetMaterialFilter(), nearList, + normTrans, id, collisionInfo, mag); + if (id != kInvalidUniqueId) { + result.x0_id.emplace(id); + result.x8_collision.emplace(collisionInfo); + } + collideDt = mag / oldMag * remDt; } - result.x70_processedDt = dt - remDt; - return ret; + mag = std::max(0.f, float(mag) - opts.x20_minimumTranslationDelta); + + zeus::CVector3f collisionNorm = collisionInfo.GetNormalLeft(); + bool floor = CGameCollision::CanBlock(collisionInfo.GetMaterialLeft(), collisionNorm); + bool clipCollision = true; + if (!opts.x19_alwaysClip) { + if (!opts.x1a_disableClipForFloorOnly || floor) + clipCollision = false; + } + + float collisionFloorDot = 0.f; + + if (collisionInfo.IsValid()) { + result.x6c_processedCollisions += 1; + if (floor) { + ret.Add(EMaterialTypes::Floor); + floorPlaneNormal = collisionInfo.GetNormalLeft(); + floorCollision = true; + } else { + ret.Add(EMaterialTypes::Wall); + } + + if (clipCollision) { + if (floorCollision) { + if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, normTrans, collisionNorm, collisionFloorDot)) + RemovePositiveZComponentFromNormal(collisionNorm); + else + collisionNorm.normalize(); + } else { + RemovePositiveZComponentFromNormal(collisionNorm); + } + } + + mState = actor.PredictMotion_Internal(collideDt); + } + + mState.x0_translation = normTrans * mag; + actor.AddMotionState(mState); + + if (collisionInfo.IsValid()) { + zeus::CVector3f vel = + actor.GetVelocity().canBeNormalized() + ? CGroundMovement::CollisionDamping(actor.GetVelocity(), actor.GetVelocity().normalized(), collisionNorm, + opts.x24_dampedNormalCoefficient, opts.x28_dampedDeltaCoefficient) + : zeus::CVector3f::skZero; + float elasticForce = floor ? opts.x2c_floorElasticForce + : opts.x34_wallElasticLinear * collisionFloorDot + opts.x30_wallElasticConstant; + float dot = collisionNorm.dot(vel); + if (dot < elasticForce) + vel += (elasticForce - dot) * collisionNorm; + if (clipCollision && floorCollision) + if (!CGroundMovement::RemoveNormalComponent(floorPlaneNormal, vel)) + vel.z() = 0.f; + if (vel.z() > opts.x38_maxPositiveVerticalVelocity) + vel *= zeus::CVector3f(opts.x38_maxPositiveVerticalVelocity / vel.z()); + + if (opts.x18_dampForceAndMomentum) { + if (actor.x15c_force.canBeNormalized()) { + // zeus::CVector3f prevForce = actor.x15c_force; + actor.x15c_force = CGroundMovement::CollisionDamping(actor.x15c_force, actor.x15c_force.normalized(), + collisionNorm, 0.f, 1.f); + } + if (actor.x150_momentum.canBeNormalized()) { + actor.x150_momentum = CGroundMovement::CollisionDamping(actor.x150_momentum, actor.x150_momentum.normalized(), + collisionNorm, 0.f, 1.f); + } + } + + if (opts.x0_setWaterLandingForce && !floor) { + if (collisionInfo.GetNormalLeft().z() < -0.1f && vel.z() > 0.f) + vel.z() *= 0.5f; + + float zNormAbs = std::fabs(collisionInfo.GetNormalLeft().z()); + if ((zNormAbs > opts.x10_downwardZThreshold && vel.z() < 0.f) || zNormAbs > opts.xc_anyZThreshold) { + actor.x15c_force = zeus::CVector3f( + 0.f, 0.f, + -(1.f + std::max(opts.x4_waterLandingForceCoefficient * zNormAbs, opts.x8_minimumWaterLandingForce)) * + actor.GetWeight()); + vel *= zeus::CVector3f(1.f - opts.x14_waterLandingVelocityReduction); + } + } + + actor.SetVelocityWR(vel); + } else { + zeus::CVector3f vel = actor.x138_velocity; + if (actor.x138_velocity.z() > opts.x38_maxPositiveVerticalVelocity) + vel *= zeus::CVector3f(opts.x38_maxPositiveVerticalVelocity / vel.z()); + + actor.SetVelocityWR(vel); + } + + actor.ClearImpulses(); + + remDt -= collideDt; + if (i >= opts.x1c_maxCollisionCycles) + break; + } + + result.x70_processedDt = dt - remDt; + return ret; } -} +} // namespace urde diff --git a/Runtime/Character/CGroundMovement.hpp b/Runtime/Character/CGroundMovement.hpp index 29745a544..96ef9c06d 100644 --- a/Runtime/Character/CGroundMovement.hpp +++ b/Runtime/Character/CGroundMovement.hpp @@ -3,70 +3,65 @@ #include "RetroTypes.hpp" #include "Collision/CCollisionInfo.hpp" -namespace urde -{ +namespace urde { class CPhysicsActor; class CStateManager; class CAreaCollisionCache; class CMaterialFilter; class CCollisionInfoList; -class CGroundMovement -{ +class CGroundMovement { public: - struct SMovementOptions - { - bool x0_setWaterLandingForce; - float x4_waterLandingForceCoefficient; - float x8_minimumWaterLandingForce; - float xc_anyZThreshold; - float x10_downwardZThreshold; - float x14_waterLandingVelocityReduction; - bool x18_dampForceAndMomentum; - bool x19_alwaysClip; - bool x1a_disableClipForFloorOnly; - u32 x1c_maxCollisionCycles; - float x20_minimumTranslationDelta; - float x24_dampedNormalCoefficient; - float x28_dampedDeltaCoefficient; - float x2c_floorElasticForce; - float x30_wallElasticConstant; - float x34_wallElasticLinear; - float x38_maxPositiveVerticalVelocity; - std::experimental::optional x3c_floorPlaneNormal; - }; + struct SMovementOptions { + bool x0_setWaterLandingForce; + float x4_waterLandingForceCoefficient; + float x8_minimumWaterLandingForce; + float xc_anyZThreshold; + float x10_downwardZThreshold; + float x14_waterLandingVelocityReduction; + bool x18_dampForceAndMomentum; + bool x19_alwaysClip; + bool x1a_disableClipForFloorOnly; + u32 x1c_maxCollisionCycles; + float x20_minimumTranslationDelta; + float x24_dampedNormalCoefficient; + float x28_dampedDeltaCoefficient; + float x2c_floorElasticForce; + float x30_wallElasticConstant; + float x34_wallElasticLinear; + float x38_maxPositiveVerticalVelocity; + std::experimental::optional x3c_floorPlaneNormal; + }; - struct SMoveObjectResult - { - std::experimental::optional x0_id; - std::experimental::optional x8_collision; - u32 x6c_processedCollisions; - float x70_processedDt; - }; + struct SMoveObjectResult { + std::experimental::optional x0_id; + std::experimental::optional x8_collision; + u32 x6c_processedCollisions; + float x70_processedDt; + }; - static void CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float); - static void MoveGroundCollider(CStateManager& mgr, CPhysicsActor& actor, float dt, - const rstl::reserved_vector* nearList); - static bool ResolveUpDown(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, - const CMaterialFilter& filter, rstl::reserved_vector& nearList, - float, float, float&, CCollisionInfoList& list); - static bool MoveGroundColliderZ(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, - const CMaterialFilter& filter, rstl::reserved_vector& nearList, - float, float&, CCollisionInfoList& list, TUniqueId& idOut); - static void MoveGroundColliderXY(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, - const CMaterialFilter& filter, rstl::reserved_vector& nearList, - float); - static zeus::CVector3f CollisionDamping(const zeus::CVector3f& a, const zeus::CVector3f& b, - const zeus::CVector3f& c, float d, float e); - static void MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float, - const rstl::reserved_vector* nearList); - static bool RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&, zeus::CVector3f&, float&); - static bool RemoveNormalComponent(const zeus::CVector3f& a, zeus::CVector3f& b); - static CMaterialList MoveObjectAnalytical(CStateManager& mgr, CPhysicsActor& actor, float, - rstl::reserved_vector& nearList, - CAreaCollisionCache& cache, const SMovementOptions& opts, - SMoveObjectResult& result); + static void CheckFalling(CPhysicsActor& actor, CStateManager& mgr, float); + static void MoveGroundCollider(CStateManager& mgr, CPhysicsActor& actor, float dt, + const rstl::reserved_vector* nearList); + static bool ResolveUpDown(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, + const CMaterialFilter& filter, rstl::reserved_vector& nearList, float, + float, float&, CCollisionInfoList& list); + static bool MoveGroundColliderZ(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, + const CMaterialFilter& filter, rstl::reserved_vector& nearList, + float, float&, CCollisionInfoList& list, TUniqueId& idOut); + static void MoveGroundColliderXY(CAreaCollisionCache& cache, CStateManager& mgr, CPhysicsActor& actor, + const CMaterialFilter& filter, rstl::reserved_vector& nearList, + float); + static zeus::CVector3f CollisionDamping(const zeus::CVector3f& a, const zeus::CVector3f& b, const zeus::CVector3f& c, + float d, float e); + static void MoveGroundCollider_New(CStateManager& mgr, CPhysicsActor& actor, float, + const rstl::reserved_vector* nearList); + static bool RemoveNormalComponent(const zeus::CVector3f&, const zeus::CVector3f&, zeus::CVector3f&, float&); + static bool RemoveNormalComponent(const zeus::CVector3f& a, zeus::CVector3f& b); + static CMaterialList MoveObjectAnalytical(CStateManager& mgr, CPhysicsActor& actor, float, + rstl::reserved_vector& nearList, + CAreaCollisionCache& cache, const SMovementOptions& opts, + SMoveObjectResult& result); }; -} - +} // namespace urde diff --git a/Runtime/Character/CHalfTransition.cpp b/Runtime/Character/CHalfTransition.cpp index 19b29d799..5b5a1f241 100644 --- a/Runtime/Character/CHalfTransition.cpp +++ b/Runtime/Character/CHalfTransition.cpp @@ -1,13 +1,11 @@ #include "CHalfTransition.hpp" #include "CMetaTransFactory.hpp" -namespace urde -{ +namespace urde { -CHalfTransition::CHalfTransition(CInputStream& in) -{ - x0_id = in.readUint32Big(); - x4_trans = CMetaTransFactory::CreateMetaTrans(in); +CHalfTransition::CHalfTransition(CInputStream& in) { + x0_id = in.readUint32Big(); + x4_trans = CMetaTransFactory::CreateMetaTrans(in); } -} +} // namespace urde diff --git a/Runtime/Character/CHalfTransition.hpp b/Runtime/Character/CHalfTransition.hpp index 335a08618..1a07da935 100644 --- a/Runtime/Character/CHalfTransition.hpp +++ b/Runtime/Character/CHalfTransition.hpp @@ -3,18 +3,16 @@ #include "IOStreams.hpp" #include "IMetaTrans.hpp" -namespace urde -{ +namespace urde { + +class CHalfTransition { + u32 x0_id; + std::shared_ptr x4_trans; -class CHalfTransition -{ - u32 x0_id; - std::shared_ptr x4_trans; public: - CHalfTransition(CInputStream& in); - u32 GetId() const {return x0_id;} - const std::shared_ptr& GetMetaTrans() const {return x4_trans;} + CHalfTransition(CInputStream& in); + u32 GetId() const { return x0_id; } + const std::shared_ptr& GetMetaTrans() const { return x4_trans; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CHierarchyPoseBuilder.cpp b/Runtime/Character/CHierarchyPoseBuilder.cpp index b7d566a6f..15e9e4945 100644 --- a/Runtime/Character/CHierarchyPoseBuilder.cpp +++ b/Runtime/Character/CHierarchyPoseBuilder.cpp @@ -2,183 +2,159 @@ #include "CAnimData.hpp" #include "CCharLayoutInfo.hpp" -namespace urde -{ +namespace urde { -void CHierarchyPoseBuilder::BuildIntoHierarchy(const CCharLayoutInfo& layout, - const CSegId& boneId, const CSegId& nullId) -{ - if (!x38_treeMap.HasElement(boneId)) - { - const CCharLayoutNode::Bone& bone = layout.GetRootNode()->GetBoneMap()[boneId]; - if (bone.x0_parentId == nullId) - { - xcec_rootId = boneId; - xcf0_hasRoot = true; - zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId); - CTreeNode& node = x38_treeMap[boneId]; - node.x14_offset = origin; - } - else - { - BuildIntoHierarchy(layout, bone.x0_parentId, nullId); - zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId); - CTreeNode& pNode = x38_treeMap[bone.x0_parentId]; - CTreeNode& node = x38_treeMap[boneId]; - node.x14_offset = origin; - node.x1_sibling = pNode.x0_child; - pNode.x0_child = boneId; - } +void CHierarchyPoseBuilder::BuildIntoHierarchy(const CCharLayoutInfo& layout, const CSegId& boneId, + const CSegId& nullId) { + if (!x38_treeMap.HasElement(boneId)) { + const CCharLayoutNode::Bone& bone = layout.GetRootNode()->GetBoneMap()[boneId]; + if (bone.x0_parentId == nullId) { + xcec_rootId = boneId; + xcf0_hasRoot = true; + zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId); + CTreeNode& node = x38_treeMap[boneId]; + node.x14_offset = origin; + } else { + BuildIntoHierarchy(layout, bone.x0_parentId, nullId); + zeus::CVector3f origin = layout.GetFromParentUnrotated(boneId); + CTreeNode& pNode = x38_treeMap[bone.x0_parentId]; + CTreeNode& node = x38_treeMap[boneId]; + node.x14_offset = origin; + node.x1_sibling = pNode.x0_child; + pNode.x0_child = boneId; } + } } void CHierarchyPoseBuilder::RecursivelyBuildNoScale(const CSegId& boneId, const CTreeNode& node, CPoseAsTransforms& pose, const zeus::CQuaternion& parentRot, - const zeus::CMatrix3f& parentXf, const zeus::CVector3f& parentOffset) const -{ - zeus::CVector3f bindOffset; - if (x0_layoutDesc.GetScaledLayoutDescription()) - { - const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription(); - bindOffset = desc.ScaledLayout()->GetFromRootUnrotated(boneId); - } - else - bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId); + const zeus::CMatrix3f& parentXf, + const zeus::CVector3f& parentOffset) const { + zeus::CVector3f bindOffset; + if (x0_layoutDesc.GetScaledLayoutDescription()) { + const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription(); + bindOffset = desc.ScaledLayout()->GetFromRootUnrotated(boneId); + } else + bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId); - zeus::CQuaternion quat = parentRot * node.x4_rotation; - zeus::CMatrix3f xf = quat; - zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset; - pose.Insert(boneId, quat, xfOffset, bindOffset); + zeus::CQuaternion quat = parentRot * node.x4_rotation; + zeus::CMatrix3f xf = quat; + zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset; + pose.Insert(boneId, quat, xfOffset, bindOffset); - CSegId curBone = node.x0_child; - while (curBone != 0) - { - const CTreeNode& node = x38_treeMap[curBone]; - RecursivelyBuild(curBone, node, pose, quat, xf, xfOffset); - curBone = node.x1_sibling; - } + CSegId curBone = node.x0_child; + while (curBone != 0) { + const CTreeNode& node = x38_treeMap[curBone]; + RecursivelyBuild(curBone, node, pose, quat, xf, xfOffset); + curBone = node.x1_sibling; + } } -void CHierarchyPoseBuilder::RecursivelyBuild(const CSegId& boneId, const CTreeNode& node, - CPoseAsTransforms& pose, const zeus::CQuaternion& parentRot, - const zeus::CMatrix3f& parentXf, const zeus::CVector3f& parentOffset) const -{ - zeus::CQuaternion quat = parentRot * node.x4_rotation; +void CHierarchyPoseBuilder::RecursivelyBuild(const CSegId& boneId, const CTreeNode& node, CPoseAsTransforms& pose, + const zeus::CQuaternion& parentRot, const zeus::CMatrix3f& parentXf, + const zeus::CVector3f& parentOffset) const { + zeus::CQuaternion quat = parentRot * node.x4_rotation; - float scale; - zeus::CVector3f bindOffset; - if (x0_layoutDesc.GetScaledLayoutDescription()) - { - const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription(); - scale = desc.GlobalScale(); - bindOffset = desc.ScaledLayout()->GetFromRootUnrotated(boneId); - } - else - { - scale = 1.f; - bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId); - } + float scale; + zeus::CVector3f bindOffset; + if (x0_layoutDesc.GetScaledLayoutDescription()) { + const CLayoutDescription::CScaledLayoutDescription& desc = *x0_layoutDesc.GetScaledLayoutDescription(); + scale = desc.GlobalScale(); + bindOffset = desc.ScaledLayout()->GetFromRootUnrotated(boneId); + } else { + scale = 1.f; + bindOffset = x0_layoutDesc.GetCharLayoutInfo()->GetFromRootUnrotated(boneId); + } - zeus::CMatrix3f mtxXf; + zeus::CMatrix3f mtxXf; + if (scale == 1.f) + mtxXf = quat; + else + mtxXf = parentXf * zeus::CMatrix3f(scale); + + zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset; + pose.Insert(boneId, mtxXf, xfOffset, bindOffset); + + CSegId curBone = node.x0_child; + while (curBone != 0) { + const CTreeNode& node = x38_treeMap[curBone]; + RecursivelyBuild(curBone, node, pose, quat, quat, xfOffset); + curBone = node.x1_sibling; + } +} + +void CHierarchyPoseBuilder::BuildTransform(const CSegId& boneId, zeus::CTransform& xfOut) const { + TLockedToken layoutInfoTok; + float scale; + if (x0_layoutDesc.GetScaledLayoutDescription()) { + layoutInfoTok = x0_layoutDesc.GetScaledLayoutDescription()->ScaledLayout(); + scale = x0_layoutDesc.GetScaledLayoutDescription()->GlobalScale(); + } else { + layoutInfoTok = x0_layoutDesc.GetCharLayoutInfo(); + scale = 1.f; + } + const CCharLayoutInfo& layoutInfo = *layoutInfoTok.GetObj(); + + u32 idCount = 0; + CSegId buildIDs[100]; + { + CSegId curId = boneId; + while (curId != 2) { + buildIDs[idCount++] = curId; + curId = layoutInfo.GetRootNode()->GetBoneMap()[curId].x0_parentId; + } + } + + zeus::CQuaternion accumRot; + zeus::CMatrix3f accumXF; + zeus::CVector3f accumPos; + for (CSegId* id = &buildIDs[idCount]; id != buildIDs; --id) { + CSegId& thisId = id[-1]; + const CTreeNode& node = x38_treeMap[thisId]; + accumRot *= node.x4_rotation; + accumPos += accumXF * node.x14_offset; if (scale == 1.f) - mtxXf = quat; + accumXF = accumRot; else - mtxXf = parentXf * zeus::CMatrix3f(scale); + accumXF = accumXF * zeus::CMatrix3f(node.x4_rotation) * zeus::CMatrix3f(scale); + } - zeus::CVector3f xfOffset = parentXf * node.x14_offset + parentOffset; - pose.Insert(boneId, mtxXf, xfOffset, bindOffset); - - CSegId curBone = node.x0_child; - while (curBone != 0) - { - const CTreeNode& node = x38_treeMap[curBone]; - RecursivelyBuild(curBone, node, pose, quat, quat, xfOffset); - curBone = node.x1_sibling; - } + xfOut.setRotation(accumXF); + xfOut.origin = accumPos; } -void CHierarchyPoseBuilder::BuildTransform(const CSegId& boneId, zeus::CTransform& xfOut) const -{ - TLockedToken layoutInfoTok; - float scale; - if (x0_layoutDesc.GetScaledLayoutDescription()) - { - layoutInfoTok = x0_layoutDesc.GetScaledLayoutDescription()->ScaledLayout(); - scale = x0_layoutDesc.GetScaledLayoutDescription()->GlobalScale(); - } - else - { - layoutInfoTok = x0_layoutDesc.GetCharLayoutInfo(); - scale = 1.f; - } - const CCharLayoutInfo& layoutInfo = *layoutInfoTok.GetObj(); - - u32 idCount = 0; - CSegId buildIDs[100]; - { - CSegId curId = boneId; - while (curId != 2) - { - buildIDs[idCount++] = curId; - curId = layoutInfo.GetRootNode()->GetBoneMap()[curId].x0_parentId; - } - } - - zeus::CQuaternion accumRot; - zeus::CMatrix3f accumXF; - zeus::CVector3f accumPos; - for (CSegId* id=&buildIDs[idCount] ; id != buildIDs ; --id) - { - CSegId& thisId = id[-1]; - const CTreeNode& node = x38_treeMap[thisId]; - accumRot *= node.x4_rotation; - accumPos += accumXF * node.x14_offset; - if (scale == 1.f) - accumXF = accumRot; - else - accumXF = accumXF * zeus::CMatrix3f(node.x4_rotation) * zeus::CMatrix3f(scale); - } - - xfOut.setRotation(accumXF); - xfOut.origin = accumPos; +void CHierarchyPoseBuilder::BuildNoScale(CPoseAsTransforms& pose) { + pose.Clear(); + const CTreeNode& node = x38_treeMap[xcec_rootId]; + zeus::CQuaternion quat; + zeus::CMatrix3f mtx; + zeus::CVector3f vec; + RecursivelyBuildNoScale(xcec_rootId, node, pose, quat, mtx, vec); } -void CHierarchyPoseBuilder::BuildNoScale(CPoseAsTransforms& pose) -{ - pose.Clear(); - const CTreeNode& node = x38_treeMap[xcec_rootId]; - zeus::CQuaternion quat; - zeus::CMatrix3f mtx; - zeus::CVector3f vec; - RecursivelyBuildNoScale(xcec_rootId, node, pose, quat, mtx, vec); +void CHierarchyPoseBuilder::Insert(const CSegId& boneId, const zeus::CQuaternion& quat) { + CTreeNode& node = x38_treeMap[boneId]; + node.x4_rotation = quat; } -void CHierarchyPoseBuilder::Insert(const CSegId& boneId, const zeus::CQuaternion& quat) -{ - CTreeNode& node = x38_treeMap[boneId]; - node.x4_rotation = quat; -} - -void CHierarchyPoseBuilder::Insert(const CSegId& boneId, const zeus::CQuaternion& quat, const zeus::CVector3f& offset) -{ - CTreeNode& node = x38_treeMap[boneId]; - node.x4_rotation = quat; - node.x14_offset = offset; +void CHierarchyPoseBuilder::Insert(const CSegId& boneId, const zeus::CQuaternion& quat, const zeus::CVector3f& offset) { + CTreeNode& node = x38_treeMap[boneId]; + node.x4_rotation = quat; + node.x14_offset = offset; } CHierarchyPoseBuilder::CHierarchyPoseBuilder(const CLayoutDescription& layout) -: x0_layoutDesc(layout), x38_treeMap(layout.GetCharLayoutInfo()->GetSegIdList().GetList().size()) -{ - TLockedToken layoutInfoTok; - if (layout.GetScaledLayoutDescription()) - layoutInfoTok = layout.GetScaledLayoutDescription()->ScaledLayout(); - else - layoutInfoTok = layout.GetCharLayoutInfo(); - const CCharLayoutInfo& layoutInfo = *layoutInfoTok.GetObj(); +: x0_layoutDesc(layout), x38_treeMap(layout.GetCharLayoutInfo()->GetSegIdList().GetList().size()) { + TLockedToken layoutInfoTok; + if (layout.GetScaledLayoutDescription()) + layoutInfoTok = layout.GetScaledLayoutDescription()->ScaledLayout(); + else + layoutInfoTok = layout.GetCharLayoutInfo(); + const CCharLayoutInfo& layoutInfo = *layoutInfoTok.GetObj(); - const CSegIdList& segIDs = layoutInfo.GetSegIdList(); - for (const CSegId& id : segIDs.GetList()) - BuildIntoHierarchy(layoutInfo, id, 2); + const CSegIdList& segIDs = layoutInfo.GetSegIdList(); + for (const CSegId& id : segIDs.GetList()) + BuildIntoHierarchy(layoutInfo, id, 2); } -} +} // namespace urde diff --git a/Runtime/Character/CHierarchyPoseBuilder.hpp b/Runtime/Character/CHierarchyPoseBuilder.hpp index 01efc1884..7a470b060 100644 --- a/Runtime/Character/CHierarchyPoseBuilder.hpp +++ b/Runtime/Character/CHierarchyPoseBuilder.hpp @@ -5,54 +5,48 @@ #include "zeus/CQuaternion.hpp" #include "CLayoutDescription.hpp" -namespace urde -{ +namespace urde { class CLayoutDescription; class CCharLayoutInfo; class CPoseAsTransforms; -class CHierarchyPoseBuilder -{ - CLayoutDescription x0_layoutDesc; - bool x34_ = 0; +class CHierarchyPoseBuilder { + CLayoutDescription x0_layoutDesc; + bool x34_ = 0; + struct CTreeNode { + CSegId x0_child = 0; + CSegId x1_sibling = 0; + zeus::CQuaternion x4_rotation; + zeus::CVector3f x14_offset; + CTreeNode() = default; + CTreeNode(const zeus::CVector3f& offset) : x14_offset(offset) {} + CTreeNode(const zeus::CQuaternion& quat) : x4_rotation(quat) {} + CTreeNode(const zeus::CQuaternion& quat, const zeus::CVector3f& offset) : x4_rotation(quat), x14_offset(offset) {} + }; + TSegIdMap x38_treeMap; - struct CTreeNode - { - CSegId x0_child = 0; - CSegId x1_sibling = 0; - zeus::CQuaternion x4_rotation; - zeus::CVector3f x14_offset; - CTreeNode() = default; - CTreeNode(const zeus::CVector3f& offset) : x14_offset(offset) {} - CTreeNode(const zeus::CQuaternion& quat) : x4_rotation(quat) {} - CTreeNode(const zeus::CQuaternion& quat, const zeus::CVector3f& offset) - : x4_rotation(quat), x14_offset(offset) {} - }; - TSegIdMap x38_treeMap; + CSegId xcec_rootId; + bool xcf0_hasRoot = false; - CSegId xcec_rootId; - bool xcf0_hasRoot = false; + void BuildIntoHierarchy(const CCharLayoutInfo& layout, const CSegId& boneId, const CSegId& nullId); + void RecursivelyBuildNoScale(const CSegId& boneId, const CTreeNode& node, CPoseAsTransforms& pose, + const zeus::CQuaternion& rot, const zeus::CMatrix3f& scale, + const zeus::CVector3f& offset) const; + void RecursivelyBuild(const CSegId& boneId, const CTreeNode& node, CPoseAsTransforms& pose, + const zeus::CQuaternion& rot, const zeus::CMatrix3f& scale, + const zeus::CVector3f& offset) const; - void BuildIntoHierarchy(const CCharLayoutInfo& layout, - const CSegId& boneId, const CSegId& nullId); - void RecursivelyBuildNoScale(const CSegId& boneId, const CTreeNode& node, - CPoseAsTransforms& pose, const zeus::CQuaternion& rot, - const zeus::CMatrix3f& scale, const zeus::CVector3f& offset) const; - void RecursivelyBuild(const CSegId& boneId, const CTreeNode& node, - CPoseAsTransforms& pose, const zeus::CQuaternion& rot, - const zeus::CMatrix3f& scale, const zeus::CVector3f& offset) const; public: - CHierarchyPoseBuilder(const CLayoutDescription& layout); + CHierarchyPoseBuilder(const CLayoutDescription& layout); - const TLockedToken CharLayoutInfo() const { return x0_layoutDesc.ScaledLayout(); } - bool HasRoot() const { return xcf0_hasRoot; } - void BuildTransform(const CSegId& boneId, zeus::CTransform& xfOut) const; - void BuildNoScale(CPoseAsTransforms& pose); - void Insert(const CSegId& boneId, const zeus::CQuaternion& quat); - void Insert(const CSegId& boneId, const zeus::CQuaternion& quat, const zeus::CVector3f& offset); - TSegIdMap& GetTreeMap() { return x38_treeMap; } + const TLockedToken CharLayoutInfo() const { return x0_layoutDesc.ScaledLayout(); } + bool HasRoot() const { return xcf0_hasRoot; } + void BuildTransform(const CSegId& boneId, zeus::CTransform& xfOut) const; + void BuildNoScale(CPoseAsTransforms& pose); + void Insert(const CSegId& boneId, const zeus::CQuaternion& quat); + void Insert(const CSegId& boneId, const zeus::CQuaternion& quat, const zeus::CVector3f& offset); + TSegIdMap& GetTreeMap() { return x38_treeMap; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CIkChain.cpp b/Runtime/Character/CIkChain.cpp index 49e77fbef..cde373bc8 100644 --- a/Runtime/Character/CIkChain.cpp +++ b/Runtime/Character/CIkChain.cpp @@ -1,58 +1,48 @@ #include "Character/CIkChain.hpp" #include "Character/CAnimData.hpp" -namespace urde -{ +namespace urde { -void CIkChain::Update(float dt) -{ - if (x44_24_activated) - x40_time = zeus::min(x40_time + dt, 1.f); - else - x40_time = zeus::max(0.f, x40_time - dt); +void CIkChain::Update(float dt) { + if (x44_24_activated) + x40_time = zeus::min(x40_time + dt, 1.f); + else + x40_time = zeus::max(0.f, x40_time - dt); } -void CIkChain::Deactivate() -{ - x44_24_activated = false; +void CIkChain::Deactivate() { x44_24_activated = false; } + +void CIkChain::Activate(const CAnimData& animData, const CSegId& segId, const zeus::CTransform& xf) { + // const CHierarchyPoseBuilder& posBuilder = animData.GetPoseBuilder(); + x0_ = segId; + + // const TLockedToken& info = posBuilder.CharLayoutInfo(); } -void CIkChain::Activate(const CAnimData& animData, const CSegId& segId, const zeus::CTransform& xf) -{ - //const CHierarchyPoseBuilder& posBuilder = animData.GetPoseBuilder(); - x0_ = segId; +void CIkChain::PreRender(CAnimData& animData, const zeus::CTransform& xf, const zeus::CVector3f& scale) {} - //const TLockedToken& info = posBuilder.CharLayoutInfo(); -} - -void CIkChain::PreRender(CAnimData& animData, const zeus::CTransform& xf, const zeus::CVector3f& scale) -{ - -} - -void CIkChain::Solve(zeus::CQuaternion& q1, zeus::CQuaternion& q2, const zeus::CVector3f& vec) -{ - const float mag = vec.magnitude(); - const float magSq = mag * mag; - const float twoMag = (2.0f * mag); - float f29 = std::acos(zeus::clamp(-1.f, (((x20_ * magSq) + x20_) - (x1c_ * x1c_)) / (twoMag * x20_), 1.f)); - float f30 = std::acos(zeus::clamp(-1.f, ((x1c_ * (magSq - (x20_ * x20_))) + x1c_) / (twoMag * x1c_), 1.f)); - - zeus::CVector3f vecA = q2.transform(x10_); - zeus::CVector3f crossVecA = x4_.cross(vecA); - float crossAMag = crossVecA.magnitude(); - crossVecA *= zeus::CVector3f(1.f / crossVecA.magnitude()); - float angle = std::asin(zeus::min(crossAMag, 1.f)); - if (x4_.dot(vecA) < 0.f) - angle = M_PIF - angle; - q2 = zeus::CQuaternion::fromAxisAngle(crossVecA, (f30 + f29) - angle) * q2; - zeus::CVector3f v1 = q1.transform((x1c_ * x4_) + (x20_ * q2.transform(x10_))); - zeus::CVector3f v2 = q1.transform(vec); - zeus::CVector3f crossVecB = v1.normalized().cross((1.f / mag) * v2); - angle = std::asin(zeus::min(crossVecB.magnitude(), 1.f)); - if (v1.dot((1.f / mag) * v2) < 0.f) - angle = M_PIF - angle; - - q1 = zeus::CQuaternion::fromAxisAngle(crossVecB * (1.f / crossVecB.magnitude()), angle) * q1; -} +void CIkChain::Solve(zeus::CQuaternion& q1, zeus::CQuaternion& q2, const zeus::CVector3f& vec) { + const float mag = vec.magnitude(); + const float magSq = mag * mag; + const float twoMag = (2.0f * mag); + float f29 = std::acos(zeus::clamp(-1.f, (((x20_ * magSq) + x20_) - (x1c_ * x1c_)) / (twoMag * x20_), 1.f)); + float f30 = std::acos(zeus::clamp(-1.f, ((x1c_ * (magSq - (x20_ * x20_))) + x1c_) / (twoMag * x1c_), 1.f)); + + zeus::CVector3f vecA = q2.transform(x10_); + zeus::CVector3f crossVecA = x4_.cross(vecA); + float crossAMag = crossVecA.magnitude(); + crossVecA *= zeus::CVector3f(1.f / crossVecA.magnitude()); + float angle = std::asin(zeus::min(crossAMag, 1.f)); + if (x4_.dot(vecA) < 0.f) + angle = M_PIF - angle; + q2 = zeus::CQuaternion::fromAxisAngle(crossVecA, (f30 + f29) - angle) * q2; + zeus::CVector3f v1 = q1.transform((x1c_ * x4_) + (x20_ * q2.transform(x10_))); + zeus::CVector3f v2 = q1.transform(vec); + zeus::CVector3f crossVecB = v1.normalized().cross((1.f / mag) * v2); + angle = std::asin(zeus::min(crossVecB.magnitude(), 1.f)); + if (v1.dot((1.f / mag) * v2) < 0.f) + angle = M_PIF - angle; + + q1 = zeus::CQuaternion::fromAxisAngle(crossVecB * (1.f / crossVecB.magnitude()), angle) * q1; } +} // namespace urde diff --git a/Runtime/Character/CIkChain.hpp b/Runtime/Character/CIkChain.hpp index 45d3be9c5..28468d09d 100644 --- a/Runtime/Character/CIkChain.hpp +++ b/Runtime/Character/CIkChain.hpp @@ -6,40 +6,36 @@ #include "zeus/CQuaternion.hpp" #include "Character/CSegId.hpp" -namespace urde -{ +namespace urde { class CAnimData; class CSegId; -class CIkChain -{ - CSegId x0_; - CSegId x1_; - CSegId x2_; - zeus::CVector3f x4_ = zeus::CVector3f::skForward; - zeus::CVector3f x10_ = zeus::CVector3f::skForward; - float x1c_ = 1.f; - float x20_ = 1.f; - zeus::CQuaternion x24_; - zeus::CVector3f x34_; - float x40_time = 0.f; +class CIkChain { + CSegId x0_; + CSegId x1_; + CSegId x2_; + zeus::CVector3f x4_ = zeus::CVector3f::skForward; + zeus::CVector3f x10_ = zeus::CVector3f::skForward; + float x1c_ = 1.f; + float x20_ = 1.f; + zeus::CQuaternion x24_; + zeus::CVector3f x34_; + float x40_time = 0.f; - union - { - struct - { - bool x44_24_activated : 1; - }; - u32 x44_dummy = 0; + union { + struct { + bool x44_24_activated : 1; }; + u32 x44_dummy = 0; + }; + public: - CIkChain() = default; + CIkChain() = default; - bool GetActive() const { return x44_24_activated; } - void Update(float); - void Deactivate(); - void Activate(const CAnimData&, const CSegId&, const zeus::CTransform&); - void PreRender(CAnimData&, const zeus::CTransform&, const zeus::CVector3f&); - void Solve(zeus::CQuaternion&, zeus::CQuaternion&, const zeus::CVector3f&); + bool GetActive() const { return x44_24_activated; } + void Update(float); + void Deactivate(); + void Activate(const CAnimData&, const CSegId&, const zeus::CTransform&); + void PreRender(CAnimData&, const zeus::CTransform&, const zeus::CVector3f&); + void Solve(zeus::CQuaternion&, zeus::CQuaternion&, const zeus::CVector3f&); }; -} - +} // namespace urde diff --git a/Runtime/Character/CInt32POINode.cpp b/Runtime/Character/CInt32POINode.cpp index c4cf52fb9..aad1b8a79 100644 --- a/Runtime/Character/CInt32POINode.cpp +++ b/Runtime/Character/CInt32POINode.cpp @@ -1,8 +1,7 @@ #include "CInt32POINode.hpp" #include "CAnimSourceReader.hpp" -namespace urde -{ +namespace urde { CInt32POINode::CInt32POINode() : CPOINode("root", EPOIType::EmptyInt32, CCharAnimTime(), -1, false, 1.f, -1, 0), x38_val(0), x3c_locatorName("root") {} @@ -10,12 +9,10 @@ CInt32POINode::CInt32POINode() CInt32POINode::CInt32POINode(CInputStream& in) : CPOINode(in), x38_val(in.readUint32Big()), x3c_locatorName(in.readString()) {} -CInt32POINode CInt32POINode::CopyNodeMinusStartTime(const CInt32POINode& node, - const CCharAnimTime& startTime) -{ - CInt32POINode ret = node; - ret.x1c_time -= startTime; - return ret; +CInt32POINode CInt32POINode::CopyNodeMinusStartTime(const CInt32POINode& node, const CCharAnimTime& startTime) { + CInt32POINode ret = node; + ret.x1c_time -= startTime; + return ret; } -} +} // namespace urde diff --git a/Runtime/Character/CInt32POINode.hpp b/Runtime/Character/CInt32POINode.hpp index a421dc9b4..209dcd73a 100644 --- a/Runtime/Character/CInt32POINode.hpp +++ b/Runtime/Character/CInt32POINode.hpp @@ -2,23 +2,20 @@ #include "CPOINode.hpp" -namespace urde -{ +namespace urde { class IAnimSourceInfo; -class CInt32POINode : public CPOINode -{ - s32 x38_val; - std::string x3c_locatorName; -public: - CInt32POINode(); - CInt32POINode(CInputStream& in); - s32 GetValue() const {return x38_val;} - std::string_view GetLocatorName() const {return x3c_locatorName;} +class CInt32POINode : public CPOINode { + s32 x38_val; + std::string x3c_locatorName; - static CInt32POINode CopyNodeMinusStartTime(const CInt32POINode& node, - const CCharAnimTime& startTime); +public: + CInt32POINode(); + CInt32POINode(CInputStream& in); + s32 GetValue() const { return x38_val; } + std::string_view GetLocatorName() const { return x3c_locatorName; } + + static CInt32POINode CopyNodeMinusStartTime(const CInt32POINode& node, const CCharAnimTime& startTime); }; -} - +} // namespace urde diff --git a/Runtime/Character/CLayoutDescription.hpp b/Runtime/Character/CLayoutDescription.hpp index 3b668513b..75174dbe7 100644 --- a/Runtime/Character/CLayoutDescription.hpp +++ b/Runtime/Character/CLayoutDescription.hpp @@ -4,42 +4,38 @@ #include "CToken.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { class CCharLayoutInfo; -class CLayoutDescription -{ +class CLayoutDescription { public: - class CScaledLayoutDescription - { - TLockedToken x0_layoutToken; - float xc_scale; - std::experimental::optional x10_scaleVec; - public: - const TLockedToken& ScaledLayout() const {return x0_layoutToken;} - float GlobalScale() const {return xc_scale;} - const std::experimental::optional& GetScaleVec() const {return x10_scaleVec;} - }; -private: + class CScaledLayoutDescription { TLockedToken x0_layoutToken; - std::experimental::optional xc_scaled; + float xc_scale; + std::experimental::optional x10_scaleVec; + + public: + const TLockedToken& ScaledLayout() const { return x0_layoutToken; } + float GlobalScale() const { return xc_scale; } + const std::experimental::optional& GetScaleVec() const { return x10_scaleVec; } + }; + +private: + TLockedToken x0_layoutToken; + std::experimental::optional xc_scaled; + public: - CLayoutDescription(const TLockedToken& token) - : x0_layoutToken(token) {} + CLayoutDescription(const TLockedToken& token) : x0_layoutToken(token) {} - const std::experimental::optional& - GetScaledLayoutDescription() const {return xc_scaled;} + const std::experimental::optional& GetScaledLayoutDescription() const { return xc_scaled; } - const TLockedToken& GetCharLayoutInfo() const {return x0_layoutToken;} - bool UsesScale() const { return bool(xc_scaled); } - const TLockedToken& ScaledLayout() const - { - if (UsesScale()) - return xc_scaled->ScaledLayout(); - return x0_layoutToken; - } + const TLockedToken& GetCharLayoutInfo() const { return x0_layoutToken; } + bool UsesScale() const { return bool(xc_scaled); } + const TLockedToken& ScaledLayout() const { + if (UsesScale()) + return xc_scaled->ScaledLayout(); + return x0_layoutToken; + } }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaAnimBlend.cpp b/Runtime/Character/CMetaAnimBlend.cpp index 9f3cfd731..149900e17 100644 --- a/Runtime/Character/CMetaAnimBlend.cpp +++ b/Runtime/Character/CMetaAnimBlend.cpp @@ -1,29 +1,24 @@ #include "CMetaAnimBlend.hpp" #include "CMetaAnimFactory.hpp" -namespace urde -{ +namespace urde { -CMetaAnimBlend::CMetaAnimBlend(CInputStream& in) -{ - x4_animA = CMetaAnimFactory::CreateMetaAnim(in); - x8_animB = CMetaAnimFactory::CreateMetaAnim(in); - xc_blend = in.readFloatBig(); - x10_ = in.readBool(); +CMetaAnimBlend::CMetaAnimBlend(CInputStream& in) { + x4_animA = CMetaAnimFactory::CreateMetaAnim(in); + x8_animB = CMetaAnimFactory::CreateMetaAnim(in); + xc_blend = in.readFloatBig(); + x10_ = in.readBool(); } -void CMetaAnimBlend::GetUniquePrimitives(std::set& primsOut) const -{ - x4_animA->GetUniquePrimitives(primsOut); - x4_animA->GetUniquePrimitives(primsOut); +void CMetaAnimBlend::GetUniquePrimitives(std::set& primsOut) const { + x4_animA->GetUniquePrimitives(primsOut); + x4_animA->GetUniquePrimitives(primsOut); } -std::shared_ptr -CMetaAnimBlend::VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const -{ - //CMetaAnimTreeBuildOrders buildOrders = CMetaAnimTreeBuildOrders::NoSpecialOrders(); - return {}; +std::shared_ptr CMetaAnimBlend::VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const { + // CMetaAnimTreeBuildOrders buildOrders = CMetaAnimTreeBuildOrders::NoSpecialOrders(); + return {}; } -} +} // namespace urde diff --git a/Runtime/Character/CMetaAnimBlend.hpp b/Runtime/Character/CMetaAnimBlend.hpp index 83bdba90e..291b84abf 100644 --- a/Runtime/Character/CMetaAnimBlend.hpp +++ b/Runtime/Character/CMetaAnimBlend.hpp @@ -3,23 +3,21 @@ #include "IMetaAnim.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { + +class CMetaAnimBlend : public IMetaAnim { + std::shared_ptr x4_animA; + std::shared_ptr x8_animB; + float xc_blend; + bool x10_; -class CMetaAnimBlend : public IMetaAnim -{ - std::shared_ptr x4_animA; - std::shared_ptr x8_animB; - float xc_blend; - bool x10_; public: - CMetaAnimBlend(CInputStream& in); - EMetaAnimType GetType() const {return EMetaAnimType::Blend;} + CMetaAnimBlend(CInputStream& in); + EMetaAnimType GetType() const { return EMetaAnimType::Blend; } - void GetUniquePrimitives(std::set& primsOut) const; - std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const; + void GetUniquePrimitives(std::set& primsOut) const; + std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaAnimFactory.cpp b/Runtime/Character/CMetaAnimFactory.cpp index 403be16d0..56eddc9d0 100644 --- a/Runtime/Character/CMetaAnimFactory.cpp +++ b/Runtime/Character/CMetaAnimFactory.cpp @@ -5,29 +5,27 @@ #include "CMetaAnimRandom.hpp" #include "CMetaAnimSequence.hpp" -namespace urde -{ +namespace urde { -std::shared_ptr CMetaAnimFactory::CreateMetaAnim(CInputStream& in) -{ - EMetaAnimType type = EMetaAnimType(in.readUint32Big()); +std::shared_ptr CMetaAnimFactory::CreateMetaAnim(CInputStream& in) { + EMetaAnimType type = EMetaAnimType(in.readUint32Big()); - switch (type) - { - case EMetaAnimType::Play: - return std::make_shared(in); - case EMetaAnimType::Blend: - return std::make_shared(in); - case EMetaAnimType::PhaseBlend: - return std::make_shared(in); - case EMetaAnimType::Random: - return std::make_shared(in); - case EMetaAnimType::Sequence: - return std::make_shared(in); - default: break; - } + switch (type) { + case EMetaAnimType::Play: + return std::make_shared(in); + case EMetaAnimType::Blend: + return std::make_shared(in); + case EMetaAnimType::PhaseBlend: + return std::make_shared(in); + case EMetaAnimType::Random: + return std::make_shared(in); + case EMetaAnimType::Sequence: + return std::make_shared(in); + default: + break; + } - return {}; + return {}; } -} +} // namespace urde diff --git a/Runtime/Character/CMetaAnimFactory.hpp b/Runtime/Character/CMetaAnimFactory.hpp index 4307d7a77..076d8a888 100644 --- a/Runtime/Character/CMetaAnimFactory.hpp +++ b/Runtime/Character/CMetaAnimFactory.hpp @@ -3,14 +3,11 @@ #include "IOStreams.hpp" #include "IMetaAnim.hpp" -namespace urde -{ +namespace urde { -class CMetaAnimFactory -{ +class CMetaAnimFactory { public: - static std::shared_ptr CreateMetaAnim(CInputStream& in); + static std::shared_ptr CreateMetaAnim(CInputStream& in); }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaAnimPhaseBlend.cpp b/Runtime/Character/CMetaAnimPhaseBlend.cpp index 6316ec8b3..b74ec7ed9 100644 --- a/Runtime/Character/CMetaAnimPhaseBlend.cpp +++ b/Runtime/Character/CMetaAnimPhaseBlend.cpp @@ -1,28 +1,23 @@ #include "CMetaAnimPhaseBlend.hpp" #include "CMetaAnimFactory.hpp" -namespace urde -{ +namespace urde { -CMetaAnimPhaseBlend::CMetaAnimPhaseBlend(CInputStream& in) -{ - x4_animA = CMetaAnimFactory::CreateMetaAnim(in); - x8_animB = CMetaAnimFactory::CreateMetaAnim(in); - xc_blend = in.readFloatBig(); - x10_ = in.readBool(); +CMetaAnimPhaseBlend::CMetaAnimPhaseBlend(CInputStream& in) { + x4_animA = CMetaAnimFactory::CreateMetaAnim(in); + x8_animB = CMetaAnimFactory::CreateMetaAnim(in); + xc_blend = in.readFloatBig(); + x10_ = in.readBool(); } -void CMetaAnimPhaseBlend::GetUniquePrimitives(std::set& primsOut) const -{ - x4_animA->GetUniquePrimitives(primsOut); - x8_animB->GetUniquePrimitives(primsOut); +void CMetaAnimPhaseBlend::GetUniquePrimitives(std::set& primsOut) const { + x4_animA->GetUniquePrimitives(primsOut); + x8_animB->GetUniquePrimitives(primsOut); } -std::shared_ptr -CMetaAnimPhaseBlend::VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const -{ - return {}; +std::shared_ptr CMetaAnimPhaseBlend::VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const { + return {}; } -} +} // namespace urde diff --git a/Runtime/Character/CMetaAnimPhaseBlend.hpp b/Runtime/Character/CMetaAnimPhaseBlend.hpp index 9ad7a899b..13781c05c 100644 --- a/Runtime/Character/CMetaAnimPhaseBlend.hpp +++ b/Runtime/Character/CMetaAnimPhaseBlend.hpp @@ -3,23 +3,21 @@ #include "IMetaAnim.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { + +class CMetaAnimPhaseBlend : public IMetaAnim { + std::shared_ptr x4_animA; + std::shared_ptr x8_animB; + float xc_blend; + bool x10_; -class CMetaAnimPhaseBlend : public IMetaAnim -{ - std::shared_ptr x4_animA; - std::shared_ptr x8_animB; - float xc_blend; - bool x10_; public: - CMetaAnimPhaseBlend(CInputStream& in); - EMetaAnimType GetType() const {return EMetaAnimType::PhaseBlend;} + CMetaAnimPhaseBlend(CInputStream& in); + EMetaAnimType GetType() const { return EMetaAnimType::PhaseBlend; } - void GetUniquePrimitives(std::set& primsOut) const; - std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const; + void GetUniquePrimitives(std::set& primsOut) const; + std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaAnimPlay.cpp b/Runtime/Character/CMetaAnimPlay.cpp index 916942830..72a0c5d07 100644 --- a/Runtime/Character/CMetaAnimPlay.cpp +++ b/Runtime/Character/CMetaAnimPlay.cpp @@ -4,35 +4,25 @@ #include "CAllFormatsAnimSource.hpp" #include "CAnimTreeAnimReaderContainer.hpp" -namespace urde -{ +namespace urde { -CMetaAnimPlay::CMetaAnimPlay(CInputStream& in) -: x4_primitive(in), x1c_startTime(in) {} +CMetaAnimPlay::CMetaAnimPlay(CInputStream& in) : x4_primitive(in), x1c_startTime(in) {} -void CMetaAnimPlay::GetUniquePrimitives(std::set& primsOut) const -{ - primsOut.insert(x4_primitive); +void CMetaAnimPlay::GetUniquePrimitives(std::set& primsOut) const { primsOut.insert(x4_primitive); } + +std::shared_ptr CMetaAnimPlay::VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const { + if (orders.x0_recursiveAdvance) { + CMetaAnimTreeBuildOrders modOrders; + modOrders.PreAdvanceForAll(*orders.x0_recursiveAdvance); + return GetAnimationTree(animSys, modOrders); + } + + TLockedToken prim = + animSys.xc_store.GetObj(SObjectTag{FOURCC('ANIM'), x4_primitive.GetAnimResId()}); + std::shared_ptr ret = std::make_shared( + x4_primitive.GetName(), CAllFormatsAnimSource::GetNewReader(prim, x1c_startTime), x4_primitive.GetAnimDbIdx()); + return ret; } -std::shared_ptr -CMetaAnimPlay::VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const -{ - if (orders.x0_recursiveAdvance) - { - CMetaAnimTreeBuildOrders modOrders; - modOrders.PreAdvanceForAll(*orders.x0_recursiveAdvance); - return GetAnimationTree(animSys, modOrders); - } - - TLockedToken prim = - animSys.xc_store.GetObj(SObjectTag{FOURCC('ANIM'), x4_primitive.GetAnimResId()}); - std::shared_ptr ret = - std::make_shared(x4_primitive.GetName(), - CAllFormatsAnimSource::GetNewReader(prim, x1c_startTime), - x4_primitive.GetAnimDbIdx()); - return ret; -} - -} +} // namespace urde diff --git a/Runtime/Character/CMetaAnimPlay.hpp b/Runtime/Character/CMetaAnimPlay.hpp index 61bc1c262..d3b217cd2 100644 --- a/Runtime/Character/CMetaAnimPlay.hpp +++ b/Runtime/Character/CMetaAnimPlay.hpp @@ -4,21 +4,19 @@ #include "CPrimitive.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { + +class CMetaAnimPlay : public IMetaAnim { + CPrimitive x4_primitive; + CCharAnimTime x1c_startTime; -class CMetaAnimPlay : public IMetaAnim -{ - CPrimitive x4_primitive; - CCharAnimTime x1c_startTime; public: - CMetaAnimPlay(CInputStream& in); - EMetaAnimType GetType() const {return EMetaAnimType::Play;} + CMetaAnimPlay(CInputStream& in); + EMetaAnimType GetType() const { return EMetaAnimType::Play; } - void GetUniquePrimitives(std::set& primsOut) const; - std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const; + void GetUniquePrimitives(std::set& primsOut) const; + std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaAnimRandom.cpp b/Runtime/Character/CMetaAnimRandom.cpp index c27dd9da4..9b0cfa3c1 100644 --- a/Runtime/Character/CMetaAnimRandom.cpp +++ b/Runtime/Character/CMetaAnimRandom.cpp @@ -2,47 +2,39 @@ #include "CMetaAnimFactory.hpp" #include "CAnimSysContext.hpp" -namespace urde -{ +namespace urde { -CMetaAnimRandom::RandomData CMetaAnimRandom::CreateRandomData(CInputStream& in) -{ - CMetaAnimRandom::RandomData ret; - u32 randCount = in.readUint32Big(); - ret.reserve(randCount); +CMetaAnimRandom::RandomData CMetaAnimRandom::CreateRandomData(CInputStream& in) { + CMetaAnimRandom::RandomData ret; + u32 randCount = in.readUint32Big(); + ret.reserve(randCount); - for (u32 i=0 ; i metaAnim = CMetaAnimFactory::CreateMetaAnim(in); - ret.emplace_back(std::move(metaAnim), in.readUint32Big()); - } + for (u32 i = 0; i < randCount; ++i) { + std::shared_ptr metaAnim = CMetaAnimFactory::CreateMetaAnim(in); + ret.emplace_back(std::move(metaAnim), in.readUint32Big()); + } - return ret; + return ret; } -CMetaAnimRandom::CMetaAnimRandom(CInputStream& in) -: x4_randomData(CreateRandomData(in)) {} +CMetaAnimRandom::CMetaAnimRandom(CInputStream& in) : x4_randomData(CreateRandomData(in)) {} -void CMetaAnimRandom::GetUniquePrimitives(std::set& primsOut) const -{ - for (const auto& pair : x4_randomData) - pair.first->GetUniquePrimitives(primsOut); +void CMetaAnimRandom::GetUniquePrimitives(std::set& primsOut) const { + for (const auto& pair : x4_randomData) + pair.first->GetUniquePrimitives(primsOut); } -std::shared_ptr -CMetaAnimRandom::VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const -{ - s32 r = animSys.x8_random->Range(1, 100); - const std::pair, u32>* useRd = nullptr; - for (auto& rd : x4_randomData) - { - useRd = &rd; - if (r <= rd.second) - break; - } +std::shared_ptr CMetaAnimRandom::VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const { + s32 r = animSys.x8_random->Range(1, 100); + const std::pair, u32>* useRd = nullptr; + for (auto& rd : x4_randomData) { + useRd = &rd; + if (r <= rd.second) + break; + } - return useRd->first->GetAnimationTree(animSys, orders); + return useRd->first->GetAnimationTree(animSys, orders); } -} +} // namespace urde diff --git a/Runtime/Character/CMetaAnimRandom.hpp b/Runtime/Character/CMetaAnimRandom.hpp index d0475ee54..fb42d7ca4 100644 --- a/Runtime/Character/CMetaAnimRandom.hpp +++ b/Runtime/Character/CMetaAnimRandom.hpp @@ -3,22 +3,20 @@ #include "IMetaAnim.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { + +class CMetaAnimRandom : public IMetaAnim { + using RandomData = std::vector, u32>>; + RandomData x4_randomData; + static RandomData CreateRandomData(CInputStream& in); -class CMetaAnimRandom : public IMetaAnim -{ - using RandomData = std::vector, u32>>; - RandomData x4_randomData; - static RandomData CreateRandomData(CInputStream& in); public: - CMetaAnimRandom(CInputStream& in); - EMetaAnimType GetType() const {return EMetaAnimType::Random;} + CMetaAnimRandom(CInputStream& in); + EMetaAnimType GetType() const { return EMetaAnimType::Random; } - void GetUniquePrimitives(std::set& primsOut) const; - std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const; + void GetUniquePrimitives(std::set& primsOut) const; + std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaAnimSequence.cpp b/Runtime/Character/CMetaAnimSequence.cpp index ba5233d76..8cee94cbb 100644 --- a/Runtime/Character/CMetaAnimSequence.cpp +++ b/Runtime/Character/CMetaAnimSequence.cpp @@ -2,40 +2,33 @@ #include "CMetaAnimFactory.hpp" #include "CAnimTreeSequence.hpp" -namespace urde -{ +namespace urde { -std::vector> CMetaAnimSequence::CreateSequence(CInputStream& in) -{ - std::vector> ret; - u32 seqCount = in.readUint32Big(); - ret.reserve(seqCount); +std::vector> CMetaAnimSequence::CreateSequence(CInputStream& in) { + std::vector> ret; + u32 seqCount = in.readUint32Big(); + ret.reserve(seqCount); - for (u32 i=0 ; i& primsOut) const -{ - for (const std::shared_ptr& anim : x4_sequence) - anim->GetUniquePrimitives(primsOut); +void CMetaAnimSequence::GetUniquePrimitives(std::set& primsOut) const { + for (const std::shared_ptr& anim : x4_sequence) + anim->GetUniquePrimitives(primsOut); } -std::shared_ptr -CMetaAnimSequence::VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const -{ - if (orders.x0_recursiveAdvance) - { - CMetaAnimTreeBuildOrders modOrders; - modOrders.PreAdvanceForAll(*orders.x0_recursiveAdvance); - return GetAnimationTree(animSys, modOrders); - } +std::shared_ptr CMetaAnimSequence::VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const { + if (orders.x0_recursiveAdvance) { + CMetaAnimTreeBuildOrders modOrders; + modOrders.PreAdvanceForAll(*orders.x0_recursiveAdvance); + return GetAnimationTree(animSys, modOrders); + } #if 0 std::vector anims; @@ -47,10 +40,9 @@ CMetaAnimSequence::VGetAnimationTree(const CAnimSysContext& animSys, } #endif - std::shared_ptr ret = - std::make_shared(x4_sequence, animSys, ""); + std::shared_ptr ret = std::make_shared(x4_sequence, animSys, ""); - return ret; + return ret; } -} +} // namespace urde diff --git a/Runtime/Character/CMetaAnimSequence.hpp b/Runtime/Character/CMetaAnimSequence.hpp index b185506bf..9d991be0b 100644 --- a/Runtime/Character/CMetaAnimSequence.hpp +++ b/Runtime/Character/CMetaAnimSequence.hpp @@ -3,21 +3,19 @@ #include "IMetaAnim.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { + +class CMetaAnimSequence : public IMetaAnim { + std::vector> x4_sequence; + std::vector> CreateSequence(CInputStream& in); -class CMetaAnimSequence : public IMetaAnim -{ - std::vector> x4_sequence; - std::vector> CreateSequence(CInputStream& in); public: - CMetaAnimSequence(CInputStream& in); - EMetaAnimType GetType() const {return EMetaAnimType::Sequence;} + CMetaAnimSequence(CInputStream& in); + EMetaAnimType GetType() const { return EMetaAnimType::Sequence; } - void GetUniquePrimitives(std::set& primsOut) const; - std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const; + void GetUniquePrimitives(std::set& primsOut) const; + std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaTransFactory.cpp b/Runtime/Character/CMetaTransFactory.cpp index 2682382c3..74905ad48 100644 --- a/Runtime/Character/CMetaTransFactory.cpp +++ b/Runtime/Character/CMetaTransFactory.cpp @@ -4,27 +4,24 @@ #include "CMetaTransPhaseTrans.hpp" #include "CMetaTransSnap.hpp" -namespace urde -{ +namespace urde { -std::shared_ptr CMetaTransFactory::CreateMetaTrans(CInputStream& in) -{ - EMetaTransType type = EMetaTransType(in.readUint32Big()); +std::shared_ptr CMetaTransFactory::CreateMetaTrans(CInputStream& in) { + EMetaTransType type = EMetaTransType(in.readUint32Big()); - switch (type) - { - case EMetaTransType::MetaAnim: - return std::make_shared(in); - case EMetaTransType::Trans: - return std::make_shared(in); - case EMetaTransType::PhaseTrans: - return std::make_shared(in); - case EMetaTransType::Snap: - return std::make_shared(); - default: - break; - } + switch (type) { + case EMetaTransType::MetaAnim: + return std::make_shared(in); + case EMetaTransType::Trans: + return std::make_shared(in); + case EMetaTransType::PhaseTrans: + return std::make_shared(in); + case EMetaTransType::Snap: + return std::make_shared(); + default: + break; + } - return {}; -} + return {}; } +} // namespace urde diff --git a/Runtime/Character/CMetaTransFactory.hpp b/Runtime/Character/CMetaTransFactory.hpp index c0af3a8ba..da5e81784 100644 --- a/Runtime/Character/CMetaTransFactory.hpp +++ b/Runtime/Character/CMetaTransFactory.hpp @@ -3,14 +3,11 @@ #include "IOStreams.hpp" #include "IMetaTrans.hpp" -namespace urde -{ +namespace urde { -class CMetaTransFactory -{ +class CMetaTransFactory { public: - static std::shared_ptr CreateMetaTrans(CInputStream& in); + static std::shared_ptr CreateMetaTrans(CInputStream& in); }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaTransMetaAnim.cpp b/Runtime/Character/CMetaTransMetaAnim.cpp index de2e4c610..b5309c5c1 100644 --- a/Runtime/Character/CMetaTransMetaAnim.cpp +++ b/Runtime/Character/CMetaTransMetaAnim.cpp @@ -2,21 +2,17 @@ #include "CMetaAnimFactory.hpp" #include "CAnimTreeLoopIn.hpp" -namespace urde -{ +namespace urde { -CMetaTransMetaAnim::CMetaTransMetaAnim(CInputStream& in) -: x4_metaAnim(CMetaAnimFactory::CreateMetaAnim(in)) {} +CMetaTransMetaAnim::CMetaTransMetaAnim(CInputStream& in) : x4_metaAnim(CMetaAnimFactory::CreateMetaAnim(in)) {} -std::shared_ptr -CMetaTransMetaAnim::VGetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animSys) const -{ - std::shared_ptr animNode = - x4_metaAnim->GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()); - return std::make_shared(a, b, animNode, animSys, - CAnimTreeLoopIn::CreatePrimitiveName(a, b, animNode)); +std::shared_ptr CMetaTransMetaAnim::VGetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animSys) const { + std::shared_ptr animNode = + x4_metaAnim->GetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()); + return std::make_shared(a, b, animNode, animSys, + CAnimTreeLoopIn::CreatePrimitiveName(a, b, animNode)); } -} +} // namespace urde diff --git a/Runtime/Character/CMetaTransMetaAnim.hpp b/Runtime/Character/CMetaTransMetaAnim.hpp index 9ddf4124a..a08645fee 100644 --- a/Runtime/Character/CMetaTransMetaAnim.hpp +++ b/Runtime/Character/CMetaTransMetaAnim.hpp @@ -4,20 +4,18 @@ #include "IMetaAnim.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { + +class CMetaTransMetaAnim : public IMetaTrans { + std::shared_ptr x4_metaAnim; -class CMetaTransMetaAnim : public IMetaTrans -{ - std::shared_ptr x4_metaAnim; public: - CMetaTransMetaAnim(CInputStream& in); - EMetaTransType GetType() const {return EMetaTransType::MetaAnim;} + CMetaTransMetaAnim(CInputStream& in); + EMetaTransType GetType() const { return EMetaTransType::MetaAnim; } - std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animSys) const; + std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animSys) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaTransPhaseTrans.cpp b/Runtime/Character/CMetaTransPhaseTrans.cpp index a76402541..bc4b9ad9c 100644 --- a/Runtime/Character/CMetaTransPhaseTrans.cpp +++ b/Runtime/Character/CMetaTransPhaseTrans.cpp @@ -4,39 +4,36 @@ #include "CAnimTreeTransition.hpp" #include "CAnimTreeTimeScale.hpp" -namespace urde -{ +namespace urde { -CMetaTransPhaseTrans::CMetaTransPhaseTrans(CInputStream& in) -{ - x4_transDur = CCharAnimTime(in); - xc_ = in.readBool(); - xd_runA = in.readBool(); - x10_flags = in.readUint32Big(); +CMetaTransPhaseTrans::CMetaTransPhaseTrans(CInputStream& in) { + x4_transDur = CCharAnimTime(in); + xc_ = in.readBool(); + xd_runA = in.readBool(); + x10_flags = in.readUint32Big(); } -std::shared_ptr -CMetaTransPhaseTrans::VGetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animSys) const -{ - std::shared_ptr nA = a.lock(); - CAnimTreeEffectiveContribution cA = nA->GetContributionOfHighestInfluence(); - std::shared_ptr nB = b.lock(); - CAnimTreeEffectiveContribution cB = nB->GetContributionOfHighestInfluence(); - float y2A = cA.GetSteadyStateAnimInfo().GetDuration() / cB.GetSteadyStateAnimInfo().GetDuration(); - float y1B = cB.GetSteadyStateAnimInfo().GetDuration() / cA.GetSteadyStateAnimInfo().GetDuration(); +std::shared_ptr CMetaTransPhaseTrans::VGetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animSys) const { + std::shared_ptr nA = a.lock(); + CAnimTreeEffectiveContribution cA = nA->GetContributionOfHighestInfluence(); + std::shared_ptr nB = b.lock(); + CAnimTreeEffectiveContribution cB = nB->GetContributionOfHighestInfluence(); + float y2A = cA.GetSteadyStateAnimInfo().GetDuration() / cB.GetSteadyStateAnimInfo().GetDuration(); + float y1B = cB.GetSteadyStateAnimInfo().GetDuration() / cA.GetSteadyStateAnimInfo().GetDuration(); - nB->VSetPhase(zeus::clamp(0.f, 1.f - cA.GetTimeRemaining() / cA.GetSteadyStateAnimInfo().GetDuration(), 1.f)); - auto tsA = std::make_shared(a, - std::make_unique(CCharAnimTime{}, 1.f, x4_transDur, y2A), - x4_transDur, CAnimTreeTimeScale::CreatePrimitiveName(a, 1.f, x4_transDur, y2A)); - auto tsB = std::make_shared(b, - std::make_unique(CCharAnimTime{}, y1B, x4_transDur, 1.f), - x4_transDur, CAnimTreeTimeScale::CreatePrimitiveName(b, y1B, x4_transDur, 1.f)); + nB->VSetPhase(zeus::clamp(0.f, 1.f - cA.GetTimeRemaining() / cA.GetSteadyStateAnimInfo().GetDuration(), 1.f)); + auto tsA = std::make_shared( + a, std::make_unique(CCharAnimTime{}, 1.f, x4_transDur, y2A), x4_transDur, + CAnimTreeTimeScale::CreatePrimitiveName(a, 1.f, x4_transDur, y2A)); + auto tsB = std::make_shared( + b, std::make_unique(CCharAnimTime{}, y1B, x4_transDur, 1.f), x4_transDur, + CAnimTreeTimeScale::CreatePrimitiveName(b, y1B, x4_transDur, 1.f)); - return std::make_shared(xc_, tsA, tsB, x4_transDur, xd_runA, x10_flags, - CAnimTreeTransition::CreatePrimitiveName(tsA, tsB, x4_transDur.GetSeconds())); + return std::make_shared( + xc_, tsA, tsB, x4_transDur, xd_runA, x10_flags, + CAnimTreeTransition::CreatePrimitiveName(tsA, tsB, x4_transDur.GetSeconds())); } -} +} // namespace urde diff --git a/Runtime/Character/CMetaTransPhaseTrans.hpp b/Runtime/Character/CMetaTransPhaseTrans.hpp index dca5b5132..e777811e6 100644 --- a/Runtime/Character/CMetaTransPhaseTrans.hpp +++ b/Runtime/Character/CMetaTransPhaseTrans.hpp @@ -4,23 +4,21 @@ #include "IOStreams.hpp" #include "CCharAnimTime.hpp" -namespace urde -{ +namespace urde { + +class CMetaTransPhaseTrans : public IMetaTrans { + CCharAnimTime x4_transDur; + bool xc_; + bool xd_runA; + u32 x10_flags; -class CMetaTransPhaseTrans : public IMetaTrans -{ - CCharAnimTime x4_transDur; - bool xc_; - bool xd_runA; - u32 x10_flags; public: - CMetaTransPhaseTrans(CInputStream& in); - EMetaTransType GetType() const {return EMetaTransType::PhaseTrans;} + CMetaTransPhaseTrans(CInputStream& in); + EMetaTransType GetType() const { return EMetaTransType::PhaseTrans; } - std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animSys) const; + std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animSys) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaTransSnap.cpp b/Runtime/Character/CMetaTransSnap.cpp index 5da19c7fa..e28512ed1 100644 --- a/Runtime/Character/CMetaTransSnap.cpp +++ b/Runtime/Character/CMetaTransSnap.cpp @@ -1,14 +1,11 @@ #include "CMetaTransSnap.hpp" -namespace urde -{ +namespace urde { -std::shared_ptr -CMetaTransSnap::VGetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animSys) const -{ - return b.lock(); +std::shared_ptr CMetaTransSnap::VGetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animSys) const { + return b.lock(); } -} +} // namespace urde diff --git a/Runtime/Character/CMetaTransSnap.hpp b/Runtime/Character/CMetaTransSnap.hpp index 80fdc54bb..b886153c6 100644 --- a/Runtime/Character/CMetaTransSnap.hpp +++ b/Runtime/Character/CMetaTransSnap.hpp @@ -3,18 +3,15 @@ #include "IMetaTrans.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { -class CMetaTransSnap : public IMetaTrans -{ +class CMetaTransSnap : public IMetaTrans { public: - EMetaTransType GetType() const {return EMetaTransType::Snap;} + EMetaTransType GetType() const { return EMetaTransType::Snap; } - std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animSys) const; + std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animSys) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CMetaTransTrans.cpp b/Runtime/Character/CMetaTransTrans.cpp index 7da9aeb7b..f356ccd20 100644 --- a/Runtime/Character/CMetaTransTrans.cpp +++ b/Runtime/Character/CMetaTransTrans.cpp @@ -1,22 +1,20 @@ #include "CMetaTransTrans.hpp" #include "CAnimTreeTransition.hpp" -namespace urde -{ +namespace urde { -CMetaTransTrans::CMetaTransTrans(CInputStream& in) -{ - x4_transDur = CCharAnimTime(in); - xc_ = in.readBool(); - xd_runA = in.readBool(); - x10_flags = in.readUint32Big(); +CMetaTransTrans::CMetaTransTrans(CInputStream& in) { + x4_transDur = CCharAnimTime(in); + xc_ = in.readBool(); + xd_runA = in.readBool(); + x10_flags = in.readUint32Big(); } std::shared_ptr CMetaTransTrans::VGetTransitionTree(const std::weak_ptr& a, const std::weak_ptr& b, - const CAnimSysContext& animSys) const -{ - return std::make_shared(xc_, a, b, x4_transDur, xd_runA, x10_flags, - CAnimTreeTransition::CreatePrimitiveName(a, b, x4_transDur.GetSeconds())); -} + const CAnimSysContext& animSys) const { + return std::make_shared( + xc_, a, b, x4_transDur, xd_runA, x10_flags, + CAnimTreeTransition::CreatePrimitiveName(a, b, x4_transDur.GetSeconds())); } +} // namespace urde diff --git a/Runtime/Character/CMetaTransTrans.hpp b/Runtime/Character/CMetaTransTrans.hpp index 412a4d2c1..2b7ab380e 100644 --- a/Runtime/Character/CMetaTransTrans.hpp +++ b/Runtime/Character/CMetaTransTrans.hpp @@ -4,23 +4,21 @@ #include "IOStreams.hpp" #include "CCharAnimTime.hpp" -namespace urde -{ +namespace urde { + +class CMetaTransTrans : public IMetaTrans { + CCharAnimTime x4_transDur; + bool xc_; + bool xd_runA; + u32 x10_flags; -class CMetaTransTrans : public IMetaTrans -{ - CCharAnimTime x4_transDur; - bool xc_; - bool xd_runA; - u32 x10_flags; public: - CMetaTransTrans(CInputStream& in); - EMetaTransType GetType() const {return EMetaTransType::Trans;} + CMetaTransTrans(CInputStream& in); + EMetaTransType GetType() const { return EMetaTransType::Trans; } - std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animSys) const; + std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animSys) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CModelData.cpp b/Runtime/Character/CModelData.cpp index f9d2c2b47..563a8a04c 100644 --- a/Runtime/Character/CModelData.cpp +++ b/Runtime/Character/CModelData.cpp @@ -13,505 +13,420 @@ #include "CCharacterFactory.hpp" #include "CAdditiveAnimPlayback.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CModelData"); CModelData::~CModelData() {} CModelData::CModelData() {} -CModelData CModelData::CModelDataNull() {return CModelData();} +CModelData CModelData::CModelDataNull() { return CModelData(); } -CModelData::CModelData(const CStaticRes& res, int instCount) -: x0_scale(res.GetScale()), m_drawInstCount(instCount) -{ - x1c_normalModel = g_SimplePool->GetObj({SBIG('CMDL'), res.GetId()}); - if (!x1c_normalModel) - Log.report(logvisor::Fatal, "unable to find CMDL %08X", res.GetId()); - m_normalModelInst = x1c_normalModel->MakeNewInstance(0, instCount); +CModelData::CModelData(const CStaticRes& res, int instCount) : x0_scale(res.GetScale()), m_drawInstCount(instCount) { + x1c_normalModel = g_SimplePool->GetObj({SBIG('CMDL'), res.GetId()}); + if (!x1c_normalModel) + Log.report(logvisor::Fatal, "unable to find CMDL %08X", res.GetId()); + m_normalModelInst = x1c_normalModel->MakeNewInstance(0, instCount); } -CModelData::CModelData(const CAnimRes& res, int instCount) -: x0_scale(res.GetScale()), m_drawInstCount(instCount) -{ - TToken factory = g_CharFactoryBuilder->GetFactory(res); - x10_animData = factory->CreateCharacter(res.GetCharacterNodeId(), res.CanLoop(), factory, - res.GetDefaultAnim(), instCount); +CModelData::CModelData(const CAnimRes& res, int instCount) : x0_scale(res.GetScale()), m_drawInstCount(instCount) { + TToken factory = g_CharFactoryBuilder->GetFactory(res); + x10_animData = + factory->CreateCharacter(res.GetCharacterNodeId(), res.CanLoop(), factory, res.GetDefaultAnim(), instCount); } -SAdvancementDeltas CModelData::GetAdvancementDeltas(const CCharAnimTime& a, - const CCharAnimTime& b) const -{ - if (x10_animData) - return x10_animData->GetAdvancementDeltas(a, b); - else - return {}; +SAdvancementDeltas CModelData::GetAdvancementDeltas(const CCharAnimTime& a, const CCharAnimTime& b) const { + if (x10_animData) + return x10_animData->GetAdvancementDeltas(a, b); + else + return {}; } -void CModelData::Render(const CStateManager& stateMgr, const zeus::CTransform& xf, - const CActorLights* lights, const CModelFlags& drawFlags) const -{ - Render(GetRenderingModel(stateMgr), xf, lights, drawFlags); +void CModelData::Render(const CStateManager& stateMgr, const zeus::CTransform& xf, const CActorLights* lights, + const CModelFlags& drawFlags) const { + Render(GetRenderingModel(stateMgr), xf, lights, drawFlags); } -bool CModelData::IsLoaded(int shaderIdx) const -{ - if (x10_animData) - { - if (!x10_animData->xd8_modelData->GetModel()->IsLoaded(shaderIdx)) - return false; - if (const CSkinnedModel* model = x10_animData->xf4_xrayModel.get()) - if (!model->GetModel()->IsLoaded(shaderIdx)) - return false; - if (const CSkinnedModel* model = x10_animData->xf8_infraModel.get()) - if (!model->GetModel()->IsLoaded(shaderIdx)) - return false; - } - - if (const CModel* model = x1c_normalModel.GetObj()) - if (!model->IsLoaded(shaderIdx)) - return false; - if (const CModel* model = x2c_xrayModel.GetObj()) - if (!model->IsLoaded(shaderIdx)) - return false; - if (const CModel* model = x3c_infraModel.GetObj()) - if (!model->IsLoaded(shaderIdx)) - return false; - - return true; -} - -CModelData::EWhichModel CModelData::GetRenderingModel(const CStateManager& stateMgr) -{ - switch (stateMgr.GetPlayerState()->GetActiveVisor(stateMgr)) - { - case CPlayerState::EPlayerVisor::XRay: - return CModelData::EWhichModel::XRay; - case CPlayerState::EPlayerVisor::Thermal: - if (stateMgr.GetThermalDrawFlag() == EThermalDrawFlag::Cold) - return CModelData::EWhichModel::Thermal; - return CModelData::EWhichModel::ThermalHot; - default: - return CModelData::EWhichModel::Normal; - } -} - -CSkinnedModel& CModelData::PickAnimatedModel(EWhichModel which) const -{ - CSkinnedModel* ret = nullptr; - switch (which) - { - case EWhichModel::XRay: - ret = x10_animData->xf4_xrayModel.get(); - break; - case EWhichModel::Thermal: - case EWhichModel::ThermalHot: - ret = x10_animData->xf8_infraModel.get(); - break; - default: break; - } - if (ret) - return *ret; - return *x10_animData->xd8_modelData.GetObj(); -} - -const std::unique_ptr& CModelData::PickStaticModel(EWhichModel which) const -{ - const std::unique_ptr* ret = nullptr; - switch (which) - { - case EWhichModel::XRay: - ret = &m_xrayModelInst; - break; - case EWhichModel::Thermal: - case EWhichModel::ThermalHot: - ret = &m_infraModelInst; - break; - default: break; - } - if (ret && *ret) - return *ret; - return m_normalModelInst; -} - -void CModelData::SetXRayModel(const std::pair& modelSkin) -{ - if (modelSkin.first.IsValid()) - { - if (g_ResFactory->GetResourceTypeById(modelSkin.first) == SBIG('CMDL')) - { - if (x10_animData && modelSkin.second.IsValid() && - g_ResFactory->GetResourceTypeById(modelSkin.second) == SBIG('CSKR')) - { - x10_animData->SetXRayModel(g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}), - g_SimplePool->GetObj({SBIG('CSKR'), modelSkin.second})); - } - else - { - x2c_xrayModel = g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}); - if (!x2c_xrayModel) - Log.report(logvisor::Fatal, "unable to find CMDL %08X", modelSkin.first); - m_xrayModelInst = x2c_xrayModel->MakeNewInstance(0, m_drawInstCount); - } - } - } -} - -void CModelData::SetInfraModel(const std::pair& modelSkin) -{ - if (modelSkin.first.IsValid()) - { - if (g_ResFactory->GetResourceTypeById(modelSkin.first) == SBIG('CMDL')) - { - if (x10_animData && modelSkin.second.IsValid() && - g_ResFactory->GetResourceTypeById(modelSkin.second) == SBIG('CSKR')) - { - x10_animData->SetInfraModel(g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}), - g_SimplePool->GetObj({SBIG('CSKR'), modelSkin.second})); - } - else - { - x3c_infraModel = g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}); - if (!x3c_infraModel) - Log.report(logvisor::Fatal, "unable to find CMDL %08X", modelSkin.first); - m_infraModelInst = x3c_infraModel->MakeNewInstance(0, m_drawInstCount); - } - } - } -} - -bool CModelData::IsDefinitelyOpaque(EWhichModel which) -{ - if (x10_animData) - { - CSkinnedModel& model = PickAnimatedModel(which); - return model.GetModelInst()->IsOpaque(); - } - else - { - const auto& model = PickStaticModel(which); - return model->IsOpaque(); - } -} - -bool CModelData::GetIsLoop() const -{ - if (!x10_animData) +bool CModelData::IsLoaded(int shaderIdx) const { + if (x10_animData) { + if (!x10_animData->xd8_modelData->GetModel()->IsLoaded(shaderIdx)) + return false; + if (const CSkinnedModel* model = x10_animData->xf4_xrayModel.get()) + if (!model->GetModel()->IsLoaded(shaderIdx)) return false; - return x10_animData->GetIsLoop(); -} - -float CModelData::GetAnimationDuration(int idx) const -{ - if (!x10_animData) - return 0.f; - return x10_animData->GetAnimationDuration(idx); -} - -void CModelData::EnableLooping(bool enable) -{ - if (!x10_animData) - return; - x10_animData->EnableLooping(enable); -} - -void CModelData::AdvanceParticles(const zeus::CTransform& xf, float dt, - CStateManager& stateMgr) -{ - if (!x10_animData) - return; - x10_animData->AdvanceParticles(xf, dt, x0_scale, stateMgr); -} - -zeus::CAABox CModelData::GetBounds() const -{ - if (x10_animData) - { - return x10_animData->GetBoundingBox(zeus::CTransform::Scale(x0_scale)); - } - else - { - const zeus::CAABox& aabb = x1c_normalModel->GetAABB(); - return zeus::CAABox(aabb.min * x0_scale, aabb.max * x0_scale); - } -} - -zeus::CAABox CModelData::GetBounds(const zeus::CTransform& xf) const -{ - zeus::CTransform xf2 = xf * zeus::CTransform::Scale(x0_scale); - if (x10_animData) - return x10_animData->GetBoundingBox(xf2); - else - return x1c_normalModel->GetAABB().getTransformedAABox(xf2); -} - -zeus::CTransform CModelData::GetScaledLocatorTransformDynamic(std::string_view name, - const CCharAnimTime* time) const -{ - zeus::CTransform xf = GetLocatorTransformDynamic(name, time); - xf.origin *= x0_scale; - return xf; -} - -zeus::CTransform CModelData::GetScaledLocatorTransform(std::string_view name) const -{ - zeus::CTransform xf = GetLocatorTransform(name); - xf.origin *= x0_scale; - return xf; -} - -zeus::CTransform CModelData::GetLocatorTransformDynamic(std::string_view name, - const CCharAnimTime* time) const -{ - if (x10_animData) - return x10_animData->GetLocatorTransform(name, time); - else - return {}; -} - -zeus::CTransform CModelData::GetLocatorTransform(std::string_view name) const -{ - if (x10_animData) - return x10_animData->GetLocatorTransform(name, nullptr); - else - return {}; -} - -SAdvancementDeltas CModelData::AdvanceAnimationIgnoreParticles(float dt, CRandom16& rand, bool advTree) -{ - if (x10_animData) - return x10_animData->AdvanceIgnoreParticles(dt, rand, advTree); - else - return {}; -} - -SAdvancementDeltas CModelData::AdvanceAnimation(float dt, CStateManager& stateMgr, TAreaId aid, bool advTree) -{ - if (x10_animData) - return x10_animData->Advance(dt, x0_scale, stateMgr, aid, advTree); - else - return {}; -} - -bool CModelData::IsAnimating() const -{ - if (!x10_animData) + if (const CSkinnedModel* model = x10_animData->xf8_infraModel.get()) + if (!model->GetModel()->IsLoaded(shaderIdx)) return false; - return x10_animData->IsAnimating(); + } + + if (const CModel* model = x1c_normalModel.GetObj()) + if (!model->IsLoaded(shaderIdx)) + return false; + if (const CModel* model = x2c_xrayModel.GetObj()) + if (!model->IsLoaded(shaderIdx)) + return false; + if (const CModel* model = x3c_infraModel.GetObj()) + if (!model->IsLoaded(shaderIdx)) + return false; + + return true; } -bool CModelData::IsInFrustum(const zeus::CTransform& xf, - const zeus::CFrustum& frustum) const -{ - if (!x10_animData && !x1c_normalModel) - return true; - return frustum.aabbFrustumTest(GetBounds(xf)); +CModelData::EWhichModel CModelData::GetRenderingModel(const CStateManager& stateMgr) { + switch (stateMgr.GetPlayerState()->GetActiveVisor(stateMgr)) { + case CPlayerState::EPlayerVisor::XRay: + return CModelData::EWhichModel::XRay; + case CPlayerState::EPlayerVisor::Thermal: + if (stateMgr.GetThermalDrawFlag() == EThermalDrawFlag::Cold) + return CModelData::EWhichModel::Thermal; + return CModelData::EWhichModel::ThermalHot; + default: + return CModelData::EWhichModel::Normal; + } } -void CModelData::RenderParticles(const zeus::CFrustum& frustum) const -{ - if (x10_animData) - x10_animData->RenderAuxiliary(frustum); +CSkinnedModel& CModelData::PickAnimatedModel(EWhichModel which) const { + CSkinnedModel* ret = nullptr; + switch (which) { + case EWhichModel::XRay: + ret = x10_animData->xf4_xrayModel.get(); + break; + case EWhichModel::Thermal: + case EWhichModel::ThermalHot: + ret = x10_animData->xf8_infraModel.get(); + break; + default: + break; + } + if (ret) + return *ret; + return *x10_animData->xd8_modelData.GetObj(); } -void CModelData::Touch(EWhichModel which, int shaderIdx) const -{ - if (x10_animData) - x10_animData->Touch(PickAnimatedModel(which), shaderIdx); - else - PickStaticModel(which)->Touch(shaderIdx); +const std::unique_ptr& CModelData::PickStaticModel(EWhichModel which) const { + const std::unique_ptr* ret = nullptr; + switch (which) { + case EWhichModel::XRay: + ret = &m_xrayModelInst; + break; + case EWhichModel::Thermal: + case EWhichModel::ThermalHot: + ret = &m_infraModelInst; + break; + default: + break; + } + if (ret && *ret) + return *ret; + return m_normalModelInst; } -void CModelData::Touch(const CStateManager& stateMgr, int shaderIdx) const -{ - Touch(const_cast(*this).GetRenderingModel(stateMgr), shaderIdx); -} - -void CModelData::RenderThermal(const zeus::CTransform& xf, const zeus::CColor& mulColor, - const zeus::CColor& addColor, const CModelFlags& flags) const -{ - CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); - CGraphics::DisableAllLights(); - CModelFlags drawFlags = flags; - drawFlags.x4_color *= mulColor; - drawFlags.addColor = addColor; - drawFlags.m_extendedShader = EExtendedShader::Thermal; - - if (x10_animData) - { - CSkinnedModel& model = PickAnimatedModel(EWhichModel::ThermalHot); - x10_animData->SetupRender(model, drawFlags, {}, nullptr); - model.Draw(drawFlags); - } - else - { - const auto& model = PickStaticModel(EWhichModel::ThermalHot); - model->Draw(drawFlags, nullptr, nullptr); +void CModelData::SetXRayModel(const std::pair& modelSkin) { + if (modelSkin.first.IsValid()) { + if (g_ResFactory->GetResourceTypeById(modelSkin.first) == SBIG('CMDL')) { + if (x10_animData && modelSkin.second.IsValid() && + g_ResFactory->GetResourceTypeById(modelSkin.second) == SBIG('CSKR')) { + x10_animData->SetXRayModel(g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}), + g_SimplePool->GetObj({SBIG('CSKR'), modelSkin.second})); + } else { + x2c_xrayModel = g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}); + if (!x2c_xrayModel) + Log.report(logvisor::Fatal, "unable to find CMDL %08X", modelSkin.first); + m_xrayModelInst = x2c_xrayModel->MakeNewInstance(0, m_drawInstCount); + } } + } } -void CModelData::RenderUnsortedParts(EWhichModel which, const zeus::CTransform& xf, - const CActorLights* lights, const CModelFlags& drawFlags) const -{ - if ((x14_25_sortThermal && which == EWhichModel::ThermalHot) || - x10_animData || !x1c_normalModel || drawFlags.x0_blendMode > 4) - { - const_cast(this)->x14_24_renderSorted = false; - return; +void CModelData::SetInfraModel(const std::pair& modelSkin) { + if (modelSkin.first.IsValid()) { + if (g_ResFactory->GetResourceTypeById(modelSkin.first) == SBIG('CMDL')) { + if (x10_animData && modelSkin.second.IsValid() && + g_ResFactory->GetResourceTypeById(modelSkin.second) == SBIG('CSKR')) { + x10_animData->SetInfraModel(g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}), + g_SimplePool->GetObj({SBIG('CSKR'), modelSkin.second})); + } else { + x3c_infraModel = g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}); + if (!x3c_infraModel) + Log.report(logvisor::Fatal, "unable to find CMDL %08X", modelSkin.first); + m_infraModelInst = x3c_infraModel->MakeNewInstance(0, m_drawInstCount); + } } + } +} - CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); - +bool CModelData::IsDefinitelyOpaque(EWhichModel which) { + if (x10_animData) { + CSkinnedModel& model = PickAnimatedModel(which); + return model.GetModelInst()->IsOpaque(); + } else { const auto& model = PickStaticModel(which); - if (lights) - { + return model->IsOpaque(); + } +} + +bool CModelData::GetIsLoop() const { + if (!x10_animData) + return false; + return x10_animData->GetIsLoop(); +} + +float CModelData::GetAnimationDuration(int idx) const { + if (!x10_animData) + return 0.f; + return x10_animData->GetAnimationDuration(idx); +} + +void CModelData::EnableLooping(bool enable) { + if (!x10_animData) + return; + x10_animData->EnableLooping(enable); +} + +void CModelData::AdvanceParticles(const zeus::CTransform& xf, float dt, CStateManager& stateMgr) { + if (!x10_animData) + return; + x10_animData->AdvanceParticles(xf, dt, x0_scale, stateMgr); +} + +zeus::CAABox CModelData::GetBounds() const { + if (x10_animData) { + return x10_animData->GetBoundingBox(zeus::CTransform::Scale(x0_scale)); + } else { + const zeus::CAABox& aabb = x1c_normalModel->GetAABB(); + return zeus::CAABox(aabb.min * x0_scale, aabb.max * x0_scale); + } +} + +zeus::CAABox CModelData::GetBounds(const zeus::CTransform& xf) const { + zeus::CTransform xf2 = xf * zeus::CTransform::Scale(x0_scale); + if (x10_animData) + return x10_animData->GetBoundingBox(xf2); + else + return x1c_normalModel->GetAABB().getTransformedAABox(xf2); +} + +zeus::CTransform CModelData::GetScaledLocatorTransformDynamic(std::string_view name, const CCharAnimTime* time) const { + zeus::CTransform xf = GetLocatorTransformDynamic(name, time); + xf.origin *= x0_scale; + return xf; +} + +zeus::CTransform CModelData::GetScaledLocatorTransform(std::string_view name) const { + zeus::CTransform xf = GetLocatorTransform(name); + xf.origin *= x0_scale; + return xf; +} + +zeus::CTransform CModelData::GetLocatorTransformDynamic(std::string_view name, const CCharAnimTime* time) const { + if (x10_animData) + return x10_animData->GetLocatorTransform(name, time); + else + return {}; +} + +zeus::CTransform CModelData::GetLocatorTransform(std::string_view name) const { + if (x10_animData) + return x10_animData->GetLocatorTransform(name, nullptr); + else + return {}; +} + +SAdvancementDeltas CModelData::AdvanceAnimationIgnoreParticles(float dt, CRandom16& rand, bool advTree) { + if (x10_animData) + return x10_animData->AdvanceIgnoreParticles(dt, rand, advTree); + else + return {}; +} + +SAdvancementDeltas CModelData::AdvanceAnimation(float dt, CStateManager& stateMgr, TAreaId aid, bool advTree) { + if (x10_animData) + return x10_animData->Advance(dt, x0_scale, stateMgr, aid, advTree); + else + return {}; +} + +bool CModelData::IsAnimating() const { + if (!x10_animData) + return false; + return x10_animData->IsAnimating(); +} + +bool CModelData::IsInFrustum(const zeus::CTransform& xf, const zeus::CFrustum& frustum) const { + if (!x10_animData && !x1c_normalModel) + return true; + return frustum.aabbFrustumTest(GetBounds(xf)); +} + +void CModelData::RenderParticles(const zeus::CFrustum& frustum) const { + if (x10_animData) + x10_animData->RenderAuxiliary(frustum); +} + +void CModelData::Touch(EWhichModel which, int shaderIdx) const { + if (x10_animData) + x10_animData->Touch(PickAnimatedModel(which), shaderIdx); + else + PickStaticModel(which)->Touch(shaderIdx); +} + +void CModelData::Touch(const CStateManager& stateMgr, int shaderIdx) const { + Touch(const_cast(*this).GetRenderingModel(stateMgr), shaderIdx); +} + +void CModelData::RenderThermal(const zeus::CTransform& xf, const zeus::CColor& mulColor, const zeus::CColor& addColor, + const CModelFlags& flags) const { + CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); + CGraphics::DisableAllLights(); + CModelFlags drawFlags = flags; + drawFlags.x4_color *= mulColor; + drawFlags.addColor = addColor; + drawFlags.m_extendedShader = EExtendedShader::Thermal; + + if (x10_animData) { + CSkinnedModel& model = PickAnimatedModel(EWhichModel::ThermalHot); + x10_animData->SetupRender(model, drawFlags, {}, nullptr); + model.Draw(drawFlags); + } else { + const auto& model = PickStaticModel(EWhichModel::ThermalHot); + model->Draw(drawFlags, nullptr, nullptr); + } +} + +void CModelData::RenderUnsortedParts(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights, + const CModelFlags& drawFlags) const { + if ((x14_25_sortThermal && which == EWhichModel::ThermalHot) || x10_animData || !x1c_normalModel || + drawFlags.x0_blendMode > 4) { + const_cast(this)->x14_24_renderSorted = false; + return; + } + + CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); + + const auto& model = PickStaticModel(which); + if (lights) { + lights->ActivateLights(*model); + } else { + std::vector useLights; + useLights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, x18_ambientColor)); + model->ActivateLights(useLights); + } + + model->DrawNormal(drawFlags, nullptr, nullptr); + // Set ambient to white + CGraphics::DisableAllLights(); + const_cast(this)->x14_24_renderSorted = true; +} + +void CModelData::Render(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights, + const CModelFlags& drawFlags) const { + if (x14_25_sortThermal && which == EWhichModel::ThermalHot) { + zeus::CColor mul(drawFlags.x4_color.a(), drawFlags.x4_color.a()); + RenderThermal(xf, mul, {0.f, 0.f, 0.f, 0.25f}, drawFlags); + } else { + CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); + + if (x10_animData) { + CSkinnedModel& model = PickAnimatedModel(which); + if (lights) { + lights->ActivateLights(*model.GetModelInst()); + } else { + std::vector useLights; + useLights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, x18_ambientColor)); + model.GetModelInst()->ActivateLights(useLights); + } + + x10_animData->Render(model, drawFlags, {}, nullptr); + } else { + const auto& model = PickStaticModel(which); + if (lights) { lights->ActivateLights(*model); - } - else - { + } else { std::vector useLights; useLights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, x18_ambientColor)); model->ActivateLights(useLights); + } + + if (x14_24_renderSorted) + model->DrawAlpha(drawFlags, nullptr, nullptr); + else + model->Draw(drawFlags, nullptr, nullptr); } - model->DrawNormal(drawFlags, nullptr, nullptr); // Set ambient to white CGraphics::DisableAllLights(); - const_cast(this)->x14_24_renderSorted = true; -} - -void CModelData::Render(EWhichModel which, const zeus::CTransform& xf, - const CActorLights* lights, const CModelFlags& drawFlags) const -{ - if (x14_25_sortThermal && which == EWhichModel::ThermalHot) - { - zeus::CColor mul(drawFlags.x4_color.a(), drawFlags.x4_color.a()); - RenderThermal(xf, mul, {0.f, 0.f, 0.f, 0.25f}, drawFlags); - } - else - { - CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); - - if (x10_animData) - { - CSkinnedModel& model = PickAnimatedModel(which); - if (lights) - { - lights->ActivateLights(*model.GetModelInst()); - } - else - { - std::vector useLights; - useLights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, x18_ambientColor)); - model.GetModelInst()->ActivateLights(useLights); - } - - x10_animData->Render(model, drawFlags, {}, nullptr); - } - else - { - const auto& model = PickStaticModel(which); - if (lights) - { - lights->ActivateLights(*model); - } - else - { - std::vector useLights; - useLights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, x18_ambientColor)); - model->ActivateLights(useLights); - } - - if (x14_24_renderSorted) - model->DrawAlpha(drawFlags, nullptr, nullptr); - else - model->Draw(drawFlags, nullptr, nullptr); - } - - // Set ambient to white - CGraphics::DisableAllLights(); - const_cast(this)->x14_24_renderSorted = false; - } + const_cast(this)->x14_24_renderSorted = false; + } } void CModelData::InvSuitDraw(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights, - const zeus::CColor& alphaColor, const zeus::CColor& additiveColor) -{ - CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); - if (x10_animData) - { - CSkinnedModel& model = PickAnimatedModel(which); - model.GetModelInst()->DisableAllLights(); - CModelFlags flags = {}; + const zeus::CColor& alphaColor, const zeus::CColor& additiveColor) { + CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); + if (x10_animData) { + CSkinnedModel& model = PickAnimatedModel(which); + model.GetModelInst()->DisableAllLights(); + CModelFlags flags = {}; - /* Z-prime */ - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - flags.x4_color = zeus::CColor::skWhite; - x10_animData->Render(model, flags, {}, nullptr); + /* Z-prime */ + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x10_animData->Render(model, flags, {}, nullptr); - /* Normal Blended */ - lights->ActivateLights(*model.GetModelInst()); - flags.m_extendedShader = EExtendedShader::ForcedAlpha; - flags.x4_color = alphaColor; - x10_animData->Render(model, flags, {}, nullptr); + /* Normal Blended */ + lights->ActivateLights(*model.GetModelInst()); + flags.m_extendedShader = EExtendedShader::ForcedAlpha; + flags.x4_color = alphaColor; + x10_animData->Render(model, flags, {}, nullptr); - /* Selection Additive */ - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x4_color = additiveColor; - x10_animData->Render(model, flags, {}, nullptr); - } - else - { - CBooModel& model = *PickStaticModel(which); - model.DisableAllLights(); - CModelFlags flags = {}; + /* Selection Additive */ + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = additiveColor; + x10_animData->Render(model, flags, {}, nullptr); + } else { + CBooModel& model = *PickStaticModel(which); + model.DisableAllLights(); + CModelFlags flags = {}; - /* Z-prime */ - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - flags.x4_color = zeus::CColor::skWhite; - model.Draw(flags, nullptr, nullptr); + /* Z-prime */ + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + model.Draw(flags, nullptr, nullptr); - /* Normal Blended */ - lights->ActivateLights(model); - flags.m_extendedShader = EExtendedShader::ForcedAlpha; - flags.x4_color = alphaColor; - model.Draw(flags, nullptr, nullptr); + /* Normal Blended */ + lights->ActivateLights(model); + flags.m_extendedShader = EExtendedShader::ForcedAlpha; + flags.x4_color = alphaColor; + model.Draw(flags, nullptr, nullptr); - /* Selection Additive */ - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x4_color = additiveColor; - model.Draw(flags, nullptr, nullptr); - } + /* Selection Additive */ + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = additiveColor; + model.Draw(flags, nullptr, nullptr); + } } -void CModelData::DisintegrateDraw(const CStateManager& mgr, const zeus::CTransform& xf, - const CTexture& tex, const zeus::CColor& addColor, float t) -{ - DisintegrateDraw(GetRenderingModel(mgr), xf, tex, addColor, t); +void CModelData::DisintegrateDraw(const CStateManager& mgr, const zeus::CTransform& xf, const CTexture& tex, + const zeus::CColor& addColor, float t) { + DisintegrateDraw(GetRenderingModel(mgr), xf, tex, addColor, t); } -void CModelData::DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf, - const CTexture& tex, const zeus::CColor& addColor, float t) -{ - zeus::CTransform scaledXf = xf * zeus::CTransform::Scale(x0_scale); - CGraphics::SetModelMatrix(scaledXf); +void CModelData::DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf, const CTexture& tex, + const zeus::CColor& addColor, float t) { + zeus::CTransform scaledXf = xf * zeus::CTransform::Scale(x0_scale); + CGraphics::SetModelMatrix(scaledXf); - CBooModel::SetDisintegrateTexture(tex.GetBooTexture()); - CModelFlags flags(5, 0, 3, zeus::CColor::skWhite); - flags.m_extendedShader = EExtendedShader::Disintegrate; - flags.addColor = addColor; - flags.addColor.a() = t; // Stash T value in here (shader does not care) + CBooModel::SetDisintegrateTexture(tex.GetBooTexture()); + CModelFlags flags(5, 0, 3, zeus::CColor::skWhite); + flags.m_extendedShader = EExtendedShader::Disintegrate; + flags.addColor = addColor; + flags.addColor.a() = t; // Stash T value in here (shader does not care) - if (x10_animData) - { - CSkinnedModel& sModel = PickAnimatedModel(which); - x10_animData->Render(sModel, flags, {}, nullptr); - } - else - { - CBooModel& model = *PickStaticModel(which); - model.Draw(flags, nullptr, nullptr); - } + if (x10_animData) { + CSkinnedModel& sModel = PickAnimatedModel(which); + x10_animData->Render(sModel, flags, {}, nullptr); + } else { + CBooModel& model = *PickStaticModel(which); + model.Draw(flags, nullptr, nullptr); + } } -} +} // namespace urde diff --git a/Runtime/Character/CModelData.hpp b/Runtime/Character/CModelData.hpp index b70647705..224f2e4d3 100644 --- a/Runtime/Character/CModelData.hpp +++ b/Runtime/Character/CModelData.hpp @@ -8,8 +8,7 @@ #include "CAnimData.hpp" #include "Graphics/CModel.hpp" -namespace urde -{ +namespace urde { class CCharAnimTime; class CStateManager; class CActorLights; @@ -20,173 +19,152 @@ class CModel; class CSkinnedModel; struct SAdvancementDeltas; -class CStaticRes -{ - CAssetId x0_cmdlId = 0; - zeus::CVector3f x4_scale; -public: - CStaticRes(CAssetId id, const zeus::CVector3f& scale) - : x0_cmdlId(id), - x4_scale(scale) - {} +class CStaticRes { + CAssetId x0_cmdlId = 0; + zeus::CVector3f x4_scale; - CAssetId GetId() const { return x0_cmdlId; } - const zeus::CVector3f& GetScale() const { return x4_scale; } - operator bool() const { return x0_cmdlId != 0; } +public: + CStaticRes(CAssetId id, const zeus::CVector3f& scale) : x0_cmdlId(id), x4_scale(scale) {} + + CAssetId GetId() const { return x0_cmdlId; } + const zeus::CVector3f& GetScale() const { return x4_scale; } + operator bool() const { return x0_cmdlId != 0; } }; -class CAnimRes -{ - CAssetId x0_ancsId; - s32 x4_charIdx = -1; - zeus::CVector3f x8_scale; - bool x14_canLoop = false; - /* NOTE: x18_bodyType - Removed in retail */ - s32 x18_defaultAnim = -1; /* NOTE: used to be x1c in demo */ +class CAnimRes { + CAssetId x0_ancsId; + s32 x4_charIdx = -1; + zeus::CVector3f x8_scale; + bool x14_canLoop = false; + /* NOTE: x18_bodyType - Removed in retail */ + s32 x18_defaultAnim = -1; /* NOTE: used to be x1c in demo */ public: - CAnimRes() = default; - CAnimRes(CAssetId ancs, s32 charIdx, const zeus::CVector3f& scale, const s32 defaultAnim, bool loop) - : x0_ancsId(ancs), - x4_charIdx(charIdx), - x8_scale(scale), - x14_canLoop(loop), - x18_defaultAnim(defaultAnim) - { + CAnimRes() = default; + CAnimRes(CAssetId ancs, s32 charIdx, const zeus::CVector3f& scale, const s32 defaultAnim, bool loop) + : x0_ancsId(ancs), x4_charIdx(charIdx), x8_scale(scale), x14_canLoop(loop), x18_defaultAnim(defaultAnim) {} + + CAssetId GetId() const { return x0_ancsId; } + s32 GetCharacterNodeId() const { return x4_charIdx; } + void SetCharacterNodeId(s32 id) { x4_charIdx = id; } + const zeus::CVector3f& GetScale() const { return x8_scale; } + bool CanLoop() const { return x14_canLoop; } + s32 GetDefaultAnim() const { return x18_defaultAnim; } +}; + +class CModelData { + friend class CActor; + zeus::CVector3f x0_scale; + bool xc_ = false; + std::unique_ptr x10_animData; + union { + struct { + bool x14_24_renderSorted : 1; + bool x14_25_sortThermal : 1; + }; + u32 _flags = 0; + }; + zeus::CColor x18_ambientColor; + + TLockedToken x1c_normalModel; + TLockedToken x2c_xrayModel; + TLockedToken x3c_infraModel; + + std::unique_ptr m_normalModelInst; + std::unique_ptr m_xrayModelInst; + std::unique_ptr m_infraModelInst; + + int m_drawInstCount; + +public: + enum class EWhichModel { Normal, XRay, Thermal, ThermalHot }; + + void SetSortThermal(bool v) { x14_25_sortThermal = v; } + bool GetSortThermal() const { return x14_25_sortThermal; } + + ~CModelData(); + CModelData(const CStaticRes& res, int instCount = 1); + CModelData(const CAnimRes& res, int instCount = 1); + CModelData(CModelData&&) = default; + CModelData& operator=(CModelData&&) = default; + CModelData(); + static CModelData CModelDataNull(); + + SAdvancementDeltas GetAdvancementDeltas(const CCharAnimTime& a, const CCharAnimTime& b) const; + void Render(const CStateManager& stateMgr, const zeus::CTransform& xf, const CActorLights* lights, + const CModelFlags& drawFlags) const; + bool IsLoaded(int shaderIdx) const; + static EWhichModel GetRenderingModel(const CStateManager& stateMgr); + CSkinnedModel& PickAnimatedModel(EWhichModel which) const; + const std::unique_ptr& PickStaticModel(EWhichModel which) const; + void SetXRayModel(const std::pair& modelSkin); + void SetInfraModel(const std::pair& modelSkin); + bool IsDefinitelyOpaque(EWhichModel); + bool GetIsLoop() const; + float GetAnimationDuration(int) const; + void EnableLooping(bool); + void AdvanceParticles(const zeus::CTransform& xf, float, CStateManager& stateMgr); + zeus::CAABox GetBounds() const; + zeus::CAABox GetBounds(const zeus::CTransform& xf) const; + zeus::CTransform GetScaledLocatorTransformDynamic(std::string_view name, const CCharAnimTime* time) const; + zeus::CTransform GetScaledLocatorTransform(std::string_view name) const; + zeus::CTransform GetLocatorTransformDynamic(std::string_view name, const CCharAnimTime* time) const; + zeus::CTransform GetLocatorTransform(std::string_view name) const; + SAdvancementDeltas AdvanceAnimationIgnoreParticles(float dt, CRandom16&, bool advTree); + SAdvancementDeltas AdvanceAnimation(float dt, CStateManager& stateMgr, TAreaId aid, bool advTree); + bool IsAnimating() const; + bool IsInFrustum(const zeus::CTransform& xf, const zeus::CFrustum& frustum) const; + void RenderParticles(const zeus::CFrustum& frustum) const; + void Touch(EWhichModel, int shaderIdx) const; + void Touch(const CStateManager& stateMgr, int shaderIdx) const; + void RenderThermal(const zeus::CTransform& xf, const zeus::CColor& mulColor, const zeus::CColor& addColor, + const CModelFlags& flags) const; + void RenderUnsortedParts(EWhichModel, const zeus::CTransform& xf, const CActorLights* lights, + const CModelFlags& drawFlags) const; + void Render(EWhichModel, const zeus::CTransform& xf, const CActorLights* lights, const CModelFlags& drawFlags) const; + + void InvSuitDraw(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights, + const zeus::CColor& color0, const zeus::CColor& color1); + void DisintegrateDraw(const CStateManager& mgr, const zeus::CTransform& xf, const CTexture& tex, + const zeus::CColor& addColor, float t); + void DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf, const CTexture& tex, + const zeus::CColor& addColor, float t); + + CAnimData* AnimationData() { return x10_animData.get(); } + const CAnimData* GetAnimationData() const { return x10_animData.get(); } + const TLockedToken& GetNormalModel() const { return x1c_normalModel; } + const TLockedToken& GetXRayModel() const { return x2c_xrayModel; } + const TLockedToken& GetThermalModel() const { return x3c_infraModel; } + bool IsNull() const { return !x10_animData && !x1c_normalModel; } + + const zeus::CVector3f& GetScale() const { return x0_scale; } + void SetScale(const zeus::CVector3f& scale) { x0_scale = scale; } + bool HasAnimData() const { return x10_animData != nullptr; } + bool HasNormalModel() const { return x1c_normalModel; } + bool HasModel(EWhichModel which) { + if (x10_animData) { + switch (which) { + case EWhichModel::Normal: + return true; + case EWhichModel::XRay: + return x10_animData->GetXRayModel().operator bool(); + case EWhichModel::Thermal: + return x10_animData->GetInfraModel().operator bool(); + default: + return false; + } } - CAssetId GetId() const { return x0_ancsId; } - s32 GetCharacterNodeId() const { return x4_charIdx; } - void SetCharacterNodeId(s32 id) { x4_charIdx = id; } - const zeus::CVector3f& GetScale() const { return x8_scale; } - bool CanLoop() const { return x14_canLoop; } - s32 GetDefaultAnim() const { return x18_defaultAnim; } -}; - -class CModelData -{ - friend class CActor; - zeus::CVector3f x0_scale; - bool xc_ = false; - std::unique_ptr x10_animData; - union - { - struct - { - bool x14_24_renderSorted : 1; - bool x14_25_sortThermal : 1; - }; - u32 _flags = 0; - }; - zeus::CColor x18_ambientColor; - - TLockedToken x1c_normalModel; - TLockedToken x2c_xrayModel; - TLockedToken x3c_infraModel; - - std::unique_ptr m_normalModelInst; - std::unique_ptr m_xrayModelInst; - std::unique_ptr m_infraModelInst; - - int m_drawInstCount; - -public: - enum class EWhichModel - { - Normal, - XRay, - Thermal, - ThermalHot - }; - - void SetSortThermal(bool v) { x14_25_sortThermal = v; } - bool GetSortThermal() const { return x14_25_sortThermal; } - - ~CModelData(); - CModelData(const CStaticRes& res, int instCount=1); - CModelData(const CAnimRes& res, int instCount=1); - CModelData(CModelData&&) = default; - CModelData& operator=(CModelData&&) = default; - CModelData(); - static CModelData CModelDataNull(); - - SAdvancementDeltas GetAdvancementDeltas(const CCharAnimTime& a, const CCharAnimTime& b) const; - void Render(const CStateManager& stateMgr, const zeus::CTransform& xf, - const CActorLights* lights, const CModelFlags& drawFlags) const; - bool IsLoaded(int shaderIdx) const; - static EWhichModel GetRenderingModel(const CStateManager& stateMgr); - CSkinnedModel& PickAnimatedModel(EWhichModel which) const; - const std::unique_ptr& PickStaticModel(EWhichModel which) const; - void SetXRayModel(const std::pair& modelSkin); - void SetInfraModel(const std::pair& modelSkin); - bool IsDefinitelyOpaque(EWhichModel); - bool GetIsLoop() const; - float GetAnimationDuration(int) const; - void EnableLooping(bool); - void AdvanceParticles(const zeus::CTransform& xf, float, CStateManager& stateMgr); - zeus::CAABox GetBounds() const; - zeus::CAABox GetBounds(const zeus::CTransform& xf) const; - zeus::CTransform GetScaledLocatorTransformDynamic(std::string_view name, const CCharAnimTime* time) const; - zeus::CTransform GetScaledLocatorTransform(std::string_view name) const; - zeus::CTransform GetLocatorTransformDynamic(std::string_view name, const CCharAnimTime* time) const; - zeus::CTransform GetLocatorTransform(std::string_view name) const; - SAdvancementDeltas AdvanceAnimationIgnoreParticles(float dt, CRandom16&, bool advTree); - SAdvancementDeltas AdvanceAnimation(float dt, CStateManager& stateMgr, TAreaId aid, bool advTree); - bool IsAnimating() const; - bool IsInFrustum(const zeus::CTransform& xf, const zeus::CFrustum& frustum) const; - void RenderParticles(const zeus::CFrustum& frustum) const; - void Touch(EWhichModel, int shaderIdx) const; - void Touch(const CStateManager& stateMgr, int shaderIdx) const; - void RenderThermal(const zeus::CTransform& xf, const zeus::CColor& mulColor, - const zeus::CColor& addColor, const CModelFlags& flags) const; - void RenderUnsortedParts(EWhichModel, const zeus::CTransform& xf, - const CActorLights* lights, const CModelFlags& drawFlags) const; - void Render(EWhichModel, const zeus::CTransform& xf, - const CActorLights* lights, const CModelFlags& drawFlags) const; - - void InvSuitDraw(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights, - const zeus::CColor& color0, const zeus::CColor& color1); - void DisintegrateDraw(const CStateManager& mgr, const zeus::CTransform& xf, - const CTexture& tex, const zeus::CColor& addColor, float t); - void DisintegrateDraw(EWhichModel which, const zeus::CTransform& xf, - const CTexture& tex, const zeus::CColor& addColor, float t); - - CAnimData* AnimationData() { return x10_animData.get(); } - const CAnimData* GetAnimationData() const { return x10_animData.get(); } - const TLockedToken& GetNormalModel() const { return x1c_normalModel; } - const TLockedToken& GetXRayModel() const { return x2c_xrayModel; } - const TLockedToken& GetThermalModel() const { return x3c_infraModel; } - bool IsNull() const { return !x10_animData && !x1c_normalModel; } - - const zeus::CVector3f& GetScale() const { return x0_scale; } - void SetScale(const zeus::CVector3f& scale) { x0_scale = scale; } - bool HasAnimData() const { return x10_animData != nullptr; } - bool HasNormalModel() const { return x1c_normalModel; } - bool HasModel(EWhichModel which) - { - if (x10_animData) - { - switch(which) - { - case EWhichModel::Normal: return true; - case EWhichModel::XRay: return x10_animData->GetXRayModel().operator bool(); - case EWhichModel::Thermal: return x10_animData->GetInfraModel().operator bool(); - default: - return false; - } - } - - switch(which) - { - case EWhichModel::Normal: - return x1c_normalModel; - case EWhichModel::XRay: - return x2c_xrayModel; - case EWhichModel::Thermal: - return x3c_infraModel; - default: return false; - } + switch (which) { + case EWhichModel::Normal: + return x1c_normalModel; + case EWhichModel::XRay: + return x2c_xrayModel; + case EWhichModel::Thermal: + return x3c_infraModel; + default: + return false; } + } }; -} - +} // namespace urde diff --git a/Runtime/Character/CPASAnimInfo.cpp b/Runtime/Character/CPASAnimInfo.cpp index 86eaab1f4..c5c09b273 100644 --- a/Runtime/Character/CPASAnimInfo.cpp +++ b/Runtime/Character/CPASAnimInfo.cpp @@ -1,40 +1,35 @@ #include "CPASAnimInfo.hpp" -namespace urde -{ +namespace urde { CPASAnimInfo::CPASAnimInfo(u32 id, rstl::reserved_vector&& parms) - : x0_id(id), x4_parms(std::move(parms)) {} +: x0_id(id), x4_parms(std::move(parms)) {} -CPASAnimParm::UParmValue CPASAnimInfo::GetAnimParmValue(u32 idx) const -{ - if (idx >= x4_parms.size()) - return CPASAnimParm::UParmValue{}; - return x4_parms[idx]; +CPASAnimParm::UParmValue CPASAnimInfo::GetAnimParmValue(u32 idx) const { + if (idx >= x4_parms.size()) + return CPASAnimParm::UParmValue{}; + return x4_parms[idx]; } -CPASAnimParm CPASAnimInfo::GetAnimParmData(u32 idx, CPASAnimParm::EParmType type) const -{ - if (idx >= x4_parms.size()) - return CPASAnimParm::NoParameter(); - const CPASAnimParm::UParmValue& parm = x4_parms[idx]; - - switch(type) - { - case CPASAnimParm::EParmType::Int32: - return CPASAnimParm::FromInt32(parm.m_int); - case CPASAnimParm::EParmType::UInt32: - return CPASAnimParm::FromUint32(parm.m_uint); - case CPASAnimParm::EParmType::Float: - return CPASAnimParm::FromReal32(parm.m_float); - case CPASAnimParm::EParmType::Bool: - return CPASAnimParm::FromBool(parm.m_bool); - case CPASAnimParm::EParmType::Enum: - return CPASAnimParm::FromEnum(parm.m_int); - default: - return CPASAnimParm::NoParameter(); - } +CPASAnimParm CPASAnimInfo::GetAnimParmData(u32 idx, CPASAnimParm::EParmType type) const { + if (idx >= x4_parms.size()) + return CPASAnimParm::NoParameter(); + const CPASAnimParm::UParmValue& parm = x4_parms[idx]; + switch (type) { + case CPASAnimParm::EParmType::Int32: + return CPASAnimParm::FromInt32(parm.m_int); + case CPASAnimParm::EParmType::UInt32: + return CPASAnimParm::FromUint32(parm.m_uint); + case CPASAnimParm::EParmType::Float: + return CPASAnimParm::FromReal32(parm.m_float); + case CPASAnimParm::EParmType::Bool: + return CPASAnimParm::FromBool(parm.m_bool); + case CPASAnimParm::EParmType::Enum: + return CPASAnimParm::FromEnum(parm.m_int); + default: + return CPASAnimParm::NoParameter(); + } } -} +} // namespace urde diff --git a/Runtime/Character/CPASAnimInfo.hpp b/Runtime/Character/CPASAnimInfo.hpp index f00892150..239699471 100644 --- a/Runtime/Character/CPASAnimInfo.hpp +++ b/Runtime/Character/CPASAnimInfo.hpp @@ -4,20 +4,18 @@ #include "rstl.hpp" #include "CPASAnimParm.hpp" -namespace urde -{ +namespace urde { + +class CPASAnimInfo { + u32 x0_id; + rstl::reserved_vector x4_parms; -class CPASAnimInfo -{ - u32 x0_id; - rstl::reserved_vector x4_parms; public: - CPASAnimInfo(u32 id) : x0_id(id) {} - CPASAnimInfo(u32 id, rstl::reserved_vector&& parms); - u32 GetAnimId() const { return x0_id; } - CPASAnimParm::UParmValue GetAnimParmValue(u32 idx) const; - CPASAnimParm GetAnimParmData(u32, CPASAnimParm::EParmType) const; + CPASAnimInfo(u32 id) : x0_id(id) {} + CPASAnimInfo(u32 id, rstl::reserved_vector&& parms); + u32 GetAnimId() const { return x0_id; } + CPASAnimParm::UParmValue GetAnimParmValue(u32 idx) const; + CPASAnimParm GetAnimParmData(u32, CPASAnimParm::EParmType) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CPASAnimParm.hpp b/Runtime/Character/CPASAnimParm.hpp index a26f1221c..ed3f47c00 100644 --- a/Runtime/Character/CPASAnimParm.hpp +++ b/Runtime/Character/CPASAnimParm.hpp @@ -2,84 +2,67 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -class CPASAnimParm -{ +class CPASAnimParm { public: - enum class EParmType - { - None = -1, - Int32 = 0, - UInt32 = 1, - Float = 2, - Bool = 3, - Enum = 4 - }; - union UParmValue - { - s32 m_int; - u32 m_uint; - float m_float; - bool m_bool; - }; + enum class EParmType { None = -1, Int32 = 0, UInt32 = 1, Float = 2, Bool = 3, Enum = 4 }; + union UParmValue { + s32 m_int; + u32 m_uint; + float m_float; + bool m_bool; + }; private: - UParmValue x0_value; - EParmType x4_type; + UParmValue x0_value; + EParmType x4_type; + public: - CPASAnimParm(UParmValue val, EParmType tp) : x0_value(val), x4_type(tp) {} + CPASAnimParm(UParmValue val, EParmType tp) : x0_value(val), x4_type(tp) {} - EParmType GetParameterType() const { return x4_type; } - s32 GetEnumValue() const {return x0_value.m_int;} - bool GetBoolValue() const {return x0_value.m_bool;} - float GetReal32Value() const {return x0_value.m_float;} - u32 GetUint32Value() const {return x0_value.m_uint;} - s32 GetInt32Value() const {return x0_value.m_int;} + EParmType GetParameterType() const { return x4_type; } + s32 GetEnumValue() const { return x0_value.m_int; } + bool GetBoolValue() const { return x0_value.m_bool; } + float GetReal32Value() const { return x0_value.m_float; } + u32 GetUint32Value() const { return x0_value.m_uint; } + s32 GetInt32Value() const { return x0_value.m_int; } - static CPASAnimParm FromEnum(s32 val) - { - UParmValue valin; - valin.m_int = val; - return CPASAnimParm(valin, EParmType::Enum); - } + static CPASAnimParm FromEnum(s32 val) { + UParmValue valin; + valin.m_int = val; + return CPASAnimParm(valin, EParmType::Enum); + } - static CPASAnimParm FromBool(bool val) - { - UParmValue valin; - valin.m_bool = val; - return CPASAnimParm(valin, EParmType::Bool); - } + static CPASAnimParm FromBool(bool val) { + UParmValue valin; + valin.m_bool = val; + return CPASAnimParm(valin, EParmType::Bool); + } - static CPASAnimParm FromReal32(float val) - { - UParmValue valin; - valin.m_float = val; - return CPASAnimParm(valin, EParmType::Float); - } + static CPASAnimParm FromReal32(float val) { + UParmValue valin; + valin.m_float = val; + return CPASAnimParm(valin, EParmType::Float); + } - static CPASAnimParm FromUint32(u32 val) - { - UParmValue valin; - valin.m_uint = val; - return CPASAnimParm(valin, EParmType::UInt32); - } + static CPASAnimParm FromUint32(u32 val) { + UParmValue valin; + valin.m_uint = val; + return CPASAnimParm(valin, EParmType::UInt32); + } - static CPASAnimParm FromInt32(s32 val) - { - UParmValue valin; - valin.m_int = val; - return CPASAnimParm(valin, EParmType::Int32); - } + static CPASAnimParm FromInt32(s32 val) { + UParmValue valin; + valin.m_int = val; + return CPASAnimParm(valin, EParmType::Int32); + } - static CPASAnimParm NoParameter() - { - UParmValue valin; - valin.m_int = -1; - return CPASAnimParm(valin, EParmType::None); - } + static CPASAnimParm NoParameter() { + UParmValue valin; + valin.m_int = -1; + return CPASAnimParm(valin, EParmType::None); + } }; -} - +} // namespace urde diff --git a/Runtime/Character/CPASAnimParmData.cpp b/Runtime/Character/CPASAnimParmData.cpp index 4a6df7227..bba370a05 100644 --- a/Runtime/Character/CPASAnimParmData.cpp +++ b/Runtime/Character/CPASAnimParmData.cpp @@ -1,21 +1,19 @@ #include "CPASAnimParmData.hpp" -namespace urde -{ +namespace urde { -CPASAnimParmData::CPASAnimParmData(s32 stateId, const CPASAnimParm& parm1, const CPASAnimParm& parm2, const CPASAnimParm& parm3, - const CPASAnimParm& parm4, const CPASAnimParm& parm5, const CPASAnimParm& parm6, - const CPASAnimParm& parm7, const CPASAnimParm& parm8) - : x0_stateId(stateId) -{ - x4_parms.push_back(parm1); - x4_parms.push_back(parm2); - x4_parms.push_back(parm3); - x4_parms.push_back(parm4); - x4_parms.push_back(parm5); - x4_parms.push_back(parm6); - x4_parms.push_back(parm7); - x4_parms.push_back(parm8); +CPASAnimParmData::CPASAnimParmData(s32 stateId, const CPASAnimParm& parm1, const CPASAnimParm& parm2, + const CPASAnimParm& parm3, const CPASAnimParm& parm4, const CPASAnimParm& parm5, + const CPASAnimParm& parm6, const CPASAnimParm& parm7, const CPASAnimParm& parm8) +: x0_stateId(stateId) { + x4_parms.push_back(parm1); + x4_parms.push_back(parm2); + x4_parms.push_back(parm3); + x4_parms.push_back(parm4); + x4_parms.push_back(parm5); + x4_parms.push_back(parm6); + x4_parms.push_back(parm7); + x4_parms.push_back(parm8); } -} +} // namespace urde diff --git a/Runtime/Character/CPASAnimParmData.hpp b/Runtime/Character/CPASAnimParmData.hpp index 8d830cac7..b16dec9d2 100644 --- a/Runtime/Character/CPASAnimParmData.hpp +++ b/Runtime/Character/CPASAnimParmData.hpp @@ -2,35 +2,36 @@ #include "RetroTypes.hpp" #include "CPASAnimParm.hpp" -namespace urde -{ -class CPASAnimParmData -{ - s32 x0_stateId; - rstl::reserved_vector x4_parms; +namespace urde { +class CPASAnimParmData { + s32 x0_stateId; + rstl::reserved_vector x4_parms; public: - CPASAnimParmData() = default; + CPASAnimParmData() = default; - CPASAnimParmData(s32 stateId, - const CPASAnimParm& parm1 = CPASAnimParm::NoParameter(), - const CPASAnimParm& parm2 = CPASAnimParm::NoParameter(), - const CPASAnimParm& parm3 = CPASAnimParm::NoParameter(), - const CPASAnimParm& parm4 = CPASAnimParm::NoParameter(), - const CPASAnimParm& parm5 = CPASAnimParm::NoParameter(), - const CPASAnimParm& parm6 = CPASAnimParm::NoParameter(), - const CPASAnimParm& parm7 = CPASAnimParm::NoParameter(), - const CPASAnimParm& parm8 = CPASAnimParm::NoParameter()); + CPASAnimParmData(s32 stateId, const CPASAnimParm& parm1 = CPASAnimParm::NoParameter(), + const CPASAnimParm& parm2 = CPASAnimParm::NoParameter(), + const CPASAnimParm& parm3 = CPASAnimParm::NoParameter(), + const CPASAnimParm& parm4 = CPASAnimParm::NoParameter(), + const CPASAnimParm& parm5 = CPASAnimParm::NoParameter(), + const CPASAnimParm& parm6 = CPASAnimParm::NoParameter(), + const CPASAnimParm& parm7 = CPASAnimParm::NoParameter(), + const CPASAnimParm& parm8 = CPASAnimParm::NoParameter()); - s32 GetStateId() const { return x0_stateId; } - const rstl::reserved_vector& GetAnimParmData() const { return x4_parms; } + s32 GetStateId() const { return x0_stateId; } + const rstl::reserved_vector& GetAnimParmData() const { return x4_parms; } - static inline CPASAnimParmData NoParameters(s32 stateId) - { - return {stateId, CPASAnimParm::NoParameter(), CPASAnimParm::NoParameter(), CPASAnimParm::NoParameter(), - CPASAnimParm::NoParameter(), CPASAnimParm::NoParameter(), CPASAnimParm::NoParameter(), - CPASAnimParm::NoParameter(), CPASAnimParm::NoParameter()}; - } + static inline CPASAnimParmData NoParameters(s32 stateId) { + return {stateId, + CPASAnimParm::NoParameter(), + CPASAnimParm::NoParameter(), + CPASAnimParm::NoParameter(), + CPASAnimParm::NoParameter(), + CPASAnimParm::NoParameter(), + CPASAnimParm::NoParameter(), + CPASAnimParm::NoParameter(), + CPASAnimParm::NoParameter()}; + } }; -} - +} // namespace urde diff --git a/Runtime/Character/CPASAnimState.cpp b/Runtime/Character/CPASAnimState.cpp index 3ce5be978..523c2e713 100644 --- a/Runtime/Character/CPASAnimState.cpp +++ b/Runtime/Character/CPASAnimState.cpp @@ -5,271 +5,245 @@ #include #include -namespace urde -{ +namespace urde { -CPASAnimState::CPASAnimState(CInputStream& in) -{ - x0_id = in.readUint32Big(); - u32 parmCount = in.readUint32Big(); - u32 animCount = in.readUint32Big(); +CPASAnimState::CPASAnimState(CInputStream& in) { + x0_id = in.readUint32Big(); + u32 parmCount = in.readUint32Big(); + u32 animCount = in.readUint32Big(); - x4_parms.reserve(parmCount); - x14_anims.reserve(animCount); - x24_selectionCache.reserve(animCount); + x4_parms.reserve(parmCount); + x14_anims.reserve(animCount); + x24_selectionCache.reserve(animCount); - for (u32 i=0 ; i parms; - for (const CPASParmInfo& parm : x4_parms) - { - CPASAnimParm::UParmValue val = {}; - switch (parm.GetParameterType()) - { - case CPASAnimParm::EParmType::Int32: - val.m_int = in.readInt32Big(); - break; - case CPASAnimParm::EParmType::UInt32: - val.m_uint = in.readUint32Big(); - break; - case CPASAnimParm::EParmType::Float: - val.m_float = in.readFloatBig(); - break; - case CPASAnimParm::EParmType::Bool: - val.m_bool = in.readBool(); - break; - case CPASAnimParm::EParmType::Enum: - val.m_int = in.readInt32Big(); - break; - default: break; - } - parms.push_back(val); - } - - auto search = std::lower_bound(x14_anims.begin(), x14_anims.end(), id, - [](const CPASAnimInfo& item, const u32& testId) -> bool {return item.GetAnimId() < testId;}); - x14_anims.emplace(search, id, std::move(parms)); - } -} - -CPASAnimState::CPASAnimState(int stateId) -: x0_id(stateId) -{} - -CPASAnimParm CPASAnimState::GetAnimParmData(s32 animId, u32 parmIdx) const -{ - auto search = rstl::binary_find(x14_anims.begin(), x14_anims.end(), animId, - [](const CPASAnimInfo& item) {return item.GetAnimId();}); - if (search == x14_anims.end()) - return CPASAnimParm::NoParameter(); - - CPASParmInfo parm = x4_parms.at(parmIdx); - return (*search).GetAnimParmData(parmIdx, parm.GetParameterType()); -} - -s32 CPASAnimState::PickRandomAnimation(CRandom16& rand) const -{ - if (x24_selectionCache.size() == 1) - return x24_selectionCache[0]; - - if (x24_selectionCache.size() > 1) - { - u32 idx = u32(floor(rand.Float())); - if (idx == x24_selectionCache.size()) - idx--; - - return x24_selectionCache[idx]; + for (u32 i = 0; i < animCount; ++i) { + s32 id = in.readUint32Big(); + rstl::reserved_vector parms; + for (const CPASParmInfo& parm : x4_parms) { + CPASAnimParm::UParmValue val = {}; + switch (parm.GetParameterType()) { + case CPASAnimParm::EParmType::Int32: + val.m_int = in.readInt32Big(); + break; + case CPASAnimParm::EParmType::UInt32: + val.m_uint = in.readUint32Big(); + break; + case CPASAnimParm::EParmType::Float: + val.m_float = in.readFloatBig(); + break; + case CPASAnimParm::EParmType::Bool: + val.m_bool = in.readBool(); + break; + case CPASAnimParm::EParmType::Enum: + val.m_int = in.readInt32Big(); + break; + default: + break; + } + parms.push_back(val); } - return -1; + auto search = + std::lower_bound(x14_anims.begin(), x14_anims.end(), id, + [](const CPASAnimInfo& item, const u32& testId) -> bool { return item.GetAnimId() < testId; }); + x14_anims.emplace(search, id, std::move(parms)); + } +} + +CPASAnimState::CPASAnimState(int stateId) : x0_id(stateId) {} + +CPASAnimParm CPASAnimState::GetAnimParmData(s32 animId, u32 parmIdx) const { + auto search = rstl::binary_find(x14_anims.begin(), x14_anims.end(), animId, + [](const CPASAnimInfo& item) { return item.GetAnimId(); }); + if (search == x14_anims.end()) + return CPASAnimParm::NoParameter(); + + CPASParmInfo parm = x4_parms.at(parmIdx); + return (*search).GetAnimParmData(parmIdx, parm.GetParameterType()); +} + +s32 CPASAnimState::PickRandomAnimation(CRandom16& rand) const { + if (x24_selectionCache.size() == 1) + return x24_selectionCache[0]; + + if (x24_selectionCache.size() > 1) { + u32 idx = u32(floor(rand.Float())); + if (idx == x24_selectionCache.size()) + idx--; + + return x24_selectionCache[idx]; + } + + return -1; } std::pair CPASAnimState::FindBestAnimation(const rstl::reserved_vector& parms, - CRandom16& rand, s32 ignoreAnim) const -{ - const_cast*>(&x24_selectionCache)->clear(); - float weight = -1.f; + CRandom16& rand, s32 ignoreAnim) const { + const_cast*>(&x24_selectionCache)->clear(); + float weight = -1.f; - for (const CPASAnimInfo& info : x14_anims) - { - if (info.GetAnimId() == ignoreAnim) - continue; + for (const CPASAnimInfo& info : x14_anims) { + if (info.GetAnimId() == ignoreAnim) + continue; - float calcWeight = 1.f; - if (x4_parms.size() > 0) - calcWeight = 0.f; + float calcWeight = 1.f; + if (x4_parms.size() > 0) + calcWeight = 0.f; - u32 unweightedCount = 0; + u32 unweightedCount = 0; - for (u32 i=0 ; i weight) - { - const_cast*>(&x24_selectionCache)->clear(); - const_cast*>(&x24_selectionCache)->push_back(info.GetAnimId()); - weight = calcWeight; - } - else if (weight == calcWeight) - { - const_cast*>(&x24_selectionCache)->push_back(info.GetAnimId()); - weight = calcWeight; - } + calcWeight += parmWeight * computedWeight; } - return {weight, PickRandomAnimation(rand)}; + if (unweightedCount == x4_parms.size()) + calcWeight = 1.0f; + + if (calcWeight > weight) { + const_cast*>(&x24_selectionCache)->clear(); + const_cast*>(&x24_selectionCache)->push_back(info.GetAnimId()); + weight = calcWeight; + } else if (weight == calcWeight) { + const_cast*>(&x24_selectionCache)->push_back(info.GetAnimId()); + weight = calcWeight; + } + } + + return {weight, PickRandomAnimation(rand)}; } -float CPASAnimState::ComputeExactMatchWeight(u32, const CPASAnimParm& parm, CPASAnimParm::UParmValue parmVal) const -{ - switch (parm.GetParameterType()) - { - case CPASAnimParm::EParmType::Int32: - return (parm.GetInt32Value() == parmVal.m_int ? 1.f : 0.f); - case CPASAnimParm::EParmType::UInt32: - return (parm.GetUint32Value() == parmVal.m_uint ? 1.f : 0.f); - case CPASAnimParm::EParmType::Float: - return ((parmVal.m_float - parm.GetReal32Value()) < FLT_EPSILON ? 1.f : 0.f); - case CPASAnimParm::EParmType::Bool: - return (parm.GetBoolValue() == parmVal.m_bool ? 1.f : 0.f); - case CPASAnimParm::EParmType::Enum: - return (parm.GetEnumValue() == parmVal.m_int ? 1.f : 0.f); - default: break; - } +float CPASAnimState::ComputeExactMatchWeight(u32, const CPASAnimParm& parm, CPASAnimParm::UParmValue parmVal) const { + switch (parm.GetParameterType()) { + case CPASAnimParm::EParmType::Int32: + return (parm.GetInt32Value() == parmVal.m_int ? 1.f : 0.f); + case CPASAnimParm::EParmType::UInt32: + return (parm.GetUint32Value() == parmVal.m_uint ? 1.f : 0.f); + case CPASAnimParm::EParmType::Float: + return ((parmVal.m_float - parm.GetReal32Value()) < FLT_EPSILON ? 1.f : 0.f); + case CPASAnimParm::EParmType::Bool: + return (parm.GetBoolValue() == parmVal.m_bool ? 1.f : 0.f); + case CPASAnimParm::EParmType::Enum: + return (parm.GetEnumValue() == parmVal.m_int ? 1.f : 0.f); + default: + break; + } - return 0.f; + return 0.f; } -float CPASAnimState::ComputePercentErrorWeight(u32 idx, const CPASAnimParm& parm, CPASAnimParm::UParmValue parmVal) const -{ - float range = 0.f; - float val = 0.f; +float CPASAnimState::ComputePercentErrorWeight(u32 idx, const CPASAnimParm& parm, + CPASAnimParm::UParmValue parmVal) const { + float range = 0.f; + float val = 0.f; - switch (parm.GetParameterType()) - { - case CPASAnimParm::EParmType::Int32: - { - const CPASParmInfo& info = x4_parms[idx]; - range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int; - val = std::fabs(parm.GetInt32Value() - parmVal.m_int); - break; - } - case CPASAnimParm::EParmType::UInt32: - { - const CPASParmInfo& info = x4_parms[idx]; - range = info.GetWeightMaxValue().m_uint - info.GetWeightMinValue().m_uint; - val = std::fabs(int(parmVal.m_uint) - int(parm.GetUint32Value())); - break; - } - case CPASAnimParm::EParmType::Float: - { - const CPASParmInfo& info = x4_parms[idx]; - range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float; - val = std::fabs(parm.GetReal32Value() - parmVal.m_float); - break; - } - case CPASAnimParm::EParmType::Bool: - { - val = parm.GetBoolValue() == parmVal.m_bool ? 0.f : 1.f; - break; - } - case CPASAnimParm::EParmType::Enum: - { - const CPASParmInfo& info = x4_parms[idx]; - range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int; - val = std::fabs(parm.GetEnumValue() - parmVal.m_int); - break; - } - default: break; - } + switch (parm.GetParameterType()) { + case CPASAnimParm::EParmType::Int32: { + const CPASParmInfo& info = x4_parms[idx]; + range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int; + val = std::fabs(parm.GetInt32Value() - parmVal.m_int); + break; + } + case CPASAnimParm::EParmType::UInt32: { + const CPASParmInfo& info = x4_parms[idx]; + range = info.GetWeightMaxValue().m_uint - info.GetWeightMinValue().m_uint; + val = std::fabs(int(parmVal.m_uint) - int(parm.GetUint32Value())); + break; + } + case CPASAnimParm::EParmType::Float: { + const CPASParmInfo& info = x4_parms[idx]; + range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float; + val = std::fabs(parm.GetReal32Value() - parmVal.m_float); + break; + } + case CPASAnimParm::EParmType::Bool: { + val = parm.GetBoolValue() == parmVal.m_bool ? 0.f : 1.f; + break; + } + case CPASAnimParm::EParmType::Enum: { + const CPASParmInfo& info = x4_parms[idx]; + range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int; + val = std::fabs(parm.GetEnumValue() - parmVal.m_int); + break; + } + default: + break; + } - if (range > FLT_EPSILON) - return (val / range) - 1.0f; + if (range > FLT_EPSILON) + return (val / range) - 1.0f; - return (val < FLT_EPSILON ? 1.f : 0.f); + return (val < FLT_EPSILON ? 1.f : 0.f); } -float CPASAnimState::ComputeAngularPercentErrorWeight(u32 idx, const CPASAnimParm& parm, CPASAnimParm::UParmValue parmVal) const -{ - float range = 0.f; - float val = 0.f; +float CPASAnimState::ComputeAngularPercentErrorWeight(u32 idx, const CPASAnimParm& parm, + CPASAnimParm::UParmValue parmVal) const { + float range = 0.f; + float val = 0.f; - switch (parm.GetParameterType()) - { - case CPASAnimParm::EParmType::Int32: - { - const CPASParmInfo& info = x4_parms[idx]; - range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int; - val = std::fabs(parmVal.m_int - parm.GetInt32Value()); - break; - } - case CPASAnimParm::EParmType::UInt32: - { - const CPASParmInfo& info = x4_parms[idx]; - range = info.GetWeightMaxValue().m_uint - info.GetWeightMinValue().m_uint; - val = std::fabs(int(parmVal.m_uint) - int(parm.GetUint32Value())); - break; - } - case CPASAnimParm::EParmType::Float: - { - const CPASParmInfo& info = x4_parms[idx]; - range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float; - val = std::fabs(parm.GetReal32Value() - parmVal.m_float); - break; - } - case CPASAnimParm::EParmType::Bool: - { - val = parm.GetBoolValue() == parmVal.m_bool ? 0.f : 1.f; - break; - } - case CPASAnimParm::EParmType::Enum: - { - const CPASParmInfo& info = x4_parms[idx]; - range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int + 1; - val = std::fabs(parm.GetEnumValue() - parmVal.m_int); - break; - } - default: break; - } + switch (parm.GetParameterType()) { + case CPASAnimParm::EParmType::Int32: { + const CPASParmInfo& info = x4_parms[idx]; + range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int; + val = std::fabs(parmVal.m_int - parm.GetInt32Value()); + break; + } + case CPASAnimParm::EParmType::UInt32: { + const CPASParmInfo& info = x4_parms[idx]; + range = info.GetWeightMaxValue().m_uint - info.GetWeightMinValue().m_uint; + val = std::fabs(int(parmVal.m_uint) - int(parm.GetUint32Value())); + break; + } + case CPASAnimParm::EParmType::Float: { + const CPASParmInfo& info = x4_parms[idx]; + range = info.GetWeightMaxValue().m_float - info.GetWeightMinValue().m_float; + val = std::fabs(parm.GetReal32Value() - parmVal.m_float); + break; + } + case CPASAnimParm::EParmType::Bool: { + val = parm.GetBoolValue() == parmVal.m_bool ? 0.f : 1.f; + break; + } + case CPASAnimParm::EParmType::Enum: { + const CPASParmInfo& info = x4_parms[idx]; + range = info.GetWeightMaxValue().m_int - info.GetWeightMinValue().m_int + 1; + val = std::fabs(parm.GetEnumValue() - parmVal.m_int); + break; + } + default: + break; + } - if (range > FLT_EPSILON) - { - float mid = 0.5f * range; - float offset = 1.f - ((val > mid ? range - val : val) / mid); - return zeus::clamp(0.f, offset, 1.f); - } + if (range > FLT_EPSILON) { + float mid = 0.5f * range; + float offset = 1.f - ((val > mid ? range - val : val) / mid); + return zeus::clamp(0.f, offset, 1.f); + } - return (val >= FLT_EPSILON ? 0.f : 1.f); -} + return (val >= FLT_EPSILON ? 0.f : 1.f); } +} // namespace urde diff --git a/Runtime/Character/CPASAnimState.hpp b/Runtime/Character/CPASAnimState.hpp index e30464335..db94422d6 100644 --- a/Runtime/Character/CPASAnimState.hpp +++ b/Runtime/Character/CPASAnimState.hpp @@ -4,28 +4,26 @@ #include "CPASParmInfo.hpp" #include "CPASAnimInfo.hpp" -namespace urde -{ +namespace urde { class CRandom16; class CPASAnimParmData; -class CPASAnimState -{ - s32 x0_id; - std::vector x4_parms; - std::vector x14_anims; - std::vector x24_selectionCache; +class CPASAnimState { + s32 x0_id; + std::vector x4_parms; + std::vector x14_anims; + std::vector x24_selectionCache; + public: - CPASAnimState(CInputStream& in); - CPASAnimState(int stateId); - s32 GetStateId() const {return x0_id;} - s32 GetNumAnims() const { return x14_anims.size(); } - CPASAnimParm GetAnimParmData(s32, u32) const; - s32 PickRandomAnimation(CRandom16 &rand) const; - std::pair FindBestAnimation(const rstl::reserved_vector&, CRandom16&, s32) const; - float ComputeExactMatchWeight(u32, const CPASAnimParm&, CPASAnimParm::UParmValue) const; - float ComputePercentErrorWeight(u32, const CPASAnimParm&, CPASAnimParm::UParmValue) const; - float ComputeAngularPercentErrorWeight(u32, const CPASAnimParm&, CPASAnimParm::UParmValue) const; + CPASAnimState(CInputStream& in); + CPASAnimState(int stateId); + s32 GetStateId() const { return x0_id; } + s32 GetNumAnims() const { return x14_anims.size(); } + CPASAnimParm GetAnimParmData(s32, u32) const; + s32 PickRandomAnimation(CRandom16& rand) const; + std::pair FindBestAnimation(const rstl::reserved_vector&, CRandom16&, s32) const; + float ComputeExactMatchWeight(u32, const CPASAnimParm&, CPASAnimParm::UParmValue) const; + float ComputePercentErrorWeight(u32, const CPASAnimParm&, CPASAnimParm::UParmValue) const; + float ComputeAngularPercentErrorWeight(u32, const CPASAnimParm&, CPASAnimParm::UParmValue) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CPASDatabase.cpp b/Runtime/Character/CPASDatabase.cpp index 060889dcb..a46806a13 100644 --- a/Runtime/Character/CPASDatabase.cpp +++ b/Runtime/Character/CPASDatabase.cpp @@ -2,48 +2,45 @@ #include "CPASAnimParmData.hpp" #include "CRandom16.hpp" -namespace urde -{ +namespace urde { -void CPASDatabase::AddAnimState(CPASAnimState&& state) -{ - auto it = std::lower_bound(x0_states.begin(), x0_states.end(), state, - [](const CPASAnimState& item, const CPASAnimState& test) -> bool {return item.GetStateId() < test.GetStateId();}); - x0_states.insert(it, std::move(state)); +void CPASDatabase::AddAnimState(CPASAnimState&& state) { + auto it = std::lower_bound(x0_states.begin(), x0_states.end(), state, + [](const CPASAnimState& item, const CPASAnimState& test) -> bool { + return item.GetStateId() < test.GetStateId(); + }); + x0_states.insert(it, std::move(state)); } -CPASDatabase::CPASDatabase(CInputStream& in) -{ - in.readUint32Big(); - u32 animStateCount = in.readUint32Big(); - u32 defaultState = in.readUint32Big(); +CPASDatabase::CPASDatabase(CInputStream& in) { + in.readUint32Big(); + u32 animStateCount = in.readUint32Big(); + u32 defaultState = in.readUint32Big(); - x0_states.reserve(animStateCount); - for (u32 i=0 ; i CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, s32 ignoreAnim) const -{ - CRandom16 rnd(4660); - return FindBestAnimation(data, rnd, ignoreAnim); +std::pair CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, s32 ignoreAnim) const { + CRandom16 rnd(4660); + return FindBestAnimation(data, rnd, ignoreAnim); } -std::pair CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, CRandom16& rand, s32 ignoreAnim) const -{ - auto it = rstl::binary_find(x0_states.cbegin(), x0_states.cend(), data.GetStateId(), - [](const CPASAnimState& item) {return item.GetStateId();}); +std::pair CPASDatabase::FindBestAnimation(const CPASAnimParmData& data, CRandom16& rand, + s32 ignoreAnim) const { + auto it = rstl::binary_find(x0_states.cbegin(), x0_states.cend(), data.GetStateId(), + [](const CPASAnimState& item) { return item.GetStateId(); }); - if (it == x0_states.cend()) - return {0.f, -1}; + if (it == x0_states.cend()) + return {0.f, -1}; - return (*it).FindBestAnimation(data.GetAnimParmData(), rand, ignoreAnim); + return (*it).FindBestAnimation(data.GetAnimParmData(), rand, ignoreAnim); } -} +} // namespace urde diff --git a/Runtime/Character/CPASDatabase.hpp b/Runtime/Character/CPASDatabase.hpp index fe1248fb4..7ac561bf6 100644 --- a/Runtime/Character/CPASDatabase.hpp +++ b/Runtime/Character/CPASDatabase.hpp @@ -3,48 +3,42 @@ #include "IOStreams.hpp" #include "CPASAnimState.hpp" -namespace urde -{ +namespace urde { class CRandom16; class CPASAnimParmData; -class CPASDatabase -{ - std::vector x0_states; - s32 x10_defaultState; - void AddAnimState(CPASAnimState&& state); - void SetDefaultState(s32 state) {x10_defaultState = state;} +class CPASDatabase { + std::vector x0_states; + s32 x10_defaultState; + void AddAnimState(CPASAnimState&& state); + void SetDefaultState(s32 state) { x10_defaultState = state; } + public: - CPASDatabase(CInputStream& in); + CPASDatabase(CInputStream& in); - std::pair FindBestAnimation(const CPASAnimParmData&, s32) const; - std::pair FindBestAnimation(const CPASAnimParmData&, CRandom16&, s32) const; - s32 GetDefaultState() const { return x10_defaultState; } - s32 GetNumAnimStates() const { return x0_states.size(); } - const CPASAnimState* GetAnimState(s32 id) const - { - for (const CPASAnimState& state : x0_states) - if (id == state.GetStateId()) - return &state; + std::pair FindBestAnimation(const CPASAnimParmData&, s32) const; + std::pair FindBestAnimation(const CPASAnimParmData&, CRandom16&, s32) const; + s32 GetDefaultState() const { return x10_defaultState; } + s32 GetNumAnimStates() const { return x0_states.size(); } + const CPASAnimState* GetAnimState(s32 id) const { + for (const CPASAnimState& state : x0_states) + if (id == state.GetStateId()) + return &state; - return nullptr; - } - const CPASAnimState* GetAnimStateByIndex(s32 index) const - { - if (index < 0 || index >= x0_states.size()) - return nullptr; + return nullptr; + } + const CPASAnimState* GetAnimStateByIndex(s32 index) const { + if (index < 0 || index >= x0_states.size()) + return nullptr; - return &x0_states.at(index); - } + return &x0_states.at(index); + } - bool HasState(s32 id) const - { - const auto& st = std::find_if(x0_states.begin(), x0_states.end(), - [&id](const CPASAnimState& other)->bool - { return other.GetStateId() == id; }); - return st != x0_states.end(); - } + bool HasState(s32 id) const { + const auto& st = std::find_if(x0_states.begin(), x0_states.end(), + [&id](const CPASAnimState& other) -> bool { return other.GetStateId() == id; }); + return st != x0_states.end(); + } }; -} - +} // namespace urde diff --git a/Runtime/Character/CPASParmInfo.cpp b/Runtime/Character/CPASParmInfo.cpp index 14fc4f5df..505617a79 100644 --- a/Runtime/Character/CPASParmInfo.cpp +++ b/Runtime/Character/CPASParmInfo.cpp @@ -1,40 +1,38 @@ #include "CPASParmInfo.hpp" -namespace urde -{ +namespace urde { -CPASParmInfo::CPASParmInfo(CInputStream& in) -{ - xc_min.m_int = 0; - x10_max.m_int = 0; - x0_type = CPASAnimParm::EParmType(in.readUint32Big()); - x4_weightFunction = EWeightFunction(in.readUint32Big()); - x8_weight = in.readFloatBig(); +CPASParmInfo::CPASParmInfo(CInputStream& in) { + xc_min.m_int = 0; + x10_max.m_int = 0; + x0_type = CPASAnimParm::EParmType(in.readUint32Big()); + x4_weightFunction = EWeightFunction(in.readUint32Big()); + x8_weight = in.readFloatBig(); - switch (x0_type) - { - case CPASAnimParm::EParmType::Int32: - xc_min.m_int = in.readInt32Big(); - x10_max.m_int = in.readInt32Big(); - break; - case CPASAnimParm::EParmType::UInt32: - xc_min.m_uint = in.readUint32Big(); - x10_max.m_uint = in.readUint32Big(); - break; - case CPASAnimParm::EParmType::Float: - xc_min.m_float = in.readFloatBig(); - x10_max.m_float = in.readFloatBig(); - break; - case CPASAnimParm::EParmType::Bool: - xc_min.m_bool = in.readBool(); - x10_max.m_bool = in.readBool(); - break; - case CPASAnimParm::EParmType::Enum: - xc_min.m_int = in.readInt32Big(); - x10_max.m_int = in.readInt32Big(); - break; - default: break; - } + switch (x0_type) { + case CPASAnimParm::EParmType::Int32: + xc_min.m_int = in.readInt32Big(); + x10_max.m_int = in.readInt32Big(); + break; + case CPASAnimParm::EParmType::UInt32: + xc_min.m_uint = in.readUint32Big(); + x10_max.m_uint = in.readUint32Big(); + break; + case CPASAnimParm::EParmType::Float: + xc_min.m_float = in.readFloatBig(); + x10_max.m_float = in.readFloatBig(); + break; + case CPASAnimParm::EParmType::Bool: + xc_min.m_bool = in.readBool(); + x10_max.m_bool = in.readBool(); + break; + case CPASAnimParm::EParmType::Enum: + xc_min.m_int = in.readInt32Big(); + x10_max.m_int = in.readInt32Big(); + break; + default: + break; + } } -} +} // namespace urde diff --git a/Runtime/Character/CPASParmInfo.hpp b/Runtime/Character/CPASParmInfo.hpp index 8aaaacb7b..adaa25ef9 100644 --- a/Runtime/Character/CPASParmInfo.hpp +++ b/Runtime/Character/CPASParmInfo.hpp @@ -3,33 +3,25 @@ #include "IOStreams.hpp" #include "CPASAnimParm.hpp" -namespace urde -{ +namespace urde { -class CPASParmInfo -{ +class CPASParmInfo { public: - enum class EWeightFunction - { - ExactMatch, - PercentError, - AngularPercent, - NoWeight - }; + enum class EWeightFunction { ExactMatch, PercentError, AngularPercent, NoWeight }; + + CPASAnimParm::EParmType x0_type; + EWeightFunction x4_weightFunction; + float x8_weight; + CPASAnimParm::UParmValue xc_min; + CPASAnimParm::UParmValue x10_max; - CPASAnimParm::EParmType x0_type; - EWeightFunction x4_weightFunction; - float x8_weight; - CPASAnimParm::UParmValue xc_min; - CPASAnimParm::UParmValue x10_max; public: - CPASParmInfo(CInputStream& in); - CPASAnimParm::EParmType GetParameterType() const {return x0_type;} - EWeightFunction GetWeightFunction() const { return x4_weightFunction; } - float GetParameterWeight() const { return x8_weight; } - CPASAnimParm::UParmValue GetWeightMinValue() const { return xc_min; } - CPASAnimParm::UParmValue GetWeightMaxValue() const { return x10_max; } + CPASParmInfo(CInputStream& in); + CPASAnimParm::EParmType GetParameterType() const { return x0_type; } + EWeightFunction GetWeightFunction() const { return x4_weightFunction; } + float GetParameterWeight() const { return x8_weight; } + CPASAnimParm::UParmValue GetWeightMinValue() const { return xc_min; } + CPASAnimParm::UParmValue GetWeightMaxValue() const { return x10_max; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CPOINode.cpp b/Runtime/Character/CPOINode.cpp index 34c8c6ac1..428c8539f 100644 --- a/Runtime/Character/CPOINode.cpp +++ b/Runtime/Character/CPOINode.cpp @@ -5,153 +5,111 @@ #include "CSoundPOINode.hpp" #include "CAnimSourceReader.hpp" -namespace urde -{ +namespace urde { -CPOINode::CPOINode(std::string_view name, EPOIType type, const CCharAnimTime& time, - s32 index, bool unique, float weight, s32 e, s32 f) -: x4_(1), - x8_name(name), - x18_type(type), - x1c_time(time), - x24_index(index), - x28_unique(unique), - x2c_weight(weight), - x30_charIdx(e), - x34_flags(f) -{} +CPOINode::CPOINode(std::string_view name, EPOIType type, const CCharAnimTime& time, s32 index, bool unique, + float weight, s32 e, s32 f) +: x4_(1) +, x8_name(name) +, x18_type(type) +, x1c_time(time) +, x24_index(index) +, x28_unique(unique) +, x2c_weight(weight) +, x30_charIdx(e) +, x34_flags(f) {} CPOINode::CPOINode(CInputStream& in) -: x4_(in.readUint16Big()), - x8_name(in.readString()), - x18_type(EPOIType(in.readUint16Big())), - x1c_time(in), - x24_index(in.readInt32Big()), - x28_unique(in.readBool()), - x2c_weight(in.readFloatBig()), - x30_charIdx(in.readInt32Big()), - x34_flags(in.readInt32Big()) -{} +: x4_(in.readUint16Big()) +, x8_name(in.readString()) +, x18_type(EPOIType(in.readUint16Big())) +, x1c_time(in) +, x24_index(in.readInt32Big()) +, x28_unique(in.readBool()) +, x2c_weight(in.readFloatBig()) +, x30_charIdx(in.readInt32Big()) +, x34_flags(in.readInt32Big()) {} -bool CPOINode::operator>(const CPOINode& other) const -{ - return x1c_time < other.x1c_time; -} +bool CPOINode::operator>(const CPOINode& other) const { return x1c_time < other.x1c_time; } -bool CPOINode::operator<(const CPOINode& other) const -{ - return x1c_time > other.x1c_time; -} +bool CPOINode::operator<(const CPOINode& other) const { return x1c_time > other.x1c_time; } template -u32 _getPOIList(const CCharAnimTime& time, - T* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, - const CCharAnimTime& curTime, - const IAnimSourceInfo& animInfo, u32 passedCount) -{ - u32 ret = 0; - if (animInfo.HasPOIData() && stream.size()) - { - CCharAnimTime dur = animInfo.GetAnimationDuration(); - CCharAnimTime targetTime = curTime + time; - if (targetTime >= dur) - targetTime = dur; - - if (passedCount >= stream.size()) - return ret; - - CCharAnimTime nodeTime = stream[passedCount].GetTime(); - while (passedCount < stream.size() && nodeTime <= targetTime) - { - u32 idx = iterator + ret; - if (idx < capacity) - { - listOut[idx] = T::CopyNodeMinusStartTime(stream[passedCount], curTime); - ++ret; - } - ++passedCount; - if (passedCount < stream.size()) - nodeTime = stream[passedCount].GetTime(); - } - } - return ret; -} - -template -u32 _getPOIList(const CCharAnimTime& time, - T* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, - const CCharAnimTime& curTime) -{ - u32 ret = 0; - +u32 _getPOIList(const CCharAnimTime& time, T* listOut, u32 capacity, u32 iterator, u32 unk1, + const std::vector& stream, const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, + u32 passedCount) { + u32 ret = 0; + if (animInfo.HasPOIData() && stream.size()) { + CCharAnimTime dur = animInfo.GetAnimationDuration(); CCharAnimTime targetTime = curTime + time; + if (targetTime >= dur) + targetTime = dur; - for (u32 it = iterator ; it < stream.size() ; ++it) - { - CCharAnimTime nodeTime = stream[it].GetTime(); - if (nodeTime > targetTime) - return ret; - u32 idx = iterator + ret; - if (nodeTime >= curTime && idx < capacity) - { - listOut[idx] = T::CopyNodeMinusStartTime(stream[it], curTime); - ++ret; - } + if (passedCount >= stream.size()) + return ret; + + CCharAnimTime nodeTime = stream[passedCount].GetTime(); + while (passedCount < stream.size() && nodeTime <= targetTime) { + u32 idx = iterator + ret; + if (idx < capacity) { + listOut[idx] = T::CopyNodeMinusStartTime(stream[passedCount], curTime); + ++ret; + } + ++passedCount; + if (passedCount < stream.size()) + nodeTime = stream[passedCount].GetTime(); } - - return ret; + } + return ret; } -template u32 _getPOIList(const CCharAnimTime& time, - CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, - const CCharAnimTime& curTime, - const IAnimSourceInfo& animInfo, u32 passedCount); -template u32 _getPOIList(const CCharAnimTime& time, - CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, - const CCharAnimTime& curTime); +template +u32 _getPOIList(const CCharAnimTime& time, T* listOut, u32 capacity, u32 iterator, u32 unk1, + const std::vector& stream, const CCharAnimTime& curTime) { + u32 ret = 0; -template u32 _getPOIList(const CCharAnimTime& time, - CInt32POINode* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, - const CCharAnimTime& curTime, - const IAnimSourceInfo& animInfo, u32 passedCount); -template u32 _getPOIList(const CCharAnimTime& time, - CInt32POINode* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, + CCharAnimTime targetTime = curTime + time; + + for (u32 it = iterator; it < stream.size(); ++it) { + CCharAnimTime nodeTime = stream[it].GetTime(); + if (nodeTime > targetTime) + return ret; + u32 idx = iterator + ret; + if (nodeTime >= curTime && idx < capacity) { + listOut[idx] = T::CopyNodeMinusStartTime(stream[it], curTime); + ++ret; + } + } + + return ret; +} + +template u32 _getPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32 unk1, const std::vector& stream, const CCharAnimTime& curTime, + const IAnimSourceInfo& animInfo, u32 passedCount); +template u32 _getPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32 unk1, const std::vector& stream, const CCharAnimTime& curTime); + +template u32 _getPOIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, + u32 unk1, const std::vector& stream, + const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, u32 passedCount); +template u32 _getPOIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, + u32 unk1, const std::vector& stream, const CCharAnimTime& curTime); -template u32 _getPOIList(const CCharAnimTime& time, - CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, - const CCharAnimTime& curTime, - const IAnimSourceInfo& animInfo, u32 passedCount); -template u32 _getPOIList(const CCharAnimTime& time, - CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, +template u32 _getPOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, + u32 iterator, u32 unk1, const std::vector& stream, + const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, + u32 passedCount); +template u32 _getPOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, + u32 iterator, u32 unk1, const std::vector& stream, const CCharAnimTime& curTime); -template u32 _getPOIList(const CCharAnimTime& time, - CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, - const CCharAnimTime& curTime, - const IAnimSourceInfo& animInfo, u32 passedCount); -template u32 _getPOIList(const CCharAnimTime& time, - CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, +template u32 _getPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, + u32 unk1, const std::vector& stream, + const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, u32 passedCount); +template u32 _getPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, + u32 unk1, const std::vector& stream, const CCharAnimTime& curTime); -} +} // namespace urde diff --git a/Runtime/Character/CPOINode.hpp b/Runtime/Character/CPOINode.hpp index 41becd1c2..2fcd6f6d8 100644 --- a/Runtime/Character/CPOINode.hpp +++ b/Runtime/Character/CPOINode.hpp @@ -3,68 +3,59 @@ #include "IOStreams.hpp" #include "CCharAnimTime.hpp" -namespace urde -{ +namespace urde { class IAnimSourceInfo; -enum class EPOIType : u16 -{ - Loop = 0, - EmptyBool = 1, - EmptyInt32 = 2, - SoundInt32 = 4, - Particle = 5, - UserEvent = 6, - RandRate = 7, - Sound = 8, +enum class EPOIType : u16 { + Loop = 0, + EmptyBool = 1, + EmptyInt32 = 2, + SoundInt32 = 4, + Particle = 5, + UserEvent = 6, + RandRate = 7, + Sound = 8, }; -class CPOINode -{ +class CPOINode { protected: - u16 x4_ = 1; - std::string x8_name; - EPOIType x18_type; - CCharAnimTime x1c_time; - s32 x24_index; - bool x28_unique; - float x2c_weight; - s32 x30_charIdx = -1; - s32 x34_flags; + u16 x4_ = 1; + std::string x8_name; + EPOIType x18_type; + CCharAnimTime x1c_time; + s32 x24_index; + bool x28_unique; + float x2c_weight; + s32 x30_charIdx = -1; + s32 x34_flags; + public: - CPOINode(std::string_view name, EPOIType type, const CCharAnimTime& time, - s32 index, bool unique, float weight, s32 charIdx, s32 flags); - CPOINode(CInputStream& in); - virtual ~CPOINode() = default; + CPOINode(std::string_view name, EPOIType type, const CCharAnimTime& time, s32 index, bool unique, float weight, + s32 charIdx, s32 flags); + CPOINode(CInputStream& in); + virtual ~CPOINode() = default; - std::string_view GetString() const { return x8_name; } - const CCharAnimTime& GetTime() const { return x1c_time; } - void SetTime(const CCharAnimTime& time) { x1c_time = time; } - EPOIType GetPoiType() const { return x18_type; } - s32 GetIndex() const { return x24_index; } - bool GetUnique() const { return x28_unique; } - float GetWeight() const { return x2c_weight; } - s32 GetCharacterIndex() const { return x30_charIdx; } - s32 GetFlags() const { return x34_flags; } + std::string_view GetString() const { return x8_name; } + const CCharAnimTime& GetTime() const { return x1c_time; } + void SetTime(const CCharAnimTime& time) { x1c_time = time; } + EPOIType GetPoiType() const { return x18_type; } + s32 GetIndex() const { return x24_index; } + bool GetUnique() const { return x28_unique; } + float GetWeight() const { return x2c_weight; } + s32 GetCharacterIndex() const { return x30_charIdx; } + s32 GetFlags() const { return x34_flags; } - bool operator>(const CPOINode& other) const; - bool operator<(const CPOINode& other) const; + bool operator>(const CPOINode& other) const; + bool operator<(const CPOINode& other) const; }; template -u32 _getPOIList(const CCharAnimTime& time, - T* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, - const CCharAnimTime& curTime, - const IAnimSourceInfo& animInfo, u32 passedCount); +u32 _getPOIList(const CCharAnimTime& time, T* listOut, u32 capacity, u32 iterator, u32 unk1, + const std::vector& stream, const CCharAnimTime& curTime, const IAnimSourceInfo& animInfo, + u32 passedCount); template -u32 _getPOIList(const CCharAnimTime& time, - T* listOut, - u32 capacity, u32 iterator, u32 unk1, - const std::vector& stream, - const CCharAnimTime& curTime); - -} +u32 _getPOIList(const CCharAnimTime& time, T* listOut, u32 capacity, u32 iterator, u32 unk1, + const std::vector& stream, const CCharAnimTime& curTime); +} // namespace urde diff --git a/Runtime/Character/CParticleData.cpp b/Runtime/Character/CParticleData.cpp index f2dd2533c..3340b3b1a 100644 --- a/Runtime/Character/CParticleData.cpp +++ b/Runtime/Character/CParticleData.cpp @@ -1,14 +1,12 @@ #include "CParticleData.hpp" -namespace urde -{ +namespace urde { CParticleData::CParticleData(CInputStream& in) -: x0_duration(in.readUint32Big()), - x4_particle(in), - xc_boneName(in.readString()), - x1c_scale(in.readFloatBig()), - x20_parentMode(EParentedMode(in.readUint32Big())) -{} +: x0_duration(in.readUint32Big()) +, x4_particle(in) +, xc_boneName(in.readString()) +, x1c_scale(in.readFloatBig()) +, x20_parentMode(EParentedMode(in.readUint32Big())) {} -} +} // namespace urde diff --git a/Runtime/Character/CParticleData.hpp b/Runtime/Character/CParticleData.hpp index 0b8129944..136c2af08 100644 --- a/Runtime/Character/CParticleData.hpp +++ b/Runtime/Character/CParticleData.hpp @@ -4,46 +4,40 @@ #include "RetroTypes.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { -class CParticleData -{ +class CParticleData { public: - enum class EParentedMode - { - Initial, - ContinuousEmitter, - ContinuousSystem - }; + enum class EParentedMode { Initial, ContinuousEmitter, ContinuousSystem }; + private: - u32 x0_duration = 0; - SObjectTag x4_particle; - std::string xc_boneName = "root"; - float x1c_scale = 1.f; - EParentedMode x20_parentMode = EParentedMode::Initial; + u32 x0_duration = 0; + SObjectTag x4_particle; + std::string xc_boneName = "root"; + float x1c_scale = 1.f; + EParentedMode x20_parentMode = EParentedMode::Initial; + public: - CParticleData() = default; - CParticleData(CInputStream& in); - u32 GetDuration() const { return x0_duration; } - const SObjectTag& GetTag() const { return x4_particle; } - std::string_view GetSegmentName() const { return xc_boneName; } - float GetScale() const { return x1c_scale; } - EParentedMode GetParentedMode() const { return x20_parentMode; } + CParticleData() = default; + CParticleData(CInputStream& in); + u32 GetDuration() const { return x0_duration; } + const SObjectTag& GetTag() const { return x4_particle; } + std::string_view GetSegmentName() const { return xc_boneName; } + float GetScale() const { return x1c_scale; } + EParentedMode GetParentedMode() const { return x20_parentMode; } }; -class CAuxiliaryParticleData -{ - u32 x0_duration = 0; - SObjectTag x4_particle; - zeus::CVector3f xc_translation; - float x18_scale = 1.f; +class CAuxiliaryParticleData { + u32 x0_duration = 0; + SObjectTag x4_particle; + zeus::CVector3f xc_translation; + float x18_scale = 1.f; + public: - u32 GetDuration() const { return x0_duration; } - const SObjectTag& GetTag() const { return x4_particle; } - const zeus::CVector3f& GetTranslation() const { return xc_translation; } - float GetScale() const { return x18_scale; } + u32 GetDuration() const { return x0_duration; } + const SObjectTag& GetTag() const { return x4_particle; } + const zeus::CVector3f& GetTranslation() const { return xc_translation; } + float GetScale() const { return x18_scale; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CParticleDatabase.cpp b/Runtime/Character/CParticleDatabase.cpp index efb6f090b..9afc21380 100644 --- a/Runtime/Character/CParticleDatabase.cpp +++ b/Runtime/Character/CParticleDatabase.cpp @@ -7,517 +7,443 @@ #include "Particle/CParticleSwoosh.hpp" #include "Particle/CParticleElectric.hpp" -namespace urde -{ +namespace urde { -CParticleDatabase::CParticleDatabase() -{ - xb4_24_updatesEnabled = true; - xb4_25_anySystemsDrawnWithModel = false; +CParticleDatabase::CParticleDatabase() { + xb4_24_updatesEnabled = true; + xb4_25_anySystemsDrawnWithModel = false; } -void CParticleDatabase::CacheParticleDesc(const SObjectTag &tag) -{ +void CParticleDatabase::CacheParticleDesc(const SObjectTag& tag) {} +void CParticleDatabase::CacheParticleDesc(const CCharacterInfo::CParticleResData& desc) { + for (CAssetId id : desc.x0_part) { + auto search = x0_particleDescs.find(id); + if (search == x0_particleDescs.cend()) + x0_particleDescs[id] = + std::make_shared>(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), id})); + } + for (CAssetId id : desc.x10_swhc) { + auto search = x14_swooshDescs.find(id); + if (search == x14_swooshDescs.cend()) + x14_swooshDescs[id] = + std::make_shared>(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), id})); + } + for (CAssetId id : desc.x20_elsc) { + auto search = x28_electricDescs.find(id); + if (search == x28_electricDescs.cend()) + x28_electricDescs[id] = + std::make_shared>(g_SimplePool->GetObj(SObjectTag{FOURCC('ELSC'), id})); + } } -void CParticleDatabase::CacheParticleDesc(const CCharacterInfo::CParticleResData& desc) -{ - for (CAssetId id : desc.x0_part) - { - auto search = x0_particleDescs.find(id); - if (search == x0_particleDescs.cend()) - x0_particleDescs[id] = std::make_shared>( - g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), id})); - } - for (CAssetId id : desc.x10_swhc) - { - auto search = x14_swooshDescs.find(id); - if (search == x14_swooshDescs.cend()) - x14_swooshDescs[id] = std::make_shared>( - g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), id})); - } - for (CAssetId id : desc.x20_elsc) - { - auto search = x28_electricDescs.find(id); - if (search == x28_electricDescs.cend()) - x28_electricDescs[id] = std::make_shared>( - g_SimplePool->GetObj(SObjectTag{FOURCC('ELSC'), id})); - } +void CParticleDatabase::SetModulationColorAllActiveEffectsForParticleDB( + const zeus::CColor& color, std::map>& map) { + for (auto& e : map) { + if (e.second) + e.second->SetModulationColor(color); + } } -void CParticleDatabase::SetModulationColorAllActiveEffectsForParticleDB(const zeus::CColor& color, - std::map>& map) -{ - for (auto& e : map) - { - if (e.second) - e.second->SetModulationColor(color); - } +void CParticleDatabase::SetModulationColorAllActiveEffects(const zeus::CColor& color) { + SetModulationColorAllActiveEffectsForParticleDB(color, x3c_rendererDrawLoop); + SetModulationColorAllActiveEffectsForParticleDB(color, x50_firstDrawLoop); + SetModulationColorAllActiveEffectsForParticleDB(color, x64_lastDrawLoop); + SetModulationColorAllActiveEffectsForParticleDB(color, x78_rendererDraw); + SetModulationColorAllActiveEffectsForParticleDB(color, x8c_firstDraw); + SetModulationColorAllActiveEffectsForParticleDB(color, xa0_lastDraw); } -void CParticleDatabase::SetModulationColorAllActiveEffects(const zeus::CColor& color) -{ - SetModulationColorAllActiveEffectsForParticleDB(color, x3c_rendererDrawLoop); - SetModulationColorAllActiveEffectsForParticleDB(color, x50_firstDrawLoop); - SetModulationColorAllActiveEffectsForParticleDB(color, x64_lastDrawLoop); - SetModulationColorAllActiveEffectsForParticleDB(color, x78_rendererDraw); - SetModulationColorAllActiveEffectsForParticleDB(color, x8c_firstDraw); - SetModulationColorAllActiveEffectsForParticleDB(color, xa0_lastDraw); +void CParticleDatabase::SuspendAllActiveEffectsForParticleDB( + CStateManager& mgr, std::map>& map) { + for (auto& e : map) { + e.second->SetParticleEmission(false, mgr); + } } -void CParticleDatabase::SuspendAllActiveEffectsForParticleDB(CStateManager& mgr, - std::map>& map) -{ - for (auto& e : map) - { - e.second->SetParticleEmission(false, mgr); - } -} - -void CParticleDatabase::SuspendAllActiveEffects(CStateManager& stateMgr) -{ - SuspendAllActiveEffectsForParticleDB(stateMgr, x3c_rendererDrawLoop); - SuspendAllActiveEffectsForParticleDB(stateMgr, x50_firstDrawLoop); - SuspendAllActiveEffectsForParticleDB(stateMgr, x64_lastDrawLoop); +void CParticleDatabase::SuspendAllActiveEffects(CStateManager& stateMgr) { + SuspendAllActiveEffectsForParticleDB(stateMgr, x3c_rendererDrawLoop); + SuspendAllActiveEffectsForParticleDB(stateMgr, x50_firstDrawLoop); + SuspendAllActiveEffectsForParticleDB(stateMgr, x64_lastDrawLoop); } void CParticleDatabase::DeleteAllLightsForParticleDB(CStateManager& mgr, - std::map>& map) -{ - for (auto& e : map) - { - e.second->DeleteLight(mgr); - } + std::map>& map) { + for (auto& e : map) { + e.second->DeleteLight(mgr); + } } -void CParticleDatabase::DeleteAllLights(CStateManager& mgr) -{ - DeleteAllLightsForParticleDB(mgr, x3c_rendererDrawLoop); - DeleteAllLightsForParticleDB(mgr, x50_firstDrawLoop); - DeleteAllLightsForParticleDB(mgr, x64_lastDrawLoop); - DeleteAllLightsForParticleDB(mgr, x78_rendererDraw); - DeleteAllLightsForParticleDB(mgr, x8c_firstDraw); - DeleteAllLightsForParticleDB(mgr, xa0_lastDraw); +void CParticleDatabase::DeleteAllLights(CStateManager& mgr) { + DeleteAllLightsForParticleDB(mgr, x3c_rendererDrawLoop); + DeleteAllLightsForParticleDB(mgr, x50_firstDrawLoop); + DeleteAllLightsForParticleDB(mgr, x64_lastDrawLoop); + DeleteAllLightsForParticleDB(mgr, x78_rendererDraw); + DeleteAllLightsForParticleDB(mgr, x8c_firstDraw); + DeleteAllLightsForParticleDB(mgr, xa0_lastDraw); } void CParticleDatabase::UpdateParticleGenDB(float dt, const CPoseAsTransforms& pose, const CCharLayoutInfo& charInfo, - const zeus::CTransform& xf, const zeus::CVector3f& scale, CStateManager& stateMgr, - std::map>& map, bool deleteIfDone) -{ - for (auto it = map.begin() ; it != map.end() ;) - { - CParticleGenInfo& info = *it->second; - if (info.GetIsActive()) - { - if (info.GetType() == EParticleGenType::Normal) - { - CSegId segId = charInfo.GetSegIdFromString(info.GetLocatorName()); - if (segId == 0xff) - { - ++it; - continue; - } - if (!pose.ContainsDataFor(segId)) - { - ++it; - continue; - } - const zeus::CVector3f& off = pose.GetOffset(segId); - switch (info.GetParentedMode()) - { - case CParticleData::EParentedMode::Initial: - { - if (info.GetIsGrabInitialData()) - { - zeus::CTransform segXf( - (info.GetFlags() & 0x10) ? zeus::CMatrix3f::skIdentityMatrix3f : pose.GetTransformMinusOffset(segId), - off * scale); - zeus::CTransform compXf = xf * segXf; - info.SetCurTransform(compXf.getRotation()); - info.SetCurOffset(compXf.origin); - info.SetCurrentTime(0.f); - info.SetIsGrabInitialData(false); - } - - info.SetOrientation(info.GetCurTransform(), stateMgr); - info.SetTranslation(info.GetCurOffset(), stateMgr); - - if (info.GetFlags() & 0x2000) - info.SetGlobalScale(info.GetCurScale() * scale); - else - info.SetGlobalScale(info.GetCurScale()); - - break; - } - case CParticleData::EParentedMode::ContinuousEmitter: - case CParticleData::EParentedMode::ContinuousSystem: - { - if (info.GetIsGrabInitialData()) - { - info.SetCurrentTime(0.f); - info.SetIsGrabInitialData(false); - } - - zeus::CTransform segXf(pose.GetTransformMinusOffset(segId), off * scale); - zeus::CTransform compXf = xf * segXf; - - if (info.GetParentedMode() == CParticleData::EParentedMode::ContinuousEmitter) - { - info.SetTranslation(compXf.origin, stateMgr); - if (info.GetFlags() & 0x10) - info.SetOrientation(xf.getRotation(), stateMgr); - else - info.SetOrientation(compXf.getRotation(), stateMgr); - } - else - { - info.SetGlobalTranslation(compXf.origin, stateMgr); - if (info.GetFlags() & 0x10) - info.SetGlobalOrientation(xf.getRotation(), stateMgr); - else - info.SetGlobalOrientation(compXf.getRotation(), stateMgr); - } - - if (info.GetFlags() & 0x2000) - info.SetGlobalScale(info.GetCurScale() * scale); - else - info.SetGlobalScale(info.GetCurScale()); - - break; - } - default: break; - } - } - - float sec = (info.GetInactiveStartTime() == 0.f) ? 10000000.f : info.GetInactiveStartTime(); - if (info.GetCurrentTime() > sec) - { - info.SetIsActive(false); - info.SetParticleEmission(false, stateMgr); - info.MarkFinishTime(); - if (info.GetFlags() & 1) - info.DestroyParticles(); - } + const zeus::CTransform& xf, const zeus::CVector3f& scale, + CStateManager& stateMgr, + std::map>& map, + bool deleteIfDone) { + for (auto it = map.begin(); it != map.end();) { + CParticleGenInfo& info = *it->second; + if (info.GetIsActive()) { + if (info.GetType() == EParticleGenType::Normal) { + CSegId segId = charInfo.GetSegIdFromString(info.GetLocatorName()); + if (segId == 0xff) { + ++it; + continue; } - - info.Update(dt, stateMgr); - - if (!info.GetIsActive()) - { - if (!info.HasActiveParticles() && info.GetCurrentTime() - info.GetFinishTime() > 5.f && deleteIfDone) - { - info.DeleteLight(stateMgr); - it = map.erase(it); - continue; - } - } - else if (info.IsSystemDeletable()) - { - info.DeleteLight(stateMgr); - it = map.erase(it); - continue; + if (!pose.ContainsDataFor(segId)) { + ++it; + continue; } + const zeus::CVector3f& off = pose.GetOffset(segId); + switch (info.GetParentedMode()) { + case CParticleData::EParentedMode::Initial: { + if (info.GetIsGrabInitialData()) { + zeus::CTransform segXf((info.GetFlags() & 0x10) ? zeus::CMatrix3f::skIdentityMatrix3f + : pose.GetTransformMinusOffset(segId), + off * scale); + zeus::CTransform compXf = xf * segXf; + info.SetCurTransform(compXf.getRotation()); + info.SetCurOffset(compXf.origin); + info.SetCurrentTime(0.f); + info.SetIsGrabInitialData(false); + } - info.OffsetTime(dt); - ++it; + info.SetOrientation(info.GetCurTransform(), stateMgr); + info.SetTranslation(info.GetCurOffset(), stateMgr); + + if (info.GetFlags() & 0x2000) + info.SetGlobalScale(info.GetCurScale() * scale); + else + info.SetGlobalScale(info.GetCurScale()); + + break; + } + case CParticleData::EParentedMode::ContinuousEmitter: + case CParticleData::EParentedMode::ContinuousSystem: { + if (info.GetIsGrabInitialData()) { + info.SetCurrentTime(0.f); + info.SetIsGrabInitialData(false); + } + + zeus::CTransform segXf(pose.GetTransformMinusOffset(segId), off * scale); + zeus::CTransform compXf = xf * segXf; + + if (info.GetParentedMode() == CParticleData::EParentedMode::ContinuousEmitter) { + info.SetTranslation(compXf.origin, stateMgr); + if (info.GetFlags() & 0x10) + info.SetOrientation(xf.getRotation(), stateMgr); + else + info.SetOrientation(compXf.getRotation(), stateMgr); + } else { + info.SetGlobalTranslation(compXf.origin, stateMgr); + if (info.GetFlags() & 0x10) + info.SetGlobalOrientation(xf.getRotation(), stateMgr); + else + info.SetGlobalOrientation(compXf.getRotation(), stateMgr); + } + + if (info.GetFlags() & 0x2000) + info.SetGlobalScale(info.GetCurScale() * scale); + else + info.SetGlobalScale(info.GetCurScale()); + + break; + } + default: + break; + } + } + + float sec = (info.GetInactiveStartTime() == 0.f) ? 10000000.f : info.GetInactiveStartTime(); + if (info.GetCurrentTime() > sec) { + info.SetIsActive(false); + info.SetParticleEmission(false, stateMgr); + info.MarkFinishTime(); + if (info.GetFlags() & 1) + info.DestroyParticles(); + } } + + info.Update(dt, stateMgr); + + if (!info.GetIsActive()) { + if (!info.HasActiveParticles() && info.GetCurrentTime() - info.GetFinishTime() > 5.f && deleteIfDone) { + info.DeleteLight(stateMgr); + it = map.erase(it); + continue; + } + } else if (info.IsSystemDeletable()) { + info.DeleteLight(stateMgr); + it = map.erase(it); + continue; + } + + info.OffsetTime(dt); + ++it; + } } void CParticleDatabase::Update(float dt, const CPoseAsTransforms& pose, const CCharLayoutInfo& charInfo, - const zeus::CTransform& xf, const zeus::CVector3f& scale, CStateManager& stateMgr) -{ - if (!xb4_24_updatesEnabled) - return; + const zeus::CTransform& xf, const zeus::CVector3f& scale, CStateManager& stateMgr) { + if (!xb4_24_updatesEnabled) + return; - UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x3c_rendererDrawLoop, true); - UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x50_firstDrawLoop, true); - UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x64_lastDrawLoop, true); - UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x78_rendererDraw, false); - UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x8c_firstDraw, false); - UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, xa0_lastDraw, false); + UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x3c_rendererDrawLoop, true); + UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x50_firstDrawLoop, true); + UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x64_lastDrawLoop, true); + UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x78_rendererDraw, false); + UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, x8c_firstDraw, false); + UpdateParticleGenDB(dt, pose, charInfo, xf, scale, stateMgr, xa0_lastDraw, false); - xb4_25_anySystemsDrawnWithModel = (x50_firstDrawLoop.size() || x64_lastDrawLoop.size() || x8c_firstDraw.size() || xa0_lastDraw.size()); + xb4_25_anySystemsDrawnWithModel = + (x50_firstDrawLoop.size() || x64_lastDrawLoop.size() || x8c_firstDraw.size() || xa0_lastDraw.size()); } -void CParticleDatabase::RenderParticleGenMap(const std::map>& map) -{ - for (auto& e : map) - { - e.second->Render(); - } +void CParticleDatabase::RenderParticleGenMap(const std::map>& map) { + for (auto& e : map) { + e.second->Render(); + } } void CParticleDatabase::RenderParticleGenMapMasked(const std::map>& map, - int mask, int target) -{ - for (auto& e : map) - { - if ((e.second->GetFlags() & mask) == target) - e.second->Render(); + int mask, int target) { + for (auto& e : map) { + if ((e.second->GetFlags() & mask) == target) + e.second->Render(); + } +} + +void CParticleDatabase::AddToRendererClippedParticleGenMap( + const std::map>& map, const zeus::CFrustum& frustum) { + for (auto& e : map) { + auto bounds = e.second->GetBounds(); + if (bounds && frustum.aabbFrustumTest(*bounds)) + e.second->AddToRenderer(); + } +} + +void CParticleDatabase::AddToRendererClippedParticleGenMapMasked( + const std::map>& map, const zeus::CFrustum& frustum, int mask, + int target) { + for (auto& e : map) { + if ((e.second->GetFlags() & mask) == target) { + auto bounds = e.second->GetBounds(); + if (bounds && frustum.aabbFrustumTest(*bounds)) + e.second->AddToRenderer(); } + } } -void CParticleDatabase::AddToRendererClippedParticleGenMap(const std::map>& map, - const zeus::CFrustum& frustum) -{ - for (auto& e : map) - { - auto bounds = e.second->GetBounds(); - if (bounds && frustum.aabbFrustumTest(*bounds)) - e.second->AddToRenderer(); - } +void CParticleDatabase::RenderSystemsToBeDrawnLastMasked(int mask, int target) const { + RenderParticleGenMapMasked(xa0_lastDraw, mask, target); + RenderParticleGenMapMasked(x64_lastDrawLoop, mask, target); } -void CParticleDatabase::AddToRendererClippedParticleGenMapMasked(const std::map>& map, - const zeus::CFrustum& frustum, int mask, int target) -{ - for (auto& e : map) - { - if ((e.second->GetFlags() & mask) == target) - { - auto bounds = e.second->GetBounds(); - if (bounds && frustum.aabbFrustumTest(*bounds)) - e.second->AddToRenderer(); - } - } +void CParticleDatabase::RenderSystemsToBeDrawnLast() const { + RenderParticleGenMap(xa0_lastDraw); + RenderParticleGenMap(x64_lastDrawLoop); } -void CParticleDatabase::RenderSystemsToBeDrawnLastMasked(int mask, int target) const -{ - RenderParticleGenMapMasked(xa0_lastDraw, mask, target); - RenderParticleGenMapMasked(x64_lastDrawLoop, mask, target); +void CParticleDatabase::RenderSystemsToBeDrawnFirstMasked(int mask, int target) const { + RenderParticleGenMapMasked(x8c_firstDraw, mask, target); + RenderParticleGenMapMasked(x50_firstDrawLoop, mask, target); } -void CParticleDatabase::RenderSystemsToBeDrawnLast() const -{ - RenderParticleGenMap(xa0_lastDraw); - RenderParticleGenMap(x64_lastDrawLoop); +void CParticleDatabase::RenderSystemsToBeDrawnFirst() const { + RenderParticleGenMap(x8c_firstDraw); + RenderParticleGenMap(x50_firstDrawLoop); } -void CParticleDatabase::RenderSystemsToBeDrawnFirstMasked(int mask, int target) const -{ - RenderParticleGenMapMasked(x8c_firstDraw, mask, target); - RenderParticleGenMapMasked(x50_firstDrawLoop, mask, target); +void CParticleDatabase::AddToRendererClippedMasked(const zeus::CFrustum& frustum, int mask, int target) const { + AddToRendererClippedParticleGenMapMasked(x78_rendererDraw, frustum, mask, target); + AddToRendererClippedParticleGenMapMasked(x3c_rendererDrawLoop, frustum, mask, target); } -void CParticleDatabase::RenderSystemsToBeDrawnFirst() const -{ - RenderParticleGenMap(x8c_firstDraw); - RenderParticleGenMap(x50_firstDrawLoop); +void CParticleDatabase::AddToRendererClipped(const zeus::CFrustum& frustum) const { + AddToRendererClippedParticleGenMap(x78_rendererDraw, frustum); + AddToRendererClippedParticleGenMap(x3c_rendererDrawLoop, frustum); } -void CParticleDatabase::AddToRendererClippedMasked(const zeus::CFrustum& frustum, int mask, int target) const -{ - AddToRendererClippedParticleGenMapMasked(x78_rendererDraw, frustum, mask, target); - AddToRendererClippedParticleGenMapMasked(x3c_rendererDrawLoop, frustum, mask, target); +CParticleGenInfo* CParticleDatabase::GetParticleEffect(std::string_view name) const { + auto search = x3c_rendererDrawLoop.find(name.data()); + if (search != x3c_rendererDrawLoop.end()) + return search->second.get(); + search = x50_firstDrawLoop.find(name.data()); + if (search != x50_firstDrawLoop.end()) + return search->second.get(); + search = x64_lastDrawLoop.find(name.data()); + if (search != x64_lastDrawLoop.end()) + return search->second.get(); + search = x78_rendererDraw.find(name.data()); + if (search != x78_rendererDraw.end()) + return search->second.get(); + search = x8c_firstDraw.find(name.data()); + if (search != x8c_firstDraw.end()) + return search->second.get(); + search = xa0_lastDraw.find(name.data()); + if (search != xa0_lastDraw.end()) + return search->second.get(); + return nullptr; } -void CParticleDatabase::AddToRendererClipped(const zeus::CFrustum& frustum) const -{ - AddToRendererClippedParticleGenMap(x78_rendererDraw, frustum); - AddToRendererClippedParticleGenMap(x3c_rendererDrawLoop, frustum); +void CParticleDatabase::SetParticleEffectState(std::string_view name, bool active, CStateManager& mgr) { + if (CParticleGenInfo* info = GetParticleEffect(name)) { + info->SetParticleEmission(active, mgr); + info->SetIsActive(active); + if (!active && (info->GetFlags() & 1) != 0) + info->DestroyParticles(); + info->SetIsGrabInitialData(true); + } } -CParticleGenInfo* CParticleDatabase::GetParticleEffect(std::string_view name) const -{ - auto search = x3c_rendererDrawLoop.find(name.data()); - if (search != x3c_rendererDrawLoop.end()) - return search->second.get(); - search = x50_firstDrawLoop.find(name.data()); - if (search != x50_firstDrawLoop.end()) - return search->second.get(); - search = x64_lastDrawLoop.find(name.data()); - if (search != x64_lastDrawLoop.end()) - return search->second.get(); - search = x78_rendererDraw.find(name.data()); - if (search != x78_rendererDraw.end()) - return search->second.get(); - search = x8c_firstDraw.find(name.data()); - if (search != x8c_firstDraw.end()) - return search->second.get(); - search = xa0_lastDraw.find(name.data()); - if (search != xa0_lastDraw.end()) - return search->second.get(); - return nullptr; -} - -void CParticleDatabase::SetParticleEffectState(std::string_view name, bool active, CStateManager& mgr) -{ - if (CParticleGenInfo* info = GetParticleEffect(name)) - { - info->SetParticleEmission(active, mgr); - info->SetIsActive(active); - if (!active && (info->GetFlags() & 1) != 0) - info->DestroyParticles(); - info->SetIsGrabInitialData(true); - } -} - -void CParticleDatabase::SetCEXTValue(std::string_view name, int idx, float value) -{ - if (CParticleGenInfo* info = GetParticleEffect(name)) - { - static_cast(static_cast(info)-> - GetParticleSystem().get())->SetCEXTValue(idx, value); - } +void CParticleDatabase::SetCEXTValue(std::string_view name, int idx, float value) { + if (CParticleGenInfo* info = GetParticleEffect(name)) { + static_cast(static_cast(info)->GetParticleSystem().get()) + ->SetCEXTValue(idx, value); + } } template -static s32 _getGraphicLightId(const T& system, const U& desc) -{ - if (system->SystemHasLight()) - return s32(desc.GetObjectTag()->id.Value()); - return -1; +static s32 _getGraphicLightId(const T& system, const U& desc) { + if (system->SystemHasLight()) + return s32(desc.GetObjectTag()->id.Value()); + return -1; } void CParticleDatabase::AddAuxiliaryParticleEffect(std::string_view name, int flags, const CAuxiliaryParticleData& data, - const zeus::CVector3f& scale, CStateManager& mgr, TAreaId aid, int lightId) -{ - if (CParticleGenInfo* info = GetParticleEffect(name)) - { - if (!info->GetIsActive()) - { - info->SetParticleEmission(true, mgr); - info->SetIsActive(true); - info->SetIsGrabInitialData(true); - info->SetFlags(flags); - } - return; + const zeus::CVector3f& scale, CStateManager& mgr, TAreaId aid, + int lightId) { + if (CParticleGenInfo* info = GetParticleEffect(name)) { + if (!info->GetIsActive()) { + info->SetParticleEmission(true, mgr); + info->SetIsActive(true); + info->SetIsGrabInitialData(true); + info->SetFlags(flags); } + return; + } - zeus::CVector3f scaleVec; - if (flags & 0x2) - scaleVec.splat(data.GetScale()); - else - scaleVec = scale * data.GetScale(); + zeus::CVector3f scaleVec; + if (flags & 0x2) + scaleVec.splat(data.GetScale()); + else + scaleVec = scale * data.GetScale(); - std::unique_ptr newGen; - switch (data.GetTag().type) - { - case SBIG('PART'): - { - auto search = x0_particleDescs.find(data.GetTag().id); - if (search != x0_particleDescs.end()) - { - auto sys = std::make_shared(*search->second); - newGen = std::make_unique(data.GetTag(), sys, data.GetDuration(), "NOT_A_VALID_LOCATOR", - scaleVec, CParticleData::EParentedMode::Initial, flags, mgr, aid, - lightId + _getGraphicLightId(sys, *search->second), - EParticleGenType::Auxiliary); + std::unique_ptr newGen; + switch (data.GetTag().type) { + case SBIG('PART'): { + auto search = x0_particleDescs.find(data.GetTag().id); + if (search != x0_particleDescs.end()) { + auto sys = std::make_shared(*search->second); + newGen = std::make_unique(data.GetTag(), sys, data.GetDuration(), "NOT_A_VALID_LOCATOR", + scaleVec, CParticleData::EParentedMode::Initial, flags, mgr, + aid, lightId + _getGraphicLightId(sys, *search->second), + EParticleGenType::Auxiliary); - newGen->SetGlobalTranslation(data.GetTranslation(), mgr); - newGen->SetIsGrabInitialData(false); - InsertParticleGen(false, flags, name, std::move(newGen)); - } - break; - } - default: break; + newGen->SetGlobalTranslation(data.GetTranslation(), mgr); + newGen->SetIsGrabInitialData(false); + InsertParticleGen(false, flags, name, std::move(newGen)); } + break; + } + default: + break; + } } void CParticleDatabase::AddParticleEffect(std::string_view name, int flags, const CParticleData& data, - const zeus::CVector3f& scale, CStateManager& mgr, TAreaId aid, - bool oneShot, int lightId) -{ - if (CParticleGenInfo* info = GetParticleEffect(name)) - { - if (!info->GetIsActive()) - { - info->SetParticleEmission(true, mgr); - info->SetIsActive(true); - info->SetIsGrabInitialData(true); - info->SetFlags(flags); - } - return; + const zeus::CVector3f& scale, CStateManager& mgr, TAreaId aid, bool oneShot, + int lightId) { + if (CParticleGenInfo* info = GetParticleEffect(name)) { + if (!info->GetIsActive()) { + info->SetParticleEmission(true, mgr); + info->SetIsActive(true); + info->SetIsGrabInitialData(true); + info->SetFlags(flags); } + return; + } - zeus::CVector3f scaleVec; - if (flags & 0x2) - scaleVec.splat(data.GetScale()); - else - scaleVec = scale * data.GetScale(); + zeus::CVector3f scaleVec; + if (flags & 0x2) + scaleVec.splat(data.GetScale()); + else + scaleVec = scale * data.GetScale(); - std::unique_ptr newGen; - switch (data.GetTag().type) - { - case SBIG('PART'): - { - auto search = x0_particleDescs.find(data.GetTag().id); - if (search != x0_particleDescs.end()) - { - auto sys = std::make_shared(*search->second); - newGen = std::make_unique(data.GetTag(), sys, data.GetDuration(), data.GetSegmentName(), - scaleVec, data.GetParentedMode(), flags, mgr, aid, - lightId + _getGraphicLightId(sys, *search->second), - EParticleGenType::Normal); - } - break; + std::unique_ptr newGen; + switch (data.GetTag().type) { + case SBIG('PART'): { + auto search = x0_particleDescs.find(data.GetTag().id); + if (search != x0_particleDescs.end()) { + auto sys = std::make_shared(*search->second); + newGen = std::make_unique( + data.GetTag(), sys, data.GetDuration(), data.GetSegmentName(), scaleVec, data.GetParentedMode(), flags, mgr, + aid, lightId + _getGraphicLightId(sys, *search->second), EParticleGenType::Normal); } - case SBIG('SWHC'): - { - auto search = x14_swooshDescs.find(data.GetTag().id); - if (search != x14_swooshDescs.end()) - { - auto sys = std::make_shared(*search->second, 0); - newGen = std::make_unique(data.GetTag(), sys, data.GetDuration(), data.GetSegmentName(), - scaleVec, data.GetParentedMode(), flags, mgr, aid, - -1, EParticleGenType::Normal); - } - break; + break; + } + case SBIG('SWHC'): { + auto search = x14_swooshDescs.find(data.GetTag().id); + if (search != x14_swooshDescs.end()) { + auto sys = std::make_shared(*search->second, 0); + newGen = std::make_unique(data.GetTag(), sys, data.GetDuration(), data.GetSegmentName(), + scaleVec, data.GetParentedMode(), flags, mgr, aid, -1, + EParticleGenType::Normal); } - case SBIG('ELSC'): - { - auto search = x28_electricDescs.find(data.GetTag().id); - if (search != x28_electricDescs.end()) - { - auto sys = std::make_shared(*search->second); - newGen = std::make_unique(data.GetTag(), sys, data.GetDuration(), data.GetSegmentName(), - scaleVec, data.GetParentedMode(), flags, mgr, aid, - lightId + _getGraphicLightId(sys, *search->second), - EParticleGenType::Normal); - } - break; - } - default: break; + break; + } + case SBIG('ELSC'): { + auto search = x28_electricDescs.find(data.GetTag().id); + if (search != x28_electricDescs.end()) { + auto sys = std::make_shared(*search->second); + newGen = std::make_unique( + data.GetTag(), sys, data.GetDuration(), data.GetSegmentName(), scaleVec, data.GetParentedMode(), flags, mgr, + aid, lightId + _getGraphicLightId(sys, *search->second), EParticleGenType::Normal); } + break; + } + default: + break; + } - if (newGen) - { - newGen->SetIsActive(true); - newGen->SetParticleEmission(true, mgr); - newGen->SetIsGrabInitialData(true); - InsertParticleGen(oneShot, flags, name, std::move(newGen)); - } + if (newGen) { + newGen->SetIsActive(true); + newGen->SetParticleEmission(true, mgr); + newGen->SetIsGrabInitialData(true); + InsertParticleGen(oneShot, flags, name, std::move(newGen)); + } } void CParticleDatabase::InsertParticleGen(bool oneShot, int flags, std::string_view name, - std::unique_ptr&& gen) -{ - std::map>* useMap; - if (oneShot) - { - if (flags & 0x40) - useMap = &xa0_lastDraw; - else if (flags & 0x20) - useMap = &x8c_firstDraw; - else - useMap = &x78_rendererDraw; - } + std::unique_ptr&& gen) { + std::map>* useMap; + if (oneShot) { + if (flags & 0x40) + useMap = &xa0_lastDraw; + else if (flags & 0x20) + useMap = &x8c_firstDraw; else - { - if (flags & 0x40) - useMap = &x64_lastDrawLoop; - else if (flags & 0x20) - useMap = &x50_firstDrawLoop; - else - useMap = &x3c_rendererDrawLoop; - } + useMap = &x78_rendererDraw; + } else { + if (flags & 0x40) + useMap = &x64_lastDrawLoop; + else if (flags & 0x20) + useMap = &x50_firstDrawLoop; + else + useMap = &x3c_rendererDrawLoop; + } - useMap->insert(std::make_pair(std::string(name), std::move(gen))); + useMap->insert(std::make_pair(std::string(name), std::move(gen))); - if (flags & 0x60) - xb4_25_anySystemsDrawnWithModel = true; + if (flags & 0x60) + xb4_25_anySystemsDrawnWithModel = true; } -} +} // namespace urde diff --git a/Runtime/Character/CParticleDatabase.hpp b/Runtime/Character/CParticleDatabase.hpp index d722a4fa5..5a80112d4 100644 --- a/Runtime/Character/CParticleDatabase.hpp +++ b/Runtime/Character/CParticleDatabase.hpp @@ -9,67 +9,65 @@ #include "Particle/CElectricDescription.hpp" #include -namespace urde -{ +namespace urde { class CPoseAsTransforms; class CCharLayoutInfo; -class CParticleDatabase -{ - std::map>> x0_particleDescs; - std::map>> x14_swooshDescs; - std::map>> x28_electricDescs; - std::map> x3c_rendererDrawLoop; - std::map> x50_firstDrawLoop; - std::map> x64_lastDrawLoop; - std::map> x78_rendererDraw; - std::map> x8c_firstDraw; - std::map> xa0_lastDraw; - bool xb4_24_updatesEnabled : 1; - bool xb4_25_anySystemsDrawnWithModel : 1; +class CParticleDatabase { + std::map>> x0_particleDescs; + std::map>> x14_swooshDescs; + std::map>> x28_electricDescs; + std::map> x3c_rendererDrawLoop; + std::map> x50_firstDrawLoop; + std::map> x64_lastDrawLoop; + std::map> x78_rendererDraw; + std::map> x8c_firstDraw; + std::map> xa0_lastDraw; + bool xb4_24_updatesEnabled : 1; + bool xb4_25_anySystemsDrawnWithModel : 1; + + static void SetModulationColorAllActiveEffectsForParticleDB( + const zeus::CColor& color, std::map>& map); + static void SuspendAllActiveEffectsForParticleDB(CStateManager& mgr, + std::map>& map); + static void DeleteAllLightsForParticleDB(CStateManager& mgr, + std::map>& map); + static void RenderParticleGenMap(const std::map>& map); + static void RenderParticleGenMapMasked(const std::map>& map, int mask, + int target); + static void AddToRendererClippedParticleGenMap(const std::map>& map, + const zeus::CFrustum& frustum); + static void + AddToRendererClippedParticleGenMapMasked(const std::map>& map, + const zeus::CFrustum& frustum, int mask, int target); + static void UpdateParticleGenDB(float dt, const CPoseAsTransforms& pose, const CCharLayoutInfo& charInfo, + const zeus::CTransform& xf, const zeus::CVector3f& vec, CStateManager& stateMgr, + std::map>& map, bool deleteIfDone); - static void SetModulationColorAllActiveEffectsForParticleDB(const zeus::CColor& color, - std::map>& map); - static void SuspendAllActiveEffectsForParticleDB(CStateManager& mgr, - std::map>& map); - static void DeleteAllLightsForParticleDB(CStateManager& mgr, - std::map>& map); - static void RenderParticleGenMap(const std::map>& map); - static void RenderParticleGenMapMasked(const std::map>& map, - int mask, int target); - static void AddToRendererClippedParticleGenMap(const std::map>& map, - const zeus::CFrustum& frustum); - static void AddToRendererClippedParticleGenMapMasked(const std::map>& map, - const zeus::CFrustum& frustum, int mask, int target); - static void UpdateParticleGenDB(float dt, const CPoseAsTransforms& pose, const CCharLayoutInfo& charInfo, - const zeus::CTransform& xf, const zeus::CVector3f& vec, CStateManager& stateMgr, - std::map>& map, bool deleteIfDone); public: - CParticleDatabase(); - void CacheParticleDesc(const SObjectTag& tag); - void CacheParticleDesc(const CCharacterInfo::CParticleResData& desc); - void SetModulationColorAllActiveEffects(const zeus::CColor& color); - void SuspendAllActiveEffects(CStateManager& stateMgr); - void DeleteAllLights(CStateManager& stateMgr); - void Update(float dt, const CPoseAsTransforms& pose, const CCharLayoutInfo& charInfo, const zeus::CTransform& xf, - const zeus::CVector3f& scale, CStateManager& stateMgr); - void RenderSystemsToBeDrawnLastMasked(int mask, int target) const; - void RenderSystemsToBeDrawnLast() const; - void RenderSystemsToBeDrawnFirstMasked(int mask, int target) const; - void RenderSystemsToBeDrawnFirst() const; - void AddToRendererClippedMasked(const zeus::CFrustum& frustum, int mask, int target) const; - void AddToRendererClipped(const zeus::CFrustum& frustum) const; - CParticleGenInfo* GetParticleEffect(std::string_view name) const; - void SetParticleEffectState(std::string_view name, bool active, CStateManager& mgr); - void SetCEXTValue(std::string_view name, int idx, float value); - void AddAuxiliaryParticleEffect(std::string_view name, int flags, const CAuxiliaryParticleData& data, - const zeus::CVector3f& scale, CStateManager& mgr, TAreaId aid, int lightId); - void AddParticleEffect(std::string_view name, int flags, const CParticleData& data, - const zeus::CVector3f& scale, CStateManager& mgr, TAreaId aid, bool oneShot, int lightId); - void InsertParticleGen(bool oneShot, int flags, std::string_view name, - std::unique_ptr&& gen); - bool AreAnySystemsDrawnWithModel() const { return xb4_25_anySystemsDrawnWithModel; } - void SetUpdatesEnabled(bool active) { xb4_24_updatesEnabled = active; } + CParticleDatabase(); + void CacheParticleDesc(const SObjectTag& tag); + void CacheParticleDesc(const CCharacterInfo::CParticleResData& desc); + void SetModulationColorAllActiveEffects(const zeus::CColor& color); + void SuspendAllActiveEffects(CStateManager& stateMgr); + void DeleteAllLights(CStateManager& stateMgr); + void Update(float dt, const CPoseAsTransforms& pose, const CCharLayoutInfo& charInfo, const zeus::CTransform& xf, + const zeus::CVector3f& scale, CStateManager& stateMgr); + void RenderSystemsToBeDrawnLastMasked(int mask, int target) const; + void RenderSystemsToBeDrawnLast() const; + void RenderSystemsToBeDrawnFirstMasked(int mask, int target) const; + void RenderSystemsToBeDrawnFirst() const; + void AddToRendererClippedMasked(const zeus::CFrustum& frustum, int mask, int target) const; + void AddToRendererClipped(const zeus::CFrustum& frustum) const; + CParticleGenInfo* GetParticleEffect(std::string_view name) const; + void SetParticleEffectState(std::string_view name, bool active, CStateManager& mgr); + void SetCEXTValue(std::string_view name, int idx, float value); + void AddAuxiliaryParticleEffect(std::string_view name, int flags, const CAuxiliaryParticleData& data, + const zeus::CVector3f& scale, CStateManager& mgr, TAreaId aid, int lightId); + void AddParticleEffect(std::string_view name, int flags, const CParticleData& data, const zeus::CVector3f& scale, + CStateManager& mgr, TAreaId aid, bool oneShot, int lightId); + void InsertParticleGen(bool oneShot, int flags, std::string_view name, std::unique_ptr&& gen); + bool AreAnySystemsDrawnWithModel() const { return xb4_25_anySystemsDrawnWithModel; } + void SetUpdatesEnabled(bool active) { xb4_24_updatesEnabled = active; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CParticleGenInfo.cpp b/Runtime/Character/CParticleGenInfo.cpp index be0281c95..128b9a0b2 100644 --- a/Runtime/Character/CParticleGenInfo.cpp +++ b/Runtime/Character/CParticleGenInfo.cpp @@ -7,36 +7,31 @@ #include "Graphics/CBooRenderer.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CParticleGenInfo::CParticleGenInfo(const SObjectTag& part, int frameCount, std::string_view boneName, - const zeus::CVector3f& scale, CParticleData::EParentedMode parentMode, - int flags, EParticleGenType type) + const zeus::CVector3f& scale, CParticleData::EParentedMode parentMode, int flags, + EParticleGenType type) : x4_part(part) , xc_seconds(frameCount / 60.f) , x10_boneName(boneName) , x28_parentMode(parentMode) , x2c_flags(flags) , x30_particleScale(scale) -, x80_type(type) -{ -} +, x80_type(type) {} static TUniqueId _initializeLight(const std::weak_ptr& system, CStateManager& stateMgr, TAreaId areaId, - int lightId) -{ - TUniqueId ret = kInvalidUniqueId; - std::shared_ptr systemRef = system.lock(); - if (systemRef->SystemHasLight()) - { - ret = stateMgr.AllocateUniqueId(); - stateMgr.AddObject( - new CGameLight(ret, areaId, false, "ParticleLight", - zeus::CTransform(systemRef->GetOrientation().buildMatrix3f(), systemRef->GetTranslation()), - kInvalidUniqueId, systemRef->GetLight(), u32(lightId), 0, 0.f)); - } - return ret; + int lightId) { + TUniqueId ret = kInvalidUniqueId; + std::shared_ptr systemRef = system.lock(); + if (systemRef->SystemHasLight()) { + ret = stateMgr.AllocateUniqueId(); + stateMgr.AddObject( + new CGameLight(ret, areaId, false, "ParticleLight", + zeus::CTransform(systemRef->GetOrientation().buildMatrix3f(), systemRef->GetTranslation()), + kInvalidUniqueId, systemRef->GetLight(), u32(lightId), 0, 0.f)); + } + return ret; } CParticleGenInfoGeneric::CParticleGenInfoGeneric(const SObjectTag& part, const std::weak_ptr& system, @@ -44,88 +39,76 @@ CParticleGenInfoGeneric::CParticleGenInfoGeneric(const SObjectTag& part, const s const zeus::CVector3f& scale, CParticleData::EParentedMode parentMode, int flags, CStateManager& stateMgr, TAreaId areaId, int lightId, EParticleGenType state) -: CParticleGenInfo(part, frameCount, boneName, scale, parentMode, flags, state), x84_system(system) -{ - if (lightId == -1) - x88_lightId = kInvalidUniqueId; - else - x88_lightId = _initializeLight(system, stateMgr, areaId, lightId); +: CParticleGenInfo(part, frameCount, boneName, scale, parentMode, flags, state), x84_system(system) { + if (lightId == -1) + x88_lightId = kInvalidUniqueId; + else + x88_lightId = _initializeLight(system, stateMgr, areaId, lightId); } void CParticleGenInfoGeneric::AddToRenderer() { g_Renderer->AddParticleGen(*x84_system.get()); } void CParticleGenInfoGeneric::Render() { x84_system->Render(); } -void CParticleGenInfoGeneric::Update(float dt, CStateManager& stateMgr) -{ - x84_system->Update(dt); +void CParticleGenInfoGeneric::Update(float dt, CStateManager& stateMgr) { + x84_system->Update(dt); - if (x88_lightId != kInvalidUniqueId) - { - TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); - if (gl) - gl->SetLight(x84_system->GetLight()); - } + if (x88_lightId != kInvalidUniqueId) { + TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); + if (gl) + gl->SetLight(x84_system->GetLight()); + } } -void CParticleGenInfoGeneric::SetOrientation(const zeus::CTransform& xf, CStateManager& stateMgr) -{ - x84_system->SetOrientation(xf); +void CParticleGenInfoGeneric::SetOrientation(const zeus::CTransform& xf, CStateManager& stateMgr) { + x84_system->SetOrientation(xf); - if (x88_lightId != kInvalidUniqueId) - { - TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); - if (gl) - gl->SetRotation(zeus::CQuaternion(xf.buildMatrix3f())); - } + if (x88_lightId != kInvalidUniqueId) { + TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); + if (gl) + gl->SetRotation(zeus::CQuaternion(xf.buildMatrix3f())); + } } -void CParticleGenInfoGeneric::SetTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr) -{ - x84_system->SetTranslation(trans); +void CParticleGenInfoGeneric::SetTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr) { + x84_system->SetTranslation(trans); - if (x88_lightId != kInvalidUniqueId) - { - TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); - if (gl) - gl->SetTranslation(trans); - } + if (x88_lightId != kInvalidUniqueId) { + TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); + if (gl) + gl->SetTranslation(trans); + } } -void CParticleGenInfoGeneric::SetGlobalOrientation(const zeus::CTransform& xf, CStateManager& stateMgr) -{ - x84_system->SetGlobalOrientation(xf); +void CParticleGenInfoGeneric::SetGlobalOrientation(const zeus::CTransform& xf, CStateManager& stateMgr) { + x84_system->SetGlobalOrientation(xf); - if (x88_lightId != kInvalidUniqueId) - { - TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); - if (gl) - gl->SetRotation(zeus::CQuaternion(xf.buildMatrix3f())); - } + if (x88_lightId != kInvalidUniqueId) { + TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); + if (gl) + gl->SetRotation(zeus::CQuaternion(xf.buildMatrix3f())); + } } -void CParticleGenInfoGeneric::SetGlobalTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr) -{ - x84_system->SetGlobalTranslation(trans); +void CParticleGenInfoGeneric::SetGlobalTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr) { + x84_system->SetGlobalTranslation(trans); - if (x88_lightId != kInvalidUniqueId) - { - TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); - if (gl) - gl->SetTranslation(trans); - } + if (x88_lightId != kInvalidUniqueId) { + TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); + if (gl) + gl->SetTranslation(trans); + } } void CParticleGenInfoGeneric::SetGlobalScale(const zeus::CVector3f& scale) { x84_system->SetGlobalScale(scale); } -void CParticleGenInfoGeneric::SetParticleEmission(bool emission, CStateManager& stateMgr) -{ - x84_system->SetParticleEmission(emission); +void CParticleGenInfoGeneric::SetParticleEmission(bool emission, CStateManager& stateMgr) { + x84_system->SetParticleEmission(emission); - TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); + TCastToPtr gl(stateMgr.ObjectById(x88_lightId)); - if (gl) - gl->SetActive(emission); + if (gl) + gl->SetActive(emission); } bool CParticleGenInfoGeneric::IsSystemDeletable() const { return x84_system->IsSystemDeletable(); } @@ -140,14 +123,12 @@ bool CParticleGenInfoGeneric::HasLight() const { return x84_system->SystemHasLig TUniqueId CParticleGenInfoGeneric::GetLightId() const { return x88_lightId; } -void CParticleGenInfoGeneric::DeleteLight(CStateManager& mgr) -{ - if (x88_lightId != kInvalidUniqueId) - { - mgr.FreeScriptObject(x88_lightId); - x88_lightId = kInvalidUniqueId; - } +void CParticleGenInfoGeneric::DeleteLight(CStateManager& mgr) { + if (x88_lightId != kInvalidUniqueId) { + mgr.FreeScriptObject(x88_lightId); + x88_lightId = kInvalidUniqueId; + } } void CParticleGenInfoGeneric::SetModulationColor(const zeus::CColor& color) { x84_system->SetModulationColor(color); } -} +} // namespace urde diff --git a/Runtime/Character/CParticleGenInfo.hpp b/Runtime/Character/CParticleGenInfo.hpp index 665877b1b..3f6d54c22 100644 --- a/Runtime/Character/CParticleGenInfo.hpp +++ b/Runtime/Character/CParticleGenInfo.hpp @@ -5,112 +5,103 @@ #include "zeus/CVector3f.hpp" #include "zeus/CAABox.hpp" -namespace urde -{ +namespace urde { struct SObjectTag; class CParticleGen; class CStateManager; -enum class EParticleGenType -{ - Normal, - Auxiliary -}; +enum class EParticleGenType { Normal, Auxiliary }; -class CParticleGenInfo -{ - SObjectTag x4_part; - float xc_seconds; - std::string x10_boneName; - float x20_curTime = 0.f; - bool x24_active = false; - CParticleData::EParentedMode x28_parentMode; - s32 x2c_flags; - zeus::CVector3f x30_particleScale; - float x3c_finishTime = 0.f; - bool x40_grabInitialData = false; - zeus::CTransform x44_transform; - zeus::CVector3f x74_offset; - EParticleGenType x80_type; +class CParticleGenInfo { + SObjectTag x4_part; + float xc_seconds; + std::string x10_boneName; + float x20_curTime = 0.f; + bool x24_active = false; + CParticleData::EParentedMode x28_parentMode; + s32 x2c_flags; + zeus::CVector3f x30_particleScale; + float x3c_finishTime = 0.f; + bool x40_grabInitialData = false; + zeus::CTransform x44_transform; + zeus::CVector3f x74_offset; + EParticleGenType x80_type; public: - CParticleGenInfo(const SObjectTag& part, int frameCount, std::string_view boneName, - const zeus::CVector3f& scale, CParticleData::EParentedMode parentMode, - int flags, EParticleGenType type); + CParticleGenInfo(const SObjectTag& part, int frameCount, std::string_view boneName, const zeus::CVector3f& scale, + CParticleData::EParentedMode parentMode, int flags, EParticleGenType type); - virtual ~CParticleGenInfo() = default; - virtual void AddToRenderer() = 0; - virtual void Render() = 0; - virtual void Update(float dt, CStateManager& stateMgr) = 0; - virtual void SetOrientation(const zeus::CTransform& xf, CStateManager& stateMgr) = 0; - virtual void SetTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr) = 0; - virtual void SetGlobalOrientation(const zeus::CTransform& xf, CStateManager& stateMgr) = 0; - virtual void SetGlobalTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr) = 0; - virtual void SetGlobalScale(const zeus::CVector3f& scale) = 0; - virtual void SetParticleEmission(bool, CStateManager& stateMgr) = 0; - virtual bool IsSystemDeletable() const = 0; - virtual std::experimental::optional GetBounds() const = 0; - virtual bool HasActiveParticles() const = 0; - virtual void DestroyParticles() = 0; - virtual bool HasLight() const = 0; - virtual TUniqueId GetLightId() const = 0; - virtual void DeleteLight(CStateManager& stateMgr) = 0; - virtual void SetModulationColor(const zeus::CColor& color) = 0; + virtual ~CParticleGenInfo() = default; + virtual void AddToRenderer() = 0; + virtual void Render() = 0; + virtual void Update(float dt, CStateManager& stateMgr) = 0; + virtual void SetOrientation(const zeus::CTransform& xf, CStateManager& stateMgr) = 0; + virtual void SetTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr) = 0; + virtual void SetGlobalOrientation(const zeus::CTransform& xf, CStateManager& stateMgr) = 0; + virtual void SetGlobalTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr) = 0; + virtual void SetGlobalScale(const zeus::CVector3f& scale) = 0; + virtual void SetParticleEmission(bool, CStateManager& stateMgr) = 0; + virtual bool IsSystemDeletable() const = 0; + virtual std::experimental::optional GetBounds() const = 0; + virtual bool HasActiveParticles() const = 0; + virtual void DestroyParticles() = 0; + virtual bool HasLight() const = 0; + virtual TUniqueId GetLightId() const = 0; + virtual void DeleteLight(CStateManager& stateMgr) = 0; + virtual void SetModulationColor(const zeus::CColor& color) = 0; - void SetFlags(s32 f) { x2c_flags = f; } - s32 GetFlags() const { return x2c_flags; } - void SetIsGrabInitialData(bool g) { x40_grabInitialData = g; } - bool GetIsGrabInitialData() const { return x40_grabInitialData; } - bool GetIsActive() const { return x24_active; } - void SetIsActive(bool a) { x24_active = a; } - void OffsetTime(float dt) { x20_curTime += dt; } - const zeus::CVector3f& GetCurOffset() const { return x74_offset; } - void SetCurOffset(const zeus::CVector3f& offset) { x74_offset = offset; } - const zeus::CTransform& GetCurTransform() const { return x44_transform; } - void SetCurTransform(const zeus::CTransform& xf) { x44_transform = xf; } - const zeus::CVector3f& GetCurScale() const { return x30_particleScale; } - void SetCurScale(const zeus::CVector3f& scale) { x30_particleScale = scale; } - void SetInactiveStartTime(float s) { xc_seconds = s; } - float GetInactiveStartTime() const { return xc_seconds; } - void MarkFinishTime() { x3c_finishTime = x20_curTime; } - float GetFinishTime() const { return x3c_finishTime; } - float GetCurrentTime() const { return x20_curTime; } - void SetCurrentTime(float t) { x20_curTime = t; } - EParticleGenType GetType() const { return x80_type; } + void SetFlags(s32 f) { x2c_flags = f; } + s32 GetFlags() const { return x2c_flags; } + void SetIsGrabInitialData(bool g) { x40_grabInitialData = g; } + bool GetIsGrabInitialData() const { return x40_grabInitialData; } + bool GetIsActive() const { return x24_active; } + void SetIsActive(bool a) { x24_active = a; } + void OffsetTime(float dt) { x20_curTime += dt; } + const zeus::CVector3f& GetCurOffset() const { return x74_offset; } + void SetCurOffset(const zeus::CVector3f& offset) { x74_offset = offset; } + const zeus::CTransform& GetCurTransform() const { return x44_transform; } + void SetCurTransform(const zeus::CTransform& xf) { x44_transform = xf; } + const zeus::CVector3f& GetCurScale() const { return x30_particleScale; } + void SetCurScale(const zeus::CVector3f& scale) { x30_particleScale = scale; } + void SetInactiveStartTime(float s) { xc_seconds = s; } + float GetInactiveStartTime() const { return xc_seconds; } + void MarkFinishTime() { x3c_finishTime = x20_curTime; } + float GetFinishTime() const { return x3c_finishTime; } + float GetCurrentTime() const { return x20_curTime; } + void SetCurrentTime(float t) { x20_curTime = t; } + EParticleGenType GetType() const { return x80_type; } - CParticleData::EParentedMode GetParentedMode() const { return x28_parentMode; } - std::string_view GetLocatorName() const { return x10_boneName; } + CParticleData::EParentedMode GetParentedMode() const { return x28_parentMode; } + std::string_view GetLocatorName() const { return x10_boneName; } }; -class CParticleGenInfoGeneric : public CParticleGenInfo -{ - std::shared_ptr x84_system; - TUniqueId x88_lightId; +class CParticleGenInfoGeneric : public CParticleGenInfo { + std::shared_ptr x84_system; + TUniqueId x88_lightId; public: - CParticleGenInfoGeneric(const SObjectTag& part, const std::weak_ptr& system, - int frames, std::string_view boneName, const zeus::CVector3f& scale, - CParticleData::EParentedMode parentMode, int flags, CStateManager& stateMgr, TAreaId, - int lightId, EParticleGenType state); + CParticleGenInfoGeneric(const SObjectTag& part, const std::weak_ptr& system, int frames, + std::string_view boneName, const zeus::CVector3f& scale, + CParticleData::EParentedMode parentMode, int flags, CStateManager& stateMgr, TAreaId, + int lightId, EParticleGenType state); - void AddToRenderer(); - void Render(); - void Update(float dt, CStateManager& stateMgr); - void SetOrientation(const zeus::CTransform& xf, CStateManager& stateMgr); - void SetTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr); - void SetGlobalOrientation(const zeus::CTransform& xf, CStateManager& stateMgr); - void SetGlobalTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr); - void SetGlobalScale(const zeus::CVector3f& scale); - void SetParticleEmission(bool, CStateManager& stateMgr); - bool IsSystemDeletable() const; - std::experimental::optional GetBounds() const; - bool HasActiveParticles() const; - void DestroyParticles(); - bool HasLight() const; - TUniqueId GetLightId() const; - void DeleteLight(CStateManager& mgr); - void SetModulationColor(const zeus::CColor& color); - const std::shared_ptr GetParticleSystem() const { return x84_system; } + void AddToRenderer(); + void Render(); + void Update(float dt, CStateManager& stateMgr); + void SetOrientation(const zeus::CTransform& xf, CStateManager& stateMgr); + void SetTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr); + void SetGlobalOrientation(const zeus::CTransform& xf, CStateManager& stateMgr); + void SetGlobalTranslation(const zeus::CVector3f& trans, CStateManager& stateMgr); + void SetGlobalScale(const zeus::CVector3f& scale); + void SetParticleEmission(bool, CStateManager& stateMgr); + bool IsSystemDeletable() const; + std::experimental::optional GetBounds() const; + bool HasActiveParticles() const; + void DestroyParticles(); + bool HasLight() const; + TUniqueId GetLightId() const; + void DeleteLight(CStateManager& mgr); + void SetModulationColor(const zeus::CColor& color); + const std::shared_ptr GetParticleSystem() const { return x84_system; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CParticlePOINode.cpp b/Runtime/Character/CParticlePOINode.cpp index ed6f4bb2c..62e3f136b 100644 --- a/Runtime/Character/CParticlePOINode.cpp +++ b/Runtime/Character/CParticlePOINode.cpp @@ -1,21 +1,17 @@ #include "CParticlePOINode.hpp" #include "CAnimSourceReader.hpp" -namespace urde -{ +namespace urde { -CParticlePOINode::CParticlePOINode() -: CPOINode("root", EPOIType::Particle, CCharAnimTime(), -1, false, 1.f, -1, 0) {} +CParticlePOINode::CParticlePOINode() : CPOINode("root", EPOIType::Particle, CCharAnimTime(), -1, false, 1.f, -1, 0) {} -CParticlePOINode::CParticlePOINode(CInputStream& in) -: CPOINode(in), x38_data(in) {} +CParticlePOINode::CParticlePOINode(CInputStream& in) : CPOINode(in), x38_data(in) {} CParticlePOINode CParticlePOINode::CopyNodeMinusStartTime(const CParticlePOINode& node, - const CCharAnimTime& startTime) -{ - CParticlePOINode ret = node; - ret.x1c_time -= startTime; - return ret; + const CCharAnimTime& startTime) { + CParticlePOINode ret = node; + ret.x1c_time -= startTime; + return ret; } -} +} // namespace urde diff --git a/Runtime/Character/CParticlePOINode.hpp b/Runtime/Character/CParticlePOINode.hpp index 83183f2a7..31af931cb 100644 --- a/Runtime/Character/CParticlePOINode.hpp +++ b/Runtime/Character/CParticlePOINode.hpp @@ -3,21 +3,18 @@ #include "CPOINode.hpp" #include "CParticleData.hpp" -namespace urde -{ +namespace urde { class IAnimSourceInfo; -class CParticlePOINode : public CPOINode -{ - CParticleData x38_data; -public: - CParticlePOINode(); - CParticlePOINode(CInputStream& in); - const CParticleData& GetParticleData() const { return x38_data; } +class CParticlePOINode : public CPOINode { + CParticleData x38_data; - static CParticlePOINode CopyNodeMinusStartTime(const CParticlePOINode& node, - const CCharAnimTime& startTime); +public: + CParticlePOINode(); + CParticlePOINode(CInputStream& in); + const CParticleData& GetParticleData() const { return x38_data; } + + static CParticlePOINode CopyNodeMinusStartTime(const CParticlePOINode& node, const CCharAnimTime& startTime); }; -} - +} // namespace urde diff --git a/Runtime/Character/CPoseAsTransforms.cpp b/Runtime/Character/CPoseAsTransforms.cpp index 702a25ccd..c9aaed3f1 100644 --- a/Runtime/Character/CPoseAsTransforms.cpp +++ b/Runtime/Character/CPoseAsTransforms.cpp @@ -1,74 +1,59 @@ #include "CPoseAsTransforms.hpp" #include "CCharLayoutInfo.hpp" -namespace urde -{ +namespace urde { -CPoseAsTransforms::CPoseAsTransforms(u8 boneCount) -: x1_count(boneCount), xd0_transformArr(new Transform[boneCount]) -{} +CPoseAsTransforms::CPoseAsTransforms(u8 boneCount) : x1_count(boneCount), xd0_transformArr(new Transform[boneCount]) {} -bool CPoseAsTransforms::ContainsDataFor(const CSegId& id) const -{ - const std::pair& link = x8_links[id]; - if (link.first != 0xff || link.second != 0xff) - return true; - return false; +bool CPoseAsTransforms::ContainsDataFor(const CSegId& id) const { + const std::pair& link = x8_links[id]; + if (link.first != 0xff || link.second != 0xff) + return true; + return false; } -void CPoseAsTransforms::Clear() -{ - for (u32 i=0 ; i<100 ; ++i) - x8_links[i] = std::make_pair(CSegId(), CSegId()); - xd4_lastInserted = 0; - x0_nextId = 0; +void CPoseAsTransforms::Clear() { + for (u32 i = 0; i < 100; ++i) + x8_links[i] = std::make_pair(CSegId(), CSegId()); + xd4_lastInserted = 0; + x0_nextId = 0; } -void CPoseAsTransforms::AccumulateScaledTransform(const CSegId& id, - zeus::CMatrix3f& rotation, - float scale) const -{ - rotation.addScaledMatrix(GetRotation(id), scale); +void CPoseAsTransforms::AccumulateScaledTransform(const CSegId& id, zeus::CMatrix3f& rotation, float scale) const { + rotation.addScaledMatrix(GetRotation(id), scale); } -const zeus::CTransform& CPoseAsTransforms::GetTransform(const CSegId& id) const -{ - const std::pair& link = x8_links[id]; - return xd0_transformArr[link.second].m_originToAccum; +const zeus::CTransform& CPoseAsTransforms::GetTransform(const CSegId& id) const { + const std::pair& link = x8_links[id]; + return xd0_transformArr[link.second].m_originToAccum; } -const zeus::CTransform& CPoseAsTransforms::GetRestToAccumTransform(const CSegId& id) const -{ - const std::pair& link = x8_links[id]; - return xd0_transformArr[link.second].m_restPoseToAccum; +const zeus::CTransform& CPoseAsTransforms::GetRestToAccumTransform(const CSegId& id) const { + const std::pair& link = x8_links[id]; + return xd0_transformArr[link.second].m_restPoseToAccum; } -const zeus::CVector3f& CPoseAsTransforms::GetOffset(const CSegId& id) const -{ - const std::pair& link = x8_links[id]; - return xd0_transformArr[link.second].m_originToAccum.origin; +const zeus::CVector3f& CPoseAsTransforms::GetOffset(const CSegId& id) const { + const std::pair& link = x8_links[id]; + return xd0_transformArr[link.second].m_originToAccum.origin; } -const zeus::CMatrix3f& CPoseAsTransforms::GetRotation(const CSegId& id) const -{ - const std::pair& link = x8_links[id]; - return xd0_transformArr[link.second].m_originToAccum.basis; +const zeus::CMatrix3f& CPoseAsTransforms::GetRotation(const CSegId& id) const { + const std::pair& link = x8_links[id]; + return xd0_transformArr[link.second].m_originToAccum.basis; } -void CPoseAsTransforms::Insert(const CSegId& id, - const zeus::CMatrix3f& rotation, - const zeus::CVector3f& offset, - const zeus::CVector3f& restOffset) -{ - Transform& xfOut = xd0_transformArr[x0_nextId]; - xfOut.m_originToAccum = zeus::CTransform(rotation, offset); - xfOut.m_restPoseToAccum = xfOut.m_originToAccum * zeus::CTransform::Translate(-restOffset); +void CPoseAsTransforms::Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset, + const zeus::CVector3f& restOffset) { + Transform& xfOut = xd0_transformArr[x0_nextId]; + xfOut.m_originToAccum = zeus::CTransform(rotation, offset); + xfOut.m_restPoseToAccum = xfOut.m_originToAccum * zeus::CTransform::Translate(-restOffset); - std::pair& link = x8_links[id]; - link.first = xd4_lastInserted; - link.second = x0_nextId; - xd4_lastInserted = id; - ++x0_nextId; + std::pair& link = x8_links[id]; + link.first = xd4_lastInserted; + link.second = x0_nextId; + xd4_lastInserted = id; + ++x0_nextId; } -} +} // namespace urde diff --git a/Runtime/Character/CPoseAsTransforms.hpp b/Runtime/Character/CPoseAsTransforms.hpp index cac5eb491..d0e8e1081 100644 --- a/Runtime/Character/CPoseAsTransforms.hpp +++ b/Runtime/Character/CPoseAsTransforms.hpp @@ -4,39 +4,35 @@ #include "CSegId.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { class CCharLayoutInfo; -class CPoseAsTransforms -{ +class CPoseAsTransforms { public: - struct Transform - { - zeus::CTransform m_originToAccum; - zeus::CTransform m_restPoseToAccum; - }; + struct Transform { + zeus::CTransform m_originToAccum; + zeus::CTransform m_restPoseToAccum; + }; + private: - CSegId x0_nextId = 0; - CSegId x1_count; - std::pair x8_links[100]; - std::unique_ptr xd0_transformArr; - CSegId xd4_lastInserted = 0; + CSegId x0_nextId = 0; + CSegId x1_count; + std::pair x8_links[100]; + std::unique_ptr xd0_transformArr; + CSegId xd4_lastInserted = 0; + public: - CPoseAsTransforms(u8 boneCount); - bool ContainsDataFor(const CSegId& id) const; - void Clear(); - void AccumulateScaledTransform(const CSegId& id, zeus::CMatrix3f& rotation, float scale) const; - const zeus::CTransform& GetTransform(const CSegId& id) const; - const zeus::CTransform& GetRestToAccumTransform(const CSegId& id) const; - const zeus::CVector3f& GetOffset(const CSegId& id) const; - const zeus::CMatrix3f& GetRotation(const CSegId& id) const; - const zeus::CMatrix3f& GetTransformMinusOffset(const CSegId& id) const { return GetRotation(id); } - void Insert(const CSegId& id, - const zeus::CMatrix3f& rotation, - const zeus::CVector3f& offset, - const zeus::CVector3f& restOffset); + CPoseAsTransforms(u8 boneCount); + bool ContainsDataFor(const CSegId& id) const; + void Clear(); + void AccumulateScaledTransform(const CSegId& id, zeus::CMatrix3f& rotation, float scale) const; + const zeus::CTransform& GetTransform(const CSegId& id) const; + const zeus::CTransform& GetRestToAccumTransform(const CSegId& id) const; + const zeus::CVector3f& GetOffset(const CSegId& id) const; + const zeus::CMatrix3f& GetRotation(const CSegId& id) const; + const zeus::CMatrix3f& GetTransformMinusOffset(const CSegId& id) const { return GetRotation(id); } + void Insert(const CSegId& id, const zeus::CMatrix3f& rotation, const zeus::CVector3f& offset, + const zeus::CVector3f& restOffset); }; -} - +} // namespace urde diff --git a/Runtime/Character/CPrimitive.cpp b/Runtime/Character/CPrimitive.cpp index a2635ccdc..5e1ebe91e 100644 --- a/Runtime/Character/CPrimitive.cpp +++ b/Runtime/Character/CPrimitive.cpp @@ -1,13 +1,11 @@ #include "CPrimitive.hpp" -namespace urde -{ +namespace urde { -CPrimitive::CPrimitive(CInputStream& in) -{ - x0_animId = in.readUint32Big(); - x4_animIdx = in.readUint32Big(); - x8_animName = in.readString(); +CPrimitive::CPrimitive(CInputStream& in) { + x0_animId = in.readUint32Big(); + x4_animIdx = in.readUint32Big(); + x8_animName = in.readString(); } -} +} // namespace urde diff --git a/Runtime/Character/CPrimitive.hpp b/Runtime/Character/CPrimitive.hpp index c22ea62e8..a3c2195a4 100644 --- a/Runtime/Character/CPrimitive.hpp +++ b/Runtime/Character/CPrimitive.hpp @@ -3,21 +3,19 @@ #include "IOStreams.hpp" #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { + +class CPrimitive { + CAssetId x0_animId; + u32 x4_animIdx; + std::string x8_animName; -class CPrimitive -{ - CAssetId x0_animId; - u32 x4_animIdx; - std::string x8_animName; public: - CPrimitive(CInputStream& in); - CAssetId GetAnimResId() const { return x0_animId; } - u32 GetAnimDbIdx() const { return x4_animIdx; } - std::string_view GetName() const { return x8_animName; } - bool operator<(const CPrimitive& other) const { return x8_animName < other.x8_animName; } + CPrimitive(CInputStream& in); + CAssetId GetAnimResId() const { return x0_animId; } + u32 GetAnimDbIdx() const { return x4_animIdx; } + std::string_view GetName() const { return x8_animName; } + bool operator<(const CPrimitive& other) const { return x8_animName < other.x8_animName; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CRagDoll.cpp b/Runtime/Character/CRagDoll.cpp index 6ca8272b2..587a30061 100644 --- a/Runtime/Character/CRagDoll.cpp +++ b/Runtime/Character/CRagDoll.cpp @@ -6,363 +6,314 @@ #include "Collision/CCollisionInfo.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { -void CRagDoll::CRagDollLengthConstraint::Update() -{ - zeus::CVector3f delta = x4_p2->x4_curPos - x0_p1->x4_curPos; - float magSq = delta.magSquared(); - float lenSq = x8_length * x8_length; - bool doSolve = true; - switch (xc_ineqType) - { - case 1: // Min - doSolve = magSq < lenSq; - break; - case 2: // Max - doSolve = magSq > lenSq; - break; - default: - break; - } - if (!doSolve) - return; - zeus::CVector3f solveVec = delta * (lenSq / (magSq + lenSq) - 0.5f); - x0_p1->x4_curPos -= solveVec; - x4_p2->x4_curPos += solveVec; +void CRagDoll::CRagDollLengthConstraint::Update() { + zeus::CVector3f delta = x4_p2->x4_curPos - x0_p1->x4_curPos; + float magSq = delta.magSquared(); + float lenSq = x8_length * x8_length; + bool doSolve = true; + switch (xc_ineqType) { + case 1: // Min + doSolve = magSq < lenSq; + break; + case 2: // Max + doSolve = magSq > lenSq; + break; + default: + break; + } + if (!doSolve) + return; + zeus::CVector3f solveVec = delta * (lenSq / (magSq + lenSq) - 0.5f); + x0_p1->x4_curPos -= solveVec; + x4_p2->x4_curPos += solveVec; } -void CRagDoll::CRagDollJointConstraint::Update() -{ - // L_hip, R_shoulder, L_shoulder, L_hip, L_knee, L_ankle - zeus::CVector3f P4ToP5 = x10_p5->x4_curPos - xc_p4->x4_curPos; // L_hip->L_knee - zeus::CVector3f cross = P4ToP5.cross( - (x8_p3->x4_curPos - x0_p1->x4_curPos).cross(x4_p2->x4_curPos - x0_p1->x4_curPos)); - // L_hip->L_knee X (L_hip->L_shoulder X L_hip->R_shoulder) - if (cross.canBeNormalized()) - { - zeus::CVector3f hipUp = cross.cross(P4ToP5).normalized(); - float dot = (x14_p6->x4_curPos - x10_p5->x4_curPos).dot(hipUp); - if (dot > 0.f) - { - zeus::CVector3f solveVec = 0.5f * dot * hipUp; - x14_p6->x4_curPos -= solveVec; - x10_p5->x4_curPos += solveVec; - } +void CRagDoll::CRagDollJointConstraint::Update() { + // L_hip, R_shoulder, L_shoulder, L_hip, L_knee, L_ankle + zeus::CVector3f P4ToP5 = x10_p5->x4_curPos - xc_p4->x4_curPos; // L_hip->L_knee + zeus::CVector3f cross = + P4ToP5.cross((x8_p3->x4_curPos - x0_p1->x4_curPos).cross(x4_p2->x4_curPos - x0_p1->x4_curPos)); + // L_hip->L_knee X (L_hip->L_shoulder X L_hip->R_shoulder) + if (cross.canBeNormalized()) { + zeus::CVector3f hipUp = cross.cross(P4ToP5).normalized(); + float dot = (x14_p6->x4_curPos - x10_p5->x4_curPos).dot(hipUp); + if (dot > 0.f) { + zeus::CVector3f solveVec = 0.5f * dot * hipUp; + x14_p6->x4_curPos -= solveVec; + x10_p5->x4_curPos += solveVec; } + } } -void CRagDoll::CRagDollPlaneConstraint::Update() -{ - zeus::CVector3f P1ToP2 = (x4_p2->x4_curPos - x0_p1->x4_curPos).normalized(); - float dot = P1ToP2.dot(xc_p4->x4_curPos - x8_p3->x4_curPos); - if (dot < 0.f) - { - zeus::CVector3f solveVec = 0.5f * dot * P1ToP2; - xc_p4->x4_curPos -= solveVec; - x10_p5->x4_curPos += solveVec; - } +void CRagDoll::CRagDollPlaneConstraint::Update() { + zeus::CVector3f P1ToP2 = (x4_p2->x4_curPos - x0_p1->x4_curPos).normalized(); + float dot = P1ToP2.dot(xc_p4->x4_curPos - x8_p3->x4_curPos); + if (dot < 0.f) { + zeus::CVector3f solveVec = 0.5f * dot * P1ToP2; + xc_p4->x4_curPos -= solveVec; + x10_p5->x4_curPos += solveVec; + } } CRagDoll::CRagDoll(float normalGravity, float floatingGravity, float overTime, u32 flags) -: x44_normalGravity(normalGravity), x48_floatingGravity(floatingGravity), x50_overTimer(overTime) -{ - x68_27_continueSmallMovements = bool(flags & 0x1); - x68_28_noOverTimer = bool(flags & 0x2); - x68_29_noAiCollision = bool(flags & 0x4); +: x44_normalGravity(normalGravity), x48_floatingGravity(floatingGravity), x50_overTimer(overTime) { + x68_27_continueSmallMovements = bool(flags & 0x1); + x68_28_noOverTimer = bool(flags & 0x2); + x68_29_noAiCollision = bool(flags & 0x4); } -void CRagDoll::AccumulateForces(float dt, float waterTop) -{ - float fps = 1.f / dt; - x64_angTimer += dt; - if (x64_angTimer > 4.f) - x64_angTimer -= 4.f; - float targetZ = std::sin(zeus::degToRad(90.f) * x64_angTimer) * 0.1f + (waterTop - 0.2f); - zeus::CVector3f centerOfVolume; - float totalVolume = 0.f; +void CRagDoll::AccumulateForces(float dt, float waterTop) { + float fps = 1.f / dt; + x64_angTimer += dt; + if (x64_angTimer > 4.f) + x64_angTimer -= 4.f; + float targetZ = std::sin(zeus::degToRad(90.f) * x64_angTimer) * 0.1f + (waterTop - 0.2f); + zeus::CVector3f centerOfVolume; + float totalVolume = 0.f; + for (auto& particle : x4_particles) { + float volume = particle.x10_radius * particle.x10_radius * particle.x10_radius; + totalVolume += volume; + centerOfVolume += particle.x4_curPos * volume; + float fromTargetZ = particle.x4_curPos.z() - targetZ; + float verticalAcc = x48_floatingGravity; + float termVelCoefficient = 0.f; + if (std::fabs(fromTargetZ) < 0.5f) { + termVelCoefficient = 0.5f * fromTargetZ / 0.5f + 0.5f; + verticalAcc = x48_floatingGravity * -fromTargetZ / 0.5f; + } else if (fromTargetZ > 0.f) { + verticalAcc = x44_normalGravity; + termVelCoefficient = 1.f; + } + particle.x20_velocity.z() += verticalAcc; + zeus::CVector3f vel = (particle.x4_curPos - particle.x14_prevPos) * fps; + float velMag = vel.magnitude(); + if (velMag > FLT_EPSILON) { + particle.x20_velocity -= + vel * (1.f / velMag) * + ((velMag * velMag * 0.75f * (1.2f * termVelCoefficient + 1000.f * (1.f - termVelCoefficient))) / + (8000.f * particle.x10_radius)); + } + } + zeus::CVector3f averageTorque; + centerOfVolume = centerOfVolume / totalVolume; + for (const auto& particle : x4_particles) { + float volume = particle.x10_radius * particle.x10_radius * particle.x10_radius; + averageTorque += (particle.x4_curPos - centerOfVolume).cross(particle.x4_curPos - particle.x14_prevPos) * volume; + } + averageTorque = averageTorque * (fps / totalVolume); + if (averageTorque.canBeNormalized()) for (auto& particle : x4_particles) - { - float volume = particle.x10_radius * particle.x10_radius * particle.x10_radius; - totalVolume += volume; - centerOfVolume += particle.x4_curPos * volume; - float fromTargetZ = particle.x4_curPos.z() - targetZ; - float verticalAcc = x48_floatingGravity; - float termVelCoefficient = 0.f; - if (std::fabs(fromTargetZ) < 0.5f) - { - termVelCoefficient = 0.5f * fromTargetZ / 0.5f + 0.5f; - verticalAcc = x48_floatingGravity * -fromTargetZ / 0.5f; - } - else if (fromTargetZ > 0.f) - { - verticalAcc = x44_normalGravity; - termVelCoefficient = 1.f; - } - particle.x20_velocity.z() += verticalAcc; - zeus::CVector3f vel = (particle.x4_curPos - particle.x14_prevPos) * fps; - float velMag = vel.magnitude(); - if (velMag > FLT_EPSILON) - { - particle.x20_velocity -= vel * (1.f / velMag) * - ((velMag * velMag * 0.75f * (1.2f * termVelCoefficient + 1000.f * - (1.f - termVelCoefficient))) / (8000.f * particle.x10_radius)); - } + particle.x20_velocity -= averageTorque.cross(particle.x4_curPos - centerOfVolume) * 25.f; +} + +void CRagDoll::AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float radius) { + x4_particles.emplace_back(id, curPos, radius, prevPos); +} + +void CRagDoll::AddLengthConstraint(int i1, int i2) { + x14_lengthConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], + (x4_particles[i1].x4_curPos - x4_particles[i2].x4_curPos).magnitude(), 0); +} + +void CRagDoll::AddMaxLengthConstraint(int i1, int i2, float length) { + x14_lengthConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], length, 2); +} + +void CRagDoll::AddMinLengthConstraint(int i1, int i2, float length) { + x14_lengthConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], length, 1); +} + +void CRagDoll::AddJointConstraint(int i1, int i2, int i3, int i4, int i5, int i6) { + x24_jointConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], &x4_particles[i3], &x4_particles[i4], + &x4_particles[i5], &x4_particles[i6]); +} + +zeus::CQuaternion CRagDoll::BoneAlign(CHierarchyPoseBuilder& pb, const CCharLayoutInfo& charInfo, int i1, int i2, + const zeus::CQuaternion& q) { + zeus::CVector3f fromParent = charInfo.GetFromParentUnrotated(x4_particles[i2].x0_id); + zeus::CVector3f delta = x4_particles[i2].x4_curPos - x4_particles[i1].x4_curPos; + delta = q.inverse().transform(delta); + zeus::CQuaternion ret = zeus::CQuaternion::shortestRotationArc(fromParent, delta); + pb.GetTreeMap()[x4_particles[i1].x0_id].x4_rotation = ret; + return ret; +} + +zeus::CAABox CRagDoll::CalculateRenderBounds() const { + zeus::CAABox aabb; + for (const auto& particle : x4_particles) { + aabb.accumulateBounds( + zeus::CAABox(particle.x4_curPos - particle.x10_radius, particle.x4_curPos + particle.x10_radius)); + } + return aabb; +} + +void CRagDoll::CheckStatic(float dt) { + x4c_impactCount = 0; + x54_impactVel = 0.f; + float halfDt = 0.5f * dt; + float halfDeltaUnitSq = halfDt * halfDt; + x58_averageVel = zeus::CVector3f::skZero; + bool movingSlowly = true; + for (auto& particle : x4_particles) { + zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos; + x58_averageVel += delta; + if (delta.magSquared() > halfDeltaUnitSq) + movingSlowly = false; + if (particle.x3c_24_impactPending) { + x4c_impactCount += 1; + x54_impactVel = std::max(particle.x38_impactFrameVel, x54_impactVel); } - zeus::CVector3f averageTorque; - centerOfVolume = centerOfVolume / totalVolume; - for (const auto& particle : x4_particles) - { - float volume = particle.x10_radius * particle.x10_radius * particle.x10_radius; - averageTorque += (particle.x4_curPos - centerOfVolume). - cross(particle.x4_curPos - particle.x14_prevPos) * volume; - } - averageTorque = averageTorque * (fps / totalVolume); - if (averageTorque.canBeNormalized()) - for (auto& particle : x4_particles) - particle.x20_velocity -= averageTorque.cross(particle.x4_curPos - centerOfVolume) * 25.f; + } + if (!x4_particles.empty()) + x58_averageVel = x58_averageVel * (1.f / (dt * x4_particles.size())); + x54_impactVel /= dt; + if (!x68_28_noOverTimer) { + x50_overTimer -= dt; + if (x50_overTimer <= 0.f) + x68_25_over = true; + } + if (movingSlowly && x68_24_prevMovingSlowly) + x68_25_over = true; + x68_24_prevMovingSlowly = movingSlowly; } -void CRagDoll::AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float radius) -{ - x4_particles.emplace_back(id, curPos, radius, prevPos); +void CRagDoll::ClearForces() { + for (auto& particle : x4_particles) + particle.x20_velocity = zeus::CVector3f::skZero; } -void CRagDoll::AddLengthConstraint(int i1, int i2) -{ - x14_lengthConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], - (x4_particles[i1].x4_curPos - x4_particles[i2].x4_curPos).magnitude(), 0); -} - -void CRagDoll::AddMaxLengthConstraint(int i1, int i2, float length) -{ - x14_lengthConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], length, 2); -} - -void CRagDoll::AddMinLengthConstraint(int i1, int i2, float length) -{ - x14_lengthConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], length, 1); -} - -void CRagDoll::AddJointConstraint(int i1, int i2, int i3, int i4, int i5, int i6) -{ - x24_jointConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], &x4_particles[i3], - &x4_particles[i4], &x4_particles[i5], &x4_particles[i6]); -} - -zeus::CQuaternion CRagDoll::BoneAlign(CHierarchyPoseBuilder& pb, const CCharLayoutInfo& charInfo, - int i1, int i2, const zeus::CQuaternion& q) -{ - zeus::CVector3f fromParent = charInfo.GetFromParentUnrotated(x4_particles[i2].x0_id); - zeus::CVector3f delta = x4_particles[i2].x4_curPos - x4_particles[i1].x4_curPos; - delta = q.inverse().transform(delta); - zeus::CQuaternion ret = zeus::CQuaternion::shortestRotationArc(fromParent, delta); - pb.GetTreeMap()[x4_particles[i1].x0_id].x4_rotation = ret; - return ret; -} - -zeus::CAABox CRagDoll::CalculateRenderBounds() const -{ - zeus::CAABox aabb; - for (const auto& particle : x4_particles) - { - aabb.accumulateBounds(zeus::CAABox(particle.x4_curPos - particle.x10_radius, - particle.x4_curPos + particle.x10_radius)); - } - return aabb; -} - -void CRagDoll::CheckStatic(float dt) -{ - x4c_impactCount = 0; - x54_impactVel = 0.f; - float halfDt = 0.5f * dt; - float halfDeltaUnitSq = halfDt * halfDt; - x58_averageVel = zeus::CVector3f::skZero; - bool movingSlowly = true; - for (auto& particle : x4_particles) - { - zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos; - x58_averageVel += delta; - if (delta.magSquared() > halfDeltaUnitSq) - movingSlowly = false; - if (particle.x3c_24_impactPending) - { - x4c_impactCount += 1; - x54_impactVel = std::max(particle.x38_impactFrameVel, x54_impactVel); - } - } - if (!x4_particles.empty()) - x58_averageVel = x58_averageVel * (1.f / (dt * x4_particles.size())); - x54_impactVel /= dt; - if (!x68_28_noOverTimer) - { - x50_overTimer -= dt; - if (x50_overTimer <= 0.f) - x68_25_over = true; - } - if (movingSlowly && x68_24_prevMovingSlowly) - x68_25_over = true; - x68_24_prevMovingSlowly = movingSlowly; -} - -void CRagDoll::ClearForces() -{ - for (auto& particle : x4_particles) - particle.x20_velocity = zeus::CVector3f::skZero; -} - -void CRagDoll::SatisfyConstraints(CStateManager& mgr) -{ - for (auto& length : x14_lengthConstraints) - length.Update(); - for (auto& joint : x24_jointConstraints) - joint.Update(); - for (auto& plane : x34_planeConstraints) - plane.Update(); - if (SatisfyWorldConstraints(mgr, 1)) - SatisfyWorldConstraints(mgr, 2); -} - -bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int pass) -{ - zeus::CAABox aabb; - for (const auto& particle : x4_particles) - { - if (pass == 1 || particle.x3c_24_impactPending) - { - aabb.accumulateBounds(particle.x14_prevPos - particle.x10_radius); - aabb.accumulateBounds(particle.x14_prevPos + particle.x10_radius); - aabb.accumulateBounds(particle.x4_curPos - particle.x10_radius); - aabb.accumulateBounds(particle.x4_curPos + particle.x10_radius); - } - } - - CAreaCollisionCache ccache(aabb); - CGameCollision::BuildAreaCollisionCache(mgr, ccache); - bool needs2ndPass = false; - - TUniqueId bestId = kInvalidUniqueId; - CMaterialList include; - if (x68_29_noAiCollision) - include = CMaterialList(EMaterialTypes::Solid); - else - include = CMaterialList(EMaterialTypes::Solid, EMaterialTypes::AIBlock); - - CMaterialList exclude; - if (x68_29_noAiCollision) - exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player, - EMaterialTypes::AIBlock, EMaterialTypes::Occluder); - else - exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player); - - rstl::reserved_vector nearList; - CMaterialFilter filter = CMaterialFilter::MakeIncludeExclude(include, exclude); - mgr.BuildNearList(nearList, aabb, filter, nullptr); - - for (auto& particle : x4_particles) - { - if (pass == 1 || particle.x3c_24_impactPending) - { - zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos; - float deltaMag = delta.magnitude(); - if (deltaMag > 0.0001f) - { - delta = delta * (1.f / deltaMag); - double d = deltaMag; - CCollidableSphere sphere(zeus::CSphere(particle.x14_prevPos, particle.x10_radius), include); - CCollisionInfo info; - CGameCollision::DetectCollision_Cached_Moving(mgr, ccache, sphere, {}, filter, - nearList, delta, bestId, info, d); - if (info.IsValid()) - { - needs2ndPass = true; - switch (pass) - { - case 1: - { - particle.x3c_24_impactPending = true; - float dot = delta.dot(info.GetNormalLeft()); - particle.x2c_impactResponseDelta = -0.125f * dot * deltaMag * info.GetNormalLeft(); - particle.x38_impactFrameVel = -dot * deltaMag; - particle.x4_curPos += float(0.0001f - (deltaMag - d) * dot) * info.GetNormalLeft(); - break; - } - case 2: - particle.x4_curPos = float(d - 0.0001) * delta + particle.x14_prevPos; - break; - default: - break; - } - } - } - else if (!x68_27_continueSmallMovements) - { - particle.x4_curPos = particle.x14_prevPos; - } - } - } - - return needs2ndPass; -} - -void CRagDoll::SatisfyWorldConstraintsOnConstruction(CStateManager& mgr) -{ - for (auto& particle : x4_particles) - particle.x3c_24_impactPending = true; +void CRagDoll::SatisfyConstraints(CStateManager& mgr) { + for (auto& length : x14_lengthConstraints) + length.Update(); + for (auto& joint : x24_jointConstraints) + joint.Update(); + for (auto& plane : x34_planeConstraints) + plane.Update(); + if (SatisfyWorldConstraints(mgr, 1)) SatisfyWorldConstraints(mgr, 2); - for (auto& particle : x4_particles) - particle.x14_prevPos = particle.x4_curPos; } -void CRagDoll::Verlet(float dt) -{ - for (auto& particle : x4_particles) - { - zeus::CVector3f oldPos = particle.x4_curPos; - particle.x4_curPos += (particle.x4_curPos - particle.x14_prevPos) * - (particle.x3c_24_impactPending ? 0.9f : 1.f); - particle.x4_curPos += particle.x20_velocity * (dt * dt); - particle.x4_curPos += particle.x2c_impactResponseDelta; - particle.x14_prevPos = oldPos; - zeus::CVector3f deltaPos = particle.x4_curPos - particle.x14_prevPos; - if (deltaPos.magSquared() > 4.f) - particle.x4_curPos = deltaPos.normalized() * 2.f + particle.x14_prevPos; - particle.x3c_24_impactPending = false; - particle.x2c_impactResponseDelta = zeus::CVector3f::skZero; +bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int pass) { + zeus::CAABox aabb; + for (const auto& particle : x4_particles) { + if (pass == 1 || particle.x3c_24_impactPending) { + aabb.accumulateBounds(particle.x14_prevPos - particle.x10_radius); + aabb.accumulateBounds(particle.x14_prevPos + particle.x10_radius); + aabb.accumulateBounds(particle.x4_curPos - particle.x10_radius); + aabb.accumulateBounds(particle.x4_curPos + particle.x10_radius); } -} + } -void CRagDoll::PreRender(const zeus::CVector3f& v, CModelData& mData) -{ - // Empty -} + CAreaCollisionCache ccache(aabb); + CGameCollision::BuildAreaCollisionCache(mgr, ccache); + bool needs2ndPass = false; -void CRagDoll::Update(CStateManager& mgr, float dt, float waterTop) -{ - if (!x68_25_over || x68_27_continueSmallMovements) - { - AccumulateForces(dt, waterTop); - Verlet(dt); - SatisfyConstraints(mgr); - ClearForces(); - CheckStatic(dt); + TUniqueId bestId = kInvalidUniqueId; + CMaterialList include; + if (x68_29_noAiCollision) + include = CMaterialList(EMaterialTypes::Solid); + else + include = CMaterialList(EMaterialTypes::Solid, EMaterialTypes::AIBlock); + + CMaterialList exclude; + if (x68_29_noAiCollision) + exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player, EMaterialTypes::AIBlock, + EMaterialTypes::Occluder); + else + exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player); + + rstl::reserved_vector nearList; + CMaterialFilter filter = CMaterialFilter::MakeIncludeExclude(include, exclude); + mgr.BuildNearList(nearList, aabb, filter, nullptr); + + for (auto& particle : x4_particles) { + if (pass == 1 || particle.x3c_24_impactPending) { + zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos; + float deltaMag = delta.magnitude(); + if (deltaMag > 0.0001f) { + delta = delta * (1.f / deltaMag); + double d = deltaMag; + CCollidableSphere sphere(zeus::CSphere(particle.x14_prevPos, particle.x10_radius), include); + CCollisionInfo info; + CGameCollision::DetectCollision_Cached_Moving(mgr, ccache, sphere, {}, filter, nearList, delta, bestId, info, + d); + if (info.IsValid()) { + needs2ndPass = true; + switch (pass) { + case 1: { + particle.x3c_24_impactPending = true; + float dot = delta.dot(info.GetNormalLeft()); + particle.x2c_impactResponseDelta = -0.125f * dot * deltaMag * info.GetNormalLeft(); + particle.x38_impactFrameVel = -dot * deltaMag; + particle.x4_curPos += float(0.0001f - (deltaMag - d) * dot) * info.GetNormalLeft(); + break; + } + case 2: + particle.x4_curPos = float(d - 0.0001) * delta + particle.x14_prevPos; + break; + default: + break; + } + } + } else if (!x68_27_continueSmallMovements) { + particle.x4_curPos = particle.x14_prevPos; + } } + } + + return needs2ndPass; } -void CRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData) -{ - zeus::CVector3f scale = mData.GetScale(); - CAnimData* aData = mData.AnimationData(); - aData->BuildPose(); - for (auto& particle : x4_particles) - if (particle.x0_id != 0xff) - particle.x4_curPos = xf * aData->GetPose().GetOffset(particle.x0_id) * scale; - SatisfyWorldConstraints(mgr, 2); - for (auto& particle : x4_particles) - particle.x3c_24_impactPending = false; - x68_26_primed = true; +void CRagDoll::SatisfyWorldConstraintsOnConstruction(CStateManager& mgr) { + for (auto& particle : x4_particles) + particle.x3c_24_impactPending = true; + SatisfyWorldConstraints(mgr, 2); + for (auto& particle : x4_particles) + particle.x14_prevPos = particle.x4_curPos; } +void CRagDoll::Verlet(float dt) { + for (auto& particle : x4_particles) { + zeus::CVector3f oldPos = particle.x4_curPos; + particle.x4_curPos += (particle.x4_curPos - particle.x14_prevPos) * (particle.x3c_24_impactPending ? 0.9f : 1.f); + particle.x4_curPos += particle.x20_velocity * (dt * dt); + particle.x4_curPos += particle.x2c_impactResponseDelta; + particle.x14_prevPos = oldPos; + zeus::CVector3f deltaPos = particle.x4_curPos - particle.x14_prevPos; + if (deltaPos.magSquared() > 4.f) + particle.x4_curPos = deltaPos.normalized() * 2.f + particle.x14_prevPos; + particle.x3c_24_impactPending = false; + particle.x2c_impactResponseDelta = zeus::CVector3f::skZero; + } } + +void CRagDoll::PreRender(const zeus::CVector3f& v, CModelData& mData) { + // Empty +} + +void CRagDoll::Update(CStateManager& mgr, float dt, float waterTop) { + if (!x68_25_over || x68_27_continueSmallMovements) { + AccumulateForces(dt, waterTop); + Verlet(dt); + SatisfyConstraints(mgr); + ClearForces(); + CheckStatic(dt); + } +} + +void CRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData) { + zeus::CVector3f scale = mData.GetScale(); + CAnimData* aData = mData.AnimationData(); + aData->BuildPose(); + for (auto& particle : x4_particles) + if (particle.x0_id != 0xff) + particle.x4_curPos = xf * aData->GetPose().GetOffset(particle.x0_id) * scale; + SatisfyWorldConstraints(mgr, 2); + for (auto& particle : x4_particles) + particle.x3c_24_impactPending = false; + x68_26_primed = true; +} + +} // namespace urde diff --git a/Runtime/Character/CRagDoll.hpp b/Runtime/Character/CRagDoll.hpp index bda2c3de9..032c33d19 100644 --- a/Runtime/Character/CRagDoll.hpp +++ b/Runtime/Character/CRagDoll.hpp @@ -5,139 +5,134 @@ #include "zeus/CAABox.hpp" #include "CSegId.hpp" -namespace urde -{ +namespace urde { class CHierarchyPoseBuilder; class CCharLayoutInfo; class CModelData; class CStateManager; -class CRagDoll -{ +class CRagDoll { protected: - class CRagDollParticle - { - friend class CRagDoll; - CSegId x0_id; - zeus::CVector3f x4_curPos; - float x10_radius; - zeus::CVector3f x14_prevPos; - zeus::CVector3f x20_velocity; - zeus::CVector3f x2c_impactResponseDelta; - float x38_impactFrameVel = 0.f; - bool x3c_24_impactPending : 1; - bool x3c_25_ : 1; - public: - CRagDollParticle(CSegId id, const zeus::CVector3f& curPos, float radius, const zeus::CVector3f& prevPos) - : x0_id(id), x4_curPos(curPos), x10_radius(radius), x14_prevPos(prevPos) - { - x3c_24_impactPending = false; - x3c_25_ = false; - } - CSegId GetBone() const { return x0_id; } - const zeus::CVector3f& GetPosition() const { return x4_curPos; } - zeus::CVector3f& Position() { return x4_curPos; } - const zeus::CVector3f& GetVelocity() const { return x20_velocity; } - zeus::CVector3f& Velocity() { return x20_velocity; } - float GetRadius() const { return x10_radius; } + class CRagDollParticle { + friend class CRagDoll; + CSegId x0_id; + zeus::CVector3f x4_curPos; + float x10_radius; + zeus::CVector3f x14_prevPos; + zeus::CVector3f x20_velocity; + zeus::CVector3f x2c_impactResponseDelta; + float x38_impactFrameVel = 0.f; + bool x3c_24_impactPending : 1; + bool x3c_25_ : 1; + + public: + CRagDollParticle(CSegId id, const zeus::CVector3f& curPos, float radius, const zeus::CVector3f& prevPos) + : x0_id(id), x4_curPos(curPos), x10_radius(radius), x14_prevPos(prevPos) { + x3c_24_impactPending = false; + x3c_25_ = false; + } + CSegId GetBone() const { return x0_id; } + const zeus::CVector3f& GetPosition() const { return x4_curPos; } + zeus::CVector3f& Position() { return x4_curPos; } + const zeus::CVector3f& GetVelocity() const { return x20_velocity; } + zeus::CVector3f& Velocity() { return x20_velocity; } + float GetRadius() const { return x10_radius; } + }; + class CRagDollLengthConstraint { + friend class CRagDoll; + CRagDollParticle* x0_p1; + CRagDollParticle* x4_p2; + float x8_length; + int xc_ineqType; + + public: + CRagDollLengthConstraint(CRagDollParticle* p1, CRagDollParticle* p2, float f1, int i1) + : x0_p1(p1), x4_p2(p2), x8_length(f1), xc_ineqType(i1) {} + void Update(); + float GetLength() const { return x8_length; } + }; + class CRagDollJointConstraint { + friend class CRagDoll; + CRagDollParticle* x0_p1; // Shoulder plane 0 + CRagDollParticle* x4_p2; // Shoulder plane 1 + CRagDollParticle* x8_p3; // Shoulder plane 2 + CRagDollParticle* xc_p4; // Shoulder + CRagDollParticle* x10_p5; // Elbow + CRagDollParticle* x14_p6; // Wrist + public: + CRagDollJointConstraint(CRagDollParticle* p1, CRagDollParticle* p2, CRagDollParticle* p3, CRagDollParticle* p4, + CRagDollParticle* p5, CRagDollParticle* p6) + : x0_p1(p1), x4_p2(p2), x8_p3(p3), xc_p4(p4), x10_p5(p5), x14_p6(p6) {} + void Update(); + }; + class CRagDollPlaneConstraint { + friend class CRagDoll; + CRagDollParticle* x0_p1; + CRagDollParticle* x4_p2; + CRagDollParticle* x8_p3; + CRagDollParticle* xc_p4; + CRagDollParticle* x10_p5; + + public: + CRagDollPlaneConstraint(CRagDollParticle* p1, CRagDollParticle* p2, CRagDollParticle* p3, CRagDollParticle* p4, + CRagDollParticle* p5) + : x0_p1(p1), x4_p2(p2), x8_p3(p3), xc_p4(p4), x10_p5(p5) {} + void Update(); + }; + std::vector x4_particles; + std::vector x14_lengthConstraints; + std::vector x24_jointConstraints; + std::vector x34_planeConstraints; + float x44_normalGravity; + float x48_floatingGravity; + u32 x4c_impactCount = 0; + float x50_overTimer; + float x54_impactVel = 0.f; + zeus::CVector3f x58_averageVel; + float x64_angTimer = 0.f; + union { + struct { + bool x68_24_prevMovingSlowly : 1; + bool x68_25_over : 1; + bool x68_26_primed : 1; + bool x68_27_continueSmallMovements : 1; + bool x68_28_noOverTimer : 1; + bool x68_29_noAiCollision : 1; }; - class CRagDollLengthConstraint - { - friend class CRagDoll; - CRagDollParticle* x0_p1; - CRagDollParticle* x4_p2; - float x8_length; - int xc_ineqType; - public: - CRagDollLengthConstraint(CRagDollParticle* p1, CRagDollParticle* p2, float f1, int i1) - : x0_p1(p1), x4_p2(p2), x8_length(f1), xc_ineqType(i1) {} - void Update(); - float GetLength() const { return x8_length; } - }; - class CRagDollJointConstraint - { - friend class CRagDoll; - CRagDollParticle* x0_p1; // Shoulder plane 0 - CRagDollParticle* x4_p2; // Shoulder plane 1 - CRagDollParticle* x8_p3; // Shoulder plane 2 - CRagDollParticle* xc_p4; // Shoulder - CRagDollParticle* x10_p5; // Elbow - CRagDollParticle* x14_p6; // Wrist - public: - CRagDollJointConstraint(CRagDollParticle* p1, CRagDollParticle* p2, CRagDollParticle* p3, - CRagDollParticle* p4, CRagDollParticle* p5, CRagDollParticle* p6) - : x0_p1(p1), x4_p2(p2), x8_p3(p3), xc_p4(p4), x10_p5(p5), x14_p6(p6) {} - void Update(); - }; - class CRagDollPlaneConstraint - { - friend class CRagDoll; - CRagDollParticle* x0_p1; - CRagDollParticle* x4_p2; - CRagDollParticle* x8_p3; - CRagDollParticle* xc_p4; - CRagDollParticle* x10_p5; - public: - CRagDollPlaneConstraint(CRagDollParticle* p1, CRagDollParticle* p2, CRagDollParticle* p3, - CRagDollParticle* p4, CRagDollParticle* p5) - : x0_p1(p1), x4_p2(p2), x8_p3(p3), xc_p4(p4), x10_p5(p5) {} - void Update(); - }; - std::vector x4_particles; - std::vector x14_lengthConstraints; - std::vector x24_jointConstraints; - std::vector x34_planeConstraints; - float x44_normalGravity; - float x48_floatingGravity; - u32 x4c_impactCount = 0; - float x50_overTimer; - float x54_impactVel = 0.f; - zeus::CVector3f x58_averageVel; - float x64_angTimer = 0.f; - union - { - struct - { - bool x68_24_prevMovingSlowly : 1; - bool x68_25_over : 1; - bool x68_26_primed : 1; - bool x68_27_continueSmallMovements : 1; - bool x68_28_noOverTimer : 1; - bool x68_29_noAiCollision : 1; - }; - u32 _dummy = 0; - }; - void AccumulateForces(float dt, float waterTop); - void SetNumParticles(int num) { x4_particles.reserve(num); } - void AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float radius); - void SetNumLengthConstraints(int num) { x14_lengthConstraints.reserve(num); } - void AddLengthConstraint(int i1, int i2); - void AddMaxLengthConstraint(int i1, int i2, float length); - void AddMinLengthConstraint(int i1, int i2, float length); - void SetNumJointConstraints(int num) { x24_jointConstraints.reserve(num); } - void AddJointConstraint(int i1, int i2, int i3, int i4, int i5, int i6); - zeus::CQuaternion BoneAlign(CHierarchyPoseBuilder& pb, const CCharLayoutInfo& charInfo, - int i1, int i2, const zeus::CQuaternion& q); - void CheckStatic(float dt); - void ClearForces(); - void SatisfyConstraints(CStateManager& mgr); - bool SatisfyWorldConstraints(CStateManager& mgr, int pass); - void SatisfyWorldConstraintsOnConstruction(CStateManager& mgr); - void Verlet(float dt); + u32 _dummy = 0; + }; + void AccumulateForces(float dt, float waterTop); + void SetNumParticles(int num) { x4_particles.reserve(num); } + void AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float radius); + void SetNumLengthConstraints(int num) { x14_lengthConstraints.reserve(num); } + void AddLengthConstraint(int i1, int i2); + void AddMaxLengthConstraint(int i1, int i2, float length); + void AddMinLengthConstraint(int i1, int i2, float length); + void SetNumJointConstraints(int num) { x24_jointConstraints.reserve(num); } + void AddJointConstraint(int i1, int i2, int i3, int i4, int i5, int i6); + zeus::CQuaternion BoneAlign(CHierarchyPoseBuilder& pb, const CCharLayoutInfo& charInfo, int i1, int i2, + const zeus::CQuaternion& q); + void CheckStatic(float dt); + void ClearForces(); + void SatisfyConstraints(CStateManager& mgr); + bool SatisfyWorldConstraints(CStateManager& mgr, int pass); + void SatisfyWorldConstraintsOnConstruction(CStateManager& mgr); + void Verlet(float dt); + public: - virtual ~CRagDoll() = default; - CRagDoll(float normalGravity, float floatingGravity, float overTime, u32 flags); + virtual ~CRagDoll() = default; + CRagDoll(float normalGravity, float floatingGravity, float overTime, u32 flags); - virtual void PreRender(const zeus::CVector3f& v, CModelData& mData); - virtual void Update(CStateManager& mgr, float dt, float waterTop); - virtual void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData); + virtual void PreRender(const zeus::CVector3f& v, CModelData& mData); + virtual void Update(CStateManager& mgr, float dt, float waterTop); + virtual void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData); - zeus::CAABox CalculateRenderBounds() const; - bool IsPrimed() const { return x68_26_primed; } - bool WillContinueSmallMovements() const { return x68_27_continueSmallMovements; } - bool IsOver() const { return x68_25_over; } - void SetNoOverTimer(bool b) { x68_28_noOverTimer = b; } - void SetContinueSmallMovements(bool b) { x68_27_continueSmallMovements = b; } + zeus::CAABox CalculateRenderBounds() const; + bool IsPrimed() const { return x68_26_primed; } + bool WillContinueSmallMovements() const { return x68_27_continueSmallMovements; } + bool IsOver() const { return x68_25_over; } + void SetNoOverTimer(bool b) { x68_28_noOverTimer = b; } + void SetContinueSmallMovements(bool b) { x68_27_continueSmallMovements = b; } }; -} +} // namespace urde diff --git a/Runtime/Character/CSegId.hpp b/Runtime/Character/CSegId.hpp index a13bd3046..3b036d45b 100644 --- a/Runtime/Character/CSegId.hpp +++ b/Runtime/Character/CSegId.hpp @@ -4,20 +4,24 @@ #include "IOStreams.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { + +class CSegId { + u8 x0_segId = 0xff; -class CSegId -{ - u8 x0_segId = 0xff; public: - CSegId() = default; - CSegId(u8 id) : x0_segId(id) {} - CSegId(CInputStream& in) : x0_segId(in.readUint32Big()) {} - CSegId& operator++() {++x0_segId; return *this;} - CSegId& operator--() {--x0_segId; return *this;} - operator u8() const {return x0_segId;} + CSegId() = default; + CSegId(u8 id) : x0_segId(id) {} + CSegId(CInputStream& in) : x0_segId(in.readUint32Big()) {} + CSegId& operator++() { + ++x0_segId; + return *this; + } + CSegId& operator--() { + --x0_segId; + return *this; + } + operator u8() const { return x0_segId; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CSegIdList.cpp b/Runtime/Character/CSegIdList.cpp index 4e2898ca8..ba04cf338 100644 --- a/Runtime/Character/CSegIdList.cpp +++ b/Runtime/Character/CSegIdList.cpp @@ -1,14 +1,12 @@ #include "CSegIdList.hpp" -namespace urde -{ +namespace urde { -CSegIdList::CSegIdList(CInputStream& in) -{ - u32 count = in.readUint32Big(); - x0_list.reserve(count); - for (u32 i=0 ; i x0_list; -class CSegIdList -{ - std::vector x0_list; public: - CSegIdList(CInputStream& in); - const std::vector& GetList() const {return x0_list;} + CSegIdList(CInputStream& in); + const std::vector& GetList() const { return x0_list; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CSegStatementSet.cpp b/Runtime/Character/CSegStatementSet.cpp index 36762903b..ae7032d05 100644 --- a/Runtime/Character/CSegStatementSet.cpp +++ b/Runtime/Character/CSegStatementSet.cpp @@ -2,22 +2,18 @@ #include "CSegIdList.hpp" #include "CCharLayoutInfo.hpp" -namespace urde -{ +namespace urde { -void CSegStatementSet::Add(const CSegIdList& list, const CCharLayoutInfo& layout, - const CSegStatementSet& other, float weight) -{ - for (const CSegId& id : list.GetList()) - { - x4_segData[id].x0_rotation *= zeus::CQuaternion::slerp(zeus::CQuaternion::skNoRotation, - other.x4_segData[id].x0_rotation, weight); - if (other.x4_segData[id].x1c_hasOffset && x4_segData[id].x1c_hasOffset) - { - zeus::CVector3f off = other.x4_segData[id].x10_offset - layout.GetFromParentUnrotated(id); - x4_segData[id].x10_offset += off * weight; - } +void CSegStatementSet::Add(const CSegIdList& list, const CCharLayoutInfo& layout, const CSegStatementSet& other, + float weight) { + for (const CSegId& id : list.GetList()) { + x4_segData[id].x0_rotation *= + zeus::CQuaternion::slerp(zeus::CQuaternion::skNoRotation, other.x4_segData[id].x0_rotation, weight); + if (other.x4_segData[id].x1c_hasOffset && x4_segData[id].x1c_hasOffset) { + zeus::CVector3f off = other.x4_segData[id].x10_offset - layout.GetFromParentUnrotated(id); + x4_segData[id].x10_offset += off * weight; } + } } -} +} // namespace urde diff --git a/Runtime/Character/CSegStatementSet.hpp b/Runtime/Character/CSegStatementSet.hpp index 59bddc1ec..77f96da87 100644 --- a/Runtime/Character/CSegStatementSet.hpp +++ b/Runtime/Character/CSegStatementSet.hpp @@ -3,22 +3,18 @@ #include "CAnimPerSegmentData.hpp" #include "CSegId.hpp" -namespace urde -{ +namespace urde { class CSegIdList; class CCharLayoutInfo; -class CSegStatementSet -{ +class CSegStatementSet { public: - /* Used to be a pointer to arbitrary subclass-provided storage, - * now it's a self-stored array */ - CAnimPerSegmentData x4_segData[100]; - void Add(const CSegIdList& list, const CCharLayoutInfo& layout, - const CSegStatementSet& other, float weight); + /* Used to be a pointer to arbitrary subclass-provided storage, + * now it's a self-stored array */ + CAnimPerSegmentData x4_segData[100]; + void Add(const CSegIdList& list, const CCharLayoutInfo& layout, const CSegStatementSet& other, float weight); - CAnimPerSegmentData& operator[](const CSegId& idx) { return x4_segData[idx]; } + CAnimPerSegmentData& operator[](const CSegId& idx) { return x4_segData[idx]; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CSequenceHelper.cpp b/Runtime/Character/CSequenceHelper.cpp index e8734a315..0bdcc99d7 100644 --- a/Runtime/Character/CSequenceHelper.cpp +++ b/Runtime/Character/CSequenceHelper.cpp @@ -7,115 +7,102 @@ #include "IMetaAnim.hpp" #include "CTreeUtils.hpp" -namespace urde -{ +namespace urde { CSequenceFundamentals::CSequenceFundamentals(const CSteadyStateAnimInfo& ssInfo, const std::vector& boolNodes, const std::vector& int32Nodes, const std::vector& particleNodes, const std::vector& soundNodes) -: x0_ssInfo(ssInfo), x18_boolNodes(boolNodes), x28_int32Nodes(int32Nodes), x38_particleNodes(particleNodes), - x48_soundNodes(soundNodes) -{ -} +: x0_ssInfo(ssInfo) +, x18_boolNodes(boolNodes) +, x28_int32Nodes(int32Nodes) +, x38_particleNodes(particleNodes) +, x48_soundNodes(soundNodes) {} -CSequenceHelper::CSequenceHelper(const std::shared_ptr& a, - const std::shared_ptr& b, +CSequenceHelper::CSequenceHelper(const std::shared_ptr& a, const std::shared_ptr& b, const CAnimSysContext& animCtx) -: x0_animCtx(animCtx) -{ - x10_treeNodes.reserve(2); - x10_treeNodes.push_back(a); - x10_treeNodes.push_back(b); +: x0_animCtx(animCtx) { + x10_treeNodes.reserve(2); + x10_treeNodes.push_back(a); + x10_treeNodes.push_back(b); } -CSequenceHelper::CSequenceHelper(const std::vector>& nodes, - const CAnimSysContext& animCtx) -: x0_animCtx(animCtx) -{ - x10_treeNodes.reserve(nodes.size()); - for (const std::shared_ptr& meta : nodes) - x10_treeNodes.push_back(meta->GetAnimationTree(animCtx, CMetaAnimTreeBuildOrders::NoSpecialOrders())); +CSequenceHelper::CSequenceHelper(const std::vector>& nodes, const CAnimSysContext& animCtx) +: x0_animCtx(animCtx) { + x10_treeNodes.reserve(nodes.size()); + for (const std::shared_ptr& meta : nodes) + x10_treeNodes.push_back(meta->GetAnimationTree(animCtx, CMetaAnimTreeBuildOrders::NoSpecialOrders())); } -CSequenceFundamentals CSequenceHelper::ComputeSequenceFundamentals() -{ - CCharAnimTime duration; - zeus::CVector3f offset; - std::vector boolNodes; - std::vector int32Nodes; - std::vector particleNodes; - std::vector soundNodes; - if (x10_treeNodes.size() > 0) - { - std::shared_ptr node = CAnimTreeNode::Cast(x10_treeNodes[0]->Clone()); - for (int i=0 ; iGetBoolPOIList(CCharAnimTime::Infinity(), boolNodeArr, 64, 0, 0); - boolNodes.reserve(boolNodes.size() + numBools); - for (int j=0 ; j boolNodes; + std::vector int32Nodes; + std::vector particleNodes; + std::vector soundNodes; + if (x10_treeNodes.size() > 0) { + std::shared_ptr node = CAnimTreeNode::Cast(x10_treeNodes[0]->Clone()); + for (int i = 0; i < x10_treeNodes.size(); ++i) { + CBoolPOINode boolNodeArr[64]; + u32 numBools = node->GetBoolPOIList(CCharAnimTime::Infinity(), boolNodeArr, 64, 0, 0); + boolNodes.reserve(boolNodes.size() + numBools); + for (int j = 0; j < numBools; ++j) { + CBoolPOINode& n = boolNodeArr[j]; + n.SetTime(n.GetTime() + duration); + boolNodes.push_back(n); + } - CInt32POINode int32NodeArr[64]; - u32 numInt32s = node->GetInt32POIList(CCharAnimTime::Infinity(), int32NodeArr, 64, 0, 0); - int32Nodes.reserve(int32Nodes.size() + numInt32s); - for (int j=0 ; jGetInt32POIList(CCharAnimTime::Infinity(), int32NodeArr, 64, 0, 0); + int32Nodes.reserve(int32Nodes.size() + numInt32s); + for (int j = 0; j < numInt32s; ++j) { + CInt32POINode& n = int32NodeArr[j]; + n.SetTime(n.GetTime() + duration); + int32Nodes.push_back(n); + } - CParticlePOINode particleNodeArr[64]; - u32 numParticles = node->GetParticlePOIList(CCharAnimTime::Infinity(), particleNodeArr, 64, 0, 0); - particleNodes.reserve(particleNodes.size() + numParticles); - for (int j=0 ; jGetParticlePOIList(CCharAnimTime::Infinity(), particleNodeArr, 64, 0, 0); + particleNodes.reserve(particleNodes.size() + numParticles); + for (int j = 0; j < numParticles; ++j) { + CParticlePOINode& n = particleNodeArr[j]; + n.SetTime(n.GetTime() + duration); + particleNodes.push_back(n); + } - CSoundPOINode soundNodeArr[64]; - u32 numSounds = node->GetSoundPOIList(CCharAnimTime::Infinity(), soundNodeArr, 64, 0, 0); - soundNodes.reserve(soundNodes.size() + numSounds); - for (int j=0 ; jGetSoundPOIList(CCharAnimTime::Infinity(), soundNodeArr, 64, 0, 0); + soundNodes.reserve(soundNodes.size() + numSounds); + for (int j = 0; j < numSounds; ++j) { + CSoundPOINode& n = soundNodeArr[j]; + n.SetTime(n.GetTime() + duration); + soundNodes.push_back(n); + } - duration += node->VGetTimeRemaining(); + duration += node->VGetTimeRemaining(); - CCharAnimTime remTime = node->VGetTimeRemaining(); - while (!remTime.EqualsZero() && !remTime.EpsilonZero()) - { - SAdvancementResults res = node->VAdvanceView(remTime); - auto simp = node->Simplified(); - if (simp) - node = CAnimTreeNode::Cast(std::move(*simp)); - //CCharAnimTime prevRemTime = remTime; - remTime = res.x0_remTime; - /* This was originally accumulating uninitialized register values (stack variable misuse?) */ - offset += res.x8_deltas.x0_posDelta; - } + CCharAnimTime remTime = node->VGetTimeRemaining(); + while (!remTime.EqualsZero() && !remTime.EpsilonZero()) { + SAdvancementResults res = node->VAdvanceView(remTime); + auto simp = node->Simplified(); + if (simp) + node = CAnimTreeNode::Cast(std::move(*simp)); + // CCharAnimTime prevRemTime = remTime; + remTime = res.x0_remTime; + /* This was originally accumulating uninitialized register values (stack variable misuse?) */ + offset += res.x8_deltas.x0_posDelta; + } - if (i < x10_treeNodes.size()-1) - { - node = CTreeUtils::GetTransitionTree(node, - CAnimTreeNode::Cast(std::move(x10_treeNodes[i+1]->Clone())), x0_animCtx); - } - } + if (i < x10_treeNodes.size() - 1) { + node = CTreeUtils::GetTransitionTree(node, CAnimTreeNode::Cast(std::move(x10_treeNodes[i + 1]->Clone())), + x0_animCtx); + } } + } - return {{false, duration, offset}, boolNodes, int32Nodes, particleNodes, soundNodes}; + return {{false, duration, offset}, boolNodes, int32Nodes, particleNodes, soundNodes}; } -} +} // namespace urde diff --git a/Runtime/Character/CSequenceHelper.hpp b/Runtime/Character/CSequenceHelper.hpp index 23487a667..d84e4b36f 100644 --- a/Runtime/Character/CSequenceHelper.hpp +++ b/Runtime/Character/CSequenceHelper.hpp @@ -7,45 +7,40 @@ #include "CSoundPOINode.hpp" #include "CAnimSysContext.hpp" -namespace urde -{ +namespace urde { class IMetaAnim; class CTransitionDatabaseGame; -class CSequenceFundamentals -{ - CSteadyStateAnimInfo x0_ssInfo; - std::vector x18_boolNodes; - std::vector x28_int32Nodes; - std::vector x38_particleNodes; - std::vector x48_soundNodes; -public: - CSequenceFundamentals(const CSteadyStateAnimInfo& ssInfo, - const std::vector& boolNodes, - const std::vector& int32Nodes, - const std::vector& particleNodes, - const std::vector& soundNodes); +class CSequenceFundamentals { + CSteadyStateAnimInfo x0_ssInfo; + std::vector x18_boolNodes; + std::vector x28_int32Nodes; + std::vector x38_particleNodes; + std::vector x48_soundNodes; - const CSteadyStateAnimInfo& GetSteadyStateAnimInfo() const { return x0_ssInfo; } - const std::vector& GetBoolPointsOfInterest() const { return x18_boolNodes; } - const std::vector& GetInt32PointsOfInterest() const { return x28_int32Nodes; } - const std::vector& GetParticlePointsOfInterest() const { return x38_particleNodes; } - const std::vector& GetSoundPointsOfInterest() const { return x48_soundNodes; } +public: + CSequenceFundamentals(const CSteadyStateAnimInfo& ssInfo, const std::vector& boolNodes, + const std::vector& int32Nodes, + const std::vector& particleNodes, + const std::vector& soundNodes); + + const CSteadyStateAnimInfo& GetSteadyStateAnimInfo() const { return x0_ssInfo; } + const std::vector& GetBoolPointsOfInterest() const { return x18_boolNodes; } + const std::vector& GetInt32PointsOfInterest() const { return x28_int32Nodes; } + const std::vector& GetParticlePointsOfInterest() const { return x38_particleNodes; } + const std::vector& GetSoundPointsOfInterest() const { return x48_soundNodes; } }; -class CSequenceHelper -{ - CAnimSysContext x0_animCtx; - std::vector> x10_treeNodes; - std::vector x20_; +class CSequenceHelper { + CAnimSysContext x0_animCtx; + std::vector> x10_treeNodes; + std::vector x20_; + public: - CSequenceHelper(const std::shared_ptr& a, - const std::shared_ptr& b, - const CAnimSysContext& animCtx); - CSequenceHelper(const std::vector>& nodes, - const CAnimSysContext& animCtx); - CSequenceFundamentals ComputeSequenceFundamentals(); + CSequenceHelper(const std::shared_ptr& a, const std::shared_ptr& b, + const CAnimSysContext& animCtx); + CSequenceHelper(const std::vector>& nodes, const CAnimSysContext& animCtx); + CSequenceFundamentals ComputeSequenceFundamentals(); }; -} - +} // namespace urde diff --git a/Runtime/Character/CSkinBank.cpp b/Runtime/Character/CSkinBank.cpp index e97f6a6ec..85a3142c3 100644 --- a/Runtime/Character/CSkinBank.cpp +++ b/Runtime/Character/CSkinBank.cpp @@ -1,25 +1,20 @@ #include "CSkinBank.hpp" #include "CPoseAsTransforms.hpp" -namespace urde -{ +namespace urde { -CSkinBank::CSkinBank(CInputStream& in) -{ - u32 boneCount = in.readUint32Big(); - x0_segments.reserve(boneCount); - for (u32 i=0 ; i& out, - const CPoseAsTransforms& pose) const -{ - for (CSegId id : x0_segments) - { - const zeus::CTransform& xf = pose.GetRestToAccumTransform(id); - out.push_back(&xf); - } +void CSkinBank::GetBankTransforms(std::vector& out, const CPoseAsTransforms& pose) const { + for (CSegId id : x0_segments) { + const zeus::CTransform& xf = pose.GetRestToAccumTransform(id); + out.push_back(&xf); + } } -} +} // namespace urde diff --git a/Runtime/Character/CSkinBank.hpp b/Runtime/Character/CSkinBank.hpp index 5f5a1b1f9..6e934937c 100644 --- a/Runtime/Character/CSkinBank.hpp +++ b/Runtime/Character/CSkinBank.hpp @@ -3,18 +3,15 @@ #include "IOStreams.hpp" #include "CSegId.hpp" -namespace urde -{ +namespace urde { class CPoseAsTransforms; -class CSkinBank -{ - std::vector x0_segments; +class CSkinBank { + std::vector x0_segments; + public: - CSkinBank(CInputStream& in); - void GetBankTransforms(std::vector& out, - const CPoseAsTransforms& pose) const; + CSkinBank(CInputStream& in); + void GetBankTransforms(std::vector& out, const CPoseAsTransforms& pose) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CSkinRules.cpp b/Runtime/Character/CSkinRules.cpp index dc0fb8795..332e4b5b0 100644 --- a/Runtime/Character/CSkinRules.cpp +++ b/Runtime/Character/CSkinRules.cpp @@ -3,52 +3,46 @@ #include "Graphics/CModel.hpp" #include "CPoseAsTransforms.hpp" -namespace urde -{ +namespace urde { -CSkinRules::CSkinRules(CInputStream& in) -{ - u32 bankCount = in.readUint32Big(); - x0_skinBanks.reserve(bankCount); - for (u32 i=0 ; i>& vnOut, - const CPoseAsTransforms& pose, const CModel& model) const -{ - vnOut.resize(m_poolToSkinIdx.size()); - for (size_t i=0 ; i::GetIObjObjectFor(std::make_unique(in)); + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/Character/CSkinRules.hpp b/Runtime/Character/CSkinRules.hpp index 147448fd0..5c10a5c8d 100644 --- a/Runtime/Character/CSkinRules.hpp +++ b/Runtime/Character/CSkinRules.hpp @@ -5,55 +5,50 @@ #include "CSkinBank.hpp" #include "CFactoryMgr.hpp" -namespace urde -{ +namespace urde { class CPoseAsTransforms; class CModel; -struct SSkinWeighting -{ - CSegId m_id; - float m_weight; - explicit SSkinWeighting(CInputStream& in) - : m_id(in), m_weight(in.readFloatBig()) {} +struct SSkinWeighting { + CSegId m_id; + float m_weight; + explicit SSkinWeighting(CInputStream& in) : m_id(in), m_weight(in.readFloatBig()) {} }; -class CVirtualBone -{ - std::vector m_weights; -public: - explicit CVirtualBone(CInputStream& in) - { - u32 weightCount = in.readUint32Big(); - m_weights.reserve(weightCount); - for (u32 i=0 ; i m_weights; - const std::vector& GetWeights() const { return m_weights; } +public: + explicit CVirtualBone(CInputStream& in) { + u32 weightCount = in.readUint32Big(); + m_weights.reserve(weightCount); + for (u32 i = 0; i < weightCount; ++i) + m_weights.emplace_back(in); + } + + const std::vector& GetWeights() const { return m_weights; } }; -class CSkinRules -{ - std::vector x0_skinBanks; - //u32 x10_vertexCount; - //u32 x14_normalCount; - std::vector m_virtualBones; - std::vector m_poolToSkinIdx; +class CSkinRules { + std::vector x0_skinBanks; + // u32 x10_vertexCount; + // u32 x14_normalCount; + std::vector m_virtualBones; + std::vector m_poolToSkinIdx; public: - explicit CSkinRules(CInputStream& in); + explicit CSkinRules(CInputStream& in); - void GetBankTransforms(std::vector& out, - const CPoseAsTransforms& pose, int skinBankIdx) const - { x0_skinBanks[skinBankIdx].GetBankTransforms(out, pose); } + void GetBankTransforms(std::vector& out, const CPoseAsTransforms& pose, + int skinBankIdx) const { + x0_skinBanks[skinBankIdx].GetBankTransforms(out, pose); + } - void TransformVerticesCPU(std::vector>& vnOut, - const CPoseAsTransforms& pose, const CModel& model) const; + void TransformVerticesCPU(std::vector>& vnOut, + const CPoseAsTransforms& pose, const CModel& model) const; }; CFactoryFnReturn FSkinRulesFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& params, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/Character/CSoundPOINode.cpp b/Runtime/Character/CSoundPOINode.cpp index 3aefbd3e6..1d73602b5 100644 --- a/Runtime/Character/CSoundPOINode.cpp +++ b/Runtime/Character/CSoundPOINode.cpp @@ -1,35 +1,25 @@ #include "CSoundPOINode.hpp" #include "CAnimSourceReader.hpp" -namespace urde -{ +namespace urde { CSoundPOINode::CSoundPOINode() -: CPOINode("root", EPOIType::Sound, CCharAnimTime(), -1, false, 1.f, -1, 0), - x38_sfxId(0), - x3c_falloff(0.f), - x40_maxDist(0.f) -{} +: CPOINode("root", EPOIType::Sound, CCharAnimTime(), -1, false, 1.f, -1, 0) +, x38_sfxId(0) +, x3c_falloff(0.f) +, x40_maxDist(0.f) {} CSoundPOINode::CSoundPOINode(CInputStream& in) -: CPOINode(in), - x38_sfxId(in.readUint32Big()), - x3c_falloff(in.readFloatBig()), - x40_maxDist(in.readFloatBig()) -{} +: CPOINode(in), x38_sfxId(in.readUint32Big()), x3c_falloff(in.readFloatBig()), x40_maxDist(in.readFloatBig()) {} -CSoundPOINode::CSoundPOINode(std::string_view name, EPOIType a, - const CCharAnimTime& time, u32 b, bool c, - float d, u32 e, u32 f, u32 sfxId, float falloff, float maxDist) -: CPOINode(name, a, time, b, c, d, e, f), - x38_sfxId(sfxId), x3c_falloff(falloff), x40_maxDist(maxDist) {} +CSoundPOINode::CSoundPOINode(std::string_view name, EPOIType a, const CCharAnimTime& time, u32 b, bool c, float d, + u32 e, u32 f, u32 sfxId, float falloff, float maxDist) +: CPOINode(name, a, time, b, c, d, e, f), x38_sfxId(sfxId), x3c_falloff(falloff), x40_maxDist(maxDist) {} -CSoundPOINode CSoundPOINode::CopyNodeMinusStartTime(const CSoundPOINode& node, - const CCharAnimTime& startTime) -{ - CSoundPOINode ret = node; - ret.x1c_time -= startTime; - return ret; +CSoundPOINode CSoundPOINode::CopyNodeMinusStartTime(const CSoundPOINode& node, const CCharAnimTime& startTime) { + CSoundPOINode ret = node; + ret.x1c_time -= startTime; + return ret; } -} +} // namespace urde diff --git a/Runtime/Character/CSoundPOINode.hpp b/Runtime/Character/CSoundPOINode.hpp index aa4a6805c..e1c08d2ec 100644 --- a/Runtime/Character/CSoundPOINode.hpp +++ b/Runtime/Character/CSoundPOINode.hpp @@ -3,28 +3,24 @@ #include "CPOINode.hpp" #include "CCharAnimTime.hpp" -namespace urde -{ +namespace urde { class IAnimSourceInfo; -class CSoundPOINode : public CPOINode -{ - u32 x38_sfxId; - float x3c_falloff; - float x40_maxDist; -public: - CSoundPOINode(); - CSoundPOINode(CInputStream& in); - CSoundPOINode(std::string_view name, EPOIType type, - const CCharAnimTime& time, u32 b, bool c, - float d, u32 e, u32 f, u32 sfxId, float falloff, float maxDist); +class CSoundPOINode : public CPOINode { + u32 x38_sfxId; + float x3c_falloff; + float x40_maxDist; - static CSoundPOINode CopyNodeMinusStartTime(const CSoundPOINode& node, - const CCharAnimTime& startTime); - u32 GetSfxId() const { return x38_sfxId; } - float GetFalloff() const { return x3c_falloff; } - float GetMaxDist() const { return x40_maxDist; } +public: + CSoundPOINode(); + CSoundPOINode(CInputStream& in); + CSoundPOINode(std::string_view name, EPOIType type, const CCharAnimTime& time, u32 b, bool c, float d, u32 e, u32 f, + u32 sfxId, float falloff, float maxDist); + + static CSoundPOINode CopyNodeMinusStartTime(const CSoundPOINode& node, const CCharAnimTime& startTime); + u32 GetSfxId() const { return x38_sfxId; } + float GetFalloff() const { return x3c_falloff; } + float GetMaxDist() const { return x40_maxDist; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CSteeringBehaviors.cpp b/Runtime/Character/CSteeringBehaviors.cpp index e4f2a81a8..db00e3797 100644 --- a/Runtime/Character/CSteeringBehaviors.cpp +++ b/Runtime/Character/CSteeringBehaviors.cpp @@ -2,431 +2,364 @@ #include "World/CPhysicsActor.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { -zeus::CVector3f CSteeringBehaviors::Flee(const CPhysicsActor& actor, - const zeus::CVector3f& v0) const -{ - zeus::CVector3f actVec = actor.GetTranslation() - v0; - if (actVec.canBeNormalized()) - return actVec.normalized(); +zeus::CVector3f CSteeringBehaviors::Flee(const CPhysicsActor& actor, const zeus::CVector3f& v0) const { + zeus::CVector3f actVec = actor.GetTranslation() - v0; + if (actVec.canBeNormalized()) + return actVec.normalized(); - return actor.GetTransform().frontVector(); + return actor.GetTransform().frontVector(); } -zeus::CVector3f CSteeringBehaviors::Seek(const CPhysicsActor& actor, - const zeus::CVector3f& target) const -{ - zeus::CVector3f posDiff = target - actor.GetTranslation(); - if (posDiff.canBeNormalized()) - return posDiff.normalized(); +zeus::CVector3f CSteeringBehaviors::Seek(const CPhysicsActor& actor, const zeus::CVector3f& target) const { + zeus::CVector3f posDiff = target - actor.GetTranslation(); + if (posDiff.canBeNormalized()) + return posDiff.normalized(); + return {}; +} + +zeus::CVector3f CSteeringBehaviors::Arrival(const CPhysicsActor& actor, const zeus::CVector3f& dest, + float dampingRadius) const { + zeus::CVector3f posDiff = dest - actor.GetTranslation(); + if (!posDiff.canBeNormalized()) + return {}; + + if (posDiff.magSquared() < (dampingRadius * dampingRadius)) + dampingRadius = posDiff.magSquared() / (dampingRadius * dampingRadius); + else + dampingRadius = 1.f; + + return dampingRadius * posDiff.normalized(); +} + +zeus::CVector3f CSteeringBehaviors::Pursuit(const CPhysicsActor& actor, const zeus::CVector3f& v0, + const zeus::CVector3f& v1) const { + zeus::CVector3f target; + if (!ProjectLinearIntersection(actor.GetTranslation(), actor.GetVelocity().magnitude(), v0, v1, target)) + target = v1 * 1.f + v0; + return CSteeringBehaviors::Seek(actor, target); +} + +zeus::CVector3f CSteeringBehaviors::Separation(const CPhysicsActor& actor, const zeus::CVector3f& pos, + float separation) const { + zeus::CVector3f posDiff = actor.GetTranslation() - pos; + if (posDiff.magSquared() >= separation * separation) + return {}; + + if (!posDiff.canBeNormalized()) + return actor.GetTransform().frontVector(); + + return (1.f - (posDiff.magSquared() / (separation * separation))) * posDiff; +} + +zeus::CVector3f CSteeringBehaviors::Alignment(const CPhysicsActor& actor, rstl::reserved_vector& list, + const CStateManager& mgr) const { + zeus::CVector3f align; + + if (!list.empty()) { + for (const TUniqueId& id : list) + if (const CActor* act = static_cast(mgr.GetObjectById(id))) + align += act->GetTransform().frontVector(); + + align *= zeus::CVector3f(1.f / float(list.size())); + } + + float diff = zeus::CVector3f::getAngleDiff(actor.GetTransform().frontVector(), align); + return align * (diff / M_PIF); +} + +zeus::CVector3f CSteeringBehaviors::Cohesion(const CPhysicsActor& actor, rstl::reserved_vector& list, + float dampingRadius, const CStateManager& mgr) const { + zeus::CVector3f dest; + if (!list.empty()) { + for (const TUniqueId& id : list) + if (const CActor* act = static_cast(mgr.GetObjectById(id))) + dest += act->GetTranslation(); + + dest *= zeus::CVector3f(1.f / float(list.size())); + return Arrival(actor, dest, dampingRadius); + } + return dest; +} + +zeus::CVector2f CSteeringBehaviors::Flee2D(const CPhysicsActor& actor, const zeus::CVector2f& v0) const { + zeus::CVector2f diffVec = actor.GetTranslation().toVec2f() - v0; + if (diffVec.magSquared() > FLT_EPSILON) + return diffVec.normalized(); + else + return actor.GetTransform().basis[1].toVec2f(); +} + +zeus::CVector2f CSteeringBehaviors::Arrival2D(const CPhysicsActor& actor, const zeus::CVector2f& v0, float f1) const { + zeus::CVector2f diffVec = v0 - actor.GetTranslation().toVec2f(); + if (diffVec.magSquared() > FLT_EPSILON) + return diffVec.normalized(); + else return {}; } -zeus::CVector3f CSteeringBehaviors::Arrival(const CPhysicsActor& actor, - const zeus::CVector3f& dest, float dampingRadius) const -{ - zeus::CVector3f posDiff = dest - actor.GetTranslation(); - if (!posDiff.canBeNormalized()) - return {}; +bool CSteeringBehaviors::SolveQuadratic(float a, float b, float c, float& xPos, float& xNeg) { + float numSq = b * b - 4.f * a * c; + if (numSq < FLT_EPSILON || std::fabs(a) < FLT_EPSILON) + return false; - if (posDiff.magSquared() < (dampingRadius * dampingRadius)) - dampingRadius = posDiff.magSquared() / (dampingRadius * dampingRadius); - else - dampingRadius = 1.f; - - return dampingRadius * posDiff.normalized(); + numSq = std::sqrt(numSq); + float denom = 2.f * a; + xPos = (-b + numSq) / denom; + xNeg = (-b - numSq) / denom; + return true; } -zeus::CVector3f CSteeringBehaviors::Pursuit(const CPhysicsActor& actor, - const zeus::CVector3f& v0, const zeus::CVector3f& v1) const -{ - zeus::CVector3f target; - if (!ProjectLinearIntersection(actor.GetTranslation(), actor.GetVelocity().magnitude(), v0, v1, target)) - target = v1 * 1.f + v0; - return CSteeringBehaviors::Seek(actor, target); -} - -zeus::CVector3f CSteeringBehaviors::Separation(const CPhysicsActor& actor, - const zeus::CVector3f& pos, float separation) const -{ - zeus::CVector3f posDiff = actor.GetTranslation() - pos; - if (posDiff.magSquared() >= separation * separation) - return {}; - - if (!posDiff.canBeNormalized()) - return actor.GetTransform().frontVector(); - - return (1.f - (posDiff.magSquared() / (separation * separation))) * posDiff; -} - -zeus::CVector3f CSteeringBehaviors::Alignment(const CPhysicsActor& actor, - rstl::reserved_vector& list, const CStateManager& mgr) const -{ - zeus::CVector3f align; - - if (!list.empty()) - { - for (const TUniqueId& id : list) - if (const CActor* act = static_cast(mgr.GetObjectById(id))) - align += act->GetTransform().frontVector(); - - align *= zeus::CVector3f(1.f / float(list.size())); +bool CSteeringBehaviors::SolveCubic(const rstl::reserved_vector& in, rstl::reserved_vector& out) { + if (in[3] != 0.f) { + float f3 = 3.f * in[3]; + float f31 = in[2] / f3; + float f4 = in[1] / f3 - f31 * f31; + float f0 = (f31 * f4 - in[0]) / in[3]; + float f1 = 2.f * f31 * f31; + f3 = f4 * f4 * f4; + float f24 = -0.5f * (f31 * f1 - f0); + f1 = f24 * f24 + f3; + if (f1 < 0.f) { + float f25 = std::acos(zeus::clamp(-1.f, f24 / std::sqrt(-f3), 1.f)); + f24 = 2.f * std::pow(-f3, 0.166667f); + for (float f23 = 0.f; f23 < 2.01f; f23 += 1.f) + out.push_back(std::cos((2.f * f23 * M_PIF + f25) / 3.f) * f24 - f31); + if (out[1] < out[0]) + std::swap(out[1], out[0]); + if (out[2] < out[1]) + std::swap(out[2], out[1]); + if (out[1] < out[0]) + std::swap(out[1], out[0]); + } else { + float f30 = std::sqrt(f1); + float f25 = std::pow(std::fabs(f24 + f30), 0.333333f); + f1 = std::pow(std::fabs(f24 - f30), 0.333333f); + f1 = (f24 - f30) > 0.f ? f1 : -f1; + f25 = (f24 + f30) > 0.f ? f25 : -f25; + out.push_back(f25 + f1 - f31); } - - float diff = zeus::CVector3f::getAngleDiff(actor.GetTransform().frontVector(), align); - return align * (diff / M_PIF); -} - -zeus::CVector3f CSteeringBehaviors::Cohesion(const CPhysicsActor& actor, - rstl::reserved_vector& list, float dampingRadius, const CStateManager& mgr) const -{ - zeus::CVector3f dest; - if (!list.empty()) - { - for (const TUniqueId& id : list) - if (const CActor* act = static_cast(mgr.GetObjectById(id))) - dest += act->GetTranslation(); - - dest *= zeus::CVector3f(1.f / float(list.size())); - return Arrival(actor, dest, dampingRadius); + for (float& f : out) { + float f8 = (2.f * in[2] + 3.f * f * in[3]) * f + in[1]; + if (f8 != 0.f) + f -= (((f * in[3] + in[2]) * f + in[1]) * f + in[0]) / f8; } - return dest; + } else if (in[2] != 0.f) { + float f23 = 0.5f * in[1] / in[2]; + float f1 = f23 * f23 - (in[1] / in[2]); + if (f1 >= 0.f) { + f1 = std::sqrt(f1); + out.push_back(-f23 - f1); + out.push_back(-f23 + f1); + } + } else if (in[1] != 0.f) { + out.push_back(-in[0] / in[1]); + } + return out.size() != 0; } -zeus::CVector2f CSteeringBehaviors::Flee2D(const CPhysicsActor& actor, - const zeus::CVector2f& v0) const -{ - zeus::CVector2f diffVec = actor.GetTranslation().toVec2f() - v0; - if (diffVec.magSquared() > FLT_EPSILON) - return diffVec.normalized(); - else - return actor.GetTransform().basis[1].toVec2f(); -} - -zeus::CVector2f CSteeringBehaviors::Arrival2D(const CPhysicsActor& actor, - const zeus::CVector2f& v0, float f1) const -{ - zeus::CVector2f diffVec = v0 - actor.GetTranslation().toVec2f(); - if (diffVec.magSquared() > FLT_EPSILON) - return diffVec.normalized(); - else - return {}; -} - -bool CSteeringBehaviors::SolveQuadratic(float a, float b, float c, float& xPos, float& xNeg) -{ - float numSq = b * b - 4.f * a * c; - if (numSq < FLT_EPSILON || std::fabs(a) < FLT_EPSILON) - return false; - - numSq = std::sqrt(numSq); - float denom = 2.f * a; - xPos = (-b + numSq) / denom; - xNeg = (-b - numSq) / denom; - return true; -} - -bool CSteeringBehaviors::SolveCubic( - const rstl::reserved_vector& in, rstl::reserved_vector& out) -{ - if (in[3] != 0.f) - { - float f3 = 3.f * in[3]; - float f31 = in[2] / f3; - float f4 = in[1] / f3 - f31 * f31; - float f0 = (f31 * f4 - in[0]) / in[3]; - float f1 = 2.f * f31 * f31; - f3 = f4 * f4 * f4; - float f24 = -0.5f * (f31 * f1 - f0); - f1 = f24 * f24 + f3; +bool CSteeringBehaviors::SolveQuartic(const rstl::reserved_vector& in, rstl::reserved_vector& out) { + if (in[4] == 0.f) { + rstl::reserved_vector newIn; + newIn.push_back(in[0]); + newIn.push_back(in[1]); + newIn.push_back(in[2]); + newIn.push_back(in[3]); + return SolveCubic(newIn, out); + } else { + rstl::reserved_vector newIn; + float f30 = in[3] / (4.f * in[4]); + float f2 = in[1] / in[4]; + float f29 = f30 * (8.f * f30 * f30 - 2.f * in[2] / in[4]) + f2; + float f31 = -6.f * f30 * f30 + (in[2] / in[4]); + float f28 = f30 * (f30 * (-3.f * f30 * f30 + (in[2] / in[4])) - f2) + (in[0] / in[4]); + newIn.push_back(4.f * f28 * f31 - f29 * f29); + newIn.push_back(-8.f * f28); + newIn.push_back(-4.f * f31); + newIn.push_back(8.f); + rstl::reserved_vector newOut; + if (SolveCubic(newIn, newOut)) { + float f26 = 2.f * newOut.back() - f31; + f31 = std::sqrt(f26); + float f1; + if (f31 == 0.f) { + f1 = newOut.back() * newOut.back() - f28; if (f1 < 0.f) - { - float f25 = std::acos(zeus::clamp(-1.f, f24 / std::sqrt(-f3), 1.f)); - f24 = 2.f * std::pow(-f3, 0.166667f); - for (float f23 = 0.f; f23 < 2.01f; f23 += 1.f) - out.push_back(std::cos((2.f * f23 * M_PIF + f25) / 3.f) * f24 - f31); - if (out[1] < out[0]) - std::swap(out[1], out[0]); - if (out[2] < out[1]) - std::swap(out[2], out[1]); - if (out[1] < out[0]) - std::swap(out[1], out[0]); - } - else - { - float f30 = std::sqrt(f1); - float f25 = std::pow(std::fabs(f24 + f30), 0.333333f); - f1 = std::pow(std::fabs(f24 - f30), 0.333333f); - f1 = (f24 - f30) > 0.f ? f1 : -f1; - f25 = (f24 + f30) > 0.f ? f25 : -f25; - out.push_back(f25 + f1 - f31); - } - for (float& f : out) - { - float f8 = (2.f * in[2] + 3.f * f * in[3]) * f + in[1]; - if (f8 != 0.f) - f -= (((f * in[3] + in[2]) * f + in[1]) * f + in[0]) / f8; - } - } - else if (in[2] != 0.f) - { - float f23 = 0.5f * in[1] / in[2]; - float f1 = f23 * f23 - (in[1] / in[2]); - if (f1 >= 0.f) - { - f1 = std::sqrt(f1); - out.push_back(-f23 - f1); - out.push_back(-f23 + f1); - } - } - else if (in[1] != 0.f) - { - out.push_back(-in[0] / in[1]); + return false; + f1 = std::sqrt(f1); + } else { + f1 = f29 / (2.f * f31); + } + float f1b = f26 - (newOut.back() + f1) * 4.f; + f26 = f26 - (newOut.back() - f1) * 4.f; + if (f1b >= 0.f) { + f1b = std::sqrt(f1b); + out.push_back((f31 - f1b) * 0.5f - f30); + out.push_back((f31 + f1b) * 0.5f - f30); + } + if (f26 >= 0.f) { + f1b = std::sqrt(f26); + out.push_back((-f31 - f1b) * 0.5f - f30); + out.push_back((-f31 + f1b) * 0.5f - f30); + } + for (float& f : out) { + float f10 = ((3.f * in[3] + 4.f * f * in[4]) * f + 2.f * in[2]) * f + in[1]; + if (f10 != 0.f) + f -= ((((f * in[4] + in[3]) * f + in[2]) * f + in[1]) * f + in[0]) / f10; + } + if (out.size() > 2) { + if (out[2] < out[0]) + std::swap(out[2], out[0]); + if (out[3] < out[1]) + std::swap(out[3], out[1]); + if (out[1] < out[0]) + std::swap(out[1], out[0]); + if (out[3] < out[2]) + std::swap(out[3], out[2]); + if (out[2] < out[1]) + std::swap(out[2], out[1]); + } } return out.size() != 0; + } } -bool CSteeringBehaviors::SolveQuartic( - const rstl::reserved_vector& in, rstl::reserved_vector& out) -{ - if (in[4] == 0.f) - { - rstl::reserved_vector newIn; - newIn.push_back(in[0]); - newIn.push_back(in[1]); - newIn.push_back(in[2]); - newIn.push_back(in[3]); - return SolveCubic(newIn, out); - } - else - { - rstl::reserved_vector newIn; - float f30 = in[3] / (4.f * in[4]); - float f2 = in[1] / in[4]; - float f29 = f30 * (8.f * f30 * f30 - 2.f * in[2] / in[4]) + f2; - float f31 = -6.f * f30 * f30 + (in[2] / in[4]); - float f28 = f30 * (f30 * (-3.f * f30 * f30 + (in[2] / in[4])) - f2) + (in[0] / in[4]); - newIn.push_back(4.f * f28 * f31 - f29 * f29); - newIn.push_back(-8.f * f28); - newIn.push_back(-4.f * f31); - newIn.push_back(8.f); - rstl::reserved_vector newOut; - if (SolveCubic(newIn, newOut)) - { - float f26 = 2.f * newOut.back() - f31; - f31 = std::sqrt(f26); - float f1; - if (f31 == 0.f) - { - f1 = newOut.back() * newOut.back() - f28; - if (f1 < 0.f) - return false; - f1 = std::sqrt(f1); - } - else - { - f1 = f29 / (2.f * f31); - } - float f1b = f26 - (newOut.back() + f1) * 4.f; - f26 = f26 - (newOut.back() - f1) * 4.f; - if (f1b >= 0.f) - { - f1b = std::sqrt(f1b); - out.push_back((f31 - f1b) * 0.5f - f30); - out.push_back((f31 + f1b) * 0.5f - f30); - } - if (f26 >= 0.f) - { - f1b = std::sqrt(f26); - out.push_back((-f31 - f1b) * 0.5f - f30); - out.push_back((-f31 + f1b) * 0.5f - f30); - } - for (float& f : out) - { - float f10 = ((3.f * in[3] + 4.f * f * in[4]) * f + 2.f * in[2]) * f + in[1]; - if (f10 != 0.f) - f -= ((((f * in[4] + in[3]) * f + in[2]) * f + in[1]) * f + in[0]) / f10; - } - if (out.size() > 2) - { - if (out[2] < out[0]) - std::swap(out[2], out[0]); - if (out[3] < out[1]) - std::swap(out[3], out[1]); - if (out[1] < out[0]) - std::swap(out[1], out[0]); - if (out[3] < out[2]) - std::swap(out[3], out[2]); - if (out[2] < out[1]) - std::swap(out[2], out[1]); - } - } - return out.size() != 0; - } +bool CSteeringBehaviors::ProjectLinearIntersection(const zeus::CVector3f& v0, float f1, const zeus::CVector3f& v1, + const zeus::CVector3f& v2, zeus::CVector3f& v3) { + zeus::CVector3f posDiff = v1 - v0; + float xPos, xNeg; + if (SolveQuadratic(v2.magSquared() - f1 * f1, posDiff.dot(v2) * 2.f, posDiff.magSquared(), xPos, xNeg) && + xNeg > 0.f) { + v3 = v2 * xNeg + v1; + return true; + } + return false; } -bool CSteeringBehaviors::ProjectLinearIntersection(const zeus::CVector3f& v0, float f1, - const zeus::CVector3f& v1, const zeus::CVector3f& v2, zeus::CVector3f& v3) -{ - zeus::CVector3f posDiff = v1 - v0; - float xPos, xNeg; - if (SolveQuadratic(v2.magSquared() - f1 * f1, - posDiff.dot(v2) * 2.f, - posDiff.magSquared(), - xPos, xNeg) && xNeg > 0.f) - { - v3 = v2 * xNeg + v1; - return true; - } - return false; -} - -bool CSteeringBehaviors::ProjectLinearIntersection(const zeus::CVector3f& v0, float f1, - const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3, zeus::CVector3f& v4) -{ - rstl::reserved_vector newIn; - rstl::reserved_vector newOut; - zeus::CVector3f f7 = v1 - v0; - newIn.push_back(f7.magSquared()); - newIn.push_back(f7.dot(v2) * 2.f); - newIn.push_back(f7.dot(v3) + v2.magSquared() - f1 * f1); - newIn.push_back(v2.dot(v3)); - newIn.push_back(v3.magSquared() * 0.25f); - bool ret = false; - if (SolveQuartic(newIn, newOut)) - for (float& f : newOut) - if (f > 0.f) - { - ret = true; - v4 = v1 + v2 * f + 0.5f * f * f * v3; - } - return ret; +bool CSteeringBehaviors::ProjectLinearIntersection(const zeus::CVector3f& v0, float f1, const zeus::CVector3f& v1, + const zeus::CVector3f& v2, const zeus::CVector3f& v3, + zeus::CVector3f& v4) { + rstl::reserved_vector newIn; + rstl::reserved_vector newOut; + zeus::CVector3f f7 = v1 - v0; + newIn.push_back(f7.magSquared()); + newIn.push_back(f7.dot(v2) * 2.f); + newIn.push_back(f7.dot(v3) + v2.magSquared() - f1 * f1); + newIn.push_back(v2.dot(v3)); + newIn.push_back(v3.magSquared() * 0.25f); + bool ret = false; + if (SolveQuartic(newIn, newOut)) + for (float& f : newOut) + if (f > 0.f) { + ret = true; + v4 = v1 + v2 * f + 0.5f * f * f * v3; + } + return ret; } bool CSteeringBehaviors::ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1, float f2, - const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3, zeus::CVector3f& v4) -{ - if (f1 > 0.f) - { - if (v2.canBeNormalized()) - { - zeus::CVector3f _12c = (v1 - v3).toVec2f(); - if (_12c.canBeNormalized()) - { - zeus::CVector3f f25 = v1; - zeus::CVector3f f22 = v2; - float f17 = (f25 - v0).magnitude() / f1 - 0.f; - float f18 = FLT_MAX; - zeus::CVector3f _150 = _12c.normalized(); - float f26 = _150.dot(f22); - float f27 = _150.cross(zeus::CVector3f::skUp).dot(f22); - for (float f19 = 0.f; f17 < f18 && f19 < 4.f;) - { - if (zeus::close_enough(f17, f2) || f17 < 0.f) - { - v4 = f25; - return true; - } - f25 += f2 * f22; - f18 = f17; - _12c = (f25 - v3).toVec2f(); - if (!_12c.canBeNormalized()) - break; - zeus::CVector3f _168 = _12c.normalized(); - f22 = _168.cross(zeus::CVector3f::skUp) * f27 + f26 * _168; - f19 += f2; - f17 = (f25 - v0).magnitude() / f1 - f19; - } - } - else - { - return ProjectLinearIntersection(v0, f1, v1, v2, v4); - } - } - else - { - v4 = v1; + const zeus::CVector3f& v1, const zeus::CVector3f& v2, + const zeus::CVector3f& v3, zeus::CVector3f& v4) { + if (f1 > 0.f) { + if (v2.canBeNormalized()) { + zeus::CVector3f _12c = (v1 - v3).toVec2f(); + if (_12c.canBeNormalized()) { + zeus::CVector3f f25 = v1; + zeus::CVector3f f22 = v2; + float f17 = (f25 - v0).magnitude() / f1 - 0.f; + float f18 = FLT_MAX; + zeus::CVector3f _150 = _12c.normalized(); + float f26 = _150.dot(f22); + float f27 = _150.cross(zeus::CVector3f::skUp).dot(f22); + for (float f19 = 0.f; f17 < f18 && f19 < 4.f;) { + if (zeus::close_enough(f17, f2) || f17 < 0.f) { + v4 = f25; return true; + } + f25 += f2 * f22; + f18 = f17; + _12c = (f25 - v3).toVec2f(); + if (!_12c.canBeNormalized()) + break; + zeus::CVector3f _168 = _12c.normalized(); + f22 = _168.cross(zeus::CVector3f::skUp) * f27 + f26 * _168; + f19 += f2; + f17 = (f25 - v0).magnitude() / f1 - f19; } + } else { + return ProjectLinearIntersection(v0, f1, v1, v2, v4); + } + } else { + v4 = v1; + return true; } - return false; + } + return false; } bool CSteeringBehaviors::ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1, float f2, - const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3, - const zeus::CVector3f& v4, zeus::CVector3f& v5) -{ - if (f1 > 0.f) - { - zeus::CVector3f _12c = (v1 - v4).toVec2f(); - if (v2.canBeNormalized() && _12c.canBeNormalized()) - { - zeus::CVector3f f24 = v1; - zeus::CVector3f f21 = v2; - float f16 = (f24 - v0).magnitude() / f1 - 0.f; - float f17 = FLT_MAX; - zeus::CVector3f _150 = _12c.normalized(); - float f25 = _150.dot(f21); - float f26 = _150.cross(zeus::CVector3f::skUp).dot(f21); - for (float f18 = 0.f; f16 < f17 && f18 < 4.f;) - { - if (zeus::close_enough(f16, f2) || f16 < 0.f) - { - v5 = f24; - return true; - } - f24 += f2 * f21; - f17 = f16; - f18 += f2; - f16 = (f24 - v0).magnitude() / f1 - f18; - _12c = (f24 - v4).toVec2f(); - if (!_12c.canBeNormalized()) - break; - zeus::CVector3f _168 = _12c.normalized(); - f21 = _168.cross(zeus::CVector3f::skUp) * f26 + f25 * _168; - } - } - else - { - return ProjectLinearIntersection(v0, f1, v1, v2, v3, v5); + const zeus::CVector3f& v1, const zeus::CVector3f& v2, + const zeus::CVector3f& v3, const zeus::CVector3f& v4, + zeus::CVector3f& v5) { + if (f1 > 0.f) { + zeus::CVector3f _12c = (v1 - v4).toVec2f(); + if (v2.canBeNormalized() && _12c.canBeNormalized()) { + zeus::CVector3f f24 = v1; + zeus::CVector3f f21 = v2; + float f16 = (f24 - v0).magnitude() / f1 - 0.f; + float f17 = FLT_MAX; + zeus::CVector3f _150 = _12c.normalized(); + float f25 = _150.dot(f21); + float f26 = _150.cross(zeus::CVector3f::skUp).dot(f21); + for (float f18 = 0.f; f16 < f17 && f18 < 4.f;) { + if (zeus::close_enough(f16, f2) || f16 < 0.f) { + v5 = f24; + return true; } + f24 += f2 * f21; + f17 = f16; + f18 += f2; + f16 = (f24 - v0).magnitude() / f1 - f18; + _12c = (f24 - v4).toVec2f(); + if (!_12c.canBeNormalized()) + break; + zeus::CVector3f _168 = _12c.normalized(); + f21 = _168.cross(zeus::CVector3f::skUp) * f26 + f25 * _168; + } + } else { + return ProjectLinearIntersection(v0, f1, v1, v2, v3, v5); } - return false; + } + return false; } -zeus::CVector3f -CSteeringBehaviors::ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel, - const zeus::CVector3f& orbitPoint, float dt, float preThinkDt) -{ - zeus::CVector3f usePos = pos; - if (vel.canBeNormalized()) - { - zeus::CVector3f pointToPos = pos - orbitPoint; - pointToPos.z() = 0.f; - if (pointToPos.canBeNormalized()) - { - zeus::CVector3f useVel = vel; - pointToPos.normalize(); - float f29 = pointToPos.dot(useVel); - float f30 = pointToPos.cross(zeus::CVector3f::skUp).dot(useVel); - for (float curDt = 0.f ; curDt < dt ;) - { - usePos += preThinkDt * useVel; - zeus::CVector3f usePointToPos = usePos - orbitPoint; - usePointToPos.z() = 0.f; - if (usePointToPos.canBeNormalized()) - { - usePointToPos.normalize(); - useVel = usePointToPos.cross(zeus::CVector3f::skUp) * f30 + usePointToPos * f29; - } - curDt += std::min(dt - curDt, preThinkDt); - } +zeus::CVector3f CSteeringBehaviors::ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel, + const zeus::CVector3f& orbitPoint, float dt, + float preThinkDt) { + zeus::CVector3f usePos = pos; + if (vel.canBeNormalized()) { + zeus::CVector3f pointToPos = pos - orbitPoint; + pointToPos.z() = 0.f; + if (pointToPos.canBeNormalized()) { + zeus::CVector3f useVel = vel; + pointToPos.normalize(); + float f29 = pointToPos.dot(useVel); + float f30 = pointToPos.cross(zeus::CVector3f::skUp).dot(useVel); + for (float curDt = 0.f; curDt < dt;) { + usePos += preThinkDt * useVel; + zeus::CVector3f usePointToPos = usePos - orbitPoint; + usePointToPos.z() = 0.f; + if (usePointToPos.canBeNormalized()) { + usePointToPos.normalize(); + useVel = usePointToPos.cross(zeus::CVector3f::skUp) * f30 + usePointToPos * f29; } + curDt += std::min(dt - curDt, preThinkDt); + } } - return usePos; + } + return usePos; } -} +} // namespace urde diff --git a/Runtime/Character/CSteeringBehaviors.hpp b/Runtime/Character/CSteeringBehaviors.hpp index a0443ed77..7dce9d580 100644 --- a/Runtime/Character/CSteeringBehaviors.hpp +++ b/Runtime/Character/CSteeringBehaviors.hpp @@ -3,43 +3,39 @@ #include "RetroTypes.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { class CPhysicsActor; class CStateManager; -class CSteeringBehaviors -{ - float x0_ = M_PIF / 2.f; +class CSteeringBehaviors { + float x0_ = M_PIF / 2.f; + public: - zeus::CVector3f Flee(const CPhysicsActor& actor, const zeus::CVector3f& v0) const; - zeus::CVector3f Seek(const CPhysicsActor& actor, const zeus::CVector3f& target) const; - zeus::CVector3f Arrival(const CPhysicsActor& actor, const zeus::CVector3f& dest, float dampingRadius) const; - zeus::CVector3f Pursuit(const CPhysicsActor& actor, const zeus::CVector3f& v0, const zeus::CVector3f& v1) const; - zeus::CVector3f Separation(const CPhysicsActor& actor, const zeus::CVector3f& pos, float separation) const; - zeus::CVector3f Alignment(const CPhysicsActor& actor, rstl::reserved_vector& list, - const CStateManager& mgr) const; - zeus::CVector3f Cohesion(const CPhysicsActor& actor, rstl::reserved_vector& list, - float dampingRadius, const CStateManager& mgr) const; - zeus::CVector2f Flee2D(const CPhysicsActor& actor, const zeus::CVector2f& v0) const; - zeus::CVector2f Arrival2D(const CPhysicsActor& actor, const zeus::CVector2f& v0, float f1) const; - static bool SolveQuadratic(float, float, float, float&, float&); - static bool SolveCubic(const rstl::reserved_vector& in, rstl::reserved_vector& out); - static bool SolveQuartic(const rstl::reserved_vector& in, rstl::reserved_vector& out); - static bool ProjectLinearIntersection(const zeus::CVector3f& v0, float f1, - const zeus::CVector3f& v1, const zeus::CVector3f& v2, zeus::CVector3f& v3); - static bool ProjectLinearIntersection(const zeus::CVector3f& v0, float f1, - const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3, - zeus::CVector3f& v4); - static bool ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1, float f2, - const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3, - zeus::CVector3f& v4); - static bool ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1, float f2, - const zeus::CVector3f& v1, const zeus::CVector3f& v2, const zeus::CVector3f& v3, - const zeus::CVector3f& v4, zeus::CVector3f& v5); - static zeus::CVector3f ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel, - const zeus::CVector3f& orbitPoint, float dt, float preThinkDt); + zeus::CVector3f Flee(const CPhysicsActor& actor, const zeus::CVector3f& v0) const; + zeus::CVector3f Seek(const CPhysicsActor& actor, const zeus::CVector3f& target) const; + zeus::CVector3f Arrival(const CPhysicsActor& actor, const zeus::CVector3f& dest, float dampingRadius) const; + zeus::CVector3f Pursuit(const CPhysicsActor& actor, const zeus::CVector3f& v0, const zeus::CVector3f& v1) const; + zeus::CVector3f Separation(const CPhysicsActor& actor, const zeus::CVector3f& pos, float separation) const; + zeus::CVector3f Alignment(const CPhysicsActor& actor, rstl::reserved_vector& list, + const CStateManager& mgr) const; + zeus::CVector3f Cohesion(const CPhysicsActor& actor, rstl::reserved_vector& list, + float dampingRadius, const CStateManager& mgr) const; + zeus::CVector2f Flee2D(const CPhysicsActor& actor, const zeus::CVector2f& v0) const; + zeus::CVector2f Arrival2D(const CPhysicsActor& actor, const zeus::CVector2f& v0, float f1) const; + static bool SolveQuadratic(float, float, float, float&, float&); + static bool SolveCubic(const rstl::reserved_vector& in, rstl::reserved_vector& out); + static bool SolveQuartic(const rstl::reserved_vector& in, rstl::reserved_vector& out); + static bool ProjectLinearIntersection(const zeus::CVector3f& v0, float f1, const zeus::CVector3f& v1, + const zeus::CVector3f& v2, zeus::CVector3f& v3); + static bool ProjectLinearIntersection(const zeus::CVector3f& v0, float f1, const zeus::CVector3f& v1, + const zeus::CVector3f& v2, const zeus::CVector3f& v3, zeus::CVector3f& v4); + static bool ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1, float f2, const zeus::CVector3f& v1, + const zeus::CVector3f& v2, const zeus::CVector3f& v3, zeus::CVector3f& v4); + static bool ProjectOrbitalIntersection(const zeus::CVector3f& v0, float f1, float f2, const zeus::CVector3f& v1, + const zeus::CVector3f& v2, const zeus::CVector3f& v3, + const zeus::CVector3f& v4, zeus::CVector3f& v5); + static zeus::CVector3f ProjectOrbitalPosition(const zeus::CVector3f& pos, const zeus::CVector3f& vel, + const zeus::CVector3f& orbitPoint, float dt, float preThinkDt); }; -} - +} // namespace urde diff --git a/Runtime/Character/CTimeScaleFunctions.cpp b/Runtime/Character/CTimeScaleFunctions.cpp index 5ba36519b..401a5b9c4 100644 --- a/Runtime/Character/CTimeScaleFunctions.cpp +++ b/Runtime/Character/CTimeScaleFunctions.cpp @@ -1,107 +1,89 @@ #include "CTimeScaleFunctions.hpp" #include "zeus/Math.hpp" -namespace urde -{ +namespace urde { -std::unique_ptr IVaryingAnimationTimeScale::Clone() const -{ - return VClone(); +std::unique_ptr IVaryingAnimationTimeScale::Clone() const { return VClone(); } + +float CConstantAnimationTimeScale::VTimeScaleIntegral(float lowerLimit, float upperLimit) const { + return (upperLimit - lowerLimit) * x4_scale; } -float CConstantAnimationTimeScale::VTimeScaleIntegral(float lowerLimit, float upperLimit) const -{ - return (upperLimit - lowerLimit) * x4_scale; +float CConstantAnimationTimeScale::VFindUpperLimit(float lowerLimit, float root) const { + return (root / x4_scale) + lowerLimit; } -float CConstantAnimationTimeScale::VFindUpperLimit(float lowerLimit, float root) const -{ - return (root / x4_scale) + lowerLimit; +std::unique_ptr CConstantAnimationTimeScale::VClone() const { + return std::make_unique(x4_scale); } -std::unique_ptr CConstantAnimationTimeScale::VClone() const -{ - return std::make_unique(x4_scale); +std::unique_ptr CConstantAnimationTimeScale::VGetFunctionMirrored(float) const { + return Clone(); } -std::unique_ptr CConstantAnimationTimeScale::VGetFunctionMirrored(float) const -{ - return Clone(); -} - -CLinearAnimationTimeScale::CLinearAnimationTimeScale(const CCharAnimTime& t1, float y1, - const CCharAnimTime& t2, float y2) -{ - float y2my1 = y2 - y1; - float t2mt1 = (t2 - t1).GetSeconds(); - x4_desc.x4_slope = y2my1 / t2mt1; - x4_desc.x8_yIntercept = y1 - y2my1 / t2mt1 * t1.GetSeconds(); - x4_desc.xc_t1 = t1.GetSeconds(); - x4_desc.x10_t2 = t2.GetSeconds(); +CLinearAnimationTimeScale::CLinearAnimationTimeScale(const CCharAnimTime& t1, float y1, const CCharAnimTime& t2, + float y2) { + float y2my1 = y2 - y1; + float t2mt1 = (t2 - t1).GetSeconds(); + x4_desc.x4_slope = y2my1 / t2mt1; + x4_desc.x8_yIntercept = y1 - y2my1 / t2mt1 * t1.GetSeconds(); + x4_desc.xc_t1 = t1.GetSeconds(); + x4_desc.x10_t2 = t2.GetSeconds(); } std::unique_ptr -CLinearAnimationTimeScale::CFunctionDescription::FunctionMirroredAround(float value) const -{ - float slope = -x4_slope; - float t1 = 2.f * value - x10_t2; - float t2 = 2.f * value - xc_t1; - float newYInt = x8_yIntercept - x4_slope * 2.f * value; - float y1 = slope * t1 + newYInt; - float y2 = slope * t2 + newYInt; - return std::make_unique(t1, y1, t2, y2); +CLinearAnimationTimeScale::CFunctionDescription::FunctionMirroredAround(float value) const { + float slope = -x4_slope; + float t1 = 2.f * value - x10_t2; + float t2 = 2.f * value - xc_t1; + float newYInt = x8_yIntercept - x4_slope * 2.f * value; + float y1 = slope * t1 + newYInt; + float y2 = slope * t2 + newYInt; + return std::make_unique(t1, y1, t2, y2); } -float CLinearAnimationTimeScale::VTimeScaleIntegral(float lowerLimit, float upperLimit) const -{ - if (lowerLimit <= upperLimit) - return TimeScaleIntegralWithSortedLimits(x4_desc, lowerLimit, upperLimit); - else - return -TimeScaleIntegralWithSortedLimits(x4_desc, upperLimit, lowerLimit); +float CLinearAnimationTimeScale::VTimeScaleIntegral(float lowerLimit, float upperLimit) const { + if (lowerLimit <= upperLimit) + return TimeScaleIntegralWithSortedLimits(x4_desc, lowerLimit, upperLimit); + else + return -TimeScaleIntegralWithSortedLimits(x4_desc, upperLimit, lowerLimit); } -float CLinearAnimationTimeScale::TimeScaleIntegralWithSortedLimits(const CFunctionDescription& desc, - float lowerLimit, float upperLimit) -{ - float lowerEval = desc.x4_slope * lowerLimit + desc.x8_yIntercept; - float upperEval = desc.x4_slope * upperLimit + desc.x8_yIntercept; - return (upperLimit - lowerLimit) * 0.5f * (lowerEval + upperEval); +float CLinearAnimationTimeScale::TimeScaleIntegralWithSortedLimits(const CFunctionDescription& desc, float lowerLimit, + float upperLimit) { + float lowerEval = desc.x4_slope * lowerLimit + desc.x8_yIntercept; + float upperEval = desc.x4_slope * upperLimit + desc.x8_yIntercept; + return (upperLimit - lowerLimit) * 0.5f * (lowerEval + upperEval); } -float CLinearAnimationTimeScale::VFindUpperLimit(float lowerLimit, float root) const -{ - return FindUpperLimitFromRoot(x4_desc, lowerLimit, root); +float CLinearAnimationTimeScale::VFindUpperLimit(float lowerLimit, float root) const { + return FindUpperLimitFromRoot(x4_desc, lowerLimit, root); } -float CLinearAnimationTimeScale::FindUpperLimitFromRoot(const CFunctionDescription& desc, - float lowerLimit, float root) -{ - float M = 0.5f * desc.x4_slope; - float upperLimit = lowerLimit; - float m = 2.f * M; - float lowerIntegration = M * lowerLimit * lowerLimit + desc.x8_yIntercept * lowerLimit; - for (int i=0 ; i<16 ; ++i) - { - float factor = (M * upperLimit * upperLimit + desc.x8_yIntercept * upperLimit - lowerIntegration - root) / - (m * upperLimit + desc.x8_yIntercept); - upperLimit -= factor; - if (zeus::close_enough(factor, 0.f)) - return upperLimit; - } - return -1.f; +float CLinearAnimationTimeScale::FindUpperLimitFromRoot(const CFunctionDescription& desc, float lowerLimit, + float root) { + float M = 0.5f * desc.x4_slope; + float upperLimit = lowerLimit; + float m = 2.f * M; + float lowerIntegration = M * lowerLimit * lowerLimit + desc.x8_yIntercept * lowerLimit; + for (int i = 0; i < 16; ++i) { + float factor = (M * upperLimit * upperLimit + desc.x8_yIntercept * upperLimit - lowerIntegration - root) / + (m * upperLimit + desc.x8_yIntercept); + upperLimit -= factor; + if (zeus::close_enough(factor, 0.f)) + return upperLimit; + } + return -1.f; } -std::unique_ptr CLinearAnimationTimeScale::VClone() const -{ - float y1 = x4_desc.x4_slope * x4_desc.xc_t1 + x4_desc.x8_yIntercept; - float y2 = x4_desc.x4_slope * x4_desc.x10_t2 + x4_desc.x8_yIntercept; - return std::make_unique(x4_desc.xc_t1, y1, x4_desc.x10_t2, y2); +std::unique_ptr CLinearAnimationTimeScale::VClone() const { + float y1 = x4_desc.x4_slope * x4_desc.xc_t1 + x4_desc.x8_yIntercept; + float y2 = x4_desc.x4_slope * x4_desc.x10_t2 + x4_desc.x8_yIntercept; + return std::make_unique(x4_desc.xc_t1, y1, x4_desc.x10_t2, y2); } -std::unique_ptr -CLinearAnimationTimeScale::VGetFunctionMirrored(float value) const -{ - return x4_desc.FunctionMirroredAround(value); +std::unique_ptr CLinearAnimationTimeScale::VGetFunctionMirrored(float value) const { + return x4_desc.FunctionMirroredAround(value); } -} +} // namespace urde diff --git a/Runtime/Character/CTimeScaleFunctions.hpp b/Runtime/Character/CTimeScaleFunctions.hpp index 02dd8c4b1..559d0b3d7 100644 --- a/Runtime/Character/CTimeScaleFunctions.hpp +++ b/Runtime/Character/CTimeScaleFunctions.hpp @@ -3,65 +3,54 @@ #include "RetroTypes.hpp" #include "CCharAnimTime.hpp" -namespace urde -{ +namespace urde { -enum class EVaryingAnimationTimeScaleType -{ - Constant, - Linear -}; +enum class EVaryingAnimationTimeScaleType { Constant, Linear }; -class IVaryingAnimationTimeScale -{ +class IVaryingAnimationTimeScale { public: - virtual ~IVaryingAnimationTimeScale() = default; - virtual EVaryingAnimationTimeScaleType GetType() const=0; - virtual float VTimeScaleIntegral(float lowerLimit, float upperLimit) const=0; - virtual float VFindUpperLimit(float lowerLimit, float root) const=0; - virtual std::unique_ptr VClone() const=0; - virtual std::unique_ptr VGetFunctionMirrored(float value) const=0; - std::unique_ptr Clone() const; + virtual ~IVaryingAnimationTimeScale() = default; + virtual EVaryingAnimationTimeScaleType GetType() const = 0; + virtual float VTimeScaleIntegral(float lowerLimit, float upperLimit) const = 0; + virtual float VFindUpperLimit(float lowerLimit, float root) const = 0; + virtual std::unique_ptr VClone() const = 0; + virtual std::unique_ptr VGetFunctionMirrored(float value) const = 0; + std::unique_ptr Clone() const; }; -class CConstantAnimationTimeScale : public IVaryingAnimationTimeScale -{ +class CConstantAnimationTimeScale : public IVaryingAnimationTimeScale { private: - float x4_scale; -public: - CConstantAnimationTimeScale(float scale) : x4_scale(scale) {} + float x4_scale; - EVaryingAnimationTimeScaleType GetType() const { return EVaryingAnimationTimeScaleType::Constant; } - float VTimeScaleIntegral(float lowerLimit, float upperLimit) const; - float VFindUpperLimit(float lowerLimit, float root) const; - std::unique_ptr VClone() const; - std::unique_ptr VGetFunctionMirrored(float value) const; +public: + CConstantAnimationTimeScale(float scale) : x4_scale(scale) {} + + EVaryingAnimationTimeScaleType GetType() const { return EVaryingAnimationTimeScaleType::Constant; } + float VTimeScaleIntegral(float lowerLimit, float upperLimit) const; + float VFindUpperLimit(float lowerLimit, float root) const; + std::unique_ptr VClone() const; + std::unique_ptr VGetFunctionMirrored(float value) const; }; -class CLinearAnimationTimeScale : public IVaryingAnimationTimeScale -{ - struct CFunctionDescription - { - float x4_slope; - float x8_yIntercept; - float xc_t1; - float x10_t2; - std::unique_ptr FunctionMirroredAround(float value) const; - } x4_desc; - static float FindUpperLimitFromRoot(const CFunctionDescription& desc, - float lowerLimit, float root); - static float TimeScaleIntegralWithSortedLimits(const CFunctionDescription& desc, - float lowerLimit, float upperLimit); -public: - CLinearAnimationTimeScale(const CCharAnimTime& t1, float y1, - const CCharAnimTime& t2, float y2); +class CLinearAnimationTimeScale : public IVaryingAnimationTimeScale { + struct CFunctionDescription { + float x4_slope; + float x8_yIntercept; + float xc_t1; + float x10_t2; + std::unique_ptr FunctionMirroredAround(float value) const; + } x4_desc; + static float FindUpperLimitFromRoot(const CFunctionDescription& desc, float lowerLimit, float root); + static float TimeScaleIntegralWithSortedLimits(const CFunctionDescription& desc, float lowerLimit, float upperLimit); - EVaryingAnimationTimeScaleType GetType() const {return EVaryingAnimationTimeScaleType::Linear;} - float VTimeScaleIntegral(float lowerLimit, float upperLimit) const; - float VFindUpperLimit(float lowerLimit, float root) const; - std::unique_ptr VClone() const; - std::unique_ptr VGetFunctionMirrored(float value) const; +public: + CLinearAnimationTimeScale(const CCharAnimTime& t1, float y1, const CCharAnimTime& t2, float y2); + + EVaryingAnimationTimeScaleType GetType() const { return EVaryingAnimationTimeScaleType::Linear; } + float VTimeScaleIntegral(float lowerLimit, float upperLimit) const; + float VFindUpperLimit(float lowerLimit, float root) const; + std::unique_ptr VClone() const; + std::unique_ptr VGetFunctionMirrored(float value) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CTransition.cpp b/Runtime/Character/CTransition.cpp index 2ff489482..5382ee148 100644 --- a/Runtime/Character/CTransition.cpp +++ b/Runtime/Character/CTransition.cpp @@ -1,14 +1,11 @@ #include "CTransition.hpp" -namespace urde -{ +namespace urde { CTransition::CTransition(CInputStream& in) - : x0_id(in.readUint32Big()) - , x4_animA(in.readUint32Big()) - , x8_animB(in.readUint32Big()) - , xc_trans(CMetaTransFactory::CreateMetaTrans(in)) -{ -} +: x0_id(in.readUint32Big()) +, x4_animA(in.readUint32Big()) +, x8_animB(in.readUint32Big()) +, xc_trans(CMetaTransFactory::CreateMetaTrans(in)) {} -} +} // namespace urde diff --git a/Runtime/Character/CTransition.hpp b/Runtime/Character/CTransition.hpp index a245d9ff3..ac7f9f2ea 100644 --- a/Runtime/Character/CTransition.hpp +++ b/Runtime/Character/CTransition.hpp @@ -3,22 +3,20 @@ #include "IOStreams.hpp" #include "CMetaTransFactory.hpp" -namespace urde -{ +namespace urde { + +class CTransition { + u32 x0_id; + u32 x4_animA; + u32 x8_animB; + std::shared_ptr xc_trans; -class CTransition -{ - u32 x0_id; - u32 x4_animA; - u32 x8_animB; - std::shared_ptr xc_trans; public: - CTransition(CInputStream& in); - u32 GetAnimA() const {return x4_animA;} - u32 GetAnimB() const {return x8_animB;} - std::pair GetAnimPair() const {return {x4_animA, x8_animB};} - const std::shared_ptr& GetMetaTrans() const {return xc_trans;} + CTransition(CInputStream& in); + u32 GetAnimA() const { return x4_animA; } + u32 GetAnimB() const { return x8_animB; } + std::pair GetAnimPair() const { return {x4_animA, x8_animB}; } + const std::shared_ptr& GetMetaTrans() const { return xc_trans; } }; -} - +} // namespace urde diff --git a/Runtime/Character/CTransitionDatabase.hpp b/Runtime/Character/CTransitionDatabase.hpp index 16aec9974..2f91f3721 100644 --- a/Runtime/Character/CTransitionDatabase.hpp +++ b/Runtime/Character/CTransitionDatabase.hpp @@ -2,15 +2,12 @@ #include "../RetroTypes.hpp" -namespace urde -{ +namespace urde { class IMetaTrans; -class CTransitionDatabase -{ +class CTransitionDatabase { public: - virtual const std::shared_ptr& GetMetaTrans(u32, u32) const=0; + virtual const std::shared_ptr& GetMetaTrans(u32, u32) const = 0; }; -} - +} // namespace urde diff --git a/Runtime/Character/CTransitionDatabaseGame.cpp b/Runtime/Character/CTransitionDatabaseGame.cpp index ad4407c0d..90adebe62 100644 --- a/Runtime/Character/CTransitionDatabaseGame.cpp +++ b/Runtime/Character/CTransitionDatabaseGame.cpp @@ -2,33 +2,29 @@ #include "CTransition.hpp" #include "CHalfTransition.hpp" -namespace urde -{ +namespace urde { CTransitionDatabaseGame::CTransitionDatabaseGame(const std::vector& transitions, const std::vector& halfTransitions, const std::shared_ptr& defaultTrans) -: x10_defaultTrans(defaultTrans) -{ - x14_transitions.reserve(transitions.size()); - for (const CTransition& trans : transitions) - x14_transitions.emplace_back(trans.GetAnimPair(), trans.GetMetaTrans()); +: x10_defaultTrans(defaultTrans) { + x14_transitions.reserve(transitions.size()); + for (const CTransition& trans : transitions) + x14_transitions.emplace_back(trans.GetAnimPair(), trans.GetMetaTrans()); - x24_halfTransitions.reserve(halfTransitions.size()); - for (const CHalfTransition& trans : halfTransitions) - x24_halfTransitions.emplace_back(trans.GetId(), trans.GetMetaTrans()); + x24_halfTransitions.reserve(halfTransitions.size()); + for (const CHalfTransition& trans : halfTransitions) + x24_halfTransitions.emplace_back(trans.GetId(), trans.GetMetaTrans()); } -const std::shared_ptr& CTransitionDatabaseGame::GetMetaTrans(u32 a, u32 b) const -{ - auto it = std::find_if(x14_transitions.cbegin(), x14_transitions.cend(), - [&](const std::pair, std::shared_ptr>& elem) -> bool - { - return elem.first.first == a && elem.first.second == b; - }); - if (it != x14_transitions.cend()) - return it->second; - return x10_defaultTrans; +const std::shared_ptr& CTransitionDatabaseGame::GetMetaTrans(u32 a, u32 b) const { + auto it = std::find_if(x14_transitions.cbegin(), x14_transitions.cend(), + [&](const std::pair, std::shared_ptr>& elem) -> bool { + return elem.first.first == a && elem.first.second == b; + }); + if (it != x14_transitions.cend()) + return it->second; + return x10_defaultTrans; } -} +} // namespace urde diff --git a/Runtime/Character/CTransitionDatabaseGame.hpp b/Runtime/Character/CTransitionDatabaseGame.hpp index a171366ae..6895c8f54 100644 --- a/Runtime/Character/CTransitionDatabaseGame.hpp +++ b/Runtime/Character/CTransitionDatabaseGame.hpp @@ -2,22 +2,20 @@ #include "CTransitionDatabase.hpp" -namespace urde -{ +namespace urde { class CTransition; class CHalfTransition; -class CTransitionDatabaseGame final : public CTransitionDatabase -{ - std::shared_ptr x10_defaultTrans; - std::vector, std::shared_ptr>> x14_transitions; - std::vector>> x24_halfTransitions; +class CTransitionDatabaseGame final : public CTransitionDatabase { + std::shared_ptr x10_defaultTrans; + std::vector, std::shared_ptr>> x14_transitions; + std::vector>> x24_halfTransitions; + public: - CTransitionDatabaseGame(const std::vector& transitions, - const std::vector& halfTransitions, - const std::shared_ptr& defaultTrans); - const std::shared_ptr& GetMetaTrans(u32, u32) const; + CTransitionDatabaseGame(const std::vector& transitions, + const std::vector& halfTransitions, + const std::shared_ptr& defaultTrans); + const std::shared_ptr& GetMetaTrans(u32, u32) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CTransitionManager.cpp b/Runtime/Character/CTransitionManager.cpp index 9b9c76703..62c8ba4db 100644 --- a/Runtime/Character/CTransitionManager.cpp +++ b/Runtime/Character/CTransitionManager.cpp @@ -1,14 +1,11 @@ #include "CTransitionManager.hpp" #include "CTreeUtils.hpp" -namespace urde -{ +namespace urde { -std::shared_ptr -CTransitionManager::GetTransitionTree(const std::shared_ptr& a, - const std::shared_ptr& b) const -{ - return CTreeUtils::GetTransitionTree(a, b, x0_animCtx); +std::shared_ptr CTransitionManager::GetTransitionTree(const std::shared_ptr& a, + const std::shared_ptr& b) const { + return CTreeUtils::GetTransitionTree(a, b, x0_animCtx); } -} +} // namespace urde diff --git a/Runtime/Character/CTransitionManager.hpp b/Runtime/Character/CTransitionManager.hpp index 8c53a992d..07a306169 100644 --- a/Runtime/Character/CTransitionManager.hpp +++ b/Runtime/Character/CTransitionManager.hpp @@ -3,21 +3,19 @@ #include "CToken.hpp" #include "CAnimSysContext.hpp" -namespace urde -{ +namespace urde { class CTransitionDatabaseGame; class CRandom16; class CSimplePool; class CAnimTreeNode; -class CTransitionManager -{ - CAnimSysContext x0_animCtx; +class CTransitionManager { + CAnimSysContext x0_animCtx; + public: - CTransitionManager(const CAnimSysContext& sysCtx) : x0_animCtx(sysCtx) {} - std::shared_ptr GetTransitionTree(const std::shared_ptr& a, - const std::shared_ptr& b) const; + CTransitionManager(const CAnimSysContext& sysCtx) : x0_animCtx(sysCtx) {} + std::shared_ptr GetTransitionTree(const std::shared_ptr& a, + const std::shared_ptr& b) const; }; -} - +} // namespace urde diff --git a/Runtime/Character/CTreeUtils.cpp b/Runtime/Character/CTreeUtils.cpp index d7fb062c2..1624b6811 100644 --- a/Runtime/Character/CTreeUtils.cpp +++ b/Runtime/Character/CTreeUtils.cpp @@ -4,17 +4,15 @@ #include "CTransitionDatabaseGame.hpp" #include "IMetaTrans.hpp" -namespace urde -{ +namespace urde { std::shared_ptr CTreeUtils::GetTransitionTree(const std::weak_ptr& a, const std::weak_ptr& b, - const CAnimSysContext& animCtx) -{ - CAnimTreeEffectiveContribution contribA = a.lock()->GetContributionOfHighestInfluence(); - CAnimTreeEffectiveContribution contribB = b.lock()->GetContributionOfHighestInfluence(); - return animCtx.x0_transDB->GetMetaTrans(contribA.GetAnimDatabaseIndex(), - contribB.GetAnimDatabaseIndex())->GetTransitionTree(a, b, animCtx); + const CAnimSysContext& animCtx) { + CAnimTreeEffectiveContribution contribA = a.lock()->GetContributionOfHighestInfluence(); + CAnimTreeEffectiveContribution contribB = b.lock()->GetContributionOfHighestInfluence(); + return animCtx.x0_transDB->GetMetaTrans(contribA.GetAnimDatabaseIndex(), contribB.GetAnimDatabaseIndex()) + ->GetTransitionTree(a, b, animCtx); } -} +} // namespace urde diff --git a/Runtime/Character/CTreeUtils.hpp b/Runtime/Character/CTreeUtils.hpp index b085672c5..3898bc0bd 100644 --- a/Runtime/Character/CTreeUtils.hpp +++ b/Runtime/Character/CTreeUtils.hpp @@ -2,18 +2,15 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CAnimTreeNode; struct CAnimSysContext; -class CTreeUtils -{ +class CTreeUtils { public: - static std::shared_ptr GetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animCtx); + static std::shared_ptr GetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animCtx); }; -} - +} // namespace urde diff --git a/Runtime/Character/CharacterCommon.hpp b/Runtime/Character/CharacterCommon.hpp index 6c720d509..4354a5e60 100644 --- a/Runtime/Character/CharacterCommon.hpp +++ b/Runtime/Character/CharacterCommon.hpp @@ -1,271 +1,149 @@ #pragma once -namespace urde -{ -namespace pas -{ -enum class ELocomotionType -{ - Invalid = -1, - Crouch = 0, - Relaxed = 1, - Lurk = 2, - Combat = 3, - Internal4 = 4, - Internal5 = 5, - Internal6 = 6, - Internal7 = 7, - Internal8 = 8, - Internal9 = 9, - Internal10 = 10, - Internal11 = 11, - Internal12 = 12, - Internal13 = 13, - Internal14 = 14 +namespace urde { +namespace pas { +enum class ELocomotionType { + Invalid = -1, + Crouch = 0, + Relaxed = 1, + Lurk = 2, + Combat = 3, + Internal4 = 4, + Internal5 = 5, + Internal6 = 6, + Internal7 = 7, + Internal8 = 8, + Internal9 = 9, + Internal10 = 10, + Internal11 = 11, + Internal12 = 12, + Internal13 = 13, + Internal14 = 14 }; -enum class ELocomotionAnim -{ - Invalid = -1, - Idle, - Walk, - Run, - BackUp, - StrafeLeft, - StrafeRight, - StrafeUp, - StrafeDown +enum class ELocomotionAnim { Invalid = -1, Idle, Walk, Run, BackUp, StrafeLeft, StrafeRight, StrafeUp, StrafeDown }; + +enum class EAnimationState { + Invalid = -1, + Fall, + Getup, + LieOnGround, + Step, + Death, + Locomotion, + KnockBack, + MeleeAttack, + Turn, + LoopAttack, + LoopReaction, + GroundHit, + Generate, + Jump, + Hurled, + Slide, + Taunt, + Scripted, + ProjectileAttack, + Cover, + WallHang, + AdditiveIdle, + AdditiveAim, + AdditiveFlinch, + AdditiveReaction }; -enum class EAnimationState -{ - Invalid = -1, - Fall, - Getup, - LieOnGround, - Step, - Death, - Locomotion, - KnockBack, - MeleeAttack, - Turn, - LoopAttack, - LoopReaction, - GroundHit, - Generate, - Jump, - Hurled, - Slide, - Taunt, - Scripted, - ProjectileAttack, - Cover, - WallHang, - AdditiveIdle, - AdditiveAim, - AdditiveFlinch, - AdditiveReaction +enum class EHurledState { + Invalid = -1, + KnockIntoAir, + KnockLoop, + KnockDown, + StrikeWall, + StrikeWallFallLoop, + OutOfStrikeWall, + Six, + Seven }; -enum class EHurledState -{ - Invalid = -1, - KnockIntoAir, - KnockLoop, - KnockDown, - StrikeWall, - StrikeWallFallLoop, - OutOfStrikeWall, - Six, - Seven +enum class EFallState { Invalid = -1, Zero }; + +enum class EReactionType { Invalid = -1, Zero, One, Two, Three }; + +enum class EAdditiveReactionType { Invalid = -1, Electrocution, One, Two, IceBreakout }; + +enum class EJumpType { Normal, One, Ambush }; + +enum class EJumpState { Invalid = -1, IntoJump, AmbushJump, Loop, OutOfJump, WallBounceLeft, WallBounceRight }; + +enum class EStepDirection { Invalid = -1, Forward = 0, Backward = 1, Left = 2, Right = 3, Up = 4, Down = 5 }; + +enum class EStepType { Normal = 0, Dodge = 1 }; + +enum class ESeverity { Invalid = -1, Zero = 0, One = 1 }; + +enum class EGetupType { Invalid = -1 }; + +enum class ELoopState { Invalid = -1, Begin, Loop, End }; + +enum class ELoopAttackType { Invalid = -1 }; + +enum class EGenerateType { Invalid = -1, Zero, One, Two, Three, Four }; + +enum class ESlideType { Invalid = -1 }; + +enum class ETauntType { Invalid = -1 }; + +enum class ECoverState { Invalid = -1, IntoCover, Cover, Lean, OutOfCover }; + +enum class ECoverDirection { Invalid = -1, Left, Right }; + +enum class ETurnDirection { Invalid = -1, Right, Left }; + +enum class EWallHangState { + Invalid = -1, + IntoJump, + JumpArc, + JumpAirLoop, + IntoWallHang, + WallHang, + Five, + OutOfWallHang, + OutOfWallHangTurn, + DetachJumpLoop, + DetachOutOfJump +}; +} // namespace pas + +enum class EBodyType { Invalid, BiPedal, Restricted, Flyer, Pitchable, RestrictedFlyer, WallWalker, NewFlyer }; + +enum class EBodyStateCmd { + Getup, + Step, + Die, + KnockDown, + KnockBack, + MeleeAttack, + ProjectileAttack, + LoopAttack, + LoopReaction, + LoopHitReaction, + ExitState, + LeanFromCover, + NextState, + MaintainVelocity, + Generate, + Hurled, + Jump, + Slide, + Taunt, + Scripted, + Cover, + WallHang, + Locomotion, + AdditiveIdle, + AdditiveAim, + AdditiveFlinch, + AdditiveReaction, + StopReaction }; -enum class EFallState -{ - Invalid = -1, - Zero -}; - -enum class EReactionType -{ - Invalid = -1, - Zero, - One, - Two, - Three -}; - -enum class EAdditiveReactionType -{ - Invalid = -1, - Electrocution, - One, - Two, - IceBreakout -}; - -enum class EJumpType -{ - Normal, - One, - Ambush -}; - -enum class EJumpState -{ - Invalid = -1, - IntoJump, - AmbushJump, - Loop, - OutOfJump, - WallBounceLeft, - WallBounceRight -}; - -enum class EStepDirection -{ - Invalid = -1, - Forward = 0, - Backward = 1, - Left = 2, - Right = 3, - Up = 4, - Down = 5 -}; - -enum class EStepType -{ - Normal = 0, - Dodge = 1 -}; - -enum class ESeverity -{ - Invalid = -1, - Zero = 0, - One = 1 -}; - -enum class EGetupType -{ - Invalid = -1 -}; - -enum class ELoopState -{ - Invalid = -1, - Begin, - Loop, - End -}; - -enum class ELoopAttackType -{ - Invalid = -1 -}; - -enum class EGenerateType -{ - Invalid = -1, - Zero, - One, - Two, - Three, - Four -}; - -enum class ESlideType -{ - Invalid = -1 -}; - -enum class ETauntType -{ - Invalid = -1 -}; - -enum class ECoverState -{ - Invalid = -1, - IntoCover, - Cover, - Lean, - OutOfCover -}; - -enum class ECoverDirection -{ - Invalid = -1, - Left, - Right -}; - -enum class ETurnDirection -{ - Invalid = -1, - Right, - Left -}; - -enum class EWallHangState -{ - Invalid = -1, - IntoJump, - JumpArc, - JumpAirLoop, - IntoWallHang, - WallHang, - Five, - OutOfWallHang, - OutOfWallHangTurn, - DetachJumpLoop, - DetachOutOfJump -}; -} - -enum class EBodyType -{ - Invalid, - BiPedal, - Restricted, - Flyer, - Pitchable, - RestrictedFlyer, - WallWalker, - NewFlyer -}; - -enum class EBodyStateCmd -{ - Getup, - Step, - Die, - KnockDown, - KnockBack, - MeleeAttack, - ProjectileAttack, - LoopAttack, - LoopReaction, - LoopHitReaction, - ExitState, - LeanFromCover, - NextState, - MaintainVelocity, - Generate, - Hurled, - Jump, - Slide, - Taunt, - Scripted, - Cover, - WallHang, - Locomotion, - AdditiveIdle, - AdditiveAim, - AdditiveFlinch, - AdditiveReaction, - StopReaction -}; - -} - +} // namespace urde diff --git a/Runtime/Character/IAnimReader.cpp b/Runtime/Character/IAnimReader.cpp index ff124af0b..0f41455e9 100644 --- a/Runtime/Character/IAnimReader.cpp +++ b/Runtime/Character/IAnimReader.cpp @@ -1,67 +1,52 @@ #include "IAnimReader.hpp" #include "CCharAnimTime.hpp" -namespace urde -{ +namespace urde { -SAdvancementDeltas -SAdvancementDeltas::Interpolate(const SAdvancementDeltas& a, const SAdvancementDeltas& b, - float oldWeight, float newWeight) -{ - float weightSum = oldWeight + newWeight; - return { - b.x0_posDelta * weightSum * 0.5f - a.x0_posDelta * (weightSum - 2.f) * 0.5f, - zeus::CQuaternion::slerpShort(a.xc_rotDelta, b.xc_rotDelta, weightSum * 0.5f) - }; +SAdvancementDeltas SAdvancementDeltas::Interpolate(const SAdvancementDeltas& a, const SAdvancementDeltas& b, + float oldWeight, float newWeight) { + float weightSum = oldWeight + newWeight; + return {b.x0_posDelta * weightSum * 0.5f - a.x0_posDelta * (weightSum - 2.f) * 0.5f, + zeus::CQuaternion::slerpShort(a.xc_rotDelta, b.xc_rotDelta, weightSum * 0.5f)}; } -SAdvancementDeltas -SAdvancementDeltas::Blend(const SAdvancementDeltas& a, const SAdvancementDeltas& b, float w) -{ - return { - b.x0_posDelta * w - a.x0_posDelta * (1.f - w), - zeus::CQuaternion::slerpShort(a.xc_rotDelta, b.xc_rotDelta, w) - }; +SAdvancementDeltas SAdvancementDeltas::Blend(const SAdvancementDeltas& a, const SAdvancementDeltas& b, float w) { + return {b.x0_posDelta * w - a.x0_posDelta * (1.f - w), + zeus::CQuaternion::slerpShort(a.xc_rotDelta, b.xc_rotDelta, w)}; } -SAdvancementResults -IAnimReader::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const -{ - SAdvancementResults ret; - ret.x0_remTime = a; - return ret; +SAdvancementResults IAnimReader::VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const { + SAdvancementResults ret; + ret.x0_remTime = a; + return ret; } -u32 IAnimReader::GetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - if (time.GreaterThanZero()) - return VGetBoolPOIList(time, listOut, capacity, iterator, unk); - return 0; +u32 IAnimReader::GetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + if (time.GreaterThanZero()) + return VGetBoolPOIList(time, listOut, capacity, iterator, unk); + return 0; } -u32 IAnimReader::GetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - if (time.GreaterThanZero()) - return VGetInt32POIList(time, listOut, capacity, iterator, unk); - return 0; +u32 IAnimReader::GetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + if (time.GreaterThanZero()) + return VGetInt32POIList(time, listOut, capacity, iterator, unk); + return 0; } -u32 IAnimReader::GetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - if (time.GreaterThanZero()) - return VGetParticlePOIList(time, listOut, capacity, iterator, unk); - return 0; +u32 IAnimReader::GetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + if (time.GreaterThanZero()) + return VGetParticlePOIList(time, listOut, capacity, iterator, unk); + return 0; } -u32 IAnimReader::GetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, - u32 capacity, u32 iterator, u32 unk) const -{ - if (time.GreaterThanZero()) - return VGetSoundPOIList(time, listOut, capacity, iterator, unk); - return 0; +u32 IAnimReader::GetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, + u32 unk) const { + if (time.GreaterThanZero()) + return VGetSoundPOIList(time, listOut, capacity, iterator, unk); + return 0; } -} +} // namespace urde diff --git a/Runtime/Character/IAnimReader.hpp b/Runtime/Character/IAnimReader.hpp index 148bc240f..51bb71edc 100644 --- a/Runtime/Character/IAnimReader.hpp +++ b/Runtime/Character/IAnimReader.hpp @@ -8,8 +8,7 @@ #include "CToken.hpp" #include "CAllFormatsAnimSource.hpp" -namespace urde -{ +namespace urde { class CSegId; class CBoolPOINode; class CInt32POINode; @@ -18,126 +17,120 @@ class CSoundPOINode; class CSegIdList; class CSegStatementSet; -struct SAdvancementDeltas -{ - zeus::CVector3f x0_posDelta; - zeus::CQuaternion xc_rotDelta; +struct SAdvancementDeltas { + zeus::CVector3f x0_posDelta; + zeus::CQuaternion xc_rotDelta; - static SAdvancementDeltas Interpolate(const SAdvancementDeltas& a, const SAdvancementDeltas& b, - float oldWeight, float newWeight); - static SAdvancementDeltas Blend(const SAdvancementDeltas& a, const SAdvancementDeltas& b, float w); + static SAdvancementDeltas Interpolate(const SAdvancementDeltas& a, const SAdvancementDeltas& b, float oldWeight, + float newWeight); + static SAdvancementDeltas Blend(const SAdvancementDeltas& a, const SAdvancementDeltas& b, float w); }; -struct SAdvancementResults -{ - CCharAnimTime x0_remTime; - SAdvancementDeltas x8_deltas; +struct SAdvancementResults { + CCharAnimTime x0_remTime; + SAdvancementDeltas x8_deltas; }; -class CSteadyStateAnimInfo -{ - CCharAnimTime x0_duration; - zeus::CVector3f x8_offset; - bool x14_looping = false; +class CSteadyStateAnimInfo { + CCharAnimTime x0_duration; + zeus::CVector3f x8_offset; + bool x14_looping = false; public: - CSteadyStateAnimInfo(bool looping, const CCharAnimTime& duration, const zeus::CVector3f& offset) - : x0_duration(duration), x8_offset(offset), x14_looping(looping) {} + CSteadyStateAnimInfo(bool looping, const CCharAnimTime& duration, const zeus::CVector3f& offset) + : x0_duration(duration), x8_offset(offset), x14_looping(looping) {} - const CCharAnimTime& GetDuration() const { return x0_duration; } - const zeus::CVector3f& GetOffset() const { return x8_offset; } - bool IsLooping() const { return x14_looping; } + const CCharAnimTime& GetDuration() const { return x0_duration; } + const zeus::CVector3f& GetOffset() const { return x8_offset; } + bool IsLooping() const { return x14_looping; } }; -struct CAnimTreeEffectiveContribution -{ - float x0_contributionWeight; - std::string x4_name; - CSteadyStateAnimInfo x14_ssInfo; - CCharAnimTime x2c_remTime; - u32 x34_dbIdx; +struct CAnimTreeEffectiveContribution { + float x0_contributionWeight; + std::string x4_name; + CSteadyStateAnimInfo x14_ssInfo; + CCharAnimTime x2c_remTime; + u32 x34_dbIdx; + public: - CAnimTreeEffectiveContribution(float cweight, std::string_view name, const CSteadyStateAnimInfo& ssInfo, - const CCharAnimTime& remTime, u32 dbIdx) - : x0_contributionWeight(cweight), x4_name(name), x14_ssInfo(ssInfo), x2c_remTime(remTime), x34_dbIdx(dbIdx) {} - float GetContributionWeight() const { return x0_contributionWeight; } - std::string_view GetPrimitiveName() const { return x4_name; } - const CSteadyStateAnimInfo& GetSteadyStateAnimInfo() const { return x14_ssInfo; } - const CCharAnimTime& GetTimeRemaining() const { return x2c_remTime; } - u32 GetAnimDatabaseIndex() const { return x34_dbIdx; } + CAnimTreeEffectiveContribution(float cweight, std::string_view name, const CSteadyStateAnimInfo& ssInfo, + const CCharAnimTime& remTime, u32 dbIdx) + : x0_contributionWeight(cweight), x4_name(name), x14_ssInfo(ssInfo), x2c_remTime(remTime), x34_dbIdx(dbIdx) {} + float GetContributionWeight() const { return x0_contributionWeight; } + std::string_view GetPrimitiveName() const { return x4_name; } + const CSteadyStateAnimInfo& GetSteadyStateAnimInfo() const { return x14_ssInfo; } + const CCharAnimTime& GetTimeRemaining() const { return x2c_remTime; } + u32 GetAnimDatabaseIndex() const { return x34_dbIdx; } }; template -class TSubAnimTypeToken : public TLockedToken -{ +class TSubAnimTypeToken : public TLockedToken {}; + +template <> +class TSubAnimTypeToken : public TLockedToken { +public: + TSubAnimTypeToken(const TLockedToken& token) + : TLockedToken(token) {} + + const CAnimSource* GetObj() const { + const CAllFormatsAnimSource* source = TLockedToken::GetObj(); + return &source->GetAsCAnimSource(); + } + const CAnimSource* operator->() const { return GetObj(); } + const CAnimSource& operator*() const { return *GetObj(); } }; template <> -class TSubAnimTypeToken : public TLockedToken -{ +class TSubAnimTypeToken : public TLockedToken { public: - TSubAnimTypeToken(const TLockedToken& token) - : TLockedToken(token) {} + TSubAnimTypeToken(const TLockedToken& token) + : TLockedToken(token) {} - const CAnimSource* GetObj() const - { - const CAllFormatsAnimSource* source = TLockedToken::GetObj(); - return &source->GetAsCAnimSource(); - } - const CAnimSource* operator->() const {return GetObj();} - const CAnimSource& operator*() const {return *GetObj();} + const CFBStreamedCompression* GetObj() const { + const CAllFormatsAnimSource* source = TLockedToken::GetObj(); + return &source->GetAsCFBStreamedCompression(); + } + const CFBStreamedCompression* operator->() const { return GetObj(); } + const CFBStreamedCompression& operator*() const { return *GetObj(); } }; -template <> -class TSubAnimTypeToken : public TLockedToken -{ +class IAnimReader { public: - TSubAnimTypeToken(const TLockedToken& token) - : TLockedToken(token) {} + virtual ~IAnimReader() = default; + virtual bool IsCAnimTreeNode() const { return false; } + virtual SAdvancementResults VAdvanceView(const CCharAnimTime& a) = 0; + virtual CCharAnimTime VGetTimeRemaining() const = 0; + virtual CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const = 0; + virtual bool VHasOffset(const CSegId& seg) const = 0; + virtual zeus::CVector3f VGetOffset(const CSegId& seg) const = 0; + virtual zeus::CQuaternion VGetRotation(const CSegId& seg) const = 0; + virtual u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, + u32) const = 0; + virtual u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, + u32) const = 0; + virtual u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, + u32) const = 0; + virtual u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, + u32) const = 0; + virtual bool VGetBoolPOIState(const char*) const = 0; + virtual s32 VGetInt32POIState(const char*) const = 0; + virtual CParticleData::EParentedMode VGetParticlePOIState(const char*) const = 0; + virtual void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const = 0; + virtual void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, + const CCharAnimTime& time) const = 0; + virtual std::unique_ptr VClone() const = 0; + virtual std::experimental::optional> VSimplified() { return {}; } + virtual void VSetPhase(float) = 0; + virtual SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; - const CFBStreamedCompression* GetObj() const - { - const CAllFormatsAnimSource* source = TLockedToken::GetObj(); - return &source->GetAsCFBStreamedCompression(); - } - const CFBStreamedCompression* operator->() const {return GetObj();} - const CFBStreamedCompression& operator*() const {return *GetObj();} + u32 GetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 GetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 GetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; + u32 GetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; + + std::experimental::optional> Simplified() { return VSimplified(); } + + std::unique_ptr Clone() const { return VClone(); } }; -class IAnimReader -{ -public: - virtual ~IAnimReader() = default; - virtual bool IsCAnimTreeNode() const {return false;} - virtual SAdvancementResults VAdvanceView(const CCharAnimTime& a)=0; - virtual CCharAnimTime VGetTimeRemaining() const=0; - virtual CSteadyStateAnimInfo VGetSteadyStateAnimInfo() const=0; - virtual bool VHasOffset(const CSegId& seg) const=0; - virtual zeus::CVector3f VGetOffset(const CSegId& seg) const=0; - virtual zeus::CQuaternion VGetRotation(const CSegId& seg) const=0; - virtual u32 VGetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const=0; - virtual u32 VGetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const=0; - virtual u32 VGetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const=0; - virtual u32 VGetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const=0; - virtual bool VGetBoolPOIState(const char*) const=0; - virtual s32 VGetInt32POIState(const char*) const=0; - virtual CParticleData::EParentedMode VGetParticlePOIState(const char*) const=0; - virtual void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut) const=0; - virtual void VGetSegStatementSet(const CSegIdList& list, CSegStatementSet& setOut, const CCharAnimTime& time) const=0; - virtual std::unique_ptr VClone() const=0; - virtual std::experimental::optional> VSimplified() {return {};} - virtual void VSetPhase(float)=0; - virtual SAdvancementResults VGetAdvancementResults(const CCharAnimTime& a, const CCharAnimTime& b) const; - - u32 GetBoolPOIList(const CCharAnimTime& time, CBoolPOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 GetInt32POIList(const CCharAnimTime& time, CInt32POINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 GetParticlePOIList(const CCharAnimTime& time, CParticlePOINode* listOut, u32 capacity, u32 iterator, u32) const; - u32 GetSoundPOIList(const CCharAnimTime& time, CSoundPOINode* listOut, u32 capacity, u32 iterator, u32) const; - - std::experimental::optional> Simplified() { return VSimplified(); } - - std::unique_ptr Clone() const { return VClone(); } -}; - -} - +} // namespace urde diff --git a/Runtime/Character/IMetaAnim.cpp b/Runtime/Character/IMetaAnim.cpp index 74a052a53..594e6c422 100644 --- a/Runtime/Character/IMetaAnim.cpp +++ b/Runtime/Character/IMetaAnim.cpp @@ -4,55 +4,45 @@ #include "CBoolPOINode.hpp" #include "CAnimTreeNode.hpp" -namespace urde -{ +namespace urde { -std::shared_ptr -IMetaAnim::GetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const -{ - if (orders.x44_singleAdvance) - { - std::shared_ptr tree = - VGetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()); - if (orders.x44_singleAdvance->IsTime() || orders.x44_singleAdvance->IsString()) - { - CCharAnimTime time = GetTime(*orders.x44_singleAdvance, *tree); - AdvanceAnim(*tree, time); - } - return tree; +std::shared_ptr IMetaAnim::GetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const { + if (orders.x44_singleAdvance) { + std::shared_ptr tree = VGetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()); + if (orders.x44_singleAdvance->IsTime() || orders.x44_singleAdvance->IsString()) { + CCharAnimTime time = GetTime(*orders.x44_singleAdvance, *tree); + AdvanceAnim(*tree, time); } - return VGetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()); + return tree; + } + return VGetAnimationTree(animSys, CMetaAnimTreeBuildOrders::NoSpecialOrders()); } -void IMetaAnim::AdvanceAnim(IAnimReader& anim, const CCharAnimTime& dt) -{ - CCharAnimTime remDt = dt; - while (remDt > CCharAnimTime()) - { - SAdvancementResults res = anim.VAdvanceView(remDt); - remDt = res.x0_remTime; - } +void IMetaAnim::AdvanceAnim(IAnimReader& anim, const CCharAnimTime& dt) { + CCharAnimTime remDt = dt; + while (remDt > CCharAnimTime()) { + SAdvancementResults res = anim.VAdvanceView(remDt); + remDt = res.x0_remTime; + } } -CCharAnimTime IMetaAnim::GetTime(const CPreAdvanceIndicator& ind, const IAnimReader& anim) -{ - if (ind.IsTime()) - return ind.GetTime(); +CCharAnimTime IMetaAnim::GetTime(const CPreAdvanceIndicator& ind, const IAnimReader& anim) { + if (ind.IsTime()) + return ind.GetTime(); - CBoolPOINode nodes[64]; - CCharAnimTime rem = anim.VGetTimeRemaining(); - u32 count = anim.VGetBoolPOIList(rem, nodes, 64, 0, 0); - const char* cmpStr = ind.GetString(); - for (u32 i=0 ; i -namespace urde -{ +namespace urde { class CAnimTreeNode; struct CAnimSysContext; struct CMetaAnimTreeBuildOrders; class CPrimitive; class IAnimReader; -enum class EMetaAnimType -{ - Play, - Blend, - PhaseBlend, - Random, - Sequence -}; +enum class EMetaAnimType { Play, Blend, PhaseBlend, Random, Sequence }; -class CPreAdvanceIndicator -{ - bool x0_isTime; - CCharAnimTime x4_time; - const char* xc_string; - /* - u32 x10_; - u32 x14_; - u32 x18_; - u32 x1c_; - u32 x20_; - u32 x24_; - u32 x28_; - u32 x2c_; - u32 x30_; - u32 x34_; - u32 x38_; - u16 x3c_; - */ +class CPreAdvanceIndicator { + bool x0_isTime; + CCharAnimTime x4_time; + const char* xc_string; + /* + u32 x10_; + u32 x14_; + u32 x18_; + u32 x1c_; + u32 x20_; + u32 x24_; + u32 x28_; + u32 x2c_; + u32 x30_; + u32 x34_; + u32 x38_; + u16 x3c_; + */ public: - CPreAdvanceIndicator(const CCharAnimTime& time) - : x0_isTime(true), x4_time(time) {} - CPreAdvanceIndicator(const char* string) - : x0_isTime(false), xc_string(string) {} - const char* GetString() const {return xc_string;} - bool IsString() const {return !x0_isTime;} - const CCharAnimTime& GetTime() const {return x4_time;} - bool IsTime() const {return x0_isTime;} + CPreAdvanceIndicator(const CCharAnimTime& time) : x0_isTime(true), x4_time(time) {} + CPreAdvanceIndicator(const char* string) : x0_isTime(false), xc_string(string) {} + const char* GetString() const { return xc_string; } + bool IsString() const { return !x0_isTime; } + const CCharAnimTime& GetTime() const { return x4_time; } + bool IsTime() const { return x0_isTime; } }; -struct CMetaAnimTreeBuildOrders -{ - std::experimental::optional x0_recursiveAdvance; - std::experimental::optional x44_singleAdvance; - static CMetaAnimTreeBuildOrders NoSpecialOrders() { return {}; } - static CMetaAnimTreeBuildOrders PreAdvanceForAll(const CPreAdvanceIndicator& ind) - { - CMetaAnimTreeBuildOrders ret; - ret.x0_recursiveAdvance.emplace(ind); - ret.x44_singleAdvance.emplace(ind); - return ret; - } +struct CMetaAnimTreeBuildOrders { + std::experimental::optional x0_recursiveAdvance; + std::experimental::optional x44_singleAdvance; + static CMetaAnimTreeBuildOrders NoSpecialOrders() { return {}; } + static CMetaAnimTreeBuildOrders PreAdvanceForAll(const CPreAdvanceIndicator& ind) { + CMetaAnimTreeBuildOrders ret; + ret.x0_recursiveAdvance.emplace(ind); + ret.x44_singleAdvance.emplace(ind); + return ret; + } }; -class IMetaAnim -{ +class IMetaAnim { public: - virtual ~IMetaAnim() = default; - virtual std::shared_ptr GetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const; - virtual void GetUniquePrimitives(std::set& primsOut) const=0; - virtual EMetaAnimType GetType() const=0; - virtual std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, - const CMetaAnimTreeBuildOrders& orders) const=0; + virtual ~IMetaAnim() = default; + virtual std::shared_ptr GetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const; + virtual void GetUniquePrimitives(std::set& primsOut) const = 0; + virtual EMetaAnimType GetType() const = 0; + virtual std::shared_ptr VGetAnimationTree(const CAnimSysContext& animSys, + const CMetaAnimTreeBuildOrders& orders) const = 0; - static void AdvanceAnim(IAnimReader& anim, const CCharAnimTime& dt); - static CCharAnimTime GetTime(const CPreAdvanceIndicator& ind, const IAnimReader& anim); + static void AdvanceAnim(IAnimReader& anim, const CCharAnimTime& dt); + static CCharAnimTime GetTime(const CPreAdvanceIndicator& ind, const IAnimReader& anim); }; -} - +} // namespace urde diff --git a/Runtime/Character/IMetaTrans.hpp b/Runtime/Character/IMetaTrans.hpp index 1b36555df..15ab80acd 100644 --- a/Runtime/Character/IMetaTrans.hpp +++ b/Runtime/Character/IMetaTrans.hpp @@ -2,35 +2,25 @@ #include "../RetroTypes.hpp" -namespace urde -{ +namespace urde { class CAnimTreeNode; struct CAnimSysContext; -enum class EMetaTransType -{ - MetaAnim, - Trans, - PhaseTrans, - Snap -}; +enum class EMetaTransType { MetaAnim, Trans, PhaseTrans, Snap }; -class IMetaTrans -{ +class IMetaTrans { public: - virtual ~IMetaTrans() = default; - virtual std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animSys) const=0; - virtual EMetaTransType GetType() const=0; + virtual ~IMetaTrans() = default; + virtual std::shared_ptr VGetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animSys) const = 0; + virtual EMetaTransType GetType() const = 0; - std::shared_ptr GetTransitionTree(const std::weak_ptr& a, - const std::weak_ptr& b, - const CAnimSysContext& animSys) - { - return VGetTransitionTree(a, b, animSys); - } + std::shared_ptr GetTransitionTree(const std::weak_ptr& a, + const std::weak_ptr& b, + const CAnimSysContext& animSys) { + return VGetTransitionTree(a, b, animSys); + } }; -} - +} // namespace urde diff --git a/Runtime/Character/IVaryingAnimationTimeScale.hpp b/Runtime/Character/IVaryingAnimationTimeScale.hpp index e304f1d2f..dedafb824 100644 --- a/Runtime/Character/IVaryingAnimationTimeScale.hpp +++ b/Runtime/Character/IVaryingAnimationTimeScale.hpp @@ -2,26 +2,20 @@ #include "CCharAnimTime.hpp" -namespace urde -{ -class IVaryingAnimationTimeScale -{ +namespace urde { +class IVaryingAnimationTimeScale { public: - virtual u32 GetType() const = 0; - virtual float VTimeScaleIntegral(const float&, const float&) const = 0; - virtual float VFindUpperLimit(const float&, const float&) const = 0; - virtual std::unique_ptr VClone() const = 0; - virtual std::unique_ptr VGetFunctionMirrored(const float&) const = 0; - CCharAnimTime FindUpperLimit(const CCharAnimTime& a, const CCharAnimTime& b) const - { - return VFindUpperLimit(a, b); - } + virtual u32 GetType() const = 0; + virtual float VTimeScaleIntegral(const float&, const float&) const = 0; + virtual float VFindUpperLimit(const float&, const float&) const = 0; + virtual std::unique_ptr VClone() const = 0; + virtual std::unique_ptr VGetFunctionMirrored(const float&) const = 0; + CCharAnimTime FindUpperLimit(const CCharAnimTime& a, const CCharAnimTime& b) const { return VFindUpperLimit(a, b); } - CCharAnimTime TimeScaleIntegral(const CCharAnimTime& a, const CCharAnimTime& b) const - { - return VTimeScaleIntegral(a, b); - } + CCharAnimTime TimeScaleIntegral(const CCharAnimTime& a, const CCharAnimTime& b) const { + return VTimeScaleIntegral(a, b); + } - std::unique_ptr Clone() const { return VClone(); } + std::unique_ptr Clone() const { return VClone(); } }; -} +} // namespace urde diff --git a/Runtime/Character/TSegIdMap.hpp b/Runtime/Character/TSegIdMap.hpp index cb7fc4810..41d45709f 100644 --- a/Runtime/Character/TSegIdMap.hpp +++ b/Runtime/Character/TSegIdMap.hpp @@ -3,68 +3,58 @@ #include #include "CSegId.hpp" -namespace urde -{ +namespace urde { template -class TSegIdMap -{ - CSegId x0_boneCount = 0; - CSegId x1_capacity = 0; - u32 x4_maxCapacity = 100; - std::pair x8_indirectionMap[100]; - std::unique_ptr xd0_bones; - CSegId xd4_curPrevBone = 0; -public: - TSegIdMap(const CSegId& capacity) : x1_capacity(capacity), xd0_bones(new T[capacity]) {} - T& operator[](const CSegId& id) {return SetElement(id);} - const T& operator[](const CSegId& id) const {return xd0_bones[x8_indirectionMap[id].second];} - T& SetElement(const CSegId& id, T&& obj) - { - size_t idx; - if (x8_indirectionMap[id].first == 0xff) - { - x8_indirectionMap[id].first = xd4_curPrevBone; - x8_indirectionMap[id].second = x0_boneCount; - xd4_curPrevBone = id; - idx = x0_boneCount; - ++x0_boneCount; - } - else - idx = x8_indirectionMap[id].second; - xd0_bones[idx] = std::move(obj); - return xd0_bones[idx]; - } - T& SetElement(const CSegId& id) - { - size_t idx; - if (x8_indirectionMap[id].first == 0xff) - { - x8_indirectionMap[id].first = xd4_curPrevBone; - x8_indirectionMap[id].second = x0_boneCount; - xd4_curPrevBone = id; - idx = x0_boneCount; - ++x0_boneCount; - } - else - idx = x8_indirectionMap[id].second; - return xd0_bones[idx]; - } - void DelElement(const CSegId& id) - { - if (x8_indirectionMap[id].first != 0xff) - { - if (id == xd4_curPrevBone) - xd4_curPrevBone = x8_indirectionMap[id].first; - x8_indirectionMap[id].first = 0xff; - x8_indirectionMap[id].second = 0xff; - --x0_boneCount; - } - } - bool HasElement(const CSegId& id) const {return x8_indirectionMap[id].first != 0xff;} +class TSegIdMap { + CSegId x0_boneCount = 0; + CSegId x1_capacity = 0; + u32 x4_maxCapacity = 100; + std::pair x8_indirectionMap[100]; + std::unique_ptr xd0_bones; + CSegId xd4_curPrevBone = 0; - u32 GetCapacity() const { return x1_capacity; } +public: + TSegIdMap(const CSegId& capacity) : x1_capacity(capacity), xd0_bones(new T[capacity]) {} + T& operator[](const CSegId& id) { return SetElement(id); } + const T& operator[](const CSegId& id) const { return xd0_bones[x8_indirectionMap[id].second]; } + T& SetElement(const CSegId& id, T&& obj) { + size_t idx; + if (x8_indirectionMap[id].first == 0xff) { + x8_indirectionMap[id].first = xd4_curPrevBone; + x8_indirectionMap[id].second = x0_boneCount; + xd4_curPrevBone = id; + idx = x0_boneCount; + ++x0_boneCount; + } else + idx = x8_indirectionMap[id].second; + xd0_bones[idx] = std::move(obj); + return xd0_bones[idx]; + } + T& SetElement(const CSegId& id) { + size_t idx; + if (x8_indirectionMap[id].first == 0xff) { + x8_indirectionMap[id].first = xd4_curPrevBone; + x8_indirectionMap[id].second = x0_boneCount; + xd4_curPrevBone = id; + idx = x0_boneCount; + ++x0_boneCount; + } else + idx = x8_indirectionMap[id].second; + return xd0_bones[idx]; + } + void DelElement(const CSegId& id) { + if (x8_indirectionMap[id].first != 0xff) { + if (id == xd4_curPrevBone) + xd4_curPrevBone = x8_indirectionMap[id].first; + x8_indirectionMap[id].first = 0xff; + x8_indirectionMap[id].second = 0xff; + --x0_boneCount; + } + } + bool HasElement(const CSegId& id) const { return x8_indirectionMap[id].first != 0xff; } + + u32 GetCapacity() const { return x1_capacity; } }; -} - +} // namespace urde diff --git a/Runtime/Collision/CAABoxFilter.cpp b/Runtime/Collision/CAABoxFilter.cpp index 91966625a..a0e48f59e 100644 --- a/Runtime/Collision/CAABoxFilter.cpp +++ b/Runtime/Collision/CAABoxFilter.cpp @@ -1,36 +1,28 @@ #include "CAABoxFilter.hpp" #include "CollisionUtil.hpp" -namespace urde -{ +namespace urde { -void CAABoxFilter::Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const -{ - FilterBoxFloorCollisions(in, out); +void CAABoxFilter::Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const { + FilterBoxFloorCollisions(in, out); } -void CAABoxFilter::FilterBoxFloorCollisions(const CCollisionInfoList& in, CCollisionInfoList& out) -{ - float minZ = 10000.f; - for (const CCollisionInfo& info : in) - { - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Wall) && info.GetPoint().z() < minZ) - minZ = info.GetPoint().z(); +void CAABoxFilter::FilterBoxFloorCollisions(const CCollisionInfoList& in, CCollisionInfoList& out) { + float minZ = 10000.f; + for (const CCollisionInfo& info : in) { + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Wall) && info.GetPoint().z() < minZ) + minZ = info.GetPoint().z(); + } + CCollisionInfoList temp; + for (const CCollisionInfo& info : in) { + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Floor)) { + if (info.GetPoint().z() < minZ) + temp.Add(info, false); + } else { + temp.Add(info, false); } - CCollisionInfoList temp; - for (const CCollisionInfo& info : in) - { - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Floor)) - { - if (info.GetPoint().z() < minZ) - temp.Add(info, false); - } - else - { - temp.Add(info, false); - } - } - CollisionUtil::AddAverageToFront(temp, out); + } + CollisionUtil::AddAverageToFront(temp, out); } -} +} // namespace urde diff --git a/Runtime/Collision/CAABoxFilter.hpp b/Runtime/Collision/CAABoxFilter.hpp index c6ef0e597..951ac9c5f 100644 --- a/Runtime/Collision/CAABoxFilter.hpp +++ b/Runtime/Collision/CAABoxFilter.hpp @@ -2,16 +2,13 @@ #include "ICollisionFilter.hpp" -namespace urde -{ +namespace urde { -class CAABoxFilter : public ICollisionFilter -{ +class CAABoxFilter : public ICollisionFilter { public: - CAABoxFilter(CActor& actor) : ICollisionFilter(actor) {} - void Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const; - static void FilterBoxFloorCollisions(const CCollisionInfoList& in, CCollisionInfoList& out); + CAABoxFilter(CActor& actor) : ICollisionFilter(actor) {} + void Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const; + static void FilterBoxFloorCollisions(const CCollisionInfoList& in, CCollisionInfoList& out); }; -} - +} // namespace urde diff --git a/Runtime/Collision/CAreaOctTree.cpp b/Runtime/Collision/CAreaOctTree.cpp index 45cbbd81e..24a7f6b23 100644 --- a/Runtime/Collision/CAreaOctTree.cpp +++ b/Runtime/Collision/CAreaOctTree.cpp @@ -3,694 +3,590 @@ #include "zeus/CVector2i.hpp" #include -namespace urde -{ +namespace urde { -static bool _close_enough(float f1, float f2, float epsilon) -{ - return std::fabs(f1 - f2) <= epsilon; +static bool _close_enough(float f1, float f2, float epsilon) { return std::fabs(f1 - f2) <= epsilon; } + +static bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CLine& line, float& lT, float& hT) { + zeus::simd_floats aabbMinF(aabb.min.mSimd); + zeus::simd_floats aabbMaxF(aabb.max.mSimd); + zeus::simd_floats lineOrigin(line.origin.mSimd); + zeus::simd_floats lineDir(line.dir.mSimd); + const float* aabbMin = aabbMinF.data(); + const float* aabbMax = aabbMaxF.data(); + const float* lorigin = lineOrigin.data(); + const float* ldir = lineDir.data(); + lT = -FLT_MAX; + hT = FLT_MAX; + + for (int i = 0; i < 3; ++i) { + if (_close_enough(*ldir, 0.f, 0.000099999997f)) + if (*lorigin < *aabbMin || *lorigin > *aabbMax) + return false; + + if (*ldir < 0.f) { + if (*aabbMax - *lorigin < lT * *ldir) + lT = (*aabbMax - *lorigin) * 1.f / *ldir; + if (*aabbMin - *lorigin > hT * *ldir) + hT = (*aabbMin - *lorigin) * 1.f / *ldir; + } else { + if (*aabbMin - *lorigin > lT * *ldir) + lT = (*aabbMin - *lorigin) * 1.f / *ldir; + if (*aabbMax - *lorigin < hT * *ldir) + hT = (*aabbMax - *lorigin) * 1.f / *ldir; + } + + ++aabbMin; + ++aabbMax; + ++lorigin; + ++ldir; + } + + return lT <= hT; } -static bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CLine& line, float& lT, float& hT) -{ - zeus::simd_floats aabbMinF(aabb.min.mSimd); - zeus::simd_floats aabbMaxF(aabb.max.mSimd); - zeus::simd_floats lineOrigin(line.origin.mSimd); - zeus::simd_floats lineDir(line.dir.mSimd); - const float* aabbMin = aabbMinF.data(); - const float* aabbMax = aabbMaxF.data(); - const float* lorigin = lineOrigin.data(); - const float* ldir = lineDir.data(); - lT = -FLT_MAX; - hT = FLT_MAX; +static const int SomeIndexA[] = {1, 2, 4}; - for (int i=0 ; i<3 ; ++i) +static const int SomeIndexB[] = {1, 2, 0}; + +static const int SomeIndexC[8][8] = {{0, 1, 2, 4, 5, 6, 8, 0xA}, {0, 1, 2, 3, 5, 6, 8, 0xA}, {0, 1, 2, 4, 5, 6, 9, 0xB}, + {0, 1, 2, 3, 5, 6, 9, 0xC}, {0, 1, 2, 4, 5, 7, 8, 0xD}, {0, 1, 2, 3, 5, 7, 8, 0xE}, + {0, 1, 2, 4, 5, 7, 9, 0xF}, {0, 1, 2, 3, 5, 7, 9, 0xF}}; + +static const std::pair> SubdivIndex[16] = { + {0, {0, 0, 0}}, {1, {0, 0, 0}}, {1, {1, 0, 0}}, {2, {0, 1, 0}}, {2, {1, 0, 0}}, {1, {2, 0, 0}}, + {2, {0, 2, 0}}, {2, {2, 0, 0}}, {2, {2, 1, 0}}, {2, {1, 2, 0}}, {3, {0, 2, 1}}, {3, {1, 0, 2}}, + {3, {0, 1, 2}}, {3, {2, 1, 0}}, {3, {2, 0, 1}}, {3, {1, 2, 0}}}; + +bool CAreaOctTree::Node::LineTestInternal(const zeus::CLine& line, const CMaterialFilter& filter, float lT, float hT, + float maxT, const zeus::CVector3f& vec) const { + float lowT = (1.f - FLT_EPSILON * 100.f) * lT; + float highT = (1.f + FLT_EPSILON * 100.f) * hT; + if (maxT != 0.f) { + if (lowT < 0.f) + lowT = 0.f; + if (highT > maxT) + highT = maxT; + if (lowT > highT) + return true; + } + + if (x20_nodeType == ETreeType::Leaf) { + TriListReference triList = GetTriangleArray(); + for (u16 i = 0; i < triList.GetSize(); ++i) { + CCollisionSurface triangle = x1c_owner.GetMasterListTriangle(triList.GetAt(i)); + + // https://en.wikipedia.org/wiki/Möller–Trumbore_intersection_algorithm + // Find vectors for two edges sharing V0 + zeus::CVector3f e0 = triangle.GetVert(1) - triangle.GetVert(0); + zeus::CVector3f e1 = triangle.GetVert(2) - triangle.GetVert(0); + + // Begin calculating determinant - also used to calculate u parameter + zeus::CVector3f P = line.dir.cross(e1); + float det = P.dot(e0); + + // If determinant is near zero, ray lies in plane of triangle + // or ray is parallel to plane of triangle + if (std::fabs(det) < (FLT_EPSILON * 10.f)) + continue; + float invDet = 1.f / det; + + // Calculate distance from V1 to ray origin + zeus::CVector3f T = line.origin - triangle.GetVert(0); + + // Calculate u parameter and test bound + float u = invDet * T.dot(P); + + // The intersection lies outside of the triangle + if (u < 0.f || u > 1.f) + continue; + + // Prepare to test v parameter + zeus::CVector3f Q = T.cross(e0); + + // Calculate T parameter and test bound + float t = invDet * Q.dot(e1); + if (t >= highT || t < lowT) + continue; + + // Calculate V parameter and test bound + float v = invDet * Q.dot(line.dir); + if (v < 0.f || u + v > 1.f) + continue; + + // Do material filter + CMaterialList matList(triangle.GetSurfaceFlags()); + if (filter.Passes(matList)) + return false; + } + } else if (x20_nodeType == ETreeType::Branch) { + if (GetChildFlags() == 0xA) // 2 leaves { - if (_close_enough(*ldir, 0.f, 0.000099999997f)) - if (*lorigin < *aabbMin || *lorigin > *aabbMax) - return false; + for (int i = 0; i < 2; ++i) { + Node child = GetChild(i); + float tf1 = lT; + float tf2 = hT; + if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2)) + if (!child.LineTestInternal(line, filter, tf1, tf2, maxT, vec)) + return false; + } + return true; + } - if (*ldir < 0.f) - { - if (*aabbMax - *lorigin < lT * *ldir) - lT = (*aabbMax - *lorigin) * 1.f / *ldir; - if (*aabbMin - *lorigin > hT * *ldir) - hT = (*aabbMin - *lorigin) * 1.f / *ldir; - } + zeus::CVector3f center = x0_aabb.center(); + + zeus::CVector3f r6 = line.origin + lT * line.dir; + zeus::CVector3f r7 = line.origin + hT * line.dir; + zeus::CVector3f r9 = vec * (center - line.origin); + + int r28 = 0; + int r25 = 0; + int r26 = 0; + for (int i = 0; i < 3; ++i) { + if (r6[i] >= center[i]) + r28 |= SomeIndexA[i]; + if (r7[i] >= center[i]) + r25 |= SomeIndexA[i]; + if (r9[i] < r9[SomeIndexB[i]]) + r26 |= SomeIndexA[i]; + } + + float f21 = lT; + int r26b = r28; + const std::pair>& idx = SubdivIndex[SomeIndexC[r26][r28 ^ r25]]; + for (int i = 0; i <= idx.first; ++i) { + float f22 = (i < idx.first) ? r9[idx.second[i]] : hT; + if (f22 > lowT && f21 <= f22) { + Node child = GetChild(r26b); + if (child.x20_nodeType != ETreeType::Invalid) + if (!child.LineTestInternal(line, filter, f21, f22, maxT, vec)) + return false; + } + if (i < idx.first) + r26b ^= 1 << idx.second[i]; + f21 = f22; + } + } + + return true; +} + +void CAreaOctTree::Node::LineTestExInternal(const zeus::CLine& line, const CMaterialFilter& filter, SRayResult& res, + float lT, float hT, float maxT, const zeus::CVector3f& dirRecip) const { + float lowT = (1.f - FLT_EPSILON * 100.f) * lT; + float highT = (1.f + FLT_EPSILON * 100.f) * hT; + if (maxT != 0.f) { + if (lowT < 0.f) + lowT = 0.f; + if (highT > maxT) + highT = maxT; + if (lowT > highT) + return; + } + + if (x20_nodeType == ETreeType::Leaf) { + TriListReference triList = GetTriangleArray(); + float bestT = highT; + bool foundTriangle = false; + SRayResult tmpRes; + + for (u16 i = 0; i < triList.GetSize(); ++i) { + CCollisionSurface triangle = x1c_owner.GetMasterListTriangle(triList.GetAt(i)); + + // https://en.wikipedia.org/wiki/Möller–Trumbore_intersection_algorithm + // Find vectors for two edges sharing V0 + zeus::CVector3f e0 = triangle.GetVert(1) - triangle.GetVert(0); + zeus::CVector3f e1 = triangle.GetVert(2) - triangle.GetVert(0); + + // Begin calculating determinant - also used to calculate u parameter + zeus::CVector3f P = line.dir.cross(e1); + float det = P.dot(e0); + + // If determinant is near zero, ray lies in plane of triangle + // or ray is parallel to plane of triangle + if (std::fabs(det) < (FLT_EPSILON * 10.f)) + continue; + float invDet = 1.f / det; + + // Calculate distance from V1 to ray origin + zeus::CVector3f T = line.origin - triangle.GetVert(0); + + // Calculate u parameter and test bound + float u = invDet * T.dot(P); + + // The intersection lies outside of the triangle + if (u < 0.f || u > 1.f) + continue; + + // Prepare to test v parameter + zeus::CVector3f Q = T.cross(e0); + + // Calculate T parameter and test bound + float t = invDet * Q.dot(e1); + if (t >= bestT || t < lowT) + continue; + + // Calculate V parameter and test bound + float v = invDet * Q.dot(line.dir); + if (v < 0.f || u + v > 1.f) + continue; + + // Do material filter + CMaterialList matList(triangle.GetSurfaceFlags()); + if (filter.Passes(matList) && t <= bestT) { + bestT = t; + foundTriangle = true; + tmpRes.x10_surface.emplace(triangle); + tmpRes.x3c_t = t; + } + } + + if (foundTriangle) { + res = tmpRes; + res.x0_plane = res.x10_surface->GetPlane(); + } + } else if (x20_nodeType == ETreeType::Branch) { + if (GetChildFlags() == 0xA) // 2 leaves + { + SRayResult tmpRes[2]; + for (int i = 0; i < 2; ++i) { + Node child = GetChild(i); + float tf1 = lT; + float tf2 = hT; + if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2)) + child.LineTestExInternal(line, filter, tmpRes[i], tf1, tf2, maxT, dirRecip); + } + + if (!tmpRes[0].x10_surface && !tmpRes[1].x10_surface) { + res = SRayResult(); + } else if (tmpRes[0].x10_surface && tmpRes[1].x10_surface) { + if (tmpRes[0].x3c_t < tmpRes[1].x3c_t) + res = tmpRes[0]; else - { - if (*aabbMin - *lorigin > lT * *ldir) - lT = (*aabbMin - *lorigin) * 1.f / *ldir; - if (*aabbMax - *lorigin < hT * *ldir) - hT = (*aabbMax - *lorigin) * 1.f / *ldir; - } + res = tmpRes[1]; + } else if (tmpRes[0].x10_surface) { + res = tmpRes[0]; + } else { + res = tmpRes[1]; + } - ++aabbMin; - ++aabbMax; - ++lorigin; - ++ldir; + if (res.x3c_t > highT) + res = SRayResult(); + + return; } - return lT <= hT; + zeus::CVector3f center = x0_aabb.center(); // r26 + + zeus::CVector3f lowPoint = line.origin + lT * line.dir; + zeus::CVector3f highPoint = line.origin + hT * line.dir; + int comps[] = {-1, -1, -1, 0}; + float compT[3]; + + int numComps = 0; + for (int i = 0; i < 3; ++i) { + if (lowPoint[i] >= center[i] || highPoint[i] <= center[i]) + if (highPoint[i] >= center[i] || lowPoint[i] <= center[i]) + continue; + if (_close_enough(line.dir[i], 0.f, 0.000099999997f)) + continue; + comps[numComps++] = i; + compT[i] = dirRecip[i] * (center[i] - line.origin[i]); + } + + // Sort componentT least to greatest + switch (numComps) { + default: + return; + case 0: + case 1: + break; + case 2: + if (compT[comps[1]] < compT[comps[0]]) + std::swap(comps[1], comps[0]); + break; + case 3: + if (compT[0] < compT[1]) { + if (compT[0] >= compT[2]) { + comps[0] = 2; + comps[1] = 0; + comps[2] = 1; + } else if (compT[1] < compT[2]) { + comps[0] = 0; + comps[1] = 1; + comps[2] = 2; + } else { + comps[0] = 0; + comps[1] = 2; + comps[2] = 1; + } + } else { + if (compT[1] >= compT[2]) { + comps[0] = 2; + comps[1] = 1; + comps[2] = 0; + } else if (compT[0] < compT[2]) { + comps[0] = 1; + comps[1] = 0; + comps[2] = 2; + } else { + comps[0] = 1; + comps[1] = 2; + comps[2] = 0; + } + } + break; + } + + zeus::CVector3f lineStart = line.origin + (lT * line.dir); + int selector = 0; + if (lineStart.x() >= center.x()) + selector = 1; + if (lineStart.y() >= center.y()) + selector |= 1 << 1; + if (lineStart.z() >= center.z()) + selector |= 1 << 2; + + float tmpLoT = lT; + for (int i = -1; i < numComps; ++i) { + if (i >= 0) + selector ^= 1 << comps[i]; + float tmpHiT = (i < numComps - 1) ? compT[comps[i + 1]] : hT; + if (tmpHiT > lowT && tmpLoT <= tmpHiT) { + Node child = GetChild(selector); + if (child.x20_nodeType != ETreeType::Invalid) + child.LineTestExInternal(line, filter, res, tmpLoT, tmpHiT, maxT, dirRecip); + if (res.x10_surface) { + if (res.x3c_t > highT) + res = SRayResult(); + break; + } + } + tmpLoT = tmpHiT; + } + } } -static const int SomeIndexA[] = -{ - 1, 2, 4 -}; - -static const int SomeIndexB[] = -{ - 1, 2, 0 -}; - -static const int SomeIndexC[8][8] = -{ - {0, 1, 2, 4, 5, 6, 8, 0xA}, - {0, 1, 2, 3, 5, 6, 8, 0xA}, - {0, 1, 2, 4, 5, 6, 9, 0xB}, - {0, 1, 2, 3, 5, 6, 9, 0xC}, - {0, 1, 2, 4, 5, 7, 8, 0xD}, - {0, 1, 2, 3, 5, 7, 8, 0xE}, - {0, 1, 2, 4, 5, 7, 9, 0xF}, - {0, 1, 2, 3, 5, 7, 9, 0xF} -}; - -static const std::pair> SubdivIndex[16] = -{ - {0, {0, 0, 0}}, - {1, {0, 0, 0}}, - {1, {1, 0, 0}}, - {2, {0, 1, 0}}, - {2, {1, 0, 0}}, - {1, {2, 0, 0}}, - {2, {0, 2, 0}}, - {2, {2, 0, 0}}, - {2, {2, 1, 0}}, - {2, {1, 2, 0}}, - {3, {0, 2, 1}}, - {3, {1, 0, 2}}, - {3, {0, 1, 2}}, - {3, {2, 1, 0}}, - {3, {2, 0, 1}}, - {3, {1, 2, 0}} -}; - -bool CAreaOctTree::Node::LineTestInternal(const zeus::CLine& line, const CMaterialFilter& filter, - float lT, float hT, float maxT, const zeus::CVector3f& vec) const -{ - float lowT = (1.f - FLT_EPSILON * 100.f) * lT; - float highT = (1.f + FLT_EPSILON * 100.f) * hT; - if (maxT != 0.f) - { - if (lowT < 0.f) - lowT = 0.f; - if (highT > maxT) - highT = maxT; - if (lowT > highT) - return true; - } - - if (x20_nodeType == ETreeType::Leaf) - { - TriListReference triList = GetTriangleArray(); - for (u16 i=0 ; i 1.f) - continue; - - // Prepare to test v parameter - zeus::CVector3f Q = T.cross(e0); - - // Calculate T parameter and test bound - float t = invDet * Q.dot(e1); - if (t >= highT || t < lowT) - continue; - - // Calculate V parameter and test bound - float v = invDet * Q.dot(line.dir); - if (v < 0.f || u + v > 1.f) - continue; - - // Do material filter - CMaterialList matList(triangle.GetSurfaceFlags()); - if (filter.Passes(matList)) - return false; - } - } - else if (x20_nodeType == ETreeType::Branch) - { - if (GetChildFlags() == 0xA) // 2 leaves - { - for (int i=0 ; i<2 ; ++i) - { - Node child = GetChild(i); - float tf1 = lT; - float tf2 = hT; - if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2)) - if (!child.LineTestInternal(line, filter, tf1, tf2, maxT, vec)) - return false; - } - return true; - } - - zeus::CVector3f center = x0_aabb.center(); - - zeus::CVector3f r6 = line.origin + lT * line.dir; - zeus::CVector3f r7 = line.origin + hT * line.dir; - zeus::CVector3f r9 = vec * (center - line.origin); - - int r28 = 0; - int r25 = 0; - int r26 = 0; - for (int i=0 ; i<3 ; ++i) - { - if (r6[i] >= center[i]) - r28 |= SomeIndexA[i]; - if (r7[i] >= center[i]) - r25 |= SomeIndexA[i]; - if (r9[i] < r9[SomeIndexB[i]]) - r26 |= SomeIndexA[i]; - } - - float f21 = lT; - int r26b = r28; - const std::pair>& idx = SubdivIndex[SomeIndexC[r26][r28 ^ r25]]; - for (int i=0 ; i<=idx.first ; ++i) - { - float f22 = (i < idx.first) ? r9[idx.second[i]] : hT; - if (f22 > lowT && f21 <= f22) - { - Node child = GetChild(r26b); - if (child.x20_nodeType != ETreeType::Invalid) - if (!child.LineTestInternal(line, filter, f21, f22, maxT, vec)) - return false; - } - if (i < idx.first) - r26b ^= 1 << idx.second[i]; - f21 = f22; - } - } - +bool CAreaOctTree::Node::LineTest(const zeus::CLine& line, const CMaterialFilter& filter, float length) const { + if (x20_nodeType == ETreeType::Invalid) return true; + + float f1 = 0.f; + float f2 = 0.f; + if (!BoxLineTest(x0_aabb, line, f1, f2)) + return true; + + zeus::CVector3f recip = 1.f / line.dir; + return LineTestInternal(line, filter, f1 - 0.000099999997f, f2 + 0.000099999997f, length, recip); } -void CAreaOctTree::Node::LineTestExInternal(const zeus::CLine& line, const CMaterialFilter& filter, - SRayResult& res, float lT, float hT, float maxT, - const zeus::CVector3f& dirRecip) const -{ - float lowT = (1.f - FLT_EPSILON * 100.f) * lT; - float highT = (1.f + FLT_EPSILON * 100.f) * hT; - if (maxT != 0.f) - { - if (lowT < 0.f) - lowT = 0.f; - if (highT > maxT) - highT = maxT; - if (lowT > highT) - return; - } +void CAreaOctTree::Node::LineTestEx(const zeus::CLine& line, const CMaterialFilter& filter, SRayResult& res, + float length) const { + if (x20_nodeType == ETreeType::Invalid) + return; - if (x20_nodeType == ETreeType::Leaf) - { - TriListReference triList = GetTriangleArray(); - float bestT = highT; - bool foundTriangle = false; - SRayResult tmpRes; + float lT = 0.f; + float hT = 0.f; + if (!BoxLineTest(x0_aabb, line, lT, hT)) + return; - for (u16 i=0 ; i 1.f) - continue; - - // Prepare to test v parameter - zeus::CVector3f Q = T.cross(e0); - - // Calculate T parameter and test bound - float t = invDet * Q.dot(e1); - if (t >= bestT || t < lowT) - continue; - - // Calculate V parameter and test bound - float v = invDet * Q.dot(line.dir); - if (v < 0.f || u + v > 1.f) - continue; - - // Do material filter - CMaterialList matList(triangle.GetSurfaceFlags()); - if (filter.Passes(matList) && t <= bestT) - { - bestT = t; - foundTriangle = true; - tmpRes.x10_surface.emplace(triangle); - tmpRes.x3c_t = t; - } - } - - if (foundTriangle) - { - res = tmpRes; - res.x0_plane = res.x10_surface->GetPlane(); - } - } - else if (x20_nodeType == ETreeType::Branch) - { - if (GetChildFlags() == 0xA) // 2 leaves - { - SRayResult tmpRes[2]; - for (int i=0 ; i<2 ; ++i) - { - Node child = GetChild(i); - float tf1 = lT; - float tf2 = hT; - if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2)) - child.LineTestExInternal(line, filter, tmpRes[i], tf1, tf2, maxT, dirRecip); - } - - if (!tmpRes[0].x10_surface && !tmpRes[1].x10_surface) - { - res = SRayResult(); - } - else if (tmpRes[0].x10_surface && tmpRes[1].x10_surface) - { - if (tmpRes[0].x3c_t < tmpRes[1].x3c_t) - res = tmpRes[0]; - else - res = tmpRes[1]; - } - else if (tmpRes[0].x10_surface) - { - res = tmpRes[0]; - } - else - { - res = tmpRes[1]; - } - - if (res.x3c_t > highT) - res = SRayResult(); - - return; - } - - zeus::CVector3f center = x0_aabb.center(); // r26 - - zeus::CVector3f lowPoint = line.origin + lT * line.dir; - zeus::CVector3f highPoint = line.origin + hT * line.dir; - int comps[] = {-1, -1, -1, 0}; - float compT[3]; - - int numComps = 0; - for (int i=0 ; i<3 ; ++i) - { - if (lowPoint[i] >= center[i] || highPoint[i] <= center[i]) - if (highPoint[i] >= center[i] || lowPoint[i] <= center[i]) - continue; - if (_close_enough(line.dir[i], 0.f, 0.000099999997f)) - continue; - comps[numComps++] = i; - compT[i] = dirRecip[i] * (center[i] - line.origin[i]); - } - - // Sort componentT least to greatest - switch (numComps) - { - default: - return; - case 0: - case 1: - break; - case 2: - if (compT[comps[1]] < compT[comps[0]]) - std::swap(comps[1], comps[0]); - break; - case 3: - if (compT[0] < compT[1]) - { - if (compT[0] >= compT[2]) - { - comps[0] = 2; - comps[1] = 0; - comps[2] = 1; - } - else if (compT[1] < compT[2]) - { - comps[0] = 0; - comps[1] = 1; - comps[2] = 2; - } - else - { - comps[0] = 0; - comps[1] = 2; - comps[2] = 1; - } - } - else - { - if (compT[1] >= compT[2]) - { - comps[0] = 2; - comps[1] = 1; - comps[2] = 0; - } - else if (compT[0] < compT[2]) - { - comps[0] = 1; - comps[1] = 0; - comps[2] = 2; - } - else - { - comps[0] = 1; - comps[1] = 2; - comps[2] = 0; - } - } - break; - } - - zeus::CVector3f lineStart = line.origin + (lT * line.dir); - int selector = 0; - if (lineStart.x() >= center.x()) - selector = 1; - if (lineStart.y() >= center.y()) - selector |= 1 << 1; - if (lineStart.z() >= center.z()) - selector |= 1 << 2; - - float tmpLoT = lT; - for (int i=-1 ; i= 0) - selector ^= 1 << comps[i]; - float tmpHiT = (i < numComps-1) ? compT[comps[i+1]] : hT; - if (tmpHiT > lowT && tmpLoT <= tmpHiT) - { - Node child = GetChild(selector); - if (child.x20_nodeType != ETreeType::Invalid) - child.LineTestExInternal(line, filter, res, tmpLoT, tmpHiT, maxT, dirRecip); - if (res.x10_surface) - { - if (res.x3c_t > highT) - res = SRayResult(); - break; - } - } - tmpLoT = tmpHiT; - } - } + zeus::CVector3f recip = 1.f / line.dir; + LineTestExInternal(line, filter, res, lT - 0.000099999997f, hT + 0.000099999997f, length, recip); } -bool CAreaOctTree::Node::LineTest(const zeus::CLine& line, const CMaterialFilter& filter, float length) const -{ - if (x20_nodeType == ETreeType::Invalid) - return true; +CAreaOctTree::Node CAreaOctTree::Node::GetChild(int idx) const { + u16 flags = *reinterpret_cast(x18_ptr); + const u32* offsets = reinterpret_cast(x18_ptr + 4); + ETreeType type = ETreeType((flags >> (2 * idx)) & 0x3); - float f1 = 0.f; - float f2 = 0.f; - if (!BoxLineTest(x0_aabb, line, f1, f2)) - return true; - - zeus::CVector3f recip = 1.f / line.dir; - return LineTestInternal(line, filter, f1 - 0.000099999997f, f2 + 0.000099999997f, length, recip); -} - -void CAreaOctTree::Node::LineTestEx(const zeus::CLine& line, const CMaterialFilter& filter, - SRayResult& res, float length) const -{ - if (x20_nodeType == ETreeType::Invalid) - return; - - float lT = 0.f; - float hT = 0.f; - if (!BoxLineTest(x0_aabb, line, lT, hT)) - return; - - zeus::CVector3f recip = 1.f / line.dir; - LineTestExInternal(line, filter, res, lT - 0.000099999997f, hT + 0.000099999997f, length, recip); -} - -CAreaOctTree::Node CAreaOctTree::Node::GetChild(int idx) const -{ - u16 flags = *reinterpret_cast(x18_ptr); - const u32* offsets = reinterpret_cast(x18_ptr + 4); - ETreeType type = ETreeType((flags >> (2 * idx)) & 0x3); - - if (type == ETreeType::Branch) - { - zeus::CAABox pos, neg, res; - x0_aabb.splitZ(neg, pos); - if (idx & 4) - { - zeus::CAABox(pos).splitY(neg, pos); - if (idx & 2) - { - zeus::CAABox(pos).splitX(neg, pos); - if (idx & 1) - res = pos; - else - res = neg; - } - else - { - zeus::CAABox(neg).splitX(neg, pos); - if (idx & 1) - res = pos; - else - res = neg; - } - } + if (type == ETreeType::Branch) { + zeus::CAABox pos, neg, res; + x0_aabb.splitZ(neg, pos); + if (idx & 4) { + zeus::CAABox(pos).splitY(neg, pos); + if (idx & 2) { + zeus::CAABox(pos).splitX(neg, pos); + if (idx & 1) + res = pos; else - { - zeus::CAABox(neg).splitY(neg, pos); - if (idx & 2) - { - zeus::CAABox(pos).splitX(neg, pos); - if (idx & 1) - res = pos; - else - res = neg; - } - else - { - zeus::CAABox(neg).splitX(neg, pos); - if (idx & 1) - res = pos; - else - res = neg; - } - } + res = neg; + } else { + zeus::CAABox(neg).splitX(neg, pos); + if (idx & 1) + res = pos; + else + res = neg; + } + } else { + zeus::CAABox(neg).splitY(neg, pos); + if (idx & 2) { + zeus::CAABox(pos).splitX(neg, pos); + if (idx & 1) + res = pos; + else + res = neg; + } else { + zeus::CAABox(neg).splitX(neg, pos); + if (idx & 1) + res = pos; + else + res = neg; + } + } - return Node(x18_ptr + offsets[idx] + 36, res, x1c_owner, ETreeType::Branch); - } - else if (type == ETreeType::Leaf) - { - const float* aabb = reinterpret_cast(x18_ptr + offsets[idx] + 36); - zeus::CAABox aabbObj(aabb[0], aabb[1], aabb[2], aabb[3], aabb[4], aabb[5]); - return Node(aabb, aabbObj, x1c_owner, ETreeType::Leaf); - } - else - { - return Node(nullptr, zeus::CAABox::skNullBox, x1c_owner, ETreeType::Invalid); - } + return Node(x18_ptr + offsets[idx] + 36, res, x1c_owner, ETreeType::Branch); + } else if (type == ETreeType::Leaf) { + const float* aabb = reinterpret_cast(x18_ptr + offsets[idx] + 36); + zeus::CAABox aabbObj(aabb[0], aabb[1], aabb[2], aabb[3], aabb[4], aabb[5]); + return Node(aabb, aabbObj, x1c_owner, ETreeType::Leaf); + } else { + return Node(nullptr, zeus::CAABox::skNullBox, x1c_owner, ETreeType::Invalid); + } } -void CAreaOctTree::SwapTreeNode(u8* ptr, Node::ETreeType type) -{ - if (type == Node::ETreeType::Branch) - { - u16* typeBits = reinterpret_cast(ptr); - *typeBits = hecl::SBig(*typeBits); - u32* offsets = reinterpret_cast(ptr + 4); +void CAreaOctTree::SwapTreeNode(u8* ptr, Node::ETreeType type) { + if (type == Node::ETreeType::Branch) { + u16* typeBits = reinterpret_cast(ptr); + *typeBits = hecl::SBig(*typeBits); + u32* offsets = reinterpret_cast(ptr + 4); - for (int i=0 ; i<8 ; ++i) - { - Node::ETreeType ctype = Node::ETreeType((*typeBits >> (2 * i)) & 0x3); - offsets[i] = hecl::SBig(offsets[i]); - SwapTreeNode(ptr + offsets[i] + 36, ctype); - } + for (int i = 0; i < 8; ++i) { + Node::ETreeType ctype = Node::ETreeType((*typeBits >> (2 * i)) & 0x3); + offsets[i] = hecl::SBig(offsets[i]); + SwapTreeNode(ptr + offsets[i] + 36, ctype); } - else if (type == Node::ETreeType::Leaf) - { - float* aabb = reinterpret_cast(ptr); - aabb[0] = hecl::SBig(aabb[0]); - aabb[1] = hecl::SBig(aabb[1]); - aabb[2] = hecl::SBig(aabb[2]); - aabb[3] = hecl::SBig(aabb[3]); - aabb[4] = hecl::SBig(aabb[4]); - aabb[5] = hecl::SBig(aabb[5]); + } else if (type == Node::ETreeType::Leaf) { + float* aabb = reinterpret_cast(ptr); + aabb[0] = hecl::SBig(aabb[0]); + aabb[1] = hecl::SBig(aabb[1]); + aabb[2] = hecl::SBig(aabb[2]); + aabb[3] = hecl::SBig(aabb[3]); + aabb[4] = hecl::SBig(aabb[4]); + aabb[5] = hecl::SBig(aabb[5]); - u16* countIdxs = reinterpret_cast(ptr + 24); - *countIdxs = hecl::SBig(*countIdxs); - for (u16 i=0 ; i<*countIdxs ; ++i) - countIdxs[i+1] = hecl::SBig(countIdxs[i+1]); - } + u16* countIdxs = reinterpret_cast(ptr + 24); + *countIdxs = hecl::SBig(*countIdxs); + for (u16 i = 0; i < *countIdxs; ++i) + countIdxs[i + 1] = hecl::SBig(countIdxs[i + 1]); + } } CAreaOctTree::CAreaOctTree(const zeus::CAABox& aabb, Node::ETreeType treeType, const u8* buf, const u8* treeBuf, - u32 matCount, const u32* materials, const u8* vertMats, const u8* edgeMats, const u8* polyMats, - u32 edgeCount, const CCollisionEdge* edges, u32 polyCount, const u16* polyEdges, - u32 vertCount, const float* verts) -: x0_aabb(aabb), x18_treeType(treeType), x1c_buf(buf), x20_treeBuf(treeBuf), - x24_matCount(matCount), x28_materials(materials), x2c_vertMats(vertMats), - x30_edgeMats(edgeMats), x34_polyMats(polyMats), x38_edgeCount(edgeCount), - x3c_edges(edges), x40_polyCount(polyCount), x44_polyEdges(polyEdges), - x48_vertCount(vertCount), x4c_verts(verts) -{ - SwapTreeNode(const_cast(x20_treeBuf), treeType); + u32 matCount, const u32* materials, const u8* vertMats, const u8* edgeMats, + const u8* polyMats, u32 edgeCount, const CCollisionEdge* edges, u32 polyCount, + const u16* polyEdges, u32 vertCount, const float* verts) +: x0_aabb(aabb) +, x18_treeType(treeType) +, x1c_buf(buf) +, x20_treeBuf(treeBuf) +, x24_matCount(matCount) +, x28_materials(materials) +, x2c_vertMats(vertMats) +, x30_edgeMats(edgeMats) +, x34_polyMats(polyMats) +, x38_edgeCount(edgeCount) +, x3c_edges(edges) +, x40_polyCount(polyCount) +, x44_polyEdges(polyEdges) +, x48_vertCount(vertCount) +, x4c_verts(verts) { + SwapTreeNode(const_cast(x20_treeBuf), treeType); - for (u32 i=0 ; i(x28_materials)[i] = hecl::SBig(x28_materials[i]); + for (u32 i = 0; i < matCount; ++i) + const_cast(x28_materials)[i] = hecl::SBig(x28_materials[i]); - for (u32 i=0 ; i(x3c_edges)[i].swapBig(); + for (u32 i = 0; i < edgeCount; ++i) + const_cast(x3c_edges)[i].swapBig(); - for (u32 i=0 ; i(x44_polyEdges)[i] = hecl::SBig(x44_polyEdges[i]); + for (u32 i = 0; i < polyCount; ++i) + const_cast(x44_polyEdges)[i] = hecl::SBig(x44_polyEdges[i]); - for (u32 i=0 ; i(x4c_verts)[i] = hecl::SBig(x4c_verts[i]); + for (u32 i = 0; i < vertCount * 3; ++i) + const_cast(x4c_verts)[i] = hecl::SBig(x4c_verts[i]); } -std::unique_ptr CAreaOctTree::MakeFromMemory(const u8* buf, unsigned int size) -{ - athena::io::MemoryReader r(buf + 8, size - 8); - r.readUint32Big(); - r.readUint32Big(); - zeus::CAABox aabb; - aabb.readBoundingBoxBig(r); - Node::ETreeType nodeType = Node::ETreeType(r.readUint32Big()); - u32 treeSize = r.readUint32Big(); - const u8* cur = reinterpret_cast(buf) + 8 + r.position(); +std::unique_ptr CAreaOctTree::MakeFromMemory(const u8* buf, unsigned int size) { + athena::io::MemoryReader r(buf + 8, size - 8); + r.readUint32Big(); + r.readUint32Big(); + zeus::CAABox aabb; + aabb.readBoundingBoxBig(r); + Node::ETreeType nodeType = Node::ETreeType(r.readUint32Big()); + u32 treeSize = r.readUint32Big(); + const u8* cur = reinterpret_cast(buf) + 8 + r.position(); - const u8* treeBuf = cur; - cur += treeSize; + const u8* treeBuf = cur; + cur += treeSize; - u32 matCount = hecl::SBig(*reinterpret_cast(cur)); - cur += 4; - const u32* matBuf = reinterpret_cast(cur); - cur += 4 * matCount; + u32 matCount = hecl::SBig(*reinterpret_cast(cur)); + cur += 4; + const u32* matBuf = reinterpret_cast(cur); + cur += 4 * matCount; - u32 vertMatsCount = hecl::SBig(*reinterpret_cast(cur)); - cur += 4; - const u8* vertMatsBuf = cur; - cur += vertMatsCount; + u32 vertMatsCount = hecl::SBig(*reinterpret_cast(cur)); + cur += 4; + const u8* vertMatsBuf = cur; + cur += vertMatsCount; - u32 edgeMatsCount = hecl::SBig(*reinterpret_cast(cur)); - cur += 4; - const u8* edgeMatsBuf = cur; - cur += edgeMatsCount; + u32 edgeMatsCount = hecl::SBig(*reinterpret_cast(cur)); + cur += 4; + const u8* edgeMatsBuf = cur; + cur += edgeMatsCount; - u32 polyMatsCount = hecl::SBig(*reinterpret_cast(cur)); - cur += 4; - const u8* polyMatsBuf = cur; - cur += polyMatsCount; + u32 polyMatsCount = hecl::SBig(*reinterpret_cast(cur)); + cur += 4; + const u8* polyMatsBuf = cur; + cur += polyMatsCount; - u32 edgeCount = hecl::SBig(*reinterpret_cast(cur)); - cur += 4; - const CCollisionEdge* edgeBuf = reinterpret_cast(cur); - cur += edgeCount * sizeof(edgeCount); + u32 edgeCount = hecl::SBig(*reinterpret_cast(cur)); + cur += 4; + const CCollisionEdge* edgeBuf = reinterpret_cast(cur); + cur += edgeCount * sizeof(edgeCount); - u32 polyCount = hecl::SBig(*reinterpret_cast(cur)); - cur += 4; - const u16* polyBuf = reinterpret_cast(cur); - cur += polyCount * 2; + u32 polyCount = hecl::SBig(*reinterpret_cast(cur)); + cur += 4; + const u16* polyBuf = reinterpret_cast(cur); + cur += polyCount * 2; - u32 vertCount = hecl::SBig(*reinterpret_cast(cur)); - cur += 4; - const float* vertBuf = reinterpret_cast(cur); + u32 vertCount = hecl::SBig(*reinterpret_cast(cur)); + cur += 4; + const float* vertBuf = reinterpret_cast(cur); - return std::make_unique(aabb, nodeType, reinterpret_cast(buf + 8), treeBuf, - matCount, matBuf, vertMatsBuf, edgeMatsBuf, polyMatsBuf, - edgeCount, edgeBuf, polyCount, polyBuf, vertCount, vertBuf); + return std::make_unique(aabb, nodeType, reinterpret_cast(buf + 8), treeBuf, matCount, matBuf, + vertMatsBuf, edgeMatsBuf, polyMatsBuf, edgeCount, edgeBuf, polyCount, polyBuf, + vertCount, vertBuf); } -CCollisionSurface CAreaOctTree::GetMasterListTriangle(u16 idx) const -{ - const CCollisionEdge& e0 = x3c_edges[x44_polyEdges[idx*3]]; - const CCollisionEdge& e1 = x3c_edges[x44_polyEdges[idx*3+1]]; - u16 vert2 = e1.GetVertIndex2(); - if (e1.GetVertIndex1() != e0.GetVertIndex1()) - if (e1.GetVertIndex1() != e0.GetVertIndex2()) - vert2 = e1.GetVertIndex1(); +CCollisionSurface CAreaOctTree::GetMasterListTriangle(u16 idx) const { + const CCollisionEdge& e0 = x3c_edges[x44_polyEdges[idx * 3]]; + const CCollisionEdge& e1 = x3c_edges[x44_polyEdges[idx * 3 + 1]]; + u16 vert2 = e1.GetVertIndex2(); + if (e1.GetVertIndex1() != e0.GetVertIndex1()) + if (e1.GetVertIndex1() != e0.GetVertIndex2()) + vert2 = e1.GetVertIndex1(); - u32 material = x28_materials[x34_polyMats[idx]]; - if (material & 0x2000000) - return CCollisionSurface(GetVert(e0.GetVertIndex2()), GetVert(e0.GetVertIndex1()), - GetVert(vert2), material); - else - return CCollisionSurface(GetVert(e0.GetVertIndex1()), GetVert(e0.GetVertIndex2()), - GetVert(vert2), material); + u32 material = x28_materials[x34_polyMats[idx]]; + if (material & 0x2000000) + return CCollisionSurface(GetVert(e0.GetVertIndex2()), GetVert(e0.GetVertIndex1()), GetVert(vert2), material); + else + return CCollisionSurface(GetVert(e0.GetVertIndex1()), GetVert(e0.GetVertIndex2()), GetVert(vert2), material); } -void CAreaOctTree::GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const -{ - const CCollisionEdge& e0 = x3c_edges[x44_polyEdges[idx*3]]; - const CCollisionEdge& e1 = x3c_edges[x44_polyEdges[idx*3+1]]; - indicesOut[2] = - (e1.GetVertIndex1() != e0.GetVertIndex1() && e1.GetVertIndex1() != e0.GetVertIndex2()) ? - e1.GetVertIndex1() : e1.GetVertIndex2(); +void CAreaOctTree::GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const { + const CCollisionEdge& e0 = x3c_edges[x44_polyEdges[idx * 3]]; + const CCollisionEdge& e1 = x3c_edges[x44_polyEdges[idx * 3 + 1]]; + indicesOut[2] = (e1.GetVertIndex1() != e0.GetVertIndex1() && e1.GetVertIndex1() != e0.GetVertIndex2()) + ? e1.GetVertIndex1() + : e1.GetVertIndex2(); - u32 material = x28_materials[x34_polyMats[idx]]; - if (material & 0x2000000) - { - indicesOut[0] = e0.GetVertIndex2(); - indicesOut[1] = e0.GetVertIndex1(); - } - else - { - indicesOut[0] = e0.GetVertIndex1(); - indicesOut[1] = e0.GetVertIndex2(); - } + u32 material = x28_materials[x34_polyMats[idx]]; + if (material & 0x2000000) { + indicesOut[0] = e0.GetVertIndex2(); + indicesOut[1] = e0.GetVertIndex1(); + } else { + indicesOut[0] = e0.GetVertIndex1(); + indicesOut[1] = e0.GetVertIndex2(); + } } -} +} // namespace urde diff --git a/Runtime/Collision/CAreaOctTree.hpp b/Runtime/Collision/CAreaOctTree.hpp index f24371d0a..ed96743be 100644 --- a/Runtime/Collision/CAreaOctTree.hpp +++ b/Runtime/Collision/CAreaOctTree.hpp @@ -6,137 +6,109 @@ #include "Collision/CCollisionSurface.hpp" #include "zeus/CLine.hpp" -namespace urde -{ +namespace urde { class CMaterialFilter; -class CAreaOctTree -{ - friend class CBooRenderer; +class CAreaOctTree { + friend class CBooRenderer; + public: - struct SRayResult - { - zeus::CPlane x0_plane; - std::experimental::optional x10_surface; - float x3c_t; - }; + struct SRayResult { + zeus::CPlane x0_plane; + std::experimental::optional x10_surface; + float x3c_t; + }; - class TriListReference - { - const u16* m_ptr; - public: - TriListReference(const u16* ptr) - : m_ptr(ptr) {} - u16 GetAt(int idx) const { return m_ptr[idx+1]; } - u16 GetSize() const { return m_ptr[0]; } - }; + class TriListReference { + const u16* m_ptr; - class Node - { - public: - enum class ETreeType - { - Invalid, - Branch, - Leaf - }; + public: + TriListReference(const u16* ptr) : m_ptr(ptr) {} + u16 GetAt(int idx) const { return m_ptr[idx + 1]; } + u16 GetSize() const { return m_ptr[0]; } + }; - private: - zeus::CAABox x0_aabb; - const u8* x18_ptr; - const CAreaOctTree& x1c_owner; - ETreeType x20_nodeType; - - bool LineTestInternal(const zeus::CLine&, const CMaterialFilter&, float, float, float, - const zeus::CVector3f&) const; - void LineTestExInternal(const zeus::CLine&, const CMaterialFilter&, SRayResult&, float, float, float, - const zeus::CVector3f&) const; - - public: - Node(const void* ptr, const zeus::CAABox& aabb, - const CAreaOctTree& owner, ETreeType type) - : x0_aabb(aabb), x18_ptr(reinterpret_cast(ptr)), x1c_owner(owner), x20_nodeType(type) - { - } - - bool LineTest(const zeus::CLine&, const CMaterialFilter&, float) const; - void LineTestEx(const zeus::CLine&, const CMaterialFilter&, SRayResult&, float) const; - - const CAreaOctTree& GetOwner() const - { - return x1c_owner; - } - - const zeus::CAABox& GetBoundingBox() const - { - return x0_aabb; - } - - u16 GetChildFlags() const - { - return *reinterpret_cast(x18_ptr); - } - - Node GetChild(int idx) const; - - TriListReference GetTriangleArray() const - { - return TriListReference(reinterpret_cast(x18_ptr + 24)); - } - - ETreeType GetChildType(int idx) const - { - u16 flags = *reinterpret_cast(x18_ptr); - return ETreeType((flags >> (2 * idx)) & 0x3); - } - - ETreeType GetTreeType() const { return x20_nodeType; } - }; + class Node { + public: + enum class ETreeType { Invalid, Branch, Leaf }; + private: zeus::CAABox x0_aabb; - Node::ETreeType x18_treeType; - const u8* x1c_buf; - const u8* x20_treeBuf; - u32 x24_matCount; - const u32* x28_materials; - const u8* x2c_vertMats; - const u8* x30_edgeMats; - const u8* x34_polyMats; - u32 x38_edgeCount; - const CCollisionEdge* x3c_edges; - u32 x40_polyCount; - const u16* x44_polyEdges; - u32 x48_vertCount; - const float* x4c_verts; + const u8* x18_ptr; + const CAreaOctTree& x1c_owner; + ETreeType x20_nodeType; - void SwapTreeNode(u8* ptr, Node::ETreeType type); + bool LineTestInternal(const zeus::CLine&, const CMaterialFilter&, float, float, float, + const zeus::CVector3f&) const; + void LineTestExInternal(const zeus::CLine&, const CMaterialFilter&, SRayResult&, float, float, float, + const zeus::CVector3f&) const; + + public: + Node(const void* ptr, const zeus::CAABox& aabb, const CAreaOctTree& owner, ETreeType type) + : x0_aabb(aabb), x18_ptr(reinterpret_cast(ptr)), x1c_owner(owner), x20_nodeType(type) {} + + bool LineTest(const zeus::CLine&, const CMaterialFilter&, float) const; + void LineTestEx(const zeus::CLine&, const CMaterialFilter&, SRayResult&, float) const; + + const CAreaOctTree& GetOwner() const { return x1c_owner; } + + const zeus::CAABox& GetBoundingBox() const { return x0_aabb; } + + u16 GetChildFlags() const { return *reinterpret_cast(x18_ptr); } + + Node GetChild(int idx) const; + + TriListReference GetTriangleArray() const { return TriListReference(reinterpret_cast(x18_ptr + 24)); } + + ETreeType GetChildType(int idx) const { + u16 flags = *reinterpret_cast(x18_ptr); + return ETreeType((flags >> (2 * idx)) & 0x3); + } + + ETreeType GetTreeType() const { return x20_nodeType; } + }; + + zeus::CAABox x0_aabb; + Node::ETreeType x18_treeType; + const u8* x1c_buf; + const u8* x20_treeBuf; + u32 x24_matCount; + const u32* x28_materials; + const u8* x2c_vertMats; + const u8* x30_edgeMats; + const u8* x34_polyMats; + u32 x38_edgeCount; + const CCollisionEdge* x3c_edges; + u32 x40_polyCount; + const u16* x44_polyEdges; + u32 x48_vertCount; + const float* x4c_verts; + + void SwapTreeNode(u8* ptr, Node::ETreeType type); public: - CAreaOctTree(const zeus::CAABox& aabb, Node::ETreeType treeType, const u8* buf, const u8* treeBuf, - u32 matCount, const u32* materials, const u8* vertMats, const u8* edgeMats, const u8* polyMats, - u32 edgeCount, const CCollisionEdge* edges, u32 polyCount, const u16* polyEdges, - u32 vertCount, const float* verts); + CAreaOctTree(const zeus::CAABox& aabb, Node::ETreeType treeType, const u8* buf, const u8* treeBuf, u32 matCount, + const u32* materials, const u8* vertMats, const u8* edgeMats, const u8* polyMats, u32 edgeCount, + const CCollisionEdge* edges, u32 polyCount, const u16* polyEdges, u32 vertCount, const float* verts); - const zeus::CAABox& GetAABB() const { return x0_aabb; } - Node GetRootNode() const { return Node(x20_treeBuf, x0_aabb, *this, x18_treeType); } - const u8* GetTreeMemory() const { return x20_treeBuf; } - zeus::CVector3f GetVert(int idx) const - { - const float* vert = &x4c_verts[idx * 3]; - return zeus::CVector3f(vert[0], vert[1], vert[2]); - } - const CCollisionEdge& GetEdge(int idx) const { return x3c_edges[idx]; } - u32 GetVertMaterial(int idx) const { return x28_materials[x2c_vertMats[idx]]; } - u32 GetEdgeMaterial(int idx) const { return x28_materials[x30_edgeMats[idx]]; } - u32 GetTriangleMaterial(int idx) const { return x28_materials[x34_polyMats[idx]]; } - u32 GetNumEdges() const { return x38_edgeCount; } - u32 GetNumVerts() const { return x48_vertCount; } - u32 GetNumTriangles() const { return x40_polyCount; } - CCollisionSurface GetMasterListTriangle(u16 idx) const; - void GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const; - const u16* GetTriangleEdgeIndices(u16 idx) const { return &x44_polyEdges[idx * 3]; } + const zeus::CAABox& GetAABB() const { return x0_aabb; } + Node GetRootNode() const { return Node(x20_treeBuf, x0_aabb, *this, x18_treeType); } + const u8* GetTreeMemory() const { return x20_treeBuf; } + zeus::CVector3f GetVert(int idx) const { + const float* vert = &x4c_verts[idx * 3]; + return zeus::CVector3f(vert[0], vert[1], vert[2]); + } + const CCollisionEdge& GetEdge(int idx) const { return x3c_edges[idx]; } + u32 GetVertMaterial(int idx) const { return x28_materials[x2c_vertMats[idx]]; } + u32 GetEdgeMaterial(int idx) const { return x28_materials[x30_edgeMats[idx]]; } + u32 GetTriangleMaterial(int idx) const { return x28_materials[x34_polyMats[idx]]; } + u32 GetNumEdges() const { return x38_edgeCount; } + u32 GetNumVerts() const { return x48_vertCount; } + u32 GetNumTriangles() const { return x40_polyCount; } + CCollisionSurface GetMasterListTriangle(u16 idx) const; + void GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const; + const u16* GetTriangleEdgeIndices(u16 idx) const { return &x44_polyEdges[idx * 3]; } - static std::unique_ptr MakeFromMemory(const u8* buf, unsigned int size); + static std::unique_ptr MakeFromMemory(const u8* buf, unsigned int size); }; -} - +} // namespace urde diff --git a/Runtime/Collision/CBallFilter.cpp b/Runtime/Collision/CBallFilter.cpp index 62134f8a0..ee0b5a104 100644 --- a/Runtime/Collision/CBallFilter.cpp +++ b/Runtime/Collision/CBallFilter.cpp @@ -1,11 +1,9 @@ #include "CBallFilter.hpp" #include "CollisionUtil.hpp" -namespace urde -{ +namespace urde { -void CBallFilter::Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const -{ - CollisionUtil::AddAverageToFront(in, out); +void CBallFilter::Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const { + CollisionUtil::AddAverageToFront(in, out); } -} +} // namespace urde diff --git a/Runtime/Collision/CBallFilter.hpp b/Runtime/Collision/CBallFilter.hpp index c1c8b6fc1..4301c56e1 100644 --- a/Runtime/Collision/CBallFilter.hpp +++ b/Runtime/Collision/CBallFilter.hpp @@ -2,16 +2,13 @@ #include "ICollisionFilter.hpp" -namespace urde -{ +namespace urde { class CPhysicsActor; -class CBallFilter : public ICollisionFilter -{ +class CBallFilter : public ICollisionFilter { public: - CBallFilter(CActor& actor) : ICollisionFilter(actor) {} - void Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const; + CBallFilter(CActor& actor) : ICollisionFilter(actor) {} + void Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const; }; -} - +} // namespace urde diff --git a/Runtime/Collision/CCollidableAABox.cpp b/Runtime/Collision/CCollidableAABox.cpp index 48b2cecaa..be3248e77 100644 --- a/Runtime/Collision/CCollidableAABox.cpp +++ b/Runtime/Collision/CCollidableAABox.cpp @@ -4,145 +4,112 @@ #include "CCollisionInfo.hpp" #include "CInternalRayCastStructure.hpp" -namespace urde -{ +namespace urde { const CCollisionPrimitive::Type CCollidableAABox::sType(CCollidableAABox::SetStaticTableIndex, "CCollidableAABox"); u32 CCollidableAABox::sTableIndex = -1; -CCollidableAABox::CCollidableAABox() -{ -} +CCollidableAABox::CCollidableAABox() {} CCollidableAABox::CCollidableAABox(const zeus::CAABox& aabox, const CMaterialList& list) - : CCollisionPrimitive(list) - , x10_aabox(aabox) -{ +: CCollisionPrimitive(list), x10_aabox(aabox) {} + +zeus::CAABox CCollidableAABox::Transform(const zeus::CTransform& xf) const { + return {xf.origin + x10_aabox.min, xf.origin + x10_aabox.max}; } -zeus::CAABox CCollidableAABox::Transform(const zeus::CTransform& xf) const -{ - return {xf.origin + x10_aabox.min, xf.origin + x10_aabox.max}; +u32 CCollidableAABox::GetTableIndex() const { return sTableIndex; } + +zeus::CAABox CCollidableAABox::CalculateAABox(const zeus::CTransform& xf) const { return Transform(xf); } + +zeus::CAABox CCollidableAABox::CalculateLocalAABox() const { return x10_aabox; } + +FourCC CCollidableAABox::GetPrimType() const { return SBIG('AABX'); } + +CRayCastResult CCollidableAABox::CastRayInternal(const CInternalRayCastStructure& rayCast) const { + if (!rayCast.GetFilter().Passes(GetMaterial())) + return {}; + zeus::CTransform rayCastXfInv = rayCast.GetTransform().inverse(); + zeus::CVector3f localRayStart = rayCastXfInv * rayCast.GetRay().start; + zeus::CVector3f localRayDir = rayCastXfInv.rotate(rayCast.GetRay().dir); + float tMin, tMax; + int axis; + bool sign; + if (!CollisionUtil::BoxLineTest(x10_aabox, localRayStart, localRayDir, tMin, tMax, axis, sign) || tMin < 0.f || + (rayCast.GetMaxTime() > 0.f && tMin > rayCast.GetMaxTime())) + return {}; + + zeus::CVector3f planeNormal; + planeNormal[axis] = sign ? 1.f : -1.f; + float planeD = axis ? x10_aabox.min[axis] : -x10_aabox.max[axis]; + CRayCastResult result(tMin, localRayStart + tMin * localRayDir, zeus::CPlane(planeNormal, planeD), GetMaterial()); + result.Transform(rayCast.GetTransform()); + return result; } -u32 CCollidableAABox::GetTableIndex() const -{ - return sTableIndex; -} +const CCollisionPrimitive::Type& CCollidableAABox::GetType() { return sType; } -zeus::CAABox CCollidableAABox::CalculateAABox(const zeus::CTransform& xf) const -{ - return Transform(xf); -} - -zeus::CAABox CCollidableAABox::CalculateLocalAABox() const -{ - return x10_aabox; -} - -FourCC CCollidableAABox::GetPrimType() const -{ - return SBIG('AABX'); -} - -CRayCastResult CCollidableAABox::CastRayInternal(const CInternalRayCastStructure& rayCast) const -{ - if (!rayCast.GetFilter().Passes(GetMaterial())) - return {}; - zeus::CTransform rayCastXfInv = rayCast.GetTransform().inverse(); - zeus::CVector3f localRayStart = rayCastXfInv * rayCast.GetRay().start; - zeus::CVector3f localRayDir = rayCastXfInv.rotate(rayCast.GetRay().dir); - float tMin, tMax; - int axis; - bool sign; - if (!CollisionUtil::BoxLineTest(x10_aabox, localRayStart, localRayDir, tMin, tMax, axis, sign) || - tMin < 0.f || (rayCast.GetMaxTime() > 0.f && tMin > rayCast.GetMaxTime())) - return {}; - - zeus::CVector3f planeNormal; - planeNormal[axis] = sign ? 1.f : -1.f; - float planeD = axis ? x10_aabox.min[axis] : -x10_aabox.max[axis]; - CRayCastResult result(tMin, localRayStart + tMin * localRayDir, zeus::CPlane(planeNormal, planeD), GetMaterial()); - result.Transform(rayCast.GetTransform()); - return result; -} - -const CCollisionPrimitive::Type& CCollidableAABox::GetType() -{ - return sType; -} - -void CCollidableAABox::SetStaticTableIndex(u32 index) -{ - sTableIndex = index; -} +void CCollidableAABox::SetStaticTableIndex(u32 index) { sTableIndex = index; } bool CCollidableAABox::CollideMovingAABox(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& infoOut) -{ - const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableAABox& p1 = static_cast(collision.GetRight().GetPrim()); + double& dOut, CCollisionInfo& infoOut) { + const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableAABox& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CAABox b0 = p0.Transform(collision.GetLeft().GetTransform()); - zeus::CAABox b1 = p1.Transform(collision.GetRight().GetTransform()); + zeus::CAABox b0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::CAABox b1 = p1.Transform(collision.GetRight().GetTransform()); - double d; - zeus::CVector3f point, normal; - if (CollisionUtil::AABox_AABox_Moving(b0, b1, dir, d, point, normal) && d > 0.0 && d < dOut) - { - dOut = d; - infoOut = CCollisionInfo(point, p0.GetMaterial(), p1.GetMaterial(), normal, -normal); - return true; - } + double d; + zeus::CVector3f point, normal; + if (CollisionUtil::AABox_AABox_Moving(b0, b1, dir, d, point, normal) && d > 0.0 && d < dOut) { + dOut = d; + infoOut = CCollisionInfo(point, p0.GetMaterial(), p1.GetMaterial(), normal, -normal); + return true; + } - return false; + return false; } bool CCollidableAABox::CollideMovingSphere(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& infoOut) -{ - const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableSphere& p1 = static_cast(collision.GetRight().GetPrim()); + double& dOut, CCollisionInfo& infoOut) { + const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableSphere& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CAABox b0 = p0.CalculateAABox(collision.GetLeft().GetTransform()); - zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform()); + zeus::CAABox b0 = p0.CalculateAABox(collision.GetLeft().GetTransform()); + zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform()); - double d = dOut; - zeus::CVector3f point, normal; - if (CollisionUtil::MovingSphereAABox(s1, b0, -dir, d, point, normal) && d < dOut) - { - point = s1.position - s1.radius * normal; - dOut = d; - infoOut = CCollisionInfo(point, p0.GetMaterial(), p1.GetMaterial(), -normal); - return true; - } + double d = dOut; + zeus::CVector3f point, normal; + if (CollisionUtil::MovingSphereAABox(s1, b0, -dir, d, point, normal) && d < dOut) { + point = s1.position - s1.radius * normal; + dOut = d; + infoOut = CCollisionInfo(point, p0.GetMaterial(), p1.GetMaterial(), -normal); + return true; + } - return false; + return false; } -namespace Collide -{ +namespace Collide { -bool AABox_AABox(const CInternalCollisionStructure& collision, CCollisionInfoList& list) -{ - const CCollidableAABox& box0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableAABox& box1 = static_cast(collision.GetRight().GetPrim()); +bool AABox_AABox(const CInternalCollisionStructure& collision, CCollisionInfoList& list) { + const CCollidableAABox& box0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableAABox& box1 = static_cast(collision.GetRight().GetPrim()); - zeus::CAABox aabb0 = box0.Transform(collision.GetLeft().GetTransform()); - zeus::CAABox aabb1 = box1.Transform(collision.GetRight().GetTransform()); + zeus::CAABox aabb0 = box0.Transform(collision.GetLeft().GetTransform()); + zeus::CAABox aabb1 = box1.Transform(collision.GetRight().GetTransform()); - return CollisionUtil::AABoxAABoxIntersection(aabb0, box0.GetMaterial(), aabb1, box1.GetMaterial(), list); + return CollisionUtil::AABoxAABoxIntersection(aabb0, box0.GetMaterial(), aabb1, box1.GetMaterial(), list); } -bool AABox_AABox_Bool(const CInternalCollisionStructure& collision) -{ - const CCollidableAABox& box0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableAABox& box1 = static_cast(collision.GetRight().GetPrim()); +bool AABox_AABox_Bool(const CInternalCollisionStructure& collision) { + const CCollidableAABox& box0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableAABox& box1 = static_cast(collision.GetRight().GetPrim()); - zeus::CAABox aabb0 = box0.Transform(collision.GetLeft().GetTransform()); - zeus::CAABox aabb1 = box1.Transform(collision.GetRight().GetTransform()); + zeus::CAABox aabb0 = box0.Transform(collision.GetLeft().GetTransform()); + zeus::CAABox aabb1 = box1.Transform(collision.GetRight().GetTransform()); - return CollisionUtil::AABoxAABoxIntersection(aabb0, aabb1); + return CollisionUtil::AABoxAABoxIntersection(aabb0, aabb1); } -} -} +} // namespace Collide +} // namespace urde diff --git a/Runtime/Collision/CCollidableAABox.hpp b/Runtime/Collision/CCollidableAABox.hpp index 2d0c95931..73ac8678d 100644 --- a/Runtime/Collision/CCollidableAABox.hpp +++ b/Runtime/Collision/CCollidableAABox.hpp @@ -2,39 +2,33 @@ #include "CCollisionPrimitive.hpp" -namespace urde -{ -namespace Collide -{ +namespace urde { +namespace Collide { bool AABox_AABox(const CInternalCollisionStructure&, CCollisionInfoList&); bool AABox_AABox_Bool(const CInternalCollisionStructure&); -} +} // namespace Collide -class CCollidableAABox : public CCollisionPrimitive -{ - static const Type sType; - static u32 sTableIndex; +class CCollidableAABox : public CCollisionPrimitive { + static const Type sType; + static u32 sTableIndex; - zeus::CAABox x10_aabox; + zeus::CAABox x10_aabox; public: - CCollidableAABox(); - CCollidableAABox(const zeus::CAABox&, const CMaterialList&); + CCollidableAABox(); + CCollidableAABox(const zeus::CAABox&, const CMaterialList&); - zeus::CAABox Transform(const zeus::CTransform&) const; - virtual u32 GetTableIndex() const; - virtual zeus::CAABox CalculateAABox(const zeus::CTransform&) const; - virtual zeus::CAABox CalculateLocalAABox() const; - virtual FourCC GetPrimType() const; - virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; - const zeus::CAABox& GetAABB() const { return x10_aabox; } + zeus::CAABox Transform(const zeus::CTransform&) const; + virtual u32 GetTableIndex() const; + virtual zeus::CAABox CalculateAABox(const zeus::CTransform&) const; + virtual zeus::CAABox CalculateLocalAABox() const; + virtual FourCC GetPrimType() const; + virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; + const zeus::CAABox& GetAABB() const { return x10_aabox; } - static const CCollisionPrimitive::Type& GetType(); - static void SetStaticTableIndex(u32 index); - static bool CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, - CCollisionInfo&); - static bool CollideMovingSphere(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, - CCollisionInfo&); + static const CCollisionPrimitive::Type& GetType(); + static void SetStaticTableIndex(u32 index); + static bool CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&); + static bool CollideMovingSphere(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&); }; -} - +} // namespace urde diff --git a/Runtime/Collision/CCollidableCollisionSurface.cpp b/Runtime/Collision/CCollidableCollisionSurface.cpp index 5711850be..1e96be8f2 100644 --- a/Runtime/Collision/CCollidableCollisionSurface.cpp +++ b/Runtime/Collision/CCollidableCollisionSurface.cpp @@ -1,17 +1,11 @@ #include "CCollidableCollisionSurface.hpp" -namespace urde -{ -const CCollisionPrimitive::Type CCollidableCollisionSurface::sType(CCollidableCollisionSurface::SetStaticTableIndex, "CCollidableCollisionSurface"); +namespace urde { +const CCollisionPrimitive::Type CCollidableCollisionSurface::sType(CCollidableCollisionSurface::SetStaticTableIndex, + "CCollidableCollisionSurface"); u32 CCollidableCollisionSurface::sTableIndex = -1; -const CCollisionPrimitive::Type& CCollidableCollisionSurface::GetType() -{ - return sType; -} +const CCollisionPrimitive::Type& CCollidableCollisionSurface::GetType() { return sType; } -void CCollidableCollisionSurface::SetStaticTableIndex(u32 index) -{ - sTableIndex = index; -} -} +void CCollidableCollisionSurface::SetStaticTableIndex(u32 index) { sTableIndex = index; } +} // namespace urde diff --git a/Runtime/Collision/CCollidableCollisionSurface.hpp b/Runtime/Collision/CCollidableCollisionSurface.hpp index 8173011e7..b2314b368 100644 --- a/Runtime/Collision/CCollidableCollisionSurface.hpp +++ b/Runtime/Collision/CCollidableCollisionSurface.hpp @@ -2,14 +2,13 @@ #include "CCollisionPrimitive.hpp" -namespace urde -{ -class CCollidableCollisionSurface -{ - static const CCollisionPrimitive::Type sType; - static u32 sTableIndex; +namespace urde { +class CCollidableCollisionSurface { + static const CCollisionPrimitive::Type sType; + static u32 sTableIndex; + public: - static const CCollisionPrimitive::Type& GetType(); - static void SetStaticTableIndex(u32 index); + static const CCollisionPrimitive::Type& GetType(); + static void SetStaticTableIndex(u32 index); }; -} +} // namespace urde diff --git a/Runtime/Collision/CCollidableOBBTree.cpp b/Runtime/Collision/CCollidableOBBTree.cpp index 07d03d30d..ca9dc0a1e 100644 --- a/Runtime/Collision/CCollidableOBBTree.cpp +++ b/Runtime/Collision/CCollidableOBBTree.cpp @@ -4,720 +4,572 @@ #include "CInternalRayCastStructure.hpp" #include "CCollisionInfoList.hpp" -namespace urde -{ +namespace urde { u32 CCollidableOBBTree::sTableIndex = 0; CCollidableOBBTree::CCollidableOBBTree(const COBBTree* tree, const urde::CMaterialList& material) - : CCollisionPrimitive(material), - x10_tree((COBBTree*)tree) {} +: CCollisionPrimitive(material), x10_tree((COBBTree*)tree) {} -bool CCollidableOBBTree::LineIntersectsLeaf(const COBBTree::CLeafData& leaf, CRayCastInfo& info) const -{ - bool ret = false; - u16 intersectIdx = 0; - for (int i=0 ; iGetSurface(surfIdx); - if (info.GetMaterialFilter().Passes(GetMaterial())) - { - if (CollisionUtil::RayTriangleIntersection(info.GetRay().start, info.GetRay().dir, - surface.GetVerts(), info.Magnitude())) - { - intersectIdx = surfIdx; - ret = true; - } - } +bool CCollidableOBBTree::LineIntersectsLeaf(const COBBTree::CLeafData& leaf, CRayCastInfo& info) const { + bool ret = false; + u16 intersectIdx = 0; + for (int i = 0; i < leaf.GetSurfaceVector().size(); ++i) { + u16 surfIdx = leaf.GetSurfaceVector()[i]; + CCollisionSurface surface = x10_tree->GetSurface(surfIdx); + if (info.GetMaterialFilter().Passes(GetMaterial())) { + if (CollisionUtil::RayTriangleIntersection(info.GetRay().start, info.GetRay().dir, surface.GetVerts(), + info.Magnitude())) { + intersectIdx = surfIdx; + ret = true; + } } + } - if (ret) - { - CCollisionSurface surf = x10_tree->GetSurface(intersectIdx); - info.Plane() = surf.GetPlane(); - info.Material() = CMaterialList(surf.GetSurfaceFlags()); - } + if (ret) { + CCollisionSurface surf = x10_tree->GetSurface(intersectIdx); + info.Plane() = surf.GetPlane(); + info.Material() = CMaterialList(surf.GetSurfaceFlags()); + } - return ret; + return ret; } bool CCollidableOBBTree::LineIntersectsOBBTree(const COBBTree::CNode& n0, const COBBTree::CNode& n1, - CRayCastInfo& info) const -{ - bool ret = false; - float t0, t1; - bool intersects0 = false; - bool intersects1 = false; - if (CollisionUtil::LineIntersectsOBBox(n0.GetOBB(), info.GetRay(), t0) && t0 < info.GetMagnitude()) - intersects0 = true; - if (CollisionUtil::LineIntersectsOBBox(n1.GetOBB(), info.GetRay(), t1) && t1 < info.GetMagnitude()) - intersects1 = true; + CRayCastInfo& info) const { + bool ret = false; + float t0, t1; + bool intersects0 = false; + bool intersects1 = false; + if (CollisionUtil::LineIntersectsOBBox(n0.GetOBB(), info.GetRay(), t0) && t0 < info.GetMagnitude()) + intersects0 = true; + if (CollisionUtil::LineIntersectsOBBox(n1.GetOBB(), info.GetRay(), t1) && t1 < info.GetMagnitude()) + intersects1 = true; - if (intersects0 && intersects1) - { - if (t0 < t1) - { - if (n0.IsLeaf() ? - LineIntersectsLeaf(n0.GetLeafData(), info) : - LineIntersectsOBBTree(n0.GetLeft(), n0.GetRight(), info)) - { - if (info.GetMagnitude() < t1) - return true; - ret = true; - } - if (n1.IsLeaf()) - { - if (LineIntersectsLeaf(n1.GetLeafData(), info)) - return true; - } - else - { - if (LineIntersectsOBBTree(n1.GetLeft(), n1.GetRight(), info)) - return true; - } - } - else - { - if (n1.IsLeaf() ? - LineIntersectsLeaf(n1.GetLeafData(), info) : - LineIntersectsOBBTree(n1.GetLeft(), n1.GetRight(), info)) - { - if (info.GetMagnitude() < t0) - return true; - ret = true; - } - if (n0.IsLeaf()) - { - if (LineIntersectsLeaf(n0.GetLeafData(), info)) - return true; - } - else - { - if (LineIntersectsOBBTree(n0.GetLeft(), n0.GetRight(), info)) - return true; - } - } - } - else if (intersects0) - { - return n0.IsLeaf() ? - LineIntersectsLeaf(n0.GetLeafData(), info) : - LineIntersectsOBBTree(n0.GetLeft(), n0.GetRight(), info); - } - else if (intersects1) - { - return n1.IsLeaf() ? - LineIntersectsLeaf(n1.GetLeafData(), info) : - LineIntersectsOBBTree(n1.GetLeft(), n1.GetRight(), info); + if (intersects0 && intersects1) { + if (t0 < t1) { + if (n0.IsLeaf() ? LineIntersectsLeaf(n0.GetLeafData(), info) + : LineIntersectsOBBTree(n0.GetLeft(), n0.GetRight(), info)) { + if (info.GetMagnitude() < t1) + return true; + ret = true; + } + if (n1.IsLeaf()) { + if (LineIntersectsLeaf(n1.GetLeafData(), info)) + return true; + } else { + if (LineIntersectsOBBTree(n1.GetLeft(), n1.GetRight(), info)) + return true; + } + } else { + if (n1.IsLeaf() ? LineIntersectsLeaf(n1.GetLeafData(), info) + : LineIntersectsOBBTree(n1.GetLeft(), n1.GetRight(), info)) { + if (info.GetMagnitude() < t0) + return true; + ret = true; + } + if (n0.IsLeaf()) { + if (LineIntersectsLeaf(n0.GetLeafData(), info)) + return true; + } else { + if (LineIntersectsOBBTree(n0.GetLeft(), n0.GetRight(), info)) + return true; + } } + } else if (intersects0) { + return n0.IsLeaf() ? LineIntersectsLeaf(n0.GetLeafData(), info) + : LineIntersectsOBBTree(n0.GetLeft(), n0.GetRight(), info); + } else if (intersects1) { + return n1.IsLeaf() ? LineIntersectsLeaf(n1.GetLeafData(), info) + : LineIntersectsOBBTree(n1.GetLeft(), n1.GetRight(), info); + } - return ret; + return ret; } -bool CCollidableOBBTree::LineIntersectsOBBTree(const COBBTree::CNode& node, CRayCastInfo& info) const -{ - float t; - bool ret = false; +bool CCollidableOBBTree::LineIntersectsOBBTree(const COBBTree::CNode& node, CRayCastInfo& info) const { + float t; + bool ret = false; - if (CollisionUtil::LineIntersectsOBBox(node.GetOBB(), info.GetRay(), t) && t < info.GetMagnitude()) - { - if (node.IsLeaf()) - { - if (LineIntersectsLeaf(node.GetLeafData(), info)) - ret = true; - } - else - { - if (LineIntersectsOBBTree(node.GetLeft(), node.GetRight(), info)) - ret = true; - } - const_cast(node).SetHit(true); - } - else - { - const_cast(*this).x18_misses += 1; + if (CollisionUtil::LineIntersectsOBBox(node.GetOBB(), info.GetRay(), t) && t < info.GetMagnitude()) { + if (node.IsLeaf()) { + if (LineIntersectsLeaf(node.GetLeafData(), info)) + ret = true; + } else { + if (LineIntersectsOBBTree(node.GetLeft(), node.GetRight(), info)) + ret = true; } + const_cast(node).SetHit(true); + } else { + const_cast(*this).x18_misses += 1; + } - return ret; + return ret; } CRayCastResult CCollidableOBBTree::LineIntersectsTree(const zeus::CMRay& ray, const CMaterialFilter& filter, - float maxTime, const zeus::CTransform& xf) const -{ - zeus::CMRay useRay = ray.getInvUnscaledTransformRay(xf); - CRayCastInfo info(useRay, filter, maxTime); - if (LineIntersectsOBBTree(x10_tree->GetRoot(), info)) - { - zeus::CPlane xfPlane = TransformPlane(info.GetPlane(), xf); - return CRayCastResult(info.GetMagnitude(), ray.start + info.GetMagnitude() * ray.dir, - xfPlane, info.GetMaterial()); - } - else - { - return {}; - } + float maxTime, const zeus::CTransform& xf) const { + zeus::CMRay useRay = ray.getInvUnscaledTransformRay(xf); + CRayCastInfo info(useRay, filter, maxTime); + if (LineIntersectsOBBTree(x10_tree->GetRoot(), info)) { + zeus::CPlane xfPlane = TransformPlane(info.GetPlane(), xf); + return CRayCastResult(info.GetMagnitude(), ray.start + info.GetMagnitude() * ray.dir, xfPlane, info.GetMaterial()); + } else { + return {}; + } } -zeus::CPlane CCollidableOBBTree::TransformPlane(const zeus::CPlane& pl, const zeus::CTransform& xf) -{ - zeus::CVector3f normal = xf.rotate(pl.normal()); - return zeus::CPlane(normal, (xf * (pl.normal() * pl.d())).dot(normal)); +zeus::CPlane CCollidableOBBTree::TransformPlane(const zeus::CPlane& pl, const zeus::CTransform& xf) { + zeus::CVector3f normal = xf.rotate(pl.normal()); + return zeus::CPlane(normal, (xf * (pl.normal() * pl.d())).dot(normal)); } bool CCollidableOBBTree::SphereCollideWithLeafMoving(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CSphere& sphere, const CMaterialList& matList, const CMaterialFilter& filter, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& infoOut) const -{ - bool ret = false; + double& dOut, CCollisionInfo& infoOut) const { + bool ret = false; - zeus::CAABox aabb(sphere.position - sphere.radius, - sphere.position + sphere.radius); - zeus::CAABox moveAABB = aabb; - zeus::CVector3f moveVec = float(dOut) * dir; - moveAABB.accumulateBounds(aabb.max + moveVec); - moveAABB.accumulateBounds(aabb.min + moveVec); + zeus::CAABox aabb(sphere.position - sphere.radius, sphere.position + sphere.radius); + zeus::CAABox moveAABB = aabb; + zeus::CVector3f moveVec = float(dOut) * dir; + moveAABB.accumulateBounds(aabb.max + moveVec); + moveAABB.accumulateBounds(aabb.min + moveVec); - zeus::CVector3f center = moveAABB.center(); - zeus::CVector3f extent = moveAABB.extents(); + zeus::CVector3f center = moveAABB.center(); + zeus::CVector3f extent = moveAABB.extents(); - for (u16 triIdx : leaf.GetSurfaceVector()) - { - CCollisionSurface surf = x10_tree->GetTransformedSurface(triIdx, xf); - CMaterialList triMat = GetMaterial(); - triMat.Add(CMaterialList(surf.GetSurfaceFlags())); - if (filter.Passes(triMat)) - { - if (CollisionUtil::TriBoxOverlap(center, extent, - surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) - { - const_cast(*this).x1c_hits += 1; + for (u16 triIdx : leaf.GetSurfaceVector()) { + CCollisionSurface surf = x10_tree->GetTransformedSurface(triIdx, xf); + CMaterialList triMat = GetMaterial(); + triMat.Add(CMaterialList(surf.GetSurfaceFlags())); + if (filter.Passes(triMat)) { + if (CollisionUtil::TriBoxOverlap(center, extent, surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) { + const_cast(*this).x1c_hits += 1; - zeus::CVector3f surfNormal = surf.GetNormal(); - if ((sphere.position + moveVec - surf.GetVert(0)).dot(surfNormal) <= sphere.radius) - { - float mag = (sphere.radius - (sphere.position - surf.GetVert(0)).dot(surfNormal)) / dir.dot(surfNormal); - zeus::CVector3f intersectPoint = sphere.position + mag * dir; + zeus::CVector3f surfNormal = surf.GetNormal(); + if ((sphere.position + moveVec - surf.GetVert(0)).dot(surfNormal) <= sphere.radius) { + float mag = (sphere.radius - (sphere.position - surf.GetVert(0)).dot(surfNormal)) / dir.dot(surfNormal); + zeus::CVector3f intersectPoint = sphere.position + mag * dir; - bool outsideEdges[] = - {(intersectPoint - surf.GetVert(0)).dot((surf.GetVert(1) - surf.GetVert(0)).cross(surfNormal)) < 0.f, - (intersectPoint - surf.GetVert(1)).dot((surf.GetVert(2) - surf.GetVert(1)).cross(surfNormal)) < 0.f, - (intersectPoint - surf.GetVert(2)).dot((surf.GetVert(0) - surf.GetVert(2)).cross(surfNormal)) < 0.f}; + bool outsideEdges[] = { + (intersectPoint - surf.GetVert(0)).dot((surf.GetVert(1) - surf.GetVert(0)).cross(surfNormal)) < 0.f, + (intersectPoint - surf.GetVert(1)).dot((surf.GetVert(2) - surf.GetVert(1)).cross(surfNormal)) < 0.f, + (intersectPoint - surf.GetVert(2)).dot((surf.GetVert(0) - surf.GetVert(2)).cross(surfNormal)) < 0.f}; - if (mag >= 0.f && !outsideEdges[0] && !outsideEdges[1] && !outsideEdges[2] && mag < dOut) - { - infoOut = CCollisionInfo(intersectPoint - sphere.radius * surfNormal, matList, triMat, surfNormal); - dOut = mag; - ret = true; - } + if (mag >= 0.f && !outsideEdges[0] && !outsideEdges[1] && !outsideEdges[2] && mag < dOut) { + infoOut = CCollisionInfo(intersectPoint - sphere.radius * surfNormal, matList, triMat, surfNormal); + dOut = mag; + ret = true; + } - bool intersects = (sphere.position - surf.GetVert(0)).dot(surfNormal) <= sphere.radius; - bool testVert[] = {true, true, true}; - const u16* edgeIndices = x10_tree->GetTriangleEdgeIndices(triIdx); - for (int k=0 ; k<3 ; ++k) - { - if (intersects || outsideEdges[k]) - { - u16 edgeIdx = edgeIndices[k]; - if (CMetroidAreaCollider::g_DupPrimitiveCheckCount != CMetroidAreaCollider::g_DupEdgeList[edgeIdx]) - { - CMetroidAreaCollider::g_DupEdgeList[edgeIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMaterialList edgeMat(x10_tree->GetEdgeMaterial(edgeIdx)); - if (!edgeMat.HasMaterial(EMaterialTypes::NoEdgeCollision)) - { - int nextIdx = (k + 1) % 3; - zeus::CVector3f edgeVec = surf.GetVert(nextIdx) - surf.GetVert(k); - float edgeVecMag = edgeVec.magnitude(); - edgeVec *= zeus::CVector3f(1.f / edgeVecMag); - float dirDotEdge = dir.dot(edgeVec); - zeus::CVector3f edgeRej = dir - dirDotEdge * edgeVec; - float edgeRejMagSq = edgeRej.magSquared(); - zeus::CVector3f vertToSphere = sphere.position - surf.GetVert(k); - float vtsDotEdge = vertToSphere.dot(edgeVec); - zeus::CVector3f vtsRej = vertToSphere - vtsDotEdge * edgeVec; - if (edgeRejMagSq > 0.f) - { - float tmp = 2.f * vtsRej.dot(edgeRej); - float tmp2 = 4.f * edgeRejMagSq * - (vtsRej.magSquared() - sphere.radius * sphere.radius) - tmp * tmp; - if (tmp2 >= 0.f) - { - float mag = 0.5f / edgeRejMagSq * (-tmp - std::sqrt(tmp2)); - if (mag >= 0.f) - { - float t = mag * dirDotEdge + vtsDotEdge; - if (t >= 0.f && t <= edgeVecMag && mag < dOut) - { - zeus::CVector3f point = surf.GetVert(k) + t * edgeVec; - infoOut = CCollisionInfo(point, matList, edgeMat, - (sphere.position + mag * dir - point).normalized()); - dOut = mag; - ret = true; - testVert[k] = false; - testVert[nextIdx] = false; - } - else if (t < -sphere.radius && dirDotEdge <= 0.f) - { - testVert[k] = false; - } - else if (t > edgeVecMag + sphere.radius && dirDotEdge >= 0.0) - { - testVert[nextIdx] = false; - } - } - } - else - { - testVert[k] = false; - testVert[nextIdx] = false; - } - } - } - } - } - } - - u16 vertIndices[3]; - x10_tree->GetTriangleVertexIndices(triIdx, vertIndices); - - for (int k=0 ; k<3 ; ++k) - { - u16 vertIdx = vertIndices[k]; - if (testVert[k]) - { - if (CMetroidAreaCollider::g_DupPrimitiveCheckCount != CMetroidAreaCollider::g_DupVertexList[vertIdx]) - { - CMetroidAreaCollider::g_DupVertexList[vertIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - double d = dOut; - if (CollisionUtil::RaySphereIntersection_Double(zeus::CSphere(surf.GetVert(k), sphere.radius), - sphere.position, dir, d) && d >= 0.0) - { - infoOut = CCollisionInfo(surf.GetVert(k), matList, x10_tree->GetVertMaterial(vertIdx), - (sphere.position + dir * d - surf.GetVert(k)).normalized()); - dOut = d; - ret = true; - } - } - } - else - { - CMetroidAreaCollider::g_DupVertexList[vertIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + bool intersects = (sphere.position - surf.GetVert(0)).dot(surfNormal) <= sphere.radius; + bool testVert[] = {true, true, true}; + const u16* edgeIndices = x10_tree->GetTriangleEdgeIndices(triIdx); + for (int k = 0; k < 3; ++k) { + if (intersects || outsideEdges[k]) { + u16 edgeIdx = edgeIndices[k]; + if (CMetroidAreaCollider::g_DupPrimitiveCheckCount != CMetroidAreaCollider::g_DupEdgeList[edgeIdx]) { + CMetroidAreaCollider::g_DupEdgeList[edgeIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMaterialList edgeMat(x10_tree->GetEdgeMaterial(edgeIdx)); + if (!edgeMat.HasMaterial(EMaterialTypes::NoEdgeCollision)) { + int nextIdx = (k + 1) % 3; + zeus::CVector3f edgeVec = surf.GetVert(nextIdx) - surf.GetVert(k); + float edgeVecMag = edgeVec.magnitude(); + edgeVec *= zeus::CVector3f(1.f / edgeVecMag); + float dirDotEdge = dir.dot(edgeVec); + zeus::CVector3f edgeRej = dir - dirDotEdge * edgeVec; + float edgeRejMagSq = edgeRej.magSquared(); + zeus::CVector3f vertToSphere = sphere.position - surf.GetVert(k); + float vtsDotEdge = vertToSphere.dot(edgeVec); + zeus::CVector3f vtsRej = vertToSphere - vtsDotEdge * edgeVec; + if (edgeRejMagSq > 0.f) { + float tmp = 2.f * vtsRej.dot(edgeRej); + float tmp2 = 4.f * edgeRejMagSq * (vtsRej.magSquared() - sphere.radius * sphere.radius) - tmp * tmp; + if (tmp2 >= 0.f) { + float mag = 0.5f / edgeRejMagSq * (-tmp - std::sqrt(tmp2)); + if (mag >= 0.f) { + float t = mag * dirDotEdge + vtsDotEdge; + if (t >= 0.f && t <= edgeVecMag && mag < dOut) { + zeus::CVector3f point = surf.GetVert(k) + t * edgeVec; + infoOut = CCollisionInfo(point, matList, edgeMat, + (sphere.position + mag * dir - point).normalized()); + dOut = mag; + ret = true; + testVert[k] = false; + testVert[nextIdx] = false; + } else if (t < -sphere.radius && dirDotEdge <= 0.f) { + testVert[k] = false; + } else if (t > edgeVecMag + sphere.radius && dirDotEdge >= 0.0) { + testVert[nextIdx] = false; } + } + } else { + testVert[k] = false; + testVert[nextIdx] = false; } + } } + } } - else - { - const u16* edgeIndices = x10_tree->GetTriangleEdgeIndices(triIdx); - CMetroidAreaCollider::g_DupEdgeList[edgeIndices[0]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMetroidAreaCollider::g_DupEdgeList[edgeIndices[1]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMetroidAreaCollider::g_DupEdgeList[edgeIndices[2]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + } - u16 vertIndices[3]; - x10_tree->GetTriangleVertexIndices(triIdx, vertIndices); - CMetroidAreaCollider::g_DupVertexList[vertIndices[0]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMetroidAreaCollider::g_DupVertexList[vertIndices[1]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMetroidAreaCollider::g_DupVertexList[vertIndices[2]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + u16 vertIndices[3]; + x10_tree->GetTriangleVertexIndices(triIdx, vertIndices); + + for (int k = 0; k < 3; ++k) { + u16 vertIdx = vertIndices[k]; + if (testVert[k]) { + if (CMetroidAreaCollider::g_DupPrimitiveCheckCount != CMetroidAreaCollider::g_DupVertexList[vertIdx]) { + CMetroidAreaCollider::g_DupVertexList[vertIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + double d = dOut; + if (CollisionUtil::RaySphereIntersection_Double(zeus::CSphere(surf.GetVert(k), sphere.radius), + sphere.position, dir, d) && + d >= 0.0) { + infoOut = CCollisionInfo(surf.GetVert(k), matList, x10_tree->GetVertMaterial(vertIdx), + (sphere.position + dir * d - surf.GetVert(k)).normalized()); + dOut = d; + ret = true; + } + } + } else { + CMetroidAreaCollider::g_DupVertexList[vertIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; } + } } - } + } else { + const u16* edgeIndices = x10_tree->GetTriangleEdgeIndices(triIdx); + CMetroidAreaCollider::g_DupEdgeList[edgeIndices[0]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMetroidAreaCollider::g_DupEdgeList[edgeIndices[1]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMetroidAreaCollider::g_DupEdgeList[edgeIndices[2]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - return ret; + u16 vertIndices[3]; + x10_tree->GetTriangleVertexIndices(triIdx, vertIndices); + CMetroidAreaCollider::g_DupVertexList[vertIndices[0]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMetroidAreaCollider::g_DupVertexList[vertIndices[1]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMetroidAreaCollider::g_DupVertexList[vertIndices[2]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + } + } + } + + return ret; } bool CCollidableOBBTree::SphereCollisionMoving(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CSphere& sphere, const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, - const zeus::CVector3f& dir, double& dOut, CCollisionInfo& info) const -{ - bool ret = false; + const zeus::CVector3f& dir, double& dOut, CCollisionInfo& info) const { + bool ret = false; - const_cast(*this).x14_tries += 1; - if (obb.OBBIntersectsBox(node.GetOBB())) - { - const_cast(node).SetHit(true); - if (node.IsLeaf()) - { - if (SphereCollideWithLeafMoving(node.GetLeafData(), xf, sphere, material, filter, dir, dOut, info)) - ret = true; - } - else - { - if (SphereCollisionMoving(node.GetLeft(), xf, sphere, obb, material, filter, dir, dOut, info)) - ret = true; - if (SphereCollisionMoving(node.GetRight(), xf, sphere, obb, material, filter, dir, dOut, info)) - ret = true; - } - } - else - { - const_cast(*this).x18_misses += 1; + const_cast(*this).x14_tries += 1; + if (obb.OBBIntersectsBox(node.GetOBB())) { + const_cast(node).SetHit(true); + if (node.IsLeaf()) { + if (SphereCollideWithLeafMoving(node.GetLeafData(), xf, sphere, material, filter, dir, dOut, info)) + ret = true; + } else { + if (SphereCollisionMoving(node.GetLeft(), xf, sphere, obb, material, filter, dir, dOut, info)) + ret = true; + if (SphereCollisionMoving(node.GetRight(), xf, sphere, obb, material, filter, dir, dOut, info)) + ret = true; } + } else { + const_cast(*this).x18_misses += 1; + } - return ret; + return ret; } bool CCollidableOBBTree::AABoxCollideWithLeafMoving(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CAABox& aabb, const CMaterialList& matList, - const CMaterialFilter& filter, const CMovingAABoxComponents& components, - const zeus::CVector3f& dir, double& dOut, CCollisionInfo& infoOut) const -{ - bool ret = false; + const CMaterialFilter& filter, + const CMovingAABoxComponents& components, + const zeus::CVector3f& dir, double& dOut, + CCollisionInfo& infoOut) const { + bool ret = false; - zeus::CAABox movedAABB = components.x6e8_aabb; - zeus::CVector3f moveVec = float(dOut) * dir; - movedAABB.accumulateBounds(aabb.min + moveVec); - movedAABB.accumulateBounds(aabb.max + moveVec); + zeus::CAABox movedAABB = components.x6e8_aabb; + zeus::CVector3f moveVec = float(dOut) * dir; + movedAABB.accumulateBounds(aabb.min + moveVec); + movedAABB.accumulateBounds(aabb.max + moveVec); - zeus::CVector3f center = movedAABB.center(); - zeus::CVector3f extent = movedAABB.extents(); + zeus::CVector3f center = movedAABB.center(); + zeus::CVector3f extent = movedAABB.extents(); - zeus::CVector3f normal, point; + zeus::CVector3f normal, point; - for (u16 triIdx : leaf.GetSurfaceVector()) - { - CCollisionSurface surf = x10_tree->GetTransformedSurface(triIdx, xf); - CMaterialList triMat = GetMaterial(); - triMat.Add(CMaterialList(surf.GetSurfaceFlags())); - if (filter.Passes(triMat)) - { - if (CollisionUtil::TriBoxOverlap(center, extent, - surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) - { - const_cast(*this).x1c_hits += 1; + for (u16 triIdx : leaf.GetSurfaceVector()) { + CCollisionSurface surf = x10_tree->GetTransformedSurface(triIdx, xf); + CMaterialList triMat = GetMaterial(); + triMat.Add(CMaterialList(surf.GetSurfaceFlags())); + if (filter.Passes(triMat)) { + if (CollisionUtil::TriBoxOverlap(center, extent, surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) { + const_cast(*this).x1c_hits += 1; - u16 vertIndices[3]; - x10_tree->GetTriangleVertexIndices(triIdx, vertIndices); + u16 vertIndices[3]; + x10_tree->GetTriangleVertexIndices(triIdx, vertIndices); - double d = dOut; - if (CMetroidAreaCollider::MovingAABoxCollisionCheck_BoxVertexTri(surf, aabb, components.x6c4_vertIdxs, - dir, d, normal, point) && d < dOut) - { - ret = true; - infoOut = CCollisionInfo(point, matList, triMat, normal); - dOut = d; - } - - for (int k=0 ; k<3 ; ++k) - { - u16 vertIdx = vertIndices[k]; - const zeus::CVector3f& vtx = x10_tree->GetVert(vertIdx); - if (CMetroidAreaCollider::g_DupPrimitiveCheckCount != CMetroidAreaCollider::g_DupVertexList[vertIdx]) - { - CMetroidAreaCollider::g_DupVertexList[vertIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - if (movedAABB.pointInside(vtx)) - { - d = dOut; - if (CMetroidAreaCollider::MovingAABoxCollisionCheck_TriVertexBox(vtx, aabb, dir, d, - normal, point) && d < dOut) - { - CMaterialList vertMat(x10_tree->GetVertMaterial(vertIdx)); - ret = true; - infoOut = CCollisionInfo(point, matList, vertMat, normal); - dOut = d; - } - } - } - } - - const u16* edgeIndices = x10_tree->GetTriangleEdgeIndices(triIdx); - for (int k=0 ; k<3 ; ++k) - { - u16 edgeIdx = edgeIndices[k]; - if (CMetroidAreaCollider::g_DupPrimitiveCheckCount != CMetroidAreaCollider::g_DupEdgeList[edgeIdx]) - { - CMetroidAreaCollider::g_DupEdgeList[edgeIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMaterialList edgeMat(x10_tree->GetEdgeMaterial(edgeIdx)); - if (!edgeMat.HasMaterial(EMaterialTypes::NoEdgeCollision)) - { - d = dOut; - const CCollisionEdge& edge = x10_tree->GetEdge(edgeIdx); - if (CMetroidAreaCollider::MovingAABoxCollisionCheck_Edge(surf.GetVert(k), - surf.GetVert((k + 1) % 3), - components.x0_edges, dir, d, normal, point) && - d < dOut) - { - ret = true; - infoOut = CCollisionInfo(point, matList, edgeMat, normal); - dOut = d; - } - } - } - } - } - else - { - const u16* edgeIndices = x10_tree->GetTriangleEdgeIndices(triIdx); - CMetroidAreaCollider::g_DupEdgeList[edgeIndices[0]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMetroidAreaCollider::g_DupEdgeList[edgeIndices[1]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMetroidAreaCollider::g_DupEdgeList[edgeIndices[2]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - - u16 vertIndices[3]; - x10_tree->GetTriangleVertexIndices(triIdx, vertIndices); - CMetroidAreaCollider::g_DupVertexList[vertIndices[0]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMetroidAreaCollider::g_DupVertexList[vertIndices[1]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - CMetroidAreaCollider::g_DupVertexList[vertIndices[2]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; - } + double d = dOut; + if (CMetroidAreaCollider::MovingAABoxCollisionCheck_BoxVertexTri(surf, aabb, components.x6c4_vertIdxs, dir, d, + normal, point) && + d < dOut) { + ret = true; + infoOut = CCollisionInfo(point, matList, triMat, normal); + dOut = d; } - } - return ret; + for (int k = 0; k < 3; ++k) { + u16 vertIdx = vertIndices[k]; + const zeus::CVector3f& vtx = x10_tree->GetVert(vertIdx); + if (CMetroidAreaCollider::g_DupPrimitiveCheckCount != CMetroidAreaCollider::g_DupVertexList[vertIdx]) { + CMetroidAreaCollider::g_DupVertexList[vertIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + if (movedAABB.pointInside(vtx)) { + d = dOut; + if (CMetroidAreaCollider::MovingAABoxCollisionCheck_TriVertexBox(vtx, aabb, dir, d, normal, point) && + d < dOut) { + CMaterialList vertMat(x10_tree->GetVertMaterial(vertIdx)); + ret = true; + infoOut = CCollisionInfo(point, matList, vertMat, normal); + dOut = d; + } + } + } + } + + const u16* edgeIndices = x10_tree->GetTriangleEdgeIndices(triIdx); + for (int k = 0; k < 3; ++k) { + u16 edgeIdx = edgeIndices[k]; + if (CMetroidAreaCollider::g_DupPrimitiveCheckCount != CMetroidAreaCollider::g_DupEdgeList[edgeIdx]) { + CMetroidAreaCollider::g_DupEdgeList[edgeIdx] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMaterialList edgeMat(x10_tree->GetEdgeMaterial(edgeIdx)); + if (!edgeMat.HasMaterial(EMaterialTypes::NoEdgeCollision)) { + d = dOut; + const CCollisionEdge& edge = x10_tree->GetEdge(edgeIdx); + if (CMetroidAreaCollider::MovingAABoxCollisionCheck_Edge(surf.GetVert(k), surf.GetVert((k + 1) % 3), + components.x0_edges, dir, d, normal, point) && + d < dOut) { + ret = true; + infoOut = CCollisionInfo(point, matList, edgeMat, normal); + dOut = d; + } + } + } + } + } else { + const u16* edgeIndices = x10_tree->GetTriangleEdgeIndices(triIdx); + CMetroidAreaCollider::g_DupEdgeList[edgeIndices[0]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMetroidAreaCollider::g_DupEdgeList[edgeIndices[1]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMetroidAreaCollider::g_DupEdgeList[edgeIndices[2]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + + u16 vertIndices[3]; + x10_tree->GetTriangleVertexIndices(triIdx, vertIndices); + CMetroidAreaCollider::g_DupVertexList[vertIndices[0]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMetroidAreaCollider::g_DupVertexList[vertIndices[1]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + CMetroidAreaCollider::g_DupVertexList[vertIndices[2]] = CMetroidAreaCollider::g_DupPrimitiveCheckCount; + } + } + } + + return ret; } bool CCollidableOBBTree::AABoxCollisionMoving(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CAABox& aabb, const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, const CMovingAABoxComponents& components, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& info) const -{ - bool ret = false; + double& dOut, CCollisionInfo& info) const { + bool ret = false; - const_cast(*this).x14_tries += 1; - if (obb.OBBIntersectsBox(node.GetOBB())) - { - const_cast(node).SetHit(true); - if (node.IsLeaf()) - { - if (AABoxCollideWithLeafMoving(node.GetLeafData(), xf, aabb, material, filter, components, dir, dOut, info)) - ret = true; - } - else - { - if (AABoxCollisionMoving(node.GetLeft(), xf, aabb, obb, material, filter, components, dir, dOut, info)) - ret = true; - if (AABoxCollisionMoving(node.GetRight(), xf, aabb, obb, material, filter, components, dir, dOut, info)) - ret = true; - } - } - else - { - const_cast(*this).x18_misses += 1; + const_cast(*this).x14_tries += 1; + if (obb.OBBIntersectsBox(node.GetOBB())) { + const_cast(node).SetHit(true); + if (node.IsLeaf()) { + if (AABoxCollideWithLeafMoving(node.GetLeafData(), xf, aabb, material, filter, components, dir, dOut, info)) + ret = true; + } else { + if (AABoxCollisionMoving(node.GetLeft(), xf, aabb, obb, material, filter, components, dir, dOut, info)) + ret = true; + if (AABoxCollisionMoving(node.GetRight(), xf, aabb, obb, material, filter, components, dir, dOut, info)) + ret = true; } + } else { + const_cast(*this).x18_misses += 1; + } - return ret; + return ret; } bool CCollidableOBBTree::SphereCollisionBoolean(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CSphere& sphere, const zeus::COBBox& obb, - const CMaterialFilter& filter) const -{ - const_cast(*this).x14_tries += 1; - if (obb.OBBIntersectsBox(node.GetOBB())) - { - const_cast(node).SetHit(true); - if (node.IsLeaf()) - { - for (u16 surfIdx : node.GetLeafData().GetSurfaceVector()) - { - CCollisionSurface surf = x10_tree->GetTransformedSurface(surfIdx, xf); - CMaterialList triMat = GetMaterial(); - triMat.Add(CMaterialList(surf.GetSurfaceFlags())); - if (filter.Passes(triMat) && CollisionUtil::TriSphereOverlap(sphere, - surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) - return true; - } - } - else - { - if (SphereCollisionBoolean(node.GetLeft(), xf, sphere, obb, filter)) - return true; - if (SphereCollisionBoolean(node.GetRight(), xf, sphere, obb, filter)) - return true; - } - } - else - { - const_cast(*this).x18_misses += 1; + const CMaterialFilter& filter) const { + const_cast(*this).x14_tries += 1; + if (obb.OBBIntersectsBox(node.GetOBB())) { + const_cast(node).SetHit(true); + if (node.IsLeaf()) { + for (u16 surfIdx : node.GetLeafData().GetSurfaceVector()) { + CCollisionSurface surf = x10_tree->GetTransformedSurface(surfIdx, xf); + CMaterialList triMat = GetMaterial(); + triMat.Add(CMaterialList(surf.GetSurfaceFlags())); + if (filter.Passes(triMat) && + CollisionUtil::TriSphereOverlap(sphere, surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) + return true; + } + } else { + if (SphereCollisionBoolean(node.GetLeft(), xf, sphere, obb, filter)) + return true; + if (SphereCollisionBoolean(node.GetRight(), xf, sphere, obb, filter)) + return true; } + } else { + const_cast(*this).x18_misses += 1; + } - return false; + return false; } bool CCollidableOBBTree::AABoxCollisionBoolean(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CAABox& aabb, const zeus::COBBox& obb, - const CMaterialFilter& filter) const -{ - zeus::CVector3f center = aabb.center(); - zeus::CVector3f extent = aabb.extents(); + const CMaterialFilter& filter) const { + zeus::CVector3f center = aabb.center(); + zeus::CVector3f extent = aabb.extents(); - const_cast(*this).x14_tries += 1; - if (obb.OBBIntersectsBox(node.GetOBB())) - { - const_cast(node).SetHit(true); - if (node.IsLeaf()) - { - for (u16 surfIdx : node.GetLeafData().GetSurfaceVector()) - { - CCollisionSurface surf = x10_tree->GetTransformedSurface(surfIdx, xf); - CMaterialList triMat = GetMaterial(); - triMat.Add(CMaterialList(surf.GetSurfaceFlags())); - if (filter.Passes(triMat) && CollisionUtil::TriBoxOverlap(center, extent, - surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) - return true; - } - } - else - { - if (AABoxCollisionBoolean(node.GetLeft(), xf, aabb, obb, filter)) - return true; - if (AABoxCollisionBoolean(node.GetRight(), xf, aabb, obb, filter)) - return true; - } - } - else - { - const_cast(*this).x18_misses += 1; + const_cast(*this).x14_tries += 1; + if (obb.OBBIntersectsBox(node.GetOBB())) { + const_cast(node).SetHit(true); + if (node.IsLeaf()) { + for (u16 surfIdx : node.GetLeafData().GetSurfaceVector()) { + CCollisionSurface surf = x10_tree->GetTransformedSurface(surfIdx, xf); + CMaterialList triMat = GetMaterial(); + triMat.Add(CMaterialList(surf.GetSurfaceFlags())); + if (filter.Passes(triMat) && + CollisionUtil::TriBoxOverlap(center, extent, surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) + return true; + } + } else { + if (AABoxCollisionBoolean(node.GetLeft(), xf, aabb, obb, filter)) + return true; + if (AABoxCollisionBoolean(node.GetRight(), xf, aabb, obb, filter)) + return true; } + } else { + const_cast(*this).x18_misses += 1; + } - return false; + return false; } bool CCollidableOBBTree::SphereCollideWithLeaf(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CSphere& sphere, const CMaterialList& material, - const CMaterialFilter& filter, CCollisionInfoList& infoList) const -{ - bool ret = false; - zeus::CVector3f point, normal; + const CMaterialFilter& filter, CCollisionInfoList& infoList) const { + bool ret = false; + zeus::CVector3f point, normal; - for (u16 surfIdx : leaf.GetSurfaceVector()) - { - CCollisionSurface surf = x10_tree->GetTransformedSurface(surfIdx, xf); - CMaterialList triMat = GetMaterial(); - triMat.Add(CMaterialList(surf.GetSurfaceFlags())); - if (filter.Passes(triMat)) - { - const_cast(*this).x1c_hits += 1; - if (CollisionUtil::TriSphereIntersection(sphere, - surf.GetVert(0), surf.GetVert(1), surf.GetVert(2), - point, normal)) - { - CCollisionInfo collision(point, material, triMat, normal); - infoList.Add(collision, false); - ret = true; - } - } + for (u16 surfIdx : leaf.GetSurfaceVector()) { + CCollisionSurface surf = x10_tree->GetTransformedSurface(surfIdx, xf); + CMaterialList triMat = GetMaterial(); + triMat.Add(CMaterialList(surf.GetSurfaceFlags())); + if (filter.Passes(triMat)) { + const_cast(*this).x1c_hits += 1; + if (CollisionUtil::TriSphereIntersection(sphere, surf.GetVert(0), surf.GetVert(1), surf.GetVert(2), point, + normal)) { + CCollisionInfo collision(point, material, triMat, normal); + infoList.Add(collision, false); + ret = true; + } } + } - return ret; + return ret; } bool CCollidableOBBTree::SphereCollision(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CSphere& sphere, const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, - CCollisionInfoList& infoList) const -{ - bool ret = false; + CCollisionInfoList& infoList) const { + bool ret = false; - const_cast(*this).x14_tries += 1; - if (obb.OBBIntersectsBox(node.GetOBB())) - { - const_cast(node).SetHit(true); - if (node.IsLeaf()) - { - if (SphereCollideWithLeaf(node.GetLeafData(), xf, sphere, material, filter, infoList)) - ret = true; - } - else - { - if (SphereCollision(node.GetLeft(), xf, sphere, obb, material, filter, infoList)) - ret = true; - if (SphereCollision(node.GetRight(), xf, sphere, obb, material, filter, infoList)) - ret = true; - } - } - else - { - const_cast(*this).x18_misses += 1; + const_cast(*this).x14_tries += 1; + if (obb.OBBIntersectsBox(node.GetOBB())) { + const_cast(node).SetHit(true); + if (node.IsLeaf()) { + if (SphereCollideWithLeaf(node.GetLeafData(), xf, sphere, material, filter, infoList)) + ret = true; + } else { + if (SphereCollision(node.GetLeft(), xf, sphere, obb, material, filter, infoList)) + ret = true; + if (SphereCollision(node.GetRight(), xf, sphere, obb, material, filter, infoList)) + ret = true; } + } else { + const_cast(*this).x18_misses += 1; + } - return ret; + return ret; } bool CCollidableOBBTree::AABoxCollideWithLeaf(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CAABox& aabb, const CMaterialList& material, const CMaterialFilter& filter, const zeus::CPlane* planes, - CCollisionInfoList& infoList) const -{ - bool ret = false; - zeus::CVector3f center = aabb.center(); - zeus::CVector3f extent = aabb.extents(); + CCollisionInfoList& infoList) const { + bool ret = false; + zeus::CVector3f center = aabb.center(); + zeus::CVector3f extent = aabb.extents(); - for (u16 surfIdx : leaf.GetSurfaceVector()) - { - CCollisionSurface surf = x10_tree->GetTransformedSurface(surfIdx, xf); - CMaterialList triMat = GetMaterial(); - triMat.Add(CMaterialList(surf.GetSurfaceFlags())); - if (filter.Passes(triMat) && CollisionUtil::TriBoxOverlap(center, extent, - surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) - { - zeus::CAABox newAABB = zeus::CAABox::skInvertedBox; - const_cast(*this).x1c_hits += 1; - if (CMetroidAreaCollider::ConvexPolyCollision(planes, surf.GetVerts(), newAABB)) - { - zeus::CPlane plane = surf.GetPlane(); - CCollisionInfo collision(newAABB, triMat, material, - plane.normal(), -plane.normal()); - infoList.Add(collision, false); - ret = true; - } - } + for (u16 surfIdx : leaf.GetSurfaceVector()) { + CCollisionSurface surf = x10_tree->GetTransformedSurface(surfIdx, xf); + CMaterialList triMat = GetMaterial(); + triMat.Add(CMaterialList(surf.GetSurfaceFlags())); + if (filter.Passes(triMat) && + CollisionUtil::TriBoxOverlap(center, extent, surf.GetVert(0), surf.GetVert(1), surf.GetVert(2))) { + zeus::CAABox newAABB = zeus::CAABox::skInvertedBox; + const_cast(*this).x1c_hits += 1; + if (CMetroidAreaCollider::ConvexPolyCollision(planes, surf.GetVerts(), newAABB)) { + zeus::CPlane plane = surf.GetPlane(); + CCollisionInfo collision(newAABB, triMat, material, plane.normal(), -plane.normal()); + infoList.Add(collision, false); + ret = true; + } } + } - return ret; + return ret; } bool CCollidableOBBTree::AABoxCollision(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CAABox& aabb, const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, - const zeus::CPlane* planes, CCollisionInfoList& infoList) const -{ - bool ret = false; + const zeus::CPlane* planes, CCollisionInfoList& infoList) const { + bool ret = false; - const_cast(*this).x14_tries += 1; - if (obb.OBBIntersectsBox(node.GetOBB())) - { - const_cast(node).SetHit(true); - if (node.IsLeaf()) - { - if (AABoxCollideWithLeaf(node.GetLeafData(), xf, aabb, material, filter, planes, infoList)) - ret = true; - } - else - { - if (AABoxCollision(node.GetLeft(), xf, aabb, obb, material, filter, planes, infoList)) - ret = true; - if (AABoxCollision(node.GetRight(), xf, aabb, obb, material, filter, planes, infoList)) - ret = true; - } - } - else - { - const_cast(*this).x18_misses += 1; + const_cast(*this).x14_tries += 1; + if (obb.OBBIntersectsBox(node.GetOBB())) { + const_cast(node).SetHit(true); + if (node.IsLeaf()) { + if (AABoxCollideWithLeaf(node.GetLeafData(), xf, aabb, material, filter, planes, infoList)) + ret = true; + } else { + if (AABoxCollision(node.GetLeft(), xf, aabb, obb, material, filter, planes, infoList)) + ret = true; + if (AABoxCollision(node.GetRight(), xf, aabb, obb, material, filter, planes, infoList)) + ret = true; } + } else { + const_cast(*this).x18_misses += 1; + } - return ret; + return ret; } -FourCC CCollidableOBBTree::GetPrimType() const -{ - return SBIG('OBBT'); +FourCC CCollidableOBBTree::GetPrimType() const { return SBIG('OBBT'); } + +CRayCastResult CCollidableOBBTree::CastRayInternal(const CInternalRayCastStructure& rayCast) const { + return LineIntersectsTree(rayCast.GetRay(), rayCast.GetFilter(), rayCast.GetMaxTime(), rayCast.GetTransform()); } -CRayCastResult CCollidableOBBTree::CastRayInternal(const CInternalRayCastStructure& rayCast) const -{ - return LineIntersectsTree(rayCast.GetRay(), rayCast.GetFilter(), - rayCast.GetMaxTime(), rayCast.GetTransform()); +zeus::CAABox CCollidableOBBTree::CalculateAABox(const zeus::CTransform& xf) const { + return zeus::COBBox::FromAABox(x10_tree->CalculateLocalAABox(), xf).calculateAABox(); } -zeus::CAABox CCollidableOBBTree::CalculateAABox(const zeus::CTransform& xf) const -{ - return zeus::COBBox::FromAABox(x10_tree->CalculateLocalAABox(), xf).calculateAABox(); -} +zeus::CAABox CCollidableOBBTree::CalculateLocalAABox() const { return x10_tree->CalculateLocalAABox(); } -zeus::CAABox CCollidableOBBTree::CalculateLocalAABox() const -{ - return x10_tree->CalculateLocalAABox(); -} - -} +} // namespace urde diff --git a/Runtime/Collision/CCollidableOBBTree.hpp b/Runtime/Collision/CCollidableOBBTree.hpp index 32ce093fb..7e8d23a7a 100644 --- a/Runtime/Collision/CCollidableOBBTree.hpp +++ b/Runtime/Collision/CCollidableOBBTree.hpp @@ -5,82 +5,82 @@ #include "zeus/COBBox.hpp" #include "CMetroidAreaCollider.hpp" -namespace urde -{ -class CRayCastInfo -{ - const zeus::CMRay& x0_ray; - const CMaterialFilter& x4_filter; - float x8_mag; - zeus::CPlane xc_plane = {zeus::CVector3f::skUp, 0.f}; - CMaterialList x20_material; +namespace urde { +class CRayCastInfo { + const zeus::CMRay& x0_ray; + const CMaterialFilter& x4_filter; + float x8_mag; + zeus::CPlane xc_plane = {zeus::CVector3f::skUp, 0.f}; + CMaterialList x20_material; + public: - CRayCastInfo(const zeus::CMRay& ray, const CMaterialFilter& filter, float mag) - : x0_ray(ray), x4_filter(filter), x8_mag(mag) {} - const zeus::CMRay& GetRay() const { return x0_ray; } - const CMaterialFilter& GetMaterialFilter() const { return x4_filter; } - float GetMagnitude() const { return x8_mag; } - float& Magnitude() { return x8_mag; } - const zeus::CPlane& GetPlane() const { return xc_plane; } - zeus::CPlane& Plane() { return xc_plane; } - const CMaterialList& GetMaterial() const { return x20_material; } - CMaterialList& Material() { return x20_material; } + CRayCastInfo(const zeus::CMRay& ray, const CMaterialFilter& filter, float mag) + : x0_ray(ray), x4_filter(filter), x8_mag(mag) {} + const zeus::CMRay& GetRay() const { return x0_ray; } + const CMaterialFilter& GetMaterialFilter() const { return x4_filter; } + float GetMagnitude() const { return x8_mag; } + float& Magnitude() { return x8_mag; } + const zeus::CPlane& GetPlane() const { return xc_plane; } + zeus::CPlane& Plane() { return xc_plane; } + const CMaterialList& GetMaterial() const { return x20_material; } + CMaterialList& Material() { return x20_material; } }; -class CCollidableOBBTree : public CCollisionPrimitive -{ - friend class CCollidableOBBTreeGroup; - COBBTree* x10_tree = nullptr; - u32 x14_tries = 0; - u32 x18_misses = 0; - u32 x1c_hits = 0; - static u32 sTableIndex; - bool LineIntersectsLeaf(const COBBTree::CLeafData& leaf, CRayCastInfo& info) const; - bool LineIntersectsOBBTree(const COBBTree::CNode& n0, const COBBTree::CNode& n1, CRayCastInfo& info) const; - bool LineIntersectsOBBTree(const COBBTree::CNode& node, CRayCastInfo& info) const; - CRayCastResult LineIntersectsTree(const zeus::CMRay& ray, const CMaterialFilter& filter, float maxTime, - const zeus::CTransform& xf) const; - static zeus::CPlane TransformPlane(const zeus::CPlane& pl, const zeus::CTransform& xf); - bool SphereCollideWithLeafMoving(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CSphere& sphere, - const CMaterialList& material, const CMaterialFilter& filter, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& info) const; - bool SphereCollisionMoving(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CSphere& sphere, - const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, - const zeus::CVector3f& dir, double& dOut, CCollisionInfo& info) const; - bool AABoxCollideWithLeafMoving(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CAABox& aabb, - const CMaterialList& material, const CMaterialFilter& filter, - const CMovingAABoxComponents& components, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& info) const; - bool AABoxCollisionMoving(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CAABox& aabb, - const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, - const CMovingAABoxComponents& components, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& info) const; - bool SphereCollisionBoolean(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CSphere& sphere, - const zeus::COBBox& obb, const CMaterialFilter& filter) const; - bool AABoxCollisionBoolean(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CAABox& aabb, - const zeus::COBBox& obb, const CMaterialFilter& filter) const; - bool SphereCollideWithLeaf(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CSphere& sphere, - const CMaterialList& material, const CMaterialFilter& filter, CCollisionInfoList& infoList) const; - bool SphereCollision(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CSphere& sphere, - const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, - CCollisionInfoList& infoList) const; - bool AABoxCollideWithLeaf(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CAABox& aabb, - const CMaterialList& material, const CMaterialFilter& filter, const zeus::CPlane* planes, - CCollisionInfoList& infoList) const; - bool AABoxCollision(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CAABox& aabb, - const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, - const zeus::CPlane* planes, CCollisionInfoList& infoList) const; +class CCollidableOBBTree : public CCollisionPrimitive { + friend class CCollidableOBBTreeGroup; + COBBTree* x10_tree = nullptr; + u32 x14_tries = 0; + u32 x18_misses = 0; + u32 x1c_hits = 0; + static u32 sTableIndex; + bool LineIntersectsLeaf(const COBBTree::CLeafData& leaf, CRayCastInfo& info) const; + bool LineIntersectsOBBTree(const COBBTree::CNode& n0, const COBBTree::CNode& n1, CRayCastInfo& info) const; + bool LineIntersectsOBBTree(const COBBTree::CNode& node, CRayCastInfo& info) const; + CRayCastResult LineIntersectsTree(const zeus::CMRay& ray, const CMaterialFilter& filter, float maxTime, + const zeus::CTransform& xf) const; + static zeus::CPlane TransformPlane(const zeus::CPlane& pl, const zeus::CTransform& xf); + bool SphereCollideWithLeafMoving(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, + const zeus::CSphere& sphere, const CMaterialList& material, + const CMaterialFilter& filter, const zeus::CVector3f& dir, double& dOut, + CCollisionInfo& info) const; + bool SphereCollisionMoving(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CSphere& sphere, + const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, + const zeus::CVector3f& dir, double& dOut, CCollisionInfo& info) const; + bool AABoxCollideWithLeafMoving(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CAABox& aabb, + const CMaterialList& material, const CMaterialFilter& filter, + const CMovingAABoxComponents& components, const zeus::CVector3f& dir, double& dOut, + CCollisionInfo& info) const; + bool AABoxCollisionMoving(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CAABox& aabb, + const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, + const CMovingAABoxComponents& components, const zeus::CVector3f& dir, double& dOut, + CCollisionInfo& info) const; + bool SphereCollisionBoolean(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CSphere& sphere, + const zeus::COBBox& obb, const CMaterialFilter& filter) const; + bool AABoxCollisionBoolean(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CAABox& aabb, + const zeus::COBBox& obb, const CMaterialFilter& filter) const; + bool SphereCollideWithLeaf(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CSphere& sphere, + const CMaterialList& material, const CMaterialFilter& filter, + CCollisionInfoList& infoList) const; + bool SphereCollision(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CSphere& sphere, + const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, + CCollisionInfoList& infoList) const; + bool AABoxCollideWithLeaf(const COBBTree::CLeafData& leaf, const zeus::CTransform& xf, const zeus::CAABox& aabb, + const CMaterialList& material, const CMaterialFilter& filter, const zeus::CPlane* planes, + CCollisionInfoList& infoList) const; + bool AABoxCollision(const COBBTree::CNode& node, const zeus::CTransform& xf, const zeus::CAABox& aabb, + const zeus::COBBox& obb, const CMaterialList& material, const CMaterialFilter& filter, + const zeus::CPlane* planes, CCollisionInfoList& infoList) const; + public: - CCollidableOBBTree(const COBBTree* tree, const CMaterialList& material); - virtual ~CCollidableOBBTree() = default; - void ResetTestStats() const; - void ResetTestStatsRecurse(const COBBTree::CNode&) const; - u32 GetTableIndex() const { return sTableIndex; } - zeus::CAABox CalculateAABox(const zeus::CTransform &) const; - zeus::CAABox CalculateLocalAABox() const; - FourCC GetPrimType() const; - CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; + CCollidableOBBTree(const COBBTree* tree, const CMaterialList& material); + virtual ~CCollidableOBBTree() = default; + void ResetTestStats() const; + void ResetTestStatsRecurse(const COBBTree::CNode&) const; + u32 GetTableIndex() const { return sTableIndex; } + zeus::CAABox CalculateAABox(const zeus::CTransform&) const; + zeus::CAABox CalculateLocalAABox() const; + FourCC GetPrimType() const; + CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; }; -} - +} // namespace urde diff --git a/Runtime/Collision/CCollidableOBBTreeGroup.cpp b/Runtime/Collision/CCollidableOBBTreeGroup.cpp index 31eaac6c6..aa5a1dab7 100644 --- a/Runtime/Collision/CCollidableOBBTreeGroup.cpp +++ b/Runtime/Collision/CCollidableOBBTreeGroup.cpp @@ -6,270 +6,216 @@ #include "CollisionUtil.hpp" #include "CToken.hpp" -namespace urde -{ -const CCollisionPrimitive::Type CCollidableOBBTreeGroup::sType(CCollidableOBBTreeGroup::SetStaticTableIndex, "CCollidableOBBTreeGroup"); +namespace urde { +const CCollisionPrimitive::Type CCollidableOBBTreeGroup::sType(CCollidableOBBTreeGroup::SetStaticTableIndex, + "CCollidableOBBTreeGroup"); u32 CCollidableOBBTreeGroup::sTableIndex = -1; -CCollidableOBBTreeGroupContainer::CCollidableOBBTreeGroupContainer(CInputStream& in) -{ - u32 treeCount = in.readUint32Big(); - x0_trees.reserve(treeCount); +CCollidableOBBTreeGroupContainer::CCollidableOBBTreeGroupContainer(CInputStream& in) { + u32 treeCount = in.readUint32Big(); + x0_trees.reserve(treeCount); - for (u32 i = 0 ; i < treeCount ; i++) - { - std::unique_ptr tree(new COBBTree(in)); - x0_trees.push_back(std::move(tree)); - } + for (u32 i = 0; i < treeCount; i++) { + std::unique_ptr tree(new COBBTree(in)); + x0_trees.push_back(std::move(tree)); + } - x10_aabbs.reserve(x0_trees.size()); + x10_aabbs.reserve(x0_trees.size()); - for (const std::unique_ptr& tree : x0_trees) - x10_aabbs.push_back(CCollidableOBBTree(tree.get(), CMaterialList()).CalculateLocalAABox()); + for (const std::unique_ptr& tree : x0_trees) + x10_aabbs.push_back(CCollidableOBBTree(tree.get(), CMaterialList()).CalculateLocalAABox()); } -CCollidableOBBTreeGroupContainer::CCollidableOBBTreeGroupContainer(const zeus::CVector3f &, const zeus::CVector3f &) -{ -} +CCollidableOBBTreeGroupContainer::CCollidableOBBTreeGroupContainer(const zeus::CVector3f&, const zeus::CVector3f&) {} CCollidableOBBTreeGroup::CCollidableOBBTreeGroup(const CCollidableOBBTreeGroupContainer* container, const CMaterialList& matList) -: CCollisionPrimitive(matList) -, x10_container(container) -{ +: CCollisionPrimitive(matList), x10_container(container) {} + +void CCollidableOBBTreeGroup::ResetTestStats() const { /* Remove me? */ } + +u32 CCollidableOBBTreeGroup::GetTableIndex() const { return sTableIndex; } + +zeus::CAABox CCollidableOBBTreeGroup::CalculateAABox(const zeus::CTransform& xf) const { + return x10_container->x20_aabox.getTransformedAABox(xf); } -void CCollidableOBBTreeGroup::ResetTestStats() const -{ - /* Remove me? */ -} +zeus::CAABox CCollidableOBBTreeGroup::CalculateLocalAABox() const { return x10_container->x20_aabox; } -u32 CCollidableOBBTreeGroup::GetTableIndex() const -{ - return sTableIndex; -} +FourCC CCollidableOBBTreeGroup::GetPrimType() const { return SBIG('OBTG'); } -zeus::CAABox CCollidableOBBTreeGroup::CalculateAABox(const zeus::CTransform& xf) const -{ - return x10_container->x20_aabox.getTransformedAABox(xf); -} +CRayCastResult CCollidableOBBTreeGroup::CastRayInternal(const CInternalRayCastStructure& rayCast) const { + CRayCastResult ret; -zeus::CAABox CCollidableOBBTreeGroup::CalculateLocalAABox() const -{ - return x10_container->x20_aabox; -} - -FourCC CCollidableOBBTreeGroup::GetPrimType() const -{ - return SBIG('OBTG'); -} - -CRayCastResult CCollidableOBBTreeGroup::CastRayInternal(const CInternalRayCastStructure& rayCast) const -{ - CRayCastResult ret; - - zeus::CMRay xfRay = rayCast.GetRay().getInvUnscaledTransformRay(rayCast.GetTransform()); - auto aabbIt = x10_container->x10_aabbs.cbegin(); - float mag = rayCast.GetMaxTime(); - for (const std::unique_ptr& tree : x10_container->x0_trees) - { - CCollidableOBBTree obbTree(tree.get(), GetMaterial()); - float tMin = 0.f; - float tMax = 0.f; - if (CollisionUtil::RayAABoxIntersection(xfRay, *aabbIt++, tMin, tMax)) - { - CInternalRayCastStructure localCast(xfRay.start, xfRay.dir, mag, - zeus::CTransform::Identity(), rayCast.GetFilter()); - CRayCastResult localResult = obbTree.CastRayInternal(localCast); - if (localResult.IsValid()) - { - if (ret.IsInvalid() || localResult.GetT() < ret.GetT()) - { - ret = localResult; - mag = localResult.GetT(); - } - } + zeus::CMRay xfRay = rayCast.GetRay().getInvUnscaledTransformRay(rayCast.GetTransform()); + auto aabbIt = x10_container->x10_aabbs.cbegin(); + float mag = rayCast.GetMaxTime(); + for (const std::unique_ptr& tree : x10_container->x0_trees) { + CCollidableOBBTree obbTree(tree.get(), GetMaterial()); + float tMin = 0.f; + float tMax = 0.f; + if (CollisionUtil::RayAABoxIntersection(xfRay, *aabbIt++, tMin, tMax)) { + CInternalRayCastStructure localCast(xfRay.start, xfRay.dir, mag, zeus::CTransform::Identity(), + rayCast.GetFilter()); + CRayCastResult localResult = obbTree.CastRayInternal(localCast); + if (localResult.IsValid()) { + if (ret.IsInvalid() || localResult.GetT() < ret.GetT()) { + ret = localResult; + mag = localResult.GetT(); } + } } + } - ret.Transform(rayCast.GetTransform()); - return ret; + ret.Transform(rayCast.GetTransform()); + return ret; } -const CCollisionPrimitive::Type& CCollidableOBBTreeGroup::GetType() -{ - return sType; +const CCollisionPrimitive::Type& CCollidableOBBTreeGroup::GetType() { return sType; } + +void CCollidableOBBTreeGroup::SetStaticTableIndex(u32 index) { sTableIndex = index; } + +bool CCollidableOBBTreeGroup::SphereCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list) { + bool ret = false; + const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); + + zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::COBBox obb1 = zeus::COBBox::FromAABox(p0.CalculateLocalAABox(), collision.GetRight().GetTransform().inverse() * + collision.GetLeft().GetTransform()); + + for (const std::unique_ptr& tree : p1.x10_container->x0_trees) { + CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); + if (obbTree.SphereCollision(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), s0, obb1, + p0.GetMaterial(), collision.GetLeft().GetFilter(), list)) + ret = true; + } + + return ret; } -void CCollidableOBBTreeGroup::SetStaticTableIndex(u32 index) -{ - sTableIndex = index; +bool CCollidableOBBTreeGroup::SphereCollideBoolean(const CInternalCollisionStructure& collision) { + const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); + + zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::COBBox obb1 = zeus::COBBox::FromAABox(p0.CalculateLocalAABox(), collision.GetRight().GetTransform().inverse() * + collision.GetLeft().GetTransform()); + + for (const std::unique_ptr& tree : p1.x10_container->x0_trees) { + CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); + if (obbTree.SphereCollisionBoolean(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), s0, obb1, + collision.GetLeft().GetFilter())) + return true; + } + + return false; } -bool CCollidableOBBTreeGroup::SphereCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list) -{ - bool ret = false; - const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); +bool CCollidableOBBTreeGroup::CollideMovingSphere(const CInternalCollisionStructure& collision, + const zeus::CVector3f& dir, double& mag, CCollisionInfo& info) { + bool ret = false; + const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); - zeus::COBBox obb1 = zeus::COBBox::FromAABox(p0.CalculateLocalAABox(), - collision.GetRight().GetTransform().inverse() * collision.GetLeft().GetTransform()); + zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); - for (const std::unique_ptr& tree : p1.x10_container->x0_trees) - { - CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); - if (obbTree.SphereCollision(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), - s0, obb1, p0.GetMaterial(), collision.GetLeft().GetFilter(), list)) - ret = true; - } + zeus::CAABox movedAABB = p0.CalculateLocalAABox(); + zeus::CVector3f moveVec = float(mag) * dir; + movedAABB.accumulateBounds(movedAABB.min + moveVec); + movedAABB.accumulateBounds(movedAABB.max + moveVec); - return ret; + zeus::COBBox p0Obb = zeus::COBBox::FromAABox(movedAABB, collision.GetRight().GetTransform().inverse() * + collision.GetLeft().GetTransform()); + + for (const std::unique_ptr& tree : p1.x10_container->x0_trees) { + CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); + CMetroidAreaCollider::ResetInternalCounters(); + if (obbTree.SphereCollisionMoving(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), s0, p0Obb, + p0.GetMaterial(), collision.GetLeft().GetFilter(), dir, mag, info)) + ret = true; + } + + return ret; } -bool CCollidableOBBTreeGroup::SphereCollideBoolean(const CInternalCollisionStructure& collision) -{ - const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); +bool CCollidableOBBTreeGroup::AABoxCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list) { + bool ret = false; + const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); - zeus::COBBox obb1 = zeus::COBBox::FromAABox(p0.CalculateLocalAABox(), - collision.GetRight().GetTransform().inverse() * collision.GetLeft().GetTransform()); + zeus::CAABox b0 = p0.CalculateAABox(collision.GetLeft().GetTransform()); + zeus::COBBox p0Obb = zeus::COBBox::FromAABox(p0.CalculateLocalAABox(), collision.GetRight().GetTransform().inverse() * + collision.GetLeft().GetTransform()); - for (const std::unique_ptr& tree : p1.x10_container->x0_trees) - { - CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); - if (obbTree.SphereCollisionBoolean(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), - s0, obb1, collision.GetLeft().GetFilter())) - return true; - } + zeus::CPlane planes[] = {{zeus::CVector3f::skRight, b0.min.dot(zeus::CVector3f::skRight)}, + {zeus::CVector3f::skLeft, b0.max.dot(zeus::CVector3f::skLeft)}, + {zeus::CVector3f::skForward, b0.min.dot(zeus::CVector3f::skForward)}, + {zeus::CVector3f::skBack, b0.max.dot(zeus::CVector3f::skBack)}, + {zeus::CVector3f::skUp, b0.min.dot(zeus::CVector3f::skUp)}, + {zeus::CVector3f::skDown, b0.max.dot(zeus::CVector3f::skDown)}}; - return false; + for (const std::unique_ptr& tree : p1.x10_container->x0_trees) { + CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); + if (obbTree.AABoxCollision(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), b0, p0Obb, + p0.GetMaterial(), collision.GetLeft().GetFilter(), planes, list)) + ret = true; + } + + return ret; } -bool CCollidableOBBTreeGroup::CollideMovingSphere(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir, - double& mag, CCollisionInfo& info) -{ - bool ret = false; - const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); +bool CCollidableOBBTreeGroup::AABoxCollideBoolean(const CInternalCollisionStructure& collision) { + const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::CAABox b0 = p0.CalculateAABox(collision.GetLeft().GetTransform()); + zeus::COBBox p0Obb = zeus::COBBox::FromAABox(p0.CalculateLocalAABox(), collision.GetRight().GetTransform().inverse() * + collision.GetLeft().GetTransform()); - zeus::CAABox movedAABB = p0.CalculateLocalAABox(); - zeus::CVector3f moveVec = float(mag) * dir; - movedAABB.accumulateBounds(movedAABB.min + moveVec); - movedAABB.accumulateBounds(movedAABB.max + moveVec); + for (const std::unique_ptr& tree : p1.x10_container->x0_trees) { + CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); + if (obbTree.AABoxCollisionBoolean(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), b0, p0Obb, + collision.GetLeft().GetFilter())) + return true; + } - zeus::COBBox p0Obb = - zeus::COBBox::FromAABox(movedAABB, - collision.GetRight().GetTransform().inverse() * collision.GetLeft().GetTransform()); - - for (const std::unique_ptr& tree : p1.x10_container->x0_trees) - { - CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); - CMetroidAreaCollider::ResetInternalCounters(); - if (obbTree.SphereCollisionMoving(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), - s0, p0Obb, p0.GetMaterial(), collision.GetLeft().GetFilter(), - dir, mag, info)) - ret = true; - } - - return ret; + return false; } -bool CCollidableOBBTreeGroup::AABoxCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list) -{ - bool ret = false; - const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); +bool CCollidableOBBTreeGroup::CollideMovingAABox(const CInternalCollisionStructure& collision, + const zeus::CVector3f& dir, double& mag, CCollisionInfo& info) { + bool ret = false; + const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CAABox b0 = p0.CalculateAABox(collision.GetLeft().GetTransform()); - zeus::COBBox p0Obb = - zeus::COBBox::FromAABox(p0.CalculateLocalAABox(), - collision.GetRight().GetTransform().inverse() * collision.GetLeft().GetTransform()); + zeus::CAABox b0 = p0.CalculateAABox(collision.GetLeft().GetTransform()); - zeus::CPlane planes[] = - { - {zeus::CVector3f::skRight, b0.min.dot(zeus::CVector3f::skRight)}, - {zeus::CVector3f::skLeft, b0.max.dot(zeus::CVector3f::skLeft)}, - {zeus::CVector3f::skForward, b0.min.dot(zeus::CVector3f::skForward)}, - {zeus::CVector3f::skBack, b0.max.dot(zeus::CVector3f::skBack)}, - {zeus::CVector3f::skUp, b0.min.dot(zeus::CVector3f::skUp)}, - {zeus::CVector3f::skDown, b0.max.dot(zeus::CVector3f::skDown)} - }; + CMovingAABoxComponents components(b0, dir); - for (const std::unique_ptr& tree : p1.x10_container->x0_trees) - { - CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); - if (obbTree.AABoxCollision(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), - b0, p0Obb, p0.GetMaterial(), collision.GetLeft().GetFilter(), - planes, list)) - ret = true; - } + zeus::CAABox movedAABB = p0.CalculateLocalAABox(); + zeus::CVector3f moveVec = float(mag) * dir; + movedAABB.accumulateBounds(movedAABB.min + moveVec); + movedAABB.accumulateBounds(movedAABB.max + moveVec); - return ret; + zeus::COBBox p0Obb = zeus::COBBox::FromAABox(movedAABB, collision.GetRight().GetTransform().inverse() * + collision.GetLeft().GetTransform()); + + for (const std::unique_ptr& tree : p1.x10_container->x0_trees) { + CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); + CMetroidAreaCollider::ResetInternalCounters(); + if (obbTree.AABoxCollisionMoving(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), b0, p0Obb, + p0.GetMaterial(), collision.GetLeft().GetFilter(), components, dir, mag, info)) + ret = true; + } + + return ret; } -bool CCollidableOBBTreeGroup::AABoxCollideBoolean(const CInternalCollisionStructure& collision) -{ - const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); - - zeus::CAABox b0 = p0.CalculateAABox(collision.GetLeft().GetTransform()); - zeus::COBBox p0Obb = - zeus::COBBox::FromAABox(p0.CalculateLocalAABox(), - collision.GetRight().GetTransform().inverse() * collision.GetLeft().GetTransform()); - - for (const std::unique_ptr& tree : p1.x10_container->x0_trees) - { - CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); - if (obbTree.AABoxCollisionBoolean(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), - b0, p0Obb, collision.GetLeft().GetFilter())) - return true; - } - - return false; +CFactoryFnReturn FCollidableOBBTreeGroupFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor( + std::make_unique(in)); } -bool CCollidableOBBTreeGroup::CollideMovingAABox(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir, - double& mag, CCollisionInfo& info) -{ - bool ret = false; - const CCollidableAABox& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableOBBTreeGroup& p1 = static_cast(collision.GetRight().GetPrim()); - - zeus::CAABox b0 = p0.CalculateAABox(collision.GetLeft().GetTransform()); - - CMovingAABoxComponents components(b0, dir); - - zeus::CAABox movedAABB = p0.CalculateLocalAABox(); - zeus::CVector3f moveVec = float(mag) * dir; - movedAABB.accumulateBounds(movedAABB.min + moveVec); - movedAABB.accumulateBounds(movedAABB.max + moveVec); - - zeus::COBBox p0Obb = - zeus::COBBox::FromAABox(movedAABB, - collision.GetRight().GetTransform().inverse() * collision.GetLeft().GetTransform()); - - for (const std::unique_ptr& tree : p1.x10_container->x0_trees) - { - CCollidableOBBTree obbTree(tree.get(), p1.GetMaterial()); - CMetroidAreaCollider::ResetInternalCounters(); - if (obbTree.AABoxCollisionMoving(obbTree.x10_tree->GetRoot(), collision.GetRight().GetTransform(), - b0, p0Obb, p0.GetMaterial(), collision.GetLeft().GetFilter(), - components, dir, mag, info)) - ret = true; - } - - return ret; -} - -CFactoryFnReturn FCollidableOBBTreeGroupFactory(const SObjectTag &tag, CInputStream& in, - const CVParamTransfer& vparms, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); -} - -} +} // namespace urde diff --git a/Runtime/Collision/CCollidableOBBTreeGroup.hpp b/Runtime/Collision/CCollidableOBBTreeGroup.hpp index be2ad4def..1a4db837d 100644 --- a/Runtime/Collision/CCollidableOBBTreeGroup.hpp +++ b/Runtime/Collision/CCollidableOBBTreeGroup.hpp @@ -6,51 +6,47 @@ #include "zeus/CAABox.hpp" #include "CCollisionPrimitive.hpp" -namespace urde -{ -class CCollidableOBBTreeGroupContainer -{ - friend class CCollidableOBBTreeGroup; - std::vector> x0_trees; - std::vector x10_aabbs; - zeus::CAABox x20_aabox; +namespace urde { +class CCollidableOBBTreeGroupContainer { + friend class CCollidableOBBTreeGroup; + std::vector> x0_trees; + std::vector x10_aabbs; + zeus::CAABox x20_aabox; + public: - CCollidableOBBTreeGroupContainer(CInputStream& in); - CCollidableOBBTreeGroupContainer(const zeus::CVector3f&, const zeus::CVector3f&); + CCollidableOBBTreeGroupContainer(CInputStream& in); + CCollidableOBBTreeGroupContainer(const zeus::CVector3f&, const zeus::CVector3f&); }; -class CCollidableOBBTreeGroup : public CCollisionPrimitive -{ - static const Type sType; - static u32 sTableIndex; - const CCollidableOBBTreeGroupContainer* x10_container; +class CCollidableOBBTreeGroup : public CCollisionPrimitive { + static const Type sType; + static u32 sTableIndex; + const CCollidableOBBTreeGroupContainer* x10_container; + public: - CCollidableOBBTreeGroup(CInputStream& in); - CCollidableOBBTreeGroup(const CCollidableOBBTreeGroupContainer*, const CMaterialList&); - virtual ~CCollidableOBBTreeGroup() {} + CCollidableOBBTreeGroup(CInputStream& in); + CCollidableOBBTreeGroup(const CCollidableOBBTreeGroupContainer*, const CMaterialList&); + virtual ~CCollidableOBBTreeGroup() {} - void ResetTestStats() const; - virtual u32 GetTableIndex() const; - virtual zeus::CAABox CalculateAABox(const zeus::CTransform&) const; - virtual zeus::CAABox CalculateLocalAABox() const; - virtual FourCC GetPrimType() const; - virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; + void ResetTestStats() const; + virtual u32 GetTableIndex() const; + virtual zeus::CAABox CalculateAABox(const zeus::CTransform&) const; + virtual zeus::CAABox CalculateLocalAABox() const; + virtual FourCC GetPrimType() const; + virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; - static const Type& GetType(); - static void SetStaticTableIndex(u32 index); - /* Sphere Collide */ - static bool SphereCollide(const CInternalCollisionStructure&, CCollisionInfoList&); - static bool SphereCollideBoolean(const CInternalCollisionStructure&); - static bool CollideMovingSphere(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, - CCollisionInfo&); - /* AABox Collide */ - static bool AABoxCollide(const CInternalCollisionStructure&, CCollisionInfoList&); - static bool AABoxCollideBoolean(const CInternalCollisionStructure&); - static bool CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, - CCollisionInfo&); + static const Type& GetType(); + static void SetStaticTableIndex(u32 index); + /* Sphere Collide */ + static bool SphereCollide(const CInternalCollisionStructure&, CCollisionInfoList&); + static bool SphereCollideBoolean(const CInternalCollisionStructure&); + static bool CollideMovingSphere(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&); + /* AABox Collide */ + static bool AABoxCollide(const CInternalCollisionStructure&, CCollisionInfoList&); + static bool AABoxCollideBoolean(const CInternalCollisionStructure&); + static bool CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&); }; CFactoryFnReturn FCollidableOBBTreeGroupFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/Collision/CCollidableSphere.cpp b/Runtime/Collision/CCollidableSphere.cpp index 470751aa5..a1193c064 100644 --- a/Runtime/Collision/CCollidableSphere.cpp +++ b/Runtime/Collision/CCollidableSphere.cpp @@ -4,313 +4,279 @@ #include "CollisionUtil.hpp" #include "CInternalRayCastStructure.hpp" -namespace urde -{ +namespace urde { const CCollisionPrimitive::Type CCollidableSphere::sType(CCollidableSphere::SetStaticTableIndex, "CCollidableSphere"); u32 CCollidableSphere::sTableIndex = -1; -namespace Collide -{ +namespace Collide { -bool Sphere_AABox(const CInternalCollisionStructure& collision, CCollisionInfoList& list) -{ - const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableAABox& p1 = static_cast(collision.GetRight().GetPrim()); +bool Sphere_AABox(const CInternalCollisionStructure& collision, CCollisionInfoList& list) { + const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableAABox& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); - zeus::CAABox b1 = p1.Transform(collision.GetRight().GetTransform()); + zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::CAABox b1 = p1.Transform(collision.GetRight().GetTransform()); - float distSq = 0.f; - int flags = 0; - for (int i=0 ; i<3 ; ++i) - { - if (s0.position[i] < b1.min[i]) - { - if (s0.position[i] + s0.radius >= b1.min[i]) - { - float dist = s0.position[i] - b1.min[i]; - distSq += dist * dist; - flags |= 1 << (2 * i); - } - else - { - return false; - } - } - else if (s0.position[i] > b1.max[i]) - { - if (s0.position[i] - s0.radius <= b1.max[i]) - { - float dist = s0.position[i] - b1.max[i]; - distSq += dist * dist; - flags |= 1 << (2 * i + 1); - } - else - { - return false; - } - } - } - - if (!flags) - { - zeus::CVector3f normal = (s0.position - b1.center()).normalized(); - zeus::CVector3f point = s0.position + normal * s0.radius; - CCollisionInfo info(point, p0.GetMaterial(), p1.GetMaterial(), normal); - list.Add(info, false); - return true; - } - - if (distSq > s0.radius * s0.radius) + float distSq = 0.f; + int flags = 0; + for (int i = 0; i < 3; ++i) { + if (s0.position[i] < b1.min[i]) { + if (s0.position[i] + s0.radius >= b1.min[i]) { + float dist = s0.position[i] - b1.min[i]; + distSq += dist * dist; + flags |= 1 << (2 * i); + } else { return false; - - zeus::CVector3f point; - switch (flags) - { - case 0x1a: - point = zeus::CVector3f(b1.max.x(), b1.max.y(), b1.min.z()); - break; - case 0x19: - point = zeus::CVector3f(b1.min.x(), b1.max.y(), b1.min.z()); - break; - case 0x16: - point = zeus::CVector3f(b1.max.x(), b1.min.y(), b1.min.z()); - break; - case 0x15: - point = zeus::CVector3f(b1.min.x(), b1.min.y(), b1.min.z()); - break; - case 0x2a: - point = zeus::CVector3f(b1.max.x(), b1.max.y(), b1.max.z()); - break; - case 0x29: - point = zeus::CVector3f(b1.min.x(), b1.max.y(), b1.max.z()); - break; - case 0x26: - point = zeus::CVector3f(b1.max.x(), b1.min.y(), b1.max.z()); - break; - case 0x25: - point = zeus::CVector3f(b1.min.x(), b1.min.y(), b1.max.z()); - break; - case 0x11: - point = zeus::CVector3f(b1.min.x(), s0.position.y(), b1.min.z()); - break; - case 0x12: - point = zeus::CVector3f(b1.max.x(), s0.position.y(), b1.min.z()); - break; - case 0x14: - point = zeus::CVector3f(s0.position.x(), b1.min.y(), b1.min.z()); - break; - case 0x18: - point = zeus::CVector3f(s0.position.x(), b1.max.y(), b1.min.z()); - break; - case 0x5: - point = zeus::CVector3f(b1.min.x(), b1.min.y(), s0.position.z()); - break; - case 0x6: - point = zeus::CVector3f(b1.max.x(), b1.min.y(), s0.position.z()); - break; - case 0x9: - point = zeus::CVector3f(b1.min.x(), b1.max.y(), s0.position.z()); - break; - case 0xa: - point = zeus::CVector3f(b1.max.x(), b1.max.y(), s0.position.z()); - break; - case 0x21: - point = zeus::CVector3f(b1.min.x(), s0.position.y(), b1.max.z()); - break; - case 0x22: - point = zeus::CVector3f(b1.max.x(), s0.position.y(), b1.max.z()); - break; - case 0x24: - point = zeus::CVector3f(s0.position.x(), b1.min.y(), b1.max.z()); - break; - case 0x28: - point = zeus::CVector3f(s0.position.x(), b1.max.y(), b1.max.z()); - break; - case 0x1: - point = zeus::CVector3f(b1.min.x(), s0.position.y(), s0.position.z()); - break; - case 0x2: - point = zeus::CVector3f(b1.max.x(), s0.position.y(), s0.position.z()); - break; - case 0x4: - point = zeus::CVector3f(s0.position.x(), b1.min.y(), s0.position.z()); - break; - case 0x8: - point = zeus::CVector3f(s0.position.x(), b1.max.y(), s0.position.z()); - break; - case 0x10: - point = zeus::CVector3f(s0.position.x(), s0.position.y(), b1.min.z()); - break; - case 0x20: - point = zeus::CVector3f(s0.position.x(), s0.position.y(), b1.max.z()); - break; - default: break; + } + } else if (s0.position[i] > b1.max[i]) { + if (s0.position[i] - s0.radius <= b1.max[i]) { + float dist = s0.position[i] - b1.max[i]; + distSq += dist * dist; + flags |= 1 << (2 * i + 1); + } else { + return false; + } } + } - CCollisionInfo info(point, p0.GetMaterial(), p1.GetMaterial(), (s0.position - point).normalized()); + if (!flags) { + zeus::CVector3f normal = (s0.position - b1.center()).normalized(); + zeus::CVector3f point = s0.position + normal * s0.radius; + CCollisionInfo info(point, p0.GetMaterial(), p1.GetMaterial(), normal); list.Add(info, false); return true; -} - -bool Sphere_AABox_Bool(const CInternalCollisionStructure& collision) -{ - const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableAABox& p1 = static_cast(collision.GetRight().GetPrim()); - - zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); - zeus::CAABox b1 = p1.Transform(collision.GetRight().GetTransform()); - - return CCollidableSphere::Sphere_AABox_Bool(s0, b1); -} - -bool Sphere_Sphere(const CInternalCollisionStructure& collision, CCollisionInfoList& list) -{ - const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableSphere& p1 = static_cast(collision.GetRight().GetPrim()); - - zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); - zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform()); - - float radiusSum = s0.radius + s1.radius; - zeus::CVector3f delta = s0.position - s1.position; - float deltaMagSq = delta.magSquared(); - if (deltaMagSq <= radiusSum * radiusSum) - { - zeus::CVector3f deltaNorm = delta.canBeNormalized() ? - (1.f / std::sqrt(deltaMagSq)) * delta : zeus::CVector3f::skRight; - zeus::CVector3f collisionPoint = deltaNorm * s1.radius + s1.position; - CCollisionInfo info(collisionPoint, p0.GetMaterial(), p1.GetMaterial(), deltaNorm); - list.Add(info, false); - - return true; - } + } + if (distSq > s0.radius * s0.radius) return false; + + zeus::CVector3f point; + switch (flags) { + case 0x1a: + point = zeus::CVector3f(b1.max.x(), b1.max.y(), b1.min.z()); + break; + case 0x19: + point = zeus::CVector3f(b1.min.x(), b1.max.y(), b1.min.z()); + break; + case 0x16: + point = zeus::CVector3f(b1.max.x(), b1.min.y(), b1.min.z()); + break; + case 0x15: + point = zeus::CVector3f(b1.min.x(), b1.min.y(), b1.min.z()); + break; + case 0x2a: + point = zeus::CVector3f(b1.max.x(), b1.max.y(), b1.max.z()); + break; + case 0x29: + point = zeus::CVector3f(b1.min.x(), b1.max.y(), b1.max.z()); + break; + case 0x26: + point = zeus::CVector3f(b1.max.x(), b1.min.y(), b1.max.z()); + break; + case 0x25: + point = zeus::CVector3f(b1.min.x(), b1.min.y(), b1.max.z()); + break; + case 0x11: + point = zeus::CVector3f(b1.min.x(), s0.position.y(), b1.min.z()); + break; + case 0x12: + point = zeus::CVector3f(b1.max.x(), s0.position.y(), b1.min.z()); + break; + case 0x14: + point = zeus::CVector3f(s0.position.x(), b1.min.y(), b1.min.z()); + break; + case 0x18: + point = zeus::CVector3f(s0.position.x(), b1.max.y(), b1.min.z()); + break; + case 0x5: + point = zeus::CVector3f(b1.min.x(), b1.min.y(), s0.position.z()); + break; + case 0x6: + point = zeus::CVector3f(b1.max.x(), b1.min.y(), s0.position.z()); + break; + case 0x9: + point = zeus::CVector3f(b1.min.x(), b1.max.y(), s0.position.z()); + break; + case 0xa: + point = zeus::CVector3f(b1.max.x(), b1.max.y(), s0.position.z()); + break; + case 0x21: + point = zeus::CVector3f(b1.min.x(), s0.position.y(), b1.max.z()); + break; + case 0x22: + point = zeus::CVector3f(b1.max.x(), s0.position.y(), b1.max.z()); + break; + case 0x24: + point = zeus::CVector3f(s0.position.x(), b1.min.y(), b1.max.z()); + break; + case 0x28: + point = zeus::CVector3f(s0.position.x(), b1.max.y(), b1.max.z()); + break; + case 0x1: + point = zeus::CVector3f(b1.min.x(), s0.position.y(), s0.position.z()); + break; + case 0x2: + point = zeus::CVector3f(b1.max.x(), s0.position.y(), s0.position.z()); + break; + case 0x4: + point = zeus::CVector3f(s0.position.x(), b1.min.y(), s0.position.z()); + break; + case 0x8: + point = zeus::CVector3f(s0.position.x(), b1.max.y(), s0.position.z()); + break; + case 0x10: + point = zeus::CVector3f(s0.position.x(), s0.position.y(), b1.min.z()); + break; + case 0x20: + point = zeus::CVector3f(s0.position.x(), s0.position.y(), b1.max.z()); + break; + default: + break; + } + + CCollisionInfo info(point, p0.GetMaterial(), p1.GetMaterial(), (s0.position - point).normalized()); + list.Add(info, false); + return true; } -bool Sphere_Sphere_Bool(const CInternalCollisionStructure& collision) -{ - const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableSphere& p1 = static_cast(collision.GetRight().GetPrim()); +bool Sphere_AABox_Bool(const CInternalCollisionStructure& collision) { + const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableAABox& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); - zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform()); + zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::CAABox b1 = p1.Transform(collision.GetRight().GetTransform()); - float radiusSum = s0.radius + s1.radius; - return (s0.position - s1.position).magSquared() <= radiusSum * radiusSum; + return CCollidableSphere::Sphere_AABox_Bool(s0, b1); } +bool Sphere_Sphere(const CInternalCollisionStructure& collision, CCollisionInfoList& list) { + const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableSphere& p1 = static_cast(collision.GetRight().GetPrim()); + + zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform()); + + float radiusSum = s0.radius + s1.radius; + zeus::CVector3f delta = s0.position - s1.position; + float deltaMagSq = delta.magSquared(); + if (deltaMagSq <= radiusSum * radiusSum) { + zeus::CVector3f deltaNorm = + delta.canBeNormalized() ? (1.f / std::sqrt(deltaMagSq)) * delta : zeus::CVector3f::skRight; + zeus::CVector3f collisionPoint = deltaNorm * s1.radius + s1.position; + CCollisionInfo info(collisionPoint, p0.GetMaterial(), p1.GetMaterial(), deltaNorm); + list.Add(info, false); + + return true; + } + + return false; } +bool Sphere_Sphere_Bool(const CInternalCollisionStructure& collision) { + const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableSphere& p1 = static_cast(collision.GetRight().GetPrim()); + + zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform()); + + float radiusSum = s0.radius + s1.radius; + return (s0.position - s1.position).magSquared() <= radiusSum * radiusSum; +} + +} // namespace Collide + CCollidableSphere::CCollidableSphere(const zeus::CSphere& sphere, const CMaterialList& list) -: CCollisionPrimitive(list), x10_sphere(sphere) -{ -} +: CCollisionPrimitive(list), x10_sphere(sphere) {} -zeus::CSphere CCollidableSphere::Transform(const zeus::CTransform& xf) const -{ - return zeus::CSphere(xf * x10_sphere.position, x10_sphere.radius); +zeus::CSphere CCollidableSphere::Transform(const zeus::CTransform& xf) const { + return zeus::CSphere(xf * x10_sphere.position, x10_sphere.radius); } u32 CCollidableSphere::GetTableIndex() const { return sTableIndex; } -zeus::CAABox CCollidableSphere::CalculateAABox(const zeus::CTransform& xf) const -{ - zeus::CVector3f xfPos = xf * x10_sphere.position; - return {xfPos - x10_sphere.radius, xfPos + x10_sphere.radius}; +zeus::CAABox CCollidableSphere::CalculateAABox(const zeus::CTransform& xf) const { + zeus::CVector3f xfPos = xf * x10_sphere.position; + return {xfPos - x10_sphere.radius, xfPos + x10_sphere.radius}; } -zeus::CAABox CCollidableSphere::CalculateLocalAABox() const -{ - return {x10_sphere.position - x10_sphere.radius, x10_sphere.position + x10_sphere.radius}; +zeus::CAABox CCollidableSphere::CalculateLocalAABox() const { + return {x10_sphere.position - x10_sphere.radius, x10_sphere.position + x10_sphere.radius}; } FourCC CCollidableSphere::GetPrimType() const { return SBIG('SPHR'); } -CRayCastResult CCollidableSphere::CastRayInternal(const CInternalRayCastStructure& rayCast) const -{ - if (!rayCast.GetFilter().Passes(GetMaterial())) - return {}; - - zeus::CSphere xfSphere = Transform(rayCast.GetTransform()); - float t = 0.f; - zeus::CVector3f point; - if (CollisionUtil::RaySphereIntersection(xfSphere, rayCast.GetRay().start, rayCast.GetRay().dir, - rayCast.GetMaxTime(), t, point)) - { - zeus::CVector3f delta = point - xfSphere.position; - float deltaMag = delta.magnitude(); - zeus::CUnitVector3f planeNormal = - (deltaMag > 0.01f) ? delta * (1.f / deltaMag) : rayCast.GetRay().dir; - float planeD = point.dot(planeNormal); - return CRayCastResult(t, point, zeus::CPlane(planeNormal, planeD), GetMaterial()); - } - +CRayCastResult CCollidableSphere::CastRayInternal(const CInternalRayCastStructure& rayCast) const { + if (!rayCast.GetFilter().Passes(GetMaterial())) return {}; + + zeus::CSphere xfSphere = Transform(rayCast.GetTransform()); + float t = 0.f; + zeus::CVector3f point; + if (CollisionUtil::RaySphereIntersection(xfSphere, rayCast.GetRay().start, rayCast.GetRay().dir, rayCast.GetMaxTime(), + t, point)) { + zeus::CVector3f delta = point - xfSphere.position; + float deltaMag = delta.magnitude(); + zeus::CUnitVector3f planeNormal = (deltaMag > 0.01f) ? delta * (1.f / deltaMag) : rayCast.GetRay().dir; + float planeD = point.dot(planeNormal); + return CRayCastResult(t, point, zeus::CPlane(planeNormal, planeD), GetMaterial()); + } + + return {}; } bool CCollidableSphere::CollideMovingAABox(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& infoOut) -{ - const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableAABox& p1 = static_cast(collision.GetRight().GetPrim()); + double& dOut, CCollisionInfo& infoOut) { + const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableAABox& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); - zeus::CAABox b1 = p1.CalculateAABox(collision.GetRight().GetTransform()); + zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::CAABox b1 = p1.CalculateAABox(collision.GetRight().GetTransform()); - double d = dOut; - zeus::CVector3f point, normal; - if (CollisionUtil::MovingSphereAABox(s0, b1, dir, d, point, normal) && d < dOut) - { - dOut = d; - infoOut = CCollisionInfo(point, p0.GetMaterial(), p1.GetMaterial(), normal); - return true; - } + double d = dOut; + zeus::CVector3f point, normal; + if (CollisionUtil::MovingSphereAABox(s0, b1, dir, d, point, normal) && d < dOut) { + dOut = d; + infoOut = CCollisionInfo(point, p0.GetMaterial(), p1.GetMaterial(), normal); + return true; + } - return false; + return false; } bool CCollidableSphere::CollideMovingSphere(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& infoOut) -{ - const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); - const CCollidableSphere& p1 = static_cast(collision.GetRight().GetPrim()); + double& dOut, CCollisionInfo& infoOut) { + const CCollidableSphere& p0 = static_cast(collision.GetLeft().GetPrim()); + const CCollidableSphere& p1 = static_cast(collision.GetRight().GetPrim()); - zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); - zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform()); + zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform()); + zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform()); - double d = dOut; - if (CollisionUtil::RaySphereIntersection_Double(zeus::CSphere(s1.position, s0.radius + s1.radius), - s0.position, dir, d) && d >= 0.0 && d < dOut) - { - dOut = d; - zeus::CVector3f normal = (s0.position + float(d) * dir - s1.position).normalized(); - infoOut = CCollisionInfo(s1.position + s1.radius * normal, p0.GetMaterial(), p1.GetMaterial(), normal); - return true; + double d = dOut; + if (CollisionUtil::RaySphereIntersection_Double(zeus::CSphere(s1.position, s0.radius + s1.radius), s0.position, dir, + d) && + d >= 0.0 && d < dOut) { + dOut = d; + zeus::CVector3f normal = (s0.position + float(d) * dir - s1.position).normalized(); + infoOut = CCollisionInfo(s1.position + s1.radius * normal, p0.GetMaterial(), p1.GetMaterial(), normal); + return true; + } + + return false; +} + +bool CCollidableSphere::Sphere_AABox_Bool(const zeus::CSphere& sphere, const zeus::CAABox& aabb) { + float mag = 0.f; + + for (int i = 0; i < 3; ++i) { + if (sphere.position[i] < aabb.min[i]) { + float tmp = sphere.position[i] - aabb.min[i]; + mag += tmp * tmp; + } else if (sphere.position[i] > aabb.max[i]) { + float tmp = sphere.position[i] - aabb.max[i]; + mag += tmp * tmp; } + } - return false; -} - -bool CCollidableSphere::Sphere_AABox_Bool(const zeus::CSphere& sphere, const zeus::CAABox& aabb) -{ - float mag = 0.f; - - for (int i=0 ; i<3 ; ++i) - { - if (sphere.position[i] < aabb.min[i]) - { - float tmp = sphere.position[i] - aabb.min[i]; - mag += tmp * tmp; - } - else if (sphere.position[i] > aabb.max[i]) - { - float tmp = sphere.position[i] - aabb.max[i]; - mag += tmp * tmp; - } - } - - return mag <= sphere.radius * sphere.radius; -} + return mag <= sphere.radius * sphere.radius; } +} // namespace urde diff --git a/Runtime/Collision/CCollidableSphere.hpp b/Runtime/Collision/CCollidableSphere.hpp index fad2f5b5b..fa89b0bd9 100644 --- a/Runtime/Collision/CCollidableSphere.hpp +++ b/Runtime/Collision/CCollidableSphere.hpp @@ -3,42 +3,36 @@ #include "CCollisionPrimitive.hpp" #include "zeus/CSphere.hpp" -namespace urde -{ -namespace Collide -{ +namespace urde { +namespace Collide { bool Sphere_AABox(const CInternalCollisionStructure&, CCollisionInfoList&); bool Sphere_AABox_Bool(const CInternalCollisionStructure&); bool Sphere_Sphere(const CInternalCollisionStructure&, CCollisionInfoList&); bool Sphere_Sphere_Bool(const CInternalCollisionStructure&); -} -class CCollidableSphere : public CCollisionPrimitive -{ - static const Type sType; - static u32 sTableIndex; +} // namespace Collide +class CCollidableSphere : public CCollisionPrimitive { + static const Type sType; + static u32 sTableIndex; - zeus::CSphere x10_sphere; + zeus::CSphere x10_sphere; public: - CCollidableSphere(const zeus::CSphere&, const CMaterialList&); + CCollidableSphere(const zeus::CSphere&, const CMaterialList&); - const zeus::CSphere& GetSphere() const { return x10_sphere; } - void SetSphereCenter(const zeus::CVector3f& center) { x10_sphere.position = center; } - zeus::CSphere Transform(const zeus::CTransform& xf) const; + const zeus::CSphere& GetSphere() const { return x10_sphere; } + void SetSphereCenter(const zeus::CVector3f& center) { x10_sphere.position = center; } + zeus::CSphere Transform(const zeus::CTransform& xf) const; - virtual u32 GetTableIndex() const; - virtual zeus::CAABox CalculateAABox(const zeus::CTransform&) const; - virtual zeus::CAABox CalculateLocalAABox() const; - virtual FourCC GetPrimType() const; - virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; + virtual u32 GetTableIndex() const; + virtual zeus::CAABox CalculateAABox(const zeus::CTransform&) const; + virtual zeus::CAABox CalculateLocalAABox() const; + virtual FourCC GetPrimType() const; + virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; - static const Type& GetType() { return sType; } - static void SetStaticTableIndex(u32 index) { sTableIndex = index; } - static bool CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, - CCollisionInfo&); - static bool CollideMovingSphere(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, - CCollisionInfo&); - static bool Sphere_AABox_Bool(const zeus::CSphere& sphere, const zeus::CAABox& aabb); + static const Type& GetType() { return sType; } + static void SetStaticTableIndex(u32 index) { sTableIndex = index; } + static bool CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&); + static bool CollideMovingSphere(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&); + static bool Sphere_AABox_Bool(const zeus::CSphere& sphere, const zeus::CAABox& aabb); }; -} - +} // namespace urde diff --git a/Runtime/Collision/CCollisionActor.cpp b/Runtime/Collision/CCollisionActor.cpp index c8035f862..9b377f38e 100644 --- a/Runtime/Collision/CCollisionActor.cpp +++ b/Runtime/Collision/CCollisionActor.cpp @@ -6,8 +6,7 @@ #include "Collision/CCollidableSphere.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { static const CMaterialList gkDefaultCollisionActorMaterials = CMaterialList(EMaterialTypes::Solid, EMaterialTypes::CollisionActor, EMaterialTypes::ScanPassthrough, EMaterialTypes::CameraPassthrough); @@ -22,12 +21,11 @@ CCollisionActor::CCollisionActor(TUniqueId uid1, TAreaId aId, TUniqueId uid2, co , x260_boxSize(vec1) , x26c_(vec2) , x278_obbContainer(new CCollidableOBBTreeGroupContainer(vec1, vec2)) -, x27c_obbTreeGroupPrimitive(new CCollidableOBBTreeGroup(x278_obbContainer.get(), GetMaterialList())) -{ - SetCoefficientOfRestitutionModifier(0.5f); - SetCallTouch(false); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( - {EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision})); +, x27c_obbTreeGroupPrimitive(new CCollidableOBBTreeGroup(x278_obbContainer.get(), GetMaterialList())) { + SetCoefficientOfRestitutionModifier(0.5f); + SetCallTouch(false); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision})); } CCollisionActor::CCollisionActor(TUniqueId uid1, TAreaId aId, TUniqueId uid2, const zeus::CVector3f& boxSize, @@ -39,12 +37,11 @@ CCollisionActor::CCollisionActor(TUniqueId uid1, TAreaId aId, TUniqueId uid2, co , x25c_owner(uid2) , x260_boxSize(boxSize) , x280_aaboxPrimitive(new CCollidableAABox(zeus::CAABox(-0.5f * boxSize, 0.5f * boxSize), - CMaterialList(EMaterialTypes::Solid, EMaterialTypes::NoStaticCollision))) -{ - SetCoefficientOfRestitutionModifier(0.5f); - SetCallTouch(false); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( - {EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision})); + CMaterialList(EMaterialTypes::Solid, EMaterialTypes::NoStaticCollision))) { + SetCoefficientOfRestitutionModifier(0.5f); + SetCallTouch(false); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision})); } CCollisionActor::CCollisionActor(TUniqueId uid1, TAreaId aId, TUniqueId uid2, bool active, float radius, float mass) @@ -55,40 +52,35 @@ CCollisionActor::CCollisionActor(TUniqueId uid1, TAreaId aId, TUniqueId uid2, bo , x25c_owner(uid2) , x284_spherePrimitive(new CCollidableSphere(zeus::CSphere(zeus::CVector3f::skZero, radius), CMaterialList(EMaterialTypes::NoStaticCollision, EMaterialTypes::Solid))) -, x288_sphereRadius(radius) -{ - SetCoefficientOfRestitutionModifier(0.5f); - SetCallTouch(false); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( - {EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision})); +, x288_sphereRadius(radius) { + SetCoefficientOfRestitutionModifier(0.5f); + SetCallTouch(false); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, {EMaterialTypes::CollisionActor, EMaterialTypes::NoStaticCollision})); } void CCollisionActor::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CCollisionActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - switch(msg) - { - case EScriptObjectMessage::Falling: - case EScriptObjectMessage::Registered: - case EScriptObjectMessage::Deleted: - case EScriptObjectMessage::InitializedInArea: - break; - case EScriptObjectMessage::Touched: - case EScriptObjectMessage::Damage: - case EScriptObjectMessage::InvulnDamage: - { - CEntity* ent = mgr.ObjectById(x25c_owner); - if (ent) - mgr.SendScriptMsg(ent, x2fc_lastTouched, msg); - } +void CCollisionActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Falling: + case EScriptObjectMessage::Registered: + case EScriptObjectMessage::Deleted: + case EScriptObjectMessage::InitializedInArea: break; - default: - mgr.SendScriptMsgAlways(x25c_owner, x8_uid, msg); + case EScriptObjectMessage::Touched: + case EScriptObjectMessage::Damage: + case EScriptObjectMessage::InvulnDamage: { + CEntity* ent = mgr.ObjectById(x25c_owner); + if (ent) + mgr.SendScriptMsg(ent, x2fc_lastTouched, msg); + } break; + default: + mgr.SendScriptMsgAlways(x25c_owner, x8_uid, msg); break; - } + } - CActor::AcceptScriptMsg(msg, uid, mgr); + CActor::AcceptScriptMsg(msg, uid, mgr); } CHealthInfo* CCollisionActor::HealthInfo(CStateManager&) { return &x28c_healthInfo; } @@ -96,85 +88,76 @@ CHealthInfo* CCollisionActor::HealthInfo(CStateManager&) { return &x28c_healthIn const CDamageVulnerability* CCollisionActor::GetDamageVulnerability() const { return &x294_damageVuln; } const CDamageVulnerability* CCollisionActor::GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, - const CDamageInfo&) const -{ - return GetDamageVulnerability(); + const CDamageInfo&) const { + return GetDamageVulnerability(); } void CCollisionActor::SetDamageVulnerability(const CDamageVulnerability& vuln) { x294_damageVuln = vuln; } -zeus::CVector3f CCollisionActor::GetScanObjectIndicatorPosition(const CStateManager& mgr) const -{ - const CGameCamera* gameCamera = static_cast(mgr.GetCameraManager()->GetCurrentCamera(mgr)); +zeus::CVector3f CCollisionActor::GetScanObjectIndicatorPosition(const CStateManager& mgr) const { + const CGameCamera* gameCamera = static_cast(mgr.GetCameraManager()->GetCurrentCamera(mgr)); - float scanScale; - if (x258_primitiveType == EPrimitiveType::Sphere) - scanScale = GetSphereRadius(); - else - { - const zeus::CVector3f v = GetBoxSize(); - float comp = (v.x() < v.y() ? v.y() : v.z()); - comp = (comp < v.z() ? v.x() : comp); + float scanScale; + if (x258_primitiveType == EPrimitiveType::Sphere) + scanScale = GetSphereRadius(); + else { + const zeus::CVector3f v = GetBoxSize(); + float comp = (v.x() < v.y() ? v.y() : v.z()); + comp = (comp < v.z() ? v.x() : comp); - scanScale = 0.5f * comp; - } - scanScale *= 3.0f; - zeus::CVector3f orbitPos = GetOrbitPosition(mgr); - return (scanScale * (orbitPos - gameCamera->GetTransform().origin).normalized()) - orbitPos; + scanScale = 0.5f * comp; + } + scanScale *= 3.0f; + zeus::CVector3f orbitPos = GetOrbitPosition(mgr); + return (scanScale * (orbitPos - gameCamera->GetTransform().origin).normalized()) - orbitPos; } -const CCollisionPrimitive* CCollisionActor::GetCollisionPrimitive() const -{ - if (x258_primitiveType == EPrimitiveType::OBBTreeGroup) - return x27c_obbTreeGroupPrimitive.get(); - if (x258_primitiveType == EPrimitiveType::AABox) - return x280_aaboxPrimitive.get(); - return x284_spherePrimitive.get(); +const CCollisionPrimitive* CCollisionActor::GetCollisionPrimitive() const { + if (x258_primitiveType == EPrimitiveType::OBBTreeGroup) + return x27c_obbTreeGroupPrimitive.get(); + if (x258_primitiveType == EPrimitiveType::AABox) + return x280_aaboxPrimitive.get(); + return x284_spherePrimitive.get(); } EWeaponCollisionResponseTypes CCollisionActor::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const -{ - return x300_responseType; + const CWeaponMode&, EProjectileAttrib) const { + return x300_responseType; } -zeus::CTransform CCollisionActor::GetPrimitiveTransform() const -{ - zeus::CTransform xf = x34_transform; - xf.origin = CPhysicsActor::GetPrimitiveTransform().origin; - return xf; +zeus::CTransform CCollisionActor::GetPrimitiveTransform() const { + zeus::CTransform xf = x34_transform; + xf.origin = CPhysicsActor::GetPrimitiveTransform().origin; + return xf; } -std::experimental::optional CCollisionActor::GetTouchBounds() const -{ - std::experimental::optional aabox; - if (x258_primitiveType == EPrimitiveType::OBBTreeGroup) - aabox = {x27c_obbTreeGroupPrimitive->CalculateAABox(x34_transform)}; - else if (x258_primitiveType == EPrimitiveType::AABox) - aabox = {x280_aaboxPrimitive->CalculateAABox(x34_transform)}; - else if (x258_primitiveType == EPrimitiveType::Sphere) - aabox = {x284_spherePrimitive->CalculateAABox(x34_transform)}; +std::experimental::optional CCollisionActor::GetTouchBounds() const { + std::experimental::optional aabox; + if (x258_primitiveType == EPrimitiveType::OBBTreeGroup) + aabox = {x27c_obbTreeGroupPrimitive->CalculateAABox(x34_transform)}; + else if (x258_primitiveType == EPrimitiveType::AABox) + aabox = {x280_aaboxPrimitive->CalculateAABox(x34_transform)}; + else if (x258_primitiveType == EPrimitiveType::Sphere) + aabox = {x284_spherePrimitive->CalculateAABox(x34_transform)}; - aabox->accumulateBounds(aabox->max + x304_extendedTouchBounds); - aabox->accumulateBounds(aabox->min - x304_extendedTouchBounds); + aabox->accumulateBounds(aabox->max + x304_extendedTouchBounds); + aabox->accumulateBounds(aabox->min - x304_extendedTouchBounds); - return aabox; + return aabox; } -void CCollisionActor::OnScanStateChanged(CActor::EScanState state, CStateManager& mgr) -{ - TCastToPtr actor = mgr.ObjectById(x25c_owner); - if (actor) - actor->OnScanStateChanged(state, mgr); +void CCollisionActor::OnScanStateChanged(CActor::EScanState state, CStateManager& mgr) { + TCastToPtr actor = mgr.ObjectById(x25c_owner); + if (actor) + actor->OnScanStateChanged(state, mgr); - CActor::OnScanStateChanged(state, mgr); + CActor::OnScanStateChanged(state, mgr); } -void CCollisionActor::Touch(CActor& actor, CStateManager& mgr) -{ - x2fc_lastTouched = actor.GetUniqueId(); - mgr.SendScriptMsgAlways(x25c_owner, GetUniqueId(), EScriptObjectMessage::Touched); +void CCollisionActor::Touch(CActor& actor, CStateManager& mgr) { + x2fc_lastTouched = actor.GetUniqueId(); + mgr.SendScriptMsgAlways(x25c_owner, GetUniqueId(), EScriptObjectMessage::Touched); } zeus::CVector3f CCollisionActor::GetOrbitPosition(const CStateManager&) const { return GetTouchBounds()->center(); } -} +} // namespace urde diff --git a/Runtime/Collision/CCollisionActor.hpp b/Runtime/Collision/CCollisionActor.hpp index 180fe50ee..72031506d 100644 --- a/Runtime/Collision/CCollisionActor.hpp +++ b/Runtime/Collision/CCollisionActor.hpp @@ -3,61 +3,54 @@ #include "World/CPhysicsActor.hpp" #include "World/CHealthInfo.hpp" #include "World/CDamageVulnerability.hpp" -namespace urde -{ +namespace urde { class CCollidableSphere; class CCollidableOBBTreeGroup; class CCollidableOBBTreeGroupContainer; -class CCollisionActor : public CPhysicsActor -{ - enum class EPrimitiveType - { - OBBTreeGroup, - AABox, - Sphere - }; +class CCollisionActor : public CPhysicsActor { + enum class EPrimitiveType { OBBTreeGroup, AABox, Sphere }; + + EPrimitiveType x258_primitiveType; + TUniqueId x25c_owner; + zeus::CVector3f x260_boxSize; + zeus::CVector3f x26c_; + std::unique_ptr x278_obbContainer; + std::unique_ptr x27c_obbTreeGroupPrimitive; + std::unique_ptr x280_aaboxPrimitive; + std::unique_ptr x284_spherePrimitive; + float x288_sphereRadius; + CHealthInfo x28c_healthInfo = CHealthInfo(0.f); + CDamageVulnerability x294_damageVuln = CDamageVulnerability::NormalVulnerabilty(); + TUniqueId x2fc_lastTouched = kInvalidUniqueId; + EWeaponCollisionResponseTypes x300_responseType = EWeaponCollisionResponseTypes::EnemyNormal; + zeus::CVector3f x304_extendedTouchBounds = zeus::CVector3f::skZero; - EPrimitiveType x258_primitiveType; - TUniqueId x25c_owner; - zeus::CVector3f x260_boxSize; - zeus::CVector3f x26c_; - std::unique_ptr x278_obbContainer; - std::unique_ptr x27c_obbTreeGroupPrimitive; - std::unique_ptr x280_aaboxPrimitive; - std::unique_ptr x284_spherePrimitive; - float x288_sphereRadius; - CHealthInfo x28c_healthInfo = CHealthInfo(0.f); - CDamageVulnerability x294_damageVuln = CDamageVulnerability::NormalVulnerabilty(); - TUniqueId x2fc_lastTouched = kInvalidUniqueId; - EWeaponCollisionResponseTypes x300_responseType = EWeaponCollisionResponseTypes::EnemyNormal; - zeus::CVector3f x304_extendedTouchBounds = zeus::CVector3f::skZero; public: - CCollisionActor(TUniqueId, TAreaId, TUniqueId, const zeus::CVector3f&, const zeus::CVector3f&, bool, float); - CCollisionActor(TUniqueId, TAreaId, TUniqueId, const zeus::CVector3f&, bool, float); - CCollisionActor(TUniqueId, TAreaId, TUniqueId, bool, float, float); + CCollisionActor(TUniqueId, TAreaId, TUniqueId, const zeus::CVector3f&, const zeus::CVector3f&, bool, float); + CCollisionActor(TUniqueId, TAreaId, TUniqueId, const zeus::CVector3f&, bool, float); + CCollisionActor(TUniqueId, TAreaId, TUniqueId, bool, float, float); - void Accept(IVisitor &visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - CHealthInfo* HealthInfo(CStateManager&); - const CDamageVulnerability* GetDamageVulnerability() const; - const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, - const CDamageInfo&) const; - void OnScanStateChanged(EScanState, CStateManager &); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + CHealthInfo* HealthInfo(CStateManager&); + const CDamageVulnerability* GetDamageVulnerability() const; + const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, + const CDamageInfo&) const; + void OnScanStateChanged(EScanState, CStateManager&); - void Touch(CActor &, CStateManager &); - zeus::CVector3f GetOrbitPosition(const CStateManager &) const; - const CCollisionPrimitive* GetCollisionPrimitive() const; - EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const; - zeus::CTransform GetPrimitiveTransform() const; - std::experimental::optional GetTouchBounds() const; - void SetDamageVulnerability(const CDamageVulnerability& vuln); - const zeus::CVector3f& GetBoxSize() const { return x260_boxSize; } - TUniqueId GetOwnerId() const { return x25c_owner; } - TUniqueId GetLastTouchedObject() const { return x2fc_lastTouched; } - zeus::CVector3f GetScanObjectIndicatorPosition(const CStateManager &) const; - void SetExtendedTouchBounds(const zeus::CVector3f& boundExt) { x304_extendedTouchBounds = boundExt; } - float GetSphereRadius() const { return x288_sphereRadius; } + void Touch(CActor&, CStateManager&); + zeus::CVector3f GetOrbitPosition(const CStateManager&) const; + const CCollisionPrimitive* GetCollisionPrimitive() const; + EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, + const CWeaponMode&, EProjectileAttrib) const; + zeus::CTransform GetPrimitiveTransform() const; + std::experimental::optional GetTouchBounds() const; + void SetDamageVulnerability(const CDamageVulnerability& vuln); + const zeus::CVector3f& GetBoxSize() const { return x260_boxSize; } + TUniqueId GetOwnerId() const { return x25c_owner; } + TUniqueId GetLastTouchedObject() const { return x2fc_lastTouched; } + zeus::CVector3f GetScanObjectIndicatorPosition(const CStateManager&) const; + void SetExtendedTouchBounds(const zeus::CVector3f& boundExt) { x304_extendedTouchBounds = boundExt; } + float GetSphereRadius() const { return x288_sphereRadius; } }; -} - +} // namespace urde diff --git a/Runtime/Collision/CCollisionActorManager.cpp b/Runtime/Collision/CCollisionActorManager.cpp index 1c8bf7a2f..6634c5f01 100644 --- a/Runtime/Collision/CCollisionActorManager.cpp +++ b/Runtime/Collision/CCollisionActorManager.cpp @@ -5,237 +5,185 @@ #include "CMaterialList.hpp" #include "Collision/CCollisionActor.hpp" -namespace urde -{ +namespace urde { CCollisionActorManager::CCollisionActorManager(CStateManager& mgr, TUniqueId owner, TAreaId area, const std::vector& descs, bool active) -: x10_ownerId(owner) -, x12_active(active) -{ - if (TCastToConstPtr act = mgr.GetObjectById(x10_ownerId)) - { - zeus::CTransform xf = act->GetTransform(); - const CAnimData* animData = act->GetModelData()->GetAnimationData(); - zeus::CVector3f scale = act->GetModelData()->GetScale(); - zeus::CTransform scaleXf = zeus::CTransform::Scale(scale); - x0_jointDescriptions.reserve(descs.size()); - for (const CJointCollisionDescription& desc : descs) - { - CJointCollisionDescription modDesc = desc; - modDesc.ScaleAllBounds(scale); - zeus::CTransform locXf = GetWRLocatorTransform(*animData, modDesc.GetPivotId(), xf, scaleXf); - if (modDesc.GetNextId() != 0xff) - { - zeus::CTransform locXf2 = GetWRLocatorTransform(*animData, modDesc.GetNextId(), xf, scaleXf); - float dist = (locXf2.origin - locXf.origin).magnitude(); - if (modDesc.GetType() == CJointCollisionDescription::ECollisionType::OBBAutoSize) - { - if (dist <= FLT_EPSILON) - continue; - zeus::CVector3f bounds = modDesc.GetBounds(); - bounds.y() += dist; - CCollisionActor* newAct = - new CCollisionActor(mgr.AllocateUniqueId(), area, x10_ownerId, bounds, - zeus::CVector3f(0.f, 0.5f * dist, 0.f), active, modDesc.GetMass()); - if (modDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero) - { - newAct->SetTransform(locXf); - } - else - { - zeus::CVector3f delta = (locXf2.origin - locXf.origin).normalized(); - zeus::CVector3f upVector = locXf.basis[2]; - if (zeus::close_enough(std::fabs(delta.dot(upVector)), 1.f)) - upVector = locXf.basis[1]; - newAct->SetTransform(zeus::lookAt(locXf.origin, locXf.origin + delta, upVector)); - } - mgr.AddObject(newAct); - x0_jointDescriptions.push_back(desc); - x0_jointDescriptions.back().SetCollisionActorId(newAct->GetUniqueId()); - } - else - { - TUniqueId newId = mgr.AllocateUniqueId(); - CCollisionActor* newAct = - new CCollisionActor(newId, area, x10_ownerId, - active, modDesc.GetRadius(), modDesc.GetMass()); - newAct->SetTransform(locXf); - mgr.AddObject(newAct); - x0_jointDescriptions.push_back(CJointCollisionDescription:: - SphereCollision(modDesc.GetPivotId(), modDesc.GetRadius(), modDesc.GetName(), 0.001f)); - x0_jointDescriptions.back().SetCollisionActorId(newId); - u32 numSeps = u32(dist / modDesc.GetMaxSeparation()); - if (numSeps) - { - x0_jointDescriptions.reserve(x0_jointDescriptions.capacity() + numSeps); - float pitch = dist / float(numSeps + 1); - for (u32 i = 0; i < numSeps; ++i) - { - float separation = pitch * float(i + 1); - x0_jointDescriptions.push_back(CJointCollisionDescription:: - SphereSubdivideCollision(modDesc.GetPivotId(), modDesc.GetNextId(), modDesc.GetRadius(), - separation, CJointCollisionDescription::EOrientationType::One, - modDesc.GetName(), 0.001f)); - TUniqueId newId2 = mgr.AllocateUniqueId(); - CCollisionActor* newAct2 = - new CCollisionActor(newId2, area, x10_ownerId, - active, modDesc.GetRadius(), modDesc.GetMass()); - if (modDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero) - { - newAct2->SetTransform( - zeus::CTransform::Translate(locXf.origin + separation * locXf.basis[1])); - } - else - { - zeus::CVector3f delta = (locXf2.origin - locXf.origin).normalized(); - zeus::CVector3f upVector = locXf.basis[2]; - if (zeus::close_enough( - std::fabs(delta.dot(upVector)), 1.f)) - upVector = locXf.basis[1]; - zeus::CTransform lookAt = zeus::lookAt(zeus::CVector3f::skZero, delta, upVector); - newAct2->SetTransform( - zeus::CTransform::Translate(lookAt.basis[1] * separation + locXf.origin)); - } - mgr.AddObject(newAct2); - x0_jointDescriptions.back().SetCollisionActorId(newId2); - } - } - } +: x10_ownerId(owner), x12_active(active) { + if (TCastToConstPtr act = mgr.GetObjectById(x10_ownerId)) { + zeus::CTransform xf = act->GetTransform(); + const CAnimData* animData = act->GetModelData()->GetAnimationData(); + zeus::CVector3f scale = act->GetModelData()->GetScale(); + zeus::CTransform scaleXf = zeus::CTransform::Scale(scale); + x0_jointDescriptions.reserve(descs.size()); + for (const CJointCollisionDescription& desc : descs) { + CJointCollisionDescription modDesc = desc; + modDesc.ScaleAllBounds(scale); + zeus::CTransform locXf = GetWRLocatorTransform(*animData, modDesc.GetPivotId(), xf, scaleXf); + if (modDesc.GetNextId() != 0xff) { + zeus::CTransform locXf2 = GetWRLocatorTransform(*animData, modDesc.GetNextId(), xf, scaleXf); + float dist = (locXf2.origin - locXf.origin).magnitude(); + if (modDesc.GetType() == CJointCollisionDescription::ECollisionType::OBBAutoSize) { + if (dist <= FLT_EPSILON) + continue; + zeus::CVector3f bounds = modDesc.GetBounds(); + bounds.y() += dist; + CCollisionActor* newAct = + new CCollisionActor(mgr.AllocateUniqueId(), area, x10_ownerId, bounds, + zeus::CVector3f(0.f, 0.5f * dist, 0.f), active, modDesc.GetMass()); + if (modDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero) { + newAct->SetTransform(locXf); + } else { + zeus::CVector3f delta = (locXf2.origin - locXf.origin).normalized(); + zeus::CVector3f upVector = locXf.basis[2]; + if (zeus::close_enough(std::fabs(delta.dot(upVector)), 1.f)) + upVector = locXf.basis[1]; + newAct->SetTransform(zeus::lookAt(locXf.origin, locXf.origin + delta, upVector)); + } + mgr.AddObject(newAct); + x0_jointDescriptions.push_back(desc); + x0_jointDescriptions.back().SetCollisionActorId(newAct->GetUniqueId()); + } else { + TUniqueId newId = mgr.AllocateUniqueId(); + CCollisionActor* newAct = + new CCollisionActor(newId, area, x10_ownerId, active, modDesc.GetRadius(), modDesc.GetMass()); + newAct->SetTransform(locXf); + mgr.AddObject(newAct); + x0_jointDescriptions.push_back(CJointCollisionDescription::SphereCollision( + modDesc.GetPivotId(), modDesc.GetRadius(), modDesc.GetName(), 0.001f)); + x0_jointDescriptions.back().SetCollisionActorId(newId); + u32 numSeps = u32(dist / modDesc.GetMaxSeparation()); + if (numSeps) { + x0_jointDescriptions.reserve(x0_jointDescriptions.capacity() + numSeps); + float pitch = dist / float(numSeps + 1); + for (u32 i = 0; i < numSeps; ++i) { + float separation = pitch * float(i + 1); + x0_jointDescriptions.push_back(CJointCollisionDescription::SphereSubdivideCollision( + modDesc.GetPivotId(), modDesc.GetNextId(), modDesc.GetRadius(), separation, + CJointCollisionDescription::EOrientationType::One, modDesc.GetName(), 0.001f)); + TUniqueId newId2 = mgr.AllocateUniqueId(); + CCollisionActor* newAct2 = + new CCollisionActor(newId2, area, x10_ownerId, active, modDesc.GetRadius(), modDesc.GetMass()); + if (modDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero) { + newAct2->SetTransform(zeus::CTransform::Translate(locXf.origin + separation * locXf.basis[1])); + } else { + zeus::CVector3f delta = (locXf2.origin - locXf.origin).normalized(); + zeus::CVector3f upVector = locXf.basis[2]; + if (zeus::close_enough(std::fabs(delta.dot(upVector)), 1.f)) + upVector = locXf.basis[1]; + zeus::CTransform lookAt = zeus::lookAt(zeus::CVector3f::skZero, delta, upVector); + newAct2->SetTransform(zeus::CTransform::Translate(lookAt.basis[1] * separation + locXf.origin)); + } + mgr.AddObject(newAct2); + x0_jointDescriptions.back().SetCollisionActorId(newId2); } - else - { - TUniqueId newId = mgr.AllocateUniqueId(); - CCollisionActor* newAct; - if (modDesc.GetType() == CJointCollisionDescription::ECollisionType::Sphere) - newAct = new CCollisionActor(newId, area, x10_ownerId, active, - modDesc.GetRadius(), modDesc.GetMass()); - else if (modDesc.GetType() == CJointCollisionDescription::ECollisionType::OBB) - newAct = new CCollisionActor(newId, area, x10_ownerId, modDesc.GetBounds(), - modDesc.GetPivotPoint(), active, modDesc.GetMass()); - else - newAct = new CCollisionActor(newId, area, x10_ownerId, modDesc.GetBounds(), - active, modDesc.GetMass()); - newAct->SetTransform(locXf); - mgr.AddObject(newAct); - x0_jointDescriptions.push_back(desc); - x0_jointDescriptions.back().SetCollisionActorId(newId); + } + } + } else { + TUniqueId newId = mgr.AllocateUniqueId(); + CCollisionActor* newAct; + if (modDesc.GetType() == CJointCollisionDescription::ECollisionType::Sphere) + newAct = new CCollisionActor(newId, area, x10_ownerId, active, modDesc.GetRadius(), modDesc.GetMass()); + else if (modDesc.GetType() == CJointCollisionDescription::ECollisionType::OBB) + newAct = new CCollisionActor(newId, area, x10_ownerId, modDesc.GetBounds(), modDesc.GetPivotPoint(), active, + modDesc.GetMass()); + else + newAct = new CCollisionActor(newId, area, x10_ownerId, modDesc.GetBounds(), active, modDesc.GetMass()); + newAct->SetTransform(locXf); + mgr.AddObject(newAct); + x0_jointDescriptions.push_back(desc); + x0_jointDescriptions.back().SetCollisionActorId(newId); + } + } + } +} + +void CCollisionActorManager::Destroy(CStateManager& mgr) const { + for (const CJointCollisionDescription& desc : x0_jointDescriptions) + mgr.FreeScriptObject(desc.GetCollisionActorId()); + + const_cast(*this).x13_destroyed = true; +} + +void CCollisionActorManager::SetActive(CStateManager& mgr, bool active) { + x12_active = active; + for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) { + if (TCastToPtr act = mgr.ObjectById(jDesc.GetCollisionActorId())) { + bool curActive = act->GetActive(); + if (curActive != active) + act->SetActive(active); + + if (active) + Update(0.f, mgr, EUpdateOptions::WorldSpace); + } + } +} + +void CCollisionActorManager::AddMaterial(CStateManager& mgr, const CMaterialList& list) { + for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) + if (TCastToPtr act = mgr.ObjectById(jDesc.GetCollisionActorId())) + act->AddMaterial(list); +} + +void CCollisionActorManager::SetMovable(CStateManager& mgr, bool movable) { + if (x14_movable == movable) + return; + x14_movable = movable; + for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) { + if (TCastToPtr act = mgr.ObjectById(jDesc.GetCollisionActorId())) { + act->SetMovable(x14_movable); + act->SetUseInSortedLists(x14_movable); + } + } +} + +void CCollisionActorManager::Update(float dt, CStateManager& mgr, EUpdateOptions opts) { + if (!x14_movable) + SetMovable(mgr, true); + if (x12_active) { + if (TCastToPtr act = mgr.ObjectById(x10_ownerId)) { + const CAnimData& animData = *act->GetModelData()->GetAnimationData(); + zeus::CTransform actXf = act->GetTransform(); + zeus::CTransform scaleXf = zeus::CTransform::Scale(act->GetModelData()->GetScale()); + for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) { + if (TCastToPtr cAct = mgr.ObjectById(jDesc.GetCollisionActorId())) { + zeus::CTransform pivotXf = GetWRLocatorTransform(animData, jDesc.GetPivotId(), actXf, scaleXf); + zeus::CVector3f origin = pivotXf.origin; + if (jDesc.GetType() == CJointCollisionDescription::ECollisionType::OBB || + jDesc.GetType() == CJointCollisionDescription::ECollisionType::OBBAutoSize) { + if (jDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero) { + cAct->SetTransform(zeus::CQuaternion(pivotXf.basis).toTransform(cAct->GetTranslation())); + } else { + zeus::CTransform nextXf = GetWRLocatorTransform(animData, jDesc.GetNextId(), actXf, scaleXf); + cAct->SetTransform(zeus::CQuaternion(zeus::lookAt(pivotXf.origin, nextXf.origin, pivotXf.basis[2]).basis) + .toTransform(cAct->GetTranslation())); } - } - } -} - -void CCollisionActorManager::Destroy(CStateManager& mgr) const -{ - for (const CJointCollisionDescription& desc : x0_jointDescriptions) - mgr.FreeScriptObject(desc.GetCollisionActorId()); - - const_cast(*this).x13_destroyed = true; -} - -void CCollisionActorManager::SetActive(CStateManager& mgr, bool active) -{ - x12_active = active; - for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) - { - if (TCastToPtr act = mgr.ObjectById(jDesc.GetCollisionActorId())) - { - bool curActive = act->GetActive(); - if (curActive != active) - act->SetActive(active); - - if (active) - Update(0.f, mgr, EUpdateOptions::WorldSpace); - } - } -} - -void CCollisionActorManager::AddMaterial(CStateManager& mgr, const CMaterialList& list) -{ - for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) - if (TCastToPtr act = mgr.ObjectById(jDesc.GetCollisionActorId())) - act->AddMaterial(list); -} - -void CCollisionActorManager::SetMovable(CStateManager& mgr, bool movable) -{ - if (x14_movable == movable) - return; - x14_movable = movable; - for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) - { - if (TCastToPtr act = mgr.ObjectById(jDesc.GetCollisionActorId())) - { - act->SetMovable(x14_movable); - act->SetUseInSortedLists(x14_movable); - } - } -} - -void CCollisionActorManager::Update(float dt, CStateManager& mgr, EUpdateOptions opts) -{ - if (!x14_movable) - SetMovable(mgr, true); - if (x12_active) - { - if (TCastToPtr act = mgr.ObjectById(x10_ownerId)) - { - const CAnimData& animData = *act->GetModelData()->GetAnimationData(); - zeus::CTransform actXf = act->GetTransform(); - zeus::CTransform scaleXf = zeus::CTransform::Scale(act->GetModelData()->GetScale()); - for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) - { - if (TCastToPtr cAct = mgr.ObjectById(jDesc.GetCollisionActorId())) - { - zeus::CTransform pivotXf = GetWRLocatorTransform(animData, jDesc.GetPivotId(), actXf, scaleXf); - zeus::CVector3f origin = pivotXf.origin; - if (jDesc.GetType() == CJointCollisionDescription::ECollisionType::OBB || - jDesc.GetType() == CJointCollisionDescription::ECollisionType::OBBAutoSize) - { - if (jDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero) - { - cAct->SetTransform(zeus::CQuaternion(pivotXf.basis).toTransform(cAct->GetTranslation())); - } - else - { - zeus::CTransform nextXf = GetWRLocatorTransform(animData, jDesc.GetNextId(), actXf, scaleXf); - cAct->SetTransform( - zeus::CQuaternion(zeus::lookAt(pivotXf.origin, nextXf.origin, pivotXf.basis[2]).basis). - toTransform(cAct->GetTranslation())); - } - } - else if (jDesc.GetType() == CJointCollisionDescription::ECollisionType::SphereSubdivide) - { - if (jDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero) - { - origin += jDesc.GetMaxSeparation() * pivotXf.basis[1]; - } - else - { - zeus::CTransform nextXf = GetWRLocatorTransform(animData, jDesc.GetNextId(), actXf, scaleXf); - origin += zeus::lookAt(origin, nextXf.origin, pivotXf.basis[2]).basis[1] * - jDesc.GetMaxSeparation(); - } - } - if (opts == EUpdateOptions::ObjectSpace) - cAct->MoveToOR(cAct->GetTransform().transposeRotate(origin - cAct->GetTranslation()), dt); - else - cAct->SetTranslation(origin); - } + } else if (jDesc.GetType() == CJointCollisionDescription::ECollisionType::SphereSubdivide) { + if (jDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero) { + origin += jDesc.GetMaxSeparation() * pivotXf.basis[1]; + } else { + zeus::CTransform nextXf = GetWRLocatorTransform(animData, jDesc.GetNextId(), actXf, scaleXf); + origin += zeus::lookAt(origin, nextXf.origin, pivotXf.basis[2]).basis[1] * jDesc.GetMaxSeparation(); } + } + if (opts == EUpdateOptions::ObjectSpace) + cAct->MoveToOR(cAct->GetTransform().transposeRotate(origin - cAct->GetTranslation()), dt); + else + cAct->SetTranslation(origin); } + } } + } } zeus::CTransform CCollisionActorManager::GetWRLocatorTransform(const CAnimData& animData, CSegId id, const zeus::CTransform& worldXf, - const zeus::CTransform& localXf) -{ - zeus::CTransform locXf = animData.GetLocatorTransform(id, nullptr); - zeus::CVector3f origin = worldXf * (localXf * locXf.origin); - locXf = worldXf.multiplyIgnoreTranslation(locXf); - locXf.origin = origin; - return locXf; + const zeus::CTransform& localXf) { + zeus::CTransform locXf = animData.GetLocatorTransform(id, nullptr); + zeus::CVector3f origin = worldXf * (localXf * locXf.origin); + locXf = worldXf.multiplyIgnoreTranslation(locXf); + locXf.origin = origin; + return locXf; } -} +} // namespace urde diff --git a/Runtime/Collision/CCollisionActorManager.hpp b/Runtime/Collision/CCollisionActorManager.hpp index ae229d37c..d15d76724 100644 --- a/Runtime/Collision/CCollisionActorManager.hpp +++ b/Runtime/Collision/CCollisionActorManager.hpp @@ -4,42 +4,35 @@ #include "zeus/CAABox.hpp" #include "Collision/CJointCollisionDescription.hpp" -namespace urde -{ +namespace urde { class CMaterialList; class CAnimData; class CCollisionActor; class CStateManager; -class CCollisionActorManager -{ +class CCollisionActorManager { public: - enum class EUpdateOptions - { - ObjectSpace, - WorldSpace - }; + enum class EUpdateOptions { ObjectSpace, WorldSpace }; private: - std::vector x0_jointDescriptions; - TUniqueId x10_ownerId; - bool x12_active; - bool x13_destroyed = false; - bool x14_movable = true; + std::vector x0_jointDescriptions; + TUniqueId x10_ownerId; + bool x12_active; + bool x13_destroyed = false; + bool x14_movable = true; + public: - CCollisionActorManager(CStateManager& mgr, TUniqueId owner, TAreaId area, - const std::vector& descs, bool active); + CCollisionActorManager(CStateManager& mgr, TUniqueId owner, TAreaId area, + const std::vector& descs, bool active); - void Update(float dt, CStateManager& mgr, CCollisionActorManager::EUpdateOptions opts); - void Destroy(CStateManager& mgr) const; - void SetActive(CStateManager& mgr, bool active); - void AddMaterial(CStateManager& mgr, const CMaterialList& list); - void SetMovable(CStateManager& mgr, bool movable); - - u32 GetNumCollisionActors() const { return x0_jointDescriptions.size(); } - const CJointCollisionDescription& GetCollisionDescFromIndex(u32 i) const { return x0_jointDescriptions[i]; } - static zeus::CTransform GetWRLocatorTransform(const CAnimData& animData, CSegId id, - const zeus::CTransform& worldXf, - const zeus::CTransform& localXf); + void Update(float dt, CStateManager& mgr, CCollisionActorManager::EUpdateOptions opts); + void Destroy(CStateManager& mgr) const; + void SetActive(CStateManager& mgr, bool active); + void AddMaterial(CStateManager& mgr, const CMaterialList& list); + void SetMovable(CStateManager& mgr, bool movable); + u32 GetNumCollisionActors() const { return x0_jointDescriptions.size(); } + const CJointCollisionDescription& GetCollisionDescFromIndex(u32 i) const { return x0_jointDescriptions[i]; } + static zeus::CTransform GetWRLocatorTransform(const CAnimData& animData, CSegId id, const zeus::CTransform& worldXf, + const zeus::CTransform& localXf); }; -} +} // namespace urde diff --git a/Runtime/Collision/CCollisionEdge.cpp b/Runtime/Collision/CCollisionEdge.cpp index 9191dd11d..4a2db3fdd 100644 --- a/Runtime/Collision/CCollisionEdge.cpp +++ b/Runtime/Collision/CCollisionEdge.cpp @@ -1,10 +1,8 @@ #include "CCollisionEdge.hpp" -namespace urde -{ -CCollisionEdge::CCollisionEdge(CInputStream& in) -{ - x0_index1 = in.readUint16Big(); - x2_index2 = in.readUint16Big(); -} +namespace urde { +CCollisionEdge::CCollisionEdge(CInputStream& in) { + x0_index1 = in.readUint16Big(); + x2_index2 = in.readUint16Big(); } +} // namespace urde diff --git a/Runtime/Collision/CCollisionEdge.hpp b/Runtime/Collision/CCollisionEdge.hpp index b9ca0b394..5a84b0454 100644 --- a/Runtime/Collision/CCollisionEdge.hpp +++ b/Runtime/Collision/CCollisionEdge.hpp @@ -2,24 +2,21 @@ #include "RetroTypes.hpp" -namespace urde -{ -class CCollisionEdge -{ - u16 x0_index1 = -1; - u16 x2_index2 = -1; +namespace urde { +class CCollisionEdge { + u16 x0_index1 = -1; + u16 x2_index2 = -1; + public: - CCollisionEdge()=default; - CCollisionEdge(CInputStream&); + CCollisionEdge() = default; + CCollisionEdge(CInputStream&); - u16 GetVertIndex1() const { return x0_index1; } - u16 GetVertIndex2() const { return x2_index2; } + u16 GetVertIndex1() const { return x0_index1; } + u16 GetVertIndex2() const { return x2_index2; } - void swapBig() - { - x0_index1 = hecl::SBig(x0_index1); - x2_index2 = hecl::SBig(x2_index2); - } + void swapBig() { + x0_index1 = hecl::SBig(x0_index1); + x2_index2 = hecl::SBig(x2_index2); + } }; -} - +} // namespace urde diff --git a/Runtime/Collision/CCollisionInfo.cpp b/Runtime/Collision/CCollisionInfo.cpp index 8072fbc37..62f9e227e 100644 --- a/Runtime/Collision/CCollisionInfo.cpp +++ b/Runtime/Collision/CCollisionInfo.cpp @@ -1,32 +1,26 @@ #include "CCollisionInfo.hpp" -namespace urde -{ +namespace urde { -CCollisionInfo CCollisionInfo::GetSwapped() const -{ - CCollisionInfo ret; - ret.x0_point = x0_point; - ret.xc_extentX = xc_extentX; - ret.x30_valid = x30_valid; - ret.x31_hasExtents = x31_hasExtents; - ret.x38_materialLeft = x40_materialRight; - ret.x40_materialRight = x38_materialLeft; - ret.x48_normalLeft = x54_normalRight; - ret.x54_normalRight = x48_normalLeft; - return ret; +CCollisionInfo CCollisionInfo::GetSwapped() const { + CCollisionInfo ret; + ret.x0_point = x0_point; + ret.xc_extentX = xc_extentX; + ret.x30_valid = x30_valid; + ret.x31_hasExtents = x31_hasExtents; + ret.x38_materialLeft = x40_materialRight; + ret.x40_materialRight = x38_materialLeft; + ret.x48_normalLeft = x54_normalRight; + ret.x54_normalRight = x48_normalLeft; + return ret; } -void CCollisionInfo::Swap() -{ - x48_normalLeft = -x48_normalLeft; - x54_normalRight = -x54_normalRight; - std::swap(x38_materialLeft, x40_materialRight); +void CCollisionInfo::Swap() { + x48_normalLeft = -x48_normalLeft; + x54_normalRight = -x54_normalRight; + std::swap(x38_materialLeft, x40_materialRight); } -zeus::CVector3f CCollisionInfo::GetExtreme() const -{ - return x0_point + xc_extentX + x18_extentY + x24_extentZ; -} +zeus::CVector3f CCollisionInfo::GetExtreme() const { return x0_point + xc_extentX + x18_extentY + x24_extentZ; } -} +} // namespace urde diff --git a/Runtime/Collision/CCollisionInfo.hpp b/Runtime/Collision/CCollisionInfo.hpp index 9bbd42ec7..57a1c5f3f 100644 --- a/Runtime/Collision/CCollisionInfo.hpp +++ b/Runtime/Collision/CCollisionInfo.hpp @@ -5,51 +5,61 @@ #include "zeus/CAABox.hpp" #include "zeus/CMatrix3f.hpp" -namespace urde -{ -class CCollisionInfo -{ - zeus::CVector3f x0_point; - zeus::CVector3f xc_extentX; - zeus::CVector3f x18_extentY; - zeus::CVector3f x24_extentZ; - bool x30_valid = false; - bool x31_hasExtents = false; - CMaterialList x38_materialLeft; - CMaterialList x40_materialRight; - zeus::CVector3f x48_normalLeft; - zeus::CVector3f x54_normalRight; -public: - CCollisionInfo() = default; - CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2, - const zeus::CVector3f& normalLeft, const zeus::CVector3f& normalRight) - : x0_point(point), x30_valid(true), x31_hasExtents(false), x38_materialLeft(list2), x40_materialRight(list1), - x48_normalLeft(normalLeft), x54_normalRight(normalRight) {} - CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2, - const zeus::CVector3f& normal) - : x0_point(point), x30_valid(true), x31_hasExtents(false), x38_materialLeft(list2), x40_materialRight(list1), - x48_normalLeft(normal), x54_normalRight(-normal) {} - CCollisionInfo(const zeus::CAABox& aabox, const CMaterialList& list1, const CMaterialList& list2, - const zeus::CVector3f& normalLeft, const zeus::CVector3f& normalRight) - : x0_point(aabox.min), - xc_extentX(aabox.max.x() - aabox.min.x(), 0.f, 0.f), - x18_extentY(0.f, aabox.max.y() - aabox.min.y(), 0.f), - x24_extentZ(0.f, 0.f, aabox.max.z() - aabox.min.z()), - x30_valid(true), x31_hasExtents(true), x38_materialLeft(list2), - x40_materialRight(list1), x48_normalLeft(normalLeft), - x54_normalRight(normalRight) - {} +namespace urde { +class CCollisionInfo { + zeus::CVector3f x0_point; + zeus::CVector3f xc_extentX; + zeus::CVector3f x18_extentY; + zeus::CVector3f x24_extentZ; + bool x30_valid = false; + bool x31_hasExtents = false; + CMaterialList x38_materialLeft; + CMaterialList x40_materialRight; + zeus::CVector3f x48_normalLeft; + zeus::CVector3f x54_normalRight; - CCollisionInfo GetSwapped() const; - bool IsValid() const { return x30_valid; } - const CMaterialList& GetMaterialLeft() const { return x38_materialLeft; } - const CMaterialList& GetMaterialRight() const { return x40_materialRight; } - zeus::CVector3f GetExtreme() const; - void Swap(); - const zeus::CVector3f& GetNormalLeft() const { return x48_normalLeft; } - const zeus::CVector3f& GetNormalRight() const { return x54_normalRight; } - const zeus::CVector3f& GetPoint() const { return x0_point; } +public: + CCollisionInfo() = default; + CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2, + const zeus::CVector3f& normalLeft, const zeus::CVector3f& normalRight) + : x0_point(point) + , x30_valid(true) + , x31_hasExtents(false) + , x38_materialLeft(list2) + , x40_materialRight(list1) + , x48_normalLeft(normalLeft) + , x54_normalRight(normalRight) {} + CCollisionInfo(const zeus::CVector3f& point, const CMaterialList& list1, const CMaterialList& list2, + const zeus::CVector3f& normal) + : x0_point(point) + , x30_valid(true) + , x31_hasExtents(false) + , x38_materialLeft(list2) + , x40_materialRight(list1) + , x48_normalLeft(normal) + , x54_normalRight(-normal) {} + CCollisionInfo(const zeus::CAABox& aabox, const CMaterialList& list1, const CMaterialList& list2, + const zeus::CVector3f& normalLeft, const zeus::CVector3f& normalRight) + : x0_point(aabox.min) + , xc_extentX(aabox.max.x() - aabox.min.x(), 0.f, 0.f) + , x18_extentY(0.f, aabox.max.y() - aabox.min.y(), 0.f) + , x24_extentZ(0.f, 0.f, aabox.max.z() - aabox.min.z()) + , x30_valid(true) + , x31_hasExtents(true) + , x38_materialLeft(list2) + , x40_materialRight(list1) + , x48_normalLeft(normalLeft) + , x54_normalRight(normalRight) {} + + CCollisionInfo GetSwapped() const; + bool IsValid() const { return x30_valid; } + const CMaterialList& GetMaterialLeft() const { return x38_materialLeft; } + const CMaterialList& GetMaterialRight() const { return x40_materialRight; } + zeus::CVector3f GetExtreme() const; + void Swap(); + const zeus::CVector3f& GetNormalLeft() const { return x48_normalLeft; } + const zeus::CVector3f& GetNormalRight() const { return x54_normalRight; } + const zeus::CVector3f& GetPoint() const { return x0_point; } }; -} - +} // namespace urde diff --git a/Runtime/Collision/CCollisionInfoList.hpp b/Runtime/Collision/CCollisionInfoList.hpp index 8dd171ed9..866ac82fe 100644 --- a/Runtime/Collision/CCollisionInfoList.hpp +++ b/Runtime/Collision/CCollisionInfoList.hpp @@ -3,36 +3,33 @@ #include "RetroTypes.hpp" #include "CCollisionInfo.hpp" -namespace urde -{ -class CCollisionInfoList -{ - rstl::reserved_vector x0_list; +namespace urde { +class CCollisionInfoList { + rstl::reserved_vector x0_list; + public: - CCollisionInfoList() = default; + CCollisionInfoList() = default; - void GetAverageLeftNormal() const; - void GetAveragePoint() const; - void GetUnionOfAllLeftMaterials() const; - size_t GetCount() const { return x0_list.size(); } - void Swap(s32); + void GetAverageLeftNormal() const; + void GetAveragePoint() const; + void GetUnionOfAllLeftMaterials() const; + size_t GetCount() const { return x0_list.size(); } + void Swap(s32); - void Add(const CCollisionInfo& info, bool swap) - { - if (x0_list.size() == 32) - return; - if (!swap) - x0_list.push_back(info); - else - x0_list.push_back(info.GetSwapped()); - } - void Clear() { x0_list.clear(); } - const CCollisionInfo& Front() const { return x0_list.front(); } - const CCollisionInfo& GetItem(int i) const { return x0_list[i]; } - rstl::reserved_vector::iterator end() { return x0_list.end(); } - rstl::reserved_vector::const_iterator end() const { return x0_list.end(); } - rstl::reserved_vector::iterator begin() { return x0_list.begin(); } - rstl::reserved_vector::const_iterator begin() const { return x0_list.begin(); } + void Add(const CCollisionInfo& info, bool swap) { + if (x0_list.size() == 32) + return; + if (!swap) + x0_list.push_back(info); + else + x0_list.push_back(info.GetSwapped()); + } + void Clear() { x0_list.clear(); } + const CCollisionInfo& Front() const { return x0_list.front(); } + const CCollisionInfo& GetItem(int i) const { return x0_list[i]; } + rstl::reserved_vector::iterator end() { return x0_list.end(); } + rstl::reserved_vector::const_iterator end() const { return x0_list.end(); } + rstl::reserved_vector::iterator begin() { return x0_list.begin(); } + rstl::reserved_vector::const_iterator begin() const { return x0_list.begin(); } }; -} - +} // namespace urde diff --git a/Runtime/Collision/CCollisionPrimitive.cpp b/Runtime/Collision/CCollisionPrimitive.cpp index b35b62aaf..a2b768045 100644 --- a/Runtime/Collision/CCollisionPrimitive.cpp +++ b/Runtime/Collision/CCollisionPrimitive.cpp @@ -4,8 +4,7 @@ #include "InternalColliders.hpp" #include "CCollisionInfoList.hpp" -namespace urde -{ +namespace urde { s32 CCollisionPrimitive::sNumTypes = 0; bool CCollisionPrimitive::sInitComplete = false; bool CCollisionPrimitive::sTypesAdded = false; @@ -26,321 +25,264 @@ void CCollisionPrimitive::SetMaterial(const CMaterialList& material) { x8_materi const CMaterialList& CCollisionPrimitive::GetMaterial() const { return x8_material; } CRayCastResult CCollisionPrimitive::CastRay(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length, - const CMaterialFilter& filter, const zeus::CTransform& xf) const -{ - return CastRayInternal(CInternalRayCastStructure(start, dir, length, xf, filter)); + const CMaterialFilter& filter, const zeus::CTransform& xf) const { + return CastRayInternal(CInternalRayCastStructure(start, dir, length, xf, filter)); } -bool CCollisionPrimitive::InternalCollide(const CInternalCollisionStructure& collision, - CCollisionInfoList& list) -{ - u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex(); - u32 idx1 = collision.GetRight().GetPrim().GetTableIndex(); +bool CCollisionPrimitive::InternalCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list) { + u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex(); + u32 idx1 = collision.GetRight().GetPrim().GetTableIndex(); - ComparisonFunc func; - if (idx0 == -1 || idx1 == -1) - { - sNullCollider = nullptr; - func = sNullCollider; - } - else - { - func = (*sTableOfCollidables)[sNumTypes * idx1 + idx0]; - } + ComparisonFunc func; + if (idx0 == -1 || idx1 == -1) { + sNullCollider = nullptr; + func = sNullCollider; + } else { + func = (*sTableOfCollidables)[sNumTypes * idx1 + idx0]; + } - if (func) - { - if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || - !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) - return false; - return func(collision, list); - } + if (func) { + if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || + !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) + return false; + return func(collision, list); + } - if (idx0 == -1 || idx1 == -1) - { - sNullCollider = nullptr; - func = sNullCollider; - } - else - { - func = (*sTableOfCollidables)[sNumTypes * idx0 + idx1]; - } + if (idx0 == -1 || idx1 == -1) { + sNullCollider = nullptr; + func = sNullCollider; + } else { + func = (*sTableOfCollidables)[sNumTypes * idx0 + idx1]; + } - if (func) - { - if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || - !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) - return false; - CInternalCollisionStructure swappedCollision(collision.GetRight(), collision.GetLeft()); - u32 startListCount = list.GetCount(); - if (func(swappedCollision, list)) - { - for (auto it = list.begin() + startListCount ; it != list.end() ; ++it) - it->Swap(); - return true; - } + if (func) { + if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || + !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) + return false; + CInternalCollisionStructure swappedCollision(collision.GetRight(), collision.GetLeft()); + u32 startListCount = list.GetCount(); + if (func(swappedCollision, list)) { + for (auto it = list.begin() + startListCount; it != list.end(); ++it) + it->Swap(); + return true; } + } - return false; + return false; } bool CCollisionPrimitive::Collide(const CInternalCollisionStructure::CPrimDesc& prim0, - const CInternalCollisionStructure::CPrimDesc& prim1, - CCollisionInfoList& list) -{ - return InternalCollide({prim0, prim1}, list); + const CInternalCollisionStructure::CPrimDesc& prim1, CCollisionInfoList& list) { + return InternalCollide({prim0, prim1}, list); } -bool CCollisionPrimitive::InternalCollideBoolean(const CInternalCollisionStructure& collision) -{ - u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex(); - u32 idx1 = collision.GetRight().GetPrim().GetTableIndex(); +bool CCollisionPrimitive::InternalCollideBoolean(const CInternalCollisionStructure& collision) { + u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex(); + u32 idx1 = collision.GetRight().GetPrim().GetTableIndex(); - BooleanComparisonFunc func; - if (idx0 == -1 || idx1 == -1) - { - sNullBooleanCollider = nullptr; - func = sNullBooleanCollider; - } - else - { - func = (*sTableOfBooleanCollidables)[sNumTypes * idx1 + idx0]; - } + BooleanComparisonFunc func; + if (idx0 == -1 || idx1 == -1) { + sNullBooleanCollider = nullptr; + func = sNullBooleanCollider; + } else { + func = (*sTableOfBooleanCollidables)[sNumTypes * idx1 + idx0]; + } - if (func) - { - if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || - !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) - return false; - return func(collision); - } + if (func) { + if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || + !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) + return false; + return func(collision); + } - if (idx0 == -1 || idx1 == -1) - { - sNullBooleanCollider = nullptr; - func = sNullBooleanCollider; - } - else - { - func = (*sTableOfBooleanCollidables)[sNumTypes * idx0 + idx1]; - } + if (idx0 == -1 || idx1 == -1) { + sNullBooleanCollider = nullptr; + func = sNullBooleanCollider; + } else { + func = (*sTableOfBooleanCollidables)[sNumTypes * idx0 + idx1]; + } - if (func) - { - if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || - !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) - return false; - CInternalCollisionStructure swappedCollision(collision.GetRight(), collision.GetLeft()); - return func(swappedCollision); - } + if (func) { + if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || + !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) + return false; + CInternalCollisionStructure swappedCollision(collision.GetRight(), collision.GetLeft()); + return func(swappedCollision); + } - CCollisionInfoList list; - return InternalCollide(collision, list); + CCollisionInfoList list; + return InternalCollide(collision, list); } bool CCollisionPrimitive::CollideBoolean(const CInternalCollisionStructure::CPrimDesc& prim0, - const CInternalCollisionStructure::CPrimDesc& prim1) -{ - return InternalCollideBoolean({prim0, prim1}); + const CInternalCollisionStructure::CPrimDesc& prim1) { + return InternalCollideBoolean({prim0, prim1}); } bool CCollisionPrimitive::InternalCollideMoving(const CInternalCollisionStructure& collision, - const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& infoOut) -{ - u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex(); - u32 idx1 = collision.GetRight().GetPrim().GetTableIndex(); + const zeus::CVector3f& dir, double& dOut, CCollisionInfo& infoOut) { + u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex(); + u32 idx1 = collision.GetRight().GetPrim().GetTableIndex(); - MovingComparisonFunc func; - if (idx0 == -1 || idx1 == -1) - { - sNullMovingCollider = nullptr; - func = sNullMovingCollider; - } - else - { - func = (*sTableOfMovingCollidables)[sNumTypes * idx1 + idx0]; - } + MovingComparisonFunc func; + if (idx0 == -1 || idx1 == -1) { + sNullMovingCollider = nullptr; + func = sNullMovingCollider; + } else { + func = (*sTableOfMovingCollidables)[sNumTypes * idx1 + idx0]; + } - if (func) - { - if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || - !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) - return false; - return func(collision, dir, dOut, infoOut); - } + if (func) { + if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || + !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) + return false; + return func(collision, dir, dOut, infoOut); + } - return false; + return false; } bool CCollisionPrimitive::CollideMoving(const CInternalCollisionStructure::CPrimDesc& prim0, - const CInternalCollisionStructure::CPrimDesc& prim1, - const zeus::CVector3f& dir, - double& dOut, - CCollisionInfo& infoOut) -{ - return InternalCollideMoving({prim0, prim1}, dir, dOut, infoOut); + const CInternalCollisionStructure::CPrimDesc& prim1, const zeus::CVector3f& dir, + double& dOut, CCollisionInfo& infoOut) { + return InternalCollideMoving({prim0, prim1}, dir, dOut, infoOut); } -void CCollisionPrimitive::InitBeginTypes() -{ - sCollisionTypeList.reset(new std::vector()); - sCollisionTypeList->reserve(3); - sTypesAdding = true; - InternalColliders::AddTypes(); +void CCollisionPrimitive::InitBeginTypes() { + sCollisionTypeList.reset(new std::vector()); + sCollisionTypeList->reserve(3); + sTypesAdding = true; + InternalColliders::AddTypes(); } -void CCollisionPrimitive::InitAddType(const CCollisionPrimitive::Type& tp) -{ - tp.GetSetter()(sCollisionTypeList->size()); - sCollisionTypeList->push_back(tp); +void CCollisionPrimitive::InitAddType(const CCollisionPrimitive::Type& tp) { + tp.GetSetter()(sCollisionTypeList->size()); + sCollisionTypeList->push_back(tp); } -void CCollisionPrimitive::InitEndTypes() -{ - sCollisionTypeList->shrink_to_fit(); - sNumTypes = sCollisionTypeList->size(); - sTypesAdding = false; - sTypesAdded = true; +void CCollisionPrimitive::InitEndTypes() { + sCollisionTypeList->shrink_to_fit(); + sNumTypes = sCollisionTypeList->size(); + sTypesAdding = false; + sTypesAdded = true; } -void CCollisionPrimitive::InitBeginColliders() -{ - sTableOfCollidables.reset(new std::vector()); - sTableOfBooleanCollidables.reset(new std::vector()); - sTableOfMovingCollidables.reset(new std::vector()); - size_t tableSz = sCollisionTypeList->size() * sCollisionTypeList->size(); - sTableOfCollidables->resize(tableSz); - sTableOfBooleanCollidables->resize(tableSz); - sTableOfMovingCollidables->resize(tableSz); - sCollidersAdding = true; - InternalColliders::AddColliders(); +void CCollisionPrimitive::InitBeginColliders() { + sTableOfCollidables.reset(new std::vector()); + sTableOfBooleanCollidables.reset(new std::vector()); + sTableOfMovingCollidables.reset(new std::vector()); + size_t tableSz = sCollisionTypeList->size() * sCollisionTypeList->size(); + sTableOfCollidables->resize(tableSz); + sTableOfBooleanCollidables->resize(tableSz); + sTableOfMovingCollidables->resize(tableSz); + sCollidersAdding = true; + InternalColliders::AddColliders(); } -void CCollisionPrimitive::InitAddBooleanCollider(const CCollisionPrimitive::BooleanComparison& cmp) -{ - int idx0 = -1; - for (int i=0 ; isize() ; ++i) - { - if (!strcmp(cmp.GetType1(), (*sCollisionTypeList)[i].GetInfo())) - { - idx0 = i; - break; - } +void CCollisionPrimitive::InitAddBooleanCollider(const CCollisionPrimitive::BooleanComparison& cmp) { + int idx0 = -1; + for (int i = 0; i < sCollisionTypeList->size(); ++i) { + if (!strcmp(cmp.GetType1(), (*sCollisionTypeList)[i].GetInfo())) { + idx0 = i; + break; } + } - int idx1 = -1; - for (int i=0 ; isize() ; ++i) - { - if (!strcmp(cmp.GetType2(), (*sCollisionTypeList)[i].GetInfo())) - { - idx1 = i; - break; - } + int idx1 = -1; + for (int i = 0; i < sCollisionTypeList->size(); ++i) { + if (!strcmp(cmp.GetType2(), (*sCollisionTypeList)[i].GetInfo())) { + idx1 = i; + break; } + } - if (idx0 < 0 || idx1 < 0 || idx0 >= sNumTypes || idx1 >= sNumTypes) - return; + if (idx0 < 0 || idx1 < 0 || idx0 >= sNumTypes || idx1 >= sNumTypes) + return; - BooleanComparisonFunc& funcOut = - (idx0 == -1 || idx1 == -1) ? sNullBooleanCollider : (*sTableOfBooleanCollidables)[idx1 * sNumTypes + idx0]; - funcOut = cmp.GetCollider(); + BooleanComparisonFunc& funcOut = + (idx0 == -1 || idx1 == -1) ? sNullBooleanCollider : (*sTableOfBooleanCollidables)[idx1 * sNumTypes + idx0]; + funcOut = cmp.GetCollider(); } -void CCollisionPrimitive::InitAddBooleanCollider(BooleanComparisonFunc cmp, const char* a, const char* b) -{ - InitAddBooleanCollider({cmp, a, b}); +void CCollisionPrimitive::InitAddBooleanCollider(BooleanComparisonFunc cmp, const char* a, const char* b) { + InitAddBooleanCollider({cmp, a, b}); } -void CCollisionPrimitive::InitAddMovingCollider(const CCollisionPrimitive::MovingComparison& cmp) -{ - int idx0 = -1; - for (int i=0 ; isize() ; ++i) - { - if (!strcmp(cmp.GetType1(), (*sCollisionTypeList)[i].GetInfo())) - { - idx0 = i; - break; - } +void CCollisionPrimitive::InitAddMovingCollider(const CCollisionPrimitive::MovingComparison& cmp) { + int idx0 = -1; + for (int i = 0; i < sCollisionTypeList->size(); ++i) { + if (!strcmp(cmp.GetType1(), (*sCollisionTypeList)[i].GetInfo())) { + idx0 = i; + break; } + } - int idx1 = -1; - for (int i=0 ; isize() ; ++i) - { - if (!strcmp(cmp.GetType2(), (*sCollisionTypeList)[i].GetInfo())) - { - idx1 = i; - break; - } + int idx1 = -1; + for (int i = 0; i < sCollisionTypeList->size(); ++i) { + if (!strcmp(cmp.GetType2(), (*sCollisionTypeList)[i].GetInfo())) { + idx1 = i; + break; } + } - if (idx0 < 0 || idx1 < 0 || idx0 >= sNumTypes || idx1 >= sNumTypes) - return; + if (idx0 < 0 || idx1 < 0 || idx0 >= sNumTypes || idx1 >= sNumTypes) + return; - MovingComparisonFunc& funcOut = - (idx0 == -1 || idx1 == -1) ? sNullMovingCollider : (*sTableOfMovingCollidables)[idx1 * sNumTypes + idx0]; - funcOut = cmp.GetCollider(); + MovingComparisonFunc& funcOut = + (idx0 == -1 || idx1 == -1) ? sNullMovingCollider : (*sTableOfMovingCollidables)[idx1 * sNumTypes + idx0]; + funcOut = cmp.GetCollider(); } -void CCollisionPrimitive::InitAddMovingCollider(MovingComparisonFunc cmp, const char* a, const char* b) -{ - InitAddMovingCollider({cmp, a, b}); +void CCollisionPrimitive::InitAddMovingCollider(MovingComparisonFunc cmp, const char* a, const char* b) { + InitAddMovingCollider({cmp, a, b}); } -void CCollisionPrimitive::InitAddCollider(const CCollisionPrimitive::Comparison& cmp) -{ - int idx0 = -1; - for (int i=0 ; isize() ; ++i) - { - if (!strcmp(cmp.GetType1(), (*sCollisionTypeList)[i].GetInfo())) - { - idx0 = i; - break; - } +void CCollisionPrimitive::InitAddCollider(const CCollisionPrimitive::Comparison& cmp) { + int idx0 = -1; + for (int i = 0; i < sCollisionTypeList->size(); ++i) { + if (!strcmp(cmp.GetType1(), (*sCollisionTypeList)[i].GetInfo())) { + idx0 = i; + break; } + } - int idx1 = -1; - for (int i=0 ; isize() ; ++i) - { - if (!strcmp(cmp.GetType2(), (*sCollisionTypeList)[i].GetInfo())) - { - idx1 = i; - break; - } + int idx1 = -1; + for (int i = 0; i < sCollisionTypeList->size(); ++i) { + if (!strcmp(cmp.GetType2(), (*sCollisionTypeList)[i].GetInfo())) { + idx1 = i; + break; } + } - if (idx0 < 0 || idx1 < 0 || idx0 >= sNumTypes || idx1 >= sNumTypes) - return; + if (idx0 < 0 || idx1 < 0 || idx0 >= sNumTypes || idx1 >= sNumTypes) + return; - ComparisonFunc& funcOut = - (idx0 == -1 || idx1 == -1) ? sNullCollider : (*sTableOfCollidables)[idx1 * sNumTypes + idx0]; - funcOut = cmp.GetCollider(); + ComparisonFunc& funcOut = + (idx0 == -1 || idx1 == -1) ? sNullCollider : (*sTableOfCollidables)[idx1 * sNumTypes + idx0]; + funcOut = cmp.GetCollider(); } -void CCollisionPrimitive::InitAddCollider(ComparisonFunc cmp, const char* a, const char* b) -{ - InitAddCollider({cmp, a, b}); +void CCollisionPrimitive::InitAddCollider(ComparisonFunc cmp, const char* a, const char* b) { + InitAddCollider({cmp, a, b}); } -void CCollisionPrimitive::InitEndColliders() -{ - sCollidersAdding = false; - sCollidersAdded = true; - sInitComplete = true; +void CCollisionPrimitive::InitEndColliders() { + sCollidersAdding = false; + sCollidersAdded = true; + sInitComplete = true; } -void CCollisionPrimitive::Uninitialize() -{ - sInitComplete = false; - sCollidersAdding = false; - sCollidersAdded = false; - sTypesAdding = false; - sTypesAdded = false; - sNumTypes = 0; - sCollisionTypeList.reset(); - sTableOfCollidables.reset(); - sTableOfMovingCollidables.reset(); - sTableOfBooleanCollidables.reset(); +void CCollisionPrimitive::Uninitialize() { + sInitComplete = false; + sCollidersAdding = false; + sCollidersAdded = false; + sTypesAdding = false; + sTypesAdded = false; + sNumTypes = 0; + sCollisionTypeList.reset(); + sTableOfCollidables.reset(); + sTableOfMovingCollidables.reset(); + sTableOfBooleanCollidables.reset(); } -} +} // namespace urde diff --git a/Runtime/Collision/CCollisionPrimitive.hpp b/Runtime/Collision/CCollisionPrimitive.hpp index 1088119ab..1bd1bbac1 100644 --- a/Runtime/Collision/CCollisionPrimitive.hpp +++ b/Runtime/Collision/CCollisionPrimitive.hpp @@ -6,174 +6,157 @@ #include -namespace urde -{ +namespace urde { class CCollisionPrimitive; class CMaterialFilter; -class CInternalCollisionStructure -{ +class CInternalCollisionStructure { public: - class CPrimDesc - { - const CCollisionPrimitive& x0_prim; - const CMaterialFilter& x4_filter; - zeus::CTransform x8_xf; - public: - CPrimDesc(const CCollisionPrimitive& prim, const CMaterialFilter& filter, - const zeus::CTransform& xf) - : x0_prim(prim), x4_filter(filter), x8_xf(xf) {} - const CCollisionPrimitive& GetPrim() const { return x0_prim; } - const CMaterialFilter& GetFilter() const { return x4_filter; } - const zeus::CTransform& GetTransform() const { return x8_xf; } - }; + class CPrimDesc { + const CCollisionPrimitive& x0_prim; + const CMaterialFilter& x4_filter; + zeus::CTransform x8_xf; + + public: + CPrimDesc(const CCollisionPrimitive& prim, const CMaterialFilter& filter, const zeus::CTransform& xf) + : x0_prim(prim), x4_filter(filter), x8_xf(xf) {} + const CCollisionPrimitive& GetPrim() const { return x0_prim; } + const CMaterialFilter& GetFilter() const { return x4_filter; } + const zeus::CTransform& GetTransform() const { return x8_xf; } + }; + private: - CPrimDesc x0_p0; - CPrimDesc x38_p1; + CPrimDesc x0_p0; + CPrimDesc x38_p1; + public: - CInternalCollisionStructure(const CPrimDesc& p0, const CPrimDesc& p1) - : x0_p0(p0), x38_p1(p1) {} - const CPrimDesc& GetLeft() const { return x0_p0; } - const CPrimDesc& GetRight() const { return x38_p1; } + CInternalCollisionStructure(const CPrimDesc& p0, const CPrimDesc& p1) : x0_p0(p0), x38_p1(p1) {} + const CPrimDesc& GetLeft() const { return x0_p0; } + const CPrimDesc& GetRight() const { return x38_p1; } }; class COBBTree; class CCollisionInfo; class CCollisionInfoList; class CInternalRayCastStructure; -typedef bool(*ComparisonFunc)(const CInternalCollisionStructure&, CCollisionInfoList&); -typedef bool(*MovingComparisonFunc)(const CInternalCollisionStructure&, const zeus::CVector3f&, - double&, CCollisionInfo&); -typedef bool(*BooleanComparisonFunc)(const CInternalCollisionStructure&); -typedef void(*PrimitiveSetter)(u32); +typedef bool (*ComparisonFunc)(const CInternalCollisionStructure&, CCollisionInfoList&); +typedef bool (*MovingComparisonFunc)(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, + CCollisionInfo&); +typedef bool (*BooleanComparisonFunc)(const CInternalCollisionStructure&); +typedef void (*PrimitiveSetter)(u32); -class CCollisionPrimitive -{ +class CCollisionPrimitive { public: - class Type - { - PrimitiveSetter x0_setter; - const char* x4_info; + class Type { + PrimitiveSetter x0_setter; + const char* x4_info; - public: - Type() = default; - Type(PrimitiveSetter setter, const char* info) - : x0_setter(setter), x4_info(info) {} + public: + Type() = default; + Type(PrimitiveSetter setter, const char* info) : x0_setter(setter), x4_info(info) {} - const char* GetInfo() const { return x4_info; } - PrimitiveSetter GetSetter() const { return x0_setter; } - }; + const char* GetInfo() const { return x4_info; } + PrimitiveSetter GetSetter() const { return x0_setter; } + }; - class Comparison - { - ComparisonFunc x0_collider; - const char* x4_type1; - const char* x8_type2; + class Comparison { + ComparisonFunc x0_collider; + const char* x4_type1; + const char* x8_type2; - public: - Comparison(ComparisonFunc collider, const char* type1, const char* type2) - : x0_collider(collider), x4_type1(type1), x8_type2(type2) - { - } + public: + Comparison(ComparisonFunc collider, const char* type1, const char* type2) + : x0_collider(collider), x4_type1(type1), x8_type2(type2) {} - ComparisonFunc GetCollider() const { return x0_collider; } - const char* GetType1() const { return x4_type1; } - const char* GetType2() const { return x8_type2; } - }; + ComparisonFunc GetCollider() const { return x0_collider; } + const char* GetType1() const { return x4_type1; } + const char* GetType2() const { return x8_type2; } + }; - class MovingComparison - { - MovingComparisonFunc x0_collider; - const char* x4_type1; - const char* x8_type2; + class MovingComparison { + MovingComparisonFunc x0_collider; + const char* x4_type1; + const char* x8_type2; - public: - MovingComparison(MovingComparisonFunc collider, const char* type1, const char* type2) - : x0_collider(collider), x4_type1(type1), x8_type2(type2) - { - } + public: + MovingComparison(MovingComparisonFunc collider, const char* type1, const char* type2) + : x0_collider(collider), x4_type1(type1), x8_type2(type2) {} - MovingComparisonFunc GetCollider() const { return x0_collider; } - const char* GetType1() const { return x4_type1; } - const char* GetType2() const { return x8_type2; } - }; + MovingComparisonFunc GetCollider() const { return x0_collider; } + const char* GetType1() const { return x4_type1; } + const char* GetType2() const { return x8_type2; } + }; - class BooleanComparison - { - BooleanComparisonFunc x0_collider; - const char* x4_type1; - const char* x8_type2; + class BooleanComparison { + BooleanComparisonFunc x0_collider; + const char* x4_type1; + const char* x8_type2; - public: - BooleanComparison(BooleanComparisonFunc collider, const char* type1, const char* type2) - : x0_collider(collider), x4_type1(type1), x8_type2(type2) - { - } + public: + BooleanComparison(BooleanComparisonFunc collider, const char* type1, const char* type2) + : x0_collider(collider), x4_type1(type1), x8_type2(type2) {} + + BooleanComparisonFunc GetCollider() const { return x0_collider; } + const char* GetType1() const { return x4_type1; } + const char* GetType2() const { return x8_type2; } + }; - BooleanComparisonFunc GetCollider() const { return x0_collider; } - const char* GetType1() const { return x4_type1; } - const char* GetType2() const { return x8_type2; } - }; private: - CMaterialList x8_material; - static s32 sNumTypes; - static bool sInitComplete; - static bool sTypesAdded; - static bool sTypesAdding; - static bool sCollidersAdded; - static bool sCollidersAdding; - static std::unique_ptr> sCollisionTypeList; - static std::unique_ptr> sTableOfCollidables; - static std::unique_ptr> sTableOfBooleanCollidables; - static std::unique_ptr> sTableOfMovingCollidables; - static ComparisonFunc sNullCollider; - static BooleanComparisonFunc sNullBooleanCollider; - static MovingComparisonFunc sNullMovingCollider; + CMaterialList x8_material; + static s32 sNumTypes; + static bool sInitComplete; + static bool sTypesAdded; + static bool sTypesAdding; + static bool sCollidersAdded; + static bool sCollidersAdding; + static std::unique_ptr> sCollisionTypeList; + static std::unique_ptr> sTableOfCollidables; + static std::unique_ptr> sTableOfBooleanCollidables; + static std::unique_ptr> sTableOfMovingCollidables; + static ComparisonFunc sNullCollider; + static BooleanComparisonFunc sNullBooleanCollider; + static MovingComparisonFunc sNullMovingCollider; - static bool InternalCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list); - static bool InternalCollideBoolean(const CInternalCollisionStructure& collision); - static bool InternalCollideMoving(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir, - double& dOut, CCollisionInfo& infoOut); + static bool InternalCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list); + static bool InternalCollideBoolean(const CInternalCollisionStructure& collision); + static bool InternalCollideMoving(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir, + double& dOut, CCollisionInfo& infoOut); public: - CCollisionPrimitive() = default; - CCollisionPrimitive(const CMaterialList& list); - virtual u32 GetTableIndex() const = 0; - virtual void SetMaterial(const CMaterialList&); - virtual const CMaterialList& GetMaterial() const; - virtual zeus::CAABox CalculateAABox(const zeus::CTransform&) const = 0; - virtual zeus::CAABox CalculateLocalAABox() const = 0; - virtual FourCC GetPrimType() const = 0; - virtual ~CCollisionPrimitive() {} - virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const = 0; - CRayCastResult CastRay(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length, - const CMaterialFilter& filter, const zeus::CTransform& xf) const; + CCollisionPrimitive() = default; + CCollisionPrimitive(const CMaterialList& list); + virtual u32 GetTableIndex() const = 0; + virtual void SetMaterial(const CMaterialList&); + virtual const CMaterialList& GetMaterial() const; + virtual zeus::CAABox CalculateAABox(const zeus::CTransform&) const = 0; + virtual zeus::CAABox CalculateLocalAABox() const = 0; + virtual FourCC GetPrimType() const = 0; + virtual ~CCollisionPrimitive() {} + virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const = 0; + CRayCastResult CastRay(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length, + const CMaterialFilter& filter, const zeus::CTransform& xf) const; - static bool Collide(const CInternalCollisionStructure::CPrimDesc& prim0, - const CInternalCollisionStructure::CPrimDesc& prim1, - CCollisionInfoList& list); - static bool CollideBoolean(const CInternalCollisionStructure::CPrimDesc& prim0, - const CInternalCollisionStructure::CPrimDesc& prim1); - static bool CollideMoving(const CInternalCollisionStructure::CPrimDesc& prim0, - const CInternalCollisionStructure::CPrimDesc& prim1, - const zeus::CVector3f& dir, - double& dOut, - CCollisionInfo& infoOut); + static bool Collide(const CInternalCollisionStructure::CPrimDesc& prim0, + const CInternalCollisionStructure::CPrimDesc& prim1, CCollisionInfoList& list); + static bool CollideBoolean(const CInternalCollisionStructure::CPrimDesc& prim0, + const CInternalCollisionStructure::CPrimDesc& prim1); + static bool CollideMoving(const CInternalCollisionStructure::CPrimDesc& prim0, + const CInternalCollisionStructure::CPrimDesc& prim1, const zeus::CVector3f& dir, + double& dOut, CCollisionInfo& infoOut); - static void InitBeginTypes(); - static void InitAddType(const Type& tp); - static void InitEndTypes(); + static void InitBeginTypes(); + static void InitAddType(const Type& tp); + static void InitEndTypes(); - static void InitBeginColliders(); - static void InitAddBooleanCollider(const BooleanComparison& cmp); - static void InitAddBooleanCollider(BooleanComparisonFunc, const char*, const char*); - static void InitAddMovingCollider(const MovingComparison& cmp); - static void InitAddMovingCollider(MovingComparisonFunc, const char*, const char*); - static void InitAddCollider(const Comparison& cmp); - static void InitAddCollider(ComparisonFunc, const char*, const char*); - static void InitEndColliders(); + static void InitBeginColliders(); + static void InitAddBooleanCollider(const BooleanComparison& cmp); + static void InitAddBooleanCollider(BooleanComparisonFunc, const char*, const char*); + static void InitAddMovingCollider(const MovingComparison& cmp); + static void InitAddMovingCollider(MovingComparisonFunc, const char*, const char*); + static void InitAddCollider(const Comparison& cmp); + static void InitAddCollider(ComparisonFunc, const char*, const char*); + static void InitEndColliders(); - static void Uninitialize(); + static void Uninitialize(); }; -} - +} // namespace urde diff --git a/Runtime/Collision/CCollisionResponseData.cpp b/Runtime/Collision/CCollisionResponseData.cpp index 332718435..cd8270d4e 100644 --- a/Runtime/Collision/CCollisionResponseData.cpp +++ b/Runtime/Collision/CCollisionResponseData.cpp @@ -8,8 +8,7 @@ #include "CSimplePool.hpp" #include "CRandom16.hpp" -namespace urde -{ +namespace urde { const EWeaponCollisionResponseTypes CCollisionResponseData::skWorldMaterialTable[32] = { EWeaponCollisionResponseTypes::Default, EWeaponCollisionResponseTypes::Unknown2, EWeaponCollisionResponseTypes::Metal, EWeaponCollisionResponseTypes::Grass, @@ -67,202 +66,172 @@ static const std::vector kWCRTDecalIDs = {SBIG('NCDL'), SBIG('DDCL'), SB using CPF = CParticleDataFactory; void CCollisionResponseData::AddParticleSystemToResponse(EWeaponCollisionResponseTypes type, CInputStream& in, - CSimplePool* resPool) -{ - int i = int(type); - std::vector tracker; - tracker.resize(8); - x0_generators[i].emplace(CPF::GetChildGeneratorDesc(in, resPool, tracker).m_token); + CSimplePool* resPool) { + int i = int(type); + std::vector tracker; + tracker.resize(8); + x0_generators[i].emplace(CPF::GetChildGeneratorDesc(in, resPool, tracker).m_token); } -bool CCollisionResponseData::CheckAndAddDecalToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool) -{ - int i = 0; - for (const FourCC& type : kWCRTDecalIDs) - { - if (type == clsId) - { - FourCC cls = CPF::GetClassID(in); - if (cls == SBIG('NONE')) - return true; - - CAssetId id = u64(in.readUint32Big()); - if (!id.IsValid()) - return true; - - x20_decals[i].emplace(resPool->GetObj({FOURCC('DPSC'), id})); - return true; - } - i++; - } - return false; -} - -bool CCollisionResponseData::CheckAndAddSoundFXToResponse(FourCC clsId, CInputStream& in) -{ - int i = 0; - for (const FourCC& type : kWCRTSFXIDs) - { - if (type == clsId) - { - FourCC cls = CPF::GetClassID(in); - if (cls == SBIG('NONE')) - return true; - - x10_sfx[i] = CPF::GetInt(in); - return true; - } - i++; - } - - return false; -} - -bool CCollisionResponseData::CheckAndAddParticleSystemToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool) -{ - int i = 0; - for (const FourCC& type : kWCRTIDs) - { - if (type == clsId) - { - AddParticleSystemToResponse(EWeaponCollisionResponseTypes(i), in, resPool); - return true; - } - i++; - } - return false; -} - -bool CCollisionResponseData::CheckAndAddResourceToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool) -{ - if (CheckAndAddParticleSystemToResponse(clsId, in, resPool)) - return true; - if (CheckAndAddSoundFXToResponse(clsId, in)) - return true; - if (CheckAndAddDecalToResponse(clsId, in, resPool)) +bool CCollisionResponseData::CheckAndAddDecalToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool) { + int i = 0; + for (const FourCC& type : kWCRTDecalIDs) { + if (type == clsId) { + FourCC cls = CPF::GetClassID(in); + if (cls == SBIG('NONE')) return true; - return false; + CAssetId id = u64(in.readUint32Big()); + if (!id.IsValid()) + return true; + + x20_decals[i].emplace(resPool->GetObj({FOURCC('DPSC'), id})); + return true; + } + i++; + } + return false; } -CCollisionResponseData::CCollisionResponseData(CInputStream& in, CSimplePool* resPool) : x30_RNGE(50.f), x34_FOFF(0.2f) -{ - x0_generators.resize(94); - x10_sfx.resize(94); - x20_decals.resize(94); - for (s32& id : x10_sfx) - id = kInvalidSFX; +bool CCollisionResponseData::CheckAndAddSoundFXToResponse(FourCC clsId, CInputStream& in) { + int i = 0; + for (const FourCC& type : kWCRTSFXIDs) { + if (type == clsId) { + FourCC cls = CPF::GetClassID(in); + if (cls == SBIG('NONE')) + return true; - FourCC clsId = CPF::GetClassID(in); - if (clsId == UncookedResType()) - { - CRandom16 rand; - CGlobalRandom gr(rand); - - while (clsId != SBIG('_END')) - { - clsId = CPF::GetClassID(in); - if (CheckAndAddResourceToResponse(clsId, in, resPool)) - continue; - - if (clsId == SBIG('RNGE')) - { - CPF::GetClassID(in); - x30_RNGE = CPF::GetReal(in); - } - else if (clsId == SBIG('FOFF')) - { - CPF::GetClassID(in); - x34_FOFF = CPF::GetReal(in); - } - } + x10_sfx[i] = CPF::GetInt(in); + return true; } + i++; + } + + return false; +} + +bool CCollisionResponseData::CheckAndAddParticleSystemToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool) { + int i = 0; + for (const FourCC& type : kWCRTIDs) { + if (type == clsId) { + AddParticleSystemToResponse(EWeaponCollisionResponseTypes(i), in, resPool); + return true; + } + i++; + } + return false; +} + +bool CCollisionResponseData::CheckAndAddResourceToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool) { + if (CheckAndAddParticleSystemToResponse(clsId, in, resPool)) + return true; + if (CheckAndAddSoundFXToResponse(clsId, in)) + return true; + if (CheckAndAddDecalToResponse(clsId, in, resPool)) + return true; + + return false; +} + +CCollisionResponseData::CCollisionResponseData(CInputStream& in, CSimplePool* resPool) +: x30_RNGE(50.f), x34_FOFF(0.2f) { + x0_generators.resize(94); + x10_sfx.resize(94); + x20_decals.resize(94); + for (s32& id : x10_sfx) + id = kInvalidSFX; + + FourCC clsId = CPF::GetClassID(in); + if (clsId == UncookedResType()) { + CRandom16 rand; + CGlobalRandom gr(rand); + + while (clsId != SBIG('_END')) { + clsId = CPF::GetClassID(in); + if (CheckAndAddResourceToResponse(clsId, in, resPool)) + continue; + + if (clsId == SBIG('RNGE')) { + CPF::GetClassID(in); + x30_RNGE = CPF::GetReal(in); + } else if (clsId == SBIG('FOFF')) { + CPF::GetClassID(in); + x34_FOFF = CPF::GetReal(in); + } + } + } } const std::experimental::optional>& -CCollisionResponseData::GetParticleDescription(EWeaponCollisionResponseTypes type) const -{ - if (x0_generators[u32(type)]) - return x0_generators[u32(type)]; - - bool foundType = false; - if (ResponseTypeIsEnemyNormal(type)) - { - type = EWeaponCollisionResponseTypes::EnemyNormal; - foundType = true; - } - else if (ResponseTypeIsEnemySpecial(type)) - { - type = EWeaponCollisionResponseTypes::EnemySpecial; - foundType = true; - } - else if (ResponseTypeIsEnemyShielded(type)) - { - type = EWeaponCollisionResponseTypes::EnemyShielded; - foundType = true; - } - - if (foundType && !x0_generators[u32(type)]) - type = EWeaponCollisionResponseTypes::EnemyNormal; - - if (!x0_generators[u32(type)] && type != EWeaponCollisionResponseTypes::None) - type = EWeaponCollisionResponseTypes::Default; - +CCollisionResponseData::GetParticleDescription(EWeaponCollisionResponseTypes type) const { + if (x0_generators[u32(type)]) return x0_generators[u32(type)]; + + bool foundType = false; + if (ResponseTypeIsEnemyNormal(type)) { + type = EWeaponCollisionResponseTypes::EnemyNormal; + foundType = true; + } else if (ResponseTypeIsEnemySpecial(type)) { + type = EWeaponCollisionResponseTypes::EnemySpecial; + foundType = true; + } else if (ResponseTypeIsEnemyShielded(type)) { + type = EWeaponCollisionResponseTypes::EnemyShielded; + foundType = true; + } + + if (foundType && !x0_generators[u32(type)]) + type = EWeaponCollisionResponseTypes::EnemyNormal; + + if (!x0_generators[u32(type)] && type != EWeaponCollisionResponseTypes::None) + type = EWeaponCollisionResponseTypes::Default; + + return x0_generators[u32(type)]; } const std::experimental::optional>& -CCollisionResponseData::GetDecalDescription(EWeaponCollisionResponseTypes type) const -{ - return x20_decals[u32(type)]; +CCollisionResponseData::GetDecalDescription(EWeaponCollisionResponseTypes type) const { + return x20_decals[u32(type)]; } -s32 CCollisionResponseData::GetSoundEffectId(EWeaponCollisionResponseTypes type) const -{ - if (x10_sfx[u32(type)] == kInvalidSFX) - { - if (ResponseTypeIsEnemyNormal(type)) - type = EWeaponCollisionResponseTypes::EnemyNormal; - else if (ResponseTypeIsEnemySpecial(type)) - type = EWeaponCollisionResponseTypes::EnemySpecial; - else if (ResponseTypeIsEnemyShielded(type)) - type = EWeaponCollisionResponseTypes::EnemyShielded; - else - type = EWeaponCollisionResponseTypes::Default; - } +s32 CCollisionResponseData::GetSoundEffectId(EWeaponCollisionResponseTypes type) const { + if (x10_sfx[u32(type)] == kInvalidSFX) { + if (ResponseTypeIsEnemyNormal(type)) + type = EWeaponCollisionResponseTypes::EnemyNormal; + else if (ResponseTypeIsEnemySpecial(type)) + type = EWeaponCollisionResponseTypes::EnemySpecial; + else if (ResponseTypeIsEnemyShielded(type)) + type = EWeaponCollisionResponseTypes::EnemyShielded; + else + type = EWeaponCollisionResponseTypes::Default; + } - return x10_sfx[u32(type)]; + return x10_sfx[u32(type)]; } -EWeaponCollisionResponseTypes CCollisionResponseData::GetWorldCollisionResponseType(s32 id) -{ - if (id < 0 || id >= 32) - return EWeaponCollisionResponseTypes::Default; - return skWorldMaterialTable[id]; +EWeaponCollisionResponseTypes CCollisionResponseData::GetWorldCollisionResponseType(s32 id) { + if (id < 0 || id >= 32) + return EWeaponCollisionResponseTypes::Default; + return skWorldMaterialTable[id]; } -bool CCollisionResponseData::ResponseTypeIsEnemyNormal(EWeaponCollisionResponseTypes type) -{ - return (type >= EWeaponCollisionResponseTypes::Unknown19 && type <= EWeaponCollisionResponseTypes::Unknown43); +bool CCollisionResponseData::ResponseTypeIsEnemyNormal(EWeaponCollisionResponseTypes type) { + return (type >= EWeaponCollisionResponseTypes::Unknown19 && type <= EWeaponCollisionResponseTypes::Unknown43); } -bool CCollisionResponseData::ResponseTypeIsEnemySpecial(EWeaponCollisionResponseTypes type) -{ - return (type >= EWeaponCollisionResponseTypes::Unknown44 && type <= EWeaponCollisionResponseTypes::Unknown68); +bool CCollisionResponseData::ResponseTypeIsEnemySpecial(EWeaponCollisionResponseTypes type) { + return (type >= EWeaponCollisionResponseTypes::Unknown44 && type <= EWeaponCollisionResponseTypes::Unknown68); } -bool CCollisionResponseData::ResponseTypeIsEnemyShielded(EWeaponCollisionResponseTypes type) -{ - return (type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::Unknown93); +bool CCollisionResponseData::ResponseTypeIsEnemyShielded(EWeaponCollisionResponseTypes type) { + return (type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::Unknown93); } FourCC CCollisionResponseData::UncookedResType() { return SBIG('CRSM'); } CFactoryFnReturn FCollisionResponseDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, - CObjectReference*) -{ - CSimplePool* sp = vparms.GetOwnedObj(); - return TToken::GetIObjObjectFor( - std::unique_ptr(new CCollisionResponseData(in, sp))); -} + CObjectReference*) { + CSimplePool* sp = vparms.GetOwnedObj(); + return TToken::GetIObjObjectFor( + std::unique_ptr(new CCollisionResponseData(in, sp))); } +} // namespace urde diff --git a/Runtime/Collision/CCollisionResponseData.hpp b/Runtime/Collision/CCollisionResponseData.hpp index 8edc69011..e94fdf755 100644 --- a/Runtime/Collision/CCollisionResponseData.hpp +++ b/Runtime/Collision/CCollisionResponseData.hpp @@ -7,70 +7,139 @@ #include "CToken.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { class CSimplePool; class CGenDescription; class CDecalDescription; -enum class EWeaponCollisionResponseTypes -{ - None, Default, Unknown2, Metal, - Grass, Ice, Goo, Wood, - Water, Mud, Lava, Sand, - Projectile,OtherProjectile,Unknown14,Unknown15, - EnemyNormal,EnemySpecial,EnemyShielded,Unknown19, - Unknown20,Unknown21,Unknown22,Unknown23, - Unknown24,Unknown25,Unknown26,Unknown27, - Unknown28,Unknown29,Unknown30,Unknown31, - Unknown32,Unknown33,Unknown34,Unknown35, - Unknown36,Unknown37,Unknown38,Unknown39, - Unknown40,Unknown41,Unknown42,Unknown43, - Unknown44,Unknown45,Unknown46,Unknown47, - Unknown48,Unknown49,Unknown50,Unknown51, - Unknown52,Unknown53,Unknown54,Unknown55, - Unknown56,Unknown57,Unknown58,Unknown59, - Unknown60,Unknown61,Unknown62,Unknown63, - Unknown64,Unknown65,Unknown66,Unknown67, - Unknown68,Unknown69,Unknown70,Unknown71, - Unknown72,Unknown73,Unknown74,Unknown75, - Unknown76,Unknown77,Unknown78,Unknown79, - Unknown80,Unknown81,Unknown82,Unknown83, - Unknown84,Unknown85,Unknown86,Unknown87, - Unknown88,Unknown89,Unknown90,Unknown91, - Unknown92,Unknown93 +enum class EWeaponCollisionResponseTypes { + None, + Default, + Unknown2, + Metal, + Grass, + Ice, + Goo, + Wood, + Water, + Mud, + Lava, + Sand, + Projectile, + OtherProjectile, + Unknown14, + Unknown15, + EnemyNormal, + EnemySpecial, + EnemyShielded, + Unknown19, + Unknown20, + Unknown21, + Unknown22, + Unknown23, + Unknown24, + Unknown25, + Unknown26, + Unknown27, + Unknown28, + Unknown29, + Unknown30, + Unknown31, + Unknown32, + Unknown33, + Unknown34, + Unknown35, + Unknown36, + Unknown37, + Unknown38, + Unknown39, + Unknown40, + Unknown41, + Unknown42, + Unknown43, + Unknown44, + Unknown45, + Unknown46, + Unknown47, + Unknown48, + Unknown49, + Unknown50, + Unknown51, + Unknown52, + Unknown53, + Unknown54, + Unknown55, + Unknown56, + Unknown57, + Unknown58, + Unknown59, + Unknown60, + Unknown61, + Unknown62, + Unknown63, + Unknown64, + Unknown65, + Unknown66, + Unknown67, + Unknown68, + Unknown69, + Unknown70, + Unknown71, + Unknown72, + Unknown73, + Unknown74, + Unknown75, + Unknown76, + Unknown77, + Unknown78, + Unknown79, + Unknown80, + Unknown81, + Unknown82, + Unknown83, + Unknown84, + Unknown85, + Unknown86, + Unknown87, + Unknown88, + Unknown89, + Unknown90, + Unknown91, + Unknown92, + Unknown93 }; -class CCollisionResponseData -{ - static const EWeaponCollisionResponseTypes skWorldMaterialTable[32]; - static const s32 kInvalidSFX; - std::vector>> x0_generators; - std::vector x10_sfx; - std::vector>> x20_decals; - float x30_RNGE; - float x34_FOFF; +class CCollisionResponseData { + static const EWeaponCollisionResponseTypes skWorldMaterialTable[32]; + static const s32 kInvalidSFX; + std::vector>> x0_generators; + std::vector x10_sfx; + std::vector>> x20_decals; + float x30_RNGE; + float x34_FOFF; + + void AddParticleSystemToResponse(EWeaponCollisionResponseTypes type, CInputStream& in, CSimplePool* resPool); + bool CheckAndAddDecalToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool); + bool CheckAndAddSoundFXToResponse(FourCC clsId, CInputStream& in); + bool CheckAndAddParticleSystemToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool); + bool CheckAndAddResourceToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool); - void AddParticleSystemToResponse(EWeaponCollisionResponseTypes type, CInputStream& in, CSimplePool* resPool); - bool CheckAndAddDecalToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool); - bool CheckAndAddSoundFXToResponse(FourCC clsId, CInputStream& in); - bool CheckAndAddParticleSystemToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool); - bool CheckAndAddResourceToResponse(FourCC clsId, CInputStream& in, CSimplePool* resPool); public: - CCollisionResponseData(CInputStream& in, CSimplePool* resPool); - const std::experimental::optional>& GetParticleDescription(EWeaponCollisionResponseTypes) const; - const std::experimental::optional>& GetDecalDescription(EWeaponCollisionResponseTypes type) const; - s32 GetSoundEffectId(EWeaponCollisionResponseTypes) const; - static EWeaponCollisionResponseTypes GetWorldCollisionResponseType(s32); - static bool ResponseTypeIsEnemyShielded(EWeaponCollisionResponseTypes); - static bool ResponseTypeIsEnemyNormal(EWeaponCollisionResponseTypes); - static bool ResponseTypeIsEnemySpecial(EWeaponCollisionResponseTypes); - float GetAudibleRange() const { return x30_RNGE; } - float GetAudibleFallOff() const { return x34_FOFF; } - static FourCC UncookedResType(); + CCollisionResponseData(CInputStream& in, CSimplePool* resPool); + const std::experimental::optional>& + GetParticleDescription(EWeaponCollisionResponseTypes) const; + const std::experimental::optional>& + GetDecalDescription(EWeaponCollisionResponseTypes type) const; + s32 GetSoundEffectId(EWeaponCollisionResponseTypes) const; + static EWeaponCollisionResponseTypes GetWorldCollisionResponseType(s32); + static bool ResponseTypeIsEnemyShielded(EWeaponCollisionResponseTypes); + static bool ResponseTypeIsEnemyNormal(EWeaponCollisionResponseTypes); + static bool ResponseTypeIsEnemySpecial(EWeaponCollisionResponseTypes); + float GetAudibleRange() const { return x30_RNGE; } + float GetAudibleFallOff() const { return x34_FOFF; } + static FourCC UncookedResType(); }; CFactoryFnReturn FCollisionResponseDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference*); -} - +} // namespace urde diff --git a/Runtime/Collision/CCollisionSurface.cpp b/Runtime/Collision/CCollisionSurface.cpp index ab5e4e4bf..6e06bc3d3 100644 --- a/Runtime/Collision/CCollisionSurface.cpp +++ b/Runtime/Collision/CCollisionSurface.cpp @@ -1,25 +1,18 @@ #include "CCollisionSurface.hpp" -namespace urde -{ -CCollisionSurface::CCollisionSurface(const zeus::CVector3f& a, const zeus::CVector3f& b, const zeus::CVector3f& c, u32 flags) - : x0_a(a), - xc_b(b), - x18_c(c), - x24_flags(flags) -{ +namespace urde { +CCollisionSurface::CCollisionSurface(const zeus::CVector3f& a, const zeus::CVector3f& b, const zeus::CVector3f& c, + u32 flags) +: x0_a(a), xc_b(b), x18_c(c), x24_flags(flags) {} + +zeus::CVector3f CCollisionSurface::GetNormal() const { + zeus::CVector3f v1 = (xc_b - x0_a).cross(x18_c - x0_a); + return zeus::CUnitVector3f(v1, true); } -zeus::CVector3f CCollisionSurface::GetNormal() const -{ - zeus::CVector3f v1 = (xc_b - x0_a).cross(x18_c - x0_a); - return zeus::CUnitVector3f(v1, true); +zeus::CPlane CCollisionSurface::GetPlane() const { + zeus::CVector3f norm = GetNormal(); + return {norm, norm.dot(x0_a)}; } -zeus::CPlane CCollisionSurface::GetPlane() const -{ - zeus::CVector3f norm = GetNormal(); - return {norm, norm.dot(x0_a)}; -} - -} +} // namespace urde diff --git a/Runtime/Collision/CCollisionSurface.hpp b/Runtime/Collision/CCollisionSurface.hpp index afc293635..e8538049a 100644 --- a/Runtime/Collision/CCollisionSurface.hpp +++ b/Runtime/Collision/CCollisionSurface.hpp @@ -3,22 +3,20 @@ #include "zeus/zeus.hpp" #include "RetroTypes.hpp" -namespace urde -{ -class CCollisionSurface -{ - zeus::CVector3f x0_a; - zeus::CVector3f xc_b; - zeus::CVector3f x18_c; - u32 x24_flags; +namespace urde { +class CCollisionSurface { + zeus::CVector3f x0_a; + zeus::CVector3f xc_b; + zeus::CVector3f x18_c; + u32 x24_flags; + public: - CCollisionSurface(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&, u32); + CCollisionSurface(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&, u32); - zeus::CVector3f GetNormal() const; - const zeus::CVector3f& GetVert(s32 idx) const { return (&x0_a)[idx]; } - const zeus::CVector3f* GetVerts() const { return &x0_a; } - zeus::CPlane GetPlane() const; - u32 GetSurfaceFlags() const { return x24_flags; } + zeus::CVector3f GetNormal() const; + const zeus::CVector3f& GetVert(s32 idx) const { return (&x0_a)[idx]; } + const zeus::CVector3f* GetVerts() const { return &x0_a; } + zeus::CPlane GetPlane() const; + u32 GetSurfaceFlags() const { return x24_flags; } }; -} - +} // namespace urde diff --git a/Runtime/Collision/CGameCollision.cpp b/Runtime/Collision/CGameCollision.cpp index 2c7861dca..07e20ea61 100644 --- a/Runtime/Collision/CGameCollision.cpp +++ b/Runtime/Collision/CGameCollision.cpp @@ -14,1133 +14,954 @@ #include "CCollidableSphere.hpp" #include "Character/CGroundMovement.hpp" -namespace urde -{ +namespace urde { -static float CollisionImpulseFiniteVsInfinite(float mass, float velNormDot, float restitution) -{ - return mass * -(1.f + restitution) * velNormDot; +static float CollisionImpulseFiniteVsInfinite(float mass, float velNormDot, float restitution) { + return mass * -(1.f + restitution) * velNormDot; } -static float CollisionImpulseFiniteVsFinite(float mass0, float mass1, float velNormDot, float restitution) -{ - return (-(1.f + restitution) * velNormDot) / ((1.f / mass0) + (1.f / mass1)); +static float CollisionImpulseFiniteVsFinite(float mass0, float mass1, float velNormDot, float restitution) { + return (-(1.f + restitution) * velNormDot) / ((1.f / mass0) + (1.f / mass1)); } -void CGameCollision::InitCollision() -{ - /* Types */ - CCollisionPrimitive::InitBeginTypes(); - CCollisionPrimitive::InitAddType(CCollidableOBBTreeGroup::GetType()); - CCollisionPrimitive::InitEndTypes(); +void CGameCollision::InitCollision() { + /* Types */ + CCollisionPrimitive::InitBeginTypes(); + CCollisionPrimitive::InitAddType(CCollidableOBBTreeGroup::GetType()); + CCollisionPrimitive::InitEndTypes(); - /* Colliders */ - CCollisionPrimitive::InitBeginColliders(); - CCollisionPrimitive::InitAddCollider(CCollidableOBBTreeGroup::SphereCollide, "CCollidableSphere", - "CCollidableOBBTreeGroup"); - CCollisionPrimitive::InitAddCollider(CCollidableOBBTreeGroup::AABoxCollide, "CCollidableAABox", - "CCollidableOBBTreeGroup"); - CCollisionPrimitive::InitAddBooleanCollider(CCollidableOBBTreeGroup::SphereCollideBoolean, "CCollidableSphere", - "CCollidableOBBTreeGroup"); - CCollisionPrimitive::InitAddBooleanCollider(CCollidableOBBTreeGroup::AABoxCollideBoolean, "CCollidableAABox", - "CCollidableOBBTreeGroup"); - CCollisionPrimitive::InitAddMovingCollider(CCollidableOBBTreeGroup::CollideMovingAABox, "CCollidableAABox", - "CCollidableOBBTreeGroup"); - CCollisionPrimitive::InitAddMovingCollider(CCollidableOBBTreeGroup::CollideMovingSphere, "CCollidableSphere", - "CCollidableOBBTreeGroup"); - CCollisionPrimitive::InitAddCollider(CGameCollision::NullCollisionCollider, "CCollidableOBBTreeGroup", - "CCollidableOBBTreeGroup"); - CCollisionPrimitive::InitAddBooleanCollider(CGameCollision::NullBooleanCollider, "CCollidableOBBTreeGroup", - "CCollidableOBBTreeGroup"); - CCollisionPrimitive::InitAddMovingCollider(CGameCollision::NullMovingCollider, "CCollidableOBBTreeGroup", - "CCollidableOBBTreeGroup"); - CCollisionPrimitive::InitEndColliders(); + /* Colliders */ + CCollisionPrimitive::InitBeginColliders(); + CCollisionPrimitive::InitAddCollider(CCollidableOBBTreeGroup::SphereCollide, "CCollidableSphere", + "CCollidableOBBTreeGroup"); + CCollisionPrimitive::InitAddCollider(CCollidableOBBTreeGroup::AABoxCollide, "CCollidableAABox", + "CCollidableOBBTreeGroup"); + CCollisionPrimitive::InitAddBooleanCollider(CCollidableOBBTreeGroup::SphereCollideBoolean, "CCollidableSphere", + "CCollidableOBBTreeGroup"); + CCollisionPrimitive::InitAddBooleanCollider(CCollidableOBBTreeGroup::AABoxCollideBoolean, "CCollidableAABox", + "CCollidableOBBTreeGroup"); + CCollisionPrimitive::InitAddMovingCollider(CCollidableOBBTreeGroup::CollideMovingAABox, "CCollidableAABox", + "CCollidableOBBTreeGroup"); + CCollisionPrimitive::InitAddMovingCollider(CCollidableOBBTreeGroup::CollideMovingSphere, "CCollidableSphere", + "CCollidableOBBTreeGroup"); + CCollisionPrimitive::InitAddCollider(CGameCollision::NullCollisionCollider, "CCollidableOBBTreeGroup", + "CCollidableOBBTreeGroup"); + CCollisionPrimitive::InitAddBooleanCollider(CGameCollision::NullBooleanCollider, "CCollidableOBBTreeGroup", + "CCollidableOBBTreeGroup"); + CCollisionPrimitive::InitAddMovingCollider(CGameCollision::NullMovingCollider, "CCollidableOBBTreeGroup", + "CCollidableOBBTreeGroup"); + CCollisionPrimitive::InitEndColliders(); } void CGameCollision::MovePlayer(CStateManager& mgr, CPhysicsActor& actor, float dt, - const rstl::reserved_vector* colliderList) -{ - actor.SetAngularEnabled(true); - actor.AddMotionState(actor.PredictAngularMotion(dt)); - if (actor.IsUseStandardCollider()) - { - MoveAndCollide(mgr, actor, dt, CBallFilter(actor), colliderList); - } + const rstl::reserved_vector* colliderList) { + actor.SetAngularEnabled(true); + actor.AddMotionState(actor.PredictAngularMotion(dt)); + if (actor.IsUseStandardCollider()) { + MoveAndCollide(mgr, actor, dt, CBallFilter(actor), colliderList); + } else { + if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) + CGroundMovement::MoveGroundCollider_New(mgr, actor, dt, colliderList); else - { - if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) - CGroundMovement::MoveGroundCollider_New(mgr, actor, dt, colliderList); - else - MoveAndCollide(mgr, actor, dt, CBallFilter(actor), colliderList); - } - actor.SetAngularEnabled(false); + MoveAndCollide(mgr, actor, dt, CBallFilter(actor), colliderList); + } + actor.SetAngularEnabled(false); } void CGameCollision::MoveAndCollide(CStateManager& mgr, CPhysicsActor& actor, float dt, const ICollisionFilter& filter, - const rstl::reserved_vector* colliderList) -{ - bool isPlayer = actor.GetMaterialList().HasMaterial(EMaterialTypes::Player); - bool r28 = false; - bool r27 = false; - int r26 = 0; - float f31 = dt; - float _4AC4 = dt; - float _4AC8 = dt; - CCollisionInfoList accumList; - CMotionState mState = actor.PredictMotion_Internal(dt); - float transMag = mState.x0_translation.magnitude(); - float m1 = 0.0005f / actor.GetCollisionAccuracyModifier(); - float m2 = transMag / (5.f * actor.GetCollisionAccuracyModifier()); - float mMax = std::max(m1, m2); - float m3 = 0.001f / actor.GetCollisionAccuracyModifier(); - - zeus::CAABox motionVol = actor.GetMotionVolume(dt); - rstl::reserved_vector useColliderList; - if (colliderList) - useColliderList = *colliderList; + const rstl::reserved_vector* colliderList) { + bool isPlayer = actor.GetMaterialList().HasMaterial(EMaterialTypes::Player); + bool r28 = false; + bool r27 = false; + int r26 = 0; + float f31 = dt; + float _4AC4 = dt; + float _4AC8 = dt; + CCollisionInfoList accumList; + CMotionState mState = actor.PredictMotion_Internal(dt); + float transMag = mState.x0_translation.magnitude(); + float m1 = 0.0005f / actor.GetCollisionAccuracyModifier(); + float m2 = transMag / (5.f * actor.GetCollisionAccuracyModifier()); + float mMax = std::max(m1, m2); + float m3 = 0.001f / actor.GetCollisionAccuracyModifier(); + + zeus::CAABox motionVol = actor.GetMotionVolume(dt); + rstl::reserved_vector useColliderList; + if (colliderList) + useColliderList = *colliderList; + else + mgr.BuildColliderList(useColliderList, actor, zeus::CAABox(motionVol.min - 1.f, motionVol.max + 1.f)); + CAreaCollisionCache cache(motionVol); + if (actor.GetCollisionPrimitive()->GetPrimType() != FOURCC('OBTG') && + !actor.GetMaterialFilter().GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision)) { + BuildAreaCollisionCache(mgr, cache); + zeus::CVector3f pos = actor.GetCollisionPrimitive()->CalculateAABox(actor.GetPrimitiveTransform()).center(); + float halfExtent = 0.5f * GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive()); + if (transMag > halfExtent) { + TUniqueId id = kInvalidUniqueId; + zeus::CVector3f dir = (1.f / transMag) * mState.x0_translation; + CRayCastResult intersectRes = + mgr.RayWorldIntersection(id, pos, dir, transMag, actor.GetMaterialFilter(), useColliderList); + if (intersectRes.IsValid()) { + f31 = dt * (intersectRes.GetT() / transMag); + mState = actor.PredictMotion_Internal(f31); + _4AC8 = halfExtent * (dt / transMag); + mMax = std::min(mMax, halfExtent); + } + } + } + + float f27 = f31; + while (true) { + actor.MoveCollisionPrimitive(mState.x0_translation); + if (DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(), actor.GetPrimitiveTransform(), + actor.GetMaterialFilter(), useColliderList)) { + r28 = true; + if (mState.x0_translation.magnitude() < mMax) { + r27 = true; + accumList.Clear(); + TUniqueId id = kInvalidUniqueId; + DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), actor.GetPrimitiveTransform(), + actor.GetMaterialFilter(), useColliderList, id, accumList); + TCastToPtr otherActor = mgr.ObjectById(id); + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); + zeus::CVector3f relVel = GetActorRelativeVelocities(actor, otherActor.GetPtr()); + CCollisionInfoList filterList0, filterList1; + CollisionUtil::FilterOutBackfaces(relVel, accumList, filterList0); + if (filterList0.GetCount() > 0) { + filter.Filter(filterList0, filterList1); + if (!filterList1.GetCount() && actor.GetMaterialList().HasMaterial(EMaterialTypes::Player)) { + CMotionState mState = actor.GetLastNonCollidingState(); + mState.x1c_velocity *= zeus::CVector3f(0.5f); + mState.x28_angularMomentum *= zeus::CVector3f(0.5f); + actor.SetMotionState(mState); + } + } + MakeCollisionCallbacks(mgr, actor, id, filterList1); + SendScriptMessages(mgr, actor, otherActor.GetPtr(), filterList1); + ResolveCollisions(actor, otherActor.GetPtr(), filterList1); + _4AC4 -= f31; + f27 = std::min(_4AC4, _4AC8); + f31 = f27; + } else { + f27 *= 0.5f; + f31 *= 0.5f; + } + } else { + actor.AddMotionState(mState); + _4AC4 -= f31; + f31 = f27; + actor.ClearImpulses(); + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); + } + + ++r26; + if (_4AC4 > 0.f && ((mState.x0_translation.magnitude() > m3 && r27) || !r27) && r26 <= 1000) + mState = actor.PredictMotion_Internal(f31); else - mgr.BuildColliderList(useColliderList, actor, zeus::CAABox(motionVol.min - 1.f, motionVol.max + 1.f)); - CAreaCollisionCache cache(motionVol); - if (actor.GetCollisionPrimitive()->GetPrimType() != FOURCC('OBTG') && - !actor.GetMaterialFilter().GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision)) - { - BuildAreaCollisionCache(mgr, cache); - zeus::CVector3f pos = actor.GetCollisionPrimitive()->CalculateAABox(actor.GetPrimitiveTransform()).center(); - float halfExtent = 0.5f * GetMinExtentForCollisionPrimitive(*actor.GetCollisionPrimitive()); - if (transMag > halfExtent) - { - TUniqueId id = kInvalidUniqueId; - zeus::CVector3f dir = (1.f / transMag) * mState.x0_translation; - CRayCastResult intersectRes = mgr.RayWorldIntersection(id, pos, dir, transMag, - actor.GetMaterialFilter(), useColliderList); - if (intersectRes.IsValid()) - { - f31 = dt * (intersectRes.GetT() / transMag); - mState = actor.PredictMotion_Internal(f31); - _4AC8 = halfExtent * (dt / transMag); - mMax = std::min(mMax, halfExtent); - } - } - } + break; + } - float f27 = f31; - while (true) - { - actor.MoveCollisionPrimitive(mState.x0_translation); - if (DetectCollisionBoolean_Cached(mgr, cache, *actor.GetCollisionPrimitive(), - actor.GetPrimitiveTransform(), actor.GetMaterialFilter(), - useColliderList)) - { - r28 = true; - if (mState.x0_translation.magnitude() < mMax) - { - r27 = true; - accumList.Clear(); - TUniqueId id = kInvalidUniqueId; - DetectCollision_Cached(mgr, cache, *actor.GetCollisionPrimitive(), actor.GetPrimitiveTransform(), - actor.GetMaterialFilter(), useColliderList, id, accumList); - TCastToPtr otherActor = mgr.ObjectById(id); - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); - zeus::CVector3f relVel = GetActorRelativeVelocities(actor, otherActor.GetPtr()); - CCollisionInfoList filterList0, filterList1; - CollisionUtil::FilterOutBackfaces(relVel, accumList, filterList0); - if (filterList0.GetCount() > 0) - { - filter.Filter(filterList0, filterList1); - if (!filterList1.GetCount() && actor.GetMaterialList().HasMaterial(EMaterialTypes::Player)) - { - CMotionState mState = actor.GetLastNonCollidingState(); - mState.x1c_velocity *= zeus::CVector3f(0.5f); - mState.x28_angularMomentum *= zeus::CVector3f(0.5f); - actor.SetMotionState(mState); - } - } - MakeCollisionCallbacks(mgr, actor, id, filterList1); - SendScriptMessages(mgr, actor, otherActor.GetPtr(), filterList1); - ResolveCollisions(actor, otherActor.GetPtr(), filterList1); - _4AC4 -= f31; - f27 = std::min(_4AC4, _4AC8); - f31 = f27; - } - else - { - f27 *= 0.5f; - f31 *= 0.5f; - } - } - else - { - actor.AddMotionState(mState); - _4AC4 -= f31; - f31 = f27; - actor.ClearImpulses(); - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); - } + f27 = _4AC4 / dt; + if (!r28 && !actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) + mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling); - ++r26; - if (_4AC4 > 0.f && ((mState.x0_translation.magnitude() > m3 && r27) || !r27) && r26 <= 1000) - mState = actor.PredictMotion_Internal(f31); - else - break; - } + if (isPlayer) + CollisionFailsafe(mgr, cache, actor, *actor.GetCollisionPrimitive(), useColliderList, f27, 2); - f27 = _4AC4 / dt; - if (!r28 && !actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) - mgr.SendScriptMsg(&actor, kInvalidUniqueId, EScriptObjectMessage::Falling); - - if (isPlayer) - CollisionFailsafe(mgr, cache, actor, *actor.GetCollisionPrimitive(), useColliderList, f27, 2); - - actor.ClearForcesAndTorques(); - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); + actor.ClearForcesAndTorques(); + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); } -zeus::CVector3f CGameCollision::GetActorRelativeVelocities(const CPhysicsActor& act0, const CPhysicsActor* act1) -{ - zeus::CVector3f ret = act0.GetVelocity(); - if (act1) - { - bool rider = false; - if (TCastToConstPtr plat = act1) - rider = plat->IsRider(act0.GetUniqueId()); - if (!rider) - ret -= act1->GetVelocity(); - } - return ret; +zeus::CVector3f CGameCollision::GetActorRelativeVelocities(const CPhysicsActor& act0, const CPhysicsActor* act1) { + zeus::CVector3f ret = act0.GetVelocity(); + if (act1) { + bool rider = false; + if (TCastToConstPtr plat = act1) + rider = plat->IsRider(act0.GetUniqueId()); + if (!rider) + ret -= act1->GetVelocity(); + } + return ret; } void CGameCollision::Move(CStateManager& mgr, CPhysicsActor& actor, float dt, - const rstl::reserved_vector* colliderList) -{ - if (!actor.IsMovable()) - return; - if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider) || actor.WillMove(mgr)) - { - if (actor.IsAngularEnabled()) - actor.AddMotionState(actor.PredictAngularMotion(dt)); - actor.UseCollisionImpulses(); - if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Solid)) - { - if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Player)) - MovePlayer(mgr, actor, dt, colliderList); - else if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) - CGroundMovement::MoveGroundCollider(mgr, actor, dt, colliderList); - else - MoveAndCollide(mgr, actor, dt, CAABoxFilter(actor), colliderList); - } - else - { - actor.AddMotionState(actor.PredictMotion_Internal(dt)); - actor.ClearForcesAndTorques(); - } - mgr.UpdateActorInSortedLists(actor); + const rstl::reserved_vector* colliderList) { + if (!actor.IsMovable()) + return; + if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider) || actor.WillMove(mgr)) { + if (actor.IsAngularEnabled()) + actor.AddMotionState(actor.PredictAngularMotion(dt)); + actor.UseCollisionImpulses(); + if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Solid)) { + if (actor.GetMaterialList().HasMaterial(EMaterialTypes::Player)) + MovePlayer(mgr, actor, dt, colliderList); + else if (actor.GetMaterialList().HasMaterial(EMaterialTypes::GroundCollider)) + CGroundMovement::MoveGroundCollider(mgr, actor, dt, colliderList); + else + MoveAndCollide(mgr, actor, dt, CAABoxFilter(actor), colliderList); + } else { + actor.AddMotionState(actor.PredictMotion_Internal(dt)); + actor.ClearForcesAndTorques(); } + mgr.UpdateActorInSortedLists(actor); + } } -bool CGameCollision::CanBlock(const CMaterialList& mat, const zeus::CVector3f& v) -{ - if ((mat.HasMaterial(EMaterialTypes::Character) && !mat.HasMaterial(EMaterialTypes::SolidCharacter)) || - mat.HasMaterial(EMaterialTypes::NoPlayerCollision)) - return false; +bool CGameCollision::CanBlock(const CMaterialList& mat, const zeus::CVector3f& v) { + if ((mat.HasMaterial(EMaterialTypes::Character) && !mat.HasMaterial(EMaterialTypes::SolidCharacter)) || + mat.HasMaterial(EMaterialTypes::NoPlayerCollision)) + return false; - if (mat.HasMaterial(EMaterialTypes::Floor)) - return true; + if (mat.HasMaterial(EMaterialTypes::Floor)) + return true; - return (v.z() > 0.85f); + return (v.z() > 0.85f); } -bool CGameCollision::IsFloor(const CMaterialList& mat, const zeus::CVector3f& v) -{ - if (mat.HasMaterial(EMaterialTypes::Floor)) - return true; - return (v.z() > 0.85f); +bool CGameCollision::IsFloor(const CMaterialList& mat, const zeus::CVector3f& v) { + if (mat.HasMaterial(EMaterialTypes::Floor)) + return true; + return (v.z() > 0.85f); } -void CGameCollision::SendMaterialMessage(CStateManager& mgr, const CMaterialList& mat, CActor& act) -{ - EScriptObjectMessage msg; - if (mat.HasMaterial(EMaterialTypes::Ice)) - msg = EScriptObjectMessage::OnIceSurface; - else if (mat.HasMaterial(EMaterialTypes::MudSlow)) - msg = EScriptObjectMessage::OnMudSlowSurface; - else - msg = EScriptObjectMessage::OnNormalSurface; +void CGameCollision::SendMaterialMessage(CStateManager& mgr, const CMaterialList& mat, CActor& act) { + EScriptObjectMessage msg; + if (mat.HasMaterial(EMaterialTypes::Ice)) + msg = EScriptObjectMessage::OnIceSurface; + else if (mat.HasMaterial(EMaterialTypes::MudSlow)) + msg = EScriptObjectMessage::OnMudSlowSurface; + else + msg = EScriptObjectMessage::OnNormalSurface; - mgr.SendScriptMsg(&act, kInvalidUniqueId, msg); + mgr.SendScriptMsg(&act, kInvalidUniqueId, msg); } -CRayCastResult -CGameCollision::RayStaticIntersection(const CStateManager& mgr, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float length, const CMaterialFilter& filter) -{ - CRayCastResult ret; - float bestT = length; - if (bestT <= 0.f) - bestT = 100000.f; +CRayCastResult CGameCollision::RayStaticIntersection(const CStateManager& mgr, const zeus::CVector3f& pos, + const zeus::CVector3f& dir, float length, + const CMaterialFilter& filter) { + CRayCastResult ret; + float bestT = length; + if (bestT <= 0.f) + bestT = 100000.f; - zeus::CLine line(pos, dir); - for (const CGameArea& area : *mgr.GetWorld()) - { - CAreaOctTree::SRayResult rayRes; - CAreaOctTree& collision = *area.GetPostConstructed()->x0_collision; - collision.GetRootNode().LineTestEx(line, filter, rayRes, length); - if (!rayRes.x10_surface || (length != 0.f && length < rayRes.x3c_t)) - continue; + zeus::CLine line(pos, dir); + for (const CGameArea& area : *mgr.GetWorld()) { + CAreaOctTree::SRayResult rayRes; + CAreaOctTree& collision = *area.GetPostConstructed()->x0_collision; + collision.GetRootNode().LineTestEx(line, filter, rayRes, length); + if (!rayRes.x10_surface || (length != 0.f && length < rayRes.x3c_t)) + continue; - if (rayRes.x3c_t < bestT) - { - ret = CRayCastResult(rayRes.x3c_t, dir * rayRes.x3c_t + pos, - rayRes.x0_plane, rayRes.x10_surface->GetSurfaceFlags()); - bestT = rayRes.x3c_t; - } + if (rayRes.x3c_t < bestT) { + ret = CRayCastResult(rayRes.x3c_t, dir * rayRes.x3c_t + pos, rayRes.x0_plane, + rayRes.x10_surface->GetSurfaceFlags()); + bestT = rayRes.x3c_t; } + } - return ret; + return ret; } bool CGameCollision::RayStaticIntersectionBool(const CStateManager& mgr, const zeus::CVector3f& start, const zeus::CVector3f& dir, float length, - const CMaterialFilter& filter) -{ - if (length <= 0.f) - length = 100000.f; - zeus::CLine line(start, dir); - for (const CGameArea& area : *mgr.GetWorld()) - { - const CAreaOctTree& collision = *area.GetPostConstructed()->x0_collision; - CAreaOctTree::Node root = collision.GetRootNode(); - if (!root.LineTest(line, filter, length)) - return false; - } + const CMaterialFilter& filter) { + if (length <= 0.f) + length = 100000.f; + zeus::CLine line(start, dir); + for (const CGameArea& area : *mgr.GetWorld()) { + const CAreaOctTree& collision = *area.GetPostConstructed()->x0_collision; + CAreaOctTree::Node root = collision.GetRootNode(); + if (!root.LineTest(line, filter, length)) + return false; + } - return true; + return true; } -CRayCastResult -CGameCollision::RayDynamicIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float length, const CMaterialFilter& filter, - const rstl::reserved_vector& nearList) -{ - CRayCastResult ret; - float bestT = length; - if (bestT <= 0.f) - bestT = 100000.f; +CRayCastResult CGameCollision::RayDynamicIntersection(const CStateManager& mgr, TUniqueId& idOut, + const zeus::CVector3f& pos, const zeus::CVector3f& dir, + float length, const CMaterialFilter& filter, + const rstl::reserved_vector& nearList) { + CRayCastResult ret; + float bestT = length; + if (bestT <= 0.f) + bestT = 100000.f; - for (TUniqueId id : nearList) - { - CEntity* ent = const_cast(mgr.GetObjectById(id)); - if (TCastToPtr physActor = ent) - { - zeus::CTransform xf = physActor->GetPrimitiveTransform(); - const CCollisionPrimitive* prim = physActor->GetCollisionPrimitive(); - CRayCastResult res = prim->CastRay(pos, dir, bestT, filter, xf); - if (!res.IsInvalid() && res.GetT() < bestT) - { - bestT = res.GetT(); - ret = res; - idOut = physActor->GetUniqueId(); - } - } + for (TUniqueId id : nearList) { + CEntity* ent = const_cast(mgr.GetObjectById(id)); + if (TCastToPtr physActor = ent) { + zeus::CTransform xf = physActor->GetPrimitiveTransform(); + const CCollisionPrimitive* prim = physActor->GetCollisionPrimitive(); + CRayCastResult res = prim->CastRay(pos, dir, bestT, filter, xf); + if (!res.IsInvalid() && res.GetT() < bestT) { + bestT = res.GetT(); + ret = res; + idOut = physActor->GetUniqueId(); + } } + } - return ret; + return ret; } -bool CGameCollision::RayDynamicIntersectionBool(const CStateManager& mgr, - const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const CMaterialFilter& filter, +bool CGameCollision::RayDynamicIntersectionBool(const CStateManager& mgr, const zeus::CVector3f& pos, + const zeus::CVector3f& dir, const CMaterialFilter& filter, const rstl::reserved_vector& nearList, - const CActor* damagee, float length) -{ - if (length <= 0.f) - length = 100000.f; + const CActor* damagee, float length) { + if (length <= 0.f) + length = 100000.f; - for (TUniqueId id : nearList) - { - const CEntity* ent = mgr.GetObjectById(id); - if (TCastToConstPtr physActor = ent) - { - if (damagee && physActor->GetUniqueId() == damagee->GetUniqueId()) - continue; - zeus::CTransform xf = physActor->GetPrimitiveTransform(); - const CCollisionPrimitive* prim = physActor->GetCollisionPrimitive(); - CRayCastResult res = prim->CastRay(pos, dir, length, filter, xf); - if (!res.IsInvalid()) - return false; - } + for (TUniqueId id : nearList) { + const CEntity* ent = mgr.GetObjectById(id); + if (TCastToConstPtr physActor = ent) { + if (damagee && physActor->GetUniqueId() == damagee->GetUniqueId()) + continue; + zeus::CTransform xf = physActor->GetPrimitiveTransform(); + const CCollisionPrimitive* prim = physActor->GetCollisionPrimitive(); + CRayCastResult res = prim->CastRay(pos, dir, length, filter, xf); + if (!res.IsInvalid()) + return false; } + } - return true; + return true; } -CRayCastResult -CGameCollision::RayWorldIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter, - const rstl::reserved_vector& nearList) -{ - CRayCastResult staticRes = RayStaticIntersection(mgr, pos, dir, mag, filter); - CRayCastResult dynamicRes = RayDynamicIntersection(mgr, idOut, pos, dir, mag, filter, nearList); +CRayCastResult CGameCollision::RayWorldIntersection(const CStateManager& mgr, TUniqueId& idOut, + const zeus::CVector3f& pos, const zeus::CVector3f& dir, float mag, + const CMaterialFilter& filter, + const rstl::reserved_vector& nearList) { + CRayCastResult staticRes = RayStaticIntersection(mgr, pos, dir, mag, filter); + CRayCastResult dynamicRes = RayDynamicIntersection(mgr, idOut, pos, dir, mag, filter, nearList); - if (dynamicRes.IsValid()) - { - if (staticRes.IsInvalid()) - return dynamicRes; - else if (staticRes.GetT() >= dynamicRes.GetT()) - return dynamicRes; - } - return staticRes; + if (dynamicRes.IsValid()) { + if (staticRes.IsInvalid()) + return dynamicRes; + else if (staticRes.GetT() >= dynamicRes.GetT()) + return dynamicRes; + } + return staticRes; } bool CGameCollision::RayStaticIntersectionArea(const CGameArea& area, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter) -{ - if (mag <= 0.f) - mag = 100000.f; - CAreaOctTree::Node node = area.GetPostConstructed()->x0_collision->GetRootNode(); - zeus::CLine line(pos, dir); - return node.LineTest(line, filter, mag); + const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter) { + if (mag <= 0.f) + mag = 100000.f; + CAreaOctTree::Node node = area.GetPostConstructed()->x0_collision->GetRootNode(); + zeus::CLine line(pos, dir); + return node.LineTest(line, filter, mag); } -void CGameCollision::BuildAreaCollisionCache(const CStateManager& mgr, CAreaCollisionCache& cache) -{ - cache.ClearCache(); - for (const CGameArea& area : *mgr.GetWorld()) - { - const CAreaOctTree& areaCollision = *area.GetPostConstructed()->x0_collision; - CMetroidAreaCollider::COctreeLeafCache octreeCache(areaCollision); - CMetroidAreaCollider::BuildOctreeLeafCache(areaCollision.GetRootNode(), - cache.GetCacheBounds(), octreeCache); - cache.AddOctreeLeafCache(octreeCache); - } +void CGameCollision::BuildAreaCollisionCache(const CStateManager& mgr, CAreaCollisionCache& cache) { + cache.ClearCache(); + for (const CGameArea& area : *mgr.GetWorld()) { + const CAreaOctTree& areaCollision = *area.GetPostConstructed()->x0_collision; + CMetroidAreaCollider::COctreeLeafCache octreeCache(areaCollision); + CMetroidAreaCollider::BuildOctreeLeafCache(areaCollision.GetRootNode(), cache.GetCacheBounds(), octreeCache); + cache.AddOctreeLeafCache(octreeCache); + } } -float CGameCollision::GetMinExtentForCollisionPrimitive(const CCollisionPrimitive& prim) -{ - if (prim.GetPrimType() == FOURCC('SPHR')) - { - const CCollidableSphere& sphere = static_cast(prim); - return 2.f * sphere.GetSphere().radius; - } - else if (prim.GetPrimType() == FOURCC('AABX')) - { - const CCollidableAABox& aabx = static_cast(prim); - const zeus::CVector3f extent = aabx.GetAABB().max - aabx.GetAABB().min; - float minExtent = std::min(extent.x(), extent.y()); - minExtent = std::min(minExtent, extent.z()); - return minExtent; - } - else if (prim.GetPrimType() == FOURCC('ABSH')) - { - // Combination AABB / Sphere cut from game - } - return 1.f; +float CGameCollision::GetMinExtentForCollisionPrimitive(const CCollisionPrimitive& prim) { + if (prim.GetPrimType() == FOURCC('SPHR')) { + const CCollidableSphere& sphere = static_cast(prim); + return 2.f * sphere.GetSphere().radius; + } else if (prim.GetPrimType() == FOURCC('AABX')) { + const CCollidableAABox& aabx = static_cast(prim); + const zeus::CVector3f extent = aabx.GetAABB().max - aabx.GetAABB().min; + float minExtent = std::min(extent.x(), extent.y()); + minExtent = std::min(minExtent, extent.z()); + return minExtent; + } else if (prim.GetPrimType() == FOURCC('ABSH')) { + // Combination AABB / Sphere cut from game + } + return 1.f; } bool CGameCollision::DetectCollisionBoolean(const CStateManager& mgr, const CCollisionPrimitive& prim, const zeus::CTransform& xf, const CMaterialFilter& filter, - const rstl::reserved_vector& nearList) -{ - if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision) && - DetectStaticCollisionBoolean(mgr, prim, xf, filter)) - return true; - if (DetectDynamicCollisionBoolean(prim, xf, nearList, mgr)) - return true; - return false; + const rstl::reserved_vector& nearList) { + if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision) && + DetectStaticCollisionBoolean(mgr, prim, xf, filter)) + return true; + if (DetectDynamicCollisionBoolean(prim, xf, nearList, mgr)) + return true; + return false; } bool CGameCollision::DetectCollisionBoolean_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, const CCollisionPrimitive& prim, const zeus::CTransform& xf, const CMaterialFilter& filter, - const rstl::reserved_vector& nearList) -{ - if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision) && - DetectStaticCollisionBoolean_Cached(mgr, cache, prim, xf, filter)) - return true; - if (DetectDynamicCollisionBoolean(prim, xf, nearList, mgr)) - return true; - return false; + const rstl::reserved_vector& nearList) { + if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision) && + DetectStaticCollisionBoolean_Cached(mgr, cache, prim, xf, filter)) + return true; + if (DetectDynamicCollisionBoolean(prim, xf, nearList, mgr)) + return true; + return false; } bool CGameCollision::DetectStaticCollisionBoolean(const CStateManager& mgr, const CCollisionPrimitive& prim, - const zeus::CTransform& xf, const CMaterialFilter& filter) -{ - if (prim.GetPrimType() == FOURCC('OBTG')) - return false; - - if (prim.GetPrimType() == FOURCC('AABX')) - { - zeus::CAABox aabb = prim.CalculateAABox(xf); - for (const CGameArea& area : *mgr.GetWorld()) - { - if (CMetroidAreaCollider::AABoxCollisionCheckBoolean( - *area.GetPostConstructed()->x0_collision, aabb, filter)) - return true; - } - } - else if (prim.GetPrimType() == FOURCC('SPHR')) - { - const CCollidableSphere& sphere = static_cast(prim); - zeus::CAABox aabb = prim.CalculateAABox(xf); - zeus::CSphere xfSphere = sphere.Transform(xf); - for (const CGameArea& area : *mgr.GetWorld()) - { - if (CMetroidAreaCollider::SphereCollisionCheckBoolean( - *area.GetPostConstructed()->x0_collision, aabb, xfSphere, filter)) - return true; - } - } - else if (prim.GetPrimType() == FOURCC('ABSH')) - { - // Combination AABB / Sphere cut from game - } - + const zeus::CTransform& xf, const CMaterialFilter& filter) { + if (prim.GetPrimType() == FOURCC('OBTG')) return false; + + if (prim.GetPrimType() == FOURCC('AABX')) { + zeus::CAABox aabb = prim.CalculateAABox(xf); + for (const CGameArea& area : *mgr.GetWorld()) { + if (CMetroidAreaCollider::AABoxCollisionCheckBoolean(*area.GetPostConstructed()->x0_collision, aabb, filter)) + return true; + } + } else if (prim.GetPrimType() == FOURCC('SPHR')) { + const CCollidableSphere& sphere = static_cast(prim); + zeus::CAABox aabb = prim.CalculateAABox(xf); + zeus::CSphere xfSphere = sphere.Transform(xf); + for (const CGameArea& area : *mgr.GetWorld()) { + if (CMetroidAreaCollider::SphereCollisionCheckBoolean(*area.GetPostConstructed()->x0_collision, aabb, xfSphere, + filter)) + return true; + } + } else if (prim.GetPrimType() == FOURCC('ABSH')) { + // Combination AABB / Sphere cut from game + } + + return false; } bool CGameCollision::DetectStaticCollisionBoolean_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const CMaterialFilter& filter) -{ - if (prim.GetPrimType() == FOURCC('OBTG')) - return false; - - zeus::CAABox aabb = prim.CalculateAABox(xf); - if (!aabb.inside(cache.GetCacheBounds())) - { - zeus::CAABox newAABB(aabb.min - 0.2f, aabb.max + 0.2f); - newAABB.accumulateBounds(cache.GetCacheBounds()); - cache.SetCacheBounds(newAABB); - BuildAreaCollisionCache(mgr, cache); - } - - if (cache.HasCacheOverflowed()) - return DetectStaticCollisionBoolean(mgr, prim, xf, filter); - - if (prim.GetPrimType() == FOURCC('AABX')) - { - for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) - if (CMetroidAreaCollider::AABoxCollisionCheckBoolean_Cached(leafCache, aabb, filter)) - return true; - } - else if (prim.GetPrimType() == FOURCC('SPHR')) - { - const CCollidableSphere& sphere = static_cast(prim); - zeus::CSphere xfSphere = sphere.Transform(xf); - for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) - if (CMetroidAreaCollider::SphereCollisionCheckBoolean_Cached(leafCache, aabb, xfSphere, filter)) - return true; - } - else if (prim.GetPrimType() == FOURCC('ABSH')) - { - // Combination AABB / Sphere cut from game - } - + const CMaterialFilter& filter) { + if (prim.GetPrimType() == FOURCC('OBTG')) return false; + + zeus::CAABox aabb = prim.CalculateAABox(xf); + if (!aabb.inside(cache.GetCacheBounds())) { + zeus::CAABox newAABB(aabb.min - 0.2f, aabb.max + 0.2f); + newAABB.accumulateBounds(cache.GetCacheBounds()); + cache.SetCacheBounds(newAABB); + BuildAreaCollisionCache(mgr, cache); + } + + if (cache.HasCacheOverflowed()) + return DetectStaticCollisionBoolean(mgr, prim, xf, filter); + + if (prim.GetPrimType() == FOURCC('AABX')) { + for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) + if (CMetroidAreaCollider::AABoxCollisionCheckBoolean_Cached(leafCache, aabb, filter)) + return true; + } else if (prim.GetPrimType() == FOURCC('SPHR')) { + const CCollidableSphere& sphere = static_cast(prim); + zeus::CSphere xfSphere = sphere.Transform(xf); + for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) + if (CMetroidAreaCollider::SphereCollisionCheckBoolean_Cached(leafCache, aabb, xfSphere, filter)) + return true; + } else if (prim.GetPrimType() == FOURCC('ABSH')) { + // Combination AABB / Sphere cut from game + } + + return false; } bool CGameCollision::DetectDynamicCollisionBoolean(const CCollisionPrimitive& prim, const zeus::CTransform& xf, const rstl::reserved_vector& nearList, - const CStateManager& mgr) -{ - for (TUniqueId id : nearList) - { - if (TCastToConstPtr actor = mgr.GetObjectById(id)) - { - CInternalCollisionStructure::CPrimDesc p0(prim, CMaterialFilter::skPassEverything, xf); - CInternalCollisionStructure::CPrimDesc p1(*actor->GetCollisionPrimitive(), - CMaterialFilter::skPassEverything, - actor->GetPrimitiveTransform()); - if (CCollisionPrimitive::CollideBoolean(p0, p1)) - return true; - } + const CStateManager& mgr) { + for (TUniqueId id : nearList) { + if (TCastToConstPtr actor = mgr.GetObjectById(id)) { + CInternalCollisionStructure::CPrimDesc p0(prim, CMaterialFilter::skPassEverything, xf); + CInternalCollisionStructure::CPrimDesc p1(*actor->GetCollisionPrimitive(), CMaterialFilter::skPassEverything, + actor->GetPrimitiveTransform()); + if (CCollisionPrimitive::CollideBoolean(p0, p1)) + return true; } + } - return false; + return false; } bool CGameCollision::DetectCollision_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, const CCollisionPrimitive& prim, const zeus::CTransform& xf, const CMaterialFilter& filter, - const rstl::reserved_vector& nearList, - TUniqueId& idOut, CCollisionInfoList& infoList) -{ - idOut = kInvalidUniqueId; - bool ret = false; - if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision)) - if (DetectStaticCollision_Cached(mgr, cache, prim, xf, filter, infoList)) - ret = true; + const rstl::reserved_vector& nearList, TUniqueId& idOut, + CCollisionInfoList& infoList) { + idOut = kInvalidUniqueId; + bool ret = false; + if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision)) + if (DetectStaticCollision_Cached(mgr, cache, prim, xf, filter, infoList)) + ret = true; - TUniqueId id = kInvalidUniqueId; - if (DetectDynamicCollision(prim, xf, nearList, id, infoList, mgr)) - { - ret = true; - idOut = id; - } + TUniqueId id = kInvalidUniqueId; + if (DetectDynamicCollision(prim, xf, nearList, id, infoList, mgr)) { + ret = true; + idOut = id; + } - return ret; + return ret; } bool CGameCollision::DetectCollision_Cached_Moving(const CStateManager& mgr, CAreaCollisionCache& cache, const CCollisionPrimitive& prim, const zeus::CTransform& xf, const CMaterialFilter& filter, const rstl::reserved_vector& nearList, - const zeus::CVector3f& dir, - TUniqueId& idOut, CCollisionInfo& infoOut, double& d) -{ - bool ret = false; - idOut = kInvalidUniqueId; - if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision)) - if (CGameCollision::DetectStaticCollision_Cached_Moving(mgr, cache, prim, xf, filter, dir, infoOut, d)) - ret = true; + const zeus::CVector3f& dir, TUniqueId& idOut, + CCollisionInfo& infoOut, double& d) { + bool ret = false; + idOut = kInvalidUniqueId; + if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::NoStaticCollision)) + if (CGameCollision::DetectStaticCollision_Cached_Moving(mgr, cache, prim, xf, filter, dir, infoOut, d)) + ret = true; - if (CGameCollision::DetectDynamicCollisionMoving(prim, xf, nearList, dir, idOut, infoOut, d, mgr)) - ret = true; + if (CGameCollision::DetectDynamicCollisionMoving(prim, xf, nearList, dir, idOut, infoOut, d, mgr)) + ret = true; - return ret; + return ret; } bool CGameCollision::DetectStaticCollision(const CStateManager& mgr, const CCollisionPrimitive& prim, const zeus::CTransform& xf, const CMaterialFilter& filter, - CCollisionInfoList& list) -{ - if (prim.GetPrimType() == FOURCC('OBTG')) - return false; + CCollisionInfoList& list) { + if (prim.GetPrimType() == FOURCC('OBTG')) + return false; - bool ret = false; - if (prim.GetPrimType() == FOURCC('AABX')) - { - zeus::CAABox aabb = prim.CalculateAABox(xf); - for (const CGameArea& area : *mgr.GetWorld()) - { - if (CMetroidAreaCollider::AABoxCollisionCheck( - *area.GetPostConstructed()->x0_collision, aabb, filter, - prim.GetMaterial(), list)) - ret = true; - } + bool ret = false; + if (prim.GetPrimType() == FOURCC('AABX')) { + zeus::CAABox aabb = prim.CalculateAABox(xf); + for (const CGameArea& area : *mgr.GetWorld()) { + if (CMetroidAreaCollider::AABoxCollisionCheck(*area.GetPostConstructed()->x0_collision, aabb, filter, + prim.GetMaterial(), list)) + ret = true; } - else if (prim.GetPrimType() == FOURCC('SPHR')) - { - const CCollidableSphere& sphere = static_cast(prim); - zeus::CAABox aabb = prim.CalculateAABox(xf); - zeus::CSphere xfSphere = sphere.Transform(xf); - for (const CGameArea& area : *mgr.GetWorld()) - { - if (CMetroidAreaCollider::SphereCollisionCheck( - *area.GetPostConstructed()->x0_collision, aabb, xfSphere, - prim.GetMaterial(), filter, list)) - ret = true; - } - } - else if (prim.GetPrimType() == FOURCC('ABSH')) - { - // Combination AABB / Sphere cut from game + } else if (prim.GetPrimType() == FOURCC('SPHR')) { + const CCollidableSphere& sphere = static_cast(prim); + zeus::CAABox aabb = prim.CalculateAABox(xf); + zeus::CSphere xfSphere = sphere.Transform(xf); + for (const CGameArea& area : *mgr.GetWorld()) { + if (CMetroidAreaCollider::SphereCollisionCheck(*area.GetPostConstructed()->x0_collision, aabb, xfSphere, + prim.GetMaterial(), filter, list)) + ret = true; } + } else if (prim.GetPrimType() == FOURCC('ABSH')) { + // Combination AABB / Sphere cut from game + } - return ret; + return ret; } bool CGameCollision::DetectStaticCollision_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const CMaterialFilter& filter, CCollisionInfoList& list) -{ - if (prim.GetPrimType() == FOURCC('OBTG')) - return false; + const CMaterialFilter& filter, CCollisionInfoList& list) { + if (prim.GetPrimType() == FOURCC('OBTG')) + return false; - bool ret = false; - zeus::CAABox calcAABB = prim.CalculateAABox(xf); - if (!calcAABB.inside(cache.GetCacheBounds())) - { - zeus::CAABox newAABB(calcAABB.min - 0.2f, calcAABB.max + 0.2f); - newAABB.accumulateBounds(cache.GetCacheBounds()); - cache.SetCacheBounds(newAABB); - BuildAreaCollisionCache(mgr, cache); - } + bool ret = false; + zeus::CAABox calcAABB = prim.CalculateAABox(xf); + if (!calcAABB.inside(cache.GetCacheBounds())) { + zeus::CAABox newAABB(calcAABB.min - 0.2f, calcAABB.max + 0.2f); + newAABB.accumulateBounds(cache.GetCacheBounds()); + cache.SetCacheBounds(newAABB); + BuildAreaCollisionCache(mgr, cache); + } - if (cache.HasCacheOverflowed()) - return DetectStaticCollision(mgr, prim, xf, filter, list); + if (cache.HasCacheOverflowed()) + return DetectStaticCollision(mgr, prim, xf, filter, list); - if (prim.GetPrimType() == FOURCC('AABX')) - { - for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) - if (CMetroidAreaCollider::AABoxCollisionCheck_Cached(leafCache, calcAABB, filter, - prim.GetMaterial(), list)) - ret = true; - } - else if (prim.GetPrimType() == FOURCC('SPHR')) - { - const CCollidableSphere& sphere = static_cast(prim); - zeus::CSphere xfSphere = sphere.Transform(xf); - for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) - if (CMetroidAreaCollider::SphereCollisionCheck_Cached(leafCache, calcAABB, xfSphere, - prim.GetMaterial(), filter, list)) - ret = true; - } - else if (prim.GetPrimType() == FOURCC('ABSH')) - { - // Combination AABB / Sphere cut from game - } + if (prim.GetPrimType() == FOURCC('AABX')) { + for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) + if (CMetroidAreaCollider::AABoxCollisionCheck_Cached(leafCache, calcAABB, filter, prim.GetMaterial(), list)) + ret = true; + } else if (prim.GetPrimType() == FOURCC('SPHR')) { + const CCollidableSphere& sphere = static_cast(prim); + zeus::CSphere xfSphere = sphere.Transform(xf); + for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) + if (CMetroidAreaCollider::SphereCollisionCheck_Cached(leafCache, calcAABB, xfSphere, prim.GetMaterial(), filter, + list)) + ret = true; + } else if (prim.GetPrimType() == FOURCC('ABSH')) { + // Combination AABB / Sphere cut from game + } - return ret; + return ret; } bool CGameCollision::DetectStaticCollision_Cached_Moving(const CStateManager& mgr, CAreaCollisionCache& cache, const CCollisionPrimitive& prim, const zeus::CTransform& xf, const CMaterialFilter& filter, const zeus::CVector3f& dir, - CCollisionInfo& infoOut, double& dOut) -{ - if (prim.GetPrimType() == FOURCC('OBTG')) - return false; + CCollisionInfo& infoOut, double& dOut) { + if (prim.GetPrimType() == FOURCC('OBTG')) + return false; - zeus::CVector3f offset = float(dOut) * dir; - zeus::CAABox aabb = prim.CalculateAABox(xf); - zeus::CAABox offsetAABB = aabb; - offsetAABB.accumulateBounds(offset + offsetAABB.min); - offsetAABB.accumulateBounds(offset + offsetAABB.max); + zeus::CVector3f offset = float(dOut) * dir; + zeus::CAABox aabb = prim.CalculateAABox(xf); + zeus::CAABox offsetAABB = aabb; + offsetAABB.accumulateBounds(offset + offsetAABB.min); + offsetAABB.accumulateBounds(offset + offsetAABB.max); - if (!offsetAABB.inside(cache.GetCacheBounds())) - { - zeus::CAABox newAABB(offsetAABB.min - 0.2f, offsetAABB.max + 0.2f); - newAABB.accumulateBounds(cache.GetCacheBounds()); - cache.SetCacheBounds(newAABB); - BuildAreaCollisionCache(mgr, cache); + if (!offsetAABB.inside(cache.GetCacheBounds())) { + zeus::CAABox newAABB(offsetAABB.min - 0.2f, offsetAABB.max + 0.2f); + newAABB.accumulateBounds(cache.GetCacheBounds()); + cache.SetCacheBounds(newAABB); + BuildAreaCollisionCache(mgr, cache); + } + + if (prim.GetPrimType() == FOURCC('AABX')) { + for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) { + CCollisionInfo info; + double d = dOut; + if (CMetroidAreaCollider::MovingAABoxCollisionCheck_Cached( + leafCache, aabb, filter, CMaterialList(EMaterialTypes::Solid), dir, dOut, info, d) && + d < dOut) { + infoOut = info; + dOut = d; + } } - - if (prim.GetPrimType() == FOURCC('AABX')) - { - for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) - { - CCollisionInfo info; - double d = dOut; - if (CMetroidAreaCollider::MovingAABoxCollisionCheck_Cached(leafCache, aabb, filter, - CMaterialList(EMaterialTypes::Solid), dir, - dOut, info, d) && d < dOut) - { - infoOut = info; - dOut = d; - } - } - } - else if (prim.GetPrimType() == FOURCC('SPHR')) - { - const CCollidableSphere& sphere = static_cast(prim); - zeus::CSphere xfSphere = sphere.Transform(xf); - for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) - { - CCollisionInfo info; - double d = dOut; - if (CMetroidAreaCollider::MovingSphereCollisionCheck_Cached(leafCache, aabb, xfSphere, filter, - CMaterialList(EMaterialTypes::Solid), dir, - dOut, info, d) && d < dOut) - { - infoOut = info; - dOut = d; - } - } + } else if (prim.GetPrimType() == FOURCC('SPHR')) { + const CCollidableSphere& sphere = static_cast(prim); + zeus::CSphere xfSphere = sphere.Transform(xf); + for (CMetroidAreaCollider::COctreeLeafCache& leafCache : cache) { + CCollisionInfo info; + double d = dOut; + if (CMetroidAreaCollider::MovingSphereCollisionCheck_Cached( + leafCache, aabb, xfSphere, filter, CMaterialList(EMaterialTypes::Solid), dir, dOut, info, d) && + d < dOut) { + infoOut = info; + dOut = d; + } } + } - return infoOut.IsValid(); + return infoOut.IsValid(); } bool CGameCollision::DetectDynamicCollision(const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const rstl::reserved_vector& nearList, - TUniqueId& idOut, CCollisionInfoList& list, const CStateManager& mgr) -{ - for (TUniqueId id : nearList) - { - if (TCastToConstPtr actor = mgr.GetObjectById(id)) - { - CInternalCollisionStructure::CPrimDesc p0(prim, CMaterialFilter::skPassEverything, xf); - CInternalCollisionStructure::CPrimDesc p1(*actor->GetCollisionPrimitive(), - CMaterialFilter::skPassEverything, - actor->GetPrimitiveTransform()); - if (CCollisionPrimitive::Collide(p0, p1, list)) - { - idOut = actor->GetUniqueId(); - return true; - } - } + const rstl::reserved_vector& nearList, TUniqueId& idOut, + CCollisionInfoList& list, const CStateManager& mgr) { + for (TUniqueId id : nearList) { + if (TCastToConstPtr actor = mgr.GetObjectById(id)) { + CInternalCollisionStructure::CPrimDesc p0(prim, CMaterialFilter::skPassEverything, xf); + CInternalCollisionStructure::CPrimDesc p1(*actor->GetCollisionPrimitive(), CMaterialFilter::skPassEverything, + actor->GetPrimitiveTransform()); + if (CCollisionPrimitive::Collide(p0, p1, list)) { + idOut = actor->GetUniqueId(); + return true; + } } + } - return false; + return false; } bool CGameCollision::DetectDynamicCollisionMoving(const CCollisionPrimitive& prim, const zeus::CTransform& xf, const rstl::reserved_vector& nearList, - const zeus::CVector3f& dir, TUniqueId& idOut, - CCollisionInfo& infoOut, double& dOut, const CStateManager& mgr) -{ - bool ret = false; - for (TUniqueId id : nearList) - { - double d = dOut; - CCollisionInfo info; - if (TCastToConstPtr actor = mgr.GetObjectById(id)) - { - CInternalCollisionStructure::CPrimDesc p0(prim, CMaterialFilter::skPassEverything, xf); - CInternalCollisionStructure::CPrimDesc p1(*actor->GetCollisionPrimitive(), - CMaterialFilter::skPassEverything, - actor->GetPrimitiveTransform()); - if (CCollisionPrimitive::CollideMoving(p0, p1, dir, d, info) && d < dOut) - { - ret = true; - infoOut = info; - dOut = d; - idOut = actor->GetUniqueId(); - } - } + const zeus::CVector3f& dir, TUniqueId& idOut, CCollisionInfo& infoOut, + double& dOut, const CStateManager& mgr) { + bool ret = false; + for (TUniqueId id : nearList) { + double d = dOut; + CCollisionInfo info; + if (TCastToConstPtr actor = mgr.GetObjectById(id)) { + CInternalCollisionStructure::CPrimDesc p0(prim, CMaterialFilter::skPassEverything, xf); + CInternalCollisionStructure::CPrimDesc p1(*actor->GetCollisionPrimitive(), CMaterialFilter::skPassEverything, + actor->GetPrimitiveTransform()); + if (CCollisionPrimitive::CollideMoving(p0, p1, dir, d, info) && d < dOut) { + ret = true; + infoOut = info; + dOut = d; + idOut = actor->GetUniqueId(); + } } + } - return ret; + return ret; } -void CGameCollision::MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor, - TUniqueId id, const CCollisionInfoList& list) -{ - actor.CollidedWith(id, list, mgr); - if (id != kInvalidUniqueId) - { - if (TCastToPtr actor = mgr.ObjectById(id)) - { - CCollisionInfoList swappedList = list; - for (CCollisionInfo& info : swappedList) - info.Swap(); - actor->CollidedWith(actor->GetUniqueId(), list, mgr); - } +void CGameCollision::MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor, TUniqueId id, + const CCollisionInfoList& list) { + actor.CollidedWith(id, list, mgr); + if (id != kInvalidUniqueId) { + if (TCastToPtr actor = mgr.ObjectById(id)) { + CCollisionInfoList swappedList = list; + for (CCollisionInfo& info : swappedList) + info.Swap(); + actor->CollidedWith(actor->GetUniqueId(), list, mgr); } + } } -void CGameCollision::SendScriptMessages(CStateManager& mgr, CActor& a0, CActor* a1, const CCollisionInfoList& list) -{ - bool onFloor = false; - bool platform = false; - bool platform2 = false; - for (const CCollisionInfo& info : list) - { - if (IsFloor(info.GetMaterialLeft(), info.GetNormalLeft())) - { - onFloor = true; - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Platform)) - platform = true; +void CGameCollision::SendScriptMessages(CStateManager& mgr, CActor& a0, CActor* a1, const CCollisionInfoList& list) { + bool onFloor = false; + bool platform = false; + bool platform2 = false; + for (const CCollisionInfo& info : list) { + if (IsFloor(info.GetMaterialLeft(), info.GetNormalLeft())) { + onFloor = true; + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Platform)) + platform = true; + SendMaterialMessage(mgr, info.GetMaterialLeft(), a0); + } + } + + if (onFloor) { + mgr.SendScriptMsg(&a0, kInvalidUniqueId, EScriptObjectMessage::OnFloor); + if (platform) { + if (TCastToPtr plat = a1) { + mgr.SendScriptMsg(plat.GetPtr(), a0.GetUniqueId(), EScriptObjectMessage::AddPlatformRider); + } + } else if (a1) { + if (TCastToPtr plat = a0) { + for (const CCollisionInfo& info : list) { + if (IsFloor(info.GetMaterialRight(), info.GetNormalRight())) { + if (info.GetMaterialRight().HasMaterial(EMaterialTypes::Platform)) + platform2 = true; SendMaterialMessage(mgr, info.GetMaterialLeft(), a0); + } } + if (platform2) { + mgr.SendScriptMsg(plat.GetPtr(), a1->GetUniqueId(), EScriptObjectMessage::AddPlatformRider); + } + } } - - if (onFloor) - { - mgr.SendScriptMsg(&a0, kInvalidUniqueId, EScriptObjectMessage::OnFloor); - if (platform) - { - if (TCastToPtr plat = a1) - { - mgr.SendScriptMsg(plat.GetPtr(), a0.GetUniqueId(), - EScriptObjectMessage::AddPlatformRider); - } - } - else if (a1) - { - if (TCastToPtr plat = a0) - { - for (const CCollisionInfo& info : list) - { - if (IsFloor(info.GetMaterialRight(), info.GetNormalRight())) - { - if (info.GetMaterialRight().HasMaterial(EMaterialTypes::Platform)) - platform2 = true; - SendMaterialMessage(mgr, info.GetMaterialLeft(), a0); - } - } - if (platform2) - { - mgr.SendScriptMsg(plat.GetPtr(), a1->GetUniqueId(), - EScriptObjectMessage::AddPlatformRider); - } - } - } - } + } } -void CGameCollision::ResolveCollisions(CPhysicsActor& a0, CPhysicsActor* a1, const CCollisionInfoList& list) -{ - for (const CCollisionInfo& info : list) - { - CCollisionInfo infoCopy = info; - float restitution = GetCoefficientOfRestitution(infoCopy) + a0.GetCoefficientOfRestitutionModifier(); - if (a1) - { - CollideWithDynamicBodyNoRot(a0, *a1, infoCopy, restitution, false); - } - else - { - CollideWithStaticBodyNoRot(a0, infoCopy.GetMaterialLeft(), infoCopy.GetMaterialRight(), - infoCopy.GetNormalLeft(), restitution, false); - } +void CGameCollision::ResolveCollisions(CPhysicsActor& a0, CPhysicsActor* a1, const CCollisionInfoList& list) { + for (const CCollisionInfo& info : list) { + CCollisionInfo infoCopy = info; + float restitution = GetCoefficientOfRestitution(infoCopy) + a0.GetCoefficientOfRestitutionModifier(); + if (a1) { + CollideWithDynamicBodyNoRot(a0, *a1, infoCopy, restitution, false); + } else { + CollideWithStaticBodyNoRot(a0, infoCopy.GetMaterialLeft(), infoCopy.GetMaterialRight(), infoCopy.GetNormalLeft(), + restitution, false); } + } } -void CGameCollision::CollideWithDynamicBodyNoRot(CPhysicsActor& a0, CPhysicsActor& a1, - const CCollisionInfo& info, float restitution, bool zeroZ) -{ - zeus::CVector3f normal = info.GetNormalLeft(); - if (zeroZ) - normal.z() = 0.f; +void CGameCollision::CollideWithDynamicBodyNoRot(CPhysicsActor& a0, CPhysicsActor& a1, const CCollisionInfo& info, + float restitution, bool zeroZ) { + zeus::CVector3f normal = info.GetNormalLeft(); + if (zeroZ) + normal.z() = 0.f; - zeus::CVector3f relVel = GetActorRelativeVelocities(a0, &a1); - float velNormDot = relVel.dot(normal); + zeus::CVector3f relVel = GetActorRelativeVelocities(a0, &a1); + float velNormDot = relVel.dot(normal); - float a0MaxCollisionVel = std::max(a0.GetVelocity().magnitude(), a0.GetMaximumCollisionVelocity()); - float a1MaxCollisionVel = std::max(a1.GetVelocity().magnitude(), a1.GetMaximumCollisionVelocity()); + float a0MaxCollisionVel = std::max(a0.GetVelocity().magnitude(), a0.GetMaximumCollisionVelocity()); + float a1MaxCollisionVel = std::max(a1.GetVelocity().magnitude(), a1.GetMaximumCollisionVelocity()); - bool a0Move = !a0.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) && a0.GetMass() != 0.f; - bool a1Move = !a1.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) && a1.GetMass() != 0.f; + bool a0Move = !a0.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) && a0.GetMass() != 0.f; + bool a1Move = !a1.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) && a1.GetMass() != 0.f; - if (velNormDot < -0.0001f) - { - if (a0Move) - { - if (a1Move) - { - float impulse = CollisionImpulseFiniteVsFinite(a0.GetMass(), a1.GetMass(), velNormDot, restitution); - a0.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity); - a1.ApplyImpulseWR(normal * -impulse, zeus::CAxisAngle::sIdentity); - } - else - { - float impulse = CollisionImpulseFiniteVsInfinite(a0.GetMass(), velNormDot, restitution); - a0.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity); - } - } - else - { - if (a1Move) - { - float impulse = CollisionImpulseFiniteVsInfinite(a1.GetMass(), velNormDot, restitution); - a1.ApplyImpulseWR(normal * -impulse, zeus::CAxisAngle::sIdentity); - } - else - { - a0.SetVelocityWR(zeus::CVector3f::skZero); - a1.SetVelocityWR(zeus::CVector3f::skZero); - } - } - a0.UseCollisionImpulses(); - a1.UseCollisionImpulses(); + if (velNormDot < -0.0001f) { + if (a0Move) { + if (a1Move) { + float impulse = CollisionImpulseFiniteVsFinite(a0.GetMass(), a1.GetMass(), velNormDot, restitution); + a0.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity); + a1.ApplyImpulseWR(normal * -impulse, zeus::CAxisAngle::sIdentity); + } else { + float impulse = CollisionImpulseFiniteVsInfinite(a0.GetMass(), velNormDot, restitution); + a0.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity); + } + } else { + if (a1Move) { + float impulse = CollisionImpulseFiniteVsInfinite(a1.GetMass(), velNormDot, restitution); + a1.ApplyImpulseWR(normal * -impulse, zeus::CAxisAngle::sIdentity); + } else { + a0.SetVelocityWR(zeus::CVector3f::skZero); + a1.SetVelocityWR(zeus::CVector3f::skZero); + } } - else if (velNormDot < 0.1f) - { - if (a0Move) - { - float impulse = 0.05f * a0.GetMass(); - a0.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity); - a0.UseCollisionImpulses(); - } - if (a1Move) - { - float impulse = -0.05f * a1.GetMass(); - a1.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity); - a1.UseCollisionImpulses(); - } + a0.UseCollisionImpulses(); + a1.UseCollisionImpulses(); + } else if (velNormDot < 0.1f) { + if (a0Move) { + float impulse = 0.05f * a0.GetMass(); + a0.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity); + a0.UseCollisionImpulses(); } + if (a1Move) { + float impulse = -0.05f * a1.GetMass(); + a1.ApplyImpulseWR(normal * impulse, zeus::CAxisAngle::sIdentity); + a1.UseCollisionImpulses(); + } + } - if (a0.GetVelocity().magnitude() > a0MaxCollisionVel) - a0.SetVelocityWR(a0.GetVelocity().normalized() * a0MaxCollisionVel); - if (a1.GetVelocity().magnitude() > a1MaxCollisionVel) - a1.SetVelocityWR(a1.GetVelocity().normalized() * a1MaxCollisionVel); + if (a0.GetVelocity().magnitude() > a0MaxCollisionVel) + a0.SetVelocityWR(a0.GetVelocity().normalized() * a0MaxCollisionVel); + if (a1.GetVelocity().magnitude() > a1MaxCollisionVel) + a1.SetVelocityWR(a1.GetVelocity().normalized() * a1MaxCollisionVel); } void CGameCollision::CollideWithStaticBodyNoRot(CPhysicsActor& a0, const CMaterialList& m0, const CMaterialList& m1, - const zeus::CUnitVector3f& normal, float restitution, bool zeroZ) -{ - zeus::CUnitVector3f useNorm = normal; - if (zeroZ && m0.HasMaterial(EMaterialTypes::Player) && !m1.HasMaterial(EMaterialTypes::Floor)) - useNorm.z() = 0.f; + const zeus::CUnitVector3f& normal, float restitution, bool zeroZ) { + zeus::CUnitVector3f useNorm = normal; + if (zeroZ && m0.HasMaterial(EMaterialTypes::Player) && !m1.HasMaterial(EMaterialTypes::Floor)) + useNorm.z() = 0.f; - if (useNorm.canBeNormalized()) - { - useNorm.normalize(); - float velNormDot = a0.GetVelocity().dot(useNorm); - if (velNormDot < 0.0001f) - { - a0.ApplyImpulseWR( - useNorm * CollisionImpulseFiniteVsInfinite(a0.GetMass(), velNormDot, restitution), - zeus::CAxisAngle::sIdentity); - a0.UseCollisionImpulses(); - } - else if (velNormDot < 0.001f) - { - a0.ApplyImpulseWR(0.05f * a0.GetMass() * useNorm, zeus::CAxisAngle::sIdentity); - a0.UseCollisionImpulses(); - } + if (useNorm.canBeNormalized()) { + useNorm.normalize(); + float velNormDot = a0.GetVelocity().dot(useNorm); + if (velNormDot < 0.0001f) { + a0.ApplyImpulseWR(useNorm * CollisionImpulseFiniteVsInfinite(a0.GetMass(), velNormDot, restitution), + zeus::CAxisAngle::sIdentity); + a0.UseCollisionImpulses(); + } else if (velNormDot < 0.001f) { + a0.ApplyImpulseWR(0.05f * a0.GetMass() * useNorm, zeus::CAxisAngle::sIdentity); + a0.UseCollisionImpulses(); } + } } -void CGameCollision::CollisionFailsafe(const CStateManager& mgr, CAreaCollisionCache& cache, - CPhysicsActor& actor, const CCollisionPrimitive& prim, - const rstl::reserved_vector& nearList, - float f1, u32 failsafeTicks) -{ - actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); - if (f1 > 0.5f) - actor.SetNumTicksPartialUpdate(actor.GetNumTicksPartialUpdate() + 1); +void CGameCollision::CollisionFailsafe(const CStateManager& mgr, CAreaCollisionCache& cache, CPhysicsActor& actor, + const CCollisionPrimitive& prim, + const rstl::reserved_vector& nearList, float f1, + u32 failsafeTicks) { + actor.MoveCollisionPrimitive(zeus::CVector3f::skZero); + if (f1 > 0.5f) + actor.SetNumTicksPartialUpdate(actor.GetNumTicksPartialUpdate() + 1); - if (actor.GetNumTicksPartialUpdate() > 1 || - DetectCollisionBoolean_Cached(mgr, cache, prim, actor.GetPrimitiveTransform(), - actor.GetMaterialFilter(), nearList)) - { - actor.SetNumTicksPartialUpdate(0); - actor.SetNumTicksStuck(actor.GetNumTicksStuck() + 1); - if (actor.GetNumTicksStuck() < failsafeTicks) - return; + if (actor.GetNumTicksPartialUpdate() > 1 || + DetectCollisionBoolean_Cached(mgr, cache, prim, actor.GetPrimitiveTransform(), actor.GetMaterialFilter(), + nearList)) { + actor.SetNumTicksPartialUpdate(0); + actor.SetNumTicksStuck(actor.GetNumTicksStuck() + 1); + if (actor.GetNumTicksStuck() < failsafeTicks) + return; - CMotionState oldMState = actor.GetMotionState(); - CMotionState lastNonCollide = actor.GetLastNonCollidingState(); - actor.SetMotionState(lastNonCollide); - if (!DetectCollisionBoolean_Cached(mgr, cache, prim, actor.GetPrimitiveTransform(), - actor.GetMaterialFilter(), nearList)) - { - lastNonCollide.x1c_velocity *= zeus::CVector3f(0.5f); - lastNonCollide.x28_angularMomentum *= zeus::CVector3f(0.5f); - actor.SetLastNonCollidingState(lastNonCollide); - //++gDebugPrintCount; - actor.SetNumTicksStuck(0); - } - else - { - actor.SetMotionState(oldMState); - if (auto nonIntersectVec = FindNonIntersectingVector(mgr, cache, actor, prim, nearList)) - { - oldMState.x0_translation += *nonIntersectVec; - actor.SetMotionState(oldMState); - actor.SetLastNonCollidingState(actor.GetMotionState()); - //++gDebugPrintCount; - } - else - { - //++gDebugPrintCount; - lastNonCollide.x1c_velocity *= zeus::CVector3f(0.5f); - lastNonCollide.x28_angularMomentum *= zeus::CVector3f(0.5f); - actor.SetLastNonCollidingState(lastNonCollide); - } - } - } - else - { + CMotionState oldMState = actor.GetMotionState(); + CMotionState lastNonCollide = actor.GetLastNonCollidingState(); + actor.SetMotionState(lastNonCollide); + if (!DetectCollisionBoolean_Cached(mgr, cache, prim, actor.GetPrimitiveTransform(), actor.GetMaterialFilter(), + nearList)) { + lastNonCollide.x1c_velocity *= zeus::CVector3f(0.5f); + lastNonCollide.x28_angularMomentum *= zeus::CVector3f(0.5f); + actor.SetLastNonCollidingState(lastNonCollide); + //++gDebugPrintCount; + actor.SetNumTicksStuck(0); + } else { + actor.SetMotionState(oldMState); + if (auto nonIntersectVec = FindNonIntersectingVector(mgr, cache, actor, prim, nearList)) { + oldMState.x0_translation += *nonIntersectVec; + actor.SetMotionState(oldMState); actor.SetLastNonCollidingState(actor.GetMotionState()); - actor.SetNumTicksStuck(0); + //++gDebugPrintCount; + } else { + //++gDebugPrintCount; + lastNonCollide.x1c_velocity *= zeus::CVector3f(0.5f); + lastNonCollide.x28_angularMomentum *= zeus::CVector3f(0.5f); + actor.SetLastNonCollidingState(lastNonCollide); + } } + } else { + actor.SetLastNonCollidingState(actor.GetMotionState()); + actor.SetNumTicksStuck(0); + } } -std::experimental::optional -CGameCollision::FindNonIntersectingVector(const CStateManager& mgr, CAreaCollisionCache& cache, - CPhysicsActor& actor, const CCollisionPrimitive& prim, - const rstl::reserved_vector& nearList) -{ - zeus::CTransform xf = actor.GetPrimitiveTransform(); - zeus::CVector3f origOrigin = xf.origin; - zeus::CVector3f center = prim.CalculateAABox(xf).center(); - for (int i=2 ; i<1000 ; i+=(i/2)) - { - float pos = i * 0.005f; - float neg = -pos; - for (int j=0 ; j<26 ; ++j) - { - zeus::CVector3f vec; - switch (j) - { - case 0: - vec = {0.f, pos, 0.f}; - break; - case 1: - vec = {0.f, neg, 0.f}; - break; - case 2: - vec = {pos, 0.f, 0.f}; - break; - case 3: - vec = {neg, 0.f, 0.f}; - break; - case 4: - vec = {0.f, 0.f, pos}; - break; - case 5: - vec = {0.f, 0.f, neg}; - break; - case 6: - vec = {0.f, pos, pos}; - break; - case 7: - vec = {0.f, neg, neg}; - break; - case 8: - vec = {0.f, neg, pos}; - break; - case 9: - vec = {0.f, pos, neg}; - break; - case 10: - vec = {pos, 0.f, pos}; - break; - case 11: - vec = {neg, 0.f, neg}; - break; - case 12: - vec = {neg, 0.f, pos}; - break; - case 13: - vec = {pos, 0.f, neg}; - break; - case 14: - vec = {pos, pos, 0.f}; - break; - case 15: - vec = {neg, neg, 0.f}; - break; - case 16: - vec = {neg, pos, 0.f}; - break; - case 17: - vec = {pos, neg, 0.f}; - break; - case 18: - vec = {pos, pos, pos}; - break; - case 19: - vec = {neg, pos, pos}; - break; - case 20: - vec = {pos, neg, pos}; - break; - case 21: - vec = {neg, neg, pos}; - break; - case 22: - vec = {pos, pos, neg}; - break; - case 23: - vec = {neg, pos, neg}; - break; - case 24: - vec = {pos, neg, neg}; - break; - case 25: - vec = {neg, neg, neg}; - break; - default: break; - } +std::experimental::optional CGameCollision::FindNonIntersectingVector( + const CStateManager& mgr, CAreaCollisionCache& cache, CPhysicsActor& actor, const CCollisionPrimitive& prim, + const rstl::reserved_vector& nearList) { + zeus::CTransform xf = actor.GetPrimitiveTransform(); + zeus::CVector3f origOrigin = xf.origin; + zeus::CVector3f center = prim.CalculateAABox(xf).center(); + for (int i = 2; i < 1000; i += (i / 2)) { + float pos = i * 0.005f; + float neg = -pos; + for (int j = 0; j < 26; ++j) { + zeus::CVector3f vec; + switch (j) { + case 0: + vec = {0.f, pos, 0.f}; + break; + case 1: + vec = {0.f, neg, 0.f}; + break; + case 2: + vec = {pos, 0.f, 0.f}; + break; + case 3: + vec = {neg, 0.f, 0.f}; + break; + case 4: + vec = {0.f, 0.f, pos}; + break; + case 5: + vec = {0.f, 0.f, neg}; + break; + case 6: + vec = {0.f, pos, pos}; + break; + case 7: + vec = {0.f, neg, neg}; + break; + case 8: + vec = {0.f, neg, pos}; + break; + case 9: + vec = {0.f, pos, neg}; + break; + case 10: + vec = {pos, 0.f, pos}; + break; + case 11: + vec = {neg, 0.f, neg}; + break; + case 12: + vec = {neg, 0.f, pos}; + break; + case 13: + vec = {pos, 0.f, neg}; + break; + case 14: + vec = {pos, pos, 0.f}; + break; + case 15: + vec = {neg, neg, 0.f}; + break; + case 16: + vec = {neg, pos, 0.f}; + break; + case 17: + vec = {pos, neg, 0.f}; + break; + case 18: + vec = {pos, pos, pos}; + break; + case 19: + vec = {neg, pos, pos}; + break; + case 20: + vec = {pos, neg, pos}; + break; + case 21: + vec = {neg, neg, pos}; + break; + case 22: + vec = {pos, pos, neg}; + break; + case 23: + vec = {neg, pos, neg}; + break; + case 24: + vec = {pos, neg, neg}; + break; + case 25: + vec = {neg, neg, neg}; + break; + default: + break; + } - zeus::CVector3f worldPoint = vec + origOrigin; - if (mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId())->GetAABB().pointInside(worldPoint)) - { - if (mgr.RayCollideWorld(center, center + vec, nearList, - CMaterialFilter::skPassEverything, &actor)) - { - xf.origin = worldPoint; - if (!DetectCollisionBoolean_Cached(mgr, cache, prim, xf, actor.GetMaterialFilter(), nearList)) - return {vec}; - } - } + zeus::CVector3f worldPoint = vec + origOrigin; + if (mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId())->GetAABB().pointInside(worldPoint)) { + if (mgr.RayCollideWorld(center, center + vec, nearList, CMaterialFilter::skPassEverything, &actor)) { + xf.origin = worldPoint; + if (!DetectCollisionBoolean_Cached(mgr, cache, prim, xf, actor.GetMaterialFilter(), nearList)) + return {vec}; } + } } + } - return {}; -} + return {}; } +} // namespace urde diff --git a/Runtime/Collision/CGameCollision.hpp b/Runtime/Collision/CGameCollision.hpp index 0b8f1a366..2596f4b1e 100644 --- a/Runtime/Collision/CGameCollision.hpp +++ b/Runtime/Collision/CGameCollision.hpp @@ -7,8 +7,7 @@ #include "CMetroidAreaCollider.hpp" #include "CCollisionPrimitive.hpp" -namespace urde -{ +namespace urde { class CActor; class CCollisionInfo; @@ -20,107 +19,101 @@ class CMaterialFilter; class CGameArea; class ICollisionFilter; -class CGameCollision -{ - static void MovePlayer(CStateManager& mgr, CPhysicsActor& actor, float dt, - const rstl::reserved_vector* colliderList); - static void MoveAndCollide(CStateManager& mgr, CPhysicsActor& actor, float dt, const ICollisionFilter& filter, - const rstl::reserved_vector* colliderList); - static zeus::CVector3f GetActorRelativeVelocities(const CPhysicsActor& act0, const CPhysicsActor* act1); -public: - static float GetCoefficientOfRestitution(const CCollisionInfo&) { return 0.f; } - static bool NullMovingCollider(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&) - { - return false; - } - static bool NullBooleanCollider(const CInternalCollisionStructure&) { return false; } - static bool NullCollisionCollider(const CInternalCollisionStructure&, CCollisionInfoList&) { return false; } - static void InitCollision(); - static void Move(CStateManager& mgr, CPhysicsActor& actor, float dt, - const rstl::reserved_vector* colliderList); +class CGameCollision { + static void MovePlayer(CStateManager& mgr, CPhysicsActor& actor, float dt, + const rstl::reserved_vector* colliderList); + static void MoveAndCollide(CStateManager& mgr, CPhysicsActor& actor, float dt, const ICollisionFilter& filter, + const rstl::reserved_vector* colliderList); + static zeus::CVector3f GetActorRelativeVelocities(const CPhysicsActor& act0, const CPhysicsActor* act1); - static bool CanBlock(const CMaterialList&, const zeus::CVector3f&); - static bool IsFloor(const CMaterialList&, const zeus::CVector3f&); - static void SendMaterialMessage(CStateManager&, const CMaterialList&, CActor&); - static CRayCastResult RayStaticIntersection(const CStateManager& mgr, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter); - static bool RayStaticIntersectionBool(const CStateManager& mgr, const zeus::CVector3f& start, - const zeus::CVector3f& dir, float length, - const CMaterialFilter& filter); - static CRayCastResult RayDynamicIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter, - const rstl::reserved_vector& nearList); - static bool RayDynamicIntersectionBool(const CStateManager& mgr, - const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const CMaterialFilter& filter, - const rstl::reserved_vector& nearList, - const CActor* damagee, float length); - static CRayCastResult RayWorldIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos, +public: + static float GetCoefficientOfRestitution(const CCollisionInfo&) { return 0.f; } + static bool NullMovingCollider(const CInternalCollisionStructure&, const zeus::CVector3f&, double&, CCollisionInfo&) { + return false; + } + static bool NullBooleanCollider(const CInternalCollisionStructure&) { return false; } + static bool NullCollisionCollider(const CInternalCollisionStructure&, CCollisionInfoList&) { return false; } + static void InitCollision(); + static void Move(CStateManager& mgr, CPhysicsActor& actor, float dt, + const rstl::reserved_vector* colliderList); + + static bool CanBlock(const CMaterialList&, const zeus::CVector3f&); + static bool IsFloor(const CMaterialList&, const zeus::CVector3f&); + static void SendMaterialMessage(CStateManager&, const CMaterialList&, CActor&); + static CRayCastResult RayStaticIntersection(const CStateManager& mgr, const zeus::CVector3f& pos, + const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter); + static bool RayStaticIntersectionBool(const CStateManager& mgr, const zeus::CVector3f& start, + const zeus::CVector3f& dir, float length, const CMaterialFilter& filter); + static CRayCastResult RayDynamicIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos, const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter, const rstl::reserved_vector& nearList); - static bool RayStaticIntersectionArea(const CGameArea& area, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter); - static void BuildAreaCollisionCache(const CStateManager& mgr, CAreaCollisionCache& cache); - static float GetMinExtentForCollisionPrimitive(const CCollisionPrimitive& prim); - static bool DetectCollisionBoolean(const CStateManager& mgr, const CCollisionPrimitive& prim, - const zeus::CTransform& xf, const CMaterialFilter& filter, - const rstl::reserved_vector& nearList); - static bool DetectCollisionBoolean_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, - const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const CMaterialFilter& filter, - const rstl::reserved_vector& nearList); - static bool DetectStaticCollisionBoolean(const CStateManager& mgr, const CCollisionPrimitive& prim, - const zeus::CTransform& xf, const CMaterialFilter& filter); - static bool DetectStaticCollisionBoolean_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, - const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const CMaterialFilter& filter); - static bool DetectDynamicCollisionBoolean(const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const rstl::reserved_vector& nearList, - const CStateManager& mgr); - static bool DetectCollision_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, - const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const CMaterialFilter& filter, - const rstl::reserved_vector& nearList, - TUniqueId& idOut, CCollisionInfoList& infoList); - static bool DetectCollision_Cached_Moving(const CStateManager& mgr, CAreaCollisionCache& cache, - const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const CMaterialFilter& filter, - const rstl::reserved_vector& nearList, - const zeus::CVector3f& vec, - TUniqueId& idOut, CCollisionInfo& infoOut, double&); - static bool DetectStaticCollision(const CStateManager& mgr, const CCollisionPrimitive& prim, - const zeus::CTransform& xf, const CMaterialFilter& filter, - CCollisionInfoList& list); - static bool DetectStaticCollision_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, - const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const CMaterialFilter& filter, CCollisionInfoList& list); - static bool DetectStaticCollision_Cached_Moving(const CStateManager& mgr, CAreaCollisionCache& cache, - const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const CMaterialFilter& filter, const zeus::CVector3f& vec, - CCollisionInfo& infoOut, double& d); - static bool DetectDynamicCollision(const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const rstl::reserved_vector& nearList, - TUniqueId& idOut, CCollisionInfoList& list, const CStateManager& mgr); - static bool DetectDynamicCollisionMoving(const CCollisionPrimitive& prim, const zeus::CTransform& xf, - const rstl::reserved_vector& nearList, - const zeus::CVector3f& vec, TUniqueId& idOut, - CCollisionInfo& infoOut, double& d, const CStateManager& mgr); - static void MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor, TUniqueId id, - const CCollisionInfoList& list); - static void SendScriptMessages(CStateManager& mgr, CActor& a0, CActor* a1, const CCollisionInfoList& list); - static void ResolveCollisions(CPhysicsActor& a0, CPhysicsActor* a1, const CCollisionInfoList& list); - static void CollideWithDynamicBodyNoRot(CPhysicsActor& a0, CPhysicsActor& a1, const CCollisionInfo& info, - float restitution, bool); - static void CollideWithStaticBodyNoRot(CPhysicsActor& a0, const CMaterialList& m0, const CMaterialList& m1, - const zeus::CUnitVector3f& normal, float restitution, bool); - static void CollisionFailsafe(const CStateManager& mgr, CAreaCollisionCache& cache, - CPhysicsActor& actor, const CCollisionPrimitive& prim, - const rstl::reserved_vector& nearList, - float, u32 failsafeTicks); - static std::experimental::optional - FindNonIntersectingVector(const CStateManager& mgr, CAreaCollisionCache& cache, - CPhysicsActor& actor, const CCollisionPrimitive& prim, - const rstl::reserved_vector& nearList); + static bool RayDynamicIntersectionBool(const CStateManager& mgr, const zeus::CVector3f& pos, + const zeus::CVector3f& dir, const CMaterialFilter& filter, + const rstl::reserved_vector& nearList, const CActor* damagee, + float length); + static CRayCastResult RayWorldIntersection(const CStateManager& mgr, TUniqueId& idOut, const zeus::CVector3f& pos, + const zeus::CVector3f& dir, float mag, const CMaterialFilter& filter, + const rstl::reserved_vector& nearList); + static bool RayStaticIntersectionArea(const CGameArea& area, const zeus::CVector3f& pos, const zeus::CVector3f& dir, + float mag, const CMaterialFilter& filter); + static void BuildAreaCollisionCache(const CStateManager& mgr, CAreaCollisionCache& cache); + static float GetMinExtentForCollisionPrimitive(const CCollisionPrimitive& prim); + static bool DetectCollisionBoolean(const CStateManager& mgr, const CCollisionPrimitive& prim, + const zeus::CTransform& xf, const CMaterialFilter& filter, + const rstl::reserved_vector& nearList); + static bool DetectCollisionBoolean_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, + const CCollisionPrimitive& prim, const zeus::CTransform& xf, + const CMaterialFilter& filter, + const rstl::reserved_vector& nearList); + static bool DetectStaticCollisionBoolean(const CStateManager& mgr, const CCollisionPrimitive& prim, + const zeus::CTransform& xf, const CMaterialFilter& filter); + static bool DetectStaticCollisionBoolean_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, + const CCollisionPrimitive& prim, const zeus::CTransform& xf, + const CMaterialFilter& filter); + static bool DetectDynamicCollisionBoolean(const CCollisionPrimitive& prim, const zeus::CTransform& xf, + const rstl::reserved_vector& nearList, + const CStateManager& mgr); + static bool DetectCollision_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, + const CCollisionPrimitive& prim, const zeus::CTransform& xf, + const CMaterialFilter& filter, + const rstl::reserved_vector& nearList, TUniqueId& idOut, + CCollisionInfoList& infoList); + static bool DetectCollision_Cached_Moving(const CStateManager& mgr, CAreaCollisionCache& cache, + const CCollisionPrimitive& prim, const zeus::CTransform& xf, + const CMaterialFilter& filter, + const rstl::reserved_vector& nearList, + const zeus::CVector3f& vec, TUniqueId& idOut, CCollisionInfo& infoOut, + double&); + static bool DetectStaticCollision(const CStateManager& mgr, const CCollisionPrimitive& prim, + const zeus::CTransform& xf, const CMaterialFilter& filter, + CCollisionInfoList& list); + static bool DetectStaticCollision_Cached(const CStateManager& mgr, CAreaCollisionCache& cache, + const CCollisionPrimitive& prim, const zeus::CTransform& xf, + const CMaterialFilter& filter, CCollisionInfoList& list); + static bool DetectStaticCollision_Cached_Moving(const CStateManager& mgr, CAreaCollisionCache& cache, + const CCollisionPrimitive& prim, const zeus::CTransform& xf, + const CMaterialFilter& filter, const zeus::CVector3f& vec, + CCollisionInfo& infoOut, double& d); + static bool DetectDynamicCollision(const CCollisionPrimitive& prim, const zeus::CTransform& xf, + const rstl::reserved_vector& nearList, TUniqueId& idOut, + CCollisionInfoList& list, const CStateManager& mgr); + static bool DetectDynamicCollisionMoving(const CCollisionPrimitive& prim, const zeus::CTransform& xf, + const rstl::reserved_vector& nearList, + const zeus::CVector3f& vec, TUniqueId& idOut, CCollisionInfo& infoOut, + double& d, const CStateManager& mgr); + static void MakeCollisionCallbacks(CStateManager& mgr, CPhysicsActor& actor, TUniqueId id, + const CCollisionInfoList& list); + static void SendScriptMessages(CStateManager& mgr, CActor& a0, CActor* a1, const CCollisionInfoList& list); + static void ResolveCollisions(CPhysicsActor& a0, CPhysicsActor* a1, const CCollisionInfoList& list); + static void CollideWithDynamicBodyNoRot(CPhysicsActor& a0, CPhysicsActor& a1, const CCollisionInfo& info, + float restitution, bool); + static void CollideWithStaticBodyNoRot(CPhysicsActor& a0, const CMaterialList& m0, const CMaterialList& m1, + const zeus::CUnitVector3f& normal, float restitution, bool); + static void CollisionFailsafe(const CStateManager& mgr, CAreaCollisionCache& cache, CPhysicsActor& actor, + const CCollisionPrimitive& prim, const rstl::reserved_vector& nearList, + float, u32 failsafeTicks); + static std::experimental::optional + FindNonIntersectingVector(const CStateManager& mgr, CAreaCollisionCache& cache, CPhysicsActor& actor, + const CCollisionPrimitive& prim, const rstl::reserved_vector& nearList); }; -} - +} // namespace urde diff --git a/Runtime/Collision/CInternalRayCastStructure.hpp b/Runtime/Collision/CInternalRayCastStructure.hpp index f42dee0b9..962bb977f 100644 --- a/Runtime/Collision/CInternalRayCastStructure.hpp +++ b/Runtime/Collision/CInternalRayCastStructure.hpp @@ -3,30 +3,23 @@ #include "zeus/CTransform.hpp" #include "zeus/CMRay.hpp" #include "CMaterialFilter.hpp" -namespace urde -{ -class CInternalRayCastStructure -{ - zeus::CMRay x0_ray; - float x38_maxTime; - zeus::CTransform x3c_xf; - const CMaterialFilter& x6c_filter; +namespace urde { +class CInternalRayCastStructure { + zeus::CMRay x0_ray; + float x38_maxTime; + zeus::CTransform x3c_xf; + const CMaterialFilter& x6c_filter; + public: - CInternalRayCastStructure(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length, - const zeus::CTransform& xf, const CMaterialFilter& filter) - : x0_ray(start, dir, length), - x38_maxTime(length), - x3c_xf(xf), - x6c_filter(filter) - { - } + CInternalRayCastStructure(const zeus::CVector3f& start, const zeus::CVector3f& dir, float length, + const zeus::CTransform& xf, const CMaterialFilter& filter) + : x0_ray(start, dir, length), x38_maxTime(length), x3c_xf(xf), x6c_filter(filter) {} - const zeus::CMRay& GetRay() const { return x0_ray; } - const zeus::CVector3f& GetStart() const { return x0_ray.start; } - const zeus::CVector3f& GetNormal() const { return x0_ray.end; } - float GetMaxTime() const { return x38_maxTime; } - const zeus::CTransform& GetTransform() const { return x3c_xf; } - const CMaterialFilter& GetFilter() const { return x6c_filter; } + const zeus::CMRay& GetRay() const { return x0_ray; } + const zeus::CVector3f& GetStart() const { return x0_ray.start; } + const zeus::CVector3f& GetNormal() const { return x0_ray.end; } + float GetMaxTime() const { return x38_maxTime; } + const zeus::CTransform& GetTransform() const { return x3c_xf; } + const CMaterialFilter& GetFilter() const { return x6c_filter; } }; -} - +} // namespace urde diff --git a/Runtime/Collision/CJointCollisionDescription.cpp b/Runtime/Collision/CJointCollisionDescription.cpp index 93bb58a9b..54dce9f4b 100644 --- a/Runtime/Collision/CJointCollisionDescription.cpp +++ b/Runtime/Collision/CJointCollisionDescription.cpp @@ -1,7 +1,6 @@ #include "Collision/CJointCollisionDescription.hpp" -namespace urde -{ +namespace urde { CJointCollisionDescription::CJointCollisionDescription(ECollisionType colType, CSegId pivotId, CSegId nextId, const zeus::CVector3f& bounds, const zeus::CVector3f& pivotPoint, @@ -16,55 +15,47 @@ CJointCollisionDescription::CJointCollisionDescription(ECollisionType colType, C , x24_radius(radius) , x28_maxSeparation(maxSeparation) , x2c_name(name) -, x40_mass(mass) -{ +, x40_mass(mass) {} + +CJointCollisionDescription CJointCollisionDescription::SphereSubdivideCollision(CSegId pivotId, CSegId nextId, + float radius, float maxSeparation, + EOrientationType orientType, + std::string_view name, float mass) { + return CJointCollisionDescription(ECollisionType::SphereSubdivide, pivotId, nextId, zeus::CVector3f::skZero, + zeus::CVector3f::skZero, radius, maxSeparation, orientType, name, mass); } -CJointCollisionDescription -CJointCollisionDescription::SphereSubdivideCollision(CSegId pivotId, CSegId nextId, float radius, - float maxSeparation, EOrientationType orientType, - std::string_view name, float mass) -{ - return CJointCollisionDescription(ECollisionType::SphereSubdivide, pivotId, nextId, zeus::CVector3f::skZero, - zeus::CVector3f::skZero, radius, maxSeparation, orientType, name, mass); +CJointCollisionDescription CJointCollisionDescription::SphereCollision(CSegId pivotId, float radius, + std::string_view name, float mass) { + return CJointCollisionDescription(ECollisionType::Sphere, pivotId, {}, zeus::CVector3f::skZero, + zeus::CVector3f::skZero, radius, 0.f, EOrientationType::Zero, name, mass); } -CJointCollisionDescription -CJointCollisionDescription::SphereCollision(CSegId pivotId, float radius, std::string_view name, float mass) -{ - return CJointCollisionDescription(ECollisionType::Sphere, pivotId, {}, zeus::CVector3f::skZero, - zeus::CVector3f::skZero, radius, 0.f, EOrientationType::Zero, name, mass); +CJointCollisionDescription CJointCollisionDescription::AABoxCollision(CSegId pivotId, const zeus::CVector3f& bounds, + std::string_view name, float mass) { + return CJointCollisionDescription(ECollisionType::AABox, pivotId, {}, bounds, zeus::CVector3f::skZero, 0.f, 0.f, + EOrientationType::Zero, name, mass); } -CJointCollisionDescription -CJointCollisionDescription::AABoxCollision(CSegId pivotId, const zeus::CVector3f& bounds, - std::string_view name, float mass) -{ - return CJointCollisionDescription(ECollisionType::AABox, pivotId, {}, bounds, zeus::CVector3f::skZero, - 0.f, 0.f, EOrientationType::Zero, name, mass); +CJointCollisionDescription CJointCollisionDescription::OBBAutoSizeCollision(CSegId pivotId, CSegId nextId, + const zeus::CVector3f& bounds, + EOrientationType orientType, + std::string_view name, float mass) { + return CJointCollisionDescription(ECollisionType::OBBAutoSize, pivotId, nextId, bounds, zeus::CVector3f::skZero, 0.f, + 0.f, orientType, name, mass); } -CJointCollisionDescription -CJointCollisionDescription::OBBAutoSizeCollision(CSegId pivotId, CSegId nextId, const zeus::CVector3f& bounds, - EOrientationType orientType, std::string_view name, float mass) -{ - return CJointCollisionDescription(ECollisionType::OBBAutoSize, pivotId, nextId, bounds, zeus::CVector3f::skZero, - 0.f, 0.f, orientType, name, mass); +CJointCollisionDescription CJointCollisionDescription::OBBCollision(CSegId pivotId, const zeus::CVector3f& bounds, + const zeus::CVector3f& pivotPoint, + std::string_view name, float mass) { + return CJointCollisionDescription(ECollisionType::OBB, pivotId, {}, bounds, pivotPoint, 0.f, 0.f, + EOrientationType::Zero, name, mass); } -CJointCollisionDescription -CJointCollisionDescription::OBBCollision(CSegId pivotId, const zeus::CVector3f& bounds, - const zeus::CVector3f& pivotPoint, std::string_view name, float mass) -{ - return CJointCollisionDescription(ECollisionType::OBB, pivotId, {}, bounds, pivotPoint, 0.f, 0.f, - EOrientationType::Zero, name, mass); -} - -void CJointCollisionDescription::ScaleAllBounds(const zeus::CVector3f& scale) -{ - xc_bounds *= scale; - x24_radius *= scale.x(); - x28_maxSeparation *= scale.x(); - x18_pivotPoint *= scale; -} +void CJointCollisionDescription::ScaleAllBounds(const zeus::CVector3f& scale) { + xc_bounds *= scale; + x24_radius *= scale.x(); + x28_maxSeparation *= scale.x(); + x18_pivotPoint *= scale; } +} // namespace urde diff --git a/Runtime/Collision/CJointCollisionDescription.hpp b/Runtime/Collision/CJointCollisionDescription.hpp index f892f6e9f..862c35be9 100644 --- a/Runtime/Collision/CJointCollisionDescription.hpp +++ b/Runtime/Collision/CJointCollisionDescription.hpp @@ -3,78 +3,68 @@ #include "Character/CSegId.hpp" #include "zeus/CAABox.hpp" -namespace urde -{ -struct SOBBJointDescription -{ - const char* from; - const char* to; - zeus::CVector3f bounds; +namespace urde { +struct SOBBJointDescription { + const char* from; + const char* to; + zeus::CVector3f bounds; }; -struct SSphereJointDescription -{ - const char* name; - float radius; +struct SSphereJointDescription { + const char* name; + float radius; }; -class CJointCollisionDescription -{ +class CJointCollisionDescription { public: - enum class ECollisionType - { - Sphere, - SphereSubdivide, - AABox, - OBBAutoSize, - OBB, - }; + enum class ECollisionType { + Sphere, + SphereSubdivide, + AABox, + OBBAutoSize, + OBB, + }; - enum class EOrientationType - { - Zero, - One - }; + enum class EOrientationType { Zero, One }; private: - ECollisionType x0_colType; - EOrientationType x4_orientType; - CSegId x8_pivotId; - CSegId x9_nextId; - zeus::CVector3f xc_bounds; - zeus::CVector3f x18_pivotPoint; - float x24_radius; - float x28_maxSeparation; - std::string x2c_name; - TUniqueId x3c_actorId = kInvalidUniqueId; - float x40_mass; + ECollisionType x0_colType; + EOrientationType x4_orientType; + CSegId x8_pivotId; + CSegId x9_nextId; + zeus::CVector3f xc_bounds; + zeus::CVector3f x18_pivotPoint; + float x24_radius; + float x28_maxSeparation; + std::string x2c_name; + TUniqueId x3c_actorId = kInvalidUniqueId; + float x40_mass; public: - CJointCollisionDescription(ECollisionType, CSegId, CSegId, const zeus::CVector3f&, const zeus::CVector3f&, float, - float, EOrientationType, std::string_view, float); - static CJointCollisionDescription SphereSubdivideCollision(CSegId pivotId, CSegId nextId, float radius, - float maxSeparation, EOrientationType orientType, - std::string_view name, float mass); - static CJointCollisionDescription SphereCollision(CSegId pivotId, float radius, std::string_view name, float mass); - static CJointCollisionDescription AABoxCollision(CSegId pivotId, const zeus::CVector3f& bounds, - std::string_view name, float mass); - static CJointCollisionDescription OBBAutoSizeCollision(CSegId pivotId, CSegId nextId, const zeus::CVector3f& bounds, - EOrientationType orientType, std::string_view, float mass); - static CJointCollisionDescription OBBCollision(CSegId pivotId, const zeus::CVector3f& bounds, - const zeus::CVector3f& pivotPoint, std::string_view name, float mass); - std::string_view GetName() const { return x2c_name; } - TUniqueId GetCollisionActorId() const { return x3c_actorId; } - void SetCollisionActorId(TUniqueId id) { x3c_actorId = id; } - const zeus::CVector3f& GetBounds() const { return xc_bounds; } - float GetRadius() const { return x24_radius; } - float GetMaxSeparation() const { return x28_maxSeparation; } - EOrientationType GetOrientationType() const { return x4_orientType; } - float GetMass() const { return x40_mass; } - const zeus::CVector3f& GetPivotPoint() const { return x18_pivotPoint; } - ECollisionType GetType() const { return x0_colType; } - CSegId GetNextId() const { return x9_nextId; } - CSegId GetPivotId() const { return x8_pivotId; } - void ScaleAllBounds(const zeus::CVector3f& scale); + CJointCollisionDescription(ECollisionType, CSegId, CSegId, const zeus::CVector3f&, const zeus::CVector3f&, float, + float, EOrientationType, std::string_view, float); + static CJointCollisionDescription SphereSubdivideCollision(CSegId pivotId, CSegId nextId, float radius, + float maxSeparation, EOrientationType orientType, + std::string_view name, float mass); + static CJointCollisionDescription SphereCollision(CSegId pivotId, float radius, std::string_view name, float mass); + static CJointCollisionDescription AABoxCollision(CSegId pivotId, const zeus::CVector3f& bounds, std::string_view name, + float mass); + static CJointCollisionDescription OBBAutoSizeCollision(CSegId pivotId, CSegId nextId, const zeus::CVector3f& bounds, + EOrientationType orientType, std::string_view, float mass); + static CJointCollisionDescription OBBCollision(CSegId pivotId, const zeus::CVector3f& bounds, + const zeus::CVector3f& pivotPoint, std::string_view name, float mass); + std::string_view GetName() const { return x2c_name; } + TUniqueId GetCollisionActorId() const { return x3c_actorId; } + void SetCollisionActorId(TUniqueId id) { x3c_actorId = id; } + const zeus::CVector3f& GetBounds() const { return xc_bounds; } + float GetRadius() const { return x24_radius; } + float GetMaxSeparation() const { return x28_maxSeparation; } + EOrientationType GetOrientationType() const { return x4_orientType; } + float GetMass() const { return x40_mass; } + const zeus::CVector3f& GetPivotPoint() const { return x18_pivotPoint; } + ECollisionType GetType() const { return x0_colType; } + CSegId GetNextId() const { return x9_nextId; } + CSegId GetPivotId() const { return x8_pivotId; } + void ScaleAllBounds(const zeus::CVector3f& scale); }; -} - +} // namespace urde diff --git a/Runtime/Collision/CMaterialFilter.cpp b/Runtime/Collision/CMaterialFilter.cpp index 85624da53..c7bcd8ae1 100644 --- a/Runtime/Collision/CMaterialFilter.cpp +++ b/Runtime/Collision/CMaterialFilter.cpp @@ -1,48 +1,40 @@ #include "CMaterialFilter.hpp" -namespace urde -{ -const CMaterialFilter CMaterialFilter::skPassEverything({0x00000000FFFFFFFF}, {0}, CMaterialFilter::EFilterType::Always); +namespace urde { +const CMaterialFilter CMaterialFilter::skPassEverything({0x00000000FFFFFFFF}, {0}, + CMaterialFilter::EFilterType::Always); -CMaterialFilter::CMaterialFilter(const CMaterialList& include, const CMaterialList& exclude, CMaterialFilter::EFilterType type) - : x0_include(include), - x8_exclude(exclude), - x10_type(type) -{ +CMaterialFilter::CMaterialFilter(const CMaterialList& include, const CMaterialList& exclude, + CMaterialFilter::EFilterType type) +: x0_include(include), x8_exclude(exclude), x10_type(type) {} + +CMaterialFilter CMaterialFilter::MakeInclude(const CMaterialList& include) { + return CMaterialFilter(include, {0ull}, EFilterType::Include); } -CMaterialFilter CMaterialFilter::MakeInclude(const CMaterialList& include) -{ - return CMaterialFilter(include, {0ull}, EFilterType::Include); +CMaterialFilter CMaterialFilter::MakeExclude(const CMaterialList& exclude) { + return CMaterialFilter({u64(0x00000000FFFFFFFF)}, exclude, EFilterType::Exclude); } -CMaterialFilter CMaterialFilter::MakeExclude(const CMaterialList& exclude) -{ - return CMaterialFilter({u64(0x00000000FFFFFFFF)}, exclude, EFilterType::Exclude); +CMaterialFilter CMaterialFilter::MakeIncludeExclude(const CMaterialList& include, const CMaterialList& exclude) { + return CMaterialFilter(include, exclude, EFilterType::IncludeExclude); } -CMaterialFilter CMaterialFilter::MakeIncludeExclude(const CMaterialList& include, const CMaterialList& exclude) -{ - return CMaterialFilter(include, exclude, EFilterType::IncludeExclude); +bool CMaterialFilter::Passes(const CMaterialList& list) const { + switch (x10_type) { + case EFilterType::Always: + return true; + case EFilterType::Include: + return (list.x0_list & x0_include.x0_list) != 0; + case EFilterType::Exclude: + return (list.x0_list & x8_exclude.x0_list) == 0; + case EFilterType::IncludeExclude: + if ((list.x0_list & x0_include.x0_list) == 0) + return false; + return (list.x0_list & x8_exclude.x0_list) == 0; + default: + return true; + } } -bool CMaterialFilter::Passes(const CMaterialList& list) const -{ - switch (x10_type) - { - case EFilterType::Always: - return true; - case EFilterType::Include: - return (list.x0_list & x0_include.x0_list) != 0; - case EFilterType::Exclude: - return (list.x0_list & x8_exclude.x0_list) == 0; - case EFilterType::IncludeExclude: - if ((list.x0_list & x0_include.x0_list) == 0) - return false; - return (list.x0_list & x8_exclude.x0_list) == 0; - default: - return true; - } -} - -} +} // namespace urde diff --git a/Runtime/Collision/CMaterialFilter.hpp b/Runtime/Collision/CMaterialFilter.hpp index 988fe7679..fb2d41f3e 100644 --- a/Runtime/Collision/CMaterialFilter.hpp +++ b/Runtime/Collision/CMaterialFilter.hpp @@ -2,37 +2,31 @@ #include "CMaterialList.hpp" #include "zeus/Math.hpp" -namespace urde -{ -class CMaterialFilter -{ +namespace urde { +class CMaterialFilter { public: - enum class EFilterType - { - Always, - Include, - Exclude, - IncludeExclude - }; + enum class EFilterType { Always, Include, Exclude, IncludeExclude }; + private: - CMaterialList x0_include; - CMaterialList x8_exclude; - EFilterType x10_type = EFilterType::IncludeExclude; + CMaterialList x0_include; + CMaterialList x8_exclude; + EFilterType x10_type = EFilterType::IncludeExclude; + public: - static const CMaterialFilter skPassEverything; + static const CMaterialFilter skPassEverything; - CMaterialFilter(const CMaterialList& include, const CMaterialList& exclude, EFilterType type); + CMaterialFilter(const CMaterialList& include, const CMaterialList& exclude, EFilterType type); - static CMaterialFilter MakeInclude(const CMaterialList& include); + static CMaterialFilter MakeInclude(const CMaterialList& include); - static CMaterialFilter MakeExclude(const CMaterialList& exclude); + static CMaterialFilter MakeExclude(const CMaterialList& exclude); - static CMaterialFilter MakeIncludeExclude(const CMaterialList& include, const CMaterialList& exclude); + static CMaterialFilter MakeIncludeExclude(const CMaterialList& include, const CMaterialList& exclude); - const CMaterialList& GetIncludeList() const { return x0_include; } - const CMaterialList& GetExcludeList() const { return x8_exclude; } - CMaterialList& IncludeList() { return x0_include; } - CMaterialList& ExcludeList() { return x8_exclude; } - bool Passes(const CMaterialList&) const; + const CMaterialList& GetIncludeList() const { return x0_include; } + const CMaterialList& GetExcludeList() const { return x8_exclude; } + CMaterialList& IncludeList() { return x0_include; } + CMaterialList& ExcludeList() { return x8_exclude; } + bool Passes(const CMaterialList&) const; }; -} +} // namespace urde diff --git a/Runtime/Collision/CMaterialList.hpp b/Runtime/Collision/CMaterialList.hpp index 873c332f4..2117a4d84 100644 --- a/Runtime/Collision/CMaterialList.hpp +++ b/Runtime/Collision/CMaterialList.hpp @@ -2,159 +2,131 @@ #include "RetroTypes.hpp" -namespace urde -{ -enum class EMaterialTypes -{ - NoStepLogic = 0, - Stone = 1, - Metal = 2, - Grass = 3, - Ice = 4, - Pillar = 5, - MetalGrating = 6, - Phazon = 7, - Dirt = 8, - Lava = 9, - LavaStone = 10, - Snow = 11, - MudSlow = 12, - HalfPipe = 13, - Mud = 14, - Glass = 15, - Shield = 16, - Sand = 17, - ProjectilePassthrough = 18, - Solid = 19, - NoPlatformCollision = 20, - CameraPassthrough = 21, - Wood = 22, - Organic = 23, - NoEdgeCollision = 24, - RedundantEdgeOrFlippedTri = 25, - SeeThrough = 26, - ScanPassthrough = 27, - AIPassthrough = 28, - Ceiling = 29, - Wall = 30, - Floor = 31, - Player = 32, - Character = 33, - Trigger = 34, - Projectile = 35, - Bomb = 36, - GroundCollider = 37, - NoStaticCollision = 38, - Scannable = 39, - Target = 40, - Orbit = 41, - Occluder = 42, - Immovable = 43, - Debris = 44, - PowerBomb = 45, - Unknown46 = 46, - CollisionActor = 47, - AIBlock = 48, - Platform = 49, - NonSolidDamageable = 50, - RadarObject = 51, - PlatformSlave = 52, - Unknown54 = 54, - SolidCharacter = 55, - ExcludeFromLineOfSightTest = 56, - ExcludeFromRadar = 57, - NoPlayerCollision = 58, - SixtyThree = 63 +namespace urde { +enum class EMaterialTypes { + NoStepLogic = 0, + Stone = 1, + Metal = 2, + Grass = 3, + Ice = 4, + Pillar = 5, + MetalGrating = 6, + Phazon = 7, + Dirt = 8, + Lava = 9, + LavaStone = 10, + Snow = 11, + MudSlow = 12, + HalfPipe = 13, + Mud = 14, + Glass = 15, + Shield = 16, + Sand = 17, + ProjectilePassthrough = 18, + Solid = 19, + NoPlatformCollision = 20, + CameraPassthrough = 21, + Wood = 22, + Organic = 23, + NoEdgeCollision = 24, + RedundantEdgeOrFlippedTri = 25, + SeeThrough = 26, + ScanPassthrough = 27, + AIPassthrough = 28, + Ceiling = 29, + Wall = 30, + Floor = 31, + Player = 32, + Character = 33, + Trigger = 34, + Projectile = 35, + Bomb = 36, + GroundCollider = 37, + NoStaticCollision = 38, + Scannable = 39, + Target = 40, + Orbit = 41, + Occluder = 42, + Immovable = 43, + Debris = 44, + PowerBomb = 45, + Unknown46 = 46, + CollisionActor = 47, + AIBlock = 48, + Platform = 49, + NonSolidDamageable = 50, + RadarObject = 51, + PlatformSlave = 52, + Unknown54 = 54, + SolidCharacter = 55, + ExcludeFromLineOfSightTest = 56, + ExcludeFromRadar = 57, + NoPlayerCollision = 58, + SixtyThree = 63 }; -class CMaterialList -{ - friend class CMaterialFilter; - u64 x0_list = 0; +class CMaterialList { + friend class CMaterialFilter; + u64 x0_list = 0; + public: - CMaterialList() = default; - CMaterialList(u64 flags) : x0_list(flags) {} - CMaterialList(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4, EMaterialTypes t5, EMaterialTypes t6) - : CMaterialList(t1, t2, t3, t4, t5) - { x0_list |= 1ull << u64(t6); } + CMaterialList() = default; + CMaterialList(u64 flags) : x0_list(flags) {} + CMaterialList(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4, EMaterialTypes t5, + EMaterialTypes t6) + : CMaterialList(t1, t2, t3, t4, t5) { + x0_list |= 1ull << u64(t6); + } - CMaterialList(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4, EMaterialTypes t5) - : CMaterialList(t1, t2, t3, t4) - { x0_list |= 1ull << u64(t5); } + CMaterialList(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4, EMaterialTypes t5) + : CMaterialList(t1, t2, t3, t4) { + x0_list |= 1ull << u64(t5); + } - CMaterialList(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4) - : CMaterialList(t1, t2, t3) - { x0_list |= 1ull << u64(t4); } + CMaterialList(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4) + : CMaterialList(t1, t2, t3) { + x0_list |= 1ull << u64(t4); + } - CMaterialList(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3) - : CMaterialList(t1, t2) - { x0_list |= 1ull << u64(t3); } + CMaterialList(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3) : CMaterialList(t1, t2) { + x0_list |= 1ull << u64(t3); + } - CMaterialList(EMaterialTypes t1, EMaterialTypes t2) - : CMaterialList(t1) - { x0_list |= 1ull << u64(t2); } + CMaterialList(EMaterialTypes t1, EMaterialTypes t2) : CMaterialList(t1) { x0_list |= 1ull << u64(t2); } - CMaterialList(EMaterialTypes t1) - : x0_list(1ull << u64(t1)) - { + CMaterialList(EMaterialTypes t1) : x0_list(1ull << u64(t1)) {} + + u64 GetValue() const { return x0_list; } + + static s32 BitPosition(u64 flag) { + for (u32 i = 0; i < 64; ++i) + if ((flag & (1ull << i)) != 0) + return i; + return -1; + } + + void Add(EMaterialTypes type) { x0_list |= (1ull << u64(type)); } + + void Add(const CMaterialList& l) { x0_list |= l.x0_list; } + + void Remove(EMaterialTypes type) { x0_list &= ~(1ull << u64(type)); } + + void Remove(const CMaterialList& other) { x0_list &= ~(other.x0_list); } + + bool HasMaterial(EMaterialTypes type) const { return (x0_list & (1ull << u64(type))) != 0; } + + bool SharesMaterials(const CMaterialList& other) { + for (u32 i = 0; i < 64; i++) { + if ((x0_list & (1ull << i)) != 0 && (other.x0_list & (1ull << i)) != 0) + return true; } - u64 GetValue() const { return x0_list; } + return false; + } - static s32 BitPosition(u64 flag) - { - for (u32 i = 0; i < 64; ++i) - if ((flag & (1ull << i)) != 0) - return i; - return -1; - } + u64 Intersection(const CMaterialList& other) const { return other.x0_list & x0_list; } - void Add(EMaterialTypes type) - { - x0_list |= (1ull << u64(type)); - } - - void Add(const CMaterialList& l) - { - x0_list |= l.x0_list; - } - - void Remove(EMaterialTypes type) - { - x0_list &= ~(1ull << u64(type)); - } - - void Remove(const CMaterialList& other) - { - x0_list &= ~(other.x0_list); - } - - bool HasMaterial(EMaterialTypes type) const - { - return (x0_list & (1ull << u64(type))) != 0; - } - - bool SharesMaterials(const CMaterialList& other) - { - for (u32 i = 0; i < 64; i++) - { - if ((x0_list & (1ull << i)) != 0 && (other.x0_list & (1ull << i)) != 0) - return true; - } - - return false; - } - - u64 Intersection(const CMaterialList& other) const - { - return other.x0_list & x0_list; - } - - u64 XOR(const CMaterialList& other) const - { - return x0_list ^ other.x0_list; - } + u64 XOR(const CMaterialList& other) const { return x0_list ^ other.x0_list; } }; -} - +} // namespace urde diff --git a/Runtime/Collision/CMetroidAreaCollider.cpp b/Runtime/Collision/CMetroidAreaCollider.cpp index 4b88e83f6..347f1f5da 100644 --- a/Runtime/Collision/CMetroidAreaCollider.cpp +++ b/Runtime/Collision/CMetroidAreaCollider.cpp @@ -3,8 +3,7 @@ #include "CollisionUtil.hpp" #include "CCollisionInfoList.hpp" -namespace urde -{ +namespace urde { u32 CMetroidAreaCollider::g_CalledClip = 0; u32 CMetroidAreaCollider::g_RejectedByClip = 0; @@ -17,1115 +16,932 @@ u16 CMetroidAreaCollider::g_DupTriangleList[0x4000] = {}; CAABoxAreaCache::CAABoxAreaCache(const zeus::CAABox& aabb, const zeus::CPlane* pl, const CMaterialFilter& filter, const CMaterialList& material, CCollisionInfoList& collisionList) -: x0_aabb(aabb), x4_planes(pl), x8_filter(filter), xc_material(material), x10_collisionList(collisionList), - x14_center(aabb.center()), x20_halfExtent(aabb.extents()) -{} +: x0_aabb(aabb) +, x4_planes(pl) +, x8_filter(filter) +, xc_material(material) +, x10_collisionList(collisionList) +, x14_center(aabb.center()) +, x20_halfExtent(aabb.extents()) {} CBooleanAABoxAreaCache::CBooleanAABoxAreaCache(const zeus::CAABox& aabb, const CMaterialFilter& filter) -: x0_aabb(aabb), x4_filter(filter), x8_center(aabb.center()), x14_halfExtent(aabb.extents()) -{} +: x0_aabb(aabb), x4_filter(filter), x8_center(aabb.center()), x14_halfExtent(aabb.extents()) {} CSphereAreaCache::CSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere, const CMaterialFilter& filter, const CMaterialList& material, CCollisionInfoList& collisionList) -: x0_aabb(aabb), x4_sphere(sphere), x8_filter(filter), xc_material(material), x10_collisionList(collisionList) -{} +: x0_aabb(aabb), x4_sphere(sphere), x8_filter(filter), xc_material(material), x10_collisionList(collisionList) {} CBooleanSphereAreaCache::CBooleanSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere, const CMaterialFilter& filter) -: x0_aabb(aabb), x4_sphere(sphere), x8_filter(filter) -{} +: x0_aabb(aabb), x4_sphere(sphere), x8_filter(filter) {} SBoxEdge::SBoxEdge(const zeus::CAABox& aabb, int idx, const zeus::CVector3f& dir) -: x0_seg(aabb.getEdge(zeus::CAABox::EBoxEdgeId(idx))), x28_start(x0_seg.x0_start), x40_end(x0_seg.x18_end), - x58_delta(x40_end - x28_start), x70_coDir(x58_delta.cross(dir).asNormalized()), - x88_dirCoDirDot(x28_start.dot(x70_coDir)) -{} +: x0_seg(aabb.getEdge(zeus::CAABox::EBoxEdgeId(idx))) +, x28_start(x0_seg.x0_start) +, x40_end(x0_seg.x18_end) +, x58_delta(x40_end - x28_start) +, x70_coDir(x58_delta.cross(dir).asNormalized()) +, x88_dirCoDirDot(x28_start.dot(x70_coDir)) {} -static void FlagEdgeIndicesForFace(int face, bool edgeFlags[12]) -{ - switch (face) - { - case 0: - edgeFlags[10] = true; - edgeFlags[11] = true; - edgeFlags[2] = true; - edgeFlags[4] = true; - return; - case 1: - edgeFlags[8] = true; - edgeFlags[9] = true; - edgeFlags[0] = true; - edgeFlags[6] = true; - return; - case 2: - edgeFlags[4] = true; - edgeFlags[5] = true; - edgeFlags[6] = true; - edgeFlags[7] = true; - return; - case 3: - edgeFlags[0] = true; - edgeFlags[1] = true; - edgeFlags[2] = true; - edgeFlags[3] = true; - return; - case 4: - edgeFlags[7] = true; - edgeFlags[8] = true; - edgeFlags[3] = true; - edgeFlags[11] = true; - return; - case 5: - edgeFlags[1] = true; - edgeFlags[5] = true; - edgeFlags[9] = true; - edgeFlags[10] = true; - return; - default: break; - } +static void FlagEdgeIndicesForFace(int face, bool edgeFlags[12]) { + switch (face) { + case 0: + edgeFlags[10] = true; + edgeFlags[11] = true; + edgeFlags[2] = true; + edgeFlags[4] = true; + return; + case 1: + edgeFlags[8] = true; + edgeFlags[9] = true; + edgeFlags[0] = true; + edgeFlags[6] = true; + return; + case 2: + edgeFlags[4] = true; + edgeFlags[5] = true; + edgeFlags[6] = true; + edgeFlags[7] = true; + return; + case 3: + edgeFlags[0] = true; + edgeFlags[1] = true; + edgeFlags[2] = true; + edgeFlags[3] = true; + return; + case 4: + edgeFlags[7] = true; + edgeFlags[8] = true; + edgeFlags[3] = true; + edgeFlags[11] = true; + return; + case 5: + edgeFlags[1] = true; + edgeFlags[5] = true; + edgeFlags[9] = true; + edgeFlags[10] = true; + return; + default: + break; + } } -static void FlagVertexIndicesForFace(int face, bool vertFlags[8]) -{ - switch (face) - { - case 0: - vertFlags[1] = true; - vertFlags[3] = true; - vertFlags[5] = true; - vertFlags[7] = true; - return; - case 1: - vertFlags[0] = true; - vertFlags[2] = true; - vertFlags[4] = true; - vertFlags[6] = true; - return; - case 2: - vertFlags[2] = true; - vertFlags[3] = true; - vertFlags[6] = true; - vertFlags[7] = true; - return; - case 3: - vertFlags[0] = true; - vertFlags[1] = true; - vertFlags[4] = true; - vertFlags[5] = true; - return; - case 4: - vertFlags[4] = true; - vertFlags[5] = true; - vertFlags[6] = true; - vertFlags[7] = true; - return; - case 5: - vertFlags[0] = true; - vertFlags[1] = true; - vertFlags[2] = true; - vertFlags[3] = true; - return; - default: break; - } +static void FlagVertexIndicesForFace(int face, bool vertFlags[8]) { + switch (face) { + case 0: + vertFlags[1] = true; + vertFlags[3] = true; + vertFlags[5] = true; + vertFlags[7] = true; + return; + case 1: + vertFlags[0] = true; + vertFlags[2] = true; + vertFlags[4] = true; + vertFlags[6] = true; + return; + case 2: + vertFlags[2] = true; + vertFlags[3] = true; + vertFlags[6] = true; + vertFlags[7] = true; + return; + case 3: + vertFlags[0] = true; + vertFlags[1] = true; + vertFlags[4] = true; + vertFlags[5] = true; + return; + case 4: + vertFlags[4] = true; + vertFlags[5] = true; + vertFlags[6] = true; + vertFlags[7] = true; + return; + case 5: + vertFlags[0] = true; + vertFlags[1] = true; + vertFlags[2] = true; + vertFlags[3] = true; + return; + default: + break; + } } -CMovingAABoxComponents::CMovingAABoxComponents(const zeus::CAABox& aabb, const zeus::CVector3f& dir) -: x6e8_aabb(aabb) -{ - bool edgeFlags[12] = {}; - bool vertFlags[8] = {}; - int useFaces = 0; +CMovingAABoxComponents::CMovingAABoxComponents(const zeus::CAABox& aabb, const zeus::CVector3f& dir) : x6e8_aabb(aabb) { + bool edgeFlags[12] = {}; + bool vertFlags[8] = {}; + int useFaces = 0; - for (int i=0 ; i<3 ; ++i) - { - if (dir[i] != 0.f) - { - int face = i * 2 + (dir[i] < 0.f); - FlagEdgeIndicesForFace(face, edgeFlags); - FlagVertexIndicesForFace(face, vertFlags); - useFaces += 1; - } + for (int i = 0; i < 3; ++i) { + if (dir[i] != 0.f) { + int face = i * 2 + (dir[i] < 0.f); + FlagEdgeIndicesForFace(face, edgeFlags); + FlagVertexIndicesForFace(face, vertFlags); + useFaces += 1; } + } - for (int i=0 ; i<12 ; ++i) - if (edgeFlags[i]) - x0_edges.push_back(SBoxEdge(aabb, i, dir)); + for (int i = 0; i < 12; ++i) + if (edgeFlags[i]) + x0_edges.push_back(SBoxEdge(aabb, i, dir)); - for (int i=0 ; i<8 ; ++i) - if (vertFlags[i]) - x6c4_vertIdxs.push_back(i); + for (int i = 0; i < 8; ++i) + if (vertFlags[i]) + x6c4_vertIdxs.push_back(i); - if (useFaces == 1) - { - x6e8_aabb = zeus::CAABox::skInvertedBox; - x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[0])); - x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[1])); - x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[2])); - x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[3])); - } + if (useFaces == 1) { + x6e8_aabb = zeus::CAABox::skInvertedBox; + x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[0])); + x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[1])); + x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[2])); + x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[3])); + } } -CMetroidAreaCollider::COctreeLeafCache::COctreeLeafCache(const CAreaOctTree& octTree) -: x0_octTree(octTree) -{ - x908_24_overflow = false; +CMetroidAreaCollider::COctreeLeafCache::COctreeLeafCache(const CAreaOctTree& octTree) : x0_octTree(octTree) { + x908_24_overflow = false; } -void CMetroidAreaCollider::COctreeLeafCache::AddLeaf(const CAreaOctTree::Node& node) -{ - if (x4_nodeCache.size() == x4_nodeCache.capacity()) - { - x908_24_overflow = true; - return; - } +void CMetroidAreaCollider::COctreeLeafCache::AddLeaf(const CAreaOctTree::Node& node) { + if (x4_nodeCache.size() == x4_nodeCache.capacity()) { + x908_24_overflow = true; + return; + } - x4_nodeCache.push_back(node); + x4_nodeCache.push_back(node); } void CMetroidAreaCollider::BuildOctreeLeafCache(const CAreaOctTree::Node& node, const zeus::CAABox& aabb, - CMetroidAreaCollider::COctreeLeafCache& cache) -{ - for (int i=0 ; i<8 ; ++i) - { - CAreaOctTree::Node::ETreeType type = node.GetChildType(i); - if (type != CAreaOctTree::Node::ETreeType::Invalid) - { - CAreaOctTree::Node ch = node.GetChild(i); - if (aabb.intersects(ch.GetBoundingBox())) - { - if (type == CAreaOctTree::Node::ETreeType::Leaf) - cache.AddLeaf(ch); - else - BuildOctreeLeafCache(ch, aabb, cache); - } - } + CMetroidAreaCollider::COctreeLeafCache& cache) { + for (int i = 0; i < 8; ++i) { + CAreaOctTree::Node::ETreeType type = node.GetChildType(i); + if (type != CAreaOctTree::Node::ETreeType::Invalid) { + CAreaOctTree::Node ch = node.GetChild(i); + if (aabb.intersects(ch.GetBoundingBox())) { + if (type == CAreaOctTree::Node::ETreeType::Leaf) + cache.AddLeaf(ch); + else + BuildOctreeLeafCache(ch, aabb, cache); + } } + } } -static zeus::CVector3f ClipRayToPlane(const zeus::CVector3f& a, const zeus::CVector3f& b, - const zeus::CPlane& plane) -{ - return (1.f - -plane.pointToPlaneDist(a) / (b - a).dot(plane.normal())) * (a - b) + b; +static zeus::CVector3f ClipRayToPlane(const zeus::CVector3f& a, const zeus::CVector3f& b, const zeus::CPlane& plane) { + return (1.f - -plane.pointToPlaneDist(a) / (b - a).dot(plane.normal())) * (a - b) + b; } bool CMetroidAreaCollider::ConvexPolyCollision(const zeus::CPlane* planes, const zeus::CVector3f* verts, - zeus::CAABox& aabb) -{ - rstl::reserved_vector vecs[2]; + zeus::CAABox& aabb) { + rstl::reserved_vector vecs[2]; - g_CalledClip += 1; - g_RejectedByClip -= 1; + g_CalledClip += 1; + g_RejectedByClip -= 1; - vecs[0].push_back(verts[0]); - vecs[0].push_back(verts[1]); - vecs[0].push_back(verts[2]); + vecs[0].push_back(verts[0]); + vecs[0].push_back(verts[1]); + vecs[0].push_back(verts[2]); - int vecIdx = 0; - int otherVecIdx = 1; - for (int i=0 ; i<6 ; ++i) - { - rstl::reserved_vector& vec = vecs[vecIdx]; - rstl::reserved_vector& otherVec = vecs[otherVecIdx]; - otherVec.clear(); + int vecIdx = 0; + int otherVecIdx = 1; + for (int i = 0; i < 6; ++i) { + rstl::reserved_vector& vec = vecs[vecIdx]; + rstl::reserved_vector& otherVec = vecs[otherVecIdx]; + otherVec.clear(); - bool inFrontOf = planes[i].pointToPlaneDist(vec.front()) >= 0.f; - for (int j=0 ; j= 0.f; - if (nextInFrontOf ^ inFrontOf) - otherVec.push_back(ClipRayToPlane(vec[j], b, planes[i])); - inFrontOf = nextInFrontOf; - } - - if (otherVec.empty()) - return false; - - vecIdx ^= 1; - otherVecIdx ^= 1; + bool inFrontOf = planes[i].pointToPlaneDist(vec.front()) >= 0.f; + for (int j = 0; j < vec.size(); ++j) { + const zeus::CVector3f& b = vec[(j + 1) % vec.size()]; + if (inFrontOf) + otherVec.push_back(vec[j]); + bool nextInFrontOf = planes[i].pointToPlaneDist(b) >= 0.f; + if (nextInFrontOf ^ inFrontOf) + otherVec.push_back(ClipRayToPlane(vec[j], b, planes[i])); + inFrontOf = nextInFrontOf; } - rstl::reserved_vector& accumVec = vecs[otherVecIdx ^ 1]; - for (const zeus::CVector3f& point : accumVec) - aabb.accumulateBounds(point); + if (otherVec.empty()) + return false; - g_RejectedByClip -= 1; - return true; + vecIdx ^= 1; + otherVecIdx ^= 1; + } + + rstl::reserved_vector& accumVec = vecs[otherVecIdx ^ 1]; + for (const zeus::CVector3f& point : accumVec) + aabb.accumulateBounds(point); + + g_RejectedByClip -= 1; + return true; } -bool CMetroidAreaCollider::AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, - const CMaterialFilter& filter) -{ - CBooleanAABoxAreaCache cache(aabb, filter); +bool CMetroidAreaCollider::AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, + const zeus::CAABox& aabb, const CMaterialFilter& filter) { + CBooleanAABoxAreaCache cache(aabb, filter); - for (const CAreaOctTree::Node& node : leafCache.x4_nodeCache) - { - if (cache.x0_aabb.intersects(node.GetBoundingBox())) - { - CAreaOctTree::TriListReference list = node.GetTriangleArray(); - for (int j=0 ; j& vertIndices, - const zeus::CVector3f& dir, double& d, - zeus::CVector3f& normalOut, zeus::CVector3f& pointOut) -{ - bool ret = false; - for (u32 idx : vertIndices) - { - zeus::CVector3f point = aabb.getPoint(idx); - if (CollisionUtil::RayTriangleIntersection_Double(point, dir, surf.GetVerts(), d)) - { - pointOut = float(d) * dir + point; - normalOut = surf.GetNormal(); - ret = true; - } +bool CMetroidAreaCollider::MovingAABoxCollisionCheck_BoxVertexTri( + const CCollisionSurface& surf, const zeus::CAABox& aabb, const rstl::reserved_vector& vertIndices, + const zeus::CVector3f& dir, double& d, zeus::CVector3f& normalOut, zeus::CVector3f& pointOut) { + bool ret = false; + for (u32 idx : vertIndices) { + zeus::CVector3f point = aabb.getPoint(idx); + if (CollisionUtil::RayTriangleIntersection_Double(point, dir, surf.GetVerts(), d)) { + pointOut = float(d) * dir + point; + normalOut = surf.GetNormal(); + ret = true; } - return ret; + } + return ret; } bool CMetroidAreaCollider::MovingAABoxCollisionCheck_TriVertexBox(const zeus::CVector3f& vert, const zeus::CAABox& aabb, const zeus::CVector3f& dir, double& dOut, - zeus::CVector3f& normal, zeus::CVector3f& point) -{ - zeus::CMRay ray(vert, -dir, dOut); - zeus::CVector3f norm; - double d; - if (CollisionUtil::RayAABoxIntersection_Double(ray, aabb, norm, d) == 2) - { - d *= dOut; - if (d < dOut) - { - normal = -norm; - dOut = d; - point = vert; - return true; - } + zeus::CVector3f& normal, zeus::CVector3f& point) { + zeus::CMRay ray(vert, -dir, dOut); + zeus::CVector3f norm; + double d; + if (CollisionUtil::RayAABoxIntersection_Double(ray, aabb, norm, d) == 2) { + d *= dOut; + if (d < dOut) { + normal = -norm; + dOut = d; + point = vert; + return true; } - return false; + } + return false; } bool CMetroidAreaCollider::MovingAABoxCollisionCheck_Edge(const zeus::CVector3f& ev0, const zeus::CVector3f& ev1, const rstl::reserved_vector& edges, const zeus::CVector3f& dir, double& d, - zeus::CVector3f& normal, zeus::CVector3f& point) -{ - bool ret = false; + zeus::CVector3f& normal, zeus::CVector3f& point) { + bool ret = false; - for (const SBoxEdge& edge : edges) - { - zeus::CVector3d ev0d = ev0; - zeus::CVector3d ev1d = ev1; - if ((edge.x70_coDir.dot(ev1d) >= edge.x88_dirCoDirDot) != - (edge.x70_coDir.dot(ev0d) >= edge.x88_dirCoDirDot)) - { - zeus::CVector3d delta = ev0d - ev1d; - zeus::CVector3d cross0 = edge.x58_delta.cross(delta); - if (cross0.magSquared() >= DBL_EPSILON) - { - zeus::CVector3d cross0Norm = cross0.asNormalized(); - if (cross0Norm.dot(dir) >= 0.0) - { - ev1d = ev0; - ev0d = ev1; - delta = ev0d - ev1d; - cross0Norm = edge.x58_delta.cross(delta).asNormalized(); - } - - zeus::CVector3d clipped = ev0d + (-(ev0d.dot(edge.x70_coDir) - edge.x88_dirCoDirDot) / - delta.dot(edge.x70_coDir)) * delta; - int maxCompIdx = (std::fabs(edge.x70_coDir.x()) > std::fabs(edge.x70_coDir.y())) ? 0 : 1; - if (std::fabs(edge.x70_coDir[maxCompIdx]) < std::fabs(edge.x70_coDir.z())) - maxCompIdx = 2; - - int ci0, ci1; - switch (maxCompIdx) - { - case 0: - ci0 = 1; - ci1 = 2; - break; - case 1: - ci0 = 0; - ci1 = 2; - break; - default: - ci0 = 0; - ci1 = 1; - break; - } - - double mag = (edge.x58_delta[ci0] * (clipped[ci1] - edge.x28_start[ci1]) - - edge.x58_delta[ci1] * (clipped[ci0] - edge.x28_start[ci0])) / - (edge.x58_delta[ci0] * dir[ci1] - edge.x58_delta[ci1] * dir[ci0]); - if (mag >= 0.0 && mag < d) - { - zeus::CVector3d clippedMag = clipped - mag * zeus::CVector3d(dir); - if ((edge.x28_start - clippedMag).dot(edge.x40_end - clippedMag) < 0.0 && mag < d) - { - normal = cross0Norm.asCVector3f(); - d = mag; - point = clipped.asCVector3f(); - ret = true; - } - } - } + for (const SBoxEdge& edge : edges) { + zeus::CVector3d ev0d = ev0; + zeus::CVector3d ev1d = ev1; + if ((edge.x70_coDir.dot(ev1d) >= edge.x88_dirCoDirDot) != (edge.x70_coDir.dot(ev0d) >= edge.x88_dirCoDirDot)) { + zeus::CVector3d delta = ev0d - ev1d; + zeus::CVector3d cross0 = edge.x58_delta.cross(delta); + if (cross0.magSquared() >= DBL_EPSILON) { + zeus::CVector3d cross0Norm = cross0.asNormalized(); + if (cross0Norm.dot(dir) >= 0.0) { + ev1d = ev0; + ev0d = ev1; + delta = ev0d - ev1d; + cross0Norm = edge.x58_delta.cross(delta).asNormalized(); } - } - return ret; + zeus::CVector3d clipped = + ev0d + (-(ev0d.dot(edge.x70_coDir) - edge.x88_dirCoDirDot) / delta.dot(edge.x70_coDir)) * delta; + int maxCompIdx = (std::fabs(edge.x70_coDir.x()) > std::fabs(edge.x70_coDir.y())) ? 0 : 1; + if (std::fabs(edge.x70_coDir[maxCompIdx]) < std::fabs(edge.x70_coDir.z())) + maxCompIdx = 2; + + int ci0, ci1; + switch (maxCompIdx) { + case 0: + ci0 = 1; + ci1 = 2; + break; + case 1: + ci0 = 0; + ci1 = 2; + break; + default: + ci0 = 0; + ci1 = 1; + break; + } + + double mag = (edge.x58_delta[ci0] * (clipped[ci1] - edge.x28_start[ci1]) - + edge.x58_delta[ci1] * (clipped[ci0] - edge.x28_start[ci0])) / + (edge.x58_delta[ci0] * dir[ci1] - edge.x58_delta[ci1] * dir[ci0]); + if (mag >= 0.0 && mag < d) { + zeus::CVector3d clippedMag = clipped - mag * zeus::CVector3d(dir); + if ((edge.x28_start - clippedMag).dot(edge.x40_end - clippedMag) < 0.0 && mag < d) { + normal = cross0Norm.asCVector3f(); + d = mag; + point = clipped.asCVector3f(); + ret = true; + } + } + } + } + } + + return ret; } bool CMetroidAreaCollider::MovingAABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, const CMaterialFilter& filter, const CMaterialList& matList, - const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut, - double& dOut) -{ - bool ret = false; - ResetInternalCounters(); - dOut = mag; + const zeus::CVector3f& dir, float mag, + CCollisionInfo& infoOut, double& dOut) { + bool ret = false; + ResetInternalCounters(); + dOut = mag; - CMovingAABoxComponents components(aabb, dir); + CMovingAABoxComponents components(aabb, dir); - zeus::CAABox movedAABB = components.x6e8_aabb; - zeus::CVector3f moveVec = mag * dir; - movedAABB.accumulateBounds(aabb.min + moveVec); - movedAABB.accumulateBounds(aabb.max + moveVec); + zeus::CAABox movedAABB = components.x6e8_aabb; + zeus::CVector3f moveVec = mag * dir; + movedAABB.accumulateBounds(aabb.min + moveVec); + movedAABB.accumulateBounds(aabb.max + moveVec); - zeus::CVector3f center = movedAABB.center(); - zeus::CVector3f extent = movedAABB.extents(); + zeus::CVector3f center = movedAABB.center(); + zeus::CVector3f extent = movedAABB.extents(); - zeus::CVector3f normal, point; + zeus::CVector3f normal, point; - for (const CAreaOctTree::Node& node : leafCache.x4_nodeCache) - { - if (movedAABB.intersects(node.GetBoundingBox())) - { - CAreaOctTree::TriListReference list = node.GetTriangleArray(); - for (int j=0 ; j= 0.f && !outsideEdges[0] && !outsideEdges[1] && !outsideEdges[2] && mag < dOut) { + infoOut = CCollisionInfo(intersectPoint - sphere.radius * surfNormal, matList, triMat, surfNormal); + dOut = mag; + triRet = true; + ret = true; + } + + bool intersects = (sphere.position - surf.GetVert(0)).dot(surfNormal) <= sphere.radius; + bool testVert[] = {true, true, true}; + const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx); + for (int k = 0; k < 3; ++k) { + if (intersects || outsideEdges[k]) { + u16 edgeIdx = edgeIndices[k]; + if (g_DupPrimitiveCheckCount != g_DupEdgeList[edgeIdx]) { + g_DupEdgeList[edgeIdx] = g_DupPrimitiveCheckCount; + CMaterialList edgeMat(node.GetOwner().GetEdgeMaterial(edgeIdx)); + if (!edgeMat.HasMaterial(EMaterialTypes::NoEdgeCollision)) { + int nextIdx = (k + 1) % 3; + zeus::CVector3f edgeVec = surf.GetVert(nextIdx) - surf.GetVert(k); + float edgeVecMag = edgeVec.magnitude(); + edgeVec *= zeus::CVector3f(1.f / edgeVecMag); + float dirDotEdge = dir.dot(edgeVec); + zeus::CVector3f edgeRej = dir - dirDotEdge * edgeVec; + float edgeRejMagSq = edgeRej.magSquared(); + zeus::CVector3f vertToSphere = sphere.position - surf.GetVert(k); + float vtsDotEdge = vertToSphere.dot(edgeVec); + zeus::CVector3f vtsRej = vertToSphere - vtsDotEdge * edgeVec; + if (edgeRejMagSq > 0.f) { + float tmp = 2.f * vtsRej.dot(edgeRej); + float tmp2 = + 4.f * edgeRejMagSq * (vtsRej.magSquared() - sphere.radius * sphere.radius) - tmp * tmp; + if (tmp2 >= 0.f) { + float mag = 0.5f / edgeRejMagSq * (-tmp - std::sqrt(tmp2)); + if (mag >= 0.f) { + float t = mag * dirDotEdge + vtsDotEdge; + if (t >= 0.f && t <= edgeVecMag && mag < dOut) { + zeus::CVector3f point = surf.GetVert(k) + t * edgeVec; + infoOut = CCollisionInfo(point, matList, edgeMat, + (sphere.position + mag * dir - point).normalized()); + dOut = mag; triRet = true; ret = true; - infoOut = CCollisionInfo(point, matList, triMat, normal); - dOut = d; - } - - for (int k=0 ; k<3 ; ++k) - { - u16 vertIdx = vertIndices[k]; - zeus::CVector3f vtx = node.GetOwner().GetVert(vertIdx); - if (g_DupPrimitiveCheckCount != g_DupVertexList[vertIdx]) - { - g_DupVertexList[vertIdx] = g_DupPrimitiveCheckCount; - if (movedAABB.pointInside(vtx)) - { - d = dOut; - if (MovingAABoxCollisionCheck_TriVertexBox(vtx, aabb, dir, d, - normal, point) && d < dOut) - { - CMaterialList vertMat(node.GetOwner().GetVertMaterial(vertIdx)); - triRet = true; - ret = true; - infoOut = CCollisionInfo(point, matList, vertMat, normal); - dOut = d; - } - } - } - } - - const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx); - for (int k=0 ; k<3 ; ++k) - { - u16 edgeIdx = edgeIndices[k]; - if (g_DupPrimitiveCheckCount != g_DupEdgeList[edgeIdx]) - { - g_DupEdgeList[edgeIdx] = g_DupPrimitiveCheckCount; - CMaterialList edgeMat(node.GetOwner().GetEdgeMaterial(edgeIdx)); - if (!edgeMat.HasMaterial(EMaterialTypes::NoEdgeCollision)) - { - d = dOut; - const CCollisionEdge& edge = node.GetOwner().GetEdge(edgeIdx); - if (MovingAABoxCollisionCheck_Edge(node.GetOwner().GetVert(edge.GetVertIndex1()), - node.GetOwner().GetVert(edge.GetVertIndex2()), - components.x0_edges, dir, d, normal, point) && - d < dOut) - { - triRet = true; - ret = true; - infoOut = CCollisionInfo(point, matList, edgeMat, normal); - dOut = d; - } - } - } - } - - if (triRet) - { - moveVec = float(dOut) * dir; - movedAABB = components.x6e8_aabb; - movedAABB.accumulateBounds(aabb.min + moveVec); - movedAABB.accumulateBounds(aabb.max + moveVec); - center = movedAABB.center(); - extent = movedAABB.extents(); + testVert[k] = false; + testVert[nextIdx] = false; + } else if (t < -sphere.radius && dirDotEdge <= 0.f) { + testVert[k] = false; + } else if (t > edgeVecMag + sphere.radius && dirDotEdge >= 0.0) { + testVert[nextIdx] = false; + } } + } else { + testVert[k] = false; + testVert[nextIdx] = false; + } } - else - { - const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx); - g_DupEdgeList[edgeIndices[0]] = g_DupPrimitiveCheckCount; - g_DupEdgeList[edgeIndices[1]] = g_DupPrimitiveCheckCount; - g_DupEdgeList[edgeIndices[2]] = g_DupPrimitiveCheckCount; - g_DupVertexList[vertIndices[0]] = g_DupPrimitiveCheckCount; - g_DupVertexList[vertIndices[1]] = g_DupPrimitiveCheckCount; - g_DupVertexList[vertIndices[2]] = g_DupPrimitiveCheckCount; - } + } } + } } - } - } - } - return ret; + for (int k = 0; k < 3; ++k) { + u16 vertIdx = vertIndices[k]; + if (testVert[k]) { + if (g_DupPrimitiveCheckCount != g_DupVertexList[vertIdx]) { + g_DupVertexList[vertIdx] = g_DupPrimitiveCheckCount; + double d = dOut; + if (CollisionUtil::RaySphereIntersection_Double(zeus::CSphere(surf.GetVert(k), sphere.radius), + sphere.position, dir, d) && + d >= 0.0) { + infoOut = CCollisionInfo(surf.GetVert(k), matList, node.GetOwner().GetVertMaterial(vertIdx), + (sphere.position + dir * d - surf.GetVert(k)).normalized()); + dOut = d; + triRet = true; + ret = true; + } + } + } else { + g_DupVertexList[vertIdx] = g_DupPrimitiveCheckCount; + } + } + + if (triRet) { + moveVec = float(dOut) * dir; + movedAABB = aabb; + movedAABB.accumulateBounds(aabb.min + moveVec); + movedAABB.accumulateBounds(aabb.max + moveVec); + center = movedAABB.center(); + extent = movedAABB.extents(); + } + } + } else { + const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx); + g_DupEdgeList[edgeIndices[0]] = g_DupPrimitiveCheckCount; + g_DupEdgeList[edgeIndices[1]] = g_DupPrimitiveCheckCount; + g_DupEdgeList[edgeIndices[2]] = g_DupPrimitiveCheckCount; + g_DupVertexList[vertIndices[0]] = g_DupPrimitiveCheckCount; + g_DupVertexList[vertIndices[1]] = g_DupPrimitiveCheckCount; + g_DupVertexList[vertIndices[2]] = g_DupPrimitiveCheckCount; + } + } + } + } + } + } + + return ret; } -bool CMetroidAreaCollider::MovingSphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, - const zeus::CSphere& sphere, - const CMaterialFilter& filter, const CMaterialList& matList, - const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut, - double& dOut) -{ - bool ret = false; - ResetInternalCounters(); - dOut = mag; - - zeus::CAABox movedAABB = aabb; - zeus::CVector3f moveVec = mag * dir; - movedAABB.accumulateBounds(aabb.min + moveVec); - movedAABB.accumulateBounds(aabb.max + moveVec); - - zeus::CVector3f center = movedAABB.center(); - zeus::CVector3f extent = movedAABB.extents(); - - for (const CAreaOctTree::Node& node : leafCache.x4_nodeCache) - { - if (movedAABB.intersects(node.GetBoundingBox())) - { - CAreaOctTree::TriListReference list = node.GetTriangleArray(); - for (int j=0 ; j= 0.f && !outsideEdges[0] && !outsideEdges[1] && !outsideEdges[2] && mag < dOut) - { - infoOut = CCollisionInfo(intersectPoint - sphere.radius * surfNormal, matList, triMat, surfNormal); - dOut = mag; - triRet = true; - ret = true; - } - - bool intersects = (sphere.position - surf.GetVert(0)).dot(surfNormal) <= sphere.radius; - bool testVert[] = {true, true, true}; - const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx); - for (int k=0 ; k<3 ; ++k) - { - if (intersects || outsideEdges[k]) - { - u16 edgeIdx = edgeIndices[k]; - if (g_DupPrimitiveCheckCount != g_DupEdgeList[edgeIdx]) - { - g_DupEdgeList[edgeIdx] = g_DupPrimitiveCheckCount; - CMaterialList edgeMat(node.GetOwner().GetEdgeMaterial(edgeIdx)); - if (!edgeMat.HasMaterial(EMaterialTypes::NoEdgeCollision)) - { - int nextIdx = (k + 1) % 3; - zeus::CVector3f edgeVec = surf.GetVert(nextIdx) - surf.GetVert(k); - float edgeVecMag = edgeVec.magnitude(); - edgeVec *= zeus::CVector3f(1.f / edgeVecMag); - float dirDotEdge = dir.dot(edgeVec); - zeus::CVector3f edgeRej = dir - dirDotEdge * edgeVec; - float edgeRejMagSq = edgeRej.magSquared(); - zeus::CVector3f vertToSphere = sphere.position - surf.GetVert(k); - float vtsDotEdge = vertToSphere.dot(edgeVec); - zeus::CVector3f vtsRej = vertToSphere - vtsDotEdge * edgeVec; - if (edgeRejMagSq > 0.f) - { - float tmp = 2.f * vtsRej.dot(edgeRej); - float tmp2 = 4.f * edgeRejMagSq * - (vtsRej.magSquared() - sphere.radius * sphere.radius) - tmp * tmp; - if (tmp2 >= 0.f) - { - float mag = 0.5f / edgeRejMagSq * (-tmp - std::sqrt(tmp2)); - if (mag >= 0.f) - { - float t = mag * dirDotEdge + vtsDotEdge; - if (t >= 0.f && t <= edgeVecMag && mag < dOut) - { - zeus::CVector3f point = surf.GetVert(k) + t * edgeVec; - infoOut = CCollisionInfo(point, matList, edgeMat, - (sphere.position + mag * dir - point).normalized()); - dOut = mag; - triRet = true; - ret = true; - testVert[k] = false; - testVert[nextIdx] = false; - } - else if (t < -sphere.radius && dirDotEdge <= 0.f) - { - testVert[k] = false; - } - else if (t > edgeVecMag + sphere.radius && dirDotEdge >= 0.0) - { - testVert[nextIdx] = false; - } - } - } - else - { - testVert[k] = false; - testVert[nextIdx] = false; - } - } - } - } - } - } - - for (int k=0 ; k<3 ; ++k) - { - u16 vertIdx = vertIndices[k]; - if (testVert[k]) - { - if (g_DupPrimitiveCheckCount != g_DupVertexList[vertIdx]) - { - g_DupVertexList[vertIdx] = g_DupPrimitiveCheckCount; - double d = dOut; - if (CollisionUtil::RaySphereIntersection_Double(zeus::CSphere(surf.GetVert(k), sphere.radius), - sphere.position, dir, d) && d >= 0.0) - { - infoOut = CCollisionInfo(surf.GetVert(k), matList, node.GetOwner().GetVertMaterial(vertIdx), - (sphere.position + dir * d - surf.GetVert(k)).normalized()); - dOut = d; - triRet = true; - ret = true; - } - } - } - else - { - g_DupVertexList[vertIdx] = g_DupPrimitiveCheckCount; - } - } - - if (triRet) - { - moveVec = float(dOut) * dir; - movedAABB = aabb; - movedAABB.accumulateBounds(aabb.min + moveVec); - movedAABB.accumulateBounds(aabb.max + moveVec); - center = movedAABB.center(); - extent = movedAABB.extents(); - } - } - } - else - { - const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx); - g_DupEdgeList[edgeIndices[0]] = g_DupPrimitiveCheckCount; - g_DupEdgeList[edgeIndices[1]] = g_DupPrimitiveCheckCount; - g_DupEdgeList[edgeIndices[2]] = g_DupPrimitiveCheckCount; - g_DupVertexList[vertIndices[0]] = g_DupPrimitiveCheckCount; - g_DupVertexList[vertIndices[1]] = g_DupPrimitiveCheckCount; - g_DupVertexList[vertIndices[2]] = g_DupPrimitiveCheckCount; - } - } - } - } - } - } - - return ret; -} - -void CMetroidAreaCollider::ResetInternalCounters() -{ - g_CalledClip = 0; - g_RejectedByClip = 0; - g_TrianglesProcessed = 0; - g_DupTrianglesProcessed = 0; - if (g_DupPrimitiveCheckCount == 0xffff) - { - memset(g_DupVertexList, 0, 0x5000); - memset(g_DupEdgeList, 0, 0xC000); - memset(g_DupTriangleList, 0, 0x8000); - g_DupPrimitiveCheckCount += 1; - } +void CMetroidAreaCollider::ResetInternalCounters() { + g_CalledClip = 0; + g_RejectedByClip = 0; + g_TrianglesProcessed = 0; + g_DupTrianglesProcessed = 0; + if (g_DupPrimitiveCheckCount == 0xffff) { + memset(g_DupVertexList, 0, 0x5000); + memset(g_DupEdgeList, 0, 0xC000); + memset(g_DupTriangleList, 0, 0x8000); g_DupPrimitiveCheckCount += 1; + } + g_DupPrimitiveCheckCount += 1; } -void CAreaCollisionCache::ClearCache() -{ - x18_leafCaches.clear(); - x1b40_24_leafOverflow = false; - x1b40_25_cacheOverflow = false; +void CAreaCollisionCache::ClearCache() { + x18_leafCaches.clear(); + x1b40_24_leafOverflow = false; + x1b40_25_cacheOverflow = false; } -void CAreaCollisionCache::AddOctreeLeafCache(const CMetroidAreaCollider::COctreeLeafCache& leafCache) -{ - if (!leafCache.GetNumLeaves()) - return; +void CAreaCollisionCache::AddOctreeLeafCache(const CMetroidAreaCollider::COctreeLeafCache& leafCache) { + if (!leafCache.GetNumLeaves()) + return; - if (leafCache.HasCacheOverflowed()) - x1b40_24_leafOverflow = true; + if (leafCache.HasCacheOverflowed()) + x1b40_24_leafOverflow = true; - if (x18_leafCaches.size() < 3) - { - x18_leafCaches.push_back(leafCache); - } - else - { - x1b40_24_leafOverflow = true; - x1b40_25_cacheOverflow = true; - } + if (x18_leafCaches.size() < 3) { + x18_leafCaches.push_back(leafCache); + } else { + x1b40_24_leafOverflow = true; + x1b40_25_cacheOverflow = true; + } } -} +} // namespace urde diff --git a/Runtime/Collision/CMetroidAreaCollider.hpp b/Runtime/Collision/CMetroidAreaCollider.hpp index 5671f77ea..c5822cf2e 100644 --- a/Runtime/Collision/CMetroidAreaCollider.hpp +++ b/Runtime/Collision/CMetroidAreaCollider.hpp @@ -4,198 +4,186 @@ #include "zeus/CAABox.hpp" #include "CAreaOctTree.hpp" -namespace urde -{ +namespace urde { class CCollisionInfoList; class CCollisionInfo; class CMaterialList; -class CAABoxAreaCache -{ +class CAABoxAreaCache { + friend class CMetroidAreaCollider; + const zeus::CAABox& x0_aabb; + const zeus::CPlane* x4_planes; + const CMaterialFilter& x8_filter; + const CMaterialList& xc_material; + CCollisionInfoList& x10_collisionList; + zeus::CVector3f x14_center; + zeus::CVector3f x20_halfExtent; + +public: + CAABoxAreaCache(const zeus::CAABox& aabb, const zeus::CPlane* pl, const CMaterialFilter& filter, + const CMaterialList& material, CCollisionInfoList& collisionList); +}; + +class CBooleanAABoxAreaCache { + friend class CMetroidAreaCollider; + const zeus::CAABox& x0_aabb; + const CMaterialFilter& x4_filter; + zeus::CVector3f x8_center; + zeus::CVector3f x14_halfExtent; + +public: + CBooleanAABoxAreaCache(const zeus::CAABox& aabb, const CMaterialFilter& filter); +}; + +class CSphereAreaCache { + friend class CMetroidAreaCollider; + const zeus::CAABox& x0_aabb; + const zeus::CSphere& x4_sphere; + const CMaterialFilter& x8_filter; + const CMaterialList& xc_material; + CCollisionInfoList& x10_collisionList; + +public: + CSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere, const CMaterialFilter& filter, + const CMaterialList& material, CCollisionInfoList& collisionList); +}; + +class CBooleanSphereAreaCache { + friend class CMetroidAreaCollider; + const zeus::CAABox& x0_aabb; + const zeus::CSphere& x4_sphere; + const CMaterialFilter& x8_filter; + +public: + CBooleanSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere, const CMaterialFilter& filter); +}; + +struct SBoxEdge { + zeus::CLineSeg x0_seg; + zeus::CVector3d x28_start; + zeus::CVector3d x40_end; + zeus::CVector3d x58_delta; + zeus::CVector3d x70_coDir; + double x88_dirCoDirDot; + SBoxEdge(const zeus::CAABox& aabb, int idx, const zeus::CVector3f& dir); +}; + +class CMovingAABoxComponents { + friend class CMetroidAreaCollider; + friend class CCollidableOBBTree; + rstl::reserved_vector x0_edges; + rstl::reserved_vector x6c4_vertIdxs; + zeus::CAABox x6e8_aabb; + +public: + CMovingAABoxComponents(const zeus::CAABox& aabb, const zeus::CVector3f& dir); +}; + +class CMetroidAreaCollider { + friend class CCollidableOBBTree; + static u32 g_CalledClip; + static u32 g_RejectedByClip; + static u32 g_TrianglesProcessed; + static u32 g_DupTrianglesProcessed; + static u16 g_DupPrimitiveCheckCount; + static u16 g_DupVertexList[0x5000]; + static u16 g_DupEdgeList[0xC000]; + static u16 g_DupTriangleList[0x4000]; + static bool AABoxCollisionCheckBoolean_Internal(const CAreaOctTree::Node& node, const CBooleanAABoxAreaCache& cache); + static bool AABoxCollisionCheck_Internal(const CAreaOctTree::Node& node, const CAABoxAreaCache& cache); + + static bool SphereCollisionCheckBoolean_Internal(const CAreaOctTree::Node& node, + const CBooleanSphereAreaCache& cache); + static bool SphereCollisionCheck_Internal(const CAreaOctTree::Node& node, const CSphereAreaCache& cache); + + static bool MovingAABoxCollisionCheck_BoxVertexTri(const CCollisionSurface& surf, const zeus::CAABox& aabb, + const rstl::reserved_vector& vertIndices, + const zeus::CVector3f& dir, double& d, zeus::CVector3f& normal, + zeus::CVector3f& point); + static bool MovingAABoxCollisionCheck_TriVertexBox(const zeus::CVector3f& vert, const zeus::CAABox& aabb, + const zeus::CVector3f& dir, double& d, zeus::CVector3f& normal, + zeus::CVector3f& point); + static bool MovingAABoxCollisionCheck_Edge(const zeus::CVector3f& ev0, const zeus::CVector3f& ev1, + const rstl::reserved_vector& edges, + const zeus::CVector3f& dir, double& d, zeus::CVector3f& normal, + zeus::CVector3f& point); + +public: + class COctreeLeafCache { friend class CMetroidAreaCollider; - const zeus::CAABox& x0_aabb; - const zeus::CPlane* x4_planes; - const CMaterialFilter& x8_filter; - const CMaterialList& xc_material; - CCollisionInfoList& x10_collisionList; - zeus::CVector3f x14_center; - zeus::CVector3f x20_halfExtent; -public: - CAABoxAreaCache(const zeus::CAABox& aabb, const zeus::CPlane* pl, const CMaterialFilter& filter, - const CMaterialList& material, CCollisionInfoList& collisionList); + const CAreaOctTree& x0_octTree; + rstl::reserved_vector x4_nodeCache; + bool x908_24_overflow : 1; + + public: + COctreeLeafCache(const CAreaOctTree& octTree); + void AddLeaf(const CAreaOctTree::Node& node); + u32 GetNumLeaves() const { return x4_nodeCache.size(); } + bool HasCacheOverflowed() const { return x908_24_overflow; } + const CAreaOctTree& GetOctTree() const { return x0_octTree; } + rstl::reserved_vector::iterator begin() { return x4_nodeCache.begin(); } + rstl::reserved_vector::iterator end() { return x4_nodeCache.end(); } + }; + static void BuildOctreeLeafCache(const CAreaOctTree::Node& root, const zeus::CAABox& aabb, + CMetroidAreaCollider::COctreeLeafCache& cache); + static bool ConvexPolyCollision(const zeus::CPlane* planes, const zeus::CVector3f* verts, zeus::CAABox& aabb); + + static bool AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, + const CMaterialFilter& filter); + static bool AABoxCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb, + const CMaterialFilter& filter); + + static bool SphereCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, + const zeus::CSphere& sphere, const CMaterialFilter& filter); + static bool SphereCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb, + const zeus::CSphere& sphere, const CMaterialFilter& filter); + + static bool AABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, + const CMaterialFilter& filter, const CMaterialList& matList, + CCollisionInfoList& list); + static bool AABoxCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb, const CMaterialFilter& filter, + const CMaterialList& matList, CCollisionInfoList& list); + + static bool SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, + const zeus::CSphere& sphere, const CMaterialList& matList, + const CMaterialFilter& filter, CCollisionInfoList& list); + static bool SphereCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb, const zeus::CSphere& sphere, + const CMaterialList& matList, const CMaterialFilter& filter, + CCollisionInfoList& list); + + static bool MovingAABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, + const CMaterialFilter& filter, const CMaterialList& matList, + const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut, + double& dOut); + static bool MovingSphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, + const zeus::CSphere& sphere, const CMaterialFilter& filter, + const CMaterialList& matList, const zeus::CVector3f& dir, float mag, + CCollisionInfo& infoOut, double& dOut); + static void ResetInternalCounters(); }; -class CBooleanAABoxAreaCache -{ - friend class CMetroidAreaCollider; - const zeus::CAABox& x0_aabb; - const CMaterialFilter& x4_filter; - zeus::CVector3f x8_center; - zeus::CVector3f x14_halfExtent; -public: - CBooleanAABoxAreaCache(const zeus::CAABox& aabb, const CMaterialFilter& filter); -}; - -class CSphereAreaCache -{ - friend class CMetroidAreaCollider; - const zeus::CAABox& x0_aabb; - const zeus::CSphere& x4_sphere; - const CMaterialFilter& x8_filter; - const CMaterialList& xc_material; - CCollisionInfoList& x10_collisionList; -public: - CSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere, const CMaterialFilter& filter, - const CMaterialList& material, CCollisionInfoList& collisionList); -}; - -class CBooleanSphereAreaCache -{ - friend class CMetroidAreaCollider; - const zeus::CAABox& x0_aabb; - const zeus::CSphere& x4_sphere; - const CMaterialFilter& x8_filter; -public: - CBooleanSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere, - const CMaterialFilter& filter); -}; - -struct SBoxEdge -{ - zeus::CLineSeg x0_seg; - zeus::CVector3d x28_start; - zeus::CVector3d x40_end; - zeus::CVector3d x58_delta; - zeus::CVector3d x70_coDir; - double x88_dirCoDirDot; - SBoxEdge(const zeus::CAABox& aabb, int idx, const zeus::CVector3f& dir); -}; - -class CMovingAABoxComponents -{ - friend class CMetroidAreaCollider; - friend class CCollidableOBBTree; - rstl::reserved_vector x0_edges; - rstl::reserved_vector x6c4_vertIdxs; - zeus::CAABox x6e8_aabb; -public: - CMovingAABoxComponents(const zeus::CAABox& aabb, const zeus::CVector3f& dir); -}; - -class CMetroidAreaCollider -{ - friend class CCollidableOBBTree; - static u32 g_CalledClip; - static u32 g_RejectedByClip; - static u32 g_TrianglesProcessed; - static u32 g_DupTrianglesProcessed; - static u16 g_DupPrimitiveCheckCount; - static u16 g_DupVertexList[0x5000]; - static u16 g_DupEdgeList[0xC000]; - static u16 g_DupTriangleList[0x4000]; - static bool AABoxCollisionCheckBoolean_Internal(const CAreaOctTree::Node& node, - const CBooleanAABoxAreaCache& cache); - static bool AABoxCollisionCheck_Internal(const CAreaOctTree::Node& node, - const CAABoxAreaCache& cache); - - static bool SphereCollisionCheckBoolean_Internal(const CAreaOctTree::Node& node, - const CBooleanSphereAreaCache& cache); - static bool SphereCollisionCheck_Internal(const CAreaOctTree::Node& node, - const CSphereAreaCache& cache); - - static bool MovingAABoxCollisionCheck_BoxVertexTri(const CCollisionSurface& surf, const zeus::CAABox& aabb, - const rstl::reserved_vector& vertIndices, - const zeus::CVector3f& dir, double& d, - zeus::CVector3f& normal, zeus::CVector3f& point); - static bool MovingAABoxCollisionCheck_TriVertexBox(const zeus::CVector3f& vert, const zeus::CAABox& aabb, - const zeus::CVector3f& dir, double& d, - zeus::CVector3f& normal, zeus::CVector3f& point); - static bool MovingAABoxCollisionCheck_Edge(const zeus::CVector3f& ev0, const zeus::CVector3f& ev1, - const rstl::reserved_vector& edges, - const zeus::CVector3f& dir, double& d, - zeus::CVector3f& normal, zeus::CVector3f& point); -public: - class COctreeLeafCache - { - friend class CMetroidAreaCollider; - const CAreaOctTree& x0_octTree; - rstl::reserved_vector x4_nodeCache; - bool x908_24_overflow : 1; - public: - COctreeLeafCache(const CAreaOctTree& octTree); - void AddLeaf(const CAreaOctTree::Node& node); - u32 GetNumLeaves() const { return x4_nodeCache.size(); } - bool HasCacheOverflowed() const { return x908_24_overflow; } - const CAreaOctTree& GetOctTree() const { return x0_octTree; } - rstl::reserved_vector::iterator begin() { return x4_nodeCache.begin(); } - rstl::reserved_vector::iterator end() { return x4_nodeCache.end(); } +class CAreaCollisionCache { + zeus::CAABox x0_aabb; + rstl::reserved_vector x18_leafCaches; + union { + struct { + bool x1b40_24_leafOverflow : 1; + bool x1b40_25_cacheOverflow : 1; }; - static void BuildOctreeLeafCache(const CAreaOctTree::Node& root, const zeus::CAABox& aabb, - CMetroidAreaCollider::COctreeLeafCache& cache); - static bool ConvexPolyCollision(const zeus::CPlane* planes, const zeus::CVector3f* verts, - zeus::CAABox& aabb); + u32 _dummy = 0; + }; - static bool AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, - const CMaterialFilter& filter); - static bool AABoxCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb, - const CMaterialFilter& filter); - - static bool SphereCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, - const zeus::CSphere& sphere, const CMaterialFilter& filter); - static bool SphereCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb, - const zeus::CSphere& sphere, const CMaterialFilter& filter); - - static bool AABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, - const CMaterialFilter& filter, const CMaterialList& matList, - CCollisionInfoList& list); - static bool AABoxCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb, - const CMaterialFilter& filter, const CMaterialList& matList, - CCollisionInfoList& list); - - static bool SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, - const zeus::CSphere& sphere, const CMaterialList& matList, - const CMaterialFilter& filter, CCollisionInfoList& list); - static bool SphereCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb, - const zeus::CSphere& sphere, const CMaterialList& matList, - const CMaterialFilter& filter, CCollisionInfoList& list); - - static bool MovingAABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, - const CMaterialFilter& filter, const CMaterialList& matList, - const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut, - double& dOut); - static bool MovingSphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, - const zeus::CSphere& sphere, - const CMaterialFilter& filter, const CMaterialList& matList, - const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut, - double& dOut); - static void ResetInternalCounters(); -}; - -class CAreaCollisionCache -{ - zeus::CAABox x0_aabb; - rstl::reserved_vector x18_leafCaches; - union - { - struct - { - bool x1b40_24_leafOverflow : 1; - bool x1b40_25_cacheOverflow : 1; - }; - u32 _dummy = 0; - }; public: - CAreaCollisionCache(const zeus::CAABox& aabb) : x0_aabb(aabb) {} - void ClearCache(); - const zeus::CAABox& GetCacheBounds() const { return x0_aabb; } - void SetCacheBounds(const zeus::CAABox& aabb) { x0_aabb = aabb; } - void AddOctreeLeafCache(const CMetroidAreaCollider::COctreeLeafCache& leafCache); - u32 GetNumCaches() const { return x18_leafCaches.size(); } - const CMetroidAreaCollider::COctreeLeafCache& GetOctreeLeafCache(int idx) { return x18_leafCaches[idx]; } - bool HasCacheOverflowed() const { return x1b40_24_leafOverflow; } - rstl::reserved_vector::iterator begin() { return x18_leafCaches.begin(); } - rstl::reserved_vector::iterator end() { return x18_leafCaches.end(); } + CAreaCollisionCache(const zeus::CAABox& aabb) : x0_aabb(aabb) {} + void ClearCache(); + const zeus::CAABox& GetCacheBounds() const { return x0_aabb; } + void SetCacheBounds(const zeus::CAABox& aabb) { x0_aabb = aabb; } + void AddOctreeLeafCache(const CMetroidAreaCollider::COctreeLeafCache& leafCache); + u32 GetNumCaches() const { return x18_leafCaches.size(); } + const CMetroidAreaCollider::COctreeLeafCache& GetOctreeLeafCache(int idx) { return x18_leafCaches[idx]; } + bool HasCacheOverflowed() const { return x1b40_24_leafOverflow; } + rstl::reserved_vector::iterator begin() { return x18_leafCaches.begin(); } + rstl::reserved_vector::iterator end() { return x18_leafCaches.end(); } }; -} - +} // namespace urde diff --git a/Runtime/Collision/COBBTree.cpp b/Runtime/Collision/COBBTree.cpp index 4182a4953..72bc07178 100644 --- a/Runtime/Collision/COBBTree.cpp +++ b/Runtime/Collision/COBBTree.cpp @@ -1,211 +1,169 @@ #include "COBBTree.hpp" #include "CCollidableOBBTreeGroup.hpp" -namespace urde -{ +namespace urde { /* This is exactly what retro did >.< */ -u32 verify_deaf_babe(CInputStream& in) -{ - return in.readUint32Big(); -} +u32 verify_deaf_babe(CInputStream& in) { return in.readUint32Big(); } /* This is exactly what retro did >.< */ -u32 verify_version(CInputStream& in) -{ - return in.readUint32Big(); -} +u32 verify_version(CInputStream& in) { return in.readUint32Big(); } -COBBTree::COBBTree(const SIndexData& indexData, const CNode* root) - : x18_indexData(indexData), - x88_root((CNode*)root) -{ -} +COBBTree::COBBTree(const SIndexData& indexData, const CNode* root) : x18_indexData(indexData), x88_root((CNode*)root) {} COBBTree::COBBTree(CInputStream& in) - : x0_magic(verify_deaf_babe(in)), - x4_version(verify_version(in)), - x8_memsize(in.readUint32()), - x18_indexData(in), - x88_root(new CNode(in)) -{ +: x0_magic(verify_deaf_babe(in)) +, x4_version(verify_version(in)) +, x8_memsize(in.readUint32()) +, x18_indexData(in) +, x88_root(new CNode(in)) {} + +std::unique_ptr COBBTree::BuildOrientedBoundingBoxTree(const zeus::CVector3f& a, + const zeus::CVector3f& b) { + return std::make_unique(a, b); } -std::unique_ptr -COBBTree::BuildOrientedBoundingBoxTree(const zeus::CVector3f& a, const zeus::CVector3f& b) -{ - return std::make_unique(a, b); -} +CCollisionSurface COBBTree::GetSurface(u16 idx) const { + int surfIdx = idx * 3; + CCollisionEdge e0 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[surfIdx]]; + CCollisionEdge e1 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[surfIdx + 1]]; + u16 vert1 = e0.GetVertIndex1(); + u16 vert2 = e0.GetVertIndex2(); + u16 vert3 = e1.GetVertIndex1(); -CCollisionSurface COBBTree::GetSurface(u16 idx) const -{ - int surfIdx = idx * 3; - CCollisionEdge e0 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[surfIdx]]; - CCollisionEdge e1 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[surfIdx + 1]]; - u16 vert1 = e0.GetVertIndex1(); - u16 vert2 = e0.GetVertIndex2(); - u16 vert3 = e1.GetVertIndex1(); + if (vert3 == vert1 || vert3 == vert2) + vert3 = e1.GetVertIndex2(); - if (vert3 == vert1 || vert3 == vert2) - vert3 = e1.GetVertIndex2(); + u32 mat = x18_indexData.x0_materials[x18_indexData.x30_surfaceMaterials[idx]]; - u32 mat = x18_indexData.x0_materials[x18_indexData.x30_surfaceMaterials[idx]]; - - if ((mat & 0x2000000) != 0) - { - return CCollisionSurface(x18_indexData.x60_vertices[vert2], x18_indexData.x60_vertices[vert1], - x18_indexData.x60_vertices[vert3], mat); - } - return CCollisionSurface(x18_indexData.x60_vertices[vert1], x18_indexData.x60_vertices[vert2], + if ((mat & 0x2000000) != 0) { + return CCollisionSurface(x18_indexData.x60_vertices[vert2], x18_indexData.x60_vertices[vert1], x18_indexData.x60_vertices[vert3], mat); + } + return CCollisionSurface(x18_indexData.x60_vertices[vert1], x18_indexData.x60_vertices[vert2], + x18_indexData.x60_vertices[vert3], mat); } -void COBBTree::GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const -{ - const CCollisionEdge& e0 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[idx*3]]; - const CCollisionEdge& e1 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[idx*3+1]]; - indicesOut[2] = - (e1.GetVertIndex1() != e0.GetVertIndex1() && e1.GetVertIndex1() != e0.GetVertIndex2()) ? - e1.GetVertIndex1() : e1.GetVertIndex2(); +void COBBTree::GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const { + const CCollisionEdge& e0 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[idx * 3]]; + const CCollisionEdge& e1 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[idx * 3 + 1]]; + indicesOut[2] = (e1.GetVertIndex1() != e0.GetVertIndex1() && e1.GetVertIndex1() != e0.GetVertIndex2()) + ? e1.GetVertIndex1() + : e1.GetVertIndex2(); - u32 material = x18_indexData.x0_materials[x18_indexData.x30_surfaceMaterials[idx]]; - if (material & 0x2000000) - { - indicesOut[0] = e0.GetVertIndex2(); - indicesOut[1] = e0.GetVertIndex1(); - } - else - { - indicesOut[0] = e0.GetVertIndex1(); - indicesOut[1] = e0.GetVertIndex2(); - } + u32 material = x18_indexData.x0_materials[x18_indexData.x30_surfaceMaterials[idx]]; + if (material & 0x2000000) { + indicesOut[0] = e0.GetVertIndex2(); + indicesOut[1] = e0.GetVertIndex1(); + } else { + indicesOut[0] = e0.GetVertIndex1(); + indicesOut[1] = e0.GetVertIndex2(); + } } -CCollisionSurface COBBTree::GetTransformedSurface(u16 idx, const zeus::CTransform& xf) const -{ - int surfIdx = idx * 3; - CCollisionEdge e0 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[surfIdx]]; - CCollisionEdge e1 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[surfIdx + 1]]; - u16 vert1 = e0.GetVertIndex1(); - u16 vert2 = e0.GetVertIndex2(); - u16 vert3 = e1.GetVertIndex1(); +CCollisionSurface COBBTree::GetTransformedSurface(u16 idx, const zeus::CTransform& xf) const { + int surfIdx = idx * 3; + CCollisionEdge e0 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[surfIdx]]; + CCollisionEdge e1 = x18_indexData.x40_edges[x18_indexData.x50_surfaceIndices[surfIdx + 1]]; + u16 vert1 = e0.GetVertIndex1(); + u16 vert2 = e0.GetVertIndex2(); + u16 vert3 = e1.GetVertIndex1(); - if (vert3 == vert1 || vert3 == vert2) - vert3 = e1.GetVertIndex2(); + if (vert3 == vert1 || vert3 == vert2) + vert3 = e1.GetVertIndex2(); - u32 mat = x18_indexData.x0_materials[x18_indexData.x30_surfaceMaterials[idx]]; + u32 mat = x18_indexData.x0_materials[x18_indexData.x30_surfaceMaterials[idx]]; - if ((mat & 0x2000000) != 0) - { - return CCollisionSurface(xf * x18_indexData.x60_vertices[vert2], xf * x18_indexData.x60_vertices[vert1], - xf * x18_indexData.x60_vertices[vert3], mat); - } - return CCollisionSurface(xf * x18_indexData.x60_vertices[vert1], xf * x18_indexData.x60_vertices[vert2], + if ((mat & 0x2000000) != 0) { + return CCollisionSurface(xf * x18_indexData.x60_vertices[vert2], xf * x18_indexData.x60_vertices[vert1], xf * x18_indexData.x60_vertices[vert3], mat); + } + return CCollisionSurface(xf * x18_indexData.x60_vertices[vert1], xf * x18_indexData.x60_vertices[vert2], + xf * x18_indexData.x60_vertices[vert3], mat); } -zeus::CAABox COBBTree::CalculateLocalAABox() const -{ - return CalculateAABox(zeus::CTransform::Identity()); +zeus::CAABox COBBTree::CalculateLocalAABox() const { return CalculateAABox(zeus::CTransform::Identity()); } + +zeus::CAABox COBBTree::CalculateAABox(const zeus::CTransform& xf) const { + if (x88_root) + return x88_root->GetOBB().calculateAABox(xf); + return zeus::CAABox::skInvertedBox; } -zeus::CAABox COBBTree::CalculateAABox(const zeus::CTransform& xf) const -{ - if (x88_root) - return x88_root->GetOBB().calculateAABox(xf); - return zeus::CAABox::skInvertedBox; +COBBTree::SIndexData::SIndexData(CInputStream& in) { + u32 count = in.readUint32Big(); + x0_materials.reserve(count); + for (u32 i = 0; i < count; i++) + x0_materials.push_back(in.readUint32Big()); + + count = in.readUint32Big(); + for (u32 i = 0; i < count; i++) + x10_vertMaterials.push_back(in.readUByte()); + count = in.readUint32Big(); + for (u32 i = 0; i < count; i++) + x20_edgeMaterials.push_back(in.readUByte()); + count = in.readUint32Big(); + for (u32 i = 0; i < count; i++) + x30_surfaceMaterials.push_back(in.readUByte()); + + count = in.readUint32Big(); + for (u32 i = 0; i < count; i++) + x40_edges.push_back(in); + + count = in.readUint32Big(); + for (u32 i = 0; i < count; i++) + x50_surfaceIndices.push_back(in.readUint16Big()); + + count = in.readUint32Big(); + for (u32 i = 0; i < count; i++) + x60_vertices.push_back(zeus::CVector3f::ReadBig(in)); } -COBBTree::SIndexData::SIndexData(CInputStream& in) -{ - u32 count = in.readUint32Big(); - x0_materials.reserve(count); - for (u32 i = 0 ; i < count ; i++) - x0_materials.push_back(in.readUint32Big()); - - count = in.readUint32Big(); - for (u32 i = 0 ; i < count ; i++) - x10_vertMaterials.push_back(in.readUByte()); - count = in.readUint32Big(); - for (u32 i = 0 ; i < count ; i++) - x20_edgeMaterials.push_back(in.readUByte()); - count = in.readUint32Big(); - for (u32 i = 0 ; i < count ; i++) - x30_surfaceMaterials.push_back(in.readUByte()); - - count = in.readUint32Big(); - for (u32 i = 0 ; i < count ; i++) - x40_edges.push_back(in); - - count = in.readUint32Big(); - for (u32 i = 0 ; i < count ; i++) - x50_surfaceIndices.push_back(in.readUint16Big()); - - count = in.readUint32Big(); - for (u32 i = 0 ; i < count ; i++) - x60_vertices.push_back(zeus::CVector3f::ReadBig(in)); +COBBTree::CNode::CNode(const zeus::CTransform& xf, const zeus::CVector3f& point, const COBBTree::CNode* left, + const COBBTree::CNode* right, const COBBTree::CLeafData* leaf) +: x0_obb(xf, point), x3c_isLeaf(leaf != nullptr) { + x40_left.reset((CNode*)left); + x44_right.reset((CNode*)right); + x48_leaf.reset((CLeafData*)leaf); } -COBBTree::CNode::CNode(const zeus::CTransform& xf, const zeus::CVector3f& point, - const COBBTree::CNode* left, const COBBTree::CNode* right, - const COBBTree::CLeafData* leaf) - : x0_obb(xf, point), - x3c_isLeaf(leaf != nullptr) -{ - x40_left.reset((CNode*)left); - x44_right.reset((CNode*)right); - x48_leaf.reset((CLeafData*)leaf); +COBBTree::CNode::CNode(CInputStream& in) { + x0_obb = zeus::COBBox::ReadBig(in); + x3c_isLeaf = in.readBool(); + if (x3c_isLeaf) + x48_leaf.reset(new CLeafData(in)); + else { + x40_left.reset(new CNode(in)); + x44_right.reset(new CNode(in)); + } } -COBBTree::CNode::CNode(CInputStream& in) -{ - x0_obb = zeus::COBBox::ReadBig(in); - x3c_isLeaf = in.readBool(); - if (x3c_isLeaf) - x48_leaf.reset(new CLeafData(in)); - else - { - x40_left.reset(new CNode(in)); - x44_right.reset(new CNode(in)); - } +size_t COBBTree::CNode::GetMemoryUsage() const { + size_t ret = 0; + if (x3c_isLeaf) + ret = x48_leaf->GetMemoryUsage() + /*sizeof(CNode)*/ 80; + else { + if (x40_left) + ret = x40_left->GetMemoryUsage() + /*sizeof(CNode)*/ 80; + if (x44_right) + ret += x44_right->GetMemoryUsage(); + } + + return (ret + 3) & ~3; } -size_t COBBTree::CNode::GetMemoryUsage() const -{ - size_t ret = 0; - if (x3c_isLeaf) - ret = x48_leaf->GetMemoryUsage() + /*sizeof(CNode)*/ 80; - else - { - if (x40_left) - ret = x40_left->GetMemoryUsage() + /*sizeof(CNode)*/ 80; - if (x44_right) - ret += x44_right->GetMemoryUsage(); - } +COBBTree::CLeafData::CLeafData(const std::vector& surface) : x0_surface(surface) {} - return (ret + 3) & ~3; +const std::vector& COBBTree::CLeafData::GetSurfaceVector() const { return x0_surface; } + +size_t COBBTree::CLeafData::GetMemoryUsage() const { + size_t ret = (x0_surface.size() * 2) + /*sizeof(CLeafData)*/ 16; + return (ret + 3) & ~3; } -COBBTree::CLeafData::CLeafData(const std::vector& surface) - : x0_surface(surface) -{ +COBBTree::CLeafData::CLeafData(CInputStream& in) { + u32 edgeCount = in.readUint32Big(); + for (u32 i = 0; i < edgeCount; i++) + x0_surface.push_back(in.readUint16Big()); } -const std::vector& COBBTree::CLeafData::GetSurfaceVector() const -{ - return x0_surface; -} - -size_t COBBTree::CLeafData::GetMemoryUsage() const -{ - size_t ret = (x0_surface.size() * 2) + /*sizeof(CLeafData)*/ 16; - return (ret + 3) & ~3; -} - -COBBTree::CLeafData::CLeafData(CInputStream& in) -{ - u32 edgeCount = in.readUint32Big(); - for (u32 i = 0 ; i < edgeCount ; i++) - x0_surface.push_back(in.readUint16Big()); -} - -} +} // namespace urde diff --git a/Runtime/Collision/COBBTree.hpp b/Runtime/Collision/COBBTree.hpp index 8161d0c57..9c5e8a0b0 100644 --- a/Runtime/Collision/COBBTree.hpp +++ b/Runtime/Collision/COBBTree.hpp @@ -5,88 +5,84 @@ #include "zeus/CVector3f.hpp" #include "zeus/COBBox.hpp" -namespace urde -{ +namespace urde { class CCollidableOBBTreeGroupContainer; -class COBBTree -{ +class COBBTree { public: - struct SIndexData - { - std::vector x0_materials; - std::vector x10_vertMaterials; - std::vector x20_edgeMaterials; - std::vector x30_surfaceMaterials; - std::vector x40_edges; - std::vector x50_surfaceIndices; - std::vector x60_vertices; - SIndexData()=default; - SIndexData(CInputStream&); - }; + struct SIndexData { + std::vector x0_materials; + std::vector x10_vertMaterials; + std::vector x20_edgeMaterials; + std::vector x30_surfaceMaterials; + std::vector x40_edges; + std::vector x50_surfaceIndices; + std::vector x60_vertices; + SIndexData() = default; + SIndexData(CInputStream&); + }; - class CLeafData - { - std::vector x0_surface; - public: - CLeafData()=default; - CLeafData(const std::vector&); - CLeafData(CInputStream&); + class CLeafData { + std::vector x0_surface; - const std::vector& GetSurfaceVector() const; - size_t GetMemoryUsage() const; - }; + public: + CLeafData() = default; + CLeafData(const std::vector&); + CLeafData(CInputStream&); - class CNode - { - zeus::COBBox x0_obb; - bool x3c_isLeaf = false; - std::unique_ptr x40_left; - std::unique_ptr x44_right; - std::unique_ptr x48_leaf; - bool x4c_hit; - public: - CNode() = default; - CNode(const CNode&)=default; - CNode(const zeus::CTransform&, const zeus::CVector3f&, const CNode*, const CNode*, const CLeafData*); - CNode(CInputStream&); + const std::vector& GetSurfaceVector() const; + size_t GetMemoryUsage() const; + }; - bool WasHit() const { return x4c_hit; } - void SetHit(bool h) { x4c_hit = h; } - const CNode& GetLeft() const { return *x40_left; } - const CNode& GetRight() const { return *x44_right; } - const CLeafData& GetLeafData() const { return *x48_leaf; } - const zeus::COBBox& GetOBB() const { return x0_obb; } - size_t GetMemoryUsage() const; - bool IsLeaf() const { return x3c_isLeaf; } - }; + class CNode { + zeus::COBBox x0_obb; + bool x3c_isLeaf = false; + std::unique_ptr x40_left; + std::unique_ptr x44_right; + std::unique_ptr x48_leaf; + bool x4c_hit; + + public: + CNode() = default; + CNode(const CNode&) = default; + CNode(const zeus::CTransform&, const zeus::CVector3f&, const CNode*, const CNode*, const CLeafData*); + CNode(CInputStream&); + + bool WasHit() const { return x4c_hit; } + void SetHit(bool h) { x4c_hit = h; } + const CNode& GetLeft() const { return *x40_left; } + const CNode& GetRight() const { return *x44_right; } + const CLeafData& GetLeafData() const { return *x48_leaf; } + const zeus::COBBox& GetOBB() const { return x0_obb; } + size_t GetMemoryUsage() const; + bool IsLeaf() const { return x3c_isLeaf; } + }; private: + u32 x0_magic = 0; + u32 x4_version = 0; + u32 x8_memsize = 0; + /* CSimpleAllocator xc_ We're not using this but lets keep track*/ + SIndexData x18_indexData; + std::unique_ptr x88_root; - u32 x0_magic = 0; - u32 x4_version = 0; - u32 x8_memsize = 0; - /* CSimpleAllocator xc_ We're not using this but lets keep track*/ - SIndexData x18_indexData; - std::unique_ptr x88_root; public: - COBBTree()=default; - COBBTree(const COBBTree::SIndexData&, const CNode*); - COBBTree(CInputStream&); + COBBTree() = default; + COBBTree(const COBBTree::SIndexData&, const CNode*); + COBBTree(CInputStream&); - static std::unique_ptr - BuildOrientedBoundingBoxTree(const zeus::CVector3f&, const zeus::CVector3f&); - CCollisionSurface GetSurface(u16 idx) const; - const u16* GetTriangleEdgeIndices(u16 idx) const { return &x18_indexData.x50_surfaceIndices[idx * 3]; } - void GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const; - const CCollisionEdge& GetEdge(int idx) const { return x18_indexData.x40_edges[idx]; } - const zeus::CVector3f& GetVert(int idx) const { return x18_indexData.x60_vertices[idx]; } - u32 GetVertMaterial(u16 idx) const { return x18_indexData.x0_materials[x18_indexData.x10_vertMaterials[idx]]; } - u32 GetEdgeMaterial(u16 idx) const { return x18_indexData.x0_materials[x18_indexData.x20_edgeMaterials[idx]]; } - CCollisionSurface GetTransformedSurface(u16 idx, const zeus::CTransform& xf) const; - zeus::CAABox CalculateLocalAABox() const; - zeus::CAABox CalculateAABox(const zeus::CTransform&) const; - const CNode& GetRoot() const { return *x88_root; } + static std::unique_ptr BuildOrientedBoundingBoxTree(const zeus::CVector3f&, + const zeus::CVector3f&); + CCollisionSurface GetSurface(u16 idx) const; + const u16* GetTriangleEdgeIndices(u16 idx) const { return &x18_indexData.x50_surfaceIndices[idx * 3]; } + void GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const; + const CCollisionEdge& GetEdge(int idx) const { return x18_indexData.x40_edges[idx]; } + const zeus::CVector3f& GetVert(int idx) const { return x18_indexData.x60_vertices[idx]; } + u32 GetVertMaterial(u16 idx) const { return x18_indexData.x0_materials[x18_indexData.x10_vertMaterials[idx]]; } + u32 GetEdgeMaterial(u16 idx) const { return x18_indexData.x0_materials[x18_indexData.x20_edgeMaterials[idx]]; } + CCollisionSurface GetTransformedSurface(u16 idx, const zeus::CTransform& xf) const; + zeus::CAABox CalculateLocalAABox() const; + zeus::CAABox CalculateAABox(const zeus::CTransform&) const; + const CNode& GetRoot() const { return *x88_root; } }; -} - +} // namespace urde diff --git a/Runtime/Collision/CRayCastResult.cpp b/Runtime/Collision/CRayCastResult.cpp index 72c02a178..bdfe815e6 100644 --- a/Runtime/Collision/CRayCastResult.cpp +++ b/Runtime/Collision/CRayCastResult.cpp @@ -1,12 +1,9 @@ #include "CRayCastResult.hpp" +namespace urde { -namespace urde -{ - -void CRayCastResult::MakeInvalid() -{ - /* NOTE: CRayCastResult: Enable this if it's required, this is a total guess - Phil */ +void CRayCastResult::MakeInvalid() { + /* NOTE: CRayCastResult: Enable this if it's required, this is a total guess - Phil */ #if 0 x0_time = 0.f; x4_point.zeroOut(); @@ -14,13 +11,12 @@ void CRayCastResult::MakeInvalid() x10_plane.d = 0.f; x28_material = CMaterialList(); #endif - x20_invalid = EInvalid::Invalid; + x20_invalid = EInvalid::Invalid; } -void CRayCastResult::Transform(const zeus::CTransform& xf) -{ - x4_point = xf * x4_point; - x10_plane = zeus::CPlane(xf.rotate(x10_plane.normal()), x10_plane.normal().dot(x4_point)); +void CRayCastResult::Transform(const zeus::CTransform& xf) { + x4_point = xf * x4_point; + x10_plane = zeus::CPlane(xf.rotate(x10_plane.normal()), x10_plane.normal().dot(x4_point)); } -} +} // namespace urde diff --git a/Runtime/Collision/CRayCastResult.hpp b/Runtime/Collision/CRayCastResult.hpp index 8f2c40042..86f49f3a5 100644 --- a/Runtime/Collision/CRayCastResult.hpp +++ b/Runtime/Collision/CRayCastResult.hpp @@ -3,49 +3,39 @@ #include "CMaterialList.hpp" #include "zeus/zeus.hpp" -namespace urde -{ -class CRayCastResult -{ +namespace urde { +class CRayCastResult { public: - enum class EInvalid : u8 - { - Invalid, - Valid - }; + enum class EInvalid : u8 { Invalid, Valid }; + private: - float x0_t = 0.f; - zeus::CVector3f x4_point; - zeus::CPlane x10_plane; - EInvalid x20_invalid = EInvalid::Invalid; - CMaterialList x28_material; + float x0_t = 0.f; + zeus::CVector3f x4_point; + zeus::CPlane x10_plane; + EInvalid x20_invalid = EInvalid::Invalid; + CMaterialList x28_material; + public: - CRayCastResult() = default; - CRayCastResult(const CRayCastResult& other, EInvalid invalid) - : x0_t(other.x0_t), - x4_point(other.x4_point), - x10_plane(other.x10_plane), - x20_invalid(invalid), - x28_material(other.x28_material) - { - } + CRayCastResult() = default; + CRayCastResult(const CRayCastResult& other, EInvalid invalid) + : x0_t(other.x0_t) + , x4_point(other.x4_point) + , x10_plane(other.x10_plane) + , x20_invalid(invalid) + , x28_material(other.x28_material) {} - CRayCastResult(float t, const zeus::CVector3f& point, - const zeus::CPlane& plane, const CMaterialList& matList) - : x0_t(t), x4_point(point), x10_plane(plane), - x20_invalid(EInvalid::Valid), x28_material(matList) - {} + CRayCastResult(float t, const zeus::CVector3f& point, const zeus::CPlane& plane, const CMaterialList& matList) + : x0_t(t), x4_point(point), x10_plane(plane), x20_invalid(EInvalid::Valid), x28_material(matList) {} - void MakeInvalid(); + void MakeInvalid(); - bool IsInvalid() const { return x20_invalid == EInvalid::Invalid; } - bool IsValid() const { return x20_invalid == EInvalid::Valid; } - float GetT() const { return x0_t; } - const zeus::CVector3f& GetPoint() const { return x4_point; } - const zeus::CPlane& GetPlane() const { return x10_plane; } - const CMaterialList& GetMaterial() const { return x28_material; } + bool IsInvalid() const { return x20_invalid == EInvalid::Invalid; } + bool IsValid() const { return x20_invalid == EInvalid::Valid; } + float GetT() const { return x0_t; } + const zeus::CVector3f& GetPoint() const { return x4_point; } + const zeus::CPlane& GetPlane() const { return x10_plane; } + const CMaterialList& GetMaterial() const { return x28_material; } - void Transform(const zeus::CTransform&); + void Transform(const zeus::CTransform&); }; -} - +} // namespace urde diff --git a/Runtime/Collision/CollisionUtil.cpp b/Runtime/Collision/CollisionUtil.cpp index c7ce67bce..f3bf1a805 100644 --- a/Runtime/Collision/CollisionUtil.cpp +++ b/Runtime/Collision/CollisionUtil.cpp @@ -2,461 +2,375 @@ #include "CCollisionInfo.hpp" #include "CCollisionInfoList.hpp" -namespace urde::CollisionUtil -{ -bool LineIntersectsOBBox(const zeus::COBBox& obb, const zeus::CMRay& ray, float& d) -{ - zeus::CVector3f norm; - return RayAABoxIntersection(ray.getInvUnscaledTransformRay(obb.transform), {-obb.extents, obb.extents}, - norm, d); +namespace urde::CollisionUtil { +bool LineIntersectsOBBox(const zeus::COBBox& obb, const zeus::CMRay& ray, float& d) { + zeus::CVector3f norm; + return RayAABoxIntersection(ray.getInvUnscaledTransformRay(obb.transform), {-obb.extents, obb.extents}, norm, d); } -u32 RayAABoxIntersection(const zeus::CMRay& ray, const zeus::CAABox& aabb, float& tMin, float& tMax) -{ - tMin = -999999.f; - tMax = 999999.f; +u32 RayAABoxIntersection(const zeus::CMRay& ray, const zeus::CAABox& aabb, float& tMin, float& tMax) { + tMin = -999999.f; + tMax = 999999.f; - for (int i=0 ; i<3 ; ++i) - { - if (std::fabs(ray.dir[i]) < 0.00001f) - { - if (ray.start[i] < aabb.min[i] || ray.start[i] > aabb.max[i]) - return 0; - } - else - { - if (ray.dir[i] < 0.f) - { - float startToMax = aabb.max[i] - ray.start[i]; - float startToMin = aabb.min[i] - ray.start[i]; - float dirRecip = 1.f / ray.dir[i]; - if (startToMax < tMin * ray.dir[i]) - tMin = startToMax * dirRecip; - if (startToMin > tMax * ray.dir[i]) - tMax = startToMin * dirRecip; - } - else - { - float startToMin = aabb.min[i] - ray.start[i]; - float startToMax = aabb.max[i] - ray.start[i]; - float dirRecip = 1.f / ray.dir[i]; - if (startToMin > tMin * ray.dir[i]) - tMin = startToMin * dirRecip; - if (startToMax < tMax * ray.dir[i]) - tMax = startToMax * dirRecip; - } - } - } - - return tMin <= tMax ? 2 : 0; -} - -u32 RayAABoxIntersection(const zeus::CMRay& ray, const zeus::CAABox& aabb, - zeus::CVector3f& norm, float& d) -{ - int sign[] = {2, 2, 2}; - bool bad = true; - zeus::CVector3f rayStart = ray.start; - zeus::CVector3f rayDelta = ray.delta; - zeus::CVector3f aabbMin = aabb.min; - zeus::CVector3f aabbMax = aabb.max; - - zeus::CVector3f vec0 = {-1.f, -1.f, -1.f}; - zeus::CVector3f vec1; - - if (rayDelta.x() != 0.f && rayDelta.y() != 0.f && rayDelta.z() != 0.f) - { - for (int i=0 ; i<3 ; ++i) - { - if (rayStart[i] < aabbMin[i]) - { - sign[i] = 1; - bad = false; - vec0[i] = (aabbMin[i] - rayStart[i]) / rayDelta[i]; - } - else if (rayStart[i] > aabbMax[i]) - { - sign[i] = 0; - bad = false; - vec0[i] = (aabbMax[i] - rayStart[i]) / rayDelta[i]; - } - } - - if (bad) - { - d = 0.f; - return 1; - } - } - else - { - zeus::CVector3f end; - for (int i=0 ; i<3 ; ++i) - { - if (rayStart[i] < aabbMin[i]) - { - sign[i] = 1; - bad = false; - end[i] = float(aabbMin[i]); - } - else if (rayStart[i] > aabbMax[i]) - { - sign[i] = 0; - bad = false; - end[i] = float(aabbMax[i]); - } - } - - if (bad) - { - d = 0.f; - return 1; - } - - for (int i=0 ; i<3 ; ++i) - if (sign[i] != 2 && rayDelta[i] != 0.f) - vec0[i] = (end[i] - rayStart[i]) / rayDelta[i]; - } - - float maxComp = vec0.x(); - int maxCompIdx = 0; - if (maxComp < vec0.y()) - { - maxComp = vec0.y(); - maxCompIdx = 1; - } - if (maxComp < vec0.z()) - { - maxComp = vec0.z(); - maxCompIdx = 2; - } - - if (maxComp < 0.f || maxComp > 1.f) + for (int i = 0; i < 3; ++i) { + if (std::fabs(ray.dir[i]) < 0.00001f) { + if (ray.start[i] < aabb.min[i] || ray.start[i] > aabb.max[i]) return 0; - - for (int i=0 ; i<3 ; ++i) - { - if (maxCompIdx != i) - { - vec1[i] = maxComp * rayDelta[i] + rayStart[i]; - if (vec1[i] > aabbMax[i]) - return 0; - } + } else { + if (ray.dir[i] < 0.f) { + float startToMax = aabb.max[i] - ray.start[i]; + float startToMin = aabb.min[i] - ray.start[i]; + float dirRecip = 1.f / ray.dir[i]; + if (startToMax < tMin * ray.dir[i]) + tMin = startToMax * dirRecip; + if (startToMin > tMax * ray.dir[i]) + tMax = startToMin * dirRecip; + } else { + float startToMin = aabb.min[i] - ray.start[i]; + float startToMax = aabb.max[i] - ray.start[i]; + float dirRecip = 1.f / ray.dir[i]; + if (startToMin > tMin * ray.dir[i]) + tMin = startToMin * dirRecip; + if (startToMax < tMax * ray.dir[i]) + tMax = startToMax * dirRecip; + } } + } - d = maxComp; - norm = zeus::CVector3f::skZero; - norm[maxCompIdx] = (sign[maxCompIdx] == 1) ? -1.f : 1.f; - return 2; + return tMin <= tMax ? 2 : 0; } -u32 RayAABoxIntersection_Double(const zeus::CMRay& ray, const zeus::CAABox& aabb, - zeus::CVector3f& norm, double& d) -{ - int sign[] = {2, 2, 2}; - bool bad = true; - zeus::CVector3d rayStart = ray.start; - zeus::CVector3d rayDelta = ray.delta; - zeus::CVector3d aabbMin = aabb.min; - zeus::CVector3d aabbMax = aabb.max; +u32 RayAABoxIntersection(const zeus::CMRay& ray, const zeus::CAABox& aabb, zeus::CVector3f& norm, float& d) { + int sign[] = {2, 2, 2}; + bool bad = true; + zeus::CVector3f rayStart = ray.start; + zeus::CVector3f rayDelta = ray.delta; + zeus::CVector3f aabbMin = aabb.min; + zeus::CVector3f aabbMax = aabb.max; - zeus::CVector3d vec0 = {-1.0, -1.0, -1.0}; - zeus::CVector3d vec1; + zeus::CVector3f vec0 = {-1.f, -1.f, -1.f}; + zeus::CVector3f vec1; - if (rayDelta.x() != 0.0 && rayDelta.y() != 0.0 && rayDelta.z() != 0.0) - { - for (int i=0 ; i<3 ; ++i) - { - if (rayStart[i] < aabbMin[i]) - { - sign[i] = 1; - bad = false; - vec0[i] = (aabbMin[i] - rayStart[i]) / rayDelta[i]; - } - else if (rayStart[i] > aabbMax[i]) - { - sign[i] = 0; - bad = false; - vec0[i] = (aabbMax[i] - rayStart[i]) / rayDelta[i]; - } - } - - if (bad) - { - d = 0.0; - return 1; - } - } - else - { - zeus::CVector3d end; - for (int i=0 ; i<3 ; ++i) - { - if (rayStart[i] < aabbMin[i]) - { - sign[i] = 1; - bad = false; - end[i] = double(aabbMin[i]); - } - else if (rayStart[i] > aabbMax[i]) - { - sign[i] = 0; - bad = false; - end[i] = double(aabbMax[i]); - } - } - - if (bad) - { - d = 0.0; - return 1; - } - - for (int i=0 ; i<3 ; ++i) - if (sign[i] != 2 && rayDelta[i] != 0.0) - vec0[i] = (end[i] - rayStart[i]) / rayDelta[i]; + if (rayDelta.x() != 0.f && rayDelta.y() != 0.f && rayDelta.z() != 0.f) { + for (int i = 0; i < 3; ++i) { + if (rayStart[i] < aabbMin[i]) { + sign[i] = 1; + bad = false; + vec0[i] = (aabbMin[i] - rayStart[i]) / rayDelta[i]; + } else if (rayStart[i] > aabbMax[i]) { + sign[i] = 0; + bad = false; + vec0[i] = (aabbMax[i] - rayStart[i]) / rayDelta[i]; + } } - double maxComp = vec0.x(); - int maxCompIdx = 0; - if (maxComp < vec0.y()) - { - maxComp = vec0.y(); - maxCompIdx = 1; + if (bad) { + d = 0.f; + return 1; } - if (maxComp < vec0.z()) - { - maxComp = vec0.z(); - maxCompIdx = 2; + } else { + zeus::CVector3f end; + for (int i = 0; i < 3; ++i) { + if (rayStart[i] < aabbMin[i]) { + sign[i] = 1; + bad = false; + end[i] = float(aabbMin[i]); + } else if (rayStart[i] > aabbMax[i]) { + sign[i] = 0; + bad = false; + end[i] = float(aabbMax[i]); + } } - if (maxComp < 0.0 || maxComp > 1.0) + if (bad) { + d = 0.f; + return 1; + } + + for (int i = 0; i < 3; ++i) + if (sign[i] != 2 && rayDelta[i] != 0.f) + vec0[i] = (end[i] - rayStart[i]) / rayDelta[i]; + } + + float maxComp = vec0.x(); + int maxCompIdx = 0; + if (maxComp < vec0.y()) { + maxComp = vec0.y(); + maxCompIdx = 1; + } + if (maxComp < vec0.z()) { + maxComp = vec0.z(); + maxCompIdx = 2; + } + + if (maxComp < 0.f || maxComp > 1.f) + return 0; + + for (int i = 0; i < 3; ++i) { + if (maxCompIdx != i) { + vec1[i] = maxComp * rayDelta[i] + rayStart[i]; + if (vec1[i] > aabbMax[i]) return 0; - - for (int i=0 ; i<3 ; ++i) - { - if (maxCompIdx != i) - { - vec1[i] = maxComp * rayDelta[i] + rayStart[i]; - if (vec1[i] > aabbMax[i]) - return 0; - } } + } - d = maxComp; - norm = zeus::CVector3f::skZero; - norm[maxCompIdx] = (sign[maxCompIdx] == 1) ? -1.0 : 1.0; - return 2; + d = maxComp; + norm = zeus::CVector3f::skZero; + norm[maxCompIdx] = (sign[maxCompIdx] == 1) ? -1.f : 1.f; + return 2; } -bool RaySphereIntersection_Double(const zeus::CSphere& sphere, const zeus::CVector3f& pos, - const zeus::CVector3f& dir, double& T) -{ - zeus::CVector3d sPosD = sphere.position; - zeus::CVector3d posD = pos; - zeus::CVector3d sphereToPos = posD - sPosD; - double f30 = sphereToPos.dot(zeus::CVector3d(dir)) * 2.0; - double f1 = f30 * f30 - 4.0 * (sphereToPos.magSquared() - sphere.radius * sphere.radius); - if (f1 >= 0.0) - { - double intersectT = 0.5 * (-f30 - std::sqrt(f1)); - if (T == 0 || intersectT < T) - { - T = intersectT; - return true; - } +u32 RayAABoxIntersection_Double(const zeus::CMRay& ray, const zeus::CAABox& aabb, zeus::CVector3f& norm, double& d) { + int sign[] = {2, 2, 2}; + bool bad = true; + zeus::CVector3d rayStart = ray.start; + zeus::CVector3d rayDelta = ray.delta; + zeus::CVector3d aabbMin = aabb.min; + zeus::CVector3d aabbMax = aabb.max; + + zeus::CVector3d vec0 = {-1.0, -1.0, -1.0}; + zeus::CVector3d vec1; + + if (rayDelta.x() != 0.0 && rayDelta.y() != 0.0 && rayDelta.z() != 0.0) { + for (int i = 0; i < 3; ++i) { + if (rayStart[i] < aabbMin[i]) { + sign[i] = 1; + bad = false; + vec0[i] = (aabbMin[i] - rayStart[i]) / rayDelta[i]; + } else if (rayStart[i] > aabbMax[i]) { + sign[i] = 0; + bad = false; + vec0[i] = (aabbMax[i] - rayStart[i]) / rayDelta[i]; + } } - return false; + + if (bad) { + d = 0.0; + return 1; + } + } else { + zeus::CVector3d end; + for (int i = 0; i < 3; ++i) { + if (rayStart[i] < aabbMin[i]) { + sign[i] = 1; + bad = false; + end[i] = double(aabbMin[i]); + } else if (rayStart[i] > aabbMax[i]) { + sign[i] = 0; + bad = false; + end[i] = double(aabbMax[i]); + } + } + + if (bad) { + d = 0.0; + return 1; + } + + for (int i = 0; i < 3; ++i) + if (sign[i] != 2 && rayDelta[i] != 0.0) + vec0[i] = (end[i] - rayStart[i]) / rayDelta[i]; + } + + double maxComp = vec0.x(); + int maxCompIdx = 0; + if (maxComp < vec0.y()) { + maxComp = vec0.y(); + maxCompIdx = 1; + } + if (maxComp < vec0.z()) { + maxComp = vec0.z(); + maxCompIdx = 2; + } + + if (maxComp < 0.0 || maxComp > 1.0) + return 0; + + for (int i = 0; i < 3; ++i) { + if (maxCompIdx != i) { + vec1[i] = maxComp * rayDelta[i] + rayStart[i]; + if (vec1[i] > aabbMax[i]) + return 0; + } + } + + d = maxComp; + norm = zeus::CVector3f::skZero; + norm[maxCompIdx] = (sign[maxCompIdx] == 1) ? -1.0 : 1.0; + return 2; +} + +bool RaySphereIntersection_Double(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir, + double& T) { + zeus::CVector3d sPosD = sphere.position; + zeus::CVector3d posD = pos; + zeus::CVector3d sphereToPos = posD - sPosD; + double f30 = sphereToPos.dot(zeus::CVector3d(dir)) * 2.0; + double f1 = f30 * f30 - 4.0 * (sphereToPos.magSquared() - sphere.radius * sphere.radius); + if (f1 >= 0.0) { + double intersectT = 0.5 * (-f30 - std::sqrt(f1)); + if (T == 0 || intersectT < T) { + T = intersectT; + return true; + } + } + return false; } bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir, - float mag, float& T, zeus::CVector3f& point) -{ - zeus::CVector3f rayToSphere = sphere.position - pos; - float magSq = rayToSphere.magSquared(); - float dirDot = rayToSphere.dot(dir); - float radSq = sphere.radius * sphere.radius; - if (dirDot < 0.f && magSq > radSq) - return false; - float intersectSq = radSq - (magSq - dirDot * dirDot); - if (intersectSq < 0.f) - return false; - T = magSq > radSq ? dirDot - std::sqrt(intersectSq) : dirDot + std::sqrt(intersectSq); - if (T < mag || mag == 0.f) - { - point = pos + T * dir; - return true; - } + float mag, float& T, zeus::CVector3f& point) { + zeus::CVector3f rayToSphere = sphere.position - pos; + float magSq = rayToSphere.magSquared(); + float dirDot = rayToSphere.dot(dir); + float radSq = sphere.radius * sphere.radius; + if (dirDot < 0.f && magSq > radSq) return false; + float intersectSq = radSq - (magSq - dirDot * dirDot); + if (intersectSq < 0.f) + return false; + T = magSq > radSq ? dirDot - std::sqrt(intersectSq) : dirDot + std::sqrt(intersectSq); + if (T < mag || mag == 0.f) { + point = pos + T * dir; + return true; + } + return false; } bool RayTriangleIntersection_Double(const zeus::CVector3f& point, const zeus::CVector3f& dir, - const zeus::CVector3f* verts, double& d) -{ - zeus::CVector3d v0tov1 = verts[1] - verts[0]; - zeus::CVector3d v0tov2 = verts[2] - verts[0]; - zeus::CVector3d cross0 = zeus::CVector3d(dir).cross(v0tov2); - double dot0 = v0tov1.dot(cross0); - if (dot0 < DBL_EPSILON) - return false; - zeus::CVector3d v0toPoint = point - verts[0]; - double dot1 = v0toPoint.dot(cross0); - if (dot1 < 0.0 || dot1 > dot0) - return false; - zeus::CVector3d cross1 = v0toPoint.cross(v0tov1); - double dot2 = cross1.dot(dir); - if (dot2 < 0.0 || dot1 + dot2 > dot0) - return false; - double final = 1.0 / dot0 * cross1.dot(v0tov2); - if (final < 0.0 || final >= d) - return false; - d = final; + const zeus::CVector3f* verts, double& d) { + zeus::CVector3d v0tov1 = verts[1] - verts[0]; + zeus::CVector3d v0tov2 = verts[2] - verts[0]; + zeus::CVector3d cross0 = zeus::CVector3d(dir).cross(v0tov2); + double dot0 = v0tov1.dot(cross0); + if (dot0 < DBL_EPSILON) + return false; + zeus::CVector3d v0toPoint = point - verts[0]; + double dot1 = v0toPoint.dot(cross0); + if (dot1 < 0.0 || dot1 > dot0) + return false; + zeus::CVector3d cross1 = v0toPoint.cross(v0tov1); + double dot2 = cross1.dot(dir); + if (dot2 < 0.0 || dot1 + dot2 > dot0) + return false; + double final = 1.0 / dot0 * cross1.dot(v0tov2); + if (final < 0.0 || final >= d) + return false; + d = final; + return true; +} + +bool RayTriangleIntersection(const zeus::CVector3f& point, const zeus::CVector3f& dir, const zeus::CVector3f* verts, + float& d) { + zeus::CVector3f v0tov1 = verts[1] - verts[0]; + zeus::CVector3f v0tov2 = verts[2] - verts[0]; + zeus::CVector3f cross0 = dir.cross(v0tov2); + float dot0 = v0tov1.dot(cross0); + if (dot0 < DBL_EPSILON) + return false; + zeus::CVector3f v0toPoint = point - verts[0]; + float dot1 = v0toPoint.dot(cross0); + if (dot1 < 0.f || dot1 > dot0) + return false; + zeus::CVector3f cross1 = v0toPoint.cross(v0tov1); + float dot2 = cross1.dot(dir); + if (dot2 < 0.f || dot1 + dot2 > dot0) + return false; + float final = 1.f / dot0 * cross1.dot(v0tov2); + if (final < 0.f || final >= d) + return false; + d = final; + return true; +} + +void FilterOutBackfaces(const zeus::CVector3f& vec, const CCollisionInfoList& in, CCollisionInfoList& out) { + if (vec.canBeNormalized()) { + zeus::CVector3f norm = vec.normalized(); + for (const CCollisionInfo& info : in) { + if (info.GetNormalLeft().dot(norm) < 0.001f) + out.Add(info, false); + } + } else { + out = in; + } +} + +void FilterByClosestNormal(const zeus::CVector3f& norm, const CCollisionInfoList& in, CCollisionInfoList& out) { + float maxDot = -1.1f; + int idx = -1; + int i = 0; + for (const CCollisionInfo& info : in) { + float dot = info.GetNormalLeft().dot(norm); + if (dot > maxDot) { + maxDot = dot; + idx = i; + } + ++i; + } + + if (idx != -1) + out.Add(in.GetItem(i), false); +} + +static const zeus::CVector3f AABBNormalTable[] = {{-1.f, 0.f, 0.f}, {1.f, 0.f, 0.f}, {0.f, -1.f, 0.f}, + {0.f, 1.f, 0.f}, {0.f, 0.f, -1.f}, {0.f, 0.f, 1.f}}; + +bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const CMaterialList& list0, const zeus::CAABox& aabb1, + const CMaterialList& list1, CCollisionInfoList& infoList) { + zeus::CVector3f maxOfMin(std::max(aabb0.min.x(), aabb1.min.x()), std::max(aabb0.min.y(), aabb1.min.y()), + std::max(aabb0.min.z(), aabb1.min.z())); + zeus::CVector3f minOfMax(std::min(aabb0.max.x(), aabb1.max.x()), std::min(aabb0.max.y(), aabb1.max.y()), + std::min(aabb0.max.z(), aabb1.max.z())); + + if (maxOfMin.x() >= minOfMax.x() || maxOfMin.y() >= minOfMax.y() || maxOfMin.z() >= minOfMax.z()) + return false; + + zeus::CAABox boolAABB(maxOfMin, minOfMax); + + int ineqFlags[] = { + (aabb0.min.x() <= aabb1.min.x() ? 1 << 0 : 0) | (aabb0.min.x() <= aabb1.max.x() ? 1 << 1 : 0) | + (aabb0.max.x() <= aabb1.min.x() ? 1 << 2 : 0) | (aabb0.max.x() <= aabb1.max.x() ? 1 << 3 : 0), + (aabb0.min.y() <= aabb1.min.y() ? 1 << 0 : 0) | (aabb0.min.y() <= aabb1.max.y() ? 1 << 1 : 0) | + (aabb0.max.y() <= aabb1.min.y() ? 1 << 2 : 0) | (aabb0.max.y() <= aabb1.max.y() ? 1 << 3 : 0), + (aabb0.min.z() <= aabb1.min.z() ? 1 << 0 : 0) | (aabb0.min.z() <= aabb1.max.z() ? 1 << 1 : 0) | + (aabb0.max.z() <= aabb1.min.z() ? 1 << 2 : 0) | (aabb0.max.z() <= aabb1.max.z() ? 1 << 3 : 0), + }; + + for (int i = 0; i < 3; ++i) { + switch (ineqFlags[i]) { + case 0x2: // aabb0.min <= aabb1.max + { + CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[i * 2 + 1], -AABBNormalTable[i * 2 + 1]); + infoList.Add(info, false); + break; + } + case 0xB: // aabb0.min <= aabb1.min && aabb0.max <= aabb1.min && aabb0.max <= aabb1.max + { + CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[i * 2], -AABBNormalTable[i * 2]); + infoList.Add(info, false); + break; + } + default: + break; + } + } + + if (infoList.GetCount()) return true; + + { + CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[4], -AABBNormalTable[4]); + infoList.Add(info, false); + } + + { + CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[5], -AABBNormalTable[5]); + infoList.Add(info, false); + } + + return true; } -bool RayTriangleIntersection(const zeus::CVector3f& point, const zeus::CVector3f& dir, - const zeus::CVector3f* verts, float& d) -{ - zeus::CVector3f v0tov1 = verts[1] - verts[0]; - zeus::CVector3f v0tov2 = verts[2] - verts[0]; - zeus::CVector3f cross0 = dir.cross(v0tov2); - float dot0 = v0tov1.dot(cross0); - if (dot0 < DBL_EPSILON) - return false; - zeus::CVector3f v0toPoint = point - verts[0]; - float dot1 = v0toPoint.dot(cross0); - if (dot1 < 0.f || dot1 > dot0) - return false; - zeus::CVector3f cross1 = v0toPoint.cross(v0tov1); - float dot2 = cross1.dot(dir); - if (dot2 < 0.f || dot1 + dot2 > dot0) - return false; - float final = 1.f / dot0 * cross1.dot(v0tov2); - if (final < 0.f || final >= d) - return false; - d = final; - return true; -} - -void FilterOutBackfaces(const zeus::CVector3f& vec, const CCollisionInfoList& in, CCollisionInfoList& out) -{ - if (vec.canBeNormalized()) - { - zeus::CVector3f norm = vec.normalized(); - for (const CCollisionInfo& info : in) - { - if (info.GetNormalLeft().dot(norm) < 0.001f) - out.Add(info, false); - } - } - else - { - out = in; - } -} - -void FilterByClosestNormal(const zeus::CVector3f& norm, const CCollisionInfoList& in, CCollisionInfoList& out) -{ - float maxDot = -1.1f; - int idx = -1; - int i=0; - for (const CCollisionInfo& info : in) - { - float dot = info.GetNormalLeft().dot(norm); - if (dot > maxDot) - { - maxDot = dot; - idx = i; - } - ++i; - } - - if (idx != -1) - out.Add(in.GetItem(i), false); -} - -static const zeus::CVector3f AABBNormalTable[] = -{ - {-1.f, 0.f, 0.f}, - {1.f, 0.f, 0.f}, - {0.f, -1.f, 0.f}, - {0.f, 1.f, 0.f}, - {0.f, 0.f, -1.f}, - {0.f, 0.f, 1.f} -}; - -bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const CMaterialList& list0, - const zeus::CAABox& aabb1, const CMaterialList& list1, - CCollisionInfoList& infoList) -{ - zeus::CVector3f maxOfMin(std::max(aabb0.min.x(), aabb1.min.x()), - std::max(aabb0.min.y(), aabb1.min.y()), - std::max(aabb0.min.z(), aabb1.min.z())); - zeus::CVector3f minOfMax(std::min(aabb0.max.x(), aabb1.max.x()), - std::min(aabb0.max.y(), aabb1.max.y()), - std::min(aabb0.max.z(), aabb1.max.z())); - - if (maxOfMin.x() >= minOfMax.x() || maxOfMin.y() >= minOfMax.y() || maxOfMin.z() >= minOfMax.z()) - return false; - - zeus::CAABox boolAABB(maxOfMin, minOfMax); - - int ineqFlags[] = - { - (aabb0.min.x() <= aabb1.min.x() ? 1 << 0 : 0) | - (aabb0.min.x() <= aabb1.max.x() ? 1 << 1 : 0) | - (aabb0.max.x() <= aabb1.min.x() ? 1 << 2 : 0) | - (aabb0.max.x() <= aabb1.max.x() ? 1 << 3 : 0), - (aabb0.min.y() <= aabb1.min.y() ? 1 << 0 : 0) | - (aabb0.min.y() <= aabb1.max.y() ? 1 << 1 : 0) | - (aabb0.max.y() <= aabb1.min.y() ? 1 << 2 : 0) | - (aabb0.max.y() <= aabb1.max.y() ? 1 << 3 : 0), - (aabb0.min.z() <= aabb1.min.z() ? 1 << 0 : 0) | - (aabb0.min.z() <= aabb1.max.z() ? 1 << 1 : 0) | - (aabb0.max.z() <= aabb1.min.z() ? 1 << 2 : 0) | - (aabb0.max.z() <= aabb1.max.z() ? 1 << 3 : 0), - }; - - for (int i=0 ; i<3 ; ++i) - { - switch (ineqFlags[i]) - { - case 0x2: // aabb0.min <= aabb1.max - { - CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[i*2+1], -AABBNormalTable[i*2+1]); - infoList.Add(info, false); - break; - } - case 0xB: // aabb0.min <= aabb1.min && aabb0.max <= aabb1.min && aabb0.max <= aabb1.max - { - CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[i*2], -AABBNormalTable[i*2]); - infoList.Add(info, false); - break; - } - default: break; - } - } - - if (infoList.GetCount()) - return true; - - { - CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[4], -AABBNormalTable[4]); - infoList.Add(info, false); - } - - { - CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[5], -AABBNormalTable[5]); - infoList.Add(info, false); - } - - return true; -} - -bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1) -{ - return aabb0.intersects(aabb1); -} +bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1) { return aabb0.intersects(aabb1); } /* http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/tribox2.txt */ /********************************************************/ @@ -473,789 +387,705 @@ bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1 /* Thanks to David Hunt for finding a ">="-bug! */ /********************************************************/ -#define FINDMINMAX(x0,x1,x2,min,max) \ - min = max = x0; \ - if (x1max) max = x1;\ - if (x2max) max = x2; +#define FINDMINMAX(x0, x1, x2, min, max) \ + min = max = x0; \ + if (x1 < min) \ + min = x1; \ + if (x1 > max) \ + max = x1; \ + if (x2 < min) \ + min = x2; \ + if (x2 > max) \ + max = x2; -static bool planeBoxOverlap(const zeus::CVector3f& normal, float d, const zeus::CVector3f& maxbox) -{ - zeus::CVector3f vmin, vmax; - for (int q=0 ; q<=2 ; q++) - { - if (normal[q] > 0.0f) - { - vmin[q] = -maxbox[q]; - vmax[q] = maxbox[q]; - } - else - { - vmin[q] = maxbox[q]; - vmax[q] = -maxbox[q]; - } +static bool planeBoxOverlap(const zeus::CVector3f& normal, float d, const zeus::CVector3f& maxbox) { + zeus::CVector3f vmin, vmax; + for (int q = 0; q <= 2; q++) { + if (normal[q] > 0.0f) { + vmin[q] = -maxbox[q]; + vmax[q] = maxbox[q]; + } else { + vmin[q] = maxbox[q]; + vmax[q] = -maxbox[q]; } - if (normal.dot(vmin) + d > 0.0f) return false; - if (normal.dot(vmax) + d >= 0.0f) return true; - + } + if (normal.dot(vmin) + d > 0.0f) return false; + if (normal.dot(vmax) + d >= 0.0f) + return true; + + return false; } - /*======================== X-tests ========================*/ -#define AXISTEST_X01(a, b, fa, fb) \ - p0 = a*v0.y() - b*v0.z(); \ - p2 = a*v2.y() - b*v2.z(); \ - if(p0rad || max<-rad) return false; +#define AXISTEST_X01(a, b, fa, fb) \ + p0 = a * v0.y() - b * v0.z(); \ + p2 = a * v2.y() - b * v2.z(); \ + if (p0 < p2) { \ + min = p0; \ + max = p2; \ + } else { \ + min = p2; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.y() + fb * boxhalfsize.z(); \ + if (min > rad || max < -rad) \ + return false; -#define AXISTEST_X2(a, b, fa, fb) \ - p0 = a*v0.y() - b*v0.z(); \ - p1 = a*v1.y() - b*v1.z(); \ - if(p0rad || max<-rad) return false; +#define AXISTEST_X2(a, b, fa, fb) \ + p0 = a * v0.y() - b * v0.z(); \ + p1 = a * v1.y() - b * v1.z(); \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.y() + fb * boxhalfsize.z(); \ + if (min > rad || max < -rad) \ + return false; /*======================== Y-tests ========================*/ -#define AXISTEST_Y02(a, b, fa, fb) \ - p0 = -a*v0.x() + b*v0.z(); \ - p2 = -a*v2.x() + b*v2.z(); \ - if(p0rad || max<-rad) return false; +#define AXISTEST_Y02(a, b, fa, fb) \ + p0 = -a * v0.x() + b * v0.z(); \ + p2 = -a * v2.x() + b * v2.z(); \ + if (p0 < p2) { \ + min = p0; \ + max = p2; \ + } else { \ + min = p2; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x() + fb * boxhalfsize.z(); \ + if (min > rad || max < -rad) \ + return false; -#define AXISTEST_Y1(a, b, fa, fb) \ - p0 = -a*v0.x() + b*v0.z(); \ - p1 = -a*v1.x() + b*v1.z(); \ - if(p0rad || max<-rad) return false; +#define AXISTEST_Y1(a, b, fa, fb) \ + p0 = -a * v0.x() + b * v0.z(); \ + p1 = -a * v1.x() + b * v1.z(); \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x() + fb * boxhalfsize.z(); \ + if (min > rad || max < -rad) \ + return false; /*======================== Z-tests ========================*/ -#define AXISTEST_Z12(a, b, fa, fb) \ - p1 = a*v1.x() - b*v1.y(); \ - p2 = a*v2.x() - b*v2.y(); \ - if(p2rad || max<-rad) return false; +#define AXISTEST_Z12(a, b, fa, fb) \ + p1 = a * v1.x() - b * v1.y(); \ + p2 = a * v2.x() - b * v2.y(); \ + if (p2 < p1) { \ + min = p2; \ + max = p1; \ + } else { \ + min = p1; \ + max = p2; \ + } \ + rad = fa * boxhalfsize.x() + fb * boxhalfsize.y(); \ + if (min > rad || max < -rad) \ + return false; -#define AXISTEST_Z0(a, b, fa, fb) \ - p0 = a*v0.x() - b*v0.y(); \ - p1 = a*v1.x() - b*v1.y(); \ - if(p0rad || max<-rad) return false; +#define AXISTEST_Z0(a, b, fa, fb) \ + p0 = a * v0.x() - b * v0.y(); \ + p1 = a * v1.x() - b * v1.y(); \ + if (p0 < p1) { \ + min = p0; \ + max = p1; \ + } else { \ + min = p1; \ + max = p0; \ + } \ + rad = fa * boxhalfsize.x() + fb * boxhalfsize.y(); \ + if (min > rad || max < -rad) \ + return false; bool TriBoxOverlap(const zeus::CVector3f& boxcenter, const zeus::CVector3f& boxhalfsize, - const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, - const zeus::CVector3f& trivert2) -{ + const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, const zeus::CVector3f& trivert2) { - /* use separating axis theorem to test overlap between triangle and box */ - /* need to test for overlap in these directions: */ - /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ - /* we do not even need to test these) */ - /* 2) normal of the triangle */ - /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ - /* this gives 3x3=9 more tests */ - zeus::CVector3f v0, v1, v2; - float min, max, d, p0, p1, p2, rad, fex, fey, fez; - zeus::CVector3f normal, e0, e1, e2; + /* use separating axis theorem to test overlap between triangle and box */ + /* need to test for overlap in these directions: */ + /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ + /* we do not even need to test these) */ + /* 2) normal of the triangle */ + /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ + /* this gives 3x3=9 more tests */ + zeus::CVector3f v0, v1, v2; + float min, max, d, p0, p1, p2, rad, fex, fey, fez; + zeus::CVector3f normal, e0, e1, e2; - /* This is the fastest branch on Sun */ - /* move everything so that the boxcenter is in (0,0,0) */ - v0 = trivert0 - boxcenter; - v1 = trivert1 - boxcenter; - v2 = trivert2 - boxcenter; + /* This is the fastest branch on Sun */ + /* move everything so that the boxcenter is in (0,0,0) */ + v0 = trivert0 - boxcenter; + v1 = trivert1 - boxcenter; + v2 = trivert2 - boxcenter; - /* compute triangle edges */ - e0 = v1 - v0; /* tri edge 0 */ - e1 = v2 - v1; /* tri edge 1 */ - e2 = v0 - v2; /* tri edge 2 */ + /* compute triangle edges */ + e0 = v1 - v0; /* tri edge 0 */ + e1 = v2 - v1; /* tri edge 1 */ + e2 = v0 - v2; /* tri edge 2 */ - /* Bullet 3: */ - /* test the 9 tests first (this was faster) */ - fex = std::fabs(e0.x()); - fey = std::fabs(e0.y()); - fez = std::fabs(e0.z()); - AXISTEST_X01(e0.z(), e0.y(), fez, fey); - AXISTEST_Y02(e0.z(), e0.x(), fez, fex); - AXISTEST_Z12(e0.y(), e0.x(), fey, fex); + /* Bullet 3: */ + /* test the 9 tests first (this was faster) */ + fex = std::fabs(e0.x()); + fey = std::fabs(e0.y()); + fez = std::fabs(e0.z()); + AXISTEST_X01(e0.z(), e0.y(), fez, fey); + AXISTEST_Y02(e0.z(), e0.x(), fez, fex); + AXISTEST_Z12(e0.y(), e0.x(), fey, fex); - fex = std::fabs(e1.x()); - fey = std::fabs(e1.y()); - fez = std::fabs(e1.z()); - AXISTEST_X01(e1.z(), e1.y(), fez, fey); - AXISTEST_Y02(e1.z(), e1.x(), fez, fex); - AXISTEST_Z0(e1.y(), e1.x(), fey, fex); + fex = std::fabs(e1.x()); + fey = std::fabs(e1.y()); + fez = std::fabs(e1.z()); + AXISTEST_X01(e1.z(), e1.y(), fez, fey); + AXISTEST_Y02(e1.z(), e1.x(), fez, fex); + AXISTEST_Z0(e1.y(), e1.x(), fey, fex); - fex = std::fabs(e2.x()); - fey = std::fabs(e2.y()); - fez = std::fabs(e2.z()); - AXISTEST_X2(e2.z(), e2.y(), fez, fey); - AXISTEST_Y1(e2.z(), e2.x(), fez, fex); - AXISTEST_Z12(e2.y(), e2.x(), fey, fex); + fex = std::fabs(e2.x()); + fey = std::fabs(e2.y()); + fez = std::fabs(e2.z()); + AXISTEST_X2(e2.z(), e2.y(), fez, fey); + AXISTEST_Y1(e2.z(), e2.x(), fez, fex); + AXISTEST_Z12(e2.y(), e2.x(), fey, fex); - /* Bullet 1: */ - /* first test overlap in the {x,y,z}-directions */ - /* find min, max of the triangle each direction, and test for overlap in */ - /* that direction -- this is equivalent to testing a minimal AABB around */ - /* the triangle against the AABB */ + /* Bullet 1: */ + /* first test overlap in the {x,y,z}-directions */ + /* find min, max of the triangle each direction, and test for overlap in */ + /* that direction -- this is equivalent to testing a minimal AABB around */ + /* the triangle against the AABB */ - /* test in X-direction */ - FINDMINMAX(v0.x(), v1.x(), v2.x(), min, max); - if (min>boxhalfsize.x() || max<-boxhalfsize.x()) return false; + /* test in X-direction */ + FINDMINMAX(v0.x(), v1.x(), v2.x(), min, max); + if (min > boxhalfsize.x() || max < -boxhalfsize.x()) + return false; - /* test in Y-direction */ - FINDMINMAX(v0.y(), v1.y(), v2.y(), min, max); - if (min>boxhalfsize.y() || max<-boxhalfsize.y()) return false; + /* test in Y-direction */ + FINDMINMAX(v0.y(), v1.y(), v2.y(), min, max); + if (min > boxhalfsize.y() || max < -boxhalfsize.y()) + return false; - /* test in Z-direction */ - FINDMINMAX(v0.z(), v1.z(), v2.z(), min, max); - if (min>boxhalfsize.z() || max<-boxhalfsize.z()) return false; + /* test in Z-direction */ + FINDMINMAX(v0.z(), v1.z(), v2.z(), min, max); + if (min > boxhalfsize.z() || max < -boxhalfsize.z()) + return false; - /* Bullet 2: */ - /* test if the box intersects the plane of the triangle */ - /* compute plane equation of triangle: normal*x+d=0 */ - normal = e0.cross(e1); - d = -normal.dot(v0); /* plane eq: normal.x+d=0 */ - if (!planeBoxOverlap(normal, d, boxhalfsize)) return false; + /* Bullet 2: */ + /* test if the box intersects the plane of the triangle */ + /* compute plane equation of triangle: normal*x+d=0 */ + normal = e0.cross(e1); + d = -normal.dot(v0); /* plane eq: normal.x+d=0 */ + if (!planeBoxOverlap(normal, d, boxhalfsize)) + return false; - return true; /* box and triangle overlaps */ + return true; /* box and triangle overlaps */ } -double TriPointSqrDist(const zeus::CVector3f& point, - const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, - const zeus::CVector3f& trivert2, float* baryX, float* baryY) -{ - zeus::CVector3d A = trivert0 - point; - zeus::CVector3d B = trivert1 - trivert0; - zeus::CVector3d C = trivert2 - trivert0; +double TriPointSqrDist(const zeus::CVector3f& point, const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, + const zeus::CVector3f& trivert2, float* baryX, float* baryY) { + zeus::CVector3d A = trivert0 - point; + zeus::CVector3d B = trivert1 - trivert0; + zeus::CVector3d C = trivert2 - trivert0; - double bMag = B.magSquared(); - double cMag = C.magSquared(); - double bDotC = B.dot(C); - double aDotB = A.dot(B); - double aDotC = A.dot(C); - double ret = A.magSquared(); + double bMag = B.magSquared(); + double cMag = C.magSquared(); + double bDotC = B.dot(C); + double aDotB = A.dot(B); + double aDotC = A.dot(C); + double ret = A.magSquared(); - double rej = std::fabs(bMag * cMag - bDotC * bDotC); - double retB = bDotC * aDotC - cMag * aDotB; - double retA = bDotC * aDotB - bMag * aDotC; + double rej = std::fabs(bMag * cMag - bDotC * bDotC); + double retB = bDotC * aDotC - cMag * aDotB; + double retA = bDotC * aDotB - bMag * aDotC; - if (retB + retA <= rej) - { - if (retB < 0.0) - { - if (retA < 0.0) - { - if (aDotB < 0.0) - { - retA = 0.0; - if (-aDotB >= bMag) - { - retB = 1.0; - ret += 2.0 * aDotB + bMag; - } - else - { - retB = -aDotB / bMag; - ret += aDotB * retB; - } - } - else - { - retB = 0.0; - if (aDotC >= 0.0) - { - retA = 0.0; - } - else if (-aDotC >= cMag) - { - retA = 1.0; - ret += 2.0 * aDotC + cMag; - } - else - { - retA = -aDotC / cMag; - ret += aDotC * retA; - } - } - } - else - { - retB = 0.0; - if (aDotC >= 0.0) - { - retA = 0.0; - } - else if (-aDotC >= cMag) - { - retA = 1.0; - ret += 2.0 * aDotC + cMag; - } - else - { - retA = -aDotC / cMag; - ret += aDotC * retA; - } - } - } - else if (retA < 0.0) - { + if (retB + retA <= rej) { + if (retB < 0.0) { + if (retA < 0.0) { + if (aDotB < 0.0) { + retA = 0.0; + if (-aDotB >= bMag) { + retB = 1.0; + ret += 2.0 * aDotB + bMag; + } else { + retB = -aDotB / bMag; + ret += aDotB * retB; + } + } else { + retB = 0.0; + if (aDotC >= 0.0) { retA = 0.0; - if (aDotB >= 0.0) - { - retB = 0.0; - } - else if (-aDotB >= bMag) - { - retB = 1.0; - ret += 2.0 * aDotB + bMag; - } - else - { - retB = -aDotB / bMag; - ret += aDotB * retB; - } + } else if (-aDotC >= cMag) { + retA = 1.0; + ret += 2.0 * aDotC + cMag; + } else { + retA = -aDotC / cMag; + ret += aDotC * retA; + } } - else - { - float f3 = 1.0 / rej; - retA *= f3; - retB *= f3; - ret += retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) + - retA * (2.0 * aDotC + (bDotC * retB + cMag * retA)); + } else { + retB = 0.0; + if (aDotC >= 0.0) { + retA = 0.0; + } else if (-aDotC >= cMag) { + retA = 1.0; + ret += 2.0 * aDotC + cMag; + } else { + retA = -aDotC / cMag; + ret += aDotC * retA; } + } + } else if (retA < 0.0) { + retA = 0.0; + if (aDotB >= 0.0) { + retB = 0.0; + } else if (-aDotB >= bMag) { + retB = 1.0; + ret += 2.0 * aDotB + bMag; + } else { + retB = -aDotB / bMag; + ret += aDotB * retB; + } + } else { + float f3 = 1.0 / rej; + retA *= f3; + retB *= f3; + ret += retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) + retA * (2.0 * aDotC + (bDotC * retB + cMag * retA)); } - else if (retB < 0.0) - { - retB = bDotC + aDotB; - retA = cMag + aDotC; - if (retA > retB) - { - retA -= retB; - retB = bMag - 2.0 * bDotC; - retB += cMag; - if (retA >= retB) - { - retB = 1.0; - retA = 0.0; - ret += 2.0 * aDotB + bMag; - } - else - { - retB = retA / retB; - retA = 1.0 - retB; - ret += retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) + - retA * (2.0 * aDotC + (bDotC * retB + cMag * retA)); - } - } - else - { - retB = 0.0; - if (retA <= 0.0) - { - retA = 1.0; - ret += 2.0 * aDotC + cMag; - } - else if (aDotC >= 0.0) - { - retA = 0.0; - } - else - { - retA = -aDotC / cMag; - ret += aDotC * retA; - } - } + } else if (retB < 0.0) { + retB = bDotC + aDotB; + retA = cMag + aDotC; + if (retA > retB) { + retA -= retB; + retB = bMag - 2.0 * bDotC; + retB += cMag; + if (retA >= retB) { + retB = 1.0; + retA = 0.0; + ret += 2.0 * aDotB + bMag; + } else { + retB = retA / retB; + retA = 1.0 - retB; + ret += + retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) + retA * (2.0 * aDotC + (bDotC * retB + cMag * retA)); + } + } else { + retB = 0.0; + if (retA <= 0.0) { + retA = 1.0; + ret += 2.0 * aDotC + cMag; + } else if (aDotC >= 0.0) { + retA = 0.0; + } else { + retA = -aDotC / cMag; + ret += aDotC * retA; + } } - else - { - if (retA < 0.0) - { - retB = bDotC + aDotC; - retA = bMag + aDotB; - if (retA > retB) - { - retA -= retB; - retB = bMag - 2.0 * bDotC; - retB += cMag; - if (retA >= retB) - { - retA = 1.0; - retB = 0.0; - ret += 2.0 * aDotC + cMag; - } - else - { - retA /= retB; - retB = 1.0 - retA; - ret += retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) + - retA * (2.0 * aDotC + (bDotC * retB + cMag * retA)); - } - } - else - { - retA = 0.0; - if (retA <= 0.0) - { - retB = 1.0; - ret += 2.0 * aDotB + bMag; - } - else if (aDotB >= 0.0) - { - retB = 0.0; - } - else - { - retB = -aDotB / bMag; - ret += aDotB * retB; - } - } + } else { + if (retA < 0.0) { + retB = bDotC + aDotC; + retA = bMag + aDotB; + if (retA > retB) { + retA -= retB; + retB = bMag - 2.0 * bDotC; + retB += cMag; + if (retA >= retB) { + retA = 1.0; + retB = 0.0; + ret += 2.0 * aDotC + cMag; + } else { + retA /= retB; + retB = 1.0 - retA; + ret += + retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) + retA * (2.0 * aDotC + (bDotC * retB + cMag * retA)); } - else - { - retB = cMag + aDotC; - retB -= bDotC; - retA = retB - aDotB; - if (retA <= 0.0) - { - retB = 0.0; - retA = 1.0; - ret += 2.0 * aDotC + cMag; - } - else - { - retB = bMag - 2.0 * bDotC; - retB += cMag; - if (retA >= retB) - { - retB = 1.0; - retA = 0.0; - ret += 2.0 * aDotB + bMag; - } - else - { - retB = retA / retB; - retA = 1.0 - retB; - ret += retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) + - retA * (2.0 * aDotC + (bDotC * retB + cMag * retA)); - } - } + } else { + retA = 0.0; + if (retA <= 0.0) { + retB = 1.0; + ret += 2.0 * aDotB + bMag; + } else if (aDotB >= 0.0) { + retB = 0.0; + } else { + retB = -aDotB / bMag; + ret += aDotB * retB; } + } + } else { + retB = cMag + aDotC; + retB -= bDotC; + retA = retB - aDotB; + if (retA <= 0.0) { + retB = 0.0; + retA = 1.0; + ret += 2.0 * aDotC + cMag; + } else { + retB = bMag - 2.0 * bDotC; + retB += cMag; + if (retA >= retB) { + retB = 1.0; + retA = 0.0; + ret += 2.0 * aDotB + bMag; + } else { + retB = retA / retB; + retA = 1.0 - retB; + ret += + retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) + retA * (2.0 * aDotC + (bDotC * retB + cMag * retA)); + } + } } + } - if (baryX) - *baryX = retA; - if (baryY) - *baryY = retB; + if (baryX) + *baryX = retA; + if (baryY) + *baryY = retB; - return ret; + return ret; } -bool TriSphereOverlap(const zeus::CSphere& sphere, - const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, - const zeus::CVector3f& trivert2) -{ - return TriPointSqrDist(sphere.position, trivert0, trivert1, trivert2, nullptr, nullptr) <= - sphere.radius * sphere.radius; +bool TriSphereOverlap(const zeus::CSphere& sphere, const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, + const zeus::CVector3f& trivert2) { + return TriPointSqrDist(sphere.position, trivert0, trivert1, trivert2, nullptr, nullptr) <= + sphere.radius * sphere.radius; } -bool TriSphereIntersection(const zeus::CSphere& sphere, - const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, - const zeus::CVector3f& trivert2, zeus::CVector3f& point, zeus::CVector3f& normal) -{ - float baryX, baryY; - if (TriPointSqrDist(sphere.position, trivert0, trivert1, trivert2, &baryX, &baryY) > - sphere.radius * sphere.radius) +bool TriSphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& trivert0, + const zeus::CVector3f& trivert1, const zeus::CVector3f& trivert2, zeus::CVector3f& point, + zeus::CVector3f& normal) { + float baryX, baryY; + if (TriPointSqrDist(sphere.position, trivert0, trivert1, trivert2, &baryX, &baryY) > sphere.radius * sphere.radius) + return false; + + zeus::CVector3f barys(baryX, baryY, 1.f - (baryX + baryY)); + point = zeus::baryToWorld(trivert2, trivert1, trivert0, barys); + + if (baryX == 0.f || baryX == 1.f || baryY == 0.f || baryY == 1.f || barys.z() == 0.f || barys.z() == 1.f) + normal = -sphere.getSurfaceNormal(point); + else + normal = (trivert1 - trivert0).cross(trivert2 - trivert0).normalized(); + + return true; +} + +bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CVector3f& point, const zeus::CVector3f& dir, float& tMin, + float& tMax, int& axis, bool& sign) { + tMin = -999999.f; + tMax = 999999.f; + + for (int i = 0; i < 3; ++i) { + if (dir[i] == 0.f) + if (point[i] < aabb.min[i] || point[i] > aabb.max[i]) return false; - zeus::CVector3f barys(baryX, baryY, 1.f - (baryX + baryY)); - point = zeus::baryToWorld(trivert2, trivert1, trivert0, barys); - - if (baryX == 0.f || baryX == 1.f || baryY == 0.f || baryY == 1.f || - barys.z() == 0.f || barys.z() == 1.f) - normal = -sphere.getSurfaceNormal(point); - else - normal = (trivert1 - trivert0).cross(trivert2 - trivert0).normalized(); - - return true; -} - -bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CVector3f& point, const zeus::CVector3f& dir, - float& tMin, float& tMax, int& axis, bool& sign) -{ - tMin = -999999.f; - tMax = 999999.f; - - for (int i=0 ; i<3 ; ++i) - { - if (dir[i] == 0.f) - if (point[i] < aabb.min[i] || point[i] > aabb.max[i]) - return false; - - float dirRecip = 1.f / dir[i]; - float tmpMin, tmpMax; - if (dir[i] < 0.f) - { - tmpMin = (aabb.max[i] - point[i]) * dirRecip; - tmpMax = (aabb.min[i] - point[i]) * dirRecip; - } - else - { - tmpMin = (aabb.min[i] - point[i]) * dirRecip; - tmpMax = (aabb.max[i] - point[i]) * dirRecip; - } - - if (tmpMin > tMin) - { - sign = dir[i] < 0.f; - axis = i; - tMin = tmpMin; - } - - if (tmpMax < tMax) - tMax = tmpMax; + float dirRecip = 1.f / dir[i]; + float tmpMin, tmpMax; + if (dir[i] < 0.f) { + tmpMin = (aabb.max[i] - point[i]) * dirRecip; + tmpMax = (aabb.min[i] - point[i]) * dirRecip; + } else { + tmpMin = (aabb.min[i] - point[i]) * dirRecip; + tmpMax = (aabb.max[i] - point[i]) * dirRecip; } - return tMin <= tMax; + if (tmpMin > tMin) { + sign = dir[i] < 0.f; + axis = i; + tMin = tmpMin; + } + + if (tmpMax < tMax) + tMax = tmpMax; + } + + return tMin <= tMax; } bool LineCircleIntersection2d(const zeus::CVector3f& point, const zeus::CVector3f& dir, const zeus::CSphere& sphere, - int axis1, int axis2, float& d) -{ - zeus::CVector3f delta = sphere.position - point; - zeus::CVector2f deltaVec(delta[axis1], delta[axis2]); - zeus::CVector2f dirVec(dir[axis1], dir[axis2]); - - float dirVecMag = dirVec.magnitude(); - if (dirVecMag < FLT_EPSILON) - return false; - - float deltaVecDot = deltaVec.dot(dirVec / dirVecMag); - float deltaVecMagSq = deltaVec.magSquared(); - - float sphereRadSq = sphere.radius * sphere.radius; - if (deltaVecDot < 0.f && deltaVecMagSq > sphereRadSq) - return false; - - float tSq = sphereRadSq - (deltaVecMagSq - deltaVecDot * deltaVecDot); - if (tSq < 0.f) - return false; - - float t = std::sqrt(tSq); - - d = (deltaVecMagSq > sphereRadSq) ? deltaVecDot - t : deltaVecDot + t; - d /= dirVecMag; - - return true; -} - -bool MovingSphereAABox(const zeus::CSphere& sphere, const zeus::CAABox& aabb, const zeus::CVector3f& dir, - double& dOut, zeus::CVector3f& point, zeus::CVector3f& normal) -{ - zeus::CAABox expAABB(aabb.min - sphere.radius, aabb.max + sphere.radius); - float tMin, tMax; - int axis; - bool sign; - if (!BoxLineTest(expAABB, sphere.position, dir, tMin, tMax, axis, sign)) - return false; - - point = sphere.position + tMin * dir; - - int nextAxis1 = (axis+1) % 3; // r0 - int nextAxis2 = (axis+2) % 3; // r5 - - bool inMin1 = point[nextAxis1] >= aabb.min[nextAxis1]; // r6 - bool inMax1 = point[nextAxis1] <= aabb.max[nextAxis1]; // r8 - bool inBounds1 = inMin1 && inMax1; // r9 - bool inMin2 = point[nextAxis2] >= aabb.min[nextAxis2]; // r7 - bool inMax2 = point[nextAxis2] <= aabb.max[nextAxis2]; // r4 - bool inBounds2 = inMin2 && inMax2; // r8 - - if (inBounds1 && inBounds2) - { - if (tMin < 0.f || tMin > dOut) - return false; - normal[axis] = sign ? 1.f : -1.f; - dOut = tMin; - point -= normal * sphere.radius; - return true; - } - else if (!inBounds1 && !inBounds2) - { - int pointFlags = (1 << axis) * sign | (1 << nextAxis1) * inMin1 | (1 << nextAxis2) * inMin2; - zeus::CVector3f aabbPoint = aabb.getPoint(pointFlags); - float d; - if (CollisionUtil::RaySphereIntersection(zeus::CSphere(aabbPoint, sphere.radius), - sphere.position, dir, dOut, d, point)) - { - int useAxis = -1; - for (int i=0 ; i<3 ; ++i) - { - if ((pointFlags & (1 << i)) ? aabbPoint[i] > point[i] : aabbPoint[i] < point[i]) - { - useAxis = i; - break; - } - } - - if (useAxis == -1) - { - normal = (point - aabbPoint).normalized(); - point -= sphere.radius * normal; - return true; - } - - int useAxisNext1 = (useAxis+1) % 3; - int useAxisNext2 = (useAxis+2) % 3; - - float d; - if (CollisionUtil::LineCircleIntersection2d(sphere.position, dir, zeus::CSphere(aabbPoint, sphere.radius), - useAxisNext1, useAxisNext2, d) && d > 0.f && d < dOut) - { - if (point[useAxis] > aabb.max[useAxis]) - { - int useAxisBit = 1 << useAxis; - if (pointFlags & useAxisBit) - return false; - - zeus::CVector3f aabbPoint1 = aabb.getPoint(pointFlags | useAxisBit); - if (CollisionUtil::RaySphereIntersection(zeus::CSphere(aabbPoint1, sphere.radius), - sphere.position, dir, dOut, d, point)) - { - dOut = d; - normal = (point - aabbPoint1).normalized(); - point -= normal * sphere.radius; - return true; - } - else - { - return false; - } - } - else if (point[useAxis] < aabb.min[useAxis]) - { - int useAxisBit = 1 << useAxis; - if (!(pointFlags & useAxisBit)) - return false; - - zeus::CVector3f aabbPoint1 = aabb.getPoint(pointFlags ^ useAxisBit); - if (CollisionUtil::RaySphereIntersection(zeus::CSphere(aabbPoint1, sphere.radius), - sphere.position, dir, dOut, d, point)) - { - dOut = d; - normal = (point - aabbPoint1).normalized(); - point -= normal * sphere.radius; - return true; - } - else - { - return false; - } - } - else - { - normal = point - aabbPoint; - normal.normalize(); - point -= normal * sphere.radius; - return true; - } - } - } - else - { - int reverseCount = 0; - float dMin = 1.0e10f; - int minAxis = 0; - for (int i=0 ; i<3 ; ++i) - { - if (std::fabs(dir[i]) > FLT_EPSILON) - { - bool pointMax = pointFlags & (1 << i); - if (pointMax != dir[i] > 0.f) - { - ++reverseCount; - float d = 1.f / dir[i] * ((pointMax ? aabb.max[i] : aabb.min[i]) - sphere.position[i]); - if (d < 0.f) - return false; - if (d < dMin) - { - dMin = d; - minAxis = i; - } - } - } - } - - if (reverseCount < 2) - return false; - - int useAxisNext1 = (minAxis+1) % 3; - int useAxisNext2 = (minAxis+2) % 3; - float d; - if (CollisionUtil::LineCircleIntersection2d(sphere.position, dir, zeus::CSphere(aabbPoint, sphere.radius), - useAxisNext1, useAxisNext2, d) && d > 0.f && d < dOut) - { - point = sphere.position + d * dir; - if (point[minAxis] > aabb.max[minAxis]) - return false; - if (point[minAxis] < aabb.min[minAxis]) - return false; - - dOut = d; - normal = point - aabbPoint; - normal.normalize(); - point -= sphere.radius * normal; - return true; - } - else - { - return false; - } - } - } - - bool useNextAxis1 = inBounds1 ? nextAxis2 : nextAxis1; - bool useNextAxis2 = inBounds1 ? nextAxis1 : nextAxis2; - - int pointFlags = ((1 << int(useNextAxis1)) * (inBounds1 ? inMin2 : inMin1)) | ((1 << axis) * sign); - zeus::CVector3f aabbPoint2 = aabb.getPoint(pointFlags); - float d; - if (LineCircleIntersection2d(sphere.position, dir, zeus::CSphere(aabbPoint2, sphere.radius), - axis, useNextAxis1, d) && d > 0.f && d < dOut) - { - point = sphere.position + d * dir; - if (point[useNextAxis2] > aabb.max[useNextAxis2]) - { - zeus::CVector3f aabbPoint3 = aabb.getPoint(pointFlags | (1 << int(useNextAxis2))); - if (point[useNextAxis2] < expAABB.max[useNextAxis2]) - { - if (RaySphereIntersection(zeus::CSphere(aabbPoint3, sphere.radius), - sphere.position, dir, dOut, d, point)) - { - dOut = d; - normal = (point - aabbPoint3).normalized(); - point -= sphere.radius * normal; - return true; - } - } - return false; - } - else if (point[useNextAxis2] < aabb.min[useNextAxis2]) - { - if (point[useNextAxis2] > expAABB.min[useNextAxis2]) - { - if (RaySphereIntersection(zeus::CSphere(aabbPoint2, sphere.radius), - sphere.position, dir, dOut, d, point)) - { - dOut = d; - normal = (point - aabbPoint2).normalized(); - point -= sphere.radius * normal; - return true; - } - } - return false; - } - else - { - dOut = d; - normal = point - aabbPoint2; - normal.normalize(); - point -= sphere.radius * normal; - return true; - } - } + int axis1, int axis2, float& d) { + zeus::CVector3f delta = sphere.position - point; + zeus::CVector2f deltaVec(delta[axis1], delta[axis2]); + zeus::CVector2f dirVec(dir[axis1], dir[axis2]); + float dirVecMag = dirVec.magnitude(); + if (dirVecMag < FLT_EPSILON) return false; + + float deltaVecDot = deltaVec.dot(dirVec / dirVecMag); + float deltaVecMagSq = deltaVec.magSquared(); + + float sphereRadSq = sphere.radius * sphere.radius; + if (deltaVecDot < 0.f && deltaVecMagSq > sphereRadSq) + return false; + + float tSq = sphereRadSq - (deltaVecMagSq - deltaVecDot * deltaVecDot); + if (tSq < 0.f) + return false; + + float t = std::sqrt(tSq); + + d = (deltaVecMagSq > sphereRadSq) ? deltaVecDot - t : deltaVecDot + t; + d /= dirVecMag; + + return true; } -bool AABox_AABox_Moving(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1, const zeus::CVector3f& dir, - double& d, zeus::CVector3f& point, zeus::CVector3f& normal) -{ - zeus::CVector3d vecMin(-FLT_MAX); - zeus::CVector3d vecMax(FLT_MAX); +bool MovingSphereAABox(const zeus::CSphere& sphere, const zeus::CAABox& aabb, const zeus::CVector3f& dir, double& dOut, + zeus::CVector3f& point, zeus::CVector3f& normal) { + zeus::CAABox expAABB(aabb.min - sphere.radius, aabb.max + sphere.radius); + float tMin, tMax; + int axis; + bool sign; + if (!BoxLineTest(expAABB, sphere.position, dir, tMin, tMax, axis, sign)) + return false; - for (int i=0 ; i<3 ; ++i) - { - if (std::fabs(dir[i]) < FLT_EPSILON) - { - if (aabb0.min[i] >= aabb1.min[i] && aabb0.min[i] <= aabb1.max[i]) - continue; - if (aabb0.max[i] >= aabb1.min[i] && aabb0.max[i] <= aabb1.max[i]) - continue; - if (aabb0.min[i] < aabb1.min[i] && aabb0.max[i] > aabb1.max[i]) - continue; - return false; - } - else - { - if (aabb0.max[i] < aabb1.min[i] && dir[i] > 0.f) - vecMin[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i]; - else if (aabb1.max[i] < aabb0.min[i] && dir[i] < 0.f) - vecMin[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i]; - else if (aabb1.max[i] > aabb0.min[i] && dir[i] < 0.f) - vecMin[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i]; - else if (aabb0.max[i] > aabb1.min[i] && dir[i] > 0.f) - vecMin[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i]; + point = sphere.position + tMin * dir; - if (aabb1.max[i] > aabb0.min[i] && dir[i] > 0.f) - vecMax[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i]; - else if (aabb0.max[i] > aabb1.min[i] && dir[i] < 0.f) - vecMax[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i]; - else if (aabb0.max[i] < aabb1.min[i] && dir[i] < 0.f) - vecMax[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i]; - else if (aabb1.max[i] < aabb0.min[i] && dir[i] > 0.f) - vecMax[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i]; - } - } + int nextAxis1 = (axis + 1) % 3; // r0 + int nextAxis2 = (axis + 2) % 3; // r5 - int maxAxis = 0; - if (vecMin[1] > vecMin[0]) - maxAxis = 1; - if (vecMin[2] > vecMin[maxAxis]) - maxAxis = 2; + bool inMin1 = point[nextAxis1] >= aabb.min[nextAxis1]; // r6 + bool inMax1 = point[nextAxis1] <= aabb.max[nextAxis1]; // r8 + bool inBounds1 = inMin1 && inMax1; // r9 + bool inMin2 = point[nextAxis2] >= aabb.min[nextAxis2]; // r7 + bool inMax2 = point[nextAxis2] <= aabb.max[nextAxis2]; // r4 + bool inBounds2 = inMin2 && inMax2; // r8 - double minMax = std::min(std::min(vecMax[2], vecMax[1]), vecMax[0]); - if (vecMin[maxAxis] > minMax) - return false; - d = vecMin[maxAxis]; - - normal = zeus::CVector3f::skZero; - normal[maxAxis] = dir[maxAxis] > 0.f ? -1.f : 1.f; - - for (int i=0 ; i<3 ; ++i) - point[i] = dir[i] > 0.f ? aabb0.max[i] : aabb0.min[i]; - - point += float(d) * dir; + if (inBounds1 && inBounds2) { + if (tMin < 0.f || tMin > dOut) + return false; + normal[axis] = sign ? 1.f : -1.f; + dOut = tMin; + point -= normal * sphere.radius; return true; + } else if (!inBounds1 && !inBounds2) { + int pointFlags = (1 << axis) * sign | (1 << nextAxis1) * inMin1 | (1 << nextAxis2) * inMin2; + zeus::CVector3f aabbPoint = aabb.getPoint(pointFlags); + float d; + if (CollisionUtil::RaySphereIntersection(zeus::CSphere(aabbPoint, sphere.radius), sphere.position, dir, dOut, d, + point)) { + int useAxis = -1; + for (int i = 0; i < 3; ++i) { + if ((pointFlags & (1 << i)) ? aabbPoint[i] > point[i] : aabbPoint[i] < point[i]) { + useAxis = i; + break; + } + } + + if (useAxis == -1) { + normal = (point - aabbPoint).normalized(); + point -= sphere.radius * normal; + return true; + } + + int useAxisNext1 = (useAxis + 1) % 3; + int useAxisNext2 = (useAxis + 2) % 3; + + float d; + if (CollisionUtil::LineCircleIntersection2d(sphere.position, dir, zeus::CSphere(aabbPoint, sphere.radius), + useAxisNext1, useAxisNext2, d) && + d > 0.f && d < dOut) { + if (point[useAxis] > aabb.max[useAxis]) { + int useAxisBit = 1 << useAxis; + if (pointFlags & useAxisBit) + return false; + + zeus::CVector3f aabbPoint1 = aabb.getPoint(pointFlags | useAxisBit); + if (CollisionUtil::RaySphereIntersection(zeus::CSphere(aabbPoint1, sphere.radius), sphere.position, dir, dOut, + d, point)) { + dOut = d; + normal = (point - aabbPoint1).normalized(); + point -= normal * sphere.radius; + return true; + } else { + return false; + } + } else if (point[useAxis] < aabb.min[useAxis]) { + int useAxisBit = 1 << useAxis; + if (!(pointFlags & useAxisBit)) + return false; + + zeus::CVector3f aabbPoint1 = aabb.getPoint(pointFlags ^ useAxisBit); + if (CollisionUtil::RaySphereIntersection(zeus::CSphere(aabbPoint1, sphere.radius), sphere.position, dir, dOut, + d, point)) { + dOut = d; + normal = (point - aabbPoint1).normalized(); + point -= normal * sphere.radius; + return true; + } else { + return false; + } + } else { + normal = point - aabbPoint; + normal.normalize(); + point -= normal * sphere.radius; + return true; + } + } + } else { + int reverseCount = 0; + float dMin = 1.0e10f; + int minAxis = 0; + for (int i = 0; i < 3; ++i) { + if (std::fabs(dir[i]) > FLT_EPSILON) { + bool pointMax = pointFlags & (1 << i); + if (pointMax != dir[i] > 0.f) { + ++reverseCount; + float d = 1.f / dir[i] * ((pointMax ? aabb.max[i] : aabb.min[i]) - sphere.position[i]); + if (d < 0.f) + return false; + if (d < dMin) { + dMin = d; + minAxis = i; + } + } + } + } + + if (reverseCount < 2) + return false; + + int useAxisNext1 = (minAxis + 1) % 3; + int useAxisNext2 = (minAxis + 2) % 3; + float d; + if (CollisionUtil::LineCircleIntersection2d(sphere.position, dir, zeus::CSphere(aabbPoint, sphere.radius), + useAxisNext1, useAxisNext2, d) && + d > 0.f && d < dOut) { + point = sphere.position + d * dir; + if (point[minAxis] > aabb.max[minAxis]) + return false; + if (point[minAxis] < aabb.min[minAxis]) + return false; + + dOut = d; + normal = point - aabbPoint; + normal.normalize(); + point -= sphere.radius * normal; + return true; + } else { + return false; + } + } + } + + bool useNextAxis1 = inBounds1 ? nextAxis2 : nextAxis1; + bool useNextAxis2 = inBounds1 ? nextAxis1 : nextAxis2; + + int pointFlags = ((1 << int(useNextAxis1)) * (inBounds1 ? inMin2 : inMin1)) | ((1 << axis) * sign); + zeus::CVector3f aabbPoint2 = aabb.getPoint(pointFlags); + float d; + if (LineCircleIntersection2d(sphere.position, dir, zeus::CSphere(aabbPoint2, sphere.radius), axis, useNextAxis1, d) && + d > 0.f && d < dOut) { + point = sphere.position + d * dir; + if (point[useNextAxis2] > aabb.max[useNextAxis2]) { + zeus::CVector3f aabbPoint3 = aabb.getPoint(pointFlags | (1 << int(useNextAxis2))); + if (point[useNextAxis2] < expAABB.max[useNextAxis2]) { + if (RaySphereIntersection(zeus::CSphere(aabbPoint3, sphere.radius), sphere.position, dir, dOut, d, point)) { + dOut = d; + normal = (point - aabbPoint3).normalized(); + point -= sphere.radius * normal; + return true; + } + } + return false; + } else if (point[useNextAxis2] < aabb.min[useNextAxis2]) { + if (point[useNextAxis2] > expAABB.min[useNextAxis2]) { + if (RaySphereIntersection(zeus::CSphere(aabbPoint2, sphere.radius), sphere.position, dir, dOut, d, point)) { + dOut = d; + normal = (point - aabbPoint2).normalized(); + point -= sphere.radius * normal; + return true; + } + } + return false; + } else { + dOut = d; + normal = point - aabbPoint2; + normal.normalize(); + point -= sphere.radius * normal; + return true; + } + } + + return false; } -void AddAverageToFront(const CCollisionInfoList& in, CCollisionInfoList& out) -{ - if (in.GetCount() > 1) - { - zeus::CVector3f pointAccum, normAccum; +bool AABox_AABox_Moving(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1, const zeus::CVector3f& dir, double& d, + zeus::CVector3f& point, zeus::CVector3f& normal) { + zeus::CVector3d vecMin(-FLT_MAX); + zeus::CVector3d vecMax(FLT_MAX); - for (const CCollisionInfo& info : in) - { - pointAccum += info.GetPoint(); - normAccum += info.GetNormalLeft(); - } + for (int i = 0; i < 3; ++i) { + if (std::fabs(dir[i]) < FLT_EPSILON) { + if (aabb0.min[i] >= aabb1.min[i] && aabb0.min[i] <= aabb1.max[i]) + continue; + if (aabb0.max[i] >= aabb1.min[i] && aabb0.max[i] <= aabb1.max[i]) + continue; + if (aabb0.min[i] < aabb1.min[i] && aabb0.max[i] > aabb1.max[i]) + continue; + return false; + } else { + if (aabb0.max[i] < aabb1.min[i] && dir[i] > 0.f) + vecMin[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i]; + else if (aabb1.max[i] < aabb0.min[i] && dir[i] < 0.f) + vecMin[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i]; + else if (aabb1.max[i] > aabb0.min[i] && dir[i] < 0.f) + vecMin[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i]; + else if (aabb0.max[i] > aabb1.min[i] && dir[i] > 0.f) + vecMin[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i]; - if (normAccum.canBeNormalized()) - { - out.Add(CCollisionInfo(pointAccum / float(in.GetCount()), - in.GetItem(0).GetMaterialRight(), in.GetItem(0).GetMaterialLeft(), - normAccum.normalized()), false); - } + if (aabb1.max[i] > aabb0.min[i] && dir[i] > 0.f) + vecMax[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i]; + else if (aabb0.max[i] > aabb1.min[i] && dir[i] < 0.f) + vecMax[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i]; + else if (aabb0.max[i] < aabb1.min[i] && dir[i] < 0.f) + vecMax[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i]; + else if (aabb1.max[i] < aabb0.min[i] && dir[i] > 0.f) + vecMax[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i]; + } + } + + int maxAxis = 0; + if (vecMin[1] > vecMin[0]) + maxAxis = 1; + if (vecMin[2] > vecMin[maxAxis]) + maxAxis = 2; + + double minMax = std::min(std::min(vecMax[2], vecMax[1]), vecMax[0]); + if (vecMin[maxAxis] > minMax) + return false; + d = vecMin[maxAxis]; + + normal = zeus::CVector3f::skZero; + normal[maxAxis] = dir[maxAxis] > 0.f ? -1.f : 1.f; + + for (int i = 0; i < 3; ++i) + point[i] = dir[i] > 0.f ? aabb0.max[i] : aabb0.min[i]; + + point += float(d) * dir; + return true; +} + +void AddAverageToFront(const CCollisionInfoList& in, CCollisionInfoList& out) { + if (in.GetCount() > 1) { + zeus::CVector3f pointAccum, normAccum; + + for (const CCollisionInfo& info : in) { + pointAccum += info.GetPoint(); + normAccum += info.GetNormalLeft(); } - for (const CCollisionInfo& info : in) - out.Add(info, false); -} + if (normAccum.canBeNormalized()) { + out.Add(CCollisionInfo(pointAccum / float(in.GetCount()), in.GetItem(0).GetMaterialRight(), + in.GetItem(0).GetMaterialLeft(), normAccum.normalized()), + false); + } + } + + for (const CCollisionInfo& info : in) + out.Add(info, false); } +} // namespace urde::CollisionUtil diff --git a/Runtime/Collision/CollisionUtil.hpp b/Runtime/Collision/CollisionUtil.hpp index f312a53b2..911bc9d6d 100644 --- a/Runtime/Collision/CollisionUtil.hpp +++ b/Runtime/Collision/CollisionUtil.hpp @@ -4,48 +4,42 @@ #include "zeus/zeus.hpp" #include "CMaterialList.hpp" -namespace urde -{ +namespace urde { class CCollisionInfoList; -namespace CollisionUtil -{ +namespace CollisionUtil { bool LineIntersectsOBBox(const zeus::COBBox&, const zeus::CMRay&, float&); u32 RayAABoxIntersection(const zeus::CMRay&, const zeus::CAABox&, float&, float&); u32 RayAABoxIntersection(const zeus::CMRay&, const zeus::CAABox&, zeus::CVector3f&, float&); u32 RayAABoxIntersection_Double(const zeus::CMRay&, const zeus::CAABox&, zeus::CVector3f&, double&); bool RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f&, const zeus::CVector3f&, double&); -bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir, +bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir, float mag, float& T, zeus::CVector3f& point); bool RayTriangleIntersection_Double(const zeus::CVector3f& point, const zeus::CVector3f& dir, const zeus::CVector3f* verts, double& d); -bool RayTriangleIntersection(const zeus::CVector3f& point, const zeus::CVector3f& dir, - const zeus::CVector3f* verts, float& d); +bool RayTriangleIntersection(const zeus::CVector3f& point, const zeus::CVector3f& dir, const zeus::CVector3f* verts, + float& d); void FilterOutBackfaces(const zeus::CVector3f& vec, const CCollisionInfoList& in, CCollisionInfoList& out); void FilterByClosestNormal(const zeus::CVector3f& norm, const CCollisionInfoList& in, CCollisionInfoList& out); -bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const CMaterialList& list0, - const zeus::CAABox& aabb1, const CMaterialList& list1, - CCollisionInfoList& infoList); +bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const CMaterialList& list0, const zeus::CAABox& aabb1, + const CMaterialList& list1, CCollisionInfoList& infoList); bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1); bool TriBoxOverlap(const zeus::CVector3f& boxcenter, const zeus::CVector3f& boxhalfsize, - const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, - const zeus::CVector3f& trivert2); -double TriPointSqrDist(const zeus::CVector3f& point, - const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, + const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, const zeus::CVector3f& trivert2); +double TriPointSqrDist(const zeus::CVector3f& point, const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, const zeus::CVector3f& trivert2, float* baryX, float* baryY); -bool TriSphereOverlap(const zeus::CSphere& sphere, - const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, +bool TriSphereOverlap(const zeus::CSphere& sphere, const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, const zeus::CVector3f& trivert2); -bool TriSphereIntersection(const zeus::CSphere& sphere, - const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, - const zeus::CVector3f& trivert2, zeus::CVector3f& point, zeus::CVector3f& normal); -bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CVector3f& point, const zeus::CVector3f& dir, - float& tMin, float& tMax, int& axis, bool& sign); +bool TriSphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& trivert0, + const zeus::CVector3f& trivert1, const zeus::CVector3f& trivert2, zeus::CVector3f& point, + zeus::CVector3f& normal); +bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CVector3f& point, const zeus::CVector3f& dir, float& tMin, + float& tMax, int& axis, bool& sign); bool LineCircleIntersection2d(const zeus::CVector3f& point, const zeus::CVector3f& dir, const zeus::CSphere& sphere, int axis1, int axis2, float& d); -bool MovingSphereAABox(const zeus::CSphere& sphere, const zeus::CAABox& aabb, const zeus::CVector3f& dir, - double& d, zeus::CVector3f& point, zeus::CVector3f& normal); -bool AABox_AABox_Moving(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1, const zeus::CVector3f& dir, - double& d, zeus::CVector3f& point, zeus::CVector3f& normal); +bool MovingSphereAABox(const zeus::CSphere& sphere, const zeus::CAABox& aabb, const zeus::CVector3f& dir, double& d, + zeus::CVector3f& point, zeus::CVector3f& normal); +bool AABox_AABox_Moving(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1, const zeus::CVector3f& dir, double& d, + zeus::CVector3f& point, zeus::CVector3f& normal); void AddAverageToFront(const CCollisionInfoList& in, CCollisionInfoList& out); -} -} +} // namespace CollisionUtil +} // namespace urde diff --git a/Runtime/Collision/ICollisionFilter.hpp b/Runtime/Collision/ICollisionFilter.hpp index 13e8ce2a1..4ba21bfee 100644 --- a/Runtime/Collision/ICollisionFilter.hpp +++ b/Runtime/Collision/ICollisionFilter.hpp @@ -2,18 +2,17 @@ #include "CCollisionInfoList.hpp" -namespace urde -{ +namespace urde { class CActor; -class ICollisionFilter -{ - CActor& x4_actor; +class ICollisionFilter { + CActor& x4_actor; + protected: - ICollisionFilter(CActor& actor) : x4_actor(actor) {} + ICollisionFilter(CActor& actor) : x4_actor(actor) {} + public: - virtual void Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const = 0; + virtual void Filter(const CCollisionInfoList& in, CCollisionInfoList& out) const = 0; }; -} - +} // namespace urde diff --git a/Runtime/Collision/InternalColliders.cpp b/Runtime/Collision/InternalColliders.cpp index 10aa68747..064ab2568 100644 --- a/Runtime/Collision/InternalColliders.cpp +++ b/Runtime/Collision/InternalColliders.cpp @@ -3,30 +3,27 @@ #include "CCollidableCollisionSurface.hpp" #include "CCollidableSphere.hpp" -namespace urde::InternalColliders -{ -void AddTypes() -{ - CCollisionPrimitive::InitAddType(CCollidableAABox::GetType()); - CCollisionPrimitive::InitAddType(CCollidableCollisionSurface::GetType()); - CCollisionPrimitive::InitAddType(CCollidableSphere::GetType()); +namespace urde::InternalColliders { +void AddTypes() { + CCollisionPrimitive::InitAddType(CCollidableAABox::GetType()); + CCollisionPrimitive::InitAddType(CCollidableCollisionSurface::GetType()); + CCollisionPrimitive::InitAddType(CCollidableSphere::GetType()); } -void AddColliders() -{ - CCollisionPrimitive::InitAddCollider(Collide::AABox_AABox, "CCollidableAABox", "CCollidableAABox"); - CCollisionPrimitive::InitAddCollider(Collide::Sphere_AABox, "CCollidableSphere", "CCollidableAABox"); - CCollisionPrimitive::InitAddCollider(Collide::Sphere_Sphere, "CCollidableSphere", "CCollidableSphere"); - CCollisionPrimitive::InitAddBooleanCollider(Collide::AABox_AABox_Bool, "CCollidableAABox", "CCollidableAABox"); - CCollisionPrimitive::InitAddBooleanCollider(Collide::Sphere_AABox_Bool, "CCollidableSphere", "CCollidableAABox"); - CCollisionPrimitive::InitAddBooleanCollider(Collide::Sphere_Sphere_Bool, "CCollidableSphere", "CCollidableSphere"); - CCollisionPrimitive::InitAddMovingCollider(CCollidableAABox::CollideMovingAABox, "CCollidableAABox", - "CCollidableAABox"); - CCollisionPrimitive::InitAddMovingCollider(CCollidableAABox::CollideMovingSphere, "CCollidableAABox", - "CCollidableSphere"); - CCollisionPrimitive::InitAddMovingCollider(CCollidableSphere::CollideMovingAABox, "CCollidableSphere", - "CCollidableAABox"); - CCollisionPrimitive::InitAddMovingCollider(CCollidableSphere::CollideMovingSphere, "CCollidableSphere", - "CCollidableSphere"); -} +void AddColliders() { + CCollisionPrimitive::InitAddCollider(Collide::AABox_AABox, "CCollidableAABox", "CCollidableAABox"); + CCollisionPrimitive::InitAddCollider(Collide::Sphere_AABox, "CCollidableSphere", "CCollidableAABox"); + CCollisionPrimitive::InitAddCollider(Collide::Sphere_Sphere, "CCollidableSphere", "CCollidableSphere"); + CCollisionPrimitive::InitAddBooleanCollider(Collide::AABox_AABox_Bool, "CCollidableAABox", "CCollidableAABox"); + CCollisionPrimitive::InitAddBooleanCollider(Collide::Sphere_AABox_Bool, "CCollidableSphere", "CCollidableAABox"); + CCollisionPrimitive::InitAddBooleanCollider(Collide::Sphere_Sphere_Bool, "CCollidableSphere", "CCollidableSphere"); + CCollisionPrimitive::InitAddMovingCollider(CCollidableAABox::CollideMovingAABox, "CCollidableAABox", + "CCollidableAABox"); + CCollisionPrimitive::InitAddMovingCollider(CCollidableAABox::CollideMovingSphere, "CCollidableAABox", + "CCollidableSphere"); + CCollisionPrimitive::InitAddMovingCollider(CCollidableSphere::CollideMovingAABox, "CCollidableSphere", + "CCollidableAABox"); + CCollisionPrimitive::InitAddMovingCollider(CCollidableSphere::CollideMovingSphere, "CCollidableSphere", + "CCollidableSphere"); } +} // namespace urde::InternalColliders diff --git a/Runtime/Collision/InternalColliders.hpp b/Runtime/Collision/InternalColliders.hpp index 1dfef20d7..305a13645 100644 --- a/Runtime/Collision/InternalColliders.hpp +++ b/Runtime/Collision/InternalColliders.hpp @@ -1,7 +1,6 @@ #pragma once -namespace urde::InternalColliders -{ - void AddTypes(); - void AddColliders(); -} +namespace urde::InternalColliders { +void AddTypes(); +void AddColliders(); +} // namespace urde::InternalColliders diff --git a/Runtime/GCNTypes.hpp b/Runtime/GCNTypes.hpp index 745e00441..42233d831 100644 --- a/Runtime/GCNTypes.hpp +++ b/Runtime/GCNTypes.hpp @@ -11,4 +11,3 @@ using s32 = int32_t; using u32 = uint32_t; using s64 = int64_t; using u64 = uint64_t; - diff --git a/Runtime/GameGlobalObjects.cpp b/Runtime/GameGlobalObjects.cpp index b01cdebb8..da785f78f 100644 --- a/Runtime/GameGlobalObjects.cpp +++ b/Runtime/GameGlobalObjects.cpp @@ -1,9 +1,7 @@ #include "GameGlobalObjects.hpp" -namespace urde -{ -namespace MP1 -{ +namespace urde { +namespace MP1 { class CGameArchitectureSupport* g_archSupport = nullptr; } @@ -20,7 +18,7 @@ class CStringTable* g_MainStringTable = nullptr; class CInputGenerator* g_InputGenerator = nullptr; class CStateManager* g_StateManager = nullptr; -ITweakGame* g_tweakGame = nullptr; +ITweakGame* g_tweakGame = nullptr; ITweakPlayer* g_tweakPlayer = nullptr; ITweakPlayerControl* g_tweakPlayerControl = nullptr; ITweakPlayerControl* g_tweakPlayerControlAlt = nullptr; @@ -36,4 +34,4 @@ ITweakParticle* g_tweakParticle = nullptr; ITweakBall* g_tweakBall = nullptr; ITweakGuiColors* g_tweakGuiColors = nullptr; -} +} // namespace urde diff --git a/Runtime/GameGlobalObjects.hpp b/Runtime/GameGlobalObjects.hpp index ed984ee01..3093aaeac 100644 --- a/Runtime/GameGlobalObjects.hpp +++ b/Runtime/GameGlobalObjects.hpp @@ -34,11 +34,9 @@ #include "../DataSpec/DNACommon/Tweaks/ITweakGuiColors.hpp" #endif -namespace urde -{ +namespace urde { extern class IMain* g_Main; -namespace MP1 -{ +namespace MP1 { extern class CGameArchitectureSupport* g_archSupport; } extern class CMemoryCardSys* g_MemoryCardSys; @@ -83,7 +81,7 @@ using ITweakBall = DataSpec::ITweakBall; using ITweakGuiColors = DataSpec::ITweakGuiColors; #endif -extern ITweakGame* g_tweakGame; +extern ITweakGame* g_tweakGame; extern ITweakPlayer* g_tweakPlayer; extern ITweakPlayerControl* g_tweakPlayerControl; extern ITweakPlayerControl* g_tweakPlayerControlAlt; @@ -99,5 +97,4 @@ extern ITweakParticle* g_tweakParticle; extern ITweakBall* g_tweakBall; extern ITweakGuiColors* g_tweakGuiColors; -} - +} // namespace urde diff --git a/Runtime/GameObjectLists.cpp b/Runtime/GameObjectLists.cpp index 8242467b3..550eb6015 100644 --- a/Runtime/GameObjectLists.cpp +++ b/Runtime/GameObjectLists.cpp @@ -8,75 +8,43 @@ #include "Camera/CGameCamera.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CActorList::CActorList() - : CObjectList(EGameObjectList::Actor) {} +CActorList::CActorList() : CObjectList(EGameObjectList::Actor) {} -bool CActorList::IsQualified(const CEntity& ent) -{ - return TCastToConstPtr(ent); +bool CActorList::IsQualified(const CEntity& ent) { return TCastToConstPtr(ent); } + +CPhysicsActorList::CPhysicsActorList() : CObjectList(EGameObjectList::PhysicsActor) {} + +bool CPhysicsActorList::IsQualified(const CEntity& ent) { return TCastToConstPtr(ent); } + +CGameCameraList::CGameCameraList() : CObjectList(EGameObjectList::GameCamera) {} + +bool CGameCameraList::IsQualified(const CEntity& ent) { return TCastToConstPtr(ent); } + +CListeningAiList::CListeningAiList() : CObjectList(EGameObjectList::ListeningAi) {} + +bool CListeningAiList::IsQualified(const CEntity& ent) { + TCastToConstPtr ai(ent); + return ai && ai->IsListening(); } -CPhysicsActorList::CPhysicsActorList() - : CObjectList(EGameObjectList::PhysicsActor) {} +CAiWaypointList::CAiWaypointList() : CObjectList(EGameObjectList::AiWaypoint) {} -bool CPhysicsActorList::IsQualified(const CEntity& ent) -{ - return TCastToConstPtr(ent); +bool CAiWaypointList::IsQualified(const CEntity& ent) { + return TCastToConstPtr(ent) || TCastToConstPtr(ent); } -CGameCameraList::CGameCameraList() - : CObjectList(EGameObjectList::GameCamera) {} +CPlatformAndDoorList::CPlatformAndDoorList() : CObjectList(EGameObjectList::PlatformAndDoor) {} -bool CGameCameraList::IsQualified(const CEntity& ent) -{ - return TCastToConstPtr(ent); -} +bool CPlatformAndDoorList::IsQualified(const CEntity& ent) { return IsDoor(ent) || IsPlatform(ent); } -CListeningAiList::CListeningAiList() - : CObjectList(EGameObjectList::ListeningAi) {} +bool CPlatformAndDoorList::IsDoor(const CEntity& ent) { return TCastToConstPtr(ent); } -bool CListeningAiList::IsQualified(const CEntity& ent) -{ - TCastToConstPtr ai(ent); - return ai && ai->IsListening(); -} +bool CPlatformAndDoorList::IsPlatform(const CEntity& ent) { return TCastToConstPtr(ent); } -CAiWaypointList::CAiWaypointList() - : CObjectList(EGameObjectList::AiWaypoint) {} +CGameLightList::CGameLightList() : CObjectList(EGameObjectList::GameLight) {} -bool CAiWaypointList::IsQualified(const CEntity& ent) -{ - return TCastToConstPtr(ent) || - TCastToConstPtr(ent); -} +bool CGameLightList::IsQualified(const CEntity& lt) { return TCastToConstPtr(lt); } -CPlatformAndDoorList::CPlatformAndDoorList() - : CObjectList(EGameObjectList::PlatformAndDoor) {} - -bool CPlatformAndDoorList::IsQualified(const CEntity& ent) -{ - return IsDoor(ent) || IsPlatform(ent); -} - -bool CPlatformAndDoorList::IsDoor(const CEntity& ent) -{ - return TCastToConstPtr(ent); -} - -bool CPlatformAndDoorList::IsPlatform(const CEntity& ent) -{ - return TCastToConstPtr(ent); -} - -CGameLightList::CGameLightList() - : CObjectList(EGameObjectList::GameLight) {} - -bool CGameLightList::IsQualified(const CEntity& lt) -{ - return TCastToConstPtr(lt); -} - -} +} // namespace urde diff --git a/Runtime/GameObjectLists.hpp b/Runtime/GameObjectLists.hpp index 091ff658b..095690c53 100644 --- a/Runtime/GameObjectLists.hpp +++ b/Runtime/GameObjectLists.hpp @@ -2,63 +2,54 @@ #include "CObjectList.hpp" -namespace urde -{ +namespace urde { -class CActorList : public CObjectList -{ +class CActorList : public CObjectList { public: - CActorList(); + CActorList(); - bool IsQualified(const CEntity&); + bool IsQualified(const CEntity&); }; -class CPhysicsActorList : public CObjectList -{ +class CPhysicsActorList : public CObjectList { public: - CPhysicsActorList(); - bool IsQualified(const CEntity&); + CPhysicsActorList(); + bool IsQualified(const CEntity&); }; -class CGameCameraList : public CObjectList -{ +class CGameCameraList : public CObjectList { public: - CGameCameraList(); - bool IsQualified(const CEntity&); + CGameCameraList(); + bool IsQualified(const CEntity&); }; -class CListeningAiList : public CObjectList -{ +class CListeningAiList : public CObjectList { public: - CListeningAiList(); + CListeningAiList(); - bool IsQualified(const CEntity&); + bool IsQualified(const CEntity&); }; -class CAiWaypointList : public CObjectList -{ +class CAiWaypointList : public CObjectList { public: - CAiWaypointList(); - bool IsQualified(const CEntity&); + CAiWaypointList(); + bool IsQualified(const CEntity&); }; -class CPlatformAndDoorList : public CObjectList -{ +class CPlatformAndDoorList : public CObjectList { public: - CPlatformAndDoorList(); + CPlatformAndDoorList(); - bool IsQualified(const CEntity&); - bool IsDoor(const CEntity&); - bool IsPlatform(const CEntity&); + bool IsQualified(const CEntity&); + bool IsDoor(const CEntity&); + bool IsPlatform(const CEntity&); }; -class CGameLightList : public CObjectList -{ +class CGameLightList : public CObjectList { public: - CGameLightList(); + CGameLightList(); - bool IsQualified(const CEntity&); + bool IsQualified(const CEntity&); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index ffc19457f..114f8aabb 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -18,8 +18,7 @@ #define FOGVOL_NEAR 0.2 #define SPHERE_RAMP_RES 32 -namespace urde -{ +namespace urde { static logvisor::Module Log("CBooRenderer"); @@ -36,1118 +35,935 @@ rstl::reserved_vector* Buckets::sPlaneObjectBucket = nullptr; const float Buckets::skWorstMinMaxDistance[2] = {99999.f, -99999.f}; float Buckets::sMinMaxDistance[2]; -void Buckets::Clear() -{ - sData->clear(); - sBucketIndex.clear(); - sPlaneObjectData->clear(); - sPlaneObjectBucket->clear(); - for (rstl::reserved_vector& bucket : *sBuckets) - bucket.clear(); - sMinMaxDistance[0] = skWorstMinMaxDistance[0]; - sMinMaxDistance[1] = skWorstMinMaxDistance[1]; +void Buckets::Clear() { + sData->clear(); + sBucketIndex.clear(); + sPlaneObjectData->clear(); + sPlaneObjectBucket->clear(); + for (rstl::reserved_vector& bucket : *sBuckets) + bucket.clear(); + sMinMaxDistance[0] = skWorstMinMaxDistance[0]; + sMinMaxDistance[1] = skWorstMinMaxDistance[1]; } -void Buckets::Sort() -{ - float delta = std::max(1.f, sMinMaxDistance[1] - sMinMaxDistance[0]); - float pitch = 49.f / delta; - for (auto it = sPlaneObjectData->begin() ; it != sPlaneObjectData->end() ; ++it) - if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity()) - sPlaneObjectBucket->push_back(s16(it - sPlaneObjectData->begin())); +void Buckets::Sort() { + float delta = std::max(1.f, sMinMaxDistance[1] - sMinMaxDistance[0]); + float pitch = 49.f / delta; + for (auto it = sPlaneObjectData->begin(); it != sPlaneObjectData->end(); ++it) + if (sPlaneObjectBucket->size() != sPlaneObjectBucket->capacity()) + sPlaneObjectBucket->push_back(s16(it - sPlaneObjectData->begin())); - u32 precision = 50; - if (sPlaneObjectBucket->size()) - { - std::sort(sPlaneObjectBucket->begin(), sPlaneObjectBucket->end(), - [](u16 a, u16 b) - { - return (*sPlaneObjectData)[a].GetDistance() > (*sPlaneObjectData)[b].GetDistance(); - }); - precision = 50 / u32(sPlaneObjectBucket->size() + 1); - pitch = 1.f / (delta / float(precision - 2)); + u32 precision = 50; + if (sPlaneObjectBucket->size()) { + std::sort(sPlaneObjectBucket->begin(), sPlaneObjectBucket->end(), + [](u16 a, u16 b) { return (*sPlaneObjectData)[a].GetDistance() > (*sPlaneObjectData)[b].GetDistance(); }); + precision = 50 / u32(sPlaneObjectBucket->size() + 1); + pitch = 1.f / (delta / float(precision - 2)); - int accum = 0; - for (u16 idx : *sPlaneObjectBucket) - { - ++accum; - CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[idx]; - planeObj.x24_targetBucket = u16(precision * accum); - } + int accum = 0; + for (u16 idx : *sPlaneObjectBucket) { + ++accum; + CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[idx]; + planeObj.x24_targetBucket = u16(precision * accum); } + } - for (CDrawable& drawable : *sData) - { - int slot; - float relDist = drawable.GetDistance() - sMinMaxDistance[0]; - if (sPlaneObjectBucket->empty()) - { - slot = zeus::clamp(1, int(relDist * pitch), 49); - } - else - { - slot = zeus::clamp(0, int(relDist * pitch), int(precision) - 2); - for (u16 idx : *sPlaneObjectBucket) - { - CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[idx]; - bool partial, full; - if (planeObj.x3c_25_zOnly) - { - partial = drawable.GetBounds().max.z() > planeObj.GetPlane().d(); - full = drawable.GetBounds().min.z() > planeObj.GetPlane().d(); - } - else - { - partial = planeObj.GetPlane().pointToPlaneDist( + for (CDrawable& drawable : *sData) { + int slot; + float relDist = drawable.GetDistance() - sMinMaxDistance[0]; + if (sPlaneObjectBucket->empty()) { + slot = zeus::clamp(1, int(relDist * pitch), 49); + } else { + slot = zeus::clamp(0, int(relDist * pitch), int(precision) - 2); + for (u16 idx : *sPlaneObjectBucket) { + CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[idx]; + bool partial, full; + if (planeObj.x3c_25_zOnly) { + partial = drawable.GetBounds().max.z() > planeObj.GetPlane().d(); + full = drawable.GetBounds().min.z() > planeObj.GetPlane().d(); + } else { + partial = planeObj.GetPlane().pointToPlaneDist( drawable.GetBounds().closestPointAlongVector(planeObj.GetPlane().normal())) > 0.f; - full = planeObj.GetPlane().pointToPlaneDist( - drawable.GetBounds().furthestPointAlongVector(planeObj.GetPlane().normal())) > 0.f; - } - bool cont; - if (drawable.GetType() == EDrawableType::Particle) - cont = planeObj.x3c_24_invertTest ? !partial : full; - else - cont = planeObj.x3c_24_invertTest ? (!partial || !full) : (partial || full); - if (!cont) - break; - slot += precision; - } + full = planeObj.GetPlane().pointToPlaneDist( + drawable.GetBounds().furthestPointAlongVector(planeObj.GetPlane().normal())) > 0.f; } - - if (slot == -1) - slot = 49; - rstl::reserved_vector& bucket = (*sBuckets)[slot]; - if (bucket.size() < bucket.capacity()) - bucket.push_back(&drawable); - //else - // Log.report(logvisor::Fatal, "Full bucket!!!"); + bool cont; + if (drawable.GetType() == EDrawableType::Particle) + cont = planeObj.x3c_24_invertTest ? !partial : full; + else + cont = planeObj.x3c_24_invertTest ? (!partial || !full) : (partial || full); + if (!cont) + break; + slot += precision; + } } - u16 bucketIdx = u16(sBuckets->size()); - for (auto it = sBuckets->rbegin() ; it != sBuckets->rend() ; ++it) - { - --bucketIdx; - sBucketIndex.push_back(bucketIdx); - rstl::reserved_vector& bucket = *it; - if (bucket.size()) - { - std::sort(bucket.begin(), bucket.end(), - [](CDrawable* a, CDrawable* b) - { - if (a->GetDistance() == b->GetDistance()) - return a->GetExtraSort() > b->GetExtraSort(); - return a->GetDistance() > b->GetDistance(); - }); - } - } + if (slot == -1) + slot = 49; + rstl::reserved_vector& bucket = (*sBuckets)[slot]; + if (bucket.size() < bucket.capacity()) + bucket.push_back(&drawable); + // else + // Log.report(logvisor::Fatal, "Full bucket!!!"); + } - for (auto it = sPlaneObjectBucket->rbegin() ; it != sPlaneObjectBucket->rend() ; ++it) - { - CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[*it]; - rstl::reserved_vector& bucket = (*sBuckets)[planeObj.x24_targetBucket]; - bucket.push_back(&planeObj); + u16 bucketIdx = u16(sBuckets->size()); + for (auto it = sBuckets->rbegin(); it != sBuckets->rend(); ++it) { + --bucketIdx; + sBucketIndex.push_back(bucketIdx); + rstl::reserved_vector& bucket = *it; + if (bucket.size()) { + std::sort(bucket.begin(), bucket.end(), [](CDrawable* a, CDrawable* b) { + if (a->GetDistance() == b->GetDistance()) + return a->GetExtraSort() > b->GetExtraSort(); + return a->GetDistance() > b->GetDistance(); + }); } + } + + for (auto it = sPlaneObjectBucket->rbegin(); it != sPlaneObjectBucket->rend(); ++it) { + CDrawablePlaneObject& planeObj = (*sPlaneObjectData)[*it]; + rstl::reserved_vector& bucket = (*sBuckets)[planeObj.x24_targetBucket]; + bucket.push_back(&planeObj); + } } void Buckets::InsertPlaneObject(float closeDist, float farDist, const zeus::CAABox& aabb, bool invertTest, - const zeus::CPlane& plane, bool zOnly, EDrawableType dtype, const void* data) -{ - if (sPlaneObjectData->size() == sPlaneObjectData->capacity()) - return; - sPlaneObjectData->push_back(CDrawablePlaneObject(dtype, closeDist, farDist, aabb, invertTest, plane, zOnly, data)); + const zeus::CPlane& plane, bool zOnly, EDrawableType dtype, const void* data) { + if (sPlaneObjectData->size() == sPlaneObjectData->capacity()) + return; + sPlaneObjectData->push_back(CDrawablePlaneObject(dtype, closeDist, farDist, aabb, invertTest, plane, zOnly, data)); } -void Buckets::Insert(const zeus::CVector3f& pos, const zeus::CAABox& aabb, EDrawableType dtype, - const void* data, const zeus::CPlane& plane, u16 extraSort) -{ - if (sData->size() != sData->capacity()) - { - float dist = plane.pointToPlaneDist(pos); - sData->push_back(CDrawable(dtype, extraSort, dist, aabb, data)); - if (sMinMaxDistance[0] > dist) - sMinMaxDistance[0] = dist; - if (sMinMaxDistance[1] < dist) - sMinMaxDistance[1] = dist; - } - else - { - Log.report(logvisor::Fatal, "Rendering buckets filled to capacity"); - } +void Buckets::Insert(const zeus::CVector3f& pos, const zeus::CAABox& aabb, EDrawableType dtype, const void* data, + const zeus::CPlane& plane, u16 extraSort) { + if (sData->size() != sData->capacity()) { + float dist = plane.pointToPlaneDist(pos); + sData->push_back(CDrawable(dtype, extraSort, dist, aabb, data)); + if (sMinMaxDistance[0] > dist) + sMinMaxDistance[0] = dist; + if (sMinMaxDistance[1] < dist) + sMinMaxDistance[1] = dist; + } else { + Log.report(logvisor::Fatal, "Rendering buckets filled to capacity"); + } } -void Buckets::Shutdown() -{ - sData = nullptr; - sBuckets = nullptr; - sPlaneObjectData = nullptr; - sPlaneObjectBucket = nullptr; +void Buckets::Shutdown() { + sData = nullptr; + sBuckets = nullptr; + sPlaneObjectData = nullptr; + sPlaneObjectBucket = nullptr; } -void Buckets::Init() -{ - sData = &sDataHolder; - sBuckets = &sBucketsHolder; - sBuckets->resize(50); - sPlaneObjectData = &sPlaneObjectDataHolder; - sPlaneObjectBucket = &sPlaneObjectBucketHolder; - sMinMaxDistance[0] = skWorstMinMaxDistance[0]; - sMinMaxDistance[1] = skWorstMinMaxDistance[1]; +void Buckets::Init() { + sData = &sDataHolder; + sBuckets = &sBucketsHolder; + sBuckets->resize(50); + sPlaneObjectData = &sPlaneObjectDataHolder; + sPlaneObjectBucket = &sPlaneObjectBucketHolder; + sMinMaxDistance[0] = skWorstMinMaxDistance[0]; + sMinMaxDistance[1] = skWorstMinMaxDistance[1]; } CBooRenderer::CAreaListItem::CAreaListItem(const std::vector* geom, const CAreaRenderOctTree* octTree, std::vector>&& textures, - std::vector&& models, int areaIdx, - const SShader* shaderSet) - : x0_geometry(geom), x4_octTree(octTree), x8_textures(std::move(textures)), - x10_models(std::move(models)), x18_areaIdx(areaIdx), m_shaderSet(shaderSet) {} + std::vector&& models, int areaIdx, const SShader* shaderSet) +: x0_geometry(geom) +, x4_octTree(octTree) +, x8_textures(std::move(textures)) +, x10_models(std::move(models)) +, x18_areaIdx(areaIdx) +, m_shaderSet(shaderSet) {} CBooRenderer::CAreaListItem::~CAreaListItem() {} -static inline bool TestBit(const u32* words, int bit) -{ - return (words[bit / 32] & (1 << (bit & 0x1f))) != 0; -} +static inline bool TestBit(const u32* words, int bit) { return (words[bit / 32] & (1 << (bit & 0x1f))) != 0; } -void CBooRenderer::ActivateLightsForModel(CAreaListItem* item, CBooModel& model) -{ - std::vector thisLights; - thisLights.reserve(4); +void CBooRenderer::ActivateLightsForModel(CAreaListItem* item, CBooModel& model) { + std::vector thisLights; + thisLights.reserve(4); - if (x300_dynamicLights.size()) - { - u32 lightOctreeWordCount = 0; - u32* lightOctreeWords = nullptr; - if (item && model.x44_areaInstanceIdx != -1) - { - lightOctreeWordCount = item->x4_octTree->x14_bitmapWordCount; - lightOctreeWords = item->x1c_lightOctreeWords.data(); - } - - float lightRads[4] = {-1.f, -1.f, -1.f, -1.f}; - CLight* lightRefs[4] = {}; - auto it = x300_dynamicLights.begin(); - for (int i=0 ; i<4 && it != x300_dynamicLights.end() ; ++it, lightOctreeWords += lightOctreeWordCount) - { - CLight& refLight = *it; - if (lightOctreeWords && !TestBit(lightOctreeWords, model.x44_areaInstanceIdx)) - continue; - - bool foundLight = false; - for (int j=0 ; jx4_octTree->x14_bitmapWordCount; + lightOctreeWords = item->x1c_lightOctreeWords.data(); } - model.ActivateLights(thisLights); + float lightRads[4] = {-1.f, -1.f, -1.f, -1.f}; + CLight* lightRefs[4] = {}; + auto it = x300_dynamicLights.begin(); + for (int i = 0; i < 4 && it != x300_dynamicLights.end(); ++it, lightOctreeWords += lightOctreeWordCount) { + CLight& refLight = *it; + if (lightOctreeWords && !TestBit(lightOctreeWords, model.x44_areaInstanceIdx)) + continue; + + bool foundLight = false; + for (int j = 0; j < i; ++j) { + if (lightRefs[j] == &refLight) + continue; + float radius = model.x20_aabb.intersectionRadius(zeus::CSphere(refLight.GetPosition(), refLight.GetRadius())); + if (radius < 0.f) + break; + if (lightRads[j] <= radius) + break; + lightRads[j] = radius; + lightRefs[j] = &refLight; + thisLights.push_back(refLight); + foundLight = true; + } + + if (foundLight) + continue; + + float radius = model.x20_aabb.intersectionRadius(zeus::CSphere(refLight.GetPosition(), refLight.GetRadius())); + if (radius < 0.f) + continue; + lightRads[i] = radius; + lightRefs[i] = &refLight; + thisLights.push_back(refLight); + ++i; + } + } + + model.ActivateLights(thisLights); } -void CBooRenderer::RenderBucketItems(CAreaListItem* item) -{ - CModelFlags flags; - flags.m_noZWrite = true; - flags.m_extendedShader = EExtendedShader::Lighting; +void CBooRenderer::RenderBucketItems(CAreaListItem* item) { + CModelFlags flags; + flags.m_noZWrite = true; + flags.m_extendedShader = EExtendedShader::Lighting; - for (u16 idx : Buckets::sBucketIndex) - { - rstl::reserved_vector& bucket = (*Buckets::sBuckets)[idx]; - for (CDrawable* drawable : bucket) - { - switch (drawable->GetType()) - { - case EDrawableType::Particle: - { - static_cast((void*)drawable->GetData())->Render(); - break; - } - case EDrawableType::WorldSurface: - { - //SetupRendererStates(); - CBooSurface* surf = static_cast((void*)drawable->GetData()); - CBooModel* model = surf->m_parent; - if (model) - { - ActivateLightsForModel(item, *model); - model->DrawSurface(*surf, flags); - } - break; - } - default: - { - if (xa8_drawableCallback) - { - xa8_drawableCallback(drawable->GetData(), xac_callbackContext, - int(drawable->GetType()) - 2); - } - break; - } - } + for (u16 idx : Buckets::sBucketIndex) { + rstl::reserved_vector& bucket = (*Buckets::sBuckets)[idx]; + for (CDrawable* drawable : bucket) { + switch (drawable->GetType()) { + case EDrawableType::Particle: { + static_cast((void*)drawable->GetData())->Render(); + break; + } + case EDrawableType::WorldSurface: { + // SetupRendererStates(); + CBooSurface* surf = static_cast((void*)drawable->GetData()); + CBooModel* model = surf->m_parent; + if (model) { + ActivateLightsForModel(item, *model); + model->DrawSurface(*surf, flags); } + break; + } + default: { + if (xa8_drawableCallback) { + xa8_drawableCallback(drawable->GetData(), xac_callbackContext, int(drawable->GetType()) - 2); + } + break; + } + } } + } } -void CBooRenderer::HandleUnsortedModel(CAreaListItem* item, CBooModel& model, const CModelFlags& flags) -{ - //ActivateLightsForModel(item, model); - CBooSurface* surf = model.x38_firstUnsortedSurface; - while (surf) - { - model.DrawSurface(*surf, flags); - surf = surf->m_next; - } +void CBooRenderer::HandleUnsortedModel(CAreaListItem* item, CBooModel& model, const CModelFlags& flags) { + // ActivateLightsForModel(item, model); + CBooSurface* surf = model.x38_firstUnsortedSurface; + while (surf) { + model.DrawSurface(*surf, flags); + surf = surf->m_next; + } } -static const struct FogVolumeControl -{ +static const struct FogVolumeControl { - u32 xfc_[12][2] = - { - {0, 1}, - {1, 3}, - {3, 2}, - {2, 0}, - {4, 5}, - {5, 7}, - {7, 6}, - {6, 4}, - {0, 4}, - {1, 5}, - {3, 7}, - {2, 6} - }; - u32 x15c_[8] = {}; - //GXVtxDescList x17c_; {{POS, DIRECT}, {TEX0, DIRECT}} + u32 xfc_[12][2] = {{0, 1}, {1, 3}, {3, 2}, {2, 0}, {4, 5}, {5, 7}, {7, 6}, {6, 4}, {0, 4}, {1, 5}, {3, 7}, {2, 6}}; + u32 x15c_[8] = {}; + // GXVtxDescList x17c_; {{POS, DIRECT}, {TEX0, DIRECT}} } s_FogVolumeCtrl = {}; -static const int OrthogonalAxis[3][2] = -{ - {1, 2}, - {0, 2}, - {0, 1} -}; +static const int OrthogonalAxis[3][2] = {{1, 2}, {0, 2}, {0, 1}}; -static float GetPlaneInterpolant(const zeus::CPlane& plane, - const zeus::CVector3f& vert1, - const zeus::CVector3f& vert2) -{ - return zeus::clamp(0.f, -plane.pointToPlaneDist(vert1) / (vert2 - vert1).dot(plane.normal()), 1.f); +static float GetPlaneInterpolant(const zeus::CPlane& plane, const zeus::CVector3f& vert1, + const zeus::CVector3f& vert2) { + return zeus::clamp(0.f, -plane.pointToPlaneDist(vert1) / (vert2 - vert1).dot(plane.normal()), 1.f); } -void CBooRenderer::CalcDrawFogFan(const zeus::CPlane* planes, int numPlanes, const zeus::CVector3f* verts, - int numVerts, int iteration, int level, CFogVolumePlaneShader& fogVol) -{ - if (level == iteration) - { - CalcDrawFogFan(planes, numPlanes, verts, numVerts, iteration, level + 1, fogVol); - return; +void CBooRenderer::CalcDrawFogFan(const zeus::CPlane* planes, int numPlanes, const zeus::CVector3f* verts, int numVerts, + int iteration, int level, CFogVolumePlaneShader& fogVol) { + if (level == iteration) { + CalcDrawFogFan(planes, numPlanes, verts, numVerts, iteration, level + 1, fogVol); + return; + } + + if (level == numPlanes) { + fogVol.addFan(verts, numVerts); + return; + } + + const zeus::CPlane& plane = planes[level]; + u32 insidePlaneCount = 0; + bool outsidePlane[20]; + for (int i = 0; i < numVerts; ++i) + outsidePlane[insidePlaneCount++] = plane.normal().dot(verts[i]) < plane.d(); + + u32 numUseVerts = 0; + zeus::CVector3f useVerts[20]; + for (int i = 0; i < numVerts; ++i) { + int nextIdx = (i + 1) % numVerts; + int insidePair = int(outsidePlane[i]) | (int(outsidePlane[nextIdx]) << 1); + if (!(insidePair & 0x1)) + useVerts[numUseVerts++] = verts[i]; + if (insidePair == 1 || insidePair == 2) { + /* Inside/outside transition; clip verts to other plane boundary */ + const zeus::CVector3f vert1 = verts[i]; + const zeus::CVector3f vert2 = verts[nextIdx]; + float interp = GetPlaneInterpolant(plane, vert1, vert2); + if (interp > 0.f || interp < 1.f) + useVerts[numUseVerts++] = (vert1 * (1.f - interp)) + (vert2 * interp); } + } - if (level == numPlanes) - { - fogVol.addFan(verts, numVerts); - return; - } - - const zeus::CPlane& plane = planes[level]; - u32 insidePlaneCount = 0; - bool outsidePlane[20]; - for (int i=0 ; i 0.f || interp < 1.f) - useVerts[numUseVerts++] = (vert1 * (1.f - interp)) + (vert2 * interp); - } - } - - if (numUseVerts >= 3) - CalcDrawFogFan(planes, numPlanes, useVerts, numUseVerts, iteration, level + 1, fogVol); + if (numUseVerts >= 3) + CalcDrawFogFan(planes, numPlanes, useVerts, numUseVerts, iteration, level + 1, fogVol); } -void CBooRenderer::DrawFogSlices(const zeus::CPlane* planes, int numPlanes, - int iteration, const zeus::CVector3f& center, float longestAxis, - CFogVolumePlaneShader& fogVol) -{ - u32 vertCount = 0; - zeus::CVector3d verts[4]; - u32 vert2Count = 0; - zeus::CVector3f verts2[4]; - const zeus::CPlane& plane = planes[iteration]; - int longestNormAxis = std::fabs(plane[1]) > std::fabs(plane[0]); - if (std::fabs(plane[2]) > std::fabs(plane[longestNormAxis])) - longestNormAxis = 2; +void CBooRenderer::DrawFogSlices(const zeus::CPlane* planes, int numPlanes, int iteration, + const zeus::CVector3f& center, float longestAxis, CFogVolumePlaneShader& fogVol) { + u32 vertCount = 0; + zeus::CVector3d verts[4]; + u32 vert2Count = 0; + zeus::CVector3f verts2[4]; + const zeus::CPlane& plane = planes[iteration]; + int longestNormAxis = std::fabs(plane[1]) > std::fabs(plane[0]); + if (std::fabs(plane[2]) > std::fabs(plane[longestNormAxis])) + longestNormAxis = 2; - zeus::CVector3d pointOnPlane = center - (plane.pointToPlaneDist(center) * plane.normal()); + zeus::CVector3d pointOnPlane = center - (plane.pointToPlaneDist(center) * plane.normal()); - float deltaSign = plane[longestNormAxis] >= 0.f ? -1.f : 1.f; - if (longestNormAxis == 1) - deltaSign = -deltaSign; + float deltaSign = plane[longestNormAxis] >= 0.f ? -1.f : 1.f; + if (longestNormAxis == 1) + deltaSign = -deltaSign; - zeus::CVector3d vec1; - zeus::CVector3d vec2; + zeus::CVector3d vec1; + zeus::CVector3d vec2; - vec1[OrthogonalAxis[longestNormAxis][0]] = longestAxis; - vec2[OrthogonalAxis[longestNormAxis][1]] = deltaSign * longestAxis; + vec1[OrthogonalAxis[longestNormAxis][0]] = longestAxis; + vec2[OrthogonalAxis[longestNormAxis][1]] = deltaSign * longestAxis; - verts[vertCount++] = pointOnPlane - vec1 - vec2; - verts[vertCount++] = pointOnPlane + vec1 - vec2; - verts[vertCount++] = pointOnPlane + vec1 + vec2; - verts[vertCount++] = pointOnPlane - vec1 + vec2; + verts[vertCount++] = pointOnPlane - vec1 - vec2; + verts[vertCount++] = pointOnPlane + vec1 - vec2; + verts[vertCount++] = pointOnPlane + vec1 + vec2; + verts[vertCount++] = pointOnPlane - vec1 + vec2; - zeus::CVector3d planeNormal = plane.normal(); - for (const zeus::CVector3d& vert : verts) - verts2[vert2Count++] = vert - (planeNormal * zeus::CVector3f(planeNormal.dot(vert) - plane.d())); + zeus::CVector3d planeNormal = plane.normal(); + for (const zeus::CVector3d& vert : verts) + verts2[vert2Count++] = vert - (planeNormal * zeus::CVector3f(planeNormal.dot(vert) - plane.d())); - CalcDrawFogFan(planes, numPlanes, verts2, vert2Count, iteration, 0, fogVol); + CalcDrawFogFan(planes, numPlanes, verts2, vert2Count, iteration, 0, fogVol); } -void CBooRenderer::RenderFogVolumeModel(const zeus::CAABox& aabb, const CModel* model, - const zeus::CTransform& modelMtx, const zeus::CTransform& viewMtx, - const CSkinnedModel* sModel, int pass, CFogVolumePlaneShader* fvs) -{ - if (!model && !sModel) - { - if (pass == 0) - { - zeus::CAABox xfAABB = aabb.getTransformedAABox(modelMtx); - zeus::CUnitVector3f viewNormal(viewMtx.basis[1]); - zeus::CPlane planes[7] = - { - {zeus::CVector3f::skRight, xfAABB.min.x()}, - {zeus::CVector3f::skLeft, -xfAABB.max.x()}, - {zeus::CVector3f::skForward, xfAABB.min.y()}, - {zeus::CVector3f::skBack, -xfAABB.max.y()}, - {zeus::CVector3f::skUp, xfAABB.min.z()}, - {zeus::CVector3f::skDown, -xfAABB.max.z()}, - {viewNormal, viewNormal.dot(viewMtx.origin) + 0.2f + 0.1f} - }; +void CBooRenderer::RenderFogVolumeModel(const zeus::CAABox& aabb, const CModel* model, const zeus::CTransform& modelMtx, + const zeus::CTransform& viewMtx, const CSkinnedModel* sModel, int pass, + CFogVolumePlaneShader* fvs) { + if (!model && !sModel) { + if (pass == 0) { + zeus::CAABox xfAABB = aabb.getTransformedAABox(modelMtx); + zeus::CUnitVector3f viewNormal(viewMtx.basis[1]); + zeus::CPlane planes[7] = {{zeus::CVector3f::skRight, xfAABB.min.x()}, + {zeus::CVector3f::skLeft, -xfAABB.max.x()}, + {zeus::CVector3f::skForward, xfAABB.min.y()}, + {zeus::CVector3f::skBack, -xfAABB.max.y()}, + {zeus::CVector3f::skUp, xfAABB.min.z()}, + {zeus::CVector3f::skDown, -xfAABB.max.z()}, + {viewNormal, viewNormal.dot(viewMtx.origin) + 0.2f + 0.1f}}; - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - float longestAxis = std::max(std::max( - xfAABB.max.x() - xfAABB.min.x(), - xfAABB.max.y() - xfAABB.min.y()), - xfAABB.max.z() - xfAABB.min.z()) * 2.f; + float longestAxis = std::max(std::max(xfAABB.max.x() - xfAABB.min.x(), xfAABB.max.y() - xfAABB.min.y()), + xfAABB.max.z() - xfAABB.min.z()) * + 2.f; - fvs->reset(7 * 6); - for (int i=0 ; i<7 ; ++i) - DrawFogSlices(planes, 7, i, xfAABB.center(), longestAxis, *fvs); - fvs->draw(0); - } - else - { - fvs->draw(pass); - } + fvs->reset(7 * 6); + for (int i = 0; i < 7; ++i) + DrawFogSlices(planes, 7, i, xfAABB.center(), longestAxis, *fvs); + fvs->draw(0); + } else { + fvs->draw(pass); } - else - { - CModelFlags flags; - switch (pass) - { - case 0: - default: - flags.m_extendedShader = EExtendedShader::SolidColorFrontfaceCullLEqualAlphaOnly; - flags.x4_color = zeus::CColor(1.f, 1.f, 1.f, 1.f); - break; - case 1: - flags.m_extendedShader = EExtendedShader::SolidColorFrontfaceCullAlwaysAlphaOnly; - flags.x4_color = zeus::CColor(1.f, 1.f, 1.f, 1.f); - break; - case 2: - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - flags.x4_color = zeus::CColor(1.f, 1.f, 1.f, 0.f); - break; - case 3: - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullGreaterAlphaOnly; - flags.x4_color = zeus::CColor(1.f, 1.f, 1.f, 0.f); - break; - } - - if (sModel) - { - sModel->Draw(flags); - } - else - { - model->UpdateLastFrame(); - model->Draw(flags); - } + } else { + CModelFlags flags; + switch (pass) { + case 0: + default: + flags.m_extendedShader = EExtendedShader::SolidColorFrontfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor(1.f, 1.f, 1.f, 1.f); + break; + case 1: + flags.m_extendedShader = EExtendedShader::SolidColorFrontfaceCullAlwaysAlphaOnly; + flags.x4_color = zeus::CColor(1.f, 1.f, 1.f, 1.f); + break; + case 2: + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor(1.f, 1.f, 1.f, 0.f); + break; + case 3: + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullGreaterAlphaOnly; + flags.x4_color = zeus::CColor(1.f, 1.f, 1.f, 0.f); + break; } + + if (sModel) { + sModel->Draw(flags); + } else { + model->UpdateLastFrame(); + model->Draw(flags); + } + } } -void CBooRenderer::SetupRendererStates() const -{ - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - CGraphics::g_ColorRegs[1] = x2fc_tevReg1Color; +void CBooRenderer::SetupRendererStates() const { + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + CGraphics::g_ColorRegs[1] = x2fc_tevReg1Color; } -void CBooRenderer::ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, - const CModel* model, const CSkinnedModel* sModel) -{ - zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(false); - zeus::CVector4f points[8]; +void CBooRenderer::ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, const CModel* model, + const CSkinnedModel* sModel) { + zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(false); + zeus::CVector4f points[8]; - for (int i=0 ; i<8 ; ++i) - { - zeus::CVector3f xfPt = CGraphics::g_GXModelView * aabb.getPoint(i); - points[i] = proj * zeus::CVector4f(xfPt); + for (int i = 0; i < 8; ++i) { + zeus::CVector3f xfPt = CGraphics::g_GXModelView * aabb.getPoint(i); + points[i] = proj * zeus::CVector4f(xfPt); + } + + zeus::CVector2i vpMax(0, 0); + zeus::CVector2i vpMin(g_Viewport.x8_width, g_Viewport.xc_height); + + bool vpInvalid = true; + for (int i = 0; i < 20; ++i) { + zeus::CVector3f overW; + if (i < 8) { + overW = points[i].toVec3f() * (1.f / points[i].w()); + } else { + const zeus::CVector4f& pt1 = points[s_FogVolumeCtrl.xfc_[i - 8][0]]; + const zeus::CVector4f& pt2 = points[s_FogVolumeCtrl.xfc_[i - 8][1]]; + + bool eq1 = (pt1.z() / pt1.w()) == 1.f; + bool eq2 = (pt2.z() / pt2.w()) == 1.f; + if (eq1 == eq2) + continue; + + float interp = -(pt1.w() - 1.f) / (pt2.w() - pt1.w()); + if (interp <= 0.f || interp >= 1.f) + continue; + + float wRecip = 1.f / (interp * (pt2.w() - pt1.w()) + pt1.w()); + zeus::CVector3f pt1_3 = pt1.toVec3f(); + zeus::CVector3f pt2_3 = pt2.toVec3f(); + overW = (pt1_3 + interp * (pt2_3 - pt1_3)) * wRecip; } - zeus::CVector2i vpMax(0, 0); - zeus::CVector2i vpMin(g_Viewport.x8_width, g_Viewport.xc_height); + // if (overW.z > 1.001f) + // continue; - bool vpInvalid = true; - for (int i=0 ; i<20 ; ++i) - { - zeus::CVector3f overW; - if (i < 8) - { - overW = points[i].toVec3f() * (1.f / points[i].w()); - } - else - { - const zeus::CVector4f& pt1 = points[s_FogVolumeCtrl.xfc_[i-8][0]]; - const zeus::CVector4f& pt2 = points[s_FogVolumeCtrl.xfc_[i-8][1]]; + int vpX = zeus::clamp(0, int(g_Viewport.x8_width * overW.x() * 0.5f + (g_Viewport.x8_width / 2)), + int(g_Viewport.x8_width)); + int vpY = zeus::clamp(0, int(g_Viewport.xc_height * overW.y() * 0.5f + (g_Viewport.xc_height / 2)), + int(g_Viewport.xc_height)); + vpMax.x = std::max(vpMax.x, vpX); + vpMin.x = std::min(vpMin.x, vpX); + vpMax.y = std::max(vpMax.y, vpY); + vpMin.y = std::min(vpMin.y, vpY); + vpInvalid = false; + } - bool eq1 = (pt1.z() / pt1.w()) == 1.f; - bool eq2 = (pt2.z() / pt2.w()) == 1.f; - if (eq1 == eq2) - continue; + zeus::CVector2i vpSize = {vpMax.x - vpMin.x, vpMax.y - vpMin.y}; + if (vpSize.x <= 0 || vpSize.y <= 0) + return; - float interp = -(pt1.w() - 1.f) / (pt2.w() - pt1.w()); - if (interp <= 0.f || interp >= 1.f) - continue; + SClipScreenRect rect = {}; + rect.x4_left = vpMin.x; + rect.x8_top = vpMin.y; + rect.xc_width = vpSize.x; + rect.x10_height = vpSize.y; - float wRecip = 1.f / (interp * (pt2.w() - pt1.w()) + pt1.w()); - zeus::CVector3f pt1_3 = pt1.toVec3f(); - zeus::CVector3f pt2_3 = pt2.toVec3f(); - overW = (pt1_3 + interp * (pt2_3 - pt1_3)) * wRecip; - } + rect.x4_left = 0; + rect.x8_top = 0; + rect.xc_width = g_Viewport.x8_width; + rect.x10_height = g_Viewport.xc_height; - //if (overW.z > 1.001f) - // continue; + // CGraphics::SetScissor(vpMin.x, vpMin.y, vpSize.x, vpSize.y); + zeus::CAABox marginAABB((CGraphics::g_GXModelView * aabb.min) - 1.f, (CGraphics::g_GXModelView * aabb.max) + 1.f); + bool camInModel = marginAABB.pointInside(CGraphics::g_ViewMatrix.origin) && (model || sModel); - int vpX = zeus::clamp(0, int(g_Viewport.x8_width * overW.x() * 0.5f + (g_Viewport.x8_width / 2)), int(g_Viewport.x8_width)); - int vpY = zeus::clamp(0, int(g_Viewport.xc_height * overW.y() * 0.5f + (g_Viewport.xc_height / 2)), int(g_Viewport.xc_height)); - vpMax.x = std::max(vpMax.x, vpX); - vpMin.x = std::min(vpMin.x, vpX); - vpMax.y = std::max(vpMax.y, vpY); - vpMin.y = std::min(vpMin.y, vpY); - vpInvalid = false; - } + CFogVolumePlaneShader* fvs; + if (!model && !sModel) { + fvs = &*((m_nextFogVolumePlaneShader == m_fogVolumePlaneShaders.end()) + ? m_fogVolumePlaneShaders.insert(m_fogVolumePlaneShaders.end(), CFogVolumePlaneShader()) + : m_nextFogVolumePlaneShader++); + } else { + fvs = nullptr; + } - zeus::CVector2i vpSize = {vpMax.x - vpMin.x, vpMax.y - vpMin.y}; - if (vpSize.x <= 0 || vpSize.y <= 0) - return; + RenderFogVolumeModel(aabb, model, CGraphics::g_GXModelMatrix, CGraphics::g_ViewMatrix, sModel, 0, fvs); + if (camInModel) + RenderFogVolumeModel(aabb, model, CGraphics::g_GXModelMatrix, CGraphics::g_ViewMatrix, sModel, 1, fvs); - SClipScreenRect rect = {}; - rect.x4_left = vpMin.x; - rect.x8_top = vpMin.y; - rect.xc_width = vpSize.x; - rect.x10_height = vpSize.y; - - rect.x4_left = 0; - rect.x8_top = 0; - rect.xc_width = g_Viewport.x8_width; - rect.x10_height = g_Viewport.xc_height; - - //CGraphics::SetScissor(vpMin.x, vpMin.y, vpSize.x, vpSize.y); - zeus::CAABox marginAABB((CGraphics::g_GXModelView * aabb.min) - 1.f, - (CGraphics::g_GXModelView * aabb.max) + 1.f); - bool camInModel = marginAABB.pointInside(CGraphics::g_ViewMatrix.origin) && (model || sModel); + CGraphics::ResolveSpareDepth(rect, 0); - CFogVolumePlaneShader* fvs; - if (!model && !sModel) - { - fvs = &*((m_nextFogVolumePlaneShader == m_fogVolumePlaneShaders.end()) ? - m_fogVolumePlaneShaders.insert(m_fogVolumePlaneShaders.end(), CFogVolumePlaneShader()) : - m_nextFogVolumePlaneShader++); - } - else - { - fvs = nullptr; - } + RenderFogVolumeModel(aabb, model, CGraphics::g_GXModelMatrix, CGraphics::g_ViewMatrix, sModel, 2, fvs); + if (camInModel) + RenderFogVolumeModel(aabb, model, CGraphics::g_GXModelMatrix, CGraphics::g_ViewMatrix, sModel, 3, fvs); - RenderFogVolumeModel(aabb, model, CGraphics::g_GXModelMatrix, CGraphics::g_ViewMatrix, sModel, 0, fvs); - if (camInModel) - RenderFogVolumeModel(aabb, model, CGraphics::g_GXModelMatrix, CGraphics::g_ViewMatrix, sModel, 1, fvs); + CGraphics::ResolveSpareDepth(rect, 1); - CGraphics::ResolveSpareDepth(rect, 0); + auto fvf = (m_nextFogVolumeFilter == m_fogVolumeFilters.end()) + ? m_fogVolumeFilters.insert(m_fogVolumeFilters.end(), CFogVolumeFilter()) + : m_nextFogVolumeFilter++; + fvf->draw2WayPass(color); + if (camInModel) + fvf->draw1WayPass(color); - RenderFogVolumeModel(aabb, model, CGraphics::g_GXModelMatrix, CGraphics::g_ViewMatrix, sModel, 2, fvs); - if (camInModel) - RenderFogVolumeModel(aabb, model, CGraphics::g_GXModelMatrix, CGraphics::g_ViewMatrix, sModel, 3, fvs); - - CGraphics::ResolveSpareDepth(rect, 1); - - auto fvf = (m_nextFogVolumeFilter == m_fogVolumeFilters.end()) ? - m_fogVolumeFilters.insert(m_fogVolumeFilters.end(), CFogVolumeFilter()) : - m_nextFogVolumeFilter++; - fvf->draw2WayPass(color); - if (camInModel) - fvf->draw1WayPass(color); - - //CGraphics::SetScissor(g_Viewport.x0_left, g_Viewport.x4_top, g_Viewport.x8_width, g_Viewport.xc_height); + // CGraphics::SetScissor(g_Viewport.x0_left, g_Viewport.x4_top, g_Viewport.x8_width, g_Viewport.xc_height); } -void CBooRenderer::GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context& ctx) -{ - u16 data[FOGVOL_RAMP_RES][FOGVOL_RAMP_RES] = {}; - for (int y=0 ; y verts; - verts.reserve(670); +void CBooRenderer::GenerateScanLinesVBO(boo::IGraphicsDataFactory::Context& ctx) { + std::vector verts; + verts.reserve(670); - for (int i=0 ; i<112 ; ++i) - { - verts.push_back(zeus::CVector3f(-1.f, (i * (4.f / 448.f) + (1.f / 448.f)) * 2.f - 1.f, 0.f)); - if (i != 0) - verts.push_back(verts.back()); - verts.push_back(zeus::CVector3f(-1.f, (i * (4.f / 448.f) - (1.f / 448.f)) * 2.f - 1.f, 0.f)); - verts.push_back(zeus::CVector3f( 1.f, (i * (4.f / 448.f) + (1.f / 448.f)) * 2.f - 1.f, 0.f)); - verts.push_back(zeus::CVector3f( 1.f, (i * (4.f / 448.f) - (1.f / 448.f)) * 2.f - 1.f, 0.f)); - if (i != 111) - verts.push_back(verts.back()); - } + for (int i = 0; i < 112; ++i) { + verts.push_back(zeus::CVector3f(-1.f, (i * (4.f / 448.f) + (1.f / 448.f)) * 2.f - 1.f, 0.f)); + if (i != 0) + verts.push_back(verts.back()); + verts.push_back(zeus::CVector3f(-1.f, (i * (4.f / 448.f) - (1.f / 448.f)) * 2.f - 1.f, 0.f)); + verts.push_back(zeus::CVector3f(1.f, (i * (4.f / 448.f) + (1.f / 448.f)) * 2.f - 1.f, 0.f)); + verts.push_back(zeus::CVector3f(1.f, (i * (4.f / 448.f) - (1.f / 448.f)) * 2.f - 1.f, 0.f)); + if (i != 111) + verts.push_back(verts.back()); + } - m_scanLinesEvenVBO = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), - sizeof(zeus::CVector3f), verts.size()); + m_scanLinesEvenVBO = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), sizeof(zeus::CVector3f), verts.size()); - verts.clear(); + verts.clear(); - for (int i=0 ; i<112 ; ++i) - { - verts.push_back(zeus::CVector3f(-1.f, (i * (4.f / 448.f) + (3.f / 448.f)) * 2.f - 1.f, 0.f)); - if (i != 0) - verts.push_back(verts.back()); - verts.push_back(zeus::CVector3f(-1.f, (i * (4.f / 448.f) + (1.f / 448.f)) * 2.f - 1.f, 0.f)); - verts.push_back(zeus::CVector3f( 1.f, (i * (4.f / 448.f) + (3.f / 448.f)) * 2.f - 1.f, 0.f)); - verts.push_back(zeus::CVector3f( 1.f, (i * (4.f / 448.f) + (1.f / 448.f)) * 2.f - 1.f, 0.f)); - if (i != 111) - verts.push_back(verts.back()); - } + for (int i = 0; i < 112; ++i) { + verts.push_back(zeus::CVector3f(-1.f, (i * (4.f / 448.f) + (3.f / 448.f)) * 2.f - 1.f, 0.f)); + if (i != 0) + verts.push_back(verts.back()); + verts.push_back(zeus::CVector3f(-1.f, (i * (4.f / 448.f) + (1.f / 448.f)) * 2.f - 1.f, 0.f)); + verts.push_back(zeus::CVector3f(1.f, (i * (4.f / 448.f) + (3.f / 448.f)) * 2.f - 1.f, 0.f)); + verts.push_back(zeus::CVector3f(1.f, (i * (4.f / 448.f) + (1.f / 448.f)) * 2.f - 1.f, 0.f)); + if (i != 111) + verts.push_back(verts.back()); + } - m_scanLinesOddVBO = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), - sizeof(zeus::CVector3f), verts.size()); + m_scanLinesOddVBO = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts.data(), sizeof(zeus::CVector3f), verts.size()); } -void CBooRenderer::LoadThermoPalette() -{ - m_thermoPaletteTex = xc_store.GetObj("TXTR_ThermoPalette"); - CTexture* thermoTexObj = m_thermoPaletteTex.GetObj(); - if (thermoTexObj) - x288_thermoPalette = thermoTexObj->GetPaletteTexture(); +void CBooRenderer::LoadThermoPalette() { + m_thermoPaletteTex = xc_store.GetObj("TXTR_ThermoPalette"); + CTexture* thermoTexObj = m_thermoPaletteTex.GetObj(); + if (thermoTexObj) + x288_thermoPalette = thermoTexObj->GetPaletteTexture(); } -void CBooRenderer::LoadBallFade() -{ - m_ballFadeTex = xc_store.GetObj("TXTR_BallFade"); - CTexture* ballFadeTexObj = m_ballFadeTex.GetObj(); - if (ballFadeTexObj) - m_ballFade = ballFadeTexObj->GetBooTexture(); +void CBooRenderer::LoadBallFade() { + m_ballFadeTex = xc_store.GetObj("TXTR_BallFade"); + CTexture* ballFadeTexObj = m_ballFadeTex.GetObj(); + if (ballFadeTexObj) + m_ballFade = ballFadeTexObj->GetBooTexture(); } CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac) -: x8_factory(resFac), xc_store(store), x2a8_thermalRand(20) -{ - g_Renderer = this; - xee_24_ = true; +: x8_factory(resFac), xc_store(store), x2a8_thermalRand(20) { + g_Renderer = this; + xee_24_ = true; - m_staticEntropy = store.GetObj("RandomStaticEntropy"); + m_staticEntropy = store.GetObj("RandomStaticEntropy"); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - GenerateFogVolumeRampTex(ctx); - GenerateSphereRampTex(ctx); - m_ballShadowId = ctx.newRenderTexture(m_ballShadowIdW, m_ballShadowIdH, boo::TextureClampMode::Repeat, 1, 0); - x14c_reflectionTex = ctx.newRenderTexture(256, 256, boo::TextureClampMode::ClampToBlack, 1, 0); - GenerateScanLinesVBO(ctx); - return true; - } BooTrace); - LoadThermoPalette(); - LoadBallFade(); - m_thermHotFilter.emplace(); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + GenerateFogVolumeRampTex(ctx); + GenerateSphereRampTex(ctx); + m_ballShadowId = ctx.newRenderTexture(m_ballShadowIdW, m_ballShadowIdH, boo::TextureClampMode::Repeat, 1, 0); + x14c_reflectionTex = ctx.newRenderTexture(256, 256, boo::TextureClampMode::ClampToBlack, 1, 0); + GenerateScanLinesVBO(ctx); + return true; + } BooTrace); + LoadThermoPalette(); + LoadBallFade(); + m_thermHotFilter.emplace(); - Buckets::Init(); + Buckets::Init(); - m_nextFogVolumePlaneShader = m_fogVolumePlaneShaders.end(); - m_nextFogVolumeFilter = m_fogVolumeFilters.end(); + m_nextFogVolumePlaneShader = m_fogVolumePlaneShaders.end(); + m_nextFogVolumeFilter = m_fogVolumeFilters.end(); } -CBooRenderer::~CBooRenderer() -{ - g_Renderer = nullptr; -} +CBooRenderer::~CBooRenderer() { g_Renderer = nullptr; } -void CBooRenderer::AddWorldSurfaces(CBooModel& model) -{ - CBooSurface* surf = model.x3c_firstSortedSurface; - while (surf) - { - const MaterialSet::Material& mat = model.GetMaterialByIndex(surf->m_data.matIdx); - zeus::CAABox aabb = surf->GetBounds(); - zeus::CVector3f pt = aabb.closestPointAlongVector(xb0_viewPlane.normal()); - Buckets::Insert(pt, aabb, EDrawableType::WorldSurface, surf, xb0_viewPlane, - mat.heclIr.m_blendSrc == boo::BlendFactor::SrcAlpha && +void CBooRenderer::AddWorldSurfaces(CBooModel& model) { + CBooSurface* surf = model.x3c_firstSortedSurface; + while (surf) { + const MaterialSet::Material& mat = model.GetMaterialByIndex(surf->m_data.matIdx); + zeus::CAABox aabb = surf->GetBounds(); + zeus::CVector3f pt = aabb.closestPointAlongVector(xb0_viewPlane.normal()); + Buckets::Insert(pt, aabb, EDrawableType::WorldSurface, surf, xb0_viewPlane, + mat.heclIr.m_blendSrc == boo::BlendFactor::SrcAlpha && mat.heclIr.m_blendDst == boo::BlendFactor::InvSrcAlpha); - surf = surf->m_next; - } + surf = surf->m_next; + } } std::list::iterator -CBooRenderer::FindStaticGeometry(const std::vector* geometry) -{ - return std::find_if(x1c_areaListItems.begin(), x1c_areaListItems.end(), - [&](CAreaListItem& item) -> bool {return item.x0_geometry == geometry;}); +CBooRenderer::FindStaticGeometry(const std::vector* geometry) { + return std::find_if(x1c_areaListItems.begin(), x1c_areaListItems.end(), + [&](CAreaListItem& item) -> bool { return item.x0_geometry == geometry; }); } void CBooRenderer::AddStaticGeometry(const std::vector* geometry, - const CAreaRenderOctTree* octTree, int areaIdx, - const SShader* shaderSet) -{ - auto search = FindStaticGeometry(geometry); - if (search == x1c_areaListItems.end()) - { - std::vector> textures; - std::vector models; - if (geometry->size()) - { - (*geometry)[0].m_instance->MakeTexturesFromMats(textures, xc_store); - models.reserve(geometry->size()); - int instIdx = 0; - for (const CMetroidModelInstance& inst : *geometry) - { - models.push_back(inst.m_instance.get()); - models.back()->x44_areaInstanceIdx = instIdx++; - } + const CAreaRenderOctTree* octTree, int areaIdx, const SShader* shaderSet) { + auto search = FindStaticGeometry(geometry); + if (search == x1c_areaListItems.end()) { + std::vector> textures; + std::vector models; + if (geometry->size()) { + (*geometry)[0].m_instance->MakeTexturesFromMats(textures, xc_store); + models.reserve(geometry->size()); + int instIdx = 0; + for (const CMetroidModelInstance& inst : *geometry) { + models.push_back(inst.m_instance.get()); + models.back()->x44_areaInstanceIdx = instIdx++; + } + } + x1c_areaListItems.emplace_back(geometry, octTree, std::move(textures), std::move(models), areaIdx, shaderSet); + } +} + +void CBooRenderer::EnablePVS(const CPVSVisSet& set, u32 areaIdx) { + xc8_pvs.emplace(set); + xe0_pvsAreaIdx = areaIdx; +} + +void CBooRenderer::DisablePVS() { xc8_pvs = std::experimental::nullopt; } + +void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activateLights) { + SetupRendererStates(); + + CModelFlags flags; + int bufIdx; + if (shadowRender) { + flags.m_extendedShader = EExtendedShader::SolidColor; + flags.x4_color = zeus::CColor::skBlack; + bufIdx = 1; + } else { + flags.m_extendedShader = EExtendedShader::Lighting; + bufIdx = 0; + } + + for (CAreaListItem& item : x1c_areaListItems) { + if (areaIdx != -1 && item.x18_areaIdx != areaIdx) + continue; + + item.m_shaderSet->m_geomLayout->Update(flags, nullptr, nullptr, &item.m_shaderSet->m_matSet, + item.m_shaderSet->m_geomLayout->m_sharedBuffer[bufIdx], nullptr); + + for (auto it = item.x10_models.begin(); it != item.x10_models.end(); ++it) { + CBooModel* model = *it; + if (model->TryLockTextures()) { + if (activateLights) + ActivateLightsForModel(&item, *model); + model->UpdateUniformData(flags, nullptr, nullptr, bufIdx); + } + } + } +} + +void CBooRenderer::RemoveStaticGeometry(const std::vector* geometry) { + auto search = FindStaticGeometry(geometry); + if (search != x1c_areaListItems.end()) + x1c_areaListItems.erase(search); +} + +void CBooRenderer::DrawAreaGeometry(int areaIdx, int mask, int targetMask) { + x318_30_inAreaDraw = true; + // SetupRendererStates(); + CModelFlags flags; + + for (CAreaListItem& item : x1c_areaListItems) { + if (areaIdx != -1 || item.x18_areaIdx == areaIdx) { + CPVSVisSet* pvs = xc8_pvs ? &*xc8_pvs : nullptr; + if (xe0_pvsAreaIdx != item.x18_areaIdx) + pvs = nullptr; + int modelIdx = 0; + for (auto it = item.x10_models.begin(); it != item.x10_models.end(); ++it, ++modelIdx) { + CBooModel* model = *it; + if (pvs) { + bool visible = pvs->GetVisible(modelIdx) != EPVSVisSetState::EndOfTree; + if ((xc4_pvsMode == EPVSMode::PVS && !visible) || (xc4_pvsMode == EPVSMode::PVSAndMask && visible)) + continue; } - x1c_areaListItems.emplace_back(geometry, octTree, std::move(textures), std::move(models), areaIdx, shaderSet); + if ((model->x41_mask & mask) != targetMask) + continue; + if (!x44_frustumPlanes.aabbFrustumTest(model->x20_aabb)) + continue; + + for (const CBooSurface* surf = model->x38_firstUnsortedSurface; surf; surf = surf->m_next) + model->DrawSurface(*surf, flags); + for (const CBooSurface* surf = model->x3c_firstSortedSurface; surf; surf = surf->m_next) + model->DrawSurface(*surf, flags); + } } + } + + x318_30_inAreaDraw = false; } -void CBooRenderer::EnablePVS(const CPVSVisSet& set, u32 areaIdx) -{ - xc8_pvs.emplace(set); - xe0_pvsAreaIdx = areaIdx; -} +void CBooRenderer::DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender) { + // SetupRendererStates(); + CModelFlags flags; + flags.m_extendedShader = shadowRender ? EExtendedShader::SolidColor : EExtendedShader::Lighting; -void CBooRenderer::DisablePVS() -{ - xc8_pvs = std::experimental::nullopt; -} + CAreaListItem* lastOctreeItem = nullptr; -void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activateLights) -{ - SetupRendererStates(); + for (CAreaListItem& item : x1c_areaListItems) { + if (areaIdx != -1 && item.x18_areaIdx != areaIdx) + continue; - CModelFlags flags; - int bufIdx; - if (shadowRender) - { - flags.m_extendedShader = EExtendedShader::SolidColor; - flags.x4_color = zeus::CColor::skBlack; - bufIdx = 1; + if (item.x4_octTree) + lastOctreeItem = &item; + + CPVSVisSet* pvs = nullptr; + if (xc8_pvs) + pvs = &*xc8_pvs; + if (xe0_pvsAreaIdx != item.x18_areaIdx) + pvs = nullptr; + + u32 idx = 0; + for (auto it = item.x10_models.begin(); it != item.x10_models.end(); ++it, ++idx) { + CBooModel* model = *it; + if (pvs) { + bool vis = pvs->GetVisible(idx) != EPVSVisSetState::EndOfTree; + switch (xc4_pvsMode) { + case EPVSMode::PVS: { + if (!vis) { + model->x40_25_modelVisible = false; + continue; + } + break; + } + case EPVSMode::PVSAndMask: { + if (!vis && (model->x41_mask & mask) != targetMask) { + model->x40_25_modelVisible = false; + continue; + } + } + default: + break; + } + } + + if ((model->x41_mask & mask) != targetMask) { + model->x40_25_modelVisible = false; + continue; + } + + if (!x44_frustumPlanes.aabbFrustumTest(model->x20_aabb)) { + model->x40_25_modelVisible = false; + continue; + } + + if (x318_25_drawWireframe) { + model->x40_25_modelVisible = false; + // HandleUnsortedModelWireframe(); + continue; + } + + model->x40_25_modelVisible = true; + HandleUnsortedModel(lastOctreeItem, *model, flags); } + } + + // SetupCGraphicsStates(); +} + +void CBooRenderer::DrawSortedGeometry(int areaIdx, int mask, int targetMask) { + // SetupRendererStates(); + + CAreaListItem* lastOctreeItem = nullptr; + + for (CAreaListItem& item : x1c_areaListItems) { + if (areaIdx != -1 && item.x18_areaIdx != areaIdx) + continue; + + if (item.x4_octTree) + lastOctreeItem = &item; + + for (auto it = item.x10_models.begin(); it != item.x10_models.end(); ++it) { + CBooModel* model = *it; + if (model->x40_25_modelVisible) + AddWorldSurfaces(*model); + } + } + + Buckets::Sort(); + RenderBucketItems(lastOctreeItem); + + // SetupCGraphicsStates(); + // DrawRenderBucketsDebug(); + Buckets::Clear(); +} + +void CBooRenderer::DrawStaticGeometry(int modelCount, int mask, int targetMask) { + DrawUnsortedGeometry(modelCount, mask, targetMask); + DrawSortedGeometry(modelCount, mask, targetMask); +} + +void CBooRenderer::DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) { + model.GetInstance().DrawFlat(unsortedOnly ? CBooModel::ESurfaceSelection::UnsortedOnly + : CBooModel::ESurfaceSelection::All, + flags.m_extendedShader); +} + +void CBooRenderer::PostRenderFogs() { + for (const auto& warp : x2c4_spaceWarps) + DrawSpaceWarp(warp.first, warp.second); + x2c4_spaceWarps.clear(); + + x2ac_fogVolumes.sort([](const CFogVolumeListItem& a, const CFogVolumeListItem& b) { + zeus::CAABox aabbA = a.x34_aabb.getTransformedAABox(a.x0_transform); + bool insideA = + aabbA.pointInside(zeus::CVector3f(CGraphics::g_ViewPoint.x(), CGraphics::g_ViewPoint.y(), aabbA.min.z())); + + zeus::CAABox aabbB = b.x34_aabb.getTransformedAABox(b.x0_transform); + bool insideB = + aabbB.pointInside(zeus::CVector3f(CGraphics::g_ViewPoint.x(), CGraphics::g_ViewPoint.y(), aabbB.min.z())); + + if (insideA != insideB) + return insideA; + + float dotA = aabbA.furthestPointAlongVector(CGraphics::g_ViewMatrix.basis[1]).dot(CGraphics::g_ViewMatrix.basis[1]); + float dotB = aabbB.furthestPointAlongVector(CGraphics::g_ViewMatrix.basis[1]).dot(CGraphics::g_ViewMatrix.basis[1]); + return dotA < dotB; + }); + for (const CFogVolumeListItem& fog : x2ac_fogVolumes) { + CGraphics::SetModelMatrix(fog.x0_transform); + ReallyRenderFogVolume(fog.x30_color, fog.x34_aabb, fog.x4c_model.GetObj(), fog.x5c_skinnedModel); + } + x2ac_fogVolumes.clear(); +} + +void CBooRenderer::AddParticleGen(const CParticleGen& gen) { + if (auto bounds = gen.GetBounds()) { + zeus::CVector3f pt = bounds.value().closestPointAlongVector(xb0_viewPlane.normal()); + Buckets::Insert(pt, bounds.value(), EDrawableType::Particle, &gen, xb0_viewPlane, 0); + } +} + +void CBooRenderer::AddParticleGen(const CParticleGen& gen, const zeus::CVector3f& pos, const zeus::CAABox& bounds) { + Buckets::Insert(pos, bounds, EDrawableType::Particle, &gen, xb0_viewPlane, 0); +} + +void CBooRenderer::AddPlaneObject(const void* obj, const zeus::CAABox& aabb, const zeus::CPlane& plane, int type) { + zeus::CVector3f closePoint = aabb.closestPointAlongVector(xb0_viewPlane.normal()); + zeus::CVector3f farPoint = aabb.furthestPointAlongVector(xb0_viewPlane.normal()); + float closeDist = xb0_viewPlane.pointToPlaneDist(closePoint); + float farDist = xb0_viewPlane.pointToPlaneDist(farPoint); + if (closeDist >= 0.f || farDist >= 0.f) { + bool zOnly = plane.normal() == zeus::CVector3f::skUp; + bool invert; + if (zOnly) + invert = CGraphics::g_ViewMatrix.origin.z() >= plane.d(); else - { - flags.m_extendedShader = EExtendedShader::Lighting; - bufIdx = 0; - } - - for (CAreaListItem& item : x1c_areaListItems) - { - if (areaIdx != -1 && item.x18_areaIdx != areaIdx) - continue; - - item.m_shaderSet->m_geomLayout->Update(flags, nullptr, nullptr, &item.m_shaderSet->m_matSet, - item.m_shaderSet->m_geomLayout->m_sharedBuffer[bufIdx], nullptr); - - for (auto it = item.x10_models.begin(); it != item.x10_models.end(); ++it) - { - CBooModel* model = *it; - if (model->TryLockTextures()) - { - if (activateLights) - ActivateLightsForModel(&item, *model); - model->UpdateUniformData(flags, nullptr, nullptr, bufIdx); - } - } - } + invert = plane.pointToPlaneDist(CGraphics::g_ViewMatrix.origin) >= 0.f; + Buckets::InsertPlaneObject(closeDist, farDist, aabb, invert, plane, zOnly, EDrawableType(type + 2), obj); + } } -void CBooRenderer::RemoveStaticGeometry(const std::vector* geometry) -{ - auto search = FindStaticGeometry(geometry); - if (search != x1c_areaListItems.end()) - x1c_areaListItems.erase(search); +void CBooRenderer::AddDrawable(const void* obj, const zeus::CVector3f& pos, const zeus::CAABox& aabb, int mode, + EDrawableSorting sorting) { + if (sorting == EDrawableSorting::UnsortedCallback) + xa8_drawableCallback(obj, xac_callbackContext, mode); + else + Buckets::Insert(pos, aabb, EDrawableType(mode + 2), obj, xb0_viewPlane, 0); } -void CBooRenderer::DrawAreaGeometry(int areaIdx, int mask, int targetMask) -{ - x318_30_inAreaDraw = true; - //SetupRendererStates(); - CModelFlags flags; - - for (CAreaListItem& item : x1c_areaListItems) - { - if (areaIdx != -1 || item.x18_areaIdx == areaIdx) - { - CPVSVisSet* pvs = xc8_pvs ? &*xc8_pvs : nullptr; - if (xe0_pvsAreaIdx != item.x18_areaIdx) - pvs = nullptr; - int modelIdx = 0; - for (auto it = item.x10_models.begin() ; it != item.x10_models.end() ; ++it, ++modelIdx) - { - CBooModel* model = *it; - if (pvs) - { - bool visible = pvs->GetVisible(modelIdx) != EPVSVisSetState::EndOfTree; - if ((xc4_pvsMode == EPVSMode::PVS && !visible) || (xc4_pvsMode == EPVSMode::PVSAndMask && visible)) - continue; - } - if ((model->x41_mask & mask) != targetMask) - continue; - if (!x44_frustumPlanes.aabbFrustumTest(model->x20_aabb)) - continue; - - for (const CBooSurface* surf = model->x38_firstUnsortedSurface ; surf ; surf = surf->m_next) - model->DrawSurface(*surf, flags); - for (const CBooSurface* surf = model->x3c_firstSortedSurface ; surf ; surf = surf->m_next) - model->DrawSurface(*surf, flags); - } - } - } - - x318_30_inAreaDraw = false; +void CBooRenderer::SetDrawableCallback(TDrawableCallback cb, const void* ctx) { + xa8_drawableCallback = cb; + xac_callbackContext = ctx; } -void CBooRenderer::DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender) -{ - //SetupRendererStates(); - CModelFlags flags; - flags.m_extendedShader = shadowRender ? EExtendedShader::SolidColor : EExtendedShader::Lighting; - - CAreaListItem* lastOctreeItem = nullptr; - - for (CAreaListItem& item : x1c_areaListItems) - { - if (areaIdx != -1 && item.x18_areaIdx != areaIdx) - continue; - - if (item.x4_octTree) - lastOctreeItem = &item; - - CPVSVisSet* pvs = nullptr; - if (xc8_pvs) - pvs = &*xc8_pvs; - if (xe0_pvsAreaIdx != item.x18_areaIdx) - pvs = nullptr; - - u32 idx = 0; - for (auto it = item.x10_models.begin() ; it != item.x10_models.end() ; ++it, ++idx) - { - CBooModel* model = *it; - if (pvs) - { - bool vis = pvs->GetVisible(idx) != EPVSVisSetState::EndOfTree; - switch (xc4_pvsMode) - { - case EPVSMode::PVS: - { - if (!vis) - { - model->x40_25_modelVisible = false; - continue; - } - break; - } - case EPVSMode::PVSAndMask: - { - if (!vis && (model->x41_mask & mask) != targetMask) - { - model->x40_25_modelVisible = false; - continue; - } - } - default: break; - } - } - - if ((model->x41_mask & mask) != targetMask) - { - model->x40_25_modelVisible = false; - continue; - } - - if (!x44_frustumPlanes.aabbFrustumTest(model->x20_aabb)) - { - model->x40_25_modelVisible = false; - continue; - } - - if (x318_25_drawWireframe) - { - model->x40_25_modelVisible = false; - //HandleUnsortedModelWireframe(); - continue; - } - - model->x40_25_modelVisible = true; - HandleUnsortedModel(lastOctreeItem, *model, flags); - } - - } - - //SetupCGraphicsStates(); +void CBooRenderer::SetWorldViewpoint(const zeus::CTransform& xf) { + CGraphics::SetViewPointMatrix(xf); + xb0_viewPlane = zeus::CPlane(xf.basis[1], xf.basis[1].dot(xf.origin)); } -void CBooRenderer::DrawSortedGeometry(int areaIdx, int mask, int targetMask) -{ - //SetupRendererStates(); - - CAreaListItem* lastOctreeItem = nullptr; - - for (CAreaListItem& item : x1c_areaListItems) - { - if (areaIdx != -1 && item.x18_areaIdx != areaIdx) - continue; - - if (item.x4_octTree) - lastOctreeItem = &item; - - for (auto it = item.x10_models.begin() ; it != item.x10_models.end() ; ++it) - { - CBooModel* model = *it; - if (model->x40_25_modelVisible) - AddWorldSurfaces(*model); - } - } - - Buckets::Sort(); - RenderBucketItems(lastOctreeItem); - - //SetupCGraphicsStates(); - //DrawRenderBucketsDebug(); - Buckets::Clear(); +void CBooRenderer::SetPerspective(float fovy, float width, float height, float znear, float zfar) { + CGraphics::SetPerspective(fovy, width / height, znear, zfar); } -void CBooRenderer::DrawStaticGeometry(int modelCount, int mask, int targetMask) -{ - DrawUnsortedGeometry(modelCount, mask, targetMask); - DrawSortedGeometry(modelCount, mask, targetMask); +void CBooRenderer::SetPerspective(float fovy, float aspect, float znear, float zfar) { + CGraphics::SetPerspective(fovy, aspect, znear, zfar); } -void CBooRenderer::DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) -{ - model.GetInstance().DrawFlat(unsortedOnly ? - CBooModel::ESurfaceSelection::UnsortedOnly : - CBooModel::ESurfaceSelection::All, - flags.m_extendedShader); +std::pair CBooRenderer::SetViewportOrtho(bool centered, float znear, float zfar) { + float left = centered ? g_Viewport.x0_left - g_Viewport.x10_halfWidth : 0.f; + float bottom = centered ? g_Viewport.x4_top - g_Viewport.x14_halfHeight : 0.f; + float top = centered ? g_Viewport.x0_left + g_Viewport.x14_halfHeight : g_Viewport.xc_height; + float right = centered ? g_Viewport.x4_top + g_Viewport.x10_halfWidth : g_Viewport.x8_width; + + CGraphics::SetOrtho(left, right, top, bottom, znear, zfar); + CGraphics::SetViewPointMatrix(zeus::CTransform::Identity()); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + + return {{left, bottom}, {right, top}}; } -void CBooRenderer::PostRenderFogs() -{ - for (const auto& warp : x2c4_spaceWarps) - DrawSpaceWarp(warp.first, warp.second); - x2c4_spaceWarps.clear(); +void CBooRenderer::SetClippingPlanes(const zeus::CFrustum& frustum) { x44_frustumPlanes = frustum; } - x2ac_fogVolumes.sort([](const CFogVolumeListItem& a, const CFogVolumeListItem& b) - { - zeus::CAABox aabbA = a.x34_aabb.getTransformedAABox(a.x0_transform); - bool insideA = aabbA.pointInside( - zeus::CVector3f(CGraphics::g_ViewPoint.x(), CGraphics::g_ViewPoint.y(), aabbA.min.z())); - - zeus::CAABox aabbB = b.x34_aabb.getTransformedAABox(b.x0_transform); - bool insideB = aabbB.pointInside( - zeus::CVector3f(CGraphics::g_ViewPoint.x(), CGraphics::g_ViewPoint.y(), aabbB.min.z())); - - if (insideA != insideB) - return insideA; - - float dotA = aabbA.furthestPointAlongVector( - CGraphics::g_ViewMatrix.basis[1]).dot(CGraphics::g_ViewMatrix.basis[1]); - float dotB = aabbB.furthestPointAlongVector( - CGraphics::g_ViewMatrix.basis[1]).dot(CGraphics::g_ViewMatrix.basis[1]); - return dotA < dotB; - }); - for (const CFogVolumeListItem& fog : x2ac_fogVolumes) - { - CGraphics::SetModelMatrix(fog.x0_transform); - ReallyRenderFogVolume(fog.x30_color, fog.x34_aabb, fog.x4c_model.GetObj(), fog.x5c_skinnedModel); - } - x2ac_fogVolumes.clear(); +void CBooRenderer::SetViewport(int l, int b, int w, int h) { + CGraphics::SetViewport(l, b, w, h); + CGraphics::SetScissor(l, b, w, h); } -void CBooRenderer::AddParticleGen(const CParticleGen& gen) -{ - if (auto bounds = gen.GetBounds()) - { - zeus::CVector3f pt = bounds.value().closestPointAlongVector(xb0_viewPlane.normal()); - Buckets::Insert(pt, bounds.value(), EDrawableType::Particle, &gen, xb0_viewPlane, 0); - } -} +void CBooRenderer::SetDebugOption(EDebugOption, int) {} -void CBooRenderer::AddParticleGen(const CParticleGen& gen, const zeus::CVector3f& pos, const zeus::CAABox& bounds) -{ - Buckets::Insert(pos, bounds, EDrawableType::Particle, &gen, xb0_viewPlane, 0); -} - -void CBooRenderer::AddPlaneObject(const void* obj, const zeus::CAABox& aabb, const zeus::CPlane& plane, int type) -{ - zeus::CVector3f closePoint = aabb.closestPointAlongVector(xb0_viewPlane.normal()); - zeus::CVector3f farPoint = aabb.furthestPointAlongVector(xb0_viewPlane.normal()); - float closeDist = xb0_viewPlane.pointToPlaneDist(closePoint); - float farDist = xb0_viewPlane.pointToPlaneDist(farPoint); - if (closeDist >= 0.f || farDist >= 0.f) - { - bool zOnly = plane.normal() == zeus::CVector3f::skUp; - bool invert; - if (zOnly) - invert = CGraphics::g_ViewMatrix.origin.z() >= plane.d(); - else - invert = plane.pointToPlaneDist(CGraphics::g_ViewMatrix.origin) >= 0.f; - Buckets::InsertPlaneObject(closeDist, farDist, aabb, invert, plane, zOnly, EDrawableType(type + 2), obj); - } -} - -void CBooRenderer::AddDrawable(const void* obj, const zeus::CVector3f& pos, const zeus::CAABox& aabb, - int mode, EDrawableSorting sorting) -{ - if (sorting == EDrawableSorting::UnsortedCallback) - xa8_drawableCallback(obj, xac_callbackContext, mode); - else - Buckets::Insert(pos, aabb, EDrawableType(mode + 2), obj, xb0_viewPlane, 0); -} - -void CBooRenderer::SetDrawableCallback(TDrawableCallback cb, const void* ctx) -{ - xa8_drawableCallback = cb; - xac_callbackContext = ctx; -} - -void CBooRenderer::SetWorldViewpoint(const zeus::CTransform& xf) -{ - CGraphics::SetViewPointMatrix(xf); - xb0_viewPlane = zeus::CPlane(xf.basis[1], xf.basis[1].dot(xf.origin)); -} - -void CBooRenderer::SetPerspective(float fovy, float width, float height, float znear, float zfar) -{ - CGraphics::SetPerspective(fovy, width / height, znear, zfar); -} - -void CBooRenderer::SetPerspective(float fovy, float aspect, float znear, float zfar) -{ - CGraphics::SetPerspective(fovy, aspect, znear, zfar); -} - -std::pair -CBooRenderer::SetViewportOrtho(bool centered, float znear, float zfar) -{ - float left = centered ? g_Viewport.x0_left - g_Viewport.x10_halfWidth : 0.f; - float bottom = centered ? g_Viewport.x4_top - g_Viewport.x14_halfHeight : 0.f; - float top = centered ? g_Viewport.x0_left + g_Viewport.x14_halfHeight : g_Viewport.xc_height; - float right = centered ? g_Viewport.x4_top + g_Viewport.x10_halfWidth : g_Viewport.x8_width; - - CGraphics::SetOrtho(left, right, top, bottom, znear, zfar); - CGraphics::SetViewPointMatrix(zeus::CTransform::Identity()); - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - - return {{left, bottom}, {right, top}}; -} - -void CBooRenderer::SetClippingPlanes(const zeus::CFrustum& frustum) -{ - x44_frustumPlanes = frustum; -} - -void CBooRenderer::SetViewport(int l, int b, int w, int h) -{ - CGraphics::SetViewport(l, b, w, h); - CGraphics::SetScissor(l, b, w, h); -} - -void CBooRenderer::SetDebugOption(EDebugOption, int) -{ -} - -void CBooRenderer::BeginScene() -{ - CGraphics::SetViewport(0, 0, g_Viewport.x8_width, g_Viewport.xc_height); - CGraphics::SetPerspective(75.f, CGraphics::g_ProjAspect, 1.f, 4096.f); - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); +void CBooRenderer::BeginScene() { + CGraphics::SetViewport(0, 0, g_Viewport.x8_width, g_Viewport.xc_height); + CGraphics::SetPerspective(75.f, CGraphics::g_ProjAspect, 1.f, 4096.f); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); #if 0 if (x310_phazonSuitMaskCountdown != 0) { @@ -1156,383 +972,315 @@ void CBooRenderer::BeginScene() x314_phazonSuitMask.reset(); } #endif - x318_27_currentRGBA6 = x318_26_requestRGBA6; - if (!x318_31_persistRGBA6) - x318_26_requestRGBA6 = false; - //GXSetPixelFmt(x318_27_currentRGBA6); - CGraphics::BeginScene(); - m_nextFogVolumePlaneShader = m_fogVolumePlaneShaders.begin(); - m_nextFogVolumeFilter = m_fogVolumeFilters.begin(); + x318_27_currentRGBA6 = x318_26_requestRGBA6; + if (!x318_31_persistRGBA6) + x318_26_requestRGBA6 = false; + // GXSetPixelFmt(x318_27_currentRGBA6); + CGraphics::BeginScene(); + m_nextFogVolumePlaneShader = m_fogVolumePlaneShaders.begin(); + m_nextFogVolumeFilter = m_fogVolumeFilters.begin(); } -void CBooRenderer::EndScene() -{ - CGraphics::EndScene(); - if (x2dc_reflectionAge >= 2) - { - // Delete reflection tex x14c_ - } - else - { - ++x2dc_reflectionAge; - } +void CBooRenderer::EndScene() { + CGraphics::EndScene(); + if (x2dc_reflectionAge >= 2) { + // Delete reflection tex x14c_ + } else { + ++x2dc_reflectionAge; + } } -void CBooRenderer::SetAmbientColor(const zeus::CColor& color) -{ - CGraphics::SetAmbientColor(color); +void CBooRenderer::SetAmbientColor(const zeus::CColor& color) { CGraphics::SetAmbientColor(color); } + +void CBooRenderer::DrawString(const char*, int, int) {} + +u32 CBooRenderer::GetFPS() { return 0; } + +void CBooRenderer::CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) { + if (!x318_24_refectionDirty) + return; + x318_24_refectionDirty = false; + x2dc_reflectionAge = 0; + + BindReflectionDrawTarget(); + SViewport backupVp = g_Viewport; + SetViewport(0, 0, 256, 256); + CGraphics::g_BooMainCommandQueue->clearTarget(); + cb(ctx, CBooModel::g_ReflectViewPos); + boo::SWindowRect rect(0, 0, 256, 256); + CGraphics::g_BooMainCommandQueue->resolveBindTexture(x14c_reflectionTex, rect, false, 0, true, false); + BindMainDrawTarget(); + SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height); } -void CBooRenderer::DrawString(const char*, int, int) -{ +void CBooRenderer::DrawSpaceWarp(const zeus::CVector3f& pt, float strength) { + m_spaceWarpFilter.setStrength(strength); + m_spaceWarpFilter.draw(pt); } -u32 CBooRenderer::GetFPS() -{ - return 0; +void CBooRenderer::DrawThermalModel(const CModel& model, const zeus::CColor& mulCol, const zeus::CColor& addCol) { + CModelFlags flags; + flags.m_extendedShader = EExtendedShader::Thermal; + flags.x4_color = mulCol; + flags.addColor = addCol; + model.UpdateLastFrame(); + model.Draw(flags); } -void CBooRenderer::CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) -{ - if (!x318_24_refectionDirty) - return; - x318_24_refectionDirty = false; - x2dc_reflectionAge = 0; +void CBooRenderer::DrawXRayOutline(const zeus::CAABox& aabb) { + CModelFlags flags; + flags.m_extendedShader = EExtendedShader::ForcedAlpha; - BindReflectionDrawTarget(); - SViewport backupVp = g_Viewport; - SetViewport(0, 0, 256, 256); - CGraphics::g_BooMainCommandQueue->clearTarget(); - cb(ctx, CBooModel::g_ReflectViewPos); - boo::SWindowRect rect(0, 0, 256, 256); - CGraphics::g_BooMainCommandQueue->resolveBindTexture(x14c_reflectionTex, rect, false, 0, true, false); - BindMainDrawTarget(); - SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height); -} + for (CAreaListItem& item : x1c_areaListItems) { + if (item.x4_octTree) { + std::vector bitmap; + item.x4_octTree->FindOverlappingModels(bitmap, aabb); -void CBooRenderer::DrawSpaceWarp(const zeus::CVector3f& pt, float strength) -{ - m_spaceWarpFilter.setStrength(strength); - m_spaceWarpFilter.draw(pt); -} - -void CBooRenderer::DrawThermalModel(const CModel& model, const zeus::CColor& mulCol, const zeus::CColor& addCol) -{ - CModelFlags flags; - flags.m_extendedShader = EExtendedShader::Thermal; - flags.x4_color = mulCol; - flags.addColor = addCol; - model.UpdateLastFrame(); - model.Draw(flags); -} - -void CBooRenderer::DrawXRayOutline(const zeus::CAABox& aabb) -{ - CModelFlags flags; - flags.m_extendedShader = EExtendedShader::ForcedAlpha; - - for (CAreaListItem& item : x1c_areaListItems) - { - if (item.x4_octTree) - { - std::vector bitmap; - item.x4_octTree->FindOverlappingModels(bitmap, aabb); - - for (u32 c=0 ; cx14_bitmapWordCount ; ++c) - { - for (u32 b=0 ; b<32 ; ++b) - { - if (bitmap[c] & (1 << b)) - { - CBooModel* model = item.x10_models[c * 32 + b]; - model->UpdateUniformData(flags, nullptr, nullptr); - const CBooSurface* surf = model->x38_firstUnsortedSurface; - while (surf) - { - if (surf->GetBounds().intersects(aabb)) - model->DrawSurface(*surf, flags); - surf = surf->m_next; - } - } - } + for (u32 c = 0; c < item.x4_octTree->x14_bitmapWordCount; ++c) { + for (u32 b = 0; b < 32; ++b) { + if (bitmap[c] & (1 << b)) { + CBooModel* model = item.x10_models[c * 32 + b]; + model->UpdateUniformData(flags, nullptr, nullptr); + const CBooSurface* surf = model->x38_firstUnsortedSurface; + while (surf) { + if (surf->GetBounds().intersects(aabb)) + model->DrawSurface(*surf, flags); + surf = surf->m_next; } + } } + } } + } } -void CBooRenderer::SetWireframeFlags(int) -{ -} +void CBooRenderer::SetWireframeFlags(int) {} -void CBooRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) -{ - if (x318_28_disableFog) - mode = ERglFogMode::None; - CGraphics::SetFog(mode, startz, endz, color); +void CBooRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) { + if (x318_28_disableFog) + mode = ERglFogMode::None; + CGraphics::SetFog(mode, startz, endz, color); } void CBooRenderer::RenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, - const TLockedToken* model, const CSkinnedModel* sModel) -{ - if (!x318_28_disableFog) - x2ac_fogVolumes.emplace_back(CGraphics::g_GXModelMatrix, color, aabb, model, sModel); + const TLockedToken* model, const CSkinnedModel* sModel) { + if (!x318_28_disableFog) + x2ac_fogVolumes.emplace_back(CGraphics::g_GXModelMatrix, color, aabb, model, sModel); } -void CBooRenderer::SetThermal(bool thermal, float level, const zeus::CColor& color) -{ - x318_29_thermalVisor = thermal; - x2f0_thermalVisorLevel = level; - x2f4_thermColor = color; - CDecal::SetMoveRedToAlphaBuffer(false); - CElementGen::SetMoveRedToAlphaBuffer(false); +void CBooRenderer::SetThermal(bool thermal, float level, const zeus::CColor& color) { + x318_29_thermalVisor = thermal; + x2f0_thermalVisorLevel = level; + x2f4_thermColor = color; + CDecal::SetMoveRedToAlphaBuffer(false); + CElementGen::SetMoveRedToAlphaBuffer(false); } -void CBooRenderer::SetThermalColdScale(float scale) -{ - x2f8_thermColdScale = zeus::clamp(0.f, scale, 1.f); +void CBooRenderer::SetThermalColdScale(float scale) { x2f8_thermColdScale = zeus::clamp(0.f, scale, 1.f); } + +void CBooRenderer::DoThermalBlendCold() { + zeus::CColor a = zeus::CColor::lerp(x2f4_thermColor, zeus::CColor::skWhite, x2f8_thermColdScale); + m_thermColdFilter.setColorA(a); + float bFac = 0.f; + float bAlpha = 1.f; + if (x2f8_thermColdScale < 0.5f) { + bAlpha = x2f8_thermColdScale * 2.f; + bFac = (1.f - bAlpha) / 8.f; + } + zeus::CColor b{bFac, bFac, bFac, bAlpha}; + m_thermColdFilter.setColorB(b); + zeus::CColor c = zeus::CColor::lerp(zeus::CColor::skBlack, zeus::CColor::skWhite, + zeus::clamp(0.f, (x2f8_thermColdScale - 0.25f) * 4.f / 3.f, 1.f)); + m_thermColdFilter.setColorC(c); + + m_thermColdFilter.setScale(x2f8_thermColdScale); + + m_thermColdFilter.setShift(x2a8_thermalRand.Next() % 32); + m_thermColdFilter.draw(); + CElementGen::SetMoveRedToAlphaBuffer(true); + CDecal::SetMoveRedToAlphaBuffer(true); } -void CBooRenderer::DoThermalBlendCold() -{ - zeus::CColor a = zeus::CColor::lerp(x2f4_thermColor, zeus::CColor::skWhite, x2f8_thermColdScale); - m_thermColdFilter.setColorA(a); - float bFac = 0.f; - float bAlpha = 1.f; - if (x2f8_thermColdScale < 0.5f) - { - bAlpha = x2f8_thermColdScale * 2.f; - bFac = (1.f - bAlpha) / 8.f; +void CBooRenderer::DoThermalBlendHot() { m_thermHotFilter->draw(); } + +u32 CBooRenderer::GetStaticWorldDataSize() { return 0; } + +void CBooRenderer::PrepareDynamicLights(const std::vector& lights) { + x300_dynamicLights = lights; + for (CAreaListItem& area : x1c_areaListItems) { + if (const CAreaRenderOctTree* arot = area.x4_octTree) { + area.x1c_lightOctreeWords.clear(); + area.x1c_lightOctreeWords.resize(arot->x14_bitmapWordCount * lights.size()); + u32* wordPtr = area.x1c_lightOctreeWords.data(); + for (const CLight& light : lights) { + float radius = light.GetRadius(); + zeus::CVector3f vMin = light.GetPosition() - radius; + zeus::CVector3f vMax = light.GetPosition() + radius; + zeus::CAABox aabb(vMin, vMax); + arot->FindOverlappingModels(wordPtr, aabb); + wordPtr += arot->x14_bitmapWordCount; + } } - zeus::CColor b{bFac, bFac, bFac, bAlpha}; - m_thermColdFilter.setColorB(b); - zeus::CColor c = zeus::CColor::lerp(zeus::CColor::skBlack, zeus::CColor::skWhite, - zeus::clamp(0.f, (x2f8_thermColdScale - 0.25f) * 4.f / 3.f, 1.f)); - m_thermColdFilter.setColorC(c); - - m_thermColdFilter.setScale(x2f8_thermColdScale); - - m_thermColdFilter.setShift(x2a8_thermalRand.Next() % 32); - m_thermColdFilter.draw(); - CElementGen::SetMoveRedToAlphaBuffer(true); - CDecal::SetMoveRedToAlphaBuffer(true); + } } -void CBooRenderer::DoThermalBlendHot() -{ - m_thermHotFilter->draw(); -} +void CBooRenderer::SetGXRegister1Color(const zeus::CColor& color) { CGraphics::g_ColorRegs[1] = color; } -u32 CBooRenderer::GetStaticWorldDataSize() -{ - return 0; -} - -void CBooRenderer::PrepareDynamicLights(const std::vector& lights) -{ - x300_dynamicLights = lights; - for (CAreaListItem& area : x1c_areaListItems) - { - if (const CAreaRenderOctTree* arot = area.x4_octTree) - { - area.x1c_lightOctreeWords.clear(); - area.x1c_lightOctreeWords.resize(arot->x14_bitmapWordCount * lights.size()); - u32* wordPtr = area.x1c_lightOctreeWords.data(); - for (const CLight& light : lights) - { - float radius = light.GetRadius(); - zeus::CVector3f vMin = light.GetPosition() - radius; - zeus::CVector3f vMax = light.GetPosition() + radius; - zeus::CAABox aabb(vMin, vMax); - arot->FindOverlappingModels(wordPtr, aabb); - wordPtr += arot->x14_bitmapWordCount; - } - } - } -} - -void CBooRenderer::SetGXRegister1Color(const zeus::CColor& color) -{ - CGraphics::g_ColorRegs[1] = color; -} - -void CBooRenderer::SetWorldLightFadeLevel(float level) -{ - x2fc_tevReg1Color = zeus::CColor(level, level, level, 1.f); -} +void CBooRenderer::SetWorldLightFadeLevel(float level) { x2fc_tevReg1Color = zeus::CColor(level, level, level, 1.f); } void CBooRenderer::ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, /*const CTexture& maskTex,*/ - const CTexture& indTex, const zeus::CColor& modColor, - float scale, float offX, float offY) -{ - float qScale = scale / 8.f; // Adjustment for URDE - m_phazonSuitFilter.draw(modColor, scale, offX * qScale, offY * qScale); + const CTexture& indTex, const zeus::CColor& modColor, float scale, + float offX, float offY) { + float qScale = scale / 8.f; // Adjustment for URDE + m_phazonSuitFilter.draw(modColor, scale, offX * qScale, offY * qScale); } -void CBooRenderer::ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor /*, const CTexture& maskTex*/) -{ - m_phazonSuitFilter.draw(modColor, 0.f, 0.f, 0.f); +void CBooRenderer::ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor /*, const CTexture& maskTex*/) { + m_phazonSuitFilter.draw(modColor, 0.f, 0.f, 0.f); } -void CBooRenderer::DoPhazonSuitIndirectAlphaBlur(float blurRadius /*, float f2*/, const TLockedToken& indTex) -{ - m_phazonSuitFilter.drawBlurPasses(blurRadius, indTex.IsLoaded() ? indTex.GetObj() : nullptr); +void CBooRenderer::DoPhazonSuitIndirectAlphaBlur(float blurRadius /*, float f2*/, + const TLockedToken& indTex) { + m_phazonSuitFilter.drawBlurPasses(blurRadius, indTex.IsLoaded() ? indTex.GetObj() : nullptr); } -void CBooRenderer::DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken& indTex, - const zeus::CColor& indirectMod, float blurRadius, - float scale, float offX, float offY) -{ - /* Indirect background already in binding 0 */ +void CBooRenderer::DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, + const TLockedToken& indTex, const zeus::CColor& indirectMod, + float blurRadius, float scale, float offX, float offY) { + /* Indirect background already in binding 0 */ - /* Resolve alpha channel of just-drawn phazon suit into binding 1 */ - SClipScreenRect rect(g_Viewport); - CGraphics::ResolveSpareTexture(rect, 1); + /* Resolve alpha channel of just-drawn phazon suit into binding 1 */ + SClipScreenRect rect(g_Viewport); + CGraphics::ResolveSpareTexture(rect, 1); - /* Perform blur filter and resolve into binding 2 */ - DoPhazonSuitIndirectAlphaBlur(blurRadius, indTex); + /* Perform blur filter and resolve into binding 2 */ + DoPhazonSuitIndirectAlphaBlur(blurRadius, indTex); - /* Draw effect; subtracting binding 1 from binding 2 for the filter 'cutout' */ - if (indTex && indTex.IsLoaded()) - ReallyDrawPhazonSuitIndirectEffect(zeus::CColor::skWhite, *indTex, indirectMod, scale, offX, offY); - else - ReallyDrawPhazonSuitEffect(nonIndirectMod); + /* Draw effect; subtracting binding 1 from binding 2 for the filter 'cutout' */ + if (indTex && indTex.IsLoaded()) + ReallyDrawPhazonSuitIndirectEffect(zeus::CColor::skWhite, *indTex, indirectMod, scale, offX, offY); + else + ReallyDrawPhazonSuitEffect(nonIndirectMod); } -void CBooRenderer::AllocatePhazonSuitMaskTexture() -{ - x318_26_requestRGBA6 = true; - x310_phazonSuitMaskCountdown = 2; +void CBooRenderer::AllocatePhazonSuitMaskTexture() { + x318_26_requestRGBA6 = true; + x310_phazonSuitMaskCountdown = 2; } -void CBooRenderer::FindOverlappingWorldModels(std::vector& modelBits, const zeus::CAABox& aabb) const -{ - u32 bitmapWords = 0; - for (const CAreaListItem& item : x1c_areaListItems) - if (item.x4_octTree) - bitmapWords += item.x4_octTree->x14_bitmapWordCount; - - if (!bitmapWords) - { - modelBits.clear(); - return; - } +void CBooRenderer::FindOverlappingWorldModels(std::vector& modelBits, const zeus::CAABox& aabb) const { + u32 bitmapWords = 0; + for (const CAreaListItem& item : x1c_areaListItems) + if (item.x4_octTree) + bitmapWords += item.x4_octTree->x14_bitmapWordCount; + if (!bitmapWords) { modelBits.clear(); - modelBits.resize(bitmapWords); + return; + } - u32 curWord = 0; - for (const CAreaListItem& item : x1c_areaListItems) - { - if (!item.x4_octTree) - continue; + modelBits.clear(); + modelBits.resize(bitmapWords); - item.x4_octTree->FindOverlappingModels(modelBits.data() + curWord, aabb); + u32 curWord = 0; + for (const CAreaListItem& item : x1c_areaListItems) { + if (!item.x4_octTree) + continue; - u32 wordModel = 0; - for (int i=0 ; ix14_bitmapWordCount ; ++i, wordModel += 32) - { - u32& word = modelBits[curWord + i]; - if (!word) - continue; - for (int j=0 ; j<32 ; ++j) - { - if ((1 << j) & word) - { - const zeus::CAABox& modelAABB = item.x10_models[wordModel + j]->x20_aabb; - if (!modelAABB.intersects(aabb)) - word &= ~(1 << j); - } - } + item.x4_octTree->FindOverlappingModels(modelBits.data() + curWord, aabb); + + u32 wordModel = 0; + for (int i = 0; i < item.x4_octTree->x14_bitmapWordCount; ++i, wordModel += 32) { + u32& word = modelBits[curWord + i]; + if (!word) + continue; + for (int j = 0; j < 32; ++j) { + if ((1 << j) & word) { + const zeus::CAABox& modelAABB = item.x10_models[wordModel + j]->x20_aabb; + if (!modelAABB.intersects(aabb)) + word &= ~(1 << j); } - - curWord += item.x4_octTree->x14_bitmapWordCount; + } } + + curWord += item.x4_octTree->x14_bitmapWordCount; + } } int CBooRenderer::DrawOverlappingWorldModelIDs(int alphaVal, const std::vector& modelBits, - const zeus::CAABox& aabb) const -{ - SetupRendererStates(); - const_cast(*this).UpdateAreaUniforms(-1, false, false); + const zeus::CAABox& aabb) const { + SetupRendererStates(); + const_cast(*this).UpdateAreaUniforms(-1, false, false); - CModelFlags flags; - flags.m_extendedShader = EExtendedShader::SolidColor; // Do solid color draw + CModelFlags flags; + flags.m_extendedShader = EExtendedShader::SolidColor; // Do solid color draw - u32 curWord = 0; - for (const CAreaListItem& item : x1c_areaListItems) - { - if (!item.x4_octTree) - continue; + u32 curWord = 0; + for (const CAreaListItem& item : x1c_areaListItems) { + if (!item.x4_octTree) + continue; - u32 wordModel = 0; - for (int i=0 ; ix14_bitmapWordCount ; ++i, wordModel += 32) - { - const u32& word = modelBits[curWord + i]; - if (!word) - continue; - for (int j=0 ; j<32 ; ++j) - { - if ((1 << j) & word) - { - if (alphaVal > 255) - return alphaVal; + u32 wordModel = 0; + for (int i = 0; i < item.x4_octTree->x14_bitmapWordCount; ++i, wordModel += 32) { + const u32& word = modelBits[curWord + i]; + if (!word) + continue; + for (int j = 0; j < 32; ++j) { + if ((1 << j) & word) { + if (alphaVal > 255) + return alphaVal; - flags.x4_color.a() = alphaVal / 255.f; - const CBooModel& model = *item.x10_models[wordModel + j]; - const_cast(model).VerifyCurrentShader(0); - for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next) - if (surf->GetBounds().intersects(aabb)) - model.DrawSurface(*surf, flags); - alphaVal += 4; - } - } + flags.x4_color.a() = alphaVal / 255.f; + const CBooModel& model = *item.x10_models[wordModel + j]; + const_cast(model).VerifyCurrentShader(0); + for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next) + if (surf->GetBounds().intersects(aabb)) + model.DrawSurface(*surf, flags); + alphaVal += 4; } - - curWord += item.x4_octTree->x14_bitmapWordCount; + } } - return alphaVal; + curWord += item.x4_octTree->x14_bitmapWordCount; + } + + return alphaVal; } void CBooRenderer::DrawOverlappingWorldModelShadows(int alphaVal, const std::vector& modelBits, - const zeus::CAABox& aabb, float alpha) const -{ - CModelFlags flags; - flags.x4_color.a() = alpha; - flags.m_extendedShader = EExtendedShader::MorphBallShadow; // Do shadow draw + const zeus::CAABox& aabb, float alpha) const { + CModelFlags flags; + flags.x4_color.a() = alpha; + flags.m_extendedShader = EExtendedShader::MorphBallShadow; // Do shadow draw - u32 curWord = 0; - for (const CAreaListItem& item : x1c_areaListItems) - { - if (!item.x4_octTree) - continue; + u32 curWord = 0; + for (const CAreaListItem& item : x1c_areaListItems) { + if (!item.x4_octTree) + continue; - u32 wordModel = 0; - for (int i=0 ; ix14_bitmapWordCount ; ++i, wordModel += 32) - { - const u32& word = modelBits[curWord + i]; - if (!word) - continue; - for (int j=0 ; j<32 ; ++j) - { - if ((1 << j) & word) - { - if (alphaVal > 255) - return; + u32 wordModel = 0; + for (int i = 0; i < item.x4_octTree->x14_bitmapWordCount; ++i, wordModel += 32) { + const u32& word = modelBits[curWord + i]; + if (!word) + continue; + for (int j = 0; j < 32; ++j) { + if ((1 << j) & word) { + if (alphaVal > 255) + return; - flags.x4_color.r() = alphaVal / 255.f; - const CBooModel& model = *item.x10_models[wordModel + j]; - const_cast(model).VerifyCurrentShader(0); - for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next) - if (surf->GetBounds().intersects(aabb)) - model.DrawSurface(*surf, flags); - alphaVal += 4; - } - } + flags.x4_color.r() = alphaVal / 255.f; + const CBooModel& model = *item.x10_models[wordModel + j]; + const_cast(model).VerifyCurrentShader(0); + for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next) + if (surf->GetBounds().intersects(aabb)) + model.DrawSurface(*surf, flags); + alphaVal += 4; } - - curWord += item.x4_octTree->x14_bitmapWordCount; + } } + + curWord += item.x4_octTree->x14_bitmapWordCount; + } } -} +} // namespace urde diff --git a/Runtime/Graphics/CBooRenderer.hpp b/Runtime/Graphics/CBooRenderer.hpp index f7abcb13e..09ba7a7e4 100644 --- a/Runtime/Graphics/CBooRenderer.hpp +++ b/Runtime/Graphics/CBooRenderer.hpp @@ -17,8 +17,7 @@ #include "World/CGameArea.hpp" #include "zeus/CPlane.hpp" -namespace urde -{ +namespace urde { class IObjectStore; class CMemorySys; class IFactory; @@ -26,287 +25,265 @@ class CTexture; class CParticleGen; class CBooModel; -class Buckets -{ - friend class CBooRenderer; +class Buckets { + friend class CBooRenderer; - static rstl::reserved_vector sBucketIndex; - static rstl::reserved_vector* sData; - static rstl::reserved_vector, 50>* sBuckets; - static rstl::reserved_vector* sPlaneObjectData; - static rstl::reserved_vector* sPlaneObjectBucket; - static const float skWorstMinMaxDistance[2]; - static float sMinMaxDistance[2]; + static rstl::reserved_vector sBucketIndex; + static rstl::reserved_vector* sData; + static rstl::reserved_vector, 50>* sBuckets; + static rstl::reserved_vector* sPlaneObjectData; + static rstl::reserved_vector* sPlaneObjectBucket; + static const float skWorstMinMaxDistance[2]; + static float sMinMaxDistance[2]; public: - static void Clear(); - static void Sort(); - static void InsertPlaneObject(float closeDist, float farDist, const zeus::CAABox& aabb, bool invertTest, - const zeus::CPlane& plane, bool zOnly, EDrawableType dtype, const void* data); - static void Insert(const zeus::CVector3f& pos, const zeus::CAABox& aabb, EDrawableType dtype, - const void* data, const zeus::CPlane& plane, u16 extraSort); - static void Shutdown(); - static void Init(); + static void Clear(); + static void Sort(); + static void InsertPlaneObject(float closeDist, float farDist, const zeus::CAABox& aabb, bool invertTest, + const zeus::CPlane& plane, bool zOnly, EDrawableType dtype, const void* data); + static void Insert(const zeus::CVector3f& pos, const zeus::CAABox& aabb, EDrawableType dtype, const void* data, + const zeus::CPlane& plane, u16 extraSort); + static void Shutdown(); + static void Init(); }; -class CBooRenderer final : public IRenderer -{ - friend class CBooModel; - friend class CModel; - friend class CGameArea; - friend class CWorldTransManager; - friend class CMorphBallShadow; +class CBooRenderer final : public IRenderer { + friend class CBooModel; + friend class CModel; + friend class CGameArea; + friend class CWorldTransManager; + friend class CMorphBallShadow; - struct CAreaListItem - { - const std::vector* x0_geometry; - const CAreaRenderOctTree* x4_octTree; - /* originally auto_ptrs of vectors */ - std::vector> x8_textures; - std::vector x10_models; - int x18_areaIdx; - /* Per-area octree-word major, light bits minor */ - std::vector x1c_lightOctreeWords; - const SShader* m_shaderSet; + struct CAreaListItem { + const std::vector* x0_geometry; + const CAreaRenderOctTree* x4_octTree; + /* originally auto_ptrs of vectors */ + std::vector> x8_textures; + std::vector x10_models; + int x18_areaIdx; + /* Per-area octree-word major, light bits minor */ + std::vector x1c_lightOctreeWords; + const SShader* m_shaderSet; - CAreaListItem(const std::vector* geom, - const CAreaRenderOctTree* octTree, - std::vector>&& textures, - std::vector&& models, int areaIdx, - const SShader* shaderSet); - ~CAreaListItem(); + CAreaListItem(const std::vector* geom, const CAreaRenderOctTree* octTree, + std::vector>&& textures, std::vector&& models, int areaIdx, + const SShader* shaderSet); + ~CAreaListItem(); + }; + + struct CFogVolumeListItem { + zeus::CTransform x0_transform; + zeus::CColor x30_color; + zeus::CAABox x34_aabb; + TLockedToken x4c_model; + // bool x58_b; Optional for model token + const CSkinnedModel* x5c_skinnedModel = nullptr; + CFogVolumeListItem(const zeus::CTransform& xf, const zeus::CColor& color, const zeus::CAABox& aabb, + const TLockedToken* model, const CSkinnedModel* sModel) + : x0_transform(xf), x30_color(color), x34_aabb(aabb), x5c_skinnedModel(sModel) { + if (model) + x4c_model = *model; + } + }; + + IFactory& x8_factory; + IObjectStore& xc_store; + TLockedToken m_staticEntropy; + // CFont x10_fnt; + u32 x18_ = 0; + std::list x1c_areaListItems; + zeus::CFrustum x44_frustumPlanes; + + TDrawableCallback xa8_drawableCallback; + const void* xac_callbackContext; + + zeus::CPlane xb0_viewPlane = {0.f, 1.f, 0.f, 0.f}; + + enum class EPVSMode { Mask, PVS, PVSAndMask } xc4_pvsMode = EPVSMode::Mask; + std::experimental::optional xc8_pvs; + u32 xe0_pvsAreaIdx = 0; + + // boo::ITextureS* xe4_blackTex = nullptr; + bool xee_24_ : 1; + + boo::ObjToken x14c_reflectionTex; + // boo::ITextureS* x150_mirrorRamp = nullptr; + boo::ObjToken x1b8_fogVolumeRamp; + boo::ObjToken x220_sphereRamp; + TLockedToken m_thermoPaletteTex; + boo::ObjToken x288_thermoPalette; + TLockedToken m_ballFadeTex; + boo::ObjToken m_ballFade; + boo::ObjToken m_ballShadowId; + boo::ObjToken m_scanLinesEvenVBO; + boo::ObjToken m_scanLinesOddVBO; + int m_ballShadowIdW = 64; + int m_ballShadowIdH = 64; + + CRandom16 x2a8_thermalRand; + std::list x2ac_fogVolumes; + std::list m_fogVolumePlaneShaders; + std::list::iterator m_nextFogVolumePlaneShader; + std::list m_fogVolumeFilters; + std::list::iterator m_nextFogVolumeFilter; + std::list> x2c4_spaceWarps; + u32 x2dc_reflectionAge = 2; + zeus::CColor x2e0_ = zeus::CColor::skWhite; + zeus::CVector3f x2e4_ = {0.f, 1.f, 0.f}; + + CSpaceWarpFilter m_spaceWarpFilter; + + float x2f0_thermalVisorLevel; + zeus::CColor x2f4_thermColor; + float x2f8_thermColdScale = 0.f; + zeus::CColor x2fc_tevReg1Color = {1.f, 0.f, 1.f, 1.f}; + CThermalColdFilter m_thermColdFilter; + std::experimental::optional m_thermHotFilter; + + std::vector x300_dynamicLights; + + u32 x310_phazonSuitMaskCountdown = 0; + // std::unique_ptr x314_phazonSuitMask; + CPhazonSuitFilter m_phazonSuitFilter; + + union { + struct { + bool x318_24_refectionDirty : 1; + bool x318_25_drawWireframe : 1; + bool x318_26_requestRGBA6 : 1; + bool x318_27_currentRGBA6 : 1; + bool x318_28_disableFog : 1; + bool x318_29_thermalVisor : 1; + bool x318_30_inAreaDraw : 1; + bool x318_31_persistRGBA6 : 1; }; + u16 dummy = 0; + }; - struct CFogVolumeListItem - { - zeus::CTransform x0_transform; - zeus::CColor x30_color; - zeus::CAABox x34_aabb; - TLockedToken x4c_model; - //bool x58_b; Optional for model token - const CSkinnedModel* x5c_skinnedModel = nullptr; - CFogVolumeListItem(const zeus::CTransform& xf, const zeus::CColor& color, - const zeus::CAABox& aabb, const TLockedToken* model, - const CSkinnedModel* sModel) - : x0_transform(xf), x30_color(color), x34_aabb(aabb), x5c_skinnedModel(sModel) - { - if (model) - x4c_model = *model; - } - }; + void GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context& ctx); + void GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx); + void GenerateScanLinesVBO(boo::IGraphicsDataFactory::Context& ctx); + void LoadThermoPalette(); + void LoadBallFade(); - IFactory& x8_factory; - IObjectStore& xc_store; - TLockedToken m_staticEntropy; - // CFont x10_fnt; - u32 x18_ = 0; - std::list x1c_areaListItems; - zeus::CFrustum x44_frustumPlanes; + void ActivateLightsForModel(CAreaListItem* item, CBooModel& model); + void RenderBucketItems(CAreaListItem* item); + void HandleUnsortedModel(CAreaListItem* item, CBooModel& model, const CModelFlags& flags); + static void CalcDrawFogFan(const zeus::CPlane* planes, int numPlanes, const zeus::CVector3f* verts, int numVerts, + int iteration, int level, CFogVolumePlaneShader& fogVol); + static void DrawFogSlices(const zeus::CPlane* planes, int numPlanes, int iteration, const zeus::CVector3f& center, + float delta, CFogVolumePlaneShader& fogVol); + static void RenderFogVolumeModel(const zeus::CAABox& aabb, const CModel* model, const zeus::CTransform& modelMtx, + const zeus::CTransform& viewMtx, const CSkinnedModel* sModel, int pass, + CFogVolumePlaneShader* fvs); + void SetupRendererStates() const; - TDrawableCallback xa8_drawableCallback; - const void* xac_callbackContext; - - zeus::CPlane xb0_viewPlane = {0.f, 1.f, 0.f, 0.f}; - - enum class EPVSMode - { - Mask, - PVS, - PVSAndMask - } xc4_pvsMode = EPVSMode::Mask; - std::experimental::optional xc8_pvs; - u32 xe0_pvsAreaIdx = 0; - - //boo::ITextureS* xe4_blackTex = nullptr; - bool xee_24_ : 1; - - boo::ObjToken x14c_reflectionTex; - //boo::ITextureS* x150_mirrorRamp = nullptr; - boo::ObjToken x1b8_fogVolumeRamp; - boo::ObjToken x220_sphereRamp; - TLockedToken m_thermoPaletteTex; - boo::ObjToken x288_thermoPalette; - TLockedToken m_ballFadeTex; - boo::ObjToken m_ballFade; - boo::ObjToken m_ballShadowId; - boo::ObjToken m_scanLinesEvenVBO; - boo::ObjToken m_scanLinesOddVBO; - int m_ballShadowIdW = 64; - int m_ballShadowIdH = 64; - - CRandom16 x2a8_thermalRand; - std::list x2ac_fogVolumes; - std::list m_fogVolumePlaneShaders; - std::list::iterator m_nextFogVolumePlaneShader; - std::list m_fogVolumeFilters; - std::list::iterator m_nextFogVolumeFilter; - std::list> x2c4_spaceWarps; - u32 x2dc_reflectionAge = 2; - zeus::CColor x2e0_ = zeus::CColor::skWhite; - zeus::CVector3f x2e4_ = {0.f, 1.f, 0.f}; - - CSpaceWarpFilter m_spaceWarpFilter; - - float x2f0_thermalVisorLevel; - zeus::CColor x2f4_thermColor; - float x2f8_thermColdScale = 0.f; - zeus::CColor x2fc_tevReg1Color = {1.f, 0.f, 1.f, 1.f}; - CThermalColdFilter m_thermColdFilter; - std::experimental::optional m_thermHotFilter; - - std::vector x300_dynamicLights; - - u32 x310_phazonSuitMaskCountdown = 0; - //std::unique_ptr x314_phazonSuitMask; - CPhazonSuitFilter m_phazonSuitFilter; - - union - { - struct - { - bool x318_24_refectionDirty : 1; - bool x318_25_drawWireframe : 1; - bool x318_26_requestRGBA6 : 1; - bool x318_27_currentRGBA6 : 1; - bool x318_28_disableFog : 1; - bool x318_29_thermalVisor : 1; - bool x318_30_inAreaDraw : 1; - bool x318_31_persistRGBA6 : 1; - }; - u16 dummy = 0; - }; - - void GenerateFogVolumeRampTex(boo::IGraphicsDataFactory::Context& ctx); - void GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx); - void GenerateScanLinesVBO(boo::IGraphicsDataFactory::Context& ctx); - void LoadThermoPalette(); - void LoadBallFade(); - - void ActivateLightsForModel(CAreaListItem* item, CBooModel& model); - void RenderBucketItems(CAreaListItem* item); - void HandleUnsortedModel(CAreaListItem* item, CBooModel& model, const CModelFlags& flags); - static void CalcDrawFogFan(const zeus::CPlane* planes, int numPlanes, const zeus::CVector3f* verts, - int numVerts, int iteration, int level, CFogVolumePlaneShader& fogVol); - static void DrawFogSlices(const zeus::CPlane* planes, int numPlanes, int iteration, - const zeus::CVector3f& center, float delta, CFogVolumePlaneShader& fogVol); - static void RenderFogVolumeModel(const zeus::CAABox& aabb, const CModel* model, const zeus::CTransform& modelMtx, - const zeus::CTransform& viewMtx, const CSkinnedModel* sModel, int pass, - CFogVolumePlaneShader* fvs); - void SetupRendererStates() const; - - void ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, /*const CTexture& maskTex,*/ - const CTexture& indTex, const zeus::CColor& modColor, - float scale, float offX, float offY); - void ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor /*, const CTexture& maskTex*/); - void DoPhazonSuitIndirectAlphaBlur(float blurRadius /*, float f2*/, const TLockedToken& indTex); + void ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, /*const CTexture& maskTex,*/ + const CTexture& indTex, const zeus::CColor& modColor, float scale, float offX, + float offY); + void ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor /*, const CTexture& maskTex*/); + void DoPhazonSuitIndirectAlphaBlur(float blurRadius /*, float f2*/, const TLockedToken& indTex); public: - CBooRenderer(IObjectStore& store, IFactory& resFac); - ~CBooRenderer(); + CBooRenderer(IObjectStore& store, IFactory& resFac); + ~CBooRenderer(); - void AddWorldSurfaces(CBooModel& model); + void AddWorldSurfaces(CBooModel& model); - std::list::iterator FindStaticGeometry(const std::vector*); - void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int areaIdx, - const SShader* shaderSet); - void EnablePVS(const CPVSVisSet&, u32); - void DisablePVS(); - void UpdateAreaUniforms(int areaIdx, bool shadowRender = false, bool activateLights = true); - void RemoveStaticGeometry(const std::vector*); - void DrawAreaGeometry(int areaIdx, int mask, int targetMask); - void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender = false); - void DrawSortedGeometry(int areaIdx, int mask, int targetMask); - void DrawStaticGeometry(int areaIdx, int mask, int targetMask); - void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly); - void PostRenderFogs(); - void AddParticleGen(const CParticleGen&); - void AddParticleGen(const CParticleGen&, const zeus::CVector3f&, const zeus::CAABox&); - void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int); - void AddDrawable(void const *, const zeus::CVector3f&, const zeus::CAABox&, int, EDrawableSorting); - void SetDrawableCallback(TDrawableCallback, const void*); - void SetWorldViewpoint(const zeus::CTransform&); - void SetPerspective(float, float, float, float, float); - void SetPerspective(float, float, float, float); - std::pair SetViewportOrtho(bool, float, float); - void SetClippingPlanes(const zeus::CFrustum& frustum); - void SetViewport(int, int, int, int); - //void SetDepthReadWrite(bool, bool); - //void SetBlendMode_AdditiveAlpha(); - //void SetBlendMode_AlphaBlended(); - //void SetBlendMode_NoColorWrite(); - //void SetBlendMode_ColorMultiply(); - //void SetBlendMode_InvertDst(); - //void SetBlendMode_InvertSrc(); - //void SetBlendMode_Replace(); - //void SetBlendMode_AdditiveDestColor(); - void SetDebugOption(EDebugOption, int); - void BeginScene(); - void EndScene(); - //void BeginPrimitive(EPrimitiveType, int); - //void BeginLines(int); - //void BeginLineStrip(int); - //void BeginTriangles(int); - //void BeginTriangleStrip(int); - //void BeginTriangleFan(int); - //void PrimVertex(const zeus::CVector3f&); - //void PrimNormal(const zeus::CVector3f&); - //void PrimColor(float, float, float, float); - //void PrimColor(const zeus::CColor&); - //void EndPrimitive(); - void SetAmbientColor(const zeus::CColor&); - void DrawString(const char*, int, int); - u32 GetFPS(); - void CacheReflection(TReflectionCallback, void*, bool); - void DrawSpaceWarp(const zeus::CVector3f&, float); - void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol); - void DrawXRayOutline(const zeus::CAABox&); - void SetWireframeFlags(int); - void SetWorldFog(ERglFogMode, float, float, const zeus::CColor&); - void RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken*, const CSkinnedModel*); - void SetThermal(bool, float, const zeus::CColor&); - void SetThermalColdScale(float scale); - void DoThermalBlendCold(); - void DoThermalBlendHot(); - u32 GetStaticWorldDataSize(); - void PrepareDynamicLights(const std::vector& lights); - void SetGXRegister1Color(const zeus::CColor& color); - void SetWorldLightFadeLevel(float level); - void DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken& indTex, - const zeus::CColor& indirectMod, float blurRadius, - float indScale, float indOffX, float indOffY); - void AllocatePhazonSuitMaskTexture(); + std::list::iterator FindStaticGeometry(const std::vector*); + void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int areaIdx, + const SShader* shaderSet); + void EnablePVS(const CPVSVisSet&, u32); + void DisablePVS(); + void UpdateAreaUniforms(int areaIdx, bool shadowRender = false, bool activateLights = true); + void RemoveStaticGeometry(const std::vector*); + void DrawAreaGeometry(int areaIdx, int mask, int targetMask); + void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender = false); + void DrawSortedGeometry(int areaIdx, int mask, int targetMask); + void DrawStaticGeometry(int areaIdx, int mask, int targetMask); + void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly); + void PostRenderFogs(); + void AddParticleGen(const CParticleGen&); + void AddParticleGen(const CParticleGen&, const zeus::CVector3f&, const zeus::CAABox&); + void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int); + void AddDrawable(void const*, const zeus::CVector3f&, const zeus::CAABox&, int, EDrawableSorting); + void SetDrawableCallback(TDrawableCallback, const void*); + void SetWorldViewpoint(const zeus::CTransform&); + void SetPerspective(float, float, float, float, float); + void SetPerspective(float, float, float, float); + std::pair SetViewportOrtho(bool, float, float); + void SetClippingPlanes(const zeus::CFrustum& frustum); + void SetViewport(int, int, int, int); + // void SetDepthReadWrite(bool, bool); + // void SetBlendMode_AdditiveAlpha(); + // void SetBlendMode_AlphaBlended(); + // void SetBlendMode_NoColorWrite(); + // void SetBlendMode_ColorMultiply(); + // void SetBlendMode_InvertDst(); + // void SetBlendMode_InvertSrc(); + // void SetBlendMode_Replace(); + // void SetBlendMode_AdditiveDestColor(); + void SetDebugOption(EDebugOption, int); + void BeginScene(); + void EndScene(); + // void BeginPrimitive(EPrimitiveType, int); + // void BeginLines(int); + // void BeginLineStrip(int); + // void BeginTriangles(int); + // void BeginTriangleStrip(int); + // void BeginTriangleFan(int); + // void PrimVertex(const zeus::CVector3f&); + // void PrimNormal(const zeus::CVector3f&); + // void PrimColor(float, float, float, float); + // void PrimColor(const zeus::CColor&); + // void EndPrimitive(); + void SetAmbientColor(const zeus::CColor&); + void DrawString(const char*, int, int); + u32 GetFPS(); + void CacheReflection(TReflectionCallback, void*, bool); + void DrawSpaceWarp(const zeus::CVector3f&, float); + void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol); + void DrawXRayOutline(const zeus::CAABox&); + void SetWireframeFlags(int); + void SetWorldFog(ERglFogMode, float, float, const zeus::CColor&); + void RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken*, const CSkinnedModel*); + void SetThermal(bool, float, const zeus::CColor&); + void SetThermalColdScale(float scale); + void DoThermalBlendCold(); + void DoThermalBlendHot(); + u32 GetStaticWorldDataSize(); + void PrepareDynamicLights(const std::vector& lights); + void SetGXRegister1Color(const zeus::CColor& color); + void SetWorldLightFadeLevel(float level); + void DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken& indTex, + const zeus::CColor& indirectMod, float blurRadius, float indScale, float indOffX, + float indOffY); + void AllocatePhazonSuitMaskTexture(); - void ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, - const CModel* model, const CSkinnedModel* sModel); + void ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, const CModel* model, + const CSkinnedModel* sModel); - const boo::ObjToken& GetThermoPalette() {return x288_thermoPalette;} - const boo::ObjToken& GetFogRampTex() {return x1b8_fogVolumeRamp;} - const boo::ObjToken& GetRandomStaticEntropyTex() const {return m_staticEntropy->GetBooTexture();} - const boo::ObjToken& GetScanLinesEvenVBO() const {return m_scanLinesEvenVBO;} - const boo::ObjToken& GetScanLinesOddVBO() const {return m_scanLinesOddVBO;} + const boo::ObjToken& GetThermoPalette() { return x288_thermoPalette; } + const boo::ObjToken& GetFogRampTex() { return x1b8_fogVolumeRamp; } + const boo::ObjToken& GetRandomStaticEntropyTex() const { return m_staticEntropy->GetBooTexture(); } + const boo::ObjToken& GetScanLinesEvenVBO() const { return m_scanLinesEvenVBO; } + const boo::ObjToken& GetScanLinesOddVBO() const { return m_scanLinesOddVBO; } - static void BindMainDrawTarget() {CGraphics::g_BooMainCommandQueue->setRenderTarget(CGraphics::g_SpareTexture);} - void BindReflectionDrawTarget() {CGraphics::g_BooMainCommandQueue->setRenderTarget(x14c_reflectionTex);} - void BindBallShadowIdTarget() - { - CGraphics::g_BooMainCommandQueue->setRenderTarget(m_ballShadowId); - SetViewport(0, 0, m_ballShadowIdW, m_ballShadowIdH); - } - void ResolveBallShadowIdTarget() - { - CGraphics::g_BooMainCommandQueue->resolveBindTexture(m_ballShadowId, - boo::SWindowRect(0, 0, - m_ballShadowIdW, - m_ballShadowIdH), - false, 0, true, false); - } + static void BindMainDrawTarget() { CGraphics::g_BooMainCommandQueue->setRenderTarget(CGraphics::g_SpareTexture); } + void BindReflectionDrawTarget() { CGraphics::g_BooMainCommandQueue->setRenderTarget(x14c_reflectionTex); } + void BindBallShadowIdTarget() { + CGraphics::g_BooMainCommandQueue->setRenderTarget(m_ballShadowId); + SetViewport(0, 0, m_ballShadowIdW, m_ballShadowIdH); + } + void ResolveBallShadowIdTarget() { + CGraphics::g_BooMainCommandQueue->resolveBindTexture( + m_ballShadowId, boo::SWindowRect(0, 0, m_ballShadowIdW, m_ballShadowIdH), false, 0, true, false); + } - void FindOverlappingWorldModels(std::vector& modelBits, const zeus::CAABox& aabb) const; - int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector& modelBits, - const zeus::CAABox& aabb) const; - void DrawOverlappingWorldModelShadows(int alphaVal, const std::vector& modelBits, - const zeus::CAABox& aabb, float alpha) const; + void FindOverlappingWorldModels(std::vector& modelBits, const zeus::CAABox& aabb) const; + int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb) const; + void DrawOverlappingWorldModelShadows(int alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb, + float alpha) const; }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CDrawable.hpp b/Runtime/Graphics/CDrawable.hpp index a5d9337cf..63e6f40e8 100644 --- a/Runtime/Graphics/CDrawable.hpp +++ b/Runtime/Graphics/CDrawable.hpp @@ -3,33 +3,24 @@ #include "GCNTypes.hpp" #include "zeus/CAABox.hpp" -namespace urde -{ -enum class EDrawableType : u16 -{ - WorldSurface, - Particle, - Actor, - SimpleShadow, - Decal -}; +namespace urde { +enum class EDrawableType : u16 { WorldSurface, Particle, Actor, SimpleShadow, Decal }; + +class CDrawable { + EDrawableType x0_type; + u16 x2_extraSort; + const void* x4_data; + zeus::CAABox x8_aabb; + float x20_viewDist; -class CDrawable -{ - EDrawableType x0_type; - u16 x2_extraSort; - const void* x4_data; - zeus::CAABox x8_aabb; - float x20_viewDist; public: - CDrawable(EDrawableType dtype, u16 extraSort, float planeDot, const zeus::CAABox& aabb, const void* data) - : x0_type(dtype), x2_extraSort(extraSort), x4_data(data), x8_aabb(aabb), x20_viewDist(planeDot) {} + CDrawable(EDrawableType dtype, u16 extraSort, float planeDot, const zeus::CAABox& aabb, const void* data) + : x0_type(dtype), x2_extraSort(extraSort), x4_data(data), x8_aabb(aabb), x20_viewDist(planeDot) {} - EDrawableType GetType() const {return x0_type;} - const zeus::CAABox& GetBounds() const {return x8_aabb;} - float GetDistance() const {return x20_viewDist;} - const void* GetData() const {return x4_data;} - u16 GetExtraSort() const {return x2_extraSort;} + EDrawableType GetType() const { return x0_type; } + const zeus::CAABox& GetBounds() const { return x8_aabb; } + float GetDistance() const { return x20_viewDist; } + const void* GetData() const { return x4_data; } + u16 GetExtraSort() const { return x2_extraSort; } }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CDrawablePlaneObject.hpp b/Runtime/Graphics/CDrawablePlaneObject.hpp index 5c738b8cb..bed866300 100644 --- a/Runtime/Graphics/CDrawablePlaneObject.hpp +++ b/Runtime/Graphics/CDrawablePlaneObject.hpp @@ -3,22 +3,22 @@ #include "CDrawable.hpp" #include "zeus/CPlane.hpp" -namespace urde -{ -class CDrawablePlaneObject : public CDrawable -{ - friend class Buckets; - u16 x24_targetBucket; - float x28_farDist; - zeus::CPlane x2c_plane; - bool x3c_24_invertTest : 1; - bool x3c_25_zOnly : 1; -public: - CDrawablePlaneObject(EDrawableType dtype, float closeDist, float farDist, const zeus::CAABox& aabb, - bool invertTest, const zeus::CPlane& plane, bool zOnly, const void* data) - : CDrawable(dtype, 0, closeDist, aabb, data), x24_targetBucket(0), x28_farDist(farDist), - x2c_plane(plane) {x3c_24_invertTest = invertTest; x3c_25_zOnly = zOnly;} - const zeus::CPlane& GetPlane() const { return x2c_plane; } -}; -} +namespace urde { +class CDrawablePlaneObject : public CDrawable { + friend class Buckets; + u16 x24_targetBucket; + float x28_farDist; + zeus::CPlane x2c_plane; + bool x3c_24_invertTest : 1; + bool x3c_25_zOnly : 1; +public: + CDrawablePlaneObject(EDrawableType dtype, float closeDist, float farDist, const zeus::CAABox& aabb, bool invertTest, + const zeus::CPlane& plane, bool zOnly, const void* data) + : CDrawable(dtype, 0, closeDist, aabb, data), x24_targetBucket(0), x28_farDist(farDist), x2c_plane(plane) { + x3c_24_invertTest = invertTest; + x3c_25_zOnly = zOnly; + } + const zeus::CPlane& GetPlane() const { return x2c_plane; } +}; +} // namespace urde diff --git a/Runtime/Graphics/CGraphics.cpp b/Runtime/Graphics/CGraphics.cpp index 6d7b1eb31..9b838dc9c 100644 --- a/Runtime/Graphics/CGraphics.cpp +++ b/Runtime/Graphics/CGraphics.cpp @@ -6,8 +6,7 @@ #include "GuiSys/CGuiSys.hpp" #include "CLineRenderer.hpp" -namespace urde -{ +namespace urde { CGraphics::CProjectionState CGraphics::g_Proj; CGraphics::CFogState CGraphics::g_Fog; @@ -32,501 +31,407 @@ bool CGraphics::g_IsGXModelMatrixIdentity = true; SViewport g_Viewport = {0, 0, 640, 480, 640 / 2.f, 480 / 2.f}; u32 CGraphics::g_FrameCounter = 0; -void CGraphics::DisableAllLights() -{ - g_NumLightsActive = 0; - g_LightActive = ERglLightBits::None; - // TODO: turn lights off for real +void CGraphics::DisableAllLights() { + g_NumLightsActive = 0; + g_LightActive = ERglLightBits::None; + // TODO: turn lights off for real } -void CGraphics::LoadLight(ERglLight light, const CLight& info) -{ - // TODO: load light for real +void CGraphics::LoadLight(ERglLight light, const CLight& info) { + // TODO: load light for real } -void CGraphics::EnableLight(ERglLight light) -{ - ERglLightBits lightBit = ERglLightBits(1 << int(light)); - if ((lightBit & g_LightActive) == ERglLightBits::None) - { - g_LightActive |= lightBit; - ++g_NumLightsActive; - // TODO: turn light on for real - } - g_LightsWereOn = g_LightActive; +void CGraphics::EnableLight(ERglLight light) { + ERglLightBits lightBit = ERglLightBits(1 << int(light)); + if ((lightBit & g_LightActive) == ERglLightBits::None) { + g_LightActive |= lightBit; + ++g_NumLightsActive; + // TODO: turn light on for real + } + g_LightsWereOn = g_LightActive; } -void CGraphics::SetLightState(ERglLightBits lightState) -{ - // TODO: set state for real - g_LightActive = lightState; - g_NumLightsActive = zeus::PopCount(lightState); +void CGraphics::SetLightState(ERglLightBits lightState) { + // TODO: set state for real + g_LightActive = lightState; + g_NumLightsActive = zeus::PopCount(lightState); } -void CGraphics::SetAmbientColor(const zeus::CColor& col) -{ - // TODO: set for real +void CGraphics::SetAmbientColor(const zeus::CColor& col) { + // TODO: set for real } -void CGraphics::SetFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) -{ - g_Fog.m_mode = mode > ERglFogMode::PerspRevExp2 ? ERglFogMode(int(mode) - 8) : mode; - switch (g_Fog.m_mode) - { - case ERglFogMode::None: - { - g_Fog.m_start = 4096.f; - g_Fog.m_rangeScale = 0.f; - break; - } - case ERglFogMode::PerspRevExp: - case ERglFogMode::PerspRevExp2: - { - float userRange = endz - startz; - g_Fog.m_color = color; - g_Fog.m_start = endz; - g_Fog.m_rangeScale = 1.f / userRange; - break; - } - default: - { - float userRange = endz - startz; - g_Fog.m_color = color; - g_Fog.m_start = startz; - g_Fog.m_rangeScale = 1.f / userRange; - break; - } - } +void CGraphics::SetFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) { + g_Fog.m_mode = mode > ERglFogMode::PerspRevExp2 ? ERglFogMode(int(mode) - 8) : mode; + switch (g_Fog.m_mode) { + case ERglFogMode::None: { + g_Fog.m_start = 4096.f; + g_Fog.m_rangeScale = 0.f; + break; + } + case ERglFogMode::PerspRevExp: + case ERglFogMode::PerspRevExp2: { + float userRange = endz - startz; + g_Fog.m_color = color; + g_Fog.m_start = endz; + g_Fog.m_rangeScale = 1.f / userRange; + break; + } + default: { + float userRange = endz - startz; + g_Fog.m_color = color; + g_Fog.m_start = startz; + g_Fog.m_rangeScale = 1.f / userRange; + break; + } + } } -void CGraphics::SetDepthWriteMode(bool test, ERglEnum comp, bool write) -{ +void CGraphics::SetDepthWriteMode(bool test, ERglEnum comp, bool write) {} +void CGraphics::SetBlendMode(ERglBlendMode, ERglBlendFactor, ERglBlendFactor, ERglLogicOp) {} + +void CGraphics::SetCullMode(ERglCullMode) {} + +void CGraphics::BeginScene() {} + +void CGraphics::EndScene() { + /* Spinwait until g_NumBreakpointsWaiting is 0 */ + /* ++g_NumBreakpointsWaiting; */ + /* GXCopyDisp to g_CurrenFrameBuf with clear enabled */ + /* Register next breakpoint with GP FIFO */ + + /* Yup, GX effectively had fences long before D3D12 and Vulkan + * (same functionality implemented in boo's execute method) */ + + /* This usually comes from VI register during interrupt; + * we don't care in the era of progressive-scan dominance, + * so simulate field-flipping with XOR instead */ + g_InterruptLastFrameUsedAbove ^= 1; + g_LastFrameUsedAbove = g_InterruptLastFrameUsedAbove; + + /* Flush text instance buffers just before GPU command list submission */ + CTextSupportShader::UpdateBuffers(); + + /* Same with line renderer */ + CLineRenderer::UpdateBuffers(); + + ++g_FrameCounter; } -void CGraphics::SetBlendMode(ERglBlendMode, ERglBlendFactor, ERglBlendFactor, ERglLogicOp) -{ +void CGraphics::SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ERglAlphaFunc comp1, u8 ref1) {} + +void CGraphics::SetViewPointMatrix(const zeus::CTransform& xf) { + g_ViewMatrix = xf; + g_ViewPoint = xf.origin; + zeus::CMatrix3f tmp(xf.basis[0], xf.basis[2], -xf.basis[1]); + g_GXViewPointMatrix = zeus::CTransform(tmp.transposed()); + SetViewMatrix(); } -void CGraphics::SetCullMode(ERglCullMode) -{ +void CGraphics::SetViewMatrix() { + g_CameraMatrix = g_GXViewPointMatrix * zeus::CTransform::Translate(-g_ViewPoint); + if (g_IsGXModelMatrixIdentity) + g_GXModelView = g_CameraMatrix; + else + g_GXModelView = g_CameraMatrix * g_GXModelMatrix; + /* Load position matrix */ + /* Inverse-transpose */ + g_GXModelViewInvXpose = g_GXModelView.inverse(); + g_GXModelViewInvXpose.origin.zeroOut(); + g_GXModelViewInvXpose.basis.transpose(); + /* Load normal matrix */ } -void CGraphics::BeginScene() -{ +void CGraphics::SetModelMatrix(const zeus::CTransform& xf) { + g_IsGXModelMatrixIdentity = false; + g_GXModelMatrix = xf; + SetViewMatrix(); } -void CGraphics::EndScene() -{ - /* Spinwait until g_NumBreakpointsWaiting is 0 */ - /* ++g_NumBreakpointsWaiting; */ - /* GXCopyDisp to g_CurrenFrameBuf with clear enabled */ - /* Register next breakpoint with GP FIFO */ +static const zeus::CMatrix4f PlusOneZ(1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 1.f, 0.f, 0.f, 0.f, 1.f); - /* Yup, GX effectively had fences long before D3D12 and Vulkan - * (same functionality implemented in boo's execute method) */ - - /* This usually comes from VI register during interrupt; - * we don't care in the era of progressive-scan dominance, - * so simulate field-flipping with XOR instead */ - g_InterruptLastFrameUsedAbove ^= 1; - g_LastFrameUsedAbove = g_InterruptLastFrameUsedAbove; - - /* Flush text instance buffers just before GPU command list submission */ - CTextSupportShader::UpdateBuffers(); - - /* Same with line renderer */ - CLineRenderer::UpdateBuffers(); - - ++g_FrameCounter; -} - -void CGraphics::SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ERglAlphaFunc comp1, u8 ref1) -{ -} - -void CGraphics::SetViewPointMatrix(const zeus::CTransform& xf) -{ - g_ViewMatrix = xf; - g_ViewPoint = xf.origin; - zeus::CMatrix3f tmp(xf.basis[0], xf.basis[2], -xf.basis[1]); - g_GXViewPointMatrix = zeus::CTransform(tmp.transposed()); - SetViewMatrix(); -} - -void CGraphics::SetViewMatrix() -{ - g_CameraMatrix = g_GXViewPointMatrix * zeus::CTransform::Translate(-g_ViewPoint); - if (g_IsGXModelMatrixIdentity) - g_GXModelView = g_CameraMatrix; - else - g_GXModelView = g_CameraMatrix * g_GXModelMatrix; - /* Load position matrix */ - /* Inverse-transpose */ - g_GXModelViewInvXpose = g_GXModelView.inverse(); - g_GXModelViewInvXpose.origin.zeroOut(); - g_GXModelViewInvXpose.basis.transpose(); - /* Load normal matrix */ -} - -void CGraphics::SetModelMatrix(const zeus::CTransform& xf) -{ - g_IsGXModelMatrixIdentity = false; - g_GXModelMatrix = xf; - SetViewMatrix(); -} - -static const zeus::CMatrix4f PlusOneZ(1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 1.f, - 0.f, 0.f, 0.f, 1.f); - -static const zeus::CMatrix4f VulkanCorrect(1.f, 0.f, 0.f, 0.f, - 0.f, -1.f, 0.f, 0.f, - 0.f, 0.f, 0.5f, 0.5f + FLT_EPSILON, +static const zeus::CMatrix4f VulkanCorrect(1.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.5f, 0.5f + FLT_EPSILON, 0.f, 0.f, 0.f, 1.f); -zeus::CMatrix4f CGraphics::CalculatePerspectiveMatrix(float fovy, float aspect, - float znear, float zfar, - bool forRenderer) -{ - CProjectionState st; - float tfov = std::tan(zeus::degToRad(fovy * 0.5f)); - st.x14_near = znear; - st.x18_far = zfar; - st.xc_top = znear * tfov; - st.x10_bottom = -st.xc_top; - st.x8_right = aspect * znear * tfov; - st.x4_left = -st.x8_right; +zeus::CMatrix4f CGraphics::CalculatePerspectiveMatrix(float fovy, float aspect, float znear, float zfar, + bool forRenderer) { + CProjectionState st; + float tfov = std::tan(zeus::degToRad(fovy * 0.5f)); + st.x14_near = znear; + st.x18_far = zfar; + st.xc_top = znear * tfov; + st.x10_bottom = -st.xc_top; + st.x8_right = aspect * znear * tfov; + st.x4_left = -st.x8_right; - float rml = st.x8_right - st.x4_left; - float rpl = st.x8_right + st.x4_left; - float tmb = st.xc_top - st.x10_bottom; - float tpb = st.xc_top + st.x10_bottom; - float fpn = st.x18_far + st.x14_near; - float fmn = st.x18_far - st.x14_near; + float rml = st.x8_right - st.x4_left; + float rpl = st.x8_right + st.x4_left; + float tmb = st.xc_top - st.x10_bottom; + float tpb = st.xc_top + st.x10_bottom; + float fpn = st.x18_far + st.x14_near; + float fmn = st.x18_far - st.x14_near; - if (!forRenderer) - { - return zeus::CMatrix4f(2.f * st.x14_near / rml, 0.f, rpl / rml, 0.f, - 0.f, 2.f * st.x14_near / tmb, tpb / tmb, 0.f, - 0.f, 0.f, -fpn / fmn, -2.f * st.x18_far * st.x14_near / fmn, - 0.f, 0.f, -1.f, 0.f); + if (!forRenderer) { + return zeus::CMatrix4f(2.f * st.x14_near / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * st.x14_near / tmb, tpb / tmb, 0.f, + 0.f, 0.f, -fpn / fmn, -2.f * st.x18_far * st.x14_near / fmn, 0.f, 0.f, -1.f, 0.f); + } + + switch (g_BooPlatform) { + case boo::IGraphicsDataFactory::Platform::OpenGL: + default: { + return zeus::CMatrix4f(2.f * st.x14_near / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * st.x14_near / tmb, tpb / tmb, 0.f, + 0.f, 0.f, -fpn / fmn, -2.f * st.x18_far * st.x14_near / fmn, 0.f, 0.f, -1.f, 0.f); + } + case boo::IGraphicsDataFactory::Platform::D3D11: + case boo::IGraphicsDataFactory::Platform::Metal: { + zeus::CMatrix4f mat2(2.f * st.x14_near / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * st.x14_near / tmb, tpb / tmb, 0.f, + 0.f, 0.f, st.x18_far / fmn, st.x14_near * st.x18_far / fmn, 0.f, 0.f, -1.f, 0.f); + return PlusOneZ * mat2; + } + case boo::IGraphicsDataFactory::Platform::Vulkan: { + zeus::CMatrix4f mat2(2.f * st.x14_near / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * st.x14_near / tmb, tpb / tmb, 0.f, + 0.f, 0.f, -fpn / fmn, -2.f * st.x18_far * st.x14_near / fmn, 0.f, 0.f, -1.f, 0.f); + return VulkanCorrect * mat2; + } + } +} + +zeus::CMatrix4f CGraphics::GetPerspectiveProjectionMatrix(bool forRenderer) { + if (g_Proj.x0_persp) { + float rml = g_Proj.x8_right - g_Proj.x4_left; + float rpl = g_Proj.x8_right + g_Proj.x4_left; + float tmb = g_Proj.xc_top - g_Proj.x10_bottom; + float tpb = g_Proj.xc_top + g_Proj.x10_bottom; + float fpn = g_Proj.x18_far + g_Proj.x14_near; + float fmn = g_Proj.x18_far - g_Proj.x14_near; + + if (!forRenderer) { + return zeus::CMatrix4f(2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * g_Proj.x14_near / tmb, + tpb / tmb, 0.f, 0.f, 0.f, -fpn / fmn, -2.f * g_Proj.x18_far * g_Proj.x14_near / fmn, 0.f, + 0.f, -1.f, 0.f); } - switch (g_BooPlatform) - { + switch (g_BooPlatform) { case boo::IGraphicsDataFactory::Platform::OpenGL: - default: - { - return zeus::CMatrix4f(2.f * st.x14_near / rml, 0.f, rpl / rml, 0.f, - 0.f, 2.f * st.x14_near / tmb, tpb / tmb, 0.f, - 0.f, 0.f, -fpn / fmn, -2.f * st.x18_far * st.x14_near / fmn, - 0.f, 0.f, -1.f, 0.f); + default: { + return zeus::CMatrix4f(2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * g_Proj.x14_near / tmb, + tpb / tmb, 0.f, 0.f, 0.f, -fpn / fmn, -2.f * g_Proj.x18_far * g_Proj.x14_near / fmn, 0.f, + 0.f, -1.f, 0.f); } case boo::IGraphicsDataFactory::Platform::D3D11: - case boo::IGraphicsDataFactory::Platform::Metal: - { - zeus::CMatrix4f mat2(2.f * st.x14_near / rml, 0.f, rpl / rml, 0.f, - 0.f, 2.f * st.x14_near / tmb, tpb / tmb, 0.f, - 0.f, 0.f, st.x18_far / fmn, st.x14_near * st.x18_far / fmn, - 0.f, 0.f, -1.f, 0.f); - return PlusOneZ * mat2; + case boo::IGraphicsDataFactory::Platform::Metal: { + zeus::CMatrix4f mat2(2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * g_Proj.x14_near / tmb, + tpb / tmb, 0.f, 0.f, 0.f, g_Proj.x18_far / fmn, g_Proj.x14_near * g_Proj.x18_far / fmn, 0.f, + 0.f, -1.f, 0.f); + return PlusOneZ * mat2; } - case boo::IGraphicsDataFactory::Platform::Vulkan: - { - zeus::CMatrix4f mat2(2.f * st.x14_near / rml, 0.f, rpl / rml, 0.f, - 0.f, 2.f * st.x14_near / tmb, tpb / tmb, 0.f, - 0.f, 0.f, -fpn / fmn, -2.f * st.x18_far * st.x14_near / fmn, - 0.f, 0.f, -1.f, 0.f); - return VulkanCorrect * mat2; + case boo::IGraphicsDataFactory::Platform::Vulkan: { + zeus::CMatrix4f mat2(2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * g_Proj.x14_near / tmb, + tpb / tmb, 0.f, 0.f, 0.f, -fpn / fmn, -2.f * g_Proj.x18_far * g_Proj.x14_near / fmn, 0.f, + 0.f, -1.f, 0.f); + return VulkanCorrect * mat2; } } -} + } else { + float rml = g_Proj.x8_right - g_Proj.x4_left; + float rpl = g_Proj.x8_right + g_Proj.x4_left; + float tmb = g_Proj.xc_top - g_Proj.x10_bottom; + float tpb = g_Proj.xc_top + g_Proj.x10_bottom; + float fpn = g_Proj.x18_far + g_Proj.x14_near; + float fmn = g_Proj.x18_far - g_Proj.x14_near; -zeus::CMatrix4f CGraphics::GetPerspectiveProjectionMatrix(bool forRenderer) -{ - if (g_Proj.x0_persp) - { - float rml = g_Proj.x8_right - g_Proj.x4_left; - float rpl = g_Proj.x8_right + g_Proj.x4_left; - float tmb = g_Proj.xc_top - g_Proj.x10_bottom; - float tpb = g_Proj.xc_top + g_Proj.x10_bottom; - float fpn = g_Proj.x18_far + g_Proj.x14_near; - float fmn = g_Proj.x18_far - g_Proj.x14_near; - - if (!forRenderer) - { - return zeus::CMatrix4f(2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f, - 0.f, 2.f * g_Proj.x14_near / tmb, tpb / tmb, 0.f, - 0.f, 0.f, -fpn / fmn, -2.f * g_Proj.x18_far * g_Proj.x14_near / fmn, - 0.f, 0.f, -1.f, 0.f); - } - - switch (g_BooPlatform) - { - case boo::IGraphicsDataFactory::Platform::OpenGL: - default: - { - return zeus::CMatrix4f(2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f, - 0.f, 2.f * g_Proj.x14_near / tmb, tpb / tmb, 0.f, - 0.f, 0.f, -fpn / fmn, -2.f * g_Proj.x18_far * g_Proj.x14_near / fmn, - 0.f, 0.f, -1.f, 0.f); - } - case boo::IGraphicsDataFactory::Platform::D3D11: - case boo::IGraphicsDataFactory::Platform::Metal: - { - zeus::CMatrix4f mat2(2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f, - 0.f, 2.f * g_Proj.x14_near / tmb, tpb / tmb, 0.f, - 0.f, 0.f, g_Proj.x18_far / fmn, g_Proj.x14_near * g_Proj.x18_far / fmn, - 0.f, 0.f, -1.f, 0.f); - return PlusOneZ * mat2; - } - case boo::IGraphicsDataFactory::Platform::Vulkan: - { - zeus::CMatrix4f mat2(2.f * g_Proj.x14_near / rml, 0.f, rpl / rml, 0.f, - 0.f, 2.f * g_Proj.x14_near / tmb, tpb / tmb, 0.f, - 0.f, 0.f, -fpn / fmn, -2.f * g_Proj.x18_far * g_Proj.x14_near / fmn, - 0.f, 0.f, -1.f, 0.f); - return VulkanCorrect * mat2; - } - } + if (!forRenderer) { + return zeus::CMatrix4f(2.f / rml, 0.f, 0.f, -rpl / rml, 0.f, 2.f / tmb, 0.f, -tpb / tmb, 0.f, 0.f, -2.f / fmn, + -fpn / fmn, 0.f, 0.f, 0.f, 1.f); } - else - { - float rml = g_Proj.x8_right - g_Proj.x4_left; - float rpl = g_Proj.x8_right + g_Proj.x4_left; - float tmb = g_Proj.xc_top - g_Proj.x10_bottom; - float tpb = g_Proj.xc_top + g_Proj.x10_bottom; - float fpn = g_Proj.x18_far + g_Proj.x14_near; - float fmn = g_Proj.x18_far - g_Proj.x14_near; - if (!forRenderer) - { - return zeus::CMatrix4f(2.f / rml, 0.f, 0.f, -rpl / rml, - 0.f, 2.f / tmb, 0.f, -tpb / tmb, - 0.f, 0.f, -2.f / fmn, -fpn / fmn, - 0.f, 0.f, 0.f, 1.f); - } - - switch (g_BooPlatform) - { - case boo::IGraphicsDataFactory::Platform::OpenGL: - default: - { - return zeus::CMatrix4f(2.f / rml, 0.f, 0.f, -rpl / rml, - 0.f, 2.f / tmb, 0.f, -tpb / tmb, - 0.f, 0.f, -2.f / fmn, -fpn / fmn, - 0.f, 0.f, 0.f, 1.f); - } - case boo::IGraphicsDataFactory::Platform::D3D11: - case boo::IGraphicsDataFactory::Platform::Metal: - { - zeus::CMatrix4f mat2(2.f / rml, 0.f, 0.f, -rpl / rml, - 0.f, 2.f / tmb, 0.f, -tpb / tmb, - 0.f, 0.f, 1.f / fmn, g_Proj.x14_near / fmn, - 0.f, 0.f, 0.f, 1.f); - return PlusOneZ * mat2; - } - case boo::IGraphicsDataFactory::Platform::Vulkan: - { - zeus::CMatrix4f mat2(2.f / rml, 0.f, 0.f, -rpl / rml, - 0.f, 2.f / tmb, 0.f, -tpb / tmb, - 0.f, 0.f, -2.f / fmn, -fpn / fmn, - 0.f, 0.f, 0.f, 1.f); - return VulkanCorrect * mat2; - } - } + switch (g_BooPlatform) { + case boo::IGraphicsDataFactory::Platform::OpenGL: + default: { + return zeus::CMatrix4f(2.f / rml, 0.f, 0.f, -rpl / rml, 0.f, 2.f / tmb, 0.f, -tpb / tmb, 0.f, 0.f, -2.f / fmn, + -fpn / fmn, 0.f, 0.f, 0.f, 1.f); } -} - -const CGraphics::CProjectionState& CGraphics::GetProjectionState() -{ - return g_Proj; -} - -void CGraphics::SetProjectionState(const CGraphics::CProjectionState& proj) -{ - g_Proj = proj; - FlushProjection(); -} - -void CGraphics::SetPerspective(float fovy, float aspect, float znear, float zfar) -{ - g_ProjAspect = aspect; - - float tfov = std::tan(zeus::degToRad(fovy * 0.5f)); - g_Proj.x0_persp = true; - g_Proj.x14_near = znear; - g_Proj.x18_far = zfar; - g_Proj.xc_top = znear * tfov; - g_Proj.x10_bottom = -g_Proj.xc_top; - g_Proj.x8_right = aspect * znear * tfov; - g_Proj.x4_left = -g_Proj.x8_right; - - FlushProjection(); -} - -void CGraphics::SetOrtho(float left, float right, - float top, float bottom, - float znear, float zfar) -{ - g_Proj.x0_persp = false; - g_Proj.x4_left = left; - g_Proj.x8_right = right; - g_Proj.xc_top = top; - g_Proj.x10_bottom = bottom; - g_Proj.x14_near = znear; - g_Proj.x18_far = zfar; - - FlushProjection(); -} - -void CGraphics::FlushProjection() -{ - if (g_Proj.x0_persp) - { - // Convert and load persp + case boo::IGraphicsDataFactory::Platform::D3D11: + case boo::IGraphicsDataFactory::Platform::Metal: { + zeus::CMatrix4f mat2(2.f / rml, 0.f, 0.f, -rpl / rml, 0.f, 2.f / tmb, 0.f, -tpb / tmb, 0.f, 0.f, 1.f / fmn, + g_Proj.x14_near / fmn, 0.f, 0.f, 0.f, 1.f); + return PlusOneZ * mat2; } - else - { - // Convert and load ortho + case boo::IGraphicsDataFactory::Platform::Vulkan: { + zeus::CMatrix4f mat2(2.f / rml, 0.f, 0.f, -rpl / rml, 0.f, 2.f / tmb, 0.f, -tpb / tmb, 0.f, 0.f, -2.f / fmn, + -fpn / fmn, 0.f, 0.f, 0.f, 1.f); + return VulkanCorrect * mat2; } + } + } } -zeus::CVector2i CGraphics::ProjectPoint(const zeus::CVector3f& point) -{ - zeus::CVector3f projPt = GetPerspectiveProjectionMatrix(false).multiplyOneOverW(point); - return {int(projPt.x() * g_Viewport.x10_halfWidth) + int(g_Viewport.x10_halfWidth), - int(g_Viewport.xc_height) - (int(projPt.y() * g_Viewport.x14_halfHeight) + - int(g_Viewport.x14_halfHeight))}; +const CGraphics::CProjectionState& CGraphics::GetProjectionState() { return g_Proj; } + +void CGraphics::SetProjectionState(const CGraphics::CProjectionState& proj) { + g_Proj = proj; + FlushProjection(); } -SClipScreenRect CGraphics::ClipScreenRectFromMS(const zeus::CVector3f& p1, - const zeus::CVector3f& p2) -{ - zeus::CVector3f xf1 = g_GXModelView * p1; - zeus::CVector3f xf2 = g_GXModelView * p2; - return ClipScreenRectFromVS(xf1, xf2); +void CGraphics::SetPerspective(float fovy, float aspect, float znear, float zfar) { + g_ProjAspect = aspect; + + float tfov = std::tan(zeus::degToRad(fovy * 0.5f)); + g_Proj.x0_persp = true; + g_Proj.x14_near = znear; + g_Proj.x18_far = zfar; + g_Proj.xc_top = znear * tfov; + g_Proj.x10_bottom = -g_Proj.xc_top; + g_Proj.x8_right = aspect * znear * tfov; + g_Proj.x4_left = -g_Proj.x8_right; + + FlushProjection(); } -SClipScreenRect CGraphics::ClipScreenRectFromVS(const zeus::CVector3f& p1, - const zeus::CVector3f& p2) -{ - if (p1.x() == 0.f && p1.y() == 0.f && p1.z() == 0.f) - return {}; - if (p2.x() == 0.f && p2.y() == 0.f && p2.z() == 0.f) - return {}; - - if (-p1.z() < GetProjectionState().x14_near || -p2.z() < GetProjectionState().x14_near) - return {}; - if (-p1.z() > GetProjectionState().x18_far || -p2.z() > GetProjectionState().x18_far) - return {}; - - zeus::CVector2i sp1 = ProjectPoint(p1); - zeus::CVector2i sp2 = ProjectPoint(p2); - int minX = std::min(sp2.x, sp1.x); - int minX2 = minX & 0xfffffffe; - int minY = std::min(sp2.y, sp1.y); - int minY2 = minY & 0xfffffffe; - - - if (minX2 >= g_Viewport.x8_width) - return {}; - - int maxX = abs(sp1.x - sp2.x) + minX; - int maxX2 = (maxX + 2) & 0xfffffffe; - if (maxX2 <= 0 /* ViewportX origin */) - return {}; - - //int finalMinX = std::max(minX, 0 /* ViewportX origin */); - //int finalMaxX = std::min(maxX, int(g_Viewport.x8_width)); - - - if (minY2 >= g_Viewport.xc_height) - return {}; - - int maxY = abs(sp1.y - sp2.y) + minY; - int maxY2 = (maxY + 2) & 0xfffffffe; - if (maxY2 <= 0 /* ViewportY origin */) - return {}; - - //int finalMinY = std::max(minY, 0 /* ViewportY origin */); - //int finalMaxY = std::min(maxY, int(g_Viewport.xc_height)); - - int width = maxX2 - minX2; - int height = maxY2 - minY2; - return {true, minX2, minY2, width, height, width, - minX2 / float(g_Viewport.x8_width), maxX2 / float(g_Viewport.x8_width), - 1.f - maxY2 / float(g_Viewport.xc_height), 1.f - minY2 / float(g_Viewport.xc_height)}; +void CGraphics::SetOrtho(float left, float right, float top, float bottom, float znear, float zfar) { + g_Proj.x0_persp = false; + g_Proj.x4_left = left; + g_Proj.x8_right = right; + g_Proj.xc_top = top; + g_Proj.x10_bottom = bottom; + g_Proj.x14_near = znear; + g_Proj.x18_far = zfar; + FlushProjection(); } -zeus::CVector3f CGraphics::ProjectModelPointToViewportSpace(const zeus::CVector3f& point) -{ - zeus::CVector3f pt = g_GXModelView * point; - return GetPerspectiveProjectionMatrix(true).multiplyOneOverW(pt); +void CGraphics::FlushProjection() { + if (g_Proj.x0_persp) { + // Convert and load persp + } else { + // Convert and load ortho + } } -zeus::CVector3f CGraphics::ProjectModelPointToViewportSpace(const zeus::CVector3f& point, float& wOut) -{ - zeus::CVector3f pt = g_GXModelView * point; - return GetPerspectiveProjectionMatrix(true).multiplyOneOverW(pt, wOut); +zeus::CVector2i CGraphics::ProjectPoint(const zeus::CVector3f& point) { + zeus::CVector3f projPt = GetPerspectiveProjectionMatrix(false).multiplyOneOverW(point); + return {int(projPt.x() * g_Viewport.x10_halfWidth) + int(g_Viewport.x10_halfWidth), + int(g_Viewport.xc_height) - (int(projPt.y() * g_Viewport.x14_halfHeight) + int(g_Viewport.x14_halfHeight))}; } -void CGraphics::SetViewportResolution(const zeus::CVector2i& res) -{ - g_Viewport.x8_width = res.x; - g_Viewport.xc_height = res.y; - g_CroppedViewport = SClipScreenRect(); - g_CroppedViewport.xc_width = res.x; - g_CroppedViewport.x10_height = res.y; - g_Viewport.x10_halfWidth = res.x / 2.f; - g_Viewport.x14_halfHeight = res.y / 2.f; - if (g_GuiSys) - g_GuiSys->OnViewportResize(); +SClipScreenRect CGraphics::ClipScreenRectFromMS(const zeus::CVector3f& p1, const zeus::CVector3f& p2) { + zeus::CVector3f xf1 = g_GXModelView * p1; + zeus::CVector3f xf2 = g_GXModelView * p2; + return ClipScreenRectFromVS(xf1, xf2); +} + +SClipScreenRect CGraphics::ClipScreenRectFromVS(const zeus::CVector3f& p1, const zeus::CVector3f& p2) { + if (p1.x() == 0.f && p1.y() == 0.f && p1.z() == 0.f) + return {}; + if (p2.x() == 0.f && p2.y() == 0.f && p2.z() == 0.f) + return {}; + + if (-p1.z() < GetProjectionState().x14_near || -p2.z() < GetProjectionState().x14_near) + return {}; + if (-p1.z() > GetProjectionState().x18_far || -p2.z() > GetProjectionState().x18_far) + return {}; + + zeus::CVector2i sp1 = ProjectPoint(p1); + zeus::CVector2i sp2 = ProjectPoint(p2); + int minX = std::min(sp2.x, sp1.x); + int minX2 = minX & 0xfffffffe; + int minY = std::min(sp2.y, sp1.y); + int minY2 = minY & 0xfffffffe; + + if (minX2 >= g_Viewport.x8_width) + return {}; + + int maxX = abs(sp1.x - sp2.x) + minX; + int maxX2 = (maxX + 2) & 0xfffffffe; + if (maxX2 <= 0 /* ViewportX origin */) + return {}; + + // int finalMinX = std::max(minX, 0 /* ViewportX origin */); + // int finalMaxX = std::min(maxX, int(g_Viewport.x8_width)); + + if (minY2 >= g_Viewport.xc_height) + return {}; + + int maxY = abs(sp1.y - sp2.y) + minY; + int maxY2 = (maxY + 2) & 0xfffffffe; + if (maxY2 <= 0 /* ViewportY origin */) + return {}; + + // int finalMinY = std::max(minY, 0 /* ViewportY origin */); + // int finalMaxY = std::min(maxY, int(g_Viewport.xc_height)); + + int width = maxX2 - minX2; + int height = maxY2 - minY2; + return {true, + minX2, + minY2, + width, + height, + width, + minX2 / float(g_Viewport.x8_width), + maxX2 / float(g_Viewport.x8_width), + 1.f - maxY2 / float(g_Viewport.xc_height), + 1.f - minY2 / float(g_Viewport.xc_height)}; +} + +zeus::CVector3f CGraphics::ProjectModelPointToViewportSpace(const zeus::CVector3f& point) { + zeus::CVector3f pt = g_GXModelView * point; + return GetPerspectiveProjectionMatrix(true).multiplyOneOverW(pt); +} + +zeus::CVector3f CGraphics::ProjectModelPointToViewportSpace(const zeus::CVector3f& point, float& wOut) { + zeus::CVector3f pt = g_GXModelView * point; + return GetPerspectiveProjectionMatrix(true).multiplyOneOverW(pt, wOut); +} + +void CGraphics::SetViewportResolution(const zeus::CVector2i& res) { + g_Viewport.x8_width = res.x; + g_Viewport.xc_height = res.y; + g_CroppedViewport = SClipScreenRect(); + g_CroppedViewport.xc_width = res.x; + g_CroppedViewport.x10_height = res.y; + g_Viewport.x10_halfWidth = res.x / 2.f; + g_Viewport.x14_halfHeight = res.y / 2.f; + if (g_GuiSys) + g_GuiSys->OnViewportResize(); } static boo::SWindowRect CachedVP; zeus::CVector2f CGraphics::g_CachedDepthRange = {0.f, 1.f}; -void CGraphics::SetViewport(int leftOff, int bottomOff, int width, int height) -{ - CachedVP.location[0] = leftOff; - CachedVP.location[1] = bottomOff; - CachedVP.size[0] = width; - CachedVP.size[1] = height; - g_BooMainCommandQueue->setViewport(CachedVP, g_CachedDepthRange[0], g_CachedDepthRange[1]); +void CGraphics::SetViewport(int leftOff, int bottomOff, int width, int height) { + CachedVP.location[0] = leftOff; + CachedVP.location[1] = bottomOff; + CachedVP.size[0] = width; + CachedVP.size[1] = height; + g_BooMainCommandQueue->setViewport(CachedVP, g_CachedDepthRange[0], g_CachedDepthRange[1]); } -void CGraphics::SetScissor(int leftOff, int bottomOff, int width, int height) -{ - boo::SWindowRect rect(leftOff, bottomOff, width, height); - g_BooMainCommandQueue->setScissor(rect); +void CGraphics::SetScissor(int leftOff, int bottomOff, int width, int height) { + boo::SWindowRect rect(leftOff, bottomOff, width, height); + g_BooMainCommandQueue->setScissor(rect); } -void CGraphics::SetDepthRange(float znear, float zfar) -{ - g_CachedDepthRange[0] = znear; - g_CachedDepthRange[1] = zfar; - g_BooMainCommandQueue->setViewport(CachedVP, g_CachedDepthRange[0], g_CachedDepthRange[1]); +void CGraphics::SetDepthRange(float znear, float zfar) { + g_CachedDepthRange[0] = znear; + g_CachedDepthRange[1] = zfar; + g_BooMainCommandQueue->setViewport(CachedVP, g_CachedDepthRange[0], g_CachedDepthRange[1]); } CTimeProvider* CGraphics::g_ExternalTimeProvider = nullptr; float CGraphics::g_DefaultSeconds = 0.f; u32 CGraphics::g_RenderTimings = 0; -float CGraphics::GetSecondsMod900() -{ - if (!g_ExternalTimeProvider) - return g_DefaultSeconds; - return g_ExternalTimeProvider->x0_currentTime; +float CGraphics::GetSecondsMod900() { + if (!g_ExternalTimeProvider) + return g_DefaultSeconds; + return g_ExternalTimeProvider->x0_currentTime; } -void CGraphics::TickRenderTimings() -{ - g_RenderTimings = (g_RenderTimings + 1) % u32(900*60); - g_DefaultSeconds = g_RenderTimings / 60.f; +void CGraphics::TickRenderTimings() { + g_RenderTimings = (g_RenderTimings + 1) % u32(900 * 60); + g_DefaultSeconds = g_RenderTimings / 60.f; } boo::IGraphicsDataFactory::Platform CGraphics::g_BooPlatform = boo::IGraphicsDataFactory::Platform::Null; @@ -535,4 +440,4 @@ boo::IGraphicsCommandQueue* CGraphics::g_BooMainCommandQueue = nullptr; boo::ObjToken CGraphics::g_SpareTexture; const boo::SystemChar* CGraphics::g_BooPlatformName = nullptr; -} +} // namespace urde diff --git a/Runtime/Graphics/CGraphics.hpp b/Runtime/Graphics/CGraphics.hpp index 483e1d097..3ca706999 100644 --- a/Runtime/Graphics/CGraphics.hpp +++ b/Runtime/Graphics/CGraphics.hpp @@ -11,200 +11,159 @@ #include "hecl/Runtime.hpp" #include "hecl/CVar.hpp" -namespace urde -{ +namespace urde { extern hecl::CVar* g_disableLighting; class CLight; class CTimeProvider; -enum class ERglLight : u8 -{ - Zero = 0, - One, - Two, - Three, - Four, - Five, - Six, - Seven -}; +enum class ERglLight : u8 { Zero = 0, One, Two, Three, Four, Five, Six, Seven }; -enum class ERglLightBits : u8 -{ - None = 0, - Zero = 1, - One = 1 << 1, - Two = 1 << 2, - Three = 1 << 3, - Four = 1 << 4, - Five = 1 << 5, - Six = 1 << 6, - Seven = 1 << 7 +enum class ERglLightBits : u8 { + None = 0, + Zero = 1, + One = 1 << 1, + Two = 1 << 2, + Three = 1 << 3, + Four = 1 << 4, + Five = 1 << 5, + Six = 1 << 6, + Seven = 1 << 7 }; ENABLE_BITWISE_ENUM(ERglLightBits) -enum class ERglEnum -{ - Never = 0, - Less = 1, - Equal = 2, - LEqual = 3, - Greater = 4, - NEqual = 5, - GEqual = 6, - Always = 7 +enum class ERglEnum { Never = 0, Less = 1, Equal = 2, LEqual = 3, Greater = 4, NEqual = 5, GEqual = 6, Always = 7 }; + +enum class ERglBlendMode { None = 0, Blend = 1, Logic = 2, Subtract = 3 }; + +enum class ERglBlendFactor { + Zero = 0, + One = 1, + SrcColor = 2, + InvSrcColor = 3, + SrcAlpha = 4, + InvSrcAlpha = 5, + DstAlpha = 6, + InvDstAlpha = 7 }; -enum class ERglBlendMode -{ - None = 0, - Blend = 1, - Logic = 2, - Subtract = 3 +enum class ERglLogicOp { + Clear = 0, + And = 1, + RevAnd = 2, + Copy = 3, + InvAnd = 4, + NoOp = 5, + Xor = 6, + Or = 7, + Nor = 8, + Equiv = 9, + Inv = 10, + RevOr = 11, + InvCopy = 12, + InvOr = 13, + NAnd = 14, + Set = 15 }; -enum class ERglBlendFactor -{ - Zero = 0, - One = 1, - SrcColor = 2, - InvSrcColor = 3, - SrcAlpha = 4, - InvSrcAlpha = 5, - DstAlpha = 6, - InvDstAlpha = 7 +enum class ERglCullMode { None = 0, Front = 1, Back = 2, All = 3 }; + +enum class ERglAlphaFunc { + Never = 0, + Less = 1, + Equal = 2, + LEqual = 3, + Greater = 4, + NEqual = 5, + GEqual = 6, + Always = 7 }; -enum class ERglLogicOp -{ - Clear = 0, - And = 1, - RevAnd = 2, - Copy = 3, - InvAnd = 4, - NoOp = 5, - Xor = 6, - Or = 7, - Nor = 8, - Equiv = 9, - Inv = 10, - RevOr = 11, - InvCopy = 12, - InvOr = 13, - NAnd = 14, - Set = 15 +enum class ERglAlphaOp { And = 0, Or = 1, Xor = 2, XNor = 3 }; + +enum class ERglFogMode : uint32_t { + None = 0x00, + + PerspLin = 0x02, + PerspExp = 0x04, + PerspExp2 = 0x05, + PerspRevExp = 0x06, + PerspRevExp2 = 0x07, + + OrthoLin = 0x0A, + OrthoExp = 0x0C, + OrthoExp2 = 0x0D, + OrthoRevExp = 0x0E, + OrthoRevExp2 = 0x0F }; -enum class ERglCullMode -{ - None = 0, - Front = 1, - Back = 2, - All = 3 -}; - -enum class ERglAlphaFunc -{ - Never = 0, - Less = 1, - Equal = 2, - LEqual = 3, - Greater = 4, - NEqual = 5, - GEqual = 6, - Always = 7 -}; - -enum class ERglAlphaOp -{ - And = 0, - Or = 1, - Xor = 2, - XNor = 3 -}; - -enum class ERglFogMode : uint32_t -{ - None = 0x00, - - PerspLin = 0x02, - PerspExp = 0x04, - PerspExp2 = 0x05, - PerspRevExp = 0x06, - PerspRevExp2 = 0x07, - - OrthoLin = 0x0A, - OrthoExp = 0x0C, - OrthoExp2 = 0x0D, - OrthoRevExp = 0x0E, - OrthoRevExp2 = 0x0F -}; - -struct SViewport -{ - u32 x0_left; - u32 x4_top; - u32 x8_width; - u32 xc_height; - float x10_halfWidth; - float x14_halfHeight; +struct SViewport { + u32 x0_left; + u32 x4_top; + u32 x8_width; + u32 xc_height; + float x10_halfWidth; + float x14_halfHeight; }; extern SViewport g_Viewport; -struct SClipScreenRect -{ - bool x0_valid = false; - int x4_left = 0; - int x8_top = 0; - int xc_width = 0; - int x10_height = 0; - int x14_dstWidth = 0; - float x18_uvXMin = 0.f; - float x1c_uvXMax = 0.f; - float x20_uvYMin = 0.f; - float x24_uvYMax = 0.f; - - SClipScreenRect() = default; - SClipScreenRect(bool valid, int left, int top, int width, int height, int dstWidth, - float uvXMin, float uvXMax, float uvYMin, float uvYMax) - : x0_valid(valid), x4_left(left), x8_top(top), xc_width(width), x10_height(height), x14_dstWidth(dstWidth), - x18_uvXMin(uvXMin), x1c_uvXMax(uvXMax), x20_uvYMin(uvYMin), x24_uvYMax(uvYMax) {} - - SClipScreenRect(const boo::SWindowRect& rect) - { - x4_left = rect.location[0]; - x8_top = rect.location[1]; - xc_width = rect.size[0]; - x10_height = rect.size[1]; - x14_dstWidth = rect.size[0]; - } +struct SClipScreenRect { + bool x0_valid = false; + int x4_left = 0; + int x8_top = 0; + int xc_width = 0; + int x10_height = 0; + int x14_dstWidth = 0; + float x18_uvXMin = 0.f; + float x1c_uvXMax = 0.f; + float x20_uvYMin = 0.f; + float x24_uvYMax = 0.f; - SClipScreenRect(const SViewport& vp) - { - x4_left = vp.x0_left; - x8_top = vp.x4_top; - xc_width = vp.x8_width; - x10_height = vp.xc_height; - } + SClipScreenRect() = default; + SClipScreenRect(bool valid, int left, int top, int width, int height, int dstWidth, float uvXMin, float uvXMax, + float uvYMin, float uvYMax) + : x0_valid(valid) + , x4_left(left) + , x8_top(top) + , xc_width(width) + , x10_height(height) + , x14_dstWidth(dstWidth) + , x18_uvXMin(uvXMin) + , x1c_uvXMax(uvXMax) + , x20_uvYMin(uvYMin) + , x24_uvYMax(uvYMax) {} + + SClipScreenRect(const boo::SWindowRect& rect) { + x4_left = rect.location[0]; + x8_top = rect.location[1]; + xc_width = rect.size[0]; + x10_height = rect.size[1]; + x14_dstWidth = rect.size[0]; + } + + SClipScreenRect(const SViewport& vp) { + x4_left = vp.x0_left; + x8_top = vp.x4_top; + xc_width = vp.x8_width; + x10_height = vp.xc_height; + } }; -enum class ETexelFormat -{ - I4 = 0, - I8 = 1, - IA4 = 2, - IA8 = 3, - C4 = 4, - C8 = 5, - C14X2 = 6, - RGB565 = 7, - RGB5A3 = 8, - RGBA8 = 9, - CMPR = 10, - RGBA8PC = 16, - C8PC = 17, - CMPRPC = 18, +enum class ETexelFormat { + I4 = 0, + I8 = 1, + IA4 = 2, + IA8 = 3, + C4 = 4, + C8 = 5, + C14X2 = 6, + RGB565 = 7, + RGB5A3 = 8, + RGBA8 = 9, + CMPR = 10, + RGBA8PC = 16, + C8PC = 17, + CMPRPC = 18, }; #define DEPTH_FAR 1.f @@ -216,196 +175,166 @@ enum class ETexelFormat #define DEPTH_HUD (1.f / 512.f) #define DEPTH_NEAR 0.f -class CGraphics -{ +class CGraphics { public: + struct CProjectionState { + bool x0_persp; + float x4_left; + float x8_right; + float xc_top; + float x10_bottom; + float x14_near; + float x18_far; + }; - struct CProjectionState - { - bool x0_persp; - float x4_left; - float x8_right; - float xc_top; - float x10_bottom; - float x14_near; - float x18_far; - }; + struct CFogState { + ERglFogMode m_mode; + zeus::CColor m_color; + float m_rangeScale = 0.f; + float m_start = 4096.f; + }; - struct CFogState - { - ERglFogMode m_mode; - zeus::CColor m_color; - float m_rangeScale = 0.f; - float m_start = 4096.f; - }; + static CProjectionState g_Proj; + static zeus::CVector2f g_CachedDepthRange; + static CFogState g_Fog; + static zeus::CColor g_ColorRegs[3]; + static float g_ProjAspect; + static u32 g_NumLightsActive; + static u32 g_NumBreakpointsWaiting; + static u32 g_FlippingState; + static bool g_LastFrameUsedAbove; + static bool g_InterruptLastFrameUsedAbove; + static ERglLightBits g_LightActive; + static ERglLightBits g_LightsWereOn; + static zeus::CTransform g_GXModelView; + static zeus::CTransform g_GXModelViewInvXpose; + static zeus::CTransform g_GXModelMatrix; + static zeus::CTransform g_ViewMatrix; + static zeus::CVector3f g_ViewPoint; + static zeus::CTransform g_GXViewPointMatrix; + static zeus::CTransform g_CameraMatrix; + static SClipScreenRect g_CroppedViewport; + static bool g_IsGXModelMatrixIdentity; - static CProjectionState g_Proj; - static zeus::CVector2f g_CachedDepthRange; - static CFogState g_Fog; - static zeus::CColor g_ColorRegs[3]; - static float g_ProjAspect; - static u32 g_NumLightsActive; - static u32 g_NumBreakpointsWaiting; - static u32 g_FlippingState; - static bool g_LastFrameUsedAbove; - static bool g_InterruptLastFrameUsedAbove; - static ERglLightBits g_LightActive; - static ERglLightBits g_LightsWereOn; - static zeus::CTransform g_GXModelView; - static zeus::CTransform g_GXModelViewInvXpose; - static zeus::CTransform g_GXModelMatrix; - static zeus::CTransform g_ViewMatrix; - static zeus::CVector3f g_ViewPoint; - static zeus::CTransform g_GXViewPointMatrix; - static zeus::CTransform g_CameraMatrix; - static SClipScreenRect g_CroppedViewport; - static bool g_IsGXModelMatrixIdentity; + static void DisableAllLights(); + static void LoadLight(ERglLight light, const CLight& info); + static void EnableLight(ERglLight light); + static void SetLightState(ERglLightBits lightState); + static void SetAmbientColor(const zeus::CColor& col); + static void SetFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color); + static void SetDepthWriteMode(bool test, ERglEnum comp, bool write); + static void SetBlendMode(ERglBlendMode, ERglBlendFactor, ERglBlendFactor, ERglLogicOp); + static void SetCullMode(ERglCullMode); + static void BeginScene(); + static void EndScene(); + static void SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ERglAlphaFunc comp1, u8 ref1); + static void SetViewPointMatrix(const zeus::CTransform& xf); + static void SetViewMatrix(); + static void SetModelMatrix(const zeus::CTransform& xf); + static zeus::CMatrix4f CalculatePerspectiveMatrix(float fovy, float aspect, float znear, float zfar, + bool forRenderer); + static zeus::CMatrix4f GetPerspectiveProjectionMatrix(bool forRenderer); + static const CProjectionState& GetProjectionState(); + static void SetProjectionState(const CProjectionState&); + static void SetPerspective(float fovy, float aspect, float znear, float zfar); + static void SetOrtho(float left, float right, float top, float bottom, float znear, float zfar); + static void FlushProjection(); + static zeus::CVector2i ProjectPoint(const zeus::CVector3f& point); + static SClipScreenRect ClipScreenRectFromMS(const zeus::CVector3f& p1, const zeus::CVector3f& p2); + static SClipScreenRect ClipScreenRectFromVS(const zeus::CVector3f& p1, const zeus::CVector3f& p2); + static zeus::CVector3f ProjectModelPointToViewportSpace(const zeus::CVector3f& point); + static zeus::CVector3f ProjectModelPointToViewportSpace(const zeus::CVector3f& point, float& wOut); - static void DisableAllLights(); - static void LoadLight(ERglLight light, const CLight& info); - static void EnableLight(ERglLight light); - static void SetLightState(ERglLightBits lightState); - static void SetAmbientColor(const zeus::CColor& col); - static void SetFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color); - static void SetDepthWriteMode(bool test, ERglEnum comp, bool write); - static void SetBlendMode(ERglBlendMode, ERglBlendFactor, ERglBlendFactor, ERglLogicOp); - static void SetCullMode(ERglCullMode); - static void BeginScene(); - static void EndScene(); - static void SetAlphaCompare(ERglAlphaFunc comp0, u8 ref0, ERglAlphaOp op, ERglAlphaFunc comp1, u8 ref1); - static void SetViewPointMatrix(const zeus::CTransform& xf); - static void SetViewMatrix(); - static void SetModelMatrix(const zeus::CTransform& xf); - static zeus::CMatrix4f CalculatePerspectiveMatrix(float fovy, float aspect, - float znear, float zfar, - bool forRenderer); - static zeus::CMatrix4f GetPerspectiveProjectionMatrix(bool forRenderer); - static const CProjectionState& GetProjectionState(); - static void SetProjectionState(const CProjectionState&); - static void SetPerspective(float fovy, float aspect, float znear, float zfar); - static void SetOrtho(float left, float right, - float top, float bottom, - float znear, float zfar); - static void FlushProjection(); - static zeus::CVector2i ProjectPoint(const zeus::CVector3f& point); - static SClipScreenRect ClipScreenRectFromMS(const zeus::CVector3f& p1, const zeus::CVector3f& p2); - static SClipScreenRect ClipScreenRectFromVS(const zeus::CVector3f& p1, const zeus::CVector3f& p2); - static zeus::CVector3f ProjectModelPointToViewportSpace(const zeus::CVector3f& point); - static zeus::CVector3f ProjectModelPointToViewportSpace(const zeus::CVector3f& point, float& wOut); + static void SetViewportResolution(const zeus::CVector2i& res); + static void SetViewport(int leftOff, int bottomOff, int width, int height); + static void SetScissor(int leftOff, int bottomOff, int width, int height); + static void SetDepthRange(float near, float far); - static void SetViewportResolution(const zeus::CVector2i& res); - static void SetViewport(int leftOff, int bottomOff, int width, int height); - static void SetScissor(int leftOff, int bottomOff, int width, int height); - static void SetDepthRange(float near, float far); + static CTimeProvider* g_ExternalTimeProvider; + static float g_DefaultSeconds; + static u32 g_RenderTimings; + static void SetExternalTimeProvider(CTimeProvider* provider) { g_ExternalTimeProvider = provider; } + static float GetSecondsMod900(); + static void TickRenderTimings(); + static u32 g_FrameCounter; + static u32 GetFrameCounter() { return g_FrameCounter; } - static CTimeProvider* g_ExternalTimeProvider; - static float g_DefaultSeconds; - static u32 g_RenderTimings; - static void SetExternalTimeProvider(CTimeProvider* provider) - {g_ExternalTimeProvider = provider;} - static float GetSecondsMod900(); - static void TickRenderTimings(); - static u32 g_FrameCounter; - static u32 GetFrameCounter() { return g_FrameCounter; } + static boo::IGraphicsDataFactory::Platform g_BooPlatform; + static const boo::SystemChar* g_BooPlatformName; + static boo::IGraphicsDataFactory* g_BooFactory; + static boo::IGraphicsCommandQueue* g_BooMainCommandQueue; + static boo::ObjToken g_SpareTexture; - static boo::IGraphicsDataFactory::Platform g_BooPlatform; - static const boo::SystemChar* g_BooPlatformName; - static boo::IGraphicsDataFactory* g_BooFactory; - static boo::IGraphicsCommandQueue* g_BooMainCommandQueue; - static boo::ObjToken g_SpareTexture; + static void InitializeBoo(boo::IGraphicsDataFactory* factory, boo::IGraphicsCommandQueue* cc, + const boo::ObjToken& spareTex) { + g_BooPlatform = factory->platform(); + g_BooPlatformName = factory->platformName(); + g_BooFactory = factory; + g_BooMainCommandQueue = cc; + g_SpareTexture = spareTex; + } - static void InitializeBoo(boo::IGraphicsDataFactory* factory, - boo::IGraphicsCommandQueue* cc, - const boo::ObjToken& spareTex) - { - g_BooPlatform = factory->platform(); - g_BooPlatformName = factory->platformName(); - g_BooFactory = factory; - g_BooMainCommandQueue = cc; - g_SpareTexture = spareTex; - } + static void ShutdownBoo() { + g_BooFactory = nullptr; + g_BooMainCommandQueue = nullptr; + g_SpareTexture.reset(); + } - static void ShutdownBoo() - { - g_BooFactory = nullptr; - g_BooMainCommandQueue = nullptr; - g_SpareTexture.reset(); - } + static const boo::SystemChar* PlatformName() { return g_BooPlatformName; } - static const boo::SystemChar* PlatformName() - { - return g_BooPlatformName; - } + static void CommitResources(const boo::FactoryCommitFunc& commitFunc __BooTraceArgs) { + g_BooFactory->commitTransaction(commitFunc __BooTraceArgsUse); + } - static void CommitResources(const boo::FactoryCommitFunc& commitFunc __BooTraceArgs) - { - g_BooFactory->commitTransaction(commitFunc __BooTraceArgsUse); - } - - static void SetShaderDataBinding(const boo::ObjToken& binding) - { - g_BooMainCommandQueue->setShaderDataBinding(binding); - } - static void ResolveSpareTexture(const SClipScreenRect& rect, int bindIdx=0, bool clearDepth=false) - { - boo::SWindowRect wrect = {rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}; - g_BooMainCommandQueue->resolveBindTexture(g_SpareTexture, wrect, true, bindIdx, true, false, clearDepth); - } - static void ResolveSpareDepth(const SClipScreenRect& rect, int bindIdx=0) - { - boo::SWindowRect wrect = {rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}; - g_BooMainCommandQueue->resolveBindTexture(g_SpareTexture, wrect, true, bindIdx, false, true); - } - static void DrawInstances(size_t start, size_t count, size_t instCount, size_t startInst = 0) - { - g_BooMainCommandQueue->drawInstances(start, count, instCount, startInst); - } - static void DrawArray(size_t start, size_t count) - { - g_BooMainCommandQueue->draw(start, count); - } - static void DrawArrayIndexed(size_t start, size_t count) - { - g_BooMainCommandQueue->drawIndexed(start, count); - } + static void SetShaderDataBinding(const boo::ObjToken& binding) { + g_BooMainCommandQueue->setShaderDataBinding(binding); + } + static void ResolveSpareTexture(const SClipScreenRect& rect, int bindIdx = 0, bool clearDepth = false) { + boo::SWindowRect wrect = {rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}; + g_BooMainCommandQueue->resolveBindTexture(g_SpareTexture, wrect, true, bindIdx, true, false, clearDepth); + } + static void ResolveSpareDepth(const SClipScreenRect& rect, int bindIdx = 0) { + boo::SWindowRect wrect = {rect.x4_left, rect.x8_top, rect.xc_width, rect.x10_height}; + g_BooMainCommandQueue->resolveBindTexture(g_SpareTexture, wrect, true, bindIdx, false, true); + } + static void DrawInstances(size_t start, size_t count, size_t instCount, size_t startInst = 0) { + g_BooMainCommandQueue->drawInstances(start, count, instCount, startInst); + } + static void DrawArray(size_t start, size_t count) { g_BooMainCommandQueue->draw(start, count); } + static void DrawArrayIndexed(size_t start, size_t count) { g_BooMainCommandQueue->drawIndexed(start, count); } }; -template -class TriFanToStrip -{ - std::vector& m_vec; - size_t m_start; - size_t m_added = 0; +template +class TriFanToStrip { + std::vector& m_vec; + size_t m_start; + size_t m_added = 0; + public: - explicit TriFanToStrip(std::vector& vec) : m_vec(vec), m_start(vec.size()) {} + explicit TriFanToStrip(std::vector& vec) : m_vec(vec), m_start(vec.size()) {} - void AddVert(const VTX& vert) - { - ++m_added; - if (m_added > 3 && (m_added & 1) == 0) - { - m_vec.reserve(m_vec.size() + 3); - m_vec.push_back(m_vec.back()); - m_vec.push_back(m_vec[m_start]); - } - m_vec.push_back(vert); + void AddVert(const VTX& vert) { + ++m_added; + if (m_added > 3 && (m_added & 1) == 0) { + m_vec.reserve(m_vec.size() + 3); + m_vec.push_back(m_vec.back()); + m_vec.push_back(m_vec[m_start]); } + m_vec.push_back(vert); + } - template - void EmplaceVert(_Args&&... args) - { - ++m_added; - if (m_added > 3 && (m_added & 1) == 0) - { - m_vec.reserve(m_vec.size() + 3); - m_vec.push_back(m_vec.back()); - m_vec.push_back(m_vec[m_start]); - } - m_vec.emplace_back(std::forward<_Args>(args)...); + template + void EmplaceVert(_Args&&... args) { + ++m_added; + if (m_added > 3 && (m_added & 1) == 0) { + m_vec.reserve(m_vec.size() + 3); + m_vec.push_back(m_vec.back()); + m_vec.push_back(m_vec[m_start]); } + m_vec.emplace_back(std::forward<_Args>(args)...); + } - void Draw() const { CGraphics::DrawArray(m_start, m_vec.size() - m_start); } + void Draw() const { CGraphics::DrawArray(m_start, m_vec.size() - m_start); } }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CGraphicsPalette.hpp b/Runtime/Graphics/CGraphicsPalette.hpp index 8a085a7b5..81061104b 100644 --- a/Runtime/Graphics/CGraphicsPalette.hpp +++ b/Runtime/Graphics/CGraphicsPalette.hpp @@ -3,38 +3,32 @@ #include #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -enum class EPaletteFormat -{ - IA8 = 0x0, - RGB565 = 0x1, - RGB5A3 = 0x2, +enum class EPaletteFormat { + IA8 = 0x0, + RGB565 = 0x1, + RGB5A3 = 0x2, }; -class CGraphicsPalette -{ - friend class CTextRenderBuffer; - EPaletteFormat x0_fmt; - u32 x4_; - int x8_entryCount; - std::unique_ptr xc_entries; - /* x10_ GXTlutObj here */ - bool x1c_ = false; +class CGraphicsPalette { + friend class CTextRenderBuffer; + EPaletteFormat x0_fmt; + u32 x4_; + int x8_entryCount; + std::unique_ptr xc_entries; + /* x10_ GXTlutObj here */ + bool x1c_ = false; + public: - CGraphicsPalette(EPaletteFormat fmt, int count) - : x0_fmt(fmt), x8_entryCount(count), xc_entries(new u16[count]) {} - CGraphicsPalette(CInputStream& in) - : x0_fmt(EPaletteFormat(in.readUint32Big())) - { - u16 w = in.readUint16Big(); - u16 h = in.readUint16Big(); - x8_entryCount = w * h; + CGraphicsPalette(EPaletteFormat fmt, int count) : x0_fmt(fmt), x8_entryCount(count), xc_entries(new u16[count]) {} + CGraphicsPalette(CInputStream& in) : x0_fmt(EPaletteFormat(in.readUint32Big())) { + u16 w = in.readUint16Big(); + u16 h = in.readUint16Big(); + x8_entryCount = w * h; - /* GX Tlut init here */ - } + /* GX Tlut init here */ + } }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CLight.cpp b/Runtime/Graphics/CLight.cpp index aae8a6a98..03a322056 100644 --- a/Runtime/Graphics/CLight.cpp +++ b/Runtime/Graphics/CLight.cpp @@ -1,127 +1,121 @@ #include "CLight.hpp" #include -namespace urde -{ +namespace urde { static const zeus::CVector3f kDefaultPosition(0.f, 0.f, 0.f); static const zeus::CVector3f kDefaultDirection(0.f, -1.f, 0.f); -float CLight::CalculateLightRadius() const -{ - if (x28_distL < FLT_EPSILON && x2c_distQ < FLT_EPSILON) - return FLT_MAX; +float CLight::CalculateLightRadius() const { + if (x28_distL < FLT_EPSILON && x2c_distQ < FLT_EPSILON) + return FLT_MAX; - float intens = GetIntensity(); + float intens = GetIntensity(); - if (x2c_distQ > FLT_EPSILON) - { - if (intens <= FLT_EPSILON) - return 0.f; - return std::sqrt(intens / 5.f * intens / 255.f * x2c_distQ); - } + if (x2c_distQ > FLT_EPSILON) { + if (intens <= FLT_EPSILON) + return 0.f; + return std::sqrt(intens / 5.f * intens / 255.f * x2c_distQ); + } - float nextIntens = 5.f * intens / 255.f; - return intens / std::min(0.2f, nextIntens) * x28_distL; + float nextIntens = 5.f * intens / 255.f; + return intens / std::min(0.2f, nextIntens) * x28_distL; } -float CLight::GetIntensity() const -{ - if (x4c_24_intensityDirty) - { - const_cast(this)->x4c_24_intensityDirty = false; - float coef = 1.f; - if (x1c_type == ELightType::Custom) - coef = x30_angleC; - const_cast(this)->x48_cachedIntensity = - coef * std::max(x18_color.r(), std::max(x18_color.g(), x18_color.b())); - } - return x48_cachedIntensity; +float CLight::GetIntensity() const { + if (x4c_24_intensityDirty) { + const_cast(this)->x4c_24_intensityDirty = false; + float coef = 1.f; + if (x1c_type == ELightType::Custom) + coef = x30_angleC; + const_cast(this)->x48_cachedIntensity = + coef * std::max(x18_color.r(), std::max(x18_color.g(), x18_color.b())); + } + return x48_cachedIntensity; } +CLight::CLight(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CColor& color, float distC, + float distL, float distQ, float angleC, float angleL, float angleQ) +: x0_pos(pos) +, xc_dir(dir) +, x18_color(color) +, x1c_type(ELightType::Custom) +, x20_spotCutoff(0.f) +, x24_distC(distC) +, x28_distL(distL) +, x2c_distQ(distQ) +, x30_angleC(angleC) +, x34_angleL(angleL) +, x38_angleQ(angleQ) +, x44_cachedRadius(0.f) +, x48_cachedIntensity(0.f) +, x4c_24_intensityDirty(true) +, x4c_25_radiusDirty(true) {} -CLight::CLight(const zeus::CVector3f& pos, - const zeus::CVector3f& dir, - const zeus::CColor& color, - float distC, float distL, float distQ, - float angleC, float angleL, float angleQ) -: x0_pos(pos), xc_dir(dir), x18_color(color), - x1c_type(ELightType::Custom), x20_spotCutoff(0.f), - x24_distC(distC), x28_distL(distL), x2c_distQ(distQ), - x30_angleC(angleC), x34_angleL(angleL), x38_angleQ(angleQ), - x44_cachedRadius(0.f), x48_cachedIntensity(0.f), - x4c_24_intensityDirty(true), x4c_25_radiusDirty(true) -{} - -CLight::CLight(ELightType type, - const zeus::CVector3f& pos, - const zeus::CVector3f& dir, - const zeus::CColor& color, +CLight::CLight(ELightType type, const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CColor& color, float cutoff) -: x0_pos(pos), xc_dir(dir), x18_color(color), - x1c_type(type), x20_spotCutoff(cutoff), - x24_distC(1.f), x28_distL(0.f), x2c_distQ(0.f), - x30_angleC(1.f), x34_angleL(0.f), x38_angleQ(0.f), - x44_cachedRadius(0.f), x48_cachedIntensity(0.f), - x4c_24_intensityDirty(true), x4c_25_radiusDirty(true) -{ - switch (type) - { - case ELightType::Spot: - { - float cosCutoff = std::cos(zeus::degToRad(cutoff)); - x30_angleC = 0.f; - x34_angleL = -cosCutoff / (1.0 - cosCutoff); - x38_angleQ = 1.f / (1.0 - cosCutoff); - break; - } - case ELightType::Directional: - { - x24_distC = 1.f; - x28_distL = 0.f; - x2c_distQ = 0.f; - break; - } - default: break; - } +: x0_pos(pos) +, xc_dir(dir) +, x18_color(color) +, x1c_type(type) +, x20_spotCutoff(cutoff) +, x24_distC(1.f) +, x28_distL(0.f) +, x2c_distQ(0.f) +, x30_angleC(1.f) +, x34_angleL(0.f) +, x38_angleQ(0.f) +, x44_cachedRadius(0.f) +, x48_cachedIntensity(0.f) +, x4c_24_intensityDirty(true) +, x4c_25_radiusDirty(true) { + switch (type) { + case ELightType::Spot: { + float cosCutoff = std::cos(zeus::degToRad(cutoff)); + x30_angleC = 0.f; + x34_angleL = -cosCutoff / (1.0 - cosCutoff); + x38_angleQ = 1.f / (1.0 - cosCutoff); + break; + } + case ELightType::Directional: { + x24_distC = 1.f; + x28_distL = 0.f; + x2c_distQ = 0.f; + break; + } + default: + break; + } } -zeus::CColor CLight::GetNormalIndependentLightingAtPoint(const zeus::CVector3f& point) const -{ - if (x1c_type == ELightType::LocalAmbient) - return x18_color; +zeus::CColor CLight::GetNormalIndependentLightingAtPoint(const zeus::CVector3f& point) const { + if (x1c_type == ELightType::LocalAmbient) + return x18_color; - float dist = std::max((x0_pos - point).magnitude(), FLT_EPSILON); - return x18_color * (1.f / (x2c_distQ * dist * dist + x28_distL * dist + x24_distC)); + float dist = std::max((x0_pos - point).magnitude(), FLT_EPSILON); + return x18_color * (1.f / (x2c_distQ * dist * dist + x28_distL * dist + x24_distC)); } -CLight CLight::BuildDirectional(const zeus::CVector3f& dir, const zeus::CColor& color) -{ - return CLight(ELightType::Directional, kDefaultPosition, dir, color, 180.f); +CLight CLight::BuildDirectional(const zeus::CVector3f& dir, const zeus::CColor& color) { + return CLight(ELightType::Directional, kDefaultPosition, dir, color, 180.f); } -CLight CLight::BuildSpot(const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const zeus::CColor& color, float angle) -{ - return CLight(ELightType::Spot, pos, dir, color, angle); +CLight CLight::BuildSpot(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CColor& color, + float angle) { + return CLight(ELightType::Spot, pos, dir, color, angle); } -CLight CLight::BuildPoint(const zeus::CVector3f& pos, const zeus::CColor& color) -{ - return CLight(ELightType::Point, pos, kDefaultDirection, color, 180.f); +CLight CLight::BuildPoint(const zeus::CVector3f& pos, const zeus::CColor& color) { + return CLight(ELightType::Point, pos, kDefaultDirection, color, 180.f); } -CLight CLight::BuildCustom(const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const zeus::CColor& color, - float distC, float distL, float distQ, - float angleC, float angleL, float angleQ) -{ - return CLight(pos, dir, color, distC, distL, distQ, angleC, angleL, angleQ); +CLight CLight::BuildCustom(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CColor& color, + float distC, float distL, float distQ, float angleC, float angleL, float angleQ) { + return CLight(pos, dir, color, distC, distL, distQ, angleC, angleL, angleQ); } -CLight CLight::BuildLocalAmbient(const zeus::CVector3f& pos, const zeus::CColor& color) -{ - return CLight(ELightType::LocalAmbient, pos, kDefaultDirection, color, 180.f); +CLight CLight::BuildLocalAmbient(const zeus::CVector3f& pos, const zeus::CColor& color) { + return CLight(ELightType::LocalAmbient, pos, kDefaultDirection, color, 180.f); } -} +} // namespace urde diff --git a/Runtime/Graphics/CLight.hpp b/Runtime/Graphics/CLight.hpp index 2b3e2f616..b68536872 100644 --- a/Runtime/Graphics/CLight.hpp +++ b/Runtime/Graphics/CLight.hpp @@ -4,141 +4,112 @@ #include "zeus/CColor.hpp" #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -enum class ELightType -{ - Spot = 0, - Point = 1, - Directional = 2, - LocalAmbient = 3, - Custom = 4, -}; -enum class EFalloffType -{ - Constant, - Linear, - Quadratic +enum class ELightType { + Spot = 0, + Point = 1, + Directional = 2, + LocalAmbient = 3, + Custom = 4, }; +enum class EFalloffType { Constant, Linear, Quadratic }; -class CLight -{ - friend class CGuiLight; - friend class CBooModel; - friend class CBooRenderer; - friend class CGameLight; +class CLight { + friend class CGuiLight; + friend class CBooModel; + friend class CBooRenderer; + friend class CGameLight; - zeus::CVector3f x0_pos; - zeus::CVector3f xc_dir = zeus::CVector3f::skDown; - zeus::CColor x18_color = zeus::CColor::skClear; - ELightType x1c_type = ELightType::Custom; - float x20_spotCutoff = 0.f; - float x24_distC = 1.f; - float x28_distL = 0.f; - float x2c_distQ = 0.f; - float x30_angleC = 1.f; - float x34_angleL = 0.f; - float x38_angleQ = 0.f; - u32 x3c_priority = 0; - u32 x40_lightId = 0; // Serves as unique key - float x44_cachedRadius = 0.f; - float x48_cachedIntensity = 0.f; - bool x4c_24_intensityDirty : 1; - bool x4c_25_radiusDirty : 1; + zeus::CVector3f x0_pos; + zeus::CVector3f xc_dir = zeus::CVector3f::skDown; + zeus::CColor x18_color = zeus::CColor::skClear; + ELightType x1c_type = ELightType::Custom; + float x20_spotCutoff = 0.f; + float x24_distC = 1.f; + float x28_distL = 0.f; + float x2c_distQ = 0.f; + float x30_angleC = 1.f; + float x34_angleL = 0.f; + float x38_angleQ = 0.f; + u32 x3c_priority = 0; + u32 x40_lightId = 0; // Serves as unique key + float x44_cachedRadius = 0.f; + float x48_cachedIntensity = 0.f; + bool x4c_24_intensityDirty : 1; + bool x4c_25_radiusDirty : 1; - float CalculateLightRadius() const; + float CalculateLightRadius() const; public: - CLight() - { - x4c_24_intensityDirty = true; - x4c_25_radiusDirty = true; + CLight() { + x4c_24_intensityDirty = true; + x4c_25_radiusDirty = true; + } + + CLight(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CColor& color, float distC, float distL, + float distQ, float angleC, float angleL, float angleQ); + + CLight(ELightType type, const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CColor& color, + float cutoff); + + void SetPosition(const zeus::CVector3f& pos) { x0_pos = pos; } + + const zeus::CVector3f& GetPosition() const { return x0_pos; } + + void SetDirection(const zeus::CVector3f& dir) { xc_dir = dir; } + + const zeus::CVector3f& GetDirection() const { return xc_dir; } + + void SetColor(const zeus::CColor& col) { + x18_color = col; + x4c_24_intensityDirty = true; + x4c_25_radiusDirty = true; + } + + void SetAttenuation(float constant, float linear, float quadratic) { + x24_distC = constant; + x28_distL = linear; + x2c_distQ = quadratic; + x4c_24_intensityDirty = true; + x4c_25_radiusDirty = true; + } + float GetAttenuationConstant() const { return x24_distC; } + float GetAttenuationLinear() const { return x28_distL; } + float GetAttenuationQuadratic() const { return x2c_distQ; } + + void SetAngleAttenuation(float constant, float linear, float quadratic) { + x30_angleC = constant; + x34_angleL = linear; + x38_angleQ = quadratic; + x4c_24_intensityDirty = true; + x4c_25_radiusDirty = true; + } + float GetAngleAttenuationConstant() const { return x30_angleC; } + float GetAngleAttenuationLinear() const { return x34_angleL; } + float GetAngleAttenuationQuadratic() const { return x38_angleQ; } + + float GetRadius() const { + if (x4c_25_radiusDirty) { + const_cast(this)->x44_cachedRadius = CalculateLightRadius(); + const_cast(this)->x4c_25_radiusDirty = false; } + return x44_cachedRadius; + } - CLight(const zeus::CVector3f& pos, - const zeus::CVector3f& dir, - const zeus::CColor& color, - float distC, float distL, float distQ, - float angleC, float angleL, float angleQ); + ELightType GetType() const { return x1c_type; } - CLight(ELightType type, - const zeus::CVector3f& pos, - const zeus::CVector3f& dir, - const zeus::CColor& color, - float cutoff); + float GetIntensity() const; + const zeus::CColor& GetColor() const { return x18_color; } + zeus::CColor GetNormalIndependentLightingAtPoint(const zeus::CVector3f& point) const; - void SetPosition(const zeus::CVector3f& pos) - { - x0_pos = pos; - } - - const zeus::CVector3f& GetPosition() const { return x0_pos; } - - void SetDirection(const zeus::CVector3f& dir) - { - xc_dir = dir; - } - - const zeus::CVector3f& GetDirection() const { return xc_dir; } - - void SetColor(const zeus::CColor& col) - { - x18_color = col; - x4c_24_intensityDirty = true; - x4c_25_radiusDirty = true; - } - - void SetAttenuation(float constant, float linear, float quadratic) - { - x24_distC = constant; - x28_distL = linear; - x2c_distQ = quadratic; - x4c_24_intensityDirty = true; - x4c_25_radiusDirty = true; - } - float GetAttenuationConstant() const { return x24_distC; } - float GetAttenuationLinear() const { return x28_distL; } - float GetAttenuationQuadratic() const { return x2c_distQ; } - - void SetAngleAttenuation(float constant, float linear, float quadratic) - { - x30_angleC = constant; - x34_angleL = linear; - x38_angleQ = quadratic; - x4c_24_intensityDirty = true; - x4c_25_radiusDirty = true; - } - float GetAngleAttenuationConstant() const { return x30_angleC; } - float GetAngleAttenuationLinear() const { return x34_angleL; } - float GetAngleAttenuationQuadratic() const { return x38_angleQ; } - - float GetRadius() const - { - if (x4c_25_radiusDirty) - { - const_cast(this)->x44_cachedRadius = CalculateLightRadius(); - const_cast(this)->x4c_25_radiusDirty = false; - } - return x44_cachedRadius; - } - - ELightType GetType() const { return x1c_type; } - - float GetIntensity() const; - const zeus::CColor& GetColor() const { return x18_color; } - zeus::CColor GetNormalIndependentLightingAtPoint(const zeus::CVector3f& point) const; - - static CLight BuildDirectional(const zeus::CVector3f& dir, const zeus::CColor& color); - static CLight BuildSpot(const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const zeus::CColor& color, float angle); - static CLight BuildPoint(const zeus::CVector3f& pos, const zeus::CColor& color); - static CLight BuildCustom(const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const zeus::CColor& color, - float distC, float distL, float distQ, - float angleC, float angleL, float angleQ); - static CLight BuildLocalAmbient(const zeus::CVector3f& pos, const zeus::CColor& color); + static CLight BuildDirectional(const zeus::CVector3f& dir, const zeus::CColor& color); + static CLight BuildSpot(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CColor& color, + float angle); + static CLight BuildPoint(const zeus::CVector3f& pos, const zeus::CColor& color); + static CLight BuildCustom(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const zeus::CColor& color, + float distC, float distL, float distQ, float angleC, float angleL, float angleQ); + static CLight BuildLocalAmbient(const zeus::CVector3f& pos, const zeus::CColor& color); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CLineRenderer.cpp b/Runtime/Graphics/CLineRenderer.cpp index 839926873..e6244a408 100644 --- a/Runtime/Graphics/CLineRenderer.cpp +++ b/Runtime/Graphics/CLineRenderer.cpp @@ -1,466 +1,382 @@ #include "CLineRenderer.hpp" #include "Shaders/CLineRendererShaders.hpp" -namespace urde -{ +namespace urde { logvisor::Module LineRendererLog("urde::CLineRenderer"); -void CLineRenderer::Initialize() -{ - CLineRendererShaders::Initialize(); -} +void CLineRenderer::Initialize() { CLineRendererShaders::Initialize(); } -void CLineRenderer::Shutdown() -{ - CLineRendererShaders::Shutdown(); - s_vertPoolTex.doDestroy(); - s_vertPoolNoTex.doDestroy(); - s_uniformPool.doDestroy(); +void CLineRenderer::Shutdown() { + CLineRendererShaders::Shutdown(); + s_vertPoolTex.doDestroy(); + s_vertPoolNoTex.doDestroy(); + s_uniformPool.doDestroy(); } hecl::VertexBufferPool CLineRenderer::s_vertPoolTex = {}; hecl::VertexBufferPool CLineRenderer::s_vertPoolNoTex = {}; hecl::UniformBufferPool CLineRenderer::s_uniformPool = {}; -CLineRenderer::CLineRenderer(boo::IGraphicsDataFactory::Context& ctx, - EPrimitiveMode mode, u32 maxVerts, - const boo::ObjToken& texture, - bool additive, bool zTest, bool zGEqual) -: m_mode(mode), m_maxVerts(maxVerts) -{ - if (maxVerts < 2) - { - LineRendererLog.report(logvisor::Fatal, _SYS_STR("maxVerts < 2, maxVerts = %i"), maxVerts); - return; - } - m_textured = texture; +CLineRenderer::CLineRenderer(boo::IGraphicsDataFactory::Context& ctx, EPrimitiveMode mode, u32 maxVerts, + const boo::ObjToken& texture, bool additive, bool zTest, bool zGEqual) +: m_mode(mode), m_maxVerts(maxVerts) { + if (maxVerts < 2) { + LineRendererLog.report(logvisor::Fatal, _SYS_STR("maxVerts < 2, maxVerts = %i"), maxVerts); + return; + } + m_textured = texture; - u32 maxTriVerts; - switch (mode) - { - case EPrimitiveMode::Lines: - case EPrimitiveMode::LineStrip: - maxTriVerts = maxVerts * 4; - break; - case EPrimitiveMode::LineLoop: - maxTriVerts = maxVerts * 4 + 4; - break; - } + u32 maxTriVerts; + switch (mode) { + case EPrimitiveMode::Lines: + case EPrimitiveMode::LineStrip: + maxTriVerts = maxVerts * 4; + break; + case EPrimitiveMode::LineLoop: + maxTriVerts = maxVerts * 4 + 4; + break; + } - if (texture) - m_vertBufTex = s_vertPoolTex.allocateBlock(CGraphics::g_BooFactory, maxTriVerts); - else - m_vertBufNoTex = s_vertPoolNoTex.allocateBlock(CGraphics::g_BooFactory, maxTriVerts); + if (texture) + m_vertBufTex = s_vertPoolTex.allocateBlock(CGraphics::g_BooFactory, maxTriVerts); + else + m_vertBufNoTex = s_vertPoolNoTex.allocateBlock(CGraphics::g_BooFactory, maxTriVerts); - m_uniformBuf = s_uniformPool.allocateBlock(CGraphics::g_BooFactory); + m_uniformBuf = s_uniformPool.allocateBlock(CGraphics::g_BooFactory); - CLineRendererShaders::BuildShaderDataBinding(ctx, *this, texture, additive, zTest, zGEqual); + CLineRendererShaders::BuildShaderDataBinding(ctx, *this, texture, additive, zTest, zGEqual); } -CLineRenderer::CLineRenderer(EPrimitiveMode mode, u32 maxVerts, - const boo::ObjToken& texture, +CLineRenderer::CLineRenderer(EPrimitiveMode mode, u32 maxVerts, const boo::ObjToken& texture, bool additive, bool zTest, bool zGEqual) -: m_mode(mode), m_maxVerts(maxVerts) -{ - if (maxVerts < 2) - { - LineRendererLog.report(logvisor::Fatal, _SYS_STR("maxVerts < 2, maxVerts = %i"), maxVerts); - return; - } - m_textured = texture; +: m_mode(mode), m_maxVerts(maxVerts) { + if (maxVerts < 2) { + LineRendererLog.report(logvisor::Fatal, _SYS_STR("maxVerts < 2, maxVerts = %i"), maxVerts); + return; + } + m_textured = texture; - u32 maxTriVerts; - switch (mode) - { - case EPrimitiveMode::Lines: - case EPrimitiveMode::LineStrip: - maxTriVerts = maxVerts * 4; - break; - case EPrimitiveMode::LineLoop: - maxTriVerts = maxVerts * 4 + 4; - break; - } + u32 maxTriVerts; + switch (mode) { + case EPrimitiveMode::Lines: + case EPrimitiveMode::LineStrip: + maxTriVerts = maxVerts * 4; + break; + case EPrimitiveMode::LineLoop: + maxTriVerts = maxVerts * 4 + 4; + break; + } - if (texture) - m_vertBufTex = s_vertPoolTex.allocateBlock(CGraphics::g_BooFactory, maxTriVerts); - else - m_vertBufNoTex = s_vertPoolNoTex.allocateBlock(CGraphics::g_BooFactory, maxTriVerts); + if (texture) + m_vertBufTex = s_vertPoolTex.allocateBlock(CGraphics::g_BooFactory, maxTriVerts); + else + m_vertBufNoTex = s_vertPoolNoTex.allocateBlock(CGraphics::g_BooFactory, maxTriVerts); - m_uniformBuf = s_uniformPool.allocateBlock(CGraphics::g_BooFactory); + m_uniformBuf = s_uniformPool.allocateBlock(CGraphics::g_BooFactory); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - CLineRendererShaders::BuildShaderDataBinding(ctx, *this, texture, additive, zTest, zGEqual); - return true; - } BooTrace); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + CLineRendererShaders::BuildShaderDataBinding(ctx, *this, texture, additive, zTest, zGEqual); + return true; + } BooTrace); } rstl::reserved_vector CLineRenderer::g_StaticLineVertsTex = {}; rstl::reserved_vector CLineRenderer::g_StaticLineVertsNoTex = {}; -static bool IntersectLines(const zeus::CVector2f& pa1, const zeus::CVector2f& pa2, - const zeus::CVector2f& pb1, const zeus::CVector2f& pb2, - zeus::CVector3f& intersect) -{ - zeus::CVector2f deltaA = pa1 - pa2; - zeus::CVector2f deltaB = pb1 - pb2; - float det = deltaA.cross(deltaB); - if (std::fabs(det) < 0.000001f) - return false; - float c0 = pa1.cross(pa2); - float c1 = pb1.cross(pb2); - intersect = (c0 * (pb1 - pb2) - c1 * (pa1 - pa2)) / det; - return true; +static bool IntersectLines(const zeus::CVector2f& pa1, const zeus::CVector2f& pa2, const zeus::CVector2f& pb1, + const zeus::CVector2f& pb2, zeus::CVector3f& intersect) { + zeus::CVector2f deltaA = pa1 - pa2; + zeus::CVector2f deltaB = pb1 - pb2; + float det = deltaA.cross(deltaB); + if (std::fabs(det) < 0.000001f) + return false; + float c0 = pa1.cross(pa2); + float c1 = pb1.cross(pb2); + intersect = (c0 * (pb1 - pb2) - c1 * (pa1 - pa2)) / det; + return true; } -void CLineRenderer::Reset() -{ - m_nextVert = 0; - m_final = false; - if (m_textured) - g_StaticLineVertsTex.clear(); - else - g_StaticLineVertsNoTex.clear(); +void CLineRenderer::Reset() { + m_nextVert = 0; + m_final = false; + if (m_textured) + g_StaticLineVertsTex.clear(); + else + g_StaticLineVertsNoTex.clear(); } void CLineRenderer::AddVertex(const zeus::CVector3f& position, const zeus::CColor& color, float width, - const zeus::CVector2f& uv) -{ - if (m_final || !m_shaderBind || m_nextVert >= m_maxVerts) - return; + const zeus::CVector2f& uv) { + if (m_final || !m_shaderBind || m_nextVert >= m_maxVerts) + return; - float adjWidth = width / 480.f; - float w; - zeus::CVector3f projPt = CGraphics::ProjectModelPointToViewportSpace(position, w); + float adjWidth = width / 480.f; + float w; + zeus::CVector3f projPt = CGraphics::ProjectModelPointToViewportSpace(position, w); - if (m_mode == EPrimitiveMode::LineLoop) - { - if (m_nextVert == 0) - { - m_firstPos = projPt; - m_firstW = w; - m_secondPos = projPt; - m_firstUV = uv; - m_firstColor = color; - m_firstWidth = adjWidth; - } - else if (m_nextVert == 1) - { - m_secondPos = projPt; - } + if (m_mode == EPrimitiveMode::LineLoop) { + if (m_nextVert == 0) { + m_firstPos = projPt; + m_firstW = w; + m_secondPos = projPt; + m_firstUV = uv; + m_firstColor = color; + m_firstWidth = adjWidth; + } else if (m_nextVert == 1) { + m_secondPos = projPt; } + } - if (m_nextVert > 1) - { + if (m_nextVert > 1) { + zeus::CVector2f dva = (m_lastPos - m_lastPos2).toVec2f(); + if (!dva.canBeNormalized()) + dva = {0.f, 1.f}; + dva = dva.normalized().perpendicularVector() * m_lastWidth; + dva.x() /= CGraphics::g_ProjAspect; + + zeus::CVector2f dvb = (projPt - m_lastPos).toVec2f(); + if (!dvb.canBeNormalized()) + dvb = {0.f, 1.f}; + dvb = dvb.normalized().perpendicularVector() * m_lastWidth; + dvb.x() /= CGraphics::g_ProjAspect; + + if (m_textured) { + if (m_mode == EPrimitiveMode::Lines) { + if (m_nextVert & 1) { + g_StaticLineVertsTex.push_back(g_StaticLineVertsTex.back()); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back(g_StaticLineVertsTex.back()); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor, m_lastUV}); + } else { + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor, m_lastUV}); + } + } else { + zeus::CVector3f intersect1; + bool good1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva, m_lastPos.toVec2f() + dvb, + projPt.toVec2f() + dvb, intersect1); + if ((intersect1.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) + good1 = false; + + zeus::CVector3f intersect2; + bool good2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva, m_lastPos.toVec2f() - dvb, + projPt.toVec2f() - dvb, intersect2); + if ((intersect2.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) + good2 = false; + + if (good1 && good2) { + intersect1.z() = float(m_lastPos.z()); + intersect2.z() = float(m_lastPos.z()); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor, m_lastUV}); + } else { + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor, m_lastUV}); + } + } + } else { + if (m_mode == EPrimitiveMode::Lines) { + if (m_nextVert & 1) { + g_StaticLineVertsNoTex.push_back(g_StaticLineVertsNoTex.back()); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back(g_StaticLineVertsNoTex.back()); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor}); + } else { + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor}); + } + } else { + zeus::CVector3f intersect1; + bool good1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva, m_lastPos.toVec2f() + dvb, + projPt.toVec2f() + dvb, intersect1); + if ((intersect1.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) + good1 = false; + + zeus::CVector3f intersect2; + bool good2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva, m_lastPos.toVec2f() - dvb, + projPt.toVec2f() - dvb, intersect2); + if ((intersect2.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) + good2 = false; + + if (good1 && good2) { + intersect1.z() = float(m_lastPos.z()); + intersect2.z() = float(m_lastPos.z()); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor}); + } else { + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor}); + } + } + } + } else if (m_nextVert == 1) { + zeus::CVector2f dv = (projPt - m_lastPos).toVec2f(); + if (!dv.canBeNormalized()) + dv = {0.f, 1.f}; + dv = dv.normalized().perpendicularVector() * m_lastWidth; + dv.x() /= CGraphics::g_ProjAspect; + if (m_textured) { + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dv, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dv, m_lastW), m_lastColor, m_lastUV}); + } else { + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dv, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dv, m_lastW), m_lastColor}); + } + } + + m_lastPos2 = m_lastPos; + m_lastPos = projPt; + m_lastW = w; + m_lastUV = uv; + m_lastColor = color; + m_lastWidth = adjWidth; + ++m_nextVert; +} + +void CLineRenderer::Render(const zeus::CColor& moduColor) { + if (!m_final && m_nextVert > 1) { + if (m_mode == EPrimitiveMode::LineLoop) { + { zeus::CVector2f dva = (m_lastPos - m_lastPos2).toVec2f(); if (!dva.canBeNormalized()) - dva = {0.f, 1.f}; + dva = {0.f, 1.f}; dva = dva.normalized().perpendicularVector() * m_lastWidth; dva.x() /= CGraphics::g_ProjAspect; - zeus::CVector2f dvb = (projPt - m_lastPos).toVec2f(); + zeus::CVector2f dvb = (m_firstPos - m_lastPos).toVec2f(); if (!dvb.canBeNormalized()) - dvb = {0.f, 1.f}; + dvb = {0.f, 1.f}; dvb = dvb.normalized().perpendicularVector() * m_lastWidth; dvb.x() /= CGraphics::g_ProjAspect; - if (m_textured) - { - if (m_mode == EPrimitiveMode::Lines) - { - if (m_nextVert & 1) - { - g_StaticLineVertsTex.push_back(g_StaticLineVertsTex.back()); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back(g_StaticLineVertsTex.back()); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor, m_lastUV}); - } - else - { - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor, m_lastUV}); - } - } - else - { - zeus::CVector3f intersect1; - bool good1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva, - m_lastPos.toVec2f() + dvb, projPt.toVec2f() + dvb, intersect1); - if ((intersect1.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) - good1 = false; + zeus::CVector3f intersect1; + bool good1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva, m_lastPos.toVec2f() + dvb, + m_firstPos.toVec2f() + dvb, intersect1); + if ((intersect1.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) + good1 = false; - zeus::CVector3f intersect2; - bool good2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva, - m_lastPos.toVec2f() - dvb, projPt.toVec2f() - dvb, intersect2); - if ((intersect2.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) - good2 = false; + zeus::CVector3f intersect2; + bool good2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva, m_lastPos.toVec2f() - dvb, + m_firstPos.toVec2f() - dvb, intersect2); + if ((intersect2.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) + good2 = false; - if (good1 && good2) - { - intersect1.z() = float(m_lastPos.z()); - intersect2.z() = float(m_lastPos.z()); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor, m_lastUV}); - } - else - { - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor, m_lastUV}); - } - } + if (m_textured) { + if (good1 && good2) { + intersect1.z() = float(m_lastPos.z()); + intersect2.z() = float(m_lastPos.z()); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor, m_lastUV}); + } else { + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor, m_lastUV}); + } + } else { + if (good1 && good2) { + intersect1.z() = float(m_lastPos.z()); + intersect2.z() = float(m_lastPos.z()); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor}); + } else { + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor}); + } } - else - { - if (m_mode == EPrimitiveMode::Lines) - { - if (m_nextVert & 1) - { - g_StaticLineVertsNoTex.push_back(g_StaticLineVertsNoTex.back()); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back(g_StaticLineVertsNoTex.back()); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor}); - } - else - { - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor}); - } - } - else - { - zeus::CVector3f intersect1; - bool good1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva, - m_lastPos.toVec2f() + dvb, projPt.toVec2f() + dvb, intersect1); - if ((intersect1.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) - good1 = false; + } + { + zeus::CVector2f dva = (m_firstPos - m_lastPos).toVec2f(); + if (!dva.canBeNormalized()) + dva = {0.f, 1.f}; + dva = dva.normalized().perpendicularVector() * m_firstWidth; + dva.x() /= CGraphics::g_ProjAspect; - zeus::CVector3f intersect2; - bool good2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva, - m_lastPos.toVec2f() - dvb, projPt.toVec2f() - dvb, intersect2); - if ((intersect2.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) - good2 = false; + zeus::CVector2f dvb = (m_secondPos - m_firstPos).toVec2f(); + if (!dvb.canBeNormalized()) + dvb = {0.f, 1.f}; + dvb = dvb.normalized().perpendicularVector() * m_firstWidth; + dvb.x() /= CGraphics::g_ProjAspect; - if (good1 && good2) - { - intersect1.z() = float(m_lastPos.z()); - intersect2.z() = float(m_lastPos.z()); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor}); - } - else - { - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor}); - } - } + zeus::CVector3f intersect1; + bool good1 = IntersectLines(m_lastPos.toVec2f() + dva, m_firstPos.toVec2f() + dva, m_firstPos.toVec2f() + dvb, + m_secondPos.toVec2f() + dvb, intersect1); + if ((intersect1.toVec2f() - m_firstPos.toVec2f()).magnitude() > m_firstWidth * 2.f) + good1 = false; + + zeus::CVector3f intersect2; + bool good2 = IntersectLines(m_lastPos.toVec2f() - dva, m_firstPos.toVec2f() - dva, m_firstPos.toVec2f() - dvb, + m_secondPos.toVec2f() - dvb, intersect2); + if ((intersect2.toVec2f() - m_firstPos.toVec2f()).magnitude() > m_firstWidth * 2.f) + good2 = false; + + if (m_textured) { + if (good1 && good2) { + intersect1.z() = float(m_firstPos.z()); + intersect2.z() = float(m_firstPos.z()); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor, m_lastUV}); + } else { + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_firstPos + dva, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_firstPos - dva, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_firstPos + dvb, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_firstPos - dvb, m_lastW), m_lastColor, m_lastUV}); + } + } else { + if (good1 && good2) { + intersect1.z() = float(m_firstPos.z()); + intersect2.z() = float(m_firstPos.z()); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor}); + } else { + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_firstPos + dva, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_firstPos - dva, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_firstPos + dvb, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_firstPos - dvb, m_lastW), m_lastColor}); + } } - } - else if (m_nextVert == 1) - { - zeus::CVector2f dv = (projPt - m_lastPos).toVec2f(); - if (!dv.canBeNormalized()) - dv = {0.f, 1.f}; - dv = dv.normalized().perpendicularVector() * m_lastWidth; - dv.x() /= CGraphics::g_ProjAspect; - if (m_textured) - { - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dv, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dv, m_lastW), m_lastColor, m_lastUV}); + } + } else { + zeus::CVector2f dv = (m_lastPos - m_lastPos2).toVec2f(); + if (!dv.canBeNormalized()) + dv = {0.f, 1.f}; + dv = dv.normalized().perpendicularVector() * m_lastWidth; + dv.x() /= CGraphics::g_ProjAspect; + if (m_textured) { + if (m_mode == EPrimitiveMode::Lines && (m_nextVert & 1)) { + } else { + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dv, m_lastW), m_lastColor, m_lastUV}); + g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dv, m_lastW), m_lastColor, m_lastUV}); } - else - { - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dv, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dv, m_lastW), m_lastColor}); + } else { + if (m_mode == EPrimitiveMode::Lines && (m_nextVert & 1)) { + } else { + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dv, m_lastW), m_lastColor}); + g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dv, m_lastW), m_lastColor}); } + } } - m_lastPos2 = m_lastPos; - m_lastPos = projPt; - m_lastW = w; - m_lastUV = uv; - m_lastColor = color; - m_lastWidth = adjWidth; - ++m_nextVert; + m_final = true; + } + + m_uniformBuf.access() = SDrawUniform{moduColor}; + if (m_textured) { + memmove(m_vertBufTex.access(), g_StaticLineVertsTex.data(), sizeof(SDrawVertTex) * g_StaticLineVertsTex.size()); + CGraphics::SetShaderDataBinding(m_shaderBind); + CGraphics::DrawArray(0, g_StaticLineVertsTex.size()); + } else { + memmove(m_vertBufNoTex.access(), g_StaticLineVertsNoTex.data(), + sizeof(SDrawVertNoTex) * g_StaticLineVertsNoTex.size()); + CGraphics::SetShaderDataBinding(m_shaderBind); + CGraphics::DrawArray(0, g_StaticLineVertsNoTex.size()); + } } -void CLineRenderer::Render(const zeus::CColor& moduColor) -{ - if (!m_final && m_nextVert > 1) - { - if (m_mode == EPrimitiveMode::LineLoop) - { - { - zeus::CVector2f dva = (m_lastPos - m_lastPos2).toVec2f(); - if (!dva.canBeNormalized()) - dva = {0.f, 1.f}; - dva = dva.normalized().perpendicularVector() * m_lastWidth; - dva.x() /= CGraphics::g_ProjAspect; - - zeus::CVector2f dvb = (m_firstPos - m_lastPos).toVec2f(); - if (!dvb.canBeNormalized()) - dvb = {0.f, 1.f}; - dvb = dvb.normalized().perpendicularVector() * m_lastWidth; - dvb.x() /= CGraphics::g_ProjAspect; - - zeus::CVector3f intersect1; - bool good1 = IntersectLines(m_lastPos2.toVec2f() + dva, m_lastPos.toVec2f() + dva, - m_lastPos.toVec2f() + dvb, m_firstPos.toVec2f() + dvb, intersect1); - if ((intersect1.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) - good1 = false; - - zeus::CVector3f intersect2; - bool good2 = IntersectLines(m_lastPos2.toVec2f() - dva, m_lastPos.toVec2f() - dva, - m_lastPos.toVec2f() - dvb, m_firstPos.toVec2f() - dvb, intersect2); - if ((intersect2.toVec2f() - m_lastPos.toVec2f()).magnitude() > m_lastWidth * 2.f) - good2 = false; - - if (m_textured) - { - if (good1 && good2) - { - intersect1.z() = float(m_lastPos.z()); - intersect2.z() = float(m_lastPos.z()); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor, m_lastUV}); - } - else - { - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor, m_lastUV}); - } - } - else - { - if (good1 && good2) - { - intersect1.z() = float(m_lastPos.z()); - intersect2.z() = float(m_lastPos.z()); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor}); - } - else - { - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dva, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dva, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dvb, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dvb, m_lastW), m_lastColor}); - } - } - } - { - zeus::CVector2f dva = (m_firstPos - m_lastPos).toVec2f(); - if (!dva.canBeNormalized()) - dva = {0.f, 1.f}; - dva = dva.normalized().perpendicularVector() * m_firstWidth; - dva.x() /= CGraphics::g_ProjAspect; - - zeus::CVector2f dvb = (m_secondPos - m_firstPos).toVec2f(); - if (!dvb.canBeNormalized()) - dvb = {0.f, 1.f}; - dvb = dvb.normalized().perpendicularVector() * m_firstWidth; - dvb.x() /= CGraphics::g_ProjAspect; - - zeus::CVector3f intersect1; - bool good1 = IntersectLines(m_lastPos.toVec2f() + dva, m_firstPos.toVec2f() + dva, - m_firstPos.toVec2f() + dvb, m_secondPos.toVec2f() + dvb, intersect1); - if ((intersect1.toVec2f() - m_firstPos.toVec2f()).magnitude() > m_firstWidth * 2.f) - good1 = false; - - zeus::CVector3f intersect2; - bool good2 = IntersectLines(m_lastPos.toVec2f() - dva, m_firstPos.toVec2f() - dva, - m_firstPos.toVec2f() - dvb, m_secondPos.toVec2f() - dvb, intersect2); - if ((intersect2.toVec2f() - m_firstPos.toVec2f()).magnitude() > m_firstWidth * 2.f) - good2 = false; - - if (m_textured) - { - if (good1 && good2) - { - intersect1.z() = float(m_firstPos.z()); - intersect2.z() = float(m_firstPos.z()); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor, m_lastUV}); - } - else - { - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_firstPos + dva, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_firstPos - dva, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_firstPos + dvb, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_firstPos - dvb, m_lastW), m_lastColor, m_lastUV}); - } - } - else - { - if (good1 && good2) - { - intersect1.z() = float(m_firstPos.z()); - intersect2.z() = float(m_firstPos.z()); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect1, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(intersect2, m_lastW), m_lastColor}); - } - else - { - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_firstPos + dva, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_firstPos - dva, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_firstPos + dvb, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_firstPos - dvb, m_lastW), m_lastColor}); - } - } - } - } - else - { - zeus::CVector2f dv = (m_lastPos - m_lastPos2).toVec2f(); - if (!dv.canBeNormalized()) - dv = {0.f, 1.f}; - dv = dv.normalized().perpendicularVector() * m_lastWidth; - dv.x() /= CGraphics::g_ProjAspect; - if (m_textured) - { - if (m_mode == EPrimitiveMode::Lines && (m_nextVert & 1)) - {} - else - { - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dv, m_lastW), m_lastColor, m_lastUV}); - g_StaticLineVertsTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dv, m_lastW), m_lastColor, m_lastUV}); - } - } - else - { - if (m_mode == EPrimitiveMode::Lines && (m_nextVert & 1)) - {} - else - { - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos + dv, m_lastW), m_lastColor}); - g_StaticLineVertsNoTex.push_back({zeus::CVector4f::ToClip(m_lastPos - dv, m_lastW), m_lastColor}); - } - } - } - - m_final = true; - } - - m_uniformBuf.access() = SDrawUniform{moduColor}; - if (m_textured) - { - memmove(m_vertBufTex.access(), g_StaticLineVertsTex.data(), - sizeof(SDrawVertTex) * g_StaticLineVertsTex.size()); - CGraphics::SetShaderDataBinding(m_shaderBind); - CGraphics::DrawArray(0, g_StaticLineVertsTex.size()); - } - else - { - memmove(m_vertBufNoTex.access(), g_StaticLineVertsNoTex.data(), - sizeof(SDrawVertNoTex) * g_StaticLineVertsNoTex.size()); - CGraphics::SetShaderDataBinding(m_shaderBind); - CGraphics::DrawArray(0, g_StaticLineVertsNoTex.size()); - } -} - -} +} // namespace urde diff --git a/Runtime/Graphics/CLineRenderer.hpp b/Runtime/Graphics/CLineRenderer.hpp index a894182c9..4d12477fb 100644 --- a/Runtime/Graphics/CLineRenderer.hpp +++ b/Runtime/Graphics/CLineRenderer.hpp @@ -8,93 +8,80 @@ #include "hecl/VertexBufferPool.hpp" #include "hecl/UniformBufferPool.hpp" -namespace urde -{ +namespace urde { -class CLineRenderer -{ +class CLineRenderer { public: - enum class EPrimitiveMode - { - Lines, - LineStrip, - LineLoop - }; + enum class EPrimitiveMode { Lines, LineStrip, LineLoop }; - struct SDrawVertTex - { - zeus::CVector4f pos; - zeus::CColor color; - zeus::CVector2f uv; - }; + struct SDrawVertTex { + zeus::CVector4f pos; + zeus::CColor color; + zeus::CVector2f uv; + }; - struct SDrawVertNoTex - { - zeus::CVector4f pos; - zeus::CColor color; - }; + struct SDrawVertNoTex { + zeus::CVector4f pos; + zeus::CColor color; + }; - struct SDrawUniform - { - zeus::CColor moduColor; - }; + struct SDrawUniform { + zeus::CColor moduColor; + }; private: - EPrimitiveMode m_mode; - u32 m_maxVerts; - u32 m_nextVert = 0; - bool m_final = false; - bool m_textured; + EPrimitiveMode m_mode; + u32 m_maxVerts; + u32 m_nextVert = 0; + bool m_final = false; + bool m_textured; - zeus::CVector3f m_firstPos; - zeus::CVector3f m_secondPos; - zeus::CVector2f m_firstUV; - zeus::CColor m_firstColor; - float m_firstWidth; - float m_firstW; + zeus::CVector3f m_firstPos; + zeus::CVector3f m_secondPos; + zeus::CVector2f m_firstUV; + zeus::CColor m_firstColor; + float m_firstWidth; + float m_firstW; - zeus::CVector3f m_lastPos; - zeus::CVector3f m_lastPos2; - zeus::CVector2f m_lastUV; - zeus::CColor m_lastColor; - float m_lastWidth; - float m_lastW; + zeus::CVector3f m_lastPos; + zeus::CVector3f m_lastPos2; + zeus::CVector2f m_lastUV; + zeus::CColor m_lastColor; + float m_lastWidth; + float m_lastW; - static rstl::reserved_vector g_StaticLineVertsTex; - static rstl::reserved_vector g_StaticLineVertsNoTex; + static rstl::reserved_vector g_StaticLineVertsTex; + static rstl::reserved_vector g_StaticLineVertsNoTex; - static hecl::VertexBufferPool s_vertPoolTex; - static hecl::VertexBufferPool s_vertPoolNoTex; - static hecl::UniformBufferPool s_uniformPool; + static hecl::VertexBufferPool s_vertPoolTex; + static hecl::VertexBufferPool s_vertPoolNoTex; + static hecl::UniformBufferPool s_uniformPool; public: - hecl::VertexBufferPool::Token m_vertBufTex; - hecl::VertexBufferPool::Token m_vertBufNoTex; - hecl::UniformBufferPool::Token m_uniformBuf; - boo::ObjToken m_shaderBind; + hecl::VertexBufferPool::Token m_vertBufTex; + hecl::VertexBufferPool::Token m_vertBufNoTex; + hecl::UniformBufferPool::Token m_uniformBuf; + boo::ObjToken m_shaderBind; - CLineRenderer(boo::IGraphicsDataFactory::Context& ctx, - EPrimitiveMode mode, u32 maxVerts, const boo::ObjToken& texture, - bool additive, bool zTest = false, bool zGEqual = false); - CLineRenderer(EPrimitiveMode mode, u32 maxVerts, const boo::ObjToken& texture, - bool additive, bool zTest = false, bool zGEqual = false); - CLineRenderer(CLineRenderer&&) = default; + CLineRenderer(boo::IGraphicsDataFactory::Context& ctx, EPrimitiveMode mode, u32 maxVerts, + const boo::ObjToken& texture, bool additive, bool zTest = false, bool zGEqual = false); + CLineRenderer(EPrimitiveMode mode, u32 maxVerts, const boo::ObjToken& texture, bool additive, + bool zTest = false, bool zGEqual = false); + CLineRenderer(CLineRenderer&&) = default; - void Reset(); - void AddVertex(const zeus::CVector3f& position, const zeus::CColor& color, float width, - const zeus::CVector2f& uv=zeus::CVector2f::skZero); - void Render(const zeus::CColor& moduColor=zeus::CColor::skWhite); + void Reset(); + void AddVertex(const zeus::CVector3f& position, const zeus::CColor& color, float width, + const zeus::CVector2f& uv = zeus::CVector2f::skZero); + void Render(const zeus::CColor& moduColor = zeus::CColor::skWhite); - static void UpdateBuffers() - { - s_vertPoolTex.updateBuffers(); - s_vertPoolNoTex.updateBuffers(); - s_uniformPool.updateBuffers(); - } + static void UpdateBuffers() { + s_vertPoolTex.updateBuffers(); + s_vertPoolNoTex.updateBuffers(); + s_uniformPool.updateBuffers(); + } - static void Initialize(); - static void Shutdown(); + static void Initialize(); + static void Shutdown(); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CMetroidModelInstance.hpp b/Runtime/Graphics/CMetroidModelInstance.hpp index e349c4980..3e132560d 100644 --- a/Runtime/Graphics/CMetroidModelInstance.hpp +++ b/Runtime/Graphics/CMetroidModelInstance.hpp @@ -7,37 +7,34 @@ #include "hecl/HMDLMeta.hpp" #include "Shaders/CModelShaders.hpp" -namespace urde -{ +namespace urde { class CBooModel; struct CBooSurface; -class CMetroidModelInstance -{ - friend class CBooRenderer; - friend class CGameArea; +class CMetroidModelInstance { + friend class CBooRenderer; + friend class CGameArea; + + int x0_visorFlags; + zeus::CTransform x4_xf; + zeus::CAABox x34_aabb; + std::vector m_surfaces; + std::unique_ptr m_instance; + hecl::HMDLMeta m_hmdlMeta; + std::unordered_map m_shaders; - int x0_visorFlags; - zeus::CTransform x4_xf; - zeus::CAABox x34_aabb; - std::vector m_surfaces; - std::unique_ptr m_instance; - hecl::HMDLMeta m_hmdlMeta; - std::unordered_map m_shaders; public: - CMetroidModelInstance() = default; - CMetroidModelInstance(CMetroidModelInstance&&) = default; - void Clear() - { - x0_visorFlags = 0; - x4_xf = {}; - x34_aabb = {}; - m_surfaces.clear(); - m_instance.reset(); - m_hmdlMeta = {}; - m_shaders.clear(); - } + CMetroidModelInstance() = default; + CMetroidModelInstance(CMetroidModelInstance&&) = default; + void Clear() { + x0_visorFlags = 0; + x4_xf = {}; + x34_aabb = {}; + m_surfaces.clear(); + m_instance.reset(); + m_hmdlMeta = {}; + m_shaders.clear(); + } }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index c1a55ad46..56eaefbc9 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -11,8 +11,7 @@ #include "hecl/HMDLMeta.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { class IObjectStore; class CTexture; class CLight; @@ -20,324 +19,285 @@ class CSkinRules; class CPoseAsTransforms; class CModel; -struct CModelFlags -{ - u8 x0_blendMode = 0; /* >6: additive, >4: blend, else opaque */ - u8 x1_matSetIdx = 0; - EExtendedShader m_extendedShader = EExtendedShader::Lighting; - bool m_noCull = false; - bool m_noZWrite = false; - u16 x2_flags = 0; /* Flags */ - zeus::CColor x4_color; /* Set into kcolor slot specified by material */ - zeus::CColor addColor = zeus::CColor::skClear; - zeus::CAABox mbShadowBox; +struct CModelFlags { + u8 x0_blendMode = 0; /* >6: additive, >4: blend, else opaque */ + u8 x1_matSetIdx = 0; + EExtendedShader m_extendedShader = EExtendedShader::Lighting; + bool m_noCull = false; + bool m_noZWrite = false; + u16 x2_flags = 0; /* Flags */ + zeus::CColor x4_color; /* Set into kcolor slot specified by material */ + zeus::CColor addColor = zeus::CColor::skClear; + zeus::CAABox mbShadowBox; - CModelFlags() = default; - CModelFlags(u8 blendMode, u8 shadIdx, u16 flags, const zeus::CColor& col) - : x0_blendMode(blendMode), x1_matSetIdx(shadIdx), - x2_flags(flags), x4_color(col) - { - /* Blend mode will override this if the surface's original material is opaque */ - } + CModelFlags() = default; + CModelFlags(u8 blendMode, u8 shadIdx, u16 flags, const zeus::CColor& col) + : x0_blendMode(blendMode), x1_matSetIdx(shadIdx), x2_flags(flags), x4_color(col) { + /* Blend mode will override this if the surface's original material is opaque */ + } - /* Flags - 0x1: depth equal - 0x2: depth update - 0x4: render without texture lock - 0x8: depth greater - 0x10: depth non-inclusive - */ + /* Flags + 0x1: depth equal + 0x2: depth update + 0x4: render without texture lock + 0x8: depth greater + 0x10: depth non-inclusive + */ - bool operator==(const CModelFlags& other) const - { - return x0_blendMode == other.x0_blendMode && x1_matSetIdx == other.x1_matSetIdx && - x2_flags == other.x2_flags && x4_color == other.x4_color; - } + bool operator==(const CModelFlags& other) const { + return x0_blendMode == other.x0_blendMode && x1_matSetIdx == other.x1_matSetIdx && x2_flags == other.x2_flags && + x4_color == other.x4_color; + } - bool operator!=(const CModelFlags& other) const - { - return x0_blendMode != other.x0_blendMode || x1_matSetIdx != other.x1_matSetIdx || - x2_flags != other.x2_flags || x4_color != other.x4_color; - } + bool operator!=(const CModelFlags& other) const { + return x0_blendMode != other.x0_blendMode || x1_matSetIdx != other.x1_matSetIdx || x2_flags != other.x2_flags || + x4_color != other.x4_color; + } }; /* urde addition: doesn't require hacky stashing of * pointers within loaded CMDL buffer */ -struct CBooSurface -{ - DataSpec::DNACMDL::SurfaceHeader_2 m_data; - size_t selfIdx; - class CBooModel* m_parent = nullptr; - CBooSurface* m_next = nullptr; +struct CBooSurface { + DataSpec::DNACMDL::SurfaceHeader_2 m_data; + size_t selfIdx; + class CBooModel* m_parent = nullptr; + CBooSurface* m_next = nullptr; - zeus::CAABox GetBounds() const - { - if (!m_data.aabbSz) - return zeus::CAABox(m_data.centroid, m_data.centroid); - else - return zeus::CAABox(m_data.aabb[0], m_data.aabb[1]); - } + zeus::CAABox GetBounds() const { + if (!m_data.aabbSz) + return zeus::CAABox(m_data.centroid, m_data.centroid); + else + return zeus::CAABox(m_data.aabb[0], m_data.aabb[1]); + } }; using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet; using UVAnimation = DataSpec::DNAMP1::MaterialSet::Material::UVAnimation; -struct GeometryUniformLayout -{ - boo::ObjToken m_sharedBuffer[2]; - size_t m_geomBufferSize = 0; - size_t m_skinBankCount = 0; - size_t m_weightVecCount = 0; +struct GeometryUniformLayout { + boo::ObjToken m_sharedBuffer[2]; + size_t m_geomBufferSize = 0; + size_t m_skinBankCount = 0; + size_t m_weightVecCount = 0; - std::vector m_skinOffs; - std::vector m_skinSizes; + std::vector m_skinOffs; + std::vector m_skinSizes; - std::vector m_uvOffs; - std::vector m_uvSizes; + std::vector m_uvOffs; + std::vector m_uvSizes; - GeometryUniformLayout(const CModel* model, const MaterialSet* matSet); - void Update(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose, - const MaterialSet* matSet, const boo::ObjToken& buf, - const CBooModel* parent) const; + GeometryUniformLayout(const CModel* model, const MaterialSet* matSet); + void Update(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose, + const MaterialSet* matSet, const boo::ObjToken& buf, + const CBooModel* parent) const; }; -struct SShader -{ - std::vector> x0_textures; - std::unordered_map m_shaders; - MaterialSet m_matSet; - std::experimental::optional m_geomLayout; - int m_matSetIdx; - SShader(int idx) : m_matSetIdx(idx) - { - x0_textures.clear(); - m_shaders.clear(); - } - void InitializeLayout(const CModel* model) { m_geomLayout.emplace(model, &m_matSet); } - void UnlockTextures(); - CModelShaders::ShaderPipelines - BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat); - void BuildShaders(const hecl::HMDLMeta& meta, - std::unordered_map& shaders); - void BuildShaders(const hecl::HMDLMeta& meta) { BuildShaders(meta, m_shaders); } +struct SShader { + std::vector> x0_textures; + std::unordered_map m_shaders; + MaterialSet m_matSet; + std::experimental::optional m_geomLayout; + int m_matSetIdx; + SShader(int idx) : m_matSetIdx(idx) { + x0_textures.clear(); + m_shaders.clear(); + } + void InitializeLayout(const CModel* model) { m_geomLayout.emplace(model, &m_matSet); } + void UnlockTextures(); + CModelShaders::ShaderPipelines BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat); + void BuildShaders(const hecl::HMDLMeta& meta, std::unordered_map& shaders); + void BuildShaders(const hecl::HMDLMeta& meta) { BuildShaders(meta, m_shaders); } }; -class CBooModel -{ - friend class CModel; - friend class CGameArea; - friend class CBooRenderer; - friend class CMetroidModelInstance; - friend class CSkinnedModel; - friend struct GeometryUniformLayout; +class CBooModel { + friend class CModel; + friend class CGameArea; + friend class CBooRenderer; + friend class CMetroidModelInstance; + friend class CSkinnedModel; + friend struct GeometryUniformLayout; + public: - enum class ESurfaceSelection - { - UnsortedOnly, - SortedOnly, - All - }; + enum class ESurfaceSelection { UnsortedOnly, SortedOnly, All }; private: - CBooModel* m_next = nullptr; - CBooModel* m_prev = nullptr; - int m_uniUpdateCount = 0; - TToken m_modelTok; - CModel* m_model; - std::vector* x0_surfaces; - const MaterialSet* x4_matSet; - const GeometryUniformLayout* m_geomLayout; - int m_matSetIdx = -1; - const std::unordered_map* m_pipelines; - std::vector> x1c_textures; - zeus::CAABox x20_aabb; - CBooSurface* x38_firstUnsortedSurface = nullptr; - CBooSurface* x3c_firstSortedSurface = nullptr; - bool x40_24_texturesLoaded : 1; - bool x40_25_modelVisible : 1; - u8 x41_mask; - u32 x44_areaInstanceIdx = -1; + CBooModel* m_next = nullptr; + CBooModel* m_prev = nullptr; + int m_uniUpdateCount = 0; + TToken m_modelTok; + CModel* m_model; + std::vector* x0_surfaces; + const MaterialSet* x4_matSet; + const GeometryUniformLayout* m_geomLayout; + int m_matSetIdx = -1; + const std::unordered_map* m_pipelines; + std::vector> x1c_textures; + zeus::CAABox x20_aabb; + CBooSurface* x38_firstUnsortedSurface = nullptr; + CBooSurface* x3c_firstSortedSurface = nullptr; + bool x40_24_texturesLoaded : 1; + bool x40_25_modelVisible : 1; + u8 x41_mask; + u32 x44_areaInstanceIdx = -1; - struct UVAnimationBuffer - { - static void ProcessAnimation(u8*& bufOut, const UVAnimation& anim); - static void PadOutBuffer(u8*& bufStart, u8*& bufOut); - static void Update(u8*& bufOut, const MaterialSet* matSet, - const CModelFlags& flags, const CBooModel* parent); - }; + struct UVAnimationBuffer { + static void ProcessAnimation(u8*& bufOut, const UVAnimation& anim); + static void PadOutBuffer(u8*& bufStart, u8*& bufOut); + static void Update(u8*& bufOut, const MaterialSet* matSet, const CModelFlags& flags, const CBooModel* parent); + }; - CModelShaders::LightingUniform m_lightingData; + CModelShaders::LightingUniform m_lightingData; - /* urde addition: boo! */ - size_t m_uniformDataSize = 0; - struct ModelInstance - { - boo::ObjToken m_geomUniformBuffer; - boo::ObjToken m_uniformBuffer; - std::vector>> m_shaderDataBindings; - boo::ObjToken m_dynamicVbo; + /* urde addition: boo! */ + size_t m_uniformDataSize = 0; + struct ModelInstance { + boo::ObjToken m_geomUniformBuffer; + boo::ObjToken m_uniformBuffer; + std::vector>> m_shaderDataBindings; + boo::ObjToken m_dynamicVbo; - boo::ObjToken GetBooVBO(const CBooModel& model, boo::IGraphicsDataFactory::Context& ctx); - }; - std::vector m_instances; + boo::ObjToken GetBooVBO(const CBooModel& model, boo::IGraphicsDataFactory::Context& ctx); + }; + std::vector m_instances; - boo::ObjToken m_staticVbo; - boo::ObjToken m_staticIbo; + boo::ObjToken m_staticVbo; + boo::ObjToken m_staticIbo; - boo::ObjToken m_txtrOverrides[8]; + boo::ObjToken m_txtrOverrides[8]; - boo::ObjToken m_lastDrawnShadowMap; - boo::ObjToken m_lastDrawnOneTexture; + boo::ObjToken m_lastDrawnShadowMap; + boo::ObjToken m_lastDrawnOneTexture; - ModelInstance* PushNewModelInstance(int sharedLayoutBuf = -1); - void DrawAlphaSurfaces(const CModelFlags& flags) const; - void DrawNormalSurfaces(const CModelFlags& flags) const; - void DrawSurfaces(const CModelFlags& flags) const; - void DrawSurface(const CBooSurface& surf, const CModelFlags& flags) const; - void WarmupDrawSurfaces() const; - void WarmupDrawSurface(const CBooSurface& surf) const; + ModelInstance* PushNewModelInstance(int sharedLayoutBuf = -1); + void DrawAlphaSurfaces(const CModelFlags& flags) const; + void DrawNormalSurfaces(const CModelFlags& flags) const; + void DrawSurfaces(const CModelFlags& flags) const; + void DrawSurface(const CBooSurface& surf, const CModelFlags& flags) const; + void WarmupDrawSurfaces() const; + void WarmupDrawSurface(const CBooSurface& surf) const; - static zeus::CVector3f g_PlayerPosition; - static float g_ModSeconds; - static float g_TransformedTime; - static float g_TransformedTime2; - static CBooModel* g_LastModelCached; + static zeus::CVector3f g_PlayerPosition; + static float g_ModSeconds; + static float g_TransformedTime; + static float g_TransformedTime2; + static CBooModel* g_LastModelCached; - static bool g_DummyTextures; - static bool g_RenderModelBlack; + static bool g_DummyTextures; + static bool g_RenderModelBlack; public: - ~CBooModel(); - CBooModel(TToken& token, CModel* parent, std::vector* surfaces, SShader& shader, - const boo::ObjToken& vbo, const boo::ObjToken& ibo, - const zeus::CAABox& aabb, u8 renderMask, int numInsts, const boo::ObjToken txtrOverrides[8]); + ~CBooModel(); + CBooModel(TToken& token, CModel* parent, std::vector* surfaces, SShader& shader, + const boo::ObjToken& vbo, const boo::ObjToken& ibo, + const zeus::CAABox& aabb, u8 renderMask, int numInsts, const boo::ObjToken txtrOverrides[8]); - static void MakeTexturesFromMats(const MaterialSet& matSet, - std::vector>& toksOut, - IObjectStore& store); - void MakeTexturesFromMats(std::vector>& toksOut, - IObjectStore& store); + static void MakeTexturesFromMats(const MaterialSet& matSet, std::vector>& toksOut, + IObjectStore& store); + void MakeTexturesFromMats(std::vector>& toksOut, IObjectStore& store); - bool IsOpaque() const {return x3c_firstSortedSurface == nullptr;} - void ActivateLights(const std::vector& lights); - void DisableAllLights(); - void RemapMaterialData(SShader& shader); - void RemapMaterialData(SShader& shader, - const std::unordered_map& pipelines); - bool TryLockTextures() const; - void UnlockTextures() const; - void SyncLoadTextures() const; - void Touch(int shaderIdx) const; - void VerifyCurrentShader(int shaderIdx); - boo::ObjToken UpdateUniformData(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose, - int sharedLayoutBuf = -1) const; - void DrawAlpha(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose) const; - void DrawNormal(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose) const; - void Draw(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose) const; - void DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) const; + bool IsOpaque() const { return x3c_firstSortedSurface == nullptr; } + void ActivateLights(const std::vector& lights); + void DisableAllLights(); + void RemapMaterialData(SShader& shader); + void RemapMaterialData(SShader& shader, const std::unordered_map& pipelines); + bool TryLockTextures() const; + void UnlockTextures() const; + void SyncLoadTextures() const; + void Touch(int shaderIdx) const; + void VerifyCurrentShader(int shaderIdx); + boo::ObjToken UpdateUniformData(const CModelFlags& flags, const CSkinRules* cskr, + const CPoseAsTransforms* pose, int sharedLayoutBuf = -1) const; + void DrawAlpha(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose) const; + void DrawNormal(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose) const; + void Draw(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose) const; + void DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) const; - void LockParent() { m_modelTok.Lock(); } - void UnlockParent() { m_modelTok.Unlock(); } + void LockParent() { m_modelTok.Lock(); } + void UnlockParent() { m_modelTok.Unlock(); } + const MaterialSet::Material& GetMaterialByIndex(int idx) const { return x4_matSet->materials.at(idx); } - const MaterialSet::Material& GetMaterialByIndex(int idx) const - { - return x4_matSet->materials.at(idx); - } + void ClearUniformCounter() { m_uniUpdateCount = 0; } + static void ClearModelUniformCounters(); - void ClearUniformCounter() { m_uniUpdateCount = 0; } - static void ClearModelUniformCounters(); + static bool g_DrawingOccluders; + static void SetDrawingOccluders(bool occ) { g_DrawingOccluders = occ; } - static bool g_DrawingOccluders; - static void SetDrawingOccluders(bool occ) {g_DrawingOccluders = occ;} + static void SetNewPlayerPositionAndTime(const zeus::CVector3f& pos); - static void SetNewPlayerPositionAndTime(const zeus::CVector3f& pos); + static zeus::CVector3f g_ReflectViewPos; + static void KillCachedViewDepState(); + static void EnsureViewDepStateCached(const CBooModel& model, const CBooSurface* surf, zeus::CMatrix4f* mtxsOut, + float& alphaOut); - static zeus::CVector3f g_ReflectViewPos; - static void KillCachedViewDepState(); - static void EnsureViewDepStateCached(const CBooModel& model, const CBooSurface* surf, - zeus::CMatrix4f* mtxsOut, float& alphaOut); + static boo::ObjToken g_shadowMap; + static zeus::CTransform g_shadowTexXf; + static void EnableShadowMaps(const boo::ObjToken& map, const zeus::CTransform& texXf); + static void DisableShadowMaps(); - static boo::ObjToken g_shadowMap; - static zeus::CTransform g_shadowTexXf; - static void EnableShadowMaps(const boo::ObjToken& map, const zeus::CTransform& texXf); - static void DisableShadowMaps(); + static boo::ObjToken g_disintegrateTexture; + static void SetDisintegrateTexture(const boo::ObjToken& map) { g_disintegrateTexture = map; } - static boo::ObjToken g_disintegrateTexture; - static void SetDisintegrateTexture(const boo::ObjToken& map) { g_disintegrateTexture = map; } + static void SetDummyTextures(bool b) { g_DummyTextures = b; } + static void SetRenderModelBlack(bool b) { g_RenderModelBlack = b; } - static void SetDummyTextures(bool b) { g_DummyTextures = b; } - static void SetRenderModelBlack(bool b) { g_RenderModelBlack = b; } + static void AssertAllFreed(); - static void AssertAllFreed(); - - const zeus::CAABox& GetAABB() const { return x20_aabb; } + const zeus::CAABox& GetAABB() const { return x20_aabb; } }; -class CModel -{ - friend class CBooModel; - friend struct GeometryUniformLayout; - //std::unique_ptr x0_data; - //u32 x4_dataLen; - TToken m_selfToken; /* DO NOT LOCK! */ - zeus::CAABox m_aabb; - u32 m_flags; - std::vector x8_surfaces; - std::vector x18_matSets; - std::unique_ptr x28_modelInst; - //CModel* x30_next = nullptr; - //CModel* x34_prev = nullptr; - int x38_lastFrame; +class CModel { + friend class CBooModel; + friend struct GeometryUniformLayout; + // std::unique_ptr x0_data; + // u32 x4_dataLen; + TToken m_selfToken; /* DO NOT LOCK! */ + zeus::CAABox m_aabb; + u32 m_flags; + std::vector x8_surfaces; + std::vector x18_matSets; + std::unique_ptr x28_modelInst; + // CModel* x30_next = nullptr; + // CModel* x34_prev = nullptr; + int x38_lastFrame; - /* urde addition: boo! */ - boo::ObjToken m_staticVbo; - hecl::HMDLMeta m_hmdlMeta; - std::unique_ptr m_dynamicVertexData; - boo::ObjToken m_ibo; + /* urde addition: boo! */ + boo::ObjToken m_staticVbo; + hecl::HMDLMeta m_hmdlMeta; + std::unique_ptr m_dynamicVertexData; + boo::ObjToken m_ibo; public: - using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet; + using MaterialSet = DataSpec::DNAMP1::HMDLMaterialSet; - CModel(std::unique_ptr&& in, u32 dataLen, IObjectStore* store, CObjectReference* selfRef); - void DrawSortedParts(const CModelFlags& flags) const; - void DrawUnsortedParts(const CModelFlags& flags) const; - void Draw(const CModelFlags& flags) const; - bool IsLoaded(int shaderIdx) const; - void Touch(int shaderIdx) { x28_modelInst->Touch(shaderIdx); } + CModel(std::unique_ptr&& in, u32 dataLen, IObjectStore* store, CObjectReference* selfRef); + void DrawSortedParts(const CModelFlags& flags) const; + void DrawUnsortedParts(const CModelFlags& flags) const; + void Draw(const CModelFlags& flags) const; + bool IsLoaded(int shaderIdx) const; + void Touch(int shaderIdx) { x28_modelInst->Touch(shaderIdx); } - const zeus::CAABox& GetAABB() const {return m_aabb;} - CBooModel& GetInstance() {return *x28_modelInst;} - const CBooModel& GetInstance() const {return *x28_modelInst;} - std::unique_ptr MakeNewInstance(int shaderIdx, int subInsts, - const boo::ObjToken txtrOverrides[8] = nullptr, - bool lockParent = true); - void UpdateLastFrame() const { const_cast(*this).x38_lastFrame = CGraphics::GetFrameCounter(); } + const zeus::CAABox& GetAABB() const { return m_aabb; } + CBooModel& GetInstance() { return *x28_modelInst; } + const CBooModel& GetInstance() const { return *x28_modelInst; } + std::unique_ptr MakeNewInstance(int shaderIdx, int subInsts, + const boo::ObjToken txtrOverrides[8] = nullptr, + bool lockParent = true); + void UpdateLastFrame() const { const_cast(*this).x38_lastFrame = CGraphics::GetFrameCounter(); } - size_t GetPoolVertexOffset(size_t idx) const; - zeus::CVector3f GetPoolVertex(size_t idx) const; - size_t GetPoolNormalOffset(size_t idx) const; - zeus::CVector3f GetPoolNormal(size_t idx) const; - void ApplyVerticesCPU(const boo::ObjToken& vertBuf, - const std::vector>& vn) const; - void RestoreVerticesCPU(const boo::ObjToken& vertBuf) const; + size_t GetPoolVertexOffset(size_t idx) const; + zeus::CVector3f GetPoolVertex(size_t idx) const; + size_t GetPoolNormalOffset(size_t idx) const; + zeus::CVector3f GetPoolNormal(size_t idx) const; + void ApplyVerticesCPU(const boo::ObjToken& vertBuf, + const std::vector>& vn) const; + void RestoreVerticesCPU(const boo::ObjToken& vertBuf) const; - void _WarmupShaders(); - static void WarmupShaders(const SObjectTag& cmdlTag); + void _WarmupShaders(); + static void WarmupShaders(const SObjectTag& cmdlTag); }; -CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag, - std::unique_ptr&& in, u32 len, - const urde::CVParamTransfer& vparms, - CObjectReference* selfRef); - -} +CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag, std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms, CObjectReference* selfRef); +} // namespace urde diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index f431f0c4a..77108b852 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -12,1518 +12,1255 @@ #include "CSimplePool.hpp" #include -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CBooModel"); bool CBooModel::g_DrawingOccluders = false; static CBooModel* g_FirstModel = nullptr; -void CBooModel::AssertAllFreed() -{ - assert(g_FirstModel == nullptr && "Dangling CBooModels detected"); -} +void CBooModel::AssertAllFreed() { assert(g_FirstModel == nullptr && "Dangling CBooModels detected"); } -void CBooModel::ClearModelUniformCounters() -{ - for (CBooModel* model = g_FirstModel ; model ; model = model->m_next) - model->ClearUniformCounter(); +void CBooModel::ClearModelUniformCounters() { + for (CBooModel* model = g_FirstModel; model; model = model->m_next) + model->ClearUniformCounter(); } zeus::CVector3f CBooModel::g_PlayerPosition = {}; float CBooModel::g_ModSeconds = 0.f; float CBooModel::g_TransformedTime = 0.f; float CBooModel::g_TransformedTime2 = 0.f; -void CBooModel::SetNewPlayerPositionAndTime(const zeus::CVector3f& pos) -{ - g_PlayerPosition = pos; - KillCachedViewDepState(); - u32 modMillis = std::chrono::duration_cast( - std::chrono::steady_clock::now().time_since_epoch()).count() % u64(100000.f * 4.f * M_PIF / 3.f); - g_ModSeconds = modMillis / 1000.f; - g_TransformedTime = 1.f / -(0.05f * std::sin(g_ModSeconds * 1.5f) - 1.f); - g_TransformedTime2 = 1.f / -(0.015f * std::sin(g_ModSeconds * 1.5f + 1.f) - 1.f); +void CBooModel::SetNewPlayerPositionAndTime(const zeus::CVector3f& pos) { + g_PlayerPosition = pos; + KillCachedViewDepState(); + u32 modMillis = + std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()) + .count() % + u64(100000.f * 4.f * M_PIF / 3.f); + g_ModSeconds = modMillis / 1000.f; + g_TransformedTime = 1.f / -(0.05f * std::sin(g_ModSeconds * 1.5f) - 1.f); + g_TransformedTime2 = 1.f / -(0.015f * std::sin(g_ModSeconds * 1.5f + 1.f) - 1.f); } CBooModel* CBooModel::g_LastModelCached = nullptr; -void CBooModel::KillCachedViewDepState() -{ - g_LastModelCached = nullptr; -} +void CBooModel::KillCachedViewDepState() { g_LastModelCached = nullptr; } bool CBooModel::g_DummyTextures = false; bool CBooModel::g_RenderModelBlack = false; zeus::CVector3f CBooModel::g_ReflectViewPos = {}; -static const zeus::CMatrix4f ReflectBaseMtx = -{ - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 1.f, - 0.f, 0.f, 0.f, 1.f -}; +static const zeus::CMatrix4f ReflectBaseMtx = {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f}; -static const zeus::CMatrix4f ReflectPostGL = -{ - 1.f, 0.f, 0.f, 0.f, - 0.f, -1.f, 0.f, 1.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f -}; +static const zeus::CMatrix4f ReflectPostGL = {1.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 1.f, + 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f}; -void CBooModel::EnsureViewDepStateCached(const CBooModel& model, const CBooSurface* surf, - zeus::CMatrix4f* mtxsOut, float& alphaOut) -{ - zeus::CVector3f modelToPlayer = g_PlayerPosition - CGraphics::g_GXModelMatrix.origin; - zeus::CVector3f modelToPlayerLocal = CGraphics::g_GXModelMatrix.transposeRotate(modelToPlayer); +void CBooModel::EnsureViewDepStateCached(const CBooModel& model, const CBooSurface* surf, zeus::CMatrix4f* mtxsOut, + float& alphaOut) { + zeus::CVector3f modelToPlayer = g_PlayerPosition - CGraphics::g_GXModelMatrix.origin; + zeus::CVector3f modelToPlayerLocal = CGraphics::g_GXModelMatrix.transposeRotate(modelToPlayer); - zeus::CVector3f surfPos; - float surfSize = 0.f; - if (surf) - { - zeus::CVector3f surfCenter(surf->m_data.centroid); - zeus::CVector3f surfNormal(surf->m_data.reflectionNormal); - float dotDelta = surfNormal.dot(modelToPlayerLocal) - surfCenter.dot(surfNormal); - surfPos = modelToPlayerLocal - surfNormal * dotDelta; - } + zeus::CVector3f surfPos; + float surfSize = 0.f; + if (surf) { + zeus::CVector3f surfCenter(surf->m_data.centroid); + zeus::CVector3f surfNormal(surf->m_data.reflectionNormal); + float dotDelta = surfNormal.dot(modelToPlayerLocal) - surfCenter.dot(surfNormal); + surfPos = modelToPlayerLocal - surfNormal * dotDelta; + } else { + surfPos = model.x20_aabb.center(); + surfSize = + (model.x20_aabb.max.x() - model.x20_aabb.min.x()) + (model.x20_aabb.max.y() - model.x20_aabb.min.y()) * 0.5f; + } + + if (g_Renderer->x318_24_refectionDirty) { + zeus::CVector3f playerToPos = g_ReflectViewPos - g_PlayerPosition; + zeus::CVector3f vecToPos = surfPos - g_PlayerPosition; + if (playerToPos.dot(playerToPos) < vecToPos.dot(vecToPos)) + g_ReflectViewPos = surfPos; + } else { + g_ReflectViewPos = surfPos; + g_Renderer->x318_24_refectionDirty = true; + } + + zeus::CVector3f playerToSurf = surfPos - modelToPlayerLocal; + float distance = std::max(-(0.5f * surfSize - playerToSurf.magnitude()), FLT_EPSILON); + if (distance >= 5.f) { + alphaOut = 0.f; + } else { + alphaOut = (5.f - distance) / 5.f; + + /* Indirect map matrix */ + mtxsOut[0] = (CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix).toMatrix4f(); + + /* Reflection map matrix */ + zeus::CVector3f v1 = playerToSurf * (1.f / surfSize); + zeus::CVector3f v2 = v1.cross(zeus::CVector3f::skUp); + if (v2.canBeNormalized()) + v2.normalize(); else - { - surfPos = model.x20_aabb.center(); - surfSize = (model.x20_aabb.max.x() - model.x20_aabb.min.x()) + - (model.x20_aabb.max.y() - model.x20_aabb.min.y()) * 0.5f; - } + v2 = zeus::CVector3f::skRight; - if (g_Renderer->x318_24_refectionDirty) - { - zeus::CVector3f playerToPos = g_ReflectViewPos - g_PlayerPosition; - zeus::CVector3f vecToPos = surfPos - g_PlayerPosition; - if (playerToPos.dot(playerToPos) < vecToPos.dot(vecToPos)) - g_ReflectViewPos = surfPos; - } - else - { - g_ReflectViewPos = surfPos; - g_Renderer->x318_24_refectionDirty = true; - } - - zeus::CVector3f playerToSurf = surfPos - modelToPlayerLocal; - float distance = std::max(-(0.5f * surfSize - playerToSurf.magnitude()), FLT_EPSILON); - if (distance >= 5.f) - { - alphaOut = 0.f; - } - else - { - alphaOut = (5.f - distance) / 5.f; - - /* Indirect map matrix */ - mtxsOut[0] = (CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix).toMatrix4f(); - - /* Reflection map matrix */ - zeus::CVector3f v1 = playerToSurf * (1.f / surfSize); - zeus::CVector3f v2 = v1.cross(zeus::CVector3f::skUp); - if (v2.canBeNormalized()) - v2.normalize(); - else - v2 = zeus::CVector3f::skRight; - - float timeScale = 0.32258067f * (0.02f * distance + 1.f); - float f1 = timeScale * g_TransformedTime; - float f2 = timeScale * g_TransformedTime2; - mtxsOut[1] = ReflectBaseMtx; - mtxsOut[1][0][0] = f1 * v2.x(); - mtxsOut[1][1][0] = f1 * v2.y(); - mtxsOut[1][3][0] = -surfPos.dot(v2) * f1 + 0.5f; - mtxsOut[1][2][1] = f2; - mtxsOut[1][3][1] = -modelToPlayerLocal.z() * f2; - switch (CGraphics::g_BooPlatform) - { - case boo::IGraphicsDataFactory::Platform::OpenGL: - mtxsOut[1] = ReflectPostGL * mtxsOut[1]; - break; - default: - break; - } + float timeScale = 0.32258067f * (0.02f * distance + 1.f); + float f1 = timeScale * g_TransformedTime; + float f2 = timeScale * g_TransformedTime2; + mtxsOut[1] = ReflectBaseMtx; + mtxsOut[1][0][0] = f1 * v2.x(); + mtxsOut[1][1][0] = f1 * v2.y(); + mtxsOut[1][3][0] = -surfPos.dot(v2) * f1 + 0.5f; + mtxsOut[1][2][1] = f2; + mtxsOut[1][3][1] = -modelToPlayerLocal.z() * f2; + switch (CGraphics::g_BooPlatform) { + case boo::IGraphicsDataFactory::Platform::OpenGL: + mtxsOut[1] = ReflectPostGL * mtxsOut[1]; + break; + default: + break; } + } } boo::ObjToken CBooModel::g_shadowMap; zeus::CTransform CBooModel::g_shadowTexXf; boo::ObjToken CBooModel::g_disintegrateTexture; -void CBooModel::EnableShadowMaps(const boo::ObjToken& map, const zeus::CTransform& texXf) -{ - g_shadowMap = map; - g_shadowTexXf = texXf; -} -void CBooModel::DisableShadowMaps() -{ - g_shadowMap = nullptr; +void CBooModel::EnableShadowMaps(const boo::ObjToken& map, const zeus::CTransform& texXf) { + g_shadowMap = map; + g_shadowTexXf = texXf; } +void CBooModel::DisableShadowMaps() { g_shadowMap = nullptr; } -CBooModel::~CBooModel() -{ - if (m_prev) - m_prev->m_next = m_next; - if (m_next) - m_next->m_prev = m_prev; - if (this == g_FirstModel) - g_FirstModel = m_next; +CBooModel::~CBooModel() { + if (m_prev) + m_prev->m_next = m_next; + if (m_next) + m_next->m_prev = m_prev; + if (this == g_FirstModel) + g_FirstModel = m_next; } CBooModel::CBooModel(TToken& token, CModel* parent, std::vector* surfaces, SShader& shader, const boo::ObjToken& vbo, const boo::ObjToken& ibo, - const zeus::CAABox& aabb, u8 renderMask, int numInsts, const boo::ObjToken txtrOverrides[8]) -: m_modelTok(token), m_model(parent), x0_surfaces(surfaces), x4_matSet(&shader.m_matSet), - m_geomLayout(&*shader.m_geomLayout), m_matSetIdx(shader.m_matSetIdx), m_pipelines(&shader.m_shaders), - x1c_textures(shader.x0_textures), x20_aabb(aabb), x40_24_texturesLoaded(false), x40_25_modelVisible(0), - x41_mask(renderMask), m_staticVbo(vbo), m_staticIbo(ibo) -{ - if (txtrOverrides) - for (int i=0 ; i<8 ; ++i) - m_txtrOverrides[i] = txtrOverrides[i]; + const zeus::CAABox& aabb, u8 renderMask, int numInsts, + const boo::ObjToken txtrOverrides[8]) +: m_modelTok(token) +, m_model(parent) +, x0_surfaces(surfaces) +, x4_matSet(&shader.m_matSet) +, m_geomLayout(&*shader.m_geomLayout) +, m_matSetIdx(shader.m_matSetIdx) +, m_pipelines(&shader.m_shaders) +, x1c_textures(shader.x0_textures) +, x20_aabb(aabb) +, x40_24_texturesLoaded(false) +, x40_25_modelVisible(0) +, x41_mask(renderMask) +, m_staticVbo(vbo) +, m_staticIbo(ibo) { + if (txtrOverrides) + for (int i = 0; i < 8; ++i) + m_txtrOverrides[i] = txtrOverrides[i]; - if (!g_FirstModel) - g_FirstModel = this; - else - { - g_FirstModel->m_prev = this; - m_next = g_FirstModel; - g_FirstModel = this; + if (!g_FirstModel) + g_FirstModel = this; + else { + g_FirstModel->m_prev = this; + m_next = g_FirstModel; + g_FirstModel = this; + } + + for (CBooSurface& surf : *x0_surfaces) + surf.m_parent = this; + + for (auto it = x0_surfaces->rbegin(); it != x0_surfaces->rend(); ++it) { + u32 matId = it->m_data.matIdx; + const MaterialSet::Material& matData = GetMaterialByIndex(matId); + if (matData.flags.depthSorting()) { + it->m_next = x3c_firstSortedSurface; + x3c_firstSortedSurface = &*it; + } else { + it->m_next = x38_firstUnsortedSurface; + x38_firstUnsortedSurface = &*it; } + } - for (CBooSurface& surf : *x0_surfaces) - surf.m_parent = this; - - for (auto it=x0_surfaces->rbegin() ; it != x0_surfaces->rend() ; ++it) - { - u32 matId = it->m_data.matIdx; - const MaterialSet::Material& matData = GetMaterialByIndex(matId); - if (matData.flags.depthSorting()) - { - it->m_next = x3c_firstSortedSurface; - x3c_firstSortedSurface = &*it; - } - else - { - it->m_next = x38_firstUnsortedSurface; - x38_firstUnsortedSurface = &*it; - } - } - - m_instances.reserve(numInsts); - for (int i=0 ; i -CBooModel::ModelInstance::GetBooVBO(const CBooModel& model, - boo::IGraphicsDataFactory::Context& ctx) -{ - if (model.m_staticVbo) - return model.m_staticVbo.get(); - if (!m_dynamicVbo && model.m_model) - { - const CModel& parent = *model.m_model; - m_dynamicVbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, - parent.m_hmdlMeta.vertStride, parent.m_hmdlMeta.vertCount); - m_dynamicVbo->load(parent.m_dynamicVertexData.get(), - parent.m_hmdlMeta.vertStride * parent.m_hmdlMeta.vertCount); - } - return m_dynamicVbo.get(); +boo::ObjToken CBooModel::ModelInstance::GetBooVBO(const CBooModel& model, + boo::IGraphicsDataFactory::Context& ctx) { + if (model.m_staticVbo) + return model.m_staticVbo.get(); + if (!m_dynamicVbo && model.m_model) { + const CModel& parent = *model.m_model; + m_dynamicVbo = + ctx.newDynamicBuffer(boo::BufferUse::Vertex, parent.m_hmdlMeta.vertStride, parent.m_hmdlMeta.vertCount); + m_dynamicVbo->load(parent.m_dynamicVertexData.get(), parent.m_hmdlMeta.vertStride * parent.m_hmdlMeta.vertCount); + } + return m_dynamicVbo.get(); } -GeometryUniformLayout::GeometryUniformLayout(const CModel* model, const MaterialSet* matSet) -{ - if (model) - { - m_skinBankCount = model->m_hmdlMeta.bankCount; - m_weightVecCount = model->m_hmdlMeta.weightCount; - } +GeometryUniformLayout::GeometryUniformLayout(const CModel* model, const MaterialSet* matSet) { + if (model) { + m_skinBankCount = model->m_hmdlMeta.bankCount; + m_weightVecCount = model->m_hmdlMeta.weightCount; + } - m_skinOffs.reserve(std::max(size_t(1), m_skinBankCount)); - m_skinSizes.reserve(std::max(size_t(1), m_skinBankCount)); + m_skinOffs.reserve(std::max(size_t(1), m_skinBankCount)); + m_skinSizes.reserve(std::max(size_t(1), m_skinBankCount)); - m_uvOffs.reserve(matSet->materials.size()); - m_uvSizes.reserve(matSet->materials.size()); + m_uvOffs.reserve(matSet->materials.size()); + m_uvSizes.reserve(matSet->materials.size()); - if (m_skinBankCount) - { - /* Skinned */ - for (size_t i=0 ; imaterials) - { - (void)mat; - size_t thisSz = ROUND_UP_256(/*mat.uvAnims.size()*/ 8 * (sizeof(zeus::CMatrix4f) * 2)); - m_uvOffs.push_back(m_geomBufferSize); - m_uvSizes.push_back(thisSz); - m_geomBufferSize += thisSz; - } + /* Animated UV transform matrices */ + for (const MaterialSet::Material& mat : matSet->materials) { + (void)mat; + size_t thisSz = ROUND_UP_256(/*mat.uvAnims.size()*/ 8 * (sizeof(zeus::CMatrix4f) * 2)); + m_uvOffs.push_back(m_geomBufferSize); + m_uvSizes.push_back(thisSz); + m_geomBufferSize += thisSz; + } } -CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) -{ - if (!x40_24_texturesLoaded && !g_DummyTextures) - return nullptr; +CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) { + if (!x40_24_texturesLoaded && !g_DummyTextures) + return nullptr; - if (m_instances.size() >= 512) - Log.report(logvisor::Fatal, "Model buffer overflow"); - m_instances.emplace_back(); - ModelInstance& newInst = m_instances.back(); + if (m_instances.size() >= 512) + Log.report(logvisor::Fatal, "Model buffer overflow"); + m_instances.emplace_back(); + ModelInstance& newInst = m_instances.back(); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + /* Build geometry uniform buffer if shared not available */ + boo::ObjToken geomUniformBuf; + if (sharedLayoutBuf >= 0) { + geomUniformBuf = m_geomLayout->m_sharedBuffer[sharedLayoutBuf]; + } else { + geomUniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, m_geomLayout->m_geomBufferSize, 1); + newInst.m_geomUniformBuffer = geomUniformBuf; + } + + /* Lighting and reflection uniforms */ + size_t uniBufSize = 0; + + /* Lighting uniform */ + size_t lightOff = 0; + size_t lightSz = 0; { - /* Build geometry uniform buffer if shared not available */ - boo::ObjToken geomUniformBuf; - if (sharedLayoutBuf >= 0) - { - geomUniformBuf = m_geomLayout->m_sharedBuffer[sharedLayoutBuf]; - } - else - { - geomUniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, m_geomLayout->m_geomBufferSize, 1); - newInst.m_geomUniformBuffer = geomUniformBuf; - } + size_t thisSz = ROUND_UP_256(sizeof(CModelShaders::LightingUniform)); + lightOff = uniBufSize; + lightSz = thisSz; + uniBufSize += thisSz; + } - /* Lighting and reflection uniforms */ - size_t uniBufSize = 0; - - /* Lighting uniform */ - size_t lightOff = 0; - size_t lightSz = 0; - { - size_t thisSz = ROUND_UP_256(sizeof(CModelShaders::LightingUniform)); - lightOff = uniBufSize; - lightSz = thisSz; - uniBufSize += thisSz; - } - - /* Surface reflection texmatrix uniform with first identity slot */ - size_t reflectOff = uniBufSize; + /* Surface reflection texmatrix uniform with first identity slot */ + size_t reflectOff = uniBufSize; + uniBufSize += 256; + for (const CBooSurface& surf : *x0_surfaces) { + const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx); + if (mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye()) uniBufSize += 256; - for (const CBooSurface& surf : *x0_surfaces) - { - const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx); - if (mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye()) - uniBufSize += 256; - } - - /* Allocate resident buffer */ - m_uniformDataSize = uniBufSize; - newInst.m_uniformBuffer = ctx.newDynamicBuffer(boo::BufferUse::Uniform, uniBufSize, 1); - - boo::ObjToken bufs[] = {geomUniformBuf.get(), - geomUniformBuf.get(), - newInst.m_uniformBuffer.get(), - newInst.m_uniformBuffer.get()}; - - /* Binding for each surface */ - newInst.m_shaderDataBindings.reserve(x0_surfaces->size()); - - boo::ObjToken mbShadowTexs[8] = {g_Renderer->m_ballShadowId.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->m_ballFade.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get()}; - size_t thisOffs[4]; - size_t thisSizes[4]; - - static const boo::PipelineStage stages[4] = {boo::PipelineStage::Vertex, - boo::PipelineStage::Vertex, - boo::PipelineStage::Fragment, - boo::PipelineStage::Vertex}; - - /* Enumerate surfaces and build data bindings */ - size_t curReflect = reflectOff + 256; - for (const CBooSurface& surf : *x0_surfaces) - { - const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx); - - boo::ObjToken texs[8] = {g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get(), - g_Renderer->x220_sphereRamp.get()}; - u32 texCount = 0; - for (atUint32 idx : mat.textureIdxs) - { - if (boo::ObjToken overtex = m_txtrOverrides[texCount]) - { - texs[texCount++] = overtex; - } - else if (g_DummyTextures) - { - texs[texCount++] = g_Renderer->x220_sphereRamp.get(); - } - else - { - TCachedToken& tex = x1c_textures[idx]; - if (boo::ObjToken btex = tex.GetObj()->GetBooTexture()) - texs[texCount++] = btex; - } - } - - if (m_geomLayout->m_skinBankCount) - { - thisOffs[0] = m_geomLayout->m_skinOffs[surf.m_data.skinMtxBankIdx]; - thisSizes[0] = m_geomLayout->m_skinSizes[surf.m_data.skinMtxBankIdx]; - } - else - { - thisOffs[0] = 0; - thisSizes[0] = 256; - } - - thisOffs[1] = m_geomLayout->m_uvOffs[surf.m_data.matIdx]; - thisSizes[1] = m_geomLayout->m_uvSizes[surf.m_data.matIdx]; - - thisOffs[2] = lightOff; - thisSizes[2] = lightSz; - - bool useReflection = mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye(); - if (useReflection) - { - if (g_Renderer->x14c_reflectionTex) - texs[texCount] = g_Renderer->x14c_reflectionTex.get(); - else - texs[texCount] = g_Renderer->x220_sphereRamp.get(); - thisOffs[3] = curReflect; - curReflect += 256; - } - else - { - thisOffs[3] = reflectOff; - } - thisSizes[3] = 256; - - const CModelShaders::ShaderPipelines& pipelines = m_pipelines->at(surf.m_data.matIdx); - - newInst.m_shaderDataBindings.emplace_back(); - std::vector>& extendeds = newInst.m_shaderDataBindings.back(); - extendeds.reserve(pipelines->size()); - - int idx = 0; - for (const auto& pipeline : *pipelines) - { - boo::ObjToken* ltexs; - if (idx == EExtendedShader::Thermal) - { - texs[7] = g_Renderer->x220_sphereRamp.get(); - ltexs = texs; - } - else if (idx == EExtendedShader::MorphBallShadow) - { - ltexs = mbShadowTexs; - } - else if (idx == EExtendedShader::WorldShadow) - { - if (g_shadowMap) - texs[7] = g_shadowMap; - else - texs[7] = g_Renderer->x220_sphereRamp.get(); - ltexs = texs; - } - else if (idx == EExtendedShader::Disintegrate) - { - if (g_disintegrateTexture) - texs[7] = g_disintegrateTexture; - else - texs[7] = g_Renderer->x220_sphereRamp.get(); - ltexs = texs; - } - else if (useReflection) - { - ltexs = texs; - } - else - { - ltexs = texs; - } - extendeds.push_back( - ctx.newShaderDataBinding(pipeline, - newInst.GetBooVBO(*this, ctx), nullptr, m_staticIbo.get(), 4, bufs, - stages, thisOffs, thisSizes, 8, ltexs, nullptr, nullptr)); - ++idx; - } - } - return true; - } BooTrace); - - return &newInst; -} - -void CBooModel::MakeTexturesFromMats(const MaterialSet& matSet, - std::vector>& toksOut, - IObjectStore& store) -{ - toksOut.reserve(matSet.head.textureIDs.size()); - for (const DataSpec::UniqueID32& id : matSet.head.textureIDs) - toksOut.emplace_back(store.GetObj({SBIG('TXTR'), id.toUint32()})); -} - -void CBooModel::MakeTexturesFromMats(std::vector>& toksOut, - IObjectStore& store) -{ - MakeTexturesFromMats(*x4_matSet, toksOut, store); -} - -void CBooModel::ActivateLights(const std::vector& lights) -{ - m_lightingData.ActivateLights(lights); -} - -void CBooModel::DisableAllLights() -{ - m_lightingData.ambient = zeus::CColor::skBlack; - - for (size_t curLight = 0 ; curLight bufs[] = {geomUniformBuf.get(), geomUniformBuf.get(), + newInst.m_uniformBuffer.get(), newInst.m_uniformBuffer.get()}; + + /* Binding for each surface */ + newInst.m_shaderDataBindings.reserve(x0_surfaces->size()); + + boo::ObjToken mbShadowTexs[8] = { + g_Renderer->m_ballShadowId.get(), g_Renderer->x220_sphereRamp.get(), g_Renderer->m_ballFade.get(), + g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), + g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get()}; + size_t thisOffs[4]; + size_t thisSizes[4]; + + static const boo::PipelineStage stages[4] = {boo::PipelineStage::Vertex, boo::PipelineStage::Vertex, + boo::PipelineStage::Fragment, boo::PipelineStage::Vertex}; + + /* Enumerate surfaces and build data bindings */ + size_t curReflect = reflectOff + 256; + for (const CBooSurface& surf : *x0_surfaces) { + const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx); + + boo::ObjToken texs[8] = {g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), + g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), + g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get(), + g_Renderer->x220_sphereRamp.get(), g_Renderer->x220_sphereRamp.get()}; + u32 texCount = 0; + for (atUint32 idx : mat.textureIdxs) { + if (boo::ObjToken overtex = m_txtrOverrides[texCount]) { + texs[texCount++] = overtex; + } else if (g_DummyTextures) { + texs[texCount++] = g_Renderer->x220_sphereRamp.get(); + } else { + TCachedToken& tex = x1c_textures[idx]; + if (boo::ObjToken btex = tex.GetObj()->GetBooTexture()) + texs[texCount++] = btex; + } + } + + if (m_geomLayout->m_skinBankCount) { + thisOffs[0] = m_geomLayout->m_skinOffs[surf.m_data.skinMtxBankIdx]; + thisSizes[0] = m_geomLayout->m_skinSizes[surf.m_data.skinMtxBankIdx]; + } else { + thisOffs[0] = 0; + thisSizes[0] = 256; + } + + thisOffs[1] = m_geomLayout->m_uvOffs[surf.m_data.matIdx]; + thisSizes[1] = m_geomLayout->m_uvSizes[surf.m_data.matIdx]; + + thisOffs[2] = lightOff; + thisSizes[2] = lightSz; + + bool useReflection = mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye(); + if (useReflection) { + if (g_Renderer->x14c_reflectionTex) + texs[texCount] = g_Renderer->x14c_reflectionTex.get(); + else + texs[texCount] = g_Renderer->x220_sphereRamp.get(); + thisOffs[3] = curReflect; + curReflect += 256; + } else { + thisOffs[3] = reflectOff; + } + thisSizes[3] = 256; + + const CModelShaders::ShaderPipelines& pipelines = m_pipelines->at(surf.m_data.matIdx); + + newInst.m_shaderDataBindings.emplace_back(); + std::vector>& extendeds = newInst.m_shaderDataBindings.back(); + extendeds.reserve(pipelines->size()); + + int idx = 0; + for (const auto& pipeline : *pipelines) { + boo::ObjToken* ltexs; + if (idx == EExtendedShader::Thermal) { + texs[7] = g_Renderer->x220_sphereRamp.get(); + ltexs = texs; + } else if (idx == EExtendedShader::MorphBallShadow) { + ltexs = mbShadowTexs; + } else if (idx == EExtendedShader::WorldShadow) { + if (g_shadowMap) + texs[7] = g_shadowMap; + else + texs[7] = g_Renderer->x220_sphereRamp.get(); + ltexs = texs; + } else if (idx == EExtendedShader::Disintegrate) { + if (g_disintegrateTexture) + texs[7] = g_disintegrateTexture; + else + texs[7] = g_Renderer->x220_sphereRamp.get(); + ltexs = texs; + } else if (useReflection) { + ltexs = texs; + } else { + ltexs = texs; + } + extendeds.push_back(ctx.newShaderDataBinding(pipeline, newInst.GetBooVBO(*this, ctx), nullptr, + m_staticIbo.get(), 4, bufs, stages, thisOffs, thisSizes, 8, ltexs, + nullptr, nullptr)); + ++idx; + } + } + return true; + } BooTrace); + + return &newInst; } -void CBooModel::RemapMaterialData(SShader& shader) -{ - if (!shader.m_geomLayout) - return; - x4_matSet = &shader.m_matSet; - m_geomLayout = &*shader.m_geomLayout; - m_matSetIdx = shader.m_matSetIdx; - x1c_textures = shader.x0_textures; - m_pipelines = &shader.m_shaders; - x40_24_texturesLoaded = false; - m_instances.clear(); +void CBooModel::MakeTexturesFromMats(const MaterialSet& matSet, std::vector>& toksOut, + IObjectStore& store) { + toksOut.reserve(matSet.head.textureIDs.size()); + for (const DataSpec::UniqueID32& id : matSet.head.textureIDs) + toksOut.emplace_back(store.GetObj({SBIG('TXTR'), id.toUint32()})); +} + +void CBooModel::MakeTexturesFromMats(std::vector>& toksOut, IObjectStore& store) { + MakeTexturesFromMats(*x4_matSet, toksOut, store); +} + +void CBooModel::ActivateLights(const std::vector& lights) { m_lightingData.ActivateLights(lights); } + +void CBooModel::DisableAllLights() { + m_lightingData.ambient = zeus::CColor::skBlack; + + for (size_t curLight = 0; curLight < URDE_MAX_LIGHTS; ++curLight) { + CModelShaders::Light& lightOut = m_lightingData.lights[curLight]; + lightOut.color = zeus::CColor::skClear; + lightOut.linAtt[0] = 1.f; + lightOut.angAtt[0] = 1.f; + } +} + +void CBooModel::RemapMaterialData(SShader& shader) { + if (!shader.m_geomLayout) + return; + x4_matSet = &shader.m_matSet; + m_geomLayout = &*shader.m_geomLayout; + m_matSetIdx = shader.m_matSetIdx; + x1c_textures = shader.x0_textures; + m_pipelines = &shader.m_shaders; + x40_24_texturesLoaded = false; + m_instances.clear(); } void CBooModel::RemapMaterialData(SShader& shader, - const std::unordered_map& pipelines) -{ - if (!shader.m_geomLayout) - return; - x4_matSet = &shader.m_matSet; - m_geomLayout = &*shader.m_geomLayout; - m_matSetIdx = shader.m_matSetIdx; - x1c_textures = shader.x0_textures; - m_pipelines = &pipelines; - x40_24_texturesLoaded = false; - m_instances.clear(); + const std::unordered_map& pipelines) { + if (!shader.m_geomLayout) + return; + x4_matSet = &shader.m_matSet; + m_geomLayout = &*shader.m_geomLayout; + m_matSetIdx = shader.m_matSetIdx; + x1c_textures = shader.x0_textures; + m_pipelines = &pipelines; + x40_24_texturesLoaded = false; + m_instances.clear(); } -bool CBooModel::TryLockTextures() const -{ - if (!x40_24_texturesLoaded) - { - bool allLoad = true; - for (TCachedToken& tex : const_cast>&>(x1c_textures)) - { - tex.Lock(); - if (!tex.IsLoaded()) - allLoad = false; - } - - const_cast(this)->x40_24_texturesLoaded = allLoad; +bool CBooModel::TryLockTextures() const { + if (!x40_24_texturesLoaded) { + bool allLoad = true; + for (TCachedToken& tex : const_cast>&>(x1c_textures)) { + tex.Lock(); + if (!tex.IsLoaded()) + allLoad = false; } - return x40_24_texturesLoaded; + const_cast(this)->x40_24_texturesLoaded = allLoad; + } + + return x40_24_texturesLoaded; } -void CBooModel::UnlockTextures() const -{ - const_cast(this)->m_instances.clear(); +void CBooModel::UnlockTextures() const { + const_cast(this)->m_instances.clear(); + for (TCachedToken& tex : const_cast>&>(x1c_textures)) + tex.Unlock(); + const_cast(this)->x40_24_texturesLoaded = false; +} + +void CBooModel::SyncLoadTextures() const { + if (!x40_24_texturesLoaded) { for (TCachedToken& tex : const_cast>&>(x1c_textures)) - tex.Unlock(); - const_cast(this)->x40_24_texturesLoaded = false; + tex.GetObj(); + const_cast(this)->x40_24_texturesLoaded = true; + } } -void CBooModel::SyncLoadTextures() const -{ - if (!x40_24_texturesLoaded) - { - for (TCachedToken& tex : const_cast>&>(x1c_textures)) - tex.GetObj(); - const_cast(this)->x40_24_texturesLoaded = true; - } -} - -void CBooModel::DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) const -{ - const CBooSurface* surf; - CModelFlags flags = {}; - flags.m_extendedShader = extendedIdx; - - if (sel != ESurfaceSelection::SortedOnly) - { - surf = x38_firstUnsortedSurface; - while (surf) - { - DrawSurface(*surf, flags); - surf = surf->m_next; - } - } - - if (sel != ESurfaceSelection::UnsortedOnly) - { - surf = x3c_firstSortedSurface; - while (surf) - { - DrawSurface(*surf, flags); - surf = surf->m_next; - } - } -} - -void CBooModel::DrawAlphaSurfaces(const CModelFlags& flags) const -{ - const CBooSurface* surf = x3c_firstSortedSurface; - while (surf) - { - DrawSurface(*surf, flags); - surf = surf->m_next; - } -} - -void CBooModel::DrawNormalSurfaces(const CModelFlags& flags) const -{ - const CBooSurface* surf = x38_firstUnsortedSurface; - while (surf) - { - DrawSurface(*surf, flags); - surf = surf->m_next; - } -} - -void CBooModel::DrawSurfaces(const CModelFlags& flags) const -{ - const CBooSurface* surf = x38_firstUnsortedSurface; - while (surf) - { - DrawSurface(*surf, flags); - surf = surf->m_next; +void CBooModel::DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) const { + const CBooSurface* surf; + CModelFlags flags = {}; + flags.m_extendedShader = extendedIdx; + + if (sel != ESurfaceSelection::SortedOnly) { + surf = x38_firstUnsortedSurface; + while (surf) { + DrawSurface(*surf, flags); + surf = surf->m_next; } + } + if (sel != ESurfaceSelection::UnsortedOnly) { surf = x3c_firstSortedSurface; - while (surf) - { - DrawSurface(*surf, flags); - surf = surf->m_next; + while (surf) { + DrawSurface(*surf, flags); + surf = surf->m_next; } + } } -static EExtendedShader ResolveExtendedShader(const MaterialSet::Material& data, const CModelFlags& flags) -{ - bool noZWrite = flags.m_noZWrite || !data.flags.depthWrite(); - - EExtendedShader extended = EExtendedShader::Flat; - if (flags.m_extendedShader == EExtendedShader::Lighting) - { - if (data.heclIr.m_blendSrc == boo::BlendFactor::One && data.heclIr.m_blendDst == boo::BlendFactor::Zero) - { - /* Override shader if originally opaque (typical for FRME models) */ - if (flags.x0_blendMode > 6) - extended = flags.m_noCull ? (noZWrite ? - EExtendedShader::ForcedAdditiveNoCullNoZWrite : - EExtendedShader::ForcedAdditiveNoCull) : - (noZWrite ? - EExtendedShader::ForcedAdditiveNoZWrite : - EExtendedShader::ForcedAdditive); - else if (flags.x0_blendMode > 4) - extended = flags.m_noCull ? (noZWrite ? - EExtendedShader::ForcedAlphaNoCullNoZWrite : - EExtendedShader::ForcedAlphaNoCull) : - (noZWrite ? - EExtendedShader::ForcedAlphaNoZWrite : - EExtendedShader::ForcedAlpha); - else - extended = flags.m_noCull ? (noZWrite ? - EExtendedShader::ForcedAlphaNoCullNoZWrite : - EExtendedShader::ForcedAlphaNoCull) : - (noZWrite ? - EExtendedShader::ForcedAlphaNoZWrite : - EExtendedShader::Lighting); - } - else if (flags.m_noCull && noZWrite) - { - /* Substitute no-cull,no-zwrite pipeline if available */ - if (data.heclIr.m_blendDst == boo::BlendFactor::One) - extended = EExtendedShader::ForcedAdditiveNoCullNoZWrite; - else - extended = EExtendedShader::ForcedAlphaNoCullNoZWrite; - } - else if (flags.m_noCull) - { - /* Substitute no-cull pipeline if available */ - if (data.heclIr.m_blendDst == boo::BlendFactor::One) - extended = EExtendedShader::ForcedAdditiveNoCull; - else - extended = EExtendedShader::ForcedAlphaNoCull; - } - else if (noZWrite) - { - /* Substitute no-zwrite pipeline if available */ - if (data.heclIr.m_blendDst == boo::BlendFactor::One) - extended = EExtendedShader::ForcedAdditiveNoZWrite; - else - extended = EExtendedShader::ForcedAlphaNoZWrite; - } - else - { - extended = EExtendedShader::Lighting; - } - } - else if (flags.m_extendedShader < EExtendedShader::MAX) - { - extended = flags.m_extendedShader; - } - - return extended; +void CBooModel::DrawAlphaSurfaces(const CModelFlags& flags) const { + const CBooSurface* surf = x3c_firstSortedSurface; + while (surf) { + DrawSurface(*surf, flags); + surf = surf->m_next; + } } -void CBooModel::DrawSurface(const CBooSurface& surf, const CModelFlags& flags) const -{ - //if (m_uniUpdateCount == 0) - // Log.report(logvisor::Fatal, "UpdateUniformData() not called"); - if (m_uniUpdateCount == 0 || m_uniUpdateCount > m_instances.size()) - return; - const ModelInstance& inst = m_instances[m_uniUpdateCount-1]; +void CBooModel::DrawNormalSurfaces(const CModelFlags& flags) const { + const CBooSurface* surf = x38_firstUnsortedSurface; + while (surf) { + DrawSurface(*surf, flags); + surf = surf->m_next; + } +} - const MaterialSet::Material& data = GetMaterialByIndex(surf.m_data.matIdx); - if (data.flags.shadowOccluderMesh() && !g_DrawingOccluders) - return; +void CBooModel::DrawSurfaces(const CModelFlags& flags) const { + const CBooSurface* surf = x38_firstUnsortedSurface; + while (surf) { + DrawSurface(*surf, flags); + surf = surf->m_next; + } - const std::vector>& extendeds = inst.m_shaderDataBindings[surf.selfIdx]; - EExtendedShader extended = ResolveExtendedShader(data, flags); + surf = x3c_firstSortedSurface; + while (surf) { + DrawSurface(*surf, flags); + surf = surf->m_next; + } +} - boo::ObjToken binding = extendeds[extended]; +static EExtendedShader ResolveExtendedShader(const MaterialSet::Material& data, const CModelFlags& flags) { + bool noZWrite = flags.m_noZWrite || !data.flags.depthWrite(); + + EExtendedShader extended = EExtendedShader::Flat; + if (flags.m_extendedShader == EExtendedShader::Lighting) { + if (data.heclIr.m_blendSrc == boo::BlendFactor::One && data.heclIr.m_blendDst == boo::BlendFactor::Zero) { + /* Override shader if originally opaque (typical for FRME models) */ + if (flags.x0_blendMode > 6) + extended = + flags.m_noCull + ? (noZWrite ? EExtendedShader::ForcedAdditiveNoCullNoZWrite : EExtendedShader::ForcedAdditiveNoCull) + : (noZWrite ? EExtendedShader::ForcedAdditiveNoZWrite : EExtendedShader::ForcedAdditive); + else if (flags.x0_blendMode > 4) + extended = flags.m_noCull + ? (noZWrite ? EExtendedShader::ForcedAlphaNoCullNoZWrite : EExtendedShader::ForcedAlphaNoCull) + : (noZWrite ? EExtendedShader::ForcedAlphaNoZWrite : EExtendedShader::ForcedAlpha); + else + extended = flags.m_noCull + ? (noZWrite ? EExtendedShader::ForcedAlphaNoCullNoZWrite : EExtendedShader::ForcedAlphaNoCull) + : (noZWrite ? EExtendedShader::ForcedAlphaNoZWrite : EExtendedShader::Lighting); + } else if (flags.m_noCull && noZWrite) { + /* Substitute no-cull,no-zwrite pipeline if available */ + if (data.heclIr.m_blendDst == boo::BlendFactor::One) + extended = EExtendedShader::ForcedAdditiveNoCullNoZWrite; + else + extended = EExtendedShader::ForcedAlphaNoCullNoZWrite; + } else if (flags.m_noCull) { + /* Substitute no-cull pipeline if available */ + if (data.heclIr.m_blendDst == boo::BlendFactor::One) + extended = EExtendedShader::ForcedAdditiveNoCull; + else + extended = EExtendedShader::ForcedAlphaNoCull; + } else if (noZWrite) { + /* Substitute no-zwrite pipeline if available */ + if (data.heclIr.m_blendDst == boo::BlendFactor::One) + extended = EExtendedShader::ForcedAdditiveNoZWrite; + else + extended = EExtendedShader::ForcedAlphaNoZWrite; + } else { + extended = EExtendedShader::Lighting; + } + } else if (flags.m_extendedShader < EExtendedShader::MAX) { + extended = flags.m_extendedShader; + } + + return extended; +} + +void CBooModel::DrawSurface(const CBooSurface& surf, const CModelFlags& flags) const { + // if (m_uniUpdateCount == 0) + // Log.report(logvisor::Fatal, "UpdateUniformData() not called"); + if (m_uniUpdateCount == 0 || m_uniUpdateCount > m_instances.size()) + return; + const ModelInstance& inst = m_instances[m_uniUpdateCount - 1]; + + const MaterialSet::Material& data = GetMaterialByIndex(surf.m_data.matIdx); + if (data.flags.shadowOccluderMesh() && !g_DrawingOccluders) + return; + + const std::vector>& extendeds = inst.m_shaderDataBindings[surf.selfIdx]; + EExtendedShader extended = ResolveExtendedShader(data, flags); + + boo::ObjToken binding = extendeds[extended]; + CGraphics::SetShaderDataBinding(binding); + CGraphics::DrawArrayIndexed(surf.m_data.idxStart, surf.m_data.idxCount); +} + +void CBooModel::WarmupDrawSurfaces() const { + const CBooSurface* surf = x38_firstUnsortedSurface; + while (surf) { + WarmupDrawSurface(*surf); + surf = surf->m_next; + } + + surf = x3c_firstSortedSurface; + while (surf) { + WarmupDrawSurface(*surf); + surf = surf->m_next; + } +} + +void CBooModel::WarmupDrawSurface(const CBooSurface& surf) const { + if (m_uniUpdateCount > m_instances.size()) + return; + const ModelInstance& inst = m_instances[m_uniUpdateCount - 1]; + + // Only warmup normal lighting and thermal visor + for (int i = 1; i <= 2; ++i) { + auto& binding = inst.m_shaderDataBindings[surf.selfIdx][i]; CGraphics::SetShaderDataBinding(binding); - CGraphics::DrawArrayIndexed(surf.m_data.idxStart, surf.m_data.idxCount); + CGraphics::DrawArrayIndexed(surf.m_data.idxStart, std::min(u32(3), surf.m_data.idxCount)); + } } -void CBooModel::WarmupDrawSurfaces() const -{ - const CBooSurface* surf = x38_firstUnsortedSurface; - while (surf) - { - WarmupDrawSurface(*surf); - surf = surf->m_next; - } +void CBooModel::UVAnimationBuffer::ProcessAnimation(u8*& bufOut, const UVAnimation& anim) { + zeus::CMatrix4f& texMtxOut = reinterpret_cast(*bufOut); + zeus::CMatrix4f& postMtxOut = reinterpret_cast(*(bufOut + sizeof(zeus::CMatrix4f))); + texMtxOut = zeus::CMatrix4f(); + postMtxOut = zeus::CMatrix4f(); + switch (anim.mode) { + case UVAnimation::Mode::MvInvNoTranslation: { + texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); + texMtxOut.m[3].w() = 1.f; + postMtxOut.m[0].x() = 0.5f; + postMtxOut.m[1].y() = 0.5f; + postMtxOut.m[3].x() = 0.5f; + postMtxOut.m[3].y() = 0.5f; + break; + } + case UVAnimation::Mode::MvInv: { + texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); + texMtxOut.m[3] = CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix.origin; + texMtxOut.m[3].w() = 1.f; + postMtxOut.m[0].x() = 0.5f; + postMtxOut.m[1].y() = 0.5f; + postMtxOut.m[3].x() = 0.5f; + postMtxOut.m[3].y() = 0.5f; + break; + } + case UVAnimation::Mode::Scroll: { + texMtxOut.m[3].x() = CGraphics::GetSecondsMod900() * anim.vals[2] + anim.vals[0]; + texMtxOut.m[3].y() = CGraphics::GetSecondsMod900() * anim.vals[3] + anim.vals[1]; + break; + } + case UVAnimation::Mode::Rotation: { + float angle = CGraphics::GetSecondsMod900() * anim.vals[1] + anim.vals[0]; + float acos = std::cos(angle); + float asin = std::sin(angle); + texMtxOut.m[0].x() = acos; + texMtxOut.m[0].y() = asin; + texMtxOut.m[1].x() = -asin; + texMtxOut.m[1].y() = acos; + texMtxOut.m[3].x() = (1.0f - (acos - asin)) * 0.5f; + texMtxOut.m[3].y() = (1.0f - (asin + acos)) * 0.5f; + break; + } + case UVAnimation::Mode::HStrip: { + float value = anim.vals[0] * anim.vals[2] * (anim.vals[3] + CGraphics::GetSecondsMod900()); + texMtxOut.m[3].x() = (float)(short)(anim.vals[1] * fmod(value, 1.0f)) * anim.vals[2]; + break; + } + case UVAnimation::Mode::VStrip: { + float value = anim.vals[0] * anim.vals[2] * (anim.vals[3] + CGraphics::GetSecondsMod900()); + texMtxOut.m[3].y() = (float)(short)(anim.vals[1] * fmod(value, 1.0f)) * anim.vals[2]; + break; + } + case UVAnimation::Mode::Model: { + texMtxOut = CGraphics::g_GXModelMatrix.toMatrix4f(); + texMtxOut.m[3].zeroOut(); + postMtxOut.m[0].x() = 0.5f; + postMtxOut.m[1].y() = 0.f; + postMtxOut.m[2].y() = 0.5f; + postMtxOut.m[3].x() = CGraphics::g_GXModelMatrix.origin.x() * 0.05f; + postMtxOut.m[3].y() = CGraphics::g_GXModelMatrix.origin.y() * 0.05f; + break; + } + case UVAnimation::Mode::CylinderEnvironment: { + texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); - surf = x3c_firstSortedSurface; - while (surf) - { - WarmupDrawSurface(*surf); - surf = surf->m_next; - } + const zeus::CVector3f& viewOrigin = CGraphics::g_ViewMatrix.origin; + float xy = (viewOrigin.x() + viewOrigin.y()) * 0.025f * anim.vals[1]; + xy = (xy - (int)xy); + float z = (viewOrigin.z()) * 0.05f * anim.vals[1]; + z = (z - (int)z); + + float halfA = anim.vals[0] * 0.5f; + + postMtxOut = + zeus::CTransform(zeus::CMatrix3f(halfA, 0.0, 0.0, 0.0, 0.0, halfA, 0.0, 0.0, 0.0), zeus::CVector3f(xy, z, 1.0)) + .toMatrix4f(); + break; + } + default: + break; + } + bufOut += sizeof(zeus::CMatrix4f) * 2; } -void CBooModel::WarmupDrawSurface(const CBooSurface& surf) const -{ - if (m_uniUpdateCount > m_instances.size()) - return; - const ModelInstance& inst = m_instances[m_uniUpdateCount-1]; - - // Only warmup normal lighting and thermal visor - for (int i=1 ; i<=2 ; ++i) - { - auto& binding = inst.m_shaderDataBindings[surf.selfIdx][i]; - CGraphics::SetShaderDataBinding(binding); - CGraphics::DrawArrayIndexed(surf.m_data.idxStart, std::min(u32(3), surf.m_data.idxCount)); - } +void CBooModel::UVAnimationBuffer::PadOutBuffer(u8*& bufStart, u8*& bufOut) { + bufOut = bufStart + ROUND_UP_256(bufOut - bufStart); } -void CBooModel::UVAnimationBuffer::ProcessAnimation(u8*& bufOut, const UVAnimation& anim) -{ - zeus::CMatrix4f& texMtxOut = reinterpret_cast(*bufOut); - zeus::CMatrix4f& postMtxOut = reinterpret_cast(*(bufOut + sizeof(zeus::CMatrix4f))); - texMtxOut = zeus::CMatrix4f(); - postMtxOut = zeus::CMatrix4f(); - switch (anim.mode) - { - case UVAnimation::Mode::MvInvNoTranslation: - { - texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); - texMtxOut.m[3].w() = 1.f; - postMtxOut.m[0].x() = 0.5f; - postMtxOut.m[1].y() = 0.5f; - postMtxOut.m[3].x() = 0.5f; - postMtxOut.m[3].y() = 0.5f; - break; - } - case UVAnimation::Mode::MvInv: - { - texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); - texMtxOut.m[3] = CGraphics::g_ViewMatrix.inverse() * CGraphics::g_GXModelMatrix.origin; - texMtxOut.m[3].w() = 1.f; - postMtxOut.m[0].x() = 0.5f; - postMtxOut.m[1].y() = 0.5f; - postMtxOut.m[3].x() = 0.5f; - postMtxOut.m[3].y() = 0.5f; - break; - } - case UVAnimation::Mode::Scroll: - { - texMtxOut.m[3].x() = CGraphics::GetSecondsMod900() * anim.vals[2] + anim.vals[0]; - texMtxOut.m[3].y() = CGraphics::GetSecondsMod900() * anim.vals[3] + anim.vals[1]; - break; - } - case UVAnimation::Mode::Rotation: - { - float angle = CGraphics::GetSecondsMod900() * anim.vals[1] + anim.vals[0]; - float acos = std::cos(angle); - float asin = std::sin(angle); - texMtxOut.m[0].x() = acos; - texMtxOut.m[0].y() = asin; - texMtxOut.m[1].x() = -asin; - texMtxOut.m[1].y() = acos; - texMtxOut.m[3].x() = (1.0f - (acos - asin)) * 0.5f; - texMtxOut.m[3].y() = (1.0f - (asin + acos)) * 0.5f; - break; - } - case UVAnimation::Mode::HStrip: - { - float value = anim.vals[0] * anim.vals[2] * (anim.vals[3] + CGraphics::GetSecondsMod900()); - texMtxOut.m[3].x() = (float)(short)(anim.vals[1] * fmod(value, 1.0f)) * anim.vals[2]; - break; - } - case UVAnimation::Mode::VStrip: - { - float value = anim.vals[0] * anim.vals[2] * (anim.vals[3] + CGraphics::GetSecondsMod900()); - texMtxOut.m[3].y() = (float)(short)(anim.vals[1] * fmod(value, 1.0f)) * anim.vals[2]; - break; - } - case UVAnimation::Mode::Model: - { - texMtxOut = CGraphics::g_GXModelMatrix.toMatrix4f(); - texMtxOut.m[3].zeroOut(); - postMtxOut.m[0].x() = 0.5f; - postMtxOut.m[1].y() = 0.f; - postMtxOut.m[2].y() = 0.5f; - postMtxOut.m[3].x() = CGraphics::g_GXModelMatrix.origin.x() * 0.05f; - postMtxOut.m[3].y() = CGraphics::g_GXModelMatrix.origin.y() * 0.05f; - break; - } - case UVAnimation::Mode::CylinderEnvironment: - { - texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); +static const zeus::CMatrix4f MBShadowPost0(1.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, + 1.f); - const zeus::CVector3f& viewOrigin = CGraphics::g_ViewMatrix.origin; - float xy = (viewOrigin.x() + viewOrigin.y()) * 0.025f * anim.vals[1]; - xy = (xy - (int)xy); - float z = (viewOrigin.z()) * 0.05f * anim.vals[1]; - z = (z - (int)z); +static const zeus::CMatrix4f MBShadowPost1(0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f, -0.0625f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, + 0.f, 1.f); - float halfA = anim.vals[0] * 0.5f; +static const zeus::CMatrix4f DisintegratePost(1.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, + 1.f); - postMtxOut = zeus::CTransform(zeus::CMatrix3f(halfA, 0.0, 0.0, - 0.0, 0.0, halfA, - 0.0, 0.0, 0.0), - zeus::CVector3f(xy, z, 1.0)).toMatrix4f(); - break; +void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet, const CModelFlags& flags, + const CBooModel* parent) { + u8* start = bufOut; + + if (flags.m_extendedShader == EExtendedShader::MorphBallShadow) { + /* Special matrices for MorphBall shadow rendering */ + zeus::CMatrix4f texMtx = (zeus::CTransform::Scale(1.f / (flags.mbShadowBox.max - flags.mbShadowBox.min)) * + zeus::CTransform::Translate(-flags.mbShadowBox.min) * CGraphics::g_GXModelView) + .toMatrix4f(); + for (const MaterialSet::Material& mat : matSet->materials) { + (void)mat; + std::array* mtxs = reinterpret_cast*>(bufOut); + mtxs[0][0] = texMtx; + mtxs[0][1] = MBShadowPost0; + mtxs[1][0] = texMtx; + mtxs[1][1] = MBShadowPost1; + bufOut += sizeof(zeus::CMatrix4f) * 2 * 8; + PadOutBuffer(start, bufOut); } - default: break; + return; + } else if (flags.m_extendedShader == EExtendedShader::Disintegrate) { + assert(parent != nullptr && "Parent CBooModel not set"); + zeus::CTransform xf = zeus::CTransform::RotateX(-zeus::degToRad(45.f)); + zeus::CAABox aabb = parent->GetAABB().getTransformedAABox(xf); + xf = zeus::CTransform::Scale(5.f / (aabb.max - aabb.min)) * zeus::CTransform::Translate(-aabb.min) * xf; + zeus::CMatrix4f texMtx = xf.toMatrix4f(); + zeus::CMatrix4f post0 = DisintegratePost; + post0[3].x() = flags.addColor.a(); + post0[3].y() = 6.f * -(1.f - flags.addColor.a()) + 1.f; + zeus::CMatrix4f post1 = DisintegratePost; + post1[3].x() = -0.85f * flags.addColor.a() - 0.15f; + post1[3].y() = float(post0[3].y()); + /* Special matrices for disintegration rendering */ + for (const MaterialSet::Material& mat : matSet->materials) { + (void)mat; + std::array* mtxs = reinterpret_cast*>(bufOut); + mtxs[0][0] = texMtx; + mtxs[0][1] = post0; + mtxs[1][0] = texMtx; + mtxs[1][1] = post1; + bufOut += sizeof(zeus::CMatrix4f) * 2 * 8; + PadOutBuffer(start, bufOut); } - bufOut += sizeof(zeus::CMatrix4f) * 2; + return; + } + + std::experimental::optional> specialMtxOut; + if (flags.m_extendedShader == EExtendedShader::Thermal) { + /* Special Mode0 matrix for exclusive Thermal Visor use */ + specialMtxOut.emplace(); + + /* This part handled in-shader + zeus::CMatrix4f& texMtxOut = (*specialMtxOut)[0]; + texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); + texMtxOut.vec[3].zeroOut(); + texMtxOut.vec[3].w = 1.f; + */ + + zeus::CMatrix4f& postMtxOut = (*specialMtxOut)[1]; + postMtxOut.m[0].x() = 0.5f; + postMtxOut.m[1].y() = 0.5f; + postMtxOut.m[3].x() = 0.5f; + postMtxOut.m[3].y() = 0.5f; + } else if (flags.m_extendedShader == EExtendedShader::WorldShadow) { + /* Special matrix for mapping world shadow */ + specialMtxOut.emplace(); + + zeus::CMatrix4f mat = g_shadowTexXf.toMatrix4f(); + zeus::CMatrix4f& texMtxOut = (*specialMtxOut)[0]; + texMtxOut[0][0] = float(mat[0][0]); + texMtxOut[1][0] = float(mat[1][0]); + texMtxOut[2][0] = float(mat[2][0]); + texMtxOut[3][0] = float(mat[3][0]); + texMtxOut[0][1] = float(mat[0][2]); + texMtxOut[1][1] = float(mat[1][2]); + texMtxOut[2][1] = float(mat[2][2]); + texMtxOut[3][1] = float(mat[3][2]); + } + + for (const MaterialSet::Material& mat : matSet->materials) { + if (specialMtxOut) { + std::array* mtxs = reinterpret_cast*>(bufOut); + mtxs[7][0] = (*specialMtxOut)[0]; + mtxs[7][1] = (*specialMtxOut)[1]; + } + u8* bufOrig = bufOut; + for (const UVAnimation& anim : mat.uvAnims) + ProcessAnimation(bufOut, anim); + bufOut = bufOrig + sizeof(zeus::CMatrix4f) * 2 * 8; + PadOutBuffer(start, bufOut); + } } -void CBooModel::UVAnimationBuffer::PadOutBuffer(u8*& bufStart, u8*& bufOut) -{ - bufOut = bufStart + ROUND_UP_256(bufOut - bufStart); -} +void GeometryUniformLayout::Update(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose, + const MaterialSet* matSet, const boo::ObjToken& buf, + const CBooModel* parent) const { + u8* dataOut = reinterpret_cast(buf->map(m_geomBufferSize)); + u8* dataCur = dataOut; -static const zeus::CMatrix4f MBShadowPost0(1.f, 0.f, 0.f, 0.f, - 0.f, -1.f, 0.f, 1.f, - 0.f, 0.f, 0.f, 1.f, - 0.f, 0.f, 0.f, 1.f); + if (m_skinBankCount) { + /* Skinned */ + std::vector bankTransforms; + size_t weightCount = m_weightVecCount * 4; + bankTransforms.reserve(weightCount); + for (size_t i = 0; i < m_skinBankCount; ++i) { + if (cskr && pose) { + cskr->GetBankTransforms(bankTransforms, *pose, i); -static const zeus::CMatrix4f MBShadowPost1(0.f, 0.f, 0.f, 1.f, - 0.f, 0.f, 1.f, -0.0625f, - 0.f, 0.f, 0.f, 1.f, - 0.f, 0.f, 0.f, 1.f); - -static const zeus::CMatrix4f DisintegratePost(1.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f, - 0.f, 0.f, 0.f, 1.f); - -void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet, - const CModelFlags& flags, const CBooModel* parent) -{ - u8* start = bufOut; - - if (flags.m_extendedShader == EExtendedShader::MorphBallShadow) - { - /* Special matrices for MorphBall shadow rendering */ - zeus::CMatrix4f texMtx = - (zeus::CTransform::Scale(1.f / (flags.mbShadowBox.max - flags.mbShadowBox.min)) * - zeus::CTransform::Translate(-flags.mbShadowBox.min) * CGraphics::g_GXModelView).toMatrix4f(); - for (const MaterialSet::Material& mat : matSet->materials) - { - (void)mat; - std::array* mtxs = reinterpret_cast*>(bufOut); - mtxs[0][0] = texMtx; - mtxs[0][1] = MBShadowPost0; - mtxs[1][0] = texMtx; - mtxs[1][1] = MBShadowPost1; - bufOut += sizeof(zeus::CMatrix4f) * 2 * 8; - PadOutBuffer(start, bufOut); + for (size_t w = 0; w < weightCount; ++w) { + zeus::CMatrix4f& obj = reinterpret_cast(*dataCur); + if (w >= bankTransforms.size()) + obj = zeus::CMatrix4f::skIdentityMatrix4f; + else + obj = bankTransforms[w]->toMatrix4f(); + dataCur += sizeof(zeus::CMatrix4f); } - return; - } - else if (flags.m_extendedShader == EExtendedShader::Disintegrate) - { - assert(parent != nullptr && "Parent CBooModel not set"); - zeus::CTransform xf = zeus::CTransform::RotateX(-zeus::degToRad(45.f)); - zeus::CAABox aabb = parent->GetAABB().getTransformedAABox(xf); - xf = zeus::CTransform::Scale(5.f / (aabb.max - aabb.min)) * - zeus::CTransform::Translate(-aabb.min) * xf; - zeus::CMatrix4f texMtx = xf.toMatrix4f(); - zeus::CMatrix4f post0 = DisintegratePost; - post0[3].x() = flags.addColor.a(); - post0[3].y() = 6.f * -(1.f - flags.addColor.a()) + 1.f; - zeus::CMatrix4f post1 = DisintegratePost; - post1[3].x() = -0.85f * flags.addColor.a() - 0.15f; - post1[3].y() = float(post0[3].y()); - /* Special matrices for disintegration rendering */ - for (const MaterialSet::Material& mat : matSet->materials) - { - (void)mat; - std::array* mtxs = reinterpret_cast*>(bufOut); - mtxs[0][0] = texMtx; - mtxs[0][1] = post0; - mtxs[1][0] = texMtx; - mtxs[1][1] = post1; - bufOut += sizeof(zeus::CMatrix4f) * 2 * 8; - PadOutBuffer(start, bufOut); + for (size_t w = 0; w < weightCount; ++w) { + zeus::CMatrix4f& objInv = reinterpret_cast(*dataCur); + if (w >= bankTransforms.size()) + objInv = zeus::CMatrix4f::skIdentityMatrix4f; + else + objInv = bankTransforms[w]->basis; + dataCur += sizeof(zeus::CMatrix4f); } - return; - } - std::experimental::optional> specialMtxOut; - if (flags.m_extendedShader == EExtendedShader::Thermal) - { - /* Special Mode0 matrix for exclusive Thermal Visor use */ - specialMtxOut.emplace(); - - /* This part handled in-shader - zeus::CMatrix4f& texMtxOut = (*specialMtxOut)[0]; - texMtxOut = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); - texMtxOut.vec[3].zeroOut(); - texMtxOut.vec[3].w = 1.f; - */ - - zeus::CMatrix4f& postMtxOut = (*specialMtxOut)[1]; - postMtxOut.m[0].x() = 0.5f; - postMtxOut.m[1].y() = 0.5f; - postMtxOut.m[3].x() = 0.5f; - postMtxOut.m[3].y() = 0.5f; - } - else if (flags.m_extendedShader == EExtendedShader::WorldShadow) - { - /* Special matrix for mapping world shadow */ - specialMtxOut.emplace(); - - zeus::CMatrix4f mat = g_shadowTexXf.toMatrix4f(); - zeus::CMatrix4f& texMtxOut = (*specialMtxOut)[0]; - texMtxOut[0][0] = float(mat[0][0]); - texMtxOut[1][0] = float(mat[1][0]); - texMtxOut[2][0] = float(mat[2][0]); - texMtxOut[3][0] = float(mat[3][0]); - texMtxOut[0][1] = float(mat[0][2]); - texMtxOut[1][1] = float(mat[1][2]); - texMtxOut[2][1] = float(mat[2][2]); - texMtxOut[3][1] = float(mat[3][2]); - } - - for (const MaterialSet::Material& mat : matSet->materials) - { - if (specialMtxOut) - { - std::array* mtxs = reinterpret_cast*>(bufOut); - mtxs[7][0] = (*specialMtxOut)[0]; - mtxs[7][1] = (*specialMtxOut)[1]; + bankTransforms.clear(); + } else { + for (size_t w = 0; w < weightCount; ++w) { + zeus::CMatrix4f& mv = reinterpret_cast(*dataCur); + mv = zeus::CMatrix4f::skIdentityMatrix4f; + dataCur += sizeof(zeus::CMatrix4f); } - u8* bufOrig = bufOut; - for (const UVAnimation& anim : mat.uvAnims) - ProcessAnimation(bufOut, anim); - bufOut = bufOrig + sizeof(zeus::CMatrix4f) * 2 * 8; - PadOutBuffer(start, bufOut); - } -} - -void GeometryUniformLayout::Update(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose, - const MaterialSet* matSet, - const boo::ObjToken& buf, - const CBooModel* parent) const -{ - u8* dataOut = reinterpret_cast(buf->map(m_geomBufferSize)); - u8* dataCur = dataOut; - - if (m_skinBankCount) - { - /* Skinned */ - std::vector bankTransforms; - size_t weightCount = m_weightVecCount * 4; - bankTransforms.reserve(weightCount); - for (size_t i=0 ; iGetBankTransforms(bankTransforms, *pose, i); - - for (size_t w=0 ; w(*dataCur); - if (w >= bankTransforms.size()) - obj = zeus::CMatrix4f::skIdentityMatrix4f; - else - obj = bankTransforms[w]->toMatrix4f(); - dataCur += sizeof(zeus::CMatrix4f); - } - for (size_t w=0 ; w(*dataCur); - if (w >= bankTransforms.size()) - objInv = zeus::CMatrix4f::skIdentityMatrix4f; - else - objInv = bankTransforms[w]->basis; - dataCur += sizeof(zeus::CMatrix4f); - } - - bankTransforms.clear(); - } - else - { - for (size_t w=0 ; w(*dataCur); - mv = zeus::CMatrix4f::skIdentityMatrix4f; - dataCur += sizeof(zeus::CMatrix4f); - } - for (size_t w=0 ; w(*dataCur); - mvinv = zeus::CMatrix4f::skIdentityMatrix4f; - dataCur += sizeof(zeus::CMatrix4f); - } - } - zeus::CMatrix4f& mv = reinterpret_cast(*dataCur); - mv = CGraphics::g_GXModelView.toMatrix4f(); - dataCur += sizeof(zeus::CMatrix4f); - - zeus::CMatrix4f& mvinv = reinterpret_cast(*dataCur); - mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); - dataCur += sizeof(zeus::CMatrix4f); - - zeus::CMatrix4f& proj = reinterpret_cast(*dataCur); - proj = CGraphics::GetPerspectiveProjectionMatrix(true); - dataCur += sizeof(zeus::CMatrix4f); - - dataCur = dataOut + ROUND_UP_256(dataCur - dataOut); + for (size_t w = 0; w < weightCount; ++w) { + zeus::CMatrix4f& mvinv = reinterpret_cast(*dataCur); + mvinv = zeus::CMatrix4f::skIdentityMatrix4f; + dataCur += sizeof(zeus::CMatrix4f); } - } - else - { - /* Non-Skinned */ - zeus::CMatrix4f& mv = reinterpret_cast(*dataCur); - mv = CGraphics::g_GXModelView.toMatrix4f(); - dataCur += sizeof(zeus::CMatrix4f); + } + zeus::CMatrix4f& mv = reinterpret_cast(*dataCur); + mv = CGraphics::g_GXModelView.toMatrix4f(); + dataCur += sizeof(zeus::CMatrix4f); - zeus::CMatrix4f& mvinv = reinterpret_cast(*dataCur); - mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); - dataCur += sizeof(zeus::CMatrix4f); + zeus::CMatrix4f& mvinv = reinterpret_cast(*dataCur); + mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); + dataCur += sizeof(zeus::CMatrix4f); - zeus::CMatrix4f& proj = reinterpret_cast(*dataCur); - proj = CGraphics::GetPerspectiveProjectionMatrix(true); - dataCur += sizeof(zeus::CMatrix4f); + zeus::CMatrix4f& proj = reinterpret_cast(*dataCur); + proj = CGraphics::GetPerspectiveProjectionMatrix(true); + dataCur += sizeof(zeus::CMatrix4f); - dataCur = dataOut + ROUND_UP_256(dataCur - dataOut); + dataCur = dataOut + ROUND_UP_256(dataCur - dataOut); } + } else { + /* Non-Skinned */ + zeus::CMatrix4f& mv = reinterpret_cast(*dataCur); + mv = CGraphics::g_GXModelView.toMatrix4f(); + dataCur += sizeof(zeus::CMatrix4f); - CBooModel::UVAnimationBuffer::Update(dataCur, matSet, flags, parent); - buf->unmap(); -} + zeus::CMatrix4f& mvinv = reinterpret_cast(*dataCur); + mvinv = CGraphics::g_GXModelViewInvXpose.toMatrix4f(); + dataCur += sizeof(zeus::CMatrix4f); -boo::ObjToken CBooModel::UpdateUniformData(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose, - int sharedLayoutBuf) const -{ - /* Invalidate instances if new shadow being drawn */ - if (flags.m_extendedShader == EExtendedShader::WorldShadow && - m_lastDrawnShadowMap != g_shadowMap) - { - const_cast(this)->m_lastDrawnShadowMap = g_shadowMap; - const_cast(this)->m_instances.clear(); - } + zeus::CMatrix4f& proj = reinterpret_cast(*dataCur); + proj = CGraphics::GetPerspectiveProjectionMatrix(true); + dataCur += sizeof(zeus::CMatrix4f); - /* Invalidate instances if new one-texture being drawn */ - if (flags.m_extendedShader == EExtendedShader::Disintegrate && - m_lastDrawnOneTexture != g_disintegrateTexture) - { - const_cast(this)->m_lastDrawnOneTexture = g_disintegrateTexture; - const_cast(this)->m_instances.clear(); - } - - const ModelInstance* inst; - if (sharedLayoutBuf >= 0) - { - if (m_instances.size() <= sharedLayoutBuf) - { - do - { - inst = const_cast(this)->PushNewModelInstance(m_instances.size()); - if (!inst) - return nullptr; - } while (m_instances.size() <= sharedLayoutBuf); - } - else - inst = &m_instances[sharedLayoutBuf]; - const_cast(this)->m_uniUpdateCount = sharedLayoutBuf + 1; - } - else - { - if (m_instances.size() <= m_uniUpdateCount) - { - inst = const_cast(this)->PushNewModelInstance(sharedLayoutBuf); - if (!inst) - return nullptr; - } - else - inst = &m_instances[m_uniUpdateCount]; - ++const_cast(this)->m_uniUpdateCount; - } - - if (inst->m_geomUniformBuffer) - m_geomLayout->Update(flags, cskr, pose, x4_matSet, inst->m_geomUniformBuffer, this); - - u8* dataOut = reinterpret_cast(inst->m_uniformBuffer->map(m_uniformDataSize)); - u8* dataCur = dataOut; - - if (flags.m_extendedShader == EExtendedShader::Thermal) /* Thermal Model (same as UV Mode 0) */ - { - CModelShaders::ThermalUniform& thermalOut = *reinterpret_cast(dataCur); - thermalOut.mulColor = flags.x4_color; - thermalOut.addColor = flags.addColor; - } - else if (flags.m_extendedShader >= EExtendedShader::SolidColor && - flags.m_extendedShader <= EExtendedShader::SolidColorBackfaceCullGreaterAlphaOnly) /* Solid color render */ - { - CModelShaders::SolidUniform& solidOut = *reinterpret_cast(dataCur); - solidOut.solidColor = flags.x4_color; - } - else if (flags.m_extendedShader == EExtendedShader::MorphBallShadow) /* MorphBall shadow render */ - { - CModelShaders::MBShadowUniform& shadowOut = *reinterpret_cast(dataCur); - shadowOut.shadowUp = CGraphics::g_GXModelView * zeus::CVector3f::skUp; - shadowOut.shadowUp.w() = flags.x4_color.a(); - shadowOut.shadowId = flags.x4_color.r(); - } - else if (flags.m_extendedShader == EExtendedShader::Disintegrate) - { - CModelShaders::OneTextureUniform& oneTexOut = *reinterpret_cast(dataCur); - oneTexOut.addColor = flags.addColor; - oneTexOut.fog = CGraphics::g_Fog; - } - else - { - CModelShaders::LightingUniform& lightingOut = *reinterpret_cast(dataCur); - lightingOut = m_lightingData; - lightingOut.colorRegs[0] = CGraphics::g_ColorRegs[0]; - lightingOut.colorRegs[1] = CGraphics::g_ColorRegs[1]; - lightingOut.colorRegs[2] = CGraphics::g_ColorRegs[2]; - lightingOut.mulColor = flags.x4_color; - lightingOut.fog = CGraphics::g_Fog; - } - - dataCur += sizeof(CModelShaders::LightingUniform); dataCur = dataOut + ROUND_UP_256(dataCur - dataOut); + } - /* Reflection texmtx uniform */ - zeus::CMatrix4f* identMtxs = reinterpret_cast(dataCur); - identMtxs[0] = zeus::CMatrix4f(); - identMtxs[1] = zeus::CMatrix4f(); - u8* curReflect = dataCur + 256; - for (const CBooSurface& surf : *x0_surfaces) - { - const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx); - if (mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye()) - { - zeus::CMatrix4f* mtxs = reinterpret_cast(curReflect); - float& alpha = reinterpret_cast(mtxs[2]); - curReflect += 256; - EnsureViewDepStateCached(*this, mat.flags.samusReflectionSurfaceEye() ? &surf : nullptr, mtxs, alpha); - } - } - - inst->m_uniformBuffer->unmap(); - return inst->m_dynamicVbo; - } - -void CBooModel::DrawAlpha(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose) const -{ - CModelFlags rFlags = flags; - /* Check if we're overriding with RenderModelBlack */ - if (g_RenderModelBlack) - { - rFlags.m_extendedShader = EExtendedShader::SolidColor; - rFlags.x4_color = zeus::CColor::skBlack; - } - - if (TryLockTextures()) - { - UpdateUniformData(rFlags, cskr, pose); - DrawAlphaSurfaces(rFlags); - } + CBooModel::UVAnimationBuffer::Update(dataCur, matSet, flags, parent); + buf->unmap(); } -void CBooModel::DrawNormal(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose) const -{ - CModelFlags rFlags = flags; - /* Check if we're overriding with RenderModelBlack */ - if (g_RenderModelBlack) - { - rFlags.m_extendedShader = EExtendedShader::SolidColor; - rFlags.x4_color = zeus::CColor::skBlack; - } - if (TryLockTextures()) - { - UpdateUniformData(rFlags, cskr, pose); - DrawNormalSurfaces(rFlags); +boo::ObjToken CBooModel::UpdateUniformData(const CModelFlags& flags, const CSkinRules* cskr, + const CPoseAsTransforms* pose, + int sharedLayoutBuf) const { + /* Invalidate instances if new shadow being drawn */ + if (flags.m_extendedShader == EExtendedShader::WorldShadow && m_lastDrawnShadowMap != g_shadowMap) { + const_cast(this)->m_lastDrawnShadowMap = g_shadowMap; + const_cast(this)->m_instances.clear(); + } + + /* Invalidate instances if new one-texture being drawn */ + if (flags.m_extendedShader == EExtendedShader::Disintegrate && m_lastDrawnOneTexture != g_disintegrateTexture) { + const_cast(this)->m_lastDrawnOneTexture = g_disintegrateTexture; + const_cast(this)->m_instances.clear(); + } + + const ModelInstance* inst; + if (sharedLayoutBuf >= 0) { + if (m_instances.size() <= sharedLayoutBuf) { + do { + inst = const_cast(this)->PushNewModelInstance(m_instances.size()); + if (!inst) + return nullptr; + } while (m_instances.size() <= sharedLayoutBuf); + } else + inst = &m_instances[sharedLayoutBuf]; + const_cast(this)->m_uniUpdateCount = sharedLayoutBuf + 1; + } else { + if (m_instances.size() <= m_uniUpdateCount) { + inst = const_cast(this)->PushNewModelInstance(sharedLayoutBuf); + if (!inst) + return nullptr; + } else + inst = &m_instances[m_uniUpdateCount]; + ++const_cast(this)->m_uniUpdateCount; + } + + if (inst->m_geomUniformBuffer) + m_geomLayout->Update(flags, cskr, pose, x4_matSet, inst->m_geomUniformBuffer, this); + + u8* dataOut = reinterpret_cast(inst->m_uniformBuffer->map(m_uniformDataSize)); + u8* dataCur = dataOut; + + if (flags.m_extendedShader == EExtendedShader::Thermal) /* Thermal Model (same as UV Mode 0) */ + { + CModelShaders::ThermalUniform& thermalOut = *reinterpret_cast(dataCur); + thermalOut.mulColor = flags.x4_color; + thermalOut.addColor = flags.addColor; + } else if (flags.m_extendedShader >= EExtendedShader::SolidColor && + flags.m_extendedShader <= EExtendedShader::SolidColorBackfaceCullGreaterAlphaOnly) /* Solid color render */ + { + CModelShaders::SolidUniform& solidOut = *reinterpret_cast(dataCur); + solidOut.solidColor = flags.x4_color; + } else if (flags.m_extendedShader == EExtendedShader::MorphBallShadow) /* MorphBall shadow render */ + { + CModelShaders::MBShadowUniform& shadowOut = *reinterpret_cast(dataCur); + shadowOut.shadowUp = CGraphics::g_GXModelView * zeus::CVector3f::skUp; + shadowOut.shadowUp.w() = flags.x4_color.a(); + shadowOut.shadowId = flags.x4_color.r(); + } else if (flags.m_extendedShader == EExtendedShader::Disintegrate) { + CModelShaders::OneTextureUniform& oneTexOut = *reinterpret_cast(dataCur); + oneTexOut.addColor = flags.addColor; + oneTexOut.fog = CGraphics::g_Fog; + } else { + CModelShaders::LightingUniform& lightingOut = *reinterpret_cast(dataCur); + lightingOut = m_lightingData; + lightingOut.colorRegs[0] = CGraphics::g_ColorRegs[0]; + lightingOut.colorRegs[1] = CGraphics::g_ColorRegs[1]; + lightingOut.colorRegs[2] = CGraphics::g_ColorRegs[2]; + lightingOut.mulColor = flags.x4_color; + lightingOut.fog = CGraphics::g_Fog; + } + + dataCur += sizeof(CModelShaders::LightingUniform); + dataCur = dataOut + ROUND_UP_256(dataCur - dataOut); + + /* Reflection texmtx uniform */ + zeus::CMatrix4f* identMtxs = reinterpret_cast(dataCur); + identMtxs[0] = zeus::CMatrix4f(); + identMtxs[1] = zeus::CMatrix4f(); + u8* curReflect = dataCur + 256; + for (const CBooSurface& surf : *x0_surfaces) { + const MaterialSet::Material& mat = x4_matSet->materials.at(surf.m_data.matIdx); + if (mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye()) { + zeus::CMatrix4f* mtxs = reinterpret_cast(curReflect); + float& alpha = reinterpret_cast(mtxs[2]); + curReflect += 256; + EnsureViewDepStateCached(*this, mat.flags.samusReflectionSurfaceEye() ? &surf : nullptr, mtxs, alpha); } + } + + inst->m_uniformBuffer->unmap(); + return inst->m_dynamicVbo; } -void CBooModel::Draw(const CModelFlags& flags, - const CSkinRules* cskr, - const CPoseAsTransforms* pose) const -{ - CModelFlags rFlags = flags; - /* Check if we're overriding with RenderModelBlack */ - if (g_RenderModelBlack) - { - rFlags.m_extendedShader = EExtendedShader::SolidColor; - rFlags.x4_color = zeus::CColor::skBlack; - } +void CBooModel::DrawAlpha(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose) const { + CModelFlags rFlags = flags; + /* Check if we're overriding with RenderModelBlack */ + if (g_RenderModelBlack) { + rFlags.m_extendedShader = EExtendedShader::SolidColor; + rFlags.x4_color = zeus::CColor::skBlack; + } - if (TryLockTextures()) - { - UpdateUniformData(rFlags, cskr, pose); - DrawSurfaces(rFlags); - } + if (TryLockTextures()) { + UpdateUniformData(rFlags, cskr, pose); + DrawAlphaSurfaces(rFlags); + } } -static const u8* MemoryFromPartData(const u8*& dataCur, const u32*& secSizeCur) -{ - const u8* ret; - if (*secSizeCur != 0) - ret = dataCur; - else - ret = nullptr; +void CBooModel::DrawNormal(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose) const { + CModelFlags rFlags = flags; + /* Check if we're overriding with RenderModelBlack */ + if (g_RenderModelBlack) { + rFlags.m_extendedShader = EExtendedShader::SolidColor; + rFlags.x4_color = zeus::CColor::skBlack; + } + if (TryLockTextures()) { + UpdateUniformData(rFlags, cskr, pose); + DrawNormalSurfaces(rFlags); + } +} - dataCur += hecl::SBig(*secSizeCur); - ++secSizeCur; - return ret; +void CBooModel::Draw(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose) const { + CModelFlags rFlags = flags; + /* Check if we're overriding with RenderModelBlack */ + if (g_RenderModelBlack) { + rFlags.m_extendedShader = EExtendedShader::SolidColor; + rFlags.x4_color = zeus::CColor::skBlack; + } + + if (TryLockTextures()) { + UpdateUniformData(rFlags, cskr, pose); + DrawSurfaces(rFlags); + } +} + +static const u8* MemoryFromPartData(const u8*& dataCur, const u32*& secSizeCur) { + const u8* ret; + if (*secSizeCur != 0) + ret = dataCur; + else + ret = nullptr; + + dataCur += hecl::SBig(*secSizeCur); + ++secSizeCur; + return ret; } std::unique_ptr CModel::MakeNewInstance(int shaderIdx, int subInsts, const boo::ObjToken txtrOverrides[8], - bool lockParent) -{ - if (shaderIdx >= x18_matSets.size()) - shaderIdx = 0; - auto ret = std::make_unique(m_selfToken, this, &x8_surfaces, x18_matSets[shaderIdx], - m_staticVbo, m_ibo, m_aabb, (m_flags & 0x2) != 0, subInsts, txtrOverrides); - if (lockParent) - ret->LockParent(); - return ret; + bool lockParent) { + if (shaderIdx >= x18_matSets.size()) + shaderIdx = 0; + auto ret = std::make_unique(m_selfToken, this, &x8_surfaces, x18_matSets[shaderIdx], m_staticVbo, m_ibo, + m_aabb, (m_flags & 0x2) != 0, subInsts, txtrOverrides); + if (lockParent) + ret->LockParent(); + return ret; } -CModelShaders::ShaderPipelines -SShader::BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat) -{ - hecl::Backend::ReflectionType reflectionType; - if (mat.flags.samusReflectionIndirectTexture()) - reflectionType = hecl::Backend::ReflectionType::Indirect; - else if (mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye()) - reflectionType = hecl::Backend::ReflectionType::Simple; - else - reflectionType = hecl::Backend::ReflectionType::None; - hecl::Backend::ShaderTag tag(mat.heclIr, - meta.colorCount, meta.uvCount, meta.weightCount, - meta.weightCount * 4, boo::Primitive(meta.topology), - reflectionType, true, true, true, mat.flags.alphaTest()); - return CModelShaders::BuildExtendedShader(tag, mat.heclIr); +CModelShaders::ShaderPipelines SShader::BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat) { + hecl::Backend::ReflectionType reflectionType; + if (mat.flags.samusReflectionIndirectTexture()) + reflectionType = hecl::Backend::ReflectionType::Indirect; + else if (mat.flags.samusReflection() || mat.flags.samusReflectionSurfaceEye()) + reflectionType = hecl::Backend::ReflectionType::Simple; + else + reflectionType = hecl::Backend::ReflectionType::None; + hecl::Backend::ShaderTag tag(mat.heclIr, meta.colorCount, meta.uvCount, meta.weightCount, meta.weightCount * 4, + boo::Primitive(meta.topology), reflectionType, true, true, true, mat.flags.alphaTest()); + return CModelShaders::BuildExtendedShader(tag, mat.heclIr); } void SShader::BuildShaders(const hecl::HMDLMeta& meta, - std::unordered_map& shaders) -{ - shaders.reserve(m_matSet.materials.size()); - int idx = 0; - for (const MaterialSet::Material& mat : m_matSet.materials) - shaders[idx++] = BuildShader(meta, mat); + std::unordered_map& shaders) { + shaders.reserve(m_matSet.materials.size()); + int idx = 0; + for (const MaterialSet::Material& mat : m_matSet.materials) + shaders[idx++] = BuildShader(meta, mat); } CModel::CModel(std::unique_ptr&& in, u32 /* dataLen */, IObjectStore* store, CObjectReference* selfRef) -: m_selfToken(selfRef) -{ - x38_lastFrame = CGraphics::GetFrameCounter() - 2; - std::unique_ptr data = std::move(in); +: m_selfToken(selfRef) { + x38_lastFrame = CGraphics::GetFrameCounter() - 2; + std::unique_ptr data = std::move(in); - u32 version = hecl::SBig(*reinterpret_cast(data.get() + 0x4)); - m_flags = hecl::SBig(*reinterpret_cast(data.get() + 0x8)); - if (version != 0x10002) - Log.report(logvisor::Fatal, "invalid CMDL for loading with boo"); + u32 version = hecl::SBig(*reinterpret_cast(data.get() + 0x4)); + m_flags = hecl::SBig(*reinterpret_cast(data.get() + 0x8)); + if (version != 0x10002) + Log.report(logvisor::Fatal, "invalid CMDL for loading with boo"); - u32 secCount = hecl::SBig(*reinterpret_cast(data.get() + 0x24)); - u32 matSetCount = hecl::SBig(*reinterpret_cast(data.get() + 0x28)); - x18_matSets.reserve(matSetCount); - const u8* dataCur = data.get() + ROUND_UP_32(0x2c + secCount * 4); - const u32* secSizeCur = reinterpret_cast(data.get() + 0x2c); - for (u32 i=0 ; i(data.get() + 0x24)); + u32 matSetCount = hecl::SBig(*reinterpret_cast(data.get() + 0x28)); + x18_matSets.reserve(matSetCount); + const u8* dataCur = data.get() + ROUND_UP_32(0x2c + secCount * 4); + const u32* secSizeCur = reinterpret_cast(data.get() + 0x2c); + for (u32 i = 0; i < matSetCount; ++i) { + u32 matSetSz = hecl::SBig(*secSizeCur); + const u8* sec = MemoryFromPartData(dataCur, secSizeCur); + x18_matSets.emplace_back(i); + SShader& shader = x18_matSets.back(); + athena::io::MemoryReader r(sec, matSetSz); + shader.m_matSet.read(r); + CBooModel::MakeTexturesFromMats(shader.m_matSet, shader.x0_textures, *store); + } + + { + u32 hmdlSz = hecl::SBig(*secSizeCur); + const u8* hmdlMetadata = MemoryFromPartData(dataCur, secSizeCur); + athena::io::MemoryReader r(hmdlMetadata, hmdlSz); + m_hmdlMeta.read(r); + } + + const u8* vboData = MemoryFromPartData(dataCur, secSizeCur); + const u8* iboData = MemoryFromPartData(dataCur, secSizeCur); + const u8* surfInfo = MemoryFromPartData(dataCur, secSizeCur); + + for (SShader& matSet : x18_matSets) { + matSet.InitializeLayout(this); + matSet.BuildShaders(m_hmdlMeta); + } + + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + /* Index buffer is always static */ + if (m_hmdlMeta.indexCount) + m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, iboData, 4, m_hmdlMeta.indexCount); + + if (!m_hmdlMeta.bankCount) { + /* Non-skinned models use static vertex buffers shared with CBooModel instances */ + if (m_hmdlMeta.vertCount) + m_staticVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, vboData, m_hmdlMeta.vertStride, m_hmdlMeta.vertCount); + } else { + /* Skinned models use per-instance dynamic buffers for vertex manipulation effects */ + size_t vboSz = m_hmdlMeta.vertStride * m_hmdlMeta.vertCount; + if (vboSz) { + m_dynamicVertexData.reset(new uint8_t[vboSz]); + memmove(m_dynamicVertexData.get(), vboData, vboSz); + } } - { - u32 hmdlSz = hecl::SBig(*secSizeCur); - const u8* hmdlMetadata = MemoryFromPartData(dataCur, secSizeCur); - athena::io::MemoryReader r(hmdlMetadata, hmdlSz); - m_hmdlMeta.read(r); + return true; + } BooTrace); + + u32 surfCount = hecl::SBig(*reinterpret_cast(surfInfo)); + x8_surfaces.reserve(surfCount); + for (u32 i = 0; i < surfCount; ++i) { + u32 surfSz = hecl::SBig(*secSizeCur); + const u8* sec = MemoryFromPartData(dataCur, secSizeCur); + x8_surfaces.emplace_back(); + CBooSurface& surf = x8_surfaces.back(); + surf.selfIdx = i; + athena::io::MemoryReader r(sec, surfSz); + surf.m_data.read(r); + } + + const float* aabbPtr = reinterpret_cast(data.get() + 0xc); + m_aabb = zeus::CAABox(hecl::SBig(aabbPtr[0]), hecl::SBig(aabbPtr[1]), hecl::SBig(aabbPtr[2]), hecl::SBig(aabbPtr[3]), + hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5])); + x28_modelInst = MakeNewInstance(0, 1, nullptr, false); +} + +void SShader::UnlockTextures() { + for (TCachedToken& tex : x0_textures) + tex.Unlock(); +} + +void CBooModel::VerifyCurrentShader(int shaderIdx) { + if (shaderIdx != m_matSetIdx && m_model) + RemapMaterialData(m_model->x18_matSets[shaderIdx]); +} + +void CBooModel::Touch(int shaderIdx) const { + const_cast(this)->VerifyCurrentShader(shaderIdx); + TryLockTextures(); +} + +void CModel::DrawSortedParts(const CModelFlags& flags) const { + const_cast(*x28_modelInst).VerifyCurrentShader(flags.x1_matSetIdx); + x28_modelInst->DrawAlpha(flags, nullptr, nullptr); +} + +void CModel::DrawUnsortedParts(const CModelFlags& flags) const { + const_cast(*x28_modelInst).VerifyCurrentShader(flags.x1_matSetIdx); + x28_modelInst->DrawNormal(flags, nullptr, nullptr); +} + +void CModel::Draw(const CModelFlags& flags) const { + const_cast(*x28_modelInst).VerifyCurrentShader(flags.x1_matSetIdx); + x28_modelInst->Draw(flags, nullptr, nullptr); +} + +bool CModel::IsLoaded(int shaderIdx) const { + const_cast(*x28_modelInst).VerifyCurrentShader(shaderIdx); + std::vector>& texs = x28_modelInst->x1c_textures; + bool loaded = true; + for (TCachedToken& tex : texs) { + if (!tex.IsLoaded()) { + loaded = false; + break; } - - const u8* vboData = MemoryFromPartData(dataCur, secSizeCur); - const u8* iboData = MemoryFromPartData(dataCur, secSizeCur); - const u8* surfInfo = MemoryFromPartData(dataCur, secSizeCur); - - for (SShader& matSet : x18_matSets) - { - matSet.InitializeLayout(this); - matSet.BuildShaders(m_hmdlMeta); - } - - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - /* Index buffer is always static */ - if (m_hmdlMeta.indexCount) - m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, iboData, 4, m_hmdlMeta.indexCount); - - if (!m_hmdlMeta.bankCount) - { - /* Non-skinned models use static vertex buffers shared with CBooModel instances */ - if (m_hmdlMeta.vertCount) - m_staticVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, vboData, - m_hmdlMeta.vertStride, m_hmdlMeta.vertCount); - } - else - { - /* Skinned models use per-instance dynamic buffers for vertex manipulation effects */ - size_t vboSz = m_hmdlMeta.vertStride * m_hmdlMeta.vertCount; - if (vboSz) - { - m_dynamicVertexData.reset(new uint8_t[vboSz]); - memmove(m_dynamicVertexData.get(), vboData, vboSz); - } - } - - return true; - } BooTrace); - - u32 surfCount = hecl::SBig(*reinterpret_cast(surfInfo)); - x8_surfaces.reserve(surfCount); - for (u32 i=0 ; i(data.get() + 0xc); - m_aabb = zeus::CAABox(hecl::SBig(aabbPtr[0]), hecl::SBig(aabbPtr[1]), hecl::SBig(aabbPtr[2]), - hecl::SBig(aabbPtr[3]), hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5])); - x28_modelInst = MakeNewInstance(0, 1, nullptr, false); + } + return loaded; } -void SShader::UnlockTextures() -{ - for (TCachedToken& tex : x0_textures) - tex.Unlock(); +size_t CModel::GetPoolVertexOffset(size_t idx) const { return m_hmdlMeta.vertStride * idx; } + +zeus::CVector3f CModel::GetPoolVertex(size_t idx) const { + auto* floats = reinterpret_cast(m_dynamicVertexData.get() + GetPoolVertexOffset(idx)); + return {floats}; } -void CBooModel::VerifyCurrentShader(int shaderIdx) -{ - if (shaderIdx != m_matSetIdx && m_model) - RemapMaterialData(m_model->x18_matSets[shaderIdx]); -} +size_t CModel::GetPoolNormalOffset(size_t idx) const { return m_hmdlMeta.vertStride * idx + 12; } -void CBooModel::Touch(int shaderIdx) const -{ - const_cast(this)->VerifyCurrentShader(shaderIdx); - TryLockTextures(); -} - -void CModel::DrawSortedParts(const CModelFlags& flags) const -{ - const_cast(*x28_modelInst).VerifyCurrentShader(flags.x1_matSetIdx); - x28_modelInst->DrawAlpha(flags, nullptr, nullptr); -} - -void CModel::DrawUnsortedParts(const CModelFlags& flags) const -{ - const_cast(*x28_modelInst).VerifyCurrentShader(flags.x1_matSetIdx); - x28_modelInst->DrawNormal(flags, nullptr, nullptr); -} - -void CModel::Draw(const CModelFlags& flags) const -{ - const_cast(*x28_modelInst).VerifyCurrentShader(flags.x1_matSetIdx); - x28_modelInst->Draw(flags, nullptr, nullptr); -} - -bool CModel::IsLoaded(int shaderIdx) const -{ - const_cast(*x28_modelInst).VerifyCurrentShader(shaderIdx); - std::vector>& texs = x28_modelInst->x1c_textures; - bool loaded = true; - for (TCachedToken& tex : texs) - { - if (!tex.IsLoaded()) - { - loaded = false; - break; - } - } - return loaded; -} - -size_t CModel::GetPoolVertexOffset(size_t idx) const -{ - return m_hmdlMeta.vertStride * idx; -} - -zeus::CVector3f CModel::GetPoolVertex(size_t idx) const -{ - auto* floats = reinterpret_cast(m_dynamicVertexData.get() + GetPoolVertexOffset(idx)); - return {floats}; -} - -size_t CModel::GetPoolNormalOffset(size_t idx) const -{ - return m_hmdlMeta.vertStride * idx + 12; -} - -zeus::CVector3f CModel::GetPoolNormal(size_t idx) const -{ - auto* floats = reinterpret_cast(m_dynamicVertexData.get() + GetPoolNormalOffset(idx)); - return {floats}; +zeus::CVector3f CModel::GetPoolNormal(size_t idx) const { + auto* floats = reinterpret_cast(m_dynamicVertexData.get() + GetPoolNormalOffset(idx)); + return {floats}; } void CModel::ApplyVerticesCPU(const boo::ObjToken& vertBuf, - const std::vector>& vn) const -{ - u8* data = reinterpret_cast(vertBuf->map(m_hmdlMeta.vertStride * m_hmdlMeta.vertCount)); - for (u32 i=0 ; i& avn = vn[i]; - float* floats = reinterpret_cast(data + GetPoolVertexOffset(i)); - floats[0] = avn.first.x(); - floats[1] = avn.first.y(); - floats[2] = avn.first.z(); - floats[3] = avn.second.x(); - floats[4] = avn.second.y(); - floats[5] = avn.second.z(); - } - vertBuf->unmap(); + const std::vector>& vn) const { + u8* data = reinterpret_cast(vertBuf->map(m_hmdlMeta.vertStride * m_hmdlMeta.vertCount)); + for (u32 i = 0; i < std::min(u32(vn.size()), m_hmdlMeta.vertCount); ++i) { + const std::pair& avn = vn[i]; + float* floats = reinterpret_cast(data + GetPoolVertexOffset(i)); + floats[0] = avn.first.x(); + floats[1] = avn.first.y(); + floats[2] = avn.first.z(); + floats[3] = avn.second.x(); + floats[4] = avn.second.y(); + floats[5] = avn.second.z(); + } + vertBuf->unmap(); } -void CModel::RestoreVerticesCPU(const boo::ObjToken& vertBuf) const -{ - size_t size = m_hmdlMeta.vertStride * m_hmdlMeta.vertCount; - u8* data = reinterpret_cast(vertBuf->map(size)); - memcpy(data, m_dynamicVertexData.get(), size); - vertBuf->unmap(); +void CModel::RestoreVerticesCPU(const boo::ObjToken& vertBuf) const { + size_t size = m_hmdlMeta.vertStride * m_hmdlMeta.vertCount; + u8* data = reinterpret_cast(vertBuf->map(size)); + memcpy(data, m_dynamicVertexData.get(), size); + vertBuf->unmap(); } -void CModel::_WarmupShaders() -{ - CBooModel::SetDummyTextures(true); - CBooModel::EnableShadowMaps(g_Renderer->x220_sphereRamp.get(), zeus::CTransform::Identity()); - CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState(); - zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix; - zeus::CTransform backupModel = CGraphics::g_GXModelMatrix; - CGraphics::SetModelMatrix(zeus::CTransform::Translate(-m_aabb.center())); - CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -2048.f, 0.f)); - CGraphics::SetOrtho(-2048.f, 2048.f, 2048.f, -2048.f, 0.f, 4096.f); - CModelFlags defaultFlags; - for (SShader& shader : x18_matSets) - { - GetInstance().RemapMaterialData(shader); - GetInstance().UpdateUniformData(defaultFlags, nullptr, nullptr); - GetInstance().WarmupDrawSurfaces(); - } - CGraphics::SetProjectionState(backupProj); - CGraphics::SetViewPointMatrix(backupViewPoint); - CGraphics::SetModelMatrix(backupModel); - CBooModel::DisableShadowMaps(); - CBooModel::SetDummyTextures(false); +void CModel::_WarmupShaders() { + CBooModel::SetDummyTextures(true); + CBooModel::EnableShadowMaps(g_Renderer->x220_sphereRamp.get(), zeus::CTransform::Identity()); + CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState(); + zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix; + zeus::CTransform backupModel = CGraphics::g_GXModelMatrix; + CGraphics::SetModelMatrix(zeus::CTransform::Translate(-m_aabb.center())); + CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -2048.f, 0.f)); + CGraphics::SetOrtho(-2048.f, 2048.f, 2048.f, -2048.f, 0.f, 4096.f); + CModelFlags defaultFlags; + for (SShader& shader : x18_matSets) { + GetInstance().RemapMaterialData(shader); + GetInstance().UpdateUniformData(defaultFlags, nullptr, nullptr); + GetInstance().WarmupDrawSurfaces(); + } + CGraphics::SetProjectionState(backupProj); + CGraphics::SetViewPointMatrix(backupViewPoint); + CGraphics::SetModelMatrix(backupModel); + CBooModel::DisableShadowMaps(); + CBooModel::SetDummyTextures(false); } -void CModel::WarmupShaders(const SObjectTag& cmdlTag) -{ - TToken model = g_SimplePool->GetObj(cmdlTag); - CModel* modelObj = model.GetObj(); - modelObj->_WarmupShaders(); +void CModel::WarmupShaders(const SObjectTag& cmdlTag) { + TToken model = g_SimplePool->GetObj(cmdlTag); + CModel* modelObj = model.GetObj(); + modelObj->_WarmupShaders(); } -CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag, - std::unique_ptr&& in, u32 len, - const urde::CVParamTransfer& vparms, - CObjectReference* selfRef) -{ - CSimplePool* sp = vparms.GetOwnedObj(); - CFactoryFnReturn ret = TToken::GetIObjObjectFor(std::make_unique(std::move(in), len, sp, selfRef)); - return ret; +CFactoryFnReturn FModelFactory(const urde::SObjectTag& tag, std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms, CObjectReference* selfRef) { + CSimplePool* sp = vparms.GetOwnedObj(); + CFactoryFnReturn ret = TToken::GetIObjObjectFor(std::make_unique(std::move(in), len, sp, selfRef)); + return ret; } -} +} // namespace urde diff --git a/Runtime/Graphics/CMoviePlayer.cpp b/Runtime/Graphics/CMoviePlayer.cpp index 071112f00..f97cd548c 100644 --- a/Runtime/Graphics/CMoviePlayer.cpp +++ b/Runtime/Graphics/CMoviePlayer.cpp @@ -8,30 +8,21 @@ #include "hecl/Pipeline.hpp" #include -namespace urde -{ +namespace urde { /* used in the original to look up fixed-point dividends on a * MIDI-style volume scale (0-127) -> (n/0x8000) */ -static const u16 StaticVolumeLookup[] = -{ - 0x0000, 0x0002, 0x0008, 0x0012, 0x0020, 0x0032, 0x0049, 0x0063, - 0x0082, 0x00A4, 0x00CB, 0x00F5, 0x0124, 0x0157, 0x018E, 0x01C9, - 0x0208, 0x024B, 0x0292, 0x02DD, 0x032C, 0x037F, 0x03D7, 0x0432, - 0x0492, 0x04F5, 0x055D, 0x05C9, 0x0638, 0x06AC, 0x0724, 0x07A0, - 0x0820, 0x08A4, 0x092C, 0x09B8, 0x0A48, 0x0ADD, 0x0B75, 0x0C12, - 0x0CB2, 0x0D57, 0x0DFF, 0x0EAC, 0x0F5D, 0x1012, 0x10CA, 0x1187, - 0x1248, 0x130D, 0x13D7, 0x14A4, 0x1575, 0x164A, 0x1724, 0x1801, - 0x18E3, 0x19C8, 0x1AB2, 0x1BA0, 0x1C91, 0x1D87, 0x1E81, 0x1F7F, - 0x2081, 0x2187, 0x2291, 0x239F, 0x24B2, 0x25C8, 0x26E2, 0x2801, - 0x2923, 0x2A4A, 0x2B75, 0x2CA3, 0x2DD6, 0x2F0D, 0x3048, 0x3187, - 0x32CA, 0x3411, 0x355C, 0x36AB, 0x37FF, 0x3956, 0x3AB1, 0x3C11, - 0x3D74, 0x3EDC, 0x4048, 0x41B7, 0x432B, 0x44A3, 0x461F, 0x479F, - 0x4923, 0x4AAB, 0x4C37, 0x4DC7, 0x4F5C, 0x50F4, 0x5290, 0x5431, - 0x55D6, 0x577E, 0x592B, 0x5ADC, 0x5C90, 0x5E49, 0x6006, 0x61C7, - 0x638C, 0x6555, 0x6722, 0x68F4, 0x6AC9, 0x6CA2, 0x6E80, 0x7061, - 0x7247, 0x7430, 0x761E, 0x7810, 0x7A06, 0x7C00, 0x7DFE, 0x8000 -}; +static const u16 StaticVolumeLookup[] = { + 0x0000, 0x0002, 0x0008, 0x0012, 0x0020, 0x0032, 0x0049, 0x0063, 0x0082, 0x00A4, 0x00CB, 0x00F5, 0x0124, + 0x0157, 0x018E, 0x01C9, 0x0208, 0x024B, 0x0292, 0x02DD, 0x032C, 0x037F, 0x03D7, 0x0432, 0x0492, 0x04F5, + 0x055D, 0x05C9, 0x0638, 0x06AC, 0x0724, 0x07A0, 0x0820, 0x08A4, 0x092C, 0x09B8, 0x0A48, 0x0ADD, 0x0B75, + 0x0C12, 0x0CB2, 0x0D57, 0x0DFF, 0x0EAC, 0x0F5D, 0x1012, 0x10CA, 0x1187, 0x1248, 0x130D, 0x13D7, 0x14A4, + 0x1575, 0x164A, 0x1724, 0x1801, 0x18E3, 0x19C8, 0x1AB2, 0x1BA0, 0x1C91, 0x1D87, 0x1E81, 0x1F7F, 0x2081, + 0x2187, 0x2291, 0x239F, 0x24B2, 0x25C8, 0x26E2, 0x2801, 0x2923, 0x2A4A, 0x2B75, 0x2CA3, 0x2DD6, 0x2F0D, + 0x3048, 0x3187, 0x32CA, 0x3411, 0x355C, 0x36AB, 0x37FF, 0x3956, 0x3AB1, 0x3C11, 0x3D74, 0x3EDC, 0x4048, + 0x41B7, 0x432B, 0x44A3, 0x461F, 0x479F, 0x4923, 0x4AAB, 0x4C37, 0x4DC7, 0x4F5C, 0x50F4, 0x5290, 0x5431, + 0x55D6, 0x577E, 0x592B, 0x5ADC, 0x5C90, 0x5E49, 0x6006, 0x61C7, 0x638C, 0x6555, 0x6722, 0x68F4, 0x6AC9, + 0x6CA2, 0x6E80, 0x7061, 0x7247, 0x7430, 0x761E, 0x7810, 0x7A06, 0x7C00, 0x7DFE, 0x8000}; /* shared boo resources */ static boo::ObjToken YUVShaderPipeline; @@ -53,671 +44,567 @@ static float SfxVolume = 1.f; static const char* BlockNames[] = {"SpecterViewBlock"}; static const char* TexNames[] = {"texY", "texU", "texV"}; -void CMoviePlayer::Initialize() -{ - YUVShaderPipeline = hecl::conv->convert(Shader_CMoviePlayerShader{}); - TjHandle = tjInitDecompress(); +void CMoviePlayer::Initialize() { + YUVShaderPipeline = hecl::conv->convert(Shader_CMoviePlayerShader{}); + TjHandle = tjInitDecompress(); } -void CMoviePlayer::Shutdown() -{ - YUVShaderPipeline.reset(); - tjDestroy(TjHandle); +void CMoviePlayer::Shutdown() { + YUVShaderPipeline.reset(); + tjDestroy(TjHandle); } -void CMoviePlayer::THPHeader::swapBig() -{ - magic = hecl::SBig(magic); - version = hecl::SBig(version); - maxBufferSize = hecl::SBig(maxBufferSize); - maxAudioSamples = hecl::SBig(maxAudioSamples); - fps = hecl::SBig(fps); - numFrames = hecl::SBig(numFrames); - firstFrameSize = hecl::SBig(firstFrameSize); - dataSize = hecl::SBig(dataSize); - componentDataOffset = hecl::SBig(componentDataOffset); - offsetsDataOffset = hecl::SBig(offsetsDataOffset); - firstFrameOffset = hecl::SBig(firstFrameOffset); - lastFrameOffset = hecl::SBig(lastFrameOffset); +void CMoviePlayer::THPHeader::swapBig() { + magic = hecl::SBig(magic); + version = hecl::SBig(version); + maxBufferSize = hecl::SBig(maxBufferSize); + maxAudioSamples = hecl::SBig(maxAudioSamples); + fps = hecl::SBig(fps); + numFrames = hecl::SBig(numFrames); + firstFrameSize = hecl::SBig(firstFrameSize); + dataSize = hecl::SBig(dataSize); + componentDataOffset = hecl::SBig(componentDataOffset); + offsetsDataOffset = hecl::SBig(offsetsDataOffset); + firstFrameOffset = hecl::SBig(firstFrameOffset); + lastFrameOffset = hecl::SBig(lastFrameOffset); } -void CMoviePlayer::THPComponents::swapBig() -{ - numComponents = hecl::SBig(numComponents); +void CMoviePlayer::THPComponents::swapBig() { numComponents = hecl::SBig(numComponents); } + +void CMoviePlayer::THPVideoInfo::swapBig() { + width = hecl::SBig(width); + height = hecl::SBig(height); } -void CMoviePlayer::THPVideoInfo::swapBig() -{ - width = hecl::SBig(width); - height = hecl::SBig(height); +void CMoviePlayer::THPAudioInfo::swapBig() { + numChannels = hecl::SBig(numChannels); + sampleRate = hecl::SBig(sampleRate); + numSamples = hecl::SBig(numSamples); } -void CMoviePlayer::THPAudioInfo::swapBig() -{ - numChannels = hecl::SBig(numChannels); - sampleRate = hecl::SBig(sampleRate); - numSamples = hecl::SBig(numSamples); +void CMoviePlayer::THPFrameHeader::swapBig() { + nextSize = hecl::SBig(nextSize); + prevSize = hecl::SBig(prevSize); + imageSize = hecl::SBig(imageSize); + audioSize = hecl::SBig(audioSize); } -void CMoviePlayer::THPFrameHeader::swapBig() -{ - nextSize = hecl::SBig(nextSize); - prevSize = hecl::SBig(prevSize); - imageSize = hecl::SBig(imageSize); - audioSize = hecl::SBig(audioSize); -} - -void CMoviePlayer::THPAudioFrameHeader::swapBig() -{ - channelSize = hecl::SBig(channelSize); - numSamples = hecl::SBig(numSamples); - for (int i=0 ; i<2 ; ++i) - { - for (int j=0 ; j<8 ; ++j) - { - channelCoefs[i][j][0] = hecl::SBig(channelCoefs[i][j][0]); - channelCoefs[i][j][1] = hecl::SBig(channelCoefs[i][j][1]); - } - channelPrevs[i][0] = hecl::SBig(channelPrevs[i][0]); - channelPrevs[i][1] = hecl::SBig(channelPrevs[i][1]); +void CMoviePlayer::THPAudioFrameHeader::swapBig() { + channelSize = hecl::SBig(channelSize); + numSamples = hecl::SBig(numSamples); + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 8; ++j) { + channelCoefs[i][j][0] = hecl::SBig(channelCoefs[i][j][0]); + channelCoefs[i][j][1] = hecl::SBig(channelCoefs[i][j][1]); } + channelPrevs[i][0] = hecl::SBig(channelPrevs[i][0]); + channelPrevs[i][1] = hecl::SBig(channelPrevs[i][1]); + } } /* Slightly modified from THPAudioDecode present in SDK; always interleaves */ -u32 CMoviePlayer::THPAudioDecode(s16* buffer, const u8* audioFrame, bool stereo) -{ - THPAudioFrameHeader header = *((const THPAudioFrameHeader*)audioFrame); - header.swapBig(); - audioFrame += sizeof(THPAudioFrameHeader); +u32 CMoviePlayer::THPAudioDecode(s16* buffer, const u8* audioFrame, bool stereo) { + THPAudioFrameHeader header = *((const THPAudioFrameHeader*)audioFrame); + header.swapBig(); + audioFrame += sizeof(THPAudioFrameHeader); - if (stereo) - { - for (int i=0 ; i<2 ; ++i) - { - unsigned samples = header.numSamples; - s16* bufferCur = buffer+i; - int16_t prev1 = header.channelPrevs[i][0]; - int16_t prev2 = header.channelPrevs[i][1]; - for (int f=0 ; f<(header.numSamples + 13) / 14 ; ++f) - { - DSPDecompressFrameStereoStride(bufferCur, audioFrame, - header.channelCoefs[i], &prev1, &prev2, samples); - samples -= 14; - bufferCur += 28; - audioFrame += 8; - } - } + if (stereo) { + for (int i = 0; i < 2; ++i) { + unsigned samples = header.numSamples; + s16* bufferCur = buffer + i; + int16_t prev1 = header.channelPrevs[i][0]; + int16_t prev2 = header.channelPrevs[i][1]; + for (int f = 0; f < (header.numSamples + 13) / 14; ++f) { + DSPDecompressFrameStereoStride(bufferCur, audioFrame, header.channelCoefs[i], &prev1, &prev2, samples); + samples -= 14; + bufferCur += 28; + audioFrame += 8; + } } - else - { - unsigned samples = header.numSamples; - s16* bufferCur = buffer; - int16_t prev1 = header.channelPrevs[0][0]; - int16_t prev2 = header.channelPrevs[0][1]; - for (int f=0 ; f<(header.numSamples + 13) / 14 ; ++f) - { - DSPDecompressFrameStereoDupe(bufferCur, audioFrame, - header.channelCoefs[0], &prev1, &prev2, samples); - samples -= 14; - bufferCur += 28; - audioFrame += 8; - } + } else { + unsigned samples = header.numSamples; + s16* bufferCur = buffer; + int16_t prev1 = header.channelPrevs[0][0]; + int16_t prev2 = header.channelPrevs[0][1]; + for (int f = 0; f < (header.numSamples + 13) / 14; ++f) { + DSPDecompressFrameStereoDupe(bufferCur, audioFrame, header.channelCoefs[0], &prev1, &prev2, samples); + samples -= 14; + bufferCur += 28; + audioFrame += 8; } + } - return header.numSamples; + return header.numSamples; } CMoviePlayer::CMoviePlayer(const char* path, float preLoadSeconds, bool loop, bool deinterlace) -: CDvdFile(path), xec_preLoadSeconds(preLoadSeconds) -{ - xf4_24_loop = loop; - m_deinterlace = deinterlace; +: CDvdFile(path), xec_preLoadSeconds(preLoadSeconds) { + xf4_24_loop = loop; + m_deinterlace = deinterlace; - /* Read THP header information */ - u8 buf[64]; - SyncRead(buf, 64); - memmove(&x28_thpHead, buf, 48); - x28_thpHead.swapBig(); + /* Read THP header information */ + u8 buf[64]; + SyncRead(buf, 64); + memmove(&x28_thpHead, buf, 48); + x28_thpHead.swapBig(); - u32 cur = x28_thpHead.componentDataOffset; - SyncSeekRead(buf, 32, ESeekOrigin::Begin, cur); - memmove(&x58_thpComponents, buf, 20); - cur += 20; - x58_thpComponents.swapBig(); + u32 cur = x28_thpHead.componentDataOffset; + SyncSeekRead(buf, 32, ESeekOrigin::Begin, cur); + memmove(&x58_thpComponents, buf, 20); + cur += 20; + x58_thpComponents.swapBig(); - for (int i=0 ; i 0.f) - { - /* Pre-load video portion */ - u32 frame = xec_preLoadSeconds * x28_thpHead.fps; - xf0_preLoadFrames = std::min(frame, x28_thpHead.numFrames); - xec_preLoadSeconds = std::min(xe4_totalSeconds, xec_preLoadSeconds); - } + xe4_totalSeconds = x28_thpHead.numFrames / x28_thpHead.fps; + if (xec_preLoadSeconds < 0.f) { + /* Load whole video */ + xec_preLoadSeconds = xe4_totalSeconds; + xf0_preLoadFrames = x28_thpHead.numFrames; + } else if (xec_preLoadSeconds > 0.f) { + /* Pre-load video portion */ + u32 frame = xec_preLoadSeconds * x28_thpHead.fps; + xf0_preLoadFrames = std::min(frame, x28_thpHead.numFrames); + xec_preLoadSeconds = std::min(xe4_totalSeconds, xec_preLoadSeconds); + } - if (xf0_preLoadFrames > 0) - xa0_bufferQueue.reserve(xf0_preLoadFrames); + if (xf0_preLoadFrames > 0) + xa0_bufferQueue.reserve(xf0_preLoadFrames); - /* All set for GPU resources */ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_blockBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(m_viewVertBlock), 1); - m_vertBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(specter::View::TexShaderVert), 4); + /* All set for GPU resources */ + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_blockBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(m_viewVertBlock), 1); + m_vertBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(specter::View::TexShaderVert), 4); - /* Allocate textures here (rather than at decode time) */ - x80_textures.reserve(3); - for (int i=0 ; i<3 ; ++i) - { - x80_textures.emplace_back(); - CTHPTextureSet& set = x80_textures.back(); - if (deinterlace) - { - /* urde addition: this way interlaced THPs don't look horrible */ - set.Y[0] = ctx.newDynamicTexture(x6c_videoInfo.width, x6c_videoInfo.height / 2, - boo::TextureFormat::I8, boo::TextureClampMode::Repeat); - set.Y[1] = ctx.newDynamicTexture(x6c_videoInfo.width, x6c_videoInfo.height / 2, - boo::TextureFormat::I8, boo::TextureClampMode::Repeat); - set.U = ctx.newDynamicTexture(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, - boo::TextureFormat::I8, boo::TextureClampMode::Repeat); - set.V = ctx.newDynamicTexture(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, - boo::TextureFormat::I8, boo::TextureClampMode::Repeat); + /* Allocate textures here (rather than at decode time) */ + x80_textures.reserve(3); + for (int i = 0; i < 3; ++i) { + x80_textures.emplace_back(); + CTHPTextureSet& set = x80_textures.back(); + if (deinterlace) { + /* urde addition: this way interlaced THPs don't look horrible */ + set.Y[0] = ctx.newDynamicTexture(x6c_videoInfo.width, x6c_videoInfo.height / 2, boo::TextureFormat::I8, + boo::TextureClampMode::Repeat); + set.Y[1] = ctx.newDynamicTexture(x6c_videoInfo.width, x6c_videoInfo.height / 2, boo::TextureFormat::I8, + boo::TextureClampMode::Repeat); + set.U = ctx.newDynamicTexture(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, boo::TextureFormat::I8, + boo::TextureClampMode::Repeat); + set.V = ctx.newDynamicTexture(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, boo::TextureFormat::I8, + boo::TextureClampMode::Repeat); - boo::ObjToken bufs[] = {m_blockBuf.get()}; - for (int j=0 ; j<2 ; ++j) - { - boo::ObjToken texs[] = {set.Y[j].get(), set.U.get(), set.V.get()}; - set.binding[j] = ctx.newShaderDataBinding(YUVShaderPipeline, m_vertBuf.get(), - nullptr, nullptr, 1, bufs, nullptr, - 3, texs, nullptr, nullptr); - } - } - else - { - /* normal progressive presentation */ - set.Y[0] = ctx.newDynamicTexture(x6c_videoInfo.width, x6c_videoInfo.height, - boo::TextureFormat::I8, boo::TextureClampMode::Repeat); - set.U = ctx.newDynamicTexture(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, - boo::TextureFormat::I8, boo::TextureClampMode::Repeat); - set.V = ctx.newDynamicTexture(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, - boo::TextureFormat::I8, boo::TextureClampMode::Repeat); - - boo::ObjToken bufs[] = {m_blockBuf.get()}; - boo::ObjToken texs[] = {set.Y[0].get(), set.U.get(), set.V.get()}; - set.binding[0] = ctx.newShaderDataBinding(YUVShaderPipeline, m_vertBuf.get(), - nullptr, nullptr, 1, bufs, nullptr, - 3, texs, nullptr, nullptr); - } - if (xf4_25_hasAudio) - set.audioBuf.reset(new s16[x28_thpHead.maxAudioSamples * 2]); + boo::ObjToken bufs[] = {m_blockBuf.get()}; + for (int j = 0; j < 2; ++j) { + boo::ObjToken texs[] = {set.Y[j].get(), set.U.get(), set.V.get()}; + set.binding[j] = ctx.newShaderDataBinding(YUVShaderPipeline, m_vertBuf.get(), nullptr, nullptr, 1, bufs, + nullptr, 3, texs, nullptr, nullptr); } - return true; - } BooTrace); + } else { + /* normal progressive presentation */ + set.Y[0] = ctx.newDynamicTexture(x6c_videoInfo.width, x6c_videoInfo.height, boo::TextureFormat::I8, + boo::TextureClampMode::Repeat); + set.U = ctx.newDynamicTexture(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, boo::TextureFormat::I8, + boo::TextureClampMode::Repeat); + set.V = ctx.newDynamicTexture(x6c_videoInfo.width / 2, x6c_videoInfo.height / 2, boo::TextureFormat::I8, + boo::TextureClampMode::Repeat); - /* Temporary planar YUV decode buffer, resulting planes copied to Boo */ - m_yuvBuf.reset(new uint8_t[tjBufSizeYUV(x6c_videoInfo.width, x6c_videoInfo.height, TJ_420)]); - - /* Schedule initial read */ - PostDVDReadRequestIfNeeded(); - - m_frame[0].m_uv = {0.f, 0.f}; - m_frame[1].m_uv = {0.f, 1.f}; - m_frame[2].m_uv = {1.f, 0.f}; - m_frame[3].m_uv = {1.f, 1.f}; - SetFrame({-0.5f, 0.5f, 0.f}, {-0.5f, -0.5f, 0.f}, {0.5f, -0.5f, 0.f}, {0.5f, 0.5f, 0.f}); - - m_viewVertBlock.finalAssign(m_viewVertBlock); - m_blockBuf->load(&m_viewVertBlock, sizeof(m_viewVertBlock)); -} - -void CMoviePlayer::SetStaticAudioVolume(int vol) -{ - StaticVolumeAtten = StaticVolumeLookup[std::max(0, std::min(127, vol))]; -} - -void CMoviePlayer::SetStaticAudio(const void* data, u32 size, u32 loopBegin, u32 loopEnd) -{ - StaticAudio = reinterpret_cast(data); - StaticAudioSize = size; - StaticLoopBegin = loopBegin; - StaticLoopEnd = loopEnd; - StaticAudioOffset = 0; - - g72x_init_state(&StaticStateLeft); - g72x_init_state(&StaticStateRight); -} - -void CMoviePlayer::SetSfxVolume(u8 volume) -{ - SfxVolume = std::min(volume, u8(127)) / 127.f; -} - -void CMoviePlayer::MixAudio(s16* out, const s16* in, u32 samples) -{ - /* No audio frames ready */ - if (xd4_audioSlot == -1) - { - if (in) - memmove(out, in, samples * 4); - else - memset(out, 0, samples * 4); - return; + boo::ObjToken bufs[] = {m_blockBuf.get()}; + boo::ObjToken texs[] = {set.Y[0].get(), set.U.get(), set.V.get()}; + set.binding[0] = ctx.newShaderDataBinding(YUVShaderPipeline, m_vertBuf.get(), nullptr, nullptr, 1, bufs, + nullptr, 3, texs, nullptr, nullptr); + } + if (xf4_25_hasAudio) + set.audioBuf.reset(new s16[x28_thpHead.maxAudioSamples * 2]); } + return true; + } BooTrace); - while (samples) - { - CTHPTextureSet* tex = &x80_textures[xd4_audioSlot]; - u32 thisSamples = std::min(tex->audioSamples - tex->playedSamples, samples); - if (!thisSamples) - { - /* Advance frame */ - ++xd4_audioSlot; - if (xd4_audioSlot >= x80_textures.size()) - xd4_audioSlot = 0; - tex = &x80_textures[xd4_audioSlot]; - thisSamples = std::min(tex->audioSamples - tex->playedSamples, samples); - } + /* Temporary planar YUV decode buffer, resulting planes copied to Boo */ + m_yuvBuf.reset(new uint8_t[tjBufSizeYUV(x6c_videoInfo.width, x6c_videoInfo.height, TJ_420)]); - if (thisSamples) - { - /* mix samples with `in` or no mix */ - if (in) - { - for (u32 i=0 ; iaudioBuf[(i+tex->playedSamples)*2]) * 0x50F4 / 0x8000 * SfxVolume); - out[1] = DSPSampClamp(in[1] + - s32(tex->audioBuf[(i+tex->playedSamples)*2+1]) * 0x50F4 / 0x8000 * SfxVolume); - } - } - else - { - for (u32 i=0 ; iaudioBuf[(i+tex->playedSamples)*2]) * 0x50F4 / 0x8000 * SfxVolume); - out[1] = DSPSampClamp( - s32(tex->audioBuf[(i+tex->playedSamples)*2+1]) * 0x50F4 / 0x8000 * SfxVolume); - } - } - tex->playedSamples += thisSamples; - samples -= thisSamples; - } - else - { - /* urde addition: failsafe for buffer overrun */ - if (in) - memmove(out, in, samples * 4); - else - memset(out, 0, samples * 4); - //fprintf(stderr, "dropped %d samples\n", samples); - return; - } - } + /* Schedule initial read */ + PostDVDReadRequestIfNeeded(); + + m_frame[0].m_uv = {0.f, 0.f}; + m_frame[1].m_uv = {0.f, 1.f}; + m_frame[2].m_uv = {1.f, 0.f}; + m_frame[3].m_uv = {1.f, 1.f}; + SetFrame({-0.5f, 0.5f, 0.f}, {-0.5f, -0.5f, 0.f}, {0.5f, -0.5f, 0.f}, {0.5f, 0.5f, 0.f}); + + m_viewVertBlock.finalAssign(m_viewVertBlock); + m_blockBuf->load(&m_viewVertBlock, sizeof(m_viewVertBlock)); } -void CMoviePlayer::MixStaticAudio(s16* out, const s16* in, u32 samples) -{ - if (!StaticAudio) - return; - while (samples) - { - u32 thisSamples = std::min(StaticLoopEnd - StaticAudioOffset, samples); - const u8* thisOffsetLeft = &StaticAudio[StaticAudioOffset/2]; - const u8* thisOffsetRight = &StaticAudio[StaticAudioSize/2 + StaticAudioOffset/2]; - - /* urde addition: mix samples with `in` or no mix */ - if (in) - { - for (u32 i=0 ; i> 4 & 0xf, &StaticStateLeft) * StaticVolumeAtten / 0x8000)); - out[3] = DSPSampClamp(in[3] + - s32(g721_decoder(thisOffsetRight[0] >> 4 & 0xf, &StaticStateRight) * StaticVolumeAtten / 0x8000)); - thisOffsetLeft += 1; - thisOffsetRight += 1; - out += 4; - in += 4; - } - } - else - { - for (u32 i=0 ; i> 4 & 0xf, &StaticStateLeft) * StaticVolumeAtten / 0x8000)); - out[3] = DSPSampClamp( - s32(g721_decoder(thisOffsetRight[0] >> 4 & 0xf, &StaticStateRight) * StaticVolumeAtten / 0x8000)); - thisOffsetLeft += 1; - thisOffsetRight += 1; - out += 4; - } - } - - StaticAudioOffset += thisSamples; - if (StaticAudioOffset == StaticLoopEnd) - StaticAudioOffset = StaticLoopBegin; - samples -= thisSamples; - } +void CMoviePlayer::SetStaticAudioVolume(int vol) { + StaticVolumeAtten = StaticVolumeLookup[std::max(0, std::min(127, vol))]; } -void CMoviePlayer::Rewind() -{ - if (x98_request) - { - x98_request->PostCancelRequest(); - x98_request.reset(); - } +void CMoviePlayer::SetStaticAudio(const void* data, u32 size, u32 loopBegin, u32 loopEnd) { + StaticAudio = reinterpret_cast(data); + StaticAudioSize = size; + StaticLoopBegin = loopBegin; + StaticLoopEnd = loopEnd; + StaticAudioOffset = 0; - xb0_nextReadSize = x28_thpHead.firstFrameSize; - xb4_nextReadOff = x28_thpHead.firstFrameOffset; - xb8_readSizeWrapped = x28_thpHead.firstFrameSize; - xbc_readOffWrapped = x28_thpHead.firstFrameOffset; - - xc0_curLoadFrame = 0; - xc4_requestFrameWrapped = 0; - xc8_curFrame = 0; - xcc_decodedTexSlot = 0; - xd0_drawTexSlot = -1; - xd4_audioSlot = -1; - xd8_decodedTexCount = 0; - xdc_frameRem = 0.f; - xe8_curSeconds = 0.f; + g72x_init_state(&StaticStateLeft); + g72x_init_state(&StaticStateRight); } -void CMoviePlayer::SetFrame(const zeus::CVector3f& a, const zeus::CVector3f& b, - const zeus::CVector3f& c, const zeus::CVector3f& d) -{ - m_frame[0].m_pos = a; - m_frame[1].m_pos = b; - m_frame[2].m_pos = d; - m_frame[3].m_pos = c; - m_vertBuf->load(m_frame, sizeof(m_frame)); -} +void CMoviePlayer::SetSfxVolume(u8 volume) { SfxVolume = std::min(volume, u8(127)) / 127.f; } -void CMoviePlayer::DrawFrame() -{ - if (xd0_drawTexSlot == -1) - return; - - /* draw appropriate field */ - CTHPTextureSet& tex = x80_textures[xd0_drawTexSlot]; - CGraphics::SetShaderDataBinding - (tex.binding[m_deinterlace ? (xfc_fieldIndex != 0) : 0]); - CGraphics::DrawArray(0, 4); - - /* ensure second field is being displayed by VI to signal advance - * (faked in urde with continuous xor) */ - if (!xfc_fieldIndex && CGraphics::g_LastFrameUsedAbove) - xf4_26_fieldFlip = true; - - ++xfc_fieldIndex; -} - -void CMoviePlayer::Update(float dt) -{ - if (xc0_curLoadFrame < xf0_preLoadFrames) - { - /* in buffering phase, ensure read data is stored for mem-cache access */ - if (x98_request && x98_request->IsComplete()) - { - ReadCompleted(); - if (xc0_curLoadFrame >= xa0_bufferQueue.size() && - xc0_curLoadFrame < xf0_preLoadFrames && - xa0_bufferQueue.size() < x28_thpHead.numFrames) - { - PostDVDReadRequestIfNeeded(); - } - } - } +void CMoviePlayer::MixAudio(s16* out, const s16* in, u32 samples) { + /* No audio frames ready */ + if (xd4_audioSlot == -1) { + if (in) + memmove(out, in, samples * 4); else - { - /* out of buffering phase, skip mem-cache straight to decode */ - if (x98_request) - { - bool flag = false; - if (xc4_requestFrameWrapped >= xa0_bufferQueue.size() && - xc0_curLoadFrame >= xa0_bufferQueue.size()) - flag = true; - if (x98_request->IsComplete() && xd8_decodedTexCount < 2 && flag) - { - DecodeFromRead(x90_requestBuf.get()); - ReadCompleted(); - PostDVDReadRequestIfNeeded(); - ++xd8_decodedTexCount; - ++xc4_requestFrameWrapped; - if (xc4_requestFrameWrapped >= x28_thpHead.numFrames && xf4_24_loop) - xc4_requestFrameWrapped = 0; - } - } + memset(out, 0, samples * 4); + return; + } + + while (samples) { + CTHPTextureSet* tex = &x80_textures[xd4_audioSlot]; + u32 thisSamples = std::min(tex->audioSamples - tex->playedSamples, samples); + if (!thisSamples) { + /* Advance frame */ + ++xd4_audioSlot; + if (xd4_audioSlot >= x80_textures.size()) + xd4_audioSlot = 0; + tex = &x80_textures[xd4_audioSlot]; + thisSamples = std::min(tex->audioSamples - tex->playedSamples, samples); } - /* submit request for additional read to keep stream-consumer happy - * (if buffer slot is available) */ - if (!x98_request && xe0_playMode == EPlayMode::Playing && - xa0_bufferQueue.size() < x28_thpHead.numFrames) - { - PostDVDReadRequestIfNeeded(); - } - - /* decode frame directly from mem-cache if needed */ - if (xd8_decodedTexCount < 2) - { - if (xe0_playMode == EPlayMode::Playing && xc4_requestFrameWrapped < xf0_preLoadFrames) - { - u32 minFrame = std::min(u32(xa0_bufferQueue.size()) - 1, xc4_requestFrameWrapped); - if (minFrame == -1) - return; - std::unique_ptr& frameData = xa0_bufferQueue[minFrame]; - DecodeFromRead(frameData.get()); - ++xd8_decodedTexCount; - ++xc4_requestFrameWrapped; - if (xc4_requestFrameWrapped >= x28_thpHead.numFrames && xf4_24_loop) - xc4_requestFrameWrapped = 0; + if (thisSamples) { + /* mix samples with `in` or no mix */ + if (in) { + for (u32 i = 0; i < thisSamples; ++i, out += 2, in += 2) { + out[0] = DSPSampClamp(in[0] + s32(tex->audioBuf[(i + tex->playedSamples) * 2]) * 0x50F4 / 0x8000 * SfxVolume); + out[1] = + DSPSampClamp(in[1] + s32(tex->audioBuf[(i + tex->playedSamples) * 2 + 1]) * 0x50F4 / 0x8000 * SfxVolume); } - } - - /* paused THPs shall not pass */ - if (xd8_decodedTexCount <= 0 || xe0_playMode != EPlayMode::Playing) - return; - - /* timing update */ - xe8_curSeconds += dt; - if (xf4_24_loop) - xe8_curSeconds = std::fmod(xe8_curSeconds, xe4_totalSeconds); - else - xe8_curSeconds = std::min(xe4_totalSeconds, xe8_curSeconds); - - /* test remainder threshold, determine if frame needs to be advanced */ - float frameDt = 1.f / x28_thpHead.fps; - float rem = xdc_frameRem - dt; - if (rem <= 0.f) - { - if (!xf4_26_fieldFlip) - { - /* second field has drawn, advance consumer-queue to next THP frame */ - ++xd0_drawTexSlot; - if (xd0_drawTexSlot >= x80_textures.size()) - xd0_drawTexSlot = 0; - if (xd4_audioSlot == -1) - xd4_audioSlot = 0; - --xd8_decodedTexCount; - ++xc8_curFrame; - if (xc8_curFrame == x28_thpHead.numFrames && xf4_24_loop) - xc8_curFrame = 0; - rem += frameDt; - xfc_fieldIndex = 0; - } - else - { - /* advance timing within second field */ - rem += dt; - xf4_26_fieldFlip = false; + } else { + for (u32 i = 0; i < thisSamples; ++i, out += 2) { + out[0] = DSPSampClamp(s32(tex->audioBuf[(i + tex->playedSamples) * 2]) * 0x50F4 / 0x8000 * SfxVolume); + out[1] = DSPSampClamp(s32(tex->audioBuf[(i + tex->playedSamples) * 2 + 1]) * 0x50F4 / 0x8000 * SfxVolume); } + } + tex->playedSamples += thisSamples; + samples -= thisSamples; + } else { + /* urde addition: failsafe for buffer overrun */ + if (in) + memmove(out, in, samples * 4); + else + memset(out, 0, samples * 4); + // fprintf(stderr, "dropped %d samples\n", samples); + return; } - xdc_frameRem = rem; + } } -void CMoviePlayer::DecodeFromRead(const void* data) -{ - const u8* inptr = (u8*)data; - CTHPTextureSet& tex = x80_textures[xcc_decodedTexSlot]; +void CMoviePlayer::MixStaticAudio(s16* out, const s16* in, u32 samples) { + if (!StaticAudio) + return; + while (samples) { + u32 thisSamples = std::min(StaticLoopEnd - StaticAudioOffset, samples); + const u8* thisOffsetLeft = &StaticAudio[StaticAudioOffset / 2]; + const u8* thisOffsetRight = &StaticAudio[StaticAudioSize / 2 + StaticAudioOffset / 2]; - THPFrameHeader frameHeader = *static_cast(data); - frameHeader.swapBig(); - inptr += 8 + x58_thpComponents.numComponents * 4; - - for (int i=0 ; imap(planeSizeHalf); - for (unsigned y=0 ; yunmap(); - - mappedData = (u8*)tex.Y[1]->map(planeSizeHalf); - for (unsigned y=0 ; yunmap(); - - tex.U->load(m_yuvBuf.get() + planeSize, planeSizeQuarter); - tex.V->load(m_yuvBuf.get() + planeSize + planeSizeQuarter, planeSizeQuarter); - } - else - { - /* Direct planar load */ - tex.Y[0]->load(m_yuvBuf.get(), planeSize); - tex.U->load(m_yuvBuf.get() + planeSize, planeSizeQuarter); - tex.V->load(m_yuvBuf.get() + planeSize + planeSizeQuarter, planeSizeQuarter); - } - - break; - } - case THPComponents::Type::Audio: - memset(tex.audioBuf.get(), 0, x28_thpHead.maxAudioSamples * 4); - tex.audioSamples = THPAudioDecode(tex.audioBuf.get(), (u8*)inptr, x74_audioInfo.numChannels == 2); - tex.playedSamples = 0; - inptr += frameHeader.audioSize; - break; - default: break; - } + /* urde addition: mix samples with `in` or no mix */ + if (in) { + for (u32 i = 0; i < thisSamples; i += 2) { + out[0] = DSPSampClamp( + in[0] + s32(g721_decoder(thisOffsetLeft[0] & 0xf, &StaticStateLeft) * StaticVolumeAtten / 0x8000)); + out[1] = DSPSampClamp( + in[1] + s32(g721_decoder(thisOffsetRight[0] & 0xf, &StaticStateRight) * StaticVolumeAtten / 0x8000)); + out[2] = DSPSampClamp( + in[2] + s32(g721_decoder(thisOffsetLeft[0] >> 4 & 0xf, &StaticStateLeft) * StaticVolumeAtten / 0x8000)); + out[3] = DSPSampClamp( + in[3] + s32(g721_decoder(thisOffsetRight[0] >> 4 & 0xf, &StaticStateRight) * StaticVolumeAtten / 0x8000)); + thisOffsetLeft += 1; + thisOffsetRight += 1; + out += 4; + in += 4; + } + } else { + for (u32 i = 0; i < thisSamples; i += 2) { + out[0] = + DSPSampClamp(s32(g721_decoder(thisOffsetLeft[0] & 0xf, &StaticStateLeft) * StaticVolumeAtten / 0x8000)); + out[1] = + DSPSampClamp(s32(g721_decoder(thisOffsetRight[0] & 0xf, &StaticStateRight) * StaticVolumeAtten / 0x8000)); + out[2] = DSPSampClamp( + s32(g721_decoder(thisOffsetLeft[0] >> 4 & 0xf, &StaticStateLeft) * StaticVolumeAtten / 0x8000)); + out[3] = DSPSampClamp( + s32(g721_decoder(thisOffsetRight[0] >> 4 & 0xf, &StaticStateRight) * StaticVolumeAtten / 0x8000)); + thisOffsetLeft += 1; + thisOffsetRight += 1; + out += 4; + } } - /* advance YUV producer-queue slot */ - ++xcc_decodedTexSlot; - if (xcc_decodedTexSlot == x80_textures.size()) - xcc_decodedTexSlot = 0; + StaticAudioOffset += thisSamples; + if (StaticAudioOffset == StaticLoopEnd) + StaticAudioOffset = StaticLoopBegin; + samples -= thisSamples; + } } -void CMoviePlayer::ReadCompleted() -{ - std::unique_ptr buffer = std::move(x90_requestBuf); +void CMoviePlayer::Rewind() { + if (x98_request) { + x98_request->PostCancelRequest(); x98_request.reset(); - const THPFrameHeader* frameHeader = - reinterpret_cast(buffer.get()); + } - /* transfer request buffer to mem-cache if needed */ - if (xc0_curLoadFrame == xa0_bufferQueue.size() && xf0_preLoadFrames > xc0_curLoadFrame) - xa0_bufferQueue.push_back(std::move(buffer)); + xb0_nextReadSize = x28_thpHead.firstFrameSize; + xb4_nextReadOff = x28_thpHead.firstFrameOffset; + xb8_readSizeWrapped = x28_thpHead.firstFrameSize; + xbc_readOffWrapped = x28_thpHead.firstFrameOffset; - /* store params of next read operation */ - xb4_nextReadOff += xb0_nextReadSize; - xb0_nextReadSize = hecl::SBig(frameHeader->nextSize); - ++xc0_curLoadFrame; + xc0_curLoadFrame = 0; + xc4_requestFrameWrapped = 0; + xc8_curFrame = 0; + xcc_decodedTexSlot = 0; + xd0_drawTexSlot = -1; + xd4_audioSlot = -1; + xd8_decodedTexCount = 0; + xdc_frameRem = 0.f; + xe8_curSeconds = 0.f; +} - if (xc0_curLoadFrame == xf0_preLoadFrames) - { - if (x28_thpHead.numFrames == xc0_curLoadFrame) - { - xb8_readSizeWrapped = x28_thpHead.firstFrameSize; - xbc_readOffWrapped = x28_thpHead.firstFrameOffset; +void CMoviePlayer::SetFrame(const zeus::CVector3f& a, const zeus::CVector3f& b, const zeus::CVector3f& c, + const zeus::CVector3f& d) { + m_frame[0].m_pos = a; + m_frame[1].m_pos = b; + m_frame[2].m_pos = d; + m_frame[3].m_pos = c; + m_vertBuf->load(m_frame, sizeof(m_frame)); +} + +void CMoviePlayer::DrawFrame() { + if (xd0_drawTexSlot == -1) + return; + + /* draw appropriate field */ + CTHPTextureSet& tex = x80_textures[xd0_drawTexSlot]; + CGraphics::SetShaderDataBinding(tex.binding[m_deinterlace ? (xfc_fieldIndex != 0) : 0]); + CGraphics::DrawArray(0, 4); + + /* ensure second field is being displayed by VI to signal advance + * (faked in urde with continuous xor) */ + if (!xfc_fieldIndex && CGraphics::g_LastFrameUsedAbove) + xf4_26_fieldFlip = true; + + ++xfc_fieldIndex; +} + +void CMoviePlayer::Update(float dt) { + if (xc0_curLoadFrame < xf0_preLoadFrames) { + /* in buffering phase, ensure read data is stored for mem-cache access */ + if (x98_request && x98_request->IsComplete()) { + ReadCompleted(); + if (xc0_curLoadFrame >= xa0_bufferQueue.size() && xc0_curLoadFrame < xf0_preLoadFrames && + xa0_bufferQueue.size() < x28_thpHead.numFrames) { + PostDVDReadRequestIfNeeded(); + } + } + } else { + /* out of buffering phase, skip mem-cache straight to decode */ + if (x98_request) { + bool flag = false; + if (xc4_requestFrameWrapped >= xa0_bufferQueue.size() && xc0_curLoadFrame >= xa0_bufferQueue.size()) + flag = true; + if (x98_request->IsComplete() && xd8_decodedTexCount < 2 && flag) { + DecodeFromRead(x90_requestBuf.get()); + ReadCompleted(); + PostDVDReadRequestIfNeeded(); + ++xd8_decodedTexCount; + ++xc4_requestFrameWrapped; + if (xc4_requestFrameWrapped >= x28_thpHead.numFrames && xf4_24_loop) + xc4_requestFrameWrapped = 0; + } + } + } + + /* submit request for additional read to keep stream-consumer happy + * (if buffer slot is available) */ + if (!x98_request && xe0_playMode == EPlayMode::Playing && xa0_bufferQueue.size() < x28_thpHead.numFrames) { + PostDVDReadRequestIfNeeded(); + } + + /* decode frame directly from mem-cache if needed */ + if (xd8_decodedTexCount < 2) { + if (xe0_playMode == EPlayMode::Playing && xc4_requestFrameWrapped < xf0_preLoadFrames) { + u32 minFrame = std::min(u32(xa0_bufferQueue.size()) - 1, xc4_requestFrameWrapped); + if (minFrame == -1) + return; + std::unique_ptr& frameData = xa0_bufferQueue[minFrame]; + DecodeFromRead(frameData.get()); + ++xd8_decodedTexCount; + ++xc4_requestFrameWrapped; + if (xc4_requestFrameWrapped >= x28_thpHead.numFrames && xf4_24_loop) + xc4_requestFrameWrapped = 0; + } + } + + /* paused THPs shall not pass */ + if (xd8_decodedTexCount <= 0 || xe0_playMode != EPlayMode::Playing) + return; + + /* timing update */ + xe8_curSeconds += dt; + if (xf4_24_loop) + xe8_curSeconds = std::fmod(xe8_curSeconds, xe4_totalSeconds); + else + xe8_curSeconds = std::min(xe4_totalSeconds, xe8_curSeconds); + + /* test remainder threshold, determine if frame needs to be advanced */ + float frameDt = 1.f / x28_thpHead.fps; + float rem = xdc_frameRem - dt; + if (rem <= 0.f) { + if (!xf4_26_fieldFlip) { + /* second field has drawn, advance consumer-queue to next THP frame */ + ++xd0_drawTexSlot; + if (xd0_drawTexSlot >= x80_textures.size()) + xd0_drawTexSlot = 0; + if (xd4_audioSlot == -1) + xd4_audioSlot = 0; + --xd8_decodedTexCount; + ++xc8_curFrame; + if (xc8_curFrame == x28_thpHead.numFrames && xf4_24_loop) + xc8_curFrame = 0; + rem += frameDt; + xfc_fieldIndex = 0; + } else { + /* advance timing within second field */ + rem += dt; + xf4_26_fieldFlip = false; + } + } + xdc_frameRem = rem; +} + +void CMoviePlayer::DecodeFromRead(const void* data) { + const u8* inptr = (u8*)data; + CTHPTextureSet& tex = x80_textures[xcc_decodedTexSlot]; + + THPFrameHeader frameHeader = *static_cast(data); + frameHeader.swapBig(); + inptr += 8 + x58_thpComponents.numComponents * 4; + + for (int i = 0; i < x58_thpComponents.numComponents; ++i) { + switch (x58_thpComponents.comps[i]) { + case THPComponents::Type::Video: { + tjDecompressToYUV(TjHandle, (u8*)inptr, frameHeader.imageSize, m_yuvBuf.get(), 0); + inptr += frameHeader.imageSize; + + uintptr_t planeSize = x6c_videoInfo.width * x6c_videoInfo.height; + uintptr_t planeSizeHalf = planeSize / 2; + uintptr_t planeSizeQuarter = planeSizeHalf / 2; + + if (m_deinterlace) { + /* Deinterlace into 2 discrete 60-fps half-res textures */ + u8* mappedData = (u8*)tex.Y[0]->map(planeSizeHalf); + for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) { + memmove(mappedData + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2), + x6c_videoInfo.width); } - else - { - xb8_readSizeWrapped = xb0_nextReadSize; - xbc_readOffWrapped = xb4_nextReadOff; + tex.Y[0]->unmap(); + + mappedData = (u8*)tex.Y[1]->map(planeSizeHalf); + for (unsigned y = 0; y < x6c_videoInfo.height / 2; ++y) { + memmove(mappedData + x6c_videoInfo.width * y, m_yuvBuf.get() + x6c_videoInfo.width * (y * 2 + 1), + x6c_videoInfo.width); } - } + tex.Y[1]->unmap(); - /* handle loop-event read */ - if (xc0_curLoadFrame >= x28_thpHead.numFrames && xf4_24_loop) - { - xb4_nextReadOff = xbc_readOffWrapped; - xb0_nextReadSize = xb8_readSizeWrapped; - xc0_curLoadFrame = xf0_preLoadFrames; + tex.U->load(m_yuvBuf.get() + planeSize, planeSizeQuarter); + tex.V->load(m_yuvBuf.get() + planeSize + planeSizeQuarter, planeSizeQuarter); + } else { + /* Direct planar load */ + tex.Y[0]->load(m_yuvBuf.get(), planeSize); + tex.U->load(m_yuvBuf.get() + planeSize, planeSizeQuarter); + tex.V->load(m_yuvBuf.get() + planeSize + planeSizeQuarter, planeSizeQuarter); + } + + break; } + case THPComponents::Type::Audio: + memset(tex.audioBuf.get(), 0, x28_thpHead.maxAudioSamples * 4); + tex.audioSamples = THPAudioDecode(tex.audioBuf.get(), (u8*)inptr, x74_audioInfo.numChannels == 2); + tex.playedSamples = 0; + inptr += frameHeader.audioSize; + break; + default: + break; + } + } + + /* advance YUV producer-queue slot */ + ++xcc_decodedTexSlot; + if (xcc_decodedTexSlot == x80_textures.size()) + xcc_decodedTexSlot = 0; } -void CMoviePlayer::PostDVDReadRequestIfNeeded() -{ - if (xc0_curLoadFrame < x28_thpHead.numFrames) - { - x90_requestBuf.reset(new uint8_t[xb0_nextReadSize]); - x98_request = AsyncSeekRead(x90_requestBuf.get(), xb0_nextReadSize, - ESeekOrigin::Begin, xb4_nextReadOff); +void CMoviePlayer::ReadCompleted() { + std::unique_ptr buffer = std::move(x90_requestBuf); + x98_request.reset(); + const THPFrameHeader* frameHeader = reinterpret_cast(buffer.get()); + + /* transfer request buffer to mem-cache if needed */ + if (xc0_curLoadFrame == xa0_bufferQueue.size() && xf0_preLoadFrames > xc0_curLoadFrame) + xa0_bufferQueue.push_back(std::move(buffer)); + + /* store params of next read operation */ + xb4_nextReadOff += xb0_nextReadSize; + xb0_nextReadSize = hecl::SBig(frameHeader->nextSize); + ++xc0_curLoadFrame; + + if (xc0_curLoadFrame == xf0_preLoadFrames) { + if (x28_thpHead.numFrames == xc0_curLoadFrame) { + xb8_readSizeWrapped = x28_thpHead.firstFrameSize; + xbc_readOffWrapped = x28_thpHead.firstFrameOffset; + } else { + xb8_readSizeWrapped = xb0_nextReadSize; + xbc_readOffWrapped = xb4_nextReadOff; } + } + + /* handle loop-event read */ + if (xc0_curLoadFrame >= x28_thpHead.numFrames && xf4_24_loop) { + xb4_nextReadOff = xbc_readOffWrapped; + xb0_nextReadSize = xb8_readSizeWrapped; + xc0_curLoadFrame = xf0_preLoadFrames; + } } +void CMoviePlayer::PostDVDReadRequestIfNeeded() { + if (xc0_curLoadFrame < x28_thpHead.numFrames) { + x90_requestBuf.reset(new uint8_t[xb0_nextReadSize]); + x98_request = AsyncSeekRead(x90_requestBuf.get(), xb0_nextReadSize, ESeekOrigin::Begin, xb4_nextReadOff); + } } + +} // namespace urde diff --git a/Runtime/Graphics/CMoviePlayer.hpp b/Runtime/Graphics/CMoviePlayer.hpp index e208598ea..57536f172 100644 --- a/Runtime/Graphics/CMoviePlayer.hpp +++ b/Runtime/Graphics/CMoviePlayer.hpp @@ -6,169 +6,149 @@ #include "specter/View.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { -class CMoviePlayer : public CDvdFile -{ +class CMoviePlayer : public CDvdFile { public: - enum class EPlayMode - { - Stopped, - Playing - }; + enum class EPlayMode { Stopped, Playing }; + private: - struct THPHeader - { - u32 magic; - u32 version; - u32 maxBufferSize; - u32 maxAudioSamples; - float fps; - u32 numFrames; - u32 firstFrameSize; - u32 dataSize; - u32 componentDataOffset; - u32 offsetsDataOffset; - u32 firstFrameOffset; - u32 lastFrameOffset; - void swapBig(); - } x28_thpHead; + struct THPHeader { + u32 magic; + u32 version; + u32 maxBufferSize; + u32 maxAudioSamples; + float fps; + u32 numFrames; + u32 firstFrameSize; + u32 dataSize; + u32 componentDataOffset; + u32 offsetsDataOffset; + u32 firstFrameOffset; + u32 lastFrameOffset; + void swapBig(); + } x28_thpHead; - struct THPComponents - { - u32 numComponents; - enum class Type : u8 - { - Video = 0x0, - Audio = 0x1, - None = 0xff - } comps[16]; - void swapBig(); - } x58_thpComponents; + struct THPComponents { + u32 numComponents; + enum class Type : u8 { Video = 0x0, Audio = 0x1, None = 0xff } comps[16]; + void swapBig(); + } x58_thpComponents; - struct THPVideoInfo - { - u32 width; - u32 height; - void swapBig(); - } x6c_videoInfo; + struct THPVideoInfo { + u32 width; + u32 height; + void swapBig(); + } x6c_videoInfo; - struct THPAudioInfo - { - u32 numChannels; - u32 sampleRate; - u32 numSamples; - void swapBig(); - } x74_audioInfo; + struct THPAudioInfo { + u32 numChannels; + u32 sampleRate; + u32 numSamples; + void swapBig(); + } x74_audioInfo; - struct THPFrameHeader - { - u32 nextSize; - u32 prevSize; - u32 imageSize; - u32 audioSize; - void swapBig(); + struct THPFrameHeader { + u32 nextSize; + u32 prevSize; + u32 imageSize; + u32 audioSize; + void swapBig(); + }; + + struct THPAudioFrameHeader { + u32 channelSize; + u32 numSamples; + s16 channelCoefs[2][8][2]; + s16 channelPrevs[2][2]; + void swapBig(); + }; + + struct CTHPTextureSet { + boo::ObjToken Y[2]; + boo::ObjToken U; + boo::ObjToken V; + u32 playedSamples = 0; + u32 audioSamples = 0; + std::unique_ptr audioBuf; + boo::ObjToken binding[2]; + }; + std::vector x80_textures; + std::unique_ptr x90_requestBuf; + std::shared_ptr x98_request; + std::vector> xa0_bufferQueue; + + u32 xb0_nextReadSize = 0; + u32 xb4_nextReadOff = 0; + u32 xb8_readSizeWrapped = 0; + u32 xbc_readOffWrapped = 0; + u32 xc0_curLoadFrame = 0; + u32 xc4_requestFrameWrapped = 0; + u32 xc8_curFrame = 0; + u32 xcc_decodedTexSlot = 0; + u32 xd0_drawTexSlot = -1; + u32 xd4_audioSlot = -1; + s32 xd8_decodedTexCount = 0; + float xdc_frameRem = 0.f; + EPlayMode xe0_playMode = EPlayMode::Playing; + float xe4_totalSeconds = 0.f; + float xe8_curSeconds = 0.f; + float xec_preLoadSeconds; + u32 xf0_preLoadFrames = 0; + u32 xf8_ = 0; + u32 xfc_fieldIndex = 0; + + std::unique_ptr m_yuvBuf; + + union { + u32 m_dummy = 0; + struct { + bool xf4_24_loop : 1; + bool xf4_25_hasAudio : 1; + bool xf4_26_fieldFlip : 1; + bool m_deinterlace : 1; }; + }; - struct THPAudioFrameHeader - { - u32 channelSize; - u32 numSamples; - s16 channelCoefs[2][8][2]; - s16 channelPrevs[2][2]; - void swapBig(); - }; + specter::View::ViewBlock m_viewVertBlock; + boo::ObjToken m_blockBuf; + boo::ObjToken m_vertBuf; - struct CTHPTextureSet - { - boo::ObjToken Y[2]; - boo::ObjToken U; - boo::ObjToken V; - u32 playedSamples = 0; - u32 audioSamples = 0; - std::unique_ptr audioBuf; - boo::ObjToken binding[2]; - }; - std::vector x80_textures; - std::unique_ptr x90_requestBuf; - std::shared_ptr x98_request; - std::vector> xa0_bufferQueue; + specter::View::TexShaderVert m_frame[4]; - u32 xb0_nextReadSize = 0; - u32 xb4_nextReadOff = 0; - u32 xb8_readSizeWrapped = 0; - u32 xbc_readOffWrapped = 0; - u32 xc0_curLoadFrame = 0; - u32 xc4_requestFrameWrapped = 0; - u32 xc8_curFrame = 0; - u32 xcc_decodedTexSlot = 0; - u32 xd0_drawTexSlot = -1; - u32 xd4_audioSlot = -1; - s32 xd8_decodedTexCount = 0; - float xdc_frameRem = 0.f; - EPlayMode xe0_playMode = EPlayMode::Playing; - float xe4_totalSeconds = 0.f; - float xe8_curSeconds = 0.f; - float xec_preLoadSeconds; - u32 xf0_preLoadFrames = 0; - u32 xf8_ = 0; - u32 xfc_fieldIndex = 0; - - std::unique_ptr m_yuvBuf; - - union - { - u32 m_dummy = 0; - struct - { - bool xf4_24_loop : 1; bool xf4_25_hasAudio : 1; - bool xf4_26_fieldFlip : 1; bool m_deinterlace : 1; - }; - }; - - specter::View::ViewBlock m_viewVertBlock; - boo::ObjToken m_blockBuf; - boo::ObjToken m_vertBuf; - - specter::View::TexShaderVert m_frame[4]; - - static u32 THPAudioDecode(s16* buffer, const u8* audioFrame, bool stereo); - void DecodeFromRead(const void* data); - void ReadCompleted(); - void PostDVDReadRequestIfNeeded(); + static u32 THPAudioDecode(s16* buffer, const u8* audioFrame, bool stereo); + void DecodeFromRead(const void* data); + void ReadCompleted(); + void PostDVDReadRequestIfNeeded(); public: - CMoviePlayer(const char* path, float preLoadSeconds, bool loop, bool deinterlace); + CMoviePlayer(const char* path, float preLoadSeconds, bool loop, bool deinterlace); - static void DisableStaticAudio() {SetStaticAudio(nullptr, 0, 0, 0);} - static void SetStaticAudioVolume(int vol); - static void SetStaticAudio(const void* data, u32 size, u32 loopBegin, u32 loopEnd); - static void SetSfxVolume(u8 volume); - static void MixStaticAudio(s16* out, const s16* in, u32 samples); - void MixAudio(s16* out, const s16* in, u32 samples); - void Rewind(); + static void DisableStaticAudio() { SetStaticAudio(nullptr, 0, 0, 0); } + static void SetStaticAudioVolume(int vol); + static void SetStaticAudio(const void* data, u32 size, u32 loopBegin, u32 loopEnd); + static void SetSfxVolume(u8 volume); + static void MixStaticAudio(s16* out, const s16* in, u32 samples); + void MixAudio(s16* out, const s16* in, u32 samples); + void Rewind(); - bool GetIsMovieFinishedPlaying() const - { - if (xf4_24_loop) - return false; - return xc8_curFrame == x28_thpHead.numFrames; - } - bool IsLooping() const { return xf4_24_loop; } - bool GetIsFullyCached() const {return xa0_bufferQueue.size() >= xf0_preLoadFrames;} - float GetPlayedSeconds() const {return xdc_frameRem + xe8_curSeconds;} - float GetTotalSeconds() const {return xe4_totalSeconds;} - void SetPlayMode(EPlayMode mode) {xe0_playMode = mode;} - void SetFrame(const zeus::CVector3f& a, const zeus::CVector3f& b, - const zeus::CVector3f& c, const zeus::CVector3f& d); - void DrawFrame(); - void Update(float dt); - std::pair GetVideoDimensions() const { return {x6c_videoInfo.width, x6c_videoInfo.height}; } + bool GetIsMovieFinishedPlaying() const { + if (xf4_24_loop) + return false; + return xc8_curFrame == x28_thpHead.numFrames; + } + bool IsLooping() const { return xf4_24_loop; } + bool GetIsFullyCached() const { return xa0_bufferQueue.size() >= xf0_preLoadFrames; } + float GetPlayedSeconds() const { return xdc_frameRem + xe8_curSeconds; } + float GetTotalSeconds() const { return xe4_totalSeconds; } + void SetPlayMode(EPlayMode mode) { xe0_playMode = mode; } + void SetFrame(const zeus::CVector3f& a, const zeus::CVector3f& b, const zeus::CVector3f& c, const zeus::CVector3f& d); + void DrawFrame(); + void Update(float dt); + std::pair GetVideoDimensions() const { return {x6c_videoInfo.width, x6c_videoInfo.height}; } - static void Initialize(); - static void Shutdown(); + static void Initialize(); + static void Shutdown(); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CPVSAreaSet.cpp b/Runtime/Graphics/CPVSAreaSet.cpp index 8748eae09..1f51ce4b6 100644 --- a/Runtime/Graphics/CPVSAreaSet.cpp +++ b/Runtime/Graphics/CPVSAreaSet.cpp @@ -1,23 +1,21 @@ #include "CPVSAreaSet.hpp" -namespace urde -{ +namespace urde { -CPVSAreaSet::CPVSAreaSet(const u8* data, u32 len) -{ - CMemoryInStream r(data, len); - x0_numFeatures = r.readUint32Big(); - x4_numLights = r.readUint32Big(); - x8_num2ndLights = r.readUint32Big(); - xc_numActors = r.readUint32Big(); - x10_leafSize = r.readUint32Big(); - x14_lightIndexCount = r.readUint32Big(); - x18_entityIndex.reserve(xc_numActors); - for (int i=0 ; i x18_entityIndex; - const u8* x1c_lightLeaves; - CPVSVisOctree x20_octree; +class CPVSAreaSet { + u32 x0_numFeatures; + u32 x4_numLights; + u32 x8_num2ndLights; + u32 xc_numActors; + u32 x10_leafSize; + u32 x14_lightIndexCount; + std::vector x18_entityIndex; + const u8* x1c_lightLeaves; + CPVSVisOctree x20_octree; - CPVSVisSet _GetLightSet(u32 lightIdx) const - { - CPVSVisSet ret; - ret.SetFromMemory(x20_octree.GetNumObjects(), x20_octree.GetNumLights(), - x1c_lightLeaves + x10_leafSize * lightIdx); - return ret; - } + CPVSVisSet _GetLightSet(u32 lightIdx) const { + CPVSVisSet ret; + ret.SetFromMemory(x20_octree.GetNumObjects(), x20_octree.GetNumLights(), x1c_lightLeaves + x10_leafSize * lightIdx); + return ret; + } public: - CPVSAreaSet(const u8* data, u32 len); - u32 GetNumFeatures() const { return x0_numFeatures; } - u32 GetNumActors() const { return xc_numActors; } - u32 Get1stLightIndex(u32 lightIdx) const { return x0_numFeatures + x8_num2ndLights + lightIdx; } - u32 Get2ndLightIndex(u32 lightIdx) const { return x0_numFeatures + lightIdx; } - bool Has2ndLayerLights() const { return x8_num2ndLights != 0; } - u32 GetEntityIdByIndex(int idx) const { return x18_entityIndex[idx]; } - const CPVSVisOctree& GetVisOctree() const { return x20_octree; } - CPVSVisSet Get1stLightSet(u32 lightIdx) const { return _GetLightSet(x8_num2ndLights + lightIdx); } - CPVSVisSet Get2ndLightSet(u32 lightIdx) const { return _GetLightSet(lightIdx); } + CPVSAreaSet(const u8* data, u32 len); + u32 GetNumFeatures() const { return x0_numFeatures; } + u32 GetNumActors() const { return xc_numActors; } + u32 Get1stLightIndex(u32 lightIdx) const { return x0_numFeatures + x8_num2ndLights + lightIdx; } + u32 Get2ndLightIndex(u32 lightIdx) const { return x0_numFeatures + lightIdx; } + bool Has2ndLayerLights() const { return x8_num2ndLights != 0; } + u32 GetEntityIdByIndex(int idx) const { return x18_entityIndex[idx]; } + const CPVSVisOctree& GetVisOctree() const { return x20_octree; } + CPVSVisSet Get1stLightSet(u32 lightIdx) const { return _GetLightSet(x8_num2ndLights + lightIdx); } + CPVSVisSet Get2ndLightSet(u32 lightIdx) const { return _GetLightSet(lightIdx); } }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CPVSVisOctree.cpp b/Runtime/Graphics/CPVSVisOctree.cpp index 31667b917..0dcea0217 100644 --- a/Runtime/Graphics/CPVSVisOctree.cpp +++ b/Runtime/Graphics/CPVSVisOctree.cpp @@ -1,113 +1,86 @@ #include "CPVSVisOctree.hpp" -namespace urde -{ +namespace urde { -CPVSVisOctree CPVSVisOctree::MakePVSVisOctree(const u8* data) -{ - CMemoryInStream r(data, 68); - zeus::CAABox aabb = aabb.ReadBoundingBoxBig(r); - u32 numObjects = r.readUint32Big(); - u32 numLights = r.readUint32Big(); - r.readUint32Big(); - return CPVSVisOctree(aabb, numObjects, numLights, data + r.position()); +CPVSVisOctree CPVSVisOctree::MakePVSVisOctree(const u8* data) { + CMemoryInStream r(data, 68); + zeus::CAABox aabb = aabb.ReadBoundingBoxBig(r); + u32 numObjects = r.readUint32Big(); + u32 numLights = r.readUint32Big(); + r.readUint32Big(); + return CPVSVisOctree(aabb, numObjects, numLights, data + r.position()); } CPVSVisOctree::CPVSVisOctree(const zeus::CAABox& aabb, u32 numObjects, u32 numLights, const u8* c) -: x0_aabb(aabb), x18_numObjects(numObjects), x1c_numLights(numLights), x20_bufferFlag(c != nullptr), x24_octreeData(c) -{ - x2c_searchAabb = x0_aabb; - x20_bufferFlag = 0; +: x0_aabb(aabb), x18_numObjects(numObjects), x1c_numLights(numLights), x20_bufferFlag(c != nullptr), x24_octreeData(c) { + x2c_searchAabb = x0_aabb; + x20_bufferFlag = 0; } -static const u32 NumChildTable[] = -{ - 0, 2, 2, 4, 2, 4, 4, 8 -}; +static const u32 NumChildTable[] = {0, 2, 2, 4, 2, 4, 4, 8}; -u32 CPVSVisOctree::GetNumChildren(u8 byte) const -{ - return NumChildTable[byte & 0x7]; +u32 CPVSVisOctree::GetNumChildren(u8 byte) const { return NumChildTable[byte & 0x7]; } + +u32 CPVSVisOctree::GetChildIndex(const u8*, const zeus::CVector3f&) const { return 0; } + +s32 CPVSVisOctree::IterateSearch(u8 nodeData, const zeus::CVector3f& tp) const { + if (!(nodeData & 0x7)) + return -1; // Leaf node + + zeus::CVector3f newMin = x2c_searchAabb.center(); + zeus::CVector3f newMax; + bool highFlags[3]; + + if (tp.x() > newMin.x()) { + newMax.x() = x2c_searchAabb.max.x(); + highFlags[0] = true; + } else { + newMax.x() = float(newMin.x()); + newMin.x() = float(x2c_searchAabb.min.x()); + highFlags[0] = false; + } + + if (tp.y() > newMin.y()) { + newMax.y() = float(x2c_searchAabb.max.y()); + highFlags[1] = true; + } else { + newMax.y() = float(newMin.y()); + newMin.y() = float(x2c_searchAabb.min.y()); + highFlags[1] = false; + } + + if (tp.z() > newMin.z()) { + newMax.z() = float(x2c_searchAabb.max.z()); + highFlags[2] = true; + } else { + newMax.z() = float(newMin.z()); + newMin.z() = float(x2c_searchAabb.min.z()); + highFlags[2] = false; + } + + u8 axisCounts[2] = {1, 1}; + if (nodeData & 0x1) + axisCounts[0] = 2; + if (nodeData & 0x2) + axisCounts[1] = 2; + + zeus::CAABox& newSearch = const_cast(x2c_searchAabb); + if (nodeData & 0x1) { + newSearch.min.x() = float(newMin.x()); + newSearch.max.x() = float(newMax.x()); + } + if (nodeData & 0x2) { + newSearch.min.y() = float(newMin.y()); + newSearch.max.y() = float(newMax.y()); + } + if (nodeData & 0x4) { + newSearch.min.z() = float(newMin.z()); + newSearch.max.z() = float(newMax.z()); + } + + // Branch node - calculate next relative pointer + return highFlags[0] * bool(nodeData & 0x1) + highFlags[1] * axisCounts[0] * bool(nodeData & 0x2) + + highFlags[2] * axisCounts[0] * axisCounts[1] * bool(nodeData & 0x4); } -u32 CPVSVisOctree::GetChildIndex(const u8*, const zeus::CVector3f&) const -{ - return 0; -} - -s32 CPVSVisOctree::IterateSearch(u8 nodeData, const zeus::CVector3f& tp) const -{ - if (!(nodeData & 0x7)) - return -1; // Leaf node - - zeus::CVector3f newMin = x2c_searchAabb.center(); - zeus::CVector3f newMax; - bool highFlags[3]; - - if (tp.x() > newMin.x()) - { - newMax.x() = x2c_searchAabb.max.x(); - highFlags[0] = true; - } - else - { - newMax.x() = float(newMin.x()); - newMin.x() = float(x2c_searchAabb.min.x()); - highFlags[0] = false; - } - - if (tp.y() > newMin.y()) - { - newMax.y() = float(x2c_searchAabb.max.y()); - highFlags[1] = true; - } - else - { - newMax.y() = float(newMin.y()); - newMin.y() = float(x2c_searchAabb.min.y()); - highFlags[1] = false; - } - - if (tp.z() > newMin.z()) - { - newMax.z() = float(x2c_searchAabb.max.z()); - highFlags[2] = true; - } - else - { - newMax.z() = float(newMin.z()); - newMin.z() = float(x2c_searchAabb.min.z()); - highFlags[2] = false; - } - - u8 axisCounts[2] = {1, 1}; - if (nodeData & 0x1) - axisCounts[0] = 2; - if (nodeData & 0x2) - axisCounts[1] = 2; - - zeus::CAABox& newSearch = const_cast(x2c_searchAabb); - if (nodeData & 0x1) - { - newSearch.min.x() = float(newMin.x()); - newSearch.max.x() = float(newMax.x()); - } - if (nodeData & 0x2) - { - newSearch.min.y() = float(newMin.y()); - newSearch.max.y() = float(newMax.y()); - } - if (nodeData & 0x4) - { - newSearch.min.z() = float(newMin.z()); - newSearch.max.z() = float(newMax.z()); - } - - // Branch node - calculate next relative pointer - return - highFlags[0] * bool(nodeData & 0x1) + - highFlags[1] * axisCounts[0] * bool(nodeData & 0x2) + - highFlags[2] * axisCounts[0] * axisCounts[1] * bool(nodeData & 0x4); -} - -} +} // namespace urde diff --git a/Runtime/Graphics/CPVSVisOctree.hpp b/Runtime/Graphics/CPVSVisOctree.hpp index b24d17397..2b2452c61 100644 --- a/Runtime/Graphics/CPVSVisOctree.hpp +++ b/Runtime/Graphics/CPVSVisOctree.hpp @@ -4,31 +4,29 @@ #include "zeus/CVector3f.hpp" #include "CPVSVisSet.hpp" -namespace urde -{ +namespace urde { + +class CPVSVisOctree { + zeus::CAABox x0_aabb; + u32 x18_numObjects; + u32 x1c_numLights; + bool x20_bufferFlag; + const u8* x24_octreeData; + zeus::CAABox x2c_searchAabb; -class CPVSVisOctree -{ - zeus::CAABox x0_aabb; - u32 x18_numObjects; - u32 x1c_numLights; - bool x20_bufferFlag; - const u8* x24_octreeData; - zeus::CAABox x2c_searchAabb; public: - static CPVSVisOctree MakePVSVisOctree(const u8* data); - CPVSVisOctree() = default; - CPVSVisOctree(const zeus::CAABox& aabb, u32 numObjects, u32 numLights, const u8* c); - u32 GetNumChildren(u8 byte) const; - u32 GetChildIndex(const u8*, const zeus::CVector3f&) const; - const zeus::CAABox& GetBounds() const { return x0_aabb; } - const u8* GetOctreeData() const { return x24_octreeData; } + static CPVSVisOctree MakePVSVisOctree(const u8* data); + CPVSVisOctree() = default; + CPVSVisOctree(const zeus::CAABox& aabb, u32 numObjects, u32 numLights, const u8* c); + u32 GetNumChildren(u8 byte) const; + u32 GetChildIndex(const u8*, const zeus::CVector3f&) const; + const zeus::CAABox& GetBounds() const { return x0_aabb; } + const u8* GetOctreeData() const { return x24_octreeData; } - u32 GetNumObjects() const { return x18_numObjects; } - u32 GetNumLights() const { return x1c_numLights; } - void ResetSearch() const { const_cast(*this).x2c_searchAabb = x0_aabb; } - s32 IterateSearch(u8 nodeData, const zeus::CVector3f& tp) const; + u32 GetNumObjects() const { return x18_numObjects; } + u32 GetNumLights() const { return x1c_numLights; } + void ResetSearch() const { const_cast(*this).x2c_searchAabb = x0_aabb; } + s32 IterateSearch(u8 nodeData, const zeus::CVector3f& tp) const; }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CPVSVisSet.cpp b/Runtime/Graphics/CPVSVisSet.cpp index b0717b5a0..0f80f7f41 100644 --- a/Runtime/Graphics/CPVSVisSet.cpp +++ b/Runtime/Graphics/CPVSVisSet.cpp @@ -1,110 +1,90 @@ #include "CPVSVisSet.hpp" #include "CPVSVisOctree.hpp" -namespace urde -{ +namespace urde { -void CPVSVisSet::Reset(EPVSVisSetState state) -{ - x0_state = state; - x4_numBits = 0; - x8_numLights = 0; - //xc_ = false; - x10_ptr = nullptr; +void CPVSVisSet::Reset(EPVSVisSetState state) { + x0_state = state; + x4_numBits = 0; + x8_numLights = 0; + // xc_ = false; + x10_ptr = nullptr; } -EPVSVisSetState CPVSVisSet::GetVisible(u32 idx) const -{ - if (x0_state != EPVSVisSetState::NodeFound) - return x0_state; +EPVSVisSetState CPVSVisSet::GetVisible(u32 idx) const { + if (x0_state != EPVSVisSetState::NodeFound) + return x0_state; - u32 numFeatures = x4_numBits - x8_numLights; - if (idx < numFeatures) - { - /* This is a feature lookup */ - if (!(x10_ptr[idx / 8] & (1 << (idx & 0x7)))) - return EPVSVisSetState::EndOfTree; - return EPVSVisSetState::OutOfBounds; + u32 numFeatures = x4_numBits - x8_numLights; + if (idx < numFeatures) { + /* This is a feature lookup */ + if (!(x10_ptr[idx / 8] & (1 << (idx & 0x7)))) + return EPVSVisSetState::EndOfTree; + return EPVSVisSetState::OutOfBounds; + } + + /* This is a light lookup */ + u32 lightTest = idx - numFeatures + idx; + const u8* ptr = &x10_ptr[lightTest / 8]; + lightTest &= 0x7; + if (lightTest != 0x7) + return EPVSVisSetState((ptr[0] & (0x3 << lightTest)) >> lightTest); + return EPVSVisSetState((ptr[0] >> 7) | ((ptr[1] & 0x1) << 1)); +} + +void CPVSVisSet::SetFromMemory(u32 numBits, u32 numLights, const u8* leafPtr) { + x0_state = EPVSVisSetState::NodeFound; + x4_numBits = numBits; + x8_numLights = numLights; + x10_ptr = leafPtr; +} + +void CPVSVisSet::SetTestPoint(const CPVSVisOctree& octree, const zeus::CVector3f& point) { + if (!octree.GetBounds().pointInside(point)) { + Reset(EPVSVisSetState::OutOfBounds); + return; + } + + const u8* octCur = octree.GetOctreeData(); + octree.ResetSearch(); + s32 nextNodeRel; + u8 curNode; + while ((nextNodeRel = octree.IterateSearch((curNode = *octCur++), point)) != -1) { + if (nextNodeRel) { + /* Skip node data */ + if (!(curNode & 0x60)) { + octCur += hecl::SBig(reinterpret_cast(octCur)[nextNodeRel - 1]); + } else if (curNode & 0x20) { + octCur += *(octCur + nextNodeRel - 1); + } else { + const u8* tmp = octCur + (nextNodeRel - 1) * 3; + octCur += (tmp[0] << 16) + (tmp[1] << 8) + tmp[2]; + } } - /* This is a light lookup */ - u32 lightTest = idx - numFeatures + idx; - const u8* ptr = &x10_ptr[lightTest / 8]; - lightTest &= 0x7; - if (lightTest != 0x7) - return EPVSVisSetState((ptr[0] & (0x3 << lightTest)) >> lightTest); - return EPVSVisSetState((ptr[0] >> 7) | ((ptr[1] & 0x1) << 1)); -} - -void CPVSVisSet::SetFromMemory(u32 numBits, u32 numLights, const u8* leafPtr) -{ - x0_state = EPVSVisSetState::NodeFound; - x4_numBits = numBits; - x8_numLights = numLights; - x10_ptr = leafPtr; -} - -void CPVSVisSet::SetTestPoint(const CPVSVisOctree& octree, const zeus::CVector3f& point) -{ - if (!octree.GetBounds().pointInside(point)) - { - Reset(EPVSVisSetState::OutOfBounds); - return; + /* Skip children data */ + if (!(curNode & 0x60)) { + octCur += (octree.GetNumChildren(curNode) - 1) * 2; + } else if (curNode & 0x20) { + octCur += octree.GetNumChildren(curNode) - 1; + } else { + octCur += (octree.GetNumChildren(curNode) - 1) * 3; } + } - const u8* octCur = octree.GetOctreeData(); - octree.ResetSearch(); - s32 nextNodeRel; - u8 curNode; - while ((nextNodeRel = octree.IterateSearch((curNode = *octCur++), point)) != -1) - { - if (nextNodeRel) - { - /* Skip node data */ - if (!(curNode & 0x60)) - { - octCur += hecl::SBig(reinterpret_cast(octCur)[nextNodeRel - 1]); - } - else if (curNode & 0x20) - { - octCur += *(octCur + nextNodeRel - 1); - } - else - { - const u8* tmp = octCur + (nextNodeRel - 1) * 3; - octCur += (tmp[0] << 16) + (tmp[1] << 8) + tmp[2]; - } - } - - /* Skip children data */ - if (!(curNode & 0x60)) - { - octCur += (octree.GetNumChildren(curNode) - 1) * 2; - } - else if (curNode & 0x20) - { - octCur += octree.GetNumChildren(curNode) - 1; - } - else - { - octCur += (octree.GetNumChildren(curNode) - 1) * 3; - } - } - - /* Handle leaf type */ - switch (curNode & 0x18) - { - case 0x18: - SetFromMemory(octree.GetNumObjects(), octree.GetNumLights(), octCur); - break; - case 0x10: - Reset(EPVSVisSetState::EndOfTree); - break; - case 0x08: - default: - Reset(EPVSVisSetState::OutOfBounds); - break; - } + /* Handle leaf type */ + switch (curNode & 0x18) { + case 0x18: + SetFromMemory(octree.GetNumObjects(), octree.GetNumLights(), octCur); + break; + case 0x10: + Reset(EPVSVisSetState::EndOfTree); + break; + case 0x08: + default: + Reset(EPVSVisSetState::OutOfBounds); + break; + } } -} +} // namespace urde diff --git a/Runtime/Graphics/CPVSVisSet.hpp b/Runtime/Graphics/CPVSVisSet.hpp index 7f6fc62d1..4b17e837c 100644 --- a/Runtime/Graphics/CPVSVisSet.hpp +++ b/Runtime/Graphics/CPVSVisSet.hpp @@ -4,31 +4,24 @@ #include "zeus/CAABox.hpp" #include -namespace urde -{ +namespace urde { class CPVSVisOctree; -enum class EPVSVisSetState -{ - EndOfTree, - NodeFound, - OutOfBounds -}; +enum class EPVSVisSetState { EndOfTree, NodeFound, OutOfBounds }; + +class CPVSVisSet { + EPVSVisSetState x0_state; + u32 x4_numBits; + u32 x8_numLights; + // bool xc_; Used to be part of auto_ptr + const u8* x10_ptr; -class CPVSVisSet -{ - EPVSVisSetState x0_state; - u32 x4_numBits; - u32 x8_numLights; - //bool xc_; Used to be part of auto_ptr - const u8* x10_ptr; public: - void Reset(EPVSVisSetState state); - EPVSVisSetState GetState() const { return x0_state; } - EPVSVisSetState GetVisible(u32 idx) const; - void SetFromMemory(u32 numBits, u32 numLights, const u8* leafPtr); - void SetTestPoint(const CPVSVisOctree& octree, const zeus::CVector3f&); + void Reset(EPVSVisSetState state); + EPVSVisSetState GetState() const { return x0_state; } + EPVSVisSetState GetVisible(u32 idx) const; + void SetFromMemory(u32 numBits, u32 numLights, const u8* leafPtr); + void SetTestPoint(const CPVSVisOctree& octree, const zeus::CVector3f&); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CRainSplashGenerator.cpp b/Runtime/Graphics/CRainSplashGenerator.cpp index fd1de3077..bc09c3da1 100644 --- a/Runtime/Graphics/CRainSplashGenerator.cpp +++ b/Runtime/Graphics/CRainSplashGenerator.cpp @@ -2,236 +2,191 @@ #include "CStateManager.hpp" #include "World/CWorld.hpp" -namespace urde -{ +namespace urde { -CRainSplashGenerator::CRainSplashGenerator(const zeus::CVector3f& scale, u32 maxSplashes, - u32 genRate, float minZ, float alpha) -: x14_scale(scale), x2c_minZ(minZ) -{ - x30_alpha = std::min(1.f, alpha); - x44_genRate = std::min(maxSplashes, genRate); - x48_24 = false; - x48_25_raining = true; - x0_rainSplashes.reserve(maxSplashes); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - for (int i=0 ; i 0.f) - { - float delta = dt * xc_speed; - float vt = std::max(0.f, x0_t - delta * x15_length); - auto vertCount = u32((x0_t - vt) / delta + 1.f); - m_renderer.Reset(); - for (u32 i=0 ; i 0.f) { + float delta = dt * xc_speed; + float vt = std::max(0.f, x0_t - delta * x15_length); + auto vertCount = u32((x0_t - vt) / delta + 1.f); + m_renderer.Reset(); + for (u32 i = 0; i < vertCount; ++i) { + float vertAlpha = vt * alpha; + zeus::CVector3f vec(vt * x4_xEnd, vt * x8_yEnd, -4.f * vt * (vt - 1.f) * x10_zParabolaHeight); + vec += pos; + vt += delta; + m_renderer.AddVertex(vec, zeus::CColor(1.f, vertAlpha), 1); } + m_renderer.Render(); + } } -void CRainSplashGenerator::SRainSplash::Draw(float alpha, float dt, const zeus::CVector3f& pos) const -{ - for (const SSplashLine& line : x0_lines) - line.Draw(alpha, dt, pos); +void CRainSplashGenerator::SRainSplash::Draw(float alpha, float dt, const zeus::CVector3f& pos) const { + for (const SSplashLine& line : x0_lines) + line.Draw(alpha, dt, pos); } -void CRainSplashGenerator::DoDraw(const zeus::CTransform& xf) const -{ - CGraphics::SetModelMatrix(xf); - if (x40_queueSize > 0) - { - if (x38_queueTail <= x3c_queueHead) - { - for (int i=x3c_queueHead ; i 0) { + if (x38_queueTail <= x3c_queueHead) { + for (int i = x3c_queueHead; i < x0_rainSplashes.size(); ++i) { + const SRainSplash& splash = x0_rainSplashes[i]; + splash.Draw(x30_alpha, x28_dt, splash.x64_pos); + } + for (int i = 0; i < x38_queueTail; ++i) { + const SRainSplash& splash = x0_rainSplashes[i]; + splash.Draw(x30_alpha, x28_dt, splash.x64_pos); + } + } else { + for (int i = x3c_queueHead; i < x38_queueTail; ++i) { + const SRainSplash& splash = x0_rainSplashes[i]; + splash.Draw(x30_alpha, x28_dt, splash.x64_pos); + } } + } } -void CRainSplashGenerator::Draw(const zeus::CTransform& xf) const -{ - if (x48_25_raining) - DoDraw(xf); +void CRainSplashGenerator::Draw(const zeus::CTransform& xf) const { + if (x48_25_raining) + DoDraw(xf); } CRainSplashGenerator::SSplashLine::SSplashLine(boo::IGraphicsDataFactory::Context& ctx) -: m_renderer(ctx, CLineRenderer::EPrimitiveMode::LineStrip, 3, nullptr, false) -{} +: m_renderer(ctx, CLineRenderer::EPrimitiveMode::LineStrip, 3, nullptr, false) {} -CRainSplashGenerator::SRainSplash::SRainSplash(boo::IGraphicsDataFactory::Context& ctx) -{ - for (int i=0 ; i<4 ; ++i) - x0_lines.emplace_back(ctx); +CRainSplashGenerator::SRainSplash::SRainSplash(boo::IGraphicsDataFactory::Context& ctx) { + for (int i = 0; i < 4; ++i) + x0_lines.emplace_back(ctx); } -void CRainSplashGenerator::SSplashLine::Update(float dt, CStateManager& mgr) -{ - if (!x16_active) - return; - if (x0_t <= 0.8f) - { - x14_ = u8(5.f * (1.f - x0_t) + 3.f * x0_t); - x0_t += dt * xc_speed; - } - else if (x15_length != 0) - { - x15_length -= 1; - } - else - { - x16_active = false; - xc_speed = mgr.GetActiveRandom()->Range(0.015625f, 8.f); - x10_zParabolaHeight = mgr.GetActiveRandom()->Range(0.015625f, 0.03125f); - x4_xEnd = mgr.GetActiveRandom()->Range(-0.125f, 0.125f); - x8_yEnd = mgr.GetActiveRandom()->Range(-0.125f, 0.125f); - x15_length = u8(mgr.GetActiveRandom()->Range(1, 2)); - } +void CRainSplashGenerator::SSplashLine::Update(float dt, CStateManager& mgr) { + if (!x16_active) + return; + if (x0_t <= 0.8f) { + x14_ = u8(5.f * (1.f - x0_t) + 3.f * x0_t); + x0_t += dt * xc_speed; + } else if (x15_length != 0) { + x15_length -= 1; + } else { + x16_active = false; + xc_speed = mgr.GetActiveRandom()->Range(0.015625f, 8.f); + x10_zParabolaHeight = mgr.GetActiveRandom()->Range(0.015625f, 0.03125f); + x4_xEnd = mgr.GetActiveRandom()->Range(-0.125f, 0.125f); + x8_yEnd = mgr.GetActiveRandom()->Range(-0.125f, 0.125f); + x15_length = u8(mgr.GetActiveRandom()->Range(1, 2)); + } } -void CRainSplashGenerator::SRainSplash::Update(float dt, CStateManager& mgr) -{ - for (SSplashLine& point : x0_lines) - point.Update(dt, mgr); +void CRainSplashGenerator::SRainSplash::Update(float dt, CStateManager& mgr) { + for (SSplashLine& point : x0_lines) + point.Update(dt, mgr); } -bool CRainSplashGenerator::SRainSplash::IsActive() const -{ - bool ret = false; - for (const SSplashLine& line : x0_lines) - ret |= line.x16_active; - return ret; +bool CRainSplashGenerator::SRainSplash::IsActive() const { + bool ret = false; + for (const SSplashLine& line : x0_lines) + ret |= line.x16_active; + return ret; } -void CRainSplashGenerator::UpdateRainSplashRange(CStateManager& mgr, int start, int end, float dt) -{ - for (int i=start ; i= x0_rainSplashes.size()) - x3c_queueHead = 0; - } +void CRainSplashGenerator::UpdateRainSplashRange(CStateManager& mgr, int start, int end, float dt) { + for (int i = start; i < end; ++i) { + SRainSplash& set = x0_rainSplashes[i]; + set.Update(dt, mgr); + if (!set.IsActive()) { + x40_queueSize -= 1; + x3c_queueHead += 1; + if (x3c_queueHead >= x0_rainSplashes.size()) + x3c_queueHead = 0; } + } } -void CRainSplashGenerator::UpdateRainSplashes(CStateManager& mgr, float magnitude, float dt) -{ - x20_generateTimer += dt; - x24_generateInterval = 1.f / (70.f * magnitude); - if (x40_queueSize > 0) - { - if (x38_queueTail <= x3c_queueHead) - { - UpdateRainSplashRange(mgr, x3c_queueHead, int(x0_rainSplashes.size()), dt); - UpdateRainSplashRange(mgr, 0, x38_queueTail, dt); - } - else - { - UpdateRainSplashRange(mgr, x3c_queueHead, x38_queueTail, dt); - } +void CRainSplashGenerator::UpdateRainSplashes(CStateManager& mgr, float magnitude, float dt) { + x20_generateTimer += dt; + x24_generateInterval = 1.f / (70.f * magnitude); + if (x40_queueSize > 0) { + if (x38_queueTail <= x3c_queueHead) { + UpdateRainSplashRange(mgr, x3c_queueHead, int(x0_rainSplashes.size()), dt); + UpdateRainSplashRange(mgr, 0, x38_queueTail, dt); + } else { + UpdateRainSplashRange(mgr, x3c_queueHead, x38_queueTail, dt); } + } } -void CRainSplashGenerator::Update(float dt, CStateManager& mgr) -{ - EEnvFxType neededFx = mgr.GetWorld()->GetNeededEnvFx(); - x28_dt = dt; - x48_25_raining = false; - if (neededFx != EEnvFxType::None && mgr.GetEnvFxManager()->IsSplashActive() && - mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f && neededFx == EEnvFxType::Rain) - { - UpdateRainSplashes(mgr, mgr.GetEnvFxManager()->GetRainMagnitude(), dt); - x48_25_raining = true; - } +void CRainSplashGenerator::Update(float dt, CStateManager& mgr) { + EEnvFxType neededFx = mgr.GetWorld()->GetNeededEnvFx(); + x28_dt = dt; + x48_25_raining = false; + if (neededFx != EEnvFxType::None && mgr.GetEnvFxManager()->IsSplashActive() && + mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f && neededFx == EEnvFxType::Rain) { + UpdateRainSplashes(mgr, mgr.GetEnvFxManager()->GetRainMagnitude(), dt); + x48_25_raining = true; + } } u32 CRainSplashGenerator::GetNextBestPt(u32 pt, const std::vector>& vn, - CRandom16& rand, float minZ) -{ - auto& refVert = vn[pt]; - float maxDist = 0.f; - u32 nextPt = pt; - for (int i=0 ; i<3 ; ++i) - { - auto idx = u32(rand.Range(0, int(vn.size() - 1))); - auto& vert = vn[idx]; - float distSq = (refVert.first - vert.first).magSquared(); - if (distSq > maxDist && - vert.second.dot(zeus::CVector3f::skUp) >= 0.f && - (vert.first.z() <= 0.f || vert.first.z() > minZ)) - { - nextPt = idx; - maxDist = distSq; - } + CRandom16& rand, float minZ) { + auto& refVert = vn[pt]; + float maxDist = 0.f; + u32 nextPt = pt; + for (int i = 0; i < 3; ++i) { + auto idx = u32(rand.Range(0, int(vn.size() - 1))); + auto& vert = vn[idx]; + float distSq = (refVert.first - vert.first).magSquared(); + if (distSq > maxDist && vert.second.dot(zeus::CVector3f::skUp) >= 0.f && + (vert.first.z() <= 0.f || vert.first.z() > minZ)) { + nextPt = idx; + maxDist = distSq; } - return nextPt; + } + return nextPt; } -void CRainSplashGenerator::SRainSplash::SetPoint(const zeus::CVector3f& pos) -{ - for (SSplashLine& line : x0_lines) - line.SetActive(); - x64_pos = pos; +void CRainSplashGenerator::SRainSplash::SetPoint(const zeus::CVector3f& pos) { + for (SSplashLine& line : x0_lines) + line.SetActive(); + x64_pos = pos; } -void CRainSplashGenerator::AddPoint(const zeus::CVector3f& pos) -{ - if (x38_queueTail >= x0_rainSplashes.size()) - x38_queueTail = 0; - x0_rainSplashes[x38_queueTail].SetPoint(pos); - x40_queueSize += 1; - x38_queueTail += 1; +void CRainSplashGenerator::AddPoint(const zeus::CVector3f& pos) { + if (x38_queueTail >= x0_rainSplashes.size()) + x38_queueTail = 0; + x0_rainSplashes[x38_queueTail].SetPoint(pos); + x40_queueSize += 1; + x38_queueTail += 1; } -void CRainSplashGenerator::GeneratePoints(const std::vector>& vn) -{ - if (!x48_25_raining) - return; +void CRainSplashGenerator::GeneratePoints(const std::vector>& vn) { + if (!x48_25_raining) + return; - if (x20_generateTimer > x24_generateInterval) - { - for (int i=0 ; i= x0_rainSplashes.size()) - break; - x34_curPoint = GetNextBestPt(x34_curPoint, vn, x10_random, x2c_minZ); - AddPoint(x14_scale * vn[x34_curPoint].first); - } - x20_generateTimer = 0.f; + if (x20_generateTimer > x24_generateInterval) { + for (int i = 0; i < x44_genRate; ++i) { + if (x40_queueSize >= x0_rainSplashes.size()) + break; + x34_curPoint = GetNextBestPt(x34_curPoint, vn, x10_random, x2c_minZ); + AddPoint(x14_scale * vn[x34_curPoint].first); } + x20_generateTimer = 0.f; + } } -} +} // namespace urde diff --git a/Runtime/Graphics/CRainSplashGenerator.hpp b/Runtime/Graphics/CRainSplashGenerator.hpp index e4d6c64b8..43824016a 100644 --- a/Runtime/Graphics/CRainSplashGenerator.hpp +++ b/Runtime/Graphics/CRainSplashGenerator.hpp @@ -5,71 +5,67 @@ #include "zeus/CVector3f.hpp" #include "Graphics/CLineRenderer.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class CRainSplashGenerator -{ - struct SSplashLine - { - float x0_t = 0.f; - float x4_xEnd = 0.f; - float x8_yEnd = 0.f; - float xc_speed = 4.f; - float x10_zParabolaHeight = 0.015625f; - u8 x14_ = 3; - u8 x15_length = 1; - bool x16_active = true; // used to be one-bit bitfield - mutable CLineRenderer m_renderer; - explicit SSplashLine(boo::IGraphicsDataFactory::Context& ctx); - void Update(float dt, CStateManager& mgr); - void Draw(float alpha, float dt, const zeus::CVector3f& pos) const; - void SetActive() { x16_active = true; } - }; - struct SRainSplash - { - rstl::reserved_vector x0_lines; - zeus::CVector3f x64_pos; - float x70_ = 0.f; - explicit SRainSplash(boo::IGraphicsDataFactory::Context& ctx); - SRainSplash(const SRainSplash&) = delete; - SRainSplash& operator=(const SRainSplash&) = delete; - SRainSplash(SRainSplash&&) = default; - SRainSplash& operator=(SRainSplash&&) = default; - void Update(float dt, CStateManager& mgr); - bool IsActive() const; - void Draw(float alpha, float dt, const zeus::CVector3f& pos) const; - void SetPoint(const zeus::CVector3f& pos); - }; - std::vector x0_rainSplashes; - CRandom16 x10_random = {99}; - zeus::CVector3f x14_scale; - float x20_generateTimer = 0.f; - float x24_generateInterval; - float x28_dt = 0.f; - float x2c_minZ; - float x30_alpha; - u32 x34_curPoint = 0; - u32 x38_queueTail = 0; - u32 x3c_queueHead = 0; - u32 x40_queueSize = 0; - u32 x44_genRate; - bool x48_24 : 1; - bool x48_25_raining : 1; - void UpdateRainSplashRange(CStateManager& mgr, int start, int end, float dt); - void UpdateRainSplashes(CStateManager& mgr, float magnitude, float dt); - void DoDraw(const zeus::CTransform& xf) const; - static u32 GetNextBestPt(u32 pt, const std::vector>& vn, - CRandom16& rand, float minZ); - void AddPoint(const zeus::CVector3f& pos); -public: - CRainSplashGenerator(const zeus::CVector3f& scale, u32 maxSplashes, u32 genRate, float minZ, float alpha); +class CRainSplashGenerator { + struct SSplashLine { + float x0_t = 0.f; + float x4_xEnd = 0.f; + float x8_yEnd = 0.f; + float xc_speed = 4.f; + float x10_zParabolaHeight = 0.015625f; + u8 x14_ = 3; + u8 x15_length = 1; + bool x16_active = true; // used to be one-bit bitfield + mutable CLineRenderer m_renderer; + explicit SSplashLine(boo::IGraphicsDataFactory::Context& ctx); void Update(float dt, CStateManager& mgr); - void GeneratePoints(const std::vector>& vn); - void Draw(const zeus::CTransform& xf) const; - bool IsRaining() const { return x48_25_raining; } + void Draw(float alpha, float dt, const zeus::CVector3f& pos) const; + void SetActive() { x16_active = true; } + }; + struct SRainSplash { + rstl::reserved_vector x0_lines; + zeus::CVector3f x64_pos; + float x70_ = 0.f; + explicit SRainSplash(boo::IGraphicsDataFactory::Context& ctx); + SRainSplash(const SRainSplash&) = delete; + SRainSplash& operator=(const SRainSplash&) = delete; + SRainSplash(SRainSplash&&) = default; + SRainSplash& operator=(SRainSplash&&) = default; + void Update(float dt, CStateManager& mgr); + bool IsActive() const; + void Draw(float alpha, float dt, const zeus::CVector3f& pos) const; + void SetPoint(const zeus::CVector3f& pos); + }; + std::vector x0_rainSplashes; + CRandom16 x10_random = {99}; + zeus::CVector3f x14_scale; + float x20_generateTimer = 0.f; + float x24_generateInterval; + float x28_dt = 0.f; + float x2c_minZ; + float x30_alpha; + u32 x34_curPoint = 0; + u32 x38_queueTail = 0; + u32 x3c_queueHead = 0; + u32 x40_queueSize = 0; + u32 x44_genRate; + bool x48_24 : 1; + bool x48_25_raining : 1; + void UpdateRainSplashRange(CStateManager& mgr, int start, int end, float dt); + void UpdateRainSplashes(CStateManager& mgr, float magnitude, float dt); + void DoDraw(const zeus::CTransform& xf) const; + static u32 GetNextBestPt(u32 pt, const std::vector>& vn, CRandom16& rand, + float minZ); + void AddPoint(const zeus::CVector3f& pos); + +public: + CRainSplashGenerator(const zeus::CVector3f& scale, u32 maxSplashes, u32 genRate, float minZ, float alpha); + void Update(float dt, CStateManager& mgr); + void GeneratePoints(const std::vector>& vn); + void Draw(const zeus::CTransform& xf) const; + bool IsRaining() const { return x48_25_raining; } }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CSimpleShadow.cpp b/Runtime/Graphics/CSimpleShadow.cpp index e23662f83..22450931f 100644 --- a/Runtime/Graphics/CSimpleShadow.cpp +++ b/Runtime/Graphics/CSimpleShadow.cpp @@ -2,98 +2,83 @@ #include "CStateManager.hpp" #include "Collision/CGameCollision.hpp" -namespace urde -{ +namespace urde { CSimpleShadow::CSimpleShadow(float scale, float userAlpha, float maxObjHeight, float displacement) -: x30_scale(scale), x38_userAlpha(userAlpha), x40_maxObjHeight(maxObjHeight), x44_displacement(displacement) -{ - x48_24_collision = false; - x48_25_alwaysCalculateRadius = true; - x48_26_radiusCalculated = false; +: x30_scale(scale), x38_userAlpha(userAlpha), x40_maxObjHeight(maxObjHeight), x44_displacement(displacement) { + x48_24_collision = false; + x48_25_alwaysCalculateRadius = true; + x48_26_radiusCalculated = false; } -zeus::CAABox CSimpleShadow::GetMaxShadowBox(const zeus::CAABox& aabb) const -{ - float extent = x34_radius * x30_scale; - zeus::CVector3f center = aabb.center(); - zeus::CAABox expandedAABB = aabb; - expandedAABB.accumulateBounds({center.x() + extent, center.y() + extent, center.z() - GetMaxObjectHeight()}); - expandedAABB.accumulateBounds({center.x() - extent, center.y() - extent, center.z() - GetMaxObjectHeight()}); - return expandedAABB; +zeus::CAABox CSimpleShadow::GetMaxShadowBox(const zeus::CAABox& aabb) const { + float extent = x34_radius * x30_scale; + zeus::CVector3f center = aabb.center(); + zeus::CAABox expandedAABB = aabb; + expandedAABB.accumulateBounds({center.x() + extent, center.y() + extent, center.z() - GetMaxObjectHeight()}); + expandedAABB.accumulateBounds({center.x() - extent, center.y() - extent, center.z() - GetMaxObjectHeight()}); + return expandedAABB; } -zeus::CAABox CSimpleShadow::GetBounds() const -{ - float extent = x34_radius * x30_scale; - return {{x0_xf.origin.x() - extent, x0_xf.origin.y() - extent, x0_xf.origin.z() - extent}, - {x0_xf.origin.x() + extent, x0_xf.origin.y() + extent, x0_xf.origin.z() + extent}}; +zeus::CAABox CSimpleShadow::GetBounds() const { + float extent = x34_radius * x30_scale; + return {{x0_xf.origin.x() - extent, x0_xf.origin.y() - extent, x0_xf.origin.z() - extent}, + {x0_xf.origin.x() + extent, x0_xf.origin.y() + extent, x0_xf.origin.z() + extent}}; } -void CSimpleShadow::Render(const TLockedToken& tex) const -{ - if (!x48_24_collision) - return; +void CSimpleShadow::Render(const TLockedToken& tex) const { + if (!x48_24_collision) + return; - CGraphics::DisableAllLights(); - CGraphics::SetModelMatrix(x0_xf); + CGraphics::DisableAllLights(); + CGraphics::SetModelMatrix(x0_xf); - if (!m_filter || m_filter->GetTex().GetObj() != tex.GetObj()) - m_filter.emplace(EFilterType::InvDstMultiply, tex, CTexturedQuadFilter::ZTest::LEqual); + if (!m_filter || m_filter->GetTex().GetObj() != tex.GetObj()) + m_filter.emplace(EFilterType::InvDstMultiply, tex, CTexturedQuadFilter::ZTest::LEqual); - float radius = x34_radius * x30_scale; - CTexturedQuadFilter::Vert verts[] = - { - {{-radius, 0.f, -radius}, {0.f, 0.f}}, - {{radius, 0.f, -radius}, {0.f, 1.f}}, - {{-radius, 0.f, radius}, {1.f, 0.f}}, - {{radius, 0.f, radius}, {1.f, 1.f}} - }; - m_filter->drawVerts(zeus::CColor::skWhite, verts); + float radius = x34_radius * x30_scale; + CTexturedQuadFilter::Vert verts[] = {{{-radius, 0.f, -radius}, {0.f, 0.f}}, + {{radius, 0.f, -radius}, {0.f, 1.f}}, + {{-radius, 0.f, radius}, {1.f, 0.f}}, + {{radius, 0.f, radius}, {1.f, 1.f}}}; + m_filter->drawVerts(zeus::CColor::skWhite, verts); } -void CSimpleShadow::Calculate(const zeus::CAABox& aabb, const zeus::CTransform& xf, const CStateManager& mgr) -{ - x48_24_collision = false; - float halfHeight = (aabb.max.z() - aabb.min.z()) * 0.5f; - zeus::CVector3f pos = xf.origin + zeus::CVector3f(0.f, 0.f, halfHeight); - CRayCastResult res = mgr.RayStaticIntersection(pos, zeus::CVector3f::skDown, x40_maxObjHeight, - CMaterialFilter::MakeExclude({EMaterialTypes::SeeThrough})); - float height = x40_maxObjHeight; - if (res.IsValid()) - { - x48_24_collision = true; - height = res.GetT(); +void CSimpleShadow::Calculate(const zeus::CAABox& aabb, const zeus::CTransform& xf, const CStateManager& mgr) { + x48_24_collision = false; + float halfHeight = (aabb.max.z() - aabb.min.z()) * 0.5f; + zeus::CVector3f pos = xf.origin + zeus::CVector3f(0.f, 0.f, halfHeight); + CRayCastResult res = mgr.RayStaticIntersection(pos, zeus::CVector3f::skDown, x40_maxObjHeight, + CMaterialFilter::MakeExclude({EMaterialTypes::SeeThrough})); + float height = x40_maxObjHeight; + if (res.IsValid()) { + x48_24_collision = true; + height = res.GetT(); + } + + if (height > 0.1f + halfHeight) { + TUniqueId cid = kInvalidUniqueId; + rstl::reserved_vector nearList; + CRayCastResult resD = CGameCollision::RayDynamicIntersection( + mgr, cid, pos, zeus::CVector3f::skDown, x40_maxObjHeight, CMaterialFilter::skPassEverything, nearList); + if (resD.IsValid() && resD.GetT() < height) { + x48_24_collision = true; + height = resD.GetT(); + res = resD; } + } - if (height > 0.1f + halfHeight) - { - TUniqueId cid = kInvalidUniqueId; - rstl::reserved_vector nearList; - CRayCastResult resD = CGameCollision::RayDynamicIntersection(mgr, cid, pos, - zeus::CVector3f::skDown, x40_maxObjHeight, - CMaterialFilter::skPassEverything, nearList); - if (resD.IsValid() && resD.GetT() < height) - { - x48_24_collision = true; - height = resD.GetT(); - res = resD; - } - } - - if (x48_24_collision) - { - x3c_heightAlpha = 1.f - height / x40_maxObjHeight; - x0_xf = zeus::lookAt(res.GetPlane().normal(), zeus::CVector3f::skZero); - x0_xf.origin = res.GetPlane().normal() * x44_displacement + res.GetPoint(); - if (x48_25_alwaysCalculateRadius || !x48_26_radiusCalculated) - { - float xExtent = aabb.max.x() - aabb.min.x(); - float yExtent = aabb.max.y() - aabb.min.y(); - x34_radius = std::sqrt(xExtent * xExtent + yExtent * yExtent) * 0.5f; - x48_26_radiusCalculated = true; - } + if (x48_24_collision) { + x3c_heightAlpha = 1.f - height / x40_maxObjHeight; + x0_xf = zeus::lookAt(res.GetPlane().normal(), zeus::CVector3f::skZero); + x0_xf.origin = res.GetPlane().normal() * x44_displacement + res.GetPoint(); + if (x48_25_alwaysCalculateRadius || !x48_26_radiusCalculated) { + float xExtent = aabb.max.x() - aabb.min.x(); + float yExtent = aabb.max.y() - aabb.min.y(); + x34_radius = std::sqrt(xExtent * xExtent + yExtent * yExtent) * 0.5f; + x48_26_radiusCalculated = true; } + } } -} +} // namespace urde diff --git a/Runtime/Graphics/CSimpleShadow.hpp b/Runtime/Graphics/CSimpleShadow.hpp index e554e184d..8b212046f 100644 --- a/Runtime/Graphics/CSimpleShadow.hpp +++ b/Runtime/Graphics/CSimpleShadow.hpp @@ -3,35 +3,33 @@ #include "zeus/CAABox.hpp" #include "Graphics/Shaders/CTexturedQuadFilter.hpp" -namespace urde -{ +namespace urde { class CTexture; class CStateManager; -class CSimpleShadow -{ - zeus::CTransform x0_xf; - float x30_scale; - float x34_radius = 1.f; - float x38_userAlpha; - float x3c_heightAlpha = 1.f; - float x40_maxObjHeight; - float x44_displacement; - bool x48_24_collision : 1; - bool x48_25_alwaysCalculateRadius : 1; - bool x48_26_radiusCalculated : 1; - mutable std::experimental::optional m_filter; -public: - CSimpleShadow(float scale, float userAlpha, float maxObjHeight, float displacement); - bool Valid() const { return x48_24_collision; } - zeus::CAABox GetMaxShadowBox(const zeus::CAABox& aabb) const; - zeus::CAABox GetBounds() const; - void SetAlwaysCalculateRadius(bool) { x48_25_alwaysCalculateRadius = true; } - float GetMaxObjectHeight() const { return x40_maxObjHeight; } - void SetUserAlpha(float a) { x38_userAlpha = a; } - const zeus::CTransform& GetTransform() const { return x0_xf; } - void Render(const TLockedToken& tex) const; - void Calculate(const zeus::CAABox& aabb, const zeus::CTransform& xf, const CStateManager& mgr); -}; -} +class CSimpleShadow { + zeus::CTransform x0_xf; + float x30_scale; + float x34_radius = 1.f; + float x38_userAlpha; + float x3c_heightAlpha = 1.f; + float x40_maxObjHeight; + float x44_displacement; + bool x48_24_collision : 1; + bool x48_25_alwaysCalculateRadius : 1; + bool x48_26_radiusCalculated : 1; + mutable std::experimental::optional m_filter; +public: + CSimpleShadow(float scale, float userAlpha, float maxObjHeight, float displacement); + bool Valid() const { return x48_24_collision; } + zeus::CAABox GetMaxShadowBox(const zeus::CAABox& aabb) const; + zeus::CAABox GetBounds() const; + void SetAlwaysCalculateRadius(bool) { x48_25_alwaysCalculateRadius = true; } + float GetMaxObjectHeight() const { return x40_maxObjHeight; } + void SetUserAlpha(float a) { x38_userAlpha = a; } + const zeus::CTransform& GetTransform() const { return x0_xf; } + void Render(const TLockedToken& tex) const; + void Calculate(const zeus::CAABox& aabb, const zeus::CTransform& xf, const CStateManager& mgr); +}; +} // namespace urde diff --git a/Runtime/Graphics/CSkinnedModel.cpp b/Runtime/Graphics/CSkinnedModel.cpp index e4c12cacc..96f8a722f 100644 --- a/Runtime/Graphics/CSkinnedModel.cpp +++ b/Runtime/Graphics/CSkinnedModel.cpp @@ -2,82 +2,60 @@ #include "Character/CSkinRules.hpp" #include "CVertexMorphEffect.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CSkinnedModel"); -CSkinnedModel::CSkinnedModel(TLockedToken model, - TLockedToken skinRules, - TLockedToken layoutInfo, - int shaderIdx, int drawInsts) -: x4_model(model), x10_skinRules(skinRules), x1c_layoutInfo(layoutInfo) -{ - if (!model) - Log.report(logvisor::Fatal, "bad model token provided to CSkinnedModel"); - if (!skinRules) - Log.report(logvisor::Fatal, "bad skin token provided to CSkinnedModel"); - if (!layoutInfo) - Log.report(logvisor::Fatal, "bad character layout token provided to CSkinnedModel"); - m_modelInst = model->MakeNewInstance(shaderIdx, drawInsts); +CSkinnedModel::CSkinnedModel(TLockedToken model, TLockedToken skinRules, + TLockedToken layoutInfo, int shaderIdx, int drawInsts) +: x4_model(model), x10_skinRules(skinRules), x1c_layoutInfo(layoutInfo) { + if (!model) + Log.report(logvisor::Fatal, "bad model token provided to CSkinnedModel"); + if (!skinRules) + Log.report(logvisor::Fatal, "bad skin token provided to CSkinnedModel"); + if (!layoutInfo) + Log.report(logvisor::Fatal, "bad character layout token provided to CSkinnedModel"); + m_modelInst = model->MakeNewInstance(shaderIdx, drawInsts); } -CSkinnedModel::CSkinnedModel(IObjectStore& store, CAssetId model, - CAssetId skinRules, CAssetId layoutInfo, +CSkinnedModel::CSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, CAssetId layoutInfo, int shaderIdx, int drawInsts) -: CSkinnedModel(store.GetObj(SObjectTag{FOURCC('CMDL'), model}), - store.GetObj(SObjectTag{FOURCC('CSKR'), skinRules}), - store.GetObj(SObjectTag{FOURCC('CINF'), layoutInfo}), - shaderIdx, drawInsts) -{ -} +: CSkinnedModel(store.GetObj(SObjectTag{FOURCC('CMDL'), model}), store.GetObj(SObjectTag{FOURCC('CSKR'), skinRules}), + store.GetObj(SObjectTag{FOURCC('CINF'), layoutInfo}), shaderIdx, drawInsts) {} -void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, - const CModelFlags& drawFlags, +void CSkinnedModel::Calculate(const CPoseAsTransforms& pose, const CModelFlags& drawFlags, const std::experimental::optional& morphEffect, - const float* morphMagnitudes) -{ - if (morphEffect || g_PointGenFunc) - { - if (boo::ObjToken vertBuf = - m_modelInst->UpdateUniformData(drawFlags, nullptr, nullptr)) - { - x10_skinRules->TransformVerticesCPU(m_vertWorkspace, pose, *x4_model); - if (morphEffect) - morphEffect->MorphVertices(m_vertWorkspace, morphMagnitudes, x10_skinRules, pose); - if (g_PointGenFunc) - g_PointGenFunc(g_PointGenCtx, m_vertWorkspace); - x4_model->ApplyVerticesCPU(vertBuf, m_vertWorkspace); - m_modifiedVBO = true; - } + const float* morphMagnitudes) { + if (morphEffect || g_PointGenFunc) { + if (boo::ObjToken vertBuf = m_modelInst->UpdateUniformData(drawFlags, nullptr, nullptr)) { + x10_skinRules->TransformVerticesCPU(m_vertWorkspace, pose, *x4_model); + if (morphEffect) + morphEffect->MorphVertices(m_vertWorkspace, morphMagnitudes, x10_skinRules, pose); + if (g_PointGenFunc) + g_PointGenFunc(g_PointGenCtx, m_vertWorkspace); + x4_model->ApplyVerticesCPU(vertBuf, m_vertWorkspace); + m_modifiedVBO = true; } - else - { - if (boo::ObjToken vertBuf = - m_modelInst->UpdateUniformData(drawFlags, x10_skinRules.GetObj(), &pose)) - { - if (m_modifiedVBO) - { - x4_model->RestoreVerticesCPU(vertBuf); - m_modifiedVBO = false; - } - } + } else { + if (boo::ObjToken vertBuf = + m_modelInst->UpdateUniformData(drawFlags, x10_skinRules.GetObj(), &pose)) { + if (m_modifiedVBO) { + x4_model->RestoreVerticesCPU(vertBuf); + m_modifiedVBO = false; + } } + } } -void CSkinnedModel::Draw(const CModelFlags& drawFlags) const -{ - if (m_modelInst->TryLockTextures()) - m_modelInst->DrawSurfaces(drawFlags); +void CSkinnedModel::Draw(const CModelFlags& drawFlags) const { + if (m_modelInst->TryLockTextures()) + m_modelInst->DrawSurfaces(drawFlags); } -CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, CAssetId model, - CAssetId skinRules, CAssetId layoutInfo, - int shaderIdx, int drawInsts) -: CSkinnedModel(store, model, skinRules, layoutInfo, shaderIdx, drawInsts) -{ -} +CMorphableSkinnedModel::CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, + CAssetId layoutInfo, int shaderIdx, int drawInsts) +: CSkinnedModel(store, model, skinRules, layoutInfo, shaderIdx, drawInsts) {} CSkinnedModel::FPointGenerator CSkinnedModel::g_PointGenFunc = nullptr; void* CSkinnedModel::g_PointGenCtx = nullptr; -} +} // namespace urde diff --git a/Runtime/Graphics/CSkinnedModel.hpp b/Runtime/Graphics/CSkinnedModel.hpp index 8fb528fe0..865b056b7 100644 --- a/Runtime/Graphics/CSkinnedModel.hpp +++ b/Runtime/Graphics/CSkinnedModel.hpp @@ -4,8 +4,7 @@ #include "CModel.hpp" #include "optional.hpp" -namespace urde -{ +namespace urde { class CModel; class CSkinRules; class CCharLayoutInfo; @@ -13,61 +12,48 @@ class CPoseAsTransforms; class CVertexMorphEffect; class IObjectStore; -class CSkinnedModel -{ - friend class CBooModel; - std::unique_ptr m_modelInst; - TLockedToken x4_model; - TLockedToken x10_skinRules; - TLockedToken x1c_layoutInfo; - std::vector> m_vertWorkspace; - bool m_modifiedVBO = false; +class CSkinnedModel { + friend class CBooModel; + std::unique_ptr m_modelInst; + TLockedToken x4_model; + TLockedToken x10_skinRules; + TLockedToken x1c_layoutInfo; + std::vector> m_vertWorkspace; + bool m_modifiedVBO = false; + public: - enum class EDataOwnership - { - Zero, - One - }; - CSkinnedModel(TLockedToken model, - TLockedToken skinRules, - TLockedToken layoutInfo, - int shaderIdx, int drawInsts); - CSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, - CAssetId layoutInfo, int shaderIdx, int drawInsts); + enum class EDataOwnership { Zero, One }; + CSkinnedModel(TLockedToken model, TLockedToken skinRules, + TLockedToken layoutInfo, int shaderIdx, int drawInsts); + CSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, CAssetId layoutInfo, int shaderIdx, + int drawInsts); - const TLockedToken& GetModel() const {return x4_model;} - const std::unique_ptr& GetModelInst() const {return m_modelInst;} - const TLockedToken& GetSkinRules() const {return x10_skinRules;} - const TLockedToken& GetLayoutInfo() const {return x1c_layoutInfo;} + const TLockedToken& GetModel() const { return x4_model; } + const std::unique_ptr& GetModelInst() const { return m_modelInst; } + const TLockedToken& GetSkinRules() const { return x10_skinRules; } + const TLockedToken& GetLayoutInfo() const { return x1c_layoutInfo; } - void Calculate(const CPoseAsTransforms& pose, - const CModelFlags& drawFlags, - const std::experimental::optional& morphEffect, - const float* morphMagnitudes); - void Draw(const CModelFlags& drawFlags) const; + void Calculate(const CPoseAsTransforms& pose, const CModelFlags& drawFlags, + const std::experimental::optional& morphEffect, const float* morphMagnitudes); + void Draw(const CModelFlags& drawFlags) const; - typedef void(*FPointGenerator)(void* item, const std::vector>& vn); - static void SetPointGeneratorFunc(void* ctx, FPointGenerator func) - { - g_PointGenFunc = func; - g_PointGenCtx = ctx; - } - static void ClearPointGeneratorFunc() - { - g_PointGenFunc = nullptr; - } - static FPointGenerator g_PointGenFunc; - static void* g_PointGenCtx; + typedef void (*FPointGenerator)(void* item, const std::vector>& vn); + static void SetPointGeneratorFunc(void* ctx, FPointGenerator func) { + g_PointGenFunc = func; + g_PointGenCtx = ctx; + } + static void ClearPointGeneratorFunc() { g_PointGenFunc = nullptr; } + static FPointGenerator g_PointGenFunc; + static void* g_PointGenCtx; }; -class CMorphableSkinnedModel : public CSkinnedModel -{ - std::unique_ptr x40_morphMagnitudes; +class CMorphableSkinnedModel : public CSkinnedModel { + std::unique_ptr x40_morphMagnitudes; + public: - CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, - CAssetId layoutInfo, int shaderIdx, int drawInsts); - const float* GetMorphMagnitudes() const { return x40_morphMagnitudes.get(); } + CMorphableSkinnedModel(IObjectStore& store, CAssetId model, CAssetId skinRules, CAssetId layoutInfo, int shaderIdx, + int drawInsts); + const float* GetMorphMagnitudes() const { return x40_morphMagnitudes.get(); } }; -} - +} // namespace urde diff --git a/Runtime/Graphics/CTexture.hpp b/Runtime/Graphics/CTexture.hpp index 9d68b8749..eff3e3618 100644 --- a/Runtime/Graphics/CTexture.hpp +++ b/Runtime/Graphics/CTexture.hpp @@ -7,78 +7,68 @@ #include "Graphics/CGraphics.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { class CVParamTransfer; -class CTexture -{ +class CTexture { public: - enum class EFontType - { - None = -1, - OneLayer = 0, /* Fill bit0 */ - OneLayerOutline = 1, /* Fill bit0, Outline bit1 */ - FourLayers = 2, - TwoLayersOutlines = 3, /* Fill bit0/2, Outline bit1/3 */ - TwoLayers = 4, /* Fill bit0/1 and copied to bit2/3 */ - TwoLayersOutlines2 = 8 /* Fill bit2/3, Outline bit0/1 */ - }; + enum class EFontType { + None = -1, + OneLayer = 0, /* Fill bit0 */ + OneLayerOutline = 1, /* Fill bit0, Outline bit1 */ + FourLayers = 2, + TwoLayersOutlines = 3, /* Fill bit0/2, Outline bit1/3 */ + TwoLayers = 4, /* Fill bit0/1 and copied to bit2/3 */ + TwoLayersOutlines2 = 8 /* Fill bit2/3, Outline bit0/1 */ + }; private: - ETexelFormat x0_fmt; - u16 x4_w; - u16 x6_h; - u32 x8_mips; - boo::ObjToken m_booTex; - boo::ObjToken m_paletteTex; - std::unique_ptr m_otex; - EFontType m_ftype = EFontType::None; + ETexelFormat x0_fmt; + u16 x4_w; + u16 x6_h; + u32 x8_mips; + boo::ObjToken m_booTex; + boo::ObjToken m_paletteTex; + std::unique_ptr m_otex; + EFontType m_ftype = EFontType::None; - size_t ComputeMippedTexelCount(); - size_t ComputeMippedBlockCountDXT1(); - void BuildI4FromGCN(CInputStream& in); - void BuildI8FromGCN(CInputStream& in); - void BuildIA4FromGCN(CInputStream& in); - void BuildIA8FromGCN(CInputStream& in); - void BuildC4FromGCN(CInputStream& in); - void BuildC8FromGCN(CInputStream& in); - void BuildC14X2FromGCN(CInputStream& in); - void BuildRGB565FromGCN(CInputStream& in); - void BuildRGB5A3FromGCN(CInputStream& in); - void BuildRGBA8FromGCN(CInputStream& in); - void BuildDXT1FromGCN(CInputStream& in); - void BuildRGBA8(const void* data, size_t length); - void BuildC8(const void* data, size_t length); - void BuildC8Font(const void* data, EFontType ftype); - void BuildDXT1(const void* data, size_t length); + size_t ComputeMippedTexelCount(); + size_t ComputeMippedBlockCountDXT1(); + void BuildI4FromGCN(CInputStream& in); + void BuildI8FromGCN(CInputStream& in); + void BuildIA4FromGCN(CInputStream& in); + void BuildIA8FromGCN(CInputStream& in); + void BuildC4FromGCN(CInputStream& in); + void BuildC8FromGCN(CInputStream& in); + void BuildC14X2FromGCN(CInputStream& in); + void BuildRGB565FromGCN(CInputStream& in); + void BuildRGB5A3FromGCN(CInputStream& in); + void BuildRGBA8FromGCN(CInputStream& in); + void BuildDXT1FromGCN(CInputStream& in); + void BuildRGBA8(const void* data, size_t length); + void BuildC8(const void* data, size_t length); + void BuildC8Font(const void* data, EFontType ftype); + void BuildDXT1(const void* data, size_t length); public: - CTexture(ETexelFormat, s16, s16, s32); - CTexture(std::unique_ptr&& in, u32 length, bool otex); - enum class EClampMode - { - None, - One - }; - ETexelFormat GetTexelFormat() const {return x0_fmt;} - ETexelFormat GetMemoryCardTexelFormat() const - {return x0_fmt == ETexelFormat::C8PC ? ETexelFormat::C8 : ETexelFormat::RGB5A3;} - u16 GetWidth() const {return x4_w;} - u16 GetHeight() const {return x6_h;} - u32 GetNumMips() const {return x8_mips;} - void Load(int slot, EClampMode clamp) const; - const boo::ObjToken& GetBooTexture() const {return m_booTex;} - const boo::ObjToken& GetPaletteTexture() const {return m_paletteTex;} - std::unique_ptr BuildMemoryCardTex(u32& sizeOut, ETexelFormat& fmtOut, - std::unique_ptr& paletteOut) const; - const boo::ObjToken& GetFontTexture(EFontType tp); + CTexture(ETexelFormat, s16, s16, s32); + CTexture(std::unique_ptr&& in, u32 length, bool otex); + enum class EClampMode { None, One }; + ETexelFormat GetTexelFormat() const { return x0_fmt; } + ETexelFormat GetMemoryCardTexelFormat() const { + return x0_fmt == ETexelFormat::C8PC ? ETexelFormat::C8 : ETexelFormat::RGB5A3; + } + u16 GetWidth() const { return x4_w; } + u16 GetHeight() const { return x6_h; } + u32 GetNumMips() const { return x8_mips; } + void Load(int slot, EClampMode clamp) const; + const boo::ObjToken& GetBooTexture() const { return m_booTex; } + const boo::ObjToken& GetPaletteTexture() const { return m_paletteTex; } + std::unique_ptr BuildMemoryCardTex(u32& sizeOut, ETexelFormat& fmtOut, std::unique_ptr& paletteOut) const; + const boo::ObjToken& GetFontTexture(EFontType tp); }; -CFactoryFnReturn FTextureFactory(const urde::SObjectTag& tag, - std::unique_ptr&& in, u32 len, - const urde::CVParamTransfer& vparms, - CObjectReference* selfRef); - -} +CFactoryFnReturn FTextureFactory(const urde::SObjectTag& tag, std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms, CObjectReference* selfRef); +} // namespace urde diff --git a/Runtime/Graphics/CTextureBoo.cpp b/Runtime/Graphics/CTextureBoo.cpp index d4433ba3b..ea4c76eea 100644 --- a/Runtime/Graphics/CTextureBoo.cpp +++ b/Runtime/Graphics/CTextureBoo.cpp @@ -3,1011 +3,855 @@ #include "CToken.hpp" #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CTextureBoo"); /* GX uses this upsampling technique to extract full 8-bit range */ -static inline uint8_t Convert3To8(uint8_t v) -{ - /* Swizzle bits: 00000123 -> 12312312 */ - return (v << 5) | (v << 2) | (v >> 1); +static inline uint8_t Convert3To8(uint8_t v) { + /* Swizzle bits: 00000123 -> 12312312 */ + return (v << 5) | (v << 2) | (v >> 1); } -static inline uint8_t Convert4To8(uint8_t v) -{ - /* Swizzle bits: 00001234 -> 12341234 */ - return (v << 4) | v; +static inline uint8_t Convert4To8(uint8_t v) { + /* Swizzle bits: 00001234 -> 12341234 */ + return (v << 4) | v; } -static inline uint8_t Convert5To8(uint8_t v) -{ - /* Swizzle bits: 00012345 -> 12345123 */ - return (v << 3) | (v >> 2); +static inline uint8_t Convert5To8(uint8_t v) { + /* Swizzle bits: 00012345 -> 12345123 */ + return (v << 3) | (v >> 2); } -static inline uint8_t Convert6To8(uint8_t v) -{ - /* Swizzle bits: 00123456 -> 12345612 */ - return (v << 2) | (v >> 4); +static inline uint8_t Convert6To8(uint8_t v) { + /* Swizzle bits: 00123456 -> 12345612 */ + return (v << 2) | (v >> 4); } -size_t CTexture::ComputeMippedTexelCount() -{ - size_t w = x4_w; - size_t h = x6_h; - size_t ret = w * h; - for (u32 i=x8_mips ; i>1 ; --i) - { - if (w > 1) - w /= 2; - if (h > 1) - h /= 2; - ret += w * h; - } - return ret; +size_t CTexture::ComputeMippedTexelCount() { + size_t w = x4_w; + size_t h = x6_h; + size_t ret = w * h; + for (u32 i = x8_mips; i > 1; --i) { + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + ret += w * h; + } + return ret; } -size_t CTexture::ComputeMippedBlockCountDXT1() -{ - size_t w = x4_w / 4; - size_t h = x6_h / 4; - size_t ret = w * h; - for (u32 i=x8_mips ; i>1 ; --i) - { - if (w > 1) - w /= 2; - if (h > 1) - h /= 2; - ret += w * h; - } - return ret; +size_t CTexture::ComputeMippedBlockCountDXT1() { + size_t w = x4_w / 4; + size_t h = x6_h / 4; + size_t ret = w * h; + for (u32 i = x8_mips; i > 1; --i) { + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + ret += w * h; + } + return ret; } -struct RGBA8 -{ - u8 r; - u8 g; - u8 b; - u8 a; +struct RGBA8 { + u8 r; + u8 g; + u8 b; + u8 a; }; -void CTexture::BuildI4FromGCN(CInputStream& in) -{ - size_t texelCount = ComputeMippedTexelCount(); - std::unique_ptr buf(new RGBA8[texelCount]); +void CTexture::BuildI4FromGCN(CInputStream& in) { + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf(new RGBA8[texelCount]); - int w = x4_w; - int h = x6_h; - RGBA8* targetMip = buf.get(); - for (u32 mip=0 ; mip> ((x&1)?0:4) & 0xf); - target[x].g = target[x].r; - target[x].b = target[x].r; - target[x].a = target[x].r; - } - } - } + int w = x4_w; + int h = x6_h; + RGBA8* targetMip = buf.get(); + for (u32 mip = 0; mip < x8_mips; ++mip) { + int bwidth = (w + 7) / 8; + int bheight = (h + 7) / 8; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 8; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 8; + for (int y = 0; y < 8; ++y) { + RGBA8* target = targetMip + (baseY + y) * w + baseX; + u8 source[4]; + in.readBytesToBuf(source, 4); + for (int x = 0; x < 8; ++x) { + target[x].r = Convert4To8(source[x / 2] >> ((x & 1) ? 0 : 4) & 0xf); + target[x].g = target[x].r; + target[x].b = target[x].r; + target[x].a = target[x].r; + } } - targetMip += w * h; - if (w > 1) - w /= 2; - if (h > 1) - h /= 2; + } } + targetMip += w * h; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * 4).get(); - return true; - } BooTrace); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + buf.get(), texelCount * 4) + .get(); + return true; + } BooTrace); } -void CTexture::BuildI8FromGCN(CInputStream& in) -{ - size_t texelCount = ComputeMippedTexelCount(); - std::unique_ptr buf(new RGBA8[texelCount]); +void CTexture::BuildI8FromGCN(CInputStream& in) { + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf(new RGBA8[texelCount]); - int w = x4_w; - int h = x6_h; - RGBA8* targetMip = buf.get(); - for (u32 mip=0 ; mip 1) - w /= 2; - if (h > 1) - h /= 2; + } } + targetMip += w * h; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * 4).get(); - return true; - } BooTrace); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + buf.get(), texelCount * 4) + .get(); + return true; + } BooTrace); } -void CTexture::BuildIA4FromGCN(CInputStream& in) -{ - size_t texelCount = ComputeMippedTexelCount(); - std::unique_ptr buf(new RGBA8[texelCount]); +void CTexture::BuildIA4FromGCN(CInputStream& in) { + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf(new RGBA8[texelCount]); - int w = x4_w; - int h = x6_h; - RGBA8* targetMip = buf.get(); - for (u32 mip=0 ; mip> 4 & 0xf); - target[x].r = intensity; - target[x].g = intensity; - target[x].b = intensity; - target[x].a = Convert4To8(source[x] & 0xf); - } - } - } + int w = x4_w; + int h = x6_h; + RGBA8* targetMip = buf.get(); + for (u32 mip = 0; mip < x8_mips; ++mip) { + int bwidth = (w + 7) / 8; + int bheight = (h + 3) / 4; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 4; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 8; + for (int y = 0; y < 4; ++y) { + RGBA8* target = targetMip + (baseY + y) * w + baseX; + u8 source[8]; + in.readBytesToBuf(source, 8); + for (int x = 0; x < 8; ++x) { + u8 intensity = Convert4To8(source[x] >> 4 & 0xf); + target[x].r = intensity; + target[x].g = intensity; + target[x].b = intensity; + target[x].a = Convert4To8(source[x] & 0xf); + } } - targetMip += w * h; - if (w > 1) - w /= 2; - if (h > 1) - h /= 2; + } } + targetMip += w * h; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * 4).get(); - return true; - } BooTrace); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + buf.get(), texelCount * 4) + .get(); + return true; + } BooTrace); } -void CTexture::BuildIA8FromGCN(CInputStream& in) -{ - size_t texelCount = ComputeMippedTexelCount(); - std::unique_ptr buf(new RGBA8[texelCount]); +void CTexture::BuildIA8FromGCN(CInputStream& in) { + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf(new RGBA8[texelCount]); - int w = x4_w; - int h = x6_h; - RGBA8* targetMip = buf.get(); - for (u32 mip=0 ; mip> 8; - target[x].r = intensity; - target[x].g = intensity; - target[x].b = intensity; - target[x].a = source[x] & 0xff; - } - } - } + int w = x4_w; + int h = x6_h; + RGBA8* targetMip = buf.get(); + for (u32 mip = 0; mip < x8_mips; ++mip) { + int bwidth = (w + 3) / 4; + int bheight = (h + 3) / 4; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 4; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 4; + for (int y = 0; y < 4; ++y) { + RGBA8* target = targetMip + (baseY + y) * w + baseX; + u16 source[4]; + in.readBytesToBuf(source, 8); + for (int x = 0; x < 4; ++x) { + u8 intensity = source[x] >> 8; + target[x].r = intensity; + target[x].g = intensity; + target[x].b = intensity; + target[x].a = source[x] & 0xff; + } } - targetMip += w * h; - if (w > 1) - w /= 2; - if (h > 1) - h /= 2; + } } + targetMip += w * h; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * 4).get(); - return true; - } BooTrace); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + buf.get(), texelCount * 4) + .get(); + return true; + } BooTrace); } -static std::vector DecodePalette(int numEntries, CInputStream& in) -{ - std::vector ret; - ret.reserve(numEntries); +static std::vector DecodePalette(int numEntries, CInputStream& in) { + std::vector ret; + ret.reserve(numEntries); - enum class EPaletteType - { - IA8, - RGB565, - RGB5A3 - }; + enum class EPaletteType { IA8, RGB565, RGB5A3 }; - EPaletteType format = EPaletteType(in.readUint32Big()); - in.readUint32Big(); - switch (format) - { - case EPaletteType::IA8: - { - for (int e=0 ; e> 11 & 0x1f), Convert6To8(texel >> 5 & 0x3f), Convert5To8(texel & 0x1f), 0xff}); + } + break; + } + case EPaletteType::RGB5A3: { + for (int e = 0; e < numEntries; ++e) { + u16 texel = in.readUint16Big(); + if (texel & 0x8000) { + ret.push_back( + {Convert5To8(texel >> 10 & 0x1f), Convert5To8(texel >> 5 & 0x1f), Convert5To8(texel & 0x1f), 0xff}); + } else { + ret.push_back({Convert4To8(texel >> 8 & 0xf), Convert4To8(texel >> 4 & 0xf), Convert4To8(texel & 0xf), + Convert3To8(texel >> 12 & 0x7)}); + } + } + break; + } + } + return ret; +} + +void CTexture::BuildC4FromGCN(CInputStream& in) { + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf(new RGBA8[texelCount]); + std::vector palette = DecodePalette(16, in); + + int w = x4_w; + int h = x6_h; + RGBA8* targetMip = buf.get(); + for (u32 mip = 0; mip < x8_mips; ++mip) { + int bwidth = (w + 7) / 8; + int bheight = (h + 7) / 8; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 8; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 8; + for (int y = 0; y < 8; ++y) { + RGBA8* target = targetMip + (baseY + y) * w + baseX; + u8 source[4]; + in.readBytesToBuf(source, 4); + for (int x = 0; x < 8; ++x) + target[x] = palette[source[x / 2] >> ((x & 1) ? 0 : 4) & 0xf]; + } + } + } + targetMip += w * h; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } + + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + buf.get(), texelCount * 4) + .get(); + return true; + } BooTrace); +} + +void CTexture::BuildC8FromGCN(CInputStream& in) { + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf(new RGBA8[texelCount]); + std::vector palette = DecodePalette(256, in); + + int w = x4_w; + int h = x6_h; + RGBA8* targetMip = buf.get(); + for (u32 mip = 0; mip < x8_mips; ++mip) { + int bwidth = (w + 7) / 8; + int bheight = (h + 3) / 4; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 4; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 8; + for (int y = 0; y < 4; ++y) { + RGBA8* target = targetMip + (baseY + y) * w + baseX; + u8 source[8]; + in.readBytesToBuf(source, 8); + for (int x = 0; x < 8; ++x) + target[x] = palette[source[x]]; + } + } + } + targetMip += w * h; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } + + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + buf.get(), texelCount * 4) + .get(); + return true; + } BooTrace); +} + +void CTexture::BuildC14X2FromGCN(CInputStream& in) {} + +void CTexture::BuildRGB565FromGCN(CInputStream& in) { + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf(new RGBA8[texelCount]); + + int w = x4_w; + int h = x6_h; + RGBA8* targetMip = buf.get(); + for (u32 mip = 0; mip < x8_mips; ++mip) { + int bwidth = (w + 3) / 4; + int bheight = (h + 3) / 4; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 4; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 4; + for (int y = 0; y < 4; ++y) { + RGBA8* target = targetMip + (baseY + y) * w + baseX; + for (int x = 0; x < 4; ++x) { u16 texel = in.readUint16Big(); - ret.push_back({Convert5To8(texel >> 11 & 0x1f), - Convert6To8(texel >> 5 & 0x3f), - Convert5To8(texel & 0x1f), - 0xff}); + target[x].r = Convert5To8(texel >> 11 & 0x1f); + target[x].g = Convert6To8(texel >> 5 & 0x3f); + target[x].b = Convert5To8(texel & 0x1f); + target[x].a = 0xff; + } } - break; + } } - case EPaletteType::RGB5A3: - { - for (int e=0 ; e 1) + w /= 2; + if (h > 1) + h /= 2; + } + + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + buf.get(), texelCount * 4) + .get(); + return true; + } BooTrace); +} + +void CTexture::BuildRGB5A3FromGCN(CInputStream& in) { + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf(new RGBA8[texelCount]); + + int w = x4_w; + int h = x6_h; + RGBA8* targetMip = buf.get(); + for (u32 mip = 0; mip < x8_mips; ++mip) { + int bwidth = (w + 3) / 4; + int bheight = (h + 3) / 4; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 4; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 4; + for (int y = 0; y < 4; ++y) { + RGBA8* target = targetMip + (baseY + y) * w + baseX; + for (int x = 0; x < 4; ++x) { u16 texel = in.readUint16Big(); - if (texel & 0x8000) - { - ret.push_back({Convert5To8(texel >> 10 & 0x1f), - Convert5To8(texel >> 5 & 0x1f), - Convert5To8(texel & 0x1f), - 0xff}); - } - else - { - ret.push_back({Convert4To8(texel >> 8 & 0xf), - Convert4To8(texel >> 4 & 0xf), - Convert4To8(texel & 0xf), - Convert3To8(texel >> 12 & 0x7)}); + if (texel & 0x8000) { + target[x].r = Convert5To8(texel >> 10 & 0x1f); + target[x].g = Convert5To8(texel >> 5 & 0x1f); + target[x].b = Convert5To8(texel & 0x1f); + target[x].a = 0xff; + } else { + target[x].r = Convert4To8(texel >> 8 & 0xf); + target[x].g = Convert4To8(texel >> 4 & 0xf); + target[x].b = Convert4To8(texel & 0xf); + target[x].a = Convert3To8(texel >> 12 & 0x7); } + } } - break; + } } - } - return ret; + targetMip += w * h; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } + + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + buf.get(), texelCount * 4) + .get(); + return true; + } BooTrace); } -void CTexture::BuildC4FromGCN(CInputStream& in) -{ - size_t texelCount = ComputeMippedTexelCount(); - std::unique_ptr buf(new RGBA8[texelCount]); - std::vector palette = DecodePalette(16, in); +void CTexture::BuildRGBA8FromGCN(CInputStream& in) { + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf(new RGBA8[texelCount]); - int w = x4_w; - int h = x6_h; - RGBA8* targetMip = buf.get(); - for (u32 mip=0 ; mip> ((x&1)?0:4) & 0xf]; - } + int w = x4_w; + int h = x6_h; + RGBA8* targetMip = buf.get(); + for (u32 mip = 0; mip < x8_mips; ++mip) { + int bwidth = (w + 3) / 4; + int bheight = (h + 3) / 4; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 4; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 4; + for (int c = 0; c < 2; ++c) { + for (int y = 0; y < 4; ++y) { + RGBA8* target = targetMip + (baseY + y) * w + baseX; + u8 source[8]; + in.readBytesToBuf(source, 8); + for (int x = 0; x < 4; ++x) { + if (c) { + target[x].g = source[x * 2]; + target[x].b = source[x * 2 + 1]; + } else { + target[x].a = source[x * 2]; + target[x].r = source[x * 2 + 1]; + } } + } } - targetMip += w * h; - if (w > 1) - w /= 2; - if (h > 1) - h /= 2; + } } + targetMip += w * h; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * 4).get(); - return true; - } BooTrace); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + buf.get(), texelCount * 4) + .get(); + return true; + } BooTrace); } -void CTexture::BuildC8FromGCN(CInputStream& in) -{ - size_t texelCount = ComputeMippedTexelCount(); - std::unique_ptr buf(new RGBA8[texelCount]); - std::vector palette = DecodePalette(256, in); - - int w = x4_w; - int h = x6_h; - RGBA8* targetMip = buf.get(); - for (u32 mip=0 ; mip 1) - w /= 2; - if (h > 1) - h /= 2; - } - - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * 4).get(); - return true; - } BooTrace); -} - -void CTexture::BuildC14X2FromGCN(CInputStream& in) -{ - -} - -void CTexture::BuildRGB565FromGCN(CInputStream& in) -{ - size_t texelCount = ComputeMippedTexelCount(); - std::unique_ptr buf(new RGBA8[texelCount]); - - int w = x4_w; - int h = x6_h; - RGBA8* targetMip = buf.get(); - for (u32 mip=0 ; mip> 11 & 0x1f); - target[x].g = Convert6To8(texel >> 5 & 0x3f); - target[x].b = Convert5To8(texel & 0x1f); - target[x].a = 0xff; - } - } - } - } - targetMip += w * h; - if (w > 1) - w /= 2; - if (h > 1) - h /= 2; - } - - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * 4).get(); - return true; - } BooTrace); -} - -void CTexture::BuildRGB5A3FromGCN(CInputStream& in) -{ - size_t texelCount = ComputeMippedTexelCount(); - std::unique_ptr buf(new RGBA8[texelCount]); - - int w = x4_w; - int h = x6_h; - RGBA8* targetMip = buf.get(); - for (u32 mip=0 ; mip> 10 & 0x1f); - target[x].g = Convert5To8(texel >> 5 & 0x1f); - target[x].b = Convert5To8(texel & 0x1f); - target[x].a = 0xff; - } - else - { - target[x].r = Convert4To8(texel >> 8 & 0xf); - target[x].g = Convert4To8(texel >> 4 & 0xf); - target[x].b = Convert4To8(texel & 0xf); - target[x].a = Convert3To8(texel >> 12 & 0x7); - } - } - } - } - } - targetMip += w * h; - if (w > 1) - w /= 2; - if (h > 1) - h /= 2; - } - - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * 4).get(); - return true; - } BooTrace); -} - -void CTexture::BuildRGBA8FromGCN(CInputStream& in) -{ - size_t texelCount = ComputeMippedTexelCount(); - std::unique_ptr buf(new RGBA8[texelCount]); - - int w = x4_w; - int h = x6_h; - RGBA8* targetMip = buf.get(); - for (u32 mip=0 ; mip 1) - w /= 2; - if (h > 1) - h /= 2; - } - - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * 4).get(); - return true; - } BooTrace); -} - -struct DXT1Block -{ - uint16_t color1; - uint16_t color2; - uint8_t lines[4]; +struct DXT1Block { + uint16_t color1; + uint16_t color2; + uint8_t lines[4]; }; -void CTexture::BuildDXT1FromGCN(CInputStream& in) -{ - size_t blockCount = ComputeMippedBlockCountDXT1(); - std::unique_ptr buf(new DXT1Block[blockCount]); +void CTexture::BuildDXT1FromGCN(CInputStream& in) { + size_t blockCount = ComputeMippedBlockCountDXT1(); + std::unique_ptr buf(new DXT1Block[blockCount]); - int w = x4_w / 4; - int h = x6_h / 4; - DXT1Block* targetMip = buf.get(); - for (u32 mip=0 ; mip> 2) & 0x3; - ind[1] = (packed >> 4) & 0x3; - ind[0] = (packed >> 6) & 0x3; - target[x].lines[i] = ind[0] | (ind[1] << 2) | (ind[2] << 4) | (ind[3] << 6); - } - } - } + int w = x4_w / 4; + int h = x6_h / 4; + DXT1Block* targetMip = buf.get(); + for (u32 mip = 0; mip < x8_mips; ++mip) { + int bwidth = (w + 1) / 2; + int bheight = (h + 1) / 2; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 2; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 2; + for (int y = 0; y < 2; ++y) { + DXT1Block* target = targetMip + (baseY + y) * w + baseX; + DXT1Block source[2]; + in.readBytesToBuf(source, 16); + for (int x = 0; x < 2; ++x) { + target[x].color1 = hecl::SBig(source[x].color1); + target[x].color2 = hecl::SBig(source[x].color2); + for (u32 i = 0; i < 4; ++i) { + u8 ind[4]; + u8 packed = source[x].lines[i]; + ind[3] = packed & 0x3; + ind[2] = (packed >> 2) & 0x3; + ind[1] = (packed >> 4) & 0x3; + ind[0] = (packed >> 6) & 0x3; + target[x].lines[i] = ind[0] | (ind[1] << 2) | (ind[2] << 4) | (ind[3] << 6); } + } } - targetMip += w * h; - - if (w > 1) - w /= 2; - if (h > 1) - h /= 2; + } } + targetMip += w * h; - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::DXT1, - boo::TextureClampMode::Repeat, buf.get(), blockCount * 8).get(); - return true; - } BooTrace); + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } + + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::DXT1, boo::TextureClampMode::Repeat, + buf.get(), blockCount * 8) + .get(); + return true; + } BooTrace); } -void CTexture::BuildRGBA8(const void* data, size_t length) -{ - size_t texelCount = ComputeMippedTexelCount(); - size_t expectedSize = texelCount * 4; - if (expectedSize > length) - Log.report(logvisor::Fatal, "insufficient TXTR length (%" PRISize "/%" PRISize ")", - length, expectedSize); +void CTexture::BuildRGBA8(const void* data, size_t length) { + size_t texelCount = ComputeMippedTexelCount(); + size_t expectedSize = texelCount * 4; + if (expectedSize > length) + Log.report(logvisor::Fatal, "insufficient TXTR length (%" PRISize "/%" PRISize ")", length, expectedSize); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, data, expectedSize).get(); - return true; - } BooTrace); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, data, + expectedSize) + .get(); + return true; + } BooTrace); } -void CTexture::BuildC8(const void* data, size_t length) -{ - size_t texelCount = ComputeMippedTexelCount(); - if (texelCount > length) - Log.report(logvisor::Fatal, "insufficient TXTR length (%" PRISize "/%" PRISize ")", - length, texelCount); - - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - uint32_t nentries = hecl::SBig(*reinterpret_cast(data)); - const u8* paletteTexels = reinterpret_cast(data) + 4; - const u8* texels = reinterpret_cast(data) + 4 + nentries * 4; - m_paletteTex = ctx.newStaticTexture(nentries, 1, 1, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, paletteTexels, nentries * 4).get(); - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::I8, - boo::TextureClampMode::Repeat, texels, texelCount).get(); - return true; - } BooTrace); -} - -void CTexture::BuildC8Font(const void* data, EFontType ftype) -{ - size_t texelCount = ComputeMippedTexelCount(); - - size_t layerCount = 1; - switch (ftype) - { - case EFontType::OneLayer: - case EFontType::OneLayerOutline: - layerCount = 1; - break; - case EFontType::FourLayers: - layerCount = 4; - break; - case EFontType::TwoLayersOutlines: - case EFontType::TwoLayers: - case EFontType::TwoLayersOutlines2: - layerCount = 2; - break; - default: break; - } +void CTexture::BuildC8(const void* data, size_t length) { + size_t texelCount = ComputeMippedTexelCount(); + if (texelCount > length) + Log.report(logvisor::Fatal, "insufficient TXTR length (%" PRISize "/%" PRISize ")", length, texelCount); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { uint32_t nentries = hecl::SBig(*reinterpret_cast(data)); + const u8* paletteTexels = reinterpret_cast(data) + 4; const u8* texels = reinterpret_cast(data) + 4 + nentries * 4; - std::unique_ptr buf(new RGBA8[texelCount * layerCount]); - memset(buf.get(), 0, texelCount * layerCount * 4); + m_paletteTex = ctx.newStaticTexture(nentries, 1, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, + paletteTexels, nentries * 4) + .get(); + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::I8, boo::TextureClampMode::Repeat, texels, + texelCount) + .get(); + return true; + } BooTrace); +} - size_t w = x4_w; - size_t h = x6_h; - RGBA8* bufCur = buf.get(); - for (size_t i=0 ; i 1) - w /= 2; - if (h > 1) - h /= 2; +void CTexture::BuildC8Font(const void* data, EFontType ftype) { + size_t texelCount = ComputeMippedTexelCount(); + + size_t layerCount = 1; + switch (ftype) { + case EFontType::OneLayer: + case EFontType::OneLayerOutline: + layerCount = 1; + break; + case EFontType::FourLayers: + layerCount = 4; + break; + case EFontType::TwoLayersOutlines: + case EFontType::TwoLayers: + case EFontType::TwoLayersOutlines2: + layerCount = 2; + break; + default: + break; + } + + uint32_t nentries = hecl::SBig(*reinterpret_cast(data)); + const u8* texels = reinterpret_cast(data) + 4 + nentries * 4; + std::unique_ptr buf(new RGBA8[texelCount * layerCount]); + memset(buf.get(), 0, texelCount * layerCount * 4); + + size_t w = x4_w; + size_t h = x6_h; + RGBA8* bufCur = buf.get(); + for (size_t i = 0; i < x8_mips; ++i) { + size_t tCount = w * h; + RGBA8* l0 = bufCur; + RGBA8* l1 = bufCur + tCount; + RGBA8* l2 = bufCur + tCount * 2; + RGBA8* l3 = bufCur + tCount * 3; + for (size_t j = 0; j < tCount; ++j) { + u8 texel = texels[j]; + switch (ftype) { + case EFontType::OneLayer: + l0[j].r = (texel & 0x1) ? 0xff : 0; + l0[j].a = 0xff; + break; + case EFontType::OneLayerOutline: + l0[j].r = (texel & 0x1) ? 0xff : 0; + l0[j].g = (texel & 0x2) ? 0xff : 0; + l0[j].a = 0xff; + break; + case EFontType::FourLayers: + l0[j].r = (texel & 0x1) ? 0xff : 0; + l0[j].a = 0xff; + l1[j].r = (texel & 0x2) ? 0xff : 0; + l1[j].a = 0xff; + l2[j].r = (texel & 0x4) ? 0xff : 0; + l2[j].a = 0xff; + l3[j].r = (texel & 0x8) ? 0xff : 0; + l3[j].a = 0xff; + break; + case EFontType::TwoLayersOutlines: + l0[j].r = (texel & 0x1) ? 0xff : 0; + l0[j].g = (texel & 0x2) ? 0xff : 0; + l0[j].a = 0xff; + l1[j].r = (texel & 0x4) ? 0xff : 0; + l1[j].g = (texel & 0x8) ? 0xff : 0; + l1[j].a = 0xff; + break; + case EFontType::TwoLayers: + l0[j].r = (texel & 0x1) ? 0xff : 0; + l0[j].a = 0xff; + l1[j].r = (texel & 0x2) ? 0xff : 0; + l1[j].a = 0xff; + break; + case EFontType::TwoLayersOutlines2: + l0[j].r = (texel & 0x4) ? 0xff : 0; + l0[j].g = (texel & 0x1) ? 0xff : 0; + l0[j].a = 0xff; + l1[j].r = (texel & 0x8) ? 0xff : 0; + l1[j].g = (texel & 0x2) ? 0xff : 0; + l1[j].a = 0xff; + break; + default: + break; + } } + texels += tCount; + bufCur += tCount * layerCount; + if (w > 1) + w /= 2; + if (h > 1) + h /= 2; + } - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticArrayTexture(x4_w, x6_h, layerCount, x8_mips, boo::TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, buf.get(), texelCount * layerCount * 4).get(); - return true; - } BooTrace); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = ctx.newStaticArrayTexture(x4_w, x6_h, layerCount, x8_mips, boo::TextureFormat::RGBA8, + boo::TextureClampMode::Repeat, buf.get(), texelCount * layerCount * 4) + .get(); + return true; + } BooTrace); } -void CTexture::BuildDXT1(const void* data, size_t length) -{ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::DXT1, - boo::TextureClampMode::Repeat, data, length).get(); - return true; - } BooTrace); +void CTexture::BuildDXT1(const void* data, size_t length) { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_booTex = + ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::DXT1, boo::TextureClampMode::Repeat, data, length) + .get(); + return true; + } BooTrace); } -CTexture::CTexture(ETexelFormat fmt, s16 w, s16 h, s32 mips) - : x0_fmt(fmt) - , x4_w(w) - , x6_h(h) - , x8_mips(mips) -{ - /* - x64_ = sMangleMipmaps; - InitBitmapBuffers(fmt, w, h, mips); - InitTextureObjs(); - */ +CTexture::CTexture(ETexelFormat fmt, s16 w, s16 h, s32 mips) : x0_fmt(fmt), x4_w(w), x6_h(h), x8_mips(mips) { + /* + x64_ = sMangleMipmaps; + InitBitmapBuffers(fmt, w, h, mips); + InitTextureObjs(); + */ } -CTexture::CTexture(std::unique_ptr&& in, u32 length, bool otex) -{ - std::unique_ptr owned = std::move(in); - athena::io::MemoryReader r(owned.get(), length); - x0_fmt = ETexelFormat(r.readUint32Big()); - x4_w = r.readUint16Big(); - x6_h = r.readUint16Big(); - x8_mips = r.readUint32Big(); +CTexture::CTexture(std::unique_ptr&& in, u32 length, bool otex) { + std::unique_ptr owned = std::move(in); + athena::io::MemoryReader r(owned.get(), length); + x0_fmt = ETexelFormat(r.readUint32Big()); + x4_w = r.readUint16Big(); + x6_h = r.readUint16Big(); + x8_mips = r.readUint32Big(); - switch (x0_fmt) - { - case ETexelFormat::I4: - BuildI4FromGCN(r); - break; - case ETexelFormat::I8: - BuildI8FromGCN(r); - break; - case ETexelFormat::IA4: - BuildIA4FromGCN(r); - break; - case ETexelFormat::IA8: - BuildIA8FromGCN(r); - break; - case ETexelFormat::C4: - BuildC4FromGCN(r); - break; - case ETexelFormat::C8: - BuildC8FromGCN(r); - break; - case ETexelFormat::C14X2: - BuildC14X2FromGCN(r); - break; - case ETexelFormat::RGB565: - BuildRGB565FromGCN(r); - break; - case ETexelFormat::RGB5A3: - BuildRGB5A3FromGCN(r); - break; - case ETexelFormat::RGBA8: - BuildRGBA8FromGCN(r); - break; - case ETexelFormat::CMPR: - BuildDXT1FromGCN(r); - break; - case ETexelFormat::RGBA8PC: - BuildRGBA8(owned.get() + 12, length - 12); - break; - case ETexelFormat::C8PC: - BuildC8(owned.get() + 12, length - 12); - otex = true; - break; - case ETexelFormat::CMPRPC: - BuildDXT1(owned.get() + 12, length - 12); - break; - default: - Log.report(logvisor::Fatal, "invalid texture type %d for boo", int(x0_fmt)); - } + switch (x0_fmt) { + case ETexelFormat::I4: + BuildI4FromGCN(r); + break; + case ETexelFormat::I8: + BuildI8FromGCN(r); + break; + case ETexelFormat::IA4: + BuildIA4FromGCN(r); + break; + case ETexelFormat::IA8: + BuildIA8FromGCN(r); + break; + case ETexelFormat::C4: + BuildC4FromGCN(r); + break; + case ETexelFormat::C8: + BuildC8FromGCN(r); + break; + case ETexelFormat::C14X2: + BuildC14X2FromGCN(r); + break; + case ETexelFormat::RGB565: + BuildRGB565FromGCN(r); + break; + case ETexelFormat::RGB5A3: + BuildRGB5A3FromGCN(r); + break; + case ETexelFormat::RGBA8: + BuildRGBA8FromGCN(r); + break; + case ETexelFormat::CMPR: + BuildDXT1FromGCN(r); + break; + case ETexelFormat::RGBA8PC: + BuildRGBA8(owned.get() + 12, length - 12); + break; + case ETexelFormat::C8PC: + BuildC8(owned.get() + 12, length - 12); + otex = true; + break; + case ETexelFormat::CMPRPC: + BuildDXT1(owned.get() + 12, length - 12); + break; + default: + Log.report(logvisor::Fatal, "invalid texture type %d for boo", int(x0_fmt)); + } - if (otex) - m_otex = std::move(owned); + if (otex) + m_otex = std::move(owned); } -void CTexture::Load(int slot, EClampMode clamp) const -{ - -} +void CTexture::Load(int slot, EClampMode clamp) const {} std::unique_ptr CTexture::BuildMemoryCardTex(u32& sizeOut, ETexelFormat& fmtOut, - std::unique_ptr& paletteOut) const -{ - if (!m_otex) - Log.report(logvisor::Fatal, "MemoryCard TXTR not loaded with 'otex'"); + std::unique_ptr& paletteOut) const { + if (!m_otex) + Log.report(logvisor::Fatal, "MemoryCard TXTR not loaded with 'otex'"); - size_t texelCount = x4_w * x6_h; - std::unique_ptr ret; - if (x0_fmt == ETexelFormat::RGBA8PC) - { - sizeOut = texelCount * 2; - fmtOut = ETexelFormat::RGB5A3; - ret.reset(new u8[sizeOut]); - u16* texel = reinterpret_cast(ret.get()); + size_t texelCount = x4_w * x6_h; + std::unique_ptr ret; + if (x0_fmt == ETexelFormat::RGBA8PC) { + sizeOut = texelCount * 2; + fmtOut = ETexelFormat::RGB5A3; + ret.reset(new u8[sizeOut]); + u16* texel = reinterpret_cast(ret.get()); - int w = x4_w; - int h = x6_h; - const RGBA8* sourceMip = reinterpret_cast(m_otex.get() + 12); - int bwidth = (w + 3) / 4; - int bheight = (h + 3) / 4; - for (int by=0 ; by> 3 << 10) | - (source[x].g >> 3 << 5) | - (source[x].b >> 3))); - } - else - { - *texel++ = hecl::SBig(u16((source[x].r >> 4 << 8) | - (source[x].g >> 4 << 4) | - (source[x].b >> 4) | - (source[x].a >> 5 << 12))); - } - } - } + int w = x4_w; + int h = x6_h; + const RGBA8* sourceMip = reinterpret_cast(m_otex.get() + 12); + int bwidth = (w + 3) / 4; + int bheight = (h + 3) / 4; + for (int by = 0; by < bheight; ++by) { + int baseY = by * 4; + for (int bx = 0; bx < bwidth; ++bx) { + int baseX = bx * 4; + for (int y = 0; y < 4; ++y) { + const RGBA8* source = sourceMip + (x6_h - (baseY + y) - 1) * w + baseX; + for (int x = 0; x < 4; ++x) { + if (source[x].a == 0xff) { + *texel++ = hecl::SBig(u16((source[x].r >> 3 << 10) | (source[x].g >> 3 << 5) | (source[x].b >> 3))); + } else { + *texel++ = hecl::SBig(u16((source[x].r >> 4 << 8) | (source[x].g >> 4 << 4) | (source[x].b >> 4) | + (source[x].a >> 5 << 12))); } + } } + } } - else if (x0_fmt == ETexelFormat::C8PC) - { - sizeOut = texelCount; - fmtOut = ETexelFormat::C8; - ret.reset(new u8[sizeOut]); - paletteOut.reset(new u8[512]); - u8* texel = ret.get(); - u16* paletteColors = reinterpret_cast(paletteOut.get()); + } else if (x0_fmt == ETexelFormat::C8PC) { + sizeOut = texelCount; + fmtOut = ETexelFormat::C8; + ret.reset(new u8[sizeOut]); + paletteOut.reset(new u8[512]); + u8* texel = ret.get(); + u16* paletteColors = reinterpret_cast(paletteOut.get()); - int w = x4_w; - int h = x6_h; - const u8* data = m_otex.get() + 12; - u32 nentries = hecl::SBig(*reinterpret_cast(data)); - const RGBA8* paletteTexels = reinterpret_cast(data + 4); - const u8* sourceMip = data + 4 + nentries * 4; + int w = x4_w; + int h = x6_h; + const u8* data = m_otex.get() + 12; + u32 nentries = hecl::SBig(*reinterpret_cast(data)); + const RGBA8* paletteTexels = reinterpret_cast(data + 4); + const u8* sourceMip = data + 4 + nentries * 4; - for (int i=0; i<256; ++i) - { - u16& color = paletteColors[i]; - if (i >= nentries) - { - color = 0; - } - else - { - const RGBA8& colorIn = paletteTexels[i]; - if (colorIn.a == 0xff) - { - color = hecl::SBig(u16((colorIn.r >> 3 << 10) | - (colorIn.g >> 3 << 5) | - (colorIn.b >> 3) | 0x8000)); - } - else - { - color = hecl::SBig(u16((colorIn.r >> 4 << 8) | - (colorIn.g >> 4 << 4) | - (colorIn.b >> 4) | - (colorIn.a >> 5 << 12))); - } - } + for (int i = 0; i < 256; ++i) { + u16& color = paletteColors[i]; + if (i >= nentries) { + color = 0; + } else { + const RGBA8& colorIn = paletteTexels[i]; + if (colorIn.a == 0xff) { + color = hecl::SBig(u16((colorIn.r >> 3 << 10) | (colorIn.g >> 3 << 5) | (colorIn.b >> 3) | 0x8000)); + } else { + color = hecl::SBig( + u16((colorIn.r >> 4 << 8) | (colorIn.g >> 4 << 4) | (colorIn.b >> 4) | (colorIn.a >> 5 << 12))); } + } + } - int bwidth = (w + 7) / 8; - int bheight = (h + 3) / 4; - for (int by=0 ; by& CTexture::GetFontTexture(EFontType tp) -{ - if (m_ftype != tp && x0_fmt == ETexelFormat::C8PC) - { - m_ftype = tp; - BuildC8Font(m_otex.get() + 12, m_ftype); - } - return m_booTex; +const boo::ObjToken& CTexture::GetFontTexture(EFontType tp) { + if (m_ftype != tp && x0_fmt == ETexelFormat::C8PC) { + m_ftype = tp; + BuildC8Font(m_otex.get() + 12, m_ftype); + } + return m_booTex; } -CFactoryFnReturn FTextureFactory(const urde::SObjectTag& tag, - std::unique_ptr&& in, u32 len, - const urde::CVParamTransfer& vparms, - CObjectReference* selfRef) -{ - u32 u32Owned = vparms.GetOwnedObj(); - return TToken::GetIObjObjectFor(std::make_unique(std::move(in), len, - u32Owned == SBIG('OTEX'))); +CFactoryFnReturn FTextureFactory(const urde::SObjectTag& tag, std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms, CObjectReference* selfRef) { + u32 u32Owned = vparms.GetOwnedObj(); + return TToken::GetIObjObjectFor(std::make_unique(std::move(in), len, u32Owned == SBIG('OTEX'))); } -} +} // namespace urde diff --git a/Runtime/Graphics/CVertexMorphEffect.cpp b/Runtime/Graphics/CVertexMorphEffect.cpp index b270a67b8..d0b6f8d0d 100644 --- a/Runtime/Graphics/CVertexMorphEffect.cpp +++ b/Runtime/Graphics/CVertexMorphEffect.cpp @@ -1,21 +1,14 @@ #include "CVertexMorphEffect.hpp" #include "Character/CSkinRules.hpp" -namespace urde -{ +namespace urde { -CVertexMorphEffect::CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, - float diagExtent, float f2, CRandom16& random) -: x0_(v1), x20_diagExtent(diagExtent), x24_random(random) -{ - -} +CVertexMorphEffect::CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, float diagExtent, + float f2, CRandom16& random) +: x0_(v1), x20_diagExtent(diagExtent), x24_random(random) {} void CVertexMorphEffect::MorphVertices(std::vector>& vn, const float* magnitudes, const TLockedToken& skinRules, - const CPoseAsTransforms& pose) const -{ + const CPoseAsTransforms& pose) const {} -} - -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/Graphics/CVertexMorphEffect.hpp b/Runtime/Graphics/CVertexMorphEffect.hpp index e5ab35429..afb380027 100644 --- a/Runtime/Graphics/CVertexMorphEffect.hpp +++ b/Runtime/Graphics/CVertexMorphEffect.hpp @@ -3,32 +3,29 @@ #include "CToken.hpp" #include "Character/CPoseAsTransforms.hpp" -namespace urde -{ +namespace urde { class CSkinRules; class CRandom16; -class CVertexMorphEffect -{ - zeus::CUnitVector3f x0_; - float xc_ = 0.f; - float x10_ = 0.f; - float x14_ = 0.f; - float x18_ = 0.f; - float x1c_ = 0.f; - float x20_diagExtent; - CRandom16& x24_random; - std::vector x28_; - std::vector x38_; +class CVertexMorphEffect { + zeus::CUnitVector3f x0_; + float xc_ = 0.f; + float x10_ = 0.f; + float x14_ = 0.f; + float x18_ = 0.f; + float x1c_ = 0.f; + float x20_diagExtent; + CRandom16& x24_random; + std::vector x28_; + std::vector x38_; + public: - CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, - float diagExtent, float f2, CRandom16& random); - void MorphVertices(std::vector>& vn, - const float* magnitudes, const TLockedToken& skinRules, - const CPoseAsTransforms& pose) const; - void Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration) {} - void Update(float) {} + CVertexMorphEffect(const zeus::CUnitVector3f& v1, const zeus::CVector3f& v2, float diagExtent, float f2, + CRandom16& random); + void MorphVertices(std::vector>& vn, const float* magnitudes, + const TLockedToken& skinRules, const CPoseAsTransforms& pose) const; + void Reset(const zeus::CVector3f& dir, const zeus::CVector3f& pos, float duration) {} + void Update(float) {} }; -} - +} // namespace urde diff --git a/Runtime/Graphics/IRenderer.hpp b/Runtime/Graphics/IRenderer.hpp index d19b1df9e..b56afaad5 100644 --- a/Runtime/Graphics/IRenderer.hpp +++ b/Runtime/Graphics/IRenderer.hpp @@ -10,8 +10,7 @@ #include "zeus/CRectangle.hpp" #include "CGraphics.hpp" -namespace urde -{ +namespace urde { class CMetroidModelInstance; class CLight; class CAreaOctTree; @@ -23,91 +22,80 @@ class CPVSVisSet; struct CAreaRenderOctTree; struct CModelFlags; -class IRenderer -{ +class IRenderer { public: - typedef void(*TDrawableCallback)(const void*, const void*, int); - using TReflectionCallback = std::function; + typedef void (*TDrawableCallback)(const void*, const void*, int); + using TReflectionCallback = std::function; - enum class EDrawableSorting - { - SortedCallback, - UnsortedCallback - }; - enum class EDebugOption - { - Zero, - One - }; - enum class EPrimitiveType - { - }; + enum class EDrawableSorting { SortedCallback, UnsortedCallback }; + enum class EDebugOption { Zero, One }; + enum class EPrimitiveType {}; - virtual ~IRenderer() = default; - virtual void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int, - const SShader*)=0; - virtual void EnablePVS(const CPVSVisSet&, u32)=0; - virtual void DisablePVS()=0; - virtual void RemoveStaticGeometry(const std::vector*)=0; - virtual void DrawAreaGeometry(int areaIdx, int mask, int targetMask)=0; - virtual void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender = false)=0; - virtual void DrawSortedGeometry(int areaIdx, int mask, int targetMask)=0; - virtual void DrawStaticGeometry(int areaIdx, int mask, int targetMask)=0; - virtual void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly)=0; - virtual void PostRenderFogs()=0; - virtual void AddParticleGen(const CParticleGen&)=0; - virtual void AddParticleGen(const CParticleGen&, const zeus::CVector3f&, const zeus::CAABox&)=0; - virtual void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int)=0; - virtual void AddDrawable(void const *, const zeus::CVector3f&, const zeus::CAABox&, int, EDrawableSorting)=0; - virtual void SetDrawableCallback(TDrawableCallback, const void*)=0; - virtual void SetWorldViewpoint(const zeus::CTransform&)=0; - virtual void SetPerspective(float, float, float, float, float)=0; - virtual void SetPerspective(float, float, float, float)=0; - virtual std::pair SetViewportOrtho(bool, float, float)=0; - virtual void SetClippingPlanes(const zeus::CFrustum&)=0; - virtual void SetViewport(int, int, int, int)=0; - //virtual void SetDepthReadWrite(bool, bool)=0; - //virtual void SetBlendMode_AdditiveAlpha()=0; - //virtual void SetBlendMode_AlphaBlended()=0; - //virtual void SetBlendMode_NoColorWrite()=0; - //virtual void SetBlendMode_ColorMultiply()=0; - //virtual void SetBlendMode_InvertDst()=0; - //virtual void SetBlendMode_InvertSrc()=0; - //virtual void SetBlendMode_Replace()=0; - //virtual void SetBlendMode_AdditiveDestColor()=0; - virtual void SetDebugOption(EDebugOption, int)=0; - virtual void BeginScene()=0; - virtual void EndScene()=0; - //virtual void BeginPrimitive(EPrimitiveType, int)=0; - //virtual void BeginLines(int)=0; - //virtual void BeginLineStrip(int)=0; - //virtual void BeginTriangles(int)=0; - //virtual void BeginTriangleStrip(int)=0; - //virtual void BeginTriangleFan(int)=0; - //virtual void PrimVertex(const zeus::CVector3f&)=0; - //virtual void PrimNormal(const zeus::CVector3f&)=0; - //virtual void PrimColor(float, float, float, float)=0; - //virtual void PrimColor(const zeus::CColor&)=0; - //virtual void EndPrimitive()=0; - virtual void SetAmbientColor(const zeus::CColor&)=0; - virtual void DrawString(const char*, int, int)=0; - virtual u32 GetFPS()=0; - virtual void CacheReflection(TReflectionCallback, void*, bool)=0; - virtual void DrawSpaceWarp(const zeus::CVector3f&, float)=0; - virtual void DrawThermalModel(const CModel&, const zeus::CColor&, const zeus::CColor&)=0; - virtual void DrawXRayOutline(const zeus::CAABox&)=0; - virtual void SetWireframeFlags(int)=0; - virtual void SetWorldFog(ERglFogMode, float, float, const zeus::CColor&)=0; - virtual void RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken*, const CSkinnedModel*)=0; - virtual void SetThermal(bool, float, const zeus::CColor&)=0; - virtual void SetThermalColdScale(float scale)=0; - virtual void DoThermalBlendCold()=0; - virtual void DoThermalBlendHot()=0; - virtual u32 GetStaticWorldDataSize()=0; - virtual void PrepareDynamicLights(const std::vector& lights)=0; - virtual void SetGXRegister1Color(const zeus::CColor& color)=0; - virtual void SetWorldLightFadeLevel(float level)=0; + virtual ~IRenderer() = default; + virtual void AddStaticGeometry(const std::vector*, const CAreaRenderOctTree*, int, + const SShader*) = 0; + virtual void EnablePVS(const CPVSVisSet&, u32) = 0; + virtual void DisablePVS() = 0; + virtual void RemoveStaticGeometry(const std::vector*) = 0; + virtual void DrawAreaGeometry(int areaIdx, int mask, int targetMask) = 0; + virtual void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender = false) = 0; + virtual void DrawSortedGeometry(int areaIdx, int mask, int targetMask) = 0; + virtual void DrawStaticGeometry(int areaIdx, int mask, int targetMask) = 0; + virtual void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) = 0; + virtual void PostRenderFogs() = 0; + virtual void AddParticleGen(const CParticleGen&) = 0; + virtual void AddParticleGen(const CParticleGen&, const zeus::CVector3f&, const zeus::CAABox&) = 0; + virtual void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int) = 0; + virtual void AddDrawable(void const*, const zeus::CVector3f&, const zeus::CAABox&, int, EDrawableSorting) = 0; + virtual void SetDrawableCallback(TDrawableCallback, const void*) = 0; + virtual void SetWorldViewpoint(const zeus::CTransform&) = 0; + virtual void SetPerspective(float, float, float, float, float) = 0; + virtual void SetPerspective(float, float, float, float) = 0; + virtual std::pair SetViewportOrtho(bool, float, float) = 0; + virtual void SetClippingPlanes(const zeus::CFrustum&) = 0; + virtual void SetViewport(int, int, int, int) = 0; + // virtual void SetDepthReadWrite(bool, bool)=0; + // virtual void SetBlendMode_AdditiveAlpha()=0; + // virtual void SetBlendMode_AlphaBlended()=0; + // virtual void SetBlendMode_NoColorWrite()=0; + // virtual void SetBlendMode_ColorMultiply()=0; + // virtual void SetBlendMode_InvertDst()=0; + // virtual void SetBlendMode_InvertSrc()=0; + // virtual void SetBlendMode_Replace()=0; + // virtual void SetBlendMode_AdditiveDestColor()=0; + virtual void SetDebugOption(EDebugOption, int) = 0; + virtual void BeginScene() = 0; + virtual void EndScene() = 0; + // virtual void BeginPrimitive(EPrimitiveType, int)=0; + // virtual void BeginLines(int)=0; + // virtual void BeginLineStrip(int)=0; + // virtual void BeginTriangles(int)=0; + // virtual void BeginTriangleStrip(int)=0; + // virtual void BeginTriangleFan(int)=0; + // virtual void PrimVertex(const zeus::CVector3f&)=0; + // virtual void PrimNormal(const zeus::CVector3f&)=0; + // virtual void PrimColor(float, float, float, float)=0; + // virtual void PrimColor(const zeus::CColor&)=0; + // virtual void EndPrimitive()=0; + virtual void SetAmbientColor(const zeus::CColor&) = 0; + virtual void DrawString(const char*, int, int) = 0; + virtual u32 GetFPS() = 0; + virtual void CacheReflection(TReflectionCallback, void*, bool) = 0; + virtual void DrawSpaceWarp(const zeus::CVector3f&, float) = 0; + virtual void DrawThermalModel(const CModel&, const zeus::CColor&, const zeus::CColor&) = 0; + virtual void DrawXRayOutline(const zeus::CAABox&) = 0; + virtual void SetWireframeFlags(int) = 0; + virtual void SetWorldFog(ERglFogMode, float, float, const zeus::CColor&) = 0; + virtual void RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken*, + const CSkinnedModel*) = 0; + virtual void SetThermal(bool, float, const zeus::CColor&) = 0; + virtual void SetThermalColdScale(float scale) = 0; + virtual void DoThermalBlendCold() = 0; + virtual void DoThermalBlendHot() = 0; + virtual u32 GetStaticWorldDataSize() = 0; + virtual void PrepareDynamicLights(const std::vector& lights) = 0; + virtual void SetGXRegister1Color(const zeus::CColor& color) = 0; + virtual void SetWorldLightFadeLevel(float level) = 0; }; -} - +} // namespace urde diff --git a/Runtime/Graphics/IWeaponRenderer.cpp b/Runtime/Graphics/IWeaponRenderer.cpp index 763e484c3..0a1e5c525 100644 --- a/Runtime/Graphics/IWeaponRenderer.cpp +++ b/Runtime/Graphics/IWeaponRenderer.cpp @@ -1,12 +1,8 @@ #include "IWeaponRenderer.hpp" #include "Particle/CParticleGen.hpp" -namespace urde -{ +namespace urde { -void CDefaultWeaponRenderer::AddParticleGen(const CParticleGen& gen) -{ - ((CParticleGen&)gen).Render(); -} +void CDefaultWeaponRenderer::AddParticleGen(const CParticleGen& gen) { ((CParticleGen&)gen).Render(); } -} +} // namespace urde diff --git a/Runtime/Graphics/IWeaponRenderer.hpp b/Runtime/Graphics/IWeaponRenderer.hpp index 99f0666bf..cd1886abe 100644 --- a/Runtime/Graphics/IWeaponRenderer.hpp +++ b/Runtime/Graphics/IWeaponRenderer.hpp @@ -1,21 +1,17 @@ #pragma once -namespace urde -{ +namespace urde { class CParticleGen; -class IWeaponRenderer -{ +class IWeaponRenderer { public: - virtual ~IWeaponRenderer() = default; - virtual void AddParticleGen(const CParticleGen&)=0; + virtual ~IWeaponRenderer() = default; + virtual void AddParticleGen(const CParticleGen&) = 0; }; -class CDefaultWeaponRenderer : public IWeaponRenderer -{ +class CDefaultWeaponRenderer : public IWeaponRenderer { public: - void AddParticleGen(const CParticleGen&); + void AddParticleGen(const CParticleGen&); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CAABoxShader.cpp b/Runtime/Graphics/Shaders/CAABoxShader.cpp index 2ba2f19d6..da4177ef8 100644 --- a/Runtime/Graphics/Shaders/CAABoxShader.cpp +++ b/Runtime/Graphics/Shaders/CAABoxShader.cpp @@ -2,95 +2,70 @@ #include "hecl/Pipeline.hpp" #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; static boo::ObjToken s_zOnlyPipeline; -void CAABoxShader::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CAABoxShader{}); - s_zOnlyPipeline = hecl::conv->convert(Shader_CAABoxShaderZOnly{}); +void CAABoxShader::Initialize() { + s_Pipeline = hecl::conv->convert(Shader_CAABoxShader{}); + s_zOnlyPipeline = hecl::conv->convert(Shader_CAABoxShaderZOnly{}); } -void CAABoxShader::Shutdown() -{ - s_Pipeline.reset(); - s_zOnlyPipeline.reset(); +void CAABoxShader::Shutdown() { + s_Pipeline.reset(); + s_zOnlyPipeline.reset(); } -CAABoxShader::CAABoxShader(bool zOnly) -{ - CGraphics::CommitResources([this, zOnly](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(zeus::CVector3f), 34); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - m_dataBind = ctx.newShaderDataBinding(zOnly ? s_zOnlyPipeline : s_Pipeline, - m_vbo.get(), nullptr, nullptr, 1, bufs, stages, - nullptr, nullptr, 0, nullptr, nullptr, nullptr); - return true; - } BooTrace); +CAABoxShader::CAABoxShader(bool zOnly) { + CGraphics::CommitResources([this, zOnly](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(zeus::CVector3f), 34); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + m_dataBind = ctx.newShaderDataBinding(zOnly ? s_zOnlyPipeline : s_Pipeline, m_vbo.get(), nullptr, nullptr, 1, bufs, + stages, nullptr, nullptr, 0, nullptr, nullptr, nullptr); + return true; + } BooTrace); } -void CAABoxShader::setAABB(const zeus::CAABox& aabb) -{ - zeus::CVector3f vboData[] = - { - {aabb.max.x(), aabb.max.y(), aabb.min.z()}, - {aabb.max.x(), aabb.min.y(), aabb.min.z()}, - {aabb.max.x(), aabb.max.y(), aabb.max.z()}, - {aabb.max.x(), aabb.min.y(), aabb.max.z()}, - {aabb.max.x(), aabb.min.y(), aabb.max.z()}, +void CAABoxShader::setAABB(const zeus::CAABox& aabb) { + zeus::CVector3f vboData[] = { + {aabb.max.x(), aabb.max.y(), aabb.min.z()}, {aabb.max.x(), aabb.min.y(), aabb.min.z()}, + {aabb.max.x(), aabb.max.y(), aabb.max.z()}, {aabb.max.x(), aabb.min.y(), aabb.max.z()}, + {aabb.max.x(), aabb.min.y(), aabb.max.z()}, - {aabb.min.x(), aabb.max.y(), aabb.min.z()}, - {aabb.min.x(), aabb.max.y(), aabb.min.z()}, - {aabb.max.x(), aabb.max.y(), aabb.min.z()}, - {aabb.min.x(), aabb.max.y(), aabb.max.z()}, - {aabb.max.x(), aabb.max.y(), aabb.max.z()}, - {aabb.max.x(), aabb.max.y(), aabb.max.z()}, + {aabb.min.x(), aabb.max.y(), aabb.min.z()}, {aabb.min.x(), aabb.max.y(), aabb.min.z()}, + {aabb.max.x(), aabb.max.y(), aabb.min.z()}, {aabb.min.x(), aabb.max.y(), aabb.max.z()}, + {aabb.max.x(), aabb.max.y(), aabb.max.z()}, {aabb.max.x(), aabb.max.y(), aabb.max.z()}, - {aabb.min.x(), aabb.max.y(), aabb.min.z()}, - {aabb.min.x(), aabb.max.y(), aabb.min.z()}, - {aabb.min.x(), aabb.min.y(), aabb.min.z()}, - {aabb.min.x(), aabb.max.y(), aabb.max.z()}, - {aabb.min.x(), aabb.min.y(), aabb.max.z()}, - {aabb.min.x(), aabb.min.y(), aabb.max.z()}, + {aabb.min.x(), aabb.max.y(), aabb.min.z()}, {aabb.min.x(), aabb.max.y(), aabb.min.z()}, + {aabb.min.x(), aabb.min.y(), aabb.min.z()}, {aabb.min.x(), aabb.max.y(), aabb.max.z()}, + {aabb.min.x(), aabb.min.y(), aabb.max.z()}, {aabb.min.x(), aabb.min.y(), aabb.max.z()}, - {aabb.min.x(), aabb.min.y(), aabb.min.z()}, - {aabb.min.x(), aabb.min.y(), aabb.min.z()}, - {aabb.max.x(), aabb.min.y(), aabb.min.z()}, - {aabb.min.x(), aabb.min.y(), aabb.max.z()}, - {aabb.max.x(), aabb.min.y(), aabb.max.z()}, - {aabb.max.x(), aabb.min.y(), aabb.max.z()}, + {aabb.min.x(), aabb.min.y(), aabb.min.z()}, {aabb.min.x(), aabb.min.y(), aabb.min.z()}, + {aabb.max.x(), aabb.min.y(), aabb.min.z()}, {aabb.min.x(), aabb.min.y(), aabb.max.z()}, + {aabb.max.x(), aabb.min.y(), aabb.max.z()}, {aabb.max.x(), aabb.min.y(), aabb.max.z()}, - {aabb.min.x(), aabb.min.y(), aabb.max.z()}, - {aabb.min.x(), aabb.min.y(), aabb.max.z()}, - {aabb.max.x(), aabb.min.y(), aabb.max.z()}, - {aabb.min.x(), aabb.max.y(), aabb.max.z()}, - {aabb.max.x(), aabb.max.y(), aabb.max.z()}, - {aabb.max.x(), aabb.max.y(), aabb.max.z()}, + {aabb.min.x(), aabb.min.y(), aabb.max.z()}, {aabb.min.x(), aabb.min.y(), aabb.max.z()}, + {aabb.max.x(), aabb.min.y(), aabb.max.z()}, {aabb.min.x(), aabb.max.y(), aabb.max.z()}, + {aabb.max.x(), aabb.max.y(), aabb.max.z()}, {aabb.max.x(), aabb.max.y(), aabb.max.z()}, - {aabb.min.x(), aabb.min.y(), aabb.min.z()}, - {aabb.min.x(), aabb.min.y(), aabb.min.z()}, - {aabb.max.x(), aabb.min.y(), aabb.min.z()}, - {aabb.min.x(), aabb.max.y(), aabb.min.z()}, - {aabb.max.x(), aabb.max.y(), aabb.min.z()}, - }; + {aabb.min.x(), aabb.min.y(), aabb.min.z()}, {aabb.min.x(), aabb.min.y(), aabb.min.z()}, + {aabb.max.x(), aabb.min.y(), aabb.min.z()}, {aabb.min.x(), aabb.max.y(), aabb.min.z()}, + {aabb.max.x(), aabb.max.y(), aabb.min.z()}, + }; - m_vbo->load(vboData, sizeof(zeus::CVector3f) * 34); + m_vbo->load(vboData, sizeof(zeus::CVector3f) * 34); } -void CAABoxShader::draw(const zeus::CColor& color) -{ - m_uniform.m_xf = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); - m_uniform.m_color = color; - m_uniBuf->load(&m_uniform, sizeof(Uniform)); +void CAABoxShader::draw(const zeus::CColor& color) { + m_uniform.m_xf = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); + m_uniform.m_color = color; + m_uniBuf->load(&m_uniform, sizeof(Uniform)); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 34); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 34); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CAABoxShader.hpp b/Runtime/Graphics/Shaders/CAABoxShader.hpp index a80d05686..97d24454b 100644 --- a/Runtime/Graphics/Shaders/CAABoxShader.hpp +++ b/Runtime/Graphics/Shaders/CAABoxShader.hpp @@ -5,28 +5,24 @@ #include "zeus/CColor.hpp" #include "zeus/CAABox.hpp" -namespace urde -{ +namespace urde { -class CAABoxShader -{ - struct Uniform - { - zeus::CMatrix4f m_xf; - zeus::CColor m_color; - }; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; +class CAABoxShader { + struct Uniform { + zeus::CMatrix4f m_xf; + zeus::CColor m_color; + }; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; public: - static void Initialize(); - static void Shutdown(); - CAABoxShader(bool zOnly); - void setAABB(const zeus::CAABox& aabb); - void draw(const zeus::CColor& color); + static void Initialize(); + static void Shutdown(); + CAABoxShader(bool zOnly); + void setAABB(const zeus::CAABox& aabb); + void draw(const zeus::CColor& color); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CCameraBlurFilter.cpp b/Runtime/Graphics/Shaders/CCameraBlurFilter.cpp index 790eefbc7..5b3fdeab1 100644 --- a/Runtime/Graphics/Shaders/CCameraBlurFilter.cpp +++ b/Runtime/Graphics/Shaders/CCameraBlurFilter.cpp @@ -2,79 +2,67 @@ #include "hecl/Pipeline.hpp" #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; -void CCameraBlurFilter::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CCameraBlurFilter{}); +void CCameraBlurFilter::Initialize() { s_Pipeline = hecl::conv->convert(Shader_CCameraBlurFilter{}); } + +void CCameraBlurFilter::Shutdown() { s_Pipeline.reset(); } + +CCameraBlurFilter::CCameraBlurFilter() { + CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 32, 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get()}; + m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, nullptr, + 1, texs, nullptr, nullptr); + return true; + } BooTrace); } -void CCameraBlurFilter::Shutdown() -{ - s_Pipeline.reset(); +void CCameraBlurFilter::draw(float amount, bool clearDepth) { + if (amount <= 0.f) + return; + + SClipScreenRect clipRect(g_Viewport); + CGraphics::ResolveSpareTexture(clipRect, 0, clearDepth); + float aspect = CGraphics::g_CroppedViewport.xc_width / float(CGraphics::g_CroppedViewport.x10_height); + + float xFac = CGraphics::g_CroppedViewport.xc_width / float(g_Viewport.x8_width); + float yFac = CGraphics::g_CroppedViewport.x10_height / float(g_Viewport.xc_height); + float xBias = CGraphics::g_CroppedViewport.x4_left / float(g_Viewport.x8_width); + float yBias = CGraphics::g_CroppedViewport.x8_top / float(g_Viewport.xc_height); + + Vert verts[4] = { + {{-1.0, -1.0}, {xBias, yBias}}, + {{-1.0, 1.0}, {xBias, yBias + yFac}}, + {{1.0, -1.0}, {xBias + xFac, yBias}}, + {{1.0, 1.0}, {xBias + xFac, yBias + yFac}}, + }; + m_vbo->load(verts, sizeof(verts)); + + for (int i = 0; i < 6; ++i) { + float tmp = i; + tmp *= 2.f * M_PIF; + tmp /= 6.f; + + float amtX = std::cos(tmp); + amtX *= amount / 448.f / aspect; + + float amtY = std::sin(tmp); + amtY *= amount / 448.f; + + m_uniform.m_uv[i][0] = amtX * xFac; + m_uniform.m_uv[i][1] = amtY * yFac; + } + m_uniform.m_opacity = std::min(amount / 2.f, 1.f); + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); } -CCameraBlurFilter::CCameraBlurFilter() -{ - CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 32, 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get()}; - m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 1, texs, nullptr, nullptr); - return true; - } BooTrace); -} - -void CCameraBlurFilter::draw(float amount, bool clearDepth) -{ - if (amount <= 0.f) - return; - - SClipScreenRect clipRect(g_Viewport); - CGraphics::ResolveSpareTexture(clipRect, 0, clearDepth); - float aspect = CGraphics::g_CroppedViewport.xc_width / float(CGraphics::g_CroppedViewport.x10_height); - - float xFac = CGraphics::g_CroppedViewport.xc_width / float(g_Viewport.x8_width); - float yFac = CGraphics::g_CroppedViewport.x10_height / float(g_Viewport.xc_height); - float xBias = CGraphics::g_CroppedViewport.x4_left / float(g_Viewport.x8_width); - float yBias = CGraphics::g_CroppedViewport.x8_top / float(g_Viewport.xc_height); - - Vert verts[4] = - { - {{-1.0, -1.0}, {xBias, yBias}}, - {{-1.0, 1.0}, {xBias, yBias + yFac}}, - {{ 1.0, -1.0}, {xBias + xFac, yBias}}, - {{ 1.0, 1.0}, {xBias + xFac, yBias + yFac}}, - }; - m_vbo->load(verts, sizeof(verts)); - - for (int i=0 ; i<6 ; ++i) - { - float tmp = i; - tmp *= 2.f * M_PIF; - tmp /= 6.f; - - float amtX = std::cos(tmp); - amtX *= amount / 448.f / aspect; - - float amtY = std::sin(tmp); - amtY *= amount / 448.f; - - m_uniform.m_uv[i][0] = amtX * xFac; - m_uniform.m_uv[i][1] = amtY * yFac; - } - m_uniform.m_opacity = std::min(amount / 2.f, 1.f); - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); -} - -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CCameraBlurFilter.hpp b/Runtime/Graphics/Shaders/CCameraBlurFilter.hpp index bfd7d91df..af5382573 100644 --- a/Runtime/Graphics/Shaders/CCameraBlurFilter.hpp +++ b/Runtime/Graphics/Shaders/CCameraBlurFilter.hpp @@ -4,33 +4,28 @@ #include "zeus/CMatrix4f.hpp" #include "zeus/CColor.hpp" -namespace urde -{ +namespace urde { -class CCameraBlurFilter -{ - struct Vert - { - zeus::CVector2f m_pos; - zeus::CVector2f m_uv; - }; - - struct Uniform - { - zeus::CVector4f m_uv[6]; - float m_opacity = 1.f; - }; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; +class CCameraBlurFilter { + struct Vert { + zeus::CVector2f m_pos; + zeus::CVector2f m_uv; + }; + + struct Uniform { + zeus::CVector4f m_uv[6]; + float m_opacity = 1.f; + }; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; public: - static void Initialize(); - static void Shutdown(); - CCameraBlurFilter(); - void draw(float amount, bool clearDepth=false); + static void Initialize(); + static void Shutdown(); + CCameraBlurFilter(); + void draw(float amount, bool clearDepth = false); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CColoredQuadFilter.cpp b/Runtime/Graphics/Shaders/CColoredQuadFilter.cpp index 17d2c959f..09ba90089 100644 --- a/Runtime/Graphics/Shaders/CColoredQuadFilter.cpp +++ b/Runtime/Graphics/Shaders/CColoredQuadFilter.cpp @@ -2,130 +2,110 @@ #include "Graphics/CGraphics.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_AlphaPipeline; static boo::ObjToken s_AddPipeline; static boo::ObjToken s_MultPipeline; -void CColoredQuadFilter::Initialize() -{ - s_AlphaPipeline = hecl::conv->convert(Shader_CColoredQuadFilter{}); - s_AddPipeline = hecl::conv->convert(Shader_CColoredQuadFilterAdd{}); - s_MultPipeline = hecl::conv->convert(Shader_CColoredQuadFilterMul{}); +void CColoredQuadFilter::Initialize() { + s_AlphaPipeline = hecl::conv->convert(Shader_CColoredQuadFilter{}); + s_AddPipeline = hecl::conv->convert(Shader_CColoredQuadFilterAdd{}); + s_MultPipeline = hecl::conv->convert(Shader_CColoredQuadFilterMul{}); } -void CColoredQuadFilter::Shutdown() -{ - s_AlphaPipeline.reset(); - s_AddPipeline.reset(); - s_MultPipeline.reset(); +void CColoredQuadFilter::Shutdown() { + s_AlphaPipeline.reset(); + s_AddPipeline.reset(); + s_MultPipeline.reset(); } -static boo::ObjToken SelectPipeline(EFilterType type) -{ - switch (type) - { - case EFilterType::Blend: - return s_AlphaPipeline; - case EFilterType::Add: - return s_AddPipeline; - case EFilterType::Multiply: - return s_MultPipeline; - default: - return {}; - } +static boo::ObjToken SelectPipeline(EFilterType type) { + switch (type) { + case EFilterType::Blend: + return s_AlphaPipeline; + case EFilterType::Add: + return s_AddPipeline; + case EFilterType::Multiply: + return s_MultPipeline; + default: + return {}; + } } -CColoredQuadFilter::CColoredQuadFilter(EFilterType type) -{ - CGraphics::CommitResources([this, type](boo::IGraphicsDataFactory::Context& ctx) - { - struct Vert - { - zeus::CVector2f m_pos; - } verts[4] = - { +CColoredQuadFilter::CColoredQuadFilter(EFilterType type) { + CGraphics::CommitResources([this, type](boo::IGraphicsDataFactory::Context& ctx) { + struct Vert { + zeus::CVector2f m_pos; + } verts[4] = { {{0.0, 0.0}}, {{0.0, 1.0}}, {{1.0, 0.0}}, {{1.0, 1.0}}, - }; - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, 16, 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - m_dataBind = ctx.newShaderDataBinding(SelectPipeline(type), m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 0, nullptr, nullptr, nullptr); - return true; - } BooTrace); + }; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, 16, 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + m_dataBind = ctx.newShaderDataBinding(SelectPipeline(type), m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, + nullptr, 0, nullptr, nullptr, nullptr); + return true; + } BooTrace); } -void CColoredQuadFilter::draw(const zeus::CColor& color, const zeus::CRectangle& rect) -{ - m_uniform.m_matrix[0][0] = rect.size.x() * 2.f; - m_uniform.m_matrix[1][1] = rect.size.y() * 2.f; - m_uniform.m_matrix[3][0] = rect.position.x() * 2.f - 1.f; - m_uniform.m_matrix[3][1] = rect.position.y() * 2.f - 1.f; - m_uniform.m_color = color; - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); +void CColoredQuadFilter::draw(const zeus::CColor& color, const zeus::CRectangle& rect) { + m_uniform.m_matrix[0][0] = rect.size.x() * 2.f; + m_uniform.m_matrix[1][1] = rect.size.y() * 2.f; + m_uniform.m_matrix[3][0] = rect.position.x() * 2.f - 1.f; + m_uniform.m_matrix[3][1] = rect.position.y() * 2.f - 1.f; + m_uniform.m_color = color; + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); } -void CWideScreenFilter::draw(const zeus::CColor& color, float t) -{ - float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); - if (aspect < 1.7777f) - { - float targetHeight = g_Viewport.x8_width / 1.7777f; - float delta = (g_Viewport.xc_height - targetHeight) * t / 2.f; - delta /= float(g_Viewport.xc_height); - zeus::CRectangle rect(0.f, 0.f, 1.f, delta); - m_bottom.draw(color, rect); - rect.position.y() = 1.f - delta; - m_top.draw(color, rect); - } +void CWideScreenFilter::draw(const zeus::CColor& color, float t) { + float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); + if (aspect < 1.7777f) { + float targetHeight = g_Viewport.x8_width / 1.7777f; + float delta = (g_Viewport.xc_height - targetHeight) * t / 2.f; + delta /= float(g_Viewport.xc_height); + zeus::CRectangle rect(0.f, 0.f, 1.f, delta); + m_bottom.draw(color, rect); + rect.position.y() = 1.f - delta; + m_top.draw(color, rect); + } } -void CWideScreenFilter::DrawFilter(EFilterShape shape, const zeus::CColor& color, float t) -{ +void CWideScreenFilter::DrawFilter(EFilterShape shape, const zeus::CColor& color, float t) {} -} - -float CWideScreenFilter::SetViewportToMatch(float t) -{ - float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); - if (aspect < 1.7777f) - { - float targetHeight = g_Viewport.x8_width / 1.7777f; - float delta = (g_Viewport.xc_height - targetHeight) * t / 2.f; - boo::SWindowRect rect = {}; - rect.size[0] = g_Viewport.x8_width; - rect.size[1] = g_Viewport.xc_height - delta * 2.f; - rect.location[1] = delta; - CGraphics::g_CroppedViewport = rect; - CGraphics::g_BooMainCommandQueue->setViewport(rect); - return 1.7777f; - } - else - { - SetViewportToFull(); - return aspect; - } -} - -void CWideScreenFilter::SetViewportToFull() -{ +float CWideScreenFilter::SetViewportToMatch(float t) { + float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); + if (aspect < 1.7777f) { + float targetHeight = g_Viewport.x8_width / 1.7777f; + float delta = (g_Viewport.xc_height - targetHeight) * t / 2.f; boo::SWindowRect rect = {}; rect.size[0] = g_Viewport.x8_width; - rect.size[1] = g_Viewport.xc_height; + rect.size[1] = g_Viewport.xc_height - delta * 2.f; + rect.location[1] = delta; CGraphics::g_CroppedViewport = rect; CGraphics::g_BooMainCommandQueue->setViewport(rect); + return 1.7777f; + } else { + SetViewportToFull(); + return aspect; + } +} + +void CWideScreenFilter::SetViewportToFull() { + boo::SWindowRect rect = {}; + rect.size[0] = g_Viewport.x8_width; + rect.size[1] = g_Viewport.xc_height; + CGraphics::g_CroppedViewport = rect; + CGraphics::g_BooMainCommandQueue->setViewport(rect); } const zeus::CRectangle CColoredQuadFilter::DefaultRect = {0.f, 0.f, 1.f, 1.f}; -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CColoredQuadFilter.hpp b/Runtime/Graphics/Shaders/CColoredQuadFilter.hpp index cabe6fb00..c4130555f 100644 --- a/Runtime/Graphics/Shaders/CColoredQuadFilter.hpp +++ b/Runtime/Graphics/Shaders/CColoredQuadFilter.hpp @@ -5,47 +5,40 @@ #include "zeus/CRectangle.hpp" #include "Camera/CCameraFilter.hpp" -namespace urde -{ +namespace urde { -class CColoredQuadFilter -{ - struct Uniform - { - zeus::CMatrix4f m_matrix; - zeus::CColor m_color; - }; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; +class CColoredQuadFilter { + struct Uniform { + zeus::CMatrix4f m_matrix; + zeus::CColor m_color; + }; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; public: - static void Initialize(); - static void Shutdown(); - static const zeus::CRectangle DefaultRect; - CColoredQuadFilter(EFilterType type); - CColoredQuadFilter(EFilterType type, const TLockedToken&) - : CColoredQuadFilter(type) {} - void draw(const zeus::CColor& color, const zeus::CRectangle& rect=DefaultRect); - void DrawFilter(EFilterShape shape, const zeus::CColor& color, float t) { draw(color); } + static void Initialize(); + static void Shutdown(); + static const zeus::CRectangle DefaultRect; + CColoredQuadFilter(EFilterType type); + CColoredQuadFilter(EFilterType type, const TLockedToken&) : CColoredQuadFilter(type) {} + void draw(const zeus::CColor& color, const zeus::CRectangle& rect = DefaultRect); + void DrawFilter(EFilterShape shape, const zeus::CColor& color, float t) { draw(color); } }; -class CWideScreenFilter -{ - CColoredQuadFilter m_top; - CColoredQuadFilter m_bottom; +class CWideScreenFilter { + CColoredQuadFilter m_top; + CColoredQuadFilter m_bottom; + public: - CWideScreenFilter(EFilterType type) - : m_top(type), m_bottom(type) {} - CWideScreenFilter(EFilterType type, const TLockedToken&) - : CWideScreenFilter(type) {} - void draw(const zeus::CColor& color, float t); - void DrawFilter(EFilterShape shape, const zeus::CColor& color, float t); + CWideScreenFilter(EFilterType type) : m_top(type), m_bottom(type) {} + CWideScreenFilter(EFilterType type, const TLockedToken&) : CWideScreenFilter(type) {} + void draw(const zeus::CColor& color, float t); + void DrawFilter(EFilterShape shape, const zeus::CColor& color, float t); - static float SetViewportToMatch(float t); - static void SetViewportToFull(); + static float SetViewportToMatch(float t); + static void SetViewportToFull(); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CDecalShaders.cpp b/Runtime/Graphics/Shaders/CDecalShaders.cpp index 7fe439eeb..ff8fa5f01 100644 --- a/Runtime/Graphics/Shaders/CDecalShaders.cpp +++ b/Runtime/Graphics/Shaders/CDecalShaders.cpp @@ -2,8 +2,7 @@ #include "Particle/CDecal.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { boo::ObjToken CDecalShaders::m_texZTestNoZWrite; boo::ObjToken CDecalShaders::m_texAdditiveZTest; @@ -12,70 +11,60 @@ boo::ObjToken CDecalShaders::m_texRedToAlphaZTest; boo::ObjToken CDecalShaders::m_noTexZTestNoZWrite; boo::ObjToken CDecalShaders::m_noTexAdditiveZTest; -void CDecalShaders::Initialize() -{ - m_texZTestNoZWrite = hecl::conv->convert(Shader_CDecalShaderTexZTest{}); - m_texAdditiveZTest = hecl::conv->convert(Shader_CDecalShaderTexAdditiveZTest{}); - m_texRedToAlphaZTest = hecl::conv->convert(Shader_CDecalShaderTexRedToAlphaZTest{}); - m_noTexZTestNoZWrite = hecl::conv->convert(Shader_CDecalShaderNoTexZTest{}); - m_noTexAdditiveZTest = hecl::conv->convert(Shader_CDecalShaderNoTexAdditiveZTest{}); +void CDecalShaders::Initialize() { + m_texZTestNoZWrite = hecl::conv->convert(Shader_CDecalShaderTexZTest{}); + m_texAdditiveZTest = hecl::conv->convert(Shader_CDecalShaderTexAdditiveZTest{}); + m_texRedToAlphaZTest = hecl::conv->convert(Shader_CDecalShaderTexRedToAlphaZTest{}); + m_noTexZTestNoZWrite = hecl::conv->convert(Shader_CDecalShaderNoTexZTest{}); + m_noTexAdditiveZTest = hecl::conv->convert(Shader_CDecalShaderNoTexAdditiveZTest{}); } -void CDecalShaders::Shutdown() -{ - m_texZTestNoZWrite.reset(); - m_texAdditiveZTest.reset(); - m_texRedToAlphaZTest.reset(); - m_noTexZTestNoZWrite.reset(); - m_noTexAdditiveZTest.reset(); +void CDecalShaders::Shutdown() { + m_texZTestNoZWrite.reset(); + m_texAdditiveZTest.reset(); + m_texRedToAlphaZTest.reset(); + m_noTexZTestNoZWrite.reset(); + m_noTexAdditiveZTest.reset(); } -void CDecalShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CQuadDecal& decal) -{ - boo::ObjToken regPipeline; - boo::ObjToken redToAlphaPipeline; +void CDecalShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CQuadDecal& decal) { + boo::ObjToken regPipeline; + boo::ObjToken redToAlphaPipeline; - if (decal.m_desc->x14_TEX) - { - if (decal.m_desc->x18_ADD) - regPipeline = m_texAdditiveZTest; - else - regPipeline = m_texZTestNoZWrite; - redToAlphaPipeline = m_texRedToAlphaZTest; - } + if (decal.m_desc->x14_TEX) { + if (decal.m_desc->x18_ADD) + regPipeline = m_texAdditiveZTest; else - { - if (decal.m_desc->x18_ADD) - regPipeline = m_noTexAdditiveZTest; - else - regPipeline = m_noTexZTestNoZWrite; - } + regPipeline = m_texZTestNoZWrite; + redToAlphaPipeline = m_texRedToAlphaZTest; + } else { + if (decal.m_desc->x18_ADD) + regPipeline = m_noTexAdditiveZTest; + else + regPipeline = m_noTexZTestNoZWrite; + } - const SQuadDescr* desc = decal.m_desc; + const SQuadDescr* desc = decal.m_desc; - CUVElement* texr = desc->x14_TEX.get(); - int texCount = 0; - boo::ObjToken textures[1]; + CUVElement* texr = desc->x14_TEX.get(); + int texCount = 0; + boo::ObjToken textures[1]; - if (texr) - { - textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture(); - texCount = 1; - } + if (texr) { + textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture(); + texCount = 1; + } - if (decal.m_instBuf) - { - boo::ObjToken uniforms[] = {decal.m_uniformBuf.get()}; + if (decal.m_instBuf) { + boo::ObjToken uniforms[] = {decal.m_uniformBuf.get()}; - if (regPipeline) - decal.m_normalDataBind = ctx.newShaderDataBinding(regPipeline, nullptr, - decal.m_instBuf.get(), nullptr, 1, uniforms, - nullptr, texCount, textures, nullptr, nullptr); - if (redToAlphaPipeline) - decal.m_redToAlphaDataBind = ctx.newShaderDataBinding(redToAlphaPipeline, nullptr, - decal.m_instBuf.get(), nullptr, 1, uniforms, - nullptr, texCount, textures, nullptr, nullptr); - } + if (regPipeline) + decal.m_normalDataBind = ctx.newShaderDataBinding(regPipeline, nullptr, decal.m_instBuf.get(), nullptr, 1, + uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (redToAlphaPipeline) + decal.m_redToAlphaDataBind = ctx.newShaderDataBinding(redToAlphaPipeline, nullptr, decal.m_instBuf.get(), nullptr, + 1, uniforms, nullptr, texCount, textures, nullptr, nullptr); + } } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CDecalShaders.hpp b/Runtime/Graphics/Shaders/CDecalShaders.hpp index 2072e1c91..be4982db3 100644 --- a/Runtime/Graphics/Shaders/CDecalShaders.hpp +++ b/Runtime/Graphics/Shaders/CDecalShaders.hpp @@ -2,25 +2,22 @@ #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { struct CQuadDecal; -class CDecalShaders -{ +class CDecalShaders { private: - static boo::ObjToken m_texZTestNoZWrite; - static boo::ObjToken m_texAdditiveZTest; - static boo::ObjToken m_texRedToAlphaZTest; + static boo::ObjToken m_texZTestNoZWrite; + static boo::ObjToken m_texAdditiveZTest; + static boo::ObjToken m_texRedToAlphaZTest; - static boo::ObjToken m_noTexZTestNoZWrite; - static boo::ObjToken m_noTexAdditiveZTest; + static boo::ObjToken m_noTexZTestNoZWrite; + static boo::ObjToken m_noTexAdditiveZTest; public: - static void Initialize(); - static void Shutdown(); - static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CQuadDecal& decal); + static void Initialize(); + static void Shutdown(); + static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CQuadDecal& decal); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CElementGenShaders.cpp b/Runtime/Graphics/Shaders/CElementGenShaders.cpp index 087b2621e..8847afc47 100644 --- a/Runtime/Graphics/Shaders/CElementGenShaders.cpp +++ b/Runtime/Graphics/Shaders/CElementGenShaders.cpp @@ -2,8 +2,7 @@ #include "Particle/CElementGen.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { boo::ObjToken CElementGenShaders::m_texZTestZWrite; boo::ObjToken CElementGenShaders::m_texNoZTestZWrite; @@ -33,266 +32,221 @@ boo::ObjToken CElementGenShaders::m_noTexNoZTestNoZWrite; boo::ObjToken CElementGenShaders::m_noTexAdditiveZTest; boo::ObjToken CElementGenShaders::m_noTexAdditiveNoZTest; -void CElementGenShaders::Initialize() -{ - m_texZTestZWrite = hecl::conv->convert(Shader_CElementGenShaderTexZTestZWrite{}); - m_texNoZTestZWrite = hecl::conv->convert(Shader_CElementGenShaderTexNoZTestZWrite{}); - m_texZTestNoZWrite = hecl::conv->convert(Shader_CElementGenShaderTexZTestNoZWrite{}); - m_texNoZTestNoZWrite = hecl::conv->convert(Shader_CElementGenShaderTexNoZTestNoZWrite{}); - m_texAdditiveZTest = hecl::conv->convert(Shader_CElementGenShaderTexAdditiveZTest{}); - m_texAdditiveNoZTest = hecl::conv->convert(Shader_CElementGenShaderTexAdditiveNoZTest{}); - m_texRedToAlphaZTest = hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaZTest{}); - m_texRedToAlphaNoZTest = hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaNoZTest{}); - m_texZTestNoZWriteSub = hecl::conv->convert(Shader_CElementGenShaderTexZTestNoZWriteSub{}); - m_texNoZTestNoZWriteSub = hecl::conv->convert(Shader_CElementGenShaderTexNoZTestNoZWriteSub{}); - m_texRedToAlphaZTestSub = hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaZTestSub{}); - m_texRedToAlphaNoZTestSub = hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaNoZTestSub{}); +void CElementGenShaders::Initialize() { + m_texZTestZWrite = hecl::conv->convert(Shader_CElementGenShaderTexZTestZWrite{}); + m_texNoZTestZWrite = hecl::conv->convert(Shader_CElementGenShaderTexNoZTestZWrite{}); + m_texZTestNoZWrite = hecl::conv->convert(Shader_CElementGenShaderTexZTestNoZWrite{}); + m_texNoZTestNoZWrite = hecl::conv->convert(Shader_CElementGenShaderTexNoZTestNoZWrite{}); + m_texAdditiveZTest = hecl::conv->convert(Shader_CElementGenShaderTexAdditiveZTest{}); + m_texAdditiveNoZTest = hecl::conv->convert(Shader_CElementGenShaderTexAdditiveNoZTest{}); + m_texRedToAlphaZTest = hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaZTest{}); + m_texRedToAlphaNoZTest = hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaNoZTest{}); + m_texZTestNoZWriteSub = hecl::conv->convert(Shader_CElementGenShaderTexZTestNoZWriteSub{}); + m_texNoZTestNoZWriteSub = hecl::conv->convert(Shader_CElementGenShaderTexNoZTestNoZWriteSub{}); + m_texRedToAlphaZTestSub = hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaZTestSub{}); + m_texRedToAlphaNoZTestSub = hecl::conv->convert(Shader_CElementGenShaderTexRedToAlphaNoZTestSub{}); - m_indTexZWrite = hecl::conv->convert(Shader_CElementGenShaderIndTexZWrite{}); - m_indTexNoZWrite = hecl::conv->convert(Shader_CElementGenShaderIndTexNoZWrite{}); - m_indTexAdditive = hecl::conv->convert(Shader_CElementGenShaderIndTexAdditive{}); + m_indTexZWrite = hecl::conv->convert(Shader_CElementGenShaderIndTexZWrite{}); + m_indTexNoZWrite = hecl::conv->convert(Shader_CElementGenShaderIndTexNoZWrite{}); + m_indTexAdditive = hecl::conv->convert(Shader_CElementGenShaderIndTexAdditive{}); - m_cindTexZWrite = hecl::conv->convert(Shader_CElementGenShaderCindTexZWrite{}); - m_cindTexNoZWrite = hecl::conv->convert(Shader_CElementGenShaderCindTexNoZWrite{}); - m_cindTexAdditive = hecl::conv->convert(Shader_CElementGenShaderCindTexAdditive{}); + m_cindTexZWrite = hecl::conv->convert(Shader_CElementGenShaderCindTexZWrite{}); + m_cindTexNoZWrite = hecl::conv->convert(Shader_CElementGenShaderCindTexNoZWrite{}); + m_cindTexAdditive = hecl::conv->convert(Shader_CElementGenShaderCindTexAdditive{}); - m_noTexZTestZWrite = hecl::conv->convert(Shader_CElementGenShaderNoTexZTestZWrite{}); - m_noTexNoZTestZWrite = hecl::conv->convert(Shader_CElementGenShaderNoTexNoZTestZWrite{}); - m_noTexZTestNoZWrite = hecl::conv->convert(Shader_CElementGenShaderNoTexZTestNoZWrite{}); - m_noTexNoZTestNoZWrite = hecl::conv->convert(Shader_CElementGenShaderNoTexNoZTestNoZWrite{}); - m_noTexAdditiveZTest = hecl::conv->convert(Shader_CElementGenShaderNoTexAdditiveZTest{}); - m_noTexAdditiveNoZTest = hecl::conv->convert(Shader_CElementGenShaderNoTexAdditiveNoZTest{}); + m_noTexZTestZWrite = hecl::conv->convert(Shader_CElementGenShaderNoTexZTestZWrite{}); + m_noTexNoZTestZWrite = hecl::conv->convert(Shader_CElementGenShaderNoTexNoZTestZWrite{}); + m_noTexZTestNoZWrite = hecl::conv->convert(Shader_CElementGenShaderNoTexZTestNoZWrite{}); + m_noTexNoZTestNoZWrite = hecl::conv->convert(Shader_CElementGenShaderNoTexNoZTestNoZWrite{}); + m_noTexAdditiveZTest = hecl::conv->convert(Shader_CElementGenShaderNoTexAdditiveZTest{}); + m_noTexAdditiveNoZTest = hecl::conv->convert(Shader_CElementGenShaderNoTexAdditiveNoZTest{}); } -void CElementGenShaders::Shutdown() -{ - m_texZTestZWrite.reset(); - m_texNoZTestZWrite.reset(); - m_texZTestNoZWrite.reset(); - m_texNoZTestNoZWrite.reset(); - m_texAdditiveZTest.reset(); - m_texAdditiveNoZTest.reset(); - m_texRedToAlphaZTest.reset(); - m_texRedToAlphaNoZTest.reset(); - m_texZTestNoZWriteSub.reset(); - m_texNoZTestNoZWriteSub.reset(); - m_texRedToAlphaZTestSub.reset(); - m_texRedToAlphaNoZTestSub.reset(); +void CElementGenShaders::Shutdown() { + m_texZTestZWrite.reset(); + m_texNoZTestZWrite.reset(); + m_texZTestNoZWrite.reset(); + m_texNoZTestNoZWrite.reset(); + m_texAdditiveZTest.reset(); + m_texAdditiveNoZTest.reset(); + m_texRedToAlphaZTest.reset(); + m_texRedToAlphaNoZTest.reset(); + m_texZTestNoZWriteSub.reset(); + m_texNoZTestNoZWriteSub.reset(); + m_texRedToAlphaZTestSub.reset(); + m_texRedToAlphaNoZTestSub.reset(); - m_indTexZWrite.reset(); - m_indTexNoZWrite.reset(); - m_indTexAdditive.reset(); + m_indTexZWrite.reset(); + m_indTexNoZWrite.reset(); + m_indTexAdditive.reset(); - m_cindTexZWrite.reset(); - m_cindTexNoZWrite.reset(); - m_cindTexAdditive.reset(); + m_cindTexZWrite.reset(); + m_cindTexNoZWrite.reset(); + m_cindTexAdditive.reset(); - m_noTexZTestZWrite.reset(); - m_noTexNoZTestZWrite.reset(); - m_noTexZTestNoZWrite.reset(); - m_noTexNoZTestNoZWrite.reset(); - m_noTexAdditiveZTest.reset(); - m_noTexAdditiveNoZTest.reset(); + m_noTexZTestZWrite.reset(); + m_noTexNoZTestZWrite.reset(); + m_noTexZTestNoZWrite.reset(); + m_noTexNoZTestNoZWrite.reset(); + m_noTexAdditiveZTest.reset(); + m_noTexAdditiveNoZTest.reset(); } -CElementGenShaders::EShaderClass CElementGenShaders::GetShaderClass(CElementGen& gen) -{ - CGenDescription* desc = gen.x1c_genDesc.GetObj(); +CElementGenShaders::EShaderClass CElementGenShaders::GetShaderClass(CElementGen& gen) { + CGenDescription* desc = gen.x1c_genDesc.GetObj(); - if (desc->x54_x40_TEXR) - { - if (desc->x58_x44_TIND) - return EShaderClass::IndTex; - else - return EShaderClass::Tex; - } + if (desc->x54_x40_TEXR) { + if (desc->x58_x44_TIND) + return EShaderClass::IndTex; else - return EShaderClass::NoTex; + return EShaderClass::Tex; + } else + return EShaderClass::NoTex; } -void CElementGenShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CElementGen& gen) -{ - CGenDescription* desc = gen.x1c_genDesc.GetObj(); - boo::ObjToken regPipeline; - boo::ObjToken regPipelineSub; - boo::ObjToken redToAlphaPipeline; - boo::ObjToken redToAlphaPipelineSub; - boo::ObjToken regPipelinePmus; - boo::ObjToken redToAlphaPipelinePmus; +void CElementGenShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CElementGen& gen) { + CGenDescription* desc = gen.x1c_genDesc.GetObj(); + boo::ObjToken regPipeline; + boo::ObjToken regPipelineSub; + boo::ObjToken redToAlphaPipeline; + boo::ObjToken redToAlphaPipelineSub; + boo::ObjToken regPipelinePmus; + boo::ObjToken redToAlphaPipelinePmus; - if (desc->x54_x40_TEXR) - { - if (desc->x58_x44_TIND) - { - if (desc->x45_30_x32_24_CIND) - { - if (gen.x26c_26_AAPH) - regPipeline = m_cindTexAdditive; - else - { - if (gen.x26c_27_ZBUF) - regPipeline = m_cindTexZWrite; - else - regPipeline = m_cindTexNoZWrite; - } - } - else - { - if (gen.x26c_26_AAPH) - regPipeline = m_indTexAdditive; - else - { - if (gen.x26c_27_ZBUF) - regPipeline = m_indTexZWrite; - else - regPipeline = m_indTexNoZWrite; - } - } - } - else - { - if (gen.x26c_28_zTest) - { - redToAlphaPipeline = m_texRedToAlphaZTest; - regPipelineSub = m_texZTestNoZWriteSub; - redToAlphaPipelineSub = m_texRedToAlphaZTestSub; - } - else - { - redToAlphaPipeline = m_texRedToAlphaNoZTest; - regPipelineSub = m_texNoZTestNoZWriteSub; - redToAlphaPipelineSub = m_texRedToAlphaNoZTestSub; - } - - if (gen.x26c_26_AAPH) - { - if (gen.x26c_28_zTest) - regPipeline = m_texAdditiveZTest; - else - regPipeline = m_texAdditiveNoZTest; - } - else - { - if (gen.x26c_28_zTest) - { - if (gen.x26c_27_ZBUF) - regPipeline = m_texZTestZWrite; - else - regPipeline = m_texZTestNoZWrite; - } - else - { - if (gen.x26c_27_ZBUF) - regPipeline = m_texNoZTestZWrite; - else - regPipeline = m_texNoZTestNoZWrite; - } - } - } - } - else - { + if (desc->x54_x40_TEXR) { + if (desc->x58_x44_TIND) { + if (desc->x45_30_x32_24_CIND) { if (gen.x26c_26_AAPH) - { - if (gen.x26c_28_zTest) - regPipeline = m_noTexAdditiveZTest; - else - regPipeline = m_noTexAdditiveNoZTest; + regPipeline = m_cindTexAdditive; + else { + if (gen.x26c_27_ZBUF) + regPipeline = m_cindTexZWrite; + else + regPipeline = m_cindTexNoZWrite; } + } else { + if (gen.x26c_26_AAPH) + regPipeline = m_indTexAdditive; + else { + if (gen.x26c_27_ZBUF) + regPipeline = m_indTexZWrite; + else + regPipeline = m_indTexNoZWrite; + } + } + } else { + if (gen.x26c_28_zTest) { + redToAlphaPipeline = m_texRedToAlphaZTest; + regPipelineSub = m_texZTestNoZWriteSub; + redToAlphaPipelineSub = m_texRedToAlphaZTestSub; + } else { + redToAlphaPipeline = m_texRedToAlphaNoZTest; + regPipelineSub = m_texNoZTestNoZWriteSub; + redToAlphaPipelineSub = m_texRedToAlphaNoZTestSub; + } + + if (gen.x26c_26_AAPH) { + if (gen.x26c_28_zTest) + regPipeline = m_texAdditiveZTest; else - { - if (gen.x26c_28_zTest) - { - if (gen.x26c_27_ZBUF) - regPipeline = m_noTexZTestZWrite; - else - regPipeline = m_noTexZTestNoZWrite; - } - else - { - if (gen.x26c_27_ZBUF) - regPipeline = m_noTexNoZTestZWrite; - else - regPipeline = m_noTexNoZTestNoZWrite; - } + regPipeline = m_texAdditiveNoZTest; + } else { + if (gen.x26c_28_zTest) { + if (gen.x26c_27_ZBUF) + regPipeline = m_texZTestZWrite; + else + regPipeline = m_texZTestNoZWrite; + } else { + if (gen.x26c_27_ZBUF) + regPipeline = m_texNoZTestZWrite; + else + regPipeline = m_texNoZTestNoZWrite; } + } } - - if (desc->x45_24_x31_26_PMUS) - { - if (desc->x54_x40_TEXR) - { - redToAlphaPipelinePmus = m_texRedToAlphaZTest; - if (desc->x44_31_x31_25_PMAB) - regPipelinePmus = m_texAdditiveZTest; - else - regPipelinePmus = m_texZTestZWrite; - } + } else { + if (gen.x26c_26_AAPH) { + if (gen.x26c_28_zTest) + regPipeline = m_noTexAdditiveZTest; + else + regPipeline = m_noTexAdditiveNoZTest; + } else { + if (gen.x26c_28_zTest) { + if (gen.x26c_27_ZBUF) + regPipeline = m_noTexZTestZWrite; else - { - if (desc->x44_31_x31_25_PMAB) - regPipelinePmus = m_noTexAdditiveZTest; - else - regPipelinePmus = m_noTexZTestZWrite; - } + regPipeline = m_noTexZTestNoZWrite; + } else { + if (gen.x26c_27_ZBUF) + regPipeline = m_noTexNoZTestZWrite; + else + regPipeline = m_noTexNoZTestNoZWrite; + } } + } - CUVElement* texr = desc->x54_x40_TEXR.get(); - CUVElement* tind = desc->x58_x44_TIND.get(); - int texCount = 0; - boo::ObjToken textures[3]; - - if (texr) - { - textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture(); - texCount = 1; - if (gen.m_instBuf) - { - if (tind) - { - textures[1] = CGraphics::g_SpareTexture.get(); - textures[2] = tind->GetValueTexture(0).GetObj()->GetBooTexture(); - texCount = 3; - } - } + if (desc->x45_24_x31_26_PMUS) { + if (desc->x54_x40_TEXR) { + redToAlphaPipelinePmus = m_texRedToAlphaZTest; + if (desc->x44_31_x31_25_PMAB) + regPipelinePmus = m_texAdditiveZTest; + else + regPipelinePmus = m_texZTestZWrite; + } else { + if (desc->x44_31_x31_25_PMAB) + regPipelinePmus = m_noTexAdditiveZTest; + else + regPipelinePmus = m_noTexZTestZWrite; } + } - if (gen.m_instBuf) - { - boo::ObjToken uniforms[] = {gen.m_uniformBuf.get()}; + CUVElement* texr = desc->x54_x40_TEXR.get(); + CUVElement* tind = desc->x58_x44_TIND.get(); + int texCount = 0; + boo::ObjToken textures[3]; - if (regPipeline) - gen.m_normalDataBind = ctx.newShaderDataBinding(regPipeline, nullptr, - gen.m_instBuf.get(), nullptr, 1, uniforms, - nullptr, texCount, textures, nullptr, nullptr); - if (regPipelineSub) - gen.m_normalSubDataBind = ctx.newShaderDataBinding(regPipelineSub, nullptr, - gen.m_instBuf.get(), nullptr, 1, uniforms, - nullptr, texCount, textures, nullptr, nullptr); - if (redToAlphaPipeline) - gen.m_redToAlphaDataBind = ctx.newShaderDataBinding(redToAlphaPipeline, nullptr, - gen.m_instBuf.get(), nullptr, 1, uniforms, - nullptr, texCount, textures, nullptr, nullptr); - if (redToAlphaPipelineSub) - gen.m_redToAlphaSubDataBind = ctx.newShaderDataBinding(redToAlphaPipelineSub, nullptr, - gen.m_instBuf.get(), nullptr, 1, uniforms, - nullptr, texCount, textures, nullptr, nullptr); + if (texr) { + textures[0] = texr->GetValueTexture(0).GetObj()->GetBooTexture(); + texCount = 1; + if (gen.m_instBuf) { + if (tind) { + textures[1] = CGraphics::g_SpareTexture.get(); + textures[2] = tind->GetValueTexture(0).GetObj()->GetBooTexture(); + texCount = 3; + } } + } - if (gen.m_instBufPmus) - { - boo::ObjToken uniforms[] = {gen.m_uniformBufPmus.get()}; - texCount = std::min(texCount, 1); + if (gen.m_instBuf) { + boo::ObjToken uniforms[] = {gen.m_uniformBuf.get()}; - if (regPipelinePmus) - gen.m_normalDataBindPmus = ctx.newShaderDataBinding(regPipelinePmus, nullptr, - gen.m_instBufPmus.get(), nullptr, 1, uniforms, - nullptr, texCount, textures, nullptr, nullptr); - if (redToAlphaPipelinePmus) - gen.m_redToAlphaDataBindPmus = ctx.newShaderDataBinding(redToAlphaPipelinePmus, nullptr, - gen.m_instBufPmus.get(), nullptr, 1, uniforms, - nullptr, texCount, textures, nullptr, nullptr); - } + if (regPipeline) + gen.m_normalDataBind = ctx.newShaderDataBinding(regPipeline, nullptr, gen.m_instBuf.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + if (regPipelineSub) + gen.m_normalSubDataBind = ctx.newShaderDataBinding(regPipelineSub, nullptr, gen.m_instBuf.get(), nullptr, 1, + uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (redToAlphaPipeline) + gen.m_redToAlphaDataBind = ctx.newShaderDataBinding(redToAlphaPipeline, nullptr, gen.m_instBuf.get(), nullptr, 1, + uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (redToAlphaPipelineSub) + gen.m_redToAlphaSubDataBind = + ctx.newShaderDataBinding(redToAlphaPipelineSub, nullptr, gen.m_instBuf.get(), nullptr, 1, uniforms, nullptr, + texCount, textures, nullptr, nullptr); + } + + if (gen.m_instBufPmus) { + boo::ObjToken uniforms[] = {gen.m_uniformBufPmus.get()}; + texCount = std::min(texCount, 1); + + if (regPipelinePmus) + gen.m_normalDataBindPmus = ctx.newShaderDataBinding(regPipelinePmus, nullptr, gen.m_instBufPmus.get(), nullptr, 1, + uniforms, nullptr, texCount, textures, nullptr, nullptr); + if (redToAlphaPipelinePmus) + gen.m_redToAlphaDataBindPmus = + ctx.newShaderDataBinding(redToAlphaPipelinePmus, nullptr, gen.m_instBufPmus.get(), nullptr, 1, uniforms, + nullptr, texCount, textures, nullptr, nullptr); + } } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CElementGenShaders.hpp b/Runtime/Graphics/Shaders/CElementGenShaders.hpp index e8163e150..a19b91c0e 100644 --- a/Runtime/Graphics/Shaders/CElementGenShaders.hpp +++ b/Runtime/Graphics/Shaders/CElementGenShaders.hpp @@ -3,55 +3,47 @@ #include "Graphics/CGraphics.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { class CElementGen; -class CElementGenShaders -{ +class CElementGenShaders { public: - enum class EShaderClass - { - Tex, - IndTex, - NoTex - }; + enum class EShaderClass { Tex, IndTex, NoTex }; private: - static boo::ObjToken m_texZTestZWrite; - static boo::ObjToken m_texNoZTestZWrite; - static boo::ObjToken m_texZTestNoZWrite; - static boo::ObjToken m_texNoZTestNoZWrite; - static boo::ObjToken m_texAdditiveZTest; - static boo::ObjToken m_texAdditiveNoZTest; - static boo::ObjToken m_texRedToAlphaZTest; - static boo::ObjToken m_texRedToAlphaNoZTest; - static boo::ObjToken m_texZTestNoZWriteSub; - static boo::ObjToken m_texNoZTestNoZWriteSub; - static boo::ObjToken m_texRedToAlphaZTestSub; - static boo::ObjToken m_texRedToAlphaNoZTestSub; + static boo::ObjToken m_texZTestZWrite; + static boo::ObjToken m_texNoZTestZWrite; + static boo::ObjToken m_texZTestNoZWrite; + static boo::ObjToken m_texNoZTestNoZWrite; + static boo::ObjToken m_texAdditiveZTest; + static boo::ObjToken m_texAdditiveNoZTest; + static boo::ObjToken m_texRedToAlphaZTest; + static boo::ObjToken m_texRedToAlphaNoZTest; + static boo::ObjToken m_texZTestNoZWriteSub; + static boo::ObjToken m_texNoZTestNoZWriteSub; + static boo::ObjToken m_texRedToAlphaZTestSub; + static boo::ObjToken m_texRedToAlphaNoZTestSub; - static boo::ObjToken m_indTexZWrite; - static boo::ObjToken m_indTexNoZWrite; - static boo::ObjToken m_indTexAdditive; + static boo::ObjToken m_indTexZWrite; + static boo::ObjToken m_indTexNoZWrite; + static boo::ObjToken m_indTexAdditive; - static boo::ObjToken m_cindTexZWrite; - static boo::ObjToken m_cindTexNoZWrite; - static boo::ObjToken m_cindTexAdditive; + static boo::ObjToken m_cindTexZWrite; + static boo::ObjToken m_cindTexNoZWrite; + static boo::ObjToken m_cindTexAdditive; - static boo::ObjToken m_noTexZTestZWrite; - static boo::ObjToken m_noTexNoZTestZWrite; - static boo::ObjToken m_noTexZTestNoZWrite; - static boo::ObjToken m_noTexNoZTestNoZWrite; - static boo::ObjToken m_noTexAdditiveZTest; - static boo::ObjToken m_noTexAdditiveNoZTest; + static boo::ObjToken m_noTexZTestZWrite; + static boo::ObjToken m_noTexNoZTestZWrite; + static boo::ObjToken m_noTexZTestNoZWrite; + static boo::ObjToken m_noTexNoZTestNoZWrite; + static boo::ObjToken m_noTexAdditiveZTest; + static boo::ObjToken m_noTexAdditiveNoZTest; public: - static void Initialize(); - static void Shutdown(); - static EShaderClass GetShaderClass(CElementGen& gen); - static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CElementGen& gen); + static void Initialize(); + static void Shutdown(); + static EShaderClass GetShaderClass(CElementGen& gen); + static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CElementGen& gen); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CEnergyBarShader.cpp b/Runtime/Graphics/Shaders/CEnergyBarShader.cpp index 7c780f4d4..0d51998d0 100644 --- a/Runtime/Graphics/Shaders/CEnergyBarShader.cpp +++ b/Runtime/Graphics/Shaders/CEnergyBarShader.cpp @@ -3,99 +3,79 @@ #include "Graphics/CGraphics.hpp" #include "Graphics/CTexture.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; -void CEnergyBarShader::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CEnergyBarShader{}); +void CEnergyBarShader::Initialize() { s_Pipeline = hecl::conv->convert(Shader_CEnergyBarShader{}); } + +void CEnergyBarShader::Shutdown() { s_Pipeline.reset(); } + +void CEnergyBarShader::updateModelMatrix() { + m_uniform.m_matrix = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); } -void CEnergyBarShader::Shutdown() -{ - s_Pipeline.reset(); +void CEnergyBarShader::draw(const zeus::CColor& color0, const std::vector& verts0, const zeus::CColor& color1, + const std::vector& verts1, const zeus::CColor& color2, + const std::vector& verts2, const CTexture* tex) { + size_t totalVerts = verts0.size() + verts1.size() + verts2.size(); + if (!totalVerts) + return; + + if (totalVerts > m_maxVerts) { + m_maxVerts = totalVerts; + m_tex = tex; + CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), m_maxVerts); + boo::ObjToken bufs[1]; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {m_tex->GetBooTexture()}; + for (int i = 0; i < 3; ++i) { + m_uniBuf[i] = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + bufs[0] = m_uniBuf[i].get(); + m_dataBind[i] = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, + nullptr, 1, texs, nullptr, nullptr); + } + return true; + } BooTrace); + } + + size_t vertIter = 0; + Vertex* verts = reinterpret_cast(m_vbo->map(sizeof(Vertex) * totalVerts)); + if (verts0.size()) { + memmove(verts, verts0.data(), sizeof(Vertex) * verts0.size()); + vertIter += verts0.size(); + } + if (verts1.size()) { + memmove(verts + vertIter, verts1.data(), sizeof(Vertex) * verts1.size()); + vertIter += verts1.size(); + } + if (verts2.size()) { + memmove(verts + vertIter, verts2.data(), sizeof(Vertex) * verts2.size()); + } + m_vbo->unmap(); + + vertIter = 0; + if (verts0.size()) { + m_uniform.m_color = color0; + m_uniBuf[0]->load(&m_uniform, sizeof(Uniform)); + CGraphics::SetShaderDataBinding(m_dataBind[0]); + CGraphics::DrawArray(0, verts0.size()); + vertIter += verts0.size(); + } + if (verts1.size()) { + m_uniform.m_color = color1; + m_uniBuf[1]->load(&m_uniform, sizeof(Uniform)); + CGraphics::SetShaderDataBinding(m_dataBind[1]); + CGraphics::DrawArray(vertIter, verts1.size()); + vertIter += verts1.size(); + } + if (verts2.size()) { + m_uniform.m_color = color2; + m_uniBuf[2]->load(&m_uniform, sizeof(Uniform)); + CGraphics::SetShaderDataBinding(m_dataBind[2]); + CGraphics::DrawArray(vertIter, verts2.size()); + } } -void CEnergyBarShader::updateModelMatrix() -{ - m_uniform.m_matrix = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); -} - -void CEnergyBarShader::draw(const zeus::CColor& color0, const std::vector& verts0, - const zeus::CColor& color1, const std::vector& verts1, - const zeus::CColor& color2, const std::vector& verts2, - const CTexture* tex) -{ - size_t totalVerts = verts0.size() + verts1.size() + verts2.size(); - if (!totalVerts) - return; - - if (totalVerts > m_maxVerts) - { - m_maxVerts = totalVerts; - m_tex = tex; - CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), m_maxVerts); - boo::ObjToken bufs[1]; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {m_tex->GetBooTexture()}; - for (int i=0 ; i<3 ; ++i) - { - m_uniBuf[i] = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - bufs[0] = m_uniBuf[i].get(); - m_dataBind[i] = ctx.newShaderDataBinding(s_Pipeline, - m_vbo.get(), nullptr, nullptr, 1, bufs, stages, - nullptr, nullptr, 1, texs, nullptr, nullptr); - } - return true; - } BooTrace); - } - - size_t vertIter = 0; - Vertex* verts = reinterpret_cast(m_vbo->map(sizeof(Vertex) * totalVerts)); - if (verts0.size()) - { - memmove(verts, verts0.data(), sizeof(Vertex) * verts0.size()); - vertIter += verts0.size(); - } - if (verts1.size()) - { - memmove(verts + vertIter, verts1.data(), sizeof(Vertex) * verts1.size()); - vertIter += verts1.size(); - } - if (verts2.size()) - { - memmove(verts + vertIter, verts2.data(), sizeof(Vertex) * verts2.size()); - } - m_vbo->unmap(); - - vertIter = 0; - if (verts0.size()) - { - m_uniform.m_color = color0; - m_uniBuf[0]->load(&m_uniform, sizeof(Uniform)); - CGraphics::SetShaderDataBinding(m_dataBind[0]); - CGraphics::DrawArray(0, verts0.size()); - vertIter += verts0.size(); - } - if (verts1.size()) - { - m_uniform.m_color = color1; - m_uniBuf[1]->load(&m_uniform, sizeof(Uniform)); - CGraphics::SetShaderDataBinding(m_dataBind[1]); - CGraphics::DrawArray(vertIter, verts1.size()); - vertIter += verts1.size(); - } - if (verts2.size()) - { - m_uniform.m_color = color2; - m_uniBuf[2]->load(&m_uniform, sizeof(Uniform)); - CGraphics::SetShaderDataBinding(m_dataBind[2]); - CGraphics::DrawArray(vertIter, verts2.size()); - } -} - -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CEnergyBarShader.hpp b/Runtime/Graphics/Shaders/CEnergyBarShader.hpp index 1461406a2..fd5ecd127 100644 --- a/Runtime/Graphics/Shaders/CEnergyBarShader.hpp +++ b/Runtime/Graphics/Shaders/CEnergyBarShader.hpp @@ -5,40 +5,34 @@ #include "zeus/CRectangle.hpp" #include "Camera/CCameraFilter.hpp" -namespace urde -{ +namespace urde { -class CEnergyBarShader -{ +class CEnergyBarShader { public: - struct Vertex - { - zeus::CVector3f pos; - zeus::CVector2f uv; - }; + struct Vertex { + zeus::CVector3f pos; + zeus::CVector2f uv; + }; private: - struct Uniform - { - zeus::CMatrix4f m_matrix; - zeus::CColor m_color; - }; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf[3]; - boo::ObjToken m_dataBind[3]; - Uniform m_uniform; - const CTexture* m_tex = nullptr; - size_t m_maxVerts = 0; + struct Uniform { + zeus::CMatrix4f m_matrix; + zeus::CColor m_color; + }; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf[3]; + boo::ObjToken m_dataBind[3]; + Uniform m_uniform; + const CTexture* m_tex = nullptr; + size_t m_maxVerts = 0; public: - static void Initialize(); - static void Shutdown(); - void updateModelMatrix(); - void draw(const zeus::CColor& color0, const std::vector& verts0, - const zeus::CColor& color1, const std::vector& verts1, - const zeus::CColor& color2, const std::vector& verts2, - const CTexture* tex); + static void Initialize(); + static void Shutdown(); + void updateModelMatrix(); + void draw(const zeus::CColor& color0, const std::vector& verts0, const zeus::CColor& color1, + const std::vector& verts1, const zeus::CColor& color2, const std::vector& verts2, + const CTexture* tex); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CEnvFxShaders.cpp b/Runtime/Graphics/Shaders/CEnvFxShaders.cpp index e6fa5cb86..fdde425f7 100644 --- a/Runtime/Graphics/Shaders/CEnvFxShaders.cpp +++ b/Runtime/Graphics/Shaders/CEnvFxShaders.cpp @@ -2,44 +2,37 @@ #include "hecl/Pipeline.hpp" #include "World/CEnvFxManager.hpp" -namespace urde -{ +namespace urde { boo::ObjToken CEnvFxShaders::m_snowPipeline; boo::ObjToken CEnvFxShaders::m_underwaterPipeline; -void CEnvFxShaders::Initialize() -{ - m_snowPipeline = hecl::conv->convert(Shader_CEnvFxSnowShader{}); - m_underwaterPipeline = hecl::conv->convert(Shader_CEnvFxUnderwaterShader{}); +void CEnvFxShaders::Initialize() { + m_snowPipeline = hecl::conv->convert(Shader_CEnvFxSnowShader{}); + m_underwaterPipeline = hecl::conv->convert(Shader_CEnvFxUnderwaterShader{}); } -void CEnvFxShaders::Shutdown() -{ - m_snowPipeline.reset(); - m_underwaterPipeline.reset(); +void CEnvFxShaders::Shutdown() { + m_snowPipeline.reset(); + m_underwaterPipeline.reset(); } -void CEnvFxShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, - CEnvFxManager& fxMgr, CEnvFxManagerGrid& grid) -{ - auto uBufInfo = grid.m_uniformBuf.getBufferInfo(); - auto iBufInfo = grid.m_instBuf.getBufferInfo(); - boo::ObjToken uniforms[] = {uBufInfo.first.get(), - fxMgr.m_fogUniformBuf.get()}; - size_t ubufOffsets[] = {size_t(uBufInfo.second), 0}; - size_t ubufSizes[] = {sizeof(CEnvFxShaders::Uniform), sizeof(CGraphics::g_Fog)}; - boo::PipelineStage uniformStages[] = {boo::PipelineStage::Vertex, boo::PipelineStage::Fragment}; - boo::ObjToken textures[] = {fxMgr.xb74_txtrSnowFlake->GetBooTexture(), - fxMgr.x40_txtrEnvGradient->GetBooTexture()}; - grid.m_snowBinding = ctx.newShaderDataBinding(m_snowPipeline, nullptr, - iBufInfo.first.get(), nullptr, 2, uniforms, - uniformStages, ubufOffsets, ubufSizes, - 2, textures, nullptr, nullptr, 0, iBufInfo.second); - textures[0] = fxMgr.xc48_underwaterFlake->GetBooTexture(); - grid.m_underwaterBinding = ctx.newShaderDataBinding(m_underwaterPipeline, nullptr, - iBufInfo.first.get(), nullptr, 2, uniforms, - uniformStages, ubufOffsets, ubufSizes, - 2, textures, nullptr, nullptr, 0, iBufInfo.second); +void CEnvFxShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CEnvFxManager& fxMgr, + CEnvFxManagerGrid& grid) { + auto uBufInfo = grid.m_uniformBuf.getBufferInfo(); + auto iBufInfo = grid.m_instBuf.getBufferInfo(); + boo::ObjToken uniforms[] = {uBufInfo.first.get(), fxMgr.m_fogUniformBuf.get()}; + size_t ubufOffsets[] = {size_t(uBufInfo.second), 0}; + size_t ubufSizes[] = {sizeof(CEnvFxShaders::Uniform), sizeof(CGraphics::g_Fog)}; + boo::PipelineStage uniformStages[] = {boo::PipelineStage::Vertex, boo::PipelineStage::Fragment}; + boo::ObjToken textures[] = {fxMgr.xb74_txtrSnowFlake->GetBooTexture(), + fxMgr.x40_txtrEnvGradient->GetBooTexture()}; + grid.m_snowBinding = + ctx.newShaderDataBinding(m_snowPipeline, nullptr, iBufInfo.first.get(), nullptr, 2, uniforms, uniformStages, + ubufOffsets, ubufSizes, 2, textures, nullptr, nullptr, 0, iBufInfo.second); + textures[0] = fxMgr.xc48_underwaterFlake->GetBooTexture(); + grid.m_underwaterBinding = + ctx.newShaderDataBinding(m_underwaterPipeline, nullptr, iBufInfo.first.get(), nullptr, 2, uniforms, uniformStages, + ubufOffsets, ubufSizes, 2, textures, nullptr, nullptr, 0, iBufInfo.second); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CEnvFxShaders.hpp b/Runtime/Graphics/Shaders/CEnvFxShaders.hpp index 58c0a1fb0..aa5de7b8a 100644 --- a/Runtime/Graphics/Shaders/CEnvFxShaders.hpp +++ b/Runtime/Graphics/Shaders/CEnvFxShaders.hpp @@ -3,37 +3,33 @@ #include "Graphics/CGraphics.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { class CEnvFxManager; class CEnvFxManagerGrid; -class CEnvFxShaders -{ +class CEnvFxShaders { public: - struct Instance - { - zeus::CVector3f positions[4]; - zeus::CColor color; - zeus::CVector2f uvs[4]; - }; - struct Uniform - { - zeus::CMatrix4f mv; - zeus::CMatrix4f proj; - zeus::CMatrix4f envMtx; - zeus::CColor moduColor; - }; + struct Instance { + zeus::CVector3f positions[4]; + zeus::CColor color; + zeus::CVector2f uvs[4]; + }; + struct Uniform { + zeus::CMatrix4f mv; + zeus::CMatrix4f proj; + zeus::CMatrix4f envMtx; + zeus::CColor moduColor; + }; private: - static boo::ObjToken m_snowPipeline; - static boo::ObjToken m_underwaterPipeline; + static boo::ObjToken m_snowPipeline; + static boo::ObjToken m_underwaterPipeline; public: - static void Initialize(); - static void Shutdown(); - static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, - CEnvFxManager& fxMgr, CEnvFxManagerGrid& grid); + static void Initialize(); + static void Shutdown(); + static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CEnvFxManager& fxMgr, + CEnvFxManagerGrid& grid); }; -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp index c3bc45091..7d0d0a8df 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp @@ -3,292 +3,255 @@ #include "World/CRippleManager.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { CFluidPlaneShader::Cache CFluidPlaneShader::_cache = {}; -u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneShaderInfo& info) -{ - u16 ret = 0; +u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneShaderInfo& info) { + u16 ret = 0; - switch (info.m_type) - { - case EFluidType::NormalWater: - case EFluidType::PhazonFluid: - case EFluidType::Four: - if (info.m_hasLightmap) - { - ret |= 1 << 2; - if (info.m_doubleLightmapBlend) - ret |= 1 << 3; - } - - if (!info.m_hasEnvMap && info.m_hasEnvBumpMap) - ret |= 1 << 4; - - if (info.m_hasEnvMap) - ret |= 1 << 5; - - break; - - case EFluidType::PoisonWater: - ret |= 1; - - if (info.m_hasLightmap) - { - ret |= 1 << 2; - if (info.m_doubleLightmapBlend) - ret |= 1 << 3; - } - - if (info.m_hasEnvBumpMap) - ret |= 1 << 4; - - break; - - case EFluidType::Lava: - ret |= 2; - - if (info.m_hasBumpMap) - ret |= 1 << 2; - - break; - - case EFluidType::ThickLava: - ret |= 3; - - if (info.m_hasBumpMap) - ret |= 1 << 2; - - break; + switch (info.m_type) { + case EFluidType::NormalWater: + case EFluidType::PhazonFluid: + case EFluidType::Four: + if (info.m_hasLightmap) { + ret |= 1 << 2; + if (info.m_doubleLightmapBlend) + ret |= 1 << 3; } - if (info.m_hasPatternTex1) - ret |= 1 << 6; - if (info.m_hasPatternTex2) - ret |= 1 << 7; - if (info.m_hasColorTex) - ret |= 1 << 8; + if (!info.m_hasEnvMap && info.m_hasEnvBumpMap) + ret |= 1 << 4; - if (info.m_additive) - ret |= 1 << 9; + if (info.m_hasEnvMap) + ret |= 1 << 5; - return ret; + break; + + case EFluidType::PoisonWater: + ret |= 1; + + if (info.m_hasLightmap) { + ret |= 1 << 2; + if (info.m_doubleLightmapBlend) + ret |= 1 << 3; + } + + if (info.m_hasEnvBumpMap) + ret |= 1 << 4; + + break; + + case EFluidType::Lava: + ret |= 2; + + if (info.m_hasBumpMap) + ret |= 1 << 2; + + break; + + case EFluidType::ThickLava: + ret |= 3; + + if (info.m_hasBumpMap) + ret |= 1 << 2; + + break; + } + + if (info.m_hasPatternTex1) + ret |= 1 << 6; + if (info.m_hasPatternTex2) + ret |= 1 << 7; + if (info.m_hasColorTex) + ret |= 1 << 8; + + if (info.m_additive) + ret |= 1 << 9; + + return ret; } -u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneDoorShaderInfo& info) -{ - u16 ret = 0; +u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneDoorShaderInfo& info) { + u16 ret = 0; - if (info.m_hasPatternTex1) - ret |= 1 << 0; - if (info.m_hasPatternTex2) - ret |= 1 << 1; - if (info.m_hasColorTex) - ret |= 1 << 2; + if (info.m_hasPatternTex1) + ret |= 1 << 0; + if (info.m_hasPatternTex2) + ret |= 1 << 1; + if (info.m_hasColorTex) + ret |= 1 << 2; - return ret; + return ret; } -template<> CFluidPlaneShader::ShaderPair -CFluidPlaneShader::Cache::GetOrBuildShader(const SFluidPlaneShaderInfo& info) -{ - u16 key = MakeCacheKey(info); - auto& slot = CacheSlot(info, key); - if (slot.m_regular) - return slot; - - slot.m_regular = hecl::conv->convert(Shader_CFluidPlaneShader{info, false}); - if (info.m_tessellation) - slot.m_tessellation = hecl::conv->convert(Shader_CFluidPlaneShader{info, true}); - +template <> +CFluidPlaneShader::ShaderPair +CFluidPlaneShader::Cache::GetOrBuildShader(const SFluidPlaneShaderInfo& info) { + u16 key = MakeCacheKey(info); + auto& slot = CacheSlot(info, key); + if (slot.m_regular) return slot; + + slot.m_regular = hecl::conv->convert(Shader_CFluidPlaneShader{info, false}); + if (info.m_tessellation) + slot.m_tessellation = hecl::conv->convert(Shader_CFluidPlaneShader{info, true}); + + return slot; } -template<> CFluidPlaneShader::ShaderPair -CFluidPlaneShader::Cache::GetOrBuildShader(const SFluidPlaneDoorShaderInfo& info) -{ - u16 key = MakeCacheKey(info); - auto& slot = CacheSlot(info, key); - if (slot.m_regular) - return slot; - - slot.m_regular = hecl::conv->convert(Shader_CFluidPlaneDoorShader{info}); - +template <> +CFluidPlaneShader::ShaderPair +CFluidPlaneShader::Cache::GetOrBuildShader(const SFluidPlaneDoorShaderInfo& info) { + u16 key = MakeCacheKey(info); + auto& slot = CacheSlot(info, key); + if (slot.m_regular) return slot; + + slot.m_regular = hecl::conv->convert(Shader_CFluidPlaneDoorShader{info}); + + return slot; } -void CFluidPlaneShader::Cache::Clear() -{ - for (auto& p : m_cache) - p.reset(); - for (auto& p : m_doorCache) - p.reset(); +void CFluidPlaneShader::Cache::Clear() { + for (auto& p : m_cache) + p.reset(); + for (auto& p : m_doorCache) + p.reset(); } -void CFluidPlaneShader::PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount) -{ - CGraphics::CommitResources( - [&](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount); - if (pipeline.m_tessellation) - m_pvbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(PatchVertex), maxVertCount); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); +void CFluidPlaneShader::PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount) { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount); + if (pipeline.m_tessellation) + m_pvbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(PatchVertex), maxVertCount); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken ubufs[] = { m_uniBuf.get(), m_uniBuf.get(), m_uniBuf.get() }; - boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex, - boo::PipelineStage::Fragment }; - size_t ubufOffs[] = {0, 0, 1280}; - size_t ubufSizes[] = {1280, 1280, sizeof(CModelShaders::LightingUniform)}; - size_t texCount = 0; - boo::ObjToken texs[8]; - if (m_patternTex1) - texs[texCount++] = m_patternTex1->GetBooTexture(); - if (m_patternTex2) - texs[texCount++] = m_patternTex2->GetBooTexture(); - if (m_colorTex) - texs[texCount++] = m_colorTex->GetBooTexture(); - if (m_bumpMap) - texs[texCount++] = m_bumpMap->GetBooTexture(); - if (m_envMap) - texs[texCount++] = m_envMap->GetBooTexture(); - if (m_envBumpMap) - texs[texCount++] = m_envBumpMap->GetBooTexture(); - if (m_lightmap) - texs[texCount++] = m_lightmap->GetBooTexture(); - auto regular = ctx.newShaderDataBinding(pipeline.m_regular, m_vbo.get(), nullptr, nullptr, 3, - ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr); - boo::ObjToken tessellation; - if (pipeline.m_tessellation) - { - texs[texCount++] = m_rippleMap.get(); - tessellation = ctx.newShaderDataBinding(pipeline.m_tessellation, m_pvbo.get(), nullptr, nullptr, 3, - ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr); - } - m_dataBind = {regular, tessellation}; - return true; - } BooTrace); + boo::ObjToken ubufs[] = {m_uniBuf.get(), m_uniBuf.get(), m_uniBuf.get()}; + boo::PipelineStage ubufStages[] = {boo::PipelineStage::Vertex, boo::PipelineStage::Vertex, + boo::PipelineStage::Fragment}; + size_t ubufOffs[] = {0, 0, 1280}; + size_t ubufSizes[] = {1280, 1280, sizeof(CModelShaders::LightingUniform)}; + size_t texCount = 0; + boo::ObjToken texs[8]; + if (m_patternTex1) + texs[texCount++] = m_patternTex1->GetBooTexture(); + if (m_patternTex2) + texs[texCount++] = m_patternTex2->GetBooTexture(); + if (m_colorTex) + texs[texCount++] = m_colorTex->GetBooTexture(); + if (m_bumpMap) + texs[texCount++] = m_bumpMap->GetBooTexture(); + if (m_envMap) + texs[texCount++] = m_envMap->GetBooTexture(); + if (m_envBumpMap) + texs[texCount++] = m_envBumpMap->GetBooTexture(); + if (m_lightmap) + texs[texCount++] = m_lightmap->GetBooTexture(); + auto regular = ctx.newShaderDataBinding(pipeline.m_regular, m_vbo.get(), nullptr, nullptr, 3, ubufs, ubufStages, + ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr); + boo::ObjToken tessellation; + if (pipeline.m_tessellation) { + texs[texCount++] = m_rippleMap.get(); + tessellation = ctx.newShaderDataBinding(pipeline.m_tessellation, m_pvbo.get(), nullptr, nullptr, 3, ubufs, + ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr); + } + m_dataBind = {regular, tessellation}; + return true; + } BooTrace); } -void CFluidPlaneShader::Shutdown() -{ - _cache.Clear(); -} +void CFluidPlaneShader::Shutdown() { _cache.Clear(); } -CFluidPlaneShader::CFluidPlaneShader(EFluidType type, - const TLockedToken& patternTex1, - const TLockedToken& patternTex2, - const TLockedToken& colorTex, - const TLockedToken& bumpMap, - const TLockedToken& envMap, - const TLockedToken& envBumpMap, - const TLockedToken& lightmap, - const boo::ObjToken& rippleMap, - bool doubleLightmapBlend, bool additive, u32 maxVertCount) -: m_patternTex1(patternTex1), - m_patternTex2(patternTex2), - m_colorTex(colorTex), - m_bumpMap(bumpMap), - m_envMap(envMap), - m_envBumpMap(envBumpMap), - m_lightmap(lightmap), - m_rippleMap(rippleMap) -{ - SFluidPlaneShaderInfo shaderInfo(type, - m_patternTex1.operator bool(), - m_patternTex2.operator bool(), - m_colorTex.operator bool(), - m_bumpMap.operator bool(), - m_envMap.operator bool(), - m_envBumpMap.operator bool(), - m_lightmap.operator bool(), - m_rippleMap.operator bool(), - doubleLightmapBlend, additive); - ShaderPair pipeline = _cache.GetOrBuildShader(shaderInfo); - PrepareBinding(pipeline, maxVertCount); +CFluidPlaneShader::CFluidPlaneShader(EFluidType type, const TLockedToken& patternTex1, + const TLockedToken& patternTex2, const TLockedToken& colorTex, + const TLockedToken& bumpMap, const TLockedToken& envMap, + const TLockedToken& envBumpMap, const TLockedToken& lightmap, + const boo::ObjToken& rippleMap, bool doubleLightmapBlend, + bool additive, u32 maxVertCount) +: m_patternTex1(patternTex1) +, m_patternTex2(patternTex2) +, m_colorTex(colorTex) +, m_bumpMap(bumpMap) +, m_envMap(envMap) +, m_envBumpMap(envBumpMap) +, m_lightmap(lightmap) +, m_rippleMap(rippleMap) { + SFluidPlaneShaderInfo shaderInfo(type, m_patternTex1.operator bool(), m_patternTex2.operator bool(), + m_colorTex.operator bool(), m_bumpMap.operator bool(), m_envMap.operator bool(), + m_envBumpMap.operator bool(), m_lightmap.operator bool(), + m_rippleMap.operator bool(), doubleLightmapBlend, additive); + ShaderPair pipeline = _cache.GetOrBuildShader(shaderInfo); + PrepareBinding(pipeline, maxVertCount); } CFluidPlaneShader::CFluidPlaneShader(const TLockedToken& patternTex1, - const TLockedToken& patternTex2, - const TLockedToken& colorTex, + const TLockedToken& patternTex2, const TLockedToken& colorTex, u32 maxVertCount) -: m_patternTex1(patternTex1), - m_patternTex2(patternTex2), - m_colorTex(colorTex) -{ - SFluidPlaneDoorShaderInfo shaderInfo(m_patternTex1.operator bool(), - m_patternTex2.operator bool(), - m_colorTex.operator bool()); - ShaderPair pipeline = _cache.GetOrBuildShader(shaderInfo); - PrepareBinding(pipeline, maxVertCount); +: m_patternTex1(patternTex1), m_patternTex2(patternTex2), m_colorTex(colorTex) { + SFluidPlaneDoorShaderInfo shaderInfo(m_patternTex1.operator bool(), m_patternTex2.operator bool(), + m_colorTex.operator bool()); + ShaderPair pipeline = _cache.GetOrBuildShader(shaderInfo); + PrepareBinding(pipeline, maxVertCount); } -void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info) -{ - Uniform& uni = *reinterpret_cast(m_uniBuf->map(sizeof(Uniform))); - uni.m_mv = CGraphics::g_GXModelView.toMatrix4f(); - uni.m_mvNorm = info.normMtx; - uni.m_proj = CGraphics::GetPerspectiveProjectionMatrix(true); - for (int i=0 ; i<6 ; ++i) - uni.m_texMtxs[i] = info.texMtxs[i]; - uni.m_lighting.ActivateLights(info.lights); - for (int i=0 ; i<3 ; ++i) - uni.m_lighting.colorRegs[i] = info.kColors[i]; - uni.m_lighting.mulColor = info.kColors[3]; - uni.m_lighting.fog.m_rangeScale = info.indScale; - m_uniBuf->unmap(); +void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info) { + Uniform& uni = *reinterpret_cast(m_uniBuf->map(sizeof(Uniform))); + uni.m_mv = CGraphics::g_GXModelView.toMatrix4f(); + uni.m_mvNorm = info.normMtx; + uni.m_proj = CGraphics::GetPerspectiveProjectionMatrix(true); + for (int i = 0; i < 6; ++i) + uni.m_texMtxs[i] = info.texMtxs[i]; + uni.m_lighting.ActivateLights(info.lights); + for (int i = 0; i < 3; ++i) + uni.m_lighting.colorRegs[i] = info.kColors[i]; + uni.m_lighting.mulColor = info.kColors[3]; + uni.m_lighting.fog.m_rangeScale = info.indScale; + m_uniBuf->unmap(); } -void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info, - const zeus::CVector3f& waterCenter, - const CRippleManager& rippleManager, - const zeus::CColor& colorMul, - float rippleNormResolution) -{ - Uniform& uni = *reinterpret_cast(m_uniBuf->map(sizeof(Uniform))); - uni.m_mv = CGraphics::g_GXModelView.toMatrix4f(); - uni.m_mvNorm = info.normMtx; - uni.m_proj = CGraphics::GetPerspectiveProjectionMatrix(true); - for (int i=0 ; i<6 ; ++i) - uni.m_texMtxs[i] = info.texMtxs[i]; - int i = 0; - for (const CRipple& ripple : rippleManager.GetRipples()) - { - assert(i < 20 && "Too many ripples"); - Ripple& rOut = uni.m_ripple[i++]; - if (ripple.GetTime() >= ripple.GetTimeFalloff()) - { - rOut.center.zeroOut(); - rOut.params.zeroOut(); - continue; - } - zeus::CVector3f localPos = ripple.GetCenter() - waterCenter; - rOut.center.x() = float(localPos.x()); - rOut.center.y() = float(localPos.y()); - rOut.center.z() = ripple.GetTime() * ripple.GetOOTimeFalloff(); - rOut.center.w() = ripple.GetOODistanceFalloff(); - rOut.params.x() = ripple.GetAmplitude(); - rOut.params.y() = ripple.GetPhase(); - rOut.params.z() = (1.f - ripple.GetTime() * ripple.GetOOTimeFalloff() * - ripple.GetOOTimeFalloff()) * ripple.GetFrequency(); +void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info, const zeus::CVector3f& waterCenter, + const CRippleManager& rippleManager, const zeus::CColor& colorMul, + float rippleNormResolution) { + Uniform& uni = *reinterpret_cast(m_uniBuf->map(sizeof(Uniform))); + uni.m_mv = CGraphics::g_GXModelView.toMatrix4f(); + uni.m_mvNorm = info.normMtx; + uni.m_proj = CGraphics::GetPerspectiveProjectionMatrix(true); + for (int i = 0; i < 6; ++i) + uni.m_texMtxs[i] = info.texMtxs[i]; + int i = 0; + for (const CRipple& ripple : rippleManager.GetRipples()) { + assert(i < 20 && "Too many ripples"); + Ripple& rOut = uni.m_ripple[i++]; + if (ripple.GetTime() >= ripple.GetTimeFalloff()) { + rOut.center.zeroOut(); + rOut.params.zeroOut(); + continue; } - uni.m_colorMul = colorMul; - uni.m_pad[0].x() = rippleNormResolution; - uni.m_lighting.ActivateLights(info.lights); - for (i=0 ; i<3 ; ++i) - uni.m_lighting.colorRegs[i] = info.kColors[i]; - uni.m_lighting.mulColor = info.kColors[3]; - uni.m_lighting.fog = CGraphics::g_Fog; - uni.m_pad2.x() = info.indScale; - m_uniBuf->unmap(); + zeus::CVector3f localPos = ripple.GetCenter() - waterCenter; + rOut.center.x() = float(localPos.x()); + rOut.center.y() = float(localPos.y()); + rOut.center.z() = ripple.GetTime() * ripple.GetOOTimeFalloff(); + rOut.center.w() = ripple.GetOODistanceFalloff(); + rOut.params.x() = ripple.GetAmplitude(); + rOut.params.y() = ripple.GetPhase(); + rOut.params.z() = + (1.f - ripple.GetTime() * ripple.GetOOTimeFalloff() * ripple.GetOOTimeFalloff()) * ripple.GetFrequency(); + } + uni.m_colorMul = colorMul; + uni.m_pad[0].x() = rippleNormResolution; + uni.m_lighting.ActivateLights(info.lights); + for (i = 0; i < 3; ++i) + uni.m_lighting.colorRegs[i] = info.kColors[i]; + uni.m_lighting.mulColor = info.kColors[3]; + uni.m_lighting.fog = CGraphics::g_Fog; + uni.m_pad2.x() = info.indScale; + m_uniBuf->unmap(); } -void CFluidPlaneShader::loadVerts(const std::vector& verts, const std::vector& pVerts) -{ - m_vbo->load(verts.data(), verts.size() * sizeof(Vertex)); - if (m_pvbo) - m_pvbo->load(pVerts.data(), pVerts.size() * sizeof(PatchVertex)); +void CFluidPlaneShader::loadVerts(const std::vector& verts, const std::vector& pVerts) { + m_vbo->load(verts.data(), verts.size() * sizeof(Vertex)); + if (m_pvbo) + m_pvbo->load(pVerts.data(), pVerts.size() * sizeof(PatchVertex)); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp b/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp index 0ee16082b..720f37398 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp @@ -9,192 +9,157 @@ #include "zeus/CAABox.hpp" #include "Shaders/shader_CFluidPlaneShader.hpp" -namespace urde -{ +namespace urde { -class CFluidPlaneShader -{ +class CFluidPlaneShader { public: - struct Vertex - { - zeus::CVector3f m_pos; - zeus::CVector3f m_norm; - zeus::CVector3f m_binorm; - zeus::CVector3f m_tangent; - zeus::CColor m_color; + struct Vertex { + zeus::CVector3f m_pos; + zeus::CVector3f m_norm; + zeus::CVector3f m_binorm; + zeus::CVector3f m_tangent; + zeus::CColor m_color; - Vertex() = default; - Vertex(const zeus::CVector3f& position) : m_pos(position) {} - Vertex(const zeus::CVector3f& position, const zeus::CColor& color) - : m_pos(position), m_color(color) {} - Vertex(const zeus::CVector3f& position, const zeus::CVector3f& normal, - const zeus::CColor& color) - : m_pos(position), m_norm(normal), m_color(color) {} - Vertex(const zeus::CVector3f& position, const zeus::CVector3f& normal, - const zeus::CVector3f& binormal, const zeus::CVector3f& tangent, - const zeus::CColor& color) - : m_pos(position), m_norm(normal), m_binorm(binormal), m_tangent(tangent), m_color(color) {} - }; + Vertex() = default; + Vertex(const zeus::CVector3f& position) : m_pos(position) {} + Vertex(const zeus::CVector3f& position, const zeus::CColor& color) : m_pos(position), m_color(color) {} + Vertex(const zeus::CVector3f& position, const zeus::CVector3f& normal, const zeus::CColor& color) + : m_pos(position), m_norm(normal), m_color(color) {} + Vertex(const zeus::CVector3f& position, const zeus::CVector3f& normal, const zeus::CVector3f& binormal, + const zeus::CVector3f& tangent, const zeus::CColor& color) + : m_pos(position), m_norm(normal), m_binorm(binormal), m_tangent(tangent), m_color(color) {} + }; - struct PatchVertex - { - zeus::CVector4f m_pos; - float m_outerLevels[4] = {}; - float m_innerLevels[4] = {}; - }; + struct PatchVertex { + zeus::CVector4f m_pos; + float m_outerLevels[4] = {}; + float m_innerLevels[4] = {}; + }; - struct RenderSetupInfo - { - zeus::CMatrix4f texMtxs[6]; - zeus::CMatrix4f normMtx; - float indScale = 1.f; - zeus::CColor kColors[4]; - std::vector lights; - }; + struct RenderSetupInfo { + zeus::CMatrix4f texMtxs[6]; + zeus::CMatrix4f normMtx; + float indScale = 1.f; + zeus::CColor kColors[4]; + std::vector lights; + }; private: - struct ShaderPair - { - boo::ObjToken m_regular; - boo::ObjToken m_tessellation; - void reset() - { - m_regular.reset(); - m_tessellation.reset(); - } - }; + struct ShaderPair { + boo::ObjToken m_regular; + boo::ObjToken m_tessellation; + void reset() { + m_regular.reset(); + m_tessellation.reset(); + } + }; - struct BindingPair - { - boo::ObjToken m_regular; - boo::ObjToken m_tessellation; - }; + struct BindingPair { + boo::ObjToken m_regular; + boo::ObjToken m_tessellation; + }; - class Cache - { - ShaderPair m_cache[1024] = {}; - ShaderPair m_doorCache[8] = {}; - ShaderPair& - CacheSlot(const SFluidPlaneShaderInfo& info, int i) { return m_cache[i]; } - ShaderPair& - CacheSlot(const SFluidPlaneDoorShaderInfo& info, int i) { return m_doorCache[i]; } - static u16 MakeCacheKey(const SFluidPlaneShaderInfo& info); - static u16 MakeCacheKey(const SFluidPlaneDoorShaderInfo& info); - public: - template - ShaderPair GetOrBuildShader(const T& info); - void Clear(); - }; - static Cache _cache; + class Cache { + ShaderPair m_cache[1024] = {}; + ShaderPair m_doorCache[8] = {}; + ShaderPair& CacheSlot(const SFluidPlaneShaderInfo& info, int i) { return m_cache[i]; } + ShaderPair& CacheSlot(const SFluidPlaneDoorShaderInfo& info, int i) { return m_doorCache[i]; } + static u16 MakeCacheKey(const SFluidPlaneShaderInfo& info); + static u16 MakeCacheKey(const SFluidPlaneDoorShaderInfo& info); - struct Ripple - { - zeus::CVector4f center; // time, distFalloff - zeus::CVector4f params; // amplitude, lookupPhase, lookupTime - }; + public: + template + ShaderPair GetOrBuildShader(const T& info); + void Clear(); + }; + static Cache _cache; - struct Uniform - { - zeus::CMatrix4f m_mv; - zeus::CMatrix4f m_mvNorm; - zeus::CMatrix4f m_proj; - zeus::CMatrix4f m_texMtxs[6]; - Ripple m_ripple[20]; - zeus::CVector4f m_colorMul; - zeus::CVector4f m_pad[3]; // rippleNormResolution, Pad out to 1280 bytes - CModelShaders::LightingUniform m_lighting; - zeus::CVector3f m_pad2; // Pad out to 768 bytes, also holds ind scale - }; + struct Ripple { + zeus::CVector4f center; // time, distFalloff + zeus::CVector4f params; // amplitude, lookupPhase, lookupTime + }; - TLockedToken m_patternTex1; - TLockedToken m_patternTex2; - TLockedToken m_colorTex; - TLockedToken m_bumpMap; - TLockedToken m_envMap; - TLockedToken m_envBumpMap; - TLockedToken m_lightmap; - boo::ObjToken m_rippleMap; - boo::ObjToken m_vbo; - boo::ObjToken m_pvbo; - boo::ObjToken m_uniBuf; - BindingPair m_dataBind; - int m_lastBind = -1; + struct Uniform { + zeus::CMatrix4f m_mv; + zeus::CMatrix4f m_mvNorm; + zeus::CMatrix4f m_proj; + zeus::CMatrix4f m_texMtxs[6]; + Ripple m_ripple[20]; + zeus::CVector4f m_colorMul; + zeus::CVector4f m_pad[3]; // rippleNormResolution, Pad out to 1280 bytes + CModelShaders::LightingUniform m_lighting; + zeus::CVector3f m_pad2; // Pad out to 768 bytes, also holds ind scale + }; + + TLockedToken m_patternTex1; + TLockedToken m_patternTex2; + TLockedToken m_colorTex; + TLockedToken m_bumpMap; + TLockedToken m_envMap; + TLockedToken m_envBumpMap; + TLockedToken m_lightmap; + boo::ObjToken m_rippleMap; + boo::ObjToken m_vbo; + boo::ObjToken m_pvbo; + boo::ObjToken m_uniBuf; + BindingPair m_dataBind; + int m_lastBind = -1; #if BOO_HAS_GL - static ShaderPair BuildShader(boo::GLDataFactory::Context& ctx, - const SFluidPlaneShaderInfo& info); - static ShaderPair BuildShader(boo::GLDataFactory::Context& ctx, - const SFluidPlaneDoorShaderInfo& info); - BindingPair BuildBinding(boo::GLDataFactory::Context& ctx, const ShaderPair& pipeline); + static ShaderPair BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info); + static ShaderPair BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info); + BindingPair BuildBinding(boo::GLDataFactory::Context& ctx, const ShaderPair& pipeline); #endif #if _WIN32 - static ShaderPair BuildShader(boo::D3D11DataFactory::Context& ctx, - const SFluidPlaneShaderInfo& info); - static ShaderPair BuildShader(boo::D3D11DataFactory::Context& ctx, - const SFluidPlaneDoorShaderInfo& info); - BindingPair BuildBinding(boo::D3D11DataFactory::Context& ctx, const ShaderPair& pipeline); + static ShaderPair BuildShader(boo::D3D11DataFactory::Context& ctx, const SFluidPlaneShaderInfo& info); + static ShaderPair BuildShader(boo::D3D11DataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info); + BindingPair BuildBinding(boo::D3D11DataFactory::Context& ctx, const ShaderPair& pipeline); #endif #if BOO_HAS_METAL - static ShaderPair BuildShader(boo::MetalDataFactory::Context& ctx, - const SFluidPlaneShaderInfo& info); - static ShaderPair BuildShader(boo::MetalDataFactory::Context& ctx, - const SFluidPlaneDoorShaderInfo& info); - BindingPair BuildBinding(boo::MetalDataFactory::Context& ctx, const ShaderPair& pipeline); + static ShaderPair BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info); + static ShaderPair BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info); + BindingPair BuildBinding(boo::MetalDataFactory::Context& ctx, const ShaderPair& pipeline); #endif #if BOO_HAS_VULKAN - static ShaderPair BuildShader(boo::VulkanDataFactory::Context& ctx, - const SFluidPlaneShaderInfo& info); - static ShaderPair BuildShader(boo::VulkanDataFactory::Context& ctx, - const SFluidPlaneDoorShaderInfo& info); - BindingPair BuildBinding(boo::VulkanDataFactory::Context& ctx, const ShaderPair& pipeline); + static ShaderPair BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info); + static ShaderPair BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info); + BindingPair BuildBinding(boo::VulkanDataFactory::Context& ctx, const ShaderPair& pipeline); #endif - template static void _Shutdown(); + template + static void _Shutdown(); + + void PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount); - void PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount); public: - CFluidPlaneShader(EFluidType type, - const TLockedToken& patternTex1, - const TLockedToken& patternTex2, - const TLockedToken& colorTex, - const TLockedToken& bumpMap, - const TLockedToken& envMap, - const TLockedToken& envBumpMap, - const TLockedToken& lightmap, - const boo::ObjToken& rippleMap, - bool doubleLightmapBlend, bool additive, u32 maxVertCount); - CFluidPlaneShader(const TLockedToken& patternTex1, - const TLockedToken& patternTex2, - const TLockedToken& colorTex, - u32 maxVertCount); - void prepareDraw(const RenderSetupInfo& info); - void prepareDraw(const RenderSetupInfo& info, - const zeus::CVector3f& waterCenter, - const CRippleManager& rippleManager, - const zeus::CColor& colorMul, - float rippleNormResolution); - void bindRegular() - { - if (m_lastBind != 0) - { - CGraphics::SetShaderDataBinding(m_dataBind.m_regular); - m_lastBind = 0; - } + CFluidPlaneShader(EFluidType type, const TLockedToken& patternTex1, + const TLockedToken& patternTex2, const TLockedToken& colorTex, + const TLockedToken& bumpMap, const TLockedToken& envMap, + const TLockedToken& envBumpMap, const TLockedToken& lightmap, + const boo::ObjToken& rippleMap, bool doubleLightmapBlend, bool additive, + u32 maxVertCount); + CFluidPlaneShader(const TLockedToken& patternTex1, const TLockedToken& patternTex2, + const TLockedToken& colorTex, u32 maxVertCount); + void prepareDraw(const RenderSetupInfo& info); + void prepareDraw(const RenderSetupInfo& info, const zeus::CVector3f& waterCenter, const CRippleManager& rippleManager, + const zeus::CColor& colorMul, float rippleNormResolution); + void bindRegular() { + if (m_lastBind != 0) { + CGraphics::SetShaderDataBinding(m_dataBind.m_regular); + m_lastBind = 0; } - bool bindTessellation() - { - if (m_lastBind != 1) - { - CGraphics::SetShaderDataBinding(m_dataBind.m_tessellation); - m_lastBind = 1; - } - return true; + } + bool bindTessellation() { + if (m_lastBind != 1) { + CGraphics::SetShaderDataBinding(m_dataBind.m_tessellation); + m_lastBind = 1; } - void doneDrawing() { m_lastBind = -1; } - void loadVerts(const std::vector& verts, const std::vector& pVerts); + return true; + } + void doneDrawing() { m_lastBind = -1; } + void loadVerts(const std::vector& verts, const std::vector& pVerts); - static void Shutdown(); + static void Shutdown(); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CFogVolumeFilter.cpp b/Runtime/Graphics/Shaders/CFogVolumeFilter.cpp index 1812c37a0..d1dd6a245 100644 --- a/Runtime/Graphics/Shaders/CFogVolumeFilter.cpp +++ b/Runtime/Graphics/Shaders/CFogVolumeFilter.cpp @@ -4,69 +4,58 @@ #include "GameGlobalObjects.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_1WayPipeline; static boo::ObjToken s_2WayPipeline; -void CFogVolumeFilter::Initialize() -{ - s_1WayPipeline = hecl::conv->convert(Shader_CFogVolumeFilter1Way{}); - s_2WayPipeline = hecl::conv->convert(Shader_CFogVolumeFilter2Way{}); +void CFogVolumeFilter::Initialize() { + s_1WayPipeline = hecl::conv->convert(Shader_CFogVolumeFilter1Way{}); + s_2WayPipeline = hecl::conv->convert(Shader_CFogVolumeFilter2Way{}); } -void CFogVolumeFilter::Shutdown() -{ - s_1WayPipeline.reset(); - s_2WayPipeline.reset(); +void CFogVolumeFilter::Shutdown() { + s_1WayPipeline.reset(); + s_2WayPipeline.reset(); } -CFogVolumeFilter::CFogVolumeFilter() -{ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - struct Vert - { - zeus::CVector2f m_pos; - zeus::CVector2f m_uv; - } verts[4] = - { +CFogVolumeFilter::CFogVolumeFilter() { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + struct Vert { + zeus::CVector2f m_pos; + zeus::CVector2f m_uv; + } verts[4] = { {{-1.0, -1.0}, {0.0, 0.0}}, - {{-1.0, 1.0}, {0.0, 1.0}}, - {{ 1.0, -1.0}, {1.0, 0.0}}, - {{ 1.0, 1.0}, {1.0, 1.0}}, - }; - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CColor), 1); - boo::ObjToken texs[] = { CGraphics::g_SpareTexture.get(), CGraphics::g_SpareTexture.get(), - g_Renderer->GetFogRampTex().get() }; - int bindIdxs[] = {0, 1, 0}; - bool bindDepth[] = {true, true, false}; - boo::ObjToken ubufs[] = {m_uniBuf.get()}; + {{-1.0, 1.0}, {0.0, 1.0}}, + {{1.0, -1.0}, {1.0, 0.0}}, + {{1.0, 1.0}, {1.0, 1.0}}, + }; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CColor), 1); + boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get(), CGraphics::g_SpareTexture.get(), + g_Renderer->GetFogRampTex().get()}; + int bindIdxs[] = {0, 1, 0}; + bool bindDepth[] = {true, true, false}; + boo::ObjToken ubufs[] = {m_uniBuf.get()}; - m_dataBind1Way = ctx.newShaderDataBinding(s_1WayPipeline, - m_vbo.get(), nullptr, nullptr, 1, ubufs, - nullptr, nullptr, nullptr, 3, texs, bindIdxs, bindDepth); - m_dataBind2Way = ctx.newShaderDataBinding(s_2WayPipeline, - m_vbo.get(), nullptr, nullptr, 1, ubufs, - nullptr, nullptr, nullptr, 3, texs, bindIdxs, bindDepth); - return true; - } BooTrace); + m_dataBind1Way = ctx.newShaderDataBinding(s_1WayPipeline, m_vbo.get(), nullptr, nullptr, 1, ubufs, nullptr, nullptr, + nullptr, 3, texs, bindIdxs, bindDepth); + m_dataBind2Way = ctx.newShaderDataBinding(s_2WayPipeline, m_vbo.get(), nullptr, nullptr, 1, ubufs, nullptr, nullptr, + nullptr, 3, texs, bindIdxs, bindDepth); + return true; + } BooTrace); } -void CFogVolumeFilter::draw2WayPass(const zeus::CColor& color) -{ - m_uniBuf->load(&color, sizeof(zeus::CColor)); - CGraphics::SetShaderDataBinding(m_dataBind2Way); - CGraphics::DrawArray(0, 4); +void CFogVolumeFilter::draw2WayPass(const zeus::CColor& color) { + m_uniBuf->load(&color, sizeof(zeus::CColor)); + CGraphics::SetShaderDataBinding(m_dataBind2Way); + CGraphics::DrawArray(0, 4); } -void CFogVolumeFilter::draw1WayPass(const zeus::CColor& color) -{ - m_uniBuf->load(&color, sizeof(zeus::CColor)); - CGraphics::SetShaderDataBinding(m_dataBind1Way); - CGraphics::DrawArray(0, 4); +void CFogVolumeFilter::draw1WayPass(const zeus::CColor& color) { + m_uniBuf->load(&color, sizeof(zeus::CColor)); + CGraphics::SetShaderDataBinding(m_dataBind1Way); + CGraphics::DrawArray(0, 4); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CFogVolumeFilter.hpp b/Runtime/Graphics/Shaders/CFogVolumeFilter.hpp index 003d98229..70c41d155 100644 --- a/Runtime/Graphics/Shaders/CFogVolumeFilter.hpp +++ b/Runtime/Graphics/Shaders/CFogVolumeFilter.hpp @@ -5,23 +5,20 @@ #include "zeus/CRectangle.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { -class CFogVolumeFilter -{ - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind1Way; - boo::ObjToken m_dataBind2Way; +class CFogVolumeFilter { + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind1Way; + boo::ObjToken m_dataBind2Way; public: - static void Initialize(); - static void Shutdown(); - CFogVolumeFilter(); - void draw2WayPass(const zeus::CColor& color); - void draw1WayPass(const zeus::CColor& color); + static void Initialize(); + static void Shutdown(); + CFogVolumeFilter(); + void draw2WayPass(const zeus::CColor& color); + void draw1WayPass(const zeus::CColor& color); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CFogVolumePlaneShader.cpp b/Runtime/Graphics/Shaders/CFogVolumePlaneShader.cpp index 0d7fe2624..331997e26 100644 --- a/Runtime/Graphics/Shaders/CFogVolumePlaneShader.cpp +++ b/Runtime/Graphics/Shaders/CFogVolumePlaneShader.cpp @@ -2,70 +2,60 @@ #include "hecl/Pipeline.hpp" #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipelines[4]; -void CFogVolumePlaneShader::Initialize() -{ - s_Pipelines[0] = hecl::conv->convert(Shader_CFogVolumePlaneShader0{}); - s_Pipelines[1] = hecl::conv->convert(Shader_CFogVolumePlaneShader1{}); - s_Pipelines[2] = hecl::conv->convert(Shader_CFogVolumePlaneShader2{}); - s_Pipelines[3] = hecl::conv->convert(Shader_CFogVolumePlaneShader3{}); +void CFogVolumePlaneShader::Initialize() { + s_Pipelines[0] = hecl::conv->convert(Shader_CFogVolumePlaneShader0{}); + s_Pipelines[1] = hecl::conv->convert(Shader_CFogVolumePlaneShader1{}); + s_Pipelines[2] = hecl::conv->convert(Shader_CFogVolumePlaneShader2{}); + s_Pipelines[3] = hecl::conv->convert(Shader_CFogVolumePlaneShader3{}); } -void CFogVolumePlaneShader::Shutdown() -{ - s_Pipelines[0].reset(); - s_Pipelines[1].reset(); - s_Pipelines[2].reset(); - s_Pipelines[3].reset(); +void CFogVolumePlaneShader::Shutdown() { + s_Pipelines[0].reset(); + s_Pipelines[1].reset(); + s_Pipelines[2].reset(); + s_Pipelines[3].reset(); } -void CFogVolumePlaneShader::CommitResources(size_t capacity) -{ - m_vertCapacity = capacity; - CGraphics::CommitResources([this, capacity](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(zeus::CVector4f), capacity); - for (int i=0 ; i<4 ; ++i) - m_dataBinds[i] = ctx.newShaderDataBinding(s_Pipelines[i], - m_vbo.get(), nullptr, nullptr, 0, nullptr, - nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr); - return true; - } BooTrace); +void CFogVolumePlaneShader::CommitResources(size_t capacity) { + m_vertCapacity = capacity; + CGraphics::CommitResources([this, capacity](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(zeus::CVector4f), capacity); + for (int i = 0; i < 4; ++i) + m_dataBinds[i] = ctx.newShaderDataBinding(s_Pipelines[i], m_vbo.get(), nullptr, nullptr, 0, nullptr, nullptr, + nullptr, nullptr, 0, nullptr, nullptr, nullptr); + return true; + } BooTrace); } -void CFogVolumePlaneShader::addFan(const zeus::CVector3f* verts, int numVerts) -{ - zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(true); - zeus::CVector4f vert0 = proj * zeus::CVector4f(CGraphics::g_GXModelView * verts[0]); - if (m_verts.size()) - { - m_verts.push_back(m_verts.back()); - m_verts.push_back(vert0); - if (m_verts.size() & 1) - m_verts.push_back(vert0); - } - TriFanToStrip fanToStrip(m_verts); - fanToStrip.AddVert(vert0); - for (int i = 1; i < numVerts; ++i) - fanToStrip.AddVert(proj * zeus::CVector4f(CGraphics::g_GXModelView * verts[i])); +void CFogVolumePlaneShader::addFan(const zeus::CVector3f* verts, int numVerts) { + zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(true); + zeus::CVector4f vert0 = proj * zeus::CVector4f(CGraphics::g_GXModelView * verts[0]); + if (m_verts.size()) { + m_verts.push_back(m_verts.back()); + m_verts.push_back(vert0); + if (m_verts.size() & 1) + m_verts.push_back(vert0); + } + TriFanToStrip fanToStrip(m_verts); + fanToStrip.AddVert(vert0); + for (int i = 1; i < numVerts; ++i) + fanToStrip.AddVert(proj * zeus::CVector4f(CGraphics::g_GXModelView * verts[i])); } -void CFogVolumePlaneShader::draw(int pass) -{ - if (m_verts.empty()) - return; - if (pass == 0) - { - if (m_vertCapacity < m_verts.size()) - CommitResources(m_verts.size()); - m_vbo->load(m_verts.data(), m_verts.size() * sizeof(zeus::CVector4f)); - } - CGraphics::SetShaderDataBinding(m_dataBinds[pass]); - CGraphics::DrawArray(0, m_verts.size()); +void CFogVolumePlaneShader::draw(int pass) { + if (m_verts.empty()) + return; + if (pass == 0) { + if (m_vertCapacity < m_verts.size()) + CommitResources(m_verts.size()); + m_vbo->load(m_verts.data(), m_verts.size() * sizeof(zeus::CVector4f)); + } + CGraphics::SetShaderDataBinding(m_dataBinds[pass]); + CGraphics::DrawArray(0, m_verts.size()); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CFogVolumePlaneShader.hpp b/Runtime/Graphics/Shaders/CFogVolumePlaneShader.hpp index 9a79cc576..26b1ab09a 100644 --- a/Runtime/Graphics/Shaders/CFogVolumePlaneShader.hpp +++ b/Runtime/Graphics/Shaders/CFogVolumePlaneShader.hpp @@ -6,26 +6,26 @@ #include "zeus/CRectangle.hpp" #include "zeus/CVector4f.hpp" -namespace urde -{ +namespace urde { -class CFogVolumePlaneShader -{ - boo::ObjToken m_vbo; - boo::ObjToken m_dataBinds[4]; - std::vector m_verts; - size_t m_vertCapacity = 0; +class CFogVolumePlaneShader { + boo::ObjToken m_vbo; + boo::ObjToken m_dataBinds[4]; + std::vector m_verts; + size_t m_vertCapacity = 0; - void CommitResources(size_t capacity); + void CommitResources(size_t capacity); public: - static void Initialize(); - static void Shutdown(); - static const zeus::CRectangle DefaultRect; - void reset(int numVerts) { m_verts.clear(); m_verts.reserve(numVerts); } - void addFan(const zeus::CVector3f* verts, int numVerts); - void draw(int pass); + static void Initialize(); + static void Shutdown(); + static const zeus::CRectangle DefaultRect; + void reset(int numVerts) { + m_verts.clear(); + m_verts.reserve(numVerts); + } + void addFan(const zeus::CVector3f* verts, int numVerts); + void draw(int pass); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CLineRendererShaders.cpp b/Runtime/Graphics/Shaders/CLineRendererShaders.cpp index 18e867a47..d58941736 100644 --- a/Runtime/Graphics/Shaders/CLineRendererShaders.cpp +++ b/Runtime/Graphics/Shaders/CLineRendererShaders.cpp @@ -2,8 +2,7 @@ #include "Graphics/CLineRenderer.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { boo::ObjToken CLineRendererShaders::m_texAlpha; boo::ObjToken CLineRendererShaders::m_texAdditive; @@ -19,111 +18,89 @@ boo::ObjToken CLineRendererShaders::m_noTexAdditiveZ; boo::ObjToken CLineRendererShaders::m_noTexAlphaZGEqual; -void CLineRendererShaders::Initialize() -{ - CGraphics::CommitResources( - [](boo::IGraphicsDataFactory::Context& ctx) - { - m_texAlpha = hecl::conv->convert(ctx, Shader_CLineRendererShaderTexAlpha{}); - m_texAdditive = hecl::conv->convert(ctx, Shader_CLineRendererShaderTexAdditive{}); - m_noTexAlpha = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAlpha{}); - m_noTexAdditive = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAdditive{}); - m_texAlphaZ = hecl::conv->convert(ctx, Shader_CLineRendererShaderTexAlphaZ{}); - m_texAdditiveZ = hecl::conv->convert(ctx, Shader_CLineRendererShaderTexAdditiveZ{}); - m_noTexAlphaZ = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAlphaZ{}); - m_noTexAdditiveZ = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAdditiveZ{}); - m_noTexAlphaZGEqual = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAlphaZGEqual{}); - return true; - } BooTrace); +void CLineRendererShaders::Initialize() { + CGraphics::CommitResources([](boo::IGraphicsDataFactory::Context& ctx) { + m_texAlpha = hecl::conv->convert(ctx, Shader_CLineRendererShaderTexAlpha{}); + m_texAdditive = hecl::conv->convert(ctx, Shader_CLineRendererShaderTexAdditive{}); + m_noTexAlpha = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAlpha{}); + m_noTexAdditive = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAdditive{}); + m_texAlphaZ = hecl::conv->convert(ctx, Shader_CLineRendererShaderTexAlphaZ{}); + m_texAdditiveZ = hecl::conv->convert(ctx, Shader_CLineRendererShaderTexAdditiveZ{}); + m_noTexAlphaZ = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAlphaZ{}); + m_noTexAdditiveZ = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAdditiveZ{}); + m_noTexAlphaZGEqual = hecl::conv->convert(ctx, Shader_CLineRendererShaderNoTexAlphaZGEqual{}); + return true; + } BooTrace); } -void CLineRendererShaders::Shutdown() -{ - m_texAlpha.reset(); - m_texAdditive.reset(); - m_noTexAlpha.reset(); - m_noTexAdditive.reset(); - m_texAlphaZ.reset(); - m_texAdditiveZ.reset(); - m_noTexAlphaZ.reset(); - m_noTexAdditiveZ.reset(); - m_noTexAlphaZGEqual.reset(); +void CLineRendererShaders::Shutdown() { + m_texAlpha.reset(); + m_texAdditive.reset(); + m_noTexAlpha.reset(); + m_noTexAdditive.reset(); + m_texAlphaZ.reset(); + m_texAdditiveZ.reset(); + m_noTexAlphaZ.reset(); + m_noTexAdditiveZ.reset(); + m_noTexAlphaZGEqual.reset(); } -void CLineRendererShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, - CLineRenderer& renderer, - const boo::ObjToken& texture, - bool additive, bool zTest, bool zGEqual) -{ - boo::ObjToken pipeline; +void CLineRendererShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CLineRenderer& renderer, + const boo::ObjToken& texture, bool additive, + bool zTest, bool zGEqual) { + boo::ObjToken pipeline; - if (zGEqual) - { - pipeline = m_noTexAlphaZGEqual; + if (zGEqual) { + pipeline = m_noTexAlphaZGEqual; + } else if (zTest) { + if (texture) { + if (additive) + pipeline = m_texAdditiveZ; + else + pipeline = m_texAlphaZ; + } else { + if (additive) + pipeline = m_noTexAdditiveZ; + else + pipeline = m_noTexAlphaZ; } - else if (zTest) - { - if (texture) - { - if (additive) - pipeline = m_texAdditiveZ; - else - pipeline = m_texAlphaZ; - } - else - { - if (additive) - pipeline = m_noTexAdditiveZ; - else - pipeline = m_noTexAlphaZ; - } - } - else - { - if (texture) - { - if (additive) - pipeline = m_texAdditive; - else - pipeline = m_texAlpha; - } - else - { - if (additive) - pipeline = m_noTexAdditive; - else - pipeline = m_noTexAlpha; - } + } else { + if (texture) { + if (additive) + pipeline = m_texAdditive; + else + pipeline = m_texAlpha; + } else { + if (additive) + pipeline = m_noTexAdditive; + else + pipeline = m_noTexAlpha; } + } - int texCount = 0; - boo::ObjToken textures[1]; + int texCount = 0; + boo::ObjToken textures[1]; - std::pair, - hecl::VertexBufferPool::IndexTp> vbufInfo; - std::pair, - hecl::UniformBufferPool::IndexTp> ubufInfo = - renderer.m_uniformBuf.getBufferInfo(); - if (texture) - { - vbufInfo = renderer.m_vertBufTex.getBufferInfo(); - textures[0] = texture; - texCount = 1; - } - else - { - vbufInfo = renderer.m_vertBufNoTex.getBufferInfo(); - } + std::pair, hecl::VertexBufferPool::IndexTp> + vbufInfo; + std::pair, hecl::UniformBufferPool::IndexTp> + ubufInfo = renderer.m_uniformBuf.getBufferInfo(); + if (texture) { + vbufInfo = renderer.m_vertBufTex.getBufferInfo(); + textures[0] = texture; + texCount = 1; + } else { + vbufInfo = renderer.m_vertBufNoTex.getBufferInfo(); + } - boo::ObjToken uniforms[] = {ubufInfo.first.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - size_t ubufOffs[] = {size_t(ubufInfo.second)}; - size_t ubufSizes[] = {sizeof(CLineRenderer::SDrawUniform)}; + boo::ObjToken uniforms[] = {ubufInfo.first.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + size_t ubufOffs[] = {size_t(ubufInfo.second)}; + size_t ubufSizes[] = {sizeof(CLineRenderer::SDrawUniform)}; - renderer.m_shaderBind = ctx.newShaderDataBinding(pipeline, vbufInfo.first.get(), - nullptr, nullptr, 1, uniforms, stages, - ubufOffs, ubufSizes, texCount, textures, - nullptr, nullptr, vbufInfo.second); + renderer.m_shaderBind = + ctx.newShaderDataBinding(pipeline, vbufInfo.first.get(), nullptr, nullptr, 1, uniforms, stages, ubufOffs, + ubufSizes, texCount, textures, nullptr, nullptr, vbufInfo.second); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CLineRendererShaders.hpp b/Runtime/Graphics/Shaders/CLineRendererShaders.hpp index 62d331c24..7ab651388 100644 --- a/Runtime/Graphics/Shaders/CLineRendererShaders.hpp +++ b/Runtime/Graphics/Shaders/CLineRendererShaders.hpp @@ -3,33 +3,30 @@ #include "Graphics/CGraphics.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { class CLineRenderer; -class CLineRendererShaders -{ - static boo::ObjToken m_texAlpha; - static boo::ObjToken m_texAdditive; +class CLineRendererShaders { + static boo::ObjToken m_texAlpha; + static boo::ObjToken m_texAdditive; - static boo::ObjToken m_noTexAlpha; - static boo::ObjToken m_noTexAdditive; + static boo::ObjToken m_noTexAlpha; + static boo::ObjToken m_noTexAdditive; - static boo::ObjToken m_texAlphaZ; - static boo::ObjToken m_texAdditiveZ; + static boo::ObjToken m_texAlphaZ; + static boo::ObjToken m_texAdditiveZ; - static boo::ObjToken m_noTexAlphaZ; - static boo::ObjToken m_noTexAdditiveZ; + static boo::ObjToken m_noTexAlphaZ; + static boo::ObjToken m_noTexAdditiveZ; - static boo::ObjToken m_noTexAlphaZGEqual; + static boo::ObjToken m_noTexAlphaZGEqual; public: - static void Initialize(); - static void Shutdown(); - static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CLineRenderer& renderer, - const boo::ObjToken& texture, bool additive, bool zTest, - bool zGEqual); + static void Initialize(); + static void Shutdown(); + static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CLineRenderer& renderer, + const boo::ObjToken& texture, bool additive, bool zTest, + bool zGEqual); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CMapSurfaceShader.cpp b/Runtime/Graphics/Shaders/CMapSurfaceShader.cpp index ed4fa019a..7f4bb2621 100644 --- a/Runtime/Graphics/Shaders/CMapSurfaceShader.cpp +++ b/Runtime/Graphics/Shaders/CMapSurfaceShader.cpp @@ -2,41 +2,30 @@ #include "hecl/Pipeline.hpp" #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; -void CMapSurfaceShader::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CMapSurfaceShader{}); -} +void CMapSurfaceShader::Initialize() { s_Pipeline = hecl::conv->convert(Shader_CMapSurfaceShader{}); } -void CMapSurfaceShader::Shutdown() -{ - s_Pipeline.reset(); -} +void CMapSurfaceShader::Shutdown() { s_Pipeline.reset(); } CMapSurfaceShader::CMapSurfaceShader(boo::IGraphicsDataFactory::Context& ctx, const boo::ObjToken& vbo, const boo::ObjToken& ibo) -: m_vbo(vbo), m_ibo(ibo) -{ - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, m_ibo.get(), - 1, bufs, stages, nullptr, nullptr, 0, nullptr, nullptr, nullptr); +: m_vbo(vbo), m_ibo(ibo) { + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, m_ibo.get(), 1, bufs, stages, nullptr, + nullptr, 0, nullptr, nullptr, nullptr); } -void CMapSurfaceShader::draw(const zeus::CColor& color, u32 start, u32 count) -{ - Uniform uniform = { - CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), color - }; - m_uniBuf->load(&uniform, sizeof(Uniform)); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArrayIndexed(start, count); +void CMapSurfaceShader::draw(const zeus::CColor& color, u32 start, u32 count) { + Uniform uniform = {CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), color}; + m_uniBuf->load(&uniform, sizeof(Uniform)); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArrayIndexed(start, count); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CMapSurfaceShader.hpp b/Runtime/Graphics/Shaders/CMapSurfaceShader.hpp index 8b67bf755..18ed9013f 100644 --- a/Runtime/Graphics/Shaders/CMapSurfaceShader.hpp +++ b/Runtime/Graphics/Shaders/CMapSurfaceShader.hpp @@ -5,29 +5,25 @@ #include "zeus/CMatrix4f.hpp" #include "zeus/CColor.hpp" -namespace urde -{ +namespace urde { -class CMapSurfaceShader -{ - struct Uniform - { - zeus::CMatrix4f mtx; - zeus::CColor color; - }; +class CMapSurfaceShader { + struct Uniform { + zeus::CMatrix4f mtx; + zeus::CColor color; + }; - boo::ObjToken m_uniBuf; - boo::ObjToken m_vbo; - boo::ObjToken m_ibo; - boo::ObjToken m_dataBind; + boo::ObjToken m_uniBuf; + boo::ObjToken m_vbo; + boo::ObjToken m_ibo; + boo::ObjToken m_dataBind; public: - static void Initialize(); - static void Shutdown(); - CMapSurfaceShader(boo::IGraphicsDataFactory::Context& ctx, const boo::ObjToken& vbo, - const boo::ObjToken& ibo); - void draw(const zeus::CColor& color, u32 start, u32 count); + static void Initialize(); + static void Shutdown(); + CMapSurfaceShader(boo::IGraphicsDataFactory::Context& ctx, const boo::ObjToken& vbo, + const boo::ObjToken& ibo); + void draw(const zeus::CColor& color, u32 start, u32 count); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CModelShaders.cpp b/Runtime/Graphics/Shaders/CModelShaders.cpp index 3e804af2b..3dce58a16 100644 --- a/Runtime/Graphics/Shaders/CModelShaders.cpp +++ b/Runtime/Graphics/Shaders/CModelShaders.cpp @@ -2,83 +2,71 @@ #include "Graphics/CLight.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { std::unordered_map CModelShaders::g_ShaderPipelines; -void CModelShaders::LightingUniform::ActivateLights(const std::vector& lts) -{ - ambient = zeus::CColor::skClear; - size_t curLight = 0; +void CModelShaders::LightingUniform::ActivateLights(const std::vector& lts) { + ambient = zeus::CColor::skClear; + size_t curLight = 0; - for (const CLight& light : lts) - { - switch (light.GetType()) - { - case ELightType::LocalAmbient: - ambient += light.GetColor(); - break; - case ELightType::Point: - case ELightType::Spot: - case ELightType::Custom: - case ELightType::Directional: - { - if (curLight >= URDE_MAX_LIGHTS) - continue; - CModelShaders::Light& lightOut = lights[curLight++]; - lightOut.pos = CGraphics::g_CameraMatrix * light.GetPosition(); - lightOut.dir = CGraphics::g_CameraMatrix.basis * light.GetDirection(); - lightOut.dir.normalize(); - lightOut.color = light.GetColor(); - lightOut.linAtt[0] = light.GetAttenuationConstant(); - lightOut.linAtt[1] = light.GetAttenuationLinear(); - lightOut.linAtt[2] = light.GetAttenuationQuadratic(); - lightOut.angAtt[0] = light.GetAngleAttenuationConstant(); - lightOut.angAtt[1] = light.GetAngleAttenuationLinear(); - lightOut.angAtt[2] = light.GetAngleAttenuationQuadratic(); + for (const CLight& light : lts) { + switch (light.GetType()) { + case ELightType::LocalAmbient: + ambient += light.GetColor(); + break; + case ELightType::Point: + case ELightType::Spot: + case ELightType::Custom: + case ELightType::Directional: { + if (curLight >= URDE_MAX_LIGHTS) + continue; + CModelShaders::Light& lightOut = lights[curLight++]; + lightOut.pos = CGraphics::g_CameraMatrix * light.GetPosition(); + lightOut.dir = CGraphics::g_CameraMatrix.basis * light.GetDirection(); + lightOut.dir.normalize(); + lightOut.color = light.GetColor(); + lightOut.linAtt[0] = light.GetAttenuationConstant(); + lightOut.linAtt[1] = light.GetAttenuationLinear(); + lightOut.linAtt[2] = light.GetAttenuationQuadratic(); + lightOut.angAtt[0] = light.GetAngleAttenuationConstant(); + lightOut.angAtt[1] = light.GetAngleAttenuationLinear(); + lightOut.angAtt[2] = light.GetAngleAttenuationQuadratic(); - if (light.GetType() == ELightType::Directional) - lightOut.pos = (-lightOut.dir) * 1048576.f; - break; - } - } + if (light.GetType() == ELightType::Directional) + lightOut.pos = (-lightOut.dir) * 1048576.f; + break; } - - for (; curLightsecond; - ShaderPipelines& newPipelines = g_ShaderPipelines[tag.val64()]; - newPipelines = std::make_shared(); - size_t idx = 0; - for (const auto& ext : g_ExtensionSlots) - (*newPipelines)[idx++] = hecl::conv->convert(hecl::HECLIR(ir, tag, ext)); - return newPipelines; -} + const hecl::Frontend::IR& ir) { + auto search = g_ShaderPipelines.find(tag.val64()); + if (search != g_ShaderPipelines.cend()) + return search->second; + ShaderPipelines& newPipelines = g_ShaderPipelines[tag.val64()]; + newPipelines = std::make_shared(); + size_t idx = 0; + for (const auto& ext : g_ExtensionSlots) + (*newPipelines)[idx++] = hecl::conv->convert(hecl::HECLIR(ir, tag, ext)); + return newPipelines; } +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CModelShaders.hpp b/Runtime/Graphics/Shaders/CModelShaders.hpp index 42d1e1cae..d004647d2 100644 --- a/Runtime/Graphics/Shaders/CModelShaders.hpp +++ b/Runtime/Graphics/Shaders/CModelShaders.hpp @@ -10,94 +10,84 @@ #define URDE_MAX_LIGHTS 8 -namespace urde -{ +namespace urde { -enum EExtendedShader : uint8_t -{ - Flat, - Lighting, - Thermal, - ForcedAlpha, - ForcedAdditive, - SolidColor, - SolidColorAdditive, - SolidColorFrontfaceCullLEqualAlphaOnly, - SolidColorFrontfaceCullAlwaysAlphaOnly, // No Z-write or test - SolidColorBackfaceCullLEqualAlphaOnly, - SolidColorBackfaceCullGreaterAlphaOnly, // No Z-write - MorphBallShadow, - WorldShadow, - ForcedAlphaNoCull, - ForcedAdditiveNoCull, - ForcedAlphaNoZWrite, - ForcedAdditiveNoZWrite, - ForcedAlphaNoCullNoZWrite, - ForcedAdditiveNoCullNoZWrite, - DepthGEqualNoZWrite, - Disintegrate, - MAX +enum EExtendedShader : uint8_t { + Flat, + Lighting, + Thermal, + ForcedAlpha, + ForcedAdditive, + SolidColor, + SolidColorAdditive, + SolidColorFrontfaceCullLEqualAlphaOnly, + SolidColorFrontfaceCullAlwaysAlphaOnly, // No Z-write or test + SolidColorBackfaceCullLEqualAlphaOnly, + SolidColorBackfaceCullGreaterAlphaOnly, // No Z-write + MorphBallShadow, + WorldShadow, + ForcedAlphaNoCull, + ForcedAdditiveNoCull, + ForcedAlphaNoZWrite, + ForcedAdditiveNoZWrite, + ForcedAlphaNoCullNoZWrite, + ForcedAdditiveNoCullNoZWrite, + DepthGEqualNoZWrite, + Disintegrate, + MAX }; -class CModelShaders -{ - friend class CModel; +class CModelShaders { + friend class CModel; + public: - struct Light - { - zeus::CVector3f pos; - zeus::CVector3f dir; - zeus::CColor color = zeus::CColor::skClear; - float linAtt[4] = {1.f, 0.f, 0.f}; - float angAtt[4] = {1.f, 0.f, 0.f}; - }; + struct Light { + zeus::CVector3f pos; + zeus::CVector3f dir; + zeus::CColor color = zeus::CColor::skClear; + float linAtt[4] = {1.f, 0.f, 0.f}; + float angAtt[4] = {1.f, 0.f, 0.f}; + }; - struct LightingUniform - { - Light lights[URDE_MAX_LIGHTS]; - zeus::CColor ambient; - zeus::CColor colorRegs[3]; - zeus::CColor mulColor; - CGraphics::CFogState fog; + struct LightingUniform { + Light lights[URDE_MAX_LIGHTS]; + zeus::CColor ambient; + zeus::CColor colorRegs[3]; + zeus::CColor mulColor; + CGraphics::CFogState fog; - void ActivateLights(const std::vector& lts); - }; + void ActivateLights(const std::vector& lts); + }; - struct ThermalUniform - { - zeus::CColor mulColor; - zeus::CColor addColor; - }; + struct ThermalUniform { + zeus::CColor mulColor; + zeus::CColor addColor; + }; - struct SolidUniform - { - zeus::CColor solidColor; - }; + struct SolidUniform { + zeus::CColor solidColor; + }; - struct MBShadowUniform - { - zeus::CVector4f shadowUp; - float shadowId; - }; + struct MBShadowUniform { + zeus::CVector4f shadowUp; + float shadowId; + }; - struct OneTextureUniform - { - zeus::CColor addColor; - CGraphics::CFogState fog; - }; + struct OneTextureUniform { + zeus::CColor addColor; + CGraphics::CFogState fog; + }; - static void Initialize(); - static void Shutdown(); + static void Initialize(); + static void Shutdown(); - using ShaderPipelinesData = std::array, EExtendedShader::MAX>; - using ShaderPipelines = std::shared_ptr; + using ShaderPipelinesData = std::array, EExtendedShader::MAX>; + using ShaderPipelines = std::shared_ptr; - static ShaderPipelines BuildExtendedShader(const hecl::Backend::ShaderTag& tag, - const hecl::Frontend::IR& ir); + static ShaderPipelines BuildExtendedShader(const hecl::Backend::ShaderTag& tag, const hecl::Frontend::IR& ir); private: - static std::unordered_map g_ShaderPipelines; + static std::unordered_map g_ShaderPipelines; }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp b/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp index 96bcddba6..a97494a3b 100644 --- a/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp +++ b/Runtime/Graphics/Shaders/CModelShadersGLSL.cpp @@ -1,52 +1,51 @@ #include "CModelShaders.hpp" #include "hecl/Backend/GLSL.hpp" -namespace urde -{ +namespace urde { using namespace std::literals; extern const hecl::Backend::Function ExtensionLightingFuncsGLSL[]; extern const hecl::Backend::Function ExtensionPostFuncsGLSL[]; -#define FOG_STRUCT_GLSL \ -"struct Fog\n" \ -"{\n" \ -" int mode;\n" \ -" vec4 color;\n" \ -" float rangeScale;\n" \ -" float start;\n" \ -"};\n" +#define FOG_STRUCT_GLSL \ + "struct Fog\n" \ + "{\n" \ + " int mode;\n" \ + " vec4 color;\n" \ + " float rangeScale;\n" \ + " float start;\n" \ + "};\n" -#define FOG_ALGORITHM_GLSL \ -" float fogZ, temp;\n" \ -" switch (fog.mode)\n" \ -" {\n" \ -" case 2:\n" \ -" fogZ = (-vtf.mvPos.z - fog.start) * fog.rangeScale;\n" \ -" break;\n" \ -" case 4:\n" \ -" fogZ = 1.0 - exp2(-8.0 * (-vtf.mvPos.z - fog.start) * fog.rangeScale);\n" \ -" break;\n" \ -" case 5:\n" \ -" temp = (-vtf.mvPos.z - fog.start) * fog.rangeScale;\n" \ -" fogZ = 1.0 - exp2(-8.0 * temp * temp);\n" \ -" break;\n" \ -" case 6:\n" \ -" fogZ = exp2(-8.0 * (fog.start + vtf.mvPos.z) * fog.rangeScale);\n" \ -" break;\n" \ -" case 7:\n" \ -" temp = (fog.start + vtf.mvPos.z) * fog.rangeScale;\n" \ -" fogZ = exp2(-8.0 * temp * temp);\n" \ -" break;\n" \ -" default:\n" \ -" fogZ = 0.0;\n" \ -" break;\n" \ -" }\n" \ -"#ifdef BLEND_DST_ONE\n" \ -" return vec4(mix(colorIn, vec4(0.0), clamp(fogZ, 0.0, 1.0)).rgb, colorIn.a);\n" \ -"#else\n" \ -" return vec4(mix(colorIn, fog.color, clamp(fogZ, 0.0, 1.0)).rgb, colorIn.a);\n" \ -"#endif\n" +#define FOG_ALGORITHM_GLSL \ + " float fogZ, temp;\n" \ + " switch (fog.mode)\n" \ + " {\n" \ + " case 2:\n" \ + " fogZ = (-vtf.mvPos.z - fog.start) * fog.rangeScale;\n" \ + " break;\n" \ + " case 4:\n" \ + " fogZ = 1.0 - exp2(-8.0 * (-vtf.mvPos.z - fog.start) * fog.rangeScale);\n" \ + " break;\n" \ + " case 5:\n" \ + " temp = (-vtf.mvPos.z - fog.start) * fog.rangeScale;\n" \ + " fogZ = 1.0 - exp2(-8.0 * temp * temp);\n" \ + " break;\n" \ + " case 6:\n" \ + " fogZ = exp2(-8.0 * (fog.start + vtf.mvPos.z) * fog.rangeScale);\n" \ + " break;\n" \ + " case 7:\n" \ + " temp = (fog.start + vtf.mvPos.z) * fog.rangeScale;\n" \ + " fogZ = exp2(-8.0 * temp * temp);\n" \ + " break;\n" \ + " default:\n" \ + " fogZ = 0.0;\n" \ + " break;\n" \ + " }\n" \ + "#ifdef BLEND_DST_ONE\n" \ + " return vec4(mix(colorIn, vec4(0.0), clamp(fogZ, 0.0, 1.0)).rgb, colorIn.a);\n" \ + "#else\n" \ + " return vec4(mix(colorIn, fog.color, clamp(fogZ, 0.0, 1.0)).rgb, colorIn.a);\n" \ + "#endif\n" static std::string_view LightingGLSL = "struct Light\n" @@ -156,72 +155,68 @@ static std::string_view LightingShadowGLSL = "}\n"sv; static std::string_view MainPostGLSL = -"vec4 MainPostFunc(vec4 colorIn)\n" -"{\n" -FOG_ALGORITHM_GLSL -"}\n" -"\n"sv; + "vec4 MainPostFunc(vec4 colorIn)\n" + "{\n" FOG_ALGORITHM_GLSL + "}\n" + "\n"sv; static std::string_view ThermalPostGLSL = -"UBINDING2 uniform ThermalUniform\n" -"{\n" -" vec4 tmulColor;\n" -" vec4 addColor;\n" -"};\n" -"vec4 ThermalPostFunc(vec4 colorIn)\n" -"{\n" -" return vec4(texture(extTex7, vtf.extTcgs[0]).rrr * tmulColor.rgb + addColor.rgb, tmulColor.a + addColor.a);\n" -"}\n" -"\n"sv; + "UBINDING2 uniform ThermalUniform\n" + "{\n" + " vec4 tmulColor;\n" + " vec4 addColor;\n" + "};\n" + "vec4 ThermalPostFunc(vec4 colorIn)\n" + "{\n" + " return vec4(texture(extTex7, vtf.extTcgs[0]).rrr * tmulColor.rgb + addColor.rgb, tmulColor.a + addColor.a);\n" + "}\n" + "\n"sv; static std::string_view SolidPostGLSL = -"UBINDING2 uniform SolidUniform\n" -"{\n" -" vec4 solidColor;\n" -"};\n" -"vec4 SolidPostFunc(vec4 colorIn)\n" -"{\n" -" return solidColor;\n" -"}\n" -"\n"sv; + "UBINDING2 uniform SolidUniform\n" + "{\n" + " vec4 solidColor;\n" + "};\n" + "vec4 SolidPostFunc(vec4 colorIn)\n" + "{\n" + " return solidColor;\n" + "}\n" + "\n"sv; static std::string_view MBShadowPostGLSL = -"UBINDING2 uniform MBShadowUniform\n" -"{\n" -" vec4 shadowUp;\n" -" float shadowId;\n" -"};\n" -"vec4 MBShadowPostFunc(vec4 colorIn)\n" -"{\n" -" float idTexel = texture(extTex0, vtf.extTcgs[0]).a;\n" -" float sphereTexel = texture(extTex1, vtf.extTcgs[1]).a;\n" -" float fadeTexel = texture(extTex2, vtf.extTcgs[2]).a;\n" -" float val = ((abs(idTexel - shadowId) < 0.001) ?\n" -" (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) *\n" -" sphereTexel * fadeTexel;\n" -" return vec4(0.0, 0.0, 0.0, val);\n" -"}\n" -"\n"sv; + "UBINDING2 uniform MBShadowUniform\n" + "{\n" + " vec4 shadowUp;\n" + " float shadowId;\n" + "};\n" + "vec4 MBShadowPostFunc(vec4 colorIn)\n" + "{\n" + " float idTexel = texture(extTex0, vtf.extTcgs[0]).a;\n" + " float sphereTexel = texture(extTex1, vtf.extTcgs[1]).a;\n" + " float fadeTexel = texture(extTex2, vtf.extTcgs[2]).a;\n" + " float val = ((abs(idTexel - shadowId) < 0.001) ?\n" + " (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) *\n" + " sphereTexel * fadeTexel;\n" + " return vec4(0.0, 0.0, 0.0, val);\n" + "}\n" + "\n"sv; -static std::string_view DisintegratePostGLSL = -FOG_STRUCT_GLSL -"UBINDING2 uniform DisintegrateUniform\n" -"{\n" -" vec4 addColor;\n" -" Fog fog;\n" -"};\n" -"vec4 DisintegratePostFunc(vec4 colorIn)\n" -"{\n" -" vec4 texel0 = texture(extTex7, vtf.extTcgs[0]);\n" -" vec4 texel1 = texture(extTex7, vtf.extTcgs[1]);\n" -" colorIn = mix(vec4(0.0), texel1, texel0);\n" -" colorIn.rgb += addColor.rgb;\n" -FOG_ALGORITHM_GLSL -"}\n" -"\n"sv; +static std::string_view DisintegratePostGLSL = FOG_STRUCT_GLSL + "UBINDING2 uniform DisintegrateUniform\n" + "{\n" + " vec4 addColor;\n" + " Fog fog;\n" + "};\n" + "vec4 DisintegratePostFunc(vec4 colorIn)\n" + "{\n" + " vec4 texel0 = texture(extTex7, vtf.extTcgs[0]);\n" + " vec4 texel1 = texture(extTex7, vtf.extTcgs[1]);\n" + " colorIn = mix(vec4(0.0), texel1, texel0);\n" + " colorIn.rgb += addColor.rgb;\n" FOG_ALGORITHM_GLSL + "}\n" + "\n"sv; -const hecl::Backend::Function ExtensionLightingFuncsGLSL[] = -{ +const hecl::Backend::Function ExtensionLightingFuncsGLSL[] = { {}, {LightingGLSL, "LightingFunc"}, {}, @@ -245,8 +240,7 @@ const hecl::Backend::Function ExtensionLightingFuncsGLSL[] = {}, }; -const hecl::Backend::Function ExtensionPostFuncsGLSL[] = -{ +const hecl::Backend::Function ExtensionPostFuncsGLSL[] = { {}, {MainPostGLSL, "MainPostFunc"}, {ThermalPostGLSL, "ThermalPostFunc"}, @@ -270,4 +264,4 @@ const hecl::Backend::Function ExtensionPostFuncsGLSL[] = {DisintegratePostGLSL, "DisintegratePostFunc"}, }; -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CModelShadersHLSL.cpp b/Runtime/Graphics/Shaders/CModelShadersHLSL.cpp index 1e6e0230a..6ad783999 100644 --- a/Runtime/Graphics/Shaders/CModelShadersHLSL.cpp +++ b/Runtime/Graphics/Shaders/CModelShadersHLSL.cpp @@ -1,7 +1,6 @@ #include "CModelShaders.hpp" -namespace urde -{ +namespace urde { using namespace std::literals; extern const hecl::Backend::Function ExtensionLightingFuncsHLSL[]; @@ -118,107 +117,104 @@ static std::string_view LightingShadowHLSL = "}\n"sv; static std::string_view MainPostHLSL = -"static float4 MainPostFunc(in VertToFrag vtf, float4 colorIn)\n" -"{\n" -" float fogZ, temp;\n" -" switch (fog.mode)\n" -" {\n" -" case 2:\n" -" fogZ = (-vtf.mvPos.z - fog.start) * fog.rangeScale;\n" -" break;\n" -" case 4:\n" -" fogZ = 1.0 - exp2(-8.0 * (-vtf.mvPos.z - fog.start) * fog.rangeScale);\n" -" break;\n" -" case 5:\n" -" temp = (-vtf.mvPos.z - fog.start) * fog.rangeScale;\n" -" fogZ = 1.0 - exp2(-8.0 * temp * temp);\n" -" break;\n" -" case 6:\n" -" fogZ = exp2(-8.0 * (fog.start + vtf.mvPos.z) * fog.rangeScale);\n" -" break;\n" -" case 7:\n" -" temp = (fog.start + vtf.mvPos.z) * fog.rangeScale;\n" -" fogZ = exp2(-8.0 * temp * temp);\n" -" break;\n" -" default:\n" -" fogZ = 0.0;\n" -" break;\n" -" }\n" -"#ifdef BLEND_DST_ONE\n" -" return float4(lerp(colorIn, float4(0.0, 0.0, 0.0, 0.0), saturate(fogZ)).rgb, colorIn.a);\n" -"#else\n" -" return float4(lerp(colorIn, fog.color, saturate(fogZ)).rgb, colorIn.a);\n" -"#endif\n" -"}\n" -"\n"sv; + "static float4 MainPostFunc(in VertToFrag vtf, float4 colorIn)\n" + "{\n" + " float fogZ, temp;\n" + " switch (fog.mode)\n" + " {\n" + " case 2:\n" + " fogZ = (-vtf.mvPos.z - fog.start) * fog.rangeScale;\n" + " break;\n" + " case 4:\n" + " fogZ = 1.0 - exp2(-8.0 * (-vtf.mvPos.z - fog.start) * fog.rangeScale);\n" + " break;\n" + " case 5:\n" + " temp = (-vtf.mvPos.z - fog.start) * fog.rangeScale;\n" + " fogZ = 1.0 - exp2(-8.0 * temp * temp);\n" + " break;\n" + " case 6:\n" + " fogZ = exp2(-8.0 * (fog.start + vtf.mvPos.z) * fog.rangeScale);\n" + " break;\n" + " case 7:\n" + " temp = (fog.start + vtf.mvPos.z) * fog.rangeScale;\n" + " fogZ = exp2(-8.0 * temp * temp);\n" + " break;\n" + " default:\n" + " fogZ = 0.0;\n" + " break;\n" + " }\n" + "#ifdef BLEND_DST_ONE\n" + " return float4(lerp(colorIn, float4(0.0, 0.0, 0.0, 0.0), saturate(fogZ)).rgb, colorIn.a);\n" + "#else\n" + " return float4(lerp(colorIn, fog.color, saturate(fogZ)).rgb, colorIn.a);\n" + "#endif\n" + "}\n" + "\n"sv; static std::string_view ThermalPostHLSL = -"cbuffer ThermalUniform : register(b2)\n" -"{\n" -" float4 tmulColor;\n" -" float4 addColor;\n" -"};\n" -"static float4 ThermalPostFunc(in VertToFrag vtf, float4 colorIn)\n" -"{\n" -" return float4(extTex7.Sample(samp, vtf.extTcgs[0]).rrr * tmulColor.rgb + addColor.rgb, tmulColor.a + addColor.a);\n" -"}\n" -"\n"sv; + "cbuffer ThermalUniform : register(b2)\n" + "{\n" + " float4 tmulColor;\n" + " float4 addColor;\n" + "};\n" + "static float4 ThermalPostFunc(in VertToFrag vtf, float4 colorIn)\n" + "{\n" + " return float4(extTex7.Sample(samp, vtf.extTcgs[0]).rrr * tmulColor.rgb + addColor.rgb, tmulColor.a + " + "addColor.a);\n" + "}\n" + "\n"sv; static std::string_view SolidPostHLSL = -"cbuffer SolidUniform : register(b2)\n" -"{\n" -" float4 solidColor;\n" -"};\n" -"static float4 SolidPostFunc(in VertToFrag vtf, float4 colorIn)\n" -"{\n" -" return solidColor;\n" -"}\n" -"\n"sv; + "cbuffer SolidUniform : register(b2)\n" + "{\n" + " float4 solidColor;\n" + "};\n" + "static float4 SolidPostFunc(in VertToFrag vtf, float4 colorIn)\n" + "{\n" + " return solidColor;\n" + "}\n" + "\n"sv; static std::string_view MBShadowPostHLSL = -"cbuffer MBShadowUniform : register(b2)\n" -"{\n" -" float4 shadowUp;\n" -" float shadowId;\n" -"};\n" -"static float4 MBShadowPostFunc(in VertToFrag vtf, float4 colorIn)\n" -"{\n" -" float idTexel = extTex0.Sample(samp, vtf.extTcgs[0]).a;\n" -" float sphereTexel = extTex1.Sample(samp, vtf.extTcgs[1]).a;\n" -" float fadeTexel = extTex2.Sample(samp, vtf.extTcgs[2]).a;\n" -" float val = ((abs(idTexel - shadowId) < 0.001) ?\n" -" (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) *\n" -" sphereTexel * fadeTexel;\n" -" return float4(0.0, 0.0, 0.0, val);\n" -"}\n" -"\n"sv; + "cbuffer MBShadowUniform : register(b2)\n" + "{\n" + " float4 shadowUp;\n" + " float shadowId;\n" + "};\n" + "static float4 MBShadowPostFunc(in VertToFrag vtf, float4 colorIn)\n" + "{\n" + " float idTexel = extTex0.Sample(samp, vtf.extTcgs[0]).a;\n" + " float sphereTexel = extTex1.Sample(samp, vtf.extTcgs[1]).a;\n" + " float fadeTexel = extTex2.Sample(samp, vtf.extTcgs[2]).a;\n" + " float val = ((abs(idTexel - shadowId) < 0.001) ?\n" + " (dot(vtf.mvNorm.xyz, shadowUp.xyz) * shadowUp.w) : 0.0) *\n" + " sphereTexel * fadeTexel;\n" + " return float4(0.0, 0.0, 0.0, val);\n" + "}\n" + "\n"sv; -const hecl::Backend::Function ExtensionLightingFuncsHLSL[] = -{ - {}, - {LightingHLSL, "LightingFunc"}, - {}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {LightingShadowHLSL, "LightingShadowFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"}, - {LightingHLSL, "LightingFunc"} -}; +const hecl::Backend::Function ExtensionLightingFuncsHLSL[] = {{}, + {LightingHLSL, "LightingFunc"}, + {}, + {LightingHLSL, "LightingFunc"}, + {LightingHLSL, "LightingFunc"}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {LightingShadowHLSL, "LightingShadowFunc"}, + {LightingHLSL, "LightingFunc"}, + {LightingHLSL, "LightingFunc"}, + {LightingHLSL, "LightingFunc"}, + {LightingHLSL, "LightingFunc"}, + {LightingHLSL, "LightingFunc"}, + {LightingHLSL, "LightingFunc"}, + {LightingHLSL, "LightingFunc"}}; -const hecl::Backend::Function ExtensionPostFuncsHLSL[] = -{ +const hecl::Backend::Function ExtensionPostFuncsHLSL[] = { {}, {MainPostHLSL, "MainPostFunc"}, {ThermalPostHLSL, "ThermalPostFunc"}, @@ -241,4 +237,4 @@ const hecl::Backend::Function ExtensionPostFuncsHLSL[] = {MainPostHLSL, "MainPostFunc"}, }; -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CModelShadersMetal.cpp b/Runtime/Graphics/Shaders/CModelShadersMetal.cpp index 425593d56..cedc598b2 100644 --- a/Runtime/Graphics/Shaders/CModelShadersMetal.cpp +++ b/Runtime/Graphics/Shaders/CModelShadersMetal.cpp @@ -1,7 +1,6 @@ #include "CModelShaders.hpp" -namespace urde -{ +namespace urde { using namespace std::literals; extern const hecl::Backend::Function ExtensionLightingFuncsMetal[]; @@ -119,111 +118,109 @@ static std::string_view LightingShadowMetal = "}\n"sv; static std::string_view MainPostMetal = -"float4 MainPostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, float4 colorIn)\n" -"{\n" -" float fogZ, temp;\n" -" switch (lu.fog.mode)\n" -" {\n" -" case 2:\n" -" fogZ = (-vtf.mvPos.z - lu.fog.start) * lu.fog.rangeScale;\n" -" break;\n" -" case 4:\n" -" fogZ = 1.0 - exp2(-8.0 * (-vtf.mvPos.z - lu.fog.start) * lu.fog.rangeScale);\n" -" break;\n" -" case 5:\n" -" temp = (-vtf.mvPos.z - lu.fog.start) * lu.fog.rangeScale;\n" -" fogZ = 1.0 - exp2(-8.0 * temp * temp);\n" -" break;\n" -" case 6:\n" -" fogZ = exp2(-8.0 * (lu.fog.start + vtf.mvPos.z) * lu.fog.rangeScale);\n" -" break;\n" -" case 7:\n" -" temp = (lu.fog.start + vtf.mvPos.z) * lu.fog.rangeScale;\n" -" fogZ = exp2(-8.0 * temp * temp);\n" -" break;\n" -" default:\n" -" fogZ = 0.0;\n" -" break;\n" -" }\n" -"#ifdef BLEND_DST_ONE\n" -" return float4(mix(colorIn, float4(0.0), saturate(fogZ)).rgb, colorIn.a);\n" -"#else\n" -" return float4(mix(colorIn, lu.fog.color, saturate(fogZ)).rgb, colorIn.a);\n" -"#endif\n" -"}\n" -"\n"sv; + "float4 MainPostFunc(thread VertToFrag& vtf, constant LightingUniform& lu, float4 colorIn)\n" + "{\n" + " float fogZ, temp;\n" + " switch (lu.fog.mode)\n" + " {\n" + " case 2:\n" + " fogZ = (-vtf.mvPos.z - lu.fog.start) * lu.fog.rangeScale;\n" + " break;\n" + " case 4:\n" + " fogZ = 1.0 - exp2(-8.0 * (-vtf.mvPos.z - lu.fog.start) * lu.fog.rangeScale);\n" + " break;\n" + " case 5:\n" + " temp = (-vtf.mvPos.z - lu.fog.start) * lu.fog.rangeScale;\n" + " fogZ = 1.0 - exp2(-8.0 * temp * temp);\n" + " break;\n" + " case 6:\n" + " fogZ = exp2(-8.0 * (lu.fog.start + vtf.mvPos.z) * lu.fog.rangeScale);\n" + " break;\n" + " case 7:\n" + " temp = (lu.fog.start + vtf.mvPos.z) * lu.fog.rangeScale;\n" + " fogZ = exp2(-8.0 * temp * temp);\n" + " break;\n" + " default:\n" + " fogZ = 0.0;\n" + " break;\n" + " }\n" + "#ifdef BLEND_DST_ONE\n" + " return float4(mix(colorIn, float4(0.0), saturate(fogZ)).rgb, colorIn.a);\n" + "#else\n" + " return float4(mix(colorIn, lu.fog.color, saturate(fogZ)).rgb, colorIn.a);\n" + "#endif\n" + "}\n" + "\n"sv; static std::string_view ThermalPostMetal = -"struct ThermalUniform\n" -"{\n" -" float4 tmulColor;\n" -" float4 addColor;\n" -"};\n" -"static float4 EXTThermalPostFunc(thread VertToFrag& vtf, constant ThermalUniform& lu,\n" -" sampler samp, sampler clampSamp, texture2d extTex7, float4 colorIn)\n" -"{\n" -" //return float4(vtf.extTcgs0.xy, 0.0, 1.0);\n" -" return float4(extTex7.sample(samp, vtf.extTcgs0).rrr * lu.tmulColor.rgb + lu.addColor.rgb,\n" -" lu.tmulColor.a + lu.addColor.a);\n" -"}\n" -"\n"sv; + "struct ThermalUniform\n" + "{\n" + " float4 tmulColor;\n" + " float4 addColor;\n" + "};\n" + "static float4 EXTThermalPostFunc(thread VertToFrag& vtf, constant ThermalUniform& lu,\n" + " sampler samp, sampler clampSamp, texture2d extTex7, float4 colorIn)\n" + "{\n" + " //return float4(vtf.extTcgs0.xy, 0.0, 1.0);\n" + " return float4(extTex7.sample(samp, vtf.extTcgs0).rrr * lu.tmulColor.rgb + lu.addColor.rgb,\n" + " lu.tmulColor.a + lu.addColor.a);\n" + "}\n" + "\n"sv; static std::string_view SolidPostMetal = -"struct SolidUniform\n" -"{\n" -" float4 solidColor;\n" -"};\n" -"static float4 SolidPostFunc(thread VertToFrag& vtf, constant SolidUniform& lu, float4 colorIn)\n" -"{\n" -" return lu.solidColor;\n" -"}\n" -"\n"sv; + "struct SolidUniform\n" + "{\n" + " float4 solidColor;\n" + "};\n" + "static float4 SolidPostFunc(thread VertToFrag& vtf, constant SolidUniform& lu, float4 colorIn)\n" + "{\n" + " return lu.solidColor;\n" + "}\n" + "\n"sv; static std::string_view MBShadowPostMetal = -"struct MBShadowUniform\n" -"{\n" -" float4 shadowUp;\n" -" float shadowId;\n" -"};\n" -"static float4 EXTMBShadowPostFunc(thread VertToFrag& vtf, constant MBShadowUniform& su, sampler samp, sampler clampSamp,\n" -" texture2d extTex0, texture2d extTex1, texture2d extTex2, float4 colorIn)\n" -"{\n" -" float idTexel = extTex0.sample(samp, vtf.extTcgs0).a;\n" -" float sphereTexel = extTex1.sample(samp, vtf.extTcgs1).a;\n" -" float fadeTexel = extTex2.sample(samp, vtf.extTcgs2).a;\n" -" float val = ((fabs(idTexel - su.shadowId) < 0.001) ?\n" -" (dot(vtf.mvNorm.xyz, su.shadowUp.xyz) * su.shadowUp.w) : 0.0) *\n" -" sphereTexel * fadeTexel;\n" -" return float4(0.0, 0.0, 0.0, val);\n" -"}\n" -"\n"sv; + "struct MBShadowUniform\n" + "{\n" + " float4 shadowUp;\n" + " float shadowId;\n" + "};\n" + "static float4 EXTMBShadowPostFunc(thread VertToFrag& vtf, constant MBShadowUniform& su, sampler samp, sampler " + "clampSamp,\n" + " texture2d extTex0, texture2d extTex1, texture2d extTex2, " + "float4 colorIn)\n" + "{\n" + " float idTexel = extTex0.sample(samp, vtf.extTcgs0).a;\n" + " float sphereTexel = extTex1.sample(samp, vtf.extTcgs1).a;\n" + " float fadeTexel = extTex2.sample(samp, vtf.extTcgs2).a;\n" + " float val = ((fabs(idTexel - su.shadowId) < 0.001) ?\n" + " (dot(vtf.mvNorm.xyz, su.shadowUp.xyz) * su.shadowUp.w) : 0.0) *\n" + " sphereTexel * fadeTexel;\n" + " return float4(0.0, 0.0, 0.0, val);\n" + "}\n" + "\n"sv; -const hecl::Backend::Function ExtensionLightingFuncsMetal[] = -{ - {}, - {LightingMetal, "LightingFunc"}, - {}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {LightingShadowMetal, "EXTLightingShadowFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"}, - {LightingMetal, "LightingFunc"} -}; +const hecl::Backend::Function ExtensionLightingFuncsMetal[] = {{}, + {LightingMetal, "LightingFunc"}, + {}, + {LightingMetal, "LightingFunc"}, + {LightingMetal, "LightingFunc"}, + {}, + {}, + {}, + {}, + {}, + {}, + {}, + {LightingShadowMetal, "EXTLightingShadowFunc"}, + {LightingMetal, "LightingFunc"}, + {LightingMetal, "LightingFunc"}, + {LightingMetal, "LightingFunc"}, + {LightingMetal, "LightingFunc"}, + {LightingMetal, "LightingFunc"}, + {LightingMetal, "LightingFunc"}, + {LightingMetal, "LightingFunc"}}; -const hecl::Backend::Function ExtensionPostFuncsMetal[] = -{ +const hecl::Backend::Function ExtensionPostFuncsMetal[] = { {}, {MainPostMetal, "MainPostFunc"}, {ThermalPostMetal, "EXTThermalPostFunc"}, @@ -251,4 +248,4 @@ static const char* ThermalBlockNames[] = {"ThermalUniform"}; static const char* SolidBlockNames[] = {"SolidUniform"}; static const char* MBShadowBlockNames[] = {"MBShadowUniform"}; -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp b/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp index 95a109c42..0592c6f45 100644 --- a/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp +++ b/Runtime/Graphics/Shaders/CParticleSwooshShaders.cpp @@ -3,8 +3,7 @@ #include "Particle/CSwooshDescription.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { boo::ObjToken CParticleSwooshShaders::m_texZWrite; boo::ObjToken CParticleSwooshShaders::m_texNoZWrite; @@ -18,87 +17,73 @@ boo::ObjToken CParticleSwooshShaders::m_noTexAdditiveNoZWr static boo::ObjToken s_Pipeline; -void CParticleSwooshShaders::Initialize() -{ - m_texZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderTexZWrite{}); - m_texNoZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderTexNoZWrite{}); - m_texAdditiveZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderTexAdditiveZWrite{}); - m_texAdditiveNoZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderTexAdditiveNoZWrite{}); - m_noTexZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderNoTexZWrite{}); - m_noTexNoZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderNoTexNoZWrite{}); - m_noTexAdditiveZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderNoTexAdditiveZWrite{}); - m_noTexAdditiveNoZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderNoTexAdditiveNoZWrite{}); +void CParticleSwooshShaders::Initialize() { + m_texZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderTexZWrite{}); + m_texNoZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderTexNoZWrite{}); + m_texAdditiveZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderTexAdditiveZWrite{}); + m_texAdditiveNoZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderTexAdditiveNoZWrite{}); + m_noTexZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderNoTexZWrite{}); + m_noTexNoZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderNoTexNoZWrite{}); + m_noTexAdditiveZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderNoTexAdditiveZWrite{}); + m_noTexAdditiveNoZWrite = hecl::conv->convert(Shader_CParticleSwooshShaderNoTexAdditiveNoZWrite{}); } -void CParticleSwooshShaders::Shutdown() -{ - m_texZWrite.reset(); - m_texNoZWrite.reset(); - m_texAdditiveZWrite.reset(); - m_texAdditiveNoZWrite.reset(); - m_noTexZWrite.reset(); - m_noTexNoZWrite.reset(); - m_noTexAdditiveZWrite.reset(); - m_noTexAdditiveNoZWrite.reset(); +void CParticleSwooshShaders::Shutdown() { + m_texZWrite.reset(); + m_texNoZWrite.reset(); + m_texAdditiveZWrite.reset(); + m_texAdditiveNoZWrite.reset(); + m_noTexZWrite.reset(); + m_noTexNoZWrite.reset(); + m_noTexAdditiveZWrite.reset(); + m_noTexAdditiveNoZWrite.reset(); } -CParticleSwooshShaders::EShaderClass CParticleSwooshShaders::GetShaderClass(CParticleSwoosh& gen) -{ - CSwooshDescription* desc = gen.GetDesc(); +CParticleSwooshShaders::EShaderClass CParticleSwooshShaders::GetShaderClass(CParticleSwoosh& gen) { + CSwooshDescription* desc = gen.GetDesc(); - if (desc->x3c_TEXR) - return EShaderClass::Tex; - else - return EShaderClass::NoTex; + if (desc->x3c_TEXR) + return EShaderClass::Tex; + else + return EShaderClass::NoTex; } -void CParticleSwooshShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CParticleSwoosh& gen) -{ - CSwooshDescription* desc = gen.GetDesc(); - boo::ObjToken pipeline; +void CParticleSwooshShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CParticleSwoosh& gen) { + CSwooshDescription* desc = gen.GetDesc(); + boo::ObjToken pipeline; - if (desc->x3c_TEXR) - { - if (desc->x44_31_AALP) - { - if (desc->x45_24_ZBUF) - pipeline = m_texAdditiveZWrite; - else - pipeline = m_texAdditiveNoZWrite; - } - else - { - if (desc->x45_24_ZBUF) - pipeline = m_texZWrite; - else - pipeline = m_texNoZWrite; - } + if (desc->x3c_TEXR) { + if (desc->x44_31_AALP) { + if (desc->x45_24_ZBUF) + pipeline = m_texAdditiveZWrite; + else + pipeline = m_texAdditiveNoZWrite; + } else { + if (desc->x45_24_ZBUF) + pipeline = m_texZWrite; + else + pipeline = m_texNoZWrite; } - else - { - if (desc->x44_31_AALP) - { - if (desc->x45_24_ZBUF) - pipeline = m_noTexAdditiveZWrite; - else - pipeline = m_noTexAdditiveNoZWrite; - } - else - { - if (desc->x45_24_ZBUF) - pipeline = m_noTexZWrite; - else - pipeline = m_noTexNoZWrite; - } + } else { + if (desc->x44_31_AALP) { + if (desc->x45_24_ZBUF) + pipeline = m_noTexAdditiveZWrite; + else + pipeline = m_noTexAdditiveNoZWrite; + } else { + if (desc->x45_24_ZBUF) + pipeline = m_noTexZWrite; + else + pipeline = m_noTexNoZWrite; } + } - CUVElement* texr = desc->x3c_TEXR.get(); - boo::ObjToken textures[] = {texr ? texr->GetValueTexture(0).GetObj()->GetBooTexture() : nullptr}; + CUVElement* texr = desc->x3c_TEXR.get(); + boo::ObjToken textures[] = {texr ? texr->GetValueTexture(0).GetObj()->GetBooTexture() : nullptr}; - boo::ObjToken uniforms[] = {gen.m_uniformBuf.get()}; - gen.m_dataBind = ctx.newShaderDataBinding(pipeline, gen.m_vertBuf.get(), - nullptr, nullptr, 1, uniforms, - nullptr, texr ? 1 : 0, textures, nullptr, nullptr); + boo::ObjToken uniforms[] = {gen.m_uniformBuf.get()}; + gen.m_dataBind = ctx.newShaderDataBinding(pipeline, gen.m_vertBuf.get(), nullptr, nullptr, 1, uniforms, nullptr, + texr ? 1 : 0, textures, nullptr, nullptr); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CParticleSwooshShaders.hpp b/Runtime/Graphics/Shaders/CParticleSwooshShaders.hpp index 48d1c059e..1d18f840e 100644 --- a/Runtime/Graphics/Shaders/CParticleSwooshShaders.hpp +++ b/Runtime/Graphics/Shaders/CParticleSwooshShaders.hpp @@ -3,43 +3,35 @@ #include "Graphics/CGraphics.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { class CParticleSwoosh; -class CParticleSwooshShaders -{ +class CParticleSwooshShaders { public: - enum class EShaderClass - { - Tex, - NoTex - }; + enum class EShaderClass { Tex, NoTex }; - struct Vert - { - zeus::CVector3f m_pos; - zeus::CVector2f m_uv; - zeus::CColor m_color; - }; + struct Vert { + zeus::CVector3f m_pos; + zeus::CVector2f m_uv; + zeus::CColor m_color; + }; private: - static boo::ObjToken m_texZWrite; - static boo::ObjToken m_texNoZWrite; - static boo::ObjToken m_texAdditiveZWrite; - static boo::ObjToken m_texAdditiveNoZWrite; + static boo::ObjToken m_texZWrite; + static boo::ObjToken m_texNoZWrite; + static boo::ObjToken m_texAdditiveZWrite; + static boo::ObjToken m_texAdditiveNoZWrite; - static boo::ObjToken m_noTexZWrite; - static boo::ObjToken m_noTexNoZWrite; - static boo::ObjToken m_noTexAdditiveZWrite; - static boo::ObjToken m_noTexAdditiveNoZWrite; + static boo::ObjToken m_noTexZWrite; + static boo::ObjToken m_noTexNoZWrite; + static boo::ObjToken m_noTexAdditiveZWrite; + static boo::ObjToken m_noTexAdditiveNoZWrite; public: - static void Initialize(); - static void Shutdown(); - static EShaderClass GetShaderClass(CParticleSwoosh& gen); - static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CParticleSwoosh& gen); + static void Initialize(); + static void Shutdown(); + static EShaderClass GetShaderClass(CParticleSwoosh& gen); + static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, CParticleSwoosh& gen); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CPhazonSuitFilter.cpp b/Runtime/Graphics/Shaders/CPhazonSuitFilter.cpp index f312a626f..dea2fa99c 100644 --- a/Runtime/Graphics/Shaders/CPhazonSuitFilter.cpp +++ b/Runtime/Graphics/Shaders/CPhazonSuitFilter.cpp @@ -3,157 +3,132 @@ #include "Graphics/CGraphics.hpp" #include "Graphics/CTexture.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_IndPipeline; static boo::ObjToken s_Pipeline; static boo::ObjToken s_BlurPipeline; -void CPhazonSuitFilter::Initialize() -{ - s_IndPipeline = hecl::conv->convert(Shader_CPhazonSuitFilterInd{}); - s_Pipeline = hecl::conv->convert(Shader_CPhazonSuitFilterNoInd{}); - s_BlurPipeline = hecl::conv->convert(Shader_CPhazonSuitFilterBlur{}); +void CPhazonSuitFilter::Initialize() { + s_IndPipeline = hecl::conv->convert(Shader_CPhazonSuitFilterInd{}); + s_Pipeline = hecl::conv->convert(Shader_CPhazonSuitFilterNoInd{}); + s_BlurPipeline = hecl::conv->convert(Shader_CPhazonSuitFilterBlur{}); } -void CPhazonSuitFilter::Shutdown() -{ - s_IndPipeline.reset(); - s_Pipeline.reset(); - s_BlurPipeline.reset(); +void CPhazonSuitFilter::Shutdown() { + s_IndPipeline.reset(); + s_Pipeline.reset(); + s_BlurPipeline.reset(); } #define BLUR_SCALE (1.f / 128.f) -void CPhazonSuitFilter::drawBlurPasses(float radius, const CTexture* indTex) -{ - if (!m_dataBind || indTex != m_indTex) - { - m_indTex = indTex; - CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) - { - m_uniBufBlurX = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1); - m_uniBufBlurY = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f) * 2, 1); +void CPhazonSuitFilter::drawBlurPasses(float radius, const CTexture* indTex) { + if (!m_dataBind || indTex != m_indTex) { + m_indTex = indTex; + CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { + m_uniBufBlurX = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1); + m_uniBufBlurY = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f) * 2, 1); - struct BlurVert - { - zeus::CVector3f pos; - zeus::CVector2f uv; - } blurVerts[4] = - { - {{-1.f, 1.f, 0.f}, {0.f, 1.f}}, - {{-1.f, -1.f, 0.f}, {0.f, 0.f}}, - {{ 1.f, 1.f, 0.f}, {1.f, 1.f}}, - {{ 1.f, -1.f, 0.f}, {1.f, 0.f}} - }; - m_blurVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, blurVerts, sizeof(BlurVert), 4); + struct BlurVert { + zeus::CVector3f pos; + zeus::CVector2f uv; + } blurVerts[4] = {{{-1.f, 1.f, 0.f}, {0.f, 1.f}}, + {{-1.f, -1.f, 0.f}, {0.f, 0.f}}, + {{1.f, 1.f, 0.f}, {1.f, 1.f}}, + {{1.f, -1.f, 0.f}, {1.f, 0.f}}}; + m_blurVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, blurVerts, sizeof(BlurVert), 4); - float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); - struct Vert - { - zeus::CVector3f pos; - zeus::CVector2f screenUv; - zeus::CVector2f indUv; - zeus::CVector2f maskUv; - } verts[4] = - { - {{-1.f, 1.f, 0.f}, {0.01f, 0.99f}, {0.f, 4.f}, {0.f, 1.f}}, - {{-1.f, -1.f, 0.f}, {0.01f, 0.01f}, {0.f, 0.f}, {0.f, 0.f}}, - {{ 1.f, 1.f, 0.f}, {0.99f, 0.99f}, {aspect * 4.f, 4.f}, {1.f, 1.f}}, - {{ 1.f, -1.f, 0.f}, {0.99f, 0.01f}, {aspect * 4.f, 0.f}, {1.f, 0.f}} - }; - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4); + float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); + struct Vert { + zeus::CVector3f pos; + zeus::CVector2f screenUv; + zeus::CVector2f indUv; + zeus::CVector2f maskUv; + } verts[4] = {{{-1.f, 1.f, 0.f}, {0.01f, 0.99f}, {0.f, 4.f}, {0.f, 1.f}}, + {{-1.f, -1.f, 0.f}, {0.01f, 0.01f}, {0.f, 0.f}, {0.f, 0.f}}, + {{1.f, 1.f, 0.f}, {0.99f, 0.99f}, {aspect * 4.f, 4.f}, {1.f, 1.f}}, + {{1.f, -1.f, 0.f}, {0.99f, 0.01f}, {aspect * 4.f, 0.f}, {1.f, 0.f}}}; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4); - boo::ObjToken bufs[] = {m_uniBufBlurX.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[4]; - int texBindIdxs[4]; + boo::ObjToken bufs[] = {m_uniBufBlurX.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[4]; + int texBindIdxs[4]; - texs[0] = CGraphics::g_SpareTexture.get(); - texBindIdxs[0] = 1; - m_dataBindBlurX = ctx.newShaderDataBinding(s_BlurPipeline, m_blurVbo.get(), nullptr, nullptr, 1, bufs, - stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr); + texs[0] = CGraphics::g_SpareTexture.get(); + texBindIdxs[0] = 1; + m_dataBindBlurX = ctx.newShaderDataBinding(s_BlurPipeline, m_blurVbo.get(), nullptr, nullptr, 1, bufs, stages, + nullptr, nullptr, 1, texs, texBindIdxs, nullptr); - bufs[0] = m_uniBufBlurY.get(); - texs[0] = CGraphics::g_SpareTexture.get(); - texBindIdxs[0] = 2; - m_dataBindBlurY = ctx.newShaderDataBinding(s_BlurPipeline, m_blurVbo.get(), nullptr, nullptr, 1, bufs, - stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr); + bufs[0] = m_uniBufBlurY.get(); + texs[0] = CGraphics::g_SpareTexture.get(); + texBindIdxs[0] = 2; + m_dataBindBlurY = ctx.newShaderDataBinding(s_BlurPipeline, m_blurVbo.get(), nullptr, nullptr, 1, bufs, stages, + nullptr, nullptr, 1, texs, texBindIdxs, nullptr); - bufs[0] = m_uniBuf.get(); - size_t texCount; - if (m_indTex) - { - texs[0] = CGraphics::g_SpareTexture.get(); - texBindIdxs[0] = 0; - texs[1] = m_indTex->GetBooTexture(); - texBindIdxs[1] = 0; - texs[2] = CGraphics::g_SpareTexture.get(); - texBindIdxs[2] = 1; - texs[3] = CGraphics::g_SpareTexture.get(); - texBindIdxs[3] = 2; - texCount = 4; - } - else - { - texs[0] = CGraphics::g_SpareTexture.get(); - texBindIdxs[0] = 0; - texs[1] = CGraphics::g_SpareTexture.get(); - texBindIdxs[1] = 1; - texs[2] = CGraphics::g_SpareTexture.get(); - texBindIdxs[2] = 2; - texCount = 3; - } + bufs[0] = m_uniBuf.get(); + size_t texCount; + if (m_indTex) { + texs[0] = CGraphics::g_SpareTexture.get(); + texBindIdxs[0] = 0; + texs[1] = m_indTex->GetBooTexture(); + texBindIdxs[1] = 0; + texs[2] = CGraphics::g_SpareTexture.get(); + texBindIdxs[2] = 1; + texs[3] = CGraphics::g_SpareTexture.get(); + texBindIdxs[3] = 2; + texCount = 4; + } else { + texs[0] = CGraphics::g_SpareTexture.get(); + texBindIdxs[0] = 0; + texs[1] = CGraphics::g_SpareTexture.get(); + texBindIdxs[1] = 1; + texs[2] = CGraphics::g_SpareTexture.get(); + texBindIdxs[2] = 2; + texCount = 3; + } - m_dataBind = ctx.newShaderDataBinding(m_indTex ? s_IndPipeline : s_Pipeline, - m_vbo.get(), nullptr, nullptr, 1, bufs, stages, - nullptr, nullptr, texCount, texs, texBindIdxs, nullptr); - return true; - } BooTrace); - } + m_dataBind = ctx.newShaderDataBinding(m_indTex ? s_IndPipeline : s_Pipeline, m_vbo.get(), nullptr, nullptr, 1, + bufs, stages, nullptr, nullptr, texCount, texs, texBindIdxs, nullptr); + return true; + } BooTrace); + } - SClipScreenRect rect; - rect.x4_left = g_Viewport.x0_left; - rect.x8_top = g_Viewport.x4_top; - rect.xc_width = g_Viewport.x8_width; - rect.x10_height = g_Viewport.xc_height; + SClipScreenRect rect; + rect.x4_left = g_Viewport.x0_left; + rect.x8_top = g_Viewport.x4_top; + rect.xc_width = g_Viewport.x8_width; + rect.x10_height = g_Viewport.xc_height; - /* X Pass */ - zeus::CVector4f blurDir = zeus::CVector4f{g_Viewport.xc_height / float(g_Viewport.x8_width) * - radius * BLUR_SCALE, 0.f, 0.f, 0.f}; - m_uniBufBlurX->load(&blurDir, sizeof(zeus::CVector4f)); + /* X Pass */ + zeus::CVector4f blurDir = + zeus::CVector4f{g_Viewport.xc_height / float(g_Viewport.x8_width) * radius * BLUR_SCALE, 0.f, 0.f, 0.f}; + m_uniBufBlurX->load(&blurDir, sizeof(zeus::CVector4f)); - CGraphics::SetShaderDataBinding(m_dataBindBlurX); - CGraphics::DrawArray(0, 4); - CGraphics::ResolveSpareTexture(rect, 2); + CGraphics::SetShaderDataBinding(m_dataBindBlurX); + CGraphics::DrawArray(0, 4); + CGraphics::ResolveSpareTexture(rect, 2); - /* Y Pass */ - blurDir = zeus::CVector4f{0.f, radius * BLUR_SCALE, 0.f, 0.f}; - m_uniBufBlurY->load(&blurDir, sizeof(zeus::CVector4f)); + /* Y Pass */ + blurDir = zeus::CVector4f{0.f, radius * BLUR_SCALE, 0.f, 0.f}; + m_uniBufBlurY->load(&blurDir, sizeof(zeus::CVector4f)); - CGraphics::SetShaderDataBinding(m_dataBindBlurY); - CGraphics::DrawArray(0, 4); - CGraphics::ResolveSpareTexture(rect, 2); + CGraphics::SetShaderDataBinding(m_dataBindBlurY); + CGraphics::DrawArray(0, 4); + CGraphics::ResolveSpareTexture(rect, 2); } -void CPhazonSuitFilter::draw(const zeus::CColor& color, - float indScale, float indOffX, float indOffY) -{ - struct Uniform - { - zeus::CColor color; - zeus::CVector4f indScaleOff; - } uniform = - { - color, - zeus::CVector4f(indScale, indScale, indOffX, indOffY) - }; +void CPhazonSuitFilter::draw(const zeus::CColor& color, float indScale, float indOffX, float indOffY) { + struct Uniform { + zeus::CColor color; + zeus::CVector4f indScaleOff; + } uniform = {color, zeus::CVector4f(indScale, indScale, indOffX, indOffY)}; - m_uniBuf->load(&uniform, sizeof(Uniform)); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); + m_uniBuf->load(&uniform, sizeof(Uniform)); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CPhazonSuitFilter.hpp b/Runtime/Graphics/Shaders/CPhazonSuitFilter.hpp index a1bc093e6..f107b4063 100644 --- a/Runtime/Graphics/Shaders/CPhazonSuitFilter.hpp +++ b/Runtime/Graphics/Shaders/CPhazonSuitFilter.hpp @@ -3,29 +3,25 @@ #include "boo/graphicsdev/IGraphicsDataFactory.hpp" #include "zeus/CColor.hpp" -namespace urde -{ +namespace urde { class CTexture; -class CPhazonSuitFilter -{ - boo::ObjToken m_uniBufBlurX; - boo::ObjToken m_uniBufBlurY; - boo::ObjToken m_uniBuf; - boo::ObjToken m_blurVbo; - boo::ObjToken m_vbo; - const CTexture* m_indTex = nullptr; - boo::ObjToken m_dataBindBlurX; - boo::ObjToken m_dataBindBlurY; - boo::ObjToken m_dataBind; +class CPhazonSuitFilter { + boo::ObjToken m_uniBufBlurX; + boo::ObjToken m_uniBufBlurY; + boo::ObjToken m_uniBuf; + boo::ObjToken m_blurVbo; + boo::ObjToken m_vbo; + const CTexture* m_indTex = nullptr; + boo::ObjToken m_dataBindBlurX; + boo::ObjToken m_dataBindBlurY; + boo::ObjToken m_dataBind; public: - static void Initialize(); - static void Shutdown(); - void drawBlurPasses(float radius, const CTexture* indTex); - void draw(const zeus::CColor& color, - float indScale, float indOffX, float indOffY); + static void Initialize(); + static void Shutdown(); + void drawBlurPasses(float radius, const CTexture* indTex); + void draw(const zeus::CColor& color, float indScale, float indOffX, float indOffY); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CRadarPaintShader.cpp b/Runtime/Graphics/Shaders/CRadarPaintShader.cpp index f005dde81..e0ae15f7b 100644 --- a/Runtime/Graphics/Shaders/CRadarPaintShader.cpp +++ b/Runtime/Graphics/Shaders/CRadarPaintShader.cpp @@ -3,53 +3,43 @@ #include "Graphics/CGraphics.hpp" #include "Graphics/CTexture.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; -void CRadarPaintShader::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CRadarPaintShader{}); +void CRadarPaintShader::Initialize() { s_Pipeline = hecl::conv->convert(Shader_CRadarPaintShader{}); } + +void CRadarPaintShader::Shutdown() { s_Pipeline.reset(); } + +void CRadarPaintShader::draw(const std::vector& instances, const CTexture* tex) { + if (!instances.size()) + return; + + if (instances.size() > m_maxInsts) { + m_maxInsts = instances.size(); + m_tex = tex; + CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Instance), m_maxInsts); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CMatrix4f), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {m_tex->GetBooTexture()}; + m_dataBind = ctx.newShaderDataBinding(s_Pipeline, nullptr, m_vbo.get(), nullptr, 1, bufs, stages, nullptr, + nullptr, 1, texs, nullptr, nullptr); + return true; + } BooTrace); + } + + zeus::CMatrix4f uniMtx = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); + m_uniBuf->load(&uniMtx, sizeof(zeus::CMatrix4f)); + + size_t mapSz = sizeof(Instance) * instances.size(); + Instance* insts = reinterpret_cast(m_vbo->map(mapSz)); + memmove(insts, instances.data(), mapSz); + m_vbo->unmap(); + + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawInstances(0, 4, instances.size()); } -void CRadarPaintShader::Shutdown() -{ - s_Pipeline.reset(); -} - -void CRadarPaintShader::draw(const std::vector& instances, const CTexture* tex) -{ - if (!instances.size()) - return; - - if (instances.size() > m_maxInsts) - { - m_maxInsts = instances.size(); - m_tex = tex; - CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Instance), m_maxInsts); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CMatrix4f), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {m_tex->GetBooTexture()}; - m_dataBind = ctx.newShaderDataBinding(s_Pipeline, nullptr, m_vbo.get(), nullptr, - 1, bufs, stages, nullptr, nullptr, 1, texs, nullptr, nullptr); - return true; - } BooTrace); - } - - zeus::CMatrix4f uniMtx = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); - m_uniBuf->load(&uniMtx, sizeof(zeus::CMatrix4f)); - - size_t mapSz = sizeof(Instance) * instances.size(); - Instance* insts = reinterpret_cast(m_vbo->map(mapSz)); - memmove(insts, instances.data(), mapSz); - m_vbo->unmap(); - - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawInstances(0, 4, instances.size()); -} - -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CRadarPaintShader.hpp b/Runtime/Graphics/Shaders/CRadarPaintShader.hpp index b6350d44e..cac244d60 100644 --- a/Runtime/Graphics/Shaders/CRadarPaintShader.hpp +++ b/Runtime/Graphics/Shaders/CRadarPaintShader.hpp @@ -5,31 +5,27 @@ #include "zeus/CRectangle.hpp" #include "Camera/CCameraFilter.hpp" -namespace urde -{ +namespace urde { -class CRadarPaintShader -{ +class CRadarPaintShader { public: - struct Instance - { - zeus::CVector3f pos[4]; - zeus::CVector2f uv[4]; - zeus::CColor color; - }; + struct Instance { + zeus::CVector3f pos[4]; + zeus::CVector2f uv[4]; + zeus::CColor color; + }; private: - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - const CTexture* m_tex = nullptr; - size_t m_maxInsts = 0; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + const CTexture* m_tex = nullptr; + size_t m_maxInsts = 0; public: - static void Initialize(); - static void Shutdown(); - void draw(const std::vector& instances, const CTexture* tex); + static void Initialize(); + static void Shutdown(); + void draw(const std::vector& instances, const CTexture* tex); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CRandomStaticFilter.cpp b/Runtime/Graphics/Shaders/CRandomStaticFilter.cpp index 4ab02e9c4..aa6ff36e1 100644 --- a/Runtime/Graphics/Shaders/CRandomStaticFilter.cpp +++ b/Runtime/Graphics/Shaders/CRandomStaticFilter.cpp @@ -4,83 +4,72 @@ #include "CSimplePool.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_AlphaPipeline; static boo::ObjToken s_AddPipeline; static boo::ObjToken s_MultPipeline; static boo::ObjToken s_CookieCutterPipeline; -void CRandomStaticFilter::Initialize() -{ - s_AlphaPipeline = hecl::conv->convert(Shader_CRandomStaticFilterAlpha{}); - s_AddPipeline = hecl::conv->convert(Shader_CRandomStaticFilterAdd{}); - s_MultPipeline = hecl::conv->convert(Shader_CRandomStaticFilterMult{}); - s_CookieCutterPipeline = hecl::conv->convert(Shader_CRandomStaticFilterCookieCutter{}); +void CRandomStaticFilter::Initialize() { + s_AlphaPipeline = hecl::conv->convert(Shader_CRandomStaticFilterAlpha{}); + s_AddPipeline = hecl::conv->convert(Shader_CRandomStaticFilterAdd{}); + s_MultPipeline = hecl::conv->convert(Shader_CRandomStaticFilterMult{}); + s_CookieCutterPipeline = hecl::conv->convert(Shader_CRandomStaticFilterCookieCutter{}); } -void CRandomStaticFilter::Shutdown() -{ - s_AlphaPipeline.reset(); - s_AddPipeline.reset(); - s_MultPipeline.reset(); - s_CookieCutterPipeline.reset(); +void CRandomStaticFilter::Shutdown() { + s_AlphaPipeline.reset(); + s_AddPipeline.reset(); + s_MultPipeline.reset(); + s_CookieCutterPipeline.reset(); } -static boo::ObjToken SelectPipeline(EFilterType type) -{ - switch (type) - { - case EFilterType::Blend: - return s_AlphaPipeline; - case EFilterType::Add: - return s_AddPipeline; - case EFilterType::Multiply: - return s_MultPipeline; - default: - return {}; - } +static boo::ObjToken SelectPipeline(EFilterType type) { + switch (type) { + case EFilterType::Blend: + return s_AlphaPipeline; + case EFilterType::Add: + return s_AddPipeline; + case EFilterType::Multiply: + return s_MultPipeline; + default: + return {}; + } } -CRandomStaticFilter::CRandomStaticFilter(EFilterType type, bool cookieCutter) -: m_cookieCutter(cookieCutter) -{ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - struct Vert - { - zeus::CVector2f m_pos; - zeus::CVector2f m_uv; - } verts[4] = - { - {{-1.f, -1.f}, {0.f, 0.f}}, - {{-1.f, 1.f}, {0.f, 448.f}}, - {{ 1.f, -1.f}, {640.f, 0.f}}, - {{ 1.f, 1.f}, {640.f, 448.f}}, - }; - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {g_Renderer->GetRandomStaticEntropyTex()}; - m_dataBind = ctx.newShaderDataBinding(m_cookieCutter ? s_CookieCutterPipeline : SelectPipeline(type), - m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, nullptr, - 1, texs, nullptr, nullptr); - return true; - } BooTrace); +CRandomStaticFilter::CRandomStaticFilter(EFilterType type, bool cookieCutter) : m_cookieCutter(cookieCutter) { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + struct Vert { + zeus::CVector2f m_pos; + zeus::CVector2f m_uv; + } verts[4] = { + {{-1.f, -1.f}, {0.f, 0.f}}, + {{-1.f, 1.f}, {0.f, 448.f}}, + {{1.f, -1.f}, {640.f, 0.f}}, + {{1.f, 1.f}, {640.f, 448.f}}, + }; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {g_Renderer->GetRandomStaticEntropyTex()}; + m_dataBind = + ctx.newShaderDataBinding(m_cookieCutter ? s_CookieCutterPipeline : SelectPipeline(type), m_vbo.get(), nullptr, + nullptr, 1, bufs, stages, nullptr, nullptr, 1, texs, nullptr, nullptr); + return true; + } BooTrace); } -void CRandomStaticFilter::draw(const zeus::CColor& color, float t) -{ - m_uniform.color = color; - m_uniform.randOff = ROUND_UP_32(int64_t(rand()) * 32767 / RAND_MAX); - m_uniform.discardThres = 1.f - t; +void CRandomStaticFilter::draw(const zeus::CColor& color, float t) { + m_uniform.color = color; + m_uniform.randOff = ROUND_UP_32(int64_t(rand()) * 32767 / RAND_MAX); + m_uniform.discardThres = 1.f - t; - m_uniBuf->load(&m_uniform, sizeof(Uniform)); + m_uniBuf->load(&m_uniform, sizeof(Uniform)); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CRandomStaticFilter.hpp b/Runtime/Graphics/Shaders/CRandomStaticFilter.hpp index af9fe7777..99087338c 100644 --- a/Runtime/Graphics/Shaders/CRandomStaticFilter.hpp +++ b/Runtime/Graphics/Shaders/CRandomStaticFilter.hpp @@ -5,41 +5,34 @@ #include "zeus/CRectangle.hpp" #include "Camera/CCameraFilter.hpp" -namespace urde -{ +namespace urde { -class CRandomStaticFilter -{ - struct Uniform - { - zeus::CColor color; - float randOff; - float discardThres; - }; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; - bool m_cookieCutter; +class CRandomStaticFilter { + struct Uniform { + zeus::CColor color; + float randOff; + float discardThres; + }; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; + bool m_cookieCutter; public: - static void Initialize(); - static void Shutdown(); - CRandomStaticFilter(EFilterType type, bool cookieCutter=false); - CRandomStaticFilter(EFilterType type, const TLockedToken&) - : CRandomStaticFilter(type) {} - void draw(const zeus::CColor& color, float t); - void DrawFilter(EFilterShape, const zeus::CColor& color, float t) { draw(color, t); } + static void Initialize(); + static void Shutdown(); + CRandomStaticFilter(EFilterType type, bool cookieCutter = false); + CRandomStaticFilter(EFilterType type, const TLockedToken&) : CRandomStaticFilter(type) {} + void draw(const zeus::CColor& color, float t); + void DrawFilter(EFilterShape, const zeus::CColor& color, float t) { draw(color, t); } }; -class CCookieCutterDepthRandomStaticFilter : public CRandomStaticFilter -{ +class CCookieCutterDepthRandomStaticFilter : public CRandomStaticFilter { public: - CCookieCutterDepthRandomStaticFilter(EFilterType type) - : CRandomStaticFilter(type, true) {} - CCookieCutterDepthRandomStaticFilter(EFilterType type, const TLockedToken&) - : CCookieCutterDepthRandomStaticFilter(type) {} + CCookieCutterDepthRandomStaticFilter(EFilterType type) : CRandomStaticFilter(type, true) {} + CCookieCutterDepthRandomStaticFilter(EFilterType type, const TLockedToken&) + : CCookieCutterDepthRandomStaticFilter(type) {} }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CScanLinesFilter.cpp b/Runtime/Graphics/Shaders/CScanLinesFilter.cpp index 776de21ae..6e285eff1 100644 --- a/Runtime/Graphics/Shaders/CScanLinesFilter.cpp +++ b/Runtime/Graphics/Shaders/CScanLinesFilter.cpp @@ -4,65 +4,56 @@ #include "GameGlobalObjects.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_AlphaPipeline; static boo::ObjToken s_AddPipeline; static boo::ObjToken s_MultPipeline; -void CScanLinesFilter::Initialize() -{ - s_AlphaPipeline = hecl::conv->convert(Shader_CScanLinesFilterAlpha{}); - s_AddPipeline = hecl::conv->convert(Shader_CScanLinesFilterAdd{}); - s_MultPipeline = hecl::conv->convert(Shader_CScanLinesFilterMult{}); +void CScanLinesFilter::Initialize() { + s_AlphaPipeline = hecl::conv->convert(Shader_CScanLinesFilterAlpha{}); + s_AddPipeline = hecl::conv->convert(Shader_CScanLinesFilterAdd{}); + s_MultPipeline = hecl::conv->convert(Shader_CScanLinesFilterMult{}); } -void CScanLinesFilter::Shutdown() -{ - s_AlphaPipeline.reset(); - s_AddPipeline.reset(); - s_MultPipeline.reset(); +void CScanLinesFilter::Shutdown() { + s_AlphaPipeline.reset(); + s_AddPipeline.reset(); + s_MultPipeline.reset(); } -static boo::ObjToken SelectPipeline(EFilterType type) -{ - switch (type) - { - case EFilterType::Blend: - return s_AlphaPipeline; - case EFilterType::Add: - return s_AddPipeline; - case EFilterType::Multiply: - return s_MultPipeline; - default: - return {}; - } +static boo::ObjToken SelectPipeline(EFilterType type) { + switch (type) { + case EFilterType::Blend: + return s_AlphaPipeline; + case EFilterType::Add: + return s_AddPipeline; + case EFilterType::Multiply: + return s_MultPipeline; + default: + return {}; + } } -CScanLinesFilter::CScanLinesFilter(EFilterType type, bool even) -: m_even(even) -{ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken vbo = m_even ? - g_Renderer->GetScanLinesEvenVBO().get() : g_Renderer->GetScanLinesOddVBO().get(); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - m_dataBind = ctx.newShaderDataBinding(SelectPipeline(type), vbo, nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 0, nullptr, nullptr, nullptr); - return true; - } BooTrace); +CScanLinesFilter::CScanLinesFilter(EFilterType type, bool even) : m_even(even) { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken vbo = + m_even ? g_Renderer->GetScanLinesEvenVBO().get() : g_Renderer->GetScanLinesOddVBO().get(); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + m_dataBind = ctx.newShaderDataBinding(SelectPipeline(type), vbo, nullptr, nullptr, 1, bufs, stages, nullptr, + nullptr, 0, nullptr, nullptr, nullptr); + return true; + } BooTrace); } -void CScanLinesFilter::draw(const zeus::CColor& color) -{ - m_uniform.color = color; - m_uniBuf->load(&m_uniform, sizeof(Uniform)); +void CScanLinesFilter::draw(const zeus::CColor& color) { + m_uniform.color = color; + m_uniBuf->load(&m_uniform, sizeof(Uniform)); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 670); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 670); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CScanLinesFilter.hpp b/Runtime/Graphics/Shaders/CScanLinesFilter.hpp index 3215ee751..8720199fc 100644 --- a/Runtime/Graphics/Shaders/CScanLinesFilter.hpp +++ b/Runtime/Graphics/Shaders/CScanLinesFilter.hpp @@ -5,45 +5,35 @@ #include "zeus/CRectangle.hpp" #include "Camera/CCameraFilter.hpp" -namespace urde -{ +namespace urde { -class CScanLinesFilter -{ - struct Uniform - { - zeus::CColor color; - }; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; - bool m_even; +class CScanLinesFilter { + struct Uniform { + zeus::CColor color; + }; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; + bool m_even; public: - static void Initialize(); - static void Shutdown(); - CScanLinesFilter(EFilterType type, bool even); - void draw(const zeus::CColor& color); - void DrawFilter(EFilterShape, const zeus::CColor& color, float) { draw(color); } + static void Initialize(); + static void Shutdown(); + CScanLinesFilter(EFilterType type, bool even); + void draw(const zeus::CColor& color); + void DrawFilter(EFilterShape, const zeus::CColor& color, float) { draw(color); } }; -class CScanLinesFilterEven : public CScanLinesFilter -{ +class CScanLinesFilterEven : public CScanLinesFilter { public: - CScanLinesFilterEven(EFilterType type) - : CScanLinesFilter(type, true) {} - CScanLinesFilterEven(EFilterType type, const TLockedToken&) - : CScanLinesFilterEven(type) {} + CScanLinesFilterEven(EFilterType type) : CScanLinesFilter(type, true) {} + CScanLinesFilterEven(EFilterType type, const TLockedToken&) : CScanLinesFilterEven(type) {} }; -class CScanLinesFilterOdd : public CScanLinesFilter -{ +class CScanLinesFilterOdd : public CScanLinesFilter { public: - CScanLinesFilterOdd(EFilterType type) - : CScanLinesFilter(type, false) {} - CScanLinesFilterOdd(EFilterType type, const TLockedToken&) - : CScanLinesFilterOdd(type) {} + CScanLinesFilterOdd(EFilterType type) : CScanLinesFilter(type, false) {} + CScanLinesFilterOdd(EFilterType type, const TLockedToken&) : CScanLinesFilterOdd(type) {} }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp b/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp index a377f0322..bee573b98 100644 --- a/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp +++ b/Runtime/Graphics/Shaders/CSpaceWarpFilter.cpp @@ -5,169 +5,148 @@ #define WARP_RAMP_RES 32 -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; -void CSpaceWarpFilter::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CSpaceWarpFilter{}); -} +void CSpaceWarpFilter::Initialize() { s_Pipeline = hecl::conv->convert(Shader_CSpaceWarpFilter{}); } -void CSpaceWarpFilter::Shutdown() -{ - s_Pipeline.reset(); -} +void CSpaceWarpFilter::Shutdown() { s_Pipeline.reset(); } -void CSpaceWarpFilter::GenerateWarpRampTex(boo::IGraphicsDataFactory::Context& ctx) -{ - u8 data[WARP_RAMP_RES+1][WARP_RAMP_RES+1][4] = {}; - float halfRes = WARP_RAMP_RES / 2.f; - for (int y=0 ; y bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get(), m_warpTex.get()}; - m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 2, texs, nullptr, nullptr); - return true; - } BooTrace); + {{-1.0, 1.0}, {0.0, 1.0}}, + {{1.0, -1.0}, {1.0, 0.0}}, + {{1.0, 1.0}, {1.0, 1.0}}, + }; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, 32, 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get(), m_warpTex.get()}; + m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, nullptr, + 2, texs, nullptr, nullptr); + return true; + } BooTrace); } -void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) -{ - /* Indirect coords are full-texture sampling when warp is completely in viewport */ - m_uniform.m_indXf[1][1] = 1.f; - m_uniform.m_indXf[0][0] = 1.f; - m_uniform.m_indXf[2][0] = 0.f; - m_uniform.m_indXf[2][1] = 0.f; +void CSpaceWarpFilter::draw(const zeus::CVector3f& pt) { + /* Indirect coords are full-texture sampling when warp is completely in viewport */ + m_uniform.m_indXf[1][1] = 1.f; + m_uniform.m_indXf[0][0] = 1.f; + m_uniform.m_indXf[2][0] = 0.f; + m_uniform.m_indXf[2][1] = 0.f; - /* Warp effect is fixed at 192x192 rectangle in original (1/2.5 viewport height) */ - float aspect = CGraphics::g_CroppedViewport.xc_width / float(CGraphics::g_CroppedViewport.x10_height); - m_uniform.m_matrix[1][1] = 1.f / 2.5f; - m_uniform.m_matrix[0][0] = m_uniform.m_matrix[1][1] / aspect; + /* Warp effect is fixed at 192x192 rectangle in original (1/2.5 viewport height) */ + float aspect = CGraphics::g_CroppedViewport.xc_width / float(CGraphics::g_CroppedViewport.x10_height); + m_uniform.m_matrix[1][1] = 1.f / 2.5f; + m_uniform.m_matrix[0][0] = m_uniform.m_matrix[1][1] / aspect; - SClipScreenRect clipRect = {}; - clipRect.x4_left = ((pt[0] - m_uniform.m_matrix[0][0]) / 2.f + 0.5f) * CGraphics::g_CroppedViewport.xc_width; - if (clipRect.x4_left >= CGraphics::g_CroppedViewport.xc_width) - return; - clipRect.x8_top = ((pt[1] - m_uniform.m_matrix[1][1]) / 2.f + 0.5f) * CGraphics::g_CroppedViewport.x10_height; - if (clipRect.x8_top >= CGraphics::g_CroppedViewport.x10_height) - return; - clipRect.xc_width = CGraphics::g_CroppedViewport.xc_width * m_uniform.m_matrix[0][0]; - if (clipRect.x4_left + clipRect.xc_width <= 0) - return; - clipRect.x10_height = CGraphics::g_CroppedViewport.x10_height * m_uniform.m_matrix[1][1]; - if (clipRect.x8_top + clipRect.x10_height <= 0) - return; + SClipScreenRect clipRect = {}; + clipRect.x4_left = ((pt[0] - m_uniform.m_matrix[0][0]) / 2.f + 0.5f) * CGraphics::g_CroppedViewport.xc_width; + if (clipRect.x4_left >= CGraphics::g_CroppedViewport.xc_width) + return; + clipRect.x8_top = ((pt[1] - m_uniform.m_matrix[1][1]) / 2.f + 0.5f) * CGraphics::g_CroppedViewport.x10_height; + if (clipRect.x8_top >= CGraphics::g_CroppedViewport.x10_height) + return; + clipRect.xc_width = CGraphics::g_CroppedViewport.xc_width * m_uniform.m_matrix[0][0]; + if (clipRect.x4_left + clipRect.xc_width <= 0) + return; + clipRect.x10_height = CGraphics::g_CroppedViewport.x10_height * m_uniform.m_matrix[1][1]; + if (clipRect.x8_top + clipRect.x10_height <= 0) + return; - float oldW = clipRect.xc_width; - if (clipRect.x4_left < 0) - { - clipRect.xc_width += clipRect.x4_left; - m_uniform.m_indXf[0][0] = clipRect.xc_width / oldW; - m_uniform.m_indXf[2][0] = -clipRect.x4_left / oldW; - clipRect.x4_left = 0; - } + float oldW = clipRect.xc_width; + if (clipRect.x4_left < 0) { + clipRect.xc_width += clipRect.x4_left; + m_uniform.m_indXf[0][0] = clipRect.xc_width / oldW; + m_uniform.m_indXf[2][0] = -clipRect.x4_left / oldW; + clipRect.x4_left = 0; + } - float oldH = clipRect.x10_height; - if (clipRect.x8_top < 0) - { - clipRect.x10_height += clipRect.x8_top; - m_uniform.m_indXf[1][1] = clipRect.x10_height / oldH; - m_uniform.m_indXf[2][1] = -clipRect.x8_top / oldH; - clipRect.x8_top = 0; - } + float oldH = clipRect.x10_height; + if (clipRect.x8_top < 0) { + clipRect.x10_height += clipRect.x8_top; + m_uniform.m_indXf[1][1] = clipRect.x10_height / oldH; + m_uniform.m_indXf[2][1] = -clipRect.x8_top / oldH; + clipRect.x8_top = 0; + } - float tmp = clipRect.x4_left + clipRect.xc_width; - if (tmp >= CGraphics::g_CroppedViewport.xc_width) - { - clipRect.xc_width = CGraphics::g_CroppedViewport.xc_width - clipRect.x4_left; - m_uniform.m_indXf[0][0] = clipRect.xc_width / oldW; - } + float tmp = clipRect.x4_left + clipRect.xc_width; + if (tmp >= CGraphics::g_CroppedViewport.xc_width) { + clipRect.xc_width = CGraphics::g_CroppedViewport.xc_width - clipRect.x4_left; + m_uniform.m_indXf[0][0] = clipRect.xc_width / oldW; + } - tmp = clipRect.x8_top + clipRect.x10_height; - if (tmp >= CGraphics::g_CroppedViewport.x10_height) - { - clipRect.x10_height = CGraphics::g_CroppedViewport.x10_height - clipRect.x8_top; - m_uniform.m_indXf[1][1] = clipRect.x10_height / oldH; - } + tmp = clipRect.x8_top + clipRect.x10_height; + if (tmp >= CGraphics::g_CroppedViewport.x10_height) { + clipRect.x10_height = CGraphics::g_CroppedViewport.x10_height - clipRect.x8_top; + m_uniform.m_indXf[1][1] = clipRect.x10_height / oldH; + } - /* Transform UV coordinates of rectangle within viewport and sampled scene texels (clamped to viewport bounds) */ - zeus::CVector2f vp{float(CGraphics::g_CroppedViewport.xc_width), float(CGraphics::g_CroppedViewport.x10_height)}; - m_uniform.m_matrix[0][0] = clipRect.xc_width / vp.x(); - m_uniform.m_matrix[1][1] = clipRect.x10_height / vp.y(); - m_uniform.m_matrix[3][0] = pt.x() + (1.f / vp.x()); - m_uniform.m_matrix[3][1] = pt.y() + (1.f / vp.y()); - if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) - m_uniform.m_matrix[3][2] = pt.z() * 2.f - 1.f; - else - m_uniform.m_matrix[3][2] = pt.z(); + /* Transform UV coordinates of rectangle within viewport and sampled scene texels (clamped to viewport bounds) */ + zeus::CVector2f vp{float(CGraphics::g_CroppedViewport.xc_width), float(CGraphics::g_CroppedViewport.x10_height)}; + m_uniform.m_matrix[0][0] = clipRect.xc_width / vp.x(); + m_uniform.m_matrix[1][1] = clipRect.x10_height / vp.y(); + m_uniform.m_matrix[3][0] = pt.x() + (1.f / vp.x()); + m_uniform.m_matrix[3][1] = pt.y() + (1.f / vp.y()); + if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) + m_uniform.m_matrix[3][2] = pt.z() * 2.f - 1.f; + else + m_uniform.m_matrix[3][2] = pt.z(); - if (clipRect.x4_left) - { - clipRect.x4_left -= 1; - clipRect.xc_width += 1; - } - if (clipRect.x8_top) - { - clipRect.x8_top -= 1; - clipRect.x10_height += 1; - } - if (clipRect.x4_left + clipRect.xc_width < CGraphics::g_CroppedViewport.xc_width) - clipRect.xc_width += 1; - if (clipRect.x8_top + clipRect.x10_height < CGraphics::g_CroppedViewport.x10_height) - clipRect.x10_height += 1; - - clipRect.x4_left += CGraphics::g_CroppedViewport.x4_left; - clipRect.x8_top += CGraphics::g_CroppedViewport.x8_top; - clipRect.x8_top = g_Viewport.xc_height - clipRect.x10_height - clipRect.x8_top; - CGraphics::ResolveSpareTexture(clipRect); + if (clipRect.x4_left) { + clipRect.x4_left -= 1; + clipRect.xc_width += 1; + } + if (clipRect.x8_top) { + clipRect.x8_top -= 1; + clipRect.x10_height += 1; + } + if (clipRect.x4_left + clipRect.xc_width < CGraphics::g_CroppedViewport.xc_width) + clipRect.xc_width += 1; + if (clipRect.x8_top + clipRect.x10_height < CGraphics::g_CroppedViewport.x10_height) + clipRect.x10_height += 1; - m_uniform.m_strength.x() = m_uniform.m_matrix[0][0] * m_strength * 0.5f * - (clipRect.x10_height / float(clipRect.xc_width)); - m_uniform.m_strength.y() = m_uniform.m_matrix[1][1] * m_strength * 0.5f; - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + clipRect.x4_left += CGraphics::g_CroppedViewport.x4_left; + clipRect.x8_top += CGraphics::g_CroppedViewport.x8_top; + clipRect.x8_top = g_Viewport.xc_height - clipRect.x10_height - clipRect.x8_top; + CGraphics::ResolveSpareTexture(clipRect); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); + m_uniform.m_strength.x() = + m_uniform.m_matrix[0][0] * m_strength * 0.5f * (clipRect.x10_height / float(clipRect.xc_width)); + m_uniform.m_strength.y() = m_uniform.m_matrix[1][1] * m_strength * 0.5f; + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp b/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp index bab72077d..36ea5eb99 100644 --- a/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp +++ b/Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp @@ -5,34 +5,30 @@ #include "zeus/CMatrix4f.hpp" #include "zeus/CColor.hpp" -namespace urde -{ +namespace urde { -class CSpaceWarpFilter -{ - struct Uniform - { - zeus::CMatrix4f m_matrix; - zeus::CMatrix4f m_indXf; - zeus::CVector3f m_strength; - }; - u8 m_shiftTexture[4][8][4] = {}; - boo::ObjToken m_warpTex; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; - float m_strength = 1.f; +class CSpaceWarpFilter { + struct Uniform { + zeus::CMatrix4f m_matrix; + zeus::CMatrix4f m_indXf; + zeus::CVector3f m_strength; + }; + u8 m_shiftTexture[4][8][4] = {}; + boo::ObjToken m_warpTex; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; + float m_strength = 1.f; - void GenerateWarpRampTex(boo::IGraphicsDataFactory::Context& ctx); + void GenerateWarpRampTex(boo::IGraphicsDataFactory::Context& ctx); public: - static void Initialize(); - static void Shutdown(); - CSpaceWarpFilter(); - void setStrength(float strength) { m_strength = strength; } - void draw(const zeus::CVector3f& pt); + static void Initialize(); + static void Shutdown(); + CSpaceWarpFilter(); + void setStrength(float strength) { m_strength = strength; } + void draw(const zeus::CVector3f& pt); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CTextSupportShader.cpp b/Runtime/Graphics/Shaders/CTextSupportShader.cpp index 740d23ba4..f7dd7a691 100644 --- a/Runtime/Graphics/Shaders/CTextSupportShader.cpp +++ b/Runtime/Graphics/Shaders/CTextSupportShader.cpp @@ -2,8 +2,7 @@ #include "GuiSys/CRasterFont.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { boo::ObjToken CTextSupportShader::s_TextAlphaPipeline; boo::ObjToken CTextSupportShader::s_TextAddPipeline; @@ -17,71 +16,63 @@ hecl::VertexBufferPool CTextSupportShader hecl::VertexBufferPool CTextSupportShader::s_ImgInsts; hecl::UniformBufferPool CTextSupportShader::s_Uniforms; -void CTextSupportShader::Initialize() -{ - s_TextAlphaPipeline = hecl::conv->convert(Shader_CTextSupportShaderAlpha{}); - s_TextAddPipeline = hecl::conv->convert(Shader_CTextSupportShaderAdd{}); - s_TextAddOverdrawPipeline = hecl::conv->convert(Shader_CTextSupportShaderAddOverdraw{}); - s_ImageAlphaPipeline = hecl::conv->convert(Shader_CTextSupportShaderImageAlpha{}); - s_ImageAddPipeline = hecl::conv->convert(Shader_CTextSupportShaderImageAdd{}); - s_ImageAddOverdrawPipeline = hecl::conv->convert(Shader_CTextSupportShaderImageAddOverdraw{}); +void CTextSupportShader::Initialize() { + s_TextAlphaPipeline = hecl::conv->convert(Shader_CTextSupportShaderAlpha{}); + s_TextAddPipeline = hecl::conv->convert(Shader_CTextSupportShaderAdd{}); + s_TextAddOverdrawPipeline = hecl::conv->convert(Shader_CTextSupportShaderAddOverdraw{}); + s_ImageAlphaPipeline = hecl::conv->convert(Shader_CTextSupportShaderImageAlpha{}); + s_ImageAddPipeline = hecl::conv->convert(Shader_CTextSupportShaderImageAdd{}); + s_ImageAddOverdrawPipeline = hecl::conv->convert(Shader_CTextSupportShaderImageAddOverdraw{}); } -void CTextSupportShader::Shutdown() -{ - s_TextAlphaPipeline.reset(); - s_TextAddPipeline.reset(); - s_TextAddOverdrawPipeline.reset(); - s_ImageAlphaPipeline.reset(); - s_ImageAddPipeline.reset(); - s_ImageAddOverdrawPipeline.reset(); +void CTextSupportShader::Shutdown() { + s_TextAlphaPipeline.reset(); + s_TextAddPipeline.reset(); + s_TextAddOverdrawPipeline.reset(); + s_ImageAlphaPipeline.reset(); + s_ImageAddPipeline.reset(); + s_ImageAddOverdrawPipeline.reset(); - s_CharInsts.doDestroy(); - s_ImgInsts.doDestroy(); - s_Uniforms.doDestroy(); + s_CharInsts.doDestroy(); + s_ImgInsts.doDestroy(); + s_Uniforms.doDestroy(); } -void CTextSupportShader::CharacterInstance::SetMetrics(const CGlyph& glyph, - const zeus::CVector2i& offset) -{ - float layer = glyph.GetLayer(); +void CTextSupportShader::CharacterInstance::SetMetrics(const CGlyph& glyph, const zeus::CVector2i& offset) { + float layer = glyph.GetLayer(); - m_pos[0].assign(offset.x, 0.f, offset.y); - m_uv[0].assign(glyph.GetStartU(), 1.f - glyph.GetStartV(), layer); + m_pos[0].assign(offset.x, 0.f, offset.y); + m_uv[0].assign(glyph.GetStartU(), 1.f - glyph.GetStartV(), layer); - m_pos[1].assign(offset.x + glyph.GetCellWidth(), 0.f, offset.y); - m_uv[1].assign(glyph.GetEndU(), 1.f - glyph.GetStartV(), layer); + m_pos[1].assign(offset.x + glyph.GetCellWidth(), 0.f, offset.y); + m_uv[1].assign(glyph.GetEndU(), 1.f - glyph.GetStartV(), layer); - m_pos[2].assign(offset.x, 0.f, offset.y + glyph.GetCellHeight()); - m_uv[2].assign(glyph.GetStartU(), 1.f - glyph.GetEndV(), layer); + m_pos[2].assign(offset.x, 0.f, offset.y + glyph.GetCellHeight()); + m_uv[2].assign(glyph.GetStartU(), 1.f - glyph.GetEndV(), layer); - m_pos[3].assign(offset.x + glyph.GetCellWidth(), 0.f, offset.y + glyph.GetCellHeight()); - m_uv[3].assign(glyph.GetEndU(), 1.f - glyph.GetEndV(), layer); + m_pos[3].assign(offset.x + glyph.GetCellWidth(), 0.f, offset.y + glyph.GetCellHeight()); + m_uv[3].assign(glyph.GetEndU(), 1.f - glyph.GetEndV(), layer); } -void CTextSupportShader::ImageInstance::SetMetrics(const CFontImageDef& imgDef, - const zeus::CVector2i& offset) -{ - zeus::CVector2f imgSize; - if (imgDef.x4_texs.size()) - { - const CTexture& tex = *imgDef.x4_texs[0].GetObj(); - imgSize.assign(tex.GetWidth() * imgDef.x14_cropFactor.x(), - tex.GetHeight() * imgDef.x14_cropFactor.y()); - } - zeus::CVector2f cropPad = imgDef.x14_cropFactor * 0.5f; +void CTextSupportShader::ImageInstance::SetMetrics(const CFontImageDef& imgDef, const zeus::CVector2i& offset) { + zeus::CVector2f imgSize; + if (imgDef.x4_texs.size()) { + const CTexture& tex = *imgDef.x4_texs[0].GetObj(); + imgSize.assign(tex.GetWidth() * imgDef.x14_cropFactor.x(), tex.GetHeight() * imgDef.x14_cropFactor.y()); + } + zeus::CVector2f cropPad = imgDef.x14_cropFactor * 0.5f; - m_pos[0].assign(offset.x, 0.f, offset.y); - m_uv[0].assign(0.5f - cropPad.x(), 0.5f + cropPad.y()); + m_pos[0].assign(offset.x, 0.f, offset.y); + m_uv[0].assign(0.5f - cropPad.x(), 0.5f + cropPad.y()); - m_pos[1].assign(offset.x + imgSize.x(), 0.f, offset.y); - m_uv[1].assign(0.5f + cropPad.x(), 0.5f + cropPad.y()); + m_pos[1].assign(offset.x + imgSize.x(), 0.f, offset.y); + m_uv[1].assign(0.5f + cropPad.x(), 0.5f + cropPad.y()); - m_pos[2].assign(offset.x, 0.f, offset.y + imgSize.y()); - m_uv[2].assign(0.5f - cropPad.x(), 0.5f - cropPad.y()); + m_pos[2].assign(offset.x, 0.f, offset.y + imgSize.y()); + m_uv[2].assign(0.5f - cropPad.x(), 0.5f - cropPad.y()); - m_pos[3].assign(offset.x + imgSize.x(), 0.f, offset.y + imgSize.y()); - m_uv[3].assign(0.5f + cropPad.x(), 0.5f - cropPad.y()); + m_pos[3].assign(offset.x + imgSize.x(), 0.f, offset.y + imgSize.y()); + m_uv[3].assign(0.5f + cropPad.x(), 0.5f - cropPad.y()); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CTextSupportShader.hpp b/Runtime/Graphics/Shaders/CTextSupportShader.hpp index 3d2587f40..957ef6288 100644 --- a/Runtime/Graphics/Shaders/CTextSupportShader.hpp +++ b/Runtime/Graphics/Shaders/CTextSupportShader.hpp @@ -5,106 +5,88 @@ #include "hecl/UniformBufferPool.hpp" #include "zeus/CVector2i.hpp" -namespace urde -{ +namespace urde { class CGlyph; class CTextRenderBuffer; class CFontImageDef; -class CTextSupportShader -{ - friend class CTextRenderBuffer; +class CTextSupportShader { + friend class CTextRenderBuffer; - static boo::ObjToken s_TextAlphaPipeline; - static boo::ObjToken s_TextAddPipeline; - static boo::ObjToken s_TextAddOverdrawPipeline; + static boo::ObjToken s_TextAlphaPipeline; + static boo::ObjToken s_TextAddPipeline; + static boo::ObjToken s_TextAddOverdrawPipeline; - static boo::ObjToken s_ImageAlphaPipeline; - static boo::ObjToken s_ImageAddPipeline; - static boo::ObjToken s_ImageAddOverdrawPipeline; + static boo::ObjToken s_ImageAlphaPipeline; + static boo::ObjToken s_ImageAddPipeline; + static boo::ObjToken s_ImageAddOverdrawPipeline; - struct Uniform - { - zeus::CMatrix4f m_mvp; - zeus::CColor m_uniformColor; - }; + struct Uniform { + zeus::CMatrix4f m_mvp; + zeus::CColor m_uniformColor; + }; - struct CharacterInstance - { - zeus::CVector3f m_pos[4]; - zeus::CVector3f m_uv[4]; - zeus::CColor m_fontColor; - zeus::CColor m_outlineColor; - zeus::CColor m_mulColor; - void SetMetrics(const CGlyph& glyph, const zeus::CVector2i& offset); - }; + struct CharacterInstance { + zeus::CVector3f m_pos[4]; + zeus::CVector3f m_uv[4]; + zeus::CColor m_fontColor; + zeus::CColor m_outlineColor; + zeus::CColor m_mulColor; + void SetMetrics(const CGlyph& glyph, const zeus::CVector2i& offset); + }; - struct ImageInstance - { - zeus::CVector3f m_pos[4]; - zeus::CVector2f m_uv[4]; - zeus::CColor m_color; - void SetMetrics(const CFontImageDef& imgDef, const zeus::CVector2i& offset); - }; + struct ImageInstance { + zeus::CVector3f m_pos[4]; + zeus::CVector2f m_uv[4]; + zeus::CColor m_color; + void SetMetrics(const CFontImageDef& imgDef, const zeus::CVector2i& offset); + }; - static hecl::VertexBufferPool s_CharInsts; - static hecl::VertexBufferPool s_ImgInsts; - static hecl::UniformBufferPool s_Uniforms; + static hecl::VertexBufferPool s_CharInsts; + static hecl::VertexBufferPool s_ImgInsts; + static hecl::UniformBufferPool s_Uniforms; public: - - static boo::ObjToken SelectTextPipeline(CGuiWidget::EGuiModelDrawFlags df) - { - switch (df) - { - case CGuiWidget::EGuiModelDrawFlags::Shadeless: - case CGuiWidget::EGuiModelDrawFlags::Opaque: - case CGuiWidget::EGuiModelDrawFlags::Alpha: - case CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw: - return s_TextAlphaPipeline; - case CGuiWidget::EGuiModelDrawFlags::Additive: - return s_TextAddPipeline; - default: - return {}; - } + static boo::ObjToken SelectTextPipeline(CGuiWidget::EGuiModelDrawFlags df) { + switch (df) { + case CGuiWidget::EGuiModelDrawFlags::Shadeless: + case CGuiWidget::EGuiModelDrawFlags::Opaque: + case CGuiWidget::EGuiModelDrawFlags::Alpha: + case CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw: + return s_TextAlphaPipeline; + case CGuiWidget::EGuiModelDrawFlags::Additive: + return s_TextAddPipeline; + default: + return {}; } + } - static boo::ObjToken SelectImagePipeline(CGuiWidget::EGuiModelDrawFlags df) - { - switch (df) - { - case CGuiWidget::EGuiModelDrawFlags::Shadeless: - case CGuiWidget::EGuiModelDrawFlags::Opaque: - case CGuiWidget::EGuiModelDrawFlags::Alpha: - case CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw: - return s_ImageAlphaPipeline; - case CGuiWidget::EGuiModelDrawFlags::Additive: - return s_ImageAddPipeline; - default: - return {}; - } + static boo::ObjToken SelectImagePipeline(CGuiWidget::EGuiModelDrawFlags df) { + switch (df) { + case CGuiWidget::EGuiModelDrawFlags::Shadeless: + case CGuiWidget::EGuiModelDrawFlags::Opaque: + case CGuiWidget::EGuiModelDrawFlags::Alpha: + case CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw: + return s_ImageAlphaPipeline; + case CGuiWidget::EGuiModelDrawFlags::Additive: + return s_ImageAddPipeline; + default: + return {}; } + } - static boo::ObjToken GetTextAdditiveOverdrawPipeline() - { - return s_TextAddOverdrawPipeline; - } + static boo::ObjToken GetTextAdditiveOverdrawPipeline() { return s_TextAddOverdrawPipeline; } - static boo::ObjToken GetImageAdditiveOverdrawPipeline() - { - return s_ImageAddOverdrawPipeline; - } + static boo::ObjToken GetImageAdditiveOverdrawPipeline() { return s_ImageAddOverdrawPipeline; } - static void UpdateBuffers() - { - s_CharInsts.updateBuffers(); - s_ImgInsts.updateBuffers(); - s_Uniforms.updateBuffers(); - } + static void UpdateBuffers() { + s_CharInsts.updateBuffers(); + s_ImgInsts.updateBuffers(); + s_Uniforms.updateBuffers(); + } - static void Initialize(); - static void Shutdown(); + static void Initialize(); + static void Shutdown(); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CTexturedQuadFilter.cpp b/Runtime/Graphics/Shaders/CTexturedQuadFilter.cpp index 80defc734..035e57174 100644 --- a/Runtime/Graphics/Shaders/CTexturedQuadFilter.cpp +++ b/Runtime/Graphics/Shaders/CTexturedQuadFilter.cpp @@ -2,8 +2,7 @@ #include "Graphics/CTexture.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_AlphaPipeline; static boo::ObjToken s_AlphaGEqualPipeline; @@ -31,334 +30,290 @@ static boo::ObjToken s_ASubtractPipeline; static boo::ObjToken s_AMultPipeline; static boo::ObjToken s_AInvDstMultPipeline; -void CTexturedQuadFilter::Initialize() -{ - s_AlphaPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlpha{}); - s_AlphaGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaGEqual{}); - s_AlphaGEqualZWritePipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaGEqualZWrite{}); - s_AlphaLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaLEqual{}); - s_AddPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAdd{}); - s_AddGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAddGEqual{}); - s_AddGEqualZWritePipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAddGEqualZWrite{}); - s_AddLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAddLEqual{}); - s_SubtractPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterSubtract{}); - s_SubtractGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterSubtractGEqual{}); - s_SubtractGEqualZWritePipeline = hecl::conv->convert(Shader_CTexturedQuadFilterSubtractGEqualZWrite{}); - s_SubtractLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterSubtractLEqual{}); - s_MultPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterMult{}); - s_MultGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterMultGEqual{}); - s_MultGEqualZWritePipeline = hecl::conv->convert(Shader_CTexturedQuadFilterMultGEqualZWrite{}); - s_MultLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterMultLEqual{}); - s_InvDstMultPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterInvDstMult{}); - s_InvDstMultGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterInvDstMultGEqual{}); - s_InvDstMultLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterInvDstMultLEqual{}); +void CTexturedQuadFilter::Initialize() { + s_AlphaPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlpha{}); + s_AlphaGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaGEqual{}); + s_AlphaGEqualZWritePipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaGEqualZWrite{}); + s_AlphaLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaLEqual{}); + s_AddPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAdd{}); + s_AddGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAddGEqual{}); + s_AddGEqualZWritePipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAddGEqualZWrite{}); + s_AddLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAddLEqual{}); + s_SubtractPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterSubtract{}); + s_SubtractGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterSubtractGEqual{}); + s_SubtractGEqualZWritePipeline = hecl::conv->convert(Shader_CTexturedQuadFilterSubtractGEqualZWrite{}); + s_SubtractLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterSubtractLEqual{}); + s_MultPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterMult{}); + s_MultGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterMultGEqual{}); + s_MultGEqualZWritePipeline = hecl::conv->convert(Shader_CTexturedQuadFilterMultGEqualZWrite{}); + s_MultLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterMultLEqual{}); + s_InvDstMultPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterInvDstMult{}); + s_InvDstMultGEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterInvDstMultGEqual{}); + s_InvDstMultLEqualPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterInvDstMultLEqual{}); } -void CTexturedQuadFilter::Shutdown() -{ - s_AlphaPipeline.reset(); - s_AlphaGEqualPipeline.reset(); - s_AlphaGEqualZWritePipeline.reset(); - s_AlphaLEqualPipeline.reset(); - s_AddPipeline.reset(); - s_AddGEqualPipeline.reset(); - s_AddGEqualZWritePipeline.reset(); - s_AddLEqualPipeline.reset(); - s_SubtractPipeline.reset(); - s_SubtractGEqualPipeline.reset(); - s_SubtractGEqualZWritePipeline.reset(); - s_SubtractLEqualPipeline.reset(); - s_MultPipeline.reset(); - s_MultGEqualPipeline.reset(); - s_MultGEqualZWritePipeline.reset(); - s_MultLEqualPipeline.reset(); - s_InvDstMultPipeline.reset(); - s_InvDstMultGEqualPipeline.reset(); - s_InvDstMultLEqualPipeline.reset(); +void CTexturedQuadFilter::Shutdown() { + s_AlphaPipeline.reset(); + s_AlphaGEqualPipeline.reset(); + s_AlphaGEqualZWritePipeline.reset(); + s_AlphaLEqualPipeline.reset(); + s_AddPipeline.reset(); + s_AddGEqualPipeline.reset(); + s_AddGEqualZWritePipeline.reset(); + s_AddLEqualPipeline.reset(); + s_SubtractPipeline.reset(); + s_SubtractGEqualPipeline.reset(); + s_SubtractGEqualZWritePipeline.reset(); + s_SubtractLEqualPipeline.reset(); + s_MultPipeline.reset(); + s_MultGEqualPipeline.reset(); + s_MultGEqualZWritePipeline.reset(); + s_MultLEqualPipeline.reset(); + s_InvDstMultPipeline.reset(); + s_InvDstMultGEqualPipeline.reset(); + s_InvDstMultLEqualPipeline.reset(); } -void CTexturedQuadFilterAlpha::Initialize() -{ - s_AAlphaPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexAlpha{}); - s_AAddPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexAdd{}); - s_ASubtractPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexSubtract{}); - s_AMultPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexMult{}); - s_AInvDstMultPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexInvDstMult{}); +void CTexturedQuadFilterAlpha::Initialize() { + s_AAlphaPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexAlpha{}); + s_AAddPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexAdd{}); + s_ASubtractPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexSubtract{}); + s_AMultPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexMult{}); + s_AInvDstMultPipeline = hecl::conv->convert(Shader_CTexturedQuadFilterAlphaTexInvDstMult{}); } -void CTexturedQuadFilterAlpha::Shutdown() -{ - s_AAlphaPipeline.reset(); - s_AAddPipeline.reset(); - s_ASubtractPipeline.reset(); - s_AMultPipeline.reset(); - s_AInvDstMultPipeline.reset(); +void CTexturedQuadFilterAlpha::Shutdown() { + s_AAlphaPipeline.reset(); + s_AAddPipeline.reset(); + s_ASubtractPipeline.reset(); + s_AMultPipeline.reset(); + s_AInvDstMultPipeline.reset(); } -static boo::ObjToken SelectPipeline(EFilterType type, CTexturedQuadFilter::ZTest zTest) -{ - switch (zTest) - { - case CTexturedQuadFilter::ZTest::GEqual: - switch (type) - { - case EFilterType::Blend: - return s_AlphaGEqualPipeline; - case EFilterType::Add: - return s_AddGEqualPipeline; - case EFilterType::Subtract: - return s_SubtractGEqualPipeline; - case EFilterType::Multiply: - return s_MultGEqualPipeline; - default: - break; - } - break; - case CTexturedQuadFilter::ZTest::GEqualZWrite: - switch (type) - { - case EFilterType::Blend: - return s_AlphaGEqualZWritePipeline; - case EFilterType::Add: - return s_AddGEqualZWritePipeline; - case EFilterType::Subtract: - return s_SubtractGEqualZWritePipeline; - case EFilterType::Multiply: - return s_MultGEqualZWritePipeline; - default: - break; - } - break; - case CTexturedQuadFilter::ZTest::LEqual: - switch (type) - { - case EFilterType::Blend: - return s_AlphaLEqualPipeline; - case EFilterType::Add: - return s_AddLEqualPipeline; - case EFilterType::Subtract: - return s_SubtractLEqualPipeline; - case EFilterType::Multiply: - return s_MultLEqualPipeline; - case EFilterType::InvDstMultiply: - return s_InvDstMultLEqualPipeline; - default: - break; - } - break; - default: - break; - } - - switch (type) - { +static boo::ObjToken SelectPipeline(EFilterType type, CTexturedQuadFilter::ZTest zTest) { + switch (zTest) { + case CTexturedQuadFilter::ZTest::GEqual: + switch (type) { case EFilterType::Blend: - return s_AlphaPipeline; + return s_AlphaGEqualPipeline; case EFilterType::Add: - return s_AddPipeline; + return s_AddGEqualPipeline; case EFilterType::Subtract: - return s_SubtractPipeline; + return s_SubtractGEqualPipeline; case EFilterType::Multiply: - return s_MultPipeline; - case EFilterType::InvDstMultiply: - return s_InvDstMultPipeline; + return s_MultGEqualPipeline; default: - return {}; + break; } -} - -static boo::ObjToken SelectAlphaPipeline(EFilterType type) -{ - switch (type) - { + break; + case CTexturedQuadFilter::ZTest::GEqualZWrite: + switch (type) { case EFilterType::Blend: - return s_AAlphaPipeline; + return s_AlphaGEqualZWritePipeline; case EFilterType::Add: - return s_AAddPipeline; + return s_AddGEqualZWritePipeline; case EFilterType::Subtract: - return s_ASubtractPipeline; + return s_SubtractGEqualZWritePipeline; case EFilterType::Multiply: - return s_AMultPipeline; - case EFilterType::InvDstMultiply: - return s_AInvDstMultPipeline; + return s_MultGEqualZWritePipeline; default: - return {}; + break; } + break; + case CTexturedQuadFilter::ZTest::LEqual: + switch (type) { + case EFilterType::Blend: + return s_AlphaLEqualPipeline; + case EFilterType::Add: + return s_AddLEqualPipeline; + case EFilterType::Subtract: + return s_SubtractLEqualPipeline; + case EFilterType::Multiply: + return s_MultLEqualPipeline; + case EFilterType::InvDstMultiply: + return s_InvDstMultLEqualPipeline; + default: + break; + } + break; + default: + break; + } + + switch (type) { + case EFilterType::Blend: + return s_AlphaPipeline; + case EFilterType::Add: + return s_AddPipeline; + case EFilterType::Subtract: + return s_SubtractPipeline; + case EFilterType::Multiply: + return s_MultPipeline; + case EFilterType::InvDstMultiply: + return s_InvDstMultPipeline; + default: + return {}; + } } -CTexturedQuadFilter::CTexturedQuadFilter(const boo::ObjToken& tex) -: m_booTex(tex) -{ - m_flipRect = CGraphics::g_BooFactory->platform() == boo::IGraphicsDataFactory::Platform::Vulkan; +static boo::ObjToken SelectAlphaPipeline(EFilterType type) { + switch (type) { + case EFilterType::Blend: + return s_AAlphaPipeline; + case EFilterType::Add: + return s_AAddPipeline; + case EFilterType::Subtract: + return s_ASubtractPipeline; + case EFilterType::Multiply: + return s_AMultPipeline; + case EFilterType::InvDstMultiply: + return s_AInvDstMultPipeline; + default: + return {}; + } +} + +CTexturedQuadFilter::CTexturedQuadFilter(const boo::ObjToken& tex) : m_booTex(tex) { + m_flipRect = CGraphics::g_BooFactory->platform() == boo::IGraphicsDataFactory::Platform::Vulkan; } CTexturedQuadFilter::CTexturedQuadFilter(EFilterType type, const boo::ObjToken& tex, ZTest ztest) -: m_booTex(tex), m_zTest(ztest) -{ - m_flipRect = CGraphics::g_BooFactory->platform() == boo::IGraphicsDataFactory::Platform::Vulkan; - tex->setClampMode(boo::TextureClampMode::ClampToEdge); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 32, 16); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {m_booTex.get()}; - m_dataBind = ctx.newShaderDataBinding(SelectPipeline(type, m_zTest), m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 1, texs, nullptr, nullptr); - return true; - } BooTrace); +: m_booTex(tex), m_zTest(ztest) { + m_flipRect = CGraphics::g_BooFactory->platform() == boo::IGraphicsDataFactory::Platform::Vulkan; + tex->setClampMode(boo::TextureClampMode::ClampToEdge); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 32, 16); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {m_booTex.get()}; + m_dataBind = ctx.newShaderDataBinding(SelectPipeline(type, m_zTest), m_vbo.get(), nullptr, nullptr, 1, bufs, stages, + nullptr, nullptr, 1, texs, nullptr, nullptr); + return true; + } BooTrace); } -CTexturedQuadFilter::CTexturedQuadFilter(EFilterType type, - TLockedToken tex, ZTest ztest) -: CTexturedQuadFilter(type, (tex ? tex->GetBooTexture() : nullptr), ztest) -{ - m_flipRect = CGraphics::g_BooFactory->platform() == boo::IGraphicsDataFactory::Platform::Vulkan; - m_tex = tex; +CTexturedQuadFilter::CTexturedQuadFilter(EFilterType type, TLockedToken tex, ZTest ztest) +: CTexturedQuadFilter(type, (tex ? tex->GetBooTexture() : nullptr), ztest) { + m_flipRect = CGraphics::g_BooFactory->platform() == boo::IGraphicsDataFactory::Platform::Vulkan; + m_tex = tex; } -void CTexturedQuadFilter::draw(const zeus::CColor& color, float uvScale, const zeus::CRectangle& rect, float z) -{ - Vert verts[4] = - { - {{0.f, 0.f, z}, {0.f, 0.f}}, - {{0.f, 1.f, z}, {0.f, uvScale}}, - {{1.f, 0.f, z}, {uvScale, 0.f}}, - {{1.f, 1.f, z}, {uvScale, uvScale}}, +void CTexturedQuadFilter::draw(const zeus::CColor& color, float uvScale, const zeus::CRectangle& rect, float z) { + Vert verts[4] = { + {{0.f, 0.f, z}, {0.f, 0.f}}, + {{0.f, 1.f, z}, {0.f, uvScale}}, + {{1.f, 0.f, z}, {uvScale, 0.f}}, + {{1.f, 1.f, z}, {uvScale, uvScale}}, + }; + m_vbo->load(verts, sizeof(verts)); + + if (!m_flipRect) { + m_uniform.m_matrix[0][0] = rect.size.x() * 2.f; + m_uniform.m_matrix[1][1] = rect.size.y() * 2.f; + m_uniform.m_matrix[3][0] = rect.position.x() * 2.f - 1.f; + m_uniform.m_matrix[3][1] = rect.position.y() * 2.f - 1.f; + } else { + m_uniform.m_matrix[0][0] = rect.size.x() * 2.f; + m_uniform.m_matrix[1][1] = rect.size.y() * -2.f; + m_uniform.m_matrix[3][0] = rect.position.x() * 2.f - 1.f; + m_uniform.m_matrix[3][1] = rect.position.y() * -2.f + 1.f; + } + m_uniform.m_color = color; + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); +} + +void CTexturedQuadFilter::drawCropped(const zeus::CColor& color, float uvScale) { + float xFac = CGraphics::g_CroppedViewport.xc_width / float(g_Viewport.x8_width); + float yFac = CGraphics::g_CroppedViewport.x10_height / float(g_Viewport.xc_height); + float xBias = CGraphics::g_CroppedViewport.x4_left / float(g_Viewport.x8_width); + float yBias = CGraphics::g_CroppedViewport.x8_top / float(g_Viewport.xc_height); + + Vert verts[4] = { + {{-1.0, -1.0, 0.f}, {xBias * uvScale, yBias * uvScale}}, + {{-1.0, 1.0, 0.f}, {xBias * uvScale, (yBias + yFac) * uvScale}}, + {{1.0, -1.0, 0.f}, {(xBias + xFac) * uvScale, yBias * uvScale}}, + {{1.0, 1.0, 0.f}, {(xBias + xFac) * uvScale, (yBias + yFac) * uvScale}}, + }; + m_vbo->load(verts, sizeof(verts)); + + m_uniform.m_color = color; + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); +} + +void CTexturedQuadFilter::drawVerts(const zeus::CColor& color, const Vert verts[4], float lod) { + m_vbo->load(verts, sizeof(Vert) * 4); + + m_uniform.m_matrix = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); + m_uniform.m_color = color; + m_uniform.m_lod = lod; + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); +} + +void CTexturedQuadFilter::DrawFilter(EFilterShape shape, const zeus::CColor& color, float t) { + m_uniform.m_matrix = zeus::CMatrix4f::skIdentityMatrix4f; + m_uniform.m_lod = 0.f; + m_uniform.m_color = color; + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + + CGraphics::SetShaderDataBinding(m_dataBind); + + if (shape == EFilterShape::FullscreenQuarters) { + Vert QuadVerts[] = { + {{-1.f, -1.f, 0.f}, {t, t}}, // ll + {{-1.f, 0.f, 0.f}, {t, 0.f}}, {{0.f, -1.f, 0.f}, {0.f, t}}, {{0.f, 0.f, 0.f}, {0.f, 0.f}}, + {{-1.f, 1.f, 0.f}, {t, t}}, // ul + {{-1.f, 0.f, 0.f}, {t, 0.f}}, {{0.f, 1.f, 0.f}, {0.f, t}}, {{0.f, 0.f, 0.f}, {0.f, 0.f}}, + {{1.f, -1.f, 0.f}, {t, t}}, // lr + {{1.f, 0.f, 0.f}, {t, 0.f}}, {{0.f, -1.f, 0.f}, {0.f, t}}, {{0.f, 0.f, 0.f}, {0.f, 0.f}}, + {{1.f, 1.f, 0.f}, {t, t}}, // ur + {{1.f, 0.f, 0.f}, {t, 0.f}}, {{0.f, 1.f, 0.f}, {0.f, t}}, {{0.f, 0.f, 0.f}, {0.f, 0.f}}, }; - m_vbo->load(verts, sizeof(verts)); - - if (!m_flipRect) - { - m_uniform.m_matrix[0][0] = rect.size.x() * 2.f; - m_uniform.m_matrix[1][1] = rect.size.y() * 2.f; - m_uniform.m_matrix[3][0] = rect.position.x() * 2.f - 1.f; - m_uniform.m_matrix[3][1] = rect.position.y() * 2.f - 1.f; - } - else - { - m_uniform.m_matrix[0][0] = rect.size.x() * 2.f; - m_uniform.m_matrix[1][1] = rect.size.y() * -2.f; - m_uniform.m_matrix[3][0] = rect.position.x() * 2.f - 1.f; - m_uniform.m_matrix[3][1] = rect.position.y() * -2.f + 1.f; - } - m_uniform.m_color = color; - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - - CGraphics::SetShaderDataBinding(m_dataBind); + m_vbo->load(QuadVerts, sizeof(Vert) * 16); CGraphics::DrawArray(0, 4); -} - -void CTexturedQuadFilter::drawCropped(const zeus::CColor& color, float uvScale) -{ - float xFac = CGraphics::g_CroppedViewport.xc_width / float(g_Viewport.x8_width); - float yFac = CGraphics::g_CroppedViewport.x10_height / float(g_Viewport.xc_height); - float xBias = CGraphics::g_CroppedViewport.x4_left / float(g_Viewport.x8_width); - float yBias = CGraphics::g_CroppedViewport.x8_top / float(g_Viewport.xc_height); - - Vert verts[4] = - { - {{-1.0, -1.0, 0.f}, {xBias * uvScale, yBias * uvScale}}, - {{-1.0, 1.0, 0.f}, {xBias * uvScale, (yBias + yFac) * uvScale}}, - {{ 1.0, -1.0, 0.f}, {(xBias + xFac) * uvScale, yBias * uvScale}}, - {{ 1.0, 1.0, 0.f}, {(xBias + xFac) * uvScale, (yBias + yFac) * uvScale}}, + CGraphics::DrawArray(4, 4); + CGraphics::DrawArray(8, 4); + CGraphics::DrawArray(12, 4); + } else { + Vert FullscreenVerts[] = { + {{-1.f, -1.f, 0.f}, {0.f, 0.f}}, + {{-1.f, 1.f, 0.f}, {0.f, t}}, + {{1.f, -1.f, 0.f}, {t, 0.f}}, + {{1.f, 1.f, 0.f}, {t, t}}, }; - m_vbo->load(verts, sizeof(verts)); - - m_uniform.m_color = color; - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - - CGraphics::SetShaderDataBinding(m_dataBind); + m_vbo->load(FullscreenVerts, sizeof(Vert) * 4); CGraphics::DrawArray(0, 4); -} - -void CTexturedQuadFilter::drawVerts(const zeus::CColor& color, const Vert verts[4], float lod) -{ - m_vbo->load(verts, sizeof(Vert) * 4); - - m_uniform.m_matrix = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); - m_uniform.m_color = color; - m_uniform.m_lod = lod; - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); -} - -void CTexturedQuadFilter::DrawFilter(EFilterShape shape, const zeus::CColor& color, float t) -{ - m_uniform.m_matrix = zeus::CMatrix4f::skIdentityMatrix4f; - m_uniform.m_lod = 0.f; - m_uniform.m_color = color; - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - - CGraphics::SetShaderDataBinding(m_dataBind); - - if (shape == EFilterShape::FullscreenQuarters) - { - Vert QuadVerts[] = - { - {{-1.f, -1.f, 0.f}, {t, t}}, // ll - {{-1.f, 0.f, 0.f}, {t, 0.f}}, - {{ 0.f, -1.f, 0.f}, {0.f, t}}, - {{ 0.f, 0.f, 0.f}, {0.f, 0.f}}, - {{-1.f, 1.f, 0.f}, {t, t}}, // ul - {{-1.f, 0.f, 0.f}, {t, 0.f}}, - {{ 0.f, 1.f, 0.f}, {0.f, t}}, - {{ 0.f, 0.f, 0.f}, {0.f, 0.f}}, - {{ 1.f, -1.f, 0.f}, {t, t}}, // lr - {{ 1.f, 0.f, 0.f}, {t, 0.f}}, - {{ 0.f, -1.f, 0.f}, {0.f, t}}, - {{ 0.f, 0.f, 0.f}, {0.f, 0.f}}, - {{ 1.f, 1.f, 0.f}, {t, t}}, // ur - {{ 1.f, 0.f, 0.f}, {t, 0.f}}, - {{ 0.f, 1.f, 0.f}, {0.f, t}}, - {{ 0.f, 0.f, 0.f}, {0.f, 0.f}}, - }; - m_vbo->load(QuadVerts, sizeof(Vert) * 16); - CGraphics::DrawArray(0, 4); - CGraphics::DrawArray(4, 4); - CGraphics::DrawArray(8, 4); - CGraphics::DrawArray(12, 4); - } - else - { - Vert FullscreenVerts[] = - { - {{-1.f, -1.f, 0.f}, {0.f, 0.f}}, - {{-1.f, 1.f, 0.f}, {0.f, t}}, - {{ 1.f, -1.f, 0.f}, {t, 0.f}}, - {{ 1.f, 1.f, 0.f}, {t, t}}, - }; - m_vbo->load(FullscreenVerts, sizeof(Vert) * 4); - CGraphics::DrawArray(0, 4); - } + } } const zeus::CRectangle CTexturedQuadFilter::DefaultRect = {0.f, 0.f, 1.f, 1.f}; CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, const boo::ObjToken& tex) -: CTexturedQuadFilter(tex) -{ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 32, 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {m_booTex.get()}; - m_dataBind = ctx.newShaderDataBinding(SelectAlphaPipeline(type), m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 1, texs, nullptr, nullptr); - return true; - } BooTrace); +: CTexturedQuadFilter(tex) { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 32, 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {m_booTex.get()}; + m_dataBind = ctx.newShaderDataBinding(SelectAlphaPipeline(type), m_vbo.get(), nullptr, nullptr, 1, bufs, stages, + nullptr, nullptr, 1, texs, nullptr, nullptr); + return true; + } BooTrace); } -CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, - TLockedToken tex) -: CTexturedQuadFilterAlpha(type, (tex ? tex->GetBooTexture() : nullptr)) -{ - m_tex = tex; +CTexturedQuadFilterAlpha::CTexturedQuadFilterAlpha(EFilterType type, TLockedToken tex) +: CTexturedQuadFilterAlpha(type, (tex ? tex->GetBooTexture() : nullptr)) { + m_tex = tex; } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp b/Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp index 953c22d89..04d5ea7ed 100644 --- a/Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp +++ b/Runtime/Graphics/Shaders/CTexturedQuadFilter.hpp @@ -6,69 +6,57 @@ #include "Camera/CCameraFilter.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { -class CTexturedQuadFilter -{ +class CTexturedQuadFilter { public: - enum class ZTest - { - None, - LEqual, - GEqual, - GEqualZWrite - }; + enum class ZTest { None, LEqual, GEqual, GEqualZWrite }; protected: - struct Uniform - { - zeus::CMatrix4f m_matrix; - zeus::CColor m_color; - float m_lod = 0.f; - }; - TLockedToken m_tex; - boo::ObjToken m_booTex; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; - ZTest m_zTest; - bool m_flipRect = false; + struct Uniform { + zeus::CMatrix4f m_matrix; + zeus::CColor m_color; + float m_lod = 0.f; + }; + TLockedToken m_tex; + boo::ObjToken m_booTex; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; + ZTest m_zTest; + bool m_flipRect = false; - CTexturedQuadFilter(const boo::ObjToken& tex); + CTexturedQuadFilter(const boo::ObjToken& tex); public: - struct Vert - { - zeus::CVector3f m_pos; - zeus::CVector2f m_uv; - }; - static void Initialize(); - static void Shutdown(); - static const zeus::CRectangle DefaultRect; - CTexturedQuadFilter(EFilterType type, TLockedToken tex, ZTest zTest = ZTest::None); - CTexturedQuadFilter(EFilterType type, const boo::ObjToken& tex, ZTest zTest = ZTest::None); - CTexturedQuadFilter(const CTexturedQuadFilter&) = delete; - CTexturedQuadFilter& operator=(const CTexturedQuadFilter&) = delete; - CTexturedQuadFilter(CTexturedQuadFilter&&) = default; - CTexturedQuadFilter& operator=(CTexturedQuadFilter&&) = default; - void draw(const zeus::CColor& color, float uvScale, const zeus::CRectangle& rect=DefaultRect, float z=0.f); - void drawCropped(const zeus::CColor& color, float uvScale); - void drawVerts(const zeus::CColor& color, const Vert verts[4], float lod=0.f); - void DrawFilter(EFilterShape shape, const zeus::CColor& color, float t); - const TLockedToken& GetTex() const { return m_tex; } - const boo::ObjToken& GetBooTex() const { return m_booTex; } + struct Vert { + zeus::CVector3f m_pos; + zeus::CVector2f m_uv; + }; + static void Initialize(); + static void Shutdown(); + static const zeus::CRectangle DefaultRect; + CTexturedQuadFilter(EFilterType type, TLockedToken tex, ZTest zTest = ZTest::None); + CTexturedQuadFilter(EFilterType type, const boo::ObjToken& tex, ZTest zTest = ZTest::None); + CTexturedQuadFilter(const CTexturedQuadFilter&) = delete; + CTexturedQuadFilter& operator=(const CTexturedQuadFilter&) = delete; + CTexturedQuadFilter(CTexturedQuadFilter&&) = default; + CTexturedQuadFilter& operator=(CTexturedQuadFilter&&) = default; + void draw(const zeus::CColor& color, float uvScale, const zeus::CRectangle& rect = DefaultRect, float z = 0.f); + void drawCropped(const zeus::CColor& color, float uvScale); + void drawVerts(const zeus::CColor& color, const Vert verts[4], float lod = 0.f); + void DrawFilter(EFilterShape shape, const zeus::CColor& color, float t); + const TLockedToken& GetTex() const { return m_tex; } + const boo::ObjToken& GetBooTex() const { return m_booTex; } }; -class CTexturedQuadFilterAlpha : public CTexturedQuadFilter -{ +class CTexturedQuadFilterAlpha : public CTexturedQuadFilter { public: - static void Initialize(); - static void Shutdown(); - CTexturedQuadFilterAlpha(EFilterType type, TLockedToken tex); - CTexturedQuadFilterAlpha(EFilterType type, const boo::ObjToken& tex); + static void Initialize(); + static void Shutdown(); + CTexturedQuadFilterAlpha(EFilterType type, TLockedToken tex); + CTexturedQuadFilterAlpha(EFilterType type, const boo::ObjToken& tex); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CThermalColdFilter.cpp b/Runtime/Graphics/Shaders/CThermalColdFilter.cpp index bf0a93f8b..ee4c41060 100644 --- a/Runtime/Graphics/Shaders/CThermalColdFilter.cpp +++ b/Runtime/Graphics/Shaders/CThermalColdFilter.cpp @@ -2,85 +2,70 @@ #include "Graphics/CGraphics.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; -void CThermalColdFilter::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CThermalColdFilter{}); -} +void CThermalColdFilter::Initialize() { s_Pipeline = hecl::conv->convert(Shader_CThermalColdFilter{}); } -void CThermalColdFilter::Shutdown() -{ - s_Pipeline.reset(); -} +void CThermalColdFilter::Shutdown() { s_Pipeline.reset(); } -CThermalColdFilter::CThermalColdFilter() -{ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_shiftTex = ctx.newDynamicTexture(8, 4, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat); +CThermalColdFilter::CThermalColdFilter() { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_shiftTex = ctx.newDynamicTexture(8, 4, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat); - struct Vert - { - zeus::CVector2f m_pos; - zeus::CVector2f m_uv; - } verts[4] = - { + struct Vert { + zeus::CVector2f m_pos; + zeus::CVector2f m_uv; + } verts[4] = { {{-1.f, -1.f}, {0.f, 0.f}}, - {{-1.f, 1.f}, {0.f, 1.f}}, - {{ 1.f, -1.f}, {1.f, 0.f}}, - {{ 1.f, 1.f}, {1.f, 1.f}}, - }; - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, 32, 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get(), m_shiftTex.get()}; - m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 2, texs, nullptr, nullptr); - return true; - } BooTrace); + {{-1.f, 1.f}, {0.f, 1.f}}, + {{1.f, -1.f}, {1.f, 0.f}}, + {{1.f, 1.f}, {1.f, 1.f}}, + }; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, 32, 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get(), m_shiftTex.get()}; + m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, nullptr, + 2, texs, nullptr, nullptr); + return true; + } BooTrace); - setShift(0); - setScale(0.f); + setShift(0); + setScale(0.f); } -void CThermalColdFilter::setShift(unsigned shift) -{ - shift = std::min(shift, 31u); - for (unsigned y=0 ; y<4 ; ++y) - { - unsigned bx = y * 8; - for (unsigned x=0 ; x<8 ; ++x) - { - unsigned px = bx + x; - unsigned spx = px + shift; - unsigned ny = spx / 8; - if (ny > 3) - ny = 3; - unsigned nx = spx % 8; - m_shiftTexture[y][x][0] = u8(nx * 255 / 7); - m_shiftTexture[y][x][1] = u8(ny * 255 / 3); - } +void CThermalColdFilter::setShift(unsigned shift) { + shift = std::min(shift, 31u); + for (unsigned y = 0; y < 4; ++y) { + unsigned bx = y * 8; + for (unsigned x = 0; x < 8; ++x) { + unsigned px = bx + x; + unsigned spx = px + shift; + unsigned ny = spx / 8; + if (ny > 3) + ny = 3; + unsigned nx = spx % 8; + m_shiftTexture[y][x][0] = u8(nx * 255 / 7); + m_shiftTexture[y][x][1] = u8(ny * 255 / 3); } - m_shiftTex->load(m_shiftTexture[0][0], sizeof(m_shiftTexture)); + } + m_shiftTex->load(m_shiftTexture[0][0], sizeof(m_shiftTexture)); } -void CThermalColdFilter::draw() -{ - CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport); +void CThermalColdFilter::draw() { + CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport); - m_uniform.m_shiftTexMtx[0][0] = 80.f * (CGraphics::g_ProjAspect / 1.33f); - m_uniform.m_shiftTexMtx[1][1] = 120.f; - m_uniform.m_shiftTexScale[0] = 1.f / m_uniform.m_shiftTexMtx[0][0]; - m_uniform.m_shiftTexScale[1] = 1.f / m_uniform.m_shiftTexMtx[1][1]; - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + m_uniform.m_shiftTexMtx[0][0] = 80.f * (CGraphics::g_ProjAspect / 1.33f); + m_uniform.m_shiftTexMtx[1][1] = 120.f; + m_uniform.m_shiftTexScale[0] = 1.f / m_uniform.m_shiftTexMtx[0][0]; + m_uniform.m_shiftTexScale[1] = 1.f / m_uniform.m_shiftTexMtx[1][1]; + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CThermalColdFilter.hpp b/Runtime/Graphics/Shaders/CThermalColdFilter.hpp index d617f42cf..f8d3fdac9 100644 --- a/Runtime/Graphics/Shaders/CThermalColdFilter.hpp +++ b/Runtime/Graphics/Shaders/CThermalColdFilter.hpp @@ -5,41 +5,36 @@ #include "zeus/CColor.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { -class CThermalColdFilter -{ - struct Uniform - { - zeus::CMatrix4f m_shiftTexMtx; - zeus::CMatrix4f m_indMtx; - zeus::CVector2f m_shiftTexScale; - zeus::CColor m_colorRegs[3]; - }; - u8 m_shiftTexture[4][8][4] = {}; - boo::ObjToken m_shiftTex; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; +class CThermalColdFilter { + struct Uniform { + zeus::CMatrix4f m_shiftTexMtx; + zeus::CMatrix4f m_indMtx; + zeus::CVector2f m_shiftTexScale; + zeus::CColor m_colorRegs[3]; + }; + u8 m_shiftTexture[4][8][4] = {}; + boo::ObjToken m_shiftTex; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; public: - static void Initialize(); - static void Shutdown(); - CThermalColdFilter(); - void setShift(unsigned shift); - void setColorA(const zeus::CColor& color) {m_uniform.m_colorRegs[0] = color;} - void setColorB(const zeus::CColor& color) {m_uniform.m_colorRegs[1] = color;} - void setColorC(const zeus::CColor& color) {m_uniform.m_colorRegs[2] = color;} - void setScale(float scale) - { - scale = 0.025f * (1.f - scale); - m_uniform.m_indMtx[0][0] = scale; - m_uniform.m_indMtx[1][1] = scale; - } - void draw(); + static void Initialize(); + static void Shutdown(); + CThermalColdFilter(); + void setShift(unsigned shift); + void setColorA(const zeus::CColor& color) { m_uniform.m_colorRegs[0] = color; } + void setColorB(const zeus::CColor& color) { m_uniform.m_colorRegs[1] = color; } + void setColorC(const zeus::CColor& color) { m_uniform.m_colorRegs[2] = color; } + void setScale(float scale) { + scale = 0.025f * (1.f - scale); + m_uniform.m_indMtx[0][0] = scale; + m_uniform.m_indMtx[1][1] = scale; + } + void draw(); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CThermalHotFilter.cpp b/Runtime/Graphics/Shaders/CThermalHotFilter.cpp index 49acb4c8e..8cd703fde 100644 --- a/Runtime/Graphics/Shaders/CThermalHotFilter.cpp +++ b/Runtime/Graphics/Shaders/CThermalHotFilter.cpp @@ -4,55 +4,43 @@ #include "GameGlobalObjects.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; -void CThermalHotFilter::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CThermalHotFilter{}); -} +void CThermalHotFilter::Initialize() { s_Pipeline = hecl::conv->convert(Shader_CThermalHotFilter{}); } -void CThermalHotFilter::Shutdown() -{ - s_Pipeline.reset(); -} +void CThermalHotFilter::Shutdown() { s_Pipeline.reset(); } -CThermalHotFilter::CThermalHotFilter() -{ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - struct Vert - { - zeus::CVector2f m_pos; - zeus::CVector2f m_uv; - } verts[4] = - { +CThermalHotFilter::CThermalHotFilter() { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + struct Vert { + zeus::CVector2f m_pos; + zeus::CVector2f m_uv; + } verts[4] = { {{-1.0, -1.0}, {0.0, 0.0}}, - {{-1.0, 1.0}, {0.0, 1.0}}, - {{ 1.0, -1.0}, {1.0, 0.0}}, - {{ 1.0, 1.0}, {1.0, 1.0}}, - }; - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, 32, 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get(), g_Renderer->GetThermoPalette()}; - m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 2, texs, nullptr, nullptr); - return true; - } BooTrace); + {{-1.0, 1.0}, {0.0, 1.0}}, + {{1.0, -1.0}, {1.0, 0.0}}, + {{1.0, 1.0}, {1.0, 1.0}}, + }; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, 32, 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get(), g_Renderer->GetThermoPalette()}; + m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, nullptr, + 2, texs, nullptr, nullptr); + return true; + } BooTrace); } -void CThermalHotFilter::draw() -{ - CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport); +void CThermalHotFilter::draw() { + CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport); - //m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + // m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CThermalHotFilter.hpp b/Runtime/Graphics/Shaders/CThermalHotFilter.hpp index c57468bcf..dee1b7228 100644 --- a/Runtime/Graphics/Shaders/CThermalHotFilter.hpp +++ b/Runtime/Graphics/Shaders/CThermalHotFilter.hpp @@ -4,29 +4,25 @@ #include "zeus/CColor.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { -class CThermalHotFilter -{ - struct Uniform - { - zeus::CColor m_colorRegs[3]; - }; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; +class CThermalHotFilter { + struct Uniform { + zeus::CColor m_colorRegs[3]; + }; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; public: - static void Initialize(); - static void Shutdown(); - CThermalHotFilter(); - void setColorA(const zeus::CColor& color) {m_uniform.m_colorRegs[0] = color;} - void setColorB(const zeus::CColor& color) {m_uniform.m_colorRegs[1] = color;} - void setColorC(const zeus::CColor& color) {m_uniform.m_colorRegs[2] = color;} - void draw(); + static void Initialize(); + static void Shutdown(); + CThermalHotFilter(); + void setColorA(const zeus::CColor& color) { m_uniform.m_colorRegs[0] = color; } + void setColorB(const zeus::CColor& color) { m_uniform.m_colorRegs[1] = color; } + void setColorC(const zeus::CColor& color) { m_uniform.m_colorRegs[2] = color; } + void draw(); }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CWorldShadowShader.cpp b/Runtime/Graphics/Shaders/CWorldShadowShader.cpp index 3d2a5c986..0c7416e2c 100644 --- a/Runtime/Graphics/Shaders/CWorldShadowShader.cpp +++ b/Runtime/Graphics/Shaders/CWorldShadowShader.cpp @@ -2,82 +2,69 @@ #include "hecl/Pipeline.hpp" #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; static boo::ObjToken s_ZPipeline; -void CWorldShadowShader::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CWorldShadowShader{}); - s_ZPipeline = hecl::conv->convert(Shader_CWorldShadowShaderZ{}); +void CWorldShadowShader::Initialize() { + s_Pipeline = hecl::conv->convert(Shader_CWorldShadowShader{}); + s_ZPipeline = hecl::conv->convert(Shader_CWorldShadowShaderZ{}); } -void CWorldShadowShader::Shutdown() -{ - s_Pipeline.reset(); - s_ZPipeline.reset(); +void CWorldShadowShader::Shutdown() { + s_Pipeline.reset(); + s_ZPipeline.reset(); } -CWorldShadowShader::CWorldShadowShader(u32 w, u32 h) -: m_w(w), m_h(h) -{ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 16, 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 0, nullptr, nullptr, nullptr); - m_zDataBind = ctx.newShaderDataBinding(s_ZPipeline, m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 0, nullptr, nullptr, nullptr); - m_tex = ctx.newRenderTexture(m_w, m_h, boo::TextureClampMode::ClampToWhite, 1, 0); - return true; - } BooTrace); +CWorldShadowShader::CWorldShadowShader(u32 w, u32 h) : m_w(w), m_h(h) { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, 16, 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, nullptr, + 0, nullptr, nullptr, nullptr); + m_zDataBind = ctx.newShaderDataBinding(s_ZPipeline, m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, + nullptr, 0, nullptr, nullptr, nullptr); + m_tex = ctx.newRenderTexture(m_w, m_h, boo::TextureClampMode::ClampToWhite, 1, 0); + return true; + } BooTrace); } -void CWorldShadowShader::bindRenderTarget() -{ - CGraphics::g_BooMainCommandQueue->setRenderTarget(m_tex); +void CWorldShadowShader::bindRenderTarget() { CGraphics::g_BooMainCommandQueue->setRenderTarget(m_tex); } + +void CWorldShadowShader::drawBase(float extent) { + zeus::CVector3f verts[] = { + {-extent, 0.f, extent}, {extent, 0.f, extent}, {-extent, 0.f, -extent}, {extent, 0.f, -extent}}; + m_vbo->load(verts, sizeof(zeus::CVector3f) * 4); + + m_uniform.m_matrix = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); + m_uniform.m_color = zeus::CColor::skWhite; + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + + CGraphics::SetShaderDataBinding(m_zDataBind); + CGraphics::DrawArray(0, 4); } -void CWorldShadowShader::drawBase(float extent) -{ - zeus::CVector3f verts[] = {{-extent, 0.f, extent}, {extent, 0.f, extent}, - {-extent, 0.f, -extent}, {extent, 0.f, -extent}}; - m_vbo->load(verts, sizeof(zeus::CVector3f) * 4); +void CWorldShadowShader::lightenShadow() { + m_uniform.m_color = zeus::CColor(1.f, 0.25f); + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - m_uniform.m_matrix = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); - m_uniform.m_color = zeus::CColor::skWhite; - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - - CGraphics::SetShaderDataBinding(m_zDataBind); - CGraphics::DrawArray(0, 4); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); } -void CWorldShadowShader::lightenShadow() -{ - m_uniform.m_color = zeus::CColor(1.f, 0.25f); - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); +void CWorldShadowShader::blendPreviousShadow() { + if (!m_prevQuad) + m_prevQuad.emplace(EFilterType::Blend, m_tex.get()); + zeus::CRectangle rect(0.f, 1.f, 1.f, -1.f); + m_prevQuad->draw({1.f, 0.85f}, 1.f, rect); } -void CWorldShadowShader::blendPreviousShadow() -{ - if (!m_prevQuad) - m_prevQuad.emplace(EFilterType::Blend, m_tex.get()); - zeus::CRectangle rect(0.f, 1.f, 1.f, -1.f); - m_prevQuad->draw({1.f, 0.85f}, 1.f, rect); +void CWorldShadowShader::resolveTexture() { + boo::SWindowRect rect = {0, 0, int(m_w), int(m_h)}; + CGraphics::g_BooMainCommandQueue->resolveBindTexture(m_tex, rect, false, 0, true, false, true); } -void CWorldShadowShader::resolveTexture() -{ - boo::SWindowRect rect = {0, 0, int(m_w), int(m_h)}; - CGraphics::g_BooMainCommandQueue->resolveBindTexture(m_tex, rect, false, 0, true, false, true); -} - -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CWorldShadowShader.hpp b/Runtime/Graphics/Shaders/CWorldShadowShader.hpp index 56b95dc0e..d5dd67d54 100644 --- a/Runtime/Graphics/Shaders/CWorldShadowShader.hpp +++ b/Runtime/Graphics/Shaders/CWorldShadowShader.hpp @@ -3,41 +3,37 @@ #include "CColoredQuadFilter.hpp" #include "CTexturedQuadFilter.hpp" -namespace urde -{ +namespace urde { -class CWorldShadowShader -{ - boo::ObjToken m_tex; - std::experimental::optional m_prevQuad; - u32 m_w, m_h; +class CWorldShadowShader { + boo::ObjToken m_tex; + std::experimental::optional m_prevQuad; + u32 m_w, m_h; - struct Uniform - { - zeus::CMatrix4f m_matrix; - zeus::CColor m_color; - }; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - boo::ObjToken m_zDataBind; - Uniform m_uniform; + struct Uniform { + zeus::CMatrix4f m_matrix; + zeus::CColor m_color; + }; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + boo::ObjToken m_zDataBind; + Uniform m_uniform; public: - static void Initialize(); - static void Shutdown(); - CWorldShadowShader(u32 w, u32 h); - void bindRenderTarget(); - void drawBase(float extent); - void lightenShadow(); - void blendPreviousShadow(); - void resolveTexture(); + static void Initialize(); + static void Shutdown(); + CWorldShadowShader(u32 w, u32 h); + void bindRenderTarget(); + void drawBase(float extent); + void lightenShadow(); + void blendPreviousShadow(); + void resolveTexture(); - u32 GetWidth() const { return m_w; } - u32 GetHeight() const { return m_h; } + u32 GetWidth() const { return m_w; } + u32 GetHeight() const { return m_h; } - const boo::ObjToken& GetTexture() const { return m_tex; } + const boo::ObjToken& GetTexture() const { return m_tex; } }; -} - +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CXRayBlurFilter.cpp b/Runtime/Graphics/Shaders/CXRayBlurFilter.cpp index 8e54ca9f4..f367bcbad 100644 --- a/Runtime/Graphics/Shaders/CXRayBlurFilter.cpp +++ b/Runtime/Graphics/Shaders/CXRayBlurFilter.cpp @@ -4,69 +4,55 @@ #include "GameGlobalObjects.hpp" #include "hecl/Pipeline.hpp" -namespace urde -{ +namespace urde { static boo::ObjToken s_Pipeline; -void CXRayBlurFilter::Initialize() -{ - s_Pipeline = hecl::conv->convert(Shader_CXRayBlurFilter{}); -} +void CXRayBlurFilter::Initialize() { s_Pipeline = hecl::conv->convert(Shader_CXRayBlurFilter{}); } -void CXRayBlurFilter::Shutdown() -{ - s_Pipeline.reset(); -} +void CXRayBlurFilter::Shutdown() { s_Pipeline.reset(); } -CXRayBlurFilter::CXRayBlurFilter(TLockedToken& tex) -: m_paletteTex(tex), m_booTex(tex->GetPaletteTexture()) -{ - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - struct Vert - { - zeus::CVector2f m_pos; - zeus::CVector2f m_uv; - } verts[4] = - { +CXRayBlurFilter::CXRayBlurFilter(TLockedToken& tex) : m_paletteTex(tex), m_booTex(tex->GetPaletteTexture()) { + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + struct Vert { + zeus::CVector2f m_pos; + zeus::CVector2f m_uv; + } verts[4] = { {{-1.f, -1.f}, {0.f, 0.f}}, - {{-1.f, 1.f}, {0.f, 1.f}}, - {{ 1.f, -1.f}, {1.f, 0.f}}, - {{ 1.f, 1.f}, {1.f, 1.f}}, - }; - m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, 32, 4); - m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); - boo::ObjToken bufs[] = {m_uniBuf.get()}; - boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; - boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get(), m_booTex}; - m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, - 1, bufs, stages, nullptr, nullptr, 2, texs, nullptr, nullptr); - return true; - } BooTrace); + {{-1.f, 1.f}, {0.f, 1.f}}, + {{1.f, -1.f}, {1.f, 0.f}}, + {{1.f, 1.f}, {1.f, 1.f}}, + }; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, 32, 4); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1); + boo::ObjToken bufs[] = {m_uniBuf.get()}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ObjToken texs[] = {CGraphics::g_SpareTexture.get(), m_booTex}; + m_dataBind = ctx.newShaderDataBinding(s_Pipeline, m_vbo.get(), nullptr, nullptr, 1, bufs, stages, nullptr, nullptr, + 2, texs, nullptr, nullptr); + return true; + } BooTrace); } -void CXRayBlurFilter::draw(float amount) -{ - CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport); +void CXRayBlurFilter::draw(float amount) { + CGraphics::ResolveSpareTexture(CGraphics::g_CroppedViewport); - float blurL = amount * g_tweakGui->GetXrayBlurScaleLinear() * 0.25f; - float blurQ = amount * g_tweakGui->GetXrayBlurScaleQuadratic() * 0.25f; + float blurL = amount * g_tweakGui->GetXrayBlurScaleLinear() * 0.25f; + float blurQ = amount * g_tweakGui->GetXrayBlurScaleQuadratic() * 0.25f; - for (int i=0 ; i<8 ; ++i) - { - float iflt = i / 2.f; - float uvScale = (1.f - (blurL * iflt + blurQ * iflt * iflt)); - float uvOffset = uvScale * -0.5f + 0.5f; - m_uniform.m_uv[i][0][0] = uvScale; - m_uniform.m_uv[i][1][1] = uvScale; - m_uniform.m_uv[i][3][0] = uvOffset; - m_uniform.m_uv[i][3][1] = uvOffset; - } - m_uniBuf->load(&m_uniform, sizeof(m_uniform)); + for (int i = 0; i < 8; ++i) { + float iflt = i / 2.f; + float uvScale = (1.f - (blurL * iflt + blurQ * iflt * iflt)); + float uvOffset = uvScale * -0.5f + 0.5f; + m_uniform.m_uv[i][0][0] = uvScale; + m_uniform.m_uv[i][1][1] = uvScale; + m_uniform.m_uv[i][3][0] = uvOffset; + m_uniform.m_uv[i][3][1] = uvOffset; + } + m_uniBuf->load(&m_uniform, sizeof(m_uniform)); - CGraphics::SetShaderDataBinding(m_dataBind); - CGraphics::DrawArray(0, 4); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); } -} +} // namespace urde diff --git a/Runtime/Graphics/Shaders/CXRayBlurFilter.hpp b/Runtime/Graphics/Shaders/CXRayBlurFilter.hpp index fb3b903f8..0dcc2131c 100644 --- a/Runtime/Graphics/Shaders/CXRayBlurFilter.hpp +++ b/Runtime/Graphics/Shaders/CXRayBlurFilter.hpp @@ -5,29 +5,25 @@ #include "zeus/CColor.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class CTexture; -class CXRayBlurFilter -{ - struct Uniform - { - zeus::CMatrix4f m_uv[8]; - }; - TLockedToken m_paletteTex; - boo::ObjToken m_booTex; - boo::ObjToken m_vbo; - boo::ObjToken m_uniBuf; - boo::ObjToken m_dataBind; - Uniform m_uniform; +class CXRayBlurFilter { + struct Uniform { + zeus::CMatrix4f m_uv[8]; + }; + TLockedToken m_paletteTex; + boo::ObjToken m_booTex; + boo::ObjToken m_vbo; + boo::ObjToken m_uniBuf; + boo::ObjToken m_dataBind; + Uniform m_uniform; public: - static void Initialize(); - static void Shutdown(); - CXRayBlurFilter(TLockedToken& tex); - void draw(float amount); + static void Initialize(); + static void Shutdown(); + CXRayBlurFilter(TLockedToken& tex); + void draw(float amount); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CAuiEnergyBarT01.cpp b/Runtime/GuiSys/CAuiEnergyBarT01.cpp index 49e74b47b..5d4bec76a 100644 --- a/Runtime/GuiSys/CAuiEnergyBarT01.cpp +++ b/Runtime/GuiSys/CAuiEnergyBarT01.cpp @@ -3,173 +3,146 @@ #include "CSimplePool.hpp" #include "CGuiWidgetDrawParms.hpp" -namespace urde -{ +namespace urde { CAuiEnergyBarT01::CAuiEnergyBarT01(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId txtrId) -: CGuiWidget(parms), xb8_txtrId(txtrId) -{ - if (g_GuiSys->GetUsageMode() != CGuiSys::EUsageMode::Two) - xbc_tex = sp->GetObj(SObjectTag{FOURCC('TXTR'), xb8_txtrId}); +: CGuiWidget(parms), xb8_txtrId(txtrId) { + if (g_GuiSys->GetUsageMode() != CGuiSys::EUsageMode::Two) + xbc_tex = sp->GetObj(SObjectTag{FOURCC('TXTR'), xb8_txtrId}); } -std::pair CAuiEnergyBarT01::DownloadBarCoordFunc(float t) -{ - float x = 12.5 * t - 6.25; - return {zeus::CVector3f{x, 0.f, -0.2f}, zeus::CVector3f{x, 0.f, 0.2f}}; +std::pair CAuiEnergyBarT01::DownloadBarCoordFunc(float t) { + float x = 12.5 * t - 6.25; + return {zeus::CVector3f{x, 0.f, -0.2f}, zeus::CVector3f{x, 0.f, 0.2f}}; } -void CAuiEnergyBarT01::Update(float dt) -{ - if (x100_shadowDrainDelayTimer > 0.f) - x100_shadowDrainDelayTimer = std::max(x100_shadowDrainDelayTimer - dt, 0.f); +void CAuiEnergyBarT01::Update(float dt) { + if (x100_shadowDrainDelayTimer > 0.f) + x100_shadowDrainDelayTimer = std::max(x100_shadowDrainDelayTimer - dt, 0.f); - if (xf8_filledEnergy < xf4_setEnergy) - { - if (xf1_wrapping) - { - xf8_filledEnergy -= dt * xe4_filledSpeed; - if (xf8_filledEnergy < 0.f) - { - xf8_filledEnergy = std::max(xf4_setEnergy, xf8_filledEnergy + xe0_maxEnergy); - xf1_wrapping = false; - xfc_shadowEnergy = xe0_maxEnergy; - } - } - else - { - xf8_filledEnergy = std::min(xf4_setEnergy, xf8_filledEnergy + dt * xe4_filledSpeed); - } + if (xf8_filledEnergy < xf4_setEnergy) { + if (xf1_wrapping) { + xf8_filledEnergy -= dt * xe4_filledSpeed; + if (xf8_filledEnergy < 0.f) { + xf8_filledEnergy = std::max(xf4_setEnergy, xf8_filledEnergy + xe0_maxEnergy); + xf1_wrapping = false; + xfc_shadowEnergy = xe0_maxEnergy; + } + } else { + xf8_filledEnergy = std::min(xf4_setEnergy, xf8_filledEnergy + dt * xe4_filledSpeed); } - else if (xf8_filledEnergy > xf4_setEnergy) - { - if (xf1_wrapping) - { - xf8_filledEnergy += dt * xe4_filledSpeed; - if (xf8_filledEnergy > xe0_maxEnergy) - { - xf8_filledEnergy = std::min(xf4_setEnergy, xf8_filledEnergy - xe0_maxEnergy); - xf1_wrapping = false; - xfc_shadowEnergy = xf8_filledEnergy; - } - } - else - { - xf8_filledEnergy = std::max(xf4_setEnergy, xf8_filledEnergy - dt * xe4_filledSpeed); - } - } - - if (xfc_shadowEnergy < xf8_filledEnergy) + } else if (xf8_filledEnergy > xf4_setEnergy) { + if (xf1_wrapping) { + xf8_filledEnergy += dt * xe4_filledSpeed; + if (xf8_filledEnergy > xe0_maxEnergy) { + xf8_filledEnergy = std::min(xf4_setEnergy, xf8_filledEnergy - xe0_maxEnergy); + xf1_wrapping = false; xfc_shadowEnergy = xf8_filledEnergy; - else if (xfc_shadowEnergy > xf8_filledEnergy && x100_shadowDrainDelayTimer == 0.f) - xfc_shadowEnergy = std::max(xf8_filledEnergy, xfc_shadowEnergy - dt * xe8_shadowSpeed); + } + } else { + xf8_filledEnergy = std::max(xf4_setEnergy, xf8_filledEnergy - dt * xe4_filledSpeed); + } + } - CGuiWidget::Update(dt); + if (xfc_shadowEnergy < xf8_filledEnergy) + xfc_shadowEnergy = xf8_filledEnergy; + else if (xfc_shadowEnergy > xf8_filledEnergy && x100_shadowDrainDelayTimer == 0.f) + xfc_shadowEnergy = std::max(xf8_filledEnergy, xfc_shadowEnergy - dt * xe8_shadowSpeed); + + CGuiWidget::Update(dt); } -void CAuiEnergyBarT01::Draw(const CGuiWidgetDrawParms& drawParms) const -{ - if (!xbc_tex || !xbc_tex.IsLoaded() || !xd8_coordFunc) - return; +void CAuiEnergyBarT01::Draw(const CGuiWidgetDrawParms& drawParms) const { + if (!xbc_tex || !xbc_tex.IsLoaded() || !xd8_coordFunc) + return; - CGraphics::SetModelMatrix(x34_worldXF); - const_cast(m_energyBarShader).updateModelMatrix(); + CGraphics::SetModelMatrix(x34_worldXF); + const_cast(m_energyBarShader).updateModelMatrix(); - float filledT = xe0_maxEnergy > 0.f ? xf8_filledEnergy / xe0_maxEnergy : 0.f; - float shadowT = xe0_maxEnergy > 0.f ? xfc_shadowEnergy / xe0_maxEnergy : 0.f; + float filledT = xe0_maxEnergy > 0.f ? xf8_filledEnergy / xe0_maxEnergy : 0.f; + float shadowT = xe0_maxEnergy > 0.f ? xfc_shadowEnergy / xe0_maxEnergy : 0.f; - zeus::CColor filledColor = xd0_filledColor; - filledColor.a() *= drawParms.x0_alphaMod; - filledColor *= xa8_color2; + zeus::CColor filledColor = xd0_filledColor; + filledColor.a() *= drawParms.x0_alphaMod; + filledColor *= xa8_color2; - zeus::CColor shadowColor = xd4_shadowColor; - shadowColor.a() *= drawParms.x0_alphaMod; - shadowColor *= xa8_color2; + zeus::CColor shadowColor = xd4_shadowColor; + shadowColor.a() *= drawParms.x0_alphaMod; + shadowColor *= xa8_color2; - zeus::CColor emptyColor = xcc_emptyColor; - emptyColor.a() *= drawParms.x0_alphaMod; - emptyColor *= xa8_color2; + zeus::CColor emptyColor = xcc_emptyColor; + emptyColor.a() *= drawParms.x0_alphaMod; + emptyColor *= xa8_color2; - for (int i=0 ; i<3 ; ++i) - { - std::vector& verts = const_cast(*this).m_verts[i]; - verts.clear(); + for (int i = 0; i < 3; ++i) { + std::vector& verts = const_cast(*this).m_verts[i]; + verts.clear(); - float start; - float end; - switch (i) - { - case 0: - default: - start = 0.f; - end = filledT; - break; - case 1: - start = filledT; - end = shadowT; - break; - case 2: - start = shadowT; - end = 1.f; - break; - } - - if (start == end) - continue; - - std::pair coords = xd8_coordFunc(start); - while (start < end) - { - verts.push_back({coords.first, zeus::CVector2f(start, 0.f)}); - verts.push_back({coords.second, zeus::CVector2f(start, 1.f)}); - start += xdc_tesselation; - if (start >= end) - { - coords = xd8_coordFunc(end); - verts.push_back({coords.first, zeus::CVector2f(end, 0.f)}); - verts.push_back({coords.second, zeus::CVector2f(end, 1.f)}); - } - else - { - coords = xd8_coordFunc(start); - } - } + float start; + float end; + switch (i) { + case 0: + default: + start = 0.f; + end = filledT; + break; + case 1: + start = filledT; + end = shadowT; + break; + case 2: + start = shadowT; + end = 1.f; + break; } - const_cast(m_energyBarShader).draw(filledColor, m_verts[0], - shadowColor, m_verts[1], - emptyColor, m_verts[2], - xbc_tex.GetObj()); + if (start == end) + continue; + + std::pair coords = xd8_coordFunc(start); + while (start < end) { + verts.push_back({coords.first, zeus::CVector2f(start, 0.f)}); + verts.push_back({coords.second, zeus::CVector2f(start, 1.f)}); + start += xdc_tesselation; + if (start >= end) { + coords = xd8_coordFunc(end); + verts.push_back({coords.first, zeus::CVector2f(end, 0.f)}); + verts.push_back({coords.second, zeus::CVector2f(end, 1.f)}); + } else { + coords = xd8_coordFunc(start); + } + } + } + + const_cast(m_energyBarShader) + .draw(filledColor, m_verts[0], shadowColor, m_verts[1], emptyColor, m_verts[2], xbc_tex.GetObj()); } -void CAuiEnergyBarT01::SetCurrEnergy(float e, ESetMode mode) -{ - e = zeus::clamp(0.f, e, xe0_maxEnergy); - if (e == xf4_setEnergy) - return; - if (xf0_alwaysResetDelayTimer || xf8_filledEnergy == xfc_shadowEnergy) - x100_shadowDrainDelayTimer = xec_shadowDrainDelay; - xf1_wrapping = mode == ESetMode::Wrapped; - xf4_setEnergy = e; - if (mode == ESetMode::Insta) - xf8_filledEnergy = xf4_setEnergy; +void CAuiEnergyBarT01::SetCurrEnergy(float e, ESetMode mode) { + e = zeus::clamp(0.f, e, xe0_maxEnergy); + if (e == xf4_setEnergy) + return; + if (xf0_alwaysResetDelayTimer || xf8_filledEnergy == xfc_shadowEnergy) + x100_shadowDrainDelayTimer = xec_shadowDrainDelay; + xf1_wrapping = mode == ESetMode::Wrapped; + xf4_setEnergy = e; + if (mode == ESetMode::Insta) + xf8_filledEnergy = xf4_setEnergy; } -void CAuiEnergyBarT01::SetMaxEnergy(float maxEnergy) -{ - xe0_maxEnergy = maxEnergy; - xf4_setEnergy = std::min(xe0_maxEnergy, xf4_setEnergy); - xf8_filledEnergy = std::min(xe0_maxEnergy, xf8_filledEnergy); - xfc_shadowEnergy = std::min(xe0_maxEnergy, xfc_shadowEnergy); +void CAuiEnergyBarT01::SetMaxEnergy(float maxEnergy) { + xe0_maxEnergy = maxEnergy; + xf4_setEnergy = std::min(xe0_maxEnergy, xf4_setEnergy); + xf8_filledEnergy = std::min(xe0_maxEnergy, xf8_filledEnergy); + xfc_shadowEnergy = std::min(xe0_maxEnergy, xfc_shadowEnergy); } -std::shared_ptr CAuiEnergyBarT01::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - CAssetId tex = in.readUint32Big(); - std::shared_ptr ret = std::make_shared(parms, sp, tex); - ret->ParseBaseInfo(frame, in, parms); - return ret; +std::shared_ptr CAuiEnergyBarT01::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + CAssetId tex = in.readUint32Big(); + std::shared_ptr ret = std::make_shared(parms, sp, tex); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CAuiEnergyBarT01.hpp b/Runtime/GuiSys/CAuiEnergyBarT01.hpp index 499866823..e5bef304e 100644 --- a/Runtime/GuiSys/CAuiEnergyBarT01.hpp +++ b/Runtime/GuiSys/CAuiEnergyBarT01.hpp @@ -5,64 +5,58 @@ #include "Graphics/CTexture.hpp" #include "Graphics/Shaders/CEnergyBarShader.hpp" -namespace urde -{ +namespace urde { class CSimplePool; -class CAuiEnergyBarT01 : public CGuiWidget -{ +class CAuiEnergyBarT01 : public CGuiWidget { public: - typedef std::pair(*FCoordFunc)(float t); - enum class ESetMode - { - Normal, - Wrapped, - Insta - }; + typedef std::pair (*FCoordFunc)(float t); + enum class ESetMode { Normal, Wrapped, Insta }; + private: - CAssetId xb8_txtrId; - TLockedToken xbc_tex; // Used to be optional - zeus::CColor xcc_emptyColor; - zeus::CColor xd0_filledColor; - zeus::CColor xd4_shadowColor; - FCoordFunc xd8_coordFunc = nullptr; - float xdc_tesselation = 1.f; - float xe0_maxEnergy = 0.f; - float xe4_filledSpeed = 1000.f; - float xe8_shadowSpeed = 1000.f; - float xec_shadowDrainDelay = 0.f; - bool xf0_alwaysResetDelayTimer = false; - bool xf1_wrapping = false; - float xf4_setEnergy = 0.f; - float xf8_filledEnergy = 0.f; - float xfc_shadowEnergy = 0.f; - float x100_shadowDrainDelayTimer = 0.f; - CEnergyBarShader m_energyBarShader; - std::vector m_verts[3]; + CAssetId xb8_txtrId; + TLockedToken xbc_tex; // Used to be optional + zeus::CColor xcc_emptyColor; + zeus::CColor xd0_filledColor; + zeus::CColor xd4_shadowColor; + FCoordFunc xd8_coordFunc = nullptr; + float xdc_tesselation = 1.f; + float xe0_maxEnergy = 0.f; + float xe4_filledSpeed = 1000.f; + float xe8_shadowSpeed = 1000.f; + float xec_shadowDrainDelay = 0.f; + bool xf0_alwaysResetDelayTimer = false; + bool xf1_wrapping = false; + float xf4_setEnergy = 0.f; + float xf8_filledEnergy = 0.f; + float xfc_shadowEnergy = 0.f; + float x100_shadowDrainDelayTimer = 0.f; + CEnergyBarShader m_energyBarShader; + std::vector m_verts[3]; + public: - CAuiEnergyBarT01(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId txtrId); - FourCC GetWidgetTypeID() const { return FOURCC('ENRG'); } - static std::pair DownloadBarCoordFunc(float t); - void Update(float dt); - void Draw(const CGuiWidgetDrawParms& drawParms) const; - float GetActualFraction() const { return xe0_maxEnergy == 0.f ? 0.f : xf4_setEnergy / xe0_maxEnergy; } - float GetSetEnergy() const { return xf4_setEnergy; } - float GetMaxEnergy() const { return xe0_maxEnergy; } - float GetFilledEnergy() const { return xf8_filledEnergy; } - void SetCurrEnergy(float e, ESetMode mode); - void SetCoordFunc(FCoordFunc func) { xd8_coordFunc = func; } - void SetEmptyColor(const zeus::CColor& c) { xcc_emptyColor = c; } - void SetFilledColor(const zeus::CColor& c) { xd0_filledColor = c; } - void SetShadowColor(const zeus::CColor& c) { xd4_shadowColor = c; } - void SetMaxEnergy(float maxEnergy); - void ResetMaxEnergy() { SetMaxEnergy(xdc_tesselation); } - void SetTesselation(float t) { xdc_tesselation = t; } - void SetIsAlwaysResetTimer(bool b) { xf0_alwaysResetDelayTimer = b; } - void SetFilledDrainSpeed(float s) { xe4_filledSpeed = s; } - void SetShadowDrainSpeed(float s) { xe8_shadowSpeed = s; } - void SetShadowDrainDelay(float d) { xec_shadowDrainDelay = d; } - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + CAuiEnergyBarT01(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId txtrId); + FourCC GetWidgetTypeID() const { return FOURCC('ENRG'); } + static std::pair DownloadBarCoordFunc(float t); + void Update(float dt); + void Draw(const CGuiWidgetDrawParms& drawParms) const; + float GetActualFraction() const { return xe0_maxEnergy == 0.f ? 0.f : xf4_setEnergy / xe0_maxEnergy; } + float GetSetEnergy() const { return xf4_setEnergy; } + float GetMaxEnergy() const { return xe0_maxEnergy; } + float GetFilledEnergy() const { return xf8_filledEnergy; } + void SetCurrEnergy(float e, ESetMode mode); + void SetCoordFunc(FCoordFunc func) { xd8_coordFunc = func; } + void SetEmptyColor(const zeus::CColor& c) { xcc_emptyColor = c; } + void SetFilledColor(const zeus::CColor& c) { xd0_filledColor = c; } + void SetShadowColor(const zeus::CColor& c) { xd4_shadowColor = c; } + void SetMaxEnergy(float maxEnergy); + void ResetMaxEnergy() { SetMaxEnergy(xdc_tesselation); } + void SetTesselation(float t) { xdc_tesselation = t; } + void SetIsAlwaysResetTimer(bool b) { xf0_alwaysResetDelayTimer = b; } + void SetFilledDrainSpeed(float s) { xe4_filledSpeed = s; } + void SetShadowDrainSpeed(float s) { xe8_shadowSpeed = s; } + void SetShadowDrainDelay(float d) { xec_shadowDrainDelay = d; } + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CAuiImagePane.cpp b/Runtime/GuiSys/CAuiImagePane.cpp index 593b94298..b3e77f5de 100644 --- a/Runtime/GuiSys/CAuiImagePane.cpp +++ b/Runtime/GuiSys/CAuiImagePane.cpp @@ -3,211 +3,183 @@ #include "Graphics/CTexture.hpp" #include "CGuiWidgetDrawParms.hpp" -namespace urde -{ +namespace urde { CAuiImagePane::CAuiImagePane(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId tex0, CAssetId tex1, rstl::reserved_vector&& coords, rstl::reserved_vector&& uvs, bool initTex) -: CGuiWidget(parms), xc8_tex0(tex0), xcc_tex1(tex1), xe0_coords(std::move(coords)), - x114_uvs(std::move(uvs)) -{ - if (initTex) - SetTextureID0(tex0, sp); +: CGuiWidget(parms), xc8_tex0(tex0), xcc_tex1(tex1), xe0_coords(std::move(coords)), x114_uvs(std::move(uvs)) { + if (initTex) + SetTextureID0(tex0, sp); } -std::shared_ptr CAuiImagePane::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - in.readUint32Big(); - in.readUint32Big(); - in.readUint32Big(); - u32 coordCount = in.readUint32Big(); - rstl::reserved_vector coords; - for (int i=0 ; i uvs; - for (int i=0 ; i ret = std::make_shared(parms, sp, -1, -1, - std::move(coords), std::move(uvs), true); - ret->ParseBaseInfo(frame, in, parms); - return ret; +std::shared_ptr CAuiImagePane::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + in.readUint32Big(); + in.readUint32Big(); + in.readUint32Big(); + u32 coordCount = in.readUint32Big(); + rstl::reserved_vector coords; + for (int i = 0; i < coordCount; ++i) + coords.push_back(zeus::CVector3f::ReadBig(in)); + u32 uvCount = in.readUint32Big(); + rstl::reserved_vector uvs; + for (int i = 0; i < uvCount; ++i) + uvs.push_back(zeus::CVector2f::ReadBig(in)); + std::shared_ptr ret = + std::make_shared(parms, sp, -1, -1, std::move(coords), std::move(uvs), true); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -void CAuiImagePane::Update(float dt) -{ - xd0_uvBias0.x() = std::fmod(xd0_uvBias0.x(), 1.f); - xd0_uvBias0.y() = std::fmod(xd0_uvBias0.y(), 1.f); - if (x138_tileSize != zeus::CVector2f::skZero && xb8_tex0Tok.IsLoaded()) - { - zeus::CVector2f tmp = zeus::CVector2f(xb8_tex0Tok->GetWidth(), xb8_tex0Tok->GetHeight()) / x138_tileSize; - x144_frameTimer = std::fmod(x144_frameTimer + dt * x140_interval, std::floor(tmp.x()) * std::floor(tmp.y())); - } +void CAuiImagePane::Update(float dt) { + xd0_uvBias0.x() = std::fmod(xd0_uvBias0.x(), 1.f); + xd0_uvBias0.y() = std::fmod(xd0_uvBias0.y(), 1.f); + if (x138_tileSize != zeus::CVector2f::skZero && xb8_tex0Tok.IsLoaded()) { + zeus::CVector2f tmp = zeus::CVector2f(xb8_tex0Tok->GetWidth(), xb8_tex0Tok->GetHeight()) / x138_tileSize; + x144_frameTimer = std::fmod(x144_frameTimer + dt * x140_interval, std::floor(tmp.x()) * std::floor(tmp.y())); + } - CGuiWidget::Update(dt); + CGuiWidget::Update(dt); } CAuiImagePane::Filters::Filters(TLockedToken& tex) -: m_texId(tex.GetObjectTag()->id), - m_darkenerQuad(EFilterType::Blend, tex), - m_flashQuad{{EFilterType::Add, tex}, {EFilterType::Add, tex}}, - m_alphaQuad{{EFilterType::Blend, tex}, {EFilterType::Blend, tex}}, - m_addQuad{{EFilterType::Add, tex}, {EFilterType::Add, tex}} -{ +: m_texId(tex.GetObjectTag()->id) +, m_darkenerQuad(EFilterType::Blend, tex) +, m_flashQuad{{EFilterType::Add, tex}, {EFilterType::Add, tex}} +, m_alphaQuad{{EFilterType::Blend, tex}, {EFilterType::Blend, tex}} +, m_addQuad{{EFilterType::Add, tex}, {EFilterType::Add, tex}} {} + +void CAuiImagePane::DoDrawImagePane(const zeus::CColor& color, const CTexture& tex, int frame, float alpha, bool noBlur, + CTexturedQuadFilterAlpha& quad) const { + zeus::CColor useColor = color; + useColor.a() *= alpha; + + rstl::reserved_vector vec; + const rstl::reserved_vector* useUVs; + if (x138_tileSize != zeus::CVector2f::skZero) { + zeus::CVector2f res(xb8_tex0Tok->GetWidth(), xb8_tex0Tok->GetHeight()); + zeus::CVector2f tmp = res / x138_tileSize; + zeus::CVector2f tmpRecip = x138_tileSize / res; + float x0 = tmpRecip.x() * (frame % int(tmp.x())); + float x1 = x0 + tmpRecip.x(); + float y0 = tmpRecip.y() * (frame % int(tmp.y())); + float y1 = y0 + tmpRecip.y(); + vec.push_back(zeus::CVector2f(x0, y0)); + vec.push_back(zeus::CVector2f(x0, y1)); + vec.push_back(zeus::CVector2f(x1, y0)); + vec.push_back(zeus::CVector2f(x1, y1)); + useUVs = &vec; + } else { + useUVs = &x114_uvs; + } + + CTexturedQuadFilter::Vert verts[] = {{xe0_coords[0], (*useUVs)[0] + xd0_uvBias0}, + {xe0_coords[1], (*useUVs)[1] + xd0_uvBias0}, + {xe0_coords[3], (*useUVs)[3] + xd0_uvBias0}, + {xe0_coords[2], (*useUVs)[2] + xd0_uvBias0}}; + + if (noBlur) { + quad.drawVerts(useColor, verts); + } else if ((x14c_deResFactor == 0.f && alpha == 1.f) || tex.GetNumMips() == 1) { + quad.drawVerts(useColor, verts, 0.f); + } else { + float tmp = (1.f - x14c_deResFactor) * alpha; + float tmp3 = 1.f - tmp * tmp * tmp; + float mip = tmp3 * (tex.GetNumMips() - 1); + quad.drawVerts(useColor, verts, mip); + } } -void CAuiImagePane::DoDrawImagePane(const zeus::CColor& color, const CTexture& tex, - int frame, float alpha, bool noBlur, CTexturedQuadFilterAlpha& quad) const -{ - zeus::CColor useColor = color; - useColor.a() *= alpha; - - rstl::reserved_vector vec; - const rstl::reserved_vector* useUVs; - if (x138_tileSize != zeus::CVector2f::skZero) - { - zeus::CVector2f res(xb8_tex0Tok->GetWidth(), xb8_tex0Tok->GetHeight()); - zeus::CVector2f tmp = res / x138_tileSize; - zeus::CVector2f tmpRecip = x138_tileSize / res; - float x0 = tmpRecip.x() * (frame % int(tmp.x())); - float x1 = x0 + tmpRecip.x(); - float y0 = tmpRecip.y() * (frame % int(tmp.y())); - float y1 = y0 + tmpRecip.y(); - vec.push_back(zeus::CVector2f(x0, y0)); - vec.push_back(zeus::CVector2f(x0, y1)); - vec.push_back(zeus::CVector2f(x1, y0)); - vec.push_back(zeus::CVector2f(x1, y1)); - useUVs = &vec; - } +void CAuiImagePane::Draw(const CGuiWidgetDrawParms& params) const { + CGraphics::SetModelMatrix(x34_worldXF); + if (!GetIsVisible() || !xb8_tex0Tok.IsLoaded()) + return; + GetIsFinishedLoadingWidgetSpecific(); + if (!m_filters || m_filters->m_texId != xb8_tex0Tok.GetObjectTag()->id) + const_cast(this)->m_filters.emplace(const_cast(this)->xb8_tex0Tok); + Filters& filters = const_cast(*m_filters); + zeus::CColor color = xa8_color2; + color.a() *= params.x0_alphaMod; + // SetZUpdate(xac_drawFlags == EGuiModelDrawFlags::Shadeless || xac_drawFlags == EGuiModelDrawFlags::Opaque); + float blur0 = 1.f; + float blur1 = 0.f; + int frame0 = x144_frameTimer; + int frame1 = 0; + if (x140_interval < 1.f && x140_interval > 0.f) { + zeus::CVector2f tmp = zeus::CVector2f(xb8_tex0Tok->GetWidth(), xb8_tex0Tok->GetHeight()) / x138_tileSize; + frame1 = (frame0 + 1) % int(tmp.x() * tmp.y()); + if (x148_fadeDuration == 0.f) + blur1 = 1.f; else - { - useUVs = &x114_uvs; - } + blur1 = std::min(std::fmod(x144_frameTimer, 1.f) / x148_fadeDuration, 1.f); + blur0 = 1.f - blur1; + } - CTexturedQuadFilter::Vert verts[] = - { - {xe0_coords[0], (*useUVs)[0] + xd0_uvBias0}, - {xe0_coords[1], (*useUVs)[1] + xd0_uvBias0}, - {xe0_coords[3], (*useUVs)[3] + xd0_uvBias0}, - {xe0_coords[2], (*useUVs)[2] + xd0_uvBias0} - }; + // Alpha blend + DoDrawImagePane(color * zeus::CColor(0.f, 0.5f), *xb8_tex0Tok, frame0, 1.f, true, filters.m_darkenerQuad); - if (noBlur) - { - quad.drawVerts(useColor, verts); - } - else if ((x14c_deResFactor == 0.f && alpha == 1.f) || tex.GetNumMips() == 1) - { - quad.drawVerts(useColor, verts, 0.f); - } - else - { - float tmp = (1.f - x14c_deResFactor) * alpha; - float tmp3 = 1.f - tmp * tmp * tmp; - float mip = tmp3 * (tex.GetNumMips() - 1); - quad.drawVerts(useColor, verts, mip); - } -} - -void CAuiImagePane::Draw(const CGuiWidgetDrawParms& params) const -{ - CGraphics::SetModelMatrix(x34_worldXF); - if (!GetIsVisible() || !xb8_tex0Tok.IsLoaded()) - return; - GetIsFinishedLoadingWidgetSpecific(); - if (!m_filters || m_filters->m_texId != xb8_tex0Tok.GetObjectTag()->id) - const_cast(this)->m_filters.emplace(const_cast(this)->xb8_tex0Tok); - Filters& filters = const_cast(*m_filters); - zeus::CColor color = xa8_color2; - color.a() *= params.x0_alphaMod; - //SetZUpdate(xac_drawFlags == EGuiModelDrawFlags::Shadeless || xac_drawFlags == EGuiModelDrawFlags::Opaque); - float blur0 = 1.f; - float blur1 = 0.f; - int frame0 = x144_frameTimer; - int frame1 = 0; - if (x140_interval < 1.f && x140_interval > 0.f) - { - zeus::CVector2f tmp = zeus::CVector2f(xb8_tex0Tok->GetWidth(), xb8_tex0Tok->GetHeight()) / x138_tileSize; - frame1 = (frame0 + 1) % int(tmp.x() * tmp.y()); - if (x148_fadeDuration == 0.f) - blur1 = 1.f; - else - blur1 = std::min(std::fmod(x144_frameTimer, 1.f) / x148_fadeDuration, 1.f); - blur0 = 1.f - blur1; - } + if (x150_flashFactor > 0.f) { + // Additive blend + zeus::CColor color2 = xa8_color2; + color2.a() = x150_flashFactor; + DoDrawImagePane(color2, *xb8_tex0Tok, frame0, blur0, false, filters.m_flashQuad[0]); + if (blur1 > 0.f) + DoDrawImagePane(color2, *xb8_tex0Tok, frame1, blur1, false, filters.m_flashQuad[1]); + } + switch (xac_drawFlags) { + case EGuiModelDrawFlags::Shadeless: + case EGuiModelDrawFlags::Opaque: + // Opaque blend + DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_alphaQuad[0]); + if (blur1 > 0.f) + DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_alphaQuad[1]); + break; + case EGuiModelDrawFlags::Alpha: // Alpha blend - DoDrawImagePane(color * zeus::CColor(0.f, 0.5f), *xb8_tex0Tok, frame0, 1.f, true, filters.m_darkenerQuad); - - if (x150_flashFactor > 0.f) - { - // Additive blend - zeus::CColor color2 = xa8_color2; - color2.a() = x150_flashFactor; - DoDrawImagePane(color2, *xb8_tex0Tok, frame0, blur0, false, filters.m_flashQuad[0]); - if (blur1 > 0.f) - DoDrawImagePane(color2, *xb8_tex0Tok, frame1, blur1, false, filters.m_flashQuad[1]); - } - - switch (xac_drawFlags) - { - case EGuiModelDrawFlags::Shadeless: - case EGuiModelDrawFlags::Opaque: - // Opaque blend - DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_alphaQuad[0]); - if (blur1 > 0.f) - DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_alphaQuad[1]); - break; - case EGuiModelDrawFlags::Alpha: - // Alpha blend - DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_alphaQuad[0]); - if (blur1 > 0.f) - DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_alphaQuad[1]); - break; - case EGuiModelDrawFlags::Additive: - // Additive blend - DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_addQuad[0]); - if (blur1 > 0.f) - DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_addQuad[1]); - break; - case EGuiModelDrawFlags::AlphaAdditiveOverdraw: - // Alpha blend - DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_alphaQuad[0]); - if (blur1 > 0.f) - DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_alphaQuad[1]); - // Full additive blend - DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_addQuad[0]); - if (blur1 > 0.f) - DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_addQuad[1]); - break; - default: break; - } + DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_alphaQuad[0]); + if (blur1 > 0.f) + DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_alphaQuad[1]); + break; + case EGuiModelDrawFlags::Additive: + // Additive blend + DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_addQuad[0]); + if (blur1 > 0.f) + DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_addQuad[1]); + break; + case EGuiModelDrawFlags::AlphaAdditiveOverdraw: + // Alpha blend + DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_alphaQuad[0]); + if (blur1 > 0.f) + DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_alphaQuad[1]); + // Full additive blend + DoDrawImagePane(color, *xb8_tex0Tok, frame0, blur0, false, filters.m_addQuad[0]); + if (blur1 > 0.f) + DoDrawImagePane(color, *xb8_tex0Tok, frame1, blur1, false, filters.m_addQuad[1]); + break; + default: + break; + } } -bool CAuiImagePane::GetIsFinishedLoadingWidgetSpecific() const -{ - return !xb8_tex0Tok || xb8_tex0Tok.IsLoaded(); +bool CAuiImagePane::GetIsFinishedLoadingWidgetSpecific() const { return !xb8_tex0Tok || xb8_tex0Tok.IsLoaded(); } + +void CAuiImagePane::SetTextureID0(CAssetId tex, CSimplePool* sp) { + xc8_tex0 = tex; + if (!sp) + return; + if (xc8_tex0.IsValid()) + xb8_tex0Tok = sp->GetObj({FOURCC('TXTR'), xc8_tex0}); + else + xb8_tex0Tok = TLockedToken(); } -void CAuiImagePane::SetTextureID0(CAssetId tex, CSimplePool* sp) -{ - xc8_tex0 = tex; - if (!sp) - return; - if (xc8_tex0.IsValid()) - xb8_tex0Tok = sp->GetObj({FOURCC('TXTR'), xc8_tex0}); - else - xb8_tex0Tok = TLockedToken(); +void CAuiImagePane::SetAnimationParms(const zeus::CVector2f& tileSize, float interval, float fadeDuration) { + x138_tileSize = tileSize; + x140_interval = interval; + x144_frameTimer = 0.f; + x148_fadeDuration = fadeDuration; } -void CAuiImagePane::SetAnimationParms(const zeus::CVector2f& tileSize, float interval, float fadeDuration) -{ - x138_tileSize = tileSize; - x140_interval = interval; - x144_frameTimer = 0.f; - x148_fadeDuration = fadeDuration; -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CAuiImagePane.hpp b/Runtime/GuiSys/CAuiImagePane.hpp index 1217581a6..ccbdebf7d 100644 --- a/Runtime/GuiSys/CAuiImagePane.hpp +++ b/Runtime/GuiSys/CAuiImagePane.hpp @@ -4,52 +4,49 @@ #include "CToken.hpp" #include "Graphics/Shaders/CTexturedQuadFilter.hpp" -namespace urde -{ +namespace urde { class CSimplePool; class CTexture; -class CAuiImagePane : public CGuiWidget -{ - TLockedToken xb8_tex0Tok; // Used to be optional - CAssetId xc8_tex0; - CAssetId xcc_tex1; - zeus::CVector2f xd0_uvBias0; - zeus::CVector2f xd8_uvBias1; - rstl::reserved_vector xe0_coords; - rstl::reserved_vector x114_uvs; - zeus::CVector2f x138_tileSize; - float x140_interval = 0.f; - float x144_frameTimer = 0.f; - float x148_fadeDuration = 0.f; - float x14c_deResFactor = 0.f; - float x150_flashFactor = 0.f; - struct Filters - { - CAssetId m_texId; - CTexturedQuadFilterAlpha m_darkenerQuad; - CTexturedQuadFilterAlpha m_flashQuad[2]; - CTexturedQuadFilterAlpha m_alphaQuad[2]; - CTexturedQuadFilterAlpha m_addQuad[2]; - Filters(TLockedToken& tex); - }; - std::experimental::optional m_filters; - void DoDrawImagePane(const zeus::CColor& color, const CTexture& tex, - int frame, float blurAmt, bool noBlur, CTexturedQuadFilterAlpha& quad) const; +class CAuiImagePane : public CGuiWidget { + TLockedToken xb8_tex0Tok; // Used to be optional + CAssetId xc8_tex0; + CAssetId xcc_tex1; + zeus::CVector2f xd0_uvBias0; + zeus::CVector2f xd8_uvBias1; + rstl::reserved_vector xe0_coords; + rstl::reserved_vector x114_uvs; + zeus::CVector2f x138_tileSize; + float x140_interval = 0.f; + float x144_frameTimer = 0.f; + float x148_fadeDuration = 0.f; + float x14c_deResFactor = 0.f; + float x150_flashFactor = 0.f; + struct Filters { + CAssetId m_texId; + CTexturedQuadFilterAlpha m_darkenerQuad; + CTexturedQuadFilterAlpha m_flashQuad[2]; + CTexturedQuadFilterAlpha m_alphaQuad[2]; + CTexturedQuadFilterAlpha m_addQuad[2]; + Filters(TLockedToken& tex); + }; + std::experimental::optional m_filters; + void DoDrawImagePane(const zeus::CColor& color, const CTexture& tex, int frame, float blurAmt, bool noBlur, + CTexturedQuadFilterAlpha& quad) const; + public: - CAuiImagePane(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId, CAssetId, - rstl::reserved_vector&& coords, - rstl::reserved_vector&& uvs, bool initTex); - FourCC GetWidgetTypeID() const { return FOURCC('IMGP'); } - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + CAuiImagePane(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId, CAssetId, + rstl::reserved_vector&& coords, rstl::reserved_vector&& uvs, + bool initTex); + FourCC GetWidgetTypeID() const { return FOURCC('IMGP'); } + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); - void Update(float dt); - void Draw(const CGuiWidgetDrawParms& params) const; - bool GetIsFinishedLoadingWidgetSpecific() const; - void SetTextureID0(CAssetId tex, CSimplePool* sp); - void SetAnimationParms(const zeus::CVector2f& vec, float interval, float duration); - void SetDeResFactor(float d) { x14c_deResFactor = d; } - void SetFlashFactor(float t) { x150_flashFactor = t; } + void Update(float dt); + void Draw(const CGuiWidgetDrawParms& params) const; + bool GetIsFinishedLoadingWidgetSpecific() const; + void SetTextureID0(CAssetId tex, CSimplePool* sp); + void SetAnimationParms(const zeus::CVector2f& vec, float interval, float duration); + void SetDeResFactor(float d) { x14c_deResFactor = d; } + void SetFlashFactor(float t) { x150_flashFactor = t; } }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CAuiMeter.cpp b/Runtime/GuiSys/CAuiMeter.cpp index 70ebfba63..37bd109a3 100644 --- a/Runtime/GuiSys/CAuiMeter.cpp +++ b/Runtime/GuiSys/CAuiMeter.cpp @@ -1,116 +1,96 @@ #include "CAuiMeter.hpp" -namespace urde -{ +namespace urde { -CAuiMeter::CAuiMeter(const CGuiWidgetParms& parms, bool noRoundUp, - u32 maxCapacity, u32 workerCount) -: CGuiGroup(parms, 0, false), xc4_noRoundUp(noRoundUp), - xc8_maxCapacity(maxCapacity), xcc_capacity(maxCapacity) -{ - xd4_workers.reserve(workerCount); +CAuiMeter::CAuiMeter(const CGuiWidgetParms& parms, bool noRoundUp, u32 maxCapacity, u32 workerCount) +: CGuiGroup(parms, 0, false), xc4_noRoundUp(noRoundUp), xc8_maxCapacity(maxCapacity), xcc_capacity(maxCapacity) { + xd4_workers.reserve(workerCount); } -void CAuiMeter::UpdateMeterWorkers() -{ - float scale = xd4_workers.size() / float(xc8_maxCapacity); +void CAuiMeter::UpdateMeterWorkers() { + float scale = xd4_workers.size() / float(xc8_maxCapacity); - int etankCap; - if (xc4_noRoundUp) - etankCap = xcc_capacity * scale; - else - etankCap = xcc_capacity * scale + 0.5f; + int etankCap; + if (xc4_noRoundUp) + etankCap = xcc_capacity * scale; + else + etankCap = xcc_capacity * scale + 0.5f; - int etankFill; - if (xc4_noRoundUp) - etankFill = xd0_value * scale; - else - etankFill = xd0_value * scale + 0.5f; + int etankFill; + if (xc4_noRoundUp) + etankFill = xd0_value * scale; + else + etankFill = xd0_value * scale + 0.5f; - for (int i=0 ; iGetWorkerWidget(0); - CGuiWidget* emptyTank = worker->GetWorkerWidget(1); + CGuiWidget* fullTank = worker->GetWorkerWidget(0); + CGuiWidget* emptyTank = worker->GetWorkerWidget(1); - if (i < etankFill) - { - if (fullTank) - fullTank->SetIsVisible(true); - if (emptyTank) - emptyTank->SetIsVisible(false); - } - else if (i < etankCap) - { - if (fullTank) - fullTank->SetIsVisible(false); - if (emptyTank) - emptyTank->SetIsVisible(true); - } - else - { - if (fullTank) - fullTank->SetIsVisible(false); - if (emptyTank) - emptyTank->SetIsVisible(false); - } + if (i < etankFill) { + if (fullTank) + fullTank->SetIsVisible(true); + if (emptyTank) + emptyTank->SetIsVisible(false); + } else if (i < etankCap) { + if (fullTank) + fullTank->SetIsVisible(false); + if (emptyTank) + emptyTank->SetIsVisible(true); + } else { + if (fullTank) + fullTank->SetIsVisible(false); + if (emptyTank) + emptyTank->SetIsVisible(false); } + } } -void CAuiMeter::OnVisibleChange() -{ - if (GetIsVisible()) - UpdateMeterWorkers(); -} - -void CAuiMeter::SetCurrValue(s32 val) -{ - xd0_value = zeus::clamp(0, val, xcc_capacity); +void CAuiMeter::OnVisibleChange() { + if (GetIsVisible()) UpdateMeterWorkers(); } -void CAuiMeter::SetCapacity(s32 cap) -{ - xcc_capacity = zeus::clamp(0, cap, xc8_maxCapacity); - xd0_value = std::min(xcc_capacity, xd0_value); - UpdateMeterWorkers(); +void CAuiMeter::SetCurrValue(s32 val) { + xd0_value = zeus::clamp(0, val, xcc_capacity); + UpdateMeterWorkers(); } -void CAuiMeter::SetMaxCapacity(s32 cap) -{ - xc8_maxCapacity = std::max(0, cap); - xcc_capacity = std::min(xc8_maxCapacity, xcc_capacity); - xd0_value = std::min(xcc_capacity, xd0_value); - UpdateMeterWorkers(); +void CAuiMeter::SetCapacity(s32 cap) { + xcc_capacity = zeus::clamp(0, cap, xc8_maxCapacity); + xd0_value = std::min(xcc_capacity, xd0_value); + UpdateMeterWorkers(); } -CGuiWidget* CAuiMeter::GetWorkerWidget(int id) const -{ - return xd4_workers[id]; +void CAuiMeter::SetMaxCapacity(s32 cap) { + xc8_maxCapacity = std::max(0, cap); + xcc_capacity = std::min(xc8_maxCapacity, xcc_capacity); + xd0_value = std::min(xcc_capacity, xd0_value); + UpdateMeterWorkers(); } -bool CAuiMeter::AddWorkerWidget(CGuiWidget* worker) -{ - CGuiGroup::AddWorkerWidget(worker); - if (worker->GetWorkerId() >= xd4_workers.size()) - xd4_workers.resize(worker->GetWorkerId() + 1); - xd4_workers[worker->GetWorkerId()] = static_cast(worker); - return true; +CGuiWidget* CAuiMeter::GetWorkerWidget(int id) const { return xd4_workers[id]; } + +bool CAuiMeter::AddWorkerWidget(CGuiWidget* worker) { + CGuiGroup::AddWorkerWidget(worker); + if (worker->GetWorkerId() >= xd4_workers.size()) + xd4_workers.resize(worker->GetWorkerId() + 1); + xd4_workers[worker->GetWorkerId()] = static_cast(worker); + return true; } -std::shared_ptr CAuiMeter::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - in.readBool(); - bool noRoundUp = in.readBool(); - u32 maxCapacity = in.readUint32Big(); - u32 workerCount = in.readUint32Big(); - std::shared_ptr ret = std::make_shared(parms, noRoundUp, maxCapacity, workerCount); - ret->ParseBaseInfo(frame, in, parms); - return ret; +std::shared_ptr CAuiMeter::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + in.readBool(); + bool noRoundUp = in.readBool(); + u32 maxCapacity = in.readUint32Big(); + u32 workerCount = in.readUint32Big(); + std::shared_ptr ret = std::make_shared(parms, noRoundUp, maxCapacity, workerCount); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CAuiMeter.hpp b/Runtime/GuiSys/CAuiMeter.hpp index 901bdd542..c6db6b208 100644 --- a/Runtime/GuiSys/CAuiMeter.hpp +++ b/Runtime/GuiSys/CAuiMeter.hpp @@ -2,33 +2,29 @@ #include "CGuiGroup.hpp" -namespace urde -{ +namespace urde { class CSimplePool; -class CAuiMeter : public CGuiGroup -{ - bool xc4_noRoundUp; - s32 xc8_maxCapacity; - s32 xcc_capacity; - s32 xd0_value = 0; - std::vector xd4_workers; - void UpdateMeterWorkers(); +class CAuiMeter : public CGuiGroup { + bool xc4_noRoundUp; + s32 xc8_maxCapacity; + s32 xcc_capacity; + s32 xd0_value = 0; + std::vector xd4_workers; + void UpdateMeterWorkers(); public: - CAuiMeter(const CGuiWidgetParms& parms, bool noRoundUp, - u32 maxCapacity, u32 workerCount); - FourCC GetWidgetTypeID() const { return FOURCC('METR'); } + CAuiMeter(const CGuiWidgetParms& parms, bool noRoundUp, u32 maxCapacity, u32 workerCount); + FourCC GetWidgetTypeID() const { return FOURCC('METR'); } - void OnVisibleChange(); - void SetCurrValue(s32 val); - void SetCapacity(s32 cap); - void SetMaxCapacity(s32 cap); - CGuiWidget* GetWorkerWidget(int id) const; - bool AddWorkerWidget(CGuiWidget* worker); + void OnVisibleChange(); + void SetCurrValue(s32 val); + void SetCapacity(s32 cap); + void SetMaxCapacity(s32 cap); + CGuiWidget* GetWorkerWidget(int id) const; + bool AddWorkerWidget(CGuiWidget* worker); - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CCompoundTargetReticle.cpp b/Runtime/GuiSys/CCompoundTargetReticle.cpp index 03c159b84..16d1c48a6 100644 --- a/Runtime/GuiSys/CCompoundTargetReticle.cpp +++ b/Runtime/GuiSys/CCompoundTargetReticle.cpp @@ -9,8 +9,7 @@ #include "World/CPlayer.hpp" #include "World/CWorld.hpp" -namespace urde -{ +namespace urde { const CTargetReticleRenderState CTargetReticleRenderState::skZeroRenderState(kInvalidUniqueId, 1.f, zeus::CVector3f::skZero, 0.f, 1.f, true); @@ -25,7 +24,7 @@ CCompoundTargetReticle::CCompoundTargetReticle(const CStateManager& mgr) , x10_laggingOrientation(mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().buildMatrix3f()) , x2c_overshootOffsetHalf(0.5f * g_tweakTargeting->GetChargeGaugeOvershootOffset()) , x30_premultOvershootOffset( - calculate_premultiplied_overshoot_offset(g_tweakTargeting->GetChargeGaugeOvershootOffset())) + calculate_premultiplied_overshoot_offset(g_tweakTargeting->GetChargeGaugeOvershootOffset())) , x34_crosshairs(g_SimplePool->GetObj(skCrosshairsReticleAssetName)) , x40_seeker(g_SimplePool->GetObj(skSeekerAssetName)) , x4c_lockConfirm(g_SimplePool->GetObj(skLockConfirmAssetName)) @@ -41,1033 +40,904 @@ CCompoundTargetReticle::CCompoundTargetReticle(const CStateManager& mgr) , xc4_chargeGauge(skChargeGaugeAssetName) , xf4_targetPos(CalculateOrbitZoneReticlePosition(mgr, false)) , x100_laggingTargetPos(CalculateOrbitZoneReticlePosition(mgr, true)) -, x208_lockonTimer(g_tweakTargeting->GetLockonDuration()) -{ - xe0_outerBeamIconSquares.reserve(9); - for (u32 i = 0; i < 9; ++i) - { - char name[1024]; - sprintf(name, "%s%d", skOuterBeamIconSquareNameBase, i); - xe0_outerBeamIconSquares.emplace_back(name); +, x208_lockonTimer(g_tweakTargeting->GetLockonDuration()) { + xe0_outerBeamIconSquares.reserve(9); + for (u32 i = 0; i < 9; ++i) { + char name[1024]; + sprintf(name, "%s%d", skOuterBeamIconSquareNameBase, i); + xe0_outerBeamIconSquares.emplace_back(name); + } + x34_crosshairs.Lock(); +} + +CCompoundTargetReticle::SScanReticuleRenderer::SScanReticuleRenderer() { + CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { + for (int i = 0; i < 2; ++i) { + m_lineRenderers[i].emplace(ctx, CLineRenderer::EPrimitiveMode::Lines, 8, nullptr, true, true); + for (int j = 0; j < 4; ++j) + m_stripRenderers[i][j].emplace(ctx, CLineRenderer::EPrimitiveMode::LineStrip, 4, nullptr, true, true); } - x34_crosshairs.Lock(); + return true; + } BooTrace); } -CCompoundTargetReticle::SScanReticuleRenderer::SScanReticuleRenderer() -{ - CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) - { - for (int i=0 ; i<2 ; ++i) - { - m_lineRenderers[i].emplace(ctx, CLineRenderer::EPrimitiveMode::Lines, 8, nullptr, true, true); - for (int j=0 ; j<4 ; ++j) - m_stripRenderers[i][j].emplace(ctx, CLineRenderer::EPrimitiveMode::LineStrip, 4, nullptr, true, true); - } - return true; - } BooTrace); +CCompoundTargetReticle::EReticleState CCompoundTargetReticle::GetDesiredReticleState(const CStateManager& mgr) const { + switch (mgr.GetPlayerState()->GetCurrentVisor()) { + case CPlayerState::EPlayerVisor::Scan: + return EReticleState::Scan; + case CPlayerState::EPlayerVisor::XRay: + return EReticleState::XRay; + case CPlayerState::EPlayerVisor::Combat: + default: + return EReticleState::Combat; + case CPlayerState::EPlayerVisor::Thermal: + return EReticleState::Thermal; + } } -CCompoundTargetReticle::EReticleState CCompoundTargetReticle::GetDesiredReticleState(const CStateManager& mgr) const -{ - switch (mgr.GetPlayerState()->GetCurrentVisor()) - { - case CPlayerState::EPlayerVisor::Scan: - return EReticleState::Scan; - case CPlayerState::EPlayerVisor::XRay: - return EReticleState::XRay; - case CPlayerState::EPlayerVisor::Combat: +void CCompoundTargetReticle::Update(float dt, const CStateManager& mgr) { + float angle = x10_laggingOrientation.angleFrom(x0_leadingOrientation).asDegrees(); + float t; + if (angle < 0.1f || angle > 45.f) + t = 1.f; + else + t = std::min(1.f, g_tweakTargeting->GetAngularLagSpeed() * dt / angle); + x10_laggingOrientation = + t == 1.f ? x0_leadingOrientation : zeus::CQuaternion::slerp(x10_laggingOrientation, x0_leadingOrientation, t); + xf4_targetPos = CalculateOrbitZoneReticlePosition(mgr, false); + x100_laggingTargetPos = CalculateOrbitZoneReticlePosition(mgr, true); + UpdateCurrLockOnGroup(dt, mgr); + UpdateNextLockOnGroup(dt, mgr); + UpdateOrbitZoneGroup(dt, mgr); + EReticleState desiredState = GetDesiredReticleState(mgr); + if (desiredState != x20_prevState && x20_prevState == x24_nextState) { + x24_nextState = desiredState; + x28_noDrawTicks = 2; + } + if (x20_prevState != x24_nextState && x28_noDrawTicks <= 0) { + x20_prevState = x24_nextState; + float combat = false; + float scan = false; + float xray = false; + float thermal = false; + switch (x24_nextState) { + case EReticleState::Combat: + combat = true; + break; + case EReticleState::Scan: + scan = true; + break; + case EReticleState::XRay: + xray = true; + break; + case EReticleState::Thermal: + thermal = true; + break; default: - return EReticleState::Combat; - case CPlayerState::EPlayerVisor::Thermal: - return EReticleState::Thermal; + break; } + if (combat) + x40_seeker.Lock(); + else + x40_seeker.Unlock(); + if (combat) + x4c_lockConfirm.Lock(); + else + x4c_lockConfirm.Unlock(); + if (combat) + x58_targetFlower.Lock(); + else + x58_targetFlower.Unlock(); + if (combat) + x64_missileBracket.Lock(); + else + x64_missileBracket.Unlock(); + if (combat) + x70_innerBeamIcon.Lock(); + else + x70_innerBeamIcon.Unlock(); + if (combat) + x7c_lockFire.Lock(); + else + x7c_lockFire.Unlock(); + if (combat) + x88_lockDagger.Lock(); + else + x88_lockDagger.Unlock(); + if (combat) + xa0_chargeTickFirst.Lock(); + else + xa0_chargeTickFirst.Unlock(); + if (xray) + xac_xrayRetRing.Lock(); + else + xac_xrayRetRing.Unlock(); + if (thermal) + xb8_thermalReticle.Lock(); + else + xb8_thermalReticle.Unlock(); + if (combat) + xc4_chargeGauge.x0_model.Lock(); + else + xc4_chargeGauge.x0_model.Unlock(); + if (!scan) + x94_grapple.Lock(); + else + x94_grapple.Unlock(); + for (SOuterItemInfo& info : xe0_outerBeamIconSquares) { + if (combat) + info.x0_model.Lock(); + else + info.x0_model.Unlock(); + } + } + CPlayerGun* gun = mgr.GetPlayer().GetPlayerGun(); + bool fullyCharged = (gun->IsCharging() ? gun->GetChargeBeamFactor() : 0.f) >= 1.f; + if (fullyCharged != x21a_fullyCharged) + x21a_fullyCharged = fullyCharged; + if (x21a_fullyCharged) + x214_fullChargeFadeTimer = std::min(dt / g_tweakTargeting->GetFullChargeFadeDuration() + x214_fullChargeFadeTimer, + g_tweakTargeting->GetFullChargeFadeDuration()); + else + x214_fullChargeFadeTimer = + std::max(x214_fullChargeFadeTimer - dt / g_tweakTargeting->GetFullChargeFadeDuration(), 0.f); + bool missileActive = gun->GetMissleMode() == CPlayerGun::EMissleMode::Active; + if (missileActive != x1f4_missileActive) { + if (x1f8_missileBracketTimer != 0.f) + x1f8_missileBracketTimer = FLT_EPSILON - x1f8_missileBracketTimer; + else + x1f8_missileBracketTimer = FLT_EPSILON; + x1f4_missileActive = missileActive; + } + CPlayerState::EBeamId beam = gun->GetCurrentBeam(); + if (beam != x200_beam) { + x204_chargeGaugeOvershootTimer = g_tweakTargeting->GetChargeGaugeOvershootDuration(); + for (int i = 0; i < 9; ++i) { + zeus::CRelAngle baseAngle = g_tweakTargeting->GetOuterBeamSquareAngles(int(beam))[i]; + SOuterItemInfo& icon = xe0_outerBeamIconSquares[i]; + zeus::CRelAngle offshootAngleDelta = baseAngle.asRadians() - icon.x10_rotAng; + if ((i & 0x1) == 1) + offshootAngleDelta = + (baseAngle > 0.f) ? zeus::CRelAngle(-2.f * M_PIF - baseAngle) : zeus::CRelAngle(2.f * M_PIF + baseAngle); + icon.xc_offshootBaseAngle = icon.x10_rotAng; + icon.x18_offshootAngleDelta = offshootAngleDelta; + icon.x14_baseAngle = baseAngle; + } + zeus::CRelAngle baseAngle = g_tweakTargeting->GetChargeGaugeAngle(int(beam)); + float offshootAngleDelta = baseAngle.asRadians() - xc4_chargeGauge.x10_rotAng; + if ((rand() & 0x1) == 1) + offshootAngleDelta = + (offshootAngleDelta > 0.f) ? -2.f * M_PIF - offshootAngleDelta : 2.f * M_PIF + offshootAngleDelta; + xc4_chargeGauge.xc_offshootBaseAngle = xc4_chargeGauge.x10_rotAng; + xc4_chargeGauge.x18_offshootAngleDelta = offshootAngleDelta; + xc4_chargeGauge.x14_baseAngle = baseAngle; + x200_beam = beam; + x208_lockonTimer = 0.f; + } + if (gun->GetLastFireButtonStates() & 0x1) { + if (!x218_beamShot) + x210_lockFireTimer = g_tweakTargeting->GetLockFireDuration(); + x218_beamShot = true; + } else { + x218_beamShot = false; + } + if (gun->GetLastFireButtonStates() & 0x2) { + if (!x219_missileShot) + x1fc_missileBracketScaleTimer = g_tweakTargeting->GetMissileBracketScaleDuration(); + x219_missileShot = true; + } else { + x219_missileShot = false; + } + if (TCastToConstPtr point = mgr.GetObjectById(xf2_nextTargetId)) { + if (point->GetUniqueId() != x1dc_grapplePoint0) { + float tmp; + if (point->GetUniqueId() == x1de_grapplePoint1) + tmp = std::max(FLT_EPSILON, x1e4_grapplePoint1T); + else + tmp = FLT_EPSILON; + x1de_grapplePoint1 = x1dc_grapplePoint0; + x1e4_grapplePoint1T = x1e0_grapplePoint0T; + x1e0_grapplePoint0T = tmp; + x1dc_grapplePoint0 = point->GetUniqueId(); + } + } else if (x1dc_grapplePoint0 != kInvalidUniqueId) { + x1de_grapplePoint1 = x1dc_grapplePoint0; + x1e4_grapplePoint1T = x1e0_grapplePoint0T; + x1e0_grapplePoint0T = 0.f; + x1dc_grapplePoint0 = kInvalidUniqueId; + } + if (x1e0_grapplePoint0T > 0.f) + x1e0_grapplePoint0T = std::min(dt / 0.5f + x1e0_grapplePoint0T, 1.f); + if (x1e4_grapplePoint1T > 0.f) { + x1e4_grapplePoint1T = std::max(0.f, x1e4_grapplePoint1T - dt / 0.5f); + if (x1e4_grapplePoint1T == 0.f) + x1de_grapplePoint1 = kInvalidUniqueId; + } + x1f0_xrayRetAngle = + zeus::CRelAngle(zeus::degToRad(g_tweakTargeting->GetXRayRetAngleSpeed() * dt) + x1f0_xrayRetAngle); + x1ec_seekerAngle = zeus::CRelAngle(zeus::degToRad(g_tweakTargeting->GetSeekerAngleSpeed() * dt) + x1ec_seekerAngle); } -void CCompoundTargetReticle::Update(float dt, const CStateManager& mgr) -{ - float angle = x10_laggingOrientation.angleFrom(x0_leadingOrientation).asDegrees(); - float t; - if (angle < 0.1f || angle > 45.f) - t = 1.f; - else - t = std::min(1.f, g_tweakTargeting->GetAngularLagSpeed() * dt / angle); - x10_laggingOrientation = t == 1.f ? x0_leadingOrientation : - zeus::CQuaternion::slerp(x10_laggingOrientation, x0_leadingOrientation, t); - xf4_targetPos = CalculateOrbitZoneReticlePosition(mgr, false); - x100_laggingTargetPos = CalculateOrbitZoneReticlePosition(mgr, true); - UpdateCurrLockOnGroup(dt, mgr); - UpdateNextLockOnGroup(dt, mgr); - UpdateOrbitZoneGroup(dt, mgr); - EReticleState desiredState = GetDesiredReticleState(mgr); - if (desiredState != x20_prevState && x20_prevState == x24_nextState) - { - x24_nextState = desiredState; - x28_noDrawTicks = 2; - } - if (x20_prevState != x24_nextState && x28_noDrawTicks <= 0) - { - x20_prevState = x24_nextState; - float combat = false; - float scan = false; - float xray = false; - float thermal = false; - switch (x24_nextState) - { - case EReticleState::Combat: - combat = true; - break; - case EReticleState::Scan: - scan = true; - break; - case EReticleState::XRay: - xray = true; - break; - case EReticleState::Thermal: - thermal = true; - break; - default: - break; - } - if (combat) - x40_seeker.Lock(); - else - x40_seeker.Unlock(); - if (combat) - x4c_lockConfirm.Lock(); - else - x4c_lockConfirm.Unlock(); - if (combat) - x58_targetFlower.Lock(); - else - x58_targetFlower.Unlock(); - if (combat) - x64_missileBracket.Lock(); - else - x64_missileBracket.Unlock(); - if (combat) - x70_innerBeamIcon.Lock(); - else - x70_innerBeamIcon.Unlock(); - if (combat) - x7c_lockFire.Lock(); - else - x7c_lockFire.Unlock(); - if (combat) - x88_lockDagger.Lock(); - else - x88_lockDagger.Unlock(); - if (combat) - xa0_chargeTickFirst.Lock(); - else - xa0_chargeTickFirst.Unlock(); - if (xray) - xac_xrayRetRing.Lock(); - else - xac_xrayRetRing.Unlock(); - if (thermal) - xb8_thermalReticle.Lock(); - else - xb8_thermalReticle.Unlock(); - if (combat) - xc4_chargeGauge.x0_model.Lock(); - else - xc4_chargeGauge.x0_model.Unlock(); - if (!scan) - x94_grapple.Lock(); - else - x94_grapple.Unlock(); - for (SOuterItemInfo& info : xe0_outerBeamIconSquares) - { - if (combat) - info.x0_model.Lock(); - else - info.x0_model.Unlock(); - } - } - CPlayerGun* gun = mgr.GetPlayer().GetPlayerGun(); - bool fullyCharged = (gun->IsCharging() ? gun->GetChargeBeamFactor() : 0.f) >= 1.f; - if (fullyCharged != x21a_fullyCharged) - x21a_fullyCharged = fullyCharged; - if (x21a_fullyCharged) - x214_fullChargeFadeTimer = - std::min(dt / g_tweakTargeting->GetFullChargeFadeDuration() + x214_fullChargeFadeTimer, - g_tweakTargeting->GetFullChargeFadeDuration()); - else - x214_fullChargeFadeTimer = - std::max(x214_fullChargeFadeTimer - dt / g_tweakTargeting->GetFullChargeFadeDuration(), 0.f); - bool missileActive = gun->GetMissleMode() == CPlayerGun::EMissleMode::Active; - if (missileActive != x1f4_missileActive) - { - if (x1f8_missileBracketTimer != 0.f) - x1f8_missileBracketTimer = FLT_EPSILON - x1f8_missileBracketTimer; - else - x1f8_missileBracketTimer = FLT_EPSILON; - x1f4_missileActive = missileActive; - } - CPlayerState::EBeamId beam = gun->GetCurrentBeam(); - if (beam != x200_beam) - { - x204_chargeGaugeOvershootTimer = g_tweakTargeting->GetChargeGaugeOvershootDuration(); - for (int i=0 ; i<9 ; ++i) - { - zeus::CRelAngle baseAngle = g_tweakTargeting->GetOuterBeamSquareAngles(int(beam))[i]; - SOuterItemInfo& icon = xe0_outerBeamIconSquares[i]; - zeus::CRelAngle offshootAngleDelta = baseAngle.asRadians() - icon.x10_rotAng; - if ((i & 0x1) == 1) - offshootAngleDelta = (baseAngle > 0.f) ? zeus::CRelAngle(-2.f * M_PIF - baseAngle) : - zeus::CRelAngle(2.f * M_PIF + baseAngle); - icon.xc_offshootBaseAngle = icon.x10_rotAng; - icon.x18_offshootAngleDelta = offshootAngleDelta; - icon.x14_baseAngle = baseAngle; - } - zeus::CRelAngle baseAngle = g_tweakTargeting->GetChargeGaugeAngle(int(beam)); - float offshootAngleDelta = baseAngle.asRadians() - xc4_chargeGauge.x10_rotAng; - if ((rand() & 0x1) == 1) - offshootAngleDelta = (offshootAngleDelta > 0.f) ? - -2.f * M_PIF - offshootAngleDelta : 2.f * M_PIF + offshootAngleDelta; - xc4_chargeGauge.xc_offshootBaseAngle = xc4_chargeGauge.x10_rotAng; - xc4_chargeGauge.x18_offshootAngleDelta = offshootAngleDelta; - xc4_chargeGauge.x14_baseAngle = baseAngle; - x200_beam = beam; - x208_lockonTimer = 0.f; - } - if (gun->GetLastFireButtonStates() & 0x1) - { - if (!x218_beamShot) - x210_lockFireTimer = g_tweakTargeting->GetLockFireDuration(); - x218_beamShot = true; - } - else - { - x218_beamShot = false; - } - if (gun->GetLastFireButtonStates() & 0x2) - { - if (!x219_missileShot) - x1fc_missileBracketScaleTimer = g_tweakTargeting->GetMissileBracketScaleDuration(); - x219_missileShot = true; - } - else - { - x219_missileShot = false; - } - if (TCastToConstPtr point = mgr.GetObjectById(xf2_nextTargetId)) - { - if (point->GetUniqueId() != x1dc_grapplePoint0) - { - float tmp; - if (point->GetUniqueId() == x1de_grapplePoint1) - tmp = std::max(FLT_EPSILON, x1e4_grapplePoint1T); - else - tmp = FLT_EPSILON; - x1de_grapplePoint1 = x1dc_grapplePoint0; - x1e4_grapplePoint1T = x1e0_grapplePoint0T; - x1e0_grapplePoint0T = tmp; - x1dc_grapplePoint0 = point->GetUniqueId(); - } - } - else if (x1dc_grapplePoint0 != kInvalidUniqueId) - { - x1de_grapplePoint1 = x1dc_grapplePoint0; - x1e4_grapplePoint1T = x1e0_grapplePoint0T; - x1e0_grapplePoint0T = 0.f; - x1dc_grapplePoint0 = kInvalidUniqueId; - } - if (x1e0_grapplePoint0T > 0.f) - x1e0_grapplePoint0T = std::min(dt / 0.5f + x1e0_grapplePoint0T, 1.f); - if (x1e4_grapplePoint1T > 0.f) - { - x1e4_grapplePoint1T = std::max(0.f, x1e4_grapplePoint1T - dt / 0.5f); - if (x1e4_grapplePoint1T == 0.f) - x1de_grapplePoint1 = kInvalidUniqueId; - } - x1f0_xrayRetAngle = - zeus::CRelAngle(zeus::degToRad(g_tweakTargeting->GetXRayRetAngleSpeed() * dt) + x1f0_xrayRetAngle); - x1ec_seekerAngle = - zeus::CRelAngle(zeus::degToRad(g_tweakTargeting->GetSeekerAngleSpeed() * dt) + x1ec_seekerAngle); +void CTargetReticleRenderState::InterpolateWithClamp(const CTargetReticleRenderState& a, CTargetReticleRenderState& out, + const CTargetReticleRenderState& b, float t) { + t = zeus::clamp(0.f, t, 1.f); + float omt = 1.f - t; + out.x4_radiusWorld = omt * a.x4_radiusWorld + t * b.x4_radiusWorld; + out.x14_factor = omt * a.x14_factor + t * b.x14_factor; + out.x18_minVpClampScale = omt * a.x18_minVpClampScale + t * b.x18_minVpClampScale; + out.x8_positionWorld = zeus::CVector3f::lerp(a.x8_positionWorld, b.x8_positionWorld, t); + + if (t == 1.f) + out.x0_target = b.x0_target; + else if (t == 0.f) + out.x0_target = a.x0_target; + else + out.x0_target = kInvalidUniqueId; } -void CTargetReticleRenderState::InterpolateWithClamp(const CTargetReticleRenderState& a, - CTargetReticleRenderState& out, - const CTargetReticleRenderState& b, float t) -{ - t = zeus::clamp(0.f, t, 1.f); - float omt = 1.f - t; - out.x4_radiusWorld = omt * a.x4_radiusWorld + t * b.x4_radiusWorld; - out.x14_factor = omt * a.x14_factor + t * b.x14_factor; - out.x18_minVpClampScale = omt * a.x18_minVpClampScale + t * b.x18_minVpClampScale; - out.x8_positionWorld = zeus::CVector3f::lerp(a.x8_positionWorld, b.x8_positionWorld, t); - - if (t == 1.f) - out.x0_target = b.x0_target; - else if (t == 0.f) - out.x0_target = a.x0_target; - else - out.x0_target = kInvalidUniqueId; +static bool IsDamageOrbit(CPlayer::EPlayerOrbitRequest req) { + switch (req) { + case CPlayer::EPlayerOrbitRequest::Five: + case CPlayer::EPlayerOrbitRequest::ActivateOrbitSource: + case CPlayer::EPlayerOrbitRequest::ProjectileCollide: + case CPlayer::EPlayerOrbitRequest::Freeze: + case CPlayer::EPlayerOrbitRequest::DamageOnGrapple: + return true; + default: + return false; + } } -static bool IsDamageOrbit(CPlayer::EPlayerOrbitRequest req) -{ - switch (req) - { - case CPlayer::EPlayerOrbitRequest::Five: - case CPlayer::EPlayerOrbitRequest::ActivateOrbitSource: - case CPlayer::EPlayerOrbitRequest::ProjectileCollide: - case CPlayer::EPlayerOrbitRequest::Freeze: - case CPlayer::EPlayerOrbitRequest::DamageOnGrapple: - return true; - default: - return false; +void CCompoundTargetReticle::UpdateCurrLockOnGroup(float dt, const CStateManager& mgr) { + TUniqueId targetId = mgr.GetPlayer().GetOrbitTargetId(); + if (targetId != xf0_targetId) { + if (targetId != kInvalidUniqueId) { + if (TCastToConstPtr point = mgr.GetObjectById(targetId)) + CSfxManager::SfxStart(SFXui_lockon_grapple, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + else + CSfxManager::SfxStart(SFXui_lockon_poi, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); } + + if (targetId == kInvalidUniqueId) { + x12c_currGroupA = x10c_currGroupInterp; + x14c_currGroupB.SetFactor(0.f); + x16c_currGroupDur = + IsDamageOrbit(mgr.GetPlayer().GetOrbitRequest()) ? 0.65f : g_tweakTargeting->GetCurrLockOnEnterDuration(); + } else { + x12c_currGroupA = x10c_currGroupInterp; + if (xf0_targetId == kInvalidUniqueId) + x12c_currGroupA.SetTargetId(targetId); + x14c_currGroupB = CTargetReticleRenderState( + targetId, 1.f, zeus::CVector3f::skZero, 1.f, + IsGrappleTarget(targetId, mgr) ? g_tweakTargeting->GetGrappleMinClampScale() : 1.f, false); + x16c_currGroupDur = xf0_targetId == kInvalidUniqueId ? g_tweakTargeting->GetCurrLockOnExitDuration() + : g_tweakTargeting->GetCurrLockOnSwitchDuration(); + } + x170_currGroupTimer = x16c_currGroupDur; + xf0_targetId = targetId; + } + if (x170_currGroupTimer > 0.f) { + UpdateTargetParameters(x12c_currGroupA, mgr); + UpdateTargetParameters(x14c_currGroupB, mgr); + x170_currGroupTimer = std::max(0.f, x170_currGroupTimer - dt); + CTargetReticleRenderState::InterpolateWithClamp(x12c_currGroupA, x10c_currGroupInterp, x14c_currGroupB, + 1.f - x170_currGroupTimer / x16c_currGroupDur); + } else { + UpdateTargetParameters(x10c_currGroupInterp, mgr); + } + if (x1f8_missileBracketTimer != 0.f && x1f8_missileBracketTimer < g_tweakTargeting->GetMissileBracketDuration()) { + if (x1f8_missileBracketTimer < 0.f) + x1f8_missileBracketTimer = std::min(0.f, x1f8_missileBracketTimer + dt); + else + x1f8_missileBracketTimer = std::min(g_tweakTargeting->GetMissileBracketDuration(), x1f8_missileBracketTimer + dt); + } + if (x204_chargeGaugeOvershootTimer > 0.f) { + x204_chargeGaugeOvershootTimer = std::max(0.f, x204_chargeGaugeOvershootTimer - dt); + if (x204_chargeGaugeOvershootTimer == 0.f) { + for (int i = 0; i < 9; ++i) + xe0_outerBeamIconSquares[i].x10_rotAng = xe0_outerBeamIconSquares[i].x14_baseAngle; + xc4_chargeGauge.x10_rotAng = xc4_chargeGauge.x14_baseAngle; + x208_lockonTimer = FLT_EPSILON; + } else { + float offshoot = + offshoot_func(x2c_overshootOffsetHalf, x30_premultOvershootOffset, + 1.f - x204_chargeGaugeOvershootTimer / g_tweakTargeting->GetChargeGaugeOvershootDuration()); + for (int i = 0; i < 9; ++i) { + SOuterItemInfo& item = xe0_outerBeamIconSquares[i]; + item.x10_rotAng = zeus::CRelAngle(item.x18_offshootAngleDelta * offshoot + item.xc_offshootBaseAngle); + } + xc4_chargeGauge.x10_rotAng = + zeus::CRelAngle(xc4_chargeGauge.x18_offshootAngleDelta * offshoot + xc4_chargeGauge.xc_offshootBaseAngle); + } + } + if (x208_lockonTimer > 0.f && x208_lockonTimer < g_tweakTargeting->GetLockonDuration()) + x208_lockonTimer = std::min(g_tweakTargeting->GetLockonDuration(), x208_lockonTimer + dt); + if (x210_lockFireTimer > 0.f) + x210_lockFireTimer = std::max(0.f, x210_lockFireTimer - dt); + if (x1fc_missileBracketScaleTimer > 0.f) + x1fc_missileBracketScaleTimer = std::max(0.f, x1fc_missileBracketScaleTimer - dt); } -void CCompoundTargetReticle::UpdateCurrLockOnGroup(float dt, const CStateManager& mgr) -{ - TUniqueId targetId = mgr.GetPlayer().GetOrbitTargetId(); - if (targetId != xf0_targetId) - { - if (targetId != kInvalidUniqueId) - { - if (TCastToConstPtr point = mgr.GetObjectById(targetId)) - CSfxManager::SfxStart(SFXui_lockon_grapple, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - else - CSfxManager::SfxStart(SFXui_lockon_poi, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - - if (targetId == kInvalidUniqueId) - { - x12c_currGroupA = x10c_currGroupInterp; - x14c_currGroupB.SetFactor(0.f); - x16c_currGroupDur = IsDamageOrbit(mgr.GetPlayer().GetOrbitRequest()) ? 0.65f : - g_tweakTargeting->GetCurrLockOnEnterDuration(); - } - else - { - x12c_currGroupA = x10c_currGroupInterp; - if (xf0_targetId == kInvalidUniqueId) - x12c_currGroupA.SetTargetId(targetId); - x14c_currGroupB = CTargetReticleRenderState(targetId, 1.f, zeus::CVector3f::skZero, 1.f, - IsGrappleTarget(targetId, mgr) ? g_tweakTargeting->GetGrappleMinClampScale() : 1.f, false); - x16c_currGroupDur = xf0_targetId == kInvalidUniqueId ? g_tweakTargeting->GetCurrLockOnExitDuration() : - g_tweakTargeting->GetCurrLockOnSwitchDuration(); - } - x170_currGroupTimer = x16c_currGroupDur; - xf0_targetId = targetId; +void CCompoundTargetReticle::UpdateNextLockOnGroup(float dt, const CStateManager& mgr) { + TUniqueId nextTargetId = mgr.GetPlayer().GetOrbitNextTargetId(); + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan && + mgr.GetPlayer().GetOrbitTargetId() != kInvalidUniqueId) + nextTargetId = mgr.GetPlayer().GetOrbitTargetId(); + if (nextTargetId != xf2_nextTargetId) { + if (nextTargetId == kInvalidUniqueId) { + x194_nextGroupA = x174_nextGroupInterp; + x1b4_nextGroupB = CTargetReticleRenderState( + kInvalidUniqueId, 1.f, + (x20_prevState == EReticleState::XRay || x20_prevState == EReticleState::Thermal) ? x100_laggingTargetPos + : xf4_targetPos, + 0.f, 1.f, true); + x1d4_nextGroupDur = x1d8_nextGroupTimer = g_tweakTargeting->GetNextLockOnExitDuration(); + xf2_nextTargetId = nextTargetId; + } else { + x194_nextGroupA = x174_nextGroupInterp; + x1b4_nextGroupB = CTargetReticleRenderState( + nextTargetId, 1.f, zeus::CVector3f::skZero, 1.f, + IsGrappleTarget(nextTargetId, mgr) ? g_tweakTargeting->GetGrappleMinClampScale() : 1.f, true); + x1d4_nextGroupDur = x1d8_nextGroupTimer = xf2_nextTargetId == kInvalidUniqueId + ? g_tweakTargeting->GetNextLockOnEnterDuration() + : g_tweakTargeting->GetNextLockOnSwitchDuration(); + xf2_nextTargetId = nextTargetId; } - if (x170_currGroupTimer > 0.f) - { - UpdateTargetParameters(x12c_currGroupA, mgr); - UpdateTargetParameters(x14c_currGroupB, mgr); - x170_currGroupTimer = std::max(0.f, x170_currGroupTimer - dt); - CTargetReticleRenderState::InterpolateWithClamp(x12c_currGroupA, x10c_currGroupInterp, x14c_currGroupB, - 1.f - x170_currGroupTimer / x16c_currGroupDur); - } - else - { - UpdateTargetParameters(x10c_currGroupInterp, mgr); - } - if (x1f8_missileBracketTimer != 0.f && x1f8_missileBracketTimer < g_tweakTargeting->GetMissileBracketDuration()) - { - if (x1f8_missileBracketTimer < 0.f) - x1f8_missileBracketTimer = - std::min(0.f, x1f8_missileBracketTimer + dt); - else - x1f8_missileBracketTimer = - std::min(g_tweakTargeting->GetMissileBracketDuration(), x1f8_missileBracketTimer + dt); - } - if (x204_chargeGaugeOvershootTimer > 0.f) - { - x204_chargeGaugeOvershootTimer = std::max(0.f, x204_chargeGaugeOvershootTimer - dt); - if (x204_chargeGaugeOvershootTimer == 0.f) - { - for (int i=0 ; i<9 ; ++i) - xe0_outerBeamIconSquares[i].x10_rotAng = xe0_outerBeamIconSquares[i].x14_baseAngle; - xc4_chargeGauge.x10_rotAng = xc4_chargeGauge.x14_baseAngle; - x208_lockonTimer = FLT_EPSILON; - } - else - { - float offshoot = offshoot_func(x2c_overshootOffsetHalf, x30_premultOvershootOffset, - 1.f - x204_chargeGaugeOvershootTimer / - g_tweakTargeting->GetChargeGaugeOvershootDuration()); - for (int i=0 ; i<9 ; ++i) - { - SOuterItemInfo& item = xe0_outerBeamIconSquares[i]; - item.x10_rotAng = zeus::CRelAngle(item.x18_offshootAngleDelta * offshoot + item.xc_offshootBaseAngle); - } - xc4_chargeGauge.x10_rotAng = zeus::CRelAngle(xc4_chargeGauge.x18_offshootAngleDelta * offshoot + - xc4_chargeGauge.xc_offshootBaseAngle); - } - } - if (x208_lockonTimer > 0.f && x208_lockonTimer < g_tweakTargeting->GetLockonDuration()) - x208_lockonTimer = std::min(g_tweakTargeting->GetLockonDuration(), x208_lockonTimer + dt); - if (x210_lockFireTimer > 0.f) - x210_lockFireTimer = std::max(0.f, x210_lockFireTimer - dt); - if (x1fc_missileBracketScaleTimer > 0.f) - x1fc_missileBracketScaleTimer = std::max(0.f, x1fc_missileBracketScaleTimer - dt); + } + if (x1d8_nextGroupTimer > 0.f) { + UpdateTargetParameters(x194_nextGroupA, mgr); + UpdateTargetParameters(x1b4_nextGroupB, mgr); + x1d8_nextGroupTimer = std::max(0.f, x1d8_nextGroupTimer - dt); + CTargetReticleRenderState::InterpolateWithClamp(x194_nextGroupA, x174_nextGroupInterp, x1b4_nextGroupB, + 1.f - x1d8_nextGroupTimer / x1d4_nextGroupDur); + } else { + UpdateTargetParameters(x174_nextGroupInterp, mgr); + } } -void CCompoundTargetReticle::UpdateNextLockOnGroup(float dt, const CStateManager& mgr) -{ - TUniqueId nextTargetId = mgr.GetPlayer().GetOrbitNextTargetId(); - if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan && - mgr.GetPlayer().GetOrbitTargetId() != kInvalidUniqueId) - nextTargetId = mgr.GetPlayer().GetOrbitTargetId(); - if (nextTargetId != xf2_nextTargetId) - { - if (nextTargetId == kInvalidUniqueId) - { - x194_nextGroupA = x174_nextGroupInterp; - x1b4_nextGroupB = CTargetReticleRenderState(kInvalidUniqueId, 1.f, - (x20_prevState == EReticleState::XRay || x20_prevState == EReticleState::Thermal) ? - x100_laggingTargetPos : xf4_targetPos, 0.f, 1.f, true); - x1d4_nextGroupDur = x1d8_nextGroupTimer = g_tweakTargeting->GetNextLockOnExitDuration(); - xf2_nextTargetId = nextTargetId; - } - else - { - x194_nextGroupA = x174_nextGroupInterp; - x1b4_nextGroupB = CTargetReticleRenderState(nextTargetId, 1.f, zeus::CVector3f::skZero, 1.f, - IsGrappleTarget(nextTargetId, mgr) ? g_tweakTargeting->GetGrappleMinClampScale() : 1.f, true); - x1d4_nextGroupDur = x1d8_nextGroupTimer = xf2_nextTargetId == kInvalidUniqueId ? - g_tweakTargeting->GetNextLockOnEnterDuration() : - g_tweakTargeting->GetNextLockOnSwitchDuration(); - xf2_nextTargetId = nextTargetId; - } - } - if (x1d8_nextGroupTimer > 0.f) - { - UpdateTargetParameters(x194_nextGroupA, mgr); - UpdateTargetParameters(x1b4_nextGroupB, mgr); - x1d8_nextGroupTimer = std::max(0.f, x1d8_nextGroupTimer - dt); - CTargetReticleRenderState::InterpolateWithClamp(x194_nextGroupA, x174_nextGroupInterp, x1b4_nextGroupB, - 1.f - x1d8_nextGroupTimer / x1d4_nextGroupDur); - } - else - { - UpdateTargetParameters(x174_nextGroupInterp, mgr); - } +void CCompoundTargetReticle::UpdateOrbitZoneGroup(float dt, const CStateManager& mgr) { + if (xf0_targetId == kInvalidUniqueId && xf2_nextTargetId != kInvalidUniqueId) + x20c_ = std::min(1.f, 2.f * dt + x20c_); + else + x20c_ = std::max(0.f, x20c_ - 2.f * dt); + if (mgr.GetPlayer().IsShowingCrosshairs() && + mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) + x1e8_crosshairsScale = std::min(1.f, dt / g_tweakTargeting->GetCrosshairsScaleDuration() + x1e8_crosshairsScale); + else + x1e8_crosshairsScale = std::max(0.f, x1e8_crosshairsScale - dt / g_tweakTargeting->GetCrosshairsScaleDuration()); } -void CCompoundTargetReticle::UpdateOrbitZoneGroup(float dt, const CStateManager& mgr) -{ - if (xf0_targetId == kInvalidUniqueId && xf2_nextTargetId != kInvalidUniqueId) - x20c_ = std::min(1.f, 2.f * dt + x20c_); - else - x20c_ = std::max(0.f, x20c_ - 2.f * dt); - if (mgr.GetPlayer().IsShowingCrosshairs() && - mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - x1e8_crosshairsScale = - std::min(1.f, dt / g_tweakTargeting->GetCrosshairsScaleDuration() + x1e8_crosshairsScale); - else - x1e8_crosshairsScale = - std::max(0.f, x1e8_crosshairsScale - dt / g_tweakTargeting->GetCrosshairsScaleDuration()); -} - -void CCompoundTargetReticle::Draw(const CStateManager& mgr, bool hideLockon) const -{ - if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && - !mgr.GetCameraManager()->IsInCinematicCamera()) - { - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - CGraphics::SetViewPointMatrix(camXf); - if (!hideLockon) - { - DrawCurrLockOnGroup(camXf.basis, mgr); - DrawNextLockOnGroup(camXf.basis, mgr); - DrawOrbitZoneGroup(camXf.basis, mgr); - } - DrawGrappleGroup(camXf.basis, mgr, hideLockon); +void CCompoundTargetReticle::Draw(const CStateManager& mgr, bool hideLockon) const { + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && + !mgr.GetCameraManager()->IsInCinematicCamera()) { + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + CGraphics::SetViewPointMatrix(camXf); + if (!hideLockon) { + DrawCurrLockOnGroup(camXf.basis, mgr); + DrawNextLockOnGroup(camXf.basis, mgr); + DrawOrbitZoneGroup(camXf.basis, mgr); } - if (x28_noDrawTicks > 0) - --x28_noDrawTicks; + DrawGrappleGroup(camXf.basis, mgr, hideLockon); + } + if (x28_noDrawTicks > 0) + --x28_noDrawTicks; } void CCompoundTargetReticle::DrawGrapplePoint(const CScriptGrapplePoint& point, float t, const CStateManager& mgr, - const zeus::CMatrix3f& rot, bool zEqual) const -{ - zeus::CVector3f orbitPos = point.GetOrbitPosition(mgr); - zeus::CColor color; - if (point.GetGrappleParameters().GetLockSwingTurn()) - color = g_tweakTargeting->GetLockedGrapplePointSelectColor(); - else - color = g_tweakTargeting->GetGrapplePointSelectColor(); - color = zeus::CColor::lerp(g_tweakTargeting->GetGrapplePointColor(), color, t); - zeus::CMatrix3f scale( - CalculateClampedScale(orbitPos, 1.f, g_tweakTargeting->GetGrappleClampMin(), - g_tweakTargeting->GetGrappleClampMax(), mgr) * - ((1.f - t) * g_tweakTargeting->GetGrappleScale() + t * g_tweakTargeting->GetGrappleSelectScale())); - zeus::CTransform modelXf(rot * scale, orbitPos); + const zeus::CMatrix3f& rot, bool zEqual) const { + zeus::CVector3f orbitPos = point.GetOrbitPosition(mgr); + zeus::CColor color; + if (point.GetGrappleParameters().GetLockSwingTurn()) + color = g_tweakTargeting->GetLockedGrapplePointSelectColor(); + else + color = g_tweakTargeting->GetGrapplePointSelectColor(); + color = zeus::CColor::lerp(g_tweakTargeting->GetGrapplePointColor(), color, t); + zeus::CMatrix3f scale( + CalculateClampedScale(orbitPos, 1.f, g_tweakTargeting->GetGrappleClampMin(), + g_tweakTargeting->GetGrappleClampMax(), mgr) * + ((1.f - t) * g_tweakTargeting->GetGrappleScale() + t * g_tweakTargeting->GetGrappleSelectScale())); + zeus::CTransform modelXf(rot * scale, orbitPos); + CGraphics::SetModelMatrix(modelXf); + CModelFlags flags(7, 0, 0, color); + x94_grapple->Draw(flags); +} + +void CCompoundTargetReticle::DrawGrappleGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr, + bool hideLockon) const { + if (x28_noDrawTicks > 0) + return; + + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam) && x94_grapple.IsLoaded() && + x20_prevState != EReticleState::Scan) { + if (hideLockon) { + for (const CEntity* ent : mgr.GetAllObjectList()) { + if (TCastToConstPtr point = ent) { + if (point->GetActive()) { + if (point->GetAreaIdAlways() != kInvalidAreaId) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(point->GetAreaIdAlways()); + CGameArea::EOcclusionState occState = + area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; + if (occState != CGameArea::EOcclusionState::Visible) + continue; + } + float t = 0.f; + if (point->GetUniqueId() == x1dc_grapplePoint0) + t = x1e0_grapplePoint0T; + else if (point->GetUniqueId() == x1de_grapplePoint1) + t = x1e4_grapplePoint1T; + if (std::fabs(t) < 0.00001f) + DrawGrapplePoint(*point, t, mgr, rot, true); + } + } + } + } else { + TCastToConstPtr point0 = mgr.GetObjectById(x1dc_grapplePoint0); + TCastToConstPtr point1 = mgr.GetObjectById(x1de_grapplePoint1); + for (int i = 0; i < 2; ++i) { + const CScriptGrapplePoint* point = i == 0 ? point0.GetPtr() : point1.GetPtr(); + float t = i == 0 ? x1e0_grapplePoint0T : x1e4_grapplePoint1T; + if (point) + DrawGrapplePoint(*point, t, mgr, rot, false); + } + } + } +} + +void CCompoundTargetReticle::DrawCurrLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr) const { + if (x28_noDrawTicks > 0) + return; + if (x1e0_grapplePoint0T + x1e4_grapplePoint1T > 0 || x10c_currGroupInterp.GetFactor() == 0.f) + return; + + float lockBreakAlpha = x10c_currGroupInterp.GetFactor(); + float visorFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); + bool lockConfirm = false; + bool lockReticule = false; + switch (x20_prevState) { + case EReticleState::Combat: + lockConfirm = true; + lockReticule = true; + break; + case EReticleState::Scan: + lockConfirm = true; + break; + default: + break; + } + + zeus::CMatrix3f lockBreakXf; + zeus::CColor lockBreakColor = zeus::CColor::skClear; + if (IsDamageOrbit(mgr.GetPlayer().GetOrbitRequest()) && x14c_currGroupB.GetFactor() == 0.f) { + zeus::CMatrix3f lockBreakRM; + for (int i = 0; i < 4; ++i) { + int a = rand() % 9; + auto b = std::div(a, 3); + lockBreakRM[b.rem][b.quot] += rand() / float(RAND_MAX) - 0.5f; + } + lockBreakXf = lockBreakRM.transposed(); + if (x10c_currGroupInterp.GetFactor() > 0.8f) + lockBreakColor = zeus::CColor(1.f, (x10c_currGroupInterp.GetFactor() - 0.8f) * 0.3f / 0.2f); + lockBreakAlpha = x10c_currGroupInterp.GetFactor() > 0.75f + ? 1.f + : std::max(0.f, (x10c_currGroupInterp.GetFactor() - 0.55f) / 0.2f); + } + + if (lockConfirm && x4c_lockConfirm.IsLoaded()) { + zeus::CMatrix3f scale(CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), + x10c_currGroupInterp.GetRadiusWorld(), + x10c_currGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetLockConfirmClampMin(), + g_tweakTargeting->GetLockConfirmClampMax(), mgr) * + g_tweakTargeting->GetLockConfirmScale() / x10c_currGroupInterp.GetFactor()); + zeus::CTransform modelXf(lockBreakXf * (rot * zeus::CMatrix3f::RotateY(x1ec_seekerAngle) * scale), + x10c_currGroupInterp.GetTargetPositionWorld()); CGraphics::SetModelMatrix(modelXf); - CModelFlags flags(7, 0, 0, color); - x94_grapple->Draw(flags); -} + zeus::CColor color = g_tweakTargeting->GetLockConfirmColor(); + color.a() *= lockBreakAlpha; + CModelFlags flags(7, 0, 0, lockBreakColor + color); + x4c_lockConfirm->Draw(flags); + } -void CCompoundTargetReticle::DrawGrappleGroup(const zeus::CMatrix3f& rot, - const CStateManager& mgr, bool hideLockon) const -{ - if (x28_noDrawTicks > 0) - return; - - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam) && - x94_grapple.IsLoaded() && x20_prevState != EReticleState::Scan) - { - if (hideLockon) - { - for (const CEntity* ent : mgr.GetAllObjectList()) - { - if (TCastToConstPtr point = ent) - { - if (point->GetActive()) - { - if (point->GetAreaIdAlways() != kInvalidAreaId) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(point->GetAreaIdAlways()); - CGameArea::EOcclusionState occState = area->IsPostConstructed() ? - area->GetOcclusionState() : - CGameArea::EOcclusionState::Occluded; - if (occState != CGameArea::EOcclusionState::Visible) - continue; - } - float t = 0.f; - if (point->GetUniqueId() == x1dc_grapplePoint0) - t = x1e0_grapplePoint0T; - else if (point->GetUniqueId() == x1de_grapplePoint1) - t = x1e4_grapplePoint1T; - if (std::fabs(t) < 0.00001f) - DrawGrapplePoint(*point, t, mgr, rot, true); - } - } - } - } - else - { - TCastToConstPtr point0 = mgr.GetObjectById(x1dc_grapplePoint0); - TCastToConstPtr point1 = mgr.GetObjectById(x1de_grapplePoint1); - for (int i=0 ; i<2 ; ++i) - { - const CScriptGrapplePoint* point = i == 0 ? point0.GetPtr() : point1.GetPtr(); - float t = i == 0 ? x1e0_grapplePoint0T : x1e4_grapplePoint1T; - if (point) - DrawGrapplePoint(*point, t, mgr, rot, false); - } - } + if (lockReticule) { + if (x58_targetFlower.IsLoaded()) { + zeus::CMatrix3f scale(CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), + x10c_currGroupInterp.GetRadiusWorld(), + x10c_currGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetTargetFlowerClampMin(), + g_tweakTargeting->GetTargetFlowerClampMax(), mgr) * + g_tweakTargeting->GetTargetFlowerScale() / lockBreakAlpha); + zeus::CTransform modelXf(lockBreakXf * (rot * zeus::CMatrix3f::RotateY(x1f0_xrayRetAngle) * scale), + x10c_currGroupInterp.GetTargetPositionWorld()); + CGraphics::SetModelMatrix(modelXf); + zeus::CColor color = g_tweakTargeting->GetTargetFlowerColor(); + color.a() *= lockBreakAlpha * visorFactor; + CModelFlags flags(7, 0, 0, lockBreakColor + color); + x58_targetFlower->Draw(flags); } -} - -void CCompoundTargetReticle::DrawCurrLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr) const -{ - if (x28_noDrawTicks > 0) - return; - if (x1e0_grapplePoint0T + x1e4_grapplePoint1T > 0 || x10c_currGroupInterp.GetFactor() == 0.f) - return; - - float lockBreakAlpha = x10c_currGroupInterp.GetFactor(); - float visorFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); - bool lockConfirm = false; - bool lockReticule = false; - switch (x20_prevState) - { - case EReticleState::Combat: - lockConfirm = true; - lockReticule = true; - break; - case EReticleState::Scan: - lockConfirm = true; - break; - default: - break; + if (x1f8_missileBracketTimer != 0.f && x64_missileBracket.IsLoaded()) { + float t = std::fabs((x1fc_missileBracketScaleTimer - 0.5f * g_tweakTargeting->GetMissileBracketScaleDuration()) / + 0.5f * g_tweakTargeting->GetMissileBracketScaleDuration()); + float tscale = ((1.f - t) * g_tweakTargeting->GetMissileBracketScaleEnd() + + t * g_tweakTargeting->GetMissileBracketScaleStart()); + zeus::CMatrix3f scale(CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), + x10c_currGroupInterp.GetRadiusWorld(), + x10c_currGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetMissileBracketClampMin(), + g_tweakTargeting->GetMissileBracketClampMax(), mgr) * + std::fabs(x1f8_missileBracketTimer) / g_tweakTargeting->GetMissileBracketDuration() * + tscale / x10c_currGroupInterp.GetFactor()); + for (int i = 0; i < 4; ++i) { + zeus::CTransform modelXf( + lockBreakXf * rot * zeus::CMatrix3f(zeus::CVector3f{i < 2 ? 1.f : -1.f, 1.f, i & 0x1 ? 1.f : -1.f}) * scale, + x10c_currGroupInterp.GetTargetPositionWorld()); + CGraphics::SetModelMatrix(modelXf); + zeus::CColor color = g_tweakTargeting->GetMissileBracketColor(); + color.a() *= lockBreakAlpha * visorFactor; + CModelFlags flags(7, 0, 0, lockBreakColor + color); + x64_missileBracket->Draw(flags); + } } - - zeus::CMatrix3f lockBreakXf; - zeus::CColor lockBreakColor = zeus::CColor::skClear; - if (IsDamageOrbit(mgr.GetPlayer().GetOrbitRequest()) && x14c_currGroupB.GetFactor() == 0.f) - { - zeus::CMatrix3f lockBreakRM; - for (int i=0 ; i<4 ; ++i) - { - int a = rand() % 9; - auto b = std::div(a, 3); - lockBreakRM[b.rem][b.quot] += rand() / float(RAND_MAX) - 0.5f; - } - lockBreakXf = lockBreakRM.transposed(); - if (x10c_currGroupInterp.GetFactor() > 0.8f) - lockBreakColor = zeus::CColor(1.f, (x10c_currGroupInterp.GetFactor() - 0.8f) * 0.3f / 0.2f); - lockBreakAlpha = x10c_currGroupInterp.GetFactor() > 0.75f ? - 1.f : std::max(0.f, (x10c_currGroupInterp.GetFactor() - 0.55f) / 0.2f); - } - - if (lockConfirm && x4c_lockConfirm.IsLoaded()) - { - zeus::CMatrix3f scale( - CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), - x10c_currGroupInterp.GetRadiusWorld(), - x10c_currGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetLockConfirmClampMin(), - g_tweakTargeting->GetLockConfirmClampMax(), mgr) * - g_tweakTargeting->GetLockConfirmScale() / x10c_currGroupInterp.GetFactor()); - zeus::CTransform modelXf(lockBreakXf * (rot * zeus::CMatrix3f::RotateY(x1ec_seekerAngle) * scale), + zeus::CMatrix3f scale(CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), + x10c_currGroupInterp.GetRadiusWorld(), + x10c_currGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetChargeGaugeClampMin(), + g_tweakTargeting->GetChargeGaugeClampMax(), mgr) * + 1.f / x10c_currGroupInterp.GetFactor() * g_tweakTargeting->GetOuterBeamSquaresScale()); + zeus::CMatrix3f outerBeamXf = rot * scale; + for (int i = 0; i < 9; ++i) { + const SOuterItemInfo& info = xe0_outerBeamIconSquares[i]; + if (info.x0_model.IsLoaded()) { + zeus::CTransform modelXf(lockBreakXf * outerBeamXf * zeus::CMatrix3f::RotateY(info.x10_rotAng), x10c_currGroupInterp.GetTargetPositionWorld()); CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetLockConfirmColor(); - color.a() *= lockBreakAlpha; + zeus::CColor color = g_tweakTargeting->GetOuterBeamSquareColor(); + color.a() *= lockBreakAlpha * visorFactor; CModelFlags flags(7, 0, 0, lockBreakColor + color); - x4c_lockConfirm->Draw(flags); + info.x0_model->Draw(flags); + } } + if (xc4_chargeGauge.x0_model.IsLoaded()) { + zeus::CMatrix3f scale(CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), + x10c_currGroupInterp.GetRadiusWorld(), + x10c_currGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetChargeGaugeClampMin(), + g_tweakTargeting->GetChargeGaugeClampMax(), mgr) * + g_tweakTargeting->GetChargeGaugeScale() / x10c_currGroupInterp.GetFactor()); + zeus::CMatrix3f chargeGaugeXf = rot * scale * zeus::CMatrix3f::RotateY(xc4_chargeGauge.x10_rotAng); + float pulseT = std::fabs(std::fmod(CGraphics::GetSecondsMod900(), g_tweakTargeting->GetChargeGaugePulsePeriod())); + zeus::CColor gaugeColor = + zeus::CColor::lerp(g_tweakTargeting->GetChargeGaugeNonFullColor(), + zeus::CColor::lerp(g_tweakTargeting->GetChargeGaugePulseColorHigh(), + g_tweakTargeting->GetChargeGaugePulseColorLow(), + pulseT < 0.5f * g_tweakTargeting->GetChargeGaugePulsePeriod() + ? pulseT / (0.5f * g_tweakTargeting->GetChargeGaugePulsePeriod()) + : (g_tweakTargeting->GetChargeGaugePulsePeriod() - pulseT) / + (0.5f * g_tweakTargeting->GetChargeGaugePulsePeriod())), + x214_fullChargeFadeTimer / g_tweakTargeting->GetFullChargeFadeDuration()); + zeus::CTransform modelXf(lockBreakXf * chargeGaugeXf, x10c_currGroupInterp.GetTargetPositionWorld()); + CGraphics::SetModelMatrix(modelXf); + zeus::CColor color = gaugeColor; + color.a() *= lockBreakAlpha * visorFactor; + CModelFlags flags(7, 0, 0, lockBreakColor + color); + xc4_chargeGauge.x0_model->Draw(flags); - if (lockReticule) - { - if (x58_targetFlower.IsLoaded()) - { - zeus::CMatrix3f scale( - CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), - x10c_currGroupInterp.GetRadiusWorld(), - x10c_currGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetTargetFlowerClampMin(), - g_tweakTargeting->GetTargetFlowerClampMax(), mgr) * - g_tweakTargeting->GetTargetFlowerScale() / lockBreakAlpha); - zeus::CTransform modelXf(lockBreakXf * (rot * zeus::CMatrix3f::RotateY(x1f0_xrayRetAngle) * scale), - x10c_currGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetTargetFlowerColor(); - color.a() *= lockBreakAlpha * visorFactor; - CModelFlags flags(7, 0, 0, lockBreakColor + color); - x58_targetFlower->Draw(flags); - } - if (x1f8_missileBracketTimer != 0.f && x64_missileBracket.IsLoaded()) - { - float t = std::fabs((x1fc_missileBracketScaleTimer - 0.5f * - g_tweakTargeting->GetMissileBracketScaleDuration()) - / 0.5f * g_tweakTargeting->GetMissileBracketScaleDuration()); - float tscale = ((1.f - t) * g_tweakTargeting->GetMissileBracketScaleEnd() + - t * g_tweakTargeting->GetMissileBracketScaleStart()); - zeus::CMatrix3f scale( - CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), - x10c_currGroupInterp.GetRadiusWorld(), - x10c_currGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetMissileBracketClampMin(), - g_tweakTargeting->GetMissileBracketClampMax(), mgr) * - std::fabs(x1f8_missileBracketTimer) / g_tweakTargeting->GetMissileBracketDuration() * - tscale / x10c_currGroupInterp.GetFactor()); - for (int i=0 ; i<4 ; ++i) - { - zeus::CTransform modelXf( - lockBreakXf * rot * - zeus::CMatrix3f(zeus::CVector3f{i < 2 ? 1.f : -1.f, 1.f, i & 0x1 ? 1.f : -1.f}) * scale, - x10c_currGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetMissileBracketColor(); - color.a() *= lockBreakAlpha * visorFactor; - CModelFlags flags(7, 0, 0, lockBreakColor + color); - x64_missileBracket->Draw(flags); - } - } - zeus::CMatrix3f scale( - CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), - x10c_currGroupInterp.GetRadiusWorld(), - x10c_currGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetChargeGaugeClampMin(), - g_tweakTargeting->GetChargeGaugeClampMax(), mgr) * - 1.f / x10c_currGroupInterp.GetFactor() * g_tweakTargeting->GetOuterBeamSquaresScale()); - zeus::CMatrix3f outerBeamXf = rot * scale; - for (int i=0 ; i<9 ; ++i) - { - const SOuterItemInfo& info = xe0_outerBeamIconSquares[i]; - if (info.x0_model.IsLoaded()) - { - zeus::CTransform modelXf(lockBreakXf * outerBeamXf * zeus::CMatrix3f::RotateY(info.x10_rotAng), - x10c_currGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetOuterBeamSquareColor(); - color.a() *= lockBreakAlpha * visorFactor; - CModelFlags flags(7, 0, 0, lockBreakColor + color); - info.x0_model->Draw(flags); - } - } - if (xc4_chargeGauge.x0_model.IsLoaded()) - { - zeus::CMatrix3f scale( - CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), - x10c_currGroupInterp.GetRadiusWorld(), - x10c_currGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetChargeGaugeClampMin(), - g_tweakTargeting->GetChargeGaugeClampMax(), mgr) * - g_tweakTargeting->GetChargeGaugeScale() / x10c_currGroupInterp.GetFactor()); - zeus::CMatrix3f chargeGaugeXf = rot * scale * zeus::CMatrix3f::RotateY(xc4_chargeGauge.x10_rotAng); - float pulseT = std::fabs(std::fmod(CGraphics::GetSecondsMod900(), - g_tweakTargeting->GetChargeGaugePulsePeriod())); - zeus::CColor gaugeColor = zeus::CColor::lerp(g_tweakTargeting->GetChargeGaugeNonFullColor(), - zeus::CColor::lerp(g_tweakTargeting->GetChargeGaugePulseColorHigh(), - g_tweakTargeting->GetChargeGaugePulseColorLow(), - pulseT < 0.5f * g_tweakTargeting->GetChargeGaugePulsePeriod() ? - pulseT / (0.5f * g_tweakTargeting->GetChargeGaugePulsePeriod()) : - (g_tweakTargeting->GetChargeGaugePulsePeriod() - pulseT) / - (0.5f * g_tweakTargeting->GetChargeGaugePulsePeriod())), - x214_fullChargeFadeTimer / g_tweakTargeting->GetFullChargeFadeDuration()); - zeus::CTransform modelXf(lockBreakXf * chargeGaugeXf, x10c_currGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = gaugeColor; - color.a() *= lockBreakAlpha * visorFactor; - CModelFlags flags(7, 0, 0, lockBreakColor + color); - xc4_chargeGauge.x0_model->Draw(flags); - - if (xa0_chargeTickFirst.IsLoaded()) - { - const CPlayerGun* gun = mgr.GetPlayer().GetPlayerGun(); - int numTicks = int(g_tweakTargeting->GetChargeTickCount() * - (gun->IsCharging() ? gun->GetChargeBeamFactor() : 0.f)); - for (int i=0 ; iDraw(flags); - modelXf.rotateLocalY(g_tweakTargeting->GetChargeTickAnglePitch()); - CGraphics::SetModelMatrix(modelXf); - } - } - } - if (x208_lockonTimer > 0.f && x70_innerBeamIcon.IsLoaded()) - { - const zeus::CColor* iconColor; - switch (x200_beam) - { - case CPlayerState::EBeamId::Power: - iconColor = &g_tweakTargeting->GetInnerBeamColorPower(); - break; - case CPlayerState::EBeamId::Ice: - iconColor = &g_tweakTargeting->GetInnerBeamColorIce(); - break; - case CPlayerState::EBeamId::Wave: - iconColor = &g_tweakTargeting->GetInnerBeamColorWave(); - break; - default: - iconColor = &g_tweakTargeting->GetInnerBeamColorPlasma(); - break; - } - zeus::CMatrix3f scale( - CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), - x10c_currGroupInterp.GetRadiusWorld(), - x10c_currGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetInnerBeamClampMin(), - g_tweakTargeting->GetInnerBeamClampMax(), mgr) * - g_tweakTargeting->GetInnerBeamScale() * (x208_lockonTimer / g_tweakTargeting->GetLockonDuration()) / - x10c_currGroupInterp.GetFactor()); - zeus::CTransform modelXf(lockBreakXf * rot * scale, x10c_currGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = *iconColor; - color.a() *= lockBreakAlpha * visorFactor; - CModelFlags flags(7, 0, 0, lockBreakColor + color); - x70_innerBeamIcon->Draw(flags); - } - if (x210_lockFireTimer > 0.f && x7c_lockFire.IsLoaded()) - { - zeus::CMatrix3f scale( - CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), - x10c_currGroupInterp.GetRadiusWorld(), - x10c_currGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetLockFireClampMin(), - g_tweakTargeting->GetLockFireClampMax(), mgr) * - g_tweakTargeting->GetLockFireScale() / x10c_currGroupInterp.GetFactor()); - zeus::CTransform modelXf(lockBreakXf * rot * scale * zeus::CMatrix3f::RotateY(x1f0_xrayRetAngle), - x10c_currGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetLockFireColor(); - color.a() *= visorFactor * lockBreakAlpha * (x210_lockFireTimer / g_tweakTargeting->GetLockFireDuration()); - CModelFlags flags(7, 0, 0, lockBreakColor + color); - x7c_lockFire->Draw(flags); - } - if (x208_lockonTimer > 0.f && x88_lockDagger.IsLoaded()) - { - float t = std::fabs((x210_lockFireTimer - 0.5f * g_tweakTargeting->GetLockFireDuration()) / - 0.5f * g_tweakTargeting->GetLockFireDuration()); - float tscale = ((1.f - t) * g_tweakTargeting->GetLockDaggerScaleEnd() + - t * g_tweakTargeting->GetLockDaggerScaleStart()); - zeus::CMatrix3f scale( - CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), - x10c_currGroupInterp.GetRadiusWorld(), - x10c_currGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetLockDaggerClampMin(), - g_tweakTargeting->GetLockDaggerClampMax(), mgr) * tscale * - (x208_lockonTimer / g_tweakTargeting->GetLockonDuration()) / x10c_currGroupInterp.GetFactor()); - zeus::CMatrix3f lockDaggerXf = rot * scale; - for (int i=0 ; i<3 ; ++i) - { - float ang; - switch (i) - { - case 0: - ang = g_tweakTargeting->GetLockDaggerAngle0(); - break; - case 1: - ang = g_tweakTargeting->GetLockDaggerAngle1(); - break; - default: - ang = g_tweakTargeting->GetLockDaggerAngle2(); - break; - } - zeus::CTransform modelXf(lockBreakXf * lockDaggerXf * zeus::CMatrix3f::RotateY(ang), - x10c_currGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetLockDaggerColor(); - color.a() *= visorFactor * lockBreakAlpha; - CModelFlags flags(7, 0, 0, lockBreakColor + color); - x88_lockDagger->Draw(flags); - } + if (xa0_chargeTickFirst.IsLoaded()) { + const CPlayerGun* gun = mgr.GetPlayer().GetPlayerGun(); + int numTicks = + int(g_tweakTargeting->GetChargeTickCount() * (gun->IsCharging() ? gun->GetChargeBeamFactor() : 0.f)); + for (int i = 0; i < numTicks; ++i) { + CModelFlags flags(7, 0, 0, lockBreakColor + color); + xa0_chargeTickFirst->Draw(flags); + modelXf.rotateLocalY(g_tweakTargeting->GetChargeTickAnglePitch()); + CGraphics::SetModelMatrix(modelXf); } + } } -} - -void CCompoundTargetReticle::DrawNextLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr) const -{ - if (x28_noDrawTicks > 0) - return; - - zeus::CVector3f position = x174_nextGroupInterp.GetTargetPositionWorld(); - float visorFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); - - bool scanRet = false; - bool xrayRet = false; - bool thermalRet = false; - switch (x20_prevState) - { - case EReticleState::Scan: - scanRet = true; + if (x208_lockonTimer > 0.f && x70_innerBeamIcon.IsLoaded()) { + const zeus::CColor* iconColor; + switch (x200_beam) { + case CPlayerState::EBeamId::Power: + iconColor = &g_tweakTargeting->GetInnerBeamColorPower(); break; - case EReticleState::XRay: - xrayRet = true; + case CPlayerState::EBeamId::Ice: + iconColor = &g_tweakTargeting->GetInnerBeamColorIce(); break; - case EReticleState::Thermal: - thermalRet = true; + case CPlayerState::EBeamId::Wave: + iconColor = &g_tweakTargeting->GetInnerBeamColorWave(); break; - default: + default: + iconColor = &g_tweakTargeting->GetInnerBeamColorPlasma(); break; + } + zeus::CMatrix3f scale( + CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), x10c_currGroupInterp.GetRadiusWorld(), + x10c_currGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetInnerBeamClampMin(), + g_tweakTargeting->GetInnerBeamClampMax(), mgr) * + g_tweakTargeting->GetInnerBeamScale() * (x208_lockonTimer / g_tweakTargeting->GetLockonDuration()) / + x10c_currGroupInterp.GetFactor()); + zeus::CTransform modelXf(lockBreakXf * rot * scale, x10c_currGroupInterp.GetTargetPositionWorld()); + CGraphics::SetModelMatrix(modelXf); + zeus::CColor color = *iconColor; + color.a() *= lockBreakAlpha * visorFactor; + CModelFlags flags(7, 0, 0, lockBreakColor + color); + x70_innerBeamIcon->Draw(flags); } - - if (!xrayRet && x174_nextGroupInterp.GetFactor() > 0.f && x40_seeker.IsLoaded()) - { - zeus::CMatrix3f scale( - CalculateClampedScale(position, x174_nextGroupInterp.GetRadiusWorld(), - x174_nextGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetSeekerClampMin(), - g_tweakTargeting->GetSeekerClampMax(), mgr) * - g_tweakTargeting->GetSeekerScale()); - zeus::CTransform modelXf(rot * zeus::CMatrix3f::RotateY(x1ec_seekerAngle) * scale, - x174_nextGroupInterp.GetTargetPositionWorld()); + if (x210_lockFireTimer > 0.f && x7c_lockFire.IsLoaded()) { + zeus::CMatrix3f scale(CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), + x10c_currGroupInterp.GetRadiusWorld(), + x10c_currGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetLockFireClampMin(), + g_tweakTargeting->GetLockFireClampMax(), mgr) * + g_tweakTargeting->GetLockFireScale() / x10c_currGroupInterp.GetFactor()); + zeus::CTransform modelXf(lockBreakXf * rot * scale * zeus::CMatrix3f::RotateY(x1f0_xrayRetAngle), + x10c_currGroupInterp.GetTargetPositionWorld()); + CGraphics::SetModelMatrix(modelXf); + zeus::CColor color = g_tweakTargeting->GetLockFireColor(); + color.a() *= visorFactor * lockBreakAlpha * (x210_lockFireTimer / g_tweakTargeting->GetLockFireDuration()); + CModelFlags flags(7, 0, 0, lockBreakColor + color); + x7c_lockFire->Draw(flags); + } + if (x208_lockonTimer > 0.f && x88_lockDagger.IsLoaded()) { + float t = std::fabs((x210_lockFireTimer - 0.5f * g_tweakTargeting->GetLockFireDuration()) / 0.5f * + g_tweakTargeting->GetLockFireDuration()); + float tscale = + ((1.f - t) * g_tweakTargeting->GetLockDaggerScaleEnd() + t * g_tweakTargeting->GetLockDaggerScaleStart()); + zeus::CMatrix3f scale( + CalculateClampedScale(x10c_currGroupInterp.GetTargetPositionWorld(), x10c_currGroupInterp.GetRadiusWorld(), + x10c_currGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetLockDaggerClampMin(), + g_tweakTargeting->GetLockDaggerClampMax(), mgr) * + tscale * (x208_lockonTimer / g_tweakTargeting->GetLockonDuration()) / x10c_currGroupInterp.GetFactor()); + zeus::CMatrix3f lockDaggerXf = rot * scale; + for (int i = 0; i < 3; ++i) { + float ang; + switch (i) { + case 0: + ang = g_tweakTargeting->GetLockDaggerAngle0(); + break; + case 1: + ang = g_tweakTargeting->GetLockDaggerAngle1(); + break; + default: + ang = g_tweakTargeting->GetLockDaggerAngle2(); + break; + } + zeus::CTransform modelXf(lockBreakXf * lockDaggerXf * zeus::CMatrix3f::RotateY(ang), + x10c_currGroupInterp.GetTargetPositionWorld()); CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetSeekerColor(); - color.a() *= x174_nextGroupInterp.GetFactor(); - CModelFlags flags(7, 0, 0, color); - x40_seeker->Draw(flags); - } - - if (xrayRet && xac_xrayRetRing.IsLoaded()) - { - zeus::CMatrix3f scale( - CalculateClampedScale(position, x174_nextGroupInterp.GetRadiusWorld(), - x174_nextGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetReticuleClampMin(), - g_tweakTargeting->GetReticuleClampMax(), mgr) * - g_tweakTargeting->GetReticuleScale()); - zeus::CTransform modelXf(rot * scale * zeus::CMatrix3f::RotateY(x1f0_xrayRetAngle), - x174_nextGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetXRayRetRingColor(); - color.a() *= visorFactor; - CModelFlags flags(7, 0, 0, color); - xac_xrayRetRing->Draw(flags); - } - - if (thermalRet && xb8_thermalReticle.IsLoaded()) - { - zeus::CMatrix3f scale( - CalculateClampedScale(position, x174_nextGroupInterp.GetRadiusWorld(), - x174_nextGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetReticuleClampMin(), - g_tweakTargeting->GetReticuleClampMax(), mgr) * - g_tweakTargeting->GetReticuleScale()); - zeus::CTransform modelXf(rot * scale, x174_nextGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetThermalReticuleColor(); - color.a() *= visorFactor; - CModelFlags flags(7, 0, 0, color); - xb8_thermalReticle->Draw(flags); - } - - if (scanRet && visorFactor > 0.f) - { - float factor = visorFactor * x174_nextGroupInterp.GetFactor(); - zeus::CMatrix3f scale( - CalculateClampedScale(position, x174_nextGroupInterp.GetRadiusWorld(), - x174_nextGroupInterp.GetMinViewportClampScale() * - g_tweakTargeting->GetScanTargetClampMin(), - g_tweakTargeting->GetScanTargetClampMax(), mgr) * - (1.f / factor)); - zeus::CTransform modelXf(rot * scale, x174_nextGroupInterp.GetTargetPositionWorld()); - CGraphics::SetModelMatrix(modelXf); - // compare, GX_LESS, no update - float alpha = 0.5f * factor; - zeus::CColor color = g_tweakGuiColors->GetScanReticuleColor(); - color.a() *= alpha; - for (int i=0 ; i<2 ; ++i) - { - float lineWidth = i ? 2.5f : 1.f; - auto& rend = *m_scanRetRenderer.m_lineRenderers[i]; - rend.Reset(); - rend.AddVertex({-0.5f, 0.f, 0.f}, color, lineWidth); - rend.AddVertex({-20.5f, 0.f, 0.f}, color, lineWidth); - rend.AddVertex({0.5f, 0.f, 0.f}, color, lineWidth); - rend.AddVertex({20.5f, 0.f, 0.f}, color, lineWidth); - rend.AddVertex({0.f, 0.f, -0.5f}, color, lineWidth); - rend.AddVertex({0.f, 0.f, -20.5f}, color, lineWidth); - rend.AddVertex({0.f, 0.f, 0.5f}, color, lineWidth); - rend.AddVertex({0.f, 0.f, 20.5f}, color, lineWidth); - rend.Render(); - - for (int j=0 ; j<4 ; ++j) - { - float xSign = j < 2 ? -1.f : 1.f; - float zSign = (j & 0x1) ? -1.f : 1.f; - // begin line strip - auto& rend = *m_scanRetRenderer.m_stripRenderers[i][j]; - rend.Reset(); - rend.AddVertex({0.5f * xSign, 0.f, 0.1f * zSign}, color, lineWidth); - rend.AddVertex({0.5f * xSign, 0.f, 0.35f * zSign}, color, lineWidth); - rend.AddVertex({0.35f * xSign, 0.f, 0.5f * zSign}, color, lineWidth); - rend.AddVertex({0.1f * xSign, 0.f, 0.5f * zSign}, color, lineWidth); - rend.Render(); - } - } + zeus::CColor color = g_tweakTargeting->GetLockDaggerColor(); + color.a() *= visorFactor * lockBreakAlpha; + CModelFlags flags(7, 0, 0, lockBreakColor + color); + x88_lockDagger->Draw(flags); + } } + } } -void CCompoundTargetReticle::DrawOrbitZoneGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr) const -{ - if (x28_noDrawTicks > 0) - return; +void CCompoundTargetReticle::DrawNextLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr) const { + if (x28_noDrawTicks > 0) + return; - if (x1e8_crosshairsScale > 0.f && x34_crosshairs.IsLoaded()) - { - CGraphics::SetModelMatrix(zeus::CTransform(rot, xf4_targetPos) * zeus::CTransform::Scale(x1e8_crosshairsScale)); - zeus::CColor color = g_tweakTargeting->GetCrosshairsColor(); - color.a() *= x1e8_crosshairsScale; - CModelFlags flags(7, 0, 0, color); - x34_crosshairs->Draw(flags); + zeus::CVector3f position = x174_nextGroupInterp.GetTargetPositionWorld(); + float visorFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); + + bool scanRet = false; + bool xrayRet = false; + bool thermalRet = false; + switch (x20_prevState) { + case EReticleState::Scan: + scanRet = true; + break; + case EReticleState::XRay: + xrayRet = true; + break; + case EReticleState::Thermal: + thermalRet = true; + break; + default: + break; + } + + if (!xrayRet && x174_nextGroupInterp.GetFactor() > 0.f && x40_seeker.IsLoaded()) { + zeus::CMatrix3f scale( + CalculateClampedScale(position, x174_nextGroupInterp.GetRadiusWorld(), + x174_nextGroupInterp.GetMinViewportClampScale() * g_tweakTargeting->GetSeekerClampMin(), + g_tweakTargeting->GetSeekerClampMax(), mgr) * + g_tweakTargeting->GetSeekerScale()); + zeus::CTransform modelXf(rot * zeus::CMatrix3f::RotateY(x1ec_seekerAngle) * scale, + x174_nextGroupInterp.GetTargetPositionWorld()); + CGraphics::SetModelMatrix(modelXf); + zeus::CColor color = g_tweakTargeting->GetSeekerColor(); + color.a() *= x174_nextGroupInterp.GetFactor(); + CModelFlags flags(7, 0, 0, color); + x40_seeker->Draw(flags); + } + + if (xrayRet && xac_xrayRetRing.IsLoaded()) { + zeus::CMatrix3f scale( + CalculateClampedScale(position, x174_nextGroupInterp.GetRadiusWorld(), + x174_nextGroupInterp.GetMinViewportClampScale() * g_tweakTargeting->GetReticuleClampMin(), + g_tweakTargeting->GetReticuleClampMax(), mgr) * + g_tweakTargeting->GetReticuleScale()); + zeus::CTransform modelXf(rot * scale * zeus::CMatrix3f::RotateY(x1f0_xrayRetAngle), + x174_nextGroupInterp.GetTargetPositionWorld()); + CGraphics::SetModelMatrix(modelXf); + zeus::CColor color = g_tweakTargeting->GetXRayRetRingColor(); + color.a() *= visorFactor; + CModelFlags flags(7, 0, 0, color); + xac_xrayRetRing->Draw(flags); + } + + if (thermalRet && xb8_thermalReticle.IsLoaded()) { + zeus::CMatrix3f scale( + CalculateClampedScale(position, x174_nextGroupInterp.GetRadiusWorld(), + x174_nextGroupInterp.GetMinViewportClampScale() * g_tweakTargeting->GetReticuleClampMin(), + g_tweakTargeting->GetReticuleClampMax(), mgr) * + g_tweakTargeting->GetReticuleScale()); + zeus::CTransform modelXf(rot * scale, x174_nextGroupInterp.GetTargetPositionWorld()); + CGraphics::SetModelMatrix(modelXf); + zeus::CColor color = g_tweakTargeting->GetThermalReticuleColor(); + color.a() *= visorFactor; + CModelFlags flags(7, 0, 0, color); + xb8_thermalReticle->Draw(flags); + } + + if (scanRet && visorFactor > 0.f) { + float factor = visorFactor * x174_nextGroupInterp.GetFactor(); + zeus::CMatrix3f scale(CalculateClampedScale(position, x174_nextGroupInterp.GetRadiusWorld(), + x174_nextGroupInterp.GetMinViewportClampScale() * + g_tweakTargeting->GetScanTargetClampMin(), + g_tweakTargeting->GetScanTargetClampMax(), mgr) * + (1.f / factor)); + zeus::CTransform modelXf(rot * scale, x174_nextGroupInterp.GetTargetPositionWorld()); + CGraphics::SetModelMatrix(modelXf); + // compare, GX_LESS, no update + float alpha = 0.5f * factor; + zeus::CColor color = g_tweakGuiColors->GetScanReticuleColor(); + color.a() *= alpha; + for (int i = 0; i < 2; ++i) { + float lineWidth = i ? 2.5f : 1.f; + auto& rend = *m_scanRetRenderer.m_lineRenderers[i]; + rend.Reset(); + rend.AddVertex({-0.5f, 0.f, 0.f}, color, lineWidth); + rend.AddVertex({-20.5f, 0.f, 0.f}, color, lineWidth); + rend.AddVertex({0.5f, 0.f, 0.f}, color, lineWidth); + rend.AddVertex({20.5f, 0.f, 0.f}, color, lineWidth); + rend.AddVertex({0.f, 0.f, -0.5f}, color, lineWidth); + rend.AddVertex({0.f, 0.f, -20.5f}, color, lineWidth); + rend.AddVertex({0.f, 0.f, 0.5f}, color, lineWidth); + rend.AddVertex({0.f, 0.f, 20.5f}, color, lineWidth); + rend.Render(); + + for (int j = 0; j < 4; ++j) { + float xSign = j < 2 ? -1.f : 1.f; + float zSign = (j & 0x1) ? -1.f : 1.f; + // begin line strip + auto& rend = *m_scanRetRenderer.m_stripRenderers[i][j]; + rend.Reset(); + rend.AddVertex({0.5f * xSign, 0.f, 0.1f * zSign}, color, lineWidth); + rend.AddVertex({0.5f * xSign, 0.f, 0.35f * zSign}, color, lineWidth); + rend.AddVertex({0.35f * xSign, 0.f, 0.5f * zSign}, color, lineWidth); + rend.AddVertex({0.1f * xSign, 0.f, 0.5f * zSign}, color, lineWidth); + rend.Render(); + } } + } } -void CCompoundTargetReticle::UpdateTargetParameters(CTargetReticleRenderState& state, const CStateManager& mgr) -{ - if (auto act = TCastToConstPtr(mgr.GetAllObjectList().GetObjectById(state.GetTargetId()))) - { - state.SetRadiusWorld(CalculateRadiusWorld(*act, mgr)); - state.SetTargetPositionWorld(CalculatePositionWorld(*act, mgr)); - } - else if (state.GetIsOrbitZoneIdlePosition()) - { - state.SetRadiusWorld(1.f); - state.SetTargetPositionWorld((x20_prevState == EReticleState::XRay || x20_prevState == EReticleState::Thermal) ? - x100_laggingTargetPos : xf4_targetPos); - } +void CCompoundTargetReticle::DrawOrbitZoneGroup(const zeus::CMatrix3f& rot, const CStateManager& mgr) const { + if (x28_noDrawTicks > 0) + return; + + if (x1e8_crosshairsScale > 0.f && x34_crosshairs.IsLoaded()) { + CGraphics::SetModelMatrix(zeus::CTransform(rot, xf4_targetPos) * zeus::CTransform::Scale(x1e8_crosshairsScale)); + zeus::CColor color = g_tweakTargeting->GetCrosshairsColor(); + color.a() *= x1e8_crosshairsScale; + CModelFlags flags(7, 0, 0, color); + x34_crosshairs->Draw(flags); + } } -float CCompoundTargetReticle::CalculateRadiusWorld(const CActor& act, const CStateManager& mgr) const -{ - auto tb = act.GetTouchBounds(); - zeus::CAABox aabb = tb ? *tb : zeus::CAABox(act.GetAimPosition(mgr, 0.f), act.GetAimPosition(mgr, 0.f)); - - float radius; - zeus::CVector3f delta = aabb.max - aabb.min; - switch (g_tweakTargeting->GetTargetRadiusMode()) - { - case 0: - { - radius = std::min(delta.x(), std::min(delta.y(), delta.z())) * 0.5f; - break; - } - case 1: - { - radius = std::max(delta.x(), std::max(delta.y(), delta.z())) * 0.5f; - break; - } - default: - { - radius = (delta.x() + delta.y() + delta.z()) / 6.f; - break; - } - } - - return radius > 0.f ? radius : 1.f; +void CCompoundTargetReticle::UpdateTargetParameters(CTargetReticleRenderState& state, const CStateManager& mgr) { + if (auto act = TCastToConstPtr(mgr.GetAllObjectList().GetObjectById(state.GetTargetId()))) { + state.SetRadiusWorld(CalculateRadiusWorld(*act, mgr)); + state.SetTargetPositionWorld(CalculatePositionWorld(*act, mgr)); + } else if (state.GetIsOrbitZoneIdlePosition()) { + state.SetRadiusWorld(1.f); + state.SetTargetPositionWorld((x20_prevState == EReticleState::XRay || x20_prevState == EReticleState::Thermal) + ? x100_laggingTargetPos + : xf4_targetPos); + } } -zeus::CVector3f CCompoundTargetReticle::CalculatePositionWorld(const CActor& act, const CStateManager& mgr) const -{ - if (x20_prevState == EReticleState::Scan) - return act.GetOrbitPosition(mgr); - return act.GetAimPosition(mgr, 0.f); +float CCompoundTargetReticle::CalculateRadiusWorld(const CActor& act, const CStateManager& mgr) const { + auto tb = act.GetTouchBounds(); + zeus::CAABox aabb = tb ? *tb : zeus::CAABox(act.GetAimPosition(mgr, 0.f), act.GetAimPosition(mgr, 0.f)); + + float radius; + zeus::CVector3f delta = aabb.max - aabb.min; + switch (g_tweakTargeting->GetTargetRadiusMode()) { + case 0: { + radius = std::min(delta.x(), std::min(delta.y(), delta.z())) * 0.5f; + break; + } + case 1: { + radius = std::max(delta.x(), std::max(delta.y(), delta.z())) * 0.5f; + break; + } + default: { + radius = (delta.x() + delta.y() + delta.z()) / 6.f; + break; + } + } + + return radius > 0.f ? radius : 1.f; } -zeus::CVector3f -CCompoundTargetReticle::CalculateOrbitZoneReticlePosition(const CStateManager& mgr, bool lag) const -{ - const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - float distMul = 224.f / float(g_tweakPlayer->GetOrbitScreenBoxHalfExtentY(0)) / - std::tan(zeus::degToRad(0.5f * curCam->GetFov())); - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - zeus::CVector3f lookDir = camXf.basis[1]; - if (lag) - lookDir = x10_laggingOrientation.transform(lookDir); - return lookDir * distMul + camXf.origin; +zeus::CVector3f CCompoundTargetReticle::CalculatePositionWorld(const CActor& act, const CStateManager& mgr) const { + if (x20_prevState == EReticleState::Scan) + return act.GetOrbitPosition(mgr); + return act.GetAimPosition(mgr, 0.f); } -bool CCompoundTargetReticle::IsGrappleTarget(TUniqueId uid, const CStateManager& mgr) const -{ - return TCastToConstPtr(mgr.GetAllObjectList().GetObjectById(uid)).operator bool(); +zeus::CVector3f CCompoundTargetReticle::CalculateOrbitZoneReticlePosition(const CStateManager& mgr, bool lag) const { + const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + float distMul = + 224.f / float(g_tweakPlayer->GetOrbitScreenBoxHalfExtentY(0)) / std::tan(zeus::degToRad(0.5f * curCam->GetFov())); + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + zeus::CVector3f lookDir = camXf.basis[1]; + if (lag) + lookDir = x10_laggingOrientation.transform(lookDir); + return lookDir * distMul + camXf.origin; } -float CCompoundTargetReticle::CalculateClampedScale(const zeus::CVector3f& pos, float scale, - float clampMin, float clampMax, - const CStateManager& mgr) -{ - const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - zeus::CVector3f viewPos = cam->GetTransform().transposeRotate(pos - cam->GetTransform().origin); - viewPos = zeus::CVector3f(viewPos.x(), viewPos.z(), -viewPos.y()); - float realX = cam->GetPerspectiveMatrix().multiplyOneOverW(viewPos).x(); - float offsetX = cam->GetPerspectiveMatrix().multiplyOneOverW(viewPos + zeus::CVector3f(scale, 0.f, 0.f)).x(); - float unclampedX = (offsetX - realX) * 640; - return zeus::clamp(clampMin, unclampedX, clampMax) / unclampedX * scale; +bool CCompoundTargetReticle::IsGrappleTarget(TUniqueId uid, const CStateManager& mgr) const { + return TCastToConstPtr(mgr.GetAllObjectList().GetObjectById(uid)).operator bool(); } -void CCompoundTargetReticle::Touch() -{ - if (x34_crosshairs.IsLoaded()) - x34_crosshairs->Touch(0); - if (x40_seeker.IsLoaded()) - x40_seeker->Touch(0); - if (x4c_lockConfirm.IsLoaded()) - x4c_lockConfirm->Touch(0); - if (x58_targetFlower.IsLoaded()) - x58_targetFlower->Touch(0); - if (x64_missileBracket.IsLoaded()) - x64_missileBracket->Touch(0); - if (x70_innerBeamIcon.IsLoaded()) - x70_innerBeamIcon->Touch(0); - if (x7c_lockFire.IsLoaded()) - x7c_lockFire->Touch(0); - if (x88_lockDagger.IsLoaded()) - x88_lockDagger->Touch(0); - if (x94_grapple.IsLoaded()) - x94_grapple->Touch(0); - if (xa0_chargeTickFirst.IsLoaded()) - xa0_chargeTickFirst->Touch(0); - if (xac_xrayRetRing.IsLoaded()) - xac_xrayRetRing->Touch(0); - if (xb8_thermalReticle.IsLoaded()) - xb8_thermalReticle->Touch(0); - if (xc4_chargeGauge.x0_model.IsLoaded()) - xc4_chargeGauge.x0_model->Touch(0); - for (SOuterItemInfo& info : xe0_outerBeamIconSquares) - if (info.x0_model.IsLoaded()) - info.x0_model->Touch(0); +float CCompoundTargetReticle::CalculateClampedScale(const zeus::CVector3f& pos, float scale, float clampMin, + float clampMax, const CStateManager& mgr) { + const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + zeus::CVector3f viewPos = cam->GetTransform().transposeRotate(pos - cam->GetTransform().origin); + viewPos = zeus::CVector3f(viewPos.x(), viewPos.z(), -viewPos.y()); + float realX = cam->GetPerspectiveMatrix().multiplyOneOverW(viewPos).x(); + float offsetX = cam->GetPerspectiveMatrix().multiplyOneOverW(viewPos + zeus::CVector3f(scale, 0.f, 0.f)).x(); + float unclampedX = (offsetX - realX) * 640; + return zeus::clamp(clampMin, unclampedX, clampMax) / unclampedX * scale; } +void CCompoundTargetReticle::Touch() { + if (x34_crosshairs.IsLoaded()) + x34_crosshairs->Touch(0); + if (x40_seeker.IsLoaded()) + x40_seeker->Touch(0); + if (x4c_lockConfirm.IsLoaded()) + x4c_lockConfirm->Touch(0); + if (x58_targetFlower.IsLoaded()) + x58_targetFlower->Touch(0); + if (x64_missileBracket.IsLoaded()) + x64_missileBracket->Touch(0); + if (x70_innerBeamIcon.IsLoaded()) + x70_innerBeamIcon->Touch(0); + if (x7c_lockFire.IsLoaded()) + x7c_lockFire->Touch(0); + if (x88_lockDagger.IsLoaded()) + x88_lockDagger->Touch(0); + if (x94_grapple.IsLoaded()) + x94_grapple->Touch(0); + if (xa0_chargeTickFirst.IsLoaded()) + xa0_chargeTickFirst->Touch(0); + if (xac_xrayRetRing.IsLoaded()) + xac_xrayRetRing->Touch(0); + if (xb8_thermalReticle.IsLoaded()) + xb8_thermalReticle->Touch(0); + if (xc4_chargeGauge.x0_model.IsLoaded()) + xc4_chargeGauge.x0_model->Touch(0); + for (SOuterItemInfo& info : xe0_outerBeamIconSquares) + if (info.x0_model.IsLoaded()) + info.x0_model->Touch(0); } + +} // namespace urde diff --git a/Runtime/GuiSys/CCompoundTargetReticle.hpp b/Runtime/GuiSys/CCompoundTargetReticle.hpp index ad490cb5c..5ba95df1e 100644 --- a/Runtime/GuiSys/CCompoundTargetReticle.hpp +++ b/Runtime/GuiSys/CCompoundTargetReticle.hpp @@ -6,182 +6,167 @@ #include "Graphics/CLineRenderer.hpp" #include "CPlayerState.hpp" -namespace urde -{ +namespace urde { class CActor; class CModel; class CStateManager; class CScriptGrapplePoint; -class CTargetReticleRenderState -{ - TUniqueId x0_target; - float x4_radiusWorld; - zeus::CVector3f x8_positionWorld; - float x14_factor; - float x18_minVpClampScale; - bool x1c_orbitZoneIdlePosition; +class CTargetReticleRenderState { + TUniqueId x0_target; + float x4_radiusWorld; + zeus::CVector3f x8_positionWorld; + float x14_factor; + float x18_minVpClampScale; + bool x1c_orbitZoneIdlePosition; public: + static const CTargetReticleRenderState skZeroRenderState; - static const CTargetReticleRenderState skZeroRenderState; - - CTargetReticleRenderState(TUniqueId target, float radiusWorld, - const zeus::CVector3f& positionWorld, float factor, - float minVpClampScale, bool orbitZoneIdlePosition) - : x0_target(target), x4_radiusWorld(radiusWorld), x8_positionWorld(positionWorld), - x14_factor(factor), x18_minVpClampScale(minVpClampScale), - x1c_orbitZoneIdlePosition(orbitZoneIdlePosition) - {} - void SetTargetId(TUniqueId id) { x0_target = id; } - void SetFactor(float f) { x14_factor = f; } - void SetIsOrbitZoneIdlePosition(bool b) { x1c_orbitZoneIdlePosition = b; } - float GetMinViewportClampScale() const { return x18_minVpClampScale; } - float GetFactor() const { return x14_factor; } - float GetRadiusWorld() const { return x4_radiusWorld; } - const zeus::CVector3f& GetTargetPositionWorld() const { return x8_positionWorld; } - bool GetIsOrbitZoneIdlePosition() const { return x1c_orbitZoneIdlePosition; } - void SetTargetPositionWorld(const zeus::CVector3f& pos) { x8_positionWorld = pos; } - void SetRadiusWorld(float r) { x4_radiusWorld = r; } - TUniqueId GetTargetId() const { return x0_target; } - void SetMinViewportClampScale(float s) { x18_minVpClampScale = s; } - static void InterpolateWithClamp(const CTargetReticleRenderState& a, CTargetReticleRenderState& out, - const CTargetReticleRenderState& b, float t); + CTargetReticleRenderState(TUniqueId target, float radiusWorld, const zeus::CVector3f& positionWorld, float factor, + float minVpClampScale, bool orbitZoneIdlePosition) + : x0_target(target) + , x4_radiusWorld(radiusWorld) + , x8_positionWorld(positionWorld) + , x14_factor(factor) + , x18_minVpClampScale(minVpClampScale) + , x1c_orbitZoneIdlePosition(orbitZoneIdlePosition) {} + void SetTargetId(TUniqueId id) { x0_target = id; } + void SetFactor(float f) { x14_factor = f; } + void SetIsOrbitZoneIdlePosition(bool b) { x1c_orbitZoneIdlePosition = b; } + float GetMinViewportClampScale() const { return x18_minVpClampScale; } + float GetFactor() const { return x14_factor; } + float GetRadiusWorld() const { return x4_radiusWorld; } + const zeus::CVector3f& GetTargetPositionWorld() const { return x8_positionWorld; } + bool GetIsOrbitZoneIdlePosition() const { return x1c_orbitZoneIdlePosition; } + void SetTargetPositionWorld(const zeus::CVector3f& pos) { x8_positionWorld = pos; } + void SetRadiusWorld(float r) { x4_radiusWorld = r; } + TUniqueId GetTargetId() const { return x0_target; } + void SetMinViewportClampScale(float s) { x18_minVpClampScale = s; } + static void InterpolateWithClamp(const CTargetReticleRenderState& a, CTargetReticleRenderState& out, + const CTargetReticleRenderState& b, float t); }; -class CCompoundTargetReticle -{ +class CCompoundTargetReticle { public: - struct SOuterItemInfo - { - TCachedToken x0_model; - float xc_offshootBaseAngle = 0.f; - float x10_rotAng = 0.f; - float x14_baseAngle = 0.f; - float x18_offshootAngleDelta = 0.f; - SOuterItemInfo(const char*); - }; + struct SOuterItemInfo { + TCachedToken x0_model; + float xc_offshootBaseAngle = 0.f; + float x10_rotAng = 0.f; + float x14_baseAngle = 0.f; + float x18_offshootAngleDelta = 0.f; + SOuterItemInfo(const char*); + }; private: + enum class EReticleState { Combat, Scan, XRay, Thermal, Four, Unspecified }; - enum class EReticleState - { - Combat, - Scan, - XRay, - Thermal, - Four, - Unspecified - }; + static constexpr const char* skCrosshairsReticleAssetName = "CMDL_Crosshairs"; + static constexpr const char* skOrbitZoneReticleAssetName = "CMDL_OrbitZone"; + static constexpr const char* skSeekerAssetName = "CMDL_Seeker"; + static constexpr const char* skLockConfirmAssetName = "CMDL_LockConfirm"; + static constexpr const char* skTargetFlowerAssetName = "CMDL_TargetFlower"; + static constexpr const char* skMissileBracketAssetName = "CMDL_MissileBracket"; + static constexpr const char* skChargeGaugeAssetName = "CMDL_ChargeGauge"; + static constexpr const char* skChargeBeamTickAssetName = "CMDL_ChargeTickFirst"; + static constexpr const char* skOuterBeamIconSquareNameBase = "CMDL_BeamSquare"; + static constexpr const char* skInnerBeamIconName = "CMDL_InnerBeamIcon"; + static constexpr const char* skLockFireAssetName = "CMDL_LockFIre"; + static constexpr const char* skLockDaggerAssetName = "CMDL_LockDagger0"; + static constexpr const char* skGrappleReticleAssetName = "CMDL_Grapple"; + static constexpr const char* skXRayRingModelName = "CMDL_XRayRetRing"; + static constexpr const char* skThermalReticleAssetName = "CMDL_ThermalRet"; + static constexpr const char* skOrbitPointAssetName = "CMDL_OrbitPoint"; + zeus::CQuaternion x0_leadingOrientation; + zeus::CQuaternion x10_laggingOrientation; + EReticleState x20_prevState = EReticleState::Unspecified; + EReticleState x24_nextState = EReticleState::Unspecified; + mutable u32 x28_noDrawTicks = 0; + float x2c_overshootOffsetHalf; + float x30_premultOvershootOffset; + TCachedToken x34_crosshairs; + TCachedToken x40_seeker; + TCachedToken x4c_lockConfirm; + TCachedToken x58_targetFlower; + TCachedToken x64_missileBracket; + TCachedToken x70_innerBeamIcon; + TCachedToken x7c_lockFire; + TCachedToken x88_lockDagger; + TCachedToken x94_grapple; + TCachedToken xa0_chargeTickFirst; + TCachedToken xac_xrayRetRing; + TCachedToken xb8_thermalReticle; + SOuterItemInfo xc4_chargeGauge; + std::vector xe0_outerBeamIconSquares; + TUniqueId xf0_targetId; + TUniqueId xf2_nextTargetId; + zeus::CVector3f xf4_targetPos; + zeus::CVector3f x100_laggingTargetPos; + CTargetReticleRenderState x10c_currGroupInterp = CTargetReticleRenderState::skZeroRenderState; + CTargetReticleRenderState x12c_currGroupA = CTargetReticleRenderState::skZeroRenderState; + CTargetReticleRenderState x14c_currGroupB = CTargetReticleRenderState::skZeroRenderState; + float x16c_currGroupDur = 0.f; + float x170_currGroupTimer = 0.f; + CTargetReticleRenderState x174_nextGroupInterp = CTargetReticleRenderState::skZeroRenderState; + CTargetReticleRenderState x194_nextGroupA = CTargetReticleRenderState::skZeroRenderState; + CTargetReticleRenderState x1b4_nextGroupB = CTargetReticleRenderState::skZeroRenderState; + float x1d4_nextGroupDur = 0.f; + float x1d8_nextGroupTimer = 0.f; + TUniqueId x1dc_grapplePoint0 = kInvalidUniqueId; + TUniqueId x1de_grapplePoint1 = kInvalidUniqueId; + float x1e0_grapplePoint0T = 0.f; + float x1e4_grapplePoint1T = 0.f; + float x1e8_crosshairsScale = 0.f; + float x1ec_seekerAngle = 0.f; + float x1f0_xrayRetAngle = 0.f; + bool x1f4_missileActive = false; + float x1f8_missileBracketTimer = 0.f; + float x1fc_missileBracketScaleTimer = 0.f; + CPlayerState::EBeamId x200_beam = CPlayerState::EBeamId::Power; + float x204_chargeGaugeOvershootTimer = 0.f; + float x208_lockonTimer; + float x20c_ = 0.f; + float x210_lockFireTimer = 0.f; + float x214_fullChargeFadeTimer = 0.f; + bool x218_beamShot = false; + bool x219_missileShot = false; + bool x21a_fullyCharged = false; + u8 x21b_ = 0; + u32 x21c_; + u32 x220_; + u32 x228_; - static constexpr const char* skCrosshairsReticleAssetName = "CMDL_Crosshairs"; - static constexpr const char* skOrbitZoneReticleAssetName = "CMDL_OrbitZone"; - static constexpr const char* skSeekerAssetName = "CMDL_Seeker"; - static constexpr const char* skLockConfirmAssetName = "CMDL_LockConfirm"; - static constexpr const char* skTargetFlowerAssetName = "CMDL_TargetFlower"; - static constexpr const char* skMissileBracketAssetName = "CMDL_MissileBracket"; - static constexpr const char* skChargeGaugeAssetName = "CMDL_ChargeGauge"; - static constexpr const char* skChargeBeamTickAssetName = "CMDL_ChargeTickFirst"; - static constexpr const char* skOuterBeamIconSquareNameBase = "CMDL_BeamSquare"; - static constexpr const char* skInnerBeamIconName = "CMDL_InnerBeamIcon"; - static constexpr const char* skLockFireAssetName = "CMDL_LockFIre"; - static constexpr const char* skLockDaggerAssetName = "CMDL_LockDagger0"; - static constexpr const char* skGrappleReticleAssetName = "CMDL_Grapple"; - static constexpr const char* skXRayRingModelName = "CMDL_XRayRetRing"; - static constexpr const char* skThermalReticleAssetName = "CMDL_ThermalRet"; - static constexpr const char* skOrbitPointAssetName = "CMDL_OrbitPoint"; - zeus::CQuaternion x0_leadingOrientation; - zeus::CQuaternion x10_laggingOrientation; - EReticleState x20_prevState = EReticleState::Unspecified; - EReticleState x24_nextState = EReticleState::Unspecified; - mutable u32 x28_noDrawTicks = 0; - float x2c_overshootOffsetHalf; - float x30_premultOvershootOffset; - TCachedToken x34_crosshairs; - TCachedToken x40_seeker; - TCachedToken x4c_lockConfirm; - TCachedToken x58_targetFlower; - TCachedToken x64_missileBracket; - TCachedToken x70_innerBeamIcon; - TCachedToken x7c_lockFire; - TCachedToken x88_lockDagger; - TCachedToken x94_grapple; - TCachedToken xa0_chargeTickFirst; - TCachedToken xac_xrayRetRing; - TCachedToken xb8_thermalReticle; - SOuterItemInfo xc4_chargeGauge; - std::vector xe0_outerBeamIconSquares; - TUniqueId xf0_targetId; - TUniqueId xf2_nextTargetId; - zeus::CVector3f xf4_targetPos; - zeus::CVector3f x100_laggingTargetPos; - CTargetReticleRenderState x10c_currGroupInterp = CTargetReticleRenderState::skZeroRenderState; - CTargetReticleRenderState x12c_currGroupA = CTargetReticleRenderState::skZeroRenderState; - CTargetReticleRenderState x14c_currGroupB = CTargetReticleRenderState::skZeroRenderState; - float x16c_currGroupDur = 0.f; - float x170_currGroupTimer = 0.f; - CTargetReticleRenderState x174_nextGroupInterp = CTargetReticleRenderState::skZeroRenderState; - CTargetReticleRenderState x194_nextGroupA = CTargetReticleRenderState::skZeroRenderState; - CTargetReticleRenderState x1b4_nextGroupB = CTargetReticleRenderState::skZeroRenderState; - float x1d4_nextGroupDur = 0.f; - float x1d8_nextGroupTimer = 0.f; - TUniqueId x1dc_grapplePoint0 = kInvalidUniqueId; - TUniqueId x1de_grapplePoint1 = kInvalidUniqueId; - float x1e0_grapplePoint0T = 0.f; - float x1e4_grapplePoint1T = 0.f; - float x1e8_crosshairsScale = 0.f; - float x1ec_seekerAngle = 0.f; - float x1f0_xrayRetAngle = 0.f; - bool x1f4_missileActive = false; - float x1f8_missileBracketTimer = 0.f; - float x1fc_missileBracketScaleTimer = 0.f; - CPlayerState::EBeamId x200_beam = CPlayerState::EBeamId::Power; - float x204_chargeGaugeOvershootTimer = 0.f; - float x208_lockonTimer; - float x20c_ = 0.f; - float x210_lockFireTimer = 0.f; - float x214_fullChargeFadeTimer = 0.f; - bool x218_beamShot = false; - bool x219_missileShot = false; - bool x21a_fullyCharged = false; - u8 x21b_ = 0; - u32 x21c_; - u32 x220_; - u32 x228_; + struct SScanReticuleRenderer { + std::experimental::optional m_lineRenderers[2]; + std::experimental::optional m_stripRenderers[2][4]; + SScanReticuleRenderer(); + }; + mutable SScanReticuleRenderer m_scanRetRenderer; - struct SScanReticuleRenderer - { - std::experimental::optional m_lineRenderers[2]; - std::experimental::optional m_stripRenderers[2][4]; - SScanReticuleRenderer(); - }; - mutable SScanReticuleRenderer m_scanRetRenderer; - - void DrawGrapplePoint(const CScriptGrapplePoint& point, float t, const CStateManager& mgr, - const zeus::CMatrix3f& rot, bool zEqual) const; + void DrawGrapplePoint(const CScriptGrapplePoint& point, float t, const CStateManager& mgr, const zeus::CMatrix3f& rot, + bool zEqual) const; public: - CCompoundTargetReticle(const CStateManager&); + CCompoundTargetReticle(const CStateManager&); - void SetLeadingOrientation(const zeus::CQuaternion& o) { x0_leadingOrientation = o; } - bool CheckLoadComplete() { return true; } - EReticleState GetDesiredReticleState(const CStateManager&) const; - void Update(float, const CStateManager&); - void UpdateCurrLockOnGroup(float, const CStateManager&); - void UpdateNextLockOnGroup(float, const CStateManager&); - void UpdateOrbitZoneGroup(float, const CStateManager&); - void Draw(const CStateManager&, bool hideLockon) const; - void DrawGrappleGroup(const zeus::CMatrix3f& rot, const CStateManager&, bool) const; - void DrawCurrLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager&) const; - void DrawNextLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager&) const; - void DrawOrbitZoneGroup(const zeus::CMatrix3f& rot, const CStateManager&) const; - void UpdateTargetParameters(CTargetReticleRenderState&, const CStateManager&); - float CalculateRadiusWorld(const CActor&, const CStateManager&) const; - zeus::CVector3f CalculatePositionWorld(const CActor&, const CStateManager&) const; - zeus::CVector3f CalculateOrbitZoneReticlePosition(const CStateManager& mgr, bool lag) const; - bool IsGrappleTarget(TUniqueId, const CStateManager&) const; - static float CalculateClampedScale(const zeus::CVector3f&, float, float, float, const CStateManager&); - void Touch(); + void SetLeadingOrientation(const zeus::CQuaternion& o) { x0_leadingOrientation = o; } + bool CheckLoadComplete() { return true; } + EReticleState GetDesiredReticleState(const CStateManager&) const; + void Update(float, const CStateManager&); + void UpdateCurrLockOnGroup(float, const CStateManager&); + void UpdateNextLockOnGroup(float, const CStateManager&); + void UpdateOrbitZoneGroup(float, const CStateManager&); + void Draw(const CStateManager&, bool hideLockon) const; + void DrawGrappleGroup(const zeus::CMatrix3f& rot, const CStateManager&, bool) const; + void DrawCurrLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager&) const; + void DrawNextLockOnGroup(const zeus::CMatrix3f& rot, const CStateManager&) const; + void DrawOrbitZoneGroup(const zeus::CMatrix3f& rot, const CStateManager&) const; + void UpdateTargetParameters(CTargetReticleRenderState&, const CStateManager&); + float CalculateRadiusWorld(const CActor&, const CStateManager&) const; + zeus::CVector3f CalculatePositionWorld(const CActor&, const CStateManager&) const; + zeus::CVector3f CalculateOrbitZoneReticlePosition(const CStateManager& mgr, bool lag) const; + bool IsGrappleTarget(TUniqueId, const CStateManager&) const; + static float CalculateClampedScale(const zeus::CVector3f&, float, float, float, const CStateManager&); + void Touch(); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CConsoleOutputWindow.cpp b/Runtime/GuiSys/CConsoleOutputWindow.cpp index f547af5c3..ad782eb42 100644 --- a/Runtime/GuiSys/CConsoleOutputWindow.cpp +++ b/Runtime/GuiSys/CConsoleOutputWindow.cpp @@ -1,21 +1,14 @@ #include "CConsoleOutputWindow.hpp" #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { -CConsoleOutputWindow::CConsoleOutputWindow(int, float, float) -: CIOWin("Console Output Window") -{ +CConsoleOutputWindow::CConsoleOutputWindow(int, float, float) : CIOWin("Console Output Window") {} + +CIOWin::EMessageReturn CConsoleOutputWindow::OnMessage(const CArchitectureMessage&, CArchitectureQueue&) { + return EMessageReturn::Normal; } -CIOWin::EMessageReturn CConsoleOutputWindow::OnMessage(const CArchitectureMessage&, CArchitectureQueue&) -{ - return EMessageReturn::Normal; -} +void CConsoleOutputWindow::Draw() const {} -void CConsoleOutputWindow::Draw() const -{ -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CConsoleOutputWindow.hpp b/Runtime/GuiSys/CConsoleOutputWindow.hpp index ca190461f..df6fc6234 100644 --- a/Runtime/GuiSys/CConsoleOutputWindow.hpp +++ b/Runtime/GuiSys/CConsoleOutputWindow.hpp @@ -2,16 +2,13 @@ #include "CIOWin.hpp" -namespace urde -{ +namespace urde { -class CConsoleOutputWindow : public CIOWin -{ +class CConsoleOutputWindow : public CIOWin { public: - CConsoleOutputWindow(int, float, float); - EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); - void Draw() const; + CConsoleOutputWindow(int, float, float); + EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); + void Draw() const; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CDrawStringOptions.hpp b/Runtime/GuiSys/CDrawStringOptions.hpp index 194eeb28a..50aa975a6 100644 --- a/Runtime/GuiSys/CDrawStringOptions.hpp +++ b/Runtime/GuiSys/CDrawStringOptions.hpp @@ -4,26 +4,21 @@ #include "RetroTypes.hpp" #include "CGuiTextSupport.hpp" -namespace urde -{ +namespace urde { -class CDrawStringOptions -{ - friend class CColorOverrideInstruction; - friend class CFontRenderState; - friend class CRasterFont; - friend class CTextExecuteBuffer; - friend class CBlockInstruction; - friend class CWordInstruction; +class CDrawStringOptions { + friend class CColorOverrideInstruction; + friend class CFontRenderState; + friend class CRasterFont; + friend class CTextExecuteBuffer; + friend class CBlockInstruction; + friend class CWordInstruction; + + ETextDirection x0_direction = ETextDirection::Horizontal; + std::vector x4_colors; - ETextDirection x0_direction = ETextDirection::Horizontal; - std::vector x4_colors; public: - CDrawStringOptions() - { - x4_colors.resize(16); - } + CDrawStringOptions() { x4_colors.resize(16); } }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CErrorOutputWindow.cpp b/Runtime/GuiSys/CErrorOutputWindow.cpp index 7b07b0f62..3666ca6af 100644 --- a/Runtime/GuiSys/CErrorOutputWindow.cpp +++ b/Runtime/GuiSys/CErrorOutputWindow.cpp @@ -1,24 +1,18 @@ #include "CErrorOutputWindow.hpp" -namespace urde -{ +namespace urde { -CErrorOutputWindow::CErrorOutputWindow(bool flag) -: CIOWin("Error Output Window") -{ - x18_25_ = true; - x18_26_ = true; - x18_27_ = true; - x18_28_ = flag; +CErrorOutputWindow::CErrorOutputWindow(bool flag) : CIOWin("Error Output Window") { + x18_25_ = true; + x18_26_ = true; + x18_27_ = true; + x18_28_ = flag; } -CIOWin::EMessageReturn CErrorOutputWindow::OnMessage(const CArchitectureMessage&, CArchitectureQueue&) -{ - return EMessageReturn::Normal; +CIOWin::EMessageReturn CErrorOutputWindow::OnMessage(const CArchitectureMessage&, CArchitectureQueue&) { + return EMessageReturn::Normal; } -void CErrorOutputWindow::Draw() const -{ -} +void CErrorOutputWindow::Draw() const {} -} +} // namespace urde diff --git a/Runtime/GuiSys/CErrorOutputWindow.hpp b/Runtime/GuiSys/CErrorOutputWindow.hpp index e3cbaad10..c338e3915 100644 --- a/Runtime/GuiSys/CErrorOutputWindow.hpp +++ b/Runtime/GuiSys/CErrorOutputWindow.hpp @@ -3,39 +3,31 @@ #include "CIOWin.hpp" #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -class CErrorOutputWindow : public CIOWin -{ +class CErrorOutputWindow : public CIOWin { public: - enum class State - { - Zero, - One, - Two - }; + enum class State { Zero, One, Two }; + private: - State x14_state = State::Zero; - union - { - struct - { - bool x18_24_; - bool x18_25_; - bool x18_26_; - bool x18_27_; - bool x18_28_; - }; - u16 dummy = 0; + State x14_state = State::Zero; + union { + struct { + bool x18_24_; + bool x18_25_; + bool x18_26_; + bool x18_27_; + bool x18_28_; }; - const wchar_t* x1c_msg; + u16 dummy = 0; + }; + const wchar_t* x1c_msg; + public: - CErrorOutputWindow(bool); - EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); - bool GetIsContinueDraw() const { return int(x14_state) < 2; } - void Draw() const; + CErrorOutputWindow(bool); + EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); + bool GetIsContinueDraw() const { return int(x14_state) < 2; } + void Draw() const; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CFontImageDef.cpp b/Runtime/GuiSys/CFontImageDef.cpp index 02cf1b5e2..f0602ab05 100644 --- a/Runtime/GuiSys/CFontImageDef.cpp +++ b/Runtime/GuiSys/CFontImageDef.cpp @@ -1,43 +1,37 @@ #include "CFontImageDef.hpp" #include "Graphics/CTexture.hpp" -namespace urde -{ +namespace urde { -CFontImageDef::CFontImageDef(const std::vector>& texs, - float interval, const zeus::CVector2f& cropFactor) -: x0_fps(interval), x14_cropFactor(cropFactor) -{ - x4_texs.reserve(texs.size()); - for (const TToken& tok : texs) - x4_texs.push_back(tok); +CFontImageDef::CFontImageDef(const std::vector>& texs, float interval, + const zeus::CVector2f& cropFactor) +: x0_fps(interval), x14_cropFactor(cropFactor) { + x4_texs.reserve(texs.size()); + for (const TToken& tok : texs) + x4_texs.push_back(tok); } CFontImageDef::CFontImageDef(const TToken& tex, const zeus::CVector2f& cropFactor) -: x0_fps(0.f), x14_cropFactor(cropFactor) -{ - x4_texs.push_back(tex); +: x0_fps(0.f), x14_cropFactor(cropFactor) { + x4_texs.push_back(tex); } -bool CFontImageDef::IsLoaded() const -{ - for (const TToken& tok : x4_texs) - if (!tok.IsLoaded()) - return false; - return true; +bool CFontImageDef::IsLoaded() const { + for (const TToken& tok : x4_texs) + if (!tok.IsLoaded()) + return false; + return true; } -s32 CFontImageDef::CalculateBaseline() const -{ - const CTexture* tex = x4_texs.front().GetObj(); - return s32(tex->GetHeight() * x14_cropFactor.y()) * 2.5f / 3.f; +s32 CFontImageDef::CalculateBaseline() const { + const CTexture* tex = x4_texs.front().GetObj(); + return s32(tex->GetHeight() * x14_cropFactor.y()) * 2.5f / 3.f; } -s32 CFontImageDef::CalculateHeight() const -{ - const CTexture* tex = x4_texs.front().GetObj(); - s32 scaledH = tex->GetHeight() * x14_cropFactor.y(); - return scaledH - (scaledH - CalculateBaseline()); +s32 CFontImageDef::CalculateHeight() const { + const CTexture* tex = x4_texs.front().GetObj(); + s32 scaledH = tex->GetHeight() * x14_cropFactor.y(); + return scaledH - (scaledH - CalculateBaseline()); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CFontImageDef.hpp b/Runtime/GuiSys/CFontImageDef.hpp index 8e379204b..53d1c6228 100644 --- a/Runtime/GuiSys/CFontImageDef.hpp +++ b/Runtime/GuiSys/CFontImageDef.hpp @@ -4,24 +4,20 @@ #include "CToken.hpp" #include "zeus/CVector2f.hpp" -namespace urde -{ +namespace urde { class CTexture; -class CFontImageDef -{ +class CFontImageDef { public: - float x0_fps; - std::vector> x4_texs; - zeus::CVector2f x14_cropFactor; + float x0_fps; + std::vector> x4_texs; + zeus::CVector2f x14_cropFactor; - CFontImageDef(const std::vector>& texs, float fps, - const zeus::CVector2f& cropFactor); - CFontImageDef(const TToken& tex, const zeus::CVector2f& cropFactor); - bool IsLoaded() const; - s32 CalculateBaseline() const; - s32 CalculateHeight() const; + CFontImageDef(const std::vector>& texs, float fps, const zeus::CVector2f& cropFactor); + CFontImageDef(const TToken& tex, const zeus::CVector2f& cropFactor); + bool IsLoaded() const; + s32 CalculateBaseline() const; + s32 CalculateHeight() const; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CFontRenderState.cpp b/Runtime/GuiSys/CFontRenderState.cpp index 925450d48..12f51d973 100644 --- a/Runtime/GuiSys/CFontRenderState.cpp +++ b/Runtime/GuiSys/CFontRenderState.cpp @@ -1,99 +1,85 @@ #include "CFontRenderState.hpp" #include "CRasterFont.hpp" -namespace urde -{ +namespace urde { -CFontRenderState::CFontRenderState() -{ - x54_colors[0] = zeus::CColor::skWhite; - x54_colors[1] = zeus::CColor::skGrey; - x54_colors[2] = zeus::CColor::skWhite; - RefreshPalette(); +CFontRenderState::CFontRenderState() { + x54_colors[0] = zeus::CColor::skWhite; + x54_colors[1] = zeus::CColor::skGrey; + x54_colors[2] = zeus::CColor::skWhite; + RefreshPalette(); } -zeus::CColor CFontRenderState::ConvertToTextureSpace(const CTextColor& col) const -{ - return col; +zeus::CColor CFontRenderState::ConvertToTextureSpace(const CTextColor& col) const { return col; } + +void CFontRenderState::PopState() { + static_cast(*this) = x10c_pushedStates.back(); + x10c_pushedStates.pop_back(); + RefreshPalette(); } -void CFontRenderState::PopState() -{ - static_cast(*this) = x10c_pushedStates.back(); - x10c_pushedStates.pop_back(); - RefreshPalette(); +void CFontRenderState::PushState() { x10c_pushedStates.push_back(*this); } + +void CFontRenderState::SetColor(EColorType tp, const CTextColor& col) { + switch (tp) { + case EColorType::Main: + case EColorType::Outline: + case EColorType::Geometry: + x54_colors[int(tp)] = col; + break; + case EColorType::Foreground: + x54_colors[0] = col; + break; + case EColorType::Background: + x54_colors[1] = col; + break; + } + RefreshColor(tp); } -void CFontRenderState::PushState() -{ - x10c_pushedStates.push_back(*this); +void CFontRenderState::RefreshPalette() { + RefreshColor(EColorType::Foreground); + RefreshColor(EColorType::Background); } -void CFontRenderState::SetColor(EColorType tp, const CTextColor& col) -{ - switch (tp) - { +void CFontRenderState::RefreshColor(EColorType tp) { + switch (tp) { + case EColorType::Main: + if (!x48_font) + return; + switch (x48_font->GetMode()) { case EColorType::Main: + if (!x64_colorOverrides[0]) + x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x54_colors[0]); + break; case EColorType::Outline: - case EColorType::Geometry: - x54_colors[int(tp)] = col; - break; - case EColorType::Foreground: - x54_colors[0] = col; - break; - case EColorType::Background: - x54_colors[1] = col; - break; + if (!x64_colorOverrides[0]) + x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x54_colors[0]); + break; + default: + break; } - RefreshColor(tp); + break; + case EColorType::Outline: + if (!x48_font) + return; + if (x64_colorOverrides[1]) + return; + if (x48_font->GetMode() == EColorType::Outline) + x0_drawStrOpts.x4_colors[1] = ConvertToTextureSpace(x54_colors[1]); + break; + case EColorType::Geometry: + if (!x64_colorOverrides[2]) + x0_drawStrOpts.x4_colors[2] = ConvertToTextureSpace(x54_colors[2]); + break; + case EColorType::Foreground: + RefreshColor(EColorType::Main); + RefreshColor(EColorType::Geometry); + break; + case EColorType::Background: + RefreshColor(EColorType::Outline); + break; + } } -void CFontRenderState::RefreshPalette() -{ - RefreshColor(EColorType::Foreground); - RefreshColor(EColorType::Background); -} - -void CFontRenderState::RefreshColor(EColorType tp) -{ - switch (tp) - { - case EColorType::Main: - if (!x48_font) - return; - switch (x48_font->GetMode()) - { - case EColorType::Main: - if (!x64_colorOverrides[0]) - x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x54_colors[0]); - break; - case EColorType::Outline: - if (!x64_colorOverrides[0]) - x0_drawStrOpts.x4_colors[0] = ConvertToTextureSpace(x54_colors[0]); - break; - default: break; - } - break; - case EColorType::Outline: - if (!x48_font) - return; - if (x64_colorOverrides[1]) - return; - if (x48_font->GetMode() == EColorType::Outline) - x0_drawStrOpts.x4_colors[1] = ConvertToTextureSpace(x54_colors[1]); - break; - case EColorType::Geometry: - if (!x64_colorOverrides[2]) - x0_drawStrOpts.x4_colors[2] = ConvertToTextureSpace(x54_colors[2]); - break; - case EColorType::Foreground: - RefreshColor(EColorType::Main); - RefreshColor(EColorType::Geometry); - break; - case EColorType::Background: - RefreshColor(EColorType::Outline); - break; - } -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CFontRenderState.hpp b/Runtime/GuiSys/CFontRenderState.hpp index b7db8a705..14c30df26 100644 --- a/Runtime/GuiSys/CFontRenderState.hpp +++ b/Runtime/GuiSys/CFontRenderState.hpp @@ -4,37 +4,35 @@ #include "CSaveableState.hpp" #include "CDrawStringOptions.hpp" -namespace urde -{ +namespace urde { class CLineInstruction; class CBlockInstruction; -class CFontRenderState : public CSaveableState -{ - friend class CLineInstruction; - friend class CBlockInstruction; - friend class CTextInstruction; - friend class CImageInstruction; - friend class CWordInstruction; +class CFontRenderState : public CSaveableState { + friend class CLineInstruction; + friend class CBlockInstruction; + friend class CTextInstruction; + friend class CImageInstruction; + friend class CWordInstruction; + + CBlockInstruction* x88_curBlock = nullptr; + CDrawStringOptions x8c_drawOpts; + s32 xd4_curX = 0; + s32 xd8_curY = 0; + const CLineInstruction* xdc_currentLineInst = nullptr; + std::vector xe8_; + std::vector xf8_; + bool x108_lineInitialized = true; + std::list x10c_pushedStates; - CBlockInstruction* x88_curBlock = nullptr; - CDrawStringOptions x8c_drawOpts; - s32 xd4_curX = 0; - s32 xd8_curY = 0; - const CLineInstruction* xdc_currentLineInst = nullptr; - std::vector xe8_; - std::vector xf8_; - bool x108_lineInitialized = true; - std::list x10c_pushedStates; public: - CFontRenderState(); - zeus::CColor ConvertToTextureSpace(const CTextColor& col) const; - void PopState(); - void PushState(); - void SetColor(EColorType tp, const CTextColor& col); - void RefreshPalette(); - void RefreshColor(EColorType tp); + CFontRenderState(); + zeus::CColor ConvertToTextureSpace(const CTextColor& col) const; + void PopState(); + void PushState(); + void SetColor(EColorType tp, const CTextColor& col); + void RefreshPalette(); + void RefreshColor(EColorType tp); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiCamera.cpp b/Runtime/GuiSys/CGuiCamera.cpp index 5d8e28668..dc6cb4dc7 100644 --- a/Runtime/GuiSys/CGuiCamera.cpp +++ b/Runtime/GuiSys/CGuiCamera.cpp @@ -3,81 +3,64 @@ #include "Graphics/CGraphics.hpp" #include "CGuiWidgetDrawParms.hpp" -namespace urde -{ +namespace urde { -CGuiCamera::CGuiCamera(const CGuiWidgetParms& parms, - float left, float right, - float top, float bottom, - float znear, float zfar) -: CGuiWidget(parms), xb8_projtype(EProjection::Orthographic), - m_proj(left, right, top, bottom, znear, zfar) -{} +CGuiCamera::CGuiCamera(const CGuiWidgetParms& parms, float left, float right, float top, float bottom, float znear, + float zfar) +: CGuiWidget(parms), xb8_projtype(EProjection::Orthographic), m_proj(left, right, top, bottom, znear, zfar) {} -CGuiCamera::CGuiCamera(const CGuiWidgetParms& parms, - float fov, float aspect, - float znear, float zfar) -: CGuiWidget(parms), xb8_projtype(EProjection::Perspective), - m_proj(fov, aspect, znear, zfar) -{} +CGuiCamera::CGuiCamera(const CGuiWidgetParms& parms, float fov, float aspect, float znear, float zfar) +: CGuiWidget(parms), xb8_projtype(EProjection::Perspective), m_proj(fov, aspect, znear, zfar) {} -zeus::CVector3f CGuiCamera::ConvertToScreenSpace(const zeus::CVector3f& vec) const -{ - zeus::CVector3f local = RotateTranslateW2O(vec); - if (local.isZero()) - return {-1.f, -1.f, 1.f}; +zeus::CVector3f CGuiCamera::ConvertToScreenSpace(const zeus::CVector3f& vec) const { + zeus::CVector3f local = RotateTranslateW2O(vec); + if (local.isZero()) + return {-1.f, -1.f, 1.f}; - zeus::CMatrix4f mat = CGraphics::CalculatePerspectiveMatrix(m_proj.xbc_fov, m_proj.xc0_aspect, - m_proj.xc4_znear, m_proj.xc8_zfar, - false); - local = zeus::CVector3f(local.x(), local.z(), -local.y()); - return mat.multiplyOneOverW(local); + zeus::CMatrix4f mat = CGraphics::CalculatePerspectiveMatrix(m_proj.xbc_fov, m_proj.xc0_aspect, m_proj.xc4_znear, + m_proj.xc8_zfar, false); + local = zeus::CVector3f(local.x(), local.z(), -local.y()); + return mat.multiplyOneOverW(local); } -void CGuiCamera::Draw(const CGuiWidgetDrawParms& parms) const -{ - if (xb8_projtype == EProjection::Perspective) - CGraphics::SetPerspective(m_proj.xbc_fov, m_proj.xc0_aspect, m_proj.xc4_znear, m_proj.xc8_zfar); - else - CGraphics::SetOrtho(m_proj.xbc_left, m_proj.xc0_right, m_proj.xc4_top, m_proj.xc8_bottom, - m_proj.xcc_znear, m_proj.xd0_zfar); - CGraphics::SetViewPointMatrix(GetGuiFrame()->GetAspectTransform() * - zeus::CTransform::Translate(parms.x4_cameraOffset) * x34_worldXF); - CGuiWidget::Draw(parms); +void CGuiCamera::Draw(const CGuiWidgetDrawParms& parms) const { + if (xb8_projtype == EProjection::Perspective) + CGraphics::SetPerspective(m_proj.xbc_fov, m_proj.xc0_aspect, m_proj.xc4_znear, m_proj.xc8_zfar); + else + CGraphics::SetOrtho(m_proj.xbc_left, m_proj.xc0_right, m_proj.xc4_top, m_proj.xc8_bottom, m_proj.xcc_znear, + m_proj.xd0_zfar); + CGraphics::SetViewPointMatrix(GetGuiFrame()->GetAspectTransform() * + zeus::CTransform::Translate(parms.x4_cameraOffset) * x34_worldXF); + CGuiWidget::Draw(parms); } -std::shared_ptr CGuiCamera::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - EProjection proj = EProjection(in.readUint32Big()); - std::shared_ptr ret = {}; - switch (proj) - { - case EProjection::Perspective: - { - float fov = in.readFloatBig(); - float aspect = in.readFloatBig(); - float znear = in.readFloatBig(); - float zfar = in.readFloatBig(); - ret = std::make_shared(parms, fov, aspect, znear, zfar); - break; - } - case EProjection::Orthographic: - { - float left = in.readFloatBig(); - float right = in.readFloatBig(); - float top = in.readFloatBig(); - float bottom = in.readFloatBig(); - float znear = in.readFloatBig(); - float zfar = in.readFloatBig(); - ret = std::make_shared(parms, left, right, top, bottom, znear, zfar); - break; - } +std::shared_ptr CGuiCamera::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + EProjection proj = EProjection(in.readUint32Big()); + std::shared_ptr ret = {}; + switch (proj) { + case EProjection::Perspective: { + float fov = in.readFloatBig(); + float aspect = in.readFloatBig(); + float znear = in.readFloatBig(); + float zfar = in.readFloatBig(); + ret = std::make_shared(parms, fov, aspect, znear, zfar); break; - } - frame->SetFrameCamera(ret->shared_from_this()); - ret->ParseBaseInfo(frame, in, parms); - return ret; + } + case EProjection::Orthographic: { + float left = in.readFloatBig(); + float right = in.readFloatBig(); + float top = in.readFloatBig(); + float bottom = in.readFloatBig(); + float znear = in.readFloatBig(); + float zfar = in.readFloatBig(); + ret = std::make_shared(parms, left, right, top, bottom, znear, zfar); + break; + } break; + } + frame->SetFrameCamera(ret->shared_from_this()); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiCamera.hpp b/Runtime/GuiSys/CGuiCamera.hpp index 51d4e6439..d56fd2f6b 100644 --- a/Runtime/GuiSys/CGuiCamera.hpp +++ b/Runtime/GuiSys/CGuiCamera.hpp @@ -2,65 +2,54 @@ #include "CGuiWidget.hpp" -namespace urde -{ +namespace urde { class CSimplePool; -class CGuiCamera : public CGuiWidget -{ +class CGuiCamera : public CGuiWidget { public: - enum class EProjection - { - Perspective, - Orthographic - }; - struct SProjection - { - union - { - struct - { - float xbc_left; - float xc0_right; - float xc4_top; - float xc8_bottom; - float xcc_znear; - float xd0_zfar; - }; - struct - { - float xbc_fov; - float xc0_aspect; - float xc4_znear; - float xc8_zfar; - }; - }; - SProjection(float left, float right, float top, float bottom, float znear, float zfar) - : xbc_left(left), xc0_right(right), xc4_top(top), xc8_bottom(bottom), xcc_znear(znear), - xd0_zfar(zfar) {} - SProjection(float fov, float aspect, float znear, float zfar) - : xbc_fov(fov), xc0_aspect(aspect), xc4_znear(znear), xc8_zfar(zfar) {} + enum class EProjection { Perspective, Orthographic }; + struct SProjection { + union { + struct { + float xbc_left; + float xc0_right; + float xc4_top; + float xc8_bottom; + float xcc_znear; + float xd0_zfar; + }; + struct { + float xbc_fov; + float xc0_aspect; + float xc4_znear; + float xc8_zfar; + }; }; + SProjection(float left, float right, float top, float bottom, float znear, float zfar) + : xbc_left(left), xc0_right(right), xc4_top(top), xc8_bottom(bottom), xcc_znear(znear), xd0_zfar(zfar) {} + SProjection(float fov, float aspect, float znear, float zfar) + : xbc_fov(fov), xc0_aspect(aspect), xc4_znear(znear), xc8_zfar(zfar) {} + }; + private: - EProjection xb8_projtype; - SProjection m_proj; + EProjection xb8_projtype; + SProjection m_proj; + public: - CGuiCamera(const CGuiWidgetParms& parms, float left, float right, - float top, float bottom, - float znear, float zfar); - CGuiCamera(const CGuiWidgetParms& parms, float fov, float aspect, float znear, float zfar); - FourCC GetWidgetTypeID() const { return FOURCC('CAMR'); } + CGuiCamera(const CGuiWidgetParms& parms, float left, float right, float top, float bottom, float znear, float zfar); + CGuiCamera(const CGuiWidgetParms& parms, float fov, float aspect, float znear, float zfar); + FourCC GetWidgetTypeID() const { return FOURCC('CAMR'); } - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); - zeus::CVector3f ConvertToScreenSpace(const zeus::CVector3f& vec) const; - const SProjection& GetProjection() const { return m_proj; } - void SetFov(float fov) { m_proj.xbc_fov = fov; } - void Draw(const CGuiWidgetDrawParms& parms) const; + zeus::CVector3f ConvertToScreenSpace(const zeus::CVector3f& vec) const; + const SProjection& GetProjection() const { return m_proj; } + void SetFov(float fov) { m_proj.xbc_fov = fov; } + void Draw(const CGuiWidgetDrawParms& parms) const; - std::shared_ptr shared_from_this() - { return std::static_pointer_cast(CGuiObject::shared_from_this()); } + std::shared_ptr shared_from_this() { + return std::static_pointer_cast(CGuiObject::shared_from_this()); + } }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiCompoundWidget.cpp b/Runtime/GuiSys/CGuiCompoundWidget.cpp index 155858deb..a70370850 100644 --- a/Runtime/GuiSys/CGuiCompoundWidget.cpp +++ b/Runtime/GuiSys/CGuiCompoundWidget.cpp @@ -1,45 +1,35 @@ #include "CGuiCompoundWidget.hpp" -namespace urde -{ +namespace urde { -CGuiCompoundWidget::CGuiCompoundWidget(const CGuiWidgetParms& parms) -: CGuiWidget(parms) -{ +CGuiCompoundWidget::CGuiCompoundWidget(const CGuiWidgetParms& parms) : CGuiWidget(parms) {} + +void CGuiCompoundWidget::OnVisibleChange() { + CGuiWidget* child = static_cast(GetChildObject()); + while (child) { + child->SetIsVisible(GetIsVisible()); + child = static_cast(child->GetNextSibling()); + } + CGuiWidget::OnVisibleChange(); } -void CGuiCompoundWidget::OnVisibleChange() -{ - CGuiWidget* child = static_cast(GetChildObject()); - while (child) - { - child->SetIsVisible(GetIsVisible()); - child = static_cast(child->GetNextSibling()); - } - CGuiWidget::OnVisibleChange(); +void CGuiCompoundWidget::OnActiveChange() { + CGuiWidget* child = static_cast(GetChildObject()); + while (child) { + child->SetIsActive(GetIsActive()); + child = static_cast(child->GetNextSibling()); + } + CGuiWidget::OnActiveChange(); } -void CGuiCompoundWidget::OnActiveChange() -{ - CGuiWidget* child = static_cast(GetChildObject()); - while (child) - { - child->SetIsActive(GetIsActive()); - child = static_cast(child->GetNextSibling()); - } - CGuiWidget::OnActiveChange(); +CGuiWidget* CGuiCompoundWidget::GetWorkerWidget(int id) const { + CGuiWidget* child = static_cast(GetChildObject()); + while (child) { + if (child->GetWorkerId() == id) + return child; + child = static_cast(child->GetNextSibling()); + } + return nullptr; } -CGuiWidget* CGuiCompoundWidget::GetWorkerWidget(int id) const -{ - CGuiWidget* child = static_cast(GetChildObject()); - while (child) - { - if (child->GetWorkerId() == id) - return child; - child = static_cast(child->GetNextSibling()); - } - return nullptr; -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiCompoundWidget.hpp b/Runtime/GuiSys/CGuiCompoundWidget.hpp index f5aa973c5..5d7feadc9 100644 --- a/Runtime/GuiSys/CGuiCompoundWidget.hpp +++ b/Runtime/GuiSys/CGuiCompoundWidget.hpp @@ -2,19 +2,16 @@ #include "CGuiWidget.hpp" -namespace urde -{ +namespace urde { -class CGuiCompoundWidget : public CGuiWidget -{ +class CGuiCompoundWidget : public CGuiWidget { public: - CGuiCompoundWidget(const CGuiWidgetParms& parms); - FourCC GetWidgetTypeID() const {return FourCC(-1);} + CGuiCompoundWidget(const CGuiWidgetParms& parms); + FourCC GetWidgetTypeID() const { return FourCC(-1); } - void OnVisibleChange(); - void OnActiveChange(); - virtual CGuiWidget* GetWorkerWidget(int id) const; + void OnVisibleChange(); + void OnActiveChange(); + virtual CGuiWidget* GetWorkerWidget(int id) const; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiFrame.cpp b/Runtime/GuiSys/CGuiFrame.cpp index 3fabe5f2a..bcaaae4cb 100644 --- a/Runtime/GuiSys/CGuiFrame.cpp +++ b/Runtime/GuiSys/CGuiFrame.cpp @@ -10,234 +10,188 @@ #include "CSimplePool.hpp" #include "Graphics/CModel.hpp" -namespace urde -{ +namespace urde { CGuiFrame::CGuiFrame(CAssetId id, CGuiSys& sys, int a, int b, int c, CSimplePool* sp) -: x0_id(id), x8_guiSys(sys), x4c_a(a), x50_b(b), x54_c(c), x58_24_loaded(false) -{ - x3c_lights.reserve(8); - m_indexedLights.reserve(8); - x10_rootWidget.reset(new CGuiWidget( - CGuiWidget::CGuiWidgetParms(this, false, 0, 0, false, false, false, zeus::CColor::skWhite, - CGuiWidget::EGuiModelDrawFlags::Alpha, false, - x8_guiSys.x8_mode != CGuiSys::EUsageMode::Zero))); - x8_guiSys.m_registeredFrames.insert(this); +: x0_id(id), x8_guiSys(sys), x4c_a(a), x50_b(b), x54_c(c), x58_24_loaded(false) { + x3c_lights.reserve(8); + m_indexedLights.reserve(8); + x10_rootWidget.reset(new CGuiWidget(CGuiWidget::CGuiWidgetParms( + this, false, 0, 0, false, false, false, zeus::CColor::skWhite, CGuiWidget::EGuiModelDrawFlags::Alpha, false, + x8_guiSys.x8_mode != CGuiSys::EUsageMode::Zero))); + x8_guiSys.m_registeredFrames.insert(this); } -CGuiFrame::~CGuiFrame() -{ - x8_guiSys.m_registeredFrames.erase(this); +CGuiFrame::~CGuiFrame() { x8_guiSys.m_registeredFrames.erase(this); } + +CGuiWidget* CGuiFrame::FindWidget(std::string_view name) const { + s16 id = x18_idDB.FindWidgetID(name); + if (id == -1) + return nullptr; + return FindWidget(id); } -CGuiWidget* CGuiFrame::FindWidget(std::string_view name) const -{ - s16 id = x18_idDB.FindWidgetID(name); - if (id == -1) - return nullptr; - return FindWidget(id); +CGuiWidget* CGuiFrame::FindWidget(s16 id) const { return x10_rootWidget->FindWidget(id); } + +void CGuiFrame::SortDrawOrder() { + std::sort(x2c_widgets.begin(), x2c_widgets.end(), + [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool { + return a->GetWorldPosition().y() > b->GetWorldPosition().y(); + }); } -CGuiWidget* CGuiFrame::FindWidget(s16 id) const -{ - return x10_rootWidget->FindWidget(id); -} +void CGuiFrame::EnableLights(u32 lights, CBooModel& model) const { + std::vector lightsOut; + lightsOut.reserve(m_indexedLights.size() + 1); + CGraphics::DisableAllLights(); -void CGuiFrame::SortDrawOrder() -{ - std::sort(x2c_widgets.begin(), x2c_widgets.end(), - [](const std::shared_ptr& a, const std::shared_ptr& b) -> bool - { - return a->GetWorldPosition().y() > b->GetWorldPosition().y(); - }); -} - -void CGuiFrame::EnableLights(u32 lights, CBooModel& model) const -{ - std::vector lightsOut; - lightsOut.reserve(m_indexedLights.size() + 1); - CGraphics::DisableAllLights(); - - zeus::CColor ambColor(zeus::CColor::skBlack); - ERglLight lightId = ERglLight::Zero; - int idx = 0; - for (CGuiLight* light : m_indexedLights) - { - if (!light || !light->GetIsVisible()) - { - ++reinterpret_cast&>(lightId); - ++idx; - continue; - } - if ((lights & (1 << idx)) != 0) - { - //const zeus::CColor& geomCol = light->GetGeometryColor(); - //if (geomCol.r || geomCol.g || geomCol.b) - //{ - //CGraphics::LoadLight(lightId, light->BuildLight()); - lightsOut.push_back(light->BuildLight()); - CGraphics::EnableLight(lightId); - //} - // accumulate ambient color - ambColor += light->GetAmbientLightColor(); - } - ++reinterpret_cast&>(lightId); - ++idx; + zeus::CColor ambColor(zeus::CColor::skBlack); + ERglLight lightId = ERglLight::Zero; + int idx = 0; + for (CGuiLight* light : m_indexedLights) { + if (!light || !light->GetIsVisible()) { + ++reinterpret_cast&>(lightId); + ++idx; + continue; } - if (lightsOut.empty()) - { - //CGraphics::SetAmbientColor(zeus::CColor::skWhite); - lightsOut.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, zeus::CColor::skWhite)); - } - else - { - //CGraphics::SetAmbientColor(ambColor); - lightsOut.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, ambColor)); + if ((lights & (1 << idx)) != 0) { + // const zeus::CColor& geomCol = light->GetGeometryColor(); + // if (geomCol.r || geomCol.g || geomCol.b) + //{ + // CGraphics::LoadLight(lightId, light->BuildLight()); + lightsOut.push_back(light->BuildLight()); + CGraphics::EnableLight(lightId); + //} + // accumulate ambient color + ambColor += light->GetAmbientLightColor(); } + ++reinterpret_cast&>(lightId); + ++idx; + } + if (lightsOut.empty()) { + // CGraphics::SetAmbientColor(zeus::CColor::skWhite); + lightsOut.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, zeus::CColor::skWhite)); + } else { + // CGraphics::SetAmbientColor(ambColor); + lightsOut.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, ambColor)); + } - model.ActivateLights(lightsOut); + model.ActivateLights(lightsOut); } -void CGuiFrame::DisableLights() const -{ - CGraphics::DisableAllLights(); +void CGuiFrame::DisableLights() const { CGraphics::DisableAllLights(); } + +void CGuiFrame::RemoveLight(CGuiLight* light) { + if (m_indexedLights.empty()) + return; + m_indexedLights[light->GetLightId()] = nullptr; } -void CGuiFrame::RemoveLight(CGuiLight* light) -{ - if (m_indexedLights.empty()) - return; - m_indexedLights[light->GetLightId()] = nullptr; +void CGuiFrame::AddLight(CGuiLight* light) { + if (m_indexedLights.empty()) + m_indexedLights.resize(8); + m_indexedLights[light->GetLightId()] = light; } -void CGuiFrame::AddLight(CGuiLight* light) -{ - if (m_indexedLights.empty()) - m_indexedLights.resize(8); - m_indexedLights[light->GetLightId()] = light; -} +void CGuiFrame::RegisterLight(std::shared_ptr&& light) { x3c_lights.push_back(std::move(light)); } -void CGuiFrame::RegisterLight(std::shared_ptr&& light) -{ - x3c_lights.push_back(std::move(light)); -} - -bool CGuiFrame::GetIsFinishedLoading() const -{ - if (x58_24_loaded) - return true; - for (const auto& widget : x2c_widgets) - { - if (widget->GetIsFinishedLoading()) - continue; - return false; - } - const_cast(this)->x58_24_loaded = true; +bool CGuiFrame::GetIsFinishedLoading() const { + if (x58_24_loaded) return true; + for (const auto& widget : x2c_widgets) { + if (widget->GetIsFinishedLoading()) + continue; + return false; + } + const_cast(this)->x58_24_loaded = true; + return true; } -void CGuiFrame::Touch() const -{ - for (const auto& widget : x2c_widgets) - widget->Touch(); +void CGuiFrame::Touch() const { + for (const auto& widget : x2c_widgets) + widget->Touch(); } -void CGuiFrame::SetAspectConstraint(float c) -{ - m_aspectConstraint = c; - CGuiSys::ViewportResizeFrame(this); +void CGuiFrame::SetAspectConstraint(float c) { + m_aspectConstraint = c; + CGuiSys::ViewportResizeFrame(this); } -void CGuiFrame::SetMaxAspect(float c) -{ - m_maxAspect = c; - CGuiSys::ViewportResizeFrame(this); +void CGuiFrame::SetMaxAspect(float c) { + m_maxAspect = c; + CGuiSys::ViewportResizeFrame(this); } -void CGuiFrame::Update(float dt) -{ - xc_headWidget->Update(dt); +void CGuiFrame::Update(float dt) { xc_headWidget->Update(dt); } + +void CGuiFrame::Draw(const CGuiWidgetDrawParms& parms) const { + CGraphics::SetCullMode(ERglCullMode::None); + CGraphics::SetAmbientColor(zeus::CColor::skWhite); + DisableLights(); + x14_camera->Draw(parms); + // Set one-stage modulate + CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, + ERglLogicOp::Clear); + + for (const auto& widget : x2c_widgets) + if (widget->GetIsVisible()) + widget->Draw(parms); + + CGraphics::SetCullMode(ERglCullMode::Front); } -void CGuiFrame::Draw(const CGuiWidgetDrawParms& parms) const -{ - CGraphics::SetCullMode(ERglCullMode::None); - CGraphics::SetAmbientColor(zeus::CColor::skWhite); - DisableLights(); - x14_camera->Draw(parms); - // Set one-stage modulate - CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, - ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear); - - for (const auto& widget : x2c_widgets) - if (widget->GetIsVisible()) - widget->Draw(parms); - - CGraphics::SetCullMode(ERglCullMode::Front); +void CGuiFrame::Initialize() { + SortDrawOrder(); + xc_headWidget->SetColor(xc_headWidget->xa4_color); + xc_headWidget->DispatchInitialize(); } -void CGuiFrame::Initialize() -{ - SortDrawOrder(); - xc_headWidget->SetColor(xc_headWidget->xa4_color); - xc_headWidget->DispatchInitialize(); -} - -void CGuiFrame::LoadWidgetsInGame(CInputStream& in, CSimplePool* sp) -{ - u32 count = in.readUint32Big(); - x2c_widgets.reserve(count); - for (u32 i=0 ; i widget = CGuiSys::CreateWidgetInGame(type, in, this, sp); - type = widget->GetWidgetTypeID(); - switch (type) - { - case SBIG('CAMR'): - case SBIG('LITE'): - case SBIG('BGND'): - break; - default: - x2c_widgets.push_back(std::move(widget)); - break; - } +void CGuiFrame::LoadWidgetsInGame(CInputStream& in, CSimplePool* sp) { + u32 count = in.readUint32Big(); + x2c_widgets.reserve(count); + for (u32 i = 0; i < count; ++i) { + DataSpec::DNAFourCC type; + type.read(in); + std::shared_ptr widget = CGuiSys::CreateWidgetInGame(type, in, this, sp); + type = widget->GetWidgetTypeID(); + switch (type) { + case SBIG('CAMR'): + case SBIG('LITE'): + case SBIG('BGND'): + break; + default: + x2c_widgets.push_back(std::move(widget)); + break; } - Initialize(); + } + Initialize(); } -void CGuiFrame::ProcessUserInput(const CFinalInput& input) const -{ - if (input.ControllerIdx() != 0) - return; - for (auto& widget : x2c_widgets) - { - if (widget->GetIsActive()) - widget->ProcessUserInput(input); - } +void CGuiFrame::ProcessUserInput(const CFinalInput& input) const { + if (input.ControllerIdx() != 0) + return; + for (auto& widget : x2c_widgets) { + if (widget->GetIsActive()) + widget->ProcessUserInput(input); + } } -std::unique_ptr CGuiFrame::CreateFrame(CAssetId frmeId, CGuiSys& sys, CInputStream& in, CSimplePool* sp) -{ - in.readInt32Big(); - int a = in.readInt32Big(); - int b = in.readInt32Big(); - int c = in.readInt32Big(); +std::unique_ptr CGuiFrame::CreateFrame(CAssetId frmeId, CGuiSys& sys, CInputStream& in, CSimplePool* sp) { + in.readInt32Big(); + int a = in.readInt32Big(); + int b = in.readInt32Big(); + int c = in.readInt32Big(); - std::unique_ptr ret = std::make_unique(frmeId, sys, a, b, c, sp); - ret->LoadWidgetsInGame(in, sp); - return ret; + std::unique_ptr ret = std::make_unique(frmeId, sys, a, b, c, sp); + ret->LoadWidgetsInGame(in, sp); + return ret; } -std::unique_ptr RGuiFrameFactoryInGame(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& cvParms, - CObjectReference* selfRef) -{ - CSimplePool* sp = cvParms.GetOwnedObj(); - std::unique_ptr frame(CGuiFrame::CreateFrame(tag.id, *g_GuiSys, in, sp)); - return TToken::GetIObjObjectFor(std::move(frame)); +std::unique_ptr RGuiFrameFactoryInGame(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& cvParms, + CObjectReference* selfRef) { + CSimplePool* sp = cvParms.GetOwnedObj(); + std::unique_ptr frame(CGuiFrame::CreateFrame(tag.id, *g_GuiSys, in, sp)); + return TToken::GetIObjObjectFor(std::move(frame)); } - -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiFrame.hpp b/Runtime/GuiSys/CGuiFrame.hpp index ba966847c..ea7cf64cc 100644 --- a/Runtime/GuiSys/CGuiFrame.hpp +++ b/Runtime/GuiSys/CGuiFrame.hpp @@ -6,8 +6,7 @@ #include "IObj.hpp" #include -namespace urde -{ +namespace urde { class CGuiSys; class CLight; class CGuiCamera; @@ -18,70 +17,68 @@ class CObjectReference; class CSimplePool; class CBooModel; -class CGuiFrame -{ - friend class CGuiSys; +class CGuiFrame { + friend class CGuiSys; + private: - std::vector m_indexedLights; + std::vector m_indexedLights; - CAssetId x0_id; - u32 x4_ = 0; - CGuiSys& x8_guiSys; - std::shared_ptr xc_headWidget; - std::shared_ptr x10_rootWidget; - std::shared_ptr x14_camera; - CGuiWidgetIdDB x18_idDB; - std::vector> x2c_widgets; - std::vector> x3c_lights; - int x4c_a; - int x50_b; - int x54_c; - bool x58_24_loaded : 1; + CAssetId x0_id; + u32 x4_ = 0; + CGuiSys& x8_guiSys; + std::shared_ptr xc_headWidget; + std::shared_ptr x10_rootWidget; + std::shared_ptr x14_camera; + CGuiWidgetIdDB x18_idDB; + std::vector> x2c_widgets; + std::vector> x3c_lights; + int x4c_a; + int x50_b; + int x54_c; + bool x58_24_loaded : 1; - zeus::CTransform m_aspectTransform; - float m_aspectConstraint = -1.f; - float m_maxAspect = -1.f; + zeus::CTransform m_aspectTransform; + float m_aspectConstraint = -1.f; + float m_maxAspect = -1.f; public: - CGuiFrame(CAssetId id, CGuiSys& sys, int a, int b, int c, CSimplePool* sp); - ~CGuiFrame(); + CGuiFrame(CAssetId id, CGuiSys& sys, int a, int b, int c, CSimplePool* sp); + ~CGuiFrame(); - CGuiSys& GetGuiSys() {return x8_guiSys;} - CAssetId GetAssetId() const {return x0_id;} + CGuiSys& GetGuiSys() { return x8_guiSys; } + CAssetId GetAssetId() const { return x0_id; } - CGuiLight* GetFrameLight(int idx) const { return m_indexedLights[idx]; } - CGuiCamera* GetFrameCamera() const { return x14_camera.get(); } - CGuiWidget* FindWidget(std::string_view name) const; - CGuiWidget* FindWidget(s16 id) const; - void SetFrameCamera(std::shared_ptr&& camr) { x14_camera = std::move(camr); } - void SetHeadWidget(std::shared_ptr&& hwig) { xc_headWidget = std::move(hwig); } - CGuiHeadWidget* GetHeadWidget() const { return xc_headWidget.get(); } - void SortDrawOrder(); - void EnableLights(u32 lights, CBooModel& model) const; - void DisableLights() const; - void RemoveLight(CGuiLight* light); - void AddLight(CGuiLight* light); - void RegisterLight(std::shared_ptr&& light); - bool GetIsFinishedLoading() const; - void Touch() const; - const zeus::CTransform& GetAspectTransform() const { return m_aspectTransform; } - void SetAspectConstraint(float c); - void SetMaxAspect(float c); + CGuiLight* GetFrameLight(int idx) const { return m_indexedLights[idx]; } + CGuiCamera* GetFrameCamera() const { return x14_camera.get(); } + CGuiWidget* FindWidget(std::string_view name) const; + CGuiWidget* FindWidget(s16 id) const; + void SetFrameCamera(std::shared_ptr&& camr) { x14_camera = std::move(camr); } + void SetHeadWidget(std::shared_ptr&& hwig) { xc_headWidget = std::move(hwig); } + CGuiHeadWidget* GetHeadWidget() const { return xc_headWidget.get(); } + void SortDrawOrder(); + void EnableLights(u32 lights, CBooModel& model) const; + void DisableLights() const; + void RemoveLight(CGuiLight* light); + void AddLight(CGuiLight* light); + void RegisterLight(std::shared_ptr&& light); + bool GetIsFinishedLoading() const; + void Touch() const; + const zeus::CTransform& GetAspectTransform() const { return m_aspectTransform; } + void SetAspectConstraint(float c); + void SetMaxAspect(float c); - void Update(float dt); - void Draw(const CGuiWidgetDrawParms& parms) const; - void Initialize(); - void LoadWidgetsInGame(CInputStream& in, CSimplePool* sp); - void ProcessUserInput(const CFinalInput& input) const; + void Update(float dt); + void Draw(const CGuiWidgetDrawParms& parms) const; + void Initialize(); + void LoadWidgetsInGame(CInputStream& in, CSimplePool* sp); + void ProcessUserInput(const CFinalInput& input) const; - CGuiWidgetIdDB& GetWidgetIdDB() {return x18_idDB;} + CGuiWidgetIdDB& GetWidgetIdDB() { return x18_idDB; } - static std::unique_ptr CreateFrame(CAssetId frmeId, CGuiSys& sys, CInputStream& in, CSimplePool* sp); + static std::unique_ptr CreateFrame(CAssetId frmeId, CGuiSys& sys, CInputStream& in, CSimplePool* sp); }; -std::unique_ptr RGuiFrameFactoryInGame(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& vparms, +std::unique_ptr RGuiFrameFactoryInGame(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiGroup.cpp b/Runtime/GuiSys/CGuiGroup.cpp index 297ae8d13..24b80a424 100644 --- a/Runtime/GuiSys/CGuiGroup.cpp +++ b/Runtime/GuiSys/CGuiGroup.cpp @@ -1,67 +1,51 @@ #include "CGuiGroup.hpp" -namespace urde -{ +namespace urde { -void CGuiGroup::LoadWidgetFnMap() -{ -} +void CGuiGroup::LoadWidgetFnMap() {} CGuiGroup::CGuiGroup(const CGuiWidgetParms& parms, int defaultWorker, bool b) -: CGuiCompoundWidget(parms), xbc_selectedWorker(defaultWorker), xc0_b(b) -{ -} +: CGuiCompoundWidget(parms), xbc_selectedWorker(defaultWorker), xc0_b(b) {} -void CGuiGroup::SelectWorkerWidget(int workerId, bool setActive, bool setVisible) -{ - CGuiWidget* child = static_cast(GetChildObject()); - while (child) - { - if (child->GetWorkerId() == workerId) - { - CGuiWidget* sel = GetSelectedWidget(); - if (setActive) - { - sel->SetIsActive(false); - child->SetIsActive(true); - } - if (setVisible) - { - sel->SetVisibility(false, ETraversalMode::Single); - child->SetVisibility(true, ETraversalMode::Single); - } - break; - } - child = static_cast(child->GetNextSibling()); +void CGuiGroup::SelectWorkerWidget(int workerId, bool setActive, bool setVisible) { + CGuiWidget* child = static_cast(GetChildObject()); + while (child) { + if (child->GetWorkerId() == workerId) { + CGuiWidget* sel = GetSelectedWidget(); + if (setActive) { + sel->SetIsActive(false); + child->SetIsActive(true); + } + if (setVisible) { + sel->SetVisibility(false, ETraversalMode::Single); + child->SetVisibility(true, ETraversalMode::Single); + } + break; } + child = static_cast(child->GetNextSibling()); + } } -CGuiWidget* CGuiGroup::GetSelectedWidget() -{ - return GetWorkerWidget(xbc_selectedWorker); +CGuiWidget* CGuiGroup::GetSelectedWidget() { return GetWorkerWidget(xbc_selectedWorker); } + +bool CGuiGroup::AddWorkerWidget(CGuiWidget* worker) { + ++xb8_workerCount; + return true; } -bool CGuiGroup::AddWorkerWidget(CGuiWidget* worker) -{ - ++xb8_workerCount; - return true; +void CGuiGroup::OnActiveChange() { + CGuiWidget* sel = GetSelectedWidget(); + if (sel) + sel->SetIsActive(true); } -void CGuiGroup::OnActiveChange() -{ - CGuiWidget* sel = GetSelectedWidget(); - if (sel) - sel->SetIsActive(true); +std::shared_ptr CGuiGroup::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + s16 defaultWorker = in.readInt16Big(); + bool b = in.readBool(); + std::shared_ptr ret = std::make_shared(parms, defaultWorker, b); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -std::shared_ptr CGuiGroup::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - s16 defaultWorker = in.readInt16Big(); - bool b = in.readBool(); - std::shared_ptr ret = std::make_shared(parms, defaultWorker, b); - ret->ParseBaseInfo(frame, in, parms); - return ret; -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiGroup.hpp b/Runtime/GuiSys/CGuiGroup.hpp index 79927b739..31218dee3 100644 --- a/Runtime/GuiSys/CGuiGroup.hpp +++ b/Runtime/GuiSys/CGuiGroup.hpp @@ -2,26 +2,24 @@ #include "CGuiCompoundWidget.hpp" -namespace urde -{ +namespace urde { + +class CGuiGroup : public CGuiCompoundWidget { + u32 xb8_workerCount = 0; + int xbc_selectedWorker; + bool xc0_b; -class CGuiGroup : public CGuiCompoundWidget -{ - u32 xb8_workerCount = 0; - int xbc_selectedWorker; - bool xc0_b; public: - CGuiGroup(const CGuiWidgetParms& parms, int defaultWorker, bool b); - FourCC GetWidgetTypeID() const { return FOURCC('GRUP'); } + CGuiGroup(const CGuiWidgetParms& parms, int defaultWorker, bool b); + FourCC GetWidgetTypeID() const { return FOURCC('GRUP'); } - void SelectWorkerWidget(int workerId, bool setActive, bool setVisible); - CGuiWidget* GetSelectedWidget(); - bool AddWorkerWidget(CGuiWidget* worker); - void OnActiveChange(); + void SelectWorkerWidget(int workerId, bool setActive, bool setVisible); + CGuiWidget* GetSelectedWidget(); + bool AddWorkerWidget(CGuiWidget* worker); + void OnActiveChange(); - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); - static void LoadWidgetFnMap(); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static void LoadWidgetFnMap(); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiHeadWidget.cpp b/Runtime/GuiSys/CGuiHeadWidget.cpp index 50cdf4b48..5fe50df86 100644 --- a/Runtime/GuiSys/CGuiHeadWidget.cpp +++ b/Runtime/GuiSys/CGuiHeadWidget.cpp @@ -1,19 +1,16 @@ #include "CGuiHeadWidget.hpp" #include "CGuiFrame.hpp" -namespace urde -{ +namespace urde { -CGuiHeadWidget::CGuiHeadWidget(const CGuiWidgetParms& parms) -: CGuiWidget(parms) {} +CGuiHeadWidget::CGuiHeadWidget(const CGuiWidgetParms& parms) : CGuiWidget(parms) {} -std::shared_ptr CGuiHeadWidget::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - std::shared_ptr ret = std::make_shared(parms); - frame->SetHeadWidget(ret->shared_from_this()); - ret->ParseBaseInfo(frame, in, parms); - return ret; +std::shared_ptr CGuiHeadWidget::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + std::shared_ptr ret = std::make_shared(parms); + frame->SetHeadWidget(ret->shared_from_this()); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiHeadWidget.hpp b/Runtime/GuiSys/CGuiHeadWidget.hpp index ba5adf3a7..4eeb9073c 100644 --- a/Runtime/GuiSys/CGuiHeadWidget.hpp +++ b/Runtime/GuiSys/CGuiHeadWidget.hpp @@ -2,19 +2,17 @@ #include "CGuiWidget.hpp" -namespace urde -{ +namespace urde { -class CGuiHeadWidget : public CGuiWidget -{ +class CGuiHeadWidget : public CGuiWidget { public: - FourCC GetWidgetTypeID() const { return FOURCC('HWIG'); } - CGuiHeadWidget(const CGuiWidgetParms& parms); - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + FourCC GetWidgetTypeID() const { return FOURCC('HWIG'); } + CGuiHeadWidget(const CGuiWidgetParms& parms); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); - std::shared_ptr shared_from_this() - { return std::static_pointer_cast(CGuiObject::shared_from_this()); } + std::shared_ptr shared_from_this() { + return std::static_pointer_cast(CGuiObject::shared_from_this()); + } }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiLight.cpp b/Runtime/GuiSys/CGuiLight.cpp index 0a2c1ceca..406c84a24 100644 --- a/Runtime/GuiSys/CGuiLight.cpp +++ b/Runtime/GuiSys/CGuiLight.cpp @@ -1,108 +1,96 @@ #include "CGuiLight.hpp" #include "CGuiFrame.hpp" -namespace urde -{ +namespace urde { CGuiLight::CGuiLight(const CGuiWidgetParms& parms, const CLight& light) -: CGuiWidget(parms), - xb8_type(light.x1c_type), - xbc_spotCutoff(light.x20_spotCutoff), - xc0_distC(light.x24_distC), - xc4_distL(light.x28_distL), - xc8_distQ(light.x2c_distQ), - xcc_angleC(light.x30_angleC), - xd0_angleL(light.x34_angleL), - xd4_angleQ(light.x38_angleQ), - xd8_lightId(light.x40_lightId) -{} +: CGuiWidget(parms) +, xb8_type(light.x1c_type) +, xbc_spotCutoff(light.x20_spotCutoff) +, xc0_distC(light.x24_distC) +, xc4_distL(light.x28_distL) +, xc8_distQ(light.x2c_distQ) +, xcc_angleC(light.x30_angleC) +, xd0_angleL(light.x34_angleL) +, xd4_angleQ(light.x38_angleQ) +, xd8_lightId(light.x40_lightId) {} -CGuiLight::~CGuiLight() -{ +CGuiLight::~CGuiLight() { xb0_frame->RemoveLight(this); } + +CLight CGuiLight::BuildLight() const { + CLight ret = CLight::BuildLocalAmbient(zeus::CVector3f::skZero, zeus::CColor::skBlack); + + switch (xb8_type) { + case ELightType::Spot: + ret = CLight::BuildSpot(GetWorldPosition(), x34_worldXF.basis[1], xa4_color, xbc_spotCutoff); + break; + case ELightType::Point: + ret = CLight::BuildPoint(GetWorldPosition(), xa4_color); + break; + case ELightType::Directional: + ret = CLight::BuildDirectional(x34_worldXF.basis[1], xa4_color); + break; + default: + break; + } + + ret.SetAttenuation(xc0_distC, xc4_distL, xc8_distQ); + ret.SetAngleAttenuation(xcc_angleC, xd0_angleL, xd4_angleQ); + return ret; +} + +void CGuiLight::SetIsVisible(bool vis) { + if (vis) + xb0_frame->AddLight(this); + else xb0_frame->RemoveLight(this); + CGuiWidget::SetIsVisible(vis); } -CLight CGuiLight::BuildLight() const -{ - CLight ret = CLight::BuildLocalAmbient(zeus::CVector3f::skZero, zeus::CColor::skBlack); +std::shared_ptr CGuiLight::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - switch (xb8_type) - { - case ELightType::Spot: - ret = CLight::BuildSpot(GetWorldPosition(), x34_worldXF.basis[1], xa4_color, xbc_spotCutoff); - break; - case ELightType::Point: - ret = CLight::BuildPoint(GetWorldPosition(), xa4_color); - break; - case ELightType::Directional: - ret = CLight::BuildDirectional(x34_worldXF.basis[1], xa4_color); - break; - default: break; - } + ELightType tp = ELightType(in.readUint32Big()); + float distC = in.readFloatBig(); + float distL = in.readFloatBig(); + float distQ = in.readFloatBig(); + float angC = in.readFloatBig(); + float angL = in.readFloatBig(); + float angQ = in.readFloatBig(); + u32 lightId = in.readUint32Big(); - ret.SetAttenuation(xc0_distC, xc4_distL, xc8_distQ); - ret.SetAngleAttenuation(xcc_angleC, xd0_angleL, xd4_angleQ); - return ret; + std::shared_ptr ret = {}; + switch (tp) { + case ELightType::Spot: { + float cutoff = in.readFloatBig(); + CLight lt = CLight::BuildSpot(zeus::CVector3f::skZero, zeus::CVector3f::skZero, parms.x10_color, cutoff); + lt.SetAttenuation(distC, distL, distQ); + lt.SetAngleAttenuation(angC, angL, angQ); + lt.x40_lightId = lightId; + ret = std::make_shared(parms, lt); + break; + } + case ELightType::Point: { + CLight lt = CLight::BuildPoint(zeus::CVector3f::skZero, parms.x10_color); + lt.SetAttenuation(distC, distL, distQ); + lt.x40_lightId = lightId; + ret = std::make_shared(parms, lt); + break; + } + case ELightType::Directional: { + CLight lt = CLight::BuildDirectional(zeus::CVector3f::skZero, parms.x10_color); + lt.x40_lightId = lightId; + ret = std::make_shared(parms, lt); + break; + } + default: + break; + } + + ret->ParseBaseInfo(frame, in, parms); + frame->RegisterLight(ret->shared_from_this()); + frame->AddLight(ret.get()); + return ret; } -void CGuiLight::SetIsVisible(bool vis) -{ - if (vis) - xb0_frame->AddLight(this); - else - xb0_frame->RemoveLight(this); - CGuiWidget::SetIsVisible(vis); -} - -std::shared_ptr CGuiLight::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - - ELightType tp = ELightType(in.readUint32Big()); - float distC = in.readFloatBig(); - float distL = in.readFloatBig(); - float distQ = in.readFloatBig(); - float angC = in.readFloatBig(); - float angL = in.readFloatBig(); - float angQ = in.readFloatBig(); - u32 lightId = in.readUint32Big(); - - std::shared_ptr ret = {}; - switch (tp) - { - case ELightType::Spot: - { - float cutoff = in.readFloatBig(); - CLight lt = CLight::BuildSpot(zeus::CVector3f::skZero, zeus::CVector3f::skZero, - parms.x10_color, cutoff); - lt.SetAttenuation(distC, distL, distQ); - lt.SetAngleAttenuation(angC, angL, angQ); - lt.x40_lightId = lightId; - ret = std::make_shared(parms, lt); - break; - } - case ELightType::Point: - { - CLight lt = CLight::BuildPoint(zeus::CVector3f::skZero, parms.x10_color); - lt.SetAttenuation(distC, distL, distQ); - lt.x40_lightId = lightId; - ret = std::make_shared(parms, lt); - break; - } - case ELightType::Directional: - { - CLight lt = CLight::BuildDirectional(zeus::CVector3f::skZero, parms.x10_color); - lt.x40_lightId = lightId; - ret = std::make_shared(parms, lt); - break; - } - default: break; - } - - ret->ParseBaseInfo(frame, in, parms); - frame->RegisterLight(ret->shared_from_this()); - frame->AddLight(ret.get()); - return ret; -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiLight.hpp b/Runtime/GuiSys/CGuiLight.hpp index 93b815690..1eaf5985e 100644 --- a/Runtime/GuiSys/CGuiLight.hpp +++ b/Runtime/GuiSys/CGuiLight.hpp @@ -3,46 +3,45 @@ #include "CGuiWidget.hpp" #include "Graphics/CLight.hpp" -namespace urde -{ +namespace urde { class CSimplePool; -class CGuiLight : public CGuiWidget -{ - ELightType xb8_type; - float xbc_spotCutoff; - float xc0_distC; - float xc4_distL; - float xc8_distQ; - float xcc_angleC; - float xd0_angleL; - float xd4_angleQ; - u32 xd8_lightId; - zeus::CColor xdc_ambColor = zeus::CColor::skBlack; +class CGuiLight : public CGuiWidget { + ELightType xb8_type; + float xbc_spotCutoff; + float xc0_distC; + float xc4_distL; + float xc8_distQ; + float xcc_angleC; + float xd0_angleL; + float xd4_angleQ; + u32 xd8_lightId; + zeus::CColor xdc_ambColor = zeus::CColor::skBlack; + public: - ~CGuiLight(); - CGuiLight(const CGuiWidgetParms& parms, const CLight& light); - FourCC GetWidgetTypeID() const { return FOURCC('LITE'); } + ~CGuiLight(); + CGuiLight(const CGuiWidgetParms& parms, const CLight& light); + FourCC GetWidgetTypeID() const { return FOURCC('LITE'); } - CLight BuildLight() const; - void SetIsVisible(bool vis); - u32 GetLightId() const {return xd8_lightId;} - const zeus::CColor& GetAmbientLightColor() const {return xdc_ambColor;} - void SetSpotCutoff(float v) {xbc_spotCutoff = v;} - void SetDistC(float v) {xc0_distC = v;} - void SetDistL(float v) {xc4_distL = v;} - void SetDistQ(float v) {xc8_distQ = v;} - void SetAngleC(float v) {xcc_angleC = v;} - void SetAngleL(float v) {xd0_angleL = v;} - void SetAngleQ(float v) {xd4_angleQ = v;} - void SetLightId(u32 idx) {xd8_lightId = idx;} - void SetAmbientLightColor(const zeus::CColor& color) {xdc_ambColor = color;} + CLight BuildLight() const; + void SetIsVisible(bool vis); + u32 GetLightId() const { return xd8_lightId; } + const zeus::CColor& GetAmbientLightColor() const { return xdc_ambColor; } + void SetSpotCutoff(float v) { xbc_spotCutoff = v; } + void SetDistC(float v) { xc0_distC = v; } + void SetDistL(float v) { xc4_distL = v; } + void SetDistQ(float v) { xc8_distQ = v; } + void SetAngleC(float v) { xcc_angleC = v; } + void SetAngleL(float v) { xd0_angleL = v; } + void SetAngleQ(float v) { xd4_angleQ = v; } + void SetLightId(u32 idx) { xd8_lightId = idx; } + void SetAmbientLightColor(const zeus::CColor& color) { xdc_ambColor = color; } - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); - std::shared_ptr shared_from_this() - { return std::static_pointer_cast(CGuiObject::shared_from_this()); } + std::shared_ptr shared_from_this() { + return std::static_pointer_cast(CGuiObject::shared_from_this()); + } }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiModel.cpp b/Runtime/GuiSys/CGuiModel.cpp index 0f92d0fd6..a038cf291 100644 --- a/Runtime/GuiSys/CGuiModel.cpp +++ b/Runtime/GuiSys/CGuiModel.cpp @@ -5,130 +5,114 @@ #include "CGuiWidgetDrawParms.hpp" #include "Graphics/CGraphics.hpp" -namespace urde -{ +namespace urde { CGuiModel::CGuiModel(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId modelId, u32 lightMask, bool flag) -: CGuiWidget(parms), xc8_modelId(modelId), xcc_lightMask(lightMask) -{ - if (!flag || !modelId.IsValid() || - parms.x0_frame->GetGuiSys().GetUsageMode() == CGuiSys::EUsageMode::Two) - return; +: CGuiWidget(parms), xc8_modelId(modelId), xcc_lightMask(lightMask) { + if (!flag || !modelId.IsValid() || parms.x0_frame->GetGuiSys().GetUsageMode() == CGuiSys::EUsageMode::Two) + return; - xb8_model = sp->GetObj({SBIG('CMDL'), modelId}); + xb8_model = sp->GetObj({SBIG('CMDL'), modelId}); } -std::vector CGuiModel::GetModelAssets() const -{ - return {xc8_modelId}; +std::vector CGuiModel::GetModelAssets() const { return {xc8_modelId}; } + +bool CGuiModel::GetIsFinishedLoadingWidgetSpecific() const { + if (!xb8_model) + return true; + const CModel* model = xb8_model.GetObj(); + if (!model) + return false; + model->GetInstance().Touch(0); + return model->IsLoaded(0); } -bool CGuiModel::GetIsFinishedLoadingWidgetSpecific() const -{ - if (!xb8_model) - return true; - const CModel* model = xb8_model.GetObj(); - if (!model) - return false; +void CGuiModel::Touch() const { + const CModel* model = xb8_model.GetObj(); + if (model) model->GetInstance().Touch(0); - return model->IsLoaded(0); } -void CGuiModel::Touch() const -{ - const CModel* model = xb8_model.GetObj(); - if (model) - model->GetInstance().Touch(0); -} +void CGuiModel::Draw(const CGuiWidgetDrawParms& parms) const { + CGraphics::SetModelMatrix(x34_worldXF); + if (!xb8_model) + return; + if (!GetIsFinishedLoading()) + return; + const CModel* model = xb8_model.GetObj(); + if (!model) + return; -void CGuiModel::Draw(const CGuiWidgetDrawParms& parms) const -{ - CGraphics::SetModelMatrix(x34_worldXF); - if (!xb8_model) - return; - if (!GetIsFinishedLoading()) - return; - const CModel* model = xb8_model.GetObj(); - if (!model) - return; + if (GetIsVisible()) { + zeus::CColor moduCol = xa8_color2; + moduCol.a() *= parms.x0_alphaMod; + xb0_frame->EnableLights(xcc_lightMask, const_cast(model->GetInstance())); + // if (xb6_29_cullFaces) + // CGraphics::SetCullMode(ERglCullMode::Front); - if (GetIsVisible()) - { - zeus::CColor moduCol = xa8_color2; - moduCol.a() *= parms.x0_alphaMod; - xb0_frame->EnableLights(xcc_lightMask, const_cast(model->GetInstance())); - //if (xb6_29_cullFaces) - // CGraphics::SetCullMode(ERglCullMode::Front); + switch (xac_drawFlags) { + case EGuiModelDrawFlags::Shadeless: { + CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + flags.m_extendedShader = EExtendedShader::Flat; + model->Draw(flags); + break; + } + case EGuiModelDrawFlags::Opaque: { + CModelFlags flags(1, 0, 3, moduCol); + flags.m_extendedShader = EExtendedShader::Lighting; + model->Draw(flags); + break; + } + case EGuiModelDrawFlags::Alpha: { + CModelFlags flags(5, 0, (u32(xb7_24_depthWrite) << 1) | u32(xb6_31_depthTest), moduCol); + flags.m_noCull = !xb6_29_cullFaces; + flags.m_noZWrite = !xb7_24_depthWrite; + model->Draw(flags); + break; + } + case EGuiModelDrawFlags::Additive: { + CModelFlags flags(7, 0, (u32(xb7_24_depthWrite) << 1) | u32(xb6_31_depthTest), moduCol); + flags.m_noCull = !xb6_29_cullFaces; + flags.m_noZWrite = !xb7_24_depthWrite; + model->Draw(flags); + break; + } + case EGuiModelDrawFlags::AlphaAdditiveOverdraw: { + CModelFlags flags(5, 0, xb6_31_depthTest, moduCol); + flags.m_noCull = !xb6_29_cullFaces; + flags.m_noZWrite = !xb7_24_depthWrite; + model->Draw(flags); - switch (xac_drawFlags) - { - case EGuiModelDrawFlags::Shadeless: - { - CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); - flags.m_extendedShader = EExtendedShader::Flat; - model->Draw(flags); - break; - } - case EGuiModelDrawFlags::Opaque: - { - CModelFlags flags(1, 0, 3, moduCol); - flags.m_extendedShader = EExtendedShader::Lighting; - model->Draw(flags); - break; - } - case EGuiModelDrawFlags::Alpha: - { - CModelFlags flags(5, 0, (u32(xb7_24_depthWrite) << 1) | u32(xb6_31_depthTest), moduCol); - flags.m_noCull = !xb6_29_cullFaces; - flags.m_noZWrite = !xb7_24_depthWrite; - model->Draw(flags); - break; - } - case EGuiModelDrawFlags::Additive: - { - CModelFlags flags(7, 0, (u32(xb7_24_depthWrite) << 1) | u32(xb6_31_depthTest), moduCol); - flags.m_noCull = !xb6_29_cullFaces; - flags.m_noZWrite = !xb7_24_depthWrite; - model->Draw(flags); - break; - } - case EGuiModelDrawFlags::AlphaAdditiveOverdraw: - { - CModelFlags flags(5, 0, xb6_31_depthTest, moduCol); - flags.m_noCull = !xb6_29_cullFaces; - flags.m_noZWrite = !xb7_24_depthWrite; - model->Draw(flags); - - flags.x0_blendMode = 7; - flags.x1_matSetIdx = 0; - flags.x2_flags = (u32(xb7_24_depthWrite) << 1) | u32(xb6_31_depthTest); - flags.x4_color = moduCol; - flags.m_noCull = !xb6_29_cullFaces; - model->Draw(flags); - break; - } - default: break; - } - - //if (xb6_29_cullFaces) - // CGraphics::SetCullMode(ERglCullMode::None); - xb0_frame->DisableLights(); + flags.x0_blendMode = 7; + flags.x1_matSetIdx = 0; + flags.x2_flags = (u32(xb7_24_depthWrite) << 1) | u32(xb6_31_depthTest); + flags.x4_color = moduCol; + flags.m_noCull = !xb6_29_cullFaces; + model->Draw(flags); + break; + } + default: + break; } - CGuiWidget::Draw(parms); + // if (xb6_29_cullFaces) + // CGraphics::SetCullMode(ERglCullMode::None); + xb0_frame->DisableLights(); + } + + CGuiWidget::Draw(parms); } -std::shared_ptr CGuiModel::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); +std::shared_ptr CGuiModel::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - CAssetId model = in.readUint32Big(); - in.readUint32Big(); - u32 lightMask = in.readUint32Big(); + CAssetId model = in.readUint32Big(); + in.readUint32Big(); + u32 lightMask = in.readUint32Big(); - std::shared_ptr ret = std::make_shared(parms, sp, model, lightMask, true); - ret->ParseBaseInfo(frame, in, parms); - return ret; + std::shared_ptr ret = std::make_shared(parms, sp, model, lightMask, true); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiModel.hpp b/Runtime/GuiSys/CGuiModel.hpp index fa6e0de38..d2d9feafc 100644 --- a/Runtime/GuiSys/CGuiModel.hpp +++ b/Runtime/GuiSys/CGuiModel.hpp @@ -4,26 +4,24 @@ #include "CToken.hpp" #include "Graphics/CModel.hpp" -namespace urde -{ +namespace urde { class CSimplePool; -class CGuiModel : public CGuiWidget -{ - TLockedToken xb8_model; - CAssetId xc8_modelId; - u32 xcc_lightMask; +class CGuiModel : public CGuiWidget { + TLockedToken xb8_model; + CAssetId xc8_modelId; + u32 xcc_lightMask; + public: - CGuiModel(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId modelId, u32 lightMask, bool flag); - FourCC GetWidgetTypeID() const { return FOURCC('MODL'); } + CGuiModel(const CGuiWidgetParms& parms, CSimplePool* sp, CAssetId modelId, u32 lightMask, bool flag); + FourCC GetWidgetTypeID() const { return FOURCC('MODL'); } - std::vector GetModelAssets() const; - bool GetIsFinishedLoadingWidgetSpecific() const; - void Touch() const; - void Draw(const CGuiWidgetDrawParms& parms) const; + std::vector GetModelAssets() const; + bool GetIsFinishedLoadingWidgetSpecific() const; + void Touch() const; + void Draw(const CGuiWidgetDrawParms& parms) const; - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiObject.cpp b/Runtime/GuiSys/CGuiObject.cpp index 04fcfbe7d..2711dff9e 100644 --- a/Runtime/GuiSys/CGuiObject.cpp +++ b/Runtime/GuiSys/CGuiObject.cpp @@ -4,156 +4,130 @@ #include "CGuiWidget.hpp" #include "CGuiFrame.hpp" -namespace urde -{ +namespace urde { -void CGuiObject::Update(float dt) -{ - if (x68_child) - x68_child->Update(dt); - if (x6c_nextSibling) - x6c_nextSibling->Update(dt); +void CGuiObject::Update(float dt) { + if (x68_child) + x68_child->Update(dt); + if (x6c_nextSibling) + x6c_nextSibling->Update(dt); } -void CGuiObject::Draw(const CGuiWidgetDrawParms& parms) const -{ - if (x68_child) - x68_child->Draw(parms); - if (x6c_nextSibling) - x6c_nextSibling->Draw(parms); +void CGuiObject::Draw(const CGuiWidgetDrawParms& parms) const { + if (x68_child) + x68_child->Draw(parms); + if (x6c_nextSibling) + x6c_nextSibling->Draw(parms); } -void CGuiObject::MoveInWorld(const zeus::CVector3f& vec) -{ - if (x64_parent) - x64_parent->RotateW2O(vec); - x4_localXF.origin += vec; - Reorthogonalize(); - RecalculateTransforms(); +void CGuiObject::MoveInWorld(const zeus::CVector3f& vec) { + if (x64_parent) + x64_parent->RotateW2O(vec); + x4_localXF.origin += vec; + Reorthogonalize(); + RecalculateTransforms(); } -void CGuiObject::SetLocalPosition(const zeus::CVector3f& pos) -{ - MoveInWorld(pos - x4_localXF.origin); +void CGuiObject::SetLocalPosition(const zeus::CVector3f& pos) { MoveInWorld(pos - x4_localXF.origin); } + +void CGuiObject::RotateReset() { + x4_localXF.basis = zeus::CMatrix3f::skIdentityMatrix3f; + Reorthogonalize(); + RecalculateTransforms(); } -void CGuiObject::RotateReset() -{ - x4_localXF.basis = zeus::CMatrix3f::skIdentityMatrix3f; - Reorthogonalize(); - RecalculateTransforms(); +zeus::CVector3f CGuiObject::RotateW2O(const zeus::CVector3f& vec) const { return x34_worldXF.transposeRotate(vec); } + +zeus::CVector3f CGuiObject::RotateO2P(const zeus::CVector3f& vec) const { return x4_localXF.rotate(vec); } + +zeus::CVector3f CGuiObject::RotateTranslateW2O(const zeus::CVector3f& vec) const { + return x34_worldXF.transposeRotate(vec - x34_worldXF.origin); } -zeus::CVector3f CGuiObject::RotateW2O(const zeus::CVector3f& vec) const -{ - return x34_worldXF.transposeRotate(vec); +void CGuiObject::MultiplyO2P(const zeus::CTransform& xf) { + x4_localXF = xf * x4_localXF; + Reorthogonalize(); + RecalculateTransforms(); } -zeus::CVector3f CGuiObject::RotateO2P(const zeus::CVector3f& vec) const -{ - return x4_localXF.rotate(vec); -} +void CGuiObject::AddChildObject(CGuiObject* obj, bool makeWorldLocal, bool atEnd) { + obj->x64_parent = this; -zeus::CVector3f CGuiObject::RotateTranslateW2O(const zeus::CVector3f& vec) const -{ - return x34_worldXF.transposeRotate(vec - x34_worldXF.origin); -} - -void CGuiObject::MultiplyO2P(const zeus::CTransform& xf) -{ - x4_localXF = xf * x4_localXF; - Reorthogonalize(); - RecalculateTransforms(); -} - -void CGuiObject::AddChildObject(CGuiObject* obj, bool makeWorldLocal, bool atEnd) -{ - obj->x64_parent = this; - - if (!x68_child) - { - x68_child = obj; - } - else if (atEnd) - { - CGuiObject* prev = nullptr; - CGuiObject* cur = x68_child; - for (; cur ; cur = cur->x6c_nextSibling) {prev = cur;} - if (prev) - prev->x6c_nextSibling = obj; - } - else - { - obj->x6c_nextSibling = x68_child; - x68_child = obj; - } - - if (makeWorldLocal) - { - zeus::CVector3f negParentWorld = -x34_worldXF.origin; - zeus::CMatrix3f basisMat( - x34_worldXF.basis[0] / x34_worldXF.basis[0].magnitude(), - x34_worldXF.basis[1] / x34_worldXF.basis[1].magnitude(), - x34_worldXF.basis[2] / x34_worldXF.basis[2].magnitude()); - zeus::CVector3f xfWorld = basisMat * negParentWorld; - obj->x4_localXF = zeus::CTransform(basisMat, xfWorld) * obj->x34_worldXF; - } - - RecalculateTransforms(); -} - -CGuiObject* CGuiObject::RemoveChildObject(CGuiObject* obj, bool makeWorldLocal) -{ + if (!x68_child) { + x68_child = obj; + } else if (atEnd) { CGuiObject* prev = nullptr; CGuiObject* cur = x68_child; - for (; cur && cur != obj ; cur = cur->x6c_nextSibling) {prev = cur;} - if (!cur) - return nullptr; - if (prev) - prev->x6c_nextSibling = cur->x6c_nextSibling; - cur->x6c_nextSibling = nullptr; - cur->x64_parent = nullptr; - - if (makeWorldLocal) - cur->x4_localXF = cur->x34_worldXF; - cur->RecalculateTransforms(); - - return cur; -} - -void CGuiObject::RecalculateTransforms() -{ - if (x64_parent) - x34_worldXF = x64_parent->x34_worldXF * x4_localXF; - else - x34_worldXF = x4_localXF; - - if (x6c_nextSibling) - x6c_nextSibling->RecalculateTransforms(); - if (x68_child) - x68_child->RecalculateTransforms(); -} - -void CGuiObject::Reorthogonalize() -{ - static bool Global = false; - if (Global) - { - x4_localXF.orthonormalize(); - RecalculateTransforms(); + for (; cur; cur = cur->x6c_nextSibling) { + prev = cur; } + if (prev) + prev->x6c_nextSibling = obj; + } else { + obj->x6c_nextSibling = x68_child; + x68_child = obj; + } + + if (makeWorldLocal) { + zeus::CVector3f negParentWorld = -x34_worldXF.origin; + zeus::CMatrix3f basisMat(x34_worldXF.basis[0] / x34_worldXF.basis[0].magnitude(), + x34_worldXF.basis[1] / x34_worldXF.basis[1].magnitude(), + x34_worldXF.basis[2] / x34_worldXF.basis[2].magnitude()); + zeus::CVector3f xfWorld = basisMat * negParentWorld; + obj->x4_localXF = zeus::CTransform(basisMat, xfWorld) * obj->x34_worldXF; + } + + RecalculateTransforms(); } -void CGuiObject::SetO2WTransform(const zeus::CTransform& xf) -{ - x4_localXF = GetParent()->x34_worldXF.inverse() * xf; +CGuiObject* CGuiObject::RemoveChildObject(CGuiObject* obj, bool makeWorldLocal) { + CGuiObject* prev = nullptr; + CGuiObject* cur = x68_child; + for (; cur && cur != obj; cur = cur->x6c_nextSibling) { + prev = cur; + } + if (!cur) + return nullptr; + if (prev) + prev->x6c_nextSibling = cur->x6c_nextSibling; + cur->x6c_nextSibling = nullptr; + cur->x64_parent = nullptr; + + if (makeWorldLocal) + cur->x4_localXF = cur->x34_worldXF; + cur->RecalculateTransforms(); + + return cur; +} + +void CGuiObject::RecalculateTransforms() { + if (x64_parent) + x34_worldXF = x64_parent->x34_worldXF * x4_localXF; + else + x34_worldXF = x4_localXF; + + if (x6c_nextSibling) + x6c_nextSibling->RecalculateTransforms(); + if (x68_child) + x68_child->RecalculateTransforms(); +} + +void CGuiObject::Reorthogonalize() { + static bool Global = false; + if (Global) { + x4_localXF.orthonormalize(); RecalculateTransforms(); + } } -void CGuiObject::SetLocalTransform(const zeus::CTransform& xf) -{ - x4_localXF = xf; - RecalculateTransforms(); +void CGuiObject::SetO2WTransform(const zeus::CTransform& xf) { + x4_localXF = GetParent()->x34_worldXF.inverse() * xf; + RecalculateTransforms(); } +void CGuiObject::SetLocalTransform(const zeus::CTransform& xf) { + x4_localXF = xf; + RecalculateTransforms(); } + +} // namespace urde diff --git a/Runtime/GuiSys/CGuiObject.hpp b/Runtime/GuiSys/CGuiObject.hpp index afde00bce..05d3aab2f 100644 --- a/Runtime/GuiSys/CGuiObject.hpp +++ b/Runtime/GuiSys/CGuiObject.hpp @@ -5,45 +5,43 @@ #include "zeus/CQuaternion.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { struct CGuiWidgetDrawParms; -class CGuiObject : public std::enable_shared_from_this -{ +class CGuiObject : public std::enable_shared_from_this { protected: - zeus::CTransform x4_localXF; - zeus::CTransform x34_worldXF; - CGuiObject* x64_parent = nullptr; - CGuiObject* x68_child = nullptr; - CGuiObject* x6c_nextSibling = nullptr; -public: - virtual ~CGuiObject() = default; - virtual void Update(float dt); - virtual void Draw(const CGuiWidgetDrawParms& parms) const; - virtual void Initialize()=0; + zeus::CTransform x4_localXF; + zeus::CTransform x34_worldXF; + CGuiObject* x64_parent = nullptr; + CGuiObject* x68_child = nullptr; + CGuiObject* x6c_nextSibling = nullptr; - void MoveInWorld(const zeus::CVector3f& vec); - const zeus::CVector3f& GetLocalPosition() const { return x4_localXF.origin; } - const zeus::CTransform& GetLocalTransform() const { return x4_localXF; } - void SetLocalPosition(const zeus::CVector3f& pos); - const zeus::CVector3f& GetWorldPosition() const { return x34_worldXF.origin; } - const zeus::CTransform& GetWorldTransform() const { return x34_worldXF; } - void RotateReset(); - zeus::CVector3f RotateW2O(const zeus::CVector3f& vec) const; - zeus::CVector3f RotateO2P(const zeus::CVector3f& vec) const; - zeus::CVector3f RotateTranslateW2O(const zeus::CVector3f& vec) const; - void MultiplyO2P(const zeus::CTransform& xf); - void AddChildObject(CGuiObject* obj, bool makeWorldLocal, bool atEnd); - CGuiObject* RemoveChildObject(CGuiObject* obj, bool makeWorldLocal); - CGuiObject* GetParent() const { return x64_parent; } - CGuiObject* GetChildObject() const { return x68_child; } - CGuiObject* GetNextSibling() const { return x6c_nextSibling; } - void RecalculateTransforms(); - void Reorthogonalize(); - void SetO2WTransform(const zeus::CTransform& xf); - void SetLocalTransform(const zeus::CTransform& xf); +public: + virtual ~CGuiObject() = default; + virtual void Update(float dt); + virtual void Draw(const CGuiWidgetDrawParms& parms) const; + virtual void Initialize() = 0; + + void MoveInWorld(const zeus::CVector3f& vec); + const zeus::CVector3f& GetLocalPosition() const { return x4_localXF.origin; } + const zeus::CTransform& GetLocalTransform() const { return x4_localXF; } + void SetLocalPosition(const zeus::CVector3f& pos); + const zeus::CVector3f& GetWorldPosition() const { return x34_worldXF.origin; } + const zeus::CTransform& GetWorldTransform() const { return x34_worldXF; } + void RotateReset(); + zeus::CVector3f RotateW2O(const zeus::CVector3f& vec) const; + zeus::CVector3f RotateO2P(const zeus::CVector3f& vec) const; + zeus::CVector3f RotateTranslateW2O(const zeus::CVector3f& vec) const; + void MultiplyO2P(const zeus::CTransform& xf); + void AddChildObject(CGuiObject* obj, bool makeWorldLocal, bool atEnd); + CGuiObject* RemoveChildObject(CGuiObject* obj, bool makeWorldLocal); + CGuiObject* GetParent() const { return x64_parent; } + CGuiObject* GetChildObject() const { return x68_child; } + CGuiObject* GetNextSibling() const { return x6c_nextSibling; } + void RecalculateTransforms(); + void Reorthogonalize(); + void SetO2WTransform(const zeus::CTransform& xf); + void SetLocalTransform(const zeus::CTransform& xf); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiPane.cpp b/Runtime/GuiSys/CGuiPane.cpp index a7e7abbf5..719d98f6f 100644 --- a/Runtime/GuiSys/CGuiPane.cpp +++ b/Runtime/GuiSys/CGuiPane.cpp @@ -1,62 +1,49 @@ #include "CGuiPane.hpp" -namespace urde -{ +namespace urde { -CGuiPane::CGuiPane(const CGuiWidgetParms& parms, const zeus::CVector2f& dim, - const zeus::CVector3f& scaleCenter) -: CGuiWidget(parms), xb8_dim(dim), xc8_scaleCenter(scaleCenter) -{ +CGuiPane::CGuiPane(const CGuiWidgetParms& parms, const zeus::CVector2f& dim, const zeus::CVector3f& scaleCenter) +: CGuiWidget(parms), xb8_dim(dim), xc8_scaleCenter(scaleCenter) { + InitializeBuffers(); +} + +void CGuiPane::ScaleDimensions(const zeus::CVector3f& scale) { + InitializeBuffers(); + + for (specter::View::TexShaderVert& v : xc0_verts) { + v.m_pos -= xc8_scaleCenter; + v.m_pos *= scale; + v.m_pos += xc8_scaleCenter; + } +} + +void CGuiPane::SetDimensions(const zeus::CVector2f& dim, bool initVBO) { + xb8_dim = dim; + if (initVBO) InitializeBuffers(); } -void CGuiPane::ScaleDimensions(const zeus::CVector3f& scale) -{ - InitializeBuffers(); +zeus::CVector2f CGuiPane::GetDimensions() const { return xb8_dim; } - for (specter::View::TexShaderVert& v : xc0_verts) - { - v.m_pos -= xc8_scaleCenter; - v.m_pos *= scale; - v.m_pos += xc8_scaleCenter; - } +void CGuiPane::InitializeBuffers() { + if (xc0_verts.size() < 4) + xc0_verts.resize(4); + + xc0_verts[0].m_pos.assign(-xb8_dim.x() * 0.5f, 0.f, xb8_dim.y() * 0.5f); + xc0_verts[1].m_pos.assign(-xb8_dim.x() * 0.5f, 0.f, -xb8_dim.y() * 0.5f); + xc0_verts[2].m_pos.assign(xb8_dim.x() * 0.5f, 0.f, xb8_dim.y() * 0.5f); + xc0_verts[3].m_pos.assign(xb8_dim.x() * 0.5f, 0.f, -xb8_dim.y() * 0.5f); } -void CGuiPane::SetDimensions(const zeus::CVector2f& dim, bool initVBO) -{ - xb8_dim = dim; - if (initVBO) - InitializeBuffers(); +void CGuiPane::WriteData(COutputStream& out, bool flag) const {} + +std::shared_ptr CGuiPane::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + zeus::CVector2f dim = zeus::CVector2f::ReadBig(in); + zeus::CVector3f scaleCenter = zeus::CVector3f::ReadBig(in); + std::shared_ptr ret = std::make_shared(parms, dim, scaleCenter); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -zeus::CVector2f CGuiPane::GetDimensions() const -{ - return xb8_dim; -} - -void CGuiPane::InitializeBuffers() -{ - if (xc0_verts.size() < 4) - xc0_verts.resize(4); - - xc0_verts[0].m_pos.assign(-xb8_dim.x() * 0.5f, 0.f, xb8_dim.y() * 0.5f); - xc0_verts[1].m_pos.assign(-xb8_dim.x() * 0.5f, 0.f, -xb8_dim.y() * 0.5f); - xc0_verts[2].m_pos.assign(xb8_dim.x() * 0.5f, 0.f, xb8_dim.y() * 0.5f); - xc0_verts[3].m_pos.assign(xb8_dim.x() * 0.5f, 0.f, -xb8_dim.y() * 0.5f); -} - -void CGuiPane::WriteData(COutputStream& out, bool flag) const -{ -} - -std::shared_ptr CGuiPane::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - zeus::CVector2f dim = zeus::CVector2f::ReadBig(in); - zeus::CVector3f scaleCenter = zeus::CVector3f::ReadBig(in); - std::shared_ptr ret = std::make_shared(parms, dim, scaleCenter); - ret->ParseBaseInfo(frame, in, parms); - return ret; -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiPane.hpp b/Runtime/GuiSys/CGuiPane.hpp index 46f70236b..377e8d631 100644 --- a/Runtime/GuiSys/CGuiPane.hpp +++ b/Runtime/GuiSys/CGuiPane.hpp @@ -3,32 +3,29 @@ #include "CGuiWidget.hpp" #include "specter/View.hpp" -namespace urde -{ +namespace urde { -class CGuiPane : public CGuiWidget -{ +class CGuiPane : public CGuiWidget { protected: - zeus::CVector2f xb8_dim; + zeus::CVector2f xb8_dim; - /* Originally a vert-buffer pointer for GX */ - std::vector xc0_verts; - // u32 x104_ = 4; /* vert count */ + /* Originally a vert-buffer pointer for GX */ + std::vector xc0_verts; + // u32 x104_ = 4; /* vert count */ - zeus::CVector3f xc8_scaleCenter; + zeus::CVector3f xc8_scaleCenter; public: - CGuiPane(const CGuiWidgetParms& parms, const zeus::CVector2f& dim, const zeus::CVector3f& scaleCenter); - FourCC GetWidgetTypeID() const { return FOURCC('PANE'); } + CGuiPane(const CGuiWidgetParms& parms, const zeus::CVector2f& dim, const zeus::CVector3f& scaleCenter); + FourCC GetWidgetTypeID() const { return FOURCC('PANE'); } - virtual void ScaleDimensions(const zeus::CVector3f& scale); - virtual void SetDimensions(const zeus::CVector2f& dim, bool initVBO); - virtual zeus::CVector2f GetDimensions() const; - virtual void InitializeBuffers(); - virtual void WriteData(COutputStream& out, bool flag) const; + virtual void ScaleDimensions(const zeus::CVector3f& scale); + virtual void SetDimensions(const zeus::CVector2f& dim, bool initVBO); + virtual zeus::CVector2f GetDimensions() const; + virtual void InitializeBuffers(); + virtual void WriteData(COutputStream& out, bool flag) const; - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiSliderGroup.cpp b/Runtime/GuiSys/CGuiSliderGroup.cpp index 7a7d91755..2b64f278c 100644 --- a/Runtime/GuiSys/CGuiSliderGroup.cpp +++ b/Runtime/GuiSys/CGuiSliderGroup.cpp @@ -1,142 +1,126 @@ #include "CGuiSliderGroup.hpp" #include "Input/CFinalInput.hpp" -namespace urde -{ +namespace urde { CGuiSliderGroup::CGuiSliderGroup(const CGuiWidgetParms& parms, float min, float max, float def, float inc) -: CGuiCompoundWidget(parms), xb8_minVal(min), xbc_maxVal(max), - xc0_roundedCurVal(def), xc4_curVal(def), xc8_increment(inc) -{ +: CGuiCompoundWidget(parms) +, xb8_minVal(min) +, xbc_maxVal(max) +, xc0_roundedCurVal(def) +, xc4_curVal(def) +, xc8_increment(inc) {} + +void CGuiSliderGroup::SetSelectionChangedCallback(std::function&& func) { + xd8_changeCallback = std::move(func); } -void CGuiSliderGroup::SetSelectionChangedCallback - (std::function&& func) -{ - xd8_changeCallback = std::move(func); +void CGuiSliderGroup::SetCurVal(float cur) { + xc0_roundedCurVal = zeus::clamp(xb8_minVal, cur, xbc_maxVal); + xc4_curVal = xc0_roundedCurVal; } -void CGuiSliderGroup::SetCurVal(float cur) -{ - xc0_roundedCurVal = zeus::clamp(xb8_minVal, cur, xbc_maxVal); - xc4_curVal = xc0_roundedCurVal; +void CGuiSliderGroup::StartDecreasing() { + xf0_state = EState::Decreasing; + xf4_24_inputPending = true; } -void CGuiSliderGroup::StartDecreasing() -{ - xf0_state = EState::Decreasing; - xf4_24_inputPending = true; +void CGuiSliderGroup::StartIncreasing() { + xf0_state = EState::Increasing; + xf4_24_inputPending = true; } -void CGuiSliderGroup::StartIncreasing() -{ - xf0_state = EState::Increasing; - xf4_24_inputPending = true; +void CGuiSliderGroup::ProcessUserInput(const CFinalInput& input) { + if (input.DLALeft()) { + StartDecreasing(); + return; + } + if (input.DLARight()) { + StartIncreasing(); + return; + } + if (input.PDPLeft()) { + StartDecreasing(); + return; + } + if (input.PDPRight()) { + StartIncreasing(); + return; + } } -void CGuiSliderGroup::ProcessUserInput(const CFinalInput& input) -{ - if (input.DLALeft()) - { - StartDecreasing(); - return; - } - if (input.DLARight()) - { - StartIncreasing(); - return; - } - if (input.PDPLeft()) - { - StartDecreasing(); - return; - } - if (input.PDPRight()) - { - StartIncreasing(); - return; - } -} +void CGuiSliderGroup::Update(float dt) { + float fullRange = xbc_maxVal - xb8_minVal; + float t1 = fullRange * dt; -void CGuiSliderGroup::Update(float dt) -{ - float fullRange = xbc_maxVal - xb8_minVal; - float t1 = fullRange * dt; + float incCurVal; + for (incCurVal = xb8_minVal; incCurVal <= xc4_curVal; incCurVal += xc8_increment) {} - float incCurVal; - for (incCurVal = xb8_minVal ; incCurVal <= xc4_curVal ; incCurVal += xc8_increment) {} + float upperIncVal = std::min(incCurVal, xbc_maxVal); + float lowerIncVal = upperIncVal - xc8_increment; - float upperIncVal = std::min(incCurVal, xbc_maxVal); - float lowerIncVal = upperIncVal - xc8_increment; - - float oldCurVal = xc4_curVal; - if (xf0_state == EState::Decreasing) - { - if (xf4_24_inputPending) - xc4_curVal = std::max(oldCurVal - t1, xb8_minVal); - else - xc4_curVal = std::max(oldCurVal - t1, lowerIncVal); - } - else if (xf0_state == EState::Increasing) - { - if (xf4_24_inputPending) - xc4_curVal = std::min(oldCurVal + t1, xbc_maxVal); - else if (xc4_curVal != lowerIncVal) - xc4_curVal = std::min(oldCurVal + t1, upperIncVal); - } - - if (xc4_curVal == oldCurVal) - xf0_state = EState::None; - - oldCurVal = xc0_roundedCurVal; - if (upperIncVal - xc4_curVal <= xc4_curVal - lowerIncVal) - xc0_roundedCurVal = upperIncVal; + float oldCurVal = xc4_curVal; + if (xf0_state == EState::Decreasing) { + if (xf4_24_inputPending) + xc4_curVal = std::max(oldCurVal - t1, xb8_minVal); else - xc0_roundedCurVal = lowerIncVal; + xc4_curVal = std::max(oldCurVal - t1, lowerIncVal); + } else if (xf0_state == EState::Increasing) { + if (xf4_24_inputPending) + xc4_curVal = std::min(oldCurVal + t1, xbc_maxVal); + else if (xc4_curVal != lowerIncVal) + xc4_curVal = std::min(oldCurVal + t1, upperIncVal); + } - if (oldCurVal != xc0_roundedCurVal && xd8_changeCallback) - xd8_changeCallback(this, oldCurVal); + if (xc4_curVal == oldCurVal) + xf0_state = EState::None; - float fac; - if (xbc_maxVal == xb8_minVal) - fac = 0.f; - else - fac = (xc4_curVal - xb8_minVal) / (xbc_maxVal - xb8_minVal); + oldCurVal = xc0_roundedCurVal; + if (upperIncVal - xc4_curVal <= xc4_curVal - lowerIncVal) + xc0_roundedCurVal = upperIncVal; + else + xc0_roundedCurVal = lowerIncVal; - const zeus::CVector3f& s0 = xcc_sliderRangeWidgets[0]->GetIdlePosition(); - const zeus::CVector3f& s1 = xcc_sliderRangeWidgets[1]->GetIdlePosition(); + if (oldCurVal != xc0_roundedCurVal && xd8_changeCallback) + xd8_changeCallback(this, oldCurVal); - xcc_sliderRangeWidgets[0]->SetLocalPosition(s1 * fac + s0 * (1.f - fac)); - xf4_24_inputPending = false; + float fac; + if (xbc_maxVal == xb8_minVal) + fac = 0.f; + else + fac = (xc4_curVal - xb8_minVal) / (xbc_maxVal - xb8_minVal); + + const zeus::CVector3f& s0 = xcc_sliderRangeWidgets[0]->GetIdlePosition(); + const zeus::CVector3f& s1 = xcc_sliderRangeWidgets[1]->GetIdlePosition(); + + xcc_sliderRangeWidgets[0]->SetLocalPosition(s1 * fac + s0 * (1.f - fac)); + xf4_24_inputPending = false; } -bool CGuiSliderGroup::AddWorkerWidget(CGuiWidget* worker) -{ - if (worker->GetWorkerId() < 0 || worker->GetWorkerId() > 1) - return true; - xcc_sliderRangeWidgets[worker->GetWorkerId()] = worker; +bool CGuiSliderGroup::AddWorkerWidget(CGuiWidget* worker) { + if (worker->GetWorkerId() < 0 || worker->GetWorkerId() > 1) return true; + xcc_sliderRangeWidgets[worker->GetWorkerId()] = worker; + return true; } -CGuiWidget* CGuiSliderGroup::GetWorkerWidget(int id) const -{ - if (id < 0 || id > 1) - return nullptr; - return xcc_sliderRangeWidgets[id]; +CGuiWidget* CGuiSliderGroup::GetWorkerWidget(int id) const { + if (id < 0 || id > 1) + return nullptr; + return xcc_sliderRangeWidgets[id]; } -std::shared_ptr CGuiSliderGroup::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); +std::shared_ptr CGuiSliderGroup::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - float min = in.readFloatBig(); - float max = in.readFloatBig(); - float cur = in.readFloatBig(); - float increment = in.readFloatBig(); + float min = in.readFloatBig(); + float max = in.readFloatBig(); + float cur = in.readFloatBig(); + float increment = in.readFloatBig(); - std::shared_ptr ret = std::make_shared(parms, min, max, cur, increment); - ret->ParseBaseInfo(frame, in, parms); - return ret; + std::shared_ptr ret = std::make_shared(parms, min, max, cur, increment); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiSliderGroup.hpp b/Runtime/GuiSys/CGuiSliderGroup.hpp index 1718ae9fc..54921f1da 100644 --- a/Runtime/GuiSys/CGuiSliderGroup.hpp +++ b/Runtime/GuiSys/CGuiSliderGroup.hpp @@ -3,60 +3,57 @@ #include "CGuiCompoundWidget.hpp" #include -namespace urde -{ +namespace urde { class CSimplePool; -class CGuiSliderGroup : public CGuiCompoundWidget -{ +class CGuiSliderGroup : public CGuiCompoundWidget { public: - enum class EState - { - None, - Decreasing, - Increasing - }; + enum class EState { None, Decreasing, Increasing }; private: - float xb8_minVal; - float xbc_maxVal; - float xc0_roundedCurVal; - float xc4_curVal; - float xc8_increment; - CGuiWidget* xcc_sliderRangeWidgets[2] = {}; - std::function xd8_changeCallback; - EState xf0_state = EState::None; - union { - struct - { - bool xf4_24_inputPending : 1; - }; - u8 _dummy = 0; + float xb8_minVal; + float xbc_maxVal; + float xc0_roundedCurVal; + float xc4_curVal; + float xc8_increment; + CGuiWidget* xcc_sliderRangeWidgets[2] = {}; + std::function xd8_changeCallback; + EState xf0_state = EState::None; + union { + struct { + bool xf4_24_inputPending : 1; }; + u8 _dummy = 0; + }; - void StartDecreasing(); - void StartIncreasing(); + void StartDecreasing(); + void StartIncreasing(); public: - CGuiSliderGroup(const CGuiWidgetParms& parms, float a, float b, float c, float d); - FourCC GetWidgetTypeID() const { return FOURCC('SLGP'); } + CGuiSliderGroup(const CGuiWidgetParms& parms, float a, float b, float c, float d); + FourCC GetWidgetTypeID() const { return FOURCC('SLGP'); } - EState GetState() const { return xf0_state; } - void SetSelectionChangedCallback(std::function&& func); - void SetIncrement(float inc) { xc8_increment = inc; } - void SetMinVal(float min) { xb8_minVal = min; SetCurVal(xc0_roundedCurVal); } - void SetMaxVal(float max) { xbc_maxVal = max; SetCurVal(xc0_roundedCurVal); } - void SetCurVal(float cur); - float GetGurVal() const { return xc0_roundedCurVal; } + EState GetState() const { return xf0_state; } + void SetSelectionChangedCallback(std::function&& func); + void SetIncrement(float inc) { xc8_increment = inc; } + void SetMinVal(float min) { + xb8_minVal = min; + SetCurVal(xc0_roundedCurVal); + } + void SetMaxVal(float max) { + xbc_maxVal = max; + SetCurVal(xc0_roundedCurVal); + } + void SetCurVal(float cur); + float GetGurVal() const { return xc0_roundedCurVal; } - void ProcessUserInput(const CFinalInput& input); - void Update(float dt); + void ProcessUserInput(const CFinalInput& input); + void Update(float dt); - bool AddWorkerWidget(CGuiWidget* worker); - CGuiWidget* GetWorkerWidget(int id) const; + bool AddWorkerWidget(CGuiWidget* worker); + CGuiWidget* GetWorkerWidget(int id) const; - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiSys.cpp b/Runtime/GuiSys/CGuiSys.cpp index 712424275..b93e70f18 100644 --- a/Runtime/GuiSys/CGuiSys.cpp +++ b/Runtime/GuiSys/CGuiSys.cpp @@ -17,89 +17,80 @@ #include "CTextExecuteBuffer.hpp" #include "CGuiFrame.hpp" -namespace urde -{ +namespace urde { CGuiSys* g_GuiSys = nullptr; CTextExecuteBuffer* g_TextExecuteBuf = nullptr; CTextParser* g_TextParser = nullptr; -std::shared_ptr CGuiSys::CreateWidgetInGame(FourCC type, CInputStream& in, - CGuiFrame* frame, CSimplePool* sp) -{ - switch (type) - { - case SBIG('BWIG'): - return CGuiWidget::Create(frame, in, sp); - case SBIG('HWIG'): - return CGuiHeadWidget::Create(frame, in, sp); - case SBIG('LITE'): - return CGuiLight::Create(frame, in, sp); - case SBIG('CAMR'): - return CGuiCamera::Create(frame, in, sp); - case SBIG('GRUP'): - return CGuiGroup::Create(frame, in, sp); - case SBIG('PANE'): - return CGuiPane::Create(frame, in, sp); - case SBIG('IMGP'): - return CAuiImagePane::Create(frame, in, sp); - case SBIG('METR'): - return CAuiMeter::Create(frame, in, sp); - case SBIG('MODL'): - return CGuiModel::Create(frame, in, sp); - case SBIG('TBGP'): - return CGuiTableGroup::Create(frame, in, sp); - case SBIG('SLGP'): - return CGuiSliderGroup::Create(frame, in, sp); - case SBIG('TXPN'): - return CGuiTextPane::Create(frame, in, sp); - case SBIG('ENRG'): - return CAuiEnergyBarT01::Create(frame, in, sp); - default: break; - } - return {}; +std::shared_ptr CGuiSys::CreateWidgetInGame(FourCC type, CInputStream& in, CGuiFrame* frame, + CSimplePool* sp) { + switch (type) { + case SBIG('BWIG'): + return CGuiWidget::Create(frame, in, sp); + case SBIG('HWIG'): + return CGuiHeadWidget::Create(frame, in, sp); + case SBIG('LITE'): + return CGuiLight::Create(frame, in, sp); + case SBIG('CAMR'): + return CGuiCamera::Create(frame, in, sp); + case SBIG('GRUP'): + return CGuiGroup::Create(frame, in, sp); + case SBIG('PANE'): + return CGuiPane::Create(frame, in, sp); + case SBIG('IMGP'): + return CAuiImagePane::Create(frame, in, sp); + case SBIG('METR'): + return CAuiMeter::Create(frame, in, sp); + case SBIG('MODL'): + return CGuiModel::Create(frame, in, sp); + case SBIG('TBGP'): + return CGuiTableGroup::Create(frame, in, sp); + case SBIG('SLGP'): + return CGuiSliderGroup::Create(frame, in, sp); + case SBIG('TXPN'): + return CGuiTextPane::Create(frame, in, sp); + case SBIG('ENRG'): + return CAuiEnergyBarT01::Create(frame, in, sp); + default: + break; + } + return {}; } CGuiSys::CGuiSys(IFactory& resFactory, CSimplePool& resStore, EUsageMode mode) -: x0_resFactory(resFactory), x4_resStore(resStore), x8_mode(mode), - xc_textExecuteBuf(new CTextExecuteBuffer()), - x10_textParser(new CTextParser(resStore)) -{ - g_TextExecuteBuf = xc_textExecuteBuf.get(); - g_TextParser = x10_textParser.get(); +: x0_resFactory(resFactory) +, x4_resStore(resStore) +, x8_mode(mode) +, xc_textExecuteBuf(new CTextExecuteBuffer()) +, x10_textParser(new CTextParser(resStore)) { + g_TextExecuteBuf = xc_textExecuteBuf.get(); + g_TextParser = x10_textParser.get(); } -void CGuiSys::OnViewportResize() -{ - for (CGuiFrame* frame : m_registeredFrames) - ViewportResizeFrame(frame); +void CGuiSys::OnViewportResize() { + for (CGuiFrame* frame : m_registeredFrames) + ViewportResizeFrame(frame); } -void CGuiSys::ViewportResizeFrame(CGuiFrame* frame) -{ - float vpAspectRatio = g_Viewport.x8_width / float(g_Viewport.xc_height); - if (frame->m_aspectConstraint > 0.f) - { - float hPad, vPad; - if (vpAspectRatio >= frame->m_aspectConstraint) - { - hPad = frame->m_aspectConstraint / vpAspectRatio; - vPad = frame->m_aspectConstraint / 1.38f; - } - else - { - hPad = 1.f; - vPad = vpAspectRatio / 1.38f; - } - frame->m_aspectTransform = zeus::CTransform::Scale({hPad, 1.f, vPad}); - } - else if (frame->m_maxAspect > 0.f) - { - if (vpAspectRatio > frame->m_maxAspect) - frame->m_aspectTransform = zeus::CTransform::Scale({frame->m_maxAspect / vpAspectRatio, 1.f, 1.f}); - else - frame->m_aspectTransform = zeus::CTransform::Identity(); +void CGuiSys::ViewportResizeFrame(CGuiFrame* frame) { + float vpAspectRatio = g_Viewport.x8_width / float(g_Viewport.xc_height); + if (frame->m_aspectConstraint > 0.f) { + float hPad, vPad; + if (vpAspectRatio >= frame->m_aspectConstraint) { + hPad = frame->m_aspectConstraint / vpAspectRatio; + vPad = frame->m_aspectConstraint / 1.38f; + } else { + hPad = 1.f; + vPad = vpAspectRatio / 1.38f; } + frame->m_aspectTransform = zeus::CTransform::Scale({hPad, 1.f, vPad}); + } else if (frame->m_maxAspect > 0.f) { + if (vpAspectRatio > frame->m_maxAspect) + frame->m_aspectTransform = zeus::CTransform::Scale({frame->m_maxAspect / vpAspectRatio, 1.f, 1.f}); + else + frame->m_aspectTransform = zeus::CTransform::Identity(); + } } -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiSys.hpp b/Runtime/GuiSys/CGuiSys.hpp index 328c5741a..3663cf808 100644 --- a/Runtime/GuiSys/CGuiSys.hpp +++ b/Runtime/GuiSys/CGuiSys.hpp @@ -7,8 +7,7 @@ #include "CSaveableState.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { class CGuiObject; class CVParamTransfer; struct SObjectTag; @@ -19,34 +18,31 @@ class CGuiFrame; class CTextParser; class CTextExecuteBuffer; -class CGuiSys -{ - friend class CGuiFrame; +class CGuiSys { + friend class CGuiFrame; + public: - enum class EUsageMode - { - Zero, - One, - Two - }; + enum class EUsageMode { Zero, One, Two }; + private: - IFactory& x0_resFactory; - CSimplePool& x4_resStore; - EUsageMode x8_mode; - std::unique_ptr xc_textExecuteBuf; - std::unique_ptr x10_textParser; - std::unordered_set m_registeredFrames; + IFactory& x0_resFactory; + CSimplePool& x4_resStore; + EUsageMode x8_mode; + std::unique_ptr xc_textExecuteBuf; + std::unique_ptr x10_textParser; + std::unordered_set m_registeredFrames; + + static std::shared_ptr CreateWidgetInGame(FourCC type, CInputStream& in, CGuiFrame* frame, + CSimplePool* sp); - static std::shared_ptr CreateWidgetInGame(FourCC type, CInputStream& in, - CGuiFrame* frame, CSimplePool* sp); public: - CGuiSys(IFactory& resFactory, CSimplePool& resStore, EUsageMode mode); + CGuiSys(IFactory& resFactory, CSimplePool& resStore, EUsageMode mode); - CSimplePool& GetResStore() {return x4_resStore;} - EUsageMode GetUsageMode() const {return x8_mode;} + CSimplePool& GetResStore() { return x4_resStore; } + EUsageMode GetUsageMode() const { return x8_mode; } - void OnViewportResize(); - static void ViewportResizeFrame(CGuiFrame* frame); + void OnViewportResize(); + static void ViewportResizeFrame(CGuiFrame* frame); }; /** Global GuiSys instance */ @@ -58,5 +54,4 @@ extern CTextExecuteBuffer* g_TextExecuteBuf; /** Global CTextParser instance */ extern CTextParser* g_TextParser; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiTableGroup.cpp b/Runtime/GuiSys/CGuiTableGroup.cpp index fa44c9fb5..e0bf5dc03 100644 --- a/Runtime/GuiSys/CGuiTableGroup.cpp +++ b/Runtime/GuiSys/CGuiTableGroup.cpp @@ -1,269 +1,211 @@ #include "CGuiTableGroup.hpp" #include "Input/CFinalInput.hpp" -namespace urde -{ +namespace urde { -bool CGuiTableGroup::CRepeatState::Update(float dt, bool state) -{ - if (x0_timer == 0.f) - { - if (state) - { - x0_timer = 0.6f; - return true; - } +bool CGuiTableGroup::CRepeatState::Update(float dt, bool state) { + if (x0_timer == 0.f) { + if (state) { + x0_timer = 0.6f; + return true; } + } else { + if (state) { + x0_timer -= dt; + if (x0_timer <= 0.f) { + x0_timer = 0.05f; + return true; + } + } else { + x0_timer = 0.f; + } + } + return false; +} + +CGuiTableGroup::CGuiTableGroup(const CGuiWidgetParms& parms, int elementCount, int defaultSel, bool selectWraparound) +: CGuiCompoundWidget(parms) +, xc0_elementCount(elementCount) +, xc4_userSelection(defaultSel) +, xc8_prevUserSelection(defaultSel) +, xcc_defaultUserSelection(defaultSel) +, xd0_selectWraparound(selectWraparound) {} + +void CGuiTableGroup::ProcessUserInput(const CFinalInput& input) { + if (input.PA()) { + DoAdvance(); + } else if (input.PB()) { + DoCancel(); + } else { + bool decrement; + if (xd1_vertical) + decrement = (input.DLAUp() || input.DDPUp()); else - { - if (state) - { - x0_timer -= dt; - if (x0_timer <= 0.f) - { - x0_timer = 0.05f; - return true; - } - } - else - { - x0_timer = 0.f; - } - } - return false; -} + decrement = (input.DLALeft() || input.DDPLeft()); -CGuiTableGroup::CGuiTableGroup(const CGuiWidgetParms& parms, int elementCount, - int defaultSel, bool selectWraparound) -: CGuiCompoundWidget(parms), - xc0_elementCount(elementCount), xc4_userSelection(defaultSel), - xc8_prevUserSelection(defaultSel), xcc_defaultUserSelection(defaultSel), - xd0_selectWraparound(selectWraparound) -{} - -void CGuiTableGroup::ProcessUserInput(const CFinalInput& input) -{ - if (input.PA()) - { - DoAdvance(); - } - else if (input.PB()) - { - DoCancel(); - } + bool increment; + if (xd1_vertical) + increment = (input.DLADown() || input.DDPDown()); else - { - bool decrement; - if (xd1_vertical) - decrement = (input.DLAUp() || input.DDPUp()); - else - decrement = (input.DLALeft() || input.DDPLeft()); + increment = (input.DLARight() || input.DDPRight()); - bool increment; - if (xd1_vertical) - increment = (input.DLADown() || input.DDPDown()); - else - increment = (input.DLARight() || input.DDPRight()); - - if (xb8_decRepeat.Update(input.DeltaTime(), decrement) && decrement) - { - DoDecrement(); - return; - } - - if (xbc_incRepeat.Update(input.DeltaTime(), increment) && increment) - { - DoIncrement(); - return; - } - } -} - -bool CGuiTableGroup::IsWorkerSelectable(int idx) const -{ - if (CGuiWidget* widget = GetWorkerWidget(idx)) - return widget->GetIsSelectable(); - return false; -} - -void CGuiTableGroup::SelectWorker(int idx) -{ - idx = zeus::clamp(0, idx, xc0_elementCount - 1); - if (idx < xc4_userSelection) - { - while (idx != xc4_userSelection) - DoSelectPrevRow(); - } - else - { - while (idx != xc4_userSelection) - DoSelectNextRow(); - } -} - -void CGuiTableGroup::DeactivateWorker(CGuiWidget* widget) -{ - widget->SetIsActive(false); -} - -void CGuiTableGroup::ActivateWorker(CGuiWidget* widget) -{ - widget->SetIsActive(true); -} - -CGuiTableGroup::TableSelectReturn CGuiTableGroup::DecrementSelectedRow() -{ - xc8_prevUserSelection = xc4_userSelection; - --xc4_userSelection; - if (xc4_userSelection < 0) - { - xc4_userSelection = xd0_selectWraparound ? xc0_elementCount - 1 : 0; - return xd0_selectWraparound ? TableSelectReturn::WrappedAround : TableSelectReturn::Unchanged; - } - return TableSelectReturn::Changed; -} - -CGuiTableGroup::TableSelectReturn CGuiTableGroup::IncrementSelectedRow() -{ - xc8_prevUserSelection = xc4_userSelection; - ++xc4_userSelection; - if (xc4_userSelection >= xc0_elementCount) - { - xc4_userSelection = xd0_selectWraparound ? 0 : xc0_elementCount - 1; - return xd0_selectWraparound ? TableSelectReturn::WrappedAround : TableSelectReturn::Unchanged; - } - return TableSelectReturn::Changed; -} - -void CGuiTableGroup::DoSelectPrevRow() -{ - DecrementSelectedRow(); - DeactivateWorker(GetWorkerWidget(xc8_prevUserSelection)); - ActivateWorker(GetWorkerWidget(xc4_userSelection)); -} - -void CGuiTableGroup::DoSelectNextRow() -{ - IncrementSelectedRow(); - DeactivateWorker(GetWorkerWidget(xc8_prevUserSelection)); - ActivateWorker(GetWorkerWidget(xc4_userSelection)); -} - -void CGuiTableGroup::DoCancel() -{ - if (xec_doMenuCancel) - xec_doMenuCancel(this); -} - -void CGuiTableGroup::DoAdvance() -{ - if (xd4_doMenuAdvance) - xd4_doMenuAdvance(this); -} - -bool CGuiTableGroup::PreDecrement() -{ - if (xd0_selectWraparound) - { - for (int sel = (xc4_userSelection + xc0_elementCount - 1) % xc0_elementCount; - sel != xc4_userSelection; - sel = (sel + xc0_elementCount - 1) % xc0_elementCount) - { - if (IsWorkerSelectable(sel)) - { - SelectWorker(sel); - return true; - } - } - - } - else - { - for (int sel = std::max(-1, xc4_userSelection - 1) ; sel >= 0 ; --sel) - { - if (IsWorkerSelectable(sel)) - { - SelectWorker(sel); - return true; - } - } + if (xb8_decRepeat.Update(input.DeltaTime(), decrement) && decrement) { + DoDecrement(); + return; } - return false; -} - -void CGuiTableGroup::DoDecrement() -{ - int oldSel = xc4_userSelection; - if (!PreDecrement()) - return; - if (x104_doMenuSelChange) - x104_doMenuSelChange(this, oldSel); -} - -bool CGuiTableGroup::PreIncrement() -{ - if (xd0_selectWraparound) - { - for (int sel = (xc4_userSelection + 1) % xc0_elementCount; - sel != xc4_userSelection; - sel = (sel + 1) % xc0_elementCount) - { - if (IsWorkerSelectable(sel)) - { - SelectWorker(sel); - return true; - } - } - + if (xbc_incRepeat.Update(input.DeltaTime(), increment) && increment) { + DoIncrement(); + return; } - else - { - for (int sel = std::min(xc0_elementCount, xc4_userSelection + 1) ; sel < xc0_elementCount ; ++sel) - { - if (IsWorkerSelectable(sel)) - { - SelectWorker(sel); - return true; - } - } + } +} + +bool CGuiTableGroup::IsWorkerSelectable(int idx) const { + if (CGuiWidget* widget = GetWorkerWidget(idx)) + return widget->GetIsSelectable(); + return false; +} + +void CGuiTableGroup::SelectWorker(int idx) { + idx = zeus::clamp(0, idx, xc0_elementCount - 1); + if (idx < xc4_userSelection) { + while (idx != xc4_userSelection) + DoSelectPrevRow(); + } else { + while (idx != xc4_userSelection) + DoSelectNextRow(); + } +} + +void CGuiTableGroup::DeactivateWorker(CGuiWidget* widget) { widget->SetIsActive(false); } + +void CGuiTableGroup::ActivateWorker(CGuiWidget* widget) { widget->SetIsActive(true); } + +CGuiTableGroup::TableSelectReturn CGuiTableGroup::DecrementSelectedRow() { + xc8_prevUserSelection = xc4_userSelection; + --xc4_userSelection; + if (xc4_userSelection < 0) { + xc4_userSelection = xd0_selectWraparound ? xc0_elementCount - 1 : 0; + return xd0_selectWraparound ? TableSelectReturn::WrappedAround : TableSelectReturn::Unchanged; + } + return TableSelectReturn::Changed; +} + +CGuiTableGroup::TableSelectReturn CGuiTableGroup::IncrementSelectedRow() { + xc8_prevUserSelection = xc4_userSelection; + ++xc4_userSelection; + if (xc4_userSelection >= xc0_elementCount) { + xc4_userSelection = xd0_selectWraparound ? 0 : xc0_elementCount - 1; + return xd0_selectWraparound ? TableSelectReturn::WrappedAround : TableSelectReturn::Unchanged; + } + return TableSelectReturn::Changed; +} + +void CGuiTableGroup::DoSelectPrevRow() { + DecrementSelectedRow(); + DeactivateWorker(GetWorkerWidget(xc8_prevUserSelection)); + ActivateWorker(GetWorkerWidget(xc4_userSelection)); +} + +void CGuiTableGroup::DoSelectNextRow() { + IncrementSelectedRow(); + DeactivateWorker(GetWorkerWidget(xc8_prevUserSelection)); + ActivateWorker(GetWorkerWidget(xc4_userSelection)); +} + +void CGuiTableGroup::DoCancel() { + if (xec_doMenuCancel) + xec_doMenuCancel(this); +} + +void CGuiTableGroup::DoAdvance() { + if (xd4_doMenuAdvance) + xd4_doMenuAdvance(this); +} + +bool CGuiTableGroup::PreDecrement() { + if (xd0_selectWraparound) { + for (int sel = (xc4_userSelection + xc0_elementCount - 1) % xc0_elementCount; sel != xc4_userSelection; + sel = (sel + xc0_elementCount - 1) % xc0_elementCount) { + if (IsWorkerSelectable(sel)) { + SelectWorker(sel); + return true; + } } - return false; + } else { + for (int sel = std::max(-1, xc4_userSelection - 1); sel >= 0; --sel) { + if (IsWorkerSelectable(sel)) { + SelectWorker(sel); + return true; + } + } + } + + return false; } -void CGuiTableGroup::DoIncrement() -{ - int oldSel = xc4_userSelection; - if (!PreIncrement()) - return; - if (x104_doMenuSelChange) - x104_doMenuSelChange(this, oldSel); +void CGuiTableGroup::DoDecrement() { + int oldSel = xc4_userSelection; + if (!PreDecrement()) + return; + if (x104_doMenuSelChange) + x104_doMenuSelChange(this, oldSel); } -std::shared_ptr CGuiTableGroup::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); +bool CGuiTableGroup::PreIncrement() { + if (xd0_selectWraparound) { + for (int sel = (xc4_userSelection + 1) % xc0_elementCount; sel != xc4_userSelection; + sel = (sel + 1) % xc0_elementCount) { + if (IsWorkerSelectable(sel)) { + SelectWorker(sel); + return true; + } + } - int elementCount = in.readInt16Big(); - in.readInt16Big(); - in.readUint32Big(); - int defaultSel = in.readInt16Big(); - in.readInt16Big(); - bool selectWraparound = in.readBool(); - in.readBool(); - in.readFloatBig(); - in.readFloatBig(); - in.readBool(); - in.readFloatBig(); - in.readInt16Big(); - in.readInt16Big(); - in.readInt16Big(); - in.readInt16Big(); + } else { + for (int sel = std::min(xc0_elementCount, xc4_userSelection + 1); sel < xc0_elementCount; ++sel) { + if (IsWorkerSelectable(sel)) { + SelectWorker(sel); + return true; + } + } + } - std::shared_ptr ret = std::make_shared(parms, elementCount, defaultSel, selectWraparound); - ret->ParseBaseInfo(frame, in, parms); - return ret; + return false; } +void CGuiTableGroup::DoIncrement() { + int oldSel = xc4_userSelection; + if (!PreIncrement()) + return; + if (x104_doMenuSelChange) + x104_doMenuSelChange(this, oldSel); } + +std::shared_ptr CGuiTableGroup::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + + int elementCount = in.readInt16Big(); + in.readInt16Big(); + in.readUint32Big(); + int defaultSel = in.readInt16Big(); + in.readInt16Big(); + bool selectWraparound = in.readBool(); + in.readBool(); + in.readFloatBig(); + in.readFloatBig(); + in.readBool(); + in.readFloatBig(); + in.readInt16Big(); + in.readInt16Big(); + in.readInt16Big(); + in.readInt16Big(); + + std::shared_ptr ret = std::make_shared(parms, elementCount, defaultSel, selectWraparound); + ret->ParseBaseInfo(frame, in, parms); + return ret; +} + +} // namespace urde diff --git a/Runtime/GuiSys/CGuiTableGroup.hpp b/Runtime/GuiSys/CGuiTableGroup.hpp index 57cb1d6a3..03c11454b 100644 --- a/Runtime/GuiSys/CGuiTableGroup.hpp +++ b/Runtime/GuiSys/CGuiTableGroup.hpp @@ -2,105 +2,87 @@ #include "CGuiCompoundWidget.hpp" -namespace urde -{ +namespace urde { -class CGuiTableGroup : public CGuiCompoundWidget -{ +class CGuiTableGroup : public CGuiCompoundWidget { public: - class CRepeatState - { - float x0_timer = 0.f; - public: - bool Update(float dt, bool state); - }; + class CRepeatState { + float x0_timer = 0.f; - enum class TableSelectReturn - { - Changed, - Unchanged, - WrappedAround - }; + public: + bool Update(float dt, bool state); + }; + + enum class TableSelectReturn { Changed, Unchanged, WrappedAround }; private: - CRepeatState xb8_decRepeat; - CRepeatState xbc_incRepeat; - int xc0_elementCount; - int xc4_userSelection; - int xc8_prevUserSelection; - int xcc_defaultUserSelection; - bool xd0_selectWraparound; - bool xd1_vertical = true; - std::function xd4_doMenuAdvance; - std::function xec_doMenuCancel; - std::function x104_doMenuSelChange; + CRepeatState xb8_decRepeat; + CRepeatState xbc_incRepeat; + int xc0_elementCount; + int xc4_userSelection; + int xc8_prevUserSelection; + int xcc_defaultUserSelection; + bool xd0_selectWraparound; + bool xd1_vertical = true; + std::function xd4_doMenuAdvance; + std::function xec_doMenuCancel; + std::function x104_doMenuSelChange; - bool IsWorkerSelectable(int) const; - void SelectWorker(int); - void DeactivateWorker(CGuiWidget* widget); - void ActivateWorker(CGuiWidget* widget); + bool IsWorkerSelectable(int) const; + void SelectWorker(int); + void DeactivateWorker(CGuiWidget* widget); + void ActivateWorker(CGuiWidget* widget); - TableSelectReturn DecrementSelectedRow(); - TableSelectReturn IncrementSelectedRow(); - void DoSelectPrevRow(); - void DoSelectNextRow(); + TableSelectReturn DecrementSelectedRow(); + TableSelectReturn IncrementSelectedRow(); + void DoSelectPrevRow(); + void DoSelectNextRow(); - void DoCancel(); - void DoAdvance(); - bool PreDecrement(); - void DoDecrement(); - bool PreIncrement(); - void DoIncrement(); + void DoCancel(); + void DoAdvance(); + bool PreDecrement(); + void DoDecrement(); + bool PreIncrement(); + void DoIncrement(); public: - CGuiTableGroup(const CGuiWidgetParms& parms, int, int, bool); - FourCC GetWidgetTypeID() const { return FOURCC('TBGP'); } + CGuiTableGroup(const CGuiWidgetParms& parms, int, int, bool); + FourCC GetWidgetTypeID() const { return FOURCC('TBGP'); } - void SetMenuAdvanceCallback(std::function&& cb) - { - xd4_doMenuAdvance = std::move(cb); + void SetMenuAdvanceCallback(std::function&& cb) { xd4_doMenuAdvance = std::move(cb); } + + void SetMenuCancelCallback(std::function&& cb) { xec_doMenuCancel = std::move(cb); } + + void SetMenuSelectionChangeCallback(std::function&& cb) { + x104_doMenuSelChange = std::move(cb); + } + + void SetColors(const zeus::CColor& selected, const zeus::CColor& unselected) { + int id = -1; + while (CGuiWidget* worker = GetWorkerWidget(++id)) { + if (id == xc4_userSelection) + worker->SetColor(selected); + else + worker->SetColor(unselected); } + } - void SetMenuCancelCallback(std::function&& cb) - { - xec_doMenuCancel = std::move(cb); - } + void SetVertical(bool v) { xd1_vertical = v; } - void SetMenuSelectionChangeCallback(std::function&& cb) - { - x104_doMenuSelChange = std::move(cb); - } + void SetUserSelection(int sel) { + xc8_prevUserSelection = xc4_userSelection; + xc4_userSelection = sel; + } - void SetColors(const zeus::CColor& selected, const zeus::CColor& unselected) - { - int id = -1; - while (CGuiWidget* worker = GetWorkerWidget(++id)) - { - if (id == xc4_userSelection) - worker->SetColor(selected); - else - worker->SetColor(unselected); - } - } + int GetElementCount() const { return xc0_elementCount; } - void SetVertical(bool v) { xd1_vertical = v; } + int GetUserSelection() const { return xc4_userSelection; } - void SetUserSelection(int sel) - { - xc8_prevUserSelection = xc4_userSelection; - xc4_userSelection = sel; - } + void ProcessUserInput(const CFinalInput& input); - int GetElementCount() const { return xc0_elementCount; } + bool AddWorkerWidget(CGuiWidget* worker) { return true; } - int GetUserSelection() const { return xc4_userSelection; } - - void ProcessUserInput(const CFinalInput& input); - - bool AddWorkerWidget(CGuiWidget* worker) { return true; } - - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiTextPane.cpp b/Runtime/GuiSys/CGuiTextPane.cpp index 2ba2d9892..accbc4a66 100644 --- a/Runtime/GuiSys/CGuiTextPane.cpp +++ b/Runtime/GuiSys/CGuiTextPane.cpp @@ -6,63 +6,54 @@ #include "Graphics/CGraphics.hpp" #include "Graphics/CGraphicsPalette.hpp" -namespace urde -{ +namespace urde { CGuiTextPane::CGuiTextPane(const CGuiWidgetParms& parms, CSimplePool* sp, const zeus::CVector2f& dim, const zeus::CVector3f& vec, CAssetId fontId, const CGuiTextProperties& props, - const zeus::CColor& fontCol, const zeus::CColor& outlineCol, - s32 extentX, s32 extentY) -: CGuiPane(parms, dim, vec), xd4_textSupport(fontId, props, fontCol, outlineCol, - zeus::CColor::skWhite, extentX, extentY, sp, xac_drawFlags) {} + const zeus::CColor& fontCol, const zeus::CColor& outlineCol, s32 extentX, s32 extentY) +: CGuiPane(parms, dim, vec) +, xd4_textSupport(fontId, props, fontCol, outlineCol, zeus::CColor::skWhite, extentX, extentY, sp, xac_drawFlags) {} -void CGuiTextPane::Update(float dt) -{ - CGuiWidget::Update(dt); - xd4_textSupport.Update(dt); +void CGuiTextPane::Update(float dt) { + CGuiWidget::Update(dt); + xd4_textSupport.Update(dt); } -bool CGuiTextPane::GetIsFinishedLoadingWidgetSpecific() const -{ - return xd4_textSupport.GetIsTextSupportFinishedLoading(); +bool CGuiTextPane::GetIsFinishedLoadingWidgetSpecific() const { + return xd4_textSupport.GetIsTextSupportFinishedLoading(); } -void CGuiTextPane::SetDimensions(const zeus::CVector2f& dim, bool initVBO) -{ - CGuiPane::SetDimensions(dim, initVBO); - if (initVBO) - InitializeBuffers(); +void CGuiTextPane::SetDimensions(const zeus::CVector2f& dim, bool initVBO) { + CGuiPane::SetDimensions(dim, initVBO); + if (initVBO) + InitializeBuffers(); } -void CGuiTextPane::ScaleDimensions(const zeus::CVector3f& scale) -{ -} +void CGuiTextPane::ScaleDimensions(const zeus::CVector3f& scale) {} -void CGuiTextPane::Draw(const CGuiWidgetDrawParms& parms) const -{ - if (!GetIsVisible()) - return; +void CGuiTextPane::Draw(const CGuiWidgetDrawParms& parms) const { + if (!GetIsVisible()) + return; - zeus::CVector2f dims = GetDimensions(); + zeus::CVector2f dims = GetDimensions(); - if (xd4_textSupport.x34_extentX) - dims.x() /= float(xd4_textSupport.x34_extentX); - else - dims.x() = 0.f; + if (xd4_textSupport.x34_extentX) + dims.x() /= float(xd4_textSupport.x34_extentX); + else + dims.x() = 0.f; - if (xd4_textSupport.x38_extentY) - dims.y() /= float(xd4_textSupport.x38_extentY); - else - dims.y() = 0.f; + if (xd4_textSupport.x38_extentY) + dims.y() /= float(xd4_textSupport.x38_extentY); + else + dims.y() = 0.f; - zeus::CTransform local = - zeus::CTransform::Translate(xc0_verts.front().m_pos + xc8_scaleCenter) * - zeus::CTransform::Scale(dims.x(), 1.f, dims.y()); - CGraphics::SetModelMatrix(x34_worldXF * local); + zeus::CTransform local = zeus::CTransform::Translate(xc0_verts.front().m_pos + xc8_scaleCenter) * + zeus::CTransform::Scale(dims.x(), 1.f, dims.y()); + CGraphics::SetModelMatrix(x34_worldXF * local); - zeus::CColor geomCol = xa8_color2; - geomCol.a() *= parms.x0_alphaMod; - const_cast(this)->xd4_textSupport.SetGeometryColor(geomCol); + zeus::CColor geomCol = xa8_color2; + geomCol.a() *= parms.x0_alphaMod; + const_cast(this)->xd4_textSupport.SetGeometryColor(geomCol); #if 0 CGraphics::SetDepthWriteMode(xb6_31_depthTest, ERglEnum::LEqual, xb7_24_depthWrite); @@ -97,34 +88,32 @@ void CGuiTextPane::Draw(const CGuiWidgetDrawParms& parms) const break; } #else - xd4_textSupport.Render(); + xd4_textSupport.Render(); #endif } -std::shared_ptr CGuiTextPane::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - zeus::CVector2f dim = zeus::CVector2f::ReadBig(in); - zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); - u32 fontId = in.readUint32Big(); - bool wordWrap = in.readBool(); - bool horizontal = in.readBool(); - EJustification justification = EJustification(in.readUint32Big()); - EVerticalJustification vJustification = EVerticalJustification(in.readUint32Big()); - CGuiTextProperties props(wordWrap, horizontal, justification, vJustification); - zeus::CColor fontCol; - fontCol.readRGBABig(in); - zeus::CColor outlineCol; - outlineCol.readRGBABig(in); - int extentX = in.readFloatBig(); - int extentY = in.readFloatBig(); - std::shared_ptr ret = - std::make_shared(parms, sp, dim, vec, fontId, props, - fontCol, outlineCol, extentX, extentY); - ret->ParseBaseInfo(frame, in, parms); - ret->InitializeBuffers(); - ret->TextSupport().SetText(u""); - return ret; +std::shared_ptr CGuiTextPane::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + zeus::CVector2f dim = zeus::CVector2f::ReadBig(in); + zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); + u32 fontId = in.readUint32Big(); + bool wordWrap = in.readBool(); + bool horizontal = in.readBool(); + EJustification justification = EJustification(in.readUint32Big()); + EVerticalJustification vJustification = EVerticalJustification(in.readUint32Big()); + CGuiTextProperties props(wordWrap, horizontal, justification, vJustification); + zeus::CColor fontCol; + fontCol.readRGBABig(in); + zeus::CColor outlineCol; + outlineCol.readRGBABig(in); + int extentX = in.readFloatBig(); + int extentY = in.readFloatBig(); + std::shared_ptr ret = + std::make_shared(parms, sp, dim, vec, fontId, props, fontCol, outlineCol, extentX, extentY); + ret->ParseBaseInfo(frame, in, parms); + ret->InitializeBuffers(); + ret->TextSupport().SetText(u""); + return ret; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiTextPane.hpp b/Runtime/GuiSys/CGuiTextPane.hpp index 26e81bb3e..9d671dedb 100644 --- a/Runtime/GuiSys/CGuiTextPane.hpp +++ b/Runtime/GuiSys/CGuiTextPane.hpp @@ -3,29 +3,27 @@ #include "CGuiPane.hpp" #include "CGuiTextSupport.hpp" -namespace urde -{ +namespace urde { + +class CGuiTextPane : public CGuiPane { + CGuiTextSupport xd4_textSupport; -class CGuiTextPane : public CGuiPane -{ - CGuiTextSupport xd4_textSupport; public: - CGuiTextPane(const CGuiWidgetParms& parms, CSimplePool* sp, const zeus::CVector2f& dim, - const zeus::CVector3f& vec, CAssetId fontId, const CGuiTextProperties& props, - const zeus::CColor& col1, const zeus::CColor& col2, s32 padX, s32 padY); - FourCC GetWidgetTypeID() const { return FOURCC('TXPN'); } + CGuiTextPane(const CGuiWidgetParms& parms, CSimplePool* sp, const zeus::CVector2f& dim, const zeus::CVector3f& vec, + CAssetId fontId, const CGuiTextProperties& props, const zeus::CColor& col1, const zeus::CColor& col2, + s32 padX, s32 padY); + FourCC GetWidgetTypeID() const { return FOURCC('TXPN'); } - CGuiTextSupport& TextSupport() { return xd4_textSupport; } - const CGuiTextSupport& GetTextSupport() const { return xd4_textSupport; } - void Update(float dt); - bool GetIsFinishedLoadingWidgetSpecific() const; - std::vector GetFontAssets() const { return {xd4_textSupport.x5c_fontId}; } - void SetDimensions(const zeus::CVector2f& dim, bool initVBO); - void ScaleDimensions(const zeus::CVector3f& scale); - void Draw(const CGuiWidgetDrawParms& parms) const; + CGuiTextSupport& TextSupport() { return xd4_textSupport; } + const CGuiTextSupport& GetTextSupport() const { return xd4_textSupport; } + void Update(float dt); + bool GetIsFinishedLoadingWidgetSpecific() const; + std::vector GetFontAssets() const { return {xd4_textSupport.x5c_fontId}; } + void SetDimensions(const zeus::CVector2f& dim, bool initVBO); + void ScaleDimensions(const zeus::CVector3f& scale); + void Draw(const CGuiWidgetDrawParms& parms) const; - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiTextSupport.cpp b/Runtime/GuiSys/CGuiTextSupport.cpp index 9c51ea128..8efecf166 100644 --- a/Runtime/GuiSys/CGuiTextSupport.cpp +++ b/Runtime/GuiSys/CGuiTextSupport.cpp @@ -8,350 +8,287 @@ #include "Graphics/CGraphics.hpp" #include "GuiSys/CRasterFont.hpp" -namespace urde -{ +namespace urde { -CGuiTextSupport::CGuiTextSupport(CAssetId fontId, const CGuiTextProperties& props, - const zeus::CColor& fontCol, const zeus::CColor& outlineCol, - const zeus::CColor& geomCol, s32 padX, s32 padY, CSimplePool* store, - CGuiWidget::EGuiModelDrawFlags drawFlags) -: x14_props(props), x24_fontColor(fontCol), x28_outlineColor(outlineCol), - x2c_geometryColor(geomCol), x34_extentX(padX), x38_extentY(padY), x5c_fontId(fontId), - m_drawFlags(drawFlags) -{ - x2cc_font = store->GetObj({SBIG('FONT'), fontId}); +CGuiTextSupport::CGuiTextSupport(CAssetId fontId, const CGuiTextProperties& props, const zeus::CColor& fontCol, + const zeus::CColor& outlineCol, const zeus::CColor& geomCol, s32 padX, s32 padY, + CSimplePool* store, CGuiWidget::EGuiModelDrawFlags drawFlags) +: x14_props(props) +, x24_fontColor(fontCol) +, x28_outlineColor(outlineCol) +, x2c_geometryColor(geomCol) +, x34_extentX(padX) +, x38_extentY(padY) +, x5c_fontId(fontId) +, m_drawFlags(drawFlags) { + x2cc_font = store->GetObj({SBIG('FONT'), fontId}); } -CTextRenderBuffer* CGuiTextSupport::GetCurrentPageRenderBuffer() const -{ - if (x60_renderBuf && !x308_multipageFlag) - return const_cast(&*x60_renderBuf); - if (!x308_multipageFlag || x2ec_renderBufferPages.size() <= x304_pageCounter) - return nullptr; - int idx = 0; - for (const CTextRenderBuffer& buf : x2ec_renderBufferPages) - if (idx++ == x304_pageCounter) - return const_cast(&buf); +CTextRenderBuffer* CGuiTextSupport::GetCurrentPageRenderBuffer() const { + if (x60_renderBuf && !x308_multipageFlag) + return const_cast(&*x60_renderBuf); + if (!x308_multipageFlag || x2ec_renderBufferPages.size() <= x304_pageCounter) return nullptr; + int idx = 0; + for (const CTextRenderBuffer& buf : x2ec_renderBufferPages) + if (idx++ == x304_pageCounter) + return const_cast(&buf); + return nullptr; } -float CGuiTextSupport::GetCurrentAnimationOverAge() const -{ - float ret = 0.f; - if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) - { - if (x50_typeEnable) - { - if (x40_primStartTimes.size()) - { - auto& lastTime = x40_primStartTimes.back(); - ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first); - } - else - { - ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate); - } - } +float CGuiTextSupport::GetCurrentAnimationOverAge() const { + float ret = 0.f; + if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { + if (x50_typeEnable) { + if (x40_primStartTimes.size()) { + auto& lastTime = x40_primStartTimes.back(); + ret = std::max(ret, (buf->GetPrimitiveCount() - lastTime.second) / x58_chRate + lastTime.first); + } else { + ret = std::max(ret, buf->GetPrimitiveCount() / x58_chRate); + } } - return ret; + } + return ret; } -float CGuiTextSupport::GetNumCharsTotal() const -{ - if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) - if (x50_typeEnable) - return buf->GetPrimitiveCount(); - return 0.f; -} - -float CGuiTextSupport::GetNumCharsPrinted() const -{ - if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) - { - if (x50_typeEnable) - { - float charsPrinted = x3c_curTime * x58_chRate; - return std::min(charsPrinted, float(buf->GetPrimitiveCount())); - } - } - return 0.f; -} - -float CGuiTextSupport::GetTotalAnimationTime() const -{ - if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) - if (x50_typeEnable) - return buf->GetPrimitiveCount() / x58_chRate; - return 0.f; -} - -bool CGuiTextSupport::IsAnimationDone() const -{ - return x3c_curTime >= GetTotalAnimationTime(); -} - -void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, float chRate) -{ - x50_typeEnable = enable; - x54_chFadeTime = std::max(chFadeTime, 0.0001f); - x58_chRate = std::max(chRate, 1.f); - if (enable) - { - if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) - { - float chStartTime = 0.f; - for (s32 i=0 ; iGetPrimitiveCount() ; ++i) - { - for (const std::pair& p : x40_primStartTimes) - { - if (p.second < i) - continue; - if (p.second != i) - break; - chStartTime = p.first; - break; - } - - buf->SetPrimitiveOpacity(i, - std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f)); - chStartTime += 1.f / x58_chRate; - } - } - } -} - -void CGuiTextSupport::Update(float dt) -{ +float CGuiTextSupport::GetNumCharsTotal() const { + if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) if (x50_typeEnable) - { - if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) - { - float chStartTime = 0.f; - for (s32 i=0 ; iGetPrimitiveCount() ; ++i) - { - for (const std::pair& p : x40_primStartTimes) - { - if (p.second < i) - continue; - if (p.second != i) - break; - chStartTime = p.first; - break; - } + return buf->GetPrimitiveCount(); + return 0.f; +} - buf->SetPrimitiveOpacity(i, - std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f)); - chStartTime += 1.f / x58_chRate; - } +float CGuiTextSupport::GetNumCharsPrinted() const { + if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { + if (x50_typeEnable) { + float charsPrinted = x3c_curTime * x58_chRate; + return std::min(charsPrinted, float(buf->GetPrimitiveCount())); + } + } + return 0.f; +} + +float CGuiTextSupport::GetTotalAnimationTime() const { + if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) + if (x50_typeEnable) + return buf->GetPrimitiveCount() / x58_chRate; + return 0.f; +} + +bool CGuiTextSupport::IsAnimationDone() const { return x3c_curTime >= GetTotalAnimationTime(); } + +void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, float chRate) { + x50_typeEnable = enable; + x54_chFadeTime = std::max(chFadeTime, 0.0001f); + x58_chRate = std::max(chRate, 1.f); + if (enable) { + if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { + float chStartTime = 0.f; + for (s32 i = 0; i < buf->GetPrimitiveCount(); ++i) { + for (const std::pair& p : x40_primStartTimes) { + if (p.second < i) + continue; + if (p.second != i) + break; + chStartTime = p.first; + break; } - x3c_curTime += dt; + + buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f)); + chStartTime += 1.f / x58_chRate; + } } - - x10_curTimeMod900 = std::fmod(x10_curTimeMod900 + dt, 900.f); + } } -void CGuiTextSupport::ClearRenderBuffer() -{ - x60_renderBuf = std::experimental::nullopt; - x2ec_renderBufferPages.clear(); -} +void CGuiTextSupport::Update(float dt) { + if (x50_typeEnable) { + if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { + float chStartTime = 0.f; + for (s32 i = 0; i < buf->GetPrimitiveCount(); ++i) { + for (const std::pair& p : x40_primStartTimes) { + if (p.second < i) + continue; + if (p.second != i) + break; + chStartTime = p.first; + break; + } -void CGuiTextSupport::CheckAndRebuildTextBuffer() -{ - g_TextExecuteBuf->Clear(); - g_TextExecuteBuf->x18_textState.x7c_enableWordWrap = x14_props.x0_wordWrap; - g_TextExecuteBuf->BeginBlock(0, 0, x34_extentX, x38_extentY, x30_imageBaseline, - ETextDirection(!x14_props.x1_horizontal), - x14_props.x4_justification, x14_props.x8_vertJustification); - g_TextExecuteBuf->AddColor(EColorType::Main, x24_fontColor); - g_TextExecuteBuf->AddColor(EColorType::Outline, x28_outlineColor); - - std::u16string initStr; - if (x5c_fontId.IsValid()) - initStr = hecl::Char16Format(L"&font=%08X;", u32(x5c_fontId.Value())); - initStr += x0_string; - - g_TextParser->ParseText(*g_TextExecuteBuf, initStr.c_str(), initStr.size(), x14_props.xc_txtrMap); - - g_TextExecuteBuf->EndBlock(); -} - -bool CGuiTextSupport::CheckAndRebuildRenderBuffer() -{ - if (x308_multipageFlag || x60_renderBuf) - if (!x308_multipageFlag || x2ec_renderBufferPages.size()) - return true; - - CheckAndRebuildTextBuffer(); - x2bc_assets = g_TextExecuteBuf->GetAssets(); - - if (!_GetIsTextSupportFinishedLoading()) - return false; - - CheckAndRebuildTextBuffer(); - if (x308_multipageFlag) - { - zeus::CVector2i extent(x34_extentX, x38_extentY); - x2ec_renderBufferPages = g_TextExecuteBuf->BuildRenderBufferPages(extent, m_drawFlags); + buf->SetPrimitiveOpacity(i, std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f)); + chStartTime += 1.f / x58_chRate; + } } - else - { - x60_renderBuf.emplace(g_TextExecuteBuf->BuildRenderBuffer(m_drawFlags)); - x2dc_oneBufBounds = x60_renderBuf->AccumulateTextBounds(); - } - g_TextExecuteBuf->Clear(); - Update(0.f); + x3c_curTime += dt; + } - return true; + x10_curTimeMod900 = std::fmod(x10_curTimeMod900 + dt, 900.f); } -const std::pair& CGuiTextSupport::GetBounds() -{ - CheckAndRebuildRenderBuffer(); - return x2dc_oneBufBounds; +void CGuiTextSupport::ClearRenderBuffer() { + x60_renderBuf = std::experimental::nullopt; + x2ec_renderBufferPages.clear(); } -void CGuiTextSupport::AutoSetExtent() -{ - auto& bounds = GetBounds(); - x34_extentX = bounds.second.x; - x38_extentY = bounds.second.y; +void CGuiTextSupport::CheckAndRebuildTextBuffer() { + g_TextExecuteBuf->Clear(); + g_TextExecuteBuf->x18_textState.x7c_enableWordWrap = x14_props.x0_wordWrap; + g_TextExecuteBuf->BeginBlock(0, 0, x34_extentX, x38_extentY, x30_imageBaseline, + ETextDirection(!x14_props.x1_horizontal), x14_props.x4_justification, + x14_props.x8_vertJustification); + g_TextExecuteBuf->AddColor(EColorType::Main, x24_fontColor); + g_TextExecuteBuf->AddColor(EColorType::Outline, x28_outlineColor); + + std::u16string initStr; + if (x5c_fontId.IsValid()) + initStr = hecl::Char16Format(L"&font=%08X;", u32(x5c_fontId.Value())); + initStr += x0_string; + + g_TextParser->ParseText(*g_TextExecuteBuf, initStr.c_str(), initStr.size(), x14_props.xc_txtrMap); + + g_TextExecuteBuf->EndBlock(); } -void CGuiTextSupport::Render() const -{ - const_cast(this)->CheckAndRebuildRenderBuffer(); - if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) - { - zeus::CTransform oldModel = CGraphics::g_GXModelMatrix; - CGraphics::SetModelMatrix(oldModel * zeus::CTransform::Scale(1.f, 1.f, -1.f)); - buf->Render(x2c_geometryColor, x10_curTimeMod900); - CGraphics::SetModelMatrix(oldModel); - } -} +bool CGuiTextSupport::CheckAndRebuildRenderBuffer() { + if (x308_multipageFlag || x60_renderBuf) + if (!x308_multipageFlag || x2ec_renderBufferPages.size()) + return true; -void CGuiTextSupport::SetGeometryColor(const zeus::CColor& col) -{ - x2c_geometryColor = col; -} + CheckAndRebuildTextBuffer(); + x2bc_assets = g_TextExecuteBuf->GetAssets(); -void CGuiTextSupport::SetOutlineColor(const zeus::CColor& col) -{ - if (col != x28_outlineColor) - { - ClearRenderBuffer(); - x28_outlineColor = col; - } -} - -void CGuiTextSupport::SetFontColor(const zeus::CColor& col) -{ - if (col != x24_fontColor) - { - ClearRenderBuffer(); - x24_fontColor = col; - } -} - -void CGuiTextSupport::AddText(std::u16string_view str) -{ - if (x60_renderBuf) - { - float t = GetCurrentAnimationOverAge(); - x40_primStartTimes.push_back(std::make_pair(std::max(t, x3c_curTime), - x60_renderBuf->GetPrimitiveCount())); - } - x0_string += str; - ClearRenderBuffer(); -} - -void CGuiTextSupport::SetText(std::u16string_view str, bool multipage) -{ - if (x0_string.compare(str)) - { - x40_primStartTimes.clear(); - x3c_curTime = 0.f; - x0_string = str; - ClearRenderBuffer(); - x308_multipageFlag = multipage; - x304_pageCounter = 0; - } -} - -void CGuiTextSupport::SetText(std::string_view str, bool multipage) -{ - SetText(hecl::UTF8ToChar16(str), multipage); -} - -bool CGuiTextSupport::_GetIsTextSupportFinishedLoading() const -{ - for (const CToken& tok : x2bc_assets) - { - const_cast(tok).Lock(); - if (!tok.IsLoaded()) - return false; - } - if (!x2cc_font) - return true; - if (x2cc_font.IsLoaded()) - return x2cc_font->IsFinishedLoading(); + if (!_GetIsTextSupportFinishedLoading()) return false; + + CheckAndRebuildTextBuffer(); + if (x308_multipageFlag) { + zeus::CVector2i extent(x34_extentX, x38_extentY); + x2ec_renderBufferPages = g_TextExecuteBuf->BuildRenderBufferPages(extent, m_drawFlags); + } else { + x60_renderBuf.emplace(g_TextExecuteBuf->BuildRenderBuffer(m_drawFlags)); + x2dc_oneBufBounds = x60_renderBuf->AccumulateTextBounds(); + } + g_TextExecuteBuf->Clear(); + Update(0.f); + + return true; } -void CGuiTextSupport::SetJustification(EJustification j) -{ - if (j != x14_props.x4_justification) - { - x14_props.x4_justification = j; - ClearRenderBuffer(); - } +const std::pair& CGuiTextSupport::GetBounds() { + CheckAndRebuildRenderBuffer(); + return x2dc_oneBufBounds; } -void CGuiTextSupport::SetVerticalJustification(EVerticalJustification j) -{ - if (j != x14_props.x8_vertJustification) - { - x14_props.x8_vertJustification = j; - ClearRenderBuffer(); - } +void CGuiTextSupport::AutoSetExtent() { + auto& bounds = GetBounds(); + x34_extentX = bounds.second.x; + x38_extentY = bounds.second.y; } -void CGuiTextSupport::SetImageBaseline(bool b) -{ - if (b != x30_imageBaseline) - { - x30_imageBaseline = b; - ClearRenderBuffer(); - } +void CGuiTextSupport::Render() const { + const_cast(this)->CheckAndRebuildRenderBuffer(); + if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) { + zeus::CTransform oldModel = CGraphics::g_GXModelMatrix; + CGraphics::SetModelMatrix(oldModel * zeus::CTransform::Scale(1.f, 1.f, -1.f)); + buf->Render(x2c_geometryColor, x10_curTimeMod900); + CGraphics::SetModelMatrix(oldModel); + } } -bool CGuiTextSupport::GetIsTextSupportFinishedLoading() const -{ - const_cast(this)->CheckAndRebuildRenderBuffer(); - return _GetIsTextSupportFinishedLoading(); +void CGuiTextSupport::SetGeometryColor(const zeus::CColor& col) { x2c_geometryColor = col; } + +void CGuiTextSupport::SetOutlineColor(const zeus::CColor& col) { + if (col != x28_outlineColor) { + ClearRenderBuffer(); + x28_outlineColor = col; + } } -void CGuiTextSupport::SetControlTXTRMap(const std::vector>* txtrMap) -{ - if (x14_props.xc_txtrMap != txtrMap) - { - x14_props.xc_txtrMap = txtrMap; - ClearRenderBuffer(); - } +void CGuiTextSupport::SetFontColor(const zeus::CColor& col) { + if (col != x24_fontColor) { + ClearRenderBuffer(); + x24_fontColor = col; + } } -int CGuiTextSupport::GetTotalPageCount() -{ - if (CheckAndRebuildRenderBuffer()) - return x2ec_renderBufferPages.size(); - return -1; +void CGuiTextSupport::AddText(std::u16string_view str) { + if (x60_renderBuf) { + float t = GetCurrentAnimationOverAge(); + x40_primStartTimes.push_back(std::make_pair(std::max(t, x3c_curTime), x60_renderBuf->GetPrimitiveCount())); + } + x0_string += str; + ClearRenderBuffer(); } -void CGuiTextSupport::SetPage(int page) -{ - x304_pageCounter = page; +void CGuiTextSupport::SetText(std::u16string_view str, bool multipage) { + if (x0_string.compare(str)) { x40_primStartTimes.clear(); x3c_curTime = 0.f; + x0_string = str; + ClearRenderBuffer(); + x308_multipageFlag = multipage; + x304_pageCounter = 0; + } } +void CGuiTextSupport::SetText(std::string_view str, bool multipage) { SetText(hecl::UTF8ToChar16(str), multipage); } + +bool CGuiTextSupport::_GetIsTextSupportFinishedLoading() const { + for (const CToken& tok : x2bc_assets) { + const_cast(tok).Lock(); + if (!tok.IsLoaded()) + return false; + } + if (!x2cc_font) + return true; + if (x2cc_font.IsLoaded()) + return x2cc_font->IsFinishedLoading(); + return false; } + +void CGuiTextSupport::SetJustification(EJustification j) { + if (j != x14_props.x4_justification) { + x14_props.x4_justification = j; + ClearRenderBuffer(); + } +} + +void CGuiTextSupport::SetVerticalJustification(EVerticalJustification j) { + if (j != x14_props.x8_vertJustification) { + x14_props.x8_vertJustification = j; + ClearRenderBuffer(); + } +} + +void CGuiTextSupport::SetImageBaseline(bool b) { + if (b != x30_imageBaseline) { + x30_imageBaseline = b; + ClearRenderBuffer(); + } +} + +bool CGuiTextSupport::GetIsTextSupportFinishedLoading() const { + const_cast(this)->CheckAndRebuildRenderBuffer(); + return _GetIsTextSupportFinishedLoading(); +} + +void CGuiTextSupport::SetControlTXTRMap(const std::vector>* txtrMap) { + if (x14_props.xc_txtrMap != txtrMap) { + x14_props.xc_txtrMap = txtrMap; + ClearRenderBuffer(); + } +} + +int CGuiTextSupport::GetTotalPageCount() { + if (CheckAndRebuildRenderBuffer()) + return x2ec_renderBufferPages.size(); + return -1; +} + +void CGuiTextSupport::SetPage(int page) { + x304_pageCounter = page; + x40_primStartTimes.clear(); + x3c_curTime = 0.f; +} + +} // namespace urde diff --git a/Runtime/GuiSys/CGuiTextSupport.hpp b/Runtime/GuiSys/CGuiTextSupport.hpp index 1c037e81e..0b34b1a06 100644 --- a/Runtime/GuiSys/CGuiTextSupport.hpp +++ b/Runtime/GuiSys/CGuiTextSupport.hpp @@ -9,140 +9,115 @@ #include "optional.hpp" #include -namespace urde -{ +namespace urde { class CSimplePool; class CRasterFont; class CTextRenderBuffer; class CTextExecuteBuffer; -enum class EJustification -{ - Left = 0, - Center, - Right, - Full, - NLeft, - NCenter, - NRight, - LeftMono, - CenterMono, - RightMono +enum class EJustification { Left = 0, Center, Right, Full, NLeft, NCenter, NRight, LeftMono, CenterMono, RightMono }; + +enum class EVerticalJustification { + Top = 0, + Center, + Bottom, + Full, + NTop, + NCenter, + NBottom, + TopMono, + CenterMono, + RightMono }; -enum class EVerticalJustification -{ - Top = 0, - Center, - Bottom, - Full, - NTop, - NCenter, - NBottom, - TopMono, - CenterMono, - RightMono -}; +enum class EColorType { Main, Outline, Geometry, Foreground, Background }; -enum class EColorType -{ - Main, - Outline, - Geometry, - Foreground, - Background -}; +enum class ETextDirection { Horizontal, Vertical }; -enum class ETextDirection -{ - Horizontal, - Vertical -}; - -class CGuiTextProperties -{ - friend class CGuiTextSupport; - bool x0_wordWrap; - bool x1_horizontal; - EJustification x4_justification; - EVerticalJustification x8_vertJustification; - const std::vector>* xc_txtrMap; -public: - CGuiTextProperties(bool wordWrap, bool horizontal, EJustification justification, - EVerticalJustification vertJustification, - const std::vector>* txtrMap=nullptr) - : x0_wordWrap(wordWrap), x1_horizontal(horizontal), x4_justification(justification), - x8_vertJustification(vertJustification), xc_txtrMap(txtrMap) {} -}; - -class CGuiTextSupport -{ - friend class CGuiTextPane; - std::u16string x0_string; - float x10_curTimeMod900 = 0.f; - CGuiTextProperties x14_props; - zeus::CColor x24_fontColor; - zeus::CColor x28_outlineColor; - zeus::CColor x2c_geometryColor; - bool x30_imageBaseline = false; - s32 x34_extentX; - s32 x38_extentY; - float x3c_curTime = 0.f; - std::vector> x40_primStartTimes; - bool x50_typeEnable = false; - float x54_chFadeTime = 0.1f; - float x58_chRate = 10.0f; - CAssetId x5c_fontId; - CGuiWidget::EGuiModelDrawFlags m_drawFlags; - std::experimental::optional x60_renderBuf; - std::vector x2bc_assets; - TLockedToken x2cc_font; - std::pair x2dc_oneBufBounds; - - std::list x2ec_renderBufferPages; - int x304_pageCounter = 0; - bool x308_multipageFlag = false; - - CTextRenderBuffer* GetCurrentPageRenderBuffer() const; - bool _GetIsTextSupportFinishedLoading() const; +class CGuiTextProperties { + friend class CGuiTextSupport; + bool x0_wordWrap; + bool x1_horizontal; + EJustification x4_justification; + EVerticalJustification x8_vertJustification; + const std::vector>* xc_txtrMap; public: - CGuiTextSupport(CAssetId fontId, const CGuiTextProperties& props, - const zeus::CColor& fontCol, const zeus::CColor& outlineCol, - const zeus::CColor& geomCol, s32 extX, s32 extY, CSimplePool* store, - CGuiWidget::EGuiModelDrawFlags drawFlags); - float GetCurrentAnimationOverAge() const; - float GetNumCharsTotal() const; - float GetNumCharsPrinted() const; - float GetTotalAnimationTime() const; - bool IsAnimationDone() const; - void SetTypeWriteEffectOptions(bool enable, float chFadeTime, float chRate); - void Update(float dt); - void ClearRenderBuffer(); - void CheckAndRebuildTextBuffer(); - bool CheckAndRebuildRenderBuffer(); - const std::pair& GetBounds(); - void AutoSetExtent(); - - void Render() const; - void SetGeometryColor(const zeus::CColor& col); - void SetOutlineColor(const zeus::CColor& col); - void SetFontColor(const zeus::CColor& col); - void AddText(std::u16string_view str); - void SetText(std::u16string_view str, bool multipage=false); - void SetText(std::string_view str, bool multipage=false); - void SetJustification(EJustification j); - void SetVerticalJustification(EVerticalJustification j); - void SetImageBaseline(bool b); - bool GetIsTextSupportFinishedLoading() const; - float GetCurTime() const { return x3c_curTime; } - void SetCurTime(float t) { x3c_curTime = t; } - std::u16string_view GetString() const { return x0_string; } - void SetControlTXTRMap(const std::vector>* txtrMap); - int GetPageCounter() const { return x304_pageCounter; } - int GetTotalPageCount(); - void SetPage(int page); + CGuiTextProperties(bool wordWrap, bool horizontal, EJustification justification, + EVerticalJustification vertJustification, + const std::vector>* txtrMap = nullptr) + : x0_wordWrap(wordWrap) + , x1_horizontal(horizontal) + , x4_justification(justification) + , x8_vertJustification(vertJustification) + , xc_txtrMap(txtrMap) {} }; -} +class CGuiTextSupport { + friend class CGuiTextPane; + std::u16string x0_string; + float x10_curTimeMod900 = 0.f; + CGuiTextProperties x14_props; + zeus::CColor x24_fontColor; + zeus::CColor x28_outlineColor; + zeus::CColor x2c_geometryColor; + bool x30_imageBaseline = false; + s32 x34_extentX; + s32 x38_extentY; + float x3c_curTime = 0.f; + std::vector> x40_primStartTimes; + bool x50_typeEnable = false; + float x54_chFadeTime = 0.1f; + float x58_chRate = 10.0f; + CAssetId x5c_fontId; + CGuiWidget::EGuiModelDrawFlags m_drawFlags; + std::experimental::optional x60_renderBuf; + std::vector x2bc_assets; + TLockedToken x2cc_font; + std::pair x2dc_oneBufBounds; + std::list x2ec_renderBufferPages; + int x304_pageCounter = 0; + bool x308_multipageFlag = false; + + CTextRenderBuffer* GetCurrentPageRenderBuffer() const; + bool _GetIsTextSupportFinishedLoading() const; + +public: + CGuiTextSupport(CAssetId fontId, const CGuiTextProperties& props, const zeus::CColor& fontCol, + const zeus::CColor& outlineCol, const zeus::CColor& geomCol, s32 extX, s32 extY, CSimplePool* store, + CGuiWidget::EGuiModelDrawFlags drawFlags); + float GetCurrentAnimationOverAge() const; + float GetNumCharsTotal() const; + float GetNumCharsPrinted() const; + float GetTotalAnimationTime() const; + bool IsAnimationDone() const; + void SetTypeWriteEffectOptions(bool enable, float chFadeTime, float chRate); + void Update(float dt); + void ClearRenderBuffer(); + void CheckAndRebuildTextBuffer(); + bool CheckAndRebuildRenderBuffer(); + const std::pair& GetBounds(); + void AutoSetExtent(); + + void Render() const; + void SetGeometryColor(const zeus::CColor& col); + void SetOutlineColor(const zeus::CColor& col); + void SetFontColor(const zeus::CColor& col); + void AddText(std::u16string_view str); + void SetText(std::u16string_view str, bool multipage = false); + void SetText(std::string_view str, bool multipage = false); + void SetJustification(EJustification j); + void SetVerticalJustification(EVerticalJustification j); + void SetImageBaseline(bool b); + bool GetIsTextSupportFinishedLoading() const; + float GetCurTime() const { return x3c_curTime; } + void SetCurTime(float t) { x3c_curTime = t; } + std::u16string_view GetString() const { return x0_string; } + void SetControlTXTRMap(const std::vector>* txtrMap); + int GetPageCounter() const { return x304_pageCounter; } + int GetTotalPageCount(); + void SetPage(int page); +}; + +} // namespace urde diff --git a/Runtime/GuiSys/CGuiWidget.cpp b/Runtime/GuiSys/CGuiWidget.cpp index e6b5405e6..2c656f409 100644 --- a/Runtime/GuiSys/CGuiWidget.cpp +++ b/Runtime/GuiSys/CGuiWidget.cpp @@ -1,266 +1,222 @@ #include "CGuiWidget.hpp" #include "CGuiFrame.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CGuiWidget"); CGuiWidget::CGuiWidget(const CGuiWidgetParms& parms) -: x70_selfId(parms.x6_selfId), x72_parentId(parms.x8_parentId), - xa4_color(parms.x10_color), xa8_color2(parms.x10_color), - xac_drawFlags(parms.x14_drawFlags), xb0_frame(parms.x0_frame) -{ - xb6_24_pg = parms.xd_g; - xb6_25_isVisible = parms.xa_defaultVisible; - xb6_26_isActive = parms.xb_defaultActive; - xb6_27_isSelectable = true; - xb6_28_eventLock = false; - xb6_29_cullFaces = parms.xc_cullFaces; - xb6_30_depthGreater = false; - xb6_31_depthTest = true; - xb7_24_depthWrite = false; - xb7_25_ = true; - RecalcWidgetColor(ETraversalMode::Single); +: x70_selfId(parms.x6_selfId) +, x72_parentId(parms.x8_parentId) +, xa4_color(parms.x10_color) +, xa8_color2(parms.x10_color) +, xac_drawFlags(parms.x14_drawFlags) +, xb0_frame(parms.x0_frame) { + xb6_24_pg = parms.xd_g; + xb6_25_isVisible = parms.xa_defaultVisible; + xb6_26_isActive = parms.xb_defaultActive; + xb6_27_isSelectable = true; + xb6_28_eventLock = false; + xb6_29_cullFaces = parms.xc_cullFaces; + xb6_30_depthGreater = false; + xb6_31_depthTest = true; + xb7_24_depthWrite = false; + xb7_25_ = true; + RecalcWidgetColor(ETraversalMode::Single); } -CGuiWidget::CGuiWidgetParms -CGuiWidget::ReadWidgetHeader(CGuiFrame* frame, CInputStream& in) -{ - std::string name = in.readString(-1); - s16 selfId = frame->GetWidgetIdDB().AddWidget(name); - std::string parent = in.readString(-1); - s16 parentId = frame->GetWidgetIdDB().AddWidget(parent); +CGuiWidget::CGuiWidgetParms CGuiWidget::ReadWidgetHeader(CGuiFrame* frame, CInputStream& in) { + std::string name = in.readString(-1); + s16 selfId = frame->GetWidgetIdDB().AddWidget(name); + std::string parent = in.readString(-1); + s16 parentId = frame->GetWidgetIdDB().AddWidget(parent); - bool useAnimController = in.readBool(); - bool defaultVis = in.readBool(); - bool defaultActive = in.readBool(); - bool cullFaces = in.readBool(); - zeus::CColor color; - color.readRGBABig(in); - EGuiModelDrawFlags df = EGuiModelDrawFlags(in.readUint32Big()); + bool useAnimController = in.readBool(); + bool defaultVis = in.readBool(); + bool defaultActive = in.readBool(); + bool cullFaces = in.readBool(); + zeus::CColor color; + color.readRGBABig(in); + EGuiModelDrawFlags df = EGuiModelDrawFlags(in.readUint32Big()); - return CGuiWidget::CGuiWidgetParms(frame, useAnimController, selfId, - parentId, defaultVis, defaultActive, - cullFaces, color, df, true, false); + return CGuiWidget::CGuiWidgetParms(frame, useAnimController, selfId, parentId, defaultVis, defaultActive, cullFaces, + color, df, true, false); } -std::shared_ptr CGuiWidget::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) -{ - CGuiWidgetParms parms = ReadWidgetHeader(frame, in); - std::shared_ptr ret = std::make_shared(parms); - ret->ParseBaseInfo(frame, in, parms); - return ret; +std::shared_ptr CGuiWidget::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { + CGuiWidgetParms parms = ReadWidgetHeader(frame, in); + std::shared_ptr ret = std::make_shared(parms); + ret->ParseBaseInfo(frame, in, parms); + return ret; } -void CGuiWidget::Initialize() -{ -} +void CGuiWidget::Initialize() {} -void CGuiWidget::ParseBaseInfo(CGuiFrame* frame, CInputStream& in, const CGuiWidgetParms& parms) -{ - CGuiWidget* parent = frame->FindWidget(parms.x8_parentId); - bool isWorker = in.readBool(); - if (isWorker) - xb4_workerId = in.readInt16Big(); - zeus::CVector3f trans = zeus::CVector3f::ReadBig(in); - zeus::CMatrix3f orient = zeus::CMatrix3f::ReadBig(in); - x74_transform = zeus::CTransform(orient, trans); - ReapplyXform(); - zeus::CVector3f::ReadBig(in); - in.readUint32Big(); - in.readUint16Big(); - if (isWorker) - { - if (!parent->AddWorkerWidget(this)) - { - Log.report(logvisor::Warning, - "Warning: Discarding useless worker id. Parent is not a compound widget."); - xb4_workerId = -1; - } +void CGuiWidget::ParseBaseInfo(CGuiFrame* frame, CInputStream& in, const CGuiWidgetParms& parms) { + CGuiWidget* parent = frame->FindWidget(parms.x8_parentId); + bool isWorker = in.readBool(); + if (isWorker) + xb4_workerId = in.readInt16Big(); + zeus::CVector3f trans = zeus::CVector3f::ReadBig(in); + zeus::CMatrix3f orient = zeus::CMatrix3f::ReadBig(in); + x74_transform = zeus::CTransform(orient, trans); + ReapplyXform(); + zeus::CVector3f::ReadBig(in); + in.readUint32Big(); + in.readUint16Big(); + if (isWorker) { + if (!parent->AddWorkerWidget(this)) { + Log.report(logvisor::Warning, "Warning: Discarding useless worker id. Parent is not a compound widget."); + xb4_workerId = -1; } - parent->AddChildWidget(this, false, true); + } + parent->AddChildWidget(this, false, true); } -void CGuiWidget::Update(float dt) -{ - CGuiWidget* ch = static_cast(GetChildObject()); - if (ch) - ch->Update(dt); - CGuiWidget* sib = static_cast(GetNextSibling()); - if (sib) - sib->Update(dt); +void CGuiWidget::Update(float dt) { + CGuiWidget* ch = static_cast(GetChildObject()); + if (ch) + ch->Update(dt); + CGuiWidget* sib = static_cast(GetNextSibling()); + if (sib) + sib->Update(dt); } void CGuiWidget::Draw(const CGuiWidgetDrawParms&) const {} void CGuiWidget::ProcessUserInput(const CFinalInput& input) {} void CGuiWidget::Touch() const {} -bool CGuiWidget::GetIsVisible() const -{ - return xb6_25_isVisible; +bool CGuiWidget::GetIsVisible() const { return xb6_25_isVisible; } + +bool CGuiWidget::GetIsActive() const { return xb6_26_isActive; } + +void CGuiWidget::InitializeRGBAFactor() { + CGuiWidget* child = static_cast(GetChildObject()); + if (child) + child->InitializeRGBAFactor(); + CGuiWidget* nextSib = static_cast(GetNextSibling()); + if (nextSib) + nextSib->InitializeRGBAFactor(); } -bool CGuiWidget::GetIsActive() const -{ - return xb6_26_isActive; +bool CGuiWidget::GetIsFinishedLoadingWidgetSpecific() const { return true; } + +void CGuiWidget::SetTransform(const zeus::CTransform& xf) { + x74_transform = xf; + ReapplyXform(); } -void CGuiWidget::InitializeRGBAFactor() -{ - CGuiWidget* child = static_cast(GetChildObject()); - if (child) - child->InitializeRGBAFactor(); - CGuiWidget* nextSib = static_cast(GetNextSibling()); - if (nextSib) - nextSib->InitializeRGBAFactor(); -} - -bool CGuiWidget::GetIsFinishedLoadingWidgetSpecific() const -{ - return true; -} - -void CGuiWidget::SetTransform(const zeus::CTransform& xf) -{ - x74_transform = xf; +void CGuiWidget::SetIdlePosition(const zeus::CVector3f& pos, bool reapply) { + x74_transform.origin = pos; + if (reapply) ReapplyXform(); } -void CGuiWidget::SetIdlePosition(const zeus::CVector3f& pos, bool reapply) -{ - x74_transform.origin = pos; - if (reapply) - ReapplyXform(); +void CGuiWidget::ReapplyXform() { + RotateReset(); + SetLocalPosition(zeus::CVector3f::skZero); + MultiplyO2P(x74_transform); } -void CGuiWidget::ReapplyXform() -{ - RotateReset(); - SetLocalPosition(zeus::CVector3f::skZero); - MultiplyO2P(x74_transform); +void CGuiWidget::AddChildWidget(CGuiWidget* widget, bool makeWorldLocal, bool atEnd) { + AddChildObject(widget, makeWorldLocal, atEnd); } -void CGuiWidget::AddChildWidget(CGuiWidget* widget, bool makeWorldLocal, bool atEnd) -{ - AddChildObject(widget, makeWorldLocal, atEnd); -} +bool CGuiWidget::AddWorkerWidget(CGuiWidget* worker) { return false; } -bool CGuiWidget::AddWorkerWidget(CGuiWidget* worker) -{ - return false; -} - -void CGuiWidget::SetVisibility(bool vis, ETraversalMode mode) -{ - switch (mode) - { - case ETraversalMode::Children: - { - CGuiWidget* child = static_cast(GetChildObject()); - if (child) - child->SetVisibility(vis, ETraversalMode::ChildrenAndSiblings); - break; - } - case ETraversalMode::ChildrenAndSiblings: - { - CGuiWidget* child = static_cast(GetChildObject()); - if (child) - child->SetVisibility(vis, ETraversalMode::ChildrenAndSiblings); - CGuiWidget* nextSib = static_cast(GetNextSibling()); - if (nextSib) - nextSib->SetVisibility(vis, ETraversalMode::ChildrenAndSiblings); - break; - } - default: break; - } - SetIsVisible(vis); -} - -void CGuiWidget::RecalcWidgetColor(ETraversalMode mode) -{ - CGuiWidget* parent = static_cast(GetParent()); - if (parent) - xa8_color2 = xa4_color * parent->xa8_color2; - else - xa8_color2 = xa4_color; - - switch (mode) - { - case ETraversalMode::ChildrenAndSiblings: - { - CGuiWidget* nextSib = static_cast(GetNextSibling()); - if (nextSib) - nextSib->RecalcWidgetColor(ETraversalMode::ChildrenAndSiblings); - } - case ETraversalMode::Children: - { - CGuiWidget* child = static_cast(GetChildObject()); - if (child) - child->RecalcWidgetColor(ETraversalMode::ChildrenAndSiblings); - } - default: break; - } -} - -CGuiWidget* CGuiWidget::FindWidget(s16 id) -{ - if (x70_selfId == id) - return this; +void CGuiWidget::SetVisibility(bool vis, ETraversalMode mode) { + switch (mode) { + case ETraversalMode::Children: { CGuiWidget* child = static_cast(GetChildObject()); if (child) - { - CGuiWidget* found = child->FindWidget(id); - if (found) - return found; - } + child->SetVisibility(vis, ETraversalMode::ChildrenAndSiblings); + break; + } + case ETraversalMode::ChildrenAndSiblings: { + CGuiWidget* child = static_cast(GetChildObject()); + if (child) + child->SetVisibility(vis, ETraversalMode::ChildrenAndSiblings); CGuiWidget* nextSib = static_cast(GetNextSibling()); if (nextSib) - { - CGuiWidget* found = nextSib->FindWidget(id); - if (found) - return found; - } - return nullptr; + nextSib->SetVisibility(vis, ETraversalMode::ChildrenAndSiblings); + break; + } + default: + break; + } + SetIsVisible(vis); } -bool CGuiWidget::GetIsFinishedLoading() const -{ - return GetIsFinishedLoadingWidgetSpecific(); +void CGuiWidget::RecalcWidgetColor(ETraversalMode mode) { + CGuiWidget* parent = static_cast(GetParent()); + if (parent) + xa8_color2 = xa4_color * parent->xa8_color2; + else + xa8_color2 = xa4_color; + + switch (mode) { + case ETraversalMode::ChildrenAndSiblings: { + CGuiWidget* nextSib = static_cast(GetNextSibling()); + if (nextSib) + nextSib->RecalcWidgetColor(ETraversalMode::ChildrenAndSiblings); + } + case ETraversalMode::Children: { + CGuiWidget* child = static_cast(GetChildObject()); + if (child) + child->RecalcWidgetColor(ETraversalMode::ChildrenAndSiblings); + } + default: + break; + } } -void CGuiWidget::DispatchInitialize() -{ - Initialize(); - CGuiWidget* ch = static_cast(GetChildObject()); - if (ch) - ch->DispatchInitialize(); - CGuiWidget* sib = static_cast(GetNextSibling()); - if (sib) - sib->DispatchInitialize(); +CGuiWidget* CGuiWidget::FindWidget(s16 id) { + if (x70_selfId == id) + return this; + CGuiWidget* child = static_cast(GetChildObject()); + if (child) { + CGuiWidget* found = child->FindWidget(id); + if (found) + return found; + } + CGuiWidget* nextSib = static_cast(GetNextSibling()); + if (nextSib) { + CGuiWidget* found = nextSib->FindWidget(id); + if (found) + return found; + } + return nullptr; } -void CGuiWidget::SetColor(const zeus::CColor& color) -{ - xa4_color = color; - RecalcWidgetColor(ETraversalMode::Children); +bool CGuiWidget::GetIsFinishedLoading() const { return GetIsFinishedLoadingWidgetSpecific(); } + +void CGuiWidget::DispatchInitialize() { + Initialize(); + CGuiWidget* ch = static_cast(GetChildObject()); + if (ch) + ch->DispatchInitialize(); + CGuiWidget* sib = static_cast(GetNextSibling()); + if (sib) + sib->DispatchInitialize(); +} + +void CGuiWidget::SetColor(const zeus::CColor& color) { + xa4_color = color; + RecalcWidgetColor(ETraversalMode::Children); } void CGuiWidget::OnActiveChange() {} void CGuiWidget::OnVisibleChange() {} -void CGuiWidget::SetIsVisible(bool vis) -{ - xb6_25_isVisible = vis; - OnVisibleChange(); +void CGuiWidget::SetIsVisible(bool vis) { + xb6_25_isVisible = vis; + OnVisibleChange(); } -void CGuiWidget::SetIsActive(bool a) -{ - if (a != xb6_26_isActive) - { - xb6_26_isActive = a; - OnActiveChange(); - } +void CGuiWidget::SetIsActive(bool a) { + if (a != xb6_26_isActive) { + xb6_26_isActive = a; + OnActiveChange(); + } } -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiWidget.hpp b/Runtime/GuiSys/CGuiWidget.hpp index 92ce03543..e8cdc5eb2 100644 --- a/Runtime/GuiSys/CGuiWidget.hpp +++ b/Runtime/GuiSys/CGuiWidget.hpp @@ -4,139 +4,120 @@ #include "CGuiObject.hpp" #include "zeus/CColor.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; class CGuiTextSupport; struct CFinalInput; class CSimplePool; -enum class ETraversalMode -{ - ChildrenAndSiblings = 0, - Children = 1, - Single = 2 -}; +enum class ETraversalMode { ChildrenAndSiblings = 0, Children = 1, Single = 2 }; -enum class EGuiTextureClampModeHorz -{ - NoClamp = 0, - Right = 1, - Left = 2, - Center = 3 -}; +enum class EGuiTextureClampModeHorz { NoClamp = 0, Right = 1, Left = 2, Center = 3 }; -enum class EGuiTextureClampModeVert -{ - NoClamp = 0, - Top = 1, - Bottom = 2, - Center = 3 -}; +enum class EGuiTextureClampModeVert { NoClamp = 0, Top = 1, Bottom = 2, Center = 3 }; + +class CGuiWidget : public CGuiObject { + friend class CGuiFrame; -class CGuiWidget : public CGuiObject -{ - friend class CGuiFrame; public: - enum class EGuiModelDrawFlags - { - Shadeless = 0, - Opaque = 1, - Alpha = 2, - Additive = 3, - AlphaAdditiveOverdraw = 4 - }; - struct CGuiWidgetParms - { - CGuiFrame* x0_frame; - bool x4_useAnimController; - s16 x6_selfId; - s16 x8_parentId; - bool xa_defaultVisible; - bool xb_defaultActive; - bool xc_cullFaces; - bool xd_g; - bool xe_h; - zeus::CColor x10_color; - EGuiModelDrawFlags x14_drawFlags; - CGuiWidgetParms(CGuiFrame* frame, bool useAnimController, s16 selfId, s16 parentId, - bool defaultVisible, bool defaultActive, bool cullFaces, - const zeus::CColor& color, EGuiModelDrawFlags drawFlags, - bool g, bool h) - : x0_frame(frame), x4_useAnimController(useAnimController), x6_selfId(selfId), - x8_parentId(parentId), xa_defaultVisible(defaultVisible), xb_defaultActive(defaultActive), - xc_cullFaces(cullFaces), xd_g(g), xe_h(h), x10_color(color), x14_drawFlags(drawFlags) {} - }; + enum class EGuiModelDrawFlags { Shadeless = 0, Opaque = 1, Alpha = 2, Additive = 3, AlphaAdditiveOverdraw = 4 }; + struct CGuiWidgetParms { + CGuiFrame* x0_frame; + bool x4_useAnimController; + s16 x6_selfId; + s16 x8_parentId; + bool xa_defaultVisible; + bool xb_defaultActive; + bool xc_cullFaces; + bool xd_g; + bool xe_h; + zeus::CColor x10_color; + EGuiModelDrawFlags x14_drawFlags; + CGuiWidgetParms(CGuiFrame* frame, bool useAnimController, s16 selfId, s16 parentId, bool defaultVisible, + bool defaultActive, bool cullFaces, const zeus::CColor& color, EGuiModelDrawFlags drawFlags, bool g, + bool h) + : x0_frame(frame) + , x4_useAnimController(useAnimController) + , x6_selfId(selfId) + , x8_parentId(parentId) + , xa_defaultVisible(defaultVisible) + , xb_defaultActive(defaultActive) + , xc_cullFaces(cullFaces) + , xd_g(g) + , xe_h(h) + , x10_color(color) + , x14_drawFlags(drawFlags) {} + }; + protected: - s16 x70_selfId; - s16 x72_parentId; - zeus::CTransform x74_transform; - zeus::CColor xa4_color; - zeus::CColor xa8_color2; - EGuiModelDrawFlags xac_drawFlags; - CGuiFrame* xb0_frame; - s16 xb4_workerId = -1; - bool xb6_24_pg : 1; - bool xb6_25_isVisible : 1; - bool xb6_26_isActive : 1; - bool xb6_27_isSelectable : 1; - bool xb6_28_eventLock : 1; - bool xb6_29_cullFaces : 1; - bool xb6_30_depthGreater : 1; - bool xb6_31_depthTest : 1; - bool xb7_24_depthWrite : 1; - bool xb7_25_ : 1; + s16 x70_selfId; + s16 x72_parentId; + zeus::CTransform x74_transform; + zeus::CColor xa4_color; + zeus::CColor xa8_color2; + EGuiModelDrawFlags xac_drawFlags; + CGuiFrame* xb0_frame; + s16 xb4_workerId = -1; + bool xb6_24_pg : 1; + bool xb6_25_isVisible : 1; + bool xb6_26_isActive : 1; + bool xb6_27_isSelectable : 1; + bool xb6_28_eventLock : 1; + bool xb6_29_cullFaces : 1; + bool xb6_30_depthGreater : 1; + bool xb6_31_depthTest : 1; + bool xb7_24_depthWrite : 1; + bool xb7_25_ : 1; public: - CGuiWidget(const CGuiWidgetParms& parms); + CGuiWidget(const CGuiWidgetParms& parms); - static CGuiWidgetParms ReadWidgetHeader(CGuiFrame* frame, CInputStream& in); - static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); + static CGuiWidgetParms ReadWidgetHeader(CGuiFrame* frame, CInputStream& in); + static std::shared_ptr Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp); - virtual void Update(float dt); - virtual void Draw(const CGuiWidgetDrawParms& drawParms) const; - virtual void Initialize(); - virtual void ProcessUserInput(const CFinalInput& input); - virtual void Touch() const; - virtual bool GetIsVisible() const; - virtual bool GetIsActive() const; - virtual FourCC GetWidgetTypeID() const { return FOURCC('BWIG'); } - virtual bool AddWorkerWidget(CGuiWidget* worker); - virtual bool GetIsFinishedLoadingWidgetSpecific() const; - virtual void OnVisibleChange(); - virtual void OnActiveChange(); + virtual void Update(float dt); + virtual void Draw(const CGuiWidgetDrawParms& drawParms) const; + virtual void Initialize(); + virtual void ProcessUserInput(const CFinalInput& input); + virtual void Touch() const; + virtual bool GetIsVisible() const; + virtual bool GetIsActive() const; + virtual FourCC GetWidgetTypeID() const { return FOURCC('BWIG'); } + virtual bool AddWorkerWidget(CGuiWidget* worker); + virtual bool GetIsFinishedLoadingWidgetSpecific() const; + virtual void OnVisibleChange(); + virtual void OnActiveChange(); - s16 GetSelfId() const {return x70_selfId;} - s16 GetParentId() const {return x72_parentId;} - s16 GetWorkerId() const {return xb4_workerId;} - const zeus::CTransform& GetTransform() const {return x74_transform;} - zeus::CTransform& GetTransform() {return x74_transform;} - const zeus::CVector3f& GetIdlePosition() const {return x74_transform.origin;} - void SetTransform(const zeus::CTransform& xf); - const zeus::CColor& GetIntermediateColor() const { return xa4_color; } - const zeus::CColor& GetGeometryColor() const { return xa8_color2; } - void SetIdlePosition(const zeus::CVector3f& pos, bool reapply); - void ReapplyXform(); - virtual void SetIsVisible(bool); - void SetIsActive(bool); - bool GetIsSelectable() const { return xb6_27_isSelectable; } - void SetIsSelectable(bool v) { xb6_27_isSelectable = v; } + s16 GetSelfId() const { return x70_selfId; } + s16 GetParentId() const { return x72_parentId; } + s16 GetWorkerId() const { return xb4_workerId; } + const zeus::CTransform& GetTransform() const { return x74_transform; } + zeus::CTransform& GetTransform() { return x74_transform; } + const zeus::CVector3f& GetIdlePosition() const { return x74_transform.origin; } + void SetTransform(const zeus::CTransform& xf); + const zeus::CColor& GetIntermediateColor() const { return xa4_color; } + const zeus::CColor& GetGeometryColor() const { return xa8_color2; } + void SetIdlePosition(const zeus::CVector3f& pos, bool reapply); + void ReapplyXform(); + virtual void SetIsVisible(bool); + void SetIsActive(bool); + bool GetIsSelectable() const { return xb6_27_isSelectable; } + void SetIsSelectable(bool v) { xb6_27_isSelectable = v; } - void ParseBaseInfo(CGuiFrame* frame, CInputStream& in, const CGuiWidgetParms& parms); - void AddChildWidget(CGuiWidget* widget, bool makeWorldLocal, bool atEnd); - void SetVisibility(bool, ETraversalMode); - void RecalcWidgetColor(ETraversalMode); - void SetColor(const zeus::CColor& color); - void InitializeRGBAFactor(); - CGuiWidget* FindWidget(s16 id); - bool GetIsFinishedLoading() const; - void DispatchInitialize(); - void SetDepthGreater(bool v) { xb6_30_depthGreater = v; } - void SetDepthTest(bool v) { xb6_31_depthTest = v; } - void SetDepthWrite(bool v) { xb7_24_depthWrite = v; } + void ParseBaseInfo(CGuiFrame* frame, CInputStream& in, const CGuiWidgetParms& parms); + void AddChildWidget(CGuiWidget* widget, bool makeWorldLocal, bool atEnd); + void SetVisibility(bool, ETraversalMode); + void RecalcWidgetColor(ETraversalMode); + void SetColor(const zeus::CColor& color); + void InitializeRGBAFactor(); + CGuiWidget* FindWidget(s16 id); + bool GetIsFinishedLoading() const; + void DispatchInitialize(); + void SetDepthGreater(bool v) { xb6_30_depthGreater = v; } + void SetDepthTest(bool v) { xb6_31_depthTest = v; } + void SetDepthWrite(bool v) { xb7_24_depthWrite = v; } - CGuiFrame* GetGuiFrame() const { return xb0_frame; } + CGuiFrame* GetGuiFrame() const { return xb0_frame; } }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiWidgetDrawParms.cpp b/Runtime/GuiSys/CGuiWidgetDrawParms.cpp index c2ba4450f..58df7407a 100644 --- a/Runtime/GuiSys/CGuiWidgetDrawParms.cpp +++ b/Runtime/GuiSys/CGuiWidgetDrawParms.cpp @@ -1,6 +1,5 @@ #include "CGuiWidgetDrawParms.hpp" -namespace urde -{ +namespace urde { CGuiWidgetDrawParms CGuiWidgetDrawParms::Default = {}; } diff --git a/Runtime/GuiSys/CGuiWidgetDrawParms.hpp b/Runtime/GuiSys/CGuiWidgetDrawParms.hpp index 02efe19ff..4ee7b0be8 100644 --- a/Runtime/GuiSys/CGuiWidgetDrawParms.hpp +++ b/Runtime/GuiSys/CGuiWidgetDrawParms.hpp @@ -2,19 +2,16 @@ #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { -struct CGuiWidgetDrawParms -{ - float x0_alphaMod = 1.f; - zeus::CVector3f x4_cameraOffset; +struct CGuiWidgetDrawParms { + float x0_alphaMod = 1.f; + zeus::CVector3f x4_cameraOffset; - CGuiWidgetDrawParms() = default; - CGuiWidgetDrawParms(float alphaMod, const zeus::CVector3f& cameraOff) - : x0_alphaMod(alphaMod), x4_cameraOffset(cameraOff) {} - static CGuiWidgetDrawParms Default; + CGuiWidgetDrawParms() = default; + CGuiWidgetDrawParms(float alphaMod, const zeus::CVector3f& cameraOff) + : x0_alphaMod(alphaMod), x4_cameraOffset(cameraOff) {} + static CGuiWidgetDrawParms Default; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CGuiWidgetIdDB.cpp b/Runtime/GuiSys/CGuiWidgetIdDB.cpp index d885b91d2..c2dad7e80 100644 --- a/Runtime/GuiSys/CGuiWidgetIdDB.cpp +++ b/Runtime/GuiSys/CGuiWidgetIdDB.cpp @@ -1,47 +1,40 @@ #include "CGuiWidgetIdDB.hpp" -namespace urde -{ +namespace urde { -CGuiWidgetIdDB::CGuiWidgetIdDB() -{ - AddWidget("kGSYS_DummyWidgetID", 0); - AddWidget("kGSYS_HeadWidgetID", 1); - AddWidget("kGSYS_DefaultCameraID"); - AddWidget("kGSYS_DefaultLightID"); +CGuiWidgetIdDB::CGuiWidgetIdDB() { + AddWidget("kGSYS_DummyWidgetID", 0); + AddWidget("kGSYS_HeadWidgetID", 1); + AddWidget("kGSYS_DefaultCameraID"); + AddWidget("kGSYS_DefaultLightID"); } -s16 CGuiWidgetIdDB::FindWidgetID(std::string_view name) const -{ - auto search = x0_dbMap.find(name.data()); - if (search == x0_dbMap.cend()) - return -1; - return search->second; +s16 CGuiWidgetIdDB::FindWidgetID(std::string_view name) const { + auto search = x0_dbMap.find(name.data()); + if (search == x0_dbMap.cend()) + return -1; + return search->second; } -s16 CGuiWidgetIdDB::AddWidget(std::string_view name, s16 id) -{ - s16 findId = FindWidgetID(name); - if (findId == -1) - { - if (id >= x14_lastPoolId) - x14_lastPoolId = id; - x0_dbMap.emplace(std::make_pair(name, id)); - findId = id; - } - return findId; +s16 CGuiWidgetIdDB::AddWidget(std::string_view name, s16 id) { + s16 findId = FindWidgetID(name); + if (findId == -1) { + if (id >= x14_lastPoolId) + x14_lastPoolId = id; + x0_dbMap.emplace(std::make_pair(name, id)); + findId = id; + } + return findId; } -s16 CGuiWidgetIdDB::AddWidget(std::string_view name) -{ - s16 findId = FindWidgetID(name); - if (findId == -1) - { - ++x14_lastPoolId; - x0_dbMap.emplace(std::make_pair(name, x14_lastPoolId)); - findId = x14_lastPoolId; - } - return findId; +s16 CGuiWidgetIdDB::AddWidget(std::string_view name) { + s16 findId = FindWidgetID(name); + if (findId == -1) { + ++x14_lastPoolId; + x0_dbMap.emplace(std::make_pair(name, x14_lastPoolId)); + findId = x14_lastPoolId; + } + return findId; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CGuiWidgetIdDB.hpp b/Runtime/GuiSys/CGuiWidgetIdDB.hpp index 5eba91134..f95052e8b 100644 --- a/Runtime/GuiSys/CGuiWidgetIdDB.hpp +++ b/Runtime/GuiSys/CGuiWidgetIdDB.hpp @@ -3,19 +3,17 @@ #include #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { + +class CGuiWidgetIdDB { + std::unordered_map x0_dbMap; + s16 x14_lastPoolId = 0; -class CGuiWidgetIdDB -{ - std::unordered_map x0_dbMap; - s16 x14_lastPoolId = 0; public: - CGuiWidgetIdDB(); - s16 FindWidgetID(std::string_view name) const; - s16 AddWidget(std::string_view name, s16 id); - s16 AddWidget(std::string_view name); + CGuiWidgetIdDB(); + s16 FindWidgetID(std::string_view name) const; + s16 AddWidget(std::string_view name, s16 id); + s16 AddWidget(std::string_view name); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudBallInterface.cpp b/Runtime/GuiSys/CHudBallInterface.cpp index 892b67597..5d05176d3 100644 --- a/Runtime/GuiSys/CHudBallInterface.cpp +++ b/Runtime/GuiSys/CHudBallInterface.cpp @@ -6,110 +6,94 @@ #include "CGuiModel.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { -CHudBallInterface::CHudBallInterface(CGuiFrame& selHud, int pbAmount, int pbCapacity, - int availableBombs, bool hasBombs, bool hasPb) -: x40_pbAmount(pbAmount), x44_pbCapacity(pbCapacity), - x48_availableBombs(availableBombs), x4c_hasPb(hasPb) -{ - x0_camera = selHud.GetFrameCamera(); - x4_basewidget_bombstuff = selHud.FindWidget("basewidget_bombstuff"); - x8_basewidget_bombdeco = selHud.FindWidget("basewidget_bombdeco"); - xc_model_bombicon = static_cast(selHud.FindWidget("model_bombicon")); - x10_textpane_bombdigits = static_cast(selHud.FindWidget("textpane_bombdigits")); - for (int i=0 ; i<3 ; ++i) - { - CGuiGroup* grp = static_cast(selHud.FindWidget(hecl::Format("group_bombcount%d", i).c_str())); - CGuiWidget* filled = grp->GetWorkerWidget(1); - CGuiWidget* empty = grp->GetWorkerWidget(0); - x14_group_bombfilled.push_back(filled); - x24_group_bombempty.push_back(empty); - if (filled) - filled->SetColor(g_tweakGuiColors->GetBallBombFilledColor()); - if (empty) - empty->SetColor(g_tweakGuiColors->GetBallBombEmptyColor()); - } - x8_basewidget_bombdeco->SetColor(g_tweakGuiColors->GetBallBombDecoColor()); - x34_camPos = x0_camera->GetLocalPosition(); - if (CGuiWidget* w = selHud.FindWidget("basewidget_energydeco")) - w->SetColor(g_tweakGuiColors->GetBallBombEnergyColor()); - SetBombParams(pbAmount, pbCapacity, availableBombs, hasBombs, hasPb, true); +CHudBallInterface::CHudBallInterface(CGuiFrame& selHud, int pbAmount, int pbCapacity, int availableBombs, bool hasBombs, + bool hasPb) +: x40_pbAmount(pbAmount), x44_pbCapacity(pbCapacity), x48_availableBombs(availableBombs), x4c_hasPb(hasPb) { + x0_camera = selHud.GetFrameCamera(); + x4_basewidget_bombstuff = selHud.FindWidget("basewidget_bombstuff"); + x8_basewidget_bombdeco = selHud.FindWidget("basewidget_bombdeco"); + xc_model_bombicon = static_cast(selHud.FindWidget("model_bombicon")); + x10_textpane_bombdigits = static_cast(selHud.FindWidget("textpane_bombdigits")); + for (int i = 0; i < 3; ++i) { + CGuiGroup* grp = static_cast(selHud.FindWidget(hecl::Format("group_bombcount%d", i).c_str())); + CGuiWidget* filled = grp->GetWorkerWidget(1); + CGuiWidget* empty = grp->GetWorkerWidget(0); + x14_group_bombfilled.push_back(filled); + x24_group_bombempty.push_back(empty); + if (filled) + filled->SetColor(g_tweakGuiColors->GetBallBombFilledColor()); + if (empty) + empty->SetColor(g_tweakGuiColors->GetBallBombEmptyColor()); + } + x8_basewidget_bombdeco->SetColor(g_tweakGuiColors->GetBallBombDecoColor()); + x34_camPos = x0_camera->GetLocalPosition(); + if (CGuiWidget* w = selHud.FindWidget("basewidget_energydeco")) + w->SetColor(g_tweakGuiColors->GetBallBombEnergyColor()); + SetBombParams(pbAmount, pbCapacity, availableBombs, hasBombs, hasPb, true); } -void CHudBallInterface::UpdatePowerBombReadoutColors() -{ - zeus::CColor fontColor; - zeus::CColor outlineColor; - if (x40_pbAmount > 0) - { - fontColor = g_tweakGuiColors->GetPowerBombDigitAvailableFont(); - outlineColor = g_tweakGuiColors->GetPowerBombDigitAvailableOutline(); - } - else if (x44_pbCapacity > 0) - { - fontColor = g_tweakGuiColors->GetPowerBombDigitDelpetedFont(); - outlineColor = g_tweakGuiColors->GetPowerBombDigitDelpetedOutline(); - } - else - { - fontColor = zeus::CColor::skClear; - outlineColor = zeus::CColor::skClear; - } - x10_textpane_bombdigits->TextSupport().SetFontColor(fontColor); - x10_textpane_bombdigits->TextSupport().SetOutlineColor(outlineColor); +void CHudBallInterface::UpdatePowerBombReadoutColors() { + zeus::CColor fontColor; + zeus::CColor outlineColor; + if (x40_pbAmount > 0) { + fontColor = g_tweakGuiColors->GetPowerBombDigitAvailableFont(); + outlineColor = g_tweakGuiColors->GetPowerBombDigitAvailableOutline(); + } else if (x44_pbCapacity > 0) { + fontColor = g_tweakGuiColors->GetPowerBombDigitDelpetedFont(); + outlineColor = g_tweakGuiColors->GetPowerBombDigitDelpetedOutline(); + } else { + fontColor = zeus::CColor::skClear; + outlineColor = zeus::CColor::skClear; + } + x10_textpane_bombdigits->TextSupport().SetFontColor(fontColor); + x10_textpane_bombdigits->TextSupport().SetOutlineColor(outlineColor); - zeus::CColor iconColor; - if (x40_pbAmount > 0 && x4c_hasPb) - iconColor = g_tweakGuiColors->GetPowerBombIconAvailableColor(); - else if (x44_pbCapacity > 0) - iconColor = g_tweakGuiColors->GetPowerBombIconDepletedColor(); - else - iconColor = zeus::CColor::skClear; + zeus::CColor iconColor; + if (x40_pbAmount > 0 && x4c_hasPb) + iconColor = g_tweakGuiColors->GetPowerBombIconAvailableColor(); + else if (x44_pbCapacity > 0) + iconColor = g_tweakGuiColors->GetPowerBombIconDepletedColor(); + else + iconColor = zeus::CColor::skClear; - xc_model_bombicon->SetColor(iconColor); + xc_model_bombicon->SetColor(iconColor); } -void CHudBallInterface::SetBombParams(int pbAmount, int pbCapacity, int availableBombs, - bool hasBombs, bool hasPb, bool init) -{ - if (pbAmount != x40_pbAmount || init) - { - x10_textpane_bombdigits->TextSupport().SetText(hecl::Format("%02d", pbAmount)); - x40_pbAmount = pbAmount; - UpdatePowerBombReadoutColors(); - } +void CHudBallInterface::SetBombParams(int pbAmount, int pbCapacity, int availableBombs, bool hasBombs, bool hasPb, + bool init) { + if (pbAmount != x40_pbAmount || init) { + x10_textpane_bombdigits->TextSupport().SetText(hecl::Format("%02d", pbAmount)); + x40_pbAmount = pbAmount; + UpdatePowerBombReadoutColors(); + } - if (x44_pbCapacity != pbCapacity || init) - { - x44_pbCapacity = pbCapacity; - UpdatePowerBombReadoutColors(); - } + if (x44_pbCapacity != pbCapacity || init) { + x44_pbCapacity = pbCapacity; + UpdatePowerBombReadoutColors(); + } - if (x4c_hasPb != hasPb) - { - x4c_hasPb = hasPb; - UpdatePowerBombReadoutColors(); - } + if (x4c_hasPb != hasPb) { + x4c_hasPb = hasPb; + UpdatePowerBombReadoutColors(); + } - for (int i=0 ; i<3 ; ++i) - { - bool lit = i < availableBombs; - x14_group_bombfilled[i]->SetVisibility(lit && hasBombs, ETraversalMode::Children); - x24_group_bombempty[i]->SetVisibility(!lit && hasBombs, ETraversalMode::Children); - } + for (int i = 0; i < 3; ++i) { + bool lit = i < availableBombs; + x14_group_bombfilled[i]->SetVisibility(lit && hasBombs, ETraversalMode::Children); + x24_group_bombempty[i]->SetVisibility(!lit && hasBombs, ETraversalMode::Children); + } - x48_availableBombs = availableBombs; + x48_availableBombs = availableBombs; - x8_basewidget_bombdeco->SetVisibility(hasBombs && x44_pbCapacity > 0, ETraversalMode::Children); + x8_basewidget_bombdeco->SetVisibility(hasBombs && x44_pbCapacity > 0, ETraversalMode::Children); } -void CHudBallInterface::SetBallModeFactor(float t) -{ - float tmp = 0.5f * 448.f * g_tweakGui->GetBallViewportYReduction(); - x0_camera->SetLocalTransform( - zeus::CTransform::Translate(x34_camPos + zeus::CVector3f(0.f, 0.f, (t * tmp - tmp) * 0.01f))); +void CHudBallInterface::SetBallModeFactor(float t) { + float tmp = 0.5f * 448.f * g_tweakGui->GetBallViewportYReduction(); + x0_camera->SetLocalTransform( + zeus::CTransform::Translate(x34_camPos + zeus::CVector3f(0.f, 0.f, (t * tmp - tmp) * 0.01f))); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CHudBallInterface.hpp b/Runtime/GuiSys/CHudBallInterface.hpp index f28871665..99cd17fc4 100644 --- a/Runtime/GuiSys/CHudBallInterface.hpp +++ b/Runtime/GuiSys/CHudBallInterface.hpp @@ -3,36 +3,32 @@ #include "rstl.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; class CGuiWidget; class CGuiCamera; class CGuiModel; class CGuiTextPane; -class CHudBallInterface -{ - CGuiCamera* x0_camera; - CGuiWidget* x4_basewidget_bombstuff; - CGuiWidget* x8_basewidget_bombdeco; - CGuiModel* xc_model_bombicon; - CGuiTextPane* x10_textpane_bombdigits; - rstl::reserved_vector x14_group_bombfilled; - rstl::reserved_vector x24_group_bombempty; - zeus::CVector3f x34_camPos; - int x40_pbAmount; - int x44_pbCapacity; - int x48_availableBombs; - bool x4c_hasPb; - void UpdatePowerBombReadoutColors(); +class CHudBallInterface { + CGuiCamera* x0_camera; + CGuiWidget* x4_basewidget_bombstuff; + CGuiWidget* x8_basewidget_bombdeco; + CGuiModel* xc_model_bombicon; + CGuiTextPane* x10_textpane_bombdigits; + rstl::reserved_vector x14_group_bombfilled; + rstl::reserved_vector x24_group_bombempty; + zeus::CVector3f x34_camPos; + int x40_pbAmount; + int x44_pbCapacity; + int x48_availableBombs; + bool x4c_hasPb; + void UpdatePowerBombReadoutColors(); + public: - CHudBallInterface(CGuiFrame& selHud, int pbAmount, int pbCapacity, - int availableBombs, bool hasBombs, bool hasPb); - void SetBombParams(int pbAmount, int pbCapacity, int availableBombs, - bool hasBombs, bool hasPb, bool init); - void SetBallModeFactor(float t); + CHudBallInterface(CGuiFrame& selHud, int pbAmount, int pbCapacity, int availableBombs, bool hasBombs, bool hasPb); + void SetBombParams(int pbAmount, int pbCapacity, int availableBombs, bool hasBombs, bool hasPb, bool init); + void SetBallModeFactor(float t); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudBossEnergyInterface.cpp b/Runtime/GuiSys/CHudBossEnergyInterface.cpp index 4919df76f..ae6dc101f 100644 --- a/Runtime/GuiSys/CHudBossEnergyInterface.cpp +++ b/Runtime/GuiSys/CHudBossEnergyInterface.cpp @@ -4,63 +4,53 @@ #include "GameGlobalObjects.hpp" #include "CGuiTextPane.hpp" -namespace urde -{ +namespace urde { -CHudBossEnergyInterface::CHudBossEnergyInterface(CGuiFrame& selHud) -{ - x10_24_visible = false; - x14_basewidget_bossenergystuff = selHud.FindWidget("basewidget_bossenergystuff"); - x18_energybart01_bossbar = static_cast(selHud.FindWidget("energybart01_bossbar")); - x1c_textpane_boss = static_cast(selHud.FindWidget("textpane_boss")); +CHudBossEnergyInterface::CHudBossEnergyInterface(CGuiFrame& selHud) { + x10_24_visible = false; + x14_basewidget_bossenergystuff = selHud.FindWidget("basewidget_bossenergystuff"); + x18_energybart01_bossbar = static_cast(selHud.FindWidget("energybart01_bossbar")); + x1c_textpane_boss = static_cast(selHud.FindWidget("textpane_boss")); - x18_energybart01_bossbar->SetCoordFunc(BossEnergyCoordFunc); - x18_energybart01_bossbar->SetTesselation(0.2f); - ITweakGuiColors::VisorEnergyBarColors barColors = g_tweakGuiColors->GetVisorEnergyBarColors(0); - x18_energybart01_bossbar->SetFilledColor(barColors.filled); - x18_energybart01_bossbar->SetShadowColor(barColors.shadow); - x18_energybart01_bossbar->SetEmptyColor(barColors.empty); + x18_energybart01_bossbar->SetCoordFunc(BossEnergyCoordFunc); + x18_energybart01_bossbar->SetTesselation(0.2f); + ITweakGuiColors::VisorEnergyBarColors barColors = g_tweakGuiColors->GetVisorEnergyBarColors(0); + x18_energybart01_bossbar->SetFilledColor(barColors.filled); + x18_energybart01_bossbar->SetShadowColor(barColors.shadow); + x18_energybart01_bossbar->SetEmptyColor(barColors.empty); } -void CHudBossEnergyInterface::Update(float dt) -{ - if (x10_24_visible) - x4_fader = std::min(x4_fader + dt, 1.f); - else - x4_fader = std::max(0.f, x4_fader - dt); +void CHudBossEnergyInterface::Update(float dt) { + if (x10_24_visible) + x4_fader = std::min(x4_fader + dt, 1.f); + else + x4_fader = std::max(0.f, x4_fader - dt); - if (x4_fader > 0.f) - { - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x0_alpha * x4_fader; - x14_basewidget_bossenergystuff->SetColor(color); - x14_basewidget_bossenergystuff->SetVisibility(true, ETraversalMode::Children); - } - else - { - x14_basewidget_bossenergystuff->SetVisibility(false, ETraversalMode::Children); - } + if (x4_fader > 0.f) { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x0_alpha * x4_fader; + x14_basewidget_bossenergystuff->SetColor(color); + x14_basewidget_bossenergystuff->SetVisibility(true, ETraversalMode::Children); + } else { + x14_basewidget_bossenergystuff->SetVisibility(false, ETraversalMode::Children); + } } -void CHudBossEnergyInterface::SetBossParams(bool visible, std::u16string_view name, - float curEnergy, float maxEnergy) -{ - x10_24_visible = visible; - if (visible) - { - x18_energybart01_bossbar->SetFilledDrainSpeed(maxEnergy); - x18_energybart01_bossbar->SetCurrEnergy(curEnergy, CAuiEnergyBarT01::ESetMode::Normal); - x18_energybart01_bossbar->SetMaxEnergy(maxEnergy); - x1c_textpane_boss->TextSupport().SetText(name); - } - x8_curEnergy = curEnergy; - xc_maxEnergy = maxEnergy; +void CHudBossEnergyInterface::SetBossParams(bool visible, std::u16string_view name, float curEnergy, float maxEnergy) { + x10_24_visible = visible; + if (visible) { + x18_energybart01_bossbar->SetFilledDrainSpeed(maxEnergy); + x18_energybart01_bossbar->SetCurrEnergy(curEnergy, CAuiEnergyBarT01::ESetMode::Normal); + x18_energybart01_bossbar->SetMaxEnergy(maxEnergy); + x1c_textpane_boss->TextSupport().SetText(name); + } + x8_curEnergy = curEnergy; + xc_maxEnergy = maxEnergy; } -std::pair CHudBossEnergyInterface::BossEnergyCoordFunc(float t) -{ - float x = 9.25f * t - 4.625f; - return {zeus::CVector3f(x, 0.f, 0.f), zeus::CVector3f(x, 0.f, 0.4f)}; +std::pair CHudBossEnergyInterface::BossEnergyCoordFunc(float t) { + float x = 9.25f * t - 4.625f; + return {zeus::CVector3f(x, 0.f, 0.f), zeus::CVector3f(x, 0.f, 0.4f)}; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CHudBossEnergyInterface.hpp b/Runtime/GuiSys/CHudBossEnergyInterface.hpp index 56aff1306..589926398 100644 --- a/Runtime/GuiSys/CHudBossEnergyInterface.hpp +++ b/Runtime/GuiSys/CHudBossEnergyInterface.hpp @@ -3,31 +3,28 @@ #include "RetroTypes.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; class CGuiWidget; class CAuiEnergyBarT01; class CGuiTextPane; -class CHudBossEnergyInterface -{ - float x0_alpha; - float x4_fader = 0.f; - float x8_curEnergy = 0.f; - float xc_maxEnergy = 0.f; - bool x10_24_visible : 1; - CGuiWidget* x14_basewidget_bossenergystuff; - CAuiEnergyBarT01* x18_energybart01_bossbar; - CGuiTextPane* x1c_textpane_boss; +class CHudBossEnergyInterface { + float x0_alpha; + float x4_fader = 0.f; + float x8_curEnergy = 0.f; + float xc_maxEnergy = 0.f; + bool x10_24_visible : 1; + CGuiWidget* x14_basewidget_bossenergystuff; + CAuiEnergyBarT01* x18_energybart01_bossbar; + CGuiTextPane* x1c_textpane_boss; + public: - CHudBossEnergyInterface(CGuiFrame& selHud); - void Update(float dt); - void SetAlpha(float a) { x0_alpha = a; } - void SetBossParams(bool visible, std::u16string_view name, - float curEnergy, float maxEnergy); - static std::pair BossEnergyCoordFunc(float t); + CHudBossEnergyInterface(CGuiFrame& selHud); + void Update(float dt); + void SetAlpha(float a) { x0_alpha = a; } + void SetBossParams(bool visible, std::u16string_view name, float curEnergy, float maxEnergy); + static std::pair BossEnergyCoordFunc(float t); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudDecoInterface.cpp b/Runtime/GuiSys/CHudDecoInterface.cpp index f0683036f..20bc9092b 100644 --- a/Runtime/GuiSys/CHudDecoInterface.cpp +++ b/Runtime/GuiSys/CHudDecoInterface.cpp @@ -10,8 +10,7 @@ #include "TCastTo.hpp" #include "CGuiWidgetDrawParms.hpp" -namespace urde -{ +namespace urde { void IHudDecoInterface::SetReticuleTransform(const zeus::CMatrix3f& xf) {} void IHudDecoInterface::SetDecoRotation(float angle) {} @@ -20,634 +19,527 @@ void IHudDecoInterface::Draw() const {} void IHudDecoInterface::ProcessInput(const CFinalInput& input) {} float IHudDecoInterface::GetHudTextAlpha() const { return 1.f; } -CHudDecoInterfaceCombat::CHudDecoInterfaceCombat(CGuiFrame& selHud) -{ - x68_24_visDebug = true; - x68_25_visGame = true; - x6c_camera = selHud.GetFrameCamera(); - x2c_camPos = x6c_camera->GetLocalPosition(); - x70_basewidget_pivot = selHud.FindWidget("basewidget_pivot"); - x74_basewidget_deco = selHud.FindWidget("basewidget_deco"); - x78_basewidget_tickdeco0 = selHud.FindWidget("basewidget_tickdeco0"); - x7c_basewidget_frame = selHud.FindWidget("basewidget_frame"); - x14_pivotPosition = x70_basewidget_pivot->GetIdlePosition(); - x78_basewidget_tickdeco0->SetColor(g_tweakGuiColors->GetTickDecoColor()); - x38_basePosition = x7c_basewidget_frame->GetLocalPosition(); - x44_baseRotation = x7c_basewidget_frame->GetLocalTransform().buildMatrix3f(); - UpdateHudAlpha(); +CHudDecoInterfaceCombat::CHudDecoInterfaceCombat(CGuiFrame& selHud) { + x68_24_visDebug = true; + x68_25_visGame = true; + x6c_camera = selHud.GetFrameCamera(); + x2c_camPos = x6c_camera->GetLocalPosition(); + x70_basewidget_pivot = selHud.FindWidget("basewidget_pivot"); + x74_basewidget_deco = selHud.FindWidget("basewidget_deco"); + x78_basewidget_tickdeco0 = selHud.FindWidget("basewidget_tickdeco0"); + x7c_basewidget_frame = selHud.FindWidget("basewidget_frame"); + x14_pivotPosition = x70_basewidget_pivot->GetIdlePosition(); + x78_basewidget_tickdeco0->SetColor(g_tweakGuiColors->GetTickDecoColor()); + x38_basePosition = x7c_basewidget_frame->GetLocalPosition(); + x44_baseRotation = x7c_basewidget_frame->GetLocalTransform().buildMatrix3f(); + UpdateHudAlpha(); } -void CHudDecoInterfaceCombat::UpdateVisibility() -{ - bool vis = x68_24_visDebug && x68_25_visGame; - x74_basewidget_deco->SetVisibility(vis, ETraversalMode::Children); - x78_basewidget_tickdeco0->SetVisibility(vis, ETraversalMode::Children); +void CHudDecoInterfaceCombat::UpdateVisibility() { + bool vis = x68_24_visDebug && x68_25_visGame; + x74_basewidget_deco->SetVisibility(vis, ETraversalMode::Children); + x78_basewidget_tickdeco0->SetVisibility(vis, ETraversalMode::Children); } -void CHudDecoInterfaceCombat::SetIsVisibleDebug(bool v) -{ - x68_24_visDebug = v; - UpdateVisibility(); +void CHudDecoInterfaceCombat::SetIsVisibleDebug(bool v) { + x68_24_visDebug = v; + UpdateVisibility(); } -void CHudDecoInterfaceCombat::SetIsVisibleGame(bool v) -{ - x68_25_visGame = v; - UpdateVisibility(); +void CHudDecoInterfaceCombat::SetIsVisibleGame(bool v) { + x68_25_visGame = v; + UpdateVisibility(); } -void CHudDecoInterfaceCombat::SetHudRotation(const zeus::CQuaternion& rot) -{ - x4_rotation = rot; +void CHudDecoInterfaceCombat::SetHudRotation(const zeus::CQuaternion& rot) { x4_rotation = rot; } + +void CHudDecoInterfaceCombat::SetHudOffset(const zeus::CVector3f& off) { x20_offset = off; } + +void CHudDecoInterfaceCombat::SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position) { + x7c_basewidget_frame->SetLocalTransform(zeus::CTransform(rotation * x44_baseRotation, position + x38_basePosition)); } -void CHudDecoInterfaceCombat::SetHudOffset(const zeus::CVector3f& off) -{ - x20_offset = off; +void CHudDecoInterfaceCombat::SetFrameColorValue(float v) { + zeus::CColor color = v > 0.f ? zeus::CColor::skWhite : g_tweakGuiColors->GetHudFrameColor(); + x7c_basewidget_frame->SetColor(color); } -void CHudDecoInterfaceCombat::SetDamageTransform(const zeus::CMatrix3f& rotation, - const zeus::CVector3f& position) -{ - x7c_basewidget_frame->SetLocalTransform(zeus::CTransform(rotation * x44_baseRotation, - position + x38_basePosition)); +void CHudDecoInterfaceCombat::Update(float dt, const CStateManager& stateMgr) { + x6c_camera->SetO2WTransform( + MP1::CSamusHud::BuildFinalCameraTransform(x4_rotation, x14_pivotPosition + x20_offset, x2c_camPos)); } -void CHudDecoInterfaceCombat::SetFrameColorValue(float v) -{ - zeus::CColor color = v > 0.f ? zeus::CColor::skWhite : g_tweakGuiColors->GetHudFrameColor(); - x7c_basewidget_frame->SetColor(color); +void CHudDecoInterfaceCombat::UpdateCameraDebugSettings(float fov, float y, float z) { + x6c_camera->SetFov(fov); + x2c_camPos.y() = y; + x2c_camPos.z() = z; } -void CHudDecoInterfaceCombat::Update(float dt, const CStateManager& stateMgr) -{ - x6c_camera->SetO2WTransform(MP1::CSamusHud::BuildFinalCameraTransform( - x4_rotation, x14_pivotPosition + x20_offset, x2c_camPos)); +void CHudDecoInterfaceCombat::UpdateHudAlpha() { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f; + x70_basewidget_pivot->SetColor(color); } -void CHudDecoInterfaceCombat::UpdateCameraDebugSettings(float fov, float y, float z) -{ - x6c_camera->SetFov(fov); - x2c_camPos.y() = y; - x2c_camPos.z() = z; +CHudDecoInterfaceScan::CHudDecoInterfaceScan(CGuiFrame& selHud) : x14_selHud(selHud), x18_scanDisplay(selHud) { + x4_scanHudFlat = g_SimplePool->GetObj("FRME_ScanHudFlat"); + x234_sidesPositioner = g_tweakGui->GetScanSidesPositionStart(); + x240_24_visDebug = true; + x240_25_visGame = true; + x244_camera = selHud.GetFrameCamera(); + x248_basewidget_pivot = selHud.FindWidget("basewidget_pivot"); + x24c_basewidget_leftside = selHud.FindWidget("basewidget_leftside"); + x250_basewidget_rightside = selHud.FindWidget("basewidget_rightside"); + x1f4_pivotPosition = x248_basewidget_pivot->GetIdlePosition(); + if (CGuiWidget* deco = selHud.FindWidget("basewidget_deco")) + deco->SetColor(g_tweakGuiColors->GetHudFrameColor()); + + x218_leftsidePosition = x24c_basewidget_leftside->GetLocalPosition(); + zeus::CTransform leftXf(zeus::CMatrix3f::RotateZ(g_tweakGui->GetScanSidesAngle()), x218_leftsidePosition); + x24c_basewidget_leftside->SetLocalTransform(leftXf); + if (CGuiWidget* w = selHud.FindWidget("basewidget_databankl")) { + zeus::CTransform xf(zeus::CMatrix3f::RotateZ(g_tweakGui->GetScanSidesAngle() * -1.f), w->GetLocalPosition()); + w->SetLocalTransform(xf); + } + if (CGuiWidget* w = selHud.FindWidget("basewidget_leftguages")) { + zeus::CTransform xf(zeus::CMatrix3f(zeus::CVector3f{g_tweakGui->GetScanSidesXScale(), 1.f, 1.f}), + w->GetLocalPosition()); + w->SetLocalTransform(xf); + } + + x224_rightsidePosition = x250_basewidget_rightside->GetLocalPosition(); + zeus::CTransform rightXf(zeus::CMatrix3f::RotateZ(g_tweakGui->GetScanSidesAngle() * -1.f), x224_rightsidePosition); + x250_basewidget_rightside->SetLocalTransform(rightXf); + if (CGuiWidget* w = selHud.FindWidget("basewidget_databankr")) { + zeus::CTransform xf(zeus::CMatrix3f::RotateZ(g_tweakGui->GetScanSidesAngle()), w->GetLocalPosition()); + w->SetLocalTransform(xf); + } + if (CGuiWidget* w = selHud.FindWidget("basewidget_rightguages")) { + zeus::CTransform xf(zeus::CMatrix3f(zeus::CVector3f{g_tweakGui->GetScanSidesXScale(), 1.f, 1.f}), + w->GetLocalPosition()); + w->SetLocalTransform(xf); + } + + zeus::CVector3f sidesPos(x234_sidesPositioner, 0.f, 0.f); + x24c_basewidget_leftside->SetLocalPosition(x24c_basewidget_leftside->RotateO2P(x218_leftsidePosition + sidesPos)); + x250_basewidget_rightside->SetLocalPosition(x250_basewidget_rightside->RotateO2P(x224_rightsidePosition - sidesPos)); + + UpdateHudAlpha(); } -void CHudDecoInterfaceCombat::UpdateHudAlpha() -{ - zeus::CColor color = zeus::CColor::skWhite; - color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f; - x70_basewidget_pivot->SetColor(color); +void CHudDecoInterfaceScan::UpdateVisibility() { + // Empty } -CHudDecoInterfaceScan::CHudDecoInterfaceScan(CGuiFrame& selHud) -: x14_selHud(selHud), x18_scanDisplay(selHud) -{ - x4_scanHudFlat = g_SimplePool->GetObj("FRME_ScanHudFlat"); - x234_sidesPositioner = g_tweakGui->GetScanSidesPositionStart(); - x240_24_visDebug = true; - x240_25_visGame = true; - x244_camera = selHud.GetFrameCamera(); - x248_basewidget_pivot = selHud.FindWidget("basewidget_pivot"); - x24c_basewidget_leftside = selHud.FindWidget("basewidget_leftside"); - x250_basewidget_rightside = selHud.FindWidget("basewidget_rightside"); - x1f4_pivotPosition = x248_basewidget_pivot->GetIdlePosition(); - if (CGuiWidget* deco = selHud.FindWidget("basewidget_deco")) - deco->SetColor(g_tweakGuiColors->GetHudFrameColor()); - - x218_leftsidePosition = x24c_basewidget_leftside->GetLocalPosition(); - zeus::CTransform leftXf(zeus::CMatrix3f::RotateZ(g_tweakGui->GetScanSidesAngle()), x218_leftsidePosition); - x24c_basewidget_leftside->SetLocalTransform(leftXf); - if (CGuiWidget* w = selHud.FindWidget("basewidget_databankl")) - { - zeus::CTransform xf(zeus::CMatrix3f::RotateZ(g_tweakGui->GetScanSidesAngle() * -1.f), w->GetLocalPosition()); - w->SetLocalTransform(xf); - } - if (CGuiWidget* w = selHud.FindWidget("basewidget_leftguages")) - { - zeus::CTransform xf(zeus::CMatrix3f(zeus::CVector3f{g_tweakGui->GetScanSidesXScale(), 1.f, 1.f}), - w->GetLocalPosition()); - w->SetLocalTransform(xf); - } - - x224_rightsidePosition = x250_basewidget_rightside->GetLocalPosition(); - zeus::CTransform rightXf(zeus::CMatrix3f::RotateZ(g_tweakGui->GetScanSidesAngle() * -1.f), x224_rightsidePosition); - x250_basewidget_rightside->SetLocalTransform(rightXf); - if (CGuiWidget* w = selHud.FindWidget("basewidget_databankr")) - { - zeus::CTransform xf(zeus::CMatrix3f::RotateZ(g_tweakGui->GetScanSidesAngle()), w->GetLocalPosition()); - w->SetLocalTransform(xf); - } - if (CGuiWidget* w = selHud.FindWidget("basewidget_rightguages")) - { - zeus::CTransform xf(zeus::CMatrix3f(zeus::CVector3f{g_tweakGui->GetScanSidesXScale(), 1.f, 1.f}), - w->GetLocalPosition()); - w->SetLocalTransform(xf); - } - - zeus::CVector3f sidesPos(x234_sidesPositioner, 0.f, 0.f); - x24c_basewidget_leftside->SetLocalPosition(x24c_basewidget_leftside->RotateO2P( - x218_leftsidePosition + sidesPos)); - x250_basewidget_rightside->SetLocalPosition(x250_basewidget_rightside->RotateO2P( - x224_rightsidePosition - sidesPos)); - - UpdateHudAlpha(); +void CHudDecoInterfaceScan::SetIsVisibleDebug(bool v) { + x240_24_visDebug = v; + UpdateVisibility(); } -void CHudDecoInterfaceScan::UpdateVisibility() -{ - // Empty +void CHudDecoInterfaceScan::SetIsVisibleGame(bool v) { + x240_25_visGame = v; + UpdateVisibility(); } -void CHudDecoInterfaceScan::SetIsVisibleDebug(bool v) -{ - x240_24_visDebug = v; - UpdateVisibility(); +void CHudDecoInterfaceScan::SetHudRotation(const zeus::CQuaternion& rot) { x1e4_rotation = rot; } + +void CHudDecoInterfaceScan::SetHudOffset(const zeus::CVector3f& off) { x200_offset = off; } + +void CHudDecoInterfaceScan::SetReticuleTransform(const zeus::CMatrix3f& xf) { + // Empty } -void CHudDecoInterfaceScan::SetIsVisibleGame(bool v) -{ - x240_25_visGame = v; - UpdateVisibility(); +void CHudDecoInterfaceScan::SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position) { + // Empty } -void CHudDecoInterfaceScan::SetHudRotation(const zeus::CQuaternion& rot) -{ - x1e4_rotation = rot; +void CHudDecoInterfaceScan::SetFrameColorValue(float v) { + // Empty } -void CHudDecoInterfaceScan::SetHudOffset(const zeus::CVector3f& off) -{ - x200_offset = off; +void CHudDecoInterfaceScan::InitializeFlatFrame() { + x10_loadedScanHudFlat = x4_scanHudFlat.GetObj(); + x10_loadedScanHudFlat->SetMaxAspect(1.33f); + x10_loadedScanHudFlat->GetFrameCamera()->SetO2WTransform(zeus::CTransform::Translate(x20c_camPos)); + x258_flat_basewidget_scanguage = x10_loadedScanHudFlat->FindWidget("basewidget_scanguage"); + x258_flat_basewidget_scanguage->SetVisibility(false, ETraversalMode::Children); + x254_flat_textpane_scanning = static_cast(x10_loadedScanHudFlat->FindWidget("textpane_scanning")); + x25c_flat_energybart01_scanbar = + static_cast(x10_loadedScanHudFlat->FindWidget("energybart01_scanbar")); + x264_flat_textpane_message = static_cast(x10_loadedScanHudFlat->FindWidget("textpane_message")); + x268_flat_textpane_scrollmessage = + static_cast(x10_loadedScanHudFlat->FindWidget("textpane_scrollmessage")); + x260_flat_basewidget_textgroup = x10_loadedScanHudFlat->FindWidget("basewidget_textgroup"); + x26c_flat_model_xmark = static_cast(x10_loadedScanHudFlat->FindWidget("model_xmark")); + x270_flat_model_abutton = static_cast(x10_loadedScanHudFlat->FindWidget("model_abutton")); + x274_flat_model_dash = static_cast(x10_loadedScanHudFlat->FindWidget("model_dash")); + x260_flat_basewidget_textgroup->SetVisibility(false, ETraversalMode::Children); + x254_flat_textpane_scanning->SetIsVisible(false); + x254_flat_textpane_scanning->TextSupport().SetFontColor(g_tweakGuiColors->GetHudMessageFill()); + x254_flat_textpane_scanning->TextSupport().SetOutlineColor(g_tweakGuiColors->GetHudMessageOutline()); + x25c_flat_energybart01_scanbar->SetCoordFunc(CAuiEnergyBarT01::DownloadBarCoordFunc); + x25c_flat_energybart01_scanbar->ResetMaxEnergy(); + x25c_flat_energybart01_scanbar->SetFilledColor(zeus::CColor(0.4f, 0.68f, 0.88f, 1.f)); + x25c_flat_energybart01_scanbar->SetShadowColor(zeus::CColor::skClear); + x25c_flat_energybart01_scanbar->SetEmptyColor(zeus::CColor::skClear); + x25c_flat_energybart01_scanbar->SetFilledDrainSpeed(999.f); + x25c_flat_energybart01_scanbar->SetShadowDrainSpeed(999.f); + x25c_flat_energybart01_scanbar->SetShadowDrainDelay(0.f); + x25c_flat_energybart01_scanbar->SetIsAlwaysResetTimer(false); + x26c_flat_model_xmark->SetVisibility(false, ETraversalMode::Children); + x26c_flat_model_xmark->SetVisibility(false, ETraversalMode::Children); + x270_flat_model_abutton->SetVisibility(false, ETraversalMode::Children); + x274_flat_model_dash->SetVisibility(false, ETraversalMode::Children); } -void CHudDecoInterfaceScan::SetReticuleTransform(const zeus::CMatrix3f& xf) -{ - // Empty -} - -void CHudDecoInterfaceScan::SetDamageTransform(const zeus::CMatrix3f& rotation, - const zeus::CVector3f& position) -{ - // Empty -} - -void CHudDecoInterfaceScan::SetFrameColorValue(float v) -{ - // Empty -} - -void CHudDecoInterfaceScan::InitializeFlatFrame() -{ - x10_loadedScanHudFlat = x4_scanHudFlat.GetObj(); - x10_loadedScanHudFlat->SetMaxAspect(1.33f); - x10_loadedScanHudFlat->GetFrameCamera()->SetO2WTransform(zeus::CTransform::Translate(x20c_camPos)); - x258_flat_basewidget_scanguage = x10_loadedScanHudFlat->FindWidget("basewidget_scanguage"); - x258_flat_basewidget_scanguage->SetVisibility(false, ETraversalMode::Children); - x254_flat_textpane_scanning = static_cast(x10_loadedScanHudFlat->FindWidget("textpane_scanning")); - x25c_flat_energybart01_scanbar = static_cast(x10_loadedScanHudFlat->FindWidget("energybart01_scanbar")); - x264_flat_textpane_message = static_cast(x10_loadedScanHudFlat->FindWidget("textpane_message")); - x268_flat_textpane_scrollmessage = static_cast(x10_loadedScanHudFlat->FindWidget("textpane_scrollmessage")); - x260_flat_basewidget_textgroup = x10_loadedScanHudFlat->FindWidget("basewidget_textgroup"); - x26c_flat_model_xmark = static_cast(x10_loadedScanHudFlat->FindWidget("model_xmark")); - x270_flat_model_abutton = static_cast(x10_loadedScanHudFlat->FindWidget("model_abutton")); - x274_flat_model_dash = static_cast(x10_loadedScanHudFlat->FindWidget("model_dash")); - x260_flat_basewidget_textgroup->SetVisibility(false, ETraversalMode::Children); - x254_flat_textpane_scanning->SetIsVisible(false); - x254_flat_textpane_scanning->TextSupport().SetFontColor(g_tweakGuiColors->GetHudMessageFill()); - x254_flat_textpane_scanning->TextSupport().SetOutlineColor(g_tweakGuiColors->GetHudMessageOutline()); - x25c_flat_energybart01_scanbar->SetCoordFunc(CAuiEnergyBarT01::DownloadBarCoordFunc); - x25c_flat_energybart01_scanbar->ResetMaxEnergy(); - x25c_flat_energybart01_scanbar->SetFilledColor(zeus::CColor(0.4f, 0.68f, 0.88f, 1.f)); - x25c_flat_energybart01_scanbar->SetShadowColor(zeus::CColor::skClear); - x25c_flat_energybart01_scanbar->SetEmptyColor(zeus::CColor::skClear); - x25c_flat_energybart01_scanbar->SetFilledDrainSpeed(999.f); - x25c_flat_energybart01_scanbar->SetShadowDrainSpeed(999.f); - x25c_flat_energybart01_scanbar->SetShadowDrainDelay(0.f); - x25c_flat_energybart01_scanbar->SetIsAlwaysResetTimer(false); - x26c_flat_model_xmark->SetVisibility(false, ETraversalMode::Children); - x26c_flat_model_xmark->SetVisibility(false, ETraversalMode::Children); - x270_flat_model_abutton->SetVisibility(false, ETraversalMode::Children); - x274_flat_model_dash->SetVisibility(false, ETraversalMode::Children); -} - -const CScannableObjectInfo* CHudDecoInterfaceScan::GetCurrScanInfo(const CStateManager& stateMgr) const -{ - if (x1d4_latestScanState == CPlayer::EPlayerScanState::NotScanning) - return nullptr; - - if (TCastToConstPtr act = stateMgr.GetObjectById(x1d2_latestScanningObject)) - return act->GetScannableObjectInfo(); - +const CScannableObjectInfo* CHudDecoInterfaceScan::GetCurrScanInfo(const CStateManager& stateMgr) const { + if (x1d4_latestScanState == CPlayer::EPlayerScanState::NotScanning) return nullptr; + + if (TCastToConstPtr act = stateMgr.GetObjectById(x1d2_latestScanningObject)) + return act->GetScannableObjectInfo(); + + return nullptr; } -void CHudDecoInterfaceScan::UpdateScanDisplay(const CStateManager& stateMgr, float dt) -{ - CPlayer& player = stateMgr.GetPlayer(); - CPlayer::EPlayerScanState scanState = player.GetScanningState(); - if (scanState != x1d4_latestScanState) - { - if (player.IsNewScanScanning()) - { - if (scanState == CPlayer::EPlayerScanState::ScanComplete) - { - if (x1d4_latestScanState == CPlayer::EPlayerScanState::Scanning) - { - // Scan complete - x254_flat_textpane_scanning->TextSupport().SetText(g_MainStringTable->GetString(15)); - x254_flat_textpane_scanning->TextSupport().SetTypeWriteEffectOptions(false, 0.f, 40.f); - x238_scanningTextAlpha = 2.f; - } - } - else if (scanState == CPlayer::EPlayerScanState::Scanning) - { - // Scanning - x254_flat_textpane_scanning->TextSupport().SetText(g_MainStringTable->GetString(14)); - x254_flat_textpane_scanning->TextSupport().SetTypeWriteEffectOptions(false, 0.f, 40.f); - x238_scanningTextAlpha = 2.f; - } +void CHudDecoInterfaceScan::UpdateScanDisplay(const CStateManager& stateMgr, float dt) { + CPlayer& player = stateMgr.GetPlayer(); + CPlayer::EPlayerScanState scanState = player.GetScanningState(); + if (scanState != x1d4_latestScanState) { + if (player.IsNewScanScanning()) { + if (scanState == CPlayer::EPlayerScanState::ScanComplete) { + if (x1d4_latestScanState == CPlayer::EPlayerScanState::Scanning) { + // Scan complete + x254_flat_textpane_scanning->TextSupport().SetText(g_MainStringTable->GetString(15)); + x254_flat_textpane_scanning->TextSupport().SetTypeWriteEffectOptions(false, 0.f, 40.f); + x238_scanningTextAlpha = 2.f; } - x1d4_latestScanState = scanState; + } else if (scanState == CPlayer::EPlayerScanState::Scanning) { + // Scanning + x254_flat_textpane_scanning->TextSupport().SetText(g_MainStringTable->GetString(14)); + x254_flat_textpane_scanning->TextSupport().SetTypeWriteEffectOptions(false, 0.f, 40.f); + x238_scanningTextAlpha = 2.f; + } } + x1d4_latestScanState = scanState; + } - if (player.GetScanningObjectId() != x1d2_latestScanningObject) - x1d2_latestScanningObject = player.GetScanningObjectId(); + if (player.GetScanningObjectId() != x1d2_latestScanningObject) + x1d2_latestScanningObject = player.GetScanningObjectId(); - if (player.GetOrbitTargetId() != x1d0_latestHudPoi) - { - x1d0_latestHudPoi = player.GetOrbitTargetId(); - if (x1d0_latestHudPoi != kInvalidUniqueId) - { - if (!player.ObjectInScanningRange(x1d0_latestHudPoi, stateMgr)) - { - // Object out of scanning range - x254_flat_textpane_scanning->TextSupport().SetText(g_MainStringTable->GetString(16)); - x254_flat_textpane_scanning->TextSupport().SetTypeWriteEffectOptions(true, 0.f, 40.f); - x238_scanningTextAlpha = 1.f; - } - } + if (player.GetOrbitTargetId() != x1d0_latestHudPoi) { + x1d0_latestHudPoi = player.GetOrbitTargetId(); + if (x1d0_latestHudPoi != kInvalidUniqueId) { + if (!player.ObjectInScanningRange(x1d0_latestHudPoi, stateMgr)) { + // Object out of scanning range + x254_flat_textpane_scanning->TextSupport().SetText(g_MainStringTable->GetString(16)); + x254_flat_textpane_scanning->TextSupport().SetTypeWriteEffectOptions(true, 0.f, 40.f); + x238_scanningTextAlpha = 1.f; + } } + } - const CScannableObjectInfo* scanInfo = GetCurrScanInfo(stateMgr); - if (x1d2_latestScanningObject != x18_scanDisplay.x10_objId || !scanInfo) - { - x18_scanDisplay.StopScan(); - if (x18_scanDisplay.xc_state == CScanDisplay::EScanState::Inactive && scanInfo) - { - x18_scanDisplay.StartScan(x1d2_latestScanningObject, *scanInfo, x264_flat_textpane_message, - x268_flat_textpane_scrollmessage, x260_flat_basewidget_textgroup, - x26c_flat_model_xmark, x270_flat_model_abutton, x274_flat_model_dash, - player.GetScanningTime()); - } + const CScannableObjectInfo* scanInfo = GetCurrScanInfo(stateMgr); + if (x1d2_latestScanningObject != x18_scanDisplay.x10_objId || !scanInfo) { + x18_scanDisplay.StopScan(); + if (x18_scanDisplay.xc_state == CScanDisplay::EScanState::Inactive && scanInfo) { + x18_scanDisplay.StartScan(x1d2_latestScanningObject, *scanInfo, x264_flat_textpane_message, + x268_flat_textpane_scrollmessage, x260_flat_basewidget_textgroup, x26c_flat_model_xmark, + x270_flat_model_abutton, x274_flat_model_dash, player.GetScanningTime()); } + } - x18_scanDisplay.Update(dt, player.GetScanningTime()); + x18_scanDisplay.Update(dt, player.GetScanningTime()); - if (x1d2_latestScanningObject != kInvalidUniqueId && GetCurrScanInfo(stateMgr)) - if (TCastToConstPtr act = stateMgr.GetObjectById(x1d2_latestScanningObject)) - if (const CScannableObjectInfo* actScan = act->GetScannableObjectInfo()) - x25c_flat_energybart01_scanbar->SetCurrEnergy(x1d8_scanningTime / actScan->GetTotalDownloadTime(), - CAuiEnergyBarT01::ESetMode::Normal); + if (x1d2_latestScanningObject != kInvalidUniqueId && GetCurrScanInfo(stateMgr)) + if (TCastToConstPtr act = stateMgr.GetObjectById(x1d2_latestScanningObject)) + if (const CScannableObjectInfo* actScan = act->GetScannableObjectInfo()) + x25c_flat_energybart01_scanbar->SetCurrEnergy(x1d8_scanningTime / actScan->GetTotalDownloadTime(), + CAuiEnergyBarT01::ESetMode::Normal); - if (x1d4_latestScanState != CPlayer::EPlayerScanState::Scanning) - if (x1d0_latestHudPoi == kInvalidUniqueId || player.ObjectInScanningRange(x1d0_latestHudPoi, stateMgr)) - x238_scanningTextAlpha = std::max(0.f, x238_scanningTextAlpha - dt); + if (x1d4_latestScanState != CPlayer::EPlayerScanState::Scanning) + if (x1d0_latestHudPoi == kInvalidUniqueId || player.ObjectInScanningRange(x1d0_latestHudPoi, stateMgr)) + x238_scanningTextAlpha = std::max(0.f, x238_scanningTextAlpha - dt); - if (x238_scanningTextAlpha > 0.f) - { - zeus::CColor color = zeus::CColor::skWhite; - color.a() = std::min(x238_scanningTextAlpha, 1.f); - x254_flat_textpane_scanning->SetColor(color); - x254_flat_textpane_scanning->SetIsVisible(true); - } - else - { - x254_flat_textpane_scanning->SetIsVisible(false); - } - - if (GetCurrScanInfo(stateMgr)) - x23c_scanBarAlpha = std::min(x23c_scanBarAlpha + 2.f * dt, 1.f); - else - x23c_scanBarAlpha = std::max(0.f, x23c_scanBarAlpha - 2.f * dt); - - if (x23c_scanBarAlpha > 0.f) - { - zeus::CColor color = zeus::CColor::skWhite; - color.a() = std::min(x23c_scanBarAlpha, 1.f); - x258_flat_basewidget_scanguage->SetColor(color); - x258_flat_basewidget_scanguage->SetVisibility(true, ETraversalMode::Children); - } - else - { - x258_flat_basewidget_scanguage->SetVisibility(false, ETraversalMode::Children); - } -} - -void CHudDecoInterfaceScan::Update(float dt, const CStateManager& stateMgr) -{ - CPlayer& player = stateMgr.GetPlayer(); - CPlayer::EPlayerScanState scanState = player.GetScanningState(); - if (scanState != CPlayer::EPlayerScanState::NotScanning) - x1d8_scanningTime = player.GetScanningTime(); - - if (scanState == CPlayer::EPlayerScanState::Scanning || scanState == CPlayer::EPlayerScanState::ScanComplete) - x230_sidesTimer = std::min(x230_sidesTimer + dt, g_tweakGui->GetScanSidesEndTime()); - else - x230_sidesTimer = std::max(0.f, x230_sidesTimer - dt); - - float sidesT = x230_sidesTimer < g_tweakGui->GetScanSidesStartTime() ? 0.f : - (x230_sidesTimer - g_tweakGui->GetScanSidesStartTime()) / g_tweakGui->GetScanSidesDuration(); - float oldSidesPositioner = x234_sidesPositioner; - x234_sidesPositioner = (1.f - sidesT) * g_tweakGui->GetScanSidesPositionStart() + - sidesT * g_tweakGui->GetScanSidesPositionEnd(); - if (oldSidesPositioner != x234_sidesPositioner) - { - zeus::CVector3f sidesPos(x234_sidesPositioner, 0.f, 0.f); - x24c_basewidget_leftside->SetLocalPosition(x218_leftsidePosition + - x24c_basewidget_leftside->RotateO2P(sidesPos)); - x250_basewidget_rightside->SetLocalPosition(x224_rightsidePosition - - x250_basewidget_rightside->RotateO2P(sidesPos)); - } - - x244_camera->SetO2WTransform( - MP1::CSamusHud::BuildFinalCameraTransform(x1e4_rotation, x1f4_pivotPosition + x200_offset, x20c_camPos)); - - if (!x10_loadedScanHudFlat) - { - if (!x4_scanHudFlat.IsLoaded() || !x4_scanHudFlat->GetIsFinishedLoading()) - return; - InitializeFlatFrame(); - } - - x10_loadedScanHudFlat->Update(dt); - UpdateScanDisplay(stateMgr, dt); -} - -void CHudDecoInterfaceScan::Draw() const -{ - x18_scanDisplay.Draw(); - if (x10_loadedScanHudFlat) - x10_loadedScanHudFlat->Draw(CGuiWidgetDrawParms::Default); -} - -void CHudDecoInterfaceScan::ProcessInput(const CFinalInput& input) -{ - x18_scanDisplay.ProcessInput(input); -} - -void CHudDecoInterfaceScan::UpdateCameraDebugSettings(float fov, float y, float z) -{ - x244_camera->SetFov(fov); - x20c_camPos.y() = y; - x20c_camPos.z() = z; -} - -void CHudDecoInterfaceScan::UpdateHudAlpha() -{ + if (x238_scanningTextAlpha > 0.f) { zeus::CColor color = zeus::CColor::skWhite; - color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f; - x248_basewidget_pivot->SetColor(color); -} + color.a() = std::min(x238_scanningTextAlpha, 1.f); + x254_flat_textpane_scanning->SetColor(color); + x254_flat_textpane_scanning->SetIsVisible(true); + } else { + x254_flat_textpane_scanning->SetIsVisible(false); + } -float CHudDecoInterfaceScan::GetHudTextAlpha() const -{ - return 1.f - std::max(std::min(x238_scanningTextAlpha, 1.f), x18_scanDisplay.x1a8_bodyAlpha); -} + if (GetCurrScanInfo(stateMgr)) + x23c_scanBarAlpha = std::min(x23c_scanBarAlpha + 2.f * dt, 1.f); + else + x23c_scanBarAlpha = std::max(0.f, x23c_scanBarAlpha - 2.f * dt); -CHudDecoInterfaceXRay::CHudDecoInterfaceXRay(CGuiFrame& selHud) -{ - xa0_camera = selHud.GetFrameCamera(); - x30_camPos = xa0_camera->GetLocalPosition(); - - x9c_24_visDebug = true; - x9c_25_visGame = true; - - xa4_basewidget_pivot = selHud.FindWidget("basewidget_pivot"); - xa8_basewidget_seeker = selHud.FindWidget("basewidget_seeker"); - xac_basewidget_rotate = selHud.FindWidget("basewidget_rotate"); - - if (CGuiWidget* w = selHud.FindWidget("basewidget_energydeco")) - w->SetColor(g_tweakGuiColors->GetXRayEnergyDecoColor()); - - if (CGuiWidget* w = selHud.FindWidget("model_frame")) - w->SetDepthWrite(true); - if (CGuiWidget* w = selHud.FindWidget("model_frame1")) - w->SetDepthWrite(true); - if (CGuiWidget* w = selHud.FindWidget("model_frame2")) - w->SetDepthWrite(true); - if (CGuiWidget* w = selHud.FindWidget("model_frame3")) - w->SetDepthWrite(true); - if (CGuiWidget* w = selHud.FindWidget("model_misslieslider")) - w->SetDepthWrite(true); - if (CGuiWidget* w = selHud.FindWidget("model_threatslider")) - w->SetDepthWrite(true); - - UpdateHudAlpha(); -} - -void CHudDecoInterfaceXRay::UpdateVisibility() -{ - // Empty -} - -void CHudDecoInterfaceXRay::SetIsVisibleDebug(bool v) -{ - x9c_24_visDebug = v; - UpdateVisibility(); -} - -void CHudDecoInterfaceXRay::SetIsVisibleGame(bool v) -{ - x9c_25_visGame = v; - UpdateVisibility(); -} - -void CHudDecoInterfaceXRay::SetHudRotation(const zeus::CQuaternion& rot) -{ - x8_rotation = rot; -} - -void CHudDecoInterfaceXRay::SetHudOffset(const zeus::CVector3f& off) -{ - x24_offset = off; -} - -void CHudDecoInterfaceXRay::SetReticuleTransform(const zeus::CMatrix3f& xf) -{ - x3c_reticuleXf = xf; -} - -void CHudDecoInterfaceXRay::SetDecoRotation(float angle) -{ - xac_basewidget_rotate->SetLocalTransform(zeus::CTransform(zeus::CMatrix3f::RotateY(angle), - xac_basewidget_rotate->GetLocalPosition())); -} - -void CHudDecoInterfaceXRay::SetDamageTransform(const zeus::CMatrix3f& rotation, - const zeus::CVector3f& position) -{ - // Empty -} - -void CHudDecoInterfaceXRay::SetFrameColorValue(float v) -{ - // Empty -} - -void CHudDecoInterfaceXRay::Update(float dt, const CStateManager& stateMgr) -{ - if (stateMgr.GetPlayer().GetOrbitState() == CPlayer::EPlayerOrbitState::OrbitObject) - x4_seekerScale = std::max(x4_seekerScale - 3.f * dt, 0.35f); - else - x4_seekerScale = std::min(3.f * dt + x4_seekerScale, 1.f); - - xa0_camera->SetO2WTransform( - MP1::CSamusHud::BuildFinalCameraTransform(x8_rotation, x18_pivotPosition + x24_offset, x30_camPos)); - - xa8_basewidget_seeker->SetLocalTransform( - zeus::CTransform(zeus::CMatrix3f(x4_seekerScale) * x3c_reticuleXf, x60_seekerPosition)); -} - -void CHudDecoInterfaceXRay::UpdateCameraDebugSettings(float fov, float y, float z) -{ - xa0_camera->SetFov(fov); - x30_camPos.y() = y; - x30_camPos.z() = z; -} - -void CHudDecoInterfaceXRay::UpdateHudAlpha() -{ + if (x23c_scanBarAlpha > 0.f) { zeus::CColor color = zeus::CColor::skWhite; - color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f; - xa4_basewidget_pivot->SetColor(color); + color.a() = std::min(x23c_scanBarAlpha, 1.f); + x258_flat_basewidget_scanguage->SetColor(color); + x258_flat_basewidget_scanguage->SetVisibility(true, ETraversalMode::Children); + } else { + x258_flat_basewidget_scanguage->SetVisibility(false, ETraversalMode::Children); + } } -CHudDecoInterfaceThermal::CHudDecoInterfaceThermal(CGuiFrame& selHud) -{ - x70_24_visDebug = true; - x70_25_visGame = true; +void CHudDecoInterfaceScan::Update(float dt, const CStateManager& stateMgr) { + CPlayer& player = stateMgr.GetPlayer(); + CPlayer::EPlayerScanState scanState = player.GetScanningState(); + if (scanState != CPlayer::EPlayerScanState::NotScanning) + x1d8_scanningTime = player.GetScanningTime(); - x74_camera = selHud.GetFrameCamera(); - x2c_camPos = x74_camera->GetLocalPosition(); + if (scanState == CPlayer::EPlayerScanState::Scanning || scanState == CPlayer::EPlayerScanState::ScanComplete) + x230_sidesTimer = std::min(x230_sidesTimer + dt, g_tweakGui->GetScanSidesEndTime()); + else + x230_sidesTimer = std::max(0.f, x230_sidesTimer - dt); - x78_basewidget_pivot = selHud.FindWidget("basewidget_pivot"); - x7c_basewidget_reticle = selHud.FindWidget("basewidget_reticle"); - x80_model_retflash = static_cast(selHud.FindWidget("model_retflash")); + float sidesT = x230_sidesTimer < g_tweakGui->GetScanSidesStartTime() + ? 0.f + : (x230_sidesTimer - g_tweakGui->GetScanSidesStartTime()) / g_tweakGui->GetScanSidesDuration(); + float oldSidesPositioner = x234_sidesPositioner; + x234_sidesPositioner = + (1.f - sidesT) * g_tweakGui->GetScanSidesPositionStart() + sidesT * g_tweakGui->GetScanSidesPositionEnd(); + if (oldSidesPositioner != x234_sidesPositioner) { + zeus::CVector3f sidesPos(x234_sidesPositioner, 0.f, 0.f); + x24c_basewidget_leftside->SetLocalPosition(x218_leftsidePosition + x24c_basewidget_leftside->RotateO2P(sidesPos)); + x250_basewidget_rightside->SetLocalPosition(x224_rightsidePosition - + x250_basewidget_rightside->RotateO2P(sidesPos)); + } - x14_pivotPosition = x78_basewidget_pivot->GetIdlePosition(); - x5c_reticulePosition = x7c_basewidget_reticle->GetIdlePosition(); + x244_camera->SetO2WTransform( + MP1::CSamusHud::BuildFinalCameraTransform(x1e4_rotation, x1f4_pivotPosition + x200_offset, x20c_camPos)); - if (CGuiWidget* w = selHud.FindWidget("basewidget_deco")) - w->SetColor(g_tweakGuiColors->GetThermalDecoColor()); + if (!x10_loadedScanHudFlat) { + if (!x4_scanHudFlat.IsLoaded() || !x4_scanHudFlat->GetIsFinishedLoading()) + return; + InitializeFlatFrame(); + } - if (CGuiWidget* w = selHud.FindWidget("basewidget_oultlinesa")) - w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); + x10_loadedScanHudFlat->Update(dt); + UpdateScanDisplay(stateMgr, dt); +} - if (CGuiWidget* w = selHud.FindWidget("basewidget_lock")) - w->SetColor(g_tweakGuiColors->GetThermalLockColor()); +void CHudDecoInterfaceScan::Draw() const { + x18_scanDisplay.Draw(); + if (x10_loadedScanHudFlat) + x10_loadedScanHudFlat->Draw(CGuiWidgetDrawParms::Default); +} - if (CGuiWidget* w = selHud.FindWidget("basewidget_reticle")) - w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); +void CHudDecoInterfaceScan::ProcessInput(const CFinalInput& input) { x18_scanDisplay.ProcessInput(input); } - if (CGuiWidget* w = selHud.FindWidget("basewidget_lockon")) - w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); +void CHudDecoInterfaceScan::UpdateCameraDebugSettings(float fov, float y, float z) { + x244_camera->SetFov(fov); + x20c_camPos.y() = y; + x20c_camPos.z() = z; +} - if (CGuiWidget* w = selHud.FindWidget("model_threaticon")) - w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); +void CHudDecoInterfaceScan::UpdateHudAlpha() { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f; + x248_basewidget_pivot->SetColor(color); +} - if (CGuiWidget* w = selHud.FindWidget("model_missileicon")) - w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); +float CHudDecoInterfaceScan::GetHudTextAlpha() const { + return 1.f - std::max(std::min(x238_scanningTextAlpha, 1.f), x18_scanDisplay.x1a8_bodyAlpha); +} - if (CGuiWidget* w = selHud.FindWidget("basewidget_lock")) - { - for (CGuiWidget* c = static_cast(w->GetChildObject()); c; - c = static_cast(c->GetNextSibling())) - { - x84_lockonWidgets.push_back({c, c->GetLocalTransform()}); - c->SetLocalTransform(c->GetLocalTransform() * zeus::CTransform::Scale(x68_lockonScale)); - } +CHudDecoInterfaceXRay::CHudDecoInterfaceXRay(CGuiFrame& selHud) { + xa0_camera = selHud.GetFrameCamera(); + x30_camPos = xa0_camera->GetLocalPosition(); + + x9c_24_visDebug = true; + x9c_25_visGame = true; + + xa4_basewidget_pivot = selHud.FindWidget("basewidget_pivot"); + xa8_basewidget_seeker = selHud.FindWidget("basewidget_seeker"); + xac_basewidget_rotate = selHud.FindWidget("basewidget_rotate"); + + if (CGuiWidget* w = selHud.FindWidget("basewidget_energydeco")) + w->SetColor(g_tweakGuiColors->GetXRayEnergyDecoColor()); + + if (CGuiWidget* w = selHud.FindWidget("model_frame")) + w->SetDepthWrite(true); + if (CGuiWidget* w = selHud.FindWidget("model_frame1")) + w->SetDepthWrite(true); + if (CGuiWidget* w = selHud.FindWidget("model_frame2")) + w->SetDepthWrite(true); + if (CGuiWidget* w = selHud.FindWidget("model_frame3")) + w->SetDepthWrite(true); + if (CGuiWidget* w = selHud.FindWidget("model_misslieslider")) + w->SetDepthWrite(true); + if (CGuiWidget* w = selHud.FindWidget("model_threatslider")) + w->SetDepthWrite(true); + + UpdateHudAlpha(); +} + +void CHudDecoInterfaceXRay::UpdateVisibility() { + // Empty +} + +void CHudDecoInterfaceXRay::SetIsVisibleDebug(bool v) { + x9c_24_visDebug = v; + UpdateVisibility(); +} + +void CHudDecoInterfaceXRay::SetIsVisibleGame(bool v) { + x9c_25_visGame = v; + UpdateVisibility(); +} + +void CHudDecoInterfaceXRay::SetHudRotation(const zeus::CQuaternion& rot) { x8_rotation = rot; } + +void CHudDecoInterfaceXRay::SetHudOffset(const zeus::CVector3f& off) { x24_offset = off; } + +void CHudDecoInterfaceXRay::SetReticuleTransform(const zeus::CMatrix3f& xf) { x3c_reticuleXf = xf; } + +void CHudDecoInterfaceXRay::SetDecoRotation(float angle) { + xac_basewidget_rotate->SetLocalTransform( + zeus::CTransform(zeus::CMatrix3f::RotateY(angle), xac_basewidget_rotate->GetLocalPosition())); +} + +void CHudDecoInterfaceXRay::SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position) { + // Empty +} + +void CHudDecoInterfaceXRay::SetFrameColorValue(float v) { + // Empty +} + +void CHudDecoInterfaceXRay::Update(float dt, const CStateManager& stateMgr) { + if (stateMgr.GetPlayer().GetOrbitState() == CPlayer::EPlayerOrbitState::OrbitObject) + x4_seekerScale = std::max(x4_seekerScale - 3.f * dt, 0.35f); + else + x4_seekerScale = std::min(3.f * dt + x4_seekerScale, 1.f); + + xa0_camera->SetO2WTransform( + MP1::CSamusHud::BuildFinalCameraTransform(x8_rotation, x18_pivotPosition + x24_offset, x30_camPos)); + + xa8_basewidget_seeker->SetLocalTransform( + zeus::CTransform(zeus::CMatrix3f(x4_seekerScale) * x3c_reticuleXf, x60_seekerPosition)); +} + +void CHudDecoInterfaceXRay::UpdateCameraDebugSettings(float fov, float y, float z) { + xa0_camera->SetFov(fov); + x30_camPos.y() = y; + x30_camPos.z() = z; +} + +void CHudDecoInterfaceXRay::UpdateHudAlpha() { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f; + xa4_basewidget_pivot->SetColor(color); +} + +CHudDecoInterfaceThermal::CHudDecoInterfaceThermal(CGuiFrame& selHud) { + x70_24_visDebug = true; + x70_25_visGame = true; + + x74_camera = selHud.GetFrameCamera(); + x2c_camPos = x74_camera->GetLocalPosition(); + + x78_basewidget_pivot = selHud.FindWidget("basewidget_pivot"); + x7c_basewidget_reticle = selHud.FindWidget("basewidget_reticle"); + x80_model_retflash = static_cast(selHud.FindWidget("model_retflash")); + + x14_pivotPosition = x78_basewidget_pivot->GetIdlePosition(); + x5c_reticulePosition = x7c_basewidget_reticle->GetIdlePosition(); + + if (CGuiWidget* w = selHud.FindWidget("basewidget_deco")) + w->SetColor(g_tweakGuiColors->GetThermalDecoColor()); + + if (CGuiWidget* w = selHud.FindWidget("basewidget_oultlinesa")) + w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); + + if (CGuiWidget* w = selHud.FindWidget("basewidget_lock")) + w->SetColor(g_tweakGuiColors->GetThermalLockColor()); + + if (CGuiWidget* w = selHud.FindWidget("basewidget_reticle")) + w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); + + if (CGuiWidget* w = selHud.FindWidget("basewidget_lockon")) + w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); + + if (CGuiWidget* w = selHud.FindWidget("model_threaticon")) + w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); + + if (CGuiWidget* w = selHud.FindWidget("model_missileicon")) + w->SetColor(g_tweakGuiColors->GetThermalOutlinesColor()); + + if (CGuiWidget* w = selHud.FindWidget("basewidget_lock")) { + for (CGuiWidget* c = static_cast(w->GetChildObject()); c; + c = static_cast(c->GetNextSibling())) { + x84_lockonWidgets.push_back({c, c->GetLocalTransform()}); + c->SetLocalTransform(c->GetLocalTransform() * zeus::CTransform::Scale(x68_lockonScale)); } + } - x14_pivotPosition = x78_basewidget_pivot->GetIdlePosition(); - UpdateHudAlpha(); + x14_pivotPosition = x78_basewidget_pivot->GetIdlePosition(); + UpdateHudAlpha(); } -void CHudDecoInterfaceThermal::UpdateVisibility() -{ - // Empty +void CHudDecoInterfaceThermal::UpdateVisibility() { + // Empty } -void CHudDecoInterfaceThermal::SetIsVisibleDebug(bool v) -{ - x70_24_visDebug = v; - UpdateVisibility(); +void CHudDecoInterfaceThermal::SetIsVisibleDebug(bool v) { + x70_24_visDebug = v; + UpdateVisibility(); } -void CHudDecoInterfaceThermal::SetIsVisibleGame(bool v) -{ - x70_25_visGame = v; - UpdateVisibility(); +void CHudDecoInterfaceThermal::SetIsVisibleGame(bool v) { + x70_25_visGame = v; + UpdateVisibility(); } -void CHudDecoInterfaceThermal::SetHudRotation(const zeus::CQuaternion& rot) -{ - x4_rotation = rot; +void CHudDecoInterfaceThermal::SetHudRotation(const zeus::CQuaternion& rot) { x4_rotation = rot; } + +void CHudDecoInterfaceThermal::SetHudOffset(const zeus::CVector3f& off) { x20_offset = off; } + +void CHudDecoInterfaceThermal::SetReticuleTransform(const zeus::CMatrix3f& xf) { x38_reticuleXf = xf; } + +void CHudDecoInterfaceThermal::SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position) { + // Empty } -void CHudDecoInterfaceThermal::SetHudOffset(const zeus::CVector3f& off) -{ - x20_offset = off; +void CHudDecoInterfaceThermal::Update(float dt, const CStateManager& stateMgr) { + float oldLockonScale = x68_lockonScale; + if (stateMgr.GetPlayer().GetOrbitTargetId() != kInvalidUniqueId) + x68_lockonScale = std::max(x68_lockonScale - 15.f * dt, 1.f); + else + x68_lockonScale = std::min(x68_lockonScale + 15.f * dt, 5.f); + + if (oldLockonScale != x68_lockonScale) + for (auto& lockWidget : x84_lockonWidgets) + lockWidget.first->SetLocalTransform(lockWidget.second * zeus::CTransform::Scale(x68_lockonScale)); + + x6c_retflashTimer += dt; + if (x6c_retflashTimer > 1.f) + x6c_retflashTimer -= 2.f; + + zeus::CColor flashColor = zeus::CColor::skWhite; + flashColor.a() = std::fabs(x6c_retflashTimer) * 0.5f + 0.5f; + x80_model_retflash->SetColor(flashColor); + + x74_camera->SetO2WTransform( + MP1::CSamusHud::BuildFinalCameraTransform(x4_rotation, x14_pivotPosition + x20_offset, x2c_camPos)); + + x7c_basewidget_reticle->SetLocalTransform(zeus::CTransform(x38_reticuleXf, x5c_reticulePosition)); } -void CHudDecoInterfaceThermal::SetReticuleTransform(const zeus::CMatrix3f& xf) -{ - x38_reticuleXf = xf; +void CHudDecoInterfaceThermal::UpdateCameraDebugSettings(float fov, float y, float z) { + x74_camera->SetFov(fov); + x2c_camPos.y() = y; + x2c_camPos.z() = z; } -void CHudDecoInterfaceThermal::SetDamageTransform(const zeus::CMatrix3f& rotation, - const zeus::CVector3f& position) -{ - // Empty +void CHudDecoInterfaceThermal::UpdateHudAlpha() { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f; + x78_basewidget_pivot->SetColor(color); } -void CHudDecoInterfaceThermal::Update(float dt, const CStateManager& stateMgr) -{ - float oldLockonScale = x68_lockonScale; - if (stateMgr.GetPlayer().GetOrbitTargetId() != kInvalidUniqueId) - x68_lockonScale = std::max(x68_lockonScale - 15.f * dt, 1.f); - else - x68_lockonScale = std::min(x68_lockonScale + 15.f * dt, 5.f); - - if (oldLockonScale != x68_lockonScale) - for (auto& lockWidget : x84_lockonWidgets) - lockWidget.first->SetLocalTransform(lockWidget.second * zeus::CTransform::Scale(x68_lockonScale)); - - x6c_retflashTimer += dt; - if (x6c_retflashTimer > 1.f) - x6c_retflashTimer -= 2.f; - - zeus::CColor flashColor = zeus::CColor::skWhite; - flashColor.a() = std::fabs(x6c_retflashTimer) * 0.5f + 0.5f; - x80_model_retflash->SetColor(flashColor); - - x74_camera->SetO2WTransform( - MP1::CSamusHud::BuildFinalCameraTransform(x4_rotation, x14_pivotPosition + x20_offset, x2c_camPos)); - - x7c_basewidget_reticle->SetLocalTransform(zeus::CTransform(x38_reticuleXf, x5c_reticulePosition)); -} - -void CHudDecoInterfaceThermal::UpdateCameraDebugSettings(float fov, float y, float z) -{ - x74_camera->SetFov(fov); - x2c_camPos.y() = y; - x2c_camPos.z() = z; -} - -void CHudDecoInterfaceThermal::UpdateHudAlpha() -{ - zeus::CColor color = zeus::CColor::skWhite; - color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f; - x78_basewidget_pivot->SetColor(color); -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CHudDecoInterface.hpp b/Runtime/GuiSys/CHudDecoInterface.hpp index 3bfe3c9f4..b012096db 100644 --- a/Runtime/GuiSys/CHudDecoInterface.hpp +++ b/Runtime/GuiSys/CHudDecoInterface.hpp @@ -7,8 +7,7 @@ #include "CScanDisplay.hpp" #include "World/CPlayer.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; struct CFinalInput; class CStateManager; @@ -17,176 +16,174 @@ class CGuiWidget; class CAuiEnergyBarT01; class CGuiModel; -class IHudDecoInterface -{ +class IHudDecoInterface { public: - virtual void SetIsVisibleDebug(bool v)=0; - virtual void SetIsVisibleGame(bool v)=0; - virtual void SetHudRotation(const zeus::CQuaternion& rot)=0; - virtual void SetHudOffset(const zeus::CVector3f& off)=0; - virtual void SetReticuleTransform(const zeus::CMatrix3f& xf); - virtual void SetDecoRotation(float angle); - virtual void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position)=0; - virtual void SetFrameColorValue(float v); - virtual void Update(float dt, const CStateManager& stateMgr)=0; - virtual void Draw() const; - virtual void ProcessInput(const CFinalInput& input); - virtual void UpdateCameraDebugSettings(float fov, float y, float z)=0; - virtual void UpdateHudAlpha()=0; - virtual float GetHudTextAlpha() const; - virtual ~IHudDecoInterface() = default; + virtual void SetIsVisibleDebug(bool v) = 0; + virtual void SetIsVisibleGame(bool v) = 0; + virtual void SetHudRotation(const zeus::CQuaternion& rot) = 0; + virtual void SetHudOffset(const zeus::CVector3f& off) = 0; + virtual void SetReticuleTransform(const zeus::CMatrix3f& xf); + virtual void SetDecoRotation(float angle); + virtual void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position) = 0; + virtual void SetFrameColorValue(float v); + virtual void Update(float dt, const CStateManager& stateMgr) = 0; + virtual void Draw() const; + virtual void ProcessInput(const CFinalInput& input); + virtual void UpdateCameraDebugSettings(float fov, float y, float z) = 0; + virtual void UpdateHudAlpha() = 0; + virtual float GetHudTextAlpha() const; + virtual ~IHudDecoInterface() = default; }; -class CHudDecoInterfaceCombat : public IHudDecoInterface -{ - zeus::CQuaternion x4_rotation; - zeus::CVector3f x14_pivotPosition; - zeus::CVector3f x20_offset; - zeus::CVector3f x2c_camPos; - zeus::CVector3f x38_basePosition; - zeus::CMatrix3f x44_baseRotation; - bool x68_24_visDebug : 1; - bool x68_25_visGame : 1; - CGuiCamera* x6c_camera; - CGuiWidget* x70_basewidget_pivot; - CGuiWidget* x74_basewidget_deco; - CGuiWidget* x78_basewidget_tickdeco0; - CGuiWidget* x7c_basewidget_frame; - void UpdateVisibility(); +class CHudDecoInterfaceCombat : public IHudDecoInterface { + zeus::CQuaternion x4_rotation; + zeus::CVector3f x14_pivotPosition; + zeus::CVector3f x20_offset; + zeus::CVector3f x2c_camPos; + zeus::CVector3f x38_basePosition; + zeus::CMatrix3f x44_baseRotation; + bool x68_24_visDebug : 1; + bool x68_25_visGame : 1; + CGuiCamera* x6c_camera; + CGuiWidget* x70_basewidget_pivot; + CGuiWidget* x74_basewidget_deco; + CGuiWidget* x78_basewidget_tickdeco0; + CGuiWidget* x7c_basewidget_frame; + void UpdateVisibility(); + public: - CHudDecoInterfaceCombat(CGuiFrame& selHud); - void SetIsVisibleDebug(bool v); - void SetIsVisibleGame(bool v); - void SetHudRotation(const zeus::CQuaternion& rot); - void SetHudOffset(const zeus::CVector3f& off); - void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position); - void SetFrameColorValue(float v); - void Update(float dt, const CStateManager& stateMgr); - void UpdateCameraDebugSettings(float fov, float y, float z); - void UpdateHudAlpha(); + CHudDecoInterfaceCombat(CGuiFrame& selHud); + void SetIsVisibleDebug(bool v); + void SetIsVisibleGame(bool v); + void SetHudRotation(const zeus::CQuaternion& rot); + void SetHudOffset(const zeus::CVector3f& off); + void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position); + void SetFrameColorValue(float v); + void Update(float dt, const CStateManager& stateMgr); + void UpdateCameraDebugSettings(float fov, float y, float z); + void UpdateHudAlpha(); }; -class CHudDecoInterfaceScan : public IHudDecoInterface -{ - TLockedToken x4_scanHudFlat; - CGuiFrame* x10_loadedScanHudFlat = nullptr; - CGuiFrame& x14_selHud; - CScanDisplay x18_scanDisplay; - TUniqueId x1d0_latestHudPoi = kInvalidUniqueId; - TUniqueId x1d2_latestScanningObject = kInvalidUniqueId; - CPlayer::EPlayerScanState x1d4_latestScanState = CPlayer::EPlayerScanState::NotScanning; - float x1d8_scanningTime = 0.f; - float x1dc_ = 0.f; - float x1e0_ = 1.f; - zeus::CQuaternion x1e4_rotation; - zeus::CVector3f x1f4_pivotPosition; - zeus::CVector3f x200_offset; - zeus::CVector3f x20c_camPos; - zeus::CVector3f x218_leftsidePosition; - zeus::CVector3f x224_rightsidePosition; - float x230_sidesTimer = 0.f; - float x234_sidesPositioner; - float x238_scanningTextAlpha = 0.f; - float x23c_scanBarAlpha = 0.f; - bool x240_24_visDebug : 1; - bool x240_25_visGame : 1; - CGuiCamera* x244_camera; - CGuiWidget* x248_basewidget_pivot; - CGuiWidget* x24c_basewidget_leftside; - CGuiWidget* x250_basewidget_rightside; - CGuiTextPane* x254_flat_textpane_scanning; - CGuiWidget* x258_flat_basewidget_scanguage; - CAuiEnergyBarT01* x25c_flat_energybart01_scanbar; - CGuiWidget* x260_flat_basewidget_textgroup; - CGuiTextPane* x264_flat_textpane_message; - CGuiTextPane* x268_flat_textpane_scrollmessage; - CGuiModel* x26c_flat_model_xmark; - CGuiModel* x270_flat_model_abutton; - CGuiModel* x274_flat_model_dash; - void UpdateVisibility(); +class CHudDecoInterfaceScan : public IHudDecoInterface { + TLockedToken x4_scanHudFlat; + CGuiFrame* x10_loadedScanHudFlat = nullptr; + CGuiFrame& x14_selHud; + CScanDisplay x18_scanDisplay; + TUniqueId x1d0_latestHudPoi = kInvalidUniqueId; + TUniqueId x1d2_latestScanningObject = kInvalidUniqueId; + CPlayer::EPlayerScanState x1d4_latestScanState = CPlayer::EPlayerScanState::NotScanning; + float x1d8_scanningTime = 0.f; + float x1dc_ = 0.f; + float x1e0_ = 1.f; + zeus::CQuaternion x1e4_rotation; + zeus::CVector3f x1f4_pivotPosition; + zeus::CVector3f x200_offset; + zeus::CVector3f x20c_camPos; + zeus::CVector3f x218_leftsidePosition; + zeus::CVector3f x224_rightsidePosition; + float x230_sidesTimer = 0.f; + float x234_sidesPositioner; + float x238_scanningTextAlpha = 0.f; + float x23c_scanBarAlpha = 0.f; + bool x240_24_visDebug : 1; + bool x240_25_visGame : 1; + CGuiCamera* x244_camera; + CGuiWidget* x248_basewidget_pivot; + CGuiWidget* x24c_basewidget_leftside; + CGuiWidget* x250_basewidget_rightside; + CGuiTextPane* x254_flat_textpane_scanning; + CGuiWidget* x258_flat_basewidget_scanguage; + CAuiEnergyBarT01* x25c_flat_energybart01_scanbar; + CGuiWidget* x260_flat_basewidget_textgroup; + CGuiTextPane* x264_flat_textpane_message; + CGuiTextPane* x268_flat_textpane_scrollmessage; + CGuiModel* x26c_flat_model_xmark; + CGuiModel* x270_flat_model_abutton; + CGuiModel* x274_flat_model_dash; + void UpdateVisibility(); + public: - CHudDecoInterfaceScan(CGuiFrame& selHud); - void SetIsVisibleDebug(bool v); - void SetIsVisibleGame(bool v); - void SetHudRotation(const zeus::CQuaternion& rot); - void SetHudOffset(const zeus::CVector3f& off); - void SetReticuleTransform(const zeus::CMatrix3f& xf); - void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position); - void SetFrameColorValue(float v); - void InitializeFlatFrame(); - const CScannableObjectInfo* GetCurrScanInfo(const CStateManager& stateMgr) const; - void UpdateScanDisplay(const CStateManager& stateMgr, float dt); - void Update(float dt, const CStateManager& stateMgr); - void Draw() const; - void ProcessInput(const CFinalInput& input); - void UpdateCameraDebugSettings(float fov, float y, float z); - void UpdateHudAlpha(); - float GetHudTextAlpha() const; + CHudDecoInterfaceScan(CGuiFrame& selHud); + void SetIsVisibleDebug(bool v); + void SetIsVisibleGame(bool v); + void SetHudRotation(const zeus::CQuaternion& rot); + void SetHudOffset(const zeus::CVector3f& off); + void SetReticuleTransform(const zeus::CMatrix3f& xf); + void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position); + void SetFrameColorValue(float v); + void InitializeFlatFrame(); + const CScannableObjectInfo* GetCurrScanInfo(const CStateManager& stateMgr) const; + void UpdateScanDisplay(const CStateManager& stateMgr, float dt); + void Update(float dt, const CStateManager& stateMgr); + void Draw() const; + void ProcessInput(const CFinalInput& input); + void UpdateCameraDebugSettings(float fov, float y, float z); + void UpdateHudAlpha(); + float GetHudTextAlpha() const; }; -class CHudDecoInterfaceXRay : public IHudDecoInterface -{ - float x4_seekerScale = 1.f; - zeus::CQuaternion x8_rotation; - zeus::CVector3f x18_pivotPosition; - zeus::CVector3f x24_offset; - zeus::CVector3f x30_camPos; - zeus::CMatrix3f x3c_reticuleXf; - zeus::CVector3f x60_seekerPosition; - zeus::CVector3f x6c_; - zeus::CMatrix3f x78_; - bool x9c_24_visDebug : 1; - bool x9c_25_visGame : 1; - CGuiCamera* xa0_camera; - CGuiWidget* xa4_basewidget_pivot; - CGuiWidget* xa8_basewidget_seeker; - CGuiWidget* xac_basewidget_rotate; - void UpdateVisibility(); +class CHudDecoInterfaceXRay : public IHudDecoInterface { + float x4_seekerScale = 1.f; + zeus::CQuaternion x8_rotation; + zeus::CVector3f x18_pivotPosition; + zeus::CVector3f x24_offset; + zeus::CVector3f x30_camPos; + zeus::CMatrix3f x3c_reticuleXf; + zeus::CVector3f x60_seekerPosition; + zeus::CVector3f x6c_; + zeus::CMatrix3f x78_; + bool x9c_24_visDebug : 1; + bool x9c_25_visGame : 1; + CGuiCamera* xa0_camera; + CGuiWidget* xa4_basewidget_pivot; + CGuiWidget* xa8_basewidget_seeker; + CGuiWidget* xac_basewidget_rotate; + void UpdateVisibility(); + public: - CHudDecoInterfaceXRay(CGuiFrame& selHud); - void SetIsVisibleDebug(bool v); - void SetIsVisibleGame(bool v); - void SetHudRotation(const zeus::CQuaternion& rot); - void SetHudOffset(const zeus::CVector3f& off); - void SetReticuleTransform(const zeus::CMatrix3f& xf); - void SetDecoRotation(float angle); - void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position); - void SetFrameColorValue(float v); - void Update(float dt, const CStateManager& stateMgr); - void UpdateCameraDebugSettings(float fov, float y, float z); - void UpdateHudAlpha(); + CHudDecoInterfaceXRay(CGuiFrame& selHud); + void SetIsVisibleDebug(bool v); + void SetIsVisibleGame(bool v); + void SetHudRotation(const zeus::CQuaternion& rot); + void SetHudOffset(const zeus::CVector3f& off); + void SetReticuleTransform(const zeus::CMatrix3f& xf); + void SetDecoRotation(float angle); + void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position); + void SetFrameColorValue(float v); + void Update(float dt, const CStateManager& stateMgr); + void UpdateCameraDebugSettings(float fov, float y, float z); + void UpdateHudAlpha(); }; -class CHudDecoInterfaceThermal : public IHudDecoInterface -{ - zeus::CQuaternion x4_rotation; - zeus::CVector3f x14_pivotPosition; - zeus::CVector3f x20_offset; - zeus::CVector3f x2c_camPos; - zeus::CMatrix3f x38_reticuleXf; - zeus::CVector3f x5c_reticulePosition; - float x68_lockonScale = 5.f; - float x6c_retflashTimer = 0.f; - bool x70_24_visDebug : 1; - bool x70_25_visGame : 1; - CGuiCamera* x74_camera; - CGuiWidget* x78_basewidget_pivot; - CGuiWidget* x7c_basewidget_reticle; - CGuiModel* x80_model_retflash; - std::vector> x84_lockonWidgets; - void UpdateVisibility(); +class CHudDecoInterfaceThermal : public IHudDecoInterface { + zeus::CQuaternion x4_rotation; + zeus::CVector3f x14_pivotPosition; + zeus::CVector3f x20_offset; + zeus::CVector3f x2c_camPos; + zeus::CMatrix3f x38_reticuleXf; + zeus::CVector3f x5c_reticulePosition; + float x68_lockonScale = 5.f; + float x6c_retflashTimer = 0.f; + bool x70_24_visDebug : 1; + bool x70_25_visGame : 1; + CGuiCamera* x74_camera; + CGuiWidget* x78_basewidget_pivot; + CGuiWidget* x7c_basewidget_reticle; + CGuiModel* x80_model_retflash; + std::vector> x84_lockonWidgets; + void UpdateVisibility(); + public: - CHudDecoInterfaceThermal(CGuiFrame& selHud); - void SetIsVisibleDebug(bool v); - void SetIsVisibleGame(bool v); - void SetHudRotation(const zeus::CQuaternion& rot); - void SetHudOffset(const zeus::CVector3f& off); - void SetReticuleTransform(const zeus::CMatrix3f& xf); - void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position); - void Update(float dt, const CStateManager& stateMgr); - void UpdateCameraDebugSettings(float fov, float y, float z); - void UpdateHudAlpha(); + CHudDecoInterfaceThermal(CGuiFrame& selHud); + void SetIsVisibleDebug(bool v); + void SetIsVisibleGame(bool v); + void SetHudRotation(const zeus::CQuaternion& rot); + void SetHudOffset(const zeus::CVector3f& off); + void SetReticuleTransform(const zeus::CMatrix3f& xf); + void SetDamageTransform(const zeus::CMatrix3f& rotation, const zeus::CVector3f& position); + void Update(float dt, const CStateManager& stateMgr); + void UpdateCameraDebugSettings(float fov, float y, float z); + void UpdateHudAlpha(); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudEnergyInterface.cpp b/Runtime/GuiSys/CHudEnergyInterface.cpp index c6a64a80d..ca178558a 100644 --- a/Runtime/GuiSys/CHudEnergyInterface.cpp +++ b/Runtime/GuiSys/CHudEnergyInterface.cpp @@ -7,192 +7,166 @@ #include "Audio/CSfxManager.hpp" #include "CGuiFrame.hpp" -namespace urde -{ +namespace urde { -static const CAuiEnergyBarT01::FCoordFunc CoordFuncs[] = -{ - CHudEnergyInterface::CombatEnergyCoordFunc, - CHudEnergyInterface::CombatEnergyCoordFunc, - CHudEnergyInterface::XRayEnergyCoordFunc, - CHudEnergyInterface::ThermalEnergyCoordFunc, - CHudEnergyInterface::BallEnergyCoordFunc -}; +static const CAuiEnergyBarT01::FCoordFunc CoordFuncs[] = { + CHudEnergyInterface::CombatEnergyCoordFunc, CHudEnergyInterface::CombatEnergyCoordFunc, + CHudEnergyInterface::XRayEnergyCoordFunc, CHudEnergyInterface::ThermalEnergyCoordFunc, + CHudEnergyInterface::BallEnergyCoordFunc}; -static const float Tesselations[] = -{ - 0.2f, 0.2f, 0.1f, 0.2f, 1.f -}; +static const float Tesselations[] = {0.2f, 0.2f, 0.1f, 0.2f, 1.f}; -CHudEnergyInterface::CHudEnergyInterface(CGuiFrame& selHud, float tankEnergy, int totalEnergyTanks, - int numTanksFilled, bool energyLow, EHudType hudType) -: x0_hudType(hudType), xc_tankEnergy(tankEnergy), x10_totalEnergyTanks(totalEnergyTanks), - x14_numTanksFilled(numTanksFilled) -{ - x1c_24_ = true; - x1c_25_ = true; - x1c_26_barDirty = true; - x1c_27_energyLow = energyLow; +CHudEnergyInterface::CHudEnergyInterface(CGuiFrame& selHud, float tankEnergy, int totalEnergyTanks, int numTanksFilled, + bool energyLow, EHudType hudType) +: x0_hudType(hudType) +, xc_tankEnergy(tankEnergy) +, x10_totalEnergyTanks(totalEnergyTanks) +, x14_numTanksFilled(numTanksFilled) { + x1c_24_ = true; + x1c_25_ = true; + x1c_26_barDirty = true; + x1c_27_energyLow = energyLow; - x20_textpane_energydigits = static_cast(selHud.FindWidget("textpane_energydigits")); - x24_meter_energytanks = static_cast(selHud.FindWidget("meter_energytanks")); - x28_textpane_energywarning = static_cast(selHud.FindWidget("textpane_energywarning")); - x2c_energybart01_energybar = static_cast(selHud.FindWidget("energybart01_energybar")); + x20_textpane_energydigits = static_cast(selHud.FindWidget("textpane_energydigits")); + x24_meter_energytanks = static_cast(selHud.FindWidget("meter_energytanks")); + x28_textpane_energywarning = static_cast(selHud.FindWidget("textpane_energywarning")); + x2c_energybart01_energybar = static_cast(selHud.FindWidget("energybart01_energybar")); - x2c_energybart01_energybar->SetCoordFunc(CoordFuncs[int(hudType)]); - x2c_energybart01_energybar->SetTesselation(Tesselations[int(hudType)]); + x2c_energybart01_energybar->SetCoordFunc(CoordFuncs[int(hudType)]); + x2c_energybart01_energybar->SetTesselation(Tesselations[int(hudType)]); - ITweakGuiColors::VisorEnergyBarColors barColors = g_tweakGuiColors->GetVisorEnergyBarColors(int(hudType)); - ITweakGuiColors::VisorEnergyInitColors initColors = g_tweakGuiColors->GetVisorEnergyInitColors(int(hudType)); + ITweakGuiColors::VisorEnergyBarColors barColors = g_tweakGuiColors->GetVisorEnergyBarColors(int(hudType)); + ITweakGuiColors::VisorEnergyInitColors initColors = g_tweakGuiColors->GetVisorEnergyInitColors(int(hudType)); - x20_textpane_energydigits->TextSupport().SetFontColor(initColors.digitsFont); - x20_textpane_energydigits->TextSupport().SetOutlineColor(initColors.digitsOutline); + x20_textpane_energydigits->TextSupport().SetFontColor(initColors.digitsFont); + x20_textpane_energydigits->TextSupport().SetOutlineColor(initColors.digitsOutline); - x2c_energybart01_energybar->SetMaxEnergy(CPlayerState::GetBaseHealthCapacity()); - x2c_energybart01_energybar->SetFilledColor(barColors.filled); - x2c_energybart01_energybar->SetShadowColor(barColors.shadow); - x2c_energybart01_energybar->SetEmptyColor(barColors.empty); - x2c_energybart01_energybar->SetFilledDrainSpeed(g_tweakGui->GetEnergyBarFilledSpeed()); - x2c_energybart01_energybar->SetShadowDrainSpeed(g_tweakGui->GetEnergyBarShadowSpeed()); - x2c_energybart01_energybar->SetShadowDrainDelay(g_tweakGui->GetEnergyBarDrainDelay()); - x2c_energybart01_energybar->SetIsAlwaysResetTimer(g_tweakGui->GetEnergyBarAlwaysResetDelay()); + x2c_energybart01_energybar->SetMaxEnergy(CPlayerState::GetBaseHealthCapacity()); + x2c_energybart01_energybar->SetFilledColor(barColors.filled); + x2c_energybart01_energybar->SetShadowColor(barColors.shadow); + x2c_energybart01_energybar->SetEmptyColor(barColors.empty); + x2c_energybart01_energybar->SetFilledDrainSpeed(g_tweakGui->GetEnergyBarFilledSpeed()); + x2c_energybart01_energybar->SetShadowDrainSpeed(g_tweakGui->GetEnergyBarShadowSpeed()); + x2c_energybart01_energybar->SetShadowDrainDelay(g_tweakGui->GetEnergyBarDrainDelay()); + x2c_energybart01_energybar->SetIsAlwaysResetTimer(g_tweakGui->GetEnergyBarAlwaysResetDelay()); - x24_meter_energytanks->SetMaxCapacity(14); + x24_meter_energytanks->SetMaxCapacity(14); - if (x28_textpane_energywarning) - { - x28_textpane_energywarning->TextSupport().SetFontColor(g_tweakGuiColors->GetEnergyWarningFont()); - x28_textpane_energywarning->TextSupport().SetOutlineColor(g_tweakGuiColors->GetEnergyWarningOutline()); - if (x1c_27_energyLow) - x28_textpane_energywarning->TextSupport().SetText(g_MainStringTable->GetString(9)); - else - x28_textpane_energywarning->TextSupport().SetText(u""); - } - - for (int i=0 ; i<14 ; ++i) - { - CGuiGroup* g = static_cast(x24_meter_energytanks->GetWorkerWidget(i)); - if (CGuiWidget* w = g->GetWorkerWidget(0)) - w->SetColor(initColors.tankFilled); - if (CGuiWidget* w = g->GetWorkerWidget(1)) - w->SetColor(initColors.tankEmpty); - } -} - -void CHudEnergyInterface::Update(float dt, float energyLowPulse) -{ - if (x28_textpane_energywarning) - { - if (x1c_27_energyLow) - { - x4_energyLowFader = std::min(x4_energyLowFader + 2.f * dt, 1.f); - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x4_energyLowFader * energyLowPulse; - x28_textpane_energywarning->SetColor(color); - } - else - { - x4_energyLowFader = std::max(0.f, x4_energyLowFader - 2.f * dt); - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x4_energyLowFader * energyLowPulse; - x28_textpane_energywarning->SetColor(color); - } - - if (x28_textpane_energywarning->GetGeometryColor().a()) - x28_textpane_energywarning->SetIsVisible(true); - else - x28_textpane_energywarning->SetIsVisible(false); - } - - if (x2c_energybart01_energybar->GetFilledEnergy() != x18_cachedBarEnergy || x1c_26_barDirty) - { - x1c_26_barDirty = false; - x18_cachedBarEnergy = x2c_energybart01_energybar->GetFilledEnergy(); - std::string string = hecl::Format("%02d", - int(std::fmod(x18_cachedBarEnergy, CPlayerState::GetEnergyTankCapacity()))); - x20_textpane_energydigits->TextSupport().SetText(string); - } - - ITweakGuiColors::VisorEnergyBarColors barColors = g_tweakGuiColors->GetVisorEnergyBarColors(int(x0_hudType)); - zeus::CColor emptyColor = x1c_27_energyLow ? g_tweakGuiColors->GetEnergyBarEmptyLowEnergy() : barColors.empty; - zeus::CColor filledColor = x1c_27_energyLow ? g_tweakGuiColors->GetEnergyBarFilledLowEnergy() : barColors.filled; - zeus::CColor shadowColor = x1c_27_energyLow ? g_tweakGuiColors->GetEnergyBarShadowLowEnergy() : barColors.shadow; - zeus::CColor useFillColor = zeus::CColor::lerp(filledColor, g_tweakGuiColors->GetEnergyBarFlashColor(), x8_flashMag); + if (x28_textpane_energywarning) { + x28_textpane_energywarning->TextSupport().SetFontColor(g_tweakGuiColors->GetEnergyWarningFont()); + x28_textpane_energywarning->TextSupport().SetOutlineColor(g_tweakGuiColors->GetEnergyWarningOutline()); if (x1c_27_energyLow) - useFillColor = zeus::CColor::lerp(useFillColor, zeus::CColor(1.f, 0.8f, 0.4f, 1.f), energyLowPulse); - x2c_energybart01_energybar->SetFilledColor(useFillColor); - x2c_energybart01_energybar->SetShadowColor(shadowColor); - x2c_energybart01_energybar->SetEmptyColor(emptyColor); + x28_textpane_energywarning->TextSupport().SetText(g_MainStringTable->GetString(9)); + else + x28_textpane_energywarning->TextSupport().SetText(u""); + } + + for (int i = 0; i < 14; ++i) { + CGuiGroup* g = static_cast(x24_meter_energytanks->GetWorkerWidget(i)); + if (CGuiWidget* w = g->GetWorkerWidget(0)) + w->SetColor(initColors.tankFilled); + if (CGuiWidget* w = g->GetWorkerWidget(1)) + w->SetColor(initColors.tankEmpty); + } } -void CHudEnergyInterface::SetEnergyLow(bool energyLow) -{ - if (x1c_27_energyLow == energyLow) - return; +void CHudEnergyInterface::Update(float dt, float energyLowPulse) { + if (x28_textpane_energywarning) { + if (x1c_27_energyLow) { + x4_energyLowFader = std::min(x4_energyLowFader + 2.f * dt, 1.f); + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x4_energyLowFader * energyLowPulse; + x28_textpane_energywarning->SetColor(color); + } else { + x4_energyLowFader = std::max(0.f, x4_energyLowFader - 2.f * dt); + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x4_energyLowFader * energyLowPulse; + x28_textpane_energywarning->SetColor(color); + } - std::u16string string; - if (energyLow) - string = g_MainStringTable->GetString(9); + if (x28_textpane_energywarning->GetGeometryColor().a()) + x28_textpane_energywarning->SetIsVisible(true); + else + x28_textpane_energywarning->SetIsVisible(false); + } - if (x28_textpane_energywarning) - x28_textpane_energywarning->TextSupport().SetText(string); + if (x2c_energybart01_energybar->GetFilledEnergy() != x18_cachedBarEnergy || x1c_26_barDirty) { + x1c_26_barDirty = false; + x18_cachedBarEnergy = x2c_energybart01_energybar->GetFilledEnergy(); + std::string string = + hecl::Format("%02d", int(std::fmod(x18_cachedBarEnergy, CPlayerState::GetEnergyTankCapacity()))); + x20_textpane_energydigits->TextSupport().SetText(string); + } - if (energyLow) - CSfxManager::SfxStart(SFXui_energy_low, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - - x1c_27_energyLow = energyLow; + ITweakGuiColors::VisorEnergyBarColors barColors = g_tweakGuiColors->GetVisorEnergyBarColors(int(x0_hudType)); + zeus::CColor emptyColor = x1c_27_energyLow ? g_tweakGuiColors->GetEnergyBarEmptyLowEnergy() : barColors.empty; + zeus::CColor filledColor = x1c_27_energyLow ? g_tweakGuiColors->GetEnergyBarFilledLowEnergy() : barColors.filled; + zeus::CColor shadowColor = x1c_27_energyLow ? g_tweakGuiColors->GetEnergyBarShadowLowEnergy() : barColors.shadow; + zeus::CColor useFillColor = zeus::CColor::lerp(filledColor, g_tweakGuiColors->GetEnergyBarFlashColor(), x8_flashMag); + if (x1c_27_energyLow) + useFillColor = zeus::CColor::lerp(useFillColor, zeus::CColor(1.f, 0.8f, 0.4f, 1.f), energyLowPulse); + x2c_energybart01_energybar->SetFilledColor(useFillColor); + x2c_energybart01_energybar->SetShadowColor(shadowColor); + x2c_energybart01_energybar->SetEmptyColor(emptyColor); } -void CHudEnergyInterface::SetFlashMagnitude(float mag) -{ - x8_flashMag = zeus::clamp(0.f, mag, 1.f); +void CHudEnergyInterface::SetEnergyLow(bool energyLow) { + if (x1c_27_energyLow == energyLow) + return; + + std::u16string string; + if (energyLow) + string = g_MainStringTable->GetString(9); + + if (x28_textpane_energywarning) + x28_textpane_energywarning->TextSupport().SetText(string); + + if (energyLow) + CSfxManager::SfxStart(SFXui_energy_low, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + + x1c_27_energyLow = energyLow; } -void CHudEnergyInterface::SetNumFilledEnergyTanks(int numTanksFilled) -{ - x14_numTanksFilled = numTanksFilled; - x24_meter_energytanks->SetCurrValue(numTanksFilled); +void CHudEnergyInterface::SetFlashMagnitude(float mag) { x8_flashMag = zeus::clamp(0.f, mag, 1.f); } + +void CHudEnergyInterface::SetNumFilledEnergyTanks(int numTanksFilled) { + x14_numTanksFilled = numTanksFilled; + x24_meter_energytanks->SetCurrValue(numTanksFilled); } -void CHudEnergyInterface::SetNumTotalEnergyTanks(int totalEnergyTanks) -{ - x10_totalEnergyTanks = totalEnergyTanks; - x24_meter_energytanks->SetCapacity(totalEnergyTanks); +void CHudEnergyInterface::SetNumTotalEnergyTanks(int totalEnergyTanks) { + x10_totalEnergyTanks = totalEnergyTanks; + x24_meter_energytanks->SetCapacity(totalEnergyTanks); } -void CHudEnergyInterface::SetCurrEnergy(float tankEnergy, bool wrapped) -{ - xc_tankEnergy = tankEnergy; - x2c_energybart01_energybar->SetCurrEnergy(tankEnergy, - tankEnergy == 0.f ? CAuiEnergyBarT01::ESetMode::Insta : CAuiEnergyBarT01::ESetMode(wrapped)); +void CHudEnergyInterface::SetCurrEnergy(float tankEnergy, bool wrapped) { + xc_tankEnergy = tankEnergy; + x2c_energybart01_energybar->SetCurrEnergy(tankEnergy, tankEnergy == 0.f ? CAuiEnergyBarT01::ESetMode::Insta + : CAuiEnergyBarT01::ESetMode(wrapped)); } -std::pair CHudEnergyInterface::CombatEnergyCoordFunc(float t) -{ - float theta = 0.46764705f * t - 0.15882353f; - float x = 17.f * std::sin(theta); - float y = 17.f * std::cos(theta) - 17.f; - return {zeus::CVector3f(x, y, 0.4f), zeus::CVector3f(x, y, 0.f)}; +std::pair CHudEnergyInterface::CombatEnergyCoordFunc(float t) { + float theta = 0.46764705f * t - 0.15882353f; + float x = 17.f * std::sin(theta); + float y = 17.f * std::cos(theta) - 17.f; + return {zeus::CVector3f(x, y, 0.4f), zeus::CVector3f(x, y, 0.f)}; } -std::pair CHudEnergyInterface::XRayEnergyCoordFunc(float t) -{ - float theta = 1.8207964f - 0.69f * t; - float x = std::cos(theta); - float z = std::sin(theta); - return {zeus::CVector3f(9.4f * x, 0.f, 9.4f * z), zeus::CVector3f(9.f * x, 0.f, 9.f * z)}; +std::pair CHudEnergyInterface::XRayEnergyCoordFunc(float t) { + float theta = 1.8207964f - 0.69f * t; + float x = std::cos(theta); + float z = std::sin(theta); + return {zeus::CVector3f(9.4f * x, 0.f, 9.4f * z), zeus::CVector3f(9.f * x, 0.f, 9.f * z)}; } -std::pair CHudEnergyInterface::ThermalEnergyCoordFunc(float t) -{ - float x = 8.1663399f * t; - return {zeus::CVector3f(x, 0.f, 0.f), zeus::CVector3f(x, 0.f, 0.4355512f)}; +std::pair CHudEnergyInterface::ThermalEnergyCoordFunc(float t) { + float x = 8.1663399f * t; + return {zeus::CVector3f(x, 0.f, 0.f), zeus::CVector3f(x, 0.f, 0.4355512f)}; } -std::pair CHudEnergyInterface::BallEnergyCoordFunc(float t) -{ - float x = 1.6666f * t; - return {zeus::CVector3f(x, 0.f, 0.f), zeus::CVector3f(x, 0.f, 0.088887997f)}; +std::pair CHudEnergyInterface::BallEnergyCoordFunc(float t) { + float x = 1.6666f * t; + return {zeus::CVector3f(x, 0.f, 0.f), zeus::CVector3f(x, 0.f, 0.088887997f)}; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CHudEnergyInterface.hpp b/Runtime/GuiSys/CHudEnergyInterface.hpp index feb21d7be..bca5d08f3 100644 --- a/Runtime/GuiSys/CHudEnergyInterface.hpp +++ b/Runtime/GuiSys/CHudEnergyInterface.hpp @@ -4,52 +4,48 @@ #include "CHudInterface.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; class CGuiWidget; class CGuiTextPane; class CAuiMeter; class CAuiEnergyBarT01; -class CHudEnergyInterface -{ - EHudType x0_hudType; - float x4_energyLowFader = 0.f; - float x8_flashMag = 0.f; - float xc_tankEnergy; - int x10_totalEnergyTanks; - int x14_numTanksFilled; - float x18_cachedBarEnergy = 0.f; - union - { - struct - { - bool x1c_24_ : 1; - bool x1c_25_ : 1; - bool x1c_26_barDirty : 1; - bool x1c_27_energyLow : 1; - }; - u16 _dummy = 0; +class CHudEnergyInterface { + EHudType x0_hudType; + float x4_energyLowFader = 0.f; + float x8_flashMag = 0.f; + float xc_tankEnergy; + int x10_totalEnergyTanks; + int x14_numTanksFilled; + float x18_cachedBarEnergy = 0.f; + union { + struct { + bool x1c_24_ : 1; + bool x1c_25_ : 1; + bool x1c_26_barDirty : 1; + bool x1c_27_energyLow : 1; }; - CGuiTextPane* x20_textpane_energydigits; - CAuiMeter* x24_meter_energytanks; - CGuiTextPane* x28_textpane_energywarning; - CAuiEnergyBarT01* x2c_energybart01_energybar; + u16 _dummy = 0; + }; + CGuiTextPane* x20_textpane_energydigits; + CAuiMeter* x24_meter_energytanks; + CGuiTextPane* x28_textpane_energywarning; + CAuiEnergyBarT01* x2c_energybart01_energybar; + public: - CHudEnergyInterface(CGuiFrame& selHud, float tankEnergy, int totalEnergyTanks, - int numTanksFilled, bool energyLow, EHudType hudType); - void Update(float dt, float energyLowPulse); - void SetEnergyLow(bool energyLow); - void SetFlashMagnitude(float mag); - void SetNumFilledEnergyTanks(int numTanksFilled); - void SetNumTotalEnergyTanks(int totalEnergyTanks); - void SetCurrEnergy(float tankEnergy, bool wrapped); - static std::pair CombatEnergyCoordFunc(float t); - static std::pair XRayEnergyCoordFunc(float t); - static std::pair ThermalEnergyCoordFunc(float t); - static std::pair BallEnergyCoordFunc(float t); + CHudEnergyInterface(CGuiFrame& selHud, float tankEnergy, int totalEnergyTanks, int numTanksFilled, bool energyLow, + EHudType hudType); + void Update(float dt, float energyLowPulse); + void SetEnergyLow(bool energyLow); + void SetFlashMagnitude(float mag); + void SetNumFilledEnergyTanks(int numTanksFilled); + void SetNumTotalEnergyTanks(int totalEnergyTanks); + void SetCurrEnergy(float tankEnergy, bool wrapped); + static std::pair CombatEnergyCoordFunc(float t); + static std::pair XRayEnergyCoordFunc(float t); + static std::pair ThermalEnergyCoordFunc(float t); + static std::pair BallEnergyCoordFunc(float t); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudFreeLookInterface.cpp b/Runtime/GuiSys/CHudFreeLookInterface.cpp index 2749c0c1f..11863d7dc 100644 --- a/Runtime/GuiSys/CHudFreeLookInterface.cpp +++ b/Runtime/GuiSys/CHudFreeLookInterface.cpp @@ -3,170 +3,152 @@ #include "CGuiModel.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { -CHudFreeLookInterface::CHudFreeLookInterface(CGuiFrame& selHud, EHudType hudType, bool inFreeLook, - bool lookControlHeld, bool lockedOnObj) -: x4_hudType(hudType) -{ - x70_24_inFreeLook = inFreeLook; - x70_25_lookControlHeld = lookControlHeld; - x70_26_lockedOnObj = lockedOnObj; - x70_27_visibleDebug = true; - x70_28_visibleGame = true; - x6c_lockOnInterp = (lockedOnObj && hudType == EHudType::Scan) ? 0.f : 1.f; +CHudFreeLookInterface::CHudFreeLookInterface(CGuiFrame& selHud, EHudType hudType, bool inFreeLook, bool lookControlHeld, + bool lockedOnObj) +: x4_hudType(hudType) { + x70_24_inFreeLook = inFreeLook; + x70_25_lookControlHeld = lookControlHeld; + x70_26_lockedOnObj = lockedOnObj; + x70_27_visibleDebug = true; + x70_28_visibleGame = true; + x6c_lockOnInterp = (lockedOnObj && hudType == EHudType::Scan) ? 0.f : 1.f; - x74_basewidget_freelookleft = selHud.FindWidget("basewidget_freelookleft"); - x78_model_shieldleft = static_cast(selHud.FindWidget("model_shieldleft")); - x7c_model_freelookleft = static_cast(selHud.FindWidget("model_freelookleft")); - x80_basewidget_freelookright = selHud.FindWidget("basewidget_freelookright"); - x84_model_shieldright = static_cast(selHud.FindWidget("model_shieldright")); - x88_model_freelookright = static_cast(selHud.FindWidget("model_freelookright")); - x8c_basewidget_outlinesb = selHud.FindWidget("basewidget_outlinesb"); + x74_basewidget_freelookleft = selHud.FindWidget("basewidget_freelookleft"); + x78_model_shieldleft = static_cast(selHud.FindWidget("model_shieldleft")); + x7c_model_freelookleft = static_cast(selHud.FindWidget("model_freelookleft")); + x80_basewidget_freelookright = selHud.FindWidget("basewidget_freelookright"); + x84_model_shieldright = static_cast(selHud.FindWidget("model_shieldright")); + x88_model_freelookright = static_cast(selHud.FindWidget("model_freelookright")); + x8c_basewidget_outlinesb = selHud.FindWidget("basewidget_outlinesb"); - x8_freeLookLeftXf = x7c_model_freelookleft->GetTransform(); - x38_freeLookRightXf = x88_model_freelookright->GetTransform(); + x8_freeLookLeftXf = x7c_model_freelookleft->GetTransform(); + x38_freeLookRightXf = x88_model_freelookright->GetTransform(); - x78_model_shieldleft->SetDepthWrite(true); - x84_model_shieldright->SetDepthWrite(true); + x78_model_shieldleft->SetDepthWrite(true); + x84_model_shieldright->SetDepthWrite(true); } -void CHudFreeLookInterface::Update(float dt) -{ - if (x70_24_inFreeLook) - x68_freeLookInterp = std::min(x68_freeLookInterp + dt / g_tweakGui->GetFreeLookFadeTime(), 1.f); - else - x68_freeLookInterp = std::max(0.f, x68_freeLookInterp - dt / g_tweakGui->GetFreeLookFadeTime()); +void CHudFreeLookInterface::Update(float dt) { + if (x70_24_inFreeLook) + x68_freeLookInterp = std::min(x68_freeLookInterp + dt / g_tweakGui->GetFreeLookFadeTime(), 1.f); + else + x68_freeLookInterp = std::max(0.f, x68_freeLookInterp - dt / g_tweakGui->GetFreeLookFadeTime()); - if (x70_26_lockedOnObj && x4_hudType == EHudType::Scan) - x6c_lockOnInterp = std::min(x6c_lockOnInterp + 2.f * dt, 1.f); - else - x6c_lockOnInterp = std::max(0.f, x6c_lockOnInterp - 2.f * dt); + if (x70_26_lockedOnObj && x4_hudType == EHudType::Scan) + x6c_lockOnInterp = std::min(x6c_lockOnInterp + 2.f * dt, 1.f); + else + x6c_lockOnInterp = std::max(0.f, x6c_lockOnInterp - 2.f * dt); } -void CHudFreeLookInterface::SetIsVisibleDebug(bool v) -{ - x70_27_visibleDebug = v; - UpdateVisibility(); +void CHudFreeLookInterface::SetIsVisibleDebug(bool v) { + x70_27_visibleDebug = v; + UpdateVisibility(); } -void CHudFreeLookInterface::SetIsVisibleGame(bool v) -{ - x70_28_visibleGame = v; - UpdateVisibility(); +void CHudFreeLookInterface::SetIsVisibleGame(bool v) { + x70_28_visibleGame = v; + UpdateVisibility(); } -void CHudFreeLookInterface::UpdateVisibility() -{ - bool vis = x70_27_visibleDebug && x70_28_visibleGame; - x74_basewidget_freelookleft->SetVisibility(vis, ETraversalMode::Children); - x80_basewidget_freelookright->SetVisibility(vis, ETraversalMode::Children); - if (vis) - Update(0.f); +void CHudFreeLookInterface::UpdateVisibility() { + bool vis = x70_27_visibleDebug && x70_28_visibleGame; + x74_basewidget_freelookleft->SetVisibility(vis, ETraversalMode::Children); + x80_basewidget_freelookright->SetVisibility(vis, ETraversalMode::Children); + if (vis) + Update(0.f); } -void CHudFreeLookInterface::SetFreeLookState(bool inFreeLook, bool lookControlHeld, - bool lockedOnObj, float vertLookAngle) -{ - x70_24_inFreeLook = inFreeLook; - vertLookAngle *= 8.f; - x70_25_lookControlHeld = lookControlHeld; - x70_26_lockedOnObj = lockedOnObj; +void CHudFreeLookInterface::SetFreeLookState(bool inFreeLook, bool lookControlHeld, bool lockedOnObj, + float vertLookAngle) { + x70_24_inFreeLook = inFreeLook; + vertLookAngle *= 8.f; + x70_25_lookControlHeld = lookControlHeld; + x70_26_lockedOnObj = lockedOnObj; - x7c_model_freelookleft->SetLocalTransform( - x8_freeLookLeftXf * zeus::CTransform::Translate(0.f, 0.f, vertLookAngle)); + x7c_model_freelookleft->SetLocalTransform(x8_freeLookLeftXf * zeus::CTransform::Translate(0.f, 0.f, vertLookAngle)); - x88_model_freelookright->SetLocalTransform( - x38_freeLookRightXf * zeus::CTransform::Translate(0.f, 0.f, vertLookAngle)); + x88_model_freelookright->SetLocalTransform(x38_freeLookRightXf * + zeus::CTransform::Translate(0.f, 0.f, vertLookAngle)); - zeus::CColor color = zeus::CColor::skWhite; - float totalInterp = x68_freeLookInterp * (1.f - x6c_lockOnInterp); - color.a() = totalInterp; - x74_basewidget_freelookleft->SetColor(color); - x80_basewidget_freelookright->SetColor(color); + zeus::CColor color = zeus::CColor::skWhite; + float totalInterp = x68_freeLookInterp * (1.f - x6c_lockOnInterp); + color.a() = totalInterp; + x74_basewidget_freelookleft->SetColor(color); + x80_basewidget_freelookright->SetColor(color); - if (x8c_basewidget_outlinesb) - { - color.a() = 0.7f * totalInterp + 0.3f; - x8c_basewidget_outlinesb->SetColor(color); - } + if (x8c_basewidget_outlinesb) { + color.a() = 0.7f * totalInterp + 0.3f; + x8c_basewidget_outlinesb->SetColor(color); + } - if (totalInterp == 0.f) - { - x74_basewidget_freelookleft->SetVisibility(false, ETraversalMode::Children); - x80_basewidget_freelookright->SetVisibility(false, ETraversalMode::Children); - } - else - { - x74_basewidget_freelookleft->SetVisibility(true, ETraversalMode::Children); - x80_basewidget_freelookright->SetVisibility(true, ETraversalMode::Children); - } + if (totalInterp == 0.f) { + x74_basewidget_freelookleft->SetVisibility(false, ETraversalMode::Children); + x80_basewidget_freelookright->SetVisibility(false, ETraversalMode::Children); + } else { + x74_basewidget_freelookleft->SetVisibility(true, ETraversalMode::Children); + x80_basewidget_freelookright->SetVisibility(true, ETraversalMode::Children); + } } -CHudFreeLookInterfaceXRay::CHudFreeLookInterfaceXRay(CGuiFrame& selHud, bool inFreeLook, - bool lookControlHeld, bool lockedOnObj) -{ - x20_inFreeLook = inFreeLook; - x21_lookControlHeld = lookControlHeld; - x22_24_visibleDebug = true; - x22_25_visibleGame = true; - x24_basewidget_freelook = selHud.FindWidget("basewidget_freelook"); - x28_model_shield = static_cast(selHud.FindWidget("model_shield")); - x2c_model_freelookleft = static_cast(selHud.FindWidget("model_freelookleft")); - x30_model_freelookright = static_cast(selHud.FindWidget("model_freelookright")); +CHudFreeLookInterfaceXRay::CHudFreeLookInterfaceXRay(CGuiFrame& selHud, bool inFreeLook, bool lookControlHeld, + bool lockedOnObj) { + x20_inFreeLook = inFreeLook; + x21_lookControlHeld = lookControlHeld; + x22_24_visibleDebug = true; + x22_25_visibleGame = true; + x24_basewidget_freelook = selHud.FindWidget("basewidget_freelook"); + x28_model_shield = static_cast(selHud.FindWidget("model_shield")); + x2c_model_freelookleft = static_cast(selHud.FindWidget("model_freelookleft")); + x30_model_freelookright = static_cast(selHud.FindWidget("model_freelookright")); - x4_freeLookLeftPos = x2c_model_freelookleft->GetLocalPosition(); - x10_freeLookRightPos = x30_model_freelookright->GetLocalPosition(); + x4_freeLookLeftPos = x2c_model_freelookleft->GetLocalPosition(); + x10_freeLookRightPos = x30_model_freelookright->GetLocalPosition(); - x28_model_shield->SetDepthWrite(true); + x28_model_shield->SetDepthWrite(true); } -void CHudFreeLookInterfaceXRay::Update(float dt) -{ - if (x20_inFreeLook) - x1c_freeLookInterp = std::min(x1c_freeLookInterp + dt / g_tweakGui->GetFreeLookFadeTime(), 1.f); - else - x1c_freeLookInterp = std::max(0.f, x1c_freeLookInterp - dt / g_tweakGui->GetFreeLookFadeTime()); +void CHudFreeLookInterfaceXRay::Update(float dt) { + if (x20_inFreeLook) + x1c_freeLookInterp = std::min(x1c_freeLookInterp + dt / g_tweakGui->GetFreeLookFadeTime(), 1.f); + else + x1c_freeLookInterp = std::max(0.f, x1c_freeLookInterp - dt / g_tweakGui->GetFreeLookFadeTime()); } -void CHudFreeLookInterfaceXRay::UpdateVisibility() -{ - bool vis = x22_24_visibleDebug && x22_25_visibleGame; - x2c_model_freelookleft->SetVisibility(vis, ETraversalMode::Children); - x30_model_freelookright->SetVisibility(vis, ETraversalMode::Children); - if (vis) - Update(0.f); +void CHudFreeLookInterfaceXRay::UpdateVisibility() { + bool vis = x22_24_visibleDebug && x22_25_visibleGame; + x2c_model_freelookleft->SetVisibility(vis, ETraversalMode::Children); + x30_model_freelookright->SetVisibility(vis, ETraversalMode::Children); + if (vis) + Update(0.f); } -void CHudFreeLookInterfaceXRay::SetIsVisibleDebug(bool v) -{ - x22_24_visibleDebug = v; - UpdateVisibility(); +void CHudFreeLookInterfaceXRay::SetIsVisibleDebug(bool v) { + x22_24_visibleDebug = v; + UpdateVisibility(); } -void CHudFreeLookInterfaceXRay::SetIsVisibleGame(bool v) -{ - x22_25_visibleGame = v; - UpdateVisibility(); +void CHudFreeLookInterfaceXRay::SetIsVisibleGame(bool v) { + x22_25_visibleGame = v; + UpdateVisibility(); } -void CHudFreeLookInterfaceXRay::SetFreeLookState(bool inFreeLook, bool lookControlHeld, - bool lockedOnObj, float vertLookAngle) -{ - x2c_model_freelookleft->SetLocalTransform( - zeus::CTransform(zeus::CMatrix3f::RotateY(vertLookAngle), x4_freeLookLeftPos)); - x30_model_freelookright->SetLocalTransform( - zeus::CTransform(zeus::CMatrix3f::RotateY(-vertLookAngle), x10_freeLookRightPos)); +void CHudFreeLookInterfaceXRay::SetFreeLookState(bool inFreeLook, bool lookControlHeld, bool lockedOnObj, + float vertLookAngle) { + x2c_model_freelookleft->SetLocalTransform( + zeus::CTransform(zeus::CMatrix3f::RotateY(vertLookAngle), x4_freeLookLeftPos)); + x30_model_freelookright->SetLocalTransform( + zeus::CTransform(zeus::CMatrix3f::RotateY(-vertLookAngle), x10_freeLookRightPos)); - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x1c_freeLookInterp; - x24_basewidget_freelook->SetColor(color); + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x1c_freeLookInterp; + x24_basewidget_freelook->SetColor(color); - if (x1c_freeLookInterp == 0.f) - x24_basewidget_freelook->SetVisibility(false, ETraversalMode::Children); - else - x24_basewidget_freelook->SetVisibility(true, ETraversalMode::Children); + if (x1c_freeLookInterp == 0.f) + x24_basewidget_freelook->SetVisibility(false, ETraversalMode::Children); + else + x24_basewidget_freelook->SetVisibility(true, ETraversalMode::Children); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CHudFreeLookInterface.hpp b/Runtime/GuiSys/CHudFreeLookInterface.hpp index 1969a4d86..562ed710a 100644 --- a/Runtime/GuiSys/CHudFreeLookInterface.hpp +++ b/Runtime/GuiSys/CHudFreeLookInterface.hpp @@ -4,83 +4,73 @@ #include "CHudInterface.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; class CGuiWidget; class CGuiModel; -class IFreeLookInterface -{ +class IFreeLookInterface { public: - virtual ~IFreeLookInterface() = default; - virtual void Update(float dt)=0; - virtual void SetIsVisibleDebug(bool v)=0; - virtual void SetIsVisibleGame(bool v)=0; - virtual void SetFreeLookState(bool inFreeLook, bool lookControlHeld, - bool lockedOnObj, float vertLookAngle)=0; + virtual ~IFreeLookInterface() = default; + virtual void Update(float dt) = 0; + virtual void SetIsVisibleDebug(bool v) = 0; + virtual void SetIsVisibleGame(bool v) = 0; + virtual void SetFreeLookState(bool inFreeLook, bool lookControlHeld, bool lockedOnObj, float vertLookAngle) = 0; }; -class CHudFreeLookInterface : public IFreeLookInterface -{ - EHudType x4_hudType; - zeus::CTransform x8_freeLookLeftXf; - zeus::CTransform x38_freeLookRightXf; - float x68_freeLookInterp = 0.f; - float x6c_lockOnInterp; - union - { - struct - { - bool x70_24_inFreeLook : 1; - bool x70_25_lookControlHeld : 1; - bool x70_26_lockedOnObj : 1; - bool x70_27_visibleDebug : 1; - bool x70_28_visibleGame : 1; - }; - u16 _dummy = 0; +class CHudFreeLookInterface : public IFreeLookInterface { + EHudType x4_hudType; + zeus::CTransform x8_freeLookLeftXf; + zeus::CTransform x38_freeLookRightXf; + float x68_freeLookInterp = 0.f; + float x6c_lockOnInterp; + union { + struct { + bool x70_24_inFreeLook : 1; + bool x70_25_lookControlHeld : 1; + bool x70_26_lockedOnObj : 1; + bool x70_27_visibleDebug : 1; + bool x70_28_visibleGame : 1; }; - CGuiWidget* x74_basewidget_freelookleft; - CGuiModel* x78_model_shieldleft; - CGuiModel* x7c_model_freelookleft; - CGuiWidget* x80_basewidget_freelookright; - CGuiModel* x84_model_shieldright; - CGuiModel* x88_model_freelookright; - CGuiWidget* x8c_basewidget_outlinesb; - void UpdateVisibility(); + u16 _dummy = 0; + }; + CGuiWidget* x74_basewidget_freelookleft; + CGuiModel* x78_model_shieldleft; + CGuiModel* x7c_model_freelookleft; + CGuiWidget* x80_basewidget_freelookright; + CGuiModel* x84_model_shieldright; + CGuiModel* x88_model_freelookright; + CGuiWidget* x8c_basewidget_outlinesb; + void UpdateVisibility(); + public: - CHudFreeLookInterface(CGuiFrame& selHud, EHudType hudType, bool inFreeLook, - bool lookControlHeld, bool lockedOnObj); - void Update(float dt); - void SetIsVisibleDebug(bool v); - void SetIsVisibleGame(bool v); - void SetFreeLookState(bool inFreeLook, bool lookControlHeld, - bool lockedOnObj, float vertLookAngle); + CHudFreeLookInterface(CGuiFrame& selHud, EHudType hudType, bool inFreeLook, bool lookControlHeld, bool lockedOnObj); + void Update(float dt); + void SetIsVisibleDebug(bool v); + void SetIsVisibleGame(bool v); + void SetFreeLookState(bool inFreeLook, bool lookControlHeld, bool lockedOnObj, float vertLookAngle); }; -class CHudFreeLookInterfaceXRay : public IFreeLookInterface -{ - zeus::CVector3f x4_freeLookLeftPos; - zeus::CVector3f x10_freeLookRightPos; - float x1c_freeLookInterp = 0.f; - bool x20_inFreeLook; - bool x21_lookControlHeld; - bool x22_24_visibleDebug : 1; - bool x22_25_visibleGame : 1; - CGuiWidget* x24_basewidget_freelook; - CGuiModel* x28_model_shield; - CGuiModel* x2c_model_freelookleft; - CGuiModel* x30_model_freelookright; - void UpdateVisibility(); +class CHudFreeLookInterfaceXRay : public IFreeLookInterface { + zeus::CVector3f x4_freeLookLeftPos; + zeus::CVector3f x10_freeLookRightPos; + float x1c_freeLookInterp = 0.f; + bool x20_inFreeLook; + bool x21_lookControlHeld; + bool x22_24_visibleDebug : 1; + bool x22_25_visibleGame : 1; + CGuiWidget* x24_basewidget_freelook; + CGuiModel* x28_model_shield; + CGuiModel* x2c_model_freelookleft; + CGuiModel* x30_model_freelookright; + void UpdateVisibility(); + public: - CHudFreeLookInterfaceXRay(CGuiFrame& selHud, bool inFreeLook, - bool lookControlHeld, bool lockedOnObj); - void Update(float dt); - void SetIsVisibleDebug(bool v); - void SetIsVisibleGame(bool v); - void SetFreeLookState(bool inFreeLook, bool lookControlHeld, - bool lockedOnObj, float vertLookAngle); + CHudFreeLookInterfaceXRay(CGuiFrame& selHud, bool inFreeLook, bool lookControlHeld, bool lockedOnObj); + void Update(float dt); + void SetIsVisibleDebug(bool v); + void SetIsVisibleGame(bool v); + void SetFreeLookState(bool inFreeLook, bool lookControlHeld, bool lockedOnObj, float vertLookAngle); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudHelmetInterface.cpp b/Runtime/GuiSys/CHudHelmetInterface.cpp index f8be4eb01..5145c3552 100644 --- a/Runtime/GuiSys/CHudHelmetInterface.cpp +++ b/Runtime/GuiSys/CHudHelmetInterface.cpp @@ -4,74 +4,63 @@ #include "GameGlobalObjects.hpp" #include "CGameState.hpp" -namespace urde -{ +namespace urde { -CHudHelmetInterface::CHudHelmetInterface(CGuiFrame& helmetFrame) -{ - x3c_24_helmetVisibleDebug = true; - x3c_25_helmetVisibleGame = true; - x3c_26_glowVisibleDebug = true; - x3c_27_glowVisibleGame = true; - x40_camera = helmetFrame.GetFrameCamera(); - x44_BaseWidget_Pivot = helmetFrame.FindWidget("BaseWidget_Pivot"); - x48_BaseWidget_Helmet = helmetFrame.FindWidget("BaseWidget_Helmet"); - x4c_BaseWidget_Glow = helmetFrame.FindWidget("BaseWidget_Glow"); - x50_BaseWidget_HelmetLight = helmetFrame.FindWidget("BaseWidget_HelmetLight"); - x24_pivotPosition = x44_BaseWidget_Pivot->GetIdlePosition(); - x50_BaseWidget_HelmetLight->SetColor(g_tweakGuiColors->GetHelmetLightColor()); +CHudHelmetInterface::CHudHelmetInterface(CGuiFrame& helmetFrame) { + x3c_24_helmetVisibleDebug = true; + x3c_25_helmetVisibleGame = true; + x3c_26_glowVisibleDebug = true; + x3c_27_glowVisibleGame = true; + x40_camera = helmetFrame.GetFrameCamera(); + x44_BaseWidget_Pivot = helmetFrame.FindWidget("BaseWidget_Pivot"); + x48_BaseWidget_Helmet = helmetFrame.FindWidget("BaseWidget_Helmet"); + x4c_BaseWidget_Glow = helmetFrame.FindWidget("BaseWidget_Glow"); + x50_BaseWidget_HelmetLight = helmetFrame.FindWidget("BaseWidget_HelmetLight"); + x24_pivotPosition = x44_BaseWidget_Pivot->GetIdlePosition(); + x50_BaseWidget_HelmetLight->SetColor(g_tweakGuiColors->GetHelmetLightColor()); } -void CHudHelmetInterface::UpdateVisibility() -{ - x48_BaseWidget_Helmet->SetVisibility(x3c_24_helmetVisibleDebug && x3c_25_helmetVisibleGame, ETraversalMode::Children); - x4c_BaseWidget_Glow->SetVisibility(x3c_26_glowVisibleDebug && x3c_27_glowVisibleGame, ETraversalMode::Children); +void CHudHelmetInterface::UpdateVisibility() { + x48_BaseWidget_Helmet->SetVisibility(x3c_24_helmetVisibleDebug && x3c_25_helmetVisibleGame, ETraversalMode::Children); + x4c_BaseWidget_Glow->SetVisibility(x3c_26_glowVisibleDebug && x3c_27_glowVisibleGame, ETraversalMode::Children); } -void CHudHelmetInterface::Update(float dt) -{ - if (x3c_28_hudLagDirty) - { - x3c_28_hudLagDirty = false; - x44_BaseWidget_Pivot->SetTransform(zeus::CTransform(x0_hudLagRotation, x24_pivotPosition + x30_hudLagPosition)); - } +void CHudHelmetInterface::Update(float dt) { + if (x3c_28_hudLagDirty) { + x3c_28_hudLagDirty = false; + x44_BaseWidget_Pivot->SetTransform(zeus::CTransform(x0_hudLagRotation, x24_pivotPosition + x30_hudLagPosition)); + } } -void CHudHelmetInterface::SetHudLagOffset(const zeus::CVector3f& off) -{ - x30_hudLagPosition = off; - x3c_28_hudLagDirty = true; +void CHudHelmetInterface::SetHudLagOffset(const zeus::CVector3f& off) { + x30_hudLagPosition = off; + x3c_28_hudLagDirty = true; } -void CHudHelmetInterface::SetHudLagRotation(const zeus::CMatrix3f& rot) -{ - x0_hudLagRotation = rot; - x3c_28_hudLagDirty = true; +void CHudHelmetInterface::SetHudLagRotation(const zeus::CMatrix3f& rot) { + x0_hudLagRotation = rot; + x3c_28_hudLagDirty = true; } -void CHudHelmetInterface::AddHelmetLightValue(float val) -{ - x50_BaseWidget_HelmetLight->SetColor(g_tweakGuiColors->GetHelmetLightColor() + zeus::CColor(val, val)); +void CHudHelmetInterface::AddHelmetLightValue(float val) { + x50_BaseWidget_HelmetLight->SetColor(g_tweakGuiColors->GetHelmetLightColor() + zeus::CColor(val, val)); } -void CHudHelmetInterface::UpdateCameraDebugSettings(float fov, float y, float z) -{ - x40_camera->SetFov(fov); - x40_camera->SetTransform(zeus::CTransform(x40_camera->GetTransform().buildMatrix3f(), zeus::CVector3f(0.f, y, z))); +void CHudHelmetInterface::UpdateCameraDebugSettings(float fov, float y, float z) { + x40_camera->SetFov(fov); + x40_camera->SetTransform(zeus::CTransform(x40_camera->GetTransform().buildMatrix3f(), zeus::CVector3f(0.f, y, z))); } -void CHudHelmetInterface::UpdateHelmetAlpha() -{ - zeus::CColor color = zeus::CColor::skWhite; - color.a() = g_GameState->GameOptions().GetHelmetAlpha() / 255.f; - x44_BaseWidget_Pivot->SetColor(color); +void CHudHelmetInterface::UpdateHelmetAlpha() { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = g_GameState->GameOptions().GetHelmetAlpha() / 255.f; + x44_BaseWidget_Pivot->SetColor(color); } -void CHudHelmetInterface::SetIsVisibleDebug(bool helmet, bool glow) -{ - x3c_24_helmetVisibleDebug = helmet; - x3c_26_glowVisibleDebug = glow; - UpdateVisibility(); +void CHudHelmetInterface::SetIsVisibleDebug(bool helmet, bool glow) { + x3c_24_helmetVisibleDebug = helmet; + x3c_26_glowVisibleDebug = glow; + UpdateVisibility(); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CHudHelmetInterface.hpp b/Runtime/GuiSys/CHudHelmetInterface.hpp index 492ad8015..a5892d2ea 100644 --- a/Runtime/GuiSys/CHudHelmetInterface.hpp +++ b/Runtime/GuiSys/CHudHelmetInterface.hpp @@ -3,45 +3,41 @@ #include "zeus/CMatrix3f.hpp" #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; class CGuiWidget; class CGuiCamera; -class CHudHelmetInterface -{ - zeus::CMatrix3f x0_hudLagRotation; - zeus::CVector3f x24_pivotPosition; - zeus::CVector3f x30_hudLagPosition; - union - { - struct - { - bool x3c_24_helmetVisibleDebug : 1; - bool x3c_25_helmetVisibleGame : 1; - bool x3c_26_glowVisibleDebug : 1; - bool x3c_27_glowVisibleGame : 1; - bool x3c_28_hudLagDirty : 1; - }; - u16 _dummy = 0; +class CHudHelmetInterface { + zeus::CMatrix3f x0_hudLagRotation; + zeus::CVector3f x24_pivotPosition; + zeus::CVector3f x30_hudLagPosition; + union { + struct { + bool x3c_24_helmetVisibleDebug : 1; + bool x3c_25_helmetVisibleGame : 1; + bool x3c_26_glowVisibleDebug : 1; + bool x3c_27_glowVisibleGame : 1; + bool x3c_28_hudLagDirty : 1; }; - CGuiCamera* x40_camera; - CGuiWidget* x44_BaseWidget_Pivot; - CGuiWidget* x48_BaseWidget_Helmet; - CGuiWidget* x4c_BaseWidget_Glow; - CGuiWidget* x50_BaseWidget_HelmetLight; - void UpdateVisibility(); + u16 _dummy = 0; + }; + CGuiCamera* x40_camera; + CGuiWidget* x44_BaseWidget_Pivot; + CGuiWidget* x48_BaseWidget_Helmet; + CGuiWidget* x4c_BaseWidget_Glow; + CGuiWidget* x50_BaseWidget_HelmetLight; + void UpdateVisibility(); + public: - CHudHelmetInterface(CGuiFrame& helmetFrame); - void Update(float dt); - void SetHudLagOffset(const zeus::CVector3f& off); - void SetHudLagRotation(const zeus::CMatrix3f& rot); - void AddHelmetLightValue(float val); - void UpdateCameraDebugSettings(float fov, float y, float z); - void UpdateHelmetAlpha(); - void SetIsVisibleDebug(bool helmet, bool glow); + CHudHelmetInterface(CGuiFrame& helmetFrame); + void Update(float dt); + void SetHudLagOffset(const zeus::CVector3f& off); + void SetHudLagRotation(const zeus::CMatrix3f& rot); + void AddHelmetLightValue(float val); + void UpdateCameraDebugSettings(float fov, float y, float z); + void UpdateHelmetAlpha(); + void SetIsVisibleDebug(bool helmet, bool glow); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudInterface.hpp b/Runtime/GuiSys/CHudInterface.hpp index 743df8490..411d717e9 100644 --- a/Runtime/GuiSys/CHudInterface.hpp +++ b/Runtime/GuiSys/CHudInterface.hpp @@ -1,16 +1,7 @@ #pragma once -namespace urde -{ +namespace urde { -enum class EHudType -{ - Combat, - Scan, - XRay, - Thermal, - Ball -}; +enum class EHudType { Combat, Scan, XRay, Thermal, Ball }; } - diff --git a/Runtime/GuiSys/CHudMissileInterface.cpp b/Runtime/GuiSys/CHudMissileInterface.cpp index d81879628..6713fc364 100644 --- a/Runtime/GuiSys/CHudMissileInterface.cpp +++ b/Runtime/GuiSys/CHudMissileInterface.cpp @@ -7,309 +7,257 @@ #include "CGuiModel.hpp" #include "CStringTable.hpp" -namespace urde -{ +namespace urde { -static const CAuiEnergyBarT01::FCoordFunc CoordFuncs[] = -{ - CHudMissileInterface::CombatMissileBarCoordFunc, - nullptr, - CHudMissileInterface::XRayMissileBarCoordFunc, - CHudMissileInterface::ThermalMissileBarCoordFunc, - nullptr -}; +static const CAuiEnergyBarT01::FCoordFunc CoordFuncs[] = {CHudMissileInterface::CombatMissileBarCoordFunc, nullptr, + CHudMissileInterface::XRayMissileBarCoordFunc, + CHudMissileInterface::ThermalMissileBarCoordFunc, nullptr}; -static const float IconTranslateRanges[] = -{ - 6.05f, 0.f, 0.f, 8.4f, 0.f -}; +static const float IconTranslateRanges[] = {6.05f, 0.f, 0.f, 8.4f, 0.f}; -CHudMissileInterface::CHudMissileInterface(CGuiFrame& selHud, int missileCapacity, int numMissiles, - float chargeFactor, bool missilesActive, EHudType hudType, - const CStateManager& mgr) -: x0_hudType(hudType), x4_missileCapacity(missileCapacity), - x8_numMissles(numMissiles), x4c_chargeBeamFactor(chargeFactor) -{ - x58_24_missilesActive = missilesActive; - x58_25_visibleDebug = true; - x58_26_visibleGame = true; +CHudMissileInterface::CHudMissileInterface(CGuiFrame& selHud, int missileCapacity, int numMissiles, float chargeFactor, + bool missilesActive, EHudType hudType, const CStateManager& mgr) +: x0_hudType(hudType) +, x4_missileCapacity(missileCapacity) +, x8_numMissles(numMissiles) +, x4c_chargeBeamFactor(chargeFactor) { + x58_24_missilesActive = missilesActive; + x58_25_visibleDebug = true; + x58_26_visibleGame = true; - x5c_basewidget_missileicon = selHud.FindWidget("basewidget_missileicon"); - x60_textpane_missiledigits = static_cast(selHud.FindWidget("textpane_missiledigits")); - x64_energybart01_missilebar = static_cast(selHud.FindWidget("energybart01_missilebar")); - x68_textpane_missilewarning = static_cast(selHud.FindWidget("textpane_missilewarning")); - x6c_model_missilearrowup = static_cast(selHud.FindWidget("model_missilearrowup")); - x70_model_missilearrowdown = static_cast(selHud.FindWidget("model_missilearrowdown")); - x74_basewidget_missileicon = selHud.FindWidget("basewidget_missileicon"); + x5c_basewidget_missileicon = selHud.FindWidget("basewidget_missileicon"); + x60_textpane_missiledigits = static_cast(selHud.FindWidget("textpane_missiledigits")); + x64_energybart01_missilebar = static_cast(selHud.FindWidget("energybart01_missilebar")); + x68_textpane_missilewarning = static_cast(selHud.FindWidget("textpane_missilewarning")); + x6c_model_missilearrowup = static_cast(selHud.FindWidget("model_missilearrowup")); + x70_model_missilearrowdown = static_cast(selHud.FindWidget("model_missilearrowdown")); + x74_basewidget_missileicon = selHud.FindWidget("basewidget_missileicon"); - x58_27_hasArrows = x6c_model_missilearrowup && x70_model_missilearrowdown; - x58_28_notXRay = hudType != EHudType::XRay; + x58_27_hasArrows = x6c_model_missilearrowup && x70_model_missilearrowdown; + x58_28_notXRay = hudType != EHudType::XRay; - x10_missleIconXf = x74_basewidget_missileicon->GetLocalTransform(); + x10_missleIconXf = x74_basewidget_missileicon->GetLocalTransform(); - x60_textpane_missiledigits->TextSupport().SetFontColor(g_tweakGuiColors->GetMissileDigitsFont()); - x60_textpane_missiledigits->TextSupport().SetOutlineColor(g_tweakGuiColors->GetMissileDigitsOutline()); - x74_basewidget_missileicon->SetColor(g_tweakGuiColors->GetMissileIconColorInactive()); - x64_energybart01_missilebar->SetEmptyColor(g_tweakGuiColors->GetMissileBarEmpty()); - x64_energybart01_missilebar->SetFilledColor(g_tweakGuiColors->GetMissileBarFilled()); - x64_energybart01_missilebar->SetShadowColor(g_tweakGuiColors->GetMissileBarShadow()); - x64_energybart01_missilebar->SetCoordFunc(CoordFuncs[int(hudType)]); - x64_energybart01_missilebar->SetTesselation(hudType == EHudType::Combat ? 1.f : 0.1f); - x64_energybart01_missilebar->SetMaxEnergy(5.f); - x64_energybart01_missilebar->SetFilledDrainSpeed(g_tweakGui->GetEnergyBarFilledSpeed()); - x64_energybart01_missilebar->SetShadowDrainSpeed(g_tweakGui->GetEnergyBarShadowSpeed()); - x64_energybart01_missilebar->SetShadowDrainDelay(g_tweakGui->GetEnergyBarDrainDelay()); - x64_energybart01_missilebar->SetIsAlwaysResetTimer(true); + x60_textpane_missiledigits->TextSupport().SetFontColor(g_tweakGuiColors->GetMissileDigitsFont()); + x60_textpane_missiledigits->TextSupport().SetOutlineColor(g_tweakGuiColors->GetMissileDigitsOutline()); + x74_basewidget_missileicon->SetColor(g_tweakGuiColors->GetMissileIconColorInactive()); + x64_energybart01_missilebar->SetEmptyColor(g_tweakGuiColors->GetMissileBarEmpty()); + x64_energybart01_missilebar->SetFilledColor(g_tweakGuiColors->GetMissileBarFilled()); + x64_energybart01_missilebar->SetShadowColor(g_tweakGuiColors->GetMissileBarShadow()); + x64_energybart01_missilebar->SetCoordFunc(CoordFuncs[int(hudType)]); + x64_energybart01_missilebar->SetTesselation(hudType == EHudType::Combat ? 1.f : 0.1f); + x64_energybart01_missilebar->SetMaxEnergy(5.f); + x64_energybart01_missilebar->SetFilledDrainSpeed(g_tweakGui->GetEnergyBarFilledSpeed()); + x64_energybart01_missilebar->SetShadowDrainSpeed(g_tweakGui->GetEnergyBarShadowSpeed()); + x64_energybart01_missilebar->SetShadowDrainDelay(g_tweakGui->GetEnergyBarDrainDelay()); + x64_energybart01_missilebar->SetIsAlwaysResetTimer(true); - if (x68_textpane_missilewarning) - { - x68_textpane_missilewarning->TextSupport().SetFontColor(g_tweakGuiColors->GetMissileWarningFont()); - x68_textpane_missilewarning->TextSupport().SetOutlineColor(g_tweakGuiColors->GetMissileWarningOutline()); + if (x68_textpane_missilewarning) { + x68_textpane_missilewarning->TextSupport().SetFontColor(g_tweakGuiColors->GetMissileWarningFont()); + x68_textpane_missilewarning->TextSupport().SetOutlineColor(g_tweakGuiColors->GetMissileWarningOutline()); + } + + SetNumMissiles(x8_numMissles, mgr); + x44_latestStatus = GetMissileInventoryStatus(); +} + +void CHudMissileInterface::UpdateVisibility(const CStateManager& mgr) { + bool vis = x58_25_visibleDebug && x58_26_visibleGame; + x5c_basewidget_missileicon->SetVisibility(vis, ETraversalMode::Children); + x64_energybart01_missilebar->SetVisibility(vis, ETraversalMode::Children); + if (vis) + Update(0.f, mgr); +} + +void CHudMissileInterface::Update(float dt, const CStateManager& mgr) { + if (x4_missileCapacity < 1) + x5c_basewidget_missileicon->SetIsVisible(false); + else + x5c_basewidget_missileicon->SetIsVisible(true); + + if (x54_missileIconIncrement < 0.f) { + x54_missileIconIncrement -= 3.f * dt; + if (x54_missileIconIncrement <= -1.f) + x54_missileIconIncrement = 1.f; + } else if (x54_missileIconIncrement > 0.f) { + x54_missileIconIncrement = std::max(0.f, x54_missileIconIncrement - dt); + } + + zeus::CColor addColor = g_tweakGuiColors->GetMissileIconColorActive() * x54_missileIconIncrement; + + if (x50_missileIconAltDeplete > 0.f) { + x74_basewidget_missileicon->SetColor(zeus::CColor::lerp(g_tweakGuiColors->GetMissileIconColorInactive(), + g_tweakGuiColors->GetMissileIconColorDepleteAlt(), + x50_missileIconAltDeplete) + + addColor); + } else { + if (x4c_chargeBeamFactor > 0.f) { + float factor = std::min(x4c_chargeBeamFactor / CPlayerState::GetMissileComboChargeFactor(), 1.f); + if (x8_numMissles > mgr.GetPlayerState()->GetMissileCostForAltAttack()) { + x74_basewidget_missileicon->SetColor(zeus::CColor::lerp(g_tweakGuiColors->GetMissileIconColorInactive(), + g_tweakGuiColors->GetMissileIconColorChargedCanAlt(), + factor) + + addColor); + } else { + x74_basewidget_missileicon->SetColor(zeus::CColor::lerp(g_tweakGuiColors->GetMissileIconColorInactive(), + g_tweakGuiColors->GetMissileIconColorChargedNoAlt(), + factor) + + addColor); + } + } else { + if (x58_24_missilesActive) + x74_basewidget_missileicon->SetColor(g_tweakGuiColors->GetMissileIconColorActive() + addColor); + else + x74_basewidget_missileicon->SetColor(g_tweakGuiColors->GetMissileIconColorInactive() + addColor); + } + } + + x50_missileIconAltDeplete = std::max(0.f, x50_missileIconAltDeplete - dt); + + x64_energybart01_missilebar->SetMaxEnergy(x4_missileCapacity); + x64_energybart01_missilebar->SetCurrEnergy(x8_numMissles, CAuiEnergyBarT01::ESetMode::Normal); + + if (x58_28_notXRay) { + x74_basewidget_missileicon->SetLocalTransform( + x10_missleIconXf * + zeus::CTransform::Translate(0.f, 0.f, + x8_numMissles * IconTranslateRanges[int(x0_hudType)] / float(x4_missileCapacity))); + } + + if (x58_27_hasArrows) { + if (xc_arrowTimer > 0.f) { + xc_arrowTimer = std::max(0.f, xc_arrowTimer - dt); + zeus::CColor color = g_tweakGuiColors->GetMissileIconColorActive(); + color.a() *= xc_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); + x6c_model_missilearrowup->SetColor(color); + x70_model_missilearrowdown->SetIsVisible(false); + } else if (xc_arrowTimer < 0.f) { + xc_arrowTimer = std::min(0.f, xc_arrowTimer + dt); + zeus::CColor color = g_tweakGuiColors->GetMissileIconColorActive(); + color.a() *= -xc_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); + x70_model_missilearrowdown->SetColor(color); + x6c_model_missilearrowup->SetIsVisible(false); + } else { + x6c_model_missilearrowup->SetIsVisible(false); + x70_model_missilearrowdown->SetIsVisible(false); + } + } + + if (x68_textpane_missilewarning) { + EInventoryStatus curStatus = GetMissileInventoryStatus(); + if (curStatus != x44_latestStatus) { + std::u16string string; + switch (curStatus) { + case EInventoryStatus::Warning: + string = g_MainStringTable->GetString(12); // Missiles Low + break; + case EInventoryStatus::Depleted: + string = g_MainStringTable->GetString(13); // Depleted + default: + break; + } + x68_textpane_missilewarning->TextSupport().SetText(string); + + if (x44_latestStatus == EInventoryStatus::Normal && curStatus == EInventoryStatus::Warning) { + CSfxManager::SfxStart(SFXui_missile_warning, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x48_missileWarningPulse = g_tweakGui->GetMissileWarningPulseTime(); + } else if (curStatus == EInventoryStatus::Depleted) { + CSfxManager::SfxStart(SFXui_missile_warning, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x48_missileWarningPulse = g_tweakGui->GetMissileWarningPulseTime(); + } + + x44_latestStatus = curStatus; } - SetNumMissiles(x8_numMissles, mgr); - x44_latestStatus = GetMissileInventoryStatus(); -} + x48_missileWarningPulse = std::max(0.f, x48_missileWarningPulse - dt); + float warnPulse = std::min(x48_missileWarningPulse, 1.f); -void CHudMissileInterface::UpdateVisibility(const CStateManager& mgr) -{ - bool vis = x58_25_visibleDebug && x58_26_visibleGame; - x5c_basewidget_missileicon->SetVisibility(vis, ETraversalMode::Children); - x64_energybart01_missilebar->SetVisibility(vis, ETraversalMode::Children); - if (vis) - Update(0.f, mgr); -} - -void CHudMissileInterface::Update(float dt, const CStateManager& mgr) -{ - if (x4_missileCapacity < 1) - x5c_basewidget_missileicon->SetIsVisible(false); + if (x44_latestStatus != EInventoryStatus::Normal) + x40_missileWarningAlpha = std::min(x40_missileWarningAlpha + 2.f * dt, 1.f); else - x5c_basewidget_missileicon->SetIsVisible(true); + x40_missileWarningAlpha = std::max(0.f, x40_missileWarningAlpha - 2.f * dt); - if (x54_missileIconIncrement < 0.f) - { - x54_missileIconIncrement -= 3.f * dt; - if (x54_missileIconIncrement <= -1.f) - x54_missileIconIncrement = 1.f; - } - else if (x54_missileIconIncrement > 0.f) - { - x54_missileIconIncrement = std::max(0.f, x54_missileIconIncrement - dt); - } - - zeus::CColor addColor = g_tweakGuiColors->GetMissileIconColorActive() * x54_missileIconIncrement; - - if (x50_missileIconAltDeplete > 0.f) - { - x74_basewidget_missileicon->SetColor( - zeus::CColor::lerp(g_tweakGuiColors->GetMissileIconColorInactive(), - g_tweakGuiColors->GetMissileIconColorDepleteAlt(), x50_missileIconAltDeplete) + addColor); - } + float tmp = std::fabs(std::fmod(CGraphics::GetSecondsMod900(), 0.5f)); + if (tmp < 0.25f) + tmp = tmp / 0.25f; else - { - if (x4c_chargeBeamFactor > 0.f) - { - float factor = std::min(x4c_chargeBeamFactor / CPlayerState::GetMissileComboChargeFactor(), 1.f); - if (x8_numMissles > mgr.GetPlayerState()->GetMissileCostForAltAttack()) - { - x74_basewidget_missileicon->SetColor( - zeus::CColor::lerp(g_tweakGuiColors->GetMissileIconColorInactive(), - g_tweakGuiColors->GetMissileIconColorChargedCanAlt(), factor) + addColor); - } - else - { - x74_basewidget_missileicon->SetColor( - zeus::CColor::lerp(g_tweakGuiColors->GetMissileIconColorInactive(), - g_tweakGuiColors->GetMissileIconColorChargedNoAlt(), factor) + addColor); - } - } - else - { - if (x58_24_missilesActive) - x74_basewidget_missileicon->SetColor(g_tweakGuiColors->GetMissileIconColorActive() + addColor); - else - x74_basewidget_missileicon->SetColor(g_tweakGuiColors->GetMissileIconColorInactive() + addColor); - } - } + tmp = (0.5f - tmp) / 0.25f; - x50_missileIconAltDeplete = std::max(0.f, x50_missileIconAltDeplete - dt); - - x64_energybart01_missilebar->SetMaxEnergy(x4_missileCapacity); - x64_energybart01_missilebar->SetCurrEnergy(x8_numMissles, CAuiEnergyBarT01::ESetMode::Normal); - - if (x58_28_notXRay) - { - x74_basewidget_missileicon->SetLocalTransform(x10_missleIconXf * - zeus::CTransform::Translate(0.f, 0.f, x8_numMissles * - IconTranslateRanges[int(x0_hudType)] / float(x4_missileCapacity))); - } - - if (x58_27_hasArrows) - { - if (xc_arrowTimer > 0.f) - { - xc_arrowTimer = std::max(0.f, xc_arrowTimer - dt); - zeus::CColor color = g_tweakGuiColors->GetMissileIconColorActive(); - color.a() *= xc_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); - x6c_model_missilearrowup->SetColor(color); - x70_model_missilearrowdown->SetIsVisible(false); - } - else if (xc_arrowTimer < 0.f) - { - xc_arrowTimer = std::min(0.f, xc_arrowTimer + dt); - zeus::CColor color = g_tweakGuiColors->GetMissileIconColorActive(); - color.a() *= -xc_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); - x70_model_missilearrowdown->SetColor(color); - x6c_model_missilearrowup->SetIsVisible(false); - } - else - { - x6c_model_missilearrowup->SetIsVisible(false); - x70_model_missilearrowdown->SetIsVisible(false); - } - } - - if (x68_textpane_missilewarning) - { - EInventoryStatus curStatus = GetMissileInventoryStatus(); - if (curStatus != x44_latestStatus) - { - std::u16string string; - switch (curStatus) - { - case EInventoryStatus::Warning: - string = g_MainStringTable->GetString(12); // Missiles Low - break; - case EInventoryStatus::Depleted: - string = g_MainStringTable->GetString(13); // Depleted - default: break; - } - x68_textpane_missilewarning->TextSupport().SetText(string); - - if (x44_latestStatus == EInventoryStatus::Normal && curStatus == EInventoryStatus::Warning) - { - CSfxManager::SfxStart(SFXui_missile_warning, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x48_missileWarningPulse = g_tweakGui->GetMissileWarningPulseTime(); - } - else if (curStatus == EInventoryStatus::Depleted) - { - CSfxManager::SfxStart(SFXui_missile_warning, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x48_missileWarningPulse = g_tweakGui->GetMissileWarningPulseTime(); - } - - x44_latestStatus = curStatus; - } - - x48_missileWarningPulse = std::max(0.f, x48_missileWarningPulse - dt); - float warnPulse = std::min(x48_missileWarningPulse, 1.f); - - if (x44_latestStatus != EInventoryStatus::Normal) - x40_missileWarningAlpha = std::min(x40_missileWarningAlpha + 2.f * dt, 1.f); - else - x40_missileWarningAlpha = std::max(0.f, x40_missileWarningAlpha - 2.f * dt); - - float tmp = std::fabs(std::fmod(CGraphics::GetSecondsMod900(), 0.5f)); - if (tmp < 0.25f) - tmp = tmp / 0.25f; - else - tmp = (0.5f - tmp) / 0.25f; - - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x40_missileWarningAlpha * tmp * warnPulse; - x68_textpane_missilewarning->SetColor(color); - if (x68_textpane_missilewarning->GetGeometryColor().a()) - x68_textpane_missilewarning->SetIsVisible(true); - else - x68_textpane_missilewarning->SetIsVisible(false); - } -} - -void CHudMissileInterface::SetIsVisibleGame(bool v, const CStateManager& mgr) -{ - x58_26_visibleGame = v; - UpdateVisibility(mgr); -} - -void CHudMissileInterface::SetIsVisibleDebug(bool v, const CStateManager& mgr) -{ - x58_25_visibleDebug = v; - UpdateVisibility(mgr); -} - -void CHudMissileInterface::SetIsMissilesActive(bool active) -{ - x58_24_missilesActive = active; -} - -void CHudMissileInterface::SetChargeBeamFactor(float t) -{ - x4c_chargeBeamFactor = t; -} - -void CHudMissileInterface::SetNumMissiles(int numMissiles, const CStateManager& mgr) -{ - numMissiles = zeus::clamp(0, numMissiles, 999); - - x60_textpane_missiledigits->TextSupport().SetText(hecl::Format("%3d", numMissiles)); - - if (x8_numMissles < numMissiles) - { - xc_arrowTimer = g_tweakGui->GetMissileArrowVisTime(); - x54_missileIconIncrement = -FLT_EPSILON; - } - else if (x8_numMissles > numMissiles) - { - xc_arrowTimer = -g_tweakGui->GetMissileArrowVisTime(); - } - - if (mgr.GetPlayerState()->GetMissileCostForAltAttack() + numMissiles <= x8_numMissles) - x50_missileIconAltDeplete = 1.f; - - x8_numMissles = numMissiles; -} - -void CHudMissileInterface::SetMissileCapacity(int missileCapacity) -{ - x4_missileCapacity = missileCapacity; -} - -CHudMissileInterface::EInventoryStatus CHudMissileInterface::GetMissileInventoryStatus() -{ - if (x64_energybart01_missilebar->GetSetEnergy() == 0.f) - return EInventoryStatus::Depleted; - return EInventoryStatus(x64_energybart01_missilebar->GetActualFraction() < - g_tweakGui->GetMissileWarningFraction()); -} - -std::pair CHudMissileInterface::CombatMissileBarCoordFunc(float t) -{ - float z = t * IconTranslateRanges[int(EHudType::Combat)]; - return {zeus::CVector3f(0.f, 0.f, z), zeus::CVector3f(0.3f, 0.f, z)}; -} - -std::pair CHudMissileInterface::XRayMissileBarCoordFunc(float t) -{ - float theta = 0.8f * (t - 0.5f); - float x = 9.55f * std::cos(theta); - float z = 9.55f * std::sin(theta); - return {zeus::CVector3f(x - 0.4f, 0.f, z), zeus::CVector3f(x, 0.f, z)}; -} - -std::pair CHudMissileInterface::ThermalMissileBarCoordFunc(float t) -{ - float transRange = IconTranslateRanges[int(EHudType::Thermal)]; - float a = 0.08f * transRange; - float b = t * transRange; - float c; - if (b < a) - c = b / a; - else if (b < transRange - a) - c = 1.f; + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x40_missileWarningAlpha * tmp * warnPulse; + x68_textpane_missilewarning->SetColor(color); + if (x68_textpane_missilewarning->GetGeometryColor().a()) + x68_textpane_missilewarning->SetIsVisible(true); else - c = 1.f - (b - (transRange - a)) / a; - - return {zeus::CVector3f(-0.5f * c - 0.1f, 0.f, b), zeus::CVector3f(-0.1f, 0.f, b)}; + x68_textpane_missilewarning->SetIsVisible(false); + } } +void CHudMissileInterface::SetIsVisibleGame(bool v, const CStateManager& mgr) { + x58_26_visibleGame = v; + UpdateVisibility(mgr); } + +void CHudMissileInterface::SetIsVisibleDebug(bool v, const CStateManager& mgr) { + x58_25_visibleDebug = v; + UpdateVisibility(mgr); +} + +void CHudMissileInterface::SetIsMissilesActive(bool active) { x58_24_missilesActive = active; } + +void CHudMissileInterface::SetChargeBeamFactor(float t) { x4c_chargeBeamFactor = t; } + +void CHudMissileInterface::SetNumMissiles(int numMissiles, const CStateManager& mgr) { + numMissiles = zeus::clamp(0, numMissiles, 999); + + x60_textpane_missiledigits->TextSupport().SetText(hecl::Format("%3d", numMissiles)); + + if (x8_numMissles < numMissiles) { + xc_arrowTimer = g_tweakGui->GetMissileArrowVisTime(); + x54_missileIconIncrement = -FLT_EPSILON; + } else if (x8_numMissles > numMissiles) { + xc_arrowTimer = -g_tweakGui->GetMissileArrowVisTime(); + } + + if (mgr.GetPlayerState()->GetMissileCostForAltAttack() + numMissiles <= x8_numMissles) + x50_missileIconAltDeplete = 1.f; + + x8_numMissles = numMissiles; +} + +void CHudMissileInterface::SetMissileCapacity(int missileCapacity) { x4_missileCapacity = missileCapacity; } + +CHudMissileInterface::EInventoryStatus CHudMissileInterface::GetMissileInventoryStatus() { + if (x64_energybart01_missilebar->GetSetEnergy() == 0.f) + return EInventoryStatus::Depleted; + return EInventoryStatus(x64_energybart01_missilebar->GetActualFraction() < g_tweakGui->GetMissileWarningFraction()); +} + +std::pair CHudMissileInterface::CombatMissileBarCoordFunc(float t) { + float z = t * IconTranslateRanges[int(EHudType::Combat)]; + return {zeus::CVector3f(0.f, 0.f, z), zeus::CVector3f(0.3f, 0.f, z)}; +} + +std::pair CHudMissileInterface::XRayMissileBarCoordFunc(float t) { + float theta = 0.8f * (t - 0.5f); + float x = 9.55f * std::cos(theta); + float z = 9.55f * std::sin(theta); + return {zeus::CVector3f(x - 0.4f, 0.f, z), zeus::CVector3f(x, 0.f, z)}; +} + +std::pair CHudMissileInterface::ThermalMissileBarCoordFunc(float t) { + float transRange = IconTranslateRanges[int(EHudType::Thermal)]; + float a = 0.08f * transRange; + float b = t * transRange; + float c; + if (b < a) + c = b / a; + else if (b < transRange - a) + c = 1.f; + else + c = 1.f - (b - (transRange - a)) / a; + + return {zeus::CVector3f(-0.5f * c - 0.1f, 0.f, b), zeus::CVector3f(-0.1f, 0.f, b)}; +} + +} // namespace urde diff --git a/Runtime/GuiSys/CHudMissileInterface.hpp b/Runtime/GuiSys/CHudMissileInterface.hpp index 72102e8e3..c0a70f35c 100644 --- a/Runtime/GuiSys/CHudMissileInterface.hpp +++ b/Runtime/GuiSys/CHudMissileInterface.hpp @@ -4,8 +4,7 @@ #include "CHudInterface.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CGuiFrame; class CGuiWidget; @@ -13,62 +12,53 @@ class CGuiTextPane; class CAuiEnergyBarT01; class CGuiModel; -class CHudMissileInterface -{ - enum class EInventoryStatus - { - Normal, - Warning, - Depleted - }; +class CHudMissileInterface { + enum class EInventoryStatus { Normal, Warning, Depleted }; - EHudType x0_hudType; - int x4_missileCapacity; - int x8_numMissles; - float xc_arrowTimer = 0.f; - zeus::CTransform x10_missleIconXf; - float x40_missileWarningAlpha = 0.f; - EInventoryStatus x44_latestStatus = EInventoryStatus::Normal; - float x48_missileWarningPulse = 0.f; - float x4c_chargeBeamFactor; - float x50_missileIconAltDeplete = 0.f; - float x54_missileIconIncrement = 0.f; - union - { - struct - { - bool x58_24_missilesActive : 1; - bool x58_25_visibleDebug : 1; - bool x58_26_visibleGame : 1; - bool x58_27_hasArrows : 1; - bool x58_28_notXRay : 1; - }; - u16 _dummy = 0; + EHudType x0_hudType; + int x4_missileCapacity; + int x8_numMissles; + float xc_arrowTimer = 0.f; + zeus::CTransform x10_missleIconXf; + float x40_missileWarningAlpha = 0.f; + EInventoryStatus x44_latestStatus = EInventoryStatus::Normal; + float x48_missileWarningPulse = 0.f; + float x4c_chargeBeamFactor; + float x50_missileIconAltDeplete = 0.f; + float x54_missileIconIncrement = 0.f; + union { + struct { + bool x58_24_missilesActive : 1; + bool x58_25_visibleDebug : 1; + bool x58_26_visibleGame : 1; + bool x58_27_hasArrows : 1; + bool x58_28_notXRay : 1; }; - CGuiWidget* x5c_basewidget_missileicon; - CGuiTextPane* x60_textpane_missiledigits; - CAuiEnergyBarT01* x64_energybart01_missilebar; - CGuiTextPane* x68_textpane_missilewarning; - CGuiModel* x6c_model_missilearrowup; - CGuiModel* x70_model_missilearrowdown; - CGuiWidget* x74_basewidget_missileicon; - void UpdateVisibility(const CStateManager& mgr); + u16 _dummy = 0; + }; + CGuiWidget* x5c_basewidget_missileicon; + CGuiTextPane* x60_textpane_missiledigits; + CAuiEnergyBarT01* x64_energybart01_missilebar; + CGuiTextPane* x68_textpane_missilewarning; + CGuiModel* x6c_model_missilearrowup; + CGuiModel* x70_model_missilearrowdown; + CGuiWidget* x74_basewidget_missileicon; + void UpdateVisibility(const CStateManager& mgr); + public: - CHudMissileInterface(CGuiFrame& selHud, int missileCapacity, int numMissiles, - float chargeFactor, bool missilesActive, EHudType hudType, - const CStateManager& mgr); - void Update(float dt, const CStateManager& mgr); - void SetIsVisibleGame(bool v, const CStateManager& mgr); - void SetIsVisibleDebug(bool v, const CStateManager& mgr); - void SetIsMissilesActive(bool active); - void SetChargeBeamFactor(float t); - void SetNumMissiles(int numMissiles, const CStateManager& mgr); - void SetMissileCapacity(int missileCapacity); - EInventoryStatus GetMissileInventoryStatus(); - static std::pair CombatMissileBarCoordFunc(float t); - static std::pair XRayMissileBarCoordFunc(float t); - static std::pair ThermalMissileBarCoordFunc(float t); + CHudMissileInterface(CGuiFrame& selHud, int missileCapacity, int numMissiles, float chargeFactor, bool missilesActive, + EHudType hudType, const CStateManager& mgr); + void Update(float dt, const CStateManager& mgr); + void SetIsVisibleGame(bool v, const CStateManager& mgr); + void SetIsVisibleDebug(bool v, const CStateManager& mgr); + void SetIsMissilesActive(bool active); + void SetChargeBeamFactor(float t); + void SetNumMissiles(int numMissiles, const CStateManager& mgr); + void SetMissileCapacity(int missileCapacity); + EInventoryStatus GetMissileInventoryStatus(); + static std::pair CombatMissileBarCoordFunc(float t); + static std::pair XRayMissileBarCoordFunc(float t); + static std::pair ThermalMissileBarCoordFunc(float t); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudRadarInterface.cpp b/Runtime/GuiSys/CHudRadarInterface.cpp index 27ac5e029..90ae33870 100644 --- a/Runtime/GuiSys/CHudRadarInterface.cpp +++ b/Runtime/GuiSys/CHudRadarInterface.cpp @@ -13,161 +13,140 @@ #include "GuiSys/CGuiWidgetDrawParms.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CHudRadarInterface::CHudRadarInterface(CGuiFrame& baseHud, CStateManager& stateMgr) -{ - x0_txtrRadarPaint = g_SimplePool->GetObj("TXTR_RadarPaint"); - x3c_24_visibleGame = true; - x3c_25_visibleDebug = true; - x40_BaseWidget_RadarStuff = baseHud.FindWidget("BaseWidget_RadarStuff"); - x44_camera = baseHud.GetFrameCamera(); - xc_radarStuffXf = x40_BaseWidget_RadarStuff->GetLocalTransform(); - x40_BaseWidget_RadarStuff->SetColor(g_tweakGuiColors->GetRadarStuffColor()); +CHudRadarInterface::CHudRadarInterface(CGuiFrame& baseHud, CStateManager& stateMgr) { + x0_txtrRadarPaint = g_SimplePool->GetObj("TXTR_RadarPaint"); + x3c_24_visibleGame = true; + x3c_25_visibleDebug = true; + x40_BaseWidget_RadarStuff = baseHud.FindWidget("BaseWidget_RadarStuff"); + x44_camera = baseHud.GetFrameCamera(); + xc_radarStuffXf = x40_BaseWidget_RadarStuff->GetLocalTransform(); + x40_BaseWidget_RadarStuff->SetColor(g_tweakGuiColors->GetRadarStuffColor()); } -void CHudRadarInterface::DoDrawRadarPaint(float radius, const zeus::CColor& color) const -{ - radius *= 4.f; - const_cast(*this).m_paintInsts.emplace_back(); - CRadarPaintShader::Instance& inst = - const_cast(*this).m_paintInsts.back(); - inst.pos[0].assign(-radius, 0.f, radius); - inst.uv[0].assign(0.f, 1.f); - inst.pos[1].assign(-radius, 0.f, -radius); - inst.uv[1].assign(0.f, 0.f); - inst.pos[2].assign(radius, 0.f, radius); - inst.uv[2].assign(1.f, 1.f); - inst.pos[3].assign(radius, 0.f, -radius); - inst.uv[3].assign(1.f, 0.f); - inst.color = color; +void CHudRadarInterface::DoDrawRadarPaint(float radius, const zeus::CColor& color) const { + radius *= 4.f; + const_cast(*this).m_paintInsts.emplace_back(); + CRadarPaintShader::Instance& inst = const_cast(*this).m_paintInsts.back(); + inst.pos[0].assign(-radius, 0.f, radius); + inst.uv[0].assign(0.f, 1.f); + inst.pos[1].assign(-radius, 0.f, -radius); + inst.uv[1].assign(0.f, 0.f); + inst.pos[2].assign(radius, 0.f, radius); + inst.uv[2].assign(1.f, 1.f); + inst.pos[3].assign(radius, 0.f, -radius); + inst.uv[3].assign(1.f, 0.f); + inst.color = color; } -void CHudRadarInterface::DrawRadarPaint(const zeus::CVector3f& enemyPos, float radius, - float alpha, const SRadarPaintDrawParms& parms) const -{ - zeus::CVector2f playerToEnemy(enemyPos.x() - parms.x0_playerPos.x(), - enemyPos.y() - parms.x0_playerPos.y()); +void CHudRadarInterface::DrawRadarPaint(const zeus::CVector3f& enemyPos, float radius, float alpha, + const SRadarPaintDrawParms& parms) const { + zeus::CVector2f playerToEnemy(enemyPos.x() - parms.x0_playerPos.x(), enemyPos.y() - parms.x0_playerPos.y()); - float zDelta = std::fabs(enemyPos.z() - parms.x0_playerPos.z()); + float zDelta = std::fabs(enemyPos.z() - parms.x0_playerPos.z()); - if (playerToEnemy.magnitude() <= parms.x78_xyRadius && zDelta <= parms.x7c_zRadius) - { - if (zDelta > parms.x80_ZCloseRadius) - alpha *= 1.f - (zDelta - parms.x80_ZCloseRadius) / (parms.x7c_zRadius - parms.x80_ZCloseRadius); - zeus::CVector2f scopeScaled = playerToEnemy * parms.x70_scopeScalar; - zeus::CTransform modelMatrix = parms.x3c_postTranslate * zeus::CTransform::Translate( - parms.xc_preTranslate * zeus::CVector3f(scopeScaled.x(), 0.f, scopeScaled.y())); - CGraphics::SetModelMatrix(modelMatrix); - zeus::CColor color = g_tweakGuiColors->GetRadarEnemyPaintColor(); - color.a() *= alpha; - DoDrawRadarPaint(radius, color); - } + if (playerToEnemy.magnitude() <= parms.x78_xyRadius && zDelta <= parms.x7c_zRadius) { + if (zDelta > parms.x80_ZCloseRadius) + alpha *= 1.f - (zDelta - parms.x80_ZCloseRadius) / (parms.x7c_zRadius - parms.x80_ZCloseRadius); + zeus::CVector2f scopeScaled = playerToEnemy * parms.x70_scopeScalar; + zeus::CTransform modelMatrix = + parms.x3c_postTranslate * + zeus::CTransform::Translate(parms.xc_preTranslate * zeus::CVector3f(scopeScaled.x(), 0.f, scopeScaled.y())); + CGraphics::SetModelMatrix(modelMatrix); + zeus::CColor color = g_tweakGuiColors->GetRadarEnemyPaintColor(); + color.a() *= alpha; + DoDrawRadarPaint(radius, color); + } } -void CHudRadarInterface::SetIsVisibleGame(bool v) -{ - x3c_24_visibleGame = v; - x40_BaseWidget_RadarStuff->SetVisibility(x3c_25_visibleDebug && x3c_24_visibleGame, - ETraversalMode::Children); +void CHudRadarInterface::SetIsVisibleGame(bool v) { + x3c_24_visibleGame = v; + x40_BaseWidget_RadarStuff->SetVisibility(x3c_25_visibleDebug && x3c_24_visibleGame, ETraversalMode::Children); } -void CHudRadarInterface::Update(float dt, const CStateManager& mgr) -{ - CPlayerState& playerState = *mgr.GetPlayerState(); - float visorTransFactor = (playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat) ? - playerState.GetVisorTransitionFactor() : 0.f; - zeus::CColor color = g_tweakGuiColors->GetRadarStuffColor(); - color.a() *= g_GameState->GameOptions().GetHUDAlpha() / 255.f * visorTransFactor; - x40_BaseWidget_RadarStuff->SetColor(color); - bool tweakVis = g_tweakGui->GetHudVisMode() >= ITweakGui::EHudVisMode::Three; - if (tweakVis != x3c_25_visibleDebug) - { - x3c_25_visibleDebug = tweakVis; - x40_BaseWidget_RadarStuff->SetVisibility(x3c_25_visibleDebug && x3c_24_visibleGame, - ETraversalMode::Children); - } +void CHudRadarInterface::Update(float dt, const CStateManager& mgr) { + CPlayerState& playerState = *mgr.GetPlayerState(); + float visorTransFactor = (playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat) + ? playerState.GetVisorTransitionFactor() + : 0.f; + zeus::CColor color = g_tweakGuiColors->GetRadarStuffColor(); + color.a() *= g_GameState->GameOptions().GetHUDAlpha() / 255.f * visorTransFactor; + x40_BaseWidget_RadarStuff->SetColor(color); + bool tweakVis = g_tweakGui->GetHudVisMode() >= ITweakGui::EHudVisMode::Three; + if (tweakVis != x3c_25_visibleDebug) { + x3c_25_visibleDebug = tweakVis; + x40_BaseWidget_RadarStuff->SetVisibility(x3c_25_visibleDebug && x3c_24_visibleGame, ETraversalMode::Children); + } } -void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) const -{ - alpha *= g_GameState->GameOptions().GetHUDAlpha() / 255.f; - if (g_tweakGui->GetHudVisMode() == ITweakGui::EHudVisMode::Zero || !x3c_24_visibleGame || - !x0_txtrRadarPaint || !x0_txtrRadarPaint.IsLoaded()) - return; +void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) const { + alpha *= g_GameState->GameOptions().GetHUDAlpha() / 255.f; + if (g_tweakGui->GetHudVisMode() == ITweakGui::EHudVisMode::Zero || !x3c_24_visibleGame || !x0_txtrRadarPaint || + !x0_txtrRadarPaint.IsLoaded()) + return; - SRadarPaintDrawParms drawParms; + SRadarPaintDrawParms drawParms; - CPlayer& player = mgr.GetPlayer(); - if (player.IsOverrideRadarRadius()) - { - drawParms.x78_xyRadius = player.GetRadarXYRadiusOverride(); - drawParms.x7c_zRadius = player.GetRadarZRadiusOverride(); - drawParms.x80_ZCloseRadius = 0.667f * drawParms.x7c_zRadius; - } - else - { - drawParms.x78_xyRadius = g_tweakGui->GetRadarXYRadius(); - drawParms.x7c_zRadius = g_tweakGui->GetRadarZRadius(); - drawParms.x80_ZCloseRadius = g_tweakGui->GetRadarZCloseRadius(); - } + CPlayer& player = mgr.GetPlayer(); + if (player.IsOverrideRadarRadius()) { + drawParms.x78_xyRadius = player.GetRadarXYRadiusOverride(); + drawParms.x7c_zRadius = player.GetRadarZRadiusOverride(); + drawParms.x80_ZCloseRadius = 0.667f * drawParms.x7c_zRadius; + } else { + drawParms.x78_xyRadius = g_tweakGui->GetRadarXYRadius(); + drawParms.x7c_zRadius = g_tweakGui->GetRadarZRadius(); + drawParms.x80_ZCloseRadius = g_tweakGui->GetRadarZCloseRadius(); + } - drawParms.x6c_scopeRadius = g_tweakGui->GetRadarScopeCoordRadius(); - drawParms.x70_scopeScalar = drawParms.x6c_scopeRadius / drawParms.x78_xyRadius; + drawParms.x6c_scopeRadius = g_tweakGui->GetRadarScopeCoordRadius(); + drawParms.x70_scopeScalar = drawParms.x6c_scopeRadius / drawParms.x78_xyRadius; - float camZ = zeus::CEulerAngles(zeus::CQuaternion( - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis)).z(); - zeus::CRelAngle angleZ(camZ); - drawParms.xc_preTranslate = zeus::CTransform::RotateY(angleZ); - drawParms.x3c_postTranslate = x40_BaseWidget_RadarStuff->GetWorldTransform(); - float enemyRadius = g_tweakGui->GetRadarEnemyPaintRadius(); + float camZ = + zeus::CEulerAngles(zeus::CQuaternion(mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis)).z(); + zeus::CRelAngle angleZ(camZ); + drawParms.xc_preTranslate = zeus::CTransform::RotateY(angleZ); + drawParms.x3c_postTranslate = x40_BaseWidget_RadarStuff->GetWorldTransform(); + float enemyRadius = g_tweakGui->GetRadarEnemyPaintRadius(); - const_cast(*this).m_paintInsts.clear(); - x44_camera->Draw(CGuiWidgetDrawParms{0.f, zeus::CVector3f{}}); - CGraphics::SetModelMatrix(drawParms.x3c_postTranslate); + const_cast(*this).m_paintInsts.clear(); + x44_camera->Draw(CGuiWidgetDrawParms{0.f, zeus::CVector3f{}}); + CGraphics::SetModelMatrix(drawParms.x3c_postTranslate); - zeus::CColor playerColor = g_tweakGuiColors->GetRadarPlayerPaintColor(); - playerColor.a() *= alpha; - DoDrawRadarPaint(g_tweakGui->GetRadarPlayerPaintRadius(), playerColor); + zeus::CColor playerColor = g_tweakGuiColors->GetRadarPlayerPaintColor(); + playerColor.a() *= alpha; + DoDrawRadarPaint(g_tweakGui->GetRadarPlayerPaintRadius(), playerColor); - zeus::CAABox radarBounds(player.GetTranslation().x() - drawParms.x78_xyRadius, - player.GetTranslation().y() - drawParms.x78_xyRadius, - player.GetTranslation().z() - drawParms.x7c_zRadius, - player.GetTranslation().x() + drawParms.x78_xyRadius, - player.GetTranslation().y() + drawParms.x78_xyRadius, - player.GetTranslation().z() + drawParms.x7c_zRadius); + zeus::CAABox radarBounds( + player.GetTranslation().x() - drawParms.x78_xyRadius, player.GetTranslation().y() - drawParms.x78_xyRadius, + player.GetTranslation().z() - drawParms.x7c_zRadius, player.GetTranslation().x() + drawParms.x78_xyRadius, + player.GetTranslation().y() + drawParms.x78_xyRadius, player.GetTranslation().z() + drawParms.x7c_zRadius); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, radarBounds, - CMaterialFilter(CMaterialList(EMaterialTypes::Target, EMaterialTypes::RadarObject), - CMaterialList(EMaterialTypes::ExcludeFromRadar), - CMaterialFilter::EFilterType::IncludeExclude), nullptr); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, radarBounds, + CMaterialFilter(CMaterialList(EMaterialTypes::Target, EMaterialTypes::RadarObject), + CMaterialList(EMaterialTypes::ExcludeFromRadar), + CMaterialFilter::EFilterType::IncludeExclude), + nullptr); - for (TUniqueId id : nearList) - { - if (TCastToConstPtr act = mgr.GetObjectById(id)) - { - if (!act->GetActive()) - continue; - if (TCastToConstPtr swarm = act.GetPtr()) - { - float radius = enemyRadius * 0.5f; - for (const CWallCrawlerSwarm::CBoid& boid : swarm->GetBoids()) - { - if (!boid.GetActive()) - continue; - DrawRadarPaint(boid.GetTranslation(), radius, 0.5f, drawParms); - } - } - else - { - DrawRadarPaint(act->GetTranslation(), enemyRadius, 1.f, drawParms); - } + for (TUniqueId id : nearList) { + if (TCastToConstPtr act = mgr.GetObjectById(id)) { + if (!act->GetActive()) + continue; + if (TCastToConstPtr swarm = act.GetPtr()) { + float radius = enemyRadius * 0.5f; + for (const CWallCrawlerSwarm::CBoid& boid : swarm->GetBoids()) { + if (!boid.GetActive()) + continue; + DrawRadarPaint(boid.GetTranslation(), radius, 0.5f, drawParms); } + } else { + DrawRadarPaint(act->GetTranslation(), enemyRadius, 1.f, drawParms); + } } + } - const_cast(*this).m_paintShader.draw(m_paintInsts, x0_txtrRadarPaint.GetObj()); + const_cast(*this).m_paintShader.draw(m_paintInsts, x0_txtrRadarPaint.GetObj()); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CHudRadarInterface.hpp b/Runtime/GuiSys/CHudRadarInterface.hpp index fff365651..bbef2a0e8 100644 --- a/Runtime/GuiSys/CHudRadarInterface.hpp +++ b/Runtime/GuiSys/CHudRadarInterface.hpp @@ -4,44 +4,41 @@ #include "Graphics/CTexture.hpp" #include "Graphics/Shaders/CRadarPaintShader.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; class CGuiWidget; class CGuiCamera; class CStateManager; -class CHudRadarInterface -{ - struct SRadarPaintDrawParms - { - zeus::CVector3f x0_playerPos; - zeus::CTransform xc_preTranslate; - zeus::CTransform x3c_postTranslate; - float x6c_scopeRadius; - float x70_scopeScalar; - float x74_alpha; - float x78_xyRadius; - float x7c_zRadius; - float x80_ZCloseRadius; - }; - TLockedToken x0_txtrRadarPaint; - zeus::CTransform xc_radarStuffXf; - bool x3c_24_visibleGame : 1; - bool x3c_25_visibleDebug : 1; - CGuiWidget* x40_BaseWidget_RadarStuff; - CGuiCamera* x44_camera; - CRadarPaintShader m_paintShader; - std::vector m_paintInsts; - void DoDrawRadarPaint(float radius, const zeus::CColor& color) const; - void DrawRadarPaint(const zeus::CVector3f& enemyPos, float radius, - float alpha, const SRadarPaintDrawParms& parms) const; +class CHudRadarInterface { + struct SRadarPaintDrawParms { + zeus::CVector3f x0_playerPos; + zeus::CTransform xc_preTranslate; + zeus::CTransform x3c_postTranslate; + float x6c_scopeRadius; + float x70_scopeScalar; + float x74_alpha; + float x78_xyRadius; + float x7c_zRadius; + float x80_ZCloseRadius; + }; + TLockedToken x0_txtrRadarPaint; + zeus::CTransform xc_radarStuffXf; + bool x3c_24_visibleGame : 1; + bool x3c_25_visibleDebug : 1; + CGuiWidget* x40_BaseWidget_RadarStuff; + CGuiCamera* x44_camera; + CRadarPaintShader m_paintShader; + std::vector m_paintInsts; + void DoDrawRadarPaint(float radius, const zeus::CColor& color) const; + void DrawRadarPaint(const zeus::CVector3f& enemyPos, float radius, float alpha, + const SRadarPaintDrawParms& parms) const; + public: - CHudRadarInterface(CGuiFrame& baseHud, CStateManager& stateMgr); - void SetIsVisibleGame(bool v); - void Update(float dt, const CStateManager& mgr); - void Draw(const CStateManager& mgr, float alpha) const; + CHudRadarInterface(CGuiFrame& baseHud, CStateManager& stateMgr); + void SetIsVisibleGame(bool v); + void Update(float dt, const CStateManager& mgr); + void Draw(const CStateManager& mgr, float alpha) const; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudThreatInterface.cpp b/Runtime/GuiSys/CHudThreatInterface.cpp index ffb373f98..2e6a14363 100644 --- a/Runtime/GuiSys/CHudThreatInterface.cpp +++ b/Runtime/GuiSys/CHudThreatInterface.cpp @@ -7,270 +7,225 @@ #include "CStringTable.hpp" #include "Audio/CSfxManager.hpp" -namespace urde -{ +namespace urde { -static const CAuiEnergyBarT01::FCoordFunc CoordFuncs[] = -{ - CHudThreatInterface::CombatThreatBarCoordFunc, - nullptr, - CHudThreatInterface::XRayThreatBarCoordFunc, - CHudThreatInterface::ThermalThreatBarCoordFunc, - nullptr -}; +static const CAuiEnergyBarT01::FCoordFunc CoordFuncs[] = {CHudThreatInterface::CombatThreatBarCoordFunc, nullptr, + CHudThreatInterface::XRayThreatBarCoordFunc, + CHudThreatInterface::ThermalThreatBarCoordFunc, nullptr}; -static const float IconTranslateRanges[] = -{ - 6.05f, 0.f, 0.f, 8.4f, 0.f -}; +static const float IconTranslateRanges[] = {6.05f, 0.f, 0.f, 8.4f, 0.f}; CHudThreatInterface::CHudThreatInterface(CGuiFrame& selHud, EHudType hudType, float threatDist) -: x4_hudType(hudType), x10_threatDist(threatDist) -{ - x54_24_visibleDebug = true; - x54_25_visibleGame = true; - x58_basewidget_threatstuff = selHud.FindWidget("basewidget_threatstuff"); - x5c_basewidget_threaticon = selHud.FindWidget("basewidget_threaticon"); - x60_model_threatarrowup = static_cast(selHud.FindWidget("model_threatarrowup")); - x64_model_threatarrowdown = static_cast(selHud.FindWidget("model_threatarrowdown")); - x68_textpane_threatwarning = static_cast(selHud.FindWidget("textpane_threatwarning")); - x6c_energybart01_threatbar = static_cast(selHud.FindWidget("energybart01_threatbar")); - x70_textpane_threatdigits = static_cast(selHud.FindWidget("textpane_threatdigits")); +: x4_hudType(hudType), x10_threatDist(threatDist) { + x54_24_visibleDebug = true; + x54_25_visibleGame = true; + x58_basewidget_threatstuff = selHud.FindWidget("basewidget_threatstuff"); + x5c_basewidget_threaticon = selHud.FindWidget("basewidget_threaticon"); + x60_model_threatarrowup = static_cast(selHud.FindWidget("model_threatarrowup")); + x64_model_threatarrowdown = static_cast(selHud.FindWidget("model_threatarrowdown")); + x68_textpane_threatwarning = static_cast(selHud.FindWidget("textpane_threatwarning")); + x6c_energybart01_threatbar = static_cast(selHud.FindWidget("energybart01_threatbar")); + x70_textpane_threatdigits = static_cast(selHud.FindWidget("textpane_threatdigits")); - if (x70_textpane_threatdigits) - { - x70_textpane_threatdigits->TextSupport().SetFontColor(g_tweakGuiColors->GetThreatDigitsFont()); - x70_textpane_threatdigits->TextSupport().SetOutlineColor(g_tweakGuiColors->GetThreatDigitsOutline()); - } + if (x70_textpane_threatdigits) { + x70_textpane_threatdigits->TextSupport().SetFontColor(g_tweakGuiColors->GetThreatDigitsFont()); + x70_textpane_threatdigits->TextSupport().SetOutlineColor(g_tweakGuiColors->GetThreatDigitsOutline()); + } - x54_26_hasArrows = x60_model_threatarrowup && x64_model_threatarrowdown; - x54_27_notXRay = hudType != EHudType::XRay; + x54_26_hasArrows = x60_model_threatarrowup && x64_model_threatarrowdown; + x54_27_notXRay = hudType != EHudType::XRay; - x5c_basewidget_threaticon->SetColor(g_tweakGuiColors->GetThreatIconColor()); - x18_threatIconXf = x5c_basewidget_threaticon->GetLocalTransform(); + x5c_basewidget_threaticon->SetColor(g_tweakGuiColors->GetThreatIconColor()); + x18_threatIconXf = x5c_basewidget_threaticon->GetLocalTransform(); - x6c_energybart01_threatbar->SetFilledColor(g_tweakGuiColors->GetThreatBarFilled()); - x6c_energybart01_threatbar->SetShadowColor(g_tweakGuiColors->GetThreatBarShadow()); - x6c_energybart01_threatbar->SetEmptyColor(g_tweakGuiColors->GetThreatBarEmpty()); - x6c_energybart01_threatbar->SetCoordFunc(CoordFuncs[int(hudType)]); - x6c_energybart01_threatbar->SetTesselation(hudType == EHudType::Combat ? 1.f : 0.1f); - x6c_energybart01_threatbar->SetMaxEnergy(g_tweakGui->GetThreatRange()); - x6c_energybart01_threatbar->SetFilledDrainSpeed(9999.f); - x6c_energybart01_threatbar->SetShadowDrainSpeed(9999.f); - x6c_energybart01_threatbar->SetShadowDrainDelay(0.f); - x6c_energybart01_threatbar->SetIsAlwaysResetTimer(false); + x6c_energybart01_threatbar->SetFilledColor(g_tweakGuiColors->GetThreatBarFilled()); + x6c_energybart01_threatbar->SetShadowColor(g_tweakGuiColors->GetThreatBarShadow()); + x6c_energybart01_threatbar->SetEmptyColor(g_tweakGuiColors->GetThreatBarEmpty()); + x6c_energybart01_threatbar->SetCoordFunc(CoordFuncs[int(hudType)]); + x6c_energybart01_threatbar->SetTesselation(hudType == EHudType::Combat ? 1.f : 0.1f); + x6c_energybart01_threatbar->SetMaxEnergy(g_tweakGui->GetThreatRange()); + x6c_energybart01_threatbar->SetFilledDrainSpeed(9999.f); + x6c_energybart01_threatbar->SetShadowDrainSpeed(9999.f); + x6c_energybart01_threatbar->SetShadowDrainDelay(0.f); + x6c_energybart01_threatbar->SetIsAlwaysResetTimer(false); - if (x68_textpane_threatwarning) - { - x68_textpane_threatwarning->TextSupport().SetFontColor(g_tweakGuiColors->GetThreatWarningFont()); - x68_textpane_threatwarning->TextSupport().SetOutlineColor(g_tweakGuiColors->GetThreatWarningOutline()); - } + if (x68_textpane_threatwarning) { + x68_textpane_threatwarning->TextSupport().SetFontColor(g_tweakGuiColors->GetThreatWarningFont()); + x68_textpane_threatwarning->TextSupport().SetOutlineColor(g_tweakGuiColors->GetThreatWarningOutline()); + } } -void CHudThreatInterface::SetThreatDistance(float threatDist) -{ - x10_threatDist = threatDist; +void CHudThreatInterface::SetThreatDistance(float threatDist) { x10_threatDist = threatDist; } + +void CHudThreatInterface::SetIsVisibleDebug(bool v) { + x54_24_visibleDebug = v; + UpdateVisibility(); } -void CHudThreatInterface::SetIsVisibleDebug(bool v) -{ - x54_24_visibleDebug = v; - UpdateVisibility(); +void CHudThreatInterface::SetIsVisibleGame(bool v) { + x54_25_visibleGame = v; + UpdateVisibility(); } -void CHudThreatInterface::SetIsVisibleGame(bool v) -{ - x54_25_visibleGame = v; - UpdateVisibility(); +void CHudThreatInterface::UpdateVisibility() { + bool vis = x54_24_visibleDebug && x54_25_visibleGame; + x58_basewidget_threatstuff->SetVisibility(vis, ETraversalMode::Children); + if (vis) + SetThreatDistance(0.f); } -void CHudThreatInterface::UpdateVisibility() -{ - bool vis = x54_24_visibleDebug && x54_25_visibleGame; - x58_basewidget_threatstuff->SetVisibility(vis, ETraversalMode::Children); - if (vis) - SetThreatDistance(0.f); -} +void CHudThreatInterface::Update(float dt) { + zeus::CColor warningColor = zeus::CColor::lerp(g_tweakGuiColors->GetThreatIconColor(), + g_tweakGuiColors->GetThreatIconWarningColor(), x50_warningColorLerp); -void CHudThreatInterface::Update(float dt) -{ - zeus::CColor warningColor = zeus::CColor::lerp(g_tweakGuiColors->GetThreatIconColor(), - g_tweakGuiColors->GetThreatIconWarningColor(), - x50_warningColorLerp); - - float maxThreatEnergy = g_tweakGui->GetThreatRange(); - if (x70_textpane_threatdigits) - { - if (x10_threatDist < maxThreatEnergy) - { - x70_textpane_threatdigits->SetIsVisible(true); - x70_textpane_threatdigits->TextSupport().SetText( - hecl::Format("%01.1f", std::max(0.f, x10_threatDist))); - } - else - { - x70_textpane_threatdigits->SetIsVisible(false); - } + float maxThreatEnergy = g_tweakGui->GetThreatRange(); + if (x70_textpane_threatdigits) { + if (x10_threatDist < maxThreatEnergy) { + x70_textpane_threatdigits->SetIsVisible(true); + x70_textpane_threatdigits->TextSupport().SetText(hecl::Format("%01.1f", std::max(0.f, x10_threatDist))); + } else { + x70_textpane_threatdigits->SetIsVisible(false); } + } - if (x54_26_hasArrows) - { - if (x14_arrowTimer > 0.f) - { - x60_model_threatarrowup->SetIsVisible(true); - x14_arrowTimer = std::max(0.f, x14_arrowTimer - dt); - zeus::CColor color = warningColor; - color.a() = x14_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); - x60_model_threatarrowup->SetColor(color); - x64_model_threatarrowdown->SetIsVisible(false); - } - else if (x14_arrowTimer < 0.f) - { - x64_model_threatarrowdown->SetIsVisible(true); - x14_arrowTimer = std::min(0.f, x14_arrowTimer + dt); - zeus::CColor color = warningColor; - color.a() = -x14_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); - x64_model_threatarrowdown->SetColor(color); - x60_model_threatarrowup->SetIsVisible(false); - } - else - { - x60_model_threatarrowup->SetIsVisible(false); - x64_model_threatarrowdown->SetIsVisible(false); - } + if (x54_26_hasArrows) { + if (x14_arrowTimer > 0.f) { + x60_model_threatarrowup->SetIsVisible(true); + x14_arrowTimer = std::max(0.f, x14_arrowTimer - dt); + zeus::CColor color = warningColor; + color.a() = x14_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); + x60_model_threatarrowup->SetColor(color); + x64_model_threatarrowdown->SetIsVisible(false); + } else if (x14_arrowTimer < 0.f) { + x64_model_threatarrowdown->SetIsVisible(true); + x14_arrowTimer = std::min(0.f, x14_arrowTimer + dt); + zeus::CColor color = warningColor; + color.a() = -x14_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); + x64_model_threatarrowdown->SetColor(color); + x60_model_threatarrowup->SetIsVisible(false); + } else { + x60_model_threatarrowup->SetIsVisible(false); + x64_model_threatarrowdown->SetIsVisible(false); } + } - if (x10_threatDist <= maxThreatEnergy) - { - float tmp = x10_threatDist - (maxThreatEnergy - x6c_energybart01_threatbar->GetSetEnergy()); - if (tmp < -0.01f) - x14_arrowTimer = g_tweakGui->GetMissileArrowVisTime(); - else if (tmp > 0.01f) - x14_arrowTimer = -g_tweakGui->GetMissileArrowVisTime(); - } + if (x10_threatDist <= maxThreatEnergy) { + float tmp = x10_threatDist - (maxThreatEnergy - x6c_energybart01_threatbar->GetSetEnergy()); + if (tmp < -0.01f) + x14_arrowTimer = g_tweakGui->GetMissileArrowVisTime(); + else if (tmp > 0.01f) + x14_arrowTimer = -g_tweakGui->GetMissileArrowVisTime(); + } else { + x14_arrowTimer = 0.f; + } + + if (x10_threatDist <= maxThreatEnergy) { + x6c_energybart01_threatbar->SetCurrEnergy(x6c_energybart01_threatbar->GetMaxEnergy() - x10_threatDist, + CAuiEnergyBarT01::ESetMode::Normal); + x5c_basewidget_threaticon->SetColor(warningColor); + } else { + x6c_energybart01_threatbar->SetCurrEnergy(0.f, CAuiEnergyBarT01::ESetMode::Normal); + x5c_basewidget_threaticon->SetColor(g_tweakGuiColors->GetThreatIconSafeColor()); + } + + if (x54_27_notXRay) { + x5c_basewidget_threaticon->SetLocalTransform( + x18_threatIconXf * zeus::CTransform::Translate(0.f, 0.f, + std::max(0.f, maxThreatEnergy - x10_threatDist) * + IconTranslateRanges[int(x4_hudType)] / maxThreatEnergy)); + } + + if (x68_textpane_threatwarning) { + if (x6c_energybart01_threatbar->GetActualFraction() > g_tweakGui->GetThreatWarningFraction()) + x68_textpane_threatwarning->SetIsVisible(true); else - { - x14_arrowTimer = 0.f; - } + x68_textpane_threatwarning->SetIsVisible(false); - if (x10_threatDist <= maxThreatEnergy) - { - x6c_energybart01_threatbar->SetCurrEnergy(x6c_energybart01_threatbar->GetMaxEnergy() - x10_threatDist, - CAuiEnergyBarT01::ESetMode::Normal); - x5c_basewidget_threaticon->SetColor(warningColor); - } + EThreatStatus newStatus; + if (maxThreatEnergy == x6c_energybart01_threatbar->GetSetEnergy()) + newStatus = EThreatStatus::Damage; + else if (x6c_energybart01_threatbar->GetActualFraction() > g_tweakGui->GetThreatWarningFraction()) + newStatus = EThreatStatus::Warning; else - { - x6c_energybart01_threatbar->SetCurrEnergy(0.f, CAuiEnergyBarT01::ESetMode::Normal); - x5c_basewidget_threaticon->SetColor(g_tweakGuiColors->GetThreatIconSafeColor()); - } + newStatus = EThreatStatus::Normal; - if (x54_27_notXRay) - { - x5c_basewidget_threaticon->SetLocalTransform(x18_threatIconXf * zeus::CTransform::Translate(0.f, 0.f, - std::max(0.f, maxThreatEnergy - x10_threatDist) * IconTranslateRanges[int(x4_hudType)] / maxThreatEnergy)); - } + if (x4c_threatStatus != newStatus) { + std::u16string string; + if (newStatus == EThreatStatus::Warning) + string = g_MainStringTable->GetString(10); + else if (newStatus == EThreatStatus::Damage) + string = g_MainStringTable->GetString(11); - if (x68_textpane_threatwarning) - { - if (x6c_energybart01_threatbar->GetActualFraction() > g_tweakGui->GetThreatWarningFraction()) - x68_textpane_threatwarning->SetIsVisible(true); - else - x68_textpane_threatwarning->SetIsVisible(false); + x68_textpane_threatwarning->TextSupport().SetText(string); - EThreatStatus newStatus; - if (maxThreatEnergy == x6c_energybart01_threatbar->GetSetEnergy()) - newStatus = EThreatStatus::Damage; - else if (x6c_energybart01_threatbar->GetActualFraction() > g_tweakGui->GetThreatWarningFraction()) - newStatus = EThreatStatus::Warning; - else - newStatus = EThreatStatus::Normal; - - if (x4c_threatStatus != newStatus) - { - std::u16string string; - if (newStatus == EThreatStatus::Warning) - string = g_MainStringTable->GetString(10); - else if (newStatus == EThreatStatus::Damage) - string = g_MainStringTable->GetString(11); - - x68_textpane_threatwarning->TextSupport().SetText(string); - - if (x4c_threatStatus == EThreatStatus::Normal && newStatus == EThreatStatus::Warning) - CSfxManager::SfxStart(SFXui_threat_warning, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - else if (newStatus == EThreatStatus::Damage) - CSfxManager::SfxStart(SFXui_threat_damage, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - - x4c_threatStatus = newStatus; - } - } - - float oldX8 = x8_damagePulseTimer; - x8_damagePulseTimer = std::fmod(x8_damagePulseTimer + dt, 0.5f); - if (x8_damagePulseTimer < 0.25f) - xc_damagePulse = x8_damagePulseTimer / 0.25f; - else - xc_damagePulse = (0.5f - x8_damagePulseTimer) / 0.25f; - - if (x4c_threatStatus == EThreatStatus::Damage && x8_damagePulseTimer < oldX8) + if (x4c_threatStatus == EThreatStatus::Normal && newStatus == EThreatStatus::Warning) + CSfxManager::SfxStart(SFXui_threat_warning, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + else if (newStatus == EThreatStatus::Damage) CSfxManager::SfxStart(SFXui_threat_damage, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - if (x68_textpane_threatwarning) - { - if (x4c_threatStatus != EThreatStatus::Normal) - { - x48_warningLerpAlpha = std::min(x48_warningLerpAlpha + 2.f * dt, 1.f); - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x48_warningLerpAlpha * xc_damagePulse; - x68_textpane_threatwarning->SetColor(color); - } - else - { - x48_warningLerpAlpha = std::max(0.f, x48_warningLerpAlpha - 2.f * dt); - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x48_warningLerpAlpha * xc_damagePulse; - x68_textpane_threatwarning->SetColor(color); - } - if (x68_textpane_threatwarning->GetGeometryColor().a() > 0.f) - x68_textpane_threatwarning->SetIsVisible(true); - else - x68_textpane_threatwarning->SetIsVisible(false); + x4c_threatStatus = newStatus; } + } - if (x4c_threatStatus == EThreatStatus::Damage) - x50_warningColorLerp = std::min(x50_warningColorLerp + 2.f * dt, 1.f); + float oldX8 = x8_damagePulseTimer; + x8_damagePulseTimer = std::fmod(x8_damagePulseTimer + dt, 0.5f); + if (x8_damagePulseTimer < 0.25f) + xc_damagePulse = x8_damagePulseTimer / 0.25f; + else + xc_damagePulse = (0.5f - x8_damagePulseTimer) / 0.25f; + + if (x4c_threatStatus == EThreatStatus::Damage && x8_damagePulseTimer < oldX8) + CSfxManager::SfxStart(SFXui_threat_damage, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + + if (x68_textpane_threatwarning) { + if (x4c_threatStatus != EThreatStatus::Normal) { + x48_warningLerpAlpha = std::min(x48_warningLerpAlpha + 2.f * dt, 1.f); + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x48_warningLerpAlpha * xc_damagePulse; + x68_textpane_threatwarning->SetColor(color); + } else { + x48_warningLerpAlpha = std::max(0.f, x48_warningLerpAlpha - 2.f * dt); + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x48_warningLerpAlpha * xc_damagePulse; + x68_textpane_threatwarning->SetColor(color); + } + if (x68_textpane_threatwarning->GetGeometryColor().a() > 0.f) + x68_textpane_threatwarning->SetIsVisible(true); else - x50_warningColorLerp = std::max(0.f, x50_warningColorLerp - 2.f * dt); + x68_textpane_threatwarning->SetIsVisible(false); + } + + if (x4c_threatStatus == EThreatStatus::Damage) + x50_warningColorLerp = std::min(x50_warningColorLerp + 2.f * dt, 1.f); + else + x50_warningColorLerp = std::max(0.f, x50_warningColorLerp - 2.f * dt); } -std::pair CHudThreatInterface::CombatThreatBarCoordFunc(float t) -{ - float z = IconTranslateRanges[int(EHudType::Combat)] * t; - return {zeus::CVector3f(-0.3f, 0.f, z), zeus::CVector3f(0.f, 0.f, z)}; +std::pair CHudThreatInterface::CombatThreatBarCoordFunc(float t) { + float z = IconTranslateRanges[int(EHudType::Combat)] * t; + return {zeus::CVector3f(-0.3f, 0.f, z), zeus::CVector3f(0.f, 0.f, z)}; } -std::pair CHudThreatInterface::XRayThreatBarCoordFunc(float t) -{ - float theta = 0.8f * (t - 0.5f); - float x = -9.55f * std::cos(theta); - float z = 9.55f * std::sin(theta); - return {zeus::CVector3f(0.4f + x, 0.f, z), zeus::CVector3f(x, 0.f, z)}; +std::pair CHudThreatInterface::XRayThreatBarCoordFunc(float t) { + float theta = 0.8f * (t - 0.5f); + float x = -9.55f * std::cos(theta); + float z = 9.55f * std::sin(theta); + return {zeus::CVector3f(0.4f + x, 0.f, z), zeus::CVector3f(x, 0.f, z)}; } -std::pair CHudThreatInterface::ThermalThreatBarCoordFunc(float t) -{ - float transRange = IconTranslateRanges[int(EHudType::Thermal)]; - float a = 0.08f * transRange; - float b = t * transRange; - float c; - if (b < a) - c = b / a; - else if (b < transRange - a) - c = 1.f; - else - c = 1.f - (b - (transRange - a)) / a; +std::pair CHudThreatInterface::ThermalThreatBarCoordFunc(float t) { + float transRange = IconTranslateRanges[int(EHudType::Thermal)]; + float a = 0.08f * transRange; + float b = t * transRange; + float c; + if (b < a) + c = b / a; + else if (b < transRange - a) + c = 1.f; + else + c = 1.f - (b - (transRange - a)) / a; - return {zeus::CVector3f(0.1f, 0.f, b), zeus::CVector3f(0.5f * c + 0.1f, 0.f, b)}; + return {zeus::CVector3f(0.1f, 0.f, b), zeus::CVector3f(0.5f * c + 0.1f, 0.f, b)}; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CHudThreatInterface.hpp b/Runtime/GuiSys/CHudThreatInterface.hpp index a00e8b364..098e88bc4 100644 --- a/Runtime/GuiSys/CHudThreatInterface.hpp +++ b/Runtime/GuiSys/CHudThreatInterface.hpp @@ -4,54 +4,47 @@ #include "RetroTypes.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; class CGuiWidget; class CGuiModel; class CGuiTextPane; class CAuiEnergyBarT01; -class CHudThreatInterface -{ - enum class EThreatStatus - { - Normal, - Warning, - Damage - }; +class CHudThreatInterface { + enum class EThreatStatus { Normal, Warning, Damage }; + + EHudType x4_hudType; + float x8_damagePulseTimer = 0.f; + float xc_damagePulse = 0.f; + float x10_threatDist; + float x14_arrowTimer = 0.f; + zeus::CTransform x18_threatIconXf; + float x48_warningLerpAlpha = 0.f; + EThreatStatus x4c_threatStatus = EThreatStatus::Normal; + float x50_warningColorLerp = 0.f; + bool x54_24_visibleDebug : 1; + bool x54_25_visibleGame : 1; + bool x54_26_hasArrows : 1; + bool x54_27_notXRay : 1; + CGuiWidget* x58_basewidget_threatstuff; + CGuiWidget* x5c_basewidget_threaticon; + CGuiModel* x60_model_threatarrowup; + CGuiModel* x64_model_threatarrowdown; + CGuiTextPane* x68_textpane_threatwarning; + CAuiEnergyBarT01* x6c_energybart01_threatbar; + CGuiTextPane* x70_textpane_threatdigits; + void UpdateVisibility(); - EHudType x4_hudType; - float x8_damagePulseTimer = 0.f; - float xc_damagePulse = 0.f; - float x10_threatDist; - float x14_arrowTimer = 0.f; - zeus::CTransform x18_threatIconXf; - float x48_warningLerpAlpha = 0.f; - EThreatStatus x4c_threatStatus = EThreatStatus::Normal; - float x50_warningColorLerp = 0.f; - bool x54_24_visibleDebug : 1; - bool x54_25_visibleGame : 1; - bool x54_26_hasArrows : 1; - bool x54_27_notXRay : 1; - CGuiWidget* x58_basewidget_threatstuff; - CGuiWidget* x5c_basewidget_threaticon; - CGuiModel* x60_model_threatarrowup; - CGuiModel* x64_model_threatarrowdown; - CGuiTextPane* x68_textpane_threatwarning; - CAuiEnergyBarT01* x6c_energybart01_threatbar; - CGuiTextPane* x70_textpane_threatdigits; - void UpdateVisibility(); public: - CHudThreatInterface(CGuiFrame& selHud, EHudType hudType, float threatDist); - void SetThreatDistance(float threatDist); - void SetIsVisibleDebug(bool v); - void SetIsVisibleGame(bool v); - void Update(float dt); - static std::pair CombatThreatBarCoordFunc(float t); - static std::pair XRayThreatBarCoordFunc(float t); - static std::pair ThermalThreatBarCoordFunc(float t); + CHudThreatInterface(CGuiFrame& selHud, EHudType hudType, float threatDist); + void SetThreatDistance(float threatDist); + void SetIsVisibleDebug(bool v); + void SetIsVisibleGame(bool v); + void Update(float dt); + static std::pair CombatThreatBarCoordFunc(float t); + static std::pair XRayThreatBarCoordFunc(float t); + static std::pair ThermalThreatBarCoordFunc(float t); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CHudVisorBeamMenu.cpp b/Runtime/GuiSys/CHudVisorBeamMenu.cpp index 7bdecb063..8ba6de7d3 100644 --- a/Runtime/GuiSys/CHudVisorBeamMenu.cpp +++ b/Runtime/GuiSys/CHudVisorBeamMenu.cpp @@ -7,335 +7,277 @@ #include "CStringTable.hpp" #include "Audio/CSfxManager.hpp" -namespace urde -{ +namespace urde { -static const char* BaseMenuNames[] = -{ - "BaseWidget_VisorMenu", - "BaseWidget_BeamMenu" -}; +static const char* BaseMenuNames[] = {"BaseWidget_VisorMenu", "BaseWidget_BeamMenu"}; -static const char* TextNames[] = -{ - "TextPane_VisorMenu", - "TextPane_BeamMenu" -}; +static const char* TextNames[] = {"TextPane_VisorMenu", "TextPane_BeamMenu"}; -static const char* BaseTitleNames[] = -{ - "basewidget_visormenutitle", - "basewidget_beammenutitle" -}; +static const char* BaseTitleNames[] = {"basewidget_visormenutitle", "basewidget_beammenutitle"}; -static const char* ModelNames[] = -{ - "model_visor", - "model_beam" -}; +static const char* ModelNames[] = {"model_visor", "model_beam"}; -static const char MenuItemOrders[2][4] = -{ - {'1', '0', '3', '2'}, - {'3', '2', '1', '0'} -}; +static const char MenuItemOrders[2][4] = {{'1', '0', '3', '2'}, {'3', '2', '1', '0'}}; -static const int MenuStringIdx[2][4] = -{ +static const int MenuStringIdx[2][4] = { {0, 2, 1, 3}, // Combat, XRay, Scan, Thermal {4, 5, 6, 7} // Power, Ice, Wave, Plasma }; -static const u16 SelectionSfxs[] = -{ - SFXui_select_visor, SFXui_select_beam -}; +static const u16 SelectionSfxs[] = {SFXui_select_visor, SFXui_select_beam}; CHudVisorBeamMenu::CHudVisorBeamMenu(CGuiFrame& baseHud, EHudVisorBeamMenu type, const rstl::reserved_vector& enables) -: x0_baseHud(baseHud), x4_type(type) -{ - x14_24_visibleDebug = true; - x14_25_visibleGame = true; - x14_26_dirty = true; +: x0_baseHud(baseHud), x4_type(type) { + x14_24_visibleDebug = true; + x14_25_visibleGame = true; + x14_26_dirty = true; - x7c_animDur = g_tweakGui->GetBeamVisorMenuAnimTime(); - x80_24_swapBeamControls = g_GameState->GameOptions().GetSwapBeamControls(); + x7c_animDur = g_tweakGui->GetBeamVisorMenuAnimTime(); + x80_24_swapBeamControls = g_GameState->GameOptions().GetSwapBeamControls(); + EHudVisorBeamMenu swappedType; + if (x80_24_swapBeamControls) + swappedType = EHudVisorBeamMenu(1 - int(x4_type)); + else + swappedType = x4_type; + + x20_textpane_menu = static_cast(x0_baseHud.FindWidget(TextNames[int(swappedType)])); + x1c_basewidget_menutitle = x0_baseHud.FindWidget(BaseTitleNames[int(swappedType)]); + x18_basewidget_menu = x0_baseHud.FindWidget(BaseMenuNames[int(swappedType)]); + + x24_model_ghost = static_cast(x0_baseHud.FindWidget(hecl::Format("%sghost", ModelNames[int(x4_type)]))); + + for (int i = 0; i < 4; ++i) { + SMenuItem& item = x28_menuItems[i]; + item.x0_model_loz = static_cast( + x0_baseHud.FindWidget(hecl::Format("%sloz%c", ModelNames[int(x4_type)], MenuItemOrders[int(x4_type)][i]))); + item.x4_model_icon = static_cast( + x0_baseHud.FindWidget(hecl::Format("%sicon%c", ModelNames[int(x4_type)], MenuItemOrders[int(x4_type)][i]))); + item.xc_opacity = enables[i] ? 1.f : 0.f; + } + + if (x4_type == EHudVisorBeamMenu::Visor) { + x20_textpane_menu->TextSupport().SetFontColor(g_tweakGuiColors->GetVisorMenuTextFont()); + x20_textpane_menu->TextSupport().SetOutlineColor(g_tweakGuiColors->GetVisorMenuTextOutline()); + } else { + x20_textpane_menu->TextSupport().SetFontColor(g_tweakGuiColors->GetBeamMenuTextFont()); + x20_textpane_menu->TextSupport().SetOutlineColor(g_tweakGuiColors->GetBeamMenuTextOutline()); + } + + zeus::CColor titleColor = zeus::CColor::skWhite; + titleColor.a() = 0.f; + x1c_basewidget_menutitle->SetColor(titleColor); + + x20_textpane_menu->TextSupport().SetText(g_MainStringTable->GetString(MenuStringIdx[int(x4_type)][x8_selectedItem])); + + for (int i = 0; i < 4; ++i) { + SMenuItem& item = x28_menuItems[i]; + item.x0_model_loz->SetColor(g_tweakGuiColors->GetVisorBeamMenuLozColor()); + UpdateMenuWidgetTransform(i, *item.x0_model_loz, 1.f); + } + + Update(0.f, true); +} + +void CHudVisorBeamMenu::UpdateMenuWidgetTransform(int idx, CGuiWidget& w, float t) { + float translate = t * g_tweakGui->GetVisorBeamMenuItemTranslate(); + float scale = + t * g_tweakGui->GetVisorBeamMenuItemInactiveScale() + (1.f - t) * g_tweakGui->GetVisorBeamMenuItemActiveScale(); + if (x4_type == EHudVisorBeamMenu::Visor) { + if (idx == 2) + idx = 3; + else if (idx == 3) + idx = 2; + } else { + if (idx == 1) + idx = 2; + else if (idx == 2) + idx = 1; + } + + switch (idx) { + case 0: + w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * zeus::CTransform::Translate(0.f, 0.f, translate) * + zeus::CTransform::Scale(scale)); + break; + case 1: + w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * zeus::CTransform::Translate(translate, 0.f, 0.f) * + zeus::CTransform::Scale(scale)); + break; + case 2: + w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * zeus::CTransform::Translate(0.f, 0.f, -translate) * + zeus::CTransform::Scale(scale)); + break; + case 3: + w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * zeus::CTransform::Translate(-translate, 0.f, 0.f) * + zeus::CTransform::Scale(scale)); + break; + default: + break; + } +} + +void CHudVisorBeamMenu::Update(float dt, bool init) { + bool curSwapBeamControls = g_GameState->GameOptions().GetSwapBeamControls(); + if (x80_24_swapBeamControls != curSwapBeamControls) { + x80_24_swapBeamControls = curSwapBeamControls; EHudVisorBeamMenu swappedType; if (x80_24_swapBeamControls) - swappedType = EHudVisorBeamMenu(1 - int(x4_type)); + swappedType = EHudVisorBeamMenu(1 - int(x4_type)); else - swappedType = x4_type; + swappedType = x4_type; + x18_basewidget_menu = x0_baseHud.FindWidget(BaseMenuNames[int(swappedType)]); x20_textpane_menu = static_cast(x0_baseHud.FindWidget(TextNames[int(swappedType)])); x1c_basewidget_menutitle = x0_baseHud.FindWidget(BaseTitleNames[int(swappedType)]); - x18_basewidget_menu = x0_baseHud.FindWidget(BaseMenuNames[int(swappedType)]); - x24_model_ghost = static_cast(x0_baseHud.FindWidget(hecl::Format("%sghost", ModelNames[int(x4_type)]))); - - for (int i=0 ; i<4 ; ++i) - { - SMenuItem& item = x28_menuItems[i]; - item.x0_model_loz = static_cast(x0_baseHud.FindWidget(hecl::Format("%sloz%c", - ModelNames[int(x4_type)], MenuItemOrders[int(x4_type)][i]))); - item.x4_model_icon = static_cast(x0_baseHud.FindWidget(hecl::Format("%sicon%c", - ModelNames[int(x4_type)], MenuItemOrders[int(x4_type)][i]))); - item.xc_opacity = enables[i] ? 1.f : 0.f; + for (int i = 0; i < 4; ++i) { + SMenuItem& item = x28_menuItems[i]; + UpdateMenuWidgetTransform(i, *item.x4_model_icon, item.x8_positioner); + UpdateMenuWidgetTransform(i, *item.x0_model_loz, 1.f); } - if (x4_type == EHudVisorBeamMenu::Visor) - { - x20_textpane_menu->TextSupport().SetFontColor(g_tweakGuiColors->GetVisorMenuTextFont()); - x20_textpane_menu->TextSupport().SetOutlineColor(g_tweakGuiColors->GetVisorMenuTextOutline()); + UpdateMenuWidgetTransform(x8_selectedItem, *x24_model_ghost, x28_menuItems[x8_selectedItem].x8_positioner); + } + + zeus::CColor activeColor = g_tweakGuiColors->GetVisorBeamMenuItemActive(); + zeus::CColor inactiveColor = g_tweakGuiColors->GetVisorBeamMenuItemInactive(); + zeus::CColor lozColor = g_tweakGuiColors->GetVisorBeamMenuLozColor(); + zeus::CColor tmpColors[4]; + + for (int i = 0; i < 4; ++i) { + SMenuItem& item = x28_menuItems[i]; + if (item.xc_opacity > 0.f) + item.xc_opacity = std::min(item.xc_opacity + dt, 1.f); + tmpColors[i] = zeus::CColor::lerp(activeColor, zeus::CColor::skClear, item.xc_opacity); + } + + switch (x6c_animPhase) { + case EAnimPhase::Steady: + for (int i = 0; i < 4; ++i) { + SMenuItem& item = x28_menuItems[i]; + zeus::CColor& color0 = (x8_selectedItem == i) ? activeColor : inactiveColor; + zeus::CColor& color1 = (x8_selectedItem == i) ? lozColor : inactiveColor; + zeus::CColor iconColor = (item.xc_opacity == 0.f) ? zeus::CColor::skClear : color0 + tmpColors[i]; + zeus::CColor lColor = (item.xc_opacity == 0.f) ? lozColor : color1 + tmpColors[i]; + item.x4_model_icon->SetColor(iconColor); + item.x0_model_loz->SetColor(lColor); + item.x8_positioner = (x8_selectedItem == i) ? 0.f : 1.f; } - else - { - x20_textpane_menu->TextSupport().SetFontColor(g_tweakGuiColors->GetBeamMenuTextFont()); - x20_textpane_menu->TextSupport().SetOutlineColor(g_tweakGuiColors->GetBeamMenuTextOutline()); + x24_model_ghost->SetColor(activeColor); + break; + case EAnimPhase::SelectFlash: { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = 0.f; + x1c_basewidget_menutitle->SetColor(color); + + zeus::CColor& color0 = std::fmod(x10_interp, 0.1f) > 0.05f ? activeColor : inactiveColor; + SMenuItem& item0 = x28_menuItems[xc_pendingSelection]; + color = color0 + tmpColors[xc_pendingSelection]; + item0.x4_model_icon->SetColor(color); + item0.x0_model_loz->SetColor(color); + + SMenuItem& item1 = x28_menuItems[x8_selectedItem]; + color = zeus::CColor::lerp(inactiveColor, activeColor, x10_interp) + tmpColors[x8_selectedItem]; + item1.x4_model_icon->SetColor(color); + item1.x0_model_loz->SetColor(lozColor); + + for (int i = 0; i < 4; ++i) + x28_menuItems[i].x8_positioner = (x8_selectedItem == i) ? 1.f - x10_interp : 1.f; + + x24_model_ghost->SetColor(zeus::CColor::lerp(activeColor, inactiveColor, item1.x8_positioner)); + break; + } + case EAnimPhase::Animate: + for (int i = 0; i < 4; ++i) { + SMenuItem& item = x28_menuItems[i]; + zeus::CColor& color0 = (x8_selectedItem == i) ? activeColor : inactiveColor; + zeus::CColor iconColor = (item.xc_opacity == 0.f) ? zeus::CColor::skClear : color0 + tmpColors[i]; + item.x4_model_icon->SetColor(iconColor); + item.x0_model_loz->SetColor((item.xc_opacity == 0.f || x8_selectedItem == i) ? lozColor : inactiveColor); + item.x8_positioner = (x8_selectedItem == i) ? 1.f - x10_interp : 1.f; } + x24_model_ghost->SetColor( + zeus::CColor::lerp(activeColor, inactiveColor, x28_menuItems[x8_selectedItem].x8_positioner)); + break; + default: + break; + } - zeus::CColor titleColor = zeus::CColor::skWhite; - titleColor.a() = 0.f; - x1c_basewidget_menutitle->SetColor(titleColor); + if (x78_textFader > 0.f) { + x78_textFader = std::max(0.f, x78_textFader - dt); + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x78_textFader / x7c_animDur; + x1c_basewidget_menutitle->SetColor(color); + } - x20_textpane_menu->TextSupport().SetText(g_MainStringTable->GetString(MenuStringIdx[int(x4_type)][x8_selectedItem])); - - for (int i=0 ; i<4 ; ++i) - { - SMenuItem& item = x28_menuItems[i]; - item.x0_model_loz->SetColor(g_tweakGuiColors->GetVisorBeamMenuLozColor()); - UpdateMenuWidgetTransform(i, *item.x0_model_loz, 1.f); + if (x14_26_dirty || init) { + x14_26_dirty = false; + for (int i = 0; i < 4; ++i) { + SMenuItem& item = x28_menuItems[i]; + UpdateMenuWidgetTransform(i, *item.x4_model_icon, item.x8_positioner); } + UpdateMenuWidgetTransform(x8_selectedItem, *x24_model_ghost, x28_menuItems[x8_selectedItem].x8_positioner); + } + if (!x14_24_visibleDebug || !x14_25_visibleGame) + return; + + x1c_basewidget_menutitle->SetVisibility(x1c_basewidget_menutitle->GetGeometryColor().a() != 0.f, + ETraversalMode::Children); + + for (int i = 0; i < 4; ++i) { + SMenuItem& item = x28_menuItems[i]; + item.x4_model_icon->SetIsVisible(item.x4_model_icon->GetGeometryColor().a() != 0.f); + } +} + +void CHudVisorBeamMenu::UpdateHudAlpha(float alpha) { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f * alpha; + x18_basewidget_menu->SetColor(color); +} + +void CHudVisorBeamMenu::SetIsVisibleGame(bool v) { + x14_25_visibleGame = v; + bool vis = x14_24_visibleDebug && x14_25_visibleGame; + x18_basewidget_menu->SetVisibility(vis, ETraversalMode::Children); + if (vis) Update(0.f, true); } -void CHudVisorBeamMenu::UpdateMenuWidgetTransform(int idx, CGuiWidget& w, float t) -{ - float translate = t * g_tweakGui->GetVisorBeamMenuItemTranslate(); - float scale = t * g_tweakGui->GetVisorBeamMenuItemInactiveScale() + - (1.f - t) * g_tweakGui->GetVisorBeamMenuItemActiveScale(); - if (x4_type == EHudVisorBeamMenu::Visor) - { - if (idx == 2) - idx = 3; - else if (idx == 3) - idx = 2; - } - else - { - if (idx == 1) - idx = 2; - else if (idx == 2) - idx = 1; - } - - switch (idx) - { - case 0: - w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * - zeus::CTransform::Translate(0.f, 0.f, translate) * - zeus::CTransform::Scale(scale)); - break; - case 1: - w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * - zeus::CTransform::Translate(translate, 0.f, 0.f) * - zeus::CTransform::Scale(scale)); - break; - case 2: - w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * - zeus::CTransform::Translate(0.f, 0.f, -translate) * - zeus::CTransform::Scale(scale)); - break; - case 3: - w.SetO2WTransform(x18_basewidget_menu->GetWorldTransform() * - zeus::CTransform::Translate(-translate, 0.f, 0.f) * - zeus::CTransform::Scale(scale)); - break; - default: break; - } +void CHudVisorBeamMenu::SetPlayerHas(const rstl::reserved_vector& enables) { + for (int i = 0; i < 4; ++i) { + SMenuItem& item = x28_menuItems[i]; + if (item.xc_opacity == 0.f && enables[i]) + item.xc_opacity = FLT_EPSILON; + } } -void CHudVisorBeamMenu::Update(float dt, bool init) -{ - bool curSwapBeamControls = g_GameState->GameOptions().GetSwapBeamControls(); - if (x80_24_swapBeamControls != curSwapBeamControls) - { - x80_24_swapBeamControls = curSwapBeamControls; - EHudVisorBeamMenu swappedType; - if (x80_24_swapBeamControls) - swappedType = EHudVisorBeamMenu(1 - int(x4_type)); - else - swappedType = x4_type; +void CHudVisorBeamMenu::SetSelection(int selection, int pending, float interp) { + if (x8_selectedItem == selection && xc_pendingSelection == pending && x10_interp == interp) + return; - x18_basewidget_menu = x0_baseHud.FindWidget(BaseMenuNames[int(swappedType)]); - x20_textpane_menu = static_cast(x0_baseHud.FindWidget(TextNames[int(swappedType)])); - x1c_basewidget_menutitle = x0_baseHud.FindWidget(BaseTitleNames[int(swappedType)]); + if (pending != selection) { + if (x6c_animPhase != EAnimPhase::SelectFlash) + CSfxManager::SfxStart(SelectionSfxs[int(x4_type)], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x6c_animPhase = EAnimPhase::SelectFlash; + } else if (interp < 1.f) { + x6c_animPhase = EAnimPhase::Animate; + x20_textpane_menu->TextSupport().SetText( + g_MainStringTable->GetString(MenuStringIdx[int(x4_type)][x8_selectedItem])); + x20_textpane_menu->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, 16.f); + } else { + if (x6c_animPhase != EAnimPhase::Steady) + x78_textFader = x7c_animDur; + x6c_animPhase = EAnimPhase::Steady; + } - for (int i=0 ; i<4 ; ++i) - { - SMenuItem& item = x28_menuItems[i]; - UpdateMenuWidgetTransform(i, *item.x4_model_icon, item.x8_positioner); - UpdateMenuWidgetTransform(i, *item.x0_model_loz, 1.f); - } - - UpdateMenuWidgetTransform(x8_selectedItem, *x24_model_ghost, x28_menuItems[x8_selectedItem].x8_positioner); - } - - zeus::CColor activeColor = g_tweakGuiColors->GetVisorBeamMenuItemActive(); - zeus::CColor inactiveColor = g_tweakGuiColors->GetVisorBeamMenuItemInactive(); - zeus::CColor lozColor = g_tweakGuiColors->GetVisorBeamMenuLozColor(); - zeus::CColor tmpColors[4]; - - for (int i=0 ; i<4 ; ++i) - { - SMenuItem& item = x28_menuItems[i]; - if (item.xc_opacity > 0.f) - item.xc_opacity = std::min(item.xc_opacity + dt, 1.f); - tmpColors[i] = zeus::CColor::lerp(activeColor, zeus::CColor::skClear, item.xc_opacity); - } - - switch (x6c_animPhase) - { - case EAnimPhase::Steady: - for (int i=0 ; i<4 ; ++i) - { - SMenuItem& item = x28_menuItems[i]; - zeus::CColor& color0 = (x8_selectedItem == i) ? activeColor : inactiveColor; - zeus::CColor& color1 = (x8_selectedItem == i) ? lozColor : inactiveColor; - zeus::CColor iconColor = (item.xc_opacity == 0.f) ? zeus::CColor::skClear : color0 + tmpColors[i]; - zeus::CColor lColor = (item.xc_opacity == 0.f) ? lozColor : color1 + tmpColors[i]; - item.x4_model_icon->SetColor(iconColor); - item.x0_model_loz->SetColor(lColor); - item.x8_positioner = (x8_selectedItem == i) ? 0.f : 1.f; - } - x24_model_ghost->SetColor(activeColor); - break; - case EAnimPhase::SelectFlash: - { - zeus::CColor color = zeus::CColor::skWhite; - color.a() = 0.f; - x1c_basewidget_menutitle->SetColor(color); - - zeus::CColor& color0 = std::fmod(x10_interp, 0.1f) > 0.05f ? activeColor : inactiveColor; - SMenuItem& item0 = x28_menuItems[xc_pendingSelection]; - color = color0 + tmpColors[xc_pendingSelection]; - item0.x4_model_icon->SetColor(color); - item0.x0_model_loz->SetColor(color); - - SMenuItem& item1 = x28_menuItems[x8_selectedItem]; - color = zeus::CColor::lerp(inactiveColor, activeColor, x10_interp) + tmpColors[x8_selectedItem]; - item1.x4_model_icon->SetColor(color); - item1.x0_model_loz->SetColor(lozColor); - - for (int i=0 ; i<4 ; ++i) - x28_menuItems[i].x8_positioner = (x8_selectedItem == i) ? 1.f - x10_interp : 1.f; - - x24_model_ghost->SetColor(zeus::CColor::lerp(activeColor, inactiveColor, item1.x8_positioner)); - break; - } - case EAnimPhase::Animate: - for (int i=0 ; i<4 ; ++i) - { - SMenuItem& item = x28_menuItems[i]; - zeus::CColor& color0 = (x8_selectedItem == i) ? activeColor : inactiveColor; - zeus::CColor iconColor = (item.xc_opacity == 0.f) ? zeus::CColor::skClear : color0 + tmpColors[i]; - item.x4_model_icon->SetColor(iconColor); - item.x0_model_loz->SetColor((item.xc_opacity == 0.f || x8_selectedItem == i) ? lozColor : inactiveColor); - item.x8_positioner = (x8_selectedItem == i) ? 1.f - x10_interp : 1.f; - } - x24_model_ghost->SetColor(zeus::CColor::lerp(activeColor, inactiveColor, x28_menuItems[x8_selectedItem].x8_positioner)); - break; - default: break; - } - - if (x78_textFader > 0.f) - { - x78_textFader = std::max(0.f, x78_textFader - dt); - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x78_textFader / x7c_animDur; - x1c_basewidget_menutitle->SetColor(color); - } - - if (x14_26_dirty || init) - { - x14_26_dirty = false; - for (int i=0 ; i<4 ; ++i) - { - SMenuItem& item = x28_menuItems[i]; - UpdateMenuWidgetTransform(i, *item.x4_model_icon, item.x8_positioner); - } - UpdateMenuWidgetTransform(x8_selectedItem, *x24_model_ghost, x28_menuItems[x8_selectedItem].x8_positioner); - } - - if (!x14_24_visibleDebug || !x14_25_visibleGame) - return; - - x1c_basewidget_menutitle->SetVisibility - (x1c_basewidget_menutitle->GetGeometryColor().a() != 0.f, ETraversalMode::Children); - - for (int i=0 ; i<4 ; ++i) - { - SMenuItem& item = x28_menuItems[i]; - item.x4_model_icon->SetIsVisible(item.x4_model_icon->GetGeometryColor().a() != 0.f); - } + x14_26_dirty = true; + x8_selectedItem = selection; + xc_pendingSelection = pending; + x10_interp = interp; } -void CHudVisorBeamMenu::UpdateHudAlpha(float alpha) -{ - zeus::CColor color = zeus::CColor::skWhite; - color.a() = g_GameState->GameOptions().GetHUDAlpha() / 255.f * alpha; - x18_basewidget_menu->SetColor(color); -} - -void CHudVisorBeamMenu::SetIsVisibleGame(bool v) -{ - x14_25_visibleGame = v; - bool vis = x14_24_visibleDebug && x14_25_visibleGame; - x18_basewidget_menu->SetVisibility(vis, ETraversalMode::Children); - if (vis) - Update(0.f, true); -} - -void CHudVisorBeamMenu::SetPlayerHas(const rstl::reserved_vector& enables) -{ - for (int i=0 ; i<4 ; ++i) - { - SMenuItem& item = x28_menuItems[i]; - if (item.xc_opacity == 0.f && enables[i]) - item.xc_opacity = FLT_EPSILON; - } -} - -void CHudVisorBeamMenu::SetSelection(int selection, int pending, float interp) -{ - if (x8_selectedItem == selection && xc_pendingSelection == pending && x10_interp == interp) - return; - - if (pending != selection) - { - if (x6c_animPhase != EAnimPhase::SelectFlash) - CSfxManager::SfxStart(SelectionSfxs[int(x4_type)], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x6c_animPhase = EAnimPhase::SelectFlash; - } - else if (interp < 1.f) - { - x6c_animPhase = EAnimPhase::Animate; - x20_textpane_menu->TextSupport().SetText(g_MainStringTable->GetString(MenuStringIdx[int(x4_type)][x8_selectedItem])); - x20_textpane_menu->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, 16.f); - } - else - { - if (x6c_animPhase != EAnimPhase::Steady) - x78_textFader = x7c_animDur; - x6c_animPhase = EAnimPhase::Steady; - } - - x14_26_dirty = true; - x8_selectedItem = selection; - xc_pendingSelection = pending; - x10_interp = interp; -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CHudVisorBeamMenu.hpp b/Runtime/GuiSys/CHudVisorBeamMenu.hpp index 31d6b1a3c..37e043130 100644 --- a/Runtime/GuiSys/CHudVisorBeamMenu.hpp +++ b/Runtime/GuiSys/CHudVisorBeamMenu.hpp @@ -3,69 +3,55 @@ #include "RetroTypes.hpp" #include -namespace urde -{ +namespace urde { class CGuiFrame; class CGuiWidget; class CGuiTextPane; class CGuiModel; -class CHudVisorBeamMenu -{ +class CHudVisorBeamMenu { public: - enum class EHudVisorBeamMenu - { - Visor, - Beam - }; + enum class EHudVisorBeamMenu { Visor, Beam }; + private: - struct SMenuItem - { - CGuiModel* x0_model_loz = nullptr; - CGuiModel* x4_model_icon = nullptr; - float x8_positioner = 0.f; - float xc_opacity = 0.f; - }; + struct SMenuItem { + CGuiModel* x0_model_loz = nullptr; + CGuiModel* x4_model_icon = nullptr; + float x8_positioner = 0.f; + float xc_opacity = 0.f; + }; - enum class EAnimPhase - { - None, - Steady, - SelectFlash, - Animate - }; + enum class EAnimPhase { None, Steady, SelectFlash, Animate }; - CGuiFrame& x0_baseHud; - EHudVisorBeamMenu x4_type; - int x8_selectedItem = 0; - int xc_pendingSelection = 0; - float x10_interp = 1.f; - bool x14_24_visibleDebug : 1; - bool x14_25_visibleGame : 1; - bool x14_26_dirty : 1; - CGuiWidget* x18_basewidget_menu; - CGuiWidget* x1c_basewidget_menutitle; - CGuiTextPane* x20_textpane_menu; - CGuiModel* x24_model_ghost; - rstl::reserved_vector x28_menuItems; - EAnimPhase x6c_animPhase = EAnimPhase::Steady; - float x70_ = FLT_EPSILON; - float x74_ = FLT_EPSILON; - float x78_textFader = 0.f; - float x7c_animDur; - bool x80_24_swapBeamControls : 1; + CGuiFrame& x0_baseHud; + EHudVisorBeamMenu x4_type; + int x8_selectedItem = 0; + int xc_pendingSelection = 0; + float x10_interp = 1.f; + bool x14_24_visibleDebug : 1; + bool x14_25_visibleGame : 1; + bool x14_26_dirty : 1; + CGuiWidget* x18_basewidget_menu; + CGuiWidget* x1c_basewidget_menutitle; + CGuiTextPane* x20_textpane_menu; + CGuiModel* x24_model_ghost; + rstl::reserved_vector x28_menuItems; + EAnimPhase x6c_animPhase = EAnimPhase::Steady; + float x70_ = FLT_EPSILON; + float x74_ = FLT_EPSILON; + float x78_textFader = 0.f; + float x7c_animDur; + bool x80_24_swapBeamControls : 1; + + void UpdateMenuWidgetTransform(int, CGuiWidget& w, float); - void UpdateMenuWidgetTransform(int, CGuiWidget& w, float); public: - CHudVisorBeamMenu(CGuiFrame& baseHud, EHudVisorBeamMenu type, - const rstl::reserved_vector& enables); - void Update(float dt, bool init); - void UpdateHudAlpha(float alpha); - void SetIsVisibleGame(bool v); - void SetPlayerHas(const rstl::reserved_vector& enables); - void SetSelection(int, int, float); - + CHudVisorBeamMenu(CGuiFrame& baseHud, EHudVisorBeamMenu type, const rstl::reserved_vector& enables); + void Update(float dt, bool init); + void UpdateHudAlpha(float alpha); + void SetIsVisibleGame(bool v); + void SetPlayerHas(const rstl::reserved_vector& enables); + void SetSelection(int, int, float); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CInstruction.cpp b/Runtime/GuiSys/CInstruction.cpp index 175ea518c..3dab285a8 100644 --- a/Runtime/GuiSys/CInstruction.cpp +++ b/Runtime/GuiSys/CInstruction.cpp @@ -4,396 +4,306 @@ #include "CRasterFont.hpp" #include "Graphics/CTexture.hpp" -namespace urde -{ +namespace urde { -void CInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ +void CInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const {} + +void CInstruction::GetAssets(std::vector& assetsOut) const {} + +size_t CInstruction::GetAssetCount() const { return 0; } + +void CColorInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + state.SetColor(x4_cType, x8_color); } -void CInstruction::GetAssets(std::vector& assetsOut) const -{ +void CColorInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); } + +void CColorOverrideInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + state.x64_colorOverrides[x4_overrideIdx] = true; + zeus::CColor convCol = state.ConvertToTextureSpace(x8_color); + state.x0_drawStrOpts.x4_colors[x4_overrideIdx] = convCol; } -size_t CInstruction::GetAssetCount() const -{ - return 0; +void CColorOverrideInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + Invoke(state, buf); } -void CColorInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - state.SetColor(x4_cType, x8_color); +void CFontInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + buf->AddFontChange(x4_font); + state.x48_font = x4_font; + state.RefreshPalette(); } -void CColorInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - Invoke(state, buf); +void CFontInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); } + +void CFontInstruction::GetAssets(std::vector& assetsOut) const { assetsOut.push_back(x4_font); } + +size_t CFontInstruction::GetAssetCount() const { return 1; } + +void CLineExtraSpaceInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + state.x78_extraLineSpace = x4_extraSpace; } -void CColorOverrideInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - state.x64_colorOverrides[x4_overrideIdx] = true; - zeus::CColor convCol = state.ConvertToTextureSpace(x8_color); - state.x0_drawStrOpts.x4_colors[x4_overrideIdx] = convCol; +void CLineExtraSpaceInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + Invoke(state, buf); } -void CColorOverrideInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - Invoke(state, buf); +void CLineInstruction::TestLargestFont(s32 w, s32 h, s32 b) { + if (!x18_largestMonoBaseline) + x18_largestMonoBaseline = b; + + if (x14_largestMonoWidth < w) + x14_largestMonoWidth = w; + + if (x10_largestMonoHeight < h) { + x10_largestMonoHeight = h; + x18_largestMonoBaseline = b; + } } -void CFontInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - buf->AddFontChange(x4_font); - state.x48_font = x4_font; - state.RefreshPalette(); +void CLineInstruction::TestLargestImage(s32 w, s32 h, s32 b) { + if (!x24_largestImageBaseline) + x24_largestImageBaseline = b; + + if (x20_largestImageWidth < w) + x20_largestImageWidth = w; + + if (x1c_largestImageHeight < h) { + x1c_largestImageHeight = h; + x24_largestImageBaseline = b; + } } -void CFontInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - Invoke(state, buf); -} - -void CFontInstruction::GetAssets(std::vector& assetsOut) const -{ - assetsOut.push_back(x4_font); -} - -size_t CFontInstruction::GetAssetCount() const -{ - return 1; -} - -void CLineExtraSpaceInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - state.x78_extraLineSpace = x4_extraSpace; -} - -void CLineExtraSpaceInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - Invoke(state, buf); -} - -void CLineInstruction::TestLargestFont(s32 w, s32 h, s32 b) -{ - if (!x18_largestMonoBaseline) - x18_largestMonoBaseline = b; - - if (x14_largestMonoWidth < w) - x14_largestMonoWidth = w; - - if (x10_largestMonoHeight < h) - { - x10_largestMonoHeight = h; - x18_largestMonoBaseline = b; +void CLineInstruction::InvokeLTR(CFontRenderState& state) const { + switch (x28_just) { + case EJustification::Left: + case EJustification::Full: + case EJustification::NLeft: + case EJustification::LeftMono: + state.xd4_curX = state.x88_curBlock->x4_offsetX; + break; + case EJustification::Center: + case EJustification::CenterMono: + state.xd4_curX = state.x88_curBlock->x4_offsetX + state.x88_curBlock->xc_blockExtentX / 2 - x8_curX / 2; + break; + case EJustification::NCenter: + if (x4_wordCount == 1) { + state.xd4_curX = state.x88_curBlock->x4_offsetX + state.x88_curBlock->xc_blockExtentX / 2 - x8_curX / 2; + } else { + state.xd4_curX = + state.x88_curBlock->x4_offsetX + state.x88_curBlock->xc_blockExtentX / 2 - state.x88_curBlock->x2c_lineX / 2; } -} - -void CLineInstruction::TestLargestImage(s32 w, s32 h, s32 b) -{ - if (!x24_largestImageBaseline) - x24_largestImageBaseline = b; - - if (x20_largestImageWidth < w) - x20_largestImageWidth = w; - - if (x1c_largestImageHeight < h) - { - x1c_largestImageHeight = h; - x24_largestImageBaseline = b; - } -} - -void CLineInstruction::InvokeLTR(CFontRenderState& state) const -{ - switch (x28_just) - { - case EJustification::Left: - case EJustification::Full: - case EJustification::NLeft: - case EJustification::LeftMono: - state.xd4_curX = state.x88_curBlock->x4_offsetX; - break; - case EJustification::Center: - case EJustification::CenterMono: - state.xd4_curX = state.x88_curBlock->x4_offsetX + - state.x88_curBlock->xc_blockExtentX / 2 - x8_curX / 2; - break; - case EJustification::NCenter: - if (x4_wordCount == 1) - { - state.xd4_curX = state.x88_curBlock->x4_offsetX + - state.x88_curBlock->xc_blockExtentX / 2 - x8_curX / 2; - } - else - { - state.xd4_curX = state.x88_curBlock->x4_offsetX + - state.x88_curBlock->xc_blockExtentX / 2 - - state.x88_curBlock->x2c_lineX / 2; - } - break; - case EJustification::Right: - case EJustification::RightMono: - state.xd4_curX = state.x88_curBlock->x4_offsetX + - state.x88_curBlock->xc_blockExtentX - x8_curX; - break; - case EJustification::NRight: - state.xd4_curX = state.x88_curBlock->x4_offsetX + - state.x88_curBlock->xc_blockExtentX - - state.x88_curBlock->x2c_lineX; - break; - default: break; - } - - if (state.xdc_currentLineInst) - { - const CLineInstruction& inst = *state.xdc_currentLineInst; - s32 val = 0; - switch (state.x88_curBlock->x1c_vertJustification) - { - case EVerticalJustification::Top: - case EVerticalJustification::Center: - case EVerticalJustification::Bottom: - case EVerticalJustification::NTop: - case EVerticalJustification::NCenter: - case EVerticalJustification::NBottom: - val = inst.xc_curY; - break; - case EVerticalJustification::Full: - val = state.x88_curBlock->x10_blockExtentY - state.x88_curBlock->x30_lineY; - if (state.x88_curBlock->x34_lineCount > 1) - val /= state.x88_curBlock->x34_lineCount - 1; - else - val = 0; - val += inst.xc_curY; - break; - case EVerticalJustification::TopMono: - val = state.x88_curBlock->x24_largestMonoH; - break; - case EVerticalJustification::CenterMono: - val = (inst.xc_curY - state.x88_curBlock->x24_largestMonoH) / 2 + - state.x88_curBlock->x24_largestMonoH; - break; - case EVerticalJustification::RightMono: - val = state.x88_curBlock->x24_largestMonoH * 2 - inst.xc_curY; - break; - } - - if (state.x88_curBlock->x1c_vertJustification != EVerticalJustification::Full) - val = val * state.x74_lineSpacing + state.x78_extraLineSpace; - - state.xd8_curY += val; - } -} - -void CLineInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - InvokeLTR(state); - state.x108_lineInitialized = true; - state.xdc_currentLineInst = this; -} - -void CLineInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - if (!state.xdc_currentLineInst) - Invoke(state, buf); -} - -void CLineSpacingInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - state.x74_lineSpacing = x4_lineSpacing; -} - -void CLineSpacingInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - Invoke(state, buf); -} - -void CPopStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - state.PopState(); -} - -void CPopStateInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - Invoke(state, buf); -} - -void CPushStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - state.PushState(); -} - -void CPushStateInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - Invoke(state, buf); -} - -void CRemoveColorOverrideInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - state.x64_colorOverrides[x4_idx] = false; -} - -void CRemoveColorOverrideInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - Invoke(state, buf); -} - -void CImageInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - if (x4_image.IsLoaded() && x4_image.x4_texs.size()) - { - const CTexture* tex = x4_image.x4_texs[0].GetObj(); - if (state.x88_curBlock->x14_dir == ETextDirection::Horizontal) - { - if (buf) - { - int y = state.xd8_curY + state.xdc_currentLineInst->GetBaseline() - x4_image.CalculateBaseline(); - zeus::CVector2i coords(state.xd4_curX, y); - buf->AddImage(coords, x4_image); - } - state.xd4_curX = state.xd4_curX + tex->GetWidth() * x4_image.x14_cropFactor.x(); - } - else - { - int scale = state.xdc_currentLineInst->x8_curX - tex->GetWidth() * x4_image.x14_cropFactor.x(); - if (buf) - { - zeus::CVector2i coords(scale / 2 + state.xd4_curX, state.xd8_curY); - buf->AddImage(coords, x4_image); - } - state.xd8_curY += x4_image.CalculateHeight(); - } - } -} - -void CImageInstruction::GetAssets(std::vector& assetsOut) const -{ - for (const CToken& tok : x4_image.x4_texs) - assetsOut.push_back(tok); -} - -size_t CImageInstruction::GetAssetCount() const -{ - return x4_image.x4_texs.size(); -} - -void CTextInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - int xOut, yOut; - if (state.x88_curBlock->x14_dir == ETextDirection::Horizontal) - { - state.x48_font->DrawString(state.x0_drawStrOpts, state.xd4_curX, - state.xdc_currentLineInst->GetBaseline() + state.xd8_curY, - xOut, yOut, buf, x4_str.c_str(), x4_str.size()); - state.xd4_curX = xOut; - } - else - { - int scale = state.xdc_currentLineInst->x8_curX - state.x48_font->GetMonoWidth(); - state.x48_font->DrawString(state.x0_drawStrOpts, scale / 2 + state.xd4_curX, - state.xd8_curY, xOut, yOut, buf, x4_str.c_str(), x4_str.size()); - state.xd8_curY = yOut; - } -} - -void CBlockInstruction::TestLargestFont(s32 monoW, s32 monoH, s32 baseline) -{ - if (!x28_largestBaseline) - x28_largestBaseline = baseline; - - if (x20_largestMonoW < monoW) - monoW = x20_largestMonoW; - - if (x24_largestMonoH < monoH) - { - x24_largestMonoH = monoH; - x28_largestBaseline = baseline; - } -} - -void CBlockInstruction::SetupPositionLTR(CFontRenderState& state) const -{ - switch (x1c_vertJustification) - { - case EVerticalJustification::Top: - case EVerticalJustification::Full: - case EVerticalJustification::NTop: - case EVerticalJustification::TopMono: - state.xd8_curY = x8_offsetY; - break; - case EVerticalJustification::Center: - case EVerticalJustification::NCenter: - state.xd8_curY = x8_offsetY + (x10_blockExtentY - x30_lineY) / 2; - break; - case EVerticalJustification::CenterMono: - state.xd8_curY = x8_offsetY + (x10_blockExtentY - x34_lineCount * x24_largestMonoH) / 2; - break; - case EVerticalJustification::Bottom: - case EVerticalJustification::NBottom: - state.xd8_curY = x8_offsetY + x10_blockExtentY - x30_lineY; - break; - case EVerticalJustification::RightMono: - state.xd8_curY = x8_offsetY + x10_blockExtentY - x34_lineCount * x24_largestMonoH; - break; - } -} - -void CBlockInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - state.x0_drawStrOpts.x0_direction = x14_dir; - state.x88_curBlock = const_cast(this); - if (x14_dir == ETextDirection::Horizontal) - SetupPositionLTR(state); -} - -void CBlockInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - Invoke(state, buf); -} - -void CWordInstruction::InvokeLTR(CFontRenderState& state) const -{ - CRasterFont* font = state.x48_font.GetObj(); - char16_t space = u' '; - int w, h; - font->GetSize(state.x0_drawStrOpts, w, h, &space, 1); + break; + case EJustification::Right: + case EJustification::RightMono: + state.xd4_curX = state.x88_curBlock->x4_offsetX + state.x88_curBlock->xc_blockExtentX - x8_curX; + break; + case EJustification::NRight: + state.xd4_curX = + state.x88_curBlock->x4_offsetX + state.x88_curBlock->xc_blockExtentX - state.x88_curBlock->x2c_lineX; + break; + default: + break; + } + if (state.xdc_currentLineInst) { const CLineInstruction& inst = *state.xdc_currentLineInst; - switch (state.x88_curBlock->x18_justification) - { - case EJustification::Full: - w += (state.x88_curBlock->xc_blockExtentX - inst.x8_curX) / (inst.x4_wordCount - 1); - break; - case EJustification::NLeft: - case EJustification::NCenter: - case EJustification::NRight: - w += (state.x88_curBlock->x2c_lineX - inst.x8_curX) / (inst.x4_wordCount - 1); - break; - default: break; + s32 val = 0; + switch (state.x88_curBlock->x1c_vertJustification) { + case EVerticalJustification::Top: + case EVerticalJustification::Center: + case EVerticalJustification::Bottom: + case EVerticalJustification::NTop: + case EVerticalJustification::NCenter: + case EVerticalJustification::NBottom: + val = inst.xc_curY; + break; + case EVerticalJustification::Full: + val = state.x88_curBlock->x10_blockExtentY - state.x88_curBlock->x30_lineY; + if (state.x88_curBlock->x34_lineCount > 1) + val /= state.x88_curBlock->x34_lineCount - 1; + else + val = 0; + val += inst.xc_curY; + break; + case EVerticalJustification::TopMono: + val = state.x88_curBlock->x24_largestMonoH; + break; + case EVerticalJustification::CenterMono: + val = (inst.xc_curY - state.x88_curBlock->x24_largestMonoH) / 2 + state.x88_curBlock->x24_largestMonoH; + break; + case EVerticalJustification::RightMono: + val = state.x88_curBlock->x24_largestMonoH * 2 - inst.xc_curY; + break; } - int wOut = state.xd4_curX; - font->DrawSpace(state.x0_drawStrOpts, wOut, - inst.xc_curY - font->GetMonoHeight() + state.xd8_curY, wOut, h, w); - state.xd4_curX = wOut; + if (state.x88_curBlock->x1c_vertJustification != EVerticalJustification::Full) + val = val * state.x74_lineSpacing + state.x78_extraLineSpace; + + state.xd8_curY += val; + } } -void CWordInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ - if (state.x108_lineInitialized) - { - state.x108_lineInitialized = false; - return; +void CLineInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + InvokeLTR(state); + state.x108_lineInitialized = true; + state.xdc_currentLineInst = this; +} + +void CLineInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + if (!state.xdc_currentLineInst) + Invoke(state, buf); +} + +void CLineSpacingInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + state.x74_lineSpacing = x4_lineSpacing; +} + +void CLineSpacingInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); } + +void CPopStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { state.PopState(); } + +void CPopStateInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); } + +void CPushStateInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { state.PushState(); } + +void CPushStateInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); } + +void CRemoveColorOverrideInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + state.x64_colorOverrides[x4_idx] = false; +} + +void CRemoveColorOverrideInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + Invoke(state, buf); +} + +void CImageInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + if (x4_image.IsLoaded() && x4_image.x4_texs.size()) { + const CTexture* tex = x4_image.x4_texs[0].GetObj(); + if (state.x88_curBlock->x14_dir == ETextDirection::Horizontal) { + if (buf) { + int y = state.xd8_curY + state.xdc_currentLineInst->GetBaseline() - x4_image.CalculateBaseline(); + zeus::CVector2i coords(state.xd4_curX, y); + buf->AddImage(coords, x4_image); + } + state.xd4_curX = state.xd4_curX + tex->GetWidth() * x4_image.x14_cropFactor.x(); + } else { + int scale = state.xdc_currentLineInst->x8_curX - tex->GetWidth() * x4_image.x14_cropFactor.x(); + if (buf) { + zeus::CVector2i coords(scale / 2 + state.xd4_curX, state.xd8_curY); + buf->AddImage(coords, x4_image); + } + state.xd8_curY += x4_image.CalculateHeight(); } - - if (state.x0_drawStrOpts.x0_direction == ETextDirection::Horizontal) - InvokeLTR(state); + } } -void CWordInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const -{ +void CImageInstruction::GetAssets(std::vector& assetsOut) const { + for (const CToken& tok : x4_image.x4_texs) + assetsOut.push_back(tok); +} + +size_t CImageInstruction::GetAssetCount() const { return x4_image.x4_texs.size(); } + +void CTextInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + int xOut, yOut; + if (state.x88_curBlock->x14_dir == ETextDirection::Horizontal) { + state.x48_font->DrawString(state.x0_drawStrOpts, state.xd4_curX, + state.xdc_currentLineInst->GetBaseline() + state.xd8_curY, xOut, yOut, buf, + x4_str.c_str(), x4_str.size()); + state.xd4_curX = xOut; + } else { + int scale = state.xdc_currentLineInst->x8_curX - state.x48_font->GetMonoWidth(); + state.x48_font->DrawString(state.x0_drawStrOpts, scale / 2 + state.xd4_curX, state.xd8_curY, xOut, yOut, buf, + x4_str.c_str(), x4_str.size()); + state.xd8_curY = yOut; + } +} + +void CBlockInstruction::TestLargestFont(s32 monoW, s32 monoH, s32 baseline) { + if (!x28_largestBaseline) + x28_largestBaseline = baseline; + + if (x20_largestMonoW < monoW) + monoW = x20_largestMonoW; + + if (x24_largestMonoH < monoH) { + x24_largestMonoH = monoH; + x28_largestBaseline = baseline; + } +} + +void CBlockInstruction::SetupPositionLTR(CFontRenderState& state) const { + switch (x1c_vertJustification) { + case EVerticalJustification::Top: + case EVerticalJustification::Full: + case EVerticalJustification::NTop: + case EVerticalJustification::TopMono: + state.xd8_curY = x8_offsetY; + break; + case EVerticalJustification::Center: + case EVerticalJustification::NCenter: + state.xd8_curY = x8_offsetY + (x10_blockExtentY - x30_lineY) / 2; + break; + case EVerticalJustification::CenterMono: + state.xd8_curY = x8_offsetY + (x10_blockExtentY - x34_lineCount * x24_largestMonoH) / 2; + break; + case EVerticalJustification::Bottom: + case EVerticalJustification::NBottom: + state.xd8_curY = x8_offsetY + x10_blockExtentY - x30_lineY; + break; + case EVerticalJustification::RightMono: + state.xd8_curY = x8_offsetY + x10_blockExtentY - x34_lineCount * x24_largestMonoH; + break; + } +} + +void CBlockInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + state.x0_drawStrOpts.x0_direction = x14_dir; + state.x88_curBlock = const_cast(this); + if (x14_dir == ETextDirection::Horizontal) + SetupPositionLTR(state); +} + +void CBlockInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { Invoke(state, buf); } + +void CWordInstruction::InvokeLTR(CFontRenderState& state) const { + CRasterFont* font = state.x48_font.GetObj(); + char16_t space = u' '; + int w, h; + font->GetSize(state.x0_drawStrOpts, w, h, &space, 1); + + const CLineInstruction& inst = *state.xdc_currentLineInst; + switch (state.x88_curBlock->x18_justification) { + case EJustification::Full: + w += (state.x88_curBlock->xc_blockExtentX - inst.x8_curX) / (inst.x4_wordCount - 1); + break; + case EJustification::NLeft: + case EJustification::NCenter: + case EJustification::NRight: + w += (state.x88_curBlock->x2c_lineX - inst.x8_curX) / (inst.x4_wordCount - 1); + break; + default: + break; + } + + int wOut = state.xd4_curX; + font->DrawSpace(state.x0_drawStrOpts, wOut, inst.xc_curY - font->GetMonoHeight() + state.xd8_curY, wOut, h, w); + state.xd4_curX = wOut; +} + +void CWordInstruction::Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + if (state.x108_lineInitialized) { state.x108_lineInitialized = false; + return; + } + + if (state.x0_drawStrOpts.x0_direction == ETextDirection::Horizontal) + InvokeLTR(state); } +void CWordInstruction::PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const { + state.x108_lineInitialized = false; } + +} // namespace urde diff --git a/Runtime/GuiSys/CInstruction.hpp b/Runtime/GuiSys/CInstruction.hpp index 4b03d97f3..6c1dadbd7 100644 --- a/Runtime/GuiSys/CInstruction.hpp +++ b/Runtime/GuiSys/CInstruction.hpp @@ -5,199 +5,192 @@ #include "CFontImageDef.hpp" #include -namespace urde -{ +namespace urde { class CFontRenderState; class CTextRenderBuffer; class CFontImageDef; -class CInstruction -{ +class CInstruction { public: - virtual ~CInstruction() = default; - virtual void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const=0; - virtual void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - virtual void GetAssets(std::vector& assetsOut) const; - virtual size_t GetAssetCount() const; + virtual ~CInstruction() = default; + virtual void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const = 0; + virtual void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + virtual void GetAssets(std::vector& assetsOut) const; + virtual size_t GetAssetCount() const; }; -class CColorInstruction : public CInstruction -{ - EColorType x4_cType; - CTextColor x8_color; +class CColorInstruction : public CInstruction { + EColorType x4_cType; + CTextColor x8_color; + public: - CColorInstruction(EColorType tp, const CTextColor& color) - : x4_cType(tp), x8_color(color) {} - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + CColorInstruction(EColorType tp, const CTextColor& color) : x4_cType(tp), x8_color(color) {} + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -class CColorOverrideInstruction : public CInstruction -{ - int x4_overrideIdx; - CTextColor x8_color; +class CColorOverrideInstruction : public CInstruction { + int x4_overrideIdx; + CTextColor x8_color; + public: - CColorOverrideInstruction(int idx, const CTextColor& color) - : x4_overrideIdx(idx), x8_color(color) {} - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + CColorOverrideInstruction(int idx, const CTextColor& color) : x4_overrideIdx(idx), x8_color(color) {} + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -class CFontInstruction : public CInstruction -{ - TLockedToken x4_font; +class CFontInstruction : public CInstruction { + TLockedToken x4_font; + public: - CFontInstruction(const TToken& font) : x4_font(font) {} - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void GetAssets(std::vector& assetsOut) const; - size_t GetAssetCount() const; + CFontInstruction(const TToken& font) : x4_font(font) {} + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void GetAssets(std::vector& assetsOut) const; + size_t GetAssetCount() const; }; -class CLineExtraSpaceInstruction : public CInstruction -{ - s32 x4_extraSpace; +class CLineExtraSpaceInstruction : public CInstruction { + s32 x4_extraSpace; + public: - CLineExtraSpaceInstruction(s32 extraSpace) : x4_extraSpace(extraSpace) {} - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + CLineExtraSpaceInstruction(s32 extraSpace) : x4_extraSpace(extraSpace) {} + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -class CLineInstruction : public CInstruction -{ - friend class CTextExecuteBuffer; - friend class CTextInstruction; - friend class CImageInstruction; - friend class CWordInstruction; +class CLineInstruction : public CInstruction { + friend class CTextExecuteBuffer; + friend class CTextInstruction; + friend class CImageInstruction; + friend class CWordInstruction; + + s32 x4_wordCount = 0; + s32 x8_curX = 0; + s32 xc_curY = 0; + s32 x10_largestMonoHeight = 0; + s32 x14_largestMonoWidth = 0; + s32 x18_largestMonoBaseline = 0; + s32 x1c_largestImageHeight = 0; + s32 x20_largestImageWidth = 0; + s32 x24_largestImageBaseline = 0; + EJustification x28_just; + EVerticalJustification x2c_vjust; + bool x30_imageBaseline; - s32 x4_wordCount = 0; - s32 x8_curX = 0; - s32 xc_curY = 0; - s32 x10_largestMonoHeight = 0; - s32 x14_largestMonoWidth = 0; - s32 x18_largestMonoBaseline = 0; - s32 x1c_largestImageHeight = 0; - s32 x20_largestImageWidth = 0; - s32 x24_largestImageBaseline = 0; - EJustification x28_just; - EVerticalJustification x2c_vjust; - bool x30_imageBaseline; public: - CLineInstruction(EJustification just, EVerticalJustification vjust, bool imageBaseline) - : x28_just(just), x2c_vjust(vjust), x30_imageBaseline(imageBaseline) {} - void TestLargestFont(s32 w, s32 h, s32 b); - void TestLargestImage(s32 w, s32 h, s32 b); - void InvokeLTR(CFontRenderState& state) const; - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + CLineInstruction(EJustification just, EVerticalJustification vjust, bool imageBaseline) + : x28_just(just), x2c_vjust(vjust), x30_imageBaseline(imageBaseline) {} + void TestLargestFont(s32 w, s32 h, s32 b); + void TestLargestImage(s32 w, s32 h, s32 b); + void InvokeLTR(CFontRenderState& state) const; + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - s32 GetHeight() const - { - if (x10_largestMonoHeight && !x30_imageBaseline) - return x10_largestMonoHeight; - else - return x1c_largestImageHeight; - } + s32 GetHeight() const { + if (x10_largestMonoHeight && !x30_imageBaseline) + return x10_largestMonoHeight; + else + return x1c_largestImageHeight; + } - s32 GetBaseline() const - { - if (x10_largestMonoHeight && !x30_imageBaseline) - return x18_largestMonoBaseline; - else - return x24_largestImageBaseline; - } + s32 GetBaseline() const { + if (x10_largestMonoHeight && !x30_imageBaseline) + return x18_largestMonoBaseline; + else + return x24_largestImageBaseline; + } }; -class CLineSpacingInstruction : public CInstruction -{ - float x4_lineSpacing; +class CLineSpacingInstruction : public CInstruction { + float x4_lineSpacing; + public: - CLineSpacingInstruction(float spacing) : x4_lineSpacing(spacing) {} - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + CLineSpacingInstruction(float spacing) : x4_lineSpacing(spacing) {} + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -class CPopStateInstruction : public CInstruction -{ +class CPopStateInstruction : public CInstruction { public: - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -class CPushStateInstruction : public CInstruction -{ +class CPushStateInstruction : public CInstruction { public: - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -class CRemoveColorOverrideInstruction : public CInstruction -{ - int x4_idx; +class CRemoveColorOverrideInstruction : public CInstruction { + int x4_idx; + public: - CRemoveColorOverrideInstruction(int idx) : x4_idx(idx) {} - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + CRemoveColorOverrideInstruction(int idx) : x4_idx(idx) {} + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -class CImageInstruction : public CInstruction -{ - CFontImageDef x4_image; +class CImageInstruction : public CInstruction { + CFontImageDef x4_image; + public: - CImageInstruction(const CFontImageDef& image) : x4_image(image) {} - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void GetAssets(std::vector& assetsOut) const; - size_t GetAssetCount() const; + CImageInstruction(const CFontImageDef& image) : x4_image(image) {} + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void GetAssets(std::vector& assetsOut) const; + size_t GetAssetCount() const; }; -class CTextInstruction : public CInstruction -{ - std::u16string x4_str; /* used to be a placement-new sized allocation */ +class CTextInstruction : public CInstruction { + std::u16string x4_str; /* used to be a placement-new sized allocation */ public: - CTextInstruction(const char16_t* str, int len) : x4_str(str, len) {} - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + CTextInstruction(const char16_t* str, int len) : x4_str(str, len) {} + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -class CBlockInstruction : public CInstruction -{ - friend class CTextExecuteBuffer; - friend class CLineInstruction; - friend class CImageInstruction; - friend class CTextInstruction; - friend class CWordInstruction; +class CBlockInstruction : public CInstruction { + friend class CTextExecuteBuffer; + friend class CLineInstruction; + friend class CImageInstruction; + friend class CTextInstruction; + friend class CWordInstruction; + + s32 x4_offsetX; + s32 x8_offsetY; + s32 xc_blockExtentX; + s32 x10_blockExtentY; + ETextDirection x14_dir; + EJustification x18_justification; + EVerticalJustification x1c_vertJustification; + s32 x20_largestMonoW = 0; + s32 x24_largestMonoH = 0; + s32 x28_largestBaseline = 0; + s32 x2c_lineX = 0; + s32 x30_lineY = 0; + s32 x34_lineCount = 0; - s32 x4_offsetX; - s32 x8_offsetY; - s32 xc_blockExtentX; - s32 x10_blockExtentY; - ETextDirection x14_dir; - EJustification x18_justification; - EVerticalJustification x1c_vertJustification; - s32 x20_largestMonoW = 0; - s32 x24_largestMonoH = 0; - s32 x28_largestBaseline = 0; - s32 x2c_lineX = 0; - s32 x30_lineY = 0; - s32 x34_lineCount = 0; public: - CBlockInstruction(s32 offX, s32 offY, s32 extX, s32 extY, ETextDirection dir, - EJustification just, EVerticalJustification vjust) - : x4_offsetX(offX), x8_offsetY(offY), - xc_blockExtentX(extX), x10_blockExtentY(extY), x14_dir(dir), - x18_justification(just), x1c_vertJustification(vjust) {} - void TestLargestFont(s32 monoW, s32 monoH, s32 baseline); - void SetupPositionLTR(CFontRenderState& state) const; - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + CBlockInstruction(s32 offX, s32 offY, s32 extX, s32 extY, ETextDirection dir, EJustification just, + EVerticalJustification vjust) + : x4_offsetX(offX) + , x8_offsetY(offY) + , xc_blockExtentX(extX) + , x10_blockExtentY(extY) + , x14_dir(dir) + , x18_justification(just) + , x1c_vertJustification(vjust) {} + void TestLargestFont(s32 monoW, s32 monoH, s32 baseline); + void SetupPositionLTR(CFontRenderState& state) const; + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -class CWordInstruction : public CInstruction -{ +class CWordInstruction : public CInstruction { public: - void InvokeLTR(CFontRenderState& state) const; - void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; - void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void InvokeLTR(CFontRenderState& state) const; + void Invoke(CFontRenderState& state, CTextRenderBuffer* buf) const; + void PageInvoke(CFontRenderState& state, CTextRenderBuffer* buf) const; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/COrbitPointMarker.cpp b/Runtime/GuiSys/COrbitPointMarker.cpp index 91d4bc993..ebe61b0c6 100644 --- a/Runtime/GuiSys/COrbitPointMarker.cpp +++ b/Runtime/GuiSys/COrbitPointMarker.cpp @@ -7,106 +7,89 @@ #include "zeus/CEulerAngles.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { -COrbitPointMarker::COrbitPointMarker() -{ - x0_zOffset = g_tweakTargeting->GetOrbitPointZOffset(); - x28_orbitPointModel = g_SimplePool->GetObj("CMDL_OrbitPoint"); +COrbitPointMarker::COrbitPointMarker() { + x0_zOffset = g_tweakTargeting->GetOrbitPointZOffset(); + x28_orbitPointModel = g_SimplePool->GetObj("CMDL_OrbitPoint"); } -bool COrbitPointMarker::CheckLoadComplete() -{ - return x28_orbitPointModel.IsLoaded(); -} +bool COrbitPointMarker::CheckLoadComplete() { return x28_orbitPointModel.IsLoaded(); } -void COrbitPointMarker::Update(float dt, const CStateManager& mgr) -{ - x24_curTime += dt; - const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - CPlayer::EPlayerOrbitState orbitState = mgr.GetPlayer().GetOrbitState(); - bool freeOrbit = orbitState >= CPlayer::EPlayerOrbitState::OrbitPoint; - if (freeOrbit != x1c_lastFreeOrbit) - { - if (orbitState == CPlayer::EPlayerOrbitState::OrbitPoint || - orbitState == CPlayer::EPlayerOrbitState::OrbitCarcass) - { - ResetInterpolationTimer(g_tweakTargeting->GetOrbitPointInTime()); - zeus::CVector3f orbitTargetPosition = mgr.GetPlayer().GetHUDOrbitTargetPosition(); - if (!x4_camRelZPos) - x10_lagTargetPos = orbitTargetPosition + zeus::CVector3f(0.f, 0.f, x0_zOffset); - else - x10_lagTargetPos = zeus::CVector3f(orbitTargetPosition.x(), orbitTargetPosition.y(), - curCam->GetTranslation().z() + x0_zOffset); - x8_lagAzimuth = - zeus::CEulerAngles(zeus::CQuaternion(curCam->GetTransform().basis)).z() + zeus::degToRad(45.f); - } - else - { - ResetInterpolationTimer(g_tweakTargeting->GetOrbitPointOutTime()); - } - x1c_lastFreeOrbit = !x1c_lastFreeOrbit; - } - - if (x20_interpTimer > 0.f) - x20_interpTimer = std::max(0.f, x20_interpTimer - dt); - - if (!x4_camRelZPos) - { - zeus::CVector3f orbitTargetPosition = mgr.GetPlayer().GetHUDOrbitTargetPosition(); - if ((orbitTargetPosition.z() + x0_zOffset) - x10_lagTargetPos.z() < 0.1f) - x10_lagTargetPos = orbitTargetPosition + zeus::CVector3f(0.f, 0.f, x0_zOffset); - else if ((orbitTargetPosition.z() + x0_zOffset) - x10_lagTargetPos.z() < 0.f) - x10_lagTargetPos = zeus::CVector3f(orbitTargetPosition.x(), orbitTargetPosition.y(), x10_lagTargetPos.z() - 0.1f); - else - x10_lagTargetPos = zeus::CVector3f(orbitTargetPosition.x(), orbitTargetPosition.y(), x10_lagTargetPos.z() + 0.1f); - } - else - { - zeus::CVector3f orbitTargetPosition = mgr.GetPlayer().GetHUDOrbitTargetPosition(); +void COrbitPointMarker::Update(float dt, const CStateManager& mgr) { + x24_curTime += dt; + const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + CPlayer::EPlayerOrbitState orbitState = mgr.GetPlayer().GetOrbitState(); + bool freeOrbit = orbitState >= CPlayer::EPlayerOrbitState::OrbitPoint; + if (freeOrbit != x1c_lastFreeOrbit) { + if (orbitState == CPlayer::EPlayerOrbitState::OrbitPoint || + orbitState == CPlayer::EPlayerOrbitState::OrbitCarcass) { + ResetInterpolationTimer(g_tweakTargeting->GetOrbitPointInTime()); + zeus::CVector3f orbitTargetPosition = mgr.GetPlayer().GetHUDOrbitTargetPosition(); + if (!x4_camRelZPos) + x10_lagTargetPos = orbitTargetPosition + zeus::CVector3f(0.f, 0.f, x0_zOffset); + else x10_lagTargetPos = zeus::CVector3f(orbitTargetPosition.x(), orbitTargetPosition.y(), - x0_zOffset + orbitTargetPosition.z()); + curCam->GetTranslation().z() + x0_zOffset); + x8_lagAzimuth = zeus::CEulerAngles(zeus::CQuaternion(curCam->GetTransform().basis)).z() + zeus::degToRad(45.f); + } else { + ResetInterpolationTimer(g_tweakTargeting->GetOrbitPointOutTime()); } + x1c_lastFreeOrbit = !x1c_lastFreeOrbit; + } + if (x20_interpTimer > 0.f) + x20_interpTimer = std::max(0.f, x20_interpTimer - dt); + + if (!x4_camRelZPos) { + zeus::CVector3f orbitTargetPosition = mgr.GetPlayer().GetHUDOrbitTargetPosition(); + if ((orbitTargetPosition.z() + x0_zOffset) - x10_lagTargetPos.z() < 0.1f) + x10_lagTargetPos = orbitTargetPosition + zeus::CVector3f(0.f, 0.f, x0_zOffset); + else if ((orbitTargetPosition.z() + x0_zOffset) - x10_lagTargetPos.z() < 0.f) + x10_lagTargetPos = zeus::CVector3f(orbitTargetPosition.x(), orbitTargetPosition.y(), x10_lagTargetPos.z() - 0.1f); + else + x10_lagTargetPos = zeus::CVector3f(orbitTargetPosition.x(), orbitTargetPosition.y(), x10_lagTargetPos.z() + 0.1f); + } else { + zeus::CVector3f orbitTargetPosition = mgr.GetPlayer().GetHUDOrbitTargetPosition(); + x10_lagTargetPos = + zeus::CVector3f(orbitTargetPosition.x(), orbitTargetPosition.y(), x0_zOffset + orbitTargetPosition.z()); + } + + if (x1c_lastFreeOrbit) { + float newAzimuth = zeus::CEulerAngles(zeus::CQuaternion(curCam->GetTransform().basis)).z() + zeus::degToRad(45.f); + float aziDelta = newAzimuth - xc_azimuth; + if (mgr.GetPlayer().IsInFreeLook()) + x8_lagAzimuth += aziDelta; + xc_azimuth = newAzimuth; + } +} + +void COrbitPointMarker::Draw(const CStateManager& mgr) const { + if ((x1c_lastFreeOrbit || x20_interpTimer > 0.f) && g_tweakTargeting->DrawOrbitPoint() && + x28_orbitPointModel.IsLoaded()) { + const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + CGraphics::SetViewPointMatrix(camXf); + zeus::CFrustum frustum = mgr.SetupDrawFrustum(g_Viewport); + frustum.updatePlanes(camXf, zeus::SProjPersp(zeus::degToRad(curCam->GetFov()), + g_Viewport.x8_width / float(g_Viewport.xc_height), 1.f, 100.f)); + g_Renderer->SetClippingPlanes(frustum); + g_Renderer->SetPerspective(curCam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, + curCam->GetNearClipDistance(), curCam->GetFarClipDistance()); + float scale; if (x1c_lastFreeOrbit) - { - float newAzimuth = zeus::CEulerAngles(zeus::CQuaternion(curCam->GetTransform().basis)).z() + zeus::degToRad(45.f); - float aziDelta = newAzimuth - xc_azimuth; - if (mgr.GetPlayer().IsInFreeLook()) - x8_lagAzimuth += aziDelta; - xc_azimuth = newAzimuth; - } + scale = 1.f - x20_interpTimer / g_tweakTargeting->GetOrbitPointInTime(); + else + scale = x20_interpTimer / g_tweakTargeting->GetOrbitPointOutTime(); + zeus::CTransform modelXf = zeus::CTransform::RotateZ(x8_lagAzimuth); + modelXf.scaleBy(scale); + modelXf.origin += x10_lagTargetPos; + CGraphics::SetModelMatrix(modelXf); + zeus::CColor color = g_tweakTargeting->GetOrbitPointColor(); + color.a() *= scale; + CModelFlags flags(7, 0, 0, color); + x28_orbitPointModel->Draw(flags); + } } -void COrbitPointMarker::Draw(const CStateManager& mgr) const -{ - if ((x1c_lastFreeOrbit || x20_interpTimer > 0.f) && g_tweakTargeting->DrawOrbitPoint() && - x28_orbitPointModel.IsLoaded()) - { - const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - CGraphics::SetViewPointMatrix(camXf); - zeus::CFrustum frustum = mgr.SetupDrawFrustum(g_Viewport); - frustum.updatePlanes(camXf, zeus::SProjPersp(zeus::degToRad(curCam->GetFov()), - g_Viewport.x8_width / float(g_Viewport.xc_height), 1.f, 100.f)); - g_Renderer->SetClippingPlanes(frustum); - g_Renderer->SetPerspective(curCam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, - curCam->GetNearClipDistance(), curCam->GetFarClipDistance()); - float scale; - if (x1c_lastFreeOrbit) - scale = 1.f - x20_interpTimer / g_tweakTargeting->GetOrbitPointInTime(); - else - scale = x20_interpTimer / g_tweakTargeting->GetOrbitPointOutTime(); - zeus::CTransform modelXf = zeus::CTransform::RotateZ(x8_lagAzimuth); - modelXf.scaleBy(scale); - modelXf.origin += x10_lagTargetPos; - CGraphics::SetModelMatrix(modelXf); - zeus::CColor color = g_tweakTargeting->GetOrbitPointColor(); - color.a() *= scale; - CModelFlags flags(7, 0, 0, color); - x28_orbitPointModel->Draw(flags); - } -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/COrbitPointMarker.hpp b/Runtime/GuiSys/COrbitPointMarker.hpp index cb4495549..426a07f61 100644 --- a/Runtime/GuiSys/COrbitPointMarker.hpp +++ b/Runtime/GuiSys/COrbitPointMarker.hpp @@ -4,25 +4,24 @@ #include "CToken.hpp" #include "Graphics/CModel.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class COrbitPointMarker -{ - float x0_zOffset; - bool x4_camRelZPos = true; - float x8_lagAzimuth = 0.f; - float xc_azimuth = 0.f; - zeus::CVector3f x10_lagTargetPos; - bool x1c_lastFreeOrbit = false; - float x20_interpTimer = 0.f; - float x24_curTime = 0.f; - TLockedToken x28_orbitPointModel; - void ResetInterpolationTimer(float time) { x20_interpTimer = time; } +class COrbitPointMarker { + float x0_zOffset; + bool x4_camRelZPos = true; + float x8_lagAzimuth = 0.f; + float xc_azimuth = 0.f; + zeus::CVector3f x10_lagTargetPos; + bool x1c_lastFreeOrbit = false; + float x20_interpTimer = 0.f; + float x24_curTime = 0.f; + TLockedToken x28_orbitPointModel; + void ResetInterpolationTimer(float time) { x20_interpTimer = time; } + public: - COrbitPointMarker(); - bool CheckLoadComplete(); - void Update(float dt, const CStateManager& mgr); - void Draw(const CStateManager& mgr) const; + COrbitPointMarker(); + bool CheckLoadComplete(); + void Update(float dt, const CStateManager& mgr); + void Draw(const CStateManager& mgr) const; }; -} +} // namespace urde diff --git a/Runtime/GuiSys/CRasterFont.cpp b/Runtime/GuiSys/CRasterFont.cpp index c4e133cad..0628fa2b9 100644 --- a/Runtime/GuiSys/CRasterFont.cpp +++ b/Runtime/GuiSys/CRasterFont.cpp @@ -4,223 +4,200 @@ #include "Graphics/CTexture.hpp" #include "CSimplePool.hpp" -namespace urde -{ -CRasterFont::CRasterFont(urde::CInputStream& in, urde::IObjectStore& store) -{ - u32 magic; - in.readBytesToBuf(&magic, 4); - if (magic != SBIG('FONT')) - return; +namespace urde { +CRasterFont::CRasterFont(urde::CInputStream& in, urde::IObjectStore& store) { + u32 magic; + in.readBytesToBuf(&magic, 4); + if (magic != SBIG('FONT')) + return; - u32 version = in.readUint32Big(); - x4_monoWidth = in.readUint32Big(); - x8_monoHeight = in.readUint32Big(); + u32 version = in.readUint32Big(); + x4_monoWidth = in.readUint32Big(); + x8_monoHeight = in.readUint32Big(); - if (version >= 1) - x8c_baseline = in.readUint32Big(); - else - x8c_baseline = x8_monoHeight; + if (version >= 1) + x8c_baseline = in.readUint32Big(); + else + x8c_baseline = x8_monoHeight; - if (version >= 2) - x90_lineMargin = in.readUint32Big(); + if (version >= 2) + x90_lineMargin = in.readUint32Big(); - bool tmp1 = in.readBool(); - bool tmp2 = in.readBool(); + bool tmp1 = in.readBool(); + bool tmp2 = in.readBool(); - u32 tmp3 = in.readUint32Big(); - u32 tmp4 = in.readUint32Big(); - std::string name= in.readString(); - u32 txtrId = (version == 5 ? in.readUint64Big() : in.readUint32Big()); - x30_fontInfo = CFontInfo(tmp1, tmp2, tmp3, tmp4, name.c_str()); - x80_texture = store.GetObj({FOURCC('TXTR'), txtrId}); - x2c_mode = EColorType(in.readUint32Big()); + u32 tmp3 = in.readUint32Big(); + u32 tmp4 = in.readUint32Big(); + std::string name = in.readString(); + u32 txtrId = (version == 5 ? in.readUint64Big() : in.readUint32Big()); + x30_fontInfo = CFontInfo(tmp1, tmp2, tmp3, tmp4, name.c_str()); + x80_texture = store.GetObj({FOURCC('TXTR'), txtrId}); + x2c_mode = EColorType(in.readUint32Big()); - u32 glyphCount = in.readUint32Big(); - xc_glyphs.reserve(glyphCount); + u32 glyphCount = in.readUint32Big(); + xc_glyphs.reserve(glyphCount); - for (u32 i = 0 ; i < glyphCount ; ++i) - { - char16_t chr = in.readUint16Big(); - float startU = in.readFloatBig(); - float startV = in.readFloatBig(); - float endU = in.readFloatBig(); - float endV = in.readFloatBig(); - s32 layer = 0; - s32 a, b, c, cellWidth, cellHeight, baseline, kernStart; - if (version < 4) - { - a = in.readInt32Big(); - b = in.readInt32Big(); - c = in.readInt32Big(); - cellWidth = in.readInt32Big(); - cellHeight = in.readInt32Big(); - baseline = in.readInt32Big(); - kernStart = in.readInt32Big(); - } - else - { - layer = in.readByte(); - a = in.readByte(); - b = in.readByte(); - c = in.readByte(); - cellWidth = in.readByte(); - cellHeight = in.readByte(); - baseline = in.readByte(); - kernStart = in.readInt16Big(); - } - xc_glyphs.push_back(std::make_pair(chr, CGlyph(a, b, c, startU, startV, endU, endV, - cellWidth, cellHeight, baseline, kernStart, layer))); + for (u32 i = 0; i < glyphCount; ++i) { + char16_t chr = in.readUint16Big(); + float startU = in.readFloatBig(); + float startV = in.readFloatBig(); + float endU = in.readFloatBig(); + float endV = in.readFloatBig(); + s32 layer = 0; + s32 a, b, c, cellWidth, cellHeight, baseline, kernStart; + if (version < 4) { + a = in.readInt32Big(); + b = in.readInt32Big(); + c = in.readInt32Big(); + cellWidth = in.readInt32Big(); + cellHeight = in.readInt32Big(); + baseline = in.readInt32Big(); + kernStart = in.readInt32Big(); + } else { + layer = in.readByte(); + a = in.readByte(); + b = in.readByte(); + c = in.readByte(); + cellWidth = in.readByte(); + cellHeight = in.readByte(); + baseline = in.readByte(); + kernStart = in.readInt16Big(); } + xc_glyphs.push_back(std::make_pair( + chr, CGlyph(a, b, c, startU, startV, endU, endV, cellWidth, cellHeight, baseline, kernStart, layer))); + } - std::sort(xc_glyphs.begin(), xc_glyphs.end(), [=](auto& a, auto& b) -> bool{ - return a.first < b.first; - }); + std::sort(xc_glyphs.begin(), xc_glyphs.end(), [=](auto& a, auto& b) -> bool { return a.first < b.first; }); - u32 kernCount = in.readUint32Big(); - x1c_kerning.reserve(kernCount); + u32 kernCount = in.readUint32Big(); + x1c_kerning.reserve(kernCount); - for (u32 i = 0 ; i < kernCount ; ++i) - { - char16_t first = in.readUint16Big(); - char16_t second = in.readUint16Big(); - s32 howMuch = in.readInt32Big(); - x1c_kerning.emplace_back(first, second, howMuch); - } + for (u32 i = 0; i < kernCount; ++i) { + char16_t first = in.readUint16Big(); + char16_t second = in.readUint16Big(); + s32 howMuch = in.readInt32Big(); + x1c_kerning.emplace_back(first, second, howMuch); + } - if (magic == SBIG('FONT') && version <= 2) - x0_initialized = true; + if (magic == SBIG('FONT') && version <= 2) + x0_initialized = true; } void CRasterFont::SinglePassDrawString(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, - CTextRenderBuffer* renderBuf, const char16_t* str, s32 length) const -{ - if (!x0_initialized) - return; + CTextRenderBuffer* renderBuf, const char16_t* str, s32 length) const { + if (!x0_initialized) + return; - const char16_t* chr = str; - const CGlyph* prevGlyph = nullptr; - while (*chr != u'\0') - { - const CGlyph* glyph = GetGlyph(*chr); - if (glyph) - { - if (opts.x0_direction == ETextDirection::Horizontal) - { - x += glyph->GetLeftPadding(); + const char16_t* chr = str; + const CGlyph* prevGlyph = nullptr; + while (*chr != u'\0') { + const CGlyph* glyph = GetGlyph(*chr); + if (glyph) { + if (opts.x0_direction == ETextDirection::Horizontal) { + x += glyph->GetLeftPadding(); - if (prevGlyph != 0) - x += KernLookup(x1c_kerning, prevGlyph->GetKernStart(), *chr); - int left = 0; - int top = 0; + if (prevGlyph != 0) + x += KernLookup(x1c_kerning, prevGlyph->GetKernStart(), *chr); + int left = 0; + int top = 0; - if (renderBuf) - { - left += x; - top += y - glyph->GetBaseline(); - renderBuf->AddCharacter(zeus::CVector2i(left, top), *chr, opts.x4_colors[2]); - } - x += glyph->GetRightPadding() + glyph->GetAdvance(); - } + if (renderBuf) { + left += x; + top += y - glyph->GetBaseline(); + renderBuf->AddCharacter(zeus::CVector2i(left, top), *chr, opts.x4_colors[2]); } - prevGlyph = glyph; - chr++; - if (length == -1) - continue; - - if ((chr - str) >= length) - break; + x += glyph->GetRightPadding() + glyph->GetAdvance(); + } } + prevGlyph = glyph; + chr++; + if (length == -1) + continue; - xout = x; - yout = y; + if ((chr - str) >= length) + break; + } + + xout = x; + yout = y; } -void CRasterFont::DrawSpace(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, int len) const -{ - if (opts.x0_direction != ETextDirection::Horizontal) - return; +void CRasterFont::DrawSpace(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, int len) const { + if (opts.x0_direction != ETextDirection::Horizontal) + return; - xout = x + len; - yout = y; + xout = x + len; + yout = y; } void CRasterFont::DrawString(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, - CTextRenderBuffer* renderBuf, const char16_t* str, int len) const -{ - if (!x0_initialized) - return; + CTextRenderBuffer* renderBuf, const char16_t* str, int len) const { + if (!x0_initialized) + return; - if (renderBuf) - { - /* CGraphicsPalette pal = CGraphicsPalette::CGraphcisPalette(2, 4); */ - /* zeus::CColor color = zeus::CColor(0.f, 0.f, 0.f, 0.f) */ - /* tmp = color.ToRGB5A3(); */ - /* tmp2 = opts.x8_.ToRGB5A3(); */ - /* tmp3 = opts.xc_.ToRGB5A3(); */ - /* tmp4 = zeus::CColor(0.f, 0.f, 0.f, 0.f); */ - /* tmp5 = tmp4.ToRGBA5A3(); */ - /* pal.UnLock(); */ - /* renderBuf->AddPaletteChange(pal); */ - renderBuf->AddPaletteChange(opts.x4_colors[0], opts.x4_colors[1]); - } + if (renderBuf) { + /* CGraphicsPalette pal = CGraphicsPalette::CGraphcisPalette(2, 4); */ + /* zeus::CColor color = zeus::CColor(0.f, 0.f, 0.f, 0.f) */ + /* tmp = color.ToRGB5A3(); */ + /* tmp2 = opts.x8_.ToRGB5A3(); */ + /* tmp3 = opts.xc_.ToRGB5A3(); */ + /* tmp4 = zeus::CColor(0.f, 0.f, 0.f, 0.f); */ + /* tmp5 = tmp4.ToRGBA5A3(); */ + /* pal.UnLock(); */ + /* renderBuf->AddPaletteChange(pal); */ + renderBuf->AddPaletteChange(opts.x4_colors[0], opts.x4_colors[1]); + } - SinglePassDrawString(opts, x, y, xout, yout, renderBuf, str, len); + SinglePassDrawString(opts, x, y, xout, yout, renderBuf, str, len); } -void CRasterFont::GetSize(const CDrawStringOptions& opts, int& width, int& height, const char16_t* str, int len) const -{ - width = 0; - height = 0; +void CRasterFont::GetSize(const CDrawStringOptions& opts, int& width, int& height, const char16_t* str, int len) const { + width = 0; + height = 0; - const char16_t* chr = str; - const CGlyph* prevGlyph = nullptr; - int prevWidth = 0; - while (*chr != u'\0') - { - const CGlyph* glyph = GetGlyph(*chr); + const char16_t* chr = str; + const CGlyph* prevGlyph = nullptr; + int prevWidth = 0; + while (*chr != u'\0') { + const CGlyph* glyph = GetGlyph(*chr); - if (glyph) - { - if (opts.x0_direction == ETextDirection::Horizontal) - { - int advance = 0; - if (prevGlyph) - advance = KernLookup(x1c_kerning, prevGlyph->GetKernStart(), *chr); + if (glyph) { + if (opts.x0_direction == ETextDirection::Horizontal) { + int advance = 0; + if (prevGlyph) + advance = KernLookup(x1c_kerning, prevGlyph->GetKernStart(), *chr); - int curWidth = prevWidth + (glyph->GetLeftPadding() + glyph->GetAdvance() + glyph->GetRightPadding() + advance); - int curHeight = glyph->GetBaseline() - (x8_monoHeight + glyph->GetCellHeight()); + int curWidth = prevWidth + (glyph->GetLeftPadding() + glyph->GetAdvance() + glyph->GetRightPadding() + advance); + int curHeight = glyph->GetBaseline() - (x8_monoHeight + glyph->GetCellHeight()); - width = curWidth; - prevWidth = curWidth; + width = curWidth; + prevWidth = curWidth; - if (curHeight > height) - height = curHeight; - } - } - - prevGlyph = glyph; - chr++; - if (len == -1) - continue; - - if ((chr - str) >= len) - break; + if (curHeight > height) + height = curHeight; + } } + + prevGlyph = glyph; + chr++; + if (len == -1) + continue; + + if ((chr - str) >= len) + break; + } } -bool CRasterFont::IsFinishedLoading() const -{ - if (!x80_texture || !x80_texture.IsLoaded()) - return false; - return true; +bool CRasterFont::IsFinishedLoading() const { + if (!x80_texture || !x80_texture.IsLoaded()) + return false; + return true; } std::unique_ptr FRasterFontFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, - CObjectReference* selfRef) -{ - CSimplePool* sp = vparms.GetOwnedObj(); - return TToken::GetIObjObjectFor(std::make_unique(in, *sp)); + CObjectReference* selfRef) { + CSimplePool* sp = vparms.GetOwnedObj(); + return TToken::GetIObjObjectFor(std::make_unique(in, *sp)); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CRasterFont.hpp b/Runtime/GuiSys/CRasterFont.hpp index e66ab78ab..18b44530a 100644 --- a/Runtime/GuiSys/CRasterFont.hpp +++ b/Runtime/GuiSys/CRasterFont.hpp @@ -6,159 +6,148 @@ #include "CGuiTextSupport.hpp" #include "Graphics/CTexture.hpp" -namespace urde -{ +namespace urde { class IObjectStore; class CDrawStringOptions; class CTextRenderBuffer; /* NOTE: Is this a good place for CGlyph and CKernPair? */ -class CGlyph -{ +class CGlyph { private: - s16 x0_leftPadding; - s16 x2_advance; - s16 x4_rightPadding; - float x8_startU; - float xc_startV; - float x10_endU; - float x14_endV; - s16 x18_cellWidth; - s16 x1a_cellHeight; - s16 x1c_baseline; - s16 x1e_kernStart; - s16 m_layer; + s16 x0_leftPadding; + s16 x2_advance; + s16 x4_rightPadding; + float x8_startU; + float xc_startV; + float x10_endU; + float x14_endV; + s16 x18_cellWidth; + s16 x1a_cellHeight; + s16 x1c_baseline; + s16 x1e_kernStart; + s16 m_layer; public: - CGlyph() = default; - CGlyph(s16 a, s16 b, s32 c, float startU, float startV, float endU, float endV, - s16 cellWidth, s16 cellHeight, s16 baseline, s16 kernStart, s16 layer=0) - : x0_leftPadding(a), x2_advance(b), x4_rightPadding(c), - x8_startU(startU), xc_startV(startV), x10_endU(endU), x14_endV(endV), - x18_cellWidth(cellWidth), x1a_cellHeight(cellHeight), - x1c_baseline(baseline), x1e_kernStart(kernStart), m_layer(layer) - {} + CGlyph() = default; + CGlyph(s16 a, s16 b, s32 c, float startU, float startV, float endU, float endV, s16 cellWidth, s16 cellHeight, + s16 baseline, s16 kernStart, s16 layer = 0) + : x0_leftPadding(a) + , x2_advance(b) + , x4_rightPadding(c) + , x8_startU(startU) + , xc_startV(startV) + , x10_endU(endU) + , x14_endV(endV) + , x18_cellWidth(cellWidth) + , x1a_cellHeight(cellHeight) + , x1c_baseline(baseline) + , x1e_kernStart(kernStart) + , m_layer(layer) {} - s16 GetLeftPadding() const { return x0_leftPadding; } - s16 GetAdvance() const { return x2_advance; } - s16 GetRightPadding() const { return x4_rightPadding; } - float GetStartU() const { return x8_startU; } - float GetStartV() const { return xc_startV; } - float GetEndU() const { return x10_endU; } - float GetEndV() const { return x14_endV; } - s16 GetCellWidth() const { return x18_cellWidth; } - s16 GetCellHeight() const { return x1a_cellHeight; } - s16 GetBaseline() const { return x1c_baseline; } - s16 GetKernStart() const { return x1e_kernStart; } - s16 GetLayer() const { return m_layer; } + s16 GetLeftPadding() const { return x0_leftPadding; } + s16 GetAdvance() const { return x2_advance; } + s16 GetRightPadding() const { return x4_rightPadding; } + float GetStartU() const { return x8_startU; } + float GetStartV() const { return xc_startV; } + float GetEndU() const { return x10_endU; } + float GetEndV() const { return x14_endV; } + s16 GetCellWidth() const { return x18_cellWidth; } + s16 GetCellHeight() const { return x1a_cellHeight; } + s16 GetBaseline() const { return x1c_baseline; } + s16 GetKernStart() const { return x1e_kernStart; } + s16 GetLayer() const { return m_layer; } }; -class CKernPair -{ +class CKernPair { private: - char16_t x0_first; - char16_t x2_second; - s32 x4_howMuch; + char16_t x0_first; + char16_t x2_second; + s32 x4_howMuch; public: - CKernPair() = default; - CKernPair(char16_t first, char16_t second, s32 howMuch) - : x0_first(first), x2_second(second), x4_howMuch(howMuch) - {} + CKernPair() = default; + CKernPair(char16_t first, char16_t second, s32 howMuch) : x0_first(first), x2_second(second), x4_howMuch(howMuch) {} - char16_t GetFirst() const { return x0_first; } - char16_t GetSecond() const { return x2_second; } - s32 GetHowMuch() const { return x4_howMuch; } + char16_t GetFirst() const { return x0_first; } + char16_t GetSecond() const { return x2_second; } + s32 GetHowMuch() const { return x4_howMuch; } }; -class CFontInfo -{ - bool x0_ = false; - bool x1_ = false; - s32 x4_ = 0; - s32 x8_fontSize = 0; - char xc_name[40]; +class CFontInfo { + bool x0_ = false; + bool x1_ = false; + s32 x4_ = 0; + s32 x8_fontSize = 0; + char xc_name[40]; public: - CFontInfo() = default; - CFontInfo(bool a, bool b, s32 c, s32 fontSize, const char* name) - : x0_(a), x1_(b), x4_(c), x8_fontSize(fontSize) - { - strcpy(xc_name, name); - (void)x0_; - (void)x1_; - (void)x4_; - (void)x8_fontSize; - } + CFontInfo() = default; + CFontInfo(bool a, bool b, s32 c, s32 fontSize, const char* name) : x0_(a), x1_(b), x4_(c), x8_fontSize(fontSize) { + strcpy(xc_name, name); + (void)x0_; + (void)x1_; + (void)x4_; + (void)x8_fontSize; + } }; -class CRasterFont -{ - bool x0_initialized = false; - s32 x4_monoWidth = 16; - s32 x8_monoHeight = 16; - std::vector> xc_glyphs; - std::vector x1c_kerning; - EColorType x2c_mode = EColorType::Main; - CFontInfo x30_fontInfo; - TLockedToken x80_texture; - s32 x8c_baseline; - s32 x90_lineMargin = 0; +class CRasterFont { + bool x0_initialized = false; + s32 x4_monoWidth = 16; + s32 x8_monoHeight = 16; + std::vector> xc_glyphs; + std::vector x1c_kerning; + EColorType x2c_mode = EColorType::Main; + CFontInfo x30_fontInfo; + TLockedToken x80_texture; + s32 x8c_baseline; + s32 x90_lineMargin = 0; - const CGlyph* InternalGetGlyph(char16_t chr) const - { - u32 i = 0; - for (; i < xc_glyphs.size(); ++i) - if (chr == xc_glyphs[i].first) - break; + const CGlyph* InternalGetGlyph(char16_t chr) const { + u32 i = 0; + for (; i < xc_glyphs.size(); ++i) + if (chr == xc_glyphs[i].first) + break; - if (i == xc_glyphs.size()) - return nullptr; - return &xc_glyphs[i].second; - } + if (i == xc_glyphs.size()) + return nullptr; + return &xc_glyphs[i].second; + } public: - CRasterFont(CInputStream& in, IObjectStore& store); + CRasterFont(CInputStream& in, IObjectStore& store); - s32 GetMonoWidth() const { return x4_monoWidth; } - s32 GetMonoHeight() const { return x8_monoHeight; } - EColorType GetMode() const { return x2c_mode; } - s32 GetLineMargin() const { return x90_lineMargin; } - s32 GetCarriageAdvance() const { return GetLineMargin() + GetMonoHeight(); } + s32 GetMonoWidth() const { return x4_monoWidth; } + s32 GetMonoHeight() const { return x8_monoHeight; } + EColorType GetMode() const { return x2c_mode; } + s32 GetLineMargin() const { return x90_lineMargin; } + s32 GetCarriageAdvance() const { return GetLineMargin() + GetMonoHeight(); } - s32 GetBaseline() const { return x8c_baseline; } - static s32 KernLookup(const std::vector& kernTable, s32 kernStart, char16_t chr) - { - auto iter = kernTable.cbegin() + kernStart; - for (; iter != kernTable.cend() && iter->GetFirst() == kernTable[kernStart].GetFirst() ; ++iter) - { - if (iter->GetSecond() == chr) - return iter->GetHowMuch(); - } - - return 0; + s32 GetBaseline() const { return x8c_baseline; } + static s32 KernLookup(const std::vector& kernTable, s32 kernStart, char16_t chr) { + auto iter = kernTable.cbegin() + kernStart; + for (; iter != kernTable.cend() && iter->GetFirst() == kernTable[kernStart].GetFirst(); ++iter) { + if (iter->GetSecond() == chr) + return iter->GetHowMuch(); } + return 0; + } - void SinglePassDrawString(const CDrawStringOptions&, int x, int y, int& xout, int& yout, - CTextRenderBuffer* renderBuf, const char16_t* str, s32 len) const; - void DrawSpace(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, int len) const; - void DrawString(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, - CTextRenderBuffer* renderBuf, - const char16_t* str, int len) const; - const CGlyph* GetGlyph(char16_t chr) const - { - return InternalGetGlyph(chr); - } - void GetSize(const CDrawStringOptions& opts, int& width, int& height, - const char16_t* str, int len) const; - const boo::ObjToken& GetTexture() - { return x80_texture->GetFontTexture(CTexture::EFontType(x2c_mode)); } + void SinglePassDrawString(const CDrawStringOptions&, int x, int y, int& xout, int& yout, CTextRenderBuffer* renderBuf, + const char16_t* str, s32 len) const; + void DrawSpace(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, int len) const; + void DrawString(const CDrawStringOptions& opts, int x, int y, int& xout, int& yout, CTextRenderBuffer* renderBuf, + const char16_t* str, int len) const; + const CGlyph* GetGlyph(char16_t chr) const { return InternalGetGlyph(chr); } + void GetSize(const CDrawStringOptions& opts, int& width, int& height, const char16_t* str, int len) const; + const boo::ObjToken& GetTexture() { + return x80_texture->GetFontTexture(CTexture::EFontType(x2c_mode)); + } - bool IsFinishedLoading() const; + bool IsFinishedLoading() const; }; std::unique_ptr FRasterFontFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/GuiSys/CSaveableState.cpp b/Runtime/GuiSys/CSaveableState.cpp index 8c5219762..82afcc89b 100644 --- a/Runtime/GuiSys/CSaveableState.cpp +++ b/Runtime/GuiSys/CSaveableState.cpp @@ -1,14 +1,12 @@ #include "CSaveableState.hpp" #include "CRasterFont.hpp" -namespace urde -{ +namespace urde { -bool CSaveableState::IsFinishedLoading() const -{ - if (!x48_font || !x48_font.IsLoaded()) - return false; - return x48_font->IsFinishedLoading(); +bool CSaveableState::IsFinishedLoading() const { + if (!x48_font || !x48_font.IsLoaded()) + return false; + return x48_font->IsFinishedLoading(); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CSaveableState.hpp b/Runtime/GuiSys/CSaveableState.hpp index 976cba669..6a4cf89c1 100644 --- a/Runtime/GuiSys/CSaveableState.hpp +++ b/Runtime/GuiSys/CSaveableState.hpp @@ -5,41 +5,38 @@ #include "CToken.hpp" #include "zeus/CColor.hpp" -namespace urde -{ +namespace urde { class CRasterFont; -class CSaveableState -{ - friend class CTextExecuteBuffer; - friend class CColorOverrideInstruction; - friend class CFontInstruction; - friend class CLineExtraSpaceInstruction; - friend class CTextInstruction; - friend class CLineSpacingInstruction; - friend class CRemoveColorOverrideInstruction; - friend class CWordInstruction; - friend class CGuiTextSupport; +class CSaveableState { + friend class CTextExecuteBuffer; + friend class CColorOverrideInstruction; + friend class CFontInstruction; + friend class CLineExtraSpaceInstruction; + friend class CTextInstruction; + friend class CLineSpacingInstruction; + friend class CRemoveColorOverrideInstruction; + friend class CWordInstruction; + friend class CGuiTextSupport; + protected: - CDrawStringOptions x0_drawStrOpts; - TLockedToken x48_font; - std::vector x54_colors; - std::vector x64_colorOverrides; - float x74_lineSpacing = 1.f; - s32 x78_extraLineSpace = 0; - bool x7c_enableWordWrap = false; - EJustification x80_just = EJustification::Left; - EVerticalJustification x84_vjust = EVerticalJustification::Top; + CDrawStringOptions x0_drawStrOpts; + TLockedToken x48_font; + std::vector x54_colors; + std::vector x64_colorOverrides; + float x74_lineSpacing = 1.f; + s32 x78_extraLineSpace = 0; + bool x7c_enableWordWrap = false; + EJustification x80_just = EJustification::Left; + EVerticalJustification x84_vjust = EVerticalJustification::Top; public: - CSaveableState() - { - x54_colors.resize(3, zeus::CColor::skBlack); - x64_colorOverrides.resize(16); - } + CSaveableState() { + x54_colors.resize(3, zeus::CColor::skBlack); + x64_colorOverrides.resize(16); + } - bool IsFinishedLoading() const; + bool IsFinishedLoading() const; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CScanDisplay.cpp b/Runtime/GuiSys/CScanDisplay.cpp index 2890159cf..0430e53f9 100644 --- a/Runtime/GuiSys/CScanDisplay.cpp +++ b/Runtime/GuiSys/CScanDisplay.cpp @@ -14,486 +14,415 @@ #include "Input/CFinalInput.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ -void CScanDisplay::CDataDot::Update(float dt) -{ - if (x20_remTime > 0.f) - { - x20_remTime = std::max(0.f, x20_remTime - dt); - float d = 0.f; - if (x1c_transDur > 0.f) - d = x20_remTime / x1c_transDur; - xc_curPos = zeus::CVector2f::lerp(x14_targetPos, x4_startPos, d); - } +namespace urde { +void CScanDisplay::CDataDot::Update(float dt) { + if (x20_remTime > 0.f) { + x20_remTime = std::max(0.f, x20_remTime - dt); + float d = 0.f; + if (x1c_transDur > 0.f) + d = x20_remTime / x1c_transDur; + xc_curPos = zeus::CVector2f::lerp(x14_targetPos, x4_startPos, d); + } - if (x24_alpha > x28_desiredAlpha) - { - float tmp = x24_alpha - 2.f * dt; - x24_alpha = std::max(tmp, x28_desiredAlpha); - } - else if (x24_alpha < x28_desiredAlpha) - { - float tmp = 2.f * dt + x24_alpha; - x24_alpha = std::min(tmp, x28_desiredAlpha); - } + if (x24_alpha > x28_desiredAlpha) { + float tmp = x24_alpha - 2.f * dt; + x24_alpha = std::max(tmp, x28_desiredAlpha); + } else if (x24_alpha < x28_desiredAlpha) { + float tmp = 2.f * dt + x24_alpha; + x24_alpha = std::min(tmp, x28_desiredAlpha); + } } -void CScanDisplay::CDataDot::Draw(const zeus::CColor& col, float radius) const -{ - if (x24_alpha == 0.f) - return; +void CScanDisplay::CDataDot::Draw(const zeus::CColor& col, float radius) const { + if (x24_alpha == 0.f) + return; - if (x0_dotState != EDotState::Hidden) - { - zeus::CTransform xf = zeus::CTransform::Translate(xc_curPos.x(), 0.f, xc_curPos.y()); - CGraphics::SetModelMatrix(xf); - zeus::CColor useColor = col; - useColor.a() *= x24_alpha; - CTexturedQuadFilter::Vert verts[4] = - { - {{-radius, 0.f, radius}, {0.f, 1.f}}, - {{-radius, 0.f, -radius}, {0.f, 0.f}}, - {{radius, 0.f, radius}, {1.f, 1.f}}, - {{radius, 0.f, -radius}, {1.f, 0.f}} - }; - const_cast(m_quad).drawVerts(useColor, verts); + if (x0_dotState != EDotState::Hidden) { + zeus::CTransform xf = zeus::CTransform::Translate(xc_curPos.x(), 0.f, xc_curPos.y()); + CGraphics::SetModelMatrix(xf); + zeus::CColor useColor = col; + useColor.a() *= x24_alpha; + CTexturedQuadFilter::Vert verts[4] = {{{-radius, 0.f, radius}, {0.f, 1.f}}, + {{-radius, 0.f, -radius}, {0.f, 0.f}}, + {{radius, 0.f, radius}, {1.f, 1.f}}, + {{radius, 0.f, -radius}, {1.f, 0.f}}}; + const_cast(m_quad).drawVerts(useColor, verts); + } +} + +void CScanDisplay::CDataDot::StartTransitionTo(const zeus::CVector2f& vec, float dur) { + x20_remTime = dur; + x1c_transDur = dur; + x4_startPos = xc_curPos; + x14_targetPos = vec; +} + +void CScanDisplay::CDataDot::SetDestPosition(const zeus::CVector2f& pos) { + if (x20_remTime <= 0.f) + xc_curPos = pos; + else + x14_targetPos = pos; +} + +CScanDisplay::CScanDisplay(const CGuiFrame& selHud) : xa0_selHud(selHud) { + x0_dataDot = g_SimplePool->GetObj("TXTR_DataDot"); + for (int i = 0; i < 4; ++i) + xbc_dataDots.emplace_back(x0_dataDot); + x170_paneStates.resize(4); +} + +void CScanDisplay::ProcessInput(const CFinalInput& input) { + if (xc_state == EScanState::Inactive || xc_state == EScanState::Done) + return; + + if (xc_state == EScanState::DownloadComplete && x1a4_xAlpha == 0.f) { + if (input.PA()) { + if (xa8_message->TextSupport().GetCurTime() < xa8_message->TextSupport().GetTotalAnimationTime()) { + xa8_message->TextSupport().SetCurTime(xa8_message->TextSupport().GetTotalAnimationTime()); + } else { + xc_state = EScanState::ViewingScan; + x1a4_xAlpha = 1.f; + CSfxManager::SfxStart(SFXui_scan_next_page, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } } -} + } else if (xc_state == EScanState::ViewingScan) { + int oldCounter = x1ac_pageCounter; + int totalPages = xac_scrollMessage->TextSupport().GetTotalPageCount(); + if (input.PA() && totalPages != -1) { + CGuiTextSupport& supp = !x1ac_pageCounter ? xa8_message->TextSupport() : xac_scrollMessage->TextSupport(); + if (supp.GetCurTime() < supp.GetTotalAnimationTime()) + supp.SetCurTime(supp.GetTotalAnimationTime()); + else + x1ac_pageCounter = std::min(totalPages, x1ac_pageCounter + 1); + } + if (x1ac_pageCounter != oldCounter) { + CSfxManager::SfxStart(SFXui_scan_next_page, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + if (x1ac_pageCounter == 0) { + xa8_message->SetIsVisible(true); + xac_scrollMessage->SetIsVisible(false); + } else { + if (oldCounter == 0) { + xa8_message->SetIsVisible(false); + xac_scrollMessage->SetIsVisible(true); + } + xac_scrollMessage->TextSupport().SetPage(x1ac_pageCounter - 1); + SetScanMessageTypeEffect(xac_scrollMessage, !x1b4_scanComplete); + } + } + } -void CScanDisplay::CDataDot::StartTransitionTo(const zeus::CVector2f& vec, float dur) -{ - x20_remTime = dur; - x1c_transDur = dur; - x4_startPos = xc_curPos; - x14_targetPos = vec; -} - -void CScanDisplay::CDataDot::SetDestPosition(const zeus::CVector2f& pos) -{ - if (x20_remTime <= 0.f) - xc_curPos = pos; + float xAlpha = 0.f; + float aAlpha = 0.f; + float dashAlpha = 0.f; + if (xc_state == EScanState::DownloadComplete) { + xAlpha = std::min(2.f * x1a4_xAlpha, 1.f); + aAlpha = (1.f - xAlpha) * std::fabs(x1b0_aPulse); + } else if (xc_state == EScanState::ViewingScan) { + if (x1ac_pageCounter < xac_scrollMessage->TextSupport().GetTotalPageCount()) + aAlpha = std::fabs(x1b0_aPulse); else - x14_targetPos = pos; + dashAlpha = 1.f; + } + + xb0_xmark->SetVisibility(xAlpha > 0.f, ETraversalMode::Children); + xb4_abutton->SetVisibility(aAlpha > 0.f, ETraversalMode::Children); + xb8_dash->SetVisibility(dashAlpha > 0.f, ETraversalMode::Children); + + xb0_xmark->SetColor(zeus::CColor(1.f, xAlpha)); + xb4_abutton->SetColor(zeus::CColor(1.f, aAlpha)); + xb8_dash->SetColor(zeus::CColor(0.53f, 0.84f, 1.f, dashAlpha)); } -CScanDisplay::CScanDisplay(const CGuiFrame& selHud) -: xa0_selHud(selHud) -{ - x0_dataDot = g_SimplePool->GetObj("TXTR_DataDot"); - for (int i=0 ; i<4 ; ++i) - xbc_dataDots.emplace_back(x0_dataDot); - x170_paneStates.resize(4); +float CScanDisplay::GetDownloadStartTime(int idx) const { + if (!x14_scannableInfo) + return 0.f; + float nTime = x14_scannableInfo->GetBucket(idx).x4_appearanceRange; + float maxTime = 0.f; + for (int i = 0; i < 4; ++i) { + float iTime = x14_scannableInfo->GetBucket(i).x4_appearanceRange; + if (iTime < nTime) + maxTime = std::max(iTime, maxTime); + } + return maxTime + g_tweakGui->GetScanAppearanceDuration(); } -void CScanDisplay::ProcessInput(const CFinalInput& input) -{ - if (xc_state == EScanState::Inactive || xc_state == EScanState::Done) - return; - - if (xc_state == EScanState::DownloadComplete && x1a4_xAlpha == 0.f) - { - if (input.PA()) - { - if (xa8_message->TextSupport().GetCurTime() < xa8_message->TextSupport().GetTotalAnimationTime()) - { - xa8_message->TextSupport().SetCurTime(xa8_message->TextSupport().GetTotalAnimationTime()); - } - else - { - xc_state = EScanState::ViewingScan; - x1a4_xAlpha = 1.f; - CSfxManager::SfxStart(SFXui_scan_next_page, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - } - } - else if (xc_state == EScanState::ViewingScan) - { - int oldCounter = x1ac_pageCounter; - int totalPages = xac_scrollMessage->TextSupport().GetTotalPageCount(); - if (input.PA() && totalPages != -1) - { - CGuiTextSupport& supp = !x1ac_pageCounter ? xa8_message->TextSupport() : xac_scrollMessage->TextSupport(); - if (supp.GetCurTime() < supp.GetTotalAnimationTime()) - supp.SetCurTime(supp.GetTotalAnimationTime()); - else - x1ac_pageCounter = std::min(totalPages, x1ac_pageCounter + 1); - } - if (x1ac_pageCounter != oldCounter) - { - CSfxManager::SfxStart(SFXui_scan_next_page, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - if (x1ac_pageCounter == 0) - { - xa8_message->SetIsVisible(true); - xac_scrollMessage->SetIsVisible(false); - } - else - { - if (oldCounter == 0) - { - xa8_message->SetIsVisible(false); - xac_scrollMessage->SetIsVisible(true); - } - xac_scrollMessage->TextSupport().SetPage(x1ac_pageCounter - 1); - SetScanMessageTypeEffect(xac_scrollMessage, !x1b4_scanComplete); - } - } - } - - float xAlpha = 0.f; - float aAlpha = 0.f; - float dashAlpha = 0.f; - if (xc_state == EScanState::DownloadComplete) - { - xAlpha = std::min(2.f * x1a4_xAlpha, 1.f); - aAlpha = (1.f - xAlpha) * std::fabs(x1b0_aPulse); - } - else if (xc_state == EScanState::ViewingScan) - { - if (x1ac_pageCounter < xac_scrollMessage->TextSupport().GetTotalPageCount()) - aAlpha = std::fabs(x1b0_aPulse); - else - dashAlpha = 1.f; - } - - xb0_xmark->SetVisibility(xAlpha > 0.f, ETraversalMode::Children); - xb4_abutton->SetVisibility(aAlpha > 0.f, ETraversalMode::Children); - xb8_dash->SetVisibility(dashAlpha > 0.f, ETraversalMode::Children); - - xb0_xmark->SetColor(zeus::CColor(1.f, xAlpha)); - xb4_abutton->SetColor(zeus::CColor(1.f, aAlpha)); - xb8_dash->SetColor(zeus::CColor(0.53f, 0.84f, 1.f, dashAlpha)); -} - -float CScanDisplay::GetDownloadStartTime(int idx) const -{ - if (!x14_scannableInfo) - return 0.f; - float nTime = x14_scannableInfo->GetBucket(idx).x4_appearanceRange; - float maxTime = 0.f; - for (int i=0 ; i<4 ; ++i) - { - float iTime = x14_scannableInfo->GetBucket(i).x4_appearanceRange; - if (iTime < nTime) - maxTime = std::max(iTime, maxTime); - } - return maxTime + g_tweakGui->GetScanAppearanceDuration(); -} - -float CScanDisplay::GetDownloadFraction(int idx, float scanningTime) const -{ - if (!x14_scannableInfo) - return 0.f; - float appearTime = GetDownloadStartTime(idx); - float appearRange = x14_scannableInfo->GetBucket(idx).x4_appearanceRange; - if (appearTime == appearRange) - return 1.f; - return zeus::clamp(0.f, (scanningTime - appearTime) / (appearRange - appearTime), 1.f); +float CScanDisplay::GetDownloadFraction(int idx, float scanningTime) const { + if (!x14_scannableInfo) + return 0.f; + float appearTime = GetDownloadStartTime(idx); + float appearRange = x14_scannableInfo->GetBucket(idx).x4_appearanceRange; + if (appearTime == appearRange) + return 1.f; + return zeus::clamp(0.f, (scanningTime - appearTime) / (appearRange - appearTime), 1.f); } void CScanDisplay::StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo, CGuiTextPane* message, - CGuiTextPane* scrollMessage, CGuiWidget* textGroup, CGuiModel* xmark, - CGuiModel* abutton, CGuiModel* dash, float scanTime) -{ - x1b4_scanComplete = scanTime >= scanInfo.GetTotalDownloadTime(); - x14_scannableInfo.emplace(scanInfo); - x10_objId = id; - xc_state = EScanState::Downloading; + CGuiTextPane* scrollMessage, CGuiWidget* textGroup, CGuiModel* xmark, CGuiModel* abutton, + CGuiModel* dash, float scanTime) { + x1b4_scanComplete = scanTime >= scanInfo.GetTotalDownloadTime(); + x14_scannableInfo.emplace(scanInfo); + x10_objId = id; + xc_state = EScanState::Downloading; + x1ac_pageCounter = 0; + x1a4_xAlpha = 0.f; + xa8_message = message; + xac_scrollMessage = scrollMessage; + xa4_textGroup = textGroup; + xb0_xmark = xmark; + xb4_abutton = abutton; + xb8_dash = dash; + xa4_textGroup->SetVisibility(true, ETraversalMode::Children); + xa4_textGroup->SetColor(zeus::CColor(1.f, 0.f)); + + for (int i = 0; i < 20; ++i) { + CAuiImagePane* pane = + static_cast(xa0_selHud.FindWidget(MP1::CPauseScreenBase::GetImagePaneName(i))); + zeus::CColor color = g_tweakGuiColors->GetScanDisplayImagePaneColor(); + color.a() = 0.f; + pane->SetColor(color); + pane->SetTextureID0(-1, g_SimplePool); + pane->SetAnimationParms(zeus::CVector2f::skZero, 0.f, 0.f); + int pos = -1; + for (int j = 0; j < 4; ++j) { + if (x14_scannableInfo->GetBucket(j).x8_imagePos == i) { + pos = j; + break; + } + } + if (pos >= 0) + x170_paneStates[pos].second = pane; + } + + for (int i = 0; i < x170_paneStates.size(); ++i) { + std::pair& state = x170_paneStates[i]; + if (state.second) { + const CScannableObjectInfo::SBucket& bucket = x14_scannableInfo->GetBucket(i); + if (bucket.x14_interval > 0.f) { + state.second->SetAnimationParms(zeus::CVector2f(bucket.xc_size.x, bucket.xc_size.y), bucket.x14_interval, + bucket.x18_fadeDuration); + } + state.second->SetTextureID0(bucket.x0_texture, g_SimplePool); + state.second->SetFlashFactor(0.f); + float startTime = GetDownloadStartTime(i); + if (scanTime >= startTime) + x170_paneStates[i].first = 0.f; + else + x170_paneStates[i].first = -1.f; + } + } + + CAssetId strId = x14_scannableInfo->GetStringTableId(); + if (strId.IsValid()) + x194_scanStr = g_SimplePool->GetObj({FOURCC('STRG'), strId}); + + for (int i = 0; i < 4; ++i) { + int pos = x14_scannableInfo->GetBucket(i).x8_imagePos; + CDataDot& dot = xbc_dataDots[i]; + if (pos != -1) { + if (GetDownloadStartTime(i) - g_tweakGui->GetScanAppearanceDuration() < scanTime) { + dot.SetAlpha(0.f); + dot.SetDotState(CDataDot::EDotState::Done); + } else { + dot.SetDesiredAlpha(1.f); + dot.SetDotState(CDataDot::EDotState::Seek); + dot.StartTransitionTo(zeus::CVector2f::skZero, FLT_EPSILON); + dot.Update(FLT_EPSILON); + } + } else { + dot.SetDotState(CDataDot::EDotState::Hidden); + } + } +} + +void CScanDisplay::StopScan() { + if (xc_state == EScanState::Done || xc_state == EScanState::Inactive) + return; + + xc_state = EScanState::Done; + for (int i = 0; i < 4; ++i) + xbc_dataDots[i].SetDesiredAlpha(0.f); +} + +void CScanDisplay::SetScanMessageTypeEffect(CGuiTextPane* pane, bool type) { + if (type) + pane->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, 60.f); + else + pane->TextSupport().SetTypeWriteEffectOptions(false, 0.f, 0.f); +} + +void CScanDisplay::Update(float dt, float scanningTime) { + if (xc_state == EScanState::Inactive) + return; + + bool active = false; + if (xc_state == EScanState::Done) { + x1a8_bodyAlpha = std::max(0.f, x1a8_bodyAlpha - 2.f * dt); + if (x1a8_bodyAlpha > 0.f) + active = true; + } else { + active = true; + x1a8_bodyAlpha = std::min(x1a8_bodyAlpha + 2.f * dt, 1.f); + if (xc_state == EScanState::DownloadComplete) { + if (xac_scrollMessage->TextSupport().GetIsTextSupportFinishedLoading()) + x1a4_xAlpha = std::max(0.f, x1a4_xAlpha - dt); + if (x1a4_xAlpha < 0.5f) { + x1b0_aPulse += 2.f * dt; + if (x1b0_aPulse > 1.f) + x1b0_aPulse -= 2.f; + } + } else if (xc_state == EScanState::ViewingScan) { + x1b0_aPulse += 2.f * dt; + if (x1b0_aPulse > 1.f) + x1b0_aPulse -= 2.f; + if (x1a4_xAlpha == 1.f) { + xa8_message->TextSupport().SetText(x194_scanStr->GetString(0)); + SetScanMessageTypeEffect(xa8_message, !x1b4_scanComplete); + } + } else if (xc_state == EScanState::Downloading && scanningTime >= x14_scannableInfo->GetTotalDownloadTime() && + x194_scanStr.IsLoaded()) { + if (x1b4_scanComplete || x14_scannableInfo->GetCategory() == 0) { + xc_state = EScanState::ViewingScan; + x1b0_aPulse = x1a4_xAlpha = 1.f; + CSfxManager::SfxStart(SFXui_scan_complete, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else { + xc_state = EScanState::DownloadComplete; + x1b0_aPulse = x1a4_xAlpha = 1.f; + xa8_message->TextSupport().SetText(std::u16string(g_MainStringTable->GetString(29)) + + g_MainStringTable->GetString(x14_scannableInfo->GetCategory() + 30) + + g_MainStringTable->GetString(30)); + SetScanMessageTypeEffect(xa8_message, true); + CSfxManager::SfxStart(SFXui_new_scan_complete, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + + if (x194_scanStr->GetStringCount() > 2) { + xac_scrollMessage->TextSupport().SetText(x194_scanStr->GetString(2), true); + SetScanMessageTypeEffect(xac_scrollMessage, !x1b4_scanComplete); + } + xac_scrollMessage->SetIsVisible(false); + } + } + + for (int i = 0; i < 4; ++i) { + if (x170_paneStates[i].second == 0) + continue; + if (x170_paneStates[i].first > 0.f) { + x170_paneStates[i].first = std::max(0.f, x170_paneStates[i].first - dt); + float tmp; + if (x170_paneStates[i].first > g_tweakGui->GetScanPaneFadeOutTime()) + tmp = 1.f - + (x170_paneStates[i].first - g_tweakGui->GetScanPaneFadeOutTime()) / g_tweakGui->GetScanPaneFadeInTime(); + else + tmp = x170_paneStates[i].first / g_tweakGui->GetScanPaneFadeOutTime(); + x170_paneStates[i].second->SetFlashFactor(tmp * g_tweakGui->GetScanPaneFlashFactor() * x1a8_bodyAlpha); + } + float alphaMul = + ((xc_state == EScanState::Downloading) ? GetDownloadFraction(i, scanningTime) : 1.f) * x1a8_bodyAlpha; + zeus::CColor color = g_tweakGuiColors->GetScanDisplayImagePaneColor(); + color.a() *= alphaMul; + x170_paneStates[i].second->SetColor(color); + x170_paneStates[i].second->SetDeResFactor(1.f - alphaMul); + if (GetDownloadStartTime(i) - g_tweakGui->GetScanAppearanceDuration() < scanningTime) { + CDataDot& dot = xbc_dataDots[i]; + switch (dot.GetDotState()) { + case CDataDot::EDotState::Seek: + case CDataDot::EDotState::Hold: + dot.SetDotState(CDataDot::EDotState::RevealPane); + dot.StartTransitionTo(zeus::CVector2f::skZero, g_tweakGui->GetScanAppearanceDuration()); + break; + case CDataDot::EDotState::RevealPane: { + float tmp = dot.GetTransitionFactor(); + if (tmp == 0.f) { + dot.SetDotState(CDataDot::EDotState::Done); + dot.SetDesiredAlpha(0.f); + CSfxManager::SfxStart(SFXui_scan_pane_reveal, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x170_paneStates[i].first = g_tweakGui->GetScanPaneFadeOutTime() + g_tweakGui->GetScanPaneFadeInTime(); + } + break; + } + default: + break; + } + } + } + + for (int i = 0; i < 4; ++i) { + CDataDot& dot = xbc_dataDots[i]; + switch (dot.GetDotState()) { + case CDataDot::EDotState::Hidden: + continue; + case CDataDot::EDotState::Seek: + case CDataDot::EDotState::Hold: { + float tmp = dot.GetTransitionFactor(); + if (tmp == 0.f) { + float vpRatio = g_Viewport.xc_height / 480.f; + float posRand = g_tweakGui->GetScanDataDotPosRandMagnitude() * vpRatio; + float durMin = dot.GetDotState() == CDataDot::EDotState::Hold ? g_tweakGui->GetScanDataDotHoldDurationMin() + : g_tweakGui->GetScanDataDotSeekDurationMin(); + float durMax = dot.GetDotState() == CDataDot::EDotState::Hold ? g_tweakGui->GetScanDataDotHoldDurationMax() + : g_tweakGui->GetScanDataDotSeekDurationMax(); + zeus::CVector2f vec( + dot.GetDotState() == CDataDot::EDotState::Hold ? dot.GetCurrPosition().x() + : (posRand * (rand() / float(RAND_MAX)) - 0.5f * posRand), + dot.GetDotState() == CDataDot::EDotState::Hold ? dot.GetCurrPosition().y() + : (posRand * (rand() / float(RAND_MAX)) - 0.5f * posRand)); + float dur = (durMax - durMin) * (rand() / float(RAND_MAX)) + durMin; + dot.StartTransitionTo(vec, dur); + dot.SetDotState(dot.GetDotState() == CDataDot::EDotState::Hold ? CDataDot::EDotState::Seek + : CDataDot::EDotState::Hold); + } + break; + } + case CDataDot::EDotState::RevealPane: + case CDataDot::EDotState::Done: { + const zeus::CVector3f& panePos = x170_paneStates[i].second->GetWorldPosition(); + zeus::CVector3f screenPos = xa0_selHud.GetFrameCamera()->ConvertToScreenSpace(panePos); + zeus::CVector2f viewportCoords(screenPos.x() * g_Viewport.x8_width * 0.5f, + screenPos.y() * g_Viewport.xc_height * 0.5f); + dot.SetDestPosition(viewportCoords); + break; + } + default: + break; + } + dot.Update(dt); + } + + if (!active) { + xc_state = EScanState::Inactive; + x10_objId = kInvalidUniqueId; + x14_scannableInfo = std::experimental::nullopt; + xa8_message->TextSupport().SetText(u""); + xac_scrollMessage->TextSupport().SetText(u""); + xa4_textGroup->SetVisibility(false, ETraversalMode::Children); + xb0_xmark->SetVisibility(false, ETraversalMode::Children); + xb4_abutton->SetVisibility(false, ETraversalMode::Children); + xb8_dash->SetVisibility(false, ETraversalMode::Children); + xa8_message = nullptr; + xac_scrollMessage = nullptr; + xa4_textGroup = nullptr; + xb0_xmark = nullptr; + xb4_abutton = nullptr; + xb8_dash = nullptr; + x170_paneStates.clear(); + x170_paneStates.resize(4); + x194_scanStr = TLockedToken(); x1ac_pageCounter = 0; - x1a4_xAlpha = 0.f; - xa8_message = message; - xac_scrollMessage = scrollMessage; - xa4_textGroup = textGroup; - xb0_xmark = xmark; - xb4_abutton = abutton; - xb8_dash = dash; - xa4_textGroup->SetVisibility(true, ETraversalMode::Children); - xa4_textGroup->SetColor(zeus::CColor(1.f, 0.f)); - - for (int i=0 ; i<20 ; ++i) - { - CAuiImagePane* pane = static_cast( - xa0_selHud.FindWidget(MP1::CPauseScreenBase::GetImagePaneName(i))); - zeus::CColor color = g_tweakGuiColors->GetScanDisplayImagePaneColor(); - color.a() = 0.f; - pane->SetColor(color); - pane->SetTextureID0(-1, g_SimplePool); - pane->SetAnimationParms(zeus::CVector2f::skZero, 0.f, 0.f); - int pos = -1; - for (int j=0 ; j<4 ; ++j) - { - if (x14_scannableInfo->GetBucket(j).x8_imagePos == i) - { - pos = j; - break; - } - } - if (pos >= 0) - x170_paneStates[pos].second = pane; - } - - for (int i=0 ; i& state = x170_paneStates[i]; - if (state.second) - { - const CScannableObjectInfo::SBucket& bucket = x14_scannableInfo->GetBucket(i); - if (bucket.x14_interval > 0.f) - { - state.second->SetAnimationParms(zeus::CVector2f(bucket.xc_size.x, bucket.xc_size.y), - bucket.x14_interval, bucket.x18_fadeDuration); - } - state.second->SetTextureID0(bucket.x0_texture, g_SimplePool); - state.second->SetFlashFactor(0.f); - float startTime = GetDownloadStartTime(i); - if (scanTime >= startTime) - x170_paneStates[i].first = 0.f; - else - x170_paneStates[i].first = -1.f; - } - } - - CAssetId strId = x14_scannableInfo->GetStringTableId(); - if (strId.IsValid()) - x194_scanStr = g_SimplePool->GetObj({FOURCC('STRG'), strId}); - - for (int i=0 ; i<4 ; ++i) - { - int pos = x14_scannableInfo->GetBucket(i).x8_imagePos; - CDataDot& dot = xbc_dataDots[i]; - if (pos != -1) - { - if (GetDownloadStartTime(i) - g_tweakGui->GetScanAppearanceDuration() < scanTime) - { - dot.SetAlpha(0.f); - dot.SetDotState(CDataDot::EDotState::Done); - } - else - { - dot.SetDesiredAlpha(1.f); - dot.SetDotState(CDataDot::EDotState::Seek); - dot.StartTransitionTo(zeus::CVector2f::skZero, FLT_EPSILON); - dot.Update(FLT_EPSILON); - } - } - else - { - dot.SetDotState(CDataDot::EDotState::Hidden); - } - } + x1b4_scanComplete = false; + } else { + xa4_textGroup->SetColor(zeus::CColor(1.f, x1a8_bodyAlpha)); + } } -void CScanDisplay::StopScan() -{ - if (xc_state == EScanState::Done || xc_state == EScanState::Inactive) - return; +void CScanDisplay::Draw() const { + if (!x0_dataDot.IsLoaded()) + return; - xc_state = EScanState::Done; - for (int i=0 ; i<4 ; ++i) - xbc_dataDots[i].SetDesiredAlpha(0.f); -} - -void CScanDisplay::SetScanMessageTypeEffect(CGuiTextPane* pane, bool type) -{ - if (type) - pane->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, 60.f); - else - pane->TextSupport().SetTypeWriteEffectOptions(false, 0.f, 0.f); -} - -void CScanDisplay::Update(float dt, float scanningTime) -{ - if (xc_state == EScanState::Inactive) - return; - - bool active = false; - if (xc_state == EScanState::Done) - { - x1a8_bodyAlpha = std::max(0.f, x1a8_bodyAlpha - 2.f * dt); - if (x1a8_bodyAlpha > 0.f) - active = true; - } - else - { - active = true; - x1a8_bodyAlpha = std::min(x1a8_bodyAlpha + 2.f * dt, 1.f); - if (xc_state == EScanState::DownloadComplete) - { - if (xac_scrollMessage->TextSupport().GetIsTextSupportFinishedLoading()) - x1a4_xAlpha = std::max(0.f, x1a4_xAlpha - dt); - if (x1a4_xAlpha < 0.5f) - { - x1b0_aPulse += 2.f * dt; - if (x1b0_aPulse > 1.f) - x1b0_aPulse -= 2.f; - } - } - else if (xc_state == EScanState::ViewingScan) - { - x1b0_aPulse += 2.f * dt; - if (x1b0_aPulse > 1.f) - x1b0_aPulse -= 2.f; - if (x1a4_xAlpha == 1.f) - { - xa8_message->TextSupport().SetText(x194_scanStr->GetString(0)); - SetScanMessageTypeEffect(xa8_message, !x1b4_scanComplete); - } - } - else if (xc_state == EScanState::Downloading && scanningTime >= x14_scannableInfo->GetTotalDownloadTime() && - x194_scanStr.IsLoaded()) - { - if (x1b4_scanComplete || x14_scannableInfo->GetCategory() == 0) - { - xc_state = EScanState::ViewingScan; - x1b0_aPulse = x1a4_xAlpha = 1.f; - CSfxManager::SfxStart(SFXui_scan_complete, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - else - { - xc_state = EScanState::DownloadComplete; - x1b0_aPulse = x1a4_xAlpha = 1.f; - xa8_message->TextSupport().SetText(std::u16string(g_MainStringTable->GetString(29)) + - g_MainStringTable->GetString(x14_scannableInfo->GetCategory() + 30) + - g_MainStringTable->GetString(30)); - SetScanMessageTypeEffect(xa8_message, true); - CSfxManager::SfxStart(SFXui_new_scan_complete, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - - if (x194_scanStr->GetStringCount() > 2) - { - xac_scrollMessage->TextSupport().SetText(x194_scanStr->GetString(2), true); - SetScanMessageTypeEffect(xac_scrollMessage, !x1b4_scanComplete); - } - xac_scrollMessage->SetIsVisible(false); - } - } - - for (int i=0 ; i<4 ; ++i) - { - if (x170_paneStates[i].second == 0) - continue; - if (x170_paneStates[i].first > 0.f) - { - x170_paneStates[i].first = std::max(0.f, x170_paneStates[i].first - dt); - float tmp; - if (x170_paneStates[i].first > g_tweakGui->GetScanPaneFadeOutTime()) - tmp = 1.f - (x170_paneStates[i].first - g_tweakGui->GetScanPaneFadeOutTime()) / g_tweakGui->GetScanPaneFadeInTime(); - else - tmp = x170_paneStates[i].first / g_tweakGui->GetScanPaneFadeOutTime(); - x170_paneStates[i].second->SetFlashFactor(tmp * g_tweakGui->GetScanPaneFlashFactor() * x1a8_bodyAlpha); - } - float alphaMul = ((xc_state == EScanState::Downloading) ? GetDownloadFraction(i, scanningTime) : 1.f) * x1a8_bodyAlpha; - zeus::CColor color = g_tweakGuiColors->GetScanDisplayImagePaneColor(); - color.a() *= alphaMul; - x170_paneStates[i].second->SetColor(color); - x170_paneStates[i].second->SetDeResFactor(1.f - alphaMul); - if (GetDownloadStartTime(i) - g_tweakGui->GetScanAppearanceDuration() < scanningTime) - { - CDataDot& dot = xbc_dataDots[i]; - switch (dot.GetDotState()) - { - case CDataDot::EDotState::Seek: - case CDataDot::EDotState::Hold: - dot.SetDotState(CDataDot::EDotState::RevealPane); - dot.StartTransitionTo(zeus::CVector2f::skZero, g_tweakGui->GetScanAppearanceDuration()); - break; - case CDataDot::EDotState::RevealPane: - { - float tmp = dot.GetTransitionFactor(); - if (tmp == 0.f) - { - dot.SetDotState(CDataDot::EDotState::Done); - dot.SetDesiredAlpha(0.f); - CSfxManager::SfxStart(SFXui_scan_pane_reveal, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x170_paneStates[i].first = g_tweakGui->GetScanPaneFadeOutTime() + g_tweakGui->GetScanPaneFadeInTime(); - } - break; - } - default: break; - } - } - } - - for (int i=0 ; i<4 ; ++i) - { - CDataDot& dot = xbc_dataDots[i]; - switch (dot.GetDotState()) - { - case CDataDot::EDotState::Hidden: - continue; - case CDataDot::EDotState::Seek: - case CDataDot::EDotState::Hold: - { - float tmp = dot.GetTransitionFactor(); - if (tmp == 0.f) - { - float vpRatio = g_Viewport.xc_height / 480.f; - float posRand = g_tweakGui->GetScanDataDotPosRandMagnitude() * vpRatio; - float durMin = dot.GetDotState() == CDataDot::EDotState::Hold ? g_tweakGui->GetScanDataDotHoldDurationMin() : g_tweakGui->GetScanDataDotSeekDurationMin(); - float durMax = dot.GetDotState() == CDataDot::EDotState::Hold ? g_tweakGui->GetScanDataDotHoldDurationMax() : g_tweakGui->GetScanDataDotSeekDurationMax(); - zeus::CVector2f vec(dot.GetDotState() == CDataDot::EDotState::Hold ? dot.GetCurrPosition().x() : (posRand * (rand() / float(RAND_MAX)) - 0.5f * posRand), - dot.GetDotState() == CDataDot::EDotState::Hold ? dot.GetCurrPosition().y() : (posRand * (rand() / float(RAND_MAX)) - 0.5f * posRand)); - float dur = (durMax - durMin) * (rand() / float(RAND_MAX)) + durMin; - dot.StartTransitionTo(vec, dur); - dot.SetDotState(dot.GetDotState() == CDataDot::EDotState::Hold ? CDataDot::EDotState::Seek : CDataDot::EDotState::Hold); - } - break; - } - case CDataDot::EDotState::RevealPane: - case CDataDot::EDotState::Done: - { - const zeus::CVector3f& panePos = x170_paneStates[i].second->GetWorldPosition(); - zeus::CVector3f screenPos = xa0_selHud.GetFrameCamera()->ConvertToScreenSpace(panePos); - zeus::CVector2f viewportCoords(screenPos.x() * g_Viewport.x8_width * 0.5f, - screenPos.y() * g_Viewport.xc_height * 0.5f); - dot.SetDestPosition(viewportCoords); - break; - } - default: break; - } - dot.Update(dt); - } - - if (!active) - { - xc_state = EScanState::Inactive; - x10_objId = kInvalidUniqueId; - x14_scannableInfo = std::experimental::nullopt; - xa8_message->TextSupport().SetText(u""); - xac_scrollMessage->TextSupport().SetText(u""); - xa4_textGroup->SetVisibility(false, ETraversalMode::Children); - xb0_xmark->SetVisibility(false, ETraversalMode::Children); - xb4_abutton->SetVisibility(false, ETraversalMode::Children); - xb8_dash->SetVisibility(false, ETraversalMode::Children); - xa8_message = nullptr; - xac_scrollMessage = nullptr; - xa4_textGroup = nullptr; - xb0_xmark = nullptr; - xb4_abutton = nullptr; - xb8_dash = nullptr; - x170_paneStates.clear(); - x170_paneStates.resize(4); - x194_scanStr = TLockedToken(); - x1ac_pageCounter = 0; - x1b4_scanComplete = false; - } - else - { - xa4_textGroup->SetColor(zeus::CColor(1.f, x1a8_bodyAlpha)); - } -} - -void CScanDisplay::Draw() const -{ - if (!x0_dataDot.IsLoaded()) - return; - - // No Z-test or write - g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f); - // Additive alpha - - float vpRatio = g_Viewport.xc_height / 480.f; - for (const CDataDot& dot : xbc_dataDots) - dot.Draw(g_tweakGuiColors->GetScanDataDotColor(), g_tweakGui->GetScanDataDotRadius() * vpRatio); -} + // No Z-test or write + g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f); + // Additive alpha + + float vpRatio = g_Viewport.xc_height / 480.f; + for (const CDataDot& dot : xbc_dataDots) + dot.Draw(g_tweakGuiColors->GetScanDataDotColor(), g_tweakGui->GetScanDataDotRadius() * vpRatio); } +} // namespace urde diff --git a/Runtime/GuiSys/CScanDisplay.hpp b/Runtime/GuiSys/CScanDisplay.hpp index 7cc3297cf..120ebf508 100644 --- a/Runtime/GuiSys/CScanDisplay.hpp +++ b/Runtime/GuiSys/CScanDisplay.hpp @@ -8,8 +8,7 @@ #include "Graphics/CTexture.hpp" #include "Graphics/Shaders/CTexturedQuadFilter.hpp" -namespace urde -{ +namespace urde { class CGuiTextPane; class CGuiWidget; class CGuiModel; @@ -18,91 +17,76 @@ class CGuiFrame; class CAuiImagePane; class CStringTable; -class CScanDisplay -{ - friend class CHudDecoInterfaceScan; -public: - class CDataDot - { - public: - enum class EDotState - { - Hidden, - Seek, - Hold, - RevealPane, - Done - }; - private: - EDotState x0_dotState = EDotState::Hidden; - zeus::CVector2f x4_startPos; - zeus::CVector2f xc_curPos; - zeus::CVector2f x14_targetPos; - float x1c_transDur = 0.f; - float x20_remTime = 0.f; - float x24_alpha = 0.f; - float x28_desiredAlpha = 0.f; - CTexturedQuadFilter m_quad; - public: - CDataDot(const TLockedToken& dataDotTex) - : m_quad(EFilterType::Add, dataDotTex) {} - void Update(float dt); - void Draw(const zeus::CColor& color, float radius) const; - float GetTransitionFactor() const { return x1c_transDur > 0.f ? x20_remTime / x1c_transDur : 0.f; } - void StartTransitionTo(const zeus::CVector2f&, float); - void SetDestPosition(const zeus::CVector2f&); - void SetDesiredAlpha(float a) { x28_desiredAlpha = a; } - void SetDotState(EDotState s) { x0_dotState = s; } - void SetAlpha(float a) { x24_alpha = a; } - const zeus::CVector2f& GetCurrPosition() const { return xc_curPos; } - EDotState GetDotState() const { return x0_dotState; } - }; +class CScanDisplay { + friend class CHudDecoInterfaceScan; - enum class EScanState - { - Inactive, - Downloading, - DownloadComplete, - ViewingScan, - Done - }; +public: + class CDataDot { + public: + enum class EDotState { Hidden, Seek, Hold, RevealPane, Done }; + + private: + EDotState x0_dotState = EDotState::Hidden; + zeus::CVector2f x4_startPos; + zeus::CVector2f xc_curPos; + zeus::CVector2f x14_targetPos; + float x1c_transDur = 0.f; + float x20_remTime = 0.f; + float x24_alpha = 0.f; + float x28_desiredAlpha = 0.f; + CTexturedQuadFilter m_quad; + + public: + CDataDot(const TLockedToken& dataDotTex) : m_quad(EFilterType::Add, dataDotTex) {} + void Update(float dt); + void Draw(const zeus::CColor& color, float radius) const; + float GetTransitionFactor() const { return x1c_transDur > 0.f ? x20_remTime / x1c_transDur : 0.f; } + void StartTransitionTo(const zeus::CVector2f&, float); + void SetDestPosition(const zeus::CVector2f&); + void SetDesiredAlpha(float a) { x28_desiredAlpha = a; } + void SetDotState(EDotState s) { x0_dotState = s; } + void SetAlpha(float a) { x24_alpha = a; } + const zeus::CVector2f& GetCurrPosition() const { return xc_curPos; } + EDotState GetDotState() const { return x0_dotState; } + }; + + enum class EScanState { Inactive, Downloading, DownloadComplete, ViewingScan, Done }; private: - TLockedToken x0_dataDot; - EScanState xc_state = EScanState::Inactive; - TUniqueId x10_objId = kInvalidUniqueId; - std::experimental::optional x14_scannableInfo; - const CGuiFrame& xa0_selHud; - CGuiWidget* xa4_textGroup = nullptr; - CGuiTextPane* xa8_message = nullptr; - CGuiTextPane* xac_scrollMessage = nullptr; - CGuiModel* xb0_xmark = nullptr; - CGuiModel* xb4_abutton = nullptr; - CGuiModel* xb8_dash = nullptr; - rstl::reserved_vector xbc_dataDots; - rstl::reserved_vector, 4> x170_paneStates; - TLockedToken x194_scanStr; // Used to be optional - float x1a4_xAlpha = 0.f; - float x1a8_bodyAlpha = 0.f; - int x1ac_pageCounter = 0; - float x1b0_aPulse = 1.f; - bool x1b4_scanComplete = false; + TLockedToken x0_dataDot; + EScanState xc_state = EScanState::Inactive; + TUniqueId x10_objId = kInvalidUniqueId; + std::experimental::optional x14_scannableInfo; + const CGuiFrame& xa0_selHud; + CGuiWidget* xa4_textGroup = nullptr; + CGuiTextPane* xa8_message = nullptr; + CGuiTextPane* xac_scrollMessage = nullptr; + CGuiModel* xb0_xmark = nullptr; + CGuiModel* xb4_abutton = nullptr; + CGuiModel* xb8_dash = nullptr; + rstl::reserved_vector xbc_dataDots; + rstl::reserved_vector, 4> x170_paneStates; + TLockedToken x194_scanStr; // Used to be optional + float x1a4_xAlpha = 0.f; + float x1a8_bodyAlpha = 0.f; + int x1ac_pageCounter = 0; + float x1b0_aPulse = 1.f; + bool x1b4_scanComplete = false; - float GetDownloadStartTime(int idx) const; - float GetDownloadFraction(int idx, float scanningTime) const; - static void SetScanMessageTypeEffect(CGuiTextPane* pane, bool type); + float GetDownloadStartTime(int idx) const; + float GetDownloadFraction(int idx, float scanningTime) const; + static void SetScanMessageTypeEffect(CGuiTextPane* pane, bool type); public: - CScanDisplay(const CGuiFrame& selHud); - void ProcessInput(const CFinalInput& input); - void StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo, CGuiTextPane* message, - CGuiTextPane* scrollMessage, CGuiWidget* textGroup, CGuiModel* xmark, - CGuiModel* abutton, CGuiModel* dash, float scanTime); - void StopScan(); - void Update(float dt, float scanningTime); - void Draw() const; - EScanState GetScanState() const { return xc_state; } - TUniqueId ScanTarget() const { return x10_objId; } + CScanDisplay(const CGuiFrame& selHud); + void ProcessInput(const CFinalInput& input); + void StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo, CGuiTextPane* message, CGuiTextPane* scrollMessage, + CGuiWidget* textGroup, CGuiModel* xmark, CGuiModel* abutton, CGuiModel* dash, float scanTime); + void StopScan(); + void Update(float dt, float scanningTime); + void Draw() const; + EScanState GetScanState() const { return xc_state; } + TUniqueId ScanTarget() const { return x10_objId; } }; -} +} // namespace urde diff --git a/Runtime/GuiSys/CSplashScreen.cpp b/Runtime/GuiSys/CSplashScreen.cpp index 27c50987e..b56d4f3f4 100644 --- a/Runtime/GuiSys/CSplashScreen.cpp +++ b/Runtime/GuiSys/CSplashScreen.cpp @@ -4,82 +4,69 @@ #include "CSimplePool.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { -static const char* SplashTextures[] -{ - "TXTR_NintendoLogo", - "TXTR_RetroLogo", - "TXTR_DolbyLogo" -}; +static const char* SplashTextures[]{"TXTR_NintendoLogo", "TXTR_RetroLogo", "TXTR_DolbyLogo"}; CSplashScreen::CSplashScreen(ESplashScreen which) -: CIOWin("SplashScreen"), x14_which(which), - m_quad(EFilterType::Blend, - g_SimplePool->GetObj(SplashTextures[int(which)])) -{ -} +: CIOWin("SplashScreen") +, x14_which(which) +, m_quad(EFilterType::Blend, g_SimplePool->GetObj(SplashTextures[int(which)])) {} -CIOWin::EMessageReturn CSplashScreen::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - switch (msg.GetType()) - { - case EArchMsgType::TimerTick: - { - if (!x25_textureLoaded) - { - if (!m_quad.GetTex().IsLoaded()) - return EMessageReturn::Exit; - x25_textureLoaded = true; - } +CIOWin::EMessageReturn CSplashScreen::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + switch (msg.GetType()) { + case EArchMsgType::TimerTick: { + if (!x25_textureLoaded) { + if (!m_quad.GetTex().IsLoaded()) + return EMessageReturn::Exit; + x25_textureLoaded = true; + } - float dt = MakeMsg::GetParmTimerTick(msg).x4_parm; - x18_splashTimeout -= dt; + float dt = MakeMsg::GetParmTimerTick(msg).x4_parm; + x18_splashTimeout -= dt; - if (x18_splashTimeout <= 0.f) - { - /* HACK: If we're not compiling with Intel's IPP library we want to skip the Dolby Pro Logic II logo - * This is purely a URDE addition and does not reflect retro's intentions. - Phil - */ + if (x18_splashTimeout <= 0.f) { + /* HACK: If we're not compiling with Intel's IPP library we want to skip the Dolby Pro Logic II logo + * This is purely a URDE addition and does not reflect retro's intentions. - Phil + */ #if INTEL_IPP - if (x14_which != ESplashScreen::Dolby) + if (x14_which != ESplashScreen::Dolby) #else - if (x14_which != ESplashScreen::Retro) + if (x14_which != ESplashScreen::Retro) #endif - queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 9999, 9999, - std::make_shared(ESplashScreen(int(x14_which) + 1)))); - return EMessageReturn::RemoveIOWinAndExit; - } - break; + queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 9999, 9999, + std::make_shared(ESplashScreen(int(x14_which) + 1)))); + return EMessageReturn::RemoveIOWinAndExit; } - default: break; - } - return EMessageReturn::Exit; + break; + } + default: + break; + } + return EMessageReturn::Exit; } -void CSplashScreen::Draw() const -{ - if (!x25_textureLoaded) - return; +void CSplashScreen::Draw() const { + if (!x25_textureLoaded) + return; - zeus::CColor color; - if (x14_which == ESplashScreen::Nintendo) - color = zeus::CColor{0.86f, 0.f, 0.f, 1.f}; + zeus::CColor color; + if (x14_which == ESplashScreen::Nintendo) + color = zeus::CColor{0.86f, 0.f, 0.f, 1.f}; - if (x18_splashTimeout > 1.5f) - color.a() = 1.f - (x18_splashTimeout - 1.5f) * 2.f; - else if (x18_splashTimeout < 0.5f) - color.a() = x18_splashTimeout * 2.f; + if (x18_splashTimeout > 1.5f) + color.a() = 1.f - (x18_splashTimeout - 1.5f) * 2.f; + else if (x18_splashTimeout < 0.5f) + color.a() = x18_splashTimeout * 2.f; - zeus::CRectangle rect; - float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); - rect.size.x() = m_quad.GetTex()->GetWidth() / (480.f * aspect); - rect.size.y() = m_quad.GetTex()->GetHeight() / 480.f; - rect.position.x() = 0.5f - rect.size.x() / 2.f; - rect.position.y() = 0.5f - rect.size.y() / 2.f; + zeus::CRectangle rect; + float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); + rect.size.x() = m_quad.GetTex()->GetWidth() / (480.f * aspect); + rect.size.y() = m_quad.GetTex()->GetHeight() / 480.f; + rect.position.x() = 0.5f - rect.size.x() / 2.f; + rect.position.y() = 0.5f - rect.size.y() / 2.f; - const_cast(m_quad).draw(color, 1.f, rect); + const_cast(m_quad).draw(color, 1.f, rect); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CSplashScreen.hpp b/Runtime/GuiSys/CSplashScreen.hpp index df8cc61e4..e5718037c 100644 --- a/Runtime/GuiSys/CSplashScreen.hpp +++ b/Runtime/GuiSys/CSplashScreen.hpp @@ -5,37 +5,26 @@ #include "Graphics/CTexture.hpp" #include "Graphics/Shaders/CTexturedQuadFilter.hpp" -namespace urde -{ +namespace urde { -class CSplashScreen : public CIOWin -{ +class CSplashScreen : public CIOWin { public: - enum class ESplashScreen - { - Nintendo, - Retro, - Dolby - }; - enum class EProgressivePhase - { - Before, - During, - After - }; + enum class ESplashScreen { Nintendo, Retro, Dolby }; + enum class EProgressivePhase { Before, During, After }; + private: - ESplashScreen x14_which; - float x18_splashTimeout = 2.f; - //float x1c_progSelectionTimeout = 0.f; - //EProgressivePhase x20_progressivePhase = EProgressivePhase::Before; - //bool x24_progressiveSelection = true; - bool x25_textureLoaded = false; - CTexturedQuadFilterAlpha m_quad; + ESplashScreen x14_which; + float x18_splashTimeout = 2.f; + // float x1c_progSelectionTimeout = 0.f; + // EProgressivePhase x20_progressivePhase = EProgressivePhase::Before; + // bool x24_progressiveSelection = true; + bool x25_textureLoaded = false; + CTexturedQuadFilterAlpha m_quad; + public: - CSplashScreen(ESplashScreen); - EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); - void Draw() const; + CSplashScreen(ESplashScreen); + EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); + void Draw() const; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CStringTable.cpp b/Runtime/GuiSys/CStringTable.cpp index b0a2579ab..350a19d9b 100644 --- a/Runtime/GuiSys/CStringTable.cpp +++ b/Runtime/GuiSys/CStringTable.cpp @@ -1,93 +1,74 @@ #include "CStringTable.hpp" #include "CToken.hpp" -namespace urde -{ -const std::vector CStringTable::skLanguages = -{ - FOURCC('ENGL'), - FOURCC('FREN'), - FOURCC('GERM'), - FOURCC('SPAN'), - FOURCC('ITAL'), - FOURCC('DUTC'), - FOURCC('JAPN') -}; +namespace urde { +const std::vector CStringTable::skLanguages = {FOURCC('ENGL'), FOURCC('FREN'), FOURCC('GERM'), FOURCC('SPAN'), + FOURCC('ITAL'), FOURCC('DUTC'), FOURCC('JAPN')}; FourCC CStringTable::mCurrentLanguage = CStringTable::skLanguages[0]; CStringTable::CStringTable(CInputStream& in) { LoadStringTable(in); } -void CStringTable::LoadStringTable(CInputStream &in) -{ - in.readUint32Big(); - in.readUint32Big(); - u32 langCount = in.readUint32Big(); - x0_stringCount = in.readUint32Big(); - std::vector> langOffsets; - for (u32 i = 0 ; i> langOffsets; + for (u32 i = 0; i < langCount; ++i) { + FourCC fcc(in.readUint32()); + u32 off = in.readUint32Big(); + langOffsets.emplace_back(fcc, off); + } + + u32 lang = 0; + u32 offset = 0; + while ((langCount--) > 0) { + if (langOffsets[lang].first == mCurrentLanguage) { + offset = langOffsets[lang].second; + break; } - u32 lang = 0; - u32 offset = 0; - while((langCount--) > 0) - { - if (langOffsets[lang].first == mCurrentLanguage) - { - offset = langOffsets[lang].second; - break; - } + lang++; + } - lang++; - } + /* + * If we fail to get a language, default to the first in the list + * This way we always display _something_ + */ + if (offset == -1) + offset = langOffsets[0].second; - /* - * If we fail to get a language, default to the first in the list - * This way we always display _something_ - */ - if (offset == -1) - offset = langOffsets[0].second; + in.seek(offset); - in.seek(offset); + u32 dataLen = in.readUint32Big(); + m_bufLen = dataLen; + x4_data.reset(new u8[dataLen]); + in.readUBytesToBuf(x4_data.get(), dataLen); - u32 dataLen = in.readUint32Big(); - m_bufLen = dataLen; - x4_data.reset(new u8[dataLen]); - in.readUBytesToBuf(x4_data.get(), dataLen); + u32* off = reinterpret_cast(x4_data.get()); + for (u32 i = 0; i < x0_stringCount; ++i, ++off) + *off = hecl::SBig(*off); - u32* off = reinterpret_cast(x4_data.get()); - for (u32 i = 0 ; i < x0_stringCount ; ++i, ++off) - *off = hecl::SBig(*off); - - for (u32 i = x0_stringCount * 4 ; i < dataLen ; i += 2) - { - u16* chr = reinterpret_cast(x4_data.get() + i); - *chr = hecl::SBig(*chr); - } + for (u32 i = x0_stringCount * 4; i < dataLen; i += 2) { + u16* chr = reinterpret_cast(x4_data.get() + i); + *chr = hecl::SBig(*chr); + } } -const char16_t* CStringTable::GetString(s32 str) const -{ - if (str < 0 || u32(str) >= x0_stringCount) - return u"Invalid"; +const char16_t* CStringTable::GetString(s32 str) const { + if (str < 0 || u32(str) >= x0_stringCount) + return u"Invalid"; - u32 off = *reinterpret_cast(x4_data.get() + str * 4); - return reinterpret_cast(x4_data.get() + off); + u32 off = *reinterpret_cast(x4_data.get() + str * 4); + return reinterpret_cast(x4_data.get() + off); } -void CStringTable::SetLanguage(s32 lang) -{ - mCurrentLanguage = skLanguages[lang]; -} +void CStringTable::SetLanguage(s32 lang) { mCurrentLanguage = skLanguages[lang]; } CFactoryFnReturn FStringTableFactory(const SObjectTag&, CInputStream& in, const CVParamTransfer&, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CStringTable.hpp b/Runtime/GuiSys/CStringTable.hpp index 3ac94b1a0..2915d986b 100644 --- a/Runtime/GuiSys/CStringTable.hpp +++ b/Runtime/GuiSys/CStringTable.hpp @@ -3,24 +3,23 @@ #include "RetroTypes.hpp" #include "IFactory.hpp" -namespace urde -{ -class CStringTable -{ - static const std::vector skLanguages; - static FourCC mCurrentLanguage; - u32 x0_stringCount = 0; - std::unique_ptr x4_data = 0; - u32 m_bufLen; -public: - CStringTable(CInputStream& in); - void LoadStringTable(CInputStream& in); +namespace urde { +class CStringTable { + static const std::vector skLanguages; + static FourCC mCurrentLanguage; + u32 x0_stringCount = 0; + std::unique_ptr x4_data = 0; + u32 m_bufLen; - const char16_t* GetString(s32) const; - u32 GetStringCount() const { return x0_stringCount; } - static void SetLanguage(s32); +public: + CStringTable(CInputStream& in); + void LoadStringTable(CInputStream& in); + + const char16_t* GetString(s32) const; + u32 GetStringCount() const { return x0_stringCount; } + static void SetLanguage(s32); }; CFactoryFnReturn FStringTableFactory(const SObjectTag&, CInputStream&, const CVParamTransfer&, CObjectReference* selfRef); -} +} // namespace urde diff --git a/Runtime/GuiSys/CTargetingManager.cpp b/Runtime/GuiSys/CTargetingManager.cpp index c34e44d09..b0ae73c08 100644 --- a/Runtime/GuiSys/CTargetingManager.cpp +++ b/Runtime/GuiSys/CTargetingManager.cpp @@ -4,43 +4,35 @@ #include "Graphics/CBooRenderer.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { -CTargetingManager::CTargetingManager(const CStateManager& mgr) -: x0_targetReticule(mgr) {} +CTargetingManager::CTargetingManager(const CStateManager& mgr) : x0_targetReticule(mgr) {} -bool CTargetingManager::CheckLoadComplete() -{ - return (x0_targetReticule.CheckLoadComplete() && x21c_orbitPointMarker.CheckLoadComplete()); +bool CTargetingManager::CheckLoadComplete() { + return (x0_targetReticule.CheckLoadComplete() && x21c_orbitPointMarker.CheckLoadComplete()); } -void CTargetingManager::Update(float dt, const CStateManager& stateMgr) -{ - x0_targetReticule.Update(dt, stateMgr); - x21c_orbitPointMarker.Update(dt, stateMgr); +void CTargetingManager::Update(float dt, const CStateManager& stateMgr) { + x0_targetReticule.Update(dt, stateMgr); + x21c_orbitPointMarker.Update(dt, stateMgr); } -void CTargetingManager::Draw(const CStateManager& mgr, bool hideLockon) const -{ - CGraphics::SetAmbientColor(zeus::CColor::skWhite); - CGraphics::DisableAllLights(); - x21c_orbitPointMarker.Draw(mgr); - const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - CGraphics::SetViewPointMatrix(camXf); - zeus::CFrustum frustum; - frustum.updatePlanes(camXf, zeus::SProjPersp(zeus::degToRad(curCam->GetFov()), - g_Viewport.x8_width / float(g_Viewport.xc_height), 1.f, 100.f)); - g_Renderer->SetClippingPlanes(frustum); - g_Renderer->SetPerspective(curCam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, - curCam->GetNearClipDistance(), curCam->GetFarClipDistance()); - x0_targetReticule.Draw(mgr, hideLockon); +void CTargetingManager::Draw(const CStateManager& mgr, bool hideLockon) const { + CGraphics::SetAmbientColor(zeus::CColor::skWhite); + CGraphics::DisableAllLights(); + x21c_orbitPointMarker.Draw(mgr); + const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + CGraphics::SetViewPointMatrix(camXf); + zeus::CFrustum frustum; + frustum.updatePlanes(camXf, zeus::SProjPersp(zeus::degToRad(curCam->GetFov()), + g_Viewport.x8_width / float(g_Viewport.xc_height), 1.f, 100.f)); + g_Renderer->SetClippingPlanes(frustum); + g_Renderer->SetPerspective(curCam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, curCam->GetNearClipDistance(), + curCam->GetFarClipDistance()); + x0_targetReticule.Draw(mgr, hideLockon); } -void CTargetingManager::Touch() -{ - x0_targetReticule.Touch(); -} +void CTargetingManager::Touch() { x0_targetReticule.Touch(); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CTargetingManager.hpp b/Runtime/GuiSys/CTargetingManager.hpp index b83d88d1c..e688ccbc0 100644 --- a/Runtime/GuiSys/CTargetingManager.hpp +++ b/Runtime/GuiSys/CTargetingManager.hpp @@ -3,20 +3,18 @@ #include "CCompoundTargetReticle.hpp" #include "COrbitPointMarker.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class CTargetingManager -{ - CCompoundTargetReticle x0_targetReticule; - COrbitPointMarker x21c_orbitPointMarker; -public: - CTargetingManager(const CStateManager& stateMgr); - bool CheckLoadComplete(); - void Update(float, const CStateManager& stateMgr); - void Draw(const CStateManager& stateMgr, bool hideLockon) const; - void Touch(); - CCompoundTargetReticle& CompoundTargetReticle() { return x0_targetReticule; } -}; -} +class CTargetingManager { + CCompoundTargetReticle x0_targetReticule; + COrbitPointMarker x21c_orbitPointMarker; +public: + CTargetingManager(const CStateManager& stateMgr); + bool CheckLoadComplete(); + void Update(float, const CStateManager& stateMgr); + void Draw(const CStateManager& stateMgr, bool hideLockon) const; + void Touch(); + CCompoundTargetReticle& CompoundTargetReticle() { return x0_targetReticule; } +}; +} // namespace urde diff --git a/Runtime/GuiSys/CTextExecuteBuffer.cpp b/Runtime/GuiSys/CTextExecuteBuffer.cpp index eb3a0466f..ebcb9f101 100644 --- a/Runtime/GuiSys/CTextExecuteBuffer.cpp +++ b/Runtime/GuiSys/CTextExecuteBuffer.cpp @@ -8,462 +8,399 @@ #include "Graphics/CGraphicsPalette.hpp" #include "Graphics/CTexture.hpp" -namespace urde -{ +namespace urde { -CTextRenderBuffer CTextExecuteBuffer::BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const -{ - CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df); +CTextRenderBuffer CTextExecuteBuffer::BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const { + CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df); - { - CFontRenderState rendState; - for (const std::shared_ptr& inst : x0_instList) - inst->Invoke(rendState, &ret); - } + { + CFontRenderState rendState; + for (const std::shared_ptr& inst : x0_instList) + inst->Invoke(rendState, &ret); + } - ret.SetMode(CTextRenderBuffer::EMode::BufferFill); + ret.SetMode(CTextRenderBuffer::EMode::BufferFill); - { - CFontRenderState rendState; - for (const std::shared_ptr& inst : x0_instList) - inst->Invoke(rendState, &ret); - } + { + CFontRenderState rendState; + for (const std::shared_ptr& inst : x0_instList) + inst->Invoke(rendState, &ret); + } - return ret; + return ret; } CTextRenderBuffer CTextExecuteBuffer::BuildRenderBufferPage(InstList::const_iterator start, InstList::const_iterator pgStart, InstList::const_iterator pgEnd, - CGuiWidget::EGuiModelDrawFlags df) const -{ - CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df); + CGuiWidget::EGuiModelDrawFlags df) const { + CTextRenderBuffer ret(CTextRenderBuffer::EMode::AllocTally, df); - { - CFontRenderState rendState; - for (auto it = start ; it != pgStart ; ++it) - { - const std::shared_ptr& inst = *it; - inst->PageInvoke(rendState, &ret); - } - for (auto it = pgStart ; it != pgEnd ; ++it) - { - const std::shared_ptr& inst = *it; - inst->Invoke(rendState, &ret); - } + { + CFontRenderState rendState; + for (auto it = start; it != pgStart; ++it) { + const std::shared_ptr& inst = *it; + inst->PageInvoke(rendState, &ret); } - - ret.SetMode(CTextRenderBuffer::EMode::BufferFill); - - { - CFontRenderState rendState; - for (auto it = start ; it != pgStart ; ++it) - { - const std::shared_ptr& inst = *it; - inst->PageInvoke(rendState, &ret); - } - for (auto it = pgStart ; it != pgEnd ; ++it) - { - const std::shared_ptr& inst = *it; - inst->Invoke(rendState, &ret); - } + for (auto it = pgStart; it != pgEnd; ++it) { + const std::shared_ptr& inst = *it; + inst->Invoke(rendState, &ret); } + } - return ret; + ret.SetMode(CTextRenderBuffer::EMode::BufferFill); + + { + CFontRenderState rendState; + for (auto it = start; it != pgStart; ++it) { + const std::shared_ptr& inst = *it; + inst->PageInvoke(rendState, &ret); + } + for (auto it = pgStart; it != pgEnd; ++it) { + const std::shared_ptr& inst = *it; + inst->Invoke(rendState, &ret); + } + } + + return ret; } std::list CTextExecuteBuffer::BuildRenderBufferPages(const zeus::CVector2i& extent, - CGuiWidget::EGuiModelDrawFlags df) const -{ - std::list ret; + CGuiWidget::EGuiModelDrawFlags df) const { + std::list ret; + + for (auto it = x0_instList.begin(); it != x0_instList.end();) { + CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally, df); - for (auto it = x0_instList.begin() ; it != x0_instList.end() ;) { - CTextRenderBuffer rbuf(CTextRenderBuffer::EMode::AllocTally, df); - - { - CFontRenderState rstate; - for (auto it2 = x0_instList.begin() ; it2 != x0_instList.end() ; ++it2) - { - const std::shared_ptr& inst2 = *it2; - inst2->Invoke(rstate, &rbuf); - } - } - - rbuf.SetMode(CTextRenderBuffer::EMode::BufferFill); - - InstList::const_iterator pageEnd = it; - { - CFontRenderState rstate; - bool seekingToPage = true; - for (auto it2 = x0_instList.begin() ; it2 != x0_instList.end() ; ++it2) - { - const std::shared_ptr& inst2 = *it2; - if (it2 == it) - seekingToPage = false; - if (seekingToPage) - { - inst2->PageInvoke(rstate, &rbuf); - } - else - { - inst2->Invoke(rstate, &rbuf); - if (!rbuf.HasSpaceAvailable(zeus::CVector2i{}, extent)) - break; - ++pageEnd; - } - } - } - - ret.push_back(BuildRenderBufferPage(x0_instList.cbegin(), it, pageEnd, df)); - it = pageEnd; + CFontRenderState rstate; + for (auto it2 = x0_instList.begin(); it2 != x0_instList.end(); ++it2) { + const std::shared_ptr& inst2 = *it2; + inst2->Invoke(rstate, &rbuf); + } } - return ret; + rbuf.SetMode(CTextRenderBuffer::EMode::BufferFill); + + InstList::const_iterator pageEnd = it; + { + CFontRenderState rstate; + bool seekingToPage = true; + for (auto it2 = x0_instList.begin(); it2 != x0_instList.end(); ++it2) { + const std::shared_ptr& inst2 = *it2; + if (it2 == it) + seekingToPage = false; + if (seekingToPage) { + inst2->PageInvoke(rstate, &rbuf); + } else { + inst2->Invoke(rstate, &rbuf); + if (!rbuf.HasSpaceAvailable(zeus::CVector2i{}, extent)) + break; + ++pageEnd; + } + } + } + + ret.push_back(BuildRenderBufferPage(x0_instList.cbegin(), it, pageEnd, df)); + it = pageEnd; + } + + return ret; } -std::vector CTextExecuteBuffer::GetAssets() const -{ - size_t totalAssets = 0; - for (const std::shared_ptr& inst : x0_instList) - totalAssets += inst->GetAssetCount(); +std::vector CTextExecuteBuffer::GetAssets() const { + size_t totalAssets = 0; + for (const std::shared_ptr& inst : x0_instList) + totalAssets += inst->GetAssetCount(); - std::vector ret; - ret.reserve(totalAssets); + std::vector ret; + ret.reserve(totalAssets); - for (const std::shared_ptr& inst : x0_instList) - inst->GetAssets(ret); + for (const std::shared_ptr& inst : x0_instList) + inst->GetAssets(ret); - return ret; + return ret; } -void CTextExecuteBuffer::AddString(const char16_t* str, int count) -{ - if (!xa4_curLine) +void CTextExecuteBuffer::AddString(const char16_t* str, int count) { + if (!xa4_curLine) + StartNewLine(); + + const char16_t* charCur = str; + const char16_t* wordCur = str; + + for (int ac = 0; *charCur && (ac < count || count == -1); ++charCur, ++ac) { + if (*charCur == u'\n' || *charCur == u' ') { + AddStringFragment(wordCur, charCur - wordCur); + wordCur = charCur + 1; + if (*charCur == u'\n') { StartNewLine(); - - const char16_t* charCur = str; - const char16_t* wordCur = str; - - for (int ac=0 ; *charCur && (ac < count || count == -1) ; ++charCur, ++ac) - { - if (*charCur == u'\n' || *charCur == u' ') - { - AddStringFragment(wordCur, charCur - wordCur); - wordCur = charCur + 1; - if (*charCur == u'\n') - { - StartNewLine(); - } - else - { - StartNewWord(); - int w, h; - char16_t space = u' '; - x18_textState.x48_font->GetSize(x18_textState.x0_drawStrOpts, w, h, &space, 1); - if (xa0_curBlock->x14_dir == ETextDirection::Horizontal) - { - xa4_curLine->x8_curX += w; - xbc_spaceDistance = w; - } - else - { - xa4_curLine->xc_curY += h; - xbc_spaceDistance = h; - } - } + } else { + StartNewWord(); + int w, h; + char16_t space = u' '; + x18_textState.x48_font->GetSize(x18_textState.x0_drawStrOpts, w, h, &space, 1); + if (xa0_curBlock->x14_dir == ETextDirection::Horizontal) { + xa4_curLine->x8_curX += w; + xbc_spaceDistance = w; + } else { + xa4_curLine->xc_curY += h; + xbc_spaceDistance = h; } + } } + } - if (charCur > wordCur) - AddStringFragment(wordCur, charCur - wordCur); + if (charCur > wordCur) + AddStringFragment(wordCur, charCur - wordCur); } -void CTextExecuteBuffer::AddStringFragment(const char16_t* str, int len) -{ - if (xa0_curBlock->x14_dir == ETextDirection::Horizontal) - for (int i=0 ; ix14_dir == ETextDirection::Horizontal) + for (int i = 0; i < len;) + i += WrapOneLTR(str + i, len - i); } -int CTextExecuteBuffer::WrapOneLTR(const char16_t* str, int len) -{ - if (!x18_textState.x48_font) - return len; +int CTextExecuteBuffer::WrapOneLTR(const char16_t* str, int len) { + if (!x18_textState.x48_font) + return len; - CRasterFont* font = x18_textState.x48_font.GetObj(); - int rem = len; - int w, h; - x18_textState.x48_font->GetSize(x18_textState.x0_drawStrOpts, w, h, str, len); + CRasterFont* font = x18_textState.x48_font.GetObj(); + int rem = len; + int w, h; + x18_textState.x48_font->GetSize(x18_textState.x0_drawStrOpts, w, h, str, len); - if (x18_textState.x7c_enableWordWrap) - { - if (w + xa4_curLine->x8_curX > xa0_curBlock->xc_blockExtentX && - xa4_curLine->x4_wordCount >= 1 && - xb0_curX + w < xa0_curBlock->xc_blockExtentX) - { - MoveWordLTR(); - } - if (w + xa4_curLine->x8_curX > xa0_curBlock->xc_blockExtentX && len > 1) - { - const char16_t* strEnd = str + len; - int aRank = 5; - - do - { - --rem; - --strEnd; - int endRank = 4; - if (len > 2) - endRank = CWordBreakTables::GetEndRank(*(strEnd - 1)); - - int beginRank = CWordBreakTables::GetBeginRank(*strEnd); - - if (endRank < aRank && endRank <= beginRank) - { - aRank = endRank; - } - else - { - x18_textState.x48_font->GetSize(x18_textState.x0_drawStrOpts, w, h, str, rem); - } - - } while (w + xa4_curLine->x8_curX > xa0_curBlock->xc_blockExtentX && rem > 1); - } + if (x18_textState.x7c_enableWordWrap) { + if (w + xa4_curLine->x8_curX > xa0_curBlock->xc_blockExtentX && xa4_curLine->x4_wordCount >= 1 && + xb0_curX + w < xa0_curBlock->xc_blockExtentX) { + MoveWordLTR(); } + if (w + xa4_curLine->x8_curX > xa0_curBlock->xc_blockExtentX && len > 1) { + const char16_t* strEnd = str + len; + int aRank = 5; - xac_curY = std::max(xac_curY, font->GetMonoHeight()); + do { + --rem; + --strEnd; + int endRank = 4; + if (len > 2) + endRank = CWordBreakTables::GetEndRank(*(strEnd - 1)); - xa4_curLine->TestLargestFont(font->GetMonoWidth(), - font->GetMonoHeight(), - font->GetBaseline()); + int beginRank = CWordBreakTables::GetBeginRank(*strEnd); - xa4_curLine->x8_curX += w; - xa0_curBlock->x2c_lineX = std::max(xa0_curBlock->x2c_lineX, xa4_curLine->x8_curX); - xb0_curX += w; + if (endRank < aRank && endRank <= beginRank) { + aRank = endRank; + } else { + x18_textState.x48_font->GetSize(x18_textState.x0_drawStrOpts, w, h, str, rem); + } - x0_instList.emplace(x0_instList.cend(), std::make_shared(str, rem)); + } while (w + xa4_curLine->x8_curX > xa0_curBlock->xc_blockExtentX && rem > 1); + } + } - if (rem != len) - StartNewLine(); + xac_curY = std::max(xac_curY, font->GetMonoHeight()); - return rem; + xa4_curLine->TestLargestFont(font->GetMonoWidth(), font->GetMonoHeight(), font->GetBaseline()); + + xa4_curLine->x8_curX += w; + xa0_curBlock->x2c_lineX = std::max(xa0_curBlock->x2c_lineX, xa4_curLine->x8_curX); + xb0_curX += w; + + x0_instList.emplace(x0_instList.cend(), std::make_shared(str, rem)); + + if (rem != len) + StartNewLine(); + + return rem; } -void CTextExecuteBuffer::MoveWordLTR() -{ - xa4_curLine->x8_curX -= (xb0_curX + xbc_spaceDistance); - xa4_curLine->xc_curY = std::min(xa4_curLine->xc_curY, xb8_curWordY); - xbc_spaceDistance = 0; - --xa4_curLine->x4_wordCount; +void CTextExecuteBuffer::MoveWordLTR() { + xa4_curLine->x8_curX -= (xb0_curX + xbc_spaceDistance); + xa4_curLine->xc_curY = std::min(xa4_curLine->xc_curY, xb8_curWordY); + xbc_spaceDistance = 0; + --xa4_curLine->x4_wordCount; + TerminateLineLTR(); + + xa4_curLine = static_cast( + x0_instList + .emplace(xa8_curWordIt, std::make_shared(x18_textState.x80_just, x18_textState.x84_vjust, + xc0_imageBaseline)) + ->get()); + + // Dunno what's up with this in the original; seems fine without + // x0_instList.emplace(xa8_curWordIt, std::make_shared()); + + ++xa0_curBlock->x34_lineCount; +} + +void CTextExecuteBuffer::StartNewLine() { + if (xa4_curLine) + TerminateLine(); + + xa8_curWordIt = x0_instList.emplace( + x0_instList.cend(), + std::make_shared(x18_textState.x80_just, x18_textState.x84_vjust, xc0_imageBaseline)); + xa4_curLine = static_cast(xa8_curWordIt->get()); + xbc_spaceDistance = 0; + + StartNewWord(); + ++xa0_curBlock->x34_lineCount; +} + +void CTextExecuteBuffer::StartNewWord() { + xa8_curWordIt = x0_instList.emplace(x0_instList.cend(), std::make_shared()); + xb0_curX = 0; + xac_curY = 0; + xb4_curWordX = xa4_curLine->x8_curX; + xb8_curWordY = xa4_curLine->xc_curY; + ++xa4_curLine->x4_wordCount; +} + +void CTextExecuteBuffer::TerminateLine() { + if (xa0_curBlock->x14_dir == ETextDirection::Horizontal) TerminateLineLTR(); - - xa4_curLine = static_cast(x0_instList.emplace(xa8_curWordIt, - std::make_shared(x18_textState.x80_just, x18_textState.x84_vjust, xc0_imageBaseline))->get()); - - // Dunno what's up with this in the original; seems fine without - //x0_instList.emplace(xa8_curWordIt, std::make_shared()); - - ++xa0_curBlock->x34_lineCount; } -void CTextExecuteBuffer::StartNewLine() -{ - if (xa4_curLine) - TerminateLine(); +void CTextExecuteBuffer::TerminateLineLTR() { + if (!xa4_curLine->xc_curY /*&& x18_textState.IsFinishedLoading()*/) { + xa4_curLine->xc_curY = std::max(xa4_curLine->GetHeight(), x18_textState.x48_font->GetCarriageAdvance()); + } - xa8_curWordIt = x0_instList.emplace(x0_instList.cend(), - std::make_shared(x18_textState.x80_just, x18_textState.x84_vjust, xc0_imageBaseline)); - xa4_curLine = static_cast(xa8_curWordIt->get()); - xbc_spaceDistance = 0; - - StartNewWord(); - ++xa0_curBlock->x34_lineCount; + if (xa0_curBlock->x1c_vertJustification == EVerticalJustification::Full) { + xa0_curBlock->x30_lineY += xa4_curLine->xc_curY; + } else { + xa0_curBlock->x30_lineY += x18_textState.x78_extraLineSpace + xa4_curLine->xc_curY * x18_textState.x74_lineSpacing; + } } -void CTextExecuteBuffer::StartNewWord() -{ - xa8_curWordIt = x0_instList.emplace(x0_instList.cend(), std::make_shared()); - xb0_curX = 0; - xac_curY = 0; - xb4_curWordX = xa4_curLine->x8_curX; - xb8_curWordY = xa4_curLine->xc_curY; - ++xa4_curLine->x4_wordCount; +void CTextExecuteBuffer::AddPopState() { + x0_instList.emplace(x0_instList.cend(), std::make_shared()); + + x18_textState = xc4_stateStack.back(); + xc4_stateStack.pop_back(); + + if (!xa4_curLine->x8_curX) { + xa4_curLine->x28_just = x18_textState.x80_just; + xa4_curLine->x2c_vjust = x18_textState.x84_vjust; + } } -void CTextExecuteBuffer::TerminateLine() -{ - if (xa0_curBlock->x14_dir == ETextDirection::Horizontal) - TerminateLineLTR(); +void CTextExecuteBuffer::AddPushState() { + x0_instList.emplace(x0_instList.cend(), std::make_shared()); + xc4_stateStack.push_back(x18_textState); } -void CTextExecuteBuffer::TerminateLineLTR() -{ - if (!xa4_curLine->xc_curY /*&& x18_textState.IsFinishedLoading()*/) - { - xa4_curLine->xc_curY = std::max(xa4_curLine->GetHeight(), - x18_textState.x48_font->GetCarriageAdvance()); - } - - if (xa0_curBlock->x1c_vertJustification == EVerticalJustification::Full) - { - xa0_curBlock->x30_lineY += xa4_curLine->xc_curY; - } - else - { - xa0_curBlock->x30_lineY += x18_textState.x78_extraLineSpace + - xa4_curLine->xc_curY * x18_textState.x74_lineSpacing; - } +void CTextExecuteBuffer::AddVerticalJustification(EVerticalJustification vjust) { + x18_textState.x84_vjust = vjust; + if (!xa4_curLine) + return; + if (xa4_curLine->x8_curX) + return; + xa4_curLine->x2c_vjust = vjust; } -void CTextExecuteBuffer::AddPopState() -{ - x0_instList.emplace(x0_instList.cend(), std::make_shared()); - - x18_textState = xc4_stateStack.back(); - xc4_stateStack.pop_back(); - - if (!xa4_curLine->x8_curX) - { - xa4_curLine->x28_just = x18_textState.x80_just; - xa4_curLine->x2c_vjust = x18_textState.x84_vjust; - } +void CTextExecuteBuffer::AddJustification(EJustification just) { + x18_textState.x80_just = just; + if (!xa4_curLine) + return; + if (xa4_curLine->x8_curX) + return; + xa4_curLine->x28_just = just; } -void CTextExecuteBuffer::AddPushState() -{ - x0_instList.emplace(x0_instList.cend(), std::make_shared()); - xc4_stateStack.push_back(x18_textState); +void CTextExecuteBuffer::AddLineExtraSpace(s32 space) { + x0_instList.emplace(x0_instList.cend(), std::make_shared(space)); + x18_textState.x78_extraLineSpace = space; } -void CTextExecuteBuffer::AddVerticalJustification(EVerticalJustification vjust) -{ - x18_textState.x84_vjust = vjust; - if (!xa4_curLine) - return; - if (xa4_curLine->x8_curX) - return; - xa4_curLine->x2c_vjust = vjust; +void CTextExecuteBuffer::AddLineSpacing(float spacing) { + x0_instList.emplace(x0_instList.cend(), std::make_shared(spacing)); + x18_textState.x74_lineSpacing = spacing; } -void CTextExecuteBuffer::AddJustification(EJustification just) -{ - x18_textState.x80_just = just; - if (!xa4_curLine) - return; - if (xa4_curLine->x8_curX) - return; - xa4_curLine->x28_just = just; +void CTextExecuteBuffer::AddRemoveColorOverride(int idx) { + x0_instList.emplace(x0_instList.cend(), std::make_shared(idx)); } -void CTextExecuteBuffer::AddLineExtraSpace(s32 space) -{ - x0_instList.emplace(x0_instList.cend(), std::make_shared(space)); - x18_textState.x78_extraLineSpace = space; +void CTextExecuteBuffer::AddColorOverride(int idx, const CTextColor& color) { + x0_instList.emplace(x0_instList.cend(), std::make_shared(idx, color)); } -void CTextExecuteBuffer::AddLineSpacing(float spacing) -{ - x0_instList.emplace(x0_instList.cend(), std::make_shared(spacing)); - x18_textState.x74_lineSpacing = spacing; +void CTextExecuteBuffer::AddColor(EColorType tp, const CTextColor& color) { + x0_instList.emplace(x0_instList.cend(), std::make_shared(tp, color)); } -void CTextExecuteBuffer::AddRemoveColorOverride(int idx) -{ - x0_instList.emplace(x0_instList.cend(), std::make_shared(idx)); +void CTextExecuteBuffer::AddImage(const CFontImageDef& image) { + if (!xa4_curLine) + StartNewLine(); + + if (xa0_curBlock) { + const CTexture* tex = image.x4_texs[0].GetObj(); + int width = tex->GetWidth() * image.x14_cropFactor.x(); + int height = tex->GetHeight() * image.x14_cropFactor.y(); + + if (x18_textState.x7c_enableWordWrap && xa4_curLine->x8_curX + width > xa0_curBlock->xc_blockExtentX && + xa4_curLine->x4_wordCount > 1) + StartNewLine(); + + xa4_curLine->TestLargestImage(width, height, image.CalculateBaseline()); + + xa4_curLine->x8_curX += width; + if (xa4_curLine->x8_curX > width) + xa0_curBlock->x2c_lineX = xa4_curLine->x8_curX; + } + + x0_instList.emplace(x0_instList.cend(), std::make_shared(image)); } -void CTextExecuteBuffer::AddColorOverride(int idx, const CTextColor& color) -{ - x0_instList.emplace(x0_instList.cend(), std::make_shared(idx, color)); +void CTextExecuteBuffer::AddFont(const TToken& font) { + x0_instList.emplace(x0_instList.cend(), std::make_shared(font)); + x18_textState.x48_font = font; + + if (xa0_curBlock) + xa0_curBlock->TestLargestFont(font->GetMonoWidth(), font->GetMonoHeight(), font->GetBaseline()); + + if (xa4_curLine) + xa4_curLine->TestLargestFont(font->GetMonoWidth(), font->GetMonoHeight(), font->GetBaseline()); } -void CTextExecuteBuffer::AddColor(EColorType tp, const CTextColor& color) -{ - x0_instList.emplace(x0_instList.cend(), std::make_shared(tp, color)); +void CTextExecuteBuffer::EndBlock() { + if (xa4_curLine) + TerminateLine(); + xa4_curLine = nullptr; + xa0_curBlock = nullptr; } -void CTextExecuteBuffer::AddImage(const CFontImageDef& image) -{ - if (!xa4_curLine) - StartNewLine(); +void CTextExecuteBuffer::BeginBlock(s32 offX, s32 offY, s32 extX, s32 extY, bool imageBaseline, ETextDirection dir, + EJustification just, EVerticalJustification vjust) { + xc0_imageBaseline = imageBaseline; + xa0_curBlock = static_cast( + x0_instList + .emplace(x0_instList.cend(), std::make_shared(offX, offY, extX, extY, dir, just, vjust)) + ->get()); - if (xa0_curBlock) - { - const CTexture* tex = image.x4_texs[0].GetObj(); - int width = tex->GetWidth() * image.x14_cropFactor.x(); - int height = tex->GetHeight() * image.x14_cropFactor.y(); + if (x18_textState.x48_font) { + CRasterFont* font = x18_textState.x48_font.GetObj(); + s32 baseline = font->GetBaseline(); + s32 monoH = font->GetMonoHeight(); + s32 monoW = font->GetMonoWidth(); + xa0_curBlock->TestLargestFont(monoW, monoH, baseline); + } - if (x18_textState.x7c_enableWordWrap && - xa4_curLine->x8_curX + width > xa0_curBlock->xc_blockExtentX && xa4_curLine->x4_wordCount > 1) - StartNewLine(); - - xa4_curLine->TestLargestImage(width, height, image.CalculateBaseline()); - - xa4_curLine->x8_curX += width; - if (xa4_curLine->x8_curX > width) - xa0_curBlock->x2c_lineX = xa4_curLine->x8_curX; - } - - x0_instList.emplace(x0_instList.cend(), std::make_shared(image)); + x18_textState.x0_drawStrOpts.x0_direction = dir; + x18_textState.x80_just = just; + x18_textState.x84_vjust = vjust; } -void CTextExecuteBuffer::AddFont(const TToken& font) -{ - x0_instList.emplace(x0_instList.cend(), std::make_shared(font)); - x18_textState.x48_font = font; - - if (xa0_curBlock) - xa0_curBlock->TestLargestFont(font->GetMonoWidth(), - font->GetMonoHeight(), - font->GetBaseline()); - - if (xa4_curLine) - xa4_curLine->TestLargestFont(font->GetMonoWidth(), - font->GetMonoHeight(), - font->GetBaseline()); +void CTextExecuteBuffer::Clear() { + x0_instList.clear(); + x18_textState = CSaveableState(); + xa0_curBlock = nullptr; + xa4_curLine = nullptr; + xa8_curWordIt = x0_instList.begin(); + xb4_curWordX = 0; + xb8_curWordY = 0; + xbc_spaceDistance = 0; } -void CTextExecuteBuffer::EndBlock() -{ - if (xa4_curLine) - TerminateLine(); - xa4_curLine = nullptr; - xa0_curBlock = nullptr; -} - -void CTextExecuteBuffer::BeginBlock(s32 offX, s32 offY, s32 extX, s32 extY, - bool imageBaseline, ETextDirection dir, EJustification just, - EVerticalJustification vjust) -{ - xc0_imageBaseline = imageBaseline; - xa0_curBlock = static_cast(x0_instList.emplace(x0_instList.cend(), - std::make_shared(offX, offY, extX, extY, dir, just, vjust))->get()); - - if (x18_textState.x48_font) - { - CRasterFont* font = x18_textState.x48_font.GetObj(); - s32 baseline = font->GetBaseline(); - s32 monoH = font->GetMonoHeight(); - s32 monoW = font->GetMonoWidth(); - xa0_curBlock->TestLargestFont(monoW, monoH, baseline); - } - - x18_textState.x0_drawStrOpts.x0_direction = dir; - x18_textState.x80_just = just; - x18_textState.x84_vjust = vjust; -} - -void CTextExecuteBuffer::Clear() -{ - x0_instList.clear(); - x18_textState = CSaveableState(); - xa0_curBlock = nullptr; - xa4_curLine = nullptr; - xa8_curWordIt = x0_instList.begin(); - xb4_curWordX = 0; - xb8_curWordY = 0; - xbc_spaceDistance = 0; -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CTextExecuteBuffer.hpp b/Runtime/GuiSys/CTextExecuteBuffer.hpp index 11573c650..daa884925 100644 --- a/Runtime/GuiSys/CTextExecuteBuffer.hpp +++ b/Runtime/GuiSys/CTextExecuteBuffer.hpp @@ -4,74 +4,65 @@ #include "CGuiTextSupport.hpp" #include -namespace urde -{ +namespace urde { class CInstruction; class CFontImageDef; class CTextRenderBuffer; class CBlockInstruction; class CLineInstruction; -class CTextExecuteBuffer -{ - friend class CGuiTextSupport; - friend class CTextRenderBufferPages; - using InstList = std::list>; +class CTextExecuteBuffer { + friend class CGuiTextSupport; + friend class CTextRenderBufferPages; + using InstList = std::list>; - InstList x0_instList; - u32 x14_ = 0; - CSaveableState x18_textState; - CBlockInstruction* xa0_curBlock = nullptr; - CLineInstruction* xa4_curLine = nullptr; - InstList::iterator xa8_curWordIt; - s32 xac_curY; - s32 xb0_curX; - s32 xb4_curWordX = 0; - s32 xb8_curWordY = 0; - s32 xbc_spaceDistance = 0; - bool xc0_imageBaseline = false; - std::list xc4_stateStack; - u32 xd8_ = 0; + InstList x0_instList; + u32 x14_ = 0; + CSaveableState x18_textState; + CBlockInstruction* xa0_curBlock = nullptr; + CLineInstruction* xa4_curLine = nullptr; + InstList::iterator xa8_curWordIt; + s32 xac_curY; + s32 xb0_curX; + s32 xb4_curWordX = 0; + s32 xb8_curWordY = 0; + s32 xbc_spaceDistance = 0; + bool xc0_imageBaseline = false; + std::list xc4_stateStack; + u32 xd8_ = 0; public: - CTextExecuteBuffer() - { - xa8_curWordIt = x0_instList.begin(); - } + CTextExecuteBuffer() { xa8_curWordIt = x0_instList.begin(); } - CTextRenderBuffer BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const; - CTextRenderBuffer BuildRenderBufferPage(InstList::const_iterator start, - InstList::const_iterator pgStart, - InstList::const_iterator pgEnd, - CGuiWidget::EGuiModelDrawFlags df) const; - std::list BuildRenderBufferPages(const zeus::CVector2i& extent, - CGuiWidget::EGuiModelDrawFlags df) const; - std::vector GetAssets() const; - void AddString(const char16_t* str, int len); - void AddStringFragment(const char16_t* str, int len); - int WrapOneLTR(const char16_t* str, int len); - void MoveWordLTR(); - void StartNewLine(); - void StartNewWord(); - void TerminateLine(); - void TerminateLineLTR(); - void AddPopState(); - void AddPushState(); - void AddVerticalJustification(EVerticalJustification vjust); - void AddJustification(EJustification just); - void AddLineExtraSpace(s32 space); - void AddLineSpacing(float spacing); - void AddRemoveColorOverride(int idx); - void AddColorOverride(int idx, const CTextColor& color); - void AddColor(EColorType, const CTextColor& color); - void AddImage(const CFontImageDef& image); - void AddFont(const TToken& font); - void EndBlock(); - void BeginBlock(s32 offX, s32 offY, s32 extX, s32 extY, - bool imageBaseline, ETextDirection dir, EJustification just, - EVerticalJustification vjust); - void Clear(); + CTextRenderBuffer BuildRenderBuffer(CGuiWidget::EGuiModelDrawFlags df) const; + CTextRenderBuffer BuildRenderBufferPage(InstList::const_iterator start, InstList::const_iterator pgStart, + InstList::const_iterator pgEnd, CGuiWidget::EGuiModelDrawFlags df) const; + std::list BuildRenderBufferPages(const zeus::CVector2i& extent, + CGuiWidget::EGuiModelDrawFlags df) const; + std::vector GetAssets() const; + void AddString(const char16_t* str, int len); + void AddStringFragment(const char16_t* str, int len); + int WrapOneLTR(const char16_t* str, int len); + void MoveWordLTR(); + void StartNewLine(); + void StartNewWord(); + void TerminateLine(); + void TerminateLineLTR(); + void AddPopState(); + void AddPushState(); + void AddVerticalJustification(EVerticalJustification vjust); + void AddJustification(EJustification just); + void AddLineExtraSpace(s32 space); + void AddLineSpacing(float spacing); + void AddRemoveColorOverride(int idx); + void AddColorOverride(int idx, const CTextColor& color); + void AddColor(EColorType, const CTextColor& color); + void AddImage(const CFontImageDef& image); + void AddFont(const TToken& font); + void EndBlock(); + void BeginBlock(s32 offX, s32 offY, s32 extX, s32 extY, bool imageBaseline, ETextDirection dir, EJustification just, + EVerticalJustification vjust); + void Clear(); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CTextParser.cpp b/Runtime/GuiSys/CTextParser.cpp index 4b533e858..055d45520 100644 --- a/Runtime/GuiSys/CTextParser.cpp +++ b/Runtime/GuiSys/CTextParser.cpp @@ -2,367 +2,299 @@ #include "CFontImageDef.hpp" #include "CTextExecuteBuffer.hpp" -namespace urde -{ +namespace urde { -static float u16stof(char16_t* str) -{ - char cstr[16]; - int i; - for (i=0 ; i<15 && str[i] != u'\0' ; ++i) - cstr[i] = str[i]; - cstr[i] = '\0'; - return strtof(cstr, nullptr); +static float u16stof(char16_t* str) { + char cstr[16]; + int i; + for (i = 0; i < 15 && str[i] != u'\0'; ++i) + cstr[i] = str[i]; + cstr[i] = '\0'; + return strtof(cstr, nullptr); } -CTextColor CTextParser::ParseColor(const char16_t* str, int len) -{ - u8 r = GetColorValue(str + 1); - u8 g = GetColorValue(str + 3); - u8 b = GetColorValue(str + 5); - u8 a = 0xff; - if (len == 9) - a = GetColorValue(str + 7); - CTextColor ret; - ret.fromRGBA8(r, g, b, a); - return ret; +CTextColor CTextParser::ParseColor(const char16_t* str, int len) { + u8 r = GetColorValue(str + 1); + u8 g = GetColorValue(str + 3); + u8 b = GetColorValue(str + 5); + u8 a = 0xff; + if (len == 9) + a = GetColorValue(str + 7); + CTextColor ret; + ret.fromRGBA8(r, g, b, a); + return ret; } -u8 CTextParser::GetColorValue(const char16_t* str) -{ - return (FromHex(str[0]) << 4) + FromHex(str[1]); +u8 CTextParser::GetColorValue(const char16_t* str) { return (FromHex(str[0]) << 4) + FromHex(str[1]); } + +u32 CTextParser::FromHex(char16_t ch) { + if (ch >= u'0' && ch <= u'9') + return ch - u'0'; + + if (ch >= u'A' && ch <= u'F') + return ch - u'A' + 10; + + if (ch >= u'a' && ch <= u'f') + return ch - u'a' + 10; + + return 0; } -u32 CTextParser::FromHex(char16_t ch) -{ - if (ch >= u'0' && ch <= u'9') - return ch - u'0'; +s32 CTextParser::ParseInt(const char16_t* str, int len, bool signVal) { + bool neg = false; + int procCur = 0; + if (signVal && len && *str == u'-') { + neg = true; + procCur = 1; + } - if (ch >= u'A' && ch <= u'F') - return ch - u'A' + 10; + int val = 0; + while (len > procCur) { + val *= 10; + wchar_t ch = str[procCur]; + val += ch - u'0'; + ++procCur; + } - if (ch >= u'a' && ch <= u'f') - return ch - u'a' + 10; - - return 0; + return neg ? -val : val; } -s32 CTextParser::ParseInt(const char16_t* str, int len, bool signVal) -{ - bool neg = false; - int procCur = 0; - if (signVal && len && *str == u'-') - { - neg = true; - procCur = 1; - } - - int val = 0; - while (len > procCur) - { - val *= 10; - wchar_t ch = str[procCur]; - val += ch - u'0'; - ++procCur; - } - - return neg ? -val : val; +bool CTextParser::Equals(const char16_t* str, int len, const char16_t* other) { + for (int i = 0; *other && i < len; ++i, ++str, ++other) { + if (*str != *other) + return false; + } + return *other == u'\0'; } -bool CTextParser::Equals(const char16_t* str, int len, const char16_t* other) -{ - for (int i=0 ; *other && i>* txtrMap) -{ - if (BeginsWith(str, len, u"font=")) - { - TToken font = GetFont(str + 5, len - 5); - out.AddFont(font); + const std::vector>* txtrMap) { + if (BeginsWith(str, len, u"font=")) { + TToken font = GetFont(str + 5, len - 5); + out.AddFont(font); + } else if (BeginsWith(str, len, u"image=")) { + CFontImageDef image = GetImage(str + 6, len - 6, txtrMap); + out.AddImage(image); + } else if (BeginsWith(str, len, u"fg-color=")) { + CTextColor color = ParseColor(str + 9, len - 9); + out.AddColor(EColorType::Foreground, color); + } else if (BeginsWith(str, len, u"main-color=")) { + CTextColor color = ParseColor(str + 11, len - 11); + out.AddColor(EColorType::Main, color); + } else if (BeginsWith(str, len, u"geometry-color=")) { + CTextColor color = ParseColor(str + 15, len - 15); + out.AddColor(EColorType::Geometry, color); + } else if (BeginsWith(str, len, u"outline-color=")) { + CTextColor color = ParseColor(str + 14, len - 14); + out.AddColor(EColorType::Outline, color); + } else if (BeginsWith(str, len, u"color")) { + const char16_t* valCur = str + 7; + len -= 7; + int val = str[6] - u'0'; + if (str[7] >= u'0' && str[7] <= u'9') { + ++valCur; + --len; + val *= 10; + val += str[7] - u'0'; } - else if (BeginsWith(str, len, u"image=")) - { - CFontImageDef image = GetImage(str + 6, len - 6, txtrMap); - out.AddImage(image); - } - else if (BeginsWith(str, len, u"fg-color=")) - { - CTextColor color = ParseColor(str + 9, len - 9); - out.AddColor(EColorType::Foreground, color); - } - else if (BeginsWith(str, len, u"main-color=")) - { - CTextColor color = ParseColor(str + 11, len - 11); - out.AddColor(EColorType::Main, color); - } - else if (BeginsWith(str, len, u"geometry-color=")) - { - CTextColor color = ParseColor(str + 15, len - 15); - out.AddColor(EColorType::Geometry, color); - } - else if (BeginsWith(str, len, u"outline-color=")) - { - CTextColor color = ParseColor(str + 14, len - 14); - out.AddColor(EColorType::Outline, color); - } - else if (BeginsWith(str, len, u"color")) - { - const char16_t* valCur = str + 7; - len -= 7; - int val = str[6] - u'0'; - if (str[7] >= u'0' && str[7] <= u'9') - { - ++valCur; - --len; - val *= 10; - val += str[7] - u'0'; - } - if (Equals(valCur + 10, len - 10, u"no")) - out.AddRemoveColorOverride(val); - else - { - CTextColor color = ParseColor(str + 10, len - 10); - out.AddColorOverride(val, color); - } - } - else if (BeginsWith(str, len, u"line-spacing=")) - { - out.AddLineSpacing(ParseInt(str + 13, len - 13, true) / 100.0); - } - else if (BeginsWith(str, len, u"line-extra-space=")) - { - out.AddLineExtraSpace(ParseInt(str + 17, len - 17, true)); - } - else if (BeginsWith(str, len, u"just=")) - { - if (Equals(str + 5, len - 5, u"left")) - out.AddJustification(EJustification::Left); - else if (Equals(str + 5, len - 5, u"center")) - out.AddJustification(EJustification::Center); - else if (Equals(str + 5, len - 5, u"right")) - out.AddJustification(EJustification::Right); - else if (Equals(str + 5, len - 5, u"full")) - out.AddJustification(EJustification::Full); - else if (Equals(str + 5, len - 5, u"nleft")) - out.AddJustification(EJustification::NLeft); - else if (Equals(str + 5, len - 5, u"ncenter")) - out.AddJustification(EJustification::NCenter); - else if (Equals(str + 5, len - 5, u"nright")) - out.AddJustification(EJustification::NRight); - } - else if (BeginsWith(str, len, u"vjust=")) - { - if (Equals(str + 6, len - 6, u"top")) - out.AddVerticalJustification(EVerticalJustification::Top); - else if (Equals(str + 6, len - 6, u"center")) - out.AddVerticalJustification(EVerticalJustification::Center); - else if (Equals(str + 6, len - 6, u"bottom")) - out.AddVerticalJustification(EVerticalJustification::Bottom); - else if (Equals(str + 6, len - 6, u"full")) - out.AddVerticalJustification(EVerticalJustification::Full); - else if (Equals(str + 6, len - 6, u"ntop")) - out.AddVerticalJustification(EVerticalJustification::NTop); - else if (Equals(str + 6, len - 6, u"ncenter")) - out.AddVerticalJustification(EVerticalJustification::NCenter); - else if (Equals(str + 6, len - 6, u"nbottom")) - out.AddVerticalJustification(EVerticalJustification::NBottom); - } - else if (Equals(str, len, u"push")) - { - out.AddPushState(); - } - else if (Equals(str, len, u"pop")) - { - out.AddPopState(); + if (Equals(valCur + 10, len - 10, u"no")) + out.AddRemoveColorOverride(val); + else { + CTextColor color = ParseColor(str + 10, len - 10); + out.AddColorOverride(val, color); } + } else if (BeginsWith(str, len, u"line-spacing=")) { + out.AddLineSpacing(ParseInt(str + 13, len - 13, true) / 100.0); + } else if (BeginsWith(str, len, u"line-extra-space=")) { + out.AddLineExtraSpace(ParseInt(str + 17, len - 17, true)); + } else if (BeginsWith(str, len, u"just=")) { + if (Equals(str + 5, len - 5, u"left")) + out.AddJustification(EJustification::Left); + else if (Equals(str + 5, len - 5, u"center")) + out.AddJustification(EJustification::Center); + else if (Equals(str + 5, len - 5, u"right")) + out.AddJustification(EJustification::Right); + else if (Equals(str + 5, len - 5, u"full")) + out.AddJustification(EJustification::Full); + else if (Equals(str + 5, len - 5, u"nleft")) + out.AddJustification(EJustification::NLeft); + else if (Equals(str + 5, len - 5, u"ncenter")) + out.AddJustification(EJustification::NCenter); + else if (Equals(str + 5, len - 5, u"nright")) + out.AddJustification(EJustification::NRight); + } else if (BeginsWith(str, len, u"vjust=")) { + if (Equals(str + 6, len - 6, u"top")) + out.AddVerticalJustification(EVerticalJustification::Top); + else if (Equals(str + 6, len - 6, u"center")) + out.AddVerticalJustification(EVerticalJustification::Center); + else if (Equals(str + 6, len - 6, u"bottom")) + out.AddVerticalJustification(EVerticalJustification::Bottom); + else if (Equals(str + 6, len - 6, u"full")) + out.AddVerticalJustification(EVerticalJustification::Full); + else if (Equals(str + 6, len - 6, u"ntop")) + out.AddVerticalJustification(EVerticalJustification::NTop); + else if (Equals(str + 6, len - 6, u"ncenter")) + out.AddVerticalJustification(EVerticalJustification::NCenter); + else if (Equals(str + 6, len - 6, u"nbottom")) + out.AddVerticalJustification(EVerticalJustification::NBottom); + } else if (Equals(str, len, u"push")) { + out.AddPushState(); + } else if (Equals(str, len, u"pop")) { + out.AddPopState(); + } } CFontImageDef CTextParser::GetImage(const char16_t* str, int len, - const std::vector>* txtrMap) -{ - int commaCount = 0; - for (int i=0 ; i>* txtrMap) { + int commaCount = 0; + for (int i = 0; i < len; ++i) + if (str[i] == u',') + ++commaCount; - if (commaCount) - { - std::u16string iterable(str, len); - size_t tokenPos; - size_t commaPos; - commaPos = iterable.find(u','); - iterable[commaPos] = u'\0'; - tokenPos = commaPos + 1; + if (commaCount) { + std::u16string iterable(str, len); + size_t tokenPos; + size_t commaPos; + commaPos = iterable.find(u','); + iterable[commaPos] = u'\0'; + tokenPos = commaPos + 1; - auto AdvanceCommaPos = [&]() - { - commaPos = iterable.find(u',', tokenPos); - if (commaPos == std::u16string::npos) - commaPos = iterable.size(); - iterable[commaPos] = u'\0'; - }; + auto AdvanceCommaPos = [&]() { + commaPos = iterable.find(u',', tokenPos); + if (commaPos == std::u16string::npos) + commaPos = iterable.size(); + iterable[commaPos] = u'\0'; + }; - auto AdvanceTokenPos = [&]() - { - tokenPos = commaPos + 1; - }; + auto AdvanceTokenPos = [&]() { tokenPos = commaPos + 1; }; - if (BeginsWith(str, len, u"A")) - { - /* Animated texture array */ - AdvanceCommaPos(); - float interval = u16stof(&iterable[tokenPos]); - AdvanceTokenPos(); + if (BeginsWith(str, len, u"A")) { + /* Animated texture array */ + AdvanceCommaPos(); + float interval = u16stof(&iterable[tokenPos]); + AdvanceTokenPos(); - std::vector> texs; - texs.reserve(commaCount - 1); - do - { - AdvanceCommaPos(); - texs.push_back(x0_store.GetObj({SBIG('TXTR'), - GetAssetIdFromString(&iterable[tokenPos], len, txtrMap)})); - AdvanceTokenPos(); - } while (commaPos != iterable.size()); + std::vector> texs; + texs.reserve(commaCount - 1); + do { + AdvanceCommaPos(); + texs.push_back(x0_store.GetObj({SBIG('TXTR'), GetAssetIdFromString(&iterable[tokenPos], len, txtrMap)})); + AdvanceTokenPos(); + } while (commaPos != iterable.size()); - return CFontImageDef(texs, interval, zeus::CVector2f(1.f, 1.f)); - } - else if (BeginsWith(str, len, u"SA")) - { - /* Scaled and animated texture array */ - AdvanceCommaPos(); - float interval = u16stof(&iterable[tokenPos]); - AdvanceTokenPos(); + return CFontImageDef(texs, interval, zeus::CVector2f(1.f, 1.f)); + } else if (BeginsWith(str, len, u"SA")) { + /* Scaled and animated texture array */ + AdvanceCommaPos(); + float interval = u16stof(&iterable[tokenPos]); + AdvanceTokenPos(); - AdvanceCommaPos(); - float cropX = u16stof(&iterable[tokenPos]); - AdvanceTokenPos(); + AdvanceCommaPos(); + float cropX = u16stof(&iterable[tokenPos]); + AdvanceTokenPos(); - AdvanceCommaPos(); - float cropY = u16stof(&iterable[tokenPos]); - AdvanceTokenPos(); + AdvanceCommaPos(); + float cropY = u16stof(&iterable[tokenPos]); + AdvanceTokenPos(); - std::vector> texs; - texs.reserve(commaCount - 3); - do - { - AdvanceCommaPos(); - texs.push_back(x0_store.GetObj({SBIG('TXTR'), - GetAssetIdFromString(&iterable[tokenPos], len, txtrMap)})); - AdvanceTokenPos(); - } while (commaPos != iterable.size()); + std::vector> texs; + texs.reserve(commaCount - 3); + do { + AdvanceCommaPos(); + texs.push_back(x0_store.GetObj({SBIG('TXTR'), GetAssetIdFromString(&iterable[tokenPos], len, txtrMap)})); + AdvanceTokenPos(); + } while (commaPos != iterable.size()); - return CFontImageDef(texs, interval, zeus::CVector2f(cropX, cropY)); - } - else if (BeginsWith(str, len, u"SI")) - { - /* Scaled single texture */ - AdvanceCommaPos(); - float cropX = u16stof(&iterable[tokenPos]); - AdvanceTokenPos(); + return CFontImageDef(texs, interval, zeus::CVector2f(cropX, cropY)); + } else if (BeginsWith(str, len, u"SI")) { + /* Scaled single texture */ + AdvanceCommaPos(); + float cropX = u16stof(&iterable[tokenPos]); + AdvanceTokenPos(); - AdvanceCommaPos(); - float cropY = u16stof(&iterable[tokenPos]); - AdvanceTokenPos(); + AdvanceCommaPos(); + float cropY = u16stof(&iterable[tokenPos]); + AdvanceTokenPos(); - AdvanceCommaPos(); - TToken tex = x0_store.GetObj({SBIG('TXTR'), - GetAssetIdFromString(&iterable[tokenPos], len, txtrMap)}); - AdvanceTokenPos(); + AdvanceCommaPos(); + TToken tex = x0_store.GetObj({SBIG('TXTR'), GetAssetIdFromString(&iterable[tokenPos], len, txtrMap)}); + AdvanceTokenPos(); - return CFontImageDef(tex, zeus::CVector2f(cropX, cropY)); - } + return CFontImageDef(tex, zeus::CVector2f(cropX, cropY)); } + } - TToken tex = x0_store.GetObj({SBIG('TXTR'), GetAssetIdFromString(str, len, txtrMap)}); - return CFontImageDef(tex, zeus::CVector2f(1.f, 1.f)); + TToken tex = x0_store.GetObj({SBIG('TXTR'), GetAssetIdFromString(str, len, txtrMap)}); + return CFontImageDef(tex, zeus::CVector2f(1.f, 1.f)); } CAssetId CTextParser::GetAssetIdFromString(const char16_t* str, int len, - const std::vector>* txtrMap) -{ - u8 r = GetColorValue(str); - u8 g = GetColorValue(str + 2); - u8 b = GetColorValue(str + 4); - u8 a = GetColorValue(str + 6); - CAssetId id = ((r << 24) | (g << 16) | (b << 8) | a) & 0xffffffff; + const std::vector>* txtrMap) { + u8 r = GetColorValue(str); + u8 g = GetColorValue(str + 2); + u8 b = GetColorValue(str + 4); + u8 a = GetColorValue(str + 6); + CAssetId id = ((r << 24) | (g << 16) | (b << 8) | a) & 0xffffffff; - if (len == 16) - { - r = GetColorValue(str + 8); - g = GetColorValue(str + 10); - b = GetColorValue(str + 12); - a = GetColorValue(str + 14); - id = (id.Value() << 32) | (((r << 24) | (g << 16) | (b << 8) | a) & 0xffffffff); - } + if (len == 16) { + r = GetColorValue(str + 8); + g = GetColorValue(str + 10); + b = GetColorValue(str + 12); + a = GetColorValue(str + 14); + id = (id.Value() << 32) | (((r << 24) | (g << 16) | (b << 8) | a) & 0xffffffff); + } - if (txtrMap) - { - auto search = rstl::binary_find(txtrMap->begin(), txtrMap->end(), id, - [](const std::pair& a) { return a.first; }); - if (search != txtrMap->end()) - id = search->second; - } + if (txtrMap) { + auto search = rstl::binary_find(txtrMap->begin(), txtrMap->end(), id, + [](const std::pair& a) { return a.first; }); + if (search != txtrMap->end()) + id = search->second; + } - return id; + return id; } -TToken CTextParser::GetFont(const char16_t* str, int len) -{ - return x0_store.GetObj({SBIG('FONT'), GetAssetIdFromString(str, len, nullptr)}); +TToken CTextParser::GetFont(const char16_t* str, int len) { + return x0_store.GetObj({SBIG('FONT'), GetAssetIdFromString(str, len, nullptr)}); } void CTextParser::ParseText(CTextExecuteBuffer& out, const char16_t* str, int len, - const std::vector>* txtrMap) -{ - int b=0, e=0; - for (b=0, e=0 ; str[e] && (len == -1 || e < len) ;) - { - if (str[e] != u'&') - { - ++e; - continue; - } - if ((len == -1 || e+1 < len) && str[e+1] != u'&') - { - if (e > b) - out.AddString(str + b, e - b); - ++e; - b = e; - - while (str[e] && (len == -1 || e < len) && str[e] != u';') - ++e; - - ParseTag(out, str + b, e - b, txtrMap); - b = e + 1; - } - else - { - out.AddString(str + b, e + 1 - b); - e += 2; - b = e; - } + const std::vector>* txtrMap) { + int b = 0, e = 0; + for (b = 0, e = 0; str[e] && (len == -1 || e < len);) { + if (str[e] != u'&') { + ++e; + continue; } - - if (e > b) + if ((len == -1 || e + 1 < len) && str[e + 1] != u'&') { + if (e > b) out.AddString(str + b, e - b); + ++e; + b = e; + + while (str[e] && (len == -1 || e < len) && str[e] != u';') + ++e; + + ParseTag(out, str + b, e - b, txtrMap); + b = e + 1; + } else { + out.AddString(str + b, e + 1 - b); + e += 2; + b = e; + } + } + + if (e > b) + out.AddString(str + b, e - b); } -} +} // namespace urde diff --git a/Runtime/GuiSys/CTextParser.hpp b/Runtime/GuiSys/CTextParser.hpp index 055a36355..dc72f69e1 100644 --- a/Runtime/GuiSys/CTextParser.hpp +++ b/Runtime/GuiSys/CTextParser.hpp @@ -2,34 +2,30 @@ #include "CGuiTextSupport.hpp" -namespace urde -{ +namespace urde { class CTextExecuteBuffer; class CFontImageDef; -class CTextParser -{ - IObjectStore& x0_store; +class CTextParser { + IObjectStore& x0_store; - static CTextColor ParseColor(const char16_t* str, int len); - static u8 GetColorValue(const char16_t* str); - static u32 FromHex(char16_t ch); - static s32 ParseInt(const char16_t* str, int len, bool signVal); - static CAssetId GetAssetIdFromString(const char16_t* str, int len, - const std::vector>* txtrMap); - static bool Equals(const char16_t* str, int len, const char16_t* other); - static bool BeginsWith(const char16_t* str, int len, const char16_t* other); - void ParseTag(CTextExecuteBuffer& out, const char16_t* str, int len, - const std::vector>* txtrMap); - CFontImageDef GetImage(const char16_t* str, int len, - const std::vector>* txtrMap); - TToken GetFont(const char16_t* str, int len); + static CTextColor ParseColor(const char16_t* str, int len); + static u8 GetColorValue(const char16_t* str); + static u32 FromHex(char16_t ch); + static s32 ParseInt(const char16_t* str, int len, bool signVal); + static CAssetId GetAssetIdFromString(const char16_t* str, int len, + const std::vector>* txtrMap); + static bool Equals(const char16_t* str, int len, const char16_t* other); + static bool BeginsWith(const char16_t* str, int len, const char16_t* other); + void ParseTag(CTextExecuteBuffer& out, const char16_t* str, int len, + const std::vector>* txtrMap); + CFontImageDef GetImage(const char16_t* str, int len, const std::vector>* txtrMap); + TToken GetFont(const char16_t* str, int len); public: - CTextParser(IObjectStore& store) : x0_store(store) {} - void ParseText(CTextExecuteBuffer& out, const char16_t* str, int len, - const std::vector>* txtrMap); + CTextParser(IObjectStore& store) : x0_store(store) {} + void ParseText(CTextExecuteBuffer& out, const char16_t* str, int len, + const std::vector>* txtrMap); }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CTextRenderBuffer.cpp b/Runtime/GuiSys/CTextRenderBuffer.cpp index 1dc2349af..5d818d251 100644 --- a/Runtime/GuiSys/CTextRenderBuffer.cpp +++ b/Runtime/GuiSys/CTextRenderBuffer.cpp @@ -9,290 +9,241 @@ #include "CInstruction.hpp" #include "Graphics/Shaders/CTextSupportShader.hpp" -namespace urde -{ +namespace urde { -CTextRenderBuffer::CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df) -: x0_mode(mode), m_drawFlags(df) {} +CTextRenderBuffer::CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df) : x0_mode(mode), m_drawFlags(df) {} -CTextRenderBuffer::BooImage::BooImage(const CFontImageDef& imgDef, const zeus::CVector2i& offset) -: m_imageDef(imgDef) -{ - m_imageData.SetMetrics(imgDef, offset); +CTextRenderBuffer::BooImage::BooImage(const CFontImageDef& imgDef, const zeus::CVector2i& offset) : m_imageDef(imgDef) { + m_imageData.SetMetrics(imgDef, offset); } -void CTextRenderBuffer::BooPrimitiveMark::SetOpacity(CTextRenderBuffer& rb, float opacity) -{ - switch (m_cmd) - { - case Command::CharacterRender: - { - BooFontCharacters& fc = rb.m_fontCharacters[m_bindIdx]; - CTextSupportShader::CharacterInstance& inst = fc.m_charData[m_instIdx]; - inst.m_mulColor.a() = opacity; - fc.m_dirty = true; - break; - } - case Command::ImageRender: - { - BooImage& img = rb.m_images[m_bindIdx]; - img.m_imageData.m_color.a() = opacity; - img.m_dirty = true; - break; - } - default: break; - } +void CTextRenderBuffer::BooPrimitiveMark::SetOpacity(CTextRenderBuffer& rb, float opacity) { + switch (m_cmd) { + case Command::CharacterRender: { + BooFontCharacters& fc = rb.m_fontCharacters[m_bindIdx]; + CTextSupportShader::CharacterInstance& inst = fc.m_charData[m_instIdx]; + inst.m_mulColor.a() = opacity; + fc.m_dirty = true; + break; + } + case Command::ImageRender: { + BooImage& img = rb.m_images[m_bindIdx]; + img.m_imageData.m_color.a() = opacity; + img.m_dirty = true; + break; + } + default: + break; + } } -void CTextRenderBuffer::CommitResources() -{ - if (m_committed) - return; - m_committed = true; +void CTextRenderBuffer::CommitResources() { + if (m_committed) + return; + m_committed = true; - /* Ensure font textures are ready outside transaction */ - for (BooFontCharacters& chs : m_fontCharacters) - chs.m_font->GetTexture(); + /* Ensure font textures are ready outside transaction */ + for (BooFontCharacters& chs : m_fontCharacters) + chs.m_font->GetTexture(); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_uniBuf = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory); - auto uBufInfo = m_uniBuf.getBufferInfo(); - decltype(uBufInfo) uBufInfo2; - if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) - { - m_uniBuf2 = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory); - uBufInfo2 = m_uniBuf2.getBufferInfo(); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_uniBuf = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory); + auto uBufInfo = m_uniBuf.getBufferInfo(); + decltype(uBufInfo) uBufInfo2; + if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { + m_uniBuf2 = CTextSupportShader::s_Uniforms.allocateBlock(CGraphics::g_BooFactory); + uBufInfo2 = m_uniBuf2.getBufferInfo(); + } + + for (BooFontCharacters& chs : m_fontCharacters) { + chs.m_instBuf = CTextSupportShader::s_CharInsts.allocateBlock(CGraphics::g_BooFactory, chs.m_charCount); + auto iBufInfo = chs.m_instBuf.getBufferInfo(); + + boo::ObjToken uniforms[] = {uBufInfo.first.get()}; + boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex}; + size_t unioffs[] = {size_t(uBufInfo.second)}; + size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)}; + boo::ObjToken texs[] = {chs.m_font->GetTexture()}; + chs.m_dataBinding = ctx.newShaderDataBinding(CTextSupportShader::SelectTextPipeline(m_drawFlags), nullptr, + iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs, + unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second); + + if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { + uniforms[0] = uBufInfo2.first.get(); + unioffs[0] = size_t(uBufInfo2.second); + chs.m_dataBinding2 = ctx.newShaderDataBinding(CTextSupportShader::GetTextAdditiveOverdrawPipeline(), nullptr, + iBufInfo.first.get(), nullptr, 1, uniforms, unistages, unioffs, + unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second); + } + } + + for (BooImage& img : m_images) { + img.m_instBuf = CTextSupportShader::s_ImgInsts.allocateBlock(CGraphics::g_BooFactory, 1); + auto iBufInfo = img.m_instBuf.getBufferInfo(); + + boo::ObjToken uniforms[] = {uBufInfo.first.get()}; + boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex}; + size_t unioffs[] = {size_t(uBufInfo.second)}; + size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)}; + img.m_dataBinding.reserve(img.m_imageDef.x4_texs.size()); + for (TToken& tex : img.m_imageDef.x4_texs) { + boo::ObjToken texs[] = {tex->GetBooTexture()}; + texs[0]->setClampMode(boo::TextureClampMode::ClampToEdge); + img.m_dataBinding.push_back(ctx.newShaderDataBinding( + CTextSupportShader::SelectImagePipeline(m_drawFlags), nullptr, iBufInfo.first.get(), nullptr, 1, uniforms, + unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second)); + } + + if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { + uniforms[0] = uBufInfo2.first.get(); + unioffs[0] = size_t(uBufInfo2.second); + img.m_dataBinding2.reserve(img.m_imageDef.x4_texs.size()); + for (TToken& tex : img.m_imageDef.x4_texs) { + boo::ObjToken texs[] = {tex->GetBooTexture()}; + img.m_dataBinding2.push_back(ctx.newShaderDataBinding( + CTextSupportShader::GetImageAdditiveOverdrawPipeline(), nullptr, iBufInfo.first.get(), nullptr, 1, + uniforms, unistages, unioffs, unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second)); } - - for (BooFontCharacters& chs : m_fontCharacters) - { - chs.m_instBuf = CTextSupportShader::s_CharInsts.allocateBlock(CGraphics::g_BooFactory, chs.m_charCount); - auto iBufInfo = chs.m_instBuf.getBufferInfo(); - - boo::ObjToken uniforms[] = {uBufInfo.first.get()}; - boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex}; - size_t unioffs[] = {size_t(uBufInfo.second)}; - size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)}; - boo::ObjToken texs[] = {chs.m_font->GetTexture()}; - chs.m_dataBinding = ctx.newShaderDataBinding(CTextSupportShader::SelectTextPipeline(m_drawFlags), - nullptr, iBufInfo.first.get(), nullptr, - 1, uniforms, unistages, unioffs, - unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second); - - if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) - { - uniforms[0] = uBufInfo2.first.get(); - unioffs[0] = size_t(uBufInfo2.second); - chs.m_dataBinding2 = ctx.newShaderDataBinding(CTextSupportShader::GetTextAdditiveOverdrawPipeline(), - nullptr, iBufInfo.first.get(), nullptr, - 1, uniforms, unistages, unioffs, - unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second); - } - } - - for (BooImage& img : m_images) - { - img.m_instBuf = CTextSupportShader::s_ImgInsts.allocateBlock(CGraphics::g_BooFactory, 1); - auto iBufInfo = img.m_instBuf.getBufferInfo(); - - boo::ObjToken uniforms[] = {uBufInfo.first.get()}; - boo::PipelineStage unistages[] = {boo::PipelineStage::Vertex}; - size_t unioffs[] = {size_t(uBufInfo.second)}; - size_t unisizes[] = {sizeof(CTextSupportShader::Uniform)}; - img.m_dataBinding.reserve(img.m_imageDef.x4_texs.size()); - for (TToken& tex : img.m_imageDef.x4_texs) - { - boo::ObjToken texs[] = {tex->GetBooTexture()}; - texs[0]->setClampMode(boo::TextureClampMode::ClampToEdge); - img.m_dataBinding.push_back(ctx.newShaderDataBinding(CTextSupportShader::SelectImagePipeline(m_drawFlags), - nullptr, iBufInfo.first.get(), nullptr, - 1, uniforms, unistages, unioffs, - unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second)); - } - - if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) - { - uniforms[0] = uBufInfo2.first.get(); - unioffs[0] = size_t(uBufInfo2.second); - img.m_dataBinding2.reserve(img.m_imageDef.x4_texs.size()); - for (TToken& tex : img.m_imageDef.x4_texs) - { - boo::ObjToken texs[] = {tex->GetBooTexture()}; - img.m_dataBinding2.push_back(ctx.newShaderDataBinding(CTextSupportShader::GetImageAdditiveOverdrawPipeline(), - nullptr, iBufInfo.first.get(), nullptr, - 1, uniforms, unistages, unioffs, - unisizes, 1, texs, nullptr, nullptr, 0, iBufInfo.second)); - } - } - } - return true; - } BooTrace); -} - -void CTextRenderBuffer::SetMode(EMode mode) -{ - if (mode == EMode::BufferFill) - { - m_images.reserve(m_imagesCount); - for (BooFontCharacters& fc : m_fontCharacters) - fc.m_charData.reserve(fc.m_charCount); + } } - m_activeFontCh = -1; - x0_mode = mode; + return true; + } BooTrace); } -void CTextRenderBuffer::SetPrimitiveOpacity(int idx, float opacity) -{ - m_primitiveMarks[idx].SetOpacity(*this, opacity); +void CTextRenderBuffer::SetMode(EMode mode) { + if (mode == EMode::BufferFill) { + m_images.reserve(m_imagesCount); + for (BooFontCharacters& fc : m_fontCharacters) + fc.m_charData.reserve(fc.m_charCount); + } + m_activeFontCh = -1; + x0_mode = mode; } -void CTextRenderBuffer::Render(const zeus::CColor& col, float time) const -{ - const_cast(this)->CommitResources(); +void CTextRenderBuffer::SetPrimitiveOpacity(int idx, float opacity) { + m_primitiveMarks[idx].SetOpacity(*this, opacity); +} - zeus::CMatrix4f mv = CGraphics::g_GXModelView.toMatrix4f(); - zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(true); - zeus::CMatrix4f mat = proj * mv; +void CTextRenderBuffer::Render(const zeus::CColor& col, float time) const { + const_cast(this)->CommitResources(); - const_cast(this)->m_uniBuf.access() = - CTextSupportShader::Uniform{mat, col}; - if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) - { - zeus::CColor colPremul = col * col.a(); - colPremul.a() = col.a(); - const_cast(this)->m_uniBuf2.access() = - CTextSupportShader::Uniform{mat, colPremul}; + zeus::CMatrix4f mv = CGraphics::g_GXModelView.toMatrix4f(); + zeus::CMatrix4f proj = CGraphics::GetPerspectiveProjectionMatrix(true); + zeus::CMatrix4f mat = proj * mv; + + const_cast(this)->m_uniBuf.access() = CTextSupportShader::Uniform{mat, col}; + if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { + zeus::CColor colPremul = col * col.a(); + colPremul.a() = col.a(); + const_cast(this)->m_uniBuf2.access() = CTextSupportShader::Uniform{mat, colPremul}; + } + + for (const BooFontCharacters& chs : m_fontCharacters) { + if (chs.m_charData.size()) { + if (chs.m_dirty) { + memmove(const_cast(chs).m_instBuf.access(), chs.m_charData.data(), + sizeof(CTextSupportShader::CharacterInstance) * chs.m_charData.size()); + const_cast(chs).m_dirty = false; + } + CGraphics::SetShaderDataBinding(chs.m_dataBinding); + CGraphics::DrawInstances(0, 4, chs.m_charData.size()); + if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { + CGraphics::SetShaderDataBinding(chs.m_dataBinding2); + CGraphics::DrawInstances(0, 4, chs.m_charData.size()); + } } + } - for (const BooFontCharacters& chs : m_fontCharacters) - { - if (chs.m_charData.size()) - { - if (chs.m_dirty) - { - memmove(const_cast(chs).m_instBuf.access(), - chs.m_charData.data(), sizeof(CTextSupportShader::CharacterInstance) * - chs.m_charData.size()); - const_cast(chs).m_dirty = false; - } - CGraphics::SetShaderDataBinding(chs.m_dataBinding); - CGraphics::DrawInstances(0, 4, chs.m_charData.size()); - if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) - { - CGraphics::SetShaderDataBinding(chs.m_dataBinding2); - CGraphics::DrawInstances(0, 4, chs.m_charData.size()); - } - } + for (const BooImage& img : m_images) { + if (img.m_dirty) { + *const_cast(img).m_instBuf.access() = img.m_imageData; + const_cast(img).m_dirty = false; } - - for (const BooImage& img : m_images) - { - if (img.m_dirty) - { - *const_cast(img).m_instBuf.access() = img.m_imageData; - const_cast(img).m_dirty = false; - } - int idx = int(img.m_imageDef.x0_fps * time) % img.m_dataBinding.size(); - CGraphics::SetShaderDataBinding(img.m_dataBinding[idx]); - CGraphics::DrawInstances(0, 4, 1); - if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) - { - CGraphics::SetShaderDataBinding(img.m_dataBinding2[idx]); - CGraphics::DrawInstances(0, 4, 1); - } + int idx = int(img.m_imageDef.x0_fps * time) % img.m_dataBinding.size(); + CGraphics::SetShaderDataBinding(img.m_dataBinding[idx]); + CGraphics::DrawInstances(0, 4, 1); + if (m_drawFlags == CGuiWidget::EGuiModelDrawFlags::AlphaAdditiveOverdraw) { + CGraphics::SetShaderDataBinding(img.m_dataBinding2[idx]); + CGraphics::DrawInstances(0, 4, 1); } + } } -void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) -{ - if (x0_mode == EMode::AllocTally) - m_primitiveMarks.push_back({Command::ImageRender, m_imagesCount++, 0}); - else - m_images.push_back({image, offset}); +void CTextRenderBuffer::AddImage(const zeus::CVector2i& offset, const CFontImageDef& image) { + if (x0_mode == EMode::AllocTally) + m_primitiveMarks.push_back({Command::ImageRender, m_imagesCount++, 0}); + else + m_images.push_back({image, offset}); } -void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, - const zeus::CColor& color) -{ - if (m_activeFontCh == -1) - return; - BooFontCharacters& chs = m_fontCharacters[m_activeFontCh]; - if (x0_mode == EMode::AllocTally) - m_primitiveMarks.push_back({Command::CharacterRender, m_activeFontCh, chs.m_charCount++}); - else - { - const CGlyph* glyph = chs.m_font.GetObj()->GetGlyph(ch); - chs.m_charData.emplace_back(); - CTextSupportShader::CharacterInstance& inst = chs.m_charData.back(); - inst.SetMetrics(*glyph, offset); - inst.m_fontColor = m_main * color; - inst.m_outlineColor = m_outline * color; - inst.m_mulColor = zeus::CColor::skWhite; +void CTextRenderBuffer::AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color) { + if (m_activeFontCh == -1) + return; + BooFontCharacters& chs = m_fontCharacters[m_activeFontCh]; + if (x0_mode == EMode::AllocTally) + m_primitiveMarks.push_back({Command::CharacterRender, m_activeFontCh, chs.m_charCount++}); + else { + const CGlyph* glyph = chs.m_font.GetObj()->GetGlyph(ch); + chs.m_charData.emplace_back(); + CTextSupportShader::CharacterInstance& inst = chs.m_charData.back(); + inst.SetMetrics(*glyph, offset); + inst.m_fontColor = m_main * color; + inst.m_outlineColor = m_outline * color; + inst.m_mulColor = zeus::CColor::skWhite; + } +} + +void CTextRenderBuffer::AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline) { + m_main = main; + m_outline = outline; +} + +void CTextRenderBuffer::AddFontChange(const TToken& font) { + for (int i = 0; i < m_fontCharacters.size(); ++i) { + BooFontCharacters& chs = m_fontCharacters[i]; + if (*chs.m_font.GetObjectTag() == *font.GetObjectTag()) { + m_activeFontCh = i; + return; } + } + + m_activeFontCh = m_fontCharacters.size(); + m_fontCharacters.push_back({font}); } -void CTextRenderBuffer::AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline) -{ - m_main = main; - m_outline = outline; +bool CTextRenderBuffer::HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const { + std::pair bounds = AccumulateTextBounds(); + if (bounds.first.x > bounds.second.x) + return true; + + if (0 < origin.y) + return false; + + zeus::CVector2i size = bounds.second - bounds.first; + return size.y <= extent.y; } -void CTextRenderBuffer::AddFontChange(const TToken& font) -{ - for (int i=0 ; i CTextRenderBuffer::AccumulateTextBounds() const { + std::pair ret = + std::make_pair(zeus::CVector2i{INT_MAX, INT_MAX}, zeus::CVector2i{INT_MIN, INT_MIN}); + + for (const BooFontCharacters& chars : m_fontCharacters) { + for (const CTextSupportShader::CharacterInstance& charInst : chars.m_charData) { + ret.first.x = std::min(ret.first.x, int(charInst.m_pos[0].x())); + ret.first.y = std::min(ret.first.y, int(charInst.m_pos[0].z())); + ret.second.x = std::max(ret.second.x, int(charInst.m_pos[3].x())); + ret.second.y = std::max(ret.second.y, int(charInst.m_pos[3].z())); } + } - m_activeFontCh = m_fontCharacters.size(); - m_fontCharacters.push_back({font}); + for (const BooImage& imgs : m_images) { + ret.first.x = std::min(ret.first.x, int(imgs.m_imageData.m_pos[0].x())); + ret.first.y = std::min(ret.first.y, int(imgs.m_imageData.m_pos[0].z())); + ret.second.x = std::max(ret.second.x, int(imgs.m_imageData.m_pos[3].x())); + ret.second.y = std::max(ret.second.y, int(imgs.m_imageData.m_pos[3].z())); + } + + return ret; } -bool CTextRenderBuffer::HasSpaceAvailable(const zeus::CVector2i& origin, - const zeus::CVector2i& extent) const -{ - std::pair bounds = AccumulateTextBounds(); - if (bounds.first.x > bounds.second.x) - return true; - - if (0 < origin.y) - return false; - - zeus::CVector2i size = bounds.second - bounds.first; - return size.y <= extent.y; -} - -std::pair CTextRenderBuffer::AccumulateTextBounds() const -{ - std::pair ret = std::make_pair(zeus::CVector2i{INT_MAX, INT_MAX}, - zeus::CVector2i{INT_MIN, INT_MIN}); - - for (const BooFontCharacters& chars : m_fontCharacters) - { - for (const CTextSupportShader::CharacterInstance& charInst : chars.m_charData) - { - ret.first.x = std::min(ret.first.x, int(charInst.m_pos[0].x())); - ret.first.y = std::min(ret.first.y, int(charInst.m_pos[0].z())); - ret.second.x = std::max(ret.second.x, int(charInst.m_pos[3].x())); - ret.second.y = std::max(ret.second.y, int(charInst.m_pos[3].z())); - } - } - - for (const BooImage& imgs : m_images) - { - ret.first.x = std::min(ret.first.x, int(imgs.m_imageData.m_pos[0].x())); - ret.first.y = std::min(ret.first.y, int(imgs.m_imageData.m_pos[0].z())); - ret.second.x = std::max(ret.second.x, int(imgs.m_imageData.m_pos[3].x())); - ret.second.y = std::max(ret.second.y, int(imgs.m_imageData.m_pos[3].z())); - } - - return ret; -} - -} +} // namespace urde diff --git a/Runtime/GuiSys/CTextRenderBuffer.hpp b/Runtime/GuiSys/CTextRenderBuffer.hpp index 5522b1976..9403bf38e 100644 --- a/Runtime/GuiSys/CTextRenderBuffer.hpp +++ b/Runtime/GuiSys/CTextRenderBuffer.hpp @@ -11,8 +11,7 @@ #include "Graphics/Shaders/CTextSupportShader.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { class CGraphicsPalette; class CRasterFont; class CGlyph; @@ -20,18 +19,12 @@ class CTextExecuteBuffer; using CTextColor = zeus::CColor; -class CTextRenderBuffer -{ - friend class CGuiTextSupport; - friend class CTextSupportShader; +class CTextRenderBuffer { + friend class CGuiTextSupport; + friend class CTextSupportShader; + public: - enum class Command - { - CharacterRender, - ImageRender, - FontChange, - PaletteChange - }; + enum class Command { CharacterRender, ImageRender, FontChange, PaletteChange }; #if 0 struct Primitive { @@ -43,14 +36,10 @@ public: u8 xe_imageIndex; }; #endif - enum class EMode - { - AllocTally, - BufferFill - }; + enum class EMode { AllocTally, BufferFill }; private: - EMode x0_mode; + EMode x0_mode; #if 0 std::vector> x4_fonts; std::vector x14_images; @@ -64,58 +53,54 @@ private: u32 x254_nextPalette = 0; #else - /* Boo-specific text-rendering functionality */ - hecl::UniformBufferPool::Token m_uniBuf; - hecl::UniformBufferPool::Token m_uniBuf2; + /* Boo-specific text-rendering functionality */ + hecl::UniformBufferPool::Token m_uniBuf; + hecl::UniformBufferPool::Token m_uniBuf2; - struct BooFontCharacters - { - TLockedToken m_font; - hecl::VertexBufferPool::Token m_instBuf; - boo::ObjToken m_dataBinding; - boo::ObjToken m_dataBinding2; - std::vector m_charData; - u32 m_charCount = 0; - bool m_dirty = true; - BooFontCharacters(const CToken& token) - : m_font(token) {} - }; - std::vector m_fontCharacters; + struct BooFontCharacters { + TLockedToken m_font; + hecl::VertexBufferPool::Token m_instBuf; + boo::ObjToken m_dataBinding; + boo::ObjToken m_dataBinding2; + std::vector m_charData; + u32 m_charCount = 0; + bool m_dirty = true; + BooFontCharacters(const CToken& token) : m_font(token) {} + }; + std::vector m_fontCharacters; - struct BooImage - { - CFontImageDef m_imageDef; - hecl::VertexBufferPool::Token m_instBuf; - std::vector> m_dataBinding; - std::vector> m_dataBinding2; - CTextSupportShader::ImageInstance m_imageData; - bool m_dirty = true; - BooImage(const CFontImageDef& imgDef, const zeus::CVector2i& offset); - }; - std::vector m_images; + struct BooImage { + CFontImageDef m_imageDef; + hecl::VertexBufferPool::Token m_instBuf; + std::vector> m_dataBinding; + std::vector> m_dataBinding2; + CTextSupportShader::ImageInstance m_imageData; + bool m_dirty = true; + BooImage(const CFontImageDef& imgDef, const zeus::CVector2i& offset); + }; + std::vector m_images; - struct BooPrimitiveMark - { - Command m_cmd; - u32 m_bindIdx; - u32 m_instIdx; - void SetOpacity(CTextRenderBuffer& rb, float opacity); - }; - std::vector m_primitiveMarks; - u32 m_imagesCount = 0; - u32 m_activeFontCh = -1; + struct BooPrimitiveMark { + Command m_cmd; + u32 m_bindIdx; + u32 m_instIdx; + void SetOpacity(CTextRenderBuffer& rb, float opacity); + }; + std::vector m_primitiveMarks; + u32 m_imagesCount = 0; + u32 m_activeFontCh = -1; - zeus::CColor m_main; - zeus::CColor m_outline = zeus::CColor::skBlack; + zeus::CColor m_main; + zeus::CColor m_outline = zeus::CColor::skBlack; - CGuiWidget::EGuiModelDrawFlags m_drawFlags; + CGuiWidget::EGuiModelDrawFlags m_drawFlags; - bool m_committed = false; - void CommitResources(); + bool m_committed = false; + void CommitResources(); #endif public: - CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df); + CTextRenderBuffer(EMode mode, CGuiWidget::EGuiModelDrawFlags df); #if 0 void SetPrimitive(const Primitive&, int); Primitive GetPrimitive(int) const; @@ -125,19 +110,18 @@ public: CGraphicsPalette* GetNextAvailablePalette(); void AddPaletteChange(const CGraphicsPalette& palette); #else - void SetPrimitiveOpacity(int idx, float opacity); - u32 GetPrimitiveCount() const { return m_primitiveMarks.size(); } + void SetPrimitiveOpacity(int idx, float opacity); + u32 GetPrimitiveCount() const { return m_primitiveMarks.size(); } #endif - void SetMode(EMode mode); - void Render(const zeus::CColor& col, float) const; - void AddImage(const zeus::CVector2i& offset, const CFontImageDef& image); - void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color); - void AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline); - void AddFontChange(const TToken& font); + void SetMode(EMode mode); + void Render(const zeus::CColor& col, float) const; + void AddImage(const zeus::CVector2i& offset, const CFontImageDef& image); + void AddCharacter(const zeus::CVector2i& offset, char16_t ch, const zeus::CColor& color); + void AddPaletteChange(const zeus::CColor& main, const zeus::CColor& outline); + void AddFontChange(const TToken& font); - bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const; - std::pair AccumulateTextBounds() const; + bool HasSpaceAvailable(const zeus::CVector2i& origin, const zeus::CVector2i& extent) const; + std::pair AccumulateTextBounds() const; }; -} - +} // namespace urde diff --git a/Runtime/GuiSys/CWordBreakTables.cpp b/Runtime/GuiSys/CWordBreakTables.cpp index cbc644a1a..16435515b 100644 --- a/Runtime/GuiSys/CWordBreakTables.cpp +++ b/Runtime/GuiSys/CWordBreakTables.cpp @@ -1,188 +1,49 @@ #include "CWordBreakTables.hpp" -namespace urde -{ +namespace urde { -struct CCharacterIdentifier -{ - wchar_t chr; - u32 rank; +struct CCharacterIdentifier { + wchar_t chr; + u32 rank; }; -static const CCharacterIdentifier gCantBeginChars[]= -{ - {L'!', 1}, - {L')', 1}, - {L',', 1}, - {L'-', 1}, - {L'.', 1}, - {L':', 1}, - {L';', 1}, - {L'?', 1}, - {L']', 1}, - {L'}', 1}, - {0x92, 1}, - {0x94, 1}, - {0xBB, 1}, - {0x3001, 1}, - {0x3002, 1}, - {0x3005, 1}, - {0x300D, 1}, - {0x300F, 1}, - {0x3011, 1}, - {0x3015, 1}, - {0x3017, 1}, - {0x3019, 1}, - {0x301B, 1}, - {0x301C, 3}, - {0x301E, 1}, - {0x302B, 3}, - {0x3041, 2}, - {0x3043, 2}, - {0x3045, 2}, - {0x3047, 2}, - {0x3049, 2}, - {0x3063, 2}, - {0x3083, 2}, - {0x3085, 2}, - {0x3087, 2}, - {0x308E, 2}, - {0x309D, 3}, - {0x309E, 3}, - {0x30A1, 2}, - {0x30A3, 2}, - {0x30A5, 2}, - {0x30A7, 2}, - {0x30A9, 2}, - {0x30C3, 2}, - {0x30E3, 2}, - {0x30E5, 2}, - {0x30E7, 2}, - {0x30EE, 2}, - {0x30F5, 2}, - {0x30F6, 2}, - {0x30FC, 2}, - {0x30FD, 3}, - {0x30FE, 3}, - {0xFF01, 1}, - {0xFF05, 3}, - {0xFF09, 1}, - {0xFF0D, 1}, - {0xFF3D, 1}, - {0xFF5D, 1}, - {0xFF61, 1}, - {0xFF63, 1}, - {0xFF64, 1}, - {0xFF1F, 1} +static const CCharacterIdentifier gCantBeginChars[] = { + {L'!', 1}, {L')', 1}, {L',', 1}, {L'-', 1}, {L'.', 1}, {L':', 1}, {L';', 1}, {L'?', 1}, + {L']', 1}, {L'}', 1}, {0x92, 1}, {0x94, 1}, {0xBB, 1}, {0x3001, 1}, {0x3002, 1}, {0x3005, 1}, + {0x300D, 1}, {0x300F, 1}, {0x3011, 1}, {0x3015, 1}, {0x3017, 1}, {0x3019, 1}, {0x301B, 1}, {0x301C, 3}, + {0x301E, 1}, {0x302B, 3}, {0x3041, 2}, {0x3043, 2}, {0x3045, 2}, {0x3047, 2}, {0x3049, 2}, {0x3063, 2}, + {0x3083, 2}, {0x3085, 2}, {0x3087, 2}, {0x308E, 2}, {0x309D, 3}, {0x309E, 3}, {0x30A1, 2}, {0x30A3, 2}, + {0x30A5, 2}, {0x30A7, 2}, {0x30A9, 2}, {0x30C3, 2}, {0x30E3, 2}, {0x30E5, 2}, {0x30E7, 2}, {0x30EE, 2}, + {0x30F5, 2}, {0x30F6, 2}, {0x30FC, 2}, {0x30FD, 3}, {0x30FE, 3}, {0xFF01, 1}, {0xFF05, 3}, {0xFF09, 1}, + {0xFF0D, 1}, {0xFF3D, 1}, {0xFF5D, 1}, {0xFF61, 1}, {0xFF63, 1}, {0xFF64, 1}, {0xFF1F, 1}}; + +static const CCharacterIdentifier gCantEndChars[] = { + {L'#', 2}, {L'$', 2}, {L'(', 1}, {L'@', 2}, {L'B', 4}, {L'C', 4}, {L'D', 4}, {L'E', 4}, {L'F', 4}, + {L'G', 4}, {L'J', 4}, {L'K', 4}, {L'L', 4}, {L'M', 4}, {L'N', 4}, {L'P', 4}, {L'Q', 4}, {L'R', 4}, + {L'S', 4}, {L'T', 4}, {L'V', 4}, {L'W', 4}, {L'X', 4}, {L'Y', 4}, {L'Z', 4}, {L'b', 4}, {L'c', 4}, + {L'd', 4}, {L'f', 4}, {L'g', 4}, {L'h', 4}, {L'j', 4}, {L'k', 4}, {L'l', 4}, {L'm', 4}, {L'n', 4}, + {L'p', 4}, {L'q', 4}, {L'r', 4}, {L's', 4}, {L't', 4}, {L'v', 4}, {L'w', 4}, {L'x', 4}, {L'y', 4}, + {L'z', 4}, {0xD1, 4}, {0xF1, 4}, {L'[', 1}, {L'{', 1}, {0x91, 1}, {0x93, 1}, {0xA2, 2}, {0xA3, 2}, + {0xA5, 2}, {0xA7, 2}, {0xA9, 2}, {0xAB, 1}, {0x20A0, 2}, {0x20A1, 2}, {0x20A2, 2}, {0x20A3, 2}, {0x20A4, 2}, + {0x20A5, 2}, {0x20A6, 2}, {0x20A7, 2}, {0x20A8, 2}, {0x20A9, 2}, {0x20AA, 2}, {0x20AB, 2}, {0x20AC, 2}, {0x300C, 1}, + {0x300E, 1}, {0x3010, 1}, {0x3012, 2}, {0x3014, 1}, {0x3016, 1}, {0x3018, 1}, {0x301A, 1}, {0xFF03, 2}, {0xFF04, 2}, + {0xFF20, 2}, {0xFF3C, 1}, {0xFF5C, 1}, {0xFFE0, 2}, {0xFFE1, 2}, {0xFFEF, 2}, }; -static const CCharacterIdentifier gCantEndChars[] = -{ - {L'#', 2}, - {L'$', 2}, - {L'(', 1}, - {L'@', 2}, - {L'B', 4}, - {L'C', 4}, - {L'D', 4}, - {L'E', 4}, - {L'F', 4}, - {L'G', 4}, - {L'J', 4}, - {L'K', 4}, - {L'L', 4}, - {L'M', 4}, - {L'N', 4}, - {L'P', 4}, - {L'Q', 4}, - {L'R', 4}, - {L'S', 4}, - {L'T', 4}, - {L'V', 4}, - {L'W', 4}, - {L'X', 4}, - {L'Y', 4}, - {L'Z', 4}, - {L'b', 4}, - {L'c', 4}, - {L'd', 4}, - {L'f', 4}, - {L'g', 4}, - {L'h', 4}, - {L'j', 4}, - {L'k', 4}, - {L'l', 4}, - {L'm', 4}, - {L'n', 4}, - {L'p', 4}, - {L'q', 4}, - {L'r', 4}, - {L's', 4}, - {L't', 4}, - {L'v', 4}, - {L'w', 4}, - {L'x', 4}, - {L'y', 4}, - {L'z', 4}, - {0xD1, 4}, - {0xF1, 4}, - {L'[', 1}, - {L'{', 1}, - {0x91, 1}, - {0x93, 1}, - {0xA2, 2}, - {0xA3, 2}, - {0xA5, 2}, - {0xA7, 2}, - {0xA9, 2}, - {0xAB, 1}, - {0x20A0, 2}, - {0x20A1, 2}, - {0x20A2, 2}, - {0x20A3, 2}, - {0x20A4, 2}, - {0x20A5, 2}, - {0x20A6, 2}, - {0x20A7, 2}, - {0x20A8, 2}, - {0x20A9, 2}, - {0x20AA, 2}, - {0x20AB, 2}, - {0x20AC, 2}, - {0x300C, 1}, - {0x300E, 1}, - {0x3010, 1}, - {0x3012, 2}, - {0x3014, 1}, - {0x3016, 1}, - {0x3018, 1}, - {0x301A, 1}, - {0xFF03, 2}, - {0xFF04, 2}, - {0xFF20, 2}, - {0xFF3C, 1}, - {0xFF5C, 1}, - {0xFFE0, 2}, - {0xFFE1, 2}, - {0xFFEF, 2}, -}; - -int CWordBreakTables::GetBeginRank(wchar_t ch) -{ - auto search = rstl::binary_find(std::cbegin(gCantBeginChars), std::cend(gCantBeginChars), ch, - [](const CCharacterIdentifier& item) {return item.chr;}); - if (search == std::cend(gCantBeginChars)) - return 5; - return search->rank; +int CWordBreakTables::GetBeginRank(wchar_t ch) { + auto search = rstl::binary_find(std::cbegin(gCantBeginChars), std::cend(gCantBeginChars), ch, + [](const CCharacterIdentifier& item) { return item.chr; }); + if (search == std::cend(gCantBeginChars)) + return 5; + return search->rank; } -int CWordBreakTables::GetEndRank(wchar_t ch) -{ - auto search = rstl::binary_find(std::cbegin(gCantEndChars), std::cend(gCantEndChars), ch, - [](const CCharacterIdentifier& item) {return item.chr;}); - if (search == std::cend(gCantEndChars)) - return 5; - return search->rank; +int CWordBreakTables::GetEndRank(wchar_t ch) { + auto search = rstl::binary_find(std::cbegin(gCantEndChars), std::cend(gCantEndChars), ch, + [](const CCharacterIdentifier& item) { return item.chr; }); + if (search == std::cend(gCantEndChars)) + return 5; + return search->rank; } -} +} // namespace urde diff --git a/Runtime/GuiSys/CWordBreakTables.hpp b/Runtime/GuiSys/CWordBreakTables.hpp index 32acccf7d..7c4e45f67 100644 --- a/Runtime/GuiSys/CWordBreakTables.hpp +++ b/Runtime/GuiSys/CWordBreakTables.hpp @@ -2,15 +2,12 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -class CWordBreakTables -{ +class CWordBreakTables { public: - static int GetBeginRank(wchar_t ch); - static int GetEndRank(wchar_t ch); + static int GetBeginRank(wchar_t ch); + static int GetEndRank(wchar_t ch); }; -} - +} // namespace urde diff --git a/Runtime/IFactory.hpp b/Runtime/IFactory.hpp index 4dc3f6178..8696420b8 100644 --- a/Runtime/IFactory.hpp +++ b/Runtime/IFactory.hpp @@ -4,8 +4,7 @@ #include #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CVParamTransfer; class IObj; class CObjectReference; @@ -15,43 +14,39 @@ class CSimplePool; class IDvdRequest; using CFactoryFnReturn = std::unique_ptr; -using FFactoryFunc = std::function; -using FMemFactoryFunc = std::function&& in, u32 len, - const urde::CVParamTransfer& vparms, - CObjectReference* selfRef)>; +using FFactoryFunc = std::function; +using FMemFactoryFunc = std::function&& in, u32 len, + const urde::CVParamTransfer& vparms, CObjectReference* selfRef)>; -class IFactory -{ +class IFactory { public: - virtual ~IFactory() = default; - virtual CFactoryFnReturn Build(const SObjectTag&, const CVParamTransfer&, CObjectReference*)=0; - virtual void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr*, CObjectReference*)=0; - virtual void CancelBuild(const SObjectTag&)=0; - virtual bool CanBuild(const SObjectTag&)=0; - virtual const SObjectTag* GetResourceIdByName(std::string_view) const=0; - virtual FourCC GetResourceTypeById(CAssetId id) const=0; - virtual void EnumerateResources(const std::function& lambda) const=0; - virtual void EnumerateNamedResources(const std::function& lambda) const=0; - virtual CResLoader* GetResLoader() { return nullptr; } - virtual CFactoryMgr* GetFactoryMgr() { return nullptr; } - virtual void LoadOriginalIDs(CSimplePool& sp) {} - virtual void AsyncIdle() {} + virtual ~IFactory() = default; + virtual CFactoryFnReturn Build(const SObjectTag&, const CVParamTransfer&, CObjectReference*) = 0; + virtual void BuildAsync(const SObjectTag&, const CVParamTransfer&, std::unique_ptr*, CObjectReference*) = 0; + virtual void CancelBuild(const SObjectTag&) = 0; + virtual bool CanBuild(const SObjectTag&) = 0; + virtual const SObjectTag* GetResourceIdByName(std::string_view) const = 0; + virtual FourCC GetResourceTypeById(CAssetId id) const = 0; + virtual void EnumerateResources(const std::function& lambda) const = 0; + virtual void + EnumerateNamedResources(const std::function& lambda) const = 0; + virtual CResLoader* GetResLoader() { return nullptr; } + virtual CFactoryMgr* GetFactoryMgr() { return nullptr; } + virtual void LoadOriginalIDs(CSimplePool& sp) {} + virtual void AsyncIdle() {} - /* Non-factory versions, replaces CResLoader */ - virtual u32 ResourceSize(const urde::SObjectTag& tag)=0; - virtual std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target)=0; - virtual std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target)=0; - virtual std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag)=0; - virtual std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size)=0; - virtual void GetTagListForFile(const char* pakName, std::vector& out) const {} + /* Non-factory versions, replaces CResLoader */ + virtual u32 ResourceSize(const urde::SObjectTag& tag) = 0; + virtual std::shared_ptr LoadResourceAsync(const urde::SObjectTag& tag, void* target) = 0; + virtual std::shared_ptr LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, + void* target) = 0; + virtual std::unique_ptr LoadResourceSync(const urde::SObjectTag& tag) = 0; + virtual std::unique_ptr LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size) = 0; + virtual void GetTagListForFile(const char* pakName, std::vector& out) const {} - virtual CAssetId TranslateOriginalToNew(CAssetId id) const { return {}; } - virtual CAssetId TranslateNewToOriginal(CAssetId id) const { return {}; } + virtual CAssetId TranslateOriginalToNew(CAssetId id) const { return {}; } + virtual CAssetId TranslateNewToOriginal(CAssetId id) const { return {}; } }; -} - +} // namespace urde diff --git a/Runtime/IMain.hpp b/Runtime/IMain.hpp index 96d7fffae..c86a25592 100644 --- a/Runtime/IMain.hpp +++ b/Runtime/IMain.hpp @@ -5,52 +5,38 @@ #include "amuse/amuse.hpp" #include "RetroTypes.hpp" -namespace hecl -{ +namespace hecl { class CVarManager; class Console; -} +} // namespace hecl -namespace urde -{ +namespace urde { class CStopwatch; -enum class EGameplayResult -{ - None, - Win, - Lose, - Playing +enum class EGameplayResult { None, Win, Lose, Playing }; + +enum class EFlowState { + None, + WinBad, + WinGood, + WinBest, + LoseGame, + Default, + StateSetter, }; -enum class EFlowState -{ - None, - WinBad, - WinGood, - WinBest, - LoseGame, - Default, - StateSetter, -}; - -class IMain -{ +class IMain { public: - virtual ~IMain() = default; - virtual void Init(const hecl::Runtime::FileStoreManager& storeMgr, - hecl::CVarManager* cvarMgr, - boo::IWindow* window, - boo::IAudioVoiceEngine* voiceEngine, - amuse::IBackendVoiceAllocator& backend)=0; - virtual void Draw()=0; - virtual bool Proc()=0; - virtual void Shutdown()=0; - virtual boo::IWindow* GetMainWindow() const= 0; - virtual EFlowState GetFlowState() const = 0; - virtual void SetFlowState(EFlowState) = 0; - virtual size_t GetExpectedIdSize() const = 0; - virtual void WarmupShaders() = 0; - virtual hecl::Console* Console() const = 0; + virtual ~IMain() = default; + virtual void Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarManager* cvarMgr, boo::IWindow* window, + boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) = 0; + virtual void Draw() = 0; + virtual bool Proc() = 0; + virtual void Shutdown() = 0; + virtual boo::IWindow* GetMainWindow() const = 0; + virtual EFlowState GetFlowState() const = 0; + virtual void SetFlowState(EFlowState) = 0; + virtual size_t GetExpectedIdSize() const = 0; + virtual void WarmupShaders() = 0; + virtual hecl::Console* Console() const = 0; }; -} - +} // namespace urde diff --git a/Runtime/IOStreams.cpp b/Runtime/IOStreams.cpp index da01a5f86..224c99009 100644 --- a/Runtime/IOStreams.cpp +++ b/Runtime/IOStreams.cpp @@ -1,18 +1,15 @@ #include "IOStreams.hpp" #include "hecl/hecl.hpp" -namespace urde -{ +namespace urde { #define DUMP_BITS 0 #if DUMP_BITS -static void PrintBinary(u32 val, u32 count) -{ - for (int i=0 ; i> (count-i-1)) & 0x1); - } +static void PrintBinary(u32 val, u32 count) { + for (int i = 0; i < count; ++i) { + printf("%d", (val >> (count - i - 1)) & 0x1); + } } #endif @@ -22,147 +19,124 @@ static void PrintBinary(u32 val, u32 count) * \param bitCount How many bits to read * \return s32 The encoded value */ -s32 CBitStreamReader::ReadEncoded(u32 bitCount) -{ +s32 CBitStreamReader::ReadEncoded(u32 bitCount) { #if DUMP_BITS - auto pos = position(); - auto boff = x20_bitOffset; + auto pos = position(); + auto boff = x20_bitOffset; #endif - u32 ret = 0; - s32 shiftAmt = x20_bitOffset - s32(bitCount); - if (shiftAmt < 0) - { - /* OR in remaining bits of cached value */ - u32 mask = bitCount == 32 ? 0xffffffff : ((1 << bitCount) - 1); - ret |= (x1c_val << u32(-shiftAmt)) & mask; + u32 ret = 0; + s32 shiftAmt = x20_bitOffset - s32(bitCount); + if (shiftAmt < 0) { + /* OR in remaining bits of cached value */ + u32 mask = bitCount == 32 ? 0xffffffff : ((1 << bitCount) - 1); + ret |= (x1c_val << u32(-shiftAmt)) & mask; - /* Load in exact number of bytes remaining */ - auto loadDiv = std::div(-shiftAmt, 8); - if (loadDiv.rem) ++loadDiv.quot; - readUBytesToBuf(reinterpret_cast(&x1c_val) + 4 - loadDiv.quot, loadDiv.quot); - x1c_val = hecl::SBig(x1c_val); + /* Load in exact number of bytes remaining */ + auto loadDiv = std::div(-shiftAmt, 8); + if (loadDiv.rem) + ++loadDiv.quot; + readUBytesToBuf(reinterpret_cast(&x1c_val) + 4 - loadDiv.quot, loadDiv.quot); + x1c_val = hecl::SBig(x1c_val); - /* New bit offset */ - x20_bitOffset = loadDiv.quot * 8 + shiftAmt; + /* New bit offset */ + x20_bitOffset = loadDiv.quot * 8 + shiftAmt; - /* OR in next bits */ - mask = (1 << u32(-shiftAmt)) - 1; - ret |= (x1c_val >> x20_bitOffset) & mask; - } - else - { - /* OR in bits of cached value */ - u32 mask = bitCount == 32 ? 0xffffffff : ((1 << bitCount) - 1); - ret |= (x1c_val >> u32(shiftAmt)) & mask; + /* OR in next bits */ + mask = (1 << u32(-shiftAmt)) - 1; + ret |= (x1c_val >> x20_bitOffset) & mask; + } else { + /* OR in bits of cached value */ + u32 mask = bitCount == 32 ? 0xffffffff : ((1 << bitCount) - 1); + ret |= (x1c_val >> u32(shiftAmt)) & mask; - /* New bit offset */ - x20_bitOffset -= bitCount; - } + /* New bit offset */ + x20_bitOffset -= bitCount; + } #if DUMP_BITS - printf("READ "); - PrintBinary(ret, bitCount); - printf(" %d %d\n", int(pos), int(boff)); + printf("READ "); + PrintBinary(ret, bitCount); + printf(" %d %d\n", int(pos), int(boff)); #endif - return ret; + return ret; } - -void CBitStreamWriter::WriteEncoded(u32 val, u32 bitCount) -{ +void CBitStreamWriter::WriteEncoded(u32 val, u32 bitCount) { #if DUMP_BITS - printf("WRITE "); - PrintBinary(val, bitCount); - printf(" %d %d\n", int(position()), int(x18_bitOffset)); + printf("WRITE "); + PrintBinary(val, bitCount); + printf(" %d %d\n", int(position()), int(x18_bitOffset)); #endif - s32 shiftAmt = x18_bitOffset - s32(bitCount); - if (shiftAmt < 0) - { - /* OR remaining bits to cached value */ - u32 mask = (1 << x18_bitOffset) - 1; - x14_val |= (val >> u32(-shiftAmt)) & mask; + s32 shiftAmt = x18_bitOffset - s32(bitCount); + if (shiftAmt < 0) { + /* OR remaining bits to cached value */ + u32 mask = (1 << x18_bitOffset) - 1; + x14_val |= (val >> u32(-shiftAmt)) & mask; - /* Write out 32-bits */ - x14_val = hecl::SBig(x14_val); - writeUBytes(reinterpret_cast(&x14_val), 4); + /* Write out 32-bits */ + x14_val = hecl::SBig(x14_val); + writeUBytes(reinterpret_cast(&x14_val), 4); - /* Cache remaining bits */ - x18_bitOffset = 0x20 + shiftAmt; - x14_val = val << x18_bitOffset; - } - else - { - /* OR bits to cached value */ - u32 mask = bitCount == 32 ? 0xffffffff : ((1 << bitCount) - 1); - x14_val |= (val & mask) << u32(shiftAmt); + /* Cache remaining bits */ + x18_bitOffset = 0x20 + shiftAmt; + x14_val = val << x18_bitOffset; + } else { + /* OR bits to cached value */ + u32 mask = bitCount == 32 ? 0xffffffff : ((1 << bitCount) - 1); + x14_val |= (val & mask) << u32(shiftAmt); - /* New bit offset */ - x18_bitOffset -= bitCount; - } + /* New bit offset */ + x18_bitOffset -= bitCount; + } } -void CBitStreamWriter::Flush() -{ - if (x18_bitOffset < 0x20) - { - auto pos = std::div(0x20 - x18_bitOffset, 8); - if (pos.rem) ++pos.quot; - x14_val = hecl::SBig(x14_val); - writeUBytes(reinterpret_cast(&x14_val), pos.quot); - x18_bitOffset = 0x20; - x14_val = 0; - } +void CBitStreamWriter::Flush() { + if (x18_bitOffset < 0x20) { + auto pos = std::div(0x20 - x18_bitOffset, 8); + if (pos.rem) + ++pos.quot; + x14_val = hecl::SBig(x14_val); + writeUBytes(reinterpret_cast(&x14_val), pos.quot); + x18_bitOffset = 0x20; + x14_val = 0; + } } -class CZipSupport -{ +class CZipSupport { public: - static void* Alloc(void*, u32 c, u32 n) - { - return new u8[c*n]; - } - static void Free(void*, void* buf) - { - delete[] static_cast(buf); - } + static void* Alloc(void*, u32 c, u32 n) { return new u8[c * n]; } + static void Free(void*, void* buf) { delete[] static_cast(buf); } }; CZipInputStream::CZipInputStream(std::unique_ptr&& strm) -: x24_compBuf(new u8[4096]), x28_strm(std::move(strm)) -{ - x30_zstrm.next_in = x24_compBuf.get(); - x30_zstrm.avail_in = 0; - x30_zstrm.zalloc = CZipSupport::Alloc; - x30_zstrm.zfree = CZipSupport::Free; - inflateInit(&x30_zstrm); +: x24_compBuf(new u8[4096]), x28_strm(std::move(strm)) { + x30_zstrm.next_in = x24_compBuf.get(); + x30_zstrm.avail_in = 0; + x30_zstrm.zalloc = CZipSupport::Alloc; + x30_zstrm.zfree = CZipSupport::Free; + inflateInit(&x30_zstrm); } -CZipInputStream::~CZipInputStream() -{ - inflateEnd(&x30_zstrm); -} +CZipInputStream::~CZipInputStream() { inflateEnd(&x30_zstrm); } -atUint64 CZipInputStream::readUBytesToBuf(void *buf, atUint64 len) -{ - x30_zstrm.next_out = (Bytef*)buf; - x30_zstrm.avail_out = len; - x30_zstrm.total_out = 0; - while (x30_zstrm.avail_out != 0) - { - if (x30_zstrm.avail_in == 0) - { - atUint64 readSz = x28_strm->readUBytesToBuf(x24_compBuf.get(), 4096); - x30_zstrm.avail_in = readSz; - x30_zstrm.next_in = x24_compBuf.get(); - } - int inflateRet = inflate(&x30_zstrm, Z_NO_FLUSH); - if (inflateRet != Z_OK) - break; +atUint64 CZipInputStream::readUBytesToBuf(void* buf, atUint64 len) { + x30_zstrm.next_out = (Bytef*)buf; + x30_zstrm.avail_out = len; + x30_zstrm.total_out = 0; + while (x30_zstrm.avail_out != 0) { + if (x30_zstrm.avail_in == 0) { + atUint64 readSz = x28_strm->readUBytesToBuf(x24_compBuf.get(), 4096); + x30_zstrm.avail_in = readSz; + x30_zstrm.next_in = x24_compBuf.get(); } - return x30_zstrm.total_out; + int inflateRet = inflate(&x30_zstrm, Z_NO_FLUSH); + if (inflateRet != Z_OK) + break; + } + return x30_zstrm.total_out; } -} +} // namespace urde diff --git a/Runtime/IOStreams.hpp b/Runtime/IOStreams.hpp index cfd0e83b9..d34969be5 100644 --- a/Runtime/IOStreams.hpp +++ b/Runtime/IOStreams.hpp @@ -7,67 +7,61 @@ #include #include -namespace urde -{ +namespace urde { using CInputStream = athena::io::IStreamReader; using COutputStream = athena::io::IStreamWriter; -struct CBitStreamReader : athena::io::MemoryReader -{ - u32 x1c_val = 0; - u32 x20_bitOffset = 0; -public: - static u32 GetBitCount(u32 maxVal) - { - u32 ret = 0; - while (maxVal != 0) - { - maxVal /= 2; - ret++; - } +struct CBitStreamReader : athena::io::MemoryReader { + u32 x1c_val = 0; + u32 x20_bitOffset = 0; - return ret; +public: + static u32 GetBitCount(u32 maxVal) { + u32 ret = 0; + while (maxVal != 0) { + maxVal /= 2; + ret++; } - CBitStreamReader(const void* data, atUint64 length) - : MemoryReader(data, length) {} + return ret; + } - s32 ReadEncoded(u32 key); + CBitStreamReader(const void* data, atUint64 length) : MemoryReader(data, length) {} + + s32 ReadEncoded(u32 key); }; -class CBitStreamWriter : public athena::io::MemoryWriter -{ - u32 x14_val = 0; - u32 x18_bitOffset = 0x20; +class CBitStreamWriter : public athena::io::MemoryWriter { + u32 x14_val = 0; + u32 x18_bitOffset = 0x20; + public: - static inline u32 GetBitCount(u32 maxVal) { return CBitStreamReader::GetBitCount(maxVal); } + static inline u32 GetBitCount(u32 maxVal) { return CBitStreamReader::GetBitCount(maxVal); } - CBitStreamWriter(atUint8* data = nullptr, atUint64 length=0x10) - : MemoryWriter(data, length) {} + CBitStreamWriter(atUint8* data = nullptr, atUint64 length = 0x10) : MemoryWriter(data, length) {} - void WriteEncoded(u32 val, u32 bitCount); + void WriteEncoded(u32 val, u32 bitCount); - void Flush(); + void Flush(); - ~CBitStreamWriter() { Flush(); } + ~CBitStreamWriter() { Flush(); } }; using CMemoryInStream = athena::io::MemoryReader; using CMemoryOutStream = athena::io::MemoryWriter; -class CZipInputStream : public CInputStream -{ - std::unique_ptr x24_compBuf; - std::unique_ptr x28_strm; - z_stream x30_zstrm = {}; +class CZipInputStream : public CInputStream { + std::unique_ptr x24_compBuf; + std::unique_ptr x28_strm; + z_stream x30_zstrm = {}; + public: - CZipInputStream(std::unique_ptr&& strm); - ~CZipInputStream(); - atUint64 readUBytesToBuf(void *buf, atUint64 len); - void seek(atInt64, athena::SeekOrigin) {} - atUint64 position() const {return 0;} - atUint64 length() const {return 0;} + CZipInputStream(std::unique_ptr&& strm); + ~CZipInputStream(); + atUint64 readUBytesToBuf(void* buf, atUint64 len); + void seek(atInt64, athena::SeekOrigin) {} + atUint64 position() const { return 0; } + atUint64 length() const { return 0; } }; -} - +} // namespace urde diff --git a/Runtime/IObj.hpp b/Runtime/IObj.hpp index 38d82b287..57c929774 100644 --- a/Runtime/IObj.hpp +++ b/Runtime/IObj.hpp @@ -2,36 +2,31 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -class IObj -{ +class IObj { public: - virtual ~IObj() = default; + virtual ~IObj() = default; }; -class TObjOwnerDerivedFromIObjUntyped : public IObj -{ +class TObjOwnerDerivedFromIObjUntyped : public IObj { protected: - void* m_objPtr; + void* m_objPtr; + public: - TObjOwnerDerivedFromIObjUntyped(void* objPtr) : m_objPtr(objPtr) {} + TObjOwnerDerivedFromIObjUntyped(void* objPtr) : m_objPtr(objPtr) {} }; -template -class TObjOwnerDerivedFromIObj : public TObjOwnerDerivedFromIObjUntyped -{ - TObjOwnerDerivedFromIObj(T* objPtr) : TObjOwnerDerivedFromIObjUntyped(objPtr) {} +template +class TObjOwnerDerivedFromIObj : public TObjOwnerDerivedFromIObjUntyped { + TObjOwnerDerivedFromIObj(T* objPtr) : TObjOwnerDerivedFromIObjUntyped(objPtr) {} + public: - static std::unique_ptr> GetNewDerivedObject(std::unique_ptr&& obj) - { - return std::unique_ptr> - (new TObjOwnerDerivedFromIObj(obj.release())); - } - ~TObjOwnerDerivedFromIObj() {std::default_delete()(static_cast(m_objPtr));} - T* GetObj() {return static_cast(m_objPtr);} + static std::unique_ptr> GetNewDerivedObject(std::unique_ptr&& obj) { + return std::unique_ptr>(new TObjOwnerDerivedFromIObj(obj.release())); + } + ~TObjOwnerDerivedFromIObj() { std::default_delete()(static_cast(m_objPtr)); } + T* GetObj() { return static_cast(m_objPtr); } }; -} - +} // namespace urde diff --git a/Runtime/IObjFactory.hpp b/Runtime/IObjFactory.hpp index eee203c1a..be272f1e9 100644 --- a/Runtime/IObjFactory.hpp +++ b/Runtime/IObjFactory.hpp @@ -3,14 +3,11 @@ #include #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -class IObjFactory -{ +class IObjFactory { public: - virtual ~IObjFactory() = default; + virtual ~IObjFactory() = default; }; -} - +} // namespace urde diff --git a/Runtime/IObjectStore.hpp b/Runtime/IObjectStore.hpp index 61b7d0e1c..2d57a98ed 100644 --- a/Runtime/IObjectStore.hpp +++ b/Runtime/IObjectStore.hpp @@ -2,27 +2,24 @@ #include -namespace urde -{ +namespace urde { struct SObjectTag; class CVParamTransfer; class IFactory; class CToken; -class IObjectStore -{ +class IObjectStore { public: - virtual ~IObjectStore() = default; - virtual CToken GetObj(const SObjectTag&, const CVParamTransfer&)=0; - virtual CToken GetObj(const SObjectTag&)=0; - virtual CToken GetObj(std::string_view)=0; - virtual CToken GetObj(std::string_view, const CVParamTransfer&)=0; - virtual bool HasObject(const SObjectTag&) const=0; - virtual bool ObjectIsLive(const SObjectTag&) const=0; - virtual IFactory& GetFactory() const=0; - virtual void Flush()=0; - virtual void ObjectUnreferenced(const SObjectTag&)=0; + virtual ~IObjectStore() = default; + virtual CToken GetObj(const SObjectTag&, const CVParamTransfer&) = 0; + virtual CToken GetObj(const SObjectTag&) = 0; + virtual CToken GetObj(std::string_view) = 0; + virtual CToken GetObj(std::string_view, const CVParamTransfer&) = 0; + virtual bool HasObject(const SObjectTag&) const = 0; + virtual bool ObjectIsLive(const SObjectTag&) const = 0; + virtual IFactory& GetFactory() const = 0; + virtual void Flush() = 0; + virtual void ObjectUnreferenced(const SObjectTag&) = 0; }; -} - +} // namespace urde diff --git a/Runtime/IRuntimeMain.hpp b/Runtime/IRuntimeMain.hpp index 9411434ee..0a24715bf 100644 --- a/Runtime/IRuntimeMain.hpp +++ b/Runtime/IRuntimeMain.hpp @@ -1,12 +1,9 @@ #pragma once -namespace urde -{ -struct IRuntimeMain -{ - void init() = 0; - int proc() = 0; - void stop() = 0; +namespace urde { +struct IRuntimeMain { + void init() = 0; + int proc() = 0; + void stop() = 0; }; -} - +} // namespace urde diff --git a/Runtime/ITweak.hpp b/Runtime/ITweak.hpp index e963d6047..feb72aa9c 100644 --- a/Runtime/ITweak.hpp +++ b/Runtime/ITweak.hpp @@ -1,11 +1,8 @@ #pragma once -namespace urde -{ -class ITweak -{ +namespace urde { +class ITweak { public: - virtual ~ITweak() {} + virtual ~ITweak() {} }; -} - +} // namespace urde diff --git a/Runtime/IVParamObj.hpp b/Runtime/IVParamObj.hpp index 98ac82f88..9204bad22 100644 --- a/Runtime/IVParamObj.hpp +++ b/Runtime/IVParamObj.hpp @@ -3,39 +3,38 @@ #include #include "IObj.hpp" -namespace urde -{ +namespace urde { -class IVParamObj : public IObj -{ +class IVParamObj : public IObj { public: - virtual ~IVParamObj() {} + virtual ~IVParamObj() {} }; -template -class TObjOwnerParam : public IVParamObj -{ - T m_param; +template +class TObjOwnerParam : public IVParamObj { + T m_param; + public: - TObjOwnerParam(T&& obj) : m_param(std::move(obj)) {} - T& GetParam() {return m_param;} + TObjOwnerParam(T&& obj) : m_param(std::move(obj)) {} + T& GetParam() { return m_param; } }; -class CVParamTransfer -{ - std::shared_ptr m_ref; +class CVParamTransfer { + std::shared_ptr m_ref; + public: - CVParamTransfer() = default; - CVParamTransfer(IVParamObj* obj) : m_ref(obj) {} - CVParamTransfer(const CVParamTransfer& other) : m_ref(other.m_ref) {} - IVParamObj* GetObj() const {return m_ref.get();} - CVParamTransfer ShareTransferRef() {return CVParamTransfer(*this);} + CVParamTransfer() = default; + CVParamTransfer(IVParamObj* obj) : m_ref(obj) {} + CVParamTransfer(const CVParamTransfer& other) : m_ref(other.m_ref) {} + IVParamObj* GetObj() const { return m_ref.get(); } + CVParamTransfer ShareTransferRef() { return CVParamTransfer(*this); } - template - T& GetOwnedObj() const {return static_cast*>(GetObj())->GetParam();} + template + T& GetOwnedObj() const { + return static_cast*>(GetObj())->GetParam(); + } - static CVParamTransfer Null() {return CVParamTransfer();} + static CVParamTransfer Null() { return CVParamTransfer(); } }; -} - +} // namespace urde diff --git a/Runtime/Input/CFinalInput.cpp b/Runtime/Input/CFinalInput.cpp index bb01b59ad..5979281cf 100644 --- a/Runtime/Input/CFinalInput.cpp +++ b/Runtime/Input/CFinalInput.cpp @@ -1,8 +1,7 @@ #include "zeus/Math.hpp" #include "CFinalInput.hpp" -namespace urde -{ +namespace urde { CFinalInput::CFinalInput() : x0_dt(0.0) @@ -46,9 +45,7 @@ CFinalInput::CFinalInput() , x2e_b28_PDPRight(false) , x2e_b29_PDPDown(false) , x2e_b30_PDPLeft(false) -, x2e_b31_PStart(false) -{ -} +, x2e_b31_PStart(false) {} CFinalInput::CFinalInput(int cIdx, float dt, const boo::DolphinControllerState& data, const CFinalInput& prevInput, float leftDiv, float rightDiv) @@ -93,48 +90,42 @@ CFinalInput::CFinalInput(int cIdx, float dt, const boo::DolphinControllerState& , x2e_b28_PDPRight(DDPRight() && !prevInput.DDPRight()) , x2e_b29_PDPDown(DDPDown() && !prevInput.DDPDown()) , x2e_b30_PDPLeft(DDPLeft() && !prevInput.DDPLeft()) -, x2e_b31_PStart(DStart() && !prevInput.DStart()) -{ +, x2e_b31_PStart(DStart() && !prevInput.DStart()) {} + +static float KBToAnaLeftX(const CKeyboardMouseControllerData& data) { + float retval = 0.0; + if (data.m_charKeys[int('a')]) + retval -= 1.0; + if (data.m_charKeys[int('d')]) + retval += 1.0; + return retval; } -static float KBToAnaLeftX(const CKeyboardMouseControllerData& data) -{ - float retval = 0.0; - if (data.m_charKeys[int('a')]) - retval -= 1.0; - if (data.m_charKeys[int('d')]) - retval += 1.0; - return retval; +static float KBToAnaLeftY(const CKeyboardMouseControllerData& data) { + float retval = 0.0; + if (data.m_charKeys[int('s')]) + retval -= 1.0; + if (data.m_charKeys[int('w')]) + retval += 1.0; + return retval; } -static float KBToAnaLeftY(const CKeyboardMouseControllerData& data) -{ - float retval = 0.0; - if (data.m_charKeys[int('s')]) - retval -= 1.0; - if (data.m_charKeys[int('w')]) - retval += 1.0; - return retval; +static float KBToAnaRightX(const CKeyboardMouseControllerData& data) { + float retval = 0.0; + if (data.m_charKeys[int('2')]) + retval -= 1.0; + if (data.m_charKeys[int('4')]) + retval += 1.0; + return retval; } -static float KBToAnaRightX(const CKeyboardMouseControllerData& data) -{ - float retval = 0.0; - if (data.m_charKeys[int('2')]) - retval -= 1.0; - if (data.m_charKeys[int('4')]) - retval += 1.0; - return retval; -} - -static float KBToAnaRightY(const CKeyboardMouseControllerData& data) -{ - float retval = 0.0; - if (data.m_charKeys[int('3')]) - retval -= 1.0; - if (data.m_charKeys[int('1')]) - retval += 1.0; - return retval; +static float KBToAnaRightY(const CKeyboardMouseControllerData& data) { + float retval = 0.0; + if (data.m_charKeys[int('3')]) + retval -= 1.0; + if (data.m_charKeys[int('1')]) + retval += 1.0; + return retval; } CFinalInput::CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData& data, const CFinalInput& prevInput) @@ -179,80 +170,75 @@ CFinalInput::CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData& , x2e_b28_PDPRight(DDPRight() && !prevInput.DDPRight()) , x2e_b29_PDPDown(DDPDown() && !prevInput.DDPDown()) , x2e_b30_PDPLeft(DDPLeft() && !prevInput.DDPLeft()) -, x2e_b31_PStart(DStart() && !prevInput.DStart()) -{ - if (x8_anaLeftX || xc_anaLeftY) - { - float len = std::sqrt(x8_anaLeftX * x8_anaLeftX + xc_anaLeftY * xc_anaLeftY); - x8_anaLeftX /= len; - xc_anaLeftY /= len; - } - if (x10_anaRightX || x14_anaRightY) - { - float len = std::sqrt(x10_anaRightX * x10_anaRightX + x14_anaRightY * x14_anaRightY); - x10_anaRightX /= len; - x14_anaRightY /= len; - } +, x2e_b31_PStart(DStart() && !prevInput.DStart()) { + if (x8_anaLeftX || xc_anaLeftY) { + float len = std::sqrt(x8_anaLeftX * x8_anaLeftX + xc_anaLeftY * xc_anaLeftY); + x8_anaLeftX /= len; + xc_anaLeftY /= len; + } + if (x10_anaRightX || x14_anaRightY) { + float len = std::sqrt(x10_anaRightX * x10_anaRightX + x14_anaRightY * x14_anaRightY); + x10_anaRightX /= len; + x14_anaRightY /= len; + } } -CFinalInput& CFinalInput::operator|=(const CFinalInput& other) -{ - if (std::fabs(other.x8_anaLeftX) > std::fabs(x8_anaLeftX)) - x8_anaLeftX = other.x8_anaLeftX; - if (std::fabs(other.xc_anaLeftY) > std::fabs(xc_anaLeftY)) - xc_anaLeftY = other.xc_anaLeftY; - if (std::fabs(other.x10_anaRightX) > std::fabs(x10_anaRightX)) - x10_anaRightX = other.x10_anaRightX; - if (std::fabs(other.x14_anaRightY) > std::fabs(x14_anaRightY)) - x14_anaRightY = other.x14_anaRightY; - if (std::fabs(other.x18_anaLeftTrigger) > std::fabs(x18_anaLeftTrigger)) - x18_anaLeftTrigger = other.x18_anaLeftTrigger; - if (std::fabs(other.x1c_anaRightTrigger) > std::fabs(x1c_anaRightTrigger)) - x1c_anaRightTrigger = other.x1c_anaRightTrigger; - x20_enableAnaLeftXP |= other.x20_enableAnaLeftXP; - x20_enableAnaLeftNegXP |= other.x20_enableAnaLeftNegXP; - x21_enableAnaLeftYP |= other.x21_enableAnaLeftYP; - x21_enableAnaLeftNegYP |= other.x21_enableAnaLeftNegYP; - x22_enableAnaRightXP |= other.x22_enableAnaRightXP; - x22_enableAnaRightNegXP |= other.x22_enableAnaRightNegXP; - x23_enableAnaRightYP |= other.x23_enableAnaRightYP; - x23_enableAnaRightNegYP |= other.x23_enableAnaRightNegYP; - x24_anaLeftTriggerP |= other.x24_anaLeftTriggerP; - x28_anaRightTriggerP |= other.x28_anaRightTriggerP; - x2c_b24_A |= other.x2c_b24_A; - x2c_b25_B |= other.x2c_b25_B; - x2c_b26_X |= other.x2c_b26_X; - x2c_b27_Y |= other.x2c_b27_Y; - x2c_b28_Z |= other.x2c_b28_Z; - x2c_b29_L |= other.x2c_b29_L; - x2c_b30_R |= other.x2c_b30_R; - x2c_b31_DPUp |= other.x2c_b31_DPUp; - x2d_b24_DPRight |= other.x2d_b24_DPRight; - x2d_b25_DPDown |= other.x2d_b25_DPDown; - x2d_b26_DPLeft |= other.x2d_b26_DPLeft; - x2d_b27_Start |= other.x2d_b27_Start; - x2d_b28_PA |= other.x2d_b28_PA; - x2d_b29_PB |= other.x2d_b29_PB; - x2d_b30_PX |= other.x2d_b30_PX; - x2d_b31_PY |= other.x2d_b31_PY; - x2e_b24_PZ |= other.x2e_b24_PZ; - x2e_b25_PL |= other.x2e_b25_PL; - x2e_b26_PR |= other.x2e_b26_PR; - x2e_b27_PDPUp |= other.x2e_b27_PDPUp; - x2e_b28_PDPRight |= other.x2e_b28_PDPRight; - x2e_b29_PDPDown |= other.x2e_b29_PDPDown; - x2e_b30_PDPLeft |= other.x2e_b30_PDPLeft; - x2e_b31_PStart |= other.x2e_b31_PStart; - return *this; +CFinalInput& CFinalInput::operator|=(const CFinalInput& other) { + if (std::fabs(other.x8_anaLeftX) > std::fabs(x8_anaLeftX)) + x8_anaLeftX = other.x8_anaLeftX; + if (std::fabs(other.xc_anaLeftY) > std::fabs(xc_anaLeftY)) + xc_anaLeftY = other.xc_anaLeftY; + if (std::fabs(other.x10_anaRightX) > std::fabs(x10_anaRightX)) + x10_anaRightX = other.x10_anaRightX; + if (std::fabs(other.x14_anaRightY) > std::fabs(x14_anaRightY)) + x14_anaRightY = other.x14_anaRightY; + if (std::fabs(other.x18_anaLeftTrigger) > std::fabs(x18_anaLeftTrigger)) + x18_anaLeftTrigger = other.x18_anaLeftTrigger; + if (std::fabs(other.x1c_anaRightTrigger) > std::fabs(x1c_anaRightTrigger)) + x1c_anaRightTrigger = other.x1c_anaRightTrigger; + x20_enableAnaLeftXP |= other.x20_enableAnaLeftXP; + x20_enableAnaLeftNegXP |= other.x20_enableAnaLeftNegXP; + x21_enableAnaLeftYP |= other.x21_enableAnaLeftYP; + x21_enableAnaLeftNegYP |= other.x21_enableAnaLeftNegYP; + x22_enableAnaRightXP |= other.x22_enableAnaRightXP; + x22_enableAnaRightNegXP |= other.x22_enableAnaRightNegXP; + x23_enableAnaRightYP |= other.x23_enableAnaRightYP; + x23_enableAnaRightNegYP |= other.x23_enableAnaRightNegYP; + x24_anaLeftTriggerP |= other.x24_anaLeftTriggerP; + x28_anaRightTriggerP |= other.x28_anaRightTriggerP; + x2c_b24_A |= other.x2c_b24_A; + x2c_b25_B |= other.x2c_b25_B; + x2c_b26_X |= other.x2c_b26_X; + x2c_b27_Y |= other.x2c_b27_Y; + x2c_b28_Z |= other.x2c_b28_Z; + x2c_b29_L |= other.x2c_b29_L; + x2c_b30_R |= other.x2c_b30_R; + x2c_b31_DPUp |= other.x2c_b31_DPUp; + x2d_b24_DPRight |= other.x2d_b24_DPRight; + x2d_b25_DPDown |= other.x2d_b25_DPDown; + x2d_b26_DPLeft |= other.x2d_b26_DPLeft; + x2d_b27_Start |= other.x2d_b27_Start; + x2d_b28_PA |= other.x2d_b28_PA; + x2d_b29_PB |= other.x2d_b29_PB; + x2d_b30_PX |= other.x2d_b30_PX; + x2d_b31_PY |= other.x2d_b31_PY; + x2e_b24_PZ |= other.x2e_b24_PZ; + x2e_b25_PL |= other.x2e_b25_PL; + x2e_b26_PR |= other.x2e_b26_PR; + x2e_b27_PDPUp |= other.x2e_b27_PDPUp; + x2e_b28_PDPRight |= other.x2e_b28_PDPRight; + x2e_b29_PDPDown |= other.x2e_b29_PDPDown; + x2e_b30_PDPLeft |= other.x2e_b30_PDPLeft; + x2e_b31_PStart |= other.x2e_b31_PStart; + return *this; } -CFinalInput CFinalInput::ScaleAnalogueSticks(float leftDiv, float rightDiv) const -{ - CFinalInput ret = *this; - ret.x8_anaLeftX = zeus::clamp(-1.f, x8_anaLeftX / leftDiv, 1.f); - ret.xc_anaLeftY = zeus::clamp(-1.f, xc_anaLeftY / leftDiv, 1.f); - ret.x10_anaRightX = zeus::clamp(-1.f, x10_anaRightX / rightDiv, 1.f); - ret.x14_anaRightY = zeus::clamp(-1.f, x14_anaRightY / rightDiv, 1.f); - return ret; -} +CFinalInput CFinalInput::ScaleAnalogueSticks(float leftDiv, float rightDiv) const { + CFinalInput ret = *this; + ret.x8_anaLeftX = zeus::clamp(-1.f, x8_anaLeftX / leftDiv, 1.f); + ret.xc_anaLeftY = zeus::clamp(-1.f, xc_anaLeftY / leftDiv, 1.f); + ret.x10_anaRightX = zeus::clamp(-1.f, x10_anaRightX / rightDiv, 1.f); + ret.x14_anaRightY = zeus::clamp(-1.f, x14_anaRightY / rightDiv, 1.f); + return ret; } +} // namespace urde diff --git a/Runtime/Input/CFinalInput.hpp b/Runtime/Input/CFinalInput.hpp index fbdc9fe6b..73ddf0beb 100644 --- a/Runtime/Input/CFinalInput.hpp +++ b/Runtime/Input/CFinalInput.hpp @@ -4,153 +4,145 @@ #include "CKeyboardMouseController.hpp" #include -namespace urde -{ +namespace urde { -struct CFinalInput -{ - float x0_dt; - u32 x4_controllerIdx; - float x8_anaLeftX; - float xc_anaLeftY; - float x10_anaRightX; - float x14_anaRightY; - float x18_anaLeftTrigger; - float x1c_anaRightTrigger; +struct CFinalInput { + float x0_dt; + u32 x4_controllerIdx; + float x8_anaLeftX; + float xc_anaLeftY; + float x10_anaRightX; + float x14_anaRightY; + float x18_anaLeftTrigger; + float x1c_anaRightTrigger; - /* These were originally per-axis bools, requiring two logical tests - * at read-time; now they're logical cardinal-direction states - * (negative values indicated) */ - bool x20_enableAnaLeftXP:1; - bool x20_enableAnaLeftNegXP:1; - bool x21_enableAnaLeftYP:1; - bool x21_enableAnaLeftNegYP:1; - bool x22_enableAnaRightXP:1; - bool x22_enableAnaRightNegXP:1; - bool x23_enableAnaRightYP:1; - bool x23_enableAnaRightNegYP:1; + /* These were originally per-axis bools, requiring two logical tests + * at read-time; now they're logical cardinal-direction states + * (negative values indicated) */ + bool x20_enableAnaLeftXP : 1; + bool x20_enableAnaLeftNegXP : 1; + bool x21_enableAnaLeftYP : 1; + bool x21_enableAnaLeftNegYP : 1; + bool x22_enableAnaRightXP : 1; + bool x22_enableAnaRightNegXP : 1; + bool x23_enableAnaRightYP : 1; + bool x23_enableAnaRightNegYP : 1; - /* These were originally redundantly-compared floats; - * now the logical state is stored directly */ - bool x24_anaLeftTriggerP:1; - bool x28_anaRightTriggerP:1; + /* These were originally redundantly-compared floats; + * now the logical state is stored directly */ + bool x24_anaLeftTriggerP : 1; + bool x28_anaRightTriggerP : 1; - bool x2c_b24_A:1; - bool x2c_b25_B:1; - bool x2c_b26_X:1; - bool x2c_b27_Y:1; - bool x2c_b28_Z:1; - bool x2c_b29_L:1; - bool x2c_b30_R:1; - bool x2c_b31_DPUp:1; - bool x2d_b24_DPRight:1; - bool x2d_b25_DPDown:1; - bool x2d_b26_DPLeft:1; - bool x2d_b27_Start:1; + bool x2c_b24_A : 1; + bool x2c_b25_B : 1; + bool x2c_b26_X : 1; + bool x2c_b27_Y : 1; + bool x2c_b28_Z : 1; + bool x2c_b29_L : 1; + bool x2c_b30_R : 1; + bool x2c_b31_DPUp : 1; + bool x2d_b24_DPRight : 1; + bool x2d_b25_DPDown : 1; + bool x2d_b26_DPLeft : 1; + bool x2d_b27_Start : 1; - bool x2d_b28_PA:1; - bool x2d_b29_PB:1; - bool x2d_b30_PX:1; - bool x2d_b31_PY:1; - bool x2e_b24_PZ:1; - bool x2e_b25_PL:1; - bool x2e_b26_PR:1; - bool x2e_b27_PDPUp:1; - bool x2e_b28_PDPRight:1; - bool x2e_b29_PDPDown:1; - bool x2e_b30_PDPLeft:1; - bool x2e_b31_PStart:1; + bool x2d_b28_PA : 1; + bool x2d_b29_PB : 1; + bool x2d_b30_PX : 1; + bool x2d_b31_PY : 1; + bool x2e_b24_PZ : 1; + bool x2e_b25_PL : 1; + bool x2e_b26_PR : 1; + bool x2e_b27_PDPUp : 1; + bool x2e_b28_PDPRight : 1; + bool x2e_b29_PDPDown : 1; + bool x2e_b30_PDPLeft : 1; + bool x2e_b31_PStart : 1; - CFinalInput(); - CFinalInput(int cIdx, float dt, - const boo::DolphinControllerState& data, - const CFinalInput& prevInput, - float leftDiv, float rightDiv); - CFinalInput(int cIdx, float dt, - const CKeyboardMouseControllerData& data, - const CFinalInput& prevInput); - CFinalInput& operator|=(const CFinalInput& other); - bool operator==(const CFinalInput& other) - { return memcmp(this, &other, sizeof(CFinalInput)) == 0; } - float DeltaTime() const {return x0_dt;} - u32 ControllerIdx() const {return x4_controllerIdx;} + CFinalInput(); + CFinalInput(int cIdx, float dt, const boo::DolphinControllerState& data, const CFinalInput& prevInput, float leftDiv, + float rightDiv); + CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData& data, const CFinalInput& prevInput); + CFinalInput& operator|=(const CFinalInput& other); + bool operator==(const CFinalInput& other) { return memcmp(this, &other, sizeof(CFinalInput)) == 0; } + float DeltaTime() const { return x0_dt; } + u32 ControllerIdx() const { return x4_controllerIdx; } - bool PStart() const {return x2e_b31_PStart;} - bool PR() const {return x2e_b26_PR;} - bool PL() const {return x2e_b25_PL;} - bool PZ() const {return x2e_b24_PZ;} - bool PY() const {return x2d_b31_PY;} - bool PX() const {return x2d_b30_PX;} - bool PB() const {return x2d_b29_PB;} - bool PA() const {return x2d_b28_PA;} - bool PDPRight() const {return x2e_b28_PDPRight;} - bool PDPLeft() const {return x2e_b30_PDPLeft;} - bool PDPDown() const {return x2e_b29_PDPDown;} - bool PDPUp() const {return x2e_b27_PDPUp;} - bool PRTrigger() const {return x28_anaRightTriggerP;} - bool PLTrigger() const {return x24_anaLeftTriggerP;} - bool PRARight() const {return x22_enableAnaRightXP;} - bool PRALeft() const {return x22_enableAnaRightNegXP;} - bool PRADown() const {return x23_enableAnaRightNegYP;} - bool PRAUp() const {return x23_enableAnaRightYP;} - bool PLARight() const {return x20_enableAnaLeftXP;} - bool PLALeft() const {return x20_enableAnaLeftNegXP;} - bool PLADown() const {return x21_enableAnaLeftNegYP;} - bool PLAUp() const {return x21_enableAnaLeftYP;} - bool DStart() const {return x2d_b27_Start;} - bool DR() const {return x2c_b30_R;} - bool DL() const {return x2c_b29_L;} - bool DZ() const {return x2c_b28_Z;} - bool DY() const {return x2c_b27_Y;} - bool DX() const {return x2c_b26_X;} - bool DB() const {return x2c_b25_B;} - bool DA() const {return x2c_b24_A;} - bool DDPRight() const {return x2d_b24_DPRight;} - bool DDPLeft() const {return x2d_b26_DPLeft;} - bool DDPDown() const {return x2d_b25_DPDown;} - bool DDPUp() const {return x2c_b31_DPUp;} - bool DRTrigger() const {return x1c_anaRightTrigger > 0.05f;} - bool DLTrigger() const {return x18_anaLeftTrigger > 0.05f;} - bool DRARight() const {return x10_anaRightX > 0.7f;} - bool DRALeft() const {return x10_anaRightX < -0.7f;} - bool DRADown() const {return x14_anaRightY < -0.7f;} - bool DRAUp() const {return x14_anaRightY > 0.7f;} - bool DLARight() const {return x8_anaLeftX > 0.7f;} - bool DLALeft() const {return x8_anaLeftX < -0.7f;} - bool DLADown() const {return xc_anaLeftY < -0.7f;} - bool DLAUp() const {return xc_anaLeftY > 0.7f;} - float AStart() const {return x2d_b27_Start ? 1.f : 0.f;} - float AR() const {return x2c_b30_R ? 1.f : 0.f;} - float AL() const {return x2c_b29_L ? 1.f : 0.f;} - float AZ() const {return x2c_b28_Z ? 1.f : 0.f;} - float AY() const {return x2c_b27_Y ? 1.f : 0.f;} - float AX() const {return x2c_b26_X ? 1.f : 0.f;} - float AB() const {return x2c_b25_B ? 1.f : 0.f;} - float AA() const {return x2c_b24_A ? 1.f : 0.f;} - float ADPRight() const {return x2d_b24_DPRight ? 1.f : 0.f;} - float ADPLeft() const {return x2d_b26_DPLeft ? 1.f : 0.f;} - float ADPDown() const {return x2d_b25_DPDown ? 1.f : 0.f;} - float ADPUp() const {return x2c_b31_DPUp ? 1.f : 0.f;} - float ARTrigger() const {return x1c_anaRightTrigger;} - float ALTrigger() const {return x18_anaLeftTrigger;} - float ARARight() const {return x10_anaRightX > 0.f ? x10_anaRightX : 0.f;} - float ARALeft() const {return x10_anaRightX < 0.f ? -x10_anaRightX : 0.f;} - float ARADown() const {return x14_anaRightY < 0.f ? -x14_anaRightY : 0.f;} - float ARAUp() const {return x14_anaRightY > 0.f ? x14_anaRightY : 0.f;} - float ALARight() const {return x8_anaLeftX > 0.f ? x8_anaLeftX : 0.f;} - float ALALeft() const {return x8_anaLeftX < 0.f ? -x8_anaLeftX : 0.f;} - float ALADown() const {return xc_anaLeftY < 0.f ? -xc_anaLeftY : 0.f;} - float ALAUp() const {return xc_anaLeftY > 0.f ? xc_anaLeftY : 0.f;} + bool PStart() const { return x2e_b31_PStart; } + bool PR() const { return x2e_b26_PR; } + bool PL() const { return x2e_b25_PL; } + bool PZ() const { return x2e_b24_PZ; } + bool PY() const { return x2d_b31_PY; } + bool PX() const { return x2d_b30_PX; } + bool PB() const { return x2d_b29_PB; } + bool PA() const { return x2d_b28_PA; } + bool PDPRight() const { return x2e_b28_PDPRight; } + bool PDPLeft() const { return x2e_b30_PDPLeft; } + bool PDPDown() const { return x2e_b29_PDPDown; } + bool PDPUp() const { return x2e_b27_PDPUp; } + bool PRTrigger() const { return x28_anaRightTriggerP; } + bool PLTrigger() const { return x24_anaLeftTriggerP; } + bool PRARight() const { return x22_enableAnaRightXP; } + bool PRALeft() const { return x22_enableAnaRightNegXP; } + bool PRADown() const { return x23_enableAnaRightNegYP; } + bool PRAUp() const { return x23_enableAnaRightYP; } + bool PLARight() const { return x20_enableAnaLeftXP; } + bool PLALeft() const { return x20_enableAnaLeftNegXP; } + bool PLADown() const { return x21_enableAnaLeftNegYP; } + bool PLAUp() const { return x21_enableAnaLeftYP; } + bool DStart() const { return x2d_b27_Start; } + bool DR() const { return x2c_b30_R; } + bool DL() const { return x2c_b29_L; } + bool DZ() const { return x2c_b28_Z; } + bool DY() const { return x2c_b27_Y; } + bool DX() const { return x2c_b26_X; } + bool DB() const { return x2c_b25_B; } + bool DA() const { return x2c_b24_A; } + bool DDPRight() const { return x2d_b24_DPRight; } + bool DDPLeft() const { return x2d_b26_DPLeft; } + bool DDPDown() const { return x2d_b25_DPDown; } + bool DDPUp() const { return x2c_b31_DPUp; } + bool DRTrigger() const { return x1c_anaRightTrigger > 0.05f; } + bool DLTrigger() const { return x18_anaLeftTrigger > 0.05f; } + bool DRARight() const { return x10_anaRightX > 0.7f; } + bool DRALeft() const { return x10_anaRightX < -0.7f; } + bool DRADown() const { return x14_anaRightY < -0.7f; } + bool DRAUp() const { return x14_anaRightY > 0.7f; } + bool DLARight() const { return x8_anaLeftX > 0.7f; } + bool DLALeft() const { return x8_anaLeftX < -0.7f; } + bool DLADown() const { return xc_anaLeftY < -0.7f; } + bool DLAUp() const { return xc_anaLeftY > 0.7f; } + float AStart() const { return x2d_b27_Start ? 1.f : 0.f; } + float AR() const { return x2c_b30_R ? 1.f : 0.f; } + float AL() const { return x2c_b29_L ? 1.f : 0.f; } + float AZ() const { return x2c_b28_Z ? 1.f : 0.f; } + float AY() const { return x2c_b27_Y ? 1.f : 0.f; } + float AX() const { return x2c_b26_X ? 1.f : 0.f; } + float AB() const { return x2c_b25_B ? 1.f : 0.f; } + float AA() const { return x2c_b24_A ? 1.f : 0.f; } + float ADPRight() const { return x2d_b24_DPRight ? 1.f : 0.f; } + float ADPLeft() const { return x2d_b26_DPLeft ? 1.f : 0.f; } + float ADPDown() const { return x2d_b25_DPDown ? 1.f : 0.f; } + float ADPUp() const { return x2c_b31_DPUp ? 1.f : 0.f; } + float ARTrigger() const { return x1c_anaRightTrigger; } + float ALTrigger() const { return x18_anaLeftTrigger; } + float ARARight() const { return x10_anaRightX > 0.f ? x10_anaRightX : 0.f; } + float ARALeft() const { return x10_anaRightX < 0.f ? -x10_anaRightX : 0.f; } + float ARADown() const { return x14_anaRightY < 0.f ? -x14_anaRightY : 0.f; } + float ARAUp() const { return x14_anaRightY > 0.f ? x14_anaRightY : 0.f; } + float ALARight() const { return x8_anaLeftX > 0.f ? x8_anaLeftX : 0.f; } + float ALALeft() const { return x8_anaLeftX < 0.f ? -x8_anaLeftX : 0.f; } + float ALADown() const { return xc_anaLeftY < 0.f ? -xc_anaLeftY : 0.f; } + float ALAUp() const { return xc_anaLeftY > 0.f ? xc_anaLeftY : 0.f; } - float ALeftX() const {return x8_anaLeftX;} - float ALeftY() const {return xc_anaLeftY;} - float ARightX() const {return x10_anaRightX;} - float ARightY() const {return x14_anaRightY;} - float ALeftTrigger() const {return x18_anaLeftTrigger;} - float ARightTrigger() const {return x1c_anaRightTrigger;} + float ALeftX() const { return x8_anaLeftX; } + float ALeftY() const { return xc_anaLeftY; } + float ARightX() const { return x10_anaRightX; } + float ARightY() const { return x14_anaRightY; } + float ALeftTrigger() const { return x18_anaLeftTrigger; } + float ARightTrigger() const { return x1c_anaRightTrigger; } - CFinalInput ScaleAnalogueSticks(float leftDiv, float rightDiv) const; + CFinalInput ScaleAnalogueSticks(float leftDiv, float rightDiv) const; }; -} - +} // namespace urde diff --git a/Runtime/Input/CInputGenerator.cpp b/Runtime/Input/CInputGenerator.cpp index 65859c550..1176b7616 100644 --- a/Runtime/Input/CInputGenerator.cpp +++ b/Runtime/Input/CInputGenerator.cpp @@ -2,43 +2,38 @@ #include "../CArchitectureMessage.hpp" #include "../CArchitectureQueue.hpp" -namespace urde -{ +namespace urde { -void CInputGenerator::Update(float dt, CArchitectureQueue& queue) -{ - if (m_firstFrame) - { - m_firstFrame = false; - return; +void CInputGenerator::Update(float dt, CArchitectureQueue& queue) { + if (m_firstFrame) { + m_firstFrame = false; + return; + } + + /* Keyboard/Mouse first */ + CFinalInput kbInput = getFinalInput(0, dt); + bool kbUsed = false; + + /* Dolphin controllers next */ + for (int i = 0; i < 4; ++i) { + bool connected; + EStatusChange change = m_dolphinCb.getStatusChange(i, connected); + if (change != EStatusChange::NoChange) + queue.Push(MakeMsg::CreateControllerStatus(EArchMsgTarget::Game, i, connected)); + if (connected) { + CFinalInput input = m_dolphinCb.getFinalInput(i, dt, m_leftDiv, m_rightDiv); + if (i == 0) /* Merge KB input with first controller */ + { + input |= kbInput; + kbUsed = true; + } + queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, input)); } + } - /* Keyboard/Mouse first */ - CFinalInput kbInput = getFinalInput(0, dt); - bool kbUsed = false; - - /* Dolphin controllers next */ - for (int i=0 ; i<4 ; ++i) - { - bool connected; - EStatusChange change = m_dolphinCb.getStatusChange(i, connected); - if (change != EStatusChange::NoChange) - queue.Push(MakeMsg::CreateControllerStatus(EArchMsgTarget::Game, i, connected)); - if (connected) - { - CFinalInput input = m_dolphinCb.getFinalInput(i, dt, m_leftDiv, m_rightDiv); - if (i == 0) /* Merge KB input with first controller */ - { - input |= kbInput; - kbUsed = true; - } - queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, input)); - } - } - - /* Send straight keyboard input if no first controller present */ - if (!kbUsed) - queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, kbInput)); + /* Send straight keyboard input if no first controller present */ + if (!kbUsed) + queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, kbInput)); } -} +} // namespace urde diff --git a/Runtime/Input/CInputGenerator.hpp b/Runtime/Input/CInputGenerator.hpp index 6e1bef186..22c5aa65f 100644 --- a/Runtime/Input/CInputGenerator.hpp +++ b/Runtime/Input/CInputGenerator.hpp @@ -5,241 +5,174 @@ #include "CFinalInput.hpp" #include "CKeyboardMouseController.hpp" -namespace urde -{ +namespace urde { class CArchitectureQueue; -enum class EIOPort -{ - Zero, - One, - Two, - Three -}; +enum class EIOPort { Zero, One, Two, Three }; -enum class EMotorState -{ - Stop, - Rumble, - StopHard -}; +enum class EMotorState { Stop, Rumble, StopHard }; -class CInputGenerator : public boo::DeviceFinder -{ - enum class EStatusChange - { - NoChange = 0, - Connected = 1, - Disconnected = 2 - }; +class CInputGenerator : public boo::DeviceFinder { + enum class EStatusChange { NoChange = 0, Connected = 1, Disconnected = 2 }; - /* When the sticks are used as logical (digital) input, - * these thresholds determine the vector magnitude indicating - * the logical state */ - float m_leftDiv; - float m_rightDiv; - CKeyboardMouseControllerData m_data; + /* When the sticks are used as logical (digital) input, + * these thresholds determine the vector magnitude indicating + * the logical state */ + float m_leftDiv; + float m_rightDiv; + CKeyboardMouseControllerData m_data; - CFinalInput m_lastUpdate; - const CFinalInput& getFinalInput(unsigned idx, float dt) - { - m_lastUpdate = CFinalInput(idx, dt, m_data, m_lastUpdate); - return m_lastUpdate; - } + CFinalInput m_lastUpdate; + const CFinalInput& getFinalInput(unsigned idx, float dt) { + m_lastUpdate = CFinalInput(idx, dt, m_data, m_lastUpdate); + return m_lastUpdate; + } + + bool m_firstFrame = true; - bool m_firstFrame = true; public: - CInputGenerator(float leftDiv, float rightDiv) - : boo::DeviceFinder({dev_typeid(DolphinSmashAdapter)}), - m_leftDiv(leftDiv), - m_rightDiv(rightDiv) {} + CInputGenerator(float leftDiv, float rightDiv) + : boo::DeviceFinder({dev_typeid(DolphinSmashAdapter)}), m_leftDiv(leftDiv), m_rightDiv(rightDiv) {} - ~CInputGenerator() - { - if (smashAdapter) - smashAdapter->setCallback(nullptr); + ~CInputGenerator() { + if (smashAdapter) + smashAdapter->setCallback(nullptr); + } + + /* Keyboard and mouse events are delivered on the main game + * thread as part of the app's main event loop. The OS is responsible + * for buffering events in its own way, then boo flushes the buffer + * at the start of each frame, invoking these methods. No atomic locking + * is necessary, only absolute state tracking. */ + + void mouseDown(const boo::SWindowCoord&, boo::EMouseButton button, boo::EModifierKey) { + m_data.m_mouseButtons[int(button)] = true; + } + void mouseUp(const boo::SWindowCoord&, boo::EMouseButton button, boo::EModifierKey) { + m_data.m_mouseButtons[int(button)] = false; + } + void mouseMove(const boo::SWindowCoord& coord) { m_data.m_mouseCoord = coord; } + void scroll(const boo::SWindowCoord&, const boo::SScrollDelta& scroll) { m_data.m_accumScroll += scroll; } + + void charKeyDown(unsigned long charCode, boo::EModifierKey, bool) { + charCode = tolower(charCode); + if (charCode > 255) + return; + m_data.m_charKeys[charCode] = true; + } + void charKeyUp(unsigned long charCode, boo::EModifierKey mods) { + charCode = tolower(charCode); + if (charCode > 255) + return; + m_data.m_charKeys[charCode] = false; + } + void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey, bool) { m_data.m_specialKeys[int(key)] = true; } + void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey) { m_data.m_specialKeys[int(key)] = false; } + void modKeyDown(boo::EModifierKey mod, bool) { m_data.m_modMask = m_data.m_modMask | mod; } + void modKeyUp(boo::EModifierKey mod) { m_data.m_modMask = m_data.m_modMask & ~mod; } + + void reset() { m_data.m_accumScroll.zeroOut(); } + + /* Input via the smash adapter is received asynchronously on a USB + * report thread. This class atomically exchanges that data to the + * game thread as needed */ + struct DolphinSmashAdapterCallback : boo::IDolphinSmashAdapterCallback { + std::atomic m_statusChanges[4]; + bool m_connected[4] = {}; + boo::DolphinControllerState m_states[4]; + std::mutex m_stateLock; + void controllerConnected(unsigned idx, boo::EDolphinControllerType) { + /* Controller thread */ + m_statusChanges[idx].store(EStatusChange::Connected); + } + void controllerDisconnected(unsigned idx) { + /* Controller thread */ + std::unique_lock lk(m_stateLock); + m_statusChanges[idx].store(EStatusChange::Disconnected); + m_states[idx].reset(); + } + void controllerUpdate(unsigned idx, boo::EDolphinControllerType, const boo::DolphinControllerState& state) { + /* Controller thread */ + std::unique_lock lk(m_stateLock); + m_states[idx] = state; } - /* Keyboard and mouse events are delivered on the main game - * thread as part of the app's main event loop. The OS is responsible - * for buffering events in its own way, then boo flushes the buffer - * at the start of each frame, invoking these methods. No atomic locking - * is necessary, only absolute state tracking. */ + CFinalInput m_lastUpdates[4]; + const CFinalInput& getFinalInput(unsigned idx, float dt, float leftDiv, float rightDiv) { + /* Game thread */ + std::unique_lock lk(m_stateLock); + boo::DolphinControllerState state = m_states[idx]; + lk.unlock(); + state.clamp(); /* PADClamp equivalent */ + m_lastUpdates[idx] = CFinalInput(idx, dt, state, m_lastUpdates[idx], leftDiv, rightDiv); + return m_lastUpdates[idx]; + } + EStatusChange getStatusChange(unsigned idx, bool& connected) { + /* Game thread */ + EStatusChange ch = m_statusChanges[idx].exchange(EStatusChange::NoChange); + if (ch == EStatusChange::Connected) + m_connected[idx] = true; + else if (ch == EStatusChange::Disconnected) + m_connected[idx] = false; + connected = m_connected[idx]; + return ch; + } + } m_dolphinCb; - void mouseDown(const boo::SWindowCoord&, boo::EMouseButton button, boo::EModifierKey) - { - m_data.m_mouseButtons[int(button)] = true; + /* Device connection/disconnection events are handled on a separate thread + * using the relevant OS API. This thread blocks in a loop until an event is + * received. Device pointers should only be manipulated by this thread using + * the deviceConnected() and deviceDisconnected() callbacks. */ + std::shared_ptr smashAdapter; + void deviceConnected(boo::DeviceToken& tok) { + /* Device listener thread */ + if (!smashAdapter) { + auto dev = tok.openAndGetDevice(); + if (dev && dev->getTypeHash() == dev_typeid(DolphinSmashAdapter)) { + smashAdapter = std::static_pointer_cast(tok.openAndGetDevice()); + smashAdapter->setCallback(&m_dolphinCb); + } } - void mouseUp(const boo::SWindowCoord&, boo::EMouseButton button, boo::EModifierKey) - { - m_data.m_mouseButtons[int(button)] = false; + } + void deviceDisconnected(boo::DeviceToken&, boo::DeviceBase* device) { + if (smashAdapter.get() == device) + smashAdapter.reset(); + } + void SetMotorState(EIOPort port, EMotorState state) { + if (smashAdapter) { + switch (state) { + case EMotorState::Stop: + smashAdapter->stopRumble(unsigned(port)); + break; + case EMotorState::Rumble: + smashAdapter->startRumble(unsigned(port)); + break; + case EMotorState::StopHard: + smashAdapter->stopRumble(unsigned(port), true); + break; + } } - void mouseMove(const boo::SWindowCoord& coord) - { - m_data.m_mouseCoord = coord; - } - void scroll(const boo::SWindowCoord&, const boo::SScrollDelta& scroll) - { - m_data.m_accumScroll += scroll; - } - - void charKeyDown(unsigned long charCode, boo::EModifierKey, bool) - { - charCode = tolower(charCode); - if (charCode > 255) - return; - m_data.m_charKeys[charCode] = true; - } - void charKeyUp(unsigned long charCode, boo::EModifierKey mods) - { - charCode = tolower(charCode); - if (charCode > 255) - return; - m_data.m_charKeys[charCode] = false; - } - void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey, bool) - { - m_data.m_specialKeys[int(key)] = true; - } - void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey) - { - m_data.m_specialKeys[int(key)] = false; - } - void modKeyDown(boo::EModifierKey mod, bool) - { - m_data.m_modMask = m_data.m_modMask | mod; - } - void modKeyUp(boo::EModifierKey mod) - { - m_data.m_modMask = m_data.m_modMask & ~mod; - } - - void reset() - { - m_data.m_accumScroll.zeroOut(); - } - - /* Input via the smash adapter is received asynchronously on a USB - * report thread. This class atomically exchanges that data to the - * game thread as needed */ - struct DolphinSmashAdapterCallback : boo::IDolphinSmashAdapterCallback - { - std::atomic m_statusChanges[4]; - bool m_connected[4] = {}; - boo::DolphinControllerState m_states[4]; - std::mutex m_stateLock; - void controllerConnected(unsigned idx, boo::EDolphinControllerType) - { - /* Controller thread */ - m_statusChanges[idx].store(EStatusChange::Connected); - } - void controllerDisconnected(unsigned idx) - { - /* Controller thread */ - std::unique_lock lk(m_stateLock); - m_statusChanges[idx].store(EStatusChange::Disconnected); - m_states[idx].reset(); - } - void controllerUpdate(unsigned idx, boo::EDolphinControllerType, - const boo::DolphinControllerState& state) - { - /* Controller thread */ - std::unique_lock lk(m_stateLock); - m_states[idx] = state; - } - - CFinalInput m_lastUpdates[4]; - const CFinalInput& getFinalInput(unsigned idx, float dt, - float leftDiv, float rightDiv) - { - /* Game thread */ - std::unique_lock lk(m_stateLock); - boo::DolphinControllerState state = m_states[idx]; - lk.unlock(); - state.clamp(); /* PADClamp equivalent */ - m_lastUpdates[idx] = CFinalInput(idx, dt, state, m_lastUpdates[idx], leftDiv, rightDiv); - return m_lastUpdates[idx]; - } - EStatusChange getStatusChange(unsigned idx, bool& connected) - { - /* Game thread */ - EStatusChange ch = m_statusChanges[idx].exchange(EStatusChange::NoChange); - if (ch == EStatusChange::Connected) - m_connected[idx] = true; - else if (ch == EStatusChange::Disconnected) - m_connected[idx] = false; - connected = m_connected[idx]; - return ch; - } - } m_dolphinCb; - - /* Device connection/disconnection events are handled on a separate thread - * using the relevant OS API. This thread blocks in a loop until an event is - * received. Device pointers should only be manipulated by this thread using - * the deviceConnected() and deviceDisconnected() callbacks. */ - std::shared_ptr smashAdapter; - void deviceConnected(boo::DeviceToken& tok) - { - /* Device listener thread */ - if (!smashAdapter) - { - auto dev = tok.openAndGetDevice(); - if (dev && dev->getTypeHash() == dev_typeid(DolphinSmashAdapter)) - { - smashAdapter = std::static_pointer_cast(tok.openAndGetDevice()); - smashAdapter->setCallback(&m_dolphinCb); - } - } - } - void deviceDisconnected(boo::DeviceToken&, boo::DeviceBase* device) - { - if (smashAdapter.get() == device) - smashAdapter.reset(); - } - void SetMotorState(EIOPort port, EMotorState state) - { - if (smashAdapter) - { - switch (state) - { - case EMotorState::Stop: - smashAdapter->stopRumble(unsigned(port)); - break; - case EMotorState::Rumble: - smashAdapter->startRumble(unsigned(port)); - break; - case EMotorState::StopHard: - smashAdapter->stopRumble(unsigned(port), true); - break; - } - } - } - void ControlAllMotors(const EMotorState* states) - { - if (smashAdapter) - { - for (int i=0 ; i<4 ; ++i) - { - switch (states[i]) - { - case EMotorState::Stop: - smashAdapter->stopRumble(i); - break; - case EMotorState::Rumble: - smashAdapter->startRumble(i); - break; - case EMotorState::StopHard: - smashAdapter->stopRumble(i, true); - break; - } - } + } + void ControlAllMotors(const EMotorState* states) { + if (smashAdapter) { + for (int i = 0; i < 4; ++i) { + switch (states[i]) { + case EMotorState::Stop: + smashAdapter->stopRumble(i); + break; + case EMotorState::Rumble: + smashAdapter->startRumble(i); + break; + case EMotorState::StopHard: + smashAdapter->stopRumble(i, true); + break; } + } } + } - /* This is where the game thread enters */ - void Update(float dt, CArchitectureQueue& queue); - + /* This is where the game thread enters */ + void Update(float dt, CArchitectureQueue& queue); }; -} - +} // namespace urde diff --git a/Runtime/Input/CKeyboardMouseController.hpp b/Runtime/Input/CKeyboardMouseController.hpp index 2c5e6f016..70bafd951 100644 --- a/Runtime/Input/CKeyboardMouseController.hpp +++ b/Runtime/Input/CKeyboardMouseController.hpp @@ -2,18 +2,15 @@ #include -namespace urde -{ +namespace urde { -struct CKeyboardMouseControllerData -{ - bool m_charKeys[256] = {}; - bool m_specialKeys[26] = {}; - bool m_mouseButtons[6] = {}; - boo::EModifierKey m_modMask = boo::EModifierKey::None; - boo::SWindowCoord m_mouseCoord; - boo::SScrollDelta m_accumScroll; +struct CKeyboardMouseControllerData { + bool m_charKeys[256] = {}; + bool m_specialKeys[26] = {}; + bool m_mouseButtons[6] = {}; + boo::EModifierKey m_modMask = boo::EModifierKey::None; + boo::SWindowCoord m_mouseCoord; + boo::SScrollDelta m_accumScroll; }; -} - +} // namespace urde diff --git a/Runtime/Input/CRumbleGenerator.cpp b/Runtime/Input/CRumbleGenerator.cpp index 5fc6c353b..9b4840369 100644 --- a/Runtime/Input/CRumbleGenerator.cpp +++ b/Runtime/Input/CRumbleGenerator.cpp @@ -1,19 +1,14 @@ #include "CRumbleGenerator.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { -CRumbleGenerator::CRumbleGenerator() -{ - xf0_24_disabled = false; - HardStopAll(); +CRumbleGenerator::CRumbleGenerator() { + xf0_24_disabled = false; + HardStopAll(); } -CRumbleGenerator::~CRumbleGenerator() -{ - HardStopAll(); -} +CRumbleGenerator::~CRumbleGenerator() { HardStopAll(); } #define PWM_MONITOR 0 #if PWM_MONITOR @@ -21,113 +16,91 @@ static bool b_tp = false; static std::chrono::steady_clock::time_point s_tp; #endif -void CRumbleGenerator::Update(float dt) -{ +void CRumbleGenerator::Update(float dt) { #if PWM_MONITOR - std::chrono::milliseconds::rep ms = 0; - std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); - if (!b_tp) - { - b_tp = true; - s_tp = now; - } - else - ms = std::chrono::duration_cast(now - s_tp).count(); + std::chrono::milliseconds::rep ms = 0; + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + if (!b_tp) { + b_tp = true; + s_tp = now; + } else + ms = std::chrono::duration_cast(now - s_tp).count(); #endif - if (!xf0_24_disabled) - { - bool updated = false; - for (int i=0 ; i<4 ; ++i) - { - float intensity = x0_voices[i].GetIntensity(); - if (!x0_voices[i].Update(dt) || intensity <= 0.f) - { - xc0_periodTime[i] = 0.f; - xd0_onTime[i] = 0.f; - if (xe0_commandArray[i] != EMotorState::Stop) - { -#if PWM_MONITOR - s_tp = now; - printf("%lldms ON\n", ms); -#endif - xe0_commandArray[i] = EMotorState::Stop; - updated = true; - } - } - else - { - xc0_periodTime[i] += dt; - if (xc0_periodTime[i] >= 1.f / (30.f * intensity)) - { - xc0_periodTime[i] = 0.f; - if (xe0_commandArray[i] != EMotorState::Rumble) - { -#if PWM_MONITOR - s_tp = now; - printf("%lldms Off\n", ms); -#endif - xe0_commandArray[i] = EMotorState::Rumble; - updated = true; - } - } - else - { - xd0_onTime[i] += dt; - if (xd0_onTime[i] >= (1.f / 30.f)) - { - xd0_onTime[i] = 0.f; - if (xe0_commandArray[i] != EMotorState::Stop) - { -#if PWM_MONITOR - s_tp = now; - printf("%lldms ON\n", ms); -#endif - xe0_commandArray[i] = EMotorState::Stop; - updated = true; - } - } - } - } - } - if (updated) - g_InputGenerator->ControlAllMotors(xe0_commandArray); - } -} - -static const EMotorState HardStopCommands[] = { EMotorState::StopHard, - EMotorState::StopHard, - EMotorState::StopHard, - EMotorState::StopHard }; - -void CRumbleGenerator::HardStopAll() -{ - for (int i=0 ; i<4 ; ++i) - { + if (!xf0_24_disabled) { + bool updated = false; + for (int i = 0; i < 4; ++i) { + float intensity = x0_voices[i].GetIntensity(); + if (!x0_voices[i].Update(dt) || intensity <= 0.f) { xc0_periodTime[i] = 0.f; xd0_onTime[i] = 0.f; - xe0_commandArray[i] = EMotorState::Stop; - x0_voices[i].HardReset(); + if (xe0_commandArray[i] != EMotorState::Stop) { +#if PWM_MONITOR + s_tp = now; + printf("%lldms ON\n", ms); +#endif + xe0_commandArray[i] = EMotorState::Stop; + updated = true; + } + } else { + xc0_periodTime[i] += dt; + if (xc0_periodTime[i] >= 1.f / (30.f * intensity)) { + xc0_periodTime[i] = 0.f; + if (xe0_commandArray[i] != EMotorState::Rumble) { +#if PWM_MONITOR + s_tp = now; + printf("%lldms Off\n", ms); +#endif + xe0_commandArray[i] = EMotorState::Rumble; + updated = true; + } + } else { + xd0_onTime[i] += dt; + if (xd0_onTime[i] >= (1.f / 30.f)) { + xd0_onTime[i] = 0.f; + if (xe0_commandArray[i] != EMotorState::Stop) { +#if PWM_MONITOR + s_tp = now; + printf("%lldms ON\n", ms); +#endif + xe0_commandArray[i] = EMotorState::Stop; + updated = true; + } + } + } + } } - g_InputGenerator->ControlAllMotors(HardStopCommands); + if (updated) + g_InputGenerator->ControlAllMotors(xe0_commandArray); + } } -s16 CRumbleGenerator::Rumble(const SAdsrData& adsr, float gain, ERumblePriority prio, EIOPort port) -{ - CRumbleVoice& vox = x0_voices[int(port)]; - s16 freeChan = vox.GetFreeChannel(); - if (prio >= vox.GetPriority(freeChan)) - { - xc0_periodTime[int(port)] = 0.f; - return vox.Activate(adsr, freeChan, gain, prio); - } - return -1; +static const EMotorState HardStopCommands[] = {EMotorState::StopHard, EMotorState::StopHard, EMotorState::StopHard, + EMotorState::StopHard}; + +void CRumbleGenerator::HardStopAll() { + for (int i = 0; i < 4; ++i) { + xc0_periodTime[i] = 0.f; + xd0_onTime[i] = 0.f; + xe0_commandArray[i] = EMotorState::Stop; + x0_voices[i].HardReset(); + } + g_InputGenerator->ControlAllMotors(HardStopCommands); } -void CRumbleGenerator::Stop(s16 id, EIOPort port) -{ - CRumbleVoice& vox = x0_voices[int(port)]; - vox.Deactivate(id, false); +s16 CRumbleGenerator::Rumble(const SAdsrData& adsr, float gain, ERumblePriority prio, EIOPort port) { + CRumbleVoice& vox = x0_voices[int(port)]; + s16 freeChan = vox.GetFreeChannel(); + if (prio >= vox.GetPriority(freeChan)) { + xc0_periodTime[int(port)] = 0.f; + return vox.Activate(adsr, freeChan, gain, prio); + } + return -1; } +void CRumbleGenerator::Stop(s16 id, EIOPort port) { + CRumbleVoice& vox = x0_voices[int(port)]; + vox.Deactivate(id, false); } + +} // namespace urde diff --git a/Runtime/Input/CRumbleGenerator.hpp b/Runtime/Input/CRumbleGenerator.hpp index de50e9a17..bd857334e 100644 --- a/Runtime/Input/CRumbleGenerator.hpp +++ b/Runtime/Input/CRumbleGenerator.hpp @@ -3,24 +3,22 @@ #include "CRumbleVoice.hpp" #include "CInputGenerator.hpp" -namespace urde -{ -class CRumbleGenerator -{ - CRumbleVoice x0_voices[4]; - float xc0_periodTime[4]; - float xd0_onTime[4]; - EMotorState xe0_commandArray[4]; - bool xf0_24_disabled : 1; -public: - CRumbleGenerator(); - ~CRumbleGenerator(); - void Update(float dt); - void HardStopAll(); - s16 Rumble(const SAdsrData& adsr, float, ERumblePriority prio, EIOPort port); - void Stop(s16 id, EIOPort port); - bool IsDisabled() const { return xf0_24_disabled; } - void SetDisabled(bool disabled) { xf0_24_disabled = disabled; } -}; -} +namespace urde { +class CRumbleGenerator { + CRumbleVoice x0_voices[4]; + float xc0_periodTime[4]; + float xd0_onTime[4]; + EMotorState xe0_commandArray[4]; + bool xf0_24_disabled : 1; +public: + CRumbleGenerator(); + ~CRumbleGenerator(); + void Update(float dt); + void HardStopAll(); + s16 Rumble(const SAdsrData& adsr, float, ERumblePriority prio, EIOPort port); + void Stop(s16 id, EIOPort port); + bool IsDisabled() const { return xf0_24_disabled; } + void SetDisabled(bool disabled) { xf0_24_disabled = disabled; } +}; +} // namespace urde diff --git a/Runtime/Input/CRumbleManager.cpp b/Runtime/Input/CRumbleManager.cpp index 65a9e3281..601dc688e 100644 --- a/Runtime/Input/CRumbleManager.cpp +++ b/Runtime/Input/CRumbleManager.cpp @@ -5,25 +5,22 @@ #include "CGameState.hpp" #include "RumbleFxTable.hpp" -namespace urde -{ +namespace urde { -s16 CRumbleManager::Rumble(CStateManager& mgr, const zeus::CVector3f& pos, - ERumbleFxId fx, float dist, ERumblePriority priority) -{ - if (zeus::close_enough(dist, 0.f)) - return -1; - zeus::CVector3f delta = mgr.GetPlayer().GetTranslation() - pos; - if (delta.magSquared() < dist * dist) - return Rumble(mgr, fx, 1.f - delta.magnitude() / dist, priority); +s16 CRumbleManager::Rumble(CStateManager& mgr, const zeus::CVector3f& pos, ERumbleFxId fx, float dist, + ERumblePriority priority) { + if (zeus::close_enough(dist, 0.f)) return -1; + zeus::CVector3f delta = mgr.GetPlayer().GetTranslation() - pos; + if (delta.magSquared() < dist * dist) + return Rumble(mgr, fx, 1.f - delta.magnitude() / dist, priority); + return -1; } -s16 CRumbleManager::Rumble(CStateManager& mgr, ERumbleFxId fx, float gain, ERumblePriority priority) -{ - if (g_GameState->GameOptions().GetIsRumbleEnabled()) - return x0_rumbleGenerator.Rumble(RumbleFxTable[int(fx)], gain, priority, EIOPort::Zero); - return -1; +s16 CRumbleManager::Rumble(CStateManager& mgr, ERumbleFxId fx, float gain, ERumblePriority priority) { + if (g_GameState->GameOptions().GetIsRumbleEnabled()) + return x0_rumbleGenerator.Rumble(RumbleFxTable[int(fx)], gain, priority, EIOPort::Zero); + return -1; } -} +} // namespace urde diff --git a/Runtime/Input/CRumbleManager.hpp b/Runtime/Input/CRumbleManager.hpp index d8e06d40e..b25e42caa 100644 --- a/Runtime/Input/CRumbleManager.hpp +++ b/Runtime/Input/CRumbleManager.hpp @@ -3,25 +3,22 @@ #include "CRumbleGenerator.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class CRumbleManager -{ - CRumbleGenerator x0_rumbleGenerator; -public: - bool IsDisabled() const { return x0_rumbleGenerator.IsDisabled(); } - void SetDisabled(bool disabled) { x0_rumbleGenerator.SetDisabled(disabled); } - void Update(float dt) { x0_rumbleGenerator.Update(dt); } - void StopRumble(s16 id) - { - if (id == -1) - return; - x0_rumbleGenerator.Stop(id, EIOPort::Zero); - } - void HardStopAll() { x0_rumbleGenerator.HardStopAll(); } - s16 Rumble(CStateManager& mgr, const zeus::CVector3f& pos, ERumbleFxId fx, float dist, ERumblePriority priority); - s16 Rumble(CStateManager& mgr, ERumbleFxId fx, float gain, ERumblePriority priority); -}; -} +class CRumbleManager { + CRumbleGenerator x0_rumbleGenerator; +public: + bool IsDisabled() const { return x0_rumbleGenerator.IsDisabled(); } + void SetDisabled(bool disabled) { x0_rumbleGenerator.SetDisabled(disabled); } + void Update(float dt) { x0_rumbleGenerator.Update(dt); } + void StopRumble(s16 id) { + if (id == -1) + return; + x0_rumbleGenerator.Stop(id, EIOPort::Zero); + } + void HardStopAll() { x0_rumbleGenerator.HardStopAll(); } + s16 Rumble(CStateManager& mgr, const zeus::CVector3f& pos, ERumbleFxId fx, float dist, ERumblePriority priority); + s16 Rumble(CStateManager& mgr, ERumbleFxId fx, float gain, ERumblePriority priority); +}; +} // namespace urde diff --git a/Runtime/Input/CRumbleVoice.cpp b/Runtime/Input/CRumbleVoice.cpp index 3e6866364..ddc98cc13 100644 --- a/Runtime/Input/CRumbleVoice.cpp +++ b/Runtime/Input/CRumbleVoice.cpp @@ -1,204 +1,160 @@ #include "CRumbleVoice.hpp" -namespace urde -{ +namespace urde { -CRumbleVoice::CRumbleVoice() -{ - x0_datas.resize(4); - x10_deltas.resize(4, SAdsrDelta::Stopped()); - x20_handleIds.resize(4); +CRumbleVoice::CRumbleVoice() { + x0_datas.resize(4); + x10_deltas.resize(4, SAdsrDelta::Stopped()); + x20_handleIds.resize(4); } -s16 CRumbleVoice::CreateRumbleHandle(s16 idx) -{ - ++x2e_lastId; - if (x2e_lastId == 0) - x2e_lastId = 1; - x20_handleIds[idx] = x2e_lastId; - return (x2e_lastId << 8) | idx; +s16 CRumbleVoice::CreateRumbleHandle(s16 idx) { + ++x2e_lastId; + if (x2e_lastId == 0) + x2e_lastId = 1; + x20_handleIds[idx] = x2e_lastId; + return (x2e_lastId << 8) | idx; } -bool CRumbleVoice::OwnsSustained(s16 handle) const -{ - int idx = handle & 0xf; - if (idx < 4) - return x20_handleIds[idx] == ((handle >> 8) & 0xff); - return false; +bool CRumbleVoice::OwnsSustained(s16 handle) const { + int idx = handle & 0xf; + if (idx < 4) + return x20_handleIds[idx] == ((handle >> 8) & 0xff); + return false; } -s16 CRumbleVoice::GetFreeChannel() const -{ - for (s16 i=0 ; i<4 ; ++i) - if (!((1 << i) & x2c_usedChannels)) - return i; - return false; +s16 CRumbleVoice::GetFreeChannel() const { + for (s16 i = 0; i < 4; ++i) + if (!((1 << i) & x2c_usedChannels)) + return i; + return false; } -float CRumbleVoice::GetIntensity() const -{ - return std::min(2.f, - std::max(x10_deltas[0].x0_curIntensity, - std::max(x10_deltas[1].x0_curIntensity, - std::max(x10_deltas[2].x0_curIntensity, - x10_deltas[3].x0_curIntensity)))); +float CRumbleVoice::GetIntensity() const { + return std::min(2.f, std::max(x10_deltas[0].x0_curIntensity, + std::max(x10_deltas[1].x0_curIntensity, + std::max(x10_deltas[2].x0_curIntensity, x10_deltas[3].x0_curIntensity)))); } -bool CRumbleVoice::UpdateChannel(SAdsrDelta& delta, const SAdsrData& data, float dt) -{ - switch (delta.x20_phase) - { - case SAdsrDelta::EPhase::PrePulse: - if (delta.x4_attackTime < (1.f/30.f)) - { - delta.x4_attackTime += dt; - } - else - { - delta.x20_phase = SAdsrDelta::EPhase::Attack; - delta.x0_curIntensity = 0.f; - delta.x4_attackTime = 0.f; - } - break; - case SAdsrDelta::EPhase::Attack: - if (delta.x4_attackTime < data.x8_attackDur) - { - float t = delta.x4_attackTime / data.x8_attackDur; - delta.x0_curIntensity = t * delta.x14_attackIntensity; - delta.x4_attackTime += dt; - } - else - { - delta.x0_curIntensity = delta.x14_attackIntensity; - delta.x20_phase = SAdsrDelta::EPhase::Decay; - } - break; - case SAdsrDelta::EPhase::Decay: - if (data.x18_24_hasSustain) - { - if (delta.x8_decayTime < data.xc_decayDur) - { - float t = delta.x8_decayTime / data.xc_decayDur; - delta.x0_curIntensity = (1.f - t) * delta.x14_attackIntensity + t * delta.x18_sustainIntensity; - delta.x8_decayTime += dt; - } - else - { - delta.x0_curIntensity = delta.x18_sustainIntensity; - delta.x20_phase = SAdsrDelta::EPhase::Sustain; - } - } - else - { - if (delta.x8_decayTime < data.xc_decayDur) - { - float t = delta.x8_decayTime / data.xc_decayDur; - delta.x0_curIntensity = (1.f - t) * delta.x14_attackIntensity; - delta.x8_decayTime += dt; - } - else - { - delta.x0_curIntensity = 0.f; - delta.x20_phase = SAdsrDelta::EPhase::Stop; - } - if (delta.x20_phase != SAdsrDelta::EPhase::Decay) - { - delta.x20_phase = SAdsrDelta::EPhase::Stop; - return true; - } - } - break; - case SAdsrDelta::EPhase::Release: - { - float a = data.x18_24_hasSustain ? delta.x18_sustainIntensity : 0.f; - if (delta.xc_releaseTime < data.x14_releaseDur) - { - float t = delta.xc_releaseTime / data.x14_releaseDur; - delta.x0_curIntensity = (1.f - t) * a; - delta.xc_releaseTime += dt; - } - else - { - delta.x0_curIntensity = 0.f; - delta.x20_phase = SAdsrDelta::EPhase::Stop; - } - if (delta.x20_phase != SAdsrDelta::EPhase::Release) - { - delta.x20_phase = SAdsrDelta::EPhase::Stop; - return true; - } +bool CRumbleVoice::UpdateChannel(SAdsrDelta& delta, const SAdsrData& data, float dt) { + switch (delta.x20_phase) { + case SAdsrDelta::EPhase::PrePulse: + if (delta.x4_attackTime < (1.f / 30.f)) { + delta.x4_attackTime += dt; + } else { + delta.x20_phase = SAdsrDelta::EPhase::Attack; + delta.x0_curIntensity = 0.f; + delta.x4_attackTime = 0.f; } break; - default: - break; + case SAdsrDelta::EPhase::Attack: + if (delta.x4_attackTime < data.x8_attackDur) { + float t = delta.x4_attackTime / data.x8_attackDur; + delta.x0_curIntensity = t * delta.x14_attackIntensity; + delta.x4_attackTime += dt; + } else { + delta.x0_curIntensity = delta.x14_attackIntensity; + delta.x20_phase = SAdsrDelta::EPhase::Decay; } - - if (data.x18_25_autoRelease) - { - if (delta.x10_autoReleaseTime < data.x4_autoReleaseDur) - delta.x10_autoReleaseTime += dt; - else if (delta.x20_phase == SAdsrDelta::EPhase::Sustain) - delta.x20_phase = SAdsrDelta::EPhase::Release; - } - - return false; -} - -bool CRumbleVoice::Update(float dt) -{ - if (x2c_usedChannels != 0) - { - for (s16 i=0 ; i<4 ; ++i) - { - if ((1 << i) & x2c_usedChannels) - { - if (UpdateChannel(x10_deltas[i], x0_datas[i], dt)) - { - x2c_usedChannels &= ~(1 << i); - x10_deltas[i] = SAdsrDelta::Stopped(); - } - } - } + break; + case SAdsrDelta::EPhase::Decay: + if (data.x18_24_hasSustain) { + if (delta.x8_decayTime < data.xc_decayDur) { + float t = delta.x8_decayTime / data.xc_decayDur; + delta.x0_curIntensity = (1.f - t) * delta.x14_attackIntensity + t * delta.x18_sustainIntensity; + delta.x8_decayTime += dt; + } else { + delta.x0_curIntensity = delta.x18_sustainIntensity; + delta.x20_phase = SAdsrDelta::EPhase::Sustain; + } + } else { + if (delta.x8_decayTime < data.xc_decayDur) { + float t = delta.x8_decayTime / data.xc_decayDur; + delta.x0_curIntensity = (1.f - t) * delta.x14_attackIntensity; + delta.x8_decayTime += dt; + } else { + delta.x0_curIntensity = 0.f; + delta.x20_phase = SAdsrDelta::EPhase::Stop; + } + if (delta.x20_phase != SAdsrDelta::EPhase::Decay) { + delta.x20_phase = SAdsrDelta::EPhase::Stop; return true; + } } - return false; + break; + case SAdsrDelta::EPhase::Release: { + float a = data.x18_24_hasSustain ? delta.x18_sustainIntensity : 0.f; + if (delta.xc_releaseTime < data.x14_releaseDur) { + float t = delta.xc_releaseTime / data.x14_releaseDur; + delta.x0_curIntensity = (1.f - t) * a; + delta.xc_releaseTime += dt; + } else { + delta.x0_curIntensity = 0.f; + delta.x20_phase = SAdsrDelta::EPhase::Stop; + } + if (delta.x20_phase != SAdsrDelta::EPhase::Release) { + delta.x20_phase = SAdsrDelta::EPhase::Stop; + return true; + } + } break; + default: + break; + } + + if (data.x18_25_autoRelease) { + if (delta.x10_autoReleaseTime < data.x4_autoReleaseDur) + delta.x10_autoReleaseTime += dt; + else if (delta.x20_phase == SAdsrDelta::EPhase::Sustain) + delta.x20_phase = SAdsrDelta::EPhase::Release; + } + + return false; } -void CRumbleVoice::HardReset() -{ - x2c_usedChannels = 0; - for (s16 i=0 ; i<4 ; ++i) - { - x10_deltas[i] = SAdsrDelta::Stopped(); - x20_handleIds[i] = 0; +bool CRumbleVoice::Update(float dt) { + if (x2c_usedChannels != 0) { + for (s16 i = 0; i < 4; ++i) { + if ((1 << i) & x2c_usedChannels) { + if (UpdateChannel(x10_deltas[i], x0_datas[i], dt)) { + x2c_usedChannels &= ~(1 << i); + x10_deltas[i] = SAdsrDelta::Stopped(); + } + } } + return true; + } + return false; } -s16 CRumbleVoice::Activate(const SAdsrData& data, s16 idx, float gain, ERumblePriority prio) -{ - if (gain > 0.f) - { - x0_datas[idx] = data; - x10_deltas[idx] = SAdsrDelta::Start(prio, x2c_usedChannels == 0); - x10_deltas[idx].x14_attackIntensity = gain * x0_datas[idx].x0_attackGain; - x10_deltas[idx].x18_sustainIntensity = gain * x0_datas[idx].x10_sustainGain; - x2c_usedChannels |= 1 << idx; - if (data.x18_24_hasSustain) - return CreateRumbleHandle(idx); - } - return -1; +void CRumbleVoice::HardReset() { + x2c_usedChannels = 0; + for (s16 i = 0; i < 4; ++i) { + x10_deltas[i] = SAdsrDelta::Stopped(); + x20_handleIds[i] = 0; + } } -void CRumbleVoice::Deactivate(s16 id, bool b1) -{ - if (id == -1) - return; - if (OwnsSustained(id)) - { - int handle = (id & 0xf); - if (x2c_usedChannels & (1 << handle)) - x10_deltas[handle].x20_phase = SAdsrDelta::EPhase::Release; - } +s16 CRumbleVoice::Activate(const SAdsrData& data, s16 idx, float gain, ERumblePriority prio) { + if (gain > 0.f) { + x0_datas[idx] = data; + x10_deltas[idx] = SAdsrDelta::Start(prio, x2c_usedChannels == 0); + x10_deltas[idx].x14_attackIntensity = gain * x0_datas[idx].x0_attackGain; + x10_deltas[idx].x18_sustainIntensity = gain * x0_datas[idx].x10_sustainGain; + x2c_usedChannels |= 1 << idx; + if (data.x18_24_hasSustain) + return CreateRumbleHandle(idx); + } + return -1; } +void CRumbleVoice::Deactivate(s16 id, bool b1) { + if (id == -1) + return; + if (OwnsSustained(id)) { + int handle = (id & 0xf); + if (x2c_usedChannels & (1 << handle)) + x10_deltas[handle].x20_phase = SAdsrDelta::EPhase::Release; + } } + +} // namespace urde diff --git a/Runtime/Input/CRumbleVoice.hpp b/Runtime/Input/CRumbleVoice.hpp index 119c04edb..5b3042756 100644 --- a/Runtime/Input/CRumbleVoice.hpp +++ b/Runtime/Input/CRumbleVoice.hpp @@ -2,112 +2,96 @@ #include "RetroTypes.hpp" -namespace urde -{ -enum class ERumbleFxId -{ - Zero = 0, - One = 1, - CameraShake = 6, - EscapeSequenceShake = 7, - PlayerBump = 11, - PlayerGunCharge = 12, - PlayerMissileFire = 13, - PlayerGrappleFire = 14, - PlayerLand = 15, - PlayerGrappleSwoosh = 17, - IntroBossProjectile = 19, - Twenty = 20, - TwentyOne = 21, - TwentyTwo = 22, - TwentyThree = 23 -}; -enum class ERumblePriority -{ - None = 0, - One = 1, - Two = 2, - Three = 3 +namespace urde { +enum class ERumbleFxId { + Zero = 0, + One = 1, + CameraShake = 6, + EscapeSequenceShake = 7, + PlayerBump = 11, + PlayerGunCharge = 12, + PlayerMissileFire = 13, + PlayerGrappleFire = 14, + PlayerLand = 15, + PlayerGrappleSwoosh = 17, + IntroBossProjectile = 19, + Twenty = 20, + TwentyOne = 21, + TwentyTwo = 22, + TwentyThree = 23 }; +enum class ERumblePriority { None = 0, One = 1, Two = 2, Three = 3 }; -struct SAdsrData -{ - float x0_attackGain = 0.f; - float x4_autoReleaseDur = 0.f; - float x8_attackDur = 0.f; - float xc_decayDur = 0.f; - float x10_sustainGain = 0.f; - float x14_releaseDur = 0.f; - union - { - struct { bool x18_24_hasSustain : 1; bool x18_25_autoRelease : 1; }; - u8 dummy = 0; +struct SAdsrData { + float x0_attackGain = 0.f; + float x4_autoReleaseDur = 0.f; + float x8_attackDur = 0.f; + float xc_decayDur = 0.f; + float x10_sustainGain = 0.f; + float x14_releaseDur = 0.f; + union { + struct { + bool x18_24_hasSustain : 1; + bool x18_25_autoRelease : 1; }; + u8 dummy = 0; + }; - SAdsrData() = default; - SAdsrData(float attackGain, float autoReleaseDur, float attackDur, float decayDur, - float sustainGain, float releaseDur, bool hasSustain, bool autoRelease) - : x0_attackGain(attackGain), x4_autoReleaseDur(autoReleaseDur), x8_attackDur(attackDur), - xc_decayDur(decayDur), x10_sustainGain(sustainGain), x14_releaseDur(releaseDur) - { - x18_24_hasSustain = hasSustain; - x18_25_autoRelease = autoRelease; - } + SAdsrData() = default; + SAdsrData(float attackGain, float autoReleaseDur, float attackDur, float decayDur, float sustainGain, + float releaseDur, bool hasSustain, bool autoRelease) + : x0_attackGain(attackGain) + , x4_autoReleaseDur(autoReleaseDur) + , x8_attackDur(attackDur) + , xc_decayDur(decayDur) + , x10_sustainGain(sustainGain) + , x14_releaseDur(releaseDur) { + x18_24_hasSustain = hasSustain; + x18_25_autoRelease = autoRelease; + } }; -struct SAdsrDelta -{ - enum class EPhase - { - Stop, - PrePulse, - Attack, - Decay, - Sustain, - Release - }; +struct SAdsrDelta { + enum class EPhase { Stop, PrePulse, Attack, Decay, Sustain, Release }; - float x0_curIntensity = 0.f; - float x4_attackTime = 0.f; - float x8_decayTime = 0.f; - float xc_releaseTime = 0.f; - float x10_autoReleaseTime = 0.f; - float x14_attackIntensity; - float x18_sustainIntensity; - ERumblePriority x1c_priority; - EPhase x20_phase; + float x0_curIntensity = 0.f; + float x4_attackTime = 0.f; + float x8_decayTime = 0.f; + float xc_releaseTime = 0.f; + float x10_autoReleaseTime = 0.f; + float x14_attackIntensity; + float x18_sustainIntensity; + ERumblePriority x1c_priority; + EPhase x20_phase; - SAdsrDelta(EPhase phase, ERumblePriority priority) - : x0_curIntensity(phase == EPhase::PrePulse ? 2.f : 0.f), x1c_priority(priority), x20_phase(phase) - {} - SAdsrDelta(EPhase phase) - : x1c_priority(ERumblePriority::None), x20_phase(phase) - {} + SAdsrDelta(EPhase phase, ERumblePriority priority) + : x0_curIntensity(phase == EPhase::PrePulse ? 2.f : 0.f), x1c_priority(priority), x20_phase(phase) {} + SAdsrDelta(EPhase phase) : x1c_priority(ERumblePriority::None), x20_phase(phase) {} - static SAdsrDelta Stopped() { return SAdsrDelta(EPhase::Stop); } - static SAdsrDelta Start(ERumblePriority priority, bool prePulse) - { return SAdsrDelta(prePulse ? EPhase::PrePulse : EPhase::Attack, priority); } + static SAdsrDelta Stopped() { return SAdsrDelta(EPhase::Stop); } + static SAdsrDelta Start(ERumblePriority priority, bool prePulse) { + return SAdsrDelta(prePulse ? EPhase::PrePulse : EPhase::Attack, priority); + } }; -class CRumbleVoice -{ - std::vector x0_datas; - std::vector x10_deltas; - rstl::reserved_vector x20_handleIds; - s16 x2c_usedChannels = 0; - u8 x2e_lastId = 0; - bool UpdateChannel(SAdsrDelta& delta, const SAdsrData& data, float dt); +class CRumbleVoice { + std::vector x0_datas; + std::vector x10_deltas; + rstl::reserved_vector x20_handleIds; + s16 x2c_usedChannels = 0; + u8 x2e_lastId = 0; + bool UpdateChannel(SAdsrDelta& delta, const SAdsrData& data, float dt); + public: - CRumbleVoice(); - s16 CreateRumbleHandle(s16 idx); - bool OwnsSustained(s16 id) const; - s16 GetFreeChannel() const; - float GetIntensity() const; - bool Update(float dt); - void HardReset(); - s16 Activate(const SAdsrData& data, s16 idx, float gain, ERumblePriority prio); - void Deactivate(s16 id, bool b1); - ERumblePriority GetPriority(s16 idx) const { return x10_deltas[idx].x1c_priority; } + CRumbleVoice(); + s16 CreateRumbleHandle(s16 idx); + bool OwnsSustained(s16 id) const; + s16 GetFreeChannel() const; + float GetIntensity() const; + bool Update(float dt); + void HardReset(); + s16 Activate(const SAdsrData& data, s16 idx, float gain, ERumblePriority prio); + void Deactivate(s16 id, bool b1); + ERumblePriority GetPriority(s16 idx) const { return x10_deltas[idx].x1c_priority; } }; -} - +} // namespace urde diff --git a/Runtime/Input/ControlMapper.cpp b/Runtime/Input/ControlMapper.cpp index 5074d7dd6..3e86b37e0 100644 --- a/Runtime/Input/ControlMapper.cpp +++ b/Runtime/Input/ControlMapper.cpp @@ -4,255 +4,181 @@ #include "DataSpec/DNACommon/Tweaks/ITweakPlayerControl.hpp" #include "../GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { -static const char* skCommandDescs[] = -{ - "Forward", - "Backward", - "Turn Left", - "Turn Right", - "Strafe Left", - "Strafe Right", - "Look Left", - "Look Right", - "Look Up", - "Look Down", - "Jump/Boost", - "Fire/Bomb", - "Missile/PowerBomb", - "Morph", - "Aim Up", - "Aim Down", - "Cycle Beam Up", - "Cycle Beam Down", - "Cycle Item", - "Power Beam", - "Ice Beam", - "Wave Beam", - "Plasma Beam", - "Toggle Holster", - "Orbit Close", - "Orbit Far", - "Orbit Object", - "Orbit Select", - "Orbit Confirm", - "Orbit Left", - "Orbit Right", - "Orbit Up", - "Orbit Down", - "Look Hold1", - "Look Hold2", - "Look Zoom In", - "Look Zoom Out", - "Aim Hold", - "Map Circle Up", - "Map Circle Down", - "Map Circle Left", - "Map Circle Right", - "Map Move Forward", - "Map Move Back", - "Map Move Left", - "Map Move Right", - "Map Zoom In", - "Map Zoom Out", - "SpiderBall", - "Chase Camera", - "XRay Visor", - "Thermo Visor", - "Enviro Visor", - "No Visor", - "Visor Menu", - "Visor Up", - "Visor Down", - "UNKNOWN", - "UNKNOWN", - "Use Shield", - "Scan Item", - "UNKNOWN" +static const char* skCommandDescs[] = { + "Forward", "Backward", "Turn Left", "Turn Right", "Strafe Left", "Strafe Right", + "Look Left", "Look Right", "Look Up", "Look Down", "Jump/Boost", "Fire/Bomb", + "Missile/PowerBomb", "Morph", "Aim Up", "Aim Down", "Cycle Beam Up", "Cycle Beam Down", + "Cycle Item", "Power Beam", "Ice Beam", "Wave Beam", "Plasma Beam", "Toggle Holster", + "Orbit Close", "Orbit Far", "Orbit Object", "Orbit Select", "Orbit Confirm", "Orbit Left", + "Orbit Right", "Orbit Up", "Orbit Down", "Look Hold1", "Look Hold2", "Look Zoom In", + "Look Zoom Out", "Aim Hold", "Map Circle Up", "Map Circle Down", "Map Circle Left", "Map Circle Right", + "Map Move Forward", "Map Move Back", "Map Move Left", "Map Move Right", "Map Zoom In", "Map Zoom Out", + "SpiderBall", "Chase Camera", "XRay Visor", "Thermo Visor", "Enviro Visor", "No Visor", + "Visor Menu", "Visor Up", "Visor Down", "UNKNOWN", "UNKNOWN", "Use Shield", + "Scan Item", "UNKNOWN" }; -static const char* skFunctionDescs[] = -{ - "None", - "Left Stick Up", - "Left Stick Down", - "Left Stick Left", - "Left Stick Right", - "Right Stick Up", - "Right Stick Down", - "Right Stick Left", - "Right Stick Right", - "Left Trigger", - "Right Trigger", - "D-Pad Up ", - "D-Pad Down ", - "D-Pad Left ", - "D-Pad Right", - "A Button", - "B Button", - "X Button", - "Y Button", - "Z Button", - "Left Trigger Press", - "Right Trigger Press", - "Start" -}; +static const char* skFunctionDescs[] = {"None", + "Left Stick Up", + "Left Stick Down", + "Left Stick Left", + "Left Stick Right", + "Right Stick Up", + "Right Stick Down", + "Right Stick Left", + "Right Stick Right", + "Left Trigger", + "Right Trigger", + "D-Pad Up ", + "D-Pad Down ", + "D-Pad Left ", + "D-Pad Right", + "A Button", + "B Button", + "X Button", + "Y Button", + "Z Button", + "Left Trigger Press", + "Right Trigger Press", + "Start"}; typedef bool (CFinalInput::*BoolReturnFn)() const; typedef float (CFinalInput::*FloatReturnFn)() const; -static BoolReturnFn skPressFuncs[] = -{ - nullptr, - &CFinalInput::PLAUp, - &CFinalInput::PLADown, - &CFinalInput::PLALeft, - &CFinalInput::PLARight, - &CFinalInput::PRAUp, - &CFinalInput::PRADown, - &CFinalInput::PRALeft, - &CFinalInput::PRARight, - &CFinalInput::PLTrigger, - &CFinalInput::PRTrigger, - &CFinalInput::PDPUp, - &CFinalInput::PDPDown, - &CFinalInput::PDPLeft, - &CFinalInput::PDPRight, - &CFinalInput::PA, - &CFinalInput::PB, - &CFinalInput::PX, - &CFinalInput::PY, - &CFinalInput::PZ, - &CFinalInput::PL, - &CFinalInput::PR, - &CFinalInput::PStart, - nullptr -}; +static BoolReturnFn skPressFuncs[] = {nullptr, + &CFinalInput::PLAUp, + &CFinalInput::PLADown, + &CFinalInput::PLALeft, + &CFinalInput::PLARight, + &CFinalInput::PRAUp, + &CFinalInput::PRADown, + &CFinalInput::PRALeft, + &CFinalInput::PRARight, + &CFinalInput::PLTrigger, + &CFinalInput::PRTrigger, + &CFinalInput::PDPUp, + &CFinalInput::PDPDown, + &CFinalInput::PDPLeft, + &CFinalInput::PDPRight, + &CFinalInput::PA, + &CFinalInput::PB, + &CFinalInput::PX, + &CFinalInput::PY, + &CFinalInput::PZ, + &CFinalInput::PL, + &CFinalInput::PR, + &CFinalInput::PStart, + nullptr}; -static BoolReturnFn skDigitalFuncs[] = -{ - nullptr, - &CFinalInput::DLAUp, - &CFinalInput::DLADown, - &CFinalInput::DLALeft, - &CFinalInput::DLARight, - &CFinalInput::DRAUp, - &CFinalInput::DRADown, - &CFinalInput::DRALeft, - &CFinalInput::DRARight, - &CFinalInput::DLTrigger, - &CFinalInput::DRTrigger, - &CFinalInput::DDPUp, - &CFinalInput::DDPDown, - &CFinalInput::DDPLeft, - &CFinalInput::DDPRight, - &CFinalInput::DA, - &CFinalInput::DB, - &CFinalInput::DX, - &CFinalInput::DY, - &CFinalInput::DZ, - &CFinalInput::DL, - &CFinalInput::DR, - &CFinalInput::DStart, - nullptr -}; +static BoolReturnFn skDigitalFuncs[] = {nullptr, + &CFinalInput::DLAUp, + &CFinalInput::DLADown, + &CFinalInput::DLALeft, + &CFinalInput::DLARight, + &CFinalInput::DRAUp, + &CFinalInput::DRADown, + &CFinalInput::DRALeft, + &CFinalInput::DRARight, + &CFinalInput::DLTrigger, + &CFinalInput::DRTrigger, + &CFinalInput::DDPUp, + &CFinalInput::DDPDown, + &CFinalInput::DDPLeft, + &CFinalInput::DDPRight, + &CFinalInput::DA, + &CFinalInput::DB, + &CFinalInput::DX, + &CFinalInput::DY, + &CFinalInput::DZ, + &CFinalInput::DL, + &CFinalInput::DR, + &CFinalInput::DStart, + nullptr}; -static FloatReturnFn skAnalogFuncs[] = -{ - nullptr, - &CFinalInput::ALAUp, - &CFinalInput::ALADown, - &CFinalInput::ALALeft, - &CFinalInput::ALARight, - &CFinalInput::ARAUp, - &CFinalInput::ARADown, - &CFinalInput::ARALeft, - &CFinalInput::ARARight, - &CFinalInput::ALTrigger, - &CFinalInput::ARTrigger, - &CFinalInput::ADPUp, - &CFinalInput::ADPDown, - &CFinalInput::ADPLeft, - &CFinalInput::ADPRight, - &CFinalInput::AA, - &CFinalInput::AB, - &CFinalInput::AX, - &CFinalInput::AY, - &CFinalInput::AZ, - &CFinalInput::AL, - &CFinalInput::AR, - &CFinalInput::AStart, - nullptr -}; +static FloatReturnFn skAnalogFuncs[] = {nullptr, + &CFinalInput::ALAUp, + &CFinalInput::ALADown, + &CFinalInput::ALALeft, + &CFinalInput::ALARight, + &CFinalInput::ARAUp, + &CFinalInput::ARADown, + &CFinalInput::ARALeft, + &CFinalInput::ARARight, + &CFinalInput::ALTrigger, + &CFinalInput::ARTrigger, + &CFinalInput::ADPUp, + &CFinalInput::ADPDown, + &CFinalInput::ADPLeft, + &CFinalInput::ADPRight, + &CFinalInput::AA, + &CFinalInput::AB, + &CFinalInput::AX, + &CFinalInput::AY, + &CFinalInput::AZ, + &CFinalInput::AL, + &CFinalInput::AR, + &CFinalInput::AStart, + nullptr}; #define kCommandFilterCount 67 static bool skCommandFilterFlag[kCommandFilterCount] = {true}; -void ControlMapper::SetCommandFiltered(ECommands cmd, bool filtered) -{ - skCommandFilterFlag[int(cmd)] = filtered; +void ControlMapper::SetCommandFiltered(ECommands cmd, bool filtered) { skCommandFilterFlag[int(cmd)] = filtered; } + +void ControlMapper::ResetCommandFilters() { + for (int i = 0; i < kCommandFilterCount; ++i) + skCommandFilterFlag[i] = true; } -void ControlMapper::ResetCommandFilters() -{ - for (int i=0 ; iGetMapping(atUint32(cmd))); + if (func > EFunctionList::MAX) + return false; + BoolReturnFn fn = skPressFuncs[int(func)]; + if (!fn) + return false; + return (input.*fn)(); } -bool ControlMapper::GetPressInput(ECommands cmd, const CFinalInput& input) -{ - if (!skCommandFilterFlag[int(cmd)]) - return false; - EFunctionList func = EFunctionList(g_currentPlayerControl->GetMapping(atUint32(cmd))); - if (func > EFunctionList::MAX) - return false; - BoolReturnFn fn = skPressFuncs[int(func)]; - if (!fn) - return false; - return (input.*fn)(); +bool ControlMapper::GetDigitalInput(ECommands cmd, const CFinalInput& input) { + if (!skCommandFilterFlag[int(cmd)]) + return false; + EFunctionList func = EFunctionList(g_currentPlayerControl->GetMapping(atUint32(cmd))); + if (func > EFunctionList::MAX) + return false; + BoolReturnFn fn = skDigitalFuncs[int(func)]; + if (!fn) + return false; + return (input.*fn)(); } -bool ControlMapper::GetDigitalInput(ECommands cmd, const CFinalInput& input) -{ - if (!skCommandFilterFlag[int(cmd)]) - return false; - EFunctionList func = EFunctionList(g_currentPlayerControl->GetMapping(atUint32(cmd))); - if (func > EFunctionList::MAX) - return false; - BoolReturnFn fn = skDigitalFuncs[int(func)]; - if (!fn) - return false; - return (input.*fn)(); +float ControlMapper::GetAnalogInput(ECommands cmd, const CFinalInput& input) { + if (!skCommandFilterFlag[int(cmd)]) + return 0.0; + EFunctionList func = EFunctionList(g_currentPlayerControl->GetMapping(atUint32(cmd))); + if (func > EFunctionList::MAX) + return 0.0; + FloatReturnFn fn = skAnalogFuncs[int(func)]; + if (!fn) + return 0.0; + return (input.*fn)(); } -float ControlMapper::GetAnalogInput(ECommands cmd, const CFinalInput& input) -{ - if (!skCommandFilterFlag[int(cmd)]) - return 0.0; - EFunctionList func = EFunctionList(g_currentPlayerControl->GetMapping(atUint32(cmd))); - if (func > EFunctionList::MAX) - return 0.0; - FloatReturnFn fn = skAnalogFuncs[int(func)]; - if (!fn) - return 0.0; - return (input.*fn)(); +const char* ControlMapper::GetDescriptionForCommand(ECommands cmd) { + if (cmd > ECommands::MAX) + return nullptr; + return skCommandDescs[int(cmd)]; } -const char* ControlMapper::GetDescriptionForCommand(ECommands cmd) -{ - if (cmd > ECommands::MAX) - return nullptr; - return skCommandDescs[int(cmd)]; +const char* ControlMapper::GetDescriptionForFunction(EFunctionList func) { + if (func > EFunctionList::MAX) + return nullptr; + return skFunctionDescs[int(func)]; } -const char* ControlMapper::GetDescriptionForFunction(EFunctionList func) -{ - if (func > EFunctionList::MAX) - return nullptr; - return skFunctionDescs[int(func)]; -} - -} +} // namespace urde diff --git a/Runtime/Input/ControlMapper.hpp b/Runtime/Input/ControlMapper.hpp index 4a110d4a6..ddac068f4 100644 --- a/Runtime/Input/ControlMapper.hpp +++ b/Runtime/Input/ControlMapper.hpp @@ -1,117 +1,112 @@ #pragma once -namespace urde -{ +namespace urde { struct CFinalInput; -class ControlMapper -{ +class ControlMapper { public: - enum class ECommands - { - Forward, - Backward, - TurnLeft, - TurnRight, - StrafeLeft, - StrafeRight, - LookLeft, - LookRight, - LookUp, - LookDown, - JumpOrBoost = 10, - FireOrBomb = 11, - MissileOrPowerBomb = 12, - Morph, - AimUp, - AimDown, - CycleBeamUp, - CycleBeamDown, - CycleItem, - PowerBeam, - IceBeam, - WaveBeam, - PlasmaBeam, - ToggleHolster = 23, - OrbitClose, - OrbitFar, - OrbitObject, - OrbitSelect, - OrbitConfirm, - OrbitLeft, - OrbitRight, - OrbitUp, - OrbitDown, - LookHold1, - LookHold2, - LookZoomIn, - LookZoomOut, - AimHold, - MapCircleUp, - MapCircleDown, - MapCircleLeft, - MapCircleRight, - MapMoveForward, - MapMoveBack, - MapMoveLeft, - MapMoveRight, - MapZoomIn, - MapZoomOut, - SpiderBall, - ChaseCamera, - XrayVisor = 50, - ThermoVisor = 51, - InviroVisor = 52, - NoVisor = 53, - VisorMenu, - VisorUp, - VisorDown, - ShowCrosshairs, - UseSheild=0x3B, - ScanItem=0x3C, - PreviousPauseScreen=0x41, - NextPauseScreen=0x42, - UNKNOWN, - None, - MAX - }; + enum class ECommands { + Forward, + Backward, + TurnLeft, + TurnRight, + StrafeLeft, + StrafeRight, + LookLeft, + LookRight, + LookUp, + LookDown, + JumpOrBoost = 10, + FireOrBomb = 11, + MissileOrPowerBomb = 12, + Morph, + AimUp, + AimDown, + CycleBeamUp, + CycleBeamDown, + CycleItem, + PowerBeam, + IceBeam, + WaveBeam, + PlasmaBeam, + ToggleHolster = 23, + OrbitClose, + OrbitFar, + OrbitObject, + OrbitSelect, + OrbitConfirm, + OrbitLeft, + OrbitRight, + OrbitUp, + OrbitDown, + LookHold1, + LookHold2, + LookZoomIn, + LookZoomOut, + AimHold, + MapCircleUp, + MapCircleDown, + MapCircleLeft, + MapCircleRight, + MapMoveForward, + MapMoveBack, + MapMoveLeft, + MapMoveRight, + MapZoomIn, + MapZoomOut, + SpiderBall, + ChaseCamera, + XrayVisor = 50, + ThermoVisor = 51, + InviroVisor = 52, + NoVisor = 53, + VisorMenu, + VisorUp, + VisorDown, + ShowCrosshairs, + UseSheild = 0x3B, + ScanItem = 0x3C, + PreviousPauseScreen = 0x41, + NextPauseScreen = 0x42, + UNKNOWN, + None, + MAX + }; - enum class EFunctionList - { - None, - LeftStickUp, - LeftStickDown, - LeftStickLeft, - LeftStickRight, - RightStickUp, - RightStickDown, - RightStickLeft, - RightStickRight, - LeftTrigger, - RightTrigger, - DPadUp, - DPadDown, - DPadLeft, - DPadRight, - AButton, - BButton, - XButton, - YButton, - ZButton, - LeftTriggerPress, - RightTriggerPress, - Start, - MAX // default case - }; + enum class EFunctionList { + None, + LeftStickUp, + LeftStickDown, + LeftStickLeft, + LeftStickRight, + RightStickUp, + RightStickDown, + RightStickLeft, + RightStickRight, + LeftTrigger, + RightTrigger, + DPadUp, + DPadDown, + DPadLeft, + DPadRight, + AButton, + BButton, + XButton, + YButton, + ZButton, + LeftTriggerPress, + RightTriggerPress, + Start, + MAX // default case + }; - static void SetCommandFiltered(ECommands cmd, bool filtered); - static void ResetCommandFilters(); - static bool GetPressInput(ECommands cmd, const CFinalInput& input); - static bool GetDigitalInput(ECommands cmd, const CFinalInput& input); - static float GetAnalogInput(ECommands cmd, const CFinalInput& input); - static const char* GetDescriptionForCommand(ECommands cmd); - static const char* GetDescriptionForFunction(EFunctionList func); + static void SetCommandFiltered(ECommands cmd, bool filtered); + static void ResetCommandFilters(); + static bool GetPressInput(ECommands cmd, const CFinalInput& input); + static bool GetDigitalInput(ECommands cmd, const CFinalInput& input); + static float GetAnalogInput(ECommands cmd, const CFinalInput& input); + static const char* GetDescriptionForCommand(ECommands cmd); + static const char* GetDescriptionForFunction(EFunctionList func); }; -} - +} // namespace urde diff --git a/Runtime/Input/IController.hpp b/Runtime/Input/IController.hpp index bb6507ee6..9bba88e7d 100644 --- a/Runtime/Input/IController.hpp +++ b/Runtime/Input/IController.hpp @@ -2,21 +2,13 @@ #include "../RetroTypes.hpp" -namespace urde -{ +namespace urde { -class IController -{ +class IController { public: - enum class EMotorState - { - Stop = 0, - Rumble = 1, - StopHard = 2 - }; - virtual void Poll()=0; - virtual void SetMotorState(EMotorState state)=0; + enum class EMotorState { Stop = 0, Rumble = 1, StopHard = 2 }; + virtual void Poll() = 0; + virtual void SetMotorState(EMotorState state) = 0; }; -} - +} // namespace urde diff --git a/Runtime/Input/RumbleFxTable.cpp b/Runtime/Input/RumbleFxTable.cpp index d2ff954b2..a887e0497 100644 --- a/Runtime/Input/RumbleFxTable.cpp +++ b/Runtime/Input/RumbleFxTable.cpp @@ -1,35 +1,32 @@ #include "RumbleFxTable.hpp" -namespace urde -{ +namespace urde { -const SAdsrData RumbleFxTable[] = -{ +const SAdsrData RumbleFxTable[] = { /* attackGain, autoReleaseDur, attackDur, decayDur, sustainGain, releaseDur, hasSustain, autoRelease */ - {0.48f, 0.f, 0.3f, 0.125f, 0.1f, 0.5f, false, false}, - {0.66f, 0.f, 0.11f, 0.175f, 0.42f, 0.375f, false, false}, - {0.42f, 0.f, 0.1f, 0.225f, 0.225f, 0.f, false, false}, - {1.5f, 0.f, 0.1f, 0.225f, 1.025f, 0.4f, false, false}, - {0.786f, 0.f, 0.1f, 0.16f, 0.655f, 0.255f, false, false}, - {1.2f, 0.f, 0.4f, 0.1f, 1.f, 0.055f, false, false}, - {1.2f, 0.f, 0.05f, 0.3f, 0.4f, 1.1f, false, false}, // CameraShake - {1.02f, 0.f, 0.065f, 0.175f, 0.85f, 0.9f, false, false}, // EscapeSequenceShake - {0.48f, 0.f, 0.065f, 0.175f, 0.4f, 0.0f, false, false}, - {0.72f, 0.f, 0.001f, 0.001f, 0.6f, 0.1f, false, false}, - {0.24f, 0.f, 0.001f, 0.525f, 0.2f, 0.2f, false, false}, - {2.4f, 0.f, 0.001f, 0.466f, 0.f, 0.f, false, false}, // PlayerBump - {0.5532f, 0.f, 0.f, 1.345f, 0.f, 1.756f, false, false}, // PlayerGunCharge - {2.4f, 0.f, 0.01f, 0.125f, 0.25f, 0.5f, false, false}, // PlayerMissileFire - {0.84f, 0.f, 0.1f, 0.125f, 0.35f, 1.0f, false, false}, // PlayerGrappleFire - {2.4f, 0.f, 0.1f, 0.225f, 0.38f, 0.3f, false, false}, // PlayerLand - {0.48f, 0.f, 0.065f, 0.175f, 0.4f, 0.f, false, false}, // IntroBossProjectile (??) - {0.3024f, 0.f, 0.1f, 1.345f, 0.f, 1.756f, false, false}, // PlayerGrappleSwoosh - {0.72f, 0.f, 0.01f, 0.01f, 0.6f, 0.1f, false, false}, - {1.1904f, 0.f, 0.f, 0.125f, 0.683f, 0.5f, true, false}, - {1.2f, 0.f, 0.01f, 0.621f, 0.f, 0.f, false, false}, - {0.5268f, 0.f, 0.114f, 1.008f, 0.f, 0.325f, false, false}, - {0.6828f, 0.f, 0.f, 0.821f, 0.f, 0.f, false, false}, - {1.8f, 0.f, 0.5f, 0.425f, 0.35f, 0.5f, false, false} -}; + {0.48f, 0.f, 0.3f, 0.125f, 0.1f, 0.5f, false, false}, + {0.66f, 0.f, 0.11f, 0.175f, 0.42f, 0.375f, false, false}, + {0.42f, 0.f, 0.1f, 0.225f, 0.225f, 0.f, false, false}, + {1.5f, 0.f, 0.1f, 0.225f, 1.025f, 0.4f, false, false}, + {0.786f, 0.f, 0.1f, 0.16f, 0.655f, 0.255f, false, false}, + {1.2f, 0.f, 0.4f, 0.1f, 1.f, 0.055f, false, false}, + {1.2f, 0.f, 0.05f, 0.3f, 0.4f, 1.1f, false, false}, // CameraShake + {1.02f, 0.f, 0.065f, 0.175f, 0.85f, 0.9f, false, false}, // EscapeSequenceShake + {0.48f, 0.f, 0.065f, 0.175f, 0.4f, 0.0f, false, false}, + {0.72f, 0.f, 0.001f, 0.001f, 0.6f, 0.1f, false, false}, + {0.24f, 0.f, 0.001f, 0.525f, 0.2f, 0.2f, false, false}, + {2.4f, 0.f, 0.001f, 0.466f, 0.f, 0.f, false, false}, // PlayerBump + {0.5532f, 0.f, 0.f, 1.345f, 0.f, 1.756f, false, false}, // PlayerGunCharge + {2.4f, 0.f, 0.01f, 0.125f, 0.25f, 0.5f, false, false}, // PlayerMissileFire + {0.84f, 0.f, 0.1f, 0.125f, 0.35f, 1.0f, false, false}, // PlayerGrappleFire + {2.4f, 0.f, 0.1f, 0.225f, 0.38f, 0.3f, false, false}, // PlayerLand + {0.48f, 0.f, 0.065f, 0.175f, 0.4f, 0.f, false, false}, // IntroBossProjectile (??) + {0.3024f, 0.f, 0.1f, 1.345f, 0.f, 1.756f, false, false}, // PlayerGrappleSwoosh + {0.72f, 0.f, 0.01f, 0.01f, 0.6f, 0.1f, false, false}, + {1.1904f, 0.f, 0.f, 0.125f, 0.683f, 0.5f, true, false}, + {1.2f, 0.f, 0.01f, 0.621f, 0.f, 0.f, false, false}, + {0.5268f, 0.f, 0.114f, 1.008f, 0.f, 0.325f, false, false}, + {0.6828f, 0.f, 0.f, 0.821f, 0.f, 0.f, false, false}, + {1.8f, 0.f, 0.5f, 0.425f, 0.35f, 0.5f, false, false}}; } diff --git a/Runtime/Input/RumbleFxTable.hpp b/Runtime/Input/RumbleFxTable.hpp index 87ef159dc..3c63da69c 100644 --- a/Runtime/Input/RumbleFxTable.hpp +++ b/Runtime/Input/RumbleFxTable.hpp @@ -2,10 +2,8 @@ #include "CRumbleVoice.hpp" -namespace urde -{ +namespace urde { extern const SAdsrData RumbleFxTable[]; } - diff --git a/Runtime/MP1/CArtifactDoll.cpp b/Runtime/MP1/CArtifactDoll.cpp index 297e31124..66620c372 100644 --- a/Runtime/MP1/CArtifactDoll.cpp +++ b/Runtime/MP1/CArtifactDoll.cpp @@ -4,27 +4,24 @@ #include "CStateManager.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -static const char* ArtifactPieceModels[] = -{ - "CMDL_Piece1", // Truth - "CMDL_Piece2", // Strength - "CMDL_Piece3", // Elder - "CMDL_Piece4", // Wild - "CMDL_Piece5", // Lifegiver - "CMDL_Piece6", // Warrior - "CMDL_Piece7", // Chozo - "CMDL_Piece8", // Nature - "CMDL_Piece9", // Sun +static const char* ArtifactPieceModels[] = { + "CMDL_Piece1", // Truth + "CMDL_Piece2", // Strength + "CMDL_Piece3", // Elder + "CMDL_Piece4", // Wild + "CMDL_Piece5", // Lifegiver + "CMDL_Piece6", // Warrior + "CMDL_Piece7", // Chozo + "CMDL_Piece8", // Nature + "CMDL_Piece9", // Sun "CMDL_Piece10", // World "CMDL_Piece11", // Spirit - "CMDL_Piece12" // Newborn + "CMDL_Piece12" // Newborn }; -static const CAssetId ArtifactHeadScans[] = -{ +static const CAssetId ArtifactHeadScans[] = { 0x32C9DDCE, // Truth 0xB45DAF60, // Strength 0x7F017CC5, // Elder @@ -36,155 +33,131 @@ static const CAssetId ArtifactHeadScans[] = 0xDE9A5FA3, // Sun 0xFBBE9D9A, // World 0x30E24E3F, // Spirit - 0xB6763C91 // Newborn + 0xB6763C91 // Newborn }; static const zeus::CColor ArtifactPreColor = {0.4f, 0.68f, 0.88f, 0.8f}; static const zeus::CColor ArtifactPostColor = {1.f, 0.63f, 0.02f, 1.f}; -CArtifactDoll::CArtifactDoll() -{ - x10_lights.resize(2, CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skWhite)); - x20_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, - false, false, false, 0.1f); - x28_24_loaded = false; - x0_models.reserve(12); - for (int i=0 ; i<12 ; ++i) - x0_models.push_back(g_SimplePool->GetObj(ArtifactPieceModels[i])); +CArtifactDoll::CArtifactDoll() { + x10_lights.resize(2, CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skWhite)); + x20_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f); + x28_24_loaded = false; + x0_models.reserve(12); + for (int i = 0; i < 12; ++i) + x0_models.push_back(g_SimplePool->GetObj(ArtifactPieceModels[i])); } -int CArtifactDoll::GetArtifactHeadScanIndex(CAssetId scanId) -{ - CAssetId orig = g_ResFactory->TranslateNewToOriginal(scanId); - for (int i=0 ; i<12 ; ++i) - if (ArtifactHeadScans[i] == orig) - return i; +int CArtifactDoll::GetArtifactHeadScanIndex(CAssetId scanId) { + CAssetId orig = g_ResFactory->TranslateNewToOriginal(scanId); + for (int i = 0; i < 12; ++i) + if (ArtifactHeadScans[i] == orig) + return i; + return -1; +} + +CAssetId CArtifactDoll::GetArtifactHeadScanFromItemType(CPlayerState::EItemType item) { + if (item < CPlayerState::EItemType::Truth || item > CPlayerState::EItemType::Newborn) return -1; + return g_ResFactory->TranslateOriginalToNew(ArtifactHeadScans[int(item) - 29]); } -CAssetId CArtifactDoll::GetArtifactHeadScanFromItemType(CPlayerState::EItemType item) -{ - if (item < CPlayerState::EItemType::Truth || item > CPlayerState::EItemType::Newborn) - return -1; - return g_ResFactory->TranslateOriginalToNew(ArtifactHeadScans[int(item) - 29]); -} - -void CArtifactDoll::UpdateArtifactHeadScan(const CStateManager& mgr, float delta) -{ - CPlayerState& playerState = *mgr.GetPlayerState(); - for (int i=0 ; i<12 ; ++i) - { - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType(i + 29))) - { - CAssetId newId = g_ResFactory->TranslateOriginalToNew(ArtifactHeadScans[i]); - playerState.SetScanTime(newId, std::min(playerState.GetScanTime(newId) + delta, 1.f)); - } +void CArtifactDoll::UpdateArtifactHeadScan(const CStateManager& mgr, float delta) { + CPlayerState& playerState = *mgr.GetPlayerState(); + for (int i = 0; i < 12; ++i) { + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType(i + 29))) { + CAssetId newId = g_ResFactory->TranslateOriginalToNew(ArtifactHeadScans[i]); + playerState.SetScanTime(newId, std::min(playerState.GetScanTime(newId) + delta, 1.f)); } + } } -void CArtifactDoll::CompleteArtifactHeadScan(const CStateManager& mgr) -{ - UpdateArtifactHeadScan(mgr, 1.f); -} +void CArtifactDoll::CompleteArtifactHeadScan(const CStateManager& mgr) { UpdateArtifactHeadScan(mgr, 1.f); } -void CArtifactDoll::Draw(float alpha, const CStateManager& mgr, - bool inArtifactCategory, int selectedArtifact) -{ - if (!IsLoaded()) - return; +void CArtifactDoll::Draw(float alpha, const CStateManager& mgr, bool inArtifactCategory, int selectedArtifact) { + if (!IsLoaded()) + return; - alpha *= x24_fader; - g_Renderer->SetPerspective(55.f, g_Viewport.x8_width, g_Viewport.xc_height, 0.2f, 4096.f); - CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -10.f, 0.f)); + alpha *= x24_fader; + g_Renderer->SetPerspective(55.f, g_Viewport.x8_width, g_Viewport.xc_height, 0.2f, 4096.f); + CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -10.f, 0.f)); - float angle = CGraphics::GetSecondsMod900() * 2.f * M_PIF * 0.25f; - CGraphics::SetModelMatrix( - zeus::CTransform::RotateX(zeus::degToRad(std::sin(angle) * 8.f)) * - zeus::CTransform::RotateZ(zeus::degToRad(std::cos(angle) * 8.f)) * - zeus::CTransform::RotateX(M_PIF / 2.f) * - zeus::CTransform::Scale(0.2f)); + float angle = CGraphics::GetSecondsMod900() * 2.f * M_PIF * 0.25f; + CGraphics::SetModelMatrix(zeus::CTransform::RotateX(zeus::degToRad(std::sin(angle) * 8.f)) * + zeus::CTransform::RotateZ(zeus::degToRad(std::cos(angle) * 8.f)) * + zeus::CTransform::RotateX(M_PIF / 2.f) * zeus::CTransform::Scale(0.2f)); - CPlayerState& playerState = *mgr.GetPlayerState(); - for (int i=0 ; i& model = x0_models[i]; - zeus::CColor color = ArtifactPreColor; - if (playerState.HasPowerUp(CPlayerState::EItemType(i + 29))) - { - if (ArtifactHeadScans[i].IsValid()) - { - CAssetId newId = g_ResFactory->TranslateOriginalToNew(ArtifactHeadScans[i]); - float interp = (playerState.GetScanTime(newId) - 0.5f) * 2.f; - if (interp < 0.5f) - color = zeus::CColor::lerp(ArtifactPreColor, zeus::CColor::skWhite, 2.f * interp); - else - color = zeus::CColor::lerp(zeus::CColor::skWhite, ArtifactPostColor, 2.f * (interp - 0.5f)); - } - else - { - color = ArtifactPostColor; - } - } - - if (inArtifactCategory && i == selectedArtifact) - { - float interp = (std::sin(CGraphics::GetSecondsMod900() * 2.f * M_PIF) + 1.f) * 0.5f; - color = zeus::CColor::lerp(zeus::CColor::skWhite, color, interp); - color.a() *= zeus::clamp(0.f, 1.25f - interp, 1.f); - } - - CModelFlags flags(7, 0, 3, zeus::CColor(1.f, 0.f)); - flags.m_extendedShader = EExtendedShader::SolidColorFrontfaceCullLEqualAlphaOnly; - x20_actorLights->ActivateLights(model->GetInstance()); - model->Draw(flags); - - flags.x4_color = color; - flags.x4_color.a() *= alpha; - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - model->Draw(flags); + CPlayerState& playerState = *mgr.GetPlayerState(); + for (int i = 0; i < x0_models.size(); ++i) { + TLockedToken& model = x0_models[i]; + zeus::CColor color = ArtifactPreColor; + if (playerState.HasPowerUp(CPlayerState::EItemType(i + 29))) { + if (ArtifactHeadScans[i].IsValid()) { + CAssetId newId = g_ResFactory->TranslateOriginalToNew(ArtifactHeadScans[i]); + float interp = (playerState.GetScanTime(newId) - 0.5f) * 2.f; + if (interp < 0.5f) + color = zeus::CColor::lerp(ArtifactPreColor, zeus::CColor::skWhite, 2.f * interp); + else + color = zeus::CColor::lerp(zeus::CColor::skWhite, ArtifactPostColor, 2.f * (interp - 0.5f)); + } else { + color = ArtifactPostColor; + } } + + if (inArtifactCategory && i == selectedArtifact) { + float interp = (std::sin(CGraphics::GetSecondsMod900() * 2.f * M_PIF) + 1.f) * 0.5f; + color = zeus::CColor::lerp(zeus::CColor::skWhite, color, interp); + color.a() *= zeus::clamp(0.f, 1.25f - interp, 1.f); + } + + CModelFlags flags(7, 0, 3, zeus::CColor(1.f, 0.f)); + flags.m_extendedShader = EExtendedShader::SolidColorFrontfaceCullLEqualAlphaOnly; + x20_actorLights->ActivateLights(model->GetInstance()); + model->Draw(flags); + + flags.x4_color = color; + flags.x4_color.a() *= alpha; + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + model->Draw(flags); + } } -void CArtifactDoll::UpdateActorLights() -{ - x10_lights[0] = CLight::BuildDirectional( - (zeus::CVector3f::skForward + 0.25f * zeus::CVector3f::skRight + 0.1f * zeus::CVector3f::skDown).normalized(), - zeus::CColor::skWhite); - x10_lights[1] = CLight::BuildDirectional(-zeus::CVector3f::skForward, zeus::CColor::skBlack); - x20_actorLights->BuildFakeLightList(x10_lights, zeus::CColor(0.25f, 1.f)); +void CArtifactDoll::UpdateActorLights() { + x10_lights[0] = CLight::BuildDirectional( + (zeus::CVector3f::skForward + 0.25f * zeus::CVector3f::skRight + 0.1f * zeus::CVector3f::skDown).normalized(), + zeus::CColor::skWhite); + x10_lights[1] = CLight::BuildDirectional(-zeus::CVector3f::skForward, zeus::CColor::skBlack); + x20_actorLights->BuildFakeLightList(x10_lights, zeus::CColor(0.25f, 1.f)); } -void CArtifactDoll::Update(float dt, const CStateManager& mgr) -{ - if (!CheckLoadComplete()) - return; +void CArtifactDoll::Update(float dt, const CStateManager& mgr) { + if (!CheckLoadComplete()) + return; - x24_fader = std::min(x24_fader + 2.f * dt, 1.f); - if (std::fabs(x24_fader - 1.f) < 0.00001f) - UpdateArtifactHeadScan(mgr, 0.5f * dt * 0.5f); - UpdateActorLights(); + x24_fader = std::min(x24_fader + 2.f * dt, 1.f); + if (std::fabs(x24_fader - 1.f) < 0.00001f) + UpdateArtifactHeadScan(mgr, 0.5f * dt * 0.5f); + UpdateActorLights(); } -void CArtifactDoll::Touch() -{ - if (!CheckLoadComplete()) - return; +void CArtifactDoll::Touch() { + if (!CheckLoadComplete()) + return; - for (TLockedToken& model : x0_models) - model->Touch(0); + for (TLockedToken& model : x0_models) + model->Touch(0); } -bool CArtifactDoll::CheckLoadComplete() -{ - if (IsLoaded()) - return true; - - for (TLockedToken& model : x0_models) - if (!model.IsLoaded()) - return false; - - x28_24_loaded = true; +bool CArtifactDoll::CheckLoadComplete() { + if (IsLoaded()) return true; + + for (TLockedToken& model : x0_models) + if (!model.IsLoaded()) + return false; + + x28_24_loaded = true; + return true; } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CArtifactDoll.hpp b/Runtime/MP1/CArtifactDoll.hpp index b70a7b38c..96e5eff25 100644 --- a/Runtime/MP1/CArtifactDoll.hpp +++ b/Runtime/MP1/CArtifactDoll.hpp @@ -5,33 +5,30 @@ #include "CToken.hpp" #include "CPlayerState.hpp" -namespace urde -{ +namespace urde { class CModel; -namespace MP1 -{ +namespace MP1 { + +class CArtifactDoll { + std::vector> x0_models; + std::vector x10_lights; + std::unique_ptr x20_actorLights; + float x24_fader = 0.f; + bool x28_24_loaded : 1; + void UpdateActorLights(); -class CArtifactDoll -{ - std::vector> x0_models; - std::vector x10_lights; - std::unique_ptr x20_actorLights; - float x24_fader = 0.f; - bool x28_24_loaded : 1; - void UpdateActorLights(); public: - CArtifactDoll(); - static int GetArtifactHeadScanIndex(CAssetId scanId); - static CAssetId GetArtifactHeadScanFromItemType(CPlayerState::EItemType item); - static void UpdateArtifactHeadScan(const CStateManager& mgr, float delta); - static void CompleteArtifactHeadScan(const CStateManager& mgr); - void Draw(float alpha, const CStateManager& mgr, bool inArtifactCategory, int selectedArtifact); - void Update(float dt, const CStateManager& mgr); - void Touch(); - bool CheckLoadComplete(); - bool IsLoaded() const { return x28_24_loaded; } + CArtifactDoll(); + static int GetArtifactHeadScanIndex(CAssetId scanId); + static CAssetId GetArtifactHeadScanFromItemType(CPlayerState::EItemType item); + static void UpdateArtifactHeadScan(const CStateManager& mgr, float delta); + static void CompleteArtifactHeadScan(const CStateManager& mgr); + void Draw(float alpha, const CStateManager& mgr, bool inArtifactCategory, int selectedArtifact); + void Update(float dt, const CStateManager& mgr); + void Touch(); + bool CheckLoadComplete(); + bool IsLoaded() const { return x28_24_loaded; } }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CAudioStateWin.cpp b/Runtime/MP1/CAudioStateWin.cpp index af5eef4d9..9c98b8613 100644 --- a/Runtime/MP1/CAudioStateWin.cpp +++ b/Runtime/MP1/CAudioStateWin.cpp @@ -6,29 +6,23 @@ #include "CGameState.hpp" #include "MP1.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CIOWin::EMessageReturn CAudioStateWin::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - CMain* m = static_cast(g_Main); +CIOWin::EMessageReturn CAudioStateWin::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + CMain* m = static_cast(g_Main); - const EArchMsgType msgType = msg.GetType(); - if (msgType == EArchMsgType::SetGameState) - { - CSfxManager::KillAll(CSfxManager::ESfxChannels::Game); - CSfxManager::TurnOnChannel(CSfxManager::ESfxChannels::Game); + const EArchMsgType msgType = msg.GetType(); + if (msgType == EArchMsgType::SetGameState) { + CSfxManager::KillAll(CSfxManager::ESfxChannels::Game); + CSfxManager::TurnOnChannel(CSfxManager::ESfxChannels::Game); + } else if (msgType == EArchMsgType::QuitGameplay) { + if (g_GameState->GetWorldTransitionManager()->GetTransType() == CWorldTransManager::ETransType::Disabled || + m->GetFlowState() != EFlowState::None) { + CSfxManager::SetChannel(CSfxManager::ESfxChannels::Default); + CSfxManager::KillAll(CSfxManager::ESfxChannels::Game); } - else if (msgType == EArchMsgType::QuitGameplay) - { - if (g_GameState->GetWorldTransitionManager()->GetTransType() == CWorldTransManager::ETransType::Disabled || - m->GetFlowState() != EFlowState::None) - { - CSfxManager::SetChannel(CSfxManager::ESfxChannels::Default); - CSfxManager::KillAll(CSfxManager::ESfxChannels::Game); - } - } - return EMessageReturn::Normal; + } + return EMessageReturn::Normal; } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CAudioStateWin.hpp b/Runtime/MP1/CAudioStateWin.hpp index 2e597279f..b0e1baa05 100644 --- a/Runtime/MP1/CAudioStateWin.hpp +++ b/Runtime/MP1/CAudioStateWin.hpp @@ -2,14 +2,11 @@ #include "../CIOWin.hpp" -namespace urde::MP1 -{ -class CAudioStateWin : public CIOWin -{ +namespace urde::MP1 { +class CAudioStateWin : public CIOWin { public: - CAudioStateWin() : CIOWin("CAudioStateWin") {} - CIOWin::EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); + CAudioStateWin() : CIOWin("CAudioStateWin") {} + CIOWin::EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CAutoSave.cpp b/Runtime/MP1/CAutoSave.cpp index 538eed9b0..8c50b8201 100644 --- a/Runtime/MP1/CAutoSave.cpp +++ b/Runtime/MP1/CAutoSave.cpp @@ -2,11 +2,7 @@ #include "CSaveGameScreen.hpp" #include "IMain.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CAutoSave::CAutoSave() -: CIOWin("") -, x14_savegameScreen(new CSaveGameScreen(ESaveContext::InGame, g_GameState->GetCardSerial())) -{ -} -} +: CIOWin(""), x14_savegameScreen(new CSaveGameScreen(ESaveContext::InGame, g_GameState->GetCardSerial())) {} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CAutoSave.hpp b/Runtime/MP1/CAutoSave.hpp index b35450e4d..9e74c81be 100644 --- a/Runtime/MP1/CAutoSave.hpp +++ b/Runtime/MP1/CAutoSave.hpp @@ -2,13 +2,12 @@ #include "CIOWin.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { class CSaveGameScreen; -class CAutoSave : CIOWin -{ - std::unique_ptr x14_savegameScreen; +class CAutoSave : CIOWin { + std::unique_ptr x14_savegameScreen; + public: - CAutoSave(); + CAutoSave(); }; -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CCredits.cpp b/Runtime/MP1/CCredits.cpp index ab662eb5e..a0deb0944 100644 --- a/Runtime/MP1/CCredits.cpp +++ b/Runtime/MP1/CCredits.cpp @@ -1,22 +1,13 @@ #include "CCredits.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CCredits::CCredits() -: CIOWin("Credits") -{ +CCredits::CCredits() : CIOWin("Credits") {} +CIOWin::EMessageReturn CCredits::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + return EMessageReturn::Normal; } -CIOWin::EMessageReturn CCredits::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - return EMessageReturn::Normal; -} +void CCredits::Draw() const {} -void CCredits::Draw() const -{ - -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CCredits.hpp b/Runtime/MP1/CCredits.hpp index c30204181..afef0d743 100644 --- a/Runtime/MP1/CCredits.hpp +++ b/Runtime/MP1/CCredits.hpp @@ -2,17 +2,14 @@ #include "CIOWin.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class CCredits : public CIOWin -{ +class CCredits : public CIOWin { public: - CCredits(); - EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); - bool GetIsContinueDraw() const { return false; } - void Draw() const; + CCredits(); + EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); + bool GetIsContinueDraw() const { return false; } + void Draw() const; }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CFaceplateDecoration.cpp b/Runtime/MP1/CFaceplateDecoration.cpp index d1944a488..a5d1a6dd3 100644 --- a/Runtime/MP1/CFaceplateDecoration.cpp +++ b/Runtime/MP1/CFaceplateDecoration.cpp @@ -5,47 +5,40 @@ #include "CSimplePool.hpp" #include "Particle/CGenDescription.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CFaceplateDecoration::CFaceplateDecoration(CStateManager& stateMgr) {} -void CFaceplateDecoration::Update(float dt, CStateManager& stateMgr) -{ - CAssetId txtrId = stateMgr.GetPlayer().GetVisorSteam().GetTextureId(); - if (!txtrId.IsValid()) - { - if (xc_ready) - { - x4_tex.Unlock(); - x0_id = txtrId; - if (m_texFilter) - m_texFilter = std::experimental::nullopt; - } +void CFaceplateDecoration::Update(float dt, CStateManager& stateMgr) { + CAssetId txtrId = stateMgr.GetPlayer().GetVisorSteam().GetTextureId(); + if (!txtrId.IsValid()) { + if (xc_ready) { + x4_tex.Unlock(); + x0_id = txtrId; + if (m_texFilter) + m_texFilter = std::experimental::nullopt; } + } - if (x0_id != txtrId && txtrId.IsValid()) - { - if (m_texFilter) - m_texFilter = std::experimental::nullopt; - x0_id = txtrId; - x4_tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), txtrId}); - xc_ready = true; - x4_tex.Lock(); - } + if (x0_id != txtrId && txtrId.IsValid()) { + if (m_texFilter) + m_texFilter = std::experimental::nullopt; + x0_id = txtrId; + x4_tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), txtrId}); + xc_ready = true; + x4_tex.Lock(); + } - if (!m_texFilter && x4_tex.IsLoaded()) - m_texFilter.emplace(EFilterType::Blend, x4_tex); + if (!m_texFilter && x4_tex.IsLoaded()) + m_texFilter.emplace(EFilterType::Blend, x4_tex); } -void CFaceplateDecoration::Draw(CStateManager& stateMgr) -{ - if (xc_ready && m_texFilter) - { - zeus::CColor color = zeus::CColor::skWhite; - color.a() = stateMgr.GetPlayer().GetVisorSteam().GetAlpha(); - m_texFilter->draw(color, 1.f); - } +void CFaceplateDecoration::Draw(CStateManager& stateMgr) { + if (xc_ready && m_texFilter) { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = stateMgr.GetPlayer().GetVisorSteam().GetAlpha(); + m_texFilter->draw(color, 1.f); + } } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CFaceplateDecoration.hpp b/Runtime/MP1/CFaceplateDecoration.hpp index d0837b745..a41d13018 100644 --- a/Runtime/MP1/CFaceplateDecoration.hpp +++ b/Runtime/MP1/CFaceplateDecoration.hpp @@ -3,25 +3,22 @@ #include "RetroTypes.hpp" #include "Graphics/Shaders/CTexturedQuadFilter.hpp" -namespace urde -{ +namespace urde { class CStateManager; -namespace MP1 -{ +namespace MP1 { + +class CFaceplateDecoration { + CAssetId x0_id; + TToken x4_tex; + bool xc_ready = false; + std::experimental::optional m_texFilter; -class CFaceplateDecoration -{ - CAssetId x0_id; - TToken x4_tex; - bool xc_ready = false; - std::experimental::optional m_texFilter; public: - CFaceplateDecoration(CStateManager& stateMgr); - void Update(float dt, CStateManager& stateMgr); - void Draw(CStateManager& stateMgr); + CFaceplateDecoration(CStateManager& stateMgr); + void Update(float dt, CStateManager& stateMgr); + void Draw(CStateManager& stateMgr); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CFrontEndUI.cpp b/Runtime/MP1/CFrontEndUI.cpp index d57019600..8d94a60b0 100644 --- a/Runtime/MP1/CFrontEndUI.cpp +++ b/Runtime/MP1/CFrontEndUI.cpp @@ -24,36 +24,27 @@ #include "Input/RumbleFxTable.hpp" #include -namespace urde::MP1 -{ +namespace urde::MP1 { /* Music volume constants */ static const float FE1_VOL = 0.7421875f; static const float FE2_VOL = 0.7421875f; /* L/R Stereo transition cues */ -static const u16 FETransitionBackSFX[3][2] = -{ - {SFXfnt_transfore_00L, SFXfnt_transfore_00R}, - {SFXfnt_transfore_01L, SFXfnt_transfore_01R}, - {SFXfnt_transfore_02L, SFXfnt_transfore_02R} +static const u16 FETransitionBackSFX[3][2] = {{SFXfnt_transfore_00L, SFXfnt_transfore_00R}, + {SFXfnt_transfore_01L, SFXfnt_transfore_01R}, + {SFXfnt_transfore_02L, SFXfnt_transfore_02R}}; + +static const u16 FETransitionForwardSFX[3][2] = {{SFXfnt_transback_00L, SFXfnt_transback_00R}, + {SFXfnt_transback_01L, SFXfnt_transback_01R}, + {SFXfnt_transback_02L, SFXfnt_transback_02R}}; + +struct FEMovie { + const char* path; + bool loop; }; -static const u16 FETransitionForwardSFX[3][2] = -{ - {SFXfnt_transback_00L, SFXfnt_transback_00R}, - {SFXfnt_transback_01L, SFXfnt_transback_01R}, - {SFXfnt_transback_02L, SFXfnt_transback_02R} -}; - -struct FEMovie -{ - const char* path; - bool loop; -}; - -static const FEMovie FEMovies[] = -{ +static const FEMovie FEMovies[] = { {"Video/00_first_start.thp", false}, {"Video/01_startloop.thp", true}, {"Video/02_start_fileselect_A.thp", false}, @@ -67,768 +58,656 @@ static const FEMovie FEMovies[] = SObjectTag g_DefaultWorldTag = {FOURCC('MLVL'), 0x158efe17}; -void CFrontEndUI::PlayAdvanceSfx() -{ - CSfxManager::SfxStart(SFXfnt_advance_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - CSfxManager::SfxStart(SFXfnt_advance_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); +void CFrontEndUI::PlayAdvanceSfx() { + CSfxManager::SfxStart(SFXfnt_advance_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(SFXfnt_advance_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); } CFrontEndUI::SNewFileSelectFrame::SNewFileSelectFrame(CSaveGameScreen* sui, u32 rnd, CFrontEndUITouchBar& touchBar) -: x0_rnd(rnd), x4_saveUI(sui), m_touchBar(touchBar) -{ - x10_frme = g_SimplePool->GetObj("FRME_NewFileSelect"); +: x0_rnd(rnd), x4_saveUI(sui), m_touchBar(touchBar) { + x10_frme = g_SimplePool->GetObj("FRME_NewFileSelect"); } -void CFrontEndUI::SNewFileSelectFrame::FinishedLoading() -{ - x1c_loadedFrame->SetAspectConstraint(1.78f); +void CFrontEndUI::SNewFileSelectFrame::FinishedLoading() { + x1c_loadedFrame->SetAspectConstraint(1.78f); - x20_tablegroup_fileselect = static_cast(x1c_loadedFrame->FindWidget("tablegroup_fileselect")); - x24_model_erase = static_cast(x1c_loadedFrame->FindWidget("model_erase")); - xf8_model_erase_position = x24_model_erase->GetLocalPosition(); - x28_textpane_erase = FindTextPanePair(x1c_loadedFrame, "textpane_erase"); - x38_textpane_gba = FindTextPanePair(x1c_loadedFrame, "textpane_gba"); - x30_textpane_cheats = FindTextPanePair(x1c_loadedFrame, "textpane_cheats"); - x48_textpane_popupadvance = FindTextPanePair(x1c_loadedFrame, "textpane_popupadvance"); - x50_textpane_popupcancel = FindTextPanePair(x1c_loadedFrame, "textpane_popupcancel"); - x58_textpane_popupextra = FindTextPanePair(x1c_loadedFrame, "textpane_popupextra"); - x40_tablegroup_popup = static_cast(x1c_loadedFrame->FindWidget("tablegroup_popup")); - x44_model_dash7 = static_cast(x1c_loadedFrame->FindWidget("model_dash7")); - x60_textpane_cancel = static_cast(x1c_loadedFrame->FindWidget("textpane_cancel")); - FindAndSetPairText(x1c_loadedFrame, "textpane_title", g_MainStringTable->GetString(97)); - CGuiTextPane* proceed = static_cast(x1c_loadedFrame->FindWidget("textpane_proceed")); - if (proceed) - proceed->TextSupport().SetText(g_MainStringTable->GetString(85)); - x40_tablegroup_popup->SetIsVisible(false); - x40_tablegroup_popup->SetIsActive(false); - x40_tablegroup_popup->SetVertical(false); - CGuiWidget* worker = x40_tablegroup_popup->GetWorkerWidget(2); - worker->SetIsSelectable(false); - worker->SetVisibility(false, ETraversalMode::Children); + x20_tablegroup_fileselect = static_cast(x1c_loadedFrame->FindWidget("tablegroup_fileselect")); + x24_model_erase = static_cast(x1c_loadedFrame->FindWidget("model_erase")); + xf8_model_erase_position = x24_model_erase->GetLocalPosition(); + x28_textpane_erase = FindTextPanePair(x1c_loadedFrame, "textpane_erase"); + x38_textpane_gba = FindTextPanePair(x1c_loadedFrame, "textpane_gba"); + x30_textpane_cheats = FindTextPanePair(x1c_loadedFrame, "textpane_cheats"); + x48_textpane_popupadvance = FindTextPanePair(x1c_loadedFrame, "textpane_popupadvance"); + x50_textpane_popupcancel = FindTextPanePair(x1c_loadedFrame, "textpane_popupcancel"); + x58_textpane_popupextra = FindTextPanePair(x1c_loadedFrame, "textpane_popupextra"); + x40_tablegroup_popup = static_cast(x1c_loadedFrame->FindWidget("tablegroup_popup")); + x44_model_dash7 = static_cast(x1c_loadedFrame->FindWidget("model_dash7")); + x60_textpane_cancel = static_cast(x1c_loadedFrame->FindWidget("textpane_cancel")); + FindAndSetPairText(x1c_loadedFrame, "textpane_title", g_MainStringTable->GetString(97)); + CGuiTextPane* proceed = static_cast(x1c_loadedFrame->FindWidget("textpane_proceed")); + if (proceed) + proceed->TextSupport().SetText(g_MainStringTable->GetString(85)); + x40_tablegroup_popup->SetIsVisible(false); + x40_tablegroup_popup->SetIsActive(false); + x40_tablegroup_popup->SetVertical(false); + CGuiWidget* worker = x40_tablegroup_popup->GetWorkerWidget(2); + worker->SetIsSelectable(false); + worker->SetVisibility(false, ETraversalMode::Children); - x20_tablegroup_fileselect->SetMenuAdvanceCallback( - std::bind(&SNewFileSelectFrame::DoFileMenuAdvance, this, std::placeholders::_1)); - x20_tablegroup_fileselect->SetMenuSelectionChangeCallback( - std::bind(&SNewFileSelectFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - x20_tablegroup_fileselect->SetMenuCancelCallback( - std::bind(&SNewFileSelectFrame::DoFileMenuCancel, this, std::placeholders::_1)); + x20_tablegroup_fileselect->SetMenuAdvanceCallback( + std::bind(&SNewFileSelectFrame::DoFileMenuAdvance, this, std::placeholders::_1)); + x20_tablegroup_fileselect->SetMenuSelectionChangeCallback( + std::bind(&SNewFileSelectFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x20_tablegroup_fileselect->SetMenuCancelCallback( + std::bind(&SNewFileSelectFrame::DoFileMenuCancel, this, std::placeholders::_1)); - x40_tablegroup_popup->SetMenuAdvanceCallback( - std::bind(&SNewFileSelectFrame::DoPopupAdvance, this, std::placeholders::_1)); - x40_tablegroup_popup->SetMenuSelectionChangeCallback( - std::bind(&SNewFileSelectFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - x40_tablegroup_popup->SetMenuCancelCallback( - std::bind(&SNewFileSelectFrame::DoPopupCancel, this, std::placeholders::_1)); + x40_tablegroup_popup->SetMenuAdvanceCallback( + std::bind(&SNewFileSelectFrame::DoPopupAdvance, this, std::placeholders::_1)); + x40_tablegroup_popup->SetMenuSelectionChangeCallback( + std::bind(&SNewFileSelectFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x40_tablegroup_popup->SetMenuCancelCallback( + std::bind(&SNewFileSelectFrame::DoPopupCancel, this, std::placeholders::_1)); - for (int i=0 ; i<3 ; ++i) - x64_fileSelections[i] = FindFileSelectOption(x1c_loadedFrame, i); + for (int i = 0; i < 3; ++i) + x64_fileSelections[i] = FindFileSelectOption(x1c_loadedFrame, i); - x104_rowPitch = (x64_fileSelections[1].x0_base->GetLocalPosition() - - x64_fileSelections[0].x0_base->GetLocalPosition()).z(); + x104_rowPitch = + (x64_fileSelections[1].x0_base->GetLocalPosition() - x64_fileSelections[0].x0_base->GetLocalPosition()).z(); } -bool CFrontEndUI::SNewFileSelectFrame::PumpLoad() -{ - if (x1c_loadedFrame) - return true; - if (x10_frme.IsLoaded()) - { - if (x10_frme->GetIsFinishedLoading()) - { - x1c_loadedFrame = x10_frme.GetObj(); - FinishedLoading(); - return true; - } +bool CFrontEndUI::SNewFileSelectFrame::PumpLoad() { + if (x1c_loadedFrame) + return true; + if (x10_frme.IsLoaded()) { + if (x10_frme->GetIsFinishedLoading()) { + x1c_loadedFrame = x10_frme.GetObj(); + FinishedLoading(); + return true; } + } + return false; +} + +bool CFrontEndUI::SNewFileSelectFrame::IsTextDoneAnimating() const { + if (x64_fileSelections[0].x28_curField != 4) return false; + if (x64_fileSelections[1].x28_curField != 4) + return false; + if (x64_fileSelections[2].x28_curField != 4) + return false; + if (!x28_textpane_erase.x0_panes[0]->GetTextSupport().IsAnimationDone()) + return false; + return x38_textpane_gba.x0_panes[0]->GetTextSupport().IsAnimationDone(); } -bool CFrontEndUI::SNewFileSelectFrame::IsTextDoneAnimating() const -{ - if (x64_fileSelections[0].x28_curField != 4) - return false; - if (x64_fileSelections[1].x28_curField != 4) - return false; - if (x64_fileSelections[2].x28_curField != 4) - return false; - if (!x28_textpane_erase.x0_panes[0]->GetTextSupport().IsAnimationDone()) - return false; - return x38_textpane_gba.x0_panes[0]->GetTextSupport().IsAnimationDone(); -} - -void CFrontEndUI::SNewFileSelectFrame::Update(float dt) -{ - bool saveReady = x4_saveUI->GetUIType() == CSaveGameScreen::EUIType::SaveReady; - if (saveReady != x10c_saveReady) - { - if (saveReady) - { - ClearFrameContents(); - } - else if (x8_subMenu != ESubMenu::Root) - { - ResetFrame(); - DeactivateEraseGamePopup(); - DeactivateNewGamePopup(); - x8_subMenu = ESubMenu::Root; - } - x10c_saveReady = saveReady; +void CFrontEndUI::SNewFileSelectFrame::Update(float dt) { + bool saveReady = x4_saveUI->GetUIType() == CSaveGameScreen::EUIType::SaveReady; + if (saveReady != x10c_saveReady) { + if (saveReady) { + ClearFrameContents(); + } else if (x8_subMenu != ESubMenu::Root) { + ResetFrame(); + DeactivateEraseGamePopup(); + DeactivateNewGamePopup(); + x8_subMenu = ESubMenu::Root; } - if (x10c_saveReady) - SetupFrameContents(); + x10c_saveReady = saveReady; + } + if (x10c_saveReady) + SetupFrameContents(); - x1c_loadedFrame->Update(dt); + x1c_loadedFrame->Update(dt); } CFrontEndUI::SNewFileSelectFrame::EAction -CFrontEndUI::SNewFileSelectFrame::ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction) -{ - xc_action = EAction::None; +CFrontEndUI::SNewFileSelectFrame::ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction) { + xc_action = EAction::None; - if (x8_subMenu != ESubMenu::EraseGamePopup) - x4_saveUI->ProcessUserInput(input); + if (x8_subMenu != ESubMenu::EraseGamePopup) + x4_saveUI->ProcessUserInput(input); - if (IsTextDoneAnimating()) - x108_curTime = std::min(0.5f, x108_curTime + input.DeltaTime()); - - if (x108_curTime < 0.5f) - return xc_action; - - if (x10c_saveReady) - { - x1c_loadedFrame->ProcessUserInput(input); - if (x8_subMenu == ESubMenu::Root || x8_subMenu == ESubMenu::EraseGame) - { - if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::FileSelect) - HandleActiveChange(x20_tablegroup_fileselect); - - if (tbAction >= CFrontEndUITouchBar::EAction::FileA && - tbAction <= CFrontEndUITouchBar::EAction::ImageGallery) - { - x20_tablegroup_fileselect->SetUserSelection(int(tbAction) - int(CFrontEndUITouchBar::EAction::FileA)); - HandleActiveChange(x20_tablegroup_fileselect); - DoFileMenuAdvance(x20_tablegroup_fileselect); - } - else if (tbAction == CFrontEndUITouchBar::EAction::Back) - { - DoFileMenuCancel(x20_tablegroup_fileselect); - } - } - else if (x8_subMenu == ESubMenu::EraseGamePopup) - { - if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::EraseBack) - HandleActiveChange(x40_tablegroup_popup); - - if (tbAction != CFrontEndUITouchBar::EAction::None) - { - if (tbAction == CFrontEndUITouchBar::EAction::Confirm) - x40_tablegroup_popup->SetUserSelection(1); - else - x40_tablegroup_popup->SetUserSelection(0); - HandleActiveChange(x40_tablegroup_popup); - DoPopupAdvance(x40_tablegroup_popup); - } - } - else if (x8_subMenu == ESubMenu::NewGamePopup) - { - if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::StartOptions) - HandleActiveChange(x40_tablegroup_popup); - - if (tbAction == CFrontEndUITouchBar::EAction::Back) - { - DoPopupCancel(x40_tablegroup_popup); - } - else if (tbAction != CFrontEndUITouchBar::EAction::None) - { - if (tbAction == CFrontEndUITouchBar::EAction::Options) - x40_tablegroup_popup->SetUserSelection(1); - else if (tbAction == CFrontEndUITouchBar::EAction::Start || - tbAction == CFrontEndUITouchBar::EAction::Hard) - x40_tablegroup_popup->SetUserSelection(0); - else if (tbAction == CFrontEndUITouchBar::EAction::Normal) - x40_tablegroup_popup->SetUserSelection(2); - HandleActiveChange(x40_tablegroup_popup); - DoPopupAdvance(x40_tablegroup_popup); - } - } - } - - if (x10d_needsEraseToggle) - { - if (x40_tablegroup_popup->GetIsActive()) - DeactivateEraseGamePopup(); - else - ActivateEraseGamePopup(); - x10d_needsEraseToggle = false; - } - - if (x10e_needsNewToggle) - { - if (x40_tablegroup_popup->GetIsActive()) - DeactivateNewGamePopup(); - else - ActivateNewGamePopup(); - x10e_needsNewToggle = false; - } + if (IsTextDoneAnimating()) + x108_curTime = std::min(0.5f, x108_curTime + input.DeltaTime()); + if (x108_curTime < 0.5f) return xc_action; -} -void CFrontEndUI::SNewFileSelectFrame::Draw() const -{ - if (x1c_loadedFrame && x10c_saveReady) - x1c_loadedFrame->Draw(CGuiWidgetDrawParms::Default); -} + if (x10c_saveReady) { + x1c_loadedFrame->ProcessUserInput(input); + if (x8_subMenu == ESubMenu::Root || x8_subMenu == ESubMenu::EraseGame) { + if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::FileSelect) + HandleActiveChange(x20_tablegroup_fileselect); -void CFrontEndUI::SNewFileSelectFrame::HandleActiveChange(CGuiTableGroup* active) -{ - if (!active) - return; + if (tbAction >= CFrontEndUITouchBar::EAction::FileA && tbAction <= CFrontEndUITouchBar::EAction::ImageGallery) { + x20_tablegroup_fileselect->SetUserSelection(int(tbAction) - int(CFrontEndUITouchBar::EAction::FileA)); + HandleActiveChange(x20_tablegroup_fileselect); + DoFileMenuAdvance(x20_tablegroup_fileselect); + } else if (tbAction == CFrontEndUITouchBar::EAction::Back) { + DoFileMenuCancel(x20_tablegroup_fileselect); + } + } else if (x8_subMenu == ESubMenu::EraseGamePopup) { + if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::EraseBack) + HandleActiveChange(x40_tablegroup_popup); - active->SetColors(zeus::CColor::skWhite, - zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); - - if (active == x20_tablegroup_fileselect) - { - x24_model_erase->SetLocalTransform(zeus::CTransform::Translate( - zeus::CVector3f{0.f, 0.f, active->GetUserSelection() * x104_rowPitch} + xf8_model_erase_position)); - - /* Set Touch Bar contents here */ - CFrontEndUITouchBar::SFileSelectDetail tbDetails[3] = {}; - for (int i=0 ; i<3 ; ++i) - { - if (const CGameState::GameFileStateInfo* data = x4_saveUI->GetGameData(i)) - { - tbDetails[i].state = data->x20_hardMode ? CFrontEndUITouchBar::EFileState::Hard : - CFrontEndUITouchBar::EFileState::Normal; - tbDetails[i].percent = data->x18_itemPercent; - } - } - m_touchBar.SetFileSelectPhase(tbDetails, x8_subMenu == ESubMenu::EraseGame, - CSlideShow::SlideShowGalleryFlags()); - } - else if (active == x40_tablegroup_popup) - { - if (x8_subMenu == ESubMenu::EraseGamePopup) - m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::EraseBack); - else if (x8_subMenu == ESubMenu::NewGamePopup) - m_touchBar.SetStartOptionsPhase(g_GameState->SystemOptions().GetPlayerBeatNormalMode()); + if (tbAction != CFrontEndUITouchBar::EAction::None) { + if (tbAction == CFrontEndUITouchBar::EAction::Confirm) + x40_tablegroup_popup->SetUserSelection(1); else - m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::None); + x40_tablegroup_popup->SetUserSelection(0); + HandleActiveChange(x40_tablegroup_popup); + DoPopupAdvance(x40_tablegroup_popup); + } + } else if (x8_subMenu == ESubMenu::NewGamePopup) { + if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::StartOptions) + HandleActiveChange(x40_tablegroup_popup); + + if (tbAction == CFrontEndUITouchBar::EAction::Back) { + DoPopupCancel(x40_tablegroup_popup); + } else if (tbAction != CFrontEndUITouchBar::EAction::None) { + if (tbAction == CFrontEndUITouchBar::EAction::Options) + x40_tablegroup_popup->SetUserSelection(1); + else if (tbAction == CFrontEndUITouchBar::EAction::Start || tbAction == CFrontEndUITouchBar::EAction::Hard) + x40_tablegroup_popup->SetUserSelection(0); + else if (tbAction == CFrontEndUITouchBar::EAction::Normal) + x40_tablegroup_popup->SetUserSelection(2); + HandleActiveChange(x40_tablegroup_popup); + DoPopupAdvance(x40_tablegroup_popup); + } } + } - if (x8_subMenu == ESubMenu::Root || x8_subMenu == ESubMenu::NewGamePopup) - x24_model_erase->SetIsVisible(false); + if (x10d_needsEraseToggle) { + if (x40_tablegroup_popup->GetIsActive()) + DeactivateEraseGamePopup(); else - x24_model_erase->SetIsVisible(true); + ActivateEraseGamePopup(); + x10d_needsEraseToggle = false; + } + + if (x10e_needsNewToggle) { + if (x40_tablegroup_popup->GetIsActive()) + DeactivateNewGamePopup(); + else + ActivateNewGamePopup(); + x10e_needsNewToggle = false; + } + + return xc_action; } -void CFrontEndUI::SNewFileSelectFrame::DeactivateEraseGamePopup() -{ - x40_tablegroup_popup->SetIsActive(false); - x40_tablegroup_popup->SetIsVisible(false); - x20_tablegroup_fileselect->SetIsActive(true); - - HandleActiveChange(x20_tablegroup_fileselect); - - x64_fileSelections[x20_tablegroup_fileselect->GetUserSelection()]. - x0_base->SetColor(zeus::CColor::skWhite); +void CFrontEndUI::SNewFileSelectFrame::Draw() const { + if (x1c_loadedFrame && x10c_saveReady) + x1c_loadedFrame->Draw(CGuiWidgetDrawParms::Default); } -void CFrontEndUI::SNewFileSelectFrame::ActivateEraseGamePopup() -{ - x40_tablegroup_popup->SetIsActive(true); - x40_tablegroup_popup->SetIsVisible(true); - x40_tablegroup_popup->SetLocalTransform( - zeus::CTransform::Translate(0.f, 0.f, x20_tablegroup_fileselect->GetUserSelection() * x104_rowPitch) * - x40_tablegroup_popup->GetTransform()); - x20_tablegroup_fileselect->SetIsActive(false); +void CFrontEndUI::SNewFileSelectFrame::HandleActiveChange(CGuiTableGroup* active) { + if (!active) + return; - x8_subMenu = ESubMenu::EraseGamePopup; - HandleActiveChange(x40_tablegroup_popup); + active->SetColors(zeus::CColor::skWhite, zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); - x48_textpane_popupadvance.SetPairText(g_MainStringTable->GetString(95)); - x50_textpane_popupcancel.SetPairText(g_MainStringTable->GetString(38)); + if (active == x20_tablegroup_fileselect) { + x24_model_erase->SetLocalTransform(zeus::CTransform::Translate( + zeus::CVector3f{0.f, 0.f, active->GetUserSelection() * x104_rowPitch} + xf8_model_erase_position)); - x64_fileSelections[x20_tablegroup_fileselect->GetUserSelection()]. - x0_base->SetColor(zeus::CColor{1.f, 1.f, 1.f, 0.f}); - x44_model_dash7->SetVisibility(false, ETraversalMode::Children); + /* Set Touch Bar contents here */ + CFrontEndUITouchBar::SFileSelectDetail tbDetails[3] = {}; + for (int i = 0; i < 3; ++i) { + if (const CGameState::GameFileStateInfo* data = x4_saveUI->GetGameData(i)) { + tbDetails[i].state = + data->x20_hardMode ? CFrontEndUITouchBar::EFileState::Hard : CFrontEndUITouchBar::EFileState::Normal; + tbDetails[i].percent = data->x18_itemPercent; + } + } + m_touchBar.SetFileSelectPhase(tbDetails, x8_subMenu == ESubMenu::EraseGame, CSlideShow::SlideShowGalleryFlags()); + } else if (active == x40_tablegroup_popup) { + if (x8_subMenu == ESubMenu::EraseGamePopup) + m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::EraseBack); + else if (x8_subMenu == ESubMenu::NewGamePopup) + m_touchBar.SetStartOptionsPhase(g_GameState->SystemOptions().GetPlayerBeatNormalMode()); + else + m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::None); + } + + if (x8_subMenu == ESubMenu::Root || x8_subMenu == ESubMenu::NewGamePopup) + x24_model_erase->SetIsVisible(false); + else + x24_model_erase->SetIsVisible(true); } -void CFrontEndUI::SNewFileSelectFrame::DeactivateNewGamePopup() -{ - x40_tablegroup_popup->SetIsActive(false); - x40_tablegroup_popup->SetIsVisible(false); - x20_tablegroup_fileselect->SetIsActive(true); +void CFrontEndUI::SNewFileSelectFrame::DeactivateEraseGamePopup() { + x40_tablegroup_popup->SetIsActive(false); + x40_tablegroup_popup->SetIsVisible(false); + x20_tablegroup_fileselect->SetIsActive(true); + HandleActiveChange(x20_tablegroup_fileselect); + + x64_fileSelections[x20_tablegroup_fileselect->GetUserSelection()].x0_base->SetColor(zeus::CColor::skWhite); +} + +void CFrontEndUI::SNewFileSelectFrame::ActivateEraseGamePopup() { + x40_tablegroup_popup->SetIsActive(true); + x40_tablegroup_popup->SetIsVisible(true); + x40_tablegroup_popup->SetLocalTransform( + zeus::CTransform::Translate(0.f, 0.f, x20_tablegroup_fileselect->GetUserSelection() * x104_rowPitch) * + x40_tablegroup_popup->GetTransform()); + x20_tablegroup_fileselect->SetIsActive(false); + + x8_subMenu = ESubMenu::EraseGamePopup; + HandleActiveChange(x40_tablegroup_popup); + + x48_textpane_popupadvance.SetPairText(g_MainStringTable->GetString(95)); + x50_textpane_popupcancel.SetPairText(g_MainStringTable->GetString(38)); + + x64_fileSelections[x20_tablegroup_fileselect->GetUserSelection()].x0_base->SetColor(zeus::CColor{1.f, 1.f, 1.f, 0.f}); + x44_model_dash7->SetVisibility(false, ETraversalMode::Children); +} + +void CFrontEndUI::SNewFileSelectFrame::DeactivateNewGamePopup() { + x40_tablegroup_popup->SetIsActive(false); + x40_tablegroup_popup->SetIsVisible(false); + x20_tablegroup_fileselect->SetIsActive(true); + + CGuiWidget* worker = x40_tablegroup_popup->GetWorkerWidget(2); + worker->SetIsSelectable(false); + worker->SetVisibility(false, ETraversalMode::Children); + + x44_model_dash7->SetVisibility(false, ETraversalMode::Children); + + HandleActiveChange(x20_tablegroup_fileselect); + + x64_fileSelections[x20_tablegroup_fileselect->GetUserSelection()].x0_base->SetColor(zeus::CColor::skWhite); + x60_textpane_cancel->TextSupport().SetText(u""); +} + +void CFrontEndUI::SNewFileSelectFrame::ActivateNewGamePopup() { + x40_tablegroup_popup->SetIsActive(true); + x40_tablegroup_popup->SetIsVisible(true); + x40_tablegroup_popup->SetUserSelection(0); + x40_tablegroup_popup->SetLocalTransform( + zeus::CTransform::Translate(0.f, 0.f, x20_tablegroup_fileselect->GetUserSelection() * x104_rowPitch) * + x40_tablegroup_popup->GetTransform()); + x20_tablegroup_fileselect->SetIsActive(false); + + x8_subMenu = ESubMenu::NewGamePopup; + HandleActiveChange(x40_tablegroup_popup); + x64_fileSelections[x20_tablegroup_fileselect->GetUserSelection()].x0_base->SetColor(zeus::CColor{1.f, 1.f, 1.f, 0.f}); + + PlayAdvanceSfx(); + + if (g_GameState->SystemOptions().GetPlayerBeatNormalMode()) { + x48_textpane_popupadvance.SetPairText(g_MainStringTable->GetString(102)); + x50_textpane_popupcancel.SetPairText(g_MainStringTable->GetString(94)); + x58_textpane_popupextra.SetPairText(g_MainStringTable->GetString(101)); CGuiWidget* worker = x40_tablegroup_popup->GetWorkerWidget(2); - worker->SetIsSelectable(false); - worker->SetVisibility(false, ETraversalMode::Children); - + worker->SetIsSelectable(true); + worker->SetVisibility(true, ETraversalMode::Children); + x44_model_dash7->SetVisibility(true, ETraversalMode::Children); + } else { + x48_textpane_popupadvance.SetPairText(g_MainStringTable->GetString(67)); + x50_textpane_popupcancel.SetPairText(g_MainStringTable->GetString(94)); x44_model_dash7->SetVisibility(false, ETraversalMode::Children); - - HandleActiveChange(x20_tablegroup_fileselect); - - x64_fileSelections[x20_tablegroup_fileselect->GetUserSelection()]. - x0_base->SetColor(zeus::CColor::skWhite); - x60_textpane_cancel->TextSupport().SetText(u""); + } + x60_textpane_cancel->TextSupport().SetText(g_MainStringTable->GetString(82)); } -void CFrontEndUI::SNewFileSelectFrame::ActivateNewGamePopup() -{ - x40_tablegroup_popup->SetIsActive(true); - x40_tablegroup_popup->SetIsVisible(true); - x40_tablegroup_popup->SetUserSelection(0); - x40_tablegroup_popup->SetLocalTransform( - zeus::CTransform::Translate(0.f, 0.f, x20_tablegroup_fileselect->GetUserSelection() * x104_rowPitch) * - x40_tablegroup_popup->GetTransform()); - x20_tablegroup_fileselect->SetIsActive(false); +void CFrontEndUI::SNewFileSelectFrame::ResetFrame() { + x8_subMenu = ESubMenu::Root; - x8_subMenu = ESubMenu::NewGamePopup; - HandleActiveChange(x40_tablegroup_popup); - x64_fileSelections[x20_tablegroup_fileselect->GetUserSelection()]. - x0_base->SetColor(zeus::CColor{1.f, 1.f, 1.f, 0.f}); + x38_textpane_gba.x0_panes[0]->SetIsSelectable(true); + x38_textpane_gba.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); - PlayAdvanceSfx(); + x30_textpane_cheats.x0_panes[0]->SetIsSelectable(true); + x30_textpane_cheats.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); - if (g_GameState->SystemOptions().GetPlayerBeatNormalMode()) - { - x48_textpane_popupadvance.SetPairText(g_MainStringTable->GetString(102)); - x50_textpane_popupcancel.SetPairText(g_MainStringTable->GetString(94)); - x58_textpane_popupextra.SetPairText(g_MainStringTable->GetString(101)); - CGuiWidget* worker = x40_tablegroup_popup->GetWorkerWidget(2); - worker->SetIsSelectable(true); - worker->SetVisibility(true, ETraversalMode::Children); - x44_model_dash7->SetVisibility(true, ETraversalMode::Children); + ClearFrameContents(); + + for (int i = 2; i >= 0; --i) + x20_tablegroup_fileselect->GetWorkerWidget(i)->SetIsSelectable(true); + x60_textpane_cancel->TextSupport().SetText(u""); +} + +void CFrontEndUI::SNewFileSelectFrame::ActivateErase() { + x8_subMenu = ESubMenu::EraseGame; + x28_textpane_erase.x0_panes[0]->SetIsSelectable(false); + zeus::CColor color = zeus::CColor::skGrey; + color.a() = 0.5f; + x28_textpane_erase.x0_panes[0]->TextSupport().SetFontColor(color); + x38_textpane_gba.x0_panes[0]->TextSupport().SetFontColor(color); + x30_textpane_cheats.x0_panes[0]->TextSupport().SetFontColor(color); + x38_textpane_gba.x0_panes[0]->SetIsSelectable(false); + x30_textpane_cheats.x0_panes[0]->SetIsSelectable(false); + + for (int i = 2; i >= 0; --i) { + SFileMenuOption& fileOpt = x64_fileSelections[i]; + if (x4_saveUI->GetGameData(i)) { + fileOpt.x0_base->SetIsSelectable(true); + x20_tablegroup_fileselect->SetUserSelection(i); + } else { + fileOpt.x0_base->SetIsSelectable(false); } - else - { - x48_textpane_popupadvance.SetPairText(g_MainStringTable->GetString(67)); - x50_textpane_popupcancel.SetPairText(g_MainStringTable->GetString(94)); - x44_model_dash7->SetVisibility(false, ETraversalMode::Children); - } - x60_textpane_cancel->TextSupport().SetText(g_MainStringTable->GetString(82)); + } + + x60_textpane_cancel->TextSupport().SetText(g_MainStringTable->GetString(82)); + HandleActiveChange(x20_tablegroup_fileselect); } -void CFrontEndUI::SNewFileSelectFrame::ResetFrame() -{ - x8_subMenu = ESubMenu::Root; +void CFrontEndUI::SNewFileSelectFrame::ClearFrameContents() { + x108_curTime = 0.f; + bool hasSave = false; + for (int i = 0; i < 3; ++i) { + if (x4_saveUI->GetGameData(i)) + hasSave = true; + SFileMenuOption& option = x64_fileSelections[i]; + option.x2c_chRate = SFileMenuOption::ComputeRandom(); + option.x28_curField = -1; + for (int j = 0; j < 4; ++j) + option.x4_textpanes[j].SetPairText(u""); + } - x38_textpane_gba.x0_panes[0]->SetIsSelectable(true); - x38_textpane_gba.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); + StartTextAnimating(x28_textpane_erase.x0_panes[0], g_MainStringTable->GetString(38), 60.f); + StartTextAnimating(x38_textpane_gba.x0_panes[0], g_MainStringTable->GetString(37), 60.f); + StartTextAnimating(x30_textpane_cheats.x0_panes[0], g_MainStringTable->GetString(96), 60.f); - x30_textpane_cheats.x0_panes[0]->SetIsSelectable(true); - x30_textpane_cheats.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); + StartTextAnimating(x28_textpane_erase.x0_panes[1], g_MainStringTable->GetString(38), 60.f); + StartTextAnimating(x38_textpane_gba.x0_panes[1], g_MainStringTable->GetString(37), 60.f); + StartTextAnimating(x30_textpane_cheats.x0_panes[1], g_MainStringTable->GetString(96), 60.f); - ClearFrameContents(); - - for (int i=2 ; i>=0 ; --i) - x20_tablegroup_fileselect->GetWorkerWidget(i)->SetIsSelectable(true); - x60_textpane_cancel->TextSupport().SetText(u""); -} - -void CFrontEndUI::SNewFileSelectFrame::ActivateErase() -{ - x8_subMenu = ESubMenu::EraseGame; + if (hasSave) { + x28_textpane_erase.x0_panes[0]->SetIsSelectable(true); + x28_textpane_erase.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); + } else { x28_textpane_erase.x0_panes[0]->SetIsSelectable(false); zeus::CColor color = zeus::CColor::skGrey; color.a() = 0.5f; x28_textpane_erase.x0_panes[0]->TextSupport().SetFontColor(color); - x38_textpane_gba.x0_panes[0]->TextSupport().SetFontColor(color); + } + + x20_tablegroup_fileselect->SetUserSelection(0); + CGuiTextPane* cheats = static_cast(x20_tablegroup_fileselect->GetWorkerWidget(5)); + if (CSlideShow::SlideShowGalleryFlags()) { + cheats->SetIsSelectable(true); + x30_textpane_cheats.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); + } else { + cheats->SetIsSelectable(false); + zeus::CColor color = zeus::CColor::skGrey; + color.a() = 0.5f; x30_textpane_cheats.x0_panes[0]->TextSupport().SetFontColor(color); - x38_textpane_gba.x0_panes[0]->SetIsSelectable(false); - x30_textpane_cheats.x0_panes[0]->SetIsSelectable(false); + } - for (int i=2 ; i>=0 ; --i) - { - SFileMenuOption& fileOpt = x64_fileSelections[i]; - if (x4_saveUI->GetGameData(i)) - { - fileOpt.x0_base->SetIsSelectable(true); - x20_tablegroup_fileselect->SetUserSelection(i); - } - else - { - fileOpt.x0_base->SetIsSelectable(false); - } - } - - x60_textpane_cancel->TextSupport().SetText(g_MainStringTable->GetString(82)); - HandleActiveChange(x20_tablegroup_fileselect); + HandleActiveChange(x20_tablegroup_fileselect); } -void CFrontEndUI::SNewFileSelectFrame::ClearFrameContents() -{ - x108_curTime = 0.f; - bool hasSave = false; - for (int i=0 ; i<3 ; ++i) - { - if (x4_saveUI->GetGameData(i)) - hasSave = true; - SFileMenuOption& option = x64_fileSelections[i]; - option.x2c_chRate = SFileMenuOption::ComputeRandom(); - option.x28_curField = -1; - for (int j=0 ; j<4 ; ++j) - option.x4_textpanes[j].SetPairText(u""); - } +void CFrontEndUI::SNewFileSelectFrame::SetupFrameContents() { + for (int i = 0; i < 3; ++i) { + SFileMenuOption& option = x64_fileSelections[i]; + if (option.x28_curField == 4) + continue; + SGuiTextPair* pair = (option.x28_curField == -1) ? nullptr : &option.x4_textpanes[option.x28_curField]; + if (!pair || pair->x0_panes[0]->GetTextSupport().GetNumCharsPrinted() >= + pair->x0_panes[0]->GetTextSupport().GetNumCharsTotal()) { + if (++option.x28_curField < 4) { + std::u16string str; + SGuiTextPair& populatePair = option.x4_textpanes[option.x28_curField]; + const CGameState::GameFileStateInfo* data = x4_saveUI->GetGameData(i); - StartTextAnimating(x28_textpane_erase.x0_panes[0], g_MainStringTable->GetString(38), 60.f); - StartTextAnimating(x38_textpane_gba.x0_panes[0], g_MainStringTable->GetString(37), 60.f); - StartTextAnimating(x30_textpane_cheats.x0_panes[0], g_MainStringTable->GetString(96), 60.f); + switch (option.x28_curField) { + case 0: + // Completion percent + if (data) { + std::u16string fileStr = g_MainStringTable->GetString(data->x20_hardMode ? 106 : 39); + str = fileStr + hecl::Char16Format(L" %02d%%", data->x18_itemPercent); + break; + } + str = g_MainStringTable->GetString(36); + break; - StartTextAnimating(x28_textpane_erase.x0_panes[1], g_MainStringTable->GetString(38), 60.f); - StartTextAnimating(x38_textpane_gba.x0_panes[1], g_MainStringTable->GetString(37), 60.f); - StartTextAnimating(x30_textpane_cheats.x0_panes[1], g_MainStringTable->GetString(96), 60.f); - - if (hasSave) - { - x28_textpane_erase.x0_panes[0]->SetIsSelectable(true); - x28_textpane_erase.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); - } - else - { - x28_textpane_erase.x0_panes[0]->SetIsSelectable(false); - zeus::CColor color = zeus::CColor::skGrey; - color.a() = 0.5f; - x28_textpane_erase.x0_panes[0]->TextSupport().SetFontColor(color); - } - - x20_tablegroup_fileselect->SetUserSelection(0); - CGuiTextPane* cheats = static_cast(x20_tablegroup_fileselect->GetWorkerWidget(5)); - if (CSlideShow::SlideShowGalleryFlags()) - { - cheats->SetIsSelectable(true); - x30_textpane_cheats.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); - } - else - { - cheats->SetIsSelectable(false); - zeus::CColor color = zeus::CColor::skGrey; - color.a() = 0.5f; - x30_textpane_cheats.x0_panes[0]->TextSupport().SetFontColor(color); - } - - HandleActiveChange(x20_tablegroup_fileselect); -} - -void CFrontEndUI::SNewFileSelectFrame::SetupFrameContents() -{ - for (int i=0 ; i<3 ; ++i) - { - SFileMenuOption& option = x64_fileSelections[i]; - if (option.x28_curField == 4) - continue; - SGuiTextPair* pair = (option.x28_curField == -1) ? nullptr : &option.x4_textpanes[option.x28_curField]; - if (!pair || - pair->x0_panes[0]->GetTextSupport().GetNumCharsPrinted() >= - pair->x0_panes[0]->GetTextSupport().GetNumCharsTotal()) - { - if (++option.x28_curField < 4) - { - std::u16string str; - SGuiTextPair& populatePair = option.x4_textpanes[option.x28_curField]; - const CGameState::GameFileStateInfo* data = x4_saveUI->GetGameData(i); - - switch (option.x28_curField) - { - case 0: - // Completion percent - if (data) - { - std::u16string fileStr = g_MainStringTable->GetString(data->x20_hardMode ? 106 : 39); - str = fileStr + hecl::Char16Format(L" %02d%%", data->x18_itemPercent); - break; - } - str = g_MainStringTable->GetString(36); - break; - - case 1: - // World name - if (data) - { - if (g_MemoryCardSys->HasSaveWorldMemory(data->x8_mlvlId)) - { - const CSaveWorldMemory& wldMem = g_MemoryCardSys->GetSaveWorldMemory(data->x8_mlvlId); - str = wldMem.GetFrontEndName(); - } - break; - } - str = g_MainStringTable->GetString(51); - break; - - case 2: - // Formatted time - if (data) - { - auto pt = std::div(data->x0_playTime, 3600); - str = hecl::Char16Format(L"%02d:%02d", pt.quot, pt.rem / 60); - break; - } - str = g_MainStringTable->GetString(52); - break; - - case 3: - // "Elapsed" - str = g_MainStringTable->GetString(data ? 54 : 53); - break; - - default: break; - } - - StartTextAnimating(populatePair.x0_panes[0], str, option.x2c_chRate); - StartTextAnimating(populatePair.x0_panes[1], str, option.x2c_chRate); + case 1: + // World name + if (data) { + if (g_MemoryCardSys->HasSaveWorldMemory(data->x8_mlvlId)) { + const CSaveWorldMemory& wldMem = g_MemoryCardSys->GetSaveWorldMemory(data->x8_mlvlId); + str = wldMem.GetFrontEndName(); } + break; + } + str = g_MainStringTable->GetString(51); + break; + + case 2: + // Formatted time + if (data) { + auto pt = std::div(data->x0_playTime, 3600); + str = hecl::Char16Format(L"%02d:%02d", pt.quot, pt.rem / 60); + break; + } + str = g_MainStringTable->GetString(52); + break; + + case 3: + // "Elapsed" + str = g_MainStringTable->GetString(data ? 54 : 53); + break; + + default: + break; } + + StartTextAnimating(populatePair.x0_panes[0], str, option.x2c_chRate); + StartTextAnimating(populatePair.x0_panes[1], str, option.x2c_chRate); + } } + } } -void CFrontEndUI::SNewFileSelectFrame::DoPopupCancel(CGuiTableGroup* caller) -{ - if (x8_subMenu == ESubMenu::EraseGamePopup) - { - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x8_subMenu = ESubMenu::EraseGame; - x10d_needsEraseToggle = true; +void CFrontEndUI::SNewFileSelectFrame::DoPopupCancel(CGuiTableGroup* caller) { + if (x8_subMenu == ESubMenu::EraseGamePopup) { + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x8_subMenu = ESubMenu::EraseGame; + x10d_needsEraseToggle = true; + } else { + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x8_subMenu = ESubMenu::Root; + x10e_needsNewToggle = true; + } +} + +void CFrontEndUI::SNewFileSelectFrame::DoPopupAdvance(CGuiTableGroup* caller) { + if (x8_subMenu == ESubMenu::EraseGamePopup) { + if (x40_tablegroup_popup->GetUserSelection() == 1) { + x4_saveUI->EraseGame(x20_tablegroup_fileselect->GetUserSelection()); + ResetFrame(); + } else + x8_subMenu = ESubMenu::EraseGame; + x10d_needsEraseToggle = true; + } else { + if (g_GameState->SystemOptions().GetPlayerBeatNormalMode()) { + if (x40_tablegroup_popup->GetUserSelection() == 1) { + PlayAdvanceSfx(); + xc_action = EAction::GameOptions; + return; + } + g_GameState->SetHardMode(!x40_tablegroup_popup->GetUserSelection()); + x4_saveUI->StartGame(x20_tablegroup_fileselect->GetUserSelection()); + } else { + if (x40_tablegroup_popup->GetUserSelection() == 1) { + PlayAdvanceSfx(); + xc_action = EAction::GameOptions; + return; + } + x4_saveUI->StartGame(x20_tablegroup_fileselect->GetUserSelection()); } - else - { - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x8_subMenu = ESubMenu::Root; + } +} + +void CFrontEndUI::SNewFileSelectFrame::DoFileMenuCancel(CGuiTableGroup* caller) { + if (x8_subMenu == ESubMenu::EraseGame) { + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ResetFrame(); + } +} + +void CFrontEndUI::SNewFileSelectFrame::DoSelectionChange(CGuiTableGroup* caller, int oldSel) { + HandleActiveChange(caller); + CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); +} + +void CFrontEndUI::SNewFileSelectFrame::DoFileMenuAdvance(CGuiTableGroup* caller) { + int userSel = x20_tablegroup_fileselect->GetUserSelection(); + if (userSel < 3) { + if (x8_subMenu == ESubMenu::EraseGame) { + if (x4_saveUI->GetGameData(userSel)) { + PlayAdvanceSfx(); + x10d_needsEraseToggle = true; + } + } else { + if (x4_saveUI->GetGameData(userSel)) { + m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::None); + x4_saveUI->StartGame(userSel); + } else x10e_needsNewToggle = true; } + } else if (userSel == 3) { + PlayAdvanceSfx(); + ActivateErase(); + } else if (userSel == 4) { + xc_action = EAction::FusionBonus; + } else if (userSel == 5) { + xc_action = EAction::SlideShow; + } } -void CFrontEndUI::SNewFileSelectFrame::DoPopupAdvance(CGuiTableGroup* caller) -{ - if (x8_subMenu == ESubMenu::EraseGamePopup) - { - if (x40_tablegroup_popup->GetUserSelection() == 1) - { - x4_saveUI->EraseGame(x20_tablegroup_fileselect->GetUserSelection()); - ResetFrame(); - } - else - x8_subMenu = ESubMenu::EraseGame; - x10d_needsEraseToggle = true; - } - else - { - if (g_GameState->SystemOptions().GetPlayerBeatNormalMode()) - { - if (x40_tablegroup_popup->GetUserSelection() == 1) - { - PlayAdvanceSfx(); - xc_action = EAction::GameOptions; - return; - } - g_GameState->SetHardMode(!x40_tablegroup_popup->GetUserSelection()); - x4_saveUI->StartGame(x20_tablegroup_fileselect->GetUserSelection()); - } - else - { - if (x40_tablegroup_popup->GetUserSelection() == 1) - { - PlayAdvanceSfx(); - xc_action = EAction::GameOptions; - return; - } - x4_saveUI->StartGame(x20_tablegroup_fileselect->GetUserSelection()); - } - } +CFrontEndUI::SFileMenuOption CFrontEndUI::SNewFileSelectFrame::FindFileSelectOption(CGuiFrame* frame, int idx) { + SFileMenuOption ret; + ret.x0_base = frame->FindWidget(hecl::Format("basewidget_file%d", idx).c_str()); + ret.x4_textpanes[0] = FindTextPanePair(frame, hecl::Format("textpane_filename%d", idx).c_str()); + ret.x4_textpanes[1] = FindTextPanePair(frame, hecl::Format("textpane_world%d", idx).c_str()); + ret.x4_textpanes[2] = FindTextPanePair(frame, hecl::Format("textpane_playtime%d", idx).c_str()); + ret.x4_textpanes[3] = FindTextPanePair(frame, hecl::Format("textpane_date%d", idx).c_str()); + return ret; } -void CFrontEndUI::SNewFileSelectFrame::DoFileMenuCancel(CGuiTableGroup* caller) -{ - if (x8_subMenu == ESubMenu::EraseGame) - { - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - ResetFrame(); - } +void CFrontEndUI::SNewFileSelectFrame::StartTextAnimating(CGuiTextPane* text, std::u16string_view str, float chRate) { + text->TextSupport().SetText(str); + text->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, chRate); } -void CFrontEndUI::SNewFileSelectFrame::DoSelectionChange(CGuiTableGroup* caller, int oldSel) -{ - HandleActiveChange(caller); - CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); +CFrontEndUI::SFusionBonusFrame::SFusionBonusFrame(CFrontEndUITouchBar& touchBar) : m_touchBar(touchBar) { + x4_gbaSupport = std::make_unique(); + xc_gbaScreen = g_SimplePool->GetObj("FRME_GBAScreen"); + x18_gbaLink = g_SimplePool->GetObj("FRME_GBALink"); } -void CFrontEndUI::SNewFileSelectFrame::DoFileMenuAdvance(CGuiTableGroup* caller) -{ - int userSel = x20_tablegroup_fileselect->GetUserSelection(); - if (userSel < 3) - { - if (x8_subMenu == ESubMenu::EraseGame) - { - if (x4_saveUI->GetGameData(userSel)) - { - PlayAdvanceSfx(); - x10d_needsEraseToggle = true; - } - } - else - { - if (x4_saveUI->GetGameData(userSel)) - { - m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::None); - x4_saveUI->StartGame(userSel); - } - else - x10e_needsNewToggle = true; - } - } - else if (userSel == 3) - { - PlayAdvanceSfx(); - ActivateErase(); - } - else if (userSel == 4) - { - xc_action = EAction::FusionBonus; - } - else if (userSel == 5) - { - xc_action = EAction::SlideShow; - } +void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::SetUIText(EUIType tp) { + int instructions = -1; + int yes = -1; + int no = -1; + + bool cableVisible = false; + bool circleGcVisible = false; + bool circleGbaVisible = false; + bool circleStartVisible = false; + bool pakoutVisible = false; + bool gbaScreenVisible = false; + bool connectVisible = false; + + switch (tp) { + case EUIType::InsertPak: + instructions = 73; // Insert Game Pak + no = 82; + yes = 83; + pakoutVisible = true; + circleGbaVisible = true; + break; + case EUIType::ConnectSocket: + instructions = 68; // Connect socket + no = 82; + yes = 83; + cableVisible = true; + circleGcVisible = true; + circleGbaVisible = true; + break; + case EUIType::PressStartAndSelect: + instructions = 74; // Hold start and select + no = 82; + yes = 83; + cableVisible = true; + circleStartVisible = true; + gbaScreenVisible = true; + break; + case EUIType::BeginLink: + instructions = 75; // Begin link? + no = 82; + yes = 83; + cableVisible = true; + gbaScreenVisible = true; + break; + case EUIType::TurnOffGBA: + instructions = 76; // Turn off GBA + no = 82; + yes = 83; + cableVisible = true; + gbaScreenVisible = true; + circleStartVisible = true; + break; + case EUIType::Linking: + x4_gbaSupport->StartLink(); + instructions = 72; // Linking + cableVisible = true; + gbaScreenVisible = true; + connectVisible = true; + break; + case EUIType::LinkFailed: + instructions = 69; // Link failed + no = 82; + yes = 83; + cableVisible = true; + circleGcVisible = true; + circleGbaVisible = true; + circleStartVisible = true; + gbaScreenVisible = true; + break; + case EUIType::LinkCompleteOrLinking: + yes = 83; + instructions = x40_linkInProgress + 71; // Complete or linking + cableVisible = true; + gbaScreenVisible = true; + break; + case EUIType::Complete: + case EUIType::Cancelled: + default: + break; + } + + std::u16string instructionsStr; + if (instructions != -1) + instructionsStr = g_MainStringTable->GetString(instructions); + xc_textpane_instructions.SetPairText(instructionsStr); + + std::u16string yesStr; + if (yes != -1) + yesStr = g_MainStringTable->GetString(yes); + x14_textpane_yes->TextSupport().SetText(yesStr); + + std::u16string noStr; + if (no != -1) + noStr = g_MainStringTable->GetString(no); + x18_textpane_no->TextSupport().SetText(noStr); + + x1c_model_gc->SetVisibility(true, ETraversalMode::Children); + x20_model_gba->SetVisibility(true, ETraversalMode::Children); + x24_model_cable->SetVisibility(cableVisible, ETraversalMode::Children); + x28_model_circlegcport->SetVisibility(circleGcVisible, ETraversalMode::Children); + x2c_model_circlegbaport->SetVisibility(circleGbaVisible, ETraversalMode::Children); + x30_model_circlestartselect->SetVisibility(circleStartVisible, ETraversalMode::Children); + x34_model_pakout->SetVisibility(pakoutVisible, ETraversalMode::Children); + x38_model_gbascreen->SetVisibility(gbaScreenVisible, ETraversalMode::Children); + x3c_model_connect->SetVisibility(connectVisible, ETraversalMode::Children); + + x0_uiType = tp; } -CFrontEndUI::SFileMenuOption CFrontEndUI::SNewFileSelectFrame::FindFileSelectOption(CGuiFrame* frame, int idx) -{ - SFileMenuOption ret; - ret.x0_base = frame->FindWidget(hecl::Format("basewidget_file%d", idx).c_str()); - ret.x4_textpanes[0] = FindTextPanePair(frame, hecl::Format("textpane_filename%d", idx).c_str()); - ret.x4_textpanes[1] = FindTextPanePair(frame, hecl::Format("textpane_world%d", idx).c_str()); - ret.x4_textpanes[2] = FindTextPanePair(frame, hecl::Format("textpane_playtime%d", idx).c_str()); - ret.x4_textpanes[3] = FindTextPanePair(frame, hecl::Format("textpane_date%d", idx).c_str()); - return ret; -} - -void CFrontEndUI::SNewFileSelectFrame::StartTextAnimating(CGuiTextPane* text, std::u16string_view str, float chRate) -{ - text->TextSupport().SetText(str); - text->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, chRate); -} - -CFrontEndUI::SFusionBonusFrame::SFusionBonusFrame(CFrontEndUITouchBar& touchBar) -: m_touchBar(touchBar) -{ - x4_gbaSupport = std::make_unique(); - xc_gbaScreen = g_SimplePool->GetObj("FRME_GBAScreen"); - x18_gbaLink = g_SimplePool->GetObj("FRME_GBALink"); -} - -void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::SetUIText(EUIType tp) -{ - int instructions = -1; - int yes = -1; - int no = -1; - - bool cableVisible = false; - bool circleGcVisible = false; - bool circleGbaVisible = false; - bool circleStartVisible = false; - bool pakoutVisible = false; - bool gbaScreenVisible = false; - bool connectVisible = false; - - switch (tp) - { - case EUIType::InsertPak: - instructions = 73; // Insert Game Pak - no = 82; - yes = 83; - pakoutVisible = true; - circleGbaVisible = true; - break; - case EUIType::ConnectSocket: - instructions = 68; // Connect socket - no = 82; - yes = 83; - cableVisible = true; - circleGcVisible = true; - circleGbaVisible = true; - break; - case EUIType::PressStartAndSelect: - instructions = 74; // Hold start and select - no = 82; - yes = 83; - cableVisible = true; - circleStartVisible = true; - gbaScreenVisible = true; - break; - case EUIType::BeginLink: - instructions = 75; // Begin link? - no = 82; - yes = 83; - cableVisible = true; - gbaScreenVisible = true; - break; - case EUIType::TurnOffGBA: - instructions = 76; // Turn off GBA - no = 82; - yes = 83; - cableVisible = true; - gbaScreenVisible = true; - circleStartVisible = true; - break; - case EUIType::Linking: - x4_gbaSupport->StartLink(); - instructions = 72; // Linking - cableVisible = true; - gbaScreenVisible = true; - connectVisible = true; - break; - case EUIType::LinkFailed: - instructions = 69; // Link failed - no = 82; - yes = 83; - cableVisible = true; - circleGcVisible = true; - circleGbaVisible = true; - circleStartVisible = true; - gbaScreenVisible = true; - break; - case EUIType::LinkCompleteOrLinking: - yes = 83; - instructions = x40_linkInProgress + 71; // Complete or linking - cableVisible = true; - gbaScreenVisible = true; - break; - case EUIType::Complete: - case EUIType::Cancelled: - default: - break; - } - - std::u16string instructionsStr; - if (instructions != -1) - instructionsStr = g_MainStringTable->GetString(instructions); - xc_textpane_instructions.SetPairText(instructionsStr); - - std::u16string yesStr; - if (yes != -1) - yesStr = g_MainStringTable->GetString(yes); - x14_textpane_yes->TextSupport().SetText(yesStr); - - std::u16string noStr; - if (no != -1) - noStr = g_MainStringTable->GetString(no); - x18_textpane_no->TextSupport().SetText(noStr); - - x1c_model_gc->SetVisibility(true, ETraversalMode::Children); - x20_model_gba->SetVisibility(true, ETraversalMode::Children); - x24_model_cable->SetVisibility(cableVisible, ETraversalMode::Children); - x28_model_circlegcport->SetVisibility(circleGcVisible, ETraversalMode::Children); - x2c_model_circlegbaport->SetVisibility(circleGbaVisible, ETraversalMode::Children); - x30_model_circlestartselect->SetVisibility(circleStartVisible, ETraversalMode::Children); - x34_model_pakout->SetVisibility(pakoutVisible, ETraversalMode::Children); - x38_model_gbascreen->SetVisibility(gbaScreenVisible, ETraversalMode::Children); - x3c_model_connect->SetVisibility(connectVisible, ETraversalMode::Children); - - x0_uiType = tp; -} - -static const CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType NextLinkUI[] = -{ +static const CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType NextLinkUI[] = { CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::ConnectSocket, CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::PressStartAndSelect, CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::BeginLink, @@ -838,11 +717,9 @@ static const CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType NextLinkUI[] CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Complete, CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::InsertPak, CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Empty, - CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Empty -}; + CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Empty}; -static const CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType PrevLinkUI[] = -{ +static const CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType PrevLinkUI[] = { CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Cancelled, CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Cancelled, CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Cancelled, @@ -852,1956 +729,1654 @@ static const CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType PrevLinkUI[] CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Empty, CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Cancelled, CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Empty, - CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Empty -}; + CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EUIType::Empty}; -CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EAction -CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::ProcessUserInput(const CFinalInput &input, bool linkInProgress, - CFrontEndUITouchBar::EAction tbAction) -{ - if (linkInProgress != x40_linkInProgress) - { - x40_linkInProgress = linkInProgress; - SetUIText(x0_uiType); - } +CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::EAction CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::ProcessUserInput( + const CFinalInput& input, bool linkInProgress, CFrontEndUITouchBar::EAction tbAction) { + if (linkInProgress != x40_linkInProgress) { + x40_linkInProgress = linkInProgress; + SetUIText(x0_uiType); + } - switch (x0_uiType) - { - case EUIType::InsertPak: - case EUIType::ConnectSocket: - case EUIType::PressStartAndSelect: - case EUIType::BeginLink: - case EUIType::LinkFailed: - case EUIType::LinkCompleteOrLinking: - case EUIType::TurnOffGBA: - if (input.PA() || tbAction == CFrontEndUITouchBar::EAction::Confirm) - { - PlayAdvanceSfx(); - SetUIText(NextLinkUI[int(x0_uiType)]); - } - else if (input.PB() || tbAction == CFrontEndUITouchBar::EAction::Back) - { - EUIType prevUi = PrevLinkUI[int(x0_uiType)]; - if (prevUi == EUIType::Empty) - break; - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - SetUIText(prevUi); - } + switch (x0_uiType) { + case EUIType::InsertPak: + case EUIType::ConnectSocket: + case EUIType::PressStartAndSelect: + case EUIType::BeginLink: + case EUIType::LinkFailed: + case EUIType::LinkCompleteOrLinking: + case EUIType::TurnOffGBA: + if (input.PA() || tbAction == CFrontEndUITouchBar::EAction::Confirm) { + PlayAdvanceSfx(); + SetUIText(NextLinkUI[int(x0_uiType)]); + } else if (input.PB() || tbAction == CFrontEndUITouchBar::EAction::Back) { + EUIType prevUi = PrevLinkUI[int(x0_uiType)]; + if (prevUi == EUIType::Empty) break; - case EUIType::Linking: - if (x4_gbaSupport->GetPhase() == CGBASupport::EPhase::Complete) - { - if (x4_gbaSupport->IsFusionLinked()) - g_GameState->SystemOptions().SetPlayerLinkedFusion(true); - if (x4_gbaSupport->IsFusionBeat()) - g_GameState->SystemOptions().SetPlayerBeatFusion(true); - if (x4_gbaSupport->IsFusionLinked()) - { - PlayAdvanceSfx(); - SetUIText(EUIType::LinkCompleteOrLinking); - } - else - { - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - SetUIText(EUIType::LinkFailed); - } - } - else if (x4_gbaSupport->GetPhase() == CGBASupport::EPhase::Failed) - { - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - SetUIText(EUIType::LinkFailed); - } - break; - case EUIType::Complete: - return EAction::Complete; - case EUIType::Cancelled: - return EAction::Cancelled; - default: break; + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + SetUIText(prevUi); } + break; + case EUIType::Linking: + if (x4_gbaSupport->GetPhase() == CGBASupport::EPhase::Complete) { + if (x4_gbaSupport->IsFusionLinked()) + g_GameState->SystemOptions().SetPlayerLinkedFusion(true); + if (x4_gbaSupport->IsFusionBeat()) + g_GameState->SystemOptions().SetPlayerBeatFusion(true); + if (x4_gbaSupport->IsFusionLinked()) { + PlayAdvanceSfx(); + SetUIText(EUIType::LinkCompleteOrLinking); + } else { + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + SetUIText(EUIType::LinkFailed); + } + } else if (x4_gbaSupport->GetPhase() == CGBASupport::EPhase::Failed) { + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + SetUIText(EUIType::LinkFailed); + } + break; + case EUIType::Complete: + return EAction::Complete; + case EUIType::Cancelled: + return EAction::Cancelled; + default: + break; + } - return EAction::None; + return EAction::None; } -void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::Update(float dt) -{ - x4_gbaSupport->Update(dt); - x8_frme->Update(dt); +void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::Update(float dt) { + x4_gbaSupport->Update(dt); + x8_frme->Update(dt); } -void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::FinishedLoading() -{ - x8_frme->SetAspectConstraint(1.78f); +void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::FinishedLoading() { + x8_frme->SetAspectConstraint(1.78f); - xc_textpane_instructions = FindTextPanePair(x8_frme, "textpane_instructions"); - x14_textpane_yes = static_cast(x8_frme->FindWidget("textpane_yes")); - x18_textpane_no = static_cast(x8_frme->FindWidget("textpane_no")); - x1c_model_gc = static_cast(x8_frme->FindWidget("model_gc")); - x20_model_gba = static_cast(x8_frme->FindWidget("model_gba")); - x24_model_cable = static_cast(x8_frme->FindWidget("model_cable")); - x28_model_circlegcport = static_cast(x8_frme->FindWidget("model_circlegcport")); - x2c_model_circlegbaport = static_cast(x8_frme->FindWidget("model_circlegbaport")); - x30_model_circlestartselect = static_cast(x8_frme->FindWidget("model_circlestartselect")); - x34_model_pakout = static_cast(x8_frme->FindWidget("model_pakout")); - x38_model_gbascreen = static_cast(x8_frme->FindWidget("model_gbascreen")); - x3c_model_connect = static_cast(x8_frme->FindWidget("model_connect")); - SetUIText(EUIType::InsertPak); + xc_textpane_instructions = FindTextPanePair(x8_frme, "textpane_instructions"); + x14_textpane_yes = static_cast(x8_frme->FindWidget("textpane_yes")); + x18_textpane_no = static_cast(x8_frme->FindWidget("textpane_no")); + x1c_model_gc = static_cast(x8_frme->FindWidget("model_gc")); + x20_model_gba = static_cast(x8_frme->FindWidget("model_gba")); + x24_model_cable = static_cast(x8_frme->FindWidget("model_cable")); + x28_model_circlegcport = static_cast(x8_frme->FindWidget("model_circlegcport")); + x2c_model_circlegbaport = static_cast(x8_frme->FindWidget("model_circlegbaport")); + x30_model_circlestartselect = static_cast(x8_frme->FindWidget("model_circlestartselect")); + x34_model_pakout = static_cast(x8_frme->FindWidget("model_pakout")); + x38_model_gbascreen = static_cast(x8_frme->FindWidget("model_gbascreen")); + x3c_model_connect = static_cast(x8_frme->FindWidget("model_connect")); + SetUIText(EUIType::InsertPak); } -void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::Draw() -{ - x8_frme->Draw(CGuiWidgetDrawParms::Default); -} +void CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::Draw() { x8_frme->Draw(CGuiWidgetDrawParms::Default); } -CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::SGBALinkFrame(CGuiFrame* linkFrame, - CGBASupport* support, +CFrontEndUI::SFusionBonusFrame::SGBALinkFrame::SGBALinkFrame(CGuiFrame* linkFrame, CGBASupport* support, bool linkInProgress) -: x4_gbaSupport(support), x8_frme(linkFrame), x40_linkInProgress(linkInProgress) -{ - support->InitializeSupport(); - FinishedLoading(); +: x4_gbaSupport(support), x8_frme(linkFrame), x40_linkInProgress(linkInProgress) { + support->InitializeSupport(); + FinishedLoading(); } -void CFrontEndUI::SFusionBonusFrame::FinishedLoading() -{ - x24_loadedFrame->SetAspectConstraint(1.78f); +void CFrontEndUI::SFusionBonusFrame::FinishedLoading() { + x24_loadedFrame->SetAspectConstraint(1.78f); - x28_tablegroup_options = static_cast(x24_loadedFrame->FindWidget("tablegroup_options")); - x2c_tablegroup_fusionsuit = static_cast(x24_loadedFrame->FindWidget("tablegroup_fusionsuit")); - x30_textpane_instructions = FindTextPanePair(x24_loadedFrame, "textpane_instructions"); + x28_tablegroup_options = static_cast(x24_loadedFrame->FindWidget("tablegroup_options")); + x2c_tablegroup_fusionsuit = static_cast(x24_loadedFrame->FindWidget("tablegroup_fusionsuit")); + x30_textpane_instructions = FindTextPanePair(x24_loadedFrame, "textpane_instructions"); - FindAndSetPairText(x24_loadedFrame, "textpane_nes", g_MainStringTable->GetString(66)); - FindAndSetPairText(x24_loadedFrame, "textpane_fusionsuit", g_MainStringTable->GetString(63)); - FindAndSetPairText(x24_loadedFrame, "textpane_fusionsuitno", g_MainStringTable->GetString(65)); - FindAndSetPairText(x24_loadedFrame, "textpane_fusionsuityes", g_MainStringTable->GetString(64)); - FindAndSetPairText(x24_loadedFrame, "textpane_title", g_MainStringTable->GetString(100)); + FindAndSetPairText(x24_loadedFrame, "textpane_nes", g_MainStringTable->GetString(66)); + FindAndSetPairText(x24_loadedFrame, "textpane_fusionsuit", g_MainStringTable->GetString(63)); + FindAndSetPairText(x24_loadedFrame, "textpane_fusionsuitno", g_MainStringTable->GetString(65)); + FindAndSetPairText(x24_loadedFrame, "textpane_fusionsuityes", g_MainStringTable->GetString(64)); + FindAndSetPairText(x24_loadedFrame, "textpane_title", g_MainStringTable->GetString(100)); - static_cast(x24_loadedFrame->FindWidget("textpane_proceed"))-> - TextSupport().SetText(g_MainStringTable->GetString(85)); - static_cast(x24_loadedFrame->FindWidget("textpane_cancel"))-> - TextSupport().SetText(g_MainStringTable->GetString(82)); + static_cast(x24_loadedFrame->FindWidget("textpane_proceed")) + ->TextSupport() + .SetText(g_MainStringTable->GetString(85)); + static_cast(x24_loadedFrame->FindWidget("textpane_cancel")) + ->TextSupport() + .SetText(g_MainStringTable->GetString(82)); - x2c_tablegroup_fusionsuit->SetIsActive(false); - x2c_tablegroup_fusionsuit->SetIsVisible(false); - x2c_tablegroup_fusionsuit->SetVertical(false); - x2c_tablegroup_fusionsuit->SetUserSelection(g_GameState->SystemOptions().GetPlayerFusionSuitActive()); + x2c_tablegroup_fusionsuit->SetIsActive(false); + x2c_tablegroup_fusionsuit->SetIsVisible(false); + x2c_tablegroup_fusionsuit->SetVertical(false); + x2c_tablegroup_fusionsuit->SetUserSelection(g_GameState->SystemOptions().GetPlayerFusionSuitActive()); - SetTableColors(x28_tablegroup_options); - SetTableColors(x2c_tablegroup_fusionsuit); + SetTableColors(x28_tablegroup_options); + SetTableColors(x2c_tablegroup_fusionsuit); - x28_tablegroup_options->SetMenuAdvanceCallback( - std::bind(&SFusionBonusFrame::DoAdvance, this, std::placeholders::_1)); - x28_tablegroup_options->SetMenuSelectionChangeCallback( - std::bind(&SFusionBonusFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - x28_tablegroup_options->SetMenuCancelCallback( - std::bind(&SFusionBonusFrame::DoCancel, this, std::placeholders::_1)); - x2c_tablegroup_fusionsuit->SetMenuSelectionChangeCallback( - std::bind(&SFusionBonusFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x28_tablegroup_options->SetMenuAdvanceCallback(std::bind(&SFusionBonusFrame::DoAdvance, this, std::placeholders::_1)); + x28_tablegroup_options->SetMenuSelectionChangeCallback( + std::bind(&SFusionBonusFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x28_tablegroup_options->SetMenuCancelCallback(std::bind(&SFusionBonusFrame::DoCancel, this, std::placeholders::_1)); + x2c_tablegroup_fusionsuit->SetMenuSelectionChangeCallback( + std::bind(&SFusionBonusFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); } -bool CFrontEndUI::SFusionBonusFrame::PumpLoad() -{ - if (x24_loadedFrame) - return true; - if (!xc_gbaScreen.IsLoaded()) - return false; - if (!x18_gbaLink.IsLoaded()) - return false; - if (!x4_gbaSupport->IsReady()) - return false; - if (!xc_gbaScreen->GetIsFinishedLoading()) - return false; - x24_loadedFrame = xc_gbaScreen.GetObj(); - FinishedLoading(); +bool CFrontEndUI::SFusionBonusFrame::PumpLoad() { + if (x24_loadedFrame) return true; -} - -void CFrontEndUI::SFusionBonusFrame::SetTableColors(CGuiTableGroup* tbgp) const -{ - tbgp->SetColors(zeus::CColor::skWhite, - zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); -} - -void CFrontEndUI::SFusionBonusFrame::Update(float dt, CSaveGameScreen* saveUI) -{ - bool doDraw = !saveUI || saveUI->GetUIType() == CSaveGameScreen::EUIType::SaveReady; - - if (doDraw != x38_lastDoDraw) - { - x38_lastDoDraw = doDraw; - ResetCompletionFlags(); - } - - if (x0_gbaLinkFrame) - x0_gbaLinkFrame->Update(dt); - else if (x24_loadedFrame) - x24_loadedFrame->Update(dt); - - bool showFusionSuit = (g_GameState->SystemOptions().GetPlayerLinkedFusion() && - g_GameState->SystemOptions().GetPlayerBeatNormalMode()) || m_gbaOverride; - bool showFusionSuitProceed = showFusionSuit && x28_tablegroup_options->GetUserSelection() == 1; - x2c_tablegroup_fusionsuit->SetIsActive(showFusionSuitProceed); - x2c_tablegroup_fusionsuit->SetIsVisible(showFusionSuitProceed); - x24_loadedFrame->FindWidget("textpane_proceed")->SetIsVisible(showFusionSuitProceed); - - std::u16string instructionStr; - x30_textpane_instructions.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); - if (x28_tablegroup_options->GetUserSelection() == 1) - { - /* Fusion Suit */ - if (x3a_mpNotComplete) - instructionStr = g_MainStringTable->GetString(80); // MP not complete - else if (!showFusionSuit) - instructionStr = g_MainStringTable->GetString(78); // To enable fusion suit - } - else - { - /* NES Metroid */ - if (x39_fusionNotComplete) - instructionStr = g_MainStringTable->GetString(79); // You have not completed fusion - else if (!g_GameState->SystemOptions().GetPlayerBeatFusion()) - instructionStr = g_MainStringTable->GetString(77); // To play NES Metroid - } - - x30_textpane_instructions.SetPairText(instructionStr); -} - -CFrontEndUI::SFusionBonusFrame::EAction -CFrontEndUI::SFusionBonusFrame::ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui, - CFrontEndUITouchBar::EAction tbAction) -{ - x8_action = EAction::None; - - if (sui) - sui->ProcessUserInput(input); - - if (x38_lastDoDraw) - { - if (x0_gbaLinkFrame) - { - if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::ProceedBack) - m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::ProceedBack); - - SGBALinkFrame::EAction action = x0_gbaLinkFrame->ProcessUserInput(input, sui, tbAction); - if (action != SGBALinkFrame::EAction::None) - { - x0_gbaLinkFrame.reset(); - if (action == SGBALinkFrame::EAction::Complete) - { - if (x28_tablegroup_options->GetUserSelection() == 0 && - !g_GameState->SystemOptions().GetPlayerBeatFusion()) - x39_fusionNotComplete = true; - else if (sui) - sui->SaveNESState(); - } - } - } - else if (x24_loadedFrame) - { - CFinalInput useInput = input; - if (input.PZ()) - { - useInput.x2d_b28_PA = true; - m_gbaOverride = true; - } - - bool showFusionSuit = (g_GameState->SystemOptions().GetPlayerLinkedFusion() && - g_GameState->SystemOptions().GetPlayerBeatNormalMode()) || m_gbaOverride; - if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::FusionBonus) - { - m_touchBar.SetFusionBonusPhase(showFusionSuit && - g_GameState->SystemOptions().GetPlayerFusionSuitActive()); - } - - x24_loadedFrame->ProcessUserInput(useInput); - - switch (tbAction) - { - case CFrontEndUITouchBar::EAction::NESMetroid: - x28_tablegroup_options->SetUserSelection(0); - ResetCompletionFlags(); - SetTableColors(x28_tablegroup_options); - DoAdvance(x28_tablegroup_options); - break; - case CFrontEndUITouchBar::EAction::FusionSuit: - x28_tablegroup_options->SetUserSelection(1); - ResetCompletionFlags(); - SetTableColors(x28_tablegroup_options); - if (showFusionSuit) - { - if (x2c_tablegroup_fusionsuit->GetUserSelection() == 1) - { - x2c_tablegroup_fusionsuit->SetUserSelection(0); - DoSelectionChange(x2c_tablegroup_fusionsuit, 0); - } - else - { - x2c_tablegroup_fusionsuit->SetUserSelection(1); - DoSelectionChange(x2c_tablegroup_fusionsuit, 1); - } - } - else - { - DoAdvance(x28_tablegroup_options); - } - break; - case CFrontEndUITouchBar::EAction::Back: - DoCancel(x28_tablegroup_options); - break; - default: break; - } - } - } - - return x8_action; -} - -void CFrontEndUI::SFusionBonusFrame::Draw() const -{ - if (!x38_lastDoDraw) - return; - if (x0_gbaLinkFrame) - x0_gbaLinkFrame->Draw(); - else if (x24_loadedFrame) - x24_loadedFrame->Draw(CGuiWidgetDrawParms::Default); -} - -void CFrontEndUI::SFusionBonusFrame::DoCancel(CGuiTableGroup* caller) -{ - x8_action = EAction::GoBack; - x28_tablegroup_options->SetUserSelection(0); - x2c_tablegroup_fusionsuit->SetIsActive(false); - x30_textpane_instructions.SetPairText(u""); - SetTableColors(x28_tablegroup_options); -} - -void CFrontEndUI::SFusionBonusFrame::DoSelectionChange(CGuiTableGroup* caller, int oldSel) -{ - if (caller == x28_tablegroup_options) - { - CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - ResetCompletionFlags(); - } - else - { - CSfxManager::SfxStart(SFXfnt_enum_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - bool fusionActive = x2c_tablegroup_fusionsuit->GetUserSelection() == 1; - g_GameState->SystemOptions().SetPlayerFusionSuitActive(fusionActive); - g_GameState->GetPlayerState()->SetIsFusionEnabled(fusionActive); - m_touchBar.SetFusionBonusPhase(g_GameState->SystemOptions().GetPlayerFusionSuitActive()); - } - SetTableColors(caller); -} - -void CFrontEndUI::SFusionBonusFrame::DoAdvance(CGuiTableGroup* caller) -{ - switch (x28_tablegroup_options->GetUserSelection()) - { - case 1: - /* Fusion Suit */ - if (x3a_mpNotComplete || m_gbaOverride) - { - x3a_mpNotComplete = false; - PlayAdvanceSfx(); - } - else if (g_GameState->SystemOptions().GetPlayerBeatNormalMode()) - { - if (g_GameState->SystemOptions().GetPlayerLinkedFusion()) - return; - x0_gbaLinkFrame = std::make_unique(x18_gbaLink.GetObj(), x4_gbaSupport.get(), false); - PlayAdvanceSfx(); - } - else - { - x3a_mpNotComplete = true; - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - break; - case 0: - /* NES Metroid */ - if (x39_fusionNotComplete && !m_gbaOverride) - { - x39_fusionNotComplete = false; - PlayAdvanceSfx(); - } - else if (g_GameState->SystemOptions().GetPlayerBeatFusion() || m_gbaOverride) - { - //x8_action = EAction::None; - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x8_action = EAction::PlayNESMetroid; - } - else - { - x0_gbaLinkFrame = std::make_unique(x18_gbaLink.GetObj(), x4_gbaSupport.get(), false); - PlayAdvanceSfx(); - } - break; - default: break; - } -} - -void CFrontEndUI::SGuiTextPair::SetPairText(std::u16string_view str) -{ - x0_panes[0]->TextSupport().SetText(str); - x0_panes[1]->TextSupport().SetText(str); -} - -CFrontEndUI::SGuiTextPair CFrontEndUI::FindTextPanePair(CGuiFrame* frame, const char* name) -{ - SGuiTextPair ret; - ret.x0_panes[0] = static_cast(frame->FindWidget(name)); - ret.x0_panes[1] = static_cast(frame->FindWidget(hecl::Format("%sb", name).c_str())); - return ret; -} - -void CFrontEndUI::FindAndSetPairText(CGuiFrame* frame, const char* name, std::u16string_view str) -{ - CGuiTextPane* w1 = static_cast(frame->FindWidget(name)); - w1->TextSupport().SetText(str); - CGuiTextPane* w2 = static_cast(frame->FindWidget(hecl::Format("%sb", name).c_str())); - w2->TextSupport().SetText(str); -} - -void CFrontEndUI::SFrontEndFrame::FinishedLoading() -{ - x14_loadedFrme->SetAspectConstraint(1.78f); - - x18_tablegroup_mainmenu = static_cast(x14_loadedFrme->FindWidget("tablegroup_mainmenu")); - x1c_gbaPair = FindTextPanePair(x14_loadedFrme, "textpane_gba"); - x1c_gbaPair.SetPairText(g_MainStringTable->GetString(37)); - x24_cheatPair = FindTextPanePair(x14_loadedFrme, "textpane_cheats"); - x24_cheatPair.SetPairText(g_MainStringTable->GetString(96)); - - FindAndSetPairText(x14_loadedFrme, "textpane_start", g_MainStringTable->GetString(67)); - FindAndSetPairText(x14_loadedFrme, "textpane_options", g_MainStringTable->GetString(94)); - FindAndSetPairText(x14_loadedFrme, "textpane_title", g_MainStringTable->GetString(98)); - - CGuiTextPane* proceed = static_cast(x14_loadedFrme->FindWidget("textpane_proceed")); - if (proceed) - proceed->TextSupport().SetText(g_MainStringTable->GetString(85)); - - x18_tablegroup_mainmenu->SetMenuAdvanceCallback( - std::bind(&SFrontEndFrame::DoAdvance, this, std::placeholders::_1)); - x18_tablegroup_mainmenu->SetMenuSelectionChangeCallback( - std::bind(&SFrontEndFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - x18_tablegroup_mainmenu->SetMenuCancelCallback( - std::bind(&SFrontEndFrame::DoCancel, this, std::placeholders::_1)); - - HandleActiveChange(x18_tablegroup_mainmenu); -} - -bool CFrontEndUI::SFrontEndFrame::PumpLoad() -{ - if (x14_loadedFrme) - return true; - if (x8_frme.IsLoaded()) - { - if (CGuiFrame* frme = x8_frme.GetObj()) - { - if (frme->GetIsFinishedLoading()) - { - x14_loadedFrme = frme; - FinishedLoading(); - return true; - } - } - } + if (!xc_gbaScreen.IsLoaded()) return false; + if (!x18_gbaLink.IsLoaded()) + return false; + if (!x4_gbaSupport->IsReady()) + return false; + if (!xc_gbaScreen->GetIsFinishedLoading()) + return false; + x24_loadedFrame = xc_gbaScreen.GetObj(); + FinishedLoading(); + return true; } -void CFrontEndUI::SFrontEndFrame::Update(float dt) -{ - CGuiTextPane* imageGallery = - static_cast(x18_tablegroup_mainmenu->GetWorkerWidget(3)); +void CFrontEndUI::SFusionBonusFrame::SetTableColors(CGuiTableGroup* tbgp) const { + tbgp->SetColors(zeus::CColor::skWhite, zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); +} - if (CSlideShow::SlideShowGalleryFlags()) - { - imageGallery->SetIsSelectable(true); - x24_cheatPair.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); - } - else - { - imageGallery->SetIsSelectable(false); - zeus::CColor color = zeus::CColor::skGrey; - color.a() = 0.5f; - x24_cheatPair.x0_panes[0]->TextSupport().SetFontColor(color); - } +void CFrontEndUI::SFusionBonusFrame::Update(float dt, CSaveGameScreen* saveUI) { + bool doDraw = !saveUI || saveUI->GetUIType() == CSaveGameScreen::EUIType::SaveReady; - x14_loadedFrme->Update(dt); + if (doDraw != x38_lastDoDraw) { + x38_lastDoDraw = doDraw; + ResetCompletionFlags(); + } + + if (x0_gbaLinkFrame) + x0_gbaLinkFrame->Update(dt); + else if (x24_loadedFrame) + x24_loadedFrame->Update(dt); + + bool showFusionSuit = (g_GameState->SystemOptions().GetPlayerLinkedFusion() && + g_GameState->SystemOptions().GetPlayerBeatNormalMode()) || + m_gbaOverride; + bool showFusionSuitProceed = showFusionSuit && x28_tablegroup_options->GetUserSelection() == 1; + x2c_tablegroup_fusionsuit->SetIsActive(showFusionSuitProceed); + x2c_tablegroup_fusionsuit->SetIsVisible(showFusionSuitProceed); + x24_loadedFrame->FindWidget("textpane_proceed")->SetIsVisible(showFusionSuitProceed); + + std::u16string instructionStr; + x30_textpane_instructions.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); + if (x28_tablegroup_options->GetUserSelection() == 1) { + /* Fusion Suit */ + if (x3a_mpNotComplete) + instructionStr = g_MainStringTable->GetString(80); // MP not complete + else if (!showFusionSuit) + instructionStr = g_MainStringTable->GetString(78); // To enable fusion suit + } else { + /* NES Metroid */ + if (x39_fusionNotComplete) + instructionStr = g_MainStringTable->GetString(79); // You have not completed fusion + else if (!g_GameState->SystemOptions().GetPlayerBeatFusion()) + instructionStr = g_MainStringTable->GetString(77); // To play NES Metroid + } + + x30_textpane_instructions.SetPairText(instructionStr); +} + +CFrontEndUI::SFusionBonusFrame::EAction CFrontEndUI::SFusionBonusFrame::ProcessUserInput( + const CFinalInput& input, CSaveGameScreen* sui, CFrontEndUITouchBar::EAction tbAction) { + x8_action = EAction::None; + + if (sui) + sui->ProcessUserInput(input); + + if (x38_lastDoDraw) { + if (x0_gbaLinkFrame) { + if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::ProceedBack) + m_touchBar.SetPhase(CFrontEndUITouchBar::EPhase::ProceedBack); + + SGBALinkFrame::EAction action = x0_gbaLinkFrame->ProcessUserInput(input, sui, tbAction); + if (action != SGBALinkFrame::EAction::None) { + x0_gbaLinkFrame.reset(); + if (action == SGBALinkFrame::EAction::Complete) { + if (x28_tablegroup_options->GetUserSelection() == 0 && !g_GameState->SystemOptions().GetPlayerBeatFusion()) + x39_fusionNotComplete = true; + else if (sui) + sui->SaveNESState(); + } + } + } else if (x24_loadedFrame) { + CFinalInput useInput = input; + if (input.PZ()) { + useInput.x2d_b28_PA = true; + m_gbaOverride = true; + } + + bool showFusionSuit = (g_GameState->SystemOptions().GetPlayerLinkedFusion() && + g_GameState->SystemOptions().GetPlayerBeatNormalMode()) || + m_gbaOverride; + if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::FusionBonus) { + m_touchBar.SetFusionBonusPhase(showFusionSuit && g_GameState->SystemOptions().GetPlayerFusionSuitActive()); + } + + x24_loadedFrame->ProcessUserInput(useInput); + + switch (tbAction) { + case CFrontEndUITouchBar::EAction::NESMetroid: + x28_tablegroup_options->SetUserSelection(0); + ResetCompletionFlags(); + SetTableColors(x28_tablegroup_options); + DoAdvance(x28_tablegroup_options); + break; + case CFrontEndUITouchBar::EAction::FusionSuit: + x28_tablegroup_options->SetUserSelection(1); + ResetCompletionFlags(); + SetTableColors(x28_tablegroup_options); + if (showFusionSuit) { + if (x2c_tablegroup_fusionsuit->GetUserSelection() == 1) { + x2c_tablegroup_fusionsuit->SetUserSelection(0); + DoSelectionChange(x2c_tablegroup_fusionsuit, 0); + } else { + x2c_tablegroup_fusionsuit->SetUserSelection(1); + DoSelectionChange(x2c_tablegroup_fusionsuit, 1); + } + } else { + DoAdvance(x28_tablegroup_options); + } + break; + case CFrontEndUITouchBar::EAction::Back: + DoCancel(x28_tablegroup_options); + break; + default: + break; + } + } + } + + return x8_action; +} + +void CFrontEndUI::SFusionBonusFrame::Draw() const { + if (!x38_lastDoDraw) + return; + if (x0_gbaLinkFrame) + x0_gbaLinkFrame->Draw(); + else if (x24_loadedFrame) + x24_loadedFrame->Draw(CGuiWidgetDrawParms::Default); +} + +void CFrontEndUI::SFusionBonusFrame::DoCancel(CGuiTableGroup* caller) { + x8_action = EAction::GoBack; + x28_tablegroup_options->SetUserSelection(0); + x2c_tablegroup_fusionsuit->SetIsActive(false); + x30_textpane_instructions.SetPairText(u""); + SetTableColors(x28_tablegroup_options); +} + +void CFrontEndUI::SFusionBonusFrame::DoSelectionChange(CGuiTableGroup* caller, int oldSel) { + if (caller == x28_tablegroup_options) { + CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ResetCompletionFlags(); + } else { + CSfxManager::SfxStart(SFXfnt_enum_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + bool fusionActive = x2c_tablegroup_fusionsuit->GetUserSelection() == 1; + g_GameState->SystemOptions().SetPlayerFusionSuitActive(fusionActive); + g_GameState->GetPlayerState()->SetIsFusionEnabled(fusionActive); + m_touchBar.SetFusionBonusPhase(g_GameState->SystemOptions().GetPlayerFusionSuitActive()); + } + SetTableColors(caller); +} + +void CFrontEndUI::SFusionBonusFrame::DoAdvance(CGuiTableGroup* caller) { + switch (x28_tablegroup_options->GetUserSelection()) { + case 1: + /* Fusion Suit */ + if (x3a_mpNotComplete || m_gbaOverride) { + x3a_mpNotComplete = false; + PlayAdvanceSfx(); + } else if (g_GameState->SystemOptions().GetPlayerBeatNormalMode()) { + if (g_GameState->SystemOptions().GetPlayerLinkedFusion()) + return; + x0_gbaLinkFrame = std::make_unique(x18_gbaLink.GetObj(), x4_gbaSupport.get(), false); + PlayAdvanceSfx(); + } else { + x3a_mpNotComplete = true; + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + break; + case 0: + /* NES Metroid */ + if (x39_fusionNotComplete && !m_gbaOverride) { + x39_fusionNotComplete = false; + PlayAdvanceSfx(); + } else if (g_GameState->SystemOptions().GetPlayerBeatFusion() || m_gbaOverride) { + // x8_action = EAction::None; + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x8_action = EAction::PlayNESMetroid; + } else { + x0_gbaLinkFrame = std::make_unique(x18_gbaLink.GetObj(), x4_gbaSupport.get(), false); + PlayAdvanceSfx(); + } + break; + default: + break; + } +} + +void CFrontEndUI::SGuiTextPair::SetPairText(std::u16string_view str) { + x0_panes[0]->TextSupport().SetText(str); + x0_panes[1]->TextSupport().SetText(str); +} + +CFrontEndUI::SGuiTextPair CFrontEndUI::FindTextPanePair(CGuiFrame* frame, const char* name) { + SGuiTextPair ret; + ret.x0_panes[0] = static_cast(frame->FindWidget(name)); + ret.x0_panes[1] = static_cast(frame->FindWidget(hecl::Format("%sb", name).c_str())); + return ret; +} + +void CFrontEndUI::FindAndSetPairText(CGuiFrame* frame, const char* name, std::u16string_view str) { + CGuiTextPane* w1 = static_cast(frame->FindWidget(name)); + w1->TextSupport().SetText(str); + CGuiTextPane* w2 = static_cast(frame->FindWidget(hecl::Format("%sb", name).c_str())); + w2->TextSupport().SetText(str); +} + +void CFrontEndUI::SFrontEndFrame::FinishedLoading() { + x14_loadedFrme->SetAspectConstraint(1.78f); + + x18_tablegroup_mainmenu = static_cast(x14_loadedFrme->FindWidget("tablegroup_mainmenu")); + x1c_gbaPair = FindTextPanePair(x14_loadedFrme, "textpane_gba"); + x1c_gbaPair.SetPairText(g_MainStringTable->GetString(37)); + x24_cheatPair = FindTextPanePair(x14_loadedFrme, "textpane_cheats"); + x24_cheatPair.SetPairText(g_MainStringTable->GetString(96)); + + FindAndSetPairText(x14_loadedFrme, "textpane_start", g_MainStringTable->GetString(67)); + FindAndSetPairText(x14_loadedFrme, "textpane_options", g_MainStringTable->GetString(94)); + FindAndSetPairText(x14_loadedFrme, "textpane_title", g_MainStringTable->GetString(98)); + + CGuiTextPane* proceed = static_cast(x14_loadedFrme->FindWidget("textpane_proceed")); + if (proceed) + proceed->TextSupport().SetText(g_MainStringTable->GetString(85)); + + x18_tablegroup_mainmenu->SetMenuAdvanceCallback(std::bind(&SFrontEndFrame::DoAdvance, this, std::placeholders::_1)); + x18_tablegroup_mainmenu->SetMenuSelectionChangeCallback( + std::bind(&SFrontEndFrame::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x18_tablegroup_mainmenu->SetMenuCancelCallback(std::bind(&SFrontEndFrame::DoCancel, this, std::placeholders::_1)); + + HandleActiveChange(x18_tablegroup_mainmenu); +} + +bool CFrontEndUI::SFrontEndFrame::PumpLoad() { + if (x14_loadedFrme) + return true; + if (x8_frme.IsLoaded()) { + if (CGuiFrame* frme = x8_frme.GetObj()) { + if (frme->GetIsFinishedLoading()) { + x14_loadedFrme = frme; + FinishedLoading(); + return true; + } + } + } + return false; +} + +void CFrontEndUI::SFrontEndFrame::Update(float dt) { + CGuiTextPane* imageGallery = static_cast(x18_tablegroup_mainmenu->GetWorkerWidget(3)); + + if (CSlideShow::SlideShowGalleryFlags()) { + imageGallery->SetIsSelectable(true); + x24_cheatPair.x0_panes[0]->TextSupport().SetFontColor(zeus::CColor::skWhite); + } else { + imageGallery->SetIsSelectable(false); + zeus::CColor color = zeus::CColor::skGrey; + color.a() = 0.5f; + x24_cheatPair.x0_panes[0]->TextSupport().SetFontColor(color); + } + + x14_loadedFrme->Update(dt); } CFrontEndUI::SFrontEndFrame::EAction -CFrontEndUI::SFrontEndFrame::ProcessUserInput(const CFinalInput& input, - CFrontEndUITouchBar::EAction tbAction) -{ - if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::NoCardSelect) - m_touchBar.SetNoCardSelectPhase(CSlideShow::SlideShowGalleryFlags()); +CFrontEndUI::SFrontEndFrame::ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction) { + if (m_touchBar.GetPhase() != CFrontEndUITouchBar::EPhase::NoCardSelect) + m_touchBar.SetNoCardSelectPhase(CSlideShow::SlideShowGalleryFlags()); - x4_action = EAction::None; - x14_loadedFrme->ProcessUserInput(input); + x4_action = EAction::None; + x14_loadedFrme->ProcessUserInput(input); - switch (tbAction) - { - case CFrontEndUITouchBar::EAction::Start: - x18_tablegroup_mainmenu->SetUserSelection(0); - HandleActiveChange(x18_tablegroup_mainmenu); - DoAdvance(x18_tablegroup_mainmenu); - break; - case CFrontEndUITouchBar::EAction::FusionBonus: - x18_tablegroup_mainmenu->SetUserSelection(1); - HandleActiveChange(x18_tablegroup_mainmenu); - DoAdvance(x18_tablegroup_mainmenu); - break; - case CFrontEndUITouchBar::EAction::Options: - x18_tablegroup_mainmenu->SetUserSelection(2); - HandleActiveChange(x18_tablegroup_mainmenu); - DoAdvance(x18_tablegroup_mainmenu); - break; - case CFrontEndUITouchBar::EAction::ImageGallery: - x18_tablegroup_mainmenu->SetUserSelection(3); - HandleActiveChange(x18_tablegroup_mainmenu); - DoAdvance(x18_tablegroup_mainmenu); - break; - default: break; - } + switch (tbAction) { + case CFrontEndUITouchBar::EAction::Start: + x18_tablegroup_mainmenu->SetUserSelection(0); + HandleActiveChange(x18_tablegroup_mainmenu); + DoAdvance(x18_tablegroup_mainmenu); + break; + case CFrontEndUITouchBar::EAction::FusionBonus: + x18_tablegroup_mainmenu->SetUserSelection(1); + HandleActiveChange(x18_tablegroup_mainmenu); + DoAdvance(x18_tablegroup_mainmenu); + break; + case CFrontEndUITouchBar::EAction::Options: + x18_tablegroup_mainmenu->SetUserSelection(2); + HandleActiveChange(x18_tablegroup_mainmenu); + DoAdvance(x18_tablegroup_mainmenu); + break; + case CFrontEndUITouchBar::EAction::ImageGallery: + x18_tablegroup_mainmenu->SetUserSelection(3); + HandleActiveChange(x18_tablegroup_mainmenu); + DoAdvance(x18_tablegroup_mainmenu); + break; + default: + break; + } - return x4_action; + return x4_action; } -void CFrontEndUI::SFrontEndFrame::Draw() const -{ - x14_loadedFrme->Draw(CGuiWidgetDrawParms::Default); +void CFrontEndUI::SFrontEndFrame::Draw() const { x14_loadedFrme->Draw(CGuiWidgetDrawParms::Default); } + +void CFrontEndUI::SFrontEndFrame::HandleActiveChange(CGuiTableGroup* active) { + active->SetColors(zeus::CColor::skWhite, zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); } -void CFrontEndUI::SFrontEndFrame::HandleActiveChange(CGuiTableGroup* active) -{ - active->SetColors(zeus::CColor::skWhite, - zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); +void CFrontEndUI::SFrontEndFrame::DoCancel(CGuiTableGroup* caller) { /* Intentionally empty */ } + +void CFrontEndUI::SFrontEndFrame::DoSelectionChange(CGuiTableGroup* caller, int oldSel) { + CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + HandleActiveChange(caller); } -void CFrontEndUI::SFrontEndFrame::DoCancel(CGuiTableGroup* caller) -{ - /* Intentionally empty */ -} - -void CFrontEndUI::SFrontEndFrame::DoSelectionChange(CGuiTableGroup* caller, int oldSel) -{ - CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - HandleActiveChange(caller); -} - -void CFrontEndUI::SFrontEndFrame::DoAdvance(CGuiTableGroup* caller) -{ - switch (x18_tablegroup_mainmenu->GetUserSelection()) - { - case 0: - CSfxManager::SfxStart(FETransitionForwardSFX[x0_rnd][0], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - CSfxManager::SfxStart(FETransitionForwardSFX[x0_rnd][1], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x4_action = EAction::StartGame; - break; - case 1: - x4_action = EAction::FusionBonus; - break; - case 2: - PlayAdvanceSfx(); - x4_action = EAction::GameOptions; - break; - case 3: - PlayAdvanceSfx(); - x4_action = EAction::SlideShow; - break; - default: break; - } +void CFrontEndUI::SFrontEndFrame::DoAdvance(CGuiTableGroup* caller) { + switch (x18_tablegroup_mainmenu->GetUserSelection()) { + case 0: + CSfxManager::SfxStart(FETransitionForwardSFX[x0_rnd][0], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(FETransitionForwardSFX[x0_rnd][1], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x4_action = EAction::StartGame; + break; + case 1: + x4_action = EAction::FusionBonus; + break; + case 2: + PlayAdvanceSfx(); + x4_action = EAction::GameOptions; + break; + case 3: + PlayAdvanceSfx(); + x4_action = EAction::SlideShow; + break; + default: + break; + } } CFrontEndUI::SFrontEndFrame::SFrontEndFrame(u32 rnd, CFrontEndUITouchBar& touchBar) -: x0_rnd(rnd), m_touchBar(touchBar) -{ - x8_frme = g_SimplePool->GetObj("FRME_FrontEndPL"); +: x0_rnd(rnd), m_touchBar(touchBar) { + x8_frme = g_SimplePool->GetObj("FRME_FrontEndPL"); } -CFrontEndUI::SNesEmulatorFrame::SNesEmulatorFrame() -{ - x4_nesEmu = std::make_unique(); +CFrontEndUI::SNesEmulatorFrame::SNesEmulatorFrame() { + x4_nesEmu = std::make_unique(); - const SObjectTag* deface = g_ResFactory->GetResourceIdByName("FONT_Deface14B"); - CGuiTextProperties props(false, true, EJustification::Left, - EVerticalJustification::Center); - xc_textSupport = std::make_unique(deface->id, props, zeus::CColor::skWhite, - zeus::CColor::skBlack, zeus::CColor::skWhite, - 0, 0, g_SimplePool, CGuiWidget::EGuiModelDrawFlags::Alpha); - xc_textSupport->SetText(g_MainStringTable->GetString(103)); + const SObjectTag* deface = g_ResFactory->GetResourceIdByName("FONT_Deface14B"); + CGuiTextProperties props(false, true, EJustification::Left, EVerticalJustification::Center); + xc_textSupport = std::make_unique(deface->id, props, zeus::CColor::skWhite, zeus::CColor::skBlack, + zeus::CColor::skWhite, 0, 0, g_SimplePool, + CGuiWidget::EGuiModelDrawFlags::Alpha); + xc_textSupport->SetText(g_MainStringTable->GetString(103)); + xc_textSupport->AutoSetExtent(); + xc_textSupport->ClearRenderBuffer(); +} + +void CFrontEndUI::SNesEmulatorFrame::SetMode(EMode mode) { + switch (mode) { + case EMode::Emulator: + x8_quitScreen.reset(); + break; + case EMode::SaveProgress: + x8_quitScreen = std::make_unique(EQuitType::SaveProgress); + break; + case EMode::ContinuePlaying: + x8_quitScreen = std::make_unique(EQuitType::ContinuePlaying); + break; + case EMode::QuitNESMetroid: + x8_quitScreen = std::make_unique(EQuitType::QuitNESMetroid); + break; + default: + break; + } + x0_mode = mode; +} + +void CFrontEndUI::SNesEmulatorFrame::ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui) { + bool processInput = true; + if (sui && sui->GetUIType() != CSaveGameScreen::EUIType::SaveReady) + processInput = false; + if (sui) + sui->ProcessUserInput(input); + if (!processInput) + return; + + switch (x0_mode) { + case EMode::Emulator: + x4_nesEmu->ProcessUserInput(input, 4); + if (input.ControllerIdx() == 0 && input.PL()) + SetMode(EMode::QuitNESMetroid); + break; + case EMode::SaveProgress: + case EMode::ContinuePlaying: + case EMode::QuitNESMetroid: + x8_quitScreen->ProcessUserInput(input); + break; + default: + break; + } +} + +bool CFrontEndUI::SNesEmulatorFrame::Update(float dt, CSaveGameScreen* saveUi) { + bool doUpdate = (saveUi && saveUi->GetUIType() != CSaveGameScreen::EUIType::SaveReady) ? false : true; + x10_remTime = std::max(x10_remTime - dt, 0.f); + + zeus::CColor geomCol(zeus::CColor::skWhite); + geomCol.a() = std::min(x10_remTime, 1.f); + xc_textSupport->SetGeometryColor(geomCol); + if (xc_textSupport->GetIsTextSupportFinishedLoading()) { xc_textSupport->AutoSetExtent(); xc_textSupport->ClearRenderBuffer(); -} - -void CFrontEndUI::SNesEmulatorFrame::SetMode(EMode mode) -{ - switch (mode) - { - case EMode::Emulator: - x8_quitScreen.reset(); - break; - case EMode::SaveProgress: - x8_quitScreen = std::make_unique(EQuitType::SaveProgress); - break; - case EMode::ContinuePlaying: - x8_quitScreen = std::make_unique(EQuitType::ContinuePlaying); - break; - case EMode::QuitNESMetroid: - x8_quitScreen = std::make_unique(EQuitType::QuitNESMetroid); - break; - default: break; - } - x0_mode = mode; -} - -void CFrontEndUI::SNesEmulatorFrame::ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui) -{ - bool processInput = true; - if (sui && sui->GetUIType() != CSaveGameScreen::EUIType::SaveReady) - processInput = false; - if (sui) - sui->ProcessUserInput(input); - if (!processInput) - return; - - switch (x0_mode) - { - case EMode::Emulator: - x4_nesEmu->ProcessUserInput(input, 4); - if (input.ControllerIdx() == 0 && input.PL()) - SetMode(EMode::QuitNESMetroid); - break; - case EMode::SaveProgress: - case EMode::ContinuePlaying: - case EMode::QuitNESMetroid: - x8_quitScreen->ProcessUserInput(input); - break; - default: break; - } -} - -bool CFrontEndUI::SNesEmulatorFrame::Update(float dt, CSaveGameScreen* saveUi) -{ - bool doUpdate = (saveUi && saveUi->GetUIType() != CSaveGameScreen::EUIType::SaveReady) ? false : true; - x10_remTime = std::max(x10_remTime - dt, 0.f); - - zeus::CColor geomCol(zeus::CColor::skWhite); - geomCol.a() = std::min(x10_remTime, 1.f); - xc_textSupport->SetGeometryColor(geomCol); - if (xc_textSupport->GetIsTextSupportFinishedLoading()) - { - xc_textSupport->AutoSetExtent(); - xc_textSupport->ClearRenderBuffer(); - } - - if (!doUpdate) - return false; - - switch (x0_mode) - { - case EMode::Emulator: - { - x4_nesEmu->Update(); - if (!x4_nesEmu->IsGameOver()) - x14_emulationSuspended = false; - if (x4_nesEmu->IsGameOver() && !x14_emulationSuspended) - { - x14_emulationSuspended = true; - if (saveUi && !saveUi->IsSavingDisabled()) - { - SetMode(EMode::SaveProgress); - break; - } - SetMode(EMode::ContinuePlaying); - break; - } - if (x4_nesEmu->GetPasswordEntryState() == CNESEmulator::EPasswordEntryState::NotEntered && saveUi) - x4_nesEmu->LoadPassword(g_GameState->SystemOptions().GetNESState()); - break; - } - - case EMode::SaveProgress: - { - if (saveUi) - { - EQuitAction action = x8_quitScreen->Update(dt); - if (action == EQuitAction::Yes) - { - memmove(g_GameState->SystemOptions().GetNESState(), x4_nesEmu->GetPassword(), 18); - saveUi->SaveNESState(); - SetMode(EMode::ContinuePlaying); - } - else if (action == EQuitAction::No) - SetMode(EMode::ContinuePlaying); - } - else - SetMode(EMode::ContinuePlaying); - break; - } - - case EMode::ContinuePlaying: - { - EQuitAction action = x8_quitScreen->Update(dt); - if (action == EQuitAction::Yes) - SetMode(EMode::Emulator); - else if (action == EQuitAction::No) - return true; - break; - } - - case EMode::QuitNESMetroid: - { - EQuitAction action = x8_quitScreen->Update(dt); - if (action == EQuitAction::Yes) - return true; - else if (action == EQuitAction::No) - SetMode(EMode::Emulator); - break; - } - - default: break; - } + } + if (!doUpdate) return false; -} -void CFrontEndUI::SNesEmulatorFrame::Draw(CSaveGameScreen* saveUi) const -{ - zeus::CColor mulColor = zeus::CColor::skWhite; - bool blackout = saveUi && saveUi->GetUIType() != CSaveGameScreen::EUIType::SaveReady; - - if (blackout) - mulColor = zeus::CColor::skBlack; - else if (x8_quitScreen) - mulColor = zeus::CColor{0.376470f, 0.376470f, 0.376470f, 1.f}; - - x4_nesEmu->Draw(mulColor, x15_enableFiltering); - if (!blackout && x8_quitScreen) - x8_quitScreen->Draw(); - - if (x10_remTime >= 7.5f) - return; - if (x10_remTime <= 0.f) - return; - if (xc_textSupport->GetIsTextSupportFinishedLoading()) - { - float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height) / 1.33f; - CGraphics::SetOrtho(-320.f * aspect, 320.f * aspect, 240.f, -240.f, -4096.f, 4096.f); - CGraphics::SetViewPointMatrix(zeus::CTransform::Identity()); - CGraphics::SetModelMatrix(zeus::CTransform::Translate(-220.f, 0.f, -200.f)); - xc_textSupport->Render(); + switch (x0_mode) { + case EMode::Emulator: { + x4_nesEmu->Update(); + if (!x4_nesEmu->IsGameOver()) + x14_emulationSuspended = false; + if (x4_nesEmu->IsGameOver() && !x14_emulationSuspended) { + x14_emulationSuspended = true; + if (saveUi && !saveUi->IsSavingDisabled()) { + SetMode(EMode::SaveProgress); + break; + } + SetMode(EMode::ContinuePlaying); + break; } + if (x4_nesEmu->GetPasswordEntryState() == CNESEmulator::EPasswordEntryState::NotEntered && saveUi) + x4_nesEmu->LoadPassword(g_GameState->SystemOptions().GetNESState()); + break; + } + + case EMode::SaveProgress: { + if (saveUi) { + EQuitAction action = x8_quitScreen->Update(dt); + if (action == EQuitAction::Yes) { + memmove(g_GameState->SystemOptions().GetNESState(), x4_nesEmu->GetPassword(), 18); + saveUi->SaveNESState(); + SetMode(EMode::ContinuePlaying); + } else if (action == EQuitAction::No) + SetMode(EMode::ContinuePlaying); + } else + SetMode(EMode::ContinuePlaying); + break; + } + + case EMode::ContinuePlaying: { + EQuitAction action = x8_quitScreen->Update(dt); + if (action == EQuitAction::Yes) + SetMode(EMode::Emulator); + else if (action == EQuitAction::No) + return true; + break; + } + + case EMode::QuitNESMetroid: { + EQuitAction action = x8_quitScreen->Update(dt); + if (action == EQuitAction::Yes) + return true; + else if (action == EQuitAction::No) + SetMode(EMode::Emulator); + break; + } + + default: + break; + } + + return false; } -CFrontEndUI::SOptionsFrontEndFrame::SOptionsFrontEndFrame() -{ - x4_frme = g_SimplePool->GetObj("FRME_OptionsFrontEnd"); - x10_pauseScreen = g_SimplePool->GetObj("STRG_PauseScreen"); - x134_24_visible = true; +void CFrontEndUI::SNesEmulatorFrame::Draw(CSaveGameScreen* saveUi) const { + zeus::CColor mulColor = zeus::CColor::skWhite; + bool blackout = saveUi && saveUi->GetUIType() != CSaveGameScreen::EUIType::SaveReady; + + if (blackout) + mulColor = zeus::CColor::skBlack; + else if (x8_quitScreen) + mulColor = zeus::CColor{0.376470f, 0.376470f, 0.376470f, 1.f}; + + x4_nesEmu->Draw(mulColor, x15_enableFiltering); + if (!blackout && x8_quitScreen) + x8_quitScreen->Draw(); + + if (x10_remTime >= 7.5f) + return; + if (x10_remTime <= 0.f) + return; + if (xc_textSupport->GetIsTextSupportFinishedLoading()) { + float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height) / 1.33f; + CGraphics::SetOrtho(-320.f * aspect, 320.f * aspect, 240.f, -240.f, -4096.f, 4096.f); + CGraphics::SetViewPointMatrix(zeus::CTransform::Identity()); + CGraphics::SetModelMatrix(zeus::CTransform::Translate(-220.f, 0.f, -200.f)); + xc_textSupport->Render(); + } } -void CFrontEndUI::SOptionsFrontEndFrame::DoSliderChange(CGuiSliderGroup* caller, float value) -{ - if (x28_tablegroup_rightmenu->GetIsActive()) - { - int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); - int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); - const auto& optionCategory = GameOptionsRegistry[leftSel]; - const SGameOption& option = optionCategory.second[rightSel]; - CGameOptions::SetOption(option.option, caller->GetGurVal()); - m_touchBarValueDirty = true; - } +CFrontEndUI::SOptionsFrontEndFrame::SOptionsFrontEndFrame() { + x4_frme = g_SimplePool->GetObj("FRME_OptionsFrontEnd"); + x10_pauseScreen = g_SimplePool->GetObj("STRG_PauseScreen"); + x134_24_visible = true; } -void CFrontEndUI::SOptionsFrontEndFrame::DoMenuCancel(CGuiTableGroup* caller) -{ - if (x28_tablegroup_rightmenu == caller) - { - DeactivateRightMenu(); - x24_tablegroup_leftmenu->SetIsActive(true); - x28_tablegroup_rightmenu->SetIsActive(false); - x28_tablegroup_rightmenu->SetUserSelection(0); - SetTableColors(x28_tablegroup_rightmenu); - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } -} - -void CFrontEndUI::SOptionsFrontEndFrame::DoMenuSelectionChange(CGuiTableGroup* caller, int oldSel) -{ - SetTableColors(caller); - if (x24_tablegroup_leftmenu == caller) - { - SetRightUIText(); - CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - else if (x28_tablegroup_rightmenu == caller) - { - HandleRightSelectionChange(); - CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - else if (x2c_tablegroup_double == caller || x30_tablegroup_triple == caller) - { - if (x28_tablegroup_rightmenu->GetIsActive()) - { - int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); - int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); - const auto& optionCategory = GameOptionsRegistry[leftSel]; - const SGameOption& option = optionCategory.second[rightSel]; - CGameOptions::SetOption(option.option, caller->GetUserSelection()); - m_touchBarValueDirty = true; - CSfxManager::SfxStart(SFXfnt_enum_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - - if (option.option == EGameOption::Rumble && caller->GetUserSelection() > 0) - { - x40_rumbleGen.HardStopAll(); - x40_rumbleGen.Rumble(RumbleFxTable[int(ERumbleFxId::PlayerBump)], 1.f, - ERumblePriority::One, EIOPort::Zero); - } - } - } -} - -void CFrontEndUI::SOptionsFrontEndFrame::DoLeftMenuAdvance(CGuiTableGroup* caller) -{ - if (caller == x24_tablegroup_leftmenu) - { - HandleRightSelectionChange(); - x28_tablegroup_rightmenu->SetUserSelection(0); - x24_tablegroup_leftmenu->SetIsActive(false); - x28_tablegroup_rightmenu->SetIsActive(true); - CSfxManager::SfxStart(SFXfnt_advance_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - CSfxManager::SfxStart(SFXfnt_advance_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } -} - -void CFrontEndUI::SOptionsFrontEndFrame::DeactivateRightMenu() -{ - x2c_tablegroup_double->SetIsActive(false); - x30_tablegroup_triple->SetIsActive(false); - x34_slidergroup_slider->SetIsActive(false); - x2c_tablegroup_double->SetVisibility(false, ETraversalMode::Children); - x30_tablegroup_triple->SetVisibility(false, ETraversalMode::Children); - x34_slidergroup_slider->SetVisibility(false, ETraversalMode::Children); -} - -void CFrontEndUI::SOptionsFrontEndFrame::HandleRightSelectionChange() -{ - DeactivateRightMenu(); +void CFrontEndUI::SOptionsFrontEndFrame::DoSliderChange(CGuiSliderGroup* caller, float value) { + if (x28_tablegroup_rightmenu->GetIsActive()) { int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); const auto& optionCategory = GameOptionsRegistry[leftSel]; const SGameOption& option = optionCategory.second[rightSel]; - - switch (option.type) - { - case EOptionType::Float: - x34_slidergroup_slider->SetIsActive(true); - x34_slidergroup_slider->SetVisibility(true, ETraversalMode::Children); - x34_slidergroup_slider->SetMinVal(option.minVal); - x34_slidergroup_slider->SetMaxVal(option.maxVal); - x34_slidergroup_slider->SetIncrement(option.increment); - x34_slidergroup_slider->SetCurVal(CGameOptions::GetOption(option.option)); - x34_slidergroup_slider->SetLocalTransform( - zeus::CTransform::Translate(0.f, 0.f, rightSel * x38_rowPitch) * - x34_slidergroup_slider->GetTransform()); - break; - - case EOptionType::DoubleEnum: - x2c_tablegroup_double->SetUserSelection(CGameOptions::GetOption(option.option)); - x2c_tablegroup_double->SetIsVisible(true); - x2c_tablegroup_double->SetIsActive(true); - x2c_tablegroup_double->SetLocalTransform( - zeus::CTransform::Translate(0.f, 0.f, rightSel * x38_rowPitch) * - x2c_tablegroup_double->GetTransform()); - SetTableColors(x2c_tablegroup_double); - break; - - case EOptionType::TripleEnum: - x30_tablegroup_triple->SetUserSelection(CGameOptions::GetOption(option.option)); - x30_tablegroup_triple->SetIsVisible(true); - x30_tablegroup_triple->SetIsActive(true); - x30_tablegroup_triple->SetLocalTransform( - zeus::CTransform::Translate(0.f, 0.f, rightSel * x38_rowPitch) * - x30_tablegroup_triple->GetTransform()); - SetTableColors(x30_tablegroup_triple); - break; - - default: break; - } + CGameOptions::SetOption(option.option, caller->GetGurVal()); + m_touchBarValueDirty = true; + } } -void CFrontEndUI::SOptionsFrontEndFrame::SetRightUIText() -{ - int userSel = x24_tablegroup_leftmenu->GetUserSelection(); - const std::pair& options = GameOptionsRegistry[userSel]; - - for (int i=0 ; i<5 ; ++i) - { - char name[36]; - snprintf(name, 36, "textpane_right%d", i); - if (i < options.first) - { - FindTextPanePair(x1c_loadedFrame, name).SetPairText( - x20_loadedPauseStrg->GetString(options.second[i].stringId)); - x28_tablegroup_rightmenu->GetWorkerWidget(i)->SetIsSelectable(true); - } - else - { - FindTextPanePair(x1c_loadedFrame, name).SetPairText(u""); - x28_tablegroup_rightmenu->GetWorkerWidget(i)->SetIsSelectable(false); - } - } -} - -void CFrontEndUI::SOptionsFrontEndFrame::SetTableColors(CGuiTableGroup* tbgp) const -{ - tbgp->SetColors(zeus::CColor::skWhite, - zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); -} - -void CFrontEndUI::SOptionsFrontEndFrame::FinishedLoading() -{ - x1c_loadedFrame->SetAspectConstraint(1.78f); - - x24_tablegroup_leftmenu = static_cast(x1c_loadedFrame->FindWidget("tablegroup_leftmenu")); - x28_tablegroup_rightmenu = static_cast(x1c_loadedFrame->FindWidget("tablegroup_rightmenu")); - x2c_tablegroup_double = static_cast(x1c_loadedFrame->FindWidget("tablegroup_double")); - x30_tablegroup_triple = static_cast(x1c_loadedFrame->FindWidget("tablegroup_triple")); - x34_slidergroup_slider = static_cast(x1c_loadedFrame->FindWidget("slidergroup_slider")); - - x24_tablegroup_leftmenu->SetMenuAdvanceCallback( - std::bind(&SOptionsFrontEndFrame::DoLeftMenuAdvance, this, std::placeholders::_1)); - x24_tablegroup_leftmenu->SetMenuSelectionChangeCallback( - std::bind(&SOptionsFrontEndFrame::DoMenuSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - - x38_rowPitch = x24_tablegroup_leftmenu->GetWorkerWidget(1)->GetIdlePosition().z() - - x24_tablegroup_leftmenu->GetWorkerWidget(0)->GetIdlePosition().z(); - - x28_tablegroup_rightmenu->SetMenuSelectionChangeCallback( - std::bind(&SOptionsFrontEndFrame::DoMenuSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - x28_tablegroup_rightmenu->SetMenuCancelCallback( - std::bind(&SOptionsFrontEndFrame::DoMenuCancel, this, std::placeholders::_1)); - - x2c_tablegroup_double->SetMenuSelectionChangeCallback( - std::bind(&SOptionsFrontEndFrame::DoMenuSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - x2c_tablegroup_double->SetMenuCancelCallback( - std::bind(&SOptionsFrontEndFrame::DoMenuCancel, this, std::placeholders::_1)); - - x30_tablegroup_triple->SetMenuSelectionChangeCallback( - std::bind(&SOptionsFrontEndFrame::DoMenuSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - x30_tablegroup_triple->SetMenuCancelCallback( - std::bind(&SOptionsFrontEndFrame::DoMenuCancel, this, std::placeholders::_1)); - - x34_slidergroup_slider->SetSelectionChangedCallback( - std::bind(&SOptionsFrontEndFrame::DoSliderChange, this, std::placeholders::_1, std::placeholders::_2)); - - FindTextPanePair(x1c_loadedFrame, "textpane_double0").SetPairText(x20_loadedPauseStrg->GetString(95)); // Off - FindTextPanePair(x1c_loadedFrame, "textpane_double1").SetPairText(x20_loadedPauseStrg->GetString(94)); // On - FindTextPanePair(x1c_loadedFrame, "textpane_triple0").SetPairText(x20_loadedPauseStrg->GetString(96)); // Mono - FindTextPanePair(x1c_loadedFrame, "textpane_triple1").SetPairText(x20_loadedPauseStrg->GetString(97)); // Stereo - FindTextPanePair(x1c_loadedFrame, "textpane_triple2").SetPairText(x20_loadedPauseStrg->GetString(98)); // Dolby - - FindTextPanePair(x1c_loadedFrame, "textpane_title").SetPairText(g_MainStringTable->GetString(99)); // OPTIONS - - if (CGuiTextPane* proceed = static_cast(x1c_loadedFrame->FindWidget("textpane_proceed"))) - proceed->TextSupport().SetText(g_MainStringTable->GetString(85)); - - if (CGuiTextPane* cancel = static_cast(x1c_loadedFrame->FindWidget("textpane_cancel"))) - cancel->TextSupport().SetText(g_MainStringTable->GetString(82)); - - // Visor, Display, Sound, Controller - for (int i=0 ; i<4 ;++i) - { - char name[36]; - snprintf(name, 36, "textpane_filename%d", i); - FindTextPanePair(x1c_loadedFrame, name).SetPairText(x20_loadedPauseStrg->GetString(16+i)); - } - - x2c_tablegroup_double->SetVertical(false); - x30_tablegroup_triple->SetVertical(false); - +void CFrontEndUI::SOptionsFrontEndFrame::DoMenuCancel(CGuiTableGroup* caller) { + if (x28_tablegroup_rightmenu == caller) { + DeactivateRightMenu(); x24_tablegroup_leftmenu->SetIsActive(true); x28_tablegroup_rightmenu->SetIsActive(false); - - SetTableColors(x24_tablegroup_leftmenu); + x28_tablegroup_rightmenu->SetUserSelection(0); SetTableColors(x28_tablegroup_rightmenu); - SetTableColors(x2c_tablegroup_double); - SetTableColors(x30_tablegroup_triple); + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } +} +void CFrontEndUI::SOptionsFrontEndFrame::DoMenuSelectionChange(CGuiTableGroup* caller, int oldSel) { + SetTableColors(caller); + if (x24_tablegroup_leftmenu == caller) { SetRightUIText(); - DeactivateRightMenu(); + CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else if (x28_tablegroup_rightmenu == caller) { + HandleRightSelectionChange(); + CSfxManager::SfxStart(SFXfnt_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else if (x2c_tablegroup_double == caller || x30_tablegroup_triple == caller) { + if (x28_tablegroup_rightmenu->GetIsActive()) { + int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); + int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); + const auto& optionCategory = GameOptionsRegistry[leftSel]; + const SGameOption& option = optionCategory.second[rightSel]; + CGameOptions::SetOption(option.option, caller->GetUserSelection()); + m_touchBarValueDirty = true; + CSfxManager::SfxStart(SFXfnt_enum_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + + if (option.option == EGameOption::Rumble && caller->GetUserSelection() > 0) { + x40_rumbleGen.HardStopAll(); + x40_rumbleGen.Rumble(RumbleFxTable[int(ERumbleFxId::PlayerBump)], 1.f, ERumblePriority::One, EIOPort::Zero); + } + } + } } -bool CFrontEndUI::SOptionsFrontEndFrame::PumpLoad() -{ - if (x1c_loadedFrame) - return true; - if (!x4_frme.IsLoaded()) - return false; - if (!x10_pauseScreen.IsLoaded()) - return false; - if (!x4_frme->GetIsFinishedLoading()) - return false; - x1c_loadedFrame = x4_frme.GetObj(); - x20_loadedPauseStrg = x10_pauseScreen.GetObj(); - m_touchBar = NewGameOptionsTouchBar(); - FinishedLoading(); +void CFrontEndUI::SOptionsFrontEndFrame::DoLeftMenuAdvance(CGuiTableGroup* caller) { + if (caller == x24_tablegroup_leftmenu) { + HandleRightSelectionChange(); + x28_tablegroup_rightmenu->SetUserSelection(0); + x24_tablegroup_leftmenu->SetIsActive(false); + x28_tablegroup_rightmenu->SetIsActive(true); + CSfxManager::SfxStart(SFXfnt_advance_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(SFXfnt_advance_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } +} + +void CFrontEndUI::SOptionsFrontEndFrame::DeactivateRightMenu() { + x2c_tablegroup_double->SetIsActive(false); + x30_tablegroup_triple->SetIsActive(false); + x34_slidergroup_slider->SetIsActive(false); + x2c_tablegroup_double->SetVisibility(false, ETraversalMode::Children); + x30_tablegroup_triple->SetVisibility(false, ETraversalMode::Children); + x34_slidergroup_slider->SetVisibility(false, ETraversalMode::Children); +} + +void CFrontEndUI::SOptionsFrontEndFrame::HandleRightSelectionChange() { + DeactivateRightMenu(); + int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); + int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); + const auto& optionCategory = GameOptionsRegistry[leftSel]; + const SGameOption& option = optionCategory.second[rightSel]; + + switch (option.type) { + case EOptionType::Float: + x34_slidergroup_slider->SetIsActive(true); + x34_slidergroup_slider->SetVisibility(true, ETraversalMode::Children); + x34_slidergroup_slider->SetMinVal(option.minVal); + x34_slidergroup_slider->SetMaxVal(option.maxVal); + x34_slidergroup_slider->SetIncrement(option.increment); + x34_slidergroup_slider->SetCurVal(CGameOptions::GetOption(option.option)); + x34_slidergroup_slider->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, rightSel * x38_rowPitch) * + x34_slidergroup_slider->GetTransform()); + break; + + case EOptionType::DoubleEnum: + x2c_tablegroup_double->SetUserSelection(CGameOptions::GetOption(option.option)); + x2c_tablegroup_double->SetIsVisible(true); + x2c_tablegroup_double->SetIsActive(true); + x2c_tablegroup_double->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, rightSel * x38_rowPitch) * + x2c_tablegroup_double->GetTransform()); + SetTableColors(x2c_tablegroup_double); + break; + + case EOptionType::TripleEnum: + x30_tablegroup_triple->SetUserSelection(CGameOptions::GetOption(option.option)); + x30_tablegroup_triple->SetIsVisible(true); + x30_tablegroup_triple->SetIsActive(true); + x30_tablegroup_triple->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, rightSel * x38_rowPitch) * + x30_tablegroup_triple->GetTransform()); + SetTableColors(x30_tablegroup_triple); + break; + + default: + break; + } +} + +void CFrontEndUI::SOptionsFrontEndFrame::SetRightUIText() { + int userSel = x24_tablegroup_leftmenu->GetUserSelection(); + const std::pair& options = GameOptionsRegistry[userSel]; + + for (int i = 0; i < 5; ++i) { + char name[36]; + snprintf(name, 36, "textpane_right%d", i); + if (i < options.first) { + FindTextPanePair(x1c_loadedFrame, name).SetPairText(x20_loadedPauseStrg->GetString(options.second[i].stringId)); + x28_tablegroup_rightmenu->GetWorkerWidget(i)->SetIsSelectable(true); + } else { + FindTextPanePair(x1c_loadedFrame, name).SetPairText(u""); + x28_tablegroup_rightmenu->GetWorkerWidget(i)->SetIsSelectable(false); + } + } +} + +void CFrontEndUI::SOptionsFrontEndFrame::SetTableColors(CGuiTableGroup* tbgp) const { + tbgp->SetColors(zeus::CColor::skWhite, zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); +} + +void CFrontEndUI::SOptionsFrontEndFrame::FinishedLoading() { + x1c_loadedFrame->SetAspectConstraint(1.78f); + + x24_tablegroup_leftmenu = static_cast(x1c_loadedFrame->FindWidget("tablegroup_leftmenu")); + x28_tablegroup_rightmenu = static_cast(x1c_loadedFrame->FindWidget("tablegroup_rightmenu")); + x2c_tablegroup_double = static_cast(x1c_loadedFrame->FindWidget("tablegroup_double")); + x30_tablegroup_triple = static_cast(x1c_loadedFrame->FindWidget("tablegroup_triple")); + x34_slidergroup_slider = static_cast(x1c_loadedFrame->FindWidget("slidergroup_slider")); + + x24_tablegroup_leftmenu->SetMenuAdvanceCallback( + std::bind(&SOptionsFrontEndFrame::DoLeftMenuAdvance, this, std::placeholders::_1)); + x24_tablegroup_leftmenu->SetMenuSelectionChangeCallback( + std::bind(&SOptionsFrontEndFrame::DoMenuSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + + x38_rowPitch = x24_tablegroup_leftmenu->GetWorkerWidget(1)->GetIdlePosition().z() - + x24_tablegroup_leftmenu->GetWorkerWidget(0)->GetIdlePosition().z(); + + x28_tablegroup_rightmenu->SetMenuSelectionChangeCallback( + std::bind(&SOptionsFrontEndFrame::DoMenuSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x28_tablegroup_rightmenu->SetMenuCancelCallback( + std::bind(&SOptionsFrontEndFrame::DoMenuCancel, this, std::placeholders::_1)); + + x2c_tablegroup_double->SetMenuSelectionChangeCallback( + std::bind(&SOptionsFrontEndFrame::DoMenuSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x2c_tablegroup_double->SetMenuCancelCallback( + std::bind(&SOptionsFrontEndFrame::DoMenuCancel, this, std::placeholders::_1)); + + x30_tablegroup_triple->SetMenuSelectionChangeCallback( + std::bind(&SOptionsFrontEndFrame::DoMenuSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x30_tablegroup_triple->SetMenuCancelCallback( + std::bind(&SOptionsFrontEndFrame::DoMenuCancel, this, std::placeholders::_1)); + + x34_slidergroup_slider->SetSelectionChangedCallback( + std::bind(&SOptionsFrontEndFrame::DoSliderChange, this, std::placeholders::_1, std::placeholders::_2)); + + FindTextPanePair(x1c_loadedFrame, "textpane_double0").SetPairText(x20_loadedPauseStrg->GetString(95)); // Off + FindTextPanePair(x1c_loadedFrame, "textpane_double1").SetPairText(x20_loadedPauseStrg->GetString(94)); // On + FindTextPanePair(x1c_loadedFrame, "textpane_triple0").SetPairText(x20_loadedPauseStrg->GetString(96)); // Mono + FindTextPanePair(x1c_loadedFrame, "textpane_triple1").SetPairText(x20_loadedPauseStrg->GetString(97)); // Stereo + FindTextPanePair(x1c_loadedFrame, "textpane_triple2").SetPairText(x20_loadedPauseStrg->GetString(98)); // Dolby + + FindTextPanePair(x1c_loadedFrame, "textpane_title").SetPairText(g_MainStringTable->GetString(99)); // OPTIONS + + if (CGuiTextPane* proceed = static_cast(x1c_loadedFrame->FindWidget("textpane_proceed"))) + proceed->TextSupport().SetText(g_MainStringTable->GetString(85)); + + if (CGuiTextPane* cancel = static_cast(x1c_loadedFrame->FindWidget("textpane_cancel"))) + cancel->TextSupport().SetText(g_MainStringTable->GetString(82)); + + // Visor, Display, Sound, Controller + for (int i = 0; i < 4; ++i) { + char name[36]; + snprintf(name, 36, "textpane_filename%d", i); + FindTextPanePair(x1c_loadedFrame, name).SetPairText(x20_loadedPauseStrg->GetString(16 + i)); + } + + x2c_tablegroup_double->SetVertical(false); + x30_tablegroup_triple->SetVertical(false); + + x24_tablegroup_leftmenu->SetIsActive(true); + x28_tablegroup_rightmenu->SetIsActive(false); + + SetTableColors(x24_tablegroup_leftmenu); + SetTableColors(x28_tablegroup_rightmenu); + SetTableColors(x2c_tablegroup_double); + SetTableColors(x30_tablegroup_triple); + + SetRightUIText(); + DeactivateRightMenu(); +} + +bool CFrontEndUI::SOptionsFrontEndFrame::PumpLoad() { + if (x1c_loadedFrame) return true; + if (!x4_frme.IsLoaded()) + return false; + if (!x10_pauseScreen.IsLoaded()) + return false; + if (!x4_frme->GetIsFinishedLoading()) + return false; + x1c_loadedFrame = x4_frme.GetObj(); + x20_loadedPauseStrg = x10_pauseScreen.GetObj(); + m_touchBar = NewGameOptionsTouchBar(); + FinishedLoading(); + return true; } -bool CFrontEndUI::SOptionsFrontEndFrame::ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui) -{ - x134_25_exitOptions = false; - if (sui) - sui->ProcessUserInput(input); - if (x1c_loadedFrame && x134_24_visible) - { - if (input.PB() && x24_tablegroup_leftmenu->GetIsActive()) - { - x134_25_exitOptions = true; - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - else - { - x1c_loadedFrame->ProcessUserInput(input); - int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); - int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); - CGameOptions::TryRestoreDefaults(input, leftSel, rightSel, true, false); +bool CFrontEndUI::SOptionsFrontEndFrame::ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui) { + x134_25_exitOptions = false; + if (sui) + sui->ProcessUserInput(input); + if (x1c_loadedFrame && x134_24_visible) { + if (input.PB() && x24_tablegroup_leftmenu->GetIsActive()) { + x134_25_exitOptions = true; + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else { + x1c_loadedFrame->ProcessUserInput(input); + int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); + int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); + CGameOptions::TryRestoreDefaults(input, leftSel, rightSel, true, false); - CGameOptionsTouchBar::EAction tbAction = m_touchBar->PopAction(); - if (x28_tablegroup_rightmenu->GetIsActive()) - { - if (tbAction == CGameOptionsTouchBar::EAction::Advance && !m_touchBarInValue) - { - int value; - m_touchBar->GetSelection(leftSel, rightSel, value); - x28_tablegroup_rightmenu->SetUserSelection(rightSel); - SetTableColors(x28_tablegroup_rightmenu); - HandleRightSelectionChange(); - const auto& optionCategory = GameOptionsRegistry[leftSel]; - const SGameOption& option = optionCategory.second[rightSel]; - if (option.type != EOptionType::RestoreDefaults) - { - m_touchBarInValue = true; - m_touchBarValueDirty = true; - } - else - { - CGameOptions::TryRestoreDefaults(input, leftSel, rightSel, true, true); - } - } - else if (tbAction == CGameOptionsTouchBar::EAction::Back) - { - if (m_touchBarInValue) - m_touchBarInValue = false; - else - DoMenuCancel(x28_tablegroup_rightmenu); - } - else if (tbAction == CGameOptionsTouchBar::EAction::ValueChange) - { - int value; - m_touchBar->GetSelection(leftSel, rightSel, value); - const auto& optionCategory = GameOptionsRegistry[leftSel]; - const SGameOption& option = optionCategory.second[rightSel]; - CGameOptions::SetOption(option.option, value); - if (option.type != EOptionType::Float) - m_touchBarValueDirty = true; - HandleRightSelectionChange(); - } - else - { - if (m_touchBarInValue) - { - if (m_touchBarValueDirty) - { - const auto& optionCategory = GameOptionsRegistry[leftSel]; - const SGameOption& option = optionCategory.second[rightSel]; - int value = CGameOptions::GetOption(option.option); - m_touchBar->SetSelection(leftSel, rightSel, value); - m_touchBarValueDirty = false; - } - } - else - { - m_touchBar->SetSelection(leftSel, -1, -1); - } - } - } - else - { - if (tbAction == CGameOptionsTouchBar::EAction::Advance) - { - int value; - m_touchBar->GetSelection(leftSel, rightSel, value); - x24_tablegroup_leftmenu->SetUserSelection(leftSel); - SetTableColors(x24_tablegroup_leftmenu); - SetRightUIText(); - DoLeftMenuAdvance(x24_tablegroup_leftmenu); - } - if (tbAction == CGameOptionsTouchBar::EAction::Back) - { - x134_25_exitOptions = true; - CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - else - { - m_touchBar->SetSelection(-1, -1, -1); - } + CGameOptionsTouchBar::EAction tbAction = m_touchBar->PopAction(); + if (x28_tablegroup_rightmenu->GetIsActive()) { + if (tbAction == CGameOptionsTouchBar::EAction::Advance && !m_touchBarInValue) { + int value; + m_touchBar->GetSelection(leftSel, rightSel, value); + x28_tablegroup_rightmenu->SetUserSelection(rightSel); + SetTableColors(x28_tablegroup_rightmenu); + HandleRightSelectionChange(); + const auto& optionCategory = GameOptionsRegistry[leftSel]; + const SGameOption& option = optionCategory.second[rightSel]; + if (option.type != EOptionType::RestoreDefaults) { + m_touchBarInValue = true; + m_touchBarValueDirty = true; + } else { + CGameOptions::TryRestoreDefaults(input, leftSel, rightSel, true, true); + } + } else if (tbAction == CGameOptionsTouchBar::EAction::Back) { + if (m_touchBarInValue) + m_touchBarInValue = false; + else + DoMenuCancel(x28_tablegroup_rightmenu); + } else if (tbAction == CGameOptionsTouchBar::EAction::ValueChange) { + int value; + m_touchBar->GetSelection(leftSel, rightSel, value); + const auto& optionCategory = GameOptionsRegistry[leftSel]; + const SGameOption& option = optionCategory.second[rightSel]; + CGameOptions::SetOption(option.option, value); + if (option.type != EOptionType::Float) + m_touchBarValueDirty = true; + HandleRightSelectionChange(); + } else { + if (m_touchBarInValue) { + if (m_touchBarValueDirty) { + const auto& optionCategory = GameOptionsRegistry[leftSel]; + const SGameOption& option = optionCategory.second[rightSel]; + int value = CGameOptions::GetOption(option.option); + m_touchBar->SetSelection(leftSel, rightSel, value); + m_touchBarValueDirty = false; } + } else { + m_touchBar->SetSelection(leftSel, -1, -1); + } } - } - return !x134_25_exitOptions; -} - -void CFrontEndUI::SOptionsFrontEndFrame::Update(float dt, CSaveGameScreen* sui) -{ - x40_rumbleGen.Update(dt); - x134_24_visible = !sui || sui->GetUIType() == CSaveGameScreen::EUIType::SaveReady; - - if (!PumpLoad()) - return; - - x0_uiAlpha = std::min(1.f, x0_uiAlpha + dt); - x1c_loadedFrame->Update(dt); - - bool isSliding = x34_slidergroup_slider->GetState() != CGuiSliderGroup::EState::None; - if (x3c_sliderSfx.operator bool() != isSliding) - { - if (isSliding) - { - x3c_sliderSfx = CSfxManager::SfxStart(SFXui_frontend_options_slider_change_lp, - 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else { + if (tbAction == CGameOptionsTouchBar::EAction::Advance) { + int value; + m_touchBar->GetSelection(leftSel, rightSel, value); + x24_tablegroup_leftmenu->SetUserSelection(leftSel); + SetTableColors(x24_tablegroup_leftmenu); + SetRightUIText(); + DoLeftMenuAdvance(x24_tablegroup_leftmenu); } - else - { - CSfxManager::SfxStop(x3c_sliderSfx); - x3c_sliderSfx.reset(); + if (tbAction == CGameOptionsTouchBar::EAction::Back) { + x134_25_exitOptions = true; + CSfxManager::SfxStart(SFXfnt_back, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else { + m_touchBar->SetSelection(-1, -1, -1); } + } } + } + return !x134_25_exitOptions; } -void CFrontEndUI::SOptionsFrontEndFrame::Draw() const -{ - if (x1c_loadedFrame && x134_24_visible) - { - CGuiWidgetDrawParms params(x0_uiAlpha, zeus::CVector3f::skZero); - x1c_loadedFrame->Draw(params); +void CFrontEndUI::SOptionsFrontEndFrame::Update(float dt, CSaveGameScreen* sui) { + x40_rumbleGen.Update(dt); + x134_24_visible = !sui || sui->GetUIType() == CSaveGameScreen::EUIType::SaveReady; + + if (!PumpLoad()) + return; + + x0_uiAlpha = std::min(1.f, x0_uiAlpha + dt); + x1c_loadedFrame->Update(dt); + + bool isSliding = x34_slidergroup_slider->GetState() != CGuiSliderGroup::EState::None; + if (x3c_sliderSfx.operator bool() != isSliding) { + if (isSliding) { + x3c_sliderSfx = + CSfxManager::SfxStart(SFXui_frontend_options_slider_change_lp, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else { + CSfxManager::SfxStop(x3c_sliderSfx); + x3c_sliderSfx.reset(); } + } } -CFrontEndUI::CFrontEndUI() -: CIOWin("FrontEndUI") -{ - CMain* m = static_cast(g_Main); - - CRandom16 r(time(nullptr)); - x18_rndA = r.Range(0, 2); - x1c_rndB = r.Range(0, 2); - - x20_depsGroup = g_SimplePool->GetObj("FrontEnd_DGRP"); - x38_pressStart = g_SimplePool->GetObj("TXTR_PressStart"); - x44_frontendAudioGrp = g_SimplePool->GetObj("FrontEnd_AGSC"); - - xdc_saveUI = std::make_unique(ESaveContext::FrontEnd, g_GameState->GetCardSerial()); - - m->ResetGameState(); - g_GameState->SetCurrentWorldId(g_ResFactory->TranslateOriginalToNew(g_DefaultWorldTag.id)); - g_GameState->GameOptions().ResetToDefaults(); - g_GameState->WriteBackupBuf(); - - for (int i=0 ; CDvdFile::FileExists(GetAttractMovieFileName(i).c_str()) ; ++i) - ++xc0_attractCount; - - m_touchBar = NewFrontEndUITouchBar(); - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); +void CFrontEndUI::SOptionsFrontEndFrame::Draw() const { + if (x1c_loadedFrame && x134_24_visible) { + CGuiWidgetDrawParms params(x0_uiAlpha, zeus::CVector3f::skZero); + x1c_loadedFrame->Draw(params); + } } -void CFrontEndUI::StartSlideShow(CArchitectureQueue& queue) -{ - xf4_curAudio->StopMixing(); - queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, - std::make_shared())); +CFrontEndUI::CFrontEndUI() : CIOWin("FrontEndUI") { + CMain* m = static_cast(g_Main); + + CRandom16 r(time(nullptr)); + x18_rndA = r.Range(0, 2); + x1c_rndB = r.Range(0, 2); + + x20_depsGroup = g_SimplePool->GetObj("FrontEnd_DGRP"); + x38_pressStart = g_SimplePool->GetObj("TXTR_PressStart"); + x44_frontendAudioGrp = g_SimplePool->GetObj("FrontEnd_AGSC"); + + xdc_saveUI = std::make_unique(ESaveContext::FrontEnd, g_GameState->GetCardSerial()); + + m->ResetGameState(); + g_GameState->SetCurrentWorldId(g_ResFactory->TranslateOriginalToNew(g_DefaultWorldTag.id)); + g_GameState->GameOptions().ResetToDefaults(); + g_GameState->WriteBackupBuf(); + + for (int i = 0; CDvdFile::FileExists(GetAttractMovieFileName(i).c_str()); ++i) + ++xc0_attractCount; + + m_touchBar = NewFrontEndUITouchBar(); + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); } -std::string CFrontEndUI::GetAttractMovieFileName(int idx) -{ - return hecl::Format("Video/attract%d.thp", idx); +void CFrontEndUI::StartSlideShow(CArchitectureQueue& queue) { + xf4_curAudio->StopMixing(); + queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, std::make_shared())); } -std::string CFrontEndUI::GetNextAttractMovieFileName() -{ - std::string ret = GetAttractMovieFileName(xbc_nextAttract); - xbc_nextAttract = (xbc_nextAttract + 1) % xc0_attractCount; - return ret; +std::string CFrontEndUI::GetAttractMovieFileName(int idx) { return hecl::Format("Video/attract%d.thp", idx); } + +std::string CFrontEndUI::GetNextAttractMovieFileName() { + std::string ret = GetAttractMovieFileName(xbc_nextAttract); + xbc_nextAttract = (xbc_nextAttract + 1) % xc0_attractCount; + return ret; } -void CFrontEndUI::SetCurrentMovie(EMenuMovie movie) -{ - if (xb8_curMovie == movie) - return; - StopAttractMovie(); +void CFrontEndUI::SetCurrentMovie(EMenuMovie movie) { + if (xb8_curMovie == movie) + return; + StopAttractMovie(); - if (xb8_curMovie != EMenuMovie::Stopped) - { - xcc_curMoviePtr->SetPlayMode(CMoviePlayer::EPlayMode::Stopped); - xcc_curMoviePtr->Rewind(); - } + if (xb8_curMovie != EMenuMovie::Stopped) { + xcc_curMoviePtr->SetPlayMode(CMoviePlayer::EPlayMode::Stopped); + xcc_curMoviePtr->Rewind(); + } - xb8_curMovie = movie; + xb8_curMovie = movie; - if (xb8_curMovie != EMenuMovie::Stopped) - { - xcc_curMoviePtr = x70_menuMovies[int(xb8_curMovie)].get(); - xcc_curMoviePtr->SetPlayMode(CMoviePlayer::EPlayMode::Playing); - } - else - xcc_curMoviePtr = nullptr; -} - -void CFrontEndUI::StopAttractMovie() -{ - if (!xc4_attractMovie) - return; - xc4_attractMovie.reset(); + if (xb8_curMovie != EMenuMovie::Stopped) { + xcc_curMoviePtr = x70_menuMovies[int(xb8_curMovie)].get(); + xcc_curMoviePtr->SetPlayMode(CMoviePlayer::EPlayMode::Playing); + } else xcc_curMoviePtr = nullptr; } -void CFrontEndUI::StartAttractMovie() -{ - if (xc4_attractMovie) - return; - SetCurrentMovie(EMenuMovie::Stopped); - xc4_attractMovie = std::make_unique(GetNextAttractMovieFileName().c_str(), 0.f, false, true); - xcc_curMoviePtr = xc4_attractMovie.get(); +void CFrontEndUI::StopAttractMovie() { + if (!xc4_attractMovie) + return; + xc4_attractMovie.reset(); + xcc_curMoviePtr = nullptr; } -void CFrontEndUI::StartStateTransition(EScreen screen) -{ - switch (x50_curScreen) - { - case EScreen::Title: - if (screen != EScreen::FileSelect) - break; - SetCurrentMovie(EMenuMovie::StartFileSelectA); - SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); - break; - case EScreen::FileSelect: - if (screen == EScreen::ToPlayGame) - { - SetCurrentMovie(EMenuMovie::FileSelectPlayGameA); - SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); - } - else if (screen == EScreen::FusionBonus) - { - SetCurrentMovie(EMenuMovie::FileSelectGBA); - SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); - CSfxManager::SfxStart(SFXfnt_tofusion_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - CSfxManager::SfxStart(SFXfnt_tofusion_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - break; - case EScreen::FusionBonus: - if (screen == EScreen::ToPlayGame) - { - SetCurrentMovie(EMenuMovie::GBAFileSelectB); - SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); - } - else if (screen == EScreen::FileSelect) - { - SetCurrentMovie(EMenuMovie::GBAFileSelectA); - SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); - CSfxManager::SfxStart(SFXfnt_fromfusion_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - CSfxManager::SfxStart(SFXfnt_fromfusion_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - default: break; - } - - switch (screen) - { - case EScreen::OpenCredits: - case EScreen::Title: - SetCurrentMovie(EMenuMovie::FirstStart); - SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); - break; - case EScreen::AttractMovie: - StartAttractMovie(); - SetFadeBlackWithMovie(); - default: break; - } - - x54_nextScreen = screen; +void CFrontEndUI::StartAttractMovie() { + if (xc4_attractMovie) + return; + SetCurrentMovie(EMenuMovie::Stopped); + xc4_attractMovie = std::make_unique(GetNextAttractMovieFileName().c_str(), 0.f, false, true); + xcc_curMoviePtr = xc4_attractMovie.get(); } -void CFrontEndUI::CompleteStateTransition() -{ - EScreen oldScreen = x50_curScreen; - x50_curScreen = x54_nextScreen; - - switch (x50_curScreen) - { - case EScreen::AttractMovie: - x54_nextScreen = EScreen::OpenCredits; - x50_curScreen = EScreen::OpenCredits; - xd0_playerSkipToTitle = false; - StartStateTransition(EScreen::Title); - break; - - case EScreen::Title: - SetCurrentMovie(EMenuMovie::StartLoop); - SetFadeBlackTimer(30.f); - break; - - case EScreen::FileSelect: - SetCurrentMovie(EMenuMovie::FileSelectLoop); - if (oldScreen == EScreen::Title) - { - xf4_curAudio->StopMixing(); - xf4_curAudio = xd8_audio2.get(); - xf4_curAudio->StartMixing(); - } - if (xdc_saveUI) - xdc_saveUI->ResetCardDriver(); - break; - - case EScreen::FusionBonus: - SetCurrentMovie(EMenuMovie::GBALoop); - break; - - case EScreen::ToPlayGame: - x14_phase = EPhase::ExitFrontEnd; - break; - - default: break; +void CFrontEndUI::StartStateTransition(EScreen screen) { + switch (x50_curScreen) { + case EScreen::Title: + if (screen != EScreen::FileSelect) + break; + SetCurrentMovie(EMenuMovie::StartFileSelectA); + SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); + break; + case EScreen::FileSelect: + if (screen == EScreen::ToPlayGame) { + SetCurrentMovie(EMenuMovie::FileSelectPlayGameA); + SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); + } else if (screen == EScreen::FusionBonus) { + SetCurrentMovie(EMenuMovie::FileSelectGBA); + SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); + CSfxManager::SfxStart(SFXfnt_tofusion_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(SFXfnt_tofusion_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); } + break; + case EScreen::FusionBonus: + if (screen == EScreen::ToPlayGame) { + SetCurrentMovie(EMenuMovie::GBAFileSelectB); + SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); + } else if (screen == EScreen::FileSelect) { + SetCurrentMovie(EMenuMovie::GBAFileSelectA); + SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); + CSfxManager::SfxStart(SFXfnt_fromfusion_L, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(SFXfnt_fromfusion_R, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + default: + break; + } + + switch (screen) { + case EScreen::OpenCredits: + case EScreen::Title: + SetCurrentMovie(EMenuMovie::FirstStart); + SetFadeBlackTimer(xcc_curMoviePtr->GetTotalSeconds()); + break; + case EScreen::AttractMovie: + StartAttractMovie(); + SetFadeBlackWithMovie(); + default: + break; + } + + x54_nextScreen = screen; } -void CFrontEndUI::HandleDebugMenuReturnValue(CGameDebug::EReturnValue val, CArchitectureQueue& queue) -{} +void CFrontEndUI::CompleteStateTransition() { + EScreen oldScreen = x50_curScreen; + x50_curScreen = x54_nextScreen; -void CFrontEndUI::Draw() const -{ - if (x14_phase < EPhase::DisplayFrontEnd) - return; + switch (x50_curScreen) { + case EScreen::AttractMovie: + x54_nextScreen = EScreen::OpenCredits; + x50_curScreen = EScreen::OpenCredits; + xd0_playerSkipToTitle = false; + StartStateTransition(EScreen::Title); + break; - if (xec_emuFrme) - { - xec_emuFrme->Draw(xdc_saveUI.get()); + case EScreen::Title: + SetCurrentMovie(EMenuMovie::StartLoop); + SetFadeBlackTimer(30.f); + break; + + case EScreen::FileSelect: + SetCurrentMovie(EMenuMovie::FileSelectLoop); + if (oldScreen == EScreen::Title) { + xf4_curAudio->StopMixing(); + xf4_curAudio = xd8_audio2.get(); + xf4_curAudio->StartMixing(); } - else - { - //g_Renderer->SetDepthReadWrite(false, false); - g_Renderer->SetViewportOrtho(false, -4096.f, 4096.f); + if (xdc_saveUI) + xdc_saveUI->ResetCardDriver(); + break; - /* Correct movie aspect ratio */ - float vpAspectRatio = g_Viewport.x8_width / float(g_Viewport.xc_height); - float hPad, vPad; - if (vpAspectRatio >= 1.78f) - { - hPad = 1.78f / vpAspectRatio; - vPad = 1.78f / 1.33f; - } - else - { - hPad = 1.f; - vPad = vpAspectRatio / 1.33f; - } + case EScreen::FusionBonus: + SetCurrentMovie(EMenuMovie::GBALoop); + break; - if (xcc_curMoviePtr && xcc_curMoviePtr->GetIsFullyCached()) - { - /* Render movie */ - xcc_curMoviePtr->SetFrame({-hPad, vPad, 0.f}, {-hPad, -vPad, 0.f}, {hPad, -vPad, 0.f}, {hPad, vPad, 0.f}); - xcc_curMoviePtr->DrawFrame(); - } + case EScreen::ToPlayGame: + x14_phase = EPhase::ExitFrontEnd; + break; - if (x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) - { - /* Render active FileSelect UI */ - if (xf0_optionsFrme) - xf0_optionsFrme->Draw(); - else if (xe0_frontendCardFrme) - xe0_frontendCardFrme->Draw(); - else - xe8_frontendNoCardFrme->Draw(); - } - else if (x50_curScreen == EScreen::FusionBonus && x54_nextScreen == EScreen::FusionBonus) - { - /* Render Fusion bonus UI */ - xe4_fusionBonusFrme->Draw(); - } - - if (x64_pressStartAlpha > 0.f && x38_pressStart.IsLoaded() && m_pressStartQuad) - { - /* Render "Press Start" */ - zeus::CRectangle rect(0.5f - x38_pressStart->GetWidth() / 2.f / 640.f * hPad, - 0.5f + (x38_pressStart->GetHeight() / 2.f - 240.f + 72.f) / 480.f * vPad, - x38_pressStart->GetWidth() / 640.f * hPad, - x38_pressStart->GetHeight() / 480.f * vPad); - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x64_pressStartAlpha; - const_cast(*m_pressStartQuad).draw(color, 1.f, rect); - } - - if (xc0_attractCount > 0) - { - /* Render fade-to-black into attract movie */ - if (((x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::Title) || - x54_nextScreen == EScreen::AttractMovie) && x58_fadeBlackTimer < 1.f) - { - /* To black */ - zeus::CColor color = zeus::CColor::skBlack; - color.a() = 1.f - x58_fadeBlackTimer; - const_cast(m_fadeToBlack).draw(color); - } - } - - if (xd0_playerSkipToTitle) - { - /* Render fade-through-black into title if player skips */ - if (x50_curScreen == EScreen::OpenCredits && x54_nextScreen == EScreen::Title) - { - /* To black */ - zeus::CColor color = zeus::CColor::skBlack; - color.a() = zeus::clamp(0.f, 1.f - x58_fadeBlackTimer, 1.f); - const_cast(m_fadeToBlack).draw(color); - } - else if (x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::Title) - { - /* From black with 30-sec skip to title */ - zeus::CColor color = zeus::CColor::skBlack; - color.a() = 1.f - zeus::clamp(0.f, 30.f - x58_fadeBlackTimer, 1.f); - const_cast(m_fadeToBlack).draw(color); - } - } - - if (xdc_saveUI) - { - /* Render memory card feedback strings */ - if ((CanShowSaveUI() && !xdc_saveUI->IsHiddenFromFrontEnd()) || - ((x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) || - (x50_curScreen == EScreen::FusionBonus && x54_nextScreen == EScreen::FusionBonus))) - xdc_saveUI->Draw(); - } - } + default: + break; + } } -void CFrontEndUI::UpdateMovies(float dt) -{ - if (xcc_curMoviePtr && x5c_fadeBlackWithMovie) - { - /* Set fade-to-black timer to match attract movie */ - x5c_fadeBlackWithMovie = false; - x58_fadeBlackTimer = xcc_curMoviePtr->GetTotalSeconds(); +void CFrontEndUI::HandleDebugMenuReturnValue(CGameDebug::EReturnValue val, CArchitectureQueue& queue) {} + +void CFrontEndUI::Draw() const { + if (x14_phase < EPhase::DisplayFrontEnd) + return; + + if (xec_emuFrme) { + xec_emuFrme->Draw(xdc_saveUI.get()); + } else { + // g_Renderer->SetDepthReadWrite(false, false); + g_Renderer->SetViewportOrtho(false, -4096.f, 4096.f); + + /* Correct movie aspect ratio */ + float vpAspectRatio = g_Viewport.x8_width / float(g_Viewport.xc_height); + float hPad, vPad; + if (vpAspectRatio >= 1.78f) { + hPad = 1.78f / vpAspectRatio; + vPad = 1.78f / 1.33f; + } else { + hPad = 1.f; + vPad = vpAspectRatio / 1.33f; } - /* Advance playing menu movies */ - for (auto& movie : x70_menuMovies) - if (movie) - movie->Update(dt); - - /* Advance attract movie */ - if (xc4_attractMovie) - xc4_attractMovie->Update(dt); -} - -void CFrontEndUI::FinishedLoadingDepsGroup() -{ - /* Transfer DGRP tokens into FrontEnd and lock */ - const CDependencyGroup* dgrp = x20_depsGroup.GetObj(); - x2c_deps.reserve(dgrp->GetObjectTagVector().size()); - for (const SObjectTag& tag : dgrp->GetObjectTagVector()) - { - x2c_deps.push_back(g_SimplePool->GetObj(tag)); - x2c_deps.back().Lock(); + if (xcc_curMoviePtr && xcc_curMoviePtr->GetIsFullyCached()) { + /* Render movie */ + xcc_curMoviePtr->SetFrame({-hPad, vPad, 0.f}, {-hPad, -vPad, 0.f}, {hPad, -vPad, 0.f}, {hPad, vPad, 0.f}); + xcc_curMoviePtr->DrawFrame(); } - x44_frontendAudioGrp.Lock(); + + if (x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) { + /* Render active FileSelect UI */ + if (xf0_optionsFrme) + xf0_optionsFrme->Draw(); + else if (xe0_frontendCardFrme) + xe0_frontendCardFrme->Draw(); + else + xe8_frontendNoCardFrme->Draw(); + } else if (x50_curScreen == EScreen::FusionBonus && x54_nextScreen == EScreen::FusionBonus) { + /* Render Fusion bonus UI */ + xe4_fusionBonusFrme->Draw(); + } + + if (x64_pressStartAlpha > 0.f && x38_pressStart.IsLoaded() && m_pressStartQuad) { + /* Render "Press Start" */ + zeus::CRectangle rect(0.5f - x38_pressStart->GetWidth() / 2.f / 640.f * hPad, + 0.5f + (x38_pressStart->GetHeight() / 2.f - 240.f + 72.f) / 480.f * vPad, + x38_pressStart->GetWidth() / 640.f * hPad, x38_pressStart->GetHeight() / 480.f * vPad); + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x64_pressStartAlpha; + const_cast(*m_pressStartQuad).draw(color, 1.f, rect); + } + + if (xc0_attractCount > 0) { + /* Render fade-to-black into attract movie */ + if (((x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::Title) || + x54_nextScreen == EScreen::AttractMovie) && + x58_fadeBlackTimer < 1.f) { + /* To black */ + zeus::CColor color = zeus::CColor::skBlack; + color.a() = 1.f - x58_fadeBlackTimer; + const_cast(m_fadeToBlack).draw(color); + } + } + + if (xd0_playerSkipToTitle) { + /* Render fade-through-black into title if player skips */ + if (x50_curScreen == EScreen::OpenCredits && x54_nextScreen == EScreen::Title) { + /* To black */ + zeus::CColor color = zeus::CColor::skBlack; + color.a() = zeus::clamp(0.f, 1.f - x58_fadeBlackTimer, 1.f); + const_cast(m_fadeToBlack).draw(color); + } else if (x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::Title) { + /* From black with 30-sec skip to title */ + zeus::CColor color = zeus::CColor::skBlack; + color.a() = 1.f - zeus::clamp(0.f, 30.f - x58_fadeBlackTimer, 1.f); + const_cast(m_fadeToBlack).draw(color); + } + } + + if (xdc_saveUI) { + /* Render memory card feedback strings */ + if ((CanShowSaveUI() && !xdc_saveUI->IsHiddenFromFrontEnd()) || + ((x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) || + (x50_curScreen == EScreen::FusionBonus && x54_nextScreen == EScreen::FusionBonus))) + xdc_saveUI->Draw(); + } + } } -bool CFrontEndUI::PumpLoad() -{ - /* Poll all tokens for load completion */ - for (CToken& tok : x2c_deps) - if (!tok.IsLoaded()) - return false; - if (!x44_frontendAudioGrp.IsLoaded()) - return false; +void CFrontEndUI::UpdateMovies(float dt) { + if (xcc_curMoviePtr && x5c_fadeBlackWithMovie) { + /* Set fade-to-black timer to match attract movie */ + x5c_fadeBlackWithMovie = false; + x58_fadeBlackTimer = xcc_curMoviePtr->GetTotalSeconds(); + } - /* Ready to construct texture quads */ - m_pressStartQuad.emplace(EFilterType::Add, x38_pressStart); + /* Advance playing menu movies */ + for (auto& movie : x70_menuMovies) + if (movie) + movie->Update(dt); + /* Advance attract movie */ + if (xc4_attractMovie) + xc4_attractMovie->Update(dt); +} + +void CFrontEndUI::FinishedLoadingDepsGroup() { + /* Transfer DGRP tokens into FrontEnd and lock */ + const CDependencyGroup* dgrp = x20_depsGroup.GetObj(); + x2c_deps.reserve(dgrp->GetObjectTagVector().size()); + for (const SObjectTag& tag : dgrp->GetObjectTagVector()) { + x2c_deps.push_back(g_SimplePool->GetObj(tag)); + x2c_deps.back().Lock(); + } + x44_frontendAudioGrp.Lock(); +} + +bool CFrontEndUI::PumpLoad() { + /* Poll all tokens for load completion */ + for (CToken& tok : x2c_deps) + if (!tok.IsLoaded()) + return false; + if (!x44_frontendAudioGrp.IsLoaded()) + return false; + + /* Ready to construct texture quads */ + m_pressStartQuad.emplace(EFilterType::Add, x38_pressStart); + + return true; +} + +bool CFrontEndUI::PumpMovieLoad() { + /* Prepare all FrontEnd movies and pause each */ + if (xd1_moviesLoaded) return true; + for (int i = 0; i < 9; ++i) { + if (!x70_menuMovies[i]) { + const FEMovie& movie = FEMovies[i]; + std::string path = movie.path; + if (i == int(EMenuMovie::StartFileSelectA)) { + auto pos = path.find("A.thp"); + if (pos != std::string::npos) + path[pos] = 'A' + x18_rndA; + } else if (i == int(EMenuMovie::FileSelectPlayGameA)) { + auto pos = path.find("A.thp"); + if (pos != std::string::npos) + path[pos] = 'A' + x1c_rndB; + } + x70_menuMovies[i] = std::make_unique(path.c_str(), 0.05f, movie.loop, false); + x70_menuMovies[i]->SetPlayMode(CMoviePlayer::EPlayMode::Stopped); + return false; + } + } + xd1_moviesLoaded = true; + return true; } -bool CFrontEndUI::PumpMovieLoad() -{ - /* Prepare all FrontEnd movies and pause each */ - if (xd1_moviesLoaded) - return true; - for (int i=0 ; i<9 ; ++i) - { - if (!x70_menuMovies[i]) - { - const FEMovie& movie = FEMovies[i]; - std::string path = movie.path; - if (i == int(EMenuMovie::StartFileSelectA)) - { - auto pos = path.find("A.thp"); - if (pos != std::string::npos) - path[pos] = 'A' + x18_rndA; - } - else if (i == int(EMenuMovie::FileSelectPlayGameA)) - { - auto pos = path.find("A.thp"); - if (pos != std::string::npos) - path[pos] = 'A' + x1c_rndB; - } - x70_menuMovies[i] = std::make_unique(path.c_str(), 0.05f, movie.loop, false); - x70_menuMovies[i]->SetPlayMode(CMoviePlayer::EPlayMode::Stopped); - return false; - } +void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue& queue) { + if (static_cast(g_Main)->GetCardBusy()) + return; + if (input.ControllerIdx() > 1) + return; + + if (xec_emuFrme) { + /* NES emulator pre-empts user input if active */ + xec_emuFrme->ProcessUserInput(input, xdc_saveUI.get()); + return; + } + + /* Controllers other than first shall not pass */ + if (x14_phase != EPhase::DisplayFrontEnd || input.ControllerIdx() != 0) + return; + + /* Pop most recent action from Touch Bar */ + CFrontEndUITouchBar::EAction touchBarAction = m_touchBar->PopAction(); + + if (x50_curScreen != x54_nextScreen) { + if (x54_nextScreen == EScreen::AttractMovie && + (input.PStart() || input.PA() || touchBarAction == CFrontEndUITouchBar::EAction::Start)) { + /* Player wants to return to opening credits from attract movie */ + SetFadeBlackTimer(std::min(1.f, x58_fadeBlackTimer)); + PlayAdvanceSfx(); + return; } - xd1_moviesLoaded = true; - return true; + + if (input.PA() || input.PStart() || touchBarAction == CFrontEndUITouchBar::EAction::Start) { + if (x50_curScreen == EScreen::OpenCredits && x54_nextScreen == EScreen::Title && x58_fadeBlackTimer > 1.f) { + /* Player is too impatient to view opening credits */ + xd0_playerSkipToTitle = true; + SetFadeBlackTimer(1.f); + return; + } + } + } else { + if (x50_curScreen == EScreen::Title) { + if (input.PStart() || input.PA() || touchBarAction == CFrontEndUITouchBar::EAction::Start) { + if (x58_fadeBlackTimer < 30.f - g_tweakGame->GetPressStartDelay()) { + /* Proceed to file select UI */ + CSfxManager::SfxStart(FETransitionBackSFX[x18_rndA][0], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(FETransitionBackSFX[x18_rndA][1], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + StartStateTransition(EScreen::FileSelect); + return; + } + } + } else if (x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) { + if (xf0_optionsFrme) { + /* Control options UI */ + if (xf0_optionsFrme->ProcessUserInput(input, xdc_saveUI.get())) + return; + /* Exit options UI */ + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + xf0_optionsFrme.reset(); + return; + } else if (xe0_frontendCardFrme) { + /* Control FrontEnd with memory card */ + switch (xe0_frontendCardFrme->ProcessUserInput(input, touchBarAction)) { + case SNewFileSelectFrame::EAction::FusionBonus: + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + StartStateTransition(EScreen::FusionBonus); + return; + case SNewFileSelectFrame::EAction::GameOptions: + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + xf0_optionsFrme = std::make_unique(); + return; + case SNewFileSelectFrame::EAction::SlideShow: + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + xd2_deferSlideShow = true; + StartSlideShow(queue); + return; + default: + return; + } + } else { + /* Control FrontEnd without memory card */ + switch (xe8_frontendNoCardFrme->ProcessUserInput(input, touchBarAction)) { + case SFrontEndFrame::EAction::FusionBonus: + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + StartStateTransition(EScreen::FusionBonus); + return; + case SFrontEndFrame::EAction::GameOptions: + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + xf0_optionsFrme = std::make_unique(); + return; + case SFrontEndFrame::EAction::StartGame: + TransitionToGame(); + return; + case SFrontEndFrame::EAction::SlideShow: + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + xd2_deferSlideShow = true; + StartSlideShow(queue); + return; + default: + return; + } + } + } else if (x50_curScreen == EScreen::FusionBonus && x54_nextScreen == EScreen::FusionBonus) { + /* Control Fusion bonus UI */ + switch (xe4_fusionBonusFrme->ProcessUserInput(input, xdc_saveUI.get(), touchBarAction)) { + case SFusionBonusFrame::EAction::GoBack: + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + StartStateTransition(EScreen::FileSelect); + return; + case SFusionBonusFrame::EAction::PlayNESMetroid: + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + xf4_curAudio->StopMixing(); + xec_emuFrme = std::make_unique(); + if (xdc_saveUI) + xdc_saveUI->SetInGame(true); + return; + default: + return; + } + } + } } -void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue& queue) -{ - if (static_cast(g_Main)->GetCardBusy()) - return; - if (input.ControllerIdx() > 1) - return; +void CFrontEndUI::TransitionToGame() { + if (x14_phase >= EPhase::ToPlayGame) + return; - if (xec_emuFrme) - { - /* NES emulator pre-empts user input if active */ - xec_emuFrme->ProcessUserInput(input, xdc_saveUI.get()); - return; - } + const u16* sfx = FETransitionForwardSFX[x1c_rndB]; + CSfxManager::SfxStart(sfx[0], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(sfx[1], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - /* Controllers other than first shall not pass */ - if (x14_phase != EPhase::DisplayFrontEnd || input.ControllerIdx() != 0) - return; - - /* Pop most recent action from Touch Bar */ - CFrontEndUITouchBar::EAction touchBarAction = m_touchBar->PopAction(); - - if (x50_curScreen != x54_nextScreen) - { - if (x54_nextScreen == EScreen::AttractMovie && (input.PStart() || input.PA() || - touchBarAction == CFrontEndUITouchBar::EAction::Start)) - { - /* Player wants to return to opening credits from attract movie */ - SetFadeBlackTimer(std::min(1.f, x58_fadeBlackTimer)); - PlayAdvanceSfx(); - return; - } - - if (input.PA() || input.PStart() || touchBarAction == CFrontEndUITouchBar::EAction::Start) - { - if (x50_curScreen == EScreen::OpenCredits && x54_nextScreen == EScreen::Title && - x58_fadeBlackTimer > 1.f) - { - /* Player is too impatient to view opening credits */ - xd0_playerSkipToTitle = true; - SetFadeBlackTimer(1.f); - return; - } - } - } - else - { - if (x50_curScreen == EScreen::Title) - { - if (input.PStart() || input.PA() || touchBarAction == CFrontEndUITouchBar::EAction::Start) - { - if (x58_fadeBlackTimer < 30.f - g_tweakGame->GetPressStartDelay()) - { - /* Proceed to file select UI */ - CSfxManager::SfxStart(FETransitionBackSFX[x18_rndA][0], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - CSfxManager::SfxStart(FETransitionBackSFX[x18_rndA][1], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - StartStateTransition(EScreen::FileSelect); - return; - } - } - } - else if (x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) - { - if (xf0_optionsFrme) - { - /* Control options UI */ - if (xf0_optionsFrme->ProcessUserInput(input, xdc_saveUI.get())) - return; - /* Exit options UI */ - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - xf0_optionsFrme.reset(); - return; - } - else if (xe0_frontendCardFrme) - { - /* Control FrontEnd with memory card */ - switch (xe0_frontendCardFrme->ProcessUserInput(input, touchBarAction)) - { - case SNewFileSelectFrame::EAction::FusionBonus: - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - StartStateTransition(EScreen::FusionBonus); - return; - case SNewFileSelectFrame::EAction::GameOptions: - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - xf0_optionsFrme = std::make_unique(); - return; - case SNewFileSelectFrame::EAction::SlideShow: - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - xd2_deferSlideShow = true; - StartSlideShow(queue); - return; - default: return; - } - } - else - { - /* Control FrontEnd without memory card */ - switch (xe8_frontendNoCardFrme->ProcessUserInput(input, touchBarAction)) - { - case SFrontEndFrame::EAction::FusionBonus: - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - StartStateTransition(EScreen::FusionBonus); - return; - case SFrontEndFrame::EAction::GameOptions: - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - xf0_optionsFrme = std::make_unique(); - return; - case SFrontEndFrame::EAction::StartGame: - TransitionToGame(); - return; - case SFrontEndFrame::EAction::SlideShow: - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - xd2_deferSlideShow = true; - StartSlideShow(queue); - return; - default: return; - } - } - } - else if (x50_curScreen == EScreen::FusionBonus && x54_nextScreen == EScreen::FusionBonus) - { - /* Control Fusion bonus UI */ - switch (xe4_fusionBonusFrme->ProcessUserInput(input, xdc_saveUI.get(), touchBarAction)) - { - case SFusionBonusFrame::EAction::GoBack: - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - StartStateTransition(EScreen::FileSelect); - return; - case SFusionBonusFrame::EAction::PlayNESMetroid: - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - xf4_curAudio->StopMixing(); - xec_emuFrme = std::make_unique(); - if (xdc_saveUI) - xdc_saveUI->SetInGame(true); - return; - default: return; - } - } - } + x14_phase = EPhase::ToPlayGame; + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); + StartStateTransition(EScreen::ToPlayGame); } -void CFrontEndUI::TransitionToGame() -{ - if (x14_phase >= EPhase::ToPlayGame) - return; - - const u16* sfx = FETransitionForwardSFX[x1c_rndB]; - CSfxManager::SfxStart(sfx[0], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - CSfxManager::SfxStart(sfx[1], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - - x14_phase = EPhase::ToPlayGame; - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); - StartStateTransition(EScreen::ToPlayGame); +void CFrontEndUI::UpdateMusicVolume() { + float volMul = (xf4_curAudio == xd4_audio1.get()) ? FE1_VOL : FE2_VOL; + if (xf4_curAudio) { + float vol = volMul * x68_musicVol * (g_GameState->GameOptions().GetMusicVolume() / 127.f); + xf4_curAudio->SetVolume(vol); + } } -void CFrontEndUI::UpdateMusicVolume() -{ - float volMul = (xf4_curAudio == xd4_audio1.get()) ? FE1_VOL : FE2_VOL; - if (xf4_curAudio) - { - float vol = volMul * x68_musicVol * (g_GameState->GameOptions().GetMusicVolume() / 127.f); - xf4_curAudio->SetVolume(vol); +static const float AudioFadeTimeA[] = {0.44f, 5.41f, 3.41f}; + +static const float AudioFadeTimeB[] = {4.2f, 6.1f, 6.1f}; + +CIOWin::EMessageReturn CFrontEndUI::Update(float dt, CArchitectureQueue& queue) { + if (xdc_saveUI && x50_curScreen >= EScreen::FileSelect) { + switch (xdc_saveUI->Update(dt)) { + case EMessageReturn::Exit: + /* Memory card operation complete, transition to game */ + TransitionToGame(); + break; + case EMessageReturn::RemoveIOWinAndExit: + case EMessageReturn::RemoveIOWin: + /* No memory card available, fallback to non-save UI */ + xe0_frontendCardFrme.reset(); + xdc_saveUI.reset(); + default: + break; } -} + } -static const float AudioFadeTimeA[] = -{ - 0.44f, 5.41f, 3.41f -}; + /* Set music fade volume */ + UpdateMusicVolume(); -static const float AudioFadeTimeB[] = -{ - 4.2f, 6.1f, 6.1f -}; + switch (x14_phase) { + case EPhase::LoadDepsGroup: + /* Poll DGRP load */ + if (!x20_depsGroup.IsLoaded()) + return EMessageReturn::Exit; + FinishedLoadingDepsGroup(); + x20_depsGroup.Unlock(); + x14_phase = EPhase::LoadDeps; -CIOWin::EMessageReturn CFrontEndUI::Update(float dt, CArchitectureQueue& queue) -{ - if (xdc_saveUI && x50_curScreen >= EScreen::FileSelect) - { - switch (xdc_saveUI->Update(dt)) - { - case EMessageReturn::Exit: - /* Memory card operation complete, transition to game */ - TransitionToGame(); - break; - case EMessageReturn::RemoveIOWinAndExit: - case EMessageReturn::RemoveIOWin: - /* No memory card available, fallback to non-save UI */ - xe0_frontendCardFrme.reset(); - xdc_saveUI.reset(); - default: break; - } + case EPhase::LoadDeps: + /* Poll loading DGRP resources */ + if (PumpLoad()) { + xe0_frontendCardFrme = std::make_unique(xdc_saveUI.get(), x1c_rndB, *m_touchBar); + xe4_fusionBonusFrme = std::make_unique(*m_touchBar); + xe8_frontendNoCardFrme = std::make_unique(x1c_rndB, *m_touchBar); + x38_pressStart.GetObj(); + CAudioSys::AddAudioGroup(x44_frontendAudioGrp->GetAudioGroupData()); + xd4_audio1 = std::make_unique("Audio/frontend_1.rsf", 416480, 1973664); + xd8_audio2 = std::make_unique("Audio/frontend_2.rsf", 273556, 1636980); + x14_phase = EPhase::LoadFrames; } + if (x14_phase == EPhase::LoadDeps) + return EMessageReturn::Exit; - /* Set music fade volume */ - UpdateMusicVolume(); + case EPhase::LoadFrames: + /* Poll loading music and FRME resources */ + if (!xd4_audio1->IsReady() || !xd8_audio2->IsReady() || !xe0_frontendCardFrme->PumpLoad() || + !xe4_fusionBonusFrme->PumpLoad() || !xe8_frontendNoCardFrme->PumpLoad() || !xdc_saveUI->PumpLoad()) + return EMessageReturn::Exit; + xf4_curAudio = xd4_audio1.get(); + xf4_curAudio->StartMixing(); + x14_phase = EPhase::LoadMovies; - switch (x14_phase) - { - case EPhase::LoadDepsGroup: - /* Poll DGRP load */ - if (!x20_depsGroup.IsLoaded()) - return EMessageReturn::Exit; - FinishedLoadingDepsGroup(); - x20_depsGroup.Unlock(); - x14_phase = EPhase::LoadDeps; - - case EPhase::LoadDeps: - /* Poll loading DGRP resources */ - if (PumpLoad()) - { - xe0_frontendCardFrme = std::make_unique(xdc_saveUI.get(), x1c_rndB, *m_touchBar); - xe4_fusionBonusFrme = std::make_unique(*m_touchBar); - xe8_frontendNoCardFrme = std::make_unique(x1c_rndB, *m_touchBar); - x38_pressStart.GetObj(); - CAudioSys::AddAudioGroup(x44_frontendAudioGrp->GetAudioGroupData()); - xd4_audio1 = std::make_unique("Audio/frontend_1.rsf", 416480, 1973664); - xd8_audio2 = std::make_unique("Audio/frontend_2.rsf", 273556, 1636980); - x14_phase = EPhase::LoadFrames; + case EPhase::LoadMovies: { + /* Poll loading movies */ + bool moviesReady = true; + if (PumpMovieLoad()) { + /* Prime first frame of movies */ + UpdateMovies(dt); + for (int i = 0; i < 9; ++i) { + if (!x70_menuMovies[i]->GetIsFullyCached()) { + moviesReady = false; + break; } - if (x14_phase == EPhase::LoadDeps) - return EMessageReturn::Exit; + } + } else + moviesReady = false; - case EPhase::LoadFrames: - /* Poll loading music and FRME resources */ - if (!xd4_audio1->IsReady() || !xd8_audio2->IsReady() || - !xe0_frontendCardFrme->PumpLoad() || !xe4_fusionBonusFrme->PumpLoad() || - !xe8_frontendNoCardFrme->PumpLoad() || !xdc_saveUI->PumpLoad()) - return EMessageReturn::Exit; - xf4_curAudio = xd4_audio1.get(); + if (moviesReady) { + /* Ready to display FrontEnd */ + x14_phase = EPhase::DisplayFrontEnd; + m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::PressStart); + StartStateTransition(EScreen::Title); + } else + return EMessageReturn::Exit; + } + + case EPhase::DisplayFrontEnd: + case EPhase::ToPlayGame: + /* Displaying frontend to user */ + if (xec_emuFrme) { + /* Update just the emulator if active */ + if (xec_emuFrme->Update(dt, xdc_saveUI.get())) { + /* Exit emulator */ + xec_emuFrme.reset(); + if (xdc_saveUI) + xdc_saveUI->SetInGame(false); xf4_curAudio->StartMixing(); - x14_phase = EPhase::LoadMovies; - - case EPhase::LoadMovies: - { - /* Poll loading movies */ - bool moviesReady = true; - if (PumpMovieLoad()) - { - /* Prime first frame of movies */ - UpdateMovies(dt); - for (int i=0 ; i<9 ; ++i) - { - if (!x70_menuMovies[i]->GetIsFullyCached()) - { - moviesReady = false; - break; - } - } - } - else - moviesReady = false; - - if (moviesReady) - { - /* Ready to display FrontEnd */ - x14_phase = EPhase::DisplayFrontEnd; - m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::PressStart); - StartStateTransition(EScreen::Title); - } - else - return EMessageReturn::Exit; + } + break; } - case EPhase::DisplayFrontEnd: - case EPhase::ToPlayGame: - /* Displaying frontend to user */ - if (xec_emuFrme) - { - /* Update just the emulator if active */ - if (xec_emuFrme->Update(dt, xdc_saveUI.get())) - { - /* Exit emulator */ - xec_emuFrme.reset(); - if (xdc_saveUI) - xdc_saveUI->SetInGame(false); - xf4_curAudio->StartMixing(); - } - break; - } + if (xd2_deferSlideShow) { + /* Start mixing slideshow music */ + xd2_deferSlideShow = false; + xf4_curAudio->StartMixing(); + if (xdc_saveUI) + xdc_saveUI->ResetCardDriver(); + } - if (xd2_deferSlideShow) - { - /* Start mixing slideshow music */ - xd2_deferSlideShow = false; - xf4_curAudio->StartMixing(); - if (xdc_saveUI) - xdc_saveUI->ResetCardDriver(); - } + if (x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) { + /* Main FrontEnd UI tree active */ + if (xf0_optionsFrme) { + bool optionsActive = true; + if (xdc_saveUI && xdc_saveUI->GetUIType() != CSaveGameScreen::EUIType::SaveReady) + optionsActive = false; - if (x50_curScreen == EScreen::FileSelect && x54_nextScreen == EScreen::FileSelect) - { - /* Main FrontEnd UI tree active */ - if (xf0_optionsFrme) - { - bool optionsActive = true; - if (xdc_saveUI && xdc_saveUI->GetUIType() != CSaveGameScreen::EUIType::SaveReady) - optionsActive = false; - - if (optionsActive) - { - /* Update options UI */ - xf0_optionsFrme->Update(dt, xdc_saveUI.get()); - } - else - { - /* Save triggered; exit options UI here */ - xf0_optionsFrme.reset(); - } - } - else if (xe0_frontendCardFrme) - { - /* Update FrontEnd with memory card UI */ - xe0_frontendCardFrme->Update(dt); - } - else - { - /* Update FrontEnd without memory card UI */ - xe8_frontendNoCardFrme->Update(dt); - } - } - else if (x50_curScreen == EScreen::FusionBonus && x54_nextScreen == EScreen::FusionBonus) - { - /* Update Fusion bonus UI */ - xe4_fusionBonusFrme->Update(dt, xdc_saveUI.get()); + if (optionsActive) { + /* Update options UI */ + xf0_optionsFrme->Update(dt, xdc_saveUI.get()); + } else { + /* Save triggered; exit options UI here */ + xf0_optionsFrme.reset(); } + } else if (xe0_frontendCardFrme) { + /* Update FrontEnd with memory card UI */ + xe0_frontendCardFrme->Update(dt); + } else { + /* Update FrontEnd without memory card UI */ + xe8_frontendNoCardFrme->Update(dt); + } + } else if (x50_curScreen == EScreen::FusionBonus && x54_nextScreen == EScreen::FusionBonus) { + /* Update Fusion bonus UI */ + xe4_fusionBonusFrme->Update(dt, xdc_saveUI.get()); + } - if (x50_curScreen != x54_nextScreen && xcc_curMoviePtr && - (xcc_curMoviePtr->GetIsMovieFinishedPlaying() || xcc_curMoviePtr->IsLooping())) - { - /* Movie-based transition complete */ - CompleteStateTransition(); - } + if (x50_curScreen != x54_nextScreen && xcc_curMoviePtr && + (xcc_curMoviePtr->GetIsMovieFinishedPlaying() || xcc_curMoviePtr->IsLooping())) { + /* Movie-based transition complete */ + CompleteStateTransition(); + } - if (x58_fadeBlackTimer > 0.f && !x5c_fadeBlackWithMovie) - { - SetFadeBlackTimer(std::max(0.f, x58_fadeBlackTimer - dt)); - if (x58_fadeBlackTimer == 0.f) - { - if (x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::Title) - { - if (xc0_attractCount > 0) - { - /* Screen black, start attract movie */ - StartStateTransition(EScreen::AttractMovie); - } - } - else if (x54_nextScreen == EScreen::AttractMovie) - { - /* Attract movie done, play open credits again */ - CompleteStateTransition(); - } - else if (x50_curScreen != x54_nextScreen) - { - /* Fade-based transition complete */ - CompleteStateTransition(); - } - } + if (x58_fadeBlackTimer > 0.f && !x5c_fadeBlackWithMovie) { + SetFadeBlackTimer(std::max(0.f, x58_fadeBlackTimer - dt)); + if (x58_fadeBlackTimer == 0.f) { + if (x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::Title) { + if (xc0_attractCount > 0) { + /* Screen black, start attract movie */ + StartStateTransition(EScreen::AttractMovie); + } + } else if (x54_nextScreen == EScreen::AttractMovie) { + /* Attract movie done, play open credits again */ + CompleteStateTransition(); + } else if (x50_curScreen != x54_nextScreen) { + /* Fade-based transition complete */ + CompleteStateTransition(); } + } + } - /* Advance active movies */ - UpdateMovies(dt); + /* Advance active movies */ + UpdateMovies(dt); - if (x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::Title) - { - /* Update press-start pulsing */ - if (x58_fadeBlackTimer < 30.f - g_tweakGame->GetPressStartDelay()) - { - x60_pressStartTime = std::fmod(x60_pressStartTime + dt, 1.f); - if (x60_pressStartTime < 0.5f) - x64_pressStartAlpha = x60_pressStartTime / 0.5f; - else - x64_pressStartAlpha = (1.f - x60_pressStartTime) / 0.5f; - } - } + if (x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::Title) { + /* Update press-start pulsing */ + if (x58_fadeBlackTimer < 30.f - g_tweakGame->GetPressStartDelay()) { + x60_pressStartTime = std::fmod(x60_pressStartTime + dt, 1.f); + if (x60_pressStartTime < 0.5f) + x64_pressStartAlpha = x60_pressStartTime / 0.5f; else - { - /* Clear press-start pulsing */ - x60_pressStartTime = 0.f; - x64_pressStartAlpha = 0.f; - } + x64_pressStartAlpha = (1.f - x60_pressStartTime) / 0.5f; + } + } else { + /* Clear press-start pulsing */ + x60_pressStartTime = 0.f; + x64_pressStartAlpha = 0.f; + } - if (x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::FileSelect) - { - /* Fade out title music */ - x68_musicVol = 1.f - zeus::clamp(0.f, (xcc_curMoviePtr->GetPlayedSeconds() - - AudioFadeTimeA[x18_rndA]) / 2.5f, 1.f); - } - else if (x54_nextScreen == EScreen::ToPlayGame) - { - /* Fade out menu music */ - float delay = AudioFadeTimeB[x1c_rndB]; - x68_musicVol = 1.f - zeus::clamp(0.f, (xcc_curMoviePtr->GetPlayedSeconds() - delay) / - (xcc_curMoviePtr->GetTotalSeconds() - delay), 1.f); - } - else - { - /* Full music volume */ - x68_musicVol = 1.f; - } - - return EMessageReturn::Exit; - - case EPhase::ExitFrontEnd: - /* Remove FrontEnd IOWin and begin updating next IOWin */ - return EMessageReturn::RemoveIOWin; - - default: break; + if (x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::FileSelect) { + /* Fade out title music */ + x68_musicVol = + 1.f - zeus::clamp(0.f, (xcc_curMoviePtr->GetPlayedSeconds() - AudioFadeTimeA[x18_rndA]) / 2.5f, 1.f); + } else if (x54_nextScreen == EScreen::ToPlayGame) { + /* Fade out menu music */ + float delay = AudioFadeTimeB[x1c_rndB]; + x68_musicVol = + 1.f - + zeus::clamp(0.f, (xcc_curMoviePtr->GetPlayedSeconds() - delay) / (xcc_curMoviePtr->GetTotalSeconds() - delay), + 1.f); + } else { + /* Full music volume */ + x68_musicVol = 1.f; } return EMessageReturn::Exit; + + case EPhase::ExitFrontEnd: + /* Remove FrontEnd IOWin and begin updating next IOWin */ + return EMessageReturn::RemoveIOWin; + + default: + break; + } + + return EMessageReturn::Exit; } -CIOWin::EMessageReturn CFrontEndUI::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - switch (msg.GetType()) - { - case EArchMsgType::UserInput: - { - /* Forward user events */ - const CArchMsgParmUserInput& input = MakeMsg::GetParmUserInput(msg); - ProcessUserInput(input.x4_parm, queue); - break; - } - case EArchMsgType::TimerTick: - { - /* Forward frame events */ - float dt = MakeMsg::GetParmTimerTick(msg).x4_parm; - return Update(dt, queue); - } - case EArchMsgType::QuitGameplay: - { - /* Immediately exit FrontEnd */ - x14_phase = EPhase::ExitFrontEnd; - break; - } - default: break; - } - return EMessageReturn::Normal; +CIOWin::EMessageReturn CFrontEndUI::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + switch (msg.GetType()) { + case EArchMsgType::UserInput: { + /* Forward user events */ + const CArchMsgParmUserInput& input = MakeMsg::GetParmUserInput(msg); + ProcessUserInput(input.x4_parm, queue); + break; + } + case EArchMsgType::TimerTick: { + /* Forward frame events */ + float dt = MakeMsg::GetParmTimerTick(msg).x4_parm; + return Update(dt, queue); + } + case EArchMsgType::QuitGameplay: { + /* Immediately exit FrontEnd */ + x14_phase = EPhase::ExitFrontEnd; + break; + } + default: + break; + } + return EMessageReturn::Normal; } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CFrontEndUI.hpp b/Runtime/MP1/CFrontEndUI.hpp index 5f1ad6991..8d6d3e597 100644 --- a/Runtime/MP1/CFrontEndUI.hpp +++ b/Runtime/MP1/CFrontEndUI.hpp @@ -15,8 +15,7 @@ #include "CFrontEndUITouchBar.hpp" #include "CGameOptionsTouchBar.hpp" -namespace urde -{ +namespace urde { class CGuiSliderGroup; class CGuiTableGroup; class CMoviePlayer; @@ -32,437 +31,361 @@ class CGuiWidget; class CGuiTableGroup; class CGuiModel; -namespace MP1 -{ +namespace MP1 { class CNESEmulator; class CSaveGameScreen; class CQuitGameScreen; -class CFrontEndUI : public CIOWin -{ +class CFrontEndUI : public CIOWin { public: - enum class EPhase - { - LoadDepsGroup, - LoadDeps, - LoadFrames, - LoadMovies, - DisplayFrontEnd, - ToPlayGame, - ExitFrontEnd - }; - enum class EScreen - { - OpenCredits, - Title, - AttractMovie, - FileSelect, - FusionBonus, - ToPlayGame - }; - enum class EMenuMovie - { - Stopped = -1, - FirstStart = 0, - StartLoop, - StartFileSelectA, - FileSelectLoop, - FileSelectPlayGameA, - FileSelectGBA, - GBALoop, - GBAFileSelectA, - GBAFileSelectB + enum class EPhase { LoadDepsGroup, LoadDeps, LoadFrames, LoadMovies, DisplayFrontEnd, ToPlayGame, ExitFrontEnd }; + enum class EScreen { OpenCredits, Title, AttractMovie, FileSelect, FusionBonus, ToPlayGame }; + enum class EMenuMovie { + Stopped = -1, + FirstStart = 0, + StartLoop, + StartFileSelectA, + FileSelectLoop, + FileSelectPlayGameA, + FileSelectGBA, + GBALoop, + GBAFileSelectA, + GBAFileSelectB + }; + + static void PlayAdvanceSfx(); + + struct SGuiTextPair { + CGuiTextPane* x0_panes[2] = {}; + void SetPairText(std::u16string_view str); + }; + static SGuiTextPair FindTextPanePair(CGuiFrame* frame, const char* name); + static void FindAndSetPairText(CGuiFrame* frame, const char* name, std::u16string_view str); + + struct SFileMenuOption { + CGuiWidget* x0_base; + + /* filename, world, playtime, date */ + SGuiTextPair x4_textpanes[4]; + + u32 x28_curField = 0; + float x2c_chRate = ComputeRandom(); + + static float ComputeRandom() { return rand() / float(RAND_MAX) * 30.f + 30.f; } + }; + + struct SNewFileSelectFrame { + enum class ESubMenu { Root, EraseGame, EraseGamePopup, NewGamePopup }; + + enum class EAction { None, GameOptions, FusionBonus, SlideShow }; + + u32 x0_rnd; + CSaveGameScreen* x4_saveUI; + ESubMenu x8_subMenu = ESubMenu::Root; + EAction xc_action = EAction::None; + TLockedToken x10_frme; + CGuiFrame* x1c_loadedFrame = nullptr; + CGuiTableGroup* x20_tablegroup_fileselect = nullptr; + CGuiModel* x24_model_erase = nullptr; + SGuiTextPair x28_textpane_erase; + SGuiTextPair x30_textpane_cheats; + SGuiTextPair x38_textpane_gba; + CGuiTableGroup* x40_tablegroup_popup = nullptr; + CGuiModel* x44_model_dash7 = nullptr; + SGuiTextPair x48_textpane_popupadvance; + SGuiTextPair x50_textpane_popupcancel; + SGuiTextPair x58_textpane_popupextra; + CGuiTextPane* x60_textpane_cancel = nullptr; + SFileMenuOption x64_fileSelections[3]; + zeus::CVector3f xf8_model_erase_position; + float x104_rowPitch = 0.f; + float x108_curTime = 0.f; + bool x10c_saveReady = false; + bool x10d_needsEraseToggle = false; + bool x10e_needsNewToggle = false; + + CFrontEndUITouchBar& m_touchBar; + + SNewFileSelectFrame(CSaveGameScreen* sui, u32 rnd, CFrontEndUITouchBar& touchBar); + void FinishedLoading(); + bool PumpLoad(); + bool IsTextDoneAnimating() const; + void Update(float dt); + EAction ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction); + void Draw() const; + + void HandleActiveChange(CGuiTableGroup* active); + void DeactivateEraseGamePopup(); + void ActivateEraseGamePopup(); + void DeactivateNewGamePopup(); + void ActivateNewGamePopup(); + + void ResetFrame(); + void ActivateErase(); + void ClearFrameContents(); + void SetupFrameContents(); + + void DoPopupCancel(CGuiTableGroup* caller); + void DoPopupAdvance(CGuiTableGroup* caller); + void DoFileMenuCancel(CGuiTableGroup* caller); + void DoSelectionChange(CGuiTableGroup* caller, int oldSel); + void DoFileMenuAdvance(CGuiTableGroup* caller); + + static SFileMenuOption FindFileSelectOption(CGuiFrame* frame, int idx); + static void StartTextAnimating(CGuiTextPane* text, std::u16string_view str, float chRate); + }; + + struct SFusionBonusFrame { + struct SGBALinkFrame { + enum class EUIType { + Empty = -1, + InsertPak = 0, + ConnectSocket = 1, + PressStartAndSelect = 2, + BeginLink = 3, + Linking = 4, + LinkFailed = 5, + LinkCompleteOrLinking = 6, + TurnOffGBA = 7, + Complete = 8, + Cancelled = 9 + }; + + enum class EAction { None = 0, Complete = 1, Cancelled = 2 }; + + EUIType x0_uiType; + CGBASupport* x4_gbaSupport; + CGuiFrame* x8_frme; + SGuiTextPair xc_textpane_instructions; + CGuiTextPane* x14_textpane_yes = nullptr; + CGuiTextPane* x18_textpane_no = nullptr; + CGuiModel* x1c_model_gc = nullptr; + CGuiModel* x20_model_gba = nullptr; + CGuiModel* x24_model_cable = nullptr; + CGuiModel* x28_model_circlegcport = nullptr; + CGuiModel* x2c_model_circlegbaport = nullptr; + CGuiModel* x30_model_circlestartselect = nullptr; + CGuiModel* x34_model_pakout = nullptr; + CGuiModel* x38_model_gbascreen = nullptr; + CGuiModel* x3c_model_connect = nullptr; + bool x40_linkInProgress; + + void SetUIText(EUIType tp); + EAction ProcessUserInput(const CFinalInput& input, bool linkInProgress, CFrontEndUITouchBar::EAction tbAction); + void Update(float dt); + void FinishedLoading(); + void Draw(); + SGBALinkFrame(CGuiFrame* linkFrame, CGBASupport* support, bool linkInProgress); }; - static void PlayAdvanceSfx(); + enum class EAction { None, GoBack, PlayNESMetroid }; - struct SGuiTextPair - { - CGuiTextPane* x0_panes[2] = {}; - void SetPairText(std::u16string_view str); - }; - static SGuiTextPair FindTextPanePair(CGuiFrame* frame, const char* name); - static void FindAndSetPairText(CGuiFrame* frame, const char* name, std::u16string_view str); + std::unique_ptr x0_gbaLinkFrame; + std::unique_ptr x4_gbaSupport; + EAction x8_action = EAction::None; + TLockedToken xc_gbaScreen; + TLockedToken x18_gbaLink; + CGuiFrame* x24_loadedFrame = nullptr; + CGuiTableGroup* x28_tablegroup_options = nullptr; + CGuiTableGroup* x2c_tablegroup_fusionsuit = nullptr; + SGuiTextPair x30_textpane_instructions; + bool x38_lastDoDraw = false; + bool x39_fusionNotComplete = false; + bool x3a_mpNotComplete = false; - struct SFileMenuOption - { - CGuiWidget* x0_base; + CFrontEndUITouchBar& m_touchBar; - /* filename, world, playtime, date */ - SGuiTextPair x4_textpanes[4]; + bool m_gbaOverride = false; - u32 x28_curField = 0; - float x2c_chRate = ComputeRandom(); + SFusionBonusFrame(CFrontEndUITouchBar& touchBar); + void FinishedLoading(); + bool PumpLoad(); + void SetTableColors(CGuiTableGroup* tbgp) const; + void Update(float dt, CSaveGameScreen* saveUI); + EAction ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui, CFrontEndUITouchBar::EAction tbAction); + void Draw() const; - static float ComputeRandom() - { - return rand() / float(RAND_MAX) * 30.f + 30.f; - } - }; - - struct SNewFileSelectFrame - { - enum class ESubMenu - { - Root, - EraseGame, - EraseGamePopup, - NewGamePopup - }; - - enum class EAction - { - None, - GameOptions, - FusionBonus, - SlideShow - }; - - u32 x0_rnd; - CSaveGameScreen* x4_saveUI; - ESubMenu x8_subMenu = ESubMenu::Root; - EAction xc_action = EAction::None; - TLockedToken x10_frme; - CGuiFrame* x1c_loadedFrame = nullptr; - CGuiTableGroup* x20_tablegroup_fileselect = nullptr; - CGuiModel* x24_model_erase = nullptr; - SGuiTextPair x28_textpane_erase; - SGuiTextPair x30_textpane_cheats; - SGuiTextPair x38_textpane_gba; - CGuiTableGroup* x40_tablegroup_popup = nullptr; - CGuiModel* x44_model_dash7 = nullptr; - SGuiTextPair x48_textpane_popupadvance; - SGuiTextPair x50_textpane_popupcancel; - SGuiTextPair x58_textpane_popupextra; - CGuiTextPane* x60_textpane_cancel = nullptr; - SFileMenuOption x64_fileSelections[3]; - zeus::CVector3f xf8_model_erase_position; - float x104_rowPitch = 0.f; - float x108_curTime = 0.f; - bool x10c_saveReady = false; - bool x10d_needsEraseToggle = false; - bool x10e_needsNewToggle = false; - - CFrontEndUITouchBar& m_touchBar; - - SNewFileSelectFrame(CSaveGameScreen* sui, u32 rnd, CFrontEndUITouchBar& touchBar); - void FinishedLoading(); - bool PumpLoad(); - bool IsTextDoneAnimating() const; - void Update(float dt); - EAction ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction); - void Draw() const; - - void HandleActiveChange(CGuiTableGroup* active); - void DeactivateEraseGamePopup(); - void ActivateEraseGamePopup(); - void DeactivateNewGamePopup(); - void ActivateNewGamePopup(); - - void ResetFrame(); - void ActivateErase(); - void ClearFrameContents(); - void SetupFrameContents(); - - void DoPopupCancel(CGuiTableGroup* caller); - void DoPopupAdvance(CGuiTableGroup* caller); - void DoFileMenuCancel(CGuiTableGroup* caller); - void DoSelectionChange(CGuiTableGroup* caller, int oldSel); - void DoFileMenuAdvance(CGuiTableGroup* caller); - - static SFileMenuOption FindFileSelectOption(CGuiFrame* frame, int idx); - static void StartTextAnimating(CGuiTextPane* text, std::u16string_view str, float chRate); - }; - - struct SFusionBonusFrame - { - struct SGBALinkFrame - { - enum class EUIType - { - Empty = -1, - InsertPak = 0, - ConnectSocket = 1, - PressStartAndSelect = 2, - BeginLink = 3, - Linking = 4, - LinkFailed = 5, - LinkCompleteOrLinking = 6, - TurnOffGBA = 7, - Complete = 8, - Cancelled = 9 - }; - - enum class EAction - { - None = 0, - Complete = 1, - Cancelled = 2 - }; - - EUIType x0_uiType; - CGBASupport* x4_gbaSupport; - CGuiFrame* x8_frme; - SGuiTextPair xc_textpane_instructions; - CGuiTextPane* x14_textpane_yes = nullptr; - CGuiTextPane* x18_textpane_no = nullptr; - CGuiModel* x1c_model_gc = nullptr; - CGuiModel* x20_model_gba = nullptr; - CGuiModel* x24_model_cable = nullptr; - CGuiModel* x28_model_circlegcport = nullptr; - CGuiModel* x2c_model_circlegbaport = nullptr; - CGuiModel* x30_model_circlestartselect = nullptr; - CGuiModel* x34_model_pakout = nullptr; - CGuiModel* x38_model_gbascreen = nullptr; - CGuiModel* x3c_model_connect = nullptr; - bool x40_linkInProgress; - - void SetUIText(EUIType tp); - EAction ProcessUserInput(const CFinalInput &input, bool linkInProgress, - CFrontEndUITouchBar::EAction tbAction); - void Update(float dt); - void FinishedLoading(); - void Draw(); - SGBALinkFrame(CGuiFrame* linkFrame, CGBASupport* support, bool linkInProgress); - }; - - enum class EAction - { - None, - GoBack, - PlayNESMetroid - }; - - std::unique_ptr x0_gbaLinkFrame; - std::unique_ptr x4_gbaSupport; - EAction x8_action = EAction::None; - TLockedToken xc_gbaScreen; - TLockedToken x18_gbaLink; - CGuiFrame* x24_loadedFrame = nullptr; - CGuiTableGroup* x28_tablegroup_options = nullptr; - CGuiTableGroup* x2c_tablegroup_fusionsuit = nullptr; - SGuiTextPair x30_textpane_instructions; - bool x38_lastDoDraw = false; - bool x39_fusionNotComplete = false; - bool x3a_mpNotComplete = false; - - CFrontEndUITouchBar& m_touchBar; - - bool m_gbaOverride = false; - - SFusionBonusFrame(CFrontEndUITouchBar& touchBar); - void FinishedLoading(); - bool PumpLoad(); - void SetTableColors(CGuiTableGroup* tbgp) const; - void Update(float dt, CSaveGameScreen* saveUI); - EAction ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui, - CFrontEndUITouchBar::EAction tbAction); - void Draw() const; - - void ResetCompletionFlags() - { - x39_fusionNotComplete = false; - x3a_mpNotComplete = false; - } - - void DoCancel(CGuiTableGroup* caller); - void DoSelectionChange(CGuiTableGroup* caller, int oldSel); - void DoAdvance(CGuiTableGroup* caller); - }; - - struct SFrontEndFrame - { - enum class EAction - { - None, - StartGame, - FusionBonus, - GameOptions, - SlideShow - }; - - u32 x0_rnd; - EAction x4_action; - TLockedToken x8_frme; - CGuiFrame* x14_loadedFrme = nullptr; - CGuiTableGroup* x18_tablegroup_mainmenu = nullptr; - SGuiTextPair x1c_gbaPair; - SGuiTextPair x24_cheatPair; - - CFrontEndUITouchBar& m_touchBar; - - SFrontEndFrame(u32 rnd, CFrontEndUITouchBar& touchBar); - void FinishedLoading(); - bool PumpLoad(); - void Update(float dt); - EAction ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction); - void Draw() const; - void HandleActiveChange(CGuiTableGroup* active); - - void DoCancel(CGuiTableGroup* caller); - void DoSelectionChange(CGuiTableGroup* caller, int oldSel); - void DoAdvance(CGuiTableGroup* caller); - }; - - struct SNesEmulatorFrame - { - enum class EMode - { - Emulator, - SaveProgress, - ContinuePlaying, - QuitNESMetroid - }; - - EMode x0_mode = EMode::Emulator; - std::unique_ptr x4_nesEmu; - std::unique_ptr x8_quitScreen; - std::unique_ptr xc_textSupport; - float x10_remTime = 8.f; - bool x14_emulationSuspended = false; - bool x15_enableFiltering = true; - - SNesEmulatorFrame(); - void SetMode(EMode mode); - void ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui); - bool Update(float dt, CSaveGameScreen* saveUi); - void Draw(CSaveGameScreen* saveUi) const; - }; - - struct SOptionsFrontEndFrame - { - float x0_uiAlpha = 0.f; - TLockedToken x4_frme; - TLockedToken x10_pauseScreen; - CGuiFrame* x1c_loadedFrame = nullptr; - CStringTable* x20_loadedPauseStrg = nullptr; - CGuiTableGroup* x24_tablegroup_leftmenu = nullptr; - CGuiTableGroup* x28_tablegroup_rightmenu = nullptr; - CGuiTableGroup* x2c_tablegroup_double = nullptr; - CGuiTableGroup* x30_tablegroup_triple = nullptr; - CGuiSliderGroup* x34_slidergroup_slider = nullptr; - float x38_rowPitch = 0.f; - CSfxHandle x3c_sliderSfx; - CRumbleGenerator x40_rumbleGen; - union - { - u8 _dummy = 0; - struct - { - bool x134_24_visible : 1; - bool x134_25_exitOptions : 1; - }; - }; - - std::unique_ptr m_touchBar; - bool m_touchBarInValue = false; - bool m_touchBarValueDirty = false; - - SOptionsFrontEndFrame(); - - void DoSliderChange(CGuiSliderGroup* caller, float value); - void DoMenuCancel(CGuiTableGroup* caller); - void DoMenuSelectionChange(CGuiTableGroup* caller, int oldSel); - void DoLeftMenuAdvance(CGuiTableGroup* caller); - - void DeactivateRightMenu(); - void HandleRightSelectionChange(); - - void SetRightUIText(); - void SetTableColors(CGuiTableGroup* tbgp) const; - void FinishedLoading(); - bool PumpLoad(); - - bool ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui); - void Update(float dt, CSaveGameScreen* saveUi); - void Draw() const; - }; - - bool CanShowSaveUI() const - { - if (x50_curScreen != EScreen::FileSelect && x50_curScreen != EScreen::FusionBonus) - return false; - if (x54_nextScreen != EScreen::FileSelect && x54_nextScreen != EScreen::FusionBonus) - return false; - return true; + void ResetCompletionFlags() { + x39_fusionNotComplete = false; + x3a_mpNotComplete = false; } + void DoCancel(CGuiTableGroup* caller); + void DoSelectionChange(CGuiTableGroup* caller, int oldSel); + void DoAdvance(CGuiTableGroup* caller); + }; + + struct SFrontEndFrame { + enum class EAction { None, StartGame, FusionBonus, GameOptions, SlideShow }; + + u32 x0_rnd; + EAction x4_action; + TLockedToken x8_frme; + CGuiFrame* x14_loadedFrme = nullptr; + CGuiTableGroup* x18_tablegroup_mainmenu = nullptr; + SGuiTextPair x1c_gbaPair; + SGuiTextPair x24_cheatPair; + + CFrontEndUITouchBar& m_touchBar; + + SFrontEndFrame(u32 rnd, CFrontEndUITouchBar& touchBar); + void FinishedLoading(); + bool PumpLoad(); + void Update(float dt); + EAction ProcessUserInput(const CFinalInput& input, CFrontEndUITouchBar::EAction tbAction); + void Draw() const; + void HandleActiveChange(CGuiTableGroup* active); + + void DoCancel(CGuiTableGroup* caller); + void DoSelectionChange(CGuiTableGroup* caller, int oldSel); + void DoAdvance(CGuiTableGroup* caller); + }; + + struct SNesEmulatorFrame { + enum class EMode { Emulator, SaveProgress, ContinuePlaying, QuitNESMetroid }; + + EMode x0_mode = EMode::Emulator; + std::unique_ptr x4_nesEmu; + std::unique_ptr x8_quitScreen; + std::unique_ptr xc_textSupport; + float x10_remTime = 8.f; + bool x14_emulationSuspended = false; + bool x15_enableFiltering = true; + + SNesEmulatorFrame(); + void SetMode(EMode mode); + void ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui); + bool Update(float dt, CSaveGameScreen* saveUi); + void Draw(CSaveGameScreen* saveUi) const; + }; + + struct SOptionsFrontEndFrame { + float x0_uiAlpha = 0.f; + TLockedToken x4_frme; + TLockedToken x10_pauseScreen; + CGuiFrame* x1c_loadedFrame = nullptr; + CStringTable* x20_loadedPauseStrg = nullptr; + CGuiTableGroup* x24_tablegroup_leftmenu = nullptr; + CGuiTableGroup* x28_tablegroup_rightmenu = nullptr; + CGuiTableGroup* x2c_tablegroup_double = nullptr; + CGuiTableGroup* x30_tablegroup_triple = nullptr; + CGuiSliderGroup* x34_slidergroup_slider = nullptr; + float x38_rowPitch = 0.f; + CSfxHandle x3c_sliderSfx; + CRumbleGenerator x40_rumbleGen; + union { + u8 _dummy = 0; + struct { + bool x134_24_visible : 1; + bool x134_25_exitOptions : 1; + }; + }; + + std::unique_ptr m_touchBar; + bool m_touchBarInValue = false; + bool m_touchBarValueDirty = false; + + SOptionsFrontEndFrame(); + + void DoSliderChange(CGuiSliderGroup* caller, float value); + void DoMenuCancel(CGuiTableGroup* caller); + void DoMenuSelectionChange(CGuiTableGroup* caller, int oldSel); + void DoLeftMenuAdvance(CGuiTableGroup* caller); + + void DeactivateRightMenu(); + void HandleRightSelectionChange(); + + void SetRightUIText(); + void SetTableColors(CGuiTableGroup* tbgp) const; + void FinishedLoading(); + bool PumpLoad(); + + bool ProcessUserInput(const CFinalInput& input, CSaveGameScreen* sui); + void Update(float dt, CSaveGameScreen* saveUi); + void Draw() const; + }; + + bool CanShowSaveUI() const { + if (x50_curScreen != EScreen::FileSelect && x50_curScreen != EScreen::FusionBonus) + return false; + if (x54_nextScreen != EScreen::FileSelect && x54_nextScreen != EScreen::FusionBonus) + return false; + return true; + } + private: - EPhase x14_phase = EPhase::LoadDepsGroup; - u32 x18_rndA; - u32 x1c_rndB; - TLockedToken x20_depsGroup; - std::vector x2c_deps; - TLockedToken x38_pressStart; - TLockedToken x44_frontendAudioGrp; - EScreen x50_curScreen = EScreen::OpenCredits; - EScreen x54_nextScreen = EScreen::OpenCredits; - float x58_fadeBlackTimer = 0.f; - bool x5c_fadeBlackWithMovie = false; - float x60_pressStartTime = 0.f; - float x64_pressStartAlpha = 0.f; - float x68_musicVol = 1.f; - u32 x6c_; - std::unique_ptr x70_menuMovies[9]; - EMenuMovie xb8_curMovie = EMenuMovie::Stopped; - int xbc_nextAttract = 0; - int xc0_attractCount = 0; - std::unique_ptr xc4_attractMovie; - CMoviePlayer* xcc_curMoviePtr = nullptr; - bool xd0_playerSkipToTitle = false; - bool xd1_moviesLoaded = false; - bool xd2_deferSlideShow = false; - std::unique_ptr xd4_audio1; - std::unique_ptr xd8_audio2; - std::unique_ptr xdc_saveUI; - std::unique_ptr xe0_frontendCardFrme; - std::unique_ptr xe4_fusionBonusFrme; - std::unique_ptr xe8_frontendNoCardFrme; - std::unique_ptr xec_emuFrme; - std::unique_ptr xf0_optionsFrme; - CStaticAudioPlayer* xf4_curAudio = nullptr; + EPhase x14_phase = EPhase::LoadDepsGroup; + u32 x18_rndA; + u32 x1c_rndB; + TLockedToken x20_depsGroup; + std::vector x2c_deps; + TLockedToken x38_pressStart; + TLockedToken x44_frontendAudioGrp; + EScreen x50_curScreen = EScreen::OpenCredits; + EScreen x54_nextScreen = EScreen::OpenCredits; + float x58_fadeBlackTimer = 0.f; + bool x5c_fadeBlackWithMovie = false; + float x60_pressStartTime = 0.f; + float x64_pressStartAlpha = 0.f; + float x68_musicVol = 1.f; + u32 x6c_; + std::unique_ptr x70_menuMovies[9]; + EMenuMovie xb8_curMovie = EMenuMovie::Stopped; + int xbc_nextAttract = 0; + int xc0_attractCount = 0; + std::unique_ptr xc4_attractMovie; + CMoviePlayer* xcc_curMoviePtr = nullptr; + bool xd0_playerSkipToTitle = false; + bool xd1_moviesLoaded = false; + bool xd2_deferSlideShow = false; + std::unique_ptr xd4_audio1; + std::unique_ptr xd8_audio2; + std::unique_ptr xdc_saveUI; + std::unique_ptr xe0_frontendCardFrme; + std::unique_ptr xe4_fusionBonusFrme; + std::unique_ptr xe8_frontendNoCardFrme; + std::unique_ptr xec_emuFrme; + std::unique_ptr xf0_optionsFrme; + CStaticAudioPlayer* xf4_curAudio = nullptr; - CColoredQuadFilter m_fadeToBlack = {EFilterType::Blend}; - std::experimental::optional m_pressStartQuad; + CColoredQuadFilter m_fadeToBlack = {EFilterType::Blend}; + std::experimental::optional m_pressStartQuad; - std::unique_ptr m_touchBar; + std::unique_ptr m_touchBar; - void SetFadeBlackWithMovie() - { - x58_fadeBlackTimer = 1000000.f; - x5c_fadeBlackWithMovie = true; - } + void SetFadeBlackWithMovie() { + x58_fadeBlackTimer = 1000000.f; + x5c_fadeBlackWithMovie = true; + } - void SetFadeBlackTimer(float seconds) - { - x58_fadeBlackTimer = seconds; - x5c_fadeBlackWithMovie = false; - } + void SetFadeBlackTimer(float seconds) { + x58_fadeBlackTimer = seconds; + x5c_fadeBlackWithMovie = false; + } + + void TransitionToGame(); + void UpdateMusicVolume(); + void FinishedLoadingDepsGroup(); + bool PumpLoad(); - void TransitionToGame(); - void UpdateMusicVolume(); - void FinishedLoadingDepsGroup(); - bool PumpLoad(); public: - - CFrontEndUI(); - void StartSlideShow(CArchitectureQueue& queue); - std::string GetAttractMovieFileName(int idx); - std::string GetNextAttractMovieFileName(); - void SetCurrentMovie(EMenuMovie movie); - void StopAttractMovie(); - void StartAttractMovie(); - void StartStateTransition(EScreen screen); - void CompleteStateTransition(); - void HandleDebugMenuReturnValue(CGameDebug::EReturnValue val, CArchitectureQueue& queue); - void Draw() const; - void UpdateMovies(float dt); - bool PumpMovieLoad(); - void ProcessUserInput(const CFinalInput& input, CArchitectureQueue& queue); - EMessageReturn Update(float dt, CArchitectureQueue& queue); - EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); + CFrontEndUI(); + void StartSlideShow(CArchitectureQueue& queue); + std::string GetAttractMovieFileName(int idx); + std::string GetNextAttractMovieFileName(); + void SetCurrentMovie(EMenuMovie movie); + void StopAttractMovie(); + void StartAttractMovie(); + void StartStateTransition(EScreen screen); + void CompleteStateTransition(); + void HandleDebugMenuReturnValue(CGameDebug::EReturnValue val, CArchitectureQueue& queue); + void Draw() const; + void UpdateMovies(float dt); + bool PumpMovieLoad(); + void ProcessUserInput(const CFinalInput& input, CArchitectureQueue& queue); + EMessageReturn Update(float dt, CArchitectureQueue& queue); + EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CFrontEndUITouchBar.cpp b/Runtime/MP1/CFrontEndUITouchBar.cpp index 08a14d685..bbdf82b0b 100644 --- a/Runtime/MP1/CFrontEndUITouchBar.cpp +++ b/Runtime/MP1/CFrontEndUITouchBar.cpp @@ -1,27 +1,20 @@ #include "CFrontEndUITouchBar.hpp" -namespace urde -{ +namespace urde { CFrontEndUITouchBar::~CFrontEndUITouchBar() {} void CFrontEndUITouchBar::SetPhase(EPhase ph) { m_phase = ph; } CFrontEndUITouchBar::EPhase CFrontEndUITouchBar::GetPhase() { return m_phase; } -void CFrontEndUITouchBar::SetFileSelectPhase(const SFileSelectDetail details[3], - bool eraseGame, bool galleryActive) -{ m_phase = EPhase::FileSelect; } -void CFrontEndUITouchBar::SetNoCardSelectPhase(bool galleryActive) -{ m_phase = EPhase::NoCardSelect; } -void CFrontEndUITouchBar::SetFusionBonusPhase(bool fusionSuitActive) -{ m_phase = EPhase::FusionBonus; } -void CFrontEndUITouchBar::SetStartOptionsPhase(bool normalBeat) -{ m_phase = EPhase::StartOptions; } +void CFrontEndUITouchBar::SetFileSelectPhase(const SFileSelectDetail details[3], bool eraseGame, bool galleryActive) { + m_phase = EPhase::FileSelect; +} +void CFrontEndUITouchBar::SetNoCardSelectPhase(bool galleryActive) { m_phase = EPhase::NoCardSelect; } +void CFrontEndUITouchBar::SetFusionBonusPhase(bool fusionSuitActive) { m_phase = EPhase::FusionBonus; } +void CFrontEndUITouchBar::SetStartOptionsPhase(bool normalBeat) { m_phase = EPhase::StartOptions; } CFrontEndUITouchBar::EAction CFrontEndUITouchBar::PopAction() { return EAction::None; } #ifndef __APPLE__ -std::unique_ptr NewFrontEndUITouchBar() -{ - return std::make_unique(); -} +std::unique_ptr NewFrontEndUITouchBar() { return std::make_unique(); } #endif -} +} // namespace urde diff --git a/Runtime/MP1/CFrontEndUITouchBar.hpp b/Runtime/MP1/CFrontEndUITouchBar.hpp index 1a495961c..7d74abffa 100644 --- a/Runtime/MP1/CFrontEndUITouchBar.hpp +++ b/Runtime/MP1/CFrontEndUITouchBar.hpp @@ -2,69 +2,48 @@ #include -namespace urde -{ +namespace urde { -class CFrontEndUITouchBar -{ +class CFrontEndUITouchBar { public: - enum class EPhase - { - None, - PressStart, - ProceedBack, - StartOptions, - EraseBack, - FileSelect, - NoCardSelect, - FusionBonus - }; - enum class EAction - { - None, - Start, - Normal, - Hard, - Back, - Confirm, - Options, - FileA, - FileB, - FileC, - Erase, - FusionBonus, - ImageGallery, - NESMetroid, - FusionSuit - }; - enum class EFileState - { - New, - Normal, - Hard - }; - struct SFileSelectDetail - { - EFileState state; - int percent; - }; + enum class EPhase { None, PressStart, ProceedBack, StartOptions, EraseBack, FileSelect, NoCardSelect, FusionBonus }; + enum class EAction { + None, + Start, + Normal, + Hard, + Back, + Confirm, + Options, + FileA, + FileB, + FileC, + Erase, + FusionBonus, + ImageGallery, + NESMetroid, + FusionSuit + }; + enum class EFileState { New, Normal, Hard }; + struct SFileSelectDetail { + EFileState state; + int percent; + }; protected: - EPhase m_phase = EPhase::None; + EPhase m_phase = EPhase::None; public: - virtual ~CFrontEndUITouchBar(); - virtual void SetPhase(EPhase ph); - virtual EPhase GetPhase(); - virtual void SetFileSelectPhase(const SFileSelectDetail details[3], - bool eraseGame, bool galleryActive); - virtual void SetNoCardSelectPhase(bool galleryActive); - virtual void SetFusionBonusPhase(bool fusionSuitActive); - virtual void SetStartOptionsPhase(bool normalBeat); - virtual EAction PopAction(); + virtual ~CFrontEndUITouchBar(); + virtual void SetPhase(EPhase ph); + virtual EPhase GetPhase(); + virtual void SetFileSelectPhase(const SFileSelectDetail details[3], bool eraseGame, bool galleryActive); + virtual void SetNoCardSelectPhase(bool galleryActive); + virtual void SetFusionBonusPhase(bool fusionSuitActive); + virtual void SetStartOptionsPhase(bool normalBeat); + virtual EAction PopAction(); }; std::unique_ptr NewFrontEndUITouchBar(); -} - +} // namespace urde diff --git a/Runtime/MP1/CGBASupport.cpp b/Runtime/MP1/CGBASupport.cpp index 23585bb5c..6aa2d758d 100644 --- a/Runtime/MP1/CGBASupport.cpp +++ b/Runtime/MP1/CGBASupport.cpp @@ -4,226 +4,202 @@ #include "jbus/Listener.hpp" #include "jbus/Endpoint.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { static jbus::Listener g_JbusListener; static std::unique_ptr g_JbusEndpoint; -void CGBASupport::Initialize() -{ - jbus::Initialize(); - g_JbusListener.start(); +void CGBASupport::Initialize() { + jbus::Initialize(); + g_JbusListener.start(); } -void CGBASupport::GlobalPoll() -{ - if (g_JbusEndpoint && !g_JbusEndpoint->connected()) - g_JbusEndpoint.reset(); - if (!g_JbusEndpoint) - { - g_JbusEndpoint = g_JbusListener.accept(); - if (g_JbusEndpoint) - g_JbusEndpoint->setChan(3); +void CGBASupport::GlobalPoll() { + if (g_JbusEndpoint && !g_JbusEndpoint->connected()) + g_JbusEndpoint.reset(); + if (!g_JbusEndpoint) { + g_JbusEndpoint = g_JbusListener.accept(); + if (g_JbusEndpoint) + g_JbusEndpoint->setChan(3); + } +} + +CGBASupport::CGBASupport() : CDvdFile("client_pad.bin") { + x28_fileSize = ROUND_UP_32(Length()); + x2c_buffer.reset(new u8[x28_fileSize]); + x30_dvdReq = AsyncRead(x2c_buffer.get(), x28_fileSize); +} + +CGBASupport::~CGBASupport() { + if (x30_dvdReq) + x30_dvdReq->PostCancelRequest(); +} + +u8 CGBASupport::CalculateFusionJBusChecksum(const u8* data, size_t len) { + u32 sum = -1; + for (int i = 0; i < len; ++i) { + u8 ch = *data++; + sum ^= ch; + for (int j = 0; j < 8; ++j) { + if ((sum & 1)) { + sum >>= 1; + sum ^= 0xb010; + } else + sum >>= 1; } + } + return sum; } -CGBASupport::CGBASupport() -: CDvdFile("client_pad.bin") -{ - x28_fileSize = ROUND_UP_32(Length()); - x2c_buffer.reset(new u8[x28_fileSize]); - x30_dvdReq = AsyncRead(x2c_buffer.get(), x28_fileSize); -} +bool CGBASupport::PollResponse() { + if (!g_JbusEndpoint) + return false; -CGBASupport::~CGBASupport() -{ - if (x30_dvdReq) - x30_dvdReq->PostCancelRequest(); -} - -u8 CGBASupport::CalculateFusionJBusChecksum(const u8* data, size_t len) -{ - u32 sum = -1; - for (int i = 0 ; i < len; ++i) - { - u8 ch = *data++; - sum ^= ch; - for (int j = 0; j < 8; ++j) - { - if ((sum & 1)) - { - sum >>= 1; - sum ^= 0xb010; - } - else - sum >>= 1; - } - } - return sum; -} - -bool CGBASupport::PollResponse() -{ - if (!g_JbusEndpoint) - return false; - - u8 status; + u8 status; + if (g_JbusEndpoint->GBAReset(&status) == jbus::GBA_NOT_READY) if (g_JbusEndpoint->GBAReset(&status) == jbus::GBA_NOT_READY) - if (g_JbusEndpoint->GBAReset(&status) == jbus::GBA_NOT_READY) - return false; + return false; + + if (g_JbusEndpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) + return false; + if (status != (jbus::GBA_JSTAT_PSF1 | jbus::GBA_JSTAT_SEND)) + return false; + + u8 bytes[4]; + if (g_JbusEndpoint->GBARead(bytes, &status) == jbus::GBA_NOT_READY) + return false; + if (reinterpret_cast(bytes) != SBIG('AMTE')) + return false; + + if (g_JbusEndpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) + return false; + if (status != jbus::GBA_JSTAT_PSF1) + return false; + + if (g_JbusEndpoint->GBAWrite((unsigned char*)"AMTE", &status) == jbus::GBA_NOT_READY) + return false; + + if (g_JbusEndpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) + return false; + if ((status & jbus::GBA_JSTAT_FLAGS_MASK) != jbus::GBA_JSTAT_FLAGS_MASK) + return false; + + u64 profStart = jbus::GetGCTicks(); + const u64 timeToSpin = jbus::GetGCTicksPerSec() / 8000; + for (;;) { + u64 curTime = jbus::GetGCTicks(); + if (curTime - profStart > timeToSpin) + return true; if (g_JbusEndpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - return false; - if (status != (jbus::GBA_JSTAT_PSF1 | jbus::GBA_JSTAT_SEND)) - return false; - - u8 bytes[4]; - if (g_JbusEndpoint->GBARead(bytes, &status) == jbus::GBA_NOT_READY) - return false; - if (reinterpret_cast(bytes) != SBIG('AMTE')) - return false; + continue; + if (!(status & jbus::GBA_JSTAT_SEND)) + continue; if (g_JbusEndpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - return false; - if (status != jbus::GBA_JSTAT_PSF1) - return false; + continue; + if (status != (jbus::GBA_JSTAT_FLAGS_MASK | jbus::GBA_JSTAT_SEND)) + continue; + break; + } - if (g_JbusEndpoint->GBAWrite((unsigned char*)"AMTE", &status) == jbus::GBA_NOT_READY) - return false; + if (g_JbusEndpoint->GBARead(bytes, &status) != jbus::GBA_READY) + return false; - if (g_JbusEndpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - return false; - if ((status & jbus::GBA_JSTAT_FLAGS_MASK) != jbus::GBA_JSTAT_FLAGS_MASK) - return false; + if (bytes[3] != CalculateFusionJBusChecksum(bytes, 3)) + return false; - u64 profStart = jbus::GetGCTicks(); - const u64 timeToSpin = jbus::GetGCTicksPerSec() / 8000; - for (;;) - { - u64 curTime = jbus::GetGCTicks(); - if (curTime - profStart > timeToSpin) - return true; + x44_fusionLinked = (bytes[2] & 0x2) == 0; + if (x44_fusionLinked && (bytes[2] & 0x1) != 0) + x45_fusionBeat = true; - if (g_JbusEndpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - continue; - if (!(status & jbus::GBA_JSTAT_SEND)) - continue; - - if (g_JbusEndpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - continue; - if (status != (jbus::GBA_JSTAT_FLAGS_MASK | jbus::GBA_JSTAT_SEND)) - continue; - break; - } - - if (g_JbusEndpoint->GBARead(bytes, &status) != jbus::GBA_READY) - return false; - - if (bytes[3] != CalculateFusionJBusChecksum(bytes, 3)) - return false; - - x44_fusionLinked = (bytes[2] & 0x2) == 0; - if (x44_fusionLinked && (bytes[2] & 0x1) != 0) - x45_fusionBeat = true; - - return true; + return true; } static void JoyBootDone(jbus::ThreadLocalEndpoint& endpoint, jbus::EJoyReturn status) {} -void CGBASupport::Update(float dt) -{ - switch (x34_phase) - { - case EPhase::LoadClientPad: - IsReady(); - break; +void CGBASupport::Update(float dt) { + switch (x34_phase) { + case EPhase::LoadClientPad: + IsReady(); + break; - case EPhase::StartProbeTimeout: - x38_timeout = 4.f; - x34_phase = EPhase::PollProbe; + case EPhase::StartProbeTimeout: + x38_timeout = 4.f; + x34_phase = EPhase::PollProbe; - case EPhase::PollProbe: - /* SIProbe poll normally occurs here with 4 second timeout */ - if (!g_JbusEndpoint) - { - x34_phase = EPhase::Failed; - break; - } - x40_siChan = g_JbusEndpoint->getChan(); - x34_phase = EPhase::StartJoyBusBoot; - - case EPhase::StartJoyBusBoot: - x34_phase = EPhase::PollJoyBusBoot; - if (!g_JbusEndpoint || g_JbusEndpoint->GBAJoyBootAsync(x40_siChan * 2, 2, - x2c_buffer.get(), x28_fileSize, &x3c_status, - std::bind(JoyBootDone, - std::placeholders::_1, - std::placeholders::_2)) != jbus::GBA_READY) - x34_phase = EPhase::Failed; - break; - - case EPhase::PollJoyBusBoot: - u8 percent; - if (g_JbusEndpoint && g_JbusEndpoint->GBAGetProcessStatus(percent) == jbus::GBA_BUSY) - break; - if (!g_JbusEndpoint || g_JbusEndpoint->GBAGetStatus(&x3c_status) == jbus::GBA_NOT_READY) - { - x34_phase = EPhase::Failed; - break; - } - x38_timeout = 4.f; - x34_phase = EPhase::DataTransfer; - break; - - case EPhase::DataTransfer: - if (PollResponse()) - { - x34_phase = EPhase::Complete; - break; - } - x38_timeout = std::max(0.f, x38_timeout - dt); - if (x38_timeout == 0.f) - x34_phase = EPhase::Failed; - break; - - default: break; + case EPhase::PollProbe: + /* SIProbe poll normally occurs here with 4 second timeout */ + if (!g_JbusEndpoint) { + x34_phase = EPhase::Failed; + break; } + x40_siChan = g_JbusEndpoint->getChan(); + x34_phase = EPhase::StartJoyBusBoot; + + case EPhase::StartJoyBusBoot: + x34_phase = EPhase::PollJoyBusBoot; + if (!g_JbusEndpoint || g_JbusEndpoint->GBAJoyBootAsync( + x40_siChan * 2, 2, x2c_buffer.get(), x28_fileSize, &x3c_status, + std::bind(JoyBootDone, std::placeholders::_1, std::placeholders::_2)) != jbus::GBA_READY) + x34_phase = EPhase::Failed; + break; + + case EPhase::PollJoyBusBoot: + u8 percent; + if (g_JbusEndpoint && g_JbusEndpoint->GBAGetProcessStatus(percent) == jbus::GBA_BUSY) + break; + if (!g_JbusEndpoint || g_JbusEndpoint->GBAGetStatus(&x3c_status) == jbus::GBA_NOT_READY) { + x34_phase = EPhase::Failed; + break; + } + x38_timeout = 4.f; + x34_phase = EPhase::DataTransfer; + break; + + case EPhase::DataTransfer: + if (PollResponse()) { + x34_phase = EPhase::Complete; + break; + } + x38_timeout = std::max(0.f, x38_timeout - dt); + if (x38_timeout == 0.f) + x34_phase = EPhase::Failed; + break; + + default: + break; + } } -bool CGBASupport::IsReady() -{ - if (x34_phase != EPhase::LoadClientPad) - return true; +bool CGBASupport::IsReady() { + if (x34_phase != EPhase::LoadClientPad) + return true; - if (x30_dvdReq->IsComplete()) - { - x30_dvdReq.reset(); - x34_phase = EPhase::Standby; - /* Conveniently already little-endian */ - reinterpret_cast(x2c_buffer[0xc8]) = u32(CBasics::GetGCTicks()); - x2c_buffer[0xaf] = 'E'; - x2c_buffer[0xbd] = 0xc9; - return true; - } - return false; -} - -void CGBASupport::InitializeSupport() -{ + if (x30_dvdReq->IsComplete()) { + x30_dvdReq.reset(); x34_phase = EPhase::Standby; - x38_timeout = 0.f; - x3c_status = false; - x40_siChan = -1; - x44_fusionLinked = false; - x45_fusionBeat = false; + /* Conveniently already little-endian */ + reinterpret_cast(x2c_buffer[0xc8]) = u32(CBasics::GetGCTicks()); + x2c_buffer[0xaf] = 'E'; + x2c_buffer[0xbd] = 0xc9; + return true; + } + return false; } -void CGBASupport::StartLink() -{ - x34_phase = EPhase::StartProbeTimeout; - x40_siChan = -1; +void CGBASupport::InitializeSupport() { + x34_phase = EPhase::Standby; + x38_timeout = 0.f; + x3c_status = false; + x40_siChan = -1; + x44_fusionLinked = false; + x45_fusionBeat = false; } +void CGBASupport::StartLink() { + x34_phase = EPhase::StartProbeTimeout; + x40_siChan = -1; } + +} // namespace urde::MP1 diff --git a/Runtime/MP1/CGBASupport.hpp b/Runtime/MP1/CGBASupport.hpp index 69bad1bed..16c791651 100644 --- a/Runtime/MP1/CGBASupport.hpp +++ b/Runtime/MP1/CGBASupport.hpp @@ -2,53 +2,49 @@ #include "CDvdFile.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class CGBASupport : public CDvdFile -{ +class CGBASupport : public CDvdFile { public: - enum class EPhase - { - LoadClientPad, - Standby, - StartProbeTimeout, - PollProbe, - StartJoyBusBoot, - PollJoyBusBoot, - DataTransfer, - Complete, - Failed - }; + enum class EPhase { + LoadClientPad, + Standby, + StartProbeTimeout, + PollProbe, + StartJoyBusBoot, + PollJoyBusBoot, + DataTransfer, + Complete, + Failed + }; private: - u32 x28_fileSize; - std::unique_ptr x2c_buffer; - EPhase x34_phase = EPhase::LoadClientPad; - float x38_timeout = 0.f; - std::shared_ptr x30_dvdReq; - u8 x3c_status = 0; - u32 x40_siChan = -1; - bool x44_fusionLinked = false; - bool x45_fusionBeat = false; + u32 x28_fileSize; + std::unique_ptr x2c_buffer; + EPhase x34_phase = EPhase::LoadClientPad; + float x38_timeout = 0.f; + std::shared_ptr x30_dvdReq; + u8 x3c_status = 0; + u32 x40_siChan = -1; + bool x44_fusionLinked = false; + bool x45_fusionBeat = false; - static u8 CalculateFusionJBusChecksum(const u8* data, size_t len); + static u8 CalculateFusionJBusChecksum(const u8* data, size_t len); public: - static void Initialize(); - static void GlobalPoll(); + static void Initialize(); + static void GlobalPoll(); - CGBASupport(); - ~CGBASupport(); - bool PollResponse(); - void Update(float dt); - bool IsReady(); - void InitializeSupport(); - void StartLink(); - EPhase GetPhase() const { return x34_phase; } - bool IsFusionLinked() const { return x44_fusionLinked; } - bool IsFusionBeat() const { return x45_fusionBeat; } + CGBASupport(); + ~CGBASupport(); + bool PollResponse(); + void Update(float dt); + bool IsReady(); + void InitializeSupport(); + void StartLink(); + EPhase GetPhase() const { return x34_phase; } + bool IsFusionLinked() const { return x44_fusionLinked; } + bool IsFusionBeat() const { return x45_fusionBeat; } }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CGameCubeDoll.cpp b/Runtime/MP1/CGameCubeDoll.cpp index 0dbf84035..59ad82540 100644 --- a/Runtime/MP1/CGameCubeDoll.cpp +++ b/Runtime/MP1/CGameCubeDoll.cpp @@ -3,64 +3,56 @@ #include "CSimplePool.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CGameCubeDoll::CGameCubeDoll() -{ - x0_model = g_SimplePool->GetObj("CMDL_GameCube"); - x8_lights.push_back(CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skWhite)); - x18_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f); - x20_24_loaded = false; +CGameCubeDoll::CGameCubeDoll() { + x0_model = g_SimplePool->GetObj("CMDL_GameCube"); + x8_lights.push_back(CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skWhite)); + x18_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f); + x20_24_loaded = false; } -void CGameCubeDoll::UpdateActorLights() -{ - x8_lights[0] = CLight::BuildDirectional( - (zeus::CVector3f::skForward + zeus::CVector3f::skRight * 0.25f + zeus::CVector3f::skDown * 0.1f).normalized(), - zeus::CColor::skWhite); - x18_actorLights->BuildFakeLightList(x8_lights, zeus::CColor(0.25f, 1.f)); +void CGameCubeDoll::UpdateActorLights() { + x8_lights[0] = CLight::BuildDirectional( + (zeus::CVector3f::skForward + zeus::CVector3f::skRight * 0.25f + zeus::CVector3f::skDown * 0.1f).normalized(), + zeus::CColor::skWhite); + x18_actorLights->BuildFakeLightList(x8_lights, zeus::CColor(0.25f, 1.f)); } -void CGameCubeDoll::Update(float dt) -{ - if (!CheckLoadComplete()) - return; - x1c_fader = std::min(2.f * dt + x1c_fader, 1.f); - UpdateActorLights(); +void CGameCubeDoll::Update(float dt) { + if (!CheckLoadComplete()) + return; + x1c_fader = std::min(2.f * dt + x1c_fader, 1.f); + UpdateActorLights(); } -void CGameCubeDoll::Draw(float alpha) -{ - if (!IsLoaded()) - return; +void CGameCubeDoll::Draw(float alpha) { + if (!IsLoaded()) + return; - g_Renderer->SetPerspective(55.f, g_Viewport.x8_width, g_Viewport.xc_height, 0.2f, 4096.f); - CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -2.f, 0.f)); - x18_actorLights->ActivateLights(x0_model->GetInstance()); - CGraphics::SetModelMatrix(zeus::CTransform::RotateZ(zeus::degToRad(360.f * CGraphics::GetSecondsMod900() * -0.25f)) * - zeus::CTransform::Scale(0.2f)); - CModelFlags flags(5, 0, 3, zeus::CColor(1.f, alpha * x1c_fader)); - x0_model->Draw(flags); + g_Renderer->SetPerspective(55.f, g_Viewport.x8_width, g_Viewport.xc_height, 0.2f, 4096.f); + CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -2.f, 0.f)); + x18_actorLights->ActivateLights(x0_model->GetInstance()); + CGraphics::SetModelMatrix(zeus::CTransform::RotateZ(zeus::degToRad(360.f * CGraphics::GetSecondsMod900() * -0.25f)) * + zeus::CTransform::Scale(0.2f)); + CModelFlags flags(5, 0, 3, zeus::CColor(1.f, alpha * x1c_fader)); + x0_model->Draw(flags); } -void CGameCubeDoll::Touch() -{ - if (!CheckLoadComplete()) - return; - x0_model->Touch(0); +void CGameCubeDoll::Touch() { + if (!CheckLoadComplete()) + return; + x0_model->Touch(0); } -bool CGameCubeDoll::CheckLoadComplete() -{ - if (IsLoaded()) - return true; - if (x0_model.IsLoaded()) - { - x20_24_loaded = true; - return true; - } - return false; +bool CGameCubeDoll::CheckLoadComplete() { + if (IsLoaded()) + return true; + if (x0_model.IsLoaded()) { + x20_24_loaded = true; + return true; + } + return false; } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CGameCubeDoll.hpp b/Runtime/MP1/CGameCubeDoll.hpp index 54edb65e2..c5782c940 100644 --- a/Runtime/MP1/CGameCubeDoll.hpp +++ b/Runtime/MP1/CGameCubeDoll.hpp @@ -4,30 +4,26 @@ #include "Character/CActorLights.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class CModel; -namespace MP1 -{ +namespace MP1 { + +class CGameCubeDoll { + TLockedToken x0_model; + std::vector x8_lights; + std::unique_ptr x18_actorLights; + float x1c_fader = 0.f; + bool x20_24_loaded : 1; + void UpdateActorLights(); -class CGameCubeDoll -{ - TLockedToken x0_model; - std::vector x8_lights; - std::unique_ptr x18_actorLights; - float x1c_fader = 0.f; - bool x20_24_loaded : 1; - void UpdateActorLights(); public: - CGameCubeDoll(); - void Update(float dt); - void Draw(float alpha); - void Touch(); - bool CheckLoadComplete(); - bool IsLoaded() const { return x20_24_loaded; } - + CGameCubeDoll(); + void Update(float dt); + void Draw(float alpha); + void Touch(); + bool CheckLoadComplete(); + bool IsLoaded() const { return x20_24_loaded; } }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CInGameGuiManager.cpp b/Runtime/MP1/CInGameGuiManager.cpp index 01ab0c8e5..112e8a4d8 100644 --- a/Runtime/MP1/CInGameGuiManager.cpp +++ b/Runtime/MP1/CInGameGuiManager.cpp @@ -17,741 +17,618 @@ #include "Graphics/CBooRenderer.hpp" #include "GuiSys/CGuiWidgetDrawParms.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -static const char* InGameGuiDGRPs[] = -{ - "InGameGui_DGRP", - "Ice_DGRP", - "Phazon_DGRP", - "Plasma_DGRP", - "Power_DGRP", - "Wave_DGRP", - "BallTransition_DGRP", - "GravitySuit_DGRP", - "Ice_Anim_DGRP", - "Plasma_Anim_DGRP", - "PowerSuit_DGRP", - "Power_Anim_DGRP", - "VariaSuit_DGRP", - "Wave_Anim_DGRP" -}; +static const char* InGameGuiDGRPs[] = {"InGameGui_DGRP", "Ice_DGRP", "Phazon_DGRP", "Plasma_DGRP", + "Power_DGRP", "Wave_DGRP", "BallTransition_DGRP", "GravitySuit_DGRP", + "Ice_Anim_DGRP", "Plasma_Anim_DGRP", "PowerSuit_DGRP", "Power_Anim_DGRP", + "VariaSuit_DGRP", "Wave_Anim_DGRP"}; -static const char* PauseScreenDGRPs[] = -{ - "InventorySuitPower_DGRP", - "InventorySuitVaria_DGRP", - "InventorySuitGravity_DGRP", - "InventorySuitPhazon_DGRP", - "InventorySuitFusionPower_DGRP", - "InventorySuitFusionVaria_DGRP", - "InventorySuitFusionGravity_DGRP", - "InventorySuitFusionPhazon_DGRP", - "SamusBallANCS_DGRP", - "SamusSpiderBallANCS_DGRP", - "PauseScreenDontDump_DGRP", - "PauseScreenDontDump_NoARAM_DGRP", - "PauseScreenTokens_DGRP" -}; +static const char* PauseScreenDGRPs[] = { + "InventorySuitPower_DGRP", "InventorySuitVaria_DGRP", "InventorySuitGravity_DGRP", + "InventorySuitPhazon_DGRP", "InventorySuitFusionPower_DGRP", "InventorySuitFusionVaria_DGRP", + "InventorySuitFusionGravity_DGRP", "InventorySuitFusionPhazon_DGRP", "SamusBallANCS_DGRP", + "SamusSpiderBallANCS_DGRP", "PauseScreenDontDump_DGRP", "PauseScreenDontDump_NoARAM_DGRP", + "PauseScreenTokens_DGRP"}; -std::vector> CInGameGuiManager::LockPauseScreenDependencies() -{ - std::vector> ret; - ret.reserve(13); - for (int i=0 ; i<13 ; ++i) - ret.push_back(g_SimplePool->GetObj(PauseScreenDGRPs[i])); - return ret; +std::vector> CInGameGuiManager::LockPauseScreenDependencies() { + std::vector> ret; + ret.reserve(13); + for (int i = 0; i < 13; ++i) + ret.push_back(g_SimplePool->GetObj(PauseScreenDGRPs[i])); + return ret; } -bool CInGameGuiManager::CheckDGRPLoadComplete() const -{ - for (const auto& dgrp : x5c_pauseScreenDGRPs) - if (!dgrp.IsLoaded()) - return false; - for (const auto& dgrp : xc8_inGameGuiDGRPs) - if (!dgrp.IsLoaded()) - return false; - return true; +bool CInGameGuiManager::CheckDGRPLoadComplete() const { + for (const auto& dgrp : x5c_pauseScreenDGRPs) + if (!dgrp.IsLoaded()) + return false; + for (const auto& dgrp : xc8_inGameGuiDGRPs) + if (!dgrp.IsLoaded()) + return false; + return true; } -void CInGameGuiManager::BeginStateTransition(EInGameGuiState state, CStateManager& stateMgr) -{ - if (x1c0_nextState == state) - return; +void CInGameGuiManager::BeginStateTransition(EInGameGuiState state, CStateManager& stateMgr) { + if (x1c0_nextState == state) + return; - x1bc_prevState = x1c0_nextState; - x1c0_nextState = state; + x1bc_prevState = x1c0_nextState; + x1c0_nextState = state; - switch (state) - { - case EInGameGuiState::InGame: - { - CSfxManager::SetChannel(CSfxManager::ESfxChannels::Game); - x4c_saveUI.reset(); - x38_autoMapper->UnmuteAllLoopedSounds(); - break; - } - case EInGameGuiState::PauseHUDMessage: - { - x44_messageScreen = std::make_unique(x124_pauseGameHudMessage, x128_pauseGameHudTime); - break; - } - case EInGameGuiState::PauseSaveGame: - { - x4c_saveUI = std::make_unique(ESaveContext::InGame, g_GameState->GetCardSerial()); - break; - } - default: - { - if (x1bc_prevState >= EInGameGuiState::Zero && x1bc_prevState <= EInGameGuiState::InGame) - x1f8_26_deferTransition = true; - break; - } - } - - x3c_pauseScreenBlur->OnNewInGameGuiState(state, stateMgr); - if (!x1f8_26_deferTransition) - DoStateTransition(stateMgr); + switch (state) { + case EInGameGuiState::InGame: { + CSfxManager::SetChannel(CSfxManager::ESfxChannels::Game); + x4c_saveUI.reset(); + x38_autoMapper->UnmuteAllLoopedSounds(); + break; + } + case EInGameGuiState::PauseHUDMessage: { + x44_messageScreen = std::make_unique(x124_pauseGameHudMessage, x128_pauseGameHudTime); + break; + } + case EInGameGuiState::PauseSaveGame: { + x4c_saveUI = std::make_unique(ESaveContext::InGame, g_GameState->GetCardSerial()); + break; + } + default: { + if (x1bc_prevState >= EInGameGuiState::Zero && x1bc_prevState <= EInGameGuiState::InGame) + x1f8_26_deferTransition = true; + break; + } + } + x3c_pauseScreenBlur->OnNewInGameGuiState(state, stateMgr); + if (!x1f8_26_deferTransition) + DoStateTransition(stateMgr); } -void CInGameGuiManager::EnsureStates(CStateManager& stateMgr) -{ - if (x1f8_26_deferTransition) - { - if (!x3c_pauseScreenBlur->IsGameDraw()) - { - DestroyAreaTextures(stateMgr); - x1f8_26_deferTransition = false; - DoStateTransition(stateMgr); +void CInGameGuiManager::EnsureStates(CStateManager& stateMgr) { + if (x1f8_26_deferTransition) { + if (!x3c_pauseScreenBlur->IsGameDraw()) { + DestroyAreaTextures(stateMgr); + x1f8_26_deferTransition = false; + DoStateTransition(stateMgr); + } + } +} + +void CInGameGuiManager::DoStateTransition(CStateManager& stateMgr) { + x34_samusHud->OnNewInGameGuiState(x1c0_nextState, stateMgr); + x38_autoMapper->OnNewInGameGuiState(x1c0_nextState, stateMgr); + + bool needsLock; + switch (x1c0_nextState) { + case EInGameGuiState::PauseGame: + case EInGameGuiState::PauseLogBook: + if (!x48_pauseScreen) { + auto pState = stateMgr.GetPlayerState(); + CPlayerState::EPlayerSuit suit = pState->GetCurrentSuitRaw(); + int suitResIdx; + if (pState->IsFusionEnabled()) { + switch (suit) { + case CPlayerState::EPlayerSuit::Phazon: + suitResIdx = 7; + break; + case CPlayerState::EPlayerSuit::Gravity: + suitResIdx = 6; + break; + case CPlayerState::EPlayerSuit::Varia: + suitResIdx = 5; + break; + default: + suitResIdx = 4; + break; } - } -} - -void CInGameGuiManager::DoStateTransition(CStateManager& stateMgr) -{ - x34_samusHud->OnNewInGameGuiState(x1c0_nextState, stateMgr); - x38_autoMapper->OnNewInGameGuiState(x1c0_nextState, stateMgr); - - bool needsLock; - switch (x1c0_nextState) - { - case EInGameGuiState::PauseGame: - case EInGameGuiState::PauseLogBook: - if (!x48_pauseScreen) - { - auto pState = stateMgr.GetPlayerState(); - CPlayerState::EPlayerSuit suit = pState->GetCurrentSuitRaw(); - int suitResIdx; - if (pState->IsFusionEnabled()) - { - switch (suit) - { - case CPlayerState::EPlayerSuit::Phazon: - suitResIdx = 7; - break; - case CPlayerState::EPlayerSuit::Gravity: - suitResIdx = 6; - break; - case CPlayerState::EPlayerSuit::Varia: - suitResIdx = 5; - break; - default: - suitResIdx = 4; - break; - } - } - else - { - switch (suit) - { - case CPlayerState::EPlayerSuit::Phazon: - suitResIdx = 3; - break; - case CPlayerState::EPlayerSuit::Gravity: - suitResIdx = 2; - break; - case CPlayerState::EPlayerSuit::Varia: - suitResIdx = 1; - break; - default: - suitResIdx = 0; - break; - } - } - - CPauseScreen::ESubScreen screen = x1c0_nextState == EInGameGuiState::PauseLogBook ? - CPauseScreen::ESubScreen::LogBook : CPauseScreen::ESubScreen::Inventory; - CDependencyGroup* suitGrp = x5c_pauseScreenDGRPs[suitResIdx].GetObj(); - x48_pauseScreen = std::make_unique(screen, *suitGrp, *suitGrp); + } else { + switch (suit) { + case CPlayerState::EPlayerSuit::Phazon: + suitResIdx = 3; + break; + case CPlayerState::EPlayerSuit::Gravity: + suitResIdx = 2; + break; + case CPlayerState::EPlayerSuit::Varia: + suitResIdx = 1; + break; + default: + suitResIdx = 0; + break; } + } - case EInGameGuiState::MapScreen: - case EInGameGuiState::PauseSaveGame: - case EInGameGuiState::PauseHUDMessage: - needsLock = true; - break; - default: - needsLock = false; - break; + CPauseScreen::ESubScreen screen = x1c0_nextState == EInGameGuiState::PauseLogBook + ? CPauseScreen::ESubScreen::LogBook + : CPauseScreen::ESubScreen::Inventory; + CDependencyGroup* suitGrp = x5c_pauseScreenDGRPs[suitResIdx].GetObj(); + x48_pauseScreen = std::make_unique(screen, *suitGrp, *suitGrp); } - for (CToken& tok : xe8_pauseResources) - { - if (needsLock) - tok.Lock(); - else - tok.Unlock(); - } + case EInGameGuiState::MapScreen: + case EInGameGuiState::PauseSaveGame: + case EInGameGuiState::PauseHUDMessage: + needsLock = true; + break; + default: + needsLock = false; + break; + } + + for (CToken& tok : xe8_pauseResources) { + if (needsLock) + tok.Lock(); + else + tok.Unlock(); + } } -void CInGameGuiManager::DestroyAreaTextures(CStateManager& stateMgr) -{ +void CInGameGuiManager::DestroyAreaTextures(CStateManager& stateMgr) {} +void CInGameGuiManager::TryReloadAreaTextures() {} + +CInGameGuiManager::CInGameGuiManager(CStateManager& stateMgr, CArchitectureQueue& archQueue) +: x0_iggmPreLoad(g_SimplePool->GetObj("PreLoadIGGM_DGRP")) +, x1c_rand(1234) +, x20_faceplateDecor(stateMgr) +, x50_deathDot(g_SimplePool->GetObj("TXTR_DeathDot")) +, x5c_pauseScreenDGRPs(LockPauseScreenDependencies()) { + x1e0_helmetVisMode = g_tweakGui->GetHelmetVisMode(); + x1e4_enableTargetingManager = g_tweakGui->GetEnableTargetingManager(); + x1e8_enableAutoMapper = g_tweakGui->GetEnableAutoMapper(); + x1ec_hudVisMode = g_tweakGui->GetHudVisMode(); + x1f0_enablePlayerVisor = g_tweakGui->GetEnablePlayerVisor(); + + x1f4_visorStaticAlpha = stateMgr.GetPlayer().GetVisorStaticAlpha(); + + x1f8_25_playerAlive = true; + x1f8_27_exitSaveUI = true; + + xc8_inGameGuiDGRPs.reserve(14); + for (int i = 0; i < 14; ++i) + xc8_inGameGuiDGRPs.push_back(g_SimplePool->GetObj(InGameGuiDGRPs[i])); } -void CInGameGuiManager::TryReloadAreaTextures() -{ - -} - -CInGameGuiManager::CInGameGuiManager(CStateManager& stateMgr, - CArchitectureQueue& archQueue) -: x0_iggmPreLoad(g_SimplePool->GetObj("PreLoadIGGM_DGRP")), x1c_rand(1234), - x20_faceplateDecor(stateMgr), x50_deathDot(g_SimplePool->GetObj("TXTR_DeathDot")), - x5c_pauseScreenDGRPs(LockPauseScreenDependencies()) -{ - x1e0_helmetVisMode = g_tweakGui->GetHelmetVisMode(); - x1e4_enableTargetingManager = g_tweakGui->GetEnableTargetingManager(); - x1e8_enableAutoMapper = g_tweakGui->GetEnableAutoMapper(); - x1ec_hudVisMode = g_tweakGui->GetHudVisMode(); - x1f0_enablePlayerVisor = g_tweakGui->GetEnablePlayerVisor(); - - x1f4_visorStaticAlpha = stateMgr.GetPlayer().GetVisorStaticAlpha(); - - x1f8_25_playerAlive = true; - x1f8_27_exitSaveUI = true; - - xc8_inGameGuiDGRPs.reserve(14); - for (int i=0 ; i<14 ; ++i) - xc8_inGameGuiDGRPs.push_back(g_SimplePool->GetObj(InGameGuiDGRPs[i])); -} - -bool CInGameGuiManager::CheckLoadComplete(CStateManager& stateMgr) -{ - switch (x18_loadPhase) - { - case ELoadPhase::LoadDepsGroup: - { - if (!x0_iggmPreLoad.IsLoaded()) - return false; - const auto& tags = x0_iggmPreLoad->GetObjectTagVector(); - x8_preLoadDeps.reserve(tags.size()); - for (const SObjectTag& tag : tags) - { - x8_preLoadDeps.push_back(g_SimplePool->GetObj(tag)); - x8_preLoadDeps.back().Lock(); - } - x0_iggmPreLoad.Unlock(); - x18_loadPhase = ELoadPhase::PreLoadDeps; +bool CInGameGuiManager::CheckLoadComplete(CStateManager& stateMgr) { + switch (x18_loadPhase) { + case ELoadPhase::LoadDepsGroup: { + if (!x0_iggmPreLoad.IsLoaded()) + return false; + const auto& tags = x0_iggmPreLoad->GetObjectTagVector(); + x8_preLoadDeps.reserve(tags.size()); + for (const SObjectTag& tag : tags) { + x8_preLoadDeps.push_back(g_SimplePool->GetObj(tag)); + x8_preLoadDeps.back().Lock(); } - case ELoadPhase::PreLoadDeps: - { - for (CToken& tok : x8_preLoadDeps) - if (!tok.IsLoaded()) - return false; - x18_loadPhase = ELoadPhase::LoadDeps; - x30_playerVisor = std::make_unique(stateMgr); - x34_samusHud = std::make_unique(stateMgr); - x38_autoMapper = std::make_unique(stateMgr); - x3c_pauseScreenBlur = std::make_unique(); - x40_samusReflection = std::make_unique(stateMgr); - } - case ELoadPhase::LoadDeps: - { - if (!x38_autoMapper->CheckLoadComplete()) - return false; - if (!x34_samusHud->CheckLoadComplete(stateMgr)) - return false; - if (!x50_deathDot.IsLoaded()) - return false; - if (!CheckDGRPLoadComplete()) - return false; - x8_preLoadDeps.clear(); - - CGuiFrame& baseHud = *x34_samusHud->x274_loadedFrmeBaseHud; - x144_basewidget_automapper = baseHud.FindWidget("BaseWidget_AutoMapper"); - x148_model_automapper = static_cast(baseHud.FindWidget("Model_AutoMapper")); - x14c_basehud_camera = baseHud.GetFrameCamera(); - x150_basewidget_functional = baseHud.FindWidget("BaseWidget_Functional"); - - x154_automapperRotate = zeus::CQuaternion(x144_basewidget_automapper->GetWorldTransform().basis); - x164_automapperOffset = x144_basewidget_automapper->GetLocalPosition(); - x170_camRotate = zeus::CQuaternion::skNoRotation; - x180_camOffset = x14c_basehud_camera->GetLocalPosition() + - zeus::CVector3f(0.f, 2.f, g_tweakAutoMapper->GetCamVerticalOffset()); - - zeus::CMatrix3f mtx(x170_camRotate); - x18c_mapCamXf = zeus::CTransform(mtx, x180_camOffset); - - BeginStateTransition(EInGameGuiState::InGame, stateMgr); - x18_loadPhase = ELoadPhase::Done; - } - case ELoadPhase::Done: - { - x34_samusHud->Touch(); - return true; - } - default: + x0_iggmPreLoad.Unlock(); + x18_loadPhase = ELoadPhase::PreLoadDeps; + } + case ELoadPhase::PreLoadDeps: { + for (CToken& tok : x8_preLoadDeps) + if (!tok.IsLoaded()) return false; - } -} + x18_loadPhase = ELoadPhase::LoadDeps; + x30_playerVisor = std::make_unique(stateMgr); + x34_samusHud = std::make_unique(stateMgr); + x38_autoMapper = std::make_unique(stateMgr); + x3c_pauseScreenBlur = std::make_unique(); + x40_samusReflection = std::make_unique(stateMgr); + } + case ELoadPhase::LoadDeps: { + if (!x38_autoMapper->CheckLoadComplete()) + return false; + if (!x34_samusHud->CheckLoadComplete(stateMgr)) + return false; + if (!x50_deathDot.IsLoaded()) + return false; + if (!CheckDGRPLoadComplete()) + return false; + x8_preLoadDeps.clear(); -void CInGameGuiManager::RefreshHudOptions() -{ - x34_samusHud->RefreshHudOptions(); -} + CGuiFrame& baseHud = *x34_samusHud->x274_loadedFrmeBaseHud; + x144_basewidget_automapper = baseHud.FindWidget("BaseWidget_AutoMapper"); + x148_model_automapper = static_cast(baseHud.FindWidget("Model_AutoMapper")); + x14c_basehud_camera = baseHud.GetFrameCamera(); + x150_basewidget_functional = baseHud.FindWidget("BaseWidget_Functional"); -void CInGameGuiManager::OnNewPauseScreenState(CArchitectureQueue& archQueue) -{ - if (x1c0_nextState != EInGameGuiState::PauseGame && x1c0_nextState != EInGameGuiState::PauseLogBook) - { - if (x48_pauseScreen && x48_pauseScreen->IsTransitioning()) - return; - x48_pauseScreen.reset(); - } + x154_automapperRotate = zeus::CQuaternion(x144_basewidget_automapper->GetWorldTransform().basis); + x164_automapperOffset = x144_basewidget_automapper->GetLocalPosition(); + x170_camRotate = zeus::CQuaternion::skNoRotation; + x180_camOffset = + x14c_basehud_camera->GetLocalPosition() + zeus::CVector3f(0.f, 2.f, g_tweakAutoMapper->GetCamVerticalOffset()); - if (x1c0_nextState >= EInGameGuiState::Zero && x1c0_nextState <= EInGameGuiState::InGame) - { - if (x44_messageScreen) - x44_messageScreen.reset(); - RefreshHudOptions(); - } - x1bc_prevState = x1c0_nextState; -} - -void CInGameGuiManager::UpdateAutoMapper(float dt, const CStateManager& stateMgr) -{ - x38_autoMapper->Update(dt, stateMgr); - zeus::CTransform xf = x148_model_automapper->GetParent()->GetWorldTransform() * - x144_basewidget_automapper->GetTransform(); - x154_automapperRotate = zeus::CQuaternion(xf.basis); - x164_automapperOffset = xf.origin; - - x170_camRotate = zeus::CQuaternion(x14c_basehud_camera->GetWorldTransform().basis); - x180_camOffset = x14c_basehud_camera->GetWorldTransform().basis[1] * 2.f + - x14c_basehud_camera->GetWorldPosition() + - x14c_basehud_camera->GetWorldTransform().basis[2] * g_tweakAutoMapper->GetCamVerticalOffset(); - - float frameLength = std::tan(zeus::degToRad(x14c_basehud_camera->GetProjection().xbc_fov) / 2.f) / 0.7f; - float scaleX = frameLength * g_tweakAutoMapper->GetAutomapperScaleX(); - float scaleZ = frameLength * g_tweakAutoMapper->GetAutomapperScaleZ(); - if (x38_autoMapper->IsFullyOutOfMiniMapState()) - { - x148_model_automapper->SetO2WTransform( - zeus::CTransform(x170_camRotate, x180_camOffset) * zeus::CTransform::Scale(scaleX, 1.f, scaleZ)); - x18c_mapCamXf = zeus::CTransform(x170_camRotate, x180_camOffset) * - zeus::CTransform::Scale(frameLength, 1.f, frameLength); - x148_model_automapper->SetColor(g_tweakAutoMapper->GetAutomapperWidgetColor()); - } - else if (x38_autoMapper->IsFullyInMiniMapState()) - { - x148_model_automapper->SetO2WTransform(zeus::CTransform(x154_automapperRotate, x164_automapperOffset)); - x18c_mapCamXf = x148_model_automapper->GetWorldTransform(); - x148_model_automapper->SetColor(g_tweakAutoMapper->GetAutomapperWidgetMiniColor()); - } - else - { - float t; - if (x38_autoMapper->GetNextState() != CAutoMapper::EAutoMapperState::MiniMap) - t = x38_autoMapper->GetInterp(); - else - t = 1.f - x38_autoMapper->GetInterp(); - float st = t * (frameLength - 1.f) + 1.f; - zeus::CQuaternion rotate = zeus::CQuaternion::slerp(x154_automapperRotate, x170_camRotate, t); - zeus::CVector3f offset = x164_automapperOffset * (1.f - t) + x180_camOffset * t; - x18c_mapCamXf = zeus::CTransform(rotate, offset) * zeus::CTransform::Scale(st, 1.f, st); - x148_model_automapper->SetO2WTransform(zeus::CTransform(rotate, offset) * - zeus::CTransform::Scale(t * (scaleX - 1.f) + 1.f, 1.f, t * (scaleZ - 1.f) + 1.f)); - x148_model_automapper->SetColor(zeus::CColor::lerp(g_tweakAutoMapper->GetAutomapperWidgetMiniColor(), - g_tweakAutoMapper->GetAutomapperWidgetColor(), t)); - } -} - -void CInGameGuiManager::Update(CStateManager& stateMgr, float dt, CArchitectureQueue& archQueue, bool useHud) -{ - EnsureStates(stateMgr); - - if (x1d8_onScreenTexAlpha == 0.f) - x1dc_onScreenTexTok = TLockedToken(); - - if (x1c4_onScreenTex.x0_id != stateMgr.GetPendingScreenTex().x0_id) - { - if (!x1dc_onScreenTexTok) - { - x1c4_onScreenTex = stateMgr.GetPendingScreenTex(); - if (x1c4_onScreenTex.x0_id.IsValid()) - { - x1dc_onScreenTexTok = g_SimplePool->GetObj({FOURCC('TXTR'), x1c4_onScreenTex.x0_id}); - x1d8_onScreenTexAlpha = FLT_EPSILON; - } - } - else - { - if (!stateMgr.GetPendingScreenTex().x0_id.IsValid() && - stateMgr.GetPendingScreenTex().x4_origin == zeus::CVector2i(0, 0)) - { - x1c4_onScreenTex.x4_origin = stateMgr.GetPendingScreenTex().x4_origin; - x1c4_onScreenTex.x0_id = {}; - x1d8_onScreenTexAlpha = 0.f; - } - else - { - x1d8_onScreenTexAlpha = std::max(0.f, x1d8_onScreenTexAlpha - dt); - } - } - } - else if (x1c4_onScreenTex.x0_id.IsValid() && x1dc_onScreenTexTok.IsLoaded()) - { - x1d8_onScreenTexAlpha = std::min(x1d8_onScreenTexAlpha + dt, 1.f); - } - - if (useHud) - { - if (stateMgr.GetPlayer().GetVisorStaticAlpha() != x1f4_visorStaticAlpha) - { - if (TCastToPtr(stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr))) - { - if (std::fabs(stateMgr.GetPlayer().GetVisorStaticAlpha() - x1f4_visorStaticAlpha) < 0.5f) - { - if (x1f4_visorStaticAlpha == 0.f) - CSfxManager::SfxStart(SFXui_hud_reboot, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - else if (x1f4_visorStaticAlpha == 1.f) - CSfxManager::SfxStart(SFXui_hud_shutdown, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - } - } - x1f4_visorStaticAlpha = stateMgr.GetPlayer().GetVisorStaticAlpha(); - x20_faceplateDecor.Update(dt, stateMgr); - x40_samusReflection->Update(dt, stateMgr, x1c_rand); - if (x1f0_enablePlayerVisor) - x30_playerVisor->Update(dt, stateMgr); - if (x1f8_25_playerAlive) - x34_samusHud->Update(dt, stateMgr, x1e0_helmetVisMode, x1ec_hudVisMode != EHudVisMode::Zero, - x1e4_enableTargetingManager); - } - - if (x1e8_enableAutoMapper) - UpdateAutoMapper(dt, stateMgr); - - x3c_pauseScreenBlur->Update(dt, stateMgr, !x140_); - - if (x4c_saveUI) - { - CIOWin::EMessageReturn ret = x4c_saveUI->Update(dt); - if (ret != CIOWin::EMessageReturn::Normal) - { - x1f8_27_exitSaveUI = ret == CIOWin::EMessageReturn::Exit; - BeginStateTransition(EInGameGuiState::InGame, stateMgr); - } - } - else if (x44_messageScreen) - { - if (!x44_messageScreen->Update(dt, x3c_pauseScreenBlur->GetBlurAmt())) - BeginStateTransition(EInGameGuiState::InGame, stateMgr); - } - - if (x48_pauseScreen) - { - x48_pauseScreen->Update(dt, stateMgr, x1c_rand, archQueue); - if (x1bc_prevState == x1c0_nextState) - { - if (x48_pauseScreen->ShouldSwitchToMapScreen()) - BeginStateTransition(EInGameGuiState::MapScreen, stateMgr); - else if (x48_pauseScreen->ShouldSwitchToInGame()) - BeginStateTransition(EInGameGuiState::InGame, stateMgr); - } - } + zeus::CMatrix3f mtx(x170_camRotate); + x18c_mapCamXf = zeus::CTransform(mtx, x180_camOffset); + BeginStateTransition(EInGameGuiState::InGame, stateMgr); + x18_loadPhase = ELoadPhase::Done; + } + case ELoadPhase::Done: { x34_samusHud->Touch(); - x30_playerVisor->Touch(); - x34_samusHud->GetTargetingManager().Touch(); + return true; + } + default: + return false; + } +} - if (x1bc_prevState != x1c0_nextState) - { - if (x1c0_nextState == EInGameGuiState::Zero || x1c0_nextState == EInGameGuiState::InGame) - TryReloadAreaTextures(); - if ((!x38_autoMapper->IsInMapperStateTransition() || !x1e8_enableAutoMapper) && - x3c_pauseScreenBlur->IsNotTransitioning()) - OnNewPauseScreenState(archQueue); - } +void CInGameGuiManager::RefreshHudOptions() { x34_samusHud->RefreshHudOptions(); } - xf8_camFilter.Update(dt); - if (stateMgr.GetCameraManager()->IsInCinematicCamera()) - { - stateMgr.SetViewportScale(zeus::CVector2f(1.f, 1.f)); - } +void CInGameGuiManager::OnNewPauseScreenState(CArchitectureQueue& archQueue) { + if (x1c0_nextState != EInGameGuiState::PauseGame && x1c0_nextState != EInGameGuiState::PauseLogBook) { + if (x48_pauseScreen && x48_pauseScreen->IsTransitioning()) + return; + x48_pauseScreen.reset(); + } + + if (x1c0_nextState >= EInGameGuiState::Zero && x1c0_nextState <= EInGameGuiState::InGame) { + if (x44_messageScreen) + x44_messageScreen.reset(); + RefreshHudOptions(); + } + x1bc_prevState = x1c0_nextState; +} + +void CInGameGuiManager::UpdateAutoMapper(float dt, const CStateManager& stateMgr) { + x38_autoMapper->Update(dt, stateMgr); + zeus::CTransform xf = + x148_model_automapper->GetParent()->GetWorldTransform() * x144_basewidget_automapper->GetTransform(); + x154_automapperRotate = zeus::CQuaternion(xf.basis); + x164_automapperOffset = xf.origin; + + x170_camRotate = zeus::CQuaternion(x14c_basehud_camera->GetWorldTransform().basis); + x180_camOffset = x14c_basehud_camera->GetWorldTransform().basis[1] * 2.f + x14c_basehud_camera->GetWorldPosition() + + x14c_basehud_camera->GetWorldTransform().basis[2] * g_tweakAutoMapper->GetCamVerticalOffset(); + + float frameLength = std::tan(zeus::degToRad(x14c_basehud_camera->GetProjection().xbc_fov) / 2.f) / 0.7f; + float scaleX = frameLength * g_tweakAutoMapper->GetAutomapperScaleX(); + float scaleZ = frameLength * g_tweakAutoMapper->GetAutomapperScaleZ(); + if (x38_autoMapper->IsFullyOutOfMiniMapState()) { + x148_model_automapper->SetO2WTransform(zeus::CTransform(x170_camRotate, x180_camOffset) * + zeus::CTransform::Scale(scaleX, 1.f, scaleZ)); + x18c_mapCamXf = + zeus::CTransform(x170_camRotate, x180_camOffset) * zeus::CTransform::Scale(frameLength, 1.f, frameLength); + x148_model_automapper->SetColor(g_tweakAutoMapper->GetAutomapperWidgetColor()); + } else if (x38_autoMapper->IsFullyInMiniMapState()) { + x148_model_automapper->SetO2WTransform(zeus::CTransform(x154_automapperRotate, x164_automapperOffset)); + x18c_mapCamXf = x148_model_automapper->GetWorldTransform(); + x148_model_automapper->SetColor(g_tweakAutoMapper->GetAutomapperWidgetMiniColor()); + } else { + float t; + if (x38_autoMapper->GetNextState() != CAutoMapper::EAutoMapperState::MiniMap) + t = x38_autoMapper->GetInterp(); else - { - stateMgr.SetViewportScale(zeus::CVector2f( - std::min(x30_playerVisor->GetDesiredViewportScaleX(stateMgr), x34_samusHud->GetViewportScale().x()), - std::min(x30_playerVisor->GetDesiredViewportScaleY(stateMgr), x34_samusHud->GetViewportScale().y()))); + t = 1.f - x38_autoMapper->GetInterp(); + float st = t * (frameLength - 1.f) + 1.f; + zeus::CQuaternion rotate = zeus::CQuaternion::slerp(x154_automapperRotate, x170_camRotate, t); + zeus::CVector3f offset = x164_automapperOffset * (1.f - t) + x180_camOffset * t; + x18c_mapCamXf = zeus::CTransform(rotate, offset) * zeus::CTransform::Scale(st, 1.f, st); + x148_model_automapper->SetO2WTransform( + zeus::CTransform(rotate, offset) * + zeus::CTransform::Scale(t * (scaleX - 1.f) + 1.f, 1.f, t * (scaleZ - 1.f) + 1.f)); + x148_model_automapper->SetColor(zeus::CColor::lerp(g_tweakAutoMapper->GetAutomapperWidgetMiniColor(), + g_tweakAutoMapper->GetAutomapperWidgetColor(), t)); + } +} + +void CInGameGuiManager::Update(CStateManager& stateMgr, float dt, CArchitectureQueue& archQueue, bool useHud) { + EnsureStates(stateMgr); + + if (x1d8_onScreenTexAlpha == 0.f) + x1dc_onScreenTexTok = TLockedToken(); + + if (x1c4_onScreenTex.x0_id != stateMgr.GetPendingScreenTex().x0_id) { + if (!x1dc_onScreenTexTok) { + x1c4_onScreenTex = stateMgr.GetPendingScreenTex(); + if (x1c4_onScreenTex.x0_id.IsValid()) { + x1dc_onScreenTexTok = g_SimplePool->GetObj({FOURCC('TXTR'), x1c4_onScreenTex.x0_id}); + x1d8_onScreenTexAlpha = FLT_EPSILON; + } + } else { + if (!stateMgr.GetPendingScreenTex().x0_id.IsValid() && + stateMgr.GetPendingScreenTex().x4_origin == zeus::CVector2i(0, 0)) { + x1c4_onScreenTex.x4_origin = stateMgr.GetPendingScreenTex().x4_origin; + x1c4_onScreenTex.x0_id = {}; + x1d8_onScreenTexAlpha = 0.f; + } else { + x1d8_onScreenTexAlpha = std::max(0.f, x1d8_onScreenTexAlpha - dt); + } } + } else if (x1c4_onScreenTex.x0_id.IsValid() && x1dc_onScreenTexTok.IsLoaded()) { + x1d8_onScreenTexAlpha = std::min(x1d8_onScreenTexAlpha + dt, 1.f); + } - x1f8_25_playerAlive = stateMgr.GetPlayerState()->IsPlayerAlive(); + if (useHud) { + if (stateMgr.GetPlayer().GetVisorStaticAlpha() != x1f4_visorStaticAlpha) { + if (TCastToPtr(stateMgr.GetCameraManager()->GetCurrentCamera(stateMgr))) { + if (std::fabs(stateMgr.GetPlayer().GetVisorStaticAlpha() - x1f4_visorStaticAlpha) < 0.5f) { + if (x1f4_visorStaticAlpha == 0.f) + CSfxManager::SfxStart(SFXui_hud_reboot, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + else if (x1f4_visorStaticAlpha == 1.f) + CSfxManager::SfxStart(SFXui_hud_shutdown, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + } + } + x1f4_visorStaticAlpha = stateMgr.GetPlayer().GetVisorStaticAlpha(); + x20_faceplateDecor.Update(dt, stateMgr); + x40_samusReflection->Update(dt, stateMgr, x1c_rand); + if (x1f0_enablePlayerVisor) + x30_playerVisor->Update(dt, stateMgr); + if (x1f8_25_playerAlive) + x34_samusHud->Update(dt, stateMgr, x1e0_helmetVisMode, x1ec_hudVisMode != EHudVisMode::Zero, + x1e4_enableTargetingManager); + } + + if (x1e8_enableAutoMapper) + UpdateAutoMapper(dt, stateMgr); + + x3c_pauseScreenBlur->Update(dt, stateMgr, !x140_); + + if (x4c_saveUI) { + CIOWin::EMessageReturn ret = x4c_saveUI->Update(dt); + if (ret != CIOWin::EMessageReturn::Normal) { + x1f8_27_exitSaveUI = ret == CIOWin::EMessageReturn::Exit; + BeginStateTransition(EInGameGuiState::InGame, stateMgr); + } + } else if (x44_messageScreen) { + if (!x44_messageScreen->Update(dt, x3c_pauseScreenBlur->GetBlurAmt())) + BeginStateTransition(EInGameGuiState::InGame, stateMgr); + } + + if (x48_pauseScreen) { + x48_pauseScreen->Update(dt, stateMgr, x1c_rand, archQueue); + if (x1bc_prevState == x1c0_nextState) { + if (x48_pauseScreen->ShouldSwitchToMapScreen()) + BeginStateTransition(EInGameGuiState::MapScreen, stateMgr); + else if (x48_pauseScreen->ShouldSwitchToInGame()) + BeginStateTransition(EInGameGuiState::InGame, stateMgr); + } + } + + x34_samusHud->Touch(); + x30_playerVisor->Touch(); + x34_samusHud->GetTargetingManager().Touch(); + + if (x1bc_prevState != x1c0_nextState) { + if (x1c0_nextState == EInGameGuiState::Zero || x1c0_nextState == EInGameGuiState::InGame) + TryReloadAreaTextures(); + if ((!x38_autoMapper->IsInMapperStateTransition() || !x1e8_enableAutoMapper) && + x3c_pauseScreenBlur->IsNotTransitioning()) + OnNewPauseScreenState(archQueue); + } + + xf8_camFilter.Update(dt); + if (stateMgr.GetCameraManager()->IsInCinematicCamera()) { + stateMgr.SetViewportScale(zeus::CVector2f(1.f, 1.f)); + } else { + stateMgr.SetViewportScale(zeus::CVector2f( + std::min(x30_playerVisor->GetDesiredViewportScaleX(stateMgr), x34_samusHud->GetViewportScale().x()), + std::min(x30_playerVisor->GetDesiredViewportScaleY(stateMgr), x34_samusHud->GetViewportScale().y()))); + } + + x1f8_25_playerAlive = stateMgr.GetPlayerState()->IsPlayerAlive(); } -bool CInGameGuiManager::IsInGameStateNotTransitioning() const -{ - return (x1bc_prevState >= EInGameGuiState::Zero && x1bc_prevState <= EInGameGuiState::InGame && - x1c0_nextState >= EInGameGuiState::Zero && x1c0_nextState <= EInGameGuiState::InGame); +bool CInGameGuiManager::IsInGameStateNotTransitioning() const { + return (x1bc_prevState >= EInGameGuiState::Zero && x1bc_prevState <= EInGameGuiState::InGame && + x1c0_nextState >= EInGameGuiState::Zero && x1c0_nextState <= EInGameGuiState::InGame); } -bool CInGameGuiManager::IsInPausedStateNotTransitioning() const -{ - return (x1bc_prevState >= EInGameGuiState::MapScreen && x1bc_prevState <= EInGameGuiState::PauseHUDMessage && - x1c0_nextState >= EInGameGuiState::MapScreen && x1c0_nextState <= EInGameGuiState::PauseHUDMessage); +bool CInGameGuiManager::IsInPausedStateNotTransitioning() const { + return (x1bc_prevState >= EInGameGuiState::MapScreen && x1bc_prevState <= EInGameGuiState::PauseHUDMessage && + x1c0_nextState >= EInGameGuiState::MapScreen && x1c0_nextState <= EInGameGuiState::PauseHUDMessage); } void CInGameGuiManager::ProcessControllerInput(CStateManager& stateMgr, const CFinalInput& input, - CArchitectureQueue& archQueue) -{ - if (input.ControllerIdx() == 0) - { - if (!IsInGameStateNotTransitioning()) - { - if (IsInPausedStateNotTransitioning()) - { - if (x1bc_prevState == EInGameGuiState::MapScreen) - { - if (x38_autoMapper->IsInMapperState(CAutoMapper::EAutoMapperState::MapScreen) || - x38_autoMapper->IsInMapperState(CAutoMapper::EAutoMapperState::MapScreenUniverse)) - { - x38_autoMapper->ProcessControllerInput(input, stateMgr); - if (x38_autoMapper->CanLeaveMapScreen(stateMgr)) - BeginStateTransition(EInGameGuiState::InGame, stateMgr); - } - return; - } - if (x1bc_prevState == EInGameGuiState::PauseSaveGame) - { - x4c_saveUI->ProcessUserInput(input); - return; - } - if (x1bc_prevState == EInGameGuiState::PauseHUDMessage) - { - x44_messageScreen->ProcessControllerInput(input); - return; - } - if (x48_pauseScreen) - x48_pauseScreen->ProcessControllerInput(stateMgr, input); - } + CArchitectureQueue& archQueue) { + if (input.ControllerIdx() == 0) { + if (!IsInGameStateNotTransitioning()) { + if (IsInPausedStateNotTransitioning()) { + if (x1bc_prevState == EInGameGuiState::MapScreen) { + if (x38_autoMapper->IsInMapperState(CAutoMapper::EAutoMapperState::MapScreen) || + x38_autoMapper->IsInMapperState(CAutoMapper::EAutoMapperState::MapScreenUniverse)) { + x38_autoMapper->ProcessControllerInput(input, stateMgr); + if (x38_autoMapper->CanLeaveMapScreen(stateMgr)) + BeginStateTransition(EInGameGuiState::InGame, stateMgr); + } + return; } - else - { - x34_samusHud->ProcessControllerInput(input); + if (x1bc_prevState == EInGameGuiState::PauseSaveGame) { + x4c_saveUI->ProcessUserInput(input); + return; } - } -} - -void CInGameGuiManager::PreDraw(CStateManager& stateMgr, bool cameraActive) -{ - if (x48_pauseScreen) - x48_pauseScreen->PreDraw(); - if (cameraActive) - x40_samusReflection->PreDraw(stateMgr); -} - -void CInGameGuiManager::Draw(CStateManager& stateMgr) -{ - //if (!GetIsGameDraw()) - // g_Renderer->x318_26_requestRGBA6 = true; - if (x1d8_onScreenTexAlpha > 0.f && x1dc_onScreenTexTok.IsLoaded()) - { - if (!m_onScreenQuad || m_onScreenQuad->GetTex().GetObj() != x1dc_onScreenTexTok.GetObj()) - m_onScreenQuad.emplace(EFilterType::Blend, x1dc_onScreenTexTok); - - // No depth read/write - // Alpha blend - int w = (g_Viewport.x0_left + (x1c4_onScreenTex.x4_origin.x - g_Viewport.x8_width) / 2 + x1c4_onScreenTex.xc_extent.x) - - x1c4_onScreenTex.x4_origin.x; - int h = (g_Viewport.x4_top + (x1c4_onScreenTex.x4_origin.y - g_Viewport.xc_height) / 2 - x1c4_onScreenTex.xc_extent.y) - - x1c4_onScreenTex.x4_origin.y; - zeus::CRectangle rect(x1c4_onScreenTex.x4_origin.x / float(g_Viewport.x8_width), - x1c4_onScreenTex.x4_origin.y / float(g_Viewport.xc_height), - w / float(g_Viewport.x8_width), h / float(g_Viewport.xc_height)); - m_onScreenQuad->draw(zeus::CColor(1.f, x1d8_onScreenTexAlpha), 1.f, rect); - } - - float staticAlpha = 0.f; - if (stateMgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && - stateMgr.GetPlayer().GetDeathTime() > 0.f) - staticAlpha = zeus::clamp(0.f, stateMgr.GetPlayer().GetDeathTime() / (0.3f * 2.5f), 1.f); - - bool notInCine = !stateMgr.GetCameraManager()->IsInCinematicCamera(); - bool drawVisor = false; - /* Let's always draw the HUD except in cinematic mode */ - if (notInCine /* && (x1bc_prevState == EInGameGuiState::InGame || x1c0_nextState == EInGameGuiState::InGame) */) - drawVisor = true; - - //if (x3c_pauseScreenBlur->IsGameDraw()) - { - x34_samusHud->GetTargetingManager().Draw(stateMgr, true); - CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); - bool scanVisor = stateMgr.GetPlayerState()->GetActiveVisor(stateMgr) == CPlayerState::EPlayerVisor::Scan; - if (drawVisor && x1f0_enablePlayerVisor) - { - if (stateMgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) - x20_faceplateDecor.Draw(stateMgr); - CTargetingManager* tgtMgr = nullptr; - if (scanVisor && x1e4_enableTargetingManager) - tgtMgr = &x34_samusHud->GetTargetingManager(); - x30_playerVisor->Draw(stateMgr, tgtMgr); - } - x40_samusReflection->Draw(stateMgr); - if (drawVisor) - { - CGraphics::SetDepthRange(DEPTH_HUD, DEPTH_SCREEN_ACTORS); - if (staticAlpha > 0.f) - m_randomStatic.draw(zeus::CColor(1.f, staticAlpha), 1.f); - x34_samusHud->Draw(stateMgr, x1f4_visorStaticAlpha * (1.f - staticAlpha), - x1e0_helmetVisMode, x1ec_hudVisMode != EHudVisMode::Zero, - x1e4_enableTargetingManager && !scanVisor); + if (x1bc_prevState == EInGameGuiState::PauseHUDMessage) { + x44_messageScreen->ProcessControllerInput(input); + return; } + if (x48_pauseScreen) + x48_pauseScreen->ProcessControllerInput(stateMgr, input); + } + } else { + x34_samusHud->ProcessControllerInput(input); } + } +} - bool preDrawBlur = true; - if (x1bc_prevState >= EInGameGuiState::Zero && x1bc_prevState <= EInGameGuiState::InGame) - if (x1bc_prevState != EInGameGuiState::MapScreen && x1c0_nextState != EInGameGuiState::MapScreen) - preDrawBlur = false; - if (preDrawBlur) - x3c_pauseScreenBlur->Draw(stateMgr); +void CInGameGuiManager::PreDraw(CStateManager& stateMgr, bool cameraActive) { + if (x48_pauseScreen) + x48_pauseScreen->PreDraw(); + if (cameraActive) + x40_samusReflection->PreDraw(stateMgr); +} - if (notInCine && x1e8_enableAutoMapper && - (x3c_pauseScreenBlur->IsGameDraw() || x1bc_prevState == EInGameGuiState::MapScreen || - x1c0_nextState == EInGameGuiState::MapScreen)) - { - float t; - if (stateMgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat) - t = stateMgr.GetPlayerState()->GetVisorTransitionFactor(); - else - t = 0.f; +void CInGameGuiManager::Draw(CStateManager& stateMgr) { + // if (!GetIsGameDraw()) + // g_Renderer->x318_26_requestRGBA6 = true; + if (x1d8_onScreenTexAlpha > 0.f && x1dc_onScreenTexTok.IsLoaded()) { + if (!m_onScreenQuad || m_onScreenQuad->GetTex().GetObj() != x1dc_onScreenTexTok.GetObj()) + m_onScreenQuad.emplace(EFilterType::Blend, x1dc_onScreenTexTok); - float mapAlpha; - if (g_tweakGui->GetShowAutomapperInMorphball()) - mapAlpha = 1.f; - else if (stateMgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) - mapAlpha = 1.f; - else - mapAlpha = 0.f; + // No depth read/write + // Alpha blend + int w = + (g_Viewport.x0_left + (x1c4_onScreenTex.x4_origin.x - g_Viewport.x8_width) / 2 + x1c4_onScreenTex.xc_extent.x) - + x1c4_onScreenTex.x4_origin.x; + int h = + (g_Viewport.x4_top + (x1c4_onScreenTex.x4_origin.y - g_Viewport.xc_height) / 2 - x1c4_onScreenTex.xc_extent.y) - + x1c4_onScreenTex.x4_origin.y; + zeus::CRectangle rect(x1c4_onScreenTex.x4_origin.x / float(g_Viewport.x8_width), + x1c4_onScreenTex.x4_origin.y / float(g_Viewport.xc_height), w / float(g_Viewport.x8_width), + h / float(g_Viewport.xc_height)); + m_onScreenQuad->draw(zeus::CColor(1.f, x1d8_onScreenTexAlpha), 1.f, rect); + } - x34_samusHud->GetBaseHudFrame()->GetFrameCamera()->Draw(CGuiWidgetDrawParms(0.f, zeus::CVector3f::skZero)); - CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_HUD); - x148_model_automapper->SetIsVisible(true); - x148_model_automapper->Draw(CGuiWidgetDrawParms(1.f, zeus::CVector3f::skZero)); - // ZTest no write - x38_autoMapper->Draw(stateMgr, zeus::CTransform::Translate(0.f, 0.02f, 0.f) * x18c_mapCamXf, - mapAlpha * x1f4_visorStaticAlpha * t); - // Zest and write - x148_model_automapper->SetIsVisible(false); + float staticAlpha = 0.f; + if (stateMgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && + stateMgr.GetPlayer().GetDeathTime() > 0.f) + staticAlpha = zeus::clamp(0.f, stateMgr.GetPlayer().GetDeathTime() / (0.3f * 2.5f), 1.f); + + bool notInCine = !stateMgr.GetCameraManager()->IsInCinematicCamera(); + bool drawVisor = false; + /* Let's always draw the HUD except in cinematic mode */ + if (notInCine /* && (x1bc_prevState == EInGameGuiState::InGame || x1c0_nextState == EInGameGuiState::InGame) */) + drawVisor = true; + + // if (x3c_pauseScreenBlur->IsGameDraw()) + { + x34_samusHud->GetTargetingManager().Draw(stateMgr, true); + CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); + bool scanVisor = stateMgr.GetPlayerState()->GetActiveVisor(stateMgr) == CPlayerState::EPlayerVisor::Scan; + if (drawVisor && x1f0_enablePlayerVisor) { + if (stateMgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) + x20_faceplateDecor.Draw(stateMgr); + CTargetingManager* tgtMgr = nullptr; + if (scanVisor && x1e4_enableTargetingManager) + tgtMgr = &x34_samusHud->GetTargetingManager(); + x30_playerVisor->Draw(stateMgr, tgtMgr); } - - if (!preDrawBlur) - x3c_pauseScreenBlur->Draw(stateMgr); - - if (x1e0_helmetVisMode != EHelmetVisMode::ReducedUpdate && notInCine) - { - float camYOff; - if (!x48_pauseScreen) - camYOff = 0.f; - else - camYOff = x48_pauseScreen->GetHelmetCamYOff(); - x34_samusHud->DrawHelmet(stateMgr, camYOff); + x40_samusReflection->Draw(stateMgr); + if (drawVisor) { + CGraphics::SetDepthRange(DEPTH_HUD, DEPTH_SCREEN_ACTORS); + if (staticAlpha > 0.f) + m_randomStatic.draw(zeus::CColor(1.f, staticAlpha), 1.f); + x34_samusHud->Draw(stateMgr, x1f4_visorStaticAlpha * (1.f - staticAlpha), x1e0_helmetVisMode, + x1ec_hudVisMode != EHudVisMode::Zero, x1e4_enableTargetingManager && !scanVisor); } + } - if (x4c_saveUI) - x4c_saveUI->Draw(); + bool preDrawBlur = true; + if (x1bc_prevState >= EInGameGuiState::Zero && x1bc_prevState <= EInGameGuiState::InGame) + if (x1bc_prevState != EInGameGuiState::MapScreen && x1c0_nextState != EInGameGuiState::MapScreen) + preDrawBlur = false; + if (preDrawBlur) + x3c_pauseScreenBlur->Draw(stateMgr); - if (x44_messageScreen) - x44_messageScreen->Draw(); + if (notInCine && x1e8_enableAutoMapper && + (x3c_pauseScreenBlur->IsGameDraw() || x1bc_prevState == EInGameGuiState::MapScreen || + x1c0_nextState == EInGameGuiState::MapScreen)) { + float t; + if (stateMgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat) + t = stateMgr.GetPlayerState()->GetVisorTransitionFactor(); + else + t = 0.f; - if (x48_pauseScreen) - x48_pauseScreen->Draw(); + float mapAlpha; + if (g_tweakGui->GetShowAutomapperInMorphball()) + mapAlpha = 1.f; + else if (stateMgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) + mapAlpha = 1.f; + else + mapAlpha = 0.f; - xf8_camFilter.Draw(); + x34_samusHud->GetBaseHudFrame()->GetFrameCamera()->Draw(CGuiWidgetDrawParms(0.f, zeus::CVector3f::skZero)); + CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_HUD); + x148_model_automapper->SetIsVisible(true); + x148_model_automapper->Draw(CGuiWidgetDrawParms(1.f, zeus::CVector3f::skZero)); + // ZTest no write + x38_autoMapper->Draw(stateMgr, zeus::CTransform::Translate(0.f, 0.02f, 0.f) * x18c_mapCamXf, + mapAlpha * x1f4_visorStaticAlpha * t); + // Zest and write + x148_model_automapper->SetIsVisible(false); + } - if (stateMgr.GetPlayer().GetDeathTime() > 0.f) - { - float dieDur; - if (stateMgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) - dieDur = 2.5f; - else - dieDur = 6.f; + if (!preDrawBlur) + x3c_pauseScreenBlur->Draw(stateMgr); - float alpha = zeus::clamp(0.f, stateMgr.GetPlayer().GetDeathTime() / dieDur, 1.f); - m_deathWhiteout.draw(zeus::CColor(1.f, alpha)); + if (x1e0_helmetVisMode != EHelmetVisMode::ReducedUpdate && notInCine) { + float camYOff; + if (!x48_pauseScreen) + camYOff = 0.f; + else + camYOff = x48_pauseScreen->GetHelmetCamYOff(); + x34_samusHud->DrawHelmet(stateMgr, camYOff); + } - float zStart = dieDur - 0.5f - 0.5f - 1.f; - float xStart = 0.5f - zStart; - float colStart = 0.5f - xStart; - if (stateMgr.GetPlayer().GetDeathTime() > zStart) - { - float zT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - zStart) / 0.5f, 1.f); - float xT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - xStart) / 0.5f, 1.f); - float colT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - colStart) / 0.5f, 1.f); - SClipScreenRect rect(g_Viewport); - CGraphics::ResolveSpareTexture(rect); - m_deathBlackout.draw(zeus::CColor::skBlack); - float z = 0.5f * (zT * zT * zT * zT * zT * (g_Viewport.xc_height - 12.f) + 12.f); - float x = 0.5f * (xT * (g_Viewport.x8_width - 12.f) + 12.f); + if (x4c_saveUI) + x4c_saveUI->Draw(); - CTexturedQuadFilter::Vert verts[] = - { - {{-x, 0.f, z}, {0.f, 0.f}}, - {{-x, 0.f, -z}, {0.f, 1.f}}, - {{x, 0.f, z}, {1.f, 0.f}}, - {{x, 0.f, -z}, {1.f, 1.f}} - }; + if (x44_messageScreen) + x44_messageScreen->Draw(); - if (!m_deathRenderTexQuad) - m_deathRenderTexQuad.emplace(EFilterType::Blend, CGraphics::g_SpareTexture.get()); - m_deathRenderTexQuad->drawVerts(zeus::CColor(1.f, colT), verts); + if (x48_pauseScreen) + x48_pauseScreen->Draw(); - if (!m_deathDotQuad) - m_deathDotQuad.emplace(EFilterType::Multiply, x50_deathDot); - m_deathDotQuad->drawVerts(zeus::CColor(1.f, colT), verts); - } + xf8_camFilter.Draw(); + + if (stateMgr.GetPlayer().GetDeathTime() > 0.f) { + float dieDur; + if (stateMgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) + dieDur = 2.5f; + else + dieDur = 6.f; + + float alpha = zeus::clamp(0.f, stateMgr.GetPlayer().GetDeathTime() / dieDur, 1.f); + m_deathWhiteout.draw(zeus::CColor(1.f, alpha)); + + float zStart = dieDur - 0.5f - 0.5f - 1.f; + float xStart = 0.5f - zStart; + float colStart = 0.5f - xStart; + if (stateMgr.GetPlayer().GetDeathTime() > zStart) { + float zT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - zStart) / 0.5f, 1.f); + float xT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - xStart) / 0.5f, 1.f); + float colT = 1.f - zeus::clamp(0.f, (stateMgr.GetPlayer().GetDeathTime() - colStart) / 0.5f, 1.f); + SClipScreenRect rect(g_Viewport); + CGraphics::ResolveSpareTexture(rect); + m_deathBlackout.draw(zeus::CColor::skBlack); + float z = 0.5f * (zT * zT * zT * zT * zT * (g_Viewport.xc_height - 12.f) + 12.f); + float x = 0.5f * (xT * (g_Viewport.x8_width - 12.f) + 12.f); + + CTexturedQuadFilter::Vert verts[] = {{{-x, 0.f, z}, {0.f, 0.f}}, + {{-x, 0.f, -z}, {0.f, 1.f}}, + {{x, 0.f, z}, {1.f, 0.f}}, + {{x, 0.f, -z}, {1.f, 1.f}}}; + + if (!m_deathRenderTexQuad) + m_deathRenderTexQuad.emplace(EFilterType::Blend, CGraphics::g_SpareTexture.get()); + m_deathRenderTexQuad->drawVerts(zeus::CColor(1.f, colT), verts); + + if (!m_deathDotQuad) + m_deathDotQuad.emplace(EFilterType::Multiply, x50_deathDot); + m_deathDotQuad->drawVerts(zeus::CColor(1.f, colT), verts); } + } } -void CInGameGuiManager::ShowPauseGameHudMessage(CStateManager& stateMgr, CAssetId pauseMsg, float time) -{ - x124_pauseGameHudMessage = pauseMsg; - x128_pauseGameHudTime = time; - PauseGame(stateMgr, EInGameGuiState::PauseHUDMessage); +void CInGameGuiManager::ShowPauseGameHudMessage(CStateManager& stateMgr, CAssetId pauseMsg, float time) { + x124_pauseGameHudMessage = pauseMsg; + x128_pauseGameHudTime = time; + PauseGame(stateMgr, EInGameGuiState::PauseHUDMessage); } -void CInGameGuiManager::PauseGame(CStateManager& stateMgr, EInGameGuiState state) -{ - g_InputGenerator->SetMotorState(EIOPort::Zero, EMotorState::Stop); - CSfxManager::SetChannel(CSfxManager::ESfxChannels::PauseScreen); - BeginStateTransition(state, stateMgr); +void CInGameGuiManager::PauseGame(CStateManager& stateMgr, EInGameGuiState state) { + g_InputGenerator->SetMotorState(EIOPort::Zero, EMotorState::Stop); + CSfxManager::SetChannel(CSfxManager::ESfxChannels::PauseScreen); + BeginStateTransition(state, stateMgr); } -void CInGameGuiManager::StartFadeIn() -{ - xf8_camFilter.SetFilter(EFilterType::Multiply, - EFilterShape::Fullscreen, - 0.f, zeus::CColor::skBlack, -1); - xf8_camFilter.DisableFilter(0.5f); +void CInGameGuiManager::StartFadeIn() { + xf8_camFilter.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, zeus::CColor::skBlack, -1); + xf8_camFilter.DisableFilter(0.5f); } -bool CInGameGuiManager::GetIsGameDraw() const -{ - // Always draw world for URDE, even while paused - return true; - //return x3c_pauseScreenBlur->IsGameDraw(); +bool CInGameGuiManager::GetIsGameDraw() const { + // Always draw world for URDE, even while paused + return true; + // return x3c_pauseScreenBlur->IsGameDraw(); } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CInGameGuiManager.hpp b/Runtime/MP1/CInGameGuiManager.hpp index 7d7c2e997..94e2e6969 100644 --- a/Runtime/MP1/CInGameGuiManager.hpp +++ b/Runtime/MP1/CInGameGuiManager.hpp @@ -16,8 +16,7 @@ #include "CInGameGuiManagerCommon.hpp" #include "Graphics/Shaders/CRandomStaticFilter.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CArchitectureQueue; class CDependencyGroup; @@ -27,125 +26,112 @@ class CGuiModel; class CGuiCamera; class CAutoMapper; -namespace MP1 -{ +namespace MP1 { class CPauseScreenBlur; class CSamusHud; class CPauseScreen; -class CInGameGuiManager -{ +class CInGameGuiManager { public: - using EHelmetVisMode = DataSpec::ITweakGui::EHelmetVisMode; - using EHudVisMode = DataSpec::ITweakGui::EHudVisMode; + using EHelmetVisMode = DataSpec::ITweakGui::EHelmetVisMode; + using EHudVisMode = DataSpec::ITweakGui::EHudVisMode; private: - enum class ELoadPhase - { - LoadDepsGroup = 0, - PreLoadDeps, - LoadDeps, - Done + enum class ELoadPhase { LoadDepsGroup = 0, PreLoadDeps, LoadDeps, Done }; + + struct SGuiProfileInfo {}; + + TLockedToken x0_iggmPreLoad; + std::vector x8_preLoadDeps; + ELoadPhase x18_loadPhase = ELoadPhase::LoadDepsGroup; + CRandom16 x1c_rand; + CFaceplateDecoration x20_faceplateDecor; + std::unique_ptr x30_playerVisor; + std::unique_ptr x34_samusHud; + std::unique_ptr x38_autoMapper; + std::unique_ptr x3c_pauseScreenBlur; + std::unique_ptr x40_samusReflection; + std::unique_ptr x44_messageScreen; + std::unique_ptr x48_pauseScreen; + std::unique_ptr x4c_saveUI; + TLockedToken x50_deathDot; + std::vector> x5c_pauseScreenDGRPs; + std::vector> xc8_inGameGuiDGRPs; + std::vector xd8_; + std::vector xe8_pauseResources; + CCameraFilterPass xf8_camFilter; + CAssetId x124_pauseGameHudMessage; + float x128_pauseGameHudTime = 0.f; + std::list x12c_; + u32 x140_ = 0; + CGuiWidget* x144_basewidget_automapper = nullptr; + CGuiModel* x148_model_automapper = nullptr; + CGuiCamera* x14c_basehud_camera = nullptr; + CGuiWidget* x150_basewidget_functional = nullptr; + zeus::CQuaternion x154_automapperRotate; + zeus::CVector3f x164_automapperOffset; + zeus::CQuaternion x170_camRotate; + zeus::CVector3f x180_camOffset; + zeus::CTransform x18c_mapCamXf; + EInGameGuiState x1bc_prevState = EInGameGuiState::Zero; + EInGameGuiState x1c0_nextState = EInGameGuiState::Zero; + SOnScreenTex x1c4_onScreenTex; + float x1d8_onScreenTexAlpha = 0.f; + TLockedToken x1dc_onScreenTexTok; // Used to be heap-allocated + std::experimental::optional m_onScreenQuad; + EHelmetVisMode x1e0_helmetVisMode; + bool x1e4_enableTargetingManager; + bool x1e8_enableAutoMapper; + EHudVisMode x1ec_hudVisMode; + u32 x1f0_enablePlayerVisor; + float x1f4_visorStaticAlpha; + + std::experimental::optional m_deathRenderTexQuad; + std::experimental::optional m_deathDotQuad; + CRandomStaticFilter m_randomStatic = {EFilterType::Blend}; + CColoredQuadFilter m_deathWhiteout = {EFilterType::Blend}; + CColoredQuadFilter m_deathBlackout = {EFilterType::Blend}; + + union { + struct { + bool x1f8_24_ : 1; + bool x1f8_25_playerAlive : 1; + bool x1f8_26_deferTransition : 1; + bool x1f8_27_exitSaveUI : 1; }; + u32 _dummy = 0; + }; - struct SGuiProfileInfo - { - - }; - - TLockedToken x0_iggmPreLoad; - std::vector x8_preLoadDeps; - ELoadPhase x18_loadPhase = ELoadPhase::LoadDepsGroup; - CRandom16 x1c_rand; - CFaceplateDecoration x20_faceplateDecor; - std::unique_ptr x30_playerVisor; - std::unique_ptr x34_samusHud; - std::unique_ptr x38_autoMapper; - std::unique_ptr x3c_pauseScreenBlur; - std::unique_ptr x40_samusReflection; - std::unique_ptr x44_messageScreen; - std::unique_ptr x48_pauseScreen; - std::unique_ptr x4c_saveUI; - TLockedToken x50_deathDot; - std::vector> x5c_pauseScreenDGRPs; - std::vector> xc8_inGameGuiDGRPs; - std::vector xd8_; - std::vector xe8_pauseResources; - CCameraFilterPass xf8_camFilter; - CAssetId x124_pauseGameHudMessage; - float x128_pauseGameHudTime = 0.f; - std::list x12c_; - u32 x140_ = 0; - CGuiWidget* x144_basewidget_automapper = nullptr; - CGuiModel* x148_model_automapper = nullptr; - CGuiCamera* x14c_basehud_camera = nullptr; - CGuiWidget* x150_basewidget_functional = nullptr; - zeus::CQuaternion x154_automapperRotate; - zeus::CVector3f x164_automapperOffset; - zeus::CQuaternion x170_camRotate; - zeus::CVector3f x180_camOffset; - zeus::CTransform x18c_mapCamXf; - EInGameGuiState x1bc_prevState = EInGameGuiState::Zero; - EInGameGuiState x1c0_nextState = EInGameGuiState::Zero; - SOnScreenTex x1c4_onScreenTex; - float x1d8_onScreenTexAlpha = 0.f; - TLockedToken x1dc_onScreenTexTok; // Used to be heap-allocated - std::experimental::optional m_onScreenQuad; - EHelmetVisMode x1e0_helmetVisMode; - bool x1e4_enableTargetingManager; - bool x1e8_enableAutoMapper; - EHudVisMode x1ec_hudVisMode; - u32 x1f0_enablePlayerVisor; - float x1f4_visorStaticAlpha; - - std::experimental::optional m_deathRenderTexQuad; - std::experimental::optional m_deathDotQuad; - CRandomStaticFilter m_randomStatic = { EFilterType::Blend }; - CColoredQuadFilter m_deathWhiteout = { EFilterType::Blend }; - CColoredQuadFilter m_deathBlackout = { EFilterType::Blend }; - - union - { - struct - { - bool x1f8_24_ : 1; - bool x1f8_25_playerAlive : 1; - bool x1f8_26_deferTransition : 1; - bool x1f8_27_exitSaveUI : 1; - }; - u32 _dummy = 0; - }; - - static std::vector> LockPauseScreenDependencies(); - bool CheckDGRPLoadComplete() const; - void BeginStateTransition(EInGameGuiState state, CStateManager& stateMgr); - void EnsureStates(CStateManager& stateMgr); - void DoStateTransition(CStateManager& stateMgr); - void DestroyAreaTextures(CStateManager& stateMgr); - void TryReloadAreaTextures(); - bool IsInGameStateNotTransitioning() const; - bool IsInPausedStateNotTransitioning() const; - void UpdateAutoMapper(float dt, const CStateManager& stateMgr); - void OnNewPauseScreenState(CArchitectureQueue& archQueue); - void RefreshHudOptions(); + static std::vector> LockPauseScreenDependencies(); + bool CheckDGRPLoadComplete() const; + void BeginStateTransition(EInGameGuiState state, CStateManager& stateMgr); + void EnsureStates(CStateManager& stateMgr); + void DoStateTransition(CStateManager& stateMgr); + void DestroyAreaTextures(CStateManager& stateMgr); + void TryReloadAreaTextures(); + bool IsInGameStateNotTransitioning() const; + bool IsInPausedStateNotTransitioning() const; + void UpdateAutoMapper(float dt, const CStateManager& stateMgr); + void OnNewPauseScreenState(CArchitectureQueue& archQueue); + void RefreshHudOptions(); public: - CInGameGuiManager(CStateManager& stateMgr, CArchitectureQueue& archQueue); - bool CheckLoadComplete(CStateManager& stateMgr); - void Update(CStateManager& stateMgr, float dt, CArchitectureQueue& archQueue, bool useHud); - void ProcessControllerInput(CStateManager& stateMgr, const CFinalInput& input, - CArchitectureQueue& archQueue); - void PreDraw(CStateManager& stateMgr, bool cameraActive); - void Draw(CStateManager& stateMgr); - void ShowPauseGameHudMessage(CStateManager& stateMgr, CAssetId pauseMsg, float time); - void PauseGame(CStateManager& stateMgr, EInGameGuiState state); - void StartFadeIn(); - bool WasInGame() const { return x1bc_prevState >= EInGameGuiState::Zero && x1bc_prevState <= EInGameGuiState::InGame; } - bool IsInGame() const { return x1c0_nextState >= EInGameGuiState::Zero && x1c0_nextState <= EInGameGuiState::InGame; } - bool IsInSaveUI() const { return x1f8_27_exitSaveUI; } - bool GetIsGameDraw() const; + CInGameGuiManager(CStateManager& stateMgr, CArchitectureQueue& archQueue); + bool CheckLoadComplete(CStateManager& stateMgr); + void Update(CStateManager& stateMgr, float dt, CArchitectureQueue& archQueue, bool useHud); + void ProcessControllerInput(CStateManager& stateMgr, const CFinalInput& input, CArchitectureQueue& archQueue); + void PreDraw(CStateManager& stateMgr, bool cameraActive); + void Draw(CStateManager& stateMgr); + void ShowPauseGameHudMessage(CStateManager& stateMgr, CAssetId pauseMsg, float time); + void PauseGame(CStateManager& stateMgr, EInGameGuiState state); + void StartFadeIn(); + bool WasInGame() const { + return x1bc_prevState >= EInGameGuiState::Zero && x1bc_prevState <= EInGameGuiState::InGame; + } + bool IsInGame() const { return x1c0_nextState >= EInGameGuiState::Zero && x1c0_nextState <= EInGameGuiState::InGame; } + bool IsInSaveUI() const { return x1f8_27_exitSaveUI; } + bool GetIsGameDraw() const; }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CInGameGuiManagerCommon.hpp b/Runtime/MP1/CInGameGuiManagerCommon.hpp index 6b6832e86..f403ecfff 100644 --- a/Runtime/MP1/CInGameGuiManagerCommon.hpp +++ b/Runtime/MP1/CInGameGuiManagerCommon.hpp @@ -2,19 +2,8 @@ #include "RetroTypes.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -enum class EInGameGuiState -{ - Zero, - InGame, - MapScreen, - PauseGame, - PauseLogBook, - PauseSaveGame, - PauseHUDMessage -}; +enum class EInGameGuiState { Zero, InGame, MapScreen, PauseGame, PauseLogBook, PauseSaveGame, PauseHUDMessage }; } - diff --git a/Runtime/MP1/CInGameTweakManager.hpp b/Runtime/MP1/CInGameTweakManager.hpp index 7c6c8e014..46b861c4a 100644 --- a/Runtime/MP1/CInGameTweakManager.hpp +++ b/Runtime/MP1/CInGameTweakManager.hpp @@ -2,14 +2,10 @@ #include "CInGameTweakManagerBase.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class CInGameTweakManager : public CInGameTweakManagerBase -{ +class CInGameTweakManager : public CInGameTweakManagerBase { public: - }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CInventoryScreen.cpp b/Runtime/MP1/CInventoryScreen.cpp index 8b66a762d..de19a61fe 100644 --- a/Runtime/MP1/CInventoryScreen.cpp +++ b/Runtime/MP1/CInventoryScreen.cpp @@ -5,18 +5,15 @@ #include "Input/ControlMapper.hpp" #include "GameGlobalObjects.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -struct SInventoryItem -{ - u32 idx; - u32 nameStrIdx; - u32 entryStrIdx; +struct SInventoryItem { + u32 idx; + u32 nameStrIdx; + u32 entryStrIdx; }; -static const SInventoryItem ArmCannonItems[] = -{ +static const SInventoryItem ArmCannonItems[] = { {0, 0x24, 0x46}, // Power Beam {1, 0x25, 0x48}, // Ice Beam {2, 0x26, 0x4a}, // Wave Beam @@ -24,8 +21,7 @@ static const SInventoryItem ArmCannonItems[] = {4, 0x28, 0x4e}, // Phazon Beam }; -static const SInventoryItem MorphballItems[] = -{ +static const SInventoryItem MorphballItems[] = { {5, 0x2e, 0x57}, // Morph Ball {6, 0x2f, 0x58}, // Boost Ball {7, 0x30, 0x59}, // Spider Ball @@ -33,8 +29,7 @@ static const SInventoryItem MorphballItems[] = {9, 0x32, 0x5b}, // Power Bomb }; -static const SInventoryItem SuitItems[] = -{ +static const SInventoryItem SuitItems[] = { {10, 0x33, 0x52}, // Power Suit {11, 0x34, 0x53}, // Varia Suit {12, 0x35, 0x54}, // Gravity Suit @@ -42,16 +37,14 @@ static const SInventoryItem SuitItems[] = {14, 0x37, 0x56}, // Energy Tank }; -static const SInventoryItem VisorItems[] = -{ +static const SInventoryItem VisorItems[] = { {15, 0x38, 0x42}, // Combat Visor {16, 0x39, 0x43}, // Scan Visor {17, 0x3a, 0x44}, // X-Ray Visor {18, 0x3b, 0x45}, // Thermal Visor }; -static const SInventoryItem SecondaryItems[] = -{ +static const SInventoryItem SecondaryItems[] = { {19, 0x3c, 0x4f}, // Space Jump Boots {20, 0x3d, 0x50}, // Grapple Beam {21, 0x3e, 0x51}, // Missile Launcher @@ -59,518 +52,433 @@ static const SInventoryItem SecondaryItems[] = {23, 0x40, 0x5d}, // Beam Combo }; -static const std::pair InventoryRegistry[] = -{ - {5, ArmCannonItems}, - {5, MorphballItems}, - {5, SuitItems}, - {4, VisorItems}, - {5, SecondaryItems}, +static const std::pair InventoryRegistry[] = { + {5, ArmCannonItems}, {5, MorphballItems}, {5, SuitItems}, {4, VisorItems}, {5, SecondaryItems}, }; CInventoryScreen::CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp) -: CPauseScreenBase(mgr, frame, pauseStrg) -{ - CPlayerState& playerState = *mgr.GetPlayerState(); - x19c_samusDoll = std::make_unique(suitDgrp, ballDgrp, - CPlayerState::EPlayerSuit(int(playerState.GetCurrentSuit()) + - playerState.IsFusionEnabled() * 4), - playerState.GetCurrentBeam(), - playerState.HasPowerUp(CPlayerState::EItemType::SpiderBall), - playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam)); +: CPauseScreenBase(mgr, frame, pauseStrg) { + CPlayerState& playerState = *mgr.GetPlayerState(); + x19c_samusDoll = std::make_unique( + suitDgrp, ballDgrp, + CPlayerState::EPlayerSuit(int(playerState.GetCurrentSuit()) + playerState.IsFusionEnabled() * 4), + playerState.GetCurrentBeam(), playerState.HasPowerUp(CPlayerState::EItemType::SpiderBall), + playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam)); } -CInventoryScreen::~CInventoryScreen() -{ - for (int i=0 ; i<5 ; ++i) - { - xd8_textpane_titles[i]->TextSupport().SetFontColor(zeus::CColor::skWhite); - x15c_model_righttitledecos[i]->SetColor(zeus::CColor::skWhite); - x144_model_titles[i]->SetColor(zeus::CColor::skWhite); - } - x8c_model_righthighlight->SetColor(zeus::CColor::skWhite); +CInventoryScreen::~CInventoryScreen() { + for (int i = 0; i < 5; ++i) { + xd8_textpane_titles[i]->TextSupport().SetFontColor(zeus::CColor::skWhite); + x15c_model_righttitledecos[i]->SetColor(zeus::CColor::skWhite); + x144_model_titles[i]->SetColor(zeus::CColor::skWhite); + } + x8c_model_righthighlight->SetColor(zeus::CColor::skWhite); } -bool CInventoryScreen::InputDisabled() const -{ - return std::fabs(x19c_samusDoll->GetViewInterpolation()) > 0 || x1a8_state == EState::Leaving; +bool CInventoryScreen::InputDisabled() const { + return std::fabs(x19c_samusDoll->GetViewInterpolation()) > 0 || x1a8_state == EState::Leaving; } -void CInventoryScreen::TransitioningAway() -{ - x1a8_state = EState::Leaving; -} +void CInventoryScreen::TransitioningAway() { x1a8_state = EState::Leaving; } -void CInventoryScreen::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) -{ - CPauseScreenBase::Update(dt, rand, archQueue); - x19c_samusDoll->Update(dt, rand); +void CInventoryScreen::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) { + CPauseScreenBase::Update(dt, rand, archQueue); + x19c_samusDoll->Update(dt, rand); - if (x10_mode == EMode::TextScroll) - { - if (x1ad_textViewing) - x1a4_textBodyAlpha = std::min(4.f * dt + x1a4_textBodyAlpha, 1.f); - else - x1a4_textBodyAlpha = std::max(0.f, x1a4_textBodyAlpha - 4.f * dt); - x174_textpane_body->SetColor(zeus::CColor(1.f, x1a4_textBodyAlpha)); - x180_basewidget_yicon->SetColor(zeus::CColor(1.f, 1.f - x1a4_textBodyAlpha)); - if (x1a4_textBodyAlpha == 0.f && x1a8_state == EState::Active) - ChangeMode(EMode::RightTable); - } - - x19c_samusDoll->SetInMorphball( - x70_tablegroup_leftlog->GetUserSelection() == 1 && x10_mode != EMode::LeftTable); - UpdateSamusDollPulses(); - if (x1a8_state == EState::Leaving && x1a4_textBodyAlpha == 0.f) - x1a8_state = EState::Inactive; -} - -void CInventoryScreen::Touch() -{ - CPauseScreenBase::Touch(); - x19c_samusDoll->Touch(); -} - -void CInventoryScreen::ProcessControllerInput(const CFinalInput& input) -{ - float viewInterp = x19c_samusDoll->GetViewInterpolation(); - if (x1a8_state == EState::Inactive || (viewInterp != 0.f && viewInterp != 1.f)) - return; - - float absViewInterp = std::fabs(viewInterp); - if (input.PY() && x19c_samusDoll->IsLoaded() && (absViewInterp > 0.f || x10_mode != EMode::TextScroll)) - x19c_samusDoll->BeginViewInterpolate(absViewInterp == 0.f); - - if (absViewInterp == 1.f) - { - if (input.PStart()) - { - x19c_samusDoll->BeginViewInterpolate(false); - x198_26_exitPauseScreen = true; - } - else if (input.PB()) - { - x19c_samusDoll->BeginViewInterpolate(false); - } - } - - if (std::fabs(x19c_samusDoll->GetViewInterpolation()) > 0.f) - { - float motionAmt = input.DeltaTime() * 6.f; - float circleUp = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleUp, input); - float circleDown = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleDown, input); - float circleLeft = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleLeft, input); - float circleRight = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleRight, input); - float moveForward = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveForward, input); - float moveBack = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveBack, input); - float moveLeft = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveLeft, input); - float moveRight = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveRight, input); - float zoomIn = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapZoomIn, input); - float zoomOut = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapZoomOut, input); - - zeus::CVector3f moveVec = {(moveRight - moveLeft) * 0.25f * motionAmt, - (zoomIn - zoomOut) * 0.5f * motionAmt, - (moveForward - moveBack) * 0.25f * motionAmt}; - x19c_samusDoll->SetOffset(moveVec, input.DeltaTime()); - x19c_samusDoll->SetRotation(0.5f * motionAmt * (circleDown - circleUp), - 0.5f * motionAmt * (circleRight - circleLeft), - input.DeltaTime()); - } + if (x10_mode == EMode::TextScroll) { + if (x1ad_textViewing) + x1a4_textBodyAlpha = std::min(4.f * dt + x1a4_textBodyAlpha, 1.f); else - { - x1ad_textViewing = false; - if (x10_mode == EMode::TextScroll) - { - int oldPage = x174_textpane_body->TextSupport().GetPageCounter(); - int newPage = oldPage; - int totalCount = x174_textpane_body->TextSupport().GetTotalPageCount(); - bool lastPage = totalCount - 1 == oldPage; - if (totalCount != -1) - { - if (input.PLAUp()) - newPage = std::max(oldPage - 1, 0); - else if (input.PLADown() || (input.PA() && !lastPage)) - newPage = std::min(oldPage + 1, totalCount - 1); - x174_textpane_body->TextSupport().SetPage(newPage); - if (oldPage != newPage) - CSfxManager::SfxStart(SFXui_pause_screen_next_page, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x198_28_pulseTextArrowTop = newPage > 0; - x198_29_pulseTextArrowBottom = !lastPage; - } - else - { - x198_29_pulseTextArrowBottom = false; - x198_28_pulseTextArrowTop = false; - } - if (!x1ac_textLeaveRequested) - x1ac_textLeaveRequested = input.PB() || (input.PA() && lastPage); - x1ad_textViewing = !x1ac_textLeaveRequested; - } - else - { - x198_29_pulseTextArrowBottom = false; - x198_28_pulseTextArrowTop = false; - } + x1a4_textBodyAlpha = std::max(0.f, x1a4_textBodyAlpha - 4.f * dt); + x174_textpane_body->SetColor(zeus::CColor(1.f, x1a4_textBodyAlpha)); + x180_basewidget_yicon->SetColor(zeus::CColor(1.f, 1.f - x1a4_textBodyAlpha)); + if (x1a4_textBodyAlpha == 0.f && x1a8_state == EState::Active) + ChangeMode(EMode::RightTable); + } - if (x1a8_state != EState::Active) - x1ad_textViewing = false; + x19c_samusDoll->SetInMorphball(x70_tablegroup_leftlog->GetUserSelection() == 1 && x10_mode != EMode::LeftTable); + UpdateSamusDollPulses(); + if (x1a8_state == EState::Leaving && x1a4_textBodyAlpha == 0.f) + x1a8_state = EState::Inactive; +} - CPauseScreenBase::ProcessControllerInput(input); +void CInventoryScreen::Touch() { + CPauseScreenBase::Touch(); + x19c_samusDoll->Touch(); +} + +void CInventoryScreen::ProcessControllerInput(const CFinalInput& input) { + float viewInterp = x19c_samusDoll->GetViewInterpolation(); + if (x1a8_state == EState::Inactive || (viewInterp != 0.f && viewInterp != 1.f)) + return; + + float absViewInterp = std::fabs(viewInterp); + if (input.PY() && x19c_samusDoll->IsLoaded() && (absViewInterp > 0.f || x10_mode != EMode::TextScroll)) + x19c_samusDoll->BeginViewInterpolate(absViewInterp == 0.f); + + if (absViewInterp == 1.f) { + if (input.PStart()) { + x19c_samusDoll->BeginViewInterpolate(false); + x198_26_exitPauseScreen = true; + } else if (input.PB()) { + x19c_samusDoll->BeginViewInterpolate(false); } + } + + if (std::fabs(x19c_samusDoll->GetViewInterpolation()) > 0.f) { + float motionAmt = input.DeltaTime() * 6.f; + float circleUp = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleUp, input); + float circleDown = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleDown, input); + float circleLeft = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleLeft, input); + float circleRight = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapCircleRight, input); + float moveForward = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveForward, input); + float moveBack = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveBack, input); + float moveLeft = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveLeft, input); + float moveRight = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapMoveRight, input); + float zoomIn = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapZoomIn, input); + float zoomOut = ControlMapper::GetAnalogInput(ControlMapper::ECommands::MapZoomOut, input); + + zeus::CVector3f moveVec = {(moveRight - moveLeft) * 0.25f * motionAmt, (zoomIn - zoomOut) * 0.5f * motionAmt, + (moveForward - moveBack) * 0.25f * motionAmt}; + x19c_samusDoll->SetOffset(moveVec, input.DeltaTime()); + x19c_samusDoll->SetRotation(0.5f * motionAmt * (circleDown - circleUp), + 0.5f * motionAmt * (circleRight - circleLeft), input.DeltaTime()); + } else { + x1ad_textViewing = false; + if (x10_mode == EMode::TextScroll) { + int oldPage = x174_textpane_body->TextSupport().GetPageCounter(); + int newPage = oldPage; + int totalCount = x174_textpane_body->TextSupport().GetTotalPageCount(); + bool lastPage = totalCount - 1 == oldPage; + if (totalCount != -1) { + if (input.PLAUp()) + newPage = std::max(oldPage - 1, 0); + else if (input.PLADown() || (input.PA() && !lastPage)) + newPage = std::min(oldPage + 1, totalCount - 1); + x174_textpane_body->TextSupport().SetPage(newPage); + if (oldPage != newPage) + CSfxManager::SfxStart(SFXui_pause_screen_next_page, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x198_28_pulseTextArrowTop = newPage > 0; + x198_29_pulseTextArrowBottom = !lastPage; + } else { + x198_29_pulseTextArrowBottom = false; + x198_28_pulseTextArrowTop = false; + } + if (!x1ac_textLeaveRequested) + x1ac_textLeaveRequested = input.PB() || (input.PA() && lastPage); + x1ad_textViewing = !x1ac_textLeaveRequested; + } else { + x198_29_pulseTextArrowBottom = false; + x198_28_pulseTextArrowTop = false; + } + + if (x1a8_state != EState::Active) + x1ad_textViewing = false; + + CPauseScreenBase::ProcessControllerInput(input); + } } -void CInventoryScreen::Draw(float transInterp, float totalAlpha, float yOff) -{ - CPauseScreenBase::Draw(transInterp, totalAlpha, std::fabs(x19c_samusDoll->GetViewInterpolation())); - x19c_samusDoll->Draw(x4_mgr, transInterp * (1.f - x1a4_textBodyAlpha)); +void CInventoryScreen::Draw(float transInterp, float totalAlpha, float yOff) { + CPauseScreenBase::Draw(transInterp, totalAlpha, std::fabs(x19c_samusDoll->GetViewInterpolation())); + x19c_samusDoll->Draw(x4_mgr, transInterp * (1.f - x1a4_textBodyAlpha)); } -float CInventoryScreen::GetCameraYBias() const -{ - return std::fabs(x19c_samusDoll->GetViewInterpolation()); -} +float CInventoryScreen::GetCameraYBias() const { return std::fabs(x19c_samusDoll->GetViewInterpolation()); } -bool CInventoryScreen::VReady() const -{ +bool CInventoryScreen::VReady() const { return true; } + +bool CInventoryScreen::HasLeftInventoryItem(int idx) const { + CPlayerState& playerState = *x4_mgr.GetPlayerState(); + switch (idx) { + case 0: // Arm Cannon return true; + case 1: // Morphball + return playerState.HasPowerUp(CPlayerState::EItemType::MorphBall); + case 2: // Suit + return true; + case 3: // Visor + return true; + case 4: // Secondary + return playerState.HasPowerUp(CPlayerState::EItemType::SpaceJumpBoots) || + playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam) || + playerState.HasPowerUp(CPlayerState::EItemType::Missiles) || + playerState.HasPowerUp(CPlayerState::EItemType::ChargeBeam) || + playerState.HasPowerUp(CPlayerState::EItemType::SuperMissile) || + playerState.HasPowerUp(CPlayerState::EItemType::IceSpreader) || + playerState.HasPowerUp(CPlayerState::EItemType::Wavebuster) || + playerState.HasPowerUp(CPlayerState::EItemType::Flamethrower); + default: + return false; + } } -bool CInventoryScreen::HasLeftInventoryItem(int idx) const -{ - CPlayerState& playerState = *x4_mgr.GetPlayerState(); - switch (idx) - { - case 0: // Arm Cannon - return true; - case 1: // Morphball - return playerState.HasPowerUp(CPlayerState::EItemType::MorphBall); - case 2: // Suit - return true; - case 3: // Visor - return true; - case 4: // Secondary - return playerState.HasPowerUp(CPlayerState::EItemType::SpaceJumpBoots) || - playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam) || - playerState.HasPowerUp(CPlayerState::EItemType::Missiles) || - playerState.HasPowerUp(CPlayerState::EItemType::ChargeBeam) || - playerState.HasPowerUp(CPlayerState::EItemType::SuperMissile) || - playerState.HasPowerUp(CPlayerState::EItemType::IceSpreader) || - playerState.HasPowerUp(CPlayerState::EItemType::Wavebuster) || - playerState.HasPowerUp(CPlayerState::EItemType::Flamethrower); - default: - return false; +void CInventoryScreen::VActivate() { + for (int i = 0; i < 5; ++i) { + if (HasLeftInventoryItem(i)) { + xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 10)); + } else { + xa8_textpane_categories[i]->TextSupport().SetText(u"??????"); + x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(false); } -} + } -void CInventoryScreen::VActivate() -{ - for (int i=0 ; i<5 ; ++i) - { - if (HasLeftInventoryItem(i)) - { - xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 10)); - } - else - { - xa8_textpane_categories[i]->TextSupport().SetText(u"??????"); - x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(false); - } - } - - x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(9)); - x180_basewidget_yicon->SetVisibility(true, ETraversalMode::Children); + x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(9)); + x180_basewidget_yicon->SetVisibility(true, ETraversalMode::Children); } void CInventoryScreen::RightTableSelectionChanged(int oldSel, int newSel) {} -void CInventoryScreen::UpdateTextBody() -{ - x1ac_textLeaveRequested = false; +void CInventoryScreen::UpdateTextBody() { + x1ac_textLeaveRequested = false; - const SInventoryItem& sel = InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()].second[x1c_rightSel]; - std::u16string entryText = xc_pauseStrg.GetString(sel.entryStrIdx); + const SInventoryItem& sel = InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()].second[x1c_rightSel]; + std::u16string entryText = xc_pauseStrg.GetString(sel.entryStrIdx); - if (sel.idx == 23) // Beam combo - { - CPlayerState& playerState = *x4_mgr.GetPlayerState(); - entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::SuperMissile) ? 71 : 65); - entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::IceSpreader) ? 73 : 65); - entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::Wavebuster) ? 75 : 65); - entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::Flamethrower) ? 77 : 65); - } - - x174_textpane_body->TextSupport().SetText(entryText, true); - x174_textpane_body->TextSupport().SetPage(0); -} - -void CInventoryScreen::ChangedMode(EMode oldMode) -{ - if (x10_mode == EMode::TextScroll) - { - x1ad_textViewing = true; - UpdateTextBody(); - } -} - -bool CInventoryScreen::HasRightInventoryItem(int idx) const -{ + if (sel.idx == 23) // Beam combo + { CPlayerState& playerState = *x4_mgr.GetPlayerState(); - switch (idx) - { - case 0: // Power Beam - return true; - case 1: // Ice Beam - return playerState.HasPowerUp(CPlayerState::EItemType::IceBeam); - case 2: // Wave Beam - return playerState.HasPowerUp(CPlayerState::EItemType::WaveBeam); - case 3: // Plasma Beam - return playerState.HasPowerUp(CPlayerState::EItemType::PlasmaBeam); - case 4: // Phazon Beam - return playerState.HasPowerUp(CPlayerState::EItemType::PhazonSuit); - case 5: // Morph Ball - return playerState.HasPowerUp(CPlayerState::EItemType::MorphBall); - case 6: // Boost Ball - return playerState.HasPowerUp(CPlayerState::EItemType::BoostBall); - case 7: // Spider Ball - return playerState.HasPowerUp(CPlayerState::EItemType::SpiderBall); - case 8: // Morph Ball Bomb - return playerState.HasPowerUp(CPlayerState::EItemType::MorphBallBombs); - case 9: // Power Bomb - return playerState.HasPowerUp(CPlayerState::EItemType::PowerBombs); - case 10: // Power Suit - return true; - case 11: // Varia Suit - return playerState.HasPowerUp(CPlayerState::EItemType::VariaSuit); - case 12: // Gravity Suit - return playerState.HasPowerUp(CPlayerState::EItemType::GravitySuit); - case 13: // Phazon Suit - return playerState.HasPowerUp(CPlayerState::EItemType::PhazonSuit); - case 14: // Energy Tank - return playerState.HasPowerUp(CPlayerState::EItemType::EnergyTanks); - case 15: // Combat Visor - return true; - case 16: // Scan Visor - return playerState.HasPowerUp(CPlayerState::EItemType::ScanVisor); - case 17: // X-Ray Visor - return playerState.HasPowerUp(CPlayerState::EItemType::XRayVisor); - case 18: // Thermal Visor - return playerState.HasPowerUp(CPlayerState::EItemType::ThermalVisor); - case 19: // Space Jump Boots - return playerState.HasPowerUp(CPlayerState::EItemType::SpaceJumpBoots); - case 20: // Grapple Beam - return playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam); - case 21: // Missile Launcher - return playerState.HasPowerUp(CPlayerState::EItemType::Missiles); - case 22: // Charge Beam - return playerState.HasPowerUp(CPlayerState::EItemType::ChargeBeam); - case 23: // Beam Combo - return playerState.HasPowerUp(CPlayerState::EItemType::SuperMissile) || - playerState.HasPowerUp(CPlayerState::EItemType::IceSpreader) || - playerState.HasPowerUp(CPlayerState::EItemType::Wavebuster) || - playerState.HasPowerUp(CPlayerState::EItemType::Flamethrower); - default: - return false; - } + entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::SuperMissile) ? 71 : 65); + entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::IceSpreader) ? 73 : 65); + entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::Wavebuster) ? 75 : 65); + entryText += xc_pauseStrg.GetString(playerState.HasPowerUp(CPlayerState::EItemType::Flamethrower) ? 77 : 65); + } + + x174_textpane_body->TextSupport().SetText(entryText, true); + x174_textpane_body->TextSupport().SetPage(0); } -bool CInventoryScreen::IsRightInventoryItemEquipped(int idx) const -{ - CPlayerState& playerState = *x4_mgr.GetPlayerState(); - switch (idx) - { - case 0: // Power Beam - return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Power; - case 1: // Ice Beam - return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Ice; - case 2: // Wave Beam - return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Wave; - case 3: // Plasma Beam - return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Plasma; - case 4: // Phazon Beam - return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Phazon2; - case 5: // Morph Ball - return playerState.HasPowerUp(CPlayerState::EItemType::MorphBall); - case 6: // Boost Ball - return playerState.HasPowerUp(CPlayerState::EItemType::BoostBall); - case 7: // Spider Ball - return playerState.HasPowerUp(CPlayerState::EItemType::SpiderBall); - case 8: // Morph Ball Bomb - return playerState.HasPowerUp(CPlayerState::EItemType::MorphBallBombs); - case 9: // Power Bomb - return playerState.HasPowerUp(CPlayerState::EItemType::PowerBombs); - case 10: // Power Suit - return playerState.GetCurrentSuit() == CPlayerState::EPlayerSuit::Power; - case 11: // Varia Suit - return playerState.GetCurrentSuit() == CPlayerState::EPlayerSuit::Varia; - case 12: // Gravity Suit - return playerState.GetCurrentSuit() == CPlayerState::EPlayerSuit::Gravity; - case 13: // Phazon Suit - return playerState.GetCurrentSuit() == CPlayerState::EPlayerSuit::Phazon; - case 14: // Energy Tank - return playerState.HasPowerUp(CPlayerState::EItemType::EnergyTanks); - case 15: // Combat Visor - return playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat; - case 16: // Scan Visor - return playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan; - case 17: // X-Ray Visor - return playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay; - case 18: // Thermal Visor - return playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal; - case 19: // Space Jump Boots - return playerState.HasPowerUp(CPlayerState::EItemType::SpaceJumpBoots); - case 20: // Grapple Beam - return playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam); - case 21: // Missile Launcher - return playerState.HasPowerUp(CPlayerState::EItemType::Missiles); - case 22: // Charge Beam - return playerState.HasPowerUp(CPlayerState::EItemType::ChargeBeam); - case 23: // Beam Combo - return playerState.HasPowerUp(CPlayerState::EItemType::SuperMissile) || - playerState.HasPowerUp(CPlayerState::EItemType::IceSpreader) || - playerState.HasPowerUp(CPlayerState::EItemType::Wavebuster) || - playerState.HasPowerUp(CPlayerState::EItemType::Flamethrower); - default: - return false; - } +void CInventoryScreen::ChangedMode(EMode oldMode) { + if (x10_mode == EMode::TextScroll) { + x1ad_textViewing = true; + UpdateTextBody(); + } } -void CInventoryScreen::UpdateRightTable() -{ - CPauseScreenBase::UpdateRightTable(); - const std::pair& category = - InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; - - int minSel = INT_MAX; - for (int i=0 ; i<5 ; ++i) - { - CGuiTextPane* title = xd8_textpane_titles[i]; - if (i < category.first) - { - if (HasRightInventoryItem(category.second[i].idx)) - { - title->TextSupport().SetText(xc_pauseStrg.GetString(category.second[i].nameStrIdx)); - x84_tablegroup_rightlog->GetWorkerWidget(i + 1)->SetIsSelectable(true); - if (i < minSel) - minSel = i; - } - else - { - title->TextSupport().SetText(u"??????"); - x84_tablegroup_rightlog->GetWorkerWidget(i + 1)->SetIsSelectable(false); - } - } - else - { - title->TextSupport().SetText(u"??????"); - } - } - - if (minSel != INT_MAX) - { - x1c_rightSel = minSel; - SetRightTableSelection(x1c_rightSel, x1c_rightSel); - } - - x84_tablegroup_rightlog->GetWorkerWidget(0)->SetIsSelectable(false); - x84_tablegroup_rightlog->GetWorkerWidget(x84_tablegroup_rightlog->GetElementCount() - 1)->SetIsSelectable(false); - zeus::CColor inactiveColor = g_tweakGuiColors->GetPauseItemAmberColor(); - inactiveColor.a() = 0.5f; - UpdateRightLogColors(false, g_tweakGuiColors->GetPauseItemAmberColor(), inactiveColor); -} - -bool CInventoryScreen::ShouldLeftTableAdvance() const -{ - return x19c_samusDoll->IsLoaded(); -} - -bool CInventoryScreen::ShouldRightTableAdvance() const -{ - return std::fabs(x19c_samusDoll->GetViewInterpolation()) == 0.f; -} - -u32 CInventoryScreen::GetRightTableCount() const -{ - return InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()].first; -} - -bool CInventoryScreen::IsRightLogDynamic() const -{ +bool CInventoryScreen::HasRightInventoryItem(int idx) const { + CPlayerState& playerState = *x4_mgr.GetPlayerState(); + switch (idx) { + case 0: // Power Beam return true; + case 1: // Ice Beam + return playerState.HasPowerUp(CPlayerState::EItemType::IceBeam); + case 2: // Wave Beam + return playerState.HasPowerUp(CPlayerState::EItemType::WaveBeam); + case 3: // Plasma Beam + return playerState.HasPowerUp(CPlayerState::EItemType::PlasmaBeam); + case 4: // Phazon Beam + return playerState.HasPowerUp(CPlayerState::EItemType::PhazonSuit); + case 5: // Morph Ball + return playerState.HasPowerUp(CPlayerState::EItemType::MorphBall); + case 6: // Boost Ball + return playerState.HasPowerUp(CPlayerState::EItemType::BoostBall); + case 7: // Spider Ball + return playerState.HasPowerUp(CPlayerState::EItemType::SpiderBall); + case 8: // Morph Ball Bomb + return playerState.HasPowerUp(CPlayerState::EItemType::MorphBallBombs); + case 9: // Power Bomb + return playerState.HasPowerUp(CPlayerState::EItemType::PowerBombs); + case 10: // Power Suit + return true; + case 11: // Varia Suit + return playerState.HasPowerUp(CPlayerState::EItemType::VariaSuit); + case 12: // Gravity Suit + return playerState.HasPowerUp(CPlayerState::EItemType::GravitySuit); + case 13: // Phazon Suit + return playerState.HasPowerUp(CPlayerState::EItemType::PhazonSuit); + case 14: // Energy Tank + return playerState.HasPowerUp(CPlayerState::EItemType::EnergyTanks); + case 15: // Combat Visor + return true; + case 16: // Scan Visor + return playerState.HasPowerUp(CPlayerState::EItemType::ScanVisor); + case 17: // X-Ray Visor + return playerState.HasPowerUp(CPlayerState::EItemType::XRayVisor); + case 18: // Thermal Visor + return playerState.HasPowerUp(CPlayerState::EItemType::ThermalVisor); + case 19: // Space Jump Boots + return playerState.HasPowerUp(CPlayerState::EItemType::SpaceJumpBoots); + case 20: // Grapple Beam + return playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam); + case 21: // Missile Launcher + return playerState.HasPowerUp(CPlayerState::EItemType::Missiles); + case 22: // Charge Beam + return playerState.HasPowerUp(CPlayerState::EItemType::ChargeBeam); + case 23: // Beam Combo + return playerState.HasPowerUp(CPlayerState::EItemType::SuperMissile) || + playerState.HasPowerUp(CPlayerState::EItemType::IceSpreader) || + playerState.HasPowerUp(CPlayerState::EItemType::Wavebuster) || + playerState.HasPowerUp(CPlayerState::EItemType::Flamethrower); + default: + return false; + } } +bool CInventoryScreen::IsRightInventoryItemEquipped(int idx) const { + CPlayerState& playerState = *x4_mgr.GetPlayerState(); + switch (idx) { + case 0: // Power Beam + return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Power; + case 1: // Ice Beam + return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Ice; + case 2: // Wave Beam + return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Wave; + case 3: // Plasma Beam + return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Plasma; + case 4: // Phazon Beam + return playerState.GetCurrentBeam() == CPlayerState::EBeamId::Phazon2; + case 5: // Morph Ball + return playerState.HasPowerUp(CPlayerState::EItemType::MorphBall); + case 6: // Boost Ball + return playerState.HasPowerUp(CPlayerState::EItemType::BoostBall); + case 7: // Spider Ball + return playerState.HasPowerUp(CPlayerState::EItemType::SpiderBall); + case 8: // Morph Ball Bomb + return playerState.HasPowerUp(CPlayerState::EItemType::MorphBallBombs); + case 9: // Power Bomb + return playerState.HasPowerUp(CPlayerState::EItemType::PowerBombs); + case 10: // Power Suit + return playerState.GetCurrentSuit() == CPlayerState::EPlayerSuit::Power; + case 11: // Varia Suit + return playerState.GetCurrentSuit() == CPlayerState::EPlayerSuit::Varia; + case 12: // Gravity Suit + return playerState.GetCurrentSuit() == CPlayerState::EPlayerSuit::Gravity; + case 13: // Phazon Suit + return playerState.GetCurrentSuit() == CPlayerState::EPlayerSuit::Phazon; + case 14: // Energy Tank + return playerState.HasPowerUp(CPlayerState::EItemType::EnergyTanks); + case 15: // Combat Visor + return playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat; + case 16: // Scan Visor + return playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan; + case 17: // X-Ray Visor + return playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay; + case 18: // Thermal Visor + return playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal; + case 19: // Space Jump Boots + return playerState.HasPowerUp(CPlayerState::EItemType::SpaceJumpBoots); + case 20: // Grapple Beam + return playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam); + case 21: // Missile Launcher + return playerState.HasPowerUp(CPlayerState::EItemType::Missiles); + case 22: // Charge Beam + return playerState.HasPowerUp(CPlayerState::EItemType::ChargeBeam); + case 23: // Beam Combo + return playerState.HasPowerUp(CPlayerState::EItemType::SuperMissile) || + playerState.HasPowerUp(CPlayerState::EItemType::IceSpreader) || + playerState.HasPowerUp(CPlayerState::EItemType::Wavebuster) || + playerState.HasPowerUp(CPlayerState::EItemType::Flamethrower); + default: + return false; + } +} + +void CInventoryScreen::UpdateRightTable() { + CPauseScreenBase::UpdateRightTable(); + const std::pair& category = InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; + + int minSel = INT_MAX; + for (int i = 0; i < 5; ++i) { + CGuiTextPane* title = xd8_textpane_titles[i]; + if (i < category.first) { + if (HasRightInventoryItem(category.second[i].idx)) { + title->TextSupport().SetText(xc_pauseStrg.GetString(category.second[i].nameStrIdx)); + x84_tablegroup_rightlog->GetWorkerWidget(i + 1)->SetIsSelectable(true); + if (i < minSel) + minSel = i; + } else { + title->TextSupport().SetText(u"??????"); + x84_tablegroup_rightlog->GetWorkerWidget(i + 1)->SetIsSelectable(false); + } + } else { + title->TextSupport().SetText(u"??????"); + } + } + + if (minSel != INT_MAX) { + x1c_rightSel = minSel; + SetRightTableSelection(x1c_rightSel, x1c_rightSel); + } + + x84_tablegroup_rightlog->GetWorkerWidget(0)->SetIsSelectable(false); + x84_tablegroup_rightlog->GetWorkerWidget(x84_tablegroup_rightlog->GetElementCount() - 1)->SetIsSelectable(false); + zeus::CColor inactiveColor = g_tweakGuiColors->GetPauseItemAmberColor(); + inactiveColor.a() = 0.5f; + UpdateRightLogColors(false, g_tweakGuiColors->GetPauseItemAmberColor(), inactiveColor); +} + +bool CInventoryScreen::ShouldLeftTableAdvance() const { return x19c_samusDoll->IsLoaded(); } + +bool CInventoryScreen::ShouldRightTableAdvance() const { + return std::fabs(x19c_samusDoll->GetViewInterpolation()) == 0.f; +} + +u32 CInventoryScreen::GetRightTableCount() const { + return InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()].first; +} + +bool CInventoryScreen::IsRightLogDynamic() const { return true; } + void CInventoryScreen::UpdateRightLogColors(bool active, const zeus::CColor& activeColor, - const zeus::CColor& inactiveColor) -{ - x80_basewidget_rightlog->SetColor(active ? zeus::CColor::skWhite : zeus::CColor(1.f, 0.71f)); - const std::pair& cat = - InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; - for (u32 i=0 ; i<5 ; ++i) - { - if (i < cat.first && IsRightInventoryItemEquipped(cat.second[i].idx)) - { - x15c_model_righttitledecos[i]->SetColor(g_tweakGuiColors->GetPauseItemBlueColor()); - xd8_textpane_titles[i]->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemBlueColor()); - } - else - { - x15c_model_righttitledecos[i]->SetColor(activeColor); - xd8_textpane_titles[i]->TextSupport().SetFontColor(activeColor); - } + const zeus::CColor& inactiveColor) { + x80_basewidget_rightlog->SetColor(active ? zeus::CColor::skWhite : zeus::CColor(1.f, 0.71f)); + const std::pair& cat = InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; + for (u32 i = 0; i < 5; ++i) { + if (i < cat.first && IsRightInventoryItemEquipped(cat.second[i].idx)) { + x15c_model_righttitledecos[i]->SetColor(g_tweakGuiColors->GetPauseItemBlueColor()); + xd8_textpane_titles[i]->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemBlueColor()); + } else { + x15c_model_righttitledecos[i]->SetColor(activeColor); + xd8_textpane_titles[i]->TextSupport().SetFontColor(activeColor); } + } } -void CInventoryScreen::UpdateRightLogHighlight(bool active, int idx, - const zeus::CColor& activeColor, - const zeus::CColor& inactiveColor) -{ - zeus::CColor actColor = g_tweakGuiColors->GetPauseItemAmberColor() * activeColor; - zeus::CColor inactColor = g_tweakGuiColors->GetPauseItemAmberColor() * inactiveColor; +void CInventoryScreen::UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, + const zeus::CColor& inactiveColor) { + zeus::CColor actColor = g_tweakGuiColors->GetPauseItemAmberColor() * activeColor; + zeus::CColor inactColor = g_tweakGuiColors->GetPauseItemAmberColor() * inactiveColor; - const std::pair& cat = - InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; - for (u32 i=0 ; i<5 ; ++i) - { - bool act = i == idx && active; - if (i < cat.first && IsRightInventoryItemEquipped(cat.second[i].idx) && act) - x8c_model_righthighlight->SetColor(g_tweakGuiColors->GetPauseItemBlueColor()); - else if (act) - x8c_model_righthighlight->SetColor(actColor); - x144_model_titles[i]->SetColor(act ? actColor : inactColor); + const std::pair& cat = InventoryRegistry[x70_tablegroup_leftlog->GetUserSelection()]; + for (u32 i = 0; i < 5; ++i) { + bool act = i == idx && active; + if (i < cat.first && IsRightInventoryItemEquipped(cat.second[i].idx) && act) + x8c_model_righthighlight->SetColor(g_tweakGuiColors->GetPauseItemBlueColor()); + else if (act) + x8c_model_righthighlight->SetColor(actColor); + x144_model_titles[i]->SetColor(act ? actColor : inactColor); + } +} + +void CInventoryScreen::UpdateSamusDollPulses() { + bool pulseSuit = false; + bool pulseBeam = false; + bool pulseGrapple = false; + bool pulseBoots = false; + bool pulseVisor = false; + int userSel = x70_tablegroup_leftlog->GetUserSelection(); + + if (x10_mode == EMode::RightTable) { + if (userSel == 2) + pulseSuit = true; + else if (userSel == 0) + pulseBeam = true; + else if (userSel == 3) + pulseVisor = true; + else if (userSel == 4) { + pulseGrapple = SecondaryItems[x1c_rightSel].idx == 20; + pulseBoots = SecondaryItems[x1c_rightSel].idx == 19; + if (SecondaryItems[x1c_rightSel].idx == 21) + pulseBeam = true; } + } + + x19c_samusDoll->SetPulseSuit(pulseSuit); + x19c_samusDoll->SetPulseBeam(pulseBeam); + x19c_samusDoll->SetPulseGrapple(pulseGrapple); + x19c_samusDoll->SetPulseBoots(pulseBoots); + x19c_samusDoll->SetPulseVisor(pulseVisor); } -void CInventoryScreen::UpdateSamusDollPulses() -{ - bool pulseSuit = false; - bool pulseBeam = false; - bool pulseGrapple = false; - bool pulseBoots = false; - bool pulseVisor = false; - int userSel = x70_tablegroup_leftlog->GetUserSelection(); - - if (x10_mode == EMode::RightTable) - { - if (userSel == 2) - pulseSuit = true; - else if (userSel == 0) - pulseBeam = true; - else if (userSel == 3) - pulseVisor = true; - else if (userSel == 4) - { - pulseGrapple = SecondaryItems[x1c_rightSel].idx == 20; - pulseBoots = SecondaryItems[x1c_rightSel].idx == 19; - if (SecondaryItems[x1c_rightSel].idx == 21) - pulseBeam = true; - } - } - - x19c_samusDoll->SetPulseSuit(pulseSuit); - x19c_samusDoll->SetPulseBeam(pulseBeam); - x19c_samusDoll->SetPulseGrapple(pulseGrapple); - x19c_samusDoll->SetPulseBoots(pulseBoots); - x19c_samusDoll->SetPulseVisor(pulseVisor); -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CInventoryScreen.hpp b/Runtime/MP1/CInventoryScreen.hpp index 9d3fba955..1b31063cb 100644 --- a/Runtime/MP1/CInventoryScreen.hpp +++ b/Runtime/MP1/CInventoryScreen.hpp @@ -4,59 +4,52 @@ #include "CPauseScreenBase.hpp" #include "CSamusDoll.hpp" -namespace urde -{ +namespace urde { class CDependencyGroup; -namespace MP1 -{ +namespace MP1 { -class CInventoryScreen : public CPauseScreenBase -{ - enum class EState - { - Active, - Leaving, - Inactive - }; +class CInventoryScreen : public CPauseScreenBase { + enum class EState { Active, Leaving, Inactive }; - std::unique_ptr x19c_samusDoll; - float x1a0_ = 0.f; - float x1a4_textBodyAlpha = 0.f; - EState x1a8_state = EState::Active; - bool x1ac_textLeaveRequested = false; - bool x1ad_textViewing; + std::unique_ptr x19c_samusDoll; + float x1a0_ = 0.f; + float x1a4_textBodyAlpha = 0.f; + EState x1a8_state = EState::Active; + bool x1ac_textLeaveRequested = false; + bool x1ad_textViewing; + + void UpdateSamusDollPulses(); + bool HasLeftInventoryItem(int idx) const; + bool HasRightInventoryItem(int idx) const; + bool IsRightInventoryItemEquipped(int idx) const; + void UpdateTextBody(); - void UpdateSamusDollPulses(); - bool HasLeftInventoryItem(int idx) const; - bool HasRightInventoryItem(int idx) const; - bool IsRightInventoryItemEquipped(int idx) const; - void UpdateTextBody(); public: - CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, - const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp); - ~CInventoryScreen(); + CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, + const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp); + ~CInventoryScreen(); - bool InputDisabled() const; - void TransitioningAway(); - void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); - void Touch(); - void ProcessControllerInput(const CFinalInput& input); - void Draw(float transInterp, float totalAlpha, float yOff); - float GetCameraYBias() const; - bool VReady() const; - void VActivate(); - void RightTableSelectionChanged(int oldSel, int newSel); - void ChangedMode(EMode oldMode); - void UpdateRightTable(); - bool ShouldLeftTableAdvance() const; - bool ShouldRightTableAdvance() const; - u32 GetRightTableCount() const; - bool IsRightLogDynamic() const; - void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor); - void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor); + bool InputDisabled() const; + void TransitioningAway(); + void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); + void Touch(); + void ProcessControllerInput(const CFinalInput& input); + void Draw(float transInterp, float totalAlpha, float yOff); + float GetCameraYBias() const; + bool VReady() const; + void VActivate(); + void RightTableSelectionChanged(int oldSel, int newSel); + void ChangedMode(EMode oldMode); + void UpdateRightTable(); + bool ShouldLeftTableAdvance() const; + bool ShouldRightTableAdvance() const; + u32 GetRightTableCount() const; + bool IsRightLogDynamic() const; + void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor); + void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, + const zeus::CColor& inactiveColor); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CLogBookScreen.cpp b/Runtime/MP1/CLogBookScreen.cpp index f710c6680..5e6df9f32 100644 --- a/Runtime/MP1/CLogBookScreen.cpp +++ b/Runtime/MP1/CLogBookScreen.cpp @@ -5,429 +5,346 @@ #include "GuiSys/CAuiImagePane.hpp" #include "MP1.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CLogBookScreen::CLogBookScreen(const CStateManager& mgr, CGuiFrame& frame, - const CStringTable& pauseStrg) -: CPauseScreenBase(mgr, frame, pauseStrg) -{ - x19c_scanCompletes.resize(5); - x200_viewScans.resize(5); - x258_artifactDoll = std::make_unique(); - CMain::EnsureWorldPaksReady(); - InitializeLogBook(); +CLogBookScreen::CLogBookScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg) +: CPauseScreenBase(mgr, frame, pauseStrg) { + x19c_scanCompletes.resize(5); + x200_viewScans.resize(5); + x258_artifactDoll = std::make_unique(); + CMain::EnsureWorldPaksReady(); + InitializeLogBook(); } -CLogBookScreen::~CLogBookScreen() -{ - CArtifactDoll::CompleteArtifactHeadScan(x4_mgr); - for (CGuiModel* model : x144_model_titles) - model->SetLocalTransform(model->GetTransform()); - CMain::EnsureWorldPakReady(g_GameState->CurrentWorldAssetId()); +CLogBookScreen::~CLogBookScreen() { + CArtifactDoll::CompleteArtifactHeadScan(x4_mgr); + for (CGuiModel* model : x144_model_titles) + model->SetLocalTransform(model->GetTransform()); + CMain::EnsureWorldPakReady(g_GameState->CurrentWorldAssetId()); } bool CLogBookScreen::IsScanComplete(CSaveWorld::EScanCategory category, CAssetId scan, - const CPlayerState& playerState) -{ - return true; - float time = playerState.GetScanTime(scan); - if (category == CSaveWorld::EScanCategory::Artifact) - return time >= 0.5f; + const CPlayerState& playerState) { + return true; + float time = playerState.GetScanTime(scan); + if (category == CSaveWorld::EScanCategory::Artifact) + return time >= 0.5f; + else + return time >= 1.f; +} + +void CLogBookScreen::InitializeLogBook() { + for (int i = 0; i < 5; ++i) + x19c_scanCompletes[i].reserve(g_MemoryCardSys->GetScanCategoryCount(CSaveWorld::EScanCategory(i + 1))); + + CPlayerState& playerState = *x4_mgr.GetPlayerState(); + for (const std::pair& scanState : g_MemoryCardSys->GetScanStates()) { + if (scanState.second == CSaveWorld::EScanCategory::None) + continue; + bool complete = IsScanComplete(scanState.second, scanState.first, playerState); + x19c_scanCompletes[int(scanState.second) - 1].push_back(std::make_pair(scanState.first, complete)); + } + + std::sort(x19c_scanCompletes[4].begin(), x19c_scanCompletes[4].end(), + [](const std::pair& a, std::pair& b) { + return CArtifactDoll::GetArtifactHeadScanIndex(a.first) < + CArtifactDoll::GetArtifactHeadScanIndex(b.first); + }); + + auto viewIt = x200_viewScans.begin(); + for (std::vector>& category : x19c_scanCompletes) { + std::vector, TLockedToken>>& viewScans = *viewIt++; + size_t viewScanCount = std::min(category.size(), size_t(5)); + viewScans.reserve(viewScanCount); + for (size_t i = 0; i < viewScanCount; ++i) + viewScans.push_back( + std::make_pair(g_SimplePool->GetObj({FOURCC('SCAN'), category[i].first}), TLockedToken{})); + } +} + +void CLogBookScreen::UpdateRightTitles() { + std::vector>& category = x19c_scanCompletes[x70_tablegroup_leftlog->GetUserSelection()]; + for (int i = 0; i < xd8_textpane_titles.size(); ++i) { + std::u16string string; + size_t scanIndex = x18_firstViewRightSel + i; + if (scanIndex < x1f0_curViewScans.size()) { + std::pair, TCachedToken>& scan = x1f0_curViewScans[scanIndex]; + if (scan.second && scan.second.IsLoaded()) { + if (category[scanIndex].second) { + if (scan.second->GetStringCount() > 1) + string = scan.second->GetString(1); + else + string = u"No Title!"; + } else { + string = u"??????"; + } + } + + if (string.empty()) + string = u"........"; + } + xd8_textpane_titles[i]->TextSupport().SetText(string); + } + + int rightSelMod = x18_firstViewRightSel % 5; + int rightSelRem = 5 - rightSelMod; + for (int i = 0; i < x144_model_titles.size(); ++i) { + float zOff = ((i >= rightSelMod) ? rightSelRem - 5 : rightSelRem) * x38_highlightPitch; + x144_model_titles[i]->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, zOff) * + x144_model_titles[i]->GetTransform()); + } +} + +void CLogBookScreen::PumpArticleLoad() { + x260_24_loaded = true; + for (std::vector, TLockedToken>>& category : + x200_viewScans) { + for (std::pair, TLockedToken>& scan : category) { + if (scan.first.IsLoaded()) { + if (!scan.second) { + scan.second = g_SimplePool->GetObj({FOURCC('STRG'), scan.first->GetStringTableId()}); + x260_24_loaded = false; + } + } else { + x260_24_loaded = false; + } + } + } + + int rem = 6; + for (std::pair, TCachedToken>& scan : x1f0_curViewScans) { + if (scan.first.IsLoaded()) { + if (!scan.second) { + scan.second = g_SimplePool->GetObj({FOURCC('STRG'), scan.first->GetStringTableId()}); + scan.second.Lock(); + --rem; + } + } else if (scan.first.IsLocked()) { + --rem; + } + if (rem == 0) + break; + } + + if (x1f0_curViewScans.size()) { + int articleIdx = x18_firstViewRightSel; + while (rem > 0) { + x1f0_curViewScans[articleIdx].first.Lock(); + articleIdx = NextSurroundingArticleIndex(articleIdx); + if (articleIdx == -1) + break; + --rem; + } + } + + for (std::pair, TCachedToken>& scan : x1f0_curViewScans) { + if (scan.first.IsLoaded()) { + if (scan.second && scan.second.IsLoaded()) { + UpdateRightTitles(); + UpdateBodyText(); + } + } + } +} + +bool CLogBookScreen::IsScanCategoryReady(CSaveWorld::EScanCategory category) const { + CPlayerState& playerState = *x4_mgr.GetPlayerState(); + for (const std::pair& scanState : g_MemoryCardSys->GetScanStates()) { + if (scanState.second != category) + continue; + if (IsScanComplete(scanState.second, scanState.first, playerState)) + return true; + } + return false; +} + +void CLogBookScreen::UpdateBodyText() { + if (x10_mode != EMode::TextScroll) { + x174_textpane_body->TextSupport().SetText(u""); + return; + } + + TCachedToken& str = x1f0_curViewScans[x1c_rightSel].second; + if (str && str.IsLoaded()) { + std::u16string accumStr = str->GetString(0); + if (str->GetStringCount() > 2) { + accumStr += u"\n\n"; + accumStr += str->GetString(2); + } + + if (IsArtifactCategorySelected()) { + int headIdx = GetSelectedArtifactHeadScanIndex(); + if (headIdx >= 0 && g_GameState->GetPlayerState()->HasPowerUp(CPlayerState::EItemType(headIdx + 29))) + accumStr = std::u16string(u"\n\n\n\n\n\n") + g_MainStringTable->GetString(105); + } + + x174_textpane_body->TextSupport().SetText(accumStr, true); + } +} + +void CLogBookScreen::UpdateBodyImagesAndText() { + const CScannableObjectInfo* scan = x1f0_curViewScans[x1c_rightSel].first.GetObj(); + for (CAuiImagePane* pane : xf0_imagePanes) { + pane->SetTextureID0(-1, g_SimplePool); + pane->SetAnimationParms(zeus::CVector2f::skZero, 0.f, 0.f); + } + + for (int i = 0; i < 4; ++i) { + const CScannableObjectInfo::SBucket& bucket = scan->GetBucket(i); + if (bucket.x8_imagePos == -1) + continue; + CAuiImagePane* pane = xf0_imagePanes[bucket.x8_imagePos]; + if (bucket.x14_interval > 0.f) { + pane->SetAnimationParms(zeus::CVector2f(bucket.xc_size.x, bucket.xc_size.y), bucket.x14_interval, + bucket.x18_fadeDuration); + } + pane->SetTextureID0(bucket.x0_texture, g_SimplePool); + pane->SetFlashFactor(0.f); + } + + x260_26_exitTextScroll = false; + UpdateBodyText(); +} + +int CLogBookScreen::NextSurroundingArticleIndex(int cur) const { + if (cur < x18_firstViewRightSel) { + int tmp = x18_firstViewRightSel + (x18_firstViewRightSel - cur + 6); + if (tmp >= x1f0_curViewScans.size()) + return cur - 1; else - return time >= 1.f; -} + return tmp; + } -void CLogBookScreen::InitializeLogBook() -{ - for (int i=0 ; i<5 ; ++i) - x19c_scanCompletes[i].reserve(g_MemoryCardSys->GetScanCategoryCount(CSaveWorld::EScanCategory(i + 1))); + if (cur < x18_firstViewRightSel + 6) { + if (cur + 1 < x1f0_curViewScans.size()) + return cur + 1; + if (x18_firstViewRightSel == 0) + return -1; + return x18_firstViewRightSel - 1; + } - CPlayerState& playerState = *x4_mgr.GetPlayerState(); - for (const std::pair& scanState : g_MemoryCardSys->GetScanStates()) - { - if (scanState.second == CSaveWorld::EScanCategory::None) - continue; - bool complete = IsScanComplete(scanState.second, scanState.first, playerState); - x19c_scanCompletes[int(scanState.second) - 1].push_back(std::make_pair(scanState.first, complete)); - } + int tmp = x18_firstViewRightSel - (cur - (x18_firstViewRightSel + 5)); + if (tmp >= 0) + return tmp; - std::sort(x19c_scanCompletes[4].begin(), x19c_scanCompletes[4].end(), - [](const std::pair& a, std::pair& b) - { - return CArtifactDoll::GetArtifactHeadScanIndex(a.first) < - CArtifactDoll::GetArtifactHeadScanIndex(b.first); - }); - - auto viewIt = x200_viewScans.begin(); - for (std::vector>& category : x19c_scanCompletes) - { - std::vector, - TLockedToken>>& viewScans = *viewIt++; - size_t viewScanCount = std::min(category.size(), size_t(5)); - viewScans.reserve(viewScanCount); - for (size_t i=0 ; iGetObj({FOURCC('SCAN'), category[i].first}), - TLockedToken{})); - } -} - -void CLogBookScreen::UpdateRightTitles() -{ - std::vector>& category = - x19c_scanCompletes[x70_tablegroup_leftlog->GetUserSelection()]; - for (int i=0 ; i, - TCachedToken>& scan = x1f0_curViewScans[scanIndex]; - if (scan.second && scan.second.IsLoaded()) - { - if (category[scanIndex].second) - { - if (scan.second->GetStringCount() > 1) - string = scan.second->GetString(1); - else - string = u"No Title!"; - } - else - { - string = u"??????"; - } - } - - if (string.empty()) - string = u"........"; - } - xd8_textpane_titles[i]->TextSupport().SetText(string); - } - - int rightSelMod = x18_firstViewRightSel % 5; - int rightSelRem = 5 - rightSelMod; - for (int i=0 ; i= rightSelMod) ? rightSelRem - 5 : rightSelRem) * x38_highlightPitch; - x144_model_titles[i]->SetLocalTransform( - zeus::CTransform::Translate(0.f, 0.f, zOff) * x144_model_titles[i]->GetTransform()); - } -} - -void CLogBookScreen::PumpArticleLoad() -{ - x260_24_loaded = true; - for (std::vector, - TLockedToken>>& category : x200_viewScans) - { - for (std::pair, - TLockedToken>& scan : category) - { - if (scan.first.IsLoaded()) - { - if (!scan.second) - { - scan.second = g_SimplePool->GetObj({FOURCC('STRG'), scan.first->GetStringTableId()}); - x260_24_loaded = false; - } - } - else - { - x260_24_loaded = false; - } - } - } - - int rem = 6; - for (std::pair, - TCachedToken>& scan : x1f0_curViewScans) - { - if (scan.first.IsLoaded()) - { - if (!scan.second) - { - scan.second = g_SimplePool->GetObj({FOURCC('STRG'), scan.first->GetStringTableId()}); - scan.second.Lock(); - --rem; - } - } - else if (scan.first.IsLocked()) - { - --rem; - } - if (rem == 0) - break; - } - - if (x1f0_curViewScans.size()) - { - int articleIdx = x18_firstViewRightSel; - while (rem > 0) - { - x1f0_curViewScans[articleIdx].first.Lock(); - articleIdx = NextSurroundingArticleIndex(articleIdx); - if (articleIdx == -1) - break; - --rem; - } - } - - for (std::pair, - TCachedToken>& scan : x1f0_curViewScans) - { - if (scan.first.IsLoaded()) - { - if (scan.second && scan.second.IsLoaded()) - { - UpdateRightTitles(); - UpdateBodyText(); - } - } - } -} - -bool CLogBookScreen::IsScanCategoryReady(CSaveWorld::EScanCategory category) const -{ - CPlayerState& playerState = *x4_mgr.GetPlayerState(); - for (const std::pair& scanState : g_MemoryCardSys->GetScanStates()) - { - if (scanState.second != category) - continue; - if (IsScanComplete(scanState.second, scanState.first, playerState)) - return true; - } - return false; -} - -void CLogBookScreen::UpdateBodyText() -{ - if (x10_mode != EMode::TextScroll) - { - x174_textpane_body->TextSupport().SetText(u""); - return; - } - - TCachedToken& str = x1f0_curViewScans[x1c_rightSel].second; - if (str && str.IsLoaded()) - { - std::u16string accumStr = str->GetString(0); - if (str->GetStringCount() > 2) - { - accumStr += u"\n\n"; - accumStr += str->GetString(2); - } - - if (IsArtifactCategorySelected()) - { - int headIdx = GetSelectedArtifactHeadScanIndex(); - if (headIdx >= 0 && g_GameState->GetPlayerState()->HasPowerUp(CPlayerState::EItemType(headIdx + 29))) - accumStr = std::u16string(u"\n\n\n\n\n\n") + g_MainStringTable->GetString(105); - } - - x174_textpane_body->TextSupport().SetText(accumStr, true); - } -} - -void CLogBookScreen::UpdateBodyImagesAndText() -{ - const CScannableObjectInfo* scan = x1f0_curViewScans[x1c_rightSel].first.GetObj(); - for (CAuiImagePane* pane : xf0_imagePanes) - { - pane->SetTextureID0(-1, g_SimplePool); - pane->SetAnimationParms(zeus::CVector2f::skZero, 0.f, 0.f); - } - - for (int i=0 ; i<4 ; ++i) - { - const CScannableObjectInfo::SBucket& bucket = scan->GetBucket(i); - if (bucket.x8_imagePos == -1) - continue; - CAuiImagePane* pane = xf0_imagePanes[bucket.x8_imagePos]; - if (bucket.x14_interval > 0.f) - { - pane->SetAnimationParms(zeus::CVector2f(bucket.xc_size.x, bucket.xc_size.y), - bucket.x14_interval, bucket.x18_fadeDuration); - } - pane->SetTextureID0(bucket.x0_texture, g_SimplePool); - pane->SetFlashFactor(0.f); - } - - x260_26_exitTextScroll = false; - UpdateBodyText(); -} - -int CLogBookScreen::NextSurroundingArticleIndex(int cur) const -{ - if (cur < x18_firstViewRightSel) - { - int tmp = x18_firstViewRightSel + (x18_firstViewRightSel - cur + 6); - if (tmp >= x1f0_curViewScans.size()) - return cur - 1; - else - return tmp; - } - - if (cur < x18_firstViewRightSel + 6) - { - if (cur + 1 < x1f0_curViewScans.size()) - return cur + 1; - if (x18_firstViewRightSel == 0) - return -1; - return x18_firstViewRightSel - 1; - } - - int tmp = x18_firstViewRightSel - (cur - (x18_firstViewRightSel + 5)); - if (tmp >= 0) - return tmp; - - if (cur >= x1f0_curViewScans.size() - 1) - return -1; - return cur + 1; -} - -bool CLogBookScreen::IsArtifactCategorySelected() const -{ - return x70_tablegroup_leftlog->GetUserSelection() == 4; -} - -int CLogBookScreen::GetSelectedArtifactHeadScanIndex() const -{ - auto& category = x19c_scanCompletes[x70_tablegroup_leftlog->GetUserSelection()]; - if (x1c_rightSel < category.size()) - return CArtifactDoll::GetArtifactHeadScanIndex(category[x1c_rightSel].first); + if (cur >= x1f0_curViewScans.size() - 1) return -1; + return cur + 1; } -bool CLogBookScreen::InputDisabled() const -{ - return x25c_leavePauseState == ELeavePauseState::LeavingPause; +bool CLogBookScreen::IsArtifactCategorySelected() const { return x70_tablegroup_leftlog->GetUserSelection() == 4; } + +int CLogBookScreen::GetSelectedArtifactHeadScanIndex() const { + auto& category = x19c_scanCompletes[x70_tablegroup_leftlog->GetUserSelection()]; + if (x1c_rightSel < category.size()) + return CArtifactDoll::GetArtifactHeadScanIndex(category[x1c_rightSel].first); + return -1; } -void CLogBookScreen::TransitioningAway() -{ - x25c_leavePauseState = ELeavePauseState::LeavingPause; -} +bool CLogBookScreen::InputDisabled() const { return x25c_leavePauseState == ELeavePauseState::LeavingPause; } -void CLogBookScreen::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) -{ - CPauseScreenBase::Update(dt, rand, archQueue); - x258_artifactDoll->Update(dt, x4_mgr); - PumpArticleLoad(); +void CLogBookScreen::TransitioningAway() { x25c_leavePauseState = ELeavePauseState::LeavingPause; } - if (x10_mode == EMode::TextScroll) - { - if (x260_25_inTextScroll) - x254_viewInterp = std::min(x254_viewInterp + 4.f * dt, 1.f); - else - x254_viewInterp = std::max(0.f, x254_viewInterp - 4.f * dt); +void CLogBookScreen::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) { + CPauseScreenBase::Update(dt, rand, archQueue); + x258_artifactDoll->Update(dt, x4_mgr); + PumpArticleLoad(); - zeus::CColor color(1.f, x254_viewInterp); - x74_basewidget_leftguages->SetColor(color); - x88_basewidget_rightguages->SetColor(color); - - zeus::CColor invColor(1.f, 1.f - x254_viewInterp); - x70_tablegroup_leftlog->SetColor(invColor); - x84_tablegroup_rightlog->SetColor(invColor); - x17c_model_textalpha->SetColor(invColor); - x174_textpane_body->SetColor(color); - - for (CAuiImagePane* pane : xf0_imagePanes) - pane->SetDeResFactor(1.f - x254_viewInterp); - - if (x254_viewInterp == 0.f && x25c_leavePauseState == ELeavePauseState::InPause) - ChangeMode(EMode::RightTable); - } - - if (x25c_leavePauseState == ELeavePauseState::LeavingPause && x254_viewInterp == 0.f) - x25c_leavePauseState = ELeavePauseState::LeftPause; -} - -void CLogBookScreen::Touch() -{ - CPauseScreenBase::Touch(); - x258_artifactDoll->Touch(); -} - -void CLogBookScreen::ProcessControllerInput(const CFinalInput& input) -{ - x260_25_inTextScroll = false; - if (x25c_leavePauseState == ELeavePauseState::LeftPause) - return; - - if (x10_mode == EMode::TextScroll) - { - int oldPage = x174_textpane_body->TextSupport().GetPageCounter(); - int newPage = oldPage; - int pageCount = x174_textpane_body->TextSupport().GetTotalPageCount(); - bool lastPage = (pageCount - 1) == oldPage; - if (pageCount != -1) - { - if (input.PLAUp()) - newPage = std::max(oldPage - 1, 0); - else if (input.PLADown() || (input.PA() && !lastPage)) - newPage = std::min(oldPage + 1, pageCount - 1); - x174_textpane_body->TextSupport().SetPage(newPage); - if (oldPage != newPage) - CSfxManager::SfxStart(SFXui_pause_screen_next_page, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x198_28_pulseTextArrowTop = newPage > 0; - x198_29_pulseTextArrowBottom = !lastPage; - } - else - { - x198_29_pulseTextArrowBottom = false; - x198_28_pulseTextArrowTop = false; - } - - if (!x260_26_exitTextScroll) - x260_26_exitTextScroll = input.PB() || (input.PA() && lastPage); - - if (g_tweakGui->GetLatchArticleText()) - x260_25_inTextScroll = !x260_26_exitTextScroll; - else - x260_25_inTextScroll = input.DA(); - } + if (x10_mode == EMode::TextScroll) { + if (x260_25_inTextScroll) + x254_viewInterp = std::min(x254_viewInterp + 4.f * dt, 1.f); else - { - x198_29_pulseTextArrowBottom = false; - x198_28_pulseTextArrowTop = false; + x254_viewInterp = std::max(0.f, x254_viewInterp - 4.f * dt); + + zeus::CColor color(1.f, x254_viewInterp); + x74_basewidget_leftguages->SetColor(color); + x88_basewidget_rightguages->SetColor(color); + + zeus::CColor invColor(1.f, 1.f - x254_viewInterp); + x70_tablegroup_leftlog->SetColor(invColor); + x84_tablegroup_rightlog->SetColor(invColor); + x17c_model_textalpha->SetColor(invColor); + x174_textpane_body->SetColor(color); + + for (CAuiImagePane* pane : xf0_imagePanes) + pane->SetDeResFactor(1.f - x254_viewInterp); + + if (x254_viewInterp == 0.f && x25c_leavePauseState == ELeavePauseState::InPause) + ChangeMode(EMode::RightTable); + } + + if (x25c_leavePauseState == ELeavePauseState::LeavingPause && x254_viewInterp == 0.f) + x25c_leavePauseState = ELeavePauseState::LeftPause; +} + +void CLogBookScreen::Touch() { + CPauseScreenBase::Touch(); + x258_artifactDoll->Touch(); +} + +void CLogBookScreen::ProcessControllerInput(const CFinalInput& input) { + x260_25_inTextScroll = false; + if (x25c_leavePauseState == ELeavePauseState::LeftPause) + return; + + if (x10_mode == EMode::TextScroll) { + int oldPage = x174_textpane_body->TextSupport().GetPageCounter(); + int newPage = oldPage; + int pageCount = x174_textpane_body->TextSupport().GetTotalPageCount(); + bool lastPage = (pageCount - 1) == oldPage; + if (pageCount != -1) { + if (input.PLAUp()) + newPage = std::max(oldPage - 1, 0); + else if (input.PLADown() || (input.PA() && !lastPage)) + newPage = std::min(oldPage + 1, pageCount - 1); + x174_textpane_body->TextSupport().SetPage(newPage); + if (oldPage != newPage) + CSfxManager::SfxStart(SFXui_pause_screen_next_page, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x198_28_pulseTextArrowTop = newPage > 0; + x198_29_pulseTextArrowBottom = !lastPage; + } else { + x198_29_pulseTextArrowBottom = false; + x198_28_pulseTextArrowTop = false; } - if (x25c_leavePauseState == ELeavePauseState::LeavingPause) - x260_25_inTextScroll = false; + if (!x260_26_exitTextScroll) + x260_26_exitTextScroll = input.PB() || (input.PA() && lastPage); - CPauseScreenBase::ProcessControllerInput(input); + if (g_tweakGui->GetLatchArticleText()) + x260_25_inTextScroll = !x260_26_exitTextScroll; + else + x260_25_inTextScroll = input.DA(); + } else { + x198_29_pulseTextArrowBottom = false; + x198_28_pulseTextArrowTop = false; + } + + if (x25c_leavePauseState == ELeavePauseState::LeavingPause) + x260_25_inTextScroll = false; + + CPauseScreenBase::ProcessControllerInput(input); } -void CLogBookScreen::Draw(float transInterp, float totalAlpha, float yOff) -{ - CPauseScreenBase::Draw(transInterp, totalAlpha, yOff); - bool artifactSel = x10_mode == EMode::RightTable && IsArtifactCategorySelected(); - x258_artifactDoll->Draw(transInterp * (1.f - x254_viewInterp), x4_mgr, artifactSel, - GetSelectedArtifactHeadScanIndex()); +void CLogBookScreen::Draw(float transInterp, float totalAlpha, float yOff) { + CPauseScreenBase::Draw(transInterp, totalAlpha, yOff); + bool artifactSel = x10_mode == EMode::RightTable && IsArtifactCategorySelected(); + x258_artifactDoll->Draw(transInterp * (1.f - x254_viewInterp), x4_mgr, artifactSel, + GetSelectedArtifactHeadScanIndex()); } -bool CLogBookScreen::VReady() const -{ - return true; -} +bool CLogBookScreen::VReady() const { return true; } -void CLogBookScreen::VActivate() -{ - for (int i=0 ; i<5 ; ++i) - { - if (IsScanCategoryReady(CSaveWorld::EScanCategory(i + 1))) - { - xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 1)); - } - else - { - xa8_textpane_categories[i]->TextSupport().SetText(u"??????"); - x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(false); - } +void CLogBookScreen::VActivate() { + for (int i = 0; i < 5; ++i) { + if (IsScanCategoryReady(CSaveWorld::EScanCategory(i + 1))) { + xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 1)); + } else { + xa8_textpane_categories[i]->TextSupport().SetText(u"??????"); + x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(false); } + } - x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(0)); + x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(0)); #if 0 for (int i=5 ; i<5 ; ++i) @@ -435,60 +352,47 @@ void CLogBookScreen::VActivate() #endif } -void CLogBookScreen::RightTableSelectionChanged(int oldSel, int newSel) -{ - UpdateRightTitles(); +void CLogBookScreen::RightTableSelectionChanged(int oldSel, int newSel) { UpdateRightTitles(); } + +void CLogBookScreen::ChangedMode(EMode oldMode) { + if (oldMode == EMode::TextScroll) { + x74_basewidget_leftguages->SetVisibility(false, ETraversalMode::Children); + x88_basewidget_rightguages->SetVisibility(false, ETraversalMode::Children); + UpdateBodyText(); + x174_textpane_body->TextSupport().SetPage(0); + } else if (x10_mode == EMode::TextScroll) { + x74_basewidget_leftguages->SetVisibility(true, ETraversalMode::Children); + x88_basewidget_rightguages->SetVisibility(true, ETraversalMode::Children); + x260_25_inTextScroll = true; + UpdateBodyImagesAndText(); + } } -void CLogBookScreen::ChangedMode(EMode oldMode) -{ - if (oldMode == EMode::TextScroll) - { - x74_basewidget_leftguages->SetVisibility(false, ETraversalMode::Children); - x88_basewidget_rightguages->SetVisibility(false, ETraversalMode::Children); - UpdateBodyText(); - x174_textpane_body->TextSupport().SetPage(0); - } - else if (x10_mode == EMode::TextScroll) - { - x74_basewidget_leftguages->SetVisibility(true, ETraversalMode::Children); - x88_basewidget_rightguages->SetVisibility(true, ETraversalMode::Children); - x260_25_inTextScroll = true; - UpdateBodyImagesAndText(); - } +void CLogBookScreen::UpdateRightTable() { + CPauseScreenBase::UpdateRightTable(); + x1f0_curViewScans.clear(); + std::vector>& category = x19c_scanCompletes[x70_tablegroup_leftlog->GetUserSelection()]; + x1f0_curViewScans.reserve(category.size()); + for (std::pair& scan : category) + x1f0_curViewScans.push_back( + std::make_pair(g_SimplePool->GetObj({FOURCC('SCAN'), scan.first}), TLockedToken{})); + + PumpArticleLoad(); + UpdateRightTitles(); } -void CLogBookScreen::UpdateRightTable() -{ - CPauseScreenBase::UpdateRightTable(); - x1f0_curViewScans.clear(); - std::vector>& category = x19c_scanCompletes[x70_tablegroup_leftlog->GetUserSelection()]; - x1f0_curViewScans.reserve(category.size()); - for (std::pair& scan : category) - x1f0_curViewScans.push_back(std::make_pair(g_SimplePool->GetObj({FOURCC('SCAN'), scan.first}), - TLockedToken{})); - - PumpArticleLoad(); - UpdateRightTitles(); +bool CLogBookScreen::ShouldLeftTableAdvance() const { + if (!x260_24_loaded || x1f0_curViewScans.empty()) + return false; + return IsScanCategoryReady(CSaveWorld::EScanCategory(x70_tablegroup_leftlog->GetUserSelection() + 1)); } -bool CLogBookScreen::ShouldLeftTableAdvance() const -{ - if (!x260_24_loaded || x1f0_curViewScans.empty()) - return false; - return IsScanCategoryReady(CSaveWorld::EScanCategory(x70_tablegroup_leftlog->GetUserSelection() + 1)); +bool CLogBookScreen::ShouldRightTableAdvance() const { + const std::pair, TLockedToken>& scan = + x1f0_curViewScans[x1c_rightSel]; + return scan.first.IsLoaded() && scan.second.IsLoaded(); } -bool CLogBookScreen::ShouldRightTableAdvance() const -{ - const std::pair, - TLockedToken>& scan = x1f0_curViewScans[x1c_rightSel]; - return scan.first.IsLoaded() && scan.second.IsLoaded(); -} +u32 CLogBookScreen::GetRightTableCount() const { return x1f0_curViewScans.size(); } -u32 CLogBookScreen::GetRightTableCount() const -{ - return x1f0_curViewScans.size(); -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CLogBookScreen.hpp b/Runtime/MP1/CLogBookScreen.hpp index 37613a009..3d00e991a 100644 --- a/Runtime/MP1/CLogBookScreen.hpp +++ b/Runtime/MP1/CLogBookScreen.hpp @@ -4,68 +4,57 @@ #include "CPauseScreenBase.hpp" #include "CArtifactDoll.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class CLogBookScreen : public CPauseScreenBase -{ - rstl::reserved_vector>, 5> x19c_scanCompletes; - std::vector, - TCachedToken>> x1f0_curViewScans; - rstl::reserved_vector, - TLockedToken>>, 5> x200_viewScans; - float x254_viewInterp = 0.f; - std::unique_ptr x258_artifactDoll; +class CLogBookScreen : public CPauseScreenBase { + rstl::reserved_vector>, 5> x19c_scanCompletes; + std::vector, TCachedToken>> x1f0_curViewScans; + rstl::reserved_vector, TLockedToken>>, 5> + x200_viewScans; + float x254_viewInterp = 0.f; + std::unique_ptr x258_artifactDoll; - enum class ELeavePauseState - { - InPause = 0, - LeavingPause = 1, - LeftPause = 2 + enum class ELeavePauseState { InPause = 0, LeavingPause = 1, LeftPause = 2 }; + + ELeavePauseState x25c_leavePauseState = ELeavePauseState::InPause; + union { + struct { + bool x260_24_loaded : 1; + bool x260_25_inTextScroll : 1; + bool x260_26_exitTextScroll : 1; }; + s32 _dummy = 0; + }; - ELeavePauseState x25c_leavePauseState = ELeavePauseState::InPause; - union - { - struct - { - bool x260_24_loaded : 1; - bool x260_25_inTextScroll : 1; - bool x260_26_exitTextScroll : 1; - }; - s32 _dummy = 0; - }; - - void InitializeLogBook(); - void UpdateRightTitles(); - void PumpArticleLoad(); - bool IsScanCategoryReady(CSaveWorld::EScanCategory category) const; - void UpdateBodyText(); - void UpdateBodyImagesAndText(); - int NextSurroundingArticleIndex(int cur) const; - bool IsArtifactCategorySelected() const; - int GetSelectedArtifactHeadScanIndex() const; - static bool IsScanComplete(CSaveWorld::EScanCategory category, CAssetId scan, const CPlayerState& playerState); + void InitializeLogBook(); + void UpdateRightTitles(); + void PumpArticleLoad(); + bool IsScanCategoryReady(CSaveWorld::EScanCategory category) const; + void UpdateBodyText(); + void UpdateBodyImagesAndText(); + int NextSurroundingArticleIndex(int cur) const; + bool IsArtifactCategorySelected() const; + int GetSelectedArtifactHeadScanIndex() const; + static bool IsScanComplete(CSaveWorld::EScanCategory category, CAssetId scan, const CPlayerState& playerState); public: - CLogBookScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg); - ~CLogBookScreen(); + CLogBookScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg); + ~CLogBookScreen(); - bool InputDisabled() const; - void TransitioningAway(); - void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); - void Touch(); - void ProcessControllerInput(const CFinalInput& input); - void Draw(float transInterp, float totalAlpha, float yOff); - bool VReady() const; - void VActivate(); - void RightTableSelectionChanged(int oldSel, int newSel); - void ChangedMode(EMode oldMode); - void UpdateRightTable(); - bool ShouldLeftTableAdvance() const; - bool ShouldRightTableAdvance() const; - u32 GetRightTableCount() const; + bool InputDisabled() const; + void TransitioningAway(); + void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); + void Touch(); + void ProcessControllerInput(const CFinalInput& input); + void Draw(float transInterp, float totalAlpha, float yOff); + bool VReady() const; + void VActivate(); + void RightTableSelectionChanged(int oldSel, int newSel); + void ChangedMode(EMode oldMode); + void UpdateRightTable(); + bool ShouldLeftTableAdvance() const; + bool ShouldRightTableAdvance() const; + u32 GetRightTableCount() const; }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CMFGame.cpp b/Runtime/MP1/CMFGame.cpp index e69b23e20..4516f77f9 100644 --- a/Runtime/MP1/CMFGame.cpp +++ b/Runtime/MP1/CMFGame.cpp @@ -8,420 +8,351 @@ #include "Audio/CMidiManager.hpp" #include "Camera/CCinematicCamera.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CMFGame::CMFGame(const std::weak_ptr& stateMgr, const std::weak_ptr& guiMgr, const CArchitectureQueue&) -: CMFGameBase("CMFGame"), x14_stateManager(stateMgr.lock()), x18_guiManager(guiMgr.lock()) -{ - x2a_25_samusAlive = true; - static_cast(*g_Main).SetMFGameBuilt(true); +: CMFGameBase("CMFGame"), x14_stateManager(stateMgr.lock()), x18_guiManager(guiMgr.lock()) { + x2a_25_samusAlive = true; + static_cast(*g_Main).SetMFGameBuilt(true); } -CMFGame::~CMFGame() -{ - CMain& main = static_cast(*g_Main); - main.SetMFGameBuilt(false); - main.SetScreenFading(false); - CDecalManager::Reinitialize(); +CMFGame::~CMFGame() { + CMain& main = static_cast(*g_Main); + main.SetMFGameBuilt(false); + main.SetScreenFading(false); + CDecalManager::Reinitialize(); } -CIOWin::EMessageReturn CMFGame::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - switch (msg.GetType()) - { - case EArchMsgType::FrameBegin: - x14_stateManager->FrameBegin(msg.GetParm()->x4_parm); +CIOWin::EMessageReturn CMFGame::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + switch (msg.GetType()) { + case EArchMsgType::FrameBegin: + x14_stateManager->FrameBegin(msg.GetParm()->x4_parm); + break; + case EArchMsgType::TimerTick: { + bool wasInitialized = x2a_24_initialized; + x2a_24_initialized = true; + float dt = MakeMsg::GetParmTimerTick(msg).x4_parm; + + /* URDE addition: this is continuously updated for animated UVs even when game paused */ + x14_stateManager->UpdateGraphicsTiming(dt); + + switch (x1c_flowState) { + case EGameFlowState::CinematicSkip: { + x20_cineSkipTime += dt; + const CEntity* cam = x14_stateManager->GetCameraManager()->GetCurrentCamera(*x14_stateManager); + TCastToConstPtr cineCam = cam; + if ((x20_cineSkipTime >= 1.f && x14_stateManager->SpecialSkipCinematic()) || !cineCam || + (cineCam->GetFlags() & 0x10 && x28_skippedCineCam != cineCam->GetUniqueId())) { + static_cast(*g_Main).SetScreenFading(false); + x1c_flowState = EGameFlowState::InGame; + x18_guiManager->StartFadeIn(); + x28_skippedCineCam = kInvalidUniqueId; break; - case EArchMsgType::TimerTick: - { - bool wasInitialized = x2a_24_initialized; - x2a_24_initialized = true; - float dt = MakeMsg::GetParmTimerTick(msg).x4_parm; - - /* URDE addition: this is continuously updated for animated UVs even when game paused */ - x14_stateManager->UpdateGraphicsTiming(dt); - - switch (x1c_flowState) - { - case EGameFlowState::CinematicSkip: - { - x20_cineSkipTime += dt; - const CEntity* cam = x14_stateManager->GetCameraManager()->GetCurrentCamera(*x14_stateManager); - TCastToConstPtr cineCam = cam; - if ((x20_cineSkipTime >= 1.f && x14_stateManager->SpecialSkipCinematic()) || !cineCam || - (cineCam->GetFlags() & 0x10 && x28_skippedCineCam != cineCam->GetUniqueId())) - { - static_cast(*g_Main).SetScreenFading(false); - x1c_flowState = EGameFlowState::InGame; - x18_guiManager->StartFadeIn(); - x28_skippedCineCam = kInvalidUniqueId; - break; - } - } - case EGameFlowState::InGame: - { - x14_stateManager->SetActiveRandomToDefault(); - switch (x14_stateManager->GetDeferredStateTransition()) - { - case EStateManagerTransition::InGame: - x14_stateManager->Update(dt); - if (!x14_stateManager->ShouldQuitGame()) - break; - //CGraphics::SetIsBeginSceneClearFb(); - break; - case EStateManagerTransition::MapScreen: - EnterMapScreen(); - break; - case EStateManagerTransition::PauseGame: - PauseGame(); - break; - case EStateManagerTransition::LogBook: - EnterLogBook(); - break; - case EStateManagerTransition::SaveGame: - SaveGame(); - break; - case EStateManagerTransition::MessageScreen: - EnterMessageScreen(x14_stateManager->GetHUDMessageTime()); - break; - } - - if (x2a_25_samusAlive && !x14_stateManager->GetPlayerState()->IsPlayerAlive()) - { - PlayerDied(); - } - x14_stateManager->ClearActiveRandom(); - break; - } - case EGameFlowState::Paused: - { - if (x18_guiManager->WasInGame() && x18_guiManager->IsInGame()) - { - x14_stateManager->SetInSaveUI(x18_guiManager->IsInSaveUI()); - UnpauseGame(); - if (x14_stateManager->GetPauseHUDMessage().IsValid()) - x14_stateManager->IncrementHUDMessageFrameCounter(); - } - break; - } - case EGameFlowState::SamusDied: - { - if (x14_stateManager->GetPlayer().IsPlayerDeadEnough()) - { - static_cast(*g_Main).SetFlowState(EFlowState::LoseGame); - queue.Push(MakeMsg::CreateQuitGameplay(EArchMsgTarget::Game)); - } - else - { - x14_stateManager->SetActiveRandomToDefault(); - x14_stateManager->Update(dt); - x14_stateManager->ClearActiveRandom(); - } - } - default: break; - } - - x18_guiManager->Update(*x14_stateManager, dt, queue, IsCameraActiveFlow()); - if (!wasInitialized) - g_GameState->GetWorldTransitionManager()->EndTransition(); - - return EMessageReturn::Exit; + } } - case EArchMsgType::UserInput: - { - if (!x2a_24_initialized) - break; - const CFinalInput& input = MakeMsg::GetParmUserInput(msg).x4_parm; - if (x1c_flowState == EGameFlowState::InGame) - { - if (input.ControllerIdx() == 0) - { - const CEntity* cam = x14_stateManager->GetCameraManager()->GetCurrentCamera(*x14_stateManager); - TCastToConstPtr cineCam = cam; - if (input.PStart()) - { - if (cineCam && x14_stateManager->GetSkipCinematicSpecialFunction() != kInvalidUniqueId) - { - CMidiManager::StopAll(); - x28_skippedCineCam = cineCam->GetUniqueId(); - x1c_flowState = EGameFlowState::CinematicSkip; - x20_cineSkipTime = 0.f; - } - else if (!cineCam) - { - x14_stateManager->DeferStateTransition(EStateManagerTransition::PauseGame); - } - } - else if (input.PZ() && !cineCam && x14_stateManager->CanShowMapScreen()) - { - x14_stateManager->DeferStateTransition(EStateManagerTransition::MapScreen); - } - } - - x14_stateManager->SetActiveRandomToDefault(); - x14_stateManager->ProcessInput(input); - x14_stateManager->ClearActiveRandom(); - } - x18_guiManager->ProcessControllerInput(*x14_stateManager, input, queue); + case EGameFlowState::InGame: { + x14_stateManager->SetActiveRandomToDefault(); + switch (x14_stateManager->GetDeferredStateTransition()) { + case EStateManagerTransition::InGame: + x14_stateManager->Update(dt); + if (!x14_stateManager->ShouldQuitGame()) + break; + // CGraphics::SetIsBeginSceneClearFb(); break; - } - case EArchMsgType::FrameEnd: - { - x14_stateManager->FrameEnd(); - if (x14_stateManager->ShouldQuitGame()) - queue.Push(MakeMsg::CreateQuitGameplay(EArchMsgTarget::Game)); + case EStateManagerTransition::MapScreen: + EnterMapScreen(); break; + case EStateManagerTransition::PauseGame: + PauseGame(); + break; + case EStateManagerTransition::LogBook: + EnterLogBook(); + break; + case EStateManagerTransition::SaveGame: + SaveGame(); + break; + case EStateManagerTransition::MessageScreen: + EnterMessageScreen(x14_stateManager->GetHUDMessageTime()); + break; + } + + if (x2a_25_samusAlive && !x14_stateManager->GetPlayerState()->IsPlayerAlive()) { + PlayerDied(); + } + x14_stateManager->ClearActiveRandom(); + break; } - case EArchMsgType::QuitGameplay: - return EMessageReturn::RemoveIOWin; - default: break; + case EGameFlowState::Paused: { + if (x18_guiManager->WasInGame() && x18_guiManager->IsInGame()) { + x14_stateManager->SetInSaveUI(x18_guiManager->IsInSaveUI()); + UnpauseGame(); + if (x14_stateManager->GetPauseHUDMessage().IsValid()) + x14_stateManager->IncrementHUDMessageFrameCounter(); + } + break; + } + case EGameFlowState::SamusDied: { + if (x14_stateManager->GetPlayer().IsPlayerDeadEnough()) { + static_cast(*g_Main).SetFlowState(EFlowState::LoseGame); + queue.Push(MakeMsg::CreateQuitGameplay(EArchMsgTarget::Game)); + } else { + x14_stateManager->SetActiveRandomToDefault(); + x14_stateManager->Update(dt); + x14_stateManager->ClearActiveRandom(); + } + } + default: + break; } - return EMessageReturn::Normal; -} + x18_guiManager->Update(*x14_stateManager, dt, queue, IsCameraActiveFlow()); + if (!wasInitialized) + g_GameState->GetWorldTransitionManager()->EndTransition(); -void CMFGame::Touch() -{ - x14_stateManager->TouchSky(); - x14_stateManager->TouchPlayerActor(); - - bool gunVisible = false; - bool ballVisible = false; - bool samusVisible = false; - CPlayer& player = x14_stateManager->GetPlayer(); - switch (player.GetMorphballTransitionState()) - { - case CPlayer::EPlayerMorphBallState::Unmorphed: - gunVisible = true; - break; - case CPlayer::EPlayerMorphBallState::Morphed: - ballVisible = true; - break; - case CPlayer::EPlayerMorphBallState::Morphing: - ballVisible = true; - samusVisible = true; - break; - case CPlayer::EPlayerMorphBallState::Unmorphing: - gunVisible = true; - samusVisible = true; - break; - } - - if (gunVisible) - player.GetPlayerGun()->TouchModel(*x14_stateManager); - if (samusVisible) - player.ModelData()->Touch(*x14_stateManager, 0); - if (ballVisible) - player.GetMorphBall()->TouchModel(*x14_stateManager); -} - -void CMFGame::Draw() const -{ + return EMessageReturn::Exit; + } + case EArchMsgType::UserInput: { if (!x2a_24_initialized) - return; - - const_cast(*this).Touch(); - if (x18_guiManager->GetIsGameDraw()) - { - static_cast(*g_Main).SetGameFrameDrawn(); - x14_stateManager->PreRender(); - x14_stateManager->DrawWorld(); - x14_stateManager->GetPlayer().IsPlayerDeadEnough(); - } - - x18_guiManager->PreDraw(*x14_stateManager, IsCameraActiveFlow()); - x18_guiManager->Draw(*x14_stateManager); - - if (x1c_flowState == EGameFlowState::CinematicSkip) - { - float c = std::min(1.f, 1.f - x20_cineSkipTime); - const_cast(m_fadeToBlack).draw(zeus::CColor{c, c, c, c}); - } -} - -void CMFGame::PlayerDied() -{ - x1c_flowState = EGameFlowState::SamusDied; - x2a_25_samusAlive = false; -} - -void CMFGame::UnpauseGame() -{ - x1c_flowState = EGameFlowState::InGame; - CSfxManager::SetChannel(CSfxManager::ESfxChannels::Game); - x14_stateManager->DeferStateTransition(EStateManagerTransition::InGame); -} - -void CMFGame::EnterMessageScreen(float time) -{ - x1c_flowState = EGameFlowState::Paused; - x18_guiManager->ShowPauseGameHudMessage(*x14_stateManager, x14_stateManager->GetPauseHUDMessage(), time); -} - -void CMFGame::SaveGame() -{ - x1c_flowState = EGameFlowState::Paused; - x18_guiManager->PauseGame(*x14_stateManager, EInGameGuiState::PauseSaveGame); -} - -void CMFGame::EnterLogBook() -{ - x1c_flowState = EGameFlowState::Paused; - x18_guiManager->PauseGame(*x14_stateManager, EInGameGuiState::PauseLogBook); -} - -void CMFGame::PauseGame() -{ - x1c_flowState = EGameFlowState::Paused; - x18_guiManager->PauseGame(*x14_stateManager, EInGameGuiState::PauseGame); -} - -void CMFGame::EnterMapScreen() -{ - x1c_flowState = EGameFlowState::Paused; - x18_guiManager->PauseGame(*x14_stateManager, EInGameGuiState::MapScreen); - x14_stateManager->SetInMapScreen(true); -} - -CMFGameLoader::CMFGameLoader() : CMFGameLoaderBase("CMFGameLoader") -{ - CMain* m = static_cast(g_Main); - switch (m->GetFlowState()) - { - case EFlowState::Default: - case EFlowState::StateSetter: - { - CAssetId mlvlId = g_GameState->CurrentWorldAssetId(); - if (g_MemoryCardSys->HasSaveWorldMemory(mlvlId)) - { - const CSaveWorldMemory& savwMem = g_MemoryCardSys->GetSaveWorldMemory(mlvlId); - if (savwMem.GetWorldNameId().IsValid()) - { - CAssetId wtMgrFont = g_ResFactory->TranslateOriginalToNew(0xB7BBD0B4); - g_GameState->GetWorldTransitionManager()->EnableTransition(wtMgrFont, - savwMem.GetWorldNameId(), - 1, false, 0.1f, 16.f, 1.f); - } + break; + const CFinalInput& input = MakeMsg::GetParmUserInput(msg).x4_parm; + if (x1c_flowState == EGameFlowState::InGame) { + if (input.ControllerIdx() == 0) { + const CEntity* cam = x14_stateManager->GetCameraManager()->GetCurrentCamera(*x14_stateManager); + TCastToConstPtr cineCam = cam; + if (input.PStart()) { + if (cineCam && x14_stateManager->GetSkipCinematicSpecialFunction() != kInvalidUniqueId) { + CMidiManager::StopAll(); + x28_skippedCineCam = cineCam->GetUniqueId(); + x1c_flowState = EGameFlowState::CinematicSkip; + x20_cineSkipTime = 0.f; + } else if (!cineCam) { + x14_stateManager->DeferStateTransition(EStateManagerTransition::PauseGame); + } + } else if (input.PZ() && !cineCam && x14_stateManager->CanShowMapScreen()) { + x14_stateManager->DeferStateTransition(EStateManagerTransition::MapScreen); } - } - default: break; - } + } - if (g_GameState->CurrentWorldAssetId() == g_ResFactory->TranslateOriginalToNew(0x158EFE17) && - g_GameState->CurrentWorldState().GetCurrentAreaId() == 0) - { - const SObjectTag* strgTag = g_ResFactory->GetResourceIdByName("STRG_IntroLevelLoad"); - if (strgTag) - g_GameState->GetWorldTransitionManager()->EnableTransition(-1, strgTag->id, - 0, false, 0.1f, 16.f, 1.f); + x14_stateManager->SetActiveRandomToDefault(); + x14_stateManager->ProcessInput(input); + x14_stateManager->ClearActiveRandom(); } + x18_guiManager->ProcessControllerInput(*x14_stateManager, input, queue); + break; + } + case EArchMsgType::FrameEnd: { + x14_stateManager->FrameEnd(); + if (x14_stateManager->ShouldQuitGame()) + queue.Push(MakeMsg::CreateQuitGameplay(EArchMsgTarget::Game)); + break; + } + case EArchMsgType::QuitGameplay: + return EMessageReturn::RemoveIOWin; + default: + break; + } + + return EMessageReturn::Normal; +} + +void CMFGame::Touch() { + x14_stateManager->TouchSky(); + x14_stateManager->TouchPlayerActor(); + + bool gunVisible = false; + bool ballVisible = false; + bool samusVisible = false; + CPlayer& player = x14_stateManager->GetPlayer(); + switch (player.GetMorphballTransitionState()) { + case CPlayer::EPlayerMorphBallState::Unmorphed: + gunVisible = true; + break; + case CPlayer::EPlayerMorphBallState::Morphed: + ballVisible = true; + break; + case CPlayer::EPlayerMorphBallState::Morphing: + ballVisible = true; + samusVisible = true; + break; + case CPlayer::EPlayerMorphBallState::Unmorphing: + gunVisible = true; + samusVisible = true; + break; + } + + if (gunVisible) + player.GetPlayerGun()->TouchModel(*x14_stateManager); + if (samusVisible) + player.ModelData()->Touch(*x14_stateManager, 0); + if (ballVisible) + player.GetMorphBall()->TouchModel(*x14_stateManager); +} + +void CMFGame::Draw() const { + if (!x2a_24_initialized) + return; + + const_cast(*this).Touch(); + if (x18_guiManager->GetIsGameDraw()) { + static_cast(*g_Main).SetGameFrameDrawn(); + x14_stateManager->PreRender(); + x14_stateManager->DrawWorld(); + x14_stateManager->GetPlayer().IsPlayerDeadEnough(); + } + + x18_guiManager->PreDraw(*x14_stateManager, IsCameraActiveFlow()); + x18_guiManager->Draw(*x14_stateManager); + + if (x1c_flowState == EGameFlowState::CinematicSkip) { + float c = std::min(1.f, 1.f - x20_cineSkipTime); + const_cast(m_fadeToBlack).draw(zeus::CColor{c, c, c, c}); + } +} + +void CMFGame::PlayerDied() { + x1c_flowState = EGameFlowState::SamusDied; + x2a_25_samusAlive = false; +} + +void CMFGame::UnpauseGame() { + x1c_flowState = EGameFlowState::InGame; + CSfxManager::SetChannel(CSfxManager::ESfxChannels::Game); + x14_stateManager->DeferStateTransition(EStateManagerTransition::InGame); +} + +void CMFGame::EnterMessageScreen(float time) { + x1c_flowState = EGameFlowState::Paused; + x18_guiManager->ShowPauseGameHudMessage(*x14_stateManager, x14_stateManager->GetPauseHUDMessage(), time); +} + +void CMFGame::SaveGame() { + x1c_flowState = EGameFlowState::Paused; + x18_guiManager->PauseGame(*x14_stateManager, EInGameGuiState::PauseSaveGame); +} + +void CMFGame::EnterLogBook() { + x1c_flowState = EGameFlowState::Paused; + x18_guiManager->PauseGame(*x14_stateManager, EInGameGuiState::PauseLogBook); +} + +void CMFGame::PauseGame() { + x1c_flowState = EGameFlowState::Paused; + x18_guiManager->PauseGame(*x14_stateManager, EInGameGuiState::PauseGame); +} + +void CMFGame::EnterMapScreen() { + x1c_flowState = EGameFlowState::Paused; + x18_guiManager->PauseGame(*x14_stateManager, EInGameGuiState::MapScreen); + x14_stateManager->SetInMapScreen(true); +} + +CMFGameLoader::CMFGameLoader() : CMFGameLoaderBase("CMFGameLoader") { + CMain* m = static_cast(g_Main); + switch (m->GetFlowState()) { + case EFlowState::Default: + case EFlowState::StateSetter: { + CAssetId mlvlId = g_GameState->CurrentWorldAssetId(); + if (g_MemoryCardSys->HasSaveWorldMemory(mlvlId)) { + const CSaveWorldMemory& savwMem = g_MemoryCardSys->GetSaveWorldMemory(mlvlId); + if (savwMem.GetWorldNameId().IsValid()) { + CAssetId wtMgrFont = g_ResFactory->TranslateOriginalToNew(0xB7BBD0B4); + g_GameState->GetWorldTransitionManager()->EnableTransition(wtMgrFont, savwMem.GetWorldNameId(), 1, false, 0.1f, + 16.f, 1.f); + } + } + } + default: + break; + } + + if (g_GameState->CurrentWorldAssetId() == g_ResFactory->TranslateOriginalToNew(0x158EFE17) && + g_GameState->CurrentWorldState().GetCurrentAreaId() == 0) { + const SObjectTag* strgTag = g_ResFactory->GetResourceIdByName("STRG_IntroLevelLoad"); + if (strgTag) + g_GameState->GetWorldTransitionManager()->EnableTransition(-1, strgTag->id, 0, false, 0.1f, 16.f, 1.f); + } } CMFGameLoader::~CMFGameLoader() {} -static const char* LoadDepPAKs[] = -{ - "TestAnim", - "SamusGun", - "SamGunFx", - nullptr -}; +static const char* LoadDepPAKs[] = {"TestAnim", "SamusGun", "SamGunFx", nullptr}; -void CMFGameLoader::MakeLoadDependencyList() -{ - std::vector tags; - for (int i=0 ; LoadDepPAKs[i] ; ++i) - g_ResFactory->GetTagListForFile(LoadDepPAKs[i], tags); +void CMFGameLoader::MakeLoadDependencyList() { + std::vector tags; + for (int i = 0; LoadDepPAKs[i]; ++i) + g_ResFactory->GetTagListForFile(LoadDepPAKs[i], tags); - x1c_loadList.reserve(tags.size()); - for (const SObjectTag& tag : tags) - x1c_loadList.push_back(g_SimplePool->GetObj(tag)); + x1c_loadList.reserve(tags.size()); + for (const SObjectTag& tag : tags) + x1c_loadList.push_back(g_SimplePool->GetObj(tag)); } -CIOWin::EMessageReturn CMFGameLoader::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - std::shared_ptr wtMgr = g_GameState->GetWorldTransitionManager(); +CIOWin::EMessageReturn CMFGameLoader::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + std::shared_ptr wtMgr = g_GameState->GetWorldTransitionManager(); - switch (msg.GetType()) - { - case EArchMsgType::TimerTick: - { - const CArchMsgParmReal32& tick = MakeMsg::GetParmTimerTick(msg); - float dt = tick.x4_parm; - if (!x2c_24_initialized) - { - if (x1c_loadList.empty()) - { - MakeLoadDependencyList(); - wtMgr->StartTransition(); - return EMessageReturn::Exit; - } - u32 loadingCount = 0; - for (CToken& tok : x1c_loadList) - { - tok.Lock(); - if (!tok.IsLoaded()) - ++loadingCount; - } - wtMgr->Update(dt); - if (loadingCount) - return EMessageReturn::Exit; - x2c_24_initialized = true; - } - else - { - wtMgr->Update(dt); - } - - if (!x14_stateMgr) - { - CWorldTransManager::WaitForModelsAndTextures(); - CWorldState& wldState = g_GameState->CurrentWorldState(); - x14_stateMgr = std::make_shared(wldState.RelayTracker(), - wldState.MapWorldInfo(), - g_GameState->GetPlayerState(), - wtMgr, - wldState.GetLayerState()); - } - - if (x14_stateMgr->xb3c_initPhase != CStateManager::EInitPhase::Done) - { - CWorldState& wldState = g_GameState->CurrentWorldState(); - x14_stateMgr->InitializeState(wldState.GetWorldAssetId(), - wldState.GetCurrentAreaId(), - wldState.GetDesiredAreaAssetId()); - return EMessageReturn::Exit; - } - - if (!x18_guiMgr) - x18_guiMgr = std::make_shared(*x14_stateMgr, queue); - if (!x18_guiMgr->CheckLoadComplete(*x14_stateMgr)) - return EMessageReturn::Exit; - - x1c_loadList.clear(); - - wtMgr->StartTextFadeOut(); - x2c_25_transitionFinished = wtMgr->IsTransitionFinished(); + switch (msg.GetType()) { + case EArchMsgType::TimerTick: { + const CArchMsgParmReal32& tick = MakeMsg::GetParmTimerTick(msg); + float dt = tick.x4_parm; + if (!x2c_24_initialized) { + if (x1c_loadList.empty()) { + MakeLoadDependencyList(); + wtMgr->StartTransition(); return EMessageReturn::Exit; + } + u32 loadingCount = 0; + for (CToken& tok : x1c_loadList) { + tok.Lock(); + if (!tok.IsLoaded()) + ++loadingCount; + } + wtMgr->Update(dt); + if (loadingCount) + return EMessageReturn::Exit; + x2c_24_initialized = true; + } else { + wtMgr->Update(dt); } - case EArchMsgType::FrameEnd: - { - if (x2c_25_transitionFinished) - { - queue.Push( - MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 10, 1000, - std::make_shared(x14_stateMgr, x18_guiMgr, queue))); - return EMessageReturn::RemoveIOWinAndExit; - } + + if (!x14_stateMgr) { + CWorldTransManager::WaitForModelsAndTextures(); + CWorldState& wldState = g_GameState->CurrentWorldState(); + x14_stateMgr = std::make_shared(wldState.RelayTracker(), wldState.MapWorldInfo(), + g_GameState->GetPlayerState(), wtMgr, wldState.GetLayerState()); } - default: - break; + + if (x14_stateMgr->xb3c_initPhase != CStateManager::EInitPhase::Done) { + CWorldState& wldState = g_GameState->CurrentWorldState(); + x14_stateMgr->InitializeState(wldState.GetWorldAssetId(), wldState.GetCurrentAreaId(), + wldState.GetDesiredAreaAssetId()); + return EMessageReturn::Exit; } + + if (!x18_guiMgr) + x18_guiMgr = std::make_shared(*x14_stateMgr, queue); + if (!x18_guiMgr->CheckLoadComplete(*x14_stateMgr)) + return EMessageReturn::Exit; + + x1c_loadList.clear(); + + wtMgr->StartTextFadeOut(); + x2c_25_transitionFinished = wtMgr->IsTransitionFinished(); return EMessageReturn::Exit; + } + case EArchMsgType::FrameEnd: { + if (x2c_25_transitionFinished) { + queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 10, 1000, + std::make_shared(x14_stateMgr, x18_guiMgr, queue))); + return EMessageReturn::RemoveIOWinAndExit; + } + } + default: + break; + } + return EMessageReturn::Exit; } void CMFGameLoader::Draw() const { g_GameState->GetWorldTransitionManager()->Draw(); } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CMFGame.hpp b/Runtime/MP1/CMFGame.hpp index ceb22e9ea..ecfeeb01a 100644 --- a/Runtime/MP1/CMFGame.hpp +++ b/Runtime/MP1/CMFGame.hpp @@ -4,89 +4,73 @@ #include "CInGameGuiManager.hpp" #include "Graphics/Shaders/CColoredQuadFilter.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CInGameGuiManager; class CToken; -namespace MP1 -{ +namespace MP1 { -enum class EGameFlowState -{ - InGame = 0, - Paused, - SamusDied, - CinematicSkip -}; +enum class EGameFlowState { InGame = 0, Paused, SamusDied, CinematicSkip }; -class CMFGame : public CMFGameBase -{ - std::shared_ptr x14_stateManager; - std::shared_ptr x18_guiManager; - EGameFlowState x1c_flowState = EGameFlowState::InGame; - float x20_cineSkipTime; - u32 x24_ = 0; - TUniqueId x28_skippedCineCam = kInvalidUniqueId; - union - { - struct - { - bool x2a_24_initialized : 1; - bool x2a_25_samusAlive : 1; - }; - u8 _dummy = 0; +class CMFGame : public CMFGameBase { + std::shared_ptr x14_stateManager; + std::shared_ptr x18_guiManager; + EGameFlowState x1c_flowState = EGameFlowState::InGame; + float x20_cineSkipTime; + u32 x24_ = 0; + TUniqueId x28_skippedCineCam = kInvalidUniqueId; + union { + struct { + bool x2a_24_initialized : 1; + bool x2a_25_samusAlive : 1; }; + u8 _dummy = 0; + }; - CColoredQuadFilter m_fadeToBlack = {EFilterType::Multiply}; + CColoredQuadFilter m_fadeToBlack = {EFilterType::Multiply}; - bool IsCameraActiveFlow() const - { - return (x1c_flowState == EGameFlowState::InGame || x1c_flowState == EGameFlowState::SamusDied); - } + bool IsCameraActiveFlow() const { + return (x1c_flowState == EGameFlowState::InGame || x1c_flowState == EGameFlowState::SamusDied); + } public: - CMFGame(const std::weak_ptr& stateMgr, const std::weak_ptr& guiMgr, - const CArchitectureQueue&); - ~CMFGame(); - CIOWin::EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); - void Touch(); - void Draw() const; - void PlayerDied(); - void UnpauseGame(); - void EnterMessageScreen(float time); - void SaveGame(); - void EnterLogBook(); - void PauseGame(); - void EnterMapScreen(); + CMFGame(const std::weak_ptr& stateMgr, const std::weak_ptr& guiMgr, + const CArchitectureQueue&); + ~CMFGame(); + CIOWin::EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); + void Touch(); + void Draw() const; + void PlayerDied(); + void UnpauseGame(); + void EnterMessageScreen(float time); + void SaveGame(); + void EnterLogBook(); + void PauseGame(); + void EnterMapScreen(); }; -class CMFGameLoader : public CMFGameLoaderBase -{ - std::shared_ptr x14_stateMgr; - std::shared_ptr x18_guiMgr; - std::vector x1c_loadList; +class CMFGameLoader : public CMFGameLoaderBase { + std::shared_ptr x14_stateMgr; + std::shared_ptr x18_guiMgr; + std::vector x1c_loadList; - union - { - struct - { - bool x2c_24_initialized : 1; - bool x2c_25_transitionFinished : 1; - }; - u8 _dummy = 0; + union { + struct { + bool x2c_24_initialized : 1; + bool x2c_25_transitionFinished : 1; }; + u8 _dummy = 0; + }; - void MakeLoadDependencyList(); + void MakeLoadDependencyList(); public: - CMFGameLoader(); - ~CMFGameLoader(); - EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); - void Draw() const; + CMFGameLoader(); + ~CMFGameLoader(); + EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue); + void Draw() const; }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CMainFlow.cpp b/Runtime/MP1/CMainFlow.cpp index 1ce173ba9..10a21a8db 100644 --- a/Runtime/MP1/CMainFlow.cpp +++ b/Runtime/MP1/CMainFlow.cpp @@ -14,101 +14,87 @@ #include "CNESEmulator.hpp" #include "CQuitGameScreen.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -void CMainFlow::AdvanceGameState(CArchitectureQueue& queue) -{ - switch (x14_gameState) - { - case EClientFlowStates::Game: - SetGameState(EClientFlowStates::GameExit, queue); - break; - case EClientFlowStates::PreFrontEnd: - SetGameState(EClientFlowStates::FrontEnd, queue); - break; - case EClientFlowStates::FrontEnd: - SetGameState(EClientFlowStates::Game, queue); - break; - case EClientFlowStates::GameExit: - { - MP1::CMain* main = static_cast(g_Main); - if (main->GetFlowState() != EFlowState::None && - main->GetFlowState() != EFlowState::StateSetter) - main->SetX30(true); - } - case EClientFlowStates::Unspecified: - SetGameState(EClientFlowStates::PreFrontEnd, queue); - break; - } -} - -void CMainFlow::SetGameState(EClientFlowStates state, CArchitectureQueue& queue) -{ - x14_gameState = state; +void CMainFlow::AdvanceGameState(CArchitectureQueue& queue) { + switch (x14_gameState) { + case EClientFlowStates::Game: + SetGameState(EClientFlowStates::GameExit, queue); + break; + case EClientFlowStates::PreFrontEnd: + SetGameState(EClientFlowStates::FrontEnd, queue); + break; + case EClientFlowStates::FrontEnd: + SetGameState(EClientFlowStates::Game, queue); + break; + case EClientFlowStates::GameExit: { MP1::CMain* main = static_cast(g_Main); - - switch (state) - { - case EClientFlowStates::GameExit: - { - switch (main->GetFlowState()) - { - case EFlowState::WinBad: - case EFlowState::WinGood: - case EFlowState::WinBest: - queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, - std::make_shared())); - break; - case EFlowState::LoseGame: - queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, - std::make_shared(CPlayMovie::EWhichMovie::LoseGame))); - break; - default: break; - } - break; - } - case EClientFlowStates::PreFrontEnd: - { - if (main->GetFlowState() == EFlowState::None) - return; - queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, - std::make_shared())); - break; - } - case EClientFlowStates::FrontEnd: - { - std::shared_ptr nextIOWin; - switch (main->GetFlowState()) - { - case EFlowState::StateSetter: - nextIOWin = std::make_shared(); - break; - case EFlowState::WinBad: - case EFlowState::WinGood: - case EFlowState::WinBest: - case EFlowState::LoseGame: - case EFlowState::Default: - nextIOWin = std::make_shared(); - break; - default: return; - } - - queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, std::move(nextIOWin))); - break; - } - case EClientFlowStates::Game: - { - g_GameState->GameOptions().EnsureSettings(); - std::shared_ptr gameLoader = std::make_shared(); - main->SetFlowState(EFlowState::Default); - queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 10, 1000, - gameLoader)); - break; - } - default: break; - } + if (main->GetFlowState() != EFlowState::None && main->GetFlowState() != EFlowState::StateSetter) + main->SetX30(true); + } + case EClientFlowStates::Unspecified: + SetGameState(EClientFlowStates::PreFrontEnd, queue); + break; + } } +void CMainFlow::SetGameState(EClientFlowStates state, CArchitectureQueue& queue) { + x14_gameState = state; + MP1::CMain* main = static_cast(g_Main); + switch (state) { + case EClientFlowStates::GameExit: { + switch (main->GetFlowState()) { + case EFlowState::WinBad: + case EFlowState::WinGood: + case EFlowState::WinBest: + queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, std::make_shared())); + break; + case EFlowState::LoseGame: + queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, + std::make_shared(CPlayMovie::EWhichMovie::LoseGame))); + break; + default: + break; + } + break; + } + case EClientFlowStates::PreFrontEnd: { + if (main->GetFlowState() == EFlowState::None) + return; + queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, std::make_shared())); + break; + } + case EClientFlowStates::FrontEnd: { + std::shared_ptr nextIOWin; + switch (main->GetFlowState()) { + case EFlowState::StateSetter: + nextIOWin = std::make_shared(); + break; + case EFlowState::WinBad: + case EFlowState::WinGood: + case EFlowState::WinBest: + case EFlowState::LoseGame: + case EFlowState::Default: + nextIOWin = std::make_shared(); + break; + default: + return; + } + + queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 12, 11, std::move(nextIOWin))); + break; + } + case EClientFlowStates::Game: { + g_GameState->GameOptions().EnsureSettings(); + std::shared_ptr gameLoader = std::make_shared(); + main->SetFlowState(EFlowState::Default); + queue.Push(MakeMsg::CreateCreateIOWin(EArchMsgTarget::IOWinManager, 10, 1000, gameLoader)); + break; + } + default: + break; + } } + +} // namespace urde::MP1 diff --git a/Runtime/MP1/CMainFlow.hpp b/Runtime/MP1/CMainFlow.hpp index 164644262..921b2efd7 100644 --- a/Runtime/MP1/CMainFlow.hpp +++ b/Runtime/MP1/CMainFlow.hpp @@ -2,25 +2,21 @@ #include "CMainFlowBase.hpp" -namespace urde -{ +namespace urde { class CArchitectureMessage; class CArchitectureQueue; -namespace MP1 -{ +namespace MP1 { -class CMainFlow : public CMainFlowBase -{ +class CMainFlow : public CMainFlowBase { public: - CMainFlow() : CMainFlowBase("CMainFlow") {} - void AdvanceGameState(CArchitectureQueue& queue); - void SetGameState(EClientFlowStates state, CArchitectureQueue& queue); - bool GetIsContinueDraw() const {return false;} - void Draw() const {} + CMainFlow() : CMainFlowBase("CMainFlow") {} + void AdvanceGameState(CArchitectureQueue& queue); + void SetGameState(EClientFlowStates state, CArchitectureQueue& queue); + bool GetIsContinueDraw() const { return false; } + void Draw() const {} }; -} - -} +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CMemoryCardDriver.cpp b/Runtime/MP1/CMemoryCardDriver.cpp index 5351f64d5..9a4d6632e 100644 --- a/Runtime/MP1/CMemoryCardDriver.cpp +++ b/Runtime/MP1/CMemoryCardDriver.cpp @@ -2,938 +2,787 @@ #include "MP1.hpp" #include "CCRC32.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -static const char* SaveFileNames[] = -{ - "MetroidPrime A", - "MetroidPrime B" -}; +static const char* SaveFileNames[] = {"MetroidPrime A", "MetroidPrime B"}; using ECardResult = kabufuda::ECardResult; using ECardSlot = kabufuda::ECardSlot; -ECardResult CMemoryCardDriver::SFileInfo::Open() -{ - return CMemoryCardSys::OpenFile(GetFileCardPort(), x14_name.c_str(), x0_fileInfo); +ECardResult CMemoryCardDriver::SFileInfo::Open() { + return CMemoryCardSys::OpenFile(GetFileCardPort(), x14_name.c_str(), x0_fileInfo); } -ECardResult CMemoryCardDriver::SFileInfo::Close() -{ - return CMemoryCardSys::CloseFile(x0_fileInfo); +ECardResult CMemoryCardDriver::SFileInfo::Close() { return CMemoryCardSys::CloseFile(x0_fileInfo); } + +ECardResult CMemoryCardDriver::SFileInfo::StartRead() { + CMemoryCardSys::CardStat stat = {}; + ECardResult result = CMemoryCardSys::GetStatus(x0_fileInfo.slot, x0_fileInfo.getFileNo(), stat); + if (result != ECardResult::READY) + return result; + + u32 length = stat.GetFileLength(); + x34_saveData.clear(); + x24_saveFileData.resize(length); + return CMemoryCardSys::ReadFile(x0_fileInfo, x24_saveFileData.data(), length, 0); } -ECardResult CMemoryCardDriver::SFileInfo::StartRead() -{ - CMemoryCardSys::CardStat stat = {}; - ECardResult result = CMemoryCardSys::GetStatus(x0_fileInfo.slot, x0_fileInfo.getFileNo(), stat); - if (result != ECardResult::READY) - return result; - - u32 length = stat.GetFileLength(); - x34_saveData.clear(); - x24_saveFileData.resize(length); - return CMemoryCardSys::ReadFile(x0_fileInfo, x24_saveFileData.data(), length, 0); +ECardResult CMemoryCardDriver::SFileInfo::TryFileRead() { + ECardResult res = CMemoryCardSys::GetResultCode(GetFileCardPort()); + if (res == ECardResult::READY) + res = FileRead(); + return res; } -ECardResult CMemoryCardDriver::SFileInfo::TryFileRead() -{ - ECardResult res = CMemoryCardSys::GetResultCode(GetFileCardPort()); - if (res == ECardResult::READY) - res = FileRead(); - return res; -} - -ECardResult CMemoryCardDriver::SFileInfo::FileRead() -{ - x34_saveData.clear(); - u32 existingCrc = hecl::SBig(*reinterpret_cast(x24_saveFileData.data())); - u32 newCrc = CCRC32::Calculate(x24_saveFileData.data() + 4, x24_saveFileData.size() - 4); - if (existingCrc == newCrc) - { - u32 saveDataOff; - ECardResult result = GetSaveDataOffset(saveDataOff); - if (result != ECardResult::READY) - { - x24_saveFileData.clear(); - return result; - } - - u32 saveSize = x24_saveFileData.size() - saveDataOff; - x34_saveData.resize(saveSize); - memmove(x34_saveData.data(), x24_saveFileData.data() + saveDataOff, saveSize); - x24_saveFileData.clear(); - return ECardResult::READY; - } - else - { - x24_saveFileData.clear(); - return ECardResult::CRC_MISMATCH; - } -} - -ECardResult CMemoryCardDriver::SFileInfo::GetSaveDataOffset(u32& offOut) -{ - CMemoryCardSys::CardStat stat = {}; - ECardResult result = CMemoryCardSys::GetStatus(x0_fileInfo.slot, x0_fileInfo.getFileNo(), stat); - if (result != ECardResult::READY) - { - offOut = -1; - return result; +ECardResult CMemoryCardDriver::SFileInfo::FileRead() { + x34_saveData.clear(); + u32 existingCrc = hecl::SBig(*reinterpret_cast(x24_saveFileData.data())); + u32 newCrc = CCRC32::Calculate(x24_saveFileData.data() + 4, x24_saveFileData.size() - 4); + if (existingCrc == newCrc) { + u32 saveDataOff; + ECardResult result = GetSaveDataOffset(saveDataOff); + if (result != ECardResult::READY) { + x24_saveFileData.clear(); + return result; } - offOut = 4; - offOut += 64; - switch (stat.GetBannerFormat()) - { - case kabufuda::EImageFormat::C8: - offOut += 3584; - break; - case kabufuda::EImageFormat::RGB5A3: - offOut += 6144; - break; - default: break; - } - - int idx = 0; - bool paletteIcon = false; - for (kabufuda::EImageFormat fmt = stat.GetIconFormat(idx); - fmt != kabufuda::EImageFormat::None; - fmt = stat.GetIconFormat(idx)) - { - if (fmt == kabufuda::EImageFormat::C8) - { - paletteIcon = true; - offOut += 1024; - } - else - offOut += 2048; - ++idx; - } - - if (paletteIcon) - offOut += 512; - + u32 saveSize = x24_saveFileData.size() - saveDataOff; + x34_saveData.resize(saveSize); + memmove(x34_saveData.data(), x24_saveFileData.data() + saveDataOff, saveSize); + x24_saveFileData.clear(); return ECardResult::READY; + } else { + x24_saveFileData.clear(); + return ECardResult::CRC_MISMATCH; + } } -CMemoryCardDriver::SGameFileSlot::SGameFileSlot() -{ - InitializeFromGameState(); +ECardResult CMemoryCardDriver::SFileInfo::GetSaveDataOffset(u32& offOut) { + CMemoryCardSys::CardStat stat = {}; + ECardResult result = CMemoryCardSys::GetStatus(x0_fileInfo.slot, x0_fileInfo.getFileNo(), stat); + if (result != ECardResult::READY) { + offOut = -1; + return result; + } + + offOut = 4; + offOut += 64; + switch (stat.GetBannerFormat()) { + case kabufuda::EImageFormat::C8: + offOut += 3584; + break; + case kabufuda::EImageFormat::RGB5A3: + offOut += 6144; + break; + default: + break; + } + + int idx = 0; + bool paletteIcon = false; + for (kabufuda::EImageFormat fmt = stat.GetIconFormat(idx); fmt != kabufuda::EImageFormat::None; + fmt = stat.GetIconFormat(idx)) { + if (fmt == kabufuda::EImageFormat::C8) { + paletteIcon = true; + offOut += 1024; + } else + offOut += 2048; + ++idx; + } + + if (paletteIcon) + offOut += 512; + + return ECardResult::READY; } -CMemoryCardDriver::SGameFileSlot::SGameFileSlot(CMemoryInStream& in) -{ - in.readBytesToBuf(x0_saveBuffer, 940); - x944_fileInfo = CGameState::LoadGameFileState(x0_saveBuffer); +CMemoryCardDriver::SGameFileSlot::SGameFileSlot() { InitializeFromGameState(); } + +CMemoryCardDriver::SGameFileSlot::SGameFileSlot(CMemoryInStream& in) { + in.readBytesToBuf(x0_saveBuffer, 940); + x944_fileInfo = CGameState::LoadGameFileState(x0_saveBuffer); } -void CMemoryCardDriver::SGameFileSlot::InitializeFromGameState() -{ - CBitStreamWriter w(x0_saveBuffer, 940); - g_GameState->PutTo(w); - w.Flush(); - x944_fileInfo = CGameState::LoadGameFileState(x0_saveBuffer); +void CMemoryCardDriver::SGameFileSlot::InitializeFromGameState() { + CBitStreamWriter w(x0_saveBuffer, 940); + g_GameState->PutTo(w); + w.Flush(); + x944_fileInfo = CGameState::LoadGameFileState(x0_saveBuffer); } -void CMemoryCardDriver::SGameFileSlot::LoadGameState(u32 idx) -{ - CBitStreamReader r(x0_saveBuffer, 940); - static_cast(g_Main)->StreamNewGameState(r, idx); +void CMemoryCardDriver::SGameFileSlot::LoadGameState(u32 idx) { + CBitStreamReader r(x0_saveBuffer, 940); + static_cast(g_Main)->StreamNewGameState(r, idx); } CMemoryCardDriver::SFileInfo::SFileInfo(kabufuda::ECardSlot port, std::string_view name) : x0_fileInfo(port), x14_name(name) {} -CMemoryCardDriver::CMemoryCardDriver(kabufuda::ECardSlot cardPort, CAssetId saveBanner, - CAssetId saveIcon0, CAssetId saveIcon1, bool importPersistent) -: x0_cardPort(cardPort), x4_saveBanner(saveBanner), - x8_saveIcon0(saveIcon0), xc_saveIcon1(saveIcon1), x19d_importPersistent(importPersistent) -{ - x100_mcFileInfos.reserve(2); - x100_mcFileInfos.emplace_back(EFileState::Unknown, SFileInfo(x0_cardPort, SaveFileNames[0])); - x100_mcFileInfos.emplace_back(EFileState::Unknown, SFileInfo(x0_cardPort, SaveFileNames[1])); +CMemoryCardDriver::CMemoryCardDriver(kabufuda::ECardSlot cardPort, CAssetId saveBanner, CAssetId saveIcon0, + CAssetId saveIcon1, bool importPersistent) +: x0_cardPort(cardPort) +, x4_saveBanner(saveBanner) +, x8_saveIcon0(saveIcon0) +, xc_saveIcon1(saveIcon1) +, x19d_importPersistent(importPersistent) { + x100_mcFileInfos.reserve(2); + x100_mcFileInfos.emplace_back(EFileState::Unknown, SFileInfo(x0_cardPort, SaveFileNames[0])); + x100_mcFileInfos.emplace_back(EFileState::Unknown, SFileInfo(x0_cardPort, SaveFileNames[1])); } -void CMemoryCardDriver::NoCardFound() -{ - x10_state = EState::NoCard; - static_cast(g_Main)->SetCardBusy(false); +void CMemoryCardDriver::NoCardFound() { + x10_state = EState::NoCard; + static_cast(g_Main)->SetCardBusy(false); } -const CGameState::GameFileStateInfo* CMemoryCardDriver::GetGameFileStateInfo(int idx) -{ - SGameFileSlot* slot = xe4_fileSlots[idx].get(); - if (!slot) - return nullptr; - return &slot->x944_fileInfo; +const CGameState::GameFileStateInfo* CMemoryCardDriver::GetGameFileStateInfo(int idx) { + SGameFileSlot* slot = xe4_fileSlots[idx].get(); + if (!slot) + return nullptr; + return &slot->x944_fileInfo; } -CMemoryCardDriver::SSaveHeader CMemoryCardDriver::LoadSaveHeader(CMemoryInStream& in) -{ - SSaveHeader ret; - ret.x0_version = in.readUint32Big(); - for (int i=0 ; i<3 ; ++i) - ret.x4_savePresent[i] = in.readBool(); - return ret; +CMemoryCardDriver::SSaveHeader CMemoryCardDriver::LoadSaveHeader(CMemoryInStream& in) { + SSaveHeader ret; + ret.x0_version = in.readUint32Big(); + for (int i = 0; i < 3; ++i) + ret.x4_savePresent[i] = in.readBool(); + return ret; } -std::unique_ptr CMemoryCardDriver::LoadSaveFile(CMemoryInStream& in) -{ - return std::make_unique(in); +std::unique_ptr CMemoryCardDriver::LoadSaveFile(CMemoryInStream& in) { + return std::make_unique(in); } -void CMemoryCardDriver::ReadFinished() -{ - CMemoryCardSys::CardStat stat = {}; - SFileInfo& fileInfo = x100_mcFileInfos[x194_fileIdx].second; - if (CMemoryCardSys::GetStatus(fileInfo.x0_fileInfo.slot, - fileInfo.x0_fileInfo.getFileNo(), stat) != ECardResult::READY) - { +void CMemoryCardDriver::ReadFinished() { + CMemoryCardSys::CardStat stat = {}; + SFileInfo& fileInfo = x100_mcFileInfos[x194_fileIdx].second; + if (CMemoryCardSys::GetStatus(fileInfo.x0_fileInfo.slot, fileInfo.x0_fileInfo.getFileNo(), stat) != + ECardResult::READY) { + NoCardFound(); + return; + } + + x20_fileTime = stat.GetTime(); + CMemoryInStream r(fileInfo.x34_saveData.data(), 3004); + SSaveHeader header = LoadSaveHeader(r); + r.readBytesToBuf(x30_systemData, 174); + + for (int i = 0; i < 3; ++i) + if (header.x4_savePresent[i]) + xe4_fileSlots[i] = LoadSaveFile(r); + + if (x19d_importPersistent) + ImportPersistentOptions(); +} + +void CMemoryCardDriver::ImportPersistentOptions() { + CBitStreamReader r(x30_systemData, 174); + CPersistentOptions opts(r); + g_GameState->ImportPersistentOptions(opts); +} + +void CMemoryCardDriver::ExportPersistentOptions() { + CBitStreamReader r(x30_systemData, 174); + CPersistentOptions opts(r); + g_GameState->ExportPersistentOptions(opts); + CBitStreamWriter w(x30_systemData, 174); + opts.PutTo(w); +} + +void CMemoryCardDriver::CheckCardCapacity() { + if (x18_cardFreeBytes < 0x2000 || !x1c_cardFreeFiles) + x14_error = EError::CardStillFull; +} + +void CMemoryCardDriver::IndexFiles() { + x14_error = EError::OK; + for (std::pair& info : x100_mcFileInfos) { + if (info.first == EFileState::Unknown) { + ECardResult result = info.second.Open(); + if (result == ECardResult::NOFILE) { + info.first = EFileState::NoFile; + continue; + } else if (result == ECardResult::READY) { + CMemoryCardSys::CardStat stat = {}; + if (CMemoryCardSys::GetStatus(info.second.x0_fileInfo.slot, info.second.x0_fileInfo.getFileNo(), stat) == + ECardResult::READY) { + u32 comment = stat.GetCommentAddr(); + if (comment == -1) + info.first = EFileState::BadFile; + else + info.first = EFileState::File; + } else { + NoCardFound(); + return; + } + if (info.second.Close() == ECardResult::NOCARD) { + NoCardFound(); + return; + } + } else { NoCardFound(); return; + } } + } - x20_fileTime = stat.GetTime(); - CMemoryInStream r(fileInfo.x34_saveData.data(), 3004); - SSaveHeader header = LoadSaveHeader(r); - r.readBytesToBuf(x30_systemData, 174); + if (x100_mcFileInfos[0].first == EFileState::File) { + if (x100_mcFileInfos[1].first == EFileState::File) { + CMemoryCardSys::CardStat stat = {}; + if (CMemoryCardSys::GetStatus(x100_mcFileInfos[0].second.x0_fileInfo.slot, + x100_mcFileInfos[0].second.x0_fileInfo.getFileNo(), stat) == ECardResult::READY) { + u32 timeA = stat.GetTime(); + if (CMemoryCardSys::GetStatus(x100_mcFileInfos[1].second.x0_fileInfo.slot, + x100_mcFileInfos[1].second.x0_fileInfo.getFileNo(), stat) == ECardResult::READY) { + u32 timeB = stat.GetTime(); + if (timeA > timeB) + x194_fileIdx = 0; + else + x194_fileIdx = 1; + StartFileRead(); + return; + } + NoCardFound(); + return; + } + NoCardFound(); + return; + } + x194_fileIdx = 0; + StartFileRead(); + return; + } - for (int i=0 ; i<3 ; ++i) - if (header.x4_savePresent[i]) - xe4_fileSlots[i] = LoadSaveFile(r); + if (x100_mcFileInfos[1].first == EFileState::File) { + x194_fileIdx = 1; + StartFileRead(); + return; + } - if (x19d_importPersistent) - ImportPersistentOptions(); + if (x100_mcFileInfos[0].first == EFileState::BadFile || x100_mcFileInfos[1].first == EFileState::BadFile) { + x10_state = EState::FileBad; + x14_error = EError::FileCorrupted; + } else { + x10_state = EState::FileBad; + x14_error = EError::FileMissing; + } } -void CMemoryCardDriver::ImportPersistentOptions() -{ - CBitStreamReader r(x30_systemData, 174); - CPersistentOptions opts(r); - g_GameState->ImportPersistentOptions(opts); +void CMemoryCardDriver::StartCardProbe() { + x10_state = EState::CardProbe; + x14_error = EError::OK; + UpdateCardProbe(); } -void CMemoryCardDriver::ExportPersistentOptions() -{ - CBitStreamReader r(x30_systemData, 174); - CPersistentOptions opts(r); - g_GameState->ExportPersistentOptions(opts); - CBitStreamWriter w(x30_systemData, 174); - opts.PutTo(w); +void CMemoryCardDriver::StartMountCard() { + x10_state = EState::CardMount; + x14_error = EError::OK; + ECardResult result = CMemoryCardSys::MountCard(x0_cardPort); + if (result != ECardResult::READY) + UpdateMountCard(result); } -void CMemoryCardDriver::CheckCardCapacity() -{ - if (x18_cardFreeBytes < 0x2000 || !x1c_cardFreeFiles) - x14_error = EError::CardStillFull; +void CMemoryCardDriver::StartCardCheck() { + x14_error = EError::OK; + x10_state = EState::CardCheck; + ECardResult result = CMemoryCardSys::CheckCard(x0_cardPort); + if (result != ECardResult::READY) + UpdateCardCheck(result); } -void CMemoryCardDriver::IndexFiles() -{ +void CMemoryCardDriver::StartFileDeleteBad() { + x14_error = EError::OK; + x10_state = EState::FileDeleteBad; + int idx = 0; + for (std::pair& info : x100_mcFileInfos) { + if (info.first == EFileState::BadFile) { + x194_fileIdx = idx; + ECardResult result = CMemoryCardSys::FastDeleteFile(x0_cardPort, info.second.GetFileNo()); + if (result != ECardResult::READY) { + UpdateFileDeleteBad(result); + return; + } + } + ++idx; + } +} + +void CMemoryCardDriver::StartFileRead() { + x14_error = EError::OK; + x10_state = EState::FileRead; + ECardResult result = x100_mcFileInfos[x194_fileIdx].second.Open(); + if (result != ECardResult::READY) { + UpdateFileRead(result); + return; + } + + result = x100_mcFileInfos[x194_fileIdx].second.StartRead(); + if (result != ECardResult::READY) + UpdateFileRead(result); +} + +void CMemoryCardDriver::StartFileDeleteAlt() { + x14_error = EError::OK; + x10_state = EState::FileDeleteAlt; + SFileInfo& fileInfo = x100_mcFileInfos[!bool(x194_fileIdx)].second; + ECardResult result = CMemoryCardSys::FastDeleteFile(x0_cardPort, fileInfo.GetFileNo()); + if (result != ECardResult::READY) + UpdateFileDeleteAlt(result); +} + +void CMemoryCardDriver::StartFileCreate() { + x14_error = EError::OK; + x10_state = EState::FileCreate; + if (x18_cardFreeBytes < 8192 || x1c_cardFreeFiles < 2) { + x10_state = EState::FileCreateFailed; + x14_error = EError::CardFull; + return; + } + + x194_fileIdx = 0; + x198_fileInfo = std::make_unique(x0_cardPort, SaveFileNames[x194_fileIdx]); + InitializeFileInfo(); + ECardResult result = x198_fileInfo->CreateFile(); + if (result != ECardResult::READY) + UpdateFileCreate(result); +} + +void CMemoryCardDriver::StartFileWrite() { + x14_error = EError::OK; + x10_state = EState::FileWrite; + ECardResult result = x198_fileInfo->WriteFile(); + if (result != ECardResult::READY) + UpdateFileWrite(result); +} + +void CMemoryCardDriver::StartFileCreateTransactional() { + x14_error = EError::OK; + x10_state = EState::FileCreateTransactional; + ClearFileInfo(); + if (x18_cardFreeBytes < 8192 || !x1c_cardFreeFiles) { + x10_state = EState::FileCreateTransactionalFailed; + x14_error = EError::CardFull; + return; + } + + x194_fileIdx = !bool(x194_fileIdx); + x198_fileInfo = std::make_unique(x0_cardPort, SaveFileNames[x194_fileIdx]); + InitializeFileInfo(); + ECardResult result = x198_fileInfo->CreateFile(); + if (result != ECardResult::READY) + UpdateFileCreateTransactional(result); +} + +void CMemoryCardDriver::StartFileWriteTransactional() { + x14_error = EError::OK; + x10_state = EState::FileWriteTransactional; + ECardResult result = x198_fileInfo->WriteFile(); + if (result != ECardResult::READY) + UpdateFileWriteTransactional(result); +} + +void CMemoryCardDriver::StartFileDeleteAltTransactional() { + x14_error = EError::OK; + x10_state = EState::FileDeleteAltTransactional; + ECardResult result = CMemoryCardSys::DeleteFile(x0_cardPort, SaveFileNames[!bool(x194_fileIdx)]); + if (result != ECardResult::READY) + UpdateFileDeleteAltTransactional(result); +} + +void CMemoryCardDriver::StartFileRenameBtoA() { + if (x194_fileIdx == 1) { + /* Rename B file to A file (ideally the card is always left with 'A' only) */ x14_error = EError::OK; - for (std::pair& info : x100_mcFileInfos) - { - if (info.first == EFileState::Unknown) - { - ECardResult result = info.second.Open(); - if (result == ECardResult::NOFILE) - { - info.first = EFileState::NoFile; - continue; - } - else if (result == ECardResult::READY) - { - CMemoryCardSys::CardStat stat = {}; - if (CMemoryCardSys::GetStatus(info.second.x0_fileInfo.slot, - info.second.x0_fileInfo.getFileNo(), stat) == - ECardResult::READY) - { - u32 comment = stat.GetCommentAddr(); - if (comment == -1) - info.first = EFileState::BadFile; - else - info.first = EFileState::File; - } - else - { - NoCardFound(); - return; - } - if (info.second.Close() == ECardResult::NOCARD) - { - NoCardFound(); - return; - } - } - else - { - NoCardFound(); - return; - } - } - } + x10_state = EState::FileRenameBtoA; + ECardResult result = + CMemoryCardSys::Rename(x0_cardPort, SaveFileNames[x194_fileIdx], SaveFileNames[!bool(x194_fileIdx)]); + if (result != ECardResult::READY) + UpdateFileRenameBtoA(result); + } else { + x10_state = EState::DriverClosed; + WriteBackupBuf(); + } +} - if (x100_mcFileInfos[0].first == EFileState::File) - { - if (x100_mcFileInfos[1].first == EFileState::File) - { - CMemoryCardSys::CardStat stat = {}; - if (CMemoryCardSys::GetStatus(x100_mcFileInfos[0].second.x0_fileInfo.slot, - x100_mcFileInfos[0].second.x0_fileInfo.getFileNo(), stat) == - ECardResult::READY) - { - u32 timeA = stat.GetTime(); - if (CMemoryCardSys::GetStatus(x100_mcFileInfos[1].second.x0_fileInfo.slot, - x100_mcFileInfos[1].second.x0_fileInfo.getFileNo(), stat) == - ECardResult::READY) - { - u32 timeB = stat.GetTime(); - if (timeA > timeB) - x194_fileIdx = 0; - else - x194_fileIdx = 1; - StartFileRead(); - return; - } - NoCardFound(); - return; - } - NoCardFound(); - return; - } - x194_fileIdx = 0; - StartFileRead(); +void CMemoryCardDriver::StartCardFormat() { + x14_error = EError::OK; + x10_state = EState::CardFormat; + ECardResult result = CMemoryCardSys::FormatCard(x0_cardPort); + if (result != ECardResult::READY) + UpdateCardFormat(result); +} + +void CMemoryCardDriver::UpdateMountCard(ECardResult result) { + switch (result) { + case ECardResult::READY: + x10_state = EState::CardMountDone; + StartCardCheck(); + break; + case ECardResult::BROKEN: + x10_state = EState::CardMountDone; + x14_error = EError::CardBroken; + // StartCardCheck(); + break; + default: + HandleCardError(result, EState::CardMountFailed); + break; + } +} + +void CMemoryCardDriver::UpdateCardProbe() { + auto result = CMemoryCardSys::CardProbe(x0_cardPort); + switch (result.x0_error) { + case ECardResult::READY: + if (result.x8_sectorSize != 0x2000) { + x10_state = EState::CardProbeFailed; + x14_error = EError::CardNon8KSectors; + return; + } + x10_state = EState::CardProbeDone; + StartMountCard(); + break; + case ECardResult::BUSY: + break; + case ECardResult::WRONGDEVICE: + x10_state = EState::CardProbeFailed; + x14_error = EError::CardWrongDevice; + break; + default: + NoCardFound(); + break; + } +} + +void CMemoryCardDriver::UpdateCardCheck(ECardResult result) { + switch (result) { + case ECardResult::READY: + x10_state = EState::CardCheckDone; + if (!GetCardFreeBytes()) + return; + if (CMemoryCardSys::GetSerialNo(x0_cardPort, x28_cardSerial) == ECardResult::READY) + return; + NoCardFound(); + break; + case ECardResult::BROKEN: + x10_state = EState::CardCheckFailed; + x14_error = EError::CardBroken; + break; + default: + HandleCardError(result, EState::CardCheckFailed); + } +} + +void CMemoryCardDriver::UpdateFileDeleteBad(ECardResult result) { + if (result == ECardResult::READY) { + x100_mcFileInfos[x194_fileIdx].first = EFileState::NoFile; + if (x100_mcFileInfos[!bool(x194_fileIdx)].first == EFileState::BadFile) { + x10_state = EState::FileBad; + StartFileDeleteBad(); + } else { + x10_state = EState::CardCheckDone; + if (!GetCardFreeBytes()) return; + IndexFiles(); + } + } else + HandleCardError(result, EState::FileDeleteBadFailed); +} + +void CMemoryCardDriver::UpdateFileRead(ECardResult result) { + if (result == ECardResult::READY) { + auto& fileInfo = x100_mcFileInfos[x194_fileIdx]; + ECardResult readRes = fileInfo.second.TryFileRead(); + if (fileInfo.second.Close() != ECardResult::READY) { + NoCardFound(); + return; } - if (x100_mcFileInfos[1].first == EFileState::File) - { - x194_fileIdx = 1; - StartFileRead(); - return; + u32 altFileIdx = !bool(x194_fileIdx); + if (readRes == ECardResult::READY) { + x10_state = EState::Ready; + ReadFinished(); + EFileState fileSt = x100_mcFileInfos[altFileIdx].first; + if (fileSt == EFileState::NoFile) + CheckCardCapacity(); + else + StartFileDeleteAlt(); + return; } - if (x100_mcFileInfos[0].first == EFileState::BadFile || - x100_mcFileInfos[1].first == EFileState::BadFile) - { + if (readRes == ECardResult::CRC_MISMATCH) { + x100_mcFileInfos[x194_fileIdx].first = EFileState::BadFile; + if (x100_mcFileInfos[altFileIdx].first == EFileState::File) { + x10_state = EState::CardCheckDone; + IndexFiles(); + } else { x10_state = EState::FileBad; x14_error = EError::FileCorrupted; + } } - else - { - x10_state = EState::FileBad; - x14_error = EError::FileMissing; - } + } else + HandleCardError(result, EState::FileBad); } -void CMemoryCardDriver::StartCardProbe() -{ - x10_state = EState::CardProbe; - x14_error = EError::OK; - UpdateCardProbe(); +void CMemoryCardDriver::UpdateFileDeleteAlt(ECardResult result) { + if (result == ECardResult::READY) { + x10_state = EState::Ready; + if (GetCardFreeBytes()) + CheckCardCapacity(); + } else + HandleCardError(result, EState::FileDeleteAltFailed); } -void CMemoryCardDriver::StartMountCard() -{ - x10_state = EState::CardMount; - x14_error = EError::OK; - ECardResult result = CMemoryCardSys::MountCard(x0_cardPort); - if (result != ECardResult::READY) - UpdateMountCard(result); +void CMemoryCardDriver::UpdateFileCreate(ECardResult result) { + if (result == ECardResult::READY) { + x10_state = EState::FileCreateDone; + StartFileWrite(); + } else + HandleCardError(result, EState::FileCreateFailed); } -void CMemoryCardDriver::StartCardCheck() -{ - x14_error = EError::OK; - x10_state = EState::CardCheck; - ECardResult result = CMemoryCardSys::CheckCard(x0_cardPort); - if (result != ECardResult::READY) - UpdateCardCheck(result); -} - -void CMemoryCardDriver::StartFileDeleteBad() -{ - x14_error = EError::OK; - x10_state = EState::FileDeleteBad; - int idx = 0; - for (std::pair& info : x100_mcFileInfos) - { - if (info.first == EFileState::BadFile) - { - x194_fileIdx = idx; - ECardResult result = CMemoryCardSys::FastDeleteFile(x0_cardPort, info.second.GetFileNo()); - if (result != ECardResult::READY) - { - UpdateFileDeleteBad(result); - return; - } - } - ++idx; - } -} - -void CMemoryCardDriver::StartFileRead() -{ - x14_error = EError::OK; - x10_state = EState::FileRead; - ECardResult result = x100_mcFileInfos[x194_fileIdx].second.Open(); - if (result != ECardResult::READY) - { - UpdateFileRead(result); - return; - } - - result = x100_mcFileInfos[x194_fileIdx].second.StartRead(); - if (result != ECardResult::READY) - UpdateFileRead(result); -} - -void CMemoryCardDriver::StartFileDeleteAlt() -{ - x14_error = EError::OK; - x10_state = EState::FileDeleteAlt; - SFileInfo& fileInfo = x100_mcFileInfos[!bool(x194_fileIdx)].second; - ECardResult result = CMemoryCardSys::FastDeleteFile(x0_cardPort, fileInfo.GetFileNo()); - if (result != ECardResult::READY) - UpdateFileDeleteAlt(result); -} - -void CMemoryCardDriver::StartFileCreate() -{ - x14_error = EError::OK; - x10_state = EState::FileCreate; - if (x18_cardFreeBytes < 8192 || x1c_cardFreeFiles < 2) - { - x10_state = EState::FileCreateFailed; - x14_error = EError::CardFull; - return; - } - - x194_fileIdx = 0; - x198_fileInfo = std::make_unique(x0_cardPort, SaveFileNames[x194_fileIdx]); - InitializeFileInfo(); - ECardResult result = x198_fileInfo->CreateFile(); - if (result != ECardResult::READY) - UpdateFileCreate(result); -} - -void CMemoryCardDriver::StartFileWrite() -{ - x14_error = EError::OK; - x10_state = EState::FileWrite; - ECardResult result = x198_fileInfo->WriteFile(); - if (result != ECardResult::READY) - UpdateFileWrite(result); -} - -void CMemoryCardDriver::StartFileCreateTransactional() -{ - x14_error = EError::OK; - x10_state = EState::FileCreateTransactional; - ClearFileInfo(); - if (x18_cardFreeBytes < 8192 || !x1c_cardFreeFiles) - { - x10_state = EState::FileCreateTransactionalFailed; - x14_error = EError::CardFull; - return; - } - - x194_fileIdx = !bool(x194_fileIdx); - x198_fileInfo = std::make_unique(x0_cardPort, SaveFileNames[x194_fileIdx]); - InitializeFileInfo(); - ECardResult result = x198_fileInfo->CreateFile(); - if (result != ECardResult::READY) - UpdateFileCreateTransactional(result); -} - -void CMemoryCardDriver::StartFileWriteTransactional() -{ - x14_error = EError::OK; - x10_state = EState::FileWriteTransactional; - ECardResult result = x198_fileInfo->WriteFile(); - if (result != ECardResult::READY) - UpdateFileWriteTransactional(result); -} - -void CMemoryCardDriver::StartFileDeleteAltTransactional() -{ - x14_error = EError::OK; - x10_state = EState::FileDeleteAltTransactional; - ECardResult result = CMemoryCardSys::DeleteFile(x0_cardPort, - SaveFileNames[!bool(x194_fileIdx)]); - if (result != ECardResult::READY) - UpdateFileDeleteAltTransactional(result); -} - -void CMemoryCardDriver::StartFileRenameBtoA() -{ - if (x194_fileIdx == 1) - { - /* Rename B file to A file (ideally the card is always left with 'A' only) */ - x14_error = EError::OK; - x10_state = EState::FileRenameBtoA; - ECardResult result = CMemoryCardSys::Rename(x0_cardPort, - SaveFileNames[x194_fileIdx], - SaveFileNames[!bool(x194_fileIdx)]); - if (result != ECardResult::READY) - UpdateFileRenameBtoA(result); - } - else - { - x10_state = EState::DriverClosed; - WriteBackupBuf(); - } -} - -void CMemoryCardDriver::StartCardFormat() -{ - x14_error = EError::OK; - x10_state = EState::CardFormat; - ECardResult result = CMemoryCardSys::FormatCard(x0_cardPort); - if (result != ECardResult::READY) - UpdateCardFormat(result); -} - -void CMemoryCardDriver::UpdateMountCard(ECardResult result) -{ - switch (result) - { - case ECardResult::READY: - x10_state = EState::CardMountDone; - StartCardCheck(); - break; - case ECardResult::BROKEN: - x10_state = EState::CardMountDone; - x14_error = EError::CardBroken; - //StartCardCheck(); - break; - default: - HandleCardError(result, EState::CardMountFailed); - break; - } -} - -void CMemoryCardDriver::UpdateCardProbe() -{ - auto result = CMemoryCardSys::CardProbe(x0_cardPort); - switch (result.x0_error) - { - case ECardResult::READY: - if (result.x8_sectorSize != 0x2000) - { - x10_state = EState::CardProbeFailed; - x14_error = EError::CardNon8KSectors; - return; - } - x10_state = EState::CardProbeDone; - StartMountCard(); - break; - case ECardResult::BUSY: - break; - case ECardResult::WRONGDEVICE: - x10_state = EState::CardProbeFailed; - x14_error = EError::CardWrongDevice; - break; - default: - NoCardFound(); - break; - } -} - -void CMemoryCardDriver::UpdateCardCheck(ECardResult result) -{ - switch (result) - { - case ECardResult::READY: - x10_state = EState::CardCheckDone; - if (!GetCardFreeBytes()) - return; - if (CMemoryCardSys::GetSerialNo(x0_cardPort, x28_cardSerial) == ECardResult::READY) - return; - NoCardFound(); - break; - case ECardResult::BROKEN: - x10_state = EState::CardCheckFailed; - x14_error = EError::CardBroken; - break; - default: - HandleCardError(result, EState::CardCheckFailed); - } -} - -void CMemoryCardDriver::UpdateFileDeleteBad(ECardResult result) -{ - if (result == ECardResult::READY) - { - x100_mcFileInfos[x194_fileIdx].first = EFileState::NoFile; - if (x100_mcFileInfos[!bool(x194_fileIdx)].first == EFileState::BadFile) - { - x10_state = EState::FileBad; - StartFileDeleteBad(); - } - else - { - x10_state = EState::CardCheckDone; - if (!GetCardFreeBytes()) - return; - IndexFiles(); - } - } - else - HandleCardError(result, EState::FileDeleteBadFailed); -} - -void CMemoryCardDriver::UpdateFileRead(ECardResult result) -{ - if (result == ECardResult::READY) - { - auto& fileInfo = x100_mcFileInfos[x194_fileIdx]; - ECardResult readRes = fileInfo.second.TryFileRead(); - if (fileInfo.second.Close() != ECardResult::READY) - { - NoCardFound(); - return; - } - - u32 altFileIdx = !bool(x194_fileIdx); - if (readRes == ECardResult::READY) - { - x10_state = EState::Ready; - ReadFinished(); - EFileState fileSt = x100_mcFileInfos[altFileIdx].first; - if (fileSt == EFileState::NoFile) - CheckCardCapacity(); - else - StartFileDeleteAlt(); - return; - } - - if (readRes == ECardResult::CRC_MISMATCH) - { - x100_mcFileInfos[x194_fileIdx].first = EFileState::BadFile; - if (x100_mcFileInfos[altFileIdx].first == EFileState::File) - { - x10_state = EState::CardCheckDone; - IndexFiles(); - } - else - { - x10_state = EState::FileBad; - x14_error = EError::FileCorrupted; - } - } - } - else - HandleCardError(result, EState::FileBad); -} - -void CMemoryCardDriver::UpdateFileDeleteAlt(ECardResult result) -{ - if (result == ECardResult::READY) - { - x10_state = EState::Ready; - if (GetCardFreeBytes()) - CheckCardCapacity(); - } - else - HandleCardError(result, EState::FileDeleteAltFailed); -} - -void CMemoryCardDriver::UpdateFileCreate(ECardResult result) -{ - if (result == ECardResult::READY) - { - x10_state = EState::FileCreateDone; - StartFileWrite(); - } - else - HandleCardError(result, EState::FileCreateFailed); -} - -void CMemoryCardDriver::UpdateFileWrite(ECardResult result) -{ - if (result == ECardResult::READY) - { - ECardResult xferResult = x198_fileInfo->PumpCardTransfer(); - if (xferResult == ECardResult::READY) - { - x10_state = EState::Ready; - if (x198_fileInfo->CloseFile() == ECardResult::READY) - { - CMemoryCardSys::CommitToDisk(x0_cardPort); - return; - } - NoCardFound(); - return; - } - if (xferResult == ECardResult::BUSY) - return; - if (xferResult == ECardResult::IOERROR) - { - x10_state = EState::FileWriteFailed; - x14_error = EError::CardIOError; - return; - } - NoCardFound(); - } - else - HandleCardError(result, EState::FileWriteFailed); -} - -void CMemoryCardDriver::UpdateFileCreateTransactional(ECardResult result) -{ - if (result == ECardResult::READY) - { - x10_state = EState::FileCreateTransactionalDone; - StartFileWriteTransactional(); - } - else - HandleCardError(result, EState::FileCreateTransactionalFailed); -} - -void CMemoryCardDriver::UpdateFileWriteTransactional(ECardResult result) -{ - if (result == ECardResult::READY) - { - ECardResult xferResult = x198_fileInfo->PumpCardTransfer(); - if (xferResult == ECardResult::READY) - { - x10_state = EState::FileWriteTransactionalDone; - if (x198_fileInfo->CloseFile() != ECardResult::READY) - { - NoCardFound(); - return; - } - StartFileDeleteAltTransactional(); - return; - } - if (xferResult == ECardResult::BUSY) - return; - if (xferResult == ECardResult::IOERROR) - { - x10_state = EState::FileWriteTransactionalFailed; - x14_error = EError::CardIOError; - return; - } - NoCardFound(); - } - else - HandleCardError(result, EState::FileWriteTransactionalFailed); -} - -void CMemoryCardDriver::UpdateFileDeleteAltTransactional(ECardResult result) -{ - if (result == ECardResult::READY) - { - x10_state = EState::FileDeleteAltTransactionalDone; - if (GetCardFreeBytes()) - StartFileRenameBtoA(); - } - else - HandleCardError(result, EState::FileDeleteAltTransactionalFailed); -} - -void CMemoryCardDriver::UpdateFileRenameBtoA(ECardResult result) -{ - if (result == ECardResult::READY) - { - x10_state = EState::DriverClosed; +void CMemoryCardDriver::UpdateFileWrite(ECardResult result) { + if (result == ECardResult::READY) { + ECardResult xferResult = x198_fileInfo->PumpCardTransfer(); + if (xferResult == ECardResult::READY) { + x10_state = EState::Ready; + if (x198_fileInfo->CloseFile() == ECardResult::READY) { CMemoryCardSys::CommitToDisk(x0_cardPort); - WriteBackupBuf(); + return; + } + NoCardFound(); + return; } - else - HandleCardError(result, EState::FileRenameBtoAFailed); -} - -void CMemoryCardDriver::UpdateCardFormat(ECardResult result) -{ - if (result == ECardResult::READY) - x10_state = EState::CardFormatted; - else if (result == ECardResult::BROKEN) - { - x10_state = EState::CardFormatFailed; - x14_error = EError::CardIOError; + if (xferResult == ECardResult::BUSY) + return; + if (xferResult == ECardResult::IOERROR) { + x10_state = EState::FileWriteFailed; + x14_error = EError::CardIOError; + return; } - else - HandleCardError(result, EState::CardFormatFailed); -} - -void CMemoryCardDriver::BuildNewFileSlot(u32 saveIdx) -{ - g_GameState->SetFileIdx(saveIdx); - bool fusionBackup = g_GameState->SystemOptions().GetPlayerFusionSuitActive(); - - std::unique_ptr& slot = xe4_fileSlots[saveIdx]; - if (!slot) - slot = std::make_unique(); - slot->LoadGameState(saveIdx); - - CBitStreamReader r(x30_systemData, 174); - g_GameState->ReadPersistentOptions(r); - ImportPersistentOptions(); - g_GameState->SetCardSerial(x28_cardSerial); - g_GameState->SystemOptions().SetPlayerFusionSuitActive(fusionBackup); -} - -void CMemoryCardDriver::EraseFileSlot(u32 saveIdx) -{ - xe4_fileSlots[saveIdx].reset(); -} - -void CMemoryCardDriver::BuildExistingFileSlot(u32 saveIdx) -{ - g_GameState->SetFileIdx(saveIdx); - - std::unique_ptr& slot = xe4_fileSlots[saveIdx]; - if (!slot) - slot = std::make_unique(); - else - slot->InitializeFromGameState(); - - CBitStreamWriter w(x30_systemData, 174); - g_GameState->PutTo(w); -} - -void CMemoryCardDriver::InitializeFileInfo() -{ - ExportPersistentOptions(); - - OSCalendarTime time = CBasics::ToCalendarTime(std::chrono::system_clock::now()); - char timeString[32]; - snprintf(timeString, 32, "%02d.%02d.%02d %02d:%02d", - time.x10_mon + 1, time.xc_mday, time.x14_year % 100, - time.x8_hour, time.x4_min); - std::string comment("Metroid Prime "); - comment += timeString; - x198_fileInfo->SetComment(comment); - - x198_fileInfo->LockBannerToken(x4_saveBanner, *g_SimplePool); - x198_fileInfo->LockIconToken(x8_saveIcon0, kabufuda::EAnimationSpeed::Middle, *g_SimplePool); - - CMemoryOutStream w = x198_fileInfo->BeginMemoryOut(3004); - - SSaveHeader header; - for (int i=0 ; i<3 ; ++i) - header.x4_savePresent[i] = xe4_fileSlots[i].operator bool(); - header.DoPut(w); - - w.writeBytes(x30_systemData, 174); - - for (int i=0 ; i<3 ; ++i) - if (xe4_fileSlots[i]) - xe4_fileSlots[i]->DoPut(w); -} - -void CMemoryCardDriver::WriteBackupBuf() -{ - g_GameState->WriteBackupBuf(); - g_GameState->SetCardSerial(x28_cardSerial); -} - -bool CMemoryCardDriver::GetCardFreeBytes() -{ - ECardResult result = CMemoryCardSys::GetNumFreeBytes(x0_cardPort, - x18_cardFreeBytes, - x1c_cardFreeFiles); - if (result == ECardResult::READY) - return true; NoCardFound(); - return false; + } else + HandleCardError(result, EState::FileWriteFailed); } -void CMemoryCardDriver::HandleCardError(ECardResult result, EState state) -{ - switch (result) - { - case ECardResult::WRONGDEVICE: - x10_state = state; - x14_error = EError::CardWrongDevice; - break; - case ECardResult::NOCARD: +void CMemoryCardDriver::UpdateFileCreateTransactional(ECardResult result) { + if (result == ECardResult::READY) { + x10_state = EState::FileCreateTransactionalDone; + StartFileWriteTransactional(); + } else + HandleCardError(result, EState::FileCreateTransactionalFailed); +} + +void CMemoryCardDriver::UpdateFileWriteTransactional(ECardResult result) { + if (result == ECardResult::READY) { + ECardResult xferResult = x198_fileInfo->PumpCardTransfer(); + if (xferResult == ECardResult::READY) { + x10_state = EState::FileWriteTransactionalDone; + if (x198_fileInfo->CloseFile() != ECardResult::READY) { NoCardFound(); - break; - case ECardResult::IOERROR: - x10_state = state; - x14_error = EError::CardIOError; - case ECardResult::ENCODING: - x10_state = state; - x14_error = EError::CardWrongCharacterSet; - break; - default: break; - } -} - -void CMemoryCardDriver::Update() -{ - kabufuda::ProbeResults result = CMemoryCardSys::CardProbe(x0_cardPort); - - if (result.x0_error == ECardResult::NOCARD) - { - if (x10_state != EState::NoCard) - NoCardFound(); - static_cast(g_Main)->SetCardBusy(false); return; + } + StartFileDeleteAltTransactional(); + return; } - - if (x10_state == EState::CardProbe) - { - UpdateCardProbe(); - static_cast(g_Main)->SetCardBusy(false); - return; + if (xferResult == ECardResult::BUSY) + return; + if (xferResult == ECardResult::IOERROR) { + x10_state = EState::FileWriteTransactionalFailed; + x14_error = EError::CardIOError; + return; } - - ECardResult resultCode = CMemoryCardSys::GetResultCode(x0_cardPort); - bool cardBusy = false; - - if (IsCardBusy(x10_state)) - { - cardBusy = true; - - switch (x10_state) - { - case EState::CardMount: - UpdateMountCard(resultCode); - break; - case EState::CardCheck: - UpdateCardCheck(resultCode); - break; - case EState::FileDeleteBad: - UpdateFileDeleteBad(resultCode); - break; - case EState::FileRead: - UpdateFileRead(resultCode); - break; - case EState::FileDeleteAlt: - UpdateFileDeleteAlt(resultCode); - break; - case EState::FileCreate: - UpdateFileCreate(resultCode); - break; - case EState::FileWrite: - UpdateFileWrite(resultCode); - break; - case EState::FileCreateTransactional: - UpdateFileCreateTransactional(resultCode); - break; - case EState::FileWriteTransactional: - UpdateFileWriteTransactional(resultCode); - break; - case EState::FileDeleteAltTransactional: - UpdateFileDeleteAltTransactional(resultCode); - break; - case EState::FileRenameBtoA: - UpdateFileRenameBtoA(resultCode); - break; - case EState::CardFormat: - UpdateCardFormat(resultCode); - break; - default: break; - } - } - - static_cast(g_Main)->SetCardBusy(cardBusy); + NoCardFound(); + } else + HandleCardError(result, EState::FileWriteTransactionalFailed); } +void CMemoryCardDriver::UpdateFileDeleteAltTransactional(ECardResult result) { + if (result == ECardResult::READY) { + x10_state = EState::FileDeleteAltTransactionalDone; + if (GetCardFreeBytes()) + StartFileRenameBtoA(); + } else + HandleCardError(result, EState::FileDeleteAltTransactionalFailed); } + +void CMemoryCardDriver::UpdateFileRenameBtoA(ECardResult result) { + if (result == ECardResult::READY) { + x10_state = EState::DriverClosed; + CMemoryCardSys::CommitToDisk(x0_cardPort); + WriteBackupBuf(); + } else + HandleCardError(result, EState::FileRenameBtoAFailed); +} + +void CMemoryCardDriver::UpdateCardFormat(ECardResult result) { + if (result == ECardResult::READY) + x10_state = EState::CardFormatted; + else if (result == ECardResult::BROKEN) { + x10_state = EState::CardFormatFailed; + x14_error = EError::CardIOError; + } else + HandleCardError(result, EState::CardFormatFailed); +} + +void CMemoryCardDriver::BuildNewFileSlot(u32 saveIdx) { + g_GameState->SetFileIdx(saveIdx); + bool fusionBackup = g_GameState->SystemOptions().GetPlayerFusionSuitActive(); + + std::unique_ptr& slot = xe4_fileSlots[saveIdx]; + if (!slot) + slot = std::make_unique(); + slot->LoadGameState(saveIdx); + + CBitStreamReader r(x30_systemData, 174); + g_GameState->ReadPersistentOptions(r); + ImportPersistentOptions(); + g_GameState->SetCardSerial(x28_cardSerial); + g_GameState->SystemOptions().SetPlayerFusionSuitActive(fusionBackup); +} + +void CMemoryCardDriver::EraseFileSlot(u32 saveIdx) { xe4_fileSlots[saveIdx].reset(); } + +void CMemoryCardDriver::BuildExistingFileSlot(u32 saveIdx) { + g_GameState->SetFileIdx(saveIdx); + + std::unique_ptr& slot = xe4_fileSlots[saveIdx]; + if (!slot) + slot = std::make_unique(); + else + slot->InitializeFromGameState(); + + CBitStreamWriter w(x30_systemData, 174); + g_GameState->PutTo(w); +} + +void CMemoryCardDriver::InitializeFileInfo() { + ExportPersistentOptions(); + + OSCalendarTime time = CBasics::ToCalendarTime(std::chrono::system_clock::now()); + char timeString[32]; + snprintf(timeString, 32, "%02d.%02d.%02d %02d:%02d", time.x10_mon + 1, time.xc_mday, time.x14_year % 100, + time.x8_hour, time.x4_min); + std::string comment("Metroid Prime "); + comment += timeString; + x198_fileInfo->SetComment(comment); + + x198_fileInfo->LockBannerToken(x4_saveBanner, *g_SimplePool); + x198_fileInfo->LockIconToken(x8_saveIcon0, kabufuda::EAnimationSpeed::Middle, *g_SimplePool); + + CMemoryOutStream w = x198_fileInfo->BeginMemoryOut(3004); + + SSaveHeader header; + for (int i = 0; i < 3; ++i) + header.x4_savePresent[i] = xe4_fileSlots[i].operator bool(); + header.DoPut(w); + + w.writeBytes(x30_systemData, 174); + + for (int i = 0; i < 3; ++i) + if (xe4_fileSlots[i]) + xe4_fileSlots[i]->DoPut(w); +} + +void CMemoryCardDriver::WriteBackupBuf() { + g_GameState->WriteBackupBuf(); + g_GameState->SetCardSerial(x28_cardSerial); +} + +bool CMemoryCardDriver::GetCardFreeBytes() { + ECardResult result = CMemoryCardSys::GetNumFreeBytes(x0_cardPort, x18_cardFreeBytes, x1c_cardFreeFiles); + if (result == ECardResult::READY) + return true; + NoCardFound(); + return false; +} + +void CMemoryCardDriver::HandleCardError(ECardResult result, EState state) { + switch (result) { + case ECardResult::WRONGDEVICE: + x10_state = state; + x14_error = EError::CardWrongDevice; + break; + case ECardResult::NOCARD: + NoCardFound(); + break; + case ECardResult::IOERROR: + x10_state = state; + x14_error = EError::CardIOError; + case ECardResult::ENCODING: + x10_state = state; + x14_error = EError::CardWrongCharacterSet; + break; + default: + break; + } +} + +void CMemoryCardDriver::Update() { + kabufuda::ProbeResults result = CMemoryCardSys::CardProbe(x0_cardPort); + + if (result.x0_error == ECardResult::NOCARD) { + if (x10_state != EState::NoCard) + NoCardFound(); + static_cast(g_Main)->SetCardBusy(false); + return; + } + + if (x10_state == EState::CardProbe) { + UpdateCardProbe(); + static_cast(g_Main)->SetCardBusy(false); + return; + } + + ECardResult resultCode = CMemoryCardSys::GetResultCode(x0_cardPort); + bool cardBusy = false; + + if (IsCardBusy(x10_state)) { + cardBusy = true; + + switch (x10_state) { + case EState::CardMount: + UpdateMountCard(resultCode); + break; + case EState::CardCheck: + UpdateCardCheck(resultCode); + break; + case EState::FileDeleteBad: + UpdateFileDeleteBad(resultCode); + break; + case EState::FileRead: + UpdateFileRead(resultCode); + break; + case EState::FileDeleteAlt: + UpdateFileDeleteAlt(resultCode); + break; + case EState::FileCreate: + UpdateFileCreate(resultCode); + break; + case EState::FileWrite: + UpdateFileWrite(resultCode); + break; + case EState::FileCreateTransactional: + UpdateFileCreateTransactional(resultCode); + break; + case EState::FileWriteTransactional: + UpdateFileWriteTransactional(resultCode); + break; + case EState::FileDeleteAltTransactional: + UpdateFileDeleteAltTransactional(resultCode); + break; + case EState::FileRenameBtoA: + UpdateFileRenameBtoA(resultCode); + break; + case EState::CardFormat: + UpdateCardFormat(resultCode); + break; + default: + break; + } + } + + static_cast(g_Main)->SetCardBusy(cardBusy); +} + +} // namespace urde::MP1 diff --git a/Runtime/MP1/CMemoryCardDriver.hpp b/Runtime/MP1/CMemoryCardDriver.hpp index f1ad73c20..a88113364 100644 --- a/Runtime/MP1/CMemoryCardDriver.hpp +++ b/Runtime/MP1/CMemoryCardDriver.hpp @@ -3,210 +3,188 @@ #include "CMemoryCardSys.hpp" #include "CGameState.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { + +class CMemoryCardDriver { + friend class CSaveGameScreen; -class CMemoryCardDriver -{ - friend class CSaveGameScreen; public: - enum class EState - { - Initial = 0, - Ready = 1, - NoCard = 2, - DriverClosed = 3, - CardFormatted = 4, - CardProbeDone = 5, - CardMountDone = 6, - CardCheckDone = 7, - FileCreateDone = 8, - FileCreateTransactionalDone = 9, - FileWriteTransactionalDone = 10, - FileDeleteAltTransactionalDone = 11, - CardProbeFailed = 12, - CardMountFailed = 13, - CardCheckFailed = 14, - FileDeleteBadFailed = 15, - FileDeleteAltFailed = 16, - FileBad = 17, - FileCreateFailed = 18, - FileWriteFailed = 19, - FileCreateTransactionalFailed = 20, - FileWriteTransactionalFailed = 21, - FileDeleteAltTransactionalFailed = 22, - FileRenameBtoAFailed = 23, - CardFormatFailed = 24, - CardProbe = 25, - CardMount = 26, - CardCheck = 27, - FileDeleteBad = 28, - FileRead = 29, - FileDeleteAlt = 30, - FileCreate = 31, - FileWrite = 32, - FileCreateTransactional = 33, - FileWriteTransactional = 34, - FileDeleteAltTransactional = 35, - FileRenameBtoA = 36, - CardFormat = 37 - }; + enum class EState { + Initial = 0, + Ready = 1, + NoCard = 2, + DriverClosed = 3, + CardFormatted = 4, + CardProbeDone = 5, + CardMountDone = 6, + CardCheckDone = 7, + FileCreateDone = 8, + FileCreateTransactionalDone = 9, + FileWriteTransactionalDone = 10, + FileDeleteAltTransactionalDone = 11, + CardProbeFailed = 12, + CardMountFailed = 13, + CardCheckFailed = 14, + FileDeleteBadFailed = 15, + FileDeleteAltFailed = 16, + FileBad = 17, + FileCreateFailed = 18, + FileWriteFailed = 19, + FileCreateTransactionalFailed = 20, + FileWriteTransactionalFailed = 21, + FileDeleteAltTransactionalFailed = 22, + FileRenameBtoAFailed = 23, + CardFormatFailed = 24, + CardProbe = 25, + CardMount = 26, + CardCheck = 27, + FileDeleteBad = 28, + FileRead = 29, + FileDeleteAlt = 30, + FileCreate = 31, + FileWrite = 32, + FileCreateTransactional = 33, + FileWriteTransactional = 34, + FileDeleteAltTransactional = 35, + FileRenameBtoA = 36, + CardFormat = 37 + }; - enum class EError - { - OK, - CardBroken, - CardWrongCharacterSet, - CardIOError, - CardWrongDevice, - CardFull, - CardStillFull, /* After attempting alt-delete (if needed) */ - CardNon8KSectors, - FileMissing, - FileCorrupted - }; + enum class EError { + OK, + CardBroken, + CardWrongCharacterSet, + CardIOError, + CardWrongDevice, + CardFull, + CardStillFull, /* After attempting alt-delete (if needed) */ + CardNon8KSectors, + FileMissing, + FileCorrupted + }; private: + struct SFileInfo { + CMemoryCardSys::CardFileHandle x0_fileInfo; - struct SFileInfo - { - CMemoryCardSys::CardFileHandle x0_fileInfo; + std::string x14_name; + std::vector x24_saveFileData; + std::vector x34_saveData; + SFileInfo(kabufuda::ECardSlot cardPort, std::string_view name); + kabufuda::ECardResult Open(); + kabufuda::ECardResult Close(); + kabufuda::ECardSlot GetFileCardPort() const { return x0_fileInfo.slot; } + int GetFileNo() const { return x0_fileInfo.getFileNo(); } + kabufuda::ECardResult StartRead(); + kabufuda::ECardResult TryFileRead(); + kabufuda::ECardResult FileRead(); + kabufuda::ECardResult GetSaveDataOffset(u32& offOut); + }; - std::string x14_name; - std::vector x24_saveFileData; - std::vector x34_saveData; - SFileInfo(kabufuda::ECardSlot cardPort, std::string_view name); - kabufuda::ECardResult Open(); - kabufuda::ECardResult Close(); - kabufuda::ECardSlot GetFileCardPort() const { return x0_fileInfo.slot; } - int GetFileNo() const { return x0_fileInfo.getFileNo(); } - kabufuda::ECardResult StartRead(); - kabufuda::ECardResult TryFileRead(); - kabufuda::ECardResult FileRead(); - kabufuda::ECardResult GetSaveDataOffset(u32& offOut); - }; + struct SSaveHeader { + u32 x0_version = 0; + bool x4_savePresent[3]; + void DoPut(CMemoryOutStream& out) const { + out.writeUint32Big(x0_version); + for (int i = 0; i < 3; ++i) + out.writeBool(x4_savePresent[i]); + } + }; - struct SSaveHeader - { - u32 x0_version = 0; - bool x4_savePresent[3]; - void DoPut(CMemoryOutStream& out) const - { - out.writeUint32Big(x0_version); - for (int i=0 ; i<3 ; ++i) - out.writeBool(x4_savePresent[i]); - } - }; + struct SGameFileSlot { + u8 x0_saveBuffer[940] = {}; + CGameState::GameFileStateInfo x944_fileInfo; + SGameFileSlot(); + SGameFileSlot(CMemoryInStream& in); + void InitializeFromGameState(); + void LoadGameState(u32 idx); + void DoPut(CMemoryOutStream& w) const { w.writeBytes(x0_saveBuffer, 940); } + }; - struct SGameFileSlot - { - u8 x0_saveBuffer[940] = {}; - CGameState::GameFileStateInfo x944_fileInfo; - SGameFileSlot(); - SGameFileSlot(CMemoryInStream& in); - void InitializeFromGameState(); - void LoadGameState(u32 idx); - void DoPut(CMemoryOutStream& w) const - { - w.writeBytes(x0_saveBuffer, 940); - } - }; + enum class EFileState { Unknown, NoFile, File, BadFile }; - enum class EFileState - { - Unknown, - NoFile, - File, - BadFile - }; - - kabufuda::ECardSlot x0_cardPort; - CAssetId x4_saveBanner; - CAssetId x8_saveIcon0; - CAssetId xc_saveIcon1; - EState x10_state = EState::Initial; - EError x14_error = EError::OK; - s32 x18_cardFreeBytes = 0; - s32 x1c_cardFreeFiles = 0; - u32 x20_fileTime = 0; - u64 x28_cardSerial = 0; - u8 x30_systemData[174] = {}; - std::unique_ptr xe4_fileSlots[3]; - std::vector> x100_mcFileInfos; - u32 x194_fileIdx = -1; - std::unique_ptr x198_fileInfo; - bool x19c_ = false; - bool x19d_importPersistent; + kabufuda::ECardSlot x0_cardPort; + CAssetId x4_saveBanner; + CAssetId x8_saveIcon0; + CAssetId xc_saveIcon1; + EState x10_state = EState::Initial; + EError x14_error = EError::OK; + s32 x18_cardFreeBytes = 0; + s32 x1c_cardFreeFiles = 0; + u32 x20_fileTime = 0; + u64 x28_cardSerial = 0; + u8 x30_systemData[174] = {}; + std::unique_ptr xe4_fileSlots[3]; + std::vector> x100_mcFileInfos; + u32 x194_fileIdx = -1; + std::unique_ptr x198_fileInfo; + bool x19c_ = false; + bool x19d_importPersistent; public: - CMemoryCardDriver(kabufuda::ECardSlot cardPort, CAssetId saveBanner, - CAssetId saveIcon0, CAssetId saveIcon1, bool importPersistent); + CMemoryCardDriver(kabufuda::ECardSlot cardPort, CAssetId saveBanner, CAssetId saveIcon0, CAssetId saveIcon1, + bool importPersistent); - void NoCardFound(); - const CGameState::GameFileStateInfo* GetGameFileStateInfo(int idx); - static SSaveHeader LoadSaveHeader(CMemoryInStream& in); - static std::unique_ptr LoadSaveFile(CMemoryInStream& in); - void ReadFinished(); - void ImportPersistentOptions(); - void ExportPersistentOptions(); - void CheckCardCapacity(); - void IndexFiles(); + void NoCardFound(); + const CGameState::GameFileStateInfo* GetGameFileStateInfo(int idx); + static SSaveHeader LoadSaveHeader(CMemoryInStream& in); + static std::unique_ptr LoadSaveFile(CMemoryInStream& in); + void ReadFinished(); + void ImportPersistentOptions(); + void ExportPersistentOptions(); + void CheckCardCapacity(); + void IndexFiles(); - void StartCardProbe(); // 25 - void StartMountCard(); // 26 - void StartCardCheck(); // 27 - void StartFileDeleteBad(); // 28 - void StartFileRead(); // 29 - void StartFileDeleteAlt(); // 30 - void StartFileCreate(); // 31 - void StartFileWrite(); // 32 - void StartFileCreateTransactional(); // 33 - void StartFileWriteTransactional(); // 34 - void StartFileDeleteAltTransactional(); // 35 - void StartFileRenameBtoA(); // 36 - void StartCardFormat(); // 37 + void StartCardProbe(); // 25 + void StartMountCard(); // 26 + void StartCardCheck(); // 27 + void StartFileDeleteBad(); // 28 + void StartFileRead(); // 29 + void StartFileDeleteAlt(); // 30 + void StartFileCreate(); // 31 + void StartFileWrite(); // 32 + void StartFileCreateTransactional(); // 33 + void StartFileWriteTransactional(); // 34 + void StartFileDeleteAltTransactional(); // 35 + void StartFileRenameBtoA(); // 36 + void StartCardFormat(); // 37 - void UpdateCardProbe(); // 25 - void UpdateMountCard(kabufuda::ECardResult result); // 26 - void UpdateCardCheck(kabufuda::ECardResult result); // 27 - void UpdateFileDeleteBad(kabufuda::ECardResult result); // 28 - void UpdateFileRead(kabufuda::ECardResult result); // 29 - void UpdateFileDeleteAlt(kabufuda::ECardResult result); // 30 - void UpdateFileCreate(kabufuda::ECardResult result); // 31 - void UpdateFileWrite(kabufuda::ECardResult result); // 32 - void UpdateFileCreateTransactional(kabufuda::ECardResult result); // 33 - void UpdateFileWriteTransactional(kabufuda::ECardResult result); // 34 - void UpdateFileDeleteAltTransactional(kabufuda::ECardResult result); // 35 - void UpdateFileRenameBtoA(kabufuda::ECardResult result); // 36 - void UpdateCardFormat(kabufuda::ECardResult result); // 37 + void UpdateCardProbe(); // 25 + void UpdateMountCard(kabufuda::ECardResult result); // 26 + void UpdateCardCheck(kabufuda::ECardResult result); // 27 + void UpdateFileDeleteBad(kabufuda::ECardResult result); // 28 + void UpdateFileRead(kabufuda::ECardResult result); // 29 + void UpdateFileDeleteAlt(kabufuda::ECardResult result); // 30 + void UpdateFileCreate(kabufuda::ECardResult result); // 31 + void UpdateFileWrite(kabufuda::ECardResult result); // 32 + void UpdateFileCreateTransactional(kabufuda::ECardResult result); // 33 + void UpdateFileWriteTransactional(kabufuda::ECardResult result); // 34 + void UpdateFileDeleteAltTransactional(kabufuda::ECardResult result); // 35 + void UpdateFileRenameBtoA(kabufuda::ECardResult result); // 36 + void UpdateCardFormat(kabufuda::ECardResult result); // 37 - void ClearFileInfo() { x198_fileInfo.reset(); } - void BuildNewFileSlot(u32 saveIdx); - void EraseFileSlot(u32 saveIdx); - void BuildExistingFileSlot(u32 saveIdx); - void InitializeFileInfo(); - void WriteBackupBuf(); - bool GetCardFreeBytes(); - void HandleCardError(kabufuda::ECardResult result, EState state); - void Update(); - void ClearError() { x14_error = EError::OK; } + void ClearFileInfo() { x198_fileInfo.reset(); } + void BuildNewFileSlot(u32 saveIdx); + void EraseFileSlot(u32 saveIdx); + void BuildExistingFileSlot(u32 saveIdx); + void InitializeFileInfo(); + void WriteBackupBuf(); + bool GetCardFreeBytes(); + void HandleCardError(kabufuda::ECardResult result, EState state); + void Update(); + void ClearError() { x14_error = EError::OK; } - static bool IsCardBusy(EState v) - { - return v >= EState::CardMount && v <= EState::CardFormat; - } + static bool IsCardBusy(EState v) { return v >= EState::CardMount && v <= EState::CardFormat; } - static bool IsCardWriting(EState v) - { - if (v < EState::CardProbe) - return false; - if (v == EState::CardCheck) - return false; - if (v == EState::FileRead) - return false; - return true; - } + static bool IsCardWriting(EState v) { + if (v < EState::CardProbe) + return false; + if (v == EState::CardCheck) + return false; + if (v == EState::FileRead) + return false; + return true; + } }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CMessageScreen.cpp b/Runtime/MP1/CMessageScreen.cpp index defebc938..8d4f56b8c 100644 --- a/Runtime/MP1/CMessageScreen.cpp +++ b/Runtime/MP1/CMessageScreen.cpp @@ -8,137 +8,124 @@ #include "Audio/CSfxManager.hpp" #include "GuiSys/CGuiWidgetDrawParms.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CMessageScreen::CMessageScreen(CAssetId msg, float delayTime) -: x74_delayTime(delayTime) -{ - x78_24_exit = false; - x0_msg = g_SimplePool->GetObj({FOURCC('STRG'), msg}); - xc_msgScreen = g_SimplePool->GetObj("FRME_MsgScreen"); +CMessageScreen::CMessageScreen(CAssetId msg, float delayTime) : x74_delayTime(delayTime) { + x78_24_exit = false; + x0_msg = g_SimplePool->GetObj({FOURCC('STRG'), msg}); + xc_msgScreen = g_SimplePool->GetObj("FRME_MsgScreen"); } -void CMessageScreen::ProcessControllerInput(const CFinalInput& input) -{ - if (!x18_loadedMsgScreen || x74_delayTime > 0.f || !input.PA()) - return; +void CMessageScreen::ProcessControllerInput(const CFinalInput& input) { + if (!x18_loadedMsgScreen || x74_delayTime > 0.f || !input.PA()) + return; - if (x1c_textpane_message->TextSupport().GetCurTime() < - x1c_textpane_message->TextSupport().GetTotalAnimationTime()) - { - x1c_textpane_message->TextSupport().SetCurTime( - x1c_textpane_message->TextSupport().GetTotalAnimationTime()); - return; + if (x1c_textpane_message->TextSupport().GetCurTime() < x1c_textpane_message->TextSupport().GetTotalAnimationTime()) { + x1c_textpane_message->TextSupport().SetCurTime(x1c_textpane_message->TextSupport().GetTotalAnimationTime()); + return; + } + + x6c_page += 1; + + if (x6c_page >= x0_msg->GetStringCount()) { + x78_24_exit = true; + return; + } + + x1c_textpane_message->TextSupport().SetTypeWriteEffectOptions(false, 0.1f, 30.f); + x1c_textpane_message->TextSupport().SetText(x0_msg->GetString(x6c_page)); + + CSfxManager::SfxStart(SFXui_message_screen_key, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + + x74_delayTime = 0.8f; +} + +bool CMessageScreen::Update(float dt, float blurAmt) { + x70_blurAmt = blurAmt; + if (!x18_loadedMsgScreen && xc_msgScreen.IsLoaded() && x0_msg.IsLoaded()) { + x18_loadedMsgScreen = xc_msgScreen.GetObj(); + x1c_textpane_message = static_cast(x18_loadedMsgScreen->FindWidget("textpane_message")); + x20_basewidget_top = x18_loadedMsgScreen->FindWidget("basewidget_top"); + x24_basewidget_center = x18_loadedMsgScreen->FindWidget("basewidget_center"); + x28_basewidget_bottom = x18_loadedMsgScreen->FindWidget("basewidget_bottom"); + x2c_model_abutton = static_cast(x18_loadedMsgScreen->FindWidget("model_abutton")); + x30_model_top = static_cast(x18_loadedMsgScreen->FindWidget("model_top")); + x38_model_bottom = static_cast(x18_loadedMsgScreen->FindWidget("model_bottom")); + x34_model_center = static_cast(x18_loadedMsgScreen->FindWidget("model_center")); + x3c_model_bg = static_cast(x18_loadedMsgScreen->FindWidget("model_bg")); + x40_model_videoband = static_cast(x18_loadedMsgScreen->FindWidget("model_videoband")); + x44_topPos = x20_basewidget_top->GetLocalPosition(); + x50_bottomPos = x28_basewidget_bottom->GetLocalPosition(); + x5c_videoBandPos = x40_model_videoband->GetLocalPosition(); + + if (CGuiWidget* w = x18_loadedMsgScreen->FindWidget("basewidget_top")) + w->SetColor(g_tweakGuiColors->GetHudFrameColor()); + if (CGuiWidget* w = x18_loadedMsgScreen->FindWidget("basewidget_centerdeco")) + w->SetColor(g_tweakGuiColors->GetHudFrameColor()); + if (CGuiWidget* w = x18_loadedMsgScreen->FindWidget("model_bottom")) + w->SetColor(g_tweakGuiColors->GetHudFrameColor()); + + x40_model_videoband->SetDepthGreater(true); + x30_model_top->SetDepthWrite(true); + x38_model_bottom->SetDepthWrite(true); + x34_model_center->SetDepthWrite(true); + x3c_model_bg->SetDepthWrite(true); + + if (x0_msg->GetStringCount()) { + x1c_textpane_message->TextSupport().SetTypeWriteEffectOptions(false, 0.1f, 30.f); + x1c_textpane_message->TextSupport().SetText(x0_msg->GetString(0)); + x1c_textpane_message->TextSupport().SetFontColor(g_tweakGuiColors->GetHudMessageFill()); + x1c_textpane_message->TextSupport().SetControlTXTRMap(&g_GameState->GameOptions().GetControlTXTRMap()); } + } - x6c_page += 1; + if (x18_loadedMsgScreen) { + if (x74_delayTime > 0.f) + x74_delayTime -= dt; - if (x6c_page >= x0_msg->GetStringCount()) - { - x78_24_exit = true; - return; - } + float xT = std::max(0.f, (x70_blurAmt - 0.5f) / 0.5f); + float scaleX; + if (xT < 0.7f) + scaleX = xT / 0.7f; + else if (xT < 0.85f) + scaleX = 0.1f * (1.f - (xT - 0.7f) / 0.15f) + 0.9f; + else + scaleX = 0.1f * ((xT - 0.7f - 0.15f) / 0.3f) + 0.9f; - x1c_textpane_message->TextSupport().SetTypeWriteEffectOptions(false, 0.1f, 30.f); - x1c_textpane_message->TextSupport().SetText(x0_msg->GetString(x6c_page)); + x24_basewidget_center->SetLocalTransform(zeus::CTransform::Scale(scaleX, 1.f, 1.f)); + x20_basewidget_top->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, 12.f * (1.f - xT))); + x28_basewidget_bottom->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, -12.f * (1.f - xT))); - CSfxManager::SfxStart(SFXui_message_screen_key, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + float alpha = std::max(0.f, (x70_blurAmt - 0.7f) / 0.3f); + zeus::CColor color = g_tweakGuiColors->GetHudFrameColor(); + color.a() *= alpha; + x20_basewidget_top->SetColor(color); + x28_basewidget_bottom->SetColor(zeus::CColor(1.f, alpha)); - x74_delayTime = 0.8f; + float pulse = 0.f; + if (x74_delayTime <= 0.f) + pulse = zeus::clamp(0.f, 0.5f * (1.f + std::sin(5.f * CGraphics::GetSecondsMod900() - M_PIF / 2.f)), 1.f); + x2c_model_abutton->SetColor(zeus::CColor(1.f, pulse)); + + x68_videoBandOffset += 12.f * dt; + if (x68_videoBandOffset > 10.f) + x68_videoBandOffset -= 20.f; + + x40_model_videoband->SetColor(zeus::CColor(1.f, 0.04f * (rand() / float(RAND_MAX)) + 0.08f)); + x40_model_videoband->SetLocalTransform( + zeus::CTransform::Translate(x5c_videoBandPos + zeus::CVector3f(0.f, 0.f, x68_videoBandOffset))); + + x18_loadedMsgScreen->Update(dt); + } + + return !x78_24_exit; } -bool CMessageScreen::Update(float dt, float blurAmt) -{ - x70_blurAmt = blurAmt; - if (!x18_loadedMsgScreen && xc_msgScreen.IsLoaded() && x0_msg.IsLoaded()) - { - x18_loadedMsgScreen = xc_msgScreen.GetObj(); - x1c_textpane_message = static_cast(x18_loadedMsgScreen->FindWidget("textpane_message")); - x20_basewidget_top = x18_loadedMsgScreen->FindWidget("basewidget_top"); - x24_basewidget_center = x18_loadedMsgScreen->FindWidget("basewidget_center"); - x28_basewidget_bottom = x18_loadedMsgScreen->FindWidget("basewidget_bottom"); - x2c_model_abutton = static_cast(x18_loadedMsgScreen->FindWidget("model_abutton")); - x30_model_top = static_cast(x18_loadedMsgScreen->FindWidget("model_top")); - x38_model_bottom = static_cast(x18_loadedMsgScreen->FindWidget("model_bottom")); - x34_model_center = static_cast(x18_loadedMsgScreen->FindWidget("model_center")); - x3c_model_bg = static_cast(x18_loadedMsgScreen->FindWidget("model_bg")); - x40_model_videoband = static_cast(x18_loadedMsgScreen->FindWidget("model_videoband")); - x44_topPos = x20_basewidget_top->GetLocalPosition(); - x50_bottomPos = x28_basewidget_bottom->GetLocalPosition(); - x5c_videoBandPos = x40_model_videoband->GetLocalPosition(); +void CMessageScreen::Draw() const { + if (!x18_loadedMsgScreen) + return; - if (CGuiWidget* w = x18_loadedMsgScreen->FindWidget("basewidget_top")) - w->SetColor(g_tweakGuiColors->GetHudFrameColor()); - if (CGuiWidget* w = x18_loadedMsgScreen->FindWidget("basewidget_centerdeco")) - w->SetColor(g_tweakGuiColors->GetHudFrameColor()); - if (CGuiWidget* w = x18_loadedMsgScreen->FindWidget("model_bottom")) - w->SetColor(g_tweakGuiColors->GetHudFrameColor()); - - x40_model_videoband->SetDepthGreater(true); - x30_model_top->SetDepthWrite(true); - x38_model_bottom->SetDepthWrite(true); - x34_model_center->SetDepthWrite(true); - x3c_model_bg->SetDepthWrite(true); - - if (x0_msg->GetStringCount()) - { - x1c_textpane_message->TextSupport().SetTypeWriteEffectOptions(false, 0.1f, 30.f); - x1c_textpane_message->TextSupport().SetText(x0_msg->GetString(0)); - x1c_textpane_message->TextSupport().SetFontColor(g_tweakGuiColors->GetHudMessageFill()); - x1c_textpane_message->TextSupport().SetControlTXTRMap(&g_GameState->GameOptions().GetControlTXTRMap()); - } - } - - if (x18_loadedMsgScreen) - { - if (x74_delayTime > 0.f) - x74_delayTime -= dt; - - float xT = std::max(0.f, (x70_blurAmt - 0.5f) / 0.5f); - float scaleX; - if (xT < 0.7f) - scaleX = xT / 0.7f; - else if (xT < 0.85f) - scaleX = 0.1f * (1.f - (xT - 0.7f) / 0.15f) + 0.9f; - else - scaleX = 0.1f * ((xT - 0.7f - 0.15f) / 0.3f) + 0.9f; - - x24_basewidget_center->SetLocalTransform(zeus::CTransform::Scale(scaleX, 1.f, 1.f)); - x20_basewidget_top->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, 12.f * (1.f - xT))); - x28_basewidget_bottom->SetLocalTransform(zeus::CTransform::Translate(0.f, 0.f, -12.f * (1.f - xT))); - - float alpha = std::max(0.f, (x70_blurAmt - 0.7f) / 0.3f); - zeus::CColor color = g_tweakGuiColors->GetHudFrameColor(); - color.a() *= alpha; - x20_basewidget_top->SetColor(color); - x28_basewidget_bottom->SetColor(zeus::CColor(1.f, alpha)); - - float pulse = 0.f; - if (x74_delayTime <= 0.f) - pulse = zeus::clamp(0.f, 0.5f * (1.f + std::sin(5.f * CGraphics::GetSecondsMod900() - M_PIF / 2.f)), 1.f); - x2c_model_abutton->SetColor(zeus::CColor(1.f, pulse)); - - x68_videoBandOffset += 12.f * dt; - if (x68_videoBandOffset > 10.f) - x68_videoBandOffset -= 20.f; - - x40_model_videoband->SetColor(zeus::CColor(1.f, 0.04f * (rand() / float(RAND_MAX)) + 0.08f)); - x40_model_videoband->SetLocalTransform( - zeus::CTransform::Translate(x5c_videoBandPos + zeus::CVector3f(0.f, 0.f, x68_videoBandOffset))); - - x18_loadedMsgScreen->Update(dt); - } - - return !x78_24_exit; + x18_loadedMsgScreen->Draw(CGuiWidgetDrawParms(x70_blurAmt, zeus::CVector3f::skZero)); } -void CMessageScreen::Draw() const -{ - if (!x18_loadedMsgScreen) - return; - - x18_loadedMsgScreen->Draw(CGuiWidgetDrawParms(x70_blurAmt, zeus::CVector3f::skZero)); -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CMessageScreen.hpp b/Runtime/MP1/CMessageScreen.hpp index e5ac19764..0ca683ea4 100644 --- a/Runtime/MP1/CMessageScreen.hpp +++ b/Runtime/MP1/CMessageScreen.hpp @@ -5,46 +5,43 @@ #include "GuiSys/CStringTable.hpp" #include "GuiSys/CGuiFrame.hpp" -namespace urde -{ +namespace urde { struct CFinalInput; class CGuiWidget; class CGuiTextPane; class CGuiModel; -namespace MP1 -{ +namespace MP1 { + +class CMessageScreen { + TLockedToken x0_msg; + TLockedToken xc_msgScreen; + CGuiFrame* x18_loadedMsgScreen = nullptr; + CGuiTextPane* x1c_textpane_message = nullptr; + CGuiWidget* x20_basewidget_top = nullptr; + CGuiWidget* x24_basewidget_center = nullptr; + CGuiWidget* x28_basewidget_bottom = nullptr; + CGuiModel* x2c_model_abutton = nullptr; + CGuiModel* x30_model_top = nullptr; + CGuiModel* x34_model_center = nullptr; + CGuiModel* x38_model_bottom = nullptr; + CGuiModel* x3c_model_bg = nullptr; + CGuiModel* x40_model_videoband = nullptr; + zeus::CVector3f x44_topPos; + zeus::CVector3f x50_bottomPos; + zeus::CVector3f x5c_videoBandPos; + float x68_videoBandOffset = 10.f; + u32 x6c_page = 0; + float x70_blurAmt = 0.f; + float x74_delayTime; + bool x78_24_exit : 1; -class CMessageScreen -{ - TLockedToken x0_msg; - TLockedToken xc_msgScreen; - CGuiFrame* x18_loadedMsgScreen = nullptr; - CGuiTextPane* x1c_textpane_message = nullptr; - CGuiWidget* x20_basewidget_top = nullptr; - CGuiWidget* x24_basewidget_center = nullptr; - CGuiWidget* x28_basewidget_bottom = nullptr; - CGuiModel* x2c_model_abutton = nullptr; - CGuiModel* x30_model_top = nullptr; - CGuiModel* x34_model_center = nullptr; - CGuiModel* x38_model_bottom = nullptr; - CGuiModel* x3c_model_bg = nullptr; - CGuiModel* x40_model_videoband = nullptr; - zeus::CVector3f x44_topPos; - zeus::CVector3f x50_bottomPos; - zeus::CVector3f x5c_videoBandPos; - float x68_videoBandOffset = 10.f; - u32 x6c_page = 0; - float x70_blurAmt = 0.f; - float x74_delayTime; - bool x78_24_exit : 1; public: - CMessageScreen(CAssetId msg, float time); - void ProcessControllerInput(const CFinalInput& input); - bool Update(float dt, float blurAmt); - void Draw() const; + CMessageScreen(CAssetId msg, float time); + void ProcessControllerInput(const CFinalInput& input); + bool Update(float dt, float blurAmt); + void Draw() const; }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/COptionsScreen.cpp b/Runtime/MP1/COptionsScreen.cpp index e1ecc582a..2644ee6e3 100644 --- a/Runtime/MP1/COptionsScreen.cpp +++ b/Runtime/MP1/COptionsScreen.cpp @@ -5,280 +5,230 @@ #include "Input/RumbleFxTable.hpp" #include "CArchitectureQueue.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -COptionsScreen::COptionsScreen(const CStateManager& mgr, CGuiFrame& frame, - const CStringTable& pauseStrg) -: CPauseScreenBase(mgr, frame, pauseStrg) -{ - x1a0_gameCube = std::make_unique(); - x2a0_24_inOptionBody = false; +COptionsScreen::COptionsScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg) +: CPauseScreenBase(mgr, frame, pauseStrg) { + x1a0_gameCube = std::make_unique(); + x2a0_24_inOptionBody = false; } -COptionsScreen::~COptionsScreen() -{ - CSfxManager::SfxStop(x1a4_sliderSfx); +COptionsScreen::~COptionsScreen() { CSfxManager::SfxStop(x1a4_sliderSfx); } + +void COptionsScreen::UpdateOptionView() { + ResetOptionWidgetVisibility(); + + const std::pair& category = GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()]; + if (category.first == 0) + return; + + float zOff = x38_highlightPitch * x1c_rightSel; + const SGameOption& opt = category.second[x1c_rightSel]; + switch (opt.type) { + case EOptionType::Float: + x18c_slidergroup_slider->SetIsActive(true); + x18c_slidergroup_slider->SetVisibility(true, ETraversalMode::Children); + x18c_slidergroup_slider->SetMinVal(opt.minVal); + x18c_slidergroup_slider->SetMaxVal(opt.maxVal); + x18c_slidergroup_slider->SetIncrement(opt.increment); + x18c_slidergroup_slider->SetCurVal(CGameOptions::GetOption(opt.option)); + x18c_slidergroup_slider->SetLocalPosition(x3c_sliderStart + zeus::CVector3f(0.f, 0.f, zOff)); + break; + case EOptionType::DoubleEnum: + x190_tablegroup_double->SetUserSelection(CGameOptions::GetOption(opt.option)); + x190_tablegroup_double->SetIsVisible(true); + x190_tablegroup_double->SetIsActive(true); + UpdateSideTable(x190_tablegroup_double); + x190_tablegroup_double->SetLocalPosition(x48_tableDoubleStart + zeus::CVector3f(0.f, 0.f, zOff)); + break; + case EOptionType::TripleEnum: + x194_tablegroup_triple->SetUserSelection(CGameOptions::GetOption(opt.option)); + x194_tablegroup_triple->SetIsVisible(true); + x194_tablegroup_triple->SetIsActive(true); + UpdateSideTable(x194_tablegroup_triple); + x194_tablegroup_triple->SetLocalPosition(x54_tableTripleStart + zeus::CVector3f(0.f, 0.f, zOff)); + break; + default: + break; + } } -void COptionsScreen::UpdateOptionView() -{ +void COptionsScreen::ResetOptionWidgetVisibility() { + x18c_slidergroup_slider->SetIsActive(false); + x18c_slidergroup_slider->SetVisibility(false, ETraversalMode::Children); + x190_tablegroup_double->SetIsVisible(false); + x190_tablegroup_double->SetIsActive(false); + x194_tablegroup_triple->SetIsActive(false); + x194_tablegroup_triple->SetIsVisible(false); +} + +void COptionsScreen::OnSliderChanged(CGuiSliderGroup* caller, float val) { + if (x10_mode != EMode::RightTable) + return; + + EGameOption opt = GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()].second[x1c_rightSel].option; + CGameOptions::SetOption(opt, caller->GetGurVal()); +} + +void COptionsScreen::OnEnumChanged(CGuiTableGroup* caller, int oldSel) { + if (x10_mode != EMode::RightTable) + return; + + EGameOption opt = GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()].second[x1c_rightSel].option; + CGameOptions::SetOption(opt, caller->GetUserSelection()); + + if (opt == EGameOption::Rumble && caller->GetUserSelection() > 0) { + x1a8_rumble.HardStopAll(); + x1a8_rumble.Rumble(RumbleFxTable[int(ERumbleFxId::PlayerBump)], 1.f, ERumblePriority::One, EIOPort::Zero); + } + + CPauseScreenBase::UpdateSideTable(caller); + CSfxManager::SfxStart(SFXui_option_enum_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); +} + +bool COptionsScreen::InputDisabled() const { return x19c_quitGame.operator bool(); } + +void COptionsScreen::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) { + x1a8_rumble.Update(dt); + CPauseScreenBase::Update(dt, rand, archQueue); + + if (x1a4_sliderSfx.operator bool() != (x18c_slidergroup_slider->GetState() != CGuiSliderGroup::EState::None)) { + if (x18c_slidergroup_slider->GetState() != CGuiSliderGroup::EState::None) { + x1a4_sliderSfx = + CSfxManager::SfxStart(SFXui_options_slider_change_lp, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else { + CSfxManager::SfxStop(x1a4_sliderSfx); + x1a4_sliderSfx.reset(); + } + } + + if (x2a0_24_inOptionBody) + x29c_optionAlpha = std::min(x29c_optionAlpha + 4.f * dt, 1.f); + else + x29c_optionAlpha = std::max(x29c_optionAlpha - 4.f * dt, 0.f); + + if (std::fabs(x29c_optionAlpha) < 0.00001f) { ResetOptionWidgetVisibility(); + x174_textpane_body->SetIsVisible(false); + } - const std::pair& category = - GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()]; - if (category.first == 0) - return; + zeus::CColor color = g_tweakGuiColors->GetPauseItemAmberColor(); + color.a() = x29c_optionAlpha; + x18c_slidergroup_slider->SetColor(color); + x190_tablegroup_double->SetColor(color); + x194_tablegroup_triple->SetColor(color); - float zOff = x38_highlightPitch * x1c_rightSel; - const SGameOption& opt = category.second[x1c_rightSel]; - switch (opt.type) - { - case EOptionType::Float: - x18c_slidergroup_slider->SetIsActive(true); - x18c_slidergroup_slider->SetVisibility(true, ETraversalMode::Children); - x18c_slidergroup_slider->SetMinVal(opt.minVal); - x18c_slidergroup_slider->SetMaxVal(opt.maxVal); - x18c_slidergroup_slider->SetIncrement(opt.increment); - x18c_slidergroup_slider->SetCurVal(CGameOptions::GetOption(opt.option)); - x18c_slidergroup_slider->SetLocalPosition(x3c_sliderStart + zeus::CVector3f(0.f, 0.f, zOff)); - break; - case EOptionType::DoubleEnum: - x190_tablegroup_double->SetUserSelection(CGameOptions::GetOption(opt.option)); - x190_tablegroup_double->SetIsVisible(true); - x190_tablegroup_double->SetIsActive(true); - UpdateSideTable(x190_tablegroup_double); - x190_tablegroup_double->SetLocalPosition(x48_tableDoubleStart + zeus::CVector3f(0.f, 0.f, zOff)); - break; - case EOptionType::TripleEnum: - x194_tablegroup_triple->SetUserSelection(CGameOptions::GetOption(opt.option)); - x194_tablegroup_triple->SetIsVisible(true); - x194_tablegroup_triple->SetIsActive(true); - UpdateSideTable(x194_tablegroup_triple); - x194_tablegroup_triple->SetLocalPosition(x54_tableTripleStart + zeus::CVector3f(0.f, 0.f, zOff)); - break; - default: break; + if (x19c_quitGame) { + EQuitAction action = x19c_quitGame->Update(dt); + if (action == EQuitAction::Yes) { + archQueue.Push(MakeMsg::CreateQuitGameplay(EArchMsgTarget::Game)); + CSfxManager::SetChannel(CSfxManager::ESfxChannels::Default); + CSfxManager::SfxStart(SFXui_options_quit_accept, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else if (action == EQuitAction::No) { + CSfxManager::SfxStart(SFXui_options_quit_reject, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x19c_quitGame.reset(); } + } + + x1a0_gameCube->Update(dt); } -void COptionsScreen::ResetOptionWidgetVisibility() -{ - x18c_slidergroup_slider->SetIsActive(false); - x18c_slidergroup_slider->SetVisibility(false, ETraversalMode::Children); - x190_tablegroup_double->SetIsVisible(false); - x190_tablegroup_double->SetIsActive(false); - x194_tablegroup_triple->SetIsActive(false); - x194_tablegroup_triple->SetIsVisible(false); +void COptionsScreen::Touch() { + CPauseScreenBase::Touch(); + x1a0_gameCube->Touch(); } -void COptionsScreen::OnSliderChanged(CGuiSliderGroup* caller, float val) -{ - if (x10_mode != EMode::RightTable) - return; - - EGameOption opt = GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()].second[x1c_rightSel].option; - CGameOptions::SetOption(opt, caller->GetGurVal()); +void COptionsScreen::ProcessControllerInput(const CFinalInput& input) { + if (!x19c_quitGame) { + CPauseScreenBase::ProcessControllerInput(input); + CGameOptions::TryRestoreDefaults(input, x70_tablegroup_leftlog->GetUserSelection(), x1c_rightSel, false, false); + if (x70_tablegroup_leftlog->GetUserSelection() == 4 && input.PA()) + x19c_quitGame = std::make_unique(EQuitType::QuitGame); + } else { + x19c_quitGame->ProcessUserInput(input); + } } -void COptionsScreen::OnEnumChanged(CGuiTableGroup* caller, int oldSel) -{ - if (x10_mode != EMode::RightTable) - return; - - EGameOption opt = GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()].second[x1c_rightSel].option; - CGameOptions::SetOption(opt, caller->GetUserSelection()); - - if (opt == EGameOption::Rumble && caller->GetUserSelection() > 0) - { - x1a8_rumble.HardStopAll(); - x1a8_rumble.Rumble(RumbleFxTable[int(ERumbleFxId::PlayerBump)], 1.f, ERumblePriority::One, EIOPort::Zero); - } - - CPauseScreenBase::UpdateSideTable(caller); - CSfxManager::SfxStart(SFXui_option_enum_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); +void COptionsScreen::Draw(float transInterp, float totalAlpha, float yOff) { + CPauseScreenBase::Draw(transInterp, totalAlpha, yOff); + x1a0_gameCube->Draw(transInterp * (1.f - x29c_optionAlpha)); + if (x19c_quitGame) { + CGraphics::SetDepthRange(DEPTH_NEAR, 0.001f); + x19c_quitGame->Draw(); + CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR); + } } -bool COptionsScreen::InputDisabled() const -{ - return x19c_quitGame.operator bool(); -} +bool COptionsScreen::VReady() const { return true; } -void COptionsScreen::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) -{ - x1a8_rumble.Update(dt); - CPauseScreenBase::Update(dt, rand, archQueue); +void COptionsScreen::VActivate() { + for (int i = 0; i < 5; ++i) + xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 16)); - if (x1a4_sliderSfx.operator bool() != - (x18c_slidergroup_slider->GetState() != CGuiSliderGroup::EState::None)) - { - if (x18c_slidergroup_slider->GetState() != CGuiSliderGroup::EState::None) - { - x1a4_sliderSfx = CSfxManager::SfxStart(SFXui_options_slider_change_lp, - 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(x1a4_sliderSfx); - x1a4_sliderSfx.reset(); - } - } - - if (x2a0_24_inOptionBody) - x29c_optionAlpha = std::min(x29c_optionAlpha + 4.f * dt, 1.f); - else - x29c_optionAlpha = std::max(x29c_optionAlpha - 4.f * dt, 0.f); - - if (std::fabs(x29c_optionAlpha) < 0.00001f) - { - ResetOptionWidgetVisibility(); - x174_textpane_body->SetIsVisible(false); - } - - zeus::CColor color = g_tweakGuiColors->GetPauseItemAmberColor(); - color.a() = x29c_optionAlpha; - x18c_slidergroup_slider->SetColor(color); - x190_tablegroup_double->SetColor(color); - x194_tablegroup_triple->SetColor(color); - - if (x19c_quitGame) - { - EQuitAction action = x19c_quitGame->Update(dt); - if (action == EQuitAction::Yes) - { - archQueue.Push(MakeMsg::CreateQuitGameplay(EArchMsgTarget::Game)); - CSfxManager::SetChannel(CSfxManager::ESfxChannels::Default); - CSfxManager::SfxStart(SFXui_options_quit_accept, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - else if (action == EQuitAction::No) - { - CSfxManager::SfxStart(SFXui_options_quit_reject, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x19c_quitGame.reset(); - } - } - - x1a0_gameCube->Update(dt); -} - -void COptionsScreen::Touch() -{ - CPauseScreenBase::Touch(); - x1a0_gameCube->Touch(); -} - -void COptionsScreen::ProcessControllerInput(const CFinalInput& input) -{ - if (!x19c_quitGame) - { - CPauseScreenBase::ProcessControllerInput(input); - CGameOptions::TryRestoreDefaults(input, x70_tablegroup_leftlog->GetUserSelection(), - x1c_rightSel, false, false); - if (x70_tablegroup_leftlog->GetUserSelection() == 4 && input.PA()) - x19c_quitGame = std::make_unique(EQuitType::QuitGame); - } - else - { - x19c_quitGame->ProcessUserInput(input); - } -} - -void COptionsScreen::Draw(float transInterp, float totalAlpha, float yOff) -{ - CPauseScreenBase::Draw(transInterp, totalAlpha, yOff); - x1a0_gameCube->Draw(transInterp * (1.f - x29c_optionAlpha)); - if (x19c_quitGame) - { - CGraphics::SetDepthRange(DEPTH_NEAR, 0.001f); - x19c_quitGame->Draw(); - CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR); - } -} - -bool COptionsScreen::VReady() const -{ - return true; -} - -void COptionsScreen::VActivate() -{ - for (int i=0 ; i<5 ; ++i) - xa8_textpane_categories[i]->TextSupport().SetText(xc_pauseStrg.GetString(i + 16)); - - x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(15)); + x178_textpane_title->TextSupport().SetText(xc_pauseStrg.GetString(15)); #if 0 for (int i=5 ; i<5 ; ++i) x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(false); #endif - x174_textpane_body->TextSupport().SetJustification(EJustification::Center); - x174_textpane_body->TextSupport().SetVerticalJustification(EVerticalJustification::Bottom); + x174_textpane_body->TextSupport().SetJustification(EJustification::Center); + x174_textpane_body->TextSupport().SetVerticalJustification(EVerticalJustification::Bottom); - static_cast(x190_tablegroup_double->GetWorkerWidget(0))-> - TextSupport().SetText(xc_pauseStrg.GetString(95)); - static_cast(x190_tablegroup_double->GetWorkerWidget(1))-> - TextSupport().SetText(xc_pauseStrg.GetString(94)); + static_cast(x190_tablegroup_double->GetWorkerWidget(0)) + ->TextSupport() + .SetText(xc_pauseStrg.GetString(95)); + static_cast(x190_tablegroup_double->GetWorkerWidget(1)) + ->TextSupport() + .SetText(xc_pauseStrg.GetString(94)); - static_cast(x194_tablegroup_triple->GetWorkerWidget(0))-> - TextSupport().SetText(xc_pauseStrg.GetString(96)); - static_cast(x194_tablegroup_triple->GetWorkerWidget(1))-> - TextSupport().SetText(xc_pauseStrg.GetString(97)); - static_cast(x194_tablegroup_triple->GetWorkerWidget(2))-> - TextSupport().SetText(xc_pauseStrg.GetString(98)); + static_cast(x194_tablegroup_triple->GetWorkerWidget(0)) + ->TextSupport() + .SetText(xc_pauseStrg.GetString(96)); + static_cast(x194_tablegroup_triple->GetWorkerWidget(1)) + ->TextSupport() + .SetText(xc_pauseStrg.GetString(97)); + static_cast(x194_tablegroup_triple->GetWorkerWidget(2)) + ->TextSupport() + .SetText(xc_pauseStrg.GetString(98)); - x18c_slidergroup_slider->SetSelectionChangedCallback( - std::bind(&COptionsScreen::OnSliderChanged, this, std::placeholders::_1, std::placeholders::_2)); - x190_tablegroup_double->SetMenuSelectionChangeCallback( - std::bind(&COptionsScreen::OnEnumChanged, this, std::placeholders::_1, std::placeholders::_2)); - x194_tablegroup_triple->SetMenuSelectionChangeCallback( - std::bind(&COptionsScreen::OnEnumChanged, this, std::placeholders::_1, std::placeholders::_2)); + x18c_slidergroup_slider->SetSelectionChangedCallback( + std::bind(&COptionsScreen::OnSliderChanged, this, std::placeholders::_1, std::placeholders::_2)); + x190_tablegroup_double->SetMenuSelectionChangeCallback( + std::bind(&COptionsScreen::OnEnumChanged, this, std::placeholders::_1, std::placeholders::_2)); + x194_tablegroup_triple->SetMenuSelectionChangeCallback( + std::bind(&COptionsScreen::OnEnumChanged, this, std::placeholders::_1, std::placeholders::_2)); } -void COptionsScreen::RightTableSelectionChanged(int oldSel, int newSel) -{ +void COptionsScreen::RightTableSelectionChanged(int oldSel, int newSel) { UpdateOptionView(); } + +void COptionsScreen::ChangedMode(EMode oldMode) { + if (x10_mode == EMode::RightTable) { + x174_textpane_body->SetIsVisible(true); UpdateOptionView(); + x2a0_24_inOptionBody = true; + } else { + x2a0_24_inOptionBody = false; + } } -void COptionsScreen::ChangedMode(EMode oldMode) -{ - if (x10_mode == EMode::RightTable) - { - x174_textpane_body->SetIsVisible(true); - UpdateOptionView(); - x2a0_24_inOptionBody = true; - } +void COptionsScreen::UpdateRightTable() { + CPauseScreenBase::UpdateRightTable(); + const std::pair& category = GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()]; + for (int i = 0; i < 5; ++i) { + if (i < category.first) + xd8_textpane_titles[i]->TextSupport().SetText(xc_pauseStrg.GetString(category.second[i].stringId)); else - { - x2a0_24_inOptionBody = false; - } + xd8_textpane_titles[i]->TextSupport().SetText(u""); + } } -void COptionsScreen::UpdateRightTable() -{ - CPauseScreenBase::UpdateRightTable(); - const std::pair& category = - GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()]; - for (int i=0 ; i<5 ; ++i) - { - if (i < category.first) - xd8_textpane_titles[i]->TextSupport().SetText(xc_pauseStrg.GetString(category.second[i].stringId)); - else - xd8_textpane_titles[i]->TextSupport().SetText(u""); - } +bool COptionsScreen::ShouldLeftTableAdvance() const { return x70_tablegroup_leftlog->GetUserSelection() != 4; } + +bool COptionsScreen::ShouldRightTableAdvance() const { return false; } + +u32 COptionsScreen::GetRightTableCount() const { + return GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()].first; } -bool COptionsScreen::ShouldLeftTableAdvance() const -{ - return x70_tablegroup_leftlog->GetUserSelection() != 4; -} - -bool COptionsScreen::ShouldRightTableAdvance() const -{ - return false; -} - -u32 COptionsScreen::GetRightTableCount() const -{ - return GameOptionsRegistry[x70_tablegroup_leftlog->GetUserSelection()].first; -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/COptionsScreen.hpp b/Runtime/MP1/COptionsScreen.hpp index 917175237..23c2152ba 100644 --- a/Runtime/MP1/COptionsScreen.hpp +++ b/Runtime/MP1/COptionsScreen.hpp @@ -5,41 +5,38 @@ #include "CGameCubeDoll.hpp" #include "CQuitGameScreen.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class COptionsScreen : public CPauseScreenBase -{ - std::unique_ptr x19c_quitGame; - std::unique_ptr x1a0_gameCube; - CSfxHandle x1a4_sliderSfx; - CRumbleGenerator x1a8_rumble; - float x29c_optionAlpha = 0.f; - bool x2a0_24_inOptionBody : 1; +class COptionsScreen : public CPauseScreenBase { + std::unique_ptr x19c_quitGame; + std::unique_ptr x1a0_gameCube; + CSfxHandle x1a4_sliderSfx; + CRumbleGenerator x1a8_rumble; + float x29c_optionAlpha = 0.f; + bool x2a0_24_inOptionBody : 1; - void UpdateOptionView(); - void ResetOptionWidgetVisibility(); - void OnSliderChanged(CGuiSliderGroup* caller, float val); - void OnEnumChanged(CGuiTableGroup* caller, int oldSel); + void UpdateOptionView(); + void ResetOptionWidgetVisibility(); + void OnSliderChanged(CGuiSliderGroup* caller, float val); + void OnEnumChanged(CGuiTableGroup* caller, int oldSel); public: - COptionsScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg); - ~COptionsScreen(); + COptionsScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg); + ~COptionsScreen(); - bool InputDisabled() const; - void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); - void Touch(); - void ProcessControllerInput(const CFinalInput& input); - void Draw(float transInterp, float totalAlpha, float yOff); - bool VReady() const; - void VActivate(); - void RightTableSelectionChanged(int oldSel, int newSel); - void ChangedMode(EMode oldMode); - void UpdateRightTable(); - bool ShouldLeftTableAdvance() const; - bool ShouldRightTableAdvance() const; - u32 GetRightTableCount() const; + bool InputDisabled() const; + void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); + void Touch(); + void ProcessControllerInput(const CFinalInput& input); + void Draw(float transInterp, float totalAlpha, float yOff); + bool VReady() const; + void VActivate(); + void RightTableSelectionChanged(int oldSel, int newSel); + void ChangedMode(EMode oldMode); + void UpdateRightTable(); + bool ShouldLeftTableAdvance() const; + bool ShouldRightTableAdvance() const; + u32 GetRightTableCount() const; }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CPauseScreen.cpp b/Runtime/MP1/CPauseScreen.cpp index ed2e8e1e6..b0b6e071c 100644 --- a/Runtime/MP1/CPauseScreen.cpp +++ b/Runtime/MP1/CPauseScreen.cpp @@ -9,312 +9,277 @@ #include "GuiSys/CGuiWidgetDrawParms.hpp" #include "Input/ControlMapper.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CPauseScreen::CPauseScreen(ESubScreen subscreen, - const CDependencyGroup& suitDgrp, - const CDependencyGroup& ballDgrp) -: x0_initialSubScreen(subscreen), - x14_strgPauseScreen(g_SimplePool->GetObj("STRG_PauseScreen")), - x20_suitDgrp(suitDgrp), x24_ballDgrp(ballDgrp), - x28_pauseScreenInstructions(g_SimplePool->GetObj("FRME_PauseScreenInstructions")), - x54_frmePauseScreenId(g_ResFactory->GetResourceIdByName("FRME_PauseScreen")->id) -{ - SObjectTag frmeTag(FOURCC('FRME'), x54_frmePauseScreenId); - x58_frmePauseScreenBufSz = g_ResFactory->ResourceSize(frmeTag); - x5c_frmePauseScreenBuf.reset(new u8[x58_frmePauseScreenBufSz]); - x60_loadTok = g_ResFactory->LoadResourceAsync(frmeTag, x5c_frmePauseScreenBuf.get()); - CSfxManager::SfxStart(SFXui_pause_screen_enter, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x7c_screens.resize(2); +CPauseScreen::CPauseScreen(ESubScreen subscreen, const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp) +: x0_initialSubScreen(subscreen) +, x14_strgPauseScreen(g_SimplePool->GetObj("STRG_PauseScreen")) +, x20_suitDgrp(suitDgrp) +, x24_ballDgrp(ballDgrp) +, x28_pauseScreenInstructions(g_SimplePool->GetObj("FRME_PauseScreenInstructions")) +, x54_frmePauseScreenId(g_ResFactory->GetResourceIdByName("FRME_PauseScreen")->id) { + SObjectTag frmeTag(FOURCC('FRME'), x54_frmePauseScreenId); + x58_frmePauseScreenBufSz = g_ResFactory->ResourceSize(frmeTag); + x5c_frmePauseScreenBuf.reset(new u8[x58_frmePauseScreenBufSz]); + x60_loadTok = g_ResFactory->LoadResourceAsync(frmeTag, x5c_frmePauseScreenBuf.get()); + CSfxManager::SfxStart(SFXui_pause_screen_enter, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x7c_screens.resize(2); } -CPauseScreen::~CPauseScreen() -{ - if (x60_loadTok) - x60_loadTok->PostCancelRequest(); +CPauseScreen::~CPauseScreen() { + if (x60_loadTok) + x60_loadTok->PostCancelRequest(); } -std::unique_ptr CPauseScreen::BuildPauseSubScreen(ESubScreen subscreen, - const CStateManager& mgr, - CGuiFrame& frame) const -{ - switch (subscreen) - { - case ESubScreen::LogBook: - return std::make_unique(mgr, frame, *x14_strgPauseScreen); - case ESubScreen::Options: - return std::make_unique(mgr, frame, *x14_strgPauseScreen); - case ESubScreen::Inventory: - return std::make_unique(mgr, frame, *x14_strgPauseScreen, x20_suitDgrp, x24_ballDgrp); - default: - return {}; - } +std::unique_ptr CPauseScreen::BuildPauseSubScreen(ESubScreen subscreen, const CStateManager& mgr, + CGuiFrame& frame) const { + switch (subscreen) { + case ESubScreen::LogBook: + return std::make_unique(mgr, frame, *x14_strgPauseScreen); + case ESubScreen::Options: + return std::make_unique(mgr, frame, *x14_strgPauseScreen); + case ESubScreen::Inventory: + return std::make_unique(mgr, frame, *x14_strgPauseScreen, x20_suitDgrp, x24_ballDgrp); + default: + return {}; + } } -void CPauseScreen::InitializeFrameGlue() -{ - x38_textpane_l1 = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_l1")); - x3c_textpane_r = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_r")); - x40_textpane_a = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_a")); - x44_textpane_b = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_b")); - x48_textpane_return = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_return")); - x4c_textpane_next = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_next")); - x50_textpane_back = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_back")); +void CPauseScreen::InitializeFrameGlue() { + x38_textpane_l1 = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_l1")); + x3c_textpane_r = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_r")); + x40_textpane_a = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_a")); + x44_textpane_b = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_b")); + x48_textpane_return = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_return")); + x4c_textpane_next = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_next")); + x50_textpane_back = static_cast(x34_loadedPauseScreenInstructions->FindWidget("textpane_back")); - x40_textpane_a->TextSupport().SetText(x14_strgPauseScreen->GetString(7)); // OPTIONS - x40_textpane_a->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemAmberColor()); - x44_textpane_b->TextSupport().SetText(x14_strgPauseScreen->GetString(6)); // LOG BOOK - x44_textpane_b->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemAmberColor()); - x40_textpane_a->SetColor(zeus::CColor::skClear); - x44_textpane_b->SetColor(zeus::CColor::skClear); + x40_textpane_a->TextSupport().SetText(x14_strgPauseScreen->GetString(7)); // OPTIONS + x40_textpane_a->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemAmberColor()); + x44_textpane_b->TextSupport().SetText(x14_strgPauseScreen->GetString(6)); // LOG BOOK + x44_textpane_b->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemAmberColor()); + x40_textpane_a->SetColor(zeus::CColor::skClear); + x44_textpane_b->SetColor(zeus::CColor::skClear); - if (CGuiWidget* deco = x34_loadedPauseScreenInstructions->FindWidget("basewidget_deco")) - { - zeus::CColor color = g_tweakGuiColors->GetPauseItemAmberColor(); - color.a() *= 0.75f; - deco->SetColor(color); - } + if (CGuiWidget* deco = x34_loadedPauseScreenInstructions->FindWidget("basewidget_deco")) { + zeus::CColor color = g_tweakGuiColors->GetPauseItemAmberColor(); + color.a() *= 0.75f; + deco->SetColor(color); + } } -bool CPauseScreen::CheckLoadComplete(const CStateManager& mgr) -{ - if (x90_resourcesLoaded) - return true; - if (!x14_strgPauseScreen.IsLoaded()) - return false; - if (!x34_loadedPauseScreenInstructions) - { - if (!x28_pauseScreenInstructions.IsLoaded()) - return false; - if (!x28_pauseScreenInstructions->GetIsFinishedLoading()) - return false; - x34_loadedPauseScreenInstructions = x28_pauseScreenInstructions.GetObj(); - x34_loadedPauseScreenInstructions->SetMaxAspect(1.77f); - InitializeFrameGlue(); - } - if (x60_loadTok) - { - if (!x60_loadTok->IsComplete()) - return false; - for (int i=0 ; i<2 ; ++i) - { - CMemoryInStream s(x5c_frmePauseScreenBuf.get(), x58_frmePauseScreenBufSz); - x64_frameInsts.push_back(CGuiFrame::CreateFrame(x54_frmePauseScreenId, *g_GuiSys, s, g_SimplePool)); - x64_frameInsts.back()->SetMaxAspect(1.77f); - } - x5c_frmePauseScreenBuf.reset(); - x60_loadTok.reset(); - } - if (!x64_frameInsts[0]->GetIsFinishedLoading() || !x64_frameInsts[1]->GetIsFinishedLoading()) - return false; - x90_resourcesLoaded = true; - StartTransition(FLT_EPSILON, mgr, x0_initialSubScreen, 2); - x91_initialTransition = true; +bool CPauseScreen::CheckLoadComplete(const CStateManager& mgr) { + if (x90_resourcesLoaded) return true; -} - -void CPauseScreen::StartTransition(float time, const CStateManager& mgr, ESubScreen subscreen, int b) -{ - if (subscreen == xc_nextSubscreen) - return; - xc_nextSubscreen = subscreen; - x4_ = b; - x10_alphaInterp = time; - std::unique_ptr& newScreenSlot = x7c_screens[1 - x78_activeIdx]; - std::unique_ptr& newScreenInst = x64_frameInsts[1 - x78_activeIdx]; - newScreenSlot = BuildPauseSubScreen(xc_nextSubscreen, mgr, *newScreenInst); - if (x7c_screens[x78_activeIdx]) - x7c_screens[x78_activeIdx]->TransitioningAway(); - x91_initialTransition = false; -} - -bool CPauseScreen::InputEnabled() const -{ - if (xc_nextSubscreen != x8_curSubscreen) - return false; - - if (const std::unique_ptr& screenSlot = x7c_screens[x78_activeIdx]) - if (screenSlot->InputDisabled()) - return false; - - if (const std::unique_ptr& screenSlot = x7c_screens[1 - x78_activeIdx]) - if (screenSlot->InputDisabled()) - return false; - - return true; -} - -CPauseScreen::ESubScreen CPauseScreen::GetPreviousSubscreen(ESubScreen screen) -{ - switch (screen) - { - case ESubScreen::Inventory: - return ESubScreen::Options; - case ESubScreen::Options: - return ESubScreen::LogBook; - case ESubScreen::LogBook: - return ESubScreen::Inventory; - default: - return ESubScreen::ToGame; + if (!x14_strgPauseScreen.IsLoaded()) + return false; + if (!x34_loadedPauseScreenInstructions) { + if (!x28_pauseScreenInstructions.IsLoaded()) + return false; + if (!x28_pauseScreenInstructions->GetIsFinishedLoading()) + return false; + x34_loadedPauseScreenInstructions = x28_pauseScreenInstructions.GetObj(); + x34_loadedPauseScreenInstructions->SetMaxAspect(1.77f); + InitializeFrameGlue(); + } + if (x60_loadTok) { + if (!x60_loadTok->IsComplete()) + return false; + for (int i = 0; i < 2; ++i) { + CMemoryInStream s(x5c_frmePauseScreenBuf.get(), x58_frmePauseScreenBufSz); + x64_frameInsts.push_back(CGuiFrame::CreateFrame(x54_frmePauseScreenId, *g_GuiSys, s, g_SimplePool)); + x64_frameInsts.back()->SetMaxAspect(1.77f); } + x5c_frmePauseScreenBuf.reset(); + x60_loadTok.reset(); + } + if (!x64_frameInsts[0]->GetIsFinishedLoading() || !x64_frameInsts[1]->GetIsFinishedLoading()) + return false; + x90_resourcesLoaded = true; + StartTransition(FLT_EPSILON, mgr, x0_initialSubScreen, 2); + x91_initialTransition = true; + return true; } -CPauseScreen::ESubScreen CPauseScreen::GetNextSubscreen(ESubScreen screen) -{ - switch (screen) - { - case ESubScreen::Inventory: - return ESubScreen::LogBook; - case ESubScreen::Options: - return ESubScreen::Inventory; - case ESubScreen::LogBook: - return ESubScreen::Options; - default: - return ESubScreen::ToGame; +void CPauseScreen::StartTransition(float time, const CStateManager& mgr, ESubScreen subscreen, int b) { + if (subscreen == xc_nextSubscreen) + return; + xc_nextSubscreen = subscreen; + x4_ = b; + x10_alphaInterp = time; + std::unique_ptr& newScreenSlot = x7c_screens[1 - x78_activeIdx]; + std::unique_ptr& newScreenInst = x64_frameInsts[1 - x78_activeIdx]; + newScreenSlot = BuildPauseSubScreen(xc_nextSubscreen, mgr, *newScreenInst); + if (x7c_screens[x78_activeIdx]) + x7c_screens[x78_activeIdx]->TransitioningAway(); + x91_initialTransition = false; +} + +bool CPauseScreen::InputEnabled() const { + if (xc_nextSubscreen != x8_curSubscreen) + return false; + + if (const std::unique_ptr& screenSlot = x7c_screens[x78_activeIdx]) + if (screenSlot->InputDisabled()) + return false; + + if (const std::unique_ptr& screenSlot = x7c_screens[1 - x78_activeIdx]) + if (screenSlot->InputDisabled()) + return false; + + return true; +} + +CPauseScreen::ESubScreen CPauseScreen::GetPreviousSubscreen(ESubScreen screen) { + switch (screen) { + case ESubScreen::Inventory: + return ESubScreen::Options; + case ESubScreen::Options: + return ESubScreen::LogBook; + case ESubScreen::LogBook: + return ESubScreen::Inventory; + default: + return ESubScreen::ToGame; + } +} + +CPauseScreen::ESubScreen CPauseScreen::GetNextSubscreen(ESubScreen screen) { + switch (screen) { + case ESubScreen::Inventory: + return ESubScreen::LogBook; + case ESubScreen::Options: + return ESubScreen::Inventory; + case ESubScreen::LogBook: + return ESubScreen::Options; + default: + return ESubScreen::ToGame; + } +} + +void CPauseScreen::ProcessControllerInput(const CStateManager& mgr, const CFinalInput& input) { + if (!IsLoaded()) + return; + + if (x8_curSubscreen == ESubScreen::ToGame) + return; + + bool bExits = false; + if (std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]) { + if (curScreen->GetMode() == CPauseScreenBase::EMode::LeftTable) + bExits = true; + curScreen->ProcessControllerInput(input); + } + + if (InputEnabled()) { + bool invalid = x8_curSubscreen == ESubScreen::ToGame; + if (input.PStart() || (input.PB() && bExits) || + (x7c_screens[x78_activeIdx] && x7c_screens[x78_activeIdx]->ShouldExitPauseScreen())) { + CSfxManager::SfxStart(SFXui_pause_screen_exit, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + StartTransition(0.5f, mgr, ESubScreen::ToGame, 2); + } else { + if (ControlMapper::GetPressInput(ControlMapper::ECommands::PreviousPauseScreen, input)) { + CSfxManager::SfxStart(SFXui_pause_screen_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + StartTransition(0.5f, mgr, GetPreviousSubscreen(x8_curSubscreen), invalid ? 2 : 0); + } else if (ControlMapper::GetPressInput(ControlMapper::ECommands::NextPauseScreen, input)) { + CSfxManager::SfxStart(SFXui_pause_screen_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + StartTransition(0.5f, mgr, GetNextSubscreen(x8_curSubscreen), invalid ? 2 : 1); + } } + } + + x38_textpane_l1->TextSupport().SetText( + hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x74_lTrigger[input.DLTrigger()].Value()))); + x3c_textpane_r->TextSupport().SetText( + hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x80_rTrigger[input.DRTrigger()].Value()))); + x48_textpane_return->TextSupport().SetText( + hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x8c_startButton[input.DStart()].Value()))); + x50_textpane_back->TextSupport().SetText( + hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x98_aButton[input.DA()].Value()))); + x4c_textpane_next->TextSupport().SetText( + hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->xa4_bButton[input.DB()].Value()))); } -void CPauseScreen::ProcessControllerInput(const CStateManager& mgr, const CFinalInput& input) -{ - if (!IsLoaded()) - return; +void CPauseScreen::TransitionComplete() { + std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]; + curScreen.reset(); + x78_activeIdx = 1 - x78_activeIdx; + x8_curSubscreen = xc_nextSubscreen; + x40_textpane_a->TextSupport().SetText(x14_strgPauseScreen->GetString(int(GetPreviousSubscreen(x8_curSubscreen)) + 6)); + x44_textpane_b->TextSupport().SetText(x14_strgPauseScreen->GetString(int(GetNextSubscreen(x8_curSubscreen)) + 6)); +} - if (x8_curSubscreen == ESubScreen::ToGame) - return; +void CPauseScreen::Update(float dt, const CStateManager& mgr, CRandom16& rand, CArchitectureQueue& archQueue) { + if (!CheckLoadComplete(mgr)) + return; - bool bExits = false; - if (std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]) - { - if (curScreen->GetMode() == CPauseScreenBase::EMode::LeftTable) - bExits = true; - curScreen->ProcessControllerInput(input); + std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]; + std::unique_ptr& otherScreen = x7c_screens[1 - x78_activeIdx]; + + if (x8_curSubscreen != xc_nextSubscreen) { + x10_alphaInterp = std::max(0.f, x10_alphaInterp - dt); + if (!curScreen || !curScreen->InputDisabled()) { + if (!otherScreen || otherScreen->IsReady()) { + if (x10_alphaInterp == 0.f) + TransitionComplete(); + } } + } - if (InputEnabled()) - { - bool invalid = x8_curSubscreen == ESubScreen::ToGame; - if (input.PStart() || (input.PB() && bExits) || - (x7c_screens[x78_activeIdx] && x7c_screens[x78_activeIdx]->ShouldExitPauseScreen())) - { - CSfxManager::SfxStart(SFXui_pause_screen_exit, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - StartTransition(0.5f, mgr, ESubScreen::ToGame, 2); - } - else - { - if (ControlMapper::GetPressInput(ControlMapper::ECommands::PreviousPauseScreen, input)) - { - CSfxManager::SfxStart(SFXui_pause_screen_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - StartTransition(0.5f, mgr, GetPreviousSubscreen(x8_curSubscreen), invalid ? 2 : 0); - } - else if (ControlMapper::GetPressInput(ControlMapper::ECommands::NextPauseScreen, input)) - { - CSfxManager::SfxStart(SFXui_pause_screen_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - StartTransition(0.5f, mgr, GetNextSubscreen(x8_curSubscreen), invalid ? 2 : 1); - } - } - } - - x38_textpane_l1->TextSupport().SetText(hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x74_lTrigger[input.DLTrigger()].Value()))); - x3c_textpane_r->TextSupport().SetText(hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x80_rTrigger[input.DRTrigger()].Value()))); - x48_textpane_return->TextSupport().SetText(hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x8c_startButton[input.DStart()].Value()))); - x50_textpane_back->TextSupport().SetText(hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->x98_aButton[input.DA()].Value()))); - x4c_textpane_next->TextSupport().SetText(hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->xa4_bButton[input.DB()].Value()))); + if (std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]) { + curScreen->Update(dt, rand, archQueue); + zeus::CColor color = zeus::CColor::skWhite; + color.a() = std::min(curScreen->GetAlpha(), x8_curSubscreen != xc_nextSubscreen ? x10_alphaInterp / 0.5f : 1.f); + x40_textpane_a->SetColor(color); + x44_textpane_b->SetColor(color); + } } -void CPauseScreen::TransitionComplete() -{ - std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]; - curScreen.reset(); - x78_activeIdx = 1 - x78_activeIdx; - x8_curSubscreen = xc_nextSubscreen; - x40_textpane_a->TextSupport().SetText(x14_strgPauseScreen->GetString(int(GetPreviousSubscreen(x8_curSubscreen)) + 6)); - x44_textpane_b->TextSupport().SetText(x14_strgPauseScreen->GetString(int(GetNextSubscreen(x8_curSubscreen)) + 6)); +void CPauseScreen::PreDraw() { + if (!IsLoaded()) + return; + if (std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]) + if (curScreen->CanDraw()) + curScreen->Touch(); } -void CPauseScreen::Update(float dt, const CStateManager& mgr, CRandom16& rand, CArchitectureQueue& archQueue) -{ - if (!CheckLoadComplete(mgr)) - return; +void CPauseScreen::Draw() { + if (!IsLoaded()) + return; - std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]; - std::unique_ptr& otherScreen = x7c_screens[1 - x78_activeIdx]; + float totalAlpha = 0.f; + float yOff = 0.f; + std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]; + if (curScreen && curScreen->CanDraw()) { + float useInterp = x10_alphaInterp == 0.f ? 1.f : x10_alphaInterp / 0.5f; + float initInterp = std::min(curScreen->GetAlpha(), useInterp); + if (xc_nextSubscreen == ESubScreen::ToGame) + totalAlpha = useInterp; + else if (x91_initialTransition) + totalAlpha = initInterp; + else + totalAlpha = 1.f; - if (x8_curSubscreen != xc_nextSubscreen) - { - x10_alphaInterp = std::max(0.f, x10_alphaInterp - dt); - if (!curScreen || !curScreen->InputDisabled()) - { - if (!otherScreen || otherScreen->IsReady()) - { - if (x10_alphaInterp == 0.f) - TransitionComplete(); - } - } - } + curScreen->Draw(x8_curSubscreen != xc_nextSubscreen ? useInterp : 1.f, totalAlpha, 0.f); + yOff = curScreen->GetCameraYBias(); + } - if (std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]) - { - curScreen->Update(dt, rand, archQueue); - zeus::CColor color = zeus::CColor::skWhite; - color.a() = std::min(curScreen->GetAlpha(), x8_curSubscreen != xc_nextSubscreen ? x10_alphaInterp / 0.5f : 1.f); - x40_textpane_a->SetColor(color); - x44_textpane_b->SetColor(color); - } + CGuiWidgetDrawParms parms(totalAlpha, zeus::CVector3f{0.f, 15.f * yOff, 0.f}); + x34_loadedPauseScreenInstructions->Draw(parms); } -void CPauseScreen::PreDraw() -{ - if (!IsLoaded()) - return; - if (std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]) - if (curScreen->CanDraw()) - curScreen->Touch(); +bool CPauseScreen::ShouldSwitchToMapScreen() const { + return IsLoaded() && x8_curSubscreen == ESubScreen::ToMap && xc_nextSubscreen == ESubScreen::ToMap; } -void CPauseScreen::Draw() -{ - if (!IsLoaded()) - return; - - float totalAlpha = 0.f; - float yOff = 0.f; - std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]; - if (curScreen && curScreen->CanDraw()) - { - float useInterp = x10_alphaInterp == 0.f ? 1.f : x10_alphaInterp / 0.5f; - float initInterp = std::min(curScreen->GetAlpha(), useInterp); - if (xc_nextSubscreen == ESubScreen::ToGame) - totalAlpha = useInterp; - else if (x91_initialTransition) - totalAlpha = initInterp; - else - totalAlpha = 1.f; - - curScreen->Draw(x8_curSubscreen != xc_nextSubscreen ? useInterp : 1.f, totalAlpha, 0.f); - yOff = curScreen->GetCameraYBias(); - } - - CGuiWidgetDrawParms parms(totalAlpha, zeus::CVector3f{0.f, 15.f * yOff, 0.f}); - x34_loadedPauseScreenInstructions->Draw(parms); +bool CPauseScreen::ShouldSwitchToInGame() const { + return IsLoaded() && x8_curSubscreen == ESubScreen::ToGame && xc_nextSubscreen == ESubScreen::ToGame; } -bool CPauseScreen::ShouldSwitchToMapScreen() const -{ - return IsLoaded() && x8_curSubscreen == ESubScreen::ToMap && xc_nextSubscreen == ESubScreen::ToMap; +float CPauseScreen::GetHelmetCamYOff() const { + CPauseScreenBase* screen = x7c_screens[x78_activeIdx].get(); + if (screen) + return screen->GetCameraYBias(); + return 0.f; } -bool CPauseScreen::ShouldSwitchToInGame() const -{ - return IsLoaded() && x8_curSubscreen == ESubScreen::ToGame && xc_nextSubscreen == ESubScreen::ToGame; -} - -float CPauseScreen::GetHelmetCamYOff() const -{ - CPauseScreenBase* screen = x7c_screens[x78_activeIdx].get(); - if (screen) - return screen->GetCameraYBias(); - return 0.f; -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CPauseScreen.hpp b/Runtime/MP1/CPauseScreen.hpp index 25b9a31f5..6dae07e6e 100644 --- a/Runtime/MP1/CPauseScreen.hpp +++ b/Runtime/MP1/CPauseScreen.hpp @@ -4,77 +4,66 @@ #include "Editor/ProjectResourceFactoryBase.hpp" #include "CPauseScreenBase.hpp" -namespace urde -{ +namespace urde { class CDependencyGroup; -namespace MP1 -{ +namespace MP1 { -class CPauseScreen -{ +class CPauseScreen { public: - enum class ESubScreen - { - LogBook, - Options, - Inventory, - ToGame, - ToMap - }; + enum class ESubScreen { LogBook, Options, Inventory, ToGame, ToMap }; private: - ESubScreen x0_initialSubScreen; - u32 x4_ = 2; - ESubScreen x8_curSubscreen = ESubScreen::ToGame; - ESubScreen xc_nextSubscreen = ESubScreen::ToGame; - float x10_alphaInterp = 0.f; - TLockedToken x14_strgPauseScreen; - const CDependencyGroup& x20_suitDgrp; - const CDependencyGroup& x24_ballDgrp; - TLockedToken x28_pauseScreenInstructions; - CGuiFrame* x34_loadedPauseScreenInstructions = nullptr; - CGuiTextPane* x38_textpane_l1 = nullptr; - CGuiTextPane* x3c_textpane_r = nullptr; - CGuiTextPane* x40_textpane_a = nullptr; - CGuiTextPane* x44_textpane_b = nullptr; - CGuiTextPane* x48_textpane_return = nullptr; - CGuiTextPane* x4c_textpane_next = nullptr; - CGuiTextPane* x50_textpane_back = nullptr; - CAssetId x54_frmePauseScreenId; - u32 x58_frmePauseScreenBufSz; - std::unique_ptr x5c_frmePauseScreenBuf; - std::shared_ptr x60_loadTok; - rstl::reserved_vector, 2> x64_frameInsts; - u32 x78_activeIdx = 0; - rstl::reserved_vector, 2> x7c_screens; - bool x90_resourcesLoaded = false; - bool x91_initialTransition = true; + ESubScreen x0_initialSubScreen; + u32 x4_ = 2; + ESubScreen x8_curSubscreen = ESubScreen::ToGame; + ESubScreen xc_nextSubscreen = ESubScreen::ToGame; + float x10_alphaInterp = 0.f; + TLockedToken x14_strgPauseScreen; + const CDependencyGroup& x20_suitDgrp; + const CDependencyGroup& x24_ballDgrp; + TLockedToken x28_pauseScreenInstructions; + CGuiFrame* x34_loadedPauseScreenInstructions = nullptr; + CGuiTextPane* x38_textpane_l1 = nullptr; + CGuiTextPane* x3c_textpane_r = nullptr; + CGuiTextPane* x40_textpane_a = nullptr; + CGuiTextPane* x44_textpane_b = nullptr; + CGuiTextPane* x48_textpane_return = nullptr; + CGuiTextPane* x4c_textpane_next = nullptr; + CGuiTextPane* x50_textpane_back = nullptr; + CAssetId x54_frmePauseScreenId; + u32 x58_frmePauseScreenBufSz; + std::unique_ptr x5c_frmePauseScreenBuf; + std::shared_ptr x60_loadTok; + rstl::reserved_vector, 2> x64_frameInsts; + u32 x78_activeIdx = 0; + rstl::reserved_vector, 2> x7c_screens; + bool x90_resourcesLoaded = false; + bool x91_initialTransition = true; + + std::unique_ptr BuildPauseSubScreen(ESubScreen subscreen, const CStateManager& mgr, + CGuiFrame& frame) const; + void StartTransition(float time, const CStateManager& mgr, ESubScreen subscreen, int); + bool CheckLoadComplete(const CStateManager& mgr); + void InitializeFrameGlue(); + bool InputEnabled() const; + static ESubScreen GetPreviousSubscreen(ESubScreen screen); + static ESubScreen GetNextSubscreen(ESubScreen screen); + void TransitionComplete(); - std::unique_ptr BuildPauseSubScreen(ESubScreen subscreen, - const CStateManager& mgr, - CGuiFrame& frame) const; - void StartTransition(float time, const CStateManager& mgr, ESubScreen subscreen, int); - bool CheckLoadComplete(const CStateManager& mgr); - void InitializeFrameGlue(); - bool InputEnabled() const; - static ESubScreen GetPreviousSubscreen(ESubScreen screen); - static ESubScreen GetNextSubscreen(ESubScreen screen); - void TransitionComplete(); public: - CPauseScreen(ESubScreen subscreen, const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp); - ~CPauseScreen(); - void ProcessControllerInput(const CStateManager& mgr, const CFinalInput& input); - void Update(float dt, const CStateManager& mgr, CRandom16& rand, CArchitectureQueue& archQueue); - void PreDraw(); - void Draw(); - bool IsLoaded() const { return x90_resourcesLoaded; } - bool ShouldSwitchToMapScreen() const; - bool ShouldSwitchToInGame() const; - bool IsTransitioning() const { return x8_curSubscreen != xc_nextSubscreen; } - float GetHelmetCamYOff() const; + CPauseScreen(ESubScreen subscreen, const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp); + ~CPauseScreen(); + void ProcessControllerInput(const CStateManager& mgr, const CFinalInput& input); + void Update(float dt, const CStateManager& mgr, CRandom16& rand, CArchitectureQueue& archQueue); + void PreDraw(); + void Draw(); + bool IsLoaded() const { return x90_resourcesLoaded; } + bool ShouldSwitchToMapScreen() const; + bool ShouldSwitchToInGame() const; + bool IsTransitioning() const { return x8_curSubscreen != xc_nextSubscreen; } + float GetHelmetCamYOff() const; }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CPauseScreenBase.cpp b/Runtime/MP1/CPauseScreenBase.cpp index c0bff1eb4..a9ce59c97 100644 --- a/Runtime/MP1/CPauseScreenBase.cpp +++ b/Runtime/MP1/CPauseScreenBase.cpp @@ -11,418 +11,363 @@ #include "CGameState.hpp" #include "GuiSys/CStringTable.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CPauseScreenBase::CPauseScreenBase(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg) -: x4_mgr(mgr), x8_frame(frame), xc_pauseStrg(pauseStrg) -{ - InitializeFrameGlue(); +: x4_mgr(mgr), x8_frame(frame), xc_pauseStrg(pauseStrg) { + InitializeFrameGlue(); } -void CPauseScreenBase::InitializeFrameGlue() -{ - x60_basewidget_pivot = x8_frame.FindWidget("basewidget_pivot"); - x64_basewidget_bgframe = x8_frame.FindWidget("basewidget_bgframe"); - x68_basewidget_leftside = x8_frame.FindWidget("basewidget_leftside"); - x6c_basewidget_leftlog = x8_frame.FindWidget("basewidget_leftlog"); - x70_tablegroup_leftlog = static_cast(x8_frame.FindWidget("tablegroup_leftlog")); - x74_basewidget_leftguages = x8_frame.FindWidget("basewidget_leftguages"); - x74_basewidget_leftguages->SetColor(zeus::CColor(1.f, 0.f)); - x78_model_lefthighlight = static_cast(x8_frame.FindWidget("model_lefthighlight")); - x7c_basewidget_rightside = x8_frame.FindWidget("basewidget_rightside"); - x80_basewidget_rightlog = x8_frame.FindWidget("basewidget_rightlog"); - x84_tablegroup_rightlog = static_cast(x8_frame.FindWidget("tablegroup_rightlog")); - x88_basewidget_rightguages = x8_frame.FindWidget("basewidget_rightguages"); - x88_basewidget_rightguages->SetColor(zeus::CColor(1.f, 0.f)); - x8c_model_righthighlight = static_cast(x8_frame.FindWidget("model_righthighlight")); - x90_model_textarrowtop = static_cast(x8_frame.FindWidget("model_textarrowtop")); - x94_model_textarrowbottom = static_cast(x8_frame.FindWidget("model_textarrowbottom")); - x98_model_scrollleftup = static_cast(x8_frame.FindWidget("model_scrollleftup")); - x9c_model_scrollleftdown = static_cast(x8_frame.FindWidget("model_scrollleftdown")); - xa0_model_scrollrightup = static_cast(x8_frame.FindWidget("model_scrollrightup")); - xa4_model_scrollrightdown = static_cast(x8_frame.FindWidget("model_scrollrightdown")); - x94_model_textarrowbottom = static_cast(x8_frame.FindWidget("model_textarrowbottom")); - x178_textpane_title = static_cast(x8_frame.FindWidget("textpane_title")); - x178_textpane_title->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemAmberColor()); - x174_textpane_body = static_cast(x8_frame.FindWidget("textpane_body")); - x174_textpane_body->SetColor(zeus::CColor(1.f, 0.f)); - x174_textpane_body->SetIsVisible(true); - x174_textpane_body->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemAmberColor()); - x174_textpane_body->TextSupport().SetPage(0); - x174_textpane_body->TextSupport().SetText(u""); - x174_textpane_body->TextSupport().SetJustification(EJustification::Left); - x174_textpane_body->TextSupport().SetVerticalJustification(EVerticalJustification::Top); - x174_textpane_body->TextSupport().SetControlTXTRMap(&g_GameState->GameOptions().GetControlTXTRMap()); - x180_basewidget_yicon = x8_frame.FindWidget("basewidget_yicon"); - x180_basewidget_yicon->SetVisibility(false, ETraversalMode::Children); - x17c_model_textalpha = static_cast(x8_frame.FindWidget("model_textalpha")); - x184_textpane_yicon = static_cast(x8_frame.FindWidget("textpane_yicon")); - x188_textpane_ytext = static_cast(x8_frame.FindWidget("textpane_ytext")); - x184_textpane_yicon->TextSupport().SetText(hecl::UTF8ToChar16(hecl::Format("&image=%8.8X;", - u32(g_tweakPlayerRes->xbc_yButton[0].Value())))); - x188_textpane_ytext->TextSupport().SetText(xc_pauseStrg.GetString(99)); - x188_textpane_ytext->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); - x18c_slidergroup_slider = static_cast(x8_frame.FindWidget("slidergroup_slider")); - x190_tablegroup_double = static_cast(x8_frame.FindWidget("tablegroup_double")); - x194_tablegroup_triple = static_cast(x8_frame.FindWidget("tablegroup_triple")); +void CPauseScreenBase::InitializeFrameGlue() { + x60_basewidget_pivot = x8_frame.FindWidget("basewidget_pivot"); + x64_basewidget_bgframe = x8_frame.FindWidget("basewidget_bgframe"); + x68_basewidget_leftside = x8_frame.FindWidget("basewidget_leftside"); + x6c_basewidget_leftlog = x8_frame.FindWidget("basewidget_leftlog"); + x70_tablegroup_leftlog = static_cast(x8_frame.FindWidget("tablegroup_leftlog")); + x74_basewidget_leftguages = x8_frame.FindWidget("basewidget_leftguages"); + x74_basewidget_leftguages->SetColor(zeus::CColor(1.f, 0.f)); + x78_model_lefthighlight = static_cast(x8_frame.FindWidget("model_lefthighlight")); + x7c_basewidget_rightside = x8_frame.FindWidget("basewidget_rightside"); + x80_basewidget_rightlog = x8_frame.FindWidget("basewidget_rightlog"); + x84_tablegroup_rightlog = static_cast(x8_frame.FindWidget("tablegroup_rightlog")); + x88_basewidget_rightguages = x8_frame.FindWidget("basewidget_rightguages"); + x88_basewidget_rightguages->SetColor(zeus::CColor(1.f, 0.f)); + x8c_model_righthighlight = static_cast(x8_frame.FindWidget("model_righthighlight")); + x90_model_textarrowtop = static_cast(x8_frame.FindWidget("model_textarrowtop")); + x94_model_textarrowbottom = static_cast(x8_frame.FindWidget("model_textarrowbottom")); + x98_model_scrollleftup = static_cast(x8_frame.FindWidget("model_scrollleftup")); + x9c_model_scrollleftdown = static_cast(x8_frame.FindWidget("model_scrollleftdown")); + xa0_model_scrollrightup = static_cast(x8_frame.FindWidget("model_scrollrightup")); + xa4_model_scrollrightdown = static_cast(x8_frame.FindWidget("model_scrollrightdown")); + x94_model_textarrowbottom = static_cast(x8_frame.FindWidget("model_textarrowbottom")); + x178_textpane_title = static_cast(x8_frame.FindWidget("textpane_title")); + x178_textpane_title->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemAmberColor()); + x174_textpane_body = static_cast(x8_frame.FindWidget("textpane_body")); + x174_textpane_body->SetColor(zeus::CColor(1.f, 0.f)); + x174_textpane_body->SetIsVisible(true); + x174_textpane_body->TextSupport().SetFontColor(g_tweakGuiColors->GetPauseItemAmberColor()); + x174_textpane_body->TextSupport().SetPage(0); + x174_textpane_body->TextSupport().SetText(u""); + x174_textpane_body->TextSupport().SetJustification(EJustification::Left); + x174_textpane_body->TextSupport().SetVerticalJustification(EVerticalJustification::Top); + x174_textpane_body->TextSupport().SetControlTXTRMap(&g_GameState->GameOptions().GetControlTXTRMap()); + x180_basewidget_yicon = x8_frame.FindWidget("basewidget_yicon"); + x180_basewidget_yicon->SetVisibility(false, ETraversalMode::Children); + x17c_model_textalpha = static_cast(x8_frame.FindWidget("model_textalpha")); + x184_textpane_yicon = static_cast(x8_frame.FindWidget("textpane_yicon")); + x188_textpane_ytext = static_cast(x8_frame.FindWidget("textpane_ytext")); + x184_textpane_yicon->TextSupport().SetText( + hecl::UTF8ToChar16(hecl::Format("&image=%8.8X;", u32(g_tweakPlayerRes->xbc_yButton[0].Value())))); + x188_textpane_ytext->TextSupport().SetText(xc_pauseStrg.GetString(99)); + x188_textpane_ytext->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); + x18c_slidergroup_slider = static_cast(x8_frame.FindWidget("slidergroup_slider")); + x190_tablegroup_double = static_cast(x8_frame.FindWidget("tablegroup_double")); + x194_tablegroup_triple = static_cast(x8_frame.FindWidget("tablegroup_triple")); - x2c_rightTableStart = x84_tablegroup_rightlog->GetWorkerWidget(0)->GetIdlePosition(); - x38_highlightPitch = x84_tablegroup_rightlog->GetWorkerWidget(1)->GetIdlePosition().z() - x2c_rightTableStart.z(); - x3c_sliderStart = x18c_slidergroup_slider->GetIdlePosition(); - x48_tableDoubleStart = x190_tablegroup_double->GetIdlePosition(); - x54_tableTripleStart = x194_tablegroup_triple->GetIdlePosition(); + x2c_rightTableStart = x84_tablegroup_rightlog->GetWorkerWidget(0)->GetIdlePosition(); + x38_highlightPitch = x84_tablegroup_rightlog->GetWorkerWidget(1)->GetIdlePosition().z() - x2c_rightTableStart.z(); + x3c_sliderStart = x18c_slidergroup_slider->GetIdlePosition(); + x48_tableDoubleStart = x190_tablegroup_double->GetIdlePosition(); + x54_tableTripleStart = x194_tablegroup_triple->GetIdlePosition(); - for (int i=0 ; i<5 ; ++i) - x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(true); + for (int i = 0; i < 5; ++i) + x70_tablegroup_leftlog->GetWorkerWidget(i)->SetIsSelectable(true); - for (int i=0 ; iGetElementCount() ; ++i) - { - CGuiWidget* w = x84_tablegroup_rightlog->GetWorkerWidget(i); - w->SetLocalTransform(zeus::CTransform::Translate( - x2c_rightTableStart + zeus::CVector3f(0.f, 0.f, x38_highlightPitch * i))); - w->SetIsSelectable(true); - } + for (int i = 0; i < x84_tablegroup_rightlog->GetElementCount(); ++i) { + CGuiWidget* w = x84_tablegroup_rightlog->GetWorkerWidget(i); + w->SetLocalTransform( + zeus::CTransform::Translate(x2c_rightTableStart + zeus::CVector3f(0.f, 0.f, x38_highlightPitch * i))); + w->SetIsSelectable(true); + } - for (int i=0 ; i<5 ; ++i) - { - xd8_textpane_titles.push_back(static_cast(x8_frame.FindWidget(hecl::Format("textpane_title%d", i + 1)))); - xd8_textpane_titles.back()->TextSupport().SetText(u""); - x144_model_titles.push_back(static_cast(x8_frame.FindWidget(hecl::Format("model_title%d", i + 1)))); - x15c_model_righttitledecos.push_back(static_cast(x8_frame.FindWidget(hecl::Format("model_righttitledeco%d", i + 1)))); - xa8_textpane_categories.push_back(static_cast(x8_frame.FindWidget(hecl::Format("textpane_category%d", i)))); - xc0_model_categories.push_back(static_cast(x8_frame.FindWidget(hecl::Format("model_category%d", i)))); - } + for (int i = 0; i < 5; ++i) { + xd8_textpane_titles.push_back( + static_cast(x8_frame.FindWidget(hecl::Format("textpane_title%d", i + 1)))); + xd8_textpane_titles.back()->TextSupport().SetText(u""); + x144_model_titles.push_back(static_cast(x8_frame.FindWidget(hecl::Format("model_title%d", i + 1)))); + x15c_model_righttitledecos.push_back( + static_cast(x8_frame.FindWidget(hecl::Format("model_righttitledeco%d", i + 1)))); + xa8_textpane_categories.push_back( + static_cast(x8_frame.FindWidget(hecl::Format("textpane_category%d", i)))); + xc0_model_categories.push_back(static_cast(x8_frame.FindWidget(hecl::Format("model_category%d", i)))); + } - for (int i=0 ; i<20 ; ++i) - xf0_imagePanes.push_back(static_cast(x8_frame.FindWidget(GetImagePaneName(i)))); + for (int i = 0; i < 20; ++i) + xf0_imagePanes.push_back(static_cast(x8_frame.FindWidget(GetImagePaneName(i)))); - x70_tablegroup_leftlog->SetUserSelection(0); - x84_tablegroup_rightlog->SetUserSelection(1); + x70_tablegroup_leftlog->SetUserSelection(0); + x84_tablegroup_rightlog->SetUserSelection(1); - x74_basewidget_leftguages->SetVisibility(false, ETraversalMode::Children); - x88_basewidget_rightguages->SetVisibility(false, ETraversalMode::Children); - x6c_basewidget_leftlog->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); + x74_basewidget_leftguages->SetVisibility(false, ETraversalMode::Children); + x88_basewidget_rightguages->SetVisibility(false, ETraversalMode::Children); + x6c_basewidget_leftlog->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); - if (IsRightLogDynamic()) - { - zeus::CColor color = g_tweakGuiColors->GetPauseItemAmberColor(); - color.a() = 0.5f; - UpdateRightLogColors(false, g_tweakGuiColors->GetPauseItemAmberColor(), color); - } - else - { - x80_basewidget_rightlog->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); - } - - for (CGuiObject* obj = x64_basewidget_bgframe->GetChildObject() ; obj ; obj = obj->GetNextSibling()) - static_cast(obj)->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); - - zeus::CColor dimColor = g_tweakGuiColors->GetPauseItemAmberColor(); - dimColor.a() = 0.2f; - x98_model_scrollleftup->SetColor(dimColor); - x9c_model_scrollleftdown->SetColor(dimColor); - xa0_model_scrollrightup->SetColor(dimColor); - xa4_model_scrollrightdown->SetColor(dimColor); - x90_model_textarrowtop->SetColor(dimColor); - x94_model_textarrowbottom->SetColor(dimColor); - - x18c_slidergroup_slider->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); - x190_tablegroup_double->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); - x194_tablegroup_triple->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); - - UpdateSideTable(x190_tablegroup_double); - UpdateSideTable(x194_tablegroup_triple); - UpdateSideTable(x70_tablegroup_leftlog); - UpdateSideTable(x84_tablegroup_rightlog); - - x18c_slidergroup_slider->SetVisibility(false, ETraversalMode::Children); - - x190_tablegroup_double->SetIsVisible(false); - x194_tablegroup_triple->SetIsVisible(false); - x190_tablegroup_double->SetVertical(false); - x194_tablegroup_triple->SetVertical(false); - - x70_tablegroup_leftlog->SetMenuAdvanceCallback( - std::bind(&CPauseScreenBase::OnLeftTableAdvance, this, std::placeholders::_1)); - x70_tablegroup_leftlog->SetMenuSelectionChangeCallback( - std::bind(&CPauseScreenBase::OnTableSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - x84_tablegroup_rightlog->SetMenuAdvanceCallback( - std::bind(&CPauseScreenBase::OnRightTableAdvance, this, std::placeholders::_1)); - x84_tablegroup_rightlog->SetMenuSelectionChangeCallback( - std::bind(&CPauseScreenBase::OnTableSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - x84_tablegroup_rightlog->SetMenuCancelCallback( - std::bind(&CPauseScreenBase::OnRightTableCancel, this, std::placeholders::_1)); - x18c_slidergroup_slider->SetSelectionChangedCallback({}); - x190_tablegroup_double->SetMenuSelectionChangeCallback({}); - x194_tablegroup_triple->SetMenuSelectionChangeCallback({}); -} - -bool CPauseScreenBase::IsReady() -{ - if (x198_24_ready) - return true; - x198_24_ready = VReady(); - if (x198_24_ready) - { - VActivate(); - ChangeMode(EMode::LeftTable); - UpdateSideTable(x70_tablegroup_leftlog); - UpdateRightTable(); - return true; - } - return false; -} - -void CPauseScreenBase::ChangeMode(EMode mode) -{ - if (x10_mode == mode) - return; - - EMode oldMode = x10_mode; + if (IsRightLogDynamic()) { zeus::CColor color = g_tweakGuiColors->GetPauseItemAmberColor(); - zeus::CColor colorDim = color; - colorDim.a() = 0.5f; + color.a() = 0.5f; + UpdateRightLogColors(false, g_tweakGuiColors->GetPauseItemAmberColor(), color); + } else { + x80_basewidget_rightlog->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); + } - switch (x10_mode) - { - case EMode::LeftTable: - x6c_basewidget_leftlog->SetColor(colorDim); - x70_tablegroup_leftlog->SetIsActive(false); - break; - case EMode::Invalid: - case EMode::RightTable: - if (IsRightLogDynamic()) - UpdateRightLogColors(false, color, colorDim); - else - x80_basewidget_rightlog->SetColor(colorDim); - x84_tablegroup_rightlog->SetIsActive(false); - break; - case EMode::TextScroll: - CSfxManager::SfxStart(SFXui_table_change_mode, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - break; - default: break; - } + for (CGuiObject* obj = x64_basewidget_bgframe->GetChildObject(); obj; obj = obj->GetNextSibling()) + static_cast(obj)->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); - x10_mode = mode; + zeus::CColor dimColor = g_tweakGuiColors->GetPauseItemAmberColor(); + dimColor.a() = 0.2f; + x98_model_scrollleftup->SetColor(dimColor); + x9c_model_scrollleftdown->SetColor(dimColor); + xa0_model_scrollrightup->SetColor(dimColor); + xa4_model_scrollrightdown->SetColor(dimColor); + x90_model_textarrowtop->SetColor(dimColor); + x94_model_textarrowbottom->SetColor(dimColor); - switch (x10_mode) - { - case EMode::LeftTable: - if (oldMode == EMode::RightTable) - CSfxManager::SfxStart(SFXui_table_change_mode, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x6c_basewidget_leftlog->SetColor(color); - x70_tablegroup_leftlog->SetIsActive(true); - UpdateSideTable(x70_tablegroup_leftlog); - x18_firstViewRightSel = 0; - x1c_rightSel = 0; - x84_tablegroup_rightlog->SetUserSelection(1); - UpdateSideTable(x84_tablegroup_rightlog); - break; - case EMode::RightTable: - if (IsRightLogDynamic()) - UpdateRightLogColors(true, color, colorDim); - else - x80_basewidget_rightlog->SetColor(colorDim); - x84_tablegroup_rightlog->SetIsActive(true); - UpdateSideTable(x84_tablegroup_rightlog); - break; - case EMode::TextScroll: - x6c_basewidget_leftlog->SetColor(colorDim); - if (IsRightLogDynamic()) - UpdateRightLogColors(true, color, colorDim); - else - x80_basewidget_rightlog->SetColor(colorDim); - x70_tablegroup_leftlog->SetIsActive(false); - x84_tablegroup_rightlog->SetIsActive(false); - break; - default: break; - } + x18c_slidergroup_slider->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); + x190_tablegroup_double->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); + x194_tablegroup_triple->SetColor(g_tweakGuiColors->GetPauseItemAmberColor()); - ChangedMode(oldMode); + UpdateSideTable(x190_tablegroup_double); + UpdateSideTable(x194_tablegroup_triple); + UpdateSideTable(x70_tablegroup_leftlog); + UpdateSideTable(x84_tablegroup_rightlog); + + x18c_slidergroup_slider->SetVisibility(false, ETraversalMode::Children); + + x190_tablegroup_double->SetIsVisible(false); + x194_tablegroup_triple->SetIsVisible(false); + x190_tablegroup_double->SetVertical(false); + x194_tablegroup_triple->SetVertical(false); + + x70_tablegroup_leftlog->SetMenuAdvanceCallback( + std::bind(&CPauseScreenBase::OnLeftTableAdvance, this, std::placeholders::_1)); + x70_tablegroup_leftlog->SetMenuSelectionChangeCallback( + std::bind(&CPauseScreenBase::OnTableSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x84_tablegroup_rightlog->SetMenuAdvanceCallback( + std::bind(&CPauseScreenBase::OnRightTableAdvance, this, std::placeholders::_1)); + x84_tablegroup_rightlog->SetMenuSelectionChangeCallback( + std::bind(&CPauseScreenBase::OnTableSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x84_tablegroup_rightlog->SetMenuCancelCallback( + std::bind(&CPauseScreenBase::OnRightTableCancel, this, std::placeholders::_1)); + x18c_slidergroup_slider->SetSelectionChangedCallback({}); + x190_tablegroup_double->SetMenuSelectionChangeCallback({}); + x194_tablegroup_triple->SetMenuSelectionChangeCallback({}); } -void CPauseScreenBase::UpdateSideTable(CGuiTableGroup* table) -{ - if (!table) - return; +bool CPauseScreenBase::IsReady() { + if (x198_24_ready) + return true; + x198_24_ready = VReady(); + if (x198_24_ready) { + VActivate(); + ChangeMode(EMode::LeftTable); + UpdateSideTable(x70_tablegroup_leftlog); + UpdateRightTable(); + return true; + } + return false; +} - zeus::CColor selColor = zeus::CColor::skWhite; - zeus::CColor deselColor = {1.f, 1.f, 1.f, 0.5f}; +void CPauseScreenBase::ChangeMode(EMode mode) { + if (x10_mode == mode) + return; - bool tableActive = true; - if (table == x84_tablegroup_rightlog && x10_mode != EMode::RightTable) - tableActive = false; + EMode oldMode = x10_mode; + zeus::CColor color = g_tweakGuiColors->GetPauseItemAmberColor(); + zeus::CColor colorDim = color; + colorDim.a() = 0.5f; - table->SetColors(selColor, deselColor); - - if (table == x84_tablegroup_rightlog) - { - int sel = x1c_rightSel - x18_firstViewRightSel; - x8c_model_righthighlight->SetLocalTransform( - x8c_model_righthighlight->GetTransform() * zeus::CTransform::Translate(0.f, 0.f, x38_highlightPitch * sel)); - x8c_model_righthighlight->SetVisibility(x10_mode == EMode::RightTable, ETraversalMode::Children); - int selInView = x1c_rightSel % 5; - if (IsRightLogDynamic()) - { - UpdateRightLogHighlight(tableActive, selInView, selColor, deselColor); - } - else - { - for (int i=0 ; iSetColor((i == selInView && tableActive) ? selColor : deselColor); - } - } + switch (x10_mode) { + case EMode::LeftTable: + x6c_basewidget_leftlog->SetColor(colorDim); + x70_tablegroup_leftlog->SetIsActive(false); + break; + case EMode::Invalid: + case EMode::RightTable: + if (IsRightLogDynamic()) + UpdateRightLogColors(false, color, colorDim); else - { - int sel = x70_tablegroup_leftlog->GetUserSelection(); - x78_model_lefthighlight->SetLocalTransform( - x78_model_lefthighlight->GetTransform() * zeus::CTransform::Translate(0.f, 0.f, x38_highlightPitch * sel)); - for (int i=0 ; iSetColor(i == sel ? selColor : deselColor); - } -} + x80_basewidget_rightlog->SetColor(colorDim); + x84_tablegroup_rightlog->SetIsActive(false); + break; + case EMode::TextScroll: + CSfxManager::SfxStart(SFXui_table_change_mode, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + default: + break; + } -void CPauseScreenBase::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) -{ - x198_27_canDraw = true; - x8_frame.Update(dt); - x14_alpha = std::min(2.f * dt + x14_alpha, 1.f); + x10_mode = mode; - u32 rightCount = GetRightTableCount(); - bool pulseRightUp = x10_mode == EMode::RightTable && x18_firstViewRightSel > 0; - bool pulseRightDown = x10_mode == EMode::RightTable && x18_firstViewRightSel + 5 < rightCount; - float rightUpT = pulseRightUp ? CGraphics::GetSecondsMod900() : 0.f; - float rightDownT = pulseRightDown ? CGraphics::GetSecondsMod900() : 0.f; - - zeus::CColor lowC = g_tweakGuiColors->GetPauseItemAmberColor(); - lowC.a() = 0.2f; - xa0_model_scrollrightup->SetColor( - zeus::CColor::lerp(lowC, g_tweakGuiColors->GetPauseItemAmberColor(), - zeus::clamp(0.f, (std::sin(5.f * rightUpT - M_PIF / 2.f) + 1.f) * 0.5f, 1.f))); - xa4_model_scrollrightdown->SetColor( - zeus::CColor::lerp(lowC, g_tweakGuiColors->GetPauseItemAmberColor(), - zeus::clamp(0.f, (std::sin(5.f * rightDownT - M_PIF / 2.f) + 1.f) * 0.5f, 1.f))); - - float textUpT = x198_28_pulseTextArrowTop ? CGraphics::GetSecondsMod900() : 0.f; - float textDownT = x198_29_pulseTextArrowBottom ? CGraphics::GetSecondsMod900() : 0.f; - - x90_model_textarrowtop->SetColor( - zeus::CColor::lerp(lowC, g_tweakGuiColors->GetPauseItemAmberColor(), - zeus::clamp(0.f, (std::sin(5.f * textUpT - M_PIF / 2.f) + 1.f) * 0.5f, 1.f))); - x94_model_textarrowbottom->SetColor( - zeus::CColor::lerp(lowC, g_tweakGuiColors->GetPauseItemAmberColor(), - zeus::clamp(0.f, (std::sin(5.f * textDownT - M_PIF / 2.f) + 1.f) * 0.5f, 1.f))); -} - -void CPauseScreenBase::ProcessControllerInput(const CFinalInput& input) -{ - x198_25_handledInput = false; - x8_frame.ProcessUserInput(input); -} - -void CPauseScreenBase::Draw(float mainAlpha, float frameAlpha, float yOff) -{ - zeus::CColor color = zeus::CColor::skWhite; - color.a() = mainAlpha * x14_alpha; - x60_basewidget_pivot->SetColor(color); - color.a() = frameAlpha; - x64_basewidget_bgframe->SetColor(color); - - CGuiWidgetDrawParms parms(1.f, zeus::CVector3f{0.f, 15.f * yOff, 0.f}); - x8_frame.Draw(parms); -} - -void CPauseScreenBase::UpdateRightTable() -{ + switch (x10_mode) { + case EMode::LeftTable: + if (oldMode == EMode::RightTable) + CSfxManager::SfxStart(SFXui_table_change_mode, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x6c_basewidget_leftlog->SetColor(color); + x70_tablegroup_leftlog->SetIsActive(true); + UpdateSideTable(x70_tablegroup_leftlog); x18_firstViewRightSel = 0; x1c_rightSel = 0; x84_tablegroup_rightlog->SetUserSelection(1); UpdateSideTable(x84_tablegroup_rightlog); -} - -void CPauseScreenBase::SetRightTableSelection(int oldSel, int newSel) -{ - int oldRightSel = x1c_rightSel; - x1c_rightSel = zeus::clamp(0, x1c_rightSel + (newSel - oldSel), int(GetRightTableCount()) - 1); - if (oldRightSel != x1c_rightSel) - CSfxManager::SfxStart(SFXui_table_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - - if (x1c_rightSel < x18_firstViewRightSel) - x18_firstViewRightSel = x1c_rightSel; - else if (x1c_rightSel >= x18_firstViewRightSel + 5) - x18_firstViewRightSel = x1c_rightSel - 4; - - x84_tablegroup_rightlog->SetUserSelection(x1c_rightSel + 1 - x18_firstViewRightSel); - UpdateSideTable(x84_tablegroup_rightlog); - RightTableSelectionChanged(oldSel, newSel); -} - -void CPauseScreenBase::OnLeftTableAdvance(CGuiTableGroup* caller) -{ - if (ShouldLeftTableAdvance()) - { - ChangeMode(EMode::RightTable); - x198_25_handledInput = true; - CSfxManager::SfxStart(SFXui_advance, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } -} - -void CPauseScreenBase::OnRightTableAdvance(CGuiTableGroup* caller) -{ - if (ShouldRightTableAdvance() && !x198_25_handledInput) - { - ChangeMode(EMode::TextScroll); - CSfxManager::SfxStart(SFXui_advance, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } -} - -void CPauseScreenBase::OnTableSelectionChange(CGuiTableGroup* caller, int oldSel) -{ - UpdateSideTable(caller); - if (x70_tablegroup_leftlog == caller) - { - CSfxManager::SfxStart(SFXui_table_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - UpdateRightTable(); - } + break; + case EMode::RightTable: + if (IsRightLogDynamic()) + UpdateRightLogColors(true, color, colorDim); else - { - SetRightTableSelection(oldSel, x84_tablegroup_rightlog->GetUserSelection()); + x80_basewidget_rightlog->SetColor(colorDim); + x84_tablegroup_rightlog->SetIsActive(true); + UpdateSideTable(x84_tablegroup_rightlog); + break; + case EMode::TextScroll: + x6c_basewidget_leftlog->SetColor(colorDim); + if (IsRightLogDynamic()) + UpdateRightLogColors(true, color, colorDim); + else + x80_basewidget_rightlog->SetColor(colorDim); + x70_tablegroup_leftlog->SetIsActive(false); + x84_tablegroup_rightlog->SetIsActive(false); + break; + default: + break; + } + + ChangedMode(oldMode); +} + +void CPauseScreenBase::UpdateSideTable(CGuiTableGroup* table) { + if (!table) + return; + + zeus::CColor selColor = zeus::CColor::skWhite; + zeus::CColor deselColor = {1.f, 1.f, 1.f, 0.5f}; + + bool tableActive = true; + if (table == x84_tablegroup_rightlog && x10_mode != EMode::RightTable) + tableActive = false; + + table->SetColors(selColor, deselColor); + + if (table == x84_tablegroup_rightlog) { + int sel = x1c_rightSel - x18_firstViewRightSel; + x8c_model_righthighlight->SetLocalTransform(x8c_model_righthighlight->GetTransform() * + zeus::CTransform::Translate(0.f, 0.f, x38_highlightPitch * sel)); + x8c_model_righthighlight->SetVisibility(x10_mode == EMode::RightTable, ETraversalMode::Children); + int selInView = x1c_rightSel % 5; + if (IsRightLogDynamic()) { + UpdateRightLogHighlight(tableActive, selInView, selColor, deselColor); + } else { + for (int i = 0; i < x144_model_titles.size(); ++i) + x144_model_titles[i]->SetColor((i == selInView && tableActive) ? selColor : deselColor); } + } else { + int sel = x70_tablegroup_leftlog->GetUserSelection(); + x78_model_lefthighlight->SetLocalTransform(x78_model_lefthighlight->GetTransform() * + zeus::CTransform::Translate(0.f, 0.f, x38_highlightPitch * sel)); + for (int i = 0; i < xc0_model_categories.size(); ++i) + xc0_model_categories[i]->SetColor(i == sel ? selColor : deselColor); + } } -void CPauseScreenBase::OnRightTableCancel(CGuiTableGroup* caller) -{ - ChangeMode(EMode::LeftTable); +void CPauseScreenBase::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) { + x198_27_canDraw = true; + x8_frame.Update(dt); + x14_alpha = std::min(2.f * dt + x14_alpha, 1.f); + + u32 rightCount = GetRightTableCount(); + bool pulseRightUp = x10_mode == EMode::RightTable && x18_firstViewRightSel > 0; + bool pulseRightDown = x10_mode == EMode::RightTable && x18_firstViewRightSel + 5 < rightCount; + float rightUpT = pulseRightUp ? CGraphics::GetSecondsMod900() : 0.f; + float rightDownT = pulseRightDown ? CGraphics::GetSecondsMod900() : 0.f; + + zeus::CColor lowC = g_tweakGuiColors->GetPauseItemAmberColor(); + lowC.a() = 0.2f; + xa0_model_scrollrightup->SetColor( + zeus::CColor::lerp(lowC, g_tweakGuiColors->GetPauseItemAmberColor(), + zeus::clamp(0.f, (std::sin(5.f * rightUpT - M_PIF / 2.f) + 1.f) * 0.5f, 1.f))); + xa4_model_scrollrightdown->SetColor( + zeus::CColor::lerp(lowC, g_tweakGuiColors->GetPauseItemAmberColor(), + zeus::clamp(0.f, (std::sin(5.f * rightDownT - M_PIF / 2.f) + 1.f) * 0.5f, 1.f))); + + float textUpT = x198_28_pulseTextArrowTop ? CGraphics::GetSecondsMod900() : 0.f; + float textDownT = x198_29_pulseTextArrowBottom ? CGraphics::GetSecondsMod900() : 0.f; + + x90_model_textarrowtop->SetColor( + zeus::CColor::lerp(lowC, g_tweakGuiColors->GetPauseItemAmberColor(), + zeus::clamp(0.f, (std::sin(5.f * textUpT - M_PIF / 2.f) + 1.f) * 0.5f, 1.f))); + x94_model_textarrowbottom->SetColor( + zeus::CColor::lerp(lowC, g_tweakGuiColors->GetPauseItemAmberColor(), + zeus::clamp(0.f, (std::sin(5.f * textDownT - M_PIF / 2.f) + 1.f) * 0.5f, 1.f))); } -static const char* PaneSuffixes[] = -{ - "0", - "1", - "2", - "3", - "01", - "12", - "23", - "012", - "123", - "0123", - "4", - "5", - "6", - "7", - "45", - "56", - "67", - "456", - "567", - "4567" -}; - -std::string CPauseScreenBase::GetImagePaneName(u32 i) -{ - return hecl::Format("imagepane_pane%s", PaneSuffixes[i]); +void CPauseScreenBase::ProcessControllerInput(const CFinalInput& input) { + x198_25_handledInput = false; + x8_frame.ProcessUserInput(input); } +void CPauseScreenBase::Draw(float mainAlpha, float frameAlpha, float yOff) { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = mainAlpha * x14_alpha; + x60_basewidget_pivot->SetColor(color); + color.a() = frameAlpha; + x64_basewidget_bgframe->SetColor(color); + + CGuiWidgetDrawParms parms(1.f, zeus::CVector3f{0.f, 15.f * yOff, 0.f}); + x8_frame.Draw(parms); } + +void CPauseScreenBase::UpdateRightTable() { + x18_firstViewRightSel = 0; + x1c_rightSel = 0; + x84_tablegroup_rightlog->SetUserSelection(1); + UpdateSideTable(x84_tablegroup_rightlog); +} + +void CPauseScreenBase::SetRightTableSelection(int oldSel, int newSel) { + int oldRightSel = x1c_rightSel; + x1c_rightSel = zeus::clamp(0, x1c_rightSel + (newSel - oldSel), int(GetRightTableCount()) - 1); + if (oldRightSel != x1c_rightSel) + CSfxManager::SfxStart(SFXui_table_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + + if (x1c_rightSel < x18_firstViewRightSel) + x18_firstViewRightSel = x1c_rightSel; + else if (x1c_rightSel >= x18_firstViewRightSel + 5) + x18_firstViewRightSel = x1c_rightSel - 4; + + x84_tablegroup_rightlog->SetUserSelection(x1c_rightSel + 1 - x18_firstViewRightSel); + UpdateSideTable(x84_tablegroup_rightlog); + RightTableSelectionChanged(oldSel, newSel); +} + +void CPauseScreenBase::OnLeftTableAdvance(CGuiTableGroup* caller) { + if (ShouldLeftTableAdvance()) { + ChangeMode(EMode::RightTable); + x198_25_handledInput = true; + CSfxManager::SfxStart(SFXui_advance, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } +} + +void CPauseScreenBase::OnRightTableAdvance(CGuiTableGroup* caller) { + if (ShouldRightTableAdvance() && !x198_25_handledInput) { + ChangeMode(EMode::TextScroll); + CSfxManager::SfxStart(SFXui_advance, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } +} + +void CPauseScreenBase::OnTableSelectionChange(CGuiTableGroup* caller, int oldSel) { + UpdateSideTable(caller); + if (x70_tablegroup_leftlog == caller) { + CSfxManager::SfxStart(SFXui_table_selection_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + UpdateRightTable(); + } else { + SetRightTableSelection(oldSel, x84_tablegroup_rightlog->GetUserSelection()); + } +} + +void CPauseScreenBase::OnRightTableCancel(CGuiTableGroup* caller) { ChangeMode(EMode::LeftTable); } + +static const char* PaneSuffixes[] = {"0", "1", "2", "3", "01", "12", "23", "012", "123", "0123", + "4", "5", "6", "7", "45", "56", "67", "456", "567", "4567"}; + +std::string CPauseScreenBase::GetImagePaneName(u32 i) { return hecl::Format("imagepane_pane%s", PaneSuffixes[i]); } + +} // namespace urde::MP1 diff --git a/Runtime/MP1/CPauseScreenBase.hpp b/Runtime/MP1/CPauseScreenBase.hpp index c8a6321d8..e0de48a3a 100644 --- a/Runtime/MP1/CPauseScreenBase.hpp +++ b/Runtime/MP1/CPauseScreenBase.hpp @@ -4,8 +4,7 @@ #include "zeus/CVector3f.hpp" #include "GuiSys/CGuiFrame.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CGuiWidget; class CGuiTableGroup; @@ -17,121 +16,112 @@ class CStringTable; class CRandom16; class CArchitectureQueue; -namespace MP1 -{ +namespace MP1 { -class CPauseScreenBase -{ +class CPauseScreenBase { public: - enum class EMode - { - Invalid = -1, - LeftTable = 0, - RightTable = 1, - TextScroll = 2 - }; + enum class EMode { Invalid = -1, LeftTable = 0, RightTable = 1, TextScroll = 2 }; + protected: - const CStateManager& x4_mgr; - CGuiFrame& x8_frame; - const CStringTable& xc_pauseStrg; - EMode x10_mode = EMode::Invalid; - float x14_alpha = 0.f; - int x18_firstViewRightSel = 0; - int x1c_rightSel = 0; - zeus::CVector3f x20_; - zeus::CVector3f x2c_rightTableStart; - float x38_highlightPitch = 0.f; - zeus::CVector3f x3c_sliderStart; - zeus::CVector3f x48_tableDoubleStart; - zeus::CVector3f x54_tableTripleStart; - CGuiWidget* x60_basewidget_pivot; - CGuiWidget* x64_basewidget_bgframe; - CGuiWidget* x68_basewidget_leftside = nullptr; - CGuiWidget* x6c_basewidget_leftlog = nullptr; - CGuiTableGroup* x70_tablegroup_leftlog = nullptr; - CGuiWidget* x74_basewidget_leftguages = nullptr; - CGuiModel* x78_model_lefthighlight = nullptr; - CGuiWidget* x7c_basewidget_rightside = nullptr; - CGuiWidget* x80_basewidget_rightlog = nullptr; - CGuiTableGroup* x84_tablegroup_rightlog = nullptr; - CGuiWidget* x88_basewidget_rightguages = nullptr; - CGuiModel* x8c_model_righthighlight = nullptr; - CGuiModel* x90_model_textarrowtop; - CGuiModel* x94_model_textarrowbottom; - CGuiModel* x98_model_scrollleftup; - CGuiModel* x9c_model_scrollleftdown; - CGuiModel* xa0_model_scrollrightup; - CGuiModel* xa4_model_scrollrightdown; - rstl::reserved_vector xa8_textpane_categories; - rstl::reserved_vector xc0_model_categories; - rstl::reserved_vector xd8_textpane_titles; - rstl::reserved_vector xf0_imagePanes; - rstl::reserved_vector x144_model_titles; - rstl::reserved_vector x15c_model_righttitledecos; - CGuiTextPane* x174_textpane_body = nullptr; - CGuiTextPane* x178_textpane_title = nullptr; - CGuiModel* x17c_model_textalpha; - CGuiWidget* x180_basewidget_yicon = nullptr; - CGuiTextPane* x184_textpane_yicon = nullptr; - CGuiTextPane* x188_textpane_ytext = nullptr; - CGuiSliderGroup* x18c_slidergroup_slider = nullptr; - CGuiTableGroup* x190_tablegroup_double = nullptr; - CGuiTableGroup* x194_tablegroup_triple = nullptr; - union - { - struct - { - bool x198_24_ready : 1; - bool x198_25_handledInput : 1; - bool x198_26_exitPauseScreen : 1; - bool x198_27_canDraw : 1; - bool x198_28_pulseTextArrowTop : 1; - bool x198_29_pulseTextArrowBottom : 1; - }; - u32 _dummy = 0; + const CStateManager& x4_mgr; + CGuiFrame& x8_frame; + const CStringTable& xc_pauseStrg; + EMode x10_mode = EMode::Invalid; + float x14_alpha = 0.f; + int x18_firstViewRightSel = 0; + int x1c_rightSel = 0; + zeus::CVector3f x20_; + zeus::CVector3f x2c_rightTableStart; + float x38_highlightPitch = 0.f; + zeus::CVector3f x3c_sliderStart; + zeus::CVector3f x48_tableDoubleStart; + zeus::CVector3f x54_tableTripleStart; + CGuiWidget* x60_basewidget_pivot; + CGuiWidget* x64_basewidget_bgframe; + CGuiWidget* x68_basewidget_leftside = nullptr; + CGuiWidget* x6c_basewidget_leftlog = nullptr; + CGuiTableGroup* x70_tablegroup_leftlog = nullptr; + CGuiWidget* x74_basewidget_leftguages = nullptr; + CGuiModel* x78_model_lefthighlight = nullptr; + CGuiWidget* x7c_basewidget_rightside = nullptr; + CGuiWidget* x80_basewidget_rightlog = nullptr; + CGuiTableGroup* x84_tablegroup_rightlog = nullptr; + CGuiWidget* x88_basewidget_rightguages = nullptr; + CGuiModel* x8c_model_righthighlight = nullptr; + CGuiModel* x90_model_textarrowtop; + CGuiModel* x94_model_textarrowbottom; + CGuiModel* x98_model_scrollleftup; + CGuiModel* x9c_model_scrollleftdown; + CGuiModel* xa0_model_scrollrightup; + CGuiModel* xa4_model_scrollrightdown; + rstl::reserved_vector xa8_textpane_categories; + rstl::reserved_vector xc0_model_categories; + rstl::reserved_vector xd8_textpane_titles; + rstl::reserved_vector xf0_imagePanes; + rstl::reserved_vector x144_model_titles; + rstl::reserved_vector x15c_model_righttitledecos; + CGuiTextPane* x174_textpane_body = nullptr; + CGuiTextPane* x178_textpane_title = nullptr; + CGuiModel* x17c_model_textalpha; + CGuiWidget* x180_basewidget_yicon = nullptr; + CGuiTextPane* x184_textpane_yicon = nullptr; + CGuiTextPane* x188_textpane_ytext = nullptr; + CGuiSliderGroup* x18c_slidergroup_slider = nullptr; + CGuiTableGroup* x190_tablegroup_double = nullptr; + CGuiTableGroup* x194_tablegroup_triple = nullptr; + union { + struct { + bool x198_24_ready : 1; + bool x198_25_handledInput : 1; + bool x198_26_exitPauseScreen : 1; + bool x198_27_canDraw : 1; + bool x198_28_pulseTextArrowTop : 1; + bool x198_29_pulseTextArrowBottom : 1; }; - void InitializeFrameGlue(); - void ChangeMode(EMode mode); - void UpdateSideTable(CGuiTableGroup* table); - void SetRightTableSelection(int oldSel, int newSel); + u32 _dummy = 0; + }; + void InitializeFrameGlue(); + void ChangeMode(EMode mode); + void UpdateSideTable(CGuiTableGroup* table); + void SetRightTableSelection(int oldSel, int newSel); - void OnLeftTableAdvance(CGuiTableGroup* caller); - void OnRightTableAdvance(CGuiTableGroup* caller); - void OnTableSelectionChange(CGuiTableGroup* caller, int oldSel); - void OnRightTableCancel(CGuiTableGroup* caller); + void OnLeftTableAdvance(CGuiTableGroup* caller); + void OnRightTableAdvance(CGuiTableGroup* caller); + void OnTableSelectionChange(CGuiTableGroup* caller, int oldSel); + void OnRightTableCancel(CGuiTableGroup* caller); public: - static std::string GetImagePaneName(u32 i); + static std::string GetImagePaneName(u32 i); - CPauseScreenBase(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg); + CPauseScreenBase(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg); - bool ShouldExitPauseScreen() const { return x198_26_exitPauseScreen; } - bool IsReady(); - bool CanDraw() const { return x198_27_canDraw; } - EMode GetMode() const { return x10_mode; } - float GetAlpha() const { return x14_alpha; } + bool ShouldExitPauseScreen() const { return x198_26_exitPauseScreen; } + bool IsReady(); + bool CanDraw() const { return x198_27_canDraw; } + EMode GetMode() const { return x10_mode; } + float GetAlpha() const { return x14_alpha; } - virtual ~CPauseScreenBase() = default; - virtual bool InputDisabled() const { return false; } - virtual void TransitioningAway() {} - virtual void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); - virtual void Touch() {} - virtual void ProcessControllerInput(const CFinalInput& input); - virtual void Draw(float transInterp, float totalAlpha, float yOff); - virtual float GetCameraYBias() const { return 0.f; } - virtual bool VReady() const=0; - virtual void VActivate()=0; - virtual void RightTableSelectionChanged(int oldSel, int newSel) {} - virtual void ChangedMode(EMode oldMode) {} - virtual void UpdateRightTable(); - virtual bool ShouldLeftTableAdvance() const { return true; } - virtual bool ShouldRightTableAdvance() const { return true; } - virtual u32 GetRightTableCount() const=0; - virtual bool IsRightLogDynamic() const { return false; } - virtual void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor) {} - virtual void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor) {} + virtual ~CPauseScreenBase() = default; + virtual bool InputDisabled() const { return false; } + virtual void TransitioningAway() {} + virtual void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); + virtual void Touch() {} + virtual void ProcessControllerInput(const CFinalInput& input); + virtual void Draw(float transInterp, float totalAlpha, float yOff); + virtual float GetCameraYBias() const { return 0.f; } + virtual bool VReady() const = 0; + virtual void VActivate() = 0; + virtual void RightTableSelectionChanged(int oldSel, int newSel) {} + virtual void ChangedMode(EMode oldMode) {} + virtual void UpdateRightTable(); + virtual bool ShouldLeftTableAdvance() const { return true; } + virtual bool ShouldRightTableAdvance() const { return true; } + virtual u32 GetRightTableCount() const = 0; + virtual bool IsRightLogDynamic() const { return false; } + virtual void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor) {} + virtual void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, + const zeus::CColor& inactiveColor) {} }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CPauseScreenBlur.cpp b/Runtime/MP1/CPauseScreenBlur.cpp index 9839cd00c..db3a7b749 100644 --- a/Runtime/MP1/CPauseScreenBlur.cpp +++ b/Runtime/MP1/CPauseScreenBlur.cpp @@ -3,119 +3,101 @@ #include "GameGlobalObjects.hpp" #include "Audio/CSfxManager.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CPauseScreenBlur::CPauseScreenBlur() -: x4_mapLightQuarter(g_SimplePool->GetObj("TXTR_MapLightQuarter")) -{ +CPauseScreenBlur::CPauseScreenBlur() : x4_mapLightQuarter(g_SimplePool->GetObj("TXTR_MapLightQuarter")) { + x50_25_gameDraw = true; +} + +void CPauseScreenBlur::OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr) { + switch (state) { + case EInGameGuiState::Zero: + case EInGameGuiState::InGame: + SetState(EState::InGame); + break; + case EInGameGuiState::MapScreen: + SetState(EState::MapScreen); + break; + case EInGameGuiState::PauseSaveGame: + SetState(EState::SaveGame); + break; + case EInGameGuiState::PauseHUDMessage: + SetState(EState::HUDMessage); + break; + case EInGameGuiState::PauseGame: + case EInGameGuiState::PauseLogBook: + SetState(EState::Pause); + break; + default: + break; + } +} + +void CPauseScreenBlur::SetState(EState state) { + if (x10_prevState == EState::InGame && state != EState::InGame) { + CSfxManager::SetChannel(CSfxManager::ESfxChannels::PauseScreen); + if (state == EState::HUDMessage) + CSfxManager::SfxStart(SFXui_into_hud_message, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + else if (state == EState::MapScreen) + CSfxManager::SfxStart(SFXui_into_map_screen, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x18_blurAmt = FLT_EPSILON; + } + + if (state == EState::InGame && (x10_prevState != EState::InGame || x14_nextState != EState::InGame)) { + CSfxManager::SetChannel(CSfxManager::ESfxChannels::Game); + if (x10_prevState == EState::HUDMessage) + CSfxManager::SfxStart(SFXui_outof_hud_message, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + else if (x10_prevState == EState::MapScreen) + CSfxManager::SfxStart(SFXui_outof_map_screen, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x18_blurAmt = -1.f; + } + + x14_nextState = state; +} + +void CPauseScreenBlur::OnBlurComplete(bool b) { + if (x14_nextState == EState::InGame && !b) + return; + x10_prevState = x14_nextState; + if (x10_prevState == EState::InGame) x50_25_gameDraw = true; } -void CPauseScreenBlur::OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr) -{ - switch (state) - { - case EInGameGuiState::Zero: - case EInGameGuiState::InGame: - SetState(EState::InGame); - break; - case EInGameGuiState::MapScreen: - SetState(EState::MapScreen); - break; - case EInGameGuiState::PauseSaveGame: - SetState(EState::SaveGame); - break; - case EInGameGuiState::PauseHUDMessage: - SetState(EState::HUDMessage); - break; - case EInGameGuiState::PauseGame: - case EInGameGuiState::PauseLogBook: - SetState(EState::Pause); - break; - default: break; - } +void CPauseScreenBlur::Update(float dt, const CStateManager& stateMgr, bool b) { + if (x10_prevState == x14_nextState) + return; + + if (x18_blurAmt < 0.f) + x18_blurAmt = std::min(0.f, 2.f * dt + x18_blurAmt); + else + x18_blurAmt = std::min(1.f, 2.f * dt + x18_blurAmt); + + if (x18_blurAmt == 0.f || x18_blurAmt == 1.f) + OnBlurComplete(b); + + if (x18_blurAmt == 0.f && b) { + x1c_camBlur.DisableBlur(0.f); + } else { + x1c_camBlur.SetBlur(EBlurType::HiBlur, g_tweakGui->GetPauseBlurFactor() * std::fabs(x18_blurAmt), 0.f); + x50_24_blurring = true; + } } -void CPauseScreenBlur::SetState(EState state) -{ - if (x10_prevState == EState::InGame && state != EState::InGame) - { - CSfxManager::SetChannel(CSfxManager::ESfxChannels::PauseScreen); - if (state == EState::HUDMessage) - CSfxManager::SfxStart(SFXui_into_hud_message, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - else if (state == EState::MapScreen) - CSfxManager::SfxStart(SFXui_into_map_screen, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x18_blurAmt = FLT_EPSILON; - } +void CPauseScreenBlur::Draw(const CStateManager&) const { + const_cast(x1c_camBlur).Draw(true); + float t = std::fabs(x18_blurAmt); + if (x1c_camBlur.GetCurrType() != EBlurType::NoBlur) { + zeus::CColor filterColor = + zeus::CColor::lerp(zeus::CColor::skWhite, g_tweakGuiColors->GetPauseBlurFilterColor(), t); + const_cast(m_quarterFilter).DrawFilter(EFilterShape::FullscreenQuarters, filterColor, t); + zeus::CColor scanLinesColor = zeus::CColor::lerp(zeus::CColor::skWhite, zeus::CColor(0.75f, 1.f), t); + const_cast(m_linesFilter).draw(scanLinesColor); + } - if (state == EState::InGame && (x10_prevState != EState::InGame || x14_nextState != EState::InGame)) - { - CSfxManager::SetChannel(CSfxManager::ESfxChannels::Game); - if (x10_prevState == EState::HUDMessage) - CSfxManager::SfxStart(SFXui_outof_hud_message, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - else if (x10_prevState == EState::MapScreen) - CSfxManager::SfxStart(SFXui_outof_map_screen, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x18_blurAmt = -1.f; - } - - x14_nextState = state; + if (x50_24_blurring /*&& x1c_camBlur.x2d_noPersistentCopy*/) { + const_cast(this)->x50_24_blurring = false; + const_cast(this)->x50_25_gameDraw = false; + } } -void CPauseScreenBlur::OnBlurComplete(bool b) -{ - if (x14_nextState == EState::InGame && !b) - return; - x10_prevState = x14_nextState; - if (x10_prevState == EState::InGame) - x50_25_gameDraw = true; -} - -void CPauseScreenBlur::Update(float dt, const CStateManager& stateMgr, bool b) -{ - if (x10_prevState == x14_nextState) - return; - - if (x18_blurAmt < 0.f) - x18_blurAmt = std::min(0.f, 2.f * dt + x18_blurAmt); - else - x18_blurAmt = std::min(1.f, 2.f * dt + x18_blurAmt); - - if (x18_blurAmt == 0.f || x18_blurAmt == 1.f) - OnBlurComplete(b); - - if (x18_blurAmt == 0.f && b) - { - x1c_camBlur.DisableBlur(0.f); - } - else - { - x1c_camBlur.SetBlur(EBlurType::HiBlur, - g_tweakGui->GetPauseBlurFactor() * std::fabs(x18_blurAmt), 0.f); - x50_24_blurring = true; - } -} - -void CPauseScreenBlur::Draw(const CStateManager&) const -{ - const_cast(x1c_camBlur).Draw(true); - float t = std::fabs(x18_blurAmt); - if (x1c_camBlur.GetCurrType() != EBlurType::NoBlur) - { - zeus::CColor filterColor = - zeus::CColor::lerp(zeus::CColor::skWhite, g_tweakGuiColors->GetPauseBlurFilterColor(), t); - const_cast(m_quarterFilter).DrawFilter(EFilterShape::FullscreenQuarters, - filterColor, t); - zeus::CColor scanLinesColor = - zeus::CColor::lerp(zeus::CColor::skWhite, zeus::CColor(0.75f, 1.f), t); - const_cast(m_linesFilter).draw(scanLinesColor); - } - - if (x50_24_blurring /*&& x1c_camBlur.x2d_noPersistentCopy*/) - { - const_cast(this)->x50_24_blurring = false; - const_cast(this)->x50_25_gameDraw = false; - } -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CPauseScreenBlur.hpp b/Runtime/MP1/CPauseScreenBlur.hpp index bfd10b62c..54c3a7d6b 100644 --- a/Runtime/MP1/CPauseScreenBlur.hpp +++ b/Runtime/MP1/CPauseScreenBlur.hpp @@ -7,54 +7,41 @@ #include "Graphics/Shaders/CTexturedQuadFilter.hpp" #include "Graphics/Shaders/CScanLinesFilter.hpp" -namespace urde -{ +namespace urde { class CStateManager; -namespace MP1 -{ +namespace MP1 { -class CPauseScreenBlur -{ - enum class EState - { - InGame, - MapScreen, - SaveGame, - HUDMessage, - Pause +class CPauseScreenBlur { + enum class EState { InGame, MapScreen, SaveGame, HUDMessage, Pause }; + + TLockedToken x4_mapLightQuarter; + EState x10_prevState = EState::InGame; + EState x14_nextState = EState::InGame; + float x18_blurAmt = 0.f; + CCameraBlurPass x1c_camBlur; + CTexturedQuadFilter m_quarterFilter = {EFilterType::Multiply, x4_mapLightQuarter}; + CScanLinesFilterEven m_linesFilter = {EFilterType::Multiply}; + + union { + struct { + bool x50_24_blurring : 1; + bool x50_25_gameDraw : 1; }; - - TLockedToken x4_mapLightQuarter; - EState x10_prevState = EState::InGame; - EState x14_nextState = EState::InGame; - float x18_blurAmt = 0.f; - CCameraBlurPass x1c_camBlur; - CTexturedQuadFilter m_quarterFilter = { EFilterType::Multiply, x4_mapLightQuarter }; - CScanLinesFilterEven m_linesFilter = { EFilterType::Multiply }; - - union - { - struct - { - bool x50_24_blurring : 1; - bool x50_25_gameDraw : 1; - }; - u32 _dummy = 0; - }; - void OnBlurComplete(bool); - void SetState(EState state); + u32 _dummy = 0; + }; + void OnBlurComplete(bool); + void SetState(EState state); public: - CPauseScreenBlur(); - void OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr); - bool IsGameDraw() const { return x50_25_gameDraw; } - void Update(float dt, const CStateManager& stateMgr, bool); - void Draw(const CStateManager& stateMgr) const; - float GetBlurAmt() const { return std::fabs(x18_blurAmt); } - bool IsNotTransitioning() const { return x10_prevState == x14_nextState; } + CPauseScreenBlur(); + void OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr); + bool IsGameDraw() const { return x50_25_gameDraw; } + void Update(float dt, const CStateManager& stateMgr, bool); + void Draw(const CStateManager& stateMgr) const; + float GetBlurAmt() const { return std::fabs(x18_blurAmt); } + bool IsNotTransitioning() const { return x10_prevState == x14_nextState; } }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CPlayMovie.cpp b/Runtime/MP1/CPlayMovie.cpp index ddf5adcd5..0b8c8dd77 100644 --- a/Runtime/MP1/CPlayMovie.cpp +++ b/Runtime/MP1/CPlayMovie.cpp @@ -1,30 +1,15 @@ #include "CPlayMovie.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -const char* kMovies[] = -{ - "Video/wingame.thp", - "Video/wingame_best.thp", - "Video/wingame_best.thp", - "Video/losegame.thp", - "Video/05_tallonText.thp", - "Video/AfterCredits.thp", - "Video/SpecialEnding.thp", - "Video/creditBG.thp" -}; +const char* kMovies[] = {"Video/wingame.thp", "Video/wingame_best.thp", "Video/wingame_best.thp", + "Video/losegame.thp", "Video/05_tallonText.thp", "Video/AfterCredits.thp", + "Video/SpecialEnding.thp", "Video/creditBG.thp"}; -bool CPlayMovie::IsResultsScreen(EWhichMovie which) -{ - return int(which) <= 2; +bool CPlayMovie::IsResultsScreen(EWhichMovie which) { return int(which) <= 2; } + +CPlayMovie::CPlayMovie(EWhichMovie which) : CPlayMovieBase("CPlayMovie", kMovies[int(which)]), x18_which(which) { + (void)x18_which; } -CPlayMovie::CPlayMovie(EWhichMovie which) -: CPlayMovieBase("CPlayMovie", kMovies[int(which)]), x18_which(which) -{ - (void)x18_which; -} - - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CPlayMovie.hpp b/Runtime/MP1/CPlayMovie.hpp index 515d12fa0..9cb030b33 100644 --- a/Runtime/MP1/CPlayMovie.hpp +++ b/Runtime/MP1/CPlayMovie.hpp @@ -3,40 +3,36 @@ #include "CPlayMovieBase.hpp" #include "RetroTypes.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class CPlayMovie : public CPlayMovieBase -{ +class CPlayMovie : public CPlayMovieBase { public: - enum class EWhichMovie - { - WinGameBad, - WinGameGood, - WinGameBest, - LoseGame, - TalonTest, - AfterCredits, - SpecialEnding, - CreditBG - }; + enum class EWhichMovie { + WinGameBad, + WinGameGood, + WinGameBest, + LoseGame, + TalonTest, + AfterCredits, + SpecialEnding, + CreditBG + }; + private: - EWhichMovie x18_which; - union - { - struct - { - bool x78_24_ : 1; - bool x78_25_ : 1; - bool x78_26_resultsScreen : 1; - bool x78_27_ : 1; - }; - u16 _dummy = 0; + EWhichMovie x18_which; + union { + struct { + bool x78_24_ : 1; + bool x78_25_ : 1; + bool x78_26_resultsScreen : 1; + bool x78_27_ : 1; }; - static bool IsResultsScreen(EWhichMovie which); + u16 _dummy = 0; + }; + static bool IsResultsScreen(EWhichMovie which); + public: - CPlayMovie(EWhichMovie which); + CPlayMovie(EWhichMovie which); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CPlayerVisor.cpp b/Runtime/MP1/CPlayerVisor.cpp index b4e43f1e1..4026b28f1 100644 --- a/Runtime/MP1/CPlayerVisor.cpp +++ b/Runtime/MP1/CPlayerVisor.cpp @@ -10,323 +10,282 @@ #include "GuiSys/CCompoundTargetReticle.hpp" #include "GuiSys/CTargetingManager.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CPlayerVisor::CPlayerVisor(CStateManager&) -: x108_newScanPane(EFilterType::Blend, CGraphics::g_SpareTexture.get()) -{ - x25_24_visorTransitioning = false; - x25_25_ = false; - xcc_scanFrameCorner = g_SimplePool->GetObj("CMDL_ScanFrameCorner"); - xd8_scanFrameCenterSide = g_SimplePool->GetObj("CMDL_ScanFrameCenterSide"); - xe4_scanFrameCenterTop = g_SimplePool->GetObj("CMDL_ScanFrameCenterTop"); - xf0_scanFrameStretchSide = g_SimplePool->GetObj("CMDL_ScanFrameStretchSide"); - xfc_scanFrameStretchTop = g_SimplePool->GetObj("CMDL_ScanFrameStretchTop"); - //x108_newScanPane = g_SimplePool->GetObj("CMDL_NewScanPane"); - x114_scanShield = g_SimplePool->GetObj("CMDL_ScanShield"); - x124_scanIconNoncritical = g_SimplePool->GetObj("CMDL_ScanIconNoncritical"); - x130_scanIconCritical = g_SimplePool->GetObj("CMDL_ScanIconCritical"); - x13c_scanTargets.resize(64); - x540_xrayPalette = g_SimplePool->GetObj("TXTR_XRayPalette"); - x0_scanWindowSizes.push_back({}); - x0_scanWindowSizes.push_back({g_tweakGui->GetScanWindowIdleWidth(), g_tweakGui->GetScanWindowIdleHeight()}); - x0_scanWindowSizes.push_back({g_tweakGui->GetScanWindowActiveWidth(), g_tweakGui->GetScanWindowActiveHeight()}); +CPlayerVisor::CPlayerVisor(CStateManager&) : x108_newScanPane(EFilterType::Blend, CGraphics::g_SpareTexture.get()) { + x25_24_visorTransitioning = false; + x25_25_ = false; + xcc_scanFrameCorner = g_SimplePool->GetObj("CMDL_ScanFrameCorner"); + xd8_scanFrameCenterSide = g_SimplePool->GetObj("CMDL_ScanFrameCenterSide"); + xe4_scanFrameCenterTop = g_SimplePool->GetObj("CMDL_ScanFrameCenterTop"); + xf0_scanFrameStretchSide = g_SimplePool->GetObj("CMDL_ScanFrameStretchSide"); + xfc_scanFrameStretchTop = g_SimplePool->GetObj("CMDL_ScanFrameStretchTop"); + // x108_newScanPane = g_SimplePool->GetObj("CMDL_NewScanPane"); + x114_scanShield = g_SimplePool->GetObj("CMDL_ScanShield"); + x124_scanIconNoncritical = g_SimplePool->GetObj("CMDL_ScanIconNoncritical"); + x130_scanIconCritical = g_SimplePool->GetObj("CMDL_ScanIconCritical"); + x13c_scanTargets.resize(64); + x540_xrayPalette = g_SimplePool->GetObj("TXTR_XRayPalette"); + x0_scanWindowSizes.push_back({}); + x0_scanWindowSizes.push_back({g_tweakGui->GetScanWindowIdleWidth(), g_tweakGui->GetScanWindowIdleHeight()}); + x0_scanWindowSizes.push_back({g_tweakGui->GetScanWindowActiveWidth(), g_tweakGui->GetScanWindowActiveHeight()}); } -CPlayerVisor::~CPlayerVisor() -{ - CSfxManager::SfxStop(x5c_visorLoopSfx); +CPlayerVisor::~CPlayerVisor() { + CSfxManager::SfxStop(x5c_visorLoopSfx); + CSfxManager::SfxStop(x60_scanningLoopSfx); +} + +int CPlayerVisor::FindEmptyInactiveScanTarget() const { + for (int i = 0; i < x13c_scanTargets.size(); ++i) { + const SScanTarget& tgt = x13c_scanTargets[i]; + if (tgt.x4_timer == 0.f) + return i; + } + return -1; +} + +int CPlayerVisor::FindCachedInactiveScanTarget(TUniqueId uid) const { + for (int i = 0; i < x13c_scanTargets.size(); ++i) { + const SScanTarget& tgt = x13c_scanTargets[i]; + if (tgt.x0_objId == uid && tgt.x4_timer > 0.f) + return i; + } + return -1; +} + +bool CPlayerVisor::DrawScanObjectIndicators(const CStateManager& mgr) const { + if (!x124_scanIconNoncritical.IsLoaded() || !x130_scanIconCritical.IsLoaded()) + return false; + if (!x114_scanShield.IsLoaded()) + return false; + + CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); + g_Renderer->SetViewportOrtho(true, 0.f, 4096.f); + + float vpScale = g_Viewport.xc_height / 448.f; + CGraphics::SetModelMatrix(zeus::CTransform::Scale(x48_interpWindowDims.x() * 17.f * vpScale, 1.f, + x48_interpWindowDims.y() * 17.f * vpScale)); + + x114_scanShield->Draw(CModelFlags(5, 0, 3, zeus::CColor::skClear)); + + const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + zeus::CTransform camMtx = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + CGraphics::SetViewPointMatrix(camMtx); + zeus::CFrustum frustum; + frustum.updatePlanes(camMtx, zeus::CProjection(zeus::SProjPersp( + cam->GetFov(), g_Viewport.x8_width / float(g_Viewport.xc_height), 1.f, 100.f))); + g_Renderer->SetClippingPlanes(frustum); + g_Renderer->SetPerspective(cam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, cam->GetNearClipDistance(), + cam->GetFarClipDistance()); + + for (const SScanTarget& tgt : x13c_scanTargets) { + if (tgt.x4_timer == 0.f) + continue; + if (TCastToConstPtr act = mgr.GetObjectById(tgt.x0_objId)) { + if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) + continue; + const CScannableObjectInfo* scanInfo = act->GetScannableObjectInfo(); + const CModel* useModel; + const zeus::CColor* useColor; + const zeus::CColor* useDimColor; + if (scanInfo->IsImportant()) { + useModel = x130_scanIconCritical.GetObj(); + useColor = &g_tweakGuiColors->GetScanIconCriticalColor(); + useDimColor = &g_tweakGuiColors->GetScanIconCriticalDimColor(); + } else { + useModel = x124_scanIconNoncritical.GetObj(); + useColor = &g_tweakGuiColors->GetScanIconNoncriticalColor(); + useDimColor = &g_tweakGuiColors->GetScanIconNoncriticalDimColor(); + } + + zeus::CVector3f scanPos = act->GetScanObjectIndicatorPosition(mgr); + float scale = CCompoundTargetReticle::CalculateClampedScale( + scanPos, 1.f, g_tweakTargeting->GetScanTargetClampMin(), g_tweakTargeting->GetScanTargetClampMax(), mgr); + zeus::CTransform xf(zeus::CMatrix3f(scale) * camMtx.basis, scanPos); + + float scanRange = g_tweakPlayer->GetScanningRange(); + float farRange = g_tweakPlayer->GetScanMaxLockDistance() - scanRange; + float farT; + if (farRange <= 0.f) + farT = 1.f; + else + farT = zeus::clamp(0.f, 1.f - ((scanPos - camMtx.origin).magnitude() - scanRange) / farRange, 1.f); + + zeus::CColor iconColor = zeus::CColor::lerp(*useColor, *useDimColor, tgt.x8_inRangeTimer); + float iconAlpha; + if (mgr.GetPlayerState()->GetScanTime(scanInfo->GetScannableObjectId()) == 1.f) { + iconAlpha = tgt.x4_timer * 0.25f; + } else { + float tmp = 1.f; + if (mgr.GetPlayer().GetOrbitTargetId() == tgt.x0_objId) + tmp = 0.75f * x2c_scanDimInterp + 0.25f; + iconAlpha = tgt.x4_timer * tmp; + } + + CGraphics::SetModelMatrix(xf); + iconColor.a() *= iconAlpha * farT; + useModel->Draw(CModelFlags(7, 0, 1, iconColor)); + } + } + + CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); + return true; +} + +void CPlayerVisor::UpdateScanObjectIndicators(const CStateManager& mgr, float dt) { + bool inBoxExists = false; + float dt2 = dt * 2.f; + + for (SScanTarget& tgt : x13c_scanTargets) { + tgt.x4_timer = std::max(0.f, tgt.x4_timer - dt); + if (mgr.GetPlayer().ObjectInScanningRange(tgt.x0_objId, mgr)) + tgt.x8_inRangeTimer = std::max(0.f, tgt.x8_inRangeTimer - dt2); + else + tgt.x8_inRangeTimer = std::min(1.f, tgt.x8_inRangeTimer + dt2); + + if (TCastToConstPtr act = mgr.GetObjectById(tgt.x0_objId)) { + const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + zeus::CVector3f orbitPos = act->GetOrbitPosition(mgr); + orbitPos = cam->ConvertToScreenSpace(orbitPos); + orbitPos.x() = orbitPos.x() * g_Viewport.x8_width / 2.f + g_Viewport.x8_width / 2.f; + orbitPos.y() = orbitPos.y() * g_Viewport.xc_height / 2.f + g_Viewport.xc_height / 2.f; + bool inBox = mgr.GetPlayer().WithinOrbitScreenBox(orbitPos, mgr.GetPlayer().GetOrbitZone(), + mgr.GetPlayer().GetOrbitType()); + if (inBox != tgt.xc_inBox) { + tgt.xc_inBox = inBox; + if (inBox) + x550_scanFrameColorImpulseInterp = 1.f; + } + inBoxExists |= inBox; + } + } + + if (inBoxExists) + x54c_scanFrameColorInterp = std::min(x54c_scanFrameColorInterp + dt2, 1.f); + else + x54c_scanFrameColorInterp = std::max(0.f, x54c_scanFrameColorInterp - dt2); + + x550_scanFrameColorImpulseInterp = std::max(0.f, x550_scanFrameColorImpulseInterp - dt); + dt += FLT_EPSILON; + + TAreaId playerArea = mgr.GetPlayer().GetAreaIdAlways(); + for (TUniqueId id : mgr.GetPlayer().GetNearbyOrbitObjects()) { + if (TCastToConstPtr act = mgr.GetObjectById(id)) { + if (act->GetAreaIdAlways() != playerArea) + continue; + if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) + continue; + int target = FindCachedInactiveScanTarget(id); + if (target != -1) { + SScanTarget& sTarget = x13c_scanTargets[target]; + sTarget.x4_timer = std::min(sTarget.x4_timer + dt2, 1.f); + continue; + } + target = FindEmptyInactiveScanTarget(); + if (target != -1) { + SScanTarget& sTarget = x13c_scanTargets[target]; + sTarget.x0_objId = id; + sTarget.x4_timer = dt; + sTarget.x8_inRangeTimer = 1.f; + sTarget.xc_inBox = false; + } + } + } +} + +void CPlayerVisor::UpdateScanWindow(float dt, const CStateManager& mgr) { + UpdateScanObjectIndicators(mgr, dt); + if (mgr.GetPlayer().GetScanningState() == CPlayer::EPlayerScanState::Scanning) { + if (!x60_scanningLoopSfx) + x60_scanningLoopSfx = + CSfxManager::SfxStart(SFXui_scanning_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId); + } else { CSfxManager::SfxStop(x60_scanningLoopSfx); + x60_scanningLoopSfx.reset(); + } + + EScanWindowState desiredState = GetDesiredScanWindowState(mgr); + switch (x34_nextState) { + case EScanWindowState::NotInScanVisor: + if (desiredState != EScanWindowState::NotInScanVisor) { + if (x30_prevState == EScanWindowState::NotInScanVisor) + x48_interpWindowDims = x0_scanWindowSizes[int(desiredState)]; + x50_nextWindowDims = x0_scanWindowSizes[int(desiredState)]; + x40_prevWindowDims = x48_interpWindowDims; + x30_prevState = x34_nextState; + x34_nextState = desiredState; + x38_windowInterpDuration = + (desiredState == EScanWindowState::Scan) ? g_tweakGui->GetScanSidesEndTime() - x3c_windowInterpTimer : 0.f; + x3c_windowInterpTimer = x38_windowInterpDuration; + } + break; + case EScanWindowState::Idle: + if (desiredState != EScanWindowState::Idle) { + x50_nextWindowDims = (desiredState == EScanWindowState::NotInScanVisor) ? x48_interpWindowDims + : x0_scanWindowSizes[int(desiredState)]; + x40_prevWindowDims = x48_interpWindowDims; + x30_prevState = x34_nextState; + x34_nextState = desiredState; + x38_windowInterpDuration = + (desiredState == EScanWindowState::Scan) ? g_tweakGui->GetScanSidesEndTime() - x3c_windowInterpTimer : 0.f; + x3c_windowInterpTimer = x38_windowInterpDuration; + if (desiredState == EScanWindowState::Scan) + CSfxManager::SfxStart(SFXui_into_scan_window, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); + } + break; + case EScanWindowState::Scan: + if (desiredState != EScanWindowState::Scan) { + x50_nextWindowDims = (desiredState == EScanWindowState::NotInScanVisor) ? x48_interpWindowDims + : x0_scanWindowSizes[int(desiredState)]; + x40_prevWindowDims = x48_interpWindowDims; + x30_prevState = x34_nextState; + x34_nextState = desiredState; + x38_windowInterpDuration = + (desiredState == EScanWindowState::Idle) ? g_tweakGui->GetScanSidesEndTime() - x3c_windowInterpTimer : 0.f; + x3c_windowInterpTimer = x38_windowInterpDuration; + if (mgr.GetPlayerState()->GetVisorTransitionFactor() == 1.f) + CSfxManager::SfxStart(SFXui_outof_scan_window, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); + } + break; + default: + break; + } + + if (x30_prevState != x34_nextState) { + x3c_windowInterpTimer = std::max(0.f, x3c_windowInterpTimer - dt); + if (x3c_windowInterpTimer == 0.f) + x30_prevState = x34_nextState; + + float t = 0.f; + if (x38_windowInterpDuration > 0.f) { + float scanSidesDuration = g_tweakGui->GetScanSidesDuration(); + float scanSidesStart = g_tweakGui->GetScanSidesStartTime(); + if (x34_nextState == EScanWindowState::Scan) + t = (x3c_windowInterpTimer < scanSidesDuration) ? 0.f + : (x3c_windowInterpTimer - scanSidesDuration) / scanSidesStart; + else + t = (x3c_windowInterpTimer > scanSidesStart) ? 1.f : x3c_windowInterpTimer / scanSidesStart; + } + + x48_interpWindowDims = x50_nextWindowDims * (1.f - t) + x40_prevWindowDims * t; + } } -int CPlayerVisor::FindEmptyInactiveScanTarget() const -{ - for (int i=0 ; iGetCurrentVisor() == CPlayerState::EPlayerVisor::Scan) { + switch (mgr.GetPlayer().GetScanningState()) { + case CPlayer::EPlayerScanState::Scanning: + case CPlayer::EPlayerScanState::ScanComplete: + return EScanWindowState::Scan; + default: + return EScanWindowState::Idle; } - return -1; + } + return EScanWindowState::NotInScanVisor; } -int CPlayerVisor::FindCachedInactiveScanTarget(TUniqueId uid) const -{ - for (int i=0 ; i 0.f) - return i; - } - return -1; -} - -bool CPlayerVisor::DrawScanObjectIndicators(const CStateManager& mgr) const -{ - if (!x124_scanIconNoncritical.IsLoaded() || !x130_scanIconCritical.IsLoaded()) - return false; - if (!x114_scanShield.IsLoaded()) - return false; - - CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); - g_Renderer->SetViewportOrtho(true, 0.f, 4096.f); - - float vpScale = g_Viewport.xc_height / 448.f; - CGraphics::SetModelMatrix( - zeus::CTransform::Scale(x48_interpWindowDims.x() * 17.f * vpScale, 1.f, - x48_interpWindowDims.y() * 17.f * vpScale)); - - x114_scanShield->Draw(CModelFlags(5, 0, 3, zeus::CColor::skClear)); - - const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - zeus::CTransform camMtx = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - CGraphics::SetViewPointMatrix(camMtx); - zeus::CFrustum frustum; - frustum.updatePlanes(camMtx, zeus::CProjection(zeus::SProjPersp(cam->GetFov(), - g_Viewport.x8_width / float(g_Viewport.xc_height), 1.f, 100.f))); - g_Renderer->SetClippingPlanes(frustum); - g_Renderer->SetPerspective(cam->GetFov(), g_Viewport.x8_width, g_Viewport.xc_height, - cam->GetNearClipDistance(), cam->GetFarClipDistance()); - - for (const SScanTarget& tgt : x13c_scanTargets) - { - if (tgt.x4_timer == 0.f) - continue; - if (TCastToConstPtr act = mgr.GetObjectById(tgt.x0_objId)) - { - if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) - continue; - const CScannableObjectInfo* scanInfo = act->GetScannableObjectInfo(); - const CModel* useModel; - const zeus::CColor* useColor; - const zeus::CColor* useDimColor; - if (scanInfo->IsImportant()) - { - useModel = x130_scanIconCritical.GetObj(); - useColor = &g_tweakGuiColors->GetScanIconCriticalColor(); - useDimColor = &g_tweakGuiColors->GetScanIconCriticalDimColor(); - } - else - { - useModel = x124_scanIconNoncritical.GetObj(); - useColor = &g_tweakGuiColors->GetScanIconNoncriticalColor(); - useDimColor = &g_tweakGuiColors->GetScanIconNoncriticalDimColor(); - } - - zeus::CVector3f scanPos = act->GetScanObjectIndicatorPosition(mgr); - float scale = CCompoundTargetReticle::CalculateClampedScale(scanPos, 1.f, - g_tweakTargeting->GetScanTargetClampMin(), - g_tweakTargeting->GetScanTargetClampMax(), mgr); - zeus::CTransform xf(zeus::CMatrix3f(scale) * camMtx.basis, scanPos); - - float scanRange = g_tweakPlayer->GetScanningRange(); - float farRange = g_tweakPlayer->GetScanMaxLockDistance() - scanRange; - float farT; - if (farRange <= 0.f) - farT = 1.f; - else - farT = zeus::clamp(0.f, 1.f - ((scanPos - camMtx.origin).magnitude() - scanRange) / farRange, 1.f); - - zeus::CColor iconColor = zeus::CColor::lerp(*useColor, *useDimColor, tgt.x8_inRangeTimer); - float iconAlpha; - if (mgr.GetPlayerState()->GetScanTime(scanInfo->GetScannableObjectId()) == 1.f) - { - iconAlpha = tgt.x4_timer * 0.25f; - } - else - { - float tmp = 1.f; - if (mgr.GetPlayer().GetOrbitTargetId() == tgt.x0_objId) - tmp = 0.75f * x2c_scanDimInterp + 0.25f; - iconAlpha = tgt.x4_timer * tmp; - } - - CGraphics::SetModelMatrix(xf); - iconColor.a() *= iconAlpha * farT; - useModel->Draw(CModelFlags(7, 0, 1, iconColor)); - } - } - - CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); - return true; -} - -void CPlayerVisor::UpdateScanObjectIndicators(const CStateManager& mgr, float dt) -{ - bool inBoxExists = false; - float dt2 = dt * 2.f; - - for (SScanTarget& tgt : x13c_scanTargets) - { - tgt.x4_timer = std::max(0.f, tgt.x4_timer - dt); - if (mgr.GetPlayer().ObjectInScanningRange(tgt.x0_objId, mgr)) - tgt.x8_inRangeTimer = std::max(0.f, tgt.x8_inRangeTimer - dt2); - else - tgt.x8_inRangeTimer = std::min(1.f, tgt.x8_inRangeTimer + dt2); - - if (TCastToConstPtr act = mgr.GetObjectById(tgt.x0_objId)) - { - const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - zeus::CVector3f orbitPos = act->GetOrbitPosition(mgr); - orbitPos = cam->ConvertToScreenSpace(orbitPos); - orbitPos.x() = orbitPos.x() * g_Viewport.x8_width / 2.f + g_Viewport.x8_width / 2.f; - orbitPos.y() = orbitPos.y() * g_Viewport.xc_height / 2.f + g_Viewport.xc_height / 2.f; - bool inBox = mgr.GetPlayer().WithinOrbitScreenBox(orbitPos, - mgr.GetPlayer().GetOrbitZone(), - mgr.GetPlayer().GetOrbitType()); - if (inBox != tgt.xc_inBox) - { - tgt.xc_inBox = inBox; - if (inBox) - x550_scanFrameColorImpulseInterp = 1.f; - } - inBoxExists |= inBox; - } - } - - if (inBoxExists) - x54c_scanFrameColorInterp = std::min(x54c_scanFrameColorInterp + dt2, 1.f); - else - x54c_scanFrameColorInterp = std::max(0.f, x54c_scanFrameColorInterp - dt2); - - x550_scanFrameColorImpulseInterp = std::max(0.f, x550_scanFrameColorImpulseInterp - dt); - dt += FLT_EPSILON; - - TAreaId playerArea = mgr.GetPlayer().GetAreaIdAlways(); - for (TUniqueId id : mgr.GetPlayer().GetNearbyOrbitObjects()) - { - if (TCastToConstPtr act = mgr.GetObjectById(id)) - { - if (act->GetAreaIdAlways() != playerArea) - continue; - if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) - continue; - int target = FindCachedInactiveScanTarget(id); - if (target != -1) - { - SScanTarget& sTarget = x13c_scanTargets[target]; - sTarget.x4_timer = std::min(sTarget.x4_timer + dt2, 1.f); - continue; - } - target = FindEmptyInactiveScanTarget(); - if (target != -1) - { - SScanTarget& sTarget = x13c_scanTargets[target]; - sTarget.x0_objId = id; - sTarget.x4_timer = dt; - sTarget.x8_inRangeTimer = 1.f; - sTarget.xc_inBox = false; - } - } - } -} - -void CPlayerVisor::UpdateScanWindow(float dt, const CStateManager& mgr) -{ - UpdateScanObjectIndicators(mgr, dt); - if (mgr.GetPlayer().GetScanningState() == CPlayer::EPlayerScanState::Scanning) - { - if (!x60_scanningLoopSfx) - x60_scanningLoopSfx = CSfxManager::SfxStart(SFXui_scanning_lp, x24_visorSfxVol, 0.f, - false, 0x7f, true, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(x60_scanningLoopSfx); - x60_scanningLoopSfx.reset(); - } - - EScanWindowState desiredState = GetDesiredScanWindowState(mgr); - switch (x34_nextState) - { - case EScanWindowState::NotInScanVisor: - if (desiredState != EScanWindowState::NotInScanVisor) - { - if (x30_prevState == EScanWindowState::NotInScanVisor) - x48_interpWindowDims = x0_scanWindowSizes[int(desiredState)]; - x50_nextWindowDims = x0_scanWindowSizes[int(desiredState)]; - x40_prevWindowDims = x48_interpWindowDims; - x30_prevState = x34_nextState; - x34_nextState = desiredState; - x38_windowInterpDuration = - (desiredState == EScanWindowState::Scan) ? g_tweakGui->GetScanSidesEndTime() - x3c_windowInterpTimer : 0.f; - x3c_windowInterpTimer = x38_windowInterpDuration; - } - break; - case EScanWindowState::Idle: - if (desiredState != EScanWindowState::Idle) - { - x50_nextWindowDims = (desiredState == EScanWindowState::NotInScanVisor) ? x48_interpWindowDims : - x0_scanWindowSizes[int(desiredState)]; - x40_prevWindowDims = x48_interpWindowDims; - x30_prevState = x34_nextState; - x34_nextState = desiredState; - x38_windowInterpDuration = - (desiredState == EScanWindowState::Scan) ? g_tweakGui->GetScanSidesEndTime() - x3c_windowInterpTimer : 0.f; - x3c_windowInterpTimer = x38_windowInterpDuration; - if (desiredState == EScanWindowState::Scan) - CSfxManager::SfxStart(SFXui_into_scan_window, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); - } - break; - case EScanWindowState::Scan: - if (desiredState != EScanWindowState::Scan) - { - x50_nextWindowDims = (desiredState == EScanWindowState::NotInScanVisor) ? x48_interpWindowDims : - x0_scanWindowSizes[int(desiredState)]; - x40_prevWindowDims = x48_interpWindowDims; - x30_prevState = x34_nextState; - x34_nextState = desiredState; - x38_windowInterpDuration = - (desiredState == EScanWindowState::Idle) ? g_tweakGui->GetScanSidesEndTime() - x3c_windowInterpTimer : 0.f; - x3c_windowInterpTimer = x38_windowInterpDuration; - if (mgr.GetPlayerState()->GetVisorTransitionFactor() == 1.f) - CSfxManager::SfxStart(SFXui_outof_scan_window, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); - } - break; - default: break; - } - - if (x30_prevState != x34_nextState) - { - x3c_windowInterpTimer = std::max(0.f, x3c_windowInterpTimer - dt); - if (x3c_windowInterpTimer == 0.f) - x30_prevState = x34_nextState; - - float t = 0.f; - if (x38_windowInterpDuration > 0.f) - { - float scanSidesDuration = g_tweakGui->GetScanSidesDuration(); - float scanSidesStart = g_tweakGui->GetScanSidesStartTime(); - if (x34_nextState == EScanWindowState::Scan) - t = (x3c_windowInterpTimer < scanSidesDuration) ? 0.f : (x3c_windowInterpTimer - scanSidesDuration) / scanSidesStart; - else - t = (x3c_windowInterpTimer > scanSidesStart) ? 1.f : x3c_windowInterpTimer / scanSidesStart; - } - - x48_interpWindowDims = x50_nextWindowDims * (1.f - t) + x40_prevWindowDims * t; - } -} - -CPlayerVisor::EScanWindowState -CPlayerVisor::GetDesiredScanWindowState(const CStateManager& mgr) const -{ - if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan) - { - switch (mgr.GetPlayer().GetScanningState()) - { - case CPlayer::EPlayerScanState::Scanning: - case CPlayer::EPlayerScanState::ScanComplete: - return EScanWindowState::Scan; - default: - return EScanWindowState::Idle; - } - } - return EScanWindowState::NotInScanVisor; -} - -void CPlayerVisor::LockUnlockAssets() -{ +void CPlayerVisor::LockUnlockAssets() { #if 0 if (x1c_curVisor == CPlayerState::EPlayerVisor::Scan) x120_assetLockCountdown = 2; @@ -360,392 +319,352 @@ void CPlayerVisor::LockUnlockAssets() #endif } -void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, const CTargetingManager* tgtMgr) const -{ - bool indicatorsDrawn = DrawScanObjectIndicators(mgr); - if (tgtMgr && indicatorsDrawn) - { - CGraphics::SetDepthRange(DEPTH_TARGET_MANAGER, DEPTH_TARGET_MANAGER); - tgtMgr->Draw(mgr, false); - CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); - } +void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, const CTargetingManager* tgtMgr) const { + bool indicatorsDrawn = DrawScanObjectIndicators(mgr); + if (tgtMgr && indicatorsDrawn) { + CGraphics::SetDepthRange(DEPTH_TARGET_MANAGER, DEPTH_TARGET_MANAGER); + tgtMgr->Draw(mgr, false); + CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN); + } - float transFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); - float scanSidesDuration = g_tweakGui->GetScanSidesDuration(); - float scanSidesStart = g_tweakGui->GetScanSidesStartTime(); + float transFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); + float scanSidesDuration = g_tweakGui->GetScanSidesDuration(); + float scanSidesStart = g_tweakGui->GetScanSidesStartTime(); - float t; - if (x34_nextState == EScanWindowState::Scan) - t = 1.f - ((x3c_windowInterpTimer < scanSidesDuration) ? 0.f : (x3c_windowInterpTimer - scanSidesDuration) / scanSidesStart); - else - t = (x3c_windowInterpTimer > scanSidesStart) ? 1.f : x3c_windowInterpTimer / scanSidesStart; + float t; + if (x34_nextState == EScanWindowState::Scan) + t = 1.f - ((x3c_windowInterpTimer < scanSidesDuration) + ? 0.f + : (x3c_windowInterpTimer - scanSidesDuration) / scanSidesStart); + else + t = (x3c_windowInterpTimer > scanSidesStart) ? 1.f : x3c_windowInterpTimer / scanSidesStart; - float vpScale = g_Viewport.xc_height / 448.f; - float divisor = (transFactor * ((1.f - t) * x58_scanMagInterp + t * g_tweakGui->GetScanWindowScanningAspect()) + (1.f - transFactor)); - divisor = 1.f / divisor; - float vpW = 169.218f * x48_interpWindowDims.x() * divisor; - vpW = zeus::clamp(0.f, vpW, 640.f) * vpScale; - float vpH = 152.218f * x48_interpWindowDims.y() * divisor; - vpH = zeus::clamp(0.f, vpH, 448.f) * vpScale; + float vpScale = g_Viewport.xc_height / 448.f; + float divisor = (transFactor * ((1.f - t) * x58_scanMagInterp + t * g_tweakGui->GetScanWindowScanningAspect()) + + (1.f - transFactor)); + divisor = 1.f / divisor; + float vpW = 169.218f * x48_interpWindowDims.x() * divisor; + vpW = zeus::clamp(0.f, vpW, 640.f) * vpScale; + float vpH = 152.218f * x48_interpWindowDims.y() * divisor; + vpH = zeus::clamp(0.f, vpH, 448.f) * vpScale; - SClipScreenRect rect; - rect.x4_left = (g_Viewport.x8_width - vpW) / 2.f; - rect.x8_top = (g_Viewport.xc_height - vpH) / 2.f; - rect.xc_width = vpW; - rect.x10_height = vpH; - CGraphics::ResolveSpareTexture(rect); + SClipScreenRect rect; + rect.x4_left = (g_Viewport.x8_width - vpW) / 2.f; + rect.x8_top = (g_Viewport.xc_height - vpH) / 2.f; + rect.xc_width = vpW; + rect.x10_height = vpH; + CGraphics::ResolveSpareTexture(rect); - x64_scanDim.Draw(); + x64_scanDim.Draw(); - g_Renderer->SetViewportOrtho(true, -1.f, 1.f); + g_Renderer->SetViewportOrtho(true, -1.f, 1.f); - zeus::CTransform windowScale = zeus::CTransform::Scale(x48_interpWindowDims.x(), 1.f, x48_interpWindowDims.y()); - zeus::CTransform seventeenScale = zeus::CTransform::Scale(17.f * vpScale, 1.f, 17.f * vpScale); - CGraphics::SetModelMatrix(seventeenScale * windowScale); + zeus::CTransform windowScale = zeus::CTransform::Scale(x48_interpWindowDims.x(), 1.f, x48_interpWindowDims.y()); + zeus::CTransform seventeenScale = zeus::CTransform::Scale(17.f * vpScale, 1.f, 17.f * vpScale); + CGraphics::SetModelMatrix(seventeenScale * windowScale); - float uvX0 = rect.x4_left / float(g_Viewport.x8_width); - float uvX1 = (rect.x4_left + rect.xc_width) / float(g_Viewport.x8_width); - float uvY0 = rect.x8_top / float(g_Viewport.xc_height); - float uvY1 = (rect.x8_top + rect.x10_height) / float(g_Viewport.xc_height); - CTexturedQuadFilter::Vert rttVerts[4] = - { - {{-5.f, 0.f, 4.45f}, {uvX0, uvY0}}, - {{ 5.f, 0.f, 4.45f}, {uvX1, uvY0}}, - {{-5.f, 0.f, -4.45f}, {uvX0, uvY1}}, - {{ 5.f, 0.f, -4.45f}, {uvX1, uvY1}} - }; - if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) - { - rttVerts[0].m_uv.y() = uvY1; - rttVerts[1].m_uv.y() = uvY1; - rttVerts[2].m_uv.y() = uvY0; - rttVerts[3].m_uv.y() = uvY0; - } - const_cast(x108_newScanPane).drawVerts(zeus::CColor(1.f, transFactor), rttVerts); + float uvX0 = rect.x4_left / float(g_Viewport.x8_width); + float uvX1 = (rect.x4_left + rect.xc_width) / float(g_Viewport.x8_width); + float uvY0 = rect.x8_top / float(g_Viewport.xc_height); + float uvY1 = (rect.x8_top + rect.x10_height) / float(g_Viewport.xc_height); + CTexturedQuadFilter::Vert rttVerts[4] = {{{-5.f, 0.f, 4.45f}, {uvX0, uvY0}}, + {{5.f, 0.f, 4.45f}, {uvX1, uvY0}}, + {{-5.f, 0.f, -4.45f}, {uvX0, uvY1}}, + {{5.f, 0.f, -4.45f}, {uvX1, uvY1}}}; + if (CGraphics::g_BooPlatform == boo::IGraphicsDataFactory::Platform::OpenGL) { + rttVerts[0].m_uv.y() = uvY1; + rttVerts[1].m_uv.y() = uvY1; + rttVerts[2].m_uv.y() = uvY0; + rttVerts[3].m_uv.y() = uvY0; + } + const_cast(x108_newScanPane).drawVerts(zeus::CColor(1.f, transFactor), rttVerts); - // No cull faces + // No cull faces - zeus::CColor frameColor = zeus::CColor::lerp( - g_tweakGuiColors->GetScanFrameInactiveColor(), - g_tweakGuiColors->GetScanFrameActiveColor(), - x54c_scanFrameColorInterp); - frameColor.a() = transFactor; + zeus::CColor frameColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanFrameInactiveColor(), + g_tweakGuiColors->GetScanFrameActiveColor(), x54c_scanFrameColorInterp); + frameColor.a() = transFactor; - CModelFlags flags(5, 0, 0, - frameColor + g_tweakGuiColors->GetScanFrameImpulseColor() * - zeus::CColor(x550_scanFrameColorImpulseInterp, x550_scanFrameColorImpulseInterp)); - flags.m_noCull = true; + CModelFlags flags(5, 0, 0, + frameColor + g_tweakGuiColors->GetScanFrameImpulseColor() * + zeus::CColor(x550_scanFrameColorImpulseInterp, x550_scanFrameColorImpulseInterp)); + flags.m_noCull = true; - zeus::CTransform verticalFlip = zeus::CTransform::Scale(1.f, 1.f, -1.f); - zeus::CTransform horizontalFlip = zeus::CTransform::Scale(-1.f, 1.f, 1.f); + zeus::CTransform verticalFlip = zeus::CTransform::Scale(1.f, 1.f, -1.f); + zeus::CTransform horizontalFlip = zeus::CTransform::Scale(-1.f, 1.f, 1.f); - if (xe4_scanFrameCenterTop.IsLoaded()) - { - zeus::CTransform modelXf = - seventeenScale * zeus::CTransform::Translate(windowScale * zeus::CVector3f(0.f, 0.f, 4.553f)); - CGraphics::SetModelMatrix(modelXf); - xe4_scanFrameCenterTop->Draw(flags); - CGraphics::SetModelMatrix(verticalFlip * modelXf); - xe4_scanFrameCenterTop->Draw(flags); - } + if (xe4_scanFrameCenterTop.IsLoaded()) { + zeus::CTransform modelXf = + seventeenScale * zeus::CTransform::Translate(windowScale * zeus::CVector3f(0.f, 0.f, 4.553f)); + CGraphics::SetModelMatrix(modelXf); + xe4_scanFrameCenterTop->Draw(flags); + CGraphics::SetModelMatrix(verticalFlip * modelXf); + xe4_scanFrameCenterTop->Draw(flags); + } - if (xd8_scanFrameCenterSide.IsLoaded()) - { - zeus::CTransform modelXf = - seventeenScale * zeus::CTransform::Translate(windowScale * zeus::CVector3f(-5.f, 0.f, 0.f)); - CGraphics::SetModelMatrix(modelXf); - xd8_scanFrameCenterSide->Draw(flags); - CGraphics::SetModelMatrix(horizontalFlip * modelXf); - xd8_scanFrameCenterSide->Draw(flags); - } + if (xd8_scanFrameCenterSide.IsLoaded()) { + zeus::CTransform modelXf = + seventeenScale * zeus::CTransform::Translate(windowScale * zeus::CVector3f(-5.f, 0.f, 0.f)); + CGraphics::SetModelMatrix(modelXf); + xd8_scanFrameCenterSide->Draw(flags); + CGraphics::SetModelMatrix(horizontalFlip * modelXf); + xd8_scanFrameCenterSide->Draw(flags); + } - if (xcc_scanFrameCorner.IsLoaded()) - { - zeus::CTransform modelXf = - seventeenScale * zeus::CTransform::Translate(windowScale * zeus::CVector3f(-5.f, 0.f, 4.553f)); - CGraphics::SetModelMatrix(modelXf); - xcc_scanFrameCorner->Draw(flags); - CGraphics::SetModelMatrix(horizontalFlip * modelXf); - xcc_scanFrameCorner->Draw(flags); - CGraphics::SetModelMatrix(verticalFlip * modelXf); - xcc_scanFrameCorner->Draw(flags); - CGraphics::SetModelMatrix(verticalFlip * horizontalFlip * modelXf); - xcc_scanFrameCorner->Draw(flags); - } + if (xcc_scanFrameCorner.IsLoaded()) { + zeus::CTransform modelXf = + seventeenScale * zeus::CTransform::Translate(windowScale * zeus::CVector3f(-5.f, 0.f, 4.553f)); + CGraphics::SetModelMatrix(modelXf); + xcc_scanFrameCorner->Draw(flags); + CGraphics::SetModelMatrix(horizontalFlip * modelXf); + xcc_scanFrameCorner->Draw(flags); + CGraphics::SetModelMatrix(verticalFlip * modelXf); + xcc_scanFrameCorner->Draw(flags); + CGraphics::SetModelMatrix(verticalFlip * horizontalFlip * modelXf); + xcc_scanFrameCorner->Draw(flags); + } - if (xfc_scanFrameStretchTop.IsLoaded()) - { - zeus::CTransform modelXf = - seventeenScale * zeus::CTransform::Translate(-1.f, 0.f, 4.553f * windowScale.basis[2][2]) * - zeus::CTransform::Scale(5.f * windowScale.basis[0][0] - 1.f - 1.884f, 1.f, 1.f); - CGraphics::SetModelMatrix(modelXf); - xfc_scanFrameStretchTop->Draw(flags); - CGraphics::SetModelMatrix(horizontalFlip * modelXf); - xfc_scanFrameStretchTop->Draw(flags); - CGraphics::SetModelMatrix(verticalFlip * modelXf); - xfc_scanFrameStretchTop->Draw(flags); - CGraphics::SetModelMatrix(verticalFlip * horizontalFlip * modelXf); - xfc_scanFrameStretchTop->Draw(flags); - } + if (xfc_scanFrameStretchTop.IsLoaded()) { + zeus::CTransform modelXf = seventeenScale * + zeus::CTransform::Translate(-1.f, 0.f, 4.553f * windowScale.basis[2][2]) * + zeus::CTransform::Scale(5.f * windowScale.basis[0][0] - 1.f - 1.884f, 1.f, 1.f); + CGraphics::SetModelMatrix(modelXf); + xfc_scanFrameStretchTop->Draw(flags); + CGraphics::SetModelMatrix(horizontalFlip * modelXf); + xfc_scanFrameStretchTop->Draw(flags); + CGraphics::SetModelMatrix(verticalFlip * modelXf); + xfc_scanFrameStretchTop->Draw(flags); + CGraphics::SetModelMatrix(verticalFlip * horizontalFlip * modelXf); + xfc_scanFrameStretchTop->Draw(flags); + } - if (xf0_scanFrameStretchSide.IsLoaded()) - { - zeus::CTransform modelXf = - seventeenScale * zeus::CTransform::Translate(-5.f * windowScale.basis[0][0], 0.f, 1.f) * - zeus::CTransform::Scale(1.f, 1.f, 4.553f * windowScale.basis[2][2] - 1.f - 1.886f); - CGraphics::SetModelMatrix(modelXf); - xf0_scanFrameStretchSide->Draw(flags); - CGraphics::SetModelMatrix(horizontalFlip * modelXf); - xf0_scanFrameStretchSide->Draw(flags); - CGraphics::SetModelMatrix(verticalFlip * modelXf); - xf0_scanFrameStretchSide->Draw(flags); - CGraphics::SetModelMatrix(verticalFlip * horizontalFlip * modelXf); - xf0_scanFrameStretchSide->Draw(flags); - } + if (xf0_scanFrameStretchSide.IsLoaded()) { + zeus::CTransform modelXf = seventeenScale * zeus::CTransform::Translate(-5.f * windowScale.basis[0][0], 0.f, 1.f) * + zeus::CTransform::Scale(1.f, 1.f, 4.553f * windowScale.basis[2][2] - 1.f - 1.886f); + CGraphics::SetModelMatrix(modelXf); + xf0_scanFrameStretchSide->Draw(flags); + CGraphics::SetModelMatrix(horizontalFlip * modelXf); + xf0_scanFrameStretchSide->Draw(flags); + CGraphics::SetModelMatrix(verticalFlip * modelXf); + xf0_scanFrameStretchSide->Draw(flags); + CGraphics::SetModelMatrix(verticalFlip * horizontalFlip * modelXf); + xf0_scanFrameStretchSide->Draw(flags); + } - // cull faces + // cull faces } -void CPlayerVisor::DrawXRayEffect(const CStateManager&) const -{ - const_cast(x90_xrayBlur).Draw(); +void CPlayerVisor::DrawXRayEffect(const CStateManager&) const { const_cast(x90_xrayBlur).Draw(); } + +void CPlayerVisor::DrawThermalEffect(const CStateManager&) const { + // Empty } -void CPlayerVisor::DrawThermalEffect(const CStateManager&) const -{ - // Empty +void CPlayerVisor::UpdateCurrentVisor(float transFactor) { + switch (x1c_curVisor) { + case CPlayerState::EPlayerVisor::XRay: + x90_xrayBlur.SetBlur(EBlurType::Xray, 36.f * transFactor, 0.f); + break; + case CPlayerState::EPlayerVisor::Scan: { + zeus::CColor dimColor = + zeus::CColor::lerp(g_tweakGuiColors->GetScanVisorHudLightMultiply(), zeus::CColor::skWhite, 1.f - transFactor); + x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, dimColor, -1); + break; + } + default: + break; + } } -void CPlayerVisor::UpdateCurrentVisor(float transFactor) -{ - switch (x1c_curVisor) - { - case CPlayerState::EPlayerVisor::XRay: - x90_xrayBlur.SetBlur(EBlurType::Xray, 36.f * transFactor, 0.f); - break; - case CPlayerState::EPlayerVisor::Scan: - { - zeus::CColor dimColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanVisorHudLightMultiply(), - zeus::CColor::skWhite, 1.f - transFactor); - x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, dimColor, -1); - break; - } - default: break; - } +void CPlayerVisor::FinishTransitionIn() { + switch (x1c_curVisor) { + case CPlayerState::EPlayerVisor::Combat: + x90_xrayBlur.DisableBlur(0.f); + break; + case CPlayerState::EPlayerVisor::XRay: + x90_xrayBlur.SetBlur(EBlurType::Xray, 36.f, 0.f); + if (!x5c_visorLoopSfx) + x5c_visorLoopSfx = + CSfxManager::SfxStart(SFXui_visor_xray_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId); + break; + case CPlayerState::EPlayerVisor::Scan: { + zeus::CColor dimColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanVisorScreenDimColor(), + g_tweakGuiColors->GetScanVisorHudLightMultiply(), x2c_scanDimInterp); + x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, dimColor, -1); + if (!x5c_visorLoopSfx) + x5c_visorLoopSfx = + CSfxManager::SfxStart(SFXui_visor_scan_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId); + break; + } + case CPlayerState::EPlayerVisor::Thermal: + if (!x5c_visorLoopSfx) + x5c_visorLoopSfx = + CSfxManager::SfxStart(SFXui_visor_thermal_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId); + break; + default: + break; + } } -void CPlayerVisor::FinishTransitionIn() -{ - switch (x1c_curVisor) - { - case CPlayerState::EPlayerVisor::Combat: - x90_xrayBlur.DisableBlur(0.f); - break; - case CPlayerState::EPlayerVisor::XRay: - x90_xrayBlur.SetBlur(EBlurType::Xray, 36.f, 0.f); - if (!x5c_visorLoopSfx) - x5c_visorLoopSfx = CSfxManager::SfxStart(SFXui_visor_xray_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId); - break; - case CPlayerState::EPlayerVisor::Scan: - { - zeus::CColor dimColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanVisorScreenDimColor(), - g_tweakGuiColors->GetScanVisorHudLightMultiply(), - x2c_scanDimInterp); - x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, dimColor, -1); - if (!x5c_visorLoopSfx) - x5c_visorLoopSfx = CSfxManager::SfxStart(SFXui_visor_scan_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId); - break; - } - case CPlayerState::EPlayerVisor::Thermal: - if (!x5c_visorLoopSfx) - x5c_visorLoopSfx = CSfxManager::SfxStart(SFXui_visor_thermal_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId); - break; - default: break; - } +void CPlayerVisor::BeginTransitionIn(const CStateManager&) { + switch (x1c_curVisor) { + case CPlayerState::EPlayerVisor::XRay: + x90_xrayBlur.SetBlur(EBlurType::Xray, 0.f, 0.f); + // xc4_vpScaleX = 0.9f; + // xc8_vpScaleY = 0.9f; + CSfxManager::SfxStart(SFXui_into_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + case CPlayerState::EPlayerVisor::Scan: + CSfxManager::SfxStart(SFXui_into_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); + x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, zeus::CColor::skWhite, -1); + break; + case CPlayerState::EPlayerVisor::Thermal: + CSfxManager::SfxStart(SFXui_into_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + default: + break; + } } -void CPlayerVisor::BeginTransitionIn(const CStateManager&) -{ - switch (x1c_curVisor) - { - case CPlayerState::EPlayerVisor::XRay: - x90_xrayBlur.SetBlur(EBlurType::Xray, 0.f, 0.f); - //xc4_vpScaleX = 0.9f; - //xc8_vpScaleY = 0.9f; - CSfxManager::SfxStart(SFXui_into_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); - break; - case CPlayerState::EPlayerVisor::Scan: - CSfxManager::SfxStart(SFXui_into_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); - x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, zeus::CColor::skWhite, -1); - break; - case CPlayerState::EPlayerVisor::Thermal: - CSfxManager::SfxStart(SFXui_into_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); - break; - default: break; - } +void CPlayerVisor::FinishTransitionOut(const CStateManager&) { + switch (x1c_curVisor) { + case CPlayerState::EPlayerVisor::XRay: + x90_xrayBlur.DisableBlur(0.f); + // xc4_vpScaleX = 1.f; + // xc8_vpScaleY = 1.f; + break; + case CPlayerState::EPlayerVisor::Scan: + x64_scanDim.DisableFilter(0.f); + x34_nextState = EScanWindowState::NotInScanVisor; + x30_prevState = EScanWindowState::NotInScanVisor; + break; + case CPlayerState::EPlayerVisor::Thermal: + x90_xrayBlur.DisableBlur(0.f); + break; + default: + break; + } } -void CPlayerVisor::FinishTransitionOut(const CStateManager&) -{ - switch (x1c_curVisor) - { - case CPlayerState::EPlayerVisor::XRay: - x90_xrayBlur.DisableBlur(0.f); - //xc4_vpScaleX = 1.f; - //xc8_vpScaleY = 1.f; - break; - case CPlayerState::EPlayerVisor::Scan: - x64_scanDim.DisableFilter(0.f); - x34_nextState = EScanWindowState::NotInScanVisor; - x30_prevState = EScanWindowState::NotInScanVisor; - break; - case CPlayerState::EPlayerVisor::Thermal: - x90_xrayBlur.DisableBlur(0.f); - break; - default: break; +void CPlayerVisor::BeginTransitionOut() { + if (x5c_visorLoopSfx) { + CSfxManager::SfxStop(x5c_visorLoopSfx); + x5c_visorLoopSfx.reset(); + } + + switch (x1c_curVisor) { + case CPlayerState::EPlayerVisor::XRay: + CSfxManager::SfxStart(SFXui_outof_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + case CPlayerState::EPlayerVisor::Scan: + if (x60_scanningLoopSfx) { + CSfxManager::SfxStop(x60_scanningLoopSfx); + x60_scanningLoopSfx.reset(); } + CSfxManager::SfxStart(SFXui_outof_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + case CPlayerState::EPlayerVisor::Thermal: + CSfxManager::SfxStart(SFXui_outof_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + default: + break; + } } -void CPlayerVisor::BeginTransitionOut() -{ - if (x5c_visorLoopSfx) - { - CSfxManager::SfxStop(x5c_visorLoopSfx); - x5c_visorLoopSfx.reset(); - } +void CPlayerVisor::Update(float dt, const CStateManager& mgr) { + x90_xrayBlur.Update(dt); - switch (x1c_curVisor) - { - case CPlayerState::EPlayerVisor::XRay: - CSfxManager::SfxStart(SFXui_outof_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); - break; - case CPlayerState::EPlayerVisor::Scan: - if (x60_scanningLoopSfx) - { - CSfxManager::SfxStop(x60_scanningLoopSfx); - x60_scanningLoopSfx.reset(); - } - CSfxManager::SfxStart(SFXui_outof_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); - break; - case CPlayerState::EPlayerVisor::Thermal: - CSfxManager::SfxStart(SFXui_outof_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId); - break; - default: break; + CPlayerState& playerState = *mgr.GetPlayerState(); + CPlayerState::EPlayerVisor activeVisor = playerState.GetActiveVisor(mgr); + CPlayerState::EPlayerVisor curVisor = playerState.GetCurrentVisor(); + CPlayerState::EPlayerVisor transVisor = playerState.GetTransitioningVisor(); + bool visorTransitioning = playerState.GetIsVisorTransitioning(); + + UpdateScanWindow(dt, mgr); + + if (x20_nextVisor != transVisor) + x20_nextVisor = transVisor; + + LockUnlockAssets(); + + if (mgr.GetPlayer().GetScanningState() == CPlayer::EPlayerScanState::ScanComplete) + x2c_scanDimInterp = std::max(0.f, x2c_scanDimInterp - 2.f * dt); + else + x2c_scanDimInterp = std::min(x2c_scanDimInterp + 2.f * dt, 1.f); + + if (visorTransitioning) { + if (!x25_24_visorTransitioning) + BeginTransitionOut(); + if (x1c_curVisor != curVisor) { + FinishTransitionOut(mgr); + x1c_curVisor = curVisor; + BeginTransitionIn(mgr); } + UpdateCurrentVisor(playerState.GetVisorTransitionFactor()); + } else { + if (x25_24_visorTransitioning) { + FinishTransitionIn(); + } else if (curVisor == CPlayerState::EPlayerVisor::Scan) { + zeus::CColor dimColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanVisorScreenDimColor(), + g_tweakGuiColors->GetScanVisorHudLightMultiply(), x2c_scanDimInterp); + x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, dimColor, -1); + } + } + + x25_24_visorTransitioning = visorTransitioning; + + if (x1c_curVisor != activeVisor) { + if (x24_visorSfxVol != 0.f) { + x24_visorSfxVol = 0.f; + CSfxManager::SfxVolume(x5c_visorLoopSfx, x24_visorSfxVol); + CSfxManager::SfxVolume(x60_scanningLoopSfx, x24_visorSfxVol); + } + } else { + if (x24_visorSfxVol != 1.f) { + x24_visorSfxVol = 1.f; + CSfxManager::SfxVolume(x5c_visorLoopSfx, x24_visorSfxVol); + CSfxManager::SfxVolume(x60_scanningLoopSfx, x24_visorSfxVol); + } + } + + float scanMag = g_tweakGui->GetScanWindowMagnification(); + if (x58_scanMagInterp < scanMag) + x58_scanMagInterp = std::min(x58_scanMagInterp + 2.f * dt, scanMag); + else + x58_scanMagInterp = std::max(x58_scanMagInterp - 2.f * dt, scanMag); } -void CPlayerVisor::Update(float dt, const CStateManager& mgr) -{ - x90_xrayBlur.Update(dt); - - CPlayerState& playerState = *mgr.GetPlayerState(); - CPlayerState::EPlayerVisor activeVisor = playerState.GetActiveVisor(mgr); - CPlayerState::EPlayerVisor curVisor = playerState.GetCurrentVisor(); - CPlayerState::EPlayerVisor transVisor = playerState.GetTransitioningVisor(); - bool visorTransitioning = playerState.GetIsVisorTransitioning(); - - UpdateScanWindow(dt, mgr); - - if (x20_nextVisor != transVisor) - x20_nextVisor = transVisor; - - LockUnlockAssets(); - - if (mgr.GetPlayer().GetScanningState() == CPlayer::EPlayerScanState::ScanComplete) - x2c_scanDimInterp = std::max(0.f, x2c_scanDimInterp - 2.f * dt); - else - x2c_scanDimInterp = std::min(x2c_scanDimInterp + 2.f * dt, 1.f); - - if (visorTransitioning) - { - if (!x25_24_visorTransitioning) - BeginTransitionOut(); - if (x1c_curVisor != curVisor) - { - FinishTransitionOut(mgr); - x1c_curVisor = curVisor; - BeginTransitionIn(mgr); - } - UpdateCurrentVisor(playerState.GetVisorTransitionFactor()); - } - else - { - if (x25_24_visorTransitioning) - { - FinishTransitionIn(); - } - else if (curVisor == CPlayerState::EPlayerVisor::Scan) - { - zeus::CColor dimColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanVisorScreenDimColor(), - g_tweakGuiColors->GetScanVisorHudLightMultiply(), - x2c_scanDimInterp); - x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, dimColor, -1); - } - } - - x25_24_visorTransitioning = visorTransitioning; - - if (x1c_curVisor != activeVisor) - { - if (x24_visorSfxVol != 0.f) - { - x24_visorSfxVol = 0.f; - CSfxManager::SfxVolume(x5c_visorLoopSfx, x24_visorSfxVol); - CSfxManager::SfxVolume(x60_scanningLoopSfx, x24_visorSfxVol); - } - } - else - { - if (x24_visorSfxVol != 1.f) - { - x24_visorSfxVol = 1.f; - CSfxManager::SfxVolume(x5c_visorLoopSfx, x24_visorSfxVol); - CSfxManager::SfxVolume(x60_scanningLoopSfx, x24_visorSfxVol); - } - } - - float scanMag = g_tweakGui->GetScanWindowMagnification(); - if (x58_scanMagInterp < scanMag) - x58_scanMagInterp = std::min(x58_scanMagInterp + 2.f * dt, scanMag); - else - x58_scanMagInterp = std::max(x58_scanMagInterp - 2.f * dt, scanMag); +void CPlayerVisor::Draw(const CStateManager& mgr, const CTargetingManager* tgtManager) const { + CGraphics::SetAmbientColor(zeus::CColor::skWhite); + CGraphics::DisableAllLights(); + switch (mgr.GetPlayerState()->GetActiveVisor(mgr)) { + case CPlayerState::EPlayerVisor::XRay: + DrawXRayEffect(mgr); + break; + case CPlayerState::EPlayerVisor::Thermal: + DrawThermalEffect(mgr); + break; + case CPlayerState::EPlayerVisor::Scan: + DrawScanEffect(mgr, tgtManager); + break; + default: + break; + } } -void CPlayerVisor::Draw(const CStateManager& mgr, const CTargetingManager* tgtManager) const -{ - CGraphics::SetAmbientColor(zeus::CColor::skWhite); - CGraphics::DisableAllLights(); - switch (mgr.GetPlayerState()->GetActiveVisor(mgr)) - { - case CPlayerState::EPlayerVisor::XRay: - DrawXRayEffect(mgr); - break; - case CPlayerState::EPlayerVisor::Thermal: - DrawThermalEffect(mgr); - break; - case CPlayerState::EPlayerVisor::Scan: - DrawScanEffect(mgr, tgtManager); - break; - default: break; - } +void CPlayerVisor::Touch() { + if (x124_scanIconNoncritical.IsLoaded()) + x124_scanIconNoncritical->Touch(0); + if (x130_scanIconCritical.IsLoaded()) + x130_scanIconCritical->Touch(0); } -void CPlayerVisor::Touch() -{ - if (x124_scanIconNoncritical.IsLoaded()) - x124_scanIconNoncritical->Touch(0); - if (x130_scanIconCritical.IsLoaded()) - x130_scanIconCritical->Touch(0); +float CPlayerVisor::GetDesiredViewportScaleX(const CStateManager& mgr) const { + return mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Combat ? 1.f : xc4_vpScaleX; } -float CPlayerVisor::GetDesiredViewportScaleX(const CStateManager& mgr) const -{ - return mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Combat ? 1.f : xc4_vpScaleX; +float CPlayerVisor::GetDesiredViewportScaleY(const CStateManager& mgr) const { + return mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Combat ? 1.f : xc8_vpScaleY; } -float CPlayerVisor::GetDesiredViewportScaleY(const CStateManager& mgr) const -{ - return mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Combat ? 1.f : xc8_vpScaleY; -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CPlayerVisor.hpp b/Runtime/MP1/CPlayerVisor.hpp index 2247be6f4..c67e69603 100644 --- a/Runtime/MP1/CPlayerVisor.hpp +++ b/Runtime/MP1/CPlayerVisor.hpp @@ -9,95 +9,85 @@ #include "Graphics/Shaders/CColoredQuadFilter.hpp" #include "Graphics/Shaders/CTexturedQuadFilter.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CTargetingManager; -namespace MP1 -{ +namespace MP1 { -class CPlayerVisor -{ - struct SScanTarget - { - TUniqueId x0_objId = kInvalidUniqueId; - float x4_timer = 0.f; - float x8_inRangeTimer = 0.f; - bool xc_inBox = false; - }; +class CPlayerVisor { + struct SScanTarget { + TUniqueId x0_objId = kInvalidUniqueId; + float x4_timer = 0.f; + float x8_inRangeTimer = 0.f; + bool xc_inBox = false; + }; - enum class EScanWindowState - { - NotInScanVisor, - Idle, - Scan - }; + enum class EScanWindowState { NotInScanVisor, Idle, Scan }; - rstl::reserved_vector x0_scanWindowSizes; - CPlayerState::EPlayerVisor x1c_curVisor = CPlayerState::EPlayerVisor::Combat; - CPlayerState::EPlayerVisor x20_nextVisor = CPlayerState::EPlayerVisor::Combat; - float x24_visorSfxVol = 1.f; // used to be u8 - bool x25_24_visorTransitioning : 1; - bool x25_25_ : 1; - float x28_ = 0.f; - float x2c_scanDimInterp = 1.f; - EScanWindowState x30_prevState = EScanWindowState::NotInScanVisor; - EScanWindowState x34_nextState = EScanWindowState::NotInScanVisor; - float x38_windowInterpDuration = 0.f; - float x3c_windowInterpTimer = 0.f; - zeus::CVector2f x40_prevWindowDims; - zeus::CVector2f x48_interpWindowDims; - zeus::CVector2f x50_nextWindowDims; - float x58_scanMagInterp = 1.f; - CSfxHandle x5c_visorLoopSfx; - CSfxHandle x60_scanningLoopSfx; - CCameraFilterPass x64_scanDim; - CCameraBlurPass x90_xrayBlur; - float xc4_vpScaleX = 1.f; - float xc8_vpScaleY = 1.f; - TLockedToken xcc_scanFrameCorner; - TLockedToken xd8_scanFrameCenterSide; - TLockedToken xe4_scanFrameCenterTop; - TLockedToken xf0_scanFrameStretchSide; - TLockedToken xfc_scanFrameStretchTop; - //TCachedToken x108_newScanPane; - CTexturedQuadFilter x108_newScanPane; - TLockedToken x114_scanShield; - int x120_assetLockCountdown = 0; - TLockedToken x124_scanIconNoncritical; - TLockedToken x130_scanIconCritical; - rstl::reserved_vector x13c_scanTargets; - TLockedToken x540_xrayPalette; - float x54c_scanFrameColorInterp = 0.f; - float x550_scanFrameColorImpulseInterp = 0.f; + rstl::reserved_vector x0_scanWindowSizes; + CPlayerState::EPlayerVisor x1c_curVisor = CPlayerState::EPlayerVisor::Combat; + CPlayerState::EPlayerVisor x20_nextVisor = CPlayerState::EPlayerVisor::Combat; + float x24_visorSfxVol = 1.f; // used to be u8 + bool x25_24_visorTransitioning : 1; + bool x25_25_ : 1; + float x28_ = 0.f; + float x2c_scanDimInterp = 1.f; + EScanWindowState x30_prevState = EScanWindowState::NotInScanVisor; + EScanWindowState x34_nextState = EScanWindowState::NotInScanVisor; + float x38_windowInterpDuration = 0.f; + float x3c_windowInterpTimer = 0.f; + zeus::CVector2f x40_prevWindowDims; + zeus::CVector2f x48_interpWindowDims; + zeus::CVector2f x50_nextWindowDims; + float x58_scanMagInterp = 1.f; + CSfxHandle x5c_visorLoopSfx; + CSfxHandle x60_scanningLoopSfx; + CCameraFilterPass x64_scanDim; + CCameraBlurPass x90_xrayBlur; + float xc4_vpScaleX = 1.f; + float xc8_vpScaleY = 1.f; + TLockedToken xcc_scanFrameCorner; + TLockedToken xd8_scanFrameCenterSide; + TLockedToken xe4_scanFrameCenterTop; + TLockedToken xf0_scanFrameStretchSide; + TLockedToken xfc_scanFrameStretchTop; + // TCachedToken x108_newScanPane; + CTexturedQuadFilter x108_newScanPane; + TLockedToken x114_scanShield; + int x120_assetLockCountdown = 0; + TLockedToken x124_scanIconNoncritical; + TLockedToken x130_scanIconCritical; + rstl::reserved_vector x13c_scanTargets; + TLockedToken x540_xrayPalette; + float x54c_scanFrameColorInterp = 0.f; + float x550_scanFrameColorImpulseInterp = 0.f; - int FindEmptyInactiveScanTarget() const; - int FindCachedInactiveScanTarget(TUniqueId uid) const; - bool DrawScanObjectIndicators(const CStateManager& mgr) const; - void UpdateScanObjectIndicators(const CStateManager& mgr, float dt); - void UpdateScanWindow(float dt, const CStateManager& mgr); - EScanWindowState GetDesiredScanWindowState(const CStateManager& mgr) const; - void LockUnlockAssets(); - void DrawScanEffect(const CStateManager& mgr, const CTargetingManager* tgtMgr) const; - void DrawXRayEffect(const CStateManager& mgr) const; - void DrawThermalEffect(const CStateManager& mgr) const; - void UpdateCurrentVisor(float transFactor); - void FinishTransitionIn(); - void BeginTransitionIn(const CStateManager& mgr); - void FinishTransitionOut(const CStateManager& mgr); - void BeginTransitionOut(); + int FindEmptyInactiveScanTarget() const; + int FindCachedInactiveScanTarget(TUniqueId uid) const; + bool DrawScanObjectIndicators(const CStateManager& mgr) const; + void UpdateScanObjectIndicators(const CStateManager& mgr, float dt); + void UpdateScanWindow(float dt, const CStateManager& mgr); + EScanWindowState GetDesiredScanWindowState(const CStateManager& mgr) const; + void LockUnlockAssets(); + void DrawScanEffect(const CStateManager& mgr, const CTargetingManager* tgtMgr) const; + void DrawXRayEffect(const CStateManager& mgr) const; + void DrawThermalEffect(const CStateManager& mgr) const; + void UpdateCurrentVisor(float transFactor); + void FinishTransitionIn(); + void BeginTransitionIn(const CStateManager& mgr); + void FinishTransitionOut(const CStateManager& mgr); + void BeginTransitionOut(); public: - CPlayerVisor(CStateManager& stateMgr); - ~CPlayerVisor(); - void Update(float dt, const CStateManager& stateMgr); - void Draw(const CStateManager& stateMgr, const CTargetingManager* tgtManager) const; - void Touch(); - float GetDesiredViewportScaleX(const CStateManager& stateMgr) const; - float GetDesiredViewportScaleY(const CStateManager& stateMgr) const; + CPlayerVisor(CStateManager& stateMgr); + ~CPlayerVisor(); + void Update(float dt, const CStateManager& stateMgr); + void Draw(const CStateManager& stateMgr, const CTargetingManager* tgtManager) const; + void Touch(); + float GetDesiredViewportScaleX(const CStateManager& stateMgr) const; + float GetDesiredViewportScaleY(const CStateManager& stateMgr) const; }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CPreFrontEnd.cpp b/Runtime/MP1/CPreFrontEnd.cpp index 074eb4255..f7f51b516 100644 --- a/Runtime/MP1/CPreFrontEnd.cpp +++ b/Runtime/MP1/CPreFrontEnd.cpp @@ -3,35 +3,28 @@ #include "GameGlobalObjects.hpp" #include "MP1.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CPreFrontEnd::CPreFrontEnd() -: CIOWin("Pre front-end window") -{ +CPreFrontEnd::CPreFrontEnd() : CIOWin("Pre front-end window") {} +CIOWin::EMessageReturn CPreFrontEnd::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue&) { + if (msg.GetType() != EArchMsgType::TimerTick) + return EMessageReturn::Normal; + + CMain* m = static_cast(g_Main); + if (CResLoader* loader = g_ResFactory->GetResLoader()) + if (!loader->AreAllPaksLoaded()) + return EMessageReturn::Exit; + if (!x14_resourceTweaksRegistered) { + m->RegisterResourceTweaks(); + x14_resourceTweaksRegistered = true; + } + m->MemoryCardInitializePump(); + if (!g_MemoryCardSys) + return EMessageReturn::Exit; + if (!m->LoadAudio()) + return EMessageReturn::Exit; + return EMessageReturn::RemoveIOWinAndExit; } -CIOWin::EMessageReturn CPreFrontEnd::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue&) -{ - if (msg.GetType() != EArchMsgType::TimerTick) - return EMessageReturn::Normal; - - CMain* m = static_cast(g_Main); - if (CResLoader* loader = g_ResFactory->GetResLoader()) - if (!loader->AreAllPaksLoaded()) - return EMessageReturn::Exit; - if (!x14_resourceTweaksRegistered) - { - m->RegisterResourceTweaks(); - x14_resourceTweaksRegistered = true; - } - m->MemoryCardInitializePump(); - if (!g_MemoryCardSys) - return EMessageReturn::Exit; - if (!m->LoadAudio()) - return EMessageReturn::Exit; - return EMessageReturn::RemoveIOWinAndExit; -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CPreFrontEnd.hpp b/Runtime/MP1/CPreFrontEnd.hpp index bcac54ff8..349594653 100644 --- a/Runtime/MP1/CPreFrontEnd.hpp +++ b/Runtime/MP1/CPreFrontEnd.hpp @@ -2,16 +2,14 @@ #include "CIOWin.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { + +class CPreFrontEnd : public CIOWin { + bool x14_resourceTweaksRegistered = false; -class CPreFrontEnd : public CIOWin -{ - bool x14_resourceTweaksRegistered = false; public: - CPreFrontEnd(); - EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); + CPreFrontEnd(); + EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CQuitGameScreen.cpp b/Runtime/MP1/CQuitGameScreen.cpp index f78ca0e81..585ca96bb 100644 --- a/Runtime/MP1/CQuitGameScreen.cpp +++ b/Runtime/MP1/CQuitGameScreen.cpp @@ -9,111 +9,89 @@ #include "GuiSys/CGuiWidgetDrawParms.hpp" #include "Audio/CSfxManager.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -static const int Titles[] = -{ - 24, 25, 26, 27, 28 -}; +static const int Titles[] = {24, 25, 26, 27, 28}; -static const int DefaultSelections[] = -{ - 1, 0, 1, 1, 0 -}; +static const int DefaultSelections[] = {1, 0, 1, 1, 0}; -static const float VerticalOffsets[] = -{ - 0.f, 1.6f, 1.f, 0.f, 1.f -}; +static const float VerticalOffsets[] = {0.f, 1.6f, 1.f, 0.f, 1.f}; -void CQuitGameScreen::SetColors() -{ - x14_tablegroup_quitgame->SetColors(zeus::CColor{0.784313f, 0.784313f, 0.784313f, 1.f}, - zeus::CColor{0.196078f, 0.196078f, 0.196078f, 1.f}); +void CQuitGameScreen::SetColors() { + x14_tablegroup_quitgame->SetColors(zeus::CColor{0.784313f, 0.784313f, 0.784313f, 1.f}, + zeus::CColor{0.196078f, 0.196078f, 0.196078f, 1.f}); } -void CQuitGameScreen::FinishedLoading() -{ - x10_loadedFrame = x4_frame.GetObj(); - x10_loadedFrame->SetMaxAspect(1.33f); +void CQuitGameScreen::FinishedLoading() { + x10_loadedFrame = x4_frame.GetObj(); + x10_loadedFrame->SetMaxAspect(1.33f); - x14_tablegroup_quitgame = static_cast( - x10_loadedFrame->FindWidget("tablegroup_quitgame")); - x14_tablegroup_quitgame->SetVertical(false); - x14_tablegroup_quitgame->SetMenuAdvanceCallback( - std::bind(&CQuitGameScreen::DoAdvance, this, std::placeholders::_1)); - x14_tablegroup_quitgame->SetMenuSelectionChangeCallback( - std::bind(&CQuitGameScreen::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + x14_tablegroup_quitgame = static_cast(x10_loadedFrame->FindWidget("tablegroup_quitgame")); + x14_tablegroup_quitgame->SetVertical(false); + x14_tablegroup_quitgame->SetMenuAdvanceCallback(std::bind(&CQuitGameScreen::DoAdvance, this, std::placeholders::_1)); + x14_tablegroup_quitgame->SetMenuSelectionChangeCallback( + std::bind(&CQuitGameScreen::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - static_cast(x10_loadedFrame->FindWidget("textpane_title"))->TextSupport(). - SetText(g_MainStringTable->GetString(Titles[int(x0_type)])); + static_cast(x10_loadedFrame->FindWidget("textpane_title")) + ->TextSupport() + .SetText(g_MainStringTable->GetString(Titles[int(x0_type)])); - static_cast(x10_loadedFrame->FindWidget("textpane_yes"))->TextSupport(). - SetText(g_MainStringTable->GetString(22)); - static_cast(x10_loadedFrame->FindWidget("textpane_no"))->TextSupport(). - SetText(g_MainStringTable->GetString(23)); + static_cast(x10_loadedFrame->FindWidget("textpane_yes")) + ->TextSupport() + .SetText(g_MainStringTable->GetString(22)); + static_cast(x10_loadedFrame->FindWidget("textpane_no")) + ->TextSupport() + .SetText(g_MainStringTable->GetString(23)); - x14_tablegroup_quitgame->SetUserSelection(DefaultSelections[int(x0_type)]); - SetColors(); + x14_tablegroup_quitgame->SetUserSelection(DefaultSelections[int(x0_type)]); + SetColors(); } -void CQuitGameScreen::DoSelectionChange(CGuiTableGroup* caller, int oldSel) -{ - SetColors(); - CSfxManager::SfxStart(SFXui_quit_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); +void CQuitGameScreen::DoSelectionChange(CGuiTableGroup* caller, int oldSel) { + SetColors(); + CSfxManager::SfxStart(SFXui_quit_change, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); } -void CQuitGameScreen::DoAdvance(CGuiTableGroup* caller) -{ - if (caller->GetUserSelection() == 0) - { - /* Yes */ - CSfxManager::SfxStart(SFXui_advance, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x18_action = EQuitAction::Yes; - } - else - { - /* No */ - CSfxManager::SfxStart(SFXui_table_change_mode, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x18_action = EQuitAction::No; - } +void CQuitGameScreen::DoAdvance(CGuiTableGroup* caller) { + if (caller->GetUserSelection() == 0) { + /* Yes */ + CSfxManager::SfxStart(SFXui_advance, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x18_action = EQuitAction::Yes; + } else { + /* No */ + CSfxManager::SfxStart(SFXui_table_change_mode, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x18_action = EQuitAction::No; + } } -EQuitAction CQuitGameScreen::Update(float dt) -{ - if (!x10_loadedFrame && x4_frame.IsLoaded()) - FinishedLoading(); - return x18_action; +EQuitAction CQuitGameScreen::Update(float dt) { + if (!x10_loadedFrame && x4_frame.IsLoaded()) + FinishedLoading(); + return x18_action; } -void CQuitGameScreen::Draw() -{ - if (x0_type == EQuitType::QuitGame) - m_blackScreen->draw(zeus::CColor(0.f, 0.5f)); +void CQuitGameScreen::Draw() { + if (x0_type == EQuitType::QuitGame) + m_blackScreen->draw(zeus::CColor(0.f, 0.5f)); - if (x10_loadedFrame) - x10_loadedFrame->Draw(CGuiWidgetDrawParms{1.f, - zeus::CVector3f{0.f, 0.f, VerticalOffsets[int(x0_type)]}}); + if (x10_loadedFrame) + x10_loadedFrame->Draw(CGuiWidgetDrawParms{1.f, zeus::CVector3f{0.f, 0.f, VerticalOffsets[int(x0_type)]}}); } -void CQuitGameScreen::ProcessUserInput(const CFinalInput& input) -{ - if (input.ControllerIdx() != 0) - return; - if (!x10_loadedFrame) - return; - x10_loadedFrame->ProcessUserInput(input); - if (input.PB() && x0_type != EQuitType::ContinueFromLastSave) - x18_action = EQuitAction::No; +void CQuitGameScreen::ProcessUserInput(const CFinalInput& input) { + if (input.ControllerIdx() != 0) + return; + if (!x10_loadedFrame) + return; + x10_loadedFrame->ProcessUserInput(input); + if (input.PB() && x0_type != EQuitType::ContinueFromLastSave) + x18_action = EQuitAction::No; } -CQuitGameScreen::CQuitGameScreen(EQuitType tp) -: x0_type(tp) -{ - x4_frame = g_SimplePool->GetObj("FRME_QuitScreen"); - if (tp == EQuitType::QuitGame) - m_blackScreen.emplace(EFilterType::Blend); +CQuitGameScreen::CQuitGameScreen(EQuitType tp) : x0_type(tp) { + x4_frame = g_SimplePool->GetObj("FRME_QuitScreen"); + if (tp == EQuitType::QuitGame) + m_blackScreen.emplace(EFilterType::Blend); } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CQuitGameScreen.hpp b/Runtime/MP1/CQuitGameScreen.hpp index 610ac2a57..b688d1251 100644 --- a/Runtime/MP1/CQuitGameScreen.hpp +++ b/Runtime/MP1/CQuitGameScreen.hpp @@ -4,51 +4,36 @@ #include "CToken.hpp" #include "Graphics/Shaders/CColoredQuadFilter.hpp" -namespace urde -{ +namespace urde { struct CFinalInput; class CGuiFrame; class CGuiTableGroup; class CGuiTextPane; -namespace MP1 -{ +namespace MP1 { -enum class EQuitType -{ - QuitGame, - ContinueFromLastSave, - SaveProgress, - QuitNESMetroid, - ContinuePlaying -}; +enum class EQuitType { QuitGame, ContinueFromLastSave, SaveProgress, QuitNESMetroid, ContinuePlaying }; -enum class EQuitAction -{ - None, - Yes, - No -}; +enum class EQuitAction { None, Yes, No }; + +class CQuitGameScreen { + EQuitType x0_type; + TLockedToken x4_frame; + CGuiFrame* x10_loadedFrame = nullptr; + CGuiTableGroup* x14_tablegroup_quitgame = nullptr; + EQuitAction x18_action = EQuitAction::None; + std::experimental::optional m_blackScreen; + void SetColors(); -class CQuitGameScreen -{ - EQuitType x0_type; - TLockedToken x4_frame; - CGuiFrame* x10_loadedFrame = nullptr; - CGuiTableGroup* x14_tablegroup_quitgame = nullptr; - EQuitAction x18_action = EQuitAction::None; - std::experimental::optional m_blackScreen; - void SetColors(); public: - void FinishedLoading(); - void DoSelectionChange(CGuiTableGroup* caller, int oldSel); - void DoAdvance(CGuiTableGroup* caller); - EQuitAction Update(float dt); - void Draw(); - void ProcessUserInput(const CFinalInput& input); - CQuitGameScreen(EQuitType type); + void FinishedLoading(); + void DoSelectionChange(CGuiTableGroup* caller, int oldSel); + void DoAdvance(CGuiTableGroup* caller); + EQuitAction Update(float dt); + void Draw(); + void ProcessUserInput(const CFinalInput& input); + CQuitGameScreen(EQuitType type); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CSamusDoll.cpp b/Runtime/MP1/CSamusDoll.cpp index 01415fee0..6e5b28886 100644 --- a/Runtime/MP1/CSamusDoll.cpp +++ b/Runtime/MP1/CSamusDoll.cpp @@ -7,547 +7,373 @@ #include "Graphics/CBooRenderer.hpp" #include "World/CMorphBall.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { const zeus::CVector3f CSamusDoll::skInitialOffset = {0.f, 0.f, 0.8f}; -static const std::pair SpiderBallGlassModels[] = -{ - {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 1}, - {"SamusPhazonBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 1}, - {"SamusPhazonBallGlassCMDL", 0}, +static const std::pair SpiderBallGlassModels[] = { + {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 1}, + {"SamusPhazonBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 1}, {"SamusPhazonBallGlassCMDL", 0}, }; -static const std::pair SpiderBallCharacters[] = -{ - {"SamusSpiderBallANCS", 0}, - {"SamusSpiderBallANCS", 0}, - {"SamusSpiderBallANCS", 1}, - {"SamusPhazonBallANCS", 0}, - {"SamusFusionBallANCS", 0}, - {"SamusFusionBallANCS", 2}, - {"SamusFusionBallANCS", 1}, - {"SamusFusionBallANCS", 3}, +static const std::pair SpiderBallCharacters[] = { + {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 1}, {"SamusPhazonBallANCS", 0}, + {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}, }; -static const std::pair BallCharacters[] = -{ - {"SamusBallANCS", 0}, - {"SamusBallANCS", 0}, - {"SamusBallANCS", 1}, - {"SamusBallANCS", 0}, - {"SamusFusionBallANCS", 0}, - {"SamusFusionBallANCS", 2}, - {"SamusFusionBallANCS", 1}, - {"SamusFusionBallANCS", 3}, +static const std::pair BallCharacters[] = { + {"SamusBallANCS", 0}, {"SamusBallANCS", 0}, {"SamusBallANCS", 1}, {"SamusBallANCS", 0}, + {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}, }; -static const u32 SpiderBallGlowColorIdxs[] = -{ - 3, 3, 2, 4, 5, 7, 6, 8 -}; +static const u32 SpiderBallGlowColorIdxs[] = {3, 3, 2, 4, 5, 7, 6, 8}; -static const u32 BallGlowColorIdxs[] = -{ - 0, 0, 1, 0, 5, 7, 6, 8 -}; +static const u32 BallGlowColorIdxs[] = {0, 0, 1, 0, 5, 7, 6, 8}; -static const char* BeamModels[] = -{ - "CMDL_InvPowerBeam", - "CMDL_InvIceBeam", - "CMDL_InvWaveBeam", - "CMDL_InvPlasmaBeam", - "CMDL_InvPowerBeam" -}; +static const char* BeamModels[] = {"CMDL_InvPowerBeam", "CMDL_InvIceBeam", "CMDL_InvWaveBeam", "CMDL_InvPlasmaBeam", + "CMDL_InvPowerBeam"}; -static const char* VisorModels[] = -{ - "CMDL_InvVisor", - "CMDL_InvGravityVisor", - "CMDL_InvVisor", - "CMDL_InvPhazonVisor", - "CMDL_InvFusionVisor", - "CMDL_InvFusionVisor", - "CMDL_InvFusionVisor", - "CMDL_InvFusionVisor" -}; +static const char* VisorModels[] = {"CMDL_InvVisor", "CMDL_InvGravityVisor", "CMDL_InvVisor", + "CMDL_InvPhazonVisor", "CMDL_InvFusionVisor", "CMDL_InvFusionVisor", + "CMDL_InvFusionVisor", "CMDL_InvFusionVisor"}; -static const char* FinModels[] = -{ - "CMDL_InvPowerFins", - "CMDL_InvPowerFins", - "CMDL_InvPowerFins", - "CMDL_InvPowerFins", - "CMDL_InvPowerFins", - "CMDL_InvVariaFins", - "CMDL_InvGravityFins", - "CMDL_InvPhazonFins" -}; +static const char* FinModels[] = {"CMDL_InvPowerFins", "CMDL_InvPowerFins", "CMDL_InvPowerFins", + "CMDL_InvPowerFins", "CMDL_InvPowerFins", "CMDL_InvVariaFins", + "CMDL_InvGravityFins", "CMDL_InvPhazonFins"}; -static const u32 Character1Idxs[8] = -{ - 0, 6, 2, 10, 16, 24, 20, 28 -}; +static const u32 Character1Idxs[8] = {0, 6, 2, 10, 16, 24, 20, 28}; -static const u32 CharacterBootsIdxs[8] = -{ - 1, 7, 3, 11, 17, 25, 21, 29 -}; +static const u32 CharacterBootsIdxs[8] = {1, 7, 3, 11, 17, 25, 21, 29}; -static const u32 Character2and3Idxs[8][2] = -{ - {14, 15}, - {8, 9}, - {4, 5}, - {12, 13}, - {18, 19}, - {26, 27}, - {22, 23}, - {30, 31} -}; +static const u32 Character2and3Idxs[8][2] = {{14, 15}, {8, 9}, {4, 5}, {12, 13}, + {18, 19}, {26, 27}, {22, 23}, {30, 31}}; CSamusDoll::CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp, - CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam, - bool hasSpiderBall, bool hasGrappleBeam) -: x10_ballXf(zeus::CTransform::Translate(0.f, 0.f, 0.625f * g_tweakPlayer->GetPlayerBallHalfExtent())), - x44_suit(suit), x48_beam(beam) -{ - x70_fixedRot.rotateZ(M_PIF); - x90_userInterpRot = xb0_userRot = x70_fixedRot; - x1d4_spiderBallGlass = g_SimplePool->GetObj(SpiderBallGlassModels[int(suit)].first); - x1e0_ballMatIdx = hasSpiderBall ? SpiderBallCharacters[int(suit)].second : BallCharacters[int(suit)].second; - x1e4_glassMatIdx = SpiderBallGlassModels[int(suit)].second; - x1e8_ballGlowColorIdx = hasSpiderBall ? SpiderBallGlowColorIdxs[int(suit)] : BallGlowColorIdxs[int(suit)]; - x1ec_itemScreenSamus = g_SimplePool->GetObj("ANCS_ItemScreenSamus"); - x1f4_invBeam = g_SimplePool->GetObj(BeamModels[int(beam)]); - x200_invVisor = g_SimplePool->GetObj(VisorModels[int(suit)]); - x20c_invGrappleBeam = g_SimplePool->GetObj("CMDL_InvGrappleBeam"); - x218_invFins = g_SimplePool->GetObj(FinModels[int(suit)]); - x224_ballInnerGlow = g_SimplePool->GetObj("BallInnerGlow"); - x22c_ballInnerGlowGen = std::make_unique(x224_ballInnerGlow); - x230_ballTransitionFlash = g_SimplePool->GetObj("MorphBallTransitionFlash"); - x23c_lights.push_back(CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skWhite)); - x24c_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f); - x270_24_hasSpiderBall = hasSpiderBall; - x270_25_hasGrappleBeam = hasGrappleBeam; - x22c_ballInnerGlowGen->SetGlobalScale(zeus::CVector3f(0.625f)); - x0_depToks.reserve(suitDgrp.GetObjectTagVector().size() + ballDgrp.GetObjectTagVector().size()); - for (const SObjectTag& tag : suitDgrp.GetObjectTagVector()) - { - x0_depToks.push_back(g_SimplePool->GetObj(tag)); - x0_depToks.back().Lock(); - } - for (const SObjectTag& tag : ballDgrp.GetObjectTagVector()) - { - x0_depToks.push_back(g_SimplePool->GetObj(tag)); - x0_depToks.back().Lock(); - } + CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam, bool hasSpiderBall, + bool hasGrappleBeam) +: x10_ballXf(zeus::CTransform::Translate(0.f, 0.f, 0.625f * g_tweakPlayer->GetPlayerBallHalfExtent())) +, x44_suit(suit) +, x48_beam(beam) { + x70_fixedRot.rotateZ(M_PIF); + x90_userInterpRot = xb0_userRot = x70_fixedRot; + x1d4_spiderBallGlass = g_SimplePool->GetObj(SpiderBallGlassModels[int(suit)].first); + x1e0_ballMatIdx = hasSpiderBall ? SpiderBallCharacters[int(suit)].second : BallCharacters[int(suit)].second; + x1e4_glassMatIdx = SpiderBallGlassModels[int(suit)].second; + x1e8_ballGlowColorIdx = hasSpiderBall ? SpiderBallGlowColorIdxs[int(suit)] : BallGlowColorIdxs[int(suit)]; + x1ec_itemScreenSamus = g_SimplePool->GetObj("ANCS_ItemScreenSamus"); + x1f4_invBeam = g_SimplePool->GetObj(BeamModels[int(beam)]); + x200_invVisor = g_SimplePool->GetObj(VisorModels[int(suit)]); + x20c_invGrappleBeam = g_SimplePool->GetObj("CMDL_InvGrappleBeam"); + x218_invFins = g_SimplePool->GetObj(FinModels[int(suit)]); + x224_ballInnerGlow = g_SimplePool->GetObj("BallInnerGlow"); + x22c_ballInnerGlowGen = std::make_unique(x224_ballInnerGlow); + x230_ballTransitionFlash = g_SimplePool->GetObj("MorphBallTransitionFlash"); + x23c_lights.push_back(CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skWhite)); + x24c_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f); + x270_24_hasSpiderBall = hasSpiderBall; + x270_25_hasGrappleBeam = hasGrappleBeam; + x22c_ballInnerGlowGen->SetGlobalScale(zeus::CVector3f(0.625f)); + x0_depToks.reserve(suitDgrp.GetObjectTagVector().size() + ballDgrp.GetObjectTagVector().size()); + for (const SObjectTag& tag : suitDgrp.GetObjectTagVector()) { + x0_depToks.push_back(g_SimplePool->GetObj(tag)); + x0_depToks.back().Lock(); + } + for (const SObjectTag& tag : ballDgrp.GetObjectTagVector()) { + x0_depToks.push_back(g_SimplePool->GetObj(tag)); + x0_depToks.back().Lock(); + } } -bool CSamusDoll::IsLoaded() const -{ - if (x270_31_loaded) - return true; - if (!x1ec_itemScreenSamus.IsLoaded()) - return false; - if (!x1f4_invBeam.IsLoaded()) - return false; - if (!x200_invVisor.IsLoaded()) - return false; - if (!x20c_invGrappleBeam.IsLoaded()) - return false; - if (!x1d4_spiderBallGlass.IsLoaded()) - return false; - if (x218_invFins && !x218_invFins.IsLoaded()) - return false; - return xc8_suitModel0.operator bool(); -} - -CModelData CSamusDoll::BuildSuitModelData1(CPlayerState::EPlayerSuit suit) -{ - CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, - Character1Idxs[int(suit)], zeus::CVector3f::skOne, 2, true)); - CAnimPlaybackParms parms(2, -1, 1.f, true); - ret.AnimationData()->SetAnimation(parms, false); - return ret; -} - -CModelData CSamusDoll::BuildSuitModelDataBoots(CPlayerState::EPlayerSuit suit) -{ - CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, - CharacterBootsIdxs[int(suit)], zeus::CVector3f::skOne, 2, true)); - CAnimPlaybackParms parms(2, -1, 1.f, true); - ret.AnimationData()->SetAnimation(parms, false); - return ret; -} - -bool CSamusDoll::CheckLoadComplete() -{ - if (IsLoaded()) - return true; - - for (const CToken& tok : x0_depToks) - if (!tok.IsLoaded()) - return false; - - xc8_suitModel0.emplace(BuildSuitModelData1(x44_suit)); - for (int i=0 ; i<2 ; ++i) - { - CAnimRes res(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, - Character2and3Idxs[int(x44_suit)][i], - zeus::CVector3f::skOne, 2, true); - CModelData mData(res); - x118_suitModel1and2.push_back(mData.GetAnimationData()->GetModelData()); - x118_suitModel1and2.back().Lock(); - } - x134_suitModelBoots.emplace(BuildSuitModelDataBoots(x44_suit)); - - CAnimRes res(g_ResFactory->GetResourceIdByName(x270_24_hasSpiderBall ? - SpiderBallCharacters[int(x44_suit)].first : - BallCharacters[int(x44_suit)].first)->id, - 0, zeus::CVector3f::skOne, 0, true); - x184_ballModelData.emplace(res); - x1e0_ballMatIdx = x270_24_hasSpiderBall ? - SpiderBallCharacters[int(x44_suit)].second : - BallCharacters[int(x44_suit)].second; - x270_31_loaded = true; +bool CSamusDoll::IsLoaded() const { + if (x270_31_loaded) return true; + if (!x1ec_itemScreenSamus.IsLoaded()) + return false; + if (!x1f4_invBeam.IsLoaded()) + return false; + if (!x200_invVisor.IsLoaded()) + return false; + if (!x20c_invGrappleBeam.IsLoaded()) + return false; + if (!x1d4_spiderBallGlass.IsLoaded()) + return false; + if (x218_invFins && !x218_invFins.IsLoaded()) + return false; + return xc8_suitModel0.operator bool(); } -void CSamusDoll::Update(float dt, CRandom16& rand) -{ - if (x1f4_invBeam.IsLoaded()) - x1f4_invBeam->Touch(0); - if (x200_invVisor.IsLoaded()) - x200_invVisor->Touch(0); - if (x20c_invGrappleBeam.IsLoaded()) - x20c_invGrappleBeam->Touch(0); - if (x1d4_spiderBallGlass.IsLoaded()) - x1d4_spiderBallGlass->Touch(0); - if (x218_invFins.IsLoaded()) - x218_invFins->Touch(0); +CModelData CSamusDoll::BuildSuitModelData1(CPlayerState::EPlayerSuit suit) { + CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, Character1Idxs[int(suit)], + zeus::CVector3f::skOne, 2, true)); + CAnimPlaybackParms parms(2, -1, 1.f, true); + ret.AnimationData()->SetAnimation(parms, false); + return ret; +} - if (!CheckLoadComplete()) - return; +CModelData CSamusDoll::BuildSuitModelDataBoots(CPlayerState::EPlayerSuit suit) { + CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, CharacterBootsIdxs[int(suit)], + zeus::CVector3f::skOne, 2, true)); + CAnimPlaybackParms parms(2, -1, 1.f, true); + ret.AnimationData()->SetAnimation(parms, false); + return ret; +} - x40_alphaIn = std::min(x40_alphaIn + 2.f * dt, 1.f); - if (x54_remTransitionTime > 0.f) - { - float oldRemTransTime = x54_remTransitionTime; - x54_remTransitionTime = std::max(0.f, x54_remTransitionTime - dt); - if (!x4c_completedMorphball && x4d_selectedMorphball && - oldRemTransTime >= x50_totalTransitionTime - 0.5f && - x54_remTransitionTime < x50_totalTransitionTime - 0.5f) - { - x238_ballTransitionFlashGen = std::make_unique(x230_ballTransitionFlash); - x238_ballTransitionFlashGen->SetGlobalScale(zeus::CVector3f(0.625f)); - } +bool CSamusDoll::CheckLoadComplete() { + if (IsLoaded()) + return true; - if (x54_remTransitionTime == 0.f) - { - x4c_completedMorphball = x4d_selectedMorphball; - if (!x4d_selectedMorphball) - { - xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false); - x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false); - } - } + for (const CToken& tok : x0_depToks) + if (!tok.IsLoaded()) + return false; + + xc8_suitModel0.emplace(BuildSuitModelData1(x44_suit)); + for (int i = 0; i < 2; ++i) { + CAnimRes res(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, Character2and3Idxs[int(x44_suit)][i], + zeus::CVector3f::skOne, 2, true); + CModelData mData(res); + x118_suitModel1and2.push_back(mData.GetAnimationData()->GetModelData()); + x118_suitModel1and2.back().Lock(); + } + x134_suitModelBoots.emplace(BuildSuitModelDataBoots(x44_suit)); + + CAnimRes res(g_ResFactory + ->GetResourceIdByName(x270_24_hasSpiderBall ? SpiderBallCharacters[int(x44_suit)].first + : BallCharacters[int(x44_suit)].first) + ->id, + 0, zeus::CVector3f::skOne, 0, true); + x184_ballModelData.emplace(res); + x1e0_ballMatIdx = + x270_24_hasSpiderBall ? SpiderBallCharacters[int(x44_suit)].second : BallCharacters[int(x44_suit)].second; + x270_31_loaded = true; + return true; +} + +void CSamusDoll::Update(float dt, CRandom16& rand) { + if (x1f4_invBeam.IsLoaded()) + x1f4_invBeam->Touch(0); + if (x200_invVisor.IsLoaded()) + x200_invVisor->Touch(0); + if (x20c_invGrappleBeam.IsLoaded()) + x20c_invGrappleBeam->Touch(0); + if (x1d4_spiderBallGlass.IsLoaded()) + x1d4_spiderBallGlass->Touch(0); + if (x218_invFins.IsLoaded()) + x218_invFins->Touch(0); + + if (!CheckLoadComplete()) + return; + + x40_alphaIn = std::min(x40_alphaIn + 2.f * dt, 1.f); + if (x54_remTransitionTime > 0.f) { + float oldRemTransTime = x54_remTransitionTime; + x54_remTransitionTime = std::max(0.f, x54_remTransitionTime - dt); + if (!x4c_completedMorphball && x4d_selectedMorphball && oldRemTransTime >= x50_totalTransitionTime - 0.5f && + x54_remTransitionTime < x50_totalTransitionTime - 0.5f) { + x238_ballTransitionFlashGen = std::make_unique(x230_ballTransitionFlash); + x238_ballTransitionFlashGen->SetGlobalScale(zeus::CVector3f(0.625f)); } - if (x270_26_pulseSuit) - x58_suitPulseFactor = std::min(x58_suitPulseFactor + 2.f * dt, 1.f); - else - x58_suitPulseFactor = std::max(x58_suitPulseFactor - 2.f * dt, 0.f); - - if (x270_27_pulseBeam) - x5c_beamPulseFactor = std::min(x5c_beamPulseFactor + 2.f * dt, 1.f); - else - x5c_beamPulseFactor = std::max(x5c_beamPulseFactor - 2.f * dt, 0.f); - - if (x270_28_pulseGrapple) - x60_grapplePulseFactor = std::min(x60_grapplePulseFactor + 2.f * dt, 1.f); - else - x60_grapplePulseFactor = std::max(x60_grapplePulseFactor - 2.f * dt, 0.f); - - if (x270_29_pulseBoots) - x64_bootsPulseFactor = std::min(x64_bootsPulseFactor + 2.f * dt, 1.f); - else - x64_bootsPulseFactor = std::max(x64_bootsPulseFactor - 2.f * dt, 0.f); - - if (x270_30_pulseVisor) - x68_visorPulseFactor = std::min(x68_visorPulseFactor + 2.f * dt, 1.f); - else - x68_visorPulseFactor = std::max(x68_visorPulseFactor - 2.f * dt, 0.f); - - if (x4c_completedMorphball) - x6c_ballPulseFactor = std::min(x6c_ballPulseFactor + 2.f * dt, 1.f); - else - x6c_ballPulseFactor = std::max(x6c_ballPulseFactor - 2.f * dt, 0.f); - - if (x44_suit == CPlayerState::EPlayerSuit::Phazon) - { - if (!x250_phazonIndirectTexture) - x250_phazonIndirectTexture = g_SimplePool->GetObj("PhazonIndirectTexture"); - } - else - { - if (x250_phazonIndirectTexture) - x250_phazonIndirectTexture = TLockedToken(); + if (x54_remTransitionTime == 0.f) { + x4c_completedMorphball = x4d_selectedMorphball; + if (!x4d_selectedMorphball) { + xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false); + x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false); + } } + } + if (x270_26_pulseSuit) + x58_suitPulseFactor = std::min(x58_suitPulseFactor + 2.f * dt, 1.f); + else + x58_suitPulseFactor = std::max(x58_suitPulseFactor - 2.f * dt, 0.f); + + if (x270_27_pulseBeam) + x5c_beamPulseFactor = std::min(x5c_beamPulseFactor + 2.f * dt, 1.f); + else + x5c_beamPulseFactor = std::max(x5c_beamPulseFactor - 2.f * dt, 0.f); + + if (x270_28_pulseGrapple) + x60_grapplePulseFactor = std::min(x60_grapplePulseFactor + 2.f * dt, 1.f); + else + x60_grapplePulseFactor = std::max(x60_grapplePulseFactor - 2.f * dt, 0.f); + + if (x270_29_pulseBoots) + x64_bootsPulseFactor = std::min(x64_bootsPulseFactor + 2.f * dt, 1.f); + else + x64_bootsPulseFactor = std::max(x64_bootsPulseFactor - 2.f * dt, 0.f); + + if (x270_30_pulseVisor) + x68_visorPulseFactor = std::min(x68_visorPulseFactor + 2.f * dt, 1.f); + else + x68_visorPulseFactor = std::max(x68_visorPulseFactor - 2.f * dt, 0.f); + + if (x4c_completedMorphball) + x6c_ballPulseFactor = std::min(x6c_ballPulseFactor + 2.f * dt, 1.f); + else + x6c_ballPulseFactor = std::max(x6c_ballPulseFactor - 2.f * dt, 0.f); + + if (x44_suit == CPlayerState::EPlayerSuit::Phazon) { + if (!x250_phazonIndirectTexture) + x250_phazonIndirectTexture = g_SimplePool->GetObj("PhazonIndirectTexture"); + } else { if (x250_phazonIndirectTexture) - { - x260_phazonOffsetAngle += 0.03f; - g_Renderer->AllocatePhazonSuitMaskTexture(); + x250_phazonIndirectTexture = TLockedToken(); + } + + if (x250_phazonIndirectTexture) { + x260_phazonOffsetAngle += 0.03f; + g_Renderer->AllocatePhazonSuitMaskTexture(); + } + + xc8_suitModel0->AdvanceAnimationIgnoreParticles(dt, rand, true); + x134_suitModelBoots->AdvanceAnimationIgnoreParticles(dt, rand, true); + x184_ballModelData->AdvanceAnimationIgnoreParticles(dt, rand, true); + + SetupLights(); + + x22c_ballInnerGlowGen->SetGlobalTranslation(x10_ballXf.origin); + x22c_ballInnerGlowGen->Update(dt); + + if (x238_ballTransitionFlashGen) { + if (x238_ballTransitionFlashGen->IsSystemDeletable()) + x238_ballTransitionFlashGen.reset(); + if (x238_ballTransitionFlashGen) { + x22c_ballInnerGlowGen->SetGlobalTranslation(x10_ballXf.origin); + x22c_ballInnerGlowGen->Update(dt); } + } - xc8_suitModel0->AdvanceAnimationIgnoreParticles(dt, rand, true); - x134_suitModelBoots->AdvanceAnimationIgnoreParticles(dt, rand, true); - x184_ballModelData->AdvanceAnimationIgnoreParticles(dt, rand, true); + if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) { + if (xc4_viewInterp < 0.f) + xc4_viewInterp = std::min(xc4_viewInterp + 3.f * dt, 0.f); + else + xc4_viewInterp = std::min(xc4_viewInterp + 3.f * dt, 1.f); - SetupLights(); + float interp = std::fabs(xc4_viewInterp); + float oneMinusInterp = 1.f - interp; + xa4_offset = x84_interpStartOffset * interp + skInitialOffset * oneMinusInterp; - x22c_ballInnerGlowGen->SetGlobalTranslation(x10_ballXf.origin); - x22c_ballInnerGlowGen->Update(dt); + xb0_userRot = zeus::CQuaternion::slerpShort(x70_fixedRot, x90_userInterpRot, interp); - if (x238_ballTransitionFlashGen) - { - if (x238_ballTransitionFlashGen->IsSystemDeletable()) - x238_ballTransitionFlashGen.reset(); - if (x238_ballTransitionFlashGen) - { - x22c_ballInnerGlowGen->SetGlobalTranslation(x10_ballXf.origin); - x22c_ballInnerGlowGen->Update(dt); - } - } - - if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) - { - if (xc4_viewInterp < 0.f) - xc4_viewInterp = std::min(xc4_viewInterp + 3.f * dt, 0.f); - else - xc4_viewInterp = std::min(xc4_viewInterp + 3.f * dt, 1.f); - - float interp = std::fabs(xc4_viewInterp); - float oneMinusInterp = 1.f - interp; - xa4_offset = x84_interpStartOffset * interp + skInitialOffset * oneMinusInterp; - - xb0_userRot = zeus::CQuaternion::slerpShort(x70_fixedRot, x90_userInterpRot, interp); - - if (xc4_viewInterp <= 0.f) // Zoom out - xc0_userZoom = x80_fixedZoom * oneMinusInterp + xa0_userInterpZoom * interp; - else // Zoom in - xc0_userZoom = x80_fixedZoom * interp + xa0_userInterpZoom * oneMinusInterp; - } + if (xc4_viewInterp <= 0.f) // Zoom out + xc0_userZoom = x80_fixedZoom * oneMinusInterp + xa0_userInterpZoom * interp; + else // Zoom in + xc0_userZoom = x80_fixedZoom * interp + xa0_userInterpZoom * oneMinusInterp; + } } -void CSamusDoll::Draw(const CStateManager& mgr, float alpha) -{ - if (!IsLoaded()) - return; +void CSamusDoll::Draw(const CStateManager& mgr, float alpha) { + if (!IsLoaded()) + return; - alpha *= x40_alphaIn; + alpha *= x40_alphaIn; - float itemPulse = zeus::clamp(0.f, (std::sin(5.f * CGraphics::GetSecondsMod900()) + 1.f) * 0.5f, 1.f) * - (1.f - std::fabs(xc4_viewInterp)); + float itemPulse = zeus::clamp(0.f, (std::sin(5.f * CGraphics::GetSecondsMod900()) + 1.f) * 0.5f, 1.f) * + (1.f - std::fabs(xc4_viewInterp)); - g_Renderer->SetPerspective(55.f, g_Viewport.x8_width, g_Viewport.xc_height, 0.2f, 4096.f); + g_Renderer->SetPerspective(55.f, g_Viewport.x8_width, g_Viewport.xc_height, 0.2f, 4096.f); - CGraphics::SetViewPointMatrix(zeus::CTransform(xb0_userRot, xa4_offset) * - zeus::CTransform::Translate(0.f, xc0_userZoom, 0.f)); + CGraphics::SetViewPointMatrix(zeus::CTransform(xb0_userRot, xa4_offset) * + zeus::CTransform::Translate(0.f, xc0_userZoom, 0.f)); - zeus::CTransform gunXf = xc8_suitModel0->GetScaledLocatorTransform("GUN_LCTR"); - zeus::CTransform visorXf = xc8_suitModel0->GetScaledLocatorTransform("VISOR_LCTR"); - zeus::CTransform grappleXf = xc8_suitModel0->GetScaledLocatorTransform("GRAPPLE_LCTR"); + zeus::CTransform gunXf = xc8_suitModel0->GetScaledLocatorTransform("GUN_LCTR"); + zeus::CTransform visorXf = xc8_suitModel0->GetScaledLocatorTransform("VISOR_LCTR"); + zeus::CTransform grappleXf = xc8_suitModel0->GetScaledLocatorTransform("GRAPPLE_LCTR"); - if (!x4c_completedMorphball || !x4d_selectedMorphball) - { - float suitPulse = itemPulse * x58_suitPulseFactor; - float bootsPulse = std::max(suitPulse, itemPulse * x64_bootsPulseFactor); + if (!x4c_completedMorphball || !x4d_selectedMorphball) { + float suitPulse = itemPulse * x58_suitPulseFactor; + float bootsPulse = std::max(suitPulse, itemPulse * x64_bootsPulseFactor); - bool phazonSuit = x44_suit == CPlayerState::EPlayerSuit::Phazon; - // Enable dst alpha 1.0 + bool phazonSuit = x44_suit == CPlayerState::EPlayerSuit::Phazon; + // Enable dst alpha 1.0 - for (int i=0 ; i<=x118_suitModel1and2.size() ; ++i) - { - TCachedToken backupModelData = xc8_suitModel0->GetAnimationData()->GetModelData(); - if (i < x118_suitModel1and2.size()) - xc8_suitModel0->AnimationData()->SubstituteModelData(x118_suitModel1and2[i]); - xc8_suitModel0->InvSuitDraw(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), - x24c_actorLights.get(), zeus::CColor(1.f, alpha), - zeus::CColor(1.f, alpha * suitPulse)); - xc8_suitModel0->AnimationData()->SubstituteModelData(backupModelData); - } - - x134_suitModelBoots->InvSuitDraw(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), - x24c_actorLights.get(), zeus::CColor(1.f, alpha), - zeus::CColor(1.f, alpha * bootsPulse)); - - { - CGraphics::SetModelMatrix(gunXf); - x1f4_invBeam->GetInstance().ActivateLights(x23c_lights); - CModelFlags flags = {}; - - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - flags.x4_color = zeus::CColor::skWhite; - x1f4_invBeam->Draw(flags); - - flags.m_extendedShader = EExtendedShader::ForcedAlpha; - flags.x4_color = zeus::CColor(1.f, alpha); - x1f4_invBeam->Draw(flags); - - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x4_color = zeus::CColor(1.f, alpha * itemPulse * x5c_beamPulseFactor); - x1f4_invBeam->Draw(flags); - } - - { - CGraphics::SetModelMatrix(visorXf); - - float visorT = std::fmod(CGraphics::GetSecondsMod900(), 1.f) * (1.f - std::fabs(xc4_viewInterp)); - float alphaBlend = (visorT < 0.25f) ? 1.f - 2.f * visorT : (visorT < 0.5f) ? 2.f * (visorT - 0.25f) + 0.5f : 1.f; - float addBlend = (visorT > 0.75f) ? 1.f - 4.f * (visorT - 0.75f) : (visorT > 0.5f) ? 4.f * (visorT - 0.5f) : 0.f; - - x200_invVisor->GetInstance().ActivateLights(x23c_lights); - CModelFlags flags = {}; - flags.m_extendedShader = EExtendedShader::Lighting; - flags.x4_color = zeus::CColor::lerp(zeus::CColor(1.f, alpha), zeus::CColor(alphaBlend, alpha), x68_visorPulseFactor); - x200_invVisor->Draw(flags); - - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x4_color = zeus::CColor(1.f, alpha * addBlend * x68_visorPulseFactor); - x200_invVisor->Draw(flags); - } - - if (x270_25_hasGrappleBeam) - { - CGraphics::SetModelMatrix(grappleXf); - - x20c_invGrappleBeam->GetInstance().ActivateLights(x23c_lights); - CModelFlags flags = {}; - flags.m_extendedShader = EExtendedShader::ForcedAlpha; - flags.x4_color = zeus::CColor(1.f, alpha); - x20c_invGrappleBeam->Draw(flags); - - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x4_color = zeus::CColor(1.f, alpha * itemPulse * x60_grapplePulseFactor); - x20c_invGrappleBeam->Draw(flags); - } - else if (x44_suit >= CPlayerState::EPlayerSuit::FusionPower) - { - CGraphics::SetModelMatrix(grappleXf); - - x218_invFins->GetInstance().ActivateLights(x23c_lights); - CModelFlags flags = {}; - flags.m_extendedShader = EExtendedShader::ForcedAlpha; - flags.x4_color = zeus::CColor(1.f, alpha); - x218_invFins->Draw(flags); - - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x4_color = zeus::CColor(1.f, alpha * suitPulse); - x218_invFins->Draw(flags); - } - - if (x54_remTransitionTime > 0.f) - { - float ballT = 1.f - x54_remTransitionTime / x50_totalTransitionTime; - - float ballAlpha = 0.f; - if (x4d_selectedMorphball) - ballAlpha = 1.f - std::min(x54_remTransitionTime / 0.25f, 1.f); - else if (x4c_completedMorphball) - ballAlpha = std::max(0.f, (x54_remTransitionTime - (x50_totalTransitionTime - 0.25f)) / 0.25f); - - if (ballAlpha > 0.f) - { - CModelFlags flags = {}; - flags.x1_matSetIdx = x1e0_ballMatIdx; - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - flags.x4_color = zeus::CColor::skWhite; - x184_ballModelData->Render(mgr, x10_ballXf, x24c_actorLights.get(), flags); - - flags.m_extendedShader = EExtendedShader::ForcedAlpha; - flags.x4_color = zeus::CColor::skWhite; - flags.x4_color.a() = alpha * ballAlpha; - x184_ballModelData->Render(mgr, x10_ballXf, x24c_actorLights.get(), flags); - - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x4_color = zeus::CColor::skWhite; - flags.x4_color.a() = x6c_ballPulseFactor * alpha * ballAlpha * itemPulse; - x184_ballModelData->Render(mgr, x10_ballXf, x24c_actorLights.get(), flags); - } - - if (x4d_selectedMorphball && ballT > 0.5f) - { - float ballEndT = (ballT - 0.5f) / 0.5f; - float oneMinusBallEndT = 1.f - ballEndT; - - float spinScale = 0.75f * oneMinusBallEndT + 1.f; - float spinAlpha; - if (ballEndT < 0.1f) - spinAlpha = 0.f; - else if (ballEndT < 0.2f) - spinAlpha = (ballEndT - 0.1f) / 0.1f; - else if (ballEndT < 0.9f) - spinAlpha = 1.f; - else - spinAlpha = 1.f - (ballT - 0.9f) / 0.1f; - - zeus::CRelAngle spinAngle = zeus::degToRad(360.f * oneMinusBallEndT); - spinAlpha *= 0.5f; - if (spinAlpha > 0.f) - { - CModelFlags flags = {}; - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x1_matSetIdx = x1e0_ballMatIdx; - flags.x4_color = zeus::CColor(1.f, spinAlpha * alpha); - x184_ballModelData->Render(mgr, x10_ballXf * zeus::CTransform::RotateZ(spinAngle) * zeus::CTransform::Scale(spinScale), - x24c_actorLights.get(), flags); - } - } - - if (x270_24_hasSpiderBall) - { - CGraphics::SetModelMatrix(x10_ballXf); - CModelFlags flags = {}; - flags.x1_matSetIdx = x1e4_glassMatIdx; - x1d4_spiderBallGlass->GetInstance().ActivateLights(x23c_lights); - - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - flags.x4_color = zeus::CColor::skWhite; - x1d4_spiderBallGlass->Draw(flags); - - flags.m_extendedShader = EExtendedShader::ForcedAlpha; - flags.x4_color = zeus::CColor::skWhite; - flags.x4_color.a() = alpha; - x1d4_spiderBallGlass->Draw(flags); - - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x4_color = zeus::CColor::skWhite; - flags.x4_color.a() = x6c_ballPulseFactor * alpha * itemPulse; - x1d4_spiderBallGlass->Draw(flags); - } - } - - if (phazonSuit && alpha > 0.1f) - { - float radius = zeus::clamp(0.2f, (10.f - (xc0_userZoom >= 0.f ? xc0_userZoom : -xc0_userZoom)) / 20.f, 1.f); - float offset = std::sin(x260_phazonOffsetAngle); - zeus::CColor color = g_tweakGuiColors->GetPauseBlurFilterColor(); - color.a() = alpha; - g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.1f, alpha), x250_phazonIndirectTexture, - color, radius, 0.1f, offset, offset); - } + for (int i = 0; i <= x118_suitModel1and2.size(); ++i) { + TCachedToken backupModelData = xc8_suitModel0->GetAnimationData()->GetModelData(); + if (i < x118_suitModel1and2.size()) + xc8_suitModel0->AnimationData()->SubstituteModelData(x118_suitModel1and2[i]); + xc8_suitModel0->InvSuitDraw(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), x24c_actorLights.get(), + zeus::CColor(1.f, alpha), zeus::CColor(1.f, alpha * suitPulse)); + xc8_suitModel0->AnimationData()->SubstituteModelData(backupModelData); } - else + + x134_suitModelBoots->InvSuitDraw(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), + x24c_actorLights.get(), zeus::CColor(1.f, alpha), + zeus::CColor(1.f, alpha * bootsPulse)); + { + CGraphics::SetModelMatrix(gunXf); + x1f4_invBeam->GetInstance().ActivateLights(x23c_lights); + CModelFlags flags = {}; + + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x1f4_invBeam->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAlpha; + flags.x4_color = zeus::CColor(1.f, alpha); + x1f4_invBeam->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor(1.f, alpha * itemPulse * x5c_beamPulseFactor); + x1f4_invBeam->Draw(flags); + } + + { + CGraphics::SetModelMatrix(visorXf); + + float visorT = std::fmod(CGraphics::GetSecondsMod900(), 1.f) * (1.f - std::fabs(xc4_viewInterp)); + float alphaBlend = (visorT < 0.25f) ? 1.f - 2.f * visorT : (visorT < 0.5f) ? 2.f * (visorT - 0.25f) + 0.5f : 1.f; + float addBlend = (visorT > 0.75f) ? 1.f - 4.f * (visorT - 0.75f) : (visorT > 0.5f) ? 4.f * (visorT - 0.5f) : 0.f; + + x200_invVisor->GetInstance().ActivateLights(x23c_lights); + CModelFlags flags = {}; + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = + zeus::CColor::lerp(zeus::CColor(1.f, alpha), zeus::CColor(alphaBlend, alpha), x68_visorPulseFactor); + x200_invVisor->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor(1.f, alpha * addBlend * x68_visorPulseFactor); + x200_invVisor->Draw(flags); + } + + if (x270_25_hasGrappleBeam) { + CGraphics::SetModelMatrix(grappleXf); + + x20c_invGrappleBeam->GetInstance().ActivateLights(x23c_lights); + CModelFlags flags = {}; + flags.m_extendedShader = EExtendedShader::ForcedAlpha; + flags.x4_color = zeus::CColor(1.f, alpha); + x20c_invGrappleBeam->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor(1.f, alpha * itemPulse * x60_grapplePulseFactor); + x20c_invGrappleBeam->Draw(flags); + } else if (x44_suit >= CPlayerState::EPlayerSuit::FusionPower) { + CGraphics::SetModelMatrix(grappleXf); + + x218_invFins->GetInstance().ActivateLights(x23c_lights); + CModelFlags flags = {}; + flags.m_extendedShader = EExtendedShader::ForcedAlpha; + flags.x4_color = zeus::CColor(1.f, alpha); + x218_invFins->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor(1.f, alpha * suitPulse); + x218_invFins->Draw(flags); + } + + if (x54_remTransitionTime > 0.f) { + float ballT = 1.f - x54_remTransitionTime / x50_totalTransitionTime; + + float ballAlpha = 0.f; + if (x4d_selectedMorphball) + ballAlpha = 1.f - std::min(x54_remTransitionTime / 0.25f, 1.f); + else if (x4c_completedMorphball) + ballAlpha = std::max(0.f, (x54_remTransitionTime - (x50_totalTransitionTime - 0.25f)) / 0.25f); + + if (ballAlpha > 0.f) { CModelFlags flags = {}; flags.x1_matSetIdx = x1e0_ballMatIdx; flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; @@ -556,248 +382,290 @@ void CSamusDoll::Draw(const CStateManager& mgr, float alpha) flags.m_extendedShader = EExtendedShader::ForcedAlpha; flags.x4_color = zeus::CColor::skWhite; - flags.x4_color.a() = alpha; + flags.x4_color.a() = alpha * ballAlpha; x184_ballModelData->Render(mgr, x10_ballXf, x24c_actorLights.get(), flags); flags.m_extendedShader = EExtendedShader::ForcedAdditive; flags.x4_color = zeus::CColor::skWhite; - flags.x4_color.a() = x6c_ballPulseFactor * alpha * itemPulse; + flags.x4_color.a() = x6c_ballPulseFactor * alpha * ballAlpha * itemPulse; x184_ballModelData->Render(mgr, x10_ballXf, x24c_actorLights.get(), flags); + } - const u8* c = CMorphBall::BallGlowColors[x1e8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; - x22c_ballInnerGlowGen->SetModulationColor(color); + if (x4d_selectedMorphball && ballT > 0.5f) { + float ballEndT = (ballT - 0.5f) / 0.5f; + float oneMinusBallEndT = 1.f - ballEndT; - if (alpha > 0.f) - { - if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 0) - { - const u8* c = CMorphBall::BallTransFlashColors[x1e8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; - x22c_ballInnerGlowGen->GetActiveChildParticle(0).SetModulationColor(color); - - if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 1) - { - const u8* c = CMorphBall::BallAuxGlowColors[x1e8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; - x22c_ballInnerGlowGen->GetActiveChildParticle(1).SetModulationColor(color); - } - } - x22c_ballInnerGlowGen->Render(); - } - - if (x270_24_hasSpiderBall) - { - CGraphics::SetModelMatrix(x10_ballXf); - CModelFlags flags = {}; - flags.x1_matSetIdx = x1e4_glassMatIdx; - x1d4_spiderBallGlass->GetInstance().ActivateLights(x23c_lights); - - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - flags.x4_color = zeus::CColor::skWhite; - x1d4_spiderBallGlass->Draw(flags); - - flags.m_extendedShader = EExtendedShader::ForcedAlpha; - flags.x4_color = zeus::CColor::skWhite; - flags.x4_color.a() = alpha; - x1d4_spiderBallGlass->Draw(flags); - - flags.m_extendedShader = EExtendedShader::ForcedAdditive; - flags.x4_color = zeus::CColor::skWhite; - flags.x4_color.a() = x6c_ballPulseFactor * alpha * itemPulse; - x1d4_spiderBallGlass->Draw(flags); - } - } - - if (x238_ballTransitionFlashGen) - { - const u8* c = CMorphBall::BallTransFlashColors[x1e8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; - x238_ballTransitionFlashGen->SetModulationColor(color); - x238_ballTransitionFlashGen->Render(); - } - - CGraphics::DisableAllLights(); -} - -void CSamusDoll::Touch() -{ - if (!CheckLoadComplete()) - return; - xc8_suitModel0->AnimationData()->PreRender(); - x134_suitModelBoots->AnimationData()->PreRender(); - x184_ballModelData->AnimationData()->PreRender(); - xc8_suitModel0->Touch(CModelData::EWhichModel::Normal, 0); - x134_suitModelBoots->Touch(CModelData::EWhichModel::Normal, 0); - x184_ballModelData->Touch(CModelData::EWhichModel::Normal, 0); -} - -void CSamusDoll::SetupLights() -{ - x23c_lights[0] = CLight::BuildDirectional(xb0_userRot.toTransform().basis[1], zeus::CColor(0.75f, 1.f)); - x24c_actorLights->BuildFakeLightList(x23c_lights, zeus::CColor::skBlack); -} - -void CSamusDoll::SetInMorphball(bool morphball) -{ - if (x54_remTransitionTime > 0.f) - return; - if (x4d_selectedMorphball == morphball) - return; - x4d_selectedMorphball = morphball; - SetTransitionAnimation(); -} - -void CSamusDoll::SetTransitionAnimation() -{ - if (!x4c_completedMorphball) - { - /* Into morphball */ - xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); - x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); - x50_totalTransitionTime = x54_remTransitionTime = xc8_suitModel0->GetAnimationData()->GetAnimationDuration(0); - } - else if (!x4d_selectedMorphball) - { - /* Outta morphball */ - xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); - x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); - x50_totalTransitionTime = x54_remTransitionTime = xc8_suitModel0->GetAnimationData()->GetAnimationDuration(1); - } -} - -void CSamusDoll::SetRotationSfxPlaying(bool playing) -{ - if (playing) - { - if (x268_rotateSfx) - return; - x268_rotateSfx = CSfxManager::SfxStart(SFXui_map_rotate, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(x268_rotateSfx); - x268_rotateSfx.reset(); - } -} - -void CSamusDoll::SetOffsetSfxPlaying(bool playing) -{ - if (playing) - { - if (x264_offsetSfx) - return; - x264_offsetSfx = CSfxManager::SfxStart(SFXui_map_pan, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(x264_offsetSfx); - x264_offsetSfx.reset(); - } -} - -void CSamusDoll::SetZoomSfxPlaying(bool playing) -{ - if (playing) - { - if (x26c_zoomSfx) - return; - x26c_zoomSfx = CSfxManager::SfxStart(SFXui_map_zoom, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(x26c_zoomSfx); - x26c_zoomSfx.reset(); - } -} - -void CSamusDoll::SetRotation(float xDelta, float zDelta, float dt) -{ - if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) - return; - SetRotationSfxPlaying(xDelta != 0.f || zDelta != 0.f); - zeus::CEulerAngles angles(xb0_userRot); - - zeus::CRelAngle angX(angles.x()); - zeus::CRelAngle angZ(angles.z()); - - angX += xDelta; - angZ += zDelta; - - float angXCenter = angX; - if (angXCenter > M_PIF) - angXCenter -= 2.f * M_PIF; - angXCenter = zeus::clamp(-1.555f, angXCenter, 1.555f); - - float angZCenter = angZ; - if (angZCenter > M_PIF) - angZCenter -= 2.f * M_PIF; - - zeus::CQuaternion quat; - quat.rotateZ(angZCenter); - quat.rotateX(angXCenter); - xb0_userRot = quat; -} - -void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float dt) -{ - if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) - return; - zeus::CVector3f oldOffset = xa4_offset; - zeus::CMatrix3f rotMtx = xb0_userRot.toTransform().basis; - xa4_offset += rotMtx * zeus::CVector3f(offset.x(), 0.f, offset.z()); - SetOffsetSfxPlaying((oldOffset - xa4_offset).magnitude() > dt); - float oldZoom = xc0_userZoom; - xc0_userZoom = zeus::clamp(-4.f, xc0_userZoom + offset.y(), -2.2f); - bool zoomSfx = std::fabs(xc0_userZoom - oldZoom) > dt; - float zoomDelta = offset.y() - (xc0_userZoom - oldZoom); - zeus::CVector3f newOffset = rotMtx[1] * zoomDelta + xa4_offset; - zeus::CVector3f delta = newOffset - xa4_offset; - oldOffset = xa4_offset; - if (!delta.isZero()) - { - zeus::CSphere sphere(skInitialOffset, 1.f); - float T; - zeus::CVector3f point; - if (CollisionUtil::RaySphereIntersection(sphere, xa4_offset, delta.normalized(), 0.f, T, point)) - { - if ((point - xa4_offset).magnitude() < std::fabs(zoomDelta)) - xa4_offset = point; - else - xa4_offset = newOffset; - } + float spinScale = 0.75f * oneMinusBallEndT + 1.f; + float spinAlpha; + if (ballEndT < 0.1f) + spinAlpha = 0.f; + else if (ballEndT < 0.2f) + spinAlpha = (ballEndT - 0.1f) / 0.1f; + else if (ballEndT < 0.9f) + spinAlpha = 1.f; else - { - xa4_offset = newOffset; + spinAlpha = 1.f - (ballT - 0.9f) / 0.1f; + + zeus::CRelAngle spinAngle = zeus::degToRad(360.f * oneMinusBallEndT); + spinAlpha *= 0.5f; + if (spinAlpha > 0.f) { + CModelFlags flags = {}; + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x1_matSetIdx = x1e0_ballMatIdx; + flags.x4_color = zeus::CColor(1.f, spinAlpha * alpha); + x184_ballModelData->Render( + mgr, x10_ballXf * zeus::CTransform::RotateZ(spinAngle) * zeus::CTransform::Scale(spinScale), + x24c_actorLights.get(), flags); } - } - if ((oldOffset - xa4_offset).magnitude() > dt) - zoomSfx = true; - SetZoomSfxPlaying(zoomSfx); - delta = xa4_offset - skInitialOffset; - if (delta.magnitude() > 1.f) - xa4_offset = delta.normalized() + skInitialOffset; -} + } -void CSamusDoll::BeginViewInterpolate(bool zoomIn) -{ - if (xc4_viewInterp == 0.f) - { - CSfxManager::SfxStart(SFXui_samus_doll_enter, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - else - { - SetOffsetSfxPlaying(false); - SetZoomSfxPlaying(false); - SetRotationSfxPlaying(false); - CSfxManager::SfxStart(SFXui_samus_doll_exit, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + if (x270_24_hasSpiderBall) { + CGraphics::SetModelMatrix(x10_ballXf); + CModelFlags flags = {}; + flags.x1_matSetIdx = x1e4_glassMatIdx; + x1d4_spiderBallGlass->GetInstance().ActivateLights(x23c_lights); + + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x1d4_spiderBallGlass->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAlpha; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a() = alpha; + x1d4_spiderBallGlass->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a() = x6c_ballPulseFactor * alpha * itemPulse; + x1d4_spiderBallGlass->Draw(flags); + } } - xc4_viewInterp = zoomIn ? FLT_EPSILON : (-1.f + FLT_EPSILON); - x84_interpStartOffset = xa4_offset; - x90_userInterpRot = xb0_userRot; - xa0_userInterpZoom = xc0_userZoom; - x80_fixedZoom = zoomIn ? -2.2f : -3.6f; + if (phazonSuit && alpha > 0.1f) { + float radius = zeus::clamp(0.2f, (10.f - (xc0_userZoom >= 0.f ? xc0_userZoom : -xc0_userZoom)) / 20.f, 1.f); + float offset = std::sin(x260_phazonOffsetAngle); + zeus::CColor color = g_tweakGuiColors->GetPauseBlurFilterColor(); + color.a() = alpha; + g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.1f, alpha), x250_phazonIndirectTexture, color, radius, + 0.1f, offset, offset); + } + } else { + CModelFlags flags = {}; + flags.x1_matSetIdx = x1e0_ballMatIdx; + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x184_ballModelData->Render(mgr, x10_ballXf, x24c_actorLights.get(), flags); + + flags.m_extendedShader = EExtendedShader::ForcedAlpha; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a() = alpha; + x184_ballModelData->Render(mgr, x10_ballXf, x24c_actorLights.get(), flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a() = x6c_ballPulseFactor * alpha * itemPulse; + x184_ballModelData->Render(mgr, x10_ballXf, x24c_actorLights.get(), flags); + + const u8* c = CMorphBall::BallGlowColors[x1e8_ballGlowColorIdx]; + zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; + x22c_ballInnerGlowGen->SetModulationColor(color); + + if (alpha > 0.f) { + if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 0) { + const u8* c = CMorphBall::BallTransFlashColors[x1e8_ballGlowColorIdx]; + zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; + x22c_ballInnerGlowGen->GetActiveChildParticle(0).SetModulationColor(color); + + if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 1) { + const u8* c = CMorphBall::BallAuxGlowColors[x1e8_ballGlowColorIdx]; + zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; + x22c_ballInnerGlowGen->GetActiveChildParticle(1).SetModulationColor(color); + } + } + x22c_ballInnerGlowGen->Render(); + } + + if (x270_24_hasSpiderBall) { + CGraphics::SetModelMatrix(x10_ballXf); + CModelFlags flags = {}; + flags.x1_matSetIdx = x1e4_glassMatIdx; + x1d4_spiderBallGlass->GetInstance().ActivateLights(x23c_lights); + + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x1d4_spiderBallGlass->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAlpha; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a() = alpha; + x1d4_spiderBallGlass->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a() = x6c_ballPulseFactor * alpha * itemPulse; + x1d4_spiderBallGlass->Draw(flags); + } + } + + if (x238_ballTransitionFlashGen) { + const u8* c = CMorphBall::BallTransFlashColors[x1e8_ballGlowColorIdx]; + zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; + x238_ballTransitionFlashGen->SetModulationColor(color); + x238_ballTransitionFlashGen->Render(); + } + + CGraphics::DisableAllLights(); } +void CSamusDoll::Touch() { + if (!CheckLoadComplete()) + return; + xc8_suitModel0->AnimationData()->PreRender(); + x134_suitModelBoots->AnimationData()->PreRender(); + x184_ballModelData->AnimationData()->PreRender(); + xc8_suitModel0->Touch(CModelData::EWhichModel::Normal, 0); + x134_suitModelBoots->Touch(CModelData::EWhichModel::Normal, 0); + x184_ballModelData->Touch(CModelData::EWhichModel::Normal, 0); } + +void CSamusDoll::SetupLights() { + x23c_lights[0] = CLight::BuildDirectional(xb0_userRot.toTransform().basis[1], zeus::CColor(0.75f, 1.f)); + x24c_actorLights->BuildFakeLightList(x23c_lights, zeus::CColor::skBlack); +} + +void CSamusDoll::SetInMorphball(bool morphball) { + if (x54_remTransitionTime > 0.f) + return; + if (x4d_selectedMorphball == morphball) + return; + x4d_selectedMorphball = morphball; + SetTransitionAnimation(); +} + +void CSamusDoll::SetTransitionAnimation() { + if (!x4c_completedMorphball) { + /* Into morphball */ + xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); + x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); + x50_totalTransitionTime = x54_remTransitionTime = xc8_suitModel0->GetAnimationData()->GetAnimationDuration(0); + } else if (!x4d_selectedMorphball) { + /* Outta morphball */ + xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); + x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); + x50_totalTransitionTime = x54_remTransitionTime = xc8_suitModel0->GetAnimationData()->GetAnimationDuration(1); + } +} + +void CSamusDoll::SetRotationSfxPlaying(bool playing) { + if (playing) { + if (x268_rotateSfx) + return; + x268_rotateSfx = CSfxManager::SfxStart(SFXui_map_rotate, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } else { + CSfxManager::SfxStop(x268_rotateSfx); + x268_rotateSfx.reset(); + } +} + +void CSamusDoll::SetOffsetSfxPlaying(bool playing) { + if (playing) { + if (x264_offsetSfx) + return; + x264_offsetSfx = CSfxManager::SfxStart(SFXui_map_pan, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } else { + CSfxManager::SfxStop(x264_offsetSfx); + x264_offsetSfx.reset(); + } +} + +void CSamusDoll::SetZoomSfxPlaying(bool playing) { + if (playing) { + if (x26c_zoomSfx) + return; + x26c_zoomSfx = CSfxManager::SfxStart(SFXui_map_zoom, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } else { + CSfxManager::SfxStop(x26c_zoomSfx); + x26c_zoomSfx.reset(); + } +} + +void CSamusDoll::SetRotation(float xDelta, float zDelta, float dt) { + if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) + return; + SetRotationSfxPlaying(xDelta != 0.f || zDelta != 0.f); + zeus::CEulerAngles angles(xb0_userRot); + + zeus::CRelAngle angX(angles.x()); + zeus::CRelAngle angZ(angles.z()); + + angX += xDelta; + angZ += zDelta; + + float angXCenter = angX; + if (angXCenter > M_PIF) + angXCenter -= 2.f * M_PIF; + angXCenter = zeus::clamp(-1.555f, angXCenter, 1.555f); + + float angZCenter = angZ; + if (angZCenter > M_PIF) + angZCenter -= 2.f * M_PIF; + + zeus::CQuaternion quat; + quat.rotateZ(angZCenter); + quat.rotateX(angXCenter); + xb0_userRot = quat; +} + +void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float dt) { + if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) + return; + zeus::CVector3f oldOffset = xa4_offset; + zeus::CMatrix3f rotMtx = xb0_userRot.toTransform().basis; + xa4_offset += rotMtx * zeus::CVector3f(offset.x(), 0.f, offset.z()); + SetOffsetSfxPlaying((oldOffset - xa4_offset).magnitude() > dt); + float oldZoom = xc0_userZoom; + xc0_userZoom = zeus::clamp(-4.f, xc0_userZoom + offset.y(), -2.2f); + bool zoomSfx = std::fabs(xc0_userZoom - oldZoom) > dt; + float zoomDelta = offset.y() - (xc0_userZoom - oldZoom); + zeus::CVector3f newOffset = rotMtx[1] * zoomDelta + xa4_offset; + zeus::CVector3f delta = newOffset - xa4_offset; + oldOffset = xa4_offset; + if (!delta.isZero()) { + zeus::CSphere sphere(skInitialOffset, 1.f); + float T; + zeus::CVector3f point; + if (CollisionUtil::RaySphereIntersection(sphere, xa4_offset, delta.normalized(), 0.f, T, point)) { + if ((point - xa4_offset).magnitude() < std::fabs(zoomDelta)) + xa4_offset = point; + else + xa4_offset = newOffset; + } else { + xa4_offset = newOffset; + } + } + if ((oldOffset - xa4_offset).magnitude() > dt) + zoomSfx = true; + SetZoomSfxPlaying(zoomSfx); + delta = xa4_offset - skInitialOffset; + if (delta.magnitude() > 1.f) + xa4_offset = delta.normalized() + skInitialOffset; +} + +void CSamusDoll::BeginViewInterpolate(bool zoomIn) { + if (xc4_viewInterp == 0.f) { + CSfxManager::SfxStart(SFXui_samus_doll_enter, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } else { + SetOffsetSfxPlaying(false); + SetZoomSfxPlaying(false); + SetRotationSfxPlaying(false); + CSfxManager::SfxStart(SFXui_samus_doll_exit, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + + xc4_viewInterp = zoomIn ? FLT_EPSILON : (-1.f + FLT_EPSILON); + x84_interpStartOffset = xa4_offset; + x90_userInterpRot = xb0_userRot; + xa0_userInterpZoom = xc0_userZoom; + x80_fixedZoom = zoomIn ? -2.2f : -3.6f; +} + +} // namespace urde::MP1 diff --git a/Runtime/MP1/CSamusDoll.hpp b/Runtime/MP1/CSamusDoll.hpp index 1c113814d..bcff170ee 100644 --- a/Runtime/MP1/CSamusDoll.hpp +++ b/Runtime/MP1/CSamusDoll.hpp @@ -8,107 +8,101 @@ #include "Character/CActorLights.hpp" #include "Audio/CSfxManager.hpp" -namespace urde -{ +namespace urde { class CDependencyGroup; -namespace MP1 -{ +namespace MP1 { -class CSamusDoll -{ - std::vector x0_depToks; - zeus::CTransform x10_ballXf; - float x40_alphaIn = 0.f; - CPlayerState::EPlayerSuit x44_suit; - CPlayerState::EBeamId x48_beam; - bool x4c_completedMorphball = false; - bool x4d_selectedMorphball = false; - float x50_totalTransitionTime = 1.f; - float x54_remTransitionTime = 0.f; - float x58_suitPulseFactor = 0.f; - float x5c_beamPulseFactor = 0.f; - float x60_grapplePulseFactor = 0.f; - float x64_bootsPulseFactor = 0.f; - float x68_visorPulseFactor = 0.f; - float x6c_ballPulseFactor = 0.f; - zeus::CQuaternion x70_fixedRot; - float x80_fixedZoom = -3.6f; - zeus::CVector3f x84_interpStartOffset = skInitialOffset; - zeus::CQuaternion x90_userInterpRot; - float xa0_userInterpZoom = -3.6f; - zeus::CVector3f xa4_offset = skInitialOffset; - zeus::CQuaternion xb0_userRot; - float xc0_userZoom = -3.6f; - float xc4_viewInterp = 0.f; - std::experimental::optional xc8_suitModel0; - rstl::reserved_vector, 2> x118_suitModel1and2; - std::experimental::optional x134_suitModelBoots; - std::experimental::optional x184_ballModelData; - TLockedToken x1d4_spiderBallGlass; - u32 x1e0_ballMatIdx; - u32 x1e4_glassMatIdx; - u32 x1e8_ballGlowColorIdx; - TLockedToken x1ec_itemScreenSamus; - TLockedToken x1f4_invBeam; - TLockedToken x200_invVisor; - TLockedToken x20c_invGrappleBeam; - TLockedToken x218_invFins; - TLockedToken x224_ballInnerGlow; - std::unique_ptr x22c_ballInnerGlowGen; - TLockedToken x230_ballTransitionFlash; - std::unique_ptr x238_ballTransitionFlashGen; - std::vector x23c_lights; - std::unique_ptr x24c_actorLights; - TLockedToken x250_phazonIndirectTexture; // Used to be optional - zeus::CRelAngle x260_phazonOffsetAngle; - CSfxHandle x264_offsetSfx; - CSfxHandle x268_rotateSfx; - CSfxHandle x26c_zoomSfx; - union - { - struct - { - bool x270_24_hasSpiderBall : 1; - bool x270_25_hasGrappleBeam : 1; - bool x270_26_pulseSuit : 1; - bool x270_27_pulseBeam : 1; - bool x270_28_pulseGrapple : 1; - bool x270_29_pulseBoots : 1; - bool x270_30_pulseVisor : 1; - bool x270_31_loaded : 1; - }; - u32 _dummy = 0; +class CSamusDoll { + std::vector x0_depToks; + zeus::CTransform x10_ballXf; + float x40_alphaIn = 0.f; + CPlayerState::EPlayerSuit x44_suit; + CPlayerState::EBeamId x48_beam; + bool x4c_completedMorphball = false; + bool x4d_selectedMorphball = false; + float x50_totalTransitionTime = 1.f; + float x54_remTransitionTime = 0.f; + float x58_suitPulseFactor = 0.f; + float x5c_beamPulseFactor = 0.f; + float x60_grapplePulseFactor = 0.f; + float x64_bootsPulseFactor = 0.f; + float x68_visorPulseFactor = 0.f; + float x6c_ballPulseFactor = 0.f; + zeus::CQuaternion x70_fixedRot; + float x80_fixedZoom = -3.6f; + zeus::CVector3f x84_interpStartOffset = skInitialOffset; + zeus::CQuaternion x90_userInterpRot; + float xa0_userInterpZoom = -3.6f; + zeus::CVector3f xa4_offset = skInitialOffset; + zeus::CQuaternion xb0_userRot; + float xc0_userZoom = -3.6f; + float xc4_viewInterp = 0.f; + std::experimental::optional xc8_suitModel0; + rstl::reserved_vector, 2> x118_suitModel1and2; + std::experimental::optional x134_suitModelBoots; + std::experimental::optional x184_ballModelData; + TLockedToken x1d4_spiderBallGlass; + u32 x1e0_ballMatIdx; + u32 x1e4_glassMatIdx; + u32 x1e8_ballGlowColorIdx; + TLockedToken x1ec_itemScreenSamus; + TLockedToken x1f4_invBeam; + TLockedToken x200_invVisor; + TLockedToken x20c_invGrappleBeam; + TLockedToken x218_invFins; + TLockedToken x224_ballInnerGlow; + std::unique_ptr x22c_ballInnerGlowGen; + TLockedToken x230_ballTransitionFlash; + std::unique_ptr x238_ballTransitionFlashGen; + std::vector x23c_lights; + std::unique_ptr x24c_actorLights; + TLockedToken x250_phazonIndirectTexture; // Used to be optional + zeus::CRelAngle x260_phazonOffsetAngle; + CSfxHandle x264_offsetSfx; + CSfxHandle x268_rotateSfx; + CSfxHandle x26c_zoomSfx; + union { + struct { + bool x270_24_hasSpiderBall : 1; + bool x270_25_hasGrappleBeam : 1; + bool x270_26_pulseSuit : 1; + bool x270_27_pulseBeam : 1; + bool x270_28_pulseGrapple : 1; + bool x270_29_pulseBoots : 1; + bool x270_30_pulseVisor : 1; + bool x270_31_loaded : 1; }; + u32 _dummy = 0; + }; + + static const zeus::CVector3f skInitialOffset; + static CModelData BuildSuitModelData1(CPlayerState::EPlayerSuit suit); + static CModelData BuildSuitModelDataBoots(CPlayerState::EPlayerSuit suit); + void SetupLights(); + void SetTransitionAnimation(); + void SetRotationSfxPlaying(bool playing); + void SetOffsetSfxPlaying(bool playing); + void SetZoomSfxPlaying(bool playing); - static const zeus::CVector3f skInitialOffset; - static CModelData BuildSuitModelData1(CPlayerState::EPlayerSuit suit); - static CModelData BuildSuitModelDataBoots(CPlayerState::EPlayerSuit suit); - void SetupLights(); - void SetTransitionAnimation(); - void SetRotationSfxPlaying(bool playing); - void SetOffsetSfxPlaying(bool playing); - void SetZoomSfxPlaying(bool playing); public: - CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp, - CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam, - bool hasSpiderBall, bool hasGrappleBeam); - bool IsLoaded() const; - bool CheckLoadComplete(); - void Update(float dt, CRandom16& rand); - void Draw(const CStateManager& mgr, float alpha); - void Touch(); - void SetInMorphball(bool morphballComplete); - void SetRotation(float xDelta, float zDelta, float dt); - void SetOffset(const zeus::CVector3f& offset, float dt); - void BeginViewInterpolate(bool zoomOut); - void SetPulseSuit(bool b) { x270_26_pulseSuit = b; } - void SetPulseVisor(bool b) { x270_30_pulseVisor = b; } - void SetPulseBoots(bool b) { x270_29_pulseBoots = b; } - void SetPulseGrapple(bool b) { x270_28_pulseGrapple = b; } - void SetPulseBeam(bool b) { x270_27_pulseBeam = b; } - float GetViewInterpolation() const { return xc4_viewInterp; } + CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp, CPlayerState::EPlayerSuit suit, + CPlayerState::EBeamId beam, bool hasSpiderBall, bool hasGrappleBeam); + bool IsLoaded() const; + bool CheckLoadComplete(); + void Update(float dt, CRandom16& rand); + void Draw(const CStateManager& mgr, float alpha); + void Touch(); + void SetInMorphball(bool morphballComplete); + void SetRotation(float xDelta, float zDelta, float dt); + void SetOffset(const zeus::CVector3f& offset, float dt); + void BeginViewInterpolate(bool zoomOut); + void SetPulseSuit(bool b) { x270_26_pulseSuit = b; } + void SetPulseVisor(bool b) { x270_30_pulseVisor = b; } + void SetPulseBoots(bool b) { x270_29_pulseBoots = b; } + void SetPulseGrapple(bool b) { x270_28_pulseGrapple = b; } + void SetPulseBeam(bool b) { x270_27_pulseBeam = b; } + float GetViewInterpolation() const { return xc4_viewInterp; } }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CSamusFaceReflection.cpp b/Runtime/MP1/CSamusFaceReflection.cpp index 1093a1c86..cde18b6ec 100644 --- a/Runtime/MP1/CSamusFaceReflection.cpp +++ b/Runtime/MP1/CSamusFaceReflection.cpp @@ -6,111 +6,97 @@ #include "World/CPlayer.hpp" #include "World/CWorld.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { static const zeus::CTransform PreXf = zeus::CTransform::Scale(0.3f) * zeus::CTransform::Translate(0.f, 0.5f, 0.f); CSamusFaceReflection::CSamusFaceReflection(CStateManager& stateMgr) -: x0_modelData(CAnimRes(g_ResFactory->GetResourceIdByName("ACS_SamusFace")->id, - 0, zeus::CVector3f::skOne, 0, true)), - x4c_lights(std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, 0, 0, 0.1f)) -{ - x60_lookDir = zeus::CVector3f::skForward; - CAnimPlaybackParms parms(0, -1, 1.f, true); - x0_modelData.AnimationData()->SetAnimation(parms, false); +: x0_modelData(CAnimRes(g_ResFactory->GetResourceIdByName("ACS_SamusFace")->id, 0, zeus::CVector3f::skOne, 0, true)) +, x4c_lights(std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, 0, 0, 0.1f)) { + x60_lookDir = zeus::CVector3f::skForward; + CAnimPlaybackParms parms(0, -1, 1.f, true); + x0_modelData.AnimationData()->SetAnimation(parms, false); } -void CSamusFaceReflection::PreDraw(const CStateManager& mgr) -{ - if (x6c_ != 2 && (x4c_lights->GetActiveLightCount() >= 1 || (x6c_ != 0 && x6c_ != 3))) - { - if (!TCastToConstPtr(mgr.GetCameraManager()->GetCurrentCamera(mgr))) - { - x70_hidden = true; - } - else - { - x70_hidden = false; - x0_modelData.AnimationData()->PreRender(); - } +void CSamusFaceReflection::PreDraw(const CStateManager& mgr) { + if (x6c_ != 2 && (x4c_lights->GetActiveLightCount() >= 1 || (x6c_ != 0 && x6c_ != 3))) { + if (!TCastToConstPtr(mgr.GetCameraManager()->GetCurrentCamera(mgr))) { + x70_hidden = true; + } else { + x70_hidden = false; + x0_modelData.AnimationData()->PreRender(); } + } } -void CSamusFaceReflection::Draw(const CStateManager& mgr) const -{ - if (x70_hidden) - return; +void CSamusFaceReflection::Draw(const CStateManager& mgr) const { + if (x70_hidden) + return; - if (TCastToConstPtr fpCam = (mgr.GetCameraManager()->GetCurrentCamera(mgr))) - { - zeus::CQuaternion camRot(fpCam->GetTransform().basis); - float dist = ITweakGui::FaceReflectionDistanceDebugValueToActualValue(g_tweakGui->GetFaceReflectionDistance()); - float height = ITweakGui::FaceReflectionHeightDebugValueToActualValue(g_tweakGui->GetFaceReflectionHeight()); - float aspect = ITweakGui::FaceReflectionAspectDebugValueToActualValue(g_tweakGui->GetFaceReflectionAspect()); - float orthoWidth = ITweakGui::FaceReflectionOrthoWidthDebugValueToActualValue(g_tweakGui->GetFaceReflectionOrthoWidth()); - float orthoHeight = ITweakGui::FaceReflectionOrthoHeightDebugValueToActualValue(g_tweakGui->GetFaceReflectionOrthoHeight()); + if (TCastToConstPtr fpCam = (mgr.GetCameraManager()->GetCurrentCamera(mgr))) { + zeus::CQuaternion camRot(fpCam->GetTransform().basis); + float dist = ITweakGui::FaceReflectionDistanceDebugValueToActualValue(g_tweakGui->GetFaceReflectionDistance()); + float height = ITweakGui::FaceReflectionHeightDebugValueToActualValue(g_tweakGui->GetFaceReflectionHeight()); + float aspect = ITweakGui::FaceReflectionAspectDebugValueToActualValue(g_tweakGui->GetFaceReflectionAspect()); + float orthoWidth = + ITweakGui::FaceReflectionOrthoWidthDebugValueToActualValue(g_tweakGui->GetFaceReflectionOrthoWidth()); + float orthoHeight = + ITweakGui::FaceReflectionOrthoHeightDebugValueToActualValue(g_tweakGui->GetFaceReflectionOrthoHeight()); - zeus::CTransform modelXf = - zeus::CTransform(camRot * x50_lookRot, - fpCam->GetTransform().basis[1] * dist + - fpCam->GetTransform().origin + - fpCam->GetTransform().basis[2] * height) * PreXf; + zeus::CTransform modelXf = + zeus::CTransform(camRot * x50_lookRot, fpCam->GetTransform().basis[1] * dist + fpCam->GetTransform().origin + + fpCam->GetTransform().basis[2] * height) * + PreXf; - CGraphics::SetViewPointMatrix(fpCam->GetTransform()); - CGraphics::SetOrtho(aspect * -orthoWidth, aspect * orthoWidth, - orthoHeight, -orthoHeight, -10.f, 10.f); + CGraphics::SetViewPointMatrix(fpCam->GetTransform()); + CGraphics::SetOrtho(aspect * -orthoWidth, aspect * orthoWidth, orthoHeight, -orthoHeight, -10.f, 10.f); - CActorLights* lights = x6c_ == 1 ? nullptr : x4c_lights.get(); - if (x6c_ == 3) - { - x0_modelData.Render(mgr, modelXf, lights, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); - } - else - { - float transFactor; - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Combat) - transFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); - else - transFactor = 0.f; - if (transFactor > 0.f) - { - x0_modelData.Render(mgr, modelXf, nullptr, CModelFlags(7, 0, 3, zeus::CColor::skBlack)); - x0_modelData.Render(mgr, modelXf, lights, CModelFlags(7, 0, 1, zeus::CColor(1.f, transFactor))); - } - } + CActorLights* lights = x6c_ == 1 ? nullptr : x4c_lights.get(); + if (x6c_ == 3) { + x0_modelData.Render(mgr, modelXf, lights, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); + } else { + float transFactor; + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Combat) + transFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); + else + transFactor = 0.f; + if (transFactor > 0.f) { + x0_modelData.Render(mgr, modelXf, nullptr, CModelFlags(7, 0, 3, zeus::CColor::skBlack)); + x0_modelData.Render(mgr, modelXf, lights, CModelFlags(7, 0, 1, zeus::CColor(1.f, transFactor))); + } } + } } -void CSamusFaceReflection::Update(float dt, const CStateManager& mgr, CRandom16& rand) -{ - if (TCastToConstPtr fpCam = (mgr.GetCameraManager()->GetCurrentCamera(mgr))) - { - x0_modelData.AdvanceAnimationIgnoreParticles(dt, rand, true); - x4c_lights->SetFindShadowLight(false); - TAreaId areaId = mgr.GetPlayer().GetAreaIdAlways(); - if (areaId == kInvalidAreaId) - return; +void CSamusFaceReflection::Update(float dt, const CStateManager& mgr, CRandom16& rand) { + if (TCastToConstPtr fpCam = (mgr.GetCameraManager()->GetCurrentCamera(mgr))) { + x0_modelData.AdvanceAnimationIgnoreParticles(dt, rand, true); + x4c_lights->SetFindShadowLight(false); + TAreaId areaId = mgr.GetPlayer().GetAreaIdAlways(); + if (areaId == kInvalidAreaId) + return; - zeus::CAABox aabb(fpCam->GetTranslation() - 0.125f, fpCam->GetTranslation() + 0.125f); - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(areaId); - x4c_lights->BuildFaceLightList(mgr, *area, aabb); + zeus::CAABox aabb(fpCam->GetTranslation() - 0.125f, fpCam->GetTranslation() + 0.125f); + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(areaId); + x4c_lights->BuildFaceLightList(mgr, *area, aabb); - zeus::CUnitVector3f lookDir(fpCam->GetTransform().basis[1]); - zeus::CUnitVector3f xfLook = - zeus::CQuaternion::lookAt(lookDir, zeus::CVector3f::skForward, 2.f * M_PIF).transform(x60_lookDir); - zeus::CQuaternion xfLook2 = zeus::CQuaternion::lookAt(zeus::CVector3f::skForward, xfLook, 2.f * M_PIF); - xfLook2 *= xfLook2; - zeus::CMatrix3f newXf(xfLook2); - zeus::CMatrix3f prevXf(x50_lookRot); - float lookDot = prevXf[1].dot(newXf[1]); - if (std::fabs(lookDot) > 1.f) - lookDot = lookDot > 0.f ? 1.f : -1.f; - float lookAng = std::acos(lookDot); - x50_lookRot = zeus::CQuaternion::slerp(x50_lookRot, xfLook2, - zeus::clamp(0.f, 18.f * dt * ((lookAng > 0.f) ? 0.5f * dt * g_tweakPlayer->GetFreeLookSpeed() / lookAng : 0.f), 1.f)); - x60_lookDir = lookDir; - } + zeus::CUnitVector3f lookDir(fpCam->GetTransform().basis[1]); + zeus::CUnitVector3f xfLook = + zeus::CQuaternion::lookAt(lookDir, zeus::CVector3f::skForward, 2.f * M_PIF).transform(x60_lookDir); + zeus::CQuaternion xfLook2 = zeus::CQuaternion::lookAt(zeus::CVector3f::skForward, xfLook, 2.f * M_PIF); + xfLook2 *= xfLook2; + zeus::CMatrix3f newXf(xfLook2); + zeus::CMatrix3f prevXf(x50_lookRot); + float lookDot = prevXf[1].dot(newXf[1]); + if (std::fabs(lookDot) > 1.f) + lookDot = lookDot > 0.f ? 1.f : -1.f; + float lookAng = std::acos(lookDot); + x50_lookRot = zeus::CQuaternion::slerp( + x50_lookRot, xfLook2, + zeus::clamp(0.f, 18.f * dt * ((lookAng > 0.f) ? 0.5f * dt * g_tweakPlayer->GetFreeLookSpeed() / lookAng : 0.f), + 1.f)); + x60_lookDir = lookDir; + } } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CSamusFaceReflection.hpp b/Runtime/MP1/CSamusFaceReflection.hpp index b7d0d993e..ec0b2a3ec 100644 --- a/Runtime/MP1/CSamusFaceReflection.hpp +++ b/Runtime/MP1/CSamusFaceReflection.hpp @@ -3,23 +3,21 @@ #include "Character/CModelData.hpp" #include "Character/CActorLights.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { + +class CSamusFaceReflection { + CModelData x0_modelData; + std::unique_ptr x4c_lights; + zeus::CQuaternion x50_lookRot; + zeus::CVector3f x60_lookDir; + u32 x6c_ = 0; + bool x70_hidden = true; -class CSamusFaceReflection -{ - CModelData x0_modelData; - std::unique_ptr x4c_lights; - zeus::CQuaternion x50_lookRot; - zeus::CVector3f x60_lookDir; - u32 x6c_ = 0; - bool x70_hidden = true; public: - CSamusFaceReflection(CStateManager& stateMgr); - void PreDraw(const CStateManager& stateMgr); - void Draw(const CStateManager& stateMgr) const; - void Update(float dt, const CStateManager& stateMgr, CRandom16& rand); + CSamusFaceReflection(CStateManager& stateMgr); + void PreDraw(const CStateManager& stateMgr); + void Draw(const CStateManager& stateMgr) const; + void Update(float dt, const CStateManager& stateMgr, CRandom16& rand); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CSamusHud.cpp b/Runtime/MP1/CSamusHud.cpp index ed5eacac2..507ff617c 100644 --- a/Runtime/MP1/CSamusHud.cpp +++ b/Runtime/MP1/CSamusHud.cpp @@ -13,1826 +13,1606 @@ #include "TCastTo.hpp" #include "World/CGameLight.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CSamusHud* CSamusHud::g_SamusHud = nullptr; CSamusHud::CSamusHud(CStateManager& stateMgr) -: x8_targetingMgr(stateMgr), - x258_frmeHelmet(g_SimplePool->GetObj("FRME_Helmet")), - x268_frmeBaseHud(g_SimplePool->GetObj("FRME_BaseHud")), - m_energyDrainFilter(g_tweakGui->GetEnergyDrainFilterAdditive() ? - EFilterType::Add : EFilterType::Blend) -{ - x2e0_26_latestFirstPerson = true; - x2e0_27_energyLow = stateMgr.GetPlayer().IsEnergyLow(stateMgr); - x33c_lights = std::make_unique(8, zeus::CVector3f::skZero, 4, 1, true, 0, 0, 0.1f); - x340_hudLights.resize(3, SCachedHudLight(zeus::CVector3f::skZero, zeus::CColor::skWhite, - 0.f, 0.f, 0.f, 0.f)); - x46c_.resize(3); - x568_fpCamDir = stateMgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform().basis[1]; - x5a4_videoBands.resize(4); - x5d8_guiLights.resize(4); - x7ac_.resize(15); - UpdateStateTransition(1.f, stateMgr); - g_SamusHud = this; +: x8_targetingMgr(stateMgr) +, x258_frmeHelmet(g_SimplePool->GetObj("FRME_Helmet")) +, x268_frmeBaseHud(g_SimplePool->GetObj("FRME_BaseHud")) +, m_energyDrainFilter(g_tweakGui->GetEnergyDrainFilterAdditive() ? EFilterType::Add : EFilterType::Blend) { + x2e0_26_latestFirstPerson = true; + x2e0_27_energyLow = stateMgr.GetPlayer().IsEnergyLow(stateMgr); + x33c_lights = std::make_unique(8, zeus::CVector3f::skZero, 4, 1, true, 0, 0, 0.1f); + x340_hudLights.resize(3, SCachedHudLight(zeus::CVector3f::skZero, zeus::CColor::skWhite, 0.f, 0.f, 0.f, 0.f)); + x46c_.resize(3); + x568_fpCamDir = stateMgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform().basis[1]; + x5a4_videoBands.resize(4); + x5d8_guiLights.resize(4); + x7ac_.resize(15); + UpdateStateTransition(1.f, stateMgr); + g_SamusHud = this; - for (int i=0 ; i<16 ; ++i) - x5ec_camFovTweaks[i] = 5.f * i + 40.f; - for (int i=0 ; i<64 ; ++i) - x62c_camYTweaks[i] = -0.5f * i; - for (int i=0 ; i<32 ; ++i) - x72c_camZTweaks[i] = 0.5f * i - 8.f; + for (int i = 0; i < 16; ++i) + x5ec_camFovTweaks[i] = 5.f * i + 40.f; + for (int i = 0; i < 64; ++i) + x62c_camYTweaks[i] = -0.5f * i; + for (int i = 0; i < 32; ++i) + x72c_camZTweaks[i] = 0.5f * i - 8.f; - x264_loadedFrmeHelmet = x258_frmeHelmet.GetObj(); - x264_loadedFrmeHelmet->SetMaxAspect(1.78f); - x274_loadedFrmeBaseHud = x268_frmeBaseHud.GetObj(); - x274_loadedFrmeBaseHud->SetMaxAspect(1.78f); - x2a0_helmetIntf = std::make_unique(*x264_loadedFrmeHelmet); + x264_loadedFrmeHelmet = x258_frmeHelmet.GetObj(); + x264_loadedFrmeHelmet->SetMaxAspect(1.78f); + x274_loadedFrmeBaseHud = x268_frmeBaseHud.GetObj(); + x274_loadedFrmeBaseHud->SetMaxAspect(1.78f); + x2a0_helmetIntf = std::make_unique(*x264_loadedFrmeHelmet); - rstl::reserved_vector hasVisors = BuildPlayerHasVisors(stateMgr); - x2a4_visorMenu = std::make_unique(*x274_loadedFrmeBaseHud, - CHudVisorBeamMenu::EHudVisorBeamMenu::Visor, - hasVisors); + rstl::reserved_vector hasVisors = BuildPlayerHasVisors(stateMgr); + x2a4_visorMenu = std::make_unique(*x274_loadedFrmeBaseHud, + CHudVisorBeamMenu::EHudVisorBeamMenu::Visor, hasVisors); - rstl::reserved_vector hasBeams = BuildPlayerHasBeams(stateMgr); - x2a8_beamMenu = std::make_unique(*x274_loadedFrmeBaseHud, - CHudVisorBeamMenu::EHudVisorBeamMenu::Beam, - hasBeams); + rstl::reserved_vector hasBeams = BuildPlayerHasBeams(stateMgr); + x2a8_beamMenu = std::make_unique(*x274_loadedFrmeBaseHud, + CHudVisorBeamMenu::EHudVisorBeamMenu::Beam, hasBeams); - x2ac_radarIntf = std::make_unique(*x274_loadedFrmeBaseHud, stateMgr); + x2ac_radarIntf = std::make_unique(*x274_loadedFrmeBaseHud, stateMgr); - InitializeFrameGluePermanent(stateMgr); - UpdateEnergy(0.f, stateMgr, true); - UpdateMissile(0.f, stateMgr, true); - UpdateBallMode(stateMgr, true); + InitializeFrameGluePermanent(stateMgr); + UpdateEnergy(0.f, stateMgr, true); + UpdateMissile(0.f, stateMgr, true); + UpdateBallMode(stateMgr, true); } -CSamusHud::~CSamusHud() -{ - if (x3a4_damageSfx) - CSfxManager::RemoveEmitter(x3a4_damageSfx); - g_SamusHud = nullptr; +CSamusHud::~CSamusHud() { + if (x3a4_damageSfx) + CSfxManager::RemoveEmitter(x3a4_damageSfx); + g_SamusHud = nullptr; } -rstl::reserved_vector CSamusHud::BuildPlayerHasVisors(const CStateManager& mgr) -{ - rstl::reserved_vector ret; - ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::CombatVisor)); - ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::XRayVisor)); - ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ScanVisor)); - ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ThermalVisor)); - return ret; +rstl::reserved_vector CSamusHud::BuildPlayerHasVisors(const CStateManager& mgr) { + rstl::reserved_vector ret; + ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::CombatVisor)); + ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::XRayVisor)); + ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ScanVisor)); + ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ThermalVisor)); + return ret; } -rstl::reserved_vector CSamusHud::BuildPlayerHasBeams(const CStateManager& mgr) -{ - rstl::reserved_vector ret; - ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PowerBeam)); - ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::IceBeam)); - ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::WaveBeam)); - ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PlasmaBeam)); - return ret; +rstl::reserved_vector CSamusHud::BuildPlayerHasBeams(const CStateManager& mgr) { + rstl::reserved_vector ret; + ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PowerBeam)); + ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::IceBeam)); + ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::WaveBeam)); + ret.push_back(mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PlasmaBeam)); + return ret; } -void CSamusHud::InitializeFrameGluePermanent(const CStateManager& mgr) -{ - x588_base_basewidget_pivot = x274_loadedFrmeBaseHud->FindWidget("basewidget_pivot"); - x58c_helmet_BaseWidget_Pivot = x264_loadedFrmeHelmet->FindWidget("BaseWidget_Pivot"); - x590_base_Model_AutoMapper = static_cast(x274_loadedFrmeBaseHud->FindWidget("Model_AutoMapper")); - x594_base_textpane_counter = static_cast(x274_loadedFrmeBaseHud->FindWidget("textpane_counter")); - x594_base_textpane_counter->TextSupport().SetFontColor(g_tweakGuiColors->GetHudCounterFill()); - x594_base_textpane_counter->TextSupport().SetOutlineColor(g_tweakGuiColors->GetHudCounterOutline()); - x598_base_basewidget_message = x274_loadedFrmeBaseHud->FindWidget("basewidget_message"); - for (CGuiWidget* child = static_cast(x598_base_basewidget_message->GetChildObject()); - child ; child = static_cast(child->GetNextSibling())) - child->SetDepthTest(false); - x59c_base_textpane_message = static_cast(x274_loadedFrmeBaseHud->FindWidget("textpane_message")); - x5a0_base_model_abutton = static_cast(x274_loadedFrmeBaseHud->FindWidget("model_abutton")); - for (int i=0 ; i<4 ; ++i) - x5d8_guiLights[i] = x264_loadedFrmeHelmet->GetFrameLight(i); - x5d8_guiLights[3]->SetColor(zeus::CColor::skBlack); - for (int i=0 ; i<4 ; ++i) - { - SVideoBand& band = x5a4_videoBands[i]; - band.x0_videoband = static_cast(x274_loadedFrmeBaseHud->FindWidget(hecl::Format("model_videoband%d", i))); - band.x4_randA = 6 + (std::rand() % ((66 - 6) + 1)); - band.x8_randB = 16 + (std::rand() % ((256 - 16) + 1)); - } - x59c_base_textpane_message->SetDepthTest(false); - x598_base_basewidget_message->SetVisibility(false, ETraversalMode::Children); - x59c_base_textpane_message->TextSupport().SetFontColor(g_tweakGuiColors->GetHudMessageFill()); - x59c_base_textpane_message->TextSupport().SetOutlineColor(g_tweakGuiColors->GetHudMessageOutline()); - x59c_base_textpane_message->TextSupport().SetControlTXTRMap(&g_GameState->GameOptions().GetControlTXTRMap()); - x590_base_Model_AutoMapper->SetDepthWrite(true); - x304_basewidgetIdlePos = x588_base_basewidget_pivot->GetIdlePosition(); - x310_cameraPos = x274_loadedFrmeBaseHud->GetFrameCamera()->GetLocalPosition(); - RefreshHudOptions(); +void CSamusHud::InitializeFrameGluePermanent(const CStateManager& mgr) { + x588_base_basewidget_pivot = x274_loadedFrmeBaseHud->FindWidget("basewidget_pivot"); + x58c_helmet_BaseWidget_Pivot = x264_loadedFrmeHelmet->FindWidget("BaseWidget_Pivot"); + x590_base_Model_AutoMapper = static_cast(x274_loadedFrmeBaseHud->FindWidget("Model_AutoMapper")); + x594_base_textpane_counter = static_cast(x274_loadedFrmeBaseHud->FindWidget("textpane_counter")); + x594_base_textpane_counter->TextSupport().SetFontColor(g_tweakGuiColors->GetHudCounterFill()); + x594_base_textpane_counter->TextSupport().SetOutlineColor(g_tweakGuiColors->GetHudCounterOutline()); + x598_base_basewidget_message = x274_loadedFrmeBaseHud->FindWidget("basewidget_message"); + for (CGuiWidget* child = static_cast(x598_base_basewidget_message->GetChildObject()); child; + child = static_cast(child->GetNextSibling())) + child->SetDepthTest(false); + x59c_base_textpane_message = static_cast(x274_loadedFrmeBaseHud->FindWidget("textpane_message")); + x5a0_base_model_abutton = static_cast(x274_loadedFrmeBaseHud->FindWidget("model_abutton")); + for (int i = 0; i < 4; ++i) + x5d8_guiLights[i] = x264_loadedFrmeHelmet->GetFrameLight(i); + x5d8_guiLights[3]->SetColor(zeus::CColor::skBlack); + for (int i = 0; i < 4; ++i) { + SVideoBand& band = x5a4_videoBands[i]; + band.x0_videoband = + static_cast(x274_loadedFrmeBaseHud->FindWidget(hecl::Format("model_videoband%d", i))); + band.x4_randA = 6 + (std::rand() % ((66 - 6) + 1)); + band.x8_randB = 16 + (std::rand() % ((256 - 16) + 1)); + } + x59c_base_textpane_message->SetDepthTest(false); + x598_base_basewidget_message->SetVisibility(false, ETraversalMode::Children); + x59c_base_textpane_message->TextSupport().SetFontColor(g_tweakGuiColors->GetHudMessageFill()); + x59c_base_textpane_message->TextSupport().SetOutlineColor(g_tweakGuiColors->GetHudMessageOutline()); + x59c_base_textpane_message->TextSupport().SetControlTXTRMap(&g_GameState->GameOptions().GetControlTXTRMap()); + x590_base_Model_AutoMapper->SetDepthWrite(true); + x304_basewidgetIdlePos = x588_base_basewidget_pivot->GetIdlePosition(); + x310_cameraPos = x274_loadedFrmeBaseHud->GetFrameCamera()->GetLocalPosition(); + RefreshHudOptions(); } -void CSamusHud::InitializeFrameGlueMutable(const CStateManager& mgr) -{ - float lastTankEnergy = std::fmod(x2d0_playerHealth, CPlayerState::GetEnergyTankCapacity()); - u32 tanksFilled = x2d0_playerHealth / CPlayerState::GetEnergyTankCapacity(); +void CSamusHud::InitializeFrameGlueMutable(const CStateManager& mgr) { + float lastTankEnergy = std::fmod(x2d0_playerHealth, CPlayerState::GetEnergyTankCapacity()); + u32 tanksFilled = x2d0_playerHealth / CPlayerState::GetEnergyTankCapacity(); - CPlayer& player = mgr.GetPlayer(); - CPlayerState& playerState = *mgr.GetPlayerState(); - CPlayerGun& gun = *player.GetPlayerGun(); - float chargeFactor = gun.IsCharging() ? gun.GetChargeBeamFactor() : 0.f; - bool missilesActive = gun.GetMissleMode() == CPlayerGun::EMissleMode::Active; - bool lockedOnObj = player.GetOrbitTargetId() != kInvalidUniqueId; + CPlayer& player = mgr.GetPlayer(); + CPlayerState& playerState = *mgr.GetPlayerState(); + CPlayerGun& gun = *player.GetPlayerGun(); + float chargeFactor = gun.IsCharging() ? gun.GetChargeBeamFactor() : 0.f; + bool missilesActive = gun.GetMissleMode() == CPlayerGun::EMissleMode::Active; + bool lockedOnObj = player.GetOrbitTargetId() != kInvalidUniqueId; - switch (x2bc_nextState) - { - case EHudState::Combat: - { - x2b4_bossEnergyIntf = std::make_unique(*x288_loadedSelectedHud); + switch (x2bc_nextState) { + case EHudState::Combat: { + x2b4_bossEnergyIntf = std::make_unique(*x288_loadedSelectedHud); - x28c_energyIntf = std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, - x2d4_totalEnergyTanks, tanksFilled, - bool(x2e0_27_energyLow), EHudType::Combat); + x28c_energyIntf = + std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, x2d4_totalEnergyTanks, + tanksFilled, bool(x2e0_27_energyLow), EHudType::Combat); - if (!x290_threatIntf) - x290_threatIntf = std::make_unique(*x288_loadedSelectedHud, EHudType::Combat, - 9999.f); - else - x290_threatIntf->SetIsVisibleGame(true); + if (!x290_threatIntf) + x290_threatIntf = std::make_unique(*x288_loadedSelectedHud, EHudType::Combat, 9999.f); + else + x290_threatIntf->SetIsVisibleGame(true); - if (!x294_missileIntf) - x294_missileIntf = std::make_unique(*x288_loadedSelectedHud, x2dc_missileCapacity, - x2d8_missileAmount, chargeFactor, missilesActive, - EHudType::Combat, mgr); - else - x294_missileIntf->SetIsVisibleGame(true, mgr); + if (!x294_missileIntf) + x294_missileIntf = + std::make_unique(*x288_loadedSelectedHud, x2dc_missileCapacity, x2d8_missileAmount, + chargeFactor, missilesActive, EHudType::Combat, mgr); + else + x294_missileIntf->SetIsVisibleGame(true, mgr); - if (!x298_freeLookIntf) - x298_freeLookIntf = std::make_unique(*x288_loadedSelectedHud, EHudType::Combat, - bool(x2e0_24_inFreeLook), bool(x2e0_25_lookControlHeld), - lockedOnObj); - else - x298_freeLookIntf->SetIsVisibleGame(true); + if (!x298_freeLookIntf) + x298_freeLookIntf = + std::make_unique(*x288_loadedSelectedHud, EHudType::Combat, bool(x2e0_24_inFreeLook), + bool(x2e0_25_lookControlHeld), lockedOnObj); + else + x298_freeLookIntf->SetIsVisibleGame(true); - if (!x29c_decoIntf) - x29c_decoIntf = std::make_unique(*x288_loadedSelectedHud); - else - x29c_decoIntf->SetIsVisibleGame(true); + if (!x29c_decoIntf) + x29c_decoIntf = std::make_unique(*x288_loadedSelectedHud); + else + x29c_decoIntf->SetIsVisibleGame(true); - x2ac_radarIntf->SetIsVisibleGame(true); - x2a4_visorMenu->SetIsVisibleGame(true); - x2a8_beamMenu->SetIsVisibleGame(true); - InitializeDamageLight(); - UpdateEnergy(0.f, mgr, true); - break; - } - case EHudState::Ball: - { - u32 numPBs = playerState.GetItemAmount(CPlayerState::EItemType::PowerBombs); - u32 pbCap = playerState.GetItemCapacity(CPlayerState::EItemType::PowerBombs); - u32 bombsAvailable; - if (gun.IsBombReady()) - bombsAvailable = gun.GetBombCount(); - else - bombsAvailable = 0; - x2b0_ballIntf = std::make_unique(*x288_loadedSelectedHud, numPBs, pbCap, - bombsAvailable, gun.IsPowerBombReady() && - player.GetMorphballTransitionState() == - CPlayer::EPlayerMorphBallState::Morphed, - playerState.HasPowerUp( - CPlayerState::EItemType::MorphBallBombs)); + x2ac_radarIntf->SetIsVisibleGame(true); + x2a4_visorMenu->SetIsVisibleGame(true); + x2a8_beamMenu->SetIsVisibleGame(true); + InitializeDamageLight(); + UpdateEnergy(0.f, mgr, true); + break; + } + case EHudState::Ball: { + u32 numPBs = playerState.GetItemAmount(CPlayerState::EItemType::PowerBombs); + u32 pbCap = playerState.GetItemCapacity(CPlayerState::EItemType::PowerBombs); + u32 bombsAvailable; + if (gun.IsBombReady()) + bombsAvailable = gun.GetBombCount(); + else + bombsAvailable = 0; + x2b0_ballIntf = std::make_unique( + *x288_loadedSelectedHud, numPBs, pbCap, bombsAvailable, + gun.IsPowerBombReady() && player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed, + playerState.HasPowerUp(CPlayerState::EItemType::MorphBallBombs)); - x28c_energyIntf = std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, - x2d4_totalEnergyTanks, tanksFilled, - bool(x2e0_27_energyLow), EHudType::Ball); + x28c_energyIntf = + std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, x2d4_totalEnergyTanks, + tanksFilled, bool(x2e0_27_energyLow), EHudType::Ball); - x290_threatIntf.reset(); - x294_missileIntf.reset(); - x298_freeLookIntf.reset(); - x29c_decoIntf.reset(); - x3d4_damageLight = nullptr; - - x2ac_radarIntf->SetIsVisibleGame(false); - x2a4_visorMenu->SetIsVisibleGame(false); - x2a8_beamMenu->SetIsVisibleGame(false); - UpdateEnergy(0.f, mgr, true); - break; - } - case EHudState::Scan: - { - x2b4_bossEnergyIntf.reset(); - - x28c_energyIntf = std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, - x2d4_totalEnergyTanks, tanksFilled, - bool(x2e0_27_energyLow), EHudType::Scan); - - x290_threatIntf.reset(); - x294_missileIntf.reset(); - - x298_freeLookIntf = std::make_unique(*x288_loadedSelectedHud, EHudType::Scan, - bool(x2e0_24_inFreeLook), bool(x2e0_25_lookControlHeld), - lockedOnObj); - - x29c_decoIntf = std::make_unique(*x288_loadedSelectedHud); - InitializeDamageLight(); - UpdateEnergy(0.f, mgr, true); - break; - } - case EHudState::XRay: - { - x2b4_bossEnergyIntf = std::make_unique(*x288_loadedSelectedHud); - - x28c_energyIntf = std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, - x2d4_totalEnergyTanks, tanksFilled, - bool(x2e0_27_energyLow), EHudType::XRay); - - x290_threatIntf = std::make_unique(*x288_loadedSelectedHud, EHudType::XRay, - 9999.f); - - x294_missileIntf = std::make_unique(*x288_loadedSelectedHud, x2dc_missileCapacity, - x2d8_missileAmount, chargeFactor, missilesActive, - EHudType::XRay, mgr); - - x298_freeLookIntf = std::make_unique(*x288_loadedSelectedHud, - bool(x2e0_24_inFreeLook), bool(x2e0_25_lookControlHeld), - lockedOnObj); - - x29c_decoIntf = std::make_unique(*x288_loadedSelectedHud); - InitializeDamageLight(); - x2a4_visorMenu->SetIsVisibleGame(true); - x2a8_beamMenu->SetIsVisibleGame(true); - UpdateEnergy(0.f, mgr, true); - break; - } - case EHudState::Thermal: - { - x2b4_bossEnergyIntf = std::make_unique(*x288_loadedSelectedHud); - - x28c_energyIntf = std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, - x2d4_totalEnergyTanks, tanksFilled, - bool(x2e0_27_energyLow), EHudType::Thermal); - - x290_threatIntf = std::make_unique(*x288_loadedSelectedHud, EHudType::Thermal, - 9999.f); - - x294_missileIntf = std::make_unique(*x288_loadedSelectedHud, x2dc_missileCapacity, - x2d8_missileAmount, chargeFactor, missilesActive, - EHudType::Thermal, mgr); - - x298_freeLookIntf = std::make_unique(*x288_loadedSelectedHud, EHudType::Thermal, - bool(x2e0_24_inFreeLook), bool(x2e0_25_lookControlHeld), - lockedOnObj); - - x29c_decoIntf = std::make_unique(*x288_loadedSelectedHud); - InitializeDamageLight(); - x2a4_visorMenu->SetIsVisibleGame(true); - x2a8_beamMenu->SetIsVisibleGame(true); - UpdateEnergy(0.f, mgr, true); - break; - } - case EHudState::None: - UninitializeFrameGlueMutable(); - default: break; - } -} - -void CSamusHud::UninitializeFrameGlueMutable() -{ - x2b4_bossEnergyIntf.reset(); - x28c_energyIntf.reset(); - x29c_decoIntf.reset(); x290_threatIntf.reset(); x294_missileIntf.reset(); x298_freeLookIntf.reset(); - x2b0_ballIntf.reset(); + x29c_decoIntf.reset(); x3d4_damageLight = nullptr; + + x2ac_radarIntf->SetIsVisibleGame(false); + x2a4_visorMenu->SetIsVisibleGame(false); + x2a8_beamMenu->SetIsVisibleGame(false); + UpdateEnergy(0.f, mgr, true); + break; + } + case EHudState::Scan: { + x2b4_bossEnergyIntf.reset(); + + x28c_energyIntf = + std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, x2d4_totalEnergyTanks, + tanksFilled, bool(x2e0_27_energyLow), EHudType::Scan); + + x290_threatIntf.reset(); + x294_missileIntf.reset(); + + x298_freeLookIntf = std::make_unique( + *x288_loadedSelectedHud, EHudType::Scan, bool(x2e0_24_inFreeLook), bool(x2e0_25_lookControlHeld), lockedOnObj); + + x29c_decoIntf = std::make_unique(*x288_loadedSelectedHud); + InitializeDamageLight(); + UpdateEnergy(0.f, mgr, true); + break; + } + case EHudState::XRay: { + x2b4_bossEnergyIntf = std::make_unique(*x288_loadedSelectedHud); + + x28c_energyIntf = + std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, x2d4_totalEnergyTanks, + tanksFilled, bool(x2e0_27_energyLow), EHudType::XRay); + + x290_threatIntf = std::make_unique(*x288_loadedSelectedHud, EHudType::XRay, 9999.f); + + x294_missileIntf = + std::make_unique(*x288_loadedSelectedHud, x2dc_missileCapacity, x2d8_missileAmount, + chargeFactor, missilesActive, EHudType::XRay, mgr); + + x298_freeLookIntf = std::make_unique(*x288_loadedSelectedHud, bool(x2e0_24_inFreeLook), + bool(x2e0_25_lookControlHeld), lockedOnObj); + + x29c_decoIntf = std::make_unique(*x288_loadedSelectedHud); + InitializeDamageLight(); + x2a4_visorMenu->SetIsVisibleGame(true); + x2a8_beamMenu->SetIsVisibleGame(true); + UpdateEnergy(0.f, mgr, true); + break; + } + case EHudState::Thermal: { + x2b4_bossEnergyIntf = std::make_unique(*x288_loadedSelectedHud); + + x28c_energyIntf = + std::make_unique(*x288_loadedSelectedHud, lastTankEnergy, x2d4_totalEnergyTanks, + tanksFilled, bool(x2e0_27_energyLow), EHudType::Thermal); + + x290_threatIntf = std::make_unique(*x288_loadedSelectedHud, EHudType::Thermal, 9999.f); + + x294_missileIntf = + std::make_unique(*x288_loadedSelectedHud, x2dc_missileCapacity, x2d8_missileAmount, + chargeFactor, missilesActive, EHudType::Thermal, mgr); + + x298_freeLookIntf = + std::make_unique(*x288_loadedSelectedHud, EHudType::Thermal, bool(x2e0_24_inFreeLook), + bool(x2e0_25_lookControlHeld), lockedOnObj); + + x29c_decoIntf = std::make_unique(*x288_loadedSelectedHud); + InitializeDamageLight(); + x2a4_visorMenu->SetIsVisibleGame(true); + x2a8_beamMenu->SetIsVisibleGame(true); + UpdateEnergy(0.f, mgr, true); + break; + } + case EHudState::None: + UninitializeFrameGlueMutable(); + default: + break; + } } -void CSamusHud::InitializeDamageLight() -{ - s16 lightId = x288_loadedSelectedHud->GetWidgetIdDB().AddWidget("DamageSpotLight"); - s16 parentId = x288_loadedSelectedHud->FindWidget("basewidget_pivot")->GetSelfId(); - CGuiWidget::CGuiWidgetParms parms(x288_loadedSelectedHud, false, lightId, - parentId, true, true, false, - g_tweakGuiColors->GetHudDamageLightColor(), - CGuiWidget::EGuiModelDrawFlags::Alpha, false, false); - - std::shared_ptr light = std::make_shared( - parms, CLight::BuildSpot(zeus::CVector3f::skZero, zeus::CVector3f::skForward, - zeus::CColor::skWhite, g_tweakGui->GetHudDamageLightSpotAngle())); - x3d4_damageLight = light.get(); - x3d4_damageLight->SetColor(zeus::CColor::skBlack); - - zeus::CColor lightColor = g_tweakGuiColors->GetHudFrameColor(); - lightColor *= lightColor.a(); - lightColor.a() = 1.f; - x3d4_damageLight->SetAmbientLightColor(lightColor); - - x3d4_damageLight->SetDistC(1.f); - x3d4_damageLight->SetDistL(0.f); - x3d4_damageLight->SetAngleC(g_tweakGui->GetDamageLightAngleC()); - x3d4_damageLight->SetAngleL(g_tweakGui->GetDamageLightAngleL()); - x3d4_damageLight->SetAngleQ(g_tweakGui->GetDamageLightAngleQ()); - x3d4_damageLight->SetLightId(4); - - x3d4_damageLight->SetLocalTransform(zeus::CTransform::Identity()); - - x288_loadedSelectedHud->RegisterLight(std::move(light)); - x288_loadedSelectedHud->FindWidget(parentId)->AddChildWidget(x3d4_damageLight, false, true); - x288_loadedSelectedHud->AddLight(x3d4_damageLight); - - zeus::CTransform lightXf = zeus::CTransform::Translate(g_tweakGui->GetDamageLightPreTranslate()); - - x3d8_lightTransforms.clear(); - x3d8_lightTransforms.reserve(10); - - zeus::CTransform negX = zeus::CTransform::RotateX(zeus::degToRad(-g_tweakGui->GetDamageLightXfXAngle())); - zeus::CTransform posX = zeus::CTransform::RotateX(zeus::degToRad(g_tweakGui->GetDamageLightXfXAngle())); - zeus::CTransform negZ = zeus::CTransform::RotateZ(zeus::degToRad(-g_tweakGui->GetDamageLightXfZAngle())); - zeus::CTransform posZ = zeus::CTransform::RotateZ(zeus::degToRad(g_tweakGui->GetDamageLightXfZAngle())); - - x3d8_lightTransforms.push_back(lightXf); - x3d8_lightTransforms.push_back(zeus::CTransform::Translate(g_tweakGui->GetDamageLightCenterTranslate()) * lightXf); - x3d8_lightTransforms.push_back(posX * lightXf); - x3d8_lightTransforms.push_back(posX * negZ * lightXf); - x3d8_lightTransforms.push_back(negZ * lightXf); - x3d8_lightTransforms.push_back(negX * negZ * lightXf); - x3d8_lightTransforms.push_back(negX * lightXf); - x3d8_lightTransforms.push_back(negX * posZ * lightXf); - x3d8_lightTransforms.push_back(posZ * lightXf); - x3d8_lightTransforms.push_back(posX * posZ * lightXf); +void CSamusHud::UninitializeFrameGlueMutable() { + x2b4_bossEnergyIntf.reset(); + x28c_energyIntf.reset(); + x29c_decoIntf.reset(); + x290_threatIntf.reset(); + x294_missileIntf.reset(); + x298_freeLookIntf.reset(); + x2b0_ballIntf.reset(); + x3d4_damageLight = nullptr; } -void CSamusHud::UpdateEnergy(float dt, const CStateManager& mgr, bool init) -{ - CPlayer& player = mgr.GetPlayer(); - CPlayerState& playerState = *mgr.GetPlayerState(); - float energy = std::max(0.f, std::ceil(playerState.GetHealthInfo().GetHP())); +void CSamusHud::InitializeDamageLight() { + s16 lightId = x288_loadedSelectedHud->GetWidgetIdDB().AddWidget("DamageSpotLight"); + s16 parentId = x288_loadedSelectedHud->FindWidget("basewidget_pivot")->GetSelfId(); + CGuiWidget::CGuiWidgetParms parms(x288_loadedSelectedHud, false, lightId, parentId, true, true, false, + g_tweakGuiColors->GetHudDamageLightColor(), CGuiWidget::EGuiModelDrawFlags::Alpha, + false, false); - u32 numEnergyTanks = playerState.GetItemCapacity(CPlayerState::EItemType::EnergyTanks); - x2e0_27_energyLow = player.IsEnergyLow(mgr); + std::shared_ptr light = std::make_shared( + parms, CLight::BuildSpot(zeus::CVector3f::skZero, zeus::CVector3f::skForward, zeus::CColor::skWhite, + g_tweakGui->GetHudDamageLightSpotAngle())); + x3d4_damageLight = light.get(); + x3d4_damageLight->SetColor(zeus::CColor::skBlack); - if (init || energy != x2d0_playerHealth || numEnergyTanks != x2d4_totalEnergyTanks) - { - float lastTankEnergy = energy; - u32 filledTanks = 0; - while (lastTankEnergy > CPlayerState::GetBaseHealthCapacity()) - { - ++filledTanks; - lastTankEnergy -= CPlayerState::GetEnergyTankCapacity(); - } + zeus::CColor lightColor = g_tweakGuiColors->GetHudFrameColor(); + lightColor *= lightColor.a(); + lightColor.a() = 1.f; + x3d4_damageLight->SetAmbientLightColor(lightColor); - if (x2bc_nextState != EHudState::None) - { - if (x28c_energyIntf) - { - float curLastTankEnergy = x2d0_playerHealth; - while (curLastTankEnergy > CPlayerState::GetBaseHealthCapacity()) - curLastTankEnergy -= CPlayerState::GetEnergyTankCapacity(); - x28c_energyIntf->SetCurrEnergy(lastTankEnergy, curLastTankEnergy < lastTankEnergy); - } - x2d0_playerHealth = energy; - if (x28c_energyIntf) - { - x28c_energyIntf->SetNumTotalEnergyTanks(numEnergyTanks); - x28c_energyIntf->SetNumFilledEnergyTanks(filledTanks); - x28c_energyIntf->SetEnergyLow(x2e0_27_energyLow); - } - x2d4_totalEnergyTanks = numEnergyTanks; - } - } + x3d4_damageLight->SetDistC(1.f); + x3d4_damageLight->SetDistL(0.f); + x3d4_damageLight->SetAngleC(g_tweakGui->GetDamageLightAngleC()); + x3d4_damageLight->SetAngleL(g_tweakGui->GetDamageLightAngleL()); + x3d4_damageLight->SetAngleQ(g_tweakGui->GetDamageLightAngleQ()); + x3d4_damageLight->SetLightId(4); - if (x2b4_bossEnergyIntf) - { - const CEntity* bossEnt = mgr.GetObjectById(mgr.GetBossId()); - if (TCastToConstPtr act = bossEnt) - { - if (const CHealthInfo* hInfo = act->GetHealthInfo(mgr)) - { - float bossEnergy = std::ceil(hInfo->GetHP()); - x2b4_bossEnergyIntf->SetBossParams(true, g_MainStringTable->GetString(mgr.GetBossStringIdx()), - bossEnergy, mgr.GetTotalBossEnergy()); - } - else - { - x2b4_bossEnergyIntf->SetBossParams(false, u"", 0.f, 0.f); - } - } - else - { - x2b4_bossEnergyIntf->SetBossParams(false, u"", 0.f, 0.f); - } - } + x3d4_damageLight->SetLocalTransform(zeus::CTransform::Identity()); + + x288_loadedSelectedHud->RegisterLight(std::move(light)); + x288_loadedSelectedHud->FindWidget(parentId)->AddChildWidget(x3d4_damageLight, false, true); + x288_loadedSelectedHud->AddLight(x3d4_damageLight); + + zeus::CTransform lightXf = zeus::CTransform::Translate(g_tweakGui->GetDamageLightPreTranslate()); + + x3d8_lightTransforms.clear(); + x3d8_lightTransforms.reserve(10); + + zeus::CTransform negX = zeus::CTransform::RotateX(zeus::degToRad(-g_tweakGui->GetDamageLightXfXAngle())); + zeus::CTransform posX = zeus::CTransform::RotateX(zeus::degToRad(g_tweakGui->GetDamageLightXfXAngle())); + zeus::CTransform negZ = zeus::CTransform::RotateZ(zeus::degToRad(-g_tweakGui->GetDamageLightXfZAngle())); + zeus::CTransform posZ = zeus::CTransform::RotateZ(zeus::degToRad(g_tweakGui->GetDamageLightXfZAngle())); + + x3d8_lightTransforms.push_back(lightXf); + x3d8_lightTransforms.push_back(zeus::CTransform::Translate(g_tweakGui->GetDamageLightCenterTranslate()) * lightXf); + x3d8_lightTransforms.push_back(posX * lightXf); + x3d8_lightTransforms.push_back(posX * negZ * lightXf); + x3d8_lightTransforms.push_back(negZ * lightXf); + x3d8_lightTransforms.push_back(negX * negZ * lightXf); + x3d8_lightTransforms.push_back(negX * lightXf); + x3d8_lightTransforms.push_back(negX * posZ * lightXf); + x3d8_lightTransforms.push_back(posZ * lightXf); + x3d8_lightTransforms.push_back(posX * posZ * lightXf); } -void CSamusHud::UpdateFreeLook(float dt, const CStateManager& mgr) -{ - TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - CPlayer& player = mgr.GetPlayer(); - bool inFreeLook = player.IsInFreeLook() && fpCam; - bool lookControlHeld = player.GetFreeLookStickState(); - if (x2e0_24_inFreeLook != inFreeLook) - { - if (inFreeLook) - CSfxManager::SfxStart(SFXui_into_freelook, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - else - CSfxManager::SfxStart(SFXui_outof_freelook, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - x2e0_24_inFreeLook = inFreeLook; +void CSamusHud::UpdateEnergy(float dt, const CStateManager& mgr, bool init) { + CPlayer& player = mgr.GetPlayer(); + CPlayerState& playerState = *mgr.GetPlayerState(); + float energy = std::max(0.f, std::ceil(playerState.GetHealthInfo().GetHP())); + + u32 numEnergyTanks = playerState.GetItemCapacity(CPlayerState::EItemType::EnergyTanks); + x2e0_27_energyLow = player.IsEnergyLow(mgr); + + if (init || energy != x2d0_playerHealth || numEnergyTanks != x2d4_totalEnergyTanks) { + float lastTankEnergy = energy; + u32 filledTanks = 0; + while (lastTankEnergy > CPlayerState::GetBaseHealthCapacity()) { + ++filledTanks; + lastTankEnergy -= CPlayerState::GetEnergyTankCapacity(); } - float deltaFrames = 60.f * dt * 0.999999f; - float oldLookDeltaDot = x574_lookDeltaDot; - zeus::CVector3f fpCamDir; - if (!fpCam) - fpCamDir = x568_fpCamDir; + if (x2bc_nextState != EHudState::None) { + if (x28c_energyIntf) { + float curLastTankEnergy = x2d0_playerHealth; + while (curLastTankEnergy > CPlayerState::GetBaseHealthCapacity()) + curLastTankEnergy -= CPlayerState::GetEnergyTankCapacity(); + x28c_energyIntf->SetCurrEnergy(lastTankEnergy, curLastTankEnergy < lastTankEnergy); + } + x2d0_playerHealth = energy; + if (x28c_energyIntf) { + x28c_energyIntf->SetNumTotalEnergyTanks(numEnergyTanks); + x28c_energyIntf->SetNumFilledEnergyTanks(filledTanks); + x28c_energyIntf->SetEnergyLow(x2e0_27_energyLow); + } + x2d4_totalEnergyTanks = numEnergyTanks; + } + } + + if (x2b4_bossEnergyIntf) { + const CEntity* bossEnt = mgr.GetObjectById(mgr.GetBossId()); + if (TCastToConstPtr act = bossEnt) { + if (const CHealthInfo* hInfo = act->GetHealthInfo(mgr)) { + float bossEnergy = std::ceil(hInfo->GetHP()); + x2b4_bossEnergyIntf->SetBossParams(true, g_MainStringTable->GetString(mgr.GetBossStringIdx()), bossEnergy, + mgr.GetTotalBossEnergy()); + } else { + x2b4_bossEnergyIntf->SetBossParams(false, u"", 0.f, 0.f); + } + } else { + x2b4_bossEnergyIntf->SetBossParams(false, u"", 0.f, 0.f); + } + } +} + +void CSamusHud::UpdateFreeLook(float dt, const CStateManager& mgr) { + TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + CPlayer& player = mgr.GetPlayer(); + bool inFreeLook = player.IsInFreeLook() && fpCam; + bool lookControlHeld = player.GetFreeLookStickState(); + if (x2e0_24_inFreeLook != inFreeLook) { + if (inFreeLook) + CSfxManager::SfxStart(SFXui_into_freelook, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); else - fpCamDir = fpCam->GetTransform().basis[1]; + CSfxManager::SfxStart(SFXui_outof_freelook, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x2e0_24_inFreeLook = inFreeLook; + } - bool lookAdj = inFreeLook ? lookControlHeld : false; + float deltaFrames = 60.f * dt * 0.999999f; + float oldLookDeltaDot = x574_lookDeltaDot; + zeus::CVector3f fpCamDir; + if (!fpCam) + fpCamDir = x568_fpCamDir; + else + fpCamDir = fpCam->GetTransform().basis[1]; - if (lookAdj) - { - x574_lookDeltaDot = fpCamDir.dot(x568_fpCamDir); - if (std::fabs(x574_lookDeltaDot) > 1.f) - x574_lookDeltaDot = (x574_lookDeltaDot >= 0.f) ? 1.f : -1.f; - } - else - { - x574_lookDeltaDot = 1.f; + bool lookAdj = inFreeLook ? lookControlHeld : false; + + if (lookAdj) { + x574_lookDeltaDot = fpCamDir.dot(x568_fpCamDir); + if (std::fabs(x574_lookDeltaDot) > 1.f) + x574_lookDeltaDot = (x574_lookDeltaDot >= 0.f) ? 1.f : -1.f; + } else { + x574_lookDeltaDot = 1.f; + } + + x568_fpCamDir = fpCamDir; + + if ((oldLookDeltaDot >= deltaFrames && x574_lookDeltaDot < deltaFrames) || + (oldLookDeltaDot < deltaFrames && x574_lookDeltaDot >= deltaFrames)) { + x578_freeLookSfxCycleTimer = 0.f; + } else if (x578_freeLookSfxCycleTimer < 0.05f) { + x578_freeLookSfxCycleTimer = std::min(x578_freeLookSfxCycleTimer + dt, 0.05f); + if (x578_freeLookSfxCycleTimer == 0.05f) { + if (x574_lookDeltaDot < deltaFrames) { + if (!x564_freeLookSfx) + x564_freeLookSfx = CSfxManager::SfxStart(SFXui_freelook_move_lp, 1.f, 0.f, true, 0x7f, true, kInvalidAreaId); + } else { + CSfxManager::SfxStop(x564_freeLookSfx); + x564_freeLookSfx.reset(); + } } + } + + if (fpCam) { + zeus::CMatrix3f camRot = fpCam->GetTransform().buildMatrix3f(); + zeus::CVector3f camDir(camRot[1]); + zeus::CUnitVector3f camDirNoZ = camDir; + camDirNoZ.z() = 0.f; + float offHorizonDot = camDir.dot(camDirNoZ); + if (std::fabs(offHorizonDot) > 1.f) + offHorizonDot = (offHorizonDot >= 0.f) ? 1.f : -1.f; + float offHorizonAngle = std::fabs(std::acos(offHorizonDot)); + if (camDir.z() < 0.f) + offHorizonAngle = -offHorizonAngle; - x568_fpCamDir = fpCamDir; - - if ((oldLookDeltaDot >= deltaFrames && x574_lookDeltaDot < deltaFrames) || - (oldLookDeltaDot < deltaFrames && x574_lookDeltaDot >= deltaFrames)) - { - x578_freeLookSfxCycleTimer = 0.f; - } - else if (x578_freeLookSfxCycleTimer < 0.05f) - { - x578_freeLookSfxCycleTimer = std::min(x578_freeLookSfxCycleTimer + dt, 0.05f); - if (x578_freeLookSfxCycleTimer == 0.05f) - { - if (x574_lookDeltaDot < deltaFrames) - { - if (!x564_freeLookSfx) - x564_freeLookSfx = CSfxManager::SfxStart(SFXui_freelook_move_lp, 1.f, 0.f, true, 0x7f, true, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(x564_freeLookSfx); - x564_freeLookSfx.reset(); - } - } - } - - if (fpCam) - { - zeus::CMatrix3f camRot = fpCam->GetTransform().buildMatrix3f(); - zeus::CVector3f camDir(camRot[1]); - zeus::CUnitVector3f camDirNoZ = camDir; - camDirNoZ.z() = 0.f; - float offHorizonDot = camDir.dot(camDirNoZ); - if (std::fabs(offHorizonDot) > 1.f) - offHorizonDot = (offHorizonDot >= 0.f) ? 1.f : -1.f; - float offHorizonAngle = std::fabs(std::acos(offHorizonDot)); - if (camDir.z() < 0.f) - offHorizonAngle = -offHorizonAngle; - - if (x298_freeLookIntf) - x298_freeLookIntf->SetFreeLookState(inFreeLook, lookControlHeld, - player.GetOrbitTargetId() != kInvalidUniqueId, - offHorizonAngle); - - if (x564_freeLookSfx) - { - float pitch = offHorizonAngle * (g_tweakGui->GetFreeLookSfxPitchScale() / 8192.f) / (M_PIF / 2.f); - if (!g_tweakGui->GetNoAbsoluteFreeLookSfxPitch()) - pitch = std::fabs(pitch); - CSfxManager::PitchBend(x564_freeLookSfx, pitch); - } - } -} - -void CSamusHud::UpdateMissile(float dt, const CStateManager& mgr, bool init) -{ - CPlayerGun& gun = *mgr.GetPlayer().GetPlayerGun(); - CPlayerState& playerState = *mgr.GetPlayerState(); - - u32 numMissles = playerState.GetItemAmount(CPlayerState::EItemType::Missiles); - u32 missileCap = playerState.GetItemCapacity(CPlayerState::EItemType::Missiles); - CPlayerGun::EMissleMode missileMode = gun.GetMissleMode(); - float chargeFactor = gun.IsCharging() ? gun.GetChargeBeamFactor() : 0.f; - - if (x294_missileIntf) - x294_missileIntf->SetChargeBeamFactor(chargeFactor); - - if (init || numMissles != x2d8_missileAmount || missileMode != x2ec_missileMode || - missileCap != x2dc_missileCapacity) - { - if (x294_missileIntf) - { - if (missileCap != x2dc_missileCapacity) - x294_missileIntf->SetMissileCapacity(missileCap); - if (numMissles != x2d8_missileAmount) - x294_missileIntf->SetNumMissiles(numMissles, mgr); - if (missileMode != x2ec_missileMode) - x294_missileIntf->SetIsMissilesActive(missileMode == CPlayerGun::EMissleMode::Active); - } - x2d8_missileAmount = numMissles; - x2ec_missileMode = missileMode; - x2dc_missileCapacity = missileCap; - } -} - -void CSamusHud::UpdateVideoBands(float dt, const CStateManager& mgr) -{ - for (int i=0 ; i<4 ; ++i) - if (x5a4_videoBands[i].x0_videoband) - x5a4_videoBands[i].x0_videoband->SetIsVisible(false); -} - -void CSamusHud::UpdateBallMode(const CStateManager& mgr, bool init) -{ - if (!x2b0_ballIntf) - return; - - CPlayer& player = mgr.GetPlayer(); - CPlayerGun& gun = *player.GetPlayerGun(); - CPlayerState& playerState = *mgr.GetPlayerState(); - u32 numPbs = playerState.GetItemAmount(CPlayerState::EItemType::PowerBombs); - u32 pbCap = playerState.GetItemCapacity(CPlayerState::EItemType::PowerBombs); - u32 bombCount = gun.IsBombReady() ? gun.GetBombCount() : 0; - bool hasBombs = playerState.HasPowerUp(CPlayerState::EItemType::MorphBallBombs); - bool pbReady = gun.IsPowerBombReady() && - player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed; - - x2b0_ballIntf->SetBombParams(numPbs, pbCap, bombCount, hasBombs, pbReady, false); -} - -void CSamusHud::UpdateThreatAssessment(float dt, const CStateManager& mgr) -{ - CMaterialFilter filter(CMaterialList(EMaterialTypes::Trigger), CMaterialList(), - CMaterialFilter::EFilterType::Include); - - CPlayer& player = mgr.GetPlayer(); - zeus::CAABox playerAABB = zeus::CAABox::skNullBox; - if (std::experimental::optional aabb = player.GetTouchBounds()) - playerAABB = *aabb; - - zeus::CAABox aabb; - aabb.accumulateBounds(player.GetTranslation() - g_tweakGui->GetThreatRange()); - aabb.accumulateBounds(player.GetTranslation() + g_tweakGui->GetThreatRange()); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, aabb, filter, nullptr); - - float threatDist = 9999.f; - for (TUniqueId id : nearList) - { - const CEntity* ent = mgr.GetObjectById(id); - if (TCastToConstPtr trigger = ent) - { - if (!bool(trigger->GetTriggerFlags() & ETriggerFlags::DetectPlayer)) - continue; - if (trigger->GetDamageInfo().GetDamage() == 0.f) - continue; - if (std::experimental::optional aabb = trigger->GetTouchBounds()) - { - float dist = playerAABB.distanceBetween(*aabb); - if (dist < threatDist) - threatDist = dist; - } - } - } - - if (player.GetThreatOverride() > 0.f) - threatDist = std::min((1.f - player.GetThreatOverride()) * g_tweakGui->GetThreatRange(), threatDist); - - if (mgr.IsFullThreat()) - threatDist = 0.f; - if (x290_threatIntf) - x290_threatIntf->SetThreatDistance(threatDist); -} - -void CSamusHud::UpdateVisorAndBeamMenus(float dt, const CStateManager& mgr) -{ - CPlayer& player = mgr.GetPlayer(); - CPlayerGun& gun = *player.GetPlayerGun(); - CPlayerState& playerState = *mgr.GetPlayerState(); - - float beamInterp = zeus::clamp(0.f, gun.GetHoloTransitionFactor(), 1.f); - float visorInterp = playerState.GetVisorTransitionFactor(); - - if (x2a8_beamMenu) - { - x2a8_beamMenu->SetSelection(int(gun.GetCurrentBeam()), int(gun.GetNextBeam()), beamInterp); - x2a8_beamMenu->SetPlayerHas(BuildPlayerHasBeams(mgr)); - } - - if (x2a4_visorMenu) - { - x2a4_visorMenu->SetSelection(int(playerState.GetCurrentVisor()), - int(playerState.GetTransitioningVisor()), visorInterp); - x2a4_visorMenu->SetPlayerHas(BuildPlayerHasVisors(mgr)); - } -} - -void CSamusHud::UpdateCameraDebugSettings() -{ - float fov = x5ec_camFovTweaks[g_tweakGui->GetHudCamFovTweak()]; - float y = x62c_camYTweaks[g_tweakGui->GetHudCamYTweak()]; - float z = x72c_camZTweaks[g_tweakGui->GetHudCamZTweak()]; - if (x2a0_helmetIntf) - x2a0_helmetIntf->UpdateCameraDebugSettings(fov, y, z); - if (x29c_decoIntf) - x29c_decoIntf->UpdateCameraDebugSettings(fov, y, z); - x274_loadedFrmeBaseHud->GetFrameCamera()->SetFov(fov); - x310_cameraPos.y() = y; - x310_cameraPos.z() = z; -} - -void CSamusHud::UpdateEnergyLow(float dt, const CStateManager& mgr) -{ - bool cineCam = TCastToConstPtr(mgr.GetCameraManager()->GetCurrentCamera(mgr)); - float oldTimer = x57c_energyLowTimer; - - x57c_energyLowTimer = std::fmod(x57c_energyLowTimer + dt, 0.5f); - if (x57c_energyLowTimer < 0.25f) - x580_energyLowPulse = x57c_energyLowTimer / 0.25f; - else - x580_energyLowPulse = (0.5f - x57c_energyLowTimer) / 0.25f; - - if (!cineCam && x2e0_27_energyLow && x57c_energyLowTimer < oldTimer) - CSfxManager::SfxStart(SFXui_energy_low, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); -} - -void CSamusHud::ApplyClassicLag(const zeus::CUnitVector3f& lookDir, zeus::CQuaternion& rot, - const CStateManager& mgr, float dt, bool invert) -{ - zeus::CQuaternion lookRot = zeus::CQuaternion::lookAt(lookDir, zeus::CVector3f::skForward, 2.f * M_PIF); - zeus::CQuaternion lookRot2; - if (invert) - { - zeus::CUnitVector3f v1(lookRot.transform(x2f8_fpCamDir)); - lookRot2 = zeus::CQuaternion::lookAt(v1, zeus::CVector3f::skForward, 2.f * M_PIF); - } - else - { - zeus::CUnitVector3f v1(lookRot.transform(x2f8_fpCamDir)); - lookRot2 = zeus::CQuaternion::lookAt(zeus::CVector3f::skForward, v1, 2.f * M_PIF); - } - - zeus::CQuaternion doubleRot = lookRot2 * lookRot2; - float dot = doubleRot.toTransform().basis[1].dot(rot.toTransform().basis[1]); - if (std::fabs(dot) > 1.f) - dot = (dot >= 0.f) ? 1.f : -1.f; - - float angle = std::acos(dot); - float tmp = 0.f; - if (angle > 0.f) - tmp = 0.5f * dt * g_tweakPlayer->GetFreeLookSpeed() / angle; - - float t = zeus::clamp(0.f, 18.f * dt * tmp, 1.f); - rot = zeus::CQuaternion::slerp(rot, doubleRot, t); -} - -void CSamusHud::UpdateHudLag(float dt, const CStateManager& mgr) -{ - CPlayer& player = mgr.GetPlayer(); - - if (x29c_decoIntf) - x29c_decoIntf->SetDecoRotation(player.GetYaw()); - - if (!g_GameState->GameOptions().GetHUDLag()) - { - if (x2a0_helmetIntf) - { - x2a0_helmetIntf->SetHudLagRotation(zeus::CMatrix3f::skIdentityMatrix3f); - x2a0_helmetIntf->SetHudLagOffset(zeus::CVector3f::skZero); - } - if (x29c_decoIntf) - { - x29c_decoIntf->SetReticuleTransform(zeus::CMatrix3f::skIdentityMatrix3f); - x29c_decoIntf->SetHudRotation(zeus::CQuaternion::skNoRotation); - x29c_decoIntf->SetHudOffset(zeus::CVector3f::skZero); - } - x588_base_basewidget_pivot->SetTransform( - zeus::CTransform::Translate(x588_base_basewidget_pivot->GetWorldPosition())); - x274_loadedFrmeBaseHud->GetFrameCamera()->SetO2WTransform( - BuildFinalCameraTransform(zeus::CQuaternion::skNoRotation, x304_basewidgetIdlePos, x310_cameraPos)); - x8_targetingMgr.CompoundTargetReticle().SetLeadingOrientation(zeus::CQuaternion::skNoRotation); - } - else - { - zeus::CVector3f fpCamDir = x2f8_fpCamDir; - if (TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr)) - fpCamDir = fpCam->GetTransform().buildMatrix3f()[1]; - - ApplyClassicLag(fpCamDir, x31c_hudLag, mgr, dt, false); - ApplyClassicLag(fpCamDir, x32c_invHudLag, mgr, dt, true); - - zeus::CQuaternion rot = zeus::CQuaternion::lookAt(zeus::CUnitVector3f(x2f8_fpCamDir), fpCamDir, 2.f * M_PIF); - rot *= rot; - rot *= rot; - x8_targetingMgr.CompoundTargetReticle().SetLeadingOrientation(rot); - - zeus::CVector3f bobTranslation = player.GetCameraBob()->GetHelmetBobTranslation(); - - zeus::CQuaternion lagRot = x44c_hudLagShakeRot * x31c_hudLag; - zeus::CVector3f lagOff = x41c_decoShakeTranslate * g_tweakGui->GetHudLagOffsetScale(); - lagOff.z() += bobTranslation.z(); - if (x2a0_helmetIntf) - { - x2a0_helmetIntf->SetHudLagRotation(lagRot); - x2a0_helmetIntf->SetHudLagOffset(lagOff); - } - if (x29c_decoIntf) - { - x29c_decoIntf->SetReticuleTransform(x32c_invHudLag); - x29c_decoIntf->SetHudRotation(lagRot); - x29c_decoIntf->SetHudOffset(lagOff); - } - - x274_loadedFrmeBaseHud->GetFrameCamera()->SetO2WTransform( - BuildFinalCameraTransform(lagRot, x304_basewidgetIdlePos + lagOff, x310_cameraPos)); - x2f8_fpCamDir = fpCamDir; - } -} - -bool CSamusHud::IsCachedLightInAreaLights(const SCachedHudLight& light, const CActorLights& areaLights) const -{ - for (const CLight& l : areaLights.GetAreaLights()) - { - if (l.GetColor() != light.xc_color || l.GetPosition() != light.x0_pos) - continue; - return true; - } - return false; -} - -bool CSamusHud::IsAreaLightInCachedLights(const CLight& light) const -{ - for (const SCachedHudLight& l : x340_hudLights) - { - if (l.x1c_fader == 0.f) - continue; - if (l.xc_color != light.GetColor() || l.x0_pos != light.GetPosition()) - continue; - return true; - } - return false; -} - -int CSamusHud::FindEmptyHudLightSlot(const CLight& light) const -{ - for (int i=0 ; i<3 ; ++i) - if (x340_hudLights[i].x1c_fader == 0.f) - return i; - return -1; -} - -zeus::CColor CSamusHud::GetVisorHudLightColor(const zeus::CColor& color, const CStateManager& mgr) const -{ - zeus::CColor ret = color; - const CPlayerState& playerState = *mgr.GetPlayerState(); - float t = playerState.GetVisorTransitionFactor(); - switch (playerState.GetCurrentVisor()) - { - case CPlayerState::EPlayerVisor::Scan: - ret *= zeus::CColor::lerp(zeus::CColor::skWhite, g_tweakGuiColors->GetScanVisorHudLightMultiply(), t); - break; - case CPlayerState::EPlayerVisor::Thermal: - ret *= g_tweakGuiColors->GetThermalVisorHudLightMultiply(); - break; - case CPlayerState::EPlayerVisor::XRay: - ret = zeus::CColor(zeus::CColor(0.3f, 0.6f, 0.1f).rgbDot(ret)); - break; - default: break; - } - return ret; -} - -void CSamusHud::UpdateHudDynamicLights(float dt, const CStateManager& mgr) -{ - if (TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr)) - { - zeus::CVector3f lookDir = fpCam->GetTransform().basis[1]; - zeus::CAABox camAABB(fpCam->GetTranslation() - 0.125f, fpCam->GetTranslation() + 0.125f); - TAreaId playerArea = mgr.GetPlayer().GetAreaIdAlways(); - if (playerArea == kInvalidAreaId) - return; - x33c_lights->BuildAreaLightList(mgr, *mgr.GetWorld()->GetAreaAlways(playerArea), camAABB); - for (SCachedHudLight& light : x340_hudLights) - if (light.x1c_fader > 0.f && - ((light.x0_pos - fpCam->GetTranslation()).normalized().dot(lookDir) <= 0.15707964f || - !IsCachedLightInAreaLights(light, *x33c_lights))) - light.x1c_fader *= -1.f; - int negCount = 0; - for (SCachedHudLight& light : x340_hudLights) - if (light.x1c_fader <= 0.f) - ++negCount; - --negCount; - for (const CLight& light : x33c_lights->GetAreaLights()) - { - if (negCount < 1) - break; - if (IsAreaLightInCachedLights(light)) - continue; - if ((light.GetPosition() - fpCam->GetTranslation()).normalized().dot(lookDir) > 0.15707964f) - { - int slot = FindEmptyHudLightSlot(light); - if (slot == -1) - continue; - --negCount; - SCachedHudLight& cachedLight = x340_hudLights[slot]; - cachedLight.x0_pos = light.GetPosition(); - cachedLight.xc_color = light.GetColor(); - cachedLight.x10_distC = light.GetAttenuationConstant(); - cachedLight.x14_distL = light.GetAttenuationLinear(); - cachedLight.x18_distQ = light.GetAttenuationQuadratic(); - cachedLight.x1c_fader = 0.001f; - } - } - - float dt2 = 2.f * dt; - for (SCachedHudLight& light : x340_hudLights) - { - if (light.x1c_fader < 0.f) - light.x1c_fader = std::min(0.f, light.x1c_fader + dt2); - else if (light.x1c_fader < 1.f && light.x1c_fader != 0.f) - light.x1c_fader = std::min(light.x1c_fader + dt2, 1.f); - } - - CPlayerState& playerState = *mgr.GetPlayerState(); - CPlayerState::EPlayerVisor visor = playerState.GetCurrentVisor(); - float visorT = playerState.GetVisorTransitionFactor(); - zeus::CColor lightAdd = - zeus::CColor::lerp(g_tweakGui->GetVisorHudLightAdd(0), - g_tweakGui->GetVisorHudLightAdd(int(visor)), - visorT); - zeus::CColor lightMul = - zeus::CColor::lerp(g_tweakGui->GetVisorHudLightMultiply(0), - g_tweakGui->GetVisorHudLightMultiply(int(visor)), - visorT); - - auto lightIt = x5d8_guiLights.begin(); - float maxIntensity = 0.f; - int maxIntensityIdx = 0; - for (int i=0 ; i<3 ; ++i) - { - SCachedHudLight& light = x340_hudLights[i]; - CGuiLight* lightWidget = *lightIt++; - zeus::CVector3f lightToCam = fpCam->GetTranslation() - light.x0_pos; - zeus::CVector3f lightNormal = fpCam->GetTransform().buildMatrix3f() * lightToCam.normalized(); - float dist = std::max(lightToCam.magnitude(), FLT_EPSILON); - float falloffMul = 1.f / - (dist * dist * light.x18_distQ * g_tweakGui->GetHudLightAttMulQuadratic() + - dist * light.x14_distL * g_tweakGui->GetHudLightAttMulLinear() + - light.x10_distC * g_tweakGui->GetHudLightAttMulConstant()); - falloffMul = std::min(falloffMul, 1.f); - lightWidget->SetO2WTransform(zeus::lookAt(zeus::CVector3f::skZero, lightNormal)); - float fadedFalloff = falloffMul * std::fabs(light.x1c_fader); - zeus::CColor lightColor = GetVisorHudLightColor(light.xc_color * zeus::CColor(fadedFalloff), mgr); - lightWidget->SetColor(lightColor); - lightAdd += lightColor * lightMul; - float greyscale = fadedFalloff * zeus::CVector3f::skForward.dot(-lightNormal) * - lightAdd.rgbDot(zeus::CColor(0.3f, 0.6f, 0.1f)); - if (greyscale > maxIntensity) - { - maxIntensity = greyscale; - maxIntensityIdx = i; - } - } - - CLight brightestGameLight = CLight::BuildPoint(zeus::CVector3f::skZero, zeus::CColor::skBlack); - for (CEntity* ent : mgr.GetLightObjectList()) - { - if (!ent || !ent->GetActive()) - continue; - CGameLight& gameLight = static_cast(*ent); - if (TCastToConstPtr(mgr.GetObjectById(gameLight.GetParentId()))) - continue; - CLight thisLight = gameLight.GetLight(); - if (thisLight.GetIntensity() > brightestGameLight.GetIntensity()) - { - zeus::CSphere sphere(thisLight.GetPosition(), thisLight.GetRadius()); - if (camAABB.intersects(sphere)) - brightestGameLight = thisLight; - } - } - - if (brightestGameLight.GetIntensity() > FLT_EPSILON) - { - zeus::CVector3f lightToCam = fpCam->GetTranslation() - brightestGameLight.GetPosition(); - float dist = std::max(lightToCam.magnitude(), FLT_EPSILON); - float falloffMul = 1.f / - (dist * dist * brightestGameLight.GetAttenuationQuadratic() * g_tweakGui->GetHudLightAttMulQuadratic() + - dist * brightestGameLight.GetAttenuationLinear() * g_tweakGui->GetHudLightAttMulLinear() + - brightestGameLight.GetAttenuationConstant() * g_tweakGui->GetHudLightAttMulConstant()); - falloffMul = std::min(falloffMul, 1.f); - zeus::CColor falloffColor = brightestGameLight.GetColor() * zeus::CColor(falloffMul); - falloffColor = GetVisorHudLightColor(falloffColor, mgr); - if (brightestGameLight.GetType() == ELightType::Spot) - { - float quarterCicleFactor = zeus::clamp(0.f, std::asin(std::max(0.f, fpCam->GetTransform().basis[1]. - dot(brightestGameLight.GetDirection()))) * (M_PIF / 2.f), 1.f); - falloffColor *= zeus::CColor(quarterCicleFactor); - } - lightAdd += falloffColor; - } - - const CGuiLight& brightestLight = *x5d8_guiLights[maxIntensityIdx]; - lightAdd += x33c_lights->GetAmbientColor() * zeus::CColor(0.25f, 1.f); - zeus::CVector3f revDir = -brightestLight.GetWorldTransform().basis[1]; - float foreDot = revDir.dot(zeus::CVector3f::skForward); - x5d8_guiLights[3]->SetO2WTransform( - zeus::lookAt(zeus::CVector3f::skZero, zeus::CVector3f::skForward * 2.f * foreDot - revDir)); - x5d8_guiLights[3]->SetColor(g_tweakGui->GetHudReflectivityLightColor() * brightestLight.GetIntermediateColor()); - x5d8_guiLights[3]->SetAmbientLightColor(lightAdd); - } -} - -void CSamusHud::UpdateHudDamage(float dt, const CStateManager& mgr, - DataSpec::ITweakGui::EHelmetVisMode helmetVis) -{ - CPlayer& player = mgr.GetPlayer(); - if (player.WasDamaged() && mgr.GetGameState() == CStateManager::EGameState::Running) - x3e8_damageTIme += dt; - else - x3e8_damageTIme = 0.f; - - float pulseDur = g_tweakGui->GetHudDamagePulseDuration(); - float pulseTime = std::fabs(std::fmod(x3e8_damageTIme, pulseDur)); - if (pulseTime < 0.5f * pulseDur) - x3ec_damageLightPulser = pulseTime / (0.5f * pulseDur); - else - x3ec_damageLightPulser = (pulseDur - pulseTime) / (0.5f * pulseDur); - - x3ec_damageLightPulser = zeus::clamp(0.f, g_tweakGui->GetHudDamageColorGain() * x3ec_damageLightPulser * std::min(0.5f, player.GetDamageAmount()), 1.f); - zeus::CColor damageAmbColor = g_tweakGuiColors->GetHudFrameColor(); - damageAmbColor *= damageAmbColor.a(); - damageAmbColor += zeus::CColor(x3ec_damageLightPulser); - damageAmbColor.a() = 1.f; - - if (x3d4_damageLight) - x3d4_damageLight->SetAmbientLightColor(damageAmbColor); - - if (x3f4_damageFilterAmt > 0.f) - { - x3f4_damageFilterAmt = std::max(0.f, x3f4_damageFilterAmt - dt); - if (x3f4_damageFilterAmt == 0.f) - { - CSfxManager::RemoveEmitter(x3a4_damageSfx); - x3a4_damageSfx.reset(); - } - } - - float tmp = x3f0_damageFilterAmtInit * g_tweakGui->GetHudDamagePeakFactor(); - float colorGain; - if (x3f4_damageFilterAmt > tmp) - colorGain = (x3f0_damageFilterAmtInit - x3f4_damageFilterAmt) / (x3f0_damageFilterAmtInit - tmp); - else - colorGain = x3f4_damageFilterAmt / tmp; - - colorGain = zeus::clamp(0.f, colorGain * x3f8_damageFilterAmtGain, 1.f); - zeus::CColor color0 = g_tweakGuiColors->GetDamageAmbientColor(); - color0.a() *= colorGain; - - zeus::CColor color1 = g_tweakGuiColors->GetDamageAmbientPulseColor(); - color1.a() *= x3ec_damageLightPulser; - zeus::CColor color2 = color0 + color1; - - if (color2.a()) - { - if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed) - color2.a() *= 0.75f; - x3a8_camFilter.SetFilter(EFilterType::Add, EFilterShape::Fullscreen, - 0.f, color2, -1); - } - else - { - x3a8_camFilter.DisableFilter(0.f); - } - - if (x3a4_damageSfx) - CSfxManager::UpdateEmitter(x3a4_damageSfx, player.GetTranslation(), player.GetTransform().basis[1], 1.f); - - if (x400_hudDamagePracticals > 0.f) - { - x400_hudDamagePracticals = std::max(0.f, x400_hudDamagePracticals - dt); - float practicals = x400_hudDamagePracticals / x3fc_hudDamagePracticalsInit; - if (x28c_energyIntf) - x28c_energyIntf->SetFlashMagnitude(practicals); - practicals = std::min(practicals * x404_hudDamagePracticalsGain, 1.f); - x2a0_helmetIntf->AddHelmetLightValue(practicals); - if (x29c_decoIntf) - x29c_decoIntf->SetFrameColorValue(practicals); - if (practicals > 0.f) - { - x3d4_damageLight->SetColor(g_tweakGuiColors->GetHudDamageLightColor() * zeus::CColor(practicals)); - x3d4_damageLight->SetIsVisible(true); - } - else - { - x3d4_damageLight->SetIsVisible(false); - } - } - - bool transformUpdate = false; - if (x414_decoShakeTranslateAmt > 0.f) - { - x418_decoShakeTranslateAmtVel -= g_tweakGui->GetDecoDamageShakeDeceleration() * 60.f * dt; - x414_decoShakeTranslateAmt = std::max(0.f, x414_decoShakeTranslateAmt + x418_decoShakeTranslateAmtVel); - transformUpdate = true; - } - if (x460_decoShakeAmt > 0.f) - { - x460_decoShakeAmt = std::max(0.f, x460_decoShakeAmt - dt); - x44c_hudLagShakeRot = zeus::CQuaternion::skNoRotation; - float rotMul = std::min(g_tweakGui->GetMaxDecoDamageShakeRotate(), - x460_decoShakeAmt / x45c_decoShakeAmtInit * x464_decoShakeAmtGain); - float rotAng = rotMul * (2.f * M_PIF / 10.f); - x44c_hudLagShakeRot.rotateX(rand() / float(RAND_MAX) * rotAng); - x44c_hudLagShakeRot.rotateZ(rand() / float(RAND_MAX) * rotAng); - zeus::CVector3f vecs[] = {zeus::CVector3f::skRight, - zeus::CVector3f::skForward, - zeus::CVector3f::skUp}; - for (int i=0 ; i<4 ; ++i) - { - int sel = int(rand() / float(RAND_MAX) * 9.f); - vecs[sel & 0x3][(sel / 3) & 0x3] += (rand() / float(RAND_MAX) - dt) * rotMul; - } - x428_decoShakeRotate = zeus::CMatrix3f(vecs[0], vecs[1], vecs[2]).transposed(); - transformUpdate = true; - } - - if (transformUpdate) - { - x41c_decoShakeTranslate = x408_damagerToPlayerNorm * std::min(g_tweakGui->GetMaxDecoDamageShakeTranslate(), - x414_decoShakeTranslateAmt); - if (x29c_decoIntf) - x29c_decoIntf->SetDamageTransform(x428_decoShakeRotate, x41c_decoShakeTranslate * - g_tweakGui->GetHudDecoShakeTranslateGain()); - } -} - -void CSamusHud::UpdateStaticSfx(CSfxHandle& handle, float& cycleTimer, u16 sfxId, float dt, - float oldStaticInterp, float staticThreshold) -{ - if ((oldStaticInterp > staticThreshold && x510_staticInterp <= staticThreshold) || - (oldStaticInterp <= staticThreshold && x510_staticInterp > staticThreshold)) - { - cycleTimer = 0.f; - } - else - { - if (cycleTimer < 0.1f) - cycleTimer = std::min(cycleTimer + dt, 0.1f); - if (cycleTimer == 0.1f) - { - if (x510_staticInterp > staticThreshold) - { - if (!handle) - handle = CSfxManager::SfxStart(sfxId, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); - } - else - { - CSfxManager::SfxStop(handle); - handle.reset(); - } - } - } -} - -void CSamusHud::UpdateStaticInterference(float dt, const CStateManager& mgr) -{ - float intf = mgr.GetPlayerState()->GetStaticInterference().GetTotalInterference(); - float oldStaticInterp = x510_staticInterp; - if (x510_staticInterp < intf) - x510_staticInterp = std::min(x510_staticInterp + dt, intf); - else - x510_staticInterp = std::max(intf, x510_staticInterp - dt); - - UpdateStaticSfx(x508_staticSfxHi, x514_staticCycleTimerHi, SFXui_static_hi, dt, oldStaticInterp, 0.1f); - UpdateStaticSfx(x50c_staticSfxLo, x518_staticCycleTimerLo, SFXui_static_lo, dt, oldStaticInterp, 0.5f); - - if (x510_staticInterp > 0.f) - { - zeus::CColor color = zeus::CColor::skWhite; - color.a() = x510_staticInterp; - x51c_camFilter2.SetFilter(EFilterType::Blend, - EFilterShape::RandomStatic, 0.f, color, -1); - } - else - { - x51c_camFilter2.DisableFilter(0.f); - } -} - -int CSamusHud::GetRelativeDirection(const zeus::CVector3f& position, const CStateManager& mgr) -{ - TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - if (!fpCam) - return 0; - zeus::CVector3f camToPosLocal = fpCam->GetTransform().transposeRotate(position - fpCam->GetTranslation()); - if (camToPosLocal == position) - return 0; - float y = std::cos(2.f * M_PIF * 0.0027777778f * 0.5f * fpCam->GetFov()); - float x = std::cos(2.f * M_PIF * 0.0027777778f * 0.5f * fpCam->GetFov() * fpCam->GetAspectRatio()); - zeus::CVector2f camToPosXY = zeus::CVector2f(camToPosLocal.x(), camToPosLocal.y()).normalized(); - zeus::CVector2f camToPosYZ = zeus::CVector2f(camToPosLocal.y(), camToPosLocal.z()).normalized(); - if (camToPosXY.dot(zeus::CVector2f(0.f, 1.f)) > x && camToPosYZ.dot(zeus::CVector2f(1.f, 0.f)) > y) - return 0; - if (camToPosXY.dot(zeus::CVector2f(0.f, -1.f)) > x && camToPosYZ.dot(zeus::CVector2f(-1.f, 0.f)) > y) - return 1; - zeus::CVector3f camToPosNorm = camToPosLocal.normalized(); - zeus::CQuaternion quat; - quat.rotateY(2.f * M_PIF / 8.f); - zeus::CVector3f vec = zeus::CVector3f::skUp; - float maxDot = -1.f; - int ret = -1; - for (int i=0 ; i<8 ; ++i) - { - float dot = camToPosNorm.dot(vec); - if (dot > maxDot) - { - maxDot = dot; - ret = i + 2; - } - vec = quat.transform(vec); - } - return ret; -} - -void CSamusHud::ShowDamage(const zeus::CVector3f& position, float dam, float prevDam, - const CStateManager& mgr) -{ - CPlayer& player = mgr.GetPlayer(); - int dir = GetRelativeDirection(position, mgr); - TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - x404_hudDamagePracticalsGain = g_tweakGui->GetHudDamagePracticalsGainLinear() * dam + - g_tweakGui->GetHudDamagePracticalsGainConstant(); - x3fc_hudDamagePracticalsInit = std::max(FLT_EPSILON, g_tweakGui->GetHudDamagePracticalsInitLinear() * dam + - g_tweakGui->GetHudDamagePracticalsInitConstant()); - x400_hudDamagePracticals = x3fc_hudDamagePracticalsInit; - if (x3d4_damageLight) - x3d4_damageLight->SetLocalTransform(x3d8_lightTransforms[dir]); - x3f8_damageFilterAmtGain = g_tweakGui->GetHudDamageFilterGainLinear() * dam + - g_tweakGui->GetHudDamageFilterGainConstant(); - x3f0_damageFilterAmtInit = g_tweakGui->GetHudDamageFilterInitLinear() * dam + - g_tweakGui->GetHudDamageFilterInitConstant(); - x3f4_damageFilterAmt = x3f0_damageFilterAmtInit; - if (!x3a4_damageSfx) - { - x3a4_damageSfx = CSfxManager::AddEmitter(SFXui_damage_lp, player.GetTranslation(), player.GetTransform().basis[1], - 0.f, false, true, 0xff, kInvalidAreaId); - } - if (fpCam) - { - x418_decoShakeTranslateAmtVel = g_tweakGui->GetHudDecoShakeTranslateVelLinear() * prevDam + - g_tweakGui->GetHudDecoShakeTranslateVelConstant(); - x414_decoShakeTranslateAmt = x418_decoShakeTranslateAmtVel; - x408_damagerToPlayerNorm = -(fpCam->GetTransform().inverse() * position).normalized(); - x464_decoShakeAmtGain = g_tweakGui->GetDecoShakeGainLinear() * prevDam + - g_tweakGui->GetDecoShakeGainConstant(); - x45c_decoShakeAmtInit = g_tweakGui->GetDecoShakeInitLinear() * prevDam + - g_tweakGui->GetDecoShakeInitConstant(); - x460_decoShakeAmt = x45c_decoShakeAmtInit; - } -} - -void CSamusHud::EnterFirstPerson(const CStateManager& mgr) -{ - CSfxManager::SfxVolume(x508_staticSfxHi, 1.f); - CSfxManager::SfxVolume(x50c_staticSfxLo, 1.f); -} - -void CSamusHud::LeaveFirstPerson(const CStateManager& mgr) -{ - CSfxManager::SfxVolume(x508_staticSfxHi, 0.f); - CSfxManager::SfxVolume(x50c_staticSfxLo, 0.f); -} - -EHudState CSamusHud::GetDesiredHudState(const CStateManager& mgr) -{ - if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed || - mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphing || - mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphing) - return EHudState::Ball; - - switch (mgr.GetPlayerState()->GetTransitioningVisor()) - { - case CPlayerState::EPlayerVisor::Combat: - return EHudState::Combat; - case CPlayerState::EPlayerVisor::XRay: - return EHudState::XRay; - case CPlayerState::EPlayerVisor::Scan: - return EHudState::Scan; - case CPlayerState::EPlayerVisor::Thermal: - return EHudState::Thermal; - default: - return EHudState::None; - } -} - -void CSamusHud::Update(float dt, const CStateManager& mgr, - CInGameGuiManager::EHelmetVisMode helmetVis, - bool hudVis, bool targetingManager) -{ - CPlayer& player = mgr.GetPlayer(); - UpdateStateTransition(dt, mgr); - bool firstPerson = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && - !mgr.GetCameraManager()->IsInCinematicCamera(); - if (firstPerson != x2e0_26_latestFirstPerson) - { - if (firstPerson) - EnterFirstPerson(mgr); - else - LeaveFirstPerson(mgr); - x2e0_26_latestFirstPerson = firstPerson; - } - - float morphT = 0.f; - switch (player.GetMorphballTransitionState()) - { - case CPlayer::EPlayerMorphBallState::Morphed: - morphT = 1.f; - break; - case CPlayer::EPlayerMorphBallState::Morphing: - morphT = player.GetMorphFactor(); - break; - case CPlayer::EPlayerMorphBallState::Unmorphing: - morphT = 1.f - player.GetMorphFactor(); - break; - default: break; - } - - float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); - float scaleMul = 1.f - zeus::clamp(0.f, (aspect - 1.33f) / (1.77f - 1.33f), 1.f); - x500_viewportScale.y() = 1.f - scaleMul * morphT * g_tweakGui->GetBallViewportYReduction() * 1.2f; - if (x2b0_ballIntf) - x2b0_ballIntf->SetBallModeFactor(morphT); - - bool helmetVisible = false; - bool glowVisible = false; - bool decoVisible = false; - if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) - { - switch (helmetVis) - { - case CInGameGuiManager::EHelmetVisMode::HelmetOnly: - helmetVisible = true; - break; - case CInGameGuiManager::EHelmetVisMode::GlowHelmetDeco: - glowVisible = true; - case CInGameGuiManager::EHelmetVisMode::HelmetDeco: - helmetVisible = true; - case CInGameGuiManager::EHelmetVisMode::Deco: - decoVisible = true; - default: break; - } - } - - if (x29c_decoIntf) - x29c_decoIntf->SetIsVisibleDebug(decoVisible); - if (x2a0_helmetIntf) - x2a0_helmetIntf->SetIsVisibleDebug(helmetVisible, glowVisible); - - x590_base_Model_AutoMapper->SetIsVisible(false); - - UpdateEnergyLow(dt, mgr); - - for (int i=0 ; i<15 ; ++i) - { - x7ac_[i].x0_ = 0; - x7ac_[i].x4_ = 0; - } - - if (x2ac_radarIntf) - x2ac_radarIntf->Update(dt, mgr); - - UpdateHudLag(dt, mgr); - - UpdateHudDynamicLights(dt, mgr); - - if (targetingManager) - x8_targetingMgr.Update(dt, mgr); - - UpdateHudDamage(dt, mgr, helmetVis); - - UpdateStaticInterference(dt, mgr); - - if (helmetVis != DataSpec::ITweakGui::EHelmetVisMode::ReducedUpdate) - { - if (x2bc_nextState != EHudState::None) - { - UpdateEnergy(dt, mgr, false); - UpdateFreeLook(dt, mgr); - } - - if (x2bc_nextState == EHudState::Ball) - { - UpdateBallMode(mgr, false); - } - else if (x2bc_nextState >= EHudState::Combat && x2bc_nextState <= EHudState::Scan) - { - UpdateThreatAssessment(dt, mgr); - UpdateMissile(dt, mgr, false); - UpdateVideoBands(dt, mgr); - } - - UpdateVisorAndBeamMenus(dt, mgr); - - if (player.WasDamaged() && mgr.GetGameState() == CStateManager::EGameState::Running) - ShowDamage(player.GetDamageLocationWR(), player.GetDamageAmount(), player.GetPrevDamageAmount(), mgr); - } - - float oldAPulse = x584_abuttonPulse; - if (!x554_hudMemoIdx) - { - x584_abuttonPulse += 2.f * dt; - if (x584_abuttonPulse > 1.f) - x584_abuttonPulse -= 2.f; - } - - zeus::CColor abuttonColor = zeus::CColor::skWhite; - abuttonColor.a() = std::fabs(x584_abuttonPulse); - x5a0_base_model_abutton->SetColor(abuttonColor); - - if (!mgr.GetCameraManager()->IsInCinematicCamera() && oldAPulse < 0.f && x584_abuttonPulse >= 0.f && - x598_base_basewidget_message->GetIsVisible() && (x558_messageTextTime == 0.f || x558_messageTextTime >= 1.f)) - { - CSfxManager::SfxStart(SFXui_hud_memo_a_pulse, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - - float allTextAlpha; - if (x29c_decoIntf) - allTextAlpha = x29c_decoIntf->GetHudTextAlpha(); - else - allTextAlpha = 1.f; - - float messageTextAlpha = 1.f; - if (x558_messageTextTime > 0.f) - messageTextAlpha = std::min(x558_messageTextTime, 1.f); - else if (!x59c_base_textpane_message->GetIsVisible() && !x598_base_basewidget_message->GetIsVisible()) - messageTextAlpha = 0.f; - - if (x2b4_bossEnergyIntf) - x2b4_bossEnergyIntf->SetAlpha(1.f - messageTextAlpha); - - if (x550_hudMemoString && x550_hudMemoString.IsLoaded()) - { - SetMessage(x550_hudMemoString->GetString(x554_hudMemoIdx), x548_hudMemoParms); - x550_hudMemoString = TLockedToken(); - } - - if (x558_messageTextTime > 0.f) - { - x558_messageTextTime = std::max(0.f, x558_messageTextTime - dt); - if (x558_messageTextTime == 0.f) - { - x59c_base_textpane_message->TextSupport().SetTypeWriteEffectOptions(false, 0.f, 1.f); - x598_base_basewidget_message->SetVisibility(false, ETraversalMode::Children); - } - } - - CGuiWidget* messageWidget; - if (x598_base_basewidget_message->GetIsVisible()) - messageWidget = x598_base_basewidget_message; - else - messageWidget = x59c_base_textpane_message; - - zeus::CColor messageColor = zeus::CColor::skWhite; - float textScale = 1.f; - messageColor.a() = std::min(allTextAlpha, messageTextAlpha); - messageWidget->SetColor(messageColor); - - if (messageWidget == x598_base_basewidget_message) - { - if (x558_messageTextTime > 0.f) - x560_messageTextScale = std::min(x558_messageTextTime, 1.f); - else - x560_messageTextScale = std::min(x560_messageTextScale + dt, 1.f); - - float textScaleT = std::max(0.f, (x560_messageTextScale - 0.75f) / 0.25f); - if (textScaleT != 1.f) - { - if (textScaleT < 0.7f) - textScale = textScaleT / 0.7f; - else if (textScaleT < 0.85f) - textScale = 0.1f * (1.f - (textScaleT - 0.7f) / 0.15f) + 0.9f; - else - textScale = 0.1f * ((textScaleT - 0.7f) - 0.15f) / 0.3f + 0.9f; - } - - x598_base_basewidget_message->SetLocalTransform(x598_base_basewidget_message->GetTransform() * - zeus::CTransform::Scale(textScale, 1.f, 1.f)); - } - - float nextSfxChars = x55c_lastSfxChars + g_tweakGui->GetWorldTransManagerCharsPerSfx(); - if (x59c_base_textpane_message->TextSupport().GetNumCharsPrinted() >= nextSfxChars) - { - x55c_lastSfxChars = nextSfxChars; - if (!x598_base_basewidget_message->GetIsVisible() || textScale == 1.f) - CSfxManager::SfxStart(SFXui_hud_memo_type, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - - if (mgr.GetEscapeSequenceTimer() > 0.f) - { - int minutes = mgr.GetEscapeSequenceTimer() / 60.f; - int seconds = std::fmod(mgr.GetEscapeSequenceTimer(), 60.f); - int hundredths = std::fmod(mgr.GetEscapeSequenceTimer() * 100.f, 100.f); - std::string timeStr = hecl::Format("%02d:%02d:%02d", - int(minutes), int(seconds), int(hundredths)); - x594_base_textpane_counter->TextSupport().SetText(timeStr); - x594_base_textpane_counter->SetIsVisible(true); - - zeus::CColor counterColor = zeus::CColor::skWhite; - counterColor.a() = zeus::clamp(0.f, std::min(1.f - std::min(x558_messageTextTime, 1.f), allTextAlpha), 1.f); - x594_base_textpane_counter->SetColor(counterColor); - } - else - { - x594_base_textpane_counter->SetIsVisible(false); - } - - x274_loadedFrmeBaseHud->Update(dt); - if (x288_loadedSelectedHud) - x288_loadedSelectedHud->Update(dt); - if (x2b4_bossEnergyIntf) - x2b4_bossEnergyIntf->Update(dt); - if (x28c_energyIntf) - x28c_energyIntf->Update(dt, x580_energyLowPulse); - if (x290_threatIntf) - x290_threatIntf->Update(dt); - if (x294_missileIntf) - x294_missileIntf->Update(dt, mgr); if (x298_freeLookIntf) - x298_freeLookIntf->Update(dt); - if (x2a0_helmetIntf) - x2a0_helmetIntf->Update(dt); + x298_freeLookIntf->SetFreeLookState(inFreeLook, lookControlHeld, player.GetOrbitTargetId() != kInvalidUniqueId, + offHorizonAngle); - if (player.GetScanningState() == CPlayer::EPlayerScanState::NotScanning) - x2f0_visorBeamMenuAlpha = std::min(x2f0_visorBeamMenuAlpha + 2.f * dt, 1.f); - else - x2f0_visorBeamMenuAlpha = std::max(0.f, x2f0_visorBeamMenuAlpha - 2.f * dt); - - CPlayerState::EPlayerVisor curVisor = mgr.GetPlayerState()->GetCurrentVisor(); - CPlayerState::EPlayerVisor transVisor = mgr.GetPlayerState()->GetTransitioningVisor(); - float transFactor = 0.f; - if (curVisor != CPlayerState::EPlayerVisor::Scan) - { - if (transVisor == CPlayerState::EPlayerVisor::Scan) - transFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); - else - transFactor = 1.f; + if (x564_freeLookSfx) { + float pitch = offHorizonAngle * (g_tweakGui->GetFreeLookSfxPitchScale() / 8192.f) / (M_PIF / 2.f); + if (!g_tweakGui->GetNoAbsoluteFreeLookSfxPitch()) + pitch = std::fabs(pitch); + CSfxManager::PitchBend(x564_freeLookSfx, pitch); } - - if (x2a4_visorMenu) - { - float hudAlpha; - if (g_GameState->GameOptions().GetSwapBeamControls()) - hudAlpha = transFactor; - else - hudAlpha = x2f0_visorBeamMenuAlpha; - x2a4_visorMenu->UpdateHudAlpha(hudAlpha); - x2a4_visorMenu->Update(dt, false); - } - - if (x2a8_beamMenu) - { - float hudAlpha; - if (g_GameState->GameOptions().GetSwapBeamControls()) - hudAlpha = x2f0_visorBeamMenuAlpha; - else - hudAlpha = transFactor; - x2a8_beamMenu->UpdateHudAlpha(hudAlpha); - x2a8_beamMenu->Update(dt, false); - } - - UpdateCameraDebugSettings(); - - if (x29c_decoIntf) - x29c_decoIntf->Update(dt, mgr); + } } -void CSamusHud::DrawAttachedEnemyEffect(const CStateManager& mgr) const -{ - float drainTime = mgr.GetPlayer().GetEnergyDrain().GetEnergyDrainTime(); - if (drainTime <= 0.f) - return; +void CSamusHud::UpdateMissile(float dt, const CStateManager& mgr, bool init) { + CPlayerGun& gun = *mgr.GetPlayer().GetPlayerGun(); + CPlayerState& playerState = *mgr.GetPlayerState(); - float modPeriod = g_tweakGui->GetEnergyDrainModPeriod(); - float alpha; - if (g_tweakGui->GetEnergyDrainSinusoidalPulse()) - { - alpha = (std::sin(-0.25f * modPeriod + 2.f * M_PIF * drainTime / modPeriod) + 1.f) * 0.5f; - } - else - { - float halfModPeriod = 0.5f * modPeriod; - float tmp = std::fabs(std::fmod(drainTime, modPeriod)); - if (tmp < halfModPeriod) - alpha = tmp / halfModPeriod; - else - alpha = (modPeriod - tmp) / halfModPeriod; - } + u32 numMissles = playerState.GetItemAmount(CPlayerState::EItemType::Missiles); + u32 missileCap = playerState.GetItemCapacity(CPlayerState::EItemType::Missiles); + CPlayerGun::EMissleMode missileMode = gun.GetMissleMode(); + float chargeFactor = gun.IsCharging() ? gun.GetChargeBeamFactor() : 0.f; - zeus::CColor filterColor = g_tweakGuiColors->GetEnergyDrainFilterColor(); - filterColor.a() *= alpha; - const_cast(m_energyDrainFilter).draw(filterColor); + if (x294_missileIntf) + x294_missileIntf->SetChargeBeamFactor(chargeFactor); + + if (init || numMissles != x2d8_missileAmount || missileMode != x2ec_missileMode || + missileCap != x2dc_missileCapacity) { + if (x294_missileIntf) { + if (missileCap != x2dc_missileCapacity) + x294_missileIntf->SetMissileCapacity(missileCap); + if (numMissles != x2d8_missileAmount) + x294_missileIntf->SetNumMissiles(numMissles, mgr); + if (missileMode != x2ec_missileMode) + x294_missileIntf->SetIsMissilesActive(missileMode == CPlayerGun::EMissleMode::Active); + } + x2d8_missileAmount = numMissles; + x2ec_missileMode = missileMode; + x2dc_missileCapacity = missileCap; + } } -void CSamusHud::Draw(const CStateManager& mgr, float alpha, - CInGameGuiManager::EHelmetVisMode helmetVis, - bool hudVis, bool targetingManager) const -{ - if (x2bc_nextState == EHudState::None) - return; - if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) - { - DrawAttachedEnemyEffect(mgr); - x51c_camFilter2.Draw(); - if (targetingManager) - x8_targetingMgr.Draw(mgr, false); - } - - if (helmetVis != CInGameGuiManager::EHelmetVisMode::ReducedUpdate && - helmetVis < CInGameGuiManager::EHelmetVisMode::HelmetOnly) - { - if (alpha < 1.f) - const_cast(m_cookieCutterStatic). - draw(zeus::CColor::skWhite, 1.f - alpha); - - if (x288_loadedSelectedHud) - { - if (mgr.GetPlayer().GetDeathTime() > 0.f) - { - if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed) - { - CGuiWidgetDrawParms parms( - x2c8_transT * zeus::clamp(0.f, 1.f - mgr.GetPlayer().GetDeathTime() / 6.f, 1.f), - zeus::CVector3f::skZero); - x288_loadedSelectedHud->Draw(parms); - } - else - { - CGuiWidgetDrawParms parms(x2c8_transT, zeus::CVector3f::skZero); - x288_loadedSelectedHud->Draw(parms); - } - } - else - { - CGuiWidgetDrawParms parms(x2c8_transT, zeus::CVector3f::skZero); - x288_loadedSelectedHud->Draw(parms); - } - } - - if (x274_loadedFrmeBaseHud) - x274_loadedFrmeBaseHud->Draw(CGuiWidgetDrawParms::Default); - } - - if (x29c_decoIntf && !x2cc_preLoadCountdown) - x29c_decoIntf->Draw(); - - if (x2bc_nextState >= EHudState::Combat && x2bc_nextState <= EHudState::Scan) - { - if (hudVis && - helmetVis != CInGameGuiManager::EHelmetVisMode::ReducedUpdate && - helmetVis < CInGameGuiManager::EHelmetVisMode::HelmetOnly) - { - float t; - if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat) - t = mgr.GetPlayerState()->GetVisorTransitionFactor(); - else - t = 0.f; - x2ac_radarIntf->Draw(mgr, t * alpha); - } - // Depth read/write enable - } +void CSamusHud::UpdateVideoBands(float dt, const CStateManager& mgr) { + for (int i = 0; i < 4; ++i) + if (x5a4_videoBands[i].x0_videoband) + x5a4_videoBands[i].x0_videoband->SetIsVisible(false); } -void CSamusHud::DrawHelmet(const CStateManager& mgr, float camYOff) const -{ - if (!x264_loadedFrmeHelmet || - mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed || - x2bc_nextState == EHudState::Ball) - return; +void CSamusHud::UpdateBallMode(const CStateManager& mgr, bool init) { + if (!x2b0_ballIntf) + return; - float t; - if (x2c4_activeTransState == ETransitionState::Transitioning && x2b8_curState == EHudState::Ball) - t = x2c8_transT; - else - t = 1.f; + CPlayer& player = mgr.GetPlayer(); + CPlayerGun& gun = *player.GetPlayerGun(); + CPlayerState& playerState = *mgr.GetPlayerState(); + u32 numPbs = playerState.GetItemAmount(CPlayerState::EItemType::PowerBombs); + u32 pbCap = playerState.GetItemCapacity(CPlayerState::EItemType::PowerBombs); + u32 bombCount = gun.IsBombReady() ? gun.GetBombCount() : 0; + bool hasBombs = playerState.HasPowerUp(CPlayerState::EItemType::MorphBallBombs); + bool pbReady = + gun.IsPowerBombReady() && player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed; - x264_loadedFrmeHelmet->Draw(CGuiWidgetDrawParms(t, zeus::CVector3f(0.f, 15.f * camYOff, 0.f))); + x2b0_ballIntf->SetBombParams(numPbs, pbCap, bombCount, hasBombs, pbReady, false); } -void CSamusHud::ProcessControllerInput(const CFinalInput& input) -{ - if (x29c_decoIntf) - x29c_decoIntf->ProcessInput(input); +void CSamusHud::UpdateThreatAssessment(float dt, const CStateManager& mgr) { + CMaterialFilter filter(CMaterialList(EMaterialTypes::Trigger), CMaterialList(), + CMaterialFilter::EFilterType::Include); + + CPlayer& player = mgr.GetPlayer(); + zeus::CAABox playerAABB = zeus::CAABox::skNullBox; + if (std::experimental::optional aabb = player.GetTouchBounds()) + playerAABB = *aabb; + + zeus::CAABox aabb; + aabb.accumulateBounds(player.GetTranslation() - g_tweakGui->GetThreatRange()); + aabb.accumulateBounds(player.GetTranslation() + g_tweakGui->GetThreatRange()); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, aabb, filter, nullptr); + + float threatDist = 9999.f; + for (TUniqueId id : nearList) { + const CEntity* ent = mgr.GetObjectById(id); + if (TCastToConstPtr trigger = ent) { + if (!bool(trigger->GetTriggerFlags() & ETriggerFlags::DetectPlayer)) + continue; + if (trigger->GetDamageInfo().GetDamage() == 0.f) + continue; + if (std::experimental::optional aabb = trigger->GetTouchBounds()) { + float dist = playerAABB.distanceBetween(*aabb); + if (dist < threatDist) + threatDist = dist; + } + } + } + + if (player.GetThreatOverride() > 0.f) + threatDist = std::min((1.f - player.GetThreatOverride()) * g_tweakGui->GetThreatRange(), threatDist); + + if (mgr.IsFullThreat()) + threatDist = 0.f; + if (x290_threatIntf) + x290_threatIntf->SetThreatDistance(threatDist); } -void CSamusHud::UpdateStateTransition(float dt, const CStateManager& mgr) -{ - if (x2cc_preLoadCountdown == 0) - { - EHudState desiredState = GetDesiredHudState(mgr); - if (desiredState != x2c0_setState) - { - x2c0_setState = desiredState; - if (desiredState == EHudState::Ball || x2bc_nextState == EHudState::Ball) - x2c8_transT = FLT_EPSILON; - x2c4_activeTransState = ETransitionState::Countdown; - } +void CSamusHud::UpdateVisorAndBeamMenus(float dt, const CStateManager& mgr) { + CPlayer& player = mgr.GetPlayer(); + CPlayerGun& gun = *player.GetPlayerGun(); + CPlayerState& playerState = *mgr.GetPlayerState(); + + float beamInterp = zeus::clamp(0.f, gun.GetHoloTransitionFactor(), 1.f); + float visorInterp = playerState.GetVisorTransitionFactor(); + + if (x2a8_beamMenu) { + x2a8_beamMenu->SetSelection(int(gun.GetCurrentBeam()), int(gun.GetNextBeam()), beamInterp); + x2a8_beamMenu->SetPlayerHas(BuildPlayerHasBeams(mgr)); + } + + if (x2a4_visorMenu) { + x2a4_visorMenu->SetSelection(int(playerState.GetCurrentVisor()), int(playerState.GetTransitioningVisor()), + visorInterp); + x2a4_visorMenu->SetPlayerHas(BuildPlayerHasVisors(mgr)); + } +} + +void CSamusHud::UpdateCameraDebugSettings() { + float fov = x5ec_camFovTweaks[g_tweakGui->GetHudCamFovTweak()]; + float y = x62c_camYTweaks[g_tweakGui->GetHudCamYTweak()]; + float z = x72c_camZTweaks[g_tweakGui->GetHudCamZTweak()]; + if (x2a0_helmetIntf) + x2a0_helmetIntf->UpdateCameraDebugSettings(fov, y, z); + if (x29c_decoIntf) + x29c_decoIntf->UpdateCameraDebugSettings(fov, y, z); + x274_loadedFrmeBaseHud->GetFrameCamera()->SetFov(fov); + x310_cameraPos.y() = y; + x310_cameraPos.z() = z; +} + +void CSamusHud::UpdateEnergyLow(float dt, const CStateManager& mgr) { + bool cineCam = TCastToConstPtr(mgr.GetCameraManager()->GetCurrentCamera(mgr)); + float oldTimer = x57c_energyLowTimer; + + x57c_energyLowTimer = std::fmod(x57c_energyLowTimer + dt, 0.5f); + if (x57c_energyLowTimer < 0.25f) + x580_energyLowPulse = x57c_energyLowTimer / 0.25f; + else + x580_energyLowPulse = (0.5f - x57c_energyLowTimer) / 0.25f; + + if (!cineCam && x2e0_27_energyLow && x57c_energyLowTimer < oldTimer) + CSfxManager::SfxStart(SFXui_energy_low, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); +} + +void CSamusHud::ApplyClassicLag(const zeus::CUnitVector3f& lookDir, zeus::CQuaternion& rot, const CStateManager& mgr, + float dt, bool invert) { + zeus::CQuaternion lookRot = zeus::CQuaternion::lookAt(lookDir, zeus::CVector3f::skForward, 2.f * M_PIF); + zeus::CQuaternion lookRot2; + if (invert) { + zeus::CUnitVector3f v1(lookRot.transform(x2f8_fpCamDir)); + lookRot2 = zeus::CQuaternion::lookAt(v1, zeus::CVector3f::skForward, 2.f * M_PIF); + } else { + zeus::CUnitVector3f v1(lookRot.transform(x2f8_fpCamDir)); + lookRot2 = zeus::CQuaternion::lookAt(zeus::CVector3f::skForward, v1, 2.f * M_PIF); + } + + zeus::CQuaternion doubleRot = lookRot2 * lookRot2; + float dot = doubleRot.toTransform().basis[1].dot(rot.toTransform().basis[1]); + if (std::fabs(dot) > 1.f) + dot = (dot >= 0.f) ? 1.f : -1.f; + + float angle = std::acos(dot); + float tmp = 0.f; + if (angle > 0.f) + tmp = 0.5f * dt * g_tweakPlayer->GetFreeLookSpeed() / angle; + + float t = zeus::clamp(0.f, 18.f * dt * tmp, 1.f); + rot = zeus::CQuaternion::slerp(rot, doubleRot, t); +} + +void CSamusHud::UpdateHudLag(float dt, const CStateManager& mgr) { + CPlayer& player = mgr.GetPlayer(); + + if (x29c_decoIntf) + x29c_decoIntf->SetDecoRotation(player.GetYaw()); + + if (!g_GameState->GameOptions().GetHUDLag()) { + if (x2a0_helmetIntf) { + x2a0_helmetIntf->SetHudLagRotation(zeus::CMatrix3f::skIdentityMatrix3f); + x2a0_helmetIntf->SetHudLagOffset(zeus::CVector3f::skZero); + } + if (x29c_decoIntf) { + x29c_decoIntf->SetReticuleTransform(zeus::CMatrix3f::skIdentityMatrix3f); + x29c_decoIntf->SetHudRotation(zeus::CQuaternion::skNoRotation); + x29c_decoIntf->SetHudOffset(zeus::CVector3f::skZero); + } + x588_base_basewidget_pivot->SetTransform( + zeus::CTransform::Translate(x588_base_basewidget_pivot->GetWorldPosition())); + x274_loadedFrmeBaseHud->GetFrameCamera()->SetO2WTransform( + BuildFinalCameraTransform(zeus::CQuaternion::skNoRotation, x304_basewidgetIdlePos, x310_cameraPos)); + x8_targetingMgr.CompoundTargetReticle().SetLeadingOrientation(zeus::CQuaternion::skNoRotation); + } else { + zeus::CVector3f fpCamDir = x2f8_fpCamDir; + if (TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr)) + fpCamDir = fpCam->GetTransform().buildMatrix3f()[1]; + + ApplyClassicLag(fpCamDir, x31c_hudLag, mgr, dt, false); + ApplyClassicLag(fpCamDir, x32c_invHudLag, mgr, dt, true); + + zeus::CQuaternion rot = zeus::CQuaternion::lookAt(zeus::CUnitVector3f(x2f8_fpCamDir), fpCamDir, 2.f * M_PIF); + rot *= rot; + rot *= rot; + x8_targetingMgr.CompoundTargetReticle().SetLeadingOrientation(rot); + + zeus::CVector3f bobTranslation = player.GetCameraBob()->GetHelmetBobTranslation(); + + zeus::CQuaternion lagRot = x44c_hudLagShakeRot * x31c_hudLag; + zeus::CVector3f lagOff = x41c_decoShakeTranslate * g_tweakGui->GetHudLagOffsetScale(); + lagOff.z() += bobTranslation.z(); + if (x2a0_helmetIntf) { + x2a0_helmetIntf->SetHudLagRotation(lagRot); + x2a0_helmetIntf->SetHudLagOffset(lagOff); + } + if (x29c_decoIntf) { + x29c_decoIntf->SetReticuleTransform(x32c_invHudLag); + x29c_decoIntf->SetHudRotation(lagRot); + x29c_decoIntf->SetHudOffset(lagOff); } - switch (x2c4_activeTransState) - { - case ETransitionState::Countdown: - if (x2cc_preLoadCountdown == 0) - { - x2c8_transT = std::max(x2c8_transT - 5.f * dt, 0.f); - if (x2c8_transT == 0.f) - { - x2cc_preLoadCountdown = 2; - x288_loadedSelectedHud = nullptr; - } - } - else - { - x2cc_preLoadCountdown -= 1; - if (x2cc_preLoadCountdown == 0) - { - UninitializeFrameGlueMutable(); - x278_selectedHud = TLockedToken(); - switch (x2c0_setState) - { - case EHudState::Thermal: - x278_selectedHud = g_SimplePool->GetObj("FRME_ThermalHud"); - break; - case EHudState::Combat: - x278_selectedHud = g_SimplePool->GetObj("FRME_CombatHud"); - break; - case EHudState::Scan: - x278_selectedHud = g_SimplePool->GetObj("FRME_ScanHud"); - break; - case EHudState::XRay: - x278_selectedHud = g_SimplePool->GetObj("FRME_XRayHudNew"); - break; - case EHudState::Ball: - x278_selectedHud = g_SimplePool->GetObj("FRME_BallHud"); - break; - default: - break; - } - x2c4_activeTransState = ETransitionState::Loading; - } - } - if (x2c4_activeTransState != ETransitionState::Loading) - return; - case ETransitionState::Loading: - if (x278_selectedHud) - { - if (!x278_selectedHud.IsLoaded() || !x278_selectedHud->GetIsFinishedLoading()) - return; - x288_loadedSelectedHud = x278_selectedHud.GetObj(); - x288_loadedSelectedHud->SetMaxAspect(1.78f); - x2b8_curState = x2bc_nextState; - x2bc_nextState = x2c0_setState; - InitializeFrameGlueMutable(mgr); - x2c4_activeTransState = ETransitionState::Transitioning; - UpdateCameraDebugSettings(); - } - else - { - x2b8_curState = x2bc_nextState; - x2bc_nextState = x2c0_setState; - x2c4_activeTransState = ETransitionState::NotTransitioning; - } + x274_loadedFrmeBaseHud->GetFrameCamera()->SetO2WTransform( + BuildFinalCameraTransform(lagRot, x304_basewidgetIdlePos + lagOff, x310_cameraPos)); + x2f8_fpCamDir = fpCamDir; + } +} + +bool CSamusHud::IsCachedLightInAreaLights(const SCachedHudLight& light, const CActorLights& areaLights) const { + for (const CLight& l : areaLights.GetAreaLights()) { + if (l.GetColor() != light.xc_color || l.GetPosition() != light.x0_pos) + continue; + return true; + } + return false; +} + +bool CSamusHud::IsAreaLightInCachedLights(const CLight& light) const { + for (const SCachedHudLight& l : x340_hudLights) { + if (l.x1c_fader == 0.f) + continue; + if (l.xc_color != light.GetColor() || l.x0_pos != light.GetPosition()) + continue; + return true; + } + return false; +} + +int CSamusHud::FindEmptyHudLightSlot(const CLight& light) const { + for (int i = 0; i < 3; ++i) + if (x340_hudLights[i].x1c_fader == 0.f) + return i; + return -1; +} + +zeus::CColor CSamusHud::GetVisorHudLightColor(const zeus::CColor& color, const CStateManager& mgr) const { + zeus::CColor ret = color; + const CPlayerState& playerState = *mgr.GetPlayerState(); + float t = playerState.GetVisorTransitionFactor(); + switch (playerState.GetCurrentVisor()) { + case CPlayerState::EPlayerVisor::Scan: + ret *= zeus::CColor::lerp(zeus::CColor::skWhite, g_tweakGuiColors->GetScanVisorHudLightMultiply(), t); + break; + case CPlayerState::EPlayerVisor::Thermal: + ret *= g_tweakGuiColors->GetThermalVisorHudLightMultiply(); + break; + case CPlayerState::EPlayerVisor::XRay: + ret = zeus::CColor(zeus::CColor(0.3f, 0.6f, 0.1f).rgbDot(ret)); + break; + default: + break; + } + return ret; +} + +void CSamusHud::UpdateHudDynamicLights(float dt, const CStateManager& mgr) { + if (TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr)) { + zeus::CVector3f lookDir = fpCam->GetTransform().basis[1]; + zeus::CAABox camAABB(fpCam->GetTranslation() - 0.125f, fpCam->GetTranslation() + 0.125f); + TAreaId playerArea = mgr.GetPlayer().GetAreaIdAlways(); + if (playerArea == kInvalidAreaId) + return; + x33c_lights->BuildAreaLightList(mgr, *mgr.GetWorld()->GetAreaAlways(playerArea), camAABB); + for (SCachedHudLight& light : x340_hudLights) + if (light.x1c_fader > 0.f && ((light.x0_pos - fpCam->GetTranslation()).normalized().dot(lookDir) <= 0.15707964f || + !IsCachedLightInAreaLights(light, *x33c_lights))) + light.x1c_fader *= -1.f; + int negCount = 0; + for (SCachedHudLight& light : x340_hudLights) + if (light.x1c_fader <= 0.f) + ++negCount; + --negCount; + for (const CLight& light : x33c_lights->GetAreaLights()) { + if (negCount < 1) break; - case ETransitionState::Transitioning: - x2c8_transT = std::min(1.f, 5.f * dt + x2c8_transT); - if (x2c8_transT == 1.f) - x2c4_activeTransState = ETransitionState::NotTransitioning; - default: break; - } -} - -bool CSamusHud::CheckLoadComplete(CStateManager& stateMgr) -{ - switch (x4_loadPhase) - { - case ELoadPhase::Zero: - if (!x8_targetingMgr.CheckLoadComplete()) - return false; - x4_loadPhase = ELoadPhase::One; - case ELoadPhase::One: - UpdateStateTransition(1.f, stateMgr); - if (x2bc_nextState != x2c0_setState) - return false; - x4_loadPhase = ELoadPhase::Two; - case ELoadPhase::Two: - if (!x264_loadedFrmeHelmet->GetIsFinishedLoading()) - return false; - if (!x274_loadedFrmeBaseHud->GetIsFinishedLoading()) - return false; - x4_loadPhase = ELoadPhase::Three; - case ELoadPhase::Three: - return true; - default: break; + if (IsAreaLightInCachedLights(light)) + continue; + if ((light.GetPosition() - fpCam->GetTranslation()).normalized().dot(lookDir) > 0.15707964f) { + int slot = FindEmptyHudLightSlot(light); + if (slot == -1) + continue; + --negCount; + SCachedHudLight& cachedLight = x340_hudLights[slot]; + cachedLight.x0_pos = light.GetPosition(); + cachedLight.xc_color = light.GetColor(); + cachedLight.x10_distC = light.GetAttenuationConstant(); + cachedLight.x14_distL = light.GetAttenuationLinear(); + cachedLight.x18_distQ = light.GetAttenuationQuadratic(); + cachedLight.x1c_fader = 0.001f; + } } - return false; + float dt2 = 2.f * dt; + for (SCachedHudLight& light : x340_hudLights) { + if (light.x1c_fader < 0.f) + light.x1c_fader = std::min(0.f, light.x1c_fader + dt2); + else if (light.x1c_fader < 1.f && light.x1c_fader != 0.f) + light.x1c_fader = std::min(light.x1c_fader + dt2, 1.f); + } + + CPlayerState& playerState = *mgr.GetPlayerState(); + CPlayerState::EPlayerVisor visor = playerState.GetCurrentVisor(); + float visorT = playerState.GetVisorTransitionFactor(); + zeus::CColor lightAdd = + zeus::CColor::lerp(g_tweakGui->GetVisorHudLightAdd(0), g_tweakGui->GetVisorHudLightAdd(int(visor)), visorT); + zeus::CColor lightMul = zeus::CColor::lerp(g_tweakGui->GetVisorHudLightMultiply(0), + g_tweakGui->GetVisorHudLightMultiply(int(visor)), visorT); + + auto lightIt = x5d8_guiLights.begin(); + float maxIntensity = 0.f; + int maxIntensityIdx = 0; + for (int i = 0; i < 3; ++i) { + SCachedHudLight& light = x340_hudLights[i]; + CGuiLight* lightWidget = *lightIt++; + zeus::CVector3f lightToCam = fpCam->GetTranslation() - light.x0_pos; + zeus::CVector3f lightNormal = fpCam->GetTransform().buildMatrix3f() * lightToCam.normalized(); + float dist = std::max(lightToCam.magnitude(), FLT_EPSILON); + float falloffMul = 1.f / (dist * dist * light.x18_distQ * g_tweakGui->GetHudLightAttMulQuadratic() + + dist * light.x14_distL * g_tweakGui->GetHudLightAttMulLinear() + + light.x10_distC * g_tweakGui->GetHudLightAttMulConstant()); + falloffMul = std::min(falloffMul, 1.f); + lightWidget->SetO2WTransform(zeus::lookAt(zeus::CVector3f::skZero, lightNormal)); + float fadedFalloff = falloffMul * std::fabs(light.x1c_fader); + zeus::CColor lightColor = GetVisorHudLightColor(light.xc_color * zeus::CColor(fadedFalloff), mgr); + lightWidget->SetColor(lightColor); + lightAdd += lightColor * lightMul; + float greyscale = + fadedFalloff * zeus::CVector3f::skForward.dot(-lightNormal) * lightAdd.rgbDot(zeus::CColor(0.3f, 0.6f, 0.1f)); + if (greyscale > maxIntensity) { + maxIntensity = greyscale; + maxIntensityIdx = i; + } + } + + CLight brightestGameLight = CLight::BuildPoint(zeus::CVector3f::skZero, zeus::CColor::skBlack); + for (CEntity* ent : mgr.GetLightObjectList()) { + if (!ent || !ent->GetActive()) + continue; + CGameLight& gameLight = static_cast(*ent); + if (TCastToConstPtr(mgr.GetObjectById(gameLight.GetParentId()))) + continue; + CLight thisLight = gameLight.GetLight(); + if (thisLight.GetIntensity() > brightestGameLight.GetIntensity()) { + zeus::CSphere sphere(thisLight.GetPosition(), thisLight.GetRadius()); + if (camAABB.intersects(sphere)) + brightestGameLight = thisLight; + } + } + + if (brightestGameLight.GetIntensity() > FLT_EPSILON) { + zeus::CVector3f lightToCam = fpCam->GetTranslation() - brightestGameLight.GetPosition(); + float dist = std::max(lightToCam.magnitude(), FLT_EPSILON); + float falloffMul = + 1.f / (dist * dist * brightestGameLight.GetAttenuationQuadratic() * g_tweakGui->GetHudLightAttMulQuadratic() + + dist * brightestGameLight.GetAttenuationLinear() * g_tweakGui->GetHudLightAttMulLinear() + + brightestGameLight.GetAttenuationConstant() * g_tweakGui->GetHudLightAttMulConstant()); + falloffMul = std::min(falloffMul, 1.f); + zeus::CColor falloffColor = brightestGameLight.GetColor() * zeus::CColor(falloffMul); + falloffColor = GetVisorHudLightColor(falloffColor, mgr); + if (brightestGameLight.GetType() == ELightType::Spot) { + float quarterCicleFactor = zeus::clamp( + 0.f, + std::asin(std::max(0.f, fpCam->GetTransform().basis[1].dot(brightestGameLight.GetDirection()))) * + (M_PIF / 2.f), + 1.f); + falloffColor *= zeus::CColor(quarterCicleFactor); + } + lightAdd += falloffColor; + } + + const CGuiLight& brightestLight = *x5d8_guiLights[maxIntensityIdx]; + lightAdd += x33c_lights->GetAmbientColor() * zeus::CColor(0.25f, 1.f); + zeus::CVector3f revDir = -brightestLight.GetWorldTransform().basis[1]; + float foreDot = revDir.dot(zeus::CVector3f::skForward); + x5d8_guiLights[3]->SetO2WTransform( + zeus::lookAt(zeus::CVector3f::skZero, zeus::CVector3f::skForward * 2.f * foreDot - revDir)); + x5d8_guiLights[3]->SetColor(g_tweakGui->GetHudReflectivityLightColor() * brightestLight.GetIntermediateColor()); + x5d8_guiLights[3]->SetAmbientLightColor(lightAdd); + } } -void CSamusHud::OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr) -{ - // Empty -} +void CSamusHud::UpdateHudDamage(float dt, const CStateManager& mgr, DataSpec::ITweakGui::EHelmetVisMode helmetVis) { + CPlayer& player = mgr.GetPlayer(); + if (player.WasDamaged() && mgr.GetGameState() == CStateManager::EGameState::Running) + x3e8_damageTIme += dt; + else + x3e8_damageTIme = 0.f; -void CSamusHud::RefreshHudOptions() -{ + float pulseDur = g_tweakGui->GetHudDamagePulseDuration(); + float pulseTime = std::fabs(std::fmod(x3e8_damageTIme, pulseDur)); + if (pulseTime < 0.5f * pulseDur) + x3ec_damageLightPulser = pulseTime / (0.5f * pulseDur); + else + x3ec_damageLightPulser = (pulseDur - pulseTime) / (0.5f * pulseDur); + + x3ec_damageLightPulser = zeus::clamp( + 0.f, g_tweakGui->GetHudDamageColorGain() * x3ec_damageLightPulser * std::min(0.5f, player.GetDamageAmount()), + 1.f); + zeus::CColor damageAmbColor = g_tweakGuiColors->GetHudFrameColor(); + damageAmbColor *= damageAmbColor.a(); + damageAmbColor += zeus::CColor(x3ec_damageLightPulser); + damageAmbColor.a() = 1.f; + + if (x3d4_damageLight) + x3d4_damageLight->SetAmbientLightColor(damageAmbColor); + + if (x3f4_damageFilterAmt > 0.f) { + x3f4_damageFilterAmt = std::max(0.f, x3f4_damageFilterAmt - dt); + if (x3f4_damageFilterAmt == 0.f) { + CSfxManager::RemoveEmitter(x3a4_damageSfx); + x3a4_damageSfx.reset(); + } + } + + float tmp = x3f0_damageFilterAmtInit * g_tweakGui->GetHudDamagePeakFactor(); + float colorGain; + if (x3f4_damageFilterAmt > tmp) + colorGain = (x3f0_damageFilterAmtInit - x3f4_damageFilterAmt) / (x3f0_damageFilterAmtInit - tmp); + else + colorGain = x3f4_damageFilterAmt / tmp; + + colorGain = zeus::clamp(0.f, colorGain * x3f8_damageFilterAmtGain, 1.f); + zeus::CColor color0 = g_tweakGuiColors->GetDamageAmbientColor(); + color0.a() *= colorGain; + + zeus::CColor color1 = g_tweakGuiColors->GetDamageAmbientPulseColor(); + color1.a() *= x3ec_damageLightPulser; + zeus::CColor color2 = color0 + color1; + + if (color2.a()) { + if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed) + color2.a() *= 0.75f; + x3a8_camFilter.SetFilter(EFilterType::Add, EFilterShape::Fullscreen, 0.f, color2, -1); + } else { + x3a8_camFilter.DisableFilter(0.f); + } + + if (x3a4_damageSfx) + CSfxManager::UpdateEmitter(x3a4_damageSfx, player.GetTranslation(), player.GetTransform().basis[1], 1.f); + + if (x400_hudDamagePracticals > 0.f) { + x400_hudDamagePracticals = std::max(0.f, x400_hudDamagePracticals - dt); + float practicals = x400_hudDamagePracticals / x3fc_hudDamagePracticalsInit; + if (x28c_energyIntf) + x28c_energyIntf->SetFlashMagnitude(practicals); + practicals = std::min(practicals * x404_hudDamagePracticalsGain, 1.f); + x2a0_helmetIntf->AddHelmetLightValue(practicals); if (x29c_decoIntf) - x29c_decoIntf->UpdateHudAlpha(); - if (x2a0_helmetIntf) - x2a0_helmetIntf->UpdateHelmetAlpha(); -} - -void CSamusHud::Touch() -{ - if (x264_loadedFrmeHelmet) - x264_loadedFrmeHelmet->Touch(); - if (x274_loadedFrmeBaseHud) - x274_loadedFrmeBaseHud->Touch(); - if (x288_loadedSelectedHud) - x288_loadedSelectedHud->Touch(); -} - -zeus::CTransform CSamusHud::BuildFinalCameraTransform(const zeus::CQuaternion& rot, - const zeus::CVector3f& pos, - const zeus::CVector3f& camPos) -{ - zeus::CQuaternion invRot = rot.inverse(); - return zeus::CTransform(invRot, invRot.transform(camPos - pos) + pos); -} - -void CSamusHud::SetMessage(std::u16string_view text, const CHUDMemoParms& info) -{ - bool isWidgetVisible = x598_base_basewidget_message->GetIsVisible(); - if (!isWidgetVisible || info.IsHintMemo()) - { - if (info.IsFadeOutOnly()) - { - x558_messageTextTime = 1.f; - if (!info.IsHintMemo() || !isWidgetVisible) - return; - CSfxManager::SfxStart(SFXui_hide_hint_memo, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - return; - } - x598_base_basewidget_message->SetColor(zeus::CColor::skWhite); - x598_base_basewidget_message->SetVisibility(false, ETraversalMode::Children); - CGuiWidget* pane = info.IsHintMemo() ? x598_base_basewidget_message : x59c_base_textpane_message; - pane->SetVisibility(true, ETraversalMode::Children); - x59c_base_textpane_message->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, 40.f); - if (info.IsClearMemoWindow()) - { - x55c_lastSfxChars = 0.f; - x59c_base_textpane_message->TextSupport().SetCurTime(0.f); - x59c_base_textpane_message->TextSupport().SetText(text); - } - else if (x59c_base_textpane_message->TextSupport().GetString().empty()) - { - x55c_lastSfxChars = 0.f; - x59c_base_textpane_message->TextSupport().AddText(text); - } - else - { - x59c_base_textpane_message->TextSupport().AddText(std::u16string(u"\n") + text.data()); - } - - x59c_base_textpane_message->SetColor(zeus::CColor::skWhite); - x598_base_basewidget_message->SetColor(zeus::CColor::skWhite); - x558_messageTextTime = info.GetDisplayTime(); - if (info.IsHintMemo()) - { - if (!isWidgetVisible) - { - CSfxManager::SfxStart(SFXui_show_hint_memo, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - } - else - { - x598_base_basewidget_message->SetLocalTransform(x598_base_basewidget_message->GetTransform()); - } + x29c_decoIntf->SetFrameColorValue(practicals); + if (practicals > 0.f) { + x3d4_damageLight->SetColor(g_tweakGuiColors->GetHudDamageLightColor() * zeus::CColor(practicals)); + x3d4_damageLight->SetIsVisible(true); + } else { + x3d4_damageLight->SetIsVisible(false); } + } + + bool transformUpdate = false; + if (x414_decoShakeTranslateAmt > 0.f) { + x418_decoShakeTranslateAmtVel -= g_tweakGui->GetDecoDamageShakeDeceleration() * 60.f * dt; + x414_decoShakeTranslateAmt = std::max(0.f, x414_decoShakeTranslateAmt + x418_decoShakeTranslateAmtVel); + transformUpdate = true; + } + if (x460_decoShakeAmt > 0.f) { + x460_decoShakeAmt = std::max(0.f, x460_decoShakeAmt - dt); + x44c_hudLagShakeRot = zeus::CQuaternion::skNoRotation; + float rotMul = std::min(g_tweakGui->GetMaxDecoDamageShakeRotate(), + x460_decoShakeAmt / x45c_decoShakeAmtInit * x464_decoShakeAmtGain); + float rotAng = rotMul * (2.f * M_PIF / 10.f); + x44c_hudLagShakeRot.rotateX(rand() / float(RAND_MAX) * rotAng); + x44c_hudLagShakeRot.rotateZ(rand() / float(RAND_MAX) * rotAng); + zeus::CVector3f vecs[] = {zeus::CVector3f::skRight, zeus::CVector3f::skForward, zeus::CVector3f::skUp}; + for (int i = 0; i < 4; ++i) { + int sel = int(rand() / float(RAND_MAX) * 9.f); + vecs[sel & 0x3][(sel / 3) & 0x3] += (rand() / float(RAND_MAX) - dt) * rotMul; + } + x428_decoShakeRotate = zeus::CMatrix3f(vecs[0], vecs[1], vecs[2]).transposed(); + transformUpdate = true; + } + + if (transformUpdate) { + x41c_decoShakeTranslate = + x408_damagerToPlayerNorm * std::min(g_tweakGui->GetMaxDecoDamageShakeTranslate(), x414_decoShakeTranslateAmt); + if (x29c_decoIntf) + x29c_decoIntf->SetDamageTransform(x428_decoShakeRotate, + x41c_decoShakeTranslate * g_tweakGui->GetHudDecoShakeTranslateGain()); + } } -void CSamusHud::InternalDeferHintMemo(CAssetId strg, u32 strgIdx, const CHUDMemoParms& info) -{ - x548_hudMemoParms = info; - x550_hudMemoString = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), strg}); - x554_hudMemoIdx = strgIdx; +void CSamusHud::UpdateStaticSfx(CSfxHandle& handle, float& cycleTimer, u16 sfxId, float dt, float oldStaticInterp, + float staticThreshold) { + if ((oldStaticInterp > staticThreshold && x510_staticInterp <= staticThreshold) || + (oldStaticInterp <= staticThreshold && x510_staticInterp > staticThreshold)) { + cycleTimer = 0.f; + } else { + if (cycleTimer < 0.1f) + cycleTimer = std::min(cycleTimer + dt, 0.1f); + if (cycleTimer == 0.1f) { + if (x510_staticInterp > staticThreshold) { + if (!handle) + handle = CSfxManager::SfxStart(sfxId, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } else { + CSfxManager::SfxStop(handle); + handle.reset(); + } + } + } } +void CSamusHud::UpdateStaticInterference(float dt, const CStateManager& mgr) { + float intf = mgr.GetPlayerState()->GetStaticInterference().GetTotalInterference(); + float oldStaticInterp = x510_staticInterp; + if (x510_staticInterp < intf) + x510_staticInterp = std::min(x510_staticInterp + dt, intf); + else + x510_staticInterp = std::max(intf, x510_staticInterp - dt); + + UpdateStaticSfx(x508_staticSfxHi, x514_staticCycleTimerHi, SFXui_static_hi, dt, oldStaticInterp, 0.1f); + UpdateStaticSfx(x50c_staticSfxLo, x518_staticCycleTimerLo, SFXui_static_lo, dt, oldStaticInterp, 0.5f); + + if (x510_staticInterp > 0.f) { + zeus::CColor color = zeus::CColor::skWhite; + color.a() = x510_staticInterp; + x51c_camFilter2.SetFilter(EFilterType::Blend, EFilterShape::RandomStatic, 0.f, color, -1); + } else { + x51c_camFilter2.DisableFilter(0.f); + } } + +int CSamusHud::GetRelativeDirection(const zeus::CVector3f& position, const CStateManager& mgr) { + TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + if (!fpCam) + return 0; + zeus::CVector3f camToPosLocal = fpCam->GetTransform().transposeRotate(position - fpCam->GetTranslation()); + if (camToPosLocal == position) + return 0; + float y = std::cos(2.f * M_PIF * 0.0027777778f * 0.5f * fpCam->GetFov()); + float x = std::cos(2.f * M_PIF * 0.0027777778f * 0.5f * fpCam->GetFov() * fpCam->GetAspectRatio()); + zeus::CVector2f camToPosXY = zeus::CVector2f(camToPosLocal.x(), camToPosLocal.y()).normalized(); + zeus::CVector2f camToPosYZ = zeus::CVector2f(camToPosLocal.y(), camToPosLocal.z()).normalized(); + if (camToPosXY.dot(zeus::CVector2f(0.f, 1.f)) > x && camToPosYZ.dot(zeus::CVector2f(1.f, 0.f)) > y) + return 0; + if (camToPosXY.dot(zeus::CVector2f(0.f, -1.f)) > x && camToPosYZ.dot(zeus::CVector2f(-1.f, 0.f)) > y) + return 1; + zeus::CVector3f camToPosNorm = camToPosLocal.normalized(); + zeus::CQuaternion quat; + quat.rotateY(2.f * M_PIF / 8.f); + zeus::CVector3f vec = zeus::CVector3f::skUp; + float maxDot = -1.f; + int ret = -1; + for (int i = 0; i < 8; ++i) { + float dot = camToPosNorm.dot(vec); + if (dot > maxDot) { + maxDot = dot; + ret = i + 2; + } + vec = quat.transform(vec); + } + return ret; +} + +void CSamusHud::ShowDamage(const zeus::CVector3f& position, float dam, float prevDam, const CStateManager& mgr) { + CPlayer& player = mgr.GetPlayer(); + int dir = GetRelativeDirection(position, mgr); + TCastToConstPtr fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + x404_hudDamagePracticalsGain = + g_tweakGui->GetHudDamagePracticalsGainLinear() * dam + g_tweakGui->GetHudDamagePracticalsGainConstant(); + x3fc_hudDamagePracticalsInit = std::max(FLT_EPSILON, g_tweakGui->GetHudDamagePracticalsInitLinear() * dam + + g_tweakGui->GetHudDamagePracticalsInitConstant()); + x400_hudDamagePracticals = x3fc_hudDamagePracticalsInit; + if (x3d4_damageLight) + x3d4_damageLight->SetLocalTransform(x3d8_lightTransforms[dir]); + x3f8_damageFilterAmtGain = + g_tweakGui->GetHudDamageFilterGainLinear() * dam + g_tweakGui->GetHudDamageFilterGainConstant(); + x3f0_damageFilterAmtInit = + g_tweakGui->GetHudDamageFilterInitLinear() * dam + g_tweakGui->GetHudDamageFilterInitConstant(); + x3f4_damageFilterAmt = x3f0_damageFilterAmtInit; + if (!x3a4_damageSfx) { + x3a4_damageSfx = CSfxManager::AddEmitter(SFXui_damage_lp, player.GetTranslation(), player.GetTransform().basis[1], + 0.f, false, true, 0xff, kInvalidAreaId); + } + if (fpCam) { + x418_decoShakeTranslateAmtVel = + g_tweakGui->GetHudDecoShakeTranslateVelLinear() * prevDam + g_tweakGui->GetHudDecoShakeTranslateVelConstant(); + x414_decoShakeTranslateAmt = x418_decoShakeTranslateAmtVel; + x408_damagerToPlayerNorm = -(fpCam->GetTransform().inverse() * position).normalized(); + x464_decoShakeAmtGain = g_tweakGui->GetDecoShakeGainLinear() * prevDam + g_tweakGui->GetDecoShakeGainConstant(); + x45c_decoShakeAmtInit = g_tweakGui->GetDecoShakeInitLinear() * prevDam + g_tweakGui->GetDecoShakeInitConstant(); + x460_decoShakeAmt = x45c_decoShakeAmtInit; + } +} + +void CSamusHud::EnterFirstPerson(const CStateManager& mgr) { + CSfxManager::SfxVolume(x508_staticSfxHi, 1.f); + CSfxManager::SfxVolume(x50c_staticSfxLo, 1.f); +} + +void CSamusHud::LeaveFirstPerson(const CStateManager& mgr) { + CSfxManager::SfxVolume(x508_staticSfxHi, 0.f); + CSfxManager::SfxVolume(x50c_staticSfxLo, 0.f); +} + +EHudState CSamusHud::GetDesiredHudState(const CStateManager& mgr) { + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed || + mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphing || + mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphing) + return EHudState::Ball; + + switch (mgr.GetPlayerState()->GetTransitioningVisor()) { + case CPlayerState::EPlayerVisor::Combat: + return EHudState::Combat; + case CPlayerState::EPlayerVisor::XRay: + return EHudState::XRay; + case CPlayerState::EPlayerVisor::Scan: + return EHudState::Scan; + case CPlayerState::EPlayerVisor::Thermal: + return EHudState::Thermal; + default: + return EHudState::None; + } +} + +void CSamusHud::Update(float dt, const CStateManager& mgr, CInGameGuiManager::EHelmetVisMode helmetVis, bool hudVis, + bool targetingManager) { + CPlayer& player = mgr.GetPlayer(); + UpdateStateTransition(dt, mgr); + bool firstPerson = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && + !mgr.GetCameraManager()->IsInCinematicCamera(); + if (firstPerson != x2e0_26_latestFirstPerson) { + if (firstPerson) + EnterFirstPerson(mgr); + else + LeaveFirstPerson(mgr); + x2e0_26_latestFirstPerson = firstPerson; + } + + float morphT = 0.f; + switch (player.GetMorphballTransitionState()) { + case CPlayer::EPlayerMorphBallState::Morphed: + morphT = 1.f; + break; + case CPlayer::EPlayerMorphBallState::Morphing: + morphT = player.GetMorphFactor(); + break; + case CPlayer::EPlayerMorphBallState::Unmorphing: + morphT = 1.f - player.GetMorphFactor(); + break; + default: + break; + } + + float aspect = g_Viewport.x8_width / float(g_Viewport.xc_height); + float scaleMul = 1.f - zeus::clamp(0.f, (aspect - 1.33f) / (1.77f - 1.33f), 1.f); + x500_viewportScale.y() = 1.f - scaleMul * morphT * g_tweakGui->GetBallViewportYReduction() * 1.2f; + if (x2b0_ballIntf) + x2b0_ballIntf->SetBallModeFactor(morphT); + + bool helmetVisible = false; + bool glowVisible = false; + bool decoVisible = false; + if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) { + switch (helmetVis) { + case CInGameGuiManager::EHelmetVisMode::HelmetOnly: + helmetVisible = true; + break; + case CInGameGuiManager::EHelmetVisMode::GlowHelmetDeco: + glowVisible = true; + case CInGameGuiManager::EHelmetVisMode::HelmetDeco: + helmetVisible = true; + case CInGameGuiManager::EHelmetVisMode::Deco: + decoVisible = true; + default: + break; + } + } + + if (x29c_decoIntf) + x29c_decoIntf->SetIsVisibleDebug(decoVisible); + if (x2a0_helmetIntf) + x2a0_helmetIntf->SetIsVisibleDebug(helmetVisible, glowVisible); + + x590_base_Model_AutoMapper->SetIsVisible(false); + + UpdateEnergyLow(dt, mgr); + + for (int i = 0; i < 15; ++i) { + x7ac_[i].x0_ = 0; + x7ac_[i].x4_ = 0; + } + + if (x2ac_radarIntf) + x2ac_radarIntf->Update(dt, mgr); + + UpdateHudLag(dt, mgr); + + UpdateHudDynamicLights(dt, mgr); + + if (targetingManager) + x8_targetingMgr.Update(dt, mgr); + + UpdateHudDamage(dt, mgr, helmetVis); + + UpdateStaticInterference(dt, mgr); + + if (helmetVis != DataSpec::ITweakGui::EHelmetVisMode::ReducedUpdate) { + if (x2bc_nextState != EHudState::None) { + UpdateEnergy(dt, mgr, false); + UpdateFreeLook(dt, mgr); + } + + if (x2bc_nextState == EHudState::Ball) { + UpdateBallMode(mgr, false); + } else if (x2bc_nextState >= EHudState::Combat && x2bc_nextState <= EHudState::Scan) { + UpdateThreatAssessment(dt, mgr); + UpdateMissile(dt, mgr, false); + UpdateVideoBands(dt, mgr); + } + + UpdateVisorAndBeamMenus(dt, mgr); + + if (player.WasDamaged() && mgr.GetGameState() == CStateManager::EGameState::Running) + ShowDamage(player.GetDamageLocationWR(), player.GetDamageAmount(), player.GetPrevDamageAmount(), mgr); + } + + float oldAPulse = x584_abuttonPulse; + if (!x554_hudMemoIdx) { + x584_abuttonPulse += 2.f * dt; + if (x584_abuttonPulse > 1.f) + x584_abuttonPulse -= 2.f; + } + + zeus::CColor abuttonColor = zeus::CColor::skWhite; + abuttonColor.a() = std::fabs(x584_abuttonPulse); + x5a0_base_model_abutton->SetColor(abuttonColor); + + if (!mgr.GetCameraManager()->IsInCinematicCamera() && oldAPulse < 0.f && x584_abuttonPulse >= 0.f && + x598_base_basewidget_message->GetIsVisible() && (x558_messageTextTime == 0.f || x558_messageTextTime >= 1.f)) { + CSfxManager::SfxStart(SFXui_hud_memo_a_pulse, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + + float allTextAlpha; + if (x29c_decoIntf) + allTextAlpha = x29c_decoIntf->GetHudTextAlpha(); + else + allTextAlpha = 1.f; + + float messageTextAlpha = 1.f; + if (x558_messageTextTime > 0.f) + messageTextAlpha = std::min(x558_messageTextTime, 1.f); + else if (!x59c_base_textpane_message->GetIsVisible() && !x598_base_basewidget_message->GetIsVisible()) + messageTextAlpha = 0.f; + + if (x2b4_bossEnergyIntf) + x2b4_bossEnergyIntf->SetAlpha(1.f - messageTextAlpha); + + if (x550_hudMemoString && x550_hudMemoString.IsLoaded()) { + SetMessage(x550_hudMemoString->GetString(x554_hudMemoIdx), x548_hudMemoParms); + x550_hudMemoString = TLockedToken(); + } + + if (x558_messageTextTime > 0.f) { + x558_messageTextTime = std::max(0.f, x558_messageTextTime - dt); + if (x558_messageTextTime == 0.f) { + x59c_base_textpane_message->TextSupport().SetTypeWriteEffectOptions(false, 0.f, 1.f); + x598_base_basewidget_message->SetVisibility(false, ETraversalMode::Children); + } + } + + CGuiWidget* messageWidget; + if (x598_base_basewidget_message->GetIsVisible()) + messageWidget = x598_base_basewidget_message; + else + messageWidget = x59c_base_textpane_message; + + zeus::CColor messageColor = zeus::CColor::skWhite; + float textScale = 1.f; + messageColor.a() = std::min(allTextAlpha, messageTextAlpha); + messageWidget->SetColor(messageColor); + + if (messageWidget == x598_base_basewidget_message) { + if (x558_messageTextTime > 0.f) + x560_messageTextScale = std::min(x558_messageTextTime, 1.f); + else + x560_messageTextScale = std::min(x560_messageTextScale + dt, 1.f); + + float textScaleT = std::max(0.f, (x560_messageTextScale - 0.75f) / 0.25f); + if (textScaleT != 1.f) { + if (textScaleT < 0.7f) + textScale = textScaleT / 0.7f; + else if (textScaleT < 0.85f) + textScale = 0.1f * (1.f - (textScaleT - 0.7f) / 0.15f) + 0.9f; + else + textScale = 0.1f * ((textScaleT - 0.7f) - 0.15f) / 0.3f + 0.9f; + } + + x598_base_basewidget_message->SetLocalTransform(x598_base_basewidget_message->GetTransform() * + zeus::CTransform::Scale(textScale, 1.f, 1.f)); + } + + float nextSfxChars = x55c_lastSfxChars + g_tweakGui->GetWorldTransManagerCharsPerSfx(); + if (x59c_base_textpane_message->TextSupport().GetNumCharsPrinted() >= nextSfxChars) { + x55c_lastSfxChars = nextSfxChars; + if (!x598_base_basewidget_message->GetIsVisible() || textScale == 1.f) + CSfxManager::SfxStart(SFXui_hud_memo_type, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + + if (mgr.GetEscapeSequenceTimer() > 0.f) { + int minutes = mgr.GetEscapeSequenceTimer() / 60.f; + int seconds = std::fmod(mgr.GetEscapeSequenceTimer(), 60.f); + int hundredths = std::fmod(mgr.GetEscapeSequenceTimer() * 100.f, 100.f); + std::string timeStr = hecl::Format("%02d:%02d:%02d", int(minutes), int(seconds), int(hundredths)); + x594_base_textpane_counter->TextSupport().SetText(timeStr); + x594_base_textpane_counter->SetIsVisible(true); + + zeus::CColor counterColor = zeus::CColor::skWhite; + counterColor.a() = zeus::clamp(0.f, std::min(1.f - std::min(x558_messageTextTime, 1.f), allTextAlpha), 1.f); + x594_base_textpane_counter->SetColor(counterColor); + } else { + x594_base_textpane_counter->SetIsVisible(false); + } + + x274_loadedFrmeBaseHud->Update(dt); + if (x288_loadedSelectedHud) + x288_loadedSelectedHud->Update(dt); + if (x2b4_bossEnergyIntf) + x2b4_bossEnergyIntf->Update(dt); + if (x28c_energyIntf) + x28c_energyIntf->Update(dt, x580_energyLowPulse); + if (x290_threatIntf) + x290_threatIntf->Update(dt); + if (x294_missileIntf) + x294_missileIntf->Update(dt, mgr); + if (x298_freeLookIntf) + x298_freeLookIntf->Update(dt); + if (x2a0_helmetIntf) + x2a0_helmetIntf->Update(dt); + + if (player.GetScanningState() == CPlayer::EPlayerScanState::NotScanning) + x2f0_visorBeamMenuAlpha = std::min(x2f0_visorBeamMenuAlpha + 2.f * dt, 1.f); + else + x2f0_visorBeamMenuAlpha = std::max(0.f, x2f0_visorBeamMenuAlpha - 2.f * dt); + + CPlayerState::EPlayerVisor curVisor = mgr.GetPlayerState()->GetCurrentVisor(); + CPlayerState::EPlayerVisor transVisor = mgr.GetPlayerState()->GetTransitioningVisor(); + float transFactor = 0.f; + if (curVisor != CPlayerState::EPlayerVisor::Scan) { + if (transVisor == CPlayerState::EPlayerVisor::Scan) + transFactor = mgr.GetPlayerState()->GetVisorTransitionFactor(); + else + transFactor = 1.f; + } + + if (x2a4_visorMenu) { + float hudAlpha; + if (g_GameState->GameOptions().GetSwapBeamControls()) + hudAlpha = transFactor; + else + hudAlpha = x2f0_visorBeamMenuAlpha; + x2a4_visorMenu->UpdateHudAlpha(hudAlpha); + x2a4_visorMenu->Update(dt, false); + } + + if (x2a8_beamMenu) { + float hudAlpha; + if (g_GameState->GameOptions().GetSwapBeamControls()) + hudAlpha = x2f0_visorBeamMenuAlpha; + else + hudAlpha = transFactor; + x2a8_beamMenu->UpdateHudAlpha(hudAlpha); + x2a8_beamMenu->Update(dt, false); + } + + UpdateCameraDebugSettings(); + + if (x29c_decoIntf) + x29c_decoIntf->Update(dt, mgr); +} + +void CSamusHud::DrawAttachedEnemyEffect(const CStateManager& mgr) const { + float drainTime = mgr.GetPlayer().GetEnergyDrain().GetEnergyDrainTime(); + if (drainTime <= 0.f) + return; + + float modPeriod = g_tweakGui->GetEnergyDrainModPeriod(); + float alpha; + if (g_tweakGui->GetEnergyDrainSinusoidalPulse()) { + alpha = (std::sin(-0.25f * modPeriod + 2.f * M_PIF * drainTime / modPeriod) + 1.f) * 0.5f; + } else { + float halfModPeriod = 0.5f * modPeriod; + float tmp = std::fabs(std::fmod(drainTime, modPeriod)); + if (tmp < halfModPeriod) + alpha = tmp / halfModPeriod; + else + alpha = (modPeriod - tmp) / halfModPeriod; + } + + zeus::CColor filterColor = g_tweakGuiColors->GetEnergyDrainFilterColor(); + filterColor.a() *= alpha; + const_cast(m_energyDrainFilter).draw(filterColor); +} + +void CSamusHud::Draw(const CStateManager& mgr, float alpha, CInGameGuiManager::EHelmetVisMode helmetVis, bool hudVis, + bool targetingManager) const { + if (x2bc_nextState == EHudState::None) + return; + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) { + DrawAttachedEnemyEffect(mgr); + x51c_camFilter2.Draw(); + if (targetingManager) + x8_targetingMgr.Draw(mgr, false); + } + + if (helmetVis != CInGameGuiManager::EHelmetVisMode::ReducedUpdate && + helmetVis < CInGameGuiManager::EHelmetVisMode::HelmetOnly) { + if (alpha < 1.f) + const_cast(m_cookieCutterStatic).draw(zeus::CColor::skWhite, 1.f - alpha); + + if (x288_loadedSelectedHud) { + if (mgr.GetPlayer().GetDeathTime() > 0.f) { + if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed) { + CGuiWidgetDrawParms parms(x2c8_transT * zeus::clamp(0.f, 1.f - mgr.GetPlayer().GetDeathTime() / 6.f, 1.f), + zeus::CVector3f::skZero); + x288_loadedSelectedHud->Draw(parms); + } else { + CGuiWidgetDrawParms parms(x2c8_transT, zeus::CVector3f::skZero); + x288_loadedSelectedHud->Draw(parms); + } + } else { + CGuiWidgetDrawParms parms(x2c8_transT, zeus::CVector3f::skZero); + x288_loadedSelectedHud->Draw(parms); + } + } + + if (x274_loadedFrmeBaseHud) + x274_loadedFrmeBaseHud->Draw(CGuiWidgetDrawParms::Default); + } + + if (x29c_decoIntf && !x2cc_preLoadCountdown) + x29c_decoIntf->Draw(); + + if (x2bc_nextState >= EHudState::Combat && x2bc_nextState <= EHudState::Scan) { + if (hudVis && helmetVis != CInGameGuiManager::EHelmetVisMode::ReducedUpdate && + helmetVis < CInGameGuiManager::EHelmetVisMode::HelmetOnly) { + float t; + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Combat) + t = mgr.GetPlayerState()->GetVisorTransitionFactor(); + else + t = 0.f; + x2ac_radarIntf->Draw(mgr, t * alpha); + } + // Depth read/write enable + } +} + +void CSamusHud::DrawHelmet(const CStateManager& mgr, float camYOff) const { + if (!x264_loadedFrmeHelmet || + mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed || + x2bc_nextState == EHudState::Ball) + return; + + float t; + if (x2c4_activeTransState == ETransitionState::Transitioning && x2b8_curState == EHudState::Ball) + t = x2c8_transT; + else + t = 1.f; + + x264_loadedFrmeHelmet->Draw(CGuiWidgetDrawParms(t, zeus::CVector3f(0.f, 15.f * camYOff, 0.f))); +} + +void CSamusHud::ProcessControllerInput(const CFinalInput& input) { + if (x29c_decoIntf) + x29c_decoIntf->ProcessInput(input); +} + +void CSamusHud::UpdateStateTransition(float dt, const CStateManager& mgr) { + if (x2cc_preLoadCountdown == 0) { + EHudState desiredState = GetDesiredHudState(mgr); + if (desiredState != x2c0_setState) { + x2c0_setState = desiredState; + if (desiredState == EHudState::Ball || x2bc_nextState == EHudState::Ball) + x2c8_transT = FLT_EPSILON; + x2c4_activeTransState = ETransitionState::Countdown; + } + } + + switch (x2c4_activeTransState) { + case ETransitionState::Countdown: + if (x2cc_preLoadCountdown == 0) { + x2c8_transT = std::max(x2c8_transT - 5.f * dt, 0.f); + if (x2c8_transT == 0.f) { + x2cc_preLoadCountdown = 2; + x288_loadedSelectedHud = nullptr; + } + } else { + x2cc_preLoadCountdown -= 1; + if (x2cc_preLoadCountdown == 0) { + UninitializeFrameGlueMutable(); + x278_selectedHud = TLockedToken(); + switch (x2c0_setState) { + case EHudState::Thermal: + x278_selectedHud = g_SimplePool->GetObj("FRME_ThermalHud"); + break; + case EHudState::Combat: + x278_selectedHud = g_SimplePool->GetObj("FRME_CombatHud"); + break; + case EHudState::Scan: + x278_selectedHud = g_SimplePool->GetObj("FRME_ScanHud"); + break; + case EHudState::XRay: + x278_selectedHud = g_SimplePool->GetObj("FRME_XRayHudNew"); + break; + case EHudState::Ball: + x278_selectedHud = g_SimplePool->GetObj("FRME_BallHud"); + break; + default: + break; + } + x2c4_activeTransState = ETransitionState::Loading; + } + } + if (x2c4_activeTransState != ETransitionState::Loading) + return; + case ETransitionState::Loading: + if (x278_selectedHud) { + if (!x278_selectedHud.IsLoaded() || !x278_selectedHud->GetIsFinishedLoading()) + return; + x288_loadedSelectedHud = x278_selectedHud.GetObj(); + x288_loadedSelectedHud->SetMaxAspect(1.78f); + x2b8_curState = x2bc_nextState; + x2bc_nextState = x2c0_setState; + InitializeFrameGlueMutable(mgr); + x2c4_activeTransState = ETransitionState::Transitioning; + UpdateCameraDebugSettings(); + } else { + x2b8_curState = x2bc_nextState; + x2bc_nextState = x2c0_setState; + x2c4_activeTransState = ETransitionState::NotTransitioning; + } + break; + case ETransitionState::Transitioning: + x2c8_transT = std::min(1.f, 5.f * dt + x2c8_transT); + if (x2c8_transT == 1.f) + x2c4_activeTransState = ETransitionState::NotTransitioning; + default: + break; + } +} + +bool CSamusHud::CheckLoadComplete(CStateManager& stateMgr) { + switch (x4_loadPhase) { + case ELoadPhase::Zero: + if (!x8_targetingMgr.CheckLoadComplete()) + return false; + x4_loadPhase = ELoadPhase::One; + case ELoadPhase::One: + UpdateStateTransition(1.f, stateMgr); + if (x2bc_nextState != x2c0_setState) + return false; + x4_loadPhase = ELoadPhase::Two; + case ELoadPhase::Two: + if (!x264_loadedFrmeHelmet->GetIsFinishedLoading()) + return false; + if (!x274_loadedFrmeBaseHud->GetIsFinishedLoading()) + return false; + x4_loadPhase = ELoadPhase::Three; + case ELoadPhase::Three: + return true; + default: + break; + } + + return false; +} + +void CSamusHud::OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr) { + // Empty +} + +void CSamusHud::RefreshHudOptions() { + if (x29c_decoIntf) + x29c_decoIntf->UpdateHudAlpha(); + if (x2a0_helmetIntf) + x2a0_helmetIntf->UpdateHelmetAlpha(); +} + +void CSamusHud::Touch() { + if (x264_loadedFrmeHelmet) + x264_loadedFrmeHelmet->Touch(); + if (x274_loadedFrmeBaseHud) + x274_loadedFrmeBaseHud->Touch(); + if (x288_loadedSelectedHud) + x288_loadedSelectedHud->Touch(); +} + +zeus::CTransform CSamusHud::BuildFinalCameraTransform(const zeus::CQuaternion& rot, const zeus::CVector3f& pos, + const zeus::CVector3f& camPos) { + zeus::CQuaternion invRot = rot.inverse(); + return zeus::CTransform(invRot, invRot.transform(camPos - pos) + pos); +} + +void CSamusHud::SetMessage(std::u16string_view text, const CHUDMemoParms& info) { + bool isWidgetVisible = x598_base_basewidget_message->GetIsVisible(); + if (!isWidgetVisible || info.IsHintMemo()) { + if (info.IsFadeOutOnly()) { + x558_messageTextTime = 1.f; + if (!info.IsHintMemo() || !isWidgetVisible) + return; + CSfxManager::SfxStart(SFXui_hide_hint_memo, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + return; + } + x598_base_basewidget_message->SetColor(zeus::CColor::skWhite); + x598_base_basewidget_message->SetVisibility(false, ETraversalMode::Children); + CGuiWidget* pane = info.IsHintMemo() ? x598_base_basewidget_message : x59c_base_textpane_message; + pane->SetVisibility(true, ETraversalMode::Children); + x59c_base_textpane_message->TextSupport().SetTypeWriteEffectOptions(true, 0.1f, 40.f); + if (info.IsClearMemoWindow()) { + x55c_lastSfxChars = 0.f; + x59c_base_textpane_message->TextSupport().SetCurTime(0.f); + x59c_base_textpane_message->TextSupport().SetText(text); + } else if (x59c_base_textpane_message->TextSupport().GetString().empty()) { + x55c_lastSfxChars = 0.f; + x59c_base_textpane_message->TextSupport().AddText(text); + } else { + x59c_base_textpane_message->TextSupport().AddText(std::u16string(u"\n") + text.data()); + } + + x59c_base_textpane_message->SetColor(zeus::CColor::skWhite); + x598_base_basewidget_message->SetColor(zeus::CColor::skWhite); + x558_messageTextTime = info.GetDisplayTime(); + if (info.IsHintMemo()) { + if (!isWidgetVisible) { + CSfxManager::SfxStart(SFXui_show_hint_memo, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + } else { + x598_base_basewidget_message->SetLocalTransform(x598_base_basewidget_message->GetTransform()); + } + } +} + +void CSamusHud::InternalDeferHintMemo(CAssetId strg, u32 strgIdx, const CHUDMemoParms& info) { + x548_hudMemoParms = info; + x550_hudMemoString = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), strg}); + x554_hudMemoIdx = strgIdx; +} + +} // namespace urde::MP1 diff --git a/Runtime/MP1/CSamusHud.hpp b/Runtime/MP1/CSamusHud.hpp index 94a10ce11..688348e6e 100644 --- a/Runtime/MP1/CSamusHud.hpp +++ b/Runtime/MP1/CSamusHud.hpp @@ -15,259 +15,220 @@ #include "Graphics/Shaders/CRandomStaticFilter.hpp" #include "World/CHUDMemoParms.hpp" -namespace urde -{ +namespace urde { class CGuiFrame; class CStateManager; class CGuiLight; -enum class EHudState -{ - Combat, - XRay, - Thermal, - Scan, - Ball, - None -}; +enum class EHudState { Combat, XRay, Thermal, Scan, Ball, None }; -namespace MP1 -{ +namespace MP1 { -class CSamusHud -{ - enum class ELoadPhase - { - Zero, - One, - Two, - Three +class CSamusHud { + enum class ELoadPhase { Zero, One, Two, Three }; + + enum class ETransitionState { NotTransitioning, Countdown, Loading, Transitioning }; + + struct SCachedHudLight { + zeus::CVector3f x0_pos; + zeus::CColor xc_color; + float x10_distC = 0.f; + float x14_distL = 0.f; + float x18_distQ = 0.f; + float x1c_fader = 0.f; + SCachedHudLight(const zeus::CVector3f& pos, const zeus::CColor& color, float f1, float f2, float f3, float f4) + : x0_pos(pos), xc_color(color), x10_distC(f1), x14_distL(f2), x18_distQ(f3), x1c_fader(f4) {} + }; + + struct SVideoBand { + CGuiModel* x0_videoband = nullptr; + float x4_randA = 0.f; + float x8_randB = 0.f; + }; + + struct SProfileInfo { + u32 x0_ = 0; + u32 x4_ = 0; + u64 x8_profUsec = 0; + }; + + friend class CInGameGuiManager; + ELoadPhase x4_loadPhase = ELoadPhase::Zero; + CTargetingManager x8_targetingMgr; + TLockedToken x258_frmeHelmet; + CGuiFrame* x264_loadedFrmeHelmet = nullptr; + TLockedToken x268_frmeBaseHud; + CGuiFrame* x274_loadedFrmeBaseHud = nullptr; + TLockedToken x278_selectedHud; // used to be optional + CGuiFrame* x288_loadedSelectedHud = nullptr; + std::unique_ptr x28c_energyIntf; + std::unique_ptr x290_threatIntf; + std::unique_ptr x294_missileIntf; + std::unique_ptr x298_freeLookIntf; + std::unique_ptr x29c_decoIntf; + std::unique_ptr x2a0_helmetIntf; + std::unique_ptr x2a4_visorMenu; + std::unique_ptr x2a8_beamMenu; + std::unique_ptr x2ac_radarIntf; + std::unique_ptr x2b0_ballIntf; + std::unique_ptr x2b4_bossEnergyIntf; + EHudState x2b8_curState = EHudState::None; + EHudState x2bc_nextState = EHudState::None; + EHudState x2c0_setState = EHudState::None; + ETransitionState x2c4_activeTransState = ETransitionState::NotTransitioning; + float x2c8_transT = 1.f; + u32 x2cc_preLoadCountdown = 0; + float x2d0_playerHealth = 0.f; + u32 x2d4_totalEnergyTanks = 0; + u32 x2d8_missileAmount = 0; + u32 x2dc_missileCapacity = 0; + + union { + struct { + bool x2e0_24_inFreeLook : 1; + bool x2e0_25_lookControlHeld : 1; + bool x2e0_26_latestFirstPerson : 1; + bool x2e0_27_energyLow : 1; }; + u16 _dummy = 0; + }; - enum class ETransitionState - { - NotTransitioning, - Countdown, - Loading, - Transitioning - }; + u32 x2e4_ = 0; + u32 x2e8_ = 0; + CPlayerGun::EMissleMode x2ec_missileMode = CPlayerGun::EMissleMode::Inactive; + float x2f0_visorBeamMenuAlpha = 1.f; + zeus::CVector3f x2f8_fpCamDir; + zeus::CVector3f x304_basewidgetIdlePos; + zeus::CVector3f x310_cameraPos; + zeus::CQuaternion x31c_hudLag; + zeus::CQuaternion x32c_invHudLag; + std::unique_ptr x33c_lights; + rstl::reserved_vector x340_hudLights; + CSfxHandle x3a4_damageSfx; + CCameraFilterPass x3a8_camFilter; + CGuiLight* x3d4_damageLight = nullptr; + std::vector x3d8_lightTransforms; + float x3e8_damageTIme = 0.f; + float x3ec_damageLightPulser = 0.f; + float x3f0_damageFilterAmtInit = 1.f; + float x3f4_damageFilterAmt = 0.f; + float x3f8_damageFilterAmtGain = 0.f; + float x3fc_hudDamagePracticalsInit = 0.f; + float x400_hudDamagePracticals = 0.f; + float x404_hudDamagePracticalsGain = 0.f; + zeus::CVector3f x408_damagerToPlayerNorm; + float x414_decoShakeTranslateAmt = 0.f; + float x418_decoShakeTranslateAmtVel = 0.f; + zeus::CVector3f x41c_decoShakeTranslate; + zeus::CMatrix3f x428_decoShakeRotate; + zeus::CQuaternion x44c_hudLagShakeRot; + float x45c_decoShakeAmtInit = 0.f; + float x460_decoShakeAmt = 0.f; + float x464_decoShakeAmtGain = 0.f; + rstl::reserved_vector x46c_; + zeus::CVector2f x500_viewportScale = {1.f, 1.f}; + CSfxHandle x508_staticSfxHi; + CSfxHandle x50c_staticSfxLo; + float x510_staticInterp = 0.f; + float x514_staticCycleTimerHi = 0.f; + float x518_staticCycleTimerLo = 0.f; + CCameraFilterPass x51c_camFilter2; + CHUDMemoParms x548_hudMemoParms; + TLockedToken x550_hudMemoString; + u32 x554_hudMemoIdx = 0; + float x558_messageTextTime = 0.f; + float x55c_lastSfxChars = 0.f; + float x560_messageTextScale = 0.f; + CSfxHandle x564_freeLookSfx; + zeus::CVector3f x568_fpCamDir; + float x574_lookDeltaDot = 1.f; + float x578_freeLookSfxCycleTimer = 0.f; + float x57c_energyLowTimer = 0.f; + float x580_energyLowPulse = 0.f; + float x584_abuttonPulse = 0.f; + CGuiWidget* x588_base_basewidget_pivot; + CGuiWidget* x58c_helmet_BaseWidget_Pivot; + CGuiModel* x590_base_Model_AutoMapper; + CGuiTextPane* x594_base_textpane_counter; + CGuiWidget* x598_base_basewidget_message; + CGuiTextPane* x59c_base_textpane_message; + CGuiModel* x5a0_base_model_abutton; + rstl::reserved_vector x5a4_videoBands; + rstl::reserved_vector x5d8_guiLights; + float x5ec_camFovTweaks[16]; + float x62c_camYTweaks[64]; + float x72c_camZTweaks[32]; + rstl::reserved_vector x7ac_; - struct SCachedHudLight - { - zeus::CVector3f x0_pos; - zeus::CColor xc_color; - float x10_distC = 0.f; - float x14_distL = 0.f; - float x18_distQ = 0.f; - float x1c_fader = 0.f; - SCachedHudLight(const zeus::CVector3f& pos, const zeus::CColor& color, - float f1, float f2, float f3, float f4) - : x0_pos(pos), xc_color(color), x10_distC(f1), x14_distL(f2), x18_distQ(f3), x1c_fader(f4) {} - }; + CColoredQuadFilter m_energyDrainFilter; + CCookieCutterDepthRandomStaticFilter m_cookieCutterStatic = {EFilterType::NoColor}; - struct SVideoBand - { - CGuiModel* x0_videoband = nullptr; - float x4_randA = 0.f; - float x8_randB = 0.f; - }; - - struct SProfileInfo - { - u32 x0_ = 0; - u32 x4_ = 0; - u64 x8_profUsec = 0; - }; - - friend class CInGameGuiManager; - ELoadPhase x4_loadPhase = ELoadPhase::Zero; - CTargetingManager x8_targetingMgr; - TLockedToken x258_frmeHelmet; - CGuiFrame* x264_loadedFrmeHelmet = nullptr; - TLockedToken x268_frmeBaseHud; - CGuiFrame* x274_loadedFrmeBaseHud = nullptr; - TLockedToken x278_selectedHud; // used to be optional - CGuiFrame* x288_loadedSelectedHud = nullptr; - std::unique_ptr x28c_energyIntf; - std::unique_ptr x290_threatIntf; - std::unique_ptr x294_missileIntf; - std::unique_ptr x298_freeLookIntf; - std::unique_ptr x29c_decoIntf; - std::unique_ptr x2a0_helmetIntf; - std::unique_ptr x2a4_visorMenu; - std::unique_ptr x2a8_beamMenu; - std::unique_ptr x2ac_radarIntf; - std::unique_ptr x2b0_ballIntf; - std::unique_ptr x2b4_bossEnergyIntf; - EHudState x2b8_curState = EHudState::None; - EHudState x2bc_nextState = EHudState::None; - EHudState x2c0_setState = EHudState::None; - ETransitionState x2c4_activeTransState = ETransitionState::NotTransitioning; - float x2c8_transT = 1.f; - u32 x2cc_preLoadCountdown = 0; - float x2d0_playerHealth = 0.f; - u32 x2d4_totalEnergyTanks = 0; - u32 x2d8_missileAmount = 0; - u32 x2dc_missileCapacity = 0; - - union - { - struct - { - bool x2e0_24_inFreeLook : 1; - bool x2e0_25_lookControlHeld : 1; - bool x2e0_26_latestFirstPerson : 1; - bool x2e0_27_energyLow : 1; - }; - u16 _dummy = 0; - }; - - u32 x2e4_ = 0; - u32 x2e8_ = 0; - CPlayerGun::EMissleMode x2ec_missileMode = CPlayerGun::EMissleMode::Inactive; - float x2f0_visorBeamMenuAlpha = 1.f; - zeus::CVector3f x2f8_fpCamDir; - zeus::CVector3f x304_basewidgetIdlePos; - zeus::CVector3f x310_cameraPos; - zeus::CQuaternion x31c_hudLag; - zeus::CQuaternion x32c_invHudLag; - std::unique_ptr x33c_lights; - rstl::reserved_vector x340_hudLights; - CSfxHandle x3a4_damageSfx; - CCameraFilterPass x3a8_camFilter; - CGuiLight* x3d4_damageLight = nullptr; - std::vector x3d8_lightTransforms; - float x3e8_damageTIme = 0.f; - float x3ec_damageLightPulser = 0.f; - float x3f0_damageFilterAmtInit = 1.f; - float x3f4_damageFilterAmt = 0.f; - float x3f8_damageFilterAmtGain = 0.f; - float x3fc_hudDamagePracticalsInit = 0.f; - float x400_hudDamagePracticals = 0.f; - float x404_hudDamagePracticalsGain = 0.f; - zeus::CVector3f x408_damagerToPlayerNorm; - float x414_decoShakeTranslateAmt = 0.f; - float x418_decoShakeTranslateAmtVel = 0.f; - zeus::CVector3f x41c_decoShakeTranslate; - zeus::CMatrix3f x428_decoShakeRotate; - zeus::CQuaternion x44c_hudLagShakeRot; - float x45c_decoShakeAmtInit = 0.f; - float x460_decoShakeAmt = 0.f; - float x464_decoShakeAmtGain = 0.f; - rstl::reserved_vector x46c_; - zeus::CVector2f x500_viewportScale = {1.f, 1.f}; - CSfxHandle x508_staticSfxHi; - CSfxHandle x50c_staticSfxLo; - float x510_staticInterp = 0.f; - float x514_staticCycleTimerHi = 0.f; - float x518_staticCycleTimerLo = 0.f; - CCameraFilterPass x51c_camFilter2; - CHUDMemoParms x548_hudMemoParms; - TLockedToken x550_hudMemoString; - u32 x554_hudMemoIdx = 0; - float x558_messageTextTime = 0.f; - float x55c_lastSfxChars = 0.f; - float x560_messageTextScale = 0.f; - CSfxHandle x564_freeLookSfx; - zeus::CVector3f x568_fpCamDir; - float x574_lookDeltaDot = 1.f; - float x578_freeLookSfxCycleTimer = 0.f; - float x57c_energyLowTimer = 0.f; - float x580_energyLowPulse = 0.f; - float x584_abuttonPulse = 0.f; - CGuiWidget* x588_base_basewidget_pivot; - CGuiWidget* x58c_helmet_BaseWidget_Pivot; - CGuiModel* x590_base_Model_AutoMapper; - CGuiTextPane* x594_base_textpane_counter; - CGuiWidget* x598_base_basewidget_message; - CGuiTextPane* x59c_base_textpane_message; - CGuiModel* x5a0_base_model_abutton; - rstl::reserved_vector x5a4_videoBands; - rstl::reserved_vector x5d8_guiLights; - float x5ec_camFovTweaks[16]; - float x62c_camYTweaks[64]; - float x72c_camZTweaks[32]; - rstl::reserved_vector x7ac_; - - CColoredQuadFilter m_energyDrainFilter; - CCookieCutterDepthRandomStaticFilter m_cookieCutterStatic = { EFilterType::NoColor }; - - static CSamusHud* g_SamusHud; - static rstl::reserved_vector BuildPlayerHasVisors(const CStateManager& mgr); - static rstl::reserved_vector BuildPlayerHasBeams(const CStateManager& mgr); - void InitializeFrameGluePermanent(const CStateManager& mgr); - void InitializeFrameGlueMutable(const CStateManager& mgr); - void UninitializeFrameGlueMutable(); - void InitializeDamageLight(); - void UpdateEnergy(float dt, const CStateManager& mgr, bool init); - void UpdateFreeLook(float dt, const CStateManager& mgr); - void UpdateMissile(float dt, const CStateManager& mgr, bool init); - void UpdateVideoBands(float dt, const CStateManager& mgr); - void UpdateBallMode(const CStateManager& mgr, bool init); - void UpdateThreatAssessment(float dt, const CStateManager& mgr); - void UpdateVisorAndBeamMenus(float dt, const CStateManager& mgr); - void UpdateCameraDebugSettings(); - void UpdateEnergyLow(float dt, const CStateManager& mgr); - void ApplyClassicLag(const zeus::CUnitVector3f& lookDir, zeus::CQuaternion& rot, - const CStateManager& mgr, float dt, bool invert); - void UpdateHudLag(float dt, const CStateManager& mgr); - bool IsCachedLightInAreaLights(const SCachedHudLight& light, const CActorLights& areaLights) const; - bool IsAreaLightInCachedLights(const CLight& light) const; - int FindEmptyHudLightSlot(const CLight& light) const; - zeus::CColor GetVisorHudLightColor(const zeus::CColor& color, const CStateManager& mgr) const; - void UpdateHudDynamicLights(float dt, const CStateManager& mgr); - void UpdateHudDamage(float dt, const CStateManager& mgr, - DataSpec::ITweakGui::EHelmetVisMode helmetVis); - void UpdateStaticSfx(CSfxHandle& handle, float& cycleTimer, u16 sfxId, float dt, - float oldStaticInterp, float staticThreshold); - void UpdateStaticInterference(float dt, const CStateManager& mgr); - int GetRelativeDirection(const zeus::CVector3f& position, const CStateManager& mgr); - void ShowDamage(const zeus::CVector3f& position, float dam, float prevDam, const CStateManager& mgr); - void EnterFirstPerson(const CStateManager& mgr); - void LeaveFirstPerson(const CStateManager& mgr); - void DrawAttachedEnemyEffect(const CStateManager& mgr) const; - static EHudState GetDesiredHudState(const CStateManager& mgr); + static CSamusHud* g_SamusHud; + static rstl::reserved_vector BuildPlayerHasVisors(const CStateManager& mgr); + static rstl::reserved_vector BuildPlayerHasBeams(const CStateManager& mgr); + void InitializeFrameGluePermanent(const CStateManager& mgr); + void InitializeFrameGlueMutable(const CStateManager& mgr); + void UninitializeFrameGlueMutable(); + void InitializeDamageLight(); + void UpdateEnergy(float dt, const CStateManager& mgr, bool init); + void UpdateFreeLook(float dt, const CStateManager& mgr); + void UpdateMissile(float dt, const CStateManager& mgr, bool init); + void UpdateVideoBands(float dt, const CStateManager& mgr); + void UpdateBallMode(const CStateManager& mgr, bool init); + void UpdateThreatAssessment(float dt, const CStateManager& mgr); + void UpdateVisorAndBeamMenus(float dt, const CStateManager& mgr); + void UpdateCameraDebugSettings(); + void UpdateEnergyLow(float dt, const CStateManager& mgr); + void ApplyClassicLag(const zeus::CUnitVector3f& lookDir, zeus::CQuaternion& rot, const CStateManager& mgr, float dt, + bool invert); + void UpdateHudLag(float dt, const CStateManager& mgr); + bool IsCachedLightInAreaLights(const SCachedHudLight& light, const CActorLights& areaLights) const; + bool IsAreaLightInCachedLights(const CLight& light) const; + int FindEmptyHudLightSlot(const CLight& light) const; + zeus::CColor GetVisorHudLightColor(const zeus::CColor& color, const CStateManager& mgr) const; + void UpdateHudDynamicLights(float dt, const CStateManager& mgr); + void UpdateHudDamage(float dt, const CStateManager& mgr, DataSpec::ITweakGui::EHelmetVisMode helmetVis); + void UpdateStaticSfx(CSfxHandle& handle, float& cycleTimer, u16 sfxId, float dt, float oldStaticInterp, + float staticThreshold); + void UpdateStaticInterference(float dt, const CStateManager& mgr); + int GetRelativeDirection(const zeus::CVector3f& position, const CStateManager& mgr); + void ShowDamage(const zeus::CVector3f& position, float dam, float prevDam, const CStateManager& mgr); + void EnterFirstPerson(const CStateManager& mgr); + void LeaveFirstPerson(const CStateManager& mgr); + void DrawAttachedEnemyEffect(const CStateManager& mgr) const; + static EHudState GetDesiredHudState(const CStateManager& mgr); public: - CSamusHud(CStateManager& stateMgr); - ~CSamusHud(); - void Update(float dt, const CStateManager& mgr, - CInGameGuiManager::EHelmetVisMode helmetVis, - bool hudVis, bool targetingManager); - void Draw(const CStateManager& mgr, float alpha, - CInGameGuiManager::EHelmetVisMode helmetVis, - bool hudVis, bool targetingManager) const; - void DrawHelmet(const CStateManager& mgr, float camYOff) const; - void ProcessControllerInput(const CFinalInput& input); - void UpdateStateTransition(float time, const CStateManager& mgr); - bool CheckLoadComplete(CStateManager& stateMgr); - void OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr); - void RefreshHudOptions(); - void Touch(); - CTargetingManager& GetTargetingManager() { return x8_targetingMgr; } - const zeus::CVector2f& GetViewportScale() const { return x500_viewportScale; } - static zeus::CTransform BuildFinalCameraTransform(const zeus::CQuaternion& rot, - const zeus::CVector3f& pos, - const zeus::CVector3f& camPos); - static void DisplayHudMemo(std::u16string_view text, const CHUDMemoParms& info) - { - if (g_SamusHud) - g_SamusHud->InternalDisplayHudMemo(text, info); - } - void InternalDisplayHudMemo(std::u16string_view text, const CHUDMemoParms& info) - { - SetMessage(text, info); - } - void SetMessage(std::u16string_view text, const CHUDMemoParms& info); - static void DeferHintMemo(CAssetId strg, u32 strgIdx, const CHUDMemoParms& info) - { - if (g_SamusHud) - g_SamusHud->InternalDeferHintMemo(strg, strgIdx, info); - } - void InternalDeferHintMemo(CAssetId strg, u32 strgIdx, const CHUDMemoParms& info); - CGuiFrame* GetBaseHudFrame() const { return x274_loadedFrmeBaseHud; } + CSamusHud(CStateManager& stateMgr); + ~CSamusHud(); + void Update(float dt, const CStateManager& mgr, CInGameGuiManager::EHelmetVisMode helmetVis, bool hudVis, + bool targetingManager); + void Draw(const CStateManager& mgr, float alpha, CInGameGuiManager::EHelmetVisMode helmetVis, bool hudVis, + bool targetingManager) const; + void DrawHelmet(const CStateManager& mgr, float camYOff) const; + void ProcessControllerInput(const CFinalInput& input); + void UpdateStateTransition(float time, const CStateManager& mgr); + bool CheckLoadComplete(CStateManager& stateMgr); + void OnNewInGameGuiState(EInGameGuiState state, CStateManager& stateMgr); + void RefreshHudOptions(); + void Touch(); + CTargetingManager& GetTargetingManager() { return x8_targetingMgr; } + const zeus::CVector2f& GetViewportScale() const { return x500_viewportScale; } + static zeus::CTransform BuildFinalCameraTransform(const zeus::CQuaternion& rot, const zeus::CVector3f& pos, + const zeus::CVector3f& camPos); + static void DisplayHudMemo(std::u16string_view text, const CHUDMemoParms& info) { + if (g_SamusHud) + g_SamusHud->InternalDisplayHudMemo(text, info); + } + void InternalDisplayHudMemo(std::u16string_view text, const CHUDMemoParms& info) { SetMessage(text, info); } + void SetMessage(std::u16string_view text, const CHUDMemoParms& info); + static void DeferHintMemo(CAssetId strg, u32 strgIdx, const CHUDMemoParms& info) { + if (g_SamusHud) + g_SamusHud->InternalDeferHintMemo(strg, strgIdx, info); + } + void InternalDeferHintMemo(CAssetId strg, u32 strgIdx, const CHUDMemoParms& info); + CGuiFrame* GetBaseHudFrame() const { return x274_loadedFrmeBaseHud; } }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CSaveGameScreen.cpp b/Runtime/MP1/CSaveGameScreen.cpp index 8c3c816c9..00440054d 100644 --- a/Runtime/MP1/CSaveGameScreen.cpp +++ b/Runtime/MP1/CSaveGameScreen.cpp @@ -9,693 +9,589 @@ #include "Audio/CSfxManager.hpp" #include "MP1/MP1.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { using EState = CMemoryCardDriver::EState; using EError = CMemoryCardDriver::EError; -void CSaveGameScreen::ResetCardDriver() -{ - x92_savingDisabled = false; - x6c_cardDriver.reset(); - bool importState = (x0_saveCtx == ESaveContext::FrontEnd && !x90_needsDriverReset); - x6c_cardDriver = ConstructCardDriver(importState); - x6c_cardDriver->StartCardProbe(); - x10_uiType = EUIType::Empty; - SetUIText(); +void CSaveGameScreen::ResetCardDriver() { + x92_savingDisabled = false; + x6c_cardDriver.reset(); + bool importState = (x0_saveCtx == ESaveContext::FrontEnd && !x90_needsDriverReset); + x6c_cardDriver = ConstructCardDriver(importState); + x6c_cardDriver->StartCardProbe(); + x10_uiType = EUIType::Empty; + SetUIText(); } -CIOWin::EMessageReturn CSaveGameScreen::Update(float dt) -{ - if (!PumpLoad()) - return CIOWin::EMessageReturn::Normal; - - x50_loadedFrame->Update(dt); - x6c_cardDriver->Update(); - - if (x6c_cardDriver->x10_state == EState::DriverClosed) - { - if (x90_needsDriverReset) - { - ResetCardDriver(); - x90_needsDriverReset = false; - } - else - x80_iowRet = CIOWin::EMessageReturn::Exit; - } - else if (x6c_cardDriver->x10_state == EState::CardCheckDone && x10_uiType != EUIType::NotOriginalCard) - { - if (x6c_cardDriver->x28_cardSerial != x8_serial) - { - if (x93_inGame) - { - x10_uiType = EUIType::NotOriginalCard; - x91_uiTextDirty = true; - } - else - { - x8_serial = x6c_cardDriver->x28_cardSerial; - x6c_cardDriver->IndexFiles(); - } - } - else - { - x6c_cardDriver->IndexFiles(); - } - } - else if (x6c_cardDriver->x10_state == EState::Ready) - { - if (x90_needsDriverReset) - x6c_cardDriver->StartFileCreateTransactional(); - } - - if (x80_iowRet != CIOWin::EMessageReturn::Normal) - return x80_iowRet; - - EUIType oldTp = x10_uiType; - x10_uiType = SelectUIType(); - if (oldTp != x10_uiType || x91_uiTextDirty) - SetUIText(); - - if (x6c_cardDriver->x10_state == EState::NoCard) - { - auto res = CMemoryCardSys::CardProbe(kabufuda::ECardSlot::SlotA); - if (res.x0_error == CMemoryCardSys::ECardResult::READY || - res.x0_error == CMemoryCardSys::ECardResult::WRONGDEVICE) - ResetCardDriver(); - } - else if (x6c_cardDriver->x10_state == EState::CardFormatted) - { - ResetCardDriver(); - } - else if (x6c_cardDriver->x10_state == EState::FileBad && - x6c_cardDriver->x14_error == EError::FileMissing) - { - x6c_cardDriver->StartFileCreate(); - } - +CIOWin::EMessageReturn CSaveGameScreen::Update(float dt) { + if (!PumpLoad()) return CIOWin::EMessageReturn::Normal; -} -bool CSaveGameScreen::PumpLoad() -{ - if (x50_loadedFrame) - return true; - if (!x14_txtrSaveBanner.IsLoaded()) - return false; - if (!x20_txtrSaveIcon0.IsLoaded()) - return false; - if (!x2c_txtrSaveIcon1.IsLoaded()) - return false; - if (!x38_strgMemoryCard.IsLoaded()) - return false; - for (TLockedToken& savw : x70_saveWorlds) - if (!savw.IsLoaded()) - return false; - if (!x44_frmeGenericMenu.IsLoaded()) - return false; + x50_loadedFrame->Update(dt); + x6c_cardDriver->Update(); - x50_loadedFrame = x44_frmeGenericMenu.GetObj(); - x50_loadedFrame->SetAspectConstraint(1.78f); - x54_textpane_message = static_cast(x50_loadedFrame->FindWidget("textpane_message")); - x58_tablegroup_choices = static_cast(x50_loadedFrame->FindWidget("tablegroup_choices")); - x5c_textpane_choice0 = static_cast(x50_loadedFrame->FindWidget("textpane_choice0")); - x60_textpane_choice1 = static_cast(x50_loadedFrame->FindWidget("textpane_choice1")); - x64_textpane_choice2 = static_cast(x50_loadedFrame->FindWidget("textpane_choice2")); - x68_textpane_choice3 = static_cast(x50_loadedFrame->FindWidget("textpane_choice3")); - - x58_tablegroup_choices->SetMenuAdvanceCallback( - std::bind(&CSaveGameScreen::DoAdvance, this, std::placeholders::_1)); - x58_tablegroup_choices->SetMenuSelectionChangeCallback( - std::bind(&CSaveGameScreen::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); - - if (x0_saveCtx == ESaveContext::InGame) - x6c_cardDriver->StartCardProbe(); - - x10_uiType = SelectUIType(); - SetUIText(); - return true; -} - -CSaveGameScreen::EUIType CSaveGameScreen::SelectUIType() const -{ - if (x6c_cardDriver->x10_state == EState::NoCard) - return EUIType::NoCardFound; - - switch (x10_uiType) - { - case EUIType::ProgressWillBeLost: - case EUIType::NotOriginalCard: - case EUIType::AllDataWillBeLost: - return x10_uiType; - default: break; - } - - if (CMemoryCardDriver::IsCardBusy(x6c_cardDriver->x10_state)) - { - if (CMemoryCardDriver::IsCardWriting(x6c_cardDriver->x10_state)) - return EUIType::BusyWriting; - return EUIType::BusyReading; - } - - if (x6c_cardDriver->x10_state == EState::Ready) - { - if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardStillFull) - return EUIType::StillInsufficientSpace; - return EUIType::SaveReady; - } - - if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardBroken) - return EUIType::NeedsFormatBroken; - - if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardWrongCharacterSet) - return EUIType::NeedsFormatEncoding; - - if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardWrongDevice) - return EUIType::WrongDevice; - - if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardFull) - { - if (x6c_cardDriver->x10_state == EState::CardCheckFailed) - return EUIType::InsufficientSpaceBadCheck; - return EUIType::InsufficientSpaceOKCheck; - } - - if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardNon8KSectors) - return EUIType::IncompatibleCard; - - if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::FileCorrupted) - return EUIType::SaveCorrupt; - - if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardIOError) - return EUIType::CardDamaged; - - return EUIType::Empty; -} - -void CSaveGameScreen::SetUIText() -{ - x91_uiTextDirty = false; - - s32 msgA = -1; - s32 msgB = -1; - s32 opt0 = -1; - s32 opt1 = -1; - s32 opt2 = -1; - - std::u16string msgAStr; - std::u16string msgBStr; - std::u16string opt0Str; - std::u16string opt1Str; - std::u16string opt2Str; - std::u16string opt3Str; - - switch (x10_uiType) - { - case EUIType::BusyReading: - msgB = 24; // Reading - break; - case EUIType::BusyWriting: - msgB = 25; // Writing - break; - case EUIType::NoCardFound: - msgB = 0; // No card found - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - opt2 = -2; - opt2Str = u"Create Dolphin Card"; - break; - case EUIType::NeedsFormatBroken: - msgB = 1; // Needs format (card broken) - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - opt2 = 20; // Format - break; - case EUIType::NeedsFormatEncoding: - msgB = 2; // Needs format (wrong char set) - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - opt2 = 20; // Format - break; - case EUIType::CardDamaged: - msgB = 3; // Damaged - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - break; - case EUIType::WrongDevice: - msgB = 5; // Invalid device - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - break; - case EUIType::InsufficientSpaceOKCheck: - msgB = 6; // Insufficient space (completely filled) - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - opt2 = 19; // Manage memory card - break; - case EUIType::InsufficientSpaceBadCheck: - msgB = bool(x0_saveCtx) + 9; // Insufficient space A or B - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - opt2 = 19; // Manage memory card - break; - case EUIType::IncompatibleCard: - msgB = 7; // Incompatible card - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - break; - case EUIType::SaveCorrupt: - msgB = 4; // Save corrupt - opt0 = 22; // Delete corrupt file - opt1 = 17; // Continue without saving - opt2 = 18; // Retry - break; - case EUIType::StillInsufficientSpace: - if (x0_saveCtx == ESaveContext::InGame) - { - msgB = 10; // Insufficient space B - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - opt2 = 19; // Manage memory card - } - else - { - msgB = 9; // Insufficient space A - opt0 = 17; // Continue without saving - opt1 = 18; // Retry - opt2 = 19; // Manage memory card - } - break; - case EUIType::ProgressWillBeLost: - msgA = 28; // Warning - msgB = 11; // Progress will be lost - opt0 = 21; // Cancel - opt1 = 16; // Continue - break; - case EUIType::NotOriginalCard: - msgA = 28; // Warning - msgB = 12; // Not the original card - opt0 = x0_saveCtx == ESaveContext::InGame ? 21 : 17; // Cancel : continue without saving - opt1 = 16; // Continue - break; - case EUIType::AllDataWillBeLost: - msgA = 28; // Warning - msgB = 13; // All card data will be erased - opt0 = 16; // Continue - opt1 = 21; // Cancel - break; - case EUIType::SaveReady: - if (x0_saveCtx == ESaveContext::InGame) - { - msgB = 8; // Save progress? - opt0 = 14; // Yes - opt1 = 15; // No - } - break; - default: break; - } - - if (msgA > -1) - msgAStr = x38_strgMemoryCard->GetString(msgA); - if (msgB > -1) - msgBStr = x38_strgMemoryCard->GetString(msgB); - x54_textpane_message->TextSupport().SetText(msgAStr + msgBStr); - - if (opt0 > -1) - opt0Str = x38_strgMemoryCard->GetString(opt0); - x5c_textpane_choice0->TextSupport().SetText(opt0Str); - - if (opt1 > -1) - opt1Str = x38_strgMemoryCard->GetString(opt1); - x60_textpane_choice1->TextSupport().SetText(opt1Str); - - if (opt2 > -1) - opt2Str = x38_strgMemoryCard->GetString(opt2); - x64_textpane_choice2->TextSupport().SetText(opt2Str); - - x68_textpane_choice3->TextSupport().SetText(opt3Str); - - m_touchBar->SetUIOpts(opt0Str, opt1Str, opt2Str); - - x5c_textpane_choice0->SetIsSelectable(opt0 != -1); - x60_textpane_choice1->SetIsSelectable(opt1 != -1); - x64_textpane_choice2->SetIsSelectable(opt2 != -1); - x68_textpane_choice3->SetIsSelectable(false); - - x58_tablegroup_choices->SetIsActive(opt0 != -1 || opt1 != -1 || opt2 != -1); - x58_tablegroup_choices->SetUserSelection(0); - SetUIColors(); -} - -void CSaveGameScreen::SetUIColors() -{ - x58_tablegroup_choices->SetColors(zeus::CColor::skWhite, - zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); -} - -void CSaveGameScreen::Draw() const -{ - if (x50_loadedFrame) - x50_loadedFrame->Draw(CGuiWidgetDrawParms::Default); -} - -void CSaveGameScreen::ContinueWithoutSaving() -{ - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWin; - g_GameState->SetCardSerial(0); -} - -void CSaveGameScreen::DoAdvance(CGuiTableGroup* caller) -{ - int userSel = x58_tablegroup_choices->GetUserSelection(); - int sfx = -1; - - switch (x10_uiType) - { - case EUIType::NoCardFound: - case EUIType::CardDamaged: - case EUIType::WrongDevice: - case EUIType::IncompatibleCard: - if (userSel == 0) - { - /* Continue without saving */ - if (x0_saveCtx == ESaveContext::InGame) - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; - else - ContinueWithoutSaving(); - sfx = x8c_navBackSfx; - } - else if (userSel == 1) - { - /* Retry */ - ResetCardDriver(); - sfx = x84_navConfirmSfx; - } - else if (userSel == 2 && x10_uiType == EUIType::NoCardFound) - { - /* Create Dolphin Card */ - CMemoryCardSys::CreateDolphinCard(kabufuda::ECardSlot::SlotA); - ResetCardDriver(); - sfx = x84_navConfirmSfx; - } - break; - - case EUIType::NeedsFormatBroken: - case EUIType::NeedsFormatEncoding: - if (userSel == 0) - { - /* Continue without saving */ - if (x0_saveCtx == ESaveContext::InGame) - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; - else - ContinueWithoutSaving(); - sfx = x8c_navBackSfx; - } - else if (userSel == 1) - { - /* Retry */ - ResetCardDriver(); - sfx = x84_navConfirmSfx; - } - else if (userSel == 2) - { - /* Format */ - x10_uiType = EUIType::AllDataWillBeLost; - x91_uiTextDirty = true; - sfx = x84_navConfirmSfx; - } - break; - - case EUIType::InsufficientSpaceBadCheck: - case EUIType::InsufficientSpaceOKCheck: - if (userSel == 0) - { - /* Continue without saving */ - if (x0_saveCtx == ESaveContext::InGame) - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; - else - ContinueWithoutSaving(); - sfx = x8c_navBackSfx; - } - else if (userSel == 1) - { - /* Retry */ - ResetCardDriver(); - sfx = x84_navConfirmSfx; - } - else if (userSel == 2) - { - /* Manage memory card */ - if (x0_saveCtx == ESaveContext::InGame) - { - x10_uiType = EUIType::ProgressWillBeLost; - x91_uiTextDirty = true; - sfx = x84_navConfirmSfx; - } - else - static_cast(g_Main)->SetManageCard(true); - } - break; - - case EUIType::SaveCorrupt: - if (userSel == 0) - { - /* Delete corrupt file */ - x6c_cardDriver->StartFileDeleteBad(); - sfx = x84_navConfirmSfx; - } - else if (userSel == 1) - { - /* Continue without saving */ - if (x0_saveCtx == ESaveContext::InGame) - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; - else - ContinueWithoutSaving(); - sfx = x8c_navBackSfx; - } - else if (userSel == 2) - { - /* Retry */ - ResetCardDriver(); - sfx = x84_navConfirmSfx; - } - break; - - case EUIType::StillInsufficientSpace: - if (x0_saveCtx == ESaveContext::InGame) - { - if (userSel == 0) - { - /* Continue without saving */ - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; - sfx = x8c_navBackSfx; - } - else if (userSel == 1) - { - /* Retry */ - ResetCardDriver(); - sfx = x84_navConfirmSfx; - } - else if (userSel == 2) - { - /* Manage memory card */ - x10_uiType = EUIType::ProgressWillBeLost; - x91_uiTextDirty = true; - sfx = x84_navConfirmSfx; - } - } - else - { - if (userSel == 0) - { - /* Continue without saving */ - if (x93_inGame) - { - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; - sfx = x8c_navBackSfx; - } - else - { - x6c_cardDriver->ClearError(); - x92_savingDisabled = true; - sfx = x84_navConfirmSfx; - } - } - else if (userSel == 1) - { - /* Retry */ - ResetCardDriver(); - sfx = x84_navConfirmSfx; - } - else if (userSel == 2) - { - /* Manage memory card */ - static_cast(g_Main)->SetManageCard(true); - } - } - break; - - case EUIType::ProgressWillBeLost: - if (userSel == 1) - { - /* Continue */ - static_cast(g_Main)->SetManageCard(true); - } - else if (userSel == 0) - { - /* Cancel */ - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; - sfx = x8c_navBackSfx; - } - break; - - case EUIType::NotOriginalCard: - if (userSel == 1) - { - /* Continue */ - x8_serial = x6c_cardDriver->x28_cardSerial; - x10_uiType = EUIType::Empty; - x6c_cardDriver->IndexFiles(); - sfx = x84_navConfirmSfx; - } - else if (userSel == 0) - { - /* Cancel */ - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; - sfx = x8c_navBackSfx; - } - break; - - case EUIType::AllDataWillBeLost: - if (userSel == 0) - { - /* Continue */ - x6c_cardDriver->StartCardFormat(); - x10_uiType = EUIType::Empty; - sfx = x84_navConfirmSfx; - } - else if (userSel == 1) - { - /* Cancel */ - ResetCardDriver(); - sfx = x8c_navBackSfx; - } - break; - - case EUIType::SaveReady: - if (x0_saveCtx == ESaveContext::InGame) - { - if (userSel == 0) - { - /* Yes */ - x6c_cardDriver->BuildExistingFileSlot(g_GameState->GetFileIdx()); - x6c_cardDriver->StartFileCreateTransactional(); - sfx = x84_navConfirmSfx; - } - else if (userSel == 1) - { - /* No */ - x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; - sfx = x8c_navBackSfx; - } - } - - default: break; - } - - if (sfx >= 0) - CSfxManager::SfxStart(sfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); -} - -void CSaveGameScreen::DoSelectionChange(CGuiTableGroup* caller, int oldSel) -{ - SetUIColors(); - CSfxManager::SfxStart(x88_navMoveSfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); -} - -void CSaveGameScreen::ProcessUserInput(const CFinalInput& input) -{ - if (x50_loadedFrame) - { - x50_loadedFrame->ProcessUserInput(input); - - int tbOpt = m_touchBar->PopOption(); - if (tbOpt != -1) - { - x58_tablegroup_choices->SetUserSelection(tbOpt); - SetUIColors(); - DoAdvance(x58_tablegroup_choices); - } - } -} - -void CSaveGameScreen::StartGame(int idx) -{ - const CGameState::GameFileStateInfo* info = x6c_cardDriver->GetGameFileStateInfo(idx); - x6c_cardDriver->ExportPersistentOptions(); - x6c_cardDriver->BuildNewFileSlot(idx); - if (!info) - x6c_cardDriver->StartFileCreateTransactional(); - else - x80_iowRet = CIOWin::EMessageReturn::Exit; -} - -void CSaveGameScreen::SaveNESState() -{ - if (!x92_savingDisabled) - { - x90_needsDriverReset = true; + if (x6c_cardDriver->x10_state == EState::DriverClosed) { + if (x90_needsDriverReset) { + ResetCardDriver(); + x90_needsDriverReset = false; + } else + x80_iowRet = CIOWin::EMessageReturn::Exit; + } else if (x6c_cardDriver->x10_state == EState::CardCheckDone && x10_uiType != EUIType::NotOriginalCard) { + if (x6c_cardDriver->x28_cardSerial != x8_serial) { + if (x93_inGame) { + x10_uiType = EUIType::NotOriginalCard; + x91_uiTextDirty = true; + } else { x8_serial = x6c_cardDriver->x28_cardSerial; - x6c_cardDriver->StartFileCreateTransactional(); + x6c_cardDriver->IndexFiles(); + } + } else { + x6c_cardDriver->IndexFiles(); } + } else if (x6c_cardDriver->x10_state == EState::Ready) { + if (x90_needsDriverReset) + x6c_cardDriver->StartFileCreateTransactional(); + } + + if (x80_iowRet != CIOWin::EMessageReturn::Normal) + return x80_iowRet; + + EUIType oldTp = x10_uiType; + x10_uiType = SelectUIType(); + if (oldTp != x10_uiType || x91_uiTextDirty) + SetUIText(); + + if (x6c_cardDriver->x10_state == EState::NoCard) { + auto res = CMemoryCardSys::CardProbe(kabufuda::ECardSlot::SlotA); + if (res.x0_error == CMemoryCardSys::ECardResult::READY || res.x0_error == CMemoryCardSys::ECardResult::WRONGDEVICE) + ResetCardDriver(); + } else if (x6c_cardDriver->x10_state == EState::CardFormatted) { + ResetCardDriver(); + } else if (x6c_cardDriver->x10_state == EState::FileBad && x6c_cardDriver->x14_error == EError::FileMissing) { + x6c_cardDriver->StartFileCreate(); + } + + return CIOWin::EMessageReturn::Normal; } -void CSaveGameScreen::EraseGame(int idx) -{ - x6c_cardDriver->EraseFileSlot(idx); - x90_needsDriverReset = true; +bool CSaveGameScreen::PumpLoad() { + if (x50_loadedFrame) + return true; + if (!x14_txtrSaveBanner.IsLoaded()) + return false; + if (!x20_txtrSaveIcon0.IsLoaded()) + return false; + if (!x2c_txtrSaveIcon1.IsLoaded()) + return false; + if (!x38_strgMemoryCard.IsLoaded()) + return false; + for (TLockedToken& savw : x70_saveWorlds) + if (!savw.IsLoaded()) + return false; + if (!x44_frmeGenericMenu.IsLoaded()) + return false; + + x50_loadedFrame = x44_frmeGenericMenu.GetObj(); + x50_loadedFrame->SetAspectConstraint(1.78f); + x54_textpane_message = static_cast(x50_loadedFrame->FindWidget("textpane_message")); + x58_tablegroup_choices = static_cast(x50_loadedFrame->FindWidget("tablegroup_choices")); + x5c_textpane_choice0 = static_cast(x50_loadedFrame->FindWidget("textpane_choice0")); + x60_textpane_choice1 = static_cast(x50_loadedFrame->FindWidget("textpane_choice1")); + x64_textpane_choice2 = static_cast(x50_loadedFrame->FindWidget("textpane_choice2")); + x68_textpane_choice3 = static_cast(x50_loadedFrame->FindWidget("textpane_choice3")); + + x58_tablegroup_choices->SetMenuAdvanceCallback(std::bind(&CSaveGameScreen::DoAdvance, this, std::placeholders::_1)); + x58_tablegroup_choices->SetMenuSelectionChangeCallback( + std::bind(&CSaveGameScreen::DoSelectionChange, this, std::placeholders::_1, std::placeholders::_2)); + + if (x0_saveCtx == ESaveContext::InGame) + x6c_cardDriver->StartCardProbe(); + + x10_uiType = SelectUIType(); + SetUIText(); + return true; +} + +CSaveGameScreen::EUIType CSaveGameScreen::SelectUIType() const { + if (x6c_cardDriver->x10_state == EState::NoCard) + return EUIType::NoCardFound; + + switch (x10_uiType) { + case EUIType::ProgressWillBeLost: + case EUIType::NotOriginalCard: + case EUIType::AllDataWillBeLost: + return x10_uiType; + default: + break; + } + + if (CMemoryCardDriver::IsCardBusy(x6c_cardDriver->x10_state)) { + if (CMemoryCardDriver::IsCardWriting(x6c_cardDriver->x10_state)) + return EUIType::BusyWriting; + return EUIType::BusyReading; + } + + if (x6c_cardDriver->x10_state == EState::Ready) { + if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardStillFull) + return EUIType::StillInsufficientSpace; + return EUIType::SaveReady; + } + + if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardBroken) + return EUIType::NeedsFormatBroken; + + if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardWrongCharacterSet) + return EUIType::NeedsFormatEncoding; + + if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardWrongDevice) + return EUIType::WrongDevice; + + if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardFull) { + if (x6c_cardDriver->x10_state == EState::CardCheckFailed) + return EUIType::InsufficientSpaceBadCheck; + return EUIType::InsufficientSpaceOKCheck; + } + + if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardNon8KSectors) + return EUIType::IncompatibleCard; + + if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::FileCorrupted) + return EUIType::SaveCorrupt; + + if (x6c_cardDriver->x14_error == CMemoryCardDriver::EError::CardIOError) + return EUIType::CardDamaged; + + return EUIType::Empty; +} + +void CSaveGameScreen::SetUIText() { + x91_uiTextDirty = false; + + s32 msgA = -1; + s32 msgB = -1; + s32 opt0 = -1; + s32 opt1 = -1; + s32 opt2 = -1; + + std::u16string msgAStr; + std::u16string msgBStr; + std::u16string opt0Str; + std::u16string opt1Str; + std::u16string opt2Str; + std::u16string opt3Str; + + switch (x10_uiType) { + case EUIType::BusyReading: + msgB = 24; // Reading + break; + case EUIType::BusyWriting: + msgB = 25; // Writing + break; + case EUIType::NoCardFound: + msgB = 0; // No card found + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + opt2 = -2; + opt2Str = u"Create Dolphin Card"; + break; + case EUIType::NeedsFormatBroken: + msgB = 1; // Needs format (card broken) + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + opt2 = 20; // Format + break; + case EUIType::NeedsFormatEncoding: + msgB = 2; // Needs format (wrong char set) + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + opt2 = 20; // Format + break; + case EUIType::CardDamaged: + msgB = 3; // Damaged + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + break; + case EUIType::WrongDevice: + msgB = 5; // Invalid device + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + break; + case EUIType::InsufficientSpaceOKCheck: + msgB = 6; // Insufficient space (completely filled) + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + opt2 = 19; // Manage memory card + break; + case EUIType::InsufficientSpaceBadCheck: + msgB = bool(x0_saveCtx) + 9; // Insufficient space A or B + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + opt2 = 19; // Manage memory card + break; + case EUIType::IncompatibleCard: + msgB = 7; // Incompatible card + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + break; + case EUIType::SaveCorrupt: + msgB = 4; // Save corrupt + opt0 = 22; // Delete corrupt file + opt1 = 17; // Continue without saving + opt2 = 18; // Retry + break; + case EUIType::StillInsufficientSpace: + if (x0_saveCtx == ESaveContext::InGame) { + msgB = 10; // Insufficient space B + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + opt2 = 19; // Manage memory card + } else { + msgB = 9; // Insufficient space A + opt0 = 17; // Continue without saving + opt1 = 18; // Retry + opt2 = 19; // Manage memory card + } + break; + case EUIType::ProgressWillBeLost: + msgA = 28; // Warning + msgB = 11; // Progress will be lost + opt0 = 21; // Cancel + opt1 = 16; // Continue + break; + case EUIType::NotOriginalCard: + msgA = 28; // Warning + msgB = 12; // Not the original card + opt0 = x0_saveCtx == ESaveContext::InGame ? 21 : 17; // Cancel : continue without saving + opt1 = 16; // Continue + break; + case EUIType::AllDataWillBeLost: + msgA = 28; // Warning + msgB = 13; // All card data will be erased + opt0 = 16; // Continue + opt1 = 21; // Cancel + break; + case EUIType::SaveReady: + if (x0_saveCtx == ESaveContext::InGame) { + msgB = 8; // Save progress? + opt0 = 14; // Yes + opt1 = 15; // No + } + break; + default: + break; + } + + if (msgA > -1) + msgAStr = x38_strgMemoryCard->GetString(msgA); + if (msgB > -1) + msgBStr = x38_strgMemoryCard->GetString(msgB); + x54_textpane_message->TextSupport().SetText(msgAStr + msgBStr); + + if (opt0 > -1) + opt0Str = x38_strgMemoryCard->GetString(opt0); + x5c_textpane_choice0->TextSupport().SetText(opt0Str); + + if (opt1 > -1) + opt1Str = x38_strgMemoryCard->GetString(opt1); + x60_textpane_choice1->TextSupport().SetText(opt1Str); + + if (opt2 > -1) + opt2Str = x38_strgMemoryCard->GetString(opt2); + x64_textpane_choice2->TextSupport().SetText(opt2Str); + + x68_textpane_choice3->TextSupport().SetText(opt3Str); + + m_touchBar->SetUIOpts(opt0Str, opt1Str, opt2Str); + + x5c_textpane_choice0->SetIsSelectable(opt0 != -1); + x60_textpane_choice1->SetIsSelectable(opt1 != -1); + x64_textpane_choice2->SetIsSelectable(opt2 != -1); + x68_textpane_choice3->SetIsSelectable(false); + + x58_tablegroup_choices->SetIsActive(opt0 != -1 || opt1 != -1 || opt2 != -1); + x58_tablegroup_choices->SetUserSelection(0); + SetUIColors(); +} + +void CSaveGameScreen::SetUIColors() { + x58_tablegroup_choices->SetColors(zeus::CColor::skWhite, zeus::CColor{0.627450f, 0.627450f, 0.627450f, 0.784313f}); +} + +void CSaveGameScreen::Draw() const { + if (x50_loadedFrame) + x50_loadedFrame->Draw(CGuiWidgetDrawParms::Default); +} + +void CSaveGameScreen::ContinueWithoutSaving() { + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWin; + g_GameState->SetCardSerial(0); +} + +void CSaveGameScreen::DoAdvance(CGuiTableGroup* caller) { + int userSel = x58_tablegroup_choices->GetUserSelection(); + int sfx = -1; + + switch (x10_uiType) { + case EUIType::NoCardFound: + case EUIType::CardDamaged: + case EUIType::WrongDevice: + case EUIType::IncompatibleCard: + if (userSel == 0) { + /* Continue without saving */ + if (x0_saveCtx == ESaveContext::InGame) + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; + else + ContinueWithoutSaving(); + sfx = x8c_navBackSfx; + } else if (userSel == 1) { + /* Retry */ + ResetCardDriver(); + sfx = x84_navConfirmSfx; + } else if (userSel == 2 && x10_uiType == EUIType::NoCardFound) { + /* Create Dolphin Card */ + CMemoryCardSys::CreateDolphinCard(kabufuda::ECardSlot::SlotA); + ResetCardDriver(); + sfx = x84_navConfirmSfx; + } + break; + + case EUIType::NeedsFormatBroken: + case EUIType::NeedsFormatEncoding: + if (userSel == 0) { + /* Continue without saving */ + if (x0_saveCtx == ESaveContext::InGame) + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; + else + ContinueWithoutSaving(); + sfx = x8c_navBackSfx; + } else if (userSel == 1) { + /* Retry */ + ResetCardDriver(); + sfx = x84_navConfirmSfx; + } else if (userSel == 2) { + /* Format */ + x10_uiType = EUIType::AllDataWillBeLost; + x91_uiTextDirty = true; + sfx = x84_navConfirmSfx; + } + break; + + case EUIType::InsufficientSpaceBadCheck: + case EUIType::InsufficientSpaceOKCheck: + if (userSel == 0) { + /* Continue without saving */ + if (x0_saveCtx == ESaveContext::InGame) + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; + else + ContinueWithoutSaving(); + sfx = x8c_navBackSfx; + } else if (userSel == 1) { + /* Retry */ + ResetCardDriver(); + sfx = x84_navConfirmSfx; + } else if (userSel == 2) { + /* Manage memory card */ + if (x0_saveCtx == ESaveContext::InGame) { + x10_uiType = EUIType::ProgressWillBeLost; + x91_uiTextDirty = true; + sfx = x84_navConfirmSfx; + } else + static_cast(g_Main)->SetManageCard(true); + } + break; + + case EUIType::SaveCorrupt: + if (userSel == 0) { + /* Delete corrupt file */ + x6c_cardDriver->StartFileDeleteBad(); + sfx = x84_navConfirmSfx; + } else if (userSel == 1) { + /* Continue without saving */ + if (x0_saveCtx == ESaveContext::InGame) + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; + else + ContinueWithoutSaving(); + sfx = x8c_navBackSfx; + } else if (userSel == 2) { + /* Retry */ + ResetCardDriver(); + sfx = x84_navConfirmSfx; + } + break; + + case EUIType::StillInsufficientSpace: + if (x0_saveCtx == ESaveContext::InGame) { + if (userSel == 0) { + /* Continue without saving */ + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; + sfx = x8c_navBackSfx; + } else if (userSel == 1) { + /* Retry */ + ResetCardDriver(); + sfx = x84_navConfirmSfx; + } else if (userSel == 2) { + /* Manage memory card */ + x10_uiType = EUIType::ProgressWillBeLost; + x91_uiTextDirty = true; + sfx = x84_navConfirmSfx; + } + } else { + if (userSel == 0) { + /* Continue without saving */ + if (x93_inGame) { + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; + sfx = x8c_navBackSfx; + } else { + x6c_cardDriver->ClearError(); + x92_savingDisabled = true; + sfx = x84_navConfirmSfx; + } + } else if (userSel == 1) { + /* Retry */ + ResetCardDriver(); + sfx = x84_navConfirmSfx; + } else if (userSel == 2) { + /* Manage memory card */ + static_cast(g_Main)->SetManageCard(true); + } + } + break; + + case EUIType::ProgressWillBeLost: + if (userSel == 1) { + /* Continue */ + static_cast(g_Main)->SetManageCard(true); + } else if (userSel == 0) { + /* Cancel */ + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; + sfx = x8c_navBackSfx; + } + break; + + case EUIType::NotOriginalCard: + if (userSel == 1) { + /* Continue */ + x8_serial = x6c_cardDriver->x28_cardSerial; + x10_uiType = EUIType::Empty; + x6c_cardDriver->IndexFiles(); + sfx = x84_navConfirmSfx; + } else if (userSel == 0) { + /* Cancel */ + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; + sfx = x8c_navBackSfx; + } + break; + + case EUIType::AllDataWillBeLost: + if (userSel == 0) { + /* Continue */ + x6c_cardDriver->StartCardFormat(); + x10_uiType = EUIType::Empty; + sfx = x84_navConfirmSfx; + } else if (userSel == 1) { + /* Cancel */ + ResetCardDriver(); + sfx = x8c_navBackSfx; + } + break; + + case EUIType::SaveReady: + if (x0_saveCtx == ESaveContext::InGame) { + if (userSel == 0) { + /* Yes */ + x6c_cardDriver->BuildExistingFileSlot(g_GameState->GetFileIdx()); + x6c_cardDriver->StartFileCreateTransactional(); + sfx = x84_navConfirmSfx; + } else if (userSel == 1) { + /* No */ + x80_iowRet = CIOWin::EMessageReturn::RemoveIOWinAndExit; + sfx = x8c_navBackSfx; + } + } + + default: + break; + } + + if (sfx >= 0) + CSfxManager::SfxStart(sfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); +} + +void CSaveGameScreen::DoSelectionChange(CGuiTableGroup* caller, int oldSel) { + SetUIColors(); + CSfxManager::SfxStart(x88_navMoveSfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); +} + +void CSaveGameScreen::ProcessUserInput(const CFinalInput& input) { + if (x50_loadedFrame) { + x50_loadedFrame->ProcessUserInput(input); + + int tbOpt = m_touchBar->PopOption(); + if (tbOpt != -1) { + x58_tablegroup_choices->SetUserSelection(tbOpt); + SetUIColors(); + DoAdvance(x58_tablegroup_choices); + } + } +} + +void CSaveGameScreen::StartGame(int idx) { + const CGameState::GameFileStateInfo* info = x6c_cardDriver->GetGameFileStateInfo(idx); + x6c_cardDriver->ExportPersistentOptions(); + x6c_cardDriver->BuildNewFileSlot(idx); + if (!info) x6c_cardDriver->StartFileCreateTransactional(); + else + x80_iowRet = CIOWin::EMessageReturn::Exit; } -const CGameState::GameFileStateInfo* CSaveGameScreen::GetGameData(int idx) const -{ - return x6c_cardDriver->GetGameFileStateInfo(idx); +void CSaveGameScreen::SaveNESState() { + if (!x92_savingDisabled) { + x90_needsDriverReset = true; + x8_serial = x6c_cardDriver->x28_cardSerial; + x6c_cardDriver->StartFileCreateTransactional(); + } +} + +void CSaveGameScreen::EraseGame(int idx) { + x6c_cardDriver->EraseFileSlot(idx); + x90_needsDriverReset = true; + x6c_cardDriver->StartFileCreateTransactional(); +} + +const CGameState::GameFileStateInfo* CSaveGameScreen::GetGameData(int idx) const { + return x6c_cardDriver->GetGameFileStateInfo(idx); } CSaveGameScreen::CSaveGameScreen(ESaveContext saveCtx, u64 serial) -: x0_saveCtx(saveCtx), x8_serial(serial), m_touchBar(NewSaveUITouchBar()) -{ - x14_txtrSaveBanner = g_SimplePool->GetObj("TXTR_SaveBanner"); - x20_txtrSaveIcon0 = g_SimplePool->GetObj("TXTR_SaveIcon0"); - x2c_txtrSaveIcon1 = g_SimplePool->GetObj("TXTR_SaveIcon1"); - x38_strgMemoryCard = g_SimplePool->GetObj("STRG_MemoryCard"); - x44_frmeGenericMenu = g_SimplePool->GetObj("FRME_GenericMenu"); +: x0_saveCtx(saveCtx), x8_serial(serial), m_touchBar(NewSaveUITouchBar()) { + x14_txtrSaveBanner = g_SimplePool->GetObj("TXTR_SaveBanner"); + x20_txtrSaveIcon0 = g_SimplePool->GetObj("TXTR_SaveIcon0"); + x2c_txtrSaveIcon1 = g_SimplePool->GetObj("TXTR_SaveIcon1"); + x38_strgMemoryCard = g_SimplePool->GetObj("STRG_MemoryCard"); + x44_frmeGenericMenu = g_SimplePool->GetObj("FRME_GenericMenu"); - x6c_cardDriver = ConstructCardDriver(x0_saveCtx == ESaveContext::FrontEnd); + x6c_cardDriver = ConstructCardDriver(x0_saveCtx == ESaveContext::FrontEnd); - if (saveCtx == ESaveContext::InGame) - { - x84_navConfirmSfx = SFXui_advance; - x88_navMoveSfx = SFXui_table_selection_change; - x8c_navBackSfx = SFXui_table_change_mode; - } - x93_inGame = bool(saveCtx); + if (saveCtx == ESaveContext::InGame) { + x84_navConfirmSfx = SFXui_advance; + x88_navMoveSfx = SFXui_table_selection_change; + x8c_navBackSfx = SFXui_table_change_mode; + } + x93_inGame = bool(saveCtx); - x70_saveWorlds.reserve(g_MemoryCardSys->GetMemoryWorlds().size()); - for (const std::pair& wld : g_MemoryCardSys->GetMemoryWorlds()) - { - x70_saveWorlds.push_back( - g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), wld.second.GetSaveWorldAssetId()})); - } + x70_saveWorlds.reserve(g_MemoryCardSys->GetMemoryWorlds().size()); + for (const std::pair& wld : g_MemoryCardSys->GetMemoryWorlds()) { + x70_saveWorlds.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), wld.second.GetSaveWorldAssetId()})); + } } -std::unique_ptr CSaveGameScreen::ConstructCardDriver(bool importPersistent) -{ - return std::make_unique(kabufuda::ECardSlot::SlotA, - g_ResFactory->GetResourceIdByName("TXTR_SaveBanner")->id, - g_ResFactory->GetResourceIdByName("TXTR_SaveIcon0")->id, - g_ResFactory->GetResourceIdByName("TXTR_SaveIcon1")->id, importPersistent); +std::unique_ptr CSaveGameScreen::ConstructCardDriver(bool importPersistent) { + return std::make_unique(kabufuda::ECardSlot::SlotA, + g_ResFactory->GetResourceIdByName("TXTR_SaveBanner")->id, + g_ResFactory->GetResourceIdByName("TXTR_SaveIcon0")->id, + g_ResFactory->GetResourceIdByName("TXTR_SaveIcon1")->id, importPersistent); } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CSaveGameScreen.hpp b/Runtime/MP1/CSaveGameScreen.hpp index 23b599846..81f413d79 100644 --- a/Runtime/MP1/CSaveGameScreen.hpp +++ b/Runtime/MP1/CSaveGameScreen.hpp @@ -6,8 +6,7 @@ #include "CMemoryCardDriver.hpp" #include "CSaveGameScreenTouchBar.hpp" -namespace urde -{ +namespace urde { class CTexture; class CStringTable; class CGuiFrame; @@ -16,108 +15,98 @@ struct CFinalInput; class CGuiTextPane; class CGuiTableGroup; -namespace MP1 -{ +namespace MP1 { -enum class ESaveContext -{ - FrontEnd, - InGame -}; +enum class ESaveContext { FrontEnd, InGame }; -class CSaveGameScreen -{ +class CSaveGameScreen { public: - enum class EUIType - { - Empty = 0, - BusyReading = 1, - BusyWriting = 2, - NoCardFound = 3, - NeedsFormatBroken = 4, - NeedsFormatEncoding = 5, - CardDamaged = 6, - WrongDevice = 7, - InsufficientSpaceBadCheck = 8, - InsufficientSpaceOKCheck = 9, - IncompatibleCard = 10, - SaveCorrupt = 11, - StillInsufficientSpace = 12, - ProgressWillBeLost = 13, - NotOriginalCard = 14, - AllDataWillBeLost = 15, - SaveReady = 16 - }; + enum class EUIType { + Empty = 0, + BusyReading = 1, + BusyWriting = 2, + NoCardFound = 3, + NeedsFormatBroken = 4, + NeedsFormatEncoding = 5, + CardDamaged = 6, + WrongDevice = 7, + InsufficientSpaceBadCheck = 8, + InsufficientSpaceOKCheck = 9, + IncompatibleCard = 10, + SaveCorrupt = 11, + StillInsufficientSpace = 12, + ProgressWillBeLost = 13, + NotOriginalCard = 14, + AllDataWillBeLost = 15, + SaveReady = 16 + }; - bool IsHiddenFromFrontEnd() - { - switch (x10_uiType) - { - case EUIType::SaveReady: - case EUIType::Empty: - case EUIType::BusyReading: - case EUIType::BusyWriting: - return false; - default: - return true; - } + bool IsHiddenFromFrontEnd() { + switch (x10_uiType) { + case EUIType::SaveReady: + case EUIType::Empty: + case EUIType::BusyReading: + case EUIType::BusyWriting: + return false; + default: + return true; } + } private: - ESaveContext x0_saveCtx; - u64 x8_serial; - EUIType x10_uiType = EUIType::Empty; - TLockedToken x14_txtrSaveBanner; - TLockedToken x20_txtrSaveIcon0; - TLockedToken x2c_txtrSaveIcon1; - TLockedToken x38_strgMemoryCard; - TLockedToken x44_frmeGenericMenu; - CGuiFrame* x50_loadedFrame = nullptr; - CGuiTextPane* x54_textpane_message; - CGuiTableGroup* x58_tablegroup_choices; - CGuiTextPane* x5c_textpane_choice0; - CGuiTextPane* x60_textpane_choice1; - CGuiTextPane* x64_textpane_choice2; - CGuiTextPane* x68_textpane_choice3; - std::unique_ptr x6c_cardDriver; - std::vector> x70_saveWorlds; - CIOWin::EMessageReturn x80_iowRet = CIOWin::EMessageReturn::Normal; - u32 x84_navConfirmSfx = SFXui_frontend_save_confirm; - u32 x88_navMoveSfx = SFXui_frontend_save_move; - u32 x8c_navBackSfx = SFXui_frontend_save_back; - bool x90_needsDriverReset = false; - bool x91_uiTextDirty = false; - bool x92_savingDisabled = false; - bool x93_inGame; + ESaveContext x0_saveCtx; + u64 x8_serial; + EUIType x10_uiType = EUIType::Empty; + TLockedToken x14_txtrSaveBanner; + TLockedToken x20_txtrSaveIcon0; + TLockedToken x2c_txtrSaveIcon1; + TLockedToken x38_strgMemoryCard; + TLockedToken x44_frmeGenericMenu; + CGuiFrame* x50_loadedFrame = nullptr; + CGuiTextPane* x54_textpane_message; + CGuiTableGroup* x58_tablegroup_choices; + CGuiTextPane* x5c_textpane_choice0; + CGuiTextPane* x60_textpane_choice1; + CGuiTextPane* x64_textpane_choice2; + CGuiTextPane* x68_textpane_choice3; + std::unique_ptr x6c_cardDriver; + std::vector> x70_saveWorlds; + CIOWin::EMessageReturn x80_iowRet = CIOWin::EMessageReturn::Normal; + u32 x84_navConfirmSfx = SFXui_frontend_save_confirm; + u32 x88_navMoveSfx = SFXui_frontend_save_move; + u32 x8c_navBackSfx = SFXui_frontend_save_back; + bool x90_needsDriverReset = false; + bool x91_uiTextDirty = false; + bool x92_savingDisabled = false; + bool x93_inGame; - std::unique_ptr m_touchBar; + std::unique_ptr m_touchBar; - void ContinueWithoutSaving(); + void ContinueWithoutSaving(); public: - static std::unique_ptr ConstructCardDriver(bool inGame); - void ResetCardDriver(); - CIOWin::EMessageReturn Update(float dt); - void SetInGame(bool v) { x93_inGame = v; } - bool PumpLoad(); - EUIType SelectUIType() const; - void SetUIText(); - void SetUIColors(); - void Draw() const; + static std::unique_ptr ConstructCardDriver(bool inGame); + void ResetCardDriver(); + CIOWin::EMessageReturn Update(float dt); + void SetInGame(bool v) { x93_inGame = v; } + bool PumpLoad(); + EUIType SelectUIType() const; + void SetUIText(); + void SetUIColors(); + void Draw() const; - void DoAdvance(CGuiTableGroup* caller); - void DoSelectionChange(CGuiTableGroup* caller, int oldSel); + void DoAdvance(CGuiTableGroup* caller); + void DoSelectionChange(CGuiTableGroup* caller, int oldSel); - void ProcessUserInput(const CFinalInput& input); - void StartGame(int idx); - void SaveNESState(); - void EraseGame(int idx); - const CGameState::GameFileStateInfo* GetGameData(int idx) const; - EUIType GetUIType() const { return x10_uiType; } - bool IsSavingDisabled() const { return x92_savingDisabled; } - CSaveGameScreen(ESaveContext saveCtx, u64 serial); + void ProcessUserInput(const CFinalInput& input); + void StartGame(int idx); + void SaveNESState(); + void EraseGame(int idx); + const CGameState::GameFileStateInfo* GetGameData(int idx) const; + EUIType GetUIType() const { return x10_uiType; } + bool IsSavingDisabled() const { return x92_savingDisabled; } + CSaveGameScreen(ESaveContext saveCtx, u64 serial); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CSaveGameScreenTouchBar.cpp b/Runtime/MP1/CSaveGameScreenTouchBar.cpp index 64db9cb05..0e79b6c4c 100644 --- a/Runtime/MP1/CSaveGameScreenTouchBar.cpp +++ b/Runtime/MP1/CSaveGameScreenTouchBar.cpp @@ -1,18 +1,12 @@ #include "CSaveGameScreenTouchBar.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { int CSaveGameScreenTouchBar::PopOption() { return -1; } -void CSaveGameScreenTouchBar::SetUIOpts(std::u16string_view opt0, - std::u16string_view opt1, - std::u16string_view opt2) {} +void CSaveGameScreenTouchBar::SetUIOpts(std::u16string_view opt0, std::u16string_view opt1, std::u16string_view opt2) {} #ifndef __APPLE__ -std::unique_ptr NewSaveUITouchBar() -{ - return std::make_unique(); -} +std::unique_ptr NewSaveUITouchBar() { return std::make_unique(); } #endif -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CSaveGameScreenTouchBar.hpp b/Runtime/MP1/CSaveGameScreenTouchBar.hpp index 263218c65..f3a1ef205 100644 --- a/Runtime/MP1/CSaveGameScreenTouchBar.hpp +++ b/Runtime/MP1/CSaveGameScreenTouchBar.hpp @@ -4,20 +4,15 @@ #include #include -namespace urde::MP1 -{ +namespace urde::MP1 { -class CSaveGameScreenTouchBar -{ +class CSaveGameScreenTouchBar { public: - virtual ~CSaveGameScreenTouchBar() = default; - virtual int PopOption(); - virtual void SetUIOpts(std::u16string_view opt0, - std::u16string_view opt1, - std::u16string_view opt2); + virtual ~CSaveGameScreenTouchBar() = default; + virtual int PopOption(); + virtual void SetUIOpts(std::u16string_view opt0, std::u16string_view opt1, std::u16string_view opt2); }; std::unique_ptr NewSaveUITouchBar(); -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CSlideShow.cpp b/Runtime/MP1/CSlideShow.cpp index 7497d187d..8fc257218 100644 --- a/Runtime/MP1/CSlideShow.cpp +++ b/Runtime/MP1/CSlideShow.cpp @@ -2,185 +2,155 @@ #include "GameGlobalObjects.hpp" #include "Editor/ProjectManager.hpp" -namespace urde -{ +namespace urde { -CSlideShow::CSlideShow() -: CIOWin("SlideShow"), x5c_slideA(*this), x90_slideB(*this) -{ - x130_ = g_tweakSlideShow->GetX54(); - x134_24_ = true; - x134_30_ = true; - x135_24_ = true; +CSlideShow::CSlideShow() : CIOWin("SlideShow"), x5c_slideA(*this), x90_slideB(*this) { + x130_ = g_tweakSlideShow->GetX54(); + x134_24_ = true; + x134_30_ = true; + x135_24_ = true; - const SObjectTag* font = g_ResFactory->GetResourceIdByName(g_tweakSlideShow->GetFont()); - if (font) - { - CGuiTextProperties propsA(false, true, EJustification::Center, EVerticalJustification::Bottom); - xc4_textA = std::make_unique(font->id, propsA, - g_tweakSlideShow->GetFontColor(), - g_tweakSlideShow->GetOutlineColor(), - zeus::CColor::skWhite, 640, 480, g_SimplePool, - CGuiWidget::EGuiModelDrawFlags::Alpha); + const SObjectTag* font = g_ResFactory->GetResourceIdByName(g_tweakSlideShow->GetFont()); + if (font) { + CGuiTextProperties propsA(false, true, EJustification::Center, EVerticalJustification::Bottom); + xc4_textA = std::make_unique(font->id, propsA, g_tweakSlideShow->GetFontColor(), + g_tweakSlideShow->GetOutlineColor(), zeus::CColor::skWhite, 640, 480, + g_SimplePool, CGuiWidget::EGuiModelDrawFlags::Alpha); - CGuiTextProperties propsB(false, true, EJustification::Right, EVerticalJustification::Bottom); - xc8_textB = std::make_unique(font->id, propsB, - g_tweakSlideShow->GetFontColor(), - g_tweakSlideShow->GetOutlineColor(), - zeus::CColor::skWhite, 640, 480, g_SimplePool, - CGuiWidget::EGuiModelDrawFlags::Alpha); - } + CGuiTextProperties propsB(false, true, EJustification::Right, EVerticalJustification::Bottom); + xc8_textB = std::make_unique(font->id, propsB, g_tweakSlideShow->GetFontColor(), + g_tweakSlideShow->GetOutlineColor(), zeus::CColor::skWhite, 640, 480, + g_SimplePool, CGuiWidget::EGuiModelDrawFlags::Alpha); + } - xf8_stickTextures.reserve(18); - x108_buttonTextures.reserve(8); - SObjectTag txtrTag(FOURCC('TXTR'), 0); - for (int i=0 ; i<9 ; ++i) - { - txtrTag.id = g_tweakPlayerRes->x24_lStick[i]; - xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); - } - for (int i=0 ; i<9 ; ++i) - { - txtrTag.id = g_tweakPlayerRes->x4c_cStick[i]; - xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); - } - for (int i=0 ; i<2 ; ++i) - { - txtrTag.id = g_tweakPlayerRes->x74_lTrigger[i]; - xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); - } - for (int i=0 ; i<2 ; ++i) - { - txtrTag.id = g_tweakPlayerRes->x80_rTrigger[i]; - xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); - } - for (int i=0 ; i<2 ; ++i) - { - txtrTag.id = g_tweakPlayerRes->xa4_bButton[i]; - xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); - } - for (int i=0 ; i<2 ; ++i) - { - txtrTag.id = g_tweakPlayerRes->xbc_yButton[i]; - xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); - } + xf8_stickTextures.reserve(18); + x108_buttonTextures.reserve(8); + SObjectTag txtrTag(FOURCC('TXTR'), 0); + for (int i = 0; i < 9; ++i) { + txtrTag.id = g_tweakPlayerRes->x24_lStick[i]; + xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); + } + for (int i = 0; i < 9; ++i) { + txtrTag.id = g_tweakPlayerRes->x4c_cStick[i]; + xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); + } + for (int i = 0; i < 2; ++i) { + txtrTag.id = g_tweakPlayerRes->x74_lTrigger[i]; + xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); + } + for (int i = 0; i < 2; ++i) { + txtrTag.id = g_tweakPlayerRes->x80_rTrigger[i]; + xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); + } + for (int i = 0; i < 2; ++i) { + txtrTag.id = g_tweakPlayerRes->xa4_bButton[i]; + xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); + } + for (int i = 0; i < 2; ++i) { + txtrTag.id = g_tweakPlayerRes->xbc_yButton[i]; + xf8_stickTextures.push_back(g_SimplePool->GetObj(txtrTag)); + } } -bool CSlideShow::LoadTXTRDep(std::string_view name) -{ - const SObjectTag* dgrpTag = g_ResFactory->GetResourceIdByName(name); - if (dgrpTag && dgrpTag->type == FOURCC('DGRP')) - { - x18_galleryTXTRDeps.push_back(g_SimplePool->GetObj(*dgrpTag)); - return true; - } - return false; -} - -bool CSlideShow::AreAllDepsLoaded(const std::vector>& deps) -{ - for (const TLockedToken& token : deps) - { - if (!token.IsLoaded()) - return false; - } +bool CSlideShow::LoadTXTRDep(std::string_view name) { + const SObjectTag* dgrpTag = g_ResFactory->GetResourceIdByName(name); + if (dgrpTag && dgrpTag->type == FOURCC('DGRP')) { + x18_galleryTXTRDeps.push_back(g_SimplePool->GetObj(*dgrpTag)); return true; + } + return false; } -CIOWin::EMessageReturn CSlideShow::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - switch (msg.GetType()) - { - case EArchMsgType::TimerTick: - { - if (x134_29_) - return EMessageReturn::RemoveIOWinAndExit; +bool CSlideShow::AreAllDepsLoaded(const std::vector>& deps) { + for (const TLockedToken& token : deps) { + if (!token.IsLoaded()) + return false; + } + return true; +} - //float dt = MakeMsg::GetParmTimerTick(msg).x4_parm; +CIOWin::EMessageReturn CSlideShow::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + switch (msg.GetType()) { + case EArchMsgType::TimerTick: { + if (x134_29_) + return EMessageReturn::RemoveIOWinAndExit; - switch (x14_phase) - { - case Phase::Zero: - { - //if (!g_resLoader->AreAllPaksLoaded()) - //{ - // g_resLoader->AsyncIdlePakLoading(); - // return EMessageReturn::Exit; - //} - x14_phase = Phase::One; - } - case Phase::One: - { - if (x18_galleryTXTRDeps.empty()) - { - x18_galleryTXTRDeps.reserve(5); - for (int i=1 ; true ; ++i) - { - std::string depResName = hecl::Format("Gallery%02d_DGRP", i); - if (!LoadTXTRDep(depResName)) - break; - } - LoadTXTRDep("GalleryAssets_DGRP"); - } - if (!AreAllDepsLoaded(x18_galleryTXTRDeps)) - return EMessageReturn::Exit; + // float dt = MakeMsg::GetParmTimerTick(msg).x4_parm; - x14_phase = Phase::Three; - } - case Phase::Two: - case Phase::Three: - { - - } - case Phase::Four: - case Phase::Five: - default: break; - } - - break; + switch (x14_phase) { + case Phase::Zero: { + // if (!g_resLoader->AreAllPaksLoaded()) + //{ + // g_resLoader->AsyncIdlePakLoading(); + // return EMessageReturn::Exit; + //} + x14_phase = Phase::One; } - case EArchMsgType::UserInput: - default: break; + case Phase::One: { + if (x18_galleryTXTRDeps.empty()) { + x18_galleryTXTRDeps.reserve(5); + for (int i = 1; true; ++i) { + std::string depResName = hecl::Format("Gallery%02d_DGRP", i); + if (!LoadTXTRDep(depResName)) + break; + } + LoadTXTRDep("GalleryAssets_DGRP"); + } + if (!AreAllDepsLoaded(x18_galleryTXTRDeps)) + return EMessageReturn::Exit; + + x14_phase = Phase::Three; + } + case Phase::Two: + case Phase::Three: { + } + case Phase::Four: + case Phase::Five: + default: + break; } - return EMessageReturn::Exit; + break; + } + case EArchMsgType::UserInput: + default: + break; + } + + return EMessageReturn::Exit; } -void CSlideShow::SSlideData::Draw() const -{ - if (!IsLoaded()) - return; +void CSlideShow::SSlideData::Draw() const { + if (!IsLoaded()) + return; - zeus::CRectangle rect; - const_cast(*m_texQuad).draw(x30_mulColor, 1.f, rect); + zeus::CRectangle rect; + const_cast(*m_texQuad).draw(x30_mulColor, 1.f, rect); - zeus::CVector2f centeredOffset((x28_canvasSize.x() - m_texQuad->GetTex()->GetWidth()) * 0.5f, - (x28_canvasSize.y() - m_texQuad->GetTex()->GetHeight()) * 0.5f); + zeus::CVector2f centeredOffset((x28_canvasSize.x() - m_texQuad->GetTex()->GetWidth()) * 0.5f, + (x28_canvasSize.y() - m_texQuad->GetTex()->GetHeight()) * 0.5f); } -void CSlideShow::Draw() const -{ - if (x14_phase == Phase::Five) - { - x5c_slideA.Draw(); - x90_slideB.Draw(); - } +void CSlideShow::Draw() const { + if (x14_phase == Phase::Five) { + x5c_slideA.Draw(); + x90_slideB.Draw(); + } } -u32 CSlideShow::SlideShowGalleryFlags() -{ - u32 ret = 0; - if (!g_GameState) - return ret; - if (g_GameState->SystemOptions().GetLogScanPercent() >= 50) - ret |= 1; - if (g_GameState->SystemOptions().GetLogScanPercent() == 100) - ret |= 2; - if (g_GameState->SystemOptions().GetPlayerBeatHardMode()) - ret |= 4; - if (g_GameState->SystemOptions().GetAllItemsCollected()) - ret |= 8; +u32 CSlideShow::SlideShowGalleryFlags() { + u32 ret = 0; + if (!g_GameState) return ret; + if (g_GameState->SystemOptions().GetLogScanPercent() >= 50) + ret |= 1; + if (g_GameState->SystemOptions().GetLogScanPercent() == 100) + ret |= 2; + if (g_GameState->SystemOptions().GetPlayerBeatHardMode()) + ret |= 4; + if (g_GameState->SystemOptions().GetAllItemsCollected()) + ret |= 8; + return ret; } -} +} // namespace urde diff --git a/Runtime/MP1/CSlideShow.hpp b/Runtime/MP1/CSlideShow.hpp index 52bfec149..ffdde950b 100644 --- a/Runtime/MP1/CSlideShow.hpp +++ b/Runtime/MP1/CSlideShow.hpp @@ -7,127 +7,104 @@ #include "Graphics/Shaders/CTexturedQuadFilter.hpp" #include "Audio/CSfxManager.hpp" -namespace urde -{ +namespace urde { class CTexture; class CDependencyGroup; -class CSlideShow : public CIOWin -{ +class CSlideShow : public CIOWin { public: - enum class Phase - { - Zero, - One, - Two, - Three, - Four, - Five - }; - struct SSlideData - { - CSlideShow& x0_parent; - u32 x4_ = -1; - u32 x8_ = -1; + enum class Phase { Zero, One, Two, Three, Four, Five }; + struct SSlideData { + CSlideShow& x0_parent; + u32 x4_ = -1; + u32 x8_ = -1; - std::experimental::optional m_texQuad; - zeus::CVector2f x18_vpOffset; - zeus::CVector2f x20_vpSize; - zeus::CVector2f x28_canvasSize; - zeus::CColor x30_mulColor = zeus::CColor::skWhite; + std::experimental::optional m_texQuad; + zeus::CVector2f x18_vpOffset; + zeus::CVector2f x20_vpSize; + zeus::CVector2f x28_canvasSize; + zeus::CColor x30_mulColor = zeus::CColor::skWhite; - SSlideData(CSlideShow& parent) : x0_parent(parent) - { - x30_mulColor.a() = 0.f; - } + SSlideData(CSlideShow& parent) : x0_parent(parent) { x30_mulColor.a() = 0.f; } - void SetTexture(const TLockedToken& tex) - { - m_texQuad.emplace(EFilterType::Blend, tex); - } - bool IsLoaded() const - { - return m_texQuad && m_texQuad->GetTex().IsLoaded(); - } - void Draw() const; - }; + void SetTexture(const TLockedToken& tex) { m_texQuad.emplace(EFilterType::Blend, tex); } + bool IsLoaded() const { return m_texQuad && m_texQuad->GetTex().IsLoaded(); } + void Draw() const; + }; private: - Phase x14_phase = Phase::Zero; - std::vector> x18_galleryTXTRDeps; - /* - u32 x2c_ = 0; - u32 x30_ = 0; - u32 x34_ = 0; - u32 x38_ = 0; - u32 x3c_ = 0; - u32 x40_ = 0; - u32 x44_ = 0; - u32 x48_ = -1; - float x4c_ = 0.f; - float x50_ = 0.f; - float x54_ = 0.f; - float x58_ = 0.f; - */ + Phase x14_phase = Phase::Zero; + std::vector> x18_galleryTXTRDeps; + /* + u32 x2c_ = 0; + u32 x30_ = 0; + u32 x34_ = 0; + u32 x38_ = 0; + u32 x3c_ = 0; + u32 x40_ = 0; + u32 x44_ = 0; + u32 x48_ = -1; + float x4c_ = 0.f; + float x50_ = 0.f; + float x54_ = 0.f; + float x58_ = 0.f; + */ - SSlideData x5c_slideA; - SSlideData x90_slideB; + SSlideData x5c_slideA; + SSlideData x90_slideB; - std::unique_ptr xc4_textA; - std::unique_ptr xc8_textB; - /* - u32 xcc_ = 0; - u32 xd4_ = 0; - u32 xd8_ = 0; - u32 xdc_ = 0; - u32 xe0_ = 0; - */ - CSfxHandle xe4_; - /* - u32 xe8_ = 0; - u32 xec_ = 0; - u32 xf0_ = 0; - u32 xf4_ = 0; - */ - std::vector> xf8_stickTextures; /* (9 LStick, 9 CStick) */ - std::vector x108_buttonTextures; /* (2L, 2R, 2B, 2Y) */ - /* - u32 x11c_ = 0; - u32 x120_ = 0; - u32 x124_ = 0; - float x128_ = 32.f; - float x12c_ = 32.f; - */ - float x130_; + std::unique_ptr xc4_textA; + std::unique_ptr xc8_textB; + /* + u32 xcc_ = 0; + u32 xd4_ = 0; + u32 xd8_ = 0; + u32 xdc_ = 0; + u32 xe0_ = 0; + */ + CSfxHandle xe4_; + /* + u32 xe8_ = 0; + u32 xec_ = 0; + u32 xf0_ = 0; + u32 xf4_ = 0; + */ + std::vector> xf8_stickTextures; /* (9 LStick, 9 CStick) */ + std::vector x108_buttonTextures; /* (2L, 2R, 2B, 2Y) */ + /* + u32 x11c_ = 0; + u32 x120_ = 0; + u32 x124_ = 0; + float x128_ = 32.f; + float x12c_ = 32.f; + */ + float x130_; - union - { - struct - { - bool x134_24_ : 1; - bool x134_25_ : 1; - bool x134_26_ : 1; - bool x134_27_ : 1; - bool x134_28_disableInput : 1; - bool x134_29_ : 1; - bool x134_30_ : 1; - bool x134_31_ : 1; - bool x135_24_ : 1; - }; - u32 dummy = 0; + union { + struct { + bool x134_24_ : 1; + bool x134_25_ : 1; + bool x134_26_ : 1; + bool x134_27_ : 1; + bool x134_28_disableInput : 1; + bool x134_29_ : 1; + bool x134_30_ : 1; + bool x134_31_ : 1; + bool x135_24_ : 1; }; + u32 dummy = 0; + }; - bool LoadTXTRDep(std::string_view name); - static bool AreAllDepsLoaded(const std::vector>& deps); + bool LoadTXTRDep(std::string_view name); + static bool AreAllDepsLoaded(const std::vector>& deps); public: - CSlideShow(); - EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); - bool GetIsContinueDraw() const {return false;} - void Draw() const; + CSlideShow(); + EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); + bool GetIsContinueDraw() const { return false; } + void Draw() const; - static u32 SlideShowGalleryFlags(); + static u32 SlideShowGalleryFlags(); }; -} - +} // namespace urde diff --git a/Runtime/MP1/CSplashScreen.cpp b/Runtime/MP1/CSplashScreen.cpp index 3e5acea27..316071f77 100644 --- a/Runtime/MP1/CSplashScreen.cpp +++ b/Runtime/MP1/CSplashScreen.cpp @@ -5,93 +5,63 @@ #include "CArchitectureMessage.hpp" #include "zeus/CColor.hpp" -namespace urde -{ +namespace urde { extern CSimplePool* g_simplePool; -namespace MP1 -{ -static const char* SplashTextures[] = -{ - "TXTR_NintendLogo", - "TXTR_RetroLogo", - "TXTR_DolbyLogo" -}; +namespace MP1 { +static const char* SplashTextures[] = {"TXTR_NintendLogo", "TXTR_RetroLogo", "TXTR_DolbyLogo"}; -CSplashScreen::CSplashScreen(ESplashScreen splash) - : CIOWin("SplashScreen"), - x14_splashScreen(splash) -{ - x28_texture = g_simplePool->GetObj(SplashTextures[(u32)splash]); +CSplashScreen::CSplashScreen(ESplashScreen splash) : CIOWin("SplashScreen"), x14_splashScreen(splash) { + x28_texture = g_simplePool->GetObj(SplashTextures[(u32)splash]); } -CIOWin::EMessageReturn CSplashScreen::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - if (msg.GetType() == EArchMsgType::UserInput && x25_) - { - CFinalInput input = MakeMsg::GetParmUserInput(msg).x4_parm; - if (x20_phase == 1) - { - if (input.x8_anaLeftX <= -0.7f || input.x2d_b26_DPLeft) - { - x24_progressiveEnabled = true; - x1c_ = 10.f; - } - else if (input.x8_anaLeftX >= 0.7f || input.x2d_b24_DPRight) - { - x24_progressiveEnabled = false; - x1c_ = 10.f; - } - else if (input.x2d_b28_PA || input.x2d_b27_Start) - { - //CGraphics::SetProgressiveMode(x24_progressiveEnabled); - x1c_ = 5.f; - x20_phase = 2; - } - } - else if (x20_phase == 2) - { - if (input.x2d_b28_PA || input.x2e_b31_PStart) - x1c_ = 0.f; - } +CIOWin::EMessageReturn CSplashScreen::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + if (msg.GetType() == EArchMsgType::UserInput && x25_) { + CFinalInput input = MakeMsg::GetParmUserInput(msg).x4_parm; + if (x20_phase == 1) { + if (input.x8_anaLeftX <= -0.7f || input.x2d_b26_DPLeft) { + x24_progressiveEnabled = true; + x1c_ = 10.f; + } else if (input.x8_anaLeftX >= 0.7f || input.x2d_b24_DPRight) { + x24_progressiveEnabled = false; + x1c_ = 10.f; + } else if (input.x2d_b28_PA || input.x2d_b27_Start) { + // CGraphics::SetProgressiveMode(x24_progressiveEnabled); + x1c_ = 5.f; + x20_phase = 2; + } + } else if (x20_phase == 2) { + if (input.x2d_b28_PA || input.x2e_b31_PStart) + x1c_ = 0.f; } - else if (msg.GetType() == EArchMsgType::TimerTick) - { - if (!x25_) - { - if (x28_texture) - x25_ = true; - } - else - { - } + } else if (msg.GetType() == EArchMsgType::TimerTick) { + if (!x25_) { + if (x28_texture) + x25_ = true; + } else { } + } - return EMessageReturn::Exit; + return EMessageReturn::Exit; } -void CSplashScreen::Draw() const -{ - zeus::CColor col; - if (x14_splashScreen == ESplashScreen::Nintendo) - col = zeus::CColor(0.86f, 0.f, 0.f); +void CSplashScreen::Draw() const { + zeus::CColor col; + if (x14_splashScreen == ESplashScreen::Nintendo) + col = zeus::CColor(0.86f, 0.f, 0.f); - float tmp = x18_; - if (tmp <= 1.5f) - { - if (x18_ <= 0.5f) - tmp /= 0.5f; - else - tmp = 1.0f; - } + float tmp = x18_; + if (tmp <= 1.5f) { + if (x18_ <= 0.5f) + tmp /= 0.5f; else - { - tmp -= 1.5f; - tmp = 1.0f - (tmp / 1.5f); - } - - CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); + tmp = 1.0f; + } else { + tmp -= 1.5f; + tmp = 1.0f - (tmp / 1.5f); + } + CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); } -} -} +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CSplashScreen.hpp b/Runtime/MP1/CSplashScreen.hpp index f3100a03c..b0f8a27eb 100644 --- a/Runtime/MP1/CSplashScreen.hpp +++ b/Runtime/MP1/CSplashScreen.hpp @@ -3,33 +3,25 @@ #include "CIOWin.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class CTexture; -namespace MP1 -{ -class CSplashScreen : public CIOWin -{ +namespace MP1 { +class CSplashScreen : public CIOWin { public: - enum ESplashScreen - { - NintendoLogo, - RetroLogo, - DolbyLogo - }; + enum ESplashScreen { NintendoLogo, RetroLogo, DolbyLogo }; + private: - ESplashScreen x14_splashScreen; - float x18_ = 2.0; - float x1c_ = 0.0; - u32 x20_phase = 0; - bool x24_progressiveEnabled = true; - bool x25_ = false; - TLockedToken x28_texture; + ESplashScreen x14_splashScreen; + float x18_ = 2.0; + float x1c_ = 0.0; + u32 x20_phase = 0; + bool x24_progressiveEnabled = true; + bool x25_ = false; + TLockedToken x28_texture; public: - CSplashScreen(ESplashScreen splash); - EMessageReturn OnMessage(const CArchitectureMessage &, CArchitectureQueue &); - void Draw() const; + CSplashScreen(ESplashScreen splash); + EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); + void Draw() const; }; -} - +} // namespace MP1 diff --git a/Runtime/MP1/CStateSetterFlow.cpp b/Runtime/MP1/CStateSetterFlow.cpp index 58d97ac8d..d456a5fd5 100644 --- a/Runtime/MP1/CStateSetterFlow.cpp +++ b/Runtime/MP1/CStateSetterFlow.cpp @@ -2,56 +2,46 @@ #include "CArchitectureMessage.hpp" #include "GameGlobalObjects.hpp" #include "MP1.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CStateSetterFlow::CStateSetterFlow() -: CIOWin("") {} +CStateSetterFlow::CStateSetterFlow() : CIOWin("") {} -CIOWin::EMessageReturn CStateSetterFlow::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) -{ - if (msg.GetType() == EArchMsgType::TimerTick) - { - MP1::CMain* m = static_cast(g_Main); +CIOWin::EMessageReturn CStateSetterFlow::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) { + if (msg.GetType() == EArchMsgType::TimerTick) { + MP1::CMain* m = static_cast(g_Main); - if (m->m_warpWorldIdx > -1) - { - CResLoader* loader = g_ResFactory->GetResLoader(); - CAssetId worldId; - for (const auto& pak : loader->GetPaks()) - { - if (*(pak->GetPath().end() - 6) == '0' + m->m_warpWorldIdx) - { - worldId = pak->GetMLVLId(); - break; - } - } - - if (worldId.IsValid()) - { - m->ResetGameState(); - - g_GameState->SetCurrentWorldId(worldId); - CWorldLayerState& layers = *g_GameState->StateForWorld(worldId).GetLayerState(); - if (m->m_warpAreaId < layers.GetAreaCount()) - { - g_GameState->StateForWorld(worldId).SetAreaId(m->m_warpAreaId); - if (m->m_warpLayerBits) - { - for (u32 i = 0; i < layers.GetAreaLayerCount(m->m_warpAreaId); ++i) - layers.SetLayerActive(m->m_warpAreaId, i, ((m->m_warpLayerBits >> i) & 1) != 0); - } - } - g_GameState->GameOptions().ResetToDefaults(); - g_GameState->WriteBackupBuf(); - return EMessageReturn::RemoveIOWinAndExit; - } + if (m->m_warpWorldIdx > -1) { + CResLoader* loader = g_ResFactory->GetResLoader(); + CAssetId worldId; + for (const auto& pak : loader->GetPaks()) { + if (*(pak->GetPath().end() - 6) == '0' + m->m_warpWorldIdx) { + worldId = pak->GetMLVLId(); + break; } + } - m->RefreshGameState(); + if (worldId.IsValid()) { + m->ResetGameState(); + + g_GameState->SetCurrentWorldId(worldId); + CWorldLayerState& layers = *g_GameState->StateForWorld(worldId).GetLayerState(); + if (m->m_warpAreaId < layers.GetAreaCount()) { + g_GameState->StateForWorld(worldId).SetAreaId(m->m_warpAreaId); + if (m->m_warpLayerBits) { + for (u32 i = 0; i < layers.GetAreaLayerCount(m->m_warpAreaId); ++i) + layers.SetLayerActive(m->m_warpAreaId, i, ((m->m_warpLayerBits >> i) & 1) != 0); + } + } + g_GameState->GameOptions().ResetToDefaults(); + g_GameState->WriteBackupBuf(); return EMessageReturn::RemoveIOWinAndExit; + } } - return EMessageReturn::Exit; + + m->RefreshGameState(); + return EMessageReturn::RemoveIOWinAndExit; + } + return EMessageReturn::Exit; } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/CStateSetterFlow.hpp b/Runtime/MP1/CStateSetterFlow.hpp index 7908b6fcf..6aaae2cb2 100644 --- a/Runtime/MP1/CStateSetterFlow.hpp +++ b/Runtime/MP1/CStateSetterFlow.hpp @@ -2,15 +2,12 @@ #include "CIOWin.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class CStateSetterFlow : public CIOWin -{ +class CStateSetterFlow : public CIOWin { public: - CStateSetterFlow(); - EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); + CStateSetterFlow(); + EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/CTweaks.cpp b/Runtime/MP1/CTweaks.cpp index 18aafdd0b..ae5e1212a 100644 --- a/Runtime/MP1/CTweaks.cpp +++ b/Runtime/MP1/CTweaks.cpp @@ -20,115 +20,110 @@ #include "DataSpec/DNAMP1/Tweaks/CTweakPlayerGun.hpp" #include "World/CPlayerCameraBob.hpp" -namespace urde -{ +namespace urde { -namespace MP1 -{ +namespace MP1 { static logvisor::Module Log("MP1::CTweaks"); -void CTweaks::RegisterTweaks(hecl::CVarManager* cvarMgr) -{ - std::experimental::optional strm; - const SObjectTag* tag; +void CTweaks::RegisterTweaks(hecl::CVarManager* cvarMgr) { + std::experimental::optional strm; + const SObjectTag* tag; - /* Particle */ - tag = g_ResFactory->GetResourceIdByName("Particle"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakParticle = new DataSpec::DNAMP1::CTweakParticle(*strm); - g_tweakParticle->initCVars(cvarMgr); + /* Particle */ + tag = g_ResFactory->GetResourceIdByName("Particle"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakParticle = new DataSpec::DNAMP1::CTweakParticle(*strm); + g_tweakParticle->initCVars(cvarMgr); - /* Player */ - tag = g_ResFactory->GetResourceIdByName("Player"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakPlayer = new DataSpec::DNAMP1::CTweakPlayer(*strm); - g_tweakPlayer->initCVars(cvarMgr); + /* Player */ + tag = g_ResFactory->GetResourceIdByName("Player"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakPlayer = new DataSpec::DNAMP1::CTweakPlayer(*strm); + g_tweakPlayer->initCVars(cvarMgr); - /* CameraBob */ - tag = g_ResFactory->GetResourceIdByName("CameraBob"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - CPlayerCameraBob::ReadTweaks(*strm); + /* CameraBob */ + tag = g_ResFactory->GetResourceIdByName("CameraBob"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + CPlayerCameraBob::ReadTweaks(*strm); - /* Ball */ - tag = g_ResFactory->GetResourceIdByName("Ball"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakBall = new DataSpec::DNAMP1::CTweakBall(*strm); - g_tweakBall->initCVars(cvarMgr); + /* Ball */ + tag = g_ResFactory->GetResourceIdByName("Ball"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakBall = new DataSpec::DNAMP1::CTweakBall(*strm); + g_tweakBall->initCVars(cvarMgr); - /* PlayerGun */ - tag = g_ResFactory->GetResourceIdByName("PlayerGun"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakPlayerGun = new DataSpec::DNAMP1::CTweakPlayerGun(*strm); - g_tweakPlayerGun->initCVars(cvarMgr); + /* PlayerGun */ + tag = g_ResFactory->GetResourceIdByName("PlayerGun"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakPlayerGun = new DataSpec::DNAMP1::CTweakPlayerGun(*strm); + g_tweakPlayerGun->initCVars(cvarMgr); - /* Targeting */ - tag = g_ResFactory->GetResourceIdByName("Targeting"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakTargeting = new DataSpec::DNAMP1::CTweakTargeting(*strm); - g_tweakTargeting->initCVars(cvarMgr); + /* Targeting */ + tag = g_ResFactory->GetResourceIdByName("Targeting"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakTargeting = new DataSpec::DNAMP1::CTweakTargeting(*strm); + g_tweakTargeting->initCVars(cvarMgr); - /* Game */ - tag = g_ResFactory->GetResourceIdByName("Game"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakGame = new DataSpec::DNAMP1::CTweakGame(*strm); - g_tweakGame->initCVars(cvarMgr); + /* Game */ + tag = g_ResFactory->GetResourceIdByName("Game"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakGame = new DataSpec::DNAMP1::CTweakGame(*strm); + g_tweakGame->initCVars(cvarMgr); - /* GuiColors */ - tag = g_ResFactory->GetResourceIdByName("GuiColors"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakGuiColors = new DataSpec::DNAMP1::CTweakGuiColors(*strm); - g_tweakGuiColors->initCVars(cvarMgr); + /* GuiColors */ + tag = g_ResFactory->GetResourceIdByName("GuiColors"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakGuiColors = new DataSpec::DNAMP1::CTweakGuiColors(*strm); + g_tweakGuiColors->initCVars(cvarMgr); - /* AutoMapper */ - tag = g_ResFactory->GetResourceIdByName("AutoMapper"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakAutoMapper = new DataSpec::DNAMP1::CTweakAutoMapper(*strm); - CMappableObject::ReadAutoMapperTweaks(*g_tweakAutoMapper); - g_tweakPlayerGun->initCVars(cvarMgr); + /* AutoMapper */ + tag = g_ResFactory->GetResourceIdByName("AutoMapper"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakAutoMapper = new DataSpec::DNAMP1::CTweakAutoMapper(*strm); + CMappableObject::ReadAutoMapperTweaks(*g_tweakAutoMapper); + g_tweakPlayerGun->initCVars(cvarMgr); - /* Gui */ - tag = g_ResFactory->GetResourceIdByName("Gui"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakGui = new DataSpec::DNAMP1::CTweakGui(*strm); - g_tweakPlayerGun->initCVars(cvarMgr); + /* Gui */ + tag = g_ResFactory->GetResourceIdByName("Gui"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakGui = new DataSpec::DNAMP1::CTweakGui(*strm); + g_tweakPlayerGun->initCVars(cvarMgr); - /* PlayerControls */ - tag = g_ResFactory->GetResourceIdByName("PlayerControls"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakPlayerControl = new DataSpec::DNAMP1::CTweakPlayerControl(*strm); + /* PlayerControls */ + tag = g_ResFactory->GetResourceIdByName("PlayerControls"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakPlayerControl = new DataSpec::DNAMP1::CTweakPlayerControl(*strm); - /* PlayerControls2 */ - tag = g_ResFactory->GetResourceIdByName("PlayerControls2"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakPlayerControlAlt = new DataSpec::DNAMP1::CTweakPlayerControl(*strm); + /* PlayerControls2 */ + tag = g_ResFactory->GetResourceIdByName("PlayerControls2"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakPlayerControlAlt = new DataSpec::DNAMP1::CTweakPlayerControl(*strm); - g_currentPlayerControl = g_tweakPlayerControl; - - /* SlideShow */ - tag = g_ResFactory->GetResourceIdByName("SlideShow"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakSlideShow = new DataSpec::DNAMP1::CTweakSlideShow(*strm); - g_tweakSlideShow->initCVars(cvarMgr); + g_currentPlayerControl = g_tweakPlayerControl; + /* SlideShow */ + tag = g_ResFactory->GetResourceIdByName("SlideShow"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakSlideShow = new DataSpec::DNAMP1::CTweakSlideShow(*strm); + g_tweakSlideShow->initCVars(cvarMgr); } -void CTweaks::RegisterResourceTweaks(hecl::CVarManager* cvarMgr) -{ - std::experimental::optional strm; - - const SObjectTag* tag = g_ResFactory->GetResourceIdByName("GunRes"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakGunRes = new DataSpec::DNAMP1::CTweakGunRes(*strm); - g_tweakGunRes->ResolveResources(*g_ResFactory); - g_tweakGunRes->initCVars(cvarMgr); +void CTweaks::RegisterResourceTweaks(hecl::CVarManager* cvarMgr) { + std::experimental::optional strm; - tag = g_ResFactory->GetResourceIdByName("PlayerRes"); - strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); - g_tweakPlayerRes = new DataSpec::DNAMP1::CTweakPlayerRes(*strm); - g_tweakPlayerRes->ResolveResources(*g_ResFactory); - g_tweakPlayerRes->initCVars(cvarMgr); + const SObjectTag* tag = g_ResFactory->GetResourceIdByName("GunRes"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakGunRes = new DataSpec::DNAMP1::CTweakGunRes(*strm); + g_tweakGunRes->ResolveResources(*g_ResFactory); + g_tweakGunRes->initCVars(cvarMgr); + + tag = g_ResFactory->GetResourceIdByName("PlayerRes"); + strm.emplace(g_ResFactory->LoadResourceSync(*tag).release(), g_ResFactory->ResourceSize(*tag), true); + g_tweakPlayerRes = new DataSpec::DNAMP1::CTweakPlayerRes(*strm); + g_tweakPlayerRes->ResolveResources(*g_ResFactory); + g_tweakPlayerRes->initCVars(cvarMgr); } -} -} +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/CTweaks.hpp b/Runtime/MP1/CTweaks.hpp index 24dbed7f1..d43e0d8b1 100644 --- a/Runtime/MP1/CTweaks.hpp +++ b/Runtime/MP1/CTweaks.hpp @@ -1,24 +1,19 @@ #pragma once #include "RetroTypes.hpp" -namespace hecl -{ +namespace hecl { class CVarManager; } -namespace urde -{ +namespace urde { -namespace MP1 -{ +namespace MP1 { -class CTweaks -{ +class CTweaks { public: - void RegisterTweaks(hecl::CVarManager* cvarMgr); - void RegisterResourceTweaks(hecl::CVarManager* cvarMgr); + void RegisterTweaks(hecl::CVarManager* cvarMgr); + void RegisterResourceTweaks(hecl::CVarManager* cvarMgr); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index b34767c8e..695b33859 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -61,588 +61,493 @@ #include "CStopwatch.hpp" #include -namespace hecl -{ - extern CVar* com_enableCheats; - extern CVar* com_developer; -}; +namespace hecl { +extern CVar* com_enableCheats; +extern CVar* com_developer; +}; // namespace hecl -namespace urde -{ -namespace MP1 -{ +namespace urde { +namespace MP1 { -CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, - boo::IAudioVoiceEngine* voiceEngine, +CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) -: m_parent(parent), - x0_audioSys(voiceEngine, backend, 0,0,0,0,0), - x30_inputGenerator(g_tweakPlayer->GetLeftLogicalThreshold(), - g_tweakPlayer->GetRightLogicalThreshold()), - x44_guiSys(*g_ResFactory, *g_SimplePool, CGuiSys::EUsageMode::Zero) -{ - CMain* m = static_cast(g_Main); +: m_parent(parent) +, x0_audioSys(voiceEngine, backend, 0, 0, 0, 0, 0) +, x30_inputGenerator(g_tweakPlayer->GetLeftLogicalThreshold(), g_tweakPlayer->GetRightLogicalThreshold()) +, x44_guiSys(*g_ResFactory, *g_SimplePool, CGuiSys::EUsageMode::Zero) { + CMain* m = static_cast(g_Main); - x30_inputGenerator.startScanning(); - g_InputGenerator = &x30_inputGenerator; + x30_inputGenerator.startScanning(); + g_InputGenerator = &x30_inputGenerator; - CAudioSys::SysSetVolume(0x7f); - CAudioSys::SetDefaultVolumeScale(0x75); - CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale()); - CStreamAudioManager::Initialize(); - CStreamAudioManager::SetMusicVolume(0x7f); - m->ResetGameState(); + CAudioSys::SysSetVolume(0x7f); + CAudioSys::SetDefaultVolumeScale(0x75); + CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale()); + CStreamAudioManager::Initialize(); + CStreamAudioManager::SetMusicVolume(0x7f); + m->ResetGameState(); - if (false && !g_tweakGame->GetSplashScreensDisabled()) - { - std::shared_ptr splash = std::make_shared(CSplashScreen::ESplashScreen::Nintendo); - x58_ioWinManager.AddIOWin(splash, 1000, 10000); - } + if (false && !g_tweakGame->GetSplashScreensDisabled()) { + std::shared_ptr splash = std::make_shared(CSplashScreen::ESplashScreen::Nintendo); + x58_ioWinManager.AddIOWin(splash, 1000, 10000); + } - std::shared_ptr mf = std::make_shared(); - x58_ioWinManager.AddIOWin(mf, 0, 0); + std::shared_ptr mf = std::make_shared(); + x58_ioWinManager.AddIOWin(mf, 0, 0); - std::shared_ptr console = std::make_shared(8, 5.f, 0.75f); - x58_ioWinManager.AddIOWin(console, 100, 0); + std::shared_ptr console = std::make_shared(8, 5.f, 0.75f); + x58_ioWinManager.AddIOWin(console, 100, 0); - std::shared_ptr audState = std::make_shared(); - x58_ioWinManager.AddIOWin(audState, 100, -1); + std::shared_ptr audState = std::make_shared(); + x58_ioWinManager.AddIOWin(audState, 100, -1); - std::shared_ptr errWin = std::make_shared(false); - x58_ioWinManager.AddIOWin(errWin, 10000, 100000); + std::shared_ptr errWin = std::make_shared(false); + x58_ioWinManager.AddIOWin(errWin, 10000, 100000); - g_GuiSys = &x44_guiSys; - g_GameState->GameOptions().EnsureSettings(); + g_GuiSys = &x44_guiSys; + g_GameState->GameOptions().EnsureSettings(); } -void CGameArchitectureSupport::UpdateTicks() -{ - x4_archQueue.Push(MakeMsg::CreateFrameBegin(EArchMsgTarget::Game, x78_gameFrameCount)); - x4_archQueue.Push(MakeMsg::CreateTimerTick(EArchMsgTarget::Game, 1.f / 60.f)); +void CGameArchitectureSupport::UpdateTicks() { + x4_archQueue.Push(MakeMsg::CreateFrameBegin(EArchMsgTarget::Game, x78_gameFrameCount)); + x4_archQueue.Push(MakeMsg::CreateTimerTick(EArchMsgTarget::Game, 1.f / 60.f)); } -void CGameArchitectureSupport::Update() -{ - g_GameState->GetWorldTransitionManager()->TouchModels(); - x30_inputGenerator.Update(1 / 60.f, x4_archQueue); - x4_archQueue.Push(MakeMsg::CreateFrameEnd(EArchMsgTarget::Game, x78_gameFrameCount)); - x58_ioWinManager.PumpMessages(x4_archQueue); +void CGameArchitectureSupport::Update() { + g_GameState->GetWorldTransitionManager()->TouchModels(); + x30_inputGenerator.Update(1 / 60.f, x4_archQueue); + x4_archQueue.Push(MakeMsg::CreateFrameEnd(EArchMsgTarget::Game, x78_gameFrameCount)); + x58_ioWinManager.PumpMessages(x4_archQueue); } -struct AudioGroupInfo -{ - const char* name; - u32 id; +struct AudioGroupInfo { + const char* name; + u32 id; }; -static const AudioGroupInfo StaticAudioGroups[] = -{ - {"Misc_AGSC", 39}, - {"MiscSamus_AGSC", 41}, - {"UI_AGSC", 40}, - {"Weapons_AGSC", 43}, - {"ZZZ_AGSC", 65} -}; - -bool CGameArchitectureSupport::LoadAudio() -{ - if (x88_audioLoadStatus == EAudioLoadStatus::Loaded) - return true; - - for (int i=0 ; i<5 ; ++i) - { - TToken& tok = x8c_pendingAudioGroups[i]; - if (tok.IsLocked()) - { - if (tok.IsLoaded()) - { - CAudioGroupSet* set = tok.GetObj(); - if (!CAudioSys::SysIsGroupSetLoaded(set->GetName())) - { - CAudioSys::SysLoadGroupSet(tok, set->GetName(), tok.GetObjectTag()->id); - CAudioSys::SysAddGroupIntoAmuse(set->GetName()); - } - } - else - { - return false; - } - } - else - { - /* Lock next pending group */ - tok.Lock(); - return false; - } - } - - CSfxManager::LoadTranslationTable(g_SimplePool, g_ResFactory->GetResourceIdByName("sound_lookup")); - x8c_pendingAudioGroups = std::vector>(); - x88_audioLoadStatus = EAudioLoadStatus::Loaded; +static const AudioGroupInfo StaticAudioGroups[] = { + {"Misc_AGSC", 39}, {"MiscSamus_AGSC", 41}, {"UI_AGSC", 40}, {"Weapons_AGSC", 43}, {"ZZZ_AGSC", 65}}; +bool CGameArchitectureSupport::LoadAudio() { + if (x88_audioLoadStatus == EAudioLoadStatus::Loaded) return true; -} -void CGameArchitectureSupport::PreloadAudio() -{ - if (x88_audioLoadStatus != EAudioLoadStatus::Uninitialized) - return; - x8c_pendingAudioGroups.clear(); - x8c_pendingAudioGroups.reserve(5); - - for (int i=0 ; i<5 ; ++i) - { - const AudioGroupInfo& info = StaticAudioGroups[i]; - CToken grp = g_SimplePool->GetObj(info.name); - if (i == 0) /* Lock first group in sequence */ - grp.Lock(); - x8c_pendingAudioGroups.push_back(std::move(grp)); + for (int i = 0; i < 5; ++i) { + TToken& tok = x8c_pendingAudioGroups[i]; + if (tok.IsLocked()) { + if (tok.IsLoaded()) { + CAudioGroupSet* set = tok.GetObj(); + if (!CAudioSys::SysIsGroupSetLoaded(set->GetName())) { + CAudioSys::SysLoadGroupSet(tok, set->GetName(), tok.GetObjectTag()->id); + CAudioSys::SysAddGroupIntoAmuse(set->GetName()); + } + } else { + return false; + } + } else { + /* Lock next pending group */ + tok.Lock(); + return false; } + } - x88_audioLoadStatus = EAudioLoadStatus::Loading; + CSfxManager::LoadTranslationTable(g_SimplePool, g_ResFactory->GetResourceIdByName("sound_lookup")); + x8c_pendingAudioGroups = std::vector>(); + x88_audioLoadStatus = EAudioLoadStatus::Loaded; + + return true; } -void CGameArchitectureSupport::UnloadAudio() -{ +void CGameArchitectureSupport::PreloadAudio() { + if (x88_audioLoadStatus != EAudioLoadStatus::Uninitialized) + return; + x8c_pendingAudioGroups.clear(); + x8c_pendingAudioGroups.reserve(5); - for (int i=0 ; i<5 ; ++i) - { - const AudioGroupInfo& info = StaticAudioGroups[i]; - const SObjectTag* tag = g_ResFactory->GetResourceIdByName(info.name); - auto name = CAudioSys::SysGetGroupSetName(tag->id); - CAudioSys::SysRemoveGroupFromAmuse(name); - CAudioSys::SysUnloadAudioGroupSet(name); - } + for (int i = 0; i < 5; ++i) { + const AudioGroupInfo& info = StaticAudioGroups[i]; + CToken grp = g_SimplePool->GetObj(info.name); + if (i == 0) /* Lock first group in sequence */ + grp.Lock(); + x8c_pendingAudioGroups.push_back(std::move(grp)); + } - x8c_pendingAudioGroups = std::vector>(); - x88_audioLoadStatus = EAudioLoadStatus::Uninitialized; + x88_audioLoadStatus = EAudioLoadStatus::Loading; } -void CGameArchitectureSupport::Draw() -{ - x58_ioWinManager.Draw(); - if (m_parent.x161_24_gameFrameDrawn) - { - ++x78_gameFrameCount; - m_parent.x161_24_gameFrameDrawn = false; - } +void CGameArchitectureSupport::UnloadAudio() { + + for (int i = 0; i < 5; ++i) { + const AudioGroupInfo& info = StaticAudioGroups[i]; + const SObjectTag* tag = g_ResFactory->GetResourceIdByName(info.name); + auto name = CAudioSys::SysGetGroupSetName(tag->id); + CAudioSys::SysRemoveGroupFromAmuse(name); + CAudioSys::SysUnloadAudioGroupSet(name); + } + + x8c_pendingAudioGroups = std::vector>(); + x88_audioLoadStatus = EAudioLoadStatus::Uninitialized; } -CGameArchitectureSupport::~CGameArchitectureSupport() -{ - x58_ioWinManager.RemoveAllIOWins(); - UnloadAudio(); - CSfxManager::Shutdown(); - CStreamAudioManager::Shutdown(); +void CGameArchitectureSupport::Draw() { + x58_ioWinManager.Draw(); + if (m_parent.x161_24_gameFrameDrawn) { + ++x78_gameFrameCount; + m_parent.x161_24_gameFrameDrawn = false; + } } -void CGameArchitectureSupport::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) -{ - x30_inputGenerator.charKeyDown(charCode, mods, isRepeat); - m_parent.m_console->handleCharCode(charCode, mods, isRepeat); +CGameArchitectureSupport::~CGameArchitectureSupport() { + x58_ioWinManager.RemoveAllIOWins(); + UnloadAudio(); + CSfxManager::Shutdown(); + CStreamAudioManager::Shutdown(); } -void CGameArchitectureSupport::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) -{ - x30_inputGenerator.specialKeyDown(key, mods, isRepeat); - m_parent.m_console->handleSpecialKeyDown(key, mods, isRepeat); +void CGameArchitectureSupport::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) { + x30_inputGenerator.charKeyDown(charCode, mods, isRepeat); + m_parent.m_console->handleCharCode(charCode, mods, isRepeat); } -void CGameArchitectureSupport::specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) -{ - x30_inputGenerator.specialKeyUp(key, mods); - m_parent.m_console->handleSpecialKeyUp(key, mods); +void CGameArchitectureSupport::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) { + x30_inputGenerator.specialKeyDown(key, mods, isRepeat); + m_parent.m_console->handleSpecialKeyDown(key, mods, isRepeat); } - - -CMain::CMain(IFactory* resFactory, CSimplePool* resStore, - boo::IGraphicsDataFactory* gfxFactory, - boo::IGraphicsCommandQueue* cmdQ, - const boo::ObjToken& spareTex) - : m_booSetter(gfxFactory, cmdQ, spareTex), - x128_globalObjects(resFactory, resStore) -{ - xe4_gameplayResult = EGameplayResult::Playing; - g_Main = this; +void CGameArchitectureSupport::specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) { + x30_inputGenerator.specialKeyUp(key, mods); + m_parent.m_console->handleSpecialKeyUp(key, mods); } -CMain::BooSetter::BooSetter(boo::IGraphicsDataFactory* factory, - boo::IGraphicsCommandQueue* cmdQ, - const boo::ObjToken& spareTex) -{ - CGraphics::InitializeBoo(factory, cmdQ, spareTex); - CParticleSwooshShaders::Initialize(); - CThermalColdFilter::Initialize(); - CThermalHotFilter::Initialize(); - CSpaceWarpFilter::Initialize(); - CCameraBlurFilter::Initialize(); - CXRayBlurFilter::Initialize(); - CFogVolumePlaneShader::Initialize(); - CFogVolumeFilter::Initialize(); - CEnergyBarShader::Initialize(); - CRadarPaintShader::Initialize(); - CMapSurfaceShader::Initialize(); - CPhazonSuitFilter::Initialize(); - CAABoxShader::Initialize(); - CWorldShadowShader::Initialize(); - CColoredQuadFilter::Initialize(); - CTexturedQuadFilter::Initialize(); - CTexturedQuadFilterAlpha::Initialize(); - CTextSupportShader::Initialize(); - CScanLinesFilter::Initialize(); - CRandomStaticFilter::Initialize(); - CEnvFxShaders::Initialize(); - CNESShader::Initialize(); +CMain::CMain(IFactory* resFactory, CSimplePool* resStore, boo::IGraphicsDataFactory* gfxFactory, + boo::IGraphicsCommandQueue* cmdQ, const boo::ObjToken& spareTex) +: m_booSetter(gfxFactory, cmdQ, spareTex), x128_globalObjects(resFactory, resStore) { + xe4_gameplayResult = EGameplayResult::Playing; + g_Main = this; } -void CMain::RegisterResourceTweaks() -{ +CMain::BooSetter::BooSetter(boo::IGraphicsDataFactory* factory, boo::IGraphicsCommandQueue* cmdQ, + const boo::ObjToken& spareTex) { + CGraphics::InitializeBoo(factory, cmdQ, spareTex); + CParticleSwooshShaders::Initialize(); + CThermalColdFilter::Initialize(); + CThermalHotFilter::Initialize(); + CSpaceWarpFilter::Initialize(); + CCameraBlurFilter::Initialize(); + CXRayBlurFilter::Initialize(); + CFogVolumePlaneShader::Initialize(); + CFogVolumeFilter::Initialize(); + CEnergyBarShader::Initialize(); + CRadarPaintShader::Initialize(); + CMapSurfaceShader::Initialize(); + CPhazonSuitFilter::Initialize(); + CAABoxShader::Initialize(); + CWorldShadowShader::Initialize(); + CColoredQuadFilter::Initialize(); + CTexturedQuadFilter::Initialize(); + CTexturedQuadFilterAlpha::Initialize(); + CTextSupportShader::Initialize(); + CScanLinesFilter::Initialize(); + CRandomStaticFilter::Initialize(); + CEnvFxShaders::Initialize(); + CNESShader::Initialize(); } -void CGameGlobalObjects::AddPaksAndFactories() -{ - CGraphics::SetViewPointMatrix(zeus::CTransform::Identity()); - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - if (CResLoader* loader = g_ResFactory->GetResLoader()) - { - loader->AddPakFileAsync("Tweaks", false, false); - loader->AddPakFileAsync("NoARAM", false, false); - loader->AddPakFileAsync("AudioGrp", false, false); - loader->AddPakFileAsync("MiscData", false, false); - loader->AddPakFileAsync("SamusGun", true, false); - loader->AddPakFileAsync("TestAnim", true, false); - loader->AddPakFileAsync("SamGunFx", true, false); - loader->AddPakFileAsync("MidiData", false, false); - loader->AddPakFileAsync("GGuiSys", false, false); - loader->AddPakFileAsync("!original_ids", false, false); - loader->WaitForPakFileLoadingComplete(); - } +void CMain::RegisterResourceTweaks() {} - if (CFactoryMgr* fmgr = g_ResFactory->GetFactoryMgr()) - { - fmgr->AddFactory(FOURCC('TXTR'), FMemFactoryFunc(FTextureFactory)); - fmgr->AddFactory(FOURCC('PART'), FFactoryFunc(FParticleFactory)); - fmgr->AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame)); - fmgr->AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory)); - fmgr->AddFactory(FOURCC('CMDL'), FMemFactoryFunc(FModelFactory)); - fmgr->AddFactory(FOURCC('CINF'), FFactoryFunc(FCharLayoutInfo)); - fmgr->AddFactory(FOURCC('CSKR'), FFactoryFunc(FSkinRulesFactory)); - fmgr->AddFactory(FOURCC('ANCS'), FFactoryFunc(FAnimCharacterSet)); - fmgr->AddFactory(FOURCC('ANIM'), FFactoryFunc(AnimSourceFactory)); - fmgr->AddFactory(FOURCC('EVNT'), FFactoryFunc(AnimPOIDataFactory)); - fmgr->AddFactory(FOURCC('DCLN'), FFactoryFunc(FCollidableOBBTreeGroupFactory)); - fmgr->AddFactory(FOURCC('DGRP'), FFactoryFunc(FDependencyGroupFactory)); - fmgr->AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory)); - fmgr->AddFactory(FOURCC('CSNG'), FFactoryFunc(FMidiDataFactory)); - fmgr->AddFactory(FOURCC('ATBL'), FFactoryFunc(FAudioTranslationTableFactory)); - fmgr->AddFactory(FOURCC('STRG'), FFactoryFunc(FStringTableFactory)); - fmgr->AddFactory(FOURCC('HINT'), FFactoryFunc(FHintFactory)); - fmgr->AddFactory(FOURCC('SAVW'), FFactoryFunc(FSaveWorldFactory)); - fmgr->AddFactory(FOURCC('MAPW'), FFactoryFunc(FMapWorldFactory)); - fmgr->AddFactory(FOURCC('OIDS'), FFactoryFunc(FMP1OriginalIDsFactory)); - fmgr->AddFactory(FOURCC('SCAN'), FFactoryFunc(FScannableObjectInfoFactory)); - fmgr->AddFactory(FOURCC('CRSC'), FFactoryFunc(FCollisionResponseDataFactory)); - fmgr->AddFactory(FOURCC('SWHC'), FFactoryFunc(FParticleSwooshDataFactory)); - fmgr->AddFactory(FOURCC('ELSC'), FFactoryFunc(FParticleElectricDataFactory)); - fmgr->AddFactory(FOURCC('WPSC'), FFactoryFunc(FProjectileWeaponDataFactory)); - fmgr->AddFactory(FOURCC('DPSC'), FFactoryFunc(FDecalDataFactory)); - fmgr->AddFactory(FOURCC('MAPA'), FFactoryFunc(FMapAreaFactory)); - fmgr->AddFactory(FOURCC('MAPU'), FFactoryFunc(FMapUniverseFactory)); - fmgr->AddFactory(FOURCC('AFSM'), FFactoryFunc(FAiFiniteStateMachineFactory)); - fmgr->AddFactory(FOURCC('PATH'), FMemFactoryFunc(FPathFindAreaFactory)); - } -} - -CGameGlobalObjects::~CGameGlobalObjects() -{ - g_ResFactory = nullptr; - g_SimplePool = nullptr; - g_CharFactoryBuilder = nullptr; - g_AiFuncMap = nullptr; - g_GameState = nullptr; - g_TweakManager = nullptr; -} - -void CMain::AddWorldPaks() -{ - CResLoader* loader = g_ResFactory->GetResLoader(); - if (!loader) - return; - auto pakPrefix = g_tweakGame->GetWorldPrefix(); - for (int i=0 ; i<9 ; ++i) - { - std::string path(pakPrefix); - - if (i != 0) - path += '0' + i; - - std::string lowerPath(path); - athena::utility::tolower(lowerPath); - if (CDvdFile::FileExists((path + ".upak").c_str())) - loader->AddPakFileAsync(path, false, true); - else if (CDvdFile::FileExists((lowerPath + ".upak").c_str())) - loader->AddPakFileAsync(lowerPath, false, true); - } +void CGameGlobalObjects::AddPaksAndFactories() { + CGraphics::SetViewPointMatrix(zeus::CTransform::Identity()); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + if (CResLoader* loader = g_ResFactory->GetResLoader()) { + loader->AddPakFileAsync("Tweaks", false, false); + loader->AddPakFileAsync("NoARAM", false, false); + loader->AddPakFileAsync("AudioGrp", false, false); + loader->AddPakFileAsync("MiscData", false, false); + loader->AddPakFileAsync("SamusGun", true, false); + loader->AddPakFileAsync("TestAnim", true, false); + loader->AddPakFileAsync("SamGunFx", true, false); + loader->AddPakFileAsync("MidiData", false, false); + loader->AddPakFileAsync("GGuiSys", false, false); + loader->AddPakFileAsync("!original_ids", false, false); loader->WaitForPakFileLoadingComplete(); + } + + if (CFactoryMgr* fmgr = g_ResFactory->GetFactoryMgr()) { + fmgr->AddFactory(FOURCC('TXTR'), FMemFactoryFunc(FTextureFactory)); + fmgr->AddFactory(FOURCC('PART'), FFactoryFunc(FParticleFactory)); + fmgr->AddFactory(FOURCC('FRME'), FFactoryFunc(RGuiFrameFactoryInGame)); + fmgr->AddFactory(FOURCC('FONT'), FFactoryFunc(FRasterFontFactory)); + fmgr->AddFactory(FOURCC('CMDL'), FMemFactoryFunc(FModelFactory)); + fmgr->AddFactory(FOURCC('CINF'), FFactoryFunc(FCharLayoutInfo)); + fmgr->AddFactory(FOURCC('CSKR'), FFactoryFunc(FSkinRulesFactory)); + fmgr->AddFactory(FOURCC('ANCS'), FFactoryFunc(FAnimCharacterSet)); + fmgr->AddFactory(FOURCC('ANIM'), FFactoryFunc(AnimSourceFactory)); + fmgr->AddFactory(FOURCC('EVNT'), FFactoryFunc(AnimPOIDataFactory)); + fmgr->AddFactory(FOURCC('DCLN'), FFactoryFunc(FCollidableOBBTreeGroupFactory)); + fmgr->AddFactory(FOURCC('DGRP'), FFactoryFunc(FDependencyGroupFactory)); + fmgr->AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory)); + fmgr->AddFactory(FOURCC('CSNG'), FFactoryFunc(FMidiDataFactory)); + fmgr->AddFactory(FOURCC('ATBL'), FFactoryFunc(FAudioTranslationTableFactory)); + fmgr->AddFactory(FOURCC('STRG'), FFactoryFunc(FStringTableFactory)); + fmgr->AddFactory(FOURCC('HINT'), FFactoryFunc(FHintFactory)); + fmgr->AddFactory(FOURCC('SAVW'), FFactoryFunc(FSaveWorldFactory)); + fmgr->AddFactory(FOURCC('MAPW'), FFactoryFunc(FMapWorldFactory)); + fmgr->AddFactory(FOURCC('OIDS'), FFactoryFunc(FMP1OriginalIDsFactory)); + fmgr->AddFactory(FOURCC('SCAN'), FFactoryFunc(FScannableObjectInfoFactory)); + fmgr->AddFactory(FOURCC('CRSC'), FFactoryFunc(FCollisionResponseDataFactory)); + fmgr->AddFactory(FOURCC('SWHC'), FFactoryFunc(FParticleSwooshDataFactory)); + fmgr->AddFactory(FOURCC('ELSC'), FFactoryFunc(FParticleElectricDataFactory)); + fmgr->AddFactory(FOURCC('WPSC'), FFactoryFunc(FProjectileWeaponDataFactory)); + fmgr->AddFactory(FOURCC('DPSC'), FFactoryFunc(FDecalDataFactory)); + fmgr->AddFactory(FOURCC('MAPA'), FFactoryFunc(FMapAreaFactory)); + fmgr->AddFactory(FOURCC('MAPU'), FFactoryFunc(FMapUniverseFactory)); + fmgr->AddFactory(FOURCC('AFSM'), FFactoryFunc(FAiFiniteStateMachineFactory)); + fmgr->AddFactory(FOURCC('PATH'), FMemFactoryFunc(FPathFindAreaFactory)); + } } -void CMain::ResetGameState() -{ - CPersistentOptions sysOpts = g_GameState->SystemOptions(); - CGameOptions gameOpts = g_GameState->GameOptions(); - x128_globalObjects.ResetGameState(); - g_GameState->ImportPersistentOptions(sysOpts); - g_GameState->SetGameOptions(gameOpts); - g_GameState->GetPlayerState()->SetIsFusionEnabled(g_GameState->SystemOptions().GetPlayerFusionSuitActive()); +CGameGlobalObjects::~CGameGlobalObjects() { + g_ResFactory = nullptr; + g_SimplePool = nullptr; + g_CharFactoryBuilder = nullptr; + g_AiFuncMap = nullptr; + g_GameState = nullptr; + g_TweakManager = nullptr; } -void CMain::InitializeSubsystems() -{ - CBasics::Initialize(); - CModelShaders::Initialize(); - CMoviePlayer::Initialize(); - CLineRenderer::Initialize(); - CElementGen::Initialize(); - CAnimData::InitializeCache(); - CDecalManager::Initialize(); - CGBASupport::Initialize(); +void CMain::AddWorldPaks() { + CResLoader* loader = g_ResFactory->GetResLoader(); + if (!loader) + return; + auto pakPrefix = g_tweakGame->GetWorldPrefix(); + for (int i = 0; i < 9; ++i) { + std::string path(pakPrefix); + + if (i != 0) + path += '0' + i; + + std::string lowerPath(path); + athena::utility::tolower(lowerPath); + if (CDvdFile::FileExists((path + ".upak").c_str())) + loader->AddPakFileAsync(path, false, true); + else if (CDvdFile::FileExists((lowerPath + ".upak").c_str())) + loader->AddPakFileAsync(lowerPath, false, true); + } + loader->WaitForPakFileLoadingComplete(); } -void CMain::MemoryCardInitializePump() -{ - if (!g_MemoryCardSys) - { - std::unique_ptr& memSys = x128_globalObjects.x0_memoryCardSys; - if (!memSys) - memSys.reset(new CMemoryCardSys()); - if (memSys->InitializePump()) - { - g_MemoryCardSys = memSys.get(); - g_GameState->InitializeMemoryStates(); - } +void CMain::ResetGameState() { + CPersistentOptions sysOpts = g_GameState->SystemOptions(); + CGameOptions gameOpts = g_GameState->GameOptions(); + x128_globalObjects.ResetGameState(); + g_GameState->ImportPersistentOptions(sysOpts); + g_GameState->SetGameOptions(gameOpts); + g_GameState->GetPlayerState()->SetIsFusionEnabled(g_GameState->SystemOptions().GetPlayerFusionSuitActive()); +} + +void CMain::InitializeSubsystems() { + CBasics::Initialize(); + CModelShaders::Initialize(); + CMoviePlayer::Initialize(); + CLineRenderer::Initialize(); + CElementGen::Initialize(); + CAnimData::InitializeCache(); + CDecalManager::Initialize(); + CGBASupport::Initialize(); +} + +void CMain::MemoryCardInitializePump() { + if (!g_MemoryCardSys) { + std::unique_ptr& memSys = x128_globalObjects.x0_memoryCardSys; + if (!memSys) + memSys.reset(new CMemoryCardSys()); + if (memSys->InitializePump()) { + g_MemoryCardSys = memSys.get(); + g_GameState->InitializeMemoryStates(); } + } } -void CMain::FillInAssetIDs() -{ +void CMain::FillInAssetIDs() {} + +bool CMain::LoadAudio() { + if (x164_archSupport) + return x164_archSupport->LoadAudio(); + return true; } -bool CMain::LoadAudio() -{ - if (x164_archSupport) - return x164_archSupport->LoadAudio(); - return true; -} +void CMain::EnsureWorldPaksReady() {} -void CMain::EnsureWorldPaksReady() -{ -} +void CMain::EnsureWorldPakReady(CAssetId mlvl) { /* TODO: Schedule resource list load for World Pak containing mlvl */ } -void CMain::EnsureWorldPakReady(CAssetId mlvl) -{ - /* TODO: Schedule resource list load for World Pak containing mlvl */ -} +void CMain::Give(hecl::Console* console, const std::vector& args) { + if (args.size() < 1 || (!g_GameState || !g_GameState->GetPlayerState())) + return; -void CMain::Give(hecl::Console* console, const std::vector& args) -{ - if (args.size() < 1 || (!g_GameState || !g_GameState->GetPlayerState())) - return; - - std::string type = args[0]; - athena::utility::tolower(type); - std::shared_ptr pState = g_GameState->GetPlayerState(); - if (type == "all") - { - for (u32 item = 0; item < u32(CPlayerState::EItemType::Max); ++item) - { - pState->ReInitalizePowerUp(CPlayerState::EItemType(item), - CPlayerState::GetPowerUpMaxValue(CPlayerState::EItemType(item))); - pState->IncrPickup(CPlayerState::EItemType(item), - CPlayerState::GetPowerUpMaxValue(CPlayerState::EItemType(item))); - } - pState->IncrPickup(CPlayerState::EItemType::HealthRefill, 99999); + std::string type = args[0]; + athena::utility::tolower(type); + std::shared_ptr pState = g_GameState->GetPlayerState(); + if (type == "all") { + for (u32 item = 0; item < u32(CPlayerState::EItemType::Max); ++item) { + pState->ReInitalizePowerUp(CPlayerState::EItemType(item), + CPlayerState::GetPowerUpMaxValue(CPlayerState::EItemType(item))); + pState->IncrPickup(CPlayerState::EItemType(item), + CPlayerState::GetPowerUpMaxValue(CPlayerState::EItemType(item))); } - else - { - CPlayerState::EItemType eType = CPlayerState::ItemNameToType(type); - if (eType == CPlayerState::EItemType::Invalid) - { - console->report(hecl::Console::Level::Info, "Invalid item %s", type.c_str()); - return; - } - if (eType == CPlayerState::EItemType::HealthRefill) - { - pState->IncrPickup(eType, 9999); - console->report(hecl::Console::Level::Info, "Cheater....., Greatly increasing Metroid encounters, have fun!"); - if (g_StateManager) - g_StateManager->Player()->AsyncLoadSuit(*g_StateManager); - return; - } - - s32 itemAmt = CPlayerState::GetPowerUpMaxValue(eType); - if (args.size() == 2) - { - s32 itemMax = CPlayerState::GetPowerUpMaxValue(eType); - itemAmt = s32(strtol(args[1].c_str(), nullptr, 10)); - itemAmt = zeus::clamp(-itemMax, itemAmt, itemMax); - } - - u32 curCap = pState->GetItemCapacity(eType); - if (itemAmt > 0 && curCap < u32(itemAmt)) - { - /* Handle special case with Missiles */ - if (eType == CPlayerState::EItemType::Missiles) - { - u32 tmp = ((u32(itemAmt) / 5) + (itemAmt % 5)) * 5; - pState->ReInitalizePowerUp(eType, tmp); - } - else - pState->ReInitalizePowerUp(eType, itemAmt); - } - - if (itemAmt > 0) - pState->IncrPickup(eType, u32(itemAmt)); - else - pState->DecrPickup(eType, zeus::clamp(0u, u32(abs(itemAmt)), pState->GetItemAmount(eType))); + pState->IncrPickup(CPlayerState::EItemType::HealthRefill, 99999); + } else { + CPlayerState::EItemType eType = CPlayerState::ItemNameToType(type); + if (eType == CPlayerState::EItemType::Invalid) { + console->report(hecl::Console::Level::Info, "Invalid item %s", type.c_str()); + return; } - if (g_StateManager) + if (eType == CPlayerState::EItemType::HealthRefill) { + pState->IncrPickup(eType, 9999); + console->report(hecl::Console::Level::Info, "Cheater....., Greatly increasing Metroid encounters, have fun!"); + if (g_StateManager) g_StateManager->Player()->AsyncLoadSuit(*g_StateManager); - console->report(hecl::Console::Level::Info, "Cheater....., Greatly increasing Metroid encounters, have fun!"); -} - -void CMain::God(hecl::Console* con, const std::vector &) -{ - if (g_GameState && g_GameState->GetPlayerState()) - { - g_GameState->GetPlayerState()->SetCanTakeDamage(!g_GameState->GetPlayerState()->CanTakeDamage()); - if (!g_GameState->GetPlayerState()->CanTakeDamage()) - con->report(hecl::Console::Level::Info, "God Mode Enabled"); - else - con->report(hecl::Console::Level::Info, "God Mode Disabled"); + return; } -} -void CMain::Teleport(hecl::Console *, const std::vector& args) -{ - if (!g_StateManager || args.size() < 3) - return; - - zeus::CVector3f loc; - for (u32 i = 0; i < 3; ++i) - loc[i] = strtof(args[i].c_str(), nullptr); - - zeus::CTransform xf = g_StateManager->Player()->GetTransform(); - xf.origin = loc; - - if (args.size() == 6) - { - zeus::CVector3f angle; - for (u32 i = 0; i < 3; ++i) - angle[i] = zeus::degToRad(strtof(args[i + 3].c_str(), nullptr)); - xf.setRotation(zeus::CMatrix3f(zeus::CQuaternion(angle))); + s32 itemAmt = CPlayerState::GetPowerUpMaxValue(eType); + if (args.size() == 2) { + s32 itemMax = CPlayerState::GetPowerUpMaxValue(eType); + itemAmt = s32(strtol(args[1].c_str(), nullptr, 10)); + itemAmt = zeus::clamp(-itemMax, itemAmt, itemMax); } - g_StateManager->Player()->Teleport(xf, *g_StateManager, false); -} -void CMain::ListWorlds(hecl::Console* con, const std::vector &) -{ - - if (g_ResFactory && g_ResFactory->GetResLoader()) - { - for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) - if (pak->IsWorldPak()) - { - for (const auto& named : pak->GetNameList()) - if (named.second.type == SBIG('MLVL')) - { - con->report(hecl::Console::Level::Info, "%s '%08X'", named.first.c_str(), - named.second.id.Value()); - } - } + u32 curCap = pState->GetItemCapacity(eType); + if (itemAmt > 0 && curCap < u32(itemAmt)) { + /* Handle special case with Missiles */ + if (eType == CPlayerState::EItemType::Missiles) { + u32 tmp = ((u32(itemAmt) / 5) + (itemAmt % 5)) * 5; + pState->ReInitalizePowerUp(eType, tmp); + } else + pState->ReInitalizePowerUp(eType, itemAmt); } -} -void CMain::WarpTo(hecl::Console* con, const std::vector& args) -{ - if (!g_StateManager) - return; - - if (args.size() < 1) - return; - - TAreaId aId; - std::string worldName; - if (args.size() == 2) - { - worldName = args[0]; - athena::utility::tolower(worldName); - aId = strtol(args[1].c_str(), nullptr, 10); - } + if (itemAmt > 0) + pState->IncrPickup(eType, u32(itemAmt)); else - aId = strtol(args[0].c_str(), nullptr, 10); + pState->DecrPickup(eType, zeus::clamp(0u, u32(abs(itemAmt)), pState->GetItemAmount(eType))); + } + if (g_StateManager) + g_StateManager->Player()->AsyncLoadSuit(*g_StateManager); + console->report(hecl::Console::Level::Info, "Cheater....., Greatly increasing Metroid encounters, have fun!"); +} - if (!worldName.empty() && g_ResFactory && g_ResFactory->GetResLoader()) - { - bool found = false; +void CMain::God(hecl::Console* con, const std::vector&) { + if (g_GameState && g_GameState->GetPlayerState()) { + g_GameState->GetPlayerState()->SetCanTakeDamage(!g_GameState->GetPlayerState()->CanTakeDamage()); + if (!g_GameState->GetPlayerState()->CanTakeDamage()) + con->report(hecl::Console::Level::Info, "God Mode Enabled"); + else + con->report(hecl::Console::Level::Info, "God Mode Disabled"); + } +} - for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) - { - if (found) - break; - if (pak->IsWorldPak()) - { - for (const auto& named : pak->GetNameList()) - if (named.second.type == SBIG('MLVL')) - { - std::string name = named.first; - athena::utility::tolower(name); - if (name.find(worldName) != std::string::npos) - { - g_GameState->SetCurrentWorldId(named.second.id); - found = true; - break; - } - } +void CMain::Teleport(hecl::Console*, const std::vector& args) { + if (!g_StateManager || args.size() < 3) + return; + + zeus::CVector3f loc; + for (u32 i = 0; i < 3; ++i) + loc[i] = strtof(args[i].c_str(), nullptr); + + zeus::CTransform xf = g_StateManager->Player()->GetTransform(); + xf.origin = loc; + + if (args.size() == 6) { + zeus::CVector3f angle; + for (u32 i = 0; i < 3; ++i) + angle[i] = zeus::degToRad(strtof(args[i + 3].c_str(), nullptr)); + xf.setRotation(zeus::CMatrix3f(zeus::CQuaternion(angle))); + } + g_StateManager->Player()->Teleport(xf, *g_StateManager, false); +} + +void CMain::ListWorlds(hecl::Console* con, const std::vector&) { + + if (g_ResFactory && g_ResFactory->GetResLoader()) { + for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) + if (pak->IsWorldPak()) { + for (const auto& named : pak->GetNameList()) + if (named.second.type == SBIG('MLVL')) { + con->report(hecl::Console::Level::Info, "%s '%08X'", named.first.c_str(), named.second.id.Value()); + } + } + } +} + +void CMain::WarpTo(hecl::Console* con, const std::vector& args) { + if (!g_StateManager) + return; + + if (args.size() < 1) + return; + + TAreaId aId; + std::string worldName; + if (args.size() == 2) { + worldName = args[0]; + athena::utility::tolower(worldName); + aId = strtol(args[1].c_str(), nullptr, 10); + } else + aId = strtol(args[0].c_str(), nullptr, 10); + + if (!worldName.empty() && g_ResFactory && g_ResFactory->GetResLoader()) { + bool found = false; + + for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) { + if (found) + break; + if (pak->IsWorldPak()) { + for (const auto& named : pak->GetNameList()) + if (named.second.type == SBIG('MLVL')) { + std::string name = named.first; + athena::utility::tolower(name); + if (name.find(worldName) != std::string::npos) { + g_GameState->SetCurrentWorldId(named.second.id); + found = true; + break; } - } + } + } } + } - g_GameState->GetWorldTransitionManager()->DisableTransition(); + g_GameState->GetWorldTransitionManager()->DisableTransition(); - if (aId >= g_GameState->CurrentWorldState().GetLayerState()->GetAreaCount()) - aId = 0; + if (aId >= g_GameState->CurrentWorldState().GetLayerState()->GetAreaCount()) + aId = 0; - g_GameState->CurrentWorldState().SetAreaId(aId); - g_Main->SetFlowState(EFlowState::None); - g_StateManager->SetWarping(true); - g_StateManager->SetShouldQuitGame(true); + g_GameState->CurrentWorldState().SetAreaId(aId); + g_Main->SetFlowState(EFlowState::None); + g_StateManager->SetWarping(true); + g_StateManager->SetShouldQuitGame(true); } -void CMain::StreamNewGameState(CBitStreamReader& r, u32 idx) -{ - bool fusionBackup = g_GameState->SystemOptions().GetPlayerFusionSuitActive(); - x128_globalObjects.x134_gameState = std::make_unique(r, idx); - g_GameState = x128_globalObjects.x134_gameState.get(); - g_GameState->SystemOptions().SetPlayerFusionSuitActive(fusionBackup); - g_GameState->GetPlayerState()->SetIsFusionEnabled(fusionBackup); - g_GameState->HintOptions().SetNextHintTime(); +void CMain::StreamNewGameState(CBitStreamReader& r, u32 idx) { + bool fusionBackup = g_GameState->SystemOptions().GetPlayerFusionSuitActive(); + x128_globalObjects.x134_gameState = std::make_unique(r, idx); + g_GameState = x128_globalObjects.x134_gameState.get(); + g_GameState->SystemOptions().SetPlayerFusionSuitActive(fusionBackup); + g_GameState->GetPlayerState()->SetIsFusionEnabled(fusionBackup); + g_GameState->HintOptions().SetNextHintTime(); } -void CMain::RefreshGameState() -{ - CPersistentOptions sysOpts = g_GameState->SystemOptions(); - u64 cardSerial = g_GameState->GetCardSerial(); - std::vector saveData = g_GameState->BackupBuf(); - CGameOptions gameOpts = g_GameState->GameOptions(); - CBitStreamReader r(saveData.data(), saveData.size()); - x128_globalObjects.StreamInGameState(r, g_GameState->GetFileIdx()); - g_GameState->SetPersistentOptions(sysOpts); - g_GameState->SetGameOptions(gameOpts); - g_GameState->GameOptions().EnsureSettings(); - g_GameState->SetCardSerial(cardSerial); - g_GameState->GetPlayerState()->SetIsFusionEnabled( - g_GameState->SystemOptions().GetPlayerFusionSuitActive()); +void CMain::RefreshGameState() { + CPersistentOptions sysOpts = g_GameState->SystemOptions(); + u64 cardSerial = g_GameState->GetCardSerial(); + std::vector saveData = g_GameState->BackupBuf(); + CGameOptions gameOpts = g_GameState->GameOptions(); + CBitStreamReader r(saveData.data(), saveData.size()); + x128_globalObjects.StreamInGameState(r, g_GameState->GetFileIdx()); + g_GameState->SetPersistentOptions(sysOpts); + g_GameState->SetGameOptions(gameOpts); + g_GameState->GameOptions().EnsureSettings(); + g_GameState->SetCardSerial(cardSerial); + g_GameState->GetPlayerState()->SetIsFusionEnabled(g_GameState->SystemOptions().GetPlayerFusionSuitActive()); } static logvisor::Module DiscordLog("Discord"); @@ -654,367 +559,330 @@ static std::string DiscordWorldName; static u32 DiscordItemPercent = 0xffffffff; static std::string DiscordState; -void CMain::InitializeDiscord() -{ - DiscordStartTime = time(0); - DiscordEventHandlers handlers = {}; - handlers.ready = HandleDiscordReady; - handlers.disconnected = HandleDiscordDisconnected; - handlers.errored = HandleDiscordErrored; - Discord_Initialize(DISCORD_APPLICATION_ID, &handlers, 1, nullptr); +void CMain::InitializeDiscord() { + DiscordStartTime = time(0); + DiscordEventHandlers handlers = {}; + handlers.ready = HandleDiscordReady; + handlers.disconnected = HandleDiscordDisconnected; + handlers.errored = HandleDiscordErrored; + Discord_Initialize(DISCORD_APPLICATION_ID, &handlers, 1, nullptr); } -void CMain::ShutdownDiscord() -{ +void CMain::ShutdownDiscord() { + DiscordWorldSTRGObj = TLockedToken(); + Discord_Shutdown(); +} + +void CMain::UpdateDiscordPresence(CAssetId worldSTRG) { + bool updated = false; + + if (worldSTRG != DiscordWorldSTRG) { + DiscordWorldSTRG = worldSTRG; + DiscordWorldSTRGObj = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), worldSTRG}); + } + if (DiscordWorldSTRGObj.IsLoaded()) { + DiscordWorldName = hecl::Char16ToUTF8(DiscordWorldSTRGObj->GetString(0)); DiscordWorldSTRGObj = TLockedToken(); - Discord_Shutdown(); -} + updated = true; + } -void CMain::UpdateDiscordPresence(CAssetId worldSTRG) -{ - bool updated = false; - - if (worldSTRG != DiscordWorldSTRG) - { - DiscordWorldSTRG = worldSTRG; - DiscordWorldSTRGObj = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), worldSTRG}); - } - if (DiscordWorldSTRGObj.IsLoaded()) - { - DiscordWorldName = hecl::Char16ToUTF8(DiscordWorldSTRGObj->GetString(0)); - DiscordWorldSTRGObj = TLockedToken(); + if (g_GameState) { + if (CPlayerState* pState = g_GameState->GetPlayerState().get()) { + u32 itemPercent = pState->CalculateItemCollectionRate() * 100 / pState->GetPickupTotal(); + if (DiscordItemPercent != itemPercent) { + DiscordItemPercent = itemPercent; + DiscordState = hecl::Format("%d%%", itemPercent); updated = true; + } } + } - if (g_GameState) - { - if (CPlayerState* pState = g_GameState->GetPlayerState().get()) - { - u32 itemPercent = pState->CalculateItemCollectionRate() * 100 / pState->GetPickupTotal(); - if (DiscordItemPercent != itemPercent) - { - DiscordItemPercent = itemPercent; - DiscordState = hecl::Format("%d%%", itemPercent); - updated = true; - } + if (updated) { + DiscordRichPresence discordPresence = {}; + discordPresence.state = DiscordState.c_str(); + discordPresence.details = DiscordWorldName.c_str(); + discordPresence.largeImageKey = "default"; + discordPresence.startTimestamp = DiscordStartTime; + Discord_UpdatePresence(&discordPresence); + } +} + +void CMain::HandleDiscordReady(const DiscordUser* request) { DiscordLog.report(logvisor::Info, "Discord Ready"); } + +void CMain::HandleDiscordDisconnected(int errorCode, const char* message) { + DiscordLog.report(logvisor::Warning, "Discord Disconnected: %s", message); +} + +void CMain::HandleDiscordErrored(int errorCode, const char* message) { + DiscordLog.report(logvisor::Error, "Discord Error: %s", message); +} + +void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarManager* cvarMgr, boo::IWindow* window, + boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend) { + InitializeDiscord(); + m_mainWindow = window; + m_cvarMgr = cvarMgr; + m_console = std::make_unique(m_cvarMgr); + m_console->registerCommand("Quit"sv, "Quits the game immediately"sv, ""sv, + std::bind(&CMain::quit, this, std::placeholders::_1, std::placeholders::_2)); + m_console->registerCommand("Give"sv, "Gives the player the specified item, maxing it out"sv, ""sv, + std::bind(&CMain::Give, this, std::placeholders::_1, std::placeholders::_2), + hecl::SConsoleCommand::ECommandFlags::Cheat); + m_console->registerCommand( + "Teleport"sv, "Teleports the player to the specified coordinates in worldspace"sv, "x y z [dX dY dZ]"sv, + std::bind(&CMain::Teleport, this, std::placeholders::_1, std::placeholders::_2), + (hecl::SConsoleCommand::ECommandFlags::Cheat | hecl::SConsoleCommand::ECommandFlags::Developer)); + m_console->registerCommand("God"sv, "Disables damage given by enemies and objects"sv, ""sv, + std::bind(&CMain::God, this, std::placeholders::_1, std::placeholders::_2), + hecl::SConsoleCommand::ECommandFlags::Cheat); + m_console->registerCommand("ListWorlds"sv, "Lists loaded worlds"sv, ""sv, + std::bind(&CMain::ListWorlds, this, std::placeholders::_1, std::placeholders::_2), + hecl::SConsoleCommand::ECommandFlags::Normal); + m_console->registerCommand("WarpTo"sv, "Warps to a given area and world"sv, "[worldname] areaId"sv, + std::bind(&CMain::WarpTo, this, std::placeholders::_1, std::placeholders::_2), + hecl::SConsoleCommand::ECommandFlags::Normal); + + InitializeSubsystems(); + x128_globalObjects.PostInitialize(); + x70_tweaks.RegisterTweaks(m_cvarMgr); + x70_tweaks.RegisterResourceTweaks(m_cvarMgr); + AddWorldPaks(); + + const auto& args = boo::APP->getArgs(); + for (auto it = args.begin(); it != args.end(); ++it) { + if (*it == _SYS_STR("--warp") && args.end() - it >= 3) { + const hecl::SystemChar* worldIdxStr = (*(it + 1)).c_str(); + const hecl::SystemChar* areaIdxStr = (*(it + 2)).c_str(); + + hecl::SystemChar* endptr; + m_warpWorldIdx = hecl::StrToUl(worldIdxStr, &endptr, 0); + if (endptr == worldIdxStr) + m_warpWorldIdx = 0; + m_warpAreaId = hecl::StrToUl(areaIdxStr, &endptr, 0); + if (endptr == areaIdxStr) + m_warpAreaId = 0; + + bool found = false; + for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) { + if (*(pak->GetPath().end() - 6) == '0' + m_warpWorldIdx) { + found = true; + break; } + } + + if (!found) { + m_warpWorldIdx = -1; + break; + } + + if (args.end() - it >= 4) { + const hecl::SystemChar* layerStr = (*(it + 3)).c_str(); + if (layerStr[0] == _SYS_STR('0') || layerStr[0] == _SYS_STR('1')) + for (const auto* cur = layerStr; *cur != _SYS_STR('\0'); ++cur) + if (*cur == _SYS_STR('1')) + m_warpLayerBits |= 1 << (cur - layerStr); + } + + SetFlowState(EFlowState::StateSetter); } + } - if (updated) - { - DiscordRichPresence discordPresence = {}; - discordPresence.state = DiscordState.c_str(); - discordPresence.details = DiscordWorldName.c_str(); - discordPresence.largeImageKey = "default"; - discordPresence.startTimestamp = DiscordStartTime; - Discord_UpdatePresence(&discordPresence); - } -} - -void CMain::HandleDiscordReady(const DiscordUser* request) -{ - DiscordLog.report(logvisor::Info, "Discord Ready"); -} - -void CMain::HandleDiscordDisconnected(int errorCode, const char* message) -{ - DiscordLog.report(logvisor::Warning, "Discord Disconnected: %s", message); -} - -void CMain::HandleDiscordErrored(int errorCode, const char* message) -{ - DiscordLog.report(logvisor::Error, "Discord Error: %s", message); -} - -void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, - hecl::CVarManager* cvarMgr, - boo::IWindow* window, - boo::IAudioVoiceEngine* voiceEngine, - amuse::IBackendVoiceAllocator& backend) -{ - InitializeDiscord(); - m_mainWindow = window; - m_cvarMgr = cvarMgr; - m_console = std::make_unique(m_cvarMgr); - m_console->registerCommand("Quit"sv, "Quits the game immediately"sv, ""sv, std::bind(&CMain::quit, this, std::placeholders::_1, std::placeholders::_2)); - m_console->registerCommand("Give"sv, "Gives the player the specified item, maxing it out"sv, ""sv, std::bind(&CMain::Give, this, std::placeholders::_1, std::placeholders::_2), hecl::SConsoleCommand::ECommandFlags::Cheat); - m_console->registerCommand("Teleport"sv, "Teleports the player to the specified coordinates in worldspace"sv, "x y z [dX dY dZ]"sv, std::bind(&CMain::Teleport, this, std::placeholders::_1, std::placeholders::_2), (hecl::SConsoleCommand::ECommandFlags::Cheat | hecl::SConsoleCommand::ECommandFlags::Developer)); - m_console->registerCommand("God"sv, "Disables damage given by enemies and objects"sv, ""sv, std::bind(&CMain::God, this, std::placeholders::_1, std::placeholders::_2), hecl::SConsoleCommand::ECommandFlags::Cheat); - m_console->registerCommand("ListWorlds"sv, "Lists loaded worlds"sv, ""sv, std::bind(&CMain::ListWorlds, this, std::placeholders::_1, std::placeholders::_2), hecl::SConsoleCommand::ECommandFlags::Normal); - m_console->registerCommand("WarpTo"sv, "Warps to a given area and world"sv, "[worldname] areaId"sv, std::bind(&CMain::WarpTo, this, std::placeholders::_1, std::placeholders::_2), hecl::SConsoleCommand::ECommandFlags::Normal); - - - InitializeSubsystems(); - x128_globalObjects.PostInitialize(); - x70_tweaks.RegisterTweaks(m_cvarMgr); - x70_tweaks.RegisterResourceTweaks(m_cvarMgr); - AddWorldPaks(); - - const auto& args = boo::APP->getArgs(); - for (auto it = args.begin(); it != args.end(); ++it) - { - if (*it == _SYS_STR("--warp") && args.end() - it >= 3) - { - const hecl::SystemChar* worldIdxStr = (*(it + 1)).c_str(); - const hecl::SystemChar* areaIdxStr = (*(it + 2)).c_str(); - - hecl::SystemChar* endptr; - m_warpWorldIdx = hecl::StrToUl(worldIdxStr, &endptr, 0); - if (endptr == worldIdxStr) - m_warpWorldIdx = 0; - m_warpAreaId = hecl::StrToUl(areaIdxStr, &endptr, 0); - if (endptr == areaIdxStr) - m_warpAreaId = 0; - - bool found = false; - for (const auto& pak : g_ResFactory->GetResLoader()->GetPaks()) - { - if (*(pak->GetPath().end() - 6) == '0' + m_warpWorldIdx) - { - found = true; - break; - } - } - - if (!found) - { - m_warpWorldIdx = -1; - break; - } - - if (args.end() - it >= 4) - { - const hecl::SystemChar* layerStr = (*(it + 3)).c_str(); - if (layerStr[0] == _SYS_STR('0') || layerStr[0] == _SYS_STR('1')) - for (const auto* cur = layerStr; *cur != _SYS_STR('\0'); ++cur) - if (*cur == _SYS_STR('1')) - m_warpLayerBits |= 1 << (cur - layerStr); - } - - SetFlowState(EFlowState::StateSetter); - } - } - - FillInAssetIDs(); - x164_archSupport.reset(new CGameArchitectureSupport(*this, voiceEngine, backend)); - g_archSupport = x164_archSupport.get(); - x164_archSupport->PreloadAudio(); - std::srand(std::time(nullptr)); - //g_TweakManager->ReadFromMemoryCard("AudioTweaks"); + FillInAssetIDs(); + x164_archSupport.reset(new CGameArchitectureSupport(*this, voiceEngine, backend)); + g_archSupport = x164_archSupport.get(); + x164_archSupport->PreloadAudio(); + std::srand(std::time(nullptr)); + // g_TweakManager->ReadFromMemoryCard("AudioTweaks"); } static logvisor::Module WarmupLog("ShaderWarmup"); -void CMain::WarmupShaders() -{ - if (m_warmupTags.size()) - return; +void CMain::WarmupShaders() { + if (m_warmupTags.size()) + return; - m_needsWarmupClear = true; - size_t modelCount = 0; - g_ResFactory->EnumerateResources([&](const SObjectTag& tag) - { - if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('MREA')) - ++modelCount; + m_needsWarmupClear = true; + size_t modelCount = 0; + g_ResFactory->EnumerateResources([&](const SObjectTag& tag) { + if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('MREA')) + ++modelCount; + return true; + }); + m_warmupTags.reserve(modelCount); + + std::unordered_set addedTags; + addedTags.reserve(modelCount); + + g_ResFactory->EnumerateResources([&](const SObjectTag& tag) { + if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('MREA')) { + if (addedTags.find(tag) != addedTags.end()) return true; - }); - m_warmupTags.reserve(modelCount); - - std::unordered_set addedTags; - addedTags.reserve(modelCount); - - g_ResFactory->EnumerateResources([&](const SObjectTag& tag) - { - if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('MREA')) - { - if (addedTags.find(tag) != addedTags.end()) - return true; - addedTags.insert(tag); - m_warmupTags.push_back(tag); - } - return true; - }); - - m_warmupIt = m_warmupTags.begin(); - - WarmupLog.report(logvisor::Info, "Began warmup of %" PRISize " objects", m_warmupTags.size()); -} - -bool CMain::Proc() -{ - // Warmup cycle overrides update - if (m_warmupTags.size()) - return false; - - m_console->proc(); - if (!m_console->isOpen()) - { - CGBASupport::GlobalPoll(); - x164_archSupport->UpdateTicks(); - x164_archSupport->Update(); - CSfxManager::Update(1.f / 60.f); - CStreamAudioManager::Update(1.f / 60.f); + addedTags.insert(tag); + m_warmupTags.push_back(tag); } + return true; + }); - if (x164_archSupport->GetIOWinManager().IsEmpty() || CheckReset()) - { - CStreamAudioManager::StopAll(); - /* - x164_archSupport.reset(); - g_archSupport = x164_archSupport.get(); - x164_archSupport->PreloadAudio(); - */ - x160_24_finished = true; - } + m_warmupIt = m_warmupTags.begin(); - Discord_RunCallbacks(); - - return x160_24_finished; + WarmupLog.report(logvisor::Info, "Began warmup of %" PRISize " objects", m_warmupTags.size()); } -void CMain::Draw() -{ - // Warmup cycle overrides draw - if (m_warmupTags.size()) - { - if (m_needsWarmupClear) - { - CGraphics::g_BooMainCommandQueue->clearTarget(true, true); - m_needsWarmupClear = false; - } - auto startTime = std::chrono::steady_clock::now(); - while (m_warmupIt != m_warmupTags.end()) - { - WarmupLog.report(logvisor::Info, "[%d / %d] Warming %.4s %08X", - int(m_warmupIt - m_warmupTags.begin() + 1), int(m_warmupTags.size()), - m_warmupIt->type.getChars(), m_warmupIt->id.Value()); +bool CMain::Proc() { + // Warmup cycle overrides update + if (m_warmupTags.size()) + return false; - if (m_warmupIt->type == FOURCC('CMDL')) - CModel::WarmupShaders(*m_warmupIt); - else if (m_warmupIt->type == FOURCC('MREA')) - CGameArea::WarmupShaders(*m_warmupIt); - ++m_warmupIt; + m_console->proc(); + if (!m_console->isOpen()) { + CGBASupport::GlobalPoll(); + x164_archSupport->UpdateTicks(); + x164_archSupport->Update(); + CSfxManager::Update(1.f / 60.f); + CStreamAudioManager::Update(1.f / 60.f); + } - // Approximately 3/4 frame of warmups - auto curTime = std::chrono::steady_clock::now(); - if (std::chrono::duration_cast(curTime - startTime).count() > 12) - break; - } - if (m_warmupIt == m_warmupTags.end()) - { - m_warmupTags = std::vector(); - WarmupLog.report(logvisor::Info, "Finished warmup"); - } - return; - } - - CGraphics::g_BooMainCommandQueue->clearTarget(true, true); - x164_archSupport->Draw(); - m_console->draw(CGraphics::g_BooMainCommandQueue); -} - -void CMain::ShutdownSubsystems() -{ - CMoviePlayer::Shutdown(); - CLineRenderer::Shutdown(); - CDecalManager::Shutdown(); - CElementGen::Shutdown(); - CAnimData::FreeCache(); - CMemoryCardSys::Shutdown(); - CModelShaders::Shutdown(); - CMappableObject::Shutdown(); -} - -void CMain::Shutdown() -{ - m_console->unregisterCommand("Give"); + if (x164_archSupport->GetIOWinManager().IsEmpty() || CheckReset()) { + CStreamAudioManager::StopAll(); + /* x164_archSupport.reset(); - ShutdownSubsystems(); - CParticleSwooshShaders::Shutdown(); - CThermalColdFilter::Shutdown(); - CThermalHotFilter::Shutdown(); - CSpaceWarpFilter::Shutdown(); - CCameraBlurFilter::Shutdown(); - CXRayBlurFilter::Shutdown(); - CFogVolumePlaneShader::Shutdown(); - CFogVolumeFilter::Shutdown(); - CEnergyBarShader::Shutdown(); - CRadarPaintShader::Shutdown(); - CMapSurfaceShader::Shutdown(); - CPhazonSuitFilter::Shutdown(); - CAABoxShader::Shutdown(); - CWorldShadowShader::Shutdown(); - CColoredQuadFilter::Shutdown(); - CTexturedQuadFilter::Shutdown(); - CTexturedQuadFilterAlpha::Shutdown(); - CTextSupportShader::Shutdown(); - CScanLinesFilter::Shutdown(); - CRandomStaticFilter::Shutdown(); - CEnvFxShaders::Shutdown(); - CFluidPlaneShader::Shutdown(); - CFluidPlaneManager::RippleMapTex.reset(); - CNESShader::Shutdown(); - CGraphics::ShutdownBoo(); - ShutdownDiscord(); - CBooModel::AssertAllFreed(); + g_archSupport = x164_archSupport.get(); + x164_archSupport->PreloadAudio(); + */ + x160_24_finished = true; + } + + Discord_RunCallbacks(); + + return x160_24_finished; } -boo::IWindow* CMain::GetMainWindow() const -{ - return m_mainWindow; +void CMain::Draw() { + // Warmup cycle overrides draw + if (m_warmupTags.size()) { + if (m_needsWarmupClear) { + CGraphics::g_BooMainCommandQueue->clearTarget(true, true); + m_needsWarmupClear = false; + } + auto startTime = std::chrono::steady_clock::now(); + while (m_warmupIt != m_warmupTags.end()) { + WarmupLog.report(logvisor::Info, "[%d / %d] Warming %.4s %08X", int(m_warmupIt - m_warmupTags.begin() + 1), + int(m_warmupTags.size()), m_warmupIt->type.getChars(), m_warmupIt->id.Value()); + + if (m_warmupIt->type == FOURCC('CMDL')) + CModel::WarmupShaders(*m_warmupIt); + else if (m_warmupIt->type == FOURCC('MREA')) + CGameArea::WarmupShaders(*m_warmupIt); + ++m_warmupIt; + + // Approximately 3/4 frame of warmups + auto curTime = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast(curTime - startTime).count() > 12) + break; + } + if (m_warmupIt == m_warmupTags.end()) { + m_warmupTags = std::vector(); + WarmupLog.report(logvisor::Info, "Finished warmup"); + } + return; + } + + CGraphics::g_BooMainCommandQueue->clearTarget(true, true); + x164_archSupport->Draw(); + m_console->draw(CGraphics::g_BooMainCommandQueue); } +void CMain::ShutdownSubsystems() { + CMoviePlayer::Shutdown(); + CLineRenderer::Shutdown(); + CDecalManager::Shutdown(); + CElementGen::Shutdown(); + CAnimData::FreeCache(); + CMemoryCardSys::Shutdown(); + CModelShaders::Shutdown(); + CMappableObject::Shutdown(); +} + +void CMain::Shutdown() { + m_console->unregisterCommand("Give"); + x164_archSupport.reset(); + ShutdownSubsystems(); + CParticleSwooshShaders::Shutdown(); + CThermalColdFilter::Shutdown(); + CThermalHotFilter::Shutdown(); + CSpaceWarpFilter::Shutdown(); + CCameraBlurFilter::Shutdown(); + CXRayBlurFilter::Shutdown(); + CFogVolumePlaneShader::Shutdown(); + CFogVolumeFilter::Shutdown(); + CEnergyBarShader::Shutdown(); + CRadarPaintShader::Shutdown(); + CMapSurfaceShader::Shutdown(); + CPhazonSuitFilter::Shutdown(); + CAABoxShader::Shutdown(); + CWorldShadowShader::Shutdown(); + CColoredQuadFilter::Shutdown(); + CTexturedQuadFilter::Shutdown(); + CTexturedQuadFilterAlpha::Shutdown(); + CTextSupportShader::Shutdown(); + CScanLinesFilter::Shutdown(); + CRandomStaticFilter::Shutdown(); + CEnvFxShaders::Shutdown(); + CFluidPlaneShader::Shutdown(); + CFluidPlaneManager::RippleMapTex.reset(); + CNESShader::Shutdown(); + CGraphics::ShutdownBoo(); + ShutdownDiscord(); + CBooModel::AssertAllFreed(); +} + +boo::IWindow* CMain::GetMainWindow() const { return m_mainWindow; } + #if MP1_USE_BOO -int CMain::appMain(boo::IApplication* app) -{ - zeus::detectCPU(); - mainWindow = app->newWindow(_SYS_STR("Metroid Prime 1 Reimplementation vZygote"), 1); - mainWindow->showWindow(); - TOneStatic globalObjs; - InitializeSubsystems(); - globalObjs->PostInitialize(); - x70_tweaks.RegisterTweaks(); - AddWorldPaks(); - g_TweakManager->ReadFromMemoryCard("AudioTweaks"); - FillInAssetIDs(); - TOneStatic archSupport; - mainWindow->setCallback(archSupport.GetAllocSpace()); +int CMain::appMain(boo::IApplication* app) { + zeus::detectCPU(); + mainWindow = app->newWindow(_SYS_STR("Metroid Prime 1 Reimplementation vZygote"), 1); + mainWindow->showWindow(); + TOneStatic globalObjs; + InitializeSubsystems(); + globalObjs->PostInitialize(); + x70_tweaks.RegisterTweaks(); + AddWorldPaks(); + g_TweakManager->ReadFromMemoryCard("AudioTweaks"); + FillInAssetIDs(); + TOneStatic archSupport; + mainWindow->setCallback(archSupport.GetAllocSpace()); - boo::IGraphicsCommandQueue* gfxQ = mainWindow->getCommandQueue(); - boo::SWindowRect windowRect = mainWindow->getWindowFrame(); - boo::ITextureR* renderTex; - boo::GraphicsDataToken data = mainWindow->getMainContextDataFactory()->commitTransaction( - [&](boo::IGraphicsDataFactory::Context& ctx) -> bool - { + boo::IGraphicsCommandQueue* gfxQ = mainWindow->getCommandQueue(); + boo::SWindowRect windowRect = mainWindow->getWindowFrame(); + boo::ITextureR* renderTex; + boo::GraphicsDataToken data = + mainWindow->getMainContextDataFactory()->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) -> bool { renderTex = ctx.newRenderTexture(windowRect.size[0], windowRect.size[1], true, true); return true; - }); - float rgba[4] = { 0.2f, 0.2f, 0.2f, 1.0f}; - gfxQ->setClearColor(rgba); + }); + float rgba[4] = {0.2f, 0.2f, 0.2f, 1.0f}; + gfxQ->setClearColor(rgba); - while (!xe8_b24_finished) - { - xe8_b24_finished = archSupport->Update(); + while (!xe8_b24_finished) { + xe8_b24_finished = archSupport->Update(); - if (archSupport->isRectDirty()) - { - const boo::SWindowRect& windowRect = archSupport->getWindowRect(); - gfxQ->resizeRenderTexture(renderTex, - windowRect.size[0], - windowRect.size[1]); - } - - gfxQ->setRenderTarget(renderTex); - gfxQ->clearTarget(); - gfxQ->resolveDisplay(renderTex); - gfxQ->execute(); - mainWindow->waitForRetrace(); + if (archSupport->isRectDirty()) { + const boo::SWindowRect& windowRect = archSupport->getWindowRect(); + gfxQ->resizeRenderTexture(renderTex, windowRect.size[0], windowRect.size[1]); } - return 0; + + gfxQ->setRenderTarget(renderTex); + gfxQ->clearTarget(); + gfxQ->resolveDisplay(renderTex); + gfxQ->execute(); + mainWindow->waitForRetrace(); + } + return 0; } #endif -} -} +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/MP1.hpp b/Runtime/MP1/MP1.hpp index 65e84654c..f23b0006b 100644 --- a/Runtime/MP1/MP1.hpp +++ b/Runtime/MP1/MP1.hpp @@ -40,91 +40,78 @@ struct DiscordUser; -namespace urde -{ +namespace urde { class IFactory; class IObjectStore; -namespace MP1 -{ +namespace MP1 { class CMain; -class CGameGlobalObjects -{ - friend class CMain; +class CGameGlobalObjects { + friend class CMain; - std::unique_ptr m_gameSimplePool; - std::unique_ptr m_gameResFactory; - std::unique_ptr x0_memoryCardSys; - IFactory* x4_resFactory; - CSimplePool* xcc_simplePool; - CCharacterFactoryBuilder xec_charFactoryBuilder; - CAiFuncMap x110_aiFuncMap; - std::unique_ptr x134_gameState; - TLockedToken x13c_mainStringTable; - CInGameTweakManager x150_tweakManager; - std::unique_ptr m_renderer; + std::unique_ptr m_gameSimplePool; + std::unique_ptr m_gameResFactory; + std::unique_ptr x0_memoryCardSys; + IFactory* x4_resFactory; + CSimplePool* xcc_simplePool; + CCharacterFactoryBuilder xec_charFactoryBuilder; + CAiFuncMap x110_aiFuncMap; + std::unique_ptr x134_gameState; + TLockedToken x13c_mainStringTable; + CInGameTweakManager x150_tweakManager; + std::unique_ptr m_renderer; - void LoadStringTable() - { - x13c_mainStringTable = g_SimplePool->GetObj("STRG_Main"); - g_MainStringTable = x13c_mainStringTable.GetObj(); - } - void AddPaksAndFactories(); - static IRenderer* - AllocateRenderer(IObjectStore& store, IFactory& resFactory) - { - g_Renderer = new CBooRenderer(store, resFactory); - return g_Renderer; - } + void LoadStringTable() { + x13c_mainStringTable = g_SimplePool->GetObj("STRG_Main"); + g_MainStringTable = x13c_mainStringTable.GetObj(); + } + void AddPaksAndFactories(); + static IRenderer* AllocateRenderer(IObjectStore& store, IFactory& resFactory) { + g_Renderer = new CBooRenderer(store, resFactory); + return g_Renderer; + } public: - CGameGlobalObjects(IFactory* resFactory, - CSimplePool* objStore) - : x4_resFactory(resFactory), xcc_simplePool(objStore) - { - if (!x4_resFactory) - { - m_gameResFactory.reset(new CResFactory()); - x4_resFactory = m_gameResFactory.get(); - } - if (!xcc_simplePool) - { - m_gameSimplePool.reset(new CSimplePool(*x4_resFactory)); - xcc_simplePool = m_gameSimplePool.get(); - } - g_ResFactory = x4_resFactory; - g_SimplePool = xcc_simplePool; - g_CharFactoryBuilder = &xec_charFactoryBuilder; - g_AiFuncMap = &x110_aiFuncMap; - x134_gameState.reset(new CGameState()); - g_GameState = x134_gameState.get(); - g_TweakManager = &x150_tweakManager; + CGameGlobalObjects(IFactory* resFactory, CSimplePool* objStore) + : x4_resFactory(resFactory), xcc_simplePool(objStore) { + if (!x4_resFactory) { + m_gameResFactory.reset(new CResFactory()); + x4_resFactory = m_gameResFactory.get(); } - - ~CGameGlobalObjects(); - - void PostInitialize() - { - AddPaksAndFactories(); - x4_resFactory->LoadOriginalIDs(*xcc_simplePool); - LoadStringTable(); - m_renderer.reset(AllocateRenderer(*xcc_simplePool, *x4_resFactory)); - CEnvFxManager::Initialize(); - CScriptMazeNode::LoadMazeSeeds(); + if (!xcc_simplePool) { + m_gameSimplePool.reset(new CSimplePool(*x4_resFactory)); + xcc_simplePool = m_gameSimplePool.get(); } + g_ResFactory = x4_resFactory; + g_SimplePool = xcc_simplePool; + g_CharFactoryBuilder = &xec_charFactoryBuilder; + g_AiFuncMap = &x110_aiFuncMap; + x134_gameState.reset(new CGameState()); + g_GameState = x134_gameState.get(); + g_TweakManager = &x150_tweakManager; + } - void ResetGameState() - { - x134_gameState.reset(new CGameState()); - g_GameState = x134_gameState.get(); - } + ~CGameGlobalObjects(); - void StreamInGameState(CBitStreamReader& stream, u32 saveIdx) - { - x134_gameState.reset(new CGameState(stream, saveIdx)); - g_GameState = x134_gameState.get(); - } + void PostInitialize() { + AddPaksAndFactories(); + x4_resFactory->LoadOriginalIDs(*xcc_simplePool); + LoadStringTable(); + m_renderer.reset(AllocateRenderer(*xcc_simplePool, *x4_resFactory)); + CEnvFxManager::Initialize(); + CScriptMazeNode::LoadMazeSeeds(); + } + + void ResetGameState() { + x134_gameState.reset(new CGameState()); + g_GameState = x134_gameState.get(); + } + + void StreamInGameState(CBitStreamReader& stream, u32 saveIdx) { + x134_gameState.reset(new CGameState(stream, saveIdx)); + g_GameState = x134_gameState.get(); + } }; #if MP1_USE_BOO @@ -133,223 +120,199 @@ class CGameArchitectureSupport : public boo::IWindowCallback class CGameArchitectureSupport #endif { - friend class CMain; - CMain& m_parent; - CArchitectureQueue x4_archQueue; - CAudioSys x0_audioSys; - CInputGenerator x30_inputGenerator; - CGuiSys x44_guiSys; - CIOWinManager x58_ioWinManager; - s32 x78_gameFrameCount; + friend class CMain; + CMain& m_parent; + CArchitectureQueue x4_archQueue; + CAudioSys x0_audioSys; + CInputGenerator x30_inputGenerator; + CGuiSys x44_guiSys; + CIOWinManager x58_ioWinManager; + s32 x78_gameFrameCount; - enum class EAudioLoadStatus - { - Loading, - Loaded, - Uninitialized - }; - EAudioLoadStatus x88_audioLoadStatus = EAudioLoadStatus::Uninitialized; - std::vector> x8c_pendingAudioGroups; + enum class EAudioLoadStatus { Loading, Loaded, Uninitialized }; + EAudioLoadStatus x88_audioLoadStatus = EAudioLoadStatus::Uninitialized; + std::vector> x8c_pendingAudioGroups; - boo::SWindowRect m_windowRect; - bool m_rectIsDirty; + boo::SWindowRect m_windowRect; + bool m_rectIsDirty; - void destroyed() { x4_archQueue.Push(MakeMsg::CreateRemoveAllIOWins(EArchMsgTarget::IOWinManager)); } + void destroyed() { x4_archQueue.Push(MakeMsg::CreateRemoveAllIOWins(EArchMsgTarget::IOWinManager)); } - void resized(const boo::SWindowRect &rect) - { - m_windowRect = rect; - m_rectIsDirty = true; - } + void resized(const boo::SWindowRect& rect) { + m_windowRect = rect; + m_rectIsDirty = true; + } public: - CGameArchitectureSupport(CMain& parent, - boo::IAudioVoiceEngine* voiceEngine, - amuse::IBackendVoiceAllocator& backend); - ~CGameArchitectureSupport(); + CGameArchitectureSupport(CMain& parent, boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend); + ~CGameArchitectureSupport(); - void mouseDown(const boo::SWindowCoord &coord, boo::EMouseButton button, boo::EModifierKey mods) - { x30_inputGenerator.mouseDown(coord, button, mods); } - void mouseUp(const boo::SWindowCoord &coord, boo::EMouseButton button, boo::EModifierKey mods) - { x30_inputGenerator.mouseUp(coord, button, mods); } - void mouseMove(const boo::SWindowCoord &coord) - { x30_inputGenerator.mouseMove(coord); } - void scroll(const boo::SWindowCoord &coord, const boo::SScrollDelta &scroll) - { x30_inputGenerator.scroll(coord, scroll); } - void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat); - void charKeyUp(unsigned long charCode, boo::EModifierKey mods) { x30_inputGenerator.charKeyUp(charCode, mods); } - void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat); + void mouseDown(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) { + x30_inputGenerator.mouseDown(coord, button, mods); + } + void mouseUp(const boo::SWindowCoord& coord, boo::EMouseButton button, boo::EModifierKey mods) { + x30_inputGenerator.mouseUp(coord, button, mods); + } + void mouseMove(const boo::SWindowCoord& coord) { x30_inputGenerator.mouseMove(coord); } + void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) { + x30_inputGenerator.scroll(coord, scroll); + } + void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat); + void charKeyUp(unsigned long charCode, boo::EModifierKey mods) { x30_inputGenerator.charKeyUp(charCode, mods); } + void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat); - void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods); - void modKeyDown(boo::EModifierKey mod, bool isRepeat) - { x30_inputGenerator.modKeyDown(mod, isRepeat);} - void modKeyUp(boo::EModifierKey mod) - { x30_inputGenerator.modKeyUp(mod); } + void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods); + void modKeyDown(boo::EModifierKey mod, bool isRepeat) { x30_inputGenerator.modKeyDown(mod, isRepeat); } + void modKeyUp(boo::EModifierKey mod) { x30_inputGenerator.modKeyUp(mod); } - void PreloadAudio(); - bool LoadAudio(); - void UnloadAudio(); - void UpdateTicks(); - void Update(); - void Draw(); + void PreloadAudio(); + bool LoadAudio(); + void UnloadAudio(); + void UpdateTicks(); + void Update(); + void Draw(); - bool isRectDirty() { return m_rectIsDirty; } - const boo::SWindowRect& getWindowRect() - { - m_rectIsDirty = false; - return m_windowRect; - } + bool isRectDirty() { return m_rectIsDirty; } + const boo::SWindowRect& getWindowRect() { + m_rectIsDirty = false; + return m_windowRect; + } - CIOWinManager& GetIOWinManager() { return x58_ioWinManager; } + CIOWinManager& GetIOWinManager() { return x58_ioWinManager; } }; #if MP1_USE_BOO -class CMain : public boo::IApplicationCallback, public IMain +class CMain : public boo::IApplicationCallback, + public IMain #else class CMain : public IMain #endif { - friend class CGameArchitectureSupport; + friend class CGameArchitectureSupport; #if MP1_USE_BOO - boo::IWindow* mainWindow; - int appMain(boo::IApplication* app); - void appQuitting(boo::IApplication*) - { xe8_b24_finished = true; } - void appFilesOpen(boo::IApplication*, const std::vector& paths) - { - fprintf(stderr, "OPENING: "); - for (const std::string& path : paths) - fprintf(stderr, "%s ", path.c_str()); - fprintf(stderr, "\n"); - } + boo::IWindow* mainWindow; + int appMain(boo::IApplication* app); + void appQuitting(boo::IApplication*) { xe8_b24_finished = true; } + void appFilesOpen(boo::IApplication*, const std::vector& paths) { + fprintf(stderr, "OPENING: "); + for (const std::string& path : paths) + fprintf(stderr, "%s ", path.c_str()); + fprintf(stderr, "\n"); + } #endif private: + struct BooSetter { + BooSetter(boo::IGraphicsDataFactory* factory, boo::IGraphicsCommandQueue* cmdQ, + const boo::ObjToken& spareTex); + } m_booSetter; - struct BooSetter - { - BooSetter(boo::IGraphicsDataFactory* factory, - boo::IGraphicsCommandQueue* cmdQ, - const boo::ObjToken& spareTex); - } m_booSetter; + // CMemorySys x6c_memSys; + CTweaks x70_tweaks; + EGameplayResult xe4_gameplayResult; - //CMemorySys x6c_memSys; - CTweaks x70_tweaks; - EGameplayResult xe4_gameplayResult; + /* urde addition: these are simply initialized along with everything else */ + CGameGlobalObjects x128_globalObjects; - /* urde addition: these are simply initialized along with everything else */ - CGameGlobalObjects x128_globalObjects; + EFlowState x12c_flowState = EFlowState::Default; - EFlowState x12c_flowState = EFlowState::Default; + u32 x130_[10] = {1000000}; - u32 x130_[10] = { 1000000 }; - - union - { - struct - { - bool x160_24_finished : 1; - bool x160_25_mfGameBuilt : 1; - bool x160_26_screenFading : 1; - bool x160_27_ : 1; - bool x160_28_manageCard : 1; - bool x160_29_ : 1; - bool x160_30_ : 1; - bool x160_31_cardBusy : 1; - bool x161_24_gameFrameDrawn : 1; - }; - u16 _dummy = 0; + union { + struct { + bool x160_24_finished : 1; + bool x160_25_mfGameBuilt : 1; + bool x160_26_screenFading : 1; + bool x160_27_ : 1; + bool x160_28_manageCard : 1; + bool x160_29_ : 1; + bool x160_30_ : 1; + bool x160_31_cardBusy : 1; + bool x161_24_gameFrameDrawn : 1; }; + u16 _dummy = 0; + }; - std::unique_ptr x164_archSupport; + std::unique_ptr x164_archSupport; - boo::IWindow* m_mainWindow = nullptr; + boo::IWindow* m_mainWindow = nullptr; - hecl::CVarManager* m_cvarMgr = nullptr; - std::unique_ptr m_console; - // Warmup state - std::vector m_warmupTags; - std::vector::iterator m_warmupIt; - bool m_needsWarmupClear = false; - bool m_doQuit = false; + hecl::CVarManager* m_cvarMgr = nullptr; + std::unique_ptr m_console; + // Warmup state + std::vector m_warmupTags; + std::vector::iterator m_warmupIt; + bool m_needsWarmupClear = false; + bool m_doQuit = false; - void InitializeSubsystems(); - static void InitializeDiscord(); - static void ShutdownDiscord(); - static void HandleDiscordReady(const DiscordUser* request); - static void HandleDiscordDisconnected(int errorCode, const char* message); - static void HandleDiscordErrored(int errorCode, const char* message); + void InitializeSubsystems(); + static void InitializeDiscord(); + static void ShutdownDiscord(); + static void HandleDiscordReady(const DiscordUser* request); + static void HandleDiscordDisconnected(int errorCode, const char* message); + static void HandleDiscordErrored(int errorCode, const char* message); public: - CMain(IFactory* resFactory, CSimplePool* resStore, - boo::IGraphicsDataFactory* gfxFactory, - boo::IGraphicsCommandQueue* cmdQ, - const boo::ObjToken& spareTex); - void RegisterResourceTweaks(); - void AddWorldPaks(); - void ResetGameState(); - void StreamNewGameState(CBitStreamReader&, u32 idx); - void RefreshGameState(); - void CheckTweakManagerDebugOptions() {} - void SetMFGameBuilt(bool b) { x160_25_mfGameBuilt = b; } - void SetScreenFading(bool b) { x160_26_screenFading = b; } - bool GetScreenFading() const { return x160_26_screenFading; } + CMain(IFactory* resFactory, CSimplePool* resStore, boo::IGraphicsDataFactory* gfxFactory, + boo::IGraphicsCommandQueue* cmdQ, const boo::ObjToken& spareTex); + void RegisterResourceTweaks(); + void AddWorldPaks(); + void ResetGameState(); + void StreamNewGameState(CBitStreamReader&, u32 idx); + void RefreshGameState(); + void CheckTweakManagerDebugOptions() {} + void SetMFGameBuilt(bool b) { x160_25_mfGameBuilt = b; } + void SetScreenFading(bool b) { x160_26_screenFading = b; } + bool GetScreenFading() const { return x160_26_screenFading; } - static void UpdateDiscordPresence(CAssetId worldSTRG = {}); + static void UpdateDiscordPresence(CAssetId worldSTRG = {}); - //int RsMain(int argc, const boo::SystemChar* argv[]); - void Init(const hecl::Runtime::FileStoreManager& storeMgr, - hecl::CVarManager* cvarManager, - boo::IWindow* window, - boo::IAudioVoiceEngine* voiceEngine, - amuse::IBackendVoiceAllocator& backend); - void WarmupShaders(); - bool Proc(); - void Draw(); - void Shutdown(); - boo::IWindow* GetMainWindow() const; + // int RsMain(int argc, const boo::SystemChar* argv[]); + void Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarManager* cvarManager, boo::IWindow* window, + boo::IAudioVoiceEngine* voiceEngine, amuse::IBackendVoiceAllocator& backend); + void WarmupShaders(); + bool Proc(); + void Draw(); + void Shutdown(); + boo::IWindow* GetMainWindow() const; - void MemoryCardInitializePump(); + void MemoryCardInitializePump(); - bool CheckReset() { return m_doQuit; } - bool CheckTerminate() { return m_doQuit; } - void DrawDebugMetrics(double, CStopwatch&) {} - void DoPredrawMetrics() {} - void FillInAssetIDs(); - bool LoadAudio(); - void ShutdownSubsystems(); - EGameplayResult GetGameplayResult() const { return xe4_gameplayResult; } - void SetGameplayResult(EGameplayResult wl) { xe4_gameplayResult = wl; } - void SetManageCard(bool v) { x160_28_manageCard = v; } - bool GetCardBusy() const { return x160_31_cardBusy; } - void SetCardBusy(bool v) { x160_31_cardBusy = v; } - void SetGameFrameDrawn() { x161_24_gameFrameDrawn = true; } - static void EnsureWorldPaksReady(); - static void EnsureWorldPakReady(CAssetId mlvl); + bool CheckReset() { return m_doQuit; } + bool CheckTerminate() { return m_doQuit; } + void DrawDebugMetrics(double, CStopwatch&) {} + void DoPredrawMetrics() {} + void FillInAssetIDs(); + bool LoadAudio(); + void ShutdownSubsystems(); + EGameplayResult GetGameplayResult() const { return xe4_gameplayResult; } + void SetGameplayResult(EGameplayResult wl) { xe4_gameplayResult = wl; } + void SetManageCard(bool v) { x160_28_manageCard = v; } + bool GetCardBusy() const { return x160_31_cardBusy; } + void SetCardBusy(bool v) { x160_31_cardBusy = v; } + void SetGameFrameDrawn() { x161_24_gameFrameDrawn = true; } + static void EnsureWorldPaksReady(); + static void EnsureWorldPakReady(CAssetId mlvl); - EFlowState GetFlowState() const { return x12c_flowState; } - void SetFlowState(EFlowState s) { x12c_flowState = s; } + EFlowState GetFlowState() const { return x12c_flowState; } + void SetFlowState(EFlowState s) { x12c_flowState = s; } - void SetX30(bool v) { x160_30_ = v; } + void SetX30(bool v) { x160_30_ = v; } - CGameArchitectureSupport* GetArchSupport() const { return x164_archSupport.get(); } + CGameArchitectureSupport* GetArchSupport() const { return x164_archSupport.get(); } - size_t GetExpectedIdSize() const { return sizeof(u32); } - void quit(hecl::Console*, const std::vector&) - { - m_doQuit = true; - } - void Give(hecl::Console*, const std::vector&); - void God(hecl::Console*, const std::vector&); - void Teleport(hecl::Console*, const std::vector&); - void ListWorlds(hecl::Console*, const std::vector&); - void WarpTo(hecl::Console*, const std::vector&); - hecl::Console* Console() const { return m_console.get(); } + size_t GetExpectedIdSize() const { return sizeof(u32); } + void quit(hecl::Console*, const std::vector&) { m_doQuit = true; } + void Give(hecl::Console*, const std::vector&); + void God(hecl::Console*, const std::vector&); + void Teleport(hecl::Console*, const std::vector&); + void ListWorlds(hecl::Console*, const std::vector&); + void WarpTo(hecl::Console*, const std::vector&); + hecl::Console* Console() const { return m_console.get(); } - int m_warpWorldIdx = -1; - TAreaId m_warpAreaId = 0; - u64 m_warpLayerBits = 0; + int m_warpWorldIdx = -1; + TAreaId m_warpAreaId = 0; + u64 m_warpLayerBits = 0; }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/MP1OriginalIDs.cpp b/Runtime/MP1/MP1OriginalIDs.cpp index 0ef1dfdc8..5d4e7a20c 100644 --- a/Runtime/MP1/MP1OriginalIDs.cpp +++ b/Runtime/MP1/MP1OriginalIDs.cpp @@ -1,51 +1,43 @@ #include "MP1OriginalIDs.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { -MP1OriginalIDs::MP1OriginalIDs(CInputStream& in) -{ - u32 count = in.readUint32Big(); - m_origToNew.reserve(count); - for (u32 i=0 ; isecond; +CAssetId MP1OriginalIDs::TranslateOriginalToNew(CAssetId id) const { + auto search = + rstl::binary_find(m_origToNew.cbegin(), m_origToNew.cend(), id, [](const auto& id) { return id.first; }); + if (search == m_origToNew.cend()) + return {}; + return search->second; } -CAssetId MP1OriginalIDs::TranslateNewToOriginal(CAssetId id) const -{ - auto search = rstl::binary_find(m_newToOrig.cbegin(), m_newToOrig.cend(), id, - [](const auto& id) { return id.first; }); - if (search == m_newToOrig.cend()) - return {}; - return search->second; +CAssetId MP1OriginalIDs::TranslateNewToOriginal(CAssetId id) const { + auto search = + rstl::binary_find(m_newToOrig.cbegin(), m_newToOrig.cend(), id, [](const auto& id) { return id.first; }); + if (search == m_newToOrig.cend()) + return {}; + return search->second; } -CFactoryFnReturn FMP1OriginalIDsFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& param, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); +CFactoryFnReturn FMP1OriginalIDsFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, + CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(in)); } -} +} // namespace urde diff --git a/Runtime/MP1/MP1OriginalIDs.hpp b/Runtime/MP1/MP1OriginalIDs.hpp index d1ee2d9b3..74d721f6d 100644 --- a/Runtime/MP1/MP1OriginalIDs.hpp +++ b/Runtime/MP1/MP1OriginalIDs.hpp @@ -3,23 +3,19 @@ #include "RetroTypes.hpp" #include "IFactory.hpp" -namespace urde -{ +namespace urde { -class MP1OriginalIDs -{ - std::vector> m_origToNew; - std::vector> m_newToOrig; +class MP1OriginalIDs { + std::vector> m_origToNew; + std::vector> m_newToOrig; public: - MP1OriginalIDs(CInputStream& in); - CAssetId TranslateOriginalToNew(CAssetId id) const; - CAssetId TranslateNewToOriginal(CAssetId id) const; + MP1OriginalIDs(CInputStream& in); + CAssetId TranslateOriginalToNew(CAssetId id) const; + CAssetId TranslateNewToOriginal(CAssetId id) const; }; -CFactoryFnReturn FMP1OriginalIDsFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& param, +CFactoryFnReturn FMP1OriginalIDsFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& param, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/MP1/World/CActorContraption.cpp b/Runtime/MP1/World/CActorContraption.cpp index 1716ea14f..7ff4c7875 100644 --- a/Runtime/MP1/World/CActorContraption.cpp +++ b/Runtime/MP1/World/CActorContraption.cpp @@ -7,97 +7,83 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { MP1::CActorContraption::CActorContraption(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& aabox, - const CMaterialList& matList, float mass, float zMomentum, const CHealthInfo& hInfo, - const CDamageVulnerability& dVuln, const CActorParameters& aParams, - CAssetId part, const CDamageInfo& dInfo, bool active) -: CScriptActor(uid, name, info, xf, std::move(mData), aabox, mass, zMomentum, matList, hInfo, dVuln, aParams, false, active, 0, - 1.f, false, false, false, false) + const CMaterialList& matList, float mass, float zMomentum, + const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, + const CActorParameters& aParams, CAssetId part, const CDamageInfo& dInfo, + bool active) +: CScriptActor(uid, name, info, xf, std::move(mData), aabox, mass, zMomentum, matList, hInfo, dVuln, aParams, false, + active, 0, 1.f, false, false, false, false) , x300_flameThrowerGen(g_SimplePool->GetObj("FlameThrower")) , x308_flameFxId(part) -, x30c_dInfo(dInfo) -{ -} +, x30c_dInfo(dInfo) {} void MP1::CActorContraption::Accept(IVisitor& visitor) { visitor.Visit(this); } -void MP1::CActorContraption::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - bool curActive = GetActive(); - if (msg == EScriptObjectMessage::Registered) - AddMaterial(EMaterialTypes::ScanPassthrough, mgr); - else if (msg == EScriptObjectMessage::SetToZero) - ResetFlameThrowers(mgr); - - CScriptActor::AcceptScriptMsg(msg, uid, mgr); - if (curActive == GetActive() || !GetActive()) - return; - +void MP1::CActorContraption::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + bool curActive = GetActive(); + if (msg == EScriptObjectMessage::Registered) + AddMaterial(EMaterialTypes::ScanPassthrough, mgr); + else if (msg == EScriptObjectMessage::SetToZero) ResetFlameThrowers(mgr); + + CScriptActor::AcceptScriptMsg(msg, uid, mgr); + if (curActive == GetActive() || !GetActive()) + return; + + ResetFlameThrowers(mgr); } -void MP1::CActorContraption::Think(float dt, CStateManager& mgr) -{ - CScriptActor::Think(dt, mgr); +void MP1::CActorContraption::Think(float dt, CStateManager& mgr) { + CScriptActor::Think(dt, mgr); - for (const std::pair& uid : x2e8_children) - { - CFlameThrower* act = static_cast(mgr.ObjectById(uid.first)); + for (const std::pair& uid : x2e8_children) { + CFlameThrower* act = static_cast(mgr.ObjectById(uid.first)); - if (act && act->GetActive()) - act->SetTransform(x34_transform * act->GetScaledLocatorTransform(uid.second)); - } + if (act && act->GetActive()) + act->SetTransform(x34_transform * act->GetScaledLocatorTransform(uid.second)); + } } -void MP1::CActorContraption::ResetFlameThrowers(CStateManager& mgr) -{ - for (const std::pair& uid : x2e8_children) - { - CFlameThrower* act = static_cast(mgr.ObjectById(uid.first)); - if (act && !act->GetX400_25()) - act->Reset(mgr, false); - } +void MP1::CActorContraption::ResetFlameThrowers(CStateManager& mgr) { + for (const std::pair& uid : x2e8_children) { + CFlameThrower* act = static_cast(mgr.ObjectById(uid.first)); + if (act && !act->GetX400_25()) + act->Reset(mgr, false); + } } -void MP1::CActorContraption::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType evType, float dt) -{ - if (evType == EUserEventType::DamageOff) - { - ResetFlameThrowers(mgr); - } - else if (evType == EUserEventType::DamageOn) - { - CFlameThrower* fl = CreateFlameThrower(node.GetLocatorName(), mgr); - if (fl && fl->GetX400_25()) - fl->Fire(GetTransform(), mgr, false); - } - else - CActor::DoUserAnimEvent(mgr, node, evType, dt); +void MP1::CActorContraption::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType evType, + float dt) { + if (evType == EUserEventType::DamageOff) { + ResetFlameThrowers(mgr); + } else if (evType == EUserEventType::DamageOn) { + CFlameThrower* fl = CreateFlameThrower(node.GetLocatorName(), mgr); + if (fl && fl->GetX400_25()) + fl->Fire(GetTransform(), mgr, false); + } else + CActor::DoUserAnimEvent(mgr, node, evType, dt); } -CFlameThrower* MP1::CActorContraption::CreateFlameThrower(std::string_view name, CStateManager& mgr) -{ - const auto& it = std::find_if(x2e8_children.begin(), x2e8_children.end(), - [&name](const std::pair& p) { return p.second == name; }); +CFlameThrower* MP1::CActorContraption::CreateFlameThrower(std::string_view name, CStateManager& mgr) { + const auto& it = std::find_if(x2e8_children.begin(), x2e8_children.end(), + [&name](const std::pair& p) { return p.second == name; }); - if (it == x2e8_children.end()) - { - TUniqueId id = mgr.AllocateUniqueId(); - CFlameInfo flameInfo(6, 6, x308_flameFxId, 20, 0.5f, 1.f, 1.f); - CFlameThrower* ret = new CFlameThrower(x300_flameThrowerGen, name, EWeaponType::Missile, flameInfo, - zeus::CTransform::Identity(), EMaterialTypes::CollisionActor, x30c_dInfo, - id, GetAreaId(), GetUniqueId(), EProjectileAttrib::None, - -1, -1, -1); + if (it == x2e8_children.end()) { + TUniqueId id = mgr.AllocateUniqueId(); + CFlameInfo flameInfo(6, 6, x308_flameFxId, 20, 0.5f, 1.f, 1.f); + CFlameThrower* ret = new CFlameThrower(x300_flameThrowerGen, name, EWeaponType::Missile, flameInfo, + zeus::CTransform::Identity(), EMaterialTypes::CollisionActor, x30c_dInfo, id, + GetAreaId(), GetUniqueId(), EProjectileAttrib::None, -1, -1, -1); - x2e8_children.emplace_back(id, name); + x2e8_children.emplace_back(id, name); - mgr.AddObject(ret); - return ret; - } - return static_cast(mgr.ObjectById(it->first)); -} + mgr.AddObject(ret); + return ret; + } + return static_cast(mgr.ObjectById(it->first)); } +} // namespace urde diff --git a/Runtime/MP1/World/CActorContraption.hpp b/Runtime/MP1/World/CActorContraption.hpp index b562b6d4c..abd8adeb8 100644 --- a/Runtime/MP1/World/CActorContraption.hpp +++ b/Runtime/MP1/World/CActorContraption.hpp @@ -3,30 +3,27 @@ #include "World/CScriptActor.hpp" #include "World/CDamageInfo.hpp" -namespace urde -{ +namespace urde { class CFlameThrower; -namespace MP1 -{ -class CActorContraption : public CScriptActor -{ - /* AKA Why Zoid?!?!?!? */ - std::vector> x2e8_children; - TToken x300_flameThrowerGen; - CAssetId x308_flameFxId; - CDamageInfo x30c_dInfo; +namespace MP1 { +class CActorContraption : public CScriptActor { + /* AKA Why Zoid?!?!?!? */ + std::vector> x2e8_children; + TToken x300_flameThrowerGen; + CAssetId x308_flameFxId; + CDamageInfo x30c_dInfo; + public: - CActorContraption(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const zeus::CAABox&, const CMaterialList&, float, float, const CHealthInfo&, - const CDamageVulnerability&, const CActorParameters&, CAssetId, const CDamageInfo&, bool); + CActorContraption(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const zeus::CAABox&, const CMaterialList&, float, float, const CHealthInfo&, + const CDamageVulnerability&, const CActorParameters&, CAssetId, const CDamageInfo&, bool); - void Accept(IVisitor &visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); - void Think(float, CStateManager &); - void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt); - CFlameThrower* CreateFlameThrower(std::string_view, CStateManager&); - void ResetFlameThrowers(CStateManager& mgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt); + CFlameThrower* CreateFlameThrower(std::string_view, CStateManager&); + void ResetFlameThrowers(CStateManager& mgr); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/World/CAtomicAlpha.cpp b/Runtime/MP1/World/CAtomicAlpha.cpp index 191ef8b61..d1e6bb761 100644 --- a/Runtime/MP1/World/CAtomicAlpha.cpp +++ b/Runtime/MP1/World/CAtomicAlpha.cpp @@ -1,14 +1,10 @@ #include "CAtomicAlpha.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CAtomicAlpha::CAtomicAlpha(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, CAssetId wpsc, const CDamageInfo& dInfo, float f1, float f2, float f3, CAssetId cmdl, bool b1, bool b2) - : CPatterned(ECharacter::AtomicAlpha, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, actParms, EKnockBackVariant::Medium) -{ - -} -} +: CPatterned(ECharacter::AtomicAlpha, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, actParms, EKnockBackVariant::Medium) {} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CAtomicAlpha.hpp b/Runtime/MP1/World/CAtomicAlpha.hpp index dcdf2062d..cf3b30de1 100644 --- a/Runtime/MP1/World/CAtomicAlpha.hpp +++ b/Runtime/MP1/World/CAtomicAlpha.hpp @@ -2,15 +2,12 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ -class CAtomicAlpha : public CPatterned -{ +namespace urde::MP1 { +class CAtomicAlpha : public CPatterned { public: - DEFINE_PATTERNED(AtomicAlpha) - CAtomicAlpha(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CActorParameters&, const CPatternedInfo&, CAssetId, const CDamageInfo&, float, float, float, - CAssetId, bool, bool); + DEFINE_PATTERNED(AtomicAlpha) + CAtomicAlpha(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const CPatternedInfo&, CAssetId, const CDamageInfo&, float, float, float, + CAssetId, bool, bool); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CBabygoth.cpp b/Runtime/MP1/World/CBabygoth.cpp index 883ed10f6..be3ac1b8e 100644 --- a/Runtime/MP1/World/CBabygoth.cpp +++ b/Runtime/MP1/World/CBabygoth.cpp @@ -1,7 +1,6 @@ #include "CBabygoth.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CBabygothData::CBabygothData(CInputStream& in) : x0_(in.readFloatBig()) , x4_(in.readFloatBig()) @@ -28,15 +27,11 @@ CBabygothData::CBabygothData(CInputStream& in) , x168_(in.readFloatBig()) , x16c_(in) , x170_(CSfxManager::TranslateSFXID(in.readUint32Big())) -, x174_(in) -{ -} +, x174_(in) {} CBabygoth::CBabygoth(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, const CBabygothData& babyData) -: CPatterned(ECharacter::Babygoth, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground, - EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Medium) -{ - -} -} + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, + const CBabygothData& babyData) +: CPatterned(ECharacter::Babygoth, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Medium) {} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CBabygoth.hpp b/Runtime/MP1/World/CBabygoth.hpp index 9fd8be32b..be7b0acf6 100644 --- a/Runtime/MP1/World/CBabygoth.hpp +++ b/Runtime/MP1/World/CBabygoth.hpp @@ -2,56 +2,54 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ -class CBabygothData -{ - float x0_; - float x4_; - CAssetId x8_; - CDamageInfo xc_; - CDamageInfo x28_; - CAssetId x44_; - CAssetId x48_; - CDamageInfo x4c_; - CDamageVulnerability x68_; - CDamageVulnerability xd0_; - CAssetId x138_; - CAssetId x13c_; - float x140_; - s16 x144_; - CAssetId x148_; - CAssetId x14c_; - CAssetId x150_; - CAssetId x154_; - s16 x158_; - s16 x15a_; - s16 x15c_; - float x160_; - float x164_; - float x168_; - CAssetId x16c_; - s16 x170_; - CAssetId x174_; +namespace urde::MP1 { +class CBabygothData { + float x0_; + float x4_; + CAssetId x8_; + CDamageInfo xc_; + CDamageInfo x28_; + CAssetId x44_; + CAssetId x48_; + CDamageInfo x4c_; + CDamageVulnerability x68_; + CDamageVulnerability xd0_; + CAssetId x138_; + CAssetId x13c_; + float x140_; + s16 x144_; + CAssetId x148_; + CAssetId x14c_; + CAssetId x150_; + CAssetId x154_; + s16 x158_; + s16 x15a_; + s16 x15c_; + float x160_; + float x164_; + float x168_; + CAssetId x16c_; + s16 x170_; + CAssetId x174_; + public: - CBabygothData(CInputStream&); - CAssetId GetShellModelResId() const; - void GetFireballDamage() const; - CAssetId GetFireballResID() const; - const CDamageVulnerability& GetShellDamageVulnerability() const; - void GetSHellHitPoints() const; - void GetFireballAttackVariance() const; - void GetFireballAttackTime() const; - void GetFireBreathDamage() const; - CAssetId GetFireBreathResId() const; + CBabygothData(CInputStream&); + CAssetId GetShellModelResId() const; + void GetFireballDamage() const; + CAssetId GetFireballResID() const; + const CDamageVulnerability& GetShellDamageVulnerability() const; + void GetSHellHitPoints() const; + void GetFireballAttackVariance() const; + void GetFireballAttackTime() const; + void GetFireBreathDamage() const; + CAssetId GetFireBreathResId() const; }; -class CBabygoth : public CPatterned -{ +class CBabygoth : public CPatterned { public: - DEFINE_PATTERNED(Babygoth) - CBabygoth(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, const CActorParameters&, const CBabygothData&); + DEFINE_PATTERNED(Babygoth) + CBabygoth(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, const CActorParameters&, const CBabygothData&); }; -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CBeetle.cpp b/Runtime/MP1/World/CBeetle.cpp index 0043565aa..366eda7f2 100644 --- a/Runtime/MP1/World/CBeetle.cpp +++ b/Runtime/MP1/World/CBeetle.cpp @@ -3,22 +3,16 @@ #include "Character/CCharLayoutInfo.hpp" #include "TCastTo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -CBeetle::CBeetle(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, - const CPatternedInfo& pInfo, CPatterned::EFlavorType flavor, CBeetle::EEntranceType, const CDamageInfo&, - const CDamageVulnerability&, const zeus::CVector3f&, float, float, float, const CDamageVulnerability&, - const CActorParameters& aParams, const std::experimental::optional) - : CPatterned(ECharacter::Beetle, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Ground, - EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant(flavor)) -{ +CBeetle::CBeetle(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CPatternedInfo& pInfo, CPatterned::EFlavorType flavor, + CBeetle::EEntranceType, const CDamageInfo&, const CDamageVulnerability&, const zeus::CVector3f&, float, + float, float, const CDamageVulnerability&, const CActorParameters& aParams, + const std::experimental::optional) +: CPatterned(ECharacter::Beetle, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Ground, + EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant(flavor)) {} -} +void CBeetle::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CBeetle::Accept(IVisitor &visitor) -{ - visitor.Visit(this); -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CBeetle.hpp b/Runtime/MP1/World/CBeetle.hpp index ba9d0ee5c..625295ecb 100644 --- a/Runtime/MP1/World/CBeetle.hpp +++ b/Runtime/MP1/World/CBeetle.hpp @@ -2,30 +2,23 @@ #include "World/CPatterned.hpp" -namespace urde -{ +namespace urde { class CDamageInfo; -namespace MP1 -{ -class CBeetle : public CPatterned -{ +namespace MP1 { +class CBeetle : public CPatterned { public: - enum class EEntranceType : u32 - { - FacePlayer, - UseOrientation - }; + enum class EEntranceType : u32 { FacePlayer, UseOrientation }; + private: public: - DEFINE_PATTERNED(Beetle) - CBeetle(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, CPatterned::EFlavorType,EEntranceType, const CDamageInfo &, const CDamageVulnerability&, - const zeus::CVector3f&, float, float, float, const CDamageVulnerability&, const CActorParameters&, - const std::experimental::optional); + DEFINE_PATTERNED(Beetle) + CBeetle(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CPatternedInfo&, + CPatterned::EFlavorType, EEntranceType, const CDamageInfo&, const CDamageVulnerability&, + const zeus::CVector3f&, float, float, float, const CDamageVulnerability&, const CActorParameters&, + const std::experimental::optional); - void Accept(IVisitor &visitor); + void Accept(IVisitor& visitor); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/World/CBloodFlower.cpp b/Runtime/MP1/World/CBloodFlower.cpp index 9d4c17f90..26fba29be 100644 --- a/Runtime/MP1/World/CBloodFlower.cpp +++ b/Runtime/MP1/World/CBloodFlower.cpp @@ -1,12 +1,11 @@ #include "CBloodFlower.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CBloodFlower::CBloodFlower(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, CAssetId partId1, CAssetId wpscId1, const CActorParameters& actParms, CAssetId wpscId2, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2, const CDamageInfo& dInfo3, CAssetId partId2, CAssetId partId3, CAssetId partId4, float f1, CAssetId partId5, u32 soundId) - : CPatterned(ECharacter::BloodFlower, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Medium) {} -} \ No newline at end of file +: CPatterned(ECharacter::BloodFlower, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Ground, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Medium) {} +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CBloodFlower.hpp b/Runtime/MP1/World/CBloodFlower.hpp index 88e717d3c..1eb1040ff 100644 --- a/Runtime/MP1/World/CBloodFlower.hpp +++ b/Runtime/MP1/World/CBloodFlower.hpp @@ -2,15 +2,13 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ -class CBloodFlower : public CPatterned -{ +namespace urde::MP1 { +class CBloodFlower : public CPatterned { public: - DEFINE_PATTERNED(BloodFlower) + DEFINE_PATTERNED(BloodFlower) - CBloodFlower(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, CAssetId, CAssetId, const CActorParameters&, CAssetId, const CDamageInfo&, - const CDamageInfo&, const CDamageInfo&, CAssetId, CAssetId, CAssetId, float, CAssetId, u32); + CBloodFlower(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, CAssetId, CAssetId, const CActorParameters&, CAssetId, const CDamageInfo&, + const CDamageInfo&, const CDamageInfo&, CAssetId, CAssetId, CAssetId, float, CAssetId, u32); }; -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CBurrower.cpp b/Runtime/MP1/World/CBurrower.cpp index de3d9c9dc..2ae618835 100644 --- a/Runtime/MP1/World/CBurrower.cpp +++ b/Runtime/MP1/World/CBurrower.cpp @@ -1,28 +1,21 @@ #include "CBurrower.hpp" #include "CStateManager.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CBurrower::CBurrower(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, - CAssetId, CAssetId, CAssetId, const CDamageInfo&, CAssetId, u32, CAssetId) + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CAssetId, + CAssetId, CAssetId, const CDamageInfo&, CAssetId, u32, CAssetId) : CPatterned(ECharacter::Burrower, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Small) -{ + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Small) {} +void CBurrower::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); + if (msg == EScriptObjectMessage::Registered) + x450_bodyController->Activate(mgr); + else if (msg == EScriptObjectMessage::InitializedInArea) { + + } else if (msg == EScriptObjectMessage::InvulnDamage) + x6a4_ = 1.f; } - -void CBurrower::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CPatterned::AcceptScriptMsg(msg, uid, mgr); - if (msg == EScriptObjectMessage::Registered) - x450_bodyController->Activate(mgr); - else if (msg == EScriptObjectMessage::InitializedInArea) - { - - } - else if (msg == EScriptObjectMessage::InvulnDamage) - x6a4_ = 1.f; -} -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CBurrower.hpp b/Runtime/MP1/World/CBurrower.hpp index cdad65507..630529bdd 100644 --- a/Runtime/MP1/World/CBurrower.hpp +++ b/Runtime/MP1/World/CBurrower.hpp @@ -2,18 +2,17 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { + +class CBurrower : public CPatterned { + float x6a4_ = 0.f; -class CBurrower : public CPatterned -{ - float x6a4_ = 0.f; public: - DEFINE_PATTERNED(Burrower) - CBurrower(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, const CActorParameters&, CAssetId, CAssetId, CAssetId, const CDamageInfo&, CAssetId, u32, - CAssetId); + DEFINE_PATTERNED(Burrower) + CBurrower(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, const CActorParameters&, CAssetId, CAssetId, CAssetId, const CDamageInfo&, CAssetId, + u32, CAssetId); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); }; -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CChozoGhost.cpp b/Runtime/MP1/World/CChozoGhost.cpp index 105b77408..47f42a46f 100644 --- a/Runtime/MP1/World/CChozoGhost.cpp +++ b/Runtime/MP1/World/CChozoGhost.cpp @@ -1,29 +1,28 @@ #include "CChozoGhost.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CChozoGhost::CBehaveChance::CBehaveChance(CInputStream& in) - : x0_propertyCount(in.readUint32Big()), x4_(in.readFloatBig()), x8_(in.readFloatBig()), xc_(in.readFloatBig()), - x10_(in.readFloatBig()), x14_(in.readFloatBig()), x18_(x0_propertyCount <= 5 ? 0.5f : in.readFloatBig() * .01f), - x1c_(x0_propertyCount <= 6 ? 2 : in.readUint32Big()) -{ - float f2 = 1.f / (x10_ + xc_ + x4_ + x8_); - x4_ *= f2; - x8_ *= f2; - xc_ *= f2; - x10_ *= f2; +: x0_propertyCount(in.readUint32Big()) +, x4_(in.readFloatBig()) +, x8_(in.readFloatBig()) +, xc_(in.readFloatBig()) +, x10_(in.readFloatBig()) +, x14_(in.readFloatBig()) +, x18_(x0_propertyCount <= 5 ? 0.5f : in.readFloatBig() * .01f) +, x1c_(x0_propertyCount <= 6 ? 2 : in.readUint32Big()) { + float f2 = 1.f / (x10_ + xc_ + x4_ + x8_); + x4_ *= f2; + x8_ *= f2; + xc_ *= f2; + x10_ *= f2; } - CChozoGhost::CChozoGhost(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, float f1, float f2, float f3, float f4, CAssetId wpsc1, const CDamageInfo& dInfo1, CAssetId wpsc2, const CDamageInfo& dInfo2, const CBehaveChance& chance1, const CBehaveChance& chance2, const CBehaveChance& chance3, u16 sId1, float f5, u16 sId2, u16 sId3, u32 w1, float f6, u32 w2, float f7, CAssetId partId, s16 sId4, float f8, float f9, u32 w3, u32 w4) - : CPatterned(ECharacter::ChozoGhost, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::Zero, EBodyType::BiPedal, actParms, EKnockBackVariant::Medium) -{ - -} -} \ No newline at end of file +: CPatterned(ECharacter::ChozoGhost, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Flyer, EColliderType::Zero, EBodyType::BiPedal, actParms, EKnockBackVariant::Medium) {} +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CChozoGhost.hpp b/Runtime/MP1/World/CChozoGhost.hpp index f625b5f49..adf9cb918 100644 --- a/Runtime/MP1/World/CChozoGhost.hpp +++ b/Runtime/MP1/World/CChozoGhost.hpp @@ -2,33 +2,31 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ -class CChozoGhost : public CPatterned -{ +namespace urde::MP1 { +class CChozoGhost : public CPatterned { public: - class CBehaveChance - { - u32 x0_propertyCount; - float x4_; - float x8_; - float xc_; - float x10_; - float x14_; - float x18_; - u32 x1c_; - public: - CBehaveChance(CInputStream&); - }; + class CBehaveChance { + u32 x0_propertyCount; + float x4_; + float x8_; + float xc_; + float x10_; + float x14_; + float x18_; + u32 x1c_; + + public: + CBehaveChance(CInputStream&); + }; private: public: - DEFINE_PATTERNED(ChozoGhost) + DEFINE_PATTERNED(ChozoGhost) - CChozoGhost(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CActorParameters&, const CPatternedInfo&, float, float, float, float, CAssetId, - const CDamageInfo&, CAssetId, const CDamageInfo&, const CChozoGhost::CBehaveChance&, - const CChozoGhost::CBehaveChance&, const CBehaveChance&, u16, float, u16, u16, u32, float, u32, float, - CAssetId, s16, float, float, u32, u32); + CChozoGhost(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const CPatternedInfo&, float, float, float, float, CAssetId, const CDamageInfo&, + CAssetId, const CDamageInfo&, const CChozoGhost::CBehaveChance&, const CChozoGhost::CBehaveChance&, + const CBehaveChance&, u16, float, u16, u16, u32, float, u32, float, CAssetId, s16, float, float, u32, + u32); }; -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CElitePirate.cpp b/Runtime/MP1/World/CElitePirate.cpp index c7f9336d2..76e96f051 100644 --- a/Runtime/MP1/World/CElitePirate.cpp +++ b/Runtime/MP1/World/CElitePirate.cpp @@ -1,26 +1,47 @@ #include "CElitePirate.hpp" #include "World/ScriptLoader.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CElitePirateData::CElitePirateData(CInputStream& in, u32 propCount) - : x0_(in.readFloatBig()), x4_(in.readFloatBig()), x8_(in.readFloatBig()), xc_(in.readFloatBig()), - x10_(in.readFloatBig()), x14_(in.readFloatBig()), x18_(in.readFloatBig()), x1c_(in.readFloatBig()), x20_(in), - x24_(CSfxManager::TranslateSFXID(in.readUint32Big())), x28_(ScriptLoader::LoadActorParameters(in)), - x90_(ScriptLoader::LoadAnimationParameters(in)), x9c_(in), xa0_(CSfxManager::TranslateSFXID(in.readUint32Big())), - xa4_(in), xa8_(in), xc4_(in.readFloatBig()), xc8_(in), xcc_(in), xd0_(in), xd4_(in), xd8_(in.readFloatBig()), - xdc_(in.readFloatBig()), xe0_(in.readFloatBig()), xe4_(in.readFloatBig()), - xe8_(zeus::degToRad(in.readFloatBig())), xec_(zeus::degToRad(in.readFloatBig())), xf0_(in.readUint32Big()), - xf4_(CSfxManager::TranslateSFXID(in.readUint32Big())), xf8_(in), xfc_(in), x118_(in), - x11c_(CSfxManager::TranslateSFXID(in.readUint32Big())), x11e_(in.readBool()), - x11f_(propCount < 24 ? true : in.readBool()) {} +: x0_(in.readFloatBig()) +, x4_(in.readFloatBig()) +, x8_(in.readFloatBig()) +, xc_(in.readFloatBig()) +, x10_(in.readFloatBig()) +, x14_(in.readFloatBig()) +, x18_(in.readFloatBig()) +, x1c_(in.readFloatBig()) +, x20_(in) +, x24_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x28_(ScriptLoader::LoadActorParameters(in)) +, x90_(ScriptLoader::LoadAnimationParameters(in)) +, x9c_(in) +, xa0_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xa4_(in) +, xa8_(in) +, xc4_(in.readFloatBig()) +, xc8_(in) +, xcc_(in) +, xd0_(in) +, xd4_(in) +, xd8_(in.readFloatBig()) +, xdc_(in.readFloatBig()) +, xe0_(in.readFloatBig()) +, xe4_(in.readFloatBig()) +, xe8_(zeus::degToRad(in.readFloatBig())) +, xec_(zeus::degToRad(in.readFloatBig())) +, xf0_(in.readUint32Big()) +, xf4_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xf8_(in) +, xfc_(in) +, x118_(in) +, x11c_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x11e_(in.readBool()) +, x11f_(propCount < 24 ? true : in.readBool()) {} CElitePirate::CElitePirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, const CElitePirateData& eliteData) - : CPatterned(ECharacter::ElitePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Large) -{ - -} -} +: CPatterned(ECharacter::ElitePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Large) {} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CElitePirate.hpp b/Runtime/MP1/World/CElitePirate.hpp index 3eb6c1803..8227ffbf7 100644 --- a/Runtime/MP1/World/CElitePirate.hpp +++ b/Runtime/MP1/World/CElitePirate.hpp @@ -4,55 +4,53 @@ #include "World/CActorParameters.hpp" #include "World/CAnimationParameters.hpp" -namespace urde::MP1 -{ -class CElitePirateData -{ - float x0_; - float x4_; - float x8_; - float xc_; - float x10_; - float x14_; - float x18_; - float x1c_; - CAssetId x20_; - s16 x24_; - CActorParameters x28_; - CAnimationParameters x90_; - CAssetId x9c_; - s16 xa0_; - CAssetId xa4_; - CDamageInfo xa8_; - float xc4_; - CAssetId xc8_; - CAssetId xcc_; - CAssetId xd0_; - CAssetId xd4_; - float xd8_; - float xdc_; - float xe0_; - float xe4_; - float xe8_; - float xec_; - u32 xf0_; - u32 xf4_; - CAssetId xf8_; - CDamageInfo xfc_; - CAssetId x118_; - s16 x11c_; - bool x11e_; - bool x11f_; +namespace urde::MP1 { +class CElitePirateData { + float x0_; + float x4_; + float x8_; + float xc_; + float x10_; + float x14_; + float x18_; + float x1c_; + CAssetId x20_; + s16 x24_; + CActorParameters x28_; + CAnimationParameters x90_; + CAssetId x9c_; + s16 xa0_; + CAssetId xa4_; + CDamageInfo xa8_; + float xc4_; + CAssetId xc8_; + CAssetId xcc_; + CAssetId xd0_; + CAssetId xd4_; + float xd8_; + float xdc_; + float xe0_; + float xe4_; + float xe8_; + float xec_; + u32 xf0_; + u32 xf4_; + CAssetId xf8_; + CDamageInfo xfc_; + CAssetId x118_; + s16 x11c_; + bool x11e_; + bool x11f_; + public: - CElitePirateData(CInputStream&, u32 propCount); + CElitePirateData(CInputStream&, u32 propCount); }; -class CElitePirate : public CPatterned -{ +class CElitePirate : public CPatterned { public: - DEFINE_PATTERNED(ElitePirate) + DEFINE_PATTERNED(ElitePirate) - CElitePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, const CActorParameters&, const CElitePirateData&); + CElitePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, const CActorParameters&, const CElitePirateData&); }; -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CEyeball.cpp b/Runtime/MP1/World/CEyeball.cpp index 4858b6aee..4ce9a59a3 100644 --- a/Runtime/MP1/World/CEyeball.cpp +++ b/Runtime/MP1/World/CEyeball.cpp @@ -7,271 +7,235 @@ #include "World/CGameArea.hpp" #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CEyeball::CEyeball(TUniqueId uid, std::string_view name, CPatterned::EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, float f1, float f2, CAssetId aId1, const CDamageInfo& dInfo, CAssetId aId2, CAssetId aId3, CAssetId aId4, CAssetId aId5, - u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, - bool b1, const CActorParameters& actParms) - : CPatterned(ECharacter::EyeBall, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, - EColliderType::Zero, EBodyType::Restricted, actParms, EKnockBackVariant::Medium), x568_attackDelay(f1), x56c_maxAttackDelay(f2), - x570_boneTracking(*GetModelData()->GetAnimationData(), "Eye"sv, zeus::degToRad(45.f), - zeus::degToRad(180.f), true), x5b4_projectileInfo(aId1, dInfo), x5dc_(aId2), x5e0_(aId3), - x5e4_(aId4), - x5e8_(aId5), x604_beamSfxId(CSfxManager::TranslateSFXID(w5)), x60c_24_canAttack(false), - x60c_25_playerInRange(false), x60c_26_alert(false), x60c_27_attackDisabled(b1), x60c_28_firingBeam(false) -{ - x5f4_animIdxs[0] = w1; - x5f4_animIdxs[1] = w2; - x5f4_animIdxs[2] = w3; - x5f4_animIdxs[3] = w4; + u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, bool b1, const CActorParameters& actParms) +: CPatterned(ECharacter::EyeBall, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, + EColliderType::Zero, EBodyType::Restricted, actParms, EKnockBackVariant::Medium) +, x568_attackDelay(f1) +, x56c_maxAttackDelay(f2) +, x570_boneTracking(*GetModelData()->GetAnimationData(), "Eye"sv, zeus::degToRad(45.f), zeus::degToRad(180.f), true) +, x5b4_projectileInfo(aId1, dInfo) +, x5dc_(aId2) +, x5e0_(aId3) +, x5e4_(aId4) +, x5e8_(aId5) +, x604_beamSfxId(CSfxManager::TranslateSFXID(w5)) +, x60c_24_canAttack(false) +, x60c_25_playerInRange(false) +, x60c_26_alert(false) +, x60c_27_attackDisabled(b1) +, x60c_28_firingBeam(false) { + x5f4_animIdxs[0] = w1; + x5f4_animIdxs[1] = w2; + x5f4_animIdxs[2] = w3; + x5f4_animIdxs[3] = w4; - x460_knockBackController.SetAutoResetImpulse(false); + x460_knockBackController.SetAutoResetImpulse(false); } -void CEyeball::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CEyeball::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CEyeball::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::ProjectileCollide: - case EScriptObjectMessage::InvulnDamage: - { - if (TCastToConstPtr proj = mgr.GetObjectById(uid)) - { - if (proj->GetOwnerId() == mgr.GetPlayer().GetUniqueId()) - if (GetDamageVulnerability()->GetVulnerability(proj->GetDamageInfo().GetWeaponMode(), false) != - EVulnerability::Deflect) - x400_24_hitByPlayerProjectile = true; - } - return; +void CEyeball::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::ProjectileCollide: + case EScriptObjectMessage::InvulnDamage: { + if (TCastToConstPtr proj = mgr.GetObjectById(uid)) { + if (proj->GetOwnerId() == mgr.GetPlayer().GetUniqueId()) + if (GetDamageVulnerability()->GetVulnerability(proj->GetDamageInfo().GetWeaponMode(), false) != + EVulnerability::Deflect) + x400_24_hitByPlayerProjectile = true; } - case EScriptObjectMessage::Alert: - x60c_26_alert = true; - break; - case EScriptObjectMessage::Registered: - { - RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); - x450_bodyController->Activate(mgr); - x330_stateMachineState.SetDelay(0.f); - CreateShadow(false); - CreateBeam(mgr); - break; + return; + } + case EScriptObjectMessage::Alert: + x60c_26_alert = true; + break; + case EScriptObjectMessage::Registered: { + RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); + x450_bodyController->Activate(mgr); + x330_stateMachineState.SetDelay(0.f); + CreateShadow(false); + CreateBeam(mgr); + break; + } + case EScriptObjectMessage::Deleted: { + if (x5ec_projectileId != kInvalidUniqueId) { + mgr.FreeScriptObject(x5ec_projectileId); + if (x608_beamSfx) { + CSfxManager::RemoveEmitter(x608_beamSfx); + x608_beamSfx.reset(); + } } - case EScriptObjectMessage::Deleted: - { - if (x5ec_projectileId != kInvalidUniqueId) - { - mgr.FreeScriptObject(x5ec_projectileId); - if (x608_beamSfx) - { - CSfxManager::RemoveEmitter(x608_beamSfx); - x608_beamSfx.reset(); - } - } - x5ec_projectileId = kInvalidUniqueId; - break; - } - default: - break; - } - CPatterned::AcceptScriptMsg(msg, uid, mgr); + x5ec_projectileId = kInvalidUniqueId; + break; + } + default: + break; + } + CPatterned::AcceptScriptMsg(msg, uid, mgr); } static float kMinAngle = std::cos(zeus::degToRad(45.f)); -void CEyeball::Think(float dt, CStateManager& mgr) -{ - CPatterned::Think(dt, mgr); - if (!GetActive()) - return; +void CEyeball::Think(float dt, CStateManager& mgr) { + CPatterned::Think(dt, mgr); + if (!GetActive()) + return; - CPlayer& player = mgr.GetPlayer(); - zeus::CVector3f direction = (player.GetTranslation() - GetTranslation()).normalized(); + CPlayer& player = mgr.GetPlayer(); + zeus::CVector3f direction = (player.GetTranslation() - GetTranslation()).normalized(); - x60c_25_playerInRange = (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && - direction.dot(GetTransform().frontVector()) > kMinAngle); + x60c_25_playerInRange = (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && + direction.dot(GetTransform().frontVector()) > kMinAngle); - if (x60c_25_playerInRange) - { - x570_boneTracking.SetActive(true); - x5a8_targetPosition = player.GetTranslation() - (0.5f * player.GetVelocity()); - x570_boneTracking.SetTargetPosition(x5a8_targetPosition); - x570_boneTracking.Update(dt); - ModelData()->AnimationData()->PreRender(); - x570_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), GetTransform(), GetModelData()->GetScale(), - *x450_bodyController.get()); - } else - x570_boneTracking.SetActive(false); + if (x60c_25_playerInRange) { + x570_boneTracking.SetActive(true); + x5a8_targetPosition = player.GetTranslation() - (0.5f * player.GetVelocity()); + x570_boneTracking.SetTargetPosition(x5a8_targetPosition); + x570_boneTracking.Update(dt); + ModelData()->AnimationData()->PreRender(); + x570_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), GetTransform(), GetModelData()->GetScale(), + *x450_bodyController.get()); + } else + x570_boneTracking.SetActive(false); - if (GetActive()) - { - CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x5ec_projectileId)); - if (projectile && projectile->GetActive()) - projectile->UpdateFX(GetLctrTransform(skEyeLocator), dt, mgr); - } + if (GetActive()) { + CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x5ec_projectileId)); + if (projectile && projectile->GetActive()) + projectile->UpdateFX(GetLctrTransform(skEyeLocator), dt, mgr); + } - if (x60c_28_firingBeam) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); - if (area->GetActive() && area->IsPostConstructed() && - area->GetPostConstructed()->x10dc_occlusionState == CGameArea::EOcclusionState::Occluded) - ResetBeamState(mgr); - } + if (x60c_28_firingBeam) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); + if (area->GetActive() && area->IsPostConstructed() && + area->GetPostConstructed()->x10dc_occlusionState == CGameArea::EOcclusionState::Occluded) + ResetBeamState(mgr); + } } -void CEyeball::CreateBeam(CStateManager& mgr) -{ - if (x5ec_projectileId != kInvalidUniqueId) - return; - - CBeamInfo beamInfo(3, x5dc_, x5e0_, x5e4_, x5e8_, 50, .5f, 1.f, 2.f, 20.f, 1.f, 1.f, 2.f, - zeus::CColor(1.f, 1.f, 1.f, 0.f), zeus::CColor(0.f, 1.f, 0.5f, 0.f), 150.f); - x5ec_projectileId = mgr.AllocateUniqueId(); - mgr.AddObject(new CPlasmaProjectile(x5b4_projectileInfo.Token(), "EyeBall_Beam"sv, EWeaponType::AI, beamInfo, - zeus::CTransform::Identity(), EMaterialTypes::Immovable, - x5b4_projectileInfo.GetDamage(), x5ec_projectileId, GetAreaIdAlways(), - GetUniqueId(), 8, false, EProjectileAttrib::KeepInCinematic)); +void CEyeball::CreateBeam(CStateManager& mgr) { + if (x5ec_projectileId != kInvalidUniqueId) + return; + CBeamInfo beamInfo(3, x5dc_, x5e0_, x5e4_, x5e8_, 50, .5f, 1.f, 2.f, 20.f, 1.f, 1.f, 2.f, + zeus::CColor(1.f, 1.f, 1.f, 0.f), zeus::CColor(0.f, 1.f, 0.5f, 0.f), 150.f); + x5ec_projectileId = mgr.AllocateUniqueId(); + mgr.AddObject(new CPlasmaProjectile(x5b4_projectileInfo.Token(), "EyeBall_Beam"sv, EWeaponType::AI, beamInfo, + zeus::CTransform::Identity(), EMaterialTypes::Immovable, + x5b4_projectileInfo.GetDamage(), x5ec_projectileId, GetAreaIdAlways(), + GetUniqueId(), 8, false, EProjectileAttrib::KeepInCinematic)); } -void CEyeball::InActive(CStateManager&, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); +void CEyeball::InActive(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); } -void CEyeball::Cover(CStateManager&, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - x60c_24_canAttack = false; - x330_stateMachineState.SetDelay(x568_attackDelay); - } +void CEyeball::Cover(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + x60c_24_canAttack = false; + x330_stateMachineState.SetDelay(x568_attackDelay); + } } -void CEyeball::Flinch(CStateManager& mgr, EStateMsg msg, float arg) -{ - if (msg == EStateMsg::Activate) - { - x32c_animState = EAnimState::One; - x330_stateMachineState.SetDelay(x568_attackDelay); - } - else if (msg == EStateMsg::Update) - TryCommand(mgr, pas::EAnimationState::KnockBack, CPatternedTryFunc(&CEyeball::TryFlinch), 0); - else if (msg == EStateMsg::Deactivate) - x32c_animState = EAnimState::Zero; +void CEyeball::Flinch(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x32c_animState = EAnimState::One; + x330_stateMachineState.SetDelay(x568_attackDelay); + } else if (msg == EStateMsg::Update) + TryCommand(mgr, pas::EAnimationState::KnockBack, CPatternedTryFunc(&CEyeball::TryFlinch), 0); + else if (msg == EStateMsg::Deactivate) + x32c_animState = EAnimState::Zero; } -void CEyeball::TryFlinch(CStateManager&, int arg) -{ - x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockBackCmd(GetTransform().basis[0], pas::ESeverity(arg))); +void CEyeball::TryFlinch(CStateManager&, int arg) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockBackCmd(GetTransform().basis[0], pas::ESeverity(arg))); } -void CEyeball::Active(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x400_24_hitByPlayerProjectile = 0; - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); - x60c_24_canAttack = false; - } - else if (msg == EStateMsg::Update) - { - if (x330_stateMachineState.GetDelay() > x56c_maxAttackDelay) - x60c_24_canAttack = true; +void CEyeball::Active(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x400_24_hitByPlayerProjectile = 0; + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); + x60c_24_canAttack = false; + } else if (msg == EStateMsg::Update) { + if (x330_stateMachineState.GetDelay() > x56c_maxAttackDelay) + x60c_24_canAttack = true; - UpdateAnimation(); - } - else if (msg == EStateMsg::Deactivate) - { - x330_stateMachineState.SetDelay(x568_attackDelay); - if (CPlasmaProjectile* proj = static_cast(mgr.ObjectById(x5ec_projectileId))) - proj->ResetBeam(mgr, true); + UpdateAnimation(); + } else if (msg == EStateMsg::Deactivate) { + x330_stateMachineState.SetDelay(x568_attackDelay); + if (CPlasmaProjectile* proj = static_cast(mgr.ObjectById(x5ec_projectileId))) + proj->ResetBeam(mgr, true); - x60c_24_canAttack = false; + x60c_24_canAttack = false; - CSfxManager::RemoveEmitter(x608_beamSfx); - x608_beamSfx.reset(); - } + CSfxManager::RemoveEmitter(x608_beamSfx); + x608_beamSfx.reset(); + } } -void CEyeball::UpdateAnimation() -{ - if (std::fabs(GetModelData()->GetAnimationData()->GetAnimTimeRemaining("Whole Body"sv) - 0.f) >= 0.00001f) - return; +void CEyeball::UpdateAnimation() { + if (std::fabs(GetModelData()->GetAnimationData()->GetAnimTimeRemaining("Whole Body"sv) - 0.f) >= 0.00001f) + return; + + x5f0_currentAnim = (x5f0_currentAnim + 1) & 3; + for (u32 i = 0; i < 4; ++i) { + if (x5f4_animIdxs[x5f0_currentAnim] != -1) + break; x5f0_currentAnim = (x5f0_currentAnim + 1) & 3; - for (u32 i=0 ; i<4 ; ++i) - { - if (x5f4_animIdxs[x5f0_currentAnim] != -1) - break; + } + s32 animIdx = x5f4_animIdxs[x5f0_currentAnim]; + if (animIdx != -1) + x450_bodyController->GetCommandMgr().DeliverCmd(CBCScriptedCmd(animIdx, false, false, 0.f)); +} - x5f0_currentAnim = (x5f0_currentAnim + 1) & 3; +void CEyeball::ResetBeamState(CStateManager& mgr) { + if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x5ec_projectileId))) + projectile->ResetBeam(mgr, true); + + x60c_28_firingBeam = false; + if (x608_beamSfx) { + CSfxManager::RemoveEmitter(x608_beamSfx); + x608_beamSfx.reset(); + } +} + +void CEyeball::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + if (type == EUserEventType::DamageOff) + ResetBeamState(mgr); + else if (type == EUserEventType::DamageOn && x60c_24_canAttack) + FireBeam(mgr, GetLctrTransform(node.GetLocatorName())); + else + CPatterned::DoUserAnimEvent(mgr, node, type, dt); +} + +void CEyeball::FireBeam(CStateManager& mgr, const zeus::CTransform& xf) { + if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x5ec_projectileId))) { + if (!projectile->GetActive()) { + projectile->Fire(xf, mgr, false); + x60c_28_firingBeam = true; + if (!x608_beamSfx) { + CAudioSys::C3DEmitterParmData parmData{ + GetTranslation(), {}, 50.f, 0.1f, 0x1, x604_beamSfxId, 1.f /* 127 */, 0.15f /* 20 / 127 */, false, 127}; + x608_beamSfx = CSfxManager::AddEmitter(parmData, true, 127, true, GetAreaIdAlways()); + } } - s32 animIdx = x5f4_animIdxs[x5f0_currentAnim]; - if (animIdx != -1) - x450_bodyController->GetCommandMgr().DeliverCmd(CBCScriptedCmd(animIdx, false, false, 0.f)); + } } -void CEyeball::ResetBeamState(CStateManager& mgr) -{ - if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x5ec_projectileId))) - projectile->ResetBeam(mgr, true); - - x60c_28_firingBeam = false; - if (x608_beamSfx) - { - CSfxManager::RemoveEmitter(x608_beamSfx); - x608_beamSfx.reset(); - } +void CEyeball::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + CPatterned::PreRender(mgr, frustum); + x570_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), GetTransform(), GetModelData()->GetScale(), + *x450_bodyController); } -void CEyeball::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) -{ - if (type == EUserEventType::DamageOff) - ResetBeamState(mgr); - else if (type == EUserEventType::DamageOn && x60c_24_canAttack) - FireBeam(mgr, GetLctrTransform(node.GetLocatorName())); - else - CPatterned::DoUserAnimEvent(mgr, node, type, dt); +void CEyeball::Death(CStateManager& mgr, const zeus::CVector3f& pos, EScriptObjectState state) { + zeus::CTransform oldXf = GetTransform(); + CPatterned::Death(mgr, pos, state); + SetTransform(oldXf); } - -void CEyeball::FireBeam(CStateManager& mgr, const zeus::CTransform& xf) -{ - if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x5ec_projectileId))) - { - if (!projectile->GetActive()) - { - projectile->Fire(xf, mgr, false); - x60c_28_firingBeam = true; - if (!x608_beamSfx) - { - CAudioSys::C3DEmitterParmData - parmData{GetTranslation(), {}, 50.f, 0.1f, 0x1, x604_beamSfxId, 1.f /* 127 */, 0.15f /* 20 / 127 */, - false, 127}; - x608_beamSfx = CSfxManager::AddEmitter(parmData, true, 127, true, GetAreaIdAlways()); - } - } - } -} - -void CEyeball::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - CPatterned::PreRender(mgr, frustum); - x570_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), GetTransform(), GetModelData()->GetScale(), - *x450_bodyController); -} - -void CEyeball::Death(CStateManager& mgr, const zeus::CVector3f& pos, EScriptObjectState state) -{ - zeus::CTransform oldXf = GetTransform(); - CPatterned::Death(mgr, pos, state); - SetTransform(oldXf); -} -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CEyeball.hpp b/Runtime/MP1/World/CEyeball.hpp index 27696f5a2..9b4338017 100644 --- a/Runtime/MP1/World/CEyeball.hpp +++ b/Runtime/MP1/World/CEyeball.hpp @@ -4,58 +4,57 @@ #include "Character/CBoneTracking.hpp" #include "Weapon/CProjectileInfo.hpp" -namespace urde::MP1 -{ -class CEyeball : public CPatterned -{ - static constexpr std::string_view skEyeLocator="Laser_LCTR"sv; - float x568_attackDelay; - float x56c_maxAttackDelay; - CBoneTracking x570_boneTracking; - zeus::CVector3f x5a8_targetPosition; - CProjectileInfo x5b4_projectileInfo; - CAssetId x5dc_; - CAssetId x5e0_; - CAssetId x5e4_; - CAssetId x5e8_; - TUniqueId x5ec_projectileId = kInvalidUniqueId; - u32 x5f0_currentAnim = 0; - s32 x5f4_animIdxs[4]; - u16 x604_beamSfxId; - CSfxHandle x608_beamSfx = 0; - bool x60c_24_canAttack : 1; - bool x60c_25_playerInRange : 1; - bool x60c_26_alert : 1; - bool x60c_27_attackDisabled : 1; - bool x60c_28_firingBeam : 1; +namespace urde::MP1 { +class CEyeball : public CPatterned { + static constexpr std::string_view skEyeLocator = "Laser_LCTR"sv; + float x568_attackDelay; + float x56c_maxAttackDelay; + CBoneTracking x570_boneTracking; + zeus::CVector3f x5a8_targetPosition; + CProjectileInfo x5b4_projectileInfo; + CAssetId x5dc_; + CAssetId x5e0_; + CAssetId x5e4_; + CAssetId x5e8_; + TUniqueId x5ec_projectileId = kInvalidUniqueId; + u32 x5f0_currentAnim = 0; + s32 x5f4_animIdxs[4]; + u16 x604_beamSfxId; + CSfxHandle x608_beamSfx = 0; + bool x60c_24_canAttack : 1; + bool x60c_25_playerInRange : 1; + bool x60c_26_alert : 1; + bool x60c_27_attackDisabled : 1; + bool x60c_28_firingBeam : 1; + + void CreateBeam(CStateManager&); + void FireBeam(CStateManager&, const zeus::CTransform&); + void TryFlinch(CStateManager&, int); + void UpdateAnimation(); + void ResetBeamState(CStateManager&); - void CreateBeam(CStateManager&); - void FireBeam(CStateManager&, const zeus::CTransform&); - void TryFlinch(CStateManager&, int); - void UpdateAnimation(); - void ResetBeamState(CStateManager&); public: - DEFINE_PATTERNED(EyeBall) + DEFINE_PATTERNED(EyeBall) - CEyeball(TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&, - CModelData&&, const CPatternedInfo&, float, float, CAssetId, const CDamageInfo&, CAssetId, CAssetId, - CAssetId, CAssetId, u32, u32, u32, u32, u32, bool, const CActorParameters&); + CEyeball(TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, float, float, CAssetId, const CDamageInfo&, CAssetId, CAssetId, CAssetId, CAssetId, + u32, u32, u32, u32, u32, bool, const CActorParameters&); - void Accept(IVisitor& visitor); - void PreRender(CStateManager&, const zeus::CFrustum&); - void Touch(CActor&, CStateManager&) {}; - void Death(CStateManager&, const zeus::CVector3f&, EScriptObjectState); + void Accept(IVisitor& visitor); + void PreRender(CStateManager&, const zeus::CFrustum&); + void Touch(CActor&, CStateManager&){}; + void Death(CStateManager&, const zeus::CVector3f&, EScriptObjectState); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); - void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float); - void Think(float, CStateManager&); - void Flinch(CStateManager&, EStateMsg, float); - void Active(CStateManager&, EStateMsg, float); - void InActive(CStateManager&, EStateMsg, float); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); + void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float); + void Think(float, CStateManager&); + void Flinch(CStateManager&, EStateMsg, float); + void Active(CStateManager&, EStateMsg, float); + void InActive(CStateManager&, EStateMsg, float); - void Cover(CStateManager&, EStateMsg, float); + void Cover(CStateManager&, EStateMsg, float); - bool ShouldAttack(CStateManager&, float) { return x60c_26_alert; } - bool ShouldFire(CStateManager&, float) { return !x60c_27_attackDisabled; } + bool ShouldAttack(CStateManager&, float) { return x60c_26_alert; } + bool ShouldFire(CStateManager&, float) { return !x60c_27_attackDisabled; } }; -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CFireFlea.cpp b/Runtime/MP1/World/CFireFlea.cpp index 438d99a79..da8023c6e 100644 --- a/Runtime/MP1/World/CFireFlea.cpp +++ b/Runtime/MP1/World/CFireFlea.cpp @@ -5,120 +5,91 @@ #include "World/CWorld.hpp" #include "TCastTo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -//region Fire Flea Death Camera +// region Fire Flea Death Camera const zeus::CColor CFireFlea::CDeathCameraEffect::skEndFadeColor{1.f, 1.f, 0.5f, 1.f}; const zeus::CColor CFireFlea::CDeathCameraEffect::skStartFadeColor{1.f, 0.f, 0.f, 0.f}; zeus::CColor CFireFlea::CDeathCameraEffect::sCurrentFadeColor = zeus::CColor::skClear; CFireFlea::CDeathCameraEffect::CDeathCameraEffect(TUniqueId uid, TAreaId areaId, std::string_view name) - : CEntity(uid, CEntityInfo(areaId, CEntity::NullConnectionList), true, name) -{ +: CEntity(uid, CEntityInfo(areaId, CEntity::NullConnectionList), true, name) {} + +void CFireFlea::CDeathCameraEffect::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CFireFlea::CDeathCameraEffect::PreThink(float dt, CStateManager& mgr) { + CCameraFilterPassPoly& filterPass = mgr.GetCameraFilterPass(5); + u32 r5 = x34_ + x38_; + u32 r8 = r5 + x3c_; + u32 r31 = r8 + x40_; + if (x44_ >= x34_ && x44_ <= r5) { + sCurrentFadeColor += zeus::CColor::lerp(skStartFadeColor, skEndFadeColor, x34_ - x44_); + filterPass.SetFilter(EFilterType::Blend, EFilterShape::Fullscreen, 0.f, sCurrentFadeColor, CAssetId()); + } else if (x44_ >= r8 && x44_ <= r31) { + sCurrentFadeColor += zeus::CColor::lerp(skEndFadeColor, skStartFadeColor, r8 - x44_); + filterPass.SetFilter(EFilterType::Blend, EFilterShape::Fullscreen, 0.f, sCurrentFadeColor, CAssetId()); + } else if (x44_ > r5) { + sCurrentFadeColor = skEndFadeColor; + filterPass.SetFilter(EFilterType::Blend, EFilterShape::Fullscreen, 0.f, sCurrentFadeColor, CAssetId()); + } + + if (r31 == x44_) { + filterPass.DisableFilter(0.f); + mgr.FreeScriptObject(GetUniqueId()); + x44_ = 0; + } else + x44_++; + + if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal) + filterPass.DisableFilter(0.f); } -void CFireFlea::CDeathCameraEffect::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CFireFlea::CDeathCameraEffect::Think(float dt, CStateManager& mgr) { sCurrentFadeColor = zeus::CColor::skClear; } -void CFireFlea::CDeathCameraEffect::PreThink(float dt, CStateManager& mgr) -{ - CCameraFilterPassPoly& filterPass = mgr.GetCameraFilterPass(5); - u32 r5 = x34_ + x38_; - u32 r8 = r5 + x3c_; - u32 r31 = r8 + x40_; - if (x44_ >= x34_ && x44_ <= r5) - { - sCurrentFadeColor += zeus::CColor::lerp(skStartFadeColor, skEndFadeColor, x34_- x44_); - filterPass.SetFilter(EFilterType::Blend, EFilterShape::Fullscreen, 0.f, sCurrentFadeColor, CAssetId()); - } - else if (x44_ >= r8 && x44_ <= r31) - { - sCurrentFadeColor += zeus::CColor::lerp(skEndFadeColor, skStartFadeColor, r8 - x44_); - filterPass.SetFilter(EFilterType::Blend, EFilterShape::Fullscreen, 0.f, sCurrentFadeColor, CAssetId()); - } - else if (x44_ > r5) - { - sCurrentFadeColor = skEndFadeColor; - filterPass.SetFilter(EFilterType::Blend, EFilterShape::Fullscreen, 0.f, sCurrentFadeColor, CAssetId()); - } - - if (r31 == x44_) - { - filterPass.DisableFilter(0.f); - mgr.FreeScriptObject(GetUniqueId()); - x44_ = 0; - } else - x44_++; - - if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal) - filterPass.DisableFilter(0.f); -} - -void CFireFlea::CDeathCameraEffect::Think(float dt, CStateManager& mgr) -{ - sCurrentFadeColor = zeus::CColor::skClear; -} - -//endregion +// endregion s32 CFireFlea::sLightIdx = 0; CFireFlea::CFireFlea(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, float f1) - : CPatterned(ECharacter::FireFlea, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Small) - , x56c_(f1) - , xd8c_pathFind(nullptr, 2, pInfo.GetPathfindingIndex(), 1.f, 1.f) -{ - CMaterialFilter filter = GetMaterialFilter(); - filter.ExcludeList().Add(EMaterialTypes::Character); - SetMaterialFilter(filter); +: CPatterned(ECharacter::FireFlea, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Small) +, x56c_(f1) +, xd8c_pathFind(nullptr, 2, pInfo.GetPathfindingIndex(), 1.f, 1.f) { + CMaterialFilter filter = GetMaterialFilter(); + filter.ExcludeList().Add(EMaterialTypes::Character); + SetMaterialFilter(filter); - ModelData()->AnimationData()->SetParticleLightIdx(sLightIdx); - ++sLightIdx; + ModelData()->AnimationData()->SetParticleLightIdx(sLightIdx); + ++sLightIdx; } -void CFireFlea::Dead(CStateManager& mgr, EStateMsg msg, float dt) -{ - if (msg != EStateMsg::Activate || mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal) - return; +void CFireFlea::Dead(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg != EStateMsg::Activate || mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal) + return; - mgr.AddObject(new CDeathCameraEffect(mgr.AllocateUniqueId(), GetAreaIdAlways(), ""sv)); + mgr.AddObject(new CDeathCameraEffect(mgr.AllocateUniqueId(), GetAreaIdAlways(), ""sv)); } -bool CFireFlea::Delay(CStateManager&, float arg) -{ - return x330_stateMachineState.GetTime() > 0.5f; +bool CFireFlea::Delay(CStateManager&, float arg) { return x330_stateMachineState.GetTime() > 0.5f; } + +void CFireFlea::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CFireFlea::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); + + if (msg == EScriptObjectMessage::Registered) { + x450_bodyController->Activate(mgr); + } else if (msg == EScriptObjectMessage::InitializedInArea) { + xd8c_pathFind.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); + xe64_ = 50.f; + } } -void CFireFlea::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +bool CFireFlea::InPosition(CStateManager& mgr, float dt) { + if (x2dc_destObj == kInvalidUniqueId) + return false; + return (xd80_ - GetTranslation()).magnitude() < 25.f; } - -void CFireFlea::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CPatterned::AcceptScriptMsg(msg, uid, mgr); - - if (msg == EScriptObjectMessage::Registered) - { - x450_bodyController->Activate(mgr); - } - else if (msg == EScriptObjectMessage::InitializedInArea) - { - xd8c_pathFind.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); - xe64_ = 50.f; - } -} - -bool CFireFlea::InPosition(CStateManager& mgr, float dt) -{ - if (x2dc_destObj == kInvalidUniqueId) - return false; - return (xd80_ - GetTranslation()).magnitude() < 25.f; -} -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CFireFlea.hpp b/Runtime/MP1/World/CFireFlea.hpp index a86e41448..5c8612773 100644 --- a/Runtime/MP1/World/CFireFlea.hpp +++ b/Runtime/MP1/World/CFireFlea.hpp @@ -3,48 +3,46 @@ #include "World/CPatterned.hpp" #include "World/CPathFindSearch.hpp" -namespace urde::MP1 -{ -class CFireFlea : public CPatterned -{ - class CDeathCameraEffect : public CEntity - { - u32 x34_ = 13; - u32 x38_ = 5; - u32 x3c_ = 60; - u32 x40_ = 190; - u32 x44_ = 0; - public: - static const zeus::CColor skStartFadeColor; - static const zeus::CColor skEndFadeColor; - static zeus::CColor sCurrentFadeColor; - CDeathCameraEffect(TUniqueId, TAreaId, std::string_view); +namespace urde::MP1 { +class CFireFlea : public CPatterned { + class CDeathCameraEffect : public CEntity { + u32 x34_ = 13; + u32 x38_ = 5; + u32 x3c_ = 60; + u32 x40_ = 190; + u32 x44_ = 0; - void Accept(IVisitor&); - void PreThink(float, CStateManager&); - void Think(float, CStateManager&); - }; - float x568_ = 1.f; - float x56c_; - u32 x570_ = 0; - float xe64_; - zeus::CVector3f xd74_; - zeus::CVector3f xd80_; - CPathFindSearch xd8c_pathFind; - - static s32 sLightIdx; - -public: - DEFINE_PATTERNED(FireFlea) - - CFireFlea(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CActorParameters&, const CPatternedInfo&, float); + public: + static const zeus::CColor skStartFadeColor; + static const zeus::CColor skEndFadeColor; + static zeus::CColor sCurrentFadeColor; + CDeathCameraEffect(TUniqueId, TAreaId, std::string_view); void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); - void Dead(CStateManager&, EStateMsg msg, float dt); - bool Delay(CStateManager&, float arg); - bool InPosition(CStateManager& mgr, float dt); - CPathFindSearch* GetSearchPath() { return &xd8c_pathFind; } + void PreThink(float, CStateManager&); + void Think(float, CStateManager&); + }; + float x568_ = 1.f; + float x56c_; + u32 x570_ = 0; + float xe64_; + zeus::CVector3f xd74_; + zeus::CVector3f xd80_; + CPathFindSearch xd8c_pathFind; + + static s32 sLightIdx; + +public: + DEFINE_PATTERNED(FireFlea) + + CFireFlea(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const CPatternedInfo&, float); + + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); + void Dead(CStateManager&, EStateMsg msg, float dt); + bool Delay(CStateManager&, float arg); + bool InPosition(CStateManager& mgr, float dt); + CPathFindSearch* GetSearchPath() { return &xd8c_pathFind; } }; -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CFlaahgraProjectile.cpp b/Runtime/MP1/World/CFlaahgraProjectile.cpp index 0bb601fa1..086a1b7ee 100644 --- a/Runtime/MP1/World/CFlaahgraProjectile.cpp +++ b/Runtime/MP1/World/CFlaahgraProjectile.cpp @@ -1,20 +1,18 @@ #include "CFlaahgraProjectile.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CFlaahgraProjectile::CFlaahgraProjectile(bool bigStrike, const TToken& desc, const zeus::CTransform& xf, const CDamageInfo& damage, TUniqueId uid, TAreaId aid, TUniqueId owner) : CEnergyProjectile(true, desc, EWeaponType::AI, xf, EMaterialTypes::Character, damage, uid, aid, owner, - kInvalidUniqueId, EProjectileAttrib::BigProjectile, false, zeus::CVector3f::skOne, - {}, 0xffff, false), x3d8_bigStrike(bigStrike) -{ - if (x3d8_bigStrike) - { - xe8_projectileAttribs |= EProjectileAttrib::BigStrike; - x150_damageDuration = 2.f; - } + kInvalidUniqueId, EProjectileAttrib::BigProjectile, false, zeus::CVector3f::skOne, {}, 0xffff, + false) +, x3d8_bigStrike(bigStrike) { + if (x3d8_bigStrike) { + xe8_projectileAttribs |= EProjectileAttrib::BigStrike; + x150_damageDuration = 2.f; + } } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlaahgraProjectile.hpp b/Runtime/MP1/World/CFlaahgraProjectile.hpp index 2a89e1ce3..7939a75bf 100644 --- a/Runtime/MP1/World/CFlaahgraProjectile.hpp +++ b/Runtime/MP1/World/CFlaahgraProjectile.hpp @@ -2,16 +2,14 @@ #include "Weapon/CEnergyProjectile.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { + +class CFlaahgraProjectile : public CEnergyProjectile { + bool x3d8_bigStrike; -class CFlaahgraProjectile : public CEnergyProjectile -{ - bool x3d8_bigStrike; public: - CFlaahgraProjectile(bool bigStrike, const TToken& desc, const zeus::CTransform& xf, - const CDamageInfo& damage, TUniqueId uid, TAreaId aid, TUniqueId owner); + CFlaahgraProjectile(bool bigStrike, const TToken& desc, const zeus::CTransform& xf, + const CDamageInfo& damage, TUniqueId uid, TAreaId aid, TUniqueId owner); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlickerBat.cpp b/Runtime/MP1/World/CFlickerBat.cpp index a5c036c21..2816a489d 100644 --- a/Runtime/MP1/World/CFlickerBat.cpp +++ b/Runtime/MP1/World/CFlickerBat.cpp @@ -6,188 +6,143 @@ #include "World/CPlayer.hpp" #include "TCastTo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CFlickerBat::CFlickerBat(TUniqueId uid, std::string_view name, CPatterned::EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EColliderType colType, bool b1, const CActorParameters& actParms, bool b2) -: CPatterned(ECharacter::FlickerBat, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, colType, - EBodyType::Pitchable, actParms, EKnockBackVariant::Small) +: CPatterned(ECharacter::FlickerBat, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, + colType, EBodyType::Pitchable, actParms, EKnockBackVariant::Small) , x580_24_(false) , x580_25_heardShot(false) , x580_26_(false) , x580_27_(b2) -, x574_state(EFlickerBatState(b1)) -{ +, x574_state(EFlickerBatState(b1)) { - SetupPlayerCollision(b1); - x3d8_xDamageThreshold = 0.f; - x402_27_noXrayModel = false; + SetupPlayerCollision(b1); + x3d8_xDamageThreshold = 0.f; + x402_27_noXrayModel = false; } -void CFlickerBat::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CFlickerBat::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CFlickerBat::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); + + if (msg == EScriptObjectMessage::Registered) { + RemoveMaterial(EMaterialTypes::Solid, mgr); + /* TODO: Implement xf3c_ in CStateManager (skipping 801311B8 - 80131224) */ + x450_bodyController->Activate(mgr); + x450_bodyController->BodyStateInfo().SetMaximumPitch(zeus::degToRad(60.f)); + } else if (msg == EScriptObjectMessage::Deleted) { + /* sub80125D88(mgr.xf3c_, uid) */ + } } -void CFlickerBat::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CPatterned::AcceptScriptMsg(msg, uid, mgr); +void CFlickerBat::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; - if (msg == EScriptObjectMessage::Registered) - { - RemoveMaterial(EMaterialTypes::Solid, mgr); - /* TODO: Implement xf3c_ in CStateManager (skipping 801311B8 - 80131224) */ - x450_bodyController->Activate(mgr); - x450_bodyController->BodyStateInfo().SetMaximumPitch(zeus::degToRad(60.f)); - } - else if (msg == EScriptObjectMessage::Deleted) - { - /* sub80125D88(mgr.xf3c_, uid) */ + x402_29_drawParticles = mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay; + + if (GetFlickerBatState() == EFlickerBatState::Two || GetFlickerBatState() == EFlickerBatState::Three) { + x578_ -= dt; + if (x578_ <= 0.f) { + if (GetFlickerBatState() == EFlickerBatState::Two) + SetFlickerBatState(EFlickerBatState::Zero, mgr); + else + SetFlickerBatState(EFlickerBatState::One, mgr); } + } + + CPatterned::Think(dt, mgr); } -void CFlickerBat::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; +void CFlickerBat::Render(const CStateManager& mgr) const { CPatterned::Render(mgr); } - x402_29_drawParticles = mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay; +void CFlickerBat::Touch(CActor& act, CStateManager& mgr) { CPatterned::Touch(act, mgr); } - if (GetFlickerBatState() == EFlickerBatState::Two || GetFlickerBatState() == EFlickerBatState::Three) - { - x578_ -= dt; - if (x578_ <= 0.f) - { - if (GetFlickerBatState() == EFlickerBatState::Two) - SetFlickerBatState(EFlickerBatState::Zero, mgr); - else - SetFlickerBatState(EFlickerBatState::One, mgr); - } +void CFlickerBat::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + CPatterned::DoUserAnimEvent(mgr, node, type, dt); +} + +void CFlickerBat::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) { + SetFlickerBatState(EFlickerBatState::Zero, mgr); + CPatterned::Death(mgr, direction, state); +} + +bool CFlickerBat::CanBeShot(CStateManager& mgr, int) { + return (GetFlickerBatState() == EFlickerBatState::Zero || GetFlickerBatState() == EFlickerBatState::Two || + mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay); +} + +void CFlickerBat::Patrol(CStateManager& mgr, EStateMsg state, float dt) { CPatterned::Patrol(mgr, state, dt); } + +void CFlickerBat::Attack(CStateManager&, EStateMsg, float) {} + +void CFlickerBat::Shuffle(CStateManager&, EStateMsg, float) {} + +void CFlickerBat::Taunt(CStateManager&, EStateMsg, float) {} + +bool CFlickerBat::InPosition(CStateManager& mgr, float arg) { + return GetTransform().frontVector().dot(mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetTranslation()) > 0.f; +} + +bool CFlickerBat::HearShot(CStateManager&, float) { + if (x580_25_heardShot) { + x580_25_heardShot = false; + return true; + } + + return false; +} + +void CFlickerBat::SetFlickerBatState(EFlickerBatState state, CStateManager& mgr) { + if (state == x574_state) + return; + + FlickerBatStateChanged(state, mgr); + x574_state = state; +} + +void CFlickerBat::FlickerBatStateChanged(EFlickerBatState state, CStateManager& mgr) { + if (state == EFlickerBatState::Zero) { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay) + CreateShadow(true); + + AddMaterial(EMaterialTypes::Target, mgr); + } else if (state == EFlickerBatState::One) { + SetMuted(true); + RemoveMaterial(EMaterialTypes::Target, mgr); + } else if (state == EFlickerBatState::Two) { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay) { + CreateShadow(true); + SetMuted(false); } - CPatterned::Think(dt, mgr); + CheckStaticIntersection(mgr); + SetupPlayerCollision(true); + } else if (state == EFlickerBatState::Three) { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay) + CreateShadow(true); + + CheckStaticIntersection(mgr); + SetupPlayerCollision(false); + } } -void CFlickerBat::Render(const CStateManager& mgr) const -{ - CPatterned::Render(mgr); +void CFlickerBat::CheckStaticIntersection(CStateManager& mgr) { + if (!x580_27_) { + x580_26_ = false; + return; + } + + zeus::CVector3f camPos = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation(); + zeus::CVector3f diff = GetBoundingBox().center() - camPos; + float mag = diff.magnitude(); + diff *= zeus::CVector3f(1.f / mag); + x580_26_ = CGameCollision::RayStaticIntersectionBool(mgr, camPos, diff, mag, + CMaterialFilter::MakeExclude({EMaterialTypes::SeeThrough})); } -void CFlickerBat::Touch(CActor& act, CStateManager& mgr) -{ - CPatterned::Touch(act, mgr); -} - -void CFlickerBat::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) -{ - CPatterned::DoUserAnimEvent(mgr, node, type, dt); -} - -void CFlickerBat::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) -{ - SetFlickerBatState(EFlickerBatState::Zero, mgr); - CPatterned::Death(mgr, direction, state); -} - -bool CFlickerBat::CanBeShot(CStateManager& mgr, int) -{ - return (GetFlickerBatState() == EFlickerBatState::Zero || GetFlickerBatState() == EFlickerBatState::Two || - mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay); -} - -void CFlickerBat::Patrol(CStateManager& mgr, EStateMsg state, float dt) -{ - CPatterned::Patrol(mgr, state, dt); -} - -void CFlickerBat::Attack(CStateManager&, EStateMsg, float) -{ -} - -void CFlickerBat::Shuffle(CStateManager&, EStateMsg, float) -{ -} - -void CFlickerBat::Taunt(CStateManager&, EStateMsg, float) -{ -} - -bool CFlickerBat::InPosition(CStateManager& mgr, float arg) -{ - return GetTransform().frontVector().dot(mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetTranslation()) > 0.f; -} - -bool CFlickerBat::HearShot(CStateManager&, float) -{ - if (x580_25_heardShot) - { - x580_25_heardShot = false; - return true; - } - - return false; -} - -void CFlickerBat::SetFlickerBatState(EFlickerBatState state, CStateManager& mgr) -{ - if (state == x574_state) - return; - - FlickerBatStateChanged(state, mgr); - x574_state = state; -} - -void CFlickerBat::FlickerBatStateChanged(EFlickerBatState state, CStateManager& mgr) -{ - if (state == EFlickerBatState::Zero) - { - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay) - CreateShadow(true); - - AddMaterial(EMaterialTypes::Target, mgr); - } - else if (state == EFlickerBatState::One) - { - SetMuted(true); - RemoveMaterial(EMaterialTypes::Target, mgr); - } - else if (state == EFlickerBatState::Two) - { - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay) - { - CreateShadow(true); - SetMuted(false); - } - - CheckStaticIntersection(mgr); - SetupPlayerCollision(true); - } - else if (state == EFlickerBatState::Three) - { - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay) - CreateShadow(true); - - CheckStaticIntersection(mgr); - SetupPlayerCollision(false); - } -} - -void CFlickerBat::CheckStaticIntersection(CStateManager& mgr) -{ - if (!x580_27_) - { - x580_26_ = false; - return; - } - - zeus::CVector3f camPos = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation(); - zeus::CVector3f diff = GetBoundingBox().center() - camPos; - float mag = diff.magnitude(); - diff *= zeus::CVector3f(1.f / mag); - x580_26_ = CGameCollision::RayStaticIntersectionBool(mgr, camPos, diff, mag, - CMaterialFilter::MakeExclude({EMaterialTypes::SeeThrough})); -} - -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CFlickerBat.hpp b/Runtime/MP1/World/CFlickerBat.hpp index 3f8b37f10..12e9c08d7 100644 --- a/Runtime/MP1/World/CFlickerBat.hpp +++ b/Runtime/MP1/World/CFlickerBat.hpp @@ -2,54 +2,46 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ -class CFlickerBat final : public CPatterned -{ +namespace urde::MP1 { +class CFlickerBat final : public CPatterned { public: - enum class EFlickerBatState - { - Zero, - One, - Two, - Three - }; + enum class EFlickerBatState { Zero, One, Two, Three }; private: - float x568_ = 0.f; - float x56c_ = 0.f; - float x570_ = 0.f; - EFlickerBatState x574_state; - float x578_ = 1.f; - float x57c_ = 0.f; - bool x580_24_ : 1; - bool x580_25_heardShot : 1; - bool x580_26_ : 1; - bool x580_27_ : 1; + float x568_ = 0.f; + float x56c_ = 0.f; + float x570_ = 0.f; + EFlickerBatState x574_state; + float x578_ = 1.f; + float x57c_ = 0.f; + bool x580_24_ : 1; + bool x580_25_heardShot : 1; + bool x580_26_ : 1; + bool x580_27_ : 1; + public: - DEFINE_PATTERNED(FlickerBat) - CFlickerBat(TUniqueId, std::string_view name, EFlavorType, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, EColliderType, bool, const CActorParameters&, bool); + DEFINE_PATTERNED(FlickerBat) + CFlickerBat(TUniqueId, std::string_view name, EFlavorType, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, EColliderType, bool, const CActorParameters&, bool); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - void Render(const CStateManager&) const; - void Touch(CActor&, CStateManager&); - void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt); - void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); - bool CanBeShot(CStateManager&, int); - void Patrol(CStateManager&, EStateMsg, float); - void Attack(CStateManager&, EStateMsg, float); - void Shuffle(CStateManager&, EStateMsg, float); - void Taunt(CStateManager&, EStateMsg, float); - bool InPosition(CStateManager&, float); - bool HearShot(CStateManager&, float); - - EFlickerBatState GetFlickerBatState() const { return x574_state; } - void SetFlickerBatState(EFlickerBatState state, CStateManager&); - void FlickerBatStateChanged(EFlickerBatState, CStateManager&); - void CheckStaticIntersection(CStateManager&); + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void Render(const CStateManager&) const; + void Touch(CActor&, CStateManager&); + void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt); + void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); + bool CanBeShot(CStateManager&, int); + void Patrol(CStateManager&, EStateMsg, float); + void Attack(CStateManager&, EStateMsg, float); + void Shuffle(CStateManager&, EStateMsg, float); + void Taunt(CStateManager&, EStateMsg, float); + bool InPosition(CStateManager&, float); + bool HearShot(CStateManager&, float); + EFlickerBatState GetFlickerBatState() const { return x574_state; } + void SetFlickerBatState(EFlickerBatState state, CStateManager&); + void FlickerBatStateChanged(EFlickerBatState, CStateManager&); + void CheckStaticIntersection(CStateManager&); }; -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlyingPirate.cpp b/Runtime/MP1/World/CFlyingPirate.cpp index b46424abb..5a5139be6 100644 --- a/Runtime/MP1/World/CFlyingPirate.cpp +++ b/Runtime/MP1/World/CFlyingPirate.cpp @@ -1,14 +1,10 @@ #include "CFlyingPirate.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CFlyingPirate::CFlyingPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, CInputStream& in, u32 propCount) - : CPatterned(ECharacter::FlyingPirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Medium) -{ - -} -} +: CPatterned(ECharacter::FlyingPirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Medium) {} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CFlyingPirate.hpp b/Runtime/MP1/World/CFlyingPirate.hpp index 098353641..c156aa182 100644 --- a/Runtime/MP1/World/CFlyingPirate.hpp +++ b/Runtime/MP1/World/CFlyingPirate.hpp @@ -2,14 +2,12 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ -class CFlyingPirate : public CPatterned -{ +namespace urde::MP1 { +class CFlyingPirate : public CPatterned { public: - DEFINE_PATTERNED(FlyingPirate) + DEFINE_PATTERNED(FlyingPirate) - CFlyingPirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CActorParameters&, const CPatternedInfo&, CInputStream&, u32); + CFlyingPirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const CPatternedInfo&, CInputStream&, u32); }; -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CMagdolite.cpp b/Runtime/MP1/World/CMagdolite.cpp index 6a1668e88..c5b5bf314 100644 --- a/Runtime/MP1/World/CMagdolite.cpp +++ b/Runtime/MP1/World/CMagdolite.cpp @@ -1,8 +1,6 @@ #include "CMagdolite.hpp" - -namespace urde::MP1 -{ +namespace urde::MP1 { CMagdolite::CMagdoliteData::CMagdoliteData(CInputStream& in) : x0_propertyCount(in.readUint32Big()) @@ -11,18 +9,14 @@ CMagdolite::CMagdoliteData::CMagdoliteData(CInputStream& in) , xc_(in.readUint32Big()) , x10_(in.readFloatBig()) , x18_(in.readFloatBig()) -, x1c_(in.readFloatBig()) -{ -} +, x1c_(in.readFloatBig()) {} CMagdolite::CMagdolite(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, float f1, float f2, - const CDamageInfo& dInfo1, const CDamageInfo& dInfo2, const CDamageVulnerability& dVuln1, - const CDamageVulnerability& dVuln2, CAssetId modelId, CAssetId skinId, float f3, float f4, - float f5, float f6, const urde::MP1::CMagdolite::CMagdoliteData& magData, float f7, float f8, float f9) + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, float f1, + float f2, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2, + const CDamageVulnerability& dVuln1, const CDamageVulnerability& dVuln2, CAssetId modelId, + CAssetId skinId, float f3, float f4, float f5, float f6, + const urde::MP1::CMagdolite::CMagdoliteData& magData, float f7, float f8, float f9) : CPatterned(ECharacter::Magdolite, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Large) -{ - -} -} + EMovementType::Flyer, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Large) {} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMagdolite.hpp b/Runtime/MP1/World/CMagdolite.hpp index 7f6b0a008..22dc67b26 100644 --- a/Runtime/MP1/World/CMagdolite.hpp +++ b/Runtime/MP1/World/CMagdolite.hpp @@ -2,31 +2,28 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ -class CMagdolite : public CPatterned -{ +namespace urde::MP1 { +class CMagdolite : public CPatterned { public: - class CMagdoliteData - { - u32 x0_propertyCount; - u32 x4_; - CAssetId x8_; - u32 xc_; - float x10_; - float x18_; - float x1c_; - public: - CMagdoliteData(CInputStream&); - }; + class CMagdoliteData { + u32 x0_propertyCount; + u32 x4_; + CAssetId x8_; + u32 xc_; + float x10_; + float x18_; + float x1c_; + + public: + CMagdoliteData(CInputStream&); + }; + private: public: - DEFINE_PATTERNED(Magdolite) - CMagdolite(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, const CActorParameters&, float, float, const CDamageInfo&, const CDamageInfo&, - const CDamageVulnerability&, const CDamageVulnerability&, CAssetId, CAssetId, float, float, float, float, - const CMagdoliteData&, float, float, float); - + DEFINE_PATTERNED(Magdolite) + CMagdolite(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, const CActorParameters&, float, float, const CDamageInfo&, const CDamageInfo&, + const CDamageVulnerability&, const CDamageVulnerability&, CAssetId, CAssetId, float, float, float, float, + const CMagdoliteData&, float, float, float); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetaree.cpp b/Runtime/MP1/World/CMetaree.cpp index 764b08811..cc95bbc34 100644 --- a/Runtime/MP1/World/CMetaree.cpp +++ b/Runtime/MP1/World/CMetaree.cpp @@ -6,13 +6,11 @@ #include "TCastTo.hpp" - -namespace urde::MP1 -{ +namespace urde::MP1 { CMetaree::CMetaree(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CDamageInfo& dInfo, - float f1, const zeus::CVector3f& v1, float f2, EBodyType bodyType, float f3, float f4, - const CActorParameters& aParms) + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, + const CDamageInfo& dInfo, float f1, const zeus::CVector3f& v1, float f2, EBodyType bodyType, + float f3, float f4, const CActorParameters& aParms) : CPatterned(ECharacter::Metaree, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, EColliderType::Zero, bodyType, aParms, EKnockBackVariant::Small) , x568_delay(f3) @@ -22,189 +20,150 @@ CMetaree::CMetaree(TUniqueId uid, std::string_view name, EFlavorType flavor, con , x580_attackSpeed(f2) , x5ca_24_(true) , x5ca_25_started(false) -, x5ca_26_deactivated(false) -{ +, x5ca_26_deactivated(false) {} + +void CMetaree::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CMetaree::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); + + if (msg == EScriptObjectMessage::Start) + x5ca_25_started = true; + else if (msg == EScriptObjectMessage::Registered) + x450_bodyController->Activate(mgr); } -void CMetaree::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CMetaree::Think(float dt, CStateManager& mgr) { + bool target = true; + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Thermal && + mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) { + target = x5ca_26_deactivated; + } + xe7_31_targetable = target; + CPatterned::Think(dt, mgr); } -void CMetaree::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CPatterned::AcceptScriptMsg(msg, uid, mgr); +void CMetaree::Explode(CStateManager& mgr, EStateMsg msg, float) { + if (msg != EStateMsg::Activate) + return; - if (msg == EScriptObjectMessage::Start) - x5ca_25_started = true; - else if (msg == EScriptObjectMessage::Registered) - x450_bodyController->Activate(mgr); + mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), x5ac_damgeInfo, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + MassiveDeath(mgr); } -void CMetaree::Think(float dt, CStateManager& mgr) -{ - bool target = true; - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Thermal && - mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - { - target = x5ca_26_deactivated; +void CMetaree::Touch(CActor& act, CStateManager& mgr) { + if (!x400_25_alive) + return; + + if (TCastToPtr projectile = act) { + if (projectile->GetOwnerId() != mgr.GetPlayer().GetUniqueId()) + return; + + x400_24_hitByPlayerProjectile = true; + x590_projectileDelta = projectile->GetTranslation() - projectile->GetPreviousPos(); + } +} + +void CMetaree::CollidedWith(TUniqueId& id, const CCollisionInfoList& colList, CStateManager& mgr) { + if (!x400_25_alive || colList.GetCount() <= 0) + return; + + mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x5ac_damgeInfo, + CMaterialFilter::MakeInclude({EMaterialTypes::Player})); + SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); + MassiveDeath(mgr); +} + +void CMetaree::Flee(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + ApplyImpulseWR(5.f * (GetMass() * (x590_projectileDelta * zeus::CVector3f{1.f, 1.f, 0.f})), + zeus::CAxisAngle::sIdentity); + + SetMomentumWR({0.f, 0.f, -GetGravityConstant() * GetMass()}); + SetTranslation(GetTranslation()); + x5a8_ = 0; + } else if (msg == EStateMsg::Update) { + if (x5a8_ != 0) + return; + + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LieOnGround) { + x5a8_ = 1; + return; } - xe7_31_targetable = target; - CPatterned::Think(dt, mgr); + + x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockDownCmd({0.f, 1.f, 0.f}, pas::ESeverity::Zero)); + } } -void CMetaree::Explode(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg != EStateMsg::Activate) - return; +void CMetaree::Dead(CStateManager& mgr, EStateMsg msg, float) { + if (msg != EStateMsg::Activate) + return; - mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), x5ac_damgeInfo, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); - MassiveDeath(mgr); + mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x5ac_damgeInfo, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Player}, {})); + DeathDelete(mgr); } -void CMetaree::Touch(CActor& act, CStateManager& mgr) -{ - if (!x400_25_alive) - return; - - if (TCastToPtr projectile = act) - { - if (projectile->GetOwnerId() != mgr.GetPlayer().GetUniqueId()) - return; - - x400_24_hitByPlayerProjectile = true; - x590_projectileDelta = projectile->GetTranslation() - projectile->GetPreviousPos(); +void CMetaree::Attack(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x5a8_ = 0; + zeus::CVector3f dir = (x584_lookPos - GetTranslation()).normalized(); + SetVelocityWR(x580_attackSpeed * dir); + CSfxManager::AddEmitter(x5c8_attackSfx, GetTranslation(), {}, true, false, 127, kInvalidAreaId); + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); + x59c_velocity = x580_attackSpeed * dir; + } else if (msg == EStateMsg::Update) { + if (x450_bodyController->GetPercentageFrozen() == 0.f) + SetVelocityWR(x59c_velocity); + else { + Stop(); + SetVelocityWR({}); } + } } -void CMetaree::CollidedWith(TUniqueId& id, const CCollisionInfoList& colList, CStateManager& mgr) -{ - if (!x400_25_alive || colList.GetCount() <= 0) - return; +void CMetaree::Halt(CStateManager& mgr, EStateMsg msg, float) { + if (msg != EStateMsg::Activate) + return; - mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x5ac_damgeInfo, - CMaterialFilter::MakeInclude({EMaterialTypes::Player})); - SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); - MassiveDeath(mgr); + Stop(); + SetVelocityWR({}); + SetMomentumWR({}); + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + x584_lookPos = x574_offset + mgr.GetPlayer().GetTranslation(); + SetTransform(zeus::lookAt(GetTranslation(), x584_lookPos)); } -void CMetaree::Flee(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - ApplyImpulseWR(5.f * (GetMass() * (x590_projectileDelta * zeus::CVector3f{1.f, 1.f, 0.f})), - zeus::CAxisAngle::sIdentity); - - SetMomentumWR({0.f, 0.f, -GetGravityConstant() * GetMass()}); - SetTranslation(GetTranslation()); - x5a8_ = 0; - } - else if (msg == EStateMsg::Update) - { - if (x5a8_ != 0) - return; - - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LieOnGround) - { - x5a8_ = 1; - return; - } - - x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockDownCmd({0.f, 1.f, 0.f}, pas::ESeverity::Zero)); - } -} - -void CMetaree::Dead(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg != EStateMsg::Activate) - return; - - mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x5ac_damgeInfo, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Player}, {})); - DeathDelete(mgr); -} - -void CMetaree::Attack(CStateManager&, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x5a8_ = 0; - zeus::CVector3f dir = (x584_lookPos - GetTranslation()).normalized(); - SetVelocityWR(x580_attackSpeed * dir); - CSfxManager::AddEmitter(x5c8_attackSfx, GetTranslation(), {}, true, false, 127, kInvalidAreaId); - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); - x59c_velocity = x580_attackSpeed * dir; - } - else if (msg == EStateMsg::Update) - { - if (x450_bodyController->GetPercentageFrozen() == 0.f) - SetVelocityWR(x59c_velocity); - else - { - Stop(); - SetVelocityWR({}); - } - } -} - -void CMetaree::Halt(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg != EStateMsg::Activate) - return; - - Stop(); - SetVelocityWR({}); +void CMetaree::Active(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x400_24_hitByPlayerProjectile = false; + x584_lookPos = GetTranslation() - zeus::CVector3f{0.f, 0.f, x570_dropHeight}; + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero, x584_lookPos)); + SetMomentumWR({0.f, 0.f, -GetGravityConstant() * GetMass()}); + } else if (msg == EStateMsg::Update) { + x450_bodyController->GetCommandMgr().SetTargetVector( + (mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized()); + } else if (msg == EStateMsg::Deactivate) { SetMomentumWR({}); - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - x584_lookPos = x574_offset + mgr.GetPlayer().GetTranslation(); - SetTransform(zeus::lookAt(GetTranslation(), x584_lookPos)); - + } } -void CMetaree::Active(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x400_24_hitByPlayerProjectile = false; - x584_lookPos = GetTranslation() - zeus::CVector3f{0.f, 0.f, x570_dropHeight}; - x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero, x584_lookPos)); - SetMomentumWR({0.f, 0.f, -GetGravityConstant() * GetMass()}); - } - else if (msg == EStateMsg::Update) - { - x450_bodyController->GetCommandMgr().SetTargetVector( - (mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized()); - } - else if (msg == EStateMsg::Deactivate) - { - SetMomentumWR({}); - } +void CMetaree::InActive(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + if (!x5ca_26_deactivated) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + } else if (msg == EStateMsg::Deactivate) { + x5ca_26_deactivated = true; + } } -void CMetaree::InActive(CStateManager&, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - if (!x5ca_26_deactivated) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); - } - else if (msg == EStateMsg::Deactivate) - { - x5ca_26_deactivated = true; - } +bool CMetaree::InRange(CStateManager& mgr, float arg) { + if (x5ca_25_started) + return true; + + return CPatterned::InRange(mgr, arg); } -bool CMetaree::InRange(CStateManager& mgr, float arg) -{ - if (x5ca_25_started) - return true; - - return CPatterned::InRange(mgr, arg); -} - -bool CMetaree::ShouldAttack(CStateManager&, float) -{ - return GetTranslation().z() < x584_lookPos.z(); -} -} +bool CMetaree::ShouldAttack(CStateManager&, float) { return GetTranslation().z() < x584_lookPos.z(); } +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetaree.hpp b/Runtime/MP1/World/CMetaree.hpp index 5ed39bbe4..576e0ab9e 100644 --- a/Runtime/MP1/World/CMetaree.hpp +++ b/Runtime/MP1/World/CMetaree.hpp @@ -4,60 +4,53 @@ #include "World/CDamageInfo.hpp" #include "DataSpec/DNAMP1/SFX/Metaree.h" -namespace urde::MP1 -{ -class CMetaree : public CPatterned -{ - float x568_delay; - float x56c_; - float x570_dropHeight; - zeus::CVector3f x574_offset; - float x580_attackSpeed; - zeus::CVector3f x584_lookPos; - zeus::CVector3f x590_projectileDelta; - zeus::CVector3f x59c_velocity; - u32 x5a8_ = 0; - CDamageInfo x5ac_damgeInfo; - u16 x5c8_attackSfx = SFXsfx0225; +namespace urde::MP1 { +class CMetaree : public CPatterned { + float x568_delay; + float x56c_; + float x570_dropHeight; + zeus::CVector3f x574_offset; + float x580_attackSpeed; + zeus::CVector3f x584_lookPos; + zeus::CVector3f x590_projectileDelta; + zeus::CVector3f x59c_velocity; + u32 x5a8_ = 0; + CDamageInfo x5ac_damgeInfo; + u16 x5c8_attackSfx = SFXsfx0225; - struct - { - struct - { - bool x5ca_24_ : 1; - bool x5ca_25_started : 1; - bool x5ca_26_deactivated : 1; - }; - u16 _dummy; + struct { + struct { + bool x5ca_24_ : 1; + bool x5ca_25_started : 1; + bool x5ca_26_deactivated : 1; }; + u16 _dummy; + }; + + u32 x5cc_; - u32 x5cc_; public: - DEFINE_PATTERNED(Metaree) - CMetaree(TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, const CDamageInfo&, float, const zeus::CVector3f&, float, EBodyType, float, float, - const CActorParameters&); + DEFINE_PATTERNED(Metaree) + CMetaree(TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, const CDamageInfo&, float, const zeus::CVector3f&, float, EBodyType, float, float, + const CActorParameters&); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); - void Touch(CActor&, CStateManager&); - void CollidedWith(TUniqueId&, const CCollisionInfoList&, CStateManager&); - void ThinkAboutMove(float) {}; - bool Delay(CStateManager&, float) - { - return x330_stateMachineState.GetTime() > x568_delay; - } - void Explode(CStateManager&, EStateMsg, float); - void Flee(CStateManager&, EStateMsg, float); - void Dead(CStateManager&, EStateMsg, float); - void Attack(CStateManager&, EStateMsg, float); - void Halt(CStateManager&, EStateMsg, float); - void Active(CStateManager&, EStateMsg, float); - void InActive(CStateManager&, EStateMsg, float); - bool InRange(CStateManager&, float); - bool ShouldAttack(CStateManager&, float); + void Touch(CActor&, CStateManager&); + void CollidedWith(TUniqueId&, const CCollisionInfoList&, CStateManager&); + void ThinkAboutMove(float){}; + bool Delay(CStateManager&, float) { return x330_stateMachineState.GetTime() > x568_delay; } + void Explode(CStateManager&, EStateMsg, float); + void Flee(CStateManager&, EStateMsg, float); + void Dead(CStateManager&, EStateMsg, float); + void Attack(CStateManager&, EStateMsg, float); + void Halt(CStateManager&, EStateMsg, float); + void Active(CStateManager&, EStateMsg, float); + void InActive(CStateManager&, EStateMsg, float); + bool InRange(CStateManager&, float); + bool ShouldAttack(CStateManager&, float); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroid.cpp b/Runtime/MP1/World/CMetroid.cpp index 4e64e24c3..235a28a6b 100644 --- a/Runtime/MP1/World/CMetroid.cpp +++ b/Runtime/MP1/World/CMetroid.cpp @@ -1,31 +1,28 @@ #include "CMetroid.hpp" #include "World/ScriptLoader.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CMetroidData::CMetroidData(CInputStream& in) -: x0_dVuln1(in), x68_dVuln2(in), - xd0_(in.readFloatBig()), - xd4_(in.readFloatBig()), - xd8_(in.readFloatBig()), - xdc_(in.readFloatBig()), - xe0_(in.readFloatBig()), - xe4_(in.readFloatBig()) -{ - xe8_animParms1 = ScriptLoader::LoadAnimationParameters(in); - xf8_animParms2 = ScriptLoader::LoadAnimationParameters(in); - x108_animParms3 = ScriptLoader::LoadAnimationParameters(in); - x118_animParms4 = ScriptLoader::LoadAnimationParameters(in); - x128_24_ = in.readBool(); +: x0_dVuln1(in) +, x68_dVuln2(in) +, xd0_(in.readFloatBig()) +, xd4_(in.readFloatBig()) +, xd8_(in.readFloatBig()) +, xdc_(in.readFloatBig()) +, xe0_(in.readFloatBig()) +, xe4_(in.readFloatBig()) { + xe8_animParms1 = ScriptLoader::LoadAnimationParameters(in); + xf8_animParms2 = ScriptLoader::LoadAnimationParameters(in); + x108_animParms3 = ScriptLoader::LoadAnimationParameters(in); + x118_animParms4 = ScriptLoader::LoadAnimationParameters(in); + x128_24_ = in.readBool(); } CMetroid::CMetroid(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, const CMetroidData& metroidData) -: CPatterned(ECharacter::Metroid, uid, name, flavor, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Medium) -{ -} +: CPatterned(ECharacter::Metroid, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, + EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Medium) {} -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroid.hpp b/Runtime/MP1/World/CMetroid.hpp index 85669071e..e0ca9ac22 100644 --- a/Runtime/MP1/World/CMetroid.hpp +++ b/Runtime/MP1/World/CMetroid.hpp @@ -3,36 +3,33 @@ #include "World/CPatterned.hpp" #include "World/CAnimationParameters.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { + +class CMetroidData { + CDamageVulnerability x0_dVuln1; + CDamageVulnerability x68_dVuln2; + float xd0_; + float xd4_; + float xd8_; + float xdc_; + float xe0_; + float xe4_; + std::experimental::optional xe8_animParms1; + std::experimental::optional xf8_animParms2; + std::experimental::optional x108_animParms3; + std::experimental::optional x118_animParms4; + bool x128_24_ : 1; -class CMetroidData -{ - CDamageVulnerability x0_dVuln1; - CDamageVulnerability x68_dVuln2; - float xd0_; - float xd4_; - float xd8_; - float xdc_; - float xe0_; - float xe4_; - std::experimental::optional xe8_animParms1; - std::experimental::optional xf8_animParms2; - std::experimental::optional x108_animParms3; - std::experimental::optional x118_animParms4; - bool x128_24_ : 1; public: - CMetroidData(CInputStream& in); + CMetroidData(CInputStream& in); }; -class CMetroid : public CPatterned -{ +class CMetroid : public CPatterned { public: - DEFINE_PATTERNED(Metroid) - CMetroid(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - const CActorParameters& aParms, const CMetroidData& metroidData); + DEFINE_PATTERNED(Metroid) + CMetroid(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, + const CMetroidData& metroidData); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroidBeta.cpp b/Runtime/MP1/World/CMetroidBeta.cpp index ac79baf35..1b585e14e 100644 --- a/Runtime/MP1/World/CMetroidBeta.cpp +++ b/Runtime/MP1/World/CMetroidBeta.cpp @@ -1,8 +1,7 @@ #include "CMetroidBeta.hpp" #include "World/ScriptLoader.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CMetroidBetaData::CMetroidBetaData(CInputStream& in) : x0_(in) @@ -21,25 +20,15 @@ CMetroidBetaData::CMetroidBetaData(CInputStream& in) , xfc_(in) , x100_(in) , x104_(in) -, x108_24_(in.readBool()) -{ -} +, x108_24_(in.readBool()) {} -CMetroidBeta::CMetroidBeta(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - const CActorParameters& aParms, const CMetroidBetaData& metroidData) +CMetroidBeta::CMetroidBeta(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, + const CMetroidBetaData& metroidData) : CPatterned(ECharacter::MetroidBeta, uid, name, EFlavorType::One, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Large) -{ -} + EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Large) {} -void CMetroidBeta::RenderHitGunEffect() const -{ +void CMetroidBeta::RenderHitGunEffect() const {} -} - -void CMetroidBeta::RenderHitBallEffect() const -{ - -} -} +void CMetroidBeta::RenderHitBallEffect() const {} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroidBeta.hpp b/Runtime/MP1/World/CMetroidBeta.hpp index 51a1fd023..9261f1105 100644 --- a/Runtime/MP1/World/CMetroidBeta.hpp +++ b/Runtime/MP1/World/CMetroidBeta.hpp @@ -3,41 +3,38 @@ #include "World/CPatterned.hpp" #include "CMetroid.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { + +class CMetroidBetaData { + CDamageVulnerability x0_; + CDamageVulnerability x68_; + float xd0_; + float xd4_; + float xd8_; + float xdc_; + float xe0_; + float xe4_; + float xe8_; + float xec_; + float xf0_; + CAssetId xf4_; + CAssetId xf8_; + CAssetId xfc_; + CAssetId x100_; + CAssetId x104_; + bool x108_24_ : 1; -class CMetroidBetaData -{ - CDamageVulnerability x0_; - CDamageVulnerability x68_; - float xd0_; - float xd4_; - float xd8_; - float xdc_; - float xe0_; - float xe4_; - float xe8_; - float xec_; - float xf0_; - CAssetId xf4_; - CAssetId xf8_; - CAssetId xfc_; - CAssetId x100_; - CAssetId x104_; - bool x108_24_ : 1; public: - CMetroidBetaData(CInputStream&); + CMetroidBetaData(CInputStream&); }; -class CMetroidBeta : public CPatterned -{ +class CMetroidBeta : public CPatterned { public: - DEFINE_PATTERNED(MetroidBeta) - CMetroidBeta(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - const CActorParameters& aParms, const CMetroidBetaData& metroidData); - void RenderHitGunEffect() const; - void RenderHitBallEffect() const; + DEFINE_PATTERNED(MetroidBeta) + CMetroidBeta(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, + const CMetroidBetaData& metroidData); + void RenderHitGunEffect() const; + void RenderHitBallEffect() const; }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroidPrimeExo.cpp b/Runtime/MP1/World/CMetroidPrimeExo.cpp index 089c99624..a2352a9db 100644 --- a/Runtime/MP1/World/CMetroidPrimeExo.cpp +++ b/Runtime/MP1/World/CMetroidPrimeExo.cpp @@ -4,147 +4,121 @@ #include "CSimplePool.hpp" #include "DataSpec/DNAMP1/ScriptObjects/MetroidPrimeStage1.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { SPrimeStruct2B::SPrimeStruct2B(CInputStream& in) -: x0_propertyCount(in.readUint32Big()), - x4_particle1(in.readUint32Big()), - x8_particle2(in.readUint32Big()), - xc_particle3(in.readUint32Big()), - x10_dInfo(in), - x2c_(in.readFloatBig()), - x30_(in.readFloatBig()), - x34_texture(in.readUint32Big()), - x38_(CSfxManager::TranslateSFXID(u16(in.readUint32Big()))), - x3a_(CSfxManager::TranslateSFXID(u16(in.readUint32Big()))) -{} +: x0_propertyCount(in.readUint32Big()) +, x4_particle1(in.readUint32Big()) +, x8_particle2(in.readUint32Big()) +, xc_particle3(in.readUint32Big()) +, x10_dInfo(in) +, x2c_(in.readFloatBig()) +, x30_(in.readFloatBig()) +, x34_texture(in.readUint32Big()) +, x38_(CSfxManager::TranslateSFXID(u16(in.readUint32Big()))) +, x3a_(CSfxManager::TranslateSFXID(u16(in.readUint32Big()))) {} SPrimeStruct5::SPrimeStruct5(CInputStream& in) -: x0_propertyCount(in.readUint32Big()), - x4_(in.readUint32Big()), - x8_(in.readUint32Big()), - xc_(in.readUint32Big()), - x10_(in.readUint32Big()), - x14_(in.readUint32Big()), - x18_(in.readUint32Big()), - x1c_(in.readUint32Big()), - x20_(in.readUint32Big()) -{} +: x0_propertyCount(in.readUint32Big()) +, x4_(in.readUint32Big()) +, x8_(in.readUint32Big()) +, xc_(in.readUint32Big()) +, x10_(in.readUint32Big()) +, x14_(in.readUint32Big()) +, x18_(in.readUint32Big()) +, x1c_(in.readUint32Big()) +, x20_(in.readUint32Big()) {} SPrimeStruct4::SPrimeStruct4(CInputStream& in) -: x0_beamInfo(in), - x44_(in.readUint32Big()), - x48_dInfo1(in), - x64_struct5(in), - x88_(in.readFloatBig()), - x8c_dInfo2(in) -{} +: x0_beamInfo(in), x44_(in.readUint32Big()), x48_dInfo1(in), x64_struct5(in), x88_(in.readFloatBig()), x8c_dInfo2(in) {} SPrimeStruct6::SPrimeStruct6(CInputStream& in) -: x0_propertyCount(in.readUint32Big()), - x4_damageVulnerability(in), - x6c_color(zeus::CColor::ReadRGBABig(in)), - x70_(in.readUint32Big()), - x74_(in.readUint32Big()) -{} +: x0_propertyCount(in.readUint32Big()) +, x4_damageVulnerability(in) +, x6c_color(zeus::CColor::ReadRGBABig(in)) +, x70_(in.readUint32Big()) +, x74_(in.readUint32Big()) {} -static CPatternedInfo LoadPatternedInfo(CInputStream& in) -{ - std::pair pcount = CPatternedInfo::HasCorrectParameterCount(in); - return CPatternedInfo(in, pcount.second); +static CPatternedInfo LoadPatternedInfo(CInputStream& in) { + std::pair pcount = CPatternedInfo::HasCorrectParameterCount(in); + return CPatternedInfo(in, pcount.second); } using CameraShakeData = DataSpec::DNAMP1::MetroidPrimeStage1::MassivePrimeStruct::CameraShakeData; -static SCameraShakePoint BuildCameraShakePoint(CameraShakeData::CameraShakerComponent::CameraShakePoint& sp) -{ - return SCameraShakePoint(false, sp.attackTime, sp.sustainTime, sp.duration, sp.magnitude); +static SCameraShakePoint BuildCameraShakePoint(CameraShakeData::CameraShakerComponent::CameraShakePoint& sp) { + return SCameraShakePoint(false, sp.attackTime, sp.sustainTime, sp.duration, sp.magnitude); } -static CCameraShakerComponent BuildCameraShakerComponent(CameraShakeData::CameraShakerComponent& comp) -{ - return CCameraShakerComponent(comp.useModulation, BuildCameraShakePoint(comp.am), - BuildCameraShakePoint(comp.fm)); +static CCameraShakerComponent BuildCameraShakerComponent(CameraShakeData::CameraShakerComponent& comp) { + return CCameraShakerComponent(comp.useModulation, BuildCameraShakePoint(comp.am), BuildCameraShakePoint(comp.fm)); } -static CCameraShakeData LoadCameraShakeData(CInputStream& in) -{ - CameraShakeData shakeData; - shakeData.read(in); - return CCameraShakeData(shakeData.duration, shakeData.sfxDist, u32(shakeData.useSfx), - zeus::CVector3f::skZero, - BuildCameraShakerComponent(shakeData.shakerComponents[0]), - BuildCameraShakerComponent(shakeData.shakerComponents[1]), - BuildCameraShakerComponent(shakeData.shakerComponents[2])); +static CCameraShakeData LoadCameraShakeData(CInputStream& in) { + CameraShakeData shakeData; + shakeData.read(in); + return CCameraShakeData(shakeData.duration, shakeData.sfxDist, u32(shakeData.useSfx), zeus::CVector3f::skZero, + BuildCameraShakerComponent(shakeData.shakerComponents[0]), + BuildCameraShakerComponent(shakeData.shakerComponents[1]), + BuildCameraShakerComponent(shakeData.shakerComponents[2])); } -static rstl::reserved_vector LoadPrimeStruct4s(CInputStream& in) -{ - rstl::reserved_vector ret; - for (int i=0 ; i<4 ; ++i) - ret.emplace_back(in); - return ret; +static rstl::reserved_vector LoadPrimeStruct4s(CInputStream& in) { + rstl::reserved_vector ret; + for (int i = 0; i < 4; ++i) + ret.emplace_back(in); + return ret; } -static rstl::reserved_vector LoadPrimeStruct6s(CInputStream& in) -{ - rstl::reserved_vector ret; - for (int i=0 ; i<4 ; ++i) - ret.emplace_back(in); - return ret; +static rstl::reserved_vector LoadPrimeStruct6s(CInputStream& in) { + rstl::reserved_vector ret; + for (int i = 0; i < 4; ++i) + ret.emplace_back(in); + return ret; } SPrimeExoParameters::SPrimeExoParameters(CInputStream& in) -: x0_propertyCount(in.readUint32Big()), - x4_patternedInfo(LoadPatternedInfo(in)), - x13c_actorParms(ScriptLoader::LoadActorParameters(in)), - x1a4_(in.readUint32Big()), - x1a8_(LoadCameraShakeData(in)), - x27c_(LoadCameraShakeData(in)), - x350_(LoadCameraShakeData(in)), - x424_(in), - x460_particle1(in.readUint32Big()), - x464_(LoadPrimeStruct4s(in)), - x708_wpsc1(in.readUint32Big()), - x70c_dInfo1(in), - x728_shakeData1(LoadCameraShakeData(in)), - x7fc_wpsc2(in.readUint32Big()), - x800_dInfo2(in), - x81c_shakeData2(LoadCameraShakeData(in)), - x8f0_(in), - x92c_(in), - x948_(LoadCameraShakeData(in)), - xa1c_particle2(in.readUint32Big()), - xa20_swoosh(in.readUint32Big()), - xa24_particle3(in.readUint32Big()), - xa28_particle4(in.readUint32Big()), - xa2c_(LoadPrimeStruct6s(in)) -{} +: x0_propertyCount(in.readUint32Big()) +, x4_patternedInfo(LoadPatternedInfo(in)) +, x13c_actorParms(ScriptLoader::LoadActorParameters(in)) +, x1a4_(in.readUint32Big()) +, x1a8_(LoadCameraShakeData(in)) +, x27c_(LoadCameraShakeData(in)) +, x350_(LoadCameraShakeData(in)) +, x424_(in) +, x460_particle1(in.readUint32Big()) +, x464_(LoadPrimeStruct4s(in)) +, x708_wpsc1(in.readUint32Big()) +, x70c_dInfo1(in) +, x728_shakeData1(LoadCameraShakeData(in)) +, x7fc_wpsc2(in.readUint32Big()) +, x800_dInfo2(in) +, x81c_shakeData2(LoadCameraShakeData(in)) +, x8f0_(in) +, x92c_(in) +, x948_(LoadCameraShakeData(in)) +, xa1c_particle2(in.readUint32Big()) +, xa20_swoosh(in.readUint32Big()) +, xa24_particle3(in.readUint32Big()) +, xa28_particle4(in.readUint32Big()) +, xa2c_(LoadPrimeStruct6s(in)) {} -SPrimeExoRoomParameters::SPrimeExoRoomParameters(CInputStream& in) -{ - u32 propCount = std::min(u32(14), in.readUint32Big()); - for (int i=0 ; i& struct4s, CAssetId wpsc1, - const CDamageInfo& dInfo1, const CCameraShakeData& shakeData4, CAssetId wpsc2, - const CDamageInfo& dInfo2, const CCameraShakeData& shakeData5, - const SPrimeProjectileInfo& projectileInfo, const CDamageInfo& dInfo3, - const CCameraShakeData& shakeData6, CAssetId particle2, CAssetId swoosh, - CAssetId particle3, CAssetId particle4, - const rstl::reserved_vector& struct6s) +CMetroidPrimeExo::CMetroidPrimeExo( + TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, + const CPatternedInfo& pInfo, const CActorParameters& aParms, u32 pw1, const CCameraShakeData& shakeData1, + const CCameraShakeData& shakeData2, const CCameraShakeData& shakeData3, const SPrimeStruct2B& struct2b, + CAssetId particle1, const rstl::reserved_vector& struct4s, CAssetId wpsc1, + const CDamageInfo& dInfo1, const CCameraShakeData& shakeData4, CAssetId wpsc2, const CDamageInfo& dInfo2, + const CCameraShakeData& shakeData5, const SPrimeProjectileInfo& projectileInfo, const CDamageInfo& dInfo3, + const CCameraShakeData& shakeData6, CAssetId particle2, CAssetId swoosh, CAssetId particle3, CAssetId particle4, + const rstl::reserved_vector& struct6s) : CPatterned(ECharacter::MetroidPrimeExo, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Large) -{ + EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Large) {} -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroidPrimeExo.hpp b/Runtime/MP1/World/CMetroidPrimeExo.hpp index 99cbf4a60..58202d9dc 100644 --- a/Runtime/MP1/World/CMetroidPrimeExo.hpp +++ b/Runtime/MP1/World/CMetroidPrimeExo.hpp @@ -7,114 +7,103 @@ #include "Weapon/CBeamInfo.hpp" #include "CMetroidPrimeProjectile.hpp" -namespace urde -{ +namespace urde { class CCameraShakeData; -namespace MP1 -{ +namespace MP1 { -struct SPrimeStruct2B -{ - u32 x0_propertyCount; - CAssetId x4_particle1; - CAssetId x8_particle2; - CAssetId xc_particle3; - CDamageInfo x10_dInfo; - float x2c_; - float x30_; - CAssetId x34_texture; - u16 x38_; - u16 x3a_; - explicit SPrimeStruct2B(CInputStream& in); +struct SPrimeStruct2B { + u32 x0_propertyCount; + CAssetId x4_particle1; + CAssetId x8_particle2; + CAssetId xc_particle3; + CDamageInfo x10_dInfo; + float x2c_; + float x30_; + CAssetId x34_texture; + u16 x38_; + u16 x3a_; + explicit SPrimeStruct2B(CInputStream& in); }; -struct SPrimeStruct5 -{ - u32 x0_propertyCount; - CAssetId x4_; - u32 x8_; - CAssetId xc_; - CAssetId x10_; - u32 x14_; - u32 x18_; - u32 x1c_; - u32 x20_; - explicit SPrimeStruct5(CInputStream& in); +struct SPrimeStruct5 { + u32 x0_propertyCount; + CAssetId x4_; + u32 x8_; + CAssetId xc_; + CAssetId x10_; + u32 x14_; + u32 x18_; + u32 x1c_; + u32 x20_; + explicit SPrimeStruct5(CInputStream& in); }; -struct SPrimeStruct4 -{ - CBeamInfo x0_beamInfo; - u32 x44_; - CDamageInfo x48_dInfo1; - SPrimeStruct5 x64_struct5; - float x88_; - CDamageInfo x8c_dInfo2; - explicit SPrimeStruct4(CInputStream& in); +struct SPrimeStruct4 { + CBeamInfo x0_beamInfo; + u32 x44_; + CDamageInfo x48_dInfo1; + SPrimeStruct5 x64_struct5; + float x88_; + CDamageInfo x8c_dInfo2; + explicit SPrimeStruct4(CInputStream& in); }; -struct SPrimeStruct6 -{ - u32 x0_propertyCount; - CDamageVulnerability x4_damageVulnerability; - zeus::CColor x6c_color; - u32 x70_; - u32 x74_; - explicit SPrimeStruct6(CInputStream& in); +struct SPrimeStruct6 { + u32 x0_propertyCount; + CDamageVulnerability x4_damageVulnerability; + zeus::CColor x6c_color; + u32 x70_; + u32 x74_; + explicit SPrimeStruct6(CInputStream& in); }; -struct SPrimeExoParameters -{ - u32 x0_propertyCount; - CPatternedInfo x4_patternedInfo; - CActorParameters x13c_actorParms; - u32 x1a4_; - CCameraShakeData x1a8_; - CCameraShakeData x27c_; - CCameraShakeData x350_; - SPrimeStruct2B x424_; - CAssetId x460_particle1; - rstl::reserved_vector x464_; - CAssetId x708_wpsc1; - CDamageInfo x70c_dInfo1; - CCameraShakeData x728_shakeData1; - CAssetId x7fc_wpsc2; - CDamageInfo x800_dInfo2; - CCameraShakeData x81c_shakeData2; - SPrimeProjectileInfo x8f0_; - CDamageInfo x92c_; - CCameraShakeData x948_; - CAssetId xa1c_particle2; - CAssetId xa20_swoosh; - CAssetId xa24_particle3; - CAssetId xa28_particle4; - rstl::reserved_vector xa2c_; - explicit SPrimeExoParameters(CInputStream& in); +struct SPrimeExoParameters { + u32 x0_propertyCount; + CPatternedInfo x4_patternedInfo; + CActorParameters x13c_actorParms; + u32 x1a4_; + CCameraShakeData x1a8_; + CCameraShakeData x27c_; + CCameraShakeData x350_; + SPrimeStruct2B x424_; + CAssetId x460_particle1; + rstl::reserved_vector x464_; + CAssetId x708_wpsc1; + CDamageInfo x70c_dInfo1; + CCameraShakeData x728_shakeData1; + CAssetId x7fc_wpsc2; + CDamageInfo x800_dInfo2; + CCameraShakeData x81c_shakeData2; + SPrimeProjectileInfo x8f0_; + CDamageInfo x92c_; + CCameraShakeData x948_; + CAssetId xa1c_particle2; + CAssetId xa20_swoosh; + CAssetId xa24_particle3; + CAssetId xa28_particle4; + rstl::reserved_vector xa2c_; + explicit SPrimeExoParameters(CInputStream& in); }; -struct SPrimeExoRoomParameters -{ - rstl::reserved_vector x0_; - explicit SPrimeExoRoomParameters(CInputStream& in); +struct SPrimeExoRoomParameters { + rstl::reserved_vector x0_; + explicit SPrimeExoRoomParameters(CInputStream& in); }; -class CMetroidPrimeExo : public CPatterned -{ +class CMetroidPrimeExo : public CPatterned { public: - DEFINE_PATTERNED(MetroidPrimeExo) - CMetroidPrimeExo(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, - u32 pw1, const CCameraShakeData& shakeData1, const CCameraShakeData& shakeData2, - const CCameraShakeData& shakeData3, const SPrimeStruct2B& struct2b, CAssetId particle1, - const rstl::reserved_vector& struct4s, CAssetId wpsc1, const CDamageInfo& dInfo1, - const CCameraShakeData& shakeData4, CAssetId wpsc2, const CDamageInfo& dInfo2, - const CCameraShakeData& shakeData5, const SPrimeProjectileInfo& projectileInfo, - const CDamageInfo& dInfo3, const CCameraShakeData& shakeData6, CAssetId particle2, - CAssetId swoosh, CAssetId particle3, CAssetId particle4, - const rstl::reserved_vector& struct6s); + DEFINE_PATTERNED(MetroidPrimeExo) + CMetroidPrimeExo(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms, u32 pw1, + const CCameraShakeData& shakeData1, const CCameraShakeData& shakeData2, + const CCameraShakeData& shakeData3, const SPrimeStruct2B& struct2b, CAssetId particle1, + const rstl::reserved_vector& struct4s, CAssetId wpsc1, const CDamageInfo& dInfo1, + const CCameraShakeData& shakeData4, CAssetId wpsc2, const CDamageInfo& dInfo2, + const CCameraShakeData& shakeData5, const SPrimeProjectileInfo& projectileInfo, + const CDamageInfo& dInfo3, const CCameraShakeData& shakeData6, CAssetId particle2, CAssetId swoosh, + CAssetId particle3, CAssetId particle4, const rstl::reserved_vector& struct6s); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/World/CMetroidPrimeProjectile.cpp b/Runtime/MP1/World/CMetroidPrimeProjectile.cpp index 78c4a8dcc..ad55303cf 100644 --- a/Runtime/MP1/World/CMetroidPrimeProjectile.cpp +++ b/Runtime/MP1/World/CMetroidPrimeProjectile.cpp @@ -2,35 +2,30 @@ #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { SPrimeProjectileInfo::SPrimeProjectileInfo(CInputStream& in) -: x0_propertyCount(in.readUint32Big()), - x4_particle(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), in.readUint32Big()})), - xc_dInfo(in), - x28_(in.readFloatBig()), - x2c_(in.readFloatBig()), - x30_(in.readFloatBig()), - x34_texture(in.readUint32Big()) -{ - x38_24_ = in.readBool(); - x38_25_ = in.readBool(); - x38_26_ = in.readBool(); - x38_27_ = in.readBool(); +: x0_propertyCount(in.readUint32Big()) +, x4_particle(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), in.readUint32Big()})) +, xc_dInfo(in) +, x28_(in.readFloatBig()) +, x2c_(in.readFloatBig()) +, x30_(in.readFloatBig()) +, x34_texture(in.readUint32Big()) { + x38_24_ = in.readBool(); + x38_25_ = in.readBool(); + x38_26_ = in.readBool(); + x38_27_ = in.readBool(); } CMetroidPrimeProjectile::CMetroidPrimeProjectile( - bool active, const TToken& desc, EWeaponType type, - const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage, - TUniqueId uid, TAreaId aid, TUniqueId owner, const SPrimeProjectileInfo& auxData, - TUniqueId homingTarget, EProjectileAttrib attribs, const zeus::CVector3f& scale, - const std::experimental::optional>& visorParticle, + bool active, const TToken& desc, EWeaponType type, const zeus::CTransform& xf, + EMaterialTypes materials, const CDamageInfo& damage, TUniqueId uid, TAreaId aid, TUniqueId owner, + const SPrimeProjectileInfo& auxData, TUniqueId homingTarget, EProjectileAttrib attribs, + const zeus::CVector3f& scale, const std::experimental::optional>& visorParticle, u16 visorSfx, bool sendCollideMsg) -: CEnergyProjectile(active, desc, type, xf, materials, damage, uid, aid, owner, homingTarget, attribs, false, - scale, visorParticle, visorSfx, sendCollideMsg), x3d8_auxData(auxData) -{ +: CEnergyProjectile(active, desc, type, xf, materials, damage, uid, aid, owner, homingTarget, attribs, false, scale, + visorParticle, visorSfx, sendCollideMsg) +, x3d8_auxData(auxData) {} -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroidPrimeProjectile.hpp b/Runtime/MP1/World/CMetroidPrimeProjectile.hpp index c7ddd2270..5add58fe5 100644 --- a/Runtime/MP1/World/CMetroidPrimeProjectile.hpp +++ b/Runtime/MP1/World/CMetroidPrimeProjectile.hpp @@ -2,36 +2,33 @@ #include "Weapon/CEnergyProjectile.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -struct SPrimeProjectileInfo -{ - u32 x0_propertyCount; - TToken x4_particle; - CDamageInfo xc_dInfo; - float x28_; - float x2c_; - float x30_; - CAssetId x34_texture; - bool x38_24_ : 1; - bool x38_25_ : 1; - bool x38_26_ : 1; - bool x38_27_ : 1; - explicit SPrimeProjectileInfo(CInputStream& in); +struct SPrimeProjectileInfo { + u32 x0_propertyCount; + TToken x4_particle; + CDamageInfo xc_dInfo; + float x28_; + float x2c_; + float x30_; + CAssetId x34_texture; + bool x38_24_ : 1; + bool x38_25_ : 1; + bool x38_26_ : 1; + bool x38_27_ : 1; + explicit SPrimeProjectileInfo(CInputStream& in); }; -class CMetroidPrimeProjectile : public CEnergyProjectile -{ - SPrimeProjectileInfo x3d8_auxData; +class CMetroidPrimeProjectile : public CEnergyProjectile { + SPrimeProjectileInfo x3d8_auxData; + public: - CMetroidPrimeProjectile(bool active, const TToken& desc, EWeaponType type, - const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage, - TUniqueId uid, TAreaId aid, TUniqueId owner, const SPrimeProjectileInfo& auxData, - TUniqueId homingTarget, EProjectileAttrib attribs, const zeus::CVector3f& scale, - const std::experimental::optional>& visorParticle, - u16 visorSfx, bool sendCollideMsg); + CMetroidPrimeProjectile(bool active, const TToken& desc, EWeaponType type, + const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage, + TUniqueId uid, TAreaId aid, TUniqueId owner, const SPrimeProjectileInfo& auxData, + TUniqueId homingTarget, EProjectileAttrib attribs, const zeus::CVector3f& scale, + const std::experimental::optional>& visorParticle, u16 visorSfx, + bool sendCollideMsg); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroidPrimeRelay.cpp b/Runtime/MP1/World/CMetroidPrimeRelay.cpp index c8e502e11..16009f3b9 100644 --- a/Runtime/MP1/World/CMetroidPrimeRelay.cpp +++ b/Runtime/MP1/World/CMetroidPrimeRelay.cpp @@ -1,22 +1,30 @@ #include "CMetroidPrimeRelay.hpp" #include "TCastTo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CMetroidPrimeRelay::CMetroidPrimeRelay(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, const zeus::CTransform& xf, const zeus::CVector3f& scale, - SPrimeExoParameters&& parms, float f1, float f2, float f3, u32 w1, - bool b1, u32 w2, const CHealthInfo& hInfo1, const CHealthInfo& hInfo2, u32 w3, - u32 w4, u32 w5, rstl::reserved_vector&& roomParms) -: CEntity(uid, info, active, name), x38_xf(xf), x68_scale(scale), x74_parms(std::move(parms)), xc84_f1(f1), - xc88_f2(f2), xc8c_f3(f3), xc90_w1(w1), xc94_b1(b1), xc98_w2(w2), xc9c_hInfo1(hInfo1), xca4_hInfo2(hInfo2), - xcac_w3(w3), xcb0_w4(w4), xcb4_w5(w5), xcb8_roomParms(std::move(roomParms)) -{} + SPrimeExoParameters&& parms, float f1, float f2, float f3, u32 w1, bool b1, + u32 w2, const CHealthInfo& hInfo1, const CHealthInfo& hInfo2, u32 w3, u32 w4, + u32 w5, rstl::reserved_vector&& roomParms) +: CEntity(uid, info, active, name) +, x38_xf(xf) +, x68_scale(scale) +, x74_parms(std::move(parms)) +, xc84_f1(f1) +, xc88_f2(f2) +, xc8c_f3(f3) +, xc90_w1(w1) +, xc94_b1(b1) +, xc98_w2(w2) +, xc9c_hInfo1(hInfo1) +, xca4_hInfo2(hInfo2) +, xcac_w3(w3) +, xcb0_w4(w4) +, xcb4_w5(w5) +, xcb8_roomParms(std::move(roomParms)) {} -void CMetroidPrimeRelay::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CMetroidPrimeRelay::Accept(IVisitor& visitor) { visitor.Visit(this); } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CMetroidPrimeRelay.hpp b/Runtime/MP1/World/CMetroidPrimeRelay.hpp index 1dcb43796..fc91bfc67 100644 --- a/Runtime/MP1/World/CMetroidPrimeRelay.hpp +++ b/Runtime/MP1/World/CMetroidPrimeRelay.hpp @@ -3,37 +3,33 @@ #include "World/CEntity.hpp" #include "CMetroidPrimeExo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class CMetroidPrimeRelay : public CEntity -{ - TUniqueId x34_mpUid = kInvalidUniqueId; - zeus::CTransform x38_xf; - zeus::CVector3f x68_scale; - SPrimeExoParameters x74_parms; - float xc84_f1; - float xc88_f2; - float xc8c_f3; - u32 xc90_w1; - bool xc94_b1; - u32 xc98_w2; - CHealthInfo xc9c_hInfo1; - CHealthInfo xca4_hInfo2; - u32 xcac_w3; - u32 xcb0_w4; - u32 xcb4_w5; - rstl::reserved_vector xcb8_roomParms; +class CMetroidPrimeRelay : public CEntity { + TUniqueId x34_mpUid = kInvalidUniqueId; + zeus::CTransform x38_xf; + zeus::CVector3f x68_scale; + SPrimeExoParameters x74_parms; + float xc84_f1; + float xc88_f2; + float xc8c_f3; + u32 xc90_w1; + bool xc94_b1; + u32 xc98_w2; + CHealthInfo xc9c_hInfo1; + CHealthInfo xca4_hInfo2; + u32 xcac_w3; + u32 xcb0_w4; + u32 xcb4_w5; + rstl::reserved_vector xcb8_roomParms; public: - CMetroidPrimeRelay(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, - const zeus::CTransform& xf, const zeus::CVector3f& scale, SPrimeExoParameters&& parms, - float f1, float f2, float f3, u32 w1, bool b1, u32 w2, const CHealthInfo& hInfo1, - const CHealthInfo& hInfo2, u32 w3, u32 w4, u32 w5, - rstl::reserved_vector&& roomParms); - void Accept(IVisitor& visitor); - TUniqueId GetMetroidPrimeExoId() const { return x34_mpUid; } + CMetroidPrimeRelay(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, + const zeus::CTransform& xf, const zeus::CVector3f& scale, SPrimeExoParameters&& parms, float f1, + float f2, float f3, u32 w1, bool b1, u32 w2, const CHealthInfo& hInfo1, const CHealthInfo& hInfo2, + u32 w3, u32 w4, u32 w5, rstl::reserved_vector&& roomParms); + void Accept(IVisitor& visitor); + TUniqueId GetMetroidPrimeExoId() const { return x34_mpUid; } }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CNewIntroBoss.cpp b/Runtime/MP1/World/CNewIntroBoss.cpp index 01931f968..7fa79e087 100644 --- a/Runtime/MP1/World/CNewIntroBoss.cpp +++ b/Runtime/MP1/World/CNewIntroBoss.cpp @@ -10,14 +10,12 @@ #include "TCastTo.hpp" #include "CNewIntroBoss.hpp" +namespace urde::MP1 { -namespace urde::MP1 -{ - -CNewIntroBoss::CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - const CActorParameters& actParms, float f1, CAssetId projectile, const CDamageInfo& dInfo, - CAssetId part1, CAssetId part2, CAssetId tex1, CAssetId tex2) +CNewIntroBoss::CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, + float f1, CAssetId projectile, const CDamageInfo& dInfo, CAssetId part1, CAssetId part2, + CAssetId tex1, CAssetId tex2) : CPatterned(ECharacter::NewIntroBoss, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Medium) , x570_(f1) @@ -26,491 +24,397 @@ CNewIntroBoss::CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntity , x5f0_(part1) , x5f4_(part2) , x5f8_(tex1) -, x5fc_(tex2) -{ - const_cast*>(&x5ac_projectileInfo.Token())->Lock(); - x574_boneTracking.SetActive(true); +, x5fc_(tex2) { + const_cast*>(&x5ac_projectileInfo.Token())->Lock(); + x574_boneTracking.SetActive(true); } -void CNewIntroBoss::Accept(IVisitor &visitor) -{ - visitor.Visit(this); -} +void CNewIntroBoss::Accept(IVisitor& visitor) { visitor.Visit(this); } -static const SSphereJointDescription skSphereJoints[] ={ - {"Head_1", 1.5f}, - {"Tail_1", 1.5f} -}; +static const SSphereJointDescription skSphereJoints[] = {{"Head_1", 1.5f}, {"Tail_1", 1.5f}}; static const SOBBJointDescription skOBBJoints[] = { - {"Pelvis", "Spine_3", {4.f, 1.f, 4.f}}, - {"Spine_3", "Tail_1", {2.f, 1.f, 2.f}}, - {"Tail_1", "Tail_2", {1.f, 1.f, 1.f}}, - {"Tail_2", "Tail_3", {1.f, 1.f, 1.f}}, - {"Tail_3", "Tail_4", {1.f, 1.f, 1.f}}, + {"Pelvis", "Spine_3", {4.f, 1.f, 4.f}}, + {"Spine_3", "Tail_1", {2.f, 1.f, 2.f}}, + {"Tail_1", "Tail_2", {1.f, 1.f, 1.f}}, + {"Tail_2", "Tail_3", {1.f, 1.f, 1.f}}, + {"Tail_3", "Tail_4", {1.f, 1.f, 1.f}}, {"R_shoulder_front", "R_elbow_front", {.5f, .5f, .5f}}, - {"R_elbow_front", "R_wrist_front", {.5f, .5f, .5f}}, + {"R_elbow_front", "R_wrist_front", {.5f, .5f, .5f}}, {"L_shoulder_front", "L_elbow_front", {.5f, .5f, .5f}}, - {"L_elbow_front", "L_wrist_front", {.5f, .5f, .5f}}, - {"R_shoulder_back", "R_elbow_back", {.5f, .5f, .5f}}, - {"R_elbow_back", "R_wrist_back", {.5f, .5f, .5f}}, - {"L_shoulder_back", "L_elbow_back", {.5f, .5f, .5f}}, - {"L_elbow_back", "L_wrist_back", {.5f, .5f, .5f}}, + {"L_elbow_front", "L_wrist_front", {.5f, .5f, .5f}}, + {"R_shoulder_back", "R_elbow_back", {.5f, .5f, .5f}}, + {"R_elbow_back", "R_wrist_back", {.5f, .5f, .5f}}, + {"L_shoulder_back", "L_elbow_back", {.5f, .5f, .5f}}, + {"L_elbow_back", "L_wrist_back", {.5f, .5f, .5f}}, }; -void CNewIntroBoss::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Registered) - { - RemoveMaterial(EMaterialTypes::Solid, mgr); - RemoveMaterial(EMaterialTypes::Target, mgr); - RemoveMaterial(EMaterialTypes::Orbit, mgr); - RemoveMaterial(EMaterialTypes::Occluder, mgr); - x450_bodyController->Activate(mgr); +void CNewIntroBoss::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Registered) { + RemoveMaterial(EMaterialTypes::Solid, mgr); + RemoveMaterial(EMaterialTypes::Target, mgr); + RemoveMaterial(EMaterialTypes::Orbit, mgr); + RemoveMaterial(EMaterialTypes::Occluder, mgr); + x450_bodyController->Activate(mgr); - if (x5d4_stage1Projectile == kInvalidUniqueId) - { - CBeamInfo stage1BeamInfo = CBeamInfo(3, x5f0_, x5f4_, x5f8_, x5fc_, 50, 1.f, 1.f, 1.5f, 20.f, - 1.f, 4.f, 8.f, zeus::CColor::skYellow, - zeus::CColor(0.1098f, 0.5764f, 0.1592f), 150.f); - CBeamInfo stage2BeamInfo(3, x5f0_, x5f4_, x5f8_, x5fc_, 50, 1.f, 1.f, 2.f, 20.f, 1.f, 4.f, 8.f, - zeus::CColor::skYellow, zeus::CColor(0.1098f, 0.5764f, 0.1592f), 150.f); + if (x5d4_stage1Projectile == kInvalidUniqueId) { + CBeamInfo stage1BeamInfo = CBeamInfo(3, x5f0_, x5f4_, x5f8_, x5fc_, 50, 1.f, 1.f, 1.5f, 20.f, 1.f, 4.f, 8.f, + zeus::CColor::skYellow, zeus::CColor(0.1098f, 0.5764f, 0.1592f), 150.f); + CBeamInfo stage2BeamInfo(3, x5f0_, x5f4_, x5f8_, x5fc_, 50, 1.f, 1.f, 2.f, 20.f, 1.f, 4.f, 8.f, + zeus::CColor::skYellow, zeus::CColor(0.1098f, 0.5764f, 0.1592f), 150.f); - x5d4_stage1Projectile = mgr.AllocateUniqueId(); - x5d6_stage2Projectile = mgr.AllocateUniqueId(); - x5d8_stage3Projectile = mgr.AllocateUniqueId(); - CPlasmaProjectile* stage1Projectile = new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam"sv, EWeaponType::AI, - stage1BeamInfo, {}, EMaterialTypes::Character, - x5ac_projectileInfo.GetDamage(), x5d4_stage1Projectile, - GetAreaIdAlways(), GetUniqueId(), 8, true, - EProjectileAttrib::KeepInCinematic); - CPlasmaProjectile* stage2Projectile = new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam_Stage2"sv, - EWeaponType::AI, stage2BeamInfo, {}, EMaterialTypes::Character, - x5ac_projectileInfo.GetDamage(), x5d6_stage2Projectile, - GetAreaIdAlways(), GetUniqueId(), 8, true, - EProjectileAttrib::KeepInCinematic); - CPlasmaProjectile* stage3Projectile = new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam_Stage2"sv, - EWeaponType::AI, stage2BeamInfo, {}, EMaterialTypes::Character, - x5ac_projectileInfo.GetDamage(), x5d8_stage3Projectile, - GetAreaIdAlways(), GetUniqueId(), 8, true, - EProjectileAttrib::KeepInCinematic); - mgr.AddObject(stage1Projectile); - mgr.AddObject(stage2Projectile); - mgr.AddObject(stage3Projectile); - x676_curProjectile = x5d4_stage1Projectile; - } - - std::vector jointCollisions; - jointCollisions.reserve(15); - - const CAnimData* animData = GetModelData()->GetAnimationData(); - for (const SSphereJointDescription& joint : skSphereJoints) - { - CSegId seg = animData->GetLocatorSegId(joint.name); - jointCollisions.push_back( - CJointCollisionDescription::SphereCollision(seg, joint.radius, joint.name, 0.001f)); - } - - for (const SOBBJointDescription& joint : skOBBJoints) - { - CSegId from = animData->GetLocatorSegId(joint.from); - CSegId to = animData->GetLocatorSegId(joint.to); - jointCollisions.push_back( - CJointCollisionDescription::OBBAutoSizeCollision(from, to, joint.bounds, - CJointCollisionDescription::EOrientationType::One, - joint.from, 0.001f)); - } - - x5ec_collisionManager.reset( - new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), jointCollisions, GetActive())); - x640_initialHp = GetHealthInfo(mgr)->GetHP(); - - for (u32 i = 0; i < x5ec_collisionManager->GetNumCollisionActors(); ++i) - { - const CJointCollisionDescription& desc = x5ec_collisionManager->GetCollisionDescFromIndex(i); - TCastToPtr colAct = mgr.ObjectById(desc.GetCollisionActorId()); - if (desc.GetName() == skSphereJoints[0].name) - { - x600_headActor = desc.GetCollisionActorId(); - if (colAct) - { - CHealthInfo* thisHealthInfo = HealthInfo(mgr); - CHealthInfo* colHealthInfo = colAct->HealthInfo(mgr); - *colHealthInfo = *thisHealthInfo; - colAct->SetDamageVulnerability(*GetDamageVulnerability()); - colAct->RemoveMaterial(EMaterialTypes::Orbit, mgr); - } - } - else if (desc.GetName() == skOBBJoints[0].from) - { - x602_pelvisActor = desc.GetCollisionActorId(); - if (colAct) - { - CHealthInfo* thisHealthInfo = HealthInfo(mgr); - CHealthInfo* colHealthInfo = colAct->HealthInfo(mgr); - *colHealthInfo = *thisHealthInfo; - colAct->SetDamageVulnerability(CDamageVulnerability::NormalVulnerabilty()); - colAct->AddMaterial(EMaterialTypes::Orbit, mgr); - MoveScannableObjectInfoToActor(colAct, mgr); - } - } else - colAct->RemoveMaterial(EMaterialTypes::Orbit, mgr); - } - } - else if (msg == EScriptObjectMessage::Deleted) - { - DeleteBeam(mgr); - x5ec_collisionManager->Destroy(mgr); - } - else if (msg == EScriptObjectMessage::Damage) - { - if (uid == x600_headActor || uid == x602_pelvisActor) - TakeDamage({}, 0.f); + x5d4_stage1Projectile = mgr.AllocateUniqueId(); + x5d6_stage2Projectile = mgr.AllocateUniqueId(); + x5d8_stage3Projectile = mgr.AllocateUniqueId(); + CPlasmaProjectile* stage1Projectile = + new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam"sv, EWeaponType::AI, stage1BeamInfo, {}, + EMaterialTypes::Character, x5ac_projectileInfo.GetDamage(), x5d4_stage1Projectile, + GetAreaIdAlways(), GetUniqueId(), 8, true, EProjectileAttrib::KeepInCinematic); + CPlasmaProjectile* stage2Projectile = + new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam_Stage2"sv, EWeaponType::AI, stage2BeamInfo, + {}, EMaterialTypes::Character, x5ac_projectileInfo.GetDamage(), x5d6_stage2Projectile, + GetAreaIdAlways(), GetUniqueId(), 8, true, EProjectileAttrib::KeepInCinematic); + CPlasmaProjectile* stage3Projectile = + new CPlasmaProjectile(x5ac_projectileInfo.Token(), "IntroBoss_Beam_Stage2"sv, EWeaponType::AI, stage2BeamInfo, + {}, EMaterialTypes::Character, x5ac_projectileInfo.GetDamage(), x5d8_stage3Projectile, + GetAreaIdAlways(), GetUniqueId(), 8, true, EProjectileAttrib::KeepInCinematic); + mgr.AddObject(stage1Projectile); + mgr.AddObject(stage2Projectile); + mgr.AddObject(stage3Projectile); + x676_curProjectile = x5d4_stage1Projectile; } - bool active = GetActive(); - CPatterned::AcceptScriptMsg(msg, uid, mgr); - if (active == GetActive()) - return; + std::vector jointCollisions; + jointCollisions.reserve(15); + const CAnimData* animData = GetModelData()->GetAnimationData(); + for (const SSphereJointDescription& joint : skSphereJoints) { + CSegId seg = animData->GetLocatorSegId(joint.name); + jointCollisions.push_back(CJointCollisionDescription::SphereCollision(seg, joint.radius, joint.name, 0.001f)); + } - if (x5ec_collisionManager) - x5ec_collisionManager->SetActive(mgr, GetActive()); - x63c_attackTime = 8.f; -} + for (const SOBBJointDescription& joint : skOBBJoints) { + CSegId from = animData->GetLocatorSegId(joint.from); + CSegId to = animData->GetLocatorSegId(joint.to); + jointCollisions.push_back(CJointCollisionDescription::OBBAutoSizeCollision( + from, to, joint.bounds, CJointCollisionDescription::EOrientationType::One, joint.from, 0.001f)); + } -pas::ELocomotionType CNewIntroBoss::GetLocoForHealth(const CStateManager& mgr) const -{ - float hp = GetHealthInfo(mgr)->GetHP(); + x5ec_collisionManager.reset( + new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), jointCollisions, GetActive())); + x640_initialHp = GetHealthInfo(mgr)->GetHP(); - if (hp > .66f * x640_initialHp) - return pas::ELocomotionType::Relaxed; - else if (hp > .33f * x640_initialHp) - return pas::ELocomotionType::Lurk; - - return pas::ELocomotionType::Combat; -} - -void CNewIntroBoss::OnScanStateChanged(EScanState state, CStateManager& mgr) -{ - CPatterned::OnScanStateChanged(state, mgr); - if (state != EScanState::Done) - return; - - TCastToPtr colAct = mgr.ObjectById(x600_headActor); - if (colAct) - colAct->AddMaterial(EMaterialTypes::Orbit, mgr); - colAct = mgr.ObjectById(x602_pelvisActor); - if (colAct) + for (u32 i = 0; i < x5ec_collisionManager->GetNumCollisionActors(); ++i) { + const CJointCollisionDescription& desc = x5ec_collisionManager->GetCollisionDescFromIndex(i); + TCastToPtr colAct = mgr.ObjectById(desc.GetCollisionActorId()); + if (desc.GetName() == skSphereJoints[0].name) { + x600_headActor = desc.GetCollisionActorId(); + if (colAct) { + CHealthInfo* thisHealthInfo = HealthInfo(mgr); + CHealthInfo* colHealthInfo = colAct->HealthInfo(mgr); + *colHealthInfo = *thisHealthInfo; + colAct->SetDamageVulnerability(*GetDamageVulnerability()); + colAct->RemoveMaterial(EMaterialTypes::Orbit, mgr); + } + } else if (desc.GetName() == skOBBJoints[0].from) { + x602_pelvisActor = desc.GetCollisionActorId(); + if (colAct) { + CHealthInfo* thisHealthInfo = HealthInfo(mgr); + CHealthInfo* colHealthInfo = colAct->HealthInfo(mgr); + *colHealthInfo = *thisHealthInfo; + colAct->SetDamageVulnerability(CDamageVulnerability::NormalVulnerabilty()); + colAct->AddMaterial(EMaterialTypes::Orbit, mgr); + MoveScannableObjectInfoToActor(colAct, mgr); + } + } else colAct->RemoveMaterial(EMaterialTypes::Orbit, mgr); + } + } else if (msg == EScriptObjectMessage::Deleted) { + DeleteBeam(mgr); + x5ec_collisionManager->Destroy(mgr); + } else if (msg == EScriptObjectMessage::Damage) { + if (uid == x600_headActor || uid == x602_pelvisActor) + TakeDamage({}, 0.f); + } + + bool active = GetActive(); + CPatterned::AcceptScriptMsg(msg, uid, mgr); + if (active == GetActive()) + return; + + if (x5ec_collisionManager) + x5ec_collisionManager->SetActive(mgr, GetActive()); + x63c_attackTime = 8.f; } -void CNewIntroBoss::DeleteBeam(CStateManager& mgr) -{ - if (x5d4_stage1Projectile != kInvalidUniqueId) - { - mgr.FreeScriptObject(x5d4_stage1Projectile); - x5d4_stage1Projectile = kInvalidUniqueId; +pas::ELocomotionType CNewIntroBoss::GetLocoForHealth(const CStateManager& mgr) const { + float hp = GetHealthInfo(mgr)->GetHP(); + + if (hp > .66f * x640_initialHp) + return pas::ELocomotionType::Relaxed; + else if (hp > .33f * x640_initialHp) + return pas::ELocomotionType::Lurk; + + return pas::ELocomotionType::Combat; +} + +void CNewIntroBoss::OnScanStateChanged(EScanState state, CStateManager& mgr) { + CPatterned::OnScanStateChanged(state, mgr); + if (state != EScanState::Done) + return; + + TCastToPtr colAct = mgr.ObjectById(x600_headActor); + if (colAct) + colAct->AddMaterial(EMaterialTypes::Orbit, mgr); + colAct = mgr.ObjectById(x602_pelvisActor); + if (colAct) + colAct->RemoveMaterial(EMaterialTypes::Orbit, mgr); +} + +void CNewIntroBoss::DeleteBeam(CStateManager& mgr) { + if (x5d4_stage1Projectile != kInvalidUniqueId) { + mgr.FreeScriptObject(x5d4_stage1Projectile); + x5d4_stage1Projectile = kInvalidUniqueId; + } + if (x5d6_stage2Projectile != kInvalidUniqueId) { + mgr.FreeScriptObject(x5d6_stage2Projectile); + x5d6_stage2Projectile = kInvalidUniqueId; + } + if (x5d8_stage3Projectile != kInvalidUniqueId) { + mgr.FreeScriptObject(x5d8_stage3Projectile); + x5d8_stage3Projectile = kInvalidUniqueId; + } + + StopRumble(mgr); +} + +void CNewIntroBoss::StopRumble(CStateManager& mgr) { + if (x674_rumbleVoice == -1) + return; + + mgr.GetRumbleManager().StopRumble(x674_rumbleVoice); + x674_rumbleVoice = -1; +} + +void CNewIntroBoss::Think(float dt, CStateManager& mgr) { + CPatterned::Think(dt, mgr); + if (x638_ < 0.2f) + x638_ += dt; + + if (x400_25_alive) { + x574_boneTracking.SetTargetPosition(x62c_targetPos + zeus::CVector3f{0.f, 0.f, 10.f}); + x574_boneTracking.Update(dt); + } + + if (x63c_attackTime > 0.f) + x63c_attackTime -= dt; + + ModelData()->AnimationData()->PreRender(); + + if (x400_25_alive) + x574_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), x34_transform, ModelData()->GetScale(), + *x450_bodyController); + + x5ec_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); + + CPlasmaProjectile* curProjectile = static_cast(mgr.ObjectById(x676_curProjectile)); + if (curProjectile && curProjectile->GetActive()) { + x628_ += dt; + zeus::CTransform xf = GetLctrTransform(x5dc_damageLocator); + + if (x400_25_alive) { + zeus::CQuaternion clampedQuat = zeus::CQuaternion::clampedRotateTo( + (x610_lookPos + (zeus::min(x628_ / 1.5f, 1.f) * (x61c_ - x610_lookPos))) - xf.origin, xf.frontVector(), + zeus::CRelAngle::FromDegrees(30.f)); + curProjectile->UpdateFX(clampedQuat.toTransform() * xf.getRotation(), dt, mgr); + } else + curProjectile->UpdateFX(xf, dt, mgr); + } + + TCastToPtr headAct = mgr.ObjectById(x600_headActor); + TCastToPtr pelvisAct = mgr.ObjectById(x602_pelvisActor); + + if (headAct && pelvisAct) { + CHealthInfo* pelvisHealth = pelvisAct->HealthInfo(mgr); + CHealthInfo* headHealth = headAct->HealthInfo(mgr); + if (headHealth->GetHP() < pelvisHealth->GetHP()) { + *HealthInfo(mgr) = *headHealth; + *pelvisAct->HealthInfo(mgr) = *headHealth; + } else { + *HealthInfo(mgr) = *pelvisHealth; + *headAct->HealthInfo(mgr) = *pelvisHealth; } - if (x5d6_stage2Projectile != kInvalidUniqueId) - { - mgr.FreeScriptObject(x5d6_stage2Projectile); - x5d6_stage2Projectile = kInvalidUniqueId; - } - if (x5d8_stage3Projectile != kInvalidUniqueId) - { - mgr.FreeScriptObject(x5d8_stage3Projectile); - x5d8_stage3Projectile = kInvalidUniqueId; + } + + if (HealthInfo(mgr)->GetHP() <= 0.f && x400_25_alive) { + if (curProjectile) + curProjectile->ResetBeam(mgr, true); + + x450_bodyController->SetPlaybackRate(1.f); + SetTransform(x644_); + StopRumble(mgr); + Death(mgr, GetTransform().frontVector(), EScriptObjectState::DeathRattle); + } +} + +void CNewIntroBoss::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType event, float dt) { + if (event == EUserEventType::DamageOn) { + x5dc_damageLocator = node.GetLocatorName(); + zeus::CTransform xf = GetLctrTransform(x5dc_damageLocator); + zeus::CVector3f playerPos = PlayerPos(mgr); + x604_predictedPlayerPos = x610_lookPos = x62c_targetPos = playerPos; + x628_ = 0.f; + if (GetLocoForHealth(mgr) == pas::ELocomotionType::Combat) + x676_curProjectile = x5d8_stage3Projectile; + else if (GetLocoForHealth(mgr) == pas::ELocomotionType::Lurk) + x676_curProjectile = x5d6_stage2Projectile; + else + x676_curProjectile = x5d4_stage1Projectile; + + if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x676_curProjectile))) { + if (!projectile->GetActive()) { + projectile->Fire(zeus::lookAt(xf.origin, x610_lookPos), mgr, false); + + if (x674_rumbleVoice == -1) + x674_rumbleVoice = + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::IntroBossProjectile, 1.f, ERumblePriority::Two); + } } + } else if (event == EUserEventType::DamageOff) { + if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x676_curProjectile))) + projectile->ResetBeam(mgr, false); + StopRumble(mgr); + x63c_attackTime = GetNextAttackTime(mgr); + SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); + } else + CActor::DoUserAnimEvent(mgr, node, event, dt); } -void CNewIntroBoss::StopRumble(CStateManager& mgr) -{ - if (x674_rumbleVoice == -1) +void CNewIntroBoss::AddToRenderer(const zeus::CFrustum&, const CStateManager& mgr) const { EnsureRendered(mgr); } + +float CNewIntroBoss::GetNextAttackTime(CStateManager& mgr) const { + float attackTime = 2.f * mgr.GetActiveRandom()->Float() + 6.f; + float hp = GetHealthInfo(mgr)->GetHP(); + + if (hp > .66 * x640_initialHp) + return attackTime; + else if (hp > .33 * x640_initialHp) + return attackTime - (0.4125f * attackTime); + return attackTime - (0.825f * attackTime); +} + +zeus::CVector3f CNewIntroBoss::PlayerPos(const CStateManager& mgr) const { + CRayCastResult result = CGameCollision::RayStaticIntersection( + mgr, mgr.GetPlayer().GetTranslation() + zeus::CVector3f{0.f, 0.f, mgr.GetPlayer().GetEyeHeight() * 0.5f}, + zeus::CVector3f::skDown, 30.f, CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); + if (result.IsValid()) + return result.GetPoint() + zeus::CVector3f{0.f, 0.f, (mgr.GetPlayer().GetEyeHeight() * 0.5f) + 0.2f}; + + return mgr.GetPlayer().GetTranslation() + zeus::CVector3f{0.f, 0.f, (mgr.GetPlayer().GetEyeHeight() * 0.5f) + 0.2f}; +} + +bool CNewIntroBoss::ShouldTurn(CStateManager& mgr, float dt) { + zeus::CVector3f playerVel = 1.f * mgr.GetPlayer().GetVelocity(); + zeus::CVector3f playerPos = PlayerPos(mgr); + x604_predictedPlayerPos = playerPos + playerVel; + + zeus::CVector2f diffPos = (x604_predictedPlayerPos - GetTranslation()).toVec2f(); + + return zeus::CVector2f::getAngleDiff(GetTransform().frontVector().toVec2f(), diffPos) > zeus::degToRad(1.f); +} + +bool CNewIntroBoss::ShouldAttack(CStateManager& mgr, float dt) { + if (x63c_attackTime > 0.f) + return false; + + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Turn) + return false; + + return !ShouldTurn(mgr, dt); +} + +bool CNewIntroBoss::AIStage(CStateManager& mgr, float) { return x568_locomotion != GetLocoForHealth(mgr); } + +bool CNewIntroBoss::AnimOver(urde::CStateManager&, float) { return x56c_ == 3; } + +void CNewIntroBoss::Generate(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x56c_ = 0; + x568_locomotion = GetLocoForHealth(mgr); + SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); + } else if (msg == EStateMsg::Update) { + if (x56c_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) { + x56c_ = 2; return; + } - mgr.GetRumbleManager().StopRumble(x674_rumbleVoice); - x674_rumbleVoice = -1; + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(GetGenerateForHealth(mgr))); + } else if (x56c_ == 2) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) { + x56c_ = 3; + SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); + } + } + } } -void CNewIntroBoss::Think(float dt, CStateManager& mgr) -{ - CPatterned::Think(dt, mgr); - if (x638_ < 0.2f) - x638_ += dt; - - if (x400_25_alive) - { - x574_boneTracking.SetTargetPosition(x62c_targetPos + zeus::CVector3f{0.f, 0.f, 10.f}); - x574_boneTracking.Update(dt); - } - - if (x63c_attackTime > 0.f) - x63c_attackTime -= dt; - - ModelData()->AnimationData()->PreRender(); - - if (x400_25_alive) - x574_boneTracking.PreRender(mgr, *ModelData()->AnimationData(), x34_transform, ModelData()->GetScale(), - *x450_bodyController); - - x5ec_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); - - CPlasmaProjectile* curProjectile = static_cast(mgr.ObjectById(x676_curProjectile)); - if (curProjectile && curProjectile->GetActive()) - { - x628_ += dt; - zeus::CTransform xf = GetLctrTransform(x5dc_damageLocator); - - if (x400_25_alive) - { - zeus::CQuaternion clampedQuat = zeus::CQuaternion::clampedRotateTo( - (x610_lookPos + (zeus::min(x628_ / 1.5f, 1.f) * (x61c_ - x610_lookPos))) - xf.origin, - xf.frontVector(), zeus::CRelAngle::FromDegrees(30.f)); - curProjectile->UpdateFX(clampedQuat.toTransform() * xf.getRotation(), dt, mgr); - } else - curProjectile->UpdateFX(xf, dt, mgr); - } - - TCastToPtr headAct = mgr.ObjectById(x600_headActor); - TCastToPtr pelvisAct = mgr.ObjectById(x602_pelvisActor); - - if (headAct && pelvisAct) - { - CHealthInfo* pelvisHealth = pelvisAct->HealthInfo(mgr); - CHealthInfo* headHealth = headAct->HealthInfo(mgr); - if (headHealth->GetHP() < pelvisHealth->GetHP()) - { - *HealthInfo(mgr) = *headHealth; - *pelvisAct->HealthInfo(mgr) = *headHealth; - } - else - { - *HealthInfo(mgr) = *pelvisHealth; - *headAct->HealthInfo(mgr) = *pelvisHealth; - } - } - - if (HealthInfo(mgr)->GetHP() <= 0.f && x400_25_alive) - { - if (curProjectile) - curProjectile->ResetBeam(mgr, true); - - x450_bodyController->SetPlaybackRate(1.f); - SetTransform(x644_); - StopRumble(mgr); - Death(mgr, GetTransform().frontVector(), EScriptObjectState::DeathRattle); - } +pas::EGenerateType CNewIntroBoss::GetGenerateForHealth(const CStateManager& mgr) const { + return GetHealthInfo(mgr)->GetHP() > 0.33f * x640_initialHp ? pas::EGenerateType::Three : pas::EGenerateType::Four; } -void CNewIntroBoss::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType event, float dt) -{ - if (event == EUserEventType::DamageOn) - { - x5dc_damageLocator = node.GetLocatorName(); - zeus::CTransform xf = GetLctrTransform(x5dc_damageLocator); - zeus::CVector3f playerPos = PlayerPos(mgr); - x604_predictedPlayerPos = x610_lookPos = x62c_targetPos = playerPos; - x628_ = 0.f; - if (GetLocoForHealth(mgr) == pas::ELocomotionType::Combat) - x676_curProjectile = x5d8_stage3Projectile; - else if (GetLocoForHealth(mgr) == pas::ELocomotionType::Lurk) - x676_curProjectile = x5d6_stage2Projectile; - else - x676_curProjectile = x5d4_stage1Projectile; +bool CNewIntroBoss::InAttackPosition(CStateManager& mgr, float dt) { + return x330_stateMachineState.GetTime() > 0.25f && x678_ && + x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Turn && + !ShouldTurn(mgr, dt); +} - if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x676_curProjectile))) - { - if (!projectile->GetActive()) - { - projectile->Fire(zeus::lookAt(xf.origin, x610_lookPos), mgr, false); - - if (x674_rumbleVoice == -1) - x674_rumbleVoice = mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::IntroBossProjectile, 1.f, ERumblePriority::Two); - } - } +void CNewIntroBoss::Attack(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) + x56c_ = 0; + else if (msg == EStateMsg::Update) { + if (x56c_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) + x56c_ = 2; + else { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCProjectileAttackCmd(pas::ESeverity::One, mgr.GetPlayer().GetTranslation(), false)); + } + } else if (x56c_ == 2) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) { + x56c_ = 3; + x638_ = 0.f; + } + if (const CPlasmaProjectile* proj = + static_cast(mgr.GetObjectById(x676_curProjectile))) { + if (!proj->GetActive()) + x62c_targetPos = mgr.GetPlayer().GetTranslation(); + } } - else if (event == EUserEventType::DamageOff) - { - if (CPlasmaProjectile* projectile = static_cast(mgr.ObjectById(x676_curProjectile))) - projectile->ResetBeam(mgr, false); - - StopRumble(mgr); - x63c_attackTime = GetNextAttackTime(mgr); - SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); - } + } else if (msg == EStateMsg::Deactivate) { + if (GetLocoForHealth(mgr) == pas::ELocomotionType::Lurk || GetLocoForHealth(mgr) == pas::ELocomotionType::Combat) + x678_ ^= 1; else - CActor::DoUserAnimEvent(mgr, node, event, dt); + x678_ = false; + } } -void CNewIntroBoss::AddToRenderer(const zeus::CFrustum&, const CStateManager& mgr) const -{ - EnsureRendered(mgr); -} +void CNewIntroBoss::Patrol(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate || msg == EStateMsg::Update) { + x450_bodyController->SetLocomotionType(x568_locomotion); + if (x638_ > 0.2f) + x62c_targetPos = PlayerPos(mgr); + else + x62c_targetPos = x610_lookPos + ((x638_ / 0.2f) * (PlayerPos(mgr) - x610_lookPos)); -float CNewIntroBoss::GetNextAttackTime(CStateManager& mgr) const -{ - float attackTime = 2.f * mgr.GetActiveRandom()->Float() + 6.f; - float hp = GetHealthInfo(mgr)->GetHP(); - - if (hp > .66 * x640_initialHp) - return attackTime; - else if (hp > .33 * x640_initialHp) - return attackTime - (0.4125f * attackTime); - return attackTime - (0.825f * attackTime); -} - -zeus::CVector3f CNewIntroBoss::PlayerPos(const CStateManager& mgr) const -{ - CRayCastResult result = CGameCollision::RayStaticIntersection(mgr, mgr.GetPlayer().GetTranslation() + - zeus::CVector3f{0.f, 0.f, - mgr.GetPlayer().GetEyeHeight() * - 0.5f}, - zeus::CVector3f::skDown, 30.f, - CMaterialFilter::MakeInclude( - {EMaterialTypes::Solid})); - if (result.IsValid()) - return result.GetPoint() + zeus::CVector3f{0.f, 0.f, (mgr.GetPlayer().GetEyeHeight() * 0.5f) + 0.2f}; - - return mgr.GetPlayer().GetTranslation() + zeus::CVector3f{0.f, 0.f, (mgr.GetPlayer().GetEyeHeight() * 0.5f) + 0.2f}; -} - -bool CNewIntroBoss::ShouldTurn(CStateManager& mgr, float dt) -{ - zeus::CVector3f playerVel = 1.f * mgr.GetPlayer().GetVelocity(); - zeus::CVector3f playerPos = PlayerPos(mgr); - x604_predictedPlayerPos = playerPos + playerVel; - - zeus::CVector2f diffPos = (x604_predictedPlayerPos - GetTranslation()).toVec2f(); - - return zeus::CVector2f::getAngleDiff(GetTransform().frontVector().toVec2f(), diffPos) > zeus::degToRad(1.f); -} - -bool CNewIntroBoss::ShouldAttack(CStateManager& mgr, float dt) -{ - if (x63c_attackTime > 0.f) - return false; - - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Turn) - return false; - - return !ShouldTurn(mgr, dt); -} - -bool CNewIntroBoss::AIStage(CStateManager& mgr, float) -{ - return x568_locomotion != GetLocoForHealth(mgr); -} - -bool CNewIntroBoss::AnimOver(urde::CStateManager&, float) -{ - return x56c_ == 3; -} - -void CNewIntroBoss::Generate(CStateManager& mgr, EStateMsg msg, float dt) -{ - if (msg == EStateMsg::Activate) - { - x56c_ = 0; - x568_locomotion = GetLocoForHealth(mgr); - SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); - } - else if (msg == EStateMsg::Update) - { - if (x56c_ == 0) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) - { - x56c_ = 2; - return; - } - - x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(GetGenerateForHealth(mgr))); - } - else if (x56c_ == 2) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) - { - x56c_ = 3; - SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); - } - } + if (ShouldTurn(mgr, 0.f)) { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd({}, (x604_predictedPlayerPos - GetTranslation()).normalized(), 1.f)); } + } } -pas::EGenerateType CNewIntroBoss::GetGenerateForHealth(const CStateManager& mgr) const -{ - return GetHealthInfo(mgr)->GetHP() > 0.33f * x640_initialHp ? pas::EGenerateType::Three : pas::EGenerateType::Four; -} - -bool CNewIntroBoss::InAttackPosition(CStateManager& mgr, float dt) -{ - return x330_stateMachineState.GetTime() > 0.25f && x678_ && - x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Turn && - !ShouldTurn(mgr, dt); -} - -void CNewIntroBoss::Attack(CStateManager& mgr, EStateMsg msg, float dt) -{ - if (msg == EStateMsg::Activate) - x56c_ = 0; - else if (msg == EStateMsg::Update) - { - if (x56c_ == 0) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) - x56c_ = 2; - else - { - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCProjectileAttackCmd(pas::ESeverity::One, mgr.GetPlayer().GetTranslation(), false)); - } - } - else if (x56c_ == 2) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) - { - x56c_ = 3; - x638_ = 0.f; - } - - if (const CPlasmaProjectile* proj = static_cast(mgr.GetObjectById( - x676_curProjectile))) - { - if (!proj->GetActive()) - x62c_targetPos = mgr.GetPlayer().GetTranslation(); - } - } - } - else if (msg == EStateMsg::Deactivate) - { - if (GetLocoForHealth(mgr) == pas::ELocomotionType::Lurk || GetLocoForHealth(mgr) == pas::ELocomotionType::Combat) - x678_ ^= 1; - else - x678_ = false; - } -} - -void CNewIntroBoss::Patrol(CStateManager& mgr, EStateMsg msg, float dt) -{ - if (msg == EStateMsg::Activate || msg == EStateMsg::Update) - { - x450_bodyController->SetLocomotionType(x568_locomotion); - if (x638_ > 0.2f) - x62c_targetPos = PlayerPos(mgr); - else - x62c_targetPos = x610_lookPos + ((x638_ / 0.2f) * (PlayerPos(mgr) - x610_lookPos)); - - if (ShouldTurn(mgr, 0.f)) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd({}, - (x604_predictedPlayerPos - - GetTranslation()).normalized(), 1.f)); - } - } -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CNewIntroBoss.hpp b/Runtime/MP1/World/CNewIntroBoss.hpp index d47a3f2db..a5a2ab8b9 100644 --- a/Runtime/MP1/World/CNewIntroBoss.hpp +++ b/Runtime/MP1/World/CNewIntroBoss.hpp @@ -4,81 +4,75 @@ #include "Character/CBoneTracking.hpp" #include "Weapon/CProjectileInfo.hpp" -namespace urde -{ +namespace urde { class CDamageInfo; class CCollisionActorManager; -namespace MP1 -{ -class CNewIntroBoss : public CPatterned -{ - pas::ELocomotionType x568_locomotion = pas::ELocomotionType::Relaxed; - u32 x56c_ = 0; - float x570_; - CBoneTracking x574_boneTracking; - CProjectileInfo x5ac_projectileInfo; - TUniqueId x5d4_stage1Projectile = kInvalidUniqueId; - TUniqueId x5d6_stage2Projectile = kInvalidUniqueId; - TUniqueId x5d8_stage3Projectile = kInvalidUniqueId; - std::string x5dc_damageLocator; // ??? - std::unique_ptr x5ec_collisionManager; - CAssetId x5f0_; - CAssetId x5f4_; - CAssetId x5f8_; - CAssetId x5fc_; - TUniqueId x600_headActor = kInvalidUniqueId; - TUniqueId x602_pelvisActor = kInvalidUniqueId; - zeus::CVector3f x604_predictedPlayerPos; - zeus::CVector3f x610_lookPos; - zeus::CVector3f x61c_; - float x628_ = 0.f; - zeus::CVector3f x62c_targetPos; - float x638_ = 0.2f; - float x63c_attackTime = 8.f; - float x640_initialHp = 0.f; - zeus::CTransform x644_; - s16 x674_rumbleVoice = -1; - TUniqueId x676_curProjectile = kInvalidUniqueId; - bool x678_ = false; - pas::ELocomotionType GetLocoForHealth(const CStateManager&) const; - pas::EGenerateType GetGenerateForHealth(const CStateManager&) const; - float GetNextAttackTime(CStateManager&) const; - zeus::CVector3f PlayerPos(const CStateManager&) const; - void DeleteBeam(CStateManager&); - void StopRumble(CStateManager&); +namespace MP1 { +class CNewIntroBoss : public CPatterned { + pas::ELocomotionType x568_locomotion = pas::ELocomotionType::Relaxed; + u32 x56c_ = 0; + float x570_; + CBoneTracking x574_boneTracking; + CProjectileInfo x5ac_projectileInfo; + TUniqueId x5d4_stage1Projectile = kInvalidUniqueId; + TUniqueId x5d6_stage2Projectile = kInvalidUniqueId; + TUniqueId x5d8_stage3Projectile = kInvalidUniqueId; + std::string x5dc_damageLocator; // ??? + std::unique_ptr x5ec_collisionManager; + CAssetId x5f0_; + CAssetId x5f4_; + CAssetId x5f8_; + CAssetId x5fc_; + TUniqueId x600_headActor = kInvalidUniqueId; + TUniqueId x602_pelvisActor = kInvalidUniqueId; + zeus::CVector3f x604_predictedPlayerPos; + zeus::CVector3f x610_lookPos; + zeus::CVector3f x61c_; + float x628_ = 0.f; + zeus::CVector3f x62c_targetPos; + float x638_ = 0.2f; + float x63c_attackTime = 8.f; + float x640_initialHp = 0.f; + zeus::CTransform x644_; + s16 x674_rumbleVoice = -1; + TUniqueId x676_curProjectile = kInvalidUniqueId; + bool x678_ = false; + pas::ELocomotionType GetLocoForHealth(const CStateManager&) const; + pas::EGenerateType GetGenerateForHealth(const CStateManager&) const; + float GetNextAttackTime(CStateManager&) const; + zeus::CVector3f PlayerPos(const CStateManager&) const; + void DeleteBeam(CStateManager&); + void StopRumble(CStateManager&); + public: - DEFINE_PATTERNED(NewIntroBoss) - CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - const CActorParameters& actParms, float, CAssetId, const CDamageInfo& dInfo, - CAssetId, CAssetId, CAssetId, CAssetId); + DEFINE_PATTERNED(NewIntroBoss) + CNewIntroBoss(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, float, CAssetId, + const CDamageInfo& dInfo, CAssetId, CAssetId, CAssetId, CAssetId); - void Accept(IVisitor &visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager&); - void Think(float dt, CStateManager& mgr); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - void OnScanStateChanged(EScanState, CStateManager&); - CProjectileInfo* GetProjectileInfo() { return &x5ac_projectileInfo; } - zeus::CAABox GetSortingBounds(const CStateManager&) const - { - zeus::CAABox box = GetModelData()->GetBounds(); - return zeus::CAABox({-0.5f, -0.5f, box.min.z()}, {0.5f, 0.5f, box.max.z()}).getTransformedAABox(x34_transform); - } - - std::experimental::optional GetTouchBounds() const { return {}; } - void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt); - void Generate(CStateManager&, EStateMsg, float); - void Attack(CStateManager&, EStateMsg, float); - void Patrol(CStateManager&, EStateMsg, float); - bool ShouldTurn(CStateManager&, float); - bool ShouldAttack(CStateManager&, float); - bool AIStage(CStateManager&, float); - bool AnimOver(CStateManager&, float); - bool InAttackPosition(CStateManager&, float); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager&); + void Think(float dt, CStateManager& mgr); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void OnScanStateChanged(EScanState, CStateManager&); + CProjectileInfo* GetProjectileInfo() { return &x5ac_projectileInfo; } + zeus::CAABox GetSortingBounds(const CStateManager&) const { + zeus::CAABox box = GetModelData()->GetBounds(); + return zeus::CAABox({-0.5f, -0.5f, box.min.z()}, {0.5f, 0.5f, box.max.z()}).getTransformedAABox(x34_transform); + } + std::experimental::optional GetTouchBounds() const { return {}; } + void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt); + void Generate(CStateManager&, EStateMsg, float); + void Attack(CStateManager&, EStateMsg, float); + void Patrol(CStateManager&, EStateMsg, float); + bool ShouldTurn(CStateManager&, float); + bool ShouldAttack(CStateManager&, float); + bool AIStage(CStateManager&, float); + bool AnimOver(CStateManager&, float); + bool InAttackPosition(CStateManager&, float); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/World/CParasite.cpp b/Runtime/MP1/World/CParasite.cpp index 2c9e12a4f..217522ac5 100644 --- a/Runtime/MP1/World/CParasite.cpp +++ b/Runtime/MP1/World/CParasite.cpp @@ -15,8 +15,7 @@ #include "Collision/CGameCollision.hpp" #include "Collision/CCollisionActor.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { const float CParasite::flt_805A8FB0 = 2.f * std::sqrt(2.5f / 24.525002f); const float CParasite::skAttackVelocity = 15.f / 2.f * (std::sqrt(2.5f / 24.525002f)); @@ -24,8 +23,8 @@ short CParasite::word_805A8FC0 = 0; const float CParasite::flt_805A8FB8 = 2.f * std::sqrt(2.5f / 24.525002f); const float CParasite::skRetreatVelocity = 3.f / 2.f * std::sqrt(2.5f / 24.525002f); -CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo &info, - const zeus::CTransform &xf, CModelData &&mData, const CPatternedInfo &pInfo, EBodyType bodyType, +CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EBodyType bodyType, float maxTelegraphReactDist, float advanceWpRadius, float f3, float alignAngVel, float f5, float stuckTimeThreshold, float collisionCloseMargin, float parasiteSearchRadius, float parasiteSeparationDist, float parasiteSeparationWeight, float parasiteAlignmentWeight, @@ -33,8 +32,7 @@ CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, c float playerSeparationDist, float playerSeparationWeight, float playerObstructionMinDist, float haltDelay, bool disableMove, EWalkerType wType, const CDamageVulnerability& dVuln, const CDamageInfo& parInfo, u16 haltSfx, u16 getUpSfx, u16 crouchSfx, CAssetId modelRes, - CAssetId skinRes, float iceZoomerJointHP, - const CActorParameters& aParams) + CAssetId skinRes, float iceZoomerJointHP, const CActorParameters& aParams) : CWallWalker(ECharacter::Parasite, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, EColliderType::Zero, bodyType, aParams, collisionCloseMargin, alignAngVel, EKnockBackVariant::Small, advanceWpRadius, wType, playerObstructionMinDist, disableMove) @@ -58,966 +56,814 @@ CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, c , x714_iceZoomerJointHP(iceZoomerJointHP) , x73c_haltSfx(CSfxManager::TranslateSFXID(haltSfx)) , x73e_getUpSfx(CSfxManager::TranslateSFXID(getUpSfx)) -, x740_crouchSfx(CSfxManager::TranslateSFXID(crouchSfx)) -{ - x742_28_onGround = true; - x742_30_attackOver = true; +, x740_crouchSfx(CSfxManager::TranslateSFXID(crouchSfx)) { + x742_28_onGround = true; + x742_30_attackOver = true; - switch (x5d0_walkerType) - { - case EWalkerType::Geemer: - x460_knockBackController.SetEnableFreeze(false); - case EWalkerType::Oculus: - x460_knockBackController.SetAutoResetImpulse(false); - break; - case EWalkerType::IceZoomer: - { - TLockedToken model = g_SimplePool->GetObj({FOURCC('CMDL'), modelRes}); - TLockedToken skin = g_SimplePool->GetObj({FOURCC('CSKR'), skinRes}); - x624_extraModel = CToken( - TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::make_unique( + switch (x5d0_walkerType) { + case EWalkerType::Geemer: + x460_knockBackController.SetEnableFreeze(false); + case EWalkerType::Oculus: + x460_knockBackController.SetAutoResetImpulse(false); + break; + case EWalkerType::IceZoomer: { + TLockedToken model = g_SimplePool->GetObj({FOURCC('CMDL'), modelRes}); + TLockedToken skin = g_SimplePool->GetObj({FOURCC('CSKR'), skinRes}); + x624_extraModel = + CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::make_unique( model, skin, x64_modelData->AnimationData()->GetModelData()->GetLayoutInfo(), 1, 1))); - } - default: - break; - } - if (x5d0_walkerType == EWalkerType::Oculus) - { - x460_knockBackController.SetEnableShock(false); - x460_knockBackController.SetEnableBurn(false); - x460_knockBackController.SetEnableBurnDeath(false); - x460_knockBackController.SetEnableExplodeDeath(false); - x460_knockBackController.SetX82_24(false); - } + } + default: + break; + } + if (x5d0_walkerType == EWalkerType::Oculus) { + x460_knockBackController.SetEnableShock(false); + x460_knockBackController.SetEnableBurn(false); + x460_knockBackController.SetEnableBurnDeath(false); + x460_knockBackController.SetEnableExplodeDeath(false); + x460_knockBackController.SetX82_24(false); + } } -void CParasite::Accept(IVisitor &visitor) { visitor.Visit(this); } +void CParasite::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CParasite::SetupIceZoomerCollision(CStateManager& mgr) -{ - std::vector descs; - descs.reserve(2); - descs.push_back(CJointCollisionDescription::SphereCollision( - x64_modelData->GetAnimationData()->GetLocatorSegId("Ice_LCTR"sv), 0.4f, "Ice_LCTR"sv, 0.001f)); - RemoveMaterial(EMaterialTypes::Solid, mgr); - AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); - x620_collisionActorManager = - std::make_unique(mgr, GetUniqueId(), GetAreaIdAlways(), - descs, GetActive()); +void CParasite::SetupIceZoomerCollision(CStateManager& mgr) { + std::vector descs; + descs.reserve(2); + descs.push_back(CJointCollisionDescription::SphereCollision( + x64_modelData->GetAnimationData()->GetLocatorSegId("Ice_LCTR"sv), 0.4f, "Ice_LCTR"sv, 0.001f)); + RemoveMaterial(EMaterialTypes::Solid, mgr); + AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); + x620_collisionActorManager = + std::make_unique(mgr, GetUniqueId(), GetAreaIdAlways(), descs, GetActive()); } void CParasite::SetupIceZoomerVulnerability(CStateManager& mgr, const CDamageVulnerability& dVuln, - const CHealthInfo& hInfo) -{ - for (u32 i = 0; i < x620_collisionActorManager->GetNumCollisionActors(); ++i) - { - const CJointCollisionDescription& cDesc = x620_collisionActorManager->GetCollisionDescFromIndex(i); - if (TCastToPtr act = mgr.ObjectById(cDesc.GetCollisionActorId())) - { - act->SetDamageVulnerability(dVuln); - *act->HealthInfo(mgr) = hInfo; - } + const CHealthInfo& hInfo) { + for (u32 i = 0; i < x620_collisionActorManager->GetNumCollisionActors(); ++i) { + const CJointCollisionDescription& cDesc = x620_collisionActorManager->GetCollisionDescFromIndex(i); + if (TCastToPtr act = mgr.ObjectById(cDesc.GetCollisionActorId())) { + act->SetDamageVulnerability(dVuln); + *act->HealthInfo(mgr) = hInfo; } + } } -void CParasite::AddDoorRepulsors(CStateManager& mgr) -{ - u32 doorCount = 0; - for (CEntity* ent : mgr.GetPhysicsActorObjectList()) - if (TCastToPtr door = ent) - if (door->GetAreaIdAlways() == GetAreaIdAlways()) - ++doorCount; - x5d8_doorRepulsors.reserve(doorCount); - for (CEntity* ent : mgr.GetPhysicsActorObjectList()) - if (TCastToPtr door = ent) - if (door->GetAreaIdAlways() == GetAreaIdAlways()) - { - if (auto tb = door->GetTouchBounds()) - { - float diagMag = (tb->min - tb->max).magnitude() * 0.75f; - x5d8_doorRepulsors.emplace_back(tb->center(), diagMag); - } - } +void CParasite::AddDoorRepulsors(CStateManager& mgr) { + u32 doorCount = 0; + for (CEntity* ent : mgr.GetPhysicsActorObjectList()) + if (TCastToPtr door = ent) + if (door->GetAreaIdAlways() == GetAreaIdAlways()) + ++doorCount; + x5d8_doorRepulsors.reserve(doorCount); + for (CEntity* ent : mgr.GetPhysicsActorObjectList()) + if (TCastToPtr door = ent) + if (door->GetAreaIdAlways() == GetAreaIdAlways()) { + if (auto tb = door->GetTouchBounds()) { + float diagMag = (tb->min - tb->max).magnitude() * 0.75f; + x5d8_doorRepulsors.emplace_back(tb->center(), diagMag); + } + } } static TUniqueId lastParasite = kInvalidUniqueId; -void CParasite::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CPatterned::AcceptScriptMsg(msg, uid, mgr); - switch (msg) - { - case EScriptObjectMessage::Registered: - x450_bodyController->Activate(mgr); - mgr.GetActiveParasites().push_back(GetUniqueId()); - CActor::CreateShadow(false); - x604_activeSpeed = x3b4_speed; - CPhysicsActor::SetBoundingBox( - zeus::CAABox(zeus::CVector3f(-x590_colSphere.GetSphere().radius), - zeus::CVector3f(x590_colSphere.GetSphere().radius))); - lastParasite = GetUniqueId(); - AddDoorRepulsors(mgr); - if (x5d0_walkerType == EWalkerType::IceZoomer) - { - SetupIceZoomerCollision(mgr); - SetupIceZoomerVulnerability(mgr, x64c_oculusHaltDVuln, - CHealthInfo(x714_iceZoomerJointHP, HealthInfo(mgr)->GetKnockbackResistance())); - } - break; - case EScriptObjectMessage::Deleted: - mgr.GetActiveParasites().remove(GetUniqueId()); - if (x5d0_walkerType == EWalkerType::IceZoomer) - DestroyActorManager(mgr); - break; - case EScriptObjectMessage::Jumped: - if (x742_25_jumpVelDirty) - { - UpdateJumpVelocity(); - x742_25_jumpVelDirty = false; - } - break; - case EScriptObjectMessage::Activate: - x5d6_27_disableMove = false; - if (x5d0_walkerType == EWalkerType::Parasite) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - break; - case EScriptObjectMessage::InvulnDamage: - if (x5d0_walkerType == EWalkerType::Oculus) - { - if (TCastToConstPtr act = mgr.GetObjectById(uid)) - { - float distSq = (act->GetTranslation() - GetTranslation()).magSquared(); - auto tb = GetTouchBounds(); - float maxComp = std::max(std::max(tb->max.y() - tb->min.y(), tb->max.z() - tb->min.z()), - tb->max.x() - tb->min.x()); - float maxCompSq = maxComp * maxComp + 1.f; - if (distSq < maxCompSq * maxCompSq) - x743_26_oculusShotAt = true; - } - } - break; - case EScriptObjectMessage::SuspendedMove: - if (x620_collisionActorManager) - x620_collisionActorManager->SetMovable(mgr, false); - break; - default: - break; +void CParasite::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); + switch (msg) { + case EScriptObjectMessage::Registered: + x450_bodyController->Activate(mgr); + mgr.GetActiveParasites().push_back(GetUniqueId()); + CActor::CreateShadow(false); + x604_activeSpeed = x3b4_speed; + CPhysicsActor::SetBoundingBox(zeus::CAABox(zeus::CVector3f(-x590_colSphere.GetSphere().radius), + zeus::CVector3f(x590_colSphere.GetSphere().radius))); + lastParasite = GetUniqueId(); + AddDoorRepulsors(mgr); + if (x5d0_walkerType == EWalkerType::IceZoomer) { + SetupIceZoomerCollision(mgr); + SetupIceZoomerVulnerability(mgr, x64c_oculusHaltDVuln, + CHealthInfo(x714_iceZoomerJointHP, HealthInfo(mgr)->GetKnockbackResistance())); } -} - -void CParasite::PreThink(float dt, CStateManager& mgr) -{ - CWallWalker::PreThink(dt, mgr); - x743_26_oculusShotAt = false; -} - -void CParasite::UpdateCollisionActors(float dt, CStateManager& mgr) -{ - x620_collisionActorManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); - if (!x743_25_vulnerable) - { - float totalHP = 0.f; - for (u32 i = 0; i < x620_collisionActorManager->GetNumCollisionActors(); ++i) - { - const CJointCollisionDescription& cDesc = x620_collisionActorManager->GetCollisionDescFromIndex(i); - if (TCastToPtr cact = mgr.ObjectById(cDesc.GetCollisionActorId())) - totalHP += cact->HealthInfo(mgr)->GetHP(); - } - if (totalHP <= 0.f) - { - x743_25_vulnerable = true; - AddMaterial(EMaterialTypes::Solid, mgr); - RemoveMaterial(EMaterialTypes::ProjectilePassthrough, mgr); - DestroyActorManager(mgr); - x64_modelData->AnimationData()->SubstituteModelData(x624_extraModel); - } - } -} - -void CParasite::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; - - ++x5d4_thinkCounter; + break; + case EScriptObjectMessage::Deleted: + mgr.GetActiveParasites().remove(GetUniqueId()); if (x5d0_walkerType == EWalkerType::IceZoomer) - UpdateCollisionActors(dt, mgr); + DestroyActorManager(mgr); + break; + case EScriptObjectMessage::Jumped: + if (x742_25_jumpVelDirty) { + UpdateJumpVelocity(); + x742_25_jumpVelDirty = false; + } + break; + case EScriptObjectMessage::Activate: + x5d6_27_disableMove = false; + if (x5d0_walkerType == EWalkerType::Parasite) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + break; + case EScriptObjectMessage::InvulnDamage: + if (x5d0_walkerType == EWalkerType::Oculus) { + if (TCastToConstPtr act = mgr.GetObjectById(uid)) { + float distSq = (act->GetTranslation() - GetTranslation()).magSquared(); + auto tb = GetTouchBounds(); + float maxComp = + std::max(std::max(tb->max.y() - tb->min.y(), tb->max.z() - tb->min.z()), tb->max.x() - tb->min.x()); + float maxCompSq = maxComp * maxComp + 1.f; + if (distSq < maxCompSq * maxCompSq) + x743_26_oculusShotAt = true; + } + } + break; + case EScriptObjectMessage::SuspendedMove: + if (x620_collisionActorManager) + x620_collisionActorManager->SetMovable(mgr, false); + break; + default: + break; + } +} - x5d6_26_playerObstructed = false; - CGameArea* area = mgr.WorldNC()->GetArea(GetAreaIdAlways()); +void CParasite::PreThink(float dt, CStateManager& mgr) { + CWallWalker::PreThink(dt, mgr); + x743_26_oculusShotAt = false; +} - CGameArea::EOcclusionState r6 = CGameArea::EOcclusionState::Occluded; - if (area->IsPostConstructed()) - r6 = area->GetPostConstructed()->x10dc_occlusionState; - if (r6 != CGameArea::EOcclusionState::Visible) +void CParasite::UpdateCollisionActors(float dt, CStateManager& mgr) { + x620_collisionActorManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); + if (!x743_25_vulnerable) { + float totalHP = 0.f; + for (u32 i = 0; i < x620_collisionActorManager->GetNumCollisionActors(); ++i) { + const CJointCollisionDescription& cDesc = x620_collisionActorManager->GetCollisionDescFromIndex(i); + if (TCastToPtr cact = mgr.ObjectById(cDesc.GetCollisionActorId())) + totalHP += cact->HealthInfo(mgr)->GetHP(); + } + if (totalHP <= 0.f) { + x743_25_vulnerable = true; + AddMaterial(EMaterialTypes::Solid, mgr); + RemoveMaterial(EMaterialTypes::ProjectilePassthrough, mgr); + DestroyActorManager(mgr); + x64_modelData->AnimationData()->SubstituteModelData(x624_extraModel); + } + } +} + +void CParasite::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; + + ++x5d4_thinkCounter; + if (x5d0_walkerType == EWalkerType::IceZoomer) + UpdateCollisionActors(dt, mgr); + + x5d6_26_playerObstructed = false; + CGameArea* area = mgr.WorldNC()->GetArea(GetAreaIdAlways()); + + CGameArea::EOcclusionState r6 = CGameArea::EOcclusionState::Occluded; + if (area->IsPostConstructed()) + r6 = area->GetPostConstructed()->x10dc_occlusionState; + if (r6 != CGameArea::EOcclusionState::Visible) + x5d6_26_playerObstructed = true; + + if (!x5d6_26_playerObstructed) { + zeus::CVector3f plVec = mgr.GetPlayer().GetTranslation(); + float distance = (GetTranslation() - plVec).magnitude(); + + if (distance > x5c4_playerObstructionMinDist) { + CRayCastResult res = mgr.RayStaticIntersection(plVec, (GetTranslation() - plVec).normalized(), distance, + CMaterialFilter::skPassEverything); + if (res.IsValid()) x5d6_26_playerObstructed = true; - - if (!x5d6_26_playerObstructed) - { - zeus::CVector3f plVec = mgr.GetPlayer().GetTranslation(); - float distance = (GetTranslation() - plVec).magnitude() ; - - if (distance > x5c4_playerObstructionMinDist) - { - CRayCastResult res = mgr.RayStaticIntersection(plVec, (GetTranslation() - plVec).normalized(), distance, - CMaterialFilter::skPassEverything); - if (res.IsValid()) - x5d6_26_playerObstructed = true; - } } + } - if (x5d6_26_playerObstructed) - { - xf8_24_movable = false; - return; - } + if (x5d6_26_playerObstructed) { + xf8_24_movable = false; + return; + } - xf8_24_movable = !x5d6_24_alignToFloor; + xf8_24_movable = !x5d6_24_alignToFloor; - if (!x5d6_27_disableMove) - { - if (x450_bodyController->IsFrozen()) - { - if ((GetTranslation() - x614_lastStuckPos).magSquared() < 0.3f /* <- Used to be a static variable */ * dt) - x60c_stuckTime += dt; - else - x60c_stuckTime = 0.f; + if (!x5d6_27_disableMove) { + if (x450_bodyController->IsFrozen()) { + if ((GetTranslation() - x614_lastStuckPos).magSquared() < 0.3f /* <- Used to be a static variable */ * dt) + x60c_stuckTime += dt; + else + x60c_stuckTime = 0.f; - x614_lastStuckPos = GetTranslation(); - if (x608_telegraphRemTime > 0.f) - x608_telegraphRemTime -= dt; - else - x608_telegraphRemTime = 0.f; - } - } - - if (x400_25_alive) - { - CPlayer* pl = mgr.Player(); - float radius; - if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && !x742_30_attackOver) - radius = x590_colSphere.GetSphere().radius; - else - radius = x708_unmorphedRadius; - - zeus::CAABox aabox{GetTranslation() - radius, GetTranslation() + radius}; - auto plBox = pl->GetTouchBounds(); - - if (plBox && plBox->intersects(aabox)) - { - if (!x742_30_attackOver) - { - x742_30_attackOver = true; - x742_27_landed = false; - } - - if (x420_curDamageRemTime <= 0.f) - { - mgr.ApplyDamage(GetUniqueId(), pl->GetUniqueId(), GetUniqueId(), GetContactDamage(), - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); - x420_curDamageRemTime = x424_damageWaitTime; - } - } - } - - CWallWalker::Think(dt, mgr); - - if (x5d6_27_disableMove) - return; - - if (x450_bodyController->IsFrozen()) - return; - - x3b4_speed = x604_activeSpeed; - if (x5d6_24_alignToFloor) - AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + 2.f * dt * x138_velocity, dt); - - x742_27_landed = false; -} - -void CParasite::Render(const CStateManager& mgr) const -{ - CWallWalker::Render(mgr); -} - -const CDamageVulnerability* CParasite::GetDamageVulnerability() const -{ - switch (x5d0_walkerType) - { - case EWalkerType::Oculus: - if (x743_24_halted) - return &x64c_oculusHaltDVuln; - break; - case EWalkerType::IceZoomer: - if (!x743_25_vulnerable) - return &CDamageVulnerability::ImmuneVulnerabilty(); - break; - default: - break; - } - return CAi::GetDamageVulnerability(); -} - -CDamageInfo CParasite::GetContactDamage() const -{ - if (x5d0_walkerType == EWalkerType::Oculus && x743_24_halted) - return x6b4_oculusHaltDInfo; - return CPatterned::GetContactDamage(); -} - -void CParasite::Touch(CActor& actor, CStateManager& mgr) -{ - CPatterned::Touch(actor, mgr); -} - -zeus::CVector3f CParasite::GetAimPosition(const CStateManager&, float) const -{ - return GetTranslation(); -} - -void CParasite::CollidedWith(TUniqueId uid, const CCollisionInfoList& list, CStateManager&) -{ - static CMaterialList testList(EMaterialTypes::Character, EMaterialTypes::Player); - if (x743_27_inJump) - { - for (const auto& info : list) - { - if (!x5d6_24_alignToFloor && info.GetMaterialLeft().Intersection(testList) == 0) - { - OrientToSurfaceNormal(info.GetNormalLeft(), 360.f); - CPhysicsActor::Stop(); - SetVelocityWR(zeus::CVector3f::skZero); - x742_27_landed = true; - x742_28_onGround = true; - } - } - } -} - -void CParasite::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) -{ - CPhysicsActor::Stop(); - TelegraphAttack(mgr, EStateMsg::Activate, 0.f); - SetMomentumWR({0.f, 0.f, -GetWeight()}); - CPatterned::Death(mgr, direction, state); -} - -void CParasite::Patrol(CStateManager& mgr, EStateMsg msg, float dt) -{ - switch (msg) - { - case EStateMsg::Activate: - x742_26_ = true; - x5d6_24_alignToFloor = true; - if (!x5d6_27_disableMove && x5d0_walkerType == EWalkerType::Parasite) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - SetMomentumWR(zeus::CVector3f::skZero); - x5d6_25_hasAlignSurface = false; - xf8_24_movable = false; - break; - case EStateMsg::Update: - if (x5bc_patrolPauseRemTime > 0.f) - { - x5bc_patrolPauseRemTime -= dt; - if (x5bc_patrolPauseRemTime <= 0.f) - { - if (x5d0_walkerType == EWalkerType::Parasite) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - x5bc_patrolPauseRemTime = 0.f; - } - } - GotoNextWaypoint(mgr); - if (x5bc_patrolPauseRemTime <= 0.f && !x5d6_27_disableMove) - DoFlockingBehavior(mgr); - break; - case EStateMsg::Deactivate: - x5d6_24_alignToFloor = false; - xf8_24_movable = true; - break; - default: - break; - } -} - -void CParasite::UpdatePFDestination(CStateManager& mgr) -{ - // Empty -} - -void CParasite::DoFlockingBehavior(CStateManager& mgr) -{ - zeus::CVector3f upVec = x34_transform.basis[2]; - rstl::reserved_vector parasiteList; - zeus::CAABox aabb(GetTranslation() - x6e4_parasiteSearchRadius, - GetTranslation() + x6e4_parasiteSearchRadius); - if ((x5d4_thinkCounter % 6) == 0) - { - rstl::reserved_vector nearList; - static CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Character); - CParasite* closestParasite = nullptr; - float minDistSq = 2.f + x6e8_parasiteSeparationDist * x6e8_parasiteSeparationDist; - mgr.BuildNearList(nearList, aabb, filter, nullptr); - for (TUniqueId id : nearList) - { - if (CParasite* parasite = CPatterned::CastTo(mgr.ObjectById(id))) - { - if (parasite != this && parasite->IsAlive()) - { - parasiteList.push_back(parasite->GetUniqueId()); - float distSq = (parasite->GetTranslation() - GetTranslation()).magSquared(); - if (distSq < minDistSq) - { - minDistSq = distSq; - closestParasite = parasite; - } - } - } - } - if (closestParasite && x6ec_parasiteSeparationWeight > 0.f && x6e8_parasiteSeparationDist > 0.f) - x628_parasiteSeparationMove = x45c_steeringBehaviors.Separation(*this, closestParasite->GetTranslation(), - x6e8_parasiteSeparationDist) * x604_activeSpeed; - else - x628_parasiteSeparationMove = zeus::CVector3f::skZero; - x634_parasiteCohesionMove = x45c_steeringBehaviors.Cohesion(*this, parasiteList, 0.6f, mgr) * x604_activeSpeed; - x640_parasiteAlignmentMove = x45c_steeringBehaviors.Alignment(*this, parasiteList, mgr) * x604_activeSpeed; - } - - if ((mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < - x700_playerSeparationDist * x700_playerSeparationDist) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( - x45c_steeringBehaviors.Separation(*this, mgr.GetPlayer().GetTranslation(), - x700_playerSeparationDist), upVec) * x604_activeSpeed, - zeus::CVector3f::skZero, x704_playerSeparationWeight)); - } - - if (x628_parasiteSeparationMove != zeus::CVector3f::skZero) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( - x628_parasiteSeparationMove, upVec), zeus::CVector3f::skZero, x6ec_parasiteSeparationWeight)); - } - - for (const auto& r : x5d8_doorRepulsors) - { - if ((r.GetVector() - GetTranslation()).magSquared() < r.GetFloat() * r.GetFloat()) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( - x45c_steeringBehaviors.Separation(*this, r.GetVector(), r.GetFloat()) * x604_activeSpeed, upVec), - zeus::CVector3f::skZero, 1.f)); - } - } - - if (x608_telegraphRemTime <= 0.f) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( - x634_parasiteCohesionMove, upVec), zeus::CVector3f::skZero, x6f4_parasiteCohesionWeight)); - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( - x640_parasiteAlignmentMove, upVec), zeus::CVector3f::skZero, x6f0_parasiteAlignmentWeight)); - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( - ProjectVectorToPlane(ProjectVectorToPlane( - x45c_steeringBehaviors.Seek(*this, x2e0_destPos), upVec) * x604_activeSpeed, upVec), - zeus::CVector3f::skZero, x6f8_destinationSeekWeight)); - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( - x34_transform.basis[1] * x604_activeSpeed, zeus::CVector3f::skZero, x6fc_forwardMoveWeight)); - } -} - -void CParasite::PathFind(CStateManager& mgr, EStateMsg msg, float dt) -{ - switch (msg) - { - case EStateMsg::Activate: - x742_26_ = true; - x5d6_24_alignToFloor = true; - if (x5d0_walkerType == EWalkerType::Parasite) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - SetMomentumWR(zeus::CVector3f::skZero); - xf8_24_movable = false; - break; - case EStateMsg::Update: - UpdatePFDestination(mgr); - DoFlockingBehavior(mgr); - break; - case EStateMsg::Deactivate: - xf8_24_movable = true; - x5d6_24_alignToFloor = false; - x742_26_ = false; - break; - default: - break; - } -} - -void CParasite::TargetPlayer(CStateManager& mgr, EStateMsg msg, float dt) -{ - switch (msg) - { - case EStateMsg::Activate: - x5f8_targetPos = mgr.GetPlayer().GetTranslation() + zeus::CVector3f(0.f, 0.f, 1.5f); - break; - case EStateMsg::Update: - x450_bodyController->FaceDirection3D( - ProjectVectorToPlane(x5f8_targetPos - GetTranslation(), x34_transform.basis[2]), - x34_transform.basis[1], 2.f); - break; - default: - break; - } -} - -TUniqueId CParasite::RecursiveFindClosestWayPoint(CStateManager& mgr, TUniqueId id, float& dist) -{ - TUniqueId ret = id; - TCastToPtr wp = mgr.ObjectById(id); - if (!wp) - return ret; - wp->SetActive(false); - dist = (wp->GetTranslation() - GetTranslation()).magSquared(); - for (const auto& conn : wp->GetConnectionList()) - { - if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) - { - TUniqueId nextId = mgr.GetIdForScript(conn.x8_objId); - if (nextId != kInvalidUniqueId) - { - if (TCastToConstPtr wp2 = mgr.GetObjectById(nextId)) - { - if (wp2->GetActive()) - { - float nextDist; - TUniqueId closestWp = RecursiveFindClosestWayPoint(mgr, nextId, nextDist); - if (nextDist < dist) - { - dist = nextDist; - ret = closestWp; - } - } - } - } - } - } - wp->SetActive(true); - return ret; -} - -TUniqueId CParasite::GetClosestWaypointForState(EScriptObjectState state, CStateManager& mgr) -{ - float minDist = FLT_MAX; - TUniqueId ret = kInvalidUniqueId; - for (const auto& conn : GetConnectionList()) - { - if (conn.x0_state == state && conn.x4_msg == EScriptObjectMessage::Follow) - { - TUniqueId id = mgr.GetIdForScript(conn.x8_objId); - float dist; - TUniqueId closestWp = RecursiveFindClosestWayPoint(mgr, id, dist); - if (dist < minDist) - { - minDist = dist; - ret = closestWp; - } - } - } - return ret; -} - -void CParasite::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) -{ - if (msg == EStateMsg::Activate) - { - SetMomentumWR(zeus::CVector3f::skZero); - TUniqueId wpId = GetClosestWaypointForState(EScriptObjectState::Patrol, mgr); - if (wpId != kInvalidUniqueId) - x2dc_destObj = wpId; - } -} - -void CParasite::Halt(CStateManager& mgr, EStateMsg msg, float) -{ - switch (msg) - { - case EStateMsg::Activate: - x330_stateMachineState.SetDelay(x710_haltDelay); - x32c_animState = EAnimState::One; - x743_24_halted = true; - x5d6_24_alignToFloor = true; - if (x5d0_walkerType == EWalkerType::Geemer) - CSfxManager::AddEmitter(x73c_haltSfx, GetTranslation(), zeus::CVector3f::skZero, - true, false, 0x7f, kInvalidAreaId); - break; - case EStateMsg::Update: - TryCommand(mgr, pas::EAnimationState::LoopReaction, &CPatterned::TryLoopReaction, 1); - x400_24_hitByPlayerProjectile = false; - break; - case EStateMsg::Deactivate: - x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); - x32c_animState = EAnimState::Zero; - x743_24_halted = false; - x5d6_24_alignToFloor = false; - break; - default: - break; - } -} - -void CParasite::Run(CStateManager&, EStateMsg, float) -{ - // Empty -} - -void CParasite::Generate(CStateManager&, EStateMsg msg, float) -{ - switch (msg) - { - case EStateMsg::Activate: - x5e8_stateProgress = 0; - break; - case EStateMsg::Update: - switch (x5e8_stateProgress) - { - case 0: - if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) - x5e8_stateProgress = 1; - else - x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero)); - break; - case 1: - if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Generate) - x5e8_stateProgress = 2; - break; - default: - break; - } - break; - default: - break; - } -} - -void CParasite::Deactivate(CStateManager& mgr, EStateMsg msg, float) -{ - switch (msg) - { - case EStateMsg::Activate: - x5e8_stateProgress = 0; - SendScriptMsgs(EScriptObjectState::DeactivateState, mgr, EScriptObjectMessage::None); - mgr.FreeScriptObject(GetUniqueId()); - break; - case EStateMsg::Update: - if (x5e8_stateProgress == 0) - { - if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) - x5e8_stateProgress = 1; - else - x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::One)); - } - break; - default: - break; - } -} - -void CParasite::Attack(CStateManager& mgr, EStateMsg msg, float) -{ - switch (msg) - { - case EStateMsg::Activate: + x614_lastStuckPos = GetTranslation(); + if (x608_telegraphRemTime > 0.f) + x608_telegraphRemTime -= dt; + else x608_telegraphRemTime = 0.f; - if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) - { - float rz = mgr.GetActiveRandom()->Float(); - float ry = mgr.GetActiveRandom()->Float(); - float rx = mgr.GetActiveRandom()->Float(); - x5f8_targetPos = (zeus::CVector3f(rx, ry, rz) - 0.5f) * 0.5f + mgr.GetPlayer().GetTranslation(); - } - else - { - float rz = mgr.GetActiveRandom()->Float(); - float ry = mgr.GetActiveRandom()->Float(); - float rx = mgr.GetActiveRandom()->Float(); - x5f8_targetPos = (zeus::CVector3f(rx, ry, rz) + mgr.GetPlayer().GetTranslation() - GetTranslation()) - .normalized() * 15.f + GetTranslation(); - } - FaceTarget(x5f8_targetPos); - x5e8_stateProgress = 0; - x742_30_attackOver = false; - x742_24_receivedTelegraph = false; - x742_28_onGround = false; - break; - case EStateMsg::Update: - switch (x5e8_stateProgress) - { - case 0: - if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Jump) - { - x5e8_stateProgress = 1; - } - else - { - x742_25_jumpVelDirty = true; - FaceTarget(x5f8_targetPos); - x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_targetPos, pas::EJumpType::Normal)); - } - break; - default: - break; - } - break; - case EStateMsg::Deactivate: - x742_28_onGround = true; - x742_30_attackOver = true; - break; - default: - break; } -} + } -void CParasite::Crouch(CStateManager&, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); - if (x5d0_walkerType == EWalkerType::Geemer) - CSfxManager::AddEmitter(x740_crouchSfx, GetTranslation(), zeus::CVector3f::skZero, - true, false, 0x7f, kInvalidAreaId); - } -} - -void CParasite::GetUp(CStateManager&, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); - if (x5d0_walkerType == EWalkerType::Geemer) - CSfxManager::AddEmitter(x73e_getUpSfx, GetTranslation(), zeus::CVector3f::skZero, - true, false, 0x7f, kInvalidAreaId); - } -} - -void CParasite::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float) -{ - switch (msg) - { - case EStateMsg::Activate: - for (auto it = mgr.GetActiveParasites().begin(); it != mgr.GetActiveParasites().end();) - { - CParasite* other = CPatterned::CastTo(mgr.ObjectById(*it)); - if (!other) - { - it = mgr.GetActiveParasites().erase(it); - continue; - } - if (other != this && other->IsAlive() && - (other->GetTranslation() - GetTranslation()).magSquared() < - x6d0_maxTelegraphReactDist * x6d0_maxTelegraphReactDist) - { - other->x742_24_receivedTelegraph = true; - other->x608_telegraphRemTime = mgr.GetActiveRandom()->Float() * 0.5f + 0.5f; - other->x5f8_targetPos = GetTranslation(); - } - ++it; - } - x400_24_hitByPlayerProjectile = false; - break; - default: - break; - } -} - -void CParasite::Jump(CStateManager& mgr, EStateMsg msg, float) -{ - switch (msg) - { - case EStateMsg::Activate: - AddMaterial(EMaterialTypes::GroundCollider, mgr); - SetMomentumWR({0.f, 0.f, -GetWeight()}); - x742_28_onGround = false; - x5d6_24_alignToFloor = false; - x742_27_landed = false; - x743_27_inJump = true; - break; - case EStateMsg::Update: - SetMomentumWR({0.f, 0.f, -GetWeight()}); - break; - case EStateMsg::Deactivate: - RemoveMaterial(EMaterialTypes::GroundCollider, mgr); - SetMomentumWR(zeus::CVector3f::skZero); - x742_28_onGround = true; - x742_27_landed = false; - x743_27_inJump = false; - break; - } -} - -void CParasite::FaceTarget(const zeus::CVector3f& target) -{ - zeus::CQuaternion q = - zeus::CQuaternion::lookAt(zeus::CTransform::Identity().basis[1], - target - GetTranslation(), zeus::degToRad(360.f)); - SetTransform(q.toTransform(GetTranslation())); -} - -void CParasite::Retreat(CStateManager& mgr, EStateMsg msg, float) -{ - switch (msg) - { - case EStateMsg::Activate: - { - zeus::CVector3f dir = mgr.GetPlayer().GetTranslation() - GetTranslation(); - dir.z() = 0.f; - if (dir.canBeNormalized()) - dir.normalize(); - else - dir = mgr.GetPlayer().GetTransform().basis[1]; - x5f8_targetPos = GetTranslation() - dir * 3.f; - FaceTarget(x5f8_targetPos); - x5e8_stateProgress = 0; - x742_27_landed = false; - x742_28_onGround = false; - x742_25_jumpVelDirty = true; - x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_targetPos, pas::EJumpType::One)); - break; - } - case EStateMsg::Update: - x3b4_speed = 1.f; - break; - case EStateMsg::Deactivate: - x742_28_onGround = true; - break; - } -} - -bool CParasite::AnimOver(CStateManager&, float) -{ - return x5e8_stateProgress == 2; -} - -bool CParasite::ShouldAttack(CStateManager& mgr, float arg) -{ - bool shouldAttack = false; - if (x742_24_receivedTelegraph && x608_telegraphRemTime > 0.1f) - shouldAttack = true; - if (!TooClose(mgr, arg) && InMaxRange(mgr, arg)) - return shouldAttack || InDetectionRange(mgr, 0.f); - return false; -} - -bool CParasite::CloseToWall(CStateManager& mgr) -{ - static CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Solid); - zeus::CAABox aabb = CPhysicsActor::GetBoundingBox(); - float margin = x590_colSphere.GetSphere().radius + x5b0_collisionCloseMargin; - aabb.min -= zeus::CVector3f(margin); - aabb.max += zeus::CVector3f(margin); - CCollidableAABox cAABB(aabb, x68_material); - return CGameCollision::DetectStaticCollisionBoolean(mgr, cAABB, {}, filter); -} - -bool CParasite::HitSomething(CStateManager& mgr, float) -{ - if (x5d4_thinkCounter & 0x1) - return true; - return x5b8_tumbleAngle < 270.f && CloseToWall(mgr); -} - -bool CParasite::Stuck(CStateManager&, float) -{ - return x60c_stuckTime > x6e0_stuckTimeThreshold; -} - -bool CParasite::Landed(CStateManager&, float) -{ - return x742_27_landed; -} - -bool CParasite::AttackOver(CStateManager&, float) -{ - return x742_30_attackOver; -} - -bool CParasite::ShotAt(CStateManager&, float) -{ - if (x5d0_walkerType != EWalkerType::Oculus) - return x400_24_hitByPlayerProjectile; - return x743_26_oculusShotAt; -} - -void CParasite::MassiveDeath(CStateManager& mgr) -{ - CPatterned::MassiveDeath(mgr); -} - -void CParasite::MassiveFrozenDeath(CStateManager& mgr) -{ - CPatterned::MassiveFrozenDeath(mgr); -} - -void CParasite::ThinkAboutMove(float dt) -{ - if (!x68_material.HasMaterial(EMaterialTypes::GroundCollider)) - CPatterned::ThinkAboutMove(dt); -} - -bool CParasite::IsOnGround() const -{ - return x742_28_onGround; -} - -void CParasite::UpdateWalkerAnimation(CStateManager& mgr, float dt) -{ - CActor::UpdateAnimation(dt, mgr, true); -} - -void CParasite::DestroyActorManager(CStateManager& mgr) -{ - x620_collisionActorManager->Destroy(mgr); -} - -void CParasite::UpdateJumpVelocity() -{ - SetMomentumWR({0.f, 0.f, -GetWeight()}); - zeus::CVector3f vec; - - if (!x742_30_attackOver) - { - vec = skAttackVelocity * GetTransform().frontVector(); - vec.z() = 0.5f * skRetreatVelocity; - } + if (x400_25_alive) { + CPlayer* pl = mgr.Player(); + float radius; + if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && !x742_30_attackOver) + radius = x590_colSphere.GetSphere().radius; else - { - vec = skRetreatVelocity * GetTransform().frontVector(); - vec.z() = 0.5f * skAttackVelocity; + radius = x708_unmorphedRadius; + + zeus::CAABox aabox{GetTranslation() - radius, GetTranslation() + radius}; + auto plBox = pl->GetTouchBounds(); + + if (plBox && plBox->intersects(aabox)) { + if (!x742_30_attackOver) { + x742_30_attackOver = true; + x742_27_landed = false; + } + + if (x420_curDamageRemTime <= 0.f) { + mgr.ApplyDamage(GetUniqueId(), pl->GetUniqueId(), GetUniqueId(), GetContactDamage(), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + x420_curDamageRemTime = x424_damageWaitTime; + } } + } - float f30 = x150_momentum.z() / xe8_mass; - float f31 = x5f8_targetPos.z() - GetTranslation().z(); - zeus::CVector3f vec2 = x5f8_targetPos - GetTranslation(); - vec2.z() = 0.f; - float f29 = vec2.magnitude(); + CWallWalker::Think(dt, mgr); - if (f29 > FLT_EPSILON) - { - vec2 *= zeus::CVector3f{1.f / f29}; - float f28 = vec2.dot(vec); - if (f28 > FLT_EPSILON) - { - float f27 = 0.f; - bool isNeg = f31 < 0.f; - float xPos, xNeg; - if (CSteeringBehaviors::SolveQuadratic(f30, vec.z(), -f31, xPos, xNeg)) - f27 = isNeg ? xPos : xNeg; + if (x5d6_27_disableMove) + return; - if (!isNeg) - f27 = f27 * f29 / f28; + if (x450_bodyController->IsFrozen()) + return; - if (f27 < 10.f) - { - vec = f29 / f27 * vec2; - vec.z() = (0.5f * f30 * f27 + f31 / f27); - } + x3b4_speed = x604_activeSpeed; + if (x5d6_24_alignToFloor) + AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + 2.f * dt * x138_velocity, dt); + + x742_27_landed = false; +} + +void CParasite::Render(const CStateManager& mgr) const { CWallWalker::Render(mgr); } + +const CDamageVulnerability* CParasite::GetDamageVulnerability() const { + switch (x5d0_walkerType) { + case EWalkerType::Oculus: + if (x743_24_halted) + return &x64c_oculusHaltDVuln; + break; + case EWalkerType::IceZoomer: + if (!x743_25_vulnerable) + return &CDamageVulnerability::ImmuneVulnerabilty(); + break; + default: + break; + } + return CAi::GetDamageVulnerability(); +} + +CDamageInfo CParasite::GetContactDamage() const { + if (x5d0_walkerType == EWalkerType::Oculus && x743_24_halted) + return x6b4_oculusHaltDInfo; + return CPatterned::GetContactDamage(); +} + +void CParasite::Touch(CActor& actor, CStateManager& mgr) { CPatterned::Touch(actor, mgr); } + +zeus::CVector3f CParasite::GetAimPosition(const CStateManager&, float) const { return GetTranslation(); } + +void CParasite::CollidedWith(TUniqueId uid, const CCollisionInfoList& list, CStateManager&) { + static CMaterialList testList(EMaterialTypes::Character, EMaterialTypes::Player); + if (x743_27_inJump) { + for (const auto& info : list) { + if (!x5d6_24_alignToFloor && info.GetMaterialLeft().Intersection(testList) == 0) { + OrientToSurfaceNormal(info.GetNormalLeft(), 360.f); + CPhysicsActor::Stop(); + SetVelocityWR(zeus::CVector3f::skZero); + x742_27_landed = true; + x742_28_onGround = true; + } + } + } +} + +void CParasite::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) { + CPhysicsActor::Stop(); + TelegraphAttack(mgr, EStateMsg::Activate, 0.f); + SetMomentumWR({0.f, 0.f, -GetWeight()}); + CPatterned::Death(mgr, direction, state); +} + +void CParasite::Patrol(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x742_26_ = true; + x5d6_24_alignToFloor = true; + if (!x5d6_27_disableMove && x5d0_walkerType == EWalkerType::Parasite) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + SetMomentumWR(zeus::CVector3f::skZero); + x5d6_25_hasAlignSurface = false; + xf8_24_movable = false; + break; + case EStateMsg::Update: + if (x5bc_patrolPauseRemTime > 0.f) { + x5bc_patrolPauseRemTime -= dt; + if (x5bc_patrolPauseRemTime <= 0.f) { + if (x5d0_walkerType == EWalkerType::Parasite) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + x5bc_patrolPauseRemTime = 0.f; + } + } + GotoNextWaypoint(mgr); + if (x5bc_patrolPauseRemTime <= 0.f && !x5d6_27_disableMove) + DoFlockingBehavior(mgr); + break; + case EStateMsg::Deactivate: + x5d6_24_alignToFloor = false; + xf8_24_movable = true; + break; + default: + break; + } +} + +void CParasite::UpdatePFDestination(CStateManager& mgr) { + // Empty +} + +void CParasite::DoFlockingBehavior(CStateManager& mgr) { + zeus::CVector3f upVec = x34_transform.basis[2]; + rstl::reserved_vector parasiteList; + zeus::CAABox aabb(GetTranslation() - x6e4_parasiteSearchRadius, GetTranslation() + x6e4_parasiteSearchRadius); + if ((x5d4_thinkCounter % 6) == 0) { + rstl::reserved_vector nearList; + static CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Character); + CParasite* closestParasite = nullptr; + float minDistSq = 2.f + x6e8_parasiteSeparationDist * x6e8_parasiteSeparationDist; + mgr.BuildNearList(nearList, aabb, filter, nullptr); + for (TUniqueId id : nearList) { + if (CParasite* parasite = CPatterned::CastTo(mgr.ObjectById(id))) { + if (parasite != this && parasite->IsAlive()) { + parasiteList.push_back(parasite->GetUniqueId()); + float distSq = (parasite->GetTranslation() - GetTranslation()).magSquared(); + if (distSq < minDistSq) { + minDistSq = distSq; + closestParasite = parasite; + } } + } } - SetVelocityWR(vec); + if (closestParasite && x6ec_parasiteSeparationWeight > 0.f && x6e8_parasiteSeparationDist > 0.f) + x628_parasiteSeparationMove = + x45c_steeringBehaviors.Separation(*this, closestParasite->GetTranslation(), x6e8_parasiteSeparationDist) * + x604_activeSpeed; + else + x628_parasiteSeparationMove = zeus::CVector3f::skZero; + x634_parasiteCohesionMove = x45c_steeringBehaviors.Cohesion(*this, parasiteList, 0.6f, mgr) * x604_activeSpeed; + x640_parasiteAlignmentMove = x45c_steeringBehaviors.Alignment(*this, parasiteList, mgr) * x604_activeSpeed; + } + + if ((mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < + x700_playerSeparationDist * x700_playerSeparationDist) { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd(ProjectVectorToPlane(x45c_steeringBehaviors.Separation(*this, mgr.GetPlayer().GetTranslation(), + x700_playerSeparationDist), + upVec) * + x604_activeSpeed, + zeus::CVector3f::skZero, x704_playerSeparationWeight)); + } + + if (x628_parasiteSeparationMove != zeus::CVector3f::skZero) { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd(ProjectVectorToPlane(x628_parasiteSeparationMove, upVec), zeus::CVector3f::skZero, + x6ec_parasiteSeparationWeight)); + } + + for (const auto& r : x5d8_doorRepulsors) { + if ((r.GetVector() - GetTranslation()).magSquared() < r.GetFloat() * r.GetFloat()) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( + ProjectVectorToPlane(x45c_steeringBehaviors.Separation(*this, r.GetVector(), r.GetFloat()) * x604_activeSpeed, + upVec), + zeus::CVector3f::skZero, 1.f)); + } + } + + if (x608_telegraphRemTime <= 0.f) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( + ProjectVectorToPlane(x634_parasiteCohesionMove, upVec), zeus::CVector3f::skZero, x6f4_parasiteCohesionWeight)); + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd(ProjectVectorToPlane(x640_parasiteAlignmentMove, upVec), zeus::CVector3f::skZero, + x6f0_parasiteAlignmentWeight)); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( + ProjectVectorToPlane( + ProjectVectorToPlane(x45c_steeringBehaviors.Seek(*this, x2e0_destPos), upVec) * x604_activeSpeed, upVec), + zeus::CVector3f::skZero, x6f8_destinationSeekWeight)); + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd(x34_transform.basis[1] * x604_activeSpeed, zeus::CVector3f::skZero, x6fc_forwardMoveWeight)); + } +} + +void CParasite::PathFind(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x742_26_ = true; + x5d6_24_alignToFloor = true; + if (x5d0_walkerType == EWalkerType::Parasite) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + SetMomentumWR(zeus::CVector3f::skZero); + xf8_24_movable = false; + break; + case EStateMsg::Update: + UpdatePFDestination(mgr); + DoFlockingBehavior(mgr); + break; + case EStateMsg::Deactivate: + xf8_24_movable = true; + x5d6_24_alignToFloor = false; + x742_26_ = false; + break; + default: + break; + } +} + +void CParasite::TargetPlayer(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x5f8_targetPos = mgr.GetPlayer().GetTranslation() + zeus::CVector3f(0.f, 0.f, 1.5f); + break; + case EStateMsg::Update: + x450_bodyController->FaceDirection3D( + ProjectVectorToPlane(x5f8_targetPos - GetTranslation(), x34_transform.basis[2]), x34_transform.basis[1], 2.f); + break; + default: + break; + } +} + +TUniqueId CParasite::RecursiveFindClosestWayPoint(CStateManager& mgr, TUniqueId id, float& dist) { + TUniqueId ret = id; + TCastToPtr wp = mgr.ObjectById(id); + if (!wp) + return ret; + wp->SetActive(false); + dist = (wp->GetTranslation() - GetTranslation()).magSquared(); + for (const auto& conn : wp->GetConnectionList()) { + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) { + TUniqueId nextId = mgr.GetIdForScript(conn.x8_objId); + if (nextId != kInvalidUniqueId) { + if (TCastToConstPtr wp2 = mgr.GetObjectById(nextId)) { + if (wp2->GetActive()) { + float nextDist; + TUniqueId closestWp = RecursiveFindClosestWayPoint(mgr, nextId, nextDist); + if (nextDist < dist) { + dist = nextDist; + ret = closestWp; + } + } + } + } + } + } + wp->SetActive(true); + return ret; +} + +TUniqueId CParasite::GetClosestWaypointForState(EScriptObjectState state, CStateManager& mgr) { + float minDist = FLT_MAX; + TUniqueId ret = kInvalidUniqueId; + for (const auto& conn : GetConnectionList()) { + if (conn.x0_state == state && conn.x4_msg == EScriptObjectMessage::Follow) { + TUniqueId id = mgr.GetIdForScript(conn.x8_objId); + float dist; + TUniqueId closestWp = RecursiveFindClosestWayPoint(mgr, id, dist); + if (dist < minDist) { + minDist = dist; + ret = closestWp; + } + } + } + return ret; +} + +void CParasite::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + SetMomentumWR(zeus::CVector3f::skZero); + TUniqueId wpId = GetClosestWaypointForState(EScriptObjectState::Patrol, mgr); + if (wpId != kInvalidUniqueId) + x2dc_destObj = wpId; + } +} + +void CParasite::Halt(CStateManager& mgr, EStateMsg msg, float) { + switch (msg) { + case EStateMsg::Activate: + x330_stateMachineState.SetDelay(x710_haltDelay); + x32c_animState = EAnimState::One; + x743_24_halted = true; + x5d6_24_alignToFloor = true; + if (x5d0_walkerType == EWalkerType::Geemer) + CSfxManager::AddEmitter(x73c_haltSfx, GetTranslation(), zeus::CVector3f::skZero, true, false, 0x7f, + kInvalidAreaId); + break; + case EStateMsg::Update: + TryCommand(mgr, pas::EAnimationState::LoopReaction, &CPatterned::TryLoopReaction, 1); + x400_24_hitByPlayerProjectile = false; + break; + case EStateMsg::Deactivate: + x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); + x32c_animState = EAnimState::Zero; + x743_24_halted = false; + x5d6_24_alignToFloor = false; + break; + default: + break; + } +} + +void CParasite::Run(CStateManager&, EStateMsg, float) { + // Empty +} + +void CParasite::Generate(CStateManager&, EStateMsg msg, float) { + switch (msg) { + case EStateMsg::Activate: + x5e8_stateProgress = 0; + break; + case EStateMsg::Update: + switch (x5e8_stateProgress) { + case 0: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) + x5e8_stateProgress = 1; + else + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero)); + break; + case 1: + if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Generate) + x5e8_stateProgress = 2; + break; + default: + break; + } + break; + default: + break; + } +} + +void CParasite::Deactivate(CStateManager& mgr, EStateMsg msg, float) { + switch (msg) { + case EStateMsg::Activate: + x5e8_stateProgress = 0; + SendScriptMsgs(EScriptObjectState::DeactivateState, mgr, EScriptObjectMessage::None); + mgr.FreeScriptObject(GetUniqueId()); + break; + case EStateMsg::Update: + if (x5e8_stateProgress == 0) { + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) + x5e8_stateProgress = 1; + else + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::One)); + } + break; + default: + break; + } +} + +void CParasite::Attack(CStateManager& mgr, EStateMsg msg, float) { + switch (msg) { + case EStateMsg::Activate: + x608_telegraphRemTime = 0.f; + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { + float rz = mgr.GetActiveRandom()->Float(); + float ry = mgr.GetActiveRandom()->Float(); + float rx = mgr.GetActiveRandom()->Float(); + x5f8_targetPos = (zeus::CVector3f(rx, ry, rz) - 0.5f) * 0.5f + mgr.GetPlayer().GetTranslation(); + } else { + float rz = mgr.GetActiveRandom()->Float(); + float ry = mgr.GetActiveRandom()->Float(); + float rx = mgr.GetActiveRandom()->Float(); + x5f8_targetPos = + (zeus::CVector3f(rx, ry, rz) + mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized() * 15.f + + GetTranslation(); + } + FaceTarget(x5f8_targetPos); + x5e8_stateProgress = 0; + x742_30_attackOver = false; + x742_24_receivedTelegraph = false; + x742_28_onGround = false; + break; + case EStateMsg::Update: + switch (x5e8_stateProgress) { + case 0: + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Jump) { + x5e8_stateProgress = 1; + } else { + x742_25_jumpVelDirty = true; + FaceTarget(x5f8_targetPos); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_targetPos, pas::EJumpType::Normal)); + } + break; + default: + break; + } + break; + case EStateMsg::Deactivate: + x742_28_onGround = true; + x742_30_attackOver = true; + break; + default: + break; + } +} + +void CParasite::Crouch(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); + if (x5d0_walkerType == EWalkerType::Geemer) + CSfxManager::AddEmitter(x740_crouchSfx, GetTranslation(), zeus::CVector3f::skZero, true, false, 0x7f, + kInvalidAreaId); + } +} + +void CParasite::GetUp(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + if (x5d0_walkerType == EWalkerType::Geemer) + CSfxManager::AddEmitter(x73e_getUpSfx, GetTranslation(), zeus::CVector3f::skZero, true, false, 0x7f, + kInvalidAreaId); + } +} + +void CParasite::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float) { + switch (msg) { + case EStateMsg::Activate: + for (auto it = mgr.GetActiveParasites().begin(); it != mgr.GetActiveParasites().end();) { + CParasite* other = CPatterned::CastTo(mgr.ObjectById(*it)); + if (!other) { + it = mgr.GetActiveParasites().erase(it); + continue; + } + if (other != this && other->IsAlive() && + (other->GetTranslation() - GetTranslation()).magSquared() < + x6d0_maxTelegraphReactDist * x6d0_maxTelegraphReactDist) { + other->x742_24_receivedTelegraph = true; + other->x608_telegraphRemTime = mgr.GetActiveRandom()->Float() * 0.5f + 0.5f; + other->x5f8_targetPos = GetTranslation(); + } + ++it; + } + x400_24_hitByPlayerProjectile = false; + break; + default: + break; + } +} + +void CParasite::Jump(CStateManager& mgr, EStateMsg msg, float) { + switch (msg) { + case EStateMsg::Activate: + AddMaterial(EMaterialTypes::GroundCollider, mgr); + SetMomentumWR({0.f, 0.f, -GetWeight()}); + x742_28_onGround = false; + x5d6_24_alignToFloor = false; + x742_27_landed = false; + x743_27_inJump = true; + break; + case EStateMsg::Update: + SetMomentumWR({0.f, 0.f, -GetWeight()}); + break; + case EStateMsg::Deactivate: + RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + SetMomentumWR(zeus::CVector3f::skZero); + x742_28_onGround = true; + x742_27_landed = false; + x743_27_inJump = false; + break; + } +} + +void CParasite::FaceTarget(const zeus::CVector3f& target) { + zeus::CQuaternion q = zeus::CQuaternion::lookAt(zeus::CTransform::Identity().basis[1], target - GetTranslation(), + zeus::degToRad(360.f)); + SetTransform(q.toTransform(GetTranslation())); +} + +void CParasite::Retreat(CStateManager& mgr, EStateMsg msg, float) { + switch (msg) { + case EStateMsg::Activate: { + zeus::CVector3f dir = mgr.GetPlayer().GetTranslation() - GetTranslation(); + dir.z() = 0.f; + if (dir.canBeNormalized()) + dir.normalize(); + else + dir = mgr.GetPlayer().GetTransform().basis[1]; + x5f8_targetPos = GetTranslation() - dir * 3.f; + FaceTarget(x5f8_targetPos); + x5e8_stateProgress = 0; + x742_27_landed = false; + x742_28_onGround = false; + x742_25_jumpVelDirty = true; + x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_targetPos, pas::EJumpType::One)); + break; + } + case EStateMsg::Update: + x3b4_speed = 1.f; + break; + case EStateMsg::Deactivate: + x742_28_onGround = true; + break; + } +} + +bool CParasite::AnimOver(CStateManager&, float) { return x5e8_stateProgress == 2; } + +bool CParasite::ShouldAttack(CStateManager& mgr, float arg) { + bool shouldAttack = false; + if (x742_24_receivedTelegraph && x608_telegraphRemTime > 0.1f) + shouldAttack = true; + if (!TooClose(mgr, arg) && InMaxRange(mgr, arg)) + return shouldAttack || InDetectionRange(mgr, 0.f); + return false; +} + +bool CParasite::CloseToWall(CStateManager& mgr) { + static CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Solid); + zeus::CAABox aabb = CPhysicsActor::GetBoundingBox(); + float margin = x590_colSphere.GetSphere().radius + x5b0_collisionCloseMargin; + aabb.min -= zeus::CVector3f(margin); + aabb.max += zeus::CVector3f(margin); + CCollidableAABox cAABB(aabb, x68_material); + return CGameCollision::DetectStaticCollisionBoolean(mgr, cAABB, {}, filter); +} + +bool CParasite::HitSomething(CStateManager& mgr, float) { + if (x5d4_thinkCounter & 0x1) + return true; + return x5b8_tumbleAngle < 270.f && CloseToWall(mgr); +} + +bool CParasite::Stuck(CStateManager&, float) { return x60c_stuckTime > x6e0_stuckTimeThreshold; } + +bool CParasite::Landed(CStateManager&, float) { return x742_27_landed; } + +bool CParasite::AttackOver(CStateManager&, float) { return x742_30_attackOver; } + +bool CParasite::ShotAt(CStateManager&, float) { + if (x5d0_walkerType != EWalkerType::Oculus) + return x400_24_hitByPlayerProjectile; + return x743_26_oculusShotAt; +} + +void CParasite::MassiveDeath(CStateManager& mgr) { CPatterned::MassiveDeath(mgr); } + +void CParasite::MassiveFrozenDeath(CStateManager& mgr) { CPatterned::MassiveFrozenDeath(mgr); } + +void CParasite::ThinkAboutMove(float dt) { + if (!x68_material.HasMaterial(EMaterialTypes::GroundCollider)) + CPatterned::ThinkAboutMove(dt); +} + +bool CParasite::IsOnGround() const { return x742_28_onGround; } + +void CParasite::UpdateWalkerAnimation(CStateManager& mgr, float dt) { CActor::UpdateAnimation(dt, mgr, true); } + +void CParasite::DestroyActorManager(CStateManager& mgr) { x620_collisionActorManager->Destroy(mgr); } + +void CParasite::UpdateJumpVelocity() { + SetMomentumWR({0.f, 0.f, -GetWeight()}); + zeus::CVector3f vec; + + if (!x742_30_attackOver) { + vec = skAttackVelocity * GetTransform().frontVector(); + vec.z() = 0.5f * skRetreatVelocity; + } else { + vec = skRetreatVelocity * GetTransform().frontVector(); + vec.z() = 0.5f * skAttackVelocity; + } + + float f30 = x150_momentum.z() / xe8_mass; + float f31 = x5f8_targetPos.z() - GetTranslation().z(); + zeus::CVector3f vec2 = x5f8_targetPos - GetTranslation(); + vec2.z() = 0.f; + float f29 = vec2.magnitude(); + + if (f29 > FLT_EPSILON) { + vec2 *= zeus::CVector3f{1.f / f29}; + float f28 = vec2.dot(vec); + if (f28 > FLT_EPSILON) { + float f27 = 0.f; + bool isNeg = f31 < 0.f; + float xPos, xNeg; + if (CSteeringBehaviors::SolveQuadratic(f30, vec.z(), -f31, xPos, xNeg)) + f27 = isNeg ? xPos : xNeg; + + if (!isNeg) + f27 = f27 * f29 / f28; + + if (f27 < 10.f) { + vec = f29 / f27 * vec2; + vec.z() = (0.5f * f30 * f27 + f31 / f27); + } + } + } + SetVelocityWR(vec); } } // namespace urde::MP1 diff --git a/Runtime/MP1/World/CParasite.hpp b/Runtime/MP1/World/CParasite.hpp index 584f64104..0a9ddb5da 100644 --- a/Runtime/MP1/World/CParasite.hpp +++ b/Runtime/MP1/World/CParasite.hpp @@ -2,154 +2,148 @@ #include "World/CWallWalker.hpp" #include "Collision/CCollisionActorManager.hpp" -namespace urde -{ +namespace urde { class CModelData; } -namespace urde::MP1 -{ -class CParasite : public CWallWalker -{ - class CRepulsor - { - zeus::CVector3f x0_v; - float xc_f; - public: - CRepulsor(const zeus::CVector3f& v, float f) : x0_v(v), xc_f(f) {} - const zeus::CVector3f& GetVector() const { return x0_v; } - float GetFloat() const { return xc_f; } - }; - static const float flt_805A8FB0; - static const float skAttackVelocity; - static short word_805A8FC0; - static const float flt_805A8FB8; - static const float skRetreatVelocity; - std::vector x5d8_doorRepulsors; - s32 x5e8_stateProgress = -1; - zeus::CVector3f x5ec_; - zeus::CVector3f x5f8_targetPos; - float x604_activeSpeed = 1.f; - float x608_telegraphRemTime = 0.f; - float x60c_stuckTime = 0.f; - zeus::CVector3f x614_lastStuckPos; - std::unique_ptr x620_collisionActorManager; - TLockedToken x624_extraModel; - zeus::CVector3f x628_parasiteSeparationMove; - zeus::CVector3f x634_parasiteCohesionMove; - zeus::CVector3f x640_parasiteAlignmentMove; - CDamageVulnerability x64c_oculusHaltDVuln; - CDamageInfo x6b4_oculusHaltDInfo; - float x6d0_maxTelegraphReactDist; - float x6d4_; - float x6dc_; - float x6e0_stuckTimeThreshold; - float x6e4_parasiteSearchRadius; - float x6e8_parasiteSeparationDist; - float x6ec_parasiteSeparationWeight; - float x6f0_parasiteAlignmentWeight; - float x6f4_parasiteCohesionWeight; - float x6f8_destinationSeekWeight; - float x6fc_forwardMoveWeight; - float x700_playerSeparationDist; - float x704_playerSeparationWeight; - float x708_unmorphedRadius; - float x710_haltDelay; - float x714_iceZoomerJointHP; - float x718_ = 0.f; - float x71c_ = 0.f; - float x720_ = 0.f; - float x724_ = 0.f; - float x728_ = 0.f; - float x72c_ = 0.f; - float x730_ = 0.f; - float x734_ = 0.f; - float x738_ = 0.f; - u16 x73c_haltSfx; - u16 x73e_getUpSfx; - u16 x740_crouchSfx; - union - { - struct - { - bool x742_24_receivedTelegraph : 1; - bool x742_25_jumpVelDirty : 1; - bool x742_26_ : 1; - bool x742_27_landed : 1; - bool x742_28_onGround : 1; - bool x742_29_ : 1; - bool x742_30_attackOver : 1; - bool x742_31_ : 1; - bool x743_24_halted : 1; - bool x743_25_vulnerable : 1; - bool x743_26_oculusShotAt : 1; - bool x743_27_inJump : 1; - }; - u16 _dummy = 0; - }; - bool CloseToWall(CStateManager& mgr); - void FaceTarget(const zeus::CVector3f& target); - TUniqueId RecursiveFindClosestWayPoint(CStateManager& mgr, TUniqueId id, float& dist); - TUniqueId GetClosestWaypointForState(EScriptObjectState state, CStateManager& mgr); - void UpdatePFDestination(CStateManager& mgr); - void DoFlockingBehavior(CStateManager& mgr); - void SetupIceZoomerCollision(CStateManager& mgr); - void SetupIceZoomerVulnerability(CStateManager& mgr, const CDamageVulnerability& dVuln, - const CHealthInfo& hInfo); - void AddDoorRepulsors(CStateManager& mgr); - void UpdateCollisionActors(float dt, CStateManager& mgr); - void DestroyActorManager(CStateManager& mgr); - void UpdateJumpVelocity(); -public: - DEFINE_PATTERNED(Parasite) - CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo &info, - const zeus::CTransform &xf, CModelData &&mData, const CPatternedInfo &pInfo, EBodyType bodyType, - float maxTelegraphReactDist, float advanceWpRadius, float f3, float alignAngVel, float f5, - float stuckTimeThreshold, float collisionCloseMargin, float parasiteSearchRadius, - float parasiteSeparationDist, float parasiteSeparationWeight, float parasiteAlignmentWeight, - float parasiteCohesionWeight, float destinationSeekWeight, float forwardMoveWeight, - float playerSeparationDist, float playerSeparationWeight, float playerObstructionMinDist, - float haltDelay, bool disableMove, EWalkerType wType, const CDamageVulnerability& dVuln, - const CDamageInfo& parInfo, u16 haltSfx, u16 getUpSfx, u16 crouchSfx, CAssetId modelRes, - CAssetId skinRes, float iceZoomerJointHP, - const CActorParameters& aParams); +namespace urde::MP1 { +class CParasite : public CWallWalker { + class CRepulsor { + zeus::CVector3f x0_v; + float xc_f; - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void PreThink(float, CStateManager&); - void Think(float dt, CStateManager& mgr); - void Render(const CStateManager&) const; - const CDamageVulnerability* GetDamageVulnerability() const; - CDamageInfo GetContactDamage() const; - void Touch(CActor& actor, CStateManager&); - zeus::CVector3f GetAimPosition(const CStateManager&, float) const; - void CollidedWith(TUniqueId uid, const CCollisionInfoList&, CStateManager&); - void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); - void Patrol(CStateManager&, EStateMsg msg, float dt); - void PathFind(CStateManager&, EStateMsg msg, float dt); - void TargetPlayer(CStateManager&, EStateMsg msg, float dt); - void TargetPatrol(CStateManager&, EStateMsg msg, float dt); - void Halt(CStateManager&, EStateMsg, float); - void Run(CStateManager&, EStateMsg, float); - void Generate(CStateManager&, EStateMsg, float); - void Deactivate(CStateManager&, EStateMsg, float); - void Attack(CStateManager&, EStateMsg, float); - void Crouch(CStateManager&, EStateMsg, float); - void GetUp(CStateManager&, EStateMsg, float); - void TelegraphAttack(CStateManager&, EStateMsg, float); - void Jump(CStateManager&, EStateMsg, float); - void Retreat(CStateManager&, EStateMsg, float); - bool AnimOver(CStateManager&, float); - bool ShouldAttack(CStateManager&, float); - bool HitSomething(CStateManager&, float); - bool Stuck(CStateManager&, float); - bool Landed(CStateManager&, float); - bool AttackOver(CStateManager&, float); - bool ShotAt(CStateManager&, float); - void MassiveDeath(CStateManager&); - void MassiveFrozenDeath(CStateManager&); - void ThinkAboutMove(float); - bool IsOnGround() const; - virtual void UpdateWalkerAnimation(CStateManager&, float); + public: + CRepulsor(const zeus::CVector3f& v, float f) : x0_v(v), xc_f(f) {} + const zeus::CVector3f& GetVector() const { return x0_v; } + float GetFloat() const { return xc_f; } + }; + static const float flt_805A8FB0; + static const float skAttackVelocity; + static short word_805A8FC0; + static const float flt_805A8FB8; + static const float skRetreatVelocity; + std::vector x5d8_doorRepulsors; + s32 x5e8_stateProgress = -1; + zeus::CVector3f x5ec_; + zeus::CVector3f x5f8_targetPos; + float x604_activeSpeed = 1.f; + float x608_telegraphRemTime = 0.f; + float x60c_stuckTime = 0.f; + zeus::CVector3f x614_lastStuckPos; + std::unique_ptr x620_collisionActorManager; + TLockedToken x624_extraModel; + zeus::CVector3f x628_parasiteSeparationMove; + zeus::CVector3f x634_parasiteCohesionMove; + zeus::CVector3f x640_parasiteAlignmentMove; + CDamageVulnerability x64c_oculusHaltDVuln; + CDamageInfo x6b4_oculusHaltDInfo; + float x6d0_maxTelegraphReactDist; + float x6d4_; + float x6dc_; + float x6e0_stuckTimeThreshold; + float x6e4_parasiteSearchRadius; + float x6e8_parasiteSeparationDist; + float x6ec_parasiteSeparationWeight; + float x6f0_parasiteAlignmentWeight; + float x6f4_parasiteCohesionWeight; + float x6f8_destinationSeekWeight; + float x6fc_forwardMoveWeight; + float x700_playerSeparationDist; + float x704_playerSeparationWeight; + float x708_unmorphedRadius; + float x710_haltDelay; + float x714_iceZoomerJointHP; + float x718_ = 0.f; + float x71c_ = 0.f; + float x720_ = 0.f; + float x724_ = 0.f; + float x728_ = 0.f; + float x72c_ = 0.f; + float x730_ = 0.f; + float x734_ = 0.f; + float x738_ = 0.f; + u16 x73c_haltSfx; + u16 x73e_getUpSfx; + u16 x740_crouchSfx; + union { + struct { + bool x742_24_receivedTelegraph : 1; + bool x742_25_jumpVelDirty : 1; + bool x742_26_ : 1; + bool x742_27_landed : 1; + bool x742_28_onGround : 1; + bool x742_29_ : 1; + bool x742_30_attackOver : 1; + bool x742_31_ : 1; + bool x743_24_halted : 1; + bool x743_25_vulnerable : 1; + bool x743_26_oculusShotAt : 1; + bool x743_27_inJump : 1; + }; + u16 _dummy = 0; + }; + bool CloseToWall(CStateManager& mgr); + void FaceTarget(const zeus::CVector3f& target); + TUniqueId RecursiveFindClosestWayPoint(CStateManager& mgr, TUniqueId id, float& dist); + TUniqueId GetClosestWaypointForState(EScriptObjectState state, CStateManager& mgr); + void UpdatePFDestination(CStateManager& mgr); + void DoFlockingBehavior(CStateManager& mgr); + void SetupIceZoomerCollision(CStateManager& mgr); + void SetupIceZoomerVulnerability(CStateManager& mgr, const CDamageVulnerability& dVuln, const CHealthInfo& hInfo); + void AddDoorRepulsors(CStateManager& mgr); + void UpdateCollisionActors(float dt, CStateManager& mgr); + void DestroyActorManager(CStateManager& mgr); + void UpdateJumpVelocity(); + +public: + DEFINE_PATTERNED(Parasite) + CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EBodyType bodyType, + float maxTelegraphReactDist, float advanceWpRadius, float f3, float alignAngVel, float f5, + float stuckTimeThreshold, float collisionCloseMargin, float parasiteSearchRadius, + float parasiteSeparationDist, float parasiteSeparationWeight, float parasiteAlignmentWeight, + float parasiteCohesionWeight, float destinationSeekWeight, float forwardMoveWeight, + float playerSeparationDist, float playerSeparationWeight, float playerObstructionMinDist, float haltDelay, + bool disableMove, EWalkerType wType, const CDamageVulnerability& dVuln, const CDamageInfo& parInfo, + u16 haltSfx, u16 getUpSfx, u16 crouchSfx, CAssetId modelRes, CAssetId skinRes, float iceZoomerJointHP, + const CActorParameters& aParams); + + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PreThink(float, CStateManager&); + void Think(float dt, CStateManager& mgr); + void Render(const CStateManager&) const; + const CDamageVulnerability* GetDamageVulnerability() const; + CDamageInfo GetContactDamage() const; + void Touch(CActor& actor, CStateManager&); + zeus::CVector3f GetAimPosition(const CStateManager&, float) const; + void CollidedWith(TUniqueId uid, const CCollisionInfoList&, CStateManager&); + void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); + void Patrol(CStateManager&, EStateMsg msg, float dt); + void PathFind(CStateManager&, EStateMsg msg, float dt); + void TargetPlayer(CStateManager&, EStateMsg msg, float dt); + void TargetPatrol(CStateManager&, EStateMsg msg, float dt); + void Halt(CStateManager&, EStateMsg, float); + void Run(CStateManager&, EStateMsg, float); + void Generate(CStateManager&, EStateMsg, float); + void Deactivate(CStateManager&, EStateMsg, float); + void Attack(CStateManager&, EStateMsg, float); + void Crouch(CStateManager&, EStateMsg, float); + void GetUp(CStateManager&, EStateMsg, float); + void TelegraphAttack(CStateManager&, EStateMsg, float); + void Jump(CStateManager&, EStateMsg, float); + void Retreat(CStateManager&, EStateMsg, float); + bool AnimOver(CStateManager&, float); + bool ShouldAttack(CStateManager&, float); + bool HitSomething(CStateManager&, float); + bool Stuck(CStateManager&, float); + bool Landed(CStateManager&, float); + bool AttackOver(CStateManager&, float); + bool ShotAt(CStateManager&, float); + void MassiveDeath(CStateManager&); + void MassiveFrozenDeath(CStateManager&); + void ThinkAboutMove(float); + bool IsOnGround() const; + virtual void UpdateWalkerAnimation(CStateManager&, float); }; -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CPuddleToadGamma.cpp b/Runtime/MP1/World/CPuddleToadGamma.cpp index ec3c4794e..1b8339f88 100644 --- a/Runtime/MP1/World/CPuddleToadGamma.cpp +++ b/Runtime/MP1/World/CPuddleToadGamma.cpp @@ -6,8 +6,7 @@ #include "Collision/CGameCollision.hpp" #include "TCastTo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { const zeus::CVector3f CPuddleToadGamma::skBellyOffset(0.f, 0.1f, -.3f); @@ -16,348 +15,300 @@ CPuddleToadGamma::CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavor const CActorParameters& aParms, float f1, float f2, float f3, const zeus::CVector3f& v1, float f4, float f5, float f6, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2, CAssetId dcln) - : CPatterned(ECharacter::PuddleToad, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, - EColliderType::Zero, EBodyType::Restricted, aParms, EKnockBackVariant::Large), x570_(dInfo1), - x58c_(dInfo2), x5a8_(f1), x5ac_(std::cos(zeus::degToRad(f2 * 0.5f))), x5b0_(f3), x5b4_(v1), x5c0_(f4), x5c4_(f5), - x5c8_(f6), x5e8_24_(false), x5e8_25_(false), x5e8_26_(false) -{ - x401_26_disableMove = true; - x460_knockBackController.SetEnableBurn(false); - x460_knockBackController.SetEnableLaggedBurnDeath(false); - x460_knockBackController.SetEnableShock(false); - x460_knockBackController.SetX81_31(false); - SetMovable(false); - if (dcln.IsValid() && g_ResFactory->GetResourceTypeById(dcln) != 0) - { - TLockedToken container = g_SimplePool->GetObj({FOURCC('DCLN'), dcln}); - x5e4_collisionTreePrim.reset(new CCollidableOBBTreeGroup(container.GetObj(), GetMaterialList())); - } - +: CPatterned(ECharacter::PuddleToad, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, + EColliderType::Zero, EBodyType::Restricted, aParms, EKnockBackVariant::Large) +, x570_(dInfo1) +, x58c_(dInfo2) +, x5a8_(f1) +, x5ac_(std::cos(zeus::degToRad(f2 * 0.5f))) +, x5b0_(f3) +, x5b4_(v1) +, x5c0_(f4) +, x5c4_(f5) +, x5c8_(f6) +, x5e8_24_(false) +, x5e8_25_(false) +, x5e8_26_(false) { + x401_26_disableMove = true; + x460_knockBackController.SetEnableBurn(false); + x460_knockBackController.SetEnableLaggedBurnDeath(false); + x460_knockBackController.SetEnableShock(false); + x460_knockBackController.SetX81_31(false); + SetMovable(false); + if (dcln.IsValid() && g_ResFactory->GetResourceTypeById(dcln) != 0) { + TLockedToken container = g_SimplePool->GetObj({FOURCC('DCLN'), dcln}); + x5e4_collisionTreePrim.reset(new CCollidableOBBTreeGroup(container.GetObj(), GetMaterialList())); + } } -void CPuddleToadGamma::SetSolid(CStateManager& mgr, bool solid) -{ - if (solid) - { - AddMaterial(EMaterialTypes::Solid, mgr); - RemoveMaterial(EMaterialTypes::NonSolidDamageable, mgr); - } else - { - RemoveMaterial(EMaterialTypes::Solid, mgr); - AddMaterial(EMaterialTypes::NonSolidDamageable, mgr); - } +void CPuddleToadGamma::SetSolid(CStateManager& mgr, bool solid) { + if (solid) { + AddMaterial(EMaterialTypes::Solid, mgr); + RemoveMaterial(EMaterialTypes::NonSolidDamageable, mgr); + } else { + RemoveMaterial(EMaterialTypes::Solid, mgr); + AddMaterial(EMaterialTypes::NonSolidDamageable, mgr); + } } -const CCollisionPrimitive* CPuddleToadGamma::GetCollisionPrimitive() const -{ - if (!x5e4_collisionTreePrim) - return CPhysicsActor::GetCollisionPrimitive(); - return x5e4_collisionTreePrim.get(); +const CCollisionPrimitive* CPuddleToadGamma::GetCollisionPrimitive() const { + if (!x5e4_collisionTreePrim) + return CPhysicsActor::GetCollisionPrimitive(); + return x5e4_collisionTreePrim.get(); } -zeus::CTransform CPuddleToadGamma::GetPrimitiveTransform() const -{ - zeus::CTransform xf = GetTransform(); - xf.origin += GetPrimitiveOffset(); - return xf; +zeus::CTransform CPuddleToadGamma::GetPrimitiveTransform() const { + zeus::CTransform xf = GetTransform(); + xf.origin += GetPrimitiveOffset(); + return xf; } -void CPuddleToadGamma::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CPatterned::AcceptScriptMsg(msg, uid, mgr); +void CPuddleToadGamma::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); - if (msg == EScriptObjectMessage::Registered) - { - x450_bodyController->Activate(mgr); - zeus::CTransform bellyXf = GetLctrTransform(mBellyLocatorName); - zeus::CVector3f bellyOffset = GetTransform().rotate(skBellyOffset); - x5d8_ = x5cc_ = bellyXf.origin + bellyOffset; - RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); - AddMaterial(EMaterialTypes::Immovable, mgr); - AddMaterial(EMaterialTypes::SolidCharacter); - } + if (msg == EScriptObjectMessage::Registered) { + x450_bodyController->Activate(mgr); + zeus::CTransform bellyXf = GetLctrTransform(mBellyLocatorName); + zeus::CVector3f bellyOffset = GetTransform().rotate(skBellyOffset); + x5d8_ = x5cc_ = bellyXf.origin + bellyOffset; + RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); + AddMaterial(EMaterialTypes::Immovable, mgr); + AddMaterial(EMaterialTypes::SolidCharacter); + } } -void CPuddleToadGamma::Think(float dt, CStateManager& mgr) -{ - CPatterned::Think(dt, mgr); - if (x5e8_25_) - x56c_ += dt; +void CPuddleToadGamma::Think(float dt, CStateManager& mgr) { + CPatterned::Think(dt, mgr); + if (x5e8_25_) + x56c_ += dt; } -std::experimental::optional CPuddleToadGamma::GetTouchBounds() const -{ - if (!GetActive()) - return {}; +std::experimental::optional CPuddleToadGamma::GetTouchBounds() const { + if (!GetActive()) + return {}; - return (x5e4_collisionTreePrim ? x5e4_collisionTreePrim->CalculateAABox(GetTransform()) : GetBoundingBox()); + return (x5e4_collisionTreePrim ? x5e4_collisionTreePrim->CalculateAABox(GetTransform()) : GetBoundingBox()); } -void CPuddleToadGamma::CenterPlayer(CStateManager& mgr, const zeus::CVector3f& pos, float dt) -{ - zeus::CVector3f dir = (mgr.GetPlayer().GetTranslation() - pos).normalized(); - mgr.GetPlayer().SetVelocityWR((1.f / (2.f * dt)) * dir); +void CPuddleToadGamma::CenterPlayer(CStateManager& mgr, const zeus::CVector3f& pos, float dt) { + zeus::CVector3f dir = (mgr.GetPlayer().GetTranslation() - pos).normalized(); + mgr.GetPlayer().SetVelocityWR((1.f / (2.f * dt)) * dir); } const CDamageVulnerability* CPuddleToadGamma::GetDamageVulnerability(const zeus::CVector3f& pos, const zeus::CVector3f& dir, - const CDamageInfo& dInfo) const -{ - if (x5e8_24_ && (x5d8_ - pos).magSquared() < 4.f) - return CAi::GetDamageVulnerability(); + const CDamageInfo& dInfo) const { + if (x5e8_24_ && (x5d8_ - pos).magSquared() < 4.f) + return CAi::GetDamageVulnerability(); - return &CDamageVulnerability::ImmuneVulnerabilty(); + return &CDamageVulnerability::ImmuneVulnerabilty(); } -void CPuddleToadGamma::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) -{ - if (type == EUserEventType::Projectile) - { - ShootPlayer(mgr, x5c0_); - return; - } - - CPatterned::DoUserAnimEvent(mgr, node, type, dt); -} - -bool CPuddleToadGamma::SpotPlayer(CStateManager&, float arg) -{ - return x56c_ >= x5c8_; -} - -bool CPuddleToadGamma::ShouldAttack(CStateManager&, float) -{ - return x56c_ >= x5c4_; -} - -bool CPuddleToadGamma::LostInterest(CStateManager& mgr, float) -{ - zeus::CAABox box = *GetTouchBounds(); - zeus::CAABox plBox = mgr.GetPlayer().GetBoundingBox(); - return !box.intersects(plBox); -} - -void CPuddleToadGamma::ShootPlayer(CStateManager&, float) -{ - -} - -bool CPuddleToadGamma::InAttackPosition(CStateManager& mgr, float) -{ - return mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && - PlayerInVortexArea(mgr); -} - -static CMaterialFilter kSolidFilter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::Character, - EMaterialTypes::Player, - EMaterialTypes::ProjectilePassthrough}); - -bool CPuddleToadGamma::PlayerInVortexArea(const CStateManager& mgr) -{ - CPlayer& player = mgr.GetPlayer(); - zeus::CTransform xf = GetLctrTransform(mMouthLocatorName); - - zeus::CVector3f playerOffset = - player.GetTranslation() + zeus::CVector3f{0.f, 0.f, player.GetMorphBall()->GetBallRadius()}; - zeus::CVector3f rotatedOffset = GetTransform().rotate(zeus::CVector3f::skForward); - - zeus::CVector3f vec1 = (playerOffset - (xf.origin - (1.f * rotatedOffset))); - float f31 = vec1.normalized().dot(rotatedOffset); - float f28 = vec1.magnitude(); - float f26 = (player.GetTranslation() - (xf.origin - (4.f * rotatedOffset))).normalized().dot(rotatedOffset); - if (f28 > 2.f) - { - CRayCastResult result = mgr.RayStaticIntersection(vec1, 1.f / f28 * vec1, - f28 - player.GetMorphBall()->GetBallRadius(), kSolidFilter); - if (result.IsValid()) - return false; - } - - return (f28 < x5b0_ && f31 > 0.f && f26 > x5ac_); -} - -void CPuddleToadGamma::InActive(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); - SetSolid(mgr, true); - mgr.GetPlayer().Set_X590(true); - x330_stateMachineState.SetDelay(2.f); - } -} - -void CPuddleToadGamma::Active(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - zeus::CTransform xf = GetLctrTransform(mBellyLocatorName); - x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset); - x56c_ = 0.f; - x5e8_25_ = true; - SetSolid(mgr, true); - mgr.GetPlayer().Set_X590(true); - } else if (msg == EStateMsg::Deactivate) - { - x5e8_25_ = false; - } -} - -void CPuddleToadGamma::Suck(CStateManager& mgr, EStateMsg msg, float arg) -{ +void CPuddleToadGamma::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + if (type == EUserEventType::Projectile) { + ShootPlayer(mgr, x5c0_); return; - if (msg == EStateMsg::Activate) - { - SetSolid(mgr, false); - mgr.GetPlayer().Set_X590(false); - mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus(); - } else if (msg == EStateMsg::Update) - { - if (x568_ == 0) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LoopReaction) - { - x568_ = 1; - return; - } + } - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType::Zero)); - } else if (x568_ == 1) - SuckPlayer(mgr, arg); - } else if (msg == EStateMsg::Deactivate) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); - } + CPatterned::DoUserAnimEvent(mgr, node, type, dt); } -void CPuddleToadGamma::SuckPlayer(CStateManager& mgr, float arg) -{ - CPlayer& player = mgr.GetPlayer(); - if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) - return; +bool CPuddleToadGamma::SpotPlayer(CStateManager&, float arg) { return x56c_ >= x5c8_; } - zeus::CVector3f posDiff = player.GetTranslation() - x5cc_; - if (posDiff.magnitude() < 3.f) - { - player.Stop(); - CenterPlayer(mgr, x5cc_, arg); - return; - } +bool CPuddleToadGamma::ShouldAttack(CStateManager&, float) { return x56c_ >= x5c4_; } - float d = x5a8_ * (x5b0_ / (posDiff.magnitude() * posDiff.magnitude())); - zeus::CVector3f force = d * (player.GetMass() * -posDiff); - player.ApplyForceWR(force, zeus::CAxisAngle::sIdentity); +bool CPuddleToadGamma::LostInterest(CStateManager& mgr, float) { + zeus::CAABox box = *GetTouchBounds(); + zeus::CAABox plBox = mgr.GetPlayer().GetBoundingBox(); + return !box.intersects(plBox); } -void CPuddleToadGamma::Attack(CStateManager& mgr, EStateMsg msg, float) -{ +void CPuddleToadGamma::ShootPlayer(CStateManager&, float) {} + +bool CPuddleToadGamma::InAttackPosition(CStateManager& mgr, float) { + return mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && + PlayerInVortexArea(mgr); +} + +static CMaterialFilter kSolidFilter = + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::Character, EMaterialTypes::Player, + EMaterialTypes::ProjectilePassthrough}); + +bool CPuddleToadGamma::PlayerInVortexArea(const CStateManager& mgr) { + CPlayer& player = mgr.GetPlayer(); + zeus::CTransform xf = GetLctrTransform(mMouthLocatorName); + + zeus::CVector3f playerOffset = + player.GetTranslation() + zeus::CVector3f{0.f, 0.f, player.GetMorphBall()->GetBallRadius()}; + zeus::CVector3f rotatedOffset = GetTransform().rotate(zeus::CVector3f::skForward); + + zeus::CVector3f vec1 = (playerOffset - (xf.origin - (1.f * rotatedOffset))); + float f31 = vec1.normalized().dot(rotatedOffset); + float f28 = vec1.magnitude(); + float f26 = (player.GetTranslation() - (xf.origin - (4.f * rotatedOffset))).normalized().dot(rotatedOffset); + if (f28 > 2.f) { + CRayCastResult result = + mgr.RayStaticIntersection(vec1, 1.f / f28 * vec1, f28 - player.GetMorphBall()->GetBallRadius(), kSolidFilter); + if (result.IsValid()) + return false; + } + + return (f28 < x5b0_ && f31 > 0.f && f26 > x5ac_); +} + +void CPuddleToadGamma::InActive(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + SetSolid(mgr, true); + mgr.GetPlayer().Set_X590(true); + x330_stateMachineState.SetDelay(2.f); + } +} + +void CPuddleToadGamma::Active(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + zeus::CTransform xf = GetLctrTransform(mBellyLocatorName); + x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset); + x56c_ = 0.f; + x5e8_25_ = true; + SetSolid(mgr, true); + mgr.GetPlayer().Set_X590(true); + } else if (msg == EStateMsg::Deactivate) { + x5e8_25_ = false; + } +} + +void CPuddleToadGamma::Suck(CStateManager& mgr, EStateMsg msg, float arg) { + return; + if (msg == EStateMsg::Activate) { + SetSolid(mgr, false); + mgr.GetPlayer().Set_X590(false); + mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus(); + } else if (msg == EStateMsg::Update) { + if (x568_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LoopReaction) { + x568_ = 1; + return; + } + + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType::Zero)); + } else if (x568_ == 1) + SuckPlayer(mgr, arg); + } else if (msg == EStateMsg::Deactivate) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); + } +} + +void CPuddleToadGamma::SuckPlayer(CStateManager& mgr, float arg) { + CPlayer& player = mgr.GetPlayer(); + if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) return; - if (msg == EStateMsg::Activate) - { - mgr.GetPlayer().Stop(); - mgr.GetPlayer().SetVelocityWR({}); - x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::One)); - x5e8_26_ = false; - mgr.GetPlayer().GetMorphBall()->SetBombJumpState(CMorphBall::EBombJumpState::BombJumpDisabled); - } else if (msg == EStateMsg::Update) - { - if (!x5e8_26_) - { - zeus::CTransform xf = GetLctrTransform(mBellyLocatorName); - x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset); - SetPlayerPosition(mgr, x5cc_); - } else if (LostInterest(mgr, 0.f)) - SetSolid(mgr, true); - } else if (msg == EStateMsg::Deactivate) - { - SetSolid(mgr, true); - mgr.GetPlayer().Set_X590(true); - mgr.GetPlayer().GetMorphBall()->SetBombJumpState(CMorphBall::EBombJumpState::BombJumpAvailable); - x5e8_24_ = false; - } -} -void CPuddleToadGamma::SetPlayerPosition(CStateManager& mgr, const zeus::CVector3f& targetPos) -{ - float preThinkDt = x500_preThinkDt; - CPlayer& player = mgr.GetPlayer(); + zeus::CVector3f posDiff = player.GetTranslation() - x5cc_; + if (posDiff.magnitude() < 3.f) { player.Stop(); - player.SetVelocityWR({}); - bool hadPlayerMaterial = player.GetMaterialList().HasMaterial(EMaterialTypes::Player); - - if (hadPlayerMaterial) - player.RemoveMaterial(EMaterialTypes::GroundCollider, mgr); - player.RemoveMaterial(EMaterialTypes::Player, mgr); - - bool hadSolidMaterial = GetMaterialList().HasMaterial(EMaterialTypes::Solid); - if (hadSolidMaterial) - RemoveMaterial(EMaterialTypes::Solid, mgr); - - CPhysicsState physState = player.GetPhysicsState(); - player.Stop(); - player.MoveToWR(targetPos, preThinkDt); - CGameCollision::Move(mgr, player, preThinkDt, nullptr); - physState.SetTranslation(player.GetTranslation()); - player.SetPhysicsState(physState); - if (hadPlayerMaterial) - player.AddMaterial(EMaterialTypes::GroundCollider, mgr); - player.AddMaterial(EMaterialTypes::Player, mgr); - if (hadSolidMaterial) - AddMaterial(EMaterialTypes::Solid, mgr); -} - -bool CPuddleToadGamma::Inside(CStateManager& mgr, float) -{ - if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) - return false; - - zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - x5cc_; - return posDiff.dot(GetTransform().frontVector()) <= 0.f && - posDiff.magSquared() < 2.f; -} - -void CPuddleToadGamma::Crouch(CStateManager& mgr, EStateMsg msg, float) -{ + CenterPlayer(mgr, x5cc_, arg); return; - if (msg == EStateMsg::Activate) - { - x568_ = 0; - x56c_ = 0.f; - x5e8_25_ = true; - x5e8_24_ = true; - mgr.GetPlayer().Stop(); - mgr.GetPlayer().SetVelocityWR({}); - SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::None); - if (!mgr.GetPlayer().AttachActorToPlayer(GetUniqueId(), false)) - x56c_ = 100.f; + } - SetSolid(mgr, false); - mgr.GetPlayer().Set_X590(false); - mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus(); - SetSolid(mgr, false); - } - else if (msg == EStateMsg::Update) - { - zeus::CTransform xf = GetLctrTransform(mBellyLocatorName); - x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset); - SetPlayerPosition(mgr, x5cc_); - if (x568_ == 0) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Locomotion) - x568_ = 1; - else - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); - } - } - else if (msg == EStateMsg::Deactivate) - { - if (mgr.GetPlayer().GetAttachedActor() == GetUniqueId()) - mgr.GetPlayer().DetachActorFromPlayer(); - mgr.GetPlayer().Set_X590(true); - x5e8_25_ = false; - } + float d = x5a8_ * (x5b0_ / (posDiff.magnitude() * posDiff.magnitude())); + zeus::CVector3f force = d * (player.GetMass() * -posDiff); + player.ApplyForceWR(force, zeus::CAxisAngle::sIdentity); } +void CPuddleToadGamma::Attack(CStateManager& mgr, EStateMsg msg, float) { + return; + if (msg == EStateMsg::Activate) { + mgr.GetPlayer().Stop(); + mgr.GetPlayer().SetVelocityWR({}); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::One)); + x5e8_26_ = false; + mgr.GetPlayer().GetMorphBall()->SetBombJumpState(CMorphBall::EBombJumpState::BombJumpDisabled); + } else if (msg == EStateMsg::Update) { + if (!x5e8_26_) { + zeus::CTransform xf = GetLctrTransform(mBellyLocatorName); + x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset); + SetPlayerPosition(mgr, x5cc_); + } else if (LostInterest(mgr, 0.f)) + SetSolid(mgr, true); + } else if (msg == EStateMsg::Deactivate) { + SetSolid(mgr, true); + mgr.GetPlayer().Set_X590(true); + mgr.GetPlayer().GetMorphBall()->SetBombJumpState(CMorphBall::EBombJumpState::BombJumpAvailable); + x5e8_24_ = false; + } } + +void CPuddleToadGamma::SetPlayerPosition(CStateManager& mgr, const zeus::CVector3f& targetPos) { + float preThinkDt = x500_preThinkDt; + CPlayer& player = mgr.GetPlayer(); + player.Stop(); + player.SetVelocityWR({}); + bool hadPlayerMaterial = player.GetMaterialList().HasMaterial(EMaterialTypes::Player); + + if (hadPlayerMaterial) + player.RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + player.RemoveMaterial(EMaterialTypes::Player, mgr); + + bool hadSolidMaterial = GetMaterialList().HasMaterial(EMaterialTypes::Solid); + if (hadSolidMaterial) + RemoveMaterial(EMaterialTypes::Solid, mgr); + + CPhysicsState physState = player.GetPhysicsState(); + player.Stop(); + player.MoveToWR(targetPos, preThinkDt); + CGameCollision::Move(mgr, player, preThinkDt, nullptr); + physState.SetTranslation(player.GetTranslation()); + player.SetPhysicsState(physState); + if (hadPlayerMaterial) + player.AddMaterial(EMaterialTypes::GroundCollider, mgr); + player.AddMaterial(EMaterialTypes::Player, mgr); + if (hadSolidMaterial) + AddMaterial(EMaterialTypes::Solid, mgr); +} + +bool CPuddleToadGamma::Inside(CStateManager& mgr, float) { + if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) + return false; + + zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - x5cc_; + return posDiff.dot(GetTransform().frontVector()) <= 0.f && posDiff.magSquared() < 2.f; +} + +void CPuddleToadGamma::Crouch(CStateManager& mgr, EStateMsg msg, float) { + return; + if (msg == EStateMsg::Activate) { + x568_ = 0; + x56c_ = 0.f; + x5e8_25_ = true; + x5e8_24_ = true; + mgr.GetPlayer().Stop(); + mgr.GetPlayer().SetVelocityWR({}); + SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::None); + if (!mgr.GetPlayer().AttachActorToPlayer(GetUniqueId(), false)) + x56c_ = 100.f; + + SetSolid(mgr, false); + mgr.GetPlayer().Set_X590(false); + mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus(); + SetSolid(mgr, false); + } else if (msg == EStateMsg::Update) { + zeus::CTransform xf = GetLctrTransform(mBellyLocatorName); + x5cc_ = xf.origin + GetTransform().rotate(skBellyOffset); + SetPlayerPosition(mgr, x5cc_); + if (x568_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Locomotion) + x568_ = 1; + else + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); + } + } else if (msg == EStateMsg::Deactivate) { + if (mgr.GetPlayer().GetAttachedActor() == GetUniqueId()) + mgr.GetPlayer().DetachActorFromPlayer(); + mgr.GetPlayer().Set_X590(true); + x5e8_25_ = false; + } +} + +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CPuddleToadGamma.hpp b/Runtime/MP1/World/CPuddleToadGamma.hpp index b60a2ce0d..6ee28593c 100644 --- a/Runtime/MP1/World/CPuddleToadGamma.hpp +++ b/Runtime/MP1/World/CPuddleToadGamma.hpp @@ -3,73 +3,70 @@ #include "World/CPatterned.hpp" #include "Collision/CCollidableOBBTreeGroup.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { -class CPuddleToadGamma final : public CPatterned -{ - static constexpr std::string_view mMouthLocatorName = "MOUTH_LCTR_SDK"sv; - static constexpr std::string_view mBellyLocatorName = "SAMUS_POS_LCTR_SDK"sv; - static const zeus::CVector3f skBellyOffset; - u32 x568_ = 0; - float x56c_ = 0.f; - CDamageInfo x570_; - CDamageInfo x58c_; - float x5a8_; - float x5ac_; - float x5b0_; - zeus::CVector3f x5b4_; - float x5c0_; - float x5c4_; - float x5c8_; - zeus::CVector3f x5cc_; - zeus::CVector3f x5d8_; - std::unique_ptr x5e4_collisionTreePrim; - bool x5e8_24_ : 1; - bool x5e8_25_ : 1; - bool x5e8_26_ : 1; +class CPuddleToadGamma final : public CPatterned { + static constexpr std::string_view mMouthLocatorName = "MOUTH_LCTR_SDK"sv; + static constexpr std::string_view mBellyLocatorName = "SAMUS_POS_LCTR_SDK"sv; + static const zeus::CVector3f skBellyOffset; + u32 x568_ = 0; + float x56c_ = 0.f; + CDamageInfo x570_; + CDamageInfo x58c_; + float x5a8_; + float x5ac_; + float x5b0_; + zeus::CVector3f x5b4_; + float x5c0_; + float x5c4_; + float x5c8_; + zeus::CVector3f x5cc_; + zeus::CVector3f x5d8_; + std::unique_ptr x5e4_collisionTreePrim; + bool x5e8_24_ : 1; + bool x5e8_25_ : 1; + bool x5e8_26_ : 1; - void SetSolid(CStateManager&, bool); + void SetSolid(CStateManager&, bool); - static void CenterPlayer(CStateManager&, const zeus::CVector3f&, float); - void ShootPlayer(CStateManager&, float); - void SuckPlayer(CStateManager&, float); - bool PlayerInVortexArea(const CStateManager&); - void SetPlayerPosition(CStateManager&, const zeus::CVector3f&); + static void CenterPlayer(CStateManager&, const zeus::CVector3f&, float); + void ShootPlayer(CStateManager&, float); + void SuckPlayer(CStateManager&, float); + bool PlayerInVortexArea(const CStateManager&); + void SetPlayerPosition(CStateManager&, const zeus::CVector3f&); public: - DEFINE_PATTERNED(PuddleToad) + DEFINE_PATTERNED(PuddleToad) - CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - const CActorParameters& aParms, float f1, float f2, float f3, const zeus::CVector3f& v1, - float f4, float f5, float f6, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2, CAssetId dcln); + CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, + const CActorParameters& aParms, float f1, float f2, float f3, const zeus::CVector3f& v1, float f4, + float f5, float f6, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2, CAssetId dcln); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float dt, CStateManager& mgr); - void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); - std::experimental::optional GetTouchBounds() const; + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float dt, CStateManager& mgr); + void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); + std::experimental::optional GetTouchBounds() const; - const CDamageVulnerability* - GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, const CDamageInfo&) const; + const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, + const CDamageInfo&) const; - const CDamageVulnerability* GetDamageVulnerability() const { return &CDamageVulnerability::ImmuneVulnerabilty(); } + const CDamageVulnerability* GetDamageVulnerability() const { return &CDamageVulnerability::ImmuneVulnerabilty(); } - const CCollisionPrimitive* GetCollisionPrimitive() const; + const CCollisionPrimitive* GetCollisionPrimitive() const; - zeus::CTransform GetPrimitiveTransform() const; + zeus::CTransform GetPrimitiveTransform() const; - void InActive(CStateManager&, EStateMsg, float); - void Active(CStateManager&, EStateMsg, float); - void Suck(CStateManager&, EStateMsg, float); - void Attack(CStateManager&, EStateMsg, float); - void Crouch(CStateManager&, EStateMsg, float); - bool InAttackPosition(CStateManager&, float); - bool SpotPlayer(CStateManager&, float); - bool ShouldAttack(CStateManager&, float); - bool LostInterest(CStateManager&, float); - bool Inside(CStateManager&, float); + void InActive(CStateManager&, EStateMsg, float); + void Active(CStateManager&, EStateMsg, float); + void Suck(CStateManager&, EStateMsg, float); + void Attack(CStateManager&, EStateMsg, float); + void Crouch(CStateManager&, EStateMsg, float); + bool InAttackPosition(CStateManager&, float); + bool SpotPlayer(CStateManager&, float); + bool ShouldAttack(CStateManager&, float); + bool LostInterest(CStateManager&, float); + bool Inside(CStateManager&, float); }; -} - +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CPuffer.cpp b/Runtime/MP1/World/CPuffer.cpp index bc436da5c..b5fd6a236 100644 --- a/Runtime/MP1/World/CPuffer.cpp +++ b/Runtime/MP1/World/CPuffer.cpp @@ -7,152 +7,114 @@ #include "World/CFire.hpp" #include "TCastTo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CPuffer::CPuffer(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& modelData, const CActorParameters& actorParameters, const CPatternedInfo& patternedInfo, float hoverSpeed, CAssetId cloudEffect, const CDamageInfo& cloudDamage, CAssetId cloudSteam, float f2, bool b1, bool b2, bool b3, const CDamageInfo& explosionDamage, s16 sfxId) - : CPatterned(ECharacter::Puffer, uid, name, EFlavorType::Zero, info, xf, std::move(modelData), patternedInfo, - EMovementType::Flyer, EColliderType::One, EBodyType::RestrictedFlyer, actorParameters, - EKnockBackVariant::Small), x568_face(xf.frontVector()), - x574_cloudEffect(g_SimplePool->GetObj({SBIG('PART'), cloudEffect})), x57c_cloudDamage(cloudDamage), x598_24_(b1), - x598_25_(b3), x598_26_(b2), x59a_(CSfxManager::TranslateSFXID(sfxId)), x59c_explosionDamage(explosionDamage), - x5b8_(f2), x5bc_cloudSteam(cloudSteam) -{ - CreateShadow(false); - x460_knockBackController.SetImpulseDurationIdx(1); - x574_cloudEffect.Lock(); +: CPatterned(ECharacter::Puffer, uid, name, EFlavorType::Zero, info, xf, std::move(modelData), patternedInfo, + EMovementType::Flyer, EColliderType::One, EBodyType::RestrictedFlyer, actorParameters, + EKnockBackVariant::Small) +, x568_face(xf.frontVector()) +, x574_cloudEffect(g_SimplePool->GetObj({SBIG('PART'), cloudEffect})) +, x57c_cloudDamage(cloudDamage) +, x598_24_(b1) +, x598_25_(b3) +, x598_26_(b2) +, x59a_(CSfxManager::TranslateSFXID(sfxId)) +, x59c_explosionDamage(explosionDamage) +, x5b8_(f2) +, x5bc_cloudSteam(cloudSteam) { + CreateShadow(false); + x460_knockBackController.SetImpulseDurationIdx(1); + x574_cloudEffect.Lock(); } -void CPuffer::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CPuffer::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CPuffer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); + + switch (msg) { + case EScriptObjectMessage::Registered: + x450_bodyController->Activate(mgr); + SetMaterialFilter( + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Player}, {EMaterialTypes::NoStaticCollision})); + break; + case EScriptObjectMessage::Action: + if (GetActive()) + x401_30_pendingDeath = true; + break; + default: + break; + } } -void CPuffer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CPatterned::AcceptScriptMsg(msg, uid, mgr); +void CPuffer::Think(float dt, CStateManager& mgr) { + CPatterned::Think(dt, mgr); + sub8025bfa4(mgr); + zeus::CVector3f moveVector = x450_bodyController->GetCommandMgr().GetMoveVector(); - switch (msg) - { - case EScriptObjectMessage::Registered: - x450_bodyController->Activate(mgr); - SetMaterialFilter( - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Player}, {EMaterialTypes::NoStaticCollision})); - break; - case EScriptObjectMessage::Action: - if (GetActive()) - x401_30_pendingDeath = true; - break; - default: - break; - } + if (x5cc_ != x2dc_destObj) { + x5cc_ = x2dc_destObj; + CSfxManager::AddEmitter(x59a_, GetTranslation(), {}, true, false, 127, -1); + } + + x450_bodyController->GetCommandMgr().ClearLocomotionCmds(); + if (moveVector.canBeNormalized()) { + zeus::CVector3f vec = x5c0_move * (1.f - (dt / 0.5f)) + (moveVector * (dt / 0.5f)); + x5c0_move = moveVector.normalized(); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(x5c0_move, x568_face, 1.f)); + } } -void CPuffer::Think(float dt, CStateManager& mgr) -{ - CPatterned::Think(dt, mgr); - sub8025bfa4(mgr); - zeus::CVector3f moveVector = x450_bodyController->GetCommandMgr().GetMoveVector(); +std::experimental::optional CPuffer::GetTouchBounds() const { + auto touchBounds = CPatterned::GetTouchBounds(); + if (touchBounds) { + touchBounds->accumulateBounds(touchBounds->min - 0.5f); + touchBounds->accumulateBounds(touchBounds->max + 0.5f); + } - if (x5cc_ != x2dc_destObj) - { - x5cc_ = x2dc_destObj; - CSfxManager::AddEmitter(x59a_, GetTranslation(), {}, true, false, 127, -1); - } - - x450_bodyController->GetCommandMgr().ClearLocomotionCmds(); - if (moveVector.canBeNormalized()) - { - zeus::CVector3f vec = x5c0_move * (1.f - (dt / 0.5f)) + (moveVector * (dt / 0.5f)); - x5c0_move = moveVector.normalized(); - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(x5c0_move, x568_face, 1.f)); - } + return touchBounds; } -std::experimental::optional CPuffer::GetTouchBounds() const -{ - auto touchBounds = CPatterned::GetTouchBounds(); - if (touchBounds) - { - touchBounds->accumulateBounds(touchBounds->min - 0.5f); - touchBounds->accumulateBounds(touchBounds->max + 0.5f); - } +void CPuffer::Touch(CActor& act, CStateManager& mgr) { + CPatterned::Touch(act, mgr); - return touchBounds; + if (x400_25_alive && act.GetUniqueId() == mgr.GetPlayer().GetUniqueId()) + x401_30_pendingDeath = true; } -void CPuffer::Touch(CActor& act, CStateManager& mgr) -{ - CPatterned::Touch(act, mgr); - - if (x400_25_alive && act.GetUniqueId() == mgr.GetPlayer().GetUniqueId()) - x401_30_pendingDeath = true; +void CPuffer::Death(CStateManager& mgr, zeus::CVector3f& vec, EScriptObjectState state) { + CPatterned::Death(mgr, vec, state); + mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x59c_explosionDamage, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {})); + zeus::CTransform xf = GetTransform() * zeus::CTransform::Scale(x57c_cloudDamage.GetRadius()); + zeus::CAABox aabox(-1.f, 1.f); + mgr.AddObject(new CFire(x574_cloudEffect, mgr.AllocateUniqueId(), GetAreaIdAlways(), true, GetUniqueId(), + GetTransform(), x57c_cloudDamage, aabox.getTransformedAABox(xf), {1.f, 1.f, 1.f}, true, + x5bc_cloudSteam, x598_24_, x598_26_, x598_25_, 1.f, x5b8_, 1.f, 1.f)); } -void CPuffer::Death(CStateManager& mgr, zeus::CVector3f& vec, EScriptObjectState state) -{ - CPatterned::Death(mgr, vec, state); - mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x59c_explosionDamage, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {})); - zeus::CTransform xf = GetTransform() * zeus::CTransform::Scale(x57c_cloudDamage.GetRadius()); - zeus::CAABox aabox(-1.f, 1.f); - mgr.AddObject(new CFire(x574_cloudEffect, mgr.AllocateUniqueId(), GetAreaIdAlways(), true, GetUniqueId(), - GetTransform(), x57c_cloudDamage, aabox.getTransformedAABox(xf), {1.f, 1.f, 1.f}, true, x5bc_cloudSteam, - x598_24_, x598_26_, x598_25_, 1.f, x5b8_, 1.f, 1.f)); -} - -static const char* GasLocators[14] = - { - "Gas_01_LCTR", - "Gas_02_LCTR", - "Gas_03_LCTR", - "Gas_04_LCTR", - "Gas_05_LCTR", - "Gas_06_LCTR", - "Gas_07_LCTR", - "Gas_08_LCTR", - "Gas_09_LCTR", - "Gas_10_LCTR", - "Gas_11_LCTR", - "Gas_12_LCTR", - "Gas_13_LCTR", - "Gas_14_LCTR", - }; - -static const char* GesJetLocators[14] = - { - "GasJet01", - "GasJet02", - "GasJet03", - "GasJet04", - "GasJet05", - "GasJet06", - "GasJet07", - "GasJet08", - "GasJet09", - "GasJet10", - "GasJet11", - "GasJet12", - "GasJet13", - "GasJet14", - }; - -void CPuffer::sub8025bfa4(CStateManager& mgr) -{ - zeus::CVector3f moveVector = x450_bodyController->GetCommandMgr().GetMoveVector(); - - if (x5d4_gasLocators.empty()) - { - for (u32 i = 0 ; i < 14; ++i) - x5d4_gasLocators.push_back(GetScaledLocatorTransform(GasLocators[i]).frontVector()); - } - - if (moveVector.canBeNormalized()) - { - - } -} +static const char* GasLocators[14] = { + "Gas_01_LCTR", "Gas_02_LCTR", "Gas_03_LCTR", "Gas_04_LCTR", "Gas_05_LCTR", "Gas_06_LCTR", "Gas_07_LCTR", + "Gas_08_LCTR", "Gas_09_LCTR", "Gas_10_LCTR", "Gas_11_LCTR", "Gas_12_LCTR", "Gas_13_LCTR", "Gas_14_LCTR", +}; + +static const char* GesJetLocators[14] = { + "GasJet01", "GasJet02", "GasJet03", "GasJet04", "GasJet05", "GasJet06", "GasJet07", + "GasJet08", "GasJet09", "GasJet10", "GasJet11", "GasJet12", "GasJet13", "GasJet14", +}; + +void CPuffer::sub8025bfa4(CStateManager& mgr) { + zeus::CVector3f moveVector = x450_bodyController->GetCommandMgr().GetMoveVector(); + + if (x5d4_gasLocators.empty()) { + for (u32 i = 0; i < 14; ++i) + x5d4_gasLocators.push_back(GetScaledLocatorTransform(GasLocators[i]).frontVector()); + } + + if (moveVector.canBeNormalized()) {} } +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CPuffer.hpp b/Runtime/MP1/World/CPuffer.hpp index 2620aba27..dbacaa30f 100644 --- a/Runtime/MP1/World/CPuffer.hpp +++ b/Runtime/MP1/World/CPuffer.hpp @@ -2,38 +2,37 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ -class CPuffer : public CPatterned -{ - zeus::CVector3f x568_face; - TToken x574_cloudEffect; - CDamageInfo x57c_cloudDamage; - bool x598_24_ : 1; - bool x598_25_ : 1; - bool x598_26_ : 1; - s16 x59a_; - CDamageInfo x59c_explosionDamage; - float x5b8_; - CAssetId x5bc_cloudSteam; - zeus::CVector3f x5c0_move; - TUniqueId x5cc_ = kInvalidUniqueId; - s32 x5d0_ = 0; - rstl::reserved_vector x5d4_gasLocators; +namespace urde::MP1 { +class CPuffer : public CPatterned { + zeus::CVector3f x568_face; + TToken x574_cloudEffect; + CDamageInfo x57c_cloudDamage; + bool x598_24_ : 1; + bool x598_25_ : 1; + bool x598_26_ : 1; + s16 x59a_; + CDamageInfo x59c_explosionDamage; + float x5b8_; + CAssetId x5bc_cloudSteam; + zeus::CVector3f x5c0_move; + TUniqueId x5cc_ = kInvalidUniqueId; + s32 x5d0_ = 0; + rstl::reserved_vector x5d4_gasLocators; + + void sub8025bfa4(CStateManager&); - void sub8025bfa4(CStateManager&); public: - DEFINE_PATTERNED(Puffer) + DEFINE_PATTERNED(Puffer) - CPuffer(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CActorParameters&, const CPatternedInfo&, float, CAssetId, const CDamageInfo&, CAssetId, - float, bool, bool, bool, const CDamageInfo&, s16); + CPuffer(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const CPatternedInfo&, float, CAssetId, const CDamageInfo&, CAssetId, float, bool, + bool, bool, const CDamageInfo&, s16); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - std::experimental::optional GetTouchBounds() const; - void Touch(CActor&, CStateManager&); - void Death(CStateManager&, zeus::CVector3f&, EScriptObjectState); + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + std::experimental::optional GetTouchBounds() const; + void Touch(CActor&, CStateManager&); + void Death(CStateManager&, zeus::CVector3f&, EScriptObjectState); }; -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CRidley.cpp b/Runtime/MP1/World/CRidley.cpp index ded301419..3b30bfc51 100644 --- a/Runtime/MP1/World/CRidley.cpp +++ b/Runtime/MP1/World/CRidley.cpp @@ -1,30 +1,56 @@ #include "MP1/World/CRidley.hpp" #include "TCastTo.hpp" -namespace urde -{ -namespace MP1 -{ +namespace urde { +namespace MP1 { CRidleyData::CRidleyData(CInputStream& in, u32 propCount) - : x0_(in), x4_(in), x8_(in), xc_(in), x10_(in), x14_(in), x18_(in), x1c_(in), x20_(in), x24_(in), x28_(in), - x2c_(in), x30_(in), x34_(in.readFloatBig()), x38_(in.readFloatBig()), x3c_(in.readFloatBig()), - x40_(in.readFloatBig()), x44_(in), x48_(in), x64_(in), xa8_(CSfxManager::TranslateSFXID(in.readUint32Big())), - xac_(in), xb0_(in), xcc_(in), x1a0_(in), x1a4_(in), x1c0_(in), - x294_(CSfxManager::TranslateSFXID(in.readUint32Big())), x298_(in), x2b4_(in), x388_(in.readFloatBig()), - x38c_(in.readFloatBig()), x390_(in), x3ac_(in.readFloatBig()), x3b0_(in), x3cc_(in.readFloatBig()), x3d0_(in), - x3f4_(in.readFloatBig()), x3f8_(CSfxManager::TranslateSFXID(in.readUint32Big())), - x3fc_(propCount > 47 ? CDamageInfo(in) : x48_) -{ -} +: x0_(in) +, x4_(in) +, x8_(in) +, xc_(in) +, x10_(in) +, x14_(in) +, x18_(in) +, x1c_(in) +, x20_(in) +, x24_(in) +, x28_(in) +, x2c_(in) +, x30_(in) +, x34_(in.readFloatBig()) +, x38_(in.readFloatBig()) +, x3c_(in.readFloatBig()) +, x40_(in.readFloatBig()) +, x44_(in) +, x48_(in) +, x64_(in) +, xa8_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xac_(in) +, xb0_(in) +, xcc_(in) +, x1a0_(in) +, x1a4_(in) +, x1c0_(in) +, x294_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x298_(in) +, x2b4_(in) +, x388_(in.readFloatBig()) +, x38c_(in.readFloatBig()) +, x390_(in) +, x3ac_(in.readFloatBig()) +, x3b0_(in) +, x3cc_(in.readFloatBig()) +, x3d0_(in) +, x3f4_(in.readFloatBig()) +, x3f8_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x3fc_(propCount > 47 ? CDamageInfo(in) : x48_) {} -CRidley::CRidley(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - const CActorParameters& actParms, CInputStream& in, u32 propCount) - : CPatterned(ECharacter::Ridley, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Flyer, EColliderType::Zero, EBodyType::Flyer, actParms, EKnockBackVariant::Large), - x568_(in, propCount) -{ -} -} -} +CRidley::CRidley(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CInputStream& in, + u32 propCount) +: CPatterned(ECharacter::Ridley, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Flyer, + EColliderType::Zero, EBodyType::Flyer, actParms, EKnockBackVariant::Large) +, x568_(in, propCount) {} +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/World/CRidley.hpp b/Runtime/MP1/World/CRidley.hpp index bc44b96ff..d9db4329f 100644 --- a/Runtime/MP1/World/CRidley.hpp +++ b/Runtime/MP1/World/CRidley.hpp @@ -5,65 +5,63 @@ #include "World/CDamageInfo.hpp" #include "World/CPatterned.hpp" -namespace urde -{ -namespace MP1 -{ -class CRidleyData -{ - CAssetId x0_; - CAssetId x4_; - CAssetId x8_; - CAssetId xc_; - CAssetId x10_; - CAssetId x14_; - CAssetId x18_; - CAssetId x1c_; - CAssetId x20_; - CAssetId x24_; - CAssetId x28_; - CAssetId x2c_; - CAssetId x30_; - float x34_; - float x38_; - float x3c_; - float x40_; - CAssetId x44_; - CDamageInfo x48_; - CBeamInfo x64_; - u16 xa8_; - CAssetId xac_; - CDamageInfo xb0_; - CCameraShakeData xcc_; - CAssetId x1a0_; - CDamageInfo x1a4_; - CCameraShakeData x1c0_; - u16 x294_; - CDamageInfo x298_; - CCameraShakeData x2b4_; - float x388_; - float x38c_; - CDamageInfo x390_; - float x3ac_; - CDamageInfo x3b0_; - float x3cc_; - CDamageInfo x3d0_; - float x3ec_; - CAssetId x3f0_; - float x3f4_; - u16 x3f8_; - CDamageInfo x3fc_; +namespace urde { +namespace MP1 { +class CRidleyData { + CAssetId x0_; + CAssetId x4_; + CAssetId x8_; + CAssetId xc_; + CAssetId x10_; + CAssetId x14_; + CAssetId x18_; + CAssetId x1c_; + CAssetId x20_; + CAssetId x24_; + CAssetId x28_; + CAssetId x2c_; + CAssetId x30_; + float x34_; + float x38_; + float x3c_; + float x40_; + CAssetId x44_; + CDamageInfo x48_; + CBeamInfo x64_; + u16 xa8_; + CAssetId xac_; + CDamageInfo xb0_; + CCameraShakeData xcc_; + CAssetId x1a0_; + CDamageInfo x1a4_; + CCameraShakeData x1c0_; + u16 x294_; + CDamageInfo x298_; + CCameraShakeData x2b4_; + float x388_; + float x38c_; + CDamageInfo x390_; + float x3ac_; + CDamageInfo x3b0_; + float x3cc_; + CDamageInfo x3d0_; + float x3ec_; + CAssetId x3f0_; + float x3f4_; + u16 x3f8_; + CDamageInfo x3fc_; + public: - CRidleyData(CInputStream&, u32); + CRidleyData(CInputStream&, u32); }; -class CRidley : public CPatterned -{ - CRidleyData x568_; +class CRidley : public CPatterned { + CRidleyData x568_; + public: - DEFINE_PATTERNED(Ridley) - CRidley(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, const CActorParameters&, CInputStream&, u32); + DEFINE_PATTERNED(Ridley) + CRidley(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CPatternedInfo&, + const CActorParameters&, CInputStream&, u32); }; -} -} +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/World/CSeedling.cpp b/Runtime/MP1/World/CSeedling.cpp index c985ac712..dcf91cc71 100644 --- a/Runtime/MP1/World/CSeedling.cpp +++ b/Runtime/MP1/World/CSeedling.cpp @@ -7,11 +7,8 @@ #include "TCastTo.hpp" #include "CSeedling.hpp" - -namespace urde -{ -namespace MP1 -{ +namespace urde { +namespace MP1 { CSeedling::CSeedling(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, @@ -25,240 +22,203 @@ CSeedling::CSeedling(TUniqueId uid, std::string_view name, const CEntityInfo& in , x6c0_projectileInfo(weaponId, dInfo1) , x6e8_deathDamage(dInfo2) , x722_24_renderOnlyClusterA(true) -, x722_25_curNeedleCluster(false) -{ - const_cast*>(&x6c0_projectileInfo.Token())->Lock(); - CreateShadow(false); - SetKeepInThermalVisor(); +, x722_25_curNeedleCluster(false) { + const_cast*>(&x6c0_projectileInfo.Token())->Lock(); + CreateShadow(false); + SetKeepInThermalVisor(); } -void CSeedling::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CSeedling::Accept(IVisitor& visitor) { visitor.Visit(this); } + +const std::string CSeedling::skNeedleLocators[2][6] = {{ + "A_spike1_LCTR_SDK", + "A_spike2_LCTR_SDK", + "A_spike3_LCTR_SDK", + "A_spike4_LCTR_SDK", + "A_spike5_LCTR_SDK", + "A_spike6_LCTR_SDK", + }, + { + "B_spike1_LCTR_SDK", + "B_spike2_LCTR_SDK", + "B_spike3_LCTR_SDK", + "B_spike4_LCTR_SDK", + "B_spike5_LCTR_SDK", + "B_spike6_LCTR_SDK", + }}; + +void CSeedling::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CPatterned::AcceptScriptMsg(msg, uid, mgr); + + if (msg == EScriptObjectMessage::Activate) { + x5d6_27_disableMove = false; + TUniqueId id = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); + if (id != kInvalidUniqueId) + x2dc_destObj = id; + } else if (msg == EScriptObjectMessage::Registered) { + x450_bodyController->Activate(mgr); + x704_modelBounds = GetModelData()->GetBounds(); + } else if (msg == EScriptObjectMessage::InitializedInArea) { + x5d8_searchPath.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); + } } -const std::string CSeedling::skNeedleLocators[2][6] = - { - { - "A_spike1_LCTR_SDK", - "A_spike2_LCTR_SDK", - "A_spike3_LCTR_SDK", - "A_spike4_LCTR_SDK", - "A_spike5_LCTR_SDK", - "A_spike6_LCTR_SDK", - }, - { - "B_spike1_LCTR_SDK", - "B_spike2_LCTR_SDK", - "B_spike3_LCTR_SDK", - "B_spike4_LCTR_SDK", - "B_spike5_LCTR_SDK", - "B_spike6_LCTR_SDK", - } - }; +void CSeedling::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; -void CSeedling::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CPatterned::AcceptScriptMsg(msg, uid, mgr); + ++x5d4_thinkCounter; + x5d6_26_playerObstructed = false; + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); + CGameArea::EOcclusionState occlusionState = CGameArea::EOcclusionState::Occluded; + if (area && area->IsPostConstructed()) + occlusionState = area->GetPostConstructed()->x10dc_occlusionState; - if (msg == EScriptObjectMessage::Activate) - { - x5d6_27_disableMove = false; - TUniqueId id = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); - if (id != kInvalidUniqueId) - x2dc_destObj = id; - } - else if (msg == EScriptObjectMessage::Registered) - { - x450_bodyController->Activate(mgr); - x704_modelBounds = GetModelData()->GetBounds(); - } - else if (msg == EScriptObjectMessage::InitializedInArea) - { - x5d8_searchPath.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea); - } -} + if (occlusionState == CGameArea::EOcclusionState::Occluded) + x5d6_26_playerObstructed = true; -void CSeedling::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; - - ++x5d4_thinkCounter; - x5d6_26_playerObstructed = false; - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); - CGameArea::EOcclusionState occlusionState = CGameArea::EOcclusionState::Occluded; - if (area && area->IsPostConstructed()) - occlusionState = area->GetPostConstructed()->x10dc_occlusionState; - - if (occlusionState == CGameArea::EOcclusionState::Occluded) + if (!x5d6_26_playerObstructed) { + zeus::CVector3f playerPos = mgr.GetPlayer().GetTranslation(); + float distance = (playerPos - GetTranslation()).magnitude(); + if (distance > x5c4_playerObstructionMinDist) { + zeus::CVector3f direction = (playerPos - GetTranslation()).normalized(); + CRayCastResult result = + mgr.RayStaticIntersection(playerPos, direction, distance, CMaterialFilter::skPassEverything); + if (result.IsValid()) x5d6_26_playerObstructed = true; - - if (!x5d6_26_playerObstructed) - { - zeus::CVector3f playerPos = mgr.GetPlayer().GetTranslation(); - float distance = (playerPos - GetTranslation()).magnitude(); - if (distance > x5c4_playerObstructionMinDist) - { - zeus::CVector3f direction = (playerPos - GetTranslation()).normalized(); - CRayCastResult result = mgr.RayStaticIntersection(playerPos, direction, distance, - CMaterialFilter::skPassEverything); - if (result.IsValid()) - x5d6_26_playerObstructed = true; - } } + } - if (x5d6_26_playerObstructed) - xf8_24_movable = false; + if (x5d6_26_playerObstructed) + xf8_24_movable = false; - xf8_24_movable = !x5d6_24_alignToFloor; - CWallWalker::Think(dt, mgr); + xf8_24_movable = !x5d6_24_alignToFloor; + CWallWalker::Think(dt, mgr); - if (!x5d6_25_hasAlignSurface && x450_bodyController->GetPercentageFrozen() < 0.00001f && x5d6_24_alignToFloor) - AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + (2.f * (dt * GetVelocity())), dt); + if (!x5d6_25_hasAlignSurface && x450_bodyController->GetPercentageFrozen() < 0.00001f && x5d6_24_alignToFloor) + AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + (2.f * (dt * GetVelocity())), dt); - if (x71c_attackCoolOff > 0.f) - x71c_attackCoolOff -= dt; + if (x71c_attackCoolOff > 0.f) + x71c_attackCoolOff -= dt; } -void CSeedling::Render(const CStateManager& mgr) const -{ - if (x400_25_alive && x6bc_spikeData) - { - u32 index = x722_24_renderOnlyClusterA ? 0 : u32(x722_25_curNeedleCluster); - CModelFlags flags; - flags.x2_flags = 3; - flags.x4_color = zeus::CColor::skWhite; +void CSeedling::Render(const CStateManager& mgr) const { + if (x400_25_alive && x6bc_spikeData) { + u32 index = x722_24_renderOnlyClusterA ? 0 : u32(x722_25_curNeedleCluster); + CModelFlags flags; + flags.x2_flags = 3; + flags.x4_color = zeus::CColor::skWhite; - for (const std::string& sv : skNeedleLocators[index]) - x6bc_spikeData->Render(mgr, GetLctrTransform(sv), x90_actorLights.get(), flags); - } + for (const std::string& sv : skNeedleLocators[index]) + x6bc_spikeData->Render(mgr, GetLctrTransform(sv), x90_actorLights.get(), flags); + } - CWallWalker::Render(mgr); + CWallWalker::Render(mgr); } -void CSeedling::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) -{ - if (type == EUserEventType::Projectile) - LaunchNeedles(mgr); - else if (type == EUserEventType::BeginAction) - x722_24_renderOnlyClusterA = true; - else - CPatterned::DoUserAnimEvent(mgr, node, type, dt); +void CSeedling::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + if (type == EUserEventType::Projectile) + LaunchNeedles(mgr); + else if (type == EUserEventType::BeginAction) + x722_24_renderOnlyClusterA = true; + else + CPatterned::DoUserAnimEvent(mgr, node, type, dt); } -std::experimental::optional CSeedling::GetTouchBounds() const -{ - return x704_modelBounds.getTransformedAABox(GetTransform()); +std::experimental::optional CSeedling::GetTouchBounds() const { + return x704_modelBounds.getTransformedAABox(GetTransform()); } -void CSeedling::Touch(CActor& act, CStateManager& mgr) -{ - if (x400_25_alive) - { - if (TCastToPtr pl = act) - MassiveDeath(mgr); - } +void CSeedling::Touch(CActor& act, CStateManager& mgr) { + if (x400_25_alive) { + if (TCastToPtr pl = act) + MassiveDeath(mgr); + } - CPatterned::Touch(act, mgr); + CPatterned::Touch(act, mgr); } -void CSeedling::Patrol(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); - x5d6_24_alignToFloor = true; - x150_momentum.zeroOut(); - x5d6_25_hasAlignSurface = false; - xf8_24_movable = false; +void CSeedling::Patrol(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + x5d6_24_alignToFloor = true; + x150_momentum.zeroOut(); + x5d6_25_hasAlignSurface = false; + xf8_24_movable = false; - TUniqueId id = (x720_prevObj != kInvalidUniqueId ? x720_prevObj : - GetWaypointForState(mgr, EScriptObjectState::Patrol, - EScriptObjectMessage::Follow)); + TUniqueId id = (x720_prevObj != kInvalidUniqueId + ? x720_prevObj + : GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow)); - if (id != kInvalidUniqueId) - x2dc_destObj = id; - } - else if (msg == EStateMsg::Update) - { - UpdateWPDestination(mgr); - zeus::CVector3f upVec = GetTransform().upVector(); - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCLocomotionCmd(ProjectVectorToPlane((x2e0_destPos - GetTranslation()).normalized(), upVec), {}, 0.f)); - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( - ProjectVectorToPlane(ProjectVectorToPlane(x45c_steeringBehaviors.Seek(*this, x2e0_destPos), upVec), upVec), - {}, 1.f)); - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(1.f * GetTransform().frontVector(), {}, 0.f)); - } - else if (msg == EStateMsg::Deactivate) - { - x720_prevObj = x2dc_destObj; - } + if (id != kInvalidUniqueId) + x2dc_destObj = id; + } else if (msg == EStateMsg::Update) { + UpdateWPDestination(mgr); + zeus::CVector3f upVec = GetTransform().upVector(); + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCLocomotionCmd(ProjectVectorToPlane((x2e0_destPos - GetTranslation()).normalized(), upVec), {}, 0.f)); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( + ProjectVectorToPlane(ProjectVectorToPlane(x45c_steeringBehaviors.Seek(*this, x2e0_destPos), upVec), upVec), {}, + 1.f)); + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(1.f * GetTransform().frontVector(), {}, 0.f)); + } else if (msg == EStateMsg::Deactivate) { + x720_prevObj = x2dc_destObj; + } } -void CSeedling::Active(CStateManager& mgr, EStateMsg msg, float arg) -{ - if (msg == EStateMsg::Activate) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - CPatterned::Patrol(mgr, msg, arg); +void CSeedling::Active(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + CPatterned::Patrol(mgr, msg, arg); } -void CSeedling::Enraged(CStateManager&, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal8); +void CSeedling::Enraged(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal8); } -void CSeedling::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - x32c_animState = EAnimState::One; - else if (msg == EStateMsg::Update) - TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 0); - else if (msg == EStateMsg::Deactivate) - { - x32c_animState = EAnimState::Zero; - x71c_attackCoolOff = (x300_maxAttackRange * mgr.GetActiveRandom()->Float()) + x304_averageAttackTime; - } +void CSeedling::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) + x32c_animState = EAnimState::One; + else if (msg == EStateMsg::Update) + TryCommand(mgr, pas::EAnimationState::ProjectileAttack, &CPatterned::TryProjectileAttack, 0); + else if (msg == EStateMsg::Deactivate) { + x32c_animState = EAnimState::Zero; + x71c_attackCoolOff = (x300_maxAttackRange * mgr.GetActiveRandom()->Float()) + x304_averageAttackTime; + } } -void CSeedling::Generate(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - x32c_animState = EAnimState::One; - else if (msg == EStateMsg::Update) - TryCommand(mgr, pas::EAnimationState::Generate, &CPatterned::TryGenerate, 0); +void CSeedling::Generate(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) + x32c_animState = EAnimState::One; + else if (msg == EStateMsg::Update) + TryCommand(mgr, pas::EAnimationState::Generate, &CPatterned::TryGenerate, 0); } -bool CSeedling::ShouldAttack(CStateManager& mgr, float) -{ - if (x71c_attackCoolOff > 0.f) - return false; +bool CSeedling::ShouldAttack(CStateManager& mgr, float) { + if (x71c_attackCoolOff > 0.f) + return false; - return mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, 6); + return mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, 6); } -void CSeedling::LaunchNeedles(CStateManager& mgr) -{ - for (const std::string& needle : skNeedleLocators[u32(x722_25_curNeedleCluster)]) - LaunchProjectile(GetLctrTransform(needle), mgr, 6, EProjectileAttrib::None, true, {}, 0xFFFF, false, - GetModelData()->GetScale()); +void CSeedling::LaunchNeedles(CStateManager& mgr) { + for (const std::string& needle : skNeedleLocators[u32(x722_25_curNeedleCluster)]) + LaunchProjectile(GetLctrTransform(needle), mgr, 6, EProjectileAttrib::None, true, {}, 0xFFFF, false, + GetModelData()->GetScale()); - x722_25_curNeedleCluster = !x722_25_curNeedleCluster; - x722_24_renderOnlyClusterA = false; + x722_25_curNeedleCluster = !x722_25_curNeedleCluster; + x722_24_renderOnlyClusterA = false; } -void CSeedling::MassiveDeath(CStateManager& mgr) -{ - if (x400_25_alive) - { - mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x6e8_deathDamage, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {})); - LaunchNeedles(mgr); - } - CPatterned::MassiveDeath(mgr); +void CSeedling::MassiveDeath(CStateManager& mgr) { + if (x400_25_alive) { + mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), x6e8_deathDamage, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {})); + LaunchNeedles(mgr); + } + CPatterned::MassiveDeath(mgr); } -} -} +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/World/CSeedling.hpp b/Runtime/MP1/World/CSeedling.hpp index c95f9d1c7..3a98994ed 100644 --- a/Runtime/MP1/World/CSeedling.hpp +++ b/Runtime/MP1/World/CSeedling.hpp @@ -4,46 +4,43 @@ #include "World/CPathFindSearch.hpp" #include "Weapon/CProjectileInfo.hpp" -namespace urde -{ -namespace MP1 -{ -class CSeedling : public CWallWalker -{ - static const std::string skNeedleLocators[2][6]; - CPathFindSearch x5d8_searchPath; - std::unique_ptr x6bc_spikeData; - CProjectileInfo x6c0_projectileInfo; - CDamageInfo x6e8_deathDamage; - zeus::CAABox x704_modelBounds = zeus::CAABox::skNullBox; - float x71c_attackCoolOff = 0.f; - TUniqueId x720_prevObj = kInvalidUniqueId; - bool x722_24_renderOnlyClusterA : 1; - bool x722_25_curNeedleCluster : 1; - void LaunchNeedles(CStateManager&); -public: - DEFINE_PATTERNED(Seedling) - CSeedling(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, - CModelData&&, const CPatternedInfo&, const CActorParameters&, - CAssetId, CAssetId, const CDamageInfo&, const CDamageInfo&, - float, float, float, float); +namespace urde { +namespace MP1 { +class CSeedling : public CWallWalker { + static const std::string skNeedleLocators[2][6]; + CPathFindSearch x5d8_searchPath; + std::unique_ptr x6bc_spikeData; + CProjectileInfo x6c0_projectileInfo; + CDamageInfo x6e8_deathDamage; + zeus::CAABox x704_modelBounds = zeus::CAABox::skNullBox; + float x71c_attackCoolOff = 0.f; + TUniqueId x720_prevObj = kInvalidUniqueId; + bool x722_24_renderOnlyClusterA : 1; + bool x722_25_curNeedleCluster : 1; + void LaunchNeedles(CStateManager&); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - void Render(const CStateManager&) const; - void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); - CProjectileInfo* GetProjectileInfo() { return &x6c0_projectileInfo; } - std::experimental::optional GetTouchBounds() const; - void Touch(CActor&, CStateManager&); - CPathFindSearch* GetSearchPath() { return &x5d8_searchPath; } - void Patrol(CStateManager&, EStateMsg, float); - void Active(CStateManager&, EStateMsg, float); - void Enraged(CStateManager&, EStateMsg, float); - void ProjectileAttack(CStateManager&, EStateMsg, float); - void Generate(CStateManager&, EStateMsg, float); - bool ShouldAttack(CStateManager&, float); - void MassiveDeath(CStateManager&); +public: + DEFINE_PATTERNED(Seedling) + CSeedling(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, const CActorParameters&, CAssetId, CAssetId, const CDamageInfo&, const CDamageInfo&, + float, float, float, float); + + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void Render(const CStateManager&) const; + void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); + CProjectileInfo* GetProjectileInfo() { return &x6c0_projectileInfo; } + std::experimental::optional GetTouchBounds() const; + void Touch(CActor&, CStateManager&); + CPathFindSearch* GetSearchPath() { return &x5d8_searchPath; } + void Patrol(CStateManager&, EStateMsg, float); + void Active(CStateManager&, EStateMsg, float); + void Enraged(CStateManager&, EStateMsg, float); + void ProjectileAttack(CStateManager&, EStateMsg, float); + void Generate(CStateManager&, EStateMsg, float); + bool ShouldAttack(CStateManager&, float); + void MassiveDeath(CStateManager&); }; -} -} +} // namespace MP1 +} // namespace urde diff --git a/Runtime/MP1/World/CSpacePirate.cpp b/Runtime/MP1/World/CSpacePirate.cpp index faab88f05..51cf3de7a 100644 --- a/Runtime/MP1/World/CSpacePirate.cpp +++ b/Runtime/MP1/World/CSpacePirate.cpp @@ -15,388 +15,316 @@ #include "World/CWorld.hpp" #include "TCastTo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CSpacePirate::CSpacePirateData::CSpacePirateData(urde::CInputStream& in, u32 propCount) -: x0_(in.readFloatBig()), x4_(in.readFloatBig()), x8_(in.readFloatBig()), xc_(in.readFloatBig()) -, x10_(in.readFloatBig()), x14_hearNoiseRange(in.readFloatBig()), x18_flags(in.readUint32Big()), x1c_(in.readBool()), x20_mainProjectileInfo(in) -, x48_(CSfxManager::TranslateSFXID(in.readUint32Big())), x4c_(in), x68_(in.readFloatBig()), x6c_(in) -, x94_(in.readFloatBig()), x98_ragdollThudSfx(CSfxManager::TranslateSFXID(in.readUint32Big())), x9c_averageNextShotTime(in.readFloatBig()) -, xa0_nextShotTimeVariation(in.readFloatBig()), xa4_(CSfxManager::TranslateSFXID(in.readUint32Big())), xa8_aimDelayTime(in.readFloatBig()) -, xac_firstBurstCount(in.readUint32Big()), xb0_minCloakAlpha(in.readFloatBig()), xb4_maxCloakAlpha(in.readFloatBig()), xb8_(in.readFloatBig()) -, xbc_(in.readFloatBig()), xc0_(CSfxManager::TranslateSFXID(in.readUint32Big())) -, xc2_(CSfxManager::TranslateSFXID(in.readUint32Big())), xc4_(propCount > 35 ? in.readFloatBig() : 0.2f) -, xc8_(propCount > 36 ? in.readFloatBig() : 8.f) -{} +: x0_(in.readFloatBig()) +, x4_(in.readFloatBig()) +, x8_(in.readFloatBig()) +, xc_(in.readFloatBig()) +, x10_(in.readFloatBig()) +, x14_hearNoiseRange(in.readFloatBig()) +, x18_flags(in.readUint32Big()) +, x1c_(in.readBool()) +, x20_mainProjectileInfo(in) +, x48_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x4c_(in) +, x68_(in.readFloatBig()) +, x6c_(in) +, x94_(in.readFloatBig()) +, x98_ragdollThudSfx(CSfxManager::TranslateSFXID(in.readUint32Big())) +, x9c_averageNextShotTime(in.readFloatBig()) +, xa0_nextShotTimeVariation(in.readFloatBig()) +, xa4_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xa8_aimDelayTime(in.readFloatBig()) +, xac_firstBurstCount(in.readUint32Big()) +, xb0_minCloakAlpha(in.readFloatBig()) +, xb4_maxCloakAlpha(in.readFloatBig()) +, xb8_(in.readFloatBig()) +, xbc_(in.readFloatBig()) +, xc0_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xc2_(CSfxManager::TranslateSFXID(in.readUint32Big())) +, xc4_(propCount > 35 ? in.readFloatBig() : 0.2f) +, xc8_(propCount > 36 ? in.readFloatBig() : 8.f) {} -static const std::string_view skParts[] = -{ - "Collar"sv, - "Neck_1"sv, - "R_shoulder"sv, - "R_elbow"sv, - "R_wrist"sv, - "L_shoulder"sv, - "L_elbow"sv, - "L_wrist"sv, - "R_hip"sv, - "R_knee"sv, - "R_ankle"sv, - "L_hip"sv, - "L_knee"sv, - "L_ankle"sv -}; +static const std::string_view skParts[] = {"Collar"sv, "Neck_1"sv, "R_shoulder"sv, "R_elbow"sv, "R_wrist"sv, + "L_shoulder"sv, "L_elbow"sv, "L_wrist"sv, "R_hip"sv, "R_knee"sv, + "R_ankle"sv, "L_hip"sv, "L_knee"sv, "L_ankle"sv}; -static const float skRadii[] = -{ - 0.45f, - 0.52f, - 0.35f, - 0.1f, - 0.15f, - 0.35f, - 0.1f, - 0.15f, - 0.15f, - 0.15f, - 0.15f, - 0.15f, - 0.15f, - 0.15f -}; +static const float skRadii[] = {0.45f, 0.52f, 0.35f, 0.1f, 0.15f, 0.35f, 0.1f, + 0.15f, 0.15f, 0.15f, 0.15f, 0.15f, 0.15f, 0.15f}; CPirateRagDoll::CPirateRagDoll(CStateManager& mgr, CSpacePirate* sp, u16 thudSfx, u32 flags) -: CRagDoll(-sp->GetGravityConstant(), -3.f, 8.f, flags), x6c_spacePirate(sp), x70_thudSfx(thudSfx) -{ - xb0_24_initSfx = true; - x6c_spacePirate->RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::AIBlock, - EMaterialTypes::GroundCollider, mgr); - x6c_spacePirate->HealthInfo(mgr)->SetHP(-1.f); - SetNumParticles(14); - SetNumLengthConstraints(47); - SetNumJointConstraints(4); - zeus::CVector3f scale = x6c_spacePirate->GetModelData()->GetScale(); - CAnimData* aData = x6c_spacePirate->ModelData()->AnimationData(); - aData->BuildPose(); - zeus::CVector3f center = x6c_spacePirate->GetBoundingBox().center(); - for (int i = 0; i < 14; ++i) - { - CSegId id = aData->GetLocatorSegId(skParts[i]); - AddParticle(id, center, x6c_spacePirate->GetTransform() * (aData->GetPose().GetOffset(id) * scale), - skRadii[i] * scale.z()); - } - SatisfyWorldConstraintsOnConstruction(mgr); - AddLengthConstraint(0, 1); - AddLengthConstraint(0, 2); - AddLengthConstraint(0, 8); - AddLengthConstraint(0, 11); - AddLengthConstraint(0, 5); - AddLengthConstraint(2, 3); - AddLengthConstraint(3, 4); - AddLengthConstraint(5, 6); - AddLengthConstraint(6, 7); - AddLengthConstraint(2, 5); - AddLengthConstraint(2, 8); - AddLengthConstraint(2, 11); - AddLengthConstraint(5, 8); - AddLengthConstraint(5, 11); - AddLengthConstraint(8, 11); - AddLengthConstraint(8, 9); - AddLengthConstraint(9, 10); - AddLengthConstraint(11, 12); - AddLengthConstraint(12, 13); - AddMinLengthConstraint(1, 8, x14_lengthConstraints[2].GetLength()); - AddMinLengthConstraint(1, 11, x14_lengthConstraints[3].GetLength()); - AddMinLengthConstraint(1, 2, x14_lengthConstraints[1].GetLength() * 0.9f); - AddMinLengthConstraint(1, 5, x14_lengthConstraints[4].GetLength() * 0.9f); - AddMinLengthConstraint(1, 4, x14_lengthConstraints[0].GetLength() * 2.5f); - AddMinLengthConstraint(1, 7, x14_lengthConstraints[0].GetLength() * 2.5f); - AddMinLengthConstraint(4, 2, x14_lengthConstraints[5].GetLength()); - AddMinLengthConstraint(7, 5, x14_lengthConstraints[7].GetLength()); - AddMinLengthConstraint(3, 5, x14_lengthConstraints[5].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength()); - AddMinLengthConstraint(6, 2, x14_lengthConstraints[7].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength()); - AddMinLengthConstraint(4, 5, x14_lengthConstraints[5].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength()); - AddMinLengthConstraint(7, 2, x14_lengthConstraints[7].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength()); - AddMinLengthConstraint(4, 7, x14_lengthConstraints[9].GetLength()); - AddMinLengthConstraint(4, 8, x14_lengthConstraints[14].GetLength()); - AddMinLengthConstraint(7, 11, x14_lengthConstraints[14].GetLength()); - AddMinLengthConstraint(10, 8, x14_lengthConstraints[15].GetLength()); - AddMinLengthConstraint(13, 11, x14_lengthConstraints[17].GetLength()); - AddMinLengthConstraint(9, 2, x14_lengthConstraints[15].GetLength() * 0.707f + x14_lengthConstraints[10].GetLength()); - AddMinLengthConstraint(12, 5, x14_lengthConstraints[17].GetLength() * 0.707f + x14_lengthConstraints[13].GetLength()); - AddMinLengthConstraint(9, 11, x14_lengthConstraints[15].GetLength()); - AddMinLengthConstraint(12, 8, x14_lengthConstraints[17].GetLength()); - AddMinLengthConstraint(10, 0, x14_lengthConstraints[2].GetLength() + x14_lengthConstraints[15].GetLength()); - AddMinLengthConstraint(13, 0, x14_lengthConstraints[3].GetLength() + x14_lengthConstraints[17].GetLength()); - AddMinLengthConstraint(10, 13, x14_lengthConstraints[14].GetLength()); - AddMinLengthConstraint(9, 12, x14_lengthConstraints[14].GetLength()); - AddMinLengthConstraint(10, 12, x14_lengthConstraints[14].GetLength()); - AddMinLengthConstraint(13, 9, x14_lengthConstraints[14].GetLength()); - AddMaxLengthConstraint(10, 13, x14_lengthConstraints[14].GetLength() * 5.f); - AddJointConstraint(8, 2, 5, 8, 9, 10); // R_hip, R_shoulder, L_shoulder, R_hip, R_knee, R_ankle - AddJointConstraint(11, 2, 5, 11, 12, 13); // L_hip, R_shoulder, L_shoulder, L_hip, L_knee, L_ankle - AddJointConstraint(2, 11, 5, 2, 3, 4); // R_shoulder, L_hip, L_shoulder, R_shoulder, R_elbow, R_wrist - AddJointConstraint(5, 2, 8, 5, 6, 7); // L_shoulder, R_shoulder, R_hip, L_shoulder, L_elbow, R_wrist - for (const auto& conn : x6c_spacePirate->GetConnectionList()) - { - if (conn.x0_state == EScriptObjectState::Modify && conn.x4_msg == EScriptObjectMessage::Follow) - { - TUniqueId wpId = mgr.GetIdForScript(conn.x8_objId); - if (TCastToConstPtr wp = mgr.GetObjectById(wpId)) - { - x90_waypoints.push_back(wpId); - x9c_wpParticleIdxs.push_back(wp->GetAnimation()); - if (x90_waypoints.size() == 4) - break; - } - } +: CRagDoll(-sp->GetGravityConstant(), -3.f, 8.f, flags), x6c_spacePirate(sp), x70_thudSfx(thudSfx) { + xb0_24_initSfx = true; + x6c_spacePirate->RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::AIBlock, EMaterialTypes::GroundCollider, mgr); + x6c_spacePirate->HealthInfo(mgr)->SetHP(-1.f); + SetNumParticles(14); + SetNumLengthConstraints(47); + SetNumJointConstraints(4); + zeus::CVector3f scale = x6c_spacePirate->GetModelData()->GetScale(); + CAnimData* aData = x6c_spacePirate->ModelData()->AnimationData(); + aData->BuildPose(); + zeus::CVector3f center = x6c_spacePirate->GetBoundingBox().center(); + for (int i = 0; i < 14; ++i) { + CSegId id = aData->GetLocatorSegId(skParts[i]); + AddParticle(id, center, x6c_spacePirate->GetTransform() * (aData->GetPose().GetOffset(id) * scale), + skRadii[i] * scale.z()); + } + SatisfyWorldConstraintsOnConstruction(mgr); + AddLengthConstraint(0, 1); + AddLengthConstraint(0, 2); + AddLengthConstraint(0, 8); + AddLengthConstraint(0, 11); + AddLengthConstraint(0, 5); + AddLengthConstraint(2, 3); + AddLengthConstraint(3, 4); + AddLengthConstraint(5, 6); + AddLengthConstraint(6, 7); + AddLengthConstraint(2, 5); + AddLengthConstraint(2, 8); + AddLengthConstraint(2, 11); + AddLengthConstraint(5, 8); + AddLengthConstraint(5, 11); + AddLengthConstraint(8, 11); + AddLengthConstraint(8, 9); + AddLengthConstraint(9, 10); + AddLengthConstraint(11, 12); + AddLengthConstraint(12, 13); + AddMinLengthConstraint(1, 8, x14_lengthConstraints[2].GetLength()); + AddMinLengthConstraint(1, 11, x14_lengthConstraints[3].GetLength()); + AddMinLengthConstraint(1, 2, x14_lengthConstraints[1].GetLength() * 0.9f); + AddMinLengthConstraint(1, 5, x14_lengthConstraints[4].GetLength() * 0.9f); + AddMinLengthConstraint(1, 4, x14_lengthConstraints[0].GetLength() * 2.5f); + AddMinLengthConstraint(1, 7, x14_lengthConstraints[0].GetLength() * 2.5f); + AddMinLengthConstraint(4, 2, x14_lengthConstraints[5].GetLength()); + AddMinLengthConstraint(7, 5, x14_lengthConstraints[7].GetLength()); + AddMinLengthConstraint(3, 5, x14_lengthConstraints[5].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength()); + AddMinLengthConstraint(6, 2, x14_lengthConstraints[7].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength()); + AddMinLengthConstraint(4, 5, x14_lengthConstraints[5].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength()); + AddMinLengthConstraint(7, 2, x14_lengthConstraints[7].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength()); + AddMinLengthConstraint(4, 7, x14_lengthConstraints[9].GetLength()); + AddMinLengthConstraint(4, 8, x14_lengthConstraints[14].GetLength()); + AddMinLengthConstraint(7, 11, x14_lengthConstraints[14].GetLength()); + AddMinLengthConstraint(10, 8, x14_lengthConstraints[15].GetLength()); + AddMinLengthConstraint(13, 11, x14_lengthConstraints[17].GetLength()); + AddMinLengthConstraint(9, 2, x14_lengthConstraints[15].GetLength() * 0.707f + x14_lengthConstraints[10].GetLength()); + AddMinLengthConstraint(12, 5, x14_lengthConstraints[17].GetLength() * 0.707f + x14_lengthConstraints[13].GetLength()); + AddMinLengthConstraint(9, 11, x14_lengthConstraints[15].GetLength()); + AddMinLengthConstraint(12, 8, x14_lengthConstraints[17].GetLength()); + AddMinLengthConstraint(10, 0, x14_lengthConstraints[2].GetLength() + x14_lengthConstraints[15].GetLength()); + AddMinLengthConstraint(13, 0, x14_lengthConstraints[3].GetLength() + x14_lengthConstraints[17].GetLength()); + AddMinLengthConstraint(10, 13, x14_lengthConstraints[14].GetLength()); + AddMinLengthConstraint(9, 12, x14_lengthConstraints[14].GetLength()); + AddMinLengthConstraint(10, 12, x14_lengthConstraints[14].GetLength()); + AddMinLengthConstraint(13, 9, x14_lengthConstraints[14].GetLength()); + AddMaxLengthConstraint(10, 13, x14_lengthConstraints[14].GetLength() * 5.f); + AddJointConstraint(8, 2, 5, 8, 9, 10); // R_hip, R_shoulder, L_shoulder, R_hip, R_knee, R_ankle + AddJointConstraint(11, 2, 5, 11, 12, 13); // L_hip, R_shoulder, L_shoulder, L_hip, L_knee, L_ankle + AddJointConstraint(2, 11, 5, 2, 3, 4); // R_shoulder, L_hip, L_shoulder, R_shoulder, R_elbow, R_wrist + AddJointConstraint(5, 2, 8, 5, 6, 7); // L_shoulder, R_shoulder, R_hip, L_shoulder, L_elbow, R_wrist + for (const auto& conn : x6c_spacePirate->GetConnectionList()) { + if (conn.x0_state == EScriptObjectState::Modify && conn.x4_msg == EScriptObjectMessage::Follow) { + TUniqueId wpId = mgr.GetIdForScript(conn.x8_objId); + if (TCastToConstPtr wp = mgr.GetObjectById(wpId)) { + x90_waypoints.push_back(wpId); + x9c_wpParticleIdxs.push_back(wp->GetAnimation()); + if (x90_waypoints.size() == 4) + break; + } } + } } -void CPirateRagDoll::PreRender(const zeus::CVector3f& v, CModelData& mData) -{ - if (!x68_25_over || x68_27_continueSmallMovements) - { - CAnimData* aData = mData.AnimationData(); - for (CSegId id : aData->GetCharLayoutInfo().GetSegIdList().GetList()) - if (aData->GetCharLayoutInfo().GetRootNode()->GetBoneMap()[id].x10_children.size() > 1) - aData->PoseBuilder().GetTreeMap()[id].x4_rotation = zeus::CQuaternion::skNoRotation; - CSegId rootId = aData->GetLocatorSegId("Skeleton_Root"sv); - aData->PoseBuilder().GetTreeMap()[rootId].x14_offset = - (0.5f * (x4_particles[8].GetPosition() + x4_particles[11].GetPosition()) - v) / mData.GetScale(); - zeus::CVector3f _7c = x4_particles[2].GetPosition() - x4_particles[5].GetPosition(); - zeus::CVector3f _88 = - (x4_particles[0].GetPosition() - - (x4_particles[8].GetPosition() + x4_particles[11].GetPosition()) * 0.5f).normalized(); - zeus::CVector3f _x94 = _88.cross(_7c).normalized(); - zeus::CQuaternion _a4(zeus::CMatrix3f(_x94.cross(_88), _x94, _88).transposed()); - aData->PoseBuilder().GetTreeMap()[rootId].x4_rotation = _a4; - if (x6c_spacePirate->x7b4_ == kInvalidUniqueId) - { - zeus::CVector3f _b0 = aData->GetCharLayoutInfo().GetFromParentUnrotated(x4_particles[1].GetBone()); - aData->PoseBuilder().GetTreeMap()[x4_particles[1].GetBone()] = zeus::CQuaternion::shortestRotationArc(_b0, - _a4.inverse().transform(x4_particles[1].GetPosition() - x4_particles[0].GetPosition())); - } - BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 3, 4, - _a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 2, 3, _a4)); - BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 6, 7, - _a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 5, 6, _a4)); - BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 9, 10, - _a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 8, 9, _a4)); - BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 12, 13, - _a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 11, 12, _a4)); - zeus::CQuaternion q; - q.rotateX(zeus::degToRad(-70.f)); - aData->PoseBuilder().GetTreeMap()[x4_particles[10].GetBone()].x4_rotation = q; - aData->PoseBuilder().GetTreeMap()[x4_particles[13].GetBone()].x4_rotation = q; - aData->MarkPoseDirty(); +void CPirateRagDoll::PreRender(const zeus::CVector3f& v, CModelData& mData) { + if (!x68_25_over || x68_27_continueSmallMovements) { + CAnimData* aData = mData.AnimationData(); + for (CSegId id : aData->GetCharLayoutInfo().GetSegIdList().GetList()) + if (aData->GetCharLayoutInfo().GetRootNode()->GetBoneMap()[id].x10_children.size() > 1) + aData->PoseBuilder().GetTreeMap()[id].x4_rotation = zeus::CQuaternion::skNoRotation; + CSegId rootId = aData->GetLocatorSegId("Skeleton_Root"sv); + aData->PoseBuilder().GetTreeMap()[rootId].x14_offset = + (0.5f * (x4_particles[8].GetPosition() + x4_particles[11].GetPosition()) - v) / mData.GetScale(); + zeus::CVector3f _7c = x4_particles[2].GetPosition() - x4_particles[5].GetPosition(); + zeus::CVector3f _88 = + (x4_particles[0].GetPosition() - (x4_particles[8].GetPosition() + x4_particles[11].GetPosition()) * 0.5f) + .normalized(); + zeus::CVector3f _x94 = _88.cross(_7c).normalized(); + zeus::CQuaternion _a4(zeus::CMatrix3f(_x94.cross(_88), _x94, _88).transposed()); + aData->PoseBuilder().GetTreeMap()[rootId].x4_rotation = _a4; + if (x6c_spacePirate->x7b4_ == kInvalidUniqueId) { + zeus::CVector3f _b0 = aData->GetCharLayoutInfo().GetFromParentUnrotated(x4_particles[1].GetBone()); + aData->PoseBuilder().GetTreeMap()[x4_particles[1].GetBone()] = zeus::CQuaternion::shortestRotationArc( + _b0, _a4.inverse().transform(x4_particles[1].GetPosition() - x4_particles[0].GetPosition())); } + BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 3, 4, + _a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 2, 3, _a4)); + BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 6, 7, + _a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 5, 6, _a4)); + BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 9, 10, + _a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 8, 9, _a4)); + BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 12, 13, + _a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 11, 12, _a4)); + zeus::CQuaternion q; + q.rotateX(zeus::degToRad(-70.f)); + aData->PoseBuilder().GetTreeMap()[x4_particles[10].GetBone()].x4_rotation = q; + aData->PoseBuilder().GetTreeMap()[x4_particles[13].GetBone()].x4_rotation = q; + aData->MarkPoseDirty(); + } } -void CPirateRagDoll::Update(CStateManager& mgr, float dt, float waterTop) -{ - if (!x68_25_over || x68_27_continueSmallMovements) - { - if (x6c_spacePirate->x7b4_ != kInvalidUniqueId) - { - // Shoulder height delta - float f2 = x4_particles[2].GetPosition().z() - x4_particles[5].GetPosition().z(); - if (f2 * f2 > 0.0625f) - { - zeus::CVector3f vec(0.f, 0.f, ((f2 > 0.f) ? f2 - 0.25f : f2 + 0.25f) * 0.1f); - x4_particles[2].Position() -= vec; - x4_particles[5].Position() += vec; - } - // Collar-hips height delta - f2 = x4_particles[0].GetPosition().z() - - (x4_particles[8].GetPosition().z() + x4_particles[11].GetPosition().z()) * 0.5f; - if (f2 * f2 > 0.0625f) - { - zeus::CVector3f vec(0.f, 0.f, ((f2 > 0.f) ? f2 - 0.25f : f2 + 0.25f) * 0.1f); - x4_particles[0].Position() -= vec; - x4_particles[8].Position() += vec; - x4_particles[11].Position() += vec; - } - } - // Collar-hips weighted center - zeus::CVector3f oldTorsoCenter = - x4_particles[8].GetPosition() * 0.25f + - x4_particles[11].GetPosition() * 0.25f + x4_particles[0].GetPosition() * 0.5f; - oldTorsoCenter.z() = - std::min(x4_particles[0].GetPosition().z() - x4_particles[0].GetRadius(), - std::min(x4_particles[8].GetPosition().z() - x4_particles[8].GetRadius(), - x4_particles[11].GetPosition().z() - x4_particles[11].GetRadius())); - if (oldTorsoCenter.z() < 0.5f + waterTop) - x84_torsoImpulse = x84_torsoImpulse * 1000.f; - zeus::CVector3f accDelta = x84_torsoImpulse * 0.333f * (1.f / x6c_spacePirate->GetMass()); - x4_particles[11].Velocity() += accDelta; - x4_particles[8].Velocity() += accDelta; - x4_particles[0].Velocity() += accDelta; - x84_torsoImpulse = zeus::CVector3f::skZero; - CRagDoll::Update(mgr, dt, waterTop); - auto particleIdxIt = x9c_wpParticleIdxs.begin(); - for (TUniqueId id : x90_waypoints) - { - if (const CScriptWaypoint* wp = static_cast(mgr.GetObjectById(id))) - if (wp->GetActive()) - x4_particles[*particleIdxIt].Position() = wp->GetTranslation(); - ++particleIdxIt; - } - // Collar-hips weighted center - zeus::CVector3f newTorsoCenter = - x4_particles[8].GetPosition() * 0.25f + - x4_particles[11].GetPosition() * 0.25f + x4_particles[0].GetPosition() * 0.5f; - newTorsoCenter.z() = - std::min(x4_particles[0].GetPosition().z() - x4_particles[0].GetRadius(), - std::min(x4_particles[8].GetPosition().z() - x4_particles[8].GetRadius(), - x4_particles[11].GetPosition().z() - x4_particles[11].GetRadius())); - x6c_spacePirate->SetTransform({}); - x6c_spacePirate->SetTranslation(newTorsoCenter); - x6c_spacePirate->SetVelocityWR((newTorsoCenter - oldTorsoCenter) * (1.f / dt)); - x74_sfxTimer -= dt; - if (x54_impactVel > 2.5f && x74_sfxTimer < 0.f && - (xb0_24_initSfx || (x6c_spacePirate->GetTranslation() - x78_lastSFXPos).magSquared() > 0.1f)) - { - CSfxManager::AddEmitter(x70_thudSfx, x6c_spacePirate->GetTranslation(), zeus::CVector3f::skZero, - std::min(25.f * x54_impactVel, 127.f) / 127.f, true, false, 0x7f, kInvalidAreaId); - x74_sfxTimer = mgr.GetActiveRandom()->Float() * 0.222f + 0.222f; - xb0_24_initSfx = false; - x78_lastSFXPos = x6c_spacePirate->GetTranslation(); - } +void CPirateRagDoll::Update(CStateManager& mgr, float dt, float waterTop) { + if (!x68_25_over || x68_27_continueSmallMovements) { + if (x6c_spacePirate->x7b4_ != kInvalidUniqueId) { + // Shoulder height delta + float f2 = x4_particles[2].GetPosition().z() - x4_particles[5].GetPosition().z(); + if (f2 * f2 > 0.0625f) { + zeus::CVector3f vec(0.f, 0.f, ((f2 > 0.f) ? f2 - 0.25f : f2 + 0.25f) * 0.1f); + x4_particles[2].Position() -= vec; + x4_particles[5].Position() += vec; + } + // Collar-hips height delta + f2 = x4_particles[0].GetPosition().z() - + (x4_particles[8].GetPosition().z() + x4_particles[11].GetPosition().z()) * 0.5f; + if (f2 * f2 > 0.0625f) { + zeus::CVector3f vec(0.f, 0.f, ((f2 > 0.f) ? f2 - 0.25f : f2 + 0.25f) * 0.1f); + x4_particles[0].Position() -= vec; + x4_particles[8].Position() += vec; + x4_particles[11].Position() += vec; + } } - else - { - x6c_spacePirate->SetMomentumWR(zeus::CVector3f::skZero); - x6c_spacePirate->Stop(); + // Collar-hips weighted center + zeus::CVector3f oldTorsoCenter = x4_particles[8].GetPosition() * 0.25f + x4_particles[11].GetPosition() * 0.25f + + x4_particles[0].GetPosition() * 0.5f; + oldTorsoCenter.z() = std::min(x4_particles[0].GetPosition().z() - x4_particles[0].GetRadius(), + std::min(x4_particles[8].GetPosition().z() - x4_particles[8].GetRadius(), + x4_particles[11].GetPosition().z() - x4_particles[11].GetRadius())); + if (oldTorsoCenter.z() < 0.5f + waterTop) + x84_torsoImpulse = x84_torsoImpulse * 1000.f; + zeus::CVector3f accDelta = x84_torsoImpulse * 0.333f * (1.f / x6c_spacePirate->GetMass()); + x4_particles[11].Velocity() += accDelta; + x4_particles[8].Velocity() += accDelta; + x4_particles[0].Velocity() += accDelta; + x84_torsoImpulse = zeus::CVector3f::skZero; + CRagDoll::Update(mgr, dt, waterTop); + auto particleIdxIt = x9c_wpParticleIdxs.begin(); + for (TUniqueId id : x90_waypoints) { + if (const CScriptWaypoint* wp = static_cast(mgr.GetObjectById(id))) + if (wp->GetActive()) + x4_particles[*particleIdxIt].Position() = wp->GetTranslation(); + ++particleIdxIt; } + // Collar-hips weighted center + zeus::CVector3f newTorsoCenter = x4_particles[8].GetPosition() * 0.25f + x4_particles[11].GetPosition() * 0.25f + + x4_particles[0].GetPosition() * 0.5f; + newTorsoCenter.z() = std::min(x4_particles[0].GetPosition().z() - x4_particles[0].GetRadius(), + std::min(x4_particles[8].GetPosition().z() - x4_particles[8].GetRadius(), + x4_particles[11].GetPosition().z() - x4_particles[11].GetRadius())); + x6c_spacePirate->SetTransform({}); + x6c_spacePirate->SetTranslation(newTorsoCenter); + x6c_spacePirate->SetVelocityWR((newTorsoCenter - oldTorsoCenter) * (1.f / dt)); + x74_sfxTimer -= dt; + if (x54_impactVel > 2.5f && x74_sfxTimer < 0.f && + (xb0_24_initSfx || (x6c_spacePirate->GetTranslation() - x78_lastSFXPos).magSquared() > 0.1f)) { + CSfxManager::AddEmitter(x70_thudSfx, x6c_spacePirate->GetTranslation(), zeus::CVector3f::skZero, + std::min(25.f * x54_impactVel, 127.f) / 127.f, true, false, 0x7f, kInvalidAreaId); + x74_sfxTimer = mgr.GetActiveRandom()->Float() * 0.222f + 0.222f; + xb0_24_initSfx = false; + x78_lastSFXPos = x6c_spacePirate->GetTranslation(); + } + } else { + x6c_spacePirate->SetMomentumWR(zeus::CVector3f::skZero); + x6c_spacePirate->Stop(); + } } -void CPirateRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData) -{ - const auto& aabb = x6c_spacePirate->GetBaseBoundingBox(); - zeus::CVector3f newMax = aabb.max; - newMax.z() = (aabb.max.z() - aabb.min.z()) * 0.5f + aabb.min.z(); - x6c_spacePirate->SetBoundingBox({aabb.min, newMax}); - CRagDoll::Prime(mgr, xf, mData); +void CPirateRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData) { + const auto& aabb = x6c_spacePirate->GetBaseBoundingBox(); + zeus::CVector3f newMax = aabb.max; + newMax.z() = (aabb.max.z() - aabb.min.z()) * 0.5f + aabb.min.z(); + x6c_spacePirate->SetBoundingBox({aabb.min, newMax}); + CRagDoll::Prime(mgr, xf, mData); } -const SBurst CSpacePirate::skBurstsQuick[] = -{ - {20, {3, 4, 5, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {20, {2, 3, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {20, {6, 5, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {20, {1, 2, 3, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {20, {7, 6, 5, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, +const SBurst CSpacePirate::skBurstsQuick[] = { + {20, {3, 4, 5, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {20, {2, 3, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, + {20, {6, 5, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {20, {1, 2, 3, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, + {20, {7, 6, 5, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}; +const SBurst CSpacePirate::skBurstsStandard[] = { + {15, {5, 3, 2, 1, -1, 0, 0, 0}, 0.100000, 0.050000}, {20, {1, 2, 3, 4, -1, 0, 0, 0}, 0.100000, 0.050000}, + {20, {7, 6, 5, 4, -1, 0, 0, 0}, 0.100000, 0.050000}, {15, {3, 4, 5, 6, -1, 0, 0, 0}, 0.100000, 0.050000}, + {15, {6, 5, 4, 3, -1, 0, 0, 0}, 0.100000, 0.050000}, {15, {2, 3, 4, 5, -1, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CSpacePirate::skBurstsStandard[] = -{ - {15, {5, 3, 2, 1, -1, 0, 0, 0}, 0.100000, 0.050000}, - {20, {1, 2, 3, 4, -1, 0, 0, 0}, 0.100000, 0.050000}, - {20, {7, 6, 5, 4, -1, 0, 0, 0}, 0.100000, 0.050000}, - {15, {3, 4, 5, 6, -1, 0, 0, 0}, 0.100000, 0.050000}, - {15, {6, 5, 4, 3, -1, 0, 0, 0}, 0.100000, 0.050000}, - {15, {2, 3, 4, 5, -1, 0, 0, 0}, 0.100000, 0.050000}, +const SBurst CSpacePirate::skBurstsFrenzied[] = { + {40, {1, 2, 3, 4, 5, 6, -1, 0}, 0.100000, 0.050000}, {40, {7, 6, 5, 4, 3, 2, -1, 0}, 0.100000, 0.050000}, + {10, {2, 3, 4, 5, 4, 3, -1, 0}, 0.100000, 0.050000}, {10, {6, 5, 4, 3, 4, 5, -1, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CSpacePirate::skBurstsFrenzied[] = -{ - {40, {1, 2, 3, 4, 5, 6, -1, 0}, 0.100000, 0.050000}, - {40, {7, 6, 5, 4, 3, 2, -1, 0}, 0.100000, 0.050000}, - {10, {2, 3, 4, 5, 4, 3, -1, 0}, 0.100000, 0.050000}, - {10, {6, 5, 4, 3, 4, 5, -1, 0}, 0.100000, 0.050000}, - {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, -}; -const SBurst CSpacePirate::skBurstsJumping[] = -{ +const SBurst CSpacePirate::skBurstsJumping[] = { {20, {16, 4, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {40, {5, 7, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {40, {1, 10, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CSpacePirate::skBurstsInjured[] = -{ - {15, {16, 1, 3, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {20, {3, 4, 6, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {25, {7, 5, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {25, {2, 6, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {15, {7, 5, 3, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +const SBurst CSpacePirate::skBurstsInjured[] = { + {15, {16, 1, 3, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {20, {3, 4, 6, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, + {25, {7, 5, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {25, {2, 6, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, + {15, {7, 5, 3, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CSpacePirate::skBurstsSeated[] = -{ +const SBurst CSpacePirate::skBurstsSeated[] = { {35, {7, 13, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {35, {9, 1, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {30, {16, 12, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CSpacePirate::skBurstsQuickOOV[] = -{ - {10, {16, 15, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {20, {13, 12, 10, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {30, {9, 11, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {30, {14, 10, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {10, {9, 11, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, +const SBurst CSpacePirate::skBurstsQuickOOV[] = { + {10, {16, 15, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {20, {13, 12, 10, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, + {30, {9, 11, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {30, {14, 10, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, + {10, {9, 11, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}; +const SBurst CSpacePirate::skBurstsStandardOOV[] = { + {26, {16, 8, 11, 14, -1, 0, 0, 0}, 0.100000, 0.050000}, {26, {16, 13, 11, 12, -1, 0, 0, 0}, 0.100000, 0.050000}, + {16, {9, 11, 13, 10, -1, 0, 0, 0}, 0.100000, 0.050000}, {16, {14, 13, 12, 11, -1, 0, 0, 0}, 0.100000, 0.050000}, + {8, {10, 11, 12, 13, -1, 0, 0, 0}, 0.100000, 0.050000}, {8, {6, 8, 11, 13, -1, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CSpacePirate::skBurstsStandardOOV[] = -{ - {26, {16, 8, 11, 14, -1, 0, 0, 0}, 0.100000, 0.050000}, - {26, {16, 13, 11, 12, -1, 0, 0, 0}, 0.100000, 0.050000}, - {16, {9, 11, 13, 10, -1, 0, 0, 0}, 0.100000, 0.050000}, - {16, {14, 13, 12, 11, -1, 0, 0, 0}, 0.100000, 0.050000}, - {8, {10, 11, 12, 13, -1, 0, 0, 0}, 0.100000, 0.050000}, - {8, {6, 8, 11, 13, -1, 0, 0, 0}, 0.100000, 0.050000}, +const SBurst CSpacePirate::skBurstsFrenziedOOV[] = { + {40, {1, 16, 14, 12, 10, 11, -1, 0}, 0.100000, 0.050000}, {40, {9, 11, 12, 13, 11, 7, -1, 0}, 0.100000, 0.050000}, + {10, {8, 10, 11, 12, 13, 12, -1, 0}, 0.100000, 0.050000}, {10, {15, 13, 12, 10, 12, 9, -1, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CSpacePirate::skBurstsFrenziedOOV[] = -{ - {40, {1, 16, 14, 12, 10, 11, -1, 0}, 0.100000, 0.050000}, - {40, {9, 11, 12, 13, 11, 7, -1, 0}, 0.100000, 0.050000}, - {10, {8, 10, 11, 12, 13, 12, -1, 0}, 0.100000, 0.050000}, - {10, {15, 13, 12, 10, 12, 9, -1, 0}, 0.100000, 0.050000}, - {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, -}; -const SBurst CSpacePirate::skBurstsJumpingOOV[] = -{ +const SBurst CSpacePirate::skBurstsJumpingOOV[] = { {40, {7, 13, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {40, {9, 1, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {20, {16, 12, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CSpacePirate::skBurstsInjuredOOV[] = -{ - {30, {9, 11, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {10, {13, 12, 10, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {15, {9, 11, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {15, {14, 10, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {30, {16, 15, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, - {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +const SBurst CSpacePirate::skBurstsInjuredOOV[] = { + {30, {9, 11, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {10, {13, 12, 10, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, + {15, {9, 11, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {15, {14, 10, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, + {30, {16, 15, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CSpacePirate::skBurstsSeatedOOV[] = -{ +const SBurst CSpacePirate::skBurstsSeatedOOV[] = { {35, {7, 13, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {35, {9, 1, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {30, {16, 12, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst* CSpacePirate::skBursts[] = -{ - skBurstsQuick, - skBurstsStandard, - skBurstsFrenzied, - skBurstsJumping, - skBurstsInjured, - skBurstsSeated, - skBurstsQuickOOV, - skBurstsStandardOOV, - skBurstsFrenziedOOV, - skBurstsJumpingOOV, - skBurstsInjuredOOV, - skBurstsSeatedOOV, - nullptr -}; +const SBurst* CSpacePirate::skBursts[] = {skBurstsQuick, + skBurstsStandard, + skBurstsFrenzied, + skBurstsJumping, + skBurstsInjured, + skBurstsSeated, + skBurstsQuickOOV, + skBurstsStandardOOV, + skBurstsFrenziedOOV, + skBurstsJumpingOOV, + skBurstsInjuredOOV, + skBurstsSeatedOOV, + nullptr}; std::list CSpacePirate::mChargePlayerList; @@ -405,1223 +333,863 @@ CSpacePirate::CSpacePirate(TUniqueId uid, std::string_view name, const CEntityIn CInputStream& in, u32 propCount) : CPatterned(ECharacter::SpacePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant::Medium) -, x568_pirateData(in, propCount), x660_pathFindSearch(nullptr, 0x1, pInfo.GetPathfindingIndex(), 1.f, 1.f), - x750_initialHP(pInfo.GetHealthInfo().GetHP()), - x764_boneTracking(*x64_modelData->AnimationData(), "Head_1"sv, 1.22173f, 3.14159f, false), - x7c4_burstFire(skBursts, x568_pirateData.xac_firstBurstCount), - x8b8_minCloakAlpha(x568_pirateData.xb0_minCloakAlpha), x8bc_maxCloakAlpha(x568_pirateData.xb4_maxCloakAlpha), - x8c0_(x568_pirateData.xb8_), x8c4_aimDelayTimer(x568_pirateData.xa8_aimDelayTime) -{ - x634_24_pendingAmbush = bool(x568_pirateData.x18_flags & 0x1); - x634_25_ceilingAmbush = bool(x568_pirateData.x18_flags & 0x2); - x634_26_ = bool(x568_pirateData.x18_flags & 0x4); - x634_27_melee = bool(x568_pirateData.x18_flags & 0x8); - x634_28_ = bool(x568_pirateData.x18_flags & 0x10); - x634_29_onlyAttackInRange = bool(x568_pirateData.x18_flags & 0x20); - x634_30_ = bool(x568_pirateData.x18_flags & 0x40); - x634_31_ = bool(x568_pirateData.x18_flags & 0x80); - x635_24_ = bool(x568_pirateData.x18_flags & 0x200); - x635_25_ = bool(x568_pirateData.x18_flags & 0x400); - x635_26_ = bool(x568_pirateData.x18_flags & 0x1000); - x635_27_shadowPirate = bool(x568_pirateData.x18_flags & 0x2000); - x635_28_ = bool(x568_pirateData.x18_flags & 0x4000); - x635_29_ = bool(x568_pirateData.x18_flags & 0x8000); - x635_30_floatingCorpse = bool(x568_pirateData.x18_flags & 0x10000); - x635_31_ragdollNoAiCollision = bool(x568_pirateData.x18_flags & 0x20000); - x636_24_trooper = bool(x568_pirateData.x18_flags & 0x40000); +, x568_pirateData(in, propCount) +, x660_pathFindSearch(nullptr, 0x1, pInfo.GetPathfindingIndex(), 1.f, 1.f) +, x750_initialHP(pInfo.GetHealthInfo().GetHP()) +, x764_boneTracking(*x64_modelData->AnimationData(), "Head_1"sv, 1.22173f, 3.14159f, false) +, x7c4_burstFire(skBursts, x568_pirateData.xac_firstBurstCount) +, x8b8_minCloakAlpha(x568_pirateData.xb0_minCloakAlpha) +, x8bc_maxCloakAlpha(x568_pirateData.xb4_maxCloakAlpha) +, x8c0_(x568_pirateData.xb8_) +, x8c4_aimDelayTimer(x568_pirateData.xa8_aimDelayTime) { + x634_24_pendingAmbush = bool(x568_pirateData.x18_flags & 0x1); + x634_25_ceilingAmbush = bool(x568_pirateData.x18_flags & 0x2); + x634_26_ = bool(x568_pirateData.x18_flags & 0x4); + x634_27_melee = bool(x568_pirateData.x18_flags & 0x8); + x634_28_ = bool(x568_pirateData.x18_flags & 0x10); + x634_29_onlyAttackInRange = bool(x568_pirateData.x18_flags & 0x20); + x634_30_ = bool(x568_pirateData.x18_flags & 0x40); + x634_31_ = bool(x568_pirateData.x18_flags & 0x80); + x635_24_ = bool(x568_pirateData.x18_flags & 0x200); + x635_25_ = bool(x568_pirateData.x18_flags & 0x400); + x635_26_ = bool(x568_pirateData.x18_flags & 0x1000); + x635_27_shadowPirate = bool(x568_pirateData.x18_flags & 0x2000); + x635_28_ = bool(x568_pirateData.x18_flags & 0x4000); + x635_29_ = bool(x568_pirateData.x18_flags & 0x8000); + x635_30_floatingCorpse = bool(x568_pirateData.x18_flags & 0x10000); + x635_31_ragdollNoAiCollision = bool(x568_pirateData.x18_flags & 0x20000); + x636_24_trooper = bool(x568_pirateData.x18_flags & 0x40000); - x758_headSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("Head_1"sv); - x7b6_gunSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_gun_LCTR"sv); - x7b7_elbowSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_elbow"sv); - x7b8_wristSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_wrist"sv); - x7b9_swooshSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("Swoosh_LCTR"sv); + x758_headSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("Head_1"sv); + x7b6_gunSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_gun_LCTR"sv); + x7b7_elbowSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_elbow"sv); + x7b8_wristSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_wrist"sv); + x7b9_swooshSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("Swoosh_LCTR"sv); - if (!x634_29_onlyAttackInRange) - { - x7a4_intoJumpDist = GetAnimationDistance(CPASAnimParmData(13, - CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(0))); - x848_dodgeDist = GetAnimationDistance(CPASAnimParmData(3, - CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(1))); - x84c_breakDodgeDist = GetAnimationDistance(CPASAnimParmData(3, - CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(2))); - } - else - { - x450_bodyController->BodyStateInfo().SetLocoAnimChangeAtEndOfAnimOnly(true); - } + if (!x634_29_onlyAttackInRange) { + x7a4_intoJumpDist = + GetAnimationDistance(CPASAnimParmData(13, CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(0))); + x848_dodgeDist = GetAnimationDistance(CPASAnimParmData(3, CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(1))); + x84c_breakDodgeDist = + GetAnimationDistance(CPASAnimParmData(3, CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(2))); + } else { + x450_bodyController->BodyStateInfo().SetLocoAnimChangeAtEndOfAnimOnly(true); + } - const auto& baseAABB = GetBaseBoundingBox(); - x7a8_ = (baseAABB.max.z() - baseAABB.min.z()) * 0.6f; + const auto& baseAABB = GetBaseBoundingBox(); + x7a8_ = (baseAABB.max.z() - baseAABB.min.z()) * 0.6f; - if (x90_actorLights) - x90_actorLights->SetAmbienceGenerated(false); + if (x90_actorLights) + x90_actorLights->SetAmbienceGenerated(false); - x460_knockBackController.sub80233d40(3, 3.f, FLT_MAX); - x460_knockBackController.SetLocomotionDuringElectrocution(true); + x460_knockBackController.sub80233d40(3, 3.f, FLT_MAX); + x460_knockBackController.SetLocomotionDuringElectrocution(true); - if (x634_29_onlyAttackInRange) - x460_knockBackController.SetKnockBackVariant(EKnockBackVariant::Small); - else if (x636_24_trooper && GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Plasma), false)) - x460_knockBackController.SetKnockBackVariant(EKnockBackVariant::Large); + if (x634_29_onlyAttackInRange) + x460_knockBackController.SetKnockBackVariant(EKnockBackVariant::Small); + else if (x636_24_trooper && GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Plasma), false)) + x460_knockBackController.SetKnockBackVariant(EKnockBackVariant::Large); - if (!x450_bodyController->HasBodyState(pas::EAnimationState::AdditiveAim)) - x634_27_melee = true; + if (!x450_bodyController->HasBodyState(pas::EAnimationState::AdditiveAim)) + x634_27_melee = true; - if (x636_24_trooper) - { - if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Plasma), false)) - x8cc_trooperColor = zeus::CColor(0.996f, 0.f, 0.157f, 1.f); - else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Ice), false)) - x8cc_trooperColor = zeus::CColor::skWhite; - else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Power), false)) - x8cc_trooperColor = zeus::CColor(0.992f, 0.937f, 0.337f, 1.f); - else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Wave), false)) - x8cc_trooperColor = zeus::CColor(0.776f, 0.054f, 1.f, 1.f); - } + if (x636_24_trooper) { + if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Plasma), false)) + x8cc_trooperColor = zeus::CColor(0.996f, 0.f, 0.157f, 1.f); + else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Ice), false)) + x8cc_trooperColor = zeus::CColor::skWhite; + else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Power), false)) + x8cc_trooperColor = zeus::CColor(0.992f, 0.937f, 0.337f, 1.f); + else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Wave), false)) + x8cc_trooperColor = zeus::CColor(0.776f, 0.054f, 1.f, 1.f); + } } -void CSpacePirate::Accept(IVisitor &visitor) -{ - visitor.Visit(this); -} +void CSpacePirate::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CSpacePirate::UpdateCloak(float dt, CStateManager& mgr) -{ - if (x635_27_shadowPirate) - { +void CSpacePirate::UpdateCloak(float dt, CStateManager& mgr) { + if (x635_27_shadowPirate) { + if (x400_25_alive) { + if (x8a8_cloakDelayTimer > 0.f) { + x8a8_cloakDelayTimer -= dt; + if (x8a8_cloakDelayTimer <= 0.f) + x3e8_alphaDelta = -0.4f; + } + } else { + x8b8_minCloakAlpha = 0.f; + x8bc_maxCloakAlpha = 1.f; + } + + if (x8ac_electricParticleTimer > 0.f) { + x8ac_electricParticleTimer -= dt; + if (x8ac_electricParticleTimer <= 0.f && !x450_bodyController->IsElectrocuting()) + mgr.GetActorModelParticles()->StopElectric(*this); + } + + if (x450_bodyController->IsFrozen()) + x3e8_alphaDelta = 2.f; + + if (x3e8_alphaDelta < 0.f && x42c_color.a() < x8b8_minCloakAlpha) { + x42c_color.a() = x8b8_minCloakAlpha; + x3e8_alphaDelta = 0.f; + RemoveMaterial(EMaterialTypes::Target, mgr); + } + + if (x3e8_alphaDelta > 0.f && x42c_color.a() > x8bc_maxCloakAlpha) { + x42c_color.a() = x8bc_maxCloakAlpha; + AddMaterial(EMaterialTypes::Target, mgr); + } + + x8b0_cloakStepTime -= dt; + if (x8b0_cloakStepTime < 0.f) { + x8b0_cloakStepTime = (1.f - mgr.GetActiveRandom()->Float()) * 0.08f; + if (x3e8_alphaDelta < 0.f) { + x8b4_shadowPirateAlpha = x42c_color.a(); if (x400_25_alive) - { - if (x8a8_cloakDelayTimer > 0.f) - { - x8a8_cloakDelayTimer -= dt; - if (x8a8_cloakDelayTimer <= 0.f) - x3e8_alphaDelta = -0.4f; - } - } - else - { - x8b8_minCloakAlpha = 0.f; - x8bc_maxCloakAlpha = 1.f; - } - - if (x8ac_electricParticleTimer > 0.f) - { - x8ac_electricParticleTimer -= dt; - if (x8ac_electricParticleTimer <= 0.f && !x450_bodyController->IsElectrocuting()) - mgr.GetActorModelParticles()->StopElectric(*this); - } - - if (x450_bodyController->IsFrozen()) - x3e8_alphaDelta = 2.f; - - if (x3e8_alphaDelta < 0.f && x42c_color.a() < x8b8_minCloakAlpha) - { - x42c_color.a() = x8b8_minCloakAlpha; - x3e8_alphaDelta = 0.f; - RemoveMaterial(EMaterialTypes::Target, mgr); - } - - if (x3e8_alphaDelta > 0.f && x42c_color.a() > x8bc_maxCloakAlpha) - { - x42c_color.a() = x8bc_maxCloakAlpha; - AddMaterial(EMaterialTypes::Target, mgr); - } - - x8b0_cloakStepTime -= dt; - if (x8b0_cloakStepTime < 0.f) - { - x8b0_cloakStepTime = (1.f - mgr.GetActiveRandom()->Float()) * 0.08f; - if (x3e8_alphaDelta < 0.f) - { - x8b4_shadowPirateAlpha = x42c_color.a(); - if (x400_25_alive) - x8b4_shadowPirateAlpha -= (x42c_color.a() - x8b8_minCloakAlpha) * x8b0_cloakStepTime; - } - else if (x3e8_alphaDelta > 0.f) - { - x8b4_shadowPirateAlpha = x42c_color.a() + x8b0_cloakStepTime * (x8bc_maxCloakAlpha - x42c_color.a()); - } - else - { - x8b4_shadowPirateAlpha = x42c_color.a(); - } - } + x8b4_shadowPirateAlpha -= (x42c_color.a() - x8b8_minCloakAlpha) * x8b0_cloakStepTime; + } else if (x3e8_alphaDelta > 0.f) { + x8b4_shadowPirateAlpha = x42c_color.a() + x8b0_cloakStepTime * (x8bc_maxCloakAlpha - x42c_color.a()); + } else { + x8b4_shadowPirateAlpha = x42c_color.a(); + } } + } } -bool CSpacePirate::ShouldFrenzy(CStateManager& mgr) -{ - bool reset = false; - if (x638_24_pendingFrenzyChance) - { - x638_24_pendingFrenzyChance = false; - if (mgr.GetActiveRandom()->Next() % 100 < 25) - reset = true; +bool CSpacePirate::ShouldFrenzy(CStateManager& mgr) { + bool reset = false; + if (x638_24_pendingFrenzyChance) { + x638_24_pendingFrenzyChance = false; + if (mgr.GetActiveRandom()->Next() % 100 < 25) + reset = true; + } + + if (!mChargePlayerList.empty()) + reset = true; + + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) + reset = true; + + if (HealthInfo(mgr)->GetHP() < 0.3f * x750_initialHP && mgr.GetActiveRandom()->Next() % 100 < 60 && + x854_lowHealthFrenzyTimer < 0.5f) + reset = true; + + if (reset) + x63c_frenzyFrames = mgr.GetActiveRandom()->Range(2, 4); + x63c_frenzyFrames -= 1; + return x63c_frenzyFrames >= 0; +} + +void CSpacePirate::ResetTeamAiRole(CStateManager& mgr) { + CTeamAiMgr::ResetTeamAiRole(!x634_27_melee ? CTeamAiMgr::EAttackType::Projectile : CTeamAiMgr::EAttackType::Melee, + mgr, x8c8_teamAiMgrId, GetUniqueId(), true); +} + +void CSpacePirate::AssignTeamAiRole(CStateManager& mgr) { + if (x8c8_teamAiMgrId == kInvalidUniqueId) + x8c8_teamAiMgrId = CTeamAiMgr::GetTeamAiMgr(*this, mgr); + if (x8c8_teamAiMgrId != kInvalidUniqueId) { + if (TCastToPtr aimgr = mgr.ObjectById(x8c8_teamAiMgrId)) { + aimgr->AssignTeamAiRole(*this, + x634_27_melee ? CTeamAiRole::ETeamAiRole::Melee : CTeamAiRole::ETeamAiRole::Projectile, + CTeamAiRole::ETeamAiRole::Unknown, CTeamAiRole::ETeamAiRole::Invalid); } - - if (!mChargePlayerList.empty()) - reset = true; - - if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) - reset = true; - - if (HealthInfo(mgr)->GetHP() < 0.3f * x750_initialHP && - mgr.GetActiveRandom()->Next() % 100 < 60 && x854_lowHealthFrenzyTimer < 0.5f) - reset = true; - - if (reset) - x63c_frenzyFrames = mgr.GetActiveRandom()->Range(2, 4); - x63c_frenzyFrames -= 1; - return x63c_frenzyFrames >= 0; + } } -void CSpacePirate::ResetTeamAiRole(CStateManager& mgr) -{ - CTeamAiMgr::ResetTeamAiRole(!x634_27_melee ? CTeamAiMgr::EAttackType::Projectile : - CTeamAiMgr::EAttackType::Melee, - mgr, x8c8_teamAiMgrId, GetUniqueId(), true); -} - -void CSpacePirate::AssignTeamAiRole(CStateManager& mgr) -{ - if (x8c8_teamAiMgrId == kInvalidUniqueId) - x8c8_teamAiMgrId = CTeamAiMgr::GetTeamAiMgr(*this, mgr); - if (x8c8_teamAiMgrId != kInvalidUniqueId) - { - if (TCastToPtr aimgr = mgr.ObjectById(x8c8_teamAiMgrId)) - { - aimgr->AssignTeamAiRole(*this, x634_27_melee ? CTeamAiRole::ETeamAiRole::Melee : - CTeamAiRole::ETeamAiRole::Projectile, CTeamAiRole::ETeamAiRole::Unknown, CTeamAiRole::ETeamAiRole::Invalid); - } +void CSpacePirate::RemoveTeamAiRole(CStateManager& mgr) { + if (x8c8_teamAiMgrId != kInvalidUniqueId) { + if (TCastToPtr aimgr = mgr.ObjectById(x8c8_teamAiMgrId)) { + if (aimgr->IsPartOfTeam(GetUniqueId())) { + aimgr->RemoveTeamAiRole(GetUniqueId()); + x8c8_teamAiMgrId = kInvalidUniqueId; + } } + } } -void CSpacePirate::RemoveTeamAiRole(CStateManager& mgr) -{ - if (x8c8_teamAiMgrId != kInvalidUniqueId) - { - if (TCastToPtr aimgr = mgr.ObjectById(x8c8_teamAiMgrId)) - { - if (aimgr->IsPartOfTeam(GetUniqueId())) - { - aimgr->RemoveTeamAiRole(GetUniqueId()); - x8c8_teamAiMgrId = kInvalidUniqueId; - } - } - } +bool CSpacePirate::CheckTargetable(CStateManager& mgr) { return GetModelAlphau8(mgr) > 127; } + +void CSpacePirate::FireProjectile(float dt, CStateManager& mgr) { + zeus::CTransform gunXf = GetLctrTransform(x7b6_gunSeg); + if (!x400_25_alive) { + LaunchProjectile(gunXf, mgr, 6, EProjectileAttrib::None, false, {}, 0xffff, false, zeus::CVector3f::skOne); + } } -bool CSpacePirate::CheckTargetable(CStateManager& mgr) -{ - return GetModelAlphau8(mgr) > 127; -} +void CSpacePirate::UpdateAttacks(float dt, CStateManager& mgr) { + bool reset = true; + if ((!x400_25_alive || + (x450_bodyController->GetBodyStateInfo().GetCurrentState()->CanShoot() && x637_29_ && !x634_27_melee && + !x634_25_ceilingAmbush && !x639_26_started && !x450_bodyController->IsElectrocuting())) && + x7c4_burstFire.GetBurstType() != -1) { + if (x400_25_alive) { + if (!x634_29_onlyAttackInRange || + (mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < x3c8_leashRadius * x3c8_leashRadius) { + reset = false; + x7bc_ -= dt; + if (x7bc_ < 0.f) { + const CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x8c8_teamAiMgrId, GetUniqueId()); + if (!role || role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Projectile) { + if (x8c8_teamAiMgrId == kInvalidUniqueId || + CTeamAiMgr::AddAttacker(CTeamAiMgr::EAttackType::Projectile, mgr, x8c8_teamAiMgrId, GetUniqueId())) { + if (ShouldFrenzy(mgr)) + x7c4_burstFire.SetBurstType(2); + if (x635_26_) + x7c4_burstFire.SetBurstType(5); + if (!PlayerSpot(mgr, 0.f) && x7c4_burstFire.GetBurstType() < 6) + x7c4_burstFire.SetBurstType(x7c4_burstFire.GetBurstType() + 6); -void CSpacePirate::FireProjectile(float dt, CStateManager& mgr) -{ - zeus::CTransform gunXf = GetLctrTransform(x7b6_gunSeg); - if (!x400_25_alive) - { - LaunchProjectile(gunXf, mgr, 6, EProjectileAttrib::None, false, {}, 0xffff, - false, zeus::CVector3f::skOne); - } -} - -void CSpacePirate::UpdateAttacks(float dt, CStateManager& mgr) -{ - bool reset = true; - if ((!x400_25_alive || (x450_bodyController->GetBodyStateInfo().GetCurrentState()->CanShoot() && - x637_29_ && !x634_27_melee && !x634_25_ceilingAmbush && !x639_26_started && - !x450_bodyController->IsElectrocuting())) && x7c4_burstFire.GetBurstType() != -1) - { - if (x400_25_alive) - { - if (!x634_29_onlyAttackInRange || (mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < - x3c8_leashRadius * x3c8_leashRadius) - { - reset = false; - x7bc_ -= dt; - if (x7bc_ < 0.f) - { - const CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x8c8_teamAiMgrId, GetUniqueId()); - if (!role || role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Projectile) - { - if (x8c8_teamAiMgrId == kInvalidUniqueId || - CTeamAiMgr::AddAttacker(CTeamAiMgr::EAttackType::Projectile, mgr, - x8c8_teamAiMgrId, GetUniqueId())) - { - if (ShouldFrenzy(mgr)) - x7c4_burstFire.SetBurstType(2); - if (x635_26_) - x7c4_burstFire.SetBurstType(5); - if (!PlayerSpot(mgr, 0.f) && x7c4_burstFire.GetBurstType() < 6) - x7c4_burstFire.SetBurstType(x7c4_burstFire.GetBurstType() + 6); - - x7c4_burstFire.Start(mgr); - x7bc_ = mgr.GetActiveRandom()->Float() * x308_attackTimeVariation + x304_averageAttackTime; - if ((GetGunEyePos() - mgr.GetPlayer().GetAimPosition(mgr, 0.f)).normalized(). - dot(mgr.GetPlayer().GetTransform().basis[1]) < 0.9f) - { - for (CEntity* ent : mgr.GetListeningAiObjectList()) - { - if (CSpacePirate* otherPirate = CPatterned::CastTo(ent)) - { - if (otherPirate != this && otherPirate->x637_25_ && - otherPirate->GetAreaIdAlways() == GetAreaIdAlways()) - x7bc_ += 0.2f; - } - } - } - } - } + x7c4_burstFire.Start(mgr); + x7bc_ = mgr.GetActiveRandom()->Float() * x308_attackTimeVariation + x304_averageAttackTime; + if ((GetGunEyePos() - mgr.GetPlayer().GetAimPosition(mgr, 0.f)) + .normalized() + .dot(mgr.GetPlayer().GetTransform().basis[1]) < 0.9f) { + for (CEntity* ent : mgr.GetListeningAiObjectList()) { + if (CSpacePirate* otherPirate = CPatterned::CastTo(ent)) { + if (otherPirate != this && otherPirate->x637_25_ && + otherPirate->GetAreaIdAlways() == GetAreaIdAlways()) + x7bc_ += 0.2f; + } } + } } + } } - - x7c4_burstFire.Update(mgr, dt); - - if (x7c4_burstFire.ShouldFire()) - { - if (mgr.GetPlayer().IsSidewaysDashing() && mgr.GetActiveRandom()->Float() < 0.5f) - x7c4_burstFire.SetAvoidAccuracy(true); - FireProjectile(dt, mgr); - x7c4_burstFire.SetAvoidAccuracy(false); - float nextShotTime = - x568_pirateData.xa0_nextShotTimeVariation * - (mgr.GetActiveRandom()->Float() - 0.5f) + x568_pirateData.x9c_averageNextShotTime; - if (x7c4_burstFire.GetTimeToNextShot() > 0.f) - x7c4_burstFire.SetTimeToNextShot(nextShotTime); - } - else if (!x7c4_burstFire.IsBurstSet()) - { - reset = true; - } + } } - if (reset) - ResetTeamAiRole(mgr); + x7c4_burstFire.Update(mgr, dt); - xe7_31_targetable = CheckTargetable(mgr); + if (x7c4_burstFire.ShouldFire()) { + if (mgr.GetPlayer().IsSidewaysDashing() && mgr.GetActiveRandom()->Float() < 0.5f) + x7c4_burstFire.SetAvoidAccuracy(true); + FireProjectile(dt, mgr); + x7c4_burstFire.SetAvoidAccuracy(false); + float nextShotTime = x568_pirateData.xa0_nextShotTimeVariation * (mgr.GetActiveRandom()->Float() - 0.5f) + + x568_pirateData.x9c_averageNextShotTime; + if (x7c4_burstFire.GetTimeToNextShot() > 0.f) + x7c4_burstFire.SetTimeToNextShot(nextShotTime); + } else if (!x7c4_burstFire.IsBurstSet()) { + reset = true; + } + } + + if (reset) + ResetTeamAiRole(mgr); + + xe7_31_targetable = CheckTargetable(mgr); } -zeus::CVector3f CSpacePirate::GetTargetPos(CStateManager& mgr) -{ - if (x7c0_targetId != mgr.GetPlayer().GetUniqueId()) - { - if (TCastToConstPtr act = mgr.GetObjectById(x7c0_targetId)) - if (act->GetActive()) - return act->GetTranslation(); +zeus::CVector3f CSpacePirate::GetTargetPos(CStateManager& mgr) { + if (x7c0_targetId != mgr.GetPlayer().GetUniqueId()) { + if (TCastToConstPtr act = mgr.GetObjectById(x7c0_targetId)) + if (act->GetActive()) + return act->GetTranslation(); + x764_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); + x7c0_targetId = mgr.GetPlayer().GetUniqueId(); + } + return mgr.GetPlayer().GetTranslation(); +} + +void CSpacePirate::UpdateAimBodyState(float dt, CStateManager& mgr) { + if (x400_25_alive && x637_25_ && !x637_29_ && !x450_bodyController->IsFrozen() && !x634_27_melee && !x85c_ragDoll && + (!x635_26_ || x639_28_) && x31c_faceVec.z() <= 0.f) { + x8c4_aimDelayTimer = std::max(0.f, x8c4_aimDelayTimer - dt); + if (x8c4_aimDelayTimer == 0.f) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCAdditiveAimCmd()); + x450_bodyController->GetCommandMgr().DeliverAdditiveTargetVector( + x34_transform.transposeRotate(GetTargetPos(mgr) - GetTranslation())); + } + } else if (x637_25_ && !x634_27_melee) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::AdditiveIdle)); + } +} + +void CSpacePirate::SetCinematicCollision(CStateManager& mgr) { + RemoveMaterial(EMaterialTypes::AIBlock, mgr); + CMaterialFilter filter = GetMaterialFilter(); + filter.IncludeList().Remove(EMaterialTypes::AIBlock); + SetMaterialFilter(filter); +} + +void CSpacePirate::SetNonCinematicCollision(CStateManager& mgr) { + AddMaterial(EMaterialTypes::AIBlock, mgr); + CMaterialFilter filter = GetMaterialFilter(); + filter.IncludeList().Add(EMaterialTypes::AIBlock); + SetMaterialFilter(filter); +} + +void CSpacePirate::CheckForProjectiles(CStateManager& mgr) { + if (x637_26_hearPlayerFire) { + zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + zeus::CAABox aabb(aimPos - 5.f, aimPos + 5.f); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, aabb, CMaterialFilter::MakeInclude({EMaterialTypes::Projectile}), nullptr); + for (TUniqueId id : nearList) { + if (TCastToConstPtr proj = mgr.GetObjectById(id)) { + zeus::CVector3f delta = GetBoundingBox().center() - proj->GetTranslation(); + if (delta.isMagnitudeSafe()) { + if (x34_transform.basis[1].dot(delta) < 0.f) { + delta.normalize(); + zeus::CVector3f projDelta = proj->GetTranslation() - proj->GetPreviousPos(); + if (projDelta.isMagnitudeSafe()) { + projDelta.normalize(); + if (projDelta.dot(delta) > 0.939f) + x637_27_inProjectilePath = true; + } + } + } else { + x637_27_inProjectilePath = true; + } + if (x637_27_inProjectilePath) + break; + } + } + x637_26_hearPlayerFire = false; + } +} + +void CSpacePirate::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; + + if (!x450_bodyController->GetActive()) + x450_bodyController->Activate(mgr); + + bool inCineCam = mgr.GetCameraManager()->IsInCinematicCamera(); + if (inCineCam && !x637_31_prevInCineCam) + SetCinematicCollision(mgr); + else if (!inCineCam && x637_31_prevInCineCam && !x635_31_ragdollNoAiCollision) + SetNonCinematicCollision(mgr); + x637_31_prevInCineCam = inCineCam; + + float steeringSpeed = x748_ == 0.f ? x644_ : 0.f; + x450_bodyController->GetCommandMgr().SetSteeringSpeedRange(steeringSpeed, steeringSpeed); + + x744_ = std::max(x744_ - dt, 0.f); + + if (x400_25_alive) { + x850_timeSinceHitByPlayer += dt; + x854_lowHealthFrenzyTimer += dt; + if (x637_27_inProjectilePath) { + x854_lowHealthFrenzyTimer = 0.f; + x637_27_inProjectilePath = false; + } + if (x400_24_hitByPlayerProjectile) { + x850_timeSinceHitByPlayer = 0.f; + x400_24_hitByPlayerProjectile = false; + } + } + + UpdateCloak(dt, mgr); + + if (!x450_bodyController->IsFrozen()) { + if (x400_25_alive) { + x748_ = std::max(x748_ - dt, 0.f); + if (x637_28_) + x7ac_ += dt; + else + x7ac_ = 0.f; + x838_ = std::max(x838_ - dt, 0.f); + x8c0_ = std::max(x8c0_ - dt, 0.f); + CheckForProjectiles(mgr); + } + UpdateAttacks(dt, mgr); + UpdateAimBodyState(dt, mgr); + x860_ikChain.Update(dt); + } + + if (x634_24_pendingAmbush) { + x634_24_pendingAmbush = false; + if (x634_25_ceilingAmbush) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal6); + else + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); + x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Ambushing"sv); + } + + if (!x85c_ragDoll || !x85c_ragDoll->IsPrimed()) { + CPatterned::Think(dt, mgr); + if (!x450_bodyController->IsFrozen()) + x764_boneTracking.Update(dt); + } else { + UpdateAlphaDelta(dt, mgr); + UpdateDamageColor(dt); + if (CSfxHandle hnd = GetSfxHandle()) + CSfxManager::UpdateEmitter(hnd, GetTranslation(), zeus::CVector3f::skZero, 1.f); + } + if (x85c_ragDoll) { + if (!x85c_ragDoll->IsPrimed()) { + x85c_ragDoll->Prime(mgr, GetTransform(), *x64_modelData); + zeus::CVector3f trans = GetTranslation(); + SetTransform({}); + SetTranslation(trans); + x450_bodyController->SetPlaybackRate(0.f); + } else { + float waterTop = -FLT_MAX; + if (xc4_fluidId != kInvalidUniqueId) + if (TCastToConstPtr water = mgr.GetObjectById(xc4_fluidId)) + if (water->GetActive()) + waterTop = water->GetTriggerBoundsWR().max.z(); + x85c_ragDoll->Update(mgr, dt * CalcDyingThinkRate(), waterTop); + x64_modelData->AdvanceParticles(x34_transform, dt, mgr); + } + if (x85c_ragDoll->IsOver() && !x85c_ragDoll->WillContinueSmallMovements() && !x400_27_fadeToDeath) { + /* Ragdoll has finished animating */ + x400_27_fadeToDeath = true; + AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); + x3e8_alphaDelta = -0.333333f; + x638_30_ragdollOver = true; + SetMomentumWR(zeus::CVector3f::skZero); + CPhysicsActor::Stop(); + } + } + if (x858_ragdollDelayTimer > 0.f) { + x858_ragdollDelayTimer -= dt; + if (x858_ragdollDelayTimer <= 0.f) { + if (!x85c_ragDoll) { + x85c_ragDoll = + std::make_unique(mgr, this, x568_pirateData.x98_ragdollThudSfx, + (x635_30_floatingCorpse ? 3 : 0) | (x635_31_ragdollNoAiCollision ? 4 : 0)); + RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); + } + x858_ragdollDelayTimer = 0.f; + } + } +} + +void CSpacePirate::SetEyeParticleActive(CStateManager& mgr, bool active) { + if (!x636_24_trooper) { + if (!x634_29_onlyAttackInRange || x635_26_) { + if (!x635_27_shadowPirate) + x64_modelData->AnimationData()->SetParticleEffectState("TwoEyes"sv, active, mgr); + } else { + x64_modelData->AnimationData()->SetParticleEffectState("OneEye"sv, active, mgr); + } + } +} + +void CSpacePirate::SetVelocityForJump() {} + +void CSpacePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + if (x637_29_ || x634_25_ceilingAmbush) { + switch (msg) { + case EScriptObjectMessage::Falling: + if (!x637_29_ || x450_bodyController->GetCurrentStateId() != pas::EAnimationState::WallHang || + x450_bodyController->GetBodyStateInfo().GetCurrentState()->ApplyGravity()) { + if (x634_25_ceilingAmbush) { + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Locomotion || + (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Jump && + !x450_bodyController->GetBodyStateInfo().GetCurrentState()->IsMoving())) { + CPhysicsActor::Stop(); + SetMomentumWR(zeus::CVector3f::skZero); + return; + } + } + } + break; + case EScriptObjectMessage::OnFloor: + x850_timeSinceHitByPlayer = FLT_MAX; + break; + default: + break; + } + } + switch (msg) { + case EScriptObjectMessage::OnNormalSurface: + case EScriptObjectMessage::Activate: + if (GetActive()) { + if (x634_29_onlyAttackInRange) + x638_31_ = true; + else + x400_24_hitByPlayerProjectile = true; + AssignTeamAiRole(mgr); + } else if (x634_25_ceilingAmbush) { + RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + x328_27_onGround = false; + } + break; + default: + break; + } + CPatterned::AcceptScriptMsg(msg, sender, mgr); + switch (msg) { + case EScriptObjectMessage::InitializedInArea: + for (const auto& conn : GetConnectionList()) { + if (conn.x0_state == EScriptObjectState::Retreat && conn.x4_msg == EScriptObjectMessage::Next) { + TUniqueId id = mgr.GetIdForScript(conn.x8_objId); + if (TCastToPtr cp = mgr.ObjectById(id)) + cp->Reserve(GetUniqueId()); + } else if (conn.x0_state == EScriptObjectState::Patrol && conn.x4_msg == EScriptObjectMessage::Follow) { + x637_24_ = true; + } + } + x660_pathFindSearch.SetArea(mgr.GetWorld()->GetAreaAlways(x4_areaId)->GetPostConstructed()->x10bc_pathArea); + if (x635_30_floatingCorpse) { + x858_ragdollDelayTimer = 0.01f; + RemoveMaterial(EMaterialTypes::Character, mgr); + x400_25_alive = false; + HealthInfo(mgr)->SetHP(-1.f); + } else { + SetEyeParticleActive(mgr, true); + } + break; + case EScriptObjectMessage::Decrement: + if (x85c_ragDoll) { + x85c_ragDoll->SetNoOverTimer(false); + x85c_ragDoll->SetContinueSmallMovements(false); + } + break; + case EScriptObjectMessage::Registered: { + if (x634_25_ceilingAmbush) { + x634_24_pendingAmbush = true; + if (x635_27_shadowPirate) { + x42c_color.a() = x568_pirateData.xb0_minCloakAlpha; + x3e8_alphaDelta = -1.f; + } + } + x75c_ = mgr.GetActiveRandom()->Next() % 6; + CMaterialFilter filter = GetMaterialFilter(); + filter.IncludeList().Remove(EMaterialTypes::AIPassthrough); + filter.ExcludeList().Add(EMaterialTypes::AIPassthrough); + SetMaterialFilter(filter); + break; + } + case EScriptObjectMessage::SetToZero: + if (x30_24_active) + x636_29_ = true; + break; + case EScriptObjectMessage::Falling: + if (!x450_bodyController->IsFrozen()) { + float zMom = GetGravityConstant() * xe8_mass; + if (x634_25_ceilingAmbush) + zMom *= 3.f; + SetMomentumWR({0.f, 0.f, -zMom}); + } + if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Step) + SetVelocityWR({0.f, 0.f, x138_velocity.z()}); + x7c4_burstFire.SetBurstType(3); + break; + case EScriptObjectMessage::Jumped: + CPatterned::AcceptScriptMsg(msg, sender, mgr); + SetMomentumWR({0.f, 0.f, -GetGravityConstant() * xe8_mass}); + SetVelocityForJump(); + break; + case EScriptObjectMessage::OnFloor: + if (!x634_29_onlyAttackInRange) + x7c4_burstFire.SetBurstType(1); + else + x7c4_burstFire.SetBurstType(4); + x637_30_ = false; + if (x635_27_shadowPirate && x138_velocity.z() < -1.f) { + x3e8_alphaDelta = 1.f; + x8a8_cloakDelayTimer += -0.05f * x138_velocity.z(); + x8a8_cloakDelayTimer = zeus::clamp(0.f, x8a8_cloakDelayTimer, 1.f); + x8bc_maxCloakAlpha = 0.5f; + if (x400_25_alive) { + mgr.GetActorModelParticles()->sub_801e51d0(*this); + x8ac_electricParticleTimer = 1.f + x8a8_cloakDelayTimer; + } + } + break; + case EScriptObjectMessage::Action: + if (TCastToPtr tp = mgr.ObjectById(sender)) { + if (tp->GetActive()) { + x764_boneTracking.SetTarget(sender); + x7c0_targetId = sender; + x400_24_hitByPlayerProjectile = true; + } else { x764_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); x7c0_targetId = mgr.GetPlayer().GetUniqueId(); + } + x7bc_ = 0.f; } - return mgr.GetPlayer().GetTranslation(); + break; + case EScriptObjectMessage::Deactivate: + case EScriptObjectMessage::Deleted: + RemoveTeamAiRole(mgr); + mChargePlayerList.remove(GetUniqueId()); + break; + case EScriptObjectMessage::Start: + x639_26_started = false; + break; + case EScriptObjectMessage::Stop: + x639_26_started = true; + break; + default: + break; + } } -void CSpacePirate::UpdateAimBodyState(float dt, CStateManager& mgr) -{ - if (x400_25_alive && x637_25_ && !x637_29_ && !x450_bodyController->IsFrozen() && - !x634_27_melee && !x85c_ragDoll && (!x635_26_ || x639_28_) && x31c_faceVec.z() <= 0.f) - { - x8c4_aimDelayTimer = std::max(0.f, x8c4_aimDelayTimer - dt); - if (x8c4_aimDelayTimer == 0.f) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCAdditiveAimCmd()); - x450_bodyController->GetCommandMgr().DeliverAdditiveTargetVector( - x34_transform.transposeRotate(GetTargetPos(mgr) - GetTranslation())); - } - } - else if (x637_25_ && !x634_27_melee) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::AdditiveIdle)); - } +void CSpacePirate::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + if (x85c_ragDoll && x85c_ragDoll->IsPrimed()) + x85c_ragDoll->PreRender(GetTranslation(), *x64_modelData); + CPatterned::PreRender(mgr, frustum); + if (!x85c_ragDoll || !x85c_ragDoll->IsPrimed()) { + x764_boneTracking.PreRender(mgr, *x64_modelData->AnimationData(), x34_transform, x64_modelData->GetScale(), + *x450_bodyController); + x860_ikChain.PreRender(*x64_modelData->AnimationData(), x34_transform, x64_modelData->GetScale()); + } } -void CSpacePirate::SetCinematicCollision(CStateManager& mgr) -{ - RemoveMaterial(EMaterialTypes::AIBlock, mgr); - CMaterialFilter filter = GetMaterialFilter(); - filter.IncludeList().Remove(EMaterialTypes::AIBlock); - SetMaterialFilter(filter); +void CSpacePirate::Render(const CStateManager& mgr) const { + float time = x400_25_alive ? CGraphics::GetSecondsMod900() : 0.f; + CTimeProvider prov(time); + g_Renderer->SetGXRegister1Color(x8cc_trooperColor); + CPatterned::Render(mgr); } -void CSpacePirate::SetNonCinematicCollision(CStateManager& mgr) -{ - AddMaterial(EMaterialTypes::AIBlock, mgr); - CMaterialFilter filter = GetMaterialFilter(); - filter.IncludeList().Add(EMaterialTypes::AIBlock); - SetMaterialFilter(filter); +void CSpacePirate::CalculateRenderBounds() { + if (x85c_ragDoll && x85c_ragDoll->IsPrimed()) { + zeus::CVector3f margin = x64_modelData->GetScale() * 0.2f; + zeus::CAABox ragdollBounds = x85c_ragDoll->CalculateRenderBounds(); + x9c_renderBounds = zeus::CAABox(ragdollBounds.min - margin, ragdollBounds.max + margin); + } else { + CActor::CalculateRenderBounds(); + } } -void CSpacePirate::CheckForProjectiles(CStateManager& mgr) -{ - if (x637_26_hearPlayerFire) - { - zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); - zeus::CAABox aabb(aimPos - 5.f, aimPos + 5.f); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, aabb, CMaterialFilter::MakeInclude({EMaterialTypes::Projectile}), nullptr); - for (TUniqueId id : nearList) - { - if (TCastToConstPtr proj = mgr.GetObjectById(id)) - { - zeus::CVector3f delta = GetBoundingBox().center() - proj->GetTranslation(); - if (delta.isMagnitudeSafe()) - { - if (x34_transform.basis[1].dot(delta) < 0.f) - { - delta.normalize(); - zeus::CVector3f projDelta = proj->GetTranslation() - proj->GetPreviousPos(); - if (projDelta.isMagnitudeSafe()) - { - projDelta.normalize(); - if (projDelta.dot(delta) > 0.939f) - x637_27_inProjectilePath = true; - } - } - } - else - { - x637_27_inProjectilePath = true; - } - if (x637_27_inProjectilePath) - break; - } - } - x637_26_hearPlayerFire = false; +void CSpacePirate::Touch(CActor& other, CStateManager& mgr) { + CPatterned::Touch(other, mgr); + if (x85c_ragDoll && x85c_ragDoll->IsPrimed()) { + if (TCastToPtr trig = other) { + if (trig->GetActive() && (trig->GetTriggerFlags() & ETriggerFlags::DetectAI) != ETriggerFlags::None && + trig->GetForceMagnitude() > 0.f) { + x85c_ragDoll->TorsoImpulse() += trig->GetForceVector(); + } } + } } -void CSpacePirate::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; +zeus::CAABox CSpacePirate::GetSortingBounds(const CStateManager& mgr) const { + zeus::CAABox aabb = x64_modelData->GetBounds(); + zeus::CVector3f radius = aabb.extents() * 0.5f; + zeus::CVector3f center = aabb.center(); + return zeus::CAABox(center - radius, center + radius); +} - if (!x450_bodyController->GetActive()) - x450_bodyController->Activate(mgr); - - bool inCineCam = mgr.GetCameraManager()->IsInCinematicCamera(); - if (inCineCam && !x637_31_prevInCineCam) - SetCinematicCollision(mgr); - else if (!inCineCam && x637_31_prevInCineCam && !x635_31_ragdollNoAiCollision) - SetNonCinematicCollision(mgr); - x637_31_prevInCineCam = inCineCam; - - float steeringSpeed = x748_ == 0.f ? x644_ : 0.f; - x450_bodyController->GetCommandMgr().SetSteeringSpeedRange(steeringSpeed, steeringSpeed); - - x744_ = std::max(x744_ - dt, 0.f); - - if (x400_25_alive) - { - x850_timeSinceHitByPlayer += dt; - x854_lowHealthFrenzyTimer += dt; - if (x637_27_inProjectilePath) - { - x854_lowHealthFrenzyTimer = 0.f; - x637_27_inProjectilePath = false; - } - if (x400_24_hitByPlayerProjectile) - { - x850_timeSinceHitByPlayer = 0.f; - x400_24_hitByPlayerProjectile = false; - } +void CSpacePirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + bool handled = false; + switch (type) { + case EUserEventType::BeginAction: + RemoveMaterial(EMaterialTypes::Solid, mgr); + x638_30_ragdollOver = true; + handled = true; + break; + case EUserEventType::EndAction: + x639_30_ = false; + handled = true; + break; + case EUserEventType::Projectile: + case EUserEventType::BecomeRagDoll: + if (x634_29_onlyAttackInRange || HealthInfo(mgr)->GetHP() <= 0.f) + x858_ragdollDelayTimer = mgr.GetActiveRandom()->Float() * 0.05f + 0.001f; + handled = true; + break; + case EUserEventType::IkLock: + if (!x860_ikChain.GetActive()) { + CSegId lctrId = x64_modelData->GetAnimationData()->GetLocatorSegId(node.GetLocatorName()); + if (lctrId != 3) { + zeus::CTransform xf = GetLctrTransform(lctrId); + x860_ikChain.Activate(*x64_modelData->AnimationData(), lctrId, xf); + x639_28_ = true; + } } + handled = true; + break; + case EUserEventType::IkRelease: + x860_ikChain.Deactivate(); + handled = true; + break; + case EUserEventType::ScreenShake: + SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); + handled = true; + break; + case EUserEventType::FadeOut: + x3e8_alphaDelta = -0.8f; + mgr.GetActorModelParticles()->sub_801e51d0(*this); + x8ac_electricParticleTimer = 1.f; + handled = true; + break; + default: + break; + } + if (!handled) + CPatterned::DoUserAnimEvent(mgr, node, type, dt); +} - UpdateCloak(dt, mgr); +void CSpacePirate::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) {} - if (!x450_bodyController->IsFrozen()) - { - if (x400_25_alive) - { - x748_ = std::max(x748_ - dt, 0.f); - if (x637_28_) - x7ac_ += dt; - else - x7ac_ = 0.f; - x838_ = std::max(x838_ - dt, 0.f); - x8c0_ = std::max(x8c0_ - dt, 0.f); - CheckForProjectiles(mgr); - } - UpdateAttacks(dt, mgr); - UpdateAimBodyState(dt, mgr); - x860_ikChain.Update(dt); - } +void CSpacePirate::KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, EKnockBackType type, + bool inDeferred, float magnitude) {} - if (x634_24_pendingAmbush) - { - x634_24_pendingAmbush = false; - if (x634_25_ceilingAmbush) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal6); - else - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch); - x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Ambushing"sv); - } +bool CSpacePirate::IsListening() const { return true; } - if (!x85c_ragDoll || !x85c_ragDoll->IsPrimed()) - { - CPatterned::Think(dt, mgr); - if (!x450_bodyController->IsFrozen()) - x764_boneTracking.Update(dt); - } +bool CSpacePirate::Listen(const zeus::CVector3f& pos, EListenNoiseType type) { + bool ret = false; + if (x400_25_alive) { + zeus::CVector3f delta = pos - GetTranslation(); + if (delta.magSquared() < x568_pirateData.x14_hearNoiseRange * x568_pirateData.x14_hearNoiseRange && + (x3c0_detectionHeightRange == 0.f || + delta.z() * delta.z() < x3c0_detectionHeightRange * x3c0_detectionHeightRange)) + x636_25_hearNoise = true; + if (type == EListenNoiseType::PlayerFire) + x637_26_hearPlayerFire = true; + } + return ret; +} + +zeus::CVector3f CSpacePirate::GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const { + return GetTranslation(); +} + +void CSpacePirate::Patrol(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Dead(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::PathFind(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::TargetCover(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Halt(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Run(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Generate(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Deactivate(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Attack(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::JumpBack(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::DoubleSnap(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Shuffle(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::TurnAround(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Skid(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::CoverAttack(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Crouch(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::GetUp(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Taunt(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Flee(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Lurk(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Jump(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Dodge(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Cover(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Approach(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::WallHang(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::WallDetach(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Enraged(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::Bounce(CStateManager& mgr, EStateMsg msg, float dt) {} + +void CSpacePirate::PathFindEx(CStateManager& mgr, EStateMsg msg, float dt) {} + +bool CSpacePirate::Leash(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::OffLine(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::Attacked(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::InRange(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::SpotPlayer(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::PatternOver(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::PatternShagged(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::AnimOver(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShouldAttack(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShouldJumpBack(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::Stuck(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::Landed(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::HearShot(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::HearPlayer(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::CoverCheck(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::CoverFind(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::CoverBlown(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::CoverNearlyBlown(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::CoveringFire(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::LineOfSight(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::AggressionCheck(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShouldDodge(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShouldRetreat(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShouldCrouch(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShouldMove(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShotAt(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::HasTargetingPoint(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShouldWallHang(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::StartAttack(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::BreakAttack(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShouldStrafe(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::ShouldSpecialAttack(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::LostInterest(CStateManager& mgr, float arg) { return false; } + +bool CSpacePirate::BounceFind(CStateManager& mgr, float arg) { return false; } + +CPathFindSearch* CSpacePirate::GetSearchPath() { return &x660_pathFindSearch; } + +u8 CSpacePirate::GetModelAlphau8(const CStateManager& mgr) const { + if ((mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay && + mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal) || + !x400_25_alive) { + if (!x635_27_shadowPirate) + return u8(x42c_color.a() * 255.f); else - { - UpdateAlphaDelta(dt, mgr); - UpdateDamageColor(dt); - if (CSfxHandle hnd = GetSfxHandle()) - CSfxManager::UpdateEmitter(hnd, GetTranslation(), zeus::CVector3f::skZero, 1.f); - } - if (x85c_ragDoll) - { - if (!x85c_ragDoll->IsPrimed()) - { - x85c_ragDoll->Prime(mgr, GetTransform(), *x64_modelData); - zeus::CVector3f trans = GetTranslation(); - SetTransform({}); - SetTranslation(trans); - x450_bodyController->SetPlaybackRate(0.f); - } - else - { - float waterTop = -FLT_MAX; - if (xc4_fluidId != kInvalidUniqueId) - if (TCastToConstPtr water = mgr.GetObjectById(xc4_fluidId)) - if (water->GetActive()) - waterTop = water->GetTriggerBoundsWR().max.z(); - x85c_ragDoll->Update(mgr, dt * CalcDyingThinkRate(), waterTop); - x64_modelData->AdvanceParticles(x34_transform, dt, mgr); - } - if (x85c_ragDoll->IsOver() && !x85c_ragDoll->WillContinueSmallMovements() && !x400_27_fadeToDeath) - { - /* Ragdoll has finished animating */ - x400_27_fadeToDeath = true; - AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); - x3e8_alphaDelta = -0.333333f; - x638_30_ragdollOver = true; - SetMomentumWR(zeus::CVector3f::skZero); - CPhysicsActor::Stop(); - } - } - if (x858_ragdollDelayTimer > 0.f) - { - x858_ragdollDelayTimer -= dt; - if (x858_ragdollDelayTimer <= 0.f) - { - if (!x85c_ragDoll) - { - x85c_ragDoll = std::make_unique( - mgr, this, x568_pirateData.x98_ragdollThudSfx, - (x635_30_floatingCorpse ? 3 : 0) | - (x635_31_ragdollNoAiCollision ? 4 : 0)); - RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); - } - x858_ragdollDelayTimer = 0.f; - } - } + return u8(x8b4_shadowPirateAlpha * 255.f); + } + return 255; } -void CSpacePirate::SetEyeParticleActive(CStateManager& mgr, bool active) -{ - if (!x636_24_trooper) - { - if (!x634_29_onlyAttackInRange || x635_26_) - { - if (!x635_27_shadowPirate) - x64_modelData->AnimationData()->SetParticleEffectState("TwoEyes"sv, active, mgr); - } - else - { - x64_modelData->AnimationData()->SetParticleEffectState("OneEye"sv, active, mgr); - } - } -} - -void CSpacePirate::SetVelocityForJump() -{ - -} - -void CSpacePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - if (x637_29_ || x634_25_ceilingAmbush) - { - switch (msg) - { - case EScriptObjectMessage::Falling: - if (!x637_29_ || x450_bodyController->GetCurrentStateId() != pas::EAnimationState::WallHang || - x450_bodyController->GetBodyStateInfo().GetCurrentState()->ApplyGravity()) - { - if (x634_25_ceilingAmbush) - { - if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Locomotion || - (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Jump && - !x450_bodyController->GetBodyStateInfo().GetCurrentState()->IsMoving())) - { - CPhysicsActor::Stop(); - SetMomentumWR(zeus::CVector3f::skZero); - return; - } - } - } - break; - case EScriptObjectMessage::OnFloor: - x850_timeSinceHitByPlayer = FLT_MAX; - break; - default: - break; - } - } - switch (msg) - { - case EScriptObjectMessage::OnNormalSurface: - case EScriptObjectMessage::Activate: - if (GetActive()) - { - if (x634_29_onlyAttackInRange) - x638_31_ = true; - else - x400_24_hitByPlayerProjectile = true; - AssignTeamAiRole(mgr); - } - else if (x634_25_ceilingAmbush) - { - RemoveMaterial(EMaterialTypes::GroundCollider, mgr); - x328_27_onGround = false; - } - break; - default: - break; - } - CPatterned::AcceptScriptMsg(msg, sender, mgr); - switch (msg) - { - case EScriptObjectMessage::InitializedInArea: - for (const auto& conn : GetConnectionList()) - { - if (conn.x0_state == EScriptObjectState::Retreat && conn.x4_msg == EScriptObjectMessage::Next) - { - TUniqueId id = mgr.GetIdForScript(conn.x8_objId); - if (TCastToPtr cp = mgr.ObjectById(id)) - cp->Reserve(GetUniqueId()); - } - else if (conn.x0_state == EScriptObjectState::Patrol && conn.x4_msg == EScriptObjectMessage::Follow) - { - x637_24_ = true; - } - } - x660_pathFindSearch.SetArea( - mgr.GetWorld()->GetAreaAlways(x4_areaId)->GetPostConstructed()->x10bc_pathArea); - if (x635_30_floatingCorpse) - { - x858_ragdollDelayTimer = 0.01f; - RemoveMaterial(EMaterialTypes::Character, mgr); - x400_25_alive = false; - HealthInfo(mgr)->SetHP(-1.f); - } - else - { - SetEyeParticleActive(mgr, true); - } - break; - case EScriptObjectMessage::Decrement: - if (x85c_ragDoll) - { - x85c_ragDoll->SetNoOverTimer(false); - x85c_ragDoll->SetContinueSmallMovements(false); - } - break; - case EScriptObjectMessage::Registered: - { - if (x634_25_ceilingAmbush) - { - x634_24_pendingAmbush = true; - if (x635_27_shadowPirate) - { - x42c_color.a() = x568_pirateData.xb0_minCloakAlpha; - x3e8_alphaDelta = -1.f; - } - } - x75c_ = mgr.GetActiveRandom()->Next() % 6; - CMaterialFilter filter = GetMaterialFilter(); - filter.IncludeList().Remove(EMaterialTypes::AIPassthrough); - filter.ExcludeList().Add(EMaterialTypes::AIPassthrough); - SetMaterialFilter(filter); - break; - } - case EScriptObjectMessage::SetToZero: - if (x30_24_active) - x636_29_ = true; - break; - case EScriptObjectMessage::Falling: - if (!x450_bodyController->IsFrozen()) - { - float zMom = GetGravityConstant() * xe8_mass; - if (x634_25_ceilingAmbush) - zMom *= 3.f; - SetMomentumWR({0.f, 0.f, -zMom}); - } - if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Step) - SetVelocityWR({0.f, 0.f, x138_velocity.z()}); - x7c4_burstFire.SetBurstType(3); - break; - case EScriptObjectMessage::Jumped: - CPatterned::AcceptScriptMsg(msg, sender, mgr); - SetMomentumWR({0.f, 0.f, -GetGravityConstant() * xe8_mass}); - SetVelocityForJump(); - break; - case EScriptObjectMessage::OnFloor: - if (!x634_29_onlyAttackInRange) - x7c4_burstFire.SetBurstType(1); - else - x7c4_burstFire.SetBurstType(4); - x637_30_ = false; - if (x635_27_shadowPirate && x138_velocity.z() < -1.f) - { - x3e8_alphaDelta = 1.f; - x8a8_cloakDelayTimer += -0.05f * x138_velocity.z(); - x8a8_cloakDelayTimer = zeus::clamp(0.f, x8a8_cloakDelayTimer, 1.f); - x8bc_maxCloakAlpha = 0.5f; - if (x400_25_alive) - { - mgr.GetActorModelParticles()->sub_801e51d0(*this); - x8ac_electricParticleTimer = 1.f + x8a8_cloakDelayTimer; - } - } - break; - case EScriptObjectMessage::Action: - if (TCastToPtr tp = mgr.ObjectById(sender)) - { - if (tp->GetActive()) - { - x764_boneTracking.SetTarget(sender); - x7c0_targetId = sender; - x400_24_hitByPlayerProjectile = true; - } - else - { - x764_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); - x7c0_targetId = mgr.GetPlayer().GetUniqueId(); - } - x7bc_ = 0.f; - } - break; - case EScriptObjectMessage::Deactivate: - case EScriptObjectMessage::Deleted: - RemoveTeamAiRole(mgr); - mChargePlayerList.remove(GetUniqueId()); - break; - case EScriptObjectMessage::Start: - x639_26_started = false; - break; - case EScriptObjectMessage::Stop: - x639_26_started = true; - break; - default: - break; - } -} - -void CSpacePirate::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - if (x85c_ragDoll && x85c_ragDoll->IsPrimed()) - x85c_ragDoll->PreRender(GetTranslation(), *x64_modelData); - CPatterned::PreRender(mgr, frustum); - if (!x85c_ragDoll || !x85c_ragDoll->IsPrimed()) - { - x764_boneTracking.PreRender(mgr, *x64_modelData->AnimationData(), x34_transform, - x64_modelData->GetScale(), *x450_bodyController); - x860_ikChain.PreRender(*x64_modelData->AnimationData(), x34_transform, x64_modelData->GetScale()); - } -} - -void CSpacePirate::Render(const CStateManager& mgr) const -{ - float time = x400_25_alive ? CGraphics::GetSecondsMod900() : 0.f; - CTimeProvider prov(time); - g_Renderer->SetGXRegister1Color(x8cc_trooperColor); - CPatterned::Render(mgr); -} - -void CSpacePirate::CalculateRenderBounds() -{ - if (x85c_ragDoll && x85c_ragDoll->IsPrimed()) - { - zeus::CVector3f margin = x64_modelData->GetScale() * 0.2f; - zeus::CAABox ragdollBounds = x85c_ragDoll->CalculateRenderBounds(); - x9c_renderBounds = zeus::CAABox(ragdollBounds.min - margin, ragdollBounds.max + margin); - } - else - { - CActor::CalculateRenderBounds(); - } -} - -void CSpacePirate::Touch(CActor& other, CStateManager& mgr) -{ - CPatterned::Touch(other, mgr); - if (x85c_ragDoll && x85c_ragDoll->IsPrimed()) - { - if (TCastToPtr trig = other) - { - if (trig->GetActive() && - (trig->GetTriggerFlags() & ETriggerFlags::DetectAI) != ETriggerFlags::None && - trig->GetForceMagnitude() > 0.f) - { - x85c_ragDoll->TorsoImpulse() += trig->GetForceVector(); - } - } - } -} - -zeus::CAABox CSpacePirate::GetSortingBounds(const CStateManager& mgr) const -{ - zeus::CAABox aabb = x64_modelData->GetBounds(); - zeus::CVector3f radius = aabb.extents() * 0.5f; - zeus::CVector3f center = aabb.center(); - return zeus::CAABox(center - radius, center + radius); -} - -void CSpacePirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) -{ - bool handled = false; - switch (type) - { - case EUserEventType::BeginAction: - RemoveMaterial(EMaterialTypes::Solid, mgr); - x638_30_ragdollOver = true; - handled = true; - break; - case EUserEventType::EndAction: - x639_30_ = false; - handled = true; - break; - case EUserEventType::Projectile: - case EUserEventType::BecomeRagDoll: - if (x634_29_onlyAttackInRange || HealthInfo(mgr)->GetHP() <= 0.f) - x858_ragdollDelayTimer = mgr.GetActiveRandom()->Float() * 0.05f + 0.001f; - handled = true; - break; - case EUserEventType::IkLock: - if (!x860_ikChain.GetActive()) - { - CSegId lctrId = x64_modelData->GetAnimationData()->GetLocatorSegId(node.GetLocatorName()); - if (lctrId != 3) - { - zeus::CTransform xf = GetLctrTransform(lctrId); - x860_ikChain.Activate(*x64_modelData->AnimationData(), lctrId, xf); - x639_28_ = true; - } - } - handled = true; - break; - case EUserEventType::IkRelease: - x860_ikChain.Deactivate(); - handled = true; - break; - case EUserEventType::ScreenShake: - SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); - handled = true; - break; - case EUserEventType::FadeOut: - x3e8_alphaDelta = -0.8f; - mgr.GetActorModelParticles()->sub_801e51d0(*this); - x8ac_electricParticleTimer = 1.f; - handled = true; - break; - default: - break; - } - if (!handled) - CPatterned::DoUserAnimEvent(mgr, node, type, dt); -} - -void CSpacePirate::Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) -{ - -} - -void CSpacePirate::KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, - EKnockBackType type, bool inDeferred, float magnitude) -{ - -} - -bool CSpacePirate::IsListening() const -{ - return true; -} - -bool CSpacePirate::Listen(const zeus::CVector3f& pos, EListenNoiseType type) -{ - bool ret = false; - if (x400_25_alive) - { - zeus::CVector3f delta = pos - GetTranslation(); - if (delta.magSquared() < x568_pirateData.x14_hearNoiseRange * x568_pirateData.x14_hearNoiseRange && - (x3c0_detectionHeightRange == 0.f || - delta.z() * delta.z() < x3c0_detectionHeightRange * x3c0_detectionHeightRange)) - x636_25_hearNoise = true; - if (type == EListenNoiseType::PlayerFire) - x637_26_hearPlayerFire = true; - } - return ret; -} - -zeus::CVector3f CSpacePirate::GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const -{ - return GetTranslation(); -} - -void CSpacePirate::Patrol(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Dead(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::PathFind(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::TargetCover(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} +float CSpacePirate::GetGravityConstant() const { return 50.f; } -void CSpacePirate::Halt(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Run(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Generate(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Deactivate(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Attack(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::JumpBack(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::DoubleSnap(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Shuffle(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::TurnAround(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Skid(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::CoverAttack(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Crouch(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::GetUp(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Taunt(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Flee(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Lurk(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Jump(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Dodge(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Cover(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Approach(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::WallHang(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::WallDetach(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} +CProjectileInfo* CSpacePirate::GetProjectileInfo() { return &x568_pirateData.x20_mainProjectileInfo; } -void CSpacePirate::Enraged(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::Bounce(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -void CSpacePirate::PathFindEx(CStateManager& mgr, EStateMsg msg, float dt) -{ - -} - -bool CSpacePirate::Leash(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::OffLine(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::Attacked(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::InRange(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::SpotPlayer(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::PatternOver(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::PatternShagged(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::AnimOver(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShouldAttack(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShouldJumpBack(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::Stuck(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::Landed(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::HearShot(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::HearPlayer(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::CoverCheck(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::CoverFind(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::CoverBlown(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::CoverNearlyBlown(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::CoveringFire(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::LineOfSight(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::AggressionCheck(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShouldDodge(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShouldRetreat(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShouldCrouch(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShouldMove(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShotAt(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::HasTargetingPoint(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShouldWallHang(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::StartAttack(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::BreakAttack(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShouldStrafe(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::ShouldSpecialAttack(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::LostInterest(CStateManager& mgr, float arg) -{ - return false; -} - -bool CSpacePirate::BounceFind(CStateManager& mgr, float arg) -{ - return false; -} - -CPathFindSearch* CSpacePirate::GetSearchPath() -{ - return &x660_pathFindSearch; -} - -u8 CSpacePirate::GetModelAlphau8(const CStateManager& mgr) const -{ - if ((mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay && - mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal) || - !x400_25_alive) - { - if (!x635_27_shadowPirate) - return u8(x42c_color.a() * 255.f); - else - return u8(x8b4_shadowPirateAlpha * 255.f); - } - return 255; -} - -float CSpacePirate::GetGravityConstant() const -{ - return 50.f; -} - -CProjectileInfo* CSpacePirate::GetProjectileInfo() -{ - return &x568_pirateData.x20_mainProjectileInfo; -} - -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CSpacePirate.hpp b/Runtime/MP1/World/CSpacePirate.hpp index d25cbfc6e..b931ba1a6 100644 --- a/Runtime/MP1/World/CSpacePirate.hpp +++ b/Runtime/MP1/World/CSpacePirate.hpp @@ -8,309 +8,306 @@ #include "World/CPathFindSearch.hpp" #include "Weapon/CBurstFire.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { class CSpacePirate; -class CPirateRagDoll : public CRagDoll -{ - CSpacePirate* x6c_spacePirate; - u16 x70_thudSfx; - float x74_sfxTimer = 0.f; - zeus::CVector3f x78_lastSFXPos; - zeus::CVector3f x84_torsoImpulse; - rstl::reserved_vector x90_waypoints; - rstl::reserved_vector x9c_wpParticleIdxs; - bool xb0_24_initSfx : 1; -public: - CPirateRagDoll(CStateManager& mgr, CSpacePirate* sp, u16 thudSfx, u32 flags); +class CPirateRagDoll : public CRagDoll { + CSpacePirate* x6c_spacePirate; + u16 x70_thudSfx; + float x74_sfxTimer = 0.f; + zeus::CVector3f x78_lastSFXPos; + zeus::CVector3f x84_torsoImpulse; + rstl::reserved_vector x90_waypoints; + rstl::reserved_vector x9c_wpParticleIdxs; + bool xb0_24_initSfx : 1; - void PreRender(const zeus::CVector3f& v, CModelData& mData); - void Update(CStateManager& mgr, float dt, float waterTop); - void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData); - zeus::CVector3f& TorsoImpulse() { return x84_torsoImpulse; } +public: + CPirateRagDoll(CStateManager& mgr, CSpacePirate* sp, u16 thudSfx, u32 flags); + + void PreRender(const zeus::CVector3f& v, CModelData& mData); + void Update(CStateManager& mgr, float dt, float waterTop); + void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData); + zeus::CVector3f& TorsoImpulse() { return x84_torsoImpulse; } }; -class CSpacePirate : public CPatterned -{ - friend class CPirateRagDoll; +class CSpacePirate : public CPatterned { + friend class CPirateRagDoll; + public: - DEFINE_PATTERNED(SpacePirate) + DEFINE_PATTERNED(SpacePirate) private: - class CSpacePirateData - { - friend class CSpacePirate; - float x0_; - float x4_; - float x8_; - float xc_; - float x10_; - float x14_hearNoiseRange; - u32 x18_flags; - bool x1c_; - CProjectileInfo x20_mainProjectileInfo; - u16 x48_; - CDamageInfo x4c_; - float x68_; - CProjectileInfo x6c_; - float x94_; - u16 x98_ragdollThudSfx; - float x9c_averageNextShotTime; - float xa0_nextShotTimeVariation; - u16 xa4_; - float xa8_aimDelayTime; - u32 xac_firstBurstCount; - float xb0_minCloakAlpha; - float xb4_maxCloakAlpha; - float xb8_; - float xbc_; - u16 xc0_; - u16 xc2_; - float xc4_; - float xc8_; - public: - CSpacePirateData(CInputStream&, u32); + class CSpacePirateData { + friend class CSpacePirate; + float x0_; + float x4_; + float x8_; + float xc_; + float x10_; + float x14_hearNoiseRange; + u32 x18_flags; + bool x1c_; + CProjectileInfo x20_mainProjectileInfo; + u16 x48_; + CDamageInfo x4c_; + float x68_; + CProjectileInfo x6c_; + float x94_; + u16 x98_ragdollThudSfx; + float x9c_averageNextShotTime; + float xa0_nextShotTimeVariation; + u16 xa4_; + float xa8_aimDelayTime; + u32 xac_firstBurstCount; + float xb0_minCloakAlpha; + float xb4_maxCloakAlpha; + float xb8_; + float xbc_; + u16 xc0_; + u16 xc2_; + float xc4_; + float xc8_; + + public: + CSpacePirateData(CInputStream&, u32); + }; + + CSpacePirateData x568_pirateData; + union { + struct { + bool x634_24_pendingAmbush : 1; + bool x634_25_ceilingAmbush : 1; + bool x634_26_ : 1; + bool x634_27_melee : 1; + bool x634_28_ : 1; + bool x634_29_onlyAttackInRange : 1; + bool x634_30_ : 1; + bool x634_31_ : 1; + bool x635_24_ : 1; + bool x635_25_ : 1; + bool x635_26_ : 1; + bool x635_27_shadowPirate : 1; + bool x635_28_ : 1; + bool x635_29_ : 1; + bool x635_30_floatingCorpse : 1; + bool x635_31_ragdollNoAiCollision : 1; + bool x636_24_trooper : 1; + bool x636_25_hearNoise : 1; + bool x636_26_ : 1; + bool x636_27_ : 1; + bool x636_28_ : 1; + bool x636_29_ : 1; + bool x636_30_ : 1; + bool x636_31_ : 1; + bool x637_24_ : 1; + bool x637_25_ : 1; + bool x637_26_hearPlayerFire : 1; + bool x637_27_inProjectilePath : 1; + bool x637_28_ : 1; + bool x637_29_ : 1; + bool x637_30_ : 1; + bool x637_31_prevInCineCam : 1; + bool x638_24_pendingFrenzyChance : 1; + bool x638_25_ : 1; + bool x638_26_ : 1; + bool x638_27_ : 1; + bool x638_28_ : 1; + bool x638_29_ : 1; + bool x638_30_ragdollOver : 1; + bool x638_31_ : 1; + bool x639_24_ : 1; + bool x639_25_ : 1; + bool x639_26_started : 1; + bool x639_27_ : 1; + bool x639_28_ : 1; + bool x639_29_ : 1; + bool x639_30_ : 1; + bool x639_31_ : 1; + bool x63a_24_ : 1; }; - CSpacePirateData x568_pirateData; - union - { - struct - { - bool x634_24_pendingAmbush : 1; - bool x634_25_ceilingAmbush : 1; - bool x634_26_ : 1; - bool x634_27_melee : 1; - bool x634_28_ : 1; - bool x634_29_onlyAttackInRange : 1; - bool x634_30_ : 1; - bool x634_31_ : 1; - bool x635_24_ : 1; - bool x635_25_ : 1; - bool x635_26_ : 1; - bool x635_27_shadowPirate : 1; - bool x635_28_ : 1; - bool x635_29_ : 1; - bool x635_30_floatingCorpse : 1; - bool x635_31_ragdollNoAiCollision : 1; - bool x636_24_trooper : 1; - bool x636_25_hearNoise : 1; - bool x636_26_ : 1; - bool x636_27_ : 1; - bool x636_28_ : 1; - bool x636_29_ : 1; - bool x636_30_ : 1; - bool x636_31_ : 1; - bool x637_24_ : 1; - bool x637_25_ : 1; - bool x637_26_hearPlayerFire : 1; - bool x637_27_inProjectilePath : 1; - bool x637_28_ : 1; - bool x637_29_ : 1; - bool x637_30_ : 1; - bool x637_31_prevInCineCam : 1; - bool x638_24_pendingFrenzyChance : 1; - bool x638_25_ : 1; - bool x638_26_ : 1; - bool x638_27_ : 1; - bool x638_28_ : 1; - bool x638_29_ : 1; - bool x638_30_ragdollOver : 1; - bool x638_31_ : 1; - bool x639_24_ : 1; - bool x639_25_ : 1; - bool x639_26_started : 1; - bool x639_27_ : 1; - bool x639_28_ : 1; - bool x639_29_ : 1; - bool x639_30_ : 1; - bool x639_31_ : 1; - bool x63a_24_ : 1; - }; + u64 _dummy = 0; + }; - u64 _dummy = 0; - }; + s32 x63c_frenzyFrames = 0; + TUniqueId x640_ = kInvalidUniqueId; + TUniqueId x642_ = kInvalidUniqueId; + float x644_ = 1.f; + zeus::CVector3f x648_ = zeus::CVector3f::skForward; + zeus::CVector3f x654_; + CPathFindSearch x660_pathFindSearch; + float x744_ = 0.f; + float x748_ = 0.f; + u32 x74c_ = 0; + float x750_initialHP; + float x754_ = 0.f; + CSegId x758_headSeg; + u32 x75c_ = 0; + s32 x760_ = -1; + CBoneTracking x764_boneTracking; + s32 x79c_ = -1; + float x7a4_intoJumpDist = 1.f; + float x7a8_ = 2.f; + float x7ac_ = 0.f; + u32 x7b0_ = 0; + TUniqueId x7b4_ = kInvalidUniqueId; + CSegId x7b6_gunSeg; + CSegId x7b7_elbowSeg; + CSegId x7b8_wristSeg; + CSegId x7b9_swooshSeg; + float x7bc_ = 1.f; + TUniqueId x7c0_targetId = kInvalidUniqueId; + CBurstFire x7c4_burstFire; + float x824_ = 3.f; + zeus::CVector3f x828_; + s32 x834_ = -1; + float x838_ = 0.f; + s32 x83c_ = -1; + TUniqueId x840_ = kInvalidUniqueId; + s32 x844_ = -1; + float x848_dodgeDist = 3.f; + float x84c_breakDodgeDist = 3.f; + float x850_timeSinceHitByPlayer = FLT_MAX; + float x854_lowHealthFrenzyTimer = FLT_MAX; + float x858_ragdollDelayTimer = 0.f; + std::unique_ptr x85c_ragDoll; + CIkChain x860_ikChain; + float x8a8_cloakDelayTimer = 0.f; + float x8ac_electricParticleTimer = 0.f; + float x8b0_cloakStepTime = 0.f; + float x8b4_shadowPirateAlpha = 0.5f; + float x8b8_minCloakAlpha; + float x8bc_maxCloakAlpha; + float x8c0_; + float x8c4_aimDelayTimer; + TUniqueId x8c8_teamAiMgrId = kInvalidUniqueId; + zeus::CColor x8cc_trooperColor = zeus::CColor::skWhite; + zeus::CVector2f x8d0_; + float x8d8_ = 0.f; + float x8dc_ = 0.f; - s32 x63c_frenzyFrames = 0; - TUniqueId x640_ = kInvalidUniqueId; - TUniqueId x642_ = kInvalidUniqueId; - float x644_ = 1.f; - zeus::CVector3f x648_ = zeus::CVector3f::skForward; - zeus::CVector3f x654_; - CPathFindSearch x660_pathFindSearch; - float x744_ = 0.f; - float x748_ = 0.f; - u32 x74c_ = 0; - float x750_initialHP; - float x754_ = 0.f; - CSegId x758_headSeg; - u32 x75c_ = 0; - s32 x760_ = -1; - CBoneTracking x764_boneTracking; - s32 x79c_ = -1; - float x7a4_intoJumpDist = 1.f; - float x7a8_ = 2.f; - float x7ac_ = 0.f; - u32 x7b0_ = 0; - TUniqueId x7b4_ = kInvalidUniqueId; - CSegId x7b6_gunSeg; - CSegId x7b7_elbowSeg; - CSegId x7b8_wristSeg; - CSegId x7b9_swooshSeg; - float x7bc_ = 1.f; - TUniqueId x7c0_targetId = kInvalidUniqueId; - CBurstFire x7c4_burstFire; - float x824_ = 3.f; - zeus::CVector3f x828_; - s32 x834_ = -1; - float x838_ = 0.f; - s32 x83c_ = -1; - TUniqueId x840_ = kInvalidUniqueId; - s32 x844_ = -1; - float x848_dodgeDist = 3.f; - float x84c_breakDodgeDist = 3.f; - float x850_timeSinceHitByPlayer = FLT_MAX; - float x854_lowHealthFrenzyTimer = FLT_MAX; - float x858_ragdollDelayTimer = 0.f; - std::unique_ptr x85c_ragDoll; - CIkChain x860_ikChain; - float x8a8_cloakDelayTimer = 0.f; - float x8ac_electricParticleTimer = 0.f; - float x8b0_cloakStepTime = 0.f; - float x8b4_shadowPirateAlpha = 0.5f; - float x8b8_minCloakAlpha; - float x8bc_maxCloakAlpha; - float x8c0_; - float x8c4_aimDelayTimer; - TUniqueId x8c8_teamAiMgrId = kInvalidUniqueId; - zeus::CColor x8cc_trooperColor = zeus::CColor::skWhite; - zeus::CVector2f x8d0_; - float x8d8_ = 0.f; - float x8dc_ = 0.f; + static const SBurst skBurstsSeatedOOV[]; + static const SBurst skBurstsInjuredOOV[]; + static const SBurst skBurstsJumpingOOV[]; + static const SBurst skBurstsFrenziedOOV[]; + static const SBurst skBurstsStandardOOV[]; + static const SBurst skBurstsQuickOOV[]; + static const SBurst skBurstsSeated[]; + static const SBurst skBurstsInjured[]; + static const SBurst skBurstsJumping[]; + static const SBurst skBurstsFrenzied[]; + static const SBurst skBurstsStandard[]; + static const SBurst skBurstsQuick[]; + static const SBurst* skBursts[]; - static const SBurst skBurstsSeatedOOV[]; - static const SBurst skBurstsInjuredOOV[]; - static const SBurst skBurstsJumpingOOV[]; - static const SBurst skBurstsFrenziedOOV[]; - static const SBurst skBurstsStandardOOV[]; - static const SBurst skBurstsQuickOOV[]; - static const SBurst skBurstsSeated[]; - static const SBurst skBurstsInjured[]; - static const SBurst skBurstsJumping[]; - static const SBurst skBurstsFrenzied[]; - static const SBurst skBurstsStandard[]; - static const SBurst skBurstsQuick[]; - static const SBurst* skBursts[]; + static std::list mChargePlayerList; - static std::list mChargePlayerList; - - void UpdateCloak(float dt, CStateManager& mgr); - bool ShouldFrenzy(CStateManager& mgr); - void ResetTeamAiRole(CStateManager& mgr); - void AssignTeamAiRole(CStateManager& mgr); - void RemoveTeamAiRole(CStateManager& mgr); - bool CheckTargetable(CStateManager& mgr); - void FireProjectile(float dt, CStateManager& mgr); - void UpdateAttacks(float dt, CStateManager& mgr); - zeus::CVector3f GetTargetPos(CStateManager& mgr); - void UpdateAimBodyState(float dt, CStateManager& mgr); - void SetCinematicCollision(CStateManager& mgr); - void SetNonCinematicCollision(CStateManager& mgr); - void CheckForProjectiles(CStateManager& mgr); - void SetEyeParticleActive(CStateManager& mgr, bool active); - void SetVelocityForJump(); + void UpdateCloak(float dt, CStateManager& mgr); + bool ShouldFrenzy(CStateManager& mgr); + void ResetTeamAiRole(CStateManager& mgr); + void AssignTeamAiRole(CStateManager& mgr); + void RemoveTeamAiRole(CStateManager& mgr); + bool CheckTargetable(CStateManager& mgr); + void FireProjectile(float dt, CStateManager& mgr); + void UpdateAttacks(float dt, CStateManager& mgr); + zeus::CVector3f GetTargetPos(CStateManager& mgr); + void UpdateAimBodyState(float dt, CStateManager& mgr); + void SetCinematicCollision(CStateManager& mgr); + void SetNonCinematicCollision(CStateManager& mgr); + void CheckForProjectiles(CStateManager& mgr); + void SetEyeParticleActive(CStateManager& mgr, bool active); + void SetVelocityForJump(); public: - CSpacePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CActorParameters&, const CPatternedInfo&, CInputStream&, u32); + CSpacePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const CPatternedInfo&, CInputStream&, u32); - void Accept(IVisitor &visitor); - void Think(float dt, CStateManager& mgr); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); - void Render(const CStateManager& mgr) const; + void Accept(IVisitor& visitor); + void Think(float dt, CStateManager& mgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); + void Render(const CStateManager& mgr) const; - void CalculateRenderBounds(); - void Touch(CActor& other, CStateManager& mgr); - zeus::CAABox GetSortingBounds(const CStateManager& mgr) const; - void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); - void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); - void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, - EKnockBackType type, bool inDeferred, float magnitude); - bool IsListening() const; - bool Listen(const zeus::CVector3f&, EListenNoiseType); - zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const; + void CalculateRenderBounds(); + void Touch(CActor& other, CStateManager& mgr); + zeus::CAABox GetSortingBounds(const CStateManager& mgr) const; + void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); + void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); + void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, EKnockBackType type, bool inDeferred, + float magnitude); + bool IsListening() const; + bool Listen(const zeus::CVector3f&, EListenNoiseType); + zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const; - void Patrol(CStateManager&, EStateMsg, float); - void Dead(CStateManager&, EStateMsg, float); - void PathFind(CStateManager&, EStateMsg, float); - void TargetPatrol(CStateManager&, EStateMsg, float); - void TargetCover(CStateManager&, EStateMsg, float); - void Halt(CStateManager&, EStateMsg, float); - void Run(CStateManager&, EStateMsg, float); - void Generate(CStateManager&, EStateMsg, float); - void Deactivate(CStateManager&, EStateMsg, float); - void Attack(CStateManager&, EStateMsg, float); - void JumpBack(CStateManager&, EStateMsg, float); - void DoubleSnap(CStateManager&, EStateMsg, float); - void Shuffle(CStateManager&, EStateMsg, float); - void TurnAround(CStateManager&, EStateMsg, float); - void Skid(CStateManager&, EStateMsg, float); - void CoverAttack(CStateManager&, EStateMsg, float); - void Crouch(CStateManager&, EStateMsg, float); - void GetUp(CStateManager&, EStateMsg, float); - void Taunt(CStateManager&, EStateMsg, float); - void Flee(CStateManager&, EStateMsg, float); - void Lurk(CStateManager&, EStateMsg, float); - void Jump(CStateManager&, EStateMsg, float); - void Dodge(CStateManager&, EStateMsg, float); - void Cover(CStateManager&, EStateMsg, float); - void Approach(CStateManager&, EStateMsg, float); - void WallHang(CStateManager&, EStateMsg, float); - void WallDetach(CStateManager&, EStateMsg, float); - void Enraged(CStateManager&, EStateMsg, float); - void SpecialAttack(CStateManager&, EStateMsg, float); - void Bounce(CStateManager&, EStateMsg, float); - void PathFindEx(CStateManager&, EStateMsg, float); + void Patrol(CStateManager&, EStateMsg, float); + void Dead(CStateManager&, EStateMsg, float); + void PathFind(CStateManager&, EStateMsg, float); + void TargetPatrol(CStateManager&, EStateMsg, float); + void TargetCover(CStateManager&, EStateMsg, float); + void Halt(CStateManager&, EStateMsg, float); + void Run(CStateManager&, EStateMsg, float); + void Generate(CStateManager&, EStateMsg, float); + void Deactivate(CStateManager&, EStateMsg, float); + void Attack(CStateManager&, EStateMsg, float); + void JumpBack(CStateManager&, EStateMsg, float); + void DoubleSnap(CStateManager&, EStateMsg, float); + void Shuffle(CStateManager&, EStateMsg, float); + void TurnAround(CStateManager&, EStateMsg, float); + void Skid(CStateManager&, EStateMsg, float); + void CoverAttack(CStateManager&, EStateMsg, float); + void Crouch(CStateManager&, EStateMsg, float); + void GetUp(CStateManager&, EStateMsg, float); + void Taunt(CStateManager&, EStateMsg, float); + void Flee(CStateManager&, EStateMsg, float); + void Lurk(CStateManager&, EStateMsg, float); + void Jump(CStateManager&, EStateMsg, float); + void Dodge(CStateManager&, EStateMsg, float); + void Cover(CStateManager&, EStateMsg, float); + void Approach(CStateManager&, EStateMsg, float); + void WallHang(CStateManager&, EStateMsg, float); + void WallDetach(CStateManager&, EStateMsg, float); + void Enraged(CStateManager&, EStateMsg, float); + void SpecialAttack(CStateManager&, EStateMsg, float); + void Bounce(CStateManager&, EStateMsg, float); + void PathFindEx(CStateManager&, EStateMsg, float); - bool Leash(CStateManager&, float); - bool OffLine(CStateManager&, float); - bool Attacked(CStateManager&, float); - bool InRange(CStateManager&, float); - bool SpotPlayer(CStateManager&, float); - bool PatternOver(CStateManager&, float); - bool PatternShagged(CStateManager&, float); - bool AnimOver(CStateManager&, float); - bool ShouldAttack(CStateManager&, float); - bool ShouldJumpBack(CStateManager&, float); - bool Stuck(CStateManager&, float); - bool Landed(CStateManager&, float); - bool HearShot(CStateManager&, float); - bool HearPlayer(CStateManager&, float); - bool CoverCheck(CStateManager&, float); - bool CoverFind(CStateManager&, float); - bool CoverBlown(CStateManager&, float); - bool CoverNearlyBlown(CStateManager&, float); - bool CoveringFire(CStateManager&, float); - bool LineOfSight(CStateManager&, float); - bool AggressionCheck(CStateManager&, float); - bool ShouldDodge(CStateManager&, float); - bool ShouldRetreat(CStateManager&, float); - bool ShouldCrouch(CStateManager&, float); - bool ShouldMove(CStateManager&, float); - bool ShotAt(CStateManager&, float); - bool HasTargetingPoint(CStateManager&, float); - bool ShouldWallHang(CStateManager&, float); - bool StartAttack(CStateManager&, float); - bool BreakAttack(CStateManager&, float); - bool ShouldStrafe(CStateManager&, float); - bool ShouldSpecialAttack(CStateManager&, float); - bool LostInterest(CStateManager&, float); - bool BounceFind(CStateManager&, float); + bool Leash(CStateManager&, float); + bool OffLine(CStateManager&, float); + bool Attacked(CStateManager&, float); + bool InRange(CStateManager&, float); + bool SpotPlayer(CStateManager&, float); + bool PatternOver(CStateManager&, float); + bool PatternShagged(CStateManager&, float); + bool AnimOver(CStateManager&, float); + bool ShouldAttack(CStateManager&, float); + bool ShouldJumpBack(CStateManager&, float); + bool Stuck(CStateManager&, float); + bool Landed(CStateManager&, float); + bool HearShot(CStateManager&, float); + bool HearPlayer(CStateManager&, float); + bool CoverCheck(CStateManager&, float); + bool CoverFind(CStateManager&, float); + bool CoverBlown(CStateManager&, float); + bool CoverNearlyBlown(CStateManager&, float); + bool CoveringFire(CStateManager&, float); + bool LineOfSight(CStateManager&, float); + bool AggressionCheck(CStateManager&, float); + bool ShouldDodge(CStateManager&, float); + bool ShouldRetreat(CStateManager&, float); + bool ShouldCrouch(CStateManager&, float); + bool ShouldMove(CStateManager&, float); + bool ShotAt(CStateManager&, float); + bool HasTargetingPoint(CStateManager&, float); + bool ShouldWallHang(CStateManager&, float); + bool StartAttack(CStateManager&, float); + bool BreakAttack(CStateManager&, float); + bool ShouldStrafe(CStateManager&, float); + bool ShouldSpecialAttack(CStateManager&, float); + bool LostInterest(CStateManager&, float); + bool BounceFind(CStateManager&, float); - CPathFindSearch* GetSearchPath(); - u8 GetModelAlphau8(const CStateManager& mgr) const; - float GetGravityConstant() const; - CProjectileInfo* GetProjectileInfo(); + CPathFindSearch* GetSearchPath(); + u8 GetModelAlphau8(const CStateManager& mgr) const; + float GetGravityConstant() const; + CProjectileInfo* GetProjectileInfo(); }; -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CSpankWeed.cpp b/Runtime/MP1/World/CSpankWeed.cpp index 7eb14e206..959f3827d 100644 --- a/Runtime/MP1/World/CSpankWeed.cpp +++ b/Runtime/MP1/World/CSpankWeed.cpp @@ -5,12 +5,11 @@ #include "CStateManager.hpp" #include -namespace urde::MP1 -{ +namespace urde::MP1 { logvisor::Module SpankLog("urde::MP1::SpankWeed"); CSpankWeed::CSpankWeed(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, float maxDetectionRange, - float maxHearingRange, float maxSightRange, float hideTime) + CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo, + float maxDetectionRange, float maxHearingRange, float maxSightRange, float hideTime) : CPatterned(ECharacter::SpankWeed, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Medium) , x568_maxDetectionRange(maxDetectionRange) @@ -18,398 +17,307 @@ CSpankWeed::CSpankWeed(TUniqueId uid, std::string_view name, const CEntityInfo& , x570_maxHearingRange(maxHearingRange) , x574_maxSightRange(maxSightRange) , x578_hideTime(hideTime) -, x584_retreatOrigin(xf.origin) -{ - SetCallTouch(false); - CreateShadow(false); +, x584_retreatOrigin(xf.origin) { + SetCallTouch(false); + CreateShadow(false); - zeus::CVector3f modelScale = GetModelData()->GetScale(); - if (modelScale.x != modelScale.y || modelScale.x != modelScale.z) - { - float scale = modelScale.magnitude() / std::sqrt(3.f); + zeus::CVector3f modelScale = GetModelData()->GetScale(); + if (modelScale.x() != modelScale.y() || modelScale.x() != modelScale.z()) { + float scale = modelScale.magnitude() / std::sqrt(3.f); - ModelData()->SetScale(zeus::CVector3f(scale)); - SpankLog.report(logvisor::Level::Warning, "WARNING: Non-uniform scale (%.2f, %.2f, %.2f) applied to Spank Weed" - "...changing scale to (%.2f, %.2f, %.2f)\n", - modelScale.x, modelScale.y, modelScale.z, - scale, scale, scale); - } - CMaterialList list = GetMaterialFilter().GetExcludeList(); - list.Add(EMaterialTypes::Character); - list.Add(EMaterialTypes::Player); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(GetMaterialFilter().GetIncludeList(), list)); + ModelData()->SetScale(zeus::CVector3f(scale)); + SpankLog.report(logvisor::Level::Warning, + "WARNING: Non-uniform scale (%.2f, %.2f, %.2f) applied to Spank Weed" + "...changing scale to (%.2f, %.2f, %.2f)\n", + modelScale.x(), modelScale.y(), modelScale.z(), scale, scale, scale); + } + CMaterialList list = GetMaterialFilter().GetExcludeList(); + list.Add(EMaterialTypes::Character); + list.Add(EMaterialTypes::Player); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(GetMaterialFilter().GetIncludeList(), list)); - CSegId segId = GetModelData()->GetAnimationData()->GetLocatorSegId("lockon_target_LCTR"sv); - if (segId != 0xFF) - { - zeus::CTransform locatorXf = GetTransform() * zeus::CTransform::Scale(GetModelData()->GetScale()) * - GetModelData()->GetAnimationData()->GetLocatorTransform(segId, nullptr); - x5a8_lockonTarget = locatorXf.origin; - x59c_lockonOffset = locatorXf.origin - GetTranslation(); - } - x460_knockBackController.SetAutoResetImpulse(false); + CSegId segId = GetModelData()->GetAnimationData()->GetLocatorSegId("lockon_target_LCTR"sv); + if (segId != 0xFF) { + zeus::CTransform locatorXf = GetTransform() * zeus::CTransform::Scale(GetModelData()->GetScale()) * + GetModelData()->GetAnimationData()->GetLocatorTransform(segId, nullptr); + x5a8_lockonTarget = locatorXf.origin; + x59c_lockonOffset = locatorXf.origin - GetTranslation(); + } + x460_knockBackController.SetAutoResetImpulse(false); } -static const SSphereJointDescription kArmCollision[]= - { - {"Arm_4", 1.5f}, - {"Arm_6", 1.f}, - {"Arm_7", 1.f}, - {"Arm_8", 1.f}, - {"Arm_9", 1.f}, - {"Arm_11", 1.f}, - {"Swoosh_LCTR", 1.5f} - }; +static const SSphereJointDescription kArmCollision[] = {{"Arm_4", 1.5f}, {"Arm_6", 1.f}, {"Arm_7", 1.f}, + {"Arm_8", 1.f}, {"Arm_9", 1.f}, {"Arm_11", 1.f}, + {"Swoosh_LCTR", 1.5f}}; -void CSpankWeed::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - bool oldActive = GetActive(); - if (msg == EScriptObjectMessage::Activate) - { - if (x90_actorLights) - x90_actorLights->SetDirty(); +void CSpankWeed::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + bool oldActive = GetActive(); + if (msg == EScriptObjectMessage::Activate) { + if (x90_actorLights) + x90_actorLights->SetDirty(); + } else if (msg == EScriptObjectMessage::Decrement) { + if (x5b4_ != 0 && x5b4_ != 5 && x5b4_ != 6 && x5b4_ != 4) { + x400_24_hitByPlayerProjectile = true; + x428_damageCooldownTimer = x424_damageWaitTime; } - else if (msg == EScriptObjectMessage::Decrement) - { - if (x5b4_ != 0 && x5b4_ != 5 && x5b4_ != 6 && x5b4_ != 4) - { - x400_24_hitByPlayerProjectile = true; - x428_damageCooldownTimer = x424_damageWaitTime; + } else if (msg == EScriptObjectMessage::Registered) { + if (!x450_bodyController->GetActive()) { + x450_bodyController->Activate(mgr); + zeus::CVector3f extents = GetBoundingBox().extents(); + + SetBoundingBox({-extents, extents}); + } + + std::vector joints; + joints.reserve(12); + + for (const SSphereJointDescription& joint : kArmCollision) { + CSegId id = GetModelData()->GetAnimationData()->GetLocatorSegId(joint.name); + if (id != 0xFF) + joints.push_back(CJointCollisionDescription::SphereCollision(id, joint.radius, joint.name, 0.001f)); + } + + x594_collisionMgr.reset(new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), joints, GetActive())); + CMaterialList list; + list.Add(EMaterialTypes::CameraPassthrough); + list.Add(EMaterialTypes::Immovable); + x594_collisionMgr->AddMaterial(mgr, list); + if (x90_actorLights) { + x90_actorLights->SetDirty(); + zeus::CVector3f swooshOrigin = GetScaledLocatorTransform("swoosh_LCTR"sv).origin; + x90_actorLights->SetActorPositionBias(GetTransform().buildMatrix3f() * swooshOrigin); + } + } else if (msg == EScriptObjectMessage::Touched) { + if (TCastToPtr colAct = mgr.ObjectById(uid)) { + if (TCastToPtr player = mgr.ObjectById(colAct->GetLastTouchedObject())) { + if (x420_curDamageRemTime <= 0.f && x5b4_ != 4 && x5b4_ != 6) { + mgr.ApplyDamage(GetUniqueId(), player->GetUniqueId(), GetUniqueId(), GetContactDamage(), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + x420_curDamageRemTime = x424_damageWaitTime; } + } } - else if (msg == EScriptObjectMessage::Registered) - { - if (!x450_bodyController->GetActive()) - { - x450_bodyController->Activate(mgr); - zeus::CVector3f extents = GetBoundingBox().extents(); + } else if (msg == EScriptObjectMessage::Deleted) { + mgr.FreeScriptObject(x590_); + x594_collisionMgr->Destroy(mgr); + } else if (msg == EScriptObjectMessage::SuspendedMove) { + x594_collisionMgr->SetMovable(mgr, false); + } - SetBoundingBox({-extents, extents}); - } + CPatterned::AcceptScriptMsg(msg, uid, mgr); - std::vector joints; - joints.reserve(12); - - for (const SSphereJointDescription& joint : kArmCollision) - { - CSegId id = GetModelData()->GetAnimationData()->GetLocatorSegId(joint.name); - if (id != 0xFF) - joints.push_back(CJointCollisionDescription::SphereCollision(id, joint.radius, joint.name, 0.001f)); - } - - x594_collisionMgr.reset(new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), joints, GetActive())); - CMaterialList list; - list.Add(EMaterialTypes::CameraPassthrough); - list.Add(EMaterialTypes::Immovable); - x594_collisionMgr->AddMaterial(mgr, list); - if (x90_actorLights) - { - x90_actorLights->SetDirty(); - zeus::CVector3f swooshOrigin = GetScaledLocatorTransform("swoosh_LCTR"sv).origin; - x90_actorLights->SetActorPositionBias(GetTransform().buildMatrix3f() * swooshOrigin); - } - } - else if (msg == EScriptObjectMessage::Touched) - { - if (TCastToPtr colAct = mgr.ObjectById(uid)) - { - if (TCastToPtr player = mgr.ObjectById(colAct->GetLastTouchedObject())) - { - if (x420_curDamageRemTime <= 0.f && x5b4_ != 4 && x5b4_ != 6) - { - mgr.ApplyDamage(GetUniqueId(), player->GetUniqueId(), GetUniqueId(), GetContactDamage(), - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); - x420_curDamageRemTime = x424_damageWaitTime; - } - } - } - } - else if (msg == EScriptObjectMessage::Deleted) - { - mgr.FreeScriptObject(x590_); - x594_collisionMgr->Destroy(mgr); - } - else if (msg == EScriptObjectMessage::SuspendedMove) - { - x594_collisionMgr->SetMovable(mgr, false); - } - - CPatterned::AcceptScriptMsg(msg, uid, mgr); - - if (GetActive() != oldActive) - x594_collisionMgr.reset(); + if (GetActive() != oldActive) + x594_collisionMgr.reset(); } -void CSpankWeed::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; +void CSpankWeed::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; - HealthInfo(mgr)->SetHP(1000000.0f); + HealthInfo(mgr)->SetHP(1000000.0f); - if (!x598_isHiding) - { - zeus::CVector3f eyeOrigin = GetLocatorTransform("Eye"sv).origin; - MoveCollisionPrimitive(GetModelData()->GetScale() * eyeOrigin); - x594_collisionMgr->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); - xe4_27_notInSortedLists = true; - } + if (!x598_isHiding) { + zeus::CVector3f eyeOrigin = GetLocatorTransform("Eye"sv).origin; + MoveCollisionPrimitive(GetModelData()->GetScale() * eyeOrigin); + x594_collisionMgr->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); + xe4_27_notInSortedLists = true; + } - CPatterned::Think(dt, mgr); + CPatterned::Think(dt, mgr); } -zeus::CVector3f CSpankWeed::GetOrbitPosition(const CStateManager& mgr) const -{ - zeus::CVector3f ret = CPatterned::GetOrbitPosition(mgr); - float delay = std::max(1.f, x330_stateMachineState.GetDelay()); - if (x5b4_ == 3 && x5b8_ == 2) - { - return (ret * (1.f - delay) + ((GetTranslation() + x59c_lockonOffset) * delay)); - } - else if (x5b4_ == 2 && x5b8_ == 3) - { - return (GetTranslation() + x59c_lockonOffset) * (1.f - delay) + (ret * delay); - } - return ret; +zeus::CVector3f CSpankWeed::GetOrbitPosition(const CStateManager& mgr) const { + zeus::CVector3f ret = CPatterned::GetOrbitPosition(mgr); + float delay = std::max(1.f, x330_stateMachineState.GetDelay()); + if (x5b4_ == 3 && x5b8_ == 2) { + return (ret * (1.f - delay) + ((GetTranslation() + x59c_lockonOffset) * delay)); + } else if (x5b4_ == 2 && x5b8_ == 3) { + return (GetTranslation() + x59c_lockonOffset) * (1.f - delay) + (ret * delay); + } + return ret; } -zeus::CVector3f CSpankWeed::GetAimPosition(const CStateManager&, float dt) const -{ - zeus::CVector3f pos = (dt > 0.f ? PredictMotion(dt).x0_translation : zeus::CVector3f::skZero); +zeus::CVector3f CSpankWeed::GetAimPosition(const CStateManager&, float dt) const { + zeus::CVector3f pos = (dt > 0.f ? PredictMotion(dt).x0_translation : zeus::CVector3f::skZero); - CSegId id = GetModelData()->GetAnimationData()->GetLocatorSegId("lockon_target_LCTR"sv); - if (id != 0xFF) - { - zeus::CVector3f lockonOff = GetModelData()->GetAnimationData()->GetLocatorTransform(id, nullptr).origin; - return pos + (GetTransform() * (GetModelData()->GetScale() * lockonOff)); - } + CSegId id = GetModelData()->GetAnimationData()->GetLocatorSegId("lockon_target_LCTR"sv); + if (id != 0xFF) { + zeus::CVector3f lockonOff = GetModelData()->GetAnimationData()->GetLocatorTransform(id, nullptr).origin; + return pos + (GetTransform() * (GetModelData()->GetScale() * lockonOff)); + } - return pos + GetBoundingBox().center(); + return pos + GetBoundingBox().center(); } -void CSpankWeed::Flinch(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x5bc_ = 0; - x5b4_ = 0; - RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); - } - else if (msg == EStateMsg::Update) - { - if (x5bc_ == 0) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::KnockBack) - x5bc_ = 2; - else - x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockBackCmd({}, pas::ESeverity::Zero)); - } - else if (x5bc_ == 2 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::KnockBack) - x5bc_ = 3; - } - else if (msg == EStateMsg::Deactivate) - { - x5b8_ = 4; - } +void CSpankWeed::Flinch(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x5bc_ = 0; + x5b4_ = 0; + RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); + } else if (msg == EStateMsg::Update) { + if (x5bc_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::KnockBack) + x5bc_ = 2; + else + x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockBackCmd({}, pas::ESeverity::Zero)); + } else if (x5bc_ == 2 && + x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::KnockBack) + x5bc_ = 3; + } else if (msg == EStateMsg::Deactivate) { + x5b8_ = 4; + } } -bool CSpankWeed::Delay(CStateManager&, float) -{ - if (x400_24_hitByPlayerProjectile) - { - if (x330_stateMachineState.GetTime() > x578_hideTime) - { - x400_24_hitByPlayerProjectile = false; - return true; - } - return false; +bool CSpankWeed::Delay(CStateManager&, float) { + if (x400_24_hitByPlayerProjectile) { + if (x330_stateMachineState.GetTime() > x578_hideTime) { + x400_24_hitByPlayerProjectile = false; + return true; } + return false; + } - return true; + return true; } -bool CSpankWeed::InRange(CStateManager& mgr, float) -{ - float playerDist = GetPlayerDistance(mgr); - if (x56c_detectionHeightRange > 0.f) - { - return std::fabs(mgr.GetPlayer().GetTranslation().z - GetTranslation().z) < x56c_detectionHeightRange && - playerDist < (x574_maxSightRange * x574_maxSightRange); - } +bool CSpankWeed::InRange(CStateManager& mgr, float) { + float playerDist = GetPlayerDistance(mgr); + if (x56c_detectionHeightRange > 0.f) { + return std::fabs(mgr.GetPlayer().GetTranslation().z() - GetTranslation().z()) < x56c_detectionHeightRange && + playerDist < (x574_maxSightRange * x574_maxSightRange); + } - return playerDist < (x574_maxSightRange * x574_maxSightRange); + return playerDist < (x574_maxSightRange * x574_maxSightRange); } -bool CSpankWeed::HearPlayer(CStateManager& mgr, float) -{ - float playerDist = GetPlayerDistance(mgr); - if (x56c_detectionHeightRange > 0.f) - { - return std::fabs(mgr.GetPlayer().GetTranslation().z - GetTranslation().z) < x56c_detectionHeightRange && - playerDist < (x570_maxHearingRange * x570_maxHearingRange); - } +bool CSpankWeed::HearPlayer(CStateManager& mgr, float) { + float playerDist = GetPlayerDistance(mgr); + if (x56c_detectionHeightRange > 0.f) { + return std::fabs(mgr.GetPlayer().GetTranslation().z() - GetTranslation().z()) < x56c_detectionHeightRange && + playerDist < (x570_maxHearingRange * x570_maxHearingRange); + } - return playerDist < (x570_maxHearingRange * x570_maxHearingRange); + return playerDist < (x570_maxHearingRange * x570_maxHearingRange); } -bool CSpankWeed::InDetectionRange(CStateManager& mgr, float) -{ - float playerDist = GetPlayerDistance(mgr); - if (x56c_detectionHeightRange > 0.f) - { - return std::fabs(mgr.GetPlayer().GetTranslation().z - GetTranslation().z) < x56c_detectionHeightRange && - playerDist < (x568_maxDetectionRange * x568_maxDetectionRange); - } +bool CSpankWeed::InDetectionRange(CStateManager& mgr, float) { + float playerDist = GetPlayerDistance(mgr); + if (x56c_detectionHeightRange > 0.f) { + return std::fabs(mgr.GetPlayer().GetTranslation().z() - GetTranslation().z()) < x56c_detectionHeightRange && + playerDist < (x568_maxDetectionRange * x568_maxDetectionRange); + } - return playerDist < (x568_maxDetectionRange * x568_maxDetectionRange); + return playerDist < (x568_maxDetectionRange * x568_maxDetectionRange); } -void CSpankWeed::Attack(CStateManager&, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::Zero)); - } - else if (msg == EStateMsg::Update) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack) - return; +void CSpankWeed::Attack(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::Zero)); + } else if (msg == EStateMsg::Update) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack) + return; - x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::Zero)); - } - else if (msg == EStateMsg::Deactivate) - { - x5b8_ = 3; - } + x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::Zero)); + } else if (msg == EStateMsg::Deactivate) { + x5b8_ = 3; + } } -void CSpankWeed::TargetPatrol(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); - RemoveMaterial(EMaterialTypes::Solid, mgr); - x5b4_ = 2; - } - else if (msg == EStateMsg::Deactivate) - { - x5b8_ = 2; - } +void CSpankWeed::TargetPatrol(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat); + RemoveMaterial(EMaterialTypes::Solid, mgr); + x5b4_ = 2; + } else if (msg == EStateMsg::Deactivate) { + x5b8_ = 2; + } } -void CSpankWeed::Lurk(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x460_knockBackController.SetEnableFreeze(true); - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); - RemoveMaterial(EMaterialTypes::Solid, mgr); - x5b4_ = 1; - } - else if (msg == EStateMsg::Deactivate) - { - x5b8_ = 1; - } +void CSpankWeed::Lurk(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x460_knockBackController.SetEnableFreeze(true); + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); + RemoveMaterial(EMaterialTypes::Solid, mgr); + x5b4_ = 1; + } else if (msg == EStateMsg::Deactivate) { + x5b8_ = 1; + } } -void CSpankWeed::FadeOut(CStateManager&, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x5bc_ = 0; - x57c_canKnockBack = false; - x5b4_ = 6; - } - else if (msg == EStateMsg::Update) - { - if (x5bc_ == 0) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Step) - x5bc_ = 2; - else - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::Normal)); +void CSpankWeed::FadeOut(CStateManager&, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x5bc_ = 0; + x57c_canKnockBack = false; + x5b4_ = 6; + } else if (msg == EStateMsg::Update) { + if (x5bc_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Step) + x5bc_ = 2; + else + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCStepCmd(pas::EStepDirection::Backward, pas::EStepType::Normal)); - } - else if (x5bc_ == 2) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Step) - x5bc_ = 3; - } - } - else if (msg == EStateMsg::Deactivate) - { - x5b8_ = 6; + } else if (x5bc_ == 2) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Step) + x5bc_ = 3; } + } else if (msg == EStateMsg::Deactivate) { + x5b8_ = 6; + } } -void CSpankWeed::FadeIn(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x5bc_ = 0; - x57c_canKnockBack = true; - x5b4_ = 5; - } - else if (msg == EStateMsg::Update) - { - if (x5bc_ == 0) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Step) - x5bc_ = 2; - else - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCStepCmd(pas::EStepDirection::Forward, pas::EStepType::Normal)); +void CSpankWeed::FadeIn(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x5bc_ = 0; + x57c_canKnockBack = true; + x5b4_ = 5; + } else if (msg == EStateMsg::Update) { + if (x5bc_ == 0) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Step) + x5bc_ = 2; + else + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCStepCmd(pas::EStepDirection::Forward, pas::EStepType::Normal)); - } - else if (x5bc_ == 2) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Step) - x5bc_ = 3; - } - } - else if (msg == EStateMsg::Deactivate) - { - x5b8_ = 5; + } else if (x5bc_ == 2) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Step) + x5bc_ = 3; } + } else if (msg == EStateMsg::Deactivate) { + x5b8_ = 5; + } - xe7_28_worldLightingDirty = true; + xe7_28_worldLightingDirty = true; } -void CSpankWeed::Patrol(CStateManager& mgr, EStateMsg msg, float) -{ - if (msg == EStateMsg::Activate) - { - x460_knockBackController.SetEnableFreeze(false); - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); - RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::Scannable, mgr); - RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); - x594_collisionMgr->SetActive(mgr, false); - x598_isHiding = true; - x5b4_ = 0; - } - else if (msg == EStateMsg::Deactivate) - { - AddMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, EMaterialTypes::Scannable, mgr); - SetTranslation(x584_retreatOrigin); - x594_collisionMgr->SetActive(mgr, true); - x598_isHiding = false; - x460_knockBackController.SetEnableFreeze(true); - x5b8_ = 0; - } +void CSpankWeed::Patrol(CStateManager& mgr, EStateMsg msg, float) { + if (msg == EStateMsg::Activate) { + x460_knockBackController.SetEnableFreeze(false); + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::Scannable, mgr); + RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr); + x594_collisionMgr->SetActive(mgr, false); + x598_isHiding = true; + x5b4_ = 0; + } else if (msg == EStateMsg::Deactivate) { + AddMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, EMaterialTypes::Scannable, mgr); + SetTranslation(x584_retreatOrigin); + x594_collisionMgr->SetActive(mgr, true); + x598_isHiding = false; + x460_knockBackController.SetEnableFreeze(true); + x5b8_ = 0; + } } void CSpankWeed::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, const CDamageInfo& info, - EKnockBackType type, bool inDeferred, float magnitude) -{ - if (!x57c_canKnockBack) - return; - CPatterned::KnockBack(backVec, mgr, info, type, inDeferred, magnitude); - x57c_canKnockBack = false; + EKnockBackType type, bool inDeferred, float magnitude) { + if (!x57c_canKnockBack) + return; + CPatterned::KnockBack(backVec, mgr, info, type, inDeferred, magnitude); + x57c_canKnockBack = false; } -float CSpankWeed::GetPlayerDistance(CStateManager& mgr) const -{ - return (mgr.GetPlayer().GetTranslation() - x5a8_lockonTarget).magSquared(); +float CSpankWeed::GetPlayerDistance(CStateManager& mgr) const { + return (mgr.GetPlayer().GetTranslation() - x5a8_lockonTarget).magSquared(); } -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CSpankWeed.hpp b/Runtime/MP1/World/CSpankWeed.hpp index 57f152fa0..3c3ade4c3 100644 --- a/Runtime/MP1/World/CSpankWeed.hpp +++ b/Runtime/MP1/World/CSpankWeed.hpp @@ -3,51 +3,50 @@ #include "World/CPatterned.hpp" #include "Collision/CCollisionActorManager.hpp" -namespace urde::MP1 -{ -class CSpankWeed : public CPatterned -{ - float x568_maxDetectionRange; - float x56c_detectionHeightRange; - float x570_maxHearingRange; - float x574_maxSightRange; - float x578_hideTime; - bool x57c_canKnockBack = false; - /* float x580_ = 0.f; unused */ - zeus::CVector3f x584_retreatOrigin; - TUniqueId x590_ = kInvalidUniqueId; - std::unique_ptr x594_collisionMgr; - bool x598_isHiding = true; - zeus::CVector3f x59c_lockonOffset; - zeus::CVector3f x5a8_lockonTarget; - s32 x5b4_ = -1; - s32 x5b8_ = -1; - s32 x5bc_ = -1; +namespace urde::MP1 { +class CSpankWeed : public CPatterned { + float x568_maxDetectionRange; + float x56c_detectionHeightRange; + float x570_maxHearingRange; + float x574_maxSightRange; + float x578_hideTime; + bool x57c_canKnockBack = false; + /* float x580_ = 0.f; unused */ + zeus::CVector3f x584_retreatOrigin; + TUniqueId x590_ = kInvalidUniqueId; + std::unique_ptr x594_collisionMgr; + bool x598_isHiding = true; + zeus::CVector3f x59c_lockonOffset; + zeus::CVector3f x5a8_lockonTarget; + s32 x5b4_ = -1; + s32 x5b8_ = -1; + s32 x5bc_ = -1; + + float GetPlayerDistance(CStateManager&) const; - float GetPlayerDistance(CStateManager&) const; public: - DEFINE_PATTERNED(SpankWeed) + DEFINE_PATTERNED(SpankWeed) - CSpankWeed(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CActorParameters&, const CPatternedInfo&, float, float, float, float); + CSpankWeed(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const CPatternedInfo&, float, float, float, float); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - zeus::CVector3f GetOrbitPosition(const CStateManager&) const; - zeus::CVector3f GetAimPosition(const CStateManager&, float) const; - bool AnimOver(CStateManager&, float) { return x5bc_ == 3; } - void Flinch(CStateManager&, EStateMsg, float); - bool Delay(CStateManager&, float); - bool InRange(CStateManager&, float); - bool HearPlayer(CStateManager&, float); - bool InDetectionRange(CStateManager&, float); - void Attack(CStateManager&, EStateMsg, float); - void TargetPatrol(CStateManager&, EStateMsg, float); - void Lurk(CStateManager&, EStateMsg, float); - void FadeOut(CStateManager&, EStateMsg, float); - void FadeIn(CStateManager&, EStateMsg, float); - void Patrol(CStateManager&, EStateMsg, float); - void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, - EKnockBackType type, bool inDeferred, float magnitude); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + zeus::CVector3f GetOrbitPosition(const CStateManager&) const; + zeus::CVector3f GetAimPosition(const CStateManager&, float) const; + bool AnimOver(CStateManager&, float) { return x5bc_ == 3; } + void Flinch(CStateManager&, EStateMsg, float); + bool Delay(CStateManager&, float); + bool InRange(CStateManager&, float); + bool HearPlayer(CStateManager&, float); + bool InDetectionRange(CStateManager&, float); + void Attack(CStateManager&, EStateMsg, float); + void TargetPatrol(CStateManager&, EStateMsg, float); + void Lurk(CStateManager&, EStateMsg, float); + void FadeOut(CStateManager&, EStateMsg, float); + void FadeIn(CStateManager&, EStateMsg, float); + void Patrol(CStateManager&, EStateMsg, float); + void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, EKnockBackType type, bool inDeferred, + float magnitude); }; -} \ No newline at end of file +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CThardusRockProjectile.cpp b/Runtime/MP1/World/CThardusRockProjectile.cpp index 1425d1c31..6f971be40 100644 --- a/Runtime/MP1/World/CThardusRockProjectile.cpp +++ b/Runtime/MP1/World/CThardusRockProjectile.cpp @@ -1,16 +1,13 @@ #include "CThardusRockProjectile.hpp" -namespace urde -{ +namespace urde { -CThardusRockProjectile::CThardusRockProjectile( - TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& modelData, const CActorParameters& aParms, - const CPatternedInfo& patternedInfo, const std::vector& mDataVec, u32) +CThardusRockProjectile::CThardusRockProjectile(TUniqueId uid, std::string_view name, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& modelData, + const CActorParameters& aParms, const CPatternedInfo& patternedInfo, + const std::vector& mDataVec, u32) : CPatterned(ECharacter::ThardusRockProjectile, uid, name, EFlavorType::Zero, info, xf, std::move(modelData), - patternedInfo, EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Medium) -{ + patternedInfo, EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, + EKnockBackVariant::Medium) {} -} - -} +} // namespace urde diff --git a/Runtime/MP1/World/CThardusRockProjectile.hpp b/Runtime/MP1/World/CThardusRockProjectile.hpp index 306b252b9..915338b7c 100644 --- a/Runtime/MP1/World/CThardusRockProjectile.hpp +++ b/Runtime/MP1/World/CThardusRockProjectile.hpp @@ -2,17 +2,14 @@ #include "World/CPatterned.hpp" -namespace urde -{ +namespace urde { -class CThardusRockProjectile : public CPatterned -{ +class CThardusRockProjectile : public CPatterned { public: - DEFINE_PATTERNED(ThardusRockProjectile) - CThardusRockProjectile(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& modelData, const CActorParameters& aParms, - const CPatternedInfo& patternedInfo, const std::vector& mDataVec, u32); + DEFINE_PATTERNED(ThardusRockProjectile) + CThardusRockProjectile(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& modelData, const CActorParameters& aParms, const CPatternedInfo& patternedInfo, + const std::vector& mDataVec, u32); }; -} - +} // namespace urde diff --git a/Runtime/MP1/World/CTryclops.cpp b/Runtime/MP1/World/CTryclops.cpp index 61440d64d..a6e0e69d8 100644 --- a/Runtime/MP1/World/CTryclops.cpp +++ b/Runtime/MP1/World/CTryclops.cpp @@ -1,10 +1,9 @@ #include "CTryclops.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CTryclops::CTryclops(urde::TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - urde::CModelData&& mData, const urde::CPatternedInfo& pInfo, const urde::CActorParameters& actParms, float, float, float, float) + urde::CModelData&& mData, const urde::CPatternedInfo& pInfo, + const urde::CActorParameters& actParms, float, float, float, float) : CPatterned(ECharacter::Tryclops, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, - EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Small) -{} -} \ No newline at end of file + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Small) {} +} // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/MP1/World/CTryclops.hpp b/Runtime/MP1/World/CTryclops.hpp index 314743a0c..a846c17af 100644 --- a/Runtime/MP1/World/CTryclops.hpp +++ b/Runtime/MP1/World/CTryclops.hpp @@ -2,13 +2,11 @@ #include "World/CPatterned.hpp" -namespace urde::MP1 -{ -class CTryclops : public CPatterned -{ +namespace urde::MP1 { +class CTryclops : public CPatterned { public: - DEFINE_PATTERNED(Tryclops) - CTryclops(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CPatternedInfo&, const CActorParameters&, float, float, float, float); + DEFINE_PATTERNED(Tryclops) + CTryclops(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CPatternedInfo&, const CActorParameters&, float, float, float, float); }; -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CWarWasp.cpp b/Runtime/MP1/World/CWarWasp.cpp index 1fc0c8798..b3500f231 100644 --- a/Runtime/MP1/World/CWarWasp.cpp +++ b/Runtime/MP1/World/CWarWasp.cpp @@ -2,16 +2,13 @@ #include "Character/CCharLayoutInfo.hpp" #include "TCastTo.hpp" -namespace urde::MP1 -{ +namespace urde::MP1 { CWarWasp::CWarWasp(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, CPatterned::EFlavorType flavor, CPatterned::EColliderType collider, const CDamageInfo& dInfo1, const CActorParameters& actorParms, CAssetId weapon, const CDamageInfo& dInfo2, CAssetId particle, u32 w3) : CPatterned(ECharacter::WarWasp, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, collider, - EBodyType::Flyer, actorParms, EKnockBackVariant::Small) -{ -} + EBodyType::Flyer, actorParms, EKnockBackVariant::Small) {} void CWarWasp::Accept(IVisitor& visitor) { visitor.Visit(this); } -} +} // namespace urde::MP1 diff --git a/Runtime/MP1/World/CWarWasp.hpp b/Runtime/MP1/World/CWarWasp.hpp index e6e407c2c..a58b3b9a3 100644 --- a/Runtime/MP1/World/CWarWasp.hpp +++ b/Runtime/MP1/World/CWarWasp.hpp @@ -2,22 +2,18 @@ #include "World/CPatterned.hpp" -namespace urde -{ +namespace urde { class CDamageInfo; -namespace MP1 -{ -class CWarWasp : public CPatterned -{ +namespace MP1 { +class CWarWasp : public CPatterned { public: - DEFINE_PATTERNED(WarWasp) - CWarWasp(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, - CPatterned::EFlavorType flavor, CPatterned::EColliderType, const CDamageInfo& dInfo1, - const CActorParameters&, CAssetId weapon, const CDamageInfo& dInfo2, CAssetId particle, u32 w3); + DEFINE_PATTERNED(WarWasp) + CWarWasp(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CPatternedInfo& pInfo, CPatterned::EFlavorType flavor, CPatterned::EColliderType, + const CDamageInfo& dInfo1, const CActorParameters&, CAssetId weapon, const CDamageInfo& dInfo2, + CAssetId particle, u32 w3); - void Accept(IVisitor &visitor); + void Accept(IVisitor& visitor); }; -} -} - +} // namespace MP1 +} // namespace urde diff --git a/Runtime/Particle/CColorElement.cpp b/Runtime/Particle/CColorElement.cpp index 2af23e142..c131b007e 100644 --- a/Runtime/Particle/CColorElement.cpp +++ b/Runtime/Particle/CColorElement.cpp @@ -7,157 +7,136 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Color_Elements */ -namespace urde -{ +namespace urde { -CCEKeyframeEmitter::CCEKeyframeEmitter(CInputStream& in) -{ - x4_percent = in.readUint32Big(); - x8_unk1 = in.readUint32Big(); - xc_loop = in.readBool(); - xd_unk2 = in.readBool(); - x10_loopEnd = in.readUint32Big(); - x14_loopStart = in.readUint32Big(); +CCEKeyframeEmitter::CCEKeyframeEmitter(CInputStream& in) { + x4_percent = in.readUint32Big(); + x8_unk1 = in.readUint32Big(); + xc_loop = in.readBool(); + xd_unk2 = in.readBool(); + x10_loopEnd = in.readUint32Big(); + x14_loopStart = in.readUint32Big(); - u32 count = in.readUint32Big(); - x18_keys.reserve(count); - for (u32 i=0 ; i= x10_loopEnd) - { - int v1 = emitterTime - x14_loopStart; - int v2 = x10_loopEnd - x14_loopStart; - calcKey = v1 % v2; - calcKey += x14_loopStart; - } - } - else - { - int v1 = x10_loopEnd - 1; - if (v1 < emitterTime) - calcKey = v1; - } - valOut = x18_keys[calcKey]; +bool CCEKeyframeEmitter::GetValue(int frame, zeus::CColor& valOut) const { + if (!x4_percent) { + int emitterTime = CParticleGlobals::g_EmitterTime; + int calcKey = emitterTime; + if (xc_loop) { + if (emitterTime >= x10_loopEnd) { + int v1 = emitterTime - x14_loopStart; + int v2 = x10_loopEnd - x14_loopStart; + calcKey = v1 % v2; + calcKey += x14_loopStart; + } + } else { + int v1 = x10_loopEnd - 1; + if (v1 < emitterTime) + calcKey = v1; } + valOut = x18_keys[calcKey]; + } else { + int ltPerc = CParticleGlobals::g_ParticleLifetimePercentage; + float ltPercRem = CParticleGlobals::g_ParticleLifetimePercentageRemainder; + if (ltPerc == 100) + valOut = x18_keys[100]; else - { - int ltPerc = CParticleGlobals::g_ParticleLifetimePercentage; - float ltPercRem = CParticleGlobals::g_ParticleLifetimePercentageRemainder; - if (ltPerc == 100) - valOut = x18_keys[100]; - else - valOut = ltPercRem * x18_keys[ltPerc+1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; - } - return false; + valOut = ltPercRem * x18_keys[ltPerc + 1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; + } + return false; } -bool CCEConstant::GetValue(int frame, zeus::CColor& valOut) const -{ - float r, g, b, a; - x4_r->GetValue(frame, r); - x8_g->GetValue(frame, g); - xc_b->GetValue(frame, b); - x10_a->GetValue(frame, a); - valOut = zeus::CColor(r, g, b, a); - return false; +bool CCEConstant::GetValue(int frame, zeus::CColor& valOut) const { + float r, g, b, a; + x4_r->GetValue(frame, r); + x8_g->GetValue(frame, g); + xc_b->GetValue(frame, b); + x10_a->GetValue(frame, a); + valOut = zeus::CColor(r, g, b, a); + return false; } -bool CCEFastConstant::GetValue(int frame, zeus::CColor& valOut) const -{ - valOut = x4_val; - return false; +bool CCEFastConstant::GetValue(int frame, zeus::CColor& valOut) const { + valOut = x4_val; + return false; } -bool CCETimeChain::GetValue(int frame, zeus::CColor& valOut) const -{ - int v; - xc_swFrame->GetValue(frame, v); - if (frame >= v) - return x8_b->GetValue(frame, valOut); +bool CCETimeChain::GetValue(int frame, zeus::CColor& valOut) const { + int v; + xc_swFrame->GetValue(frame, v); + if (frame >= v) + return x8_b->GetValue(frame, valOut); + else + return x4_a->GetValue(frame, valOut); +} + +bool CCEFadeEnd::GetValue(int frame, zeus::CColor& valOut) const { + float c; + xc_startFrame->GetValue(frame, c); + + if (frame < c) { + x4_a->GetValue(frame, valOut); + return false; + } + + float d; + x10_endFrame->GetValue(frame, d); + + zeus::CColor colA; + zeus::CColor colB; + x4_a->GetValue(frame, colA); + x8_b->GetValue(frame, colB); + + float t = (frame - c) / (d - c); + valOut = zeus::CColor::lerp(colA, colB, t); + return false; +} + +bool CCEFade::GetValue(int frame, zeus::CColor& valOut) const { + float c; + xc_endFrame->GetValue(frame, c); + + float t = frame / c; + if (t > 1.f) { + x8_b->GetValue(frame, valOut); + return false; + } + + zeus::CColor colA; + zeus::CColor colB; + x4_a->GetValue(frame, colA); + x8_b->GetValue(frame, colB); + + valOut = zeus::CColor::lerp(colA, colB, t); + return false; +} + +bool CCEPulse::GetValue(int frame, zeus::CColor& valOut) const { + int a, b; + x4_aDuration->GetValue(frame, a); + x8_bDuration->GetValue(frame, b); + int cv = zeus::max(1, a + b + 1); + + if (b >= 1) { + int cv2 = frame % cv; + if (cv2 >= a) + x10_bVal->GetValue(frame, valOut); else - return x4_a->GetValue(frame, valOut); + xc_aVal->GetValue(frame, valOut); + } else + xc_aVal->GetValue(frame, valOut); + + return false; } -bool CCEFadeEnd::GetValue(int frame, zeus::CColor& valOut) const -{ - float c; - xc_startFrame->GetValue(frame, c); - - if (frame < c) - { - x4_a->GetValue(frame, valOut); - return false; - } - - float d; - x10_endFrame->GetValue(frame, d); - - zeus::CColor colA; - zeus::CColor colB; - x4_a->GetValue(frame, colA); - x8_b->GetValue(frame, colB); - - float t = (frame - c) / (d - c); - valOut = zeus::CColor::lerp(colA, colB, t); - return false; +bool CCEParticleColor::GetValue(int /*frame*/, zeus::CColor& colorOut) const { + colorOut = CElementGen::g_currentParticle->x34_color; + return false; } -bool CCEFade::GetValue(int frame, zeus::CColor& valOut) const -{ - float c; - xc_endFrame->GetValue(frame, c); - - float t = frame / c; - if (t > 1.f) - { - x8_b->GetValue(frame, valOut); - return false; - } - - zeus::CColor colA; - zeus::CColor colB; - x4_a->GetValue(frame, colA); - x8_b->GetValue(frame, colB); - - valOut = zeus::CColor::lerp(colA, colB, t); - return false; -} - -bool CCEPulse::GetValue(int frame, zeus::CColor& valOut) const -{ - int a, b; - x4_aDuration->GetValue(frame, a); - x8_bDuration->GetValue(frame, b); - int cv = zeus::max(1, a + b + 1); - - if (b >= 1) - { - int cv2 = frame % cv; - if (cv2 >= a) - x10_bVal->GetValue(frame, valOut); - else - xc_aVal->GetValue(frame, valOut); - } - else - xc_aVal->GetValue(frame, valOut); - - return false; -} - -bool CCEParticleColor::GetValue(int /*frame*/, zeus::CColor& colorOut) const -{ - colorOut = CElementGen::g_currentParticle->x34_color; - return false; -} - -} +} // namespace urde diff --git a/Runtime/Particle/CColorElement.hpp b/Runtime/Particle/CColorElement.hpp index 43e5e9337..43afa36af 100644 --- a/Runtime/Particle/CColorElement.hpp +++ b/Runtime/Particle/CColorElement.hpp @@ -4,99 +4,93 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Color_Elements */ -namespace urde -{ +namespace urde { + +class CCEKeyframeEmitter : public CColorElement { + u32 x4_percent; + u32 x8_unk1; + bool xc_loop; + bool xd_unk2; + s32 x10_loopEnd; + s32 x14_loopStart; + std::vector x18_keys; -class CCEKeyframeEmitter : public CColorElement -{ - u32 x4_percent; - u32 x8_unk1; - bool xc_loop; - bool xd_unk2; - s32 x10_loopEnd; - s32 x14_loopStart; - std::vector x18_keys; public: - CCEKeyframeEmitter(CInputStream& in); - bool GetValue(int frame, zeus::CColor& colorOut) const; + CCEKeyframeEmitter(CInputStream& in); + bool GetValue(int frame, zeus::CColor& colorOut) const; }; -class CCEConstant : public CColorElement -{ - std::unique_ptr x4_r; - std::unique_ptr x8_g; - std::unique_ptr xc_b; - std::unique_ptr x10_a; +class CCEConstant : public CColorElement { + std::unique_ptr x4_r; + std::unique_ptr x8_g; + std::unique_ptr xc_b; + std::unique_ptr x10_a; + public: - CCEConstant(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d) - : x4_r(std::move(a)), x8_g(std::move(b)), xc_b(std::move(c)), x10_a(std::move(d)) {} - bool GetValue(int frame, zeus::CColor& colorOut) const; + CCEConstant(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d) + : x4_r(std::move(a)), x8_g(std::move(b)), xc_b(std::move(c)), x10_a(std::move(d)) {} + bool GetValue(int frame, zeus::CColor& colorOut) const; }; -class CCEFastConstant : public CColorElement -{ - zeus::CColor x4_val; +class CCEFastConstant : public CColorElement { + zeus::CColor x4_val; + public: - CCEFastConstant(float a, float b, float c, float d) - : x4_val(a, b, c, d) {} - bool GetValue(int frame, zeus::CColor& colorOut) const; + CCEFastConstant(float a, float b, float c, float d) : x4_val(a, b, c, d) {} + bool GetValue(int frame, zeus::CColor& colorOut) const; }; -class CCETimeChain : public CColorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_swFrame; +class CCETimeChain : public CColorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_swFrame; + public: - CCETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} - bool GetValue(int frame, zeus::CColor& colorOut) const; + CCETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} + bool GetValue(int frame, zeus::CColor& colorOut) const; }; -class CCEFadeEnd : public CColorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_startFrame; - std::unique_ptr x10_endFrame; +class CCEFadeEnd : public CColorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_startFrame; + std::unique_ptr x10_endFrame; + public: - CCEFadeEnd(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_startFrame(std::move(c)), x10_endFrame(std::move(d)) {} - bool GetValue(int frame, zeus::CColor& colorOut) const; + CCEFadeEnd(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d) + : x4_a(std::move(a)), x8_b(std::move(b)), xc_startFrame(std::move(c)), x10_endFrame(std::move(d)) {} + bool GetValue(int frame, zeus::CColor& colorOut) const; }; -class CCEFade : public CColorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_endFrame; +class CCEFade : public CColorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_endFrame; + public: - CCEFade(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_endFrame(std::move(c)) {} - bool GetValue(int frame, zeus::CColor& colorOut) const; + CCEFade(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_a(std::move(a)), x8_b(std::move(b)), xc_endFrame(std::move(c)) {} + bool GetValue(int frame, zeus::CColor& colorOut) const; }; -class CCEPulse : public CColorElement -{ - std::unique_ptr x4_aDuration; - std::unique_ptr x8_bDuration; - std::unique_ptr xc_aVal; - std::unique_ptr x10_bVal; +class CCEPulse : public CColorElement { + std::unique_ptr x4_aDuration; + std::unique_ptr x8_bDuration; + std::unique_ptr xc_aVal; + std::unique_ptr x10_bVal; + public: - CCEPulse(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d) - : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_aVal(std::move(c)), x10_bVal(std::move(d)) {} - bool GetValue(int frame, zeus::CColor& colorOut) const; + CCEPulse(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d) + : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_aVal(std::move(c)), x10_bVal(std::move(d)) {} + bool GetValue(int frame, zeus::CColor& colorOut) const; }; -class CCEParticleColor : public CColorElement -{ +class CCEParticleColor : public CColorElement { public: - bool GetValue(int frame, zeus::CColor& colorOut) const; + bool GetValue(int frame, zeus::CColor& colorOut) const; }; -} - +} // namespace urde diff --git a/Runtime/Particle/CDecal.cpp b/Runtime/Particle/CDecal.cpp index 89ae413f9..13859da36 100644 --- a/Runtime/Particle/CDecal.cpp +++ b/Runtime/Particle/CDecal.cpp @@ -3,322 +3,269 @@ #include "Graphics/Shaders/CDecalShaders.hpp" #include "Graphics/CModel.hpp" -namespace urde -{ +namespace urde { CRandom16 CDecal::sDecalRandom; bool CDecal::sMoveRedToAlphaBuffer = false; CDecal::CDecal(const TToken& desc, const zeus::CTransform& xf) -: x0_description(desc), - xc_transform(xf) -{ - CGlobalRandom gr(sDecalRandom); +: x0_description(desc), xc_transform(xf) { + CGlobalRandom gr(sDecalRandom); - CDecalDescription& desco = *x0_description; - x5c_31_quad1Invalid = InitQuad(x3c_decalQuads[0], desco.x0_Quads[0]); - x5c_30_quad2Invalid = InitQuad(x3c_decalQuads[1], desco.x0_Quads[1]); + CDecalDescription& desco = *x0_description; + x5c_31_quad1Invalid = InitQuad(x3c_decalQuads[0], desco.x0_Quads[0]); + x5c_30_quad2Invalid = InitQuad(x3c_decalQuads[1], desco.x0_Quads[1]); - CDecalDescription* d = x0_description.GetObj(); - if (d->x38_DMDL) - { - if (d->x48_DLFT) - d->x48_DLFT->GetValue(0, x54_modelLifetime); - else - x54_modelLifetime = 0x7FFFFF; - - if (d->x50_DMRT) - d->x50_DMRT->GetValue(0, x60_rotation); - } + CDecalDescription* d = x0_description.GetObj(); + if (d->x38_DMDL) { + if (d->x48_DLFT) + d->x48_DLFT->GetValue(0, x54_modelLifetime); else - x5c_29_modelInvalid = true; + x54_modelLifetime = 0x7FFFFF; - CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) - { - for (int i=0 ; i<2 ; ++i) - { - CQuadDecal& decal = x3c_decalQuads[i]; - if (decal.m_desc->x14_TEX) - decal.m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SParticleInstanceTex), 1); - else - decal.m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SParticleInstanceNoTex), 1); - decal.m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1); - CDecalShaders::BuildShaderDataBinding(ctx, decal); - } - return true; - } BooTrace); -} + if (d->x50_DMRT) + d->x50_DMRT->GetValue(0, x60_rotation); + } else + x5c_29_modelInvalid = true; -bool CDecal::InitQuad(CQuadDecal& quad, const SQuadDescr& desc) -{ - quad.m_desc = &desc; - if (desc.x14_TEX) - { - if (desc.x0_LFT) - desc.x0_LFT->GetValue(0, quad.x4_lifetime); - else - quad.x4_lifetime = 0x7FFFFF; - if (desc.x8_ROT) - { - desc.x8_ROT->GetValue(0, quad.x8_rotation); - quad.x0_24_invalid = desc.x8_ROT->IsConstant(); - } - - if (desc.x4_SZE) - { - quad.x0_24_invalid = desc.x4_SZE->IsConstant(); - float size = 1.f; - desc.x4_SZE->GetValue(0, size); - quad.x0_24_invalid = size <= 1.f; - } - - if (desc.xc_OFF) - quad.x0_24_invalid = desc.xc_OFF->IsFastConstant(); - return false; + CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { + for (int i = 0; i < 2; ++i) { + CQuadDecal& decal = x3c_decalQuads[i]; + if (decal.m_desc->x14_TEX) + decal.m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SParticleInstanceTex), 1); + else + decal.m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(SParticleInstanceNoTex), 1); + decal.m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1); + CDecalShaders::BuildShaderDataBinding(ctx, decal); } - - quad.x0_24_invalid = false; return true; + } BooTrace); } - -void CDecal::SetGlobalSeed(u16 seed) -{ - sDecalRandom.SetSeed(seed); -} - -void CDecal::SetMoveRedToAlphaBuffer(bool move) -{ - sMoveRedToAlphaBuffer = move; -} - -void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const -{ - zeus::CColor color = zeus::CColor::skWhite; - float size = 1.f; - zeus::CVector3f offset; - if (CColorElement* clr = desc.x10_CLR.get()) - clr->GetValue(x58_frameIdx, color); - if (CRealElement* sze = desc.x4_SZE.get()) - { - sze->GetValue(x58_frameIdx, size); - size *= 0.5f; - } - if (CRealElement* rot = desc.x8_ROT.get()) - rot->GetValue(x58_frameIdx, decal.x8_rotation); - if (CVectorElement* off = desc.xc_OFF.get()) - { - off->GetValue(x58_frameIdx, offset); - offset.y() = 0.f; - } - zeus::CTransform modXf = xc_transform; - modXf.origin += offset; - CGraphics::SetModelMatrix(modXf); - - SParticleUniforms uniformData = - { - CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), - {1.f, 1.f, 1.f, 1.f} - }; - decal.m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms)); - - bool redToAlpha = sMoveRedToAlphaBuffer && desc.x18_ADD && desc.x14_TEX; - - SUVElementSet uvSet = {0.f, 1.f, 0.f, 1.f}; - if (CUVElement* tex = desc.x14_TEX.get()) - { - TLockedToken texObj = tex->GetValueTexture(x58_frameIdx); - if (!texObj.IsLoaded()) - return; - tex->GetValueUV(x58_frameIdx, uvSet); - if (redToAlpha) - CGraphics::SetShaderDataBinding(decal.m_redToAlphaDataBind); - else - CGraphics::SetShaderDataBinding(decal.m_normalDataBind); - - g_instTexData.clear(); - g_instTexData.reserve(1); - - g_instTexData.emplace_back(); - SParticleInstanceTex& inst = g_instTexData.back(); - if (decal.x8_rotation == 0.f) - { - inst.pos[0] = zeus::CVector3f(-size, 0.001f, size); - inst.pos[1] = zeus::CVector3f(size, 0.001f, size); - inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size); - inst.pos[3] = zeus::CVector3f(size, 0.001f, -size); - } - else - { - float ang = zeus::degToRad(decal.x8_rotation); - float sinSize = std::sin(ang) * size; - float cosSize = std::cos(ang) * size; - inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize); - inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize); - inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize)); - inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize); - } - inst.color = color; - inst.uvs[0] = zeus::CVector2f(uvSet.xMin, uvSet.yMin); - inst.uvs[1] = zeus::CVector2f(uvSet.xMax, uvSet.yMin); - inst.uvs[2] = zeus::CVector2f(uvSet.xMin, uvSet.yMax); - inst.uvs[3] = zeus::CVector2f(uvSet.xMax, uvSet.yMax); - - decal.m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); - CGraphics::DrawInstances(0, 4, g_instTexData.size()); - } +bool CDecal::InitQuad(CQuadDecal& quad, const SQuadDescr& desc) { + quad.m_desc = &desc; + if (desc.x14_TEX) { + if (desc.x0_LFT) + desc.x0_LFT->GetValue(0, quad.x4_lifetime); else - { - g_instNoTexData.clear(); - g_instNoTexData.reserve(1); - - g_instNoTexData.emplace_back(); - SParticleInstanceNoTex& inst = g_instNoTexData.back(); - if (decal.x8_rotation == 0.f) - { - inst.pos[0] = zeus::CVector3f(-size, 0.001f, size); - inst.pos[1] = zeus::CVector3f(size, 0.001f, size); - inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size); - inst.pos[3] = zeus::CVector3f(size, 0.001f, -size); - } - else - { - float ang = zeus::degToRad(decal.x8_rotation); - float sinSize = std::sin(ang) * size; - float cosSize = std::cos(ang) * size; - inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize); - inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize); - inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize)); - inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize); - } - inst.color = color; - - decal.m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); - CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); + quad.x4_lifetime = 0x7FFFFF; + if (desc.x8_ROT) { + desc.x8_ROT->GetValue(0, quad.x8_rotation); + quad.x0_24_invalid = desc.x8_ROT->IsConstant(); } + + if (desc.x4_SZE) { + quad.x0_24_invalid = desc.x4_SZE->IsConstant(); + float size = 1.f; + desc.x4_SZE->GetValue(0, size); + quad.x0_24_invalid = size <= 1.f; + } + + if (desc.xc_OFF) + quad.x0_24_invalid = desc.xc_OFF->IsFastConstant(); + return false; + } + + quad.x0_24_invalid = false; + return true; } -void CDecal::RenderMdl() const -{ - const CDecalDescription& desc = *x0_description; - zeus::CColor color = zeus::CColor::skWhite; - zeus::CVector3f dmop; - zeus::CTransform rotXf; +void CDecal::SetGlobalSeed(u16 seed) { sDecalRandom.SetSeed(seed); } - if (!desc.x5c_25_DMOO) - rotXf = xc_transform.getRotation(); +void CDecal::SetMoveRedToAlphaBuffer(bool move) { sMoveRedToAlphaBuffer = move; } - bool dmrtIsConst = false; - if (CVectorElement* dmrt = desc.x50_DMRT.get()) - dmrtIsConst = dmrt->IsFastConstant(); +void CDecal::RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const { + zeus::CColor color = zeus::CColor::skWhite; + float size = 1.f; + zeus::CVector3f offset; + if (CColorElement* clr = desc.x10_CLR.get()) + clr->GetValue(x58_frameIdx, color); + if (CRealElement* sze = desc.x4_SZE.get()) { + sze->GetValue(x58_frameIdx, size); + size *= 0.5f; + } + if (CRealElement* rot = desc.x8_ROT.get()) + rot->GetValue(x58_frameIdx, decal.x8_rotation); + if (CVectorElement* off = desc.xc_OFF.get()) { + off->GetValue(x58_frameIdx, offset); + offset.y() = 0.f; + } + zeus::CTransform modXf = xc_transform; + modXf.origin += offset; + CGraphics::SetModelMatrix(modXf); - zeus::CTransform dmrtXf; - if (dmrtIsConst) - { - desc.x50_DMRT->GetValue(x58_frameIdx, const_cast(x60_rotation)); - dmrtXf = zeus::CTransform::RotateZ(zeus::degToRad(x60_rotation.z())); - dmrtXf.rotateLocalY(zeus::degToRad(x60_rotation.y())); - dmrtXf.rotateLocalX(zeus::degToRad(x60_rotation.x())); - } + SParticleUniforms uniformData = { + CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}}; + decal.m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms)); - dmrtXf = rotXf * dmrtXf; + bool redToAlpha = sMoveRedToAlphaBuffer && desc.x18_ADD && desc.x14_TEX; - if (CVectorElement* dmopo = desc.x4c_DMOP.get()) - dmopo->GetValue(x58_frameIdx, dmop); - - zeus::CTransform worldXf = zeus::CTransform::Translate(rotXf * dmop + xc_transform.origin); - - if (dmrtIsConst) - { - worldXf = worldXf * dmrtXf; - } + SUVElementSet uvSet = {0.f, 1.f, 0.f, 1.f}; + if (CUVElement* tex = desc.x14_TEX.get()) { + TLockedToken texObj = tex->GetValueTexture(x58_frameIdx); + if (!texObj.IsLoaded()) + return; + tex->GetValueUV(x58_frameIdx, uvSet); + if (redToAlpha) + CGraphics::SetShaderDataBinding(decal.m_redToAlphaDataBind); else - { - if (CVectorElement* dmrt = desc.x50_DMRT.get()) - { - zeus::CVector3f dmrtVec; - dmrt->GetValue(x58_frameIdx, dmrtVec); - dmrtXf = zeus::CTransform::RotateZ(zeus::degToRad(dmrtVec.z())); - dmrtXf.rotateLocalY(zeus::degToRad(dmrtVec.y())); - dmrtXf.rotateLocalX(zeus::degToRad(dmrtVec.x())); - worldXf = worldXf * rotXf * dmrtXf; - } - else - { - worldXf = worldXf * dmrtXf; - } - } + CGraphics::SetShaderDataBinding(decal.m_normalDataBind); - if (CVectorElement* dmsc = desc.x54_DMSC.get()) - { - zeus::CVector3f dmscVec; - dmsc->GetValue(x58_frameIdx, dmscVec); - worldXf = worldXf * zeus::CTransform::Scale(dmscVec); - } + g_instTexData.clear(); + g_instTexData.reserve(1); - if (CColorElement* dmcl = desc.x58_DMCL.get()) - dmcl->GetValue(x58_frameIdx, color); - - CGraphics::SetModelMatrix(worldXf); - - if (desc.x5c_24_DMAB) - { - CModelFlags flags(7, 0, 1, color); - desc.x38_DMDL.m_token->Draw(flags); + g_instTexData.emplace_back(); + SParticleInstanceTex& inst = g_instTexData.back(); + if (decal.x8_rotation == 0.f) { + inst.pos[0] = zeus::CVector3f(-size, 0.001f, size); + inst.pos[1] = zeus::CVector3f(size, 0.001f, size); + inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size); + inst.pos[3] = zeus::CVector3f(size, 0.001f, -size); + } else { + float ang = zeus::degToRad(decal.x8_rotation); + float sinSize = std::sin(ang) * size; + float cosSize = std::cos(ang) * size; + inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize); + inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize); + inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize)); + inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize); } - else - { - if (color.a() == 1.f) - { - CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); - desc.x38_DMDL.m_token->Draw(flags); - } - else - { - CModelFlags flags(5, 0, 1, color); - desc.x38_DMDL.m_token->Draw(flags); - } + inst.color = color; + inst.uvs[0] = zeus::CVector2f(uvSet.xMin, uvSet.yMin); + inst.uvs[1] = zeus::CVector2f(uvSet.xMax, uvSet.yMin); + inst.uvs[2] = zeus::CVector2f(uvSet.xMin, uvSet.yMax); + inst.uvs[3] = zeus::CVector2f(uvSet.xMax, uvSet.yMax); + + decal.m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); + CGraphics::DrawInstances(0, 4, g_instTexData.size()); + } else { + g_instNoTexData.clear(); + g_instNoTexData.reserve(1); + + g_instNoTexData.emplace_back(); + SParticleInstanceNoTex& inst = g_instNoTexData.back(); + if (decal.x8_rotation == 0.f) { + inst.pos[0] = zeus::CVector3f(-size, 0.001f, size); + inst.pos[1] = zeus::CVector3f(size, 0.001f, size); + inst.pos[2] = zeus::CVector3f(-size, 0.001f, -size); + inst.pos[3] = zeus::CVector3f(size, 0.001f, -size); + } else { + float ang = zeus::degToRad(decal.x8_rotation); + float sinSize = std::sin(ang) * size; + float cosSize = std::cos(ang) * size; + inst.pos[0] = zeus::CVector3f(sinSize - cosSize, 0.001f, cosSize + sinSize); + inst.pos[1] = zeus::CVector3f(cosSize + sinSize, 0.001f, cosSize - sinSize); + inst.pos[2] = zeus::CVector3f(-(cosSize + sinSize), 0.001f, -(cosSize - sinSize)); + inst.pos[3] = zeus::CVector3f(-sinSize + cosSize, 0.001f, -cosSize - sinSize); } + inst.color = color; + + decal.m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); + CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); + } } -void CDecal::Render() const -{ - CGlobalRandom gr(sDecalRandom); - if (x5c_29_modelInvalid && x5c_30_quad2Invalid && x5c_31_quad1Invalid) - return; +void CDecal::RenderMdl() const { + const CDecalDescription& desc = *x0_description; + zeus::CColor color = zeus::CColor::skWhite; + zeus::CVector3f dmop; + zeus::CTransform rotXf; - CGraphics::DisableAllLights(); - CParticleGlobals::SetEmitterTime(x58_frameIdx); + if (!desc.x5c_25_DMOO) + rotXf = xc_transform.getRotation(); - const CDecalDescription& desc = *x0_description; - if (desc.x0_Quads[0].x14_TEX && !x5c_31_quad1Invalid) - { - CParticleGlobals::SetParticleLifetime(x3c_decalQuads[0].x4_lifetime); - CParticleGlobals::UpdateParticleLifetimeTweenValues(x58_frameIdx); - RenderQuad(const_cast(x3c_decalQuads[0]), desc.x0_Quads[0]); + bool dmrtIsConst = false; + if (CVectorElement* dmrt = desc.x50_DMRT.get()) + dmrtIsConst = dmrt->IsFastConstant(); + + zeus::CTransform dmrtXf; + if (dmrtIsConst) { + desc.x50_DMRT->GetValue(x58_frameIdx, const_cast(x60_rotation)); + dmrtXf = zeus::CTransform::RotateZ(zeus::degToRad(x60_rotation.z())); + dmrtXf.rotateLocalY(zeus::degToRad(x60_rotation.y())); + dmrtXf.rotateLocalX(zeus::degToRad(x60_rotation.x())); + } + + dmrtXf = rotXf * dmrtXf; + + if (CVectorElement* dmopo = desc.x4c_DMOP.get()) + dmopo->GetValue(x58_frameIdx, dmop); + + zeus::CTransform worldXf = zeus::CTransform::Translate(rotXf * dmop + xc_transform.origin); + + if (dmrtIsConst) { + worldXf = worldXf * dmrtXf; + } else { + if (CVectorElement* dmrt = desc.x50_DMRT.get()) { + zeus::CVector3f dmrtVec; + dmrt->GetValue(x58_frameIdx, dmrtVec); + dmrtXf = zeus::CTransform::RotateZ(zeus::degToRad(dmrtVec.z())); + dmrtXf.rotateLocalY(zeus::degToRad(dmrtVec.y())); + dmrtXf.rotateLocalX(zeus::degToRad(dmrtVec.x())); + worldXf = worldXf * rotXf * dmrtXf; + } else { + worldXf = worldXf * dmrtXf; } - if (desc.x0_Quads[1].x14_TEX && !x5c_30_quad2Invalid) - { - CParticleGlobals::SetParticleLifetime(x3c_decalQuads[1].x4_lifetime); - CParticleGlobals::UpdateParticleLifetimeTweenValues(x58_frameIdx); - RenderQuad(const_cast(x3c_decalQuads[1]), desc.x0_Quads[1]); - } - if (desc.x38_DMDL && !x5c_29_modelInvalid) - { - CParticleGlobals::SetParticleLifetime(x54_modelLifetime); - CParticleGlobals::UpdateParticleLifetimeTweenValues(x58_frameIdx); - RenderMdl(); + } + + if (CVectorElement* dmsc = desc.x54_DMSC.get()) { + zeus::CVector3f dmscVec; + dmsc->GetValue(x58_frameIdx, dmscVec); + worldXf = worldXf * zeus::CTransform::Scale(dmscVec); + } + + if (CColorElement* dmcl = desc.x58_DMCL.get()) + dmcl->GetValue(x58_frameIdx, color); + + CGraphics::SetModelMatrix(worldXf); + + if (desc.x5c_24_DMAB) { + CModelFlags flags(7, 0, 1, color); + desc.x38_DMDL.m_token->Draw(flags); + } else { + if (color.a() == 1.f) { + CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + desc.x38_DMDL.m_token->Draw(flags); + } else { + CModelFlags flags(5, 0, 1, color); + desc.x38_DMDL.m_token->Draw(flags); } + } } -void CDecal::Update(float dt) -{ - if (x58_frameIdx >= x3c_decalQuads[0].x4_lifetime) - x5c_31_quad1Invalid = true; - if (x58_frameIdx >= x3c_decalQuads[1].x4_lifetime) - x5c_30_quad2Invalid = true; - if (x58_frameIdx >= x54_modelLifetime) - x5c_29_modelInvalid = true; - ++x58_frameIdx; +void CDecal::Render() const { + CGlobalRandom gr(sDecalRandom); + if (x5c_29_modelInvalid && x5c_30_quad2Invalid && x5c_31_quad1Invalid) + return; + + CGraphics::DisableAllLights(); + CParticleGlobals::SetEmitterTime(x58_frameIdx); + + const CDecalDescription& desc = *x0_description; + if (desc.x0_Quads[0].x14_TEX && !x5c_31_quad1Invalid) { + CParticleGlobals::SetParticleLifetime(x3c_decalQuads[0].x4_lifetime); + CParticleGlobals::UpdateParticleLifetimeTweenValues(x58_frameIdx); + RenderQuad(const_cast(x3c_decalQuads[0]), desc.x0_Quads[0]); + } + if (desc.x0_Quads[1].x14_TEX && !x5c_30_quad2Invalid) { + CParticleGlobals::SetParticleLifetime(x3c_decalQuads[1].x4_lifetime); + CParticleGlobals::UpdateParticleLifetimeTweenValues(x58_frameIdx); + RenderQuad(const_cast(x3c_decalQuads[1]), desc.x0_Quads[1]); + } + if (desc.x38_DMDL && !x5c_29_modelInvalid) { + CParticleGlobals::SetParticleLifetime(x54_modelLifetime); + CParticleGlobals::UpdateParticleLifetimeTweenValues(x58_frameIdx); + RenderMdl(); + } } +void CDecal::Update(float dt) { + if (x58_frameIdx >= x3c_decalQuads[0].x4_lifetime) + x5c_31_quad1Invalid = true; + if (x58_frameIdx >= x3c_decalQuads[1].x4_lifetime) + x5c_30_quad2Invalid = true; + if (x58_frameIdx >= x54_modelLifetime) + x5c_29_modelInvalid = true; + ++x58_frameIdx; } + +} // namespace urde diff --git a/Runtime/Particle/CDecal.hpp b/Runtime/Particle/CDecal.hpp index 2f6c80cdf..d51462c56 100644 --- a/Runtime/Particle/CDecal.hpp +++ b/Runtime/Particle/CDecal.hpp @@ -6,68 +6,56 @@ #include "CDecalDescription.hpp" #include "CRandom16.hpp" -namespace urde -{ +namespace urde { struct SQuadDescr; -struct CQuadDecal -{ - union - { - struct - { - bool x0_24_invalid : 1; - }; - u32 _dummy = 0; +struct CQuadDecal { + union { + struct { + bool x0_24_invalid : 1; }; - s32 x4_lifetime = 0; - float x8_rotation = 0.f; - const SQuadDescr* m_desc = nullptr; - CQuadDecal() = default; - CQuadDecal(s32 i, float f) - : x4_lifetime(i), - x8_rotation(f) - { - x0_24_invalid = true; - } + u32 _dummy = 0; + }; + s32 x4_lifetime = 0; + float x8_rotation = 0.f; + const SQuadDescr* m_desc = nullptr; + CQuadDecal() = default; + CQuadDecal(s32 i, float f) : x4_lifetime(i), x8_rotation(f) { x0_24_invalid = true; } - boo::ObjToken m_instBuf; - boo::ObjToken m_uniformBuf; - boo::ObjToken m_normalDataBind; - boo::ObjToken m_redToAlphaDataBind; + boo::ObjToken m_instBuf; + boo::ObjToken m_uniformBuf; + boo::ObjToken m_normalDataBind; + boo::ObjToken m_redToAlphaDataBind; }; -class CDecal -{ - friend class CDecalManager; - static bool sMoveRedToAlphaBuffer; - static CRandom16 sDecalRandom; +class CDecal { + friend class CDecalManager; + static bool sMoveRedToAlphaBuffer; + static CRandom16 sDecalRandom; - TLockedToken x0_description; - zeus::CTransform xc_transform; - CQuadDecal x3c_decalQuads[2]; - s32 x54_modelLifetime = 0; - s32 x58_frameIdx = 0; - union - { - struct - { - bool x5c_31_quad1Invalid : 1; - bool x5c_30_quad2Invalid : 1; - bool x5c_29_modelInvalid : 1; - }; - u32 x5c_dummy = 0; + TLockedToken x0_description; + zeus::CTransform xc_transform; + CQuadDecal x3c_decalQuads[2]; + s32 x54_modelLifetime = 0; + s32 x58_frameIdx = 0; + union { + struct { + bool x5c_31_quad1Invalid : 1; + bool x5c_30_quad2Invalid : 1; + bool x5c_29_modelInvalid : 1; }; - zeus::CVector3f x60_rotation; - bool InitQuad(CQuadDecal& quad, const SQuadDescr& desc); + u32 x5c_dummy = 0; + }; + zeus::CVector3f x60_rotation; + bool InitQuad(CQuadDecal& quad, const SQuadDescr& desc); + public: - CDecal(const TToken& desc, const zeus::CTransform& xf); - void RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const; - void RenderMdl() const; - void Render() const; - void Update(float dt); + CDecal(const TToken& desc, const zeus::CTransform& xf); + void RenderQuad(CQuadDecal& decal, const SQuadDescr& desc) const; + void RenderMdl() const; + void Render() const; + void Update(float dt); - static void SetGlobalSeed(u16); - static void SetMoveRedToAlphaBuffer(bool); + static void SetGlobalSeed(u16); + static void SetMoveRedToAlphaBuffer(bool); }; -} - +} // namespace urde diff --git a/Runtime/Particle/CDecalDataFactory.cpp b/Runtime/Particle/CDecalDataFactory.cpp index 5f859f132..272a95773 100644 --- a/Runtime/Particle/CDecalDataFactory.cpp +++ b/Runtime/Particle/CDecalDataFactory.cpp @@ -7,139 +7,128 @@ #include "CSimplePool.hpp" #include "CRandom16.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CDecalDataFactory"); using CPF = CParticleDataFactory; -CDecalDescription* CDecalDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) -{ - return CreateGeneratorDescription(in, resPool); +CDecalDescription* CDecalDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) { + return CreateGeneratorDescription(in, resPool); } -CDecalDescription* CDecalDataFactory::CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool) -{ - FourCC clsId = CPF::GetClassID(in); - if (clsId == FOURCC('DPSM')) - { - CDecalDescription* desc = new CDecalDescription; - if (CreateDPSM(desc, in, resPool)) - return desc; - else - delete desc; - } - return nullptr; +CDecalDescription* CDecalDataFactory::CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool) { + FourCC clsId = CPF::GetClassID(in); + if (clsId == FOURCC('DPSM')) { + CDecalDescription* desc = new CDecalDescription; + if (CreateDPSM(desc, in, resPool)) + return desc; + else + delete desc; + } + return nullptr; } -bool CDecalDataFactory::CreateDPSM(CDecalDescription* desc, CInputStream& in, CSimplePool* resPool) -{ - CRandom16 rand; - CGlobalRandom gr{rand}; - FourCC clsId = CPF::GetClassID(in); +bool CDecalDataFactory::CreateDPSM(CDecalDescription* desc, CInputStream& in, CSimplePool* resPool) { + CRandom16 rand; + CGlobalRandom gr{rand}; + FourCC clsId = CPF::GetClassID(in); - while (clsId != SBIG('_END')) - { - bool loadFirstDesc = false; - switch (clsId) - { - case SBIG('1SZE'): - case SBIG('1LFT'): - case SBIG('1ROT'): - case SBIG('1OFF'): - case SBIG('1CLR'): - case SBIG('1TEX'): - case SBIG('1ADD'): - loadFirstDesc = true; - case SBIG('2LFT'): - case SBIG('2SZE'): - case SBIG('2ROT'): - case SBIG('2OFF'): - case SBIG('2CLR'): - case SBIG('2TEX'): - case SBIG('2ADD'): - if (loadFirstDesc) - GetQuadDecalInfo(in, resPool, clsId, desc->x0_Quads[0]); - else - GetQuadDecalInfo(in, resPool, clsId, desc->x0_Quads[1]); - break; - - case SBIG('DMDL'): - desc->x38_DMDL = CPF::GetModel(in, resPool); - break; - case SBIG('DLFT'): - desc->x48_DLFT = CPF::GetIntElement(in); - break; - case SBIG('DMOP'): - desc->x4c_DMOP = CPF::GetVectorElement(in); - break; - case SBIG('DMRT'): - desc->x50_DMRT = CPF::GetVectorElement(in); - break; - case SBIG('DMSC'): - desc->x54_DMSC = CPF::GetVectorElement(in); - break; - case SBIG('DMCL'): - desc->x58_DMCL = CPF::GetColorElement(in); - break; - case SBIG('DMAB'): - desc->x5c_24_DMAB = CPF::GetBool(in); - break; - case SBIG('DMOO'): - desc->x5c_25_DMOO = CPF::GetBool(in); - break; - default: - { - uint32_t clsName = clsId.toUint32(); - Log.report(logvisor::Fatal, "Unknown DPSC class %.4s @%" PRIi64, &clsName, in.position()); - return false; - } - } - - clsId = CPF::GetClassID(in); - } - return true; -} - -void CDecalDataFactory::GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, SQuadDescr& quad) -{ - switch (clsId) - { - case SBIG('1LFT'): - case SBIG('2LFT'): - quad.x0_LFT = CPF::GetIntElement(in); - break; + while (clsId != SBIG('_END')) { + bool loadFirstDesc = false; + switch (clsId) { case SBIG('1SZE'): - case SBIG('2SZE'): - quad.x4_SZE = CPF::GetRealElement(in); - break; + case SBIG('1LFT'): case SBIG('1ROT'): - case SBIG('2ROT'): - quad.x8_ROT = CPF::GetRealElement(in); - break; case SBIG('1OFF'): - case SBIG('2OFF'): - quad.xc_OFF = CPF::GetVectorElement(in); - break; case SBIG('1CLR'): - case SBIG('2CLR'): - quad.x10_CLR = CPF::GetColorElement(in); - break; case SBIG('1TEX'): - case SBIG('2TEX'): - quad.x14_TEX = CPF::GetTextureElement(in, resPool); - break; case SBIG('1ADD'): + loadFirstDesc = true; + case SBIG('2LFT'): + case SBIG('2SZE'): + case SBIG('2ROT'): + case SBIG('2OFF'): + case SBIG('2CLR'): + case SBIG('2TEX'): case SBIG('2ADD'): - quad.x18_ADD = CPF::GetBool(in); - break; + if (loadFirstDesc) + GetQuadDecalInfo(in, resPool, clsId, desc->x0_Quads[0]); + else + GetQuadDecalInfo(in, resPool, clsId, desc->x0_Quads[1]); + break; + + case SBIG('DMDL'): + desc->x38_DMDL = CPF::GetModel(in, resPool); + break; + case SBIG('DLFT'): + desc->x48_DLFT = CPF::GetIntElement(in); + break; + case SBIG('DMOP'): + desc->x4c_DMOP = CPF::GetVectorElement(in); + break; + case SBIG('DMRT'): + desc->x50_DMRT = CPF::GetVectorElement(in); + break; + case SBIG('DMSC'): + desc->x54_DMSC = CPF::GetVectorElement(in); + break; + case SBIG('DMCL'): + desc->x58_DMCL = CPF::GetColorElement(in); + break; + case SBIG('DMAB'): + desc->x5c_24_DMAB = CPF::GetBool(in); + break; + case SBIG('DMOO'): + desc->x5c_25_DMOO = CPF::GetBool(in); + break; + default: { + uint32_t clsName = clsId.toUint32(); + Log.report(logvisor::Fatal, "Unknown DPSC class %.4s @%" PRIi64, &clsName, in.position()); + return false; } + } + + clsId = CPF::GetClassID(in); + } + return true; +} + +void CDecalDataFactory::GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, SQuadDescr& quad) { + switch (clsId) { + case SBIG('1LFT'): + case SBIG('2LFT'): + quad.x0_LFT = CPF::GetIntElement(in); + break; + case SBIG('1SZE'): + case SBIG('2SZE'): + quad.x4_SZE = CPF::GetRealElement(in); + break; + case SBIG('1ROT'): + case SBIG('2ROT'): + quad.x8_ROT = CPF::GetRealElement(in); + break; + case SBIG('1OFF'): + case SBIG('2OFF'): + quad.xc_OFF = CPF::GetVectorElement(in); + break; + case SBIG('1CLR'): + case SBIG('2CLR'): + quad.x10_CLR = CPF::GetColorElement(in); + break; + case SBIG('1TEX'): + case SBIG('2TEX'): + quad.x14_TEX = CPF::GetTextureElement(in, resPool); + break; + case SBIG('1ADD'): + case SBIG('2ADD'): + quad.x18_ADD = CPF::GetBool(in); + break; + } } CFactoryFnReturn FDecalDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, - CObjectReference*) -{ - CSimplePool* sp = vparms.GetOwnedObj(); - return TToken::GetIObjObjectFor( - std::unique_ptr(CDecalDataFactory::GetGeneratorDesc(in, sp))); -} + CObjectReference*) { + CSimplePool* sp = vparms.GetOwnedObj(); + return TToken::GetIObjObjectFor( + std::unique_ptr(CDecalDataFactory::GetGeneratorDesc(in, sp))); } +} // namespace urde diff --git a/Runtime/Particle/CDecalDataFactory.hpp b/Runtime/Particle/CDecalDataFactory.hpp index b19052c69..0e27f8c9f 100644 --- a/Runtime/Particle/CDecalDataFactory.hpp +++ b/Runtime/Particle/CDecalDataFactory.hpp @@ -7,20 +7,18 @@ #include "IOStreams.hpp" #include "CDecalDescription.hpp" -namespace urde -{ +namespace urde { class CSimplePool; -class CDecalDataFactory -{ - static bool CreateDPSM(CDecalDescription* desc, CInputStream& in, CSimplePool* resPool); - static CDecalDescription* CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool); - static void GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, SQuadDescr& quad); +class CDecalDataFactory { + static bool CreateDPSM(CDecalDescription* desc, CInputStream& in, CSimplePool* resPool); + static CDecalDescription* CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool); + static void GetQuadDecalInfo(CInputStream& in, CSimplePool* resPool, FourCC clsId, SQuadDescr& quad); public: - static CDecalDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); + static CDecalDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); }; CFactoryFnReturn FDecalDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference*); -} +} // namespace urde diff --git a/Runtime/Particle/CDecalDescription.hpp b/Runtime/Particle/CDecalDescription.hpp index 8704c95fb..4ab48674d 100644 --- a/Runtime/Particle/CDecalDescription.hpp +++ b/Runtime/Particle/CDecalDescription.hpp @@ -7,35 +7,34 @@ #include "CUVElement.hpp" #include "CParticleDataFactory.hpp" -namespace urde -{ +namespace urde { -struct SQuadDescr -{ - std::unique_ptr x0_LFT; - std::unique_ptr x4_SZE; - std::unique_ptr x8_ROT; - std::unique_ptr xc_OFF; - std::unique_ptr x10_CLR; - std::unique_ptr x14_TEX; - bool x18_ADD = false; +struct SQuadDescr { + std::unique_ptr x0_LFT; + std::unique_ptr x4_SZE; + std::unique_ptr x8_ROT; + std::unique_ptr xc_OFF; + std::unique_ptr x10_CLR; + std::unique_ptr x14_TEX; + bool x18_ADD = false; }; -class CDecalDescription -{ +class CDecalDescription { public: - SQuadDescr x0_Quads[2]; - SParticleModel x38_DMDL; - std::unique_ptr x48_DLFT; - std::unique_ptr x4c_DMOP; - std::unique_ptr x50_DMRT; - std::unique_ptr x54_DMSC; - std::unique_ptr x58_DMCL; - union - { - struct { bool x5c_24_DMAB : 1; bool x5c_25_DMOO : 1;}; - u8 dummy = 0; + SQuadDescr x0_Quads[2]; + SParticleModel x38_DMDL; + std::unique_ptr x48_DLFT; + std::unique_ptr x4c_DMOP; + std::unique_ptr x50_DMRT; + std::unique_ptr x54_DMSC; + std::unique_ptr x58_DMCL; + union { + struct { + bool x5c_24_DMAB : 1; + bool x5c_25_DMOO : 1; }; + u8 dummy = 0; + }; }; -} +} // namespace urde diff --git a/Runtime/Particle/CDecalManager.cpp b/Runtime/Particle/CDecalManager.cpp index 8dbf3b247..c391312b7 100644 --- a/Runtime/Particle/CDecalManager.cpp +++ b/Runtime/Particle/CDecalManager.cpp @@ -6,126 +6,111 @@ #include "GameGlobalObjects.hpp" #include "Graphics/Shaders/CDecalShaders.hpp" -namespace urde -{ -bool CDecalManager::m_PoolInitialized = false; -s32 CDecalManager::m_FreeIndex = 63; -float CDecalManager::m_DeltaTimeSinceLastDecalCreation = 0.f; -s32 CDecalManager::m_LastDecalCreatedIndex = -1; +namespace urde { +bool CDecalManager::m_PoolInitialized = false; +s32 CDecalManager::m_FreeIndex = 63; +float CDecalManager::m_DeltaTimeSinceLastDecalCreation = 0.f; +s32 CDecalManager::m_LastDecalCreatedIndex = -1; CAssetId CDecalManager::m_LastDecalCreatedAssetId = -1; rstl::reserved_vector CDecalManager::m_DecalPool; rstl::reserved_vector CDecalManager::m_ActiveIndexList; -void CDecalManager::Initialize() -{ - if (m_PoolInitialized) - return; +void CDecalManager::Initialize() { + if (m_PoolInitialized) + return; - m_DecalPool.clear(); - for (int i=0 ; i<64 ; ++i) - m_DecalPool.emplace_back(std::experimental::optional{}, 0, i-1, false); + m_DecalPool.clear(); + for (int i = 0; i < 64; ++i) + m_DecalPool.emplace_back(std::experimental::optional{}, 0, i - 1, false); - m_FreeIndex = 63; - m_PoolInitialized = true; - m_DeltaTimeSinceLastDecalCreation = 0.f; - m_LastDecalCreatedIndex = -1; - m_LastDecalCreatedAssetId = -1; + m_FreeIndex = 63; + m_PoolInitialized = true; + m_DeltaTimeSinceLastDecalCreation = 0.f; + m_LastDecalCreatedIndex = -1; + m_LastDecalCreatedAssetId = -1; - /* Compile shaders */ - CDecalShaders::Initialize(); + /* Compile shaders */ + CDecalShaders::Initialize(); } -void CDecalManager::Reinitialize() -{ - if (!m_PoolInitialized) - Initialize(); +void CDecalManager::Reinitialize() { + if (!m_PoolInitialized) + Initialize(); - m_DecalPool.clear(); - for (int i=0 ; i<64 ; ++i) - m_DecalPool.emplace_back(std::experimental::optional{}, 0, i-1, false); + m_DecalPool.clear(); + for (int i = 0; i < 64; ++i) + m_DecalPool.emplace_back(std::experimental::optional{}, 0, i - 1, false); - m_ActiveIndexList.clear(); + m_ActiveIndexList.clear(); - m_FreeIndex = 63; + m_FreeIndex = 63; } -void CDecalManager::Shutdown() -{ - m_ActiveIndexList.clear(); - m_DecalPool.clear(); - CDecalShaders::Shutdown(); +void CDecalManager::Shutdown() { + m_ActiveIndexList.clear(); + m_DecalPool.clear(); + CDecalShaders::Shutdown(); } -void CDecalManager::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) -{ - for (s32 idx : m_ActiveIndexList) - { - CDecalManager::SDecal& decal = m_DecalPool[idx]; - if (decal.x75_24_notIce || mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot) - { - const zeus::CVector3f& point = decal.x0_decal->xc_transform.origin; - zeus::CAABox aabb(point, point); - g_Renderer->AddDrawable(&*decal.x0_decal, point, aabb, 2, - IRenderer::EDrawableSorting::SortedCallback); - } +void CDecalManager::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) { + for (s32 idx : m_ActiveIndexList) { + CDecalManager::SDecal& decal = m_DecalPool[idx]; + if (decal.x75_24_notIce || mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot) { + const zeus::CVector3f& point = decal.x0_decal->xc_transform.origin; + zeus::CAABox aabb(point, point); + g_Renderer->AddDrawable(&*decal.x0_decal, point, aabb, 2, IRenderer::EDrawableSorting::SortedCallback); } + } } rstl::reserved_vector::iterator -CDecalManager::RemoveFromActiveList(rstl::reserved_vector::iterator it, s32 idx) -{ - it = m_ActiveIndexList.erase(it); - m_DecalPool[idx].x74_index = u8(m_FreeIndex); - m_FreeIndex = idx; - if (m_LastDecalCreatedIndex == m_FreeIndex) - m_LastDecalCreatedIndex = -1; - return it; +CDecalManager::RemoveFromActiveList(rstl::reserved_vector::iterator it, s32 idx) { + it = m_ActiveIndexList.erase(it); + m_DecalPool[idx].x74_index = u8(m_FreeIndex); + m_FreeIndex = idx; + if (m_LastDecalCreatedIndex == m_FreeIndex) + m_LastDecalCreatedIndex = -1; + return it; } -void CDecalManager::Update(float dt, CStateManager& mgr) -{ - m_DeltaTimeSinceLastDecalCreation += dt; - for (auto it = m_ActiveIndexList.begin() ; it != m_ActiveIndexList.end() ;) - { - SDecal& decal = m_DecalPool[*it]; - if (decal.x70_areaId != mgr.GetNextAreaId() || - (decal.x0_decal->x5c_29_modelInvalid && - decal.x0_decal->x5c_30_quad2Invalid && - decal.x0_decal->x5c_31_quad1Invalid)) - { - it = RemoveFromActiveList(it, *it); - continue; - } - decal.x0_decal->Update(dt); - ++it; +void CDecalManager::Update(float dt, CStateManager& mgr) { + m_DeltaTimeSinceLastDecalCreation += dt; + for (auto it = m_ActiveIndexList.begin(); it != m_ActiveIndexList.end();) { + SDecal& decal = m_DecalPool[*it]; + if (decal.x70_areaId != mgr.GetNextAreaId() || + (decal.x0_decal->x5c_29_modelInvalid && decal.x0_decal->x5c_30_quad2Invalid && + decal.x0_decal->x5c_31_quad1Invalid)) { + it = RemoveFromActiveList(it, *it); + continue; } + decal.x0_decal->Update(dt); + ++it; + } } -void CDecalManager::AddDecal(const TToken& decal, const zeus::CTransform& xf, - bool notIce, CStateManager& mgr) -{ - if (m_LastDecalCreatedIndex != -1 && m_DeltaTimeSinceLastDecalCreation < 0.75f && - m_LastDecalCreatedAssetId == decal.GetObjectTag()->id) - { - SDecal& existingDecal = m_DecalPool[m_LastDecalCreatedIndex]; - if ((existingDecal.x0_decal->xc_transform.origin - xf.origin).magSquared() < 0.01f) - return; - } +void CDecalManager::AddDecal(const TToken& decal, const zeus::CTransform& xf, bool notIce, + CStateManager& mgr) { + if (m_LastDecalCreatedIndex != -1 && m_DeltaTimeSinceLastDecalCreation < 0.75f && + m_LastDecalCreatedAssetId == decal.GetObjectTag()->id) { + SDecal& existingDecal = m_DecalPool[m_LastDecalCreatedIndex]; + if ((existingDecal.x0_decal->xc_transform.origin - xf.origin).magSquared() < 0.01f) + return; + } - if (m_FreeIndex == -1) - RemoveFromActiveList(m_ActiveIndexList.begin(), m_ActiveIndexList[0]); + if (m_FreeIndex == -1) + RemoveFromActiveList(m_ActiveIndexList.begin(), m_ActiveIndexList[0]); - s32 thisIndex = m_FreeIndex; - SDecal& freeDecal = m_DecalPool[thisIndex]; - m_FreeIndex = freeDecal.x74_index; - freeDecal.x0_decal.emplace(decal, xf); + s32 thisIndex = m_FreeIndex; + SDecal& freeDecal = m_DecalPool[thisIndex]; + m_FreeIndex = freeDecal.x74_index; + freeDecal.x0_decal.emplace(decal, xf); - freeDecal.x70_areaId = mgr.GetNextAreaId(); - freeDecal.x75_24_notIce = notIce; - m_DeltaTimeSinceLastDecalCreation = 0.f; - m_LastDecalCreatedIndex = thisIndex; - m_LastDecalCreatedAssetId = decal.GetObjectTag()->id; - m_ActiveIndexList.push_back(thisIndex); + freeDecal.x70_areaId = mgr.GetNextAreaId(); + freeDecal.x75_24_notIce = notIce; + m_DeltaTimeSinceLastDecalCreation = 0.f; + m_LastDecalCreatedIndex = thisIndex; + m_LastDecalCreatedAssetId = decal.GetObjectTag()->id; + m_ActiveIndexList.push_back(thisIndex); } -} +} // namespace urde diff --git a/Runtime/Particle/CDecalManager.hpp b/Runtime/Particle/CDecalManager.hpp index d88628eeb..724d1df9d 100644 --- a/Runtime/Particle/CDecalManager.hpp +++ b/Runtime/Particle/CDecalManager.hpp @@ -7,40 +7,39 @@ #include "CDecal.hpp" #include "zeus/CFrustum.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class CDecalManager -{ - struct SDecal - { - std::experimental::optional x0_decal; - TAreaId x70_areaId; - s8 x74_index; - bool x75_24_notIce : 1; - SDecal(const std::experimental::optional& decal, TAreaId aid, s8 idx, bool notIce) - : x0_decal(decal), x70_areaId(aid), x74_index(idx) { x75_24_notIce = notIce; } - }; +class CDecalManager { + struct SDecal { + std::experimental::optional x0_decal; + TAreaId x70_areaId; + s8 x74_index; + bool x75_24_notIce : 1; + SDecal(const std::experimental::optional& decal, TAreaId aid, s8 idx, bool notIce) + : x0_decal(decal), x70_areaId(aid), x74_index(idx) { + x75_24_notIce = notIce; + } + }; + + static bool m_PoolInitialized; + static s32 m_FreeIndex; + static float m_DeltaTimeSinceLastDecalCreation; + static s32 m_LastDecalCreatedIndex; + static CAssetId m_LastDecalCreatedAssetId; + static rstl::reserved_vector m_DecalPool; + static rstl::reserved_vector m_ActiveIndexList; + static rstl::reserved_vector::iterator RemoveFromActiveList(rstl::reserved_vector::iterator it, + s32 idx); - static bool m_PoolInitialized; - static s32 m_FreeIndex; - static float m_DeltaTimeSinceLastDecalCreation; - static s32 m_LastDecalCreatedIndex; - static CAssetId m_LastDecalCreatedAssetId; - static rstl::reserved_vector m_DecalPool; - static rstl::reserved_vector m_ActiveIndexList; - static rstl::reserved_vector::iterator - RemoveFromActiveList(rstl::reserved_vector::iterator it, s32 idx); public: - static void Initialize(); - static void Reinitialize(); - static void Shutdown(); - static void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr); - static void Update(float dt, CStateManager& mgr); - static void AddDecal(const TToken& decal, const zeus::CTransform& xf, - bool notIce, CStateManager& mgr); + static void Initialize(); + static void Reinitialize(); + static void Shutdown(); + static void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr); + static void Update(float dt, CStateManager& mgr); + static void AddDecal(const TToken& decal, const zeus::CTransform& xf, bool notIce, + CStateManager& mgr); }; -} - +} // namespace urde diff --git a/Runtime/Particle/CElectricDescription.hpp b/Runtime/Particle/CElectricDescription.hpp index 6db0dc851..442511313 100644 --- a/Runtime/Particle/CElectricDescription.hpp +++ b/Runtime/Particle/CElectricDescription.hpp @@ -8,31 +8,28 @@ #include "CColorElement.hpp" #include "CUVElement.hpp" -namespace urde -{ -class CElectricDescription -{ +namespace urde { +class CElectricDescription { public: - std::unique_ptr x0_LIFE; - std::unique_ptr x4_SLIF; - std::unique_ptr x8_GRAT; - std::unique_ptr xc_SCNT; - std::unique_ptr x10_SSEG; - std::unique_ptr x14_COLR; - std::unique_ptr x18_IEMT; - std::unique_ptr x1c_FEMT; - std::unique_ptr x20_AMPL; - std::unique_ptr x24_AMPD; - std::unique_ptr x28_LWD1; - std::unique_ptr x2c_LWD2; - std::unique_ptr x30_LWD3; - std::unique_ptr x34_LCL1; - std::unique_ptr x38_LCL2; - std::unique_ptr x3c_LCL3; - SSwooshGeneratorDesc x40_SSWH; - SChildGeneratorDesc x50_GPSM; - SChildGeneratorDesc x60_EPSM; - bool x70_ZERY; + std::unique_ptr x0_LIFE; + std::unique_ptr x4_SLIF; + std::unique_ptr x8_GRAT; + std::unique_ptr xc_SCNT; + std::unique_ptr x10_SSEG; + std::unique_ptr x14_COLR; + std::unique_ptr x18_IEMT; + std::unique_ptr x1c_FEMT; + std::unique_ptr x20_AMPL; + std::unique_ptr x24_AMPD; + std::unique_ptr x28_LWD1; + std::unique_ptr x2c_LWD2; + std::unique_ptr x30_LWD3; + std::unique_ptr x34_LCL1; + std::unique_ptr x38_LCL2; + std::unique_ptr x3c_LCL3; + SSwooshGeneratorDesc x40_SSWH; + SChildGeneratorDesc x50_GPSM; + SChildGeneratorDesc x60_EPSM; + bool x70_ZERY; }; -} - +} // namespace urde diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index b5b92bd07..638d57d97 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -12,8 +12,7 @@ #define MAX_GLOBAL_PARTICLES 2560 -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CElementGen"); u16 CElementGen::g_GlobalSeed = 99; @@ -29,1396 +28,1225 @@ std::vector g_instTexData; std::vector g_instIndTexData; std::vector g_instNoTexData; -void CElementGen::Initialize() -{ - if (g_ParticleSystemInitialized) - return; +void CElementGen::Initialize() { + if (g_ParticleSystemInitialized) + return; - g_ParticleAliveCount = 0; - g_ParticleSystemAliveCount = 0; - g_ParticleSystemInitialized = true; + g_ParticleAliveCount = 0; + g_ParticleSystemAliveCount = 0; + g_ParticleSystemInitialized = true; - /* Compile shaders */ - CElementGenShaders::Initialize(); + /* Compile shaders */ + CElementGenShaders::Initialize(); } -void CElementGen::Shutdown() -{ - CElementGenShaders::Shutdown(); -} +void CElementGen::Shutdown() { CElementGenShaders::Shutdown(); } -static const size_t ShadClsSizes[] = -{ - sizeof(SParticleInstanceTex), - sizeof(SParticleInstanceIndTex), - sizeof(SParticleInstanceNoTex) -}; +static const size_t ShadClsSizes[] = {sizeof(SParticleInstanceTex), sizeof(SParticleInstanceIndTex), + sizeof(SParticleInstanceNoTex)}; -CElementGen::CElementGen(const TToken& gen, - EModelOrientationType orientType, +CElementGen::CElementGen(const TToken& gen, EModelOrientationType orientType, EOptionalSystemFlags flags) -: x1c_genDesc(gen), x2c_orientType(orientType), - x27c_randState(x94_randomSeed) -{ - CGenDescription* desc = x1c_genDesc.GetObj(); - x28_loadedGenDesc = desc; +: x1c_genDesc(gen), x2c_orientType(orientType), x27c_randState(x94_randomSeed) { + CGenDescription* desc = x1c_genDesc.GetObj(); + x28_loadedGenDesc = desc; - x26d_27_enableOPTS = (flags & EOptionalSystemFlags::Two) != EOptionalSystemFlags::None; + x26d_27_enableOPTS = (flags & EOptionalSystemFlags::Two) != EOptionalSystemFlags::None; - if (desc->x54_x40_TEXR) - desc->x54_x40_TEXR->GetValueTexture(0).GetObj(); - if (desc->x58_x44_TIND) - desc->x58_x44_TIND->GetValueTexture(0).GetObj(); + if (desc->x54_x40_TEXR) + desc->x54_x40_TEXR->GetValueTexture(0).GetObj(); + if (desc->x58_x44_TIND) + desc->x58_x44_TIND->GetValueTexture(0).GetObj(); - CGlobalRandom globRnd(x27c_randState); - if (CIntElement* seedElem = desc->x1c_x10_SEED.get()) - { - int seedVal; - seedElem->GetValue(x74_curFrame, seedVal); - x94_randomSeed = seedVal; + CGlobalRandom globRnd(x27c_randState); + if (CIntElement* seedElem = desc->x1c_x10_SEED.get()) { + int seedVal; + seedElem->GetValue(x74_curFrame, seedVal); + x94_randomSeed = seedVal; + } + x27c_randState.SetSeed(x94_randomSeed); + ++g_ParticleSystemAliveCount; + x26c_25_LIT_ = desc->x44_29_x30_29_LIT_; + x26c_26_AAPH = desc->x44_26_x30_26_AAPH; + x26c_27_ZBUF = desc->x44_27_x30_27_ZBUF; + x26c_28_zTest = true; + x26c_29_ORNT = desc->x30_30_ORNT; + x26c_30_MBLR = x26c_29_ORNT ? false : desc->x44_30_x31_24_MBLR; + + if (CIntElement* mbspElem = desc->x48_x34_MBSP.get()) + mbspElem->GetValue(x74_curFrame, x270_MBSP); + m_maxMBSP = x270_MBSP; + + if (CModVectorElement* elem = desc->x7c_x68_VEL1.get()) { + x280_VELSources[0] = elem; + x278_hasVMD[0] = desc->x45_26_x31_28_VMD1; + } + + if (CModVectorElement* elem = desc->x80_x6c_VEL2.get()) { + x280_VELSources[1] = elem; + x278_hasVMD[1] = desc->x45_27_x31_29_VMD2; + } + + if (CModVectorElement* elem = desc->x84_x70_VEL3.get()) { + x280_VELSources[2] = elem; + x278_hasVMD[2] = desc->x45_28_x31_30_VMD3; + } + + if (CModVectorElement* elem = desc->x88_x74_VEL4.get()) { + x280_VELSources[3] = elem; + x278_hasVMD[3] = desc->x45_29_x31_31_VMD4; + } + + if (desc->x10c_ADV1 || desc->x110_ADV2 || desc->x114_ADV3 || desc->x118_ADV4 || desc->x11c_ADV5 || desc->x120_ADV6 || + desc->x124_ADV7 || desc->x128_ADV8) + x26d_28_enableADV = true; + + if (CIntElement* cssdElem = desc->xa0_x8c_CSSD.get()) + cssdElem->GetValue(0, x2a0_CSSD); + + if (CIntElement* pisyElem = desc->xc8_xb4_PISY.get()) { + pisyElem->GetValue(0, x2a8_PISY); + if (x2a8_PISY <= 0) + x2a8_PISY = 1; + } + + if (CIntElement* sisyElem = desc->xcc_xb8_SISY.get()) + sisyElem->GetValue(0, x2a4_SISY); + + if (CIntElement* sssdElem = desc->xe4_xd0_SSSD.get()) + sssdElem->GetValue(0, x2ac_SSSD); + + if (CVectorElement* sspoElem = desc->xe8_xd4_SSPO.get()) { + sspoElem->GetValue(0, x2b0_SSPO); + if (!sspoElem->IsFastConstant()) + x26c_24_translationDirty = true; + } + + if (CIntElement* sesdElem = desc->xf8_xe4_SESD.get()) + sesdElem->GetValue(0, x2bc_SESD); + + if (CVectorElement* sepoElem = desc->xfc_xe8_SEPO.get()) { + sepoElem->GetValue(0, x2c0_SEPO); + if (!sepoElem->IsFastConstant()) + x26c_24_translationDirty = true; + } + + if (CVectorElement* pofsElem = desc->x18_xc_POFS.get()) { + pofsElem->GetValue(x74_curFrame, xf4_POFS); + if (!pofsElem->IsFastConstant()) + x26c_24_translationDirty = true; + } + + if (CIntElement* psltElem = desc->xc_x0_PSLT.get()) + psltElem->GetValue(0, x268_PSLT); + else + x268_PSLT = INT_MAX; + + if (CIntElement* maxpElem = desc->x28_x1c_MAXP.get()) { + maxpElem->GetValue(x74_curFrame, x90_MAXP); + m_maxMAXP = maxpElem->GetMaxValue(); + } + + m_maxMAXP = std::min(m_maxMAXP, 256); + x30_particles.reserve(m_maxMAXP); + if (x2c_orientType == EModelOrientationType::One) + x50_parentMatrices.resize(m_maxMAXP); + + x26c_31_LINE = desc->x44_24_x30_24_LINE; + x26d_24_FXLL = desc->x44_25_x30_25_FXLL; + + if (CIntElement* ltypElem = desc->x100_xec_LTYP.get()) { + int ltyp; + ltypElem->GetValue(x74_curFrame, ltyp); + switch (LightType(ltyp)) { + case LightType::None: + default: + x308_lightType = LightType::None; + break; + case LightType::Directional: + x308_lightType = LightType::Directional; + break; + case LightType::Custom: + x308_lightType = LightType::Custom; + break; + case LightType::Spot: + x308_lightType = LightType::Spot; + break; } - x27c_randState.SetSeed(x94_randomSeed); - ++g_ParticleSystemAliveCount; - x26c_25_LIT_ = desc->x44_29_x30_29_LIT_; - x26c_26_AAPH = desc->x44_26_x30_26_AAPH; - x26c_27_ZBUF = desc->x44_27_x30_27_ZBUF; - x26c_28_zTest = true; - x26c_29_ORNT = desc->x30_30_ORNT; - x26c_30_MBLR = x26c_29_ORNT ? false : desc->x44_30_x31_24_MBLR; + } + if (CIntElement* lfotElem = desc->x114_x100_LFOT.get()) { + int lfot; + lfotElem->GetValue(x74_curFrame, lfot); + switch (EFalloffType(lfot)) { + case EFalloffType::Constant: + x32c_falloffType = EFalloffType::Constant; + break; + case EFalloffType::Linear: + default: + x32c_falloffType = EFalloffType::Linear; + break; + case EFalloffType::Quadratic: + x32c_falloffType = EFalloffType::Quadratic; + break; + } + } + + if (x26c_31_LINE) { + CUVElement* texr = desc->x54_x40_TEXR.get(); + boo::ObjToken tex; + if (texr) + tex = texr->GetValueTexture(0).GetObj()->GetBooTexture(); + int maxVerts = (m_maxMAXP == 0 ? 256 : m_maxMAXP); + m_lineRenderer.reset( + new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, tex, x26c_26_AAPH, x26c_28_zTest)); + } else { + m_shaderClass = CElementGenShaders::GetShaderClass(*this); + } + + size_t maxInsts = x26c_30_MBLR ? (m_maxMBSP * m_maxMAXP) : m_maxMAXP; + maxInsts = (maxInsts == 0 ? 256 : maxInsts); + + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + if (!x26c_31_LINE) { + m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[int(m_shaderClass)], maxInsts); + m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1); + } + if (desc->x45_24_x31_26_PMUS) { + m_instBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[int(m_shaderClass)], maxInsts); + m_uniformBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1); + } + CElementGenShaders::BuildShaderDataBinding(ctx, *this); + return true; + } BooTrace); +} + +CElementGen::~CElementGen() { + --g_ParticleSystemAliveCount; + g_ParticleAliveCount -= x30_particles.size(); +} + +bool CElementGen::Update(double t) { + CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::g_currentParticleSystem; + CParticleGlobals::SParticleSystem thisSystem{FOURCC('PART'), this}; + CParticleGlobals::g_currentParticleSystem = &thisSystem; + CGenDescription* desc = x1c_genDesc.GetObj(); + CIntElement* pswtElem = desc->x10_x4_PSWT.get(); + if (pswtElem && !x26d_25_warmedUp) { + int pswt = 0; + pswtElem->GetValue(x74_curFrame, pswt); + Log.report(logvisor::Info, "Running warmup on particle system 0x%08x for %d ticks.", desc, pswt); + InternalUpdate((1.f / 60.f) * pswt); + x26d_25_warmedUp = true; + } + bool ret = InternalUpdate(t); + CParticleGlobals::g_currentParticleSystem = prevSystem; + return ret; +} + +bool CElementGen::InternalUpdate(double dt) { + CGlobalRandom gr(x27c_randState); + CGenDescription* desc = x1c_genDesc.GetObj(); + + double dt1 = 1.0 / 60.0; + if (std::fabs(dt - 1.0 / 60.0) >= 1.0 / 60000.0) + dt1 = dt; + double t = x74_curFrame / 60.0; + CParticleGlobals::SetEmitterTime(x74_curFrame); + + if (CRealElement* pstsElem = desc->x14_x8_PSTS.get()) { + float psts; + pstsElem->GetValue(x74_curFrame, psts); + double dt1Scaled = psts * dt1; + dt1 = std::max(0.0, dt1Scaled); + } + + x78_curSeconds += dt1; + + if (x26c_30_MBLR && dt > 0.0) { if (CIntElement* mbspElem = desc->x48_x34_MBSP.get()) - mbspElem->GetValue(x74_curFrame, x270_MBSP); - m_maxMBSP = x270_MBSP; + mbspElem->GetValue(x74_curFrame, x270_MBSP); + x270_MBSP = std::min(x270_MBSP, m_maxMBSP); + } - if (CModVectorElement* elem = desc->x7c_x68_VEL1.get()) - { - x280_VELSources[0] = elem; - x278_hasVMD[0] = desc->x45_26_x31_28_VMD1; - } + int frameUpdateCount = 0; + while (t < x78_curSeconds && std::fabs(t - x78_curSeconds) >= 1.0 / 60000.0) { + x2d4_aabbMin.splat(FLT_MAX); + x2e0_aabbMax.splat(-FLT_MAX); + x2ec_maxSize = 0.f; + CParticleGlobals::SetEmitterTime(x74_curFrame); + UpdateExistingParticles(); + CParticleGlobals::SetParticleLifetime(x268_PSLT); - if (CModVectorElement* elem = desc->x80_x6c_VEL2.get()) - { - x280_VELSources[1] = elem; - x278_hasVMD[1] = desc->x45_27_x31_29_VMD2; - } + if (x74_curFrame < x268_PSLT && x88_particleEmission) { + float grte = 0.f; + if (CRealElement* grteElem = desc->x2c_x20_GRTE.get()) { + if (grteElem->GetValue(x74_curFrame, grte)) { + x30_particles.clear(); + return true; + } + } - if (CModVectorElement* elem = desc->x84_x70_VEL3.get()) - { - x280_VELSources[2] = elem; - x278_hasVMD[2] = desc->x45_28_x31_30_VMD3; - } + grte = std::max(0.f, grte * x98_generatorRate); + x8c_generatorRemainder += grte; + int genCount = floorf(x8c_generatorRemainder); + x8c_generatorRemainder = x8c_generatorRemainder - genCount; - if (CModVectorElement* elem = desc->x88_x74_VEL4.get()) - { - x280_VELSources[3] = elem; - x278_hasVMD[3] = desc->x45_29_x31_31_VMD4; - } - - if (desc->x10c_ADV1 || desc->x110_ADV2 || desc->x114_ADV3 || desc->x118_ADV4 || - desc->x11c_ADV5 || desc->x120_ADV6 || desc->x124_ADV7 || desc->x128_ADV8) - x26d_28_enableADV = true; - - if (CIntElement* cssdElem = desc->xa0_x8c_CSSD.get()) - cssdElem->GetValue(0, x2a0_CSSD); - - if (CIntElement* pisyElem = desc->xc8_xb4_PISY.get()) - { - pisyElem->GetValue(0, x2a8_PISY); - if (x2a8_PISY <= 0) - x2a8_PISY = 1; - } - - if (CIntElement* sisyElem = desc->xcc_xb8_SISY.get()) - sisyElem->GetValue(0, x2a4_SISY); - - if (CIntElement* sssdElem = desc->xe4_xd0_SSSD.get()) - sssdElem->GetValue(0, x2ac_SSSD); - - if (CVectorElement* sspoElem = desc->xe8_xd4_SSPO.get()) - { - sspoElem->GetValue(0, x2b0_SSPO); - if (!sspoElem->IsFastConstant()) - x26c_24_translationDirty = true; - } - - if (CIntElement* sesdElem = desc->xf8_xe4_SESD.get()) - sesdElem->GetValue(0, x2bc_SESD); - - if (CVectorElement* sepoElem = desc->xfc_xe8_SEPO.get()) - { - sepoElem->GetValue(0, x2c0_SEPO); - if (!sepoElem->IsFastConstant()) - x26c_24_translationDirty = true; - } - - if (CVectorElement* pofsElem = desc->x18_xc_POFS.get()) - { - pofsElem->GetValue(x74_curFrame, xf4_POFS); - if (!pofsElem->IsFastConstant()) - x26c_24_translationDirty = true; - } - - if (CIntElement* psltElem = desc->xc_x0_PSLT.get()) - psltElem->GetValue(0, x268_PSLT); - else - x268_PSLT = INT_MAX; - - if (CIntElement* maxpElem = desc->x28_x1c_MAXP.get()) - { + if (CIntElement* maxpElem = desc->x28_x1c_MAXP.get()) maxpElem->GetValue(x74_curFrame, x90_MAXP); - m_maxMAXP = maxpElem->GetMaxValue(); + + CreateNewParticles(genCount); } - m_maxMAXP = std::min(m_maxMAXP, 256); - x30_particles.reserve(m_maxMAXP); - if (x2c_orientType == EModelOrientationType::One) - x50_parentMatrices.resize(m_maxMAXP); + if (x26c_24_translationDirty) + UpdatePSTranslationAndOrientation(); - x26c_31_LINE = desc->x44_24_x30_24_LINE; - x26d_24_FXLL = desc->x44_25_x30_25_FXLL; + if (x308_lightType != LightType::None) + UpdateLightParameters(); - if (CIntElement* ltypElem = desc->x100_xec_LTYP.get()) - { - int ltyp; - ltypElem->GetValue(x74_curFrame, ltyp); - switch (LightType(ltyp)) - { - case LightType::None: - default: - x308_lightType = LightType::None; - break; - case LightType::Directional: - x308_lightType = LightType::Directional; - break; - case LightType::Custom: - x308_lightType = LightType::Custom; - break; - case LightType::Spot: - x308_lightType = LightType::Spot; - break; - } - } + UpdateChildParticleSystems(1 / 60.0); - if (CIntElement* lfotElem = desc->x114_x100_LFOT.get()) - { - int lfot; - lfotElem->GetValue(x74_curFrame, lfot); - switch (EFalloffType(lfot)) - { - case EFalloffType::Constant: - x32c_falloffType = EFalloffType::Constant; - break; - case EFalloffType::Linear: - default: - x32c_falloffType = EFalloffType::Linear; - break; - case EFalloffType::Quadratic: - x32c_falloffType = EFalloffType::Quadratic; - break; - } - } + ++frameUpdateCount; + ++x74_curFrame; + t += 1 / 60.0; + } - if (x26c_31_LINE) - { - CUVElement* texr = desc->x54_x40_TEXR.get(); - boo::ObjToken tex; - if (texr) - tex = texr->GetValueTexture(0).GetObj()->GetBooTexture(); - int maxVerts = (m_maxMAXP == 0 ? 256 : m_maxMAXP); - m_lineRenderer.reset(new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, - maxVerts * 2, tex, x26c_26_AAPH, x26c_28_zTest)); - } - else - { - m_shaderClass = CElementGenShaders::GetShaderClass(*this); - } + if (std::fabs(t - x78_curSeconds) < 1.0 / 60000.0) { + x78_curSeconds = t; + x80_timeDeltaScale = 1.f; + } else { + UpdateChildParticleSystems(dt1 - (frameUpdateCount / 60.0)); + x80_timeDeltaScale = 1.f - (t - x78_curSeconds) * 60.f; + } - size_t maxInsts = x26c_30_MBLR ? (m_maxMBSP * m_maxMAXP) : m_maxMAXP; - maxInsts = (maxInsts == 0 ? 256 : maxInsts); + BuildParticleSystemBounds(); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - if (!x26c_31_LINE) - { - m_instBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[int(m_shaderClass)], maxInsts); - m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1); - } - if (desc->x45_24_x31_26_PMUS) - { - m_instBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Vertex, ShadClsSizes[int(m_shaderClass)], maxInsts); - m_uniformBufPmus = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(SParticleUniforms), 1); - } - CElementGenShaders::BuildShaderDataBinding(ctx, *this); - return true; - } BooTrace); + return false; } -CElementGen::~CElementGen() -{ - --g_ParticleSystemAliveCount; - g_ParticleAliveCount -= x30_particles.size(); +void CElementGen::AccumulateBounds(const zeus::CVector3f& pos, float size) { + x2e0_aabbMax[0] = std::max(pos[0], float(x2e0_aabbMax[0])); + x2e0_aabbMax[1] = std::max(pos[1], float(x2e0_aabbMax[1])); + x2e0_aabbMax[2] = std::max(pos[2], float(x2e0_aabbMax[2])); + x2d4_aabbMin[0] = std::min(pos[0], float(x2d4_aabbMin[0])); + x2d4_aabbMin[1] = std::min(pos[1], float(x2d4_aabbMin[1])); + x2d4_aabbMin[2] = std::min(pos[2], float(x2d4_aabbMin[2])); + x2ec_maxSize = std::max(size, x2ec_maxSize); } -bool CElementGen::Update(double t) -{ - CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::g_currentParticleSystem; - CParticleGlobals::SParticleSystem thisSystem { FOURCC('PART'), this }; - CParticleGlobals::g_currentParticleSystem = &thisSystem; - CGenDescription* desc = x1c_genDesc.GetObj(); - CIntElement* pswtElem = desc->x10_x4_PSWT.get(); - if (pswtElem && !x26d_25_warmedUp) - { - int pswt = 0; - pswtElem->GetValue(x74_curFrame, pswt); - Log.report(logvisor::Info, - "Running warmup on particle system 0x%08x for %d ticks.", - desc, pswt); - InternalUpdate((1.f / 60.f) * pswt); - x26d_25_warmedUp = true; - } - bool ret = InternalUpdate(t); - CParticleGlobals::g_currentParticleSystem = prevSystem; - return ret; +void CElementGen::UpdateAdvanceAccessParameters(u32 activeParticleCount, u32 particleFrame) { + if (activeParticleCount >= x60_advValues.size()) { + CParticleGlobals::g_particleAccessParameters = nullptr; + return; + } + + CGenDescription* desc = x1c_genDesc.GetObj(); + + std::array& arr = x60_advValues[activeParticleCount]; + CParticleGlobals::g_particleAccessParameters = &arr; + + if (CRealElement* adv1 = desc->x10c_ADV1.get()) + adv1->GetValue(particleFrame, arr[0]); + if (CRealElement* adv2 = desc->x110_ADV2.get()) + adv2->GetValue(particleFrame, arr[1]); + if (CRealElement* adv3 = desc->x114_ADV3.get()) + adv3->GetValue(particleFrame, arr[2]); + if (CRealElement* adv4 = desc->x118_ADV4.get()) + adv4->GetValue(particleFrame, arr[3]); + if (CRealElement* adv5 = desc->x11c_ADV5.get()) + adv5->GetValue(particleFrame, arr[4]); + if (CRealElement* adv6 = desc->x120_ADV6.get()) + adv6->GetValue(particleFrame, arr[5]); + if (CRealElement* adv7 = desc->x124_ADV7.get()) + adv7->GetValue(particleFrame, arr[6]); + if (CRealElement* adv8 = desc->x128_ADV8.get()) + adv8->GetValue(particleFrame, arr[7]); } -bool CElementGen::InternalUpdate(double dt) -{ - CGlobalRandom gr(x27c_randState); - CGenDescription* desc = x1c_genDesc.GetObj(); +bool CElementGen::UpdateVelocitySource(u32 idx, u32 particleFrame, CParticle& particle) { + bool err; + if (x278_hasVMD[idx]) { + zeus::CVector3f localVel = x208_orientationInverse * particle.x1c_vel; + zeus::CVector3f localPos = x208_orientationInverse * (particle.x4_pos - xdc_translation); + err = x280_VELSources[idx]->GetValue(particleFrame, localVel, localPos); + particle.x1c_vel = x1d8_orientation.rotate(localVel); + particle.x4_pos = x1d8_orientation.rotate(localVel) + xdc_translation; + } else { + err = x280_VELSources[idx]->GetValue(particleFrame, particle.x1c_vel, particle.x4_pos); + } - double dt1 = 1.0 / 60.0; - if (std::fabs(dt - 1.0 / 60.0) >= 1.0 / 60000.0) - dt1 = dt; - double t = x74_curFrame / 60.0; - CParticleGlobals::SetEmitterTime(x74_curFrame); + if (err) { + particle.x0_endFrame = -1; + return true; + } - if (CRealElement* pstsElem = desc->x14_x8_PSTS.get()) - { - float psts; - pstsElem->GetValue(x74_curFrame, psts); - double dt1Scaled = psts * dt1; - dt1 = std::max(0.0, dt1Scaled); - } - - x78_curSeconds += dt1; - - if (x26c_30_MBLR && dt > 0.0) - { - if (CIntElement* mbspElem = desc->x48_x34_MBSP.get()) - mbspElem->GetValue(x74_curFrame, x270_MBSP); - x270_MBSP = std::min(x270_MBSP, m_maxMBSP); - } - - int frameUpdateCount = 0; - while (t < x78_curSeconds && std::fabs(t - x78_curSeconds) >= 1.0 / 60000.0) - { - x2d4_aabbMin.splat(FLT_MAX); - x2e0_aabbMax.splat(-FLT_MAX); - x2ec_maxSize = 0.f; - CParticleGlobals::SetEmitterTime(x74_curFrame); - UpdateExistingParticles(); - CParticleGlobals::SetParticleLifetime(x268_PSLT); - - if (x74_curFrame < x268_PSLT && x88_particleEmission) - { - float grte = 0.f; - if (CRealElement* grteElem = desc->x2c_x20_GRTE.get()) - { - if (grteElem->GetValue(x74_curFrame, grte)) - { - x30_particles.clear(); - return true; - } - } - - grte = std::max(0.f, grte * x98_generatorRate); - x8c_generatorRemainder += grte; - int genCount = floorf(x8c_generatorRemainder); - x8c_generatorRemainder = x8c_generatorRemainder - genCount; - - if (CIntElement* maxpElem = desc->x28_x1c_MAXP.get()) - maxpElem->GetValue(x74_curFrame, x90_MAXP); - - CreateNewParticles(genCount); - } - - if (x26c_24_translationDirty) - UpdatePSTranslationAndOrientation(); - - if (x308_lightType != LightType::None) - UpdateLightParameters(); - - UpdateChildParticleSystems(1 / 60.0); - - ++frameUpdateCount; - ++x74_curFrame; - t += 1 / 60.0; - } - - if (std::fabs(t - x78_curSeconds) < 1.0 / 60000.0) - { - x78_curSeconds = t; - x80_timeDeltaScale = 1.f; - } - else - { - UpdateChildParticleSystems(dt1 - (frameUpdateCount / 60.0)); - x80_timeDeltaScale = 1.f - (t - x78_curSeconds) * 60.f; - } - - BuildParticleSystemBounds(); - - return false; + return false; } -void CElementGen::AccumulateBounds(const zeus::CVector3f& pos, float size) -{ - x2e0_aabbMax[0] = std::max(pos[0], float(x2e0_aabbMax[0])); - x2e0_aabbMax[1] = std::max(pos[1], float(x2e0_aabbMax[1])); - x2e0_aabbMax[2] = std::max(pos[2], float(x2e0_aabbMax[2])); - x2d4_aabbMin[0] = std::min(pos[0], float(x2d4_aabbMin[0])); - x2d4_aabbMin[1] = std::min(pos[1], float(x2d4_aabbMin[1])); - x2d4_aabbMin[2] = std::min(pos[2], float(x2d4_aabbMin[2])); - x2ec_maxSize = std::max(size, x2ec_maxSize); -} - -void CElementGen::UpdateAdvanceAccessParameters(u32 activeParticleCount, u32 particleFrame) -{ - if (activeParticleCount >= x60_advValues.size()) - { - CParticleGlobals::g_particleAccessParameters = nullptr; - return; - } - - CGenDescription* desc = x1c_genDesc.GetObj(); - - std::array& arr = x60_advValues[activeParticleCount]; - CParticleGlobals::g_particleAccessParameters = &arr; - - if (CRealElement* adv1 = desc->x10c_ADV1.get()) - adv1->GetValue(particleFrame, arr[0]); - if (CRealElement* adv2 = desc->x110_ADV2.get()) - adv2->GetValue(particleFrame, arr[1]); - if (CRealElement* adv3 = desc->x114_ADV3.get()) - adv3->GetValue(particleFrame, arr[2]); - if (CRealElement* adv4 = desc->x118_ADV4.get()) - adv4->GetValue(particleFrame, arr[3]); - if (CRealElement* adv5 = desc->x11c_ADV5.get()) - adv5->GetValue(particleFrame, arr[4]); - if (CRealElement* adv6 = desc->x120_ADV6.get()) - adv6->GetValue(particleFrame, arr[5]); - if (CRealElement* adv7 = desc->x124_ADV7.get()) - adv7->GetValue(particleFrame, arr[6]); - if (CRealElement* adv8 = desc->x128_ADV8.get()) - adv8->GetValue(particleFrame, arr[7]); -} - -bool CElementGen::UpdateVelocitySource(u32 idx, u32 particleFrame, CParticle& particle) -{ - bool err; - if (x278_hasVMD[idx]) - { - zeus::CVector3f localVel = x208_orientationInverse * particle.x1c_vel; - zeus::CVector3f localPos = x208_orientationInverse * (particle.x4_pos - xdc_translation); - err = x280_VELSources[idx]->GetValue(particleFrame, localVel, localPos); - particle.x1c_vel = x1d8_orientation.rotate(localVel); - particle.x4_pos = x1d8_orientation.rotate(localVel) + xdc_translation; - } - else - { - err = x280_VELSources[idx]->GetValue(particleFrame, particle.x1c_vel, particle.x4_pos); - } - - if (err) - { - particle.x0_endFrame = -1; - return true; - } - - return false; -} - -void CElementGen::UpdateExistingParticles() -{ - CGenDescription* desc = x1c_genDesc.GetObj(); - - x25c_activeParticleCount = 0; - CParticleGlobals::SetEmitterTime(x74_curFrame); - if (x25c_activeParticleCount < x60_advValues.size()) - CParticleGlobals::g_particleAccessParameters = &x60_advValues[x25c_activeParticleCount]; - else - CParticleGlobals::g_particleAccessParameters = nullptr; - - for (auto it = x30_particles.begin(); it != x30_particles.end();) - { - CParticle& particle = *it; - - if (particle.x0_endFrame < x74_curFrame) - { - --g_ParticleAliveCount; - if (it+1 == x30_particles.end()) - { - x30_particles.pop_back(); - break; - } - else - { - particle = x30_particles.back(); - - if (x2c_orientType == EModelOrientationType::One) - x50_parentMatrices[x25c_activeParticleCount] = x50_parentMatrices[x30_particles.size()-1]; - - if (x26d_28_enableADV) - x60_advValues[x25c_activeParticleCount] = x60_advValues[x30_particles.size()-1]; - - x30_particles.pop_back(); - if (particle.x0_endFrame < x74_curFrame) - continue; - } - } - - particle.x10_prevPos = particle.x4_pos; - particle.x4_pos += particle.x1c_vel; - - g_currentParticle = &particle; - - CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); - int particleFrame = x74_curFrame - particle.x28_startFrame; - CParticleGlobals::UpdateParticleLifetimeTweenValues(particleFrame); - - if (x26d_28_enableADV) - UpdateAdvanceAccessParameters(x25c_activeParticleCount, particleFrame); - - ++x25c_activeParticleCount; - - for (int i=0 ; i<4 ; ++i) - { - if (!x280_VELSources[i]) - break; - UpdateVelocitySource(i, particleFrame, particle); - } - - if (x26c_31_LINE) - { - if (CRealElement* leng = desc->x20_x14_LENG.get()) - leng->GetValue(particleFrame, particle.x2c_lineLengthOrSize); - if (CRealElement* widt = desc->x24_x18_WIDT.get()) - widt->GetValue(particleFrame, particle.x30_lineWidthOrRota); - } - else - { - if (CRealElement* rota = desc->x50_x3c_ROTA.get()) - rota->GetValue(particleFrame, particle.x30_lineWidthOrRota); - if (CRealElement* size = desc->x4c_x38_SIZE.get()) - size->GetValue(particleFrame, particle.x2c_lineLengthOrSize); - } - - if (CColorElement* colr = desc->x30_x24_COLR.get()) - colr->GetValue(particleFrame, particle.x34_color); - - AccumulateBounds(particle.x4_pos, particle.x2c_lineLengthOrSize); - ++it; - } - - if (x30_particles.empty()) - return; - - for (CWarp* warp : x4_modifierList) - if (warp->UpdateWarp()) - warp->ModifyParticles(x30_particles); -} - -void CElementGen::CreateNewParticles(int count) -{ - CGenDescription* desc = x1c_genDesc.GetObj(); - - if (!g_ParticleSystemInitialized) - Initialize(); - if (!count || x30_particles.size() >= x90_MAXP) - return; - - if (count + x30_particles.size() > x90_MAXP) - count = x90_MAXP - x30_particles.size(); - int newTotalCount = g_ParticleAliveCount + count; - if (newTotalCount > 2560) - count = 2560 - g_ParticleAliveCount; - - CGlobalRandom gr(x27c_randState); - x30_particles.reserve(x90_MAXP); - if (x26d_28_enableADV && x60_advValues.empty()) - x60_advValues.resize(m_maxMAXP); +void CElementGen::UpdateExistingParticles() { + CGenDescription* desc = x1c_genDesc.GetObj(); + x25c_activeParticleCount = 0; + CParticleGlobals::SetEmitterTime(x74_curFrame); + if (x25c_activeParticleCount < x60_advValues.size()) + CParticleGlobals::g_particleAccessParameters = &x60_advValues[x25c_activeParticleCount]; + else CParticleGlobals::g_particleAccessParameters = nullptr; - for (int i=0 ; ix34_x28_LTME.get()) - ltme->GetValue(0, particle.x0_endFrame); - CParticleGlobals::SetParticleLifetime(particle.x0_endFrame); - CParticleGlobals::UpdateParticleLifetimeTweenValues(0); - g_currentParticle = &particle; if (x26d_28_enableADV) - UpdateAdvanceAccessParameters(x30_particles.size()-1, 0); - particle.x0_endFrame += x74_curFrame; + x60_advValues[x25c_activeParticleCount] = x60_advValues[x30_particles.size() - 1]; - if (CColorElement* colr = desc->x30_x24_COLR.get()) - colr->GetValue(0, particle.x34_color); - else - particle.x34_color = zeus::CColor::skWhite; - - if (CEmitterElement* emtr = desc->x40_x2c_EMTR.get()) - { - emtr->GetValue(x74_curFrame, particle.x4_pos, particle.x1c_vel); - zeus::CVector3f compXf1 = (x13c_globalScaleTransformInverse * x1a8_localScaleTransformInverse) * xdc_translation; - zeus::CVector3f compXf2 = x1d8_orientation.rotate(particle.x4_pos); - particle.x4_pos = compXf1 + compXf2 + xf4_POFS; - particle.x1c_vel = x1d8_orientation.rotate(particle.x1c_vel); - } - else - { - zeus::CVector3f compXf1 = (x13c_globalScaleTransformInverse * x1a8_localScaleTransformInverse) * xdc_translation; - particle.x4_pos = compXf1 + xf4_POFS; - particle.x1c_vel.zeroOut(); - } - particle.x10_prevPos = particle.x4_pos; - - if (x26c_31_LINE) - { - if (CRealElement* leng = desc->x20_x14_LENG.get()) - leng->GetValue(0, particle.x2c_lineLengthOrSize); - else - particle.x2c_lineLengthOrSize = 1.f; - - if (CRealElement* widt = desc->x24_x18_WIDT.get()) - widt->GetValue(0, particle.x30_lineWidthOrRota); - else - particle.x30_lineWidthOrRota = 1.f; - } - else - { - if (CRealElement* rota = desc->x50_x3c_ROTA.get()) - rota->GetValue(0, particle.x30_lineWidthOrRota); - else - particle.x30_lineWidthOrRota = 0.f; - - if (CRealElement* size = desc->x4c_x38_SIZE.get()) - size->GetValue(0, particle.x2c_lineLengthOrSize); - else - particle.x2c_lineLengthOrSize = 0.1f; - } - - AccumulateBounds(particle.x4_pos, particle.x2c_lineLengthOrSize); + x30_particles.pop_back(); + if (particle.x0_endFrame < x74_curFrame) + continue; + } } + + particle.x10_prevPos = particle.x4_pos; + particle.x4_pos += particle.x1c_vel; + + g_currentParticle = &particle; + + CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); + int particleFrame = x74_curFrame - particle.x28_startFrame; + CParticleGlobals::UpdateParticleLifetimeTweenValues(particleFrame); + + if (x26d_28_enableADV) + UpdateAdvanceAccessParameters(x25c_activeParticleCount, particleFrame); + + ++x25c_activeParticleCount; + + for (int i = 0; i < 4; ++i) { + if (!x280_VELSources[i]) + break; + UpdateVelocitySource(i, particleFrame, particle); + } + + if (x26c_31_LINE) { + if (CRealElement* leng = desc->x20_x14_LENG.get()) + leng->GetValue(particleFrame, particle.x2c_lineLengthOrSize); + if (CRealElement* widt = desc->x24_x18_WIDT.get()) + widt->GetValue(particleFrame, particle.x30_lineWidthOrRota); + } else { + if (CRealElement* rota = desc->x50_x3c_ROTA.get()) + rota->GetValue(particleFrame, particle.x30_lineWidthOrRota); + if (CRealElement* size = desc->x4c_x38_SIZE.get()) + size->GetValue(particleFrame, particle.x2c_lineLengthOrSize); + } + + if (CColorElement* colr = desc->x30_x24_COLR.get()) + colr->GetValue(particleFrame, particle.x34_color); + + AccumulateBounds(particle.x4_pos, particle.x2c_lineLengthOrSize); + ++it; + } + + if (x30_particles.empty()) + return; + + for (CWarp* warp : x4_modifierList) + if (warp->UpdateWarp()) + warp->ModifyParticles(x30_particles); } -void CElementGen::UpdatePSTranslationAndOrientation() -{ - CGenDescription* desc = x1c_genDesc.GetObj(); +void CElementGen::CreateNewParticles(int count) { + CGenDescription* desc = x1c_genDesc.GetObj(); - CGlobalRandom gr(x27c_randState); - if (x268_PSLT < x74_curFrame) - return; + if (!g_ParticleSystemInitialized) + Initialize(); + if (!count || x30_particles.size() >= x90_MAXP) + return; - if (CVectorElement* pofs = desc->x18_xc_POFS.get()) - pofs->GetValue(x74_curFrame, xf4_POFS); + if (count + x30_particles.size() > x90_MAXP) + count = x90_MAXP - x30_particles.size(); + int newTotalCount = g_ParticleAliveCount + count; + if (newTotalCount > 2560) + count = 2560 - g_ParticleAliveCount; - if (CVectorElement* sspo = desc->xe8_xd4_SSPO.get()) - sspo->GetValue(x74_curFrame, x2b0_SSPO); + CGlobalRandom gr(x27c_randState); + x30_particles.reserve(x90_MAXP); + if (x26d_28_enableADV && x60_advValues.empty()) + x60_advValues.resize(m_maxMAXP); - if (CVectorElement* sepo = desc->xfc_xe8_SEPO.get()) - sepo->GetValue(x74_curFrame, x2c0_SEPO); -} + CParticleGlobals::g_particleAccessParameters = nullptr; -std::unique_ptr CElementGen::ConstructChildParticleSystem(const TToken& desc) -{ - CElementGen* ret = new CElementGen(desc, EModelOrientationType::Normal, - x26d_27_enableOPTS ? EOptionalSystemFlags::Two : EOptionalSystemFlags::One); - ret->x26d_26_modelsUseLights = x26d_26_modelsUseLights; - ret->SetGlobalTranslation(xe8_globalTranslation); - ret->SetGlobalOrientation(x22c_globalOrientation); - ret->SetGlobalScale(x100_globalScale); - ret->SetLocalScale(x16c_localScale); - ret->SetTranslation(xdc_translation); - ret->SetOrientation(x1d8_orientation); - ret->SetParticleEmission(x88_particleEmission); - ret->SetModulationColor(x338_moduColor); - return std::unique_ptr(ret); -} + for (int i = 0; i < count; ++i) { + x30_particles.emplace_back(); + ++g_ParticleAliveCount; + ++x25c_activeParticleCount; + ++x260_cumulativeParticles; + if (x2c_orientType == EModelOrientationType::One) + x50_parentMatrices[x30_particles.size() - 1] = x1d8_orientation.buildMatrix3f(); -void CElementGen::UpdateChildParticleSystems(double dt) -{ - CGenDescription* desc = x1c_genDesc.GetObj(); + CParticle& particle = x30_particles.back(); + particle.x28_startFrame = x74_curFrame; + if (CIntElement* ltme = desc->x34_x28_LTME.get()) + ltme->GetValue(0, particle.x0_endFrame); + CParticleGlobals::SetParticleLifetime(particle.x0_endFrame); + CParticleGlobals::UpdateParticleLifetimeTweenValues(0); + g_currentParticle = &particle; + if (x26d_28_enableADV) + UpdateAdvanceAccessParameters(x30_particles.size() - 1, 0); + particle.x0_endFrame += x74_curFrame; - CGlobalRandom gr(x27c_randState); - - SChildGeneratorDesc& icts = desc->x8c_x78_ICTS; - if (icts.m_found && x84_prevFrame != x74_curFrame && x2a0_CSSD == x74_curFrame) - { - int ncsyVal = 1; - if (CIntElement* ncsy = desc->x9c_x88_NCSY.get()) - ncsy->GetValue(x74_curFrame, ncsyVal); - - CGenDescription* ictsDesc = icts.m_token.GetObj(); - if (!(x26d_27_enableOPTS && ictsDesc->x45_31_x32_25_OPTS)) - { - x290_activePartChildren.reserve(ncsyVal + x290_activePartChildren.size()); - for (int i=0 ; i chGen = ConstructChildParticleSystem(icts.m_token); - x290_activePartChildren.emplace_back(std::move(chGen)); - } - } - } - - SChildGeneratorDesc& iits = desc->xb8_xa4_IITS; - if (iits.m_found && x84_prevFrame != x74_curFrame && x74_curFrame < x268_PSLT && - x88_particleEmission == 1 && x74_curFrame >= x2a4_SISY && - ((x74_curFrame - x2a4_SISY) % x2a8_PISY) == 0) - { - CGenDescription* iitsDesc = iits.m_token.GetObj(); - if (!(x26d_27_enableOPTS && iitsDesc->x45_31_x32_25_OPTS)) - { - std::unique_ptr chGen = ConstructChildParticleSystem(iits.m_token); - x290_activePartChildren.emplace_back(std::move(chGen)); - } - } - - CSpawnSystemKeyframeData* kssm = desc->xd0_xbc_KSSM.get(); - if (kssm && x84_prevFrame != x74_curFrame && x74_curFrame < x268_PSLT) - { - u16 backupSeed = g_GlobalSeed; - u16 incSeed = backupSeed; - - std::vector& systems = - kssm->GetSpawnedSystemsAtFrame(x74_curFrame); - x290_activePartChildren.reserve(x290_activePartChildren.size() + systems.size()); - for (CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo& system : systems) - { - TLockedToken& token = system.GetToken(); - if (!(x26d_27_enableOPTS && token.GetObj()->x45_31_x32_25_OPTS)) - { - g_GlobalSeed = incSeed; - std::unique_ptr chGen = ConstructChildParticleSystem(token); - x290_activePartChildren.emplace_back(std::move(chGen)); - } - incSeed += 1; - } - - g_GlobalSeed = backupSeed; - } - - SChildGeneratorDesc& idts = desc->xa4_x90_IDTS; - if (idts.m_found && x74_curFrame == x268_PSLT && x84_prevFrame != x74_curFrame) - { - int ndsyVal = 1; - if (CIntElement* ndsy = desc->xb4_xa0_NDSY.get()) - ndsy->GetValue(0, ndsyVal); - - CGenDescription* idtsDesc = idts.m_token.GetObj(); - if (!(x26d_27_enableOPTS && idtsDesc->x45_31_x32_25_OPTS)) - { - x290_activePartChildren.reserve(ndsyVal + x290_activePartChildren.size()); - for (int i=0 ; i chGen = ConstructChildParticleSystem(idts.m_token); - x290_activePartChildren.emplace_back(std::move(chGen)); - } - } - } - - SSwooshGeneratorDesc& sswh = desc->xd4_xc0_SSWH; - if (sswh.m_found && x84_prevFrame != x74_curFrame && x74_curFrame == x2ac_SSSD) - { - std::unique_ptr sswhGen = std::make_unique(sswh.m_token, 0); - sswhGen->SetGlobalTranslation(xe8_globalTranslation); - sswhGen->SetGlobalScale(x100_globalScale); - sswhGen->SetLocalScale(x16c_localScale); - sswhGen->SetTranslation(xdc_translation + x2b0_SSPO); - sswhGen->SetOrientation(x1d8_orientation); - sswhGen->SetParticleEmission(x88_particleEmission); - x290_activePartChildren.emplace_back(std::move(sswhGen)); - } - - SElectricGeneratorDesc& selc = desc->xec_xd8_SELC; - if (selc.m_found && x84_prevFrame != x74_curFrame && x74_curFrame == x2bc_SESD) - { - std::unique_ptr selcGen = std::make_unique(selc.m_token); - selcGen->SetGlobalTranslation(xe8_globalTranslation); - selcGen->SetGlobalScale(x100_globalScale); - selcGen->SetLocalScale(x16c_localScale); - selcGen->SetTranslation(xdc_translation + x2c0_SEPO); - selcGen->SetOrientation(x1d8_orientation); - selcGen->SetParticleEmission(x88_particleEmission); - x290_activePartChildren.emplace_back(std::move(selcGen)); - } - - for (auto p = x290_activePartChildren.begin() ; p != x290_activePartChildren.end() ;) - { - std::unique_ptr& ch = *p; - - ch->Update(dt); - if (ch->IsSystemDeletable()) - { - p = x290_activePartChildren.erase(p); - continue; - } - - ++p; - } - - x84_prevFrame = x74_curFrame; -} - -void CElementGen::UpdateLightParameters() -{ - CGenDescription* desc = x1c_genDesc.GetObj(); - - if (CColorElement* lclr = desc->x104_xf0_LCLR.get()) - lclr->GetValue(x74_curFrame, x30c_LCLR); - - if (CRealElement* lint = desc->x108_xf4_LINT.get()) - lint->GetValue(x74_curFrame, x310_LINT); - - switch (x308_lightType) - { - default: - case LightType::None: - case LightType::Custom: - case LightType::Spot: - { - if (CVectorElement* loff = desc->x10c_xf8_LOFF.get()) - loff->GetValue(x74_curFrame, x314_LOFF); - - if (CRealElement* lfor = desc->x118_x104_LFOR.get()) - lfor->GetValue(x74_curFrame, x330_LFOR); - - if (x308_lightType == LightType::Spot) - { - if (CRealElement* lsla = desc->x11c_x108_LSLA.get()) - lsla->GetValue(x74_curFrame, x334_LSLA); - } - } - case LightType::Directional: - { - if (x308_lightType != LightType::Custom) - { - if (CVectorElement* ldir = desc->x110_xfc_LDIR.get()) - ldir->GetValue(x74_curFrame, x320_LDIR); - } - } - } -} - -u32 CElementGen::GetParticleCountAllInternal() const -{ - u32 ret = x25c_activeParticleCount; - - for (const std::unique_ptr& ch : x290_activePartChildren) - if (ch->Get4CharId() == FOURCC('PART')) - ret += static_cast(*ch).GetParticleCountAll(); - - return ret; -} - -void CElementGen::EndLifetime() -{ - x268_PSLT = 0; - for (std::unique_ptr& ch : x290_activePartChildren) - { - if (ch->Get4CharId() == FOURCC('PART')) - static_cast(*ch).EndLifetime(); - else - ch->SetParticleEmission(false); - } -} - -void CElementGen::ForceParticleCreation(int amount) -{ - CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::g_currentParticleSystem; - CParticleGlobals::SParticleSystem thisSystem{ FOURCC('PART'), this }; - CParticleGlobals::g_currentParticleSystem = &thisSystem; - CParticleGlobals::SetEmitterTime(x74_curFrame); - CreateNewParticles(amount); - CParticleGlobals::g_currentParticleSystem = prevSystem; -} - -void CElementGen::BuildParticleSystemBounds() -{ - zeus::CAABox aabb; - bool accumulated = false; - - for (std::unique_ptr& ch : x290_activePartChildren) - { - auto chBounds = ch->GetBounds(); - if (chBounds) - { - accumulated = true; - aabb.accumulateBounds(chBounds.value()); - } - } - - x264_recursiveParticleCount = GetParticleCountAllInternal(); - if (GetParticleCount() > 0) - { - zeus::CVector3f scale = x100_globalScale * x2ec_maxSize; - zeus::CTransform xf = (x10c_globalScaleTransform * x22c_globalOrientation) * x178_localScaleTransform; - zeus::CAABox box = zeus::CAABox(x2d4_aabbMin, x2e0_aabbMax).getTransformedAABox(xf); - zeus::CVector3f min = box.min + xe8_globalTranslation - scale; - zeus::CVector3f max = box.max + xe8_globalTranslation + scale; - x2f0_systemBounds = zeus::CAABox(min, max); - } + if (CColorElement* colr = desc->x30_x24_COLR.get()) + colr->GetValue(0, particle.x34_color); else - x2f0_systemBounds = zeus::CAABox::skInvertedBox; + particle.x34_color = zeus::CColor::skWhite; - if (accumulated) - x2f0_systemBounds.accumulateBounds(aabb); -} + if (CEmitterElement* emtr = desc->x40_x2c_EMTR.get()) { + emtr->GetValue(x74_curFrame, particle.x4_pos, particle.x1c_vel); + zeus::CVector3f compXf1 = (x13c_globalScaleTransformInverse * x1a8_localScaleTransformInverse) * xdc_translation; + zeus::CVector3f compXf2 = x1d8_orientation.rotate(particle.x4_pos); + particle.x4_pos = compXf1 + compXf2 + xf4_POFS; + particle.x1c_vel = x1d8_orientation.rotate(particle.x1c_vel); + } else { + zeus::CVector3f compXf1 = (x13c_globalScaleTransformInverse * x1a8_localScaleTransformInverse) * xdc_translation; + particle.x4_pos = compXf1 + xf4_POFS; + particle.x1c_vel.zeroOut(); + } + particle.x10_prevPos = particle.x4_pos; -u32 CElementGen::GetSystemCount() -{ - u32 ret = 0; - for (const std::unique_ptr& child : x290_activePartChildren) - { - if (child->Get4CharId() == FOURCC('PART')) - ret += static_cast(*child).GetSystemCount(); - else - ret += 1; + if (x26c_31_LINE) { + if (CRealElement* leng = desc->x20_x14_LENG.get()) + leng->GetValue(0, particle.x2c_lineLengthOrSize); + else + particle.x2c_lineLengthOrSize = 1.f; + + if (CRealElement* widt = desc->x24_x18_WIDT.get()) + widt->GetValue(0, particle.x30_lineWidthOrRota); + else + particle.x30_lineWidthOrRota = 1.f; + } else { + if (CRealElement* rota = desc->x50_x3c_ROTA.get()) + rota->GetValue(0, particle.x30_lineWidthOrRota); + else + particle.x30_lineWidthOrRota = 0.f; + + if (CRealElement* size = desc->x4c_x38_SIZE.get()) + size->GetValue(0, particle.x2c_lineLengthOrSize); + else + particle.x2c_lineLengthOrSize = 0.1f; } - return (ret + (x25c_activeParticleCount != 0)); + AccumulateBounds(particle.x4_pos, particle.x2c_lineLengthOrSize); + } } -void CElementGen::Render(const CActorLights* actorLights) -{ - CGenDescription* desc = x1c_genDesc.GetObj(); +void CElementGen::UpdatePSTranslationAndOrientation() { + CGenDescription* desc = x1c_genDesc.GetObj(); - x274_backupLightActive = CGraphics::g_LightActive; - CGraphics::DisableAllLights(); + CGlobalRandom gr(x27c_randState); + if (x268_PSLT < x74_curFrame) + return; - for (std::unique_ptr& child : x290_activePartChildren) - child->Render(); + if (CVectorElement* pofs = desc->x18_xc_POFS.get()) + pofs->GetValue(x74_curFrame, xf4_POFS); - CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::g_currentParticleSystem; - CParticleGlobals::SParticleSystem thisSystem{ FOURCC('PART'), this }; - CParticleGlobals::g_currentParticleSystem = &thisSystem; + if (CVectorElement* sspo = desc->xe8_xd4_SSPO.get()) + sspo->GetValue(x74_curFrame, x2b0_SSPO); - if (x30_particles.size()) - { - SParticleModel& pmdl = desc->x5c_x48_PMDL; - if (pmdl.m_found || desc->x45_24_x31_26_PMUS) - RenderModels(actorLights); - - if (x26c_31_LINE) - RenderLines(); - else - RenderParticles(); - } - - CParticleGlobals::g_currentParticleSystem = prevSystem; + if (CVectorElement* sepo = desc->xfc_xe8_SEPO.get()) + sepo->GetValue(x74_curFrame, x2c0_SEPO); } -void CElementGen::RenderModels(const CActorLights* actorLights) -{ - CGenDescription* desc = x1c_genDesc.GetObj(); +std::unique_ptr CElementGen::ConstructChildParticleSystem(const TToken& desc) { + CElementGen* ret = new CElementGen(desc, EModelOrientationType::Normal, + x26d_27_enableOPTS ? EOptionalSystemFlags::Two : EOptionalSystemFlags::One); + ret->x26d_26_modelsUseLights = x26d_26_modelsUseLights; + ret->SetGlobalTranslation(xe8_globalTranslation); + ret->SetGlobalOrientation(x22c_globalOrientation); + ret->SetGlobalScale(x100_globalScale); + ret->SetLocalScale(x16c_localScale); + ret->SetTranslation(xdc_translation); + ret->SetOrientation(x1d8_orientation); + ret->SetParticleEmission(x88_particleEmission); + ret->SetModulationColor(x338_moduColor); + return std::unique_ptr(ret); +} - if (x26d_26_modelsUseLights) - CGraphics::SetLightState(x274_backupLightActive); - CGlobalRandom gr(x27c_randState); +void CElementGen::UpdateChildParticleSystems(double dt) { + CGenDescription* desc = x1c_genDesc.GetObj(); - SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; - CUVElement* texr = desc->x54_x40_TEXR.get(); - CTexture* cachedTex = nullptr; - bool texConst = true; - bool moveRedToAlphaBuffer = false; + CGlobalRandom gr(x27c_randState); - if (desc->x45_24_x31_26_PMUS) - { - if (sMoveRedToAlphaBuffer && desc->x44_31_x31_25_PMAB && desc->x54_x40_TEXR) - moveRedToAlphaBuffer = true; + SChildGeneratorDesc& icts = desc->x8c_x78_ICTS; + if (icts.m_found && x84_prevFrame != x74_curFrame && x2a0_CSSD == x74_curFrame) { + int ncsyVal = 1; + if (CIntElement* ncsy = desc->x9c_x88_NCSY.get()) + ncsy->GetValue(x74_curFrame, ncsyVal); - if (desc->x44_31_x31_25_PMAB) - { - CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false); - if (moveRedToAlphaBuffer) - CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear); - else - CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear); - } - else - { - CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true); - CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear); - } + CGenDescription* ictsDesc = icts.m_token.GetObj(); + if (!(x26d_27_enableOPTS && ictsDesc->x45_31_x32_25_OPTS)) { + x290_activePartChildren.reserve(ncsyVal + x290_activePartChildren.size()); + for (int i = 0; i < ncsyVal; ++i) { + std::unique_ptr chGen = ConstructChildParticleSystem(icts.m_token); + x290_activePartChildren.emplace_back(std::move(chGen)); + } + } + } - CGraphics::SetCullMode(ERglCullMode::None); + SChildGeneratorDesc& iits = desc->xb8_xa4_IITS; + if (iits.m_found && x84_prevFrame != x74_curFrame && x74_curFrame < x268_PSLT && x88_particleEmission == 1 && + x74_curFrame >= x2a4_SISY && ((x74_curFrame - x2a4_SISY) % x2a8_PISY) == 0) { + CGenDescription* iitsDesc = iits.m_token.GetObj(); + if (!(x26d_27_enableOPTS && iitsDesc->x45_31_x32_25_OPTS)) { + std::unique_ptr chGen = ConstructChildParticleSystem(iits.m_token); + x290_activePartChildren.emplace_back(std::move(chGen)); + } + } - if (texr) - { - CParticle& target = x30_particles[0]; - int partFrame = x74_curFrame - target.x28_startFrame; - cachedTex = texr->GetValueTexture(partFrame).GetObj(); - cachedTex->Load(0, CTexture::EClampMode::One); - /* Shade as TEXC * RASC and TEXA * RASA */ - if (moveRedToAlphaBuffer) - { - /* Color = Prev.rgb * Prev.a */ - /* Alpha = Tex.r * Prev.a */ - } - texConst = texr->HasConstantTexture(); - texr->GetValueUV(partFrame, uvs); - } + CSpawnSystemKeyframeData* kssm = desc->xd0_xbc_KSSM.get(); + if (kssm && x84_prevFrame != x74_curFrame && x74_curFrame < x268_PSLT) { + u16 backupSeed = g_GlobalSeed; + u16 incSeed = backupSeed; - switch (m_shaderClass) - { - case CElementGenShaders::EShaderClass::Tex: - g_instTexData.clear(); - g_instTexData.reserve(x30_particles.size()); - break; - case CElementGenShaders::EShaderClass::NoTex: - g_instNoTexData.clear(); - g_instNoTexData.reserve(x30_particles.size()); - break; - default: - Log.report(logvisor::Fatal, "unexpected particle shader class"); - break; - } - - SParticleUniforms uniformData = - { - CGraphics::GetPerspectiveProjectionMatrix(true), - {1.f, 1.f, 1.f, 1.f} - }; - - m_uniformBufPmus->load(&uniformData, sizeof(SParticleUniforms)); - - if (moveRedToAlphaBuffer) - CGraphics::SetShaderDataBinding(m_redToAlphaDataBindPmus); - else - CGraphics::SetShaderDataBinding(m_normalDataBindPmus); + std::vector& systems = + kssm->GetSpawnedSystemsAtFrame(x74_curFrame); + x290_activePartChildren.reserve(x290_activePartChildren.size() + systems.size()); + for (CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo& system : systems) { + TLockedToken& token = system.GetToken(); + if (!(x26d_27_enableOPTS && token.GetObj()->x45_31_x32_25_OPTS)) { + g_GlobalSeed = incSeed; + std::unique_ptr chGen = ConstructChildParticleSystem(token); + x290_activePartChildren.emplace_back(std::move(chGen)); + } + incSeed += 1; } - zeus::CTransform orient = zeus::CTransform::Identity(); - if (desc->x45_25_x31_27_PMOO) - orient = x1d8_orientation; - orient = orient * x22c_globalOrientation; + g_GlobalSeed = backupSeed; + } - CVectorElement* pmrt = desc->x70_x5c_PMRT.get(); - bool pmrtConst = false; - if (pmrt) - pmrtConst = pmrt->IsFastConstant(); + SChildGeneratorDesc& idts = desc->xa4_x90_IDTS; + if (idts.m_found && x74_curFrame == x268_PSLT && x84_prevFrame != x74_curFrame) { + int ndsyVal = 1; + if (CIntElement* ndsy = desc->xb4_xa0_NDSY.get()) + ndsy->GetValue(0, ndsyVal); - zeus::CVector3f trans = (x13c_globalScaleTransformInverse * x1a8_localScaleTransformInverse) * xe8_globalTranslation; + CGenDescription* idtsDesc = idts.m_token.GetObj(); + if (!(x26d_27_enableOPTS && idtsDesc->x45_31_x32_25_OPTS)) { + x290_activePartChildren.reserve(ndsyVal + x290_activePartChildren.size()); + for (int i = 0; i < ndsyVal; ++i) { + std::unique_ptr chGen = ConstructChildParticleSystem(idts.m_token); + x290_activePartChildren.emplace_back(std::move(chGen)); + } + } + } - zeus::CTransform rot = zeus::CTransform::Identity(); - if (pmrtConst) - { + SSwooshGeneratorDesc& sswh = desc->xd4_xc0_SSWH; + if (sswh.m_found && x84_prevFrame != x74_curFrame && x74_curFrame == x2ac_SSSD) { + std::unique_ptr sswhGen = std::make_unique(sswh.m_token, 0); + sswhGen->SetGlobalTranslation(xe8_globalTranslation); + sswhGen->SetGlobalScale(x100_globalScale); + sswhGen->SetLocalScale(x16c_localScale); + sswhGen->SetTranslation(xdc_translation + x2b0_SSPO); + sswhGen->SetOrientation(x1d8_orientation); + sswhGen->SetParticleEmission(x88_particleEmission); + x290_activePartChildren.emplace_back(std::move(sswhGen)); + } + + SElectricGeneratorDesc& selc = desc->xec_xd8_SELC; + if (selc.m_found && x84_prevFrame != x74_curFrame && x74_curFrame == x2bc_SESD) { + std::unique_ptr selcGen = std::make_unique(selc.m_token); + selcGen->SetGlobalTranslation(xe8_globalTranslation); + selcGen->SetGlobalScale(x100_globalScale); + selcGen->SetLocalScale(x16c_localScale); + selcGen->SetTranslation(xdc_translation + x2c0_SEPO); + selcGen->SetOrientation(x1d8_orientation); + selcGen->SetParticleEmission(x88_particleEmission); + x290_activePartChildren.emplace_back(std::move(selcGen)); + } + + for (auto p = x290_activePartChildren.begin(); p != x290_activePartChildren.end();) { + std::unique_ptr& ch = *p; + + ch->Update(dt); + if (ch->IsSystemDeletable()) { + p = x290_activePartChildren.erase(p); + continue; + } + + ++p; + } + + x84_prevFrame = x74_curFrame; +} + +void CElementGen::UpdateLightParameters() { + CGenDescription* desc = x1c_genDesc.GetObj(); + + if (CColorElement* lclr = desc->x104_xf0_LCLR.get()) + lclr->GetValue(x74_curFrame, x30c_LCLR); + + if (CRealElement* lint = desc->x108_xf4_LINT.get()) + lint->GetValue(x74_curFrame, x310_LINT); + + switch (x308_lightType) { + default: + case LightType::None: + case LightType::Custom: + case LightType::Spot: { + if (CVectorElement* loff = desc->x10c_xf8_LOFF.get()) + loff->GetValue(x74_curFrame, x314_LOFF); + + if (CRealElement* lfor = desc->x118_x104_LFOR.get()) + lfor->GetValue(x74_curFrame, x330_LFOR); + + if (x308_lightType == LightType::Spot) { + if (CRealElement* lsla = desc->x11c_x108_LSLA.get()) + lsla->GetValue(x74_curFrame, x334_LSLA); + } + } + case LightType::Directional: { + if (x308_lightType != LightType::Custom) { + if (CVectorElement* ldir = desc->x110_xfc_LDIR.get()) + ldir->GetValue(x74_curFrame, x320_LDIR); + } + } + } +} + +u32 CElementGen::GetParticleCountAllInternal() const { + u32 ret = x25c_activeParticleCount; + + for (const std::unique_ptr& ch : x290_activePartChildren) + if (ch->Get4CharId() == FOURCC('PART')) + ret += static_cast(*ch).GetParticleCountAll(); + + return ret; +} + +void CElementGen::EndLifetime() { + x268_PSLT = 0; + for (std::unique_ptr& ch : x290_activePartChildren) { + if (ch->Get4CharId() == FOURCC('PART')) + static_cast(*ch).EndLifetime(); + else + ch->SetParticleEmission(false); + } +} + +void CElementGen::ForceParticleCreation(int amount) { + CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::g_currentParticleSystem; + CParticleGlobals::SParticleSystem thisSystem{FOURCC('PART'), this}; + CParticleGlobals::g_currentParticleSystem = &thisSystem; + CParticleGlobals::SetEmitterTime(x74_curFrame); + CreateNewParticles(amount); + CParticleGlobals::g_currentParticleSystem = prevSystem; +} + +void CElementGen::BuildParticleSystemBounds() { + zeus::CAABox aabb; + bool accumulated = false; + + for (std::unique_ptr& ch : x290_activePartChildren) { + auto chBounds = ch->GetBounds(); + if (chBounds) { + accumulated = true; + aabb.accumulateBounds(chBounds.value()); + } + } + + x264_recursiveParticleCount = GetParticleCountAllInternal(); + if (GetParticleCount() > 0) { + zeus::CVector3f scale = x100_globalScale * x2ec_maxSize; + zeus::CTransform xf = (x10c_globalScaleTransform * x22c_globalOrientation) * x178_localScaleTransform; + zeus::CAABox box = zeus::CAABox(x2d4_aabbMin, x2e0_aabbMax).getTransformedAABox(xf); + zeus::CVector3f min = box.min + xe8_globalTranslation - scale; + zeus::CVector3f max = box.max + xe8_globalTranslation + scale; + x2f0_systemBounds = zeus::CAABox(min, max); + } else + x2f0_systemBounds = zeus::CAABox::skInvertedBox; + + if (accumulated) + x2f0_systemBounds.accumulateBounds(aabb); +} + +u32 CElementGen::GetSystemCount() { + u32 ret = 0; + for (const std::unique_ptr& child : x290_activePartChildren) { + if (child->Get4CharId() == FOURCC('PART')) + ret += static_cast(*child).GetSystemCount(); + else + ret += 1; + } + + return (ret + (x25c_activeParticleCount != 0)); +} + +void CElementGen::Render(const CActorLights* actorLights) { + CGenDescription* desc = x1c_genDesc.GetObj(); + + x274_backupLightActive = CGraphics::g_LightActive; + CGraphics::DisableAllLights(); + + for (std::unique_ptr& child : x290_activePartChildren) + child->Render(); + + CParticleGlobals::SParticleSystem* prevSystem = CParticleGlobals::g_currentParticleSystem; + CParticleGlobals::SParticleSystem thisSystem{FOURCC('PART'), this}; + CParticleGlobals::g_currentParticleSystem = &thisSystem; + + if (x30_particles.size()) { + SParticleModel& pmdl = desc->x5c_x48_PMDL; + if (pmdl.m_found || desc->x45_24_x31_26_PMUS) + RenderModels(actorLights); + + if (x26c_31_LINE) + RenderLines(); + else + RenderParticles(); + } + + CParticleGlobals::g_currentParticleSystem = prevSystem; +} + +void CElementGen::RenderModels(const CActorLights* actorLights) { + CGenDescription* desc = x1c_genDesc.GetObj(); + + if (x26d_26_modelsUseLights) + CGraphics::SetLightState(x274_backupLightActive); + CGlobalRandom gr(x27c_randState); + + SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; + CUVElement* texr = desc->x54_x40_TEXR.get(); + CTexture* cachedTex = nullptr; + bool texConst = true; + bool moveRedToAlphaBuffer = false; + + if (desc->x45_24_x31_26_PMUS) { + if (sMoveRedToAlphaBuffer && desc->x44_31_x31_25_PMAB && desc->x54_x40_TEXR) + moveRedToAlphaBuffer = true; + + if (desc->x44_31_x31_25_PMAB) { + CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false); + if (moveRedToAlphaBuffer) + CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear); + else + CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, + ERglLogicOp::Clear); + } else { + CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true); + CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, + ERglLogicOp::Clear); + } + + CGraphics::SetCullMode(ERglCullMode::None); + + if (texr) { + CParticle& target = x30_particles[0]; + int partFrame = x74_curFrame - target.x28_startFrame; + cachedTex = texr->GetValueTexture(partFrame).GetObj(); + cachedTex->Load(0, CTexture::EClampMode::One); + /* Shade as TEXC * RASC and TEXA * RASA */ + if (moveRedToAlphaBuffer) { + /* Color = Prev.rgb * Prev.a */ + /* Alpha = Tex.r * Prev.a */ + } + texConst = texr->HasConstantTexture(); + texr->GetValueUV(partFrame, uvs); + } + + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: + g_instTexData.clear(); + g_instTexData.reserve(x30_particles.size()); + break; + case CElementGenShaders::EShaderClass::NoTex: + g_instNoTexData.clear(); + g_instNoTexData.reserve(x30_particles.size()); + break; + default: + Log.report(logvisor::Fatal, "unexpected particle shader class"); + break; + } + + SParticleUniforms uniformData = {CGraphics::GetPerspectiveProjectionMatrix(true), {1.f, 1.f, 1.f, 1.f}}; + + m_uniformBufPmus->load(&uniformData, sizeof(SParticleUniforms)); + + if (moveRedToAlphaBuffer) + CGraphics::SetShaderDataBinding(m_redToAlphaDataBindPmus); + else + CGraphics::SetShaderDataBinding(m_normalDataBindPmus); + } + + zeus::CTransform orient = zeus::CTransform::Identity(); + if (desc->x45_25_x31_27_PMOO) + orient = x1d8_orientation; + orient = orient * x22c_globalOrientation; + + CVectorElement* pmrt = desc->x70_x5c_PMRT.get(); + bool pmrtConst = false; + if (pmrt) + pmrtConst = pmrt->IsFastConstant(); + + zeus::CVector3f trans = (x13c_globalScaleTransformInverse * x1a8_localScaleTransformInverse) * xe8_globalTranslation; + + zeus::CTransform rot = zeus::CTransform::Identity(); + if (pmrtConst) { + zeus::CVector3f pmrtVal; + pmrt->GetValue(x74_curFrame, pmrtVal); + rot = zeus::CTransform::RotateZ(zeus::degToRad(pmrtVal[2])); + rot.rotateLocalY(zeus::degToRad(pmrtVal[1])); + rot.rotateLocalX(zeus::degToRad(pmrtVal[0])); + } + rot = orient * rot; + + CParticleGlobals::SetEmitterTime(x74_curFrame); + zeus::CColor col = {1.f, 1.f, 1.f, 1.f}; + + zeus::CVector3f pmopVec; + auto matrixIt = x50_parentMatrices.begin(); + for (int i = 0; i < x30_particles.size(); ++i) { + CParticle& particle = x30_particles[i]; + g_currentParticle = &particle; + + if (particle.x0_endFrame == -1) { + if (x2c_orientType == EModelOrientationType::One) + ++matrixIt; + continue; + } + CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); + int partFrame = x74_curFrame - particle.x28_startFrame - 1; + CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame); + if (i < x60_advValues.size()) + CParticleGlobals::g_particleAccessParameters = &x60_advValues[i]; + else + CParticleGlobals::g_particleAccessParameters = nullptr; + CVectorElement* pmop = desc->x6c_x58_PMOP.get(); + if (pmop) + pmop->GetValue(partFrame, pmopVec); + + zeus::CTransform partTrans = zeus::CTransform::Translate(particle.x4_pos + trans); + if (x2c_orientType == EModelOrientationType::One) { + zeus::CTransform partRot(*matrixIt); + zeus::CVector3f pmopRotateOffset = (orient * partRot) * pmopVec; + partTrans = partTrans * partRot; + partTrans += pmopRotateOffset; + } else { + partTrans += orient * pmopVec; + } + + if (pmrtConst) { + partTrans = partTrans * rot; + } else { + if (pmrt) { zeus::CVector3f pmrtVal; - pmrt->GetValue(x74_curFrame, pmrtVal); + pmrt->GetValue(partFrame, pmrtVal); rot = zeus::CTransform::RotateZ(zeus::degToRad(pmrtVal[2])); rot.rotateLocalY(zeus::degToRad(pmrtVal[1])); rot.rotateLocalX(zeus::degToRad(pmrtVal[0])); - } - rot = orient * rot; - - CParticleGlobals::SetEmitterTime(x74_curFrame); - zeus::CColor col = {1.f, 1.f, 1.f, 1.f}; - - zeus::CVector3f pmopVec; - auto matrixIt = x50_parentMatrices.begin(); - for (int i=0 ; ix6c_x58_PMOP.get(); - if (pmop) - pmop->GetValue(partFrame, pmopVec); - - zeus::CTransform partTrans = zeus::CTransform::Translate(particle.x4_pos + trans); - if (x2c_orientType == EModelOrientationType::One) - { - zeus::CTransform partRot(*matrixIt); - zeus::CVector3f pmopRotateOffset = (orient * partRot) * pmopVec; - partTrans = partTrans * partRot; - partTrans += pmopRotateOffset; - } - else - { - partTrans += orient * pmopVec; - } - - if (pmrtConst) - { - partTrans = partTrans * rot; - } - else - { - if (pmrt) - { - zeus::CVector3f pmrtVal; - pmrt->GetValue(partFrame, pmrtVal); - rot = zeus::CTransform::RotateZ(zeus::degToRad(pmrtVal[2])); - rot.rotateLocalY(zeus::degToRad(pmrtVal[1])); - rot.rotateLocalX(zeus::degToRad(pmrtVal[0])); - partTrans = partTrans * (orient * rot); - } - else - { - partTrans = partTrans * rot; - } - } - - CVectorElement* pmsc = desc->x74_x60_PMSC.get(); - if (pmsc) - { - zeus::CVector3f pmscVal; - pmsc->GetValue(partFrame, pmscVal); - partTrans = partTrans * zeus::CTransform::Scale(pmscVal); - } - - CColorElement* pmcl = desc->x78_x64_PMCL.get(); - if (pmcl) - pmcl->GetValue(partFrame, col); - - CGraphics::SetModelMatrix((x10c_globalScaleTransform * partTrans) * x178_localScaleTransform); - - if (desc->x45_24_x31_26_PMUS) - { - if (!texConst) - { - CTexture* tex = texr->GetValueTexture(x74_curFrame - particle.x28_startFrame).GetObj(); - if (tex != cachedTex) - { - tex->Load(0, CTexture::EClampMode::One); - cachedTex = tex; - } - } - - switch (m_shaderClass) - { - case CElementGenShaders::EShaderClass::Tex: - { - g_instTexData.emplace_back(); - SParticleInstanceTex& inst = g_instTexData.back(); - inst.pos[0] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, 0.5f}; - inst.pos[1] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, 0.5f}; - inst.pos[2] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, -0.5f}; - inst.pos[3] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, -0.5f}; - inst.color = col; - inst.uvs[0] = {uvs.xMax, uvs.yMax}; - inst.uvs[1] = {uvs.xMin, uvs.yMax}; - inst.uvs[2] = {uvs.xMax, uvs.yMin}; - inst.uvs[3] = {uvs.xMin, uvs.yMin}; - break; - } - case CElementGenShaders::EShaderClass::NoTex: - { - g_instNoTexData.emplace_back(); - SParticleInstanceNoTex& inst = g_instNoTexData.back(); - inst.pos[0] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, 0.5f}; - inst.pos[1] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, 0.5f}; - inst.pos[2] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, -0.5f}; - inst.pos[3] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, -0.5f}; - inst.color = col; - break; - } - default: break; - } - } - else - { - CModel* model = desc->x5c_x48_PMDL.m_token.GetObj(); - if (actorLights) - actorLights->ActivateLights(model->GetInstance()); - if (g_subtractBlend) - { - model->Draw({5, 0, 1, zeus::CColor(1.f, 0.5f)}); - } - else if (desc->x44_31_x31_25_PMAB) - { - model->Draw({7, 0, 1, col}); - } - else - { - if (1.f == col.a()) - model->Draw({0, 0, 3, zeus::CColor::skWhite}); - else - model->Draw({5, 0, 1, col}); - } - } - - if (x2c_orientType == EModelOrientationType::One) - ++matrixIt; + partTrans = partTrans * (orient * rot); + } else { + partTrans = partTrans * rot; + } } - if (desc->x45_24_x31_26_PMUS) - { - switch (m_shaderClass) - { - case CElementGenShaders::EShaderClass::Tex: - m_instBufPmus->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); - CGraphics::DrawInstances(0, 4, g_instTexData.size()); - break; - case CElementGenShaders::EShaderClass::NoTex: - m_instBufPmus->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); - CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); - break; - default: break; + CVectorElement* pmsc = desc->x74_x60_PMSC.get(); + if (pmsc) { + zeus::CVector3f pmscVal; + pmsc->GetValue(partFrame, pmscVal); + partTrans = partTrans * zeus::CTransform::Scale(pmscVal); + } + + CColorElement* pmcl = desc->x78_x64_PMCL.get(); + if (pmcl) + pmcl->GetValue(partFrame, col); + + CGraphics::SetModelMatrix((x10c_globalScaleTransform * partTrans) * x178_localScaleTransform); + + if (desc->x45_24_x31_26_PMUS) { + if (!texConst) { + CTexture* tex = texr->GetValueTexture(x74_curFrame - particle.x28_startFrame).GetObj(); + if (tex != cachedTex) { + tex->Load(0, CTexture::EClampMode::One); + cachedTex = tex; } + } + + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: { + g_instTexData.emplace_back(); + SParticleInstanceTex& inst = g_instTexData.back(); + inst.pos[0] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, 0.5f}; + inst.pos[1] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, 0.5f}; + inst.pos[2] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, -0.5f}; + inst.pos[3] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, -0.5f}; + inst.color = col; + inst.uvs[0] = {uvs.xMax, uvs.yMax}; + inst.uvs[1] = {uvs.xMin, uvs.yMax}; + inst.uvs[2] = {uvs.xMax, uvs.yMin}; + inst.uvs[3] = {uvs.xMin, uvs.yMin}; + break; + } + case CElementGenShaders::EShaderClass::NoTex: { + g_instNoTexData.emplace_back(); + SParticleInstanceNoTex& inst = g_instNoTexData.back(); + inst.pos[0] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, 0.5f}; + inst.pos[1] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, 0.5f}; + inst.pos[2] = CGraphics::g_GXModelView * zeus::CVector3f{0.5f, 0.f, -0.5f}; + inst.pos[3] = CGraphics::g_GXModelView * zeus::CVector3f{-0.5f, 0.f, -0.5f}; + inst.color = col; + break; + } + default: + break; + } + } else { + CModel* model = desc->x5c_x48_PMDL.m_token.GetObj(); + if (actorLights) + actorLights->ActivateLights(model->GetInstance()); + if (g_subtractBlend) { + model->Draw({5, 0, 1, zeus::CColor(1.f, 0.5f)}); + } else if (desc->x44_31_x31_25_PMAB) { + model->Draw({7, 0, 1, col}); + } else { + if (1.f == col.a()) + model->Draw({0, 0, 3, zeus::CColor::skWhite}); + else + model->Draw({5, 0, 1, col}); + } } - if (x26d_26_modelsUseLights) - CGraphics::DisableAllLights(); + if (x2c_orientType == EModelOrientationType::One) + ++matrixIt; + } - CGraphics::SetCullMode(ERglCullMode::Front); - if (moveRedToAlphaBuffer) - { - /* Restore passthrough */ + if (desc->x45_24_x31_26_PMUS) { + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: + m_instBufPmus->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); + CGraphics::DrawInstances(0, 4, g_instTexData.size()); + break; + case CElementGenShaders::EShaderClass::NoTex: + m_instBufPmus->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); + CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); + break; + default: + break; } + } + + if (x26d_26_modelsUseLights) + CGraphics::DisableAllLights(); + + CGraphics::SetCullMode(ERglCullMode::Front); + if (moveRedToAlphaBuffer) { + /* Restore passthrough */ + } } -void CElementGen::RenderLines() -{ - CGenDescription* desc = x1c_genDesc.GetObj(); - CGlobalRandom gr(x27c_randState); +void CElementGen::RenderLines() { + CGenDescription* desc = x1c_genDesc.GetObj(); + CGlobalRandom gr(x27c_randState); - zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix); - systemViewPointMatrix.origin.zeroOut(); - zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x22c_globalOrientation; - systemViewPointMatrix = ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) * systemViewPointMatrix) * x178_localScaleTransform; - CGraphics::SetModelMatrix(systemViewPointMatrix); + zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix); + systemViewPointMatrix.origin.zeroOut(); + zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x22c_globalOrientation; + systemViewPointMatrix = + ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) * systemViewPointMatrix) * + x178_localScaleTransform; + CGraphics::SetModelMatrix(systemViewPointMatrix); - CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); + CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); - if (x26c_26_AAPH) - { - CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false); - CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear); - } - else - { - CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true); - CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear); + if (x26c_26_AAPH) { + CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false); + CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear); + } else { + CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true); + CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, + ERglLogicOp::Clear); + } + + CRealElement* widt = desc->x24_x18_WIDT.get(); + bool widtConst = false; + if (widt) + widtConst = widt->IsConstant(); + + CUVElement* texr = desc->x54_x40_TEXR.get(); + SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; + bool constTexr = true; + bool constUVs = true; + CTexture* cachedTex = nullptr; + zeus::CColor moduColor = zeus::CColor::skWhite; + if (texr) { + CParticle& target = x30_particles[0]; + int partFrame = x74_curFrame - target.x28_startFrame; + cachedTex = texr->GetValueTexture(partFrame).GetObj(); + cachedTex->Load(0, CTexture::EClampMode::One); + + /* Set TEXC * RASC */ + + if (x338_moduColor != zeus::CColor::skBlack) { + /* Add RASC * PREVC pass for MODU color loaded into channel mat-color */ + moduColor = x338_moduColor; } - CRealElement* widt = desc->x24_x18_WIDT.get(); - bool widtConst = false; - if (widt) - widtConst = widt->IsConstant(); + constTexr = texr->HasConstantTexture(); + texr->GetValueUV(partFrame, uvs); + constUVs = texr->HasConstantUV(); + } - CUVElement* texr = desc->x54_x40_TEXR.get(); - SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; - bool constTexr = true; - bool constUVs = true; - CTexture* cachedTex = nullptr; - zeus::CColor moduColor = zeus::CColor::skWhite; - if (texr) - { - CParticle& target = x30_particles[0]; - int partFrame = x74_curFrame - target.x28_startFrame; - cachedTex = texr->GetValueTexture(partFrame).GetObj(); - cachedTex->Load(0, CTexture::EClampMode::One); + float constWidth = 1.f; + if (widtConst) { + widt->GetValue(0, constWidth); + constWidth = std::max(0.f, std::min(constWidth, 42.5f)); + } - /* Set TEXC * RASC */ + m_lineRenderer->Reset(); - if (x338_moduColor != zeus::CColor::skBlack) - { - /* Add RASC * PREVC pass for MODU color loaded into channel mat-color */ - moduColor = x338_moduColor; - } + for (int i = 0; i < x30_particles.size(); ++i) { + CParticle& particle = x30_particles[i]; + g_currentParticle = &particle; - constTexr = texr->HasConstantTexture(); - texr->GetValueUV(partFrame, uvs); - constUVs = texr->HasConstantUV(); + int partFrame = x74_curFrame - particle.x28_startFrame; + + if (!constTexr) { + CTexture* tex = texr->GetValueTexture(partFrame).GetObj(); + if (tex != cachedTex) { + tex->Load(0, CTexture::EClampMode::One); + cachedTex = tex; + } } - float constWidth = 1.f; - if (widtConst) - { - widt->GetValue(0, constWidth); - constWidth = std::max(0.f, std::min(constWidth, 42.5f)); + if (!constUVs) + texr->GetValueUV(partFrame, uvs); + + zeus::CVector3f dVec = particle.x4_pos - particle.x10_prevPos; + if (x26d_24_FXLL) + if (dVec.magSquared() >= 0.f) + dVec.normalize(); + + zeus::CVector3f p1 = systemCameraMatrix * particle.x4_pos; + zeus::CVector3f p2 = systemCameraMatrix * (particle.x2c_lineLengthOrSize * dVec + particle.x4_pos); + + if (widtConst) { + m_lineRenderer->AddVertex(p1, particle.x34_color, constWidth, {uvs.xMin, uvs.yMin}); + m_lineRenderer->AddVertex(p2, particle.x34_color, constWidth, {uvs.xMax, uvs.yMax}); + } else if (widt) { + float width = 1.f; + widt->GetValue(0, width); + width = std::max(0.f, std::min(width, 42.5f)); + m_lineRenderer->AddVertex(p1, particle.x34_color, width, {uvs.xMin, uvs.yMin}); + m_lineRenderer->AddVertex(p2, particle.x34_color, width, {uvs.xMax, uvs.yMax}); } + } - m_lineRenderer->Reset(); - - for (int i=0 ; iGetValueTexture(partFrame).GetObj(); - if (tex != cachedTex) - { - tex->Load(0, CTexture::EClampMode::One); - cachedTex = tex; - } - } - - if (!constUVs) - texr->GetValueUV(partFrame, uvs); - - zeus::CVector3f dVec = particle.x4_pos - particle.x10_prevPos; - if (x26d_24_FXLL) - if (dVec.magSquared() >= 0.f) - dVec.normalize(); - - zeus::CVector3f p1 = systemCameraMatrix * particle.x4_pos; - zeus::CVector3f p2 = systemCameraMatrix * (particle.x2c_lineLengthOrSize * dVec + particle.x4_pos); - - if (widtConst) - { - m_lineRenderer->AddVertex(p1, particle.x34_color, constWidth, {uvs.xMin, uvs.yMin}); - m_lineRenderer->AddVertex(p2, particle.x34_color, constWidth, {uvs.xMax, uvs.yMax}); - } - else if (widt) - { - float width = 1.f; - widt->GetValue(0, width); - width = std::max(0.f, std::min(width, 42.5f)); - m_lineRenderer->AddVertex(p1, particle.x34_color, width, {uvs.xMin, uvs.yMin}); - m_lineRenderer->AddVertex(p2, particle.x34_color, width, {uvs.xMax, uvs.yMax}); - } - } - - m_lineRenderer->Render(moduColor); + m_lineRenderer->Render(moduColor); } -void CElementGen::RenderParticles() -{ - CGenDescription* desc = x1c_genDesc.GetObj(); - CGlobalRandom gr(x27c_randState); +void CElementGen::RenderParticles() { + CGenDescription* desc = x1c_genDesc.GetObj(); + CGlobalRandom gr(x27c_randState); - CUVElement* texr = desc->x54_x40_TEXR.get(); - CUVElement* tind = desc->x58_x44_TIND.get(); - if (texr && tind) - { - RenderParticlesIndirectTexture(); + CUVElement* texr = desc->x54_x40_TEXR.get(); + CUVElement* tind = desc->x58_x44_TIND.get(); + if (texr && tind) { + RenderParticlesIndirectTexture(); + return; + } + + CRealElement* size = desc->x4c_x38_SIZE.get(); + if (size && size->IsConstant()) { + float sizeVal; + size->GetValue(0, sizeVal); + if (sizeVal == 0.f) { + size->GetValue(1, sizeVal); + if (sizeVal == 0.f) return; } + } - CRealElement* size = desc->x4c_x38_SIZE.get(); - if (size && size->IsConstant()) - { - float sizeVal; - size->GetValue(0, sizeVal); - if (sizeVal == 0.f) - { - size->GetValue(1, sizeVal); - if (sizeVal == 0.f) - return; - } + zeus::CTransform systemModelMatrix(CGraphics::g_ViewMatrix); + systemModelMatrix.origin.zeroOut(); + zeus::CTransform systemCameraMatrix = systemModelMatrix.inverse() * x22c_globalOrientation; + systemModelMatrix = + ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) * systemModelMatrix) * + x178_localScaleTransform; + if (x26c_29_ORNT) + CGraphics::SetModelMatrix(systemModelMatrix * systemCameraMatrix); + else + CGraphics::SetModelMatrix(systemModelMatrix); + + CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); + + SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; + bool constUVs = true; + CTexture* cachedTex = nullptr; + + SParticleUniforms uniformData = { + CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}}; + + if (texr) { + CParticle& target = x30_particles[0]; + int partFrame = x74_curFrame - target.x28_startFrame; + cachedTex = texr->GetValueTexture(partFrame).GetObj(); + cachedTex->Load(0, CTexture::EClampMode::One); + + if (x338_moduColor != zeus::CColor::skBlack) { + /* Add RASC * PREVC pass for MODU color loaded into channel mat-color */ + uniformData.moduColor = x338_moduColor; } - zeus::CTransform systemModelMatrix(CGraphics::g_ViewMatrix); - systemModelMatrix.origin.zeroOut(); - zeus::CTransform systemCameraMatrix = systemModelMatrix.inverse() * x22c_globalOrientation; - systemModelMatrix = ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) * - systemModelMatrix) * x178_localScaleTransform; - if (x26c_29_ORNT) - CGraphics::SetModelMatrix(systemModelMatrix * systemCameraMatrix); + texr->GetValueUV(partFrame, uvs); + constUVs = texr->HasConstantUV(); + } + + m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms)); + + std::vector sortItems; + if (desc->x44_28_x30_28_SORT) { + sortItems.reserve(x30_particles.size()); + + for (int i = 0; i < x30_particles.size(); ++i) { + const CParticle& particle = x30_particles[i]; + sortItems.emplace_back(i); + CParticleListItem& sortItem = sortItems.back(); + sortItem.x4_viewPoint = + systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos); + } + + std::sort(sortItems.begin(), sortItems.end(), [](const CParticleListItem& a, const CParticleListItem& b) -> bool { + return a.x4_viewPoint[1] > b.x4_viewPoint[1]; + }); + } + + bool moveRedToAlphaBuffer = false; + if (sMoveRedToAlphaBuffer && x26c_26_AAPH) + moveRedToAlphaBuffer = true; + + if (g_subtractBlend) { + if (moveRedToAlphaBuffer) + CGraphics::SetShaderDataBinding(m_redToAlphaSubDataBind); else - CGraphics::SetModelMatrix(systemModelMatrix); - - CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); - - SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; - bool constUVs = true; - CTexture* cachedTex = nullptr; - - SParticleUniforms uniformData = - { - CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), - {1.f, 1.f, 1.f, 1.f} - }; - - if (texr) - { - CParticle& target = x30_particles[0]; - int partFrame = x74_curFrame - target.x28_startFrame; - cachedTex = texr->GetValueTexture(partFrame).GetObj(); - cachedTex->Load(0, CTexture::EClampMode::One); - - if (x338_moduColor != zeus::CColor::skBlack) - { - /* Add RASC * PREVC pass for MODU color loaded into channel mat-color */ - uniformData.moduColor = x338_moduColor; - } - - texr->GetValueUV(partFrame, uvs); - constUVs = texr->HasConstantUV(); - } - - m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms)); - - std::vector sortItems; - if (desc->x44_28_x30_28_SORT) - { - sortItems.reserve(x30_particles.size()); - - for (int i=0 ; i bool - {return a.x4_viewPoint[1] > b.x4_viewPoint[1];}); - } - - bool moveRedToAlphaBuffer = false; - if (sMoveRedToAlphaBuffer && x26c_26_AAPH) - moveRedToAlphaBuffer = true; - - if (g_subtractBlend) - { - if (moveRedToAlphaBuffer) - CGraphics::SetShaderDataBinding(m_redToAlphaSubDataBind); - else - CGraphics::SetShaderDataBinding(m_normalSubDataBind); - } + CGraphics::SetShaderDataBinding(m_normalSubDataBind); + } else { + if (moveRedToAlphaBuffer) + CGraphics::SetShaderDataBinding(m_redToAlphaDataBind); else - { - if (moveRedToAlphaBuffer) - CGraphics::SetShaderDataBinding(m_redToAlphaDataBind); - else - CGraphics::SetShaderDataBinding(m_normalDataBind); - } + CGraphics::SetShaderDataBinding(m_normalDataBind); + } - int mbspVal = std::max(1, x270_MBSP); + int mbspVal = std::max(1, x270_MBSP); - CParticleGlobals::SetEmitterTime(x74_curFrame); - if (!x26c_30_MBLR) - { + CParticleGlobals::SetEmitterTime(x74_curFrame); + if (!x26c_30_MBLR) { #if 0 if (!desc->x44_28_x30_28_SORT && constUVs && !x26c_29_ORNT) { @@ -1447,730 +1275,626 @@ void CElementGen::RenderParticles() } #endif - switch (m_shaderClass) - { - case CElementGenShaders::EShaderClass::Tex: - g_instTexData.clear(); - g_instTexData.reserve(x30_particles.size()); - break; - case CElementGenShaders::EShaderClass::NoTex: - g_instNoTexData.clear(); - g_instNoTexData.reserve(x30_particles.size()); - break; - default: - Log.report(logvisor::Fatal, "unexpected particle shader class"); - break; - } - - if (!x26c_29_ORNT) - { - for (int i = 0; i < x30_particles.size(); ++i) - { - int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i; - CParticle& particle = x30_particles[partIdx]; - g_currentParticle = &particle; - - int partFrame = x74_curFrame - particle.x28_startFrame - 1; - zeus::CVector3f viewPoint; - if (desc->x44_28_x30_28_SORT) - viewPoint = sortItems[i].x4_viewPoint; - else - viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * - x80_timeDeltaScale + particle.x10_prevPos); - - if (!constUVs) - { - CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); - CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame); - texr->GetValueUV(partFrame, uvs); - } - - float size = 0.5f * particle.x2c_lineLengthOrSize; - if (0.f == particle.x30_lineWidthOrRota) - { - switch (m_shaderClass) - { - case CElementGenShaders::EShaderClass::Tex: - { - g_instTexData.emplace_back(); - SParticleInstanceTex& inst = g_instTexData.back(); - inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f}; - inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f}; - inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f}; - inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f}; - inst.color = particle.x34_color; - inst.uvs[0] = {uvs.xMax, uvs.yMax}; - inst.uvs[1] = {uvs.xMin, uvs.yMax}; - inst.uvs[2] = {uvs.xMax, uvs.yMin}; - inst.uvs[3] = {uvs.xMin, uvs.yMin}; - break; - } - case CElementGenShaders::EShaderClass::NoTex: - { - g_instNoTexData.emplace_back(); - SParticleInstanceNoTex& inst = g_instNoTexData.back(); - inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f}; - inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f}; - inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f}; - inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f}; - inst.color = particle.x34_color; - break; - } - default: - break; - } - } - else - { - float theta = zeus::degToRad(particle.x30_lineWidthOrRota); - float sinT = std::sin(theta) * size; - float cosT = std::cos(theta) * size; - - switch (m_shaderClass) - { - case CElementGenShaders::EShaderClass::Tex: - { - g_instTexData.emplace_back(); - SParticleInstanceTex& inst = g_instTexData.back(); - inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f}; - inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f}; - inst.pos[2] = zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), - 1.f}; - inst.pos[3] = zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), - 1.f}; - inst.color = particle.x34_color; - inst.uvs[0] = {uvs.xMax, uvs.yMax}; - inst.uvs[1] = {uvs.xMin, uvs.yMax}; - inst.uvs[2] = {uvs.xMax, uvs.yMin}; - inst.uvs[3] = {uvs.xMin, uvs.yMin}; - break; - } - case CElementGenShaders::EShaderClass::NoTex: - { - g_instNoTexData.emplace_back(); - SParticleInstanceNoTex& inst = g_instNoTexData.back(); - inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f}; - inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f}; - inst.pos[2] = zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), - 1.f}; - inst.pos[3] = zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), - 1.f}; - inst.color = particle.x34_color; - break; - } - default: - break; - } - } - } - } - else - { - for (int i = 0; i < x30_particles.size(); ++i) - { - int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i; - CParticle& particle = x30_particles[partIdx]; - g_currentParticle = &particle; - - int partFrame = x74_curFrame - particle.x28_startFrame - 1; - zeus::CVector3f viewPoint = ((particle.x4_pos - particle.x10_prevPos) * - x80_timeDeltaScale + particle.x10_prevPos); - float width = !desc->x50_x3c_ROTA ? 1.f : particle.x30_lineWidthOrRota; - zeus::CVector3f dir; - if (particle.x1c_vel.canBeNormalized()) - { - dir = particle.x1c_vel.normalized(); - } - else - { - zeus::CVector3f delta = particle.x4_pos - particle.x10_prevPos; - if (delta.canBeNormalized()) - dir = delta.normalized(); - else - dir = zeus::CVector3f::skUp; - } - - zeus::CVector3f foreVec = particle.x2c_lineLengthOrSize * dir; - zeus::CVector3f rightVec; - if (desc->x30_31_RSOP) - { - rightVec = dir.cross(CGraphics::g_ViewMatrix.basis[1]); - if (rightVec.canBeNormalized()) - { - rightVec = rightVec.normalized() * (particle.x2c_lineLengthOrSize * width); - } - else - { - rightVec = dir.cross((CGraphics::g_ViewMatrix.origin - particle.x4_pos).normalized()); - if (rightVec.canBeNormalized()) - { - rightVec = rightVec.normalized() * (particle.x2c_lineLengthOrSize * width); - } - } - } - else - { - rightVec = foreVec.cross(CGraphics::g_ViewMatrix.basis[1]) * width; - } - - if (!constUVs) - { - CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); - CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame); - texr->GetValueUV(partFrame, uvs); - } - - switch (m_shaderClass) - { - case CElementGenShaders::EShaderClass::Tex: - { - g_instTexData.emplace_back(); - SParticleInstanceTex& inst = g_instTexData.back(); - viewPoint += rightVec * 0.5f; - inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec}; - inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec}; - viewPoint -= rightVec; - inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec}; - inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec}; - inst.color = particle.x34_color; - inst.uvs[0] = {uvs.xMax, uvs.yMax}; - inst.uvs[1] = {uvs.xMin, uvs.yMax}; - inst.uvs[2] = {uvs.xMax, uvs.yMin}; - inst.uvs[3] = {uvs.xMin, uvs.yMin}; - break; - } - case CElementGenShaders::EShaderClass::NoTex: - { - g_instNoTexData.emplace_back(); - SParticleInstanceNoTex& inst = g_instNoTexData.back(); - viewPoint += rightVec * 0.5f; - inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec}; - inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec}; - viewPoint -= rightVec; - inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec}; - inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec}; - inst.color = particle.x34_color; - break; - } - default: - break; - } - } - } - - switch (m_shaderClass) - { - case CElementGenShaders::EShaderClass::Tex: - m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); - CGraphics::DrawInstances(0, 4, g_instTexData.size()); - break; - case CElementGenShaders::EShaderClass::NoTex: - m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); - CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); - break; - default: break; - } - } - else - { - switch (m_shaderClass) - { - case CElementGenShaders::EShaderClass::Tex: - g_instTexData.clear(); - g_instTexData.reserve(x30_particles.size() * mbspVal); - break; - case CElementGenShaders::EShaderClass::NoTex: - g_instNoTexData.clear(); - g_instNoTexData.reserve(x30_particles.size() * mbspVal); - break; - default: - Log.report(logvisor::Fatal, "unexpected particle shader class"); - break; - } - float mbspFac = 1.f / float(mbspVal); - for (int i=0 ; ix44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i; - CParticle& particle = x30_particles[partIdx]; - g_currentParticle = &particle; - - int partFrame = x74_curFrame - particle.x28_startFrame - 1; - - if (!constUVs) - { - CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); - CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame); - texr->GetValueUV(partFrame, uvs); - } - - zeus::CVector3f dVec = particle.x4_pos - particle.x10_prevPos; - zeus::CVector3f vec = dVec * x80_timeDeltaScale + particle.x10_prevPos; - zeus::CVector3f mbspVec = dVec * mbspFac; - float size = 0.5f * particle.x2c_lineLengthOrSize; - if (0.f == particle.x30_lineWidthOrRota) - { - for (int j=0 ; jload(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); - CGraphics::DrawInstances(0, 4, g_instTexData.size()); - break; - case CElementGenShaders::EShaderClass::NoTex: - m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); - CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); - break; - default: break; - } - } -} - -void CElementGen::RenderParticlesIndirectTexture() -{ - CGenDescription* desc = x1c_genDesc.GetObj(); - - zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix); - systemViewPointMatrix.origin.zeroOut(); - zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x22c_globalOrientation; - systemViewPointMatrix = ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) * systemViewPointMatrix) * x178_localScaleTransform; - CGraphics::SetModelMatrix(systemViewPointMatrix); - - SParticleUniforms uniformData = - { - CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), - {1.f, 1.f, 1.f, 1.f} - }; - m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms)); - - CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); - - if (x26c_26_AAPH) - { - CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true); - CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear); - } - else - { - CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, x26c_27_ZBUF); - CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear); + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: + g_instTexData.clear(); + g_instTexData.reserve(x30_particles.size()); + break; + case CElementGenShaders::EShaderClass::NoTex: + g_instNoTexData.clear(); + g_instNoTexData.reserve(x30_particles.size()); + break; + default: + Log.report(logvisor::Fatal, "unexpected particle shader class"); + break; } - CUVElement* texr = desc->x54_x40_TEXR.get(); - CParticle& firstParticle = x30_particles[0]; - int partFrame = x74_curFrame - firstParticle.x28_startFrame; - CTexture* cachedTex = texr->GetValueTexture(partFrame).GetObj(); - cachedTex->Load(0, CTexture::EClampMode::One); - - SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; - bool constTexr = texr->HasConstantTexture(); - texr->GetValueUV(partFrame, uvs); - bool constUVs = texr->HasConstantUV(); - - CUVElement* tind = desc->x58_x44_TIND.get(); - CTexture* cachedIndTex = tind->GetValueTexture(partFrame).GetObj(); - cachedIndTex->Load(2, CTexture::EClampMode::One); - - SUVElementSet uvsInd = {0.f, 0.f, 1.f, 1.f}; - bool constIndTexr = tind->HasConstantTexture(); - bool constIndUVs = tind->HasConstantUV(); - tind->GetValueUV(partFrame, uvsInd); - - std::vector sortItems; - if (desc->x44_28_x30_28_SORT) - { - sortItems.reserve(x30_particles.size()); - - for (int i=0 ; i bool - {return a.x4_viewPoint[1] >= b.x4_viewPoint[1];}); - } - - g_instIndTexData.clear(); - g_instIndTexData.reserve(x30_particles.size()); - - if (!x30_particles.empty()) - CGraphics::SetShaderDataBinding(m_normalDataBind); - - for (int i=0 ; ix44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i; CParticle& particle = x30_particles[partIdx]; g_currentParticle = &particle; - int partFrame = x74_curFrame - particle.x28_startFrame; + int partFrame = x74_curFrame - particle.x28_startFrame - 1; zeus::CVector3f viewPoint; if (desc->x44_28_x30_28_SORT) - viewPoint = sortItems[i].x4_viewPoint; + viewPoint = sortItems[i].x4_viewPoint; else - viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos); + viewPoint = systemCameraMatrix * + ((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos); - if (!constTexr) - { - CTexture* tex = texr->GetValueTexture(partFrame).GetObj(); - if (tex != cachedTex) - { - tex->Load(0, CTexture::EClampMode::One); - cachedTex = tex; - } + if (!constUVs) { + CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); + CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame); + texr->GetValueUV(partFrame, uvs); } - if (!constIndTexr) - { - CTexture* tex = tind->GetValueTexture(partFrame).GetObj(); - if (tex != cachedIndTex) - { - tex->Load(2, CTexture::EClampMode::One); - cachedIndTex = tex; - } - } - - if (!constUVs) - texr->GetValueUV(partFrame, uvs); - - if (!constIndUVs) - tind->GetValueUV(partFrame, uvsInd); - float size = 0.5f * particle.x2c_lineLengthOrSize; - zeus::CVector3f p1 = {viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size}; - zeus::CVector3f p2 = {viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size}; - SClipScreenRect clipRect = CGraphics::ClipScreenRectFromMS(p1, p2); - - if (!clipRect.x0_valid) - continue; - - CGraphics::ResolveSpareTexture(clipRect); - - g_instIndTexData.emplace_back(); - SParticleInstanceIndTex& inst = g_instIndTexData.back(); - inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f}; - inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f}; - inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f}; - inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f}; - inst.color = particle.x34_color; - inst.texrTindUVs[0] = zeus::CVector4f{uvs.xMax, uvs.yMax, uvsInd.xMax, uvsInd.yMax}; - inst.texrTindUVs[1] = zeus::CVector4f{uvs.xMin, uvs.yMax, uvsInd.xMin, uvsInd.yMax}; - inst.texrTindUVs[2] = zeus::CVector4f{uvs.xMax, uvs.yMin, uvsInd.xMax, uvsInd.yMin}; - inst.texrTindUVs[3] = zeus::CVector4f{uvs.xMin, uvs.yMin, uvsInd.xMin, uvsInd.yMin}; - switch (CGraphics::g_BooPlatform) - { - case boo::IGraphicsDataFactory::Platform::OpenGL: - inst.sceneUVs = zeus::CVector4f{clipRect.x18_uvXMin, clipRect.x24_uvYMax, clipRect.x1c_uvXMax, clipRect.x20_uvYMin}; + if (0.f == particle.x30_lineWidthOrRota) { + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: { + g_instTexData.emplace_back(); + SParticleInstanceTex& inst = g_instTexData.back(); + inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f}; + inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f}; + inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f}; + inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f}; + inst.color = particle.x34_color; + inst.uvs[0] = {uvs.xMax, uvs.yMax}; + inst.uvs[1] = {uvs.xMin, uvs.yMax}; + inst.uvs[2] = {uvs.xMax, uvs.yMin}; + inst.uvs[3] = {uvs.xMin, uvs.yMin}; break; - default: - inst.sceneUVs = zeus::CVector4f{clipRect.x18_uvXMin, 1.f - clipRect.x24_uvYMax, clipRect.x1c_uvXMax, 1.f - clipRect.x20_uvYMin}; + } + case CElementGenShaders::EShaderClass::NoTex: { + g_instNoTexData.emplace_back(); + SParticleInstanceNoTex& inst = g_instNoTexData.back(); + inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f}; + inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f}; + inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f}; + inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f}; + inst.color = particle.x34_color; break; + } + default: + break; + } + } else { + float theta = zeus::degToRad(particle.x30_lineWidthOrRota); + float sinT = std::sin(theta) * size; + float cosT = std::cos(theta) * size; + + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: { + g_instTexData.emplace_back(); + SParticleInstanceTex& inst = g_instTexData.back(); + inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f}; + inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f}; + inst.pos[2] = + zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f}; + inst.pos[3] = + zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f}; + inst.color = particle.x34_color; + inst.uvs[0] = {uvs.xMax, uvs.yMax}; + inst.uvs[1] = {uvs.xMin, uvs.yMax}; + inst.uvs[2] = {uvs.xMax, uvs.yMin}; + inst.uvs[3] = {uvs.xMin, uvs.yMin}; + break; + } + case CElementGenShaders::EShaderClass::NoTex: { + g_instNoTexData.emplace_back(); + SParticleInstanceNoTex& inst = g_instNoTexData.back(); + inst.pos[0] = zeus::CVector4f{viewPoint.x() + sinT + cosT, viewPoint.y(), viewPoint.z() + cosT - sinT, 1.f}; + inst.pos[1] = zeus::CVector4f{viewPoint.x() + sinT - cosT, viewPoint.y(), viewPoint.z() + sinT + cosT, 1.f}; + inst.pos[2] = + zeus::CVector4f{viewPoint.x() + (cosT - sinT), viewPoint.y(), viewPoint.z() + (-cosT - sinT), 1.f}; + inst.pos[3] = + zeus::CVector4f{viewPoint.x() - (sinT + cosT), viewPoint.y(), viewPoint.z() - (cosT - sinT), 1.f}; + inst.color = particle.x34_color; + break; + } + default: + break; + } } - CGraphics::DrawInstances(0, 4, 1, g_instIndTexData.size() - 1); - } + } + } else { + for (int i = 0; i < x30_particles.size(); ++i) { + int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i; + CParticle& particle = x30_particles[partIdx]; + g_currentParticle = &particle; - if (g_instIndTexData.size()) - { - m_instBuf->load(g_instIndTexData.data(), g_instIndTexData.size() * sizeof(SParticleInstanceIndTex)); - //CGraphics::SetShaderDataBinding(m_normalDataBind); - //CGraphics::DrawInstances(0, 4, g_instIndTexData.size()); - } -} - -void CElementGen::SetOrientation(const zeus::CTransform& orientation) -{ - x1d8_orientation = orientation; - x208_orientationInverse = x1d8_orientation.inverse(); - - for (const std::unique_ptr& ch : x290_activePartChildren) - ch->SetOrientation(orientation); -} - -void CElementGen::SetTranslation(const zeus::CVector3f& translation) -{ - xdc_translation = translation; - - for (const std::unique_ptr& ch : x290_activePartChildren) - { - switch (ch->Get4CharId()) - { - case SBIG('SELC'): - ch->SetTranslation(translation + x2c0_SEPO); - break; - case SBIG('SWHC'): - ch->SetTranslation(translation + x2b0_SSPO); - break; - default: - ch->SetTranslation(translation); - break; + int partFrame = x74_curFrame - particle.x28_startFrame - 1; + zeus::CVector3f viewPoint = + ((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos); + float width = !desc->x50_x3c_ROTA ? 1.f : particle.x30_lineWidthOrRota; + zeus::CVector3f dir; + if (particle.x1c_vel.canBeNormalized()) { + dir = particle.x1c_vel.normalized(); + } else { + zeus::CVector3f delta = particle.x4_pos - particle.x10_prevPos; + if (delta.canBeNormalized()) + dir = delta.normalized(); + else + dir = zeus::CVector3f::skUp; } + + zeus::CVector3f foreVec = particle.x2c_lineLengthOrSize * dir; + zeus::CVector3f rightVec; + if (desc->x30_31_RSOP) { + rightVec = dir.cross(CGraphics::g_ViewMatrix.basis[1]); + if (rightVec.canBeNormalized()) { + rightVec = rightVec.normalized() * (particle.x2c_lineLengthOrSize * width); + } else { + rightVec = dir.cross((CGraphics::g_ViewMatrix.origin - particle.x4_pos).normalized()); + if (rightVec.canBeNormalized()) { + rightVec = rightVec.normalized() * (particle.x2c_lineLengthOrSize * width); + } + } + } else { + rightVec = foreVec.cross(CGraphics::g_ViewMatrix.basis[1]) * width; + } + + if (!constUVs) { + CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); + CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame); + texr->GetValueUV(partFrame, uvs); + } + + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: { + g_instTexData.emplace_back(); + SParticleInstanceTex& inst = g_instTexData.back(); + viewPoint += rightVec * 0.5f; + inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec}; + inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec}; + viewPoint -= rightVec; + inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec}; + inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec}; + inst.color = particle.x34_color; + inst.uvs[0] = {uvs.xMax, uvs.yMax}; + inst.uvs[1] = {uvs.xMin, uvs.yMax}; + inst.uvs[2] = {uvs.xMax, uvs.yMin}; + inst.uvs[3] = {uvs.xMin, uvs.yMin}; + break; + } + case CElementGenShaders::EShaderClass::NoTex: { + g_instNoTexData.emplace_back(); + SParticleInstanceNoTex& inst = g_instNoTexData.back(); + viewPoint += rightVec * 0.5f; + inst.pos[0] = zeus::CVector4f{viewPoint + 0.5f * foreVec}; + inst.pos[1] = zeus::CVector4f{viewPoint - 0.5f * foreVec}; + viewPoint -= rightVec; + inst.pos[2] = zeus::CVector4f{viewPoint + 0.5f * foreVec}; + inst.pos[3] = zeus::CVector4f{viewPoint - 0.5f * foreVec}; + inst.color = particle.x34_color; + break; + } + default: + break; + } + } } -} -void CElementGen::SetGlobalOrientation(const zeus::CTransform& rotation) -{ - x22c_globalOrientation.setRotation(rotation); - - for (const std::unique_ptr& ch : x290_activePartChildren) - ch->SetGlobalOrientation(x22c_globalOrientation); -} - -void CElementGen::SetGlobalTranslation(const zeus::CVector3f& translation) -{ - xe8_globalTranslation = translation; - - for (const std::unique_ptr& ch : x290_activePartChildren) - ch->SetGlobalTranslation(translation); -} - -void CElementGen::SetGlobalScale(const zeus::CVector3f& scale) -{ - x100_globalScale = scale; - x10c_globalScaleTransform = zeus::CTransform::Scale(scale); - x13c_globalScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale); - - for (const std::unique_ptr& ch : x290_activePartChildren) - ch->SetGlobalScale(scale); -} - -void CElementGen::SetLocalScale(const zeus::CVector3f& scale) -{ - x16c_localScale = scale; - x178_localScaleTransform = zeus::CTransform::Scale(scale); - x1a8_localScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale); - - for (const std::unique_ptr& ch : x290_activePartChildren) - ch->SetLocalScale(scale); -} - -void CElementGen::SetGlobalOrientAndTrans(const zeus::CTransform& xf) -{ - SetGlobalOrientation(xf); - SetGlobalTranslation(xf.origin); -} - -void CElementGen::SetParticleEmission(bool enabled) -{ - x88_particleEmission = enabled; - - for (const std::unique_ptr& ch : x290_activePartChildren) - ch->SetParticleEmission(enabled); -} - -void CElementGen::SetModulationColor(const zeus::CColor& color) -{ - x338_moduColor = color; - - for (const std::unique_ptr& ch : x290_activePartChildren) - ch->SetModulationColor(color); -} - -void CElementGen::SetGeneratorRate(float rate) -{ - if (rate >= 0.0f) - x98_generatorRate = rate; - else - x98_generatorRate = 0.0f; - - for (std::unique_ptr& child : x290_activePartChildren) - { - if (child->Get4CharId() == FOURCC('PART')) - child->SetGeneratorRate(x98_generatorRate); - } -} - -const zeus::CTransform& CElementGen::GetOrientation() const -{ - return x1d8_orientation; -} - -const zeus::CVector3f& CElementGen::GetTranslation() const -{ - return xdc_translation; -} - -const zeus::CTransform& CElementGen::GetGlobalOrientation() const -{ - return x22c_globalOrientation; -} - -const zeus::CVector3f& CElementGen::GetGlobalTranslation() const -{ - return xe8_globalTranslation; -} - -const zeus::CVector3f& CElementGen::GetGlobalScale() const -{ - return x100_globalScale; -} - -const zeus::CColor& CElementGen::GetModulationColor() const -{ - return x338_moduColor; -} - -bool CElementGen::IsSystemDeletable() const -{ - for (const std::unique_ptr& ch : x290_activePartChildren) - if (!ch->IsSystemDeletable()) - return false; - - if (x268_PSLT < x74_curFrame && x25c_activeParticleCount == 0) - return true; - - return false; -} - -std::experimental::optional CElementGen::GetBounds() const -{ - if (GetParticleCountAll() == 0) - return std::experimental::nullopt; - else - return {x2f0_systemBounds}; -} - -u32 CElementGen::GetParticleCount() const -{ - return x25c_activeParticleCount; -} - -bool CElementGen::SystemHasLight() const -{ - return x308_lightType != LightType::None; -} - -CLight CElementGen::GetLight() const -{ - switch (x308_lightType) - { - case LightType::Directional: - return CLight::BuildDirectional(x320_LDIR.normalized(), x30c_LCLR * x310_LINT); - case LightType::Spot: - return CLight::BuildSpot(x314_LOFF, x320_LDIR.normalized(), x30c_LCLR * x310_LINT, x334_LSLA); + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: + m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); + CGraphics::DrawInstances(0, 4, g_instTexData.size()); + break; + case CElementGenShaders::EShaderClass::NoTex: + m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); + CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); + break; default: - { - float quad = x32c_falloffType == EFalloffType::Quadratic ? x330_LFOR : 0.f; - float linear = x32c_falloffType == EFalloffType::Linear ? x330_LFOR : 0.f; - float constant = x32c_falloffType == EFalloffType::Constant ? 1.f : 0.f; - return CLight::BuildCustom(x314_LOFF, {1.f, 0.f, 0.f}, x30c_LCLR, - constant, linear, quad, x310_LINT, 0.f, 0.f); + break; } + } else { + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: + g_instTexData.clear(); + g_instTexData.reserve(x30_particles.size() * mbspVal); + break; + case CElementGenShaders::EShaderClass::NoTex: + g_instNoTexData.clear(); + g_instNoTexData.reserve(x30_particles.size() * mbspVal); + break; + default: + Log.report(logvisor::Fatal, "unexpected particle shader class"); + break; } + float mbspFac = 1.f / float(mbspVal); + for (int i = 0; i < x30_particles.size(); ++i) { + int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i; + CParticle& particle = x30_particles[partIdx]; + g_currentParticle = &particle; + + int partFrame = x74_curFrame - particle.x28_startFrame - 1; + + if (!constUVs) { + CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame); + CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame); + texr->GetValueUV(partFrame, uvs); + } + + zeus::CVector3f dVec = particle.x4_pos - particle.x10_prevPos; + zeus::CVector3f vec = dVec * x80_timeDeltaScale + particle.x10_prevPos; + zeus::CVector3f mbspVec = dVec * mbspFac; + float size = 0.5f * particle.x2c_lineLengthOrSize; + if (0.f == particle.x30_lineWidthOrRota) { + for (int j = 0; j < mbspVal; ++j) { + vec += mbspVec; + zeus::CVector3f vec2 = systemCameraMatrix * vec; + + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: { + g_instTexData.emplace_back(); + SParticleInstanceTex& inst = g_instTexData.back(); + inst.pos[0] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() + size, 1.f}; + inst.pos[1] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() + size, 1.f}; + inst.pos[2] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() - size, 1.f}; + inst.pos[3] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() - size, 1.f}; + inst.color = particle.x34_color; + inst.uvs[0] = {uvs.xMax, uvs.yMax}; + inst.uvs[1] = {uvs.xMin, uvs.yMax}; + inst.uvs[2] = {uvs.xMax, uvs.yMin}; + inst.uvs[3] = {uvs.xMin, uvs.yMin}; + break; + } + case CElementGenShaders::EShaderClass::NoTex: { + g_instNoTexData.emplace_back(); + SParticleInstanceNoTex& inst = g_instNoTexData.back(); + inst.pos[0] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() + size, 1.f}; + inst.pos[1] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() + size, 1.f}; + inst.pos[2] = zeus::CVector4f{vec2.x() + size, vec2.y(), vec2.z() - size, 1.f}; + inst.pos[3] = zeus::CVector4f{vec2.x() - size, vec2.y(), vec2.z() - size, 1.f}; + inst.color = particle.x34_color; + break; + } + default: + break; + } + } + } else { + float theta = zeus::degToRad(particle.x30_lineWidthOrRota); + float sinT = std::sin(theta) * size; + float cosT = std::cos(theta) * size; + + for (int j = 0; j < mbspVal; ++j) { + vec += mbspVec; + zeus::CVector3f vec2 = systemCameraMatrix * vec; + + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: { + g_instTexData.emplace_back(); + SParticleInstanceTex& inst = g_instTexData.back(); + inst.pos[0] = zeus::CVector4f{vec2.x() + sinT + cosT, vec2.y(), vec2.z() + cosT - sinT, 1.f}; + inst.pos[1] = zeus::CVector4f{vec2.x() + sinT - cosT, vec2.y(), vec2.z() + sinT + cosT, 1.f}; + inst.pos[2] = zeus::CVector4f{vec2.x() + (cosT - sinT), vec2.y(), vec2.z() + (-cosT - sinT), 1.f}; + inst.pos[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f}; + inst.color = particle.x34_color; + inst.uvs[0] = {uvs.xMax, uvs.yMax}; + inst.uvs[1] = {uvs.xMin, uvs.yMax}; + inst.uvs[2] = {uvs.xMax, uvs.yMin}; + inst.uvs[3] = {uvs.xMin, uvs.yMin}; + break; + } + case CElementGenShaders::EShaderClass::NoTex: { + g_instNoTexData.emplace_back(); + SParticleInstanceNoTex& inst = g_instNoTexData.back(); + inst.pos[0] = zeus::CVector4f{vec2.x() + sinT + cosT, vec2.y(), vec2.z() + cosT - sinT, 1.f}; + inst.pos[1] = zeus::CVector4f{vec2.x() + sinT - cosT, vec2.y(), vec2.z() + sinT + cosT, 1.f}; + inst.pos[2] = zeus::CVector4f{vec2.x() + (cosT - sinT), vec2.y(), vec2.z() + (-cosT - sinT), 1.f}; + inst.pos[3] = zeus::CVector4f{vec2.x() - (sinT + cosT), vec2.y(), vec2.z() - (cosT - sinT), 1.f}; + inst.color = particle.x34_color; + break; + } + default: + break; + } + } + } + } + switch (m_shaderClass) { + case CElementGenShaders::EShaderClass::Tex: + m_instBuf->load(g_instTexData.data(), g_instTexData.size() * sizeof(SParticleInstanceTex)); + CGraphics::DrawInstances(0, 4, g_instTexData.size()); + break; + case CElementGenShaders::EShaderClass::NoTex: + m_instBuf->load(g_instNoTexData.data(), g_instNoTexData.size() * sizeof(SParticleInstanceNoTex)); + CGraphics::DrawInstances(0, 4, g_instNoTexData.size()); + break; + default: + break; + } + } } -bool CElementGen::GetParticleEmission() const -{ - return x88_particleEmission; +void CElementGen::RenderParticlesIndirectTexture() { + CGenDescription* desc = x1c_genDesc.GetObj(); + + zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix); + systemViewPointMatrix.origin.zeroOut(); + zeus::CTransform systemCameraMatrix = systemViewPointMatrix.inverse() * x22c_globalOrientation; + systemViewPointMatrix = + ((zeus::CTransform::Translate(xe8_globalTranslation) * x10c_globalScaleTransform) * systemViewPointMatrix) * + x178_localScaleTransform; + CGraphics::SetModelMatrix(systemViewPointMatrix); + + SParticleUniforms uniformData = { + CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(), {1.f, 1.f, 1.f, 1.f}}; + m_uniformBuf->load(&uniformData, sizeof(SParticleUniforms)); + + CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0); + + if (x26c_26_AAPH) { + CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true); + CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear); + } else { + CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, x26c_27_ZBUF); + CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, + ERglLogicOp::Clear); + } + + CUVElement* texr = desc->x54_x40_TEXR.get(); + CParticle& firstParticle = x30_particles[0]; + int partFrame = x74_curFrame - firstParticle.x28_startFrame; + CTexture* cachedTex = texr->GetValueTexture(partFrame).GetObj(); + cachedTex->Load(0, CTexture::EClampMode::One); + + SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; + bool constTexr = texr->HasConstantTexture(); + texr->GetValueUV(partFrame, uvs); + bool constUVs = texr->HasConstantUV(); + + CUVElement* tind = desc->x58_x44_TIND.get(); + CTexture* cachedIndTex = tind->GetValueTexture(partFrame).GetObj(); + cachedIndTex->Load(2, CTexture::EClampMode::One); + + SUVElementSet uvsInd = {0.f, 0.f, 1.f, 1.f}; + bool constIndTexr = tind->HasConstantTexture(); + bool constIndUVs = tind->HasConstantUV(); + tind->GetValueUV(partFrame, uvsInd); + + std::vector sortItems; + if (desc->x44_28_x30_28_SORT) { + sortItems.reserve(x30_particles.size()); + + for (int i = 0; i < x30_particles.size(); ++i) { + const CParticle& particle = x30_particles[i]; + sortItems.emplace_back(i); + CParticleListItem& sortItem = sortItems.back(); + sortItem.x4_viewPoint = + systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos); + } + + std::sort(sortItems.begin(), sortItems.end(), [](const CParticleListItem& a, const CParticleListItem& b) -> bool { + return a.x4_viewPoint[1] >= b.x4_viewPoint[1]; + }); + } + + g_instIndTexData.clear(); + g_instIndTexData.reserve(x30_particles.size()); + + if (!x30_particles.empty()) + CGraphics::SetShaderDataBinding(m_normalDataBind); + + for (int i = 0; i < x30_particles.size(); ++i) { + int partIdx = desc->x44_28_x30_28_SORT ? sortItems[i].x0_partIdx : i; + CParticle& particle = x30_particles[partIdx]; + g_currentParticle = &particle; + + int partFrame = x74_curFrame - particle.x28_startFrame; + zeus::CVector3f viewPoint; + if (desc->x44_28_x30_28_SORT) + viewPoint = sortItems[i].x4_viewPoint; + else + viewPoint = + systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x80_timeDeltaScale + particle.x10_prevPos); + + if (!constTexr) { + CTexture* tex = texr->GetValueTexture(partFrame).GetObj(); + if (tex != cachedTex) { + tex->Load(0, CTexture::EClampMode::One); + cachedTex = tex; + } + } + + if (!constIndTexr) { + CTexture* tex = tind->GetValueTexture(partFrame).GetObj(); + if (tex != cachedIndTex) { + tex->Load(2, CTexture::EClampMode::One); + cachedIndTex = tex; + } + } + + if (!constUVs) + texr->GetValueUV(partFrame, uvs); + + if (!constIndUVs) + tind->GetValueUV(partFrame, uvsInd); + + float size = 0.5f * particle.x2c_lineLengthOrSize; + zeus::CVector3f p1 = {viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size}; + zeus::CVector3f p2 = {viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size}; + SClipScreenRect clipRect = CGraphics::ClipScreenRectFromMS(p1, p2); + + if (!clipRect.x0_valid) + continue; + + CGraphics::ResolveSpareTexture(clipRect); + + g_instIndTexData.emplace_back(); + SParticleInstanceIndTex& inst = g_instIndTexData.back(); + inst.pos[0] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() + size, 1.f}; + inst.pos[1] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() + size, 1.f}; + inst.pos[2] = zeus::CVector4f{viewPoint.x() + size, viewPoint.y(), viewPoint.z() - size, 1.f}; + inst.pos[3] = zeus::CVector4f{viewPoint.x() - size, viewPoint.y(), viewPoint.z() - size, 1.f}; + inst.color = particle.x34_color; + inst.texrTindUVs[0] = zeus::CVector4f{uvs.xMax, uvs.yMax, uvsInd.xMax, uvsInd.yMax}; + inst.texrTindUVs[1] = zeus::CVector4f{uvs.xMin, uvs.yMax, uvsInd.xMin, uvsInd.yMax}; + inst.texrTindUVs[2] = zeus::CVector4f{uvs.xMax, uvs.yMin, uvsInd.xMax, uvsInd.yMin}; + inst.texrTindUVs[3] = zeus::CVector4f{uvs.xMin, uvs.yMin, uvsInd.xMin, uvsInd.yMin}; + switch (CGraphics::g_BooPlatform) { + case boo::IGraphicsDataFactory::Platform::OpenGL: + inst.sceneUVs = + zeus::CVector4f{clipRect.x18_uvXMin, clipRect.x24_uvYMax, clipRect.x1c_uvXMax, clipRect.x20_uvYMin}; + break; + default: + inst.sceneUVs = zeus::CVector4f{clipRect.x18_uvXMin, 1.f - clipRect.x24_uvYMax, clipRect.x1c_uvXMax, + 1.f - clipRect.x20_uvYMin}; + break; + } + CGraphics::DrawInstances(0, 4, 1, g_instIndTexData.size() - 1); + } + + if (g_instIndTexData.size()) { + m_instBuf->load(g_instIndTexData.data(), g_instIndTexData.size() * sizeof(SParticleInstanceIndTex)); + // CGraphics::SetShaderDataBinding(m_normalDataBind); + // CGraphics::DrawInstances(0, 4, g_instIndTexData.size()); + } } -void CElementGen::DestroyParticles() -{ - g_ParticleAliveCount -= x30_particles.size(); - x30_particles.clear(); - x50_parentMatrices.clear(); +void CElementGen::SetOrientation(const zeus::CTransform& orientation) { + x1d8_orientation = orientation; + x208_orientationInverse = x1d8_orientation.inverse(); - for (const std::unique_ptr& ch : x290_activePartChildren) - ch->DestroyParticles(); + for (const std::unique_ptr& ch : x290_activePartChildren) + ch->SetOrientation(orientation); } -void CElementGen::Reset() -{ - x30_particles.clear(); - x50_parentMatrices.clear(); - x290_activePartChildren.clear(); +void CElementGen::SetTranslation(const zeus::CVector3f& translation) { + xdc_translation = translation; - x74_curFrame = 0; - x78_curSeconds = 0.f; - x84_prevFrame = -1; - x25c_activeParticleCount = 0; - x26d_25_warmedUp = false; + for (const std::unique_ptr& ch : x290_activePartChildren) { + switch (ch->Get4CharId()) { + case SBIG('SELC'): + ch->SetTranslation(translation + x2c0_SEPO); + break; + case SBIG('SWHC'): + ch->SetTranslation(translation + x2b0_SSPO); + break; + default: + ch->SetTranslation(translation); + break; + } + } } -void CElementGen::SetMoveRedToAlphaBuffer(bool move) -{ - sMoveRedToAlphaBuffer = move; +void CElementGen::SetGlobalOrientation(const zeus::CTransform& rotation) { + x22c_globalOrientation.setRotation(rotation); + + for (const std::unique_ptr& ch : x290_activePartChildren) + ch->SetGlobalOrientation(x22c_globalOrientation); } +void CElementGen::SetGlobalTranslation(const zeus::CVector3f& translation) { + xe8_globalTranslation = translation; + + for (const std::unique_ptr& ch : x290_activePartChildren) + ch->SetGlobalTranslation(translation); } + +void CElementGen::SetGlobalScale(const zeus::CVector3f& scale) { + x100_globalScale = scale; + x10c_globalScaleTransform = zeus::CTransform::Scale(scale); + x13c_globalScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale); + + for (const std::unique_ptr& ch : x290_activePartChildren) + ch->SetGlobalScale(scale); +} + +void CElementGen::SetLocalScale(const zeus::CVector3f& scale) { + x16c_localScale = scale; + x178_localScaleTransform = zeus::CTransform::Scale(scale); + x1a8_localScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale); + + for (const std::unique_ptr& ch : x290_activePartChildren) + ch->SetLocalScale(scale); +} + +void CElementGen::SetGlobalOrientAndTrans(const zeus::CTransform& xf) { + SetGlobalOrientation(xf); + SetGlobalTranslation(xf.origin); +} + +void CElementGen::SetParticleEmission(bool enabled) { + x88_particleEmission = enabled; + + for (const std::unique_ptr& ch : x290_activePartChildren) + ch->SetParticleEmission(enabled); +} + +void CElementGen::SetModulationColor(const zeus::CColor& color) { + x338_moduColor = color; + + for (const std::unique_ptr& ch : x290_activePartChildren) + ch->SetModulationColor(color); +} + +void CElementGen::SetGeneratorRate(float rate) { + if (rate >= 0.0f) + x98_generatorRate = rate; + else + x98_generatorRate = 0.0f; + + for (std::unique_ptr& child : x290_activePartChildren) { + if (child->Get4CharId() == FOURCC('PART')) + child->SetGeneratorRate(x98_generatorRate); + } +} + +const zeus::CTransform& CElementGen::GetOrientation() const { return x1d8_orientation; } + +const zeus::CVector3f& CElementGen::GetTranslation() const { return xdc_translation; } + +const zeus::CTransform& CElementGen::GetGlobalOrientation() const { return x22c_globalOrientation; } + +const zeus::CVector3f& CElementGen::GetGlobalTranslation() const { return xe8_globalTranslation; } + +const zeus::CVector3f& CElementGen::GetGlobalScale() const { return x100_globalScale; } + +const zeus::CColor& CElementGen::GetModulationColor() const { return x338_moduColor; } + +bool CElementGen::IsSystemDeletable() const { + for (const std::unique_ptr& ch : x290_activePartChildren) + if (!ch->IsSystemDeletable()) + return false; + + if (x268_PSLT < x74_curFrame && x25c_activeParticleCount == 0) + return true; + + return false; +} + +std::experimental::optional CElementGen::GetBounds() const { + if (GetParticleCountAll() == 0) + return std::experimental::nullopt; + else + return {x2f0_systemBounds}; +} + +u32 CElementGen::GetParticleCount() const { return x25c_activeParticleCount; } + +bool CElementGen::SystemHasLight() const { return x308_lightType != LightType::None; } + +CLight CElementGen::GetLight() const { + switch (x308_lightType) { + case LightType::Directional: + return CLight::BuildDirectional(x320_LDIR.normalized(), x30c_LCLR * x310_LINT); + case LightType::Spot: + return CLight::BuildSpot(x314_LOFF, x320_LDIR.normalized(), x30c_LCLR * x310_LINT, x334_LSLA); + default: { + float quad = x32c_falloffType == EFalloffType::Quadratic ? x330_LFOR : 0.f; + float linear = x32c_falloffType == EFalloffType::Linear ? x330_LFOR : 0.f; + float constant = x32c_falloffType == EFalloffType::Constant ? 1.f : 0.f; + return CLight::BuildCustom(x314_LOFF, {1.f, 0.f, 0.f}, x30c_LCLR, constant, linear, quad, x310_LINT, 0.f, 0.f); + } + } +} + +bool CElementGen::GetParticleEmission() const { return x88_particleEmission; } + +void CElementGen::DestroyParticles() { + g_ParticleAliveCount -= x30_particles.size(); + x30_particles.clear(); + x50_parentMatrices.clear(); + + for (const std::unique_ptr& ch : x290_activePartChildren) + ch->DestroyParticles(); +} + +void CElementGen::Reset() { + x30_particles.clear(); + x50_parentMatrices.clear(); + x290_activePartChildren.clear(); + + x74_curFrame = 0; + x78_curSeconds = 0.f; + x84_prevFrame = -1; + x25c_activeParticleCount = 0; + x26d_25_warmedUp = false; +} + +void CElementGen::SetMoveRedToAlphaBuffer(bool move) { sMoveRedToAlphaBuffer = move; } + +} // namespace urde diff --git a/Runtime/Particle/CElementGen.hpp b/Runtime/Particle/CElementGen.hpp index 684c0ed8a..98a8c29dc 100644 --- a/Runtime/Particle/CElementGen.hpp +++ b/Runtime/Particle/CElementGen.hpp @@ -14,8 +14,7 @@ #include "Graphics/CLineRenderer.hpp" #include "Particle/CGenDescription.hpp" -namespace urde -{ +namespace urde { class CWarp; class CLight; class IGenDescription; @@ -24,229 +23,210 @@ class CParticleSwoosh; class CParticleElectric; class CActorLights; -class CElementGen : public CParticleGen -{ - static u16 g_GlobalSeed; - static bool g_subtractBlend; +class CElementGen : public CParticleGen { + static u16 g_GlobalSeed; + static bool g_subtractBlend; + public: - static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; } - static void SetSubtractBlend(bool s) { g_subtractBlend = s; } - enum class EModelOrientationType - { - Normal, - One - }; - enum class EOptionalSystemFlags - { - None, - One, - Two - }; - enum class LightType - { - None = 0, - Custom = 1, - Directional = 2, - Spot = 3 - }; - class CParticleListItem - { - friend class CElementGen; - s16 x0_partIdx; - zeus::CVector3f x4_viewPoint; - public: - CParticleListItem(s16 idx) - : x0_partIdx(idx) {} - }; - static CParticle* g_currentParticle; + static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; } + static void SetSubtractBlend(bool s) { g_subtractBlend = s; } + enum class EModelOrientationType { Normal, One }; + enum class EOptionalSystemFlags { None, One, Two }; + enum class LightType { None = 0, Custom = 1, Directional = 2, Spot = 3 }; + class CParticleListItem { + friend class CElementGen; + s16 x0_partIdx; + zeus::CVector3f x4_viewPoint; + + public: + CParticleListItem(s16 idx) : x0_partIdx(idx) {} + }; + static CParticle* g_currentParticle; + private: - friend class CElementGenShaders; - TLockedToken x1c_genDesc; - CGenDescription* x28_loadedGenDesc; - EModelOrientationType x2c_orientType; - std::vector x30_particles; - std::vector x40; - std::vector x50_parentMatrices; - std::vector> x60_advValues; + friend class CElementGenShaders; + TLockedToken x1c_genDesc; + CGenDescription* x28_loadedGenDesc; + EModelOrientationType x2c_orientType; + std::vector x30_particles; + std::vector x40; + std::vector x50_parentMatrices; + std::vector> x60_advValues; - int x70_internalStartFrame = 0; - int x74_curFrame = 0; - double x78_curSeconds = 0.f; - float x80_timeDeltaScale; - int x84_prevFrame = -1; - bool x88_particleEmission = true; - float x8c_generatorRemainder = 0.f; - int x90_MAXP = 0; - int m_maxMAXP = 256; - u16 x94_randomSeed = 99; - float x98_generatorRate = 1.f; - float x9c_cextValues[16] = {}; + int x70_internalStartFrame = 0; + int x74_curFrame = 0; + double x78_curSeconds = 0.f; + float x80_timeDeltaScale; + int x84_prevFrame = -1; + bool x88_particleEmission = true; + float x8c_generatorRemainder = 0.f; + int x90_MAXP = 0; + int m_maxMAXP = 256; + u16 x94_randomSeed = 99; + float x98_generatorRate = 1.f; + float x9c_cextValues[16] = {}; - zeus::CVector3f xdc_translation; - zeus::CVector3f xe8_globalTranslation; - zeus::CVector3f xf4_POFS; - zeus::CVector3f x100_globalScale = {1.f, 1.f, 1.f}; - zeus::CTransform x10c_globalScaleTransform = zeus::CTransform::Identity(); - zeus::CTransform x13c_globalScaleTransformInverse = zeus::CTransform::Identity(); - zeus::CVector3f x16c_localScale = {1.f, 1.f, 1.f}; - zeus::CTransform x178_localScaleTransform = zeus::CTransform::Identity(); - zeus::CTransform x1a8_localScaleTransformInverse = zeus::CTransform::Identity(); - zeus::CTransform x1d8_orientation = zeus::CTransform::Identity(); - zeus::CTransform x208_orientationInverse = zeus::CTransform::Identity(); - zeus::CTransform x22c_globalOrientation = zeus::CTransform::Identity(); + zeus::CVector3f xdc_translation; + zeus::CVector3f xe8_globalTranslation; + zeus::CVector3f xf4_POFS; + zeus::CVector3f x100_globalScale = {1.f, 1.f, 1.f}; + zeus::CTransform x10c_globalScaleTransform = zeus::CTransform::Identity(); + zeus::CTransform x13c_globalScaleTransformInverse = zeus::CTransform::Identity(); + zeus::CVector3f x16c_localScale = {1.f, 1.f, 1.f}; + zeus::CTransform x178_localScaleTransform = zeus::CTransform::Identity(); + zeus::CTransform x1a8_localScaleTransformInverse = zeus::CTransform::Identity(); + zeus::CTransform x1d8_orientation = zeus::CTransform::Identity(); + zeus::CTransform x208_orientationInverse = zeus::CTransform::Identity(); + zeus::CTransform x22c_globalOrientation = zeus::CTransform::Identity(); - u32 x25c_activeParticleCount = 0; - u32 x260_cumulativeParticles = 0; - u32 x264_recursiveParticleCount = 0; - int x268_PSLT; + u32 x25c_activeParticleCount = 0; + u32 x260_cumulativeParticles = 0; + u32 x264_recursiveParticleCount = 0; + int x268_PSLT; - union - { - struct - { - bool x26c_24_translationDirty : 1; - bool x26c_25_LIT_ : 1; - bool x26c_26_AAPH : 1; - bool x26c_27_ZBUF : 1; - bool x26c_28_zTest : 1; - bool x26c_29_ORNT : 1; - bool x26c_30_MBLR : 1; - bool x26c_31_LINE : 1; - bool x26d_24_FXLL : 1; - bool x26d_25_warmedUp : 1; - bool x26d_26_modelsUseLights : 1; - bool x26d_27_enableOPTS : 1; - bool x26d_28_enableADV : 1; - }; - u32 _dummy = 0; + union { + struct { + bool x26c_24_translationDirty : 1; + bool x26c_25_LIT_ : 1; + bool x26c_26_AAPH : 1; + bool x26c_27_ZBUF : 1; + bool x26c_28_zTest : 1; + bool x26c_29_ORNT : 1; + bool x26c_30_MBLR : 1; + bool x26c_31_LINE : 1; + bool x26d_24_FXLL : 1; + bool x26d_25_warmedUp : 1; + bool x26d_26_modelsUseLights : 1; + bool x26d_27_enableOPTS : 1; + bool x26d_28_enableADV : 1; }; + u32 _dummy = 0; + }; - int x270_MBSP = 0; - int m_maxMBSP = 0; - ERglLightBits x274_backupLightActive = ERglLightBits::None; - bool x278_hasVMD[4] = {}; - CRandom16 x27c_randState; - CModVectorElement* x280_VELSources[4] = {}; + int x270_MBSP = 0; + int m_maxMBSP = 0; + ERglLightBits x274_backupLightActive = ERglLightBits::None; + bool x278_hasVMD[4] = {}; + CRandom16 x27c_randState; + CModVectorElement* x280_VELSources[4] = {}; - std::vector> x290_activePartChildren; - int x2a0_CSSD = 0; - int x2a4_SISY = 16; - int x2a8_PISY = 16; - int x2ac_SSSD = 0; - zeus::CVector3f x2b0_SSPO; - int x2bc_SESD = 0; - zeus::CVector3f x2c0_SEPO; - float x2cc = 0.f; - float x2d0 = 0.f; - zeus::CVector3f x2d4_aabbMin; - zeus::CVector3f x2e0_aabbMax; - float x2ec_maxSize = 0.f; - zeus::CAABox x2f0_systemBounds = zeus::CAABox::skInvertedBox; - LightType x308_lightType; - zeus::CColor x30c_LCLR = zeus::CColor::skWhite; - float x310_LINT = 1.f; - zeus::CVector3f x314_LOFF; - zeus::CVector3f x320_LDIR = {1.f, 0.f, 0.f}; - EFalloffType x32c_falloffType = EFalloffType::Linear; - float x330_LFOR = 1.f; - float x334_LSLA = 45.f; - zeus::CColor x338_moduColor = {1.f, 1.f, 1.f, 1.f}; + std::vector> x290_activePartChildren; + int x2a0_CSSD = 0; + int x2a4_SISY = 16; + int x2a8_PISY = 16; + int x2ac_SSSD = 0; + zeus::CVector3f x2b0_SSPO; + int x2bc_SESD = 0; + zeus::CVector3f x2c0_SEPO; + float x2cc = 0.f; + float x2d0 = 0.f; + zeus::CVector3f x2d4_aabbMin; + zeus::CVector3f x2e0_aabbMax; + float x2ec_maxSize = 0.f; + zeus::CAABox x2f0_systemBounds = zeus::CAABox::skInvertedBox; + LightType x308_lightType; + zeus::CColor x30c_LCLR = zeus::CColor::skWhite; + float x310_LINT = 1.f; + zeus::CVector3f x314_LOFF; + zeus::CVector3f x320_LDIR = {1.f, 0.f, 0.f}; + EFalloffType x32c_falloffType = EFalloffType::Linear; + float x330_LFOR = 1.f; + float x334_LSLA = 45.f; + zeus::CColor x338_moduColor = {1.f, 1.f, 1.f, 1.f}; - std::unique_ptr m_lineRenderer; - CElementGenShaders::EShaderClass m_shaderClass; + std::unique_ptr m_lineRenderer; + CElementGenShaders::EShaderClass m_shaderClass; - void AccumulateBounds(const zeus::CVector3f& pos, float size); + void AccumulateBounds(const zeus::CVector3f& pos, float size); public: - CElementGen(const TToken& gen, - EModelOrientationType orientType = EModelOrientationType::Normal, - EOptionalSystemFlags flags = EOptionalSystemFlags::One); - ~CElementGen(); + CElementGen(const TToken& gen, EModelOrientationType orientType = EModelOrientationType::Normal, + EOptionalSystemFlags flags = EOptionalSystemFlags::One); + ~CElementGen(); - boo::ObjToken m_normalDataBind; - boo::ObjToken m_normalSubDataBind; - boo::ObjToken m_redToAlphaDataBind; - boo::ObjToken m_redToAlphaSubDataBind; - boo::ObjToken m_instBuf; - boo::ObjToken m_uniformBuf; + boo::ObjToken m_normalDataBind; + boo::ObjToken m_normalSubDataBind; + boo::ObjToken m_redToAlphaDataBind; + boo::ObjToken m_redToAlphaSubDataBind; + boo::ObjToken m_instBuf; + boo::ObjToken m_uniformBuf; - boo::ObjToken m_normalDataBindPmus; - boo::ObjToken m_redToAlphaDataBindPmus; - boo::ObjToken m_instBufPmus; - boo::ObjToken m_uniformBufPmus; + boo::ObjToken m_normalDataBindPmus; + boo::ObjToken m_redToAlphaDataBindPmus; + boo::ObjToken m_instBufPmus; + boo::ObjToken m_uniformBufPmus; - CGenDescription* GetDesc() {return x1c_genDesc.GetObj();} - const SObjectTag* GetDescTag() const {return x1c_genDesc.GetObjectTag();} + CGenDescription* GetDesc() { return x1c_genDesc.GetObj(); } + const SObjectTag* GetDescTag() const { return x1c_genDesc.GetObjectTag(); } - static bool g_ParticleSystemInitialized; - static int g_ParticleAliveCount; - static int g_ParticleSystemAliveCount; - static bool sMoveRedToAlphaBuffer; - static void Initialize(); - static void Shutdown(); + static bool g_ParticleSystemInitialized; + static int g_ParticleAliveCount; + static int g_ParticleSystemAliveCount; + static bool sMoveRedToAlphaBuffer; + static void Initialize(); + static void Shutdown(); - void UpdateAdvanceAccessParameters(u32 activeParticleCount, u32 particleFrame); - bool UpdateVelocitySource(u32 idx, u32 particleFrame, CParticle& particle); - void UpdateExistingParticles(); - void CreateNewParticles(int); - void UpdatePSTranslationAndOrientation(); - void UpdateChildParticleSystems(double); - std::unique_ptr ConstructChildParticleSystem(const TToken&); - void UpdateLightParameters(); - void BuildParticleSystemBounds(); - u32 GetEmitterTime() const { return x74_curFrame; } - u32 GetSystemCount(); - u32 GetCumulativeParticleCount() const { return x260_cumulativeParticles; } - u32 GetParticleCountAllInternal() const; - u32 GetParticleCountAll() const { return x264_recursiveParticleCount; } - void EndLifetime(); - void ForceParticleCreation(int amount); - float GetCEXTValue(int i) const { return x9c_cextValues[i]; } - void SetCEXTValue(int i, float v) { x9c_cextValues[i] = v; } + void UpdateAdvanceAccessParameters(u32 activeParticleCount, u32 particleFrame); + bool UpdateVelocitySource(u32 idx, u32 particleFrame, CParticle& particle); + void UpdateExistingParticles(); + void CreateNewParticles(int); + void UpdatePSTranslationAndOrientation(); + void UpdateChildParticleSystems(double); + std::unique_ptr ConstructChildParticleSystem(const TToken&); + void UpdateLightParameters(); + void BuildParticleSystemBounds(); + u32 GetEmitterTime() const { return x74_curFrame; } + u32 GetSystemCount(); + u32 GetCumulativeParticleCount() const { return x260_cumulativeParticles; } + u32 GetParticleCountAllInternal() const; + u32 GetParticleCountAll() const { return x264_recursiveParticleCount; } + void EndLifetime(); + void ForceParticleCreation(int amount); + float GetCEXTValue(int i) const { return x9c_cextValues[i]; } + void SetCEXTValue(int i, float v) { x9c_cextValues[i] = v; } - bool InternalUpdate(double); - void RenderModels(const CActorLights* actLights); - void RenderLines(); - void RenderParticles(); - void RenderParticlesIndirectTexture(); + bool InternalUpdate(double); + void RenderModels(const CActorLights* actLights); + void RenderLines(); + void RenderParticles(); + void RenderParticlesIndirectTexture(); - bool Update(double); - void Render(const CActorLights* = nullptr); - void SetOrientation(const zeus::CTransform&); - void SetTranslation(const zeus::CVector3f&); - void SetGlobalOrientation(const zeus::CTransform&); - void SetGlobalTranslation(const zeus::CVector3f&); - void SetGlobalScale(const zeus::CVector3f&); - void SetLocalScale(const zeus::CVector3f&); - void SetGlobalOrientAndTrans(const zeus::CTransform& xf); - void SetParticleEmission(bool); - void SetModulationColor(const zeus::CColor&); - void SetGeneratorRate(float rate); - const zeus::CTransform& GetOrientation() const; - const zeus::CVector3f& GetTranslation() const; - const zeus::CTransform& GetGlobalOrientation() const; - const zeus::CVector3f& GetGlobalTranslation() const; - const zeus::CVector3f& GetGlobalScale() const; - const zeus::CColor& GetModulationColor() const; - float GetGeneratorRate() const { return x98_generatorRate; } - bool IsSystemDeletable() const; - std::experimental::optional GetBounds() const; - u32 GetParticleCount() const; - bool SystemHasLight() const; - CLight GetLight() const; - bool GetParticleEmission() const; - void DestroyParticles(); - void Reset(); - FourCC Get4CharId() const { return FOURCC('PART'); } - size_t GetNumActiveChildParticles() const { return x290_activePartChildren.size(); } - CParticleGen& GetActiveChildParticle(size_t idx) const { return *x290_activePartChildren[idx]; } - bool IsIndirectTextured() const { return x28_loadedGenDesc->x54_x40_TEXR && x28_loadedGenDesc->x58_x44_TIND; } - void SetModelsUseLights(bool v) { x26d_26_modelsUseLights = v; } - static void SetMoveRedToAlphaBuffer(bool); + bool Update(double); + void Render(const CActorLights* = nullptr); + void SetOrientation(const zeus::CTransform&); + void SetTranslation(const zeus::CVector3f&); + void SetGlobalOrientation(const zeus::CTransform&); + void SetGlobalTranslation(const zeus::CVector3f&); + void SetGlobalScale(const zeus::CVector3f&); + void SetLocalScale(const zeus::CVector3f&); + void SetGlobalOrientAndTrans(const zeus::CTransform& xf); + void SetParticleEmission(bool); + void SetModulationColor(const zeus::CColor&); + void SetGeneratorRate(float rate); + const zeus::CTransform& GetOrientation() const; + const zeus::CVector3f& GetTranslation() const; + const zeus::CTransform& GetGlobalOrientation() const; + const zeus::CVector3f& GetGlobalTranslation() const; + const zeus::CVector3f& GetGlobalScale() const; + const zeus::CColor& GetModulationColor() const; + float GetGeneratorRate() const { return x98_generatorRate; } + bool IsSystemDeletable() const; + std::experimental::optional GetBounds() const; + u32 GetParticleCount() const; + bool SystemHasLight() const; + CLight GetLight() const; + bool GetParticleEmission() const; + void DestroyParticles(); + void Reset(); + FourCC Get4CharId() const { return FOURCC('PART'); } + size_t GetNumActiveChildParticles() const { return x290_activePartChildren.size(); } + CParticleGen& GetActiveChildParticle(size_t idx) const { return *x290_activePartChildren[idx]; } + bool IsIndirectTextured() const { return x28_loadedGenDesc->x54_x40_TEXR && x28_loadedGenDesc->x58_x44_TIND; } + void SetModelsUseLights(bool v) { x26d_26_modelsUseLights = v; } + static void SetMoveRedToAlphaBuffer(bool); - s32 GetMaxParticles() const { return x90_MAXP; } + s32 GetMaxParticles() const { return x90_MAXP; } }; ENABLE_BITWISE_ENUM(CElementGen::EOptionalSystemFlags) -} - +} // namespace urde diff --git a/Runtime/Particle/CEmitterElement.cpp b/Runtime/Particle/CEmitterElement.cpp index 30eb231e9..b816f6c97 100644 --- a/Runtime/Particle/CEmitterElement.cpp +++ b/Runtime/Particle/CEmitterElement.cpp @@ -3,76 +3,71 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Emitter_Elements */ -namespace urde -{ +namespace urde { -bool CEESimpleEmitter::GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const -{ - x4_loc->GetValue(frame, pPos); +bool CEESimpleEmitter::GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const { + x4_loc->GetValue(frame, pPos); - if (x8_vec) - x8_vec->GetValue(frame, pVel); - else - pVel = zeus::CVector3f(); + if (x8_vec) + x8_vec->GetValue(frame, pVel); + else + pVel = zeus::CVector3f(); - return false; + return false; } -bool CVESphere::GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const -{ - zeus::CVector3f a; - x4_sphereOrigin->GetValue(frame, a); - float b; - x8_sphereRadius->GetValue(frame, b); - CRandom16* rand = CRandom16::GetRandomNumber(); - int rand1 = rand->Range(-100, 100); - int rand2 = rand->Range(-100, 100); - int rand3 = rand->Range(-100, 100); +bool CVESphere::GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const { + zeus::CVector3f a; + x4_sphereOrigin->GetValue(frame, a); + float b; + x8_sphereRadius->GetValue(frame, b); + CRandom16* rand = CRandom16::GetRandomNumber(); + int rand1 = rand->Range(-100, 100); + int rand2 = rand->Range(-100, 100); + int rand3 = rand->Range(-100, 100); - zeus::CVector3f normVec1 = zeus::CVector3f(0.0099999998f * float(rand3), - 0.0099999998f * float(rand2), - 0.0099999998f * float(rand1)); - if (normVec1.canBeNormalized()) - normVec1.normalize(); + zeus::CVector3f normVec1 = + zeus::CVector3f(0.0099999998f * float(rand3), 0.0099999998f * float(rand2), 0.0099999998f * float(rand1)); + if (normVec1.canBeNormalized()) + normVec1.normalize(); - pPos = b * normVec1 + a; + pPos = b * normVec1 + a; - zeus::CVector3f normVec2 = (pPos - a); - if (normVec2.canBeNormalized()) - normVec2.normalize(); + zeus::CVector3f normVec2 = (pPos - a); + if (normVec2.canBeNormalized()) + normVec2.normalize(); - float c; - xc_velocityMag->GetValue(frame, c); - pVel = c * normVec2; + float c; + xc_velocityMag->GetValue(frame, c); + pVel = c * normVec2; - return false; + return false; } -bool CVEAngleSphere::GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const -{ - zeus::CVector3f a; - x4_sphereOrigin->GetValue(frame, a); +bool CVEAngleSphere::GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const { + zeus::CVector3f a; + x4_sphereOrigin->GetValue(frame, a); - float b, d, e, f, g; - x8_sphereRadius->GetValue(frame, b); - x10_angleXBias->GetValue(frame, d); - x14_angleYBias->GetValue(frame, e); - x18_angleXRange->GetValue(frame, f); - x1c_angleYRange->GetValue(frame, g); - CRandom16* rand = CRandom16::GetRandomNumber(); - d = zeus::degToRad(d + ((0.5f * (f * rand->Float())) - f)); - e = zeus::degToRad(e + ((0.5f * (g * rand->Float())) - g)); + float b, d, e, f, g; + x8_sphereRadius->GetValue(frame, b); + x10_angleXBias->GetValue(frame, d); + x14_angleYBias->GetValue(frame, e); + x18_angleXRange->GetValue(frame, f); + x1c_angleYRange->GetValue(frame, g); + CRandom16* rand = CRandom16::GetRandomNumber(); + d = zeus::degToRad(d + ((0.5f * (f * rand->Float())) - f)); + e = zeus::degToRad(e + ((0.5f * (g * rand->Float())) - g)); - float cosD = std::cos(d); - pPos.x() = a.x() + (b * (-std::sin(e) * cosD)); - pPos.y() = a.y() + (b * std::sin(d)); - pPos.z() = a.z() + (b * (cosD * cosD)); - zeus::CVector3f normVec = (pPos - a).normalized(); + float cosD = std::cos(d); + pPos.x() = a.x() + (b * (-std::sin(e) * cosD)); + pPos.y() = a.y() + (b * std::sin(d)); + pPos.z() = a.z() + (b * (cosD * cosD)); + zeus::CVector3f normVec = (pPos - a).normalized(); - float c; - xc_velocityMag->GetValue(frame, c); - pVel = c * normVec; - return false; + float c; + xc_velocityMag->GetValue(frame, c); + pVel = c * normVec; + return false; } -} +} // namespace urde diff --git a/Runtime/Particle/CEmitterElement.hpp b/Runtime/Particle/CEmitterElement.hpp index c2a896bd2..119faa780 100644 --- a/Runtime/Particle/CEmitterElement.hpp +++ b/Runtime/Particle/CEmitterElement.hpp @@ -4,50 +4,51 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Emitter_Elements */ -namespace urde -{ +namespace urde { + +class CEESimpleEmitter : public CEmitterElement { + std::unique_ptr x4_loc; + std::unique_ptr x8_vec; -class CEESimpleEmitter : public CEmitterElement -{ - std::unique_ptr x4_loc; - std::unique_ptr x8_vec; public: - CEESimpleEmitter(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_loc(std::move(a)), x8_vec(std::move(b)) {} - bool GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const; + CEESimpleEmitter(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_loc(std::move(a)), x8_vec(std::move(b)) {} + bool GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const; }; -class CVESphere : public CEmitterElement -{ - std::unique_ptr x4_sphereOrigin; - std::unique_ptr x8_sphereRadius; - std::unique_ptr xc_velocityMag; +class CVESphere : public CEmitterElement { + std::unique_ptr x4_sphereOrigin; + std::unique_ptr x8_sphereRadius; + std::unique_ptr xc_velocityMag; + public: - CVESphere(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c) - : x4_sphereOrigin(std::move(a)), x8_sphereRadius(std::move(b)), xc_velocityMag(std::move(c)) {} - bool GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const; + CVESphere(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_sphereOrigin(std::move(a)), x8_sphereRadius(std::move(b)), xc_velocityMag(std::move(c)) {} + bool GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const; }; -class CVEAngleSphere : public CEmitterElement -{ - std::unique_ptr x4_sphereOrigin; - std::unique_ptr x8_sphereRadius; - std::unique_ptr xc_velocityMag; - std::unique_ptr x10_angleXBias; - std::unique_ptr x14_angleYBias; - std::unique_ptr x18_angleXRange; - std::unique_ptr x1c_angleYRange; +class CVEAngleSphere : public CEmitterElement { + std::unique_ptr x4_sphereOrigin; + std::unique_ptr x8_sphereRadius; + std::unique_ptr xc_velocityMag; + std::unique_ptr x10_angleXBias; + std::unique_ptr x14_angleYBias; + std::unique_ptr x18_angleXRange; + std::unique_ptr x1c_angleYRange; + public: - CVEAngleSphere(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d, - std::unique_ptr&& e, std::unique_ptr&& f, - std::unique_ptr&& g) - : x4_sphereOrigin(std::move(a)), x8_sphereRadius(std::move(b)), xc_velocityMag(std::move(c)), - x10_angleXBias(std::move(d)), x14_angleYBias(std::move(e)), x18_angleXRange(std::move(f)), - x1c_angleYRange(std::move(g)) {} - bool GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const; + CVEAngleSphere(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c, std::unique_ptr&& d, + std::unique_ptr&& e, std::unique_ptr&& f, + std::unique_ptr&& g) + : x4_sphereOrigin(std::move(a)) + , x8_sphereRadius(std::move(b)) + , xc_velocityMag(std::move(c)) + , x10_angleXBias(std::move(d)) + , x14_angleYBias(std::move(e)) + , x18_angleXRange(std::move(f)) + , x1c_angleYRange(std::move(g)) {} + bool GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const; }; -} - +} // namespace urde diff --git a/Runtime/Particle/CFlameWarp.cpp b/Runtime/Particle/CFlameWarp.cpp index 75a536eff..3f313a1bd 100644 --- a/Runtime/Particle/CFlameWarp.cpp +++ b/Runtime/Particle/CFlameWarp.cpp @@ -1,92 +1,81 @@ #include "CFlameWarp.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { -void CFlameWarp::ModifyParticles(std::vector& particles) -{ - if (x9c_stateMgr == 0 || particles.size() < 9) - return; +void CFlameWarp::ModifyParticles(std::vector& particles) { + if (x9c_stateMgr == 0 || particles.size() < 9) + return; - std::vector> vec; - vec.reserve(particles.size()); + std::vector> vec; + vec.reserve(particles.size()); - x90_minSize = FLT_MAX; - x94_maxSize = FLT_MIN; - float maxTransp = 0.f; - u8 idx = 0; - for (CParticle& particle : particles) - { - float transp = 1.f - particle.x34_color.a(); - if (transp > maxTransp) - { - float distSq = (particle.x4_pos - x74_warpPoint).magSquared(); - if (distSq > x8c_maxDistSq && distSq < x98_maxInfluenceDistSq) - { - x8c_maxDistSq = distSq; - maxTransp = transp; - x80_floatingPoint = particle.x4_pos; - } - } - - if (particle.x2c_lineLengthOrSize < x90_minSize) - x90_minSize = particle.x2c_lineLengthOrSize; - if (particle.x2c_lineLengthOrSize > x94_maxSize) - x94_maxSize = particle.x2c_lineLengthOrSize; - - vec.emplace_back(transp, idx); - - if (xa0_25_collisionWarp) - { - zeus::CVector3f delta = particle.x4_pos - particle.x10_prevPos; - if (delta.magSquared() >= 0.0011920929f) - { - zeus::CVector3f deltaNorm = delta.normalized(); - zeus::CVector3f behindPos = particle.x10_prevPos - deltaNorm * 5.f; - zeus::CVector3f fullDelta = particle.x4_pos - behindPos; - CRayCastResult result = - x9c_stateMgr->RayStaticIntersection(behindPos, deltaNorm, fullDelta.magnitude(), - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::ProjectilePassthrough})); - if (result.IsValid()) - { - float dist = result.GetPlane().pointToPlaneDist(particle.x4_pos); - if (dist <= 0.f) - { - particle.x4_pos =- result.GetPlane().normal() * dist; - if (result.GetPlane().normal().dot(particle.x1c_vel) < 0.f) - { - zeus::CVector3f prevStepPos = particle.x4_pos - particle.x1c_vel; - particle.x4_pos += (-result.GetPlane().pointToPlaneDist(prevStepPos) / - particle.x1c_vel.dot(result.GetPlane().normal()) - 1.f) * particle.x1c_vel; - particle.x1c_vel -= particle.x1c_vel * 0.001f; - } - } - } - } - } - - ++idx; + x90_minSize = FLT_MAX; + x94_maxSize = FLT_MIN; + float maxTransp = 0.f; + u8 idx = 0; + for (CParticle& particle : particles) { + float transp = 1.f - particle.x34_color.a(); + if (transp > maxTransp) { + float distSq = (particle.x4_pos - x74_warpPoint).magSquared(); + if (distSq > x8c_maxDistSq && distSq < x98_maxInfluenceDistSq) { + x8c_maxDistSq = distSq; + maxTransp = transp; + x80_floatingPoint = particle.x4_pos; + } } - std::sort(vec.begin(), vec.end(), [](auto& a, auto& b) { return a.first < b.first; }); + if (particle.x2c_lineLengthOrSize < x90_minSize) + x90_minSize = particle.x2c_lineLengthOrSize; + if (particle.x2c_lineLengthOrSize > x94_maxSize) + x94_maxSize = particle.x2c_lineLengthOrSize; - for (int i=0 ; i<9 ; ++i) - { - CParticle& part = particles[vec[i].second]; - x4_vecs[i] = part.x4_pos; - if (i > 0) - { - zeus::CVector3f delta = x4_vecs[i] - x4_vecs[i-1]; - if (delta.magnitude() < 0.0011920929f) - x4_vecs[i] += delta.normalized() * 0.0011920929f; + vec.emplace_back(transp, idx); + + if (xa0_25_collisionWarp) { + zeus::CVector3f delta = particle.x4_pos - particle.x10_prevPos; + if (delta.magSquared() >= 0.0011920929f) { + zeus::CVector3f deltaNorm = delta.normalized(); + zeus::CVector3f behindPos = particle.x10_prevPos - deltaNorm * 5.f; + zeus::CVector3f fullDelta = particle.x4_pos - behindPos; + CRayCastResult result = x9c_stateMgr->RayStaticIntersection( + behindPos, deltaNorm, fullDelta.magnitude(), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough})); + if (result.IsValid()) { + float dist = result.GetPlane().pointToPlaneDist(particle.x4_pos); + if (dist <= 0.f) { + particle.x4_pos = -result.GetPlane().normal() * dist; + if (result.GetPlane().normal().dot(particle.x1c_vel) < 0.f) { + zeus::CVector3f prevStepPos = particle.x4_pos - particle.x1c_vel; + particle.x4_pos += + (-result.GetPlane().pointToPlaneDist(prevStepPos) / particle.x1c_vel.dot(result.GetPlane().normal()) - + 1.f) * + particle.x1c_vel; + particle.x1c_vel -= particle.x1c_vel * 0.001f; + } + } } + } } - x4_vecs[0] = x74_warpPoint; - x80_floatingPoint = x4_vecs[8]; - xa0_26_processed = true; + ++idx; + } + + std::sort(vec.begin(), vec.end(), [](auto& a, auto& b) { return a.first < b.first; }); + + for (int i = 0; i < 9; ++i) { + CParticle& part = particles[vec[i].second]; + x4_vecs[i] = part.x4_pos; + if (i > 0) { + zeus::CVector3f delta = x4_vecs[i] - x4_vecs[i - 1]; + if (delta.magnitude() < 0.0011920929f) + x4_vecs[i] += delta.normalized() * 0.0011920929f; + } + } + + x4_vecs[0] = x74_warpPoint; + x80_floatingPoint = x4_vecs[8]; + xa0_26_processed = true; } -} +} // namespace urde diff --git a/Runtime/Particle/CFlameWarp.hpp b/Runtime/Particle/CFlameWarp.hpp index f8af860d8..ea3d9e215 100644 --- a/Runtime/Particle/CFlameWarp.hpp +++ b/Runtime/Particle/CFlameWarp.hpp @@ -2,39 +2,37 @@ #include "CWarp.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class CFlameWarp : public CWarp -{ - rstl::reserved_vector x4_vecs; - zeus::CVector3f x74_warpPoint; - zeus::CVector3f x80_floatingPoint; - float x8c_maxDistSq = 0.f; - float x90_minSize = FLT_MAX; - float x94_maxSize = FLT_MIN; - float x98_maxInfluenceDistSq; - CStateManager* x9c_stateMgr = nullptr; - bool xa0_24_activated : 1; - bool xa0_25_collisionWarp : 1; - bool xa0_26_processed : 1; +class CFlameWarp : public CWarp { + rstl::reserved_vector x4_vecs; + zeus::CVector3f x74_warpPoint; + zeus::CVector3f x80_floatingPoint; + float x8c_maxDistSq = 0.f; + float x90_minSize = FLT_MAX; + float x94_maxSize = FLT_MIN; + float x98_maxInfluenceDistSq; + CStateManager* x9c_stateMgr = nullptr; + bool xa0_24_activated : 1; + bool xa0_25_collisionWarp : 1; + bool xa0_26_processed : 1; + public: - CFlameWarp(float maxInfluenceDist, const zeus::CVector3f& warpPoint, bool collisionWarp) - : x74_warpPoint(warpPoint), x80_floatingPoint(warpPoint), - x98_maxInfluenceDistSq(maxInfluenceDist * maxInfluenceDist) - { - x4_vecs.resize(9, warpPoint); - xa0_24_activated = false; - xa0_25_collisionWarp = collisionWarp; - xa0_26_processed = false; - } + CFlameWarp(float maxInfluenceDist, const zeus::CVector3f& warpPoint, bool collisionWarp) + : x74_warpPoint(warpPoint) + , x80_floatingPoint(warpPoint) + , x98_maxInfluenceDistSq(maxInfluenceDist * maxInfluenceDist) { + x4_vecs.resize(9, warpPoint); + xa0_24_activated = false; + xa0_25_collisionWarp = collisionWarp; + xa0_26_processed = false; + } - bool UpdateWarp() { return xa0_24_activated; } - void ModifyParticles(std::vector& particles); - void Activate(bool val) { xa0_24_activated = val; } - bool IsActivated() { return xa0_24_activated; } - FourCC Get4CharID() { return FOURCC('FWRP'); } + bool UpdateWarp() { return xa0_24_activated; } + void ModifyParticles(std::vector& particles); + void Activate(bool val) { xa0_24_activated = val; } + bool IsActivated() { return xa0_24_activated; } + FourCC Get4CharID() { return FOURCC('FWRP'); } }; -} - +} // namespace urde diff --git a/Runtime/Particle/CGenDescription.hpp b/Runtime/Particle/CGenDescription.hpp index d3488e047..321710e7b 100644 --- a/Runtime/Particle/CGenDescription.hpp +++ b/Runtime/Particle/CGenDescription.hpp @@ -13,101 +13,105 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/PART_(File_Format) */ -namespace urde -{ +namespace urde { -class CGenDescription -{ +class CGenDescription { public: - /* Naming convention: __ */ + /* Naming convention: __ */ - /* Removed from demo */ - // std::unique_ptr x0_PSIV; - // std::unique_ptr x4_PSVM; - // std::unique_ptr x8_PSOV; - std::unique_ptr xc_x0_PSLT; - std::unique_ptr x10_x4_PSWT; - std::unique_ptr x14_x8_PSTS; - std::unique_ptr x18_xc_POFS; - std::unique_ptr x1c_x10_SEED; - std::unique_ptr x20_x14_LENG; - std::unique_ptr x24_x18_WIDT; - std::unique_ptr x28_x1c_MAXP; - std::unique_ptr x2c_x20_GRTE; - std::unique_ptr x30_x24_COLR; - std::unique_ptr x34_x28_LTME; - /* Removed from demo (replaced by EMTR) */ - // std::unique_ptr x38_ILOC; - // std::unique_ptr x3c_IVEC; - std::unique_ptr x40_x2c_EMTR; - union - { - struct - { - bool x44_28_x30_28_SORT : 1; bool x44_30_x31_24_MBLR : 1; bool x44_24_x30_24_LINE : 1; bool x44_29_x30_29_LIT_ : 1; - bool x44_26_x30_26_AAPH : 1; bool x44_27_x30_27_ZBUF : 1; bool x44_25_x30_25_FXLL : 1; bool x44_31_x31_25_PMAB : 1; - bool x45_29_x31_31_VMD4 : 1; bool x45_28_x31_30_VMD3 : 1; bool x45_27_x31_29_VMD2 : 1; bool x45_26_x31_28_VMD1 : 1; - bool x45_31_x32_25_OPTS : 1; bool x45_24_x31_26_PMUS : 1; bool x45_25_x31_27_PMOO : 1; bool x45_30_x32_24_CIND : 1; - /* 0-00 additions */ - bool x30_30_ORNT : 1; bool x30_31_RSOP : 1; - }; - uint32_t dummy1 = 0; + /* Removed from demo */ + // std::unique_ptr x0_PSIV; + // std::unique_ptr x4_PSVM; + // std::unique_ptr x8_PSOV; + std::unique_ptr xc_x0_PSLT; + std::unique_ptr x10_x4_PSWT; + std::unique_ptr x14_x8_PSTS; + std::unique_ptr x18_xc_POFS; + std::unique_ptr x1c_x10_SEED; + std::unique_ptr x20_x14_LENG; + std::unique_ptr x24_x18_WIDT; + std::unique_ptr x28_x1c_MAXP; + std::unique_ptr x2c_x20_GRTE; + std::unique_ptr x30_x24_COLR; + std::unique_ptr x34_x28_LTME; + /* Removed from demo (replaced by EMTR) */ + // std::unique_ptr x38_ILOC; + // std::unique_ptr x3c_IVEC; + std::unique_ptr x40_x2c_EMTR; + union { + struct { + bool x44_28_x30_28_SORT : 1; + bool x44_30_x31_24_MBLR : 1; + bool x44_24_x30_24_LINE : 1; + bool x44_29_x30_29_LIT_ : 1; + bool x44_26_x30_26_AAPH : 1; + bool x44_27_x30_27_ZBUF : 1; + bool x44_25_x30_25_FXLL : 1; + bool x44_31_x31_25_PMAB : 1; + bool x45_29_x31_31_VMD4 : 1; + bool x45_28_x31_30_VMD3 : 1; + bool x45_27_x31_29_VMD2 : 1; + bool x45_26_x31_28_VMD1 : 1; + bool x45_31_x32_25_OPTS : 1; + bool x45_24_x31_26_PMUS : 1; + bool x45_25_x31_27_PMOO : 1; + bool x45_30_x32_24_CIND : 1; + /* 0-00 additions */ + bool x30_30_ORNT : 1; + bool x30_31_RSOP : 1; }; - std::unique_ptr x48_x34_MBSP; - std::unique_ptr x4c_x38_SIZE; - std::unique_ptr x50_x3c_ROTA; - std::unique_ptr x54_x40_TEXR; - std::unique_ptr x58_x44_TIND; - SParticleModel x5c_x48_PMDL; - std::unique_ptr x6c_x58_PMOP; - std::unique_ptr x70_x5c_PMRT; - std::unique_ptr x74_x60_PMSC; - std::unique_ptr x78_x64_PMCL; - std::unique_ptr x7c_x68_VEL1; - std::unique_ptr x80_x6c_VEL2; - std::unique_ptr x84_x70_VEL3; - std::unique_ptr x88_x74_VEL4; - SChildGeneratorDesc x8c_x78_ICTS; - std::unique_ptr x9c_x88_NCSY; - std::unique_ptr xa0_x8c_CSSD; - SChildGeneratorDesc xa4_x90_IDTS; - std::unique_ptr xb4_xa0_NDSY; - SChildGeneratorDesc xb8_xa4_IITS; - std::unique_ptr xc8_xb4_PISY; - std::unique_ptr xcc_xb8_SISY; - std::unique_ptr xd0_xbc_KSSM; - SSwooshGeneratorDesc xd4_xc0_SSWH; - std::unique_ptr xe4_xd0_SSSD; - std::unique_ptr xe8_xd4_SSPO; - SElectricGeneratorDesc xec_xd8_SELC; - std::unique_ptr xf8_xe4_SESD; - std::unique_ptr xfc_xe8_SEPO; - std::unique_ptr x100_xec_LTYP; - std::unique_ptr x104_xf0_LCLR; - std::unique_ptr x108_xf4_LINT; - std::unique_ptr x10c_xf8_LOFF; - std::unique_ptr x110_xfc_LDIR; - std::unique_ptr x114_x100_LFOT; - std::unique_ptr x118_x104_LFOR; - std::unique_ptr x11c_x108_LSLA; - std::unique_ptr x10c_ADV1; - std::unique_ptr x110_ADV2; - std::unique_ptr x114_ADV3; - std::unique_ptr x118_ADV4; - std::unique_ptr x11c_ADV5; - std::unique_ptr x120_ADV6; - std::unique_ptr x124_ADV7; - std::unique_ptr x128_ADV8; + uint32_t dummy1 = 0; + }; + std::unique_ptr x48_x34_MBSP; + std::unique_ptr x4c_x38_SIZE; + std::unique_ptr x50_x3c_ROTA; + std::unique_ptr x54_x40_TEXR; + std::unique_ptr x58_x44_TIND; + SParticleModel x5c_x48_PMDL; + std::unique_ptr x6c_x58_PMOP; + std::unique_ptr x70_x5c_PMRT; + std::unique_ptr x74_x60_PMSC; + std::unique_ptr x78_x64_PMCL; + std::unique_ptr x7c_x68_VEL1; + std::unique_ptr x80_x6c_VEL2; + std::unique_ptr x84_x70_VEL3; + std::unique_ptr x88_x74_VEL4; + SChildGeneratorDesc x8c_x78_ICTS; + std::unique_ptr x9c_x88_NCSY; + std::unique_ptr xa0_x8c_CSSD; + SChildGeneratorDesc xa4_x90_IDTS; + std::unique_ptr xb4_xa0_NDSY; + SChildGeneratorDesc xb8_xa4_IITS; + std::unique_ptr xc8_xb4_PISY; + std::unique_ptr xcc_xb8_SISY; + std::unique_ptr xd0_xbc_KSSM; + SSwooshGeneratorDesc xd4_xc0_SSWH; + std::unique_ptr xe4_xd0_SSSD; + std::unique_ptr xe8_xd4_SSPO; + SElectricGeneratorDesc xec_xd8_SELC; + std::unique_ptr xf8_xe4_SESD; + std::unique_ptr xfc_xe8_SEPO; + std::unique_ptr x100_xec_LTYP; + std::unique_ptr x104_xf0_LCLR; + std::unique_ptr x108_xf4_LINT; + std::unique_ptr x10c_xf8_LOFF; + std::unique_ptr x110_xfc_LDIR; + std::unique_ptr x114_x100_LFOT; + std::unique_ptr x118_x104_LFOR; + std::unique_ptr x11c_x108_LSLA; + std::unique_ptr x10c_ADV1; + std::unique_ptr x110_ADV2; + std::unique_ptr x114_ADV3; + std::unique_ptr x118_ADV4; + std::unique_ptr x11c_ADV5; + std::unique_ptr x120_ADV6; + std::unique_ptr x124_ADV7; + std::unique_ptr x128_ADV8; + /* Custom additions */ + std::unique_ptr m_bevelGradient; /* FourCC BGCL */ - /* Custom additions */ - std::unique_ptr m_bevelGradient; /* FourCC BGCL */ - - CGenDescription() - { - x45_25_x31_27_PMOO = true; - } + CGenDescription() { x45_25_x31_27_PMOO = true; } }; -} - +} // namespace urde diff --git a/Runtime/Particle/CIntElement.cpp b/Runtime/Particle/CIntElement.cpp index 863f0fed1..87c7cc2dd 100644 --- a/Runtime/Particle/CIntElement.cpp +++ b/Runtime/Particle/CIntElement.cpp @@ -6,366 +6,290 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Int_Elements */ -namespace urde -{ +namespace urde { -CIEKeyframeEmitter::CIEKeyframeEmitter(CInputStream& in) -{ - x4_percent = in.readUint32Big(); - x8_unk1 = in.readUint32Big(); - xc_loop = in.readBool(); - xd_unk2 = in.readBool(); - x10_loopEnd = in.readUint32Big(); - x14_loopStart = in.readUint32Big(); +CIEKeyframeEmitter::CIEKeyframeEmitter(CInputStream& in) { + x4_percent = in.readUint32Big(); + x8_unk1 = in.readUint32Big(); + xc_loop = in.readBool(); + xd_unk2 = in.readBool(); + x10_loopEnd = in.readUint32Big(); + x14_loopStart = in.readUint32Big(); - u32 count = in.readUint32Big(); - x18_keys.reserve(count); - for (u32 i=0 ; i= x10_loopEnd) - { - int v1 = emitterTime - x14_loopStart; - int v2 = x10_loopEnd - x14_loopStart; - calcKey = v1 % v2; - calcKey += x14_loopStart; - } - } - else - { - int v1 = x10_loopEnd - 1; - if (v1 < emitterTime) - calcKey = v1; - } - valOut = x18_keys[calcKey]; +bool CIEKeyframeEmitter::GetValue(int frame, int& valOut) const { + if (!x4_percent) { + int emitterTime = CParticleGlobals::g_EmitterTime; + int calcKey = emitterTime; + if (xc_loop) { + if (emitterTime >= x10_loopEnd) { + int v1 = emitterTime - x14_loopStart; + int v2 = x10_loopEnd - x14_loopStart; + calcKey = v1 % v2; + calcKey += x14_loopStart; + } + } else { + int v1 = x10_loopEnd - 1; + if (v1 < emitterTime) + calcKey = v1; } + valOut = x18_keys[calcKey]; + } else { + int ltPerc = CParticleGlobals::g_ParticleLifetimePercentage; + float ltPercRem = CParticleGlobals::g_ParticleLifetimePercentageRemainder; + if (ltPerc == 100) + valOut = x18_keys[100]; else - { - int ltPerc = CParticleGlobals::g_ParticleLifetimePercentage; - float ltPercRem = CParticleGlobals::g_ParticleLifetimePercentageRemainder; - if (ltPerc == 100) - valOut = x18_keys[100]; - else - valOut = ltPercRem * x18_keys[ltPerc+1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; - } - return false; + valOut = ltPercRem * x18_keys[ltPerc + 1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; + } + return false; } -int CIEKeyframeEmitter::GetMaxValue() const -{ - int maxVal = INT_MIN; - for (int k : x18_keys) - if (k > maxVal) - maxVal = k; - return maxVal; +int CIEKeyframeEmitter::GetMaxValue() const { + int maxVal = INT_MIN; + for (int k : x18_keys) + if (k > maxVal) + maxVal = k; + return maxVal; } -bool CIEDeath::GetValue(int frame, int &valOut) const -{ +bool CIEDeath::GetValue(int frame, int& valOut) const { + x4_a->GetValue(frame, valOut); + int b; + x8_b->GetValue(frame, b); + /* Not 100% sure about this, originally some kinda branchless comparison */ + return frame > b; +} + +int CIEDeath::GetMaxValue() const { return x4_a->GetMaxValue(); } + +bool CIEClamp::GetValue(int frame, int& valOut) const { + int a, b; + x4_min->GetValue(frame, a); + x8_max->GetValue(frame, b); + xc_val->GetValue(frame, valOut); + if (valOut > b) + valOut = b; + if (valOut < a) + valOut = a; + return false; +} + +int CIEClamp::GetMaxValue() const { + int a, b, valOut; + a = x4_min->GetMaxValue(); + b = x8_max->GetMaxValue(); + valOut = xc_val->GetMaxValue(); + if (valOut > b) + valOut = b; + if (valOut < a) + valOut = a; + return valOut; +} + +bool CIETimeChain::GetValue(int frame, int& valOut) const { + int v; + xc_swFrame->GetValue(frame, v); + if (frame >= v) + return x8_b->GetValue(frame, valOut); + else + return x4_a->GetValue(frame, valOut); +} + +int CIETimeChain::GetMaxValue() const { return std::max(x8_b->GetMaxValue(), x4_a->GetMaxValue()); } + +bool CIEAdd::GetValue(int frame, int& valOut) const { + int a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a + b; + return false; +} + +int CIEAdd::GetMaxValue() const { + int a, b; + a = x4_a->GetMaxValue(); + b = x8_b->GetMaxValue(); + return a + b; +} + +bool CIEConstant::GetValue(int frame, int& valOut) const { + valOut = x4_val; + return false; +} + +int CIEConstant::GetMaxValue() const { return x4_val; } + +bool CIEImpulse::GetValue(int frame, int& valOut) const { + if (frame == 0) x4_a->GetValue(frame, valOut); - int b; - x8_b->GetValue(frame, b); - /* Not 100% sure about this, originally some kinda branchless comparison */ - return frame > b; + else + valOut = 0; + return false; } -int CIEDeath::GetMaxValue() const -{ - return x4_a->GetMaxValue(); +int CIEImpulse::GetMaxValue() const { return x4_a->GetMaxValue(); } + +bool CIELifetimePercent::GetValue(int frame, int& valOut) const { + int a; + x4_percentVal->GetValue(frame, a); + a = std::max(0, a); + valOut = (a / 100.0f) * CParticleGlobals::g_ParticleLifetimeReal + 0.5f; + return false; } -bool CIEClamp::GetValue(int frame, int& valOut) const -{ - int a, b; - x4_min->GetValue(frame, a); - x8_max->GetValue(frame, b); - xc_val->GetValue(frame, valOut); - if (valOut > b) - valOut = b; - if (valOut < a) - valOut = a; - return false; +int CIELifetimePercent::GetMaxValue() const { + int a; + a = x4_percentVal->GetMaxValue(); + a = std::max(0, a); + return (a / 100.0f) * 10000 + 0.5f; /* Assume 10000 frames max (not ideal estimate) */ } -int CIEClamp::GetMaxValue() const -{ - int a, b, valOut; - a = x4_min->GetMaxValue(); - b = x8_max->GetMaxValue(); - valOut = xc_val->GetMaxValue(); - if (valOut > b) - valOut = b; - if (valOut < a) - valOut = a; - return valOut; -} - -bool CIETimeChain::GetValue(int frame, int& valOut) const -{ - int v; - xc_swFrame->GetValue(frame, v); - if (frame >= v) - return x8_b->GetValue(frame, valOut); - else - return x4_a->GetValue(frame, valOut); -} - -int CIETimeChain::GetMaxValue() const -{ - return std::max(x8_b->GetMaxValue(), x4_a->GetMaxValue()); -} - -bool CIEAdd::GetValue(int frame, int& valOut) const -{ +bool CIEInitialRandom::GetValue(int frame, int& valOut) const { + if (frame == 0) { int a, b; x4_a->GetValue(frame, a); x8_b->GetValue(frame, b); - valOut = a + b; - return false; + valOut = CRandom16::GetRandomNumber()->Range(a, b); + } + return false; } -int CIEAdd::GetMaxValue() const -{ - int a, b; - a = x4_a->GetMaxValue(); - b = x8_b->GetMaxValue(); - return a + b; -} +int CIEInitialRandom::GetMaxValue() const { return x8_b->GetMaxValue(); } -bool CIEConstant::GetValue(int frame, int& valOut) const -{ - valOut = x4_val; - return false; -} +bool CIEPulse::GetValue(int frame, int& valOut) const { + int a, b; + x4_aDuration->GetValue(frame, a); + x8_bDuration->GetValue(frame, b); + int cv = std::max(1, a + b + 1); -int CIEConstant::GetMaxValue() const -{ - return x4_val; -} - -bool CIEImpulse::GetValue(int frame, int& valOut) const -{ - if (frame == 0) - x4_a->GetValue(frame, valOut); + if (b >= 1) { + int cv2 = frame % cv; + if (cv2 >= a) + x10_bVal->GetValue(frame, valOut); else - valOut = 0; - return false; + xc_aVal->GetValue(frame, valOut); + } else + xc_aVal->GetValue(frame, valOut); + + return false; } -int CIEImpulse::GetMaxValue() const -{ - return x4_a->GetMaxValue(); +int CIEPulse::GetMaxValue() const { return std::max(xc_aVal->GetMaxValue(), x10_bVal->GetMaxValue()); } + +bool CIEMultiply::GetValue(int frame, int& valOut) const { + int a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a * b; + return false; } -bool CIELifetimePercent::GetValue(int frame, int& valOut) const -{ - int a; - x4_percentVal->GetValue(frame, a); - a = std::max(0, a); - valOut = (a / 100.0f) * CParticleGlobals::g_ParticleLifetimeReal + 0.5f; - return false; +int CIEMultiply::GetMaxValue() const { return x4_a->GetMaxValue() * x8_b->GetMaxValue(); } + +bool CIESampleAndHold::GetValue(int frame, int& valOut) const { + if (x8_nextSampleFrame < frame) { + int b, c; + xc_waitFramesMin->GetValue(frame, b); + x10_waitFramesMax->GetValue(frame, c); + /* const-correctness, who needs it? */ + const_cast(this)->x8_nextSampleFrame = CRandom16::GetRandomNumber()->Range(b, c) + frame; + x4_sampleSource->GetValue(frame, valOut); + const_cast(this)->x14_holdVal = valOut; + } else + valOut = x14_holdVal; + return false; } -int CIELifetimePercent::GetMaxValue() const -{ - int a; - a = x4_percentVal->GetMaxValue(); - a = std::max(0, a); - return (a / 100.0f) * 10000 + 0.5f; /* Assume 10000 frames max (not ideal estimate) */ +int CIESampleAndHold::GetMaxValue() const { return x4_sampleSource->GetMaxValue(); } + +bool CIERandom::GetValue(int frame, int& valOut) const { + int a, b; + x4_min->GetValue(frame, a); + x8_max->GetValue(frame, b); + if (a > 0) + valOut = CRandom16::GetRandomNumber()->Range(a, b); + else + valOut = CRandom16::GetRandomNumber()->Next(); + return false; } -bool CIEInitialRandom::GetValue(int frame, int& valOut) const -{ - if (frame == 0) - { - int a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = CRandom16::GetRandomNumber()->Range(a, b); - } - return false; +int CIERandom::GetMaxValue() const { + if (x4_min->GetMaxValue() > 0) + return x8_max->GetMaxValue(); + else + return 65535; } -int CIEInitialRandom::GetMaxValue() const -{ - return x8_b->GetMaxValue(); +bool CIETimeScale::GetValue(int frame, int& valOut) const { + float a; + x4_a->GetValue(frame, a); + valOut = float(frame) * a; + return false; } -bool CIEPulse::GetValue(int frame, int& valOut) const -{ - int a, b; - x4_aDuration->GetValue(frame, a); - x8_bDuration->GetValue(frame, b); - int cv = std::max(1, a + b + 1); +int CIETimeScale::GetMaxValue() const { return 10000; /* Assume 10000 frames max (not ideal estimate) */ } - if (b >= 1) - { - int cv2 = frame % cv; - if (cv2 >= a) - x10_bVal->GetValue(frame, valOut); - else - xc_aVal->GetValue(frame, valOut); - } - else - xc_aVal->GetValue(frame, valOut); - - return false; +bool CIEGetCumulativeParticleCount::GetValue(int frame, int& valOut) const { + valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetCumulativeParticleCount(); + return false; } -int CIEPulse::GetMaxValue() const -{ - return std::max(xc_aVal->GetMaxValue(), x10_bVal->GetMaxValue()); +int CIEGetCumulativeParticleCount::GetMaxValue() const { return 256; } + +bool CIEGetActiveParticleCount::GetValue(int frame, int& valOut) const { + valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetParticleCount(); + return false; } -bool CIEMultiply::GetValue(int frame, int& valOut) const -{ - int a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = a * b; - return false; +int CIEGetActiveParticleCount::GetMaxValue() const { return 256; } + +bool CIEGetEmitterTime::GetValue(int frame, int& valOut) const { + valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetEmitterTime(); + return false; } -int CIEMultiply::GetMaxValue() const -{ - return x4_a->GetMaxValue() * x8_b->GetMaxValue(); +int CIEGetEmitterTime::GetMaxValue() const { return 10000; /* Assume 10000 frames max (not ideal estimate) */ } + +bool CIEModulo::GetValue(int frame, int& valOut) const { + int a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + if (b != 0) + valOut = a % b; + else + valOut = a; + return false; } -bool CIESampleAndHold::GetValue(int frame, int& valOut) const -{ - if (x8_nextSampleFrame < frame) - { - int b, c; - xc_waitFramesMin->GetValue(frame, b); - x10_waitFramesMax->GetValue(frame, c); - /* const-correctness, who needs it? */ - const_cast(this)->x8_nextSampleFrame = CRandom16::GetRandomNumber()->Range(b, c) + frame; - x4_sampleSource->GetValue(frame, valOut); - const_cast(this)->x14_holdVal = valOut; - } - else - valOut = x14_holdVal; - return false; +int CIEModulo::GetMaxValue() const { + int a, b; + a = x4_a->GetMaxValue(); + b = x8_b->GetMaxValue(); + if (b != 0) + return b - 1; + else + return a; } -int CIESampleAndHold::GetMaxValue() const -{ - return x4_sampleSource->GetMaxValue(); +bool CIESubtract::GetValue(int frame, int& valOut) const { + int a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a - b; + return false; } -bool CIERandom::GetValue(int frame, int& valOut) const -{ - int a, b; - x4_min->GetValue(frame, a); - x8_max->GetValue(frame, b); - if (a > 0) - valOut = CRandom16::GetRandomNumber()->Range(a, b); - else - valOut = CRandom16::GetRandomNumber()->Next(); - return false; +int CIESubtract::GetMaxValue() const { + int a, b; + a = x4_a->GetMaxValue(); + b = x8_b->GetMaxValue(); + return a - b; } -int CIERandom::GetMaxValue() const -{ - if (x4_min->GetMaxValue() > 0) - return x8_max->GetMaxValue(); - else - return 65535; -} - -bool CIETimeScale::GetValue(int frame, int& valOut) const -{ - float a; - x4_a->GetValue(frame, a); - valOut = float(frame) * a; - return false; -} - -int CIETimeScale::GetMaxValue() const -{ - return 10000; /* Assume 10000 frames max (not ideal estimate) */ -} - -bool CIEGetCumulativeParticleCount::GetValue(int frame, int& valOut) const -{ - valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetCumulativeParticleCount(); - return false; -} - -int CIEGetCumulativeParticleCount::GetMaxValue() const -{ - return 256; -} - -bool CIEGetActiveParticleCount::GetValue(int frame, int &valOut) const -{ - valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetParticleCount(); - return false; -} - -int CIEGetActiveParticleCount::GetMaxValue() const -{ - return 256; -} - -bool CIEGetEmitterTime::GetValue(int frame, int &valOut) const -{ - valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetEmitterTime(); - return false; -} - -int CIEGetEmitterTime::GetMaxValue() const -{ - return 10000; /* Assume 10000 frames max (not ideal estimate) */ -} - -bool CIEModulo::GetValue(int frame, int& valOut) const -{ - int a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - if (b != 0) - valOut = a % b; - else - valOut = a; - return false; -} - -int CIEModulo::GetMaxValue() const -{ - int a, b; - a = x4_a->GetMaxValue(); - b = x8_b->GetMaxValue(); - if (b != 0) - return b - 1; - else - return a; -} - -bool CIESubtract::GetValue(int frame, int& valOut) const -{ - int a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = a - b; - return false; -} - -int CIESubtract::GetMaxValue() const -{ - int a, b; - a = x4_a->GetMaxValue(); - b = x8_b->GetMaxValue(); - return a - b; -} - -} +} // namespace urde diff --git a/Runtime/Particle/CIntElement.hpp b/Runtime/Particle/CIntElement.hpp index 3eb2bd9c7..63da02e50 100644 --- a/Runtime/Particle/CIntElement.hpp +++ b/Runtime/Particle/CIntElement.hpp @@ -4,213 +4,203 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Int_Elements */ -namespace urde -{ +namespace urde { + +class CIEKeyframeEmitter : public CIntElement { + u32 x4_percent; + u32 x8_unk1; + bool xc_loop; + bool xd_unk2; + u32 x10_loopEnd; + u32 x14_loopStart; + std::vector x18_keys; -class CIEKeyframeEmitter : public CIntElement -{ - u32 x4_percent; - u32 x8_unk1; - bool xc_loop; - bool xd_unk2; - u32 x10_loopEnd; - u32 x14_loopStart; - std::vector x18_keys; public: - CIEKeyframeEmitter(CInputStream& in); - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEKeyframeEmitter(CInputStream& in); + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEDeath : public CIntElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CIEDeath : public CIntElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CIEDeath(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEDeath(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEClamp : public CIntElement -{ - std::unique_ptr x4_min; - std::unique_ptr x8_max; - std::unique_ptr xc_val; +class CIEClamp : public CIntElement { + std::unique_ptr x4_min; + std::unique_ptr x8_max; + std::unique_ptr xc_val; + public: - CIEClamp(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) - : x4_min(std::move(a)), x8_max(std::move(b)), xc_val(std::move(c)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEClamp(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_min(std::move(a)), x8_max(std::move(b)), xc_val(std::move(c)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIETimeChain : public CIntElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_swFrame; +class CIETimeChain : public CIntElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_swFrame; + public: - CIETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEAdd : public CIntElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CIEAdd : public CIntElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CIEAdd(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEAdd(std::unique_ptr&& a, std::unique_ptr&& b) : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEConstant : public CIntElement -{ - int x4_val; +class CIEConstant : public CIntElement { + int x4_val; + public: - CIEConstant(int val) : x4_val(val) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEConstant(int val) : x4_val(val) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEImpulse : public CIntElement -{ - std::unique_ptr x4_a; +class CIEImpulse : public CIntElement { + std::unique_ptr x4_a; + public: - CIEImpulse(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEImpulse(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIELifetimePercent : public CIntElement -{ - std::unique_ptr x4_percentVal; +class CIELifetimePercent : public CIntElement { + std::unique_ptr x4_percentVal; + public: - CIELifetimePercent(std::unique_ptr&& a) - : x4_percentVal(std::move(a)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIELifetimePercent(std::unique_ptr&& a) : x4_percentVal(std::move(a)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEInitialRandom : public CIntElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CIEInitialRandom : public CIntElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CIEInitialRandom(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEInitialRandom(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEPulse : public CIntElement -{ - std::unique_ptr x4_aDuration; - std::unique_ptr x8_bDuration; - std::unique_ptr xc_aVal; - std::unique_ptr x10_bVal; +class CIEPulse : public CIntElement { + std::unique_ptr x4_aDuration; + std::unique_ptr x8_bDuration; + std::unique_ptr xc_aVal; + std::unique_ptr x10_bVal; + public: - CIEPulse(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d) - : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_aVal(std::move(c)), x10_bVal(std::move(d)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEPulse(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d) + : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_aVal(std::move(c)), x10_bVal(std::move(d)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEMultiply : public CIntElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CIEMultiply : public CIntElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CIEMultiply(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEMultiply(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIESampleAndHold : public CIntElement -{ - std::unique_ptr x4_sampleSource; - int x8_nextSampleFrame = 0; - std::unique_ptr xc_waitFramesMin; - std::unique_ptr x10_waitFramesMax; - int x14_holdVal; +class CIESampleAndHold : public CIntElement { + std::unique_ptr x4_sampleSource; + int x8_nextSampleFrame = 0; + std::unique_ptr xc_waitFramesMin; + std::unique_ptr x10_waitFramesMax; + int x14_holdVal; + public: - CIESampleAndHold(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c) - : x4_sampleSource(std::move(a)), xc_waitFramesMin(std::move(b)), x10_waitFramesMax(std::move(c)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIESampleAndHold(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_sampleSource(std::move(a)), xc_waitFramesMin(std::move(b)), x10_waitFramesMax(std::move(c)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIERandom : public CIntElement -{ - std::unique_ptr x4_min; - std::unique_ptr x8_max; +class CIERandom : public CIntElement { + std::unique_ptr x4_min; + std::unique_ptr x8_max; + public: - CIERandom(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_min(std::move(a)), x8_max(std::move(b)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIERandom(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_min(std::move(a)), x8_max(std::move(b)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIETimeScale : public CIntElement -{ - std::unique_ptr x4_a; +class CIETimeScale : public CIntElement { + std::unique_ptr x4_a; + public: - CIETimeScale(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIETimeScale(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEGetCumulativeParticleCount : public CIntElement -{ +class CIEGetCumulativeParticleCount : public CIntElement { public: - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEGetActiveParticleCount : public CIntElement -{ +class CIEGetActiveParticleCount : public CIntElement { public: - bool GetValue(int frame, int &valOut) const; - int GetMaxValue() const; + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEGetEmitterTime : public CIntElement -{ +class CIEGetEmitterTime : public CIntElement { public: - bool GetValue(int frame, int &valOut) const; - int GetMaxValue() const; + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIEModulo : public CIntElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CIEModulo : public CIntElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CIEModulo(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIEModulo(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -class CIESubtract : public CIntElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CIESubtract : public CIntElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CIESubtract(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, int& valOut) const; - int GetMaxValue() const; + CIESubtract(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, int& valOut) const; + int GetMaxValue() const; }; -} - +} // namespace urde diff --git a/Runtime/Particle/CModVectorElement.cpp b/Runtime/Particle/CModVectorElement.cpp index 55bdd05fb..be1fd9bb5 100644 --- a/Runtime/Particle/CModVectorElement.cpp +++ b/Runtime/Particle/CModVectorElement.cpp @@ -5,255 +5,237 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Mod_Vector_Elements */ -namespace urde -{ +namespace urde { -bool CMVEImplosion::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const -{ - zeus::CVector3f av; - x4_implPoint->GetValue(frame, av); +bool CMVEImplosion::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const { + zeus::CVector3f av; + x4_implPoint->GetValue(frame, av); - zeus::CVector3f dv = av - pPos; - float dvm = dv.magnitude(); + zeus::CVector3f dv = av - pPos; + float dvm = dv.magnitude(); - float c; - xc_maxMag->GetValue(frame, c); - if (dvm > c) - return false; - - float d; - x10_minMag->GetValue(frame, d); - if (x14_enableMinMag && dvm < d) - return true; - - if (0.f == dvm) - return false; - - float b; - x8_magScale->GetValue(frame, b); - pVel += zeus::CVector3f(b / dvm) * dv; + float c; + xc_maxMag->GetValue(frame, c); + if (dvm > c) return false; + + float d; + x10_minMag->GetValue(frame, d); + if (x14_enableMinMag && dvm < d) + return true; + + if (0.f == dvm) + return false; + + float b; + x8_magScale->GetValue(frame, b); + pVel += zeus::CVector3f(b / dvm) * dv; + return false; } -bool CMVEExponentialImplosion::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const -{ - zeus::CVector3f av; - x4_implPoint->GetValue(frame, av); +bool CMVEExponentialImplosion::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const { + zeus::CVector3f av; + x4_implPoint->GetValue(frame, av); - zeus::CVector3f dv = av - pPos; - float dvm = dv.magnitude(); + zeus::CVector3f dv = av - pPos; + float dvm = dv.magnitude(); - float c; - xc_maxMag->GetValue(frame, c); - if (dvm > c) - return false; - - float d; - x10_minMag->GetValue(frame, d); - if (x14_enableMinMag && dvm < d) - return true; - - if (0.f == dvm) - return false; - - float b; - x8_magScale->GetValue(frame, b); - pVel += zeus::CVector3f(b) * dv; + float c; + xc_maxMag->GetValue(frame, c); + if (dvm > c) return false; + + float d; + x10_minMag->GetValue(frame, d); + if (x14_enableMinMag && dvm < d) + return true; + + if (0.f == dvm) + return false; + + float b; + x8_magScale->GetValue(frame, b); + pVel += zeus::CVector3f(b) * dv; + return false; } -bool CMVELinearImplosion::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const -{ - zeus::CVector3f av; - x4_implPoint->GetValue(frame, av); +bool CMVELinearImplosion::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const { + zeus::CVector3f av; + x4_implPoint->GetValue(frame, av); - zeus::CVector3f dv = av - pPos; - float dvm = dv.magnitude(); + zeus::CVector3f dv = av - pPos; + float dvm = dv.magnitude(); - float c; - xc_maxMag->GetValue(frame, c); - if (dvm > c) - return false; - - float d; - x10_minMag->GetValue(frame, d); - if (x14_enableMinMag && dvm < d) - return true; - - if (0.f == dvm) - return false; - - float b; - x8_magScale->GetValue(frame, b); - pVel = zeus::CVector3f(b / dvm) * dv; + float c; + xc_maxMag->GetValue(frame, c); + if (dvm > c) return false; + + float d; + x10_minMag->GetValue(frame, d); + if (x14_enableMinMag && dvm < d) + return true; + + if (0.f == dvm) + return false; + + float b; + x8_magScale->GetValue(frame, b); + pVel = zeus::CVector3f(b / dvm) * dv; + return false; } -bool CMVETimeChain::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const -{ - int v; - xc_swFrame->GetValue(frame, v); - if (frame >= v) - return x8_b->GetValue(frame, pVel, pPos); - else - return x4_a->GetValue(frame, pVel, pPos); +bool CMVETimeChain::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const { + int v; + xc_swFrame->GetValue(frame, v); + if (frame >= v) + return x8_b->GetValue(frame, pVel, pPos); + else + return x4_a->GetValue(frame, pVel, pPos); } CMVEBounce::CMVEBounce(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, std::unique_ptr&& d, bool e) -: x4_planePoint(std::move(a)), x8_planeNormal(std::move(b)), xc_friction(std::move(c)), - x10_restitution(std::move(d)), x14_planePrecomputed(false), x15_dieOnPenetrate(e), x24_planeD(0.0) -{ - if (x4_planePoint && x8_planeNormal && x4_planePoint->IsFastConstant() && x8_planeNormal->IsFastConstant()) - { - /* Precompute Hesse normal form of plane (for penetration testing) - * https://en.wikipedia.org/wiki/Hesse_normal_form */ - x14_planePrecomputed = true; - x8_planeNormal->GetValue(0, x18_planeValidatedNormal); +: x4_planePoint(std::move(a)) +, x8_planeNormal(std::move(b)) +, xc_friction(std::move(c)) +, x10_restitution(std::move(d)) +, x14_planePrecomputed(false) +, x15_dieOnPenetrate(e) +, x24_planeD(0.0) { + if (x4_planePoint && x8_planeNormal && x4_planePoint->IsFastConstant() && x8_planeNormal->IsFastConstant()) { + /* Precompute Hesse normal form of plane (for penetration testing) + * https://en.wikipedia.org/wiki/Hesse_normal_form */ + x14_planePrecomputed = true; + x8_planeNormal->GetValue(0, x18_planeValidatedNormal); - if (x18_planeValidatedNormal.magSquared() > 0.0) - x18_planeValidatedNormal.normalize(); - zeus::CVector3f a; - x4_planePoint->GetValue(0, a); - x24_planeD = x18_planeValidatedNormal.dot(a); - } + if (x18_planeValidatedNormal.magSquared() > 0.0) + x18_planeValidatedNormal.normalize(); + zeus::CVector3f a; + x4_planePoint->GetValue(0, a); + x24_planeD = x18_planeValidatedNormal.dot(a); + } } -bool CMVEBounce::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const -{ - if (!x14_planePrecomputed) - { - /* Compute Hesse normal form of plane (for penetration testing) */ - x8_planeNormal->GetValue(frame, const_cast(x18_planeValidatedNormal)); - const_cast(x18_planeValidatedNormal).normalize(); +bool CMVEBounce::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const { + if (!x14_planePrecomputed) { + /* Compute Hesse normal form of plane (for penetration testing) */ + x8_planeNormal->GetValue(frame, const_cast(x18_planeValidatedNormal)); + const_cast(x18_planeValidatedNormal).normalize(); - zeus::CVector3f a; - x4_planePoint->GetValue(frame, a); + zeus::CVector3f a; + x4_planePoint->GetValue(frame, a); - const_cast(x24_planeD) = x18_planeValidatedNormal.dot(a); - } + const_cast(x24_planeD) = x18_planeValidatedNormal.dot(a); + } - float dot = x18_planeValidatedNormal.dot(pPos); - if (dot - x24_planeD > 0.0f) - return false; - else if (x15_dieOnPenetrate) - return true; - - /* Deflection event */ - - if (pVel.dot(x18_planeValidatedNormal) >= 0.0f) - return false; - - zeus::CVector3f delta = pPos - pVel; - pPos += (-(delta.dot(x18_planeValidatedNormal) - x24_planeD) / pVel.dot(x18_planeValidatedNormal) - 1.f) * pVel; - - float d = 0.0f; - x10_restitution->GetValue(frame, d); - pVel -= d * pVel; - - float c = 0.0f; - xc_friction->GetValue(frame, c); - pVel -= (1.f + c) * x18_planeValidatedNormal.dot(pVel) * x18_planeValidatedNormal; + float dot = x18_planeValidatedNormal.dot(pPos); + if (dot - x24_planeD > 0.0f) return false; -} + else if (x15_dieOnPenetrate) + return true; -bool CMVEConstant::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const -{ - float x, y, z; - x4_x->GetValue(frame, x); - x8_y->GetValue(frame, y); - xc_z->GetValue(frame, z); - pVel.assign(x, y, z); + /* Deflection event */ + + if (pVel.dot(x18_planeValidatedNormal) >= 0.0f) return false; + + zeus::CVector3f delta = pPos - pVel; + pPos += (-(delta.dot(x18_planeValidatedNormal) - x24_planeD) / pVel.dot(x18_planeValidatedNormal) - 1.f) * pVel; + + float d = 0.0f; + x10_restitution->GetValue(frame, d); + pVel -= d * pVel; + + float c = 0.0f; + xc_friction->GetValue(frame, c); + pVel -= (1.f + c) * x18_planeValidatedNormal.dot(pVel) * x18_planeValidatedNormal; + return false; } -bool CMVEFastConstant::GetValue(int /*frame*/, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const -{ - pVel = x4_val; - return false; +bool CMVEConstant::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const { + float x, y, z; + x4_x->GetValue(frame, x); + x8_y->GetValue(frame, y); + xc_z->GetValue(frame, z); + pVel.assign(x, y, z); + return false; } -bool CMVEGravity::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const -{ - zeus::CVector3f grav; - x4_a->GetValue(frame, grav); - pVel += grav; - return false; +bool CMVEFastConstant::GetValue(int /*frame*/, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const { + pVel = x4_val; + return false; } -bool CMVEExplode::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const -{ - if (frame == 0) - { - CRandom16* rand = CRandom16::GetRandomNumber(); - zeus::CVector3f vec = {rand->Float() - 0.5f, rand->Float() - 0.5f, rand->Float() - 0.5f}; - vec.normalize(); - float a; - x4_a->GetValue(frame, a); - pVel = vec * a; - } +bool CMVEGravity::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const { + zeus::CVector3f grav; + x4_a->GetValue(frame, grav); + pVel += grav; + return false; +} + +bool CMVEExplode::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const { + if (frame == 0) { + CRandom16* rand = CRandom16::GetRandomNumber(); + zeus::CVector3f vec = {rand->Float() - 0.5f, rand->Float() - 0.5f, rand->Float() - 0.5f}; + vec.normalize(); + float a; + x4_a->GetValue(frame, a); + pVel = vec * a; + } else { + float b; + x8_b->GetValue(frame, b); + pVel *= zeus::CVector3f(b); + } + + return false; +} + +bool CMVESetPosition::GetValue(int frame, zeus::CVector3f& /*pVel*/, zeus::CVector3f& pPos) const { + x4_a->GetValue(frame, pPos); + return false; +} + +bool CMVEPulse::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const { + int a, b; + x4_aDuration->GetValue(frame, a); + x8_bDuration->GetValue(frame, b); + int cv = std::max(1, a + b + 1); + + if (b >= 1) { + int cv2 = frame % cv; + if (cv2 >= a) + x10_bVal->GetValue(frame, pVel, pPos); else - { - float b; - x8_b->GetValue(frame, b); - pVel *= zeus::CVector3f(b); - } + xc_aVal->GetValue(frame, pVel, pPos); + } else + xc_aVal->GetValue(frame, pVel, pPos); - return false; + return false; } -bool CMVESetPosition::GetValue(int frame, zeus::CVector3f& /*pVel*/, zeus::CVector3f& pPos) const -{ - x4_a->GetValue(frame, pPos); - return false; +bool CMVEWind::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const { + zeus::CVector3f wVel; + x4_velocity->GetValue(frame, wVel); + float factor; + x8_factor->GetValue(frame, factor); + pVel += (wVel - pVel) * factor; + return false; } -bool CMVEPulse::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const -{ - int a, b; - x4_aDuration->GetValue(frame, a); - x8_bDuration->GetValue(frame, b); - int cv = std::max(1, a + b + 1); +bool CMVESwirl::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const { + zeus::CVector3f a, b; + x4_helixPoint->GetValue(frame, a); + x8_curveBinormal->GetValue(frame, b); - if (b >= 1) - { - int cv2 = frame % cv; - if (cv2 >= a) - x10_bVal->GetValue(frame, pVel, pPos); - else - xc_aVal->GetValue(frame, pVel, pPos); - } - else - xc_aVal->GetValue(frame, pVel, pPos); - - return false; + const zeus::CVector3f posToOrigin = a - pPos; + const zeus::CVector3f posToHelix = posToOrigin - posToOrigin.dot(b) * b; + float c = 0.0f, d = 0.0f; + xc_filterGain->GetValue(frame, c); + x10_tangentialVelocity->GetValue(frame, d); + const zeus::CVector3f wetVel = (posToHelix.cross(b) * d + b * b.dot(pVel)); + pVel = c * wetVel + (1.f - c) * pVel; + return false; } -bool CMVEWind::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& /*pPos*/) const -{ - zeus::CVector3f wVel; - x4_velocity->GetValue(frame, wVel); - float factor; - x8_factor->GetValue(frame, factor); - pVel += (wVel - pVel) * factor; - return false; -} - -bool CMVESwirl::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const -{ - zeus::CVector3f a, b; - x4_helixPoint->GetValue(frame, a); - x8_curveBinormal->GetValue(frame, b); - - const zeus::CVector3f posToOrigin = a - pPos; - const zeus::CVector3f posToHelix = posToOrigin - posToOrigin.dot(b) * b; - float c = 0.0f, d = 0.0f; - xc_filterGain->GetValue(frame, c); - x10_tangentialVelocity->GetValue(frame, d); - const zeus::CVector3f wetVel = (posToHelix.cross(b) * d + b * b.dot(pVel)); - pVel = c * wetVel + (1.f - c) * pVel; - return false; -} - - -} +} // namespace urde diff --git a/Runtime/Particle/CModVectorElement.hpp b/Runtime/Particle/CModVectorElement.hpp index 771fb6cb8..963e7333c 100644 --- a/Runtime/Particle/CModVectorElement.hpp +++ b/Runtime/Particle/CModVectorElement.hpp @@ -4,167 +4,172 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Mod_Vector_Elements */ -namespace urde -{ +namespace urde { + +class CMVEImplosion : public CModVectorElement { + std::unique_ptr x4_implPoint; + std::unique_ptr x8_magScale; + std::unique_ptr xc_maxMag; + std::unique_ptr x10_minMag; + bool x14_enableMinMag; -class CMVEImplosion : public CModVectorElement -{ - std::unique_ptr x4_implPoint; - std::unique_ptr x8_magScale; - std::unique_ptr xc_maxMag; - std::unique_ptr x10_minMag; - bool x14_enableMinMag; public: - CMVEImplosion(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d, bool e) - : x4_implPoint(std::move(a)), x8_magScale(std::move(b)), xc_maxMag(std::move(c)), x10_minMag(std::move(d)), - x14_enableMinMag(std::move(e)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVEImplosion(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c, std::unique_ptr&& d, bool e) + : x4_implPoint(std::move(a)) + , x8_magScale(std::move(b)) + , xc_maxMag(std::move(c)) + , x10_minMag(std::move(d)) + , x14_enableMinMag(std::move(e)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVEExponentialImplosion : public CModVectorElement -{ - std::unique_ptr x4_implPoint; - std::unique_ptr x8_magScale; - std::unique_ptr xc_maxMag; - std::unique_ptr x10_minMag; - bool x14_enableMinMag; +class CMVEExponentialImplosion : public CModVectorElement { + std::unique_ptr x4_implPoint; + std::unique_ptr x8_magScale; + std::unique_ptr xc_maxMag; + std::unique_ptr x10_minMag; + bool x14_enableMinMag; + public: - CMVEExponentialImplosion(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d, bool e) - : x4_implPoint(std::move(a)), x8_magScale(std::move(b)), xc_maxMag(std::move(c)), x10_minMag(std::move(d)), - x14_enableMinMag(std::move(e)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVEExponentialImplosion(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c, std::unique_ptr&& d, bool e) + : x4_implPoint(std::move(a)) + , x8_magScale(std::move(b)) + , xc_maxMag(std::move(c)) + , x10_minMag(std::move(d)) + , x14_enableMinMag(std::move(e)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVELinearImplosion : public CModVectorElement -{ - std::unique_ptr x4_implPoint; - std::unique_ptr x8_magScale; - std::unique_ptr xc_maxMag; - std::unique_ptr x10_minMag; - bool x14_enableMinMag; +class CMVELinearImplosion : public CModVectorElement { + std::unique_ptr x4_implPoint; + std::unique_ptr x8_magScale; + std::unique_ptr xc_maxMag; + std::unique_ptr x10_minMag; + bool x14_enableMinMag; + public: - CMVELinearImplosion(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d, bool e) - : x4_implPoint(std::move(a)), x8_magScale(std::move(b)), xc_maxMag(std::move(c)), x10_minMag(std::move(d)), - x14_enableMinMag(std::move(e)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVELinearImplosion(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c, std::unique_ptr&& d, bool e) + : x4_implPoint(std::move(a)) + , x8_magScale(std::move(b)) + , xc_maxMag(std::move(c)) + , x10_minMag(std::move(d)) + , x14_enableMinMag(std::move(e)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVETimeChain : public CModVectorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_swFrame; +class CMVETimeChain : public CModVectorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_swFrame; + public: - CMVETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c) + : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVEBounce : public CModVectorElement -{ - std::unique_ptr x4_planePoint; - std::unique_ptr x8_planeNormal; - std::unique_ptr xc_friction; - std::unique_ptr x10_restitution; - bool x14_planePrecomputed; - bool x15_dieOnPenetrate; - zeus::CVector3f x18_planeValidatedNormal; - float x24_planeD; +class CMVEBounce : public CModVectorElement { + std::unique_ptr x4_planePoint; + std::unique_ptr x8_planeNormal; + std::unique_ptr xc_friction; + std::unique_ptr x10_restitution; + bool x14_planePrecomputed; + bool x15_dieOnPenetrate; + zeus::CVector3f x18_planeValidatedNormal; + float x24_planeD; + public: - CMVEBounce(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d, bool e); - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVEBounce(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c, std::unique_ptr&& d, bool e); + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVEConstant : public CModVectorElement -{ - std::unique_ptr x4_x; - std::unique_ptr x8_y; - std::unique_ptr xc_z; +class CMVEConstant : public CModVectorElement { + std::unique_ptr x4_x; + std::unique_ptr x8_y; + std::unique_ptr xc_z; + public: - CMVEConstant(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c) - : x4_x(std::move(a)), x8_y(std::move(b)), xc_z(std::move(c)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVEConstant(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_x(std::move(a)), x8_y(std::move(b)), xc_z(std::move(c)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVEFastConstant : public CModVectorElement -{ - zeus::CVector3f x4_val; +class CMVEFastConstant : public CModVectorElement { + zeus::CVector3f x4_val; + public: - CMVEFastConstant(float a, float b, float c) - : x4_val(a, b, c) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVEFastConstant(float a, float b, float c) : x4_val(a, b, c) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVEGravity : public CModVectorElement -{ - std::unique_ptr x4_a; +class CMVEGravity : public CModVectorElement { + std::unique_ptr x4_a; + public: - CMVEGravity(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVEGravity(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVEExplode : public CModVectorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CMVEExplode : public CModVectorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CMVEExplode(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVEExplode(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVESetPosition : public CModVectorElement -{ - std::unique_ptr x4_a; +class CMVESetPosition : public CModVectorElement { + std::unique_ptr x4_a; + public: - CMVESetPosition(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVESetPosition(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVEPulse : public CModVectorElement -{ - std::unique_ptr x4_aDuration; - std::unique_ptr x8_bDuration; - std::unique_ptr xc_aVal; - std::unique_ptr x10_bVal; +class CMVEPulse : public CModVectorElement { + std::unique_ptr x4_aDuration; + std::unique_ptr x8_bDuration; + std::unique_ptr xc_aVal; + std::unique_ptr x10_bVal; + public: - CMVEPulse(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d) - : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_aVal(std::move(c)), x10_bVal(std::move(d)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVEPulse(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d) + : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_aVal(std::move(c)), x10_bVal(std::move(d)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVEWind : public CModVectorElement -{ - std::unique_ptr x4_velocity; - std::unique_ptr x8_factor; +class CMVEWind : public CModVectorElement { + std::unique_ptr x4_velocity; + std::unique_ptr x8_factor; + public: - CMVEWind(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_velocity(std::move(a)), x8_factor(std::move(b)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVEWind(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_velocity(std::move(a)), x8_factor(std::move(b)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -class CMVESwirl : public CModVectorElement -{ - std::unique_ptr x4_helixPoint; - std::unique_ptr x8_curveBinormal; - std::unique_ptr xc_filterGain; - std::unique_ptr x10_tangentialVelocity; +class CMVESwirl : public CModVectorElement { + std::unique_ptr x4_helixPoint; + std::unique_ptr x8_curveBinormal; + std::unique_ptr xc_filterGain; + std::unique_ptr x10_tangentialVelocity; + public: - CMVESwirl(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d) - : x4_helixPoint(std::move(a)), x8_curveBinormal(std::move(b)), - xc_filterGain(std::move(c)), x10_tangentialVelocity(std::move(d)) {} - bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; + CMVESwirl(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d) + : x4_helixPoint(std::move(a)) + , x8_curveBinormal(std::move(b)) + , xc_filterGain(std::move(c)) + , x10_tangentialVelocity(std::move(d)) {} + bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const; }; -} - +} // namespace urde diff --git a/Runtime/Particle/CParticleDataFactory.cpp b/Runtime/Particle/CParticleDataFactory.cpp index bf92b710a..f464591bf 100644 --- a/Runtime/Particle/CParticleDataFactory.cpp +++ b/Runtime/Particle/CParticleDataFactory.cpp @@ -7,1177 +7,1025 @@ #include "CSwooshDescription.hpp" #include "CElectricDescription.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CParticleDataFactory"); -float CParticleDataFactory::GetReal(CInputStream& in) -{ - return in.readFloatBig(); +float CParticleDataFactory::GetReal(CInputStream& in) { return in.readFloatBig(); } + +s32 CParticleDataFactory::GetInt(CInputStream& in) { return in.readInt32Big(); } + +bool CParticleDataFactory::GetBool(CInputStream& in) { + FourCC cid = GetClassID(in); + if (cid != FOURCC('CNST')) + Log.report(logvisor::Fatal, "bool element does not begin with CNST"); + return in.readBool(); } -s32 CParticleDataFactory::GetInt(CInputStream& in) -{ - return in.readInt32Big(); +FourCC CParticleDataFactory::GetClassID(CInputStream& in) { + uint32_t val; + in.readBytesToBuf(&val, 4); + return val; } -bool CParticleDataFactory::GetBool(CInputStream& in) -{ - FourCC cid = GetClassID(in); - if (cid != FOURCC('CNST')) - Log.report(logvisor::Fatal, "bool element does not begin with CNST"); - return in.readBool(); -} - -FourCC CParticleDataFactory::GetClassID(CInputStream& in) -{ - uint32_t val; - in.readBytesToBuf(&val, 4); - return val; -} - -SParticleModel CParticleDataFactory::GetModel(CInputStream& in, CSimplePool* resPool) -{ - FourCC clsId = GetClassID(in); - if (clsId == SBIG('NONE')) - return {}; - CAssetId id = in.readUint32Big(); - if (!id.IsValid()) - return {}; - return {resPool->GetObj({FOURCC('CMDL'), id}), true}; +SParticleModel CParticleDataFactory::GetModel(CInputStream& in, CSimplePool* resPool) { + FourCC clsId = GetClassID(in); + if (clsId == SBIG('NONE')) + return {}; + CAssetId id = in.readUint32Big(); + if (!id.IsValid()) + return {}; + return {resPool->GetObj({FOURCC('CMDL'), id}), true}; } SChildGeneratorDesc CParticleDataFactory::GetChildGeneratorDesc(CAssetId res, CSimplePool* resPool, - const std::vector& tracker) -{ - if (std::count(tracker.cbegin(), tracker.cend(), res) == 0) - return {resPool->GetObj({FOURCC('PART'), res}), true}; - return {}; + const std::vector& tracker) { + if (std::count(tracker.cbegin(), tracker.cend(), res) == 0) + return {resPool->GetObj({FOURCC('PART'), res}), true}; + return {}; } SChildGeneratorDesc CParticleDataFactory::GetChildGeneratorDesc(CInputStream& in, CSimplePool* resPool, - const std::vector& tracker) -{ - FourCC clsId = GetClassID(in); - if (clsId == SBIG('NONE')) - return {}; + const std::vector& tracker) { + FourCC clsId = GetClassID(in); + if (clsId == SBIG('NONE')) + return {}; + CAssetId id = in.readUint32Big(); + if (!id.IsValid()) + return {}; + return GetChildGeneratorDesc(id, resPool, tracker); +} + +SSwooshGeneratorDesc CParticleDataFactory::GetSwooshGeneratorDesc(CInputStream& in, CSimplePool* resPool) { + FourCC clsId = GetClassID(in); + if (clsId == SBIG('NONE')) + return {}; + CAssetId id = in.readUint32Big(); + if (!id.IsValid()) + return {}; + return {resPool->GetObj({FOURCC('SWHC'), id}), true}; +} + +SElectricGeneratorDesc CParticleDataFactory::GetElectricGeneratorDesc(CInputStream& in, CSimplePool* resPool) { + FourCC clsId = GetClassID(in); + if (clsId == SBIG('NONE')) + return {}; + CAssetId id = in.readUint32Big(); + if (!id.IsValid()) + return {}; + return {resPool->GetObj({FOURCC('ELSC'), id}), true}; +} + +std::unique_ptr CParticleDataFactory::GetTextureElement(CInputStream& in, CSimplePool* resPool) { + FourCC clsId = GetClassID(in); + switch (clsId) { + case SBIG('CNST'): { + FourCC subId = GetClassID(in); + if (subId == SBIG('NONE')) + return nullptr; CAssetId id = in.readUint32Big(); - if (!id.IsValid()) - return {}; - return GetChildGeneratorDesc(id, resPool, tracker); -} - -SSwooshGeneratorDesc CParticleDataFactory::GetSwooshGeneratorDesc(CInputStream& in, CSimplePool* resPool) -{ - FourCC clsId = GetClassID(in); - if (clsId == SBIG('NONE')) - return {}; + TToken txtr = resPool->GetObj({FOURCC('TXTR'), id}); + return std::make_unique(std::move(txtr)); + } + case SBIG('ATEX'): { + FourCC subId = GetClassID(in); + if (subId == SBIG('NONE')) + return nullptr; CAssetId id = in.readUint32Big(); - if (!id.IsValid()) - return {}; - return {resPool->GetObj({FOURCC('SWHC'), id}), true}; + auto a = GetIntElement(in); + auto b = GetIntElement(in); + auto c = GetIntElement(in); + auto d = GetIntElement(in); + auto e = GetIntElement(in); + bool f = GetBool(in); + TToken txtr = resPool->GetObj({FOURCC('TXTR'), id}); + return std::make_unique(std::move(txtr), std::move(std::move(a)), std::move(b), std::move(c), + std::move(d), std::move(e), std::move(f)); + } + default: + break; + } + return nullptr; } -SElectricGeneratorDesc CParticleDataFactory::GetElectricGeneratorDesc(CInputStream& in, CSimplePool* resPool) -{ - FourCC clsId = GetClassID(in); - if (clsId == SBIG('NONE')) - return {}; - CAssetId id = in.readUint32Big(); - if (!id.IsValid()) - return {}; - return {resPool->GetObj({FOURCC('ELSC'), id}), true}; +std::unique_ptr CParticleDataFactory::GetColorElement(CInputStream& in) { + FourCC clsId = GetClassID(in); + switch (clsId) { + case SBIG('KEYE'): + case SBIG('KEYP'): { + return std::make_unique(in); + } + case SBIG('CNST'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + if (a->IsConstant() && b->IsConstant() && c->IsConstant() && d->IsConstant()) { + float af, bf, cf, df; + a->GetValue(0, af); + b->GetValue(0, bf); + c->GetValue(0, cf); + d->GetValue(0, df); + return std::make_unique(af, bf, cf, df); + } else { + return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c), std::move(d)); + } + } + case SBIG('CHAN'): { + auto a = GetColorElement(in); + auto b = GetColorElement(in); + auto c = GetIntElement(in); + return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c)); + } + case SBIG('CFDE'): { + auto a = GetColorElement(in); + auto b = GetColorElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c), std::move(d)); + } + case SBIG('FADE'): { + auto a = GetColorElement(in); + auto b = GetColorElement(in); + auto c = GetRealElement(in); + return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c)); + } + case SBIG('PULS'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + auto c = GetColorElement(in); + auto d = GetColorElement(in); + return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c), std::move(d)); + } + case SBIG('PCOL'): { + return std::make_unique(); + } + default: + break; + } + return nullptr; } -std::unique_ptr CParticleDataFactory::GetTextureElement(CInputStream& in, CSimplePool* resPool) -{ - FourCC clsId = GetClassID(in); - switch (clsId) - { - case SBIG('CNST'): - { - FourCC subId = GetClassID(in); - if (subId == SBIG('NONE')) - return nullptr; - CAssetId id = in.readUint32Big(); - TToken txtr = resPool->GetObj({FOURCC('TXTR'), id}); - return std::make_unique(std::move(txtr)); +std::unique_ptr CParticleDataFactory::GetModVectorElement(CInputStream& in) { + FourCC clsId = GetClassID(in); + switch (clsId) { + case SBIG('IMPL'): { + auto a = GetVectorElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + bool e = GetBool(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); + } + case SBIG('EMPL'): { + auto a = GetVectorElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + bool e = GetBool(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), + std::move(e)); + } + case SBIG('CHAN'): { + auto a = GetModVectorElement(in); + auto b = GetModVectorElement(in); + auto c = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c)); + } + case SBIG('BNCE'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + bool e = GetBool(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); + } + case SBIG('CNST'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + if (a->IsConstant() && b->IsConstant() && c->IsConstant()) { + float af, bf, cf; + a->GetValue(0, af); + b->GetValue(0, bf); + c->GetValue(0, cf); + return std::make_unique(af, bf, cf); + } else { + return std::make_unique(std::move(a), std::move(b), std::move(c)); } - case SBIG('ATEX'): - { - FourCC subId = GetClassID(in); - if (subId == SBIG('NONE')) - return nullptr; - CAssetId id = in.readUint32Big(); - auto a = GetIntElement(in); - auto b = GetIntElement(in); - auto c = GetIntElement(in); - auto d = GetIntElement(in); - auto e = GetIntElement(in); - bool f = GetBool(in); - TToken txtr = resPool->GetObj({FOURCC('TXTR'), id}); - return std::make_unique(std::move(txtr), std::move(std::move(a)), std::move(b), std::move(c), - std::move(d), std::move(e), std::move(f)); - } - default: break; - } - return nullptr; + } + case SBIG('GRAV'): { + auto a = GetVectorElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('EXPL'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('SPOS'): { + auto a = GetVectorElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('LMPL'): { + auto a = GetVectorElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + bool e = GetBool(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); + } + case SBIG('PULS'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + auto c = GetModVectorElement(in); + auto d = GetModVectorElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); + } + case SBIG('WIND'): { + auto a = GetVectorElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('SWRL'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); + } + default: + break; + } + return nullptr; } -std::unique_ptr CParticleDataFactory::GetColorElement(CInputStream& in) -{ - FourCC clsId = GetClassID(in); - switch (clsId) - { - case SBIG('KEYE'): - case SBIG('KEYP'): - { - return std::make_unique(in); - } - case SBIG('CNST'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - if (a->IsConstant() && b->IsConstant() && c->IsConstant() && d->IsConstant()) - { - float af, bf, cf, df; - a->GetValue(0, af); - b->GetValue(0, bf); - c->GetValue(0, cf); - d->GetValue(0, df); - return std::make_unique(af, bf, cf, df); - } - else - { - return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c), std::move(d)); - } - } - case SBIG('CHAN'): - { - auto a = GetColorElement(in); - auto b = GetColorElement(in); - auto c = GetIntElement(in); - return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c)); - } - case SBIG('CFDE'): - { - auto a = GetColorElement(in); - auto b = GetColorElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c), std::move(d)); - } - case SBIG('FADE'): - { - auto a = GetColorElement(in); - auto b = GetColorElement(in); - auto c = GetRealElement(in); - return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c)); - } - case SBIG('PULS'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - auto c = GetColorElement(in); - auto d = GetColorElement(in); - return std::make_unique(std::move(std::move(a)), std::move(b), std::move(c), std::move(d)); - } - case SBIG('PCOL'): - { - return std::make_unique(); - } - default: break; - } - return nullptr; -} - -std::unique_ptr CParticleDataFactory::GetModVectorElement(CInputStream& in) -{ - FourCC clsId = GetClassID(in); - switch (clsId) - { - case SBIG('IMPL'): - { - auto a = GetVectorElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - bool e = GetBool(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); - } - case SBIG('EMPL'): - { - auto a = GetVectorElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - bool e = GetBool(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), - std::move(d), std::move(e)); - } - case SBIG('CHAN'): - { - auto a = GetModVectorElement(in); - auto b = GetModVectorElement(in); - auto c = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - case SBIG('BNCE'): - { - auto a = GetVectorElement(in); - auto b = GetVectorElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - bool e = GetBool(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); - } - case SBIG('CNST'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - if (a->IsConstant() && b->IsConstant() && c->IsConstant()) - { - float af, bf, cf; - a->GetValue(0, af); - b->GetValue(0, bf); - c->GetValue(0, cf); - return std::make_unique(af, bf, cf); - } - else - { - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - } - case SBIG('GRAV'): - { - auto a = GetVectorElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('EXPL'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('SPOS'): - { - auto a = GetVectorElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('LMPL'): - { - auto a = GetVectorElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - bool e = GetBool(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); - } - case SBIG('PULS'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - auto c = GetModVectorElement(in); - auto d = GetModVectorElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); - } - case SBIG('WIND'): - { - auto a = GetVectorElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('SWRL'): - { - auto a = GetVectorElement(in); - auto b = GetVectorElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); - } - default: break; - } - return nullptr; -} - -std::unique_ptr CParticleDataFactory::GetEmitterElement(CInputStream& in) -{ - FourCC clsId = GetClassID(in); - switch (clsId) - { - case SBIG('SETR'): - { - FourCC prop = GetClassID(in); - if (prop == SBIG('ILOC')) - { - auto a = GetVectorElement(in); - prop = GetClassID(in); - if (prop == SBIG('IVEC')) - { - auto b = GetVectorElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - } - return nullptr; - } - case SBIG('SEMR'): - { - auto a = GetVectorElement(in); +std::unique_ptr CParticleDataFactory::GetEmitterElement(CInputStream& in) { + FourCC clsId = GetClassID(in); + switch (clsId) { + case SBIG('SETR'): { + FourCC prop = GetClassID(in); + if (prop == SBIG('ILOC')) { + auto a = GetVectorElement(in); + prop = GetClassID(in); + if (prop == SBIG('IVEC')) { auto b = GetVectorElement(in); return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('SPHE'): - { - auto a = GetVectorElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - case SBIG('ASPH'): - { - auto a = GetVectorElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - auto e = GetRealElement(in); - auto f = GetRealElement(in); - auto g = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e), - std::move(f), std::move(g)); - } - default: break; + } } return nullptr; + } + case SBIG('SEMR'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('SPHE'): { + auto a = GetVectorElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c)); + } + case SBIG('ASPH'): { + auto a = GetVectorElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + auto e = GetRealElement(in); + auto f = GetRealElement(in); + auto g = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e), + std::move(f), std::move(g)); + } + default: + break; + } + return nullptr; } -std::unique_ptr CParticleDataFactory::GetVectorElement(CInputStream& in) -{ - FourCC clsId = GetClassID(in); - switch (clsId) - { - case SBIG('CONE'): - { - auto a = GetVectorElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); +std::unique_ptr CParticleDataFactory::GetVectorElement(CInputStream& in) { + FourCC clsId = GetClassID(in); + switch (clsId) { + case SBIG('CONE'): { + auto a = GetVectorElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('CHAN'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + auto c = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c)); + } + case SBIG('ANGC'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + auto e = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); + } + case SBIG('ADD_'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('CCLU'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + auto c = GetIntElement(in); + auto d = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); + } + case SBIG('CNST'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + if (a->IsConstant() && b->IsConstant() && c->IsConstant()) { + float af, bf, cf; + a->GetValue(0, af); + b->GetValue(0, bf); + c->GetValue(0, cf); + return std::make_unique(af, bf, cf); + } else { + return std::make_unique(std::move(a), std::move(b), std::move(c)); } - case SBIG('CHAN'): - { - auto a = GetVectorElement(in); - auto b = GetVectorElement(in); - auto c = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - case SBIG('ANGC'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - auto e = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); - } - case SBIG('ADD_'): - { - auto a = GetVectorElement(in); - auto b = GetVectorElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('CCLU'): - { - auto a = GetVectorElement(in); - auto b = GetVectorElement(in); - auto c = GetIntElement(in); - auto d = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); - } - case SBIG('CNST'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - if (a->IsConstant() && b->IsConstant() && c->IsConstant()) - { - float af, bf, cf; - a->GetValue(0, af); - b->GetValue(0, bf); - c->GetValue(0, cf); - return std::make_unique(af, bf, cf); - } - else - { - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - } - case SBIG('CIRC'): - { - auto a = GetVectorElement(in); - auto b = GetVectorElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - auto e = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); - } - case SBIG('KEYE'): - case SBIG('KEYP'): - { - return std::make_unique(in); - } - case SBIG('MULT'): - { - auto a = GetVectorElement(in); - auto b = GetVectorElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('RTOV'): - { - auto a = GetRealElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('PULS'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - auto c = GetVectorElement(in); - auto d = GetVectorElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); - } - case SBIG('PVEL'): - { - return std::make_unique(); - } - case SBIG('PLCO'): - { - return std::make_unique(); - } - case SBIG('PLOC'): - { - return std::make_unique(); - } - case SBIG('PSOF'): - { - return std::make_unique(); - } - case SBIG('PSOU'): - { - return std::make_unique(); - } - case SBIG('PSOR'): - { - return std::make_unique(); - } - case SBIG('PSTR'): - { - return std::make_unique(); - } - case SBIG('SUB_'): - { - auto a = GetVectorElement(in); - auto b = GetVectorElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('CTVC'): - { - auto a = GetColorElement(in); - return std::make_unique(std::move(a)); - } - default: break; - } - return nullptr; + } + case SBIG('CIRC'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + auto e = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); + } + case SBIG('KEYE'): + case SBIG('KEYP'): { + return std::make_unique(in); + } + case SBIG('MULT'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('RTOV'): { + auto a = GetRealElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('PULS'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + auto c = GetVectorElement(in); + auto d = GetVectorElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); + } + case SBIG('PVEL'): { + return std::make_unique(); + } + case SBIG('PLCO'): { + return std::make_unique(); + } + case SBIG('PLOC'): { + return std::make_unique(); + } + case SBIG('PSOF'): { + return std::make_unique(); + } + case SBIG('PSOU'): { + return std::make_unique(); + } + case SBIG('PSOR'): { + return std::make_unique(); + } + case SBIG('PSTR'): { + return std::make_unique(); + } + case SBIG('SUB_'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('CTVC'): { + auto a = GetColorElement(in); + return std::make_unique(std::move(a)); + } + default: + break; + } + return nullptr; } -std::unique_ptr CParticleDataFactory::GetRealElement(CInputStream& in) -{ - FourCC clsId = GetClassID(in); - switch (clsId) - { - case SBIG('LFTW'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('CNST'): - { - float a = GetReal(in); - return std::make_unique(std::move(a)); - } - case SBIG('CHAN'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - case SBIG('ADD_'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('CLMP'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - case SBIG('KEYE'): - case SBIG('KEYP'): - { - return std::make_unique(in); - } - case SBIG('IRND'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('RAND'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('DOTP'): - { - auto a = GetVectorElement(in); - auto b = GetVectorElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('MULT'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('PULS'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); - } - case SBIG('SCAL'): - { - auto a = GetRealElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('RLPT'): - { - auto a = GetRealElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('SINE'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - case SBIG('ISWT'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('CLTN'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); - } - case SBIG('CEQL'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); - } - case SBIG('PAP1'): - { - return std::make_unique(); - } - case SBIG('PAP2'): - { - return std::make_unique(); - } - case SBIG('PAP3'): - { - return std::make_unique(); - } - case SBIG('PAP4'): - { - return std::make_unique(); - } - case SBIG('PAP5'): - { - return std::make_unique(); - } - case SBIG('PAP6'): - { - return std::make_unique(); - } - case SBIG('PAP7'): - { - return std::make_unique(); - } - case SBIG('PAP8'): - { - return std::make_unique(); - } - case SBIG('PSLL'): - { - return std::make_unique(); - } - case SBIG('PRLW'): - { - return std::make_unique(); - } - case SBIG('SUB_'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('VMAG'): - { - auto a = GetVectorElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('VXTR'): - { - auto a = GetVectorElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('VYTR'): - { - auto a = GetVectorElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('VZTR'): - { - auto a = GetVectorElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('CEXT'): - { - auto a = GetIntElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('ITRL'): - { - auto a = GetIntElement(in); - auto b = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('CRNG'): - { - auto a = GetRealElement(in); - auto b = GetRealElement(in); - auto c = GetRealElement(in); - auto d = GetRealElement(in); - auto e = GetRealElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); - } - case SBIG('GTCR'): - { - auto a = GetColorElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('GTCG'): - { - auto a = GetColorElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('GTCB'): - { - auto a = GetColorElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('GTCA'): - { - auto a = GetColorElement(in); - return std::make_unique(std::move(a)); - } - default: break; - } - return nullptr; +std::unique_ptr CParticleDataFactory::GetRealElement(CInputStream& in) { + FourCC clsId = GetClassID(in); + switch (clsId) { + case SBIG('LFTW'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('CNST'): { + float a = GetReal(in); + return std::make_unique(std::move(a)); + } + case SBIG('CHAN'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c)); + } + case SBIG('ADD_'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('CLMP'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c)); + } + case SBIG('KEYE'): + case SBIG('KEYP'): { + return std::make_unique(in); + } + case SBIG('IRND'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('RAND'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('DOTP'): { + auto a = GetVectorElement(in); + auto b = GetVectorElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('MULT'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('PULS'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); + } + case SBIG('SCAL'): { + auto a = GetRealElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('RLPT'): { + auto a = GetRealElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('SINE'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c)); + } + case SBIG('ISWT'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('CLTN'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); + } + case SBIG('CEQL'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); + } + case SBIG('PAP1'): { + return std::make_unique(); + } + case SBIG('PAP2'): { + return std::make_unique(); + } + case SBIG('PAP3'): { + return std::make_unique(); + } + case SBIG('PAP4'): { + return std::make_unique(); + } + case SBIG('PAP5'): { + return std::make_unique(); + } + case SBIG('PAP6'): { + return std::make_unique(); + } + case SBIG('PAP7'): { + return std::make_unique(); + } + case SBIG('PAP8'): { + return std::make_unique(); + } + case SBIG('PSLL'): { + return std::make_unique(); + } + case SBIG('PRLW'): { + return std::make_unique(); + } + case SBIG('SUB_'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('VMAG'): { + auto a = GetVectorElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('VXTR'): { + auto a = GetVectorElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('VYTR'): { + auto a = GetVectorElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('VZTR'): { + auto a = GetVectorElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('CEXT'): { + auto a = GetIntElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('ITRL'): { + auto a = GetIntElement(in); + auto b = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('CRNG'): { + auto a = GetRealElement(in); + auto b = GetRealElement(in); + auto c = GetRealElement(in); + auto d = GetRealElement(in); + auto e = GetRealElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d), std::move(e)); + } + case SBIG('GTCR'): { + auto a = GetColorElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('GTCG'): { + auto a = GetColorElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('GTCB'): { + auto a = GetColorElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('GTCA'): { + auto a = GetColorElement(in); + return std::make_unique(std::move(a)); + } + default: + break; + } + return nullptr; } -std::unique_ptr CParticleDataFactory::GetIntElement(CInputStream& in) -{ - FourCC clsId = GetClassID(in); - switch (clsId) - { - case SBIG('KEYE'): - case SBIG('KEYP'): - { - return std::make_unique(in); - } - case SBIG('DETH'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('CLMP'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - auto c = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - case SBIG('CHAN'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - auto c = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - case SBIG('ADD_'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('CNST'): - { - int a = GetInt(in); - return std::make_unique(std::move(a)); - } - case SBIG('IMPL'): - { - auto a = GetIntElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('ILPT'): - { - auto a = GetIntElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('IRND'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('PULS'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - auto c = GetIntElement(in); - auto d = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); - } - case SBIG('MULT'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('SPAH'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - auto c = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b), std::move(c)); - } - case SBIG('RAND'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('TSCL'): - { - auto a = GetRealElement(in); - return std::make_unique(std::move(a)); - } - case SBIG('GAPC'): - { - return std::make_unique(); - } - case SBIG('GTCP'): - { - return std::make_unique(); - } - case SBIG('GEMT'): - { - return std::make_unique(); - } - case SBIG('MODU'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - case SBIG('SUB_'): - { - auto a = GetIntElement(in); - auto b = GetIntElement(in); - return std::make_unique(std::move(a), std::move(b)); - } - default: break; - } - return nullptr; +std::unique_ptr CParticleDataFactory::GetIntElement(CInputStream& in) { + FourCC clsId = GetClassID(in); + switch (clsId) { + case SBIG('KEYE'): + case SBIG('KEYP'): { + return std::make_unique(in); + } + case SBIG('DETH'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('CLMP'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + auto c = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c)); + } + case SBIG('CHAN'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + auto c = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c)); + } + case SBIG('ADD_'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('CNST'): { + int a = GetInt(in); + return std::make_unique(std::move(a)); + } + case SBIG('IMPL'): { + auto a = GetIntElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('ILPT'): { + auto a = GetIntElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('IRND'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('PULS'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + auto c = GetIntElement(in); + auto d = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c), std::move(d)); + } + case SBIG('MULT'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('SPAH'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + auto c = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b), std::move(c)); + } + case SBIG('RAND'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('TSCL'): { + auto a = GetRealElement(in); + return std::make_unique(std::move(a)); + } + case SBIG('GAPC'): { + return std::make_unique(); + } + case SBIG('GTCP'): { + return std::make_unique(); + } + case SBIG('GEMT'): { + return std::make_unique(); + } + case SBIG('MODU'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + case SBIG('SUB_'): { + auto a = GetIntElement(in); + auto b = GetIntElement(in); + return std::make_unique(std::move(a), std::move(b)); + } + default: + break; + } + return nullptr; } -CGenDescription* CParticleDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) -{ - std::vector tracker; - tracker.reserve(8); - return CreateGeneratorDescription(in, tracker, 0, resPool); +CGenDescription* CParticleDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) { + std::vector tracker; + tracker.reserve(8); + return CreateGeneratorDescription(in, tracker, 0, resPool); } CGenDescription* CParticleDataFactory::CreateGeneratorDescription(CInputStream& in, std::vector& tracker, - CAssetId resId, CSimplePool* resPool) -{ - if (std::count(tracker.cbegin(), tracker.cend(), resId) == 0) - { - tracker.push_back(resId); - FourCC cid = GetClassID(in); - if (cid == FOURCC('GPSM')) - { - CGenDescription* ret = new CGenDescription; - CreateGPSM(ret, in, tracker, resPool); - LoadGPSMTokens(ret); - return ret; - } + CAssetId resId, CSimplePool* resPool) { + if (std::count(tracker.cbegin(), tracker.cend(), resId) == 0) { + tracker.push_back(resId); + FourCC cid = GetClassID(in); + if (cid == FOURCC('GPSM')) { + CGenDescription* ret = new CGenDescription; + CreateGPSM(ret, in, tracker, resPool); + LoadGPSMTokens(ret); + return ret; } - return nullptr; + } + return nullptr; } -bool CParticleDataFactory::CreateGPSM(CGenDescription* fillDesc, CInputStream& in, - std::vector& tracker, CSimplePool* resPool) -{ - CRandom16 rand; - CGlobalRandom gr(rand); - FourCC clsId = GetClassID(in); - while (clsId != SBIG('_END')) - { - switch (clsId) - { - case SBIG('PMCL'): - fillDesc->x78_x64_PMCL = GetColorElement(in); - break; - case SBIG('LFOR'): - fillDesc->x118_x104_LFOR = GetRealElement(in); - break; - case SBIG('IDTS'): - fillDesc->xa4_x90_IDTS = GetChildGeneratorDesc(in, resPool, tracker); - break; - case SBIG('EMTR'): - fillDesc->x40_x2c_EMTR = GetEmitterElement(in); - break; - case SBIG('COLR'): - fillDesc->x30_x24_COLR = GetColorElement(in); - break; - case SBIG('CIND'): - fillDesc->x45_30_x32_24_CIND = GetBool(in); - break; - case SBIG('AAPH'): - fillDesc->x44_26_x30_26_AAPH = GetBool(in); - break; - case SBIG('CSSD'): - fillDesc->xa0_x8c_CSSD = GetIntElement(in); - break; - case SBIG('GRTE'): - fillDesc->x2c_x20_GRTE = GetRealElement(in); - break; - case SBIG('FXLL'): - fillDesc->x44_25_x30_25_FXLL = GetBool(in); - break; - case SBIG('ICTS'): - fillDesc->x8c_x78_ICTS = GetChildGeneratorDesc(in, resPool, tracker); - break; - case SBIG('KSSM'): - { - fillDesc->xd0_xbc_KSSM.reset(); - FourCC cid = GetClassID(in); - if (cid != SBIG('CNST')) - break; - fillDesc->xd0_xbc_KSSM.reset(new CSpawnSystemKeyframeData(in)); - fillDesc->xd0_xbc_KSSM->LoadAllSpawnedSystemTokens(resPool); - break; - } - case SBIG('ILOC'): - GetVectorElement(in); - break; - case SBIG('IITS'): - fillDesc->xb8_xa4_IITS = GetChildGeneratorDesc(in, resPool, tracker); - break; - case SBIG('IVEC'): - GetVectorElement(in); - break; - case SBIG('LDIR'): - fillDesc->x110_xfc_LDIR = GetVectorElement(in); - break; - case SBIG('LCLR'): - fillDesc->x104_xf0_LCLR = GetColorElement(in); - break; - case SBIG('LENG'): - fillDesc->x20_x14_LENG = GetRealElement(in); - break; - case SBIG('MAXP'): - fillDesc->x28_x1c_MAXP = GetIntElement(in); - break; - case SBIG('LOFF'): - fillDesc->x10c_xf8_LOFF = GetVectorElement(in); - break; - case SBIG('LINT'): - fillDesc->x108_xf4_LINT = GetRealElement(in); - break; - case SBIG('LINE'): - fillDesc->x44_24_x30_24_LINE = GetBool(in); - break; - case SBIG('LFOT'): - fillDesc->x114_x100_LFOT = GetIntElement(in); - break; - case SBIG('LIT_'): - fillDesc->x44_29_x30_29_LIT_ = GetBool(in); - break; - case SBIG('LTME'): - fillDesc->x34_x28_LTME = GetIntElement(in); - break; - case SBIG('LSLA'): - fillDesc->x11c_x108_LSLA = GetRealElement(in); - break; - case SBIG('LTYP'): - fillDesc->x100_xec_LTYP = GetIntElement(in); - break; - case SBIG('NDSY'): - fillDesc->xb4_xa0_NDSY = GetIntElement(in); - break; - case SBIG('MBSP'): - fillDesc->x48_x34_MBSP = GetIntElement(in); - break; - case SBIG('MBLR'): - fillDesc->x44_30_x31_24_MBLR = GetBool(in); - break; - case SBIG('NCSY'): - fillDesc->x9c_x88_NCSY = GetIntElement(in); - break; - case SBIG('PISY'): - fillDesc->xc8_xb4_PISY = GetIntElement(in); - break; - case SBIG('OPTS'): - fillDesc->x45_31_x32_25_OPTS = GetBool(in); - break; - case SBIG('PMAB'): - fillDesc->x44_31_x31_25_PMAB = GetBool(in); - break; - case SBIG('SESD'): - fillDesc->xf8_xe4_SESD = GetIntElement(in); - break; - case SBIG('SEPO'): - fillDesc->xfc_xe8_SEPO = GetVectorElement(in); - break; - case SBIG('PSLT'): - fillDesc->xc_x0_PSLT = GetIntElement(in); - break; - case SBIG('PMSC'): - fillDesc->x74_x60_PMSC = GetVectorElement(in); - break; - case SBIG('PMOP'): - fillDesc->x6c_x58_PMOP = GetVectorElement(in); - break; - case SBIG('PMDL'): - fillDesc->x5c_x48_PMDL = GetModel(in, resPool); - break; - case SBIG('PMRT'): - fillDesc->x70_x5c_PMRT = GetVectorElement(in); - break; - case SBIG('POFS'): - fillDesc->x18_xc_POFS = GetVectorElement(in); - break; - case SBIG('PMUS'): - fillDesc->x45_24_x31_26_PMUS = GetBool(in); - break; - case SBIG('PSIV'): - GetVectorElement(in); - break; - case SBIG('ROTA'): - fillDesc->x50_x3c_ROTA = GetRealElement(in); - break; - case SBIG('PSVM'): - GetModVectorElement(in); - break; - case SBIG('PSTS'): - fillDesc->x14_x8_PSTS = GetRealElement(in); - break; - case SBIG('PSOV'): - GetVectorElement(in); - break; - case SBIG('PSWT'): - fillDesc->x10_x4_PSWT = GetIntElement(in); - break; - case SBIG('SEED'): - fillDesc->x1c_x10_SEED = GetIntElement(in); - break; - case SBIG('PMOO'): - fillDesc->x45_25_x31_27_PMOO = GetBool(in); - break; - case SBIG('SSSD'): - fillDesc->xe4_xd0_SSSD = GetIntElement(in); - break; - case SBIG('SORT'): - fillDesc->x44_28_x30_28_SORT = GetBool(in); - break; - case SBIG('SIZE'): - fillDesc->x4c_x38_SIZE = GetRealElement(in); - break; - case SBIG('SISY'): - fillDesc->xcc_xb8_SISY = GetIntElement(in); - break; - case SBIG('SSPO'): - fillDesc->xe8_xd4_SSPO = GetVectorElement(in); - break; - case SBIG('TEXR'): - { - std::unique_ptr tex(GetTextureElement(in, resPool)); - if (tex->GetValueTexture(0)) - fillDesc->x54_x40_TEXR = std::move(tex); - break; - } - case SBIG('SSWH'): - fillDesc->xd4_xc0_SSWH = GetSwooshGeneratorDesc(in, resPool); - break; - case SBIG('TIND'): - { - std::unique_ptr tex(GetTextureElement(in, resPool)); - if (tex->GetValueTexture(0)) - fillDesc->x58_x44_TIND = std::move(tex); - break; - } - case SBIG('VMD4'): - fillDesc->x45_29_x31_31_VMD4 = GetBool(in); - break; - case SBIG('VMD3'): - fillDesc->x45_28_x31_30_VMD3 = GetBool(in); - break; - case SBIG('VMD2'): - fillDesc->x45_27_x31_29_VMD2 = GetBool(in); - break; - case SBIG('VMD1'): - fillDesc->x45_26_x31_28_VMD1 = GetBool(in); - break; - case SBIG('VEL4'): - fillDesc->x88_x74_VEL4 = GetModVectorElement(in); - break; - case SBIG('VEL3'): - fillDesc->x84_x70_VEL3 = GetModVectorElement(in); - break; - case SBIG('VEL2'): - fillDesc->x80_x6c_VEL2 = GetModVectorElement(in); - break; - case SBIG('VEL1'): - fillDesc->x7c_x68_VEL1 = GetModVectorElement(in); - break; - case SBIG('ZBUF'): - fillDesc->x44_27_x30_27_ZBUF = GetBool(in); - break; - case SBIG('WIDT'): - fillDesc->x24_x18_WIDT = GetRealElement(in); - break; - case SBIG('ORNT'): - fillDesc->x30_30_ORNT = GetBool(in); - break; - case SBIG('RSOP'): - fillDesc->x30_31_RSOP = GetBool(in); - break; - case SBIG('ADV1'): - fillDesc->x10c_ADV1 = GetRealElement(in); - break; - case SBIG('ADV2'): - fillDesc->x110_ADV2 = GetRealElement(in); - break; - case SBIG('ADV3'): - fillDesc->x114_ADV3 = GetRealElement(in); - break; - case SBIG('ADV4'): - fillDesc->x118_ADV4 = GetRealElement(in); - break; - case SBIG('ADV5'): - fillDesc->x11c_ADV5 = GetRealElement(in); - break; - case SBIG('ADV6'): - fillDesc->x120_ADV6 = GetRealElement(in); - break; - case SBIG('ADV7'): - fillDesc->x124_ADV7 = GetRealElement(in); - break; - case SBIG('ADV8'): - fillDesc->x128_ADV8 = GetRealElement(in); - break; - case SBIG('SELC'): - fillDesc->xec_xd8_SELC = GetElectricGeneratorDesc(in, resPool); - break; - default: - { - uint32_t clsName = clsId.toUint32(); - Log.report(logvisor::Fatal, "Unknown GPSM class %.4s @%" PRIi64, &clsName, in.position()); - return false; - } - } - clsId = GetClassID(in); +bool CParticleDataFactory::CreateGPSM(CGenDescription* fillDesc, CInputStream& in, std::vector& tracker, + CSimplePool* resPool) { + CRandom16 rand; + CGlobalRandom gr(rand); + FourCC clsId = GetClassID(in); + while (clsId != SBIG('_END')) { + switch (clsId) { + case SBIG('PMCL'): + fillDesc->x78_x64_PMCL = GetColorElement(in); + break; + case SBIG('LFOR'): + fillDesc->x118_x104_LFOR = GetRealElement(in); + break; + case SBIG('IDTS'): + fillDesc->xa4_x90_IDTS = GetChildGeneratorDesc(in, resPool, tracker); + break; + case SBIG('EMTR'): + fillDesc->x40_x2c_EMTR = GetEmitterElement(in); + break; + case SBIG('COLR'): + fillDesc->x30_x24_COLR = GetColorElement(in); + break; + case SBIG('CIND'): + fillDesc->x45_30_x32_24_CIND = GetBool(in); + break; + case SBIG('AAPH'): + fillDesc->x44_26_x30_26_AAPH = GetBool(in); + break; + case SBIG('CSSD'): + fillDesc->xa0_x8c_CSSD = GetIntElement(in); + break; + case SBIG('GRTE'): + fillDesc->x2c_x20_GRTE = GetRealElement(in); + break; + case SBIG('FXLL'): + fillDesc->x44_25_x30_25_FXLL = GetBool(in); + break; + case SBIG('ICTS'): + fillDesc->x8c_x78_ICTS = GetChildGeneratorDesc(in, resPool, tracker); + break; + case SBIG('KSSM'): { + fillDesc->xd0_xbc_KSSM.reset(); + FourCC cid = GetClassID(in); + if (cid != SBIG('CNST')) + break; + fillDesc->xd0_xbc_KSSM.reset(new CSpawnSystemKeyframeData(in)); + fillDesc->xd0_xbc_KSSM->LoadAllSpawnedSystemTokens(resPool); + break; } - - /* Now for our custom additions, if available */ - if (!in.atEnd() && (in.position() + 4) < in.length()) - { - clsId = GetClassID(in); - if (clsId == 0xFFFFFFFF) - return true; - - while (clsId != SBIG('_END') && !in.atEnd()) - { - switch (clsId) - { - case SBIG('BGCL'): - fillDesc->m_bevelGradient = GetColorElement(in); - break; - default: - break; - } - clsId = GetClassID(in); - } + case SBIG('ILOC'): + GetVectorElement(in); + break; + case SBIG('IITS'): + fillDesc->xb8_xa4_IITS = GetChildGeneratorDesc(in, resPool, tracker); + break; + case SBIG('IVEC'): + GetVectorElement(in); + break; + case SBIG('LDIR'): + fillDesc->x110_xfc_LDIR = GetVectorElement(in); + break; + case SBIG('LCLR'): + fillDesc->x104_xf0_LCLR = GetColorElement(in); + break; + case SBIG('LENG'): + fillDesc->x20_x14_LENG = GetRealElement(in); + break; + case SBIG('MAXP'): + fillDesc->x28_x1c_MAXP = GetIntElement(in); + break; + case SBIG('LOFF'): + fillDesc->x10c_xf8_LOFF = GetVectorElement(in); + break; + case SBIG('LINT'): + fillDesc->x108_xf4_LINT = GetRealElement(in); + break; + case SBIG('LINE'): + fillDesc->x44_24_x30_24_LINE = GetBool(in); + break; + case SBIG('LFOT'): + fillDesc->x114_x100_LFOT = GetIntElement(in); + break; + case SBIG('LIT_'): + fillDesc->x44_29_x30_29_LIT_ = GetBool(in); + break; + case SBIG('LTME'): + fillDesc->x34_x28_LTME = GetIntElement(in); + break; + case SBIG('LSLA'): + fillDesc->x11c_x108_LSLA = GetRealElement(in); + break; + case SBIG('LTYP'): + fillDesc->x100_xec_LTYP = GetIntElement(in); + break; + case SBIG('NDSY'): + fillDesc->xb4_xa0_NDSY = GetIntElement(in); + break; + case SBIG('MBSP'): + fillDesc->x48_x34_MBSP = GetIntElement(in); + break; + case SBIG('MBLR'): + fillDesc->x44_30_x31_24_MBLR = GetBool(in); + break; + case SBIG('NCSY'): + fillDesc->x9c_x88_NCSY = GetIntElement(in); + break; + case SBIG('PISY'): + fillDesc->xc8_xb4_PISY = GetIntElement(in); + break; + case SBIG('OPTS'): + fillDesc->x45_31_x32_25_OPTS = GetBool(in); + break; + case SBIG('PMAB'): + fillDesc->x44_31_x31_25_PMAB = GetBool(in); + break; + case SBIG('SESD'): + fillDesc->xf8_xe4_SESD = GetIntElement(in); + break; + case SBIG('SEPO'): + fillDesc->xfc_xe8_SEPO = GetVectorElement(in); + break; + case SBIG('PSLT'): + fillDesc->xc_x0_PSLT = GetIntElement(in); + break; + case SBIG('PMSC'): + fillDesc->x74_x60_PMSC = GetVectorElement(in); + break; + case SBIG('PMOP'): + fillDesc->x6c_x58_PMOP = GetVectorElement(in); + break; + case SBIG('PMDL'): + fillDesc->x5c_x48_PMDL = GetModel(in, resPool); + break; + case SBIG('PMRT'): + fillDesc->x70_x5c_PMRT = GetVectorElement(in); + break; + case SBIG('POFS'): + fillDesc->x18_xc_POFS = GetVectorElement(in); + break; + case SBIG('PMUS'): + fillDesc->x45_24_x31_26_PMUS = GetBool(in); + break; + case SBIG('PSIV'): + GetVectorElement(in); + break; + case SBIG('ROTA'): + fillDesc->x50_x3c_ROTA = GetRealElement(in); + break; + case SBIG('PSVM'): + GetModVectorElement(in); + break; + case SBIG('PSTS'): + fillDesc->x14_x8_PSTS = GetRealElement(in); + break; + case SBIG('PSOV'): + GetVectorElement(in); + break; + case SBIG('PSWT'): + fillDesc->x10_x4_PSWT = GetIntElement(in); + break; + case SBIG('SEED'): + fillDesc->x1c_x10_SEED = GetIntElement(in); + break; + case SBIG('PMOO'): + fillDesc->x45_25_x31_27_PMOO = GetBool(in); + break; + case SBIG('SSSD'): + fillDesc->xe4_xd0_SSSD = GetIntElement(in); + break; + case SBIG('SORT'): + fillDesc->x44_28_x30_28_SORT = GetBool(in); + break; + case SBIG('SIZE'): + fillDesc->x4c_x38_SIZE = GetRealElement(in); + break; + case SBIG('SISY'): + fillDesc->xcc_xb8_SISY = GetIntElement(in); + break; + case SBIG('SSPO'): + fillDesc->xe8_xd4_SSPO = GetVectorElement(in); + break; + case SBIG('TEXR'): { + std::unique_ptr tex(GetTextureElement(in, resPool)); + if (tex->GetValueTexture(0)) + fillDesc->x54_x40_TEXR = std::move(tex); + break; } - return true; + case SBIG('SSWH'): + fillDesc->xd4_xc0_SSWH = GetSwooshGeneratorDesc(in, resPool); + break; + case SBIG('TIND'): { + std::unique_ptr tex(GetTextureElement(in, resPool)); + if (tex->GetValueTexture(0)) + fillDesc->x58_x44_TIND = std::move(tex); + break; + } + case SBIG('VMD4'): + fillDesc->x45_29_x31_31_VMD4 = GetBool(in); + break; + case SBIG('VMD3'): + fillDesc->x45_28_x31_30_VMD3 = GetBool(in); + break; + case SBIG('VMD2'): + fillDesc->x45_27_x31_29_VMD2 = GetBool(in); + break; + case SBIG('VMD1'): + fillDesc->x45_26_x31_28_VMD1 = GetBool(in); + break; + case SBIG('VEL4'): + fillDesc->x88_x74_VEL4 = GetModVectorElement(in); + break; + case SBIG('VEL3'): + fillDesc->x84_x70_VEL3 = GetModVectorElement(in); + break; + case SBIG('VEL2'): + fillDesc->x80_x6c_VEL2 = GetModVectorElement(in); + break; + case SBIG('VEL1'): + fillDesc->x7c_x68_VEL1 = GetModVectorElement(in); + break; + case SBIG('ZBUF'): + fillDesc->x44_27_x30_27_ZBUF = GetBool(in); + break; + case SBIG('WIDT'): + fillDesc->x24_x18_WIDT = GetRealElement(in); + break; + case SBIG('ORNT'): + fillDesc->x30_30_ORNT = GetBool(in); + break; + case SBIG('RSOP'): + fillDesc->x30_31_RSOP = GetBool(in); + break; + case SBIG('ADV1'): + fillDesc->x10c_ADV1 = GetRealElement(in); + break; + case SBIG('ADV2'): + fillDesc->x110_ADV2 = GetRealElement(in); + break; + case SBIG('ADV3'): + fillDesc->x114_ADV3 = GetRealElement(in); + break; + case SBIG('ADV4'): + fillDesc->x118_ADV4 = GetRealElement(in); + break; + case SBIG('ADV5'): + fillDesc->x11c_ADV5 = GetRealElement(in); + break; + case SBIG('ADV6'): + fillDesc->x120_ADV6 = GetRealElement(in); + break; + case SBIG('ADV7'): + fillDesc->x124_ADV7 = GetRealElement(in); + break; + case SBIG('ADV8'): + fillDesc->x128_ADV8 = GetRealElement(in); + break; + case SBIG('SELC'): + fillDesc->xec_xd8_SELC = GetElectricGeneratorDesc(in, resPool); + break; + default: { + uint32_t clsName = clsId.toUint32(); + Log.report(logvisor::Fatal, "Unknown GPSM class %.4s @%" PRIi64, &clsName, in.position()); + return false; + } + } + clsId = GetClassID(in); + } + + /* Now for our custom additions, if available */ + if (!in.atEnd() && (in.position() + 4) < in.length()) { + clsId = GetClassID(in); + if (clsId == 0xFFFFFFFF) + return true; + + while (clsId != SBIG('_END') && !in.atEnd()) { + switch (clsId) { + case SBIG('BGCL'): + fillDesc->m_bevelGradient = GetColorElement(in); + break; + default: + break; + } + clsId = GetClassID(in); + } + } + return true; } -void CParticleDataFactory::LoadGPSMTokens(CGenDescription* desc) -{ - if (desc->x5c_x48_PMDL.m_found) - desc->x5c_x48_PMDL.m_model = desc->x5c_x48_PMDL.m_token.GetObj(); +void CParticleDataFactory::LoadGPSMTokens(CGenDescription* desc) { + if (desc->x5c_x48_PMDL.m_found) + desc->x5c_x48_PMDL.m_model = desc->x5c_x48_PMDL.m_token.GetObj(); - if (desc->x8c_x78_ICTS.m_found) - desc->x8c_x78_ICTS.m_gen = desc->x8c_x78_ICTS.m_token.GetObj(); + if (desc->x8c_x78_ICTS.m_found) + desc->x8c_x78_ICTS.m_gen = desc->x8c_x78_ICTS.m_token.GetObj(); - if (desc->xa4_x90_IDTS.m_found) - desc->xa4_x90_IDTS.m_gen = desc->xa4_x90_IDTS.m_token.GetObj(); + if (desc->xa4_x90_IDTS.m_found) + desc->xa4_x90_IDTS.m_gen = desc->xa4_x90_IDTS.m_token.GetObj(); - if (desc->xb8_xa4_IITS.m_found) - desc->xb8_xa4_IITS.m_gen = desc->xb8_xa4_IITS.m_token.GetObj(); + if (desc->xb8_xa4_IITS.m_found) + desc->xb8_xa4_IITS.m_gen = desc->xb8_xa4_IITS.m_token.GetObj(); - if (desc->xd4_xc0_SSWH.m_found) - desc->xd4_xc0_SSWH.m_swoosh = desc->xd4_xc0_SSWH.m_token.GetObj(); + if (desc->xd4_xc0_SSWH.m_found) + desc->xd4_xc0_SSWH.m_swoosh = desc->xd4_xc0_SSWH.m_token.GetObj(); } -CFactoryFnReturn FParticleFactory(const SObjectTag& tag, CInputStream& in, - const CVParamTransfer& vparms, - CObjectReference* selfRef) -{ - CSimplePool* sp = vparms.GetOwnedObj(); - return TToken::GetIObjObjectFor( - std::unique_ptr(CParticleDataFactory::GetGeneratorDesc(in, sp))); +CFactoryFnReturn FParticleFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, + CObjectReference* selfRef) { + CSimplePool* sp = vparms.GetOwnedObj(); + return TToken::GetIObjObjectFor( + std::unique_ptr(CParticleDataFactory::GetGeneratorDesc(in, sp))); } -} +} // namespace urde diff --git a/Runtime/Particle/CParticleDataFactory.hpp b/Runtime/Particle/CParticleDataFactory.hpp index e150aebb3..857194be0 100644 --- a/Runtime/Particle/CParticleDataFactory.hpp +++ b/Runtime/Particle/CParticleDataFactory.hpp @@ -6,8 +6,7 @@ #include "CToken.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { class CGenDescription; class CSwooshDescription; class CElectricDescription; @@ -22,86 +21,79 @@ class CVectorElement; class CRealElement; class CIntElement; -struct SParticleModel -{ - TLockedToken m_token; - bool m_found = false; - CModel* m_model = nullptr; - SParticleModel() = default; - SParticleModel(CToken&& tok, bool found) - : m_token(std::move(tok)), m_found(found) {} - operator bool() const { return m_found; } +struct SParticleModel { + TLockedToken m_token; + bool m_found = false; + CModel* m_model = nullptr; + SParticleModel() = default; + SParticleModel(CToken&& tok, bool found) : m_token(std::move(tok)), m_found(found) {} + operator bool() const { return m_found; } }; -struct SChildGeneratorDesc -{ - TLockedToken m_token; - bool m_found = false; - CGenDescription* m_gen = nullptr; - SChildGeneratorDesc() = default; - SChildGeneratorDesc(CToken&& tok, bool found) - : m_token(std::move(tok)), m_found(found) {} - operator bool() const { return m_found; } +struct SChildGeneratorDesc { + TLockedToken m_token; + bool m_found = false; + CGenDescription* m_gen = nullptr; + SChildGeneratorDesc() = default; + SChildGeneratorDesc(CToken&& tok, bool found) : m_token(std::move(tok)), m_found(found) {} + operator bool() const { return m_found; } }; -struct SSwooshGeneratorDesc -{ - TLockedToken m_token; - bool m_found = false; - CSwooshDescription* m_swoosh = nullptr; - SSwooshGeneratorDesc() = default; - SSwooshGeneratorDesc(CToken&& tok, bool found) - : m_token(std::move(tok)), m_found(found) {} - operator bool() const { return m_found; } +struct SSwooshGeneratorDesc { + TLockedToken m_token; + bool m_found = false; + CSwooshDescription* m_swoosh = nullptr; + SSwooshGeneratorDesc() = default; + SSwooshGeneratorDesc(CToken&& tok, bool found) : m_token(std::move(tok)), m_found(found) {} + operator bool() const { return m_found; } }; -struct SElectricGeneratorDesc -{ - TLockedToken m_token; - bool m_found = false; - CElectricDescription* m_electric = nullptr; - SElectricGeneratorDesc() = default; - SElectricGeneratorDesc(CToken&& tok, bool found) - : m_token(std::move(tok)), m_found(found) {} - operator bool() const { return m_found; } +struct SElectricGeneratorDesc { + TLockedToken m_token; + bool m_found = false; + CElectricDescription* m_electric = nullptr; + SElectricGeneratorDesc() = default; + SElectricGeneratorDesc(CToken&& tok, bool found) : m_token(std::move(tok)), m_found(found) {} + operator bool() const { return m_found; } }; -class CParticleDataFactory -{ - friend class CDecalDataFactory; - friend class CCollisionResponseData; - friend class CParticleElectricDataFactory; - friend class CParticleSwooshDataFactory; - friend class CProjectileWeaponDataFactory; +class CParticleDataFactory { + friend class CDecalDataFactory; + friend class CCollisionResponseData; + friend class CParticleElectricDataFactory; + friend class CParticleSwooshDataFactory; + friend class CProjectileWeaponDataFactory; - static SParticleModel GetModel(CInputStream& in, CSimplePool* resPool); - static SChildGeneratorDesc GetChildGeneratorDesc(CAssetId res, CSimplePool* resPool, const std::vector& tracker); - static SChildGeneratorDesc GetChildGeneratorDesc(CInputStream& in, CSimplePool* resPool, const std::vector& tracker); - static SSwooshGeneratorDesc GetSwooshGeneratorDesc(CInputStream& in, CSimplePool* resPool); - static SElectricGeneratorDesc GetElectricGeneratorDesc(CInputStream& in, CSimplePool* resPool); - static std::unique_ptr GetTextureElement(CInputStream& in, CSimplePool* resPool); - static std::unique_ptr GetColorElement(CInputStream& in); - static std::unique_ptr GetModVectorElement(CInputStream& in); - static std::unique_ptr GetEmitterElement(CInputStream& in); - static std::unique_ptr GetVectorElement(CInputStream& in); - static std::unique_ptr GetRealElement(CInputStream& in); - static std::unique_ptr GetIntElement(CInputStream& in); + static SParticleModel GetModel(CInputStream& in, CSimplePool* resPool); + static SChildGeneratorDesc GetChildGeneratorDesc(CAssetId res, CSimplePool* resPool, + const std::vector& tracker); + static SChildGeneratorDesc GetChildGeneratorDesc(CInputStream& in, CSimplePool* resPool, + const std::vector& tracker); + static SSwooshGeneratorDesc GetSwooshGeneratorDesc(CInputStream& in, CSimplePool* resPool); + static SElectricGeneratorDesc GetElectricGeneratorDesc(CInputStream& in, CSimplePool* resPool); + static std::unique_ptr GetTextureElement(CInputStream& in, CSimplePool* resPool); + static std::unique_ptr GetColorElement(CInputStream& in); + static std::unique_ptr GetModVectorElement(CInputStream& in); + static std::unique_ptr GetEmitterElement(CInputStream& in); + static std::unique_ptr GetVectorElement(CInputStream& in); + static std::unique_ptr GetRealElement(CInputStream& in); + static std::unique_ptr GetIntElement(CInputStream& in); + + static float GetReal(CInputStream& in); + static s32 GetInt(CInputStream& in); + static bool GetBool(CInputStream& in); + static FourCC GetClassID(CInputStream& in); + static CGenDescription* CreateGeneratorDescription(CInputStream& in, std::vector& tracker, CAssetId resId, + CSimplePool* resPool); + static bool CreateGPSM(CGenDescription* fillDesc, CInputStream& in, std::vector& tracker, + CSimplePool* resPool); + static void LoadGPSMTokens(CGenDescription* desc); - static float GetReal(CInputStream& in); - static s32 GetInt(CInputStream& in); - static bool GetBool(CInputStream& in); - static FourCC GetClassID(CInputStream& in); - static CGenDescription* CreateGeneratorDescription(CInputStream& in, std::vector& tracker, - CAssetId resId, CSimplePool* resPool); - static bool CreateGPSM(CGenDescription* fillDesc, CInputStream& in, - std::vector& tracker, CSimplePool* resPool); - static void LoadGPSMTokens(CGenDescription* desc); public: - static CGenDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); + static CGenDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); }; CFactoryFnReturn FParticleFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference* selfRef); -} - +} // namespace urde diff --git a/Runtime/Particle/CParticleElectric.cpp b/Runtime/Particle/CParticleElectric.cpp index 36ddd5e6a..994dda5e8 100644 --- a/Runtime/Particle/CParticleElectric.cpp +++ b/Runtime/Particle/CParticleElectric.cpp @@ -10,874 +10,730 @@ #include "zeus/CRelAngle.hpp" #include "zeus/CQuaternion.hpp" -namespace urde -{ +namespace urde { u16 CParticleElectric::g_GlobalSeed = 99; CParticleElectric::CParticleElectric(const TToken& token) -: x1c_elecDesc(token), x14c_randState(g_GlobalSeed++) -{ - x1bc_allocated.resize(32); +: x1c_elecDesc(token), x14c_randState(g_GlobalSeed++) { + x1bc_allocated.resize(32); - x450_24_emitting = true; - x450_29_transformDirty = true; - CElectricDescription* desc = x1c_elecDesc.GetObj(); + x450_24_emitting = true; + x450_29_transformDirty = true; + CElectricDescription* desc = x1c_elecDesc.GetObj(); - if (CIntElement* sseg = desc->x10_SSEG.get()) - sseg->GetValue(x28_currentFrame, x150_SSEG); + if (CIntElement* sseg = desc->x10_SSEG.get()) + sseg->GetValue(x28_currentFrame, x150_SSEG); - if (CIntElement* scnt = desc->xc_SCNT.get()) - scnt->GetValue(x28_currentFrame, x154_SCNT); + if (CIntElement* scnt = desc->xc_SCNT.get()) + scnt->GetValue(x28_currentFrame, x154_SCNT); - x154_SCNT = std::min(x154_SCNT, 32); + x154_SCNT = std::min(x154_SCNT, 32); - if (CIntElement* life = desc->x0_LIFE.get()) - life->GetValue(0, x2c_LIFE); - else - x2c_LIFE = INT_MAX; + if (CIntElement* life = desc->x0_LIFE.get()) + life->GetValue(0, x2c_LIFE); + else + x2c_LIFE = INT_MAX; - if (desc->x40_SSWH) - { - x450_27_haveSSWH = true; - for (int i=0 ; ix40_SSWH.m_token, x150_SSEG)); - x1e0_swooshGenerators.back()->DoElectricWarmup(); - } + if (desc->x40_SSWH) { + x450_27_haveSSWH = true; + for (int i = 0; i < x154_SCNT; ++i) { + x1e0_swooshGenerators.emplace_back(new CParticleSwoosh(desc->x40_SSWH.m_token, x150_SSEG)); + x1e0_swooshGenerators.back()->DoElectricWarmup(); } + } - ++x150_SSEG; - x420_calculatedVerts.resize(x150_SSEG); - x440_fractalOffsets.resize(x150_SSEG); - x430_fractalMags.resize(x150_SSEG); + ++x150_SSEG; + x420_calculatedVerts.resize(x150_SSEG); + x440_fractalOffsets.resize(x150_SSEG); + x430_fractalMags.resize(x150_SSEG); - if (desc->x50_GPSM) - { - x450_25_haveGPSM = true; - x400_gpsmGenerators.reserve(x154_SCNT); - for (int i=0 ; ix50_GPSM.m_token)); - x400_gpsmGenerators.back()->SetParticleEmission(false); - } + if (desc->x50_GPSM) { + x450_25_haveGPSM = true; + x400_gpsmGenerators.reserve(x154_SCNT); + for (int i = 0; i < x154_SCNT; ++i) { + x400_gpsmGenerators.emplace_back(new CElementGen(desc->x50_GPSM.m_token)); + x400_gpsmGenerators.back()->SetParticleEmission(false); } + } - if (desc->x60_EPSM) - { - x450_26_haveEPSM = true; - x410_epsmGenerators.reserve(x154_SCNT); - for (int i=0 ; ix60_EPSM.m_token)); - x410_epsmGenerators.back()->SetParticleEmission(false); - } + if (desc->x60_EPSM) { + x450_26_haveEPSM = true; + x410_epsmGenerators.reserve(x154_SCNT); + for (int i = 0; i < x154_SCNT; ++i) { + x410_epsmGenerators.emplace_back(new CElementGen(desc->x60_EPSM.m_token)); + x410_epsmGenerators.back()->SetParticleEmission(false); } + } - if (x1c_elecDesc->x28_LWD1 || x1c_elecDesc->x2c_LWD2 || x1c_elecDesc->x30_LWD3) - { - x450_28_haveLWD = true; - for (int i=0 ; ix28_LWD1 || x1c_elecDesc->x2c_LWD2 || x1c_elecDesc->x30_LWD3) { + x450_28_haveLWD = true; + for (int i = 0; i < x154_SCNT; ++i) + x2e4_lineManagers.emplace_back(new CLineManager()); + } } -void CParticleElectric::RenderSwooshes() -{ - for (CParticleElectricManager& elec : x3e8_electricManagers) - x1e0_swooshGenerators[elec.x0_idx]->Render(); +void CParticleElectric::RenderSwooshes() { + for (CParticleElectricManager& elec : x3e8_electricManagers) + x1e0_swooshGenerators[elec.x0_idx]->Render(); } -void CParticleElectric::SetupLineGXMaterial() -{ - // Konst color/alpha 0 +void CParticleElectric::SetupLineGXMaterial() { + // Konst color/alpha 0 } void CParticleElectric::DrawLineStrip(const std::vector& verts, float width, - const zeus::CColor& color) -{ - size_t useIdx = m_nextLineRenderer; - if (++m_nextLineRenderer > m_lineRenderers.size()) - m_lineRenderers.resize(m_nextLineRenderer); - if (!m_lineRenderers[useIdx]) - m_lineRenderers[useIdx] = std::make_unique(CLineRenderer::EPrimitiveMode::LineStrip, - x150_SSEG, nullptr, true, true); - CLineRenderer& renderer = *m_lineRenderers[useIdx]; - zeus::CColor useColor = x1b8_moduColor * color; + const zeus::CColor& color) { + size_t useIdx = m_nextLineRenderer; + if (++m_nextLineRenderer > m_lineRenderers.size()) + m_lineRenderers.resize(m_nextLineRenderer); + if (!m_lineRenderers[useIdx]) + m_lineRenderers[useIdx] = + std::make_unique(CLineRenderer::EPrimitiveMode::LineStrip, x150_SSEG, nullptr, true, true); + CLineRenderer& renderer = *m_lineRenderers[useIdx]; + zeus::CColor useColor = x1b8_moduColor * color; - renderer.Reset(); - for (const zeus::CVector3f& vert : verts) - renderer.AddVertex(vert, useColor, width); - renderer.Render(); + renderer.Reset(); + for (const zeus::CVector3f& vert : verts) + renderer.AddVertex(vert, useColor, width); + renderer.Render(); } -void CParticleElectric::RenderLines() -{ - m_nextLineRenderer = 0; - CGraphics::DisableAllLights(); - // Z-test, no write - // Additive blend +void CParticleElectric::RenderLines() { + m_nextLineRenderer = 0; + CGraphics::DisableAllLights(); + // Z-test, no write + // Additive blend - CGraphics::SetModelMatrix(zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * - zeus::CTransform::Translate(x38_translation) * x44_orientation * - zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale)); - // Disable culling - SetupLineGXMaterial(); - for (CParticleElectricManager& elec : x3e8_electricManagers) - { - CLineManager& line = *x2e4_lineManagers[elec.x0_idx]; - if (x1c_elecDesc->x28_LWD1) - DrawLineStrip(line.x0_verts, line.x10_widths[0], line.x1c_colors[0]); - if (x1c_elecDesc->x2c_LWD2) - DrawLineStrip(line.x0_verts, line.x10_widths[1], line.x1c_colors[1]); - if (x1c_elecDesc->x30_LWD3) - DrawLineStrip(line.x0_verts, line.x10_widths[2], line.x1c_colors[2]); + CGraphics::SetModelMatrix(zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * + zeus::CTransform::Translate(x38_translation) * x44_orientation * + zeus::CTransform::Scale(xe0_globalScale) * zeus::CTransform::Scale(xec_localScale)); + // Disable culling + SetupLineGXMaterial(); + for (CParticleElectricManager& elec : x3e8_electricManagers) { + CLineManager& line = *x2e4_lineManagers[elec.x0_idx]; + if (x1c_elecDesc->x28_LWD1) + DrawLineStrip(line.x0_verts, line.x10_widths[0], line.x1c_colors[0]); + if (x1c_elecDesc->x2c_LWD2) + DrawLineStrip(line.x0_verts, line.x10_widths[1], line.x1c_colors[1]); + if (x1c_elecDesc->x30_LWD3) + DrawLineStrip(line.x0_verts, line.x10_widths[2], line.x1c_colors[2]); + } + + // Enable culling + // Line Width 1 +} + +void CParticleElectric::UpdateCachedTransform() { + xf8_cachedXf = zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * + zeus::CTransform::Translate(x38_translation) * x44_orientation; + x450_29_transformDirty = false; +} + +void CParticleElectric::UpdateLine(int idx, int frame) { + CLineManager& line = *x2e4_lineManagers[idx]; + + if (CColorElement* lcl1 = x1c_elecDesc->x34_LCL1.get()) + lcl1->GetValue(frame, line.x1c_colors[0]); + if (CColorElement* lcl2 = x1c_elecDesc->x38_LCL2.get()) + lcl2->GetValue(frame, line.x1c_colors[1]); + if (CColorElement* lcl3 = x1c_elecDesc->x3c_LCL3.get()) + lcl3->GetValue(frame, line.x1c_colors[2]); + + if (CRealElement* lwd1 = x1c_elecDesc->x28_LWD1.get()) + lwd1->GetValue(frame, line.x10_widths[0]); + if (CRealElement* lwd2 = x1c_elecDesc->x2c_LWD2.get()) + lwd2->GetValue(frame, line.x10_widths[1]); + if (CRealElement* lwd3 = x1c_elecDesc->x30_LWD3.get()) + lwd3->GetValue(frame, line.x10_widths[2]); +} + +void CParticleElectric::UpdateElectricalEffects() { + for (auto it = x3e8_electricManagers.begin(); it != x3e8_electricManagers.end();) { + CParticleElectricManager& elec = *it; + if (elec.x4_slif < 1) { + x1bc_allocated[elec.x0_idx] = false; + if (elec.x10_gpsmIdx != -1) + x400_gpsmGenerators[elec.x10_gpsmIdx]->SetParticleEmission(false); + if (elec.x14_epsmIdx != -1) + x410_epsmGenerators[elec.x14_epsmIdx]->SetParticleEmission(false); + it = x3e8_electricManagers.erase(it); + continue; } - // Enable culling - // Line Width 1 + CParticleGlobals::SetParticleLifetime(elec.xc_endFrame - elec.x8_startFrame); + int frame = x28_currentFrame - elec.x8_startFrame; + CParticleGlobals::UpdateParticleLifetimeTweenValues(frame); + + if (x450_27_haveSSWH) { + CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; + zeus::CColor color = zeus::CColor::skWhite; + if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) + colr->GetValue(frame, color); + swoosh.SetModulationColor(color * x1b8_moduColor); + } + + if (x450_28_haveLWD) + UpdateLine(elec.x0_idx, frame); + + elec.x4_slif -= 1; + ++it; + } } -void CParticleElectric::UpdateCachedTransform() -{ - xf8_cachedXf = zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * - zeus::CTransform::Translate(x38_translation) * x44_orientation; - x450_29_transformDirty = false; +void CParticleElectric::CalculateFractal(int start, int end, float ampl, float ampd) { + float tmp = (end - start) / float(x430_fractalMags.size()) * ampl; + int storeIdx = (start + end) / 2; + x430_fractalMags[storeIdx] = (x430_fractalMags[start] + x430_fractalMags[end]) * 0.5f + tmp * x14c_randState.Float() - + tmp * 0.5f + ampd * x14c_randState.Float() - ampd * 0.5f; + if ((start + end) & 1) + x430_fractalMags[end - 1] = x430_fractalMags[end]; + + if (storeIdx - start > 1) + CalculateFractal(start, storeIdx, ampl, ampd); + if (end - storeIdx > 1) + CalculateFractal(storeIdx, end, ampl, ampd); } -void CParticleElectric::UpdateLine(int idx, int frame) -{ - CLineManager& line = *x2e4_lineManagers[idx]; +void CParticleElectric::CalculatePoints() { + zeus::CVector3f pos, vel; + if (CEmitterElement* iemt = x1c_elecDesc->x18_IEMT.get()) + iemt->GetValue(x28_currentFrame, pos, vel); - if (CColorElement* lcl1 = x1c_elecDesc->x34_LCL1.get()) - lcl1->GetValue(frame, line.x1c_colors[0]); - if (CColorElement* lcl2 = x1c_elecDesc->x38_LCL2.get()) - lcl2->GetValue(frame, line.x1c_colors[1]); - if (CColorElement* lcl3 = x1c_elecDesc->x3c_LCL3.get()) - lcl3->GetValue(frame, line.x1c_colors[2]); + if (x178_overrideIPos) + pos = *x178_overrideIPos; + if (x188_overrideIVel) + vel = *x188_overrideIVel; - if (CRealElement* lwd1 = x1c_elecDesc->x28_LWD1.get()) - lwd1->GetValue(frame, line.x10_widths[0]); - if (CRealElement* lwd2 = x1c_elecDesc->x2c_LWD2.get()) - lwd2->GetValue(frame, line.x10_widths[1]); - if (CRealElement* lwd3 = x1c_elecDesc->x30_LWD3.get()) - lwd3->GetValue(frame, line.x10_widths[2]); + rstl::reserved_vector points; + + if (!vel.isZero()) { + points.push_back(pos); + points.push_back(pos + vel); + points.push_back(pos + vel * 2.f); + } else { + points.push_back(pos); + } + + zeus::CVector3f fpos = zeus::CVector3f::skForward; + zeus::CVector3f fvel; + if (CEmitterElement* femt = x1c_elecDesc->x1c_FEMT.get()) + femt->GetValue(x28_currentFrame, fpos, fvel); + + if (x198_overrideFPos) + fpos = *x198_overrideFPos; + if (x1a8_overrideFVel) + fvel = *x1a8_overrideFVel; + + if (!fvel.isZero()) { + if (points.size() == 3) { + points.push_back(fpos); + points[2] = fpos + fvel; + } else { + points.push_back(fpos + fvel * 2.f); + points.push_back(fpos + fvel); + points.push_back(fpos); + } + } else { + points.push_back(fpos); + } + + if (points.size() == 4) { + int segs = x150_SSEG - 1; + float segDiv = 1.f / float(segs); + float curDiv = segDiv; + for (int i = 1; i < segs; ++i) { + float t = segDiv * x14c_randState.Range(-0.45f, 0.45f) + curDiv; + x420_calculatedVerts[i] = zeus::getBezierPoint(points[0], points[1], points[2], points[3], t); + curDiv += segDiv; + } + x420_calculatedVerts[segs] = points[3]; + } else { + x420_calculatedVerts[0] = pos; + int segs = x150_SSEG - 1; + float segDiv = 1.f / float(segs); + zeus::CVector3f accum = x420_calculatedVerts[0]; + zeus::CVector3f segDelta = (fpos - pos) * segDiv; + for (int i = 1; i < segs; ++i) { + float r = x14c_randState.Range(-0.45f, 0.45f); + x420_calculatedVerts[i] = segDelta * r + accum; + accum += segDelta; + } + x420_calculatedVerts[segs] = fpos; + } + + for (int i = 0; i < x150_SSEG; ++i) + x430_fractalMags[i] = 0.f; + + float amplVal = 1.f; + if (CRealElement* ampl = x1c_elecDesc->x20_AMPL.get()) { + ampl->GetValue(x28_currentFrame, amplVal); + amplVal *= 2.f; + } + + float ampdVal = 0.f; + if (CRealElement* ampd = x1c_elecDesc->x24_AMPD.get()) + ampd->GetValue(x28_currentFrame, ampdVal); + + CalculateFractal(0, x420_calculatedVerts.size() - 1, amplVal, ampdVal); + + zeus::CVector3f v0 = x420_calculatedVerts[0] - x420_calculatedVerts[1]; + zeus::CVector3f v1 = x420_calculatedVerts[x420_calculatedVerts.size() - 1] - x420_calculatedVerts[1]; + zeus::CVector3f upVec = zeus::CVector3f::skUp; + if (v0.canBeNormalized() && v1.canBeNormalized()) { + v0.normalize(); + v1.normalize(); + float dot = v0.dot(v1); + if (dot < 0) + dot = -dot; + if (std::fabs(dot - 1.f) < 0.00001f) + upVec = zeus::lookAt(x420_calculatedVerts[0], x420_calculatedVerts[1]).basis[2]; + else + upVec = v0.cross(v1).normalized(); + } else if (x420_calculatedVerts[0] != x420_calculatedVerts[1]) { + upVec = zeus::lookAt(x420_calculatedVerts[0], x420_calculatedVerts[1]).basis[2]; + } + + float commonRand = x14c_randState.Range(0.f, 360.f); + + for (int i = 1; i < x420_calculatedVerts.size() - 1; ++i) { + zeus::CVector3f delta = x420_calculatedVerts[i] - x420_calculatedVerts[i - 1]; + if (!delta.isZero()) { + zeus::CRelAngle angle = + zeus::degToRad(x430_fractalMags[i] / amplVal * 16.f * x14c_randState.Range(-1.f, 1.f) + commonRand); + x440_fractalOffsets[i] = zeus::CQuaternion::fromAxisAngle(delta, angle).transform(x430_fractalMags[i] * upVec); + } + } + + for (int i = 1; i < x420_calculatedVerts.size() - 1; ++i) + x420_calculatedVerts[i] += x440_fractalOffsets[i]; + + if (x1c_elecDesc->x70_ZERY) + for (int i = 0; i < x420_calculatedVerts.size(); ++i) + x420_calculatedVerts[i].y() = 0.f; } -void CParticleElectric::UpdateElectricalEffects() -{ - for (auto it = x3e8_electricManagers.begin() ; it != x3e8_electricManagers.end() ;) - { - CParticleElectricManager& elec = *it; - if (elec.x4_slif < 1) - { - x1bc_allocated[elec.x0_idx] = false; - if (elec.x10_gpsmIdx != -1) - x400_gpsmGenerators[elec.x10_gpsmIdx]->SetParticleEmission(false); - if (elec.x14_epsmIdx != -1) - x410_epsmGenerators[elec.x14_epsmIdx]->SetParticleEmission(false); - it = x3e8_electricManagers.erase(it); - continue; - } +void CParticleElectric::CreateNewParticles(int count) { + int allocIdx = 0; + for (int i = 0; i < count; ++i) { + if (x3e8_electricManagers.size() < x154_SCNT) { + zeus::CTransform cachedRot = xf8_cachedXf.getRotation(); + int toAdd = x1bc_allocated.size() - allocIdx; + for (int j = 0; j < toAdd; ++j, ++allocIdx) { + if (x1bc_allocated[allocIdx]) + continue; + x1bc_allocated[allocIdx] = true; + + int lifetime = 1; + if (CIntElement* slif = x1c_elecDesc->x4_SLIF.get()) + slif->GetValue(x28_currentFrame, lifetime); + + x3e8_electricManagers.push_back(CParticleElectricManager(allocIdx, lifetime, x28_currentFrame)); + CParticleElectricManager& elec = x3e8_electricManagers.back(); CParticleGlobals::SetParticleLifetime(elec.xc_endFrame - elec.x8_startFrame); int frame = x28_currentFrame - elec.x8_startFrame; CParticleGlobals::UpdateParticleLifetimeTweenValues(frame); + CalculatePoints(); - if (x450_27_haveSSWH) - { - CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; - zeus::CColor color = zeus::CColor::skWhite; - if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) - colr->GetValue(frame, color); - swoosh.SetModulationColor(color * x1b8_moduColor); + if (x450_27_haveSSWH) { + CParticleSwoosh& swoosh = *x1e0_swooshGenerators[allocIdx]; + swoosh.SetParticleEmission(true); + swoosh.SetGlobalTranslation(xf8_cachedXf.origin); + swoosh.SetGlobalOrientation(cachedRot); + swoosh.SetGlobalScale(xe0_globalScale); + swoosh.SetLocalScale(xec_localScale); + zeus::CColor color = zeus::CColor::skWhite; + if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) + colr->GetValue(frame, color); + swoosh.SetModulationColor(color * x1b8_moduColor); + swoosh.DoElectricCreate(x420_calculatedVerts); } - if (x450_28_haveLWD) - UpdateLine(elec.x0_idx, frame); - - elec.x4_slif -= 1; - ++it; - } -} - -void CParticleElectric::CalculateFractal(int start, int end, float ampl, float ampd) -{ - float tmp = (end - start) / float(x430_fractalMags.size()) * ampl; - int storeIdx = (start + end) / 2; - x430_fractalMags[storeIdx] = (x430_fractalMags[start] + x430_fractalMags[end]) * 0.5f + - tmp * x14c_randState.Float() - tmp * 0.5f + ampd * x14c_randState.Float() - ampd * 0.5f; - if ((start + end) & 1) - x430_fractalMags[end-1] = x430_fractalMags[end]; - - if (storeIdx - start > 1) - CalculateFractal(start, storeIdx, ampl, ampd); - if (end - storeIdx > 1) - CalculateFractal(storeIdx, end, ampl, ampd); -} - -void CParticleElectric::CalculatePoints() -{ - zeus::CVector3f pos, vel; - if (CEmitterElement* iemt = x1c_elecDesc->x18_IEMT.get()) - iemt->GetValue(x28_currentFrame, pos, vel); - - if (x178_overrideIPos) - pos = *x178_overrideIPos; - if (x188_overrideIVel) - vel = *x188_overrideIVel; - - rstl::reserved_vector points; - - if (!vel.isZero()) - { - points.push_back(pos); - points.push_back(pos + vel); - points.push_back(pos + vel * 2.f); - } - else - { - points.push_back(pos); - } - - zeus::CVector3f fpos = zeus::CVector3f::skForward; - zeus::CVector3f fvel; - if (CEmitterElement* femt = x1c_elecDesc->x1c_FEMT.get()) - femt->GetValue(x28_currentFrame, fpos, fvel); - - if (x198_overrideFPos) - fpos = *x198_overrideFPos; - if (x1a8_overrideFVel) - fvel = *x1a8_overrideFVel; - - if (!fvel.isZero()) - { - if (points.size() == 3) - { - points.push_back(fpos); - points[2] = fpos + fvel; + if (x450_28_haveLWD) { + CLineManager& line = *x2e4_lineManagers[allocIdx]; + line.x0_verts = x420_calculatedVerts; + UpdateLine(allocIdx, 0); + if (x450_27_haveSSWH) { + x130_buildBounds = zeus::CAABox::skInvertedBox; + for (const zeus::CVector3f& vec : x420_calculatedVerts) + x130_buildBounds.accumulateBounds(vec); + line.x28_aabb = x130_buildBounds; + } } - else - { - points.push_back(fpos + fvel * 2.f); - points.push_back(fpos + fvel); - points.push_back(fpos); - } - } - else - { - points.push_back(fpos); - } - if (points.size() == 4) - { - int segs = x150_SSEG - 1; - float segDiv = 1.f / float(segs); - float curDiv = segDiv; - for (int i=1 ; ix20_AMPL.get()) - { - ampl->GetValue(x28_currentFrame, amplVal); - amplVal *= 2.f; - } - - float ampdVal = 0.f; - if (CRealElement* ampd = x1c_elecDesc->x24_AMPD.get()) - ampd->GetValue(x28_currentFrame, ampdVal); - - CalculateFractal(0, x420_calculatedVerts.size() - 1, amplVal, ampdVal); - - zeus::CVector3f v0 = x420_calculatedVerts[0] - x420_calculatedVerts[1]; - zeus::CVector3f v1 = x420_calculatedVerts[x420_calculatedVerts.size() - 1] - x420_calculatedVerts[1]; - zeus::CVector3f upVec = zeus::CVector3f::skUp; - if (v0.canBeNormalized() && v1.canBeNormalized()) - { - v0.normalize(); - v1.normalize(); - float dot = v0.dot(v1); - if (dot < 0) - dot = -dot; - if (std::fabs(dot - 1.f) < 0.00001f) - upVec = zeus::lookAt(x420_calculatedVerts[0], x420_calculatedVerts[1]).basis[2]; - else - upVec = v0.cross(v1).normalized(); - } - else if (x420_calculatedVerts[0] != x420_calculatedVerts[1]) - { - upVec = zeus::lookAt(x420_calculatedVerts[0], x420_calculatedVerts[1]).basis[2]; - } - - float commonRand = x14c_randState.Range(0.f, 360.f); - - for (int i=1 ; ix70_ZERY) - for (int i=0 ; ix4_SLIF.get()) - slif->GetValue(x28_currentFrame, lifetime); - - x3e8_electricManagers.push_back(CParticleElectricManager(allocIdx, lifetime, x28_currentFrame)); - CParticleElectricManager& elec = x3e8_electricManagers.back(); - CParticleGlobals::SetParticleLifetime(elec.xc_endFrame - elec.x8_startFrame); - int frame = x28_currentFrame - elec.x8_startFrame; - CParticleGlobals::UpdateParticleLifetimeTweenValues(frame); - CalculatePoints(); - - if (x450_27_haveSSWH) - { - CParticleSwoosh& swoosh = *x1e0_swooshGenerators[allocIdx]; - swoosh.SetParticleEmission(true); - swoosh.SetGlobalTranslation(xf8_cachedXf.origin); - swoosh.SetGlobalOrientation(cachedRot); - swoosh.SetGlobalScale(xe0_globalScale); - swoosh.SetLocalScale(xec_localScale); - zeus::CColor color = zeus::CColor::skWhite; - if (CColorElement* colr = x1c_elecDesc->x14_COLR.get()) - colr->GetValue(frame, color); - swoosh.SetModulationColor(color * x1b8_moduColor); - swoosh.DoElectricCreate(x420_calculatedVerts); - } - - if (x450_28_haveLWD) - { - CLineManager& line = *x2e4_lineManagers[allocIdx]; - line.x0_verts = x420_calculatedVerts; - UpdateLine(allocIdx, 0); - if (x450_27_haveSSWH) - { - x130_buildBounds = zeus::CAABox::skInvertedBox; - for (const zeus::CVector3f& vec : x420_calculatedVerts) - x130_buildBounds.accumulateBounds(vec); - line.x28_aabb = x130_buildBounds; - } - } - - if (x450_25_haveGPSM) - { - for (int k=0 ; kx8_GRAT.get()) - { - if (grat->GetValue(x28_currentFrame, genRate)) - { - x3e8_electricManagers.clear(); - for (int i=0 ; ix8_GRAT.get()) { + if (grat->GetValue(x28_currentFrame, genRate)) { + x3e8_electricManagers.clear(); + for (int i = 0; i < x1bc_allocated.size(); ++i) + x1bc_allocated[i] = false; + return; + } else { + genRate = std::max(0.f, genRate); } + } - x15c_genRem += genRate; - int partCount = std::floor(x15c_genRem); - x15c_genRem -= partCount; - CreateNewParticles(partCount); + x15c_genRem += genRate; + int partCount = std::floor(x15c_genRem); + x15c_genRem -= partCount; + CreateNewParticles(partCount); } -void CParticleElectric::BuildBounds() -{ - if (GetParticleCount() <= 0) - { - x160_systemBounds = zeus::CAABox::skInvertedBox; - return; - } - +void CParticleElectric::BuildBounds() { + if (GetParticleCount() <= 0) { x160_systemBounds = zeus::CAABox::skInvertedBox; + return; + } - if (x450_27_haveSSWH) - { - for (CParticleElectricManager& elec : x3e8_electricManagers) - { - CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; - if (auto bounds = swoosh.GetBounds()) - x160_systemBounds.accumulateBounds(*bounds); - } - } - else if (x450_28_haveLWD) - { - zeus::CAABox tmp = zeus::CAABox::skInvertedBox; - for (CParticleElectricManager& elec : x3e8_electricManagers) - { - CLineManager& line = *x2e4_lineManagers[elec.x0_idx]; - tmp.accumulateBounds(line.x28_aabb); - } - if (!tmp.invalid()) - { - x160_systemBounds.accumulateBounds(tmp.getTransformedAABox( - zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * - zeus::CTransform::Translate(x38_translation) * x44_orientation * - zeus::CTransform::Scale(xe0_globalScale))); - } - } + x160_systemBounds = zeus::CAABox::skInvertedBox; - if (x450_25_haveGPSM) - { - for (int i=0 ; iGetBounds()) - x160_systemBounds.accumulateBounds(*bounds); + if (x450_27_haveSSWH) { + for (CParticleElectricManager& elec : x3e8_electricManagers) { + CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; + if (auto bounds = swoosh.GetBounds()) + x160_systemBounds.accumulateBounds(*bounds); } + } else if (x450_28_haveLWD) { + zeus::CAABox tmp = zeus::CAABox::skInvertedBox; + for (CParticleElectricManager& elec : x3e8_electricManagers) { + CLineManager& line = *x2e4_lineManagers[elec.x0_idx]; + tmp.accumulateBounds(line.x28_aabb); + } + if (!tmp.invalid()) { + x160_systemBounds.accumulateBounds(tmp.getTransformedAABox( + zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * + zeus::CTransform::Translate(x38_translation) * x44_orientation * zeus::CTransform::Scale(xe0_globalScale))); + } + } - if (x450_26_haveEPSM) - { - for (int i=0 ; iGetBounds()) - x160_systemBounds.accumulateBounds(*bounds); - } + if (x450_25_haveGPSM) { + for (int i = 0; i < x154_SCNT; ++i) + if (auto bounds = x400_gpsmGenerators[i]->GetBounds()) + x160_systemBounds.accumulateBounds(*bounds); + } + + if (x450_26_haveEPSM) { + for (int i = 0; i < x154_SCNT; ++i) + if (auto bounds = x410_epsmGenerators[i]->GetBounds()) + x160_systemBounds.accumulateBounds(*bounds); + } } -bool CParticleElectric::Update(double dt) -{ - CGlobalRandom gr(x14c_randState); - bool ret = false; +bool CParticleElectric::Update(double dt) { + CGlobalRandom gr(x14c_randState); + bool ret = false; - if (x450_25_haveGPSM) - { - for (int i=0 ; iIsSystemDeletable()) - break; + if (x450_25_haveGPSM) { + for (int i = 0; i < x154_SCNT; ++i) + if (!x400_gpsmGenerators[i]->IsSystemDeletable()) + break; + } + + if (x450_26_haveEPSM) { + for (int i = 0; i < x154_SCNT; ++i) + if (!x410_epsmGenerators[i]->IsSystemDeletable()) + break; + } + + bool emitting = x450_24_emitting && x28_currentFrame < x2c_LIFE; + + double evalTime = x28_currentFrame / 60.0; + x30_curTime += dt; + + if (x450_29_transformDirty) { + UpdateCachedTransform(); + zeus::CTransform globalOrient = xf8_cachedXf.getRotation(); + if (x450_27_haveSSWH) { + for (CParticleElectricManager& elec : x3e8_electricManagers) { + CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; + swoosh.SetGlobalTranslation(xf8_cachedXf.origin); + swoosh.SetGlobalOrientation(globalOrient); + swoosh.SetGlobalScale(xe0_globalScale); + swoosh.SetLocalScale(xec_localScale); + } } - if (x450_26_haveEPSM) - { - for (int i=0 ; iIsSystemDeletable()) - break; + if (x450_25_haveGPSM) { + for (CParticleElectricManager& elec : x3e8_electricManagers) { + CElementGen& gen = *x400_gpsmGenerators[elec.x0_idx]; + gen.SetGlobalTranslation(xf8_cachedXf.origin); + gen.SetGlobalOrientation(globalOrient); + gen.SetGlobalScale(xe0_globalScale); + gen.SetLocalScale(xec_localScale); + } } - bool emitting = x450_24_emitting && x28_currentFrame < x2c_LIFE; + if (x450_26_haveEPSM) { + for (CParticleElectricManager& elec : x3e8_electricManagers) { + CElementGen& gen = *x410_epsmGenerators[elec.x0_idx]; + gen.SetGlobalTranslation(xf8_cachedXf.origin); + gen.SetGlobalOrientation(globalOrient); + gen.SetGlobalScale(xe0_globalScale); + gen.SetLocalScale(xec_localScale); + } + } - double evalTime = x28_currentFrame / 60.0; - x30_curTime += dt; + ret = true; + } + while (evalTime < x30_curTime) { + CParticleGlobals::SetEmitterTime(x28_currentFrame); + UpdateElectricalEffects(); + if (emitting) + AddElectricalEffects(); + + if (x450_25_haveGPSM) { + if (x28_currentFrame >= x2c_LIFE) + for (int i = 0; i < x154_SCNT; ++i) + x400_gpsmGenerators[i]->EndLifetime(); + for (int i = 0; i < x154_SCNT; ++i) + x400_gpsmGenerators[i]->Update(1.0 / 60.0); + } + + if (x450_26_haveEPSM) { + if (x28_currentFrame >= x2c_LIFE) + for (int i = 0; i < x154_SCNT; ++i) + x410_epsmGenerators[i]->EndLifetime(); + for (int i = 0; i < x154_SCNT; ++i) + x410_epsmGenerators[i]->Update(1.0 / 60.0); + } + + ret = true; + evalTime += (1.0 / 60.0); + x28_currentFrame += 1; + } + + if (ret) + BuildBounds(); + + return ret; +} + +void CParticleElectric::Render(const CActorLights* lights) { + if (x3e8_electricManagers.size()) { if (x450_29_transformDirty) - { - UpdateCachedTransform(); - zeus::CTransform globalOrient = xf8_cachedXf.getRotation(); - if (x450_27_haveSSWH) - { - for (CParticleElectricManager& elec : x3e8_electricManagers) - { - CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; - swoosh.SetGlobalTranslation(xf8_cachedXf.origin); - swoosh.SetGlobalOrientation(globalOrient); - swoosh.SetGlobalScale(xe0_globalScale); - swoosh.SetLocalScale(xec_localScale); - } - } - - if (x450_25_haveGPSM) - { - for (CParticleElectricManager& elec : x3e8_electricManagers) - { - CElementGen& gen = *x400_gpsmGenerators[elec.x0_idx]; - gen.SetGlobalTranslation(xf8_cachedXf.origin); - gen.SetGlobalOrientation(globalOrient); - gen.SetGlobalScale(xe0_globalScale); - gen.SetLocalScale(xec_localScale); - } - } - - if (x450_26_haveEPSM) - { - for (CParticleElectricManager& elec : x3e8_electricManagers) - { - CElementGen& gen = *x410_epsmGenerators[elec.x0_idx]; - gen.SetGlobalTranslation(xf8_cachedXf.origin); - gen.SetGlobalOrientation(globalOrient); - gen.SetGlobalScale(xe0_globalScale); - gen.SetLocalScale(xec_localScale); - } - } - - ret = true; - } - - while (evalTime < x30_curTime) - { - CParticleGlobals::SetEmitterTime(x28_currentFrame); - UpdateElectricalEffects(); - if (emitting) - AddElectricalEffects(); - - if (x450_25_haveGPSM) - { - if (x28_currentFrame >= x2c_LIFE) - for (int i=0 ; iEndLifetime(); - for (int i=0 ; iUpdate(1.0 / 60.0); - } - - if (x450_26_haveEPSM) - { - if (x28_currentFrame >= x2c_LIFE) - for (int i=0 ; iEndLifetime(); - for (int i=0 ; iUpdate(1.0 / 60.0); - } - - ret = true; - evalTime += (1.0 / 60.0); - x28_currentFrame += 1; - } - - if (ret) - BuildBounds(); - - return ret; -} - -void CParticleElectric::Render(const CActorLights* lights) -{ - if (x3e8_electricManagers.size()) - { - if (x450_29_transformDirty) - UpdateCachedTransform(); - if (x450_27_haveSSWH) - RenderSwooshes(); - if (x450_28_haveLWD) - RenderLines(); - } - - if (x450_25_haveGPSM) - { - for (int i=0 ; iRender(lights); - } - - if (x450_26_haveEPSM) - { - for (int i=0 ; iRender(lights); - } -} - -void CParticleElectric::SetOrientation(const zeus::CTransform& orientation) -{ - x44_orientation = orientation; - x74_invOrientation = x44_orientation.inverse(); - x450_29_transformDirty = true; -} - -void CParticleElectric::SetTranslation(const zeus::CVector3f& translation) -{ - x38_translation = translation; - x450_29_transformDirty = true; -} - -void CParticleElectric::SetGlobalOrientation(const zeus::CTransform& orientation) -{ - xb0_globalOrientation = orientation; - x450_29_transformDirty = true; - + UpdateCachedTransform(); if (x450_27_haveSSWH) - { - for (CParticleElectricManager& elec : x3e8_electricManagers) - { - CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; - swoosh.SetGlobalOrientation(xb0_globalOrientation); - } + RenderSwooshes(); + if (x450_28_haveLWD) + RenderLines(); + } + + if (x450_25_haveGPSM) { + for (int i = 0; i < x154_SCNT; ++i) + x400_gpsmGenerators[i]->Render(lights); + } + + if (x450_26_haveEPSM) { + for (int i = 0; i < x154_SCNT; ++i) + x410_epsmGenerators[i]->Render(lights); + } +} + +void CParticleElectric::SetOrientation(const zeus::CTransform& orientation) { + x44_orientation = orientation; + x74_invOrientation = x44_orientation.inverse(); + x450_29_transformDirty = true; +} + +void CParticleElectric::SetTranslation(const zeus::CVector3f& translation) { + x38_translation = translation; + x450_29_transformDirty = true; +} + +void CParticleElectric::SetGlobalOrientation(const zeus::CTransform& orientation) { + xb0_globalOrientation = orientation; + x450_29_transformDirty = true; + + if (x450_27_haveSSWH) { + for (CParticleElectricManager& elec : x3e8_electricManagers) { + CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; + swoosh.SetGlobalOrientation(xb0_globalOrientation); } + } - if (x450_25_haveGPSM) - { - for (int i=0 ; iSetGlobalOrientation(xb0_globalOrientation); + if (x450_25_haveGPSM) { + for (int i = 0; i < x154_SCNT; ++i) + x400_gpsmGenerators[i]->SetGlobalOrientation(xb0_globalOrientation); + } + + if (x450_26_haveEPSM) { + for (int i = 0; i < x154_SCNT; ++i) + x410_epsmGenerators[i]->SetGlobalOrientation(xb0_globalOrientation); + } +} + +void CParticleElectric::SetGlobalTranslation(const zeus::CVector3f& translation) { + xa4_globalTranslation = translation; + x450_29_transformDirty = true; + + if (x450_27_haveSSWH) { + for (CParticleElectricManager& elec : x3e8_electricManagers) { + CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; + swoosh.SetGlobalTranslation(xa4_globalTranslation); } + } - if (x450_26_haveEPSM) - { - for (int i=0 ; iSetGlobalOrientation(xb0_globalOrientation); + if (x450_25_haveGPSM) { + for (int i = 0; i < x154_SCNT; ++i) + x400_gpsmGenerators[i]->SetGlobalTranslation(xa4_globalTranslation); + } + + if (x450_26_haveEPSM) { + for (int i = 0; i < x154_SCNT; ++i) + x410_epsmGenerators[i]->SetGlobalTranslation(xa4_globalTranslation); + } +} + +void CParticleElectric::SetGlobalScale(const zeus::CVector3f& scale) { + xe0_globalScale = scale; + x450_29_transformDirty = true; +} + +void CParticleElectric::SetLocalScale(const zeus::CVector3f& scale) { + xec_localScale = scale; + x450_29_transformDirty = true; + + if (x450_27_haveSSWH) { + for (CParticleElectricManager& elec : x3e8_electricManagers) { + CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; + swoosh.SetLocalScale(xec_localScale); } + } + + if (x450_25_haveGPSM) { + for (int i = 0; i < x154_SCNT; ++i) + x400_gpsmGenerators[i]->SetLocalScale(xec_localScale); + } + + if (x450_26_haveEPSM) { + for (int i = 0; i < x154_SCNT; ++i) + x410_epsmGenerators[i]->SetLocalScale(xec_localScale); + } } -void CParticleElectric::SetGlobalTranslation(const zeus::CVector3f& translation) -{ - xa4_globalTranslation = translation; - x450_29_transformDirty = true; +void CParticleElectric::SetParticleEmission(bool e) { x450_24_emitting = e; } - if (x450_27_haveSSWH) - { - for (CParticleElectricManager& elec : x3e8_electricManagers) - { - CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; - swoosh.SetGlobalTranslation(xa4_globalTranslation); - } - } +void CParticleElectric::SetModulationColor(const zeus::CColor& color) { x1b8_moduColor = color; } - if (x450_25_haveGPSM) - { - for (int i=0 ; iSetGlobalTranslation(xa4_globalTranslation); - } +const zeus::CTransform& CParticleElectric::GetOrientation() const { return x44_orientation; } - if (x450_26_haveEPSM) - { - for (int i=0 ; iSetGlobalTranslation(xa4_globalTranslation); - } -} +const zeus::CVector3f& CParticleElectric::GetTranslation() const { return x38_translation; } -void CParticleElectric::SetGlobalScale(const zeus::CVector3f& scale) -{ - xe0_globalScale = scale; - x450_29_transformDirty = true; -} +const zeus::CTransform& CParticleElectric::GetGlobalOrientation() const { return xb0_globalOrientation; } -void CParticleElectric::SetLocalScale(const zeus::CVector3f& scale) -{ - xec_localScale = scale; - x450_29_transformDirty = true; +const zeus::CVector3f& CParticleElectric::GetGlobalTranslation() const { return xa4_globalTranslation; } - if (x450_27_haveSSWH) - { - for (CParticleElectricManager& elec : x3e8_electricManagers) - { - CParticleSwoosh& swoosh = *x1e0_swooshGenerators[elec.x0_idx]; - swoosh.SetLocalScale(xec_localScale); - } - } +const zeus::CVector3f& CParticleElectric::GetGlobalScale() const { return xe0_globalScale; } - if (x450_25_haveGPSM) - { - for (int i=0 ; iSetLocalScale(xec_localScale); - } +const zeus::CColor& CParticleElectric::GetModulationColor() const { return x1b8_moduColor; } - if (x450_26_haveEPSM) - { - for (int i=0 ; iSetLocalScale(xec_localScale); - } -} - -void CParticleElectric::SetParticleEmission(bool e) -{ - x450_24_emitting = e; -} - -void CParticleElectric::SetModulationColor(const zeus::CColor& color) -{ - x1b8_moduColor = color; -} - -const zeus::CTransform& CParticleElectric::GetOrientation() const -{ - return x44_orientation; -} - -const zeus::CVector3f& CParticleElectric::GetTranslation() const -{ - return x38_translation; -} - -const zeus::CTransform& CParticleElectric::GetGlobalOrientation() const -{ - return xb0_globalOrientation; -} - -const zeus::CVector3f& CParticleElectric::GetGlobalTranslation() const -{ - return xa4_globalTranslation; -} - -const zeus::CVector3f& CParticleElectric::GetGlobalScale() const -{ - return xe0_globalScale; -} - -const zeus::CColor& CParticleElectric::GetModulationColor() const -{ - return x1b8_moduColor; -} - -bool CParticleElectric::IsSystemDeletable() const -{ - if (x450_24_emitting && x28_currentFrame < x2c_LIFE) - return false; - - if (x3e8_electricManagers.size()) - return false; - - if (x450_25_haveGPSM) - { - for (int i=0 ; iIsSystemDeletable()) - return false; - } - - if (x450_26_haveEPSM) - { - for (int i=0 ; iIsSystemDeletable()) - return false; - } - - return true; -} - -std::experimental::optional CParticleElectric::GetBounds() const -{ - if (GetParticleCount() <= 0) - return {}; - else - return x160_systemBounds; -} - -u32 CParticleElectric::GetParticleCount() const -{ - u32 ret = 0; - - for (const CParticleElectricManager& elec : x3e8_electricManagers) - { - if (x450_27_haveSSWH) - ret += x1e0_swooshGenerators[elec.x0_idx]->GetParticleCount(); - if (x450_28_haveLWD) - ret += x150_SSEG; - } - - if (x450_25_haveGPSM) - { - for (int i=0 ; iGetParticleCount(); - } - - if (x450_26_haveEPSM) - { - for (int i=0 ; iGetParticleCount(); - } - - return ret; -} - -bool CParticleElectric::SystemHasLight() const -{ - if (x450_25_haveGPSM) - return x400_gpsmGenerators.front()->SystemHasLight(); - else if (x450_26_haveEPSM) - return x410_epsmGenerators.front()->SystemHasLight(); +bool CParticleElectric::IsSystemDeletable() const { + if (x450_24_emitting && x28_currentFrame < x2c_LIFE) return false; + + if (x3e8_electricManagers.size()) + return false; + + if (x450_25_haveGPSM) { + for (int i = 0; i < x154_SCNT; ++i) + if (!x400_gpsmGenerators[i]->IsSystemDeletable()) + return false; + } + + if (x450_26_haveEPSM) { + for (int i = 0; i < x154_SCNT; ++i) + if (!x410_epsmGenerators[i]->IsSystemDeletable()) + return false; + } + + return true; } -CLight CParticleElectric::GetLight() const -{ - if (x450_25_haveGPSM) - return x400_gpsmGenerators.front()->GetLight(); - else if (x450_26_haveEPSM) - return x410_epsmGenerators.front()->GetLight(); - return CLight::BuildLocalAmbient(GetGlobalTranslation(), zeus::CColor::skOrange); +std::experimental::optional CParticleElectric::GetBounds() const { + if (GetParticleCount() <= 0) + return {}; + else + return x160_systemBounds; } -bool CParticleElectric::GetParticleEmission() const -{ - return x450_24_emitting; +u32 CParticleElectric::GetParticleCount() const { + u32 ret = 0; + + for (const CParticleElectricManager& elec : x3e8_electricManagers) { + if (x450_27_haveSSWH) + ret += x1e0_swooshGenerators[elec.x0_idx]->GetParticleCount(); + if (x450_28_haveLWD) + ret += x150_SSEG; + } + + if (x450_25_haveGPSM) { + for (int i = 0; i < x154_SCNT; ++i) + ret += x400_gpsmGenerators[i]->GetParticleCount(); + } + + if (x450_26_haveEPSM) { + for (int i = 0; i < x154_SCNT; ++i) + ret += x410_epsmGenerators[i]->GetParticleCount(); + } + + return ret; } -void CParticleElectric::DestroyParticles() -{ - // Empty +bool CParticleElectric::SystemHasLight() const { + if (x450_25_haveGPSM) + return x400_gpsmGenerators.front()->SystemHasLight(); + else if (x450_26_haveEPSM) + return x410_epsmGenerators.front()->SystemHasLight(); + return false; } +CLight CParticleElectric::GetLight() const { + if (x450_25_haveGPSM) + return x400_gpsmGenerators.front()->GetLight(); + else if (x450_26_haveEPSM) + return x410_epsmGenerators.front()->GetLight(); + return CLight::BuildLocalAmbient(GetGlobalTranslation(), zeus::CColor::skOrange); } + +bool CParticleElectric::GetParticleEmission() const { return x450_24_emitting; } + +void CParticleElectric::DestroyParticles() { + // Empty +} + +} // namespace urde diff --git a/Runtime/Particle/CParticleElectric.hpp b/Runtime/Particle/CParticleElectric.hpp index 3419e2254..9a8e25c37 100644 --- a/Runtime/Particle/CParticleElectric.hpp +++ b/Runtime/Particle/CParticleElectric.hpp @@ -5,141 +5,139 @@ #include "CRandom16.hpp" #include "Graphics/CLineRenderer.hpp" -namespace urde -{ +namespace urde { class CElectricDescription; class CParticleSwoosh; class CElementGen; -class CParticleElectric : public CParticleGen -{ - static u16 g_GlobalSeed; -public: - static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; } - class CLineManager - { - friend class CParticleElectric; - std::vector x0_verts; - float x10_widths[3] = {1.f, 2.f, 3.f}; - zeus::CColor x1c_colors[3]; - zeus::CAABox x28_aabb = zeus::CAABox::skInvertedBox; - }; +class CParticleElectric : public CParticleGen { + static u16 g_GlobalSeed; - class CParticleElectricManager - { - friend class CParticleElectric; - u32 x0_idx; - u32 x4_slif; - u32 x8_startFrame; - u32 xc_endFrame; - int x10_gpsmIdx = -1; - int x14_epsmIdx = -1; - public: - CParticleElectricManager(u32 idx, u32 slif, u32 startFrame) - : x0_idx(idx), x4_slif(slif), x8_startFrame(startFrame), xc_endFrame(startFrame + slif) {} - }; +public: + static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; } + class CLineManager { + friend class CParticleElectric; + std::vector x0_verts; + float x10_widths[3] = {1.f, 2.f, 3.f}; + zeus::CColor x1c_colors[3]; + zeus::CAABox x28_aabb = zeus::CAABox::skInvertedBox; + }; + + class CParticleElectricManager { + friend class CParticleElectric; + u32 x0_idx; + u32 x4_slif; + u32 x8_startFrame; + u32 xc_endFrame; + int x10_gpsmIdx = -1; + int x14_epsmIdx = -1; + + public: + CParticleElectricManager(u32 idx, u32 slif, u32 startFrame) + : x0_idx(idx), x4_slif(slif), x8_startFrame(startFrame), xc_endFrame(startFrame + slif) {} + }; private: - TLockedToken x1c_elecDesc; - int x28_currentFrame = 0; - int x2c_LIFE; - double x30_curTime = 0.0; - zeus::CVector3f x38_translation; - zeus::CTransform x44_orientation; - zeus::CTransform x74_invOrientation; - zeus::CVector3f xa4_globalTranslation; - zeus::CTransform xb0_globalOrientation; - zeus::CVector3f xe0_globalScale = zeus::CVector3f::skOne; - zeus::CVector3f xec_localScale = zeus::CVector3f::skOne; - zeus::CTransform xf8_cachedXf; - float x128 = 0.f; - float x12c = 0.f; - zeus::CAABox x130_buildBounds = zeus::CAABox::skInvertedBox; - CRandom16 x14c_randState; - int x150_SSEG = 8; - int x154_SCNT = 1; - int x158 = 0; - float x15c_genRem = 0.f; - zeus::CAABox x160_systemBounds = zeus::CAABox::skInvertedBox; - std::experimental::optional x178_overrideIPos; - std::experimental::optional x188_overrideIVel; - std::experimental::optional x198_overrideFPos; - std::experimental::optional x1a8_overrideFVel; - zeus::CColor x1b8_moduColor; - rstl::reserved_vector x1bc_allocated; - rstl::reserved_vector, 32> x1e0_swooshGenerators; - rstl::reserved_vector, 32> x2e4_lineManagers; - std::list x3e8_electricManagers; - std::vector> x400_gpsmGenerators; - std::vector> x410_epsmGenerators; - std::vector x420_calculatedVerts; - std::vector x430_fractalMags; - std::vector x440_fractalOffsets; + TLockedToken x1c_elecDesc; + int x28_currentFrame = 0; + int x2c_LIFE; + double x30_curTime = 0.0; + zeus::CVector3f x38_translation; + zeus::CTransform x44_orientation; + zeus::CTransform x74_invOrientation; + zeus::CVector3f xa4_globalTranslation; + zeus::CTransform xb0_globalOrientation; + zeus::CVector3f xe0_globalScale = zeus::CVector3f::skOne; + zeus::CVector3f xec_localScale = zeus::CVector3f::skOne; + zeus::CTransform xf8_cachedXf; + float x128 = 0.f; + float x12c = 0.f; + zeus::CAABox x130_buildBounds = zeus::CAABox::skInvertedBox; + CRandom16 x14c_randState; + int x150_SSEG = 8; + int x154_SCNT = 1; + int x158 = 0; + float x15c_genRem = 0.f; + zeus::CAABox x160_systemBounds = zeus::CAABox::skInvertedBox; + std::experimental::optional x178_overrideIPos; + std::experimental::optional x188_overrideIVel; + std::experimental::optional x198_overrideFPos; + std::experimental::optional x1a8_overrideFVel; + zeus::CColor x1b8_moduColor; + rstl::reserved_vector x1bc_allocated; + rstl::reserved_vector, 32> x1e0_swooshGenerators; + rstl::reserved_vector, 32> x2e4_lineManagers; + std::list x3e8_electricManagers; + std::vector> x400_gpsmGenerators; + std::vector> x410_epsmGenerators; + std::vector x420_calculatedVerts; + std::vector x430_fractalMags; + std::vector x440_fractalOffsets; - size_t m_nextLineRenderer = 0; - std::vector> m_lineRenderers; + size_t m_nextLineRenderer = 0; + std::vector> m_lineRenderers; - union - { - struct - { - bool x450_24_emitting : 1; bool x450_25_haveGPSM : 1; bool x450_26_haveEPSM : 1; - bool x450_27_haveSSWH : 1; bool x450_28_haveLWD: 1; bool x450_29_transformDirty : 1; - }; - u32 dummy = 0; + union { + struct { + bool x450_24_emitting : 1; + bool x450_25_haveGPSM : 1; + bool x450_26_haveEPSM : 1; + bool x450_27_haveSSWH : 1; + bool x450_28_haveLWD : 1; + bool x450_29_transformDirty : 1; }; + u32 dummy = 0; + }; - void SetupLineGXMaterial(); - void DrawLineStrip(const std::vector& verts, float width, const zeus::CColor& color); - void RenderLines(); - void RenderSwooshes(); - void UpdateCachedTransform(); - void UpdateLine(int idx, int frame); - void UpdateElectricalEffects(); - void CalculateFractal(int start, int end, float ampl, float ampd); - void CalculatePoints(); - void CreateNewParticles(int count); - void AddElectricalEffects(); - void BuildBounds(); + void SetupLineGXMaterial(); + void DrawLineStrip(const std::vector& verts, float width, const zeus::CColor& color); + void RenderLines(); + void RenderSwooshes(); + void UpdateCachedTransform(); + void UpdateLine(int idx, int frame); + void UpdateElectricalEffects(); + void CalculateFractal(int start, int end, float ampl, float ampd); + void CalculatePoints(); + void CreateNewParticles(int count); + void AddElectricalEffects(); + void BuildBounds(); public: - CParticleElectric(const TToken& desc); + CParticleElectric(const TToken& desc); - bool Update(double); - void Render(const CActorLights* = nullptr); - void SetOrientation(const zeus::CTransform&); - void SetTranslation(const zeus::CVector3f&); - void SetGlobalOrientation(const zeus::CTransform&); - void SetGlobalTranslation(const zeus::CVector3f&); - void SetGlobalScale(const zeus::CVector3f&); - void SetLocalScale(const zeus::CVector3f&); - void SetParticleEmission(bool); - void SetModulationColor(const zeus::CColor&); - void SetOverrideIPos(const zeus::CVector3f& vec) { x178_overrideIPos.emplace(vec); } - void SetOverrideIVel(const zeus::CVector3f& vec) { x188_overrideIVel.emplace(vec); } - void SetOverrideFPos(const zeus::CVector3f& vec) { x198_overrideFPos.emplace(vec); } - void SetOverrideFVel(const zeus::CVector3f& vec) { x1a8_overrideFVel.emplace(vec); } - const zeus::CTransform& GetOrientation() const; - const zeus::CVector3f& GetTranslation() const; - const zeus::CTransform& GetGlobalOrientation() const; - const zeus::CVector3f& GetGlobalTranslation() const; - const zeus::CVector3f& GetGlobalScale() const; - const zeus::CColor& GetModulationColor() const; - bool IsSystemDeletable() const; - std::experimental::optional GetBounds() const; - u32 GetParticleCount() const; - bool SystemHasLight() const; - CLight GetLight() const; - bool GetParticleEmission() const; - void DestroyParticles(); - void Reset() {} - void ForceParticleCreation(s32 count) - { - CGlobalRandom gRnd{x14c_randState}; - CreateNewParticles(count); - } - FourCC Get4CharId() const { return FOURCC('ELSC'); } + bool Update(double); + void Render(const CActorLights* = nullptr); + void SetOrientation(const zeus::CTransform&); + void SetTranslation(const zeus::CVector3f&); + void SetGlobalOrientation(const zeus::CTransform&); + void SetGlobalTranslation(const zeus::CVector3f&); + void SetGlobalScale(const zeus::CVector3f&); + void SetLocalScale(const zeus::CVector3f&); + void SetParticleEmission(bool); + void SetModulationColor(const zeus::CColor&); + void SetOverrideIPos(const zeus::CVector3f& vec) { x178_overrideIPos.emplace(vec); } + void SetOverrideIVel(const zeus::CVector3f& vec) { x188_overrideIVel.emplace(vec); } + void SetOverrideFPos(const zeus::CVector3f& vec) { x198_overrideFPos.emplace(vec); } + void SetOverrideFVel(const zeus::CVector3f& vec) { x1a8_overrideFVel.emplace(vec); } + const zeus::CTransform& GetOrientation() const; + const zeus::CVector3f& GetTranslation() const; + const zeus::CTransform& GetGlobalOrientation() const; + const zeus::CVector3f& GetGlobalTranslation() const; + const zeus::CVector3f& GetGlobalScale() const; + const zeus::CColor& GetModulationColor() const; + bool IsSystemDeletable() const; + std::experimental::optional GetBounds() const; + u32 GetParticleCount() const; + bool SystemHasLight() const; + CLight GetLight() const; + bool GetParticleEmission() const; + void DestroyParticles(); + void Reset() {} + void ForceParticleCreation(s32 count) { + CGlobalRandom gRnd{x14c_randState}; + CreateNewParticles(count); + } + FourCC Get4CharId() const { return FOURCC('ELSC'); } }; -} - +} // namespace urde diff --git a/Runtime/Particle/CParticleElectricDataFactory.cpp b/Runtime/Particle/CParticleElectricDataFactory.cpp index 81c15e33a..ebf31104d 100644 --- a/Runtime/Particle/CParticleElectricDataFactory.cpp +++ b/Runtime/Particle/CParticleElectricDataFactory.cpp @@ -7,136 +7,124 @@ #include "CSimplePool.hpp" #include "CRandom16.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CParticleElectricDataFactory"); using CPF = CParticleDataFactory; -CElectricDescription* CParticleElectricDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) -{ - return CreateElectricDescription(in, resPool); +CElectricDescription* CParticleElectricDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) { + return CreateElectricDescription(in, resPool); } -CElectricDescription* CParticleElectricDataFactory::CreateElectricDescription(CInputStream& in, CSimplePool* resPool) -{ - FourCC cid = CPF::GetClassID(in); - if (cid == FOURCC('ELSM')) - { - CElectricDescription* desc = new CElectricDescription; - CreateELSM(desc, in, resPool); - LoadELSMTokens(desc); - return desc; +CElectricDescription* CParticleElectricDataFactory::CreateElectricDescription(CInputStream& in, CSimplePool* resPool) { + FourCC cid = CPF::GetClassID(in); + if (cid == FOURCC('ELSM')) { + CElectricDescription* desc = new CElectricDescription; + CreateELSM(desc, in, resPool); + LoadELSMTokens(desc); + return desc; + } + + return nullptr; +} + +bool CParticleElectricDataFactory::CreateELSM(CElectricDescription* desc, CInputStream& in, CSimplePool* resPool) { + CRandom16 rand; + CGlobalRandom gr{rand}; + + FourCC clsId = CPF::GetClassID(in); + while (clsId != SBIG('_END')) { + switch (clsId) { + case SBIG('LIFE'): + desc->x0_LIFE = CPF::GetIntElement(in); + break; + case SBIG('SLIF'): + desc->x4_SLIF = CPF::GetIntElement(in); + break; + case SBIG('GRAT'): + desc->x8_GRAT = CPF::GetRealElement(in); + break; + case SBIG('SCNT'): + desc->xc_SCNT = CPF::GetIntElement(in); + break; + case SBIG('SSEG'): + desc->x10_SSEG = CPF::GetIntElement(in); + break; + case SBIG('COLR'): + desc->x14_COLR = CPF::GetColorElement(in); + break; + case SBIG('IEMT'): + desc->x18_IEMT = CPF::GetEmitterElement(in); + break; + case SBIG('FEMT'): + desc->x1c_FEMT = CPF::GetEmitterElement(in); + break; + case SBIG('AMPL'): + desc->x20_AMPL = CPF::GetRealElement(in); + break; + case SBIG('AMPD'): + desc->x24_AMPD = CPF::GetRealElement(in); + break; + case SBIG('LWD1'): + desc->x28_LWD1 = CPF::GetRealElement(in); + break; + case SBIG('LWD2'): + desc->x2c_LWD2 = CPF::GetRealElement(in); + break; + case SBIG('LWD3'): + desc->x30_LWD3 = CPF::GetRealElement(in); + break; + case SBIG('LCL1'): + desc->x34_LCL1 = CPF::GetColorElement(in); + break; + case SBIG('LCL2'): + desc->x38_LCL2 = CPF::GetColorElement(in); + break; + case SBIG('LCL3'): + desc->x3c_LCL3 = CPF::GetColorElement(in); + break; + case SBIG('SSWH'): + desc->x40_SSWH = CPF::GetSwooshGeneratorDesc(in, resPool); + break; + case SBIG('GPSM'): { + std::vector tracker; + tracker.reserve(8); + desc->x50_GPSM = CPF::GetChildGeneratorDesc(in, resPool, tracker); + break; } - - return nullptr; -} - -bool CParticleElectricDataFactory::CreateELSM(CElectricDescription* desc, CInputStream& in, CSimplePool* resPool) -{ - CRandom16 rand; - CGlobalRandom gr{rand}; - - FourCC clsId = CPF::GetClassID(in); - while (clsId != SBIG('_END')) - { - switch (clsId) - { - case SBIG('LIFE'): - desc->x0_LIFE = CPF::GetIntElement(in); - break; - case SBIG('SLIF'): - desc->x4_SLIF = CPF::GetIntElement(in); - break; - case SBIG('GRAT'): - desc->x8_GRAT = CPF::GetRealElement(in); - break; - case SBIG('SCNT'): - desc->xc_SCNT = CPF::GetIntElement(in); - break; - case SBIG('SSEG'): - desc->x10_SSEG = CPF::GetIntElement(in); - break; - case SBIG('COLR'): - desc->x14_COLR = CPF::GetColorElement(in); - break; - case SBIG('IEMT'): - desc->x18_IEMT = CPF::GetEmitterElement(in); - break; - case SBIG('FEMT'): - desc->x1c_FEMT = CPF::GetEmitterElement(in); - break; - case SBIG('AMPL'): - desc->x20_AMPL = CPF::GetRealElement(in); - break; - case SBIG('AMPD'): - desc->x24_AMPD = CPF::GetRealElement(in); - break; - case SBIG('LWD1'): - desc->x28_LWD1 = CPF::GetRealElement(in); - break; - case SBIG('LWD2'): - desc->x2c_LWD2 = CPF::GetRealElement(in); - break; - case SBIG('LWD3'): - desc->x30_LWD3 = CPF::GetRealElement(in); - break; - case SBIG('LCL1'): - desc->x34_LCL1 = CPF::GetColorElement(in); - break; - case SBIG('LCL2'): - desc->x38_LCL2 = CPF::GetColorElement(in); - break; - case SBIG('LCL3'): - desc->x3c_LCL3 = CPF::GetColorElement(in); - break; - case SBIG('SSWH'): - desc->x40_SSWH = CPF::GetSwooshGeneratorDesc(in, resPool); - break; - case SBIG('GPSM'): - { - std::vector tracker; - tracker.reserve(8); - desc->x50_GPSM = CPF::GetChildGeneratorDesc(in, resPool, tracker); - break; - } - case SBIG('EPSM'): - { - std::vector tracker; - tracker.reserve(8); - desc->x60_EPSM = CPF::GetChildGeneratorDesc(in, resPool, tracker); - break; - } - case SBIG('ZERY'): - desc->x70_ZERY = CPF::GetBool(in); - break; - default: - { - uint32_t clsName = clsId.toUint32(); - Log.report(logvisor::Fatal, "Unknown ELSM class %.4s @%" PRIi64, &clsName, in.position()); - return false; - } - } - clsId = CPF::GetClassID(in); + case SBIG('EPSM'): { + std::vector tracker; + tracker.reserve(8); + desc->x60_EPSM = CPF::GetChildGeneratorDesc(in, resPool, tracker); + break; } - return true; + case SBIG('ZERY'): + desc->x70_ZERY = CPF::GetBool(in); + break; + default: { + uint32_t clsName = clsId.toUint32(); + Log.report(logvisor::Fatal, "Unknown ELSM class %.4s @%" PRIi64, &clsName, in.position()); + return false; + } + } + clsId = CPF::GetClassID(in); + } + return true; } -void CParticleElectricDataFactory::LoadELSMTokens(CElectricDescription* desc) -{ - if (desc->x40_SSWH.m_found) - desc->x40_SSWH.m_swoosh = desc->x40_SSWH.m_token.GetObj(); - if (desc->x50_GPSM.m_found) - desc->x50_GPSM.m_gen = desc->x50_GPSM.m_token.GetObj(); - if (desc->x60_EPSM.m_found) - desc->x60_EPSM.m_gen = desc->x60_EPSM.m_token.GetObj(); +void CParticleElectricDataFactory::LoadELSMTokens(CElectricDescription* desc) { + if (desc->x40_SSWH.m_found) + desc->x40_SSWH.m_swoosh = desc->x40_SSWH.m_token.GetObj(); + if (desc->x50_GPSM.m_found) + desc->x50_GPSM.m_gen = desc->x50_GPSM.m_token.GetObj(); + if (desc->x60_EPSM.m_found) + desc->x60_EPSM.m_gen = desc->x60_EPSM.m_token.GetObj(); } CFactoryFnReturn FParticleElectricDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, - CObjectReference*) -{ - CSimplePool* sp = vparms.GetOwnedObj(); - return TToken::GetIObjObjectFor( - std::unique_ptr(CParticleElectricDataFactory::GetGeneratorDesc(in, sp))); -} + CObjectReference*) { + CSimplePool* sp = vparms.GetOwnedObj(); + return TToken::GetIObjObjectFor( + std::unique_ptr(CParticleElectricDataFactory::GetGeneratorDesc(in, sp))); } +} // namespace urde diff --git a/Runtime/Particle/CParticleElectricDataFactory.hpp b/Runtime/Particle/CParticleElectricDataFactory.hpp index 70cf5b487..96f53a40e 100644 --- a/Runtime/Particle/CParticleElectricDataFactory.hpp +++ b/Runtime/Particle/CParticleElectricDataFactory.hpp @@ -6,20 +6,18 @@ #include "CToken.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { class CElectricDescription; class CSimplePool; -class CParticleElectricDataFactory -{ - static CElectricDescription* CreateElectricDescription(CInputStream& in, CSimplePool* resPool); - static bool CreateELSM(CElectricDescription* desc, CInputStream& in, CSimplePool* resPool); - static void LoadELSMTokens(CElectricDescription* desc); +class CParticleElectricDataFactory { + static CElectricDescription* CreateElectricDescription(CInputStream& in, CSimplePool* resPool); + static bool CreateELSM(CElectricDescription* desc, CInputStream& in, CSimplePool* resPool); + static void LoadELSMTokens(CElectricDescription* desc); + public: - static CElectricDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); + static CElectricDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); }; CFactoryFnReturn FParticleElectricDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference*); -} - +} // namespace urde diff --git a/Runtime/Particle/CParticleGen.cpp b/Runtime/Particle/CParticleGen.cpp index 6f8963345..7361cb7c9 100644 --- a/Runtime/Particle/CParticleGen.cpp +++ b/Runtime/Particle/CParticleGen.cpp @@ -1,11 +1,7 @@ #include "CParticleGen.hpp" -namespace urde -{ +namespace urde { -void CParticleGen::AddModifier(CWarp* mod) -{ - x4_modifierList.push_back(mod); -} +void CParticleGen::AddModifier(CWarp* mod) { x4_modifierList.push_back(mod); } -} +} // namespace urde diff --git a/Runtime/Particle/CParticleGen.hpp b/Runtime/Particle/CParticleGen.hpp index dd913f67d..35e17295f 100644 --- a/Runtime/Particle/CParticleGen.hpp +++ b/Runtime/Particle/CParticleGen.hpp @@ -8,60 +8,57 @@ #include "zeus/CAABox.hpp" #include -namespace urde -{ +namespace urde { class CWarp; class CActorLights; -struct CParticle -{ - int x0_endFrame = 0; - zeus::CVector3f x4_pos; - zeus::CVector3f x10_prevPos; - zeus::CVector3f x1c_vel; - int x28_startFrame = 0; - float x2c_lineLengthOrSize = 0.f; - float x30_lineWidthOrRota = 0.f; - zeus::CColor x34_color = {0.f, 0.f, 0.f, 1.f}; +struct CParticle { + int x0_endFrame = 0; + zeus::CVector3f x4_pos; + zeus::CVector3f x10_prevPos; + zeus::CVector3f x1c_vel; + int x28_startFrame = 0; + float x2c_lineLengthOrSize = 0.f; + float x30_lineWidthOrRota = 0.f; + zeus::CColor x34_color = {0.f, 0.f, 0.f, 1.f}; }; -class CParticleGen -{ +class CParticleGen { protected: - std::list x4_modifierList; + std::list x4_modifierList; + public: - virtual ~CParticleGen() = default; + virtual ~CParticleGen() = default; - virtual bool Update(double)=0; - virtual void Render(const CActorLights* = nullptr)=0; - virtual void SetOrientation(const zeus::CTransform&)=0; - virtual void SetTranslation(const zeus::CVector3f&)=0; - virtual void SetGlobalOrientation(const zeus::CTransform&)=0; - virtual void SetGlobalTranslation(const zeus::CVector3f&)=0; - virtual void SetGlobalScale(const zeus::CVector3f&)=0; - virtual void SetLocalScale(const zeus::CVector3f&)=0; - virtual void SetParticleEmission(bool)=0; - virtual void SetModulationColor(const zeus::CColor&)=0; - virtual void SetGeneratorRate(float rate) {} - virtual const zeus::CTransform& GetOrientation() const=0; - virtual const zeus::CVector3f& GetTranslation() const=0; - virtual const zeus::CTransform& GetGlobalOrientation() const=0; - virtual const zeus::CVector3f& GetGlobalTranslation() const=0; - virtual const zeus::CVector3f& GetGlobalScale() const=0; - virtual const zeus::CColor& GetModulationColor() const=0; - virtual float GetGeneratorRate() const { return 1.f; } - virtual bool IsSystemDeletable() const=0; - virtual std::experimental::optional GetBounds() const=0; - virtual u32 GetParticleCount() const=0; - virtual bool SystemHasLight() const=0; - virtual CLight GetLight() const=0; - virtual bool GetParticleEmission() const=0; - virtual void DestroyParticles()=0; - virtual void Reset()=0; - virtual FourCC Get4CharId() const=0; + virtual bool Update(double) = 0; + virtual void Render(const CActorLights* = nullptr) = 0; + virtual void SetOrientation(const zeus::CTransform&) = 0; + virtual void SetTranslation(const zeus::CVector3f&) = 0; + virtual void SetGlobalOrientation(const zeus::CTransform&) = 0; + virtual void SetGlobalTranslation(const zeus::CVector3f&) = 0; + virtual void SetGlobalScale(const zeus::CVector3f&) = 0; + virtual void SetLocalScale(const zeus::CVector3f&) = 0; + virtual void SetParticleEmission(bool) = 0; + virtual void SetModulationColor(const zeus::CColor&) = 0; + virtual void SetGeneratorRate(float rate) {} + virtual const zeus::CTransform& GetOrientation() const = 0; + virtual const zeus::CVector3f& GetTranslation() const = 0; + virtual const zeus::CTransform& GetGlobalOrientation() const = 0; + virtual const zeus::CVector3f& GetGlobalTranslation() const = 0; + virtual const zeus::CVector3f& GetGlobalScale() const = 0; + virtual const zeus::CColor& GetModulationColor() const = 0; + virtual float GetGeneratorRate() const { return 1.f; } + virtual bool IsSystemDeletable() const = 0; + virtual std::experimental::optional GetBounds() const = 0; + virtual u32 GetParticleCount() const = 0; + virtual bool SystemHasLight() const = 0; + virtual CLight GetLight() const = 0; + virtual bool GetParticleEmission() const = 0; + virtual void DestroyParticles() = 0; + virtual void Reset() = 0; + virtual FourCC Get4CharId() const = 0; - virtual void AddModifier(CWarp* mod); + virtual void AddModifier(CWarp* mod); }; -} - +} // namespace urde diff --git a/Runtime/Particle/CParticleGlobals.cpp b/Runtime/Particle/CParticleGlobals.cpp index c806ead58..42d8ace65 100644 --- a/Runtime/Particle/CParticleGlobals.cpp +++ b/Runtime/Particle/CParticleGlobals.cpp @@ -1,7 +1,6 @@ #include "CParticleGlobals.hpp" -namespace urde -{ +namespace urde { int CParticleGlobals::g_EmitterTime = 0; float CParticleGlobals::g_EmitterTimeReal = 0.0; @@ -15,4 +14,4 @@ float CParticleGlobals::g_ParticleLifetimePercentageRemainder = 0.0; const std::array* CParticleGlobals::g_particleAccessParameters = nullptr; CParticleGlobals::SParticleSystem* CParticleGlobals::g_currentParticleSystem = nullptr; -} +} // namespace urde diff --git a/Runtime/Particle/CParticleGlobals.hpp b/Runtime/Particle/CParticleGlobals.hpp index 4665729d0..281877cdd 100644 --- a/Runtime/Particle/CParticleGlobals.hpp +++ b/Runtime/Particle/CParticleGlobals.hpp @@ -7,80 +7,69 @@ #include "RetroTypes.hpp" #include -namespace urde -{ +namespace urde { class CElementGen; -class CParticleGlobals -{ +class CParticleGlobals { public: - static int g_EmitterTime; - static float g_EmitterTimeReal; - static void SetEmitterTime(int frame) - { - g_EmitterTime = frame; - g_EmitterTimeReal = frame; - } + static int g_EmitterTime; + static float g_EmitterTimeReal; + static void SetEmitterTime(int frame) { + g_EmitterTime = frame; + g_EmitterTimeReal = frame; + } - static int g_ParticleLifetime; - static float g_ParticleLifetimeReal; - static void SetParticleLifetime(int frame) - { - g_ParticleLifetime = frame; - g_ParticleLifetimeReal = frame; - } + static int g_ParticleLifetime; + static float g_ParticleLifetimeReal; + static void SetParticleLifetime(int frame) { + g_ParticleLifetime = frame; + g_ParticleLifetimeReal = frame; + } - static int g_ParticleLifetimePercentage; - static float g_ParticleLifetimePercentageReal; - static float g_ParticleLifetimePercentageRemainder; - static void UpdateParticleLifetimeTweenValues(int frame) - { - float lt = g_ParticleLifetime != 0.0f ? g_ParticleLifetime : 1.0f; - g_ParticleLifetimePercentageReal = 100.0f * frame / lt; - g_ParticleLifetimePercentage = int(g_ParticleLifetimePercentageReal); - g_ParticleLifetimePercentageRemainder = g_ParticleLifetimePercentageReal - g_ParticleLifetimePercentage; - g_ParticleLifetimePercentage = zeus::clamp(0, g_ParticleLifetimePercentage, 100); - } + static int g_ParticleLifetimePercentage; + static float g_ParticleLifetimePercentageReal; + static float g_ParticleLifetimePercentageRemainder; + static void UpdateParticleLifetimeTweenValues(int frame) { + float lt = g_ParticleLifetime != 0.0f ? g_ParticleLifetime : 1.0f; + g_ParticleLifetimePercentageReal = 100.0f * frame / lt; + g_ParticleLifetimePercentage = int(g_ParticleLifetimePercentageReal); + g_ParticleLifetimePercentageRemainder = g_ParticleLifetimePercentageReal - g_ParticleLifetimePercentage; + g_ParticleLifetimePercentage = zeus::clamp(0, g_ParticleLifetimePercentage, 100); + } - static const std::array* g_particleAccessParameters; + static const std::array* g_particleAccessParameters; - struct SParticleSystem - { - FourCC x0_type; - CElementGen* x4_system; - }; + struct SParticleSystem { + FourCC x0_type; + CElementGen* x4_system; + }; - static SParticleSystem* g_currentParticleSystem; + static SParticleSystem* g_currentParticleSystem; }; -struct SParticleInstanceTex -{ - zeus::CVector4f pos[4]; - zeus::CColor color; - zeus::CVector2f uvs[4]; +struct SParticleInstanceTex { + zeus::CVector4f pos[4]; + zeus::CColor color; + zeus::CVector2f uvs[4]; }; extern std::vector g_instTexData; -struct SParticleInstanceIndTex -{ - zeus::CVector4f pos[4]; - zeus::CColor color; - zeus::CVector4f texrTindUVs[4]; - zeus::CVector4f sceneUVs; +struct SParticleInstanceIndTex { + zeus::CVector4f pos[4]; + zeus::CColor color; + zeus::CVector4f texrTindUVs[4]; + zeus::CVector4f sceneUVs; }; extern std::vector g_instIndTexData; -struct SParticleInstanceNoTex -{ - zeus::CVector4f pos[4]; - zeus::CColor color; +struct SParticleInstanceNoTex { + zeus::CVector4f pos[4]; + zeus::CColor color; }; extern std::vector g_instNoTexData; -struct SParticleUniforms -{ - zeus::CMatrix4f mvp; - zeus::CColor moduColor; +struct SParticleUniforms { + zeus::CMatrix4f mvp; + zeus::CColor moduColor; }; -} - +} // namespace urde diff --git a/Runtime/Particle/CParticleSwoosh.cpp b/Runtime/Particle/CParticleSwoosh.cpp index 130739c01..f52968006 100644 --- a/Runtime/Particle/CParticleSwoosh.cpp +++ b/Runtime/Particle/CParticleSwoosh.cpp @@ -3,1189 +3,1012 @@ #include "CParticleGlobals.hpp" #include -namespace urde -{ +namespace urde { int CParticleSwoosh::g_ParticleSystemAliveCount = 0; CParticleSwoosh::CParticleSwoosh(const TToken& desc, int leng) -: x1c_desc(desc), x1c0_rand(x1c_desc->x45_26_CRND ? - std::chrono::duration_cast( - std::chrono::steady_clock::now().time_since_epoch()).count() : 99) -{ - x1d0_24_emitting = true; - ++g_ParticleSystemAliveCount; +: x1c_desc(desc) +, x1c0_rand(x1c_desc->x45_26_CRND ? std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()) + .count() + : 99) { + x1d0_24_emitting = true; + ++g_ParticleSystemAliveCount; - if (leng > 0) - x1b4_LENG = leng; - else if (CIntElement* leng = x1c_desc->x10_LENG.get()) - leng->GetValue(0, x1b4_LENG); - x1b4_LENG += 1; + if (leng > 0) + x1b4_LENG = leng; + else if (CIntElement* leng = x1c_desc->x10_LENG.get()) + leng->GetValue(0, x1b4_LENG); + x1b4_LENG += 1; - if (CIntElement* side = x1c_desc->x18_SIDE.get()) - side->GetValue(0, x1b8_SIDE); + if (CIntElement* side = x1c_desc->x18_SIDE.get()) + side->GetValue(0, x1b8_SIDE); - x1d0_28_LLRD = x1c_desc->x44_24_LLRD; - x1d0_29_VLS1 = x1c_desc->x44_26_VLS1; - x1d0_30_VLS2 = x1c_desc->x44_27_VLS2; + x1d0_28_LLRD = x1c_desc->x44_24_LLRD; + x1d0_29_VLS1 = x1c_desc->x44_26_VLS1; + x1d0_30_VLS2 = x1c_desc->x44_27_VLS2; - if (IsValid()) - { - if (CIntElement* pslt = x1c_desc->x0_PSLT.get()) - pslt->GetValue(0, x2c_PSLT); - else - x2c_PSLT = INT_MAX; + if (IsValid()) { + if (CIntElement* pslt = x1c_desc->x0_PSLT.get()) + pslt->GetValue(0, x2c_PSLT); + else + x2c_PSLT = INT_MAX; - x1d0_25_AALP = x1c_desc->x44_31_AALP; + x1d0_25_AALP = x1c_desc->x44_31_AALP; - if (CIntElement* spln = x1c_desc->x38_SPLN.get()) - spln->GetValue(0, x1b0_SPLN); - if (x1b0_SPLN < 0) - x1b0_SPLN = 0; + if (CIntElement* spln = x1c_desc->x38_SPLN.get()) + spln->GetValue(0, x1b0_SPLN); + if (x1b0_SPLN < 0) + x1b0_SPLN = 0; - x15c_swooshes.clear(); - x15c_swooshes.reserve(x1b4_LENG); - for (int i=0 ; ix44_29_WIRE) - { - int maxVerts = x1b4_LENG * (x1b0_SPLN+1) * x1b8_SIDE * 12; - m_lineRenderer.reset(new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, - maxVerts * 2, nullptr, x1d0_25_AALP)); - } - else - { - int maxVerts = x1b4_LENG * (x1b0_SPLN+1) * x1b8_SIDE * 4; - m_cachedVerts.reserve(maxVerts); - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - m_vertBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(CParticleSwooshShaders::Vert), maxVerts); - m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CMatrix4f), 1); - CParticleSwooshShaders::BuildShaderDataBinding(ctx, *this); - return true; - } BooTrace); - } + if (x1c_desc->x44_29_WIRE) { + int maxVerts = x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 12; + m_lineRenderer.reset( + new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, nullptr, x1d0_25_AALP)); + } else { + int maxVerts = x1b4_LENG * (x1b0_SPLN + 1) * x1b8_SIDE * 4; + m_cachedVerts.reserve(maxVerts); + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + m_vertBuf = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(CParticleSwooshShaders::Vert), maxVerts); + m_uniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CMatrix4f), 1); + CParticleSwooshShaders::BuildShaderDataBinding(ctx, *this); + return true; + } BooTrace); } + } } -CParticleSwoosh::~CParticleSwoosh() -{ - --g_ParticleSystemAliveCount; +CParticleSwoosh::~CParticleSwoosh() { --g_ParticleSystemAliveCount; } + +void CParticleSwoosh::UpdateMaxRadius(float r) { x208_maxRadius = std::max(x208_maxRadius, r); } + +void CParticleSwoosh::UpdateBounds(const zeus::CVector3f& pos) { + x1fc_aabbMax[0] = std::max(pos[0], float(x1fc_aabbMax[0])); + x1fc_aabbMax[1] = std::max(pos[1], float(x1fc_aabbMax[1])); + x1fc_aabbMax[2] = std::max(pos[2], float(x1fc_aabbMax[2])); + x1f0_aabbMin[0] = std::min(pos[0], float(x1f0_aabbMin[0])); + x1f0_aabbMin[1] = std::min(pos[1], float(x1f0_aabbMin[1])); + x1f0_aabbMin[2] = std::min(pos[2], float(x1f0_aabbMin[2])); } -void CParticleSwoosh::UpdateMaxRadius(float r) -{ - x208_maxRadius = std::max(x208_maxRadius, r); +float CParticleSwoosh::GetLeftRadius(int i) const { + float ret = 0.f; + if (CRealElement* lrad = x1c_desc->x8_LRAD.get()) + lrad->GetValue(x15c_swooshes[i].x68_frame, ret); + return ret; } -void CParticleSwoosh::UpdateBounds(const zeus::CVector3f& pos) -{ - x1fc_aabbMax[0] = std::max(pos[0], float(x1fc_aabbMax[0])); - x1fc_aabbMax[1] = std::max(pos[1], float(x1fc_aabbMax[1])); - x1fc_aabbMax[2] = std::max(pos[2], float(x1fc_aabbMax[2])); - x1f0_aabbMin[0] = std::min(pos[0], float(x1f0_aabbMin[0])); - x1f0_aabbMin[1] = std::min(pos[1], float(x1f0_aabbMin[1])); - x1f0_aabbMin[2] = std::min(pos[2], float(x1f0_aabbMin[2])); +float CParticleSwoosh::GetRightRadius(int i) const { + float ret = 0.f; + if (CRealElement* rrad = x1c_desc->xc_RRAD.get()) + rrad->GetValue(x15c_swooshes[i].x68_frame, ret); + return ret; } -float CParticleSwoosh::GetLeftRadius(int i) const -{ - float ret = 0.f; - if (CRealElement* lrad = x1c_desc->x8_LRAD.get()) - lrad->GetValue(x15c_swooshes[i].x68_frame, ret); - return ret; +void CParticleSwoosh::UpdateSwooshTranslation(const zeus::CVector3f& translation) { + x15c_swooshes[x158_curParticle].xc_translation = x11c_invScaleXf * translation; } -float CParticleSwoosh::GetRightRadius(int i) const -{ - float ret = 0.f; - if (CRealElement* rrad = x1c_desc->xc_RRAD.get()) - rrad->GetValue(x15c_swooshes[i].x68_frame, ret); - return ret; -} +void CParticleSwoosh::UpdateTranslationAndOrientation() { + x208_maxRadius = 0.f; + x1f0_aabbMin = zeus::CVector3f(FLT_MAX); + x1fc_aabbMax = zeus::CVector3f(-FLT_MAX); + CParticleGlobals::SetParticleLifetime(x1b4_LENG); + CParticleGlobals::SetEmitterTime(x28_curFrame); -void CParticleSwoosh::UpdateSwooshTranslation(const zeus::CVector3f& translation) -{ - x15c_swooshes[x158_curParticle].xc_translation = x11c_invScaleXf * translation; -} + for (int i = 0; i < x15c_swooshes.size(); ++i) { + SSwooshData& swoosh = x15c_swooshes[i]; + if (!swoosh.x0_active) + continue; -void CParticleSwoosh::UpdateTranslationAndOrientation() -{ - x208_maxRadius = 0.f; - x1f0_aabbMin = zeus::CVector3f(FLT_MAX); - x1fc_aabbMax = zeus::CVector3f(-FLT_MAX); - CParticleGlobals::SetParticleLifetime(x1b4_LENG); - CParticleGlobals::SetEmitterTime(x28_curFrame); - - for (int i=0 ; ix44_28_SROT) - { - if (CRealElement* irot = x1c_desc->x1c_IROT.get()) - irot->GetValue(x28_curFrame, swoosh.x30_irot); - swoosh.x34_rotm = 0.f; - } - else - { - if (CRealElement* rotm = x1c_desc->x20_ROTM.get()) - rotm->GetValue(x28_curFrame, swoosh.x34_rotm); - else - swoosh.x34_rotm = 0.f; - } - - if (CModVectorElement* velm = x1c_desc->x30_VELM.get()) - { - if (x1d0_29_VLS1) - { - zeus::CVector3f localVel = x74_invOrientation * swoosh.x74_velocity; - zeus::CVector3f localTrans = x74_invOrientation * (swoosh.xc_translation - x38_translation); - velm->GetValue(swoosh.x68_frame, localVel, localTrans); - swoosh.x74_velocity = x44_orientation * localVel; - swoosh.xc_translation = x44_orientation * localTrans + x38_translation; - } - else - { - velm->GetValue(swoosh.x68_frame, swoosh.x74_velocity, swoosh.xc_translation); - } - } - - if (CModVectorElement* vlm2 = x1c_desc->x34_VLM2.get()) - { - if (x1d0_30_VLS2) - { - zeus::CVector3f localVel = x74_invOrientation * swoosh.x74_velocity; - zeus::CVector3f localTrans = x74_invOrientation * (swoosh.xc_translation - x38_translation); - vlm2->GetValue(swoosh.x68_frame, localVel, localTrans); - swoosh.x74_velocity = x44_orientation * localVel; - swoosh.xc_translation = x44_orientation * localTrans + x38_translation; - } - else - { - vlm2->GetValue(swoosh.x68_frame, swoosh.x74_velocity, swoosh.xc_translation); - } - } - - if (swoosh.x68_frame > 0) - { - swoosh.xc_translation += swoosh.x74_velocity; - } - - if (CVectorElement* npos = x1c_desc->x2c_NPOS.get()) - { - zeus::CVector3f vec; - npos->GetValue(swoosh.x68_frame, vec); - swoosh.x24_useOffset = swoosh.x18_offset + vec; - } - - if (CColorElement* colr = x1c_desc->x14_COLR.get()) - { - colr->GetValue(swoosh.x68_frame, swoosh.x6c_color); - } - - swoosh.x4_leftRad = GetLeftRadius(i); - UpdateMaxRadius(swoosh.x4_leftRad); - - if (x1d0_28_LLRD) - { - swoosh.x8_rightRad = swoosh.x4_leftRad; - } - else - { - swoosh.x8_rightRad = GetRightRadius(i); - UpdateMaxRadius(swoosh.x8_rightRad); - } - - UpdateBounds(swoosh.xc_translation + swoosh.x24_useOffset); - } -} - -bool CParticleSwoosh::Update(double dt) -{ - if (!IsValid()) - return false; - - CParticleGlobals::SetParticleLifetime(x1b4_LENG); - CParticleGlobals::SetEmitterTime(x28_curFrame); - CParticleGlobals::UpdateParticleLifetimeTweenValues(0); - CGlobalRandom gr(x1c0_rand); - - double evalTime = x28_curFrame / 60.0; - float time = 1.f; - if (CRealElement* timeElem = x1c_desc->x4_TIME.get()) - timeElem->GetValue(x28_curFrame, time); - - x30_curTime += std::max(0.0, dt * time); - while (x1d0_26_forceOneUpdate || evalTime < x30_curTime) - { - x1d0_26_forceOneUpdate = false; - - x158_curParticle += 1; - if (x158_curParticle >= x15c_swooshes.size()) - x158_curParticle = 0; - - if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) - { - UpdateSwooshTranslation(x38_translation); - - if (CRealElement* irot = x1c_desc->x1c_IROT.get()) - irot->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x30_irot); - else - x15c_swooshes[x158_curParticle].x30_irot = 0.f; - - x15c_swooshes[x158_curParticle].x34_rotm = 0.f; - x15c_swooshes[x158_curParticle].x70_startFrame = x28_curFrame; - - if (!x15c_swooshes[x158_curParticle].x0_active) - { - x1ac_particleCount += 1; - x15c_swooshes[x158_curParticle].x0_active = true; - } - - x15c_swooshes[x158_curParticle].x38_orientation = x44_orientation; - - if (CVectorElement* ivel = x1c_desc->x28_IVEL.get()) - { - ivel->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x74_velocity); - x15c_swooshes[x158_curParticle].x74_velocity = x44_orientation * x15c_swooshes[x158_curParticle].x74_velocity; - } - - if (CVectorElement* pofs = x1c_desc->x24_POFS.get()) - pofs->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x18_offset); - - x15c_swooshes[x158_curParticle].x24_useOffset = x15c_swooshes[x158_curParticle].x18_offset; - - if (CColorElement* colr = x1c_desc->x14_COLR.get()) - colr->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x6c_color); - else - x15c_swooshes[x158_curParticle].x6c_color = zeus::CColor::skWhite; - - int tspn = 0; - if (CIntElement* tspnElem = x1c_desc->x40_TSPN.get()) - tspnElem->GetValue(x28_curFrame, tspn); - x1cc_TSPN = tspn; - } - else if (x15c_swooshes[x158_curParticle].x0_active) - { - x1ac_particleCount = std::max(0, int(x1ac_particleCount) - 1); - x15c_swooshes[x158_curParticle].x0_active = false; - } - - UpdateTranslationAndOrientation(); - - evalTime += (1.0 / 60.0); - x28_curFrame += 1; + swoosh.x68_frame = x28_curFrame - swoosh.x70_startFrame; + CParticleGlobals::UpdateParticleLifetimeTweenValues(swoosh.x68_frame); + if (x1c_desc->x44_28_SROT) { + if (CRealElement* irot = x1c_desc->x1c_IROT.get()) + irot->GetValue(x28_curFrame, swoosh.x30_irot); + swoosh.x34_rotm = 0.f; + } else { + if (CRealElement* rotm = x1c_desc->x20_ROTM.get()) + rotm->GetValue(x28_curFrame, swoosh.x34_rotm); + else + swoosh.x34_rotm = 0.f; } + if (CModVectorElement* velm = x1c_desc->x30_VELM.get()) { + if (x1d0_29_VLS1) { + zeus::CVector3f localVel = x74_invOrientation * swoosh.x74_velocity; + zeus::CVector3f localTrans = x74_invOrientation * (swoosh.xc_translation - x38_translation); + velm->GetValue(swoosh.x68_frame, localVel, localTrans); + swoosh.x74_velocity = x44_orientation * localVel; + swoosh.xc_translation = x44_orientation * localTrans + x38_translation; + } else { + velm->GetValue(swoosh.x68_frame, swoosh.x74_velocity, swoosh.xc_translation); + } + } + + if (CModVectorElement* vlm2 = x1c_desc->x34_VLM2.get()) { + if (x1d0_30_VLS2) { + zeus::CVector3f localVel = x74_invOrientation * swoosh.x74_velocity; + zeus::CVector3f localTrans = x74_invOrientation * (swoosh.xc_translation - x38_translation); + vlm2->GetValue(swoosh.x68_frame, localVel, localTrans); + swoosh.x74_velocity = x44_orientation * localVel; + swoosh.xc_translation = x44_orientation * localTrans + x38_translation; + } else { + vlm2->GetValue(swoosh.x68_frame, swoosh.x74_velocity, swoosh.xc_translation); + } + } + + if (swoosh.x68_frame > 0) { + swoosh.xc_translation += swoosh.x74_velocity; + } + + if (CVectorElement* npos = x1c_desc->x2c_NPOS.get()) { + zeus::CVector3f vec; + npos->GetValue(swoosh.x68_frame, vec); + swoosh.x24_useOffset = swoosh.x18_offset + vec; + } + + if (CColorElement* colr = x1c_desc->x14_COLR.get()) { + colr->GetValue(swoosh.x68_frame, swoosh.x6c_color); + } + + swoosh.x4_leftRad = GetLeftRadius(i); + UpdateMaxRadius(swoosh.x4_leftRad); + + if (x1d0_28_LLRD) { + swoosh.x8_rightRad = swoosh.x4_leftRad; + } else { + swoosh.x8_rightRad = GetRightRadius(i); + UpdateMaxRadius(swoosh.x8_rightRad); + } + + UpdateBounds(swoosh.xc_translation + swoosh.x24_useOffset); + } +} + +bool CParticleSwoosh::Update(double dt) { + if (!IsValid()) return false; + + CParticleGlobals::SetParticleLifetime(x1b4_LENG); + CParticleGlobals::SetEmitterTime(x28_curFrame); + CParticleGlobals::UpdateParticleLifetimeTweenValues(0); + CGlobalRandom gr(x1c0_rand); + + double evalTime = x28_curFrame / 60.0; + float time = 1.f; + if (CRealElement* timeElem = x1c_desc->x4_TIME.get()) + timeElem->GetValue(x28_curFrame, time); + + x30_curTime += std::max(0.0, dt * time); + while (x1d0_26_forceOneUpdate || evalTime < x30_curTime) { + x1d0_26_forceOneUpdate = false; + + x158_curParticle += 1; + if (x158_curParticle >= x15c_swooshes.size()) + x158_curParticle = 0; + + if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) { + UpdateSwooshTranslation(x38_translation); + + if (CRealElement* irot = x1c_desc->x1c_IROT.get()) + irot->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x30_irot); + else + x15c_swooshes[x158_curParticle].x30_irot = 0.f; + + x15c_swooshes[x158_curParticle].x34_rotm = 0.f; + x15c_swooshes[x158_curParticle].x70_startFrame = x28_curFrame; + + if (!x15c_swooshes[x158_curParticle].x0_active) { + x1ac_particleCount += 1; + x15c_swooshes[x158_curParticle].x0_active = true; + } + + x15c_swooshes[x158_curParticle].x38_orientation = x44_orientation; + + if (CVectorElement* ivel = x1c_desc->x28_IVEL.get()) { + ivel->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x74_velocity); + x15c_swooshes[x158_curParticle].x74_velocity = x44_orientation * x15c_swooshes[x158_curParticle].x74_velocity; + } + + if (CVectorElement* pofs = x1c_desc->x24_POFS.get()) + pofs->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x18_offset); + + x15c_swooshes[x158_curParticle].x24_useOffset = x15c_swooshes[x158_curParticle].x18_offset; + + if (CColorElement* colr = x1c_desc->x14_COLR.get()) + colr->GetValue(x28_curFrame, x15c_swooshes[x158_curParticle].x6c_color); + else + x15c_swooshes[x158_curParticle].x6c_color = zeus::CColor::skWhite; + + int tspn = 0; + if (CIntElement* tspnElem = x1c_desc->x40_TSPN.get()) + tspnElem->GetValue(x28_curFrame, tspn); + x1cc_TSPN = tspn; + } else if (x15c_swooshes[x158_curParticle].x0_active) { + x1ac_particleCount = std::max(0, int(x1ac_particleCount) - 1); + x15c_swooshes[x158_curParticle].x0_active = false; + } + + UpdateTranslationAndOrientation(); + + evalTime += (1.0 / 60.0); + x28_curFrame += 1; + } + + return false; } zeus::CVector3f CParticleSwoosh::GetSplinePoint(const zeus::CVector3f& p0, const zeus::CVector3f& p1, - const zeus::CVector3f& p2, const zeus::CVector3f& p3, float t) -{ - if (t > 0.f) - return p1; - if (t >= 1.f) - return p2; + const zeus::CVector3f& p2, const zeus::CVector3f& p3, float t) { + if (t > 0.f) + return p1; + if (t >= 1.f) + return p2; - // Tricubic spline interpolation - float t2 = t * t; - float t3 = t2 * t; + // Tricubic spline interpolation + float t2 = t * t; + float t3 = t2 * t; - float p0Coef = -0.5f * t3 + t2 - 0.5f * t; - float p1Coef = 1.5f * t3 - 2.5f * t2 + 1.f; - float p2Coef = -1.5f * t3 + 2.f * t2 + 0.5f * t; - float p3Coef = 0.5f * t3 + 0.5f * t2; + float p0Coef = -0.5f * t3 + t2 - 0.5f * t; + float p1Coef = 1.5f * t3 - 2.5f * t2 + 1.f; + float p2Coef = -1.5f * t3 + 2.f * t2 + 0.5f * t; + float p3Coef = 0.5f * t3 + 0.5f * t2; - return p0 * p0Coef + p1 * p1Coef + p2 * p2Coef + p3 * p3Coef; + return p0 * p0Coef + p1 * p1Coef + p2 * p2Coef + p3 * p3Coef; } -int CParticleSwoosh::WrapIndex(int i) const -{ - while (i < 0) - i += x1b4_LENG; - while (i >= x1b4_LENG) - i -= x1b4_LENG; - return i; +int CParticleSwoosh::WrapIndex(int i) const { + while (i < 0) + i += x1b4_LENG; + while (i >= x1b4_LENG) + i -= x1b4_LENG; + return i; } -void CParticleSwoosh::RenderNSidedSpline() -{ - if (x1c_desc->x44_29_WIRE) - { - x1bc_prim = GX::LINES; - m_lineRenderer->Reset(); - } - else - { - x1bc_prim = GX::QUADS; +void CParticleSwoosh::RenderNSidedSpline() { + if (x1c_desc->x44_29_WIRE) { + x1bc_prim = GX::LINES; + m_lineRenderer->Reset(); + } else { + x1bc_prim = GX::QUADS; + } + + bool cros = x1c_desc->x44_25_CROS; + if (x1b8_SIDE >= 4 || x1b8_SIDE & 0x1) + cros = false; + + int curIdx = x158_curParticle; + for (int i = 0; i < x15c_swooshes.size(); ++i) { + bool a0 = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active; + bool a1 = x15c_swooshes[WrapIndex(curIdx)].x0_active; + if (!a1 || (a1 && !a0)) { + curIdx -= 1; + if (curIdx < 0) + curIdx = x15c_swooshes.size() - 1; + continue; } - bool cros = x1c_desc->x44_25_CROS; - if (x1b8_SIDE >= 4 || x1b8_SIDE & 0x1) - cros = false; + SSwooshData& refSwoosh = x15c_swooshes[curIdx]; - int curIdx = x158_curParticle; - for (int i=0 ; i M_PIF) { + ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF; + if (ang > M_PIF) + ang -= 2.f * M_PIF; + else if (ang < -M_PIF) + ang += 2.f * M_PIF; } - SSwooshData& refSwoosh = x15c_swooshes[curIdx]; + float z = std::sin(ang); + float x = std::cos(ang); - float sideDiv = 360.f / float(x1b8_SIDE); - for (int j=0 ; j<4 ; ++j) - { - int crossRefIdx = 0; - if (j == 0) - { - crossRefIdx = WrapIndex(curIdx + 1); - if (!x15c_swooshes[crossRefIdx].x0_active) - crossRefIdx = curIdx; - } - else if (j == 1) - { - crossRefIdx = WrapIndex(curIdx); - } - else if (j == 2) - { - crossRefIdx = WrapIndex(curIdx - 1); - } - else if (j == 3) - { - crossRefIdx = WrapIndex(curIdx - 2); - if (!x15c_swooshes[crossRefIdx].x0_active) - crossRefIdx = WrapIndex(curIdx - 1); - } + float rad = (n > 0.f && n <= 180.f) ? crossSwoosh.x4_leftRad : crossSwoosh.x8_rightRad; + zeus::CVector3f offset = crossSwoosh.xc_translation + crossSwoosh.x24_useOffset; - if (x1b4_LENG == 2) - { - if (j == 0) - crossRefIdx = WrapIndex(curIdx); - if (j == 3) - crossRefIdx = WrapIndex(curIdx - 1); - } - else if (x158_curParticle == curIdx && j == 0) - { - crossRefIdx = x158_curParticle; - } - else - { - if (WrapIndex(x158_curParticle + 2) == curIdx && j == 3) - crossRefIdx = WrapIndex(x158_curParticle + 1); - else if (x1ac_particleCount - 2 == i && j == 3) - crossRefIdx = 0; - } - - SSwooshData& crossSwoosh = x15c_swooshes[crossRefIdx]; - for (int k=0 ; k M_PIF) - { - ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF; - if (ang > M_PIF) - ang -= 2.f * M_PIF; - else if (ang < -M_PIF) - ang += 2.f * M_PIF; - } - - float z = std::sin(ang); - float x = std::cos(ang); - - float rad = (n > 0.f && n <= 180.f) ? crossSwoosh.x4_leftRad : crossSwoosh.x8_rightRad; - zeus::CVector3f offset = crossSwoosh.xc_translation + crossSwoosh.x24_useOffset; - - if (j == 0) - x16c_p0[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; - else if (j == 1) - x17c_p1[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; - else if (j == 2) - x18c_p2[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; - else if (j == 3) - x19c_p3[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; - } - } - - if (x1c_desc->x3c_TEXR) - { - if (x1ec_TSPN > 0) - x1d4_uvs.xMin = (i % x1ec_TSPN) * x1e8_uvSpan; - else - x1d4_uvs.xMin = i * x1e8_uvSpan; - } - - float segUvSpan = x1e8_uvSpan / float(x1b0_SPLN + 1); - for (int j=0 ; j= x1b8_SIDE) - otherK = 0; - zeus::CColor color = refSwoosh.x6c_color * x20c_moduColor; - if (cros) - { - int otherK = k + x1b8_SIDE / 2; - zeus::CVector3f v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0); - zeus::CVector3f v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0); - zeus::CVector3f v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1); - zeus::CVector3f v3 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t1); - - m_cachedVerts.push_back({v0, {x1d4_uvs.xMin, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v1, {x1d4_uvs.xMin, x1d4_uvs.yMax}, color}); - m_cachedVerts.push_back({v2, {x1d4_uvs.xMax, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v3, {x1d4_uvs.xMax, x1d4_uvs.yMax}, color}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); - } - else - { - zeus::CVector3f v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0); - zeus::CVector3f v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0); - zeus::CVector3f v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1); - zeus::CVector3f v3 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t1); - - if (x1bc_prim == GX::LINES) - { - m_lineRenderer->AddVertex(v0, color, 1.f); - m_lineRenderer->AddVertex(v1, color, 1.f); - m_lineRenderer->AddVertex(v1, color, 1.f); - m_lineRenderer->AddVertex(v2, color, 1.f); - m_lineRenderer->AddVertex(v2, color, 1.f); - m_lineRenderer->AddVertex(v0, color, 1.f); - m_lineRenderer->AddVertex(v0, color, 1.f); - m_lineRenderer->AddVertex(v2, color, 1.f); - m_lineRenderer->AddVertex(v2, color, 1.f); - m_lineRenderer->AddVertex(v3, color, 1.f); - m_lineRenderer->AddVertex(v3, color, 1.f); - m_lineRenderer->AddVertex(v0, color, 1.f); - } - else if (x1bc_prim == GX::QUADS) - { - m_cachedVerts.push_back({v0, {x1d4_uvs.xMin, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v1, {x1d4_uvs.xMin, x1d4_uvs.yMax}, color}); - m_cachedVerts.push_back({v2, {x1d4_uvs.xMax, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v3, {x1d4_uvs.xMax, x1d4_uvs.yMax}, color}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); - } - } - } - - if (x1c_desc->x3c_TEXR && x1b0_SPLN > 0) - x1d4_uvs.xMin += segUvSpan; - } - - curIdx -= 1; - if (curIdx < 0) - curIdx = x15c_swooshes.size() - 1; + if (j == 0) + x16c_p0[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; + else if (j == 1) + x17c_p1[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; + else if (j == 2) + x18c_p2[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; + else if (j == 3) + x19c_p3[k] = crossSwoosh.x38_orientation * zeus::CVector3f(rad * x, 0.f, rad * z) + offset; + } } - if (x1bc_prim == GX::LINES) - m_lineRenderer->Render(); + if (x1c_desc->x3c_TEXR) { + if (x1ec_TSPN > 0) + x1d4_uvs.xMin = (i % x1ec_TSPN) * x1e8_uvSpan; + else + x1d4_uvs.xMin = i * x1e8_uvSpan; + } + + float segUvSpan = x1e8_uvSpan / float(x1b0_SPLN + 1); + for (int j = 0; j < x1b0_SPLN + 1; ++j) { + float t0 = j / float(x1b0_SPLN + 1); + float t1 = (j + 1) / float(x1b0_SPLN + 1); + int faces = x1b8_SIDE; + if (x1b8_SIDE <= 2) + faces = 1; + else if (cros) + faces = x1b8_SIDE / 2; + + x1d4_uvs.xMax = x1d4_uvs.xMin + segUvSpan; + + for (int k = 0; k < faces; ++k) { + int otherK = k + 1; + if (k + 1 >= x1b8_SIDE) + otherK = 0; + zeus::CColor color = refSwoosh.x6c_color * x20c_moduColor; + if (cros) { + int otherK = k + x1b8_SIDE / 2; + zeus::CVector3f v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0); + zeus::CVector3f v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0); + zeus::CVector3f v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1); + zeus::CVector3f v3 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t1); + + m_cachedVerts.push_back({v0, {x1d4_uvs.xMin, x1d4_uvs.yMin}, color}); + m_cachedVerts.push_back({v1, {x1d4_uvs.xMin, x1d4_uvs.yMax}, color}); + m_cachedVerts.push_back({v2, {x1d4_uvs.xMax, x1d4_uvs.yMin}, color}); + m_cachedVerts.push_back({v3, {x1d4_uvs.xMax, x1d4_uvs.yMax}, color}); + CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + } else { + zeus::CVector3f v0 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t0); + zeus::CVector3f v1 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t0); + zeus::CVector3f v2 = GetSplinePoint(x16c_p0[otherK], x17c_p1[otherK], x18c_p2[otherK], x19c_p3[otherK], t1); + zeus::CVector3f v3 = GetSplinePoint(x16c_p0[k], x17c_p1[k], x18c_p2[k], x19c_p3[k], t1); + + if (x1bc_prim == GX::LINES) { + m_lineRenderer->AddVertex(v0, color, 1.f); + m_lineRenderer->AddVertex(v1, color, 1.f); + m_lineRenderer->AddVertex(v1, color, 1.f); + m_lineRenderer->AddVertex(v2, color, 1.f); + m_lineRenderer->AddVertex(v2, color, 1.f); + m_lineRenderer->AddVertex(v0, color, 1.f); + m_lineRenderer->AddVertex(v0, color, 1.f); + m_lineRenderer->AddVertex(v2, color, 1.f); + m_lineRenderer->AddVertex(v2, color, 1.f); + m_lineRenderer->AddVertex(v3, color, 1.f); + m_lineRenderer->AddVertex(v3, color, 1.f); + m_lineRenderer->AddVertex(v0, color, 1.f); + } else if (x1bc_prim == GX::QUADS) { + m_cachedVerts.push_back({v0, {x1d4_uvs.xMin, x1d4_uvs.yMin}, color}); + m_cachedVerts.push_back({v1, {x1d4_uvs.xMin, x1d4_uvs.yMax}, color}); + m_cachedVerts.push_back({v2, {x1d4_uvs.xMax, x1d4_uvs.yMin}, color}); + m_cachedVerts.push_back({v3, {x1d4_uvs.xMax, x1d4_uvs.yMax}, color}); + CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + } + } + } + + if (x1c_desc->x3c_TEXR && x1b0_SPLN > 0) + x1d4_uvs.xMin += segUvSpan; + } + + curIdx -= 1; + if (curIdx < 0) + curIdx = x15c_swooshes.size() - 1; + } + + if (x1bc_prim == GX::LINES) + m_lineRenderer->Render(); } -void CParticleSwoosh::RenderNSidedNoSpline() -{ - RenderNSidedSpline(); +void CParticleSwoosh::RenderNSidedNoSpline() { RenderNSidedSpline(); } + +void CParticleSwoosh::Render3SidedSolidSpline() { + if (x15c_swooshes.size() < 2) + return; + + int curIdx = x158_curParticle; + float curUvSpan = -x1e8_uvSpan; + zeus::CColor prevColor0 = zeus::CColor::skClear; + for (int i = 0; i < x15c_swooshes.size(); ++i) { + SSwooshData& swoosh = x15c_swooshes[curIdx]; + + curIdx -= 1; + if (curIdx < 0) + curIdx = x15c_swooshes.size() - 1; + + float ang1 = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm); + if (std::fabs(ang1) > M_PIF) { + ang1 -= std::floor(ang1 / (2.f * M_PIF)) * 2.f * M_PIF; + if (ang1 > M_PIF) + ang1 -= 2.f * M_PIF; + else if (ang1 < -M_PIF) + ang1 += 2.f * M_PIF; + } + + zeus::CVector3f ang1Vec(std::sin(ang1) * swoosh.x4_leftRad, 0.f, std::cos(ang1) * swoosh.x4_leftRad); + + float ang2 = ang1 + 2.0943952f; // +120 degrees + if (ang2 > M_PIF) + ang2 -= 2.f * M_PIF; + + zeus::CVector3f ang2Vec(std::sin(ang2) * swoosh.x4_leftRad, 0.f, std::cos(ang2) * swoosh.x4_leftRad); + + float ang3 = ang2 + 2.0943952f; // +120 degrees + if (ang3 > M_PIF) + ang3 -= 2.f * M_PIF; + + zeus::CVector3f ang3Vec(std::sin(ang3) * swoosh.x4_leftRad, 0.f, std::cos(ang3) * swoosh.x4_leftRad); + + if (i == 2) { + x19c_p3[0] = x17c_p1[0] * 2.f - x16c_p0[0]; + x19c_p3[1] = x17c_p1[1] * 2.f - x16c_p0[1]; + x19c_p3[2] = x17c_p1[2] * 2.f - x16c_p0[2]; + } else { + x19c_p3[0] = x18c_p2[0]; + x19c_p3[1] = x18c_p2[1]; + x19c_p3[2] = x18c_p2[2]; + } + + x18c_p2[0] = x17c_p1[0]; + x18c_p2[1] = x17c_p1[1]; + x18c_p2[2] = x17c_p1[2]; + + x17c_p1[0] = x16c_p0[0]; + x17c_p1[1] = x16c_p0[1]; + x17c_p1[2] = x16c_p0[2]; + + zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + x16c_p0[0] = swoosh.x38_orientation * ang1Vec + useOffset; + x16c_p0[1] = swoosh.x38_orientation * ang2Vec + useOffset; + x16c_p0[2] = swoosh.x38_orientation * ang3Vec + useOffset; + + zeus::CColor useColor0 = prevColor0; + + if (swoosh.x0_active) { + zeus::CColor prevColor1 = prevColor0; + prevColor0 = swoosh.x6c_color * x20c_moduColor; + float prevUvSpan = curUvSpan; + curUvSpan += x1e8_uvSpan; + if (i > 1) { + // int vertCount = (x1b0_SPLN + 1) * 12; + float uv1 = 0.f; + zeus::CColor useColor1 = prevColor1; + zeus::CVector3f v01 = zeus::CVector3f::skZero; + zeus::CVector3f v11 = zeus::CVector3f::skZero; + zeus::CVector3f v21 = zeus::CVector3f::skZero; + zeus::CColor c1 = zeus::CColor::skClear; + float uvDelta = prevUvSpan - curUvSpan; + for (int j = 0; j < x1b0_SPLN + 1; ++j) { + float uv0 = uv1; + float t1 = (j + 1) / float(x1b0_SPLN + 1); + zeus::CVector3f v00 = v01; + zeus::CVector3f v10 = v11; + zeus::CVector3f v20 = v21; + zeus::CColor c0 = c1; + + if (j == 0) { + float t0 = j / float(x1b0_SPLN + 1); + v00 = GetSplinePoint(x16c_p0[0], x17c_p1[0], x18c_p2[0], x19c_p3[0], t0); + v10 = GetSplinePoint(x16c_p0[1], x17c_p1[1], x18c_p2[1], x19c_p3[1], t0); + v20 = GetSplinePoint(x16c_p0[2], x17c_p1[2], x18c_p2[2], x19c_p3[2], t0); + c0 = zeus::CColor::lerp(useColor0, useColor1, t0); + uv0 = t0 * uvDelta + curUvSpan; + } + + v01 = GetSplinePoint(x16c_p0[0], x17c_p1[0], x18c_p2[0], x19c_p3[0], t1); + v11 = GetSplinePoint(x16c_p0[1], x17c_p1[1], x18c_p2[1], x19c_p3[1], t1); + v21 = GetSplinePoint(x16c_p0[2], x17c_p1[2], x18c_p2[2], x19c_p3[2], t1); + c1 = zeus::CColor::lerp(useColor0, useColor1, t1); + uv1 = t1 * uvDelta + curUvSpan; + + m_cachedVerts.push_back({v00, {uv0, x1d4_uvs.yMin}, c0}); + m_cachedVerts.push_back({v10, {uv0, x1d4_uvs.yMax}, c0}); + m_cachedVerts.push_back({v01, {uv1, x1d4_uvs.yMin}, c1}); + m_cachedVerts.push_back({v11, {uv1, x1d4_uvs.yMax}, c1}); + CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + + m_cachedVerts.push_back({v10, {uv0, x1d4_uvs.yMin}, c0}); + m_cachedVerts.push_back({v20, {uv0, x1d4_uvs.yMax}, c0}); + m_cachedVerts.push_back({v11, {uv1, x1d4_uvs.yMin}, c1}); + m_cachedVerts.push_back({v21, {uv1, x1d4_uvs.yMax}, c1}); + CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + + m_cachedVerts.push_back({v20, {uv0, x1d4_uvs.yMin}, c0}); + m_cachedVerts.push_back({v00, {uv0, x1d4_uvs.yMax}, c0}); + m_cachedVerts.push_back({v21, {uv1, x1d4_uvs.yMin}, c1}); + m_cachedVerts.push_back({v01, {uv1, x1d4_uvs.yMax}, c1}); + CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + } + } + } + } } -void CParticleSwoosh::Render3SidedSolidSpline() -{ - if (x15c_swooshes.size() < 2) - return; +void CParticleSwoosh::Render3SidedSolidNoSplineNoGaps() { + if (x15c_swooshes.size() < 2) + return; - int curIdx = x158_curParticle; - float curUvSpan = -x1e8_uvSpan; - zeus::CColor prevColor0 = zeus::CColor::skClear; - for (int i=0 ; i M_PIF) { + ang1 -= std::floor(ang1 / (2.f * M_PIF)) * 2.f * M_PIF; + if (ang1 > M_PIF) + ang1 -= 2.f * M_PIF; + else if (ang1 < -M_PIF) + ang1 += 2.f * M_PIF; + } + + zeus::CVector3f ang1Vec(std::sin(ang1) * swoosh.x4_leftRad, 0.f, std::cos(ang1) * swoosh.x4_leftRad); + + float ang2 = ang1 + 2.0943952f; // +120 degrees + if (ang2 > M_PIF) + ang2 -= 2.f * M_PIF; + + zeus::CVector3f ang2Vec(std::sin(ang2) * swoosh.x4_leftRad, 0.f, std::cos(ang2) * swoosh.x4_leftRad); + + float ang3 = ang2 + 2.0943952f; // +120 degrees + if (ang3 > M_PIF) + ang3 -= 2.f * M_PIF; + + zeus::CVector3f ang3Vec(std::sin(ang3) * swoosh.x4_leftRad, 0.f, std::cos(ang3) * swoosh.x4_leftRad); + + zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + p0[i & 1] = swoosh.x38_orientation * ang1Vec + useOffset; + p1[i & 1] = swoosh.x38_orientation * ang2Vec + useOffset; + p2[i & 1] = swoosh.x38_orientation * ang3Vec + useOffset; + + if (!swoosh.x0_active) { + lastActive = false; + continue; + } + + if (!lastActive) { + lastActive = true; + continue; + } + + lastActive = true; + zeus::CColor c1 = c0; + c0 = swoosh.x6c_color * x20c_moduColor; + + float uv1 = uv0; + uv0 += x1e8_uvSpan; + + m_cachedVerts.push_back({p0[i & 1], {uv0, x1d4_uvs.yMin}, c0}); + m_cachedVerts.push_back({p1[i & 1], {uv0, x1d4_uvs.yMax}, c0}); + m_cachedVerts.push_back({p0[!(i & 1)], {uv1, x1d4_uvs.yMin}, c1}); + m_cachedVerts.push_back({p1[!(i & 1)], {uv1, x1d4_uvs.yMax}, c1}); + CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + + m_cachedVerts.push_back({p1[i & 1], {uv0, x1d4_uvs.yMin}, c0}); + m_cachedVerts.push_back({p2[i & 1], {uv0, x1d4_uvs.yMax}, c0}); + m_cachedVerts.push_back({p1[!(i & 1)], {uv1, x1d4_uvs.yMin}, c1}); + m_cachedVerts.push_back({p2[!(i & 1)], {uv1, x1d4_uvs.yMax}, c1}); + CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + + m_cachedVerts.push_back({p2[i & 1], {uv0, x1d4_uvs.yMin}, c0}); + m_cachedVerts.push_back({p0[i & 1], {uv0, x1d4_uvs.yMax}, c0}); + m_cachedVerts.push_back({p2[!(i & 1)], {uv1, x1d4_uvs.yMin}, c1}); + m_cachedVerts.push_back({p0[!(i & 1)], {uv1, x1d4_uvs.yMax}, c1}); + CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); + } +} + +void CParticleSwoosh::Render2SidedSpline() { RenderNSidedSpline(); } + +void CParticleSwoosh::Render2SidedNoSplineGaps() { + int drawStart = 0; + bool streaming = false; + int curIdx = x158_curParticle; + for (int i = 0; i < x15c_swooshes.size(); ++i) { + SSwooshData& swoosh = x15c_swooshes[curIdx]; + bool otherActive = x15c_swooshes[WrapIndex(curIdx - 1)].x0_active; + + curIdx -= 1; + if (curIdx < 0) + curIdx = x15c_swooshes.size() - 2; + + if (!swoosh.x0_active) { + if (streaming) { + streaming = false; + CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); + } + continue; + } + + if (!streaming) { + if (!otherActive) + continue; + if (i >= x15c_swooshes.size() - 2) + continue; + streaming = true; + drawStart = m_cachedVerts.size(); + } + + float ang = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm); + if (std::fabs(ang) > M_PIF) { + ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF; + if (ang > M_PIF) + ang -= 2.f * M_PIF; + else if (ang < -M_PIF) + ang += 2.f * M_PIF; + } + + float sinAng = std::sin(ang); + float cosAng = std::cos(ang); + + zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + zeus::CVector3f v0 = + swoosh.x38_orientation * zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) + + useOffset; + zeus::CVector3f v1 = + swoosh.x38_orientation * zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f, -sinAng * swoosh.x8_rightRad) + + useOffset; + + zeus::CColor color = swoosh.x6c_color * x20c_moduColor; + + m_cachedVerts.push_back({v0, {1.f, x1d4_uvs.yMin}, color}); + m_cachedVerts.push_back({v1, {1.f, x1d4_uvs.yMax}, color}); + m_cachedVerts.push_back({v0, {0.f, x1d4_uvs.yMin}, color}); + m_cachedVerts.push_back({v1, {0.f, x1d4_uvs.yMax}, color}); + } + + if (streaming) + CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); +} + +void CParticleSwoosh::Render2SidedNoSplineNoGaps() { + int drawStart = 0; + int curIdx = x158_curParticle; + int particleCount = x1ac_particleCount; + float uvOffset = 0.f; + if (x1c_desc->x3c_TEXR) { + if (x1c_desc->x45_25_ORNT) { + zeus::CVector3f camToParticle = + ((zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * xec_scaleXf).inverse() * + CGraphics::g_ViewMatrix) + .origin; + zeus::CVector3f dotVec = zeus::CVector3f::skZero; + + for (int i = 0; i < x15c_swooshes.size(); ++i) { SSwooshData& swoosh = x15c_swooshes[curIdx]; curIdx -= 1; if (curIdx < 0) - curIdx = x15c_swooshes.size() - 1; + curIdx = x15c_swooshes.size() - 1; - float ang1 = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm); - if (std::fabs(ang1) > M_PIF) - { - ang1 -= std::floor(ang1 / (2.f * M_PIF)) * 2.f * M_PIF; - if (ang1 > M_PIF) - ang1 -= 2.f * M_PIF; - else if (ang1 < -M_PIF) - ang1 += 2.f * M_PIF; - } + if (swoosh.x0_active) { + particleCount -= 1; + int otherIdx = curIdx - 1; + if (otherIdx < 0) + otherIdx = x15c_swooshes.size() - 1; - zeus::CVector3f ang1Vec(std::sin(ang1) * swoosh.x4_leftRad, 0.f, std::cos(ang1) * swoosh.x4_leftRad); + SSwooshData& otherSwoosh = x15c_swooshes[otherIdx]; - float ang2 = ang1 + 2.0943952f; // +120 degrees - if (ang2 > M_PIF) - ang2 -= 2.f * M_PIF; + zeus::CVector3f delta = otherSwoosh.xc_translation - swoosh.xc_translation; + if (otherIdx == x158_curParticle) + delta = swoosh.xc_translation - x15c_swooshes[(curIdx + 1) % x15c_swooshes.size()].xc_translation; - zeus::CVector3f ang2Vec(std::sin(ang2) * swoosh.x4_leftRad, 0.f, std::cos(ang2) * swoosh.x4_leftRad); + if (delta.canBeNormalized()) { + zeus::CVector3f deltaCross = delta.cross(camToParticle - swoosh.xc_translation); + if (deltaCross.canBeNormalized()) { + deltaCross.normalize(); + dotVec = (deltaCross.dot(dotVec) < 0.f ? -1.f : 1.f) * deltaCross; + zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + zeus::CVector3f v0 = dotVec * swoosh.x4_leftRad + useOffset; + zeus::CVector3f v1 = dotVec * -swoosh.x8_rightRad + useOffset; - float ang3 = ang2 + 2.0943952f; // +120 degrees - if (ang3 > M_PIF) - ang3 -= 2.f * M_PIF; + zeus::CColor color = swoosh.x6c_color * x20c_moduColor; - zeus::CVector3f ang3Vec(std::sin(ang3) * swoosh.x4_leftRad, 0.f, std::cos(ang3) * swoosh.x4_leftRad); - - if (i == 2) - { - x19c_p3[0] = x17c_p1[0] * 2.f - x16c_p0[0]; - x19c_p3[1] = x17c_p1[1] * 2.f - x16c_p0[1]; - x19c_p3[2] = x17c_p1[2] * 2.f - x16c_p0[2]; - } - else - { - x19c_p3[0] = x18c_p2[0]; - x19c_p3[1] = x18c_p2[1]; - x19c_p3[2] = x18c_p2[2]; - } - - x18c_p2[0] = x17c_p1[0]; - x18c_p2[1] = x17c_p1[1]; - x18c_p2[2] = x17c_p1[2]; - - x17c_p1[0] = x16c_p0[0]; - x17c_p1[1] = x16c_p0[1]; - x17c_p1[2] = x16c_p0[2]; - - zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; - x16c_p0[0] = swoosh.x38_orientation * ang1Vec + useOffset; - x16c_p0[1] = swoosh.x38_orientation * ang2Vec + useOffset; - x16c_p0[2] = swoosh.x38_orientation * ang3Vec + useOffset; - - zeus::CColor useColor0 = prevColor0; - - if (swoosh.x0_active) - { - zeus::CColor prevColor1 = prevColor0; - prevColor0 = swoosh.x6c_color * x20c_moduColor; - float prevUvSpan = curUvSpan; - curUvSpan += x1e8_uvSpan; - if (i > 1) - { - //int vertCount = (x1b0_SPLN + 1) * 12; - float uv1 = 0.f; - zeus::CColor useColor1 = prevColor1; - zeus::CVector3f v01 = zeus::CVector3f::skZero; - zeus::CVector3f v11 = zeus::CVector3f::skZero; - zeus::CVector3f v21 = zeus::CVector3f::skZero; - zeus::CColor c1 = zeus::CColor::skClear; - float uvDelta = prevUvSpan - curUvSpan; - for (int j=0 ; j M_PIF) - { - ang1 -= std::floor(ang1 / (2.f * M_PIF)) * 2.f * M_PIF; - if (ang1 > M_PIF) - ang1 -= 2.f * M_PIF; - else if (ang1 < -M_PIF) - ang1 += 2.f * M_PIF; - } - - zeus::CVector3f ang1Vec(std::sin(ang1) * swoosh.x4_leftRad, 0.f, std::cos(ang1) * swoosh.x4_leftRad); - - float ang2 = ang1 + 2.0943952f; // +120 degrees - if (ang2 > M_PIF) - ang2 -= 2.f * M_PIF; - - zeus::CVector3f ang2Vec(std::sin(ang2) * swoosh.x4_leftRad, 0.f, std::cos(ang2) * swoosh.x4_leftRad); - - float ang3 = ang2 + 2.0943952f; // +120 degrees - if (ang3 > M_PIF) - ang3 -= 2.f * M_PIF; - - zeus::CVector3f ang3Vec(std::sin(ang3) * swoosh.x4_leftRad, 0.f, std::cos(ang3) * swoosh.x4_leftRad); - - zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; - p0[i&1] = swoosh.x38_orientation * ang1Vec + useOffset; - p1[i&1] = swoosh.x38_orientation * ang2Vec + useOffset; - p2[i&1] = swoosh.x38_orientation * ang3Vec + useOffset; - - if (!swoosh.x0_active) - { - lastActive = false; - continue; - } - - if (!lastActive) - { - lastActive = true; - continue; - } - - lastActive = true; - zeus::CColor c1 = c0; - c0 = swoosh.x6c_color * x20c_moduColor; - - float uv1 = uv0; - uv0 += x1e8_uvSpan; - - m_cachedVerts.push_back({p0[i&1], {uv0, x1d4_uvs.yMin}, c0}); - m_cachedVerts.push_back({p1[i&1], {uv0, x1d4_uvs.yMax}, c0}); - m_cachedVerts.push_back({p0[!(i&1)], {uv1, x1d4_uvs.yMin}, c1}); - m_cachedVerts.push_back({p1[!(i&1)], {uv1, x1d4_uvs.yMax}, c1}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); - - m_cachedVerts.push_back({p1[i&1], {uv0, x1d4_uvs.yMin}, c0}); - m_cachedVerts.push_back({p2[i&1], {uv0, x1d4_uvs.yMax}, c0}); - m_cachedVerts.push_back({p1[!(i&1)], {uv1, x1d4_uvs.yMin}, c1}); - m_cachedVerts.push_back({p2[!(i&1)], {uv1, x1d4_uvs.yMax}, c1}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); - - m_cachedVerts.push_back({p2[i&1], {uv0, x1d4_uvs.yMin}, c0}); - m_cachedVerts.push_back({p0[i&1], {uv0, x1d4_uvs.yMax}, c0}); - m_cachedVerts.push_back({p2[!(i&1)], {uv1, x1d4_uvs.yMin}, c1}); - m_cachedVerts.push_back({p0[!(i&1)], {uv1, x1d4_uvs.yMax}, c1}); - CGraphics::DrawArray(m_cachedVerts.size() - 4, 4); - } -} - -void CParticleSwoosh::Render2SidedSpline() -{ - RenderNSidedSpline(); -} - -void CParticleSwoosh::Render2SidedNoSplineGaps() -{ - int drawStart = 0; - bool streaming = false; - int curIdx = x158_curParticle; - for (int i=0 ; i= 1.f && particleCount) { CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); + drawStart = m_cachedVerts.size(); + uvOffset -= 1.f; + m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); + m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); + } + + if (x1ec_TSPN > 0) + uvOffset += x1e8_uvSpan; + else + uvOffset = i * x1e8_uvSpan; } - continue; + } } + } + } else { + for (int i = 0; i < x15c_swooshes.size(); ++i) { + SSwooshData& swoosh = x15c_swooshes[curIdx]; - if (!streaming) - { - if (!otherActive) - continue; - if (i >= x15c_swooshes.size() - 2) - continue; - streaming = true; - drawStart = m_cachedVerts.size(); - } + curIdx -= 1; + if (curIdx < 0) + curIdx = x15c_swooshes.size() - 1; - float ang = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm); - if (std::fabs(ang) > M_PIF) - { + if (swoosh.x0_active) { + particleCount -= 1; + + float ang = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm); + if (std::fabs(ang) > M_PIF) { ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF; if (ang > M_PIF) - ang -= 2.f * M_PIF; + ang -= 2.f * M_PIF; else if (ang < -M_PIF) - ang += 2.f * M_PIF; + ang += 2.f * M_PIF; + } + + float sinAng = std::sin(ang); + float cosAng = std::cos(ang); + + zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; + zeus::CVector3f v0 = + swoosh.x38_orientation * zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) + + useOffset; + zeus::CVector3f v1 = swoosh.x38_orientation * + zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f, -sinAng * swoosh.x8_rightRad) + + useOffset; + + zeus::CColor color = swoosh.x6c_color * x20c_moduColor; + + m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); + m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); + if (uvOffset >= 1.f && particleCount) { + CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); + drawStart = m_cachedVerts.size(); + uvOffset -= 1.f; + m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); + m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); + } + + if (x1ec_TSPN > 0) + uvOffset += x1e8_uvSpan; + else + uvOffset = i * x1e8_uvSpan; + } + } + } + } else { + for (int i = 0; i < x15c_swooshes.size(); ++i) { + SSwooshData& swoosh = x15c_swooshes[curIdx]; + + curIdx -= 1; + if (curIdx < 0) + curIdx = x15c_swooshes.size() - 1; + + if (swoosh.x0_active) { + float ang = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm); + if (std::fabs(ang) > M_PIF) { + ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF; + if (ang > M_PIF) + ang -= 2.f * M_PIF; + else if (ang < -M_PIF) + ang += 2.f * M_PIF; } float sinAng = std::sin(ang); float cosAng = std::cos(ang); zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; - zeus::CVector3f v0 = swoosh.x38_orientation * - zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) + useOffset; - zeus::CVector3f v1 = swoosh.x38_orientation * - zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f, -sinAng * swoosh.x8_rightRad) + useOffset; + zeus::CVector3f v0 = + swoosh.x38_orientation * zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) + + useOffset; + zeus::CVector3f v1 = + swoosh.x38_orientation * zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f, -sinAng * swoosh.x8_rightRad) + + useOffset; zeus::CColor color = swoosh.x6c_color * x20c_moduColor; - - m_cachedVerts.push_back({v0, {1.f, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v1, {1.f, x1d4_uvs.yMax}, color}); - m_cachedVerts.push_back({v0, {0.f, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v1, {0.f, x1d4_uvs.yMax}, color}); + m_cachedVerts.push_back({v0, {}, color}); + m_cachedVerts.push_back({v1, {}, color}); + } } + } - if (streaming) - CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); + CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); } -void CParticleSwoosh::Render2SidedNoSplineNoGaps() -{ - int drawStart = 0; - int curIdx = x158_curParticle; - int particleCount = x1ac_particleCount; - float uvOffset = 0.f; - if (x1c_desc->x3c_TEXR) - { - if (x1c_desc->x45_25_ORNT) - { - zeus::CVector3f camToParticle = - ((zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * xec_scaleXf).inverse() * CGraphics::g_ViewMatrix).origin; - zeus::CVector3f dotVec = zeus::CVector3f::skZero; +void CParticleSwoosh::Render(const CActorLights*) { + if (x1b4_LENG < 2 || x1ac_particleCount <= 1) + return; - for (int i=0 ; ix3c_TEXR.get()) { + TLockedToken tex = texr->GetValueTexture(x28_curFrame); + // Load tex + x1e4_tex = tex.GetObj(); - if (delta.canBeNormalized()) - { - zeus::CVector3f deltaCross = delta.cross(camToParticle - swoosh.xc_translation); - if (deltaCross.canBeNormalized()) - { - deltaCross.normalize(); - dotVec = (deltaCross.dot(dotVec) < 0.f ? -1.f : 1.f) * deltaCross; - zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; - zeus::CVector3f v0 = dotVec * swoosh.x4_leftRad + useOffset; - zeus::CVector3f v1 = dotVec * -swoosh.x8_rightRad + useOffset; + texr->GetValueUV(x28_curFrame, x1d4_uvs); - zeus::CColor color = swoosh.x6c_color * x20c_moduColor; + x1d0_31_constantTex = texr->HasConstantTexture(); + x1d1_24_constantUv = texr->HasConstantUV(); - m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); - if (uvOffset >= 1.f && particleCount) - { - CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); - drawStart = m_cachedVerts.size(); - uvOffset -= 1.f; - m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); - } + if (CIntElement* tspn = x1c_desc->x40_TSPN.get()) + tspn->GetValue(x28_curFrame, x1ec_TSPN); - if (x1ec_TSPN > 0) - uvOffset += x1e8_uvSpan; - else - uvOffset = i * x1e8_uvSpan; - } - } - } - } - } - else - { - for (int i=0 ; i 0) + x1e8_uvSpan = 1.f / float(x1ec_TSPN); - if (swoosh.x0_active) - { - particleCount -= 1; + // TEV0 modulate + } else { + // TEV0 passthru + } - float ang = zeus::degToRad(swoosh.x30_irot + swoosh.x34_rotm); - if (std::fabs(ang) > M_PIF) - { - ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF; - if (ang > M_PIF) - ang -= 2.f * M_PIF; - else if (ang < -M_PIF) - ang += 2.f * M_PIF; - } + // TEV1 passthru - float sinAng = std::sin(ang); - float cosAng = std::cos(ang); - - zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; - zeus::CVector3f v0 = swoosh.x38_orientation * - zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) + useOffset; - zeus::CVector3f v1 = swoosh.x38_orientation * - zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f, -sinAng * swoosh.x8_rightRad) + useOffset; - - zeus::CColor color = swoosh.x6c_color * x20c_moduColor; - - m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); - if (uvOffset >= 1.f && particleCount) - { - CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); - drawStart = m_cachedVerts.size(); - uvOffset -= 1.f; - m_cachedVerts.push_back({v0, {uvOffset, x1d4_uvs.yMin}, color}); - m_cachedVerts.push_back({v1, {uvOffset, x1d4_uvs.yMax}, color}); - } - - if (x1ec_TSPN > 0) - uvOffset += x1e8_uvSpan; - else - uvOffset = i * x1e8_uvSpan; - } - } - } + if (x1b8_SIDE == 2) { + if (x1b0_SPLN <= 0) { + if (x1d0_27_renderGaps) + Render2SidedNoSplineGaps(); + else + Render2SidedNoSplineNoGaps(); + } else { + Render2SidedSpline(); } + } else if (x1b8_SIDE == 3) { + if (x1b0_SPLN > 0) + Render3SidedSolidSpline(); else - { - for (int i=0 ; i M_PIF) - { - ang -= std::floor(ang / (2.f * M_PIF)) * 2.f * M_PIF; - if (ang > M_PIF) - ang -= 2.f * M_PIF; - else if (ang < -M_PIF) - ang += 2.f * M_PIF; - } - - float sinAng = std::sin(ang); - float cosAng = std::cos(ang); - - zeus::CVector3f useOffset = swoosh.xc_translation + swoosh.x24_useOffset; - zeus::CVector3f v0 = swoosh.x38_orientation * - zeus::CVector3f(cosAng * swoosh.x4_leftRad, 0.f, sinAng * swoosh.x4_leftRad) + useOffset; - zeus::CVector3f v1 = swoosh.x38_orientation * - zeus::CVector3f(-cosAng * swoosh.x8_rightRad, 0.f, -sinAng * swoosh.x8_rightRad) + useOffset; - - zeus::CColor color = swoosh.x6c_color * x20c_moduColor; - m_cachedVerts.push_back({v0, {}, color}); - m_cachedVerts.push_back({v1, {}, color}); - } - } - } - - CGraphics::DrawArray(drawStart, m_cachedVerts.size() - drawStart); -} - -void CParticleSwoosh::Render(const CActorLights*) -{ - if (x1b4_LENG < 2 || x1ac_particleCount <= 1) - return; - - m_cachedVerts.clear(); - if (m_dataBind) - CGraphics::SetShaderDataBinding(m_dataBind); - - CParticleGlobals::SetParticleLifetime(x1b4_LENG); - CGlobalRandom gr(x1c0_rand); - CGraphics::DisableAllLights(); - // Z-test, Z-update if x45_24_ZBUF - // Additive if x1d0_25_AALP, otherwise alpha blend - - CGraphics::SetModelMatrix( - zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * - xec_scaleXf * zeus::CTransform::Scale(x14c_localScale)); - - // Disable face culling - - if (CUVElement* texr = x1c_desc->x3c_TEXR.get()) - { - TLockedToken tex = texr->GetValueTexture(x28_curFrame); - // Load tex - x1e4_tex = tex.GetObj(); - - texr->GetValueUV(x28_curFrame, x1d4_uvs); - - x1d0_31_constantTex = texr->HasConstantTexture(); - x1d1_24_constantUv = texr->HasConstantUV(); - - if (CIntElement* tspn = x1c_desc->x40_TSPN.get()) - tspn->GetValue(x28_curFrame, x1ec_TSPN); - - if (x1ec_TSPN <= 0) - x1ec_TSPN = x15c_swooshes.size() - 1; - - x1e8_uvSpan = 1.f; - if (x1ec_TSPN > 0) - x1e8_uvSpan = 1.f / float(x1ec_TSPN); - - // TEV0 modulate - } + Render3SidedSolidNoSplineNoGaps(); + } else { + if (x1b0_SPLN > 0) + RenderNSidedSpline(); else - { - // TEV0 passthru - } + RenderNSidedNoSpline(); + } - // TEV1 passthru - - if (x1b8_SIDE == 2) - { - if (x1b0_SPLN <= 0) - { - if (x1d0_27_renderGaps) - Render2SidedNoSplineGaps(); - else - Render2SidedNoSplineNoGaps(); - } - else - { - Render2SidedSpline(); - } - } - else if (x1b8_SIDE == 3) - { - if (x1b0_SPLN > 0) - Render3SidedSolidSpline(); - else - Render3SidedSolidNoSplineNoGaps(); - } - else - { - if (x1b0_SPLN > 0) - RenderNSidedSpline(); - else - RenderNSidedNoSpline(); - } - - zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); - m_uniformBuf->load(&mvp, sizeof(zeus::CMatrix4f)); - if (m_cachedVerts.size()) - m_vertBuf->load(m_cachedVerts.data(), m_cachedVerts.size() * sizeof(CParticleSwooshShaders::Vert)); + zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(true) * CGraphics::g_GXModelView.toMatrix4f(); + m_uniformBuf->load(&mvp, sizeof(zeus::CMatrix4f)); + if (m_cachedVerts.size()) + m_vertBuf->load(m_cachedVerts.data(), m_cachedVerts.size() * sizeof(CParticleSwooshShaders::Vert)); } -void CParticleSwoosh::SetOrientation(const zeus::CTransform& xf) -{ - x44_orientation = xf; - x74_invOrientation = xf.inverse(); - x15c_swooshes[x158_curParticle].x38_orientation = xf; +void CParticleSwoosh::SetOrientation(const zeus::CTransform& xf) { + x44_orientation = xf; + x74_invOrientation = xf.inverse(); + x15c_swooshes[x158_curParticle].x38_orientation = xf; } -void CParticleSwoosh::SetTranslation(const zeus::CVector3f& translation) -{ - x38_translation = translation; - UpdateSwooshTranslation(x38_translation); +void CParticleSwoosh::SetTranslation(const zeus::CVector3f& translation) { + x38_translation = translation; + UpdateSwooshTranslation(x38_translation); } -void CParticleSwoosh::SetGlobalOrientation(const zeus::CTransform& xf) -{ - xb0_globalOrientation = xf.getRotation(); +void CParticleSwoosh::SetGlobalOrientation(const zeus::CTransform& xf) { xb0_globalOrientation = xf.getRotation(); } + +void CParticleSwoosh::SetGlobalTranslation(const zeus::CVector3f& translation) { xa4_globalTranslation = translation; } + +void CParticleSwoosh::SetGlobalScale(const zeus::CVector3f& scale) { + xe0_globalScale = scale; + xec_scaleXf = zeus::CTransform::Scale(scale); + x11c_invScaleXf = zeus::CTransform::Scale(1.f / scale); } -void CParticleSwoosh::SetGlobalTranslation(const zeus::CVector3f& translation) -{ - xa4_globalTranslation = translation; -} +void CParticleSwoosh::SetLocalScale(const zeus::CVector3f& scale) { x14c_localScale = scale; } -void CParticleSwoosh::SetGlobalScale(const zeus::CVector3f& scale) -{ - xe0_globalScale = scale; - xec_scaleXf = zeus::CTransform::Scale(scale); - x11c_invScaleXf = zeus::CTransform::Scale(1.f / scale); -} +void CParticleSwoosh::SetParticleEmission(bool e) { x1d0_24_emitting = e; } -void CParticleSwoosh::SetLocalScale(const zeus::CVector3f& scale) -{ - x14c_localScale = scale; -} +void CParticleSwoosh::SetModulationColor(const zeus::CColor& color) { x20c_moduColor = color; } -void CParticleSwoosh::SetParticleEmission(bool e) -{ - x1d0_24_emitting = e; -} +const zeus::CTransform& CParticleSwoosh::GetOrientation() const { return x44_orientation; } -void CParticleSwoosh::SetModulationColor(const zeus::CColor& color) -{ - x20c_moduColor = color; -} +const zeus::CVector3f& CParticleSwoosh::GetTranslation() const { return x38_translation; } -const zeus::CTransform& CParticleSwoosh::GetOrientation() const -{ - return x44_orientation; -} +const zeus::CTransform& CParticleSwoosh::GetGlobalOrientation() const { return xb0_globalOrientation; } -const zeus::CVector3f& CParticleSwoosh::GetTranslation() const -{ - return x38_translation; -} +const zeus::CVector3f& CParticleSwoosh::GetGlobalTranslation() const { return xa4_globalTranslation; } -const zeus::CTransform& CParticleSwoosh::GetGlobalOrientation() const -{ - return xb0_globalOrientation; -} +const zeus::CVector3f& CParticleSwoosh::GetGlobalScale() const { return xe0_globalScale; } -const zeus::CVector3f& CParticleSwoosh::GetGlobalTranslation() const -{ - return xa4_globalTranslation; -} +const zeus::CColor& CParticleSwoosh::GetModulationColor() const { return x20c_moduColor; } -const zeus::CVector3f& CParticleSwoosh::GetGlobalScale() const -{ - return xe0_globalScale; -} - -const zeus::CColor& CParticleSwoosh::GetModulationColor() const -{ - return x20c_moduColor; -} - -bool CParticleSwoosh::IsSystemDeletable() const -{ - if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) - return false; - - if (GetParticleCount() >= 2) - return false; - - return true; -} - -std::experimental::optional CParticleSwoosh::GetBounds() const -{ - if (GetParticleCount() <= 1) - { - zeus::CVector3f trans = x38_translation + xa4_globalTranslation; - return zeus::CAABox(trans, trans); - } - else - { - zeus::CTransform xf = zeus::CTransform::Translate(xa4_globalTranslation) * - xb0_globalOrientation * xec_scaleXf; - return zeus::CAABox(x1f0_aabbMin - x208_maxRadius, x1fc_aabbMax + x208_maxRadius).getTransformedAABox(xf); - } -} - -u32 CParticleSwoosh::GetParticleCount() const -{ - return x1ac_particleCount; -} - -bool CParticleSwoosh::SystemHasLight() const -{ +bool CParticleSwoosh::IsSystemDeletable() const { + if (x1d0_24_emitting && x28_curFrame < x2c_PSLT) return false; + + if (GetParticleCount() >= 2) + return false; + + return true; } -CLight CParticleSwoosh::GetLight() const -{ - return CLight::BuildLocalAmbient(zeus::CVector3f::skZero, zeus::CColor::skWhite); +std::experimental::optional CParticleSwoosh::GetBounds() const { + if (GetParticleCount() <= 1) { + zeus::CVector3f trans = x38_translation + xa4_globalTranslation; + return zeus::CAABox(trans, trans); + } else { + zeus::CTransform xf = zeus::CTransform::Translate(xa4_globalTranslation) * xb0_globalOrientation * xec_scaleXf; + return zeus::CAABox(x1f0_aabbMin - x208_maxRadius, x1fc_aabbMax + x208_maxRadius).getTransformedAABox(xf); + } } -bool CParticleSwoosh::GetParticleEmission() const -{ - return x1d0_24_emitting; +u32 CParticleSwoosh::GetParticleCount() const { return x1ac_particleCount; } + +bool CParticleSwoosh::SystemHasLight() const { return false; } + +CLight CParticleSwoosh::GetLight() const { + return CLight::BuildLocalAmbient(zeus::CVector3f::skZero, zeus::CColor::skWhite); } -void CParticleSwoosh::DestroyParticles() -{ - // Empty +bool CParticleSwoosh::GetParticleEmission() const { return x1d0_24_emitting; } + +void CParticleSwoosh::DestroyParticles() { + // Empty } -} +} // namespace urde diff --git a/Runtime/Particle/CParticleSwoosh.hpp b/Runtime/Particle/CParticleSwoosh.hpp index b7c9e8034..290cb8b51 100644 --- a/Runtime/Particle/CParticleSwoosh.hpp +++ b/Runtime/Particle/CParticleSwoosh.hpp @@ -9,217 +9,208 @@ #include "DataSpec/DNACommon/GX.hpp" #include "Graphics/Shaders/CParticleSwooshShaders.hpp" -namespace urde -{ +namespace urde { class CSwooshDescription; -class CParticleSwoosh : public CParticleGen -{ - friend class CParticleSwooshShaders; +class CParticleSwoosh : public CParticleGen { + friend class CParticleSwooshShaders; - struct SSwooshData - { - bool x0_active; - float x4_leftRad; - float x8_rightRad; - zeus::CVector3f xc_translation; // Updated by system's velocity sources or user code - zeus::CVector3f x18_offset; // Updated by POFS once per system update (also resets x24_useOffset) - zeus::CVector3f x24_useOffset; // Combination of POFS and NPOS, once per particle instance - float x30_irot; // Rotation bias once per system update - float x34_rotm; // Rotation bias once per particle instance - zeus::CTransform x38_orientation; // Updated by user code - int x68_frame; // Frame index of evaluated data - zeus::CColor x6c_color; // Updated by COLR - int x70_startFrame; - zeus::CVector3f x74_velocity; + struct SSwooshData { + bool x0_active; + float x4_leftRad; + float x8_rightRad; + zeus::CVector3f xc_translation; // Updated by system's velocity sources or user code + zeus::CVector3f x18_offset; // Updated by POFS once per system update (also resets x24_useOffset) + zeus::CVector3f x24_useOffset; // Combination of POFS and NPOS, once per particle instance + float x30_irot; // Rotation bias once per system update + float x34_rotm; // Rotation bias once per particle instance + zeus::CTransform x38_orientation; // Updated by user code + int x68_frame; // Frame index of evaluated data + zeus::CColor x6c_color; // Updated by COLR + int x70_startFrame; + zeus::CVector3f x74_velocity; - SSwooshData(const zeus::CVector3f& translation, const zeus::CVector3f& offset, float irot, float rotm, - int startFrame, bool active, const zeus::CTransform& orient, const zeus::CVector3f& vel, - float leftRad, float rightRad, const zeus::CColor& color) - : x0_active(active), x4_leftRad(leftRad), x8_rightRad(rightRad), xc_translation(translation), - x18_offset(offset), x24_useOffset(offset), x30_irot(irot), x34_rotm(rotm), x38_orientation(orient), - x6c_color(color), x70_startFrame(startFrame), x74_velocity(vel) {} + SSwooshData(const zeus::CVector3f& translation, const zeus::CVector3f& offset, float irot, float rotm, + int startFrame, bool active, const zeus::CTransform& orient, const zeus::CVector3f& vel, float leftRad, + float rightRad, const zeus::CColor& color) + : x0_active(active) + , x4_leftRad(leftRad) + , x8_rightRad(rightRad) + , xc_translation(translation) + , x18_offset(offset) + , x24_useOffset(offset) + , x30_irot(irot) + , x34_rotm(rotm) + , x38_orientation(orient) + , x6c_color(color) + , x70_startFrame(startFrame) + , x74_velocity(vel) {} + }; + + TLockedToken x1c_desc; + u32 x28_curFrame = 0; + int x2c_PSLT = 0; + double x30_curTime = 0.0; + zeus::CVector3f x38_translation; + zeus::CTransform x44_orientation; + zeus::CTransform x74_invOrientation; + zeus::CVector3f xa4_globalTranslation; + zeus::CTransform xb0_globalOrientation; + zeus::CVector3f xe0_globalScale = {1.f, 1.f, 1.f}; + zeus::CTransform xec_scaleXf; + zeus::CTransform x11c_invScaleXf; + zeus::CVector3f x14c_localScale = {1.f, 1.f, 1.f}; + u32 x158_curParticle = 0; + std::vector x15c_swooshes; + std::vector x16c_p0; + std::vector x17c_p1; + std::vector x18c_p2; + std::vector x19c_p3; + u32 x1ac_particleCount = 0; + int x1b0_SPLN = 0; + int x1b4_LENG = 0; + int x1b8_SIDE = 0; + GX::Primitive x1bc_prim; + CRandom16 x1c0_rand; + float x1c4_ = 0.f; + float x1c8_ = 0.f; + float x1cc_TSPN; + + union { + struct { + bool x1d0_24_emitting : 1; + bool x1d0_25_AALP : 1; + bool x1d0_26_forceOneUpdate : 1; + bool x1d0_27_renderGaps : 1; + bool x1d0_28_LLRD : 1; + bool x1d0_29_VLS1 : 1; + bool x1d0_30_VLS2 : 1; + bool x1d0_31_constantTex : 1; + bool x1d1_24_constantUv : 1; }; + u32 _dummy = 0; + }; - TLockedToken x1c_desc; - u32 x28_curFrame = 0; - int x2c_PSLT = 0; - double x30_curTime = 0.0; - zeus::CVector3f x38_translation; - zeus::CTransform x44_orientation; - zeus::CTransform x74_invOrientation; - zeus::CVector3f xa4_globalTranslation; - zeus::CTransform xb0_globalOrientation; - zeus::CVector3f xe0_globalScale = {1.f, 1.f, 1.f}; - zeus::CTransform xec_scaleXf; - zeus::CTransform x11c_invScaleXf; - zeus::CVector3f x14c_localScale = {1.f, 1.f, 1.f}; - u32 x158_curParticle = 0; - std::vector x15c_swooshes; - std::vector x16c_p0; - std::vector x17c_p1; - std::vector x18c_p2; - std::vector x19c_p3; - u32 x1ac_particleCount = 0; - int x1b0_SPLN = 0; - int x1b4_LENG = 0; - int x1b8_SIDE = 0; - GX::Primitive x1bc_prim; - CRandom16 x1c0_rand; - float x1c4_ = 0.f; - float x1c8_ = 0.f; - float x1cc_TSPN; + SUVElementSet x1d4_uvs = {}; + CTexture* x1e4_tex = nullptr; + float x1e8_uvSpan = 1.f; + int x1ec_TSPN = 0; + zeus::CVector3f x1f0_aabbMin; + zeus::CVector3f x1fc_aabbMax; + float x208_maxRadius = 0.f; + zeus::CColor x20c_moduColor = zeus::CColor::skWhite; - union - { - struct - { - bool x1d0_24_emitting : 1; - bool x1d0_25_AALP : 1; - bool x1d0_26_forceOneUpdate : 1; - bool x1d0_27_renderGaps : 1; - bool x1d0_28_LLRD : 1; - bool x1d0_29_VLS1 : 1; - bool x1d0_30_VLS2 : 1; - bool x1d0_31_constantTex : 1; - bool x1d1_24_constantUv : 1; - }; - u32 _dummy = 0; - }; + boo::ObjToken m_dataBind; + boo::ObjToken m_vertBuf; + boo::ObjToken m_uniformBuf; + std::unique_ptr m_lineRenderer; + std::vector m_cachedVerts; - SUVElementSet x1d4_uvs = {}; - CTexture* x1e4_tex = nullptr; - float x1e8_uvSpan = 1.f; - int x1ec_TSPN = 0; - zeus::CVector3f x1f0_aabbMin; - zeus::CVector3f x1fc_aabbMax; - float x208_maxRadius = 0.f; - zeus::CColor x20c_moduColor = zeus::CColor::skWhite; + static int g_ParticleSystemAliveCount; - boo::ObjToken m_dataBind; - boo::ObjToken m_vertBuf; - boo::ObjToken m_uniformBuf; - std::unique_ptr m_lineRenderer; - std::vector m_cachedVerts; + bool IsValid() const { return x1b4_LENG >= 2 && x1b8_SIDE >= 2; } + void UpdateMaxRadius(float r); + void UpdateBounds(const zeus::CVector3f& pos); + float GetLeftRadius(int i) const; + float GetRightRadius(int i) const; + void UpdateSwooshTranslation(const zeus::CVector3f& translation); + void UpdateTranslationAndOrientation(); - static int g_ParticleSystemAliveCount; - - bool IsValid() const { return x1b4_LENG >= 2 && x1b8_SIDE >= 2; } - void UpdateMaxRadius(float r); - void UpdateBounds(const zeus::CVector3f& pos); - float GetLeftRadius(int i) const; - float GetRightRadius(int i) const; - void UpdateSwooshTranslation(const zeus::CVector3f& translation); - void UpdateTranslationAndOrientation(); - - static zeus::CVector3f GetSplinePoint(const zeus::CVector3f& p0, const zeus::CVector3f& p1, - const zeus::CVector3f& p2, const zeus::CVector3f& p3, float t); - int WrapIndex(int i) const; - void RenderNSidedSpline(); - void RenderNSidedNoSpline(); - void Render3SidedSolidSpline(); - void Render3SidedSolidNoSplineNoGaps(); - void Render2SidedSpline(); - void Render2SidedNoSplineGaps(); - void Render2SidedNoSplineNoGaps(); + static zeus::CVector3f GetSplinePoint(const zeus::CVector3f& p0, const zeus::CVector3f& p1, const zeus::CVector3f& p2, + const zeus::CVector3f& p3, float t); + int WrapIndex(int i) const; + void RenderNSidedSpline(); + void RenderNSidedNoSpline(); + void Render3SidedSolidSpline(); + void Render3SidedSolidNoSplineNoGaps(); + void Render2SidedSpline(); + void Render2SidedNoSplineGaps(); + void Render2SidedNoSplineNoGaps(); public: - CParticleSwoosh(const TToken& desc, int); - ~CParticleSwoosh(); + CParticleSwoosh(const TToken& desc, int); + ~CParticleSwoosh(); - CSwooshDescription* GetDesc() { return x1c_desc.GetObj(); } + CSwooshDescription* GetDesc() { return x1c_desc.GetObj(); } - bool Update(double); - void Render(const CActorLights* = nullptr); - void SetOrientation(const zeus::CTransform&); - void SetTranslation(const zeus::CVector3f&); - void SetGlobalOrientation(const zeus::CTransform&); - void SetGlobalTranslation(const zeus::CVector3f&); - void SetGlobalScale(const zeus::CVector3f&); - void SetLocalScale(const zeus::CVector3f&); - void SetParticleEmission(bool); - void SetModulationColor(const zeus::CColor&); - const zeus::CTransform& GetOrientation() const; - const zeus::CVector3f& GetTranslation() const; - const zeus::CTransform& GetGlobalOrientation() const; - const zeus::CVector3f& GetGlobalTranslation() const; - const zeus::CVector3f& GetGlobalScale() const; - const zeus::CColor& GetModulationColor() const; - bool IsSystemDeletable() const; - std::experimental::optional GetBounds() const; - u32 GetParticleCount() const; - bool SystemHasLight() const; - CLight GetLight() const; - bool GetParticleEmission() const; - void DestroyParticles(); - void Reset() {} - FourCC Get4CharId() const { return FOURCC('SWHC'); } - void SetRenderGaps(bool r) { x1d0_27_renderGaps = r; } + bool Update(double); + void Render(const CActorLights* = nullptr); + void SetOrientation(const zeus::CTransform&); + void SetTranslation(const zeus::CVector3f&); + void SetGlobalOrientation(const zeus::CTransform&); + void SetGlobalTranslation(const zeus::CVector3f&); + void SetGlobalScale(const zeus::CVector3f&); + void SetLocalScale(const zeus::CVector3f&); + void SetParticleEmission(bool); + void SetModulationColor(const zeus::CColor&); + const zeus::CTransform& GetOrientation() const; + const zeus::CVector3f& GetTranslation() const; + const zeus::CTransform& GetGlobalOrientation() const; + const zeus::CVector3f& GetGlobalTranslation() const; + const zeus::CVector3f& GetGlobalScale() const; + const zeus::CColor& GetModulationColor() const; + bool IsSystemDeletable() const; + std::experimental::optional GetBounds() const; + u32 GetParticleCount() const; + bool SystemHasLight() const; + CLight GetLight() const; + bool GetParticleEmission() const; + void DestroyParticles(); + void Reset() {} + FourCC Get4CharId() const { return FOURCC('SWHC'); } + void SetRenderGaps(bool r) { x1d0_27_renderGaps = r; } - void DoWarmupUpdate() - { - x1d0_26_forceOneUpdate = true; - Update(0.0); + void DoWarmupUpdate() { + x1d0_26_forceOneUpdate = true; + Update(0.0); + } + + void DoElectricWarmup() { + for (int i = 0; i < x15c_swooshes.size(); ++i) { + x1d0_26_forceOneUpdate = true; + Update(0.0); } + } - void DoElectricWarmup() - { - for (int i=0 ; i& offsets) { + u32 curIdx = x158_curParticle; + for (int i = 0; i < x15c_swooshes.size(); ++i) { + curIdx = u32((curIdx + 1) % x15c_swooshes.size()); + x15c_swooshes[curIdx].xc_translation = offsets[i]; } + } - void DoElectricCreate(const std::vector& offsets) - { - u32 curIdx = x158_curParticle; - for (int i=0 ; i 0) + vec = rotation * zeus::CVector3f(std::cos(i + anglePhase) * xAmplitude, 0.f, std::sin(float(i)) * zAmplitude); + data.xc_translation = trans + vec; + trans += swooshSegDelta; + std::swap(rot, data.x30_irot); } + } - void DoGrappleUpdate(const zeus::CVector3f& beamGunPos, const zeus::CTransform& rotation, float anglePhase, - float xAmplitude, float zAmplitude, const zeus::CVector3f& swooshSegDelta) - { - float rot = x15c_swooshes.back().x30_irot; - zeus::CVector3f trans = beamGunPos; - for (int i=0 ; i 0) - vec = rotation * zeus::CVector3f(std::cos(i + anglePhase) * xAmplitude, 0.f, - std::sin(float(i)) * zAmplitude); - data.xc_translation = trans + vec; - trans += swooshSegDelta; - std::swap(rot, data.x30_irot); - } - } - - void DoSpiderBallWarmup(zeus::CVector3f& translation, const zeus::CVector3f& transInc) - { - SetOrientation(zeus::lookAt(zeus::CVector3f::skZero, transInc)); - for (int i=0 ; i<6 ; ++i) - { - SetTranslation(translation); - x1d0_26_forceOneUpdate = true; - Update(0.0); - translation += transInc; - } + void DoSpiderBallWarmup(zeus::CVector3f& translation, const zeus::CVector3f& transInc) { + SetOrientation(zeus::lookAt(zeus::CVector3f::skZero, transInc)); + for (int i = 0; i < 6; ++i) { + SetTranslation(translation); + x1d0_26_forceOneUpdate = true; + Update(0.0); + translation += transInc; } + } }; -} - +} // namespace urde diff --git a/Runtime/Particle/CParticleSwooshDataFactory.cpp b/Runtime/Particle/CParticleSwooshDataFactory.cpp index 9fc924f32..a9f447ed0 100644 --- a/Runtime/Particle/CParticleSwooshDataFactory.cpp +++ b/Runtime/Particle/CParticleSwooshDataFactory.cpp @@ -6,142 +6,133 @@ #include "CRandom16.hpp" #include "CSimplePool.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CParticleSwooshDataFactory"); using CPF = CParticleDataFactory; -CSwooshDescription* CParticleSwooshDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) -{ - return CreateGeneratorDescription(in, resPool); +CSwooshDescription* CParticleSwooshDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) { + return CreateGeneratorDescription(in, resPool); } -CSwooshDescription* CParticleSwooshDataFactory::CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool) -{ - FourCC clsId = CPF::GetClassID(in); - if (clsId == FOURCC('SWSH')) - { - CSwooshDescription* desc = new CSwooshDescription; - if (CreateWPSM(desc, in, resPool)) - return desc; - else - delete desc; - } - return nullptr; +CSwooshDescription* CParticleSwooshDataFactory::CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool) { + FourCC clsId = CPF::GetClassID(in); + if (clsId == FOURCC('SWSH')) { + CSwooshDescription* desc = new CSwooshDescription; + if (CreateWPSM(desc, in, resPool)) + return desc; + else + delete desc; + } + return nullptr; } -bool CParticleSwooshDataFactory::CreateWPSM(CSwooshDescription* desc, CInputStream& in, CSimplePool* resPool) -{ - CRandom16 rand; - FourCC clsId = CPF::GetClassID(in); - while (clsId != SBIG('_END')) - { - CGlobalRandom gr(rand); - switch (clsId) - { - case SBIG('PSLT'): - desc->x0_PSLT = CPF::GetIntElement(in); - break; - case SBIG('TIME'): - desc->x4_TIME = CPF::GetRealElement(in); - break; - case SBIG('LRAD'): - desc->x8_LRAD = CPF::GetRealElement(in); - break; - case SBIG('RRAD'): - desc->xc_RRAD = CPF::GetRealElement(in); - break; - case SBIG('LENG'): - desc->x10_LENG = CPF::GetIntElement(in); - break; - case SBIG('COLR'): - desc->x14_COLR = CPF::GetColorElement(in); - break; - case SBIG('SIDE'): - desc->x18_SIDE = CPF::GetIntElement(in); - break; - case SBIG('IROT'): - desc->x1c_IROT = CPF::GetRealElement(in); - break; - case SBIG('ROTM'): - desc->x20_ROTM = CPF::GetRealElement(in); - break; - case SBIG('POFS'): - desc->x24_POFS = CPF::GetVectorElement(in); - break; - case SBIG('IVEL'): - desc->x28_IVEL = CPF::GetVectorElement(in); - break; - case SBIG('NPOS'): - desc->x2c_NPOS = CPF::GetVectorElement(in); - break; - case SBIG('VELM'): - desc->x30_VELM = CPF::GetModVectorElement(in); - break; - case SBIG('VLM2'): - desc->x34_VLM2 = CPF::GetModVectorElement(in); - break; - case SBIG('SPLN'): - desc->x38_SPLN = CPF::GetIntElement(in); - break; - case SBIG('TEXR'): - desc->x3c_TEXR = CPF::GetTextureElement(in, resPool); - break; - case SBIG('TSPN'): - desc->x40_TSPN = CPF::GetIntElement(in); - break; - case SBIG('LLRD'): - desc->x44_24_LLRD = CPF::GetBool(in); - break; - case SBIG('CROS'): - desc->x44_25_CROS = CPF::GetBool(in); - break; - case SBIG('VLS1'): - desc->x44_26_VLS1 = CPF::GetBool(in); - break; - case SBIG('VLS2'): - desc->x44_27_VLS2 = CPF::GetBool(in); - break; - case SBIG('SROT'): - desc->x44_28_SROT = CPF::GetBool(in); - break; - case SBIG('WIRE'): - desc->x44_29_WIRE = CPF::GetBool(in); - break; - case SBIG('TEXW'): - desc->x44_30_TEXW = CPF::GetBool(in); - break; - case SBIG('AALP'): - desc->x44_31_AALP = CPF::GetBool(in); - break; - case SBIG('ZBUF'): - desc->x45_24_ZBUF = CPF::GetBool(in); - break; - case SBIG('ORNT'): - desc->x45_25_ORNT = CPF::GetBool(in); - break; - case SBIG('CRND'): - desc->x45_26_CRND = CPF::GetBool(in); - break; - default: - { - uint32_t clsName = clsId.toUint32(); - Log.report(logvisor::Fatal, "Unknown SWSH class %.4s @%" PRIi64, &clsName, in.position()); - return false; - } - } - clsId = CPF::GetClassID(in); +bool CParticleSwooshDataFactory::CreateWPSM(CSwooshDescription* desc, CInputStream& in, CSimplePool* resPool) { + CRandom16 rand; + FourCC clsId = CPF::GetClassID(in); + while (clsId != SBIG('_END')) { + CGlobalRandom gr(rand); + switch (clsId) { + case SBIG('PSLT'): + desc->x0_PSLT = CPF::GetIntElement(in); + break; + case SBIG('TIME'): + desc->x4_TIME = CPF::GetRealElement(in); + break; + case SBIG('LRAD'): + desc->x8_LRAD = CPF::GetRealElement(in); + break; + case SBIG('RRAD'): + desc->xc_RRAD = CPF::GetRealElement(in); + break; + case SBIG('LENG'): + desc->x10_LENG = CPF::GetIntElement(in); + break; + case SBIG('COLR'): + desc->x14_COLR = CPF::GetColorElement(in); + break; + case SBIG('SIDE'): + desc->x18_SIDE = CPF::GetIntElement(in); + break; + case SBIG('IROT'): + desc->x1c_IROT = CPF::GetRealElement(in); + break; + case SBIG('ROTM'): + desc->x20_ROTM = CPF::GetRealElement(in); + break; + case SBIG('POFS'): + desc->x24_POFS = CPF::GetVectorElement(in); + break; + case SBIG('IVEL'): + desc->x28_IVEL = CPF::GetVectorElement(in); + break; + case SBIG('NPOS'): + desc->x2c_NPOS = CPF::GetVectorElement(in); + break; + case SBIG('VELM'): + desc->x30_VELM = CPF::GetModVectorElement(in); + break; + case SBIG('VLM2'): + desc->x34_VLM2 = CPF::GetModVectorElement(in); + break; + case SBIG('SPLN'): + desc->x38_SPLN = CPF::GetIntElement(in); + break; + case SBIG('TEXR'): + desc->x3c_TEXR = CPF::GetTextureElement(in, resPool); + break; + case SBIG('TSPN'): + desc->x40_TSPN = CPF::GetIntElement(in); + break; + case SBIG('LLRD'): + desc->x44_24_LLRD = CPF::GetBool(in); + break; + case SBIG('CROS'): + desc->x44_25_CROS = CPF::GetBool(in); + break; + case SBIG('VLS1'): + desc->x44_26_VLS1 = CPF::GetBool(in); + break; + case SBIG('VLS2'): + desc->x44_27_VLS2 = CPF::GetBool(in); + break; + case SBIG('SROT'): + desc->x44_28_SROT = CPF::GetBool(in); + break; + case SBIG('WIRE'): + desc->x44_29_WIRE = CPF::GetBool(in); + break; + case SBIG('TEXW'): + desc->x44_30_TEXW = CPF::GetBool(in); + break; + case SBIG('AALP'): + desc->x44_31_AALP = CPF::GetBool(in); + break; + case SBIG('ZBUF'): + desc->x45_24_ZBUF = CPF::GetBool(in); + break; + case SBIG('ORNT'): + desc->x45_25_ORNT = CPF::GetBool(in); + break; + case SBIG('CRND'): + desc->x45_26_CRND = CPF::GetBool(in); + break; + default: { + uint32_t clsName = clsId.toUint32(); + Log.report(logvisor::Fatal, "Unknown SWSH class %.4s @%" PRIi64, &clsName, in.position()); + return false; } + } + clsId = CPF::GetClassID(in); + } - return true; + return true; } CFactoryFnReturn FParticleSwooshDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, - CObjectReference*) -{ - CSimplePool* sp = vparms.GetOwnedObj(); - return TToken::GetIObjObjectFor( - std::unique_ptr(CParticleSwooshDataFactory::GetGeneratorDesc(in, sp))); -} + CObjectReference*) { + CSimplePool* sp = vparms.GetOwnedObj(); + return TToken::GetIObjObjectFor( + std::unique_ptr(CParticleSwooshDataFactory::GetGeneratorDesc(in, sp))); } +} // namespace urde diff --git a/Runtime/Particle/CParticleSwooshDataFactory.hpp b/Runtime/Particle/CParticleSwooshDataFactory.hpp index c03f806f8..c23432f6c 100644 --- a/Runtime/Particle/CParticleSwooshDataFactory.hpp +++ b/Runtime/Particle/CParticleSwooshDataFactory.hpp @@ -6,19 +6,17 @@ #include "CToken.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { class CSwooshDescription; class CSimplePool; -class CParticleSwooshDataFactory -{ - static CSwooshDescription* CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool); - static bool CreateWPSM(CSwooshDescription* desc, CInputStream& in, CSimplePool* resPool); +class CParticleSwooshDataFactory { + static CSwooshDescription* CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool); + static bool CreateWPSM(CSwooshDescription* desc, CInputStream& in, CSimplePool* resPool); + public: - static CSwooshDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); + static CSwooshDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); }; CFactoryFnReturn FParticleSwooshDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference*); -} - +} // namespace urde diff --git a/Runtime/Particle/CProjectileWeaponDataFactory.cpp b/Runtime/Particle/CProjectileWeaponDataFactory.cpp index dcd7ae90e..64101c016 100644 --- a/Runtime/Particle/CProjectileWeaponDataFactory.cpp +++ b/Runtime/Particle/CProjectileWeaponDataFactory.cpp @@ -8,171 +8,158 @@ #include "CRandom16.hpp" #include "CSimplePool.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::CProjectileWeaponDataFactory"); using CPF = CParticleDataFactory; -CWeaponDescription* CProjectileWeaponDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) -{ - return CreateGeneratorDescription(in, resPool); +CWeaponDescription* CProjectileWeaponDataFactory::GetGeneratorDesc(CInputStream& in, CSimplePool* resPool) { + return CreateGeneratorDescription(in, resPool); } -CWeaponDescription* CProjectileWeaponDataFactory::CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool) -{ - FourCC clsId = CPF::GetClassID(in); - if (clsId == FOURCC('WPSM')) - { - CWeaponDescription* desc = new CWeaponDescription; - CreateWPSM(desc, in, resPool); - return desc; - } +CWeaponDescription* CProjectileWeaponDataFactory::CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool) { + FourCC clsId = CPF::GetClassID(in); + if (clsId == FOURCC('WPSM')) { + CWeaponDescription* desc = new CWeaponDescription; + CreateWPSM(desc, in, resPool); + return desc; + } - return nullptr; + return nullptr; } -bool CProjectileWeaponDataFactory::CreateWPSM(CWeaponDescription* desc, CInputStream& in, CSimplePool* resPool) -{ - CRandom16 rand; - CGlobalRandom gr{rand}; - FourCC clsId = CPF::GetClassID(in); +bool CProjectileWeaponDataFactory::CreateWPSM(CWeaponDescription* desc, CInputStream& in, CSimplePool* resPool) { + CRandom16 rand; + CGlobalRandom gr{rand}; + FourCC clsId = CPF::GetClassID(in); - while (clsId != SBIG('_END')) - { - switch (clsId) - { - case SBIG('IORN'): - desc->x0_IORN = CPF::GetVectorElement(in); - break; - case SBIG('IVEC'): - desc->x4_IVEC = CPF::GetVectorElement(in); - break; - case SBIG('PSOV'): - desc->x8_PSOV = CPF::GetVectorElement(in); - break; - case SBIG('PSVM'): - desc->xc_PSVM = CPF::GetModVectorElement(in); - break; - case SBIG('VMD2'): - desc->x10_VMD2 = CPF::GetBool(in); - break; - case SBIG('PSLT'): - desc->x14_PSLT = CPF::GetIntElement(in); - break; - case SBIG('PSCL'): - desc->x18_PSCL = CPF::GetVectorElement(in); - break; - case SBIG('PCOL'): - desc->x1c_PCOL = CPF::GetColorElement(in); - break; - case SBIG('POFS'): - desc->x20_POFS = CPF::GetVectorElement(in); - break; - case SBIG('OFST'): - desc->x24_OFST = CPF::GetVectorElement(in); - break; - case SBIG('APSO'): - desc->x28_APSO = CPF::GetBool(in); - break; - case SBIG('HOMG'): - desc->x29_HOMG = CPF::GetBool(in); - break; - case SBIG('AP11'): - desc->x2a_AP11 = CPF::GetBool(in); - break; - case SBIG('AP21'): - desc->x2b_AP21 = CPF::GetBool(in); - break; - case SBIG('AS11'): - desc->x2c_AS11 = CPF::GetBool(in); - break; - case SBIG('AS12'): - desc->x2d_AS12 = CPF::GetBool(in); - break; - case SBIG('AS13'): - desc->x2e_AS13 = CPF::GetBool(in); - break; - case SBIG('TRAT'): - desc->x30_TRAT = CPF::GetRealElement(in); - break; - case SBIG('APSM'): - { - std::vector tracker; - tracker.reserve(8); - desc->x34_APSM = CPF::GetChildGeneratorDesc(in, resPool, tracker); - break; - } - case SBIG('APS2'): - { - std::vector tracker; - tracker.reserve(8); - desc->x44_APS2 = CPF::GetChildGeneratorDesc(in, resPool, tracker); - break; - } - case SBIG('ASW1'): - desc->x54_ASW1 = CPF::GetSwooshGeneratorDesc(in, resPool); - break; - case SBIG('ASW2'): - desc->x64_ASW2 = CPF::GetSwooshGeneratorDesc(in, resPool); - break; - case SBIG('ASW3'): - desc->x74_ASW3 = CPF::GetSwooshGeneratorDesc(in, resPool); - break; - case SBIG('OHEF'): - desc->x84_OHEF = CPF::GetModel(in, resPool); - break; - case SBIG('COLR'): - { - FourCC cid = CPF::GetClassID(in); - if (cid == SBIG('NONE')) - break; - CAssetId id(in); - if (id.IsValid()) - desc->x94_COLR = {resPool->GetObj({FOURCC('CRSC'), id}), true}; - break; - } - case SBIG('EWTR'): - desc->xa4_EWTR = CPF::GetBool(in); - break; - case SBIG('LWTR'): - desc->xa5_LWTR = CPF::GetBool(in); - break; - case SBIG('SWTR'): - desc->xa6_SWTR = CPF::GetBool(in); - break; - case SBIG('PJFX'): - { - FourCC cid = CPF::GetClassID(in); - if (cid == FOURCC('NONE')) - break; - - desc->xa8_PJFX = CPF::GetInt(in); - break; - } - case SBIG('RNGE'): - desc->xac_RNGE = CPF::GetRealElement(in); - break; - case SBIG('FOFF'): - desc->xb0_FOFF = CPF::GetRealElement(in); - break; - default: - { - uint32_t clsName = clsId.toUint32(); - Log.report(logvisor::Fatal, "Unknown WPSM class %.4s @%" PRIi64, &clsName, in.position()); - return false; - } - } - clsId = CPF::GetClassID(in); + while (clsId != SBIG('_END')) { + switch (clsId) { + case SBIG('IORN'): + desc->x0_IORN = CPF::GetVectorElement(in); + break; + case SBIG('IVEC'): + desc->x4_IVEC = CPF::GetVectorElement(in); + break; + case SBIG('PSOV'): + desc->x8_PSOV = CPF::GetVectorElement(in); + break; + case SBIG('PSVM'): + desc->xc_PSVM = CPF::GetModVectorElement(in); + break; + case SBIG('VMD2'): + desc->x10_VMD2 = CPF::GetBool(in); + break; + case SBIG('PSLT'): + desc->x14_PSLT = CPF::GetIntElement(in); + break; + case SBIG('PSCL'): + desc->x18_PSCL = CPF::GetVectorElement(in); + break; + case SBIG('PCOL'): + desc->x1c_PCOL = CPF::GetColorElement(in); + break; + case SBIG('POFS'): + desc->x20_POFS = CPF::GetVectorElement(in); + break; + case SBIG('OFST'): + desc->x24_OFST = CPF::GetVectorElement(in); + break; + case SBIG('APSO'): + desc->x28_APSO = CPF::GetBool(in); + break; + case SBIG('HOMG'): + desc->x29_HOMG = CPF::GetBool(in); + break; + case SBIG('AP11'): + desc->x2a_AP11 = CPF::GetBool(in); + break; + case SBIG('AP21'): + desc->x2b_AP21 = CPF::GetBool(in); + break; + case SBIG('AS11'): + desc->x2c_AS11 = CPF::GetBool(in); + break; + case SBIG('AS12'): + desc->x2d_AS12 = CPF::GetBool(in); + break; + case SBIG('AS13'): + desc->x2e_AS13 = CPF::GetBool(in); + break; + case SBIG('TRAT'): + desc->x30_TRAT = CPF::GetRealElement(in); + break; + case SBIG('APSM'): { + std::vector tracker; + tracker.reserve(8); + desc->x34_APSM = CPF::GetChildGeneratorDesc(in, resPool, tracker); + break; } - return true; + case SBIG('APS2'): { + std::vector tracker; + tracker.reserve(8); + desc->x44_APS2 = CPF::GetChildGeneratorDesc(in, resPool, tracker); + break; + } + case SBIG('ASW1'): + desc->x54_ASW1 = CPF::GetSwooshGeneratorDesc(in, resPool); + break; + case SBIG('ASW2'): + desc->x64_ASW2 = CPF::GetSwooshGeneratorDesc(in, resPool); + break; + case SBIG('ASW3'): + desc->x74_ASW3 = CPF::GetSwooshGeneratorDesc(in, resPool); + break; + case SBIG('OHEF'): + desc->x84_OHEF = CPF::GetModel(in, resPool); + break; + case SBIG('COLR'): { + FourCC cid = CPF::GetClassID(in); + if (cid == SBIG('NONE')) + break; + CAssetId id(in); + if (id.IsValid()) + desc->x94_COLR = {resPool->GetObj({FOURCC('CRSC'), id}), true}; + break; + } + case SBIG('EWTR'): + desc->xa4_EWTR = CPF::GetBool(in); + break; + case SBIG('LWTR'): + desc->xa5_LWTR = CPF::GetBool(in); + break; + case SBIG('SWTR'): + desc->xa6_SWTR = CPF::GetBool(in); + break; + case SBIG('PJFX'): { + FourCC cid = CPF::GetClassID(in); + if (cid == FOURCC('NONE')) + break; + + desc->xa8_PJFX = CPF::GetInt(in); + break; + } + case SBIG('RNGE'): + desc->xac_RNGE = CPF::GetRealElement(in); + break; + case SBIG('FOFF'): + desc->xb0_FOFF = CPF::GetRealElement(in); + break; + default: { + uint32_t clsName = clsId.toUint32(); + Log.report(logvisor::Fatal, "Unknown WPSM class %.4s @%" PRIi64, &clsName, in.position()); + return false; + } + } + clsId = CPF::GetClassID(in); + } + return true; } CFactoryFnReturn FProjectileWeaponDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, - CObjectReference*) -{ - CSimplePool* sp = vparms.GetOwnedObj(); - return TToken::GetIObjObjectFor( - std::unique_ptr(CProjectileWeaponDataFactory::GetGeneratorDesc(in, sp))); -} + CObjectReference*) { + CSimplePool* sp = vparms.GetOwnedObj(); + return TToken::GetIObjObjectFor( + std::unique_ptr(CProjectileWeaponDataFactory::GetGeneratorDesc(in, sp))); } +} // namespace urde diff --git a/Runtime/Particle/CProjectileWeaponDataFactory.hpp b/Runtime/Particle/CProjectileWeaponDataFactory.hpp index 32e972d67..5299b717a 100644 --- a/Runtime/Particle/CProjectileWeaponDataFactory.hpp +++ b/Runtime/Particle/CProjectileWeaponDataFactory.hpp @@ -6,20 +6,17 @@ #include "CToken.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { class CWeaponDescription; class CSimplePool; -class CProjectileWeaponDataFactory -{ - static CWeaponDescription* CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool); - static bool CreateWPSM(CWeaponDescription* desc, CInputStream& in, CSimplePool* resPool); +class CProjectileWeaponDataFactory { + static CWeaponDescription* CreateGeneratorDescription(CInputStream& in, CSimplePool* resPool); + static bool CreateWPSM(CWeaponDescription* desc, CInputStream& in, CSimplePool* resPool); public: - static CWeaponDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); + static CWeaponDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* resPool); }; CFactoryFnReturn FProjectileWeaponDataFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, CObjectReference*); -} - +} // namespace urde diff --git a/Runtime/Particle/CRealElement.cpp b/Runtime/Particle/CRealElement.cpp index b8cd147df..962927025 100644 --- a/Runtime/Particle/CRealElement.cpp +++ b/Runtime/Particle/CRealElement.cpp @@ -8,396 +8,344 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Real_Elements */ -namespace urde -{ +namespace urde { -CREKeyframeEmitter::CREKeyframeEmitter(CInputStream& in) -{ - x4_percent = in.readUint32Big(); - x8_unk1 = in.readUint32Big(); - xc_loop = in.readBool(); - xd_unk2 = in.readBool(); - x10_loopEnd = in.readUint32Big(); - x14_loopStart = in.readUint32Big(); +CREKeyframeEmitter::CREKeyframeEmitter(CInputStream& in) { + x4_percent = in.readUint32Big(); + x8_unk1 = in.readUint32Big(); + xc_loop = in.readBool(); + xd_unk2 = in.readBool(); + x10_loopEnd = in.readUint32Big(); + x14_loopStart = in.readUint32Big(); - u32 count = in.readUint32Big(); - x18_keys.reserve(count); - for (u32 i=0 ; i= x10_loopEnd) - { - int v1 = emitterTime - x14_loopStart; - int v2 = x10_loopEnd - x14_loopStart; - calcKey = v1 % v2; - calcKey += x14_loopStart; - } - } - else - { - int v1 = x10_loopEnd - 1; - if (v1 < emitterTime) - calcKey = v1; - } - valOut = x18_keys[calcKey]; +bool CREKeyframeEmitter::GetValue(int frame, float& valOut) const { + if (!x4_percent) { + int emitterTime = CParticleGlobals::g_EmitterTime; + int calcKey = emitterTime; + if (xc_loop) { + if (emitterTime >= x10_loopEnd) { + int v1 = emitterTime - x14_loopStart; + int v2 = x10_loopEnd - x14_loopStart; + calcKey = v1 % v2; + calcKey += x14_loopStart; + } + } else { + int v1 = x10_loopEnd - 1; + if (v1 < emitterTime) + calcKey = v1; } + valOut = x18_keys[calcKey]; + } else { + int ltPerc = CParticleGlobals::g_ParticleLifetimePercentage; + float ltPercRem = CParticleGlobals::g_ParticleLifetimePercentageRemainder; + if (ltPerc == 100) + valOut = x18_keys[100]; else - { - int ltPerc = CParticleGlobals::g_ParticleLifetimePercentage; - float ltPercRem = CParticleGlobals::g_ParticleLifetimePercentageRemainder; - if (ltPerc == 100) - valOut = x18_keys[100]; - else - valOut = ltPercRem * x18_keys[ltPerc+1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; - } - return false; + valOut = ltPercRem * x18_keys[ltPerc + 1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; + } + return false; } -bool CRELifetimeTween::GetValue(int frame, float& valOut) const -{ - float ltFac = frame / CParticleGlobals::g_ParticleLifetimeReal; - float a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = b * ltFac + (1.0f - ltFac) * a; - return false; +bool CRELifetimeTween::GetValue(int frame, float& valOut) const { + float ltFac = frame / CParticleGlobals::g_ParticleLifetimeReal; + float a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = b * ltFac + (1.0f - ltFac) * a; + return false; } -bool CREConstant::GetValue(int frame, float& valOut) const -{ - valOut = x4_val; - return false; +bool CREConstant::GetValue(int frame, float& valOut) const { + valOut = x4_val; + return false; } -bool CRETimeChain::GetValue(int frame, float& valOut) const -{ - int v; - xc_swFrame->GetValue(frame, v); - if (frame >= v) - return x8_b->GetValue(frame, valOut); - else - return x4_a->GetValue(frame, valOut); +bool CRETimeChain::GetValue(int frame, float& valOut) const { + int v; + xc_swFrame->GetValue(frame, v); + if (frame >= v) + return x8_b->GetValue(frame, valOut); + else + return x4_a->GetValue(frame, valOut); } -bool CREAdd::GetValue(int frame, float& valOut) const -{ - float a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = a + b; - return false; +bool CREAdd::GetValue(int frame, float& valOut) const { + float a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a + b; + return false; } -bool CREClamp::GetValue(int frame,float& valOut) const -{ - float a, b; - x4_min->GetValue(frame, a); - x8_max->GetValue(frame, b); - xc_val->GetValue(frame, valOut); - if (valOut > b) - valOut = b; - if (valOut < a) - valOut = a; - return false; +bool CREClamp::GetValue(int frame, float& valOut) const { + float a, b; + x4_min->GetValue(frame, a); + x8_max->GetValue(frame, b); + xc_val->GetValue(frame, valOut); + if (valOut > b) + valOut = b; + if (valOut < a) + valOut = a; + return false; } -bool CREInitialRandom::GetValue(int frame, float& valOut) const -{ - if (frame == 0) - { - float a, b; - x4_min->GetValue(frame, a); - x8_max->GetValue(frame, b); - float rand = CRandom16::GetRandomNumber()->Float(); - valOut = b * rand + a * (1.0f - rand); - } - return false; -} - -bool CRERandom::GetValue(int frame, float& valOut) const -{ +bool CREInitialRandom::GetValue(int frame, float& valOut) const { + if (frame == 0) { float a, b; x4_min->GetValue(frame, a); x8_max->GetValue(frame, b); float rand = CRandom16::GetRandomNumber()->Float(); valOut = b * rand + a * (1.0f - rand); - return false; + } + return false; } -bool CREDotProduct::GetValue(int frame, float& valOut) const -{ - zeus::CVector3f a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = a.dot(b); - return false; +bool CRERandom::GetValue(int frame, float& valOut) const { + float a, b; + x4_min->GetValue(frame, a); + x8_max->GetValue(frame, b); + float rand = CRandom16::GetRandomNumber()->Float(); + valOut = b * rand + a * (1.0f - rand); + return false; } - -bool CREMultiply::GetValue(int frame, float& valOut) const -{ - float a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = a * b; - return false; +bool CREDotProduct::GetValue(int frame, float& valOut) const { + zeus::CVector3f a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a.dot(b); + return false; } -bool CREPulse::GetValue(int frame, float& valOut) const -{ - int a, b; - x4_aDuration->GetValue(frame, a); - x8_bDuration->GetValue(frame, b); - int cv = std::max(1, a + b + 1); +bool CREMultiply::GetValue(int frame, float& valOut) const { + float a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a * b; + return false; +} - if (b >= 1) - { - int cv2 = frame % cv; - if (cv2 >= a) - x10_valB->GetValue(frame, valOut); - else - xc_valA->GetValue(frame, valOut); - } +bool CREPulse::GetValue(int frame, float& valOut) const { + int a, b; + x4_aDuration->GetValue(frame, a); + x8_bDuration->GetValue(frame, b); + int cv = std::max(1, a + b + 1); + + if (b >= 1) { + int cv2 = frame % cv; + if (cv2 >= a) + x10_valB->GetValue(frame, valOut); else - xc_valA->GetValue(frame, valOut); + xc_valA->GetValue(frame, valOut); + } else + xc_valA->GetValue(frame, valOut); - return false; + return false; } -bool CRETimeScale::GetValue(int frame, float& valOut) const -{ - float a; - x4_a->GetValue(frame, a); - valOut = float(frame) * a; - return false; +bool CRETimeScale::GetValue(int frame, float& valOut) const { + float a; + x4_a->GetValue(frame, a); + valOut = float(frame) * a; + return false; } -bool CRELifetimePercent::GetValue(int frame, float& valOut) const -{ - float a; - x4_percentVal->GetValue(frame, a); - a = std::max(0.0f, a); - valOut = (a / 100.0f) * CParticleGlobals::g_ParticleLifetimeReal; - return false; +bool CRELifetimePercent::GetValue(int frame, float& valOut) const { + float a; + x4_percentVal->GetValue(frame, a); + a = std::max(0.0f, a); + valOut = (a / 100.0f) * CParticleGlobals::g_ParticleLifetimeReal; + return false; } -bool CRESineWave::GetValue(int frame, float& valOut) const -{ - float a, b, c; - x4_frequency->GetValue(frame, a); - x8_amplitude->GetValue(frame, b); - xc_phase->GetValue(frame, c); - valOut = std::sin(zeus::degToRad(frame * a + c)) * b; - return false; +bool CRESineWave::GetValue(int frame, float& valOut) const { + float a, b, c; + x4_frequency->GetValue(frame, a); + x8_amplitude->GetValue(frame, b); + xc_phase->GetValue(frame, c); + valOut = std::sin(zeus::degToRad(frame * a + c)) * b; + return false; } -bool CREInitialSwitch::GetValue(int frame, float& valOut) const -{ - if (frame == 0) - x4_a->GetValue(frame, valOut); - else - x8_b->GetValue(frame, valOut); - return false; +bool CREInitialSwitch::GetValue(int frame, float& valOut) const { + if (frame == 0) + x4_a->GetValue(frame, valOut); + else + x8_b->GetValue(frame, valOut); + return false; } -bool CRECompareLessThan::GetValue(int frame, float& valOut) const -{ - float a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - if (a < b) - xc_c->GetValue(frame, valOut); - else - x10_d->GetValue(frame, valOut); - return false; +bool CRECompareLessThan::GetValue(int frame, float& valOut) const { + float a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + if (a < b) + xc_c->GetValue(frame, valOut); + else + x10_d->GetValue(frame, valOut); + return false; } -bool CRECompareEquals::GetValue(int frame, float& valOut) const -{ - float a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - if (std::fabs(a-b) < 0.00001f) - xc_c->GetValue(frame, valOut); - else - x10_d->GetValue(frame, valOut); - return false; +bool CRECompareEquals::GetValue(int frame, float& valOut) const { + float a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + if (std::fabs(a - b) < 0.00001f) + xc_c->GetValue(frame, valOut); + else + x10_d->GetValue(frame, valOut); + return false; } -bool CREParticleAccessParam1::GetValue(int /*frame*/, float& valOut) const -{ - valOut = (*CParticleGlobals::g_particleAccessParameters)[0]; - return false; +bool CREParticleAccessParam1::GetValue(int /*frame*/, float& valOut) const { + valOut = (*CParticleGlobals::g_particleAccessParameters)[0]; + return false; } -bool CREParticleAccessParam2::GetValue(int /*frame*/, float& valOut) const -{ - valOut = (*CParticleGlobals::g_particleAccessParameters)[1]; - return false; +bool CREParticleAccessParam2::GetValue(int /*frame*/, float& valOut) const { + valOut = (*CParticleGlobals::g_particleAccessParameters)[1]; + return false; } -bool CREParticleAccessParam3::GetValue(int /*frame*/, float& valOut) const -{ - valOut = (*CParticleGlobals::g_particleAccessParameters)[2]; - return false; +bool CREParticleAccessParam3::GetValue(int /*frame*/, float& valOut) const { + valOut = (*CParticleGlobals::g_particleAccessParameters)[2]; + return false; } -bool CREParticleAccessParam4::GetValue(int /*frame*/, float& valOut) const -{ - valOut = (*CParticleGlobals::g_particleAccessParameters)[3]; - return false; +bool CREParticleAccessParam4::GetValue(int /*frame*/, float& valOut) const { + valOut = (*CParticleGlobals::g_particleAccessParameters)[3]; + return false; } -bool CREParticleAccessParam5::GetValue(int /*frame*/, float& valOut) const -{ - valOut = (*CParticleGlobals::g_particleAccessParameters)[4]; - return false; +bool CREParticleAccessParam5::GetValue(int /*frame*/, float& valOut) const { + valOut = (*CParticleGlobals::g_particleAccessParameters)[4]; + return false; } -bool CREParticleAccessParam6::GetValue(int /*frame*/, float& valOut) const -{ - valOut = (*CParticleGlobals::g_particleAccessParameters)[5]; - return false; +bool CREParticleAccessParam6::GetValue(int /*frame*/, float& valOut) const { + valOut = (*CParticleGlobals::g_particleAccessParameters)[5]; + return false; } -bool CREParticleAccessParam7::GetValue(int /*frame*/, float& valOut) const -{ - valOut = (*CParticleGlobals::g_particleAccessParameters)[6]; - return false; +bool CREParticleAccessParam7::GetValue(int /*frame*/, float& valOut) const { + valOut = (*CParticleGlobals::g_particleAccessParameters)[6]; + return false; } -bool CREParticleAccessParam8::GetValue(int /*frame*/, float& valOut) const -{ - valOut = (*CParticleGlobals::g_particleAccessParameters)[7]; - return false; +bool CREParticleAccessParam8::GetValue(int /*frame*/, float& valOut) const { + valOut = (*CParticleGlobals::g_particleAccessParameters)[7]; + return false; } -bool CREParticleSizeOrLineLength::GetValue(int /*frame*/, float& valOut) const -{ - valOut = CElementGen::g_currentParticle->x2c_lineLengthOrSize; - return false; +bool CREParticleSizeOrLineLength::GetValue(int /*frame*/, float& valOut) const { + valOut = CElementGen::g_currentParticle->x2c_lineLengthOrSize; + return false; } -bool CREParticleRotationOrLineWidth::GetValue(int /*frame*/, float& valOut) const -{ - valOut = CElementGen::g_currentParticle->x30_lineWidthOrRota; - return false; +bool CREParticleRotationOrLineWidth::GetValue(int /*frame*/, float& valOut) const { + valOut = CElementGen::g_currentParticle->x30_lineWidthOrRota; + return false; } -bool CRESubtract::GetValue(int frame, float& valOut) const -{ - float a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = a - b; - return false; +bool CRESubtract::GetValue(int frame, float& valOut) const { + float a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a - b; + return false; } -bool CREVectorMagnitude::GetValue(int frame, float& valOut) const -{ - zeus::CVector3f a; - x4_a->GetValue(frame, a); - valOut = a.magnitude(); - return false; +bool CREVectorMagnitude::GetValue(int frame, float& valOut) const { + zeus::CVector3f a; + x4_a->GetValue(frame, a); + valOut = a.magnitude(); + return false; } -bool CREVectorXToReal::GetValue(int frame, float& valOut) const -{ - zeus::CVector3f a; - x4_a->GetValue(frame, a); - valOut = a[0]; - return false; +bool CREVectorXToReal::GetValue(int frame, float& valOut) const { + zeus::CVector3f a; + x4_a->GetValue(frame, a); + valOut = a[0]; + return false; } -bool CREVectorYToReal::GetValue(int frame, float& valOut) const -{ - zeus::CVector3f a; - x4_a->GetValue(frame, a); - valOut = a[1]; - return false; +bool CREVectorYToReal::GetValue(int frame, float& valOut) const { + zeus::CVector3f a; + x4_a->GetValue(frame, a); + valOut = a[1]; + return false; } -bool CREVectorZToReal::GetValue(int frame, float& valOut) const -{ - zeus::CVector3f a; - x4_a->GetValue(frame, a); - valOut = a[2]; - return false; +bool CREVectorZToReal::GetValue(int frame, float& valOut) const { + zeus::CVector3f a; + x4_a->GetValue(frame, a); + valOut = a[2]; + return false; } -bool CRECEXT::GetValue(int frame, float& valOut) const -{ - int a; - x4_a->GetValue(frame, a); - int cv = std::max(0, a); - valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetCEXTValue(cv & 0xf); - return false; +bool CRECEXT::GetValue(int frame, float& valOut) const { + int a; + x4_a->GetValue(frame, a); + int cv = std::max(0, a); + valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetCEXTValue(cv & 0xf); + return false; } -bool CREIntTimesReal::GetValue(int frame, float& valOut) const -{ - int a; - x4_a->GetValue(frame, a); - float b; - x8_b->GetValue(frame, b); - valOut = float(a) * b; - return false; +bool CREIntTimesReal::GetValue(int frame, float& valOut) const { + int a; + x4_a->GetValue(frame, a); + float b; + x8_b->GetValue(frame, b); + valOut = float(a) * b; + return false; } -bool CREConstantRange::GetValue(int frame, float& valOut) const -{ - float val, min, max; - x4_val->GetValue(frame, val); - x8_min->GetValue(frame, min); - xc_max->GetValue(frame, max); +bool CREConstantRange::GetValue(int frame, float& valOut) const { + float val, min, max; + x4_val->GetValue(frame, val); + x8_min->GetValue(frame, min); + xc_max->GetValue(frame, max); - if (val > min && val < max) - x10_inRange->GetValue(frame, valOut); - else - x14_outOfRange->GetValue(frame, valOut); + if (val > min && val < max) + x10_inRange->GetValue(frame, valOut); + else + x14_outOfRange->GetValue(frame, valOut); - return false; + return false; } -bool CREGetComponentRed::GetValue(int frame, float& valOut) const -{ - zeus::CColor a = zeus::CColor::skBlack; - x4_a->GetValue(frame, a); - valOut = a.r(); - return false; +bool CREGetComponentRed::GetValue(int frame, float& valOut) const { + zeus::CColor a = zeus::CColor::skBlack; + x4_a->GetValue(frame, a); + valOut = a.r(); + return false; } -bool CREGetComponentGreen::GetValue(int frame, float& valOut) const -{ - zeus::CColor a = zeus::CColor::skBlack; - x4_a->GetValue(frame, a); - valOut = a.g(); - return false; +bool CREGetComponentGreen::GetValue(int frame, float& valOut) const { + zeus::CColor a = zeus::CColor::skBlack; + x4_a->GetValue(frame, a); + valOut = a.g(); + return false; } -bool CREGetComponentBlue::GetValue(int frame, float& valOut) const -{ - zeus::CColor a = zeus::CColor::skBlack; - x4_a->GetValue(frame, a); - valOut = a.b(); - return false; +bool CREGetComponentBlue::GetValue(int frame, float& valOut) const { + zeus::CColor a = zeus::CColor::skBlack; + x4_a->GetValue(frame, a); + valOut = a.b(); + return false; } -bool CREGetComponentAlpha::GetValue(int frame, float& valOut) const -{ - zeus::CColor a = zeus::CColor::skBlack; - x4_a->GetValue(frame, a); - valOut = a.a(); - return false; +bool CREGetComponentAlpha::GetValue(int frame, float& valOut) const { + zeus::CColor a = zeus::CColor::skBlack; + x4_a->GetValue(frame, a); + valOut = a.a(); + return false; } -} +} // namespace urde diff --git a/Runtime/Particle/CRealElement.hpp b/Runtime/Particle/CRealElement.hpp index 8269ce8b0..a007f8ee1 100644 --- a/Runtime/Particle/CRealElement.hpp +++ b/Runtime/Particle/CRealElement.hpp @@ -4,374 +4,353 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Real_Elements */ -namespace urde -{ +namespace urde { + +class CREKeyframeEmitter : public CRealElement { + u32 x4_percent; + u32 x8_unk1; + bool xc_loop; + bool xd_unk2; + u32 x10_loopEnd; + u32 x14_loopStart; + std::vector x18_keys; -class CREKeyframeEmitter : public CRealElement -{ - u32 x4_percent; - u32 x8_unk1; - bool xc_loop; - bool xd_unk2; - u32 x10_loopEnd; - u32 x14_loopStart; - std::vector x18_keys; public: - CREKeyframeEmitter(CInputStream& in); - bool GetValue(int frame, float& valOut) const; + CREKeyframeEmitter(CInputStream& in); + bool GetValue(int frame, float& valOut) const; }; -class CRELifetimeTween : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CRELifetimeTween : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CRELifetimeTween(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, float& valOut) const; + CRELifetimeTween(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREConstant : public CRealElement -{ - float x4_val; +class CREConstant : public CRealElement { + float x4_val; + public: - CREConstant(float val) : x4_val(val) {} - bool GetValue(int frame, float& valOut) const; - bool IsConstant() const {return true;} + CREConstant(float val) : x4_val(val) {} + bool GetValue(int frame, float& valOut) const; + bool IsConstant() const { return true; } }; -class CRETimeChain : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_swFrame; +class CRETimeChain : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_swFrame; + public: - CRETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} - bool GetValue(int frame, float& valOut) const; + CRETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREAdd : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CREAdd : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CREAdd(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, float& valOut) const; + CREAdd(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREClamp : public CRealElement -{ - std::unique_ptr x4_min; - std::unique_ptr x8_max; - std::unique_ptr xc_val; +class CREClamp : public CRealElement { + std::unique_ptr x4_min; + std::unique_ptr x8_max; + std::unique_ptr xc_val; + public: - CREClamp(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) - : x4_min(std::move(a)), x8_max(std::move(b)), xc_val(std::move(c)) {} - bool GetValue(int frame, float& valOut) const; + CREClamp(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_min(std::move(a)), x8_max(std::move(b)), xc_val(std::move(c)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREInitialRandom : public CRealElement -{ - std::unique_ptr x4_min; - std::unique_ptr x8_max; +class CREInitialRandom : public CRealElement { + std::unique_ptr x4_min; + std::unique_ptr x8_max; + public: - CREInitialRandom(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_min(std::move(a)), x8_max(std::move(b)) {} - bool GetValue(int frame, float& valOut) const; - bool IsConstant() const {return true;} + CREInitialRandom(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_min(std::move(a)), x8_max(std::move(b)) {} + bool GetValue(int frame, float& valOut) const; + bool IsConstant() const { return true; } }; -class CRERandom : public CRealElement -{ - std::unique_ptr x4_min; - std::unique_ptr x8_max; +class CRERandom : public CRealElement { + std::unique_ptr x4_min; + std::unique_ptr x8_max; + public: - CRERandom(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_min(std::move(a)), x8_max(std::move(b)) {} - bool GetValue(int frame, float& valOut) const; + CRERandom(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_min(std::move(a)), x8_max(std::move(b)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREDotProduct : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CREDotProduct : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CREDotProduct(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, float& valOut) const; + CREDotProduct(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREMultiply : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CREMultiply : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CREMultiply(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, float& valOut) const; + CREMultiply(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREPulse : public CRealElement -{ - std::unique_ptr x4_aDuration; - std::unique_ptr x8_bDuration; - std::unique_ptr xc_valA; - std::unique_ptr x10_valB; +class CREPulse : public CRealElement { + std::unique_ptr x4_aDuration; + std::unique_ptr x8_bDuration; + std::unique_ptr xc_valA; + std::unique_ptr x10_valB; + public: - CREPulse(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d) - : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_valA(std::move(c)), x10_valB(std::move(d)) {} - bool GetValue(int frame, float& valOut) const; + CREPulse(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d) + : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_valA(std::move(c)), x10_valB(std::move(d)) {} + bool GetValue(int frame, float& valOut) const; }; -class CRETimeScale : public CRealElement -{ - std::unique_ptr x4_a; +class CRETimeScale : public CRealElement { + std::unique_ptr x4_a; + public: - CRETimeScale(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + CRETimeScale(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, float& valOut) const; }; -class CRELifetimePercent : public CRealElement -{ - std::unique_ptr x4_percentVal; +class CRELifetimePercent : public CRealElement { + std::unique_ptr x4_percentVal; + public: - CRELifetimePercent(std::unique_ptr&& a) - : x4_percentVal(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + CRELifetimePercent(std::unique_ptr&& a) : x4_percentVal(std::move(a)) {} + bool GetValue(int frame, float& valOut) const; }; -class CRESineWave : public CRealElement -{ - std::unique_ptr x4_frequency; - std::unique_ptr x8_amplitude; - std::unique_ptr xc_phase; +class CRESineWave : public CRealElement { + std::unique_ptr x4_frequency; + std::unique_ptr x8_amplitude; + std::unique_ptr xc_phase; + public: - CRESineWave(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c) - : x4_frequency(std::move(a)), x8_amplitude(std::move(b)), xc_phase(std::move(c)) {} - bool GetValue(int frame, float& valOut) const; + CRESineWave(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_frequency(std::move(a)), x8_amplitude(std::move(b)), xc_phase(std::move(c)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREInitialSwitch : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CREInitialSwitch : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CREInitialSwitch(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, float& valOut) const; + CREInitialSwitch(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, float& valOut) const; }; -class CRECompareLessThan : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_c; - std::unique_ptr x10_d; -public: - CRECompareLessThan(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_c(std::move(c)), x10_d(std::move(d)) {} - bool GetValue(int frame, float& valOut) const; -}; +class CRECompareLessThan : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_c; + std::unique_ptr x10_d; -class CRECompareEquals : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_c; - std::unique_ptr x10_d; public: - CRECompareEquals(std::unique_ptr&& a, std::unique_ptr&& b, + CRECompareLessThan(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, std::unique_ptr&& d) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_c(std::move(c)), x10_d(std::move(d)) {} - bool GetValue(int frame, float& valOut) const; + : x4_a(std::move(a)), x8_b(std::move(b)), xc_c(std::move(c)), x10_d(std::move(d)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREParticleAccessParam1 : public CRealElement -{ +class CRECompareEquals : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_c; + std::unique_ptr x10_d; + public: - bool GetValue(int frame, float& valOut) const; + CRECompareEquals(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c, std::unique_ptr&& d) + : x4_a(std::move(a)), x8_b(std::move(b)), xc_c(std::move(c)), x10_d(std::move(d)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREParticleAccessParam2 : public CRealElement -{ +class CREParticleAccessParam1 : public CRealElement { public: - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREParticleAccessParam3 : public CRealElement -{ +class CREParticleAccessParam2 : public CRealElement { public: - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREParticleAccessParam4 : public CRealElement -{ +class CREParticleAccessParam3 : public CRealElement { public: - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREParticleAccessParam5 : public CRealElement -{ +class CREParticleAccessParam4 : public CRealElement { public: - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREParticleAccessParam6 : public CRealElement -{ +class CREParticleAccessParam5 : public CRealElement { public: - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREParticleAccessParam7 : public CRealElement -{ +class CREParticleAccessParam6 : public CRealElement { public: - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREParticleAccessParam8 : public CRealElement -{ +class CREParticleAccessParam7 : public CRealElement { public: - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREParticleSizeOrLineLength : public CRealElement -{ +class CREParticleAccessParam8 : public CRealElement { public: - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREParticleRotationOrLineWidth : public CRealElement -{ +class CREParticleSizeOrLineLength : public CRealElement { public: - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CRESubtract : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CREParticleRotationOrLineWidth : public CRealElement { public: - CRESubtract(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREVectorMagnitude : public CRealElement -{ - std::unique_ptr x4_a; +class CRESubtract : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CREVectorMagnitude(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + CRESubtract(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREVectorXToReal : public CRealElement -{ - std::unique_ptr x4_a; +class CREVectorMagnitude : public CRealElement { + std::unique_ptr x4_a; + public: - CREVectorXToReal(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + CREVectorMagnitude(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREVectorYToReal : public CRealElement -{ - std::unique_ptr x4_a; +class CREVectorXToReal : public CRealElement { + std::unique_ptr x4_a; + public: - CREVectorYToReal(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + CREVectorXToReal(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREVectorZToReal : public CRealElement -{ - std::unique_ptr x4_a; +class CREVectorYToReal : public CRealElement { + std::unique_ptr x4_a; + public: - CREVectorZToReal(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + CREVectorYToReal(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, float& valOut) const; }; -class CRECEXT : public CRealElement -{ - std::unique_ptr x4_a; +class CREVectorZToReal : public CRealElement { + std::unique_ptr x4_a; + public: - CRECEXT(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + CREVectorZToReal(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREIntTimesReal : public CRealElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CRECEXT : public CRealElement { + std::unique_ptr x4_a; + public: - CREIntTimesReal(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, float& valOut) const; + CRECEXT(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREConstantRange : public CRealElement -{ - std::unique_ptr x4_val; - std::unique_ptr x8_min; - std::unique_ptr xc_max; - std::unique_ptr x10_inRange; - std::unique_ptr x14_outOfRange; +class CREIntTimesReal : public CRealElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CREConstantRange(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d, - std::unique_ptr&& e) - : x4_val(std::move(a)), x8_min(std::move(b)), xc_max(std::move(c)), - x10_inRange(std::move(d)), x14_outOfRange(std::move(e)) {} - - bool GetValue(int frame, float& valOut) const; + CREIntTimesReal(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, float& valOut) const; }; -class CREGetComponentRed : public CRealElement -{ - std::unique_ptr x4_a; +class CREConstantRange : public CRealElement { + std::unique_ptr x4_val; + std::unique_ptr x8_min; + std::unique_ptr xc_max; + std::unique_ptr x10_inRange; + std::unique_ptr x14_outOfRange; + public: - CREGetComponentRed(std::unique_ptr&& a) - : x4_a(std::move(a)) {} + CREConstantRange(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c, std::unique_ptr&& d, + std::unique_ptr&& e) + : x4_val(std::move(a)) + , x8_min(std::move(b)) + , xc_max(std::move(c)) + , x10_inRange(std::move(d)) + , x14_outOfRange(std::move(e)) {} - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREGetComponentGreen : public CRealElement -{ - std::unique_ptr x4_a; +class CREGetComponentRed : public CRealElement { + std::unique_ptr x4_a; + public: - CREGetComponentGreen(std::unique_ptr&& a) - : x4_a(std::move(a)) {} + CREGetComponentRed(std::unique_ptr&& a) : x4_a(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREGetComponentBlue : public CRealElement -{ - std::unique_ptr x4_a; +class CREGetComponentGreen : public CRealElement { + std::unique_ptr x4_a; + public: - CREGetComponentBlue(std::unique_ptr&& a) - : x4_a(std::move(a)) {} + CREGetComponentGreen(std::unique_ptr&& a) : x4_a(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -class CREGetComponentAlpha : public CRealElement -{ - std::unique_ptr x4_a; +class CREGetComponentBlue : public CRealElement { + std::unique_ptr x4_a; + public: - CREGetComponentAlpha(std::unique_ptr&& a) - : x4_a(std::move(a)) {} + CREGetComponentBlue(std::unique_ptr&& a) : x4_a(std::move(a)) {} - bool GetValue(int frame, float& valOut) const; + bool GetValue(int frame, float& valOut) const; }; -} +class CREGetComponentAlpha : public CRealElement { + std::unique_ptr x4_a; + +public: + CREGetComponentAlpha(std::unique_ptr&& a) : x4_a(std::move(a)) {} + + bool GetValue(int frame, float& valOut) const; +}; +} // namespace urde diff --git a/Runtime/Particle/CSpawnSystemKeyframeData.cpp b/Runtime/Particle/CSpawnSystemKeyframeData.cpp index 05f1fae36..992259751 100644 --- a/Runtime/Particle/CSpawnSystemKeyframeData.cpp +++ b/Runtime/Particle/CSpawnSystemKeyframeData.cpp @@ -5,61 +5,54 @@ #include "Graphics/CModel.hpp" #include "CSimplePool.hpp" -namespace urde -{ +namespace urde { -CSpawnSystemKeyframeData::CSpawnSystemKeyframeData(CInputStream& in) -{ - x0 = in.readUint32Big(); - x4 = in.readUint32Big(); - x8_endFrame = in.readUint32Big(); - xc = in.readUint32Big(); +CSpawnSystemKeyframeData::CSpawnSystemKeyframeData(CInputStream& in) { + x0 = in.readUint32Big(); + x4 = in.readUint32Big(); + x8_endFrame = in.readUint32Big(); + xc = in.readUint32Big(); - u32 count = in.readUint32Big(); - x10_spawns.reserve(count); - for (u32 i=0 ; i()); - std::vector& v2 = x10_spawns.back().second; - u32 v2c = in.readUint32Big(); - v2.reserve(v2c); - for (u32 j=0 ; j()); + std::vector& v2 = x10_spawns.back().second; + u32 v2c = in.readUint32Big(); + v2.reserve(v2c); + for (u32 j = 0; j < v2c; ++j) + v2.emplace_back(in); + } } -CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo::CSpawnSystemKeyframeInfo(CInputStream& in) -{ - x0_id = in.readUint32Big(); - x4 = in.readUint32Big(); - x8 = in.readUint32Big(); - xc = in.readUint32Big(); +CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo::CSpawnSystemKeyframeInfo(CInputStream& in) { + x0_id = in.readUint32Big(); + x4 = in.readUint32Big(); + x8 = in.readUint32Big(); + xc = in.readUint32Big(); } -void CSpawnSystemKeyframeData::LoadAllSpawnedSystemTokens(CSimplePool* pool) -{ - for (auto& spawn : x10_spawns) - for (CSpawnSystemKeyframeInfo& elem : spawn.second) - elem.LoadToken(pool); +void CSpawnSystemKeyframeData::LoadAllSpawnedSystemTokens(CSimplePool* pool) { + for (auto& spawn : x10_spawns) + for (CSpawnSystemKeyframeInfo& elem : spawn.second) + elem.LoadToken(pool); } -void CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo::LoadToken(CSimplePool* pool) -{ - x10_token = std::move(pool->GetObj({FOURCC('PART'), x0_id})); - x18_found = true; +void CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo::LoadToken(CSimplePool* pool) { + x10_token = std::move(pool->GetObj({FOURCC('PART'), x0_id})); + x18_found = true; } std::vector& -CSpawnSystemKeyframeData::GetSpawnedSystemsAtFrame(u32 frame) -{ - static std::vector emptyReturn; - if (frame >= x8_endFrame) - return emptyReturn; - for (auto& spawn : x10_spawns) - if (spawn.first == frame) - return spawn.second; +CSpawnSystemKeyframeData::GetSpawnedSystemsAtFrame(u32 frame) { + static std::vector emptyReturn; + if (frame >= x8_endFrame) return emptyReturn; + for (auto& spawn : x10_spawns) + if (spawn.first == frame) + return spawn.second; + return emptyReturn; } -} +} // namespace urde diff --git a/Runtime/Particle/CSpawnSystemKeyframeData.hpp b/Runtime/Particle/CSpawnSystemKeyframeData.hpp index da8e34130..af6f7d22f 100644 --- a/Runtime/Particle/CSpawnSystemKeyframeData.hpp +++ b/Runtime/Particle/CSpawnSystemKeyframeData.hpp @@ -3,39 +3,38 @@ #include "IOStreams.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class CSimplePool; class CGenDescription; -class CSpawnSystemKeyframeData -{ +class CSpawnSystemKeyframeData { public: - class CSpawnSystemKeyframeInfo - { - friend class CSpawnSystemKeyframeData; - u32 x0_id; - u32 x4; - u32 x8; - u32 xc; - TLockedToken x10_token; - bool x18_found = false; - void LoadToken(CSimplePool* pool); - public: - CSpawnSystemKeyframeInfo(CInputStream& in); - TLockedToken& GetToken() {return x10_token;} - }; -private: - u32 x0; + class CSpawnSystemKeyframeInfo { + friend class CSpawnSystemKeyframeData; + u32 x0_id; u32 x4; - u32 x8_endFrame; + u32 x8; u32 xc; - std::vector>> x10_spawns; + TLockedToken x10_token; + bool x18_found = false; + void LoadToken(CSimplePool* pool); + + public: + CSpawnSystemKeyframeInfo(CInputStream& in); + TLockedToken& GetToken() { return x10_token; } + }; + +private: + u32 x0; + u32 x4; + u32 x8_endFrame; + u32 xc; + std::vector>> x10_spawns; + public: - CSpawnSystemKeyframeData(CInputStream& in); - void LoadAllSpawnedSystemTokens(CSimplePool* pool); - std::vector& GetSpawnedSystemsAtFrame(u32 frame); + CSpawnSystemKeyframeData(CInputStream& in); + void LoadAllSpawnedSystemTokens(CSimplePool* pool); + std::vector& GetSpawnedSystemsAtFrame(u32 frame); }; -} - +} // namespace urde diff --git a/Runtime/Particle/CSwooshDescription.hpp b/Runtime/Particle/CSwooshDescription.hpp index adef52387..1d4f86070 100644 --- a/Runtime/Particle/CSwooshDescription.hpp +++ b/Runtime/Particle/CSwooshDescription.hpp @@ -8,43 +8,43 @@ #include "CColorElement.hpp" #include "CUVElement.hpp" -namespace urde -{ -class CSwooshDescription -{ +namespace urde { +class CSwooshDescription { public: - std::unique_ptr x0_PSLT; - std::unique_ptr x4_TIME; - std::unique_ptr x8_LRAD; - std::unique_ptr xc_RRAD; - std::unique_ptr x10_LENG; - std::unique_ptr x14_COLR; - std::unique_ptr x18_SIDE; - std::unique_ptr x1c_IROT; - std::unique_ptr x20_ROTM; - std::unique_ptr x24_POFS; - std::unique_ptr x28_IVEL; - std::unique_ptr x2c_NPOS; - std::unique_ptr x30_VELM; - std::unique_ptr x34_VLM2; - std::unique_ptr x38_SPLN; - std::unique_ptr x3c_TEXR; - std::unique_ptr x40_TSPN; - union - { - struct - { - bool x44_24_LLRD : 1; bool x44_25_CROS : 1; bool x44_26_VLS1 : 1; bool x44_27_VLS2 : 1; - bool x44_28_SROT : 1; bool x44_29_WIRE : 1; bool x44_30_TEXW : 1; bool x44_31_AALP : 1; - bool x45_24_ZBUF : 1; bool x45_25_ORNT : 1; bool x45_26_CRND : 1; - }; - u16 dummy = 0; + std::unique_ptr x0_PSLT; + std::unique_ptr x4_TIME; + std::unique_ptr x8_LRAD; + std::unique_ptr xc_RRAD; + std::unique_ptr x10_LENG; + std::unique_ptr x14_COLR; + std::unique_ptr x18_SIDE; + std::unique_ptr x1c_IROT; + std::unique_ptr x20_ROTM; + std::unique_ptr x24_POFS; + std::unique_ptr x28_IVEL; + std::unique_ptr x2c_NPOS; + std::unique_ptr x30_VELM; + std::unique_ptr x34_VLM2; + std::unique_ptr x38_SPLN; + std::unique_ptr x3c_TEXR; + std::unique_ptr x40_TSPN; + union { + struct { + bool x44_24_LLRD : 1; + bool x44_25_CROS : 1; + bool x44_26_VLS1 : 1; + bool x44_27_VLS2 : 1; + bool x44_28_SROT : 1; + bool x44_29_WIRE : 1; + bool x44_30_TEXW : 1; + bool x44_31_AALP : 1; + bool x45_24_ZBUF : 1; + bool x45_25_ORNT : 1; + bool x45_26_CRND : 1; }; + u16 dummy = 0; + }; - CSwooshDescription() - { - x44_25_CROS = true; - } + CSwooshDescription() { x44_25_CROS = true; } }; -} - +} // namespace urde diff --git a/Runtime/Particle/CUVElement.cpp b/Runtime/Particle/CUVElement.cpp index 8e2071fdb..0d2b6114c 100644 --- a/Runtime/Particle/CUVElement.cpp +++ b/Runtime/Particle/CUVElement.cpp @@ -2,61 +2,53 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#UV_Elements */ -namespace urde -{ +namespace urde { CUVEAnimTexture::CUVEAnimTexture(TToken&& tex, std::unique_ptr&& tileW, std::unique_ptr&& tileH, std::unique_ptr&& strideW, std::unique_ptr&& strideH, std::unique_ptr&& cycleFrames, bool loop) -: x4_tex(std::move(tex)), x24_loop(loop), x28_cycleFrames(std::move(cycleFrames)) -{ - tileW->GetValue(0, x10_tileW); - tileH->GetValue(0, x14_tileH); - strideW->GetValue(0, x18_strideW); - strideH->GetValue(0, x1c_strideH); +: x4_tex(std::move(tex)), x24_loop(loop), x28_cycleFrames(std::move(cycleFrames)) { + tileW->GetValue(0, x10_tileW); + tileH->GetValue(0, x14_tileH); + strideW->GetValue(0, x18_strideW); + strideH->GetValue(0, x1c_strideH); - int width = x4_tex.GetObj()->GetWidth(); - int height = x4_tex.GetObj()->GetHeight(); - float widthF = width; - float heightF = height; - int xTiles = std::max(1, width / x18_strideW); - int yTiles = std::max(1, height / x1c_strideH); - x20_tiles = xTiles * yTiles; - x2c_uvElems.reserve(x20_tiles); - for (int y=yTiles-1 ; y>=0 ; --y) - { - for (int x=0 ; xGetWidth(); + int height = x4_tex.GetObj()->GetHeight(); + float widthF = width; + float heightF = height; + int xTiles = std::max(1, width / x18_strideW); + int yTiles = std::max(1, height / x1c_strideH); + x20_tiles = xTiles * yTiles; + x2c_uvElems.reserve(x20_tiles); + for (int y = yTiles - 1; y >= 0; --y) { + for (int x = 0; x < xTiles; ++x) { + int px = x18_strideW * x; + int px2 = px + x10_tileW; + int py = x1c_strideH * y; + int py2 = py + x14_tileH; + x2c_uvElems.push_back({px / widthF, py / heightF, px2 / widthF, py2 / heightF}); } + } } -void CUVEAnimTexture::GetValueUV(int frame, SUVElementSet& valOut) const -{ - int cv; - x28_cycleFrames->GetValue(frame, cv); - float cvf = cv / float(x20_tiles); - cvf = frame / cvf; +void CUVEAnimTexture::GetValueUV(int frame, SUVElementSet& valOut) const { + int cv; + x28_cycleFrames->GetValue(frame, cv); + float cvf = cv / float(x20_tiles); + cvf = frame / cvf; - int tile = cvf; - if (x24_loop) - { - if (cvf >= x20_tiles) - tile = int(cvf) % x20_tiles; - } - else - { - if (cvf >= x20_tiles) - tile = x20_tiles - 1; - } + int tile = cvf; + if (x24_loop) { + if (cvf >= x20_tiles) + tile = int(cvf) % x20_tiles; + } else { + if (cvf >= x20_tiles) + tile = x20_tiles - 1; + } - valOut = x2c_uvElems[tile]; + valOut = x2c_uvElems[tile]; } -} +} // namespace urde diff --git a/Runtime/Particle/CUVElement.hpp b/Runtime/Particle/CUVElement.hpp index 0920dd363..099fe4e99 100644 --- a/Runtime/Particle/CUVElement.hpp +++ b/Runtime/Particle/CUVElement.hpp @@ -6,65 +6,48 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#UV_Elements */ -namespace urde -{ +namespace urde { class CToken; -struct SUVElementSet -{ - float xMin, yMin, xMax, yMax; +struct SUVElementSet { + float xMin, yMin, xMax, yMax; }; -class CUVElement : public IElement -{ +class CUVElement : public IElement { public: - virtual TLockedToken GetValueTexture(int frame) const=0; - virtual void GetValueUV(int frame, SUVElementSet& valOut) const=0; - virtual bool HasConstantTexture() const=0; - virtual bool HasConstantUV() const=0; + virtual TLockedToken GetValueTexture(int frame) const = 0; + virtual void GetValueUV(int frame, SUVElementSet& valOut) const = 0; + virtual bool HasConstantTexture() const = 0; + virtual bool HasConstantUV() const = 0; }; -struct CUVEConstant : public CUVElement -{ - TLockedToken x4_tex; +struct CUVEConstant : public CUVElement { + TLockedToken x4_tex; + public: - CUVEConstant(TToken&& tex) - : x4_tex(std::move(tex)) - { - - } - TLockedToken GetValueTexture(int frame) const - { - return TLockedToken(x4_tex); - } - void GetValueUV(int frame, SUVElementSet& valOut) const - { - valOut = {0.f, 0.f, 1.f, 1.f}; - } - bool HasConstantTexture() const {return true;} - bool HasConstantUV() const {return true;} + CUVEConstant(TToken&& tex) : x4_tex(std::move(tex)) {} + TLockedToken GetValueTexture(int frame) const { return TLockedToken(x4_tex); } + void GetValueUV(int frame, SUVElementSet& valOut) const { valOut = {0.f, 0.f, 1.f, 1.f}; } + bool HasConstantTexture() const { return true; } + bool HasConstantUV() const { return true; } }; -struct CUVEAnimTexture : public CUVElement -{ - TLockedToken x4_tex; - int x10_tileW, x14_tileH, x18_strideW, x1c_strideH; - int x20_tiles; - bool x24_loop; - std::unique_ptr x28_cycleFrames; - std::vector x2c_uvElems; +struct CUVEAnimTexture : public CUVElement { + TLockedToken x4_tex; + int x10_tileW, x14_tileH, x18_strideW, x1c_strideH; + int x20_tiles; + bool x24_loop; + std::unique_ptr x28_cycleFrames; + std::vector x2c_uvElems; + public: - CUVEAnimTexture(TToken&& tex, std::unique_ptr&& tileW, std::unique_ptr&& tileH, - std::unique_ptr&& strideW, std::unique_ptr&& strideH, - std::unique_ptr&& cycleFrames, bool loop); - TLockedToken GetValueTexture(int frame) const - { - return TLockedToken(x4_tex); - } - void GetValueUV(int frame, SUVElementSet& valOut) const; - bool HasConstantTexture() const {return true;} - bool HasConstantUV() const {return false;} + CUVEAnimTexture(TToken&& tex, std::unique_ptr&& tileW, std::unique_ptr&& tileH, + std::unique_ptr&& strideW, std::unique_ptr&& strideH, + std::unique_ptr&& cycleFrames, bool loop); + TLockedToken GetValueTexture(int frame) const { return TLockedToken(x4_tex); } + void GetValueUV(int frame, SUVElementSet& valOut) const; + bool HasConstantTexture() const { return true; } + bool HasConstantUV() const { return false; } }; -} - +} // namespace urde diff --git a/Runtime/Particle/CVectorElement.cpp b/Runtime/Particle/CVectorElement.cpp index 2a6388a5b..a547749f4 100644 --- a/Runtime/Particle/CVectorElement.cpp +++ b/Runtime/Particle/CVectorElement.cpp @@ -7,324 +7,291 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Vector_Elements */ -namespace urde -{ +namespace urde { -CVEKeyframeEmitter::CVEKeyframeEmitter(CInputStream& in) -{ - x4_percent = in.readUint32Big(); - x8_unk1 = in.readUint32Big(); - xc_loop = in.readBool(); - xd_unk2 = in.readBool(); - x10_loopEnd = in.readUint32Big(); - x14_loopStart = in.readUint32Big(); +CVEKeyframeEmitter::CVEKeyframeEmitter(CInputStream& in) { + x4_percent = in.readUint32Big(); + x8_unk1 = in.readUint32Big(); + xc_loop = in.readBool(); + xd_unk2 = in.readBool(); + x10_loopEnd = in.readUint32Big(); + x14_loopStart = in.readUint32Big(); - u32 count = in.readUint32Big(); - x18_keys.reserve(count); - for (u32 i=0 ; i= x10_loopEnd) - { - int v1 = emitterTime - x14_loopStart; - int v2 = x10_loopEnd - x14_loopStart; - calcKey = v1 % v2; - calcKey += x14_loopStart; - } - } - else - { - int v1 = x10_loopEnd - 1; - if (v1 < emitterTime) - calcKey = v1; - } - valOut = x18_keys[calcKey]; +bool CVEKeyframeEmitter::GetValue(int frame, zeus::CVector3f& valOut) const { + if (!x4_percent) { + int emitterTime = CParticleGlobals::g_EmitterTime; + int calcKey = emitterTime; + if (xc_loop) { + if (emitterTime >= x10_loopEnd) { + int v1 = emitterTime - x14_loopStart; + int v2 = x10_loopEnd - x14_loopStart; + calcKey = v1 % v2; + calcKey += x14_loopStart; + } + } else { + int v1 = x10_loopEnd - 1; + if (v1 < emitterTime) + calcKey = v1; } + valOut = x18_keys[calcKey]; + } else { + int ltPerc = CParticleGlobals::g_ParticleLifetimePercentage; + float ltPercRem = CParticleGlobals::g_ParticleLifetimePercentageRemainder; + if (ltPerc == 100) + valOut = x18_keys[100]; else - { - int ltPerc = CParticleGlobals::g_ParticleLifetimePercentage; - float ltPercRem = CParticleGlobals::g_ParticleLifetimePercentageRemainder; - if (ltPerc == 100) - valOut = x18_keys[100]; - else - valOut = ltPercRem * x18_keys[ltPerc+1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; - } - return false; + valOut = ltPercRem * x18_keys[ltPerc + 1] + (1.0f - ltPercRem) * x18_keys[ltPerc]; + } + return false; } CVECone::CVECone(std::unique_ptr&& a, std::unique_ptr&& b) -: x4_direction(std::move(a)), x8_magnitude(std::move(b)) -{ - zeus::CVector3f av; - x4_direction->GetValue(0, av); - zeus::CVector3f avNorm = av.normalized(); - if (avNorm.x() > 0.8f) - xc_xVec = av.cross(zeus::CVector3f(0.f, 1.f, 0.f)); - else - xc_xVec = av.cross(zeus::CVector3f(1.f, 0.f, 0.f)); - x18_yVec = avNorm.cross(xc_xVec); +: x4_direction(std::move(a)), x8_magnitude(std::move(b)) { + zeus::CVector3f av; + x4_direction->GetValue(0, av); + zeus::CVector3f avNorm = av.normalized(); + if (avNorm.x() > 0.8f) + xc_xVec = av.cross(zeus::CVector3f(0.f, 1.f, 0.f)); + else + xc_xVec = av.cross(zeus::CVector3f(1.f, 0.f, 0.f)); + x18_yVec = avNorm.cross(xc_xVec); } -bool CVECone::GetValue(int frame, zeus::CVector3f& valOut) const -{ - float b; - x8_magnitude->GetValue(frame, b); - zeus::CVector3f dir; - x4_direction->GetValue(frame, dir); - float b2 = std::min(1.f, b); +bool CVECone::GetValue(int frame, zeus::CVector3f& valOut) const { + float b; + x8_magnitude->GetValue(frame, b); + zeus::CVector3f dir; + x4_direction->GetValue(frame, dir); + float b2 = std::min(1.f, b); - float randX, randY; - do - { - float rand1 = CRandom16::GetRandomNumber()->Float() - 0.5f; - randX = 2.f * b2 * rand1; - float rand2 = CRandom16::GetRandomNumber()->Float() - 0.5f; - randY = 2.f * b2 * rand2; - } while (randX * randX + randY * randY > 1.f); + float randX, randY; + do { + float rand1 = CRandom16::GetRandomNumber()->Float() - 0.5f; + randX = 2.f * b2 * rand1; + float rand2 = CRandom16::GetRandomNumber()->Float() - 0.5f; + randY = 2.f * b2 * rand2; + } while (randX * randX + randY * randY > 1.f); - valOut = xc_xVec * randX + x18_yVec * randY + dir; - return false; + valOut = xc_xVec * randX + x18_yVec * randY + dir; + return false; } -bool CVETimeChain::GetValue(int frame, zeus::CVector3f& valOut) const -{ - int v; - xc_swFrame->GetValue(frame, v); - if (frame >= v) - return x8_b->GetValue(frame, valOut); - else - return x4_a->GetValue(frame, valOut); +bool CVETimeChain::GetValue(int frame, zeus::CVector3f& valOut) const { + int v; + xc_swFrame->GetValue(frame, v); + if (frame >= v) + return x8_b->GetValue(frame, valOut); + else + return x4_a->GetValue(frame, valOut); } -bool CVEAngleCone::GetValue(int frame, zeus::CVector3f& valOut) const -{ - float xc, yc, xr, yr; - x4_angleXConstant->GetValue(frame, xc); - x8_angleYConstant->GetValue(frame, yc); - xc_angleXRange->GetValue(frame, xr); - x10_angleYRange->GetValue(frame, yr); +bool CVEAngleCone::GetValue(int frame, zeus::CVector3f& valOut) const { + float xc, yc, xr, yr; + x4_angleXConstant->GetValue(frame, xc); + x8_angleYConstant->GetValue(frame, yc); + xc_angleXRange->GetValue(frame, xr); + x10_angleYRange->GetValue(frame, yr); - float xtmp = CRandom16::GetRandomNumber()->Float() * xr; - float xang = zeus::degToRad(0.5f * xr - xtmp + xc); + float xtmp = CRandom16::GetRandomNumber()->Float() * xr; + float xang = zeus::degToRad(0.5f * xr - xtmp + xc); - float ytmp = CRandom16::GetRandomNumber()->Float() * yr; - float yang = zeus::degToRad(0.5f * yr - ytmp + yc); + float ytmp = CRandom16::GetRandomNumber()->Float() * yr; + float yang = zeus::degToRad(0.5f * yr - ytmp + yc); - float mag; - x14_magnitude->GetValue(frame, mag); + float mag; + x14_magnitude->GetValue(frame, mag); - /* This takes a +Z vector and rotates it around X and Y axis (like a rotation matrix would) */ - valOut = zeus::CVector3f(std::cos(xang) * -std::sin(yang), std::sin(xang), std::cos(xang) * std::cos(yang)) * zeus::CVector3f(mag); - return false; + /* This takes a +Z vector and rotates it around X and Y axis (like a rotation matrix would) */ + valOut = zeus::CVector3f(std::cos(xang) * -std::sin(yang), std::sin(xang), std::cos(xang) * std::cos(yang)) * + zeus::CVector3f(mag); + return false; } -bool CVEAdd::GetValue(int frame, zeus::CVector3f& valOut) const -{ - zeus::CVector3f a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = a + b; - return false; +bool CVEAdd::GetValue(int frame, zeus::CVector3f& valOut) const { + zeus::CVector3f a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a + b; + return false; } CVECircleCluster::CVECircleCluster(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, std::unique_ptr&& d) -: x4_a(std::move(a)), x24_magnitude(std::move(d)) -{ - int cv; - c->GetValue(0, cv); - x20_deltaAngle = zeus::degToRad(360.f / float(cv)); +: x4_a(std::move(a)), x24_magnitude(std::move(d)) { + int cv; + c->GetValue(0, cv); + x20_deltaAngle = zeus::degToRad(360.f / float(cv)); - zeus::CVector3f bv; - b->GetValue(0, bv); - bv.normalize(); - if (bv[0] > 0.8f) - x8_xVec = bv.cross(zeus::CVector3f(0.f, 1.f, 0.f)); - else - x8_xVec = bv.cross(zeus::CVector3f(1.f, 0.f, 0.f)); - x14_yVec = bv.cross(x8_xVec); + zeus::CVector3f bv; + b->GetValue(0, bv); + bv.normalize(); + if (bv[0] > 0.8f) + x8_xVec = bv.cross(zeus::CVector3f(0.f, 1.f, 0.f)); + else + x8_xVec = bv.cross(zeus::CVector3f(1.f, 0.f, 0.f)); + x14_yVec = bv.cross(x8_xVec); } -bool CVECircleCluster::GetValue(int frame, zeus::CVector3f& valOut) const -{ - zeus::CVector3f av; - x4_a->GetValue(frame, av); +bool CVECircleCluster::GetValue(int frame, zeus::CVector3f& valOut) const { + zeus::CVector3f av; + x4_a->GetValue(frame, av); - float curAngle = frame * x20_deltaAngle; - zeus::CVector3f x = x8_xVec * std::cos(curAngle); - zeus::CVector3f y = x14_yVec * std::sin(curAngle); - zeus::CVector3f tv = x + y + av; + float curAngle = frame * x20_deltaAngle; + zeus::CVector3f x = x8_xVec * std::cos(curAngle); + zeus::CVector3f y = x14_yVec * std::sin(curAngle); + zeus::CVector3f tv = x + y + av; - float dv; - x24_magnitude->GetValue(frame, dv); + float dv; + x24_magnitude->GetValue(frame, dv); - zeus::CVector3f magVec(dv * tv.magnitude()); - zeus::CVector3f rv = magVec * zeus::CVector3f(CRandom16::GetRandomNumber()->Float(), - CRandom16::GetRandomNumber()->Float(), - CRandom16::GetRandomNumber()->Float()); + zeus::CVector3f magVec(dv * tv.magnitude()); + zeus::CVector3f rv = + magVec * zeus::CVector3f(CRandom16::GetRandomNumber()->Float(), CRandom16::GetRandomNumber()->Float(), + CRandom16::GetRandomNumber()->Float()); - valOut = tv + rv; - return false; + valOut = tv + rv; + return false; } -bool CVEConstant::GetValue(int frame, zeus::CVector3f& valOut) const -{ - float a, b, c; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - xc_c->GetValue(frame, c); - valOut = zeus::CVector3f(a, b, c); - return false; +bool CVEConstant::GetValue(int frame, zeus::CVector3f& valOut) const { + float a, b, c; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + xc_c->GetValue(frame, c); + valOut = zeus::CVector3f(a, b, c); + return false; } -bool CVEFastConstant::GetValue(int frame, zeus::CVector3f& valOut) const -{ - valOut = x4_val; - return false; +bool CVEFastConstant::GetValue(int frame, zeus::CVector3f& valOut) const { + valOut = x4_val; + return false; } CVECircle::CVECircle(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, std::unique_ptr&& d, std::unique_ptr&& e) -: x4_direction(std::move(a)), x20_angleConstant(std::move(c)), - x24_angleLinear(std::move(d)), x28_radius(std::move(e)) -{ - zeus::CVector3f bv; - b->GetValue(0, bv); - bv.normalize(); - if (bv[0] > 0.8f) - x8_xVec = bv.cross(zeus::CVector3f(0.f, 1.f, 0.f)); +: x4_direction(std::move(a)), x20_angleConstant(std::move(c)), x24_angleLinear(std::move(d)), x28_radius(std::move(e)) { + zeus::CVector3f bv; + b->GetValue(0, bv); + bv.normalize(); + if (bv[0] > 0.8f) + x8_xVec = bv.cross(zeus::CVector3f(0.f, 1.f, 0.f)); + else + x8_xVec = bv.cross(zeus::CVector3f(1.f, 0.f, 0.f)); + x14_yVec = bv.cross(x8_xVec); +} + +bool CVECircle::GetValue(int frame, zeus::CVector3f& valOut) const { + float c, d, e; + x20_angleConstant->GetValue(frame, c); + x24_angleLinear->GetValue(frame, d); + x28_radius->GetValue(frame, e); + + float curAngle = zeus::degToRad(d * frame + c); + + zeus::CVector3f av; + x4_direction->GetValue(frame, av); + + zeus::CVector3f x = x8_xVec * e * std::cos(curAngle); + zeus::CVector3f y = x14_yVec * e * std::sin(curAngle); + + valOut = x + y + av; + return false; +} + +bool CVEMultiply::GetValue(int frame, zeus::CVector3f& valOut) const { + zeus::CVector3f a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a * b; + return false; +} + +bool CVERealToVector::GetValue(int frame, zeus::CVector3f& valOut) const { + float a; + x4_a->GetValue(frame, a); + valOut = zeus::CVector3f(a); + return false; +} + +bool CVEPulse::GetValue(int frame, zeus::CVector3f& valOut) const { + int a, b; + x4_aDuration->GetValue(frame, a); + x8_bDuration->GetValue(frame, b); + int cv = std::max(1, a + b + 1); + + if (b >= 1) { + int cv2 = frame % cv; + if (cv2 >= a) + x10_bVal->GetValue(frame, valOut); else - x8_xVec = bv.cross(zeus::CVector3f(1.f, 0.f, 0.f)); - x14_yVec = bv.cross(x8_xVec); + xc_aVal->GetValue(frame, valOut); + } else + xc_aVal->GetValue(frame, valOut); + + return false; } -bool CVECircle::GetValue(int frame, zeus::CVector3f& valOut) const -{ - float c, d, e; - x20_angleConstant->GetValue(frame, c); - x24_angleLinear->GetValue(frame, d); - x28_radius->GetValue(frame, e); - - float curAngle = zeus::degToRad(d * frame + c); - - zeus::CVector3f av; - x4_direction->GetValue(frame, av); - - zeus::CVector3f x = x8_xVec * e * std::cos(curAngle); - zeus::CVector3f y = x14_yVec * e * std::sin(curAngle); - - valOut = x + y + av; - return false; +bool CVEParticleVelocity::GetValue(int /*frame*/, zeus::CVector3f& valOut) const { + valOut = CElementGen::g_currentParticle->x1c_vel; + return false; } -bool CVEMultiply::GetValue(int frame, zeus::CVector3f& valOut) const -{ - zeus::CVector3f a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = a * b; - return false; +bool CVEParticleColor::GetValue(int /*frame*/, zeus::CVector3f& valOut) const { + valOut = CElementGen::g_currentParticle->x10_prevPos; + return false; } -bool CVERealToVector::GetValue(int frame, zeus::CVector3f& valOut) const -{ - float a; - x4_a->GetValue(frame, a); - valOut = zeus::CVector3f(a); - return false; +bool CVEParticleLocation::GetValue(int /*frame*/, zeus::CVector3f& valOut) const { + valOut = CElementGen::g_currentParticle->x4_pos; + return false; } -bool CVEPulse::GetValue(int frame, zeus::CVector3f& valOut) const -{ - int a, b; - x4_aDuration->GetValue(frame, a); - x8_bDuration->GetValue(frame, b); - int cv = std::max(1, a + b + 1); - - if (b >= 1) - { - int cv2 = frame % cv; - if (cv2 >= a) - x10_bVal->GetValue(frame, valOut); - else - xc_aVal->GetValue(frame, valOut); - } - else - xc_aVal->GetValue(frame, valOut); - - return false; +bool CVEParticleSystemOrientationFront::GetValue(int /*frame*/, zeus::CVector3f& valOut) const { + zeus::CMatrix4f trans = + CParticleGlobals::g_currentParticleSystem->x4_system->GetOrientation().toMatrix4f().transposed(); + valOut.assign(trans.m[0].y(), trans.m[1].y(), trans.m[2].y()); + return false; } -bool CVEParticleVelocity::GetValue(int /*frame*/, zeus::CVector3f& valOut) const -{ - valOut = CElementGen::g_currentParticle->x1c_vel; - return false; +bool CVEParticleSystemOrientationUp::GetValue(int /*frame*/, zeus::CVector3f& valOut) const { + zeus::CMatrix4f trans = + CParticleGlobals::g_currentParticleSystem->x4_system->GetOrientation().toMatrix4f().transposed(); + valOut.assign(trans.m[0].z(), trans.m[1].z(), trans.m[2].z()); + return false; } -bool CVEParticleColor::GetValue(int /*frame*/, zeus::CVector3f& valOut) const -{ - valOut = CElementGen::g_currentParticle->x10_prevPos; - return false; +bool CVEParticleSystemOrientationRight::GetValue(int /*frame*/, zeus::CVector3f& valOut) const { + zeus::CMatrix4f trans = + CParticleGlobals::g_currentParticleSystem->x4_system->GetOrientation().toMatrix4f().transposed(); + valOut.assign(trans.m[0].x(), trans.m[1].x(), trans.m[2].x()); + return false; } -bool CVEParticleLocation::GetValue(int /*frame*/, zeus::CVector3f& valOut) const -{ - valOut = CElementGen::g_currentParticle->x4_pos; - return false; +bool CVEParticleSystemTranslation::GetValue(int /*frame*/, zeus::CVector3f& valOut) const { + valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetTranslation(); + return false; } -bool CVEParticleSystemOrientationFront::GetValue(int /*frame*/, zeus::CVector3f& valOut) const -{ - zeus::CMatrix4f trans = CParticleGlobals::g_currentParticleSystem->x4_system->GetOrientation().toMatrix4f().transposed(); - valOut.assign(trans.m[0].y(), trans.m[1].y(), trans.m[2].y()); - return false; +bool CVESubtract::GetValue(int frame, zeus::CVector3f& valOut) const { + zeus::CVector3f a, b; + x4_a->GetValue(frame, a); + x8_b->GetValue(frame, b); + valOut = a - b; + return false; } -bool CVEParticleSystemOrientationUp::GetValue(int /*frame*/, zeus::CVector3f& valOut) const -{ - zeus::CMatrix4f trans = CParticleGlobals::g_currentParticleSystem->x4_system->GetOrientation().toMatrix4f().transposed(); - valOut.assign(trans.m[0].z(), trans.m[1].z(), trans.m[2].z()); - return false; +bool CVEColorToVector::GetValue(int frame, zeus::CVector3f& valOut) const { + zeus::CColor val = {0.0f, 0.0f, 0.0f, 1.0f}; + x4_a->GetValue(frame, val); + valOut = zeus::CVector3f{val.mSimd}; + return false; } -bool CVEParticleSystemOrientationRight::GetValue(int /*frame*/, zeus::CVector3f& valOut) const -{ - zeus::CMatrix4f trans = CParticleGlobals::g_currentParticleSystem->x4_system->GetOrientation().toMatrix4f().transposed(); - valOut.assign(trans.m[0].x(), trans.m[1].x(), trans.m[2].x()); - return false; -} - -bool CVEParticleSystemTranslation::GetValue(int /*frame*/, zeus::CVector3f& valOut) const -{ - valOut = CParticleGlobals::g_currentParticleSystem->x4_system->GetTranslation(); - return false; -} - -bool CVESubtract::GetValue(int frame, zeus::CVector3f& valOut) const -{ - zeus::CVector3f a, b; - x4_a->GetValue(frame, a); - x8_b->GetValue(frame, b); - valOut = a - b; - return false; -} - -bool CVEColorToVector::GetValue(int frame, zeus::CVector3f &valOut) const -{ - zeus::CColor val = {0.0f, 0.0f, 0.0f, 1.0f}; - x4_a->GetValue(frame, val); - valOut = zeus::CVector3f{val.mSimd}; - return false; -} - -} +} // namespace urde diff --git a/Runtime/Particle/CVectorElement.hpp b/Runtime/Particle/CVectorElement.hpp index d1e19222b..434ace7c4 100644 --- a/Runtime/Particle/CVectorElement.hpp +++ b/Runtime/Particle/CVectorElement.hpp @@ -4,214 +4,203 @@ /* Documentation at: http://www.metroid2002.com/retromodding/wiki/Particle_Script#Vector_Elements */ -namespace urde -{ +namespace urde { + +class CVEKeyframeEmitter : public CVectorElement { + u32 x4_percent; + u32 x8_unk1; + bool xc_loop; + bool xd_unk2; + u32 x10_loopEnd; + u32 x14_loopStart; + std::vector x18_keys; -class CVEKeyframeEmitter : public CVectorElement -{ - u32 x4_percent; - u32 x8_unk1; - bool xc_loop; - bool xd_unk2; - u32 x10_loopEnd; - u32 x14_loopStart; - std::vector x18_keys; public: - CVEKeyframeEmitter(CInputStream& in); - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVEKeyframeEmitter(CInputStream& in); + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVECone : public CVectorElement -{ - std::unique_ptr x4_direction; - std::unique_ptr x8_magnitude; - zeus::CVector3f xc_xVec; - zeus::CVector3f x18_yVec; +class CVECone : public CVectorElement { + std::unique_ptr x4_direction; + std::unique_ptr x8_magnitude; + zeus::CVector3f xc_xVec; + zeus::CVector3f x18_yVec; + public: - CVECone(std::unique_ptr&& a, std::unique_ptr&& b); - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVECone(std::unique_ptr&& a, std::unique_ptr&& b); + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVETimeChain : public CVectorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_swFrame; +class CVETimeChain : public CVectorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_swFrame; + public: - CVETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVETimeChain(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c) + : x4_a(std::move(a)), x8_b(std::move(b)), xc_swFrame(std::move(c)) {} + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEAngleCone : public CVectorElement -{ - std::unique_ptr x4_angleXConstant; - std::unique_ptr x8_angleYConstant; - std::unique_ptr xc_angleXRange; - std::unique_ptr x10_angleYRange; - std::unique_ptr x14_magnitude; +class CVEAngleCone : public CVectorElement { + std::unique_ptr x4_angleXConstant; + std::unique_ptr x8_angleYConstant; + std::unique_ptr xc_angleXRange; + std::unique_ptr x10_angleYRange; + std::unique_ptr x14_magnitude; + public: - CVEAngleCone(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d, - std::unique_ptr&& e) - : x4_angleXConstant(std::move(a)), x8_angleYConstant(std::move(b)), - xc_angleXRange(std::move(c)), x10_angleYRange(std::move(d)), x14_magnitude(std::move(e)) {} - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVEAngleCone(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d, std::unique_ptr&& e) + : x4_angleXConstant(std::move(a)) + , x8_angleYConstant(std::move(b)) + , xc_angleXRange(std::move(c)) + , x10_angleYRange(std::move(d)) + , x14_magnitude(std::move(e)) {} + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEAdd : public CVectorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CVEAdd : public CVectorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CVEAdd(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVEAdd(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVECircleCluster : public CVectorElement -{ - std::unique_ptr x4_a; - zeus::CVector3f x8_xVec; - zeus::CVector3f x14_yVec; - float x20_deltaAngle; - std::unique_ptr x24_magnitude; +class CVECircleCluster : public CVectorElement { + std::unique_ptr x4_a; + zeus::CVector3f x8_xVec; + zeus::CVector3f x14_yVec; + float x20_deltaAngle; + std::unique_ptr x24_magnitude; + public: - CVECircleCluster(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d); - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVECircleCluster(std::unique_ptr&& a, std::unique_ptr&& b, + std::unique_ptr&& c, std::unique_ptr&& d); + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEConstant : public CVectorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; - std::unique_ptr xc_c; +class CVEConstant : public CVectorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + std::unique_ptr xc_c; + public: - CVEConstant(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) - : x4_a(std::move(a)), x8_b(std::move(b)), xc_c(std::move(c)) {} - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVEConstant(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c) + : x4_a(std::move(a)), x8_b(std::move(b)), xc_c(std::move(c)) {} + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEFastConstant : public CVectorElement -{ - zeus::CVector3f x4_val; +class CVEFastConstant : public CVectorElement { + zeus::CVector3f x4_val; + public: - CVEFastConstant(float a, float b, float c) : x4_val(a, b, c) {} - bool GetValue(int frame, zeus::CVector3f& valOut) const; - bool IsFastConstant() const {return true;} + CVEFastConstant(float a, float b, float c) : x4_val(a, b, c) {} + bool GetValue(int frame, zeus::CVector3f& valOut) const; + bool IsFastConstant() const { return true; } }; -class CVECircle : public CVectorElement -{ - std::unique_ptr x4_direction; - zeus::CVector3f x8_xVec; - zeus::CVector3f x14_yVec; - std::unique_ptr x20_angleConstant; - std::unique_ptr x24_angleLinear; - std::unique_ptr x28_radius; +class CVECircle : public CVectorElement { + std::unique_ptr x4_direction; + zeus::CVector3f x8_xVec; + zeus::CVector3f x14_yVec; + std::unique_ptr x20_angleConstant; + std::unique_ptr x24_angleLinear; + std::unique_ptr x28_radius; + public: - CVECircle(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d, - std::unique_ptr&& e); - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVECircle(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d, std::unique_ptr&& e); + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEMultiply : public CVectorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CVEMultiply : public CVectorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CVEMultiply(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) {} - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVEMultiply(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVERealToVector : public CVectorElement -{ - std::unique_ptr x4_a; +class CVERealToVector : public CVectorElement { + std::unique_ptr x4_a; + public: - CVERealToVector(std::unique_ptr&& a) - : x4_a(std::move(a)) {} - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVERealToVector(std::unique_ptr&& a) : x4_a(std::move(a)) {} + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEPulse : public CVectorElement -{ - std::unique_ptr x4_aDuration; - std::unique_ptr x8_bDuration; - std::unique_ptr xc_aVal; - std::unique_ptr x10_bVal; +class CVEPulse : public CVectorElement { + std::unique_ptr x4_aDuration; + std::unique_ptr x8_bDuration; + std::unique_ptr xc_aVal; + std::unique_ptr x10_bVal; + public: - CVEPulse(std::unique_ptr&& a, std::unique_ptr&& b, - std::unique_ptr&& c, std::unique_ptr&& d) - : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_aVal(std::move(c)), x10_bVal(std::move(d)) {} - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVEPulse(std::unique_ptr&& a, std::unique_ptr&& b, std::unique_ptr&& c, + std::unique_ptr&& d) + : x4_aDuration(std::move(a)), x8_bDuration(std::move(b)), xc_aVal(std::move(c)), x10_bVal(std::move(d)) {} + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEParticleVelocity : public CVectorElement -{ +class CVEParticleVelocity : public CVectorElement { public: - bool GetValue(int frame, zeus::CVector3f& valOut) const; + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEParticleColor : public CVectorElement -{ +class CVEParticleColor : public CVectorElement { public: - bool GetValue(int frame, zeus::CVector3f& valOut) const; + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEParticleLocation : public CVectorElement -{ +class CVEParticleLocation : public CVectorElement { public: - bool GetValue(int frame, zeus::CVector3f& valOut) const; + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEParticleSystemOrientationFront : public CVectorElement -{ +class CVEParticleSystemOrientationFront : public CVectorElement { public: - bool GetValue(int frame, zeus::CVector3f& valOut) const; + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEParticleSystemOrientationUp : public CVectorElement -{ +class CVEParticleSystemOrientationUp : public CVectorElement { public: - bool GetValue(int frame, zeus::CVector3f& valOut) const; + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEParticleSystemOrientationRight : public CVectorElement -{ +class CVEParticleSystemOrientationRight : public CVectorElement { public: - bool GetValue(int frame, zeus::CVector3f& valOut) const; + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEParticleSystemTranslation : public CVectorElement -{ +class CVEParticleSystemTranslation : public CVectorElement { public: - bool GetValue(int frame, zeus::CVector3f& valOut) const; + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVESubtract : public CVectorElement -{ - std::unique_ptr x4_a; - std::unique_ptr x8_b; +class CVESubtract : public CVectorElement { + std::unique_ptr x4_a; + std::unique_ptr x8_b; + public: - CVESubtract(std::unique_ptr&& a, std::unique_ptr&& b) - : x4_a(std::move(a)), x8_b(std::move(b)) - {} - bool GetValue(int frame, zeus::CVector3f& valOut) const; + CVESubtract(std::unique_ptr&& a, std::unique_ptr&& b) + : x4_a(std::move(a)), x8_b(std::move(b)) {} + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -class CVEColorToVector : public CVectorElement -{ - std::unique_ptr x4_a; -public: - CVEColorToVector(std::unique_ptr&& a) - : x4_a(std::move(a)) {} +class CVEColorToVector : public CVectorElement { + std::unique_ptr x4_a; - bool GetValue(int frame, zeus::CVector3f& valOut) const; +public: + CVEColorToVector(std::unique_ptr&& a) : x4_a(std::move(a)) {} + + bool GetValue(int frame, zeus::CVector3f& valOut) const; }; -} - +} // namespace urde diff --git a/Runtime/Particle/CWarp.hpp b/Runtime/Particle/CWarp.hpp index 5ec6f5070..92614a7a0 100644 --- a/Runtime/Particle/CWarp.hpp +++ b/Runtime/Particle/CWarp.hpp @@ -5,19 +5,16 @@ #include "RetroTypes.hpp" #include "CParticleGen.hpp" -namespace urde -{ +namespace urde { -class CWarp -{ +class CWarp { public: - virtual ~CWarp() = default; - virtual bool UpdateWarp()=0; - virtual void ModifyParticles(std::vector& particles)=0; - virtual void Activate(bool)=0; - virtual bool IsActivated()=0; - virtual FourCC Get4CharID()=0; + virtual ~CWarp() = default; + virtual bool UpdateWarp() = 0; + virtual void ModifyParticles(std::vector& particles) = 0; + virtual void Activate(bool) = 0; + virtual bool IsActivated() = 0; + virtual FourCC Get4CharID() = 0; }; -} - +} // namespace urde diff --git a/Runtime/Particle/CWeaponDescription.hpp b/Runtime/Particle/CWeaponDescription.hpp index 6a30bbe62..b3d591ac8 100644 --- a/Runtime/Particle/CWeaponDescription.hpp +++ b/Runtime/Particle/CWeaponDescription.hpp @@ -7,53 +7,49 @@ #include "CModVectorElement.hpp" #include "CColorElement.hpp" -namespace urde -{ +namespace urde { class CCollisionResponseData; -struct SCollisionResponseData -{ - TToken m_res; - bool m_found = false; - SCollisionResponseData() = default; - SCollisionResponseData(CToken&& tok, bool found) - : m_res(std::move(tok)), m_found(found) {} - operator bool() const { return m_found; } +struct SCollisionResponseData { + TToken m_res; + bool m_found = false; + SCollisionResponseData() = default; + SCollisionResponseData(CToken&& tok, bool found) : m_res(std::move(tok)), m_found(found) {} + operator bool() const { return m_found; } }; -class CWeaponDescription -{ +class CWeaponDescription { public: - std::unique_ptr x0_IORN; - std::unique_ptr x4_IVEC; - std::unique_ptr x8_PSOV; - std::unique_ptr xc_PSVM; - bool x10_VMD2; - std::unique_ptr x14_PSLT; - std::unique_ptr x18_PSCL; - std::unique_ptr x1c_PCOL; - std::unique_ptr x20_POFS; - std::unique_ptr x24_OFST; - bool x28_APSO; - bool x29_HOMG; - bool x2a_AP11; - bool x2b_AP21; - bool x2c_AS11; - bool x2d_AS12; - bool x2e_AS13; - std::unique_ptr x30_TRAT; - SChildGeneratorDesc x34_APSM; - SChildGeneratorDesc x44_APS2; - SSwooshGeneratorDesc x54_ASW1; - SSwooshGeneratorDesc x64_ASW2; - SSwooshGeneratorDesc x74_ASW3; - SParticleModel x84_OHEF; - SCollisionResponseData x94_COLR; - bool xa4_EWTR = true; - bool xa5_LWTR = true; - bool xa6_SWTR = true; - s32 xa8_PJFX = -1; - std::unique_ptr xac_RNGE; - std::unique_ptr xb0_FOFF; + std::unique_ptr x0_IORN; + std::unique_ptr x4_IVEC; + std::unique_ptr x8_PSOV; + std::unique_ptr xc_PSVM; + bool x10_VMD2; + std::unique_ptr x14_PSLT; + std::unique_ptr x18_PSCL; + std::unique_ptr x1c_PCOL; + std::unique_ptr x20_POFS; + std::unique_ptr x24_OFST; + bool x28_APSO; + bool x29_HOMG; + bool x2a_AP11; + bool x2b_AP21; + bool x2c_AS11; + bool x2d_AS12; + bool x2e_AS13; + std::unique_ptr x30_TRAT; + SChildGeneratorDesc x34_APSM; + SChildGeneratorDesc x44_APS2; + SSwooshGeneratorDesc x54_ASW1; + SSwooshGeneratorDesc x64_ASW2; + SSwooshGeneratorDesc x74_ASW3; + SParticleModel x84_OHEF; + SCollisionResponseData x94_COLR; + bool xa4_EWTR = true; + bool xa5_LWTR = true; + bool xa6_SWTR = true; + s32 xa8_PJFX = -1; + std::unique_ptr xac_RNGE; + std::unique_ptr xb0_FOFF; }; -} +} // namespace urde diff --git a/Runtime/Particle/IElement.hpp b/Runtime/Particle/IElement.hpp index 84f0cbc45..1fbb3d928 100644 --- a/Runtime/Particle/IElement.hpp +++ b/Runtime/Particle/IElement.hpp @@ -6,53 +6,44 @@ #include "zeus/CColor.hpp" #include "IOStreams.hpp" -namespace urde -{ +namespace urde { -class IElement -{ +class IElement { public: - virtual ~IElement() = default; + virtual ~IElement() = default; }; -class CRealElement : public IElement -{ +class CRealElement : public IElement { public: - virtual bool GetValue(int frame, float& valOut) const=0; - virtual bool IsConstant() const {return false;} + virtual bool GetValue(int frame, float& valOut) const = 0; + virtual bool IsConstant() const { return false; } }; -class CIntElement : public IElement -{ +class CIntElement : public IElement { public: - virtual bool GetValue(int frame, int& valOut) const=0; - virtual int GetMaxValue() const=0; + virtual bool GetValue(int frame, int& valOut) const = 0; + virtual int GetMaxValue() const = 0; }; -class CVectorElement : public IElement -{ +class CVectorElement : public IElement { public: - virtual bool GetValue(int frame, zeus::CVector3f& valOut) const=0; - virtual bool IsFastConstant() const {return false;} + virtual bool GetValue(int frame, zeus::CVector3f& valOut) const = 0; + virtual bool IsFastConstant() const { return false; } }; -class CModVectorElement : public IElement -{ +class CModVectorElement : public IElement { public: - virtual bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const=0; + virtual bool GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPos) const = 0; }; -class CColorElement : public IElement -{ +class CColorElement : public IElement { public: - virtual bool GetValue(int frame, zeus::CColor& colorOut) const=0; + virtual bool GetValue(int frame, zeus::CColor& colorOut) const = 0; }; -class CEmitterElement : public IElement -{ +class CEmitterElement : public IElement { public: - virtual bool GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const=0; + virtual bool GetValue(int frame, zeus::CVector3f& pPos, zeus::CVector3f& pVel) const = 0; }; -} - +} // namespace urde diff --git a/Runtime/RetroTypes.cpp b/Runtime/RetroTypes.cpp index d695c3890..ba1790397 100644 --- a/Runtime/RetroTypes.cpp +++ b/Runtime/RetroTypes.cpp @@ -2,38 +2,31 @@ #include "GameGlobalObjects.hpp" #include "IMain.hpp" -namespace urde -{ +namespace urde { logvisor::Module Log("urde::RetroTypes::CAssetId"); -CAssetId::CAssetId(CInputStream& in) -{ - if (g_Main) - { - if (g_Main->GetExpectedIdSize() == sizeof(u32)) - Assign(in.readUint32Big()); - else if (g_Main->GetExpectedIdSize() == sizeof(u64)) - Assign(in.readUint64Big()); - else - Log.report(logvisor::Fatal, "Unsupported id length %i", g_Main->GetExpectedIdSize()); - } +CAssetId::CAssetId(CInputStream& in) { + if (g_Main) { + if (g_Main->GetExpectedIdSize() == sizeof(u32)) + Assign(in.readUint32Big()); + else if (g_Main->GetExpectedIdSize() == sizeof(u64)) + Assign(in.readUint64Big()); else - Log.report(logvisor::Fatal, "Input constructor called before runtime Main entered!"); + Log.report(logvisor::Fatal, "Unsupported id length %i", g_Main->GetExpectedIdSize()); + } else + Log.report(logvisor::Fatal, "Input constructor called before runtime Main entered!"); } -void CAssetId::PutTo(COutputStream& out) -{ - if (g_Main) - { - if (g_Main->GetExpectedIdSize() == sizeof(u32)) - out.writeUint32Big(u32(id)); - else if (g_Main->GetExpectedIdSize() == sizeof(u64)) - out.writeUint64Big(id); - else - Log.report(logvisor::Fatal, "Unsupported id length %i", g_Main->GetExpectedIdSize()); - } +void CAssetId::PutTo(COutputStream& out) { + if (g_Main) { + if (g_Main->GetExpectedIdSize() == sizeof(u32)) + out.writeUint32Big(u32(id)); + else if (g_Main->GetExpectedIdSize() == sizeof(u64)) + out.writeUint64Big(id); else - Log.report(logvisor::Fatal, "PutTo called before runtime Main entered!"); + Log.report(logvisor::Fatal, "Unsupported id length %i", g_Main->GetExpectedIdSize()); + } else + Log.report(logvisor::Fatal, "PutTo called before runtime Main entered!"); } -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/RetroTypes.hpp b/Runtime/RetroTypes.hpp index e09d5d224..6ba1c1386 100644 --- a/Runtime/RetroTypes.hpp +++ b/Runtime/RetroTypes.hpp @@ -14,78 +14,72 @@ using namespace std::literals; -namespace urde -{ +namespace urde { using FourCC = hecl::FourCC; -class CAssetId -{ - u64 id = UINT64_MAX; +class CAssetId { + u64 id = UINT64_MAX; + public: - CAssetId() = default; - CAssetId(u64 v) { Assign(v); } - explicit CAssetId(CInputStream& in); - bool IsValid() const { return id != UINT64_MAX; } - u64 Value() const { return id; } - void Assign(u64 v) { id = (v == UINT32_MAX ? UINT64_MAX : (v == 0 ? UINT64_MAX : v)); } - void Reset() { id = UINT64_MAX; } - void PutTo(COutputStream& out); - bool operator==(const CAssetId& other) const { return id == other.id; } - bool operator!=(const CAssetId& other) const { return id != other.id; } - bool operator<(const CAssetId& other) const { return id < other.id; } + CAssetId() = default; + CAssetId(u64 v) { Assign(v); } + explicit CAssetId(CInputStream& in); + bool IsValid() const { return id != UINT64_MAX; } + u64 Value() const { return id; } + void Assign(u64 v) { id = (v == UINT32_MAX ? UINT64_MAX : (v == 0 ? UINT64_MAX : v)); } + void Reset() { id = UINT64_MAX; } + void PutTo(COutputStream& out); + bool operator==(const CAssetId& other) const { return id == other.id; } + bool operator!=(const CAssetId& other) const { return id != other.id; } + bool operator<(const CAssetId& other) const { return id < other.id; } }; //#define kInvalidAssetId CAssetId() -struct SObjectTag -{ - FourCC type; - CAssetId id; +struct SObjectTag { + FourCC type; + CAssetId id; - operator bool() const { return id.IsValid(); } - bool operator!=(const SObjectTag& other) const { return id != other.id; } - bool operator==(const SObjectTag& other) const { return id == other.id; } - bool operator<(const SObjectTag& other) const { return id < other.id; } - SObjectTag() = default; - SObjectTag(FourCC tp, CAssetId rid) : type(tp), id(rid) {} - SObjectTag(CInputStream& in) - { - in.readBytesToBuf(&type, 4); - id = CAssetId(in); - } - void readMLVL(CInputStream& in) - { - id = CAssetId(in); - in.readBytesToBuf(&type, 4); - } + operator bool() const { return id.IsValid(); } + bool operator!=(const SObjectTag& other) const { return id != other.id; } + bool operator==(const SObjectTag& other) const { return id == other.id; } + bool operator<(const SObjectTag& other) const { return id < other.id; } + SObjectTag() = default; + SObjectTag(FourCC tp, CAssetId rid) : type(tp), id(rid) {} + SObjectTag(CInputStream& in) { + in.readBytesToBuf(&type, 4); + id = CAssetId(in); + } + void readMLVL(CInputStream& in) { + id = CAssetId(in); + in.readBytesToBuf(&type, 4); + } }; -struct TEditorId -{ - TEditorId() = default; - TEditorId(u32 idin) : id(idin) {} - u32 id = u32(-1); - u8 LayerNum() const { return u8((id >> 26) & 0x3f); } - u16 AreaNum() const { return u16((id >> 16) & 0x3ff); } - u16 Id() const { return u16(id & 0xffff); } - bool operator<(const TEditorId& other) const { return (id & 0x3ffffff) < (other.id & 0x3ffffff); } - bool operator!=(const TEditorId& other) const { return (id & 0x3ffffff) != (other.id & 0x3ffffff); } - bool operator==(const TEditorId& other) const { return (id & 0x3ffffff) == (other.id & 0x3ffffff); } +struct TEditorId { + TEditorId() = default; + TEditorId(u32 idin) : id(idin) {} + u32 id = u32(-1); + u8 LayerNum() const { return u8((id >> 26) & 0x3f); } + u16 AreaNum() const { return u16((id >> 16) & 0x3ff); } + u16 Id() const { return u16(id & 0xffff); } + bool operator<(const TEditorId& other) const { return (id & 0x3ffffff) < (other.id & 0x3ffffff); } + bool operator!=(const TEditorId& other) const { return (id & 0x3ffffff) != (other.id & 0x3ffffff); } + bool operator==(const TEditorId& other) const { return (id & 0x3ffffff) == (other.id & 0x3ffffff); } }; #define kInvalidEditorId TEditorId() -struct TUniqueId -{ - TUniqueId() = default; - TUniqueId(u16 value, u16 version) : id(value | (version << 10)) {} - u16 id = u16(-1); - u16 Version() const { return u16((id >> 10) & 0x3f); } - u16 Value() const { return u16(id & 0x3ff); } - bool operator<(const TUniqueId& other) const { return (id < other.id); } - bool operator!=(const TUniqueId& other) const { return (id != other.id); } - bool operator==(const TUniqueId& other) const { return (id == other.id); } +struct TUniqueId { + TUniqueId() = default; + TUniqueId(u16 value, u16 version) : id(value | (version << 10)) {} + u16 id = u16(-1); + u16 Version() const { return u16((id >> 10) & 0x3f); } + u16 Value() const { return u16(id & 0x3ff); } + bool operator<(const TUniqueId& other) const { return (id < other.id); } + bool operator!=(const TUniqueId& other) const { return (id != other.id); } + bool operator==(const TUniqueId& other) const { return (id == other.id); } }; #define kInvalidUniqueId TUniqueId() @@ -115,70 +109,59 @@ public: }; #endif -template -T GetAverage(const T* v, s32 count) -{ - T r = v[0]; - for (s32 i = 1; i < count; ++i) - r += v[i]; +template +T GetAverage(const T* v, s32 count) { + T r = v[0]; + for (s32 i = 1; i < count; ++i) + r += v[i]; - return r / count; + return r / count; } -template -class TReservedAverage : rstl::reserved_vector -{ +template +class TReservedAverage : rstl::reserved_vector { public: - TReservedAverage() = default; + TReservedAverage() = default; - TReservedAverage(const T& t) { rstl::reserved_vector::resize(N, t); } + TReservedAverage(const T& t) { rstl::reserved_vector::resize(N, t); } - void AddValue(const T& t) - { - if (this->size() < N) - { - this->insert(this->begin(), t); - } else - { - this->pop_back(); - this->insert(this->begin(), t); - } + void AddValue(const T& t) { + if (this->size() < N) { + this->insert(this->begin(), t); + } else { + this->pop_back(); + this->insert(this->begin(), t); } + } - std::experimental::optional GetAverage() const - { - if (this->empty()) - return {}; + std::experimental::optional GetAverage() const { + if (this->empty()) + return {}; - return {urde::GetAverage(this->data(), this->size())}; - } + return {urde::GetAverage(this->data(), this->size())}; + } - std::experimental::optional GetEntry(int i) const - { - if (i >= this->size()) - return {}; - return this->operator[](i); - } + std::experimental::optional GetEntry(int i) const { + if (i >= this->size()) + return {}; + return this->operator[](i); + } - void Clear() { this->clear(); } + void Clear() { this->clear(); } - size_t Size() const { return this->size(); } + size_t Size() const { return this->size(); } }; -} +} // namespace urde -namespace std -{ +namespace std { template <> -struct hash -{ - size_t operator()(const urde::SObjectTag& tag) const noexcept { return tag.id.Value(); } +struct hash { + size_t operator()(const urde::SObjectTag& tag) const noexcept { return tag.id.Value(); } }; template <> -struct hash -{ - size_t operator()(const urde::CAssetId& id) const noexcept { return id.Value(); } +struct hash { + size_t operator()(const urde::CAssetId& id) const noexcept { return id.Value(); } }; -} - +} // namespace std diff --git a/Runtime/Weapon/CAuxWeapon.cpp b/Runtime/Weapon/CAuxWeapon.cpp index 199f2d3b1..f0de646e5 100644 --- a/Runtime/Weapon/CAuxWeapon.cpp +++ b/Runtime/Weapon/CAuxWeapon.cpp @@ -5,384 +5,318 @@ #include "CNewFlameThrower.hpp" #include "CEnergyProjectile.hpp" -namespace urde -{ +namespace urde { -static const CCameraShakeData skHardShake = { 0.3f, 100.f, 0, zeus::CVector3f::skZero, - {}, {1, {0, 0.f, 0.f, 0.3f, -2.f}, {1, 0.f, 0.f, 0.05f, 0.5f}}, {} }; +static const CCameraShakeData skHardShake = { + 0.3f, 100.f, 0, zeus::CVector3f::skZero, {}, {1, {0, 0.f, 0.f, 0.3f, -2.f}, {1, 0.f, 0.f, 0.05f, 0.5f}}, {}}; CAuxWeapon::CAuxWeapon(TUniqueId playerId) -: x0_missile(g_SimplePool->GetObj("Missile")), - xc_flameMuzzle(g_SimplePool->GetObj("FlameMuzzle")), - x18_busterMuzzle(g_SimplePool->GetObj("BusterMuzzle")), - x6c_playerId(playerId) -{ - x0_missile.GetObj(); - xc_flameMuzzle.GetObj(); - x18_busterMuzzle.GetObj(); - x80_24_isLoaded = false; - InitComboData(); +: x0_missile(g_SimplePool->GetObj("Missile")) +, xc_flameMuzzle(g_SimplePool->GetObj("FlameMuzzle")) +, x18_busterMuzzle(g_SimplePool->GetObj("BusterMuzzle")) +, x6c_playerId(playerId) { + x0_missile.GetObj(); + xc_flameMuzzle.GetObj(); + x18_busterMuzzle.GetObj(); + x80_24_isLoaded = false; + InitComboData(); } -static const char* skComboNames[] = -{ - "SuperMissile", - "IceCombo", - "WaveBuster", - "FlameThrower", - "SuperMissile" -}; +static const char* skComboNames[] = {"SuperMissile", "IceCombo", "WaveBuster", "FlameThrower", "SuperMissile"}; -void CAuxWeapon::InitComboData() -{ - for (int i=0 ; i<5 ; ++i) - x28_combos.push_back(g_SimplePool->GetObj(skComboNames[i])); +void CAuxWeapon::InitComboData() { + for (int i = 0; i < 5; ++i) + x28_combos.push_back(g_SimplePool->GetObj(skComboNames[i])); } -void CAuxWeapon::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Deleted) - { - DeleteFlameThrower(mgr); - DeleteWaveBusterBeam(mgr); - } +void CAuxWeapon::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Deleted) { + DeleteFlameThrower(mgr); + DeleteWaveBusterBeam(mgr); + } } -bool CAuxWeapon::IsComboFxActive(const CStateManager& mgr) const -{ - switch (x74_firingBeamId) - { - case CPlayerState::EBeamId::Wave: - if (const CEntity* ent = mgr.GetObjectById(x70_waveBusterId)) - return static_cast(ent)->IsFiring(); - break; - case CPlayerState::EBeamId::Plasma: - if (const CEntity* ent = mgr.GetObjectById(x6e_flameThrowerId)) - return static_cast(ent)->IsFiring(); - break; - default: - break; - } - return false; +bool CAuxWeapon::IsComboFxActive(const CStateManager& mgr) const { + switch (x74_firingBeamId) { + case CPlayerState::EBeamId::Wave: + if (const CEntity* ent = mgr.GetObjectById(x70_waveBusterId)) + return static_cast(ent)->IsFiring(); + break; + case CPlayerState::EBeamId::Plasma: + if (const CEntity* ent = mgr.GetObjectById(x6e_flameThrowerId)) + return static_cast(ent)->IsFiring(); + break; + default: + break; + } + return false; } -void CAuxWeapon::Load(CPlayerState::EBeamId curBeam, CStateManager& mgr) -{ - x80_24_isLoaded = false; - switch (x78_loadBeamId) - { - case CPlayerState::EBeamId::Wave: - DeleteWaveBusterBeam(mgr); - break; - case CPlayerState::EBeamId::Plasma: - DeleteFlameThrower(mgr); - break; - default: - break; - } - x28_combos[int(x78_loadBeamId)].Unlock(); - x28_combos[int(curBeam)].Lock(); - x78_loadBeamId = curBeam; - LoadIdle(); +void CAuxWeapon::Load(CPlayerState::EBeamId curBeam, CStateManager& mgr) { + x80_24_isLoaded = false; + switch (x78_loadBeamId) { + case CPlayerState::EBeamId::Wave: + DeleteWaveBusterBeam(mgr); + break; + case CPlayerState::EBeamId::Plasma: + DeleteFlameThrower(mgr); + break; + default: + break; + } + x28_combos[int(x78_loadBeamId)].Unlock(); + x28_combos[int(curBeam)].Lock(); + x78_loadBeamId = curBeam; + LoadIdle(); } -void CAuxWeapon::StopComboFx(CStateManager& mgr, bool deactivate) -{ - switch (x74_firingBeamId) - { - case CPlayerState::EBeamId::Wave: - { - auto* wb = static_cast(mgr.ObjectById(x70_waveBusterId)); - if (wb) - { - wb->ResetBeam(deactivate); - DeleteWaveBusterBeam(mgr); - } - break; +void CAuxWeapon::StopComboFx(CStateManager& mgr, bool deactivate) { + switch (x74_firingBeamId) { + case CPlayerState::EBeamId::Wave: { + auto* wb = static_cast(mgr.ObjectById(x70_waveBusterId)); + if (wb) { + wb->ResetBeam(deactivate); + DeleteWaveBusterBeam(mgr); } - case CPlayerState::EBeamId::Plasma: - { - auto* ft = static_cast(mgr.ObjectById(x6e_flameThrowerId)); - if (ft) - { - mgr.GetPlayerState()->SetFiringComboBeam(false); - if (ft->IsFiring()) - { - ft->Reset(mgr, deactivate); - FreeComboVoiceId(); - } - else if (ft->GetActive() && deactivate) - { - ft->Reset(mgr, deactivate); - } - } - break; - } - default: - break; + break; + } + case CPlayerState::EBeamId::Plasma: { + auto* ft = static_cast(mgr.ObjectById(x6e_flameThrowerId)); + if (ft) { + mgr.GetPlayerState()->SetFiringComboBeam(false); + if (ft->IsFiring()) { + ft->Reset(mgr, deactivate); + FreeComboVoiceId(); + } else if (ft->GetActive() && deactivate) { + ft->Reset(mgr, deactivate); + } } + break; + } + default: + break; + } - if (deactivate) - { - x74_firingBeamId = CPlayerState::EBeamId::Invalid; - x68_ammoConsumeTimer = 0.f; - } + if (deactivate) { + x74_firingBeamId = CPlayerState::EBeamId::Invalid; + x68_ammoConsumeTimer = 0.f; + } } bool CAuxWeapon::UpdateComboFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, - const zeus::CTransform& xf, CStateManager& mgr) -{ - if (!x80_24_isLoaded || x74_firingBeamId == CPlayerState::EBeamId::Invalid) - return false; + const zeus::CTransform& xf, CStateManager& mgr) { + if (!x80_24_isLoaded || x74_firingBeamId == CPlayerState::EBeamId::Invalid) + return false; - bool firing = false; - if (x7c_comboSfx && !CSfxManager::IsPlaying(x7c_comboSfx)) - FreeComboVoiceId(); - - switch (x74_firingBeamId) - { - case CPlayerState::EBeamId::Wave: - case CPlayerState::EBeamId::Plasma: - { - bool firingFx = false; - if (x74_firingBeamId == CPlayerState::EBeamId::Wave) - { - auto* wb = static_cast(mgr.ObjectById(x70_waveBusterId)); - if (wb && wb->IsFiring()) - { - wb->UpdateFx(xf, dt, mgr); - firing = true; - firingFx = true; - } - else - { - DeleteWaveBusterBeam(mgr); - mgr.GetPlayerState()->SetFiringComboBeam(false); - } - } - else - { - auto* ft = static_cast(mgr.ObjectById(x6e_flameThrowerId)); - bool needsDelete = true; - if (ft) - { - firingFx = ft->CanRenderAuxEffects(); - if (ft->GetActive()) - { - ft->UpdateFx(xf, dt, mgr); - firing = ft->IsFiring(); - } - if (x6e_flameThrowerId != kInvalidUniqueId) - needsDelete = ft->AreEffectsFinished(); - } - if (needsDelete) - { - DeleteFlameThrower(mgr); - mgr.GetPlayerState()->SetFiringComboBeam(false); - } - } - - if (firingFx) - { - x68_ammoConsumeTimer += dt; - if (mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles) > 0) - { - if (x68_ammoConsumeTimer >= mgr.GetPlayerState()->GetComboFireAmmoPeriod()) - { - mgr.GetPlayerState()->DecrPickup(CPlayerState::EItemType::Missiles, 1); - x68_ammoConsumeTimer = 0.f; - } - } - } - - if (mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles) == 0) - StopComboFx(mgr, false); - - x24_muzzleFxGen->SetGlobalTranslation(pos); - x24_muzzleFxGen->SetGlobalScale(scale); - x24_muzzleFxGen->SetParticleEmission(firingFx); - x24_muzzleFxGen->Update(dt); - break; - } - default: - break; - } - - return firing; -} - -void CAuxWeapon::FreeComboVoiceId() -{ - CSfxManager::SfxStop(x7c_comboSfx); - x7c_comboSfx.reset(); -} - -void CAuxWeapon::DeleteFlameThrower(CStateManager& mgr) -{ + bool firing = false; + if (x7c_comboSfx && !CSfxManager::IsPlaying(x7c_comboSfx)) FreeComboVoiceId(); - if (x6e_flameThrowerId != kInvalidUniqueId) - { - mgr.FreeScriptObject(x6e_flameThrowerId); - x6e_flameThrowerId = kInvalidUniqueId; - x74_firingBeamId = CPlayerState::EBeamId::Invalid; + + switch (x74_firingBeamId) { + case CPlayerState::EBeamId::Wave: + case CPlayerState::EBeamId::Plasma: { + bool firingFx = false; + if (x74_firingBeamId == CPlayerState::EBeamId::Wave) { + auto* wb = static_cast(mgr.ObjectById(x70_waveBusterId)); + if (wb && wb->IsFiring()) { + wb->UpdateFx(xf, dt, mgr); + firing = true; + firingFx = true; + } else { + DeleteWaveBusterBeam(mgr); mgr.GetPlayerState()->SetFiringComboBeam(false); - } -} - -void CAuxWeapon::CreateFlameThrower(const zeus::CTransform& xf, CStateManager& mgr, float dt) -{ - DeleteFlameThrower(mgr); - if (x6e_flameThrowerId != kInvalidUniqueId) - return; - - CAssetId resInfo[] = - { - NWeaponTypes::get_asset_id_from_name("NFTMainFire"), - NWeaponTypes::get_asset_id_from_name("NFTMainSmoke"), - NWeaponTypes::get_asset_id_from_name("NFTSwooshCenter"), - NWeaponTypes::get_asset_id_from_name("NFTSwooshFire"), - NWeaponTypes::get_asset_id_from_name("NFTSecondarySmoke"), - NWeaponTypes::get_asset_id_from_name("NFTSecondaryFire"), - NWeaponTypes::get_asset_id_from_name("NFTSecondarySparks"), - {} - }; - x6e_flameThrowerId = mgr.AllocateUniqueId(); - CNewFlameThrower* ft = new CNewFlameThrower(x28_combos[3], "Player_FlameThrower", EWeaponType::Plasma, - resInfo, xf, EMaterialTypes::Player, CGunWeapon::GetShotDamageInfo(g_tweakPlayerGun->GetComboShotInfo(3), mgr), - x6e_flameThrowerId, kInvalidAreaId, x6c_playerId, EProjectileAttrib::None); - mgr.AddObject(ft); - ft->Think(dt, mgr); - ft->StartFiring(xf, mgr); - x24_muzzleFxGen = std::make_unique(xc_flameMuzzle); - x7c_comboSfx = NWeaponTypes::play_sfx(SFXwpn_combo_flamethrower, false, true, 0.165f); - mgr.GetCameraManager()->AddCameraShaker(skHardShake, false); - mgr.GetPlayerState()->SetFiringComboBeam(true); - x74_firingBeamId = CPlayerState::EBeamId::Plasma; -} - -void CAuxWeapon::DeleteWaveBusterBeam(CStateManager& mgr) -{ - FreeComboVoiceId(); - if (x70_waveBusterId != kInvalidUniqueId) - { - mgr.FreeScriptObject(x70_waveBusterId); - x70_waveBusterId = kInvalidUniqueId; - x74_firingBeamId = CPlayerState::EBeamId::Invalid; + } + } else { + auto* ft = static_cast(mgr.ObjectById(x6e_flameThrowerId)); + bool needsDelete = true; + if (ft) { + firingFx = ft->CanRenderAuxEffects(); + if (ft->GetActive()) { + ft->UpdateFx(xf, dt, mgr); + firing = ft->IsFiring(); + } + if (x6e_flameThrowerId != kInvalidUniqueId) + needsDelete = ft->AreEffectsFinished(); + } + if (needsDelete) { + DeleteFlameThrower(mgr); mgr.GetPlayerState()->SetFiringComboBeam(false); + } } + + if (firingFx) { + x68_ammoConsumeTimer += dt; + if (mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles) > 0) { + if (x68_ammoConsumeTimer >= mgr.GetPlayerState()->GetComboFireAmmoPeriod()) { + mgr.GetPlayerState()->DecrPickup(CPlayerState::EItemType::Missiles, 1); + x68_ammoConsumeTimer = 0.f; + } + } + } + + if (mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles) == 0) + StopComboFx(mgr, false); + + x24_muzzleFxGen->SetGlobalTranslation(pos); + x24_muzzleFxGen->SetGlobalScale(scale); + x24_muzzleFxGen->SetParticleEmission(firingFx); + x24_muzzleFxGen->Update(dt); + break; + } + default: + break; + } + + return firing; } -void CAuxWeapon::CreateWaveBusterBeam(EProjectileAttrib attribs, TUniqueId homingTarget, - const zeus::CTransform& xf, CStateManager& mgr) -{ - DeleteFlameThrower(mgr); - if (x70_waveBusterId != kInvalidUniqueId) - return; - - x70_waveBusterId = mgr.AllocateUniqueId(); - CWaveBuster* wb = new CWaveBuster(x28_combos[2], EWeaponType::Wave, xf, EMaterialTypes::Player, - CGunWeapon::GetShotDamageInfo(g_tweakPlayerGun->GetComboShotInfo(2), mgr), x70_waveBusterId, - kInvalidAreaId, x6c_playerId, homingTarget, attribs); - mgr.AddObject(wb); - x24_muzzleFxGen = std::make_unique(x18_busterMuzzle); - x7c_comboSfx = NWeaponTypes::play_sfx(SFXwpn_combo_wavebuster, false, true, 0.165f); - mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::skChargedShotCameraShakeData, false); - mgr.GetPlayerState()->SetFiringComboBeam(true); - x74_firingBeamId = CPlayerState::EBeamId::Wave; +void CAuxWeapon::FreeComboVoiceId() { + CSfxManager::SfxStop(x7c_comboSfx); + x7c_comboSfx.reset(); } -static const u16 skSoundId[] = { 1810, 1837, 1847, 1842, 1810 }; +void CAuxWeapon::DeleteFlameThrower(CStateManager& mgr) { + FreeComboVoiceId(); + if (x6e_flameThrowerId != kInvalidUniqueId) { + mgr.FreeScriptObject(x6e_flameThrowerId); + x6e_flameThrowerId = kInvalidUniqueId; + x74_firingBeamId = CPlayerState::EBeamId::Invalid; + mgr.GetPlayerState()->SetFiringComboBeam(false); + } +} + +void CAuxWeapon::CreateFlameThrower(const zeus::CTransform& xf, CStateManager& mgr, float dt) { + DeleteFlameThrower(mgr); + if (x6e_flameThrowerId != kInvalidUniqueId) + return; + + CAssetId resInfo[] = {NWeaponTypes::get_asset_id_from_name("NFTMainFire"), + NWeaponTypes::get_asset_id_from_name("NFTMainSmoke"), + NWeaponTypes::get_asset_id_from_name("NFTSwooshCenter"), + NWeaponTypes::get_asset_id_from_name("NFTSwooshFire"), + NWeaponTypes::get_asset_id_from_name("NFTSecondarySmoke"), + NWeaponTypes::get_asset_id_from_name("NFTSecondaryFire"), + NWeaponTypes::get_asset_id_from_name("NFTSecondarySparks"), + {}}; + x6e_flameThrowerId = mgr.AllocateUniqueId(); + CNewFlameThrower* ft = new CNewFlameThrower( + x28_combos[3], "Player_FlameThrower", EWeaponType::Plasma, resInfo, xf, EMaterialTypes::Player, + CGunWeapon::GetShotDamageInfo(g_tweakPlayerGun->GetComboShotInfo(3), mgr), x6e_flameThrowerId, kInvalidAreaId, + x6c_playerId, EProjectileAttrib::None); + mgr.AddObject(ft); + ft->Think(dt, mgr); + ft->StartFiring(xf, mgr); + x24_muzzleFxGen = std::make_unique(xc_flameMuzzle); + x7c_comboSfx = NWeaponTypes::play_sfx(SFXwpn_combo_flamethrower, false, true, 0.165f); + mgr.GetCameraManager()->AddCameraShaker(skHardShake, false); + mgr.GetPlayerState()->SetFiringComboBeam(true); + x74_firingBeamId = CPlayerState::EBeamId::Plasma; +} + +void CAuxWeapon::DeleteWaveBusterBeam(CStateManager& mgr) { + FreeComboVoiceId(); + if (x70_waveBusterId != kInvalidUniqueId) { + mgr.FreeScriptObject(x70_waveBusterId); + x70_waveBusterId = kInvalidUniqueId; + x74_firingBeamId = CPlayerState::EBeamId::Invalid; + mgr.GetPlayerState()->SetFiringComboBeam(false); + } +} + +void CAuxWeapon::CreateWaveBusterBeam(EProjectileAttrib attribs, TUniqueId homingTarget, const zeus::CTransform& xf, + CStateManager& mgr) { + DeleteFlameThrower(mgr); + if (x70_waveBusterId != kInvalidUniqueId) + return; + + x70_waveBusterId = mgr.AllocateUniqueId(); + CWaveBuster* wb = new CWaveBuster(x28_combos[2], EWeaponType::Wave, xf, EMaterialTypes::Player, + CGunWeapon::GetShotDamageInfo(g_tweakPlayerGun->GetComboShotInfo(2), mgr), + x70_waveBusterId, kInvalidAreaId, x6c_playerId, homingTarget, attribs); + mgr.AddObject(wb); + x24_muzzleFxGen = std::make_unique(x18_busterMuzzle); + x7c_comboSfx = NWeaponTypes::play_sfx(SFXwpn_combo_wavebuster, false, true, 0.165f); + mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::skChargedShotCameraShakeData, false); + mgr.GetPlayerState()->SetFiringComboBeam(true); + x74_firingBeamId = CPlayerState::EBeamId::Wave; +} + +static const u16 skSoundId[] = {1810, 1837, 1847, 1842, 1810}; void CAuxWeapon::LaunchMissile(float dt, bool underwater, bool charged, CPlayerState::EBeamId currentBeam, EProjectileAttrib attrib, const zeus::CTransform& xf, TUniqueId homingId, - CStateManager& mgr) -{ - const SShotParam& info = - charged ? g_tweakPlayerGun->GetComboShotInfo(int(currentBeam)) : g_tweakPlayerGun->GetMissileInfo(); - u16 sfxId = charged ? skSoundId[int(currentBeam)] : u16(SFXwpn_fire_missile); - CEnergyProjectile* proj = new CEnergyProjectile(true, charged ? x28_combos[int(currentBeam)] : x0_missile, - charged ? EWeaponType::Power : EWeaponType::Missile, xf, EMaterialTypes::Player, - CGunWeapon::GetShotDamageInfo(info, mgr), mgr.AllocateUniqueId(), kInvalidAreaId, x6c_playerId, homingId, - attrib | EProjectileAttrib::ArmCannon, underwater, zeus::CVector3f::skOne, {}, -1, false); - mgr.AddObject(proj); - proj->Think(dt, mgr); - if (charged) - { - proj->SetCameraShake(CCameraShakeData::BuildMissileCameraShake(0.25f, 0.75f, 50.f, proj->GetTranslation())); - mgr.GetCameraManager()->AddCameraShaker(skHardShake, false); - } - else - { - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerMissileFire, 0.5f, ERumblePriority::One); - } - x7c_comboSfx = NWeaponTypes::play_sfx(sfxId, underwater, false, 0.165f); + CStateManager& mgr) { + const SShotParam& info = + charged ? g_tweakPlayerGun->GetComboShotInfo(int(currentBeam)) : g_tweakPlayerGun->GetMissileInfo(); + u16 sfxId = charged ? skSoundId[int(currentBeam)] : u16(SFXwpn_fire_missile); + CEnergyProjectile* proj = new CEnergyProjectile( + true, charged ? x28_combos[int(currentBeam)] : x0_missile, charged ? EWeaponType::Power : EWeaponType::Missile, + xf, EMaterialTypes::Player, CGunWeapon::GetShotDamageInfo(info, mgr), mgr.AllocateUniqueId(), kInvalidAreaId, + x6c_playerId, homingId, attrib | EProjectileAttrib::ArmCannon, underwater, zeus::CVector3f::skOne, {}, -1, false); + mgr.AddObject(proj); + proj->Think(dt, mgr); + if (charged) { + proj->SetCameraShake(CCameraShakeData::BuildMissileCameraShake(0.25f, 0.75f, 50.f, proj->GetTranslation())); + mgr.GetCameraManager()->AddCameraShaker(skHardShake, false); + } else { + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerMissileFire, 0.5f, ERumblePriority::One); + } + x7c_comboSfx = NWeaponTypes::play_sfx(sfxId, underwater, false, 0.165f); } void CAuxWeapon::Fire(float dt, bool underwater, CPlayerState::EBeamId currentBeam, EChargeState chargeState, - const zeus::CTransform& xf, CStateManager& mgr, EWeaponType type, TUniqueId homingId) -{ - if (!x80_24_isLoaded) - return; + const zeus::CTransform& xf, CStateManager& mgr, EWeaponType type, TUniqueId homingId) { + if (!x80_24_isLoaded) + return; - EProjectileAttrib attrib = EProjectileAttrib::None; - if (chargeState == EChargeState::Charged) - attrib = CGameProjectile::GetBeamAttribType(type) | EProjectileAttrib::ComboShot; + EProjectileAttrib attrib = EProjectileAttrib::None; + if (chargeState == EChargeState::Charged) + attrib = CGameProjectile::GetBeamAttribType(type) | EProjectileAttrib::ComboShot; - if (chargeState == EChargeState::Normal) - { - LaunchMissile(dt, underwater, chargeState == EChargeState::Charged, currentBeam, attrib, xf, homingId, mgr); - } - else - { - switch (currentBeam) - { - case CPlayerState::EBeamId::Power: - case CPlayerState::EBeamId::Ice: - LaunchMissile(dt, underwater, chargeState == EChargeState::Charged, currentBeam, attrib, xf, homingId, mgr); - break; - case CPlayerState::EBeamId::Wave: - CreateWaveBusterBeam(attrib, homingId, xf, mgr); - break; - case CPlayerState::EBeamId::Plasma: - CreateFlameThrower(xf, mgr, dt); - break; - default: - break; - } - } -} - -void CAuxWeapon::LoadIdle() -{ - x80_24_isLoaded = x28_combos[int(x78_loadBeamId)].IsLoaded(); -} - -void CAuxWeapon::RenderMuzzleFx() const -{ - switch (x74_firingBeamId) - { + if (chargeState == EChargeState::Normal) { + LaunchMissile(dt, underwater, chargeState == EChargeState::Charged, currentBeam, attrib, xf, homingId, mgr); + } else { + switch (currentBeam) { + case CPlayerState::EBeamId::Power: + case CPlayerState::EBeamId::Ice: + LaunchMissile(dt, underwater, chargeState == EChargeState::Charged, currentBeam, attrib, xf, homingId, mgr); + break; case CPlayerState::EBeamId::Wave: + CreateWaveBusterBeam(attrib, homingId, xf, mgr); + break; case CPlayerState::EBeamId::Plasma: - x24_muzzleFxGen->Render(); - break; + CreateFlameThrower(xf, mgr, dt); + break; default: - break; + break; } + } } -TUniqueId CAuxWeapon::HasTarget(const CStateManager& mgr) const -{ - if (x74_firingBeamId == CPlayerState::EBeamId::Wave) - if (auto* wb = static_cast(mgr.GetObjectById(x70_waveBusterId))) - return wb->GetHomingTargetId(); - return kInvalidUniqueId; +void CAuxWeapon::LoadIdle() { x80_24_isLoaded = x28_combos[int(x78_loadBeamId)].IsLoaded(); } + +void CAuxWeapon::RenderMuzzleFx() const { + switch (x74_firingBeamId) { + case CPlayerState::EBeamId::Wave: + case CPlayerState::EBeamId::Plasma: + x24_muzzleFxGen->Render(); + break; + default: + break; + } } -void CAuxWeapon::SetNewTarget(TUniqueId targetId, CStateManager& mgr) -{ - if (x74_firingBeamId == CPlayerState::EBeamId::Wave) - if (auto* wb = static_cast(mgr.ObjectById(x70_waveBusterId))) - wb->SetNewTarget(targetId); +TUniqueId CAuxWeapon::HasTarget(const CStateManager& mgr) const { + if (x74_firingBeamId == CPlayerState::EBeamId::Wave) + if (auto* wb = static_cast(mgr.GetObjectById(x70_waveBusterId))) + return wb->GetHomingTargetId(); + return kInvalidUniqueId; } +void CAuxWeapon::SetNewTarget(TUniqueId targetId, CStateManager& mgr) { + if (x74_firingBeamId == CPlayerState::EBeamId::Wave) + if (auto* wb = static_cast(mgr.ObjectById(x70_waveBusterId))) + wb->SetNewTarget(targetId); } + +} // namespace urde diff --git a/Runtime/Weapon/CAuxWeapon.hpp b/Runtime/Weapon/CAuxWeapon.hpp index 1f9842679..165a0cfbc 100644 --- a/Runtime/Weapon/CAuxWeapon.hpp +++ b/Runtime/Weapon/CAuxWeapon.hpp @@ -6,50 +6,47 @@ #include "CGunWeapon.hpp" #include "CWeapon.hpp" -namespace urde -{ +namespace urde { + +class CAuxWeapon { + TCachedToken x0_missile; + TCachedToken xc_flameMuzzle; + TCachedToken x18_busterMuzzle; + std::unique_ptr x24_muzzleFxGen; + rstl::reserved_vector, 5> x28_combos; + float x68_ammoConsumeTimer = 0.f; + TUniqueId x6c_playerId; + TUniqueId x6e_flameThrowerId = kInvalidUniqueId; + TUniqueId x70_waveBusterId = kInvalidUniqueId; + CPlayerState::EBeamId x74_firingBeamId = CPlayerState::EBeamId::Invalid; + CPlayerState::EBeamId x78_loadBeamId = CPlayerState::EBeamId::Power; + CSfxHandle x7c_comboSfx; + bool x80_24_isLoaded : 1; + void InitComboData(); + void FreeComboVoiceId(); + void DeleteFlameThrower(CStateManager& mgr); + void CreateFlameThrower(const zeus::CTransform& xf, CStateManager& mgr, float dt); + void DeleteWaveBusterBeam(CStateManager& mgr); + void CreateWaveBusterBeam(EProjectileAttrib attribs, TUniqueId homingTarget, const zeus::CTransform& xf, + CStateManager& mgr); + void LaunchMissile(float dt, bool underwater, bool charged, CPlayerState::EBeamId currentBeam, + EProjectileAttrib attrib, const zeus::CTransform& xf, TUniqueId homingId, CStateManager& mgr); -class CAuxWeapon -{ - TCachedToken x0_missile; - TCachedToken xc_flameMuzzle; - TCachedToken x18_busterMuzzle; - std::unique_ptr x24_muzzleFxGen; - rstl::reserved_vector, 5> x28_combos; - float x68_ammoConsumeTimer = 0.f; - TUniqueId x6c_playerId; - TUniqueId x6e_flameThrowerId = kInvalidUniqueId; - TUniqueId x70_waveBusterId = kInvalidUniqueId; - CPlayerState::EBeamId x74_firingBeamId = CPlayerState::EBeamId::Invalid; - CPlayerState::EBeamId x78_loadBeamId = CPlayerState::EBeamId::Power; - CSfxHandle x7c_comboSfx; - bool x80_24_isLoaded : 1; - void InitComboData(); - void FreeComboVoiceId(); - void DeleteFlameThrower(CStateManager& mgr); - void CreateFlameThrower(const zeus::CTransform& xf, CStateManager& mgr, float dt); - void DeleteWaveBusterBeam(CStateManager& mgr); - void CreateWaveBusterBeam(EProjectileAttrib attribs, TUniqueId homingTarget, - const zeus::CTransform& xf, CStateManager& mgr); - void LaunchMissile(float dt, bool underwater, bool charged, CPlayerState::EBeamId currentBeam, - EProjectileAttrib attrib, const zeus::CTransform& xf, TUniqueId homingId, - CStateManager& mgr); public: - explicit CAuxWeapon(TUniqueId playerId); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - bool IsComboFxActive(const CStateManager& mgr) const; - void Load(CPlayerState::EBeamId curBeam, CStateManager& mgr); - void StopComboFx(CStateManager& mgr, bool deactivate); - bool UpdateComboFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, - const zeus::CTransform& xf, CStateManager& mgr); - void Fire(float dt, bool underwater, CPlayerState::EBeamId currentBeam, EChargeState chargeState, - const zeus::CTransform& xf, CStateManager& mgr, EWeaponType type, TUniqueId homingId); - void LoadIdle(); - bool IsLoaded() const { return x80_24_isLoaded; } - void RenderMuzzleFx() const; - TUniqueId HasTarget(const CStateManager& mgr) const; - void SetNewTarget(TUniqueId targetId, CStateManager& mgr); + explicit CAuxWeapon(TUniqueId playerId); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + bool IsComboFxActive(const CStateManager& mgr) const; + void Load(CPlayerState::EBeamId curBeam, CStateManager& mgr); + void StopComboFx(CStateManager& mgr, bool deactivate); + bool UpdateComboFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, const zeus::CTransform& xf, + CStateManager& mgr); + void Fire(float dt, bool underwater, CPlayerState::EBeamId currentBeam, EChargeState chargeState, + const zeus::CTransform& xf, CStateManager& mgr, EWeaponType type, TUniqueId homingId); + void LoadIdle(); + bool IsLoaded() const { return x80_24_isLoaded; } + void RenderMuzzleFx() const; + TUniqueId HasTarget(const CStateManager& mgr) const; + void SetNewTarget(TUniqueId targetId, CStateManager& mgr); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CBeamInfo.hpp b/Runtime/Weapon/CBeamInfo.hpp index af7a14c10..08a64e812 100644 --- a/Runtime/Weapon/CBeamInfo.hpp +++ b/Runtime/Weapon/CBeamInfo.hpp @@ -4,44 +4,63 @@ #include "IOStreams.hpp" #include "zeus/CColor.hpp" -namespace urde -{ -struct CBeamInfo -{ - u32 x0_; - s32 x4_; - CAssetId x8_; - CAssetId xc_; - CAssetId x10_; - CAssetId x14_; - s32 x18_; - float x1c_; - float x20_; - float x24_; - float x28_; - float x2c_; - float x30_; - float x34_; - float x38_; - zeus::CColor x3c_; - zeus::CColor x40_; +namespace urde { +struct CBeamInfo { + u32 x0_; + s32 x4_; + CAssetId x8_; + CAssetId xc_; + CAssetId x10_; + CAssetId x14_; + s32 x18_; + float x1c_; + float x20_; + float x24_; + float x28_; + float x2c_; + float x30_; + float x34_; + float x38_; + zeus::CColor x3c_; + zeus::CColor x40_; - CBeamInfo(CInputStream& in) - : x0_(in.readUint32Big()), x4_(in.readUint32Big()), x8_(in.readUint32Big()), xc_(in.readUint32Big()), - x10_(in.readUint32Big()), x14_(in.readUint32Big()), x18_(in.readFloatBig()), x1c_(in.readFloatBig()), - x20_(in.readFloatBig()), x24_(in.readFloatBig()), x28_(in.readFloatBig()), x2c_(in.readFloatBig()), - x30_(in.readFloatBig()), x34_(in.readFloatBig()), x38_(in.readFloatBig()), - x3c_(zeus::CColor::ReadRGBABig(in)), x40_(zeus::CColor::ReadRGBABig(in)) - { - } + CBeamInfo(CInputStream& in) + : x0_(in.readUint32Big()) + , x4_(in.readUint32Big()) + , x8_(in.readUint32Big()) + , xc_(in.readUint32Big()) + , x10_(in.readUint32Big()) + , x14_(in.readUint32Big()) + , x18_(in.readFloatBig()) + , x1c_(in.readFloatBig()) + , x20_(in.readFloatBig()) + , x24_(in.readFloatBig()) + , x28_(in.readFloatBig()) + , x2c_(in.readFloatBig()) + , x30_(in.readFloatBig()) + , x34_(in.readFloatBig()) + , x38_(in.readFloatBig()) + , x3c_(zeus::CColor::ReadRGBABig(in)) + , x40_(zeus::CColor::ReadRGBABig(in)) {} - CBeamInfo(s32 w1, CAssetId w2, CAssetId w3, CAssetId w4, CAssetId w5, s32 w6, float f1, float f2, float f3, - float f4, float f5, float f6, float f7, const zeus::CColor& col1, const zeus::CColor& col2, float f8) - : x4_(w1), x8_(w2), xc_(w3), x10_(w4), x14_(w5), x18_(w6), x1c_(f1), x20_(f2), x24_(f3), x28_(f4), x2c_(f5), - x30_(f6), x34_(f7), x38_(f8), x3c_(col1), x40_(col2) - { - - } + CBeamInfo(s32 w1, CAssetId w2, CAssetId w3, CAssetId w4, CAssetId w5, s32 w6, float f1, float f2, float f3, float f4, + float f5, float f6, float f7, const zeus::CColor& col1, const zeus::CColor& col2, float f8) + : x4_(w1) + , x8_(w2) + , xc_(w3) + , x10_(w4) + , x14_(w5) + , x18_(w6) + , x1c_(f1) + , x20_(f2) + , x24_(f3) + , x28_(f4) + , x2c_(f5) + , x30_(f6) + , x34_(f7) + , x38_(f8) + , x3c_(col1) + , x40_(col2) {} }; -} +} // namespace urde diff --git a/Runtime/Weapon/CBeamProjectile.cpp b/Runtime/Weapon/CBeamProjectile.cpp index 2025d52b5..8889762f1 100644 --- a/Runtime/Weapon/CBeamProjectile.cpp +++ b/Runtime/Weapon/CBeamProjectile.cpp @@ -1,8 +1,7 @@ #include "Weapon/CBeamProjectile.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CBeamProjectile::CBeamProjectile(const TToken& wDesc, std::string_view name, EWeaponType wType, const zeus::CTransform& xf, s32 flags, float f1, float f2, EMaterialTypes matType, @@ -17,41 +16,27 @@ CBeamProjectile::CBeamProjectile(const TToken& wDesc, std::s , x300_(b1 == false ? x2ec_ : 0.f) , x308_(f2) , x464_24_(b1) -, x464_25_(false) -{ +, x464_25_(false) {} -} - -std::experimental::optional CBeamProjectile::GetTouchBounds() const -{ - if (!GetActive()) - return {}; - if (!x464_25_) - { - zeus::CVector3f pos = GetTranslation(); - return {{pos - 1.f, pos + 1.f}}; - } +std::experimental::optional CBeamProjectile::GetTouchBounds() const { + if (!GetActive()) return {}; + if (!x464_25_) { + zeus::CVector3f pos = GetTranslation(); + return {{pos - 1.f, pos + 1.f}}; + } + return {}; } -void CBeamProjectile::CalculateRenderBounds() -{ - x9c_renderBounds = x354_.getTransformedAABox(x324_); +void CBeamProjectile::CalculateRenderBounds() { x9c_renderBounds = x354_.getTransformedAABox(x324_); } + +void CBeamProjectile::ResetBeam(CStateManager&, bool) { + if (x464_24_) + x300_ = 0.f; } -void CBeamProjectile::ResetBeam(CStateManager &, bool) -{ - if (x464_24_) - x300_ = 0.f; -} +void CBeamProjectile::UpdateFX(const zeus::CTransform&, float, CStateManager&) {} -void CBeamProjectile::UpdateFX(const zeus::CTransform &, float, CStateManager &) -{ -} +void CBeamProjectile::Accept(urde::IVisitor& visitor) { visitor.Visit(this); } -void CBeamProjectile::Accept(urde::IVisitor& visitor) -{ - visitor.Visit(this); -} - -} +} // namespace urde diff --git a/Runtime/Weapon/CBeamProjectile.hpp b/Runtime/Weapon/CBeamProjectile.hpp index 557701387..0a9d245ed 100644 --- a/Runtime/Weapon/CBeamProjectile.hpp +++ b/Runtime/Weapon/CBeamProjectile.hpp @@ -1,51 +1,50 @@ #pragma once #include "Weapon/CGameProjectile.hpp" -namespace urde -{ -class CBeamProjectile : public CGameProjectile -{ - u32 x2e8_; - float x2ec_; - float x2f0_; - float x2f4_; - u32 x2f8_ = 0; - TUniqueId x2fc_ = kInvalidUniqueId; - TUniqueId x2fe_ = kInvalidUniqueId; - float x300_; - float x304_; - float x308_; - zeus::CVector3f x30c_ = zeus::CVector3f::skUp; - zeus::CTransform x324_; - zeus::CAABox x354_ = zeus::CAABox::skNullBox; - rstl::reserved_vector x384_; - rstl::reserved_vector x400_; - bool x464_24_ : 1; - bool x464_25_ : 1; +namespace urde { +class CBeamProjectile : public CGameProjectile { + u32 x2e8_; + float x2ec_; + float x2f0_; + float x2f4_; + u32 x2f8_ = 0; + TUniqueId x2fc_ = kInvalidUniqueId; + TUniqueId x2fe_ = kInvalidUniqueId; + float x300_; + float x304_; + float x308_; + zeus::CVector3f x30c_ = zeus::CVector3f::skUp; + zeus::CTransform x324_; + zeus::CAABox x354_ = zeus::CAABox::skNullBox; + rstl::reserved_vector x384_; + rstl::reserved_vector x400_; + bool x464_24_ : 1; + bool x464_25_ : 1; + public: - CBeamProjectile(const TToken& wDesc, std::string_view name, EWeaponType wType, - const zeus::CTransform& xf, s32 flags, float f1, float f2, EMaterialTypes matType, - const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, - EProjectileAttrib attribs, bool b1); + CBeamProjectile(const TToken& wDesc, std::string_view name, EWeaponType wType, + const zeus::CTransform& xf, s32 flags, float f1, float f2, EMaterialTypes matType, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, EProjectileAttrib attribs, + bool b1); - void Accept(IVisitor &visitor); - float GetMaxRadius() const; - zeus::CVector3f GetSurfaceNormal() const; - void GetDamageType() const; - void GetCurrentPos() const; - void PointCache(); - void GetPointCache() const; - void CauseDamage(bool); - zeus::CVector3f GetBeamOrigin() const; - void GetInvMaxLength() const; - void GetCurrentLength(); - void GetMaxLength(); - s32 GetIntMaxLength(); + void Accept(IVisitor& visitor); + float GetMaxRadius() const; + zeus::CVector3f GetSurfaceNormal() const; + void GetDamageType() const; + void GetCurrentPos() const; + void PointCache(); + void GetPointCache() const; + void CauseDamage(bool); + zeus::CVector3f GetBeamOrigin() const; + void GetInvMaxLength() const; + void GetCurrentLength(); + void GetMaxLength(); + s32 GetIntMaxLength(); - std::experimental::optional GetTouchBounds() const; - void CalculateRenderBounds(); - virtual void ResetBeam(CStateManager&, bool); - virtual void UpdateFX(const zeus::CTransform&, float, CStateManager&); - virtual void Fire(const zeus::CTransform&, CStateManager&, bool) = 0; + std::experimental::optional GetTouchBounds() const; + void CalculateRenderBounds(); + virtual void ResetBeam(CStateManager&, bool); + virtual void UpdateFX(const zeus::CTransform&, float, CStateManager&); + virtual void Fire(const zeus::CTransform&, CStateManager&, bool) = 0; }; -} +} // namespace urde diff --git a/Runtime/Weapon/CBomb.cpp b/Runtime/Weapon/CBomb.cpp index 16751fa24..80d6873a2 100644 --- a/Runtime/Weapon/CBomb.cpp +++ b/Runtime/Weapon/CBomb.cpp @@ -8,178 +8,155 @@ #include "TCastTo.hpp" #include "DataSpec/DNAMP1/SFX/Weapons.h" -namespace urde -{ +namespace urde { CBomb::CBomb(const TCachedToken& particle1, const TCachedToken& particle2, - TUniqueId uid, TAreaId aid, TUniqueId playerId, float f1, - const zeus::CTransform& xf, const CDamageInfo& dInfo) + TUniqueId uid, TAreaId aid, TUniqueId playerId, float f1, const zeus::CTransform& xf, + const CDamageInfo& dInfo) : CWeapon(uid, aid, true, playerId, EWeaponType::Bomb, "Bomb", xf, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Trigger, - EMaterialTypes::NonSolidDamageable}, - {EMaterialTypes::Projectile, EMaterialTypes::Bomb}), + CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid, EMaterialTypes::Trigger, EMaterialTypes::NonSolidDamageable}, + {EMaterialTypes::Projectile, EMaterialTypes::Bomb}), {EMaterialTypes::Projectile, EMaterialTypes::Bomb}, dInfo, EProjectileAttrib::Bombs, CModelData::CModelDataNull()) , x17c_fuseTime(f1) -, x180_particle1(new CElementGen(particle1, CElementGen::EModelOrientationType::Normal, - CElementGen::EOptionalSystemFlags::One)) -, x184_particle2(new CElementGen(particle2, CElementGen::EModelOrientationType::Normal, - CElementGen::EOptionalSystemFlags::One)) +, x180_particle1( + new CElementGen(particle1, CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One)) +, x184_particle2( + new CElementGen(particle2, CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One)) , x18c_(particle2.GetObj()) , x190_24_isNotDetonated(true) , x190_25_(false) -, x190_26_disableFuse(false) -{ - x180_particle1->SetGlobalTranslation(xf.origin); - x184_particle2->SetGlobalTranslation(xf.origin); +, x190_26_disableFuse(false) { + x180_particle1->SetGlobalTranslation(xf.origin); + x184_particle2->SetGlobalTranslation(xf.origin); } -void CBomb::Accept(urde::IVisitor& visitor) -{ - visitor.Visit(this); -} +void CBomb::Accept(urde::IVisitor& visitor) { visitor.Visit(this); } -void CBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Registered) - { +void CBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Registered) { - x188_lightId = mgr.AllocateUniqueId(); - CGameLight* gameLight = new CGameLight(x188_lightId, GetAreaIdAlways(), false, - std::string("Bomb_PLight") + GetName().data(), GetTransform(), GetUniqueId(), - x184_particle2->GetLight(), reinterpret_cast(x18c_), 1, 0.f); - mgr.AddObject(gameLight); - mgr.AddWeaponId(xec_ownerId, xf0_weaponType); - CSfxManager::AddEmitter(SFXwpn_bomb_drop, GetTranslation(), {}, true, false, 0x7f, -1); - mgr.InformListeners(GetTranslation(), EListenNoiseType::BombExplode); - return; - } - else if (msg == EScriptObjectMessage::Deleted) - { - if (x188_lightId != kInvalidUniqueId) - mgr.FreeScriptObject(x188_lightId); - - if (x190_24_isNotDetonated) - mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); - - return; - } - - CActor::AcceptScriptMsg(msg, uid, mgr); -} - -static CMaterialFilter kSolidFilter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::Character, EMaterialTypes::Player, - EMaterialTypes::ProjectilePassthrough}); -void CBomb::Think(float dt, urde::CStateManager& mgr) -{ - CWeapon::Think(dt, mgr); + x188_lightId = mgr.AllocateUniqueId(); + CGameLight* gameLight = new CGameLight(x188_lightId, GetAreaIdAlways(), false, + std::string("Bomb_PLight") + GetName().data(), GetTransform(), GetUniqueId(), + x184_particle2->GetLight(), reinterpret_cast(x18c_), 1, 0.f); + mgr.AddObject(gameLight); + mgr.AddWeaponId(xec_ownerId, xf0_weaponType); + CSfxManager::AddEmitter(SFXwpn_bomb_drop, GetTranslation(), {}, true, false, 0x7f, -1); + mgr.InformListeners(GetTranslation(), EListenNoiseType::BombExplode); + return; + } else if (msg == EScriptObjectMessage::Deleted) { + if (x188_lightId != kInvalidUniqueId) + mgr.FreeScriptObject(x188_lightId); if (x190_24_isNotDetonated) - { - if (x17c_fuseTime <= 0.f) - { - Explode(GetTranslation(), mgr); - if (TCastToPtr light = mgr.ObjectById(x188_lightId)) - light->SetActive(true); - } + mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); - if (x17c_fuseTime > 0.5f) - x180_particle1->Update(dt); - else - UpdateLight(dt, mgr); + return; + } - if (!x190_26_disableFuse) - x17c_fuseTime -= dt; - } - else - { - UpdateLight(dt, mgr); - if (x184_particle2->IsSystemDeletable()) - mgr.FreeScriptObject(GetUniqueId()); - } - - if (x190_24_isNotDetonated) - { - - if (x164_.magSquared() > 0.f) - x158_ += dt * x164_; - - if (x158_.magSquared() > 0.f) - { - x170_prevLocation = GetTranslation(); - CActor::SetTranslation((dt * x158_) + GetTranslation()); - - zeus::CVector3f diffVec = (GetTranslation() - x170_prevLocation); - float diffMag = diffVec.magnitude(); - if (diffMag == 0.f) - Explode(GetTranslation(), mgr); - else - { - CRayCastResult res = mgr.RayStaticIntersection(x170_prevLocation, (1.f / diffMag) * diffVec, diffMag, - kSolidFilter); - if (res.IsValid()) - Explode(GetTranslation(), mgr); - } - } - } - - x180_particle1->SetGlobalTranslation(GetTranslation()); - x184_particle2->SetGlobalTranslation(GetTranslation()); + CActor::AcceptScriptMsg(msg, uid, mgr); } -void CBomb::AddToRenderer(const zeus::CFrustum& frustum, const urde::CStateManager& mgr) const -{ - zeus::CVector3f origin = GetTranslation(); - float ballRadius = mgr.GetPlayer().GetMorphBall()->GetBallRadius(); +static CMaterialFilter kSolidFilter = + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::Character, EMaterialTypes::Player, + EMaterialTypes::ProjectilePassthrough}); +void CBomb::Think(float dt, urde::CStateManager& mgr) { + CWeapon::Think(dt, mgr); - zeus::CAABox aabox(origin - (0.9f * ballRadius), origin + (0.9f * ballRadius)); - zeus::CVector3f closestPoint = aabox.closestPointAlongVector(CGraphics::g_ViewMatrix.frontVector()); + if (x190_24_isNotDetonated) { + if (x17c_fuseTime <= 0.f) { + Explode(GetTranslation(), mgr); + if (TCastToPtr light = mgr.ObjectById(x188_lightId)) + light->SetActive(true); + } - if (x190_24_isNotDetonated && x17c_fuseTime > 0.5f) - g_Renderer->AddParticleGen(*x180_particle1, closestPoint, aabox); + if (x17c_fuseTime > 0.5f) + x180_particle1->Update(dt); else - g_Renderer->AddParticleGen(*x184_particle2, closestPoint, aabox); + UpdateLight(dt, mgr); + + if (!x190_26_disableFuse) + x17c_fuseTime -= dt; + } else { + UpdateLight(dt, mgr); + if (x184_particle2->IsSystemDeletable()) + mgr.FreeScriptObject(GetUniqueId()); + } + + if (x190_24_isNotDetonated) { + + if (x164_.magSquared() > 0.f) + x158_ += dt * x164_; + + if (x158_.magSquared() > 0.f) { + x170_prevLocation = GetTranslation(); + CActor::SetTranslation((dt * x158_) + GetTranslation()); + + zeus::CVector3f diffVec = (GetTranslation() - x170_prevLocation); + float diffMag = diffVec.magnitude(); + if (diffMag == 0.f) + Explode(GetTranslation(), mgr); + else { + CRayCastResult res = + mgr.RayStaticIntersection(x170_prevLocation, (1.f / diffMag) * diffVec, diffMag, kSolidFilter); + if (res.IsValid()) + Explode(GetTranslation(), mgr); + } + } + } + + x180_particle1->SetGlobalTranslation(GetTranslation()); + x184_particle2->SetGlobalTranslation(GetTranslation()); } -void CBomb::Touch(CActor&, urde::CStateManager&) -{ +void CBomb::AddToRenderer(const zeus::CFrustum& frustum, const urde::CStateManager& mgr) const { + zeus::CVector3f origin = GetTranslation(); + float ballRadius = mgr.GetPlayer().GetMorphBall()->GetBallRadius(); + + zeus::CAABox aabox(origin - (0.9f * ballRadius), origin + (0.9f * ballRadius)); + zeus::CVector3f closestPoint = aabox.closestPointAlongVector(CGraphics::g_ViewMatrix.frontVector()); + + if (x190_24_isNotDetonated && x17c_fuseTime > 0.5f) + g_Renderer->AddParticleGen(*x180_particle1, closestPoint, aabox); + else + g_Renderer->AddParticleGen(*x184_particle2, closestPoint, aabox); +} + +void CBomb::Touch(CActor&, urde::CStateManager&) { #if 0 x190_24_isNotDetonated; /* wat? */ #endif } -std::experimental::optional CBomb::GetTouchBounds() const -{ - float radius = (x190_24_isNotDetonated ? 0.2f : x12c_curDamageInfo.GetRadius()); - float minX = (x170_prevLocation.x() >= GetTranslation().x() ? x170_prevLocation.x() : GetTranslation().x()) - radius; - float minY = (x170_prevLocation.y() >= GetTranslation().y() ? x170_prevLocation.y() : GetTranslation().y()) - radius; - float minZ = (x170_prevLocation.z() >= GetTranslation().z() ? x170_prevLocation.z() : GetTranslation().z()) - radius; - float maxX = (x170_prevLocation.x() >= GetTranslation().x() ? x170_prevLocation.x() : GetTranslation().x()) + radius; - float maxY = (x170_prevLocation.y() >= GetTranslation().y() ? x170_prevLocation.y() : GetTranslation().y()) + radius; - float maxZ = (x170_prevLocation.z() >= GetTranslation().z() ? x170_prevLocation.z() : GetTranslation().z()) + radius; +std::experimental::optional CBomb::GetTouchBounds() const { + float radius = (x190_24_isNotDetonated ? 0.2f : x12c_curDamageInfo.GetRadius()); + float minX = (x170_prevLocation.x() >= GetTranslation().x() ? x170_prevLocation.x() : GetTranslation().x()) - radius; + float minY = (x170_prevLocation.y() >= GetTranslation().y() ? x170_prevLocation.y() : GetTranslation().y()) - radius; + float minZ = (x170_prevLocation.z() >= GetTranslation().z() ? x170_prevLocation.z() : GetTranslation().z()) - radius; + float maxX = (x170_prevLocation.x() >= GetTranslation().x() ? x170_prevLocation.x() : GetTranslation().x()) + radius; + float maxY = (x170_prevLocation.y() >= GetTranslation().y() ? x170_prevLocation.y() : GetTranslation().y()) + radius; + float maxZ = (x170_prevLocation.z() >= GetTranslation().z() ? x170_prevLocation.z() : GetTranslation().z()) + radius; - return {{minX, minY, minZ, maxX, maxY, maxZ}}; + return {{minX, minY, minZ, maxX, maxY, maxZ}}; } -void CBomb::Explode(const zeus::CVector3f& pos, CStateManager& mgr) -{ - mgr.ApplyDamageToWorld(xec_ownerId, *this, pos, x12c_curDamageInfo, xf8_filter); - CSfxManager::AddEmitter(SFXwpn_bomb_explo, GetTranslation(), {}, true, false, 0x7f, -1); - mgr.InformListeners(pos, EListenNoiseType::BombExplode); - mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); - x190_24_isNotDetonated = false; - +void CBomb::Explode(const zeus::CVector3f& pos, CStateManager& mgr) { + mgr.ApplyDamageToWorld(xec_ownerId, *this, pos, x12c_curDamageInfo, xf8_filter); + CSfxManager::AddEmitter(SFXwpn_bomb_explo, GetTranslation(), {}, true, false, 0x7f, -1); + mgr.InformListeners(pos, EListenNoiseType::BombExplode); + mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); + x190_24_isNotDetonated = false; } -void CBomb::UpdateLight(float dt, CStateManager& mgr) -{ - x184_particle2->Update(dt); - if (x188_lightId == kInvalidUniqueId) - return; +void CBomb::UpdateLight(float dt, CStateManager& mgr) { + x184_particle2->Update(dt); + if (x188_lightId == kInvalidUniqueId) + return; - if (TCastToPtr light = mgr.ObjectById(x188_lightId)) - if (light->GetActive()) - light->SetLight(x184_particle2->GetLight()); + if (TCastToPtr light = mgr.ObjectById(x188_lightId)) + if (light->GetActive()) + light->SetLight(x184_particle2->GetLight()); } -} +} // namespace urde diff --git a/Runtime/Weapon/CBomb.hpp b/Runtime/Weapon/CBomb.hpp index 66d1ef2b3..962fa050b 100644 --- a/Runtime/Weapon/CBomb.hpp +++ b/Runtime/Weapon/CBomb.hpp @@ -3,39 +3,36 @@ #include "CWeapon.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class CElementGen; -class CBomb : public CWeapon -{ +class CBomb : public CWeapon { + + zeus::CVector3f x158_; + zeus::CVector3f x164_; + zeus::CVector3f x170_prevLocation; + float x17c_fuseTime; + std::unique_ptr x180_particle1; + std::unique_ptr x184_particle2; + TUniqueId x188_lightId = kInvalidUniqueId; + const CGenDescription* x18c_; + bool x190_24_isNotDetonated : 1; + bool x190_25_ : 1; + bool x190_26_disableFuse : 1; - zeus::CVector3f x158_; - zeus::CVector3f x164_; - zeus::CVector3f x170_prevLocation; - float x17c_fuseTime; - std::unique_ptr x180_particle1; - std::unique_ptr x184_particle2; - TUniqueId x188_lightId = kInvalidUniqueId; - const CGenDescription* x18c_; - bool x190_24_isNotDetonated : 1; - bool x190_25_ : 1; - bool x190_26_disableFuse : 1; public: - CBomb(const TCachedToken& particle1, const TCachedToken& particle2, - TUniqueId uid, TAreaId aid, TUniqueId playerId, float f1, - const zeus::CTransform& xf, const CDamageInfo& dInfo); + CBomb(const TCachedToken& particle1, const TCachedToken& particle2, TUniqueId uid, + TAreaId aid, TUniqueId playerId, float f1, const zeus::CTransform& xf, const CDamageInfo& dInfo); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - void Render(const CStateManager&) const {} - void Touch(CActor&, CStateManager&); - void Explode(const zeus::CVector3f&, CStateManager&); - void UpdateLight(float, CStateManager&); - std::experimental::optional GetTouchBounds() const; + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const {} + void Touch(CActor&, CStateManager&); + void Explode(const zeus::CVector3f&, CStateManager&); + void UpdateLight(float, CStateManager&); + std::experimental::optional GetTouchBounds() const; }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CBurstFire.cpp b/Runtime/Weapon/CBurstFire.cpp index 25363df3b..c90105271 100644 --- a/Runtime/Weapon/CBurstFire.cpp +++ b/Runtime/Weapon/CBurstFire.cpp @@ -1,108 +1,81 @@ #include "CBurstFire.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ -CBurstFire::CBurstFire(const SBurst** burstDefs, s32 firstBurstCount) -: x10_firstBurstCounter(firstBurstCount) -{ - while (*burstDefs) - { - x1c_burstDefs.push_back(*burstDefs); - ++burstDefs; +namespace urde { +CBurstFire::CBurstFire(const SBurst** burstDefs, s32 firstBurstCount) : x10_firstBurstCounter(firstBurstCount) { + while (*burstDefs) { + x1c_burstDefs.push_back(*burstDefs); + ++burstDefs; + } +} + +void CBurstFire::Update(CStateManager& mgr, float dt) { + x14_24_shouldFire = false; + if (x18_curBursts) { + x8_timeToNextShot -= dt; + if (x8_timeToNextShot < 0.f) { + x4_angleIdx += 1; + if (x18_curBursts->x4_shotAngles[x4_angleIdx] > 0) { + x14_24_shouldFire = true; + x8_timeToNextShot = x18_curBursts->x24_timeToNextShot; + x8_timeToNextShot += (mgr.GetActiveRandom()->Float() - 0.5f) * x18_curBursts->x28_timeToNextShotVariance; + } else { + x18_curBursts = nullptr; + } } + } } -void CBurstFire::Update(CStateManager& mgr, float dt) -{ - x14_24_shouldFire = false; - if (x18_curBursts) - { - x8_timeToNextShot -= dt; - if (x8_timeToNextShot < 0.f) - { - x4_angleIdx += 1; - if (x18_curBursts->x4_shotAngles[x4_angleIdx] > 0) - { - x14_24_shouldFire = true; - x8_timeToNextShot = x18_curBursts->x24_timeToNextShot; - x8_timeToNextShot += (mgr.GetActiveRandom()->Float() - 0.5f) * - x18_curBursts->x28_timeToNextShotVariance; - } - else - { - x18_curBursts = nullptr; - } - } +zeus::CVector3f CBurstFire::GetDistanceCompensatedError(float dist, float maxErrDist) const { + float xErr = GetMaxXError(); + float zErr = GetMaxZError(); + xErr = std::min(xErr, dist / maxErrDist * xErr); + zErr = std::min(zErr, dist / maxErrDist * zErr); + return GetError(xErr, zErr); +} + +void CBurstFire::Start(CStateManager& mgr) { + s32 burstIdx = -1; + const SBurst* bursts = x1c_burstDefs[x0_burstType]; + if (x10_firstBurstCounter-- > 0) { + burstIdx = xc_firstBurstIdx < 0 ? 0 : xc_firstBurstIdx; + } else { + int random = mgr.GetActiveRandom()->Range(0, 100); + int advanceAccum = 0; + do { + burstIdx += 1; + s32 advanceWeight = bursts[burstIdx].x0_randomSelectionWeight; + if (advanceWeight == 0) { + advanceAccum = 100; + burstIdx -= 1; + } + advanceAccum += advanceWeight; + } while (random > advanceAccum); + } + x18_curBursts = &bursts[burstIdx]; + x4_angleIdx = -1; + x8_timeToNextShot = 0.f; + x14_24_shouldFire = false; +} + +zeus::CVector3f CBurstFire::GetError(float xMag, float zMag) const { + zeus::CVector3f ret; + if (x14_24_shouldFire && x18_curBursts) { + s32 r0 = x18_curBursts->x4_shotAngles[x4_angleIdx]; + if (x14_25_avoidAccuracy && (r0 == 4 || r0 == 12)) + r0 = x4_angleIdx > 0 ? x18_curBursts->x4_shotAngles[x4_angleIdx - 1] + : x18_curBursts->x4_shotAngles[x4_angleIdx + 1]; + if (r0 > 0) { + float angle = r0 * zeus::degToRad(-22.5f); + ret.x() = std::cos(angle) * xMag; + ret.z() = std::sin(angle) * zMag; } + } + return ret; } -zeus::CVector3f CBurstFire::GetDistanceCompensatedError(float dist, float maxErrDist) const -{ - float xErr = GetMaxXError(); - float zErr = GetMaxZError(); - xErr = std::min(xErr, dist / maxErrDist * xErr); - zErr = std::min(zErr, dist / maxErrDist * zErr); - return GetError(xErr, zErr); -} +float CBurstFire::GetMaxXError() const { return g_tweakPlayer->GetPlayerXYHalfExtent() * 3.625f + 0.2f; } -void CBurstFire::Start(CStateManager& mgr) -{ - s32 burstIdx = -1; - const SBurst* bursts = x1c_burstDefs[x0_burstType]; - if (x10_firstBurstCounter-- > 0) - { - burstIdx = xc_firstBurstIdx < 0 ? 0 : xc_firstBurstIdx; - } - else - { - int random = mgr.GetActiveRandom()->Range(0, 100); - int advanceAccum = 0; - do - { - burstIdx += 1; - s32 advanceWeight = bursts[burstIdx].x0_randomSelectionWeight; - if (advanceWeight == 0) - { - advanceAccum = 100; - burstIdx -= 1; - } - advanceAccum += advanceWeight; - } while (random > advanceAccum); - } - x18_curBursts = &bursts[burstIdx]; - x4_angleIdx = -1; - x8_timeToNextShot = 0.f; - x14_24_shouldFire = false; -} +float CBurstFire::GetMaxZError() const { return g_tweakPlayer->GetEyeOffset(); } -zeus::CVector3f CBurstFire::GetError(float xMag, float zMag) const -{ - zeus::CVector3f ret; - if (x14_24_shouldFire && x18_curBursts) - { - s32 r0 = x18_curBursts->x4_shotAngles[x4_angleIdx]; - if (x14_25_avoidAccuracy && (r0 == 4 || r0 == 12)) - r0 = x4_angleIdx > 0 ? x18_curBursts->x4_shotAngles[x4_angleIdx - 1] : - x18_curBursts->x4_shotAngles[x4_angleIdx + 1]; - if (r0 > 0) - { - float angle = r0 * zeus::degToRad(-22.5f); - ret.x() = std::cos(angle) * xMag; - ret.z() = std::sin(angle) * zMag; - } - } - return ret; -} - -float CBurstFire::GetMaxXError() const -{ - return g_tweakPlayer->GetPlayerXYHalfExtent() * 3.625f + 0.2f; -} - -float CBurstFire::GetMaxZError() const -{ - return g_tweakPlayer->GetEyeOffset(); -} - -} +} // namespace urde diff --git a/Runtime/Weapon/CBurstFire.hpp b/Runtime/Weapon/CBurstFire.hpp index ba4a4d3ab..d2d986629 100644 --- a/Runtime/Weapon/CBurstFire.hpp +++ b/Runtime/Weapon/CBurstFire.hpp @@ -2,47 +2,47 @@ #include "CStateManager.hpp" -namespace urde -{ -struct SBurst -{ - s32 x0_randomSelectionWeight; - s32 x4_shotAngles[8]; - float x24_timeToNextShot; - float x28_timeToNextShotVariance; +namespace urde { +struct SBurst { + s32 x0_randomSelectionWeight; + s32 x4_shotAngles[8]; + float x24_timeToNextShot; + float x28_timeToNextShotVariance; }; -class CBurstFire -{ - s32 x0_burstType = -1; - s32 x4_angleIdx = -1; - float x8_timeToNextShot = 0.f; - s32 xc_firstBurstIdx = 0; - s32 x10_firstBurstCounter; - union - { - struct { bool x14_24_shouldFire : 1; bool x14_25_avoidAccuracy : 1; }; - u32 _dummy = 0; +class CBurstFire { + s32 x0_burstType = -1; + s32 x4_angleIdx = -1; + float x8_timeToNextShot = 0.f; + s32 xc_firstBurstIdx = 0; + s32 x10_firstBurstCounter; + union { + struct { + bool x14_24_shouldFire : 1; + bool x14_25_avoidAccuracy : 1; }; + u32 _dummy = 0; + }; + + const SBurst* x18_curBursts = nullptr; + rstl::reserved_vector x1c_burstDefs; - const SBurst* x18_curBursts = nullptr; - rstl::reserved_vector x1c_burstDefs; public: - CBurstFire(const SBurst** burstDefs, s32 firstBurstCount); + CBurstFire(const SBurst** burstDefs, s32 firstBurstCount); - void SetAvoidAccuracy(bool b) { x14_25_avoidAccuracy = b; } - void SetBurstType(s32 type) { x0_burstType = type; } - void SetTimeToNextShot(float t) { x8_timeToNextShot = t; } - float GetTimeToNextShot() const { return x8_timeToNextShot; } - s32 GetBurstType() const { return x0_burstType; } - void Start(CStateManager& mgr); - void Update(CStateManager& mgr, float dt); - zeus::CVector3f GetError(float xMag, float zMag) const; - zeus::CVector3f GetDistanceCompensatedError(float dist, float maxErrDist) const; - float GetMaxXError() const; - float GetMaxZError() const; - void SetFirstBurstIndex(s32 idx) { xc_firstBurstIdx = idx; } - bool ShouldFire() const { return x14_24_shouldFire; } - bool IsBurstSet() const { return x18_curBursts != nullptr; } + void SetAvoidAccuracy(bool b) { x14_25_avoidAccuracy = b; } + void SetBurstType(s32 type) { x0_burstType = type; } + void SetTimeToNextShot(float t) { x8_timeToNextShot = t; } + float GetTimeToNextShot() const { return x8_timeToNextShot; } + s32 GetBurstType() const { return x0_burstType; } + void Start(CStateManager& mgr); + void Update(CStateManager& mgr, float dt); + zeus::CVector3f GetError(float xMag, float zMag) const; + zeus::CVector3f GetDistanceCompensatedError(float dist, float maxErrDist) const; + float GetMaxXError() const; + float GetMaxZError() const; + void SetFirstBurstIndex(s32 idx) { xc_firstBurstIdx = idx; } + bool ShouldFire() const { return x14_24_shouldFire; } + bool IsBurstSet() const { return x18_curBursts != nullptr; } }; -} +} // namespace urde diff --git a/Runtime/Weapon/CEnergyProjectile.cpp b/Runtime/Weapon/CEnergyProjectile.cpp index 75cec6741..27bd35e8a 100644 --- a/Runtime/Weapon/CEnergyProjectile.cpp +++ b/Runtime/Weapon/CEnergyProjectile.cpp @@ -12,8 +12,7 @@ #include "CSimplePool.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CEnergyProjectile::CEnergyProjectile(bool active, const TToken& desc, EWeaponType type, const zeus::CTransform& xf, EMaterialTypes excludeMat, const CDamageInfo& damage, @@ -21,411 +20,350 @@ CEnergyProjectile::CEnergyProjectile(bool active, const TToken>& visorParticle, u16 visorSfx, bool sendCollideMsg) -: CGameProjectile(active, desc, "GameProjectile", type, xf, excludeMat, damage, uid, aid, - owner, homingTarget, attribs, underwater, scale, visorParticle, visorSfx, sendCollideMsg), - x2ec_dir(xf.basis[1]), x2f8_mag(x2ec_dir.magnitude()), - x2fc_camShake(CCameraShakeData::BuildProjectileCameraShake(0.5f, 0.75f)) -{ - xe6_27_thermalVisorFlags = 2; +: CGameProjectile(active, desc, "GameProjectile", type, xf, excludeMat, damage, uid, aid, owner, homingTarget, attribs, + underwater, scale, visorParticle, visorSfx, sendCollideMsg) +, x2ec_dir(xf.basis[1]) +, x2f8_mag(x2ec_dir.magnitude()) +, x2fc_camShake(CCameraShakeData::BuildProjectileCameraShake(0.5f, 0.75f)) { + xe6_27_thermalVisorFlags = 2; } -void CEnergyProjectile::PlayImpactSound(const zeus::CVector3f& pos, EWeaponCollisionResponseTypes type) -{ - s32 sfxId = x170_projectile.GetSoundIdForCollision(type); - if (sfxId >= 0) - { - CAudioSys::C3DEmitterParmData parmData = {}; - parmData.x18_maxDist = x170_projectile.GetAudibleRange(); - parmData.x1c_distComp = x170_projectile.GetAudibleFallOff(); - parmData.x20_flags = 0x1; // Continuous parameter update - parmData.x24_sfxId = CSfxManager::TranslateSFXID(u16(sfxId)); - parmData.x26_maxVol = 1.f; - parmData.x27_minVol = 0.16f; - parmData.x29_prio = 0x7f; - CSfxHandle hnd = CSfxManager::AddEmitter(parmData, true, 0x7f, false, kInvalidAreaId); - if (x2e4_26_waterUpdate) - CSfxManager::PitchBend(hnd, -1.f); +void CEnergyProjectile::PlayImpactSound(const zeus::CVector3f& pos, EWeaponCollisionResponseTypes type) { + s32 sfxId = x170_projectile.GetSoundIdForCollision(type); + if (sfxId >= 0) { + CAudioSys::C3DEmitterParmData parmData = {}; + parmData.x18_maxDist = x170_projectile.GetAudibleRange(); + parmData.x1c_distComp = x170_projectile.GetAudibleFallOff(); + parmData.x20_flags = 0x1; // Continuous parameter update + parmData.x24_sfxId = CSfxManager::TranslateSFXID(u16(sfxId)); + parmData.x26_maxVol = 1.f; + parmData.x27_minVol = 0.16f; + parmData.x29_prio = 0x7f; + CSfxHandle hnd = CSfxManager::AddEmitter(parmData, true, 0x7f, false, kInvalidAreaId); + if (x2e4_26_waterUpdate) + CSfxManager::PitchBend(hnd, -1.f); + } +} + +void CEnergyProjectile::ChangeProjectileOwner(TUniqueId owner, CStateManager& mgr) { + if (TCastToConstPtr act = mgr.GetObjectById(owner)) { + float rDam = g_tweakPlayerGun->GetRichochetDamage(u32(x110_origDamageInfo.GetWeaponMode().GetType())); + x110_origDamageInfo.MultiplyDamageAndRadius(rDam); + mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); + xec_ownerId = owner; + mgr.AddWeaponId(xec_ownerId, xf0_weaponType); + + /* Can now damage Player */ + xf8_filter.ExcludeList().Add(EMaterialTypes::Character); + xf8_filter.ExcludeList().Remove(EMaterialTypes::Player); + xf8_filter = CMaterialFilter::MakeIncludeExclude(xf8_filter.GetIncludeList(), xf8_filter.GetExcludeList()); + } +} + +void CEnergyProjectile::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Deleted: + if (x2e4_24_active) + mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); + if (x2e8_sfx) { + CSfxManager::RemoveEmitter(x2e8_sfx); + x2e8_sfx.reset(); } -} + break; + case EScriptObjectMessage::Registered: { + if (CElementGen* ps1 = x170_projectile.GetAttachedPS1()) + if (ps1->SystemHasLight()) + CreateProjectileLight("ProjectileLight_GameProjectile", ps1->GetLight(), mgr); + TLockedToken desc = x170_projectile.GetWeaponDescription(); + s32 sfx = desc->xa8_PJFX; + if (sfx != -1) { + float range = 50.f; + float falloff = 0.2f; + if (CRealElement* rnge = desc->xac_RNGE.get()) + rnge->GetValue(0, range); + if (CRealElement* foff = desc->xb0_FOFF.get()) + foff->GetValue(0, falloff); -void CEnergyProjectile::ChangeProjectileOwner(TUniqueId owner, CStateManager& mgr) -{ - if (TCastToConstPtr act = mgr.GetObjectById(owner)) - { - float rDam = g_tweakPlayerGun->GetRichochetDamage(u32(x110_origDamageInfo.GetWeaponMode().GetType())); - x110_origDamageInfo.MultiplyDamageAndRadius(rDam); - mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); - xec_ownerId = owner; - mgr.AddWeaponId(xec_ownerId, xf0_weaponType); - - /* Can now damage Player */ - xf8_filter.ExcludeList().Add(EMaterialTypes::Character); - xf8_filter.ExcludeList().Remove(EMaterialTypes::Player); - xf8_filter = CMaterialFilter::MakeIncludeExclude(xf8_filter.GetIncludeList(), xf8_filter.GetExcludeList()); + CAudioSys::C3DEmitterParmData parmData = {}; + parmData.x0_pos = x170_projectile.GetTranslation(); + parmData.xc_dir = x170_projectile.GetVelocity(); + parmData.x18_maxDist = range; + parmData.x1c_distComp = falloff; + parmData.x20_flags = 0x9; // Continuous parameter update, doppler + parmData.x24_sfxId = CSfxManager::TranslateSFXID(sfx); + parmData.x26_maxVol = 1.f; + parmData.x27_minVol = 0.16f; + parmData.x29_prio = 0x7f; + x2e8_sfx = CSfxManager::AddEmitter(parmData, true, 0x7f, false, kInvalidAreaId); } + mgr.AddWeaponId(xec_ownerId, xf0_weaponType); + break; + } + default: + break; + } + CGameProjectile::AcceptScriptMsg(msg, sender, mgr); } -void CEnergyProjectile::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Deleted: - if (x2e4_24_active) - mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); - if (x2e8_sfx) - { - CSfxManager::RemoveEmitter(x2e8_sfx); - x2e8_sfx.reset(); - } - break; - case EScriptObjectMessage::Registered: - { - if (CElementGen* ps1 = x170_projectile.GetAttachedPS1()) - if (ps1->SystemHasLight()) - CreateProjectileLight("ProjectileLight_GameProjectile", ps1->GetLight(), mgr); - TLockedToken desc = x170_projectile.GetWeaponDescription(); - s32 sfx = desc->xa8_PJFX; - if (sfx != -1) - { - float range = 50.f; - float falloff = 0.2f; - if (CRealElement* rnge = desc->xac_RNGE.get()) - rnge->GetValue(0, range); - if (CRealElement* foff = desc->xb0_FOFF.get()) - foff->GetValue(0, falloff); - - CAudioSys::C3DEmitterParmData parmData = {}; - parmData.x0_pos = x170_projectile.GetTranslation(); - parmData.xc_dir = x170_projectile.GetVelocity(); - parmData.x18_maxDist = range; - parmData.x1c_distComp = falloff; - parmData.x20_flags = 0x9; // Continuous parameter update, doppler - parmData.x24_sfxId = CSfxManager::TranslateSFXID(sfx); - parmData.x26_maxVol = 1.f; - parmData.x27_minVol = 0.16f; - parmData.x29_prio = 0x7f; - x2e8_sfx = CSfxManager::AddEmitter(parmData, true, 0x7f, false, kInvalidAreaId); - } - mgr.AddWeaponId(xec_ownerId, xf0_weaponType); - break; - } - default: - break; - } - CGameProjectile::AcceptScriptMsg(msg, sender, mgr); -} - -void CEnergyProjectile::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CEnergyProjectile::Accept(IVisitor& visitor) { visitor.Visit(this); } /* Material surface types only (not meta flags) */ static constexpr u64 kCheckMaterial = 0xE3FFFE; -void CEnergyProjectile::ResolveCollisionWithWorld(const CRayCastResult& res, CStateManager& mgr) -{ - EWeaponCollisionResponseTypes crType = CCollisionResponseData::GetWorldCollisionResponseType( - CMaterialList::BitPosition((res.GetMaterial().GetValue() & 0xffffffff) & kCheckMaterial)); - if ((xe8_projectileAttribs & (EProjectileAttrib::Wave | EProjectileAttrib::ComboShot)) != - (EProjectileAttrib::Wave | EProjectileAttrib::ComboShot)) - { - /* Not wavebuster */ - if (Explode(res.GetPoint(), res.GetPlane().normal(), crType, mgr, - CDamageVulnerability::NormalVulnerabilty(), kInvalidUniqueId)) - mgr.ApplyDamageToWorld(xec_ownerId, *this, res.GetPoint(), x12c_curDamageInfo, xf8_filter); - x2c2_lastResolvedObj = kInvalidUniqueId; - } +void CEnergyProjectile::ResolveCollisionWithWorld(const CRayCastResult& res, CStateManager& mgr) { + EWeaponCollisionResponseTypes crType = CCollisionResponseData::GetWorldCollisionResponseType( + CMaterialList::BitPosition((res.GetMaterial().GetValue() & 0xffffffff) & kCheckMaterial)); + if ((xe8_projectileAttribs & (EProjectileAttrib::Wave | EProjectileAttrib::ComboShot)) != + (EProjectileAttrib::Wave | EProjectileAttrib::ComboShot)) { + /* Not wavebuster */ + if (Explode(res.GetPoint(), res.GetPlane().normal(), crType, mgr, CDamageVulnerability::NormalVulnerabilty(), + kInvalidUniqueId)) + mgr.ApplyDamageToWorld(xec_ownerId, *this, res.GetPoint(), x12c_curDamageInfo, xf8_filter); + x2c2_lastResolvedObj = kInvalidUniqueId; + } } -void CEnergyProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr) -{ - x2c2_lastResolvedObj = act.GetUniqueId(); - EWeaponCollisionResponseTypes crType = - act.GetCollisionResponseType(res.GetPoint(), x34_transform.basis[1].normalized(), - x12c_curDamageInfo.GetWeaponMode(), xe8_projectileAttribs); - act.Touch(*this, mgr); - const CDamageVulnerability* dVuln = act.GetDamageVulnerability(); - if (!Explode(res.GetPoint(), res.GetPlane().normal(), crType, mgr, *dVuln, act.GetUniqueId())) - { - mgr.SendScriptMsg(&act, GetUniqueId(), EScriptObjectMessage::Touched); - act.SendScriptMsgs(EScriptObjectState::ReflectedDamage, mgr, EScriptObjectMessage::None); - } +void CEnergyProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr) { + x2c2_lastResolvedObj = act.GetUniqueId(); + EWeaponCollisionResponseTypes crType = act.GetCollisionResponseType( + res.GetPoint(), x34_transform.basis[1].normalized(), x12c_curDamageInfo.GetWeaponMode(), xe8_projectileAttribs); + act.Touch(*this, mgr); + const CDamageVulnerability* dVuln = act.GetDamageVulnerability(); + if (!Explode(res.GetPoint(), res.GetPlane().normal(), crType, mgr, *dVuln, act.GetUniqueId())) { + mgr.SendScriptMsg(&act, GetUniqueId(), EScriptObjectMessage::Touched); + act.SendScriptMsgs(EScriptObjectState::ReflectedDamage, mgr, EScriptObjectMessage::None); + } else { + CGameProjectile::ResolveCollisionWithActor(res, act, mgr); + ApplyDamageToActors(mgr, x12c_curDamageInfo); + } + if (TCastToPtr proj = act) { + proj->Explode(GetTranslation(), x34_transform.basis[1], EWeaponCollisionResponseTypes::OtherProjectile, mgr, + *GetDamageVulnerability(), GetUniqueId()); + } +} + +void CEnergyProjectile::Think(float dt, CStateManager& mgr) { + CWeapon::Think(dt, mgr); + if (mgr.GetWorld()->GetCurrentAreaId() != GetAreaIdAlways() && + (xe8_projectileAttribs & EProjectileAttrib::ArmCannon) == EProjectileAttrib::ArmCannon) + mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId()); + + UpdateProjectileMovement(dt, mgr); + TUniqueId id = kInvalidUniqueId; + CRayCastResult res = DoCollisionCheck(id, mgr); + if (res.IsValid()) { + if (TCastToPtr act = mgr.ObjectById(id)) + ResolveCollisionWithActor(res, *act, mgr); else - { - CGameProjectile::ResolveCollisionWithActor(res, act, mgr); - ApplyDamageToActors(mgr, x12c_curDamageInfo); - } - if (TCastToPtr proj = act) - { - proj->Explode(GetTranslation(), x34_transform.basis[1], - EWeaponCollisionResponseTypes::OtherProjectile, - mgr, *GetDamageVulnerability(), GetUniqueId()); + ResolveCollisionWithWorld(res, mgr); + } + + x170_projectile.UpdateParticleFX(); + if (x2e4_24_active && x3d0_26_) + Explode(GetTranslation(), zeus::CVector3f::skUp, EWeaponCollisionResponseTypes::Default, mgr, + CDamageVulnerability::NormalVulnerabilty(), kInvalidUniqueId); + + if (x2c8_projectileLight != kInvalidUniqueId) { + if (TCastToPtr light = mgr.ObjectById(x2c8_projectileLight)) { + light->SetTransform(GetTransform()); + light->SetTranslation(GetTranslation()); + if (CElementGen* ps1 = x170_projectile.GetAttachedPS1()) + if (ps1->SystemHasLight()) + light->SetLight(ps1->GetLight()); } + } + + if (x2e8_sfx) { + CSfxManager::UpdateEmitter(x2e8_sfx, x170_projectile.GetTranslation(), x170_projectile.GetVelocity(), 1.f); + CSfxManager::PitchBend(x2e8_sfx, x2e4_26_waterUpdate ? -1.f : 0.f); + } + + x3d4_curTime += dt; + if (x3d4_curTime > 45.f || x170_projectile.IsSystemDeletable() || x3d0_24_dead) + mgr.FreeScriptObject(GetUniqueId()); } -void CEnergyProjectile::Think(float dt, CStateManager& mgr) -{ - CWeapon::Think(dt, mgr); - if (mgr.GetWorld()->GetCurrentAreaId() != GetAreaIdAlways() && - (xe8_projectileAttribs & EProjectileAttrib::ArmCannon) == EProjectileAttrib::ArmCannon) - mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId()); - - UpdateProjectileMovement(dt, mgr); - TUniqueId id = kInvalidUniqueId; - CRayCastResult res = DoCollisionCheck(id, mgr); - if (res.IsValid()) - { - if (TCastToPtr act = mgr.ObjectById(id)) - ResolveCollisionWithActor(res, *act, mgr); - else - ResolveCollisionWithWorld(res, mgr); +void CEnergyProjectile::Render(const CStateManager& mgr) const { + CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); + if (visor == CPlayerState::EPlayerVisor::Combat) { + if ((xe8_projectileAttribs & EProjectileAttrib::Charged) == EProjectileAttrib::Charged || + (xe8_projectileAttribs & EProjectileAttrib::ComboShot) == EProjectileAttrib::ComboShot) { + float warpTime = 1.f - float(x170_projectile.GameTime()); + if (warpTime > 0.f) + mgr.DrawSpaceWarp(GetTranslation(), warpTime * 0.75f); } + } - x170_projectile.UpdateParticleFX(); - if (x2e4_24_active && x3d0_26_) - Explode(GetTranslation(), zeus::CVector3f::skUp, EWeaponCollisionResponseTypes::Default, mgr, - CDamageVulnerability::NormalVulnerabilty(), kInvalidUniqueId); - - if (x2c8_projectileLight != kInvalidUniqueId) - { - if (TCastToPtr light = mgr.ObjectById(x2c8_projectileLight)) - { - light->SetTransform(GetTransform()); - light->SetTranslation(GetTranslation()); - if (CElementGen* ps1 = x170_projectile.GetAttachedPS1()) - if (ps1->SystemHasLight()) - light->SetLight(ps1->GetLight()); - } - } - - if (x2e8_sfx) - { - CSfxManager::UpdateEmitter(x2e8_sfx, x170_projectile.GetTranslation(), x170_projectile.GetVelocity(), 1.f); - CSfxManager::PitchBend(x2e8_sfx, x2e4_26_waterUpdate ? -1.f : 0.f); - } - - x3d4_curTime += dt; - if (x3d4_curTime > 45.f || x170_projectile.IsSystemDeletable() || x3d0_24_dead) - mgr.FreeScriptObject(GetUniqueId()); + if (visor == CPlayerState::EPlayerVisor::XRay) { + CElementGen::SetSubtractBlend((xe8_projectileAttribs & EProjectileAttrib::Ice) != EProjectileAttrib::Ice); + CGraphics::SetFog(ERglFogMode::PerspLin, 0.f, 75.f, zeus::CColor::skBlack); + x170_projectile.RenderParticles(); + CGameProjectile::Render(mgr); + mgr.SetupFogForArea(GetAreaIdAlways()); + CElementGen::SetSubtractBlend(false); + } else if ((xe8_projectileAttribs & EProjectileAttrib::Ice) == EProjectileAttrib::Ice && + mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) { + CElementGen::SetSubtractBlend(true); + x170_projectile.RenderParticles(); + CGameProjectile::Render(mgr); + mgr.SetupFogForArea(GetAreaIdAlways()); + CElementGen::SetSubtractBlend(false); + } else { + CGameProjectile::Render(mgr); + } } -void CEnergyProjectile::Render(const CStateManager& mgr) const -{ - CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); - if (visor == CPlayerState::EPlayerVisor::Combat) - { - if ((xe8_projectileAttribs & EProjectileAttrib::Charged) == EProjectileAttrib::Charged || - (xe8_projectileAttribs & EProjectileAttrib::ComboShot) == EProjectileAttrib::ComboShot) - { - float warpTime = 1.f - float(x170_projectile.GameTime()); - if (warpTime > 0.f) - mgr.DrawSpaceWarp(GetTranslation(), warpTime * 0.75f); - } - } +void CEnergyProjectile::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + auto bounds = x170_projectile.GetBounds(); + if (bounds && !frustum.aabbFrustumTest(*bounds)) + return; - if (visor == CPlayerState::EPlayerVisor::XRay) - { - CElementGen::SetSubtractBlend((xe8_projectileAttribs & EProjectileAttrib::Ice) != EProjectileAttrib::Ice); - CGraphics::SetFog(ERglFogMode::PerspLin, 0.f, 75.f, zeus::CColor::skBlack); - x170_projectile.RenderParticles(); - CGameProjectile::Render(mgr); - mgr.SetupFogForArea(GetAreaIdAlways()); - CElementGen::SetSubtractBlend(false); - } - else if ((xe8_projectileAttribs & EProjectileAttrib::Ice) == EProjectileAttrib::Ice && - mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) - { - CElementGen::SetSubtractBlend(true); - x170_projectile.RenderParticles(); - CGameProjectile::Render(mgr); - mgr.SetupFogForArea(GetAreaIdAlways()); - CElementGen::SetSubtractBlend(false); - } - else - { - CGameProjectile::Render(mgr); - } + CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); + if (visor != CPlayerState::EPlayerVisor::XRay && + ((xe8_projectileAttribs & EProjectileAttrib::Ice) != EProjectileAttrib::Ice || + mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot)) + x170_projectile.AddToRenderer(); + EnsureRendered(mgr); } -void CEnergyProjectile::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - auto bounds = x170_projectile.GetBounds(); - if (bounds && !frustum.aabbFrustumTest(*bounds)) - return; - - CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); - if (visor != CPlayerState::EPlayerVisor::XRay && - ((xe8_projectileAttribs & EProjectileAttrib::Ice) != EProjectileAttrib::Ice || - mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot)) - x170_projectile.AddToRenderer(); - EnsureRendered(mgr); -} - -void CEnergyProjectile::Touch(CActor& act, CStateManager& mgr) -{ - // Empty +void CEnergyProjectile::Touch(CActor& act, CStateManager& mgr) { + // Empty } bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3f& normal, EWeaponCollisionResponseTypes type, CStateManager& mgr, - const CDamageVulnerability& dVuln, TUniqueId hitActor) -{ - zeus::CVector3f offsetPos = pos + normal * 0.01f; - bool done = true; - bool retargetPlayer = false; - bool deflect = false; - zeus::CVector3f targetPos; - EVulnerability vulnType = dVuln.GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false); - if (vulnType == EVulnerability::Deflect) - { - deflect = true; - EVulnerability deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode()); - switch (deflectType) - { - case EVulnerability::Weak: - deflect = false; - break; - case EVulnerability::Deflect: - case EVulnerability::Immune: - if (deflectType != EVulnerability::Deflect || - (xf0_weaponType != EWeaponType::Missile && - (xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::ComboShot)) - if (xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player)) - retargetPlayer = true; - break; - default: - break; + const CDamageVulnerability& dVuln, TUniqueId hitActor) { + zeus::CVector3f offsetPos = pos + normal * 0.01f; + bool done = true; + bool retargetPlayer = false; + bool deflect = false; + zeus::CVector3f targetPos; + EVulnerability vulnType = dVuln.GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false); + if (vulnType == EVulnerability::Deflect) { + deflect = true; + EVulnerability deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode()); + switch (deflectType) { + case EVulnerability::Weak: + deflect = false; + break; + case EVulnerability::Deflect: + case EVulnerability::Immune: + if (deflectType != EVulnerability::Deflect || + (xf0_weaponType != EWeaponType::Missile && + (xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::ComboShot)) + if (xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player)) + retargetPlayer = true; + break; + default: + break; + } + if (retargetPlayer) { + float ang = mgr.GetActiveRandom()->Range(0.f, 2.f * M_PIF); + float y = std::sin(ang); + float x = std::cos(ang); + targetPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f) + zeus::CVector3f(x, 0.f, y); + ChangeProjectileOwner(hitActor, mgr); + } + } + + if (vulnType != EVulnerability::Immune && !deflect) { + deflect = + (type == EWeaponCollisionResponseTypes::Unknown15 || type == EWeaponCollisionResponseTypes::EnemyShielded || + (type >= EWeaponCollisionResponseTypes::Unknown69 && type <= EWeaponCollisionResponseTypes::Unknown93)); + } + + SetTranslation(offsetPos); + + if (deflect) { + done = false; + x2c0_homingTargetId = kInvalidUniqueId; + x3d0_25_ = false; + } else { + StopProjectile(mgr); + if (x3d0_27_camShakeDirty) { + x2fc_camShake.SetSfxPositionAndDistance(pos, 50.f); + mgr.GetCameraManager()->AddCameraShaker(x2fc_camShake, false); + } + } + + PlayImpactSound(pos, type); + mgr.InformListeners(pos, EListenNoiseType::ProjectileExplode); + if (auto particle = x170_projectile.CollisionOccured(type, !done, retargetPlayer, offsetPos, normal, targetPos)) { + zeus::CTransform particleXf = zeus::lookAt(zeus::CVector3f::skZero, normal); + particleXf.origin = offsetPos; + if (xf0_weaponType != EWeaponType::Power || !xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player) || + !x2e4_27_inWater) { + if (auto decal = x170_projectile.GetDecalForCollision(type)) { + CDecalManager::AddDecal(*decal, particleXf, + (xe8_projectileAttribs & EProjectileAttrib::Ice) != EProjectileAttrib::Ice, mgr); + } + zeus::CVector3f scale = zeus::CVector3f::skOne; + bool camClose = false; + if (mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) { + float mag = (offsetPos - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation()).magnitude(); + if (mag < 4.f) { + scale = zeus::CVector3f(0.75f * (mag * 0.25f) + 0.25f); + camClose = true; } - if (retargetPlayer) - { - float ang = mgr.GetActiveRandom()->Range(0.f, 2.f * M_PIF); - float y = std::sin(ang); - float x = std::cos(ang); - targetPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f) + zeus::CVector3f(x, 0.f, y); - ChangeProjectileOwner(hitActor, mgr); - } - } - - if (vulnType != EVulnerability::Immune && !deflect) - { - deflect = (type == EWeaponCollisionResponseTypes::Unknown15 || - type == EWeaponCollisionResponseTypes::EnemyShielded || - (type >= EWeaponCollisionResponseTypes::Unknown69 && - type <= EWeaponCollisionResponseTypes::Unknown93)); - } - - SetTranslation(offsetPos); - - if (deflect) - { - done = false; - x2c0_homingTargetId = kInvalidUniqueId; - x3d0_25_ = false; - } - else - { - StopProjectile(mgr); - if (x3d0_27_camShakeDirty) - { - x2fc_camShake.SetSfxPositionAndDistance(pos, 50.f); - mgr.GetCameraManager()->AddCameraShaker(x2fc_camShake, false); - } - } - - PlayImpactSound(pos, type); - mgr.InformListeners(pos, EListenNoiseType::ProjectileExplode); - if (auto particle = x170_projectile.CollisionOccured(type, !done, retargetPlayer, offsetPos, normal, targetPos)) - { - zeus::CTransform particleXf = zeus::lookAt(zeus::CVector3f::skZero, normal); - particleXf.origin = offsetPos; - if (xf0_weaponType != EWeaponType::Power || - !xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player) || - !x2e4_27_inWater) - { - if (auto decal = x170_projectile.GetDecalForCollision(type)) - { - CDecalManager::AddDecal(*decal, particleXf, - (xe8_projectileAttribs & EProjectileAttrib::Ice) != EProjectileAttrib::Ice, mgr); - } - zeus::CVector3f scale = zeus::CVector3f::skOne; - bool camClose = false; - if (mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) - { - float mag = (offsetPos - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation()).magnitude(); - if (mag < 4.f) - { - scale = zeus::CVector3f(0.75f * (mag * 0.25f) + 0.25f); - camClose = true; - } - } - u32 explodeFlags = 0x8; - if ((xe8_projectileAttribs & EProjectileAttrib::Ice) == EProjectileAttrib::Ice) - explodeFlags |= 0x4; - if (camClose) - explodeFlags |= 0x2; - CEntityInfo explosionInfo(GetAreaIdAlways(), CEntity::NullConnectionList); - CExplosion* explosion = new CExplosion(*particle, mgr.AllocateUniqueId(), true, explosionInfo, - "Projectile collision response", particleXf, explodeFlags, scale, zeus::CColor::skWhite); - mgr.AddObject(explosion); - if (TCastToPtr hActor = mgr.ObjectById(hitActor)) - { - bool validPlat = false; - CScriptPlatform* plat = TCastToPtr(hActor.GetPtr()).GetPtr(); - validPlat = plat != nullptr; - if (!validPlat && hActor->GetMaterialList().HasMaterial(EMaterialTypes::Bomb)) - { - for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) - { - if (TCastToPtr otherPlat = ent) - { - if (otherPlat->IsSlave(hitActor)) - { - plat = otherPlat.GetPtr(); - validPlat = true; - break; - } - } - } - } - if (validPlat) - plat->AddSlave(explosion->GetUniqueId(), mgr); + } + u32 explodeFlags = 0x8; + if ((xe8_projectileAttribs & EProjectileAttrib::Ice) == EProjectileAttrib::Ice) + explodeFlags |= 0x4; + if (camClose) + explodeFlags |= 0x2; + CEntityInfo explosionInfo(GetAreaIdAlways(), CEntity::NullConnectionList); + CExplosion* explosion = + new CExplosion(*particle, mgr.AllocateUniqueId(), true, explosionInfo, "Projectile collision response", + particleXf, explodeFlags, scale, zeus::CColor::skWhite); + mgr.AddObject(explosion); + if (TCastToPtr hActor = mgr.ObjectById(hitActor)) { + bool validPlat = false; + CScriptPlatform* plat = TCastToPtr(hActor.GetPtr()).GetPtr(); + validPlat = plat != nullptr; + if (!validPlat && hActor->GetMaterialList().HasMaterial(EMaterialTypes::Bomb)) { + for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) { + if (TCastToPtr otherPlat = ent) { + if (otherPlat->IsSlave(hitActor)) { + plat = otherPlat.GetPtr(); + validPlat = true; + break; + } } + } } - else - { - x3d0_24_dead = true; - } - - if ((xe8_projectileAttribs & (EProjectileAttrib::ComboShot | EProjectileAttrib::Ice)) == - (EProjectileAttrib::ComboShot | EProjectileAttrib::Ice)) - { - /* Ice Spreader */ - TLockedToken iceSpreadParticle = g_SimplePool->GetObj("IceSpread1"); - u32 flags = (xe6_27_thermalVisorFlags & 0x2) == 0 ? 1 : 0; - flags |= 0x2; - CIceImpact* iceImpact = new CIceImpact(iceSpreadParticle, mgr.AllocateUniqueId(), GetAreaIdAlways(), - true, "Ice spread explosion", particleXf, flags, - zeus::CVector3f::skOne, zeus::CColor::skWhite); - mgr.AddObject(iceImpact); - } + if (validPlat) + plat->AddSlave(explosion->GetUniqueId(), mgr); + } + } else { + x3d0_24_dead = true; } - return done; + if ((xe8_projectileAttribs & (EProjectileAttrib::ComboShot | EProjectileAttrib::Ice)) == + (EProjectileAttrib::ComboShot | EProjectileAttrib::Ice)) { + /* Ice Spreader */ + TLockedToken iceSpreadParticle = g_SimplePool->GetObj("IceSpread1"); + u32 flags = (xe6_27_thermalVisorFlags & 0x2) == 0 ? 1 : 0; + flags |= 0x2; + CIceImpact* iceImpact = + new CIceImpact(iceSpreadParticle, mgr.AllocateUniqueId(), GetAreaIdAlways(), true, "Ice spread explosion", + particleXf, flags, zeus::CVector3f::skOne, zeus::CColor::skWhite); + mgr.AddObject(iceImpact); + } + } + + return done; } -void CEnergyProjectile::StopProjectile(CStateManager& mgr) -{ - DeleteProjectileLight(mgr); - mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); - x2e4_24_active = false; - x68_material = CMaterialList(); - mgr.UpdateActorInSortedLists(*this); - if (x2e8_sfx) - { - CSfxManager::RemoveEmitter(x2e8_sfx); - x2e8_sfx.reset(); - } +void CEnergyProjectile::StopProjectile(CStateManager& mgr) { + DeleteProjectileLight(mgr); + mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); + x2e4_24_active = false; + x68_material = CMaterialList(); + mgr.UpdateActorInSortedLists(*this); + if (x2e8_sfx) { + CSfxManager::RemoveEmitter(x2e8_sfx); + x2e8_sfx.reset(); + } } -} +} // namespace urde diff --git a/Runtime/Weapon/CEnergyProjectile.hpp b/Runtime/Weapon/CEnergyProjectile.hpp index b3ee52d16..a6e034456 100644 --- a/Runtime/Weapon/CEnergyProjectile.hpp +++ b/Runtime/Weapon/CEnergyProjectile.hpp @@ -3,49 +3,47 @@ #include "CGameProjectile.hpp" #include "Camera/CCameraShakeData.hpp" -namespace urde -{ +namespace urde { -class CEnergyProjectile : public CGameProjectile -{ - CSfxHandle x2e8_sfx; - zeus::CVector3f x2ec_dir; - float x2f8_mag; - CCameraShakeData x2fc_camShake; - union - { - struct - { - bool x3d0_24_dead : 1; - bool x3d0_25_ : 1; - bool x3d0_26_ : 1; - bool x3d0_27_camShakeDirty : 1; - }; - u32 _dummy = 0; +class CEnergyProjectile : public CGameProjectile { + CSfxHandle x2e8_sfx; + zeus::CVector3f x2ec_dir; + float x2f8_mag; + CCameraShakeData x2fc_camShake; + union { + struct { + bool x3d0_24_dead : 1; + bool x3d0_25_ : 1; + bool x3d0_26_ : 1; + bool x3d0_27_camShakeDirty : 1; }; - float x3d4_curTime = 0.f; - void StopProjectile(CStateManager& mgr); + u32 _dummy = 0; + }; + float x3d4_curTime = 0.f; + void StopProjectile(CStateManager& mgr); + public: - CEnergyProjectile(bool active, const TToken& desc, EWeaponType type, - const zeus::CTransform& xf, EMaterialTypes excludeMat, const CDamageInfo& damage, - TUniqueId uid, TAreaId aid, TUniqueId owner, TUniqueId homingTarget, - EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale, - const std::experimental::optional>& visorParticle, - u16 visorSfx, bool sendCollideMsg); - void SetCameraShake(const CCameraShakeData& data) { x2fc_camShake = data; x3d0_27_camShakeDirty = true; } - void PlayImpactSound(const zeus::CVector3f& pos, EWeaponCollisionResponseTypes type); - void ChangeProjectileOwner(TUniqueId owner, CStateManager& mgr); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - void Accept(IVisitor& visitor); - void ResolveCollisionWithWorld(const CRayCastResult& res, CStateManager& mgr); - void ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr); - void Think(float dt, CStateManager& mgr); - void Render(const CStateManager& mgr) const; - void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; - void Touch(CActor& act, CStateManager& mgr); - virtual bool Explode(const zeus::CVector3f& pos, const zeus::CVector3f& normal, EWeaponCollisionResponseTypes type, - CStateManager& mgr, const CDamageVulnerability& dVuln, TUniqueId hitActor); + CEnergyProjectile(bool active, const TToken& desc, EWeaponType type, const zeus::CTransform& xf, + EMaterialTypes excludeMat, const CDamageInfo& damage, TUniqueId uid, TAreaId aid, TUniqueId owner, + TUniqueId homingTarget, EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale, + const std::experimental::optional>& visorParticle, u16 visorSfx, + bool sendCollideMsg); + void SetCameraShake(const CCameraShakeData& data) { + x2fc_camShake = data; + x3d0_27_camShakeDirty = true; + } + void PlayImpactSound(const zeus::CVector3f& pos, EWeaponCollisionResponseTypes type); + void ChangeProjectileOwner(TUniqueId owner, CStateManager& mgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + void Accept(IVisitor& visitor); + void ResolveCollisionWithWorld(const CRayCastResult& res, CStateManager& mgr); + void ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr); + void Think(float dt, CStateManager& mgr); + void Render(const CStateManager& mgr) const; + void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; + void Touch(CActor& act, CStateManager& mgr); + virtual bool Explode(const zeus::CVector3f& pos, const zeus::CVector3f& normal, EWeaponCollisionResponseTypes type, + CStateManager& mgr, const CDamageVulnerability& dVuln, TUniqueId hitActor); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CFidget.cpp b/Runtime/Weapon/CFidget.cpp index 52d965496..d89722572 100644 --- a/Runtime/Weapon/CFidget.cpp +++ b/Runtime/Weapon/CFidget.cpp @@ -2,160 +2,137 @@ #include "CStateManager.hpp" #include "World/CPlayer.hpp" -namespace urde -{ +namespace urde { static float kMinorFidgetDelay = 20.f; static float kMajorFidgetDelay = 20.f; -CFidget::EState CFidget::Update(int fireButtonStates, bool bobbing, - bool inStrikeCooldown, float dt, CStateManager& mgr) -{ - switch (x0_state) - { - case EState::NoFidget: - break; - case EState::MinorFidget: - return x34_24_loading ? EState::Loading : EState::StillMinorFidget; - case EState::MajorFidget: - return x34_24_loading ? EState::Loading : EState::StillMajorFidget; - case EState::HolsterBeam: - return x34_24_loading ? EState::Loading : EState::StillHolsterBeam; - default: - x0_state = EState::NoFidget; - break; - } - - if (fireButtonStates != 0) - { - x14_timeSinceFire = 0.f; - x2c_holsterTimeSinceFire = 0.f; - } - else - { - if (x14_timeSinceFire < 6.f) - x14_timeSinceFire += dt; - if (x2c_holsterTimeSinceFire < x30_timeUntilHolster + 1.f) - x2c_holsterTimeSinceFire += dt; - } - - if (inStrikeCooldown) - x18_timeSinceStrikeCooldown = 0.f; - else if (x18_timeSinceStrikeCooldown < 11.f) - x18_timeSinceStrikeCooldown += dt; - - if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) - { - if (x1c_timeSinceUnmorph < 21.f) - x1c_timeSinceUnmorph += dt; - } - else - { - x1c_timeSinceUnmorph = 0.f; - } - - if (bobbing) - x20_timeSinceBobbing = 0.f; - else if (x20_timeSinceBobbing < 21.f) - x20_timeSinceBobbing += dt; - - u32 pendingTriggerBits = 0; - if (x0_state == EState::NoFidget) - { - if ((x10_delayTimerEnableBits & 0x1) != 0) - { - x24_minorDelayTimer += dt; - if (x24_minorDelayTimer > kMinorFidgetDelay) - { - pendingTriggerBits |= 0x1; - x24_minorDelayTimer = 0.f; - } - } - - if ((x10_delayTimerEnableBits & 0x2) != 0) - { - x28_majorDelayTimer += dt; - if (x28_majorDelayTimer > kMajorFidgetDelay) - { - pendingTriggerBits |= 0x2; - x28_majorDelayTimer = 0.f; - } - } - } - - if (x2c_holsterTimeSinceFire > x30_timeUntilHolster) - { - x0_state = EState::HolsterBeam; - } - else - { - if (x18_timeSinceStrikeCooldown > 10.f && x1c_timeSinceUnmorph > 20.f && x20_timeSinceBobbing > 20.f) - { - if ((pendingTriggerBits & 0x1) != 0) - x8_delayTriggerBits |= 0x1; - else if ((pendingTriggerBits & 0x2) != 0) - x8_delayTriggerBits |= 0x2; - } - - if ((x8_delayTriggerBits & 0x3) == 0x3) - x0_state = (mgr.GetActiveRandom()->Next() % 100) >= 50 ? EState::MajorFidget : EState::MinorFidget; - else if ((x8_delayTriggerBits & 0x1) == 0x1) - x0_state = EState::MinorFidget; - else if ((x8_delayTriggerBits & 0x2) == 0x2) - x0_state = EState::MajorFidget; - else - x0_state = EState::NoFidget; - } - - switch (x0_state) - { - case EState::MinorFidget: - x34_24_loading = true; - x10_delayTimerEnableBits = 2; - x8_delayTriggerBits &= ~0x1; - kMinorFidgetDelay = mgr.GetActiveRandom()->Range(20.f, 29.f); - x4_type = SamusGun::EFidgetType::Minor; - xc_animSet = mgr.GetActiveRandom()->Range(0, 4); - break; - case EState::MajorFidget: - x34_24_loading = true; - x10_delayTimerEnableBits = 1; - x8_delayTriggerBits &= ~0x2; - kMajorFidgetDelay = mgr.GetActiveRandom()->Range(20.f, 30.f); - x4_type = SamusGun::EFidgetType::Major; - xc_animSet = mgr.GetActiveRandom()->Range(0, 5); - break; - case EState::HolsterBeam: - x4_type = SamusGun::EFidgetType::Minor; - x34_24_loading = true; - xc_animSet = 0; - break; - default: - break; - } - - return x0_state; -} - -void CFidget::ResetMinor() -{ +CFidget::EState CFidget::Update(int fireButtonStates, bool bobbing, bool inStrikeCooldown, float dt, + CStateManager& mgr) { + switch (x0_state) { + case EState::NoFidget: + break; + case EState::MinorFidget: + return x34_24_loading ? EState::Loading : EState::StillMinorFidget; + case EState::MajorFidget: + return x34_24_loading ? EState::Loading : EState::StillMajorFidget; + case EState::HolsterBeam: + return x34_24_loading ? EState::Loading : EState::StillHolsterBeam; + default: x0_state = EState::NoFidget; -} + break; + } -void CFidget::ResetAll() -{ - x0_state = EState::NoFidget; - x4_type = SamusGun::EFidgetType::Invalid; - x18_timeSinceStrikeCooldown = 0.f; - x1c_timeSinceUnmorph = 0.f; + if (fireButtonStates != 0) { x14_timeSinceFire = 0.f; - x24_minorDelayTimer = 0.f; - x28_majorDelayTimer = 0.f; x2c_holsterTimeSinceFire = 0.f; - x8_delayTriggerBits = 0; - xc_animSet = -1; - x10_delayTimerEnableBits = 3; - x34_24_loading = false; + } else { + if (x14_timeSinceFire < 6.f) + x14_timeSinceFire += dt; + if (x2c_holsterTimeSinceFire < x30_timeUntilHolster + 1.f) + x2c_holsterTimeSinceFire += dt; + } + + if (inStrikeCooldown) + x18_timeSinceStrikeCooldown = 0.f; + else if (x18_timeSinceStrikeCooldown < 11.f) + x18_timeSinceStrikeCooldown += dt; + + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) { + if (x1c_timeSinceUnmorph < 21.f) + x1c_timeSinceUnmorph += dt; + } else { + x1c_timeSinceUnmorph = 0.f; + } + + if (bobbing) + x20_timeSinceBobbing = 0.f; + else if (x20_timeSinceBobbing < 21.f) + x20_timeSinceBobbing += dt; + + u32 pendingTriggerBits = 0; + if (x0_state == EState::NoFidget) { + if ((x10_delayTimerEnableBits & 0x1) != 0) { + x24_minorDelayTimer += dt; + if (x24_minorDelayTimer > kMinorFidgetDelay) { + pendingTriggerBits |= 0x1; + x24_minorDelayTimer = 0.f; + } + } + + if ((x10_delayTimerEnableBits & 0x2) != 0) { + x28_majorDelayTimer += dt; + if (x28_majorDelayTimer > kMajorFidgetDelay) { + pendingTriggerBits |= 0x2; + x28_majorDelayTimer = 0.f; + } + } + } + + if (x2c_holsterTimeSinceFire > x30_timeUntilHolster) { + x0_state = EState::HolsterBeam; + } else { + if (x18_timeSinceStrikeCooldown > 10.f && x1c_timeSinceUnmorph > 20.f && x20_timeSinceBobbing > 20.f) { + if ((pendingTriggerBits & 0x1) != 0) + x8_delayTriggerBits |= 0x1; + else if ((pendingTriggerBits & 0x2) != 0) + x8_delayTriggerBits |= 0x2; + } + + if ((x8_delayTriggerBits & 0x3) == 0x3) + x0_state = (mgr.GetActiveRandom()->Next() % 100) >= 50 ? EState::MajorFidget : EState::MinorFidget; + else if ((x8_delayTriggerBits & 0x1) == 0x1) + x0_state = EState::MinorFidget; + else if ((x8_delayTriggerBits & 0x2) == 0x2) + x0_state = EState::MajorFidget; + else + x0_state = EState::NoFidget; + } + + switch (x0_state) { + case EState::MinorFidget: + x34_24_loading = true; + x10_delayTimerEnableBits = 2; + x8_delayTriggerBits &= ~0x1; + kMinorFidgetDelay = mgr.GetActiveRandom()->Range(20.f, 29.f); + x4_type = SamusGun::EFidgetType::Minor; + xc_animSet = mgr.GetActiveRandom()->Range(0, 4); + break; + case EState::MajorFidget: + x34_24_loading = true; + x10_delayTimerEnableBits = 1; + x8_delayTriggerBits &= ~0x2; + kMajorFidgetDelay = mgr.GetActiveRandom()->Range(20.f, 30.f); + x4_type = SamusGun::EFidgetType::Major; + xc_animSet = mgr.GetActiveRandom()->Range(0, 5); + break; + case EState::HolsterBeam: + x4_type = SamusGun::EFidgetType::Minor; + x34_24_loading = true; + xc_animSet = 0; + break; + default: + break; + } + + return x0_state; } +void CFidget::ResetMinor() { x0_state = EState::NoFidget; } + +void CFidget::ResetAll() { + x0_state = EState::NoFidget; + x4_type = SamusGun::EFidgetType::Invalid; + x18_timeSinceStrikeCooldown = 0.f; + x1c_timeSinceUnmorph = 0.f; + x14_timeSinceFire = 0.f; + x24_minorDelayTimer = 0.f; + x28_majorDelayTimer = 0.f; + x2c_holsterTimeSinceFire = 0.f; + x8_delayTriggerBits = 0; + xc_animSet = -1; + x10_delayTimerEnableBits = 3; + x34_24_loading = false; } + +} // namespace urde diff --git a/Runtime/Weapon/CFidget.hpp b/Runtime/Weapon/CFidget.hpp index 117ba1f09..13792cdea 100644 --- a/Runtime/Weapon/CFidget.hpp +++ b/Runtime/Weapon/CFidget.hpp @@ -3,49 +3,47 @@ #include "RetroTypes.hpp" #include "CGunMotion.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class CFidget -{ +class CFidget { public: - enum class EState - { - NoFidget, - MinorFidget, - MajorFidget, - HolsterBeam, - StillMinorFidget, - StillMajorFidget, - StillHolsterBeam, - Loading - }; + enum class EState { + NoFidget, + MinorFidget, + MajorFidget, + HolsterBeam, + StillMinorFidget, + StillMajorFidget, + StillHolsterBeam, + Loading + }; + private: - EState x0_state = EState::NoFidget; - SamusGun::EFidgetType x4_type = SamusGun::EFidgetType::Invalid; - u32 x8_delayTriggerBits = 0; - // 0: panel, 1: panel reset, 2: adjust nozzle, 3: panel buttons - s32 xc_animSet = -1; - u32 x10_delayTimerEnableBits = 3; - float x14_timeSinceFire = 0.f; - float x18_timeSinceStrikeCooldown = 0.f; - float x1c_timeSinceUnmorph = 0.f; - float x20_timeSinceBobbing = 0.f; - float x24_minorDelayTimer = 0.f; - float x28_majorDelayTimer = 0.f; - float x2c_holsterTimeSinceFire = 0.f; - float x30_timeUntilHolster = 105.f; - bool x34_24_loading = false; + EState x0_state = EState::NoFidget; + SamusGun::EFidgetType x4_type = SamusGun::EFidgetType::Invalid; + u32 x8_delayTriggerBits = 0; + // 0: panel, 1: panel reset, 2: adjust nozzle, 3: panel buttons + s32 xc_animSet = -1; + u32 x10_delayTimerEnableBits = 3; + float x14_timeSinceFire = 0.f; + float x18_timeSinceStrikeCooldown = 0.f; + float x1c_timeSinceUnmorph = 0.f; + float x20_timeSinceBobbing = 0.f; + float x24_minorDelayTimer = 0.f; + float x28_majorDelayTimer = 0.f; + float x2c_holsterTimeSinceFire = 0.f; + float x30_timeUntilHolster = 105.f; + bool x34_24_loading = false; + public: - EState GetState() const { return x0_state; } - SamusGun::EFidgetType GetType() const { return x4_type; } - s32 GetAnimSet() const { return xc_animSet; } - EState Update(int fireButtonStates, bool bobbing, bool inStrikeCooldown, float dt, CStateManager& mgr); - void ResetMinor(); - void ResetAll(); - void DoneLoading() { x34_24_loading = false; } + EState GetState() const { return x0_state; } + SamusGun::EFidgetType GetType() const { return x4_type; } + s32 GetAnimSet() const { return xc_animSet; } + EState Update(int fireButtonStates, bool bobbing, bool inStrikeCooldown, float dt, CStateManager& mgr); + void ResetMinor(); + void ResetAll(); + void DoneLoading() { x34_24_loading = false; } }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CFlameInfo.cpp b/Runtime/Weapon/CFlameInfo.cpp index 2ac470f4e..2a3322519 100644 --- a/Runtime/Weapon/CFlameInfo.cpp +++ b/Runtime/Weapon/CFlameInfo.cpp @@ -1,17 +1,8 @@ #include "Weapon/CFlameInfo.hpp" -namespace urde -{ +namespace urde { CFlameInfo::CFlameInfo(s32 w1, s32 w2, CAssetId flameFxId, s32 w3, float f1, float f2, float f3) - : x0_(w1) - , x4_(w2) - , x8_flameFxId(flameFxId) - , xc_(w3) - , x10_(f1) - , x18_(f2) - , x1c_(f3) -{ -} +: x0_(w1), x4_(w2), x8_flameFxId(flameFxId), xc_(w3), x10_(f1), x18_(f2), x1c_(f3) {} -} +} // namespace urde diff --git a/Runtime/Weapon/CFlameInfo.hpp b/Runtime/Weapon/CFlameInfo.hpp index 196f9b12a..9cc0b9c55 100644 --- a/Runtime/Weapon/CFlameInfo.hpp +++ b/Runtime/Weapon/CFlameInfo.hpp @@ -2,22 +2,21 @@ #include "Weapon/CGameProjectile.hpp" -namespace urde -{ -class CFlameInfo -{ - s32 x0_; - s32 x4_; - CAssetId x8_flameFxId; - s32 xc_; - float x10_; - float x18_; - float x1c_; -public: - CFlameInfo(s32, s32, CAssetId, s32, float, float, float); +namespace urde { +class CFlameInfo { + s32 x0_; + s32 x4_; + CAssetId x8_flameFxId; + s32 xc_; + float x10_; + float x18_; + float x1c_; - void GetAttributes() const; - float GetLength() const; - CAssetId GetFlameFxId() const { return x8_flameFxId; } +public: + CFlameInfo(s32, s32, CAssetId, s32, float, float, float); + + void GetAttributes() const; + float GetLength() const; + CAssetId GetFlameFxId() const { return x8_flameFxId; } }; -} +} // namespace urde diff --git a/Runtime/Weapon/CFlameThrower.cpp b/Runtime/Weapon/CFlameThrower.cpp index 30f36530c..46ee66e81 100644 --- a/Runtime/Weapon/CFlameThrower.cpp +++ b/Runtime/Weapon/CFlameThrower.cpp @@ -4,8 +4,7 @@ #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { const zeus::CVector3f CFlameThrower::kLightOffset(0, 3.f, 2.f); CFlameThrower::CFlameThrower(const TToken& wDesc, std::string_view name, EWeaponType wType, @@ -16,9 +15,7 @@ CFlameThrower::CFlameThrower(const TToken& wDesc, std::strin zeus::CVector3f(1.f), {}, -1, false) , x2e8_(xf) , x33c_flameDesc(g_SimplePool->GetObj({FOURCC('PART'), flameInfo.GetFlameFxId()})) -, x348_flameGen(new CElementGen(x33c_flameDesc)) -{ -} +, x348_flameGen(new CElementGen(x33c_flameDesc)) {} void CFlameThrower::Accept(IVisitor& visitor) { visitor.Visit(this); } @@ -27,4 +24,4 @@ void CFlameThrower::SetTransform(const zeus::CTransform& xf) { x2e8_ = xf; } void CFlameThrower::Reset(CStateManager&, bool) {} void CFlameThrower::Fire(const zeus::CTransform&, CStateManager&, bool) {} -} +} // namespace urde diff --git a/Runtime/Weapon/CFlameThrower.hpp b/Runtime/Weapon/CFlameThrower.hpp index e547d03d6..0450677e6 100644 --- a/Runtime/Weapon/CFlameThrower.hpp +++ b/Runtime/Weapon/CFlameThrower.hpp @@ -2,37 +2,33 @@ #include "Weapon/CGameProjectile.hpp" -namespace urde -{ +namespace urde { class CFlameInfo; class CElementGen; -class CFlameThrower : public CGameProjectile -{ - static const zeus::CVector3f kLightOffset; - zeus::CTransform x2e8_; - zeus::CAABox x318_ = zeus::CAABox::skNullBox; - TToken x33c_flameDesc; - std::unique_ptr x348_flameGen; +class CFlameThrower : public CGameProjectile { + static const zeus::CVector3f kLightOffset; + zeus::CTransform x2e8_; + zeus::CAABox x318_ = zeus::CAABox::skNullBox; + TToken x33c_flameDesc; + std::unique_ptr x348_flameGen; - union - { - struct - { - bool x400_25 : 1; - }; - u32 _dummy = 0; + union { + struct { + bool x400_25 : 1; }; + u32 _dummy = 0; + }; public: - CFlameThrower(const TToken& wDesc, std::string_view name, EWeaponType wType, - const CFlameInfo& flameInfo, const zeus::CTransform& xf, EMaterialTypes matType, - const CDamageInfo& dInfo, TUniqueId uid, TAreaId aId, TUniqueId owner, EProjectileAttrib attribs, - u32 w2, s16 sId, u32 w3); + CFlameThrower(const TToken& wDesc, std::string_view name, EWeaponType wType, + const CFlameInfo& flameInfo, const zeus::CTransform& xf, EMaterialTypes matType, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aId, TUniqueId owner, EProjectileAttrib attribs, + u32 w2, s16 sId, u32 w3); - void Accept(IVisitor& visitor); - void SetTransform(const zeus::CTransform& xf); - void Reset(CStateManager&, bool); - void Fire(const zeus::CTransform&, CStateManager&, bool); - bool GetX400_25() const { return x400_25; } + void Accept(IVisitor& visitor); + void SetTransform(const zeus::CTransform& xf); + void Reset(CStateManager&, bool); + void Fire(const zeus::CTransform&, CStateManager&, bool); + bool GetX400_25() const { return x400_25; } }; -} +} // namespace urde diff --git a/Runtime/Weapon/CGSComboFire.cpp b/Runtime/Weapon/CGSComboFire.cpp index d4f447773..ebff0abe7 100644 --- a/Runtime/Weapon/CGSComboFire.cpp +++ b/Runtime/Weapon/CGSComboFire.cpp @@ -3,74 +3,62 @@ #include "Character/CPASAnimParmData.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { -bool CGSComboFire::Update(CAnimData& data, float dt, CStateManager& mgr) -{ - if (x8_cueAnimId != -1) - { - x0_delay -= dt; - if (x0_delay <= 0.f) - { - data.EnableLooping(x4_loopState == 1); - CAnimPlaybackParms aparms(x8_cueAnimId, -1, 1.f, true); - data.SetAnimation(aparms, false); - x0_delay = 0.f; - x8_cueAnimId = -1; - } +bool CGSComboFire::Update(CAnimData& data, float dt, CStateManager& mgr) { + if (x8_cueAnimId != -1) { + x0_delay -= dt; + if (x0_delay <= 0.f) { + data.EnableLooping(x4_loopState == 1); + CAnimPlaybackParms aparms(x8_cueAnimId, -1, 1.f, true); + data.SetAnimation(aparms, false); + x0_delay = 0.f; + x8_cueAnimId = -1; } - else if (!data.IsAnimTimeRemaining(0.001f, "Whole Body")) - { - switch (x4_loopState) - { - case 0: - SetAnim(data, xc_gunId, 1, mgr, 0.f); - switch (xc_gunId) - { - case 4: - case 0: - case 1: - x10_24_over = true; - break; - default: - break; - } - break; - case 2: - x4_loopState = -1; - return true; - default: - break; - } + } else if (!data.IsAnimTimeRemaining(0.001f, "Whole Body")) { + switch (x4_loopState) { + case 0: + SetAnim(data, xc_gunId, 1, mgr, 0.f); + switch (xc_gunId) { + case 4: + case 0: + case 1: + x10_24_over = true; + break; + default: + break; + } + break; + case 2: + x4_loopState = -1; + return true; + default: + break; } - return false; + } + return false; } -s32 CGSComboFire::SetAnim(CAnimData& data, s32 gunId, s32 loopState, CStateManager& mgr, float delay) -{ - s32 useLoopState = 2; - if (!x10_25_idle) - useLoopState = loopState; - x10_25_idle = false; - const CPASDatabase& pas = data.GetCharacterInfo().GetPASDatabase(); - CPASAnimParmData parms(4, CPASAnimParm::FromInt32(gunId), CPASAnimParm::FromEnum(useLoopState)); - auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - x10_24_over = false; - xc_gunId = gunId; - x4_loopState = useLoopState; - if (delay != 0.f) - { - x0_delay = delay; - x8_cueAnimId = anim.second; - } - else - { - data.EnableLooping(loopState == 1); - CAnimPlaybackParms aparms(anim.second, -1, 1.f, true); - data.SetAnimation(aparms, false); - } - return anim.second; +s32 CGSComboFire::SetAnim(CAnimData& data, s32 gunId, s32 loopState, CStateManager& mgr, float delay) { + s32 useLoopState = 2; + if (!x10_25_idle) + useLoopState = loopState; + x10_25_idle = false; + const CPASDatabase& pas = data.GetCharacterInfo().GetPASDatabase(); + CPASAnimParmData parms(4, CPASAnimParm::FromInt32(gunId), CPASAnimParm::FromEnum(useLoopState)); + auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + x10_24_over = false; + xc_gunId = gunId; + x4_loopState = useLoopState; + if (delay != 0.f) { + x0_delay = delay; + x8_cueAnimId = anim.second; + } else { + data.EnableLooping(loopState == 1); + CAnimPlaybackParms aparms(anim.second, -1, 1.f, true); + data.SetAnimation(aparms, false); + } + return anim.second; } -} +} // namespace urde diff --git a/Runtime/Weapon/CGSComboFire.hpp b/Runtime/Weapon/CGSComboFire.hpp index 14057fcab..5dbb1f390 100644 --- a/Runtime/Weapon/CGSComboFire.hpp +++ b/Runtime/Weapon/CGSComboFire.hpp @@ -2,36 +2,32 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CAnimData; class CStateManager; -class CGSComboFire -{ - float x0_delay = 0.f; - s32 x4_loopState = -1; // In, loop, out - s32 x8_cueAnimId = -1; - s32 xc_gunId = -1; +class CGSComboFire { + float x0_delay = 0.f; + s32 x4_loopState = -1; // In, loop, out + s32 x8_cueAnimId = -1; + s32 xc_gunId = -1; - union - { - struct - { - bool x10_24_over : 1; - bool x10_25_idle : 1; - }; - u8 _dummy = 0; + union { + struct { + bool x10_24_over : 1; + bool x10_25_idle : 1; }; + u8 _dummy = 0; + }; + public: - bool IsComboOver() const { return x10_24_over; } - s32 GetLoopState() const { return x4_loopState; } - void SetLoopState(s32 l) { x4_loopState = l; } - void SetIdle(bool i) { x10_25_idle = i; } - s32 GetGunId() const { return xc_gunId; } - bool Update(CAnimData& data, float dt, CStateManager& mgr); - s32 SetAnim(CAnimData& data, s32 gunId, s32 loopState, CStateManager& mgr, float delay); + bool IsComboOver() const { return x10_24_over; } + s32 GetLoopState() const { return x4_loopState; } + void SetLoopState(s32 l) { x4_loopState = l; } + void SetIdle(bool i) { x10_25_idle = i; } + s32 GetGunId() const { return xc_gunId; } + bool Update(CAnimData& data, float dt, CStateManager& mgr); + s32 SetAnim(CAnimData& data, s32 gunId, s32 loopState, CStateManager& mgr, float delay); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CGSFidget.cpp b/Runtime/Weapon/CGSFidget.cpp index 61de44276..6dc4e3e94 100644 --- a/Runtime/Weapon/CGSFidget.cpp +++ b/Runtime/Weapon/CGSFidget.cpp @@ -4,48 +4,37 @@ #include "Character/CAnimData.hpp" #include "CStateManager.hpp" -namespace urde -{ -bool CGSFidget::Update(CAnimData& data, float dt, CStateManager& mgr) -{ - return !data.IsAnimTimeRemaining(0.001f, "Whole Body"); +namespace urde { +bool CGSFidget::Update(CAnimData& data, float dt, CStateManager& mgr) { + return !data.IsAnimTimeRemaining(0.001f, "Whole Body"); } -s32 CGSFidget::SetAnim(CAnimData& data, s32 type, s32 gunId, s32 animSet, CStateManager& mgr) -{ - const CPASDatabase& pas = data.GetCharacterInfo().GetPASDatabase(); - CPASAnimParmData parms(1, CPASAnimParm::FromEnum(type), CPASAnimParm::FromInt32(gunId), - CPASAnimParm::FromInt32(animSet)); - auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - bool loop = pas.GetAnimState(1)->GetAnimParmData(anim.second, 3).GetBoolValue(); - x14_gunId = gunId; - x18_animSet = animSet; - if (anim.second != -1) - { - data.EnableLooping(loop); - CAnimPlaybackParms aParms(anim.second, -1, 1.f, true); - data.SetAnimation(aParms, false); - UnLoadAnim(); - } - return anim.second; +s32 CGSFidget::SetAnim(CAnimData& data, s32 type, s32 gunId, s32 animSet, CStateManager& mgr) { + const CPASDatabase& pas = data.GetCharacterInfo().GetPASDatabase(); + CPASAnimParmData parms(1, CPASAnimParm::FromEnum(type), CPASAnimParm::FromInt32(gunId), + CPASAnimParm::FromInt32(animSet)); + auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + bool loop = pas.GetAnimState(1)->GetAnimParmData(anim.second, 3).GetBoolValue(); + x14_gunId = gunId; + x18_animSet = animSet; + if (anim.second != -1) { + data.EnableLooping(loop); + CAnimPlaybackParms aParms(anim.second, -1, 1.f, true); + data.SetAnimation(aParms, false); + UnLoadAnim(); + } + return anim.second; } -void CGSFidget::LoadAnimAsync(CAnimData& data, s32 type, s32 gunId, s32 animSet, CStateManager& mgr) -{ - CPASAnimParmData parms(1, CPASAnimParm::FromEnum(type), CPASAnimParm::FromInt32(gunId), - CPASAnimParm::FromInt32(animSet)); - auto anim = data.GetCharacterInfo().GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - if (anim.second != -1) - NWeaponTypes::get_token_vector(data, anim.second, x0_anims, true); +void CGSFidget::LoadAnimAsync(CAnimData& data, s32 type, s32 gunId, s32 animSet, CStateManager& mgr) { + CPASAnimParmData parms(1, CPASAnimParm::FromEnum(type), CPASAnimParm::FromInt32(gunId), + CPASAnimParm::FromInt32(animSet)); + auto anim = data.GetCharacterInfo().GetPASDatabase().FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + if (anim.second != -1) + NWeaponTypes::get_token_vector(data, anim.second, x0_anims, true); } -void CGSFidget::UnLoadAnim() -{ - x0_anims.clear(); -} +void CGSFidget::UnLoadAnim() { x0_anims.clear(); } -bool CGSFidget::IsAnimLoaded() const -{ - return NWeaponTypes::are_tokens_ready(x0_anims); -} -} +bool CGSFidget::IsAnimLoaded() const { return NWeaponTypes::are_tokens_ready(x0_anims); } +} // namespace urde diff --git a/Runtime/Weapon/CGSFidget.hpp b/Runtime/Weapon/CGSFidget.hpp index 0af095b65..f034dcc2a 100644 --- a/Runtime/Weapon/CGSFidget.hpp +++ b/Runtime/Weapon/CGSFidget.hpp @@ -3,23 +3,21 @@ #include "RetroTypes.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class CAnimData; class CStateManager; -class CGSFidget -{ - std::vector x0_anims; - s32 x10_ = -1; - s32 x14_gunId = -1; - s32 x18_animSet = -1; +class CGSFidget { + std::vector x0_anims; + s32 x10_ = -1; + s32 x14_gunId = -1; + s32 x18_animSet = -1; + public: - bool Update(CAnimData& data, float dt, CStateManager& mgr); - s32 SetAnim(CAnimData& data, s32 type, s32 gunId, s32 animSet, CStateManager& mgr); - void LoadAnimAsync(CAnimData& data, s32 type, s32 gunId, s32 animSet, CStateManager& mgr); - void UnLoadAnim(); - bool IsAnimLoaded() const; + bool Update(CAnimData& data, float dt, CStateManager& mgr); + s32 SetAnim(CAnimData& data, s32 type, s32 gunId, s32 animSet, CStateManager& mgr); + void LoadAnimAsync(CAnimData& data, s32 type, s32 gunId, s32 animSet, CStateManager& mgr); + void UnLoadAnim(); + bool IsAnimLoaded() const; }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CGSFreeLook.cpp b/Runtime/Weapon/CGSFreeLook.cpp index 05203e67f..84d8329e2 100644 --- a/Runtime/Weapon/CGSFreeLook.cpp +++ b/Runtime/Weapon/CGSFreeLook.cpp @@ -2,65 +2,54 @@ #include "CStateManager.hpp" #include "Character/CPASAnimParmData.hpp" -namespace urde -{ +namespace urde { -bool CGSFreeLook::Update(CAnimData& data, float dt, CStateManager& mgr) -{ - if (x4_cueAnimId != -1) - { - x0_delay -= dt; - if (x0_delay <= 0.f) - { - data.EnableLooping(x8_loopState == 1); - CAnimPlaybackParms aparms(x4_cueAnimId, -1, 1.f, true); - data.SetAnimation(aparms, false); - x0_delay = 0.f; - x4_cueAnimId = -1; - } +bool CGSFreeLook::Update(CAnimData& data, float dt, CStateManager& mgr) { + if (x4_cueAnimId != -1) { + x0_delay -= dt; + if (x0_delay <= 0.f) { + data.EnableLooping(x8_loopState == 1); + CAnimPlaybackParms aparms(x4_cueAnimId, -1, 1.f, true); + data.SetAnimation(aparms, false); + x0_delay = 0.f; + x4_cueAnimId = -1; } - else if (!data.IsAnimTimeRemaining(0.001f, "Whole Body")) - { - switch (x8_loopState) - { - case 0: - SetAnim(data, xc_gunId, x10_setId, 1, mgr, 0.f); - break; - case 2: - x8_loopState = -1; - return true; - default: - break; - } + } else if (!data.IsAnimTimeRemaining(0.001f, "Whole Body")) { + switch (x8_loopState) { + case 0: + SetAnim(data, xc_gunId, x10_setId, 1, mgr, 0.f); + break; + case 2: + x8_loopState = -1; + return true; + default: + break; } - return false; + } + return false; } -s32 CGSFreeLook::SetAnim(CAnimData& data, s32 gunId, s32 setId, s32 loopState, CStateManager& mgr, float delay) -{ - s32 useLoopState = 1; - if (!x14_idle) - useLoopState = loopState; - x14_idle = false; - const CPASDatabase& pas = data.GetCharacterInfo().GetPASDatabase(); - CPASAnimParmData parms(3, CPASAnimParm::FromInt32(gunId), - CPASAnimParm::FromInt32(setId), CPASAnimParm::FromEnum(useLoopState)); - auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - xc_gunId = gunId; - x10_setId = pas.GetAnimState(3)->GetAnimParmData(anim.second, 1).GetInt32Value(); - x8_loopState = useLoopState; - if (delay != 0.f) - { - x0_delay = delay; - x4_cueAnimId = anim.second; - } - else - { - data.EnableLooping(loopState == 1); - CAnimPlaybackParms aparms(anim.second, -1, 1.f, true); - data.SetAnimation(aparms, false); - } - return anim.second; +s32 CGSFreeLook::SetAnim(CAnimData& data, s32 gunId, s32 setId, s32 loopState, CStateManager& mgr, float delay) { + s32 useLoopState = 1; + if (!x14_idle) + useLoopState = loopState; + x14_idle = false; + const CPASDatabase& pas = data.GetCharacterInfo().GetPASDatabase(); + CPASAnimParmData parms(3, CPASAnimParm::FromInt32(gunId), CPASAnimParm::FromInt32(setId), + CPASAnimParm::FromEnum(useLoopState)); + auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + xc_gunId = gunId; + x10_setId = pas.GetAnimState(3)->GetAnimParmData(anim.second, 1).GetInt32Value(); + x8_loopState = useLoopState; + if (delay != 0.f) { + x0_delay = delay; + x4_cueAnimId = anim.second; + } else { + data.EnableLooping(loopState == 1); + CAnimPlaybackParms aparms(anim.second, -1, 1.f, true); + data.SetAnimation(aparms, false); + } + return anim.second; } -} +} // namespace urde diff --git a/Runtime/Weapon/CGSFreeLook.hpp b/Runtime/Weapon/CGSFreeLook.hpp index bd8b37c7a..55e2daca3 100644 --- a/Runtime/Weapon/CGSFreeLook.hpp +++ b/Runtime/Weapon/CGSFreeLook.hpp @@ -2,29 +2,26 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { class CAnimData; class CStateManager; -class CGSFreeLook -{ - float x0_delay = 0.f; - s32 x4_cueAnimId = -1; - s32 x8_loopState = -1; // In, loop, out - s32 xc_gunId = 0; - s32 x10_setId = -1; - bool x14_idle = false; -public: - s32 GetSetId() const { return x10_setId; } - void SetLoopState(s32 l) { x8_loopState = l; } - s32 GetLoopState() const { return x8_loopState; } - void SetIdle(bool l) { x14_idle = l; } - s32 GetGunId() const { return xc_gunId; } - bool Update(CAnimData& data, float dt, CStateManager& mgr); - s32 SetAnim(CAnimData& data, s32 gunId, s32 setId, s32 loopState, CStateManager& mgr, float delay); +class CGSFreeLook { + float x0_delay = 0.f; + s32 x4_cueAnimId = -1; + s32 x8_loopState = -1; // In, loop, out + s32 xc_gunId = 0; + s32 x10_setId = -1; + bool x14_idle = false; +public: + s32 GetSetId() const { return x10_setId; } + void SetLoopState(s32 l) { x8_loopState = l; } + s32 GetLoopState() const { return x8_loopState; } + void SetIdle(bool l) { x14_idle = l; } + s32 GetGunId() const { return xc_gunId; } + bool Update(CAnimData& data, float dt, CStateManager& mgr); + s32 SetAnim(CAnimData& data, s32 gunId, s32 setId, s32 loopState, CStateManager& mgr, float delay); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CGameProjectile.cpp b/Runtime/Weapon/CGameProjectile.cpp index 55fe63f47..477ed2151 100644 --- a/Runtime/Weapon/CGameProjectile.cpp +++ b/Runtime/Weapon/CGameProjectile.cpp @@ -11,8 +11,7 @@ #include "World/CScriptPlatform.hpp" #include "Collision/CCollisionActor.hpp" -namespace urde -{ +namespace urde { CGameProjectile::CGameProjectile(bool active, const TToken& wDesc, std::string_view name, EWeaponType wType, const zeus::CTransform& xf, EMaterialTypes excludeMat, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, @@ -24,522 +23,410 @@ CGameProjectile::CGameProjectile(bool active, const TToken& CMaterialFilter::MakeIncludeExclude( {EMaterialTypes::Solid, EMaterialTypes::NonSolidDamageable}, {EMaterialTypes::Projectile, EMaterialTypes::ProjectilePassthrough, excludeMat}), - CMaterialList(), dInfo, attribs | GetBeamAttribType(wType), CModelData::CModelDataNull()), - x158_visorParticle(visorParticle), x168_visorSfx(visorSfx), x170_projectile(wDesc, xf.origin, xf.basis, scale, - (attribs & EProjectileAttrib::ParticleOPTS) == EProjectileAttrib::ParticleOPTS), x298_lastOrigin(xf.origin), - x2a4_projExtent((xe8_projectileAttribs & EProjectileAttrib::BigProjectile) == - EProjectileAttrib::BigProjectile ? 0.25f : 0.1f), - x2c0_homingTargetId(homingTarget), x2cc_wpscId(wDesc.GetObjectTag()->id) -{ - x2e4_24_active = true; - x2e4_25_startedUnderwater = underwater; - x2e4_26_waterUpdate = underwater; - x2e4_27_inWater = underwater; - x2e4_28_sendProjectileCollideMsg = sendCollideMsg; + CMaterialList(), dInfo, attribs | GetBeamAttribType(wType), CModelData::CModelDataNull()) +, x158_visorParticle(visorParticle) +, x168_visorSfx(visorSfx) +, x170_projectile(wDesc, xf.origin, xf.basis, scale, + (attribs & EProjectileAttrib::ParticleOPTS) == EProjectileAttrib::ParticleOPTS) +, x298_lastOrigin(xf.origin) +, x2a4_projExtent((xe8_projectileAttribs & EProjectileAttrib::BigProjectile) == EProjectileAttrib::BigProjectile ? 0.25f + : 0.1f) +, x2c0_homingTargetId(homingTarget) +, x2cc_wpscId(wDesc.GetObjectTag()->id) { + x2e4_24_active = true; + x2e4_25_startedUnderwater = underwater; + x2e4_26_waterUpdate = underwater; + x2e4_27_inWater = underwater; + x2e4_28_sendProjectileCollideMsg = sendCollideMsg; } void CGameProjectile::Accept(urde::IVisitor& visitor) { visitor.Visit(this); } -void CGameProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr) -{ - zeus::CVector3f revDir = -x34_transform.basis[1].normalized(); - if (TCastToPtr(act)) - { - if (x158_visorParticle && mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) - { - if (zeus::radToDeg( - std::acos(mgr.GetCameraManager()->GetCurrentCameraTransform(mgr). - basis[1].normalized().dot(revDir))) <= 45.f) - { - /* Hit us head on! Draw Billboard! */ - std::experimental::optional> bb = {*x158_visorParticle}; - CHUDBillboardEffect* effect = new CHUDBillboardEffect(bb, {}, - mgr.AllocateUniqueId(), true, "VisorAcid", - CHUDBillboardEffect::GetNearClipDistance(mgr), - CHUDBillboardEffect::GetScaleForPOV(mgr), - zeus::CColor::skWhite, zeus::CVector3f::skOne, - zeus::CVector3f::skZero); - mgr.AddObject(effect); - CSfxManager::SfxStart(x168_visorSfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - if (x2e4_28_sendProjectileCollideMsg) - mgr.SendScriptMsg(&mgr.GetPlayer(), GetUniqueId(), EScriptObjectMessage::ProjectileCollide); - } - } +void CGameProjectile::ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr) { + zeus::CVector3f revDir = -x34_transform.basis[1].normalized(); + if (TCastToPtr(act)) { + if (x158_visorParticle && mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) { + if (zeus::radToDeg(std::acos( + mgr.GetCameraManager()->GetCurrentCameraTransform(mgr).basis[1].normalized().dot(revDir))) <= 45.f) { + /* Hit us head on! Draw Billboard! */ + std::experimental::optional> bb = {*x158_visorParticle}; + CHUDBillboardEffect* effect = new CHUDBillboardEffect( + bb, {}, mgr.AllocateUniqueId(), true, "VisorAcid", CHUDBillboardEffect::GetNearClipDistance(mgr), + CHUDBillboardEffect::GetScaleForPOV(mgr), zeus::CColor::skWhite, zeus::CVector3f::skOne, + zeus::CVector3f::skZero); + mgr.AddObject(effect); + CSfxManager::SfxStart(x168_visorSfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + if (x2e4_28_sendProjectileCollideMsg) + mgr.SendScriptMsg(&mgr.GetPlayer(), GetUniqueId(), EScriptObjectMessage::ProjectileCollide); + } } + } } -void CGameProjectile::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId /*uid*/, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::AddSplashInhabitant) - { - if (!x2e4_27_inWater) - { - x2e4_27_inWater = true; - x2e4_26_waterUpdate = true; - } +void CGameProjectile::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId /*uid*/, CStateManager& mgr) { + if (msg == EScriptObjectMessage::AddSplashInhabitant) { + if (!x2e4_27_inWater) { + x2e4_27_inWater = true; + x2e4_26_waterUpdate = true; } - else if (msg == EScriptObjectMessage::UpdateSplashInhabitant) - { - if (!x2e4_26_waterUpdate) - x2e4_26_waterUpdate = true; + } else if (msg == EScriptObjectMessage::UpdateSplashInhabitant) { + if (!x2e4_26_waterUpdate) + x2e4_26_waterUpdate = true; + } else if (msg == EScriptObjectMessage::RemoveSplashInhabitant) { + if (x2e4_26_waterUpdate) { + x2e4_26_waterUpdate = false; + x2e4_27_inWater = false; } - else if (msg == EScriptObjectMessage::RemoveSplashInhabitant) - { - if (x2e4_26_waterUpdate) - { - x2e4_26_waterUpdate = false; - x2e4_27_inWater = false; - } - } - else if (msg == EScriptObjectMessage::Deleted) - DeleteProjectileLight(mgr); -} - -EProjectileAttrib CGameProjectile::GetBeamAttribType(EWeaponType wType) -{ - if (wType == EWeaponType::Ice) - return EProjectileAttrib::Ice; - else if (wType == EWeaponType::Wave) - return EProjectileAttrib::Wave; - else if (wType == EWeaponType::Plasma) - return EProjectileAttrib::Plasma; - else if (wType == EWeaponType::Phazon) - return EProjectileAttrib::Phazon; - - return EProjectileAttrib::None; -} - -void CGameProjectile::DeleteProjectileLight(CStateManager& mgr) -{ - if (x2c8_projectileLight != kInvalidUniqueId) - { - mgr.FreeScriptObject(x2c8_projectileLight); - x2c8_projectileLight = kInvalidUniqueId; - } -} - -void CGameProjectile::CreateProjectileLight(std::string_view name, const CLight& light, CStateManager& mgr) -{ + } else if (msg == EScriptObjectMessage::Deleted) DeleteProjectileLight(mgr); - x2c8_projectileLight = mgr.AllocateUniqueId(); - mgr.AddObject(new CGameLight(x2c8_projectileLight, GetAreaId(), GetActive(), name, GetTransform(), GetUniqueId(), - light, u32(x2cc_wpscId.Value()), 0, 0.f)); } -void CGameProjectile::Chase(float dt, CStateManager& mgr) -{ - if (!x170_projectile.IsProjectileActive() || - x2c0_homingTargetId == kInvalidUniqueId) +EProjectileAttrib CGameProjectile::GetBeamAttribType(EWeaponType wType) { + if (wType == EWeaponType::Ice) + return EProjectileAttrib::Ice; + else if (wType == EWeaponType::Wave) + return EProjectileAttrib::Wave; + else if (wType == EWeaponType::Plasma) + return EProjectileAttrib::Plasma; + else if (wType == EWeaponType::Phazon) + return EProjectileAttrib::Phazon; + + return EProjectileAttrib::None; +} + +void CGameProjectile::DeleteProjectileLight(CStateManager& mgr) { + if (x2c8_projectileLight != kInvalidUniqueId) { + mgr.FreeScriptObject(x2c8_projectileLight); + x2c8_projectileLight = kInvalidUniqueId; + } +} + +void CGameProjectile::CreateProjectileLight(std::string_view name, const CLight& light, CStateManager& mgr) { + DeleteProjectileLight(mgr); + x2c8_projectileLight = mgr.AllocateUniqueId(); + mgr.AddObject(new CGameLight(x2c8_projectileLight, GetAreaId(), GetActive(), name, GetTransform(), GetUniqueId(), + light, u32(x2cc_wpscId.Value()), 0, 0.f)); +} + +void CGameProjectile::Chase(float dt, CStateManager& mgr) { + if (!x170_projectile.IsProjectileActive() || x2c0_homingTargetId == kInvalidUniqueId) + return; + + if (TCastToConstPtr act = mgr.GetObjectById(x2c0_homingTargetId)) { + if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Target) && + !act->GetMaterialList().HasMaterial(EMaterialTypes::Player)) { + x2c0_homingTargetId = kInvalidUniqueId; + } else { + zeus::CVector3f homingPos = act->GetHomingPosition(mgr, 0.f); + + TCastToConstPtr swarm = act.GetPtr(); + if (swarm) { + int lockOnId = swarm->GetCurrentLockOnId(); + if (swarm->GetLockOnLocationValid(lockOnId)) { + homingPos = swarm->GetLockOnLocation(lockOnId); + } else { + x2c0_homingTargetId = kInvalidUniqueId; + return; + } + } + + zeus::CVector3f projToPos = homingPos - x170_projectile.GetTranslation(); + if (x2e0_minHomingDist > 0.f && projToPos.magnitude() < x2e0_minHomingDist) { + x2c0_homingTargetId = kInvalidUniqueId; + return; + } + + if (!swarm && !TCastToConstPtr(act.GetPtr())) + if (auto tb = act->GetTouchBounds()) + projToPos.z() += (tb->max.z() - tb->min.z()) * 0.5f; + + zeus::CQuaternion qDelta = + zeus::CQuaternion::shortestRotationArc(x170_projectile.GetTransform().basis[1], projToPos); + + float wThres = qDelta.w() * qDelta.w() * 2.f - 1.f; + if (wThres > 0.99f) return; - if (TCastToConstPtr act = mgr.GetObjectById(x2c0_homingTargetId)) - { - if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Target) && - !act->GetMaterialList().HasMaterial(EMaterialTypes::Player)) - { - x2c0_homingTargetId = kInvalidUniqueId; - } - else - { - zeus::CVector3f homingPos = act->GetHomingPosition(mgr, 0.f); + float turnRate; + if (x2e4_26_waterUpdate) + turnRate = x170_projectile.GetMaxTurnRate() * 0.5f; + else + turnRate = x170_projectile.GetMaxTurnRate(); - TCastToConstPtr swarm = act.GetPtr(); - if (swarm) - { - int lockOnId = swarm->GetCurrentLockOnId(); - if (swarm->GetLockOnLocationValid(lockOnId)) - { - homingPos = swarm->GetLockOnLocation(lockOnId); - } - else - { - x2c0_homingTargetId = kInvalidUniqueId; - return; - } - } + float maxTurnDelta = zeus::degToRad(turnRate * dt); + float turnDelta = std::acos(wThres); + if (maxTurnDelta < turnDelta) { + /* Clamp quat to max delta */ + qDelta = + zeus::CQuaternion(std::cos(maxTurnDelta * 0.5f), + (std::sin(maxTurnDelta * 0.5f) / std::sin(turnDelta * 0.5f)) * qDelta.getImaginary()); + } - zeus::CVector3f projToPos = homingPos - x170_projectile.GetTranslation(); - if (x2e0_minHomingDist > 0.f && projToPos.magnitude() < x2e0_minHomingDist) - { - x2c0_homingTargetId = kInvalidUniqueId; - return; - } - - if (!swarm && !TCastToConstPtr(act.GetPtr())) - if (auto tb = act->GetTouchBounds()) - projToPos.z() += (tb->max.z() - tb->min.z()) * 0.5f; - - zeus::CQuaternion qDelta = - zeus::CQuaternion::shortestRotationArc(x170_projectile.GetTransform().basis[1], projToPos); - - float wThres = qDelta.w() * qDelta.w() * 2.f - 1.f; - if (wThres > 0.99f) - return; - - float turnRate; - if (x2e4_26_waterUpdate) - turnRate = x170_projectile.GetMaxTurnRate() * 0.5f; - else - turnRate = x170_projectile.GetMaxTurnRate(); - - float maxTurnDelta = zeus::degToRad(turnRate * dt); - float turnDelta = std::acos(wThres); - if (maxTurnDelta < turnDelta) - { - /* Clamp quat to max delta */ - qDelta = zeus::CQuaternion(std::cos(maxTurnDelta * 0.5f), - (std::sin(maxTurnDelta * 0.5f) / std::sin(turnDelta * 0.5f)) * qDelta.getImaginary()); - } - - zeus::CTransform xf = qDelta.toTransform() * x170_projectile.GetTransform(); - xf.orthonormalize(); - x170_projectile.SetWorldSpaceOrientation(xf); - } + zeus::CTransform xf = qDelta.toTransform() * x170_projectile.GetTransform(); + xf.orthonormalize(); + x170_projectile.SetWorldSpaceOrientation(xf); } + } } -void CGameProjectile::UpdateHoming(float dt, CStateManager& mgr) -{ - if (!x2e4_24_active || x2c0_homingTargetId == kInvalidUniqueId || x2a8_homingDt <= 0.f) - return; +void CGameProjectile::UpdateHoming(float dt, CStateManager& mgr) { + if (!x2e4_24_active || x2c0_homingTargetId == kInvalidUniqueId || x2a8_homingDt <= 0.f) + return; - x2b0_targetHomingTime += dt; + x2b0_targetHomingTime += dt; - while (x2b0_targetHomingTime >= x2b8_curHomingTime) - { - Chase(x2a8_homingDt, mgr); - x2b8_curHomingTime += x2a8_homingDt; + while (x2b0_targetHomingTime >= x2b8_curHomingTime) { + Chase(x2a8_homingDt, mgr); + x2b8_curHomingTime += x2a8_homingDt; + } +} + +void CGameProjectile::UpdateProjectileMovement(float dt, CStateManager& mgr) { + float useDt = dt; + if (x2e4_26_waterUpdate) + useDt = 37.5f * dt * dt; + + x298_lastOrigin = x34_transform.origin; + x170_projectile.Update(useDt); + SetTransform(x170_projectile.GetTransform()); + SetTranslation(x170_projectile.GetTranslation()); + UpdateHoming(dt, mgr); +} + +CRayCastResult CGameProjectile::DoCollisionCheck(TUniqueId& idOut, CStateManager& mgr) { + CRayCastResult res; + if (x2e4_24_active) { + zeus::CVector3f posDelta = x34_transform.origin - x298_lastOrigin; + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, GetProjectileBounds(), + CMaterialFilter::MakeExclude(EMaterialTypes::ProjectilePassthrough), this); + + res = RayCollisionCheckWithWorld(idOut, x298_lastOrigin, x34_transform.origin, posDelta.magnitude(), nearList, mgr); + } + return res; +} + +void CGameProjectile::ApplyDamageToActors(CStateManager& mgr, const CDamageInfo& dInfo) { + if (x2c6_pendingDamagee != kInvalidUniqueId) { + if (TCastToPtr act = mgr.ObjectById(x2c6_pendingDamagee)) { + mgr.ApplyDamage(GetUniqueId(), act->GetUniqueId(), xec_ownerId, dInfo, xf8_filter, x34_transform.basis[1]); + if ((xe8_projectileAttribs & EProjectileAttrib::PlayerUnFreeze) == EProjectileAttrib::PlayerUnFreeze && + mgr.GetPlayer().GetUniqueId() == act->GetUniqueId() && mgr.GetPlayer().GetFrozenState()) + mgr.GetPlayer().UnFreeze(mgr); } -} - -void CGameProjectile::UpdateProjectileMovement(float dt, CStateManager& mgr) -{ - float useDt = dt; - if (x2e4_26_waterUpdate) - useDt = 37.5f * dt * dt; - - x298_lastOrigin = x34_transform.origin; - x170_projectile.Update(useDt); - SetTransform(x170_projectile.GetTransform()); - SetTranslation(x170_projectile.GetTranslation()); - UpdateHoming(dt, mgr); -} - -CRayCastResult -CGameProjectile::DoCollisionCheck(TUniqueId& idOut, CStateManager& mgr) -{ - CRayCastResult res; - if (x2e4_24_active) - { - zeus::CVector3f posDelta = x34_transform.origin - x298_lastOrigin; - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, GetProjectileBounds(), - CMaterialFilter::MakeExclude(EMaterialTypes::ProjectilePassthrough), this); - - res = RayCollisionCheckWithWorld(idOut, x298_lastOrigin, x34_transform.origin, - posDelta.magnitude(), nearList, mgr); - - } - return res; -} - -void CGameProjectile::ApplyDamageToActors(CStateManager& mgr, const CDamageInfo& dInfo) -{ - if (x2c6_pendingDamagee != kInvalidUniqueId) - { - if (TCastToPtr act = mgr.ObjectById(x2c6_pendingDamagee)) - { - mgr.ApplyDamage(GetUniqueId(), act->GetUniqueId(), xec_ownerId, dInfo, xf8_filter, x34_transform.basis[1]); - if ((xe8_projectileAttribs & EProjectileAttrib::PlayerUnFreeze) == EProjectileAttrib::PlayerUnFreeze && - mgr.GetPlayer().GetUniqueId() == act->GetUniqueId() && mgr.GetPlayer().GetFrozenState()) - mgr.GetPlayer().UnFreeze(mgr); - } - x2c6_pendingDamagee = kInvalidUniqueId; - } - - for (CProjectileTouchResult& res : x2d0_touchResults) - { - if (TCastToConstPtr act = mgr.GetObjectById(res.GetActorId())) - { - mgr.ApplyDamage(GetUniqueId(), act->GetUniqueId(), xec_ownerId, dInfo, xf8_filter, x34_transform.basis[1]); - if ((xe8_projectileAttribs & EProjectileAttrib::PlayerUnFreeze) == EProjectileAttrib::PlayerUnFreeze && - mgr.GetPlayer().GetUniqueId() == act->GetUniqueId() && mgr.GetPlayer().GetFrozenState()) - mgr.GetPlayer().UnFreeze(mgr); - } - } - - x2d0_touchResults.clear(); -} - -void CGameProjectile::FluidFxThink(EFluidState state, CScriptWater& water, CStateManager& mgr) -{ - if (x170_projectile.GetWeaponDescription()->xa6_SWTR) - CWeapon::FluidFXThink(state, water, mgr); -} - -CRayCastResult -CGameProjectile::RayCollisionCheckWithWorld(TUniqueId& idOut, const zeus::CVector3f& start, - const zeus::CVector3f& end, float mag, - const rstl::reserved_vector& nearList, - CStateManager& mgr) -{ - x2d0_touchResults.clear(); - idOut = kInvalidUniqueId; x2c6_pendingDamagee = kInvalidUniqueId; - CRayCastResult res; - zeus::CVector3f delta = end - start; - if (!delta.canBeNormalized()) - return res; + } - float bestMag = mag; - zeus::CVector3f dir = delta.normalized(); - CRayCastResult res2 = mgr.RayStaticIntersection(start, dir, mag, xf8_filter); - if (res2.IsValid()) - { - bestMag = res2.GetT(); - res = res2; + for (CProjectileTouchResult& res : x2d0_touchResults) { + if (TCastToConstPtr act = mgr.GetObjectById(res.GetActorId())) { + mgr.ApplyDamage(GetUniqueId(), act->GetUniqueId(), xec_ownerId, dInfo, xf8_filter, x34_transform.basis[1]); + if ((xe8_projectileAttribs & EProjectileAttrib::PlayerUnFreeze) == EProjectileAttrib::PlayerUnFreeze && + mgr.GetPlayer().GetUniqueId() == act->GetUniqueId() && mgr.GetPlayer().GetFrozenState()) + mgr.GetPlayer().UnFreeze(mgr); } + } - for (TUniqueId id : nearList) - { - if (CActor* ent = static_cast(mgr.ObjectById(id))) - { - CProjectileTouchResult tRes = CanCollideWith(*ent, mgr); - if (tRes.GetActorId() == kInvalidUniqueId) - continue; - if (tRes.HasRayCastResult()) - { - if (tRes.GetRayCastResult().GetT() < bestMag) - { - ent->Touch(*this, mgr); - bestMag = tRes.GetRayCastResult().GetT(); - res = tRes.GetRayCastResult(); - x2c6_pendingDamagee = idOut = tRes.GetActorId(); - } - } - else - { - auto tb = ent->GetTouchBounds(); - CGameProjectile* projObj = nullptr; - if (TCastToPtr door = ent) - { - tb = door->GetProjectileBounds(); - } - else if (TCastToPtr proj = ent) - { - tb.emplace(proj->GetProjectileBounds()); - projObj = proj.GetPtr(); - } - if (!tb) - continue; + x2d0_touchResults.clear(); +} - CCollidableAABox prim(*tb, ent->GetMaterialList()); - CRayCastResult res3 = - prim.CastRayInternal(CInternalRayCastStructure(start, dir, mag, {}, - CMaterialFilter::skPassEverything)); - if (res3.IsValid()) - { - if (res3.GetT() < bestMag) - { - bestMag = res3.GetT(); - res = res3; - x2c6_pendingDamagee = idOut = tRes.GetActorId(); - } - } - else if (tb->pointInside(start) || (projObj && projObj->GetProjectileBounds().intersects(*tb))) - { - x2c6_pendingDamagee = idOut = ent->GetUniqueId(); - zeus::CUnitVector3f norm(-dir); - res = CRayCastResult(0.f, start, {norm, norm.dot(start)}, ent->GetMaterialList()); - break; - } - } - } - } - - if (x2e4_27_inWater && idOut == kInvalidUniqueId) - x2e4_27_inWater = false; +void CGameProjectile::FluidFxThink(EFluidState state, CScriptWater& water, CStateManager& mgr) { + if (x170_projectile.GetWeaponDescription()->xa6_SWTR) + CWeapon::FluidFXThink(state, water, mgr); +} +CRayCastResult CGameProjectile::RayCollisionCheckWithWorld(TUniqueId& idOut, const zeus::CVector3f& start, + const zeus::CVector3f& end, float mag, + const rstl::reserved_vector& nearList, + CStateManager& mgr) { + x2d0_touchResults.clear(); + idOut = kInvalidUniqueId; + x2c6_pendingDamagee = kInvalidUniqueId; + CRayCastResult res; + zeus::CVector3f delta = end - start; + if (!delta.canBeNormalized()) return res; + + float bestMag = mag; + zeus::CVector3f dir = delta.normalized(); + CRayCastResult res2 = mgr.RayStaticIntersection(start, dir, mag, xf8_filter); + if (res2.IsValid()) { + bestMag = res2.GetT(); + res = res2; + } + + for (TUniqueId id : nearList) { + if (CActor* ent = static_cast(mgr.ObjectById(id))) { + CProjectileTouchResult tRes = CanCollideWith(*ent, mgr); + if (tRes.GetActorId() == kInvalidUniqueId) + continue; + if (tRes.HasRayCastResult()) { + if (tRes.GetRayCastResult().GetT() < bestMag) { + ent->Touch(*this, mgr); + bestMag = tRes.GetRayCastResult().GetT(); + res = tRes.GetRayCastResult(); + x2c6_pendingDamagee = idOut = tRes.GetActorId(); + } + } else { + auto tb = ent->GetTouchBounds(); + CGameProjectile* projObj = nullptr; + if (TCastToPtr door = ent) { + tb = door->GetProjectileBounds(); + } else if (TCastToPtr proj = ent) { + tb.emplace(proj->GetProjectileBounds()); + projObj = proj.GetPtr(); + } + if (!tb) + continue; + + CCollidableAABox prim(*tb, ent->GetMaterialList()); + CRayCastResult res3 = + prim.CastRayInternal(CInternalRayCastStructure(start, dir, mag, {}, CMaterialFilter::skPassEverything)); + if (res3.IsValid()) { + if (res3.GetT() < bestMag) { + bestMag = res3.GetT(); + res = res3; + x2c6_pendingDamagee = idOut = tRes.GetActorId(); + } + } else if (tb->pointInside(start) || (projObj && projObj->GetProjectileBounds().intersects(*tb))) { + x2c6_pendingDamagee = idOut = ent->GetUniqueId(); + zeus::CUnitVector3f norm(-dir); + res = CRayCastResult(0.f, start, {norm, norm.dot(start)}, ent->GetMaterialList()); + break; + } + } + } + } + + if (x2e4_27_inWater && idOut == kInvalidUniqueId) + x2e4_27_inWater = false; + + return res; } -CProjectileTouchResult CGameProjectile::CanCollideWith(CActor& act, CStateManager& mgr) -{ - if (act.GetDamageVulnerability()->GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false) == - EVulnerability::PassThrough) - { - return {kInvalidUniqueId, {}}; - } - else - { - if (TCastToPtr(act)) - { - return CanCollideWithTrigger(act, mgr); - } - else if (TCastToPtr(act) || TCastToPtr(act) || - CPatterned::CastTo(&act)) - { - return CanCollideWithComplexCollision(act, mgr); - } - else - { - return CanCollideWithGameObject(act, mgr); - } - } -} - -CProjectileTouchResult CGameProjectile::CanCollideWithComplexCollision(CActor& act, CStateManager& mgr) -{ - CPhysicsActor* useAct = nullptr; - if (TCastToPtr plat = act) - { - if (plat->HasComplexCollision()) - useAct = plat.GetPtr(); - } - else if (MP1::CPuddleToadGamma* toad = CPatterned::CastTo(&act)) - { - useAct = toad; - } - else if (TCastToPtr cact = act) - { - if (cact->GetOwnerId() == xec_ownerId) - return {kInvalidUniqueId, {}}; - useAct = cact.GetPtr(); - } - - if (useAct) - { - const CCollisionPrimitive* prim = useAct->GetCollisionPrimitive(); - zeus::CTransform xf = useAct->GetPrimitiveTransform(); - zeus::CVector3f deltaPos = GetTranslation() - x298_lastOrigin; - if (deltaPos.canBeNormalized()) - { - zeus::CVector3f dir = deltaPos.normalized(); - float mag = deltaPos.magnitude(); - CRayCastResult res = - prim->CastRayInternal({x298_lastOrigin, dir, mag, xf, - CMaterialFilter::MakeIncludeExclude( - {EMaterialTypes::Solid}, - {EMaterialTypes::ProjectilePassthrough})}); - if (!res.IsValid()) - { - if (prim->GetPrimType() == FOURCC('SPHR')) - { - mag *= 2.f; - CRayCastResult res2 = - prim->CastRayInternal({x298_lastOrigin - dir * mag, dir, deltaPos.magnitude(), xf, - CMaterialFilter::MakeIncludeExclude( - {EMaterialTypes::Solid}, - {EMaterialTypes::ProjectilePassthrough})}); - if (res2.IsValid()) - return {act.GetUniqueId(), {res2}}; - } - else if (TCastToPtr cAct = act) - { - float rad = cAct->GetSphereRadius(); - if ((x298_lastOrigin - GetTranslation()).magSquared() < rad * rad) - { - zeus::CVector3f point = x298_lastOrigin - dir * rad * 1.125f; - zeus::CUnitVector3f revDir(-dir); - return {act.GetUniqueId(), {{0.f, point, {revDir, point.dot(revDir)}, act.GetMaterialList()}}}; - } - } - return {kInvalidUniqueId, {}}; - } - else - { - return {act.GetUniqueId(), {res}}; - } - } - else - { - return {kInvalidUniqueId, {}}; - } - } - else - { - return {act.GetUniqueId(), {}}; - } -} - -CProjectileTouchResult CGameProjectile::CanCollideWithGameObject(CActor& act, CStateManager& mgr) -{ - TCastToPtr proj = act; - if (!proj) - { - if (!act.GetMaterialList().HasMaterial(EMaterialTypes::Solid) && !act.HealthInfo(mgr)) - { - return {kInvalidUniqueId, {}}; - } - else if (act.GetUniqueId() == xec_ownerId) - { - return {kInvalidUniqueId, {}}; - } - else if (act.GetUniqueId() == x2c2_lastResolvedObj) - { - return {kInvalidUniqueId, {}}; - } - else if (xf8_filter.GetExcludeList().Intersection(act.GetMaterialList())) - { - return {kInvalidUniqueId, {}}; - } - else if (TCastToPtr ai = act) - { - if (!ai->CanBeShot(mgr, int(xe8_projectileAttribs))) - return {kInvalidUniqueId, {}}; - } - } - else if ((xe8_projectileAttribs & EProjectileAttrib::PartialCharge) == EProjectileAttrib::PartialCharge || - (proj->xe8_projectileAttribs & EProjectileAttrib::PartialCharge) == EProjectileAttrib::PartialCharge) - { - return {act.GetUniqueId(), {}}; - } - else if ((xe8_projectileAttribs & EProjectileAttrib::PartialCharge) != EProjectileAttrib::PartialCharge && - (proj->xe8_projectileAttribs & EProjectileAttrib::PartialCharge) != EProjectileAttrib::PartialCharge) - { - return {kInvalidUniqueId, {}}; - } - return {act.GetUniqueId(), {}}; -} - -CProjectileTouchResult CGameProjectile::CanCollideWithTrigger(CActor& act, CStateManager& mgr) -{ - bool isWater = TCastToPtr(act).operator bool(); - if (isWater) - { - bool enteredWater = false; - if (isWater && !x2e4_25_startedUnderwater) - { - if (!x170_projectile.GetWeaponDescription()->xa4_EWTR) - enteredWater = true; - } - /* This case is logically unreachable */ - bool leftWater = false; - if (!isWater && x2e4_25_startedUnderwater) - { - if (!x170_projectile.GetWeaponDescription()->xa5_LWTR) - leftWater = true; - } - return {(enteredWater || leftWater) ? act.GetUniqueId() : kInvalidUniqueId, {}}; - } +CProjectileTouchResult CGameProjectile::CanCollideWith(CActor& act, CStateManager& mgr) { + if (act.GetDamageVulnerability()->GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false) == + EVulnerability::PassThrough) { return {kInvalidUniqueId, {}}; + } else { + if (TCastToPtr(act)) { + return CanCollideWithTrigger(act, mgr); + } else if (TCastToPtr(act) || TCastToPtr(act) || + CPatterned::CastTo(&act)) { + return CanCollideWithComplexCollision(act, mgr); + } else { + return CanCollideWithGameObject(act, mgr); + } + } } -zeus::CAABox CGameProjectile::GetProjectileBounds() const -{ - return {{std::min(x298_lastOrigin.x(), GetTranslation().x()) - x2a4_projExtent, - std::min(x298_lastOrigin.y(), GetTranslation().y()) - x2a4_projExtent, - std::min(x298_lastOrigin.z(), GetTranslation().z()) - x2a4_projExtent}, - {std::max(x298_lastOrigin.x(), GetTranslation().x()) + x2a4_projExtent, - std::max(x298_lastOrigin.y(), GetTranslation().y()) + x2a4_projExtent, - std::max(x298_lastOrigin.z(), GetTranslation().z()) + x2a4_projExtent}}; +CProjectileTouchResult CGameProjectile::CanCollideWithComplexCollision(CActor& act, CStateManager& mgr) { + CPhysicsActor* useAct = nullptr; + if (TCastToPtr plat = act) { + if (plat->HasComplexCollision()) + useAct = plat.GetPtr(); + } else if (MP1::CPuddleToadGamma* toad = CPatterned::CastTo(&act)) { + useAct = toad; + } else if (TCastToPtr cact = act) { + if (cact->GetOwnerId() == xec_ownerId) + return {kInvalidUniqueId, {}}; + useAct = cact.GetPtr(); + } + + if (useAct) { + const CCollisionPrimitive* prim = useAct->GetCollisionPrimitive(); + zeus::CTransform xf = useAct->GetPrimitiveTransform(); + zeus::CVector3f deltaPos = GetTranslation() - x298_lastOrigin; + if (deltaPos.canBeNormalized()) { + zeus::CVector3f dir = deltaPos.normalized(); + float mag = deltaPos.magnitude(); + CRayCastResult res = prim->CastRayInternal( + {x298_lastOrigin, dir, mag, xf, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough})}); + if (!res.IsValid()) { + if (prim->GetPrimType() == FOURCC('SPHR')) { + mag *= 2.f; + CRayCastResult res2 = prim->CastRayInternal( + {x298_lastOrigin - dir * mag, dir, deltaPos.magnitude(), xf, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough})}); + if (res2.IsValid()) + return {act.GetUniqueId(), {res2}}; + } else if (TCastToPtr cAct = act) { + float rad = cAct->GetSphereRadius(); + if ((x298_lastOrigin - GetTranslation()).magSquared() < rad * rad) { + zeus::CVector3f point = x298_lastOrigin - dir * rad * 1.125f; + zeus::CUnitVector3f revDir(-dir); + return {act.GetUniqueId(), {{0.f, point, {revDir, point.dot(revDir)}, act.GetMaterialList()}}}; + } + } + return {kInvalidUniqueId, {}}; + } else { + return {act.GetUniqueId(), {res}}; + } + } else { + return {kInvalidUniqueId, {}}; + } + } else { + return {act.GetUniqueId(), {}}; + } } -std::experimental::optional CGameProjectile::GetTouchBounds() const -{ - if (x2e4_24_active) - return {GetProjectileBounds()}; - return {}; +CProjectileTouchResult CGameProjectile::CanCollideWithGameObject(CActor& act, CStateManager& mgr) { + TCastToPtr proj = act; + if (!proj) { + if (!act.GetMaterialList().HasMaterial(EMaterialTypes::Solid) && !act.HealthInfo(mgr)) { + return {kInvalidUniqueId, {}}; + } else if (act.GetUniqueId() == xec_ownerId) { + return {kInvalidUniqueId, {}}; + } else if (act.GetUniqueId() == x2c2_lastResolvedObj) { + return {kInvalidUniqueId, {}}; + } else if (xf8_filter.GetExcludeList().Intersection(act.GetMaterialList())) { + return {kInvalidUniqueId, {}}; + } else if (TCastToPtr ai = act) { + if (!ai->CanBeShot(mgr, int(xe8_projectileAttribs))) + return {kInvalidUniqueId, {}}; + } + } else if ((xe8_projectileAttribs & EProjectileAttrib::PartialCharge) == EProjectileAttrib::PartialCharge || + (proj->xe8_projectileAttribs & EProjectileAttrib::PartialCharge) == EProjectileAttrib::PartialCharge) { + return {act.GetUniqueId(), {}}; + } else if ((xe8_projectileAttribs & EProjectileAttrib::PartialCharge) != EProjectileAttrib::PartialCharge && + (proj->xe8_projectileAttribs & EProjectileAttrib::PartialCharge) != EProjectileAttrib::PartialCharge) { + return {kInvalidUniqueId, {}}; + } + return {act.GetUniqueId(), {}}; } +CProjectileTouchResult CGameProjectile::CanCollideWithTrigger(CActor& act, CStateManager& mgr) { + bool isWater = TCastToPtr(act).operator bool(); + if (isWater) { + bool enteredWater = false; + if (isWater && !x2e4_25_startedUnderwater) { + if (!x170_projectile.GetWeaponDescription()->xa4_EWTR) + enteredWater = true; + } + /* This case is logically unreachable */ + bool leftWater = false; + if (!isWater && x2e4_25_startedUnderwater) { + if (!x170_projectile.GetWeaponDescription()->xa5_LWTR) + leftWater = true; + } + return {(enteredWater || leftWater) ? act.GetUniqueId() : kInvalidUniqueId, {}}; + } + return {kInvalidUniqueId, {}}; } + +zeus::CAABox CGameProjectile::GetProjectileBounds() const { + return {{std::min(x298_lastOrigin.x(), GetTranslation().x()) - x2a4_projExtent, + std::min(x298_lastOrigin.y(), GetTranslation().y()) - x2a4_projExtent, + std::min(x298_lastOrigin.z(), GetTranslation().z()) - x2a4_projExtent}, + {std::max(x298_lastOrigin.x(), GetTranslation().x()) + x2a4_projExtent, + std::max(x298_lastOrigin.y(), GetTranslation().y()) + x2a4_projExtent, + std::max(x298_lastOrigin.z(), GetTranslation().z()) + x2a4_projExtent}}; +} + +std::experimental::optional CGameProjectile::GetTouchBounds() const { + if (x2e4_24_active) + return {GetProjectileBounds()}; + return {}; +} + +} // namespace urde diff --git a/Runtime/Weapon/CGameProjectile.hpp b/Runtime/Weapon/CGameProjectile.hpp index b0f5794b7..b3f6d35b6 100644 --- a/Runtime/Weapon/CGameProjectile.hpp +++ b/Runtime/Weapon/CGameProjectile.hpp @@ -9,85 +9,80 @@ #include "Weapon/CProjectileWeapon.hpp" #include "Collision/CRayCastResult.hpp" -namespace urde -{ +namespace urde { class CGenDescription; class CWeaponDescription; -class CProjectileTouchResult -{ - TUniqueId x0_id; - std::experimental::optional x4_result; +class CProjectileTouchResult { + TUniqueId x0_id; + std::experimental::optional x4_result; + public: - CProjectileTouchResult(TUniqueId id, const std::experimental::optional& result) - : x0_id(id), x4_result(result) {} - TUniqueId GetActorId() const { return x0_id; } - bool HasRayCastResult() const { return x4_result.operator bool(); } - const CRayCastResult& GetRayCastResult() const { return *x4_result; } + CProjectileTouchResult(TUniqueId id, const std::experimental::optional& result) + : x0_id(id), x4_result(result) {} + TUniqueId GetActorId() const { return x0_id; } + bool HasRayCastResult() const { return x4_result.operator bool(); } + const CRayCastResult& GetRayCastResult() const { return *x4_result; } }; -class CGameProjectile : public CWeapon -{ +class CGameProjectile : public CWeapon { protected: - std::experimental::optional> x158_visorParticle; - u16 x168_visorSfx; - CProjectileWeapon x170_projectile; - zeus::CVector3f x298_lastOrigin; - float x2a4_projExtent; - float x2a8_homingDt = 0.03f; - double x2b0_targetHomingTime = 0.0; - double x2b8_curHomingTime = x2a8_homingDt; - TUniqueId x2c0_homingTargetId; - TUniqueId x2c2_lastResolvedObj = kInvalidUniqueId; - TUniqueId x2c4_ = kInvalidUniqueId; - TUniqueId x2c6_pendingDamagee = kInvalidUniqueId; - TUniqueId x2c8_projectileLight = kInvalidUniqueId; - CAssetId x2cc_wpscId; - std::vector x2d0_touchResults; - float x2e0_minHomingDist = 0.f; - union - { - struct - { - bool x2e4_24_active : 1; - bool x2e4_25_startedUnderwater : 1; - bool x2e4_26_waterUpdate : 1; - bool x2e4_27_inWater : 1; - bool x2e4_28_sendProjectileCollideMsg : 1; - }; + std::experimental::optional> x158_visorParticle; + u16 x168_visorSfx; + CProjectileWeapon x170_projectile; + zeus::CVector3f x298_lastOrigin; + float x2a4_projExtent; + float x2a8_homingDt = 0.03f; + double x2b0_targetHomingTime = 0.0; + double x2b8_curHomingTime = x2a8_homingDt; + TUniqueId x2c0_homingTargetId; + TUniqueId x2c2_lastResolvedObj = kInvalidUniqueId; + TUniqueId x2c4_ = kInvalidUniqueId; + TUniqueId x2c6_pendingDamagee = kInvalidUniqueId; + TUniqueId x2c8_projectileLight = kInvalidUniqueId; + CAssetId x2cc_wpscId; + std::vector x2d0_touchResults; + float x2e0_minHomingDist = 0.f; + union { + struct { + bool x2e4_24_active : 1; + bool x2e4_25_startedUnderwater : 1; + bool x2e4_26_waterUpdate : 1; + bool x2e4_27_inWater : 1; + bool x2e4_28_sendProjectileCollideMsg : 1; }; + }; + public: - CGameProjectile(bool active, const TToken&, std::string_view name, - EWeaponType wType, const zeus::CTransform& xf, EMaterialTypes excludeMat, - const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, - TUniqueId homingTarget, EProjectileAttrib attribs, bool underwater, const zeus::CVector3f& scale, - const std::experimental::optional>& visorParticle, - u16 visorSfx, bool sendCollideMsg); + CGameProjectile(bool active, const TToken&, std::string_view name, EWeaponType wType, + const zeus::CTransform& xf, EMaterialTypes excludeMat, const CDamageInfo& dInfo, TUniqueId uid, + TAreaId aid, TUniqueId owner, TUniqueId homingTarget, EProjectileAttrib attribs, bool underwater, + const zeus::CVector3f& scale, + const std::experimental::optional>& visorParticle, u16 visorSfx, + bool sendCollideMsg); - virtual void Accept(IVisitor &visitor); - virtual void ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); - static EProjectileAttrib GetBeamAttribType(EWeaponType wType); - void DeleteProjectileLight(CStateManager&); - void CreateProjectileLight(std::string_view, const CLight&, CStateManager&); - void Chase(float dt, CStateManager& mgr); - void UpdateHoming(float dt, CStateManager& mgr); - void UpdateProjectileMovement(float dt, CStateManager& mgr); - CRayCastResult DoCollisionCheck(TUniqueId& idOut, CStateManager& mgr); - void ApplyDamageToActors(CStateManager& mgr, const CDamageInfo& dInfo); - void FluidFxThink(EFluidState state, CScriptWater& water, CStateManager& mgr); - CRayCastResult RayCollisionCheckWithWorld(TUniqueId& idOut, const zeus::CVector3f& start, - const zeus::CVector3f& end, float mag, - const rstl::reserved_vector& nearList, - CStateManager& mgr); - CProjectileTouchResult CanCollideWith(CActor& act, CStateManager& mgr); - CProjectileTouchResult CanCollideWithComplexCollision(CActor& act, CStateManager& mgr); - CProjectileTouchResult CanCollideWithGameObject(CActor& act, CStateManager& mgr); - CProjectileTouchResult CanCollideWithTrigger(CActor& act, CStateManager& mgr); - zeus::CAABox GetProjectileBounds() const; - std::experimental::optional GetTouchBounds() const; - TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; } - zeus::CVector3f GetPreviousPos() const { return x298_lastOrigin; } + virtual void Accept(IVisitor& visitor); + virtual void ResolveCollisionWithActor(const CRayCastResult& res, CActor& act, CStateManager& mgr); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + static EProjectileAttrib GetBeamAttribType(EWeaponType wType); + void DeleteProjectileLight(CStateManager&); + void CreateProjectileLight(std::string_view, const CLight&, CStateManager&); + void Chase(float dt, CStateManager& mgr); + void UpdateHoming(float dt, CStateManager& mgr); + void UpdateProjectileMovement(float dt, CStateManager& mgr); + CRayCastResult DoCollisionCheck(TUniqueId& idOut, CStateManager& mgr); + void ApplyDamageToActors(CStateManager& mgr, const CDamageInfo& dInfo); + void FluidFxThink(EFluidState state, CScriptWater& water, CStateManager& mgr); + CRayCastResult RayCollisionCheckWithWorld(TUniqueId& idOut, const zeus::CVector3f& start, const zeus::CVector3f& end, + float mag, const rstl::reserved_vector& nearList, + CStateManager& mgr); + CProjectileTouchResult CanCollideWith(CActor& act, CStateManager& mgr); + CProjectileTouchResult CanCollideWithComplexCollision(CActor& act, CStateManager& mgr); + CProjectileTouchResult CanCollideWithGameObject(CActor& act, CStateManager& mgr); + CProjectileTouchResult CanCollideWithTrigger(CActor& act, CStateManager& mgr); + zeus::CAABox GetProjectileBounds() const; + std::experimental::optional GetTouchBounds() const; + TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; } + zeus::CVector3f GetPreviousPos() const { return x298_lastOrigin; } }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CGrappleArm.cpp b/Runtime/Weapon/CGrappleArm.cpp index 32d83debf..420047a66 100644 --- a/Runtime/Weapon/CGrappleArm.cpp +++ b/Runtime/Weapon/CGrappleArm.cpp @@ -9,8 +9,7 @@ #include "Graphics/CSkinnedModel.hpp" #include "Graphics/CVertexMorphEffect.hpp" -namespace urde -{ +namespace urde { float CGrappleArm::g_GrappleBeamAnglePhaseDelta = 0.875f; float CGrappleArm::g_GrappleBeamXWaveAmplitude = 0.25f; @@ -18,666 +17,579 @@ float CGrappleArm::g_GrappleBeamZWaveAmplitude = 0.125f; float CGrappleArm::g_GrappleBeamSpeed = 5.f; CGrappleArm::CGrappleArm(const zeus::CVector3f& scale) -: x0_grappleArmModel(CAnimRes(g_tweakGunRes->x8_grappleArm, 0, scale, 41, false)), - xa0_grappleGearModel(CStaticRes(NWeaponTypes::get_asset_id_from_name("GrappleGear"), scale)), - xec_grapNoz1Model(CStaticRes(NWeaponTypes::get_asset_id_from_name("GrapNoz1"), scale)), - x138_grapNoz2Model(CStaticRes(NWeaponTypes::get_asset_id_from_name("GrapNoz2"), scale)), - x184_grappleArm(g_SimplePool->GetObj(SObjectTag{FOURCC('ANCS'), g_tweakGunRes->x8_grappleArm})), - x31c_scale(scale), - x354_grappleSegmentDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xb4_grappleSegment})), - x360_grappleClawDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xb8_grappleClaw})), - x36c_grappleHitDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xbc_grappleHit})), - x378_grappleMuzzleDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xc0_grappleMuzzle})), - x384_grappleSwooshDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), g_tweakGunRes->xc4_grappleSwoosh})), - x390_grappleSegmentGen(std::make_unique(x354_grappleSegmentDesc)), - x394_grappleClawGen(std::make_unique(x360_grappleClawDesc)), - x398_grappleHitGen(std::make_unique(x36c_grappleHitDesc)), - x39c_grappleMuzzleGen(std::make_unique(x378_grappleMuzzleDesc)), - x3a0_grappleSwooshGen(std::make_unique(x384_grappleSwooshDesc, 0)), - x3a4_rainSplashGenerator(std::make_unique(scale, 20, 2, 0.f, 0.125f)) -{ - x0_grappleArmModel->SetSortThermal(true); - xa0_grappleGearModel.SetSortThermal(true); - xec_grapNoz1Model.SetSortThermal(true); - x138_grapNoz2Model.SetSortThermal(true); +: x0_grappleArmModel(CAnimRes(g_tweakGunRes->x8_grappleArm, 0, scale, 41, false)) +, xa0_grappleGearModel(CStaticRes(NWeaponTypes::get_asset_id_from_name("GrappleGear"), scale)) +, xec_grapNoz1Model(CStaticRes(NWeaponTypes::get_asset_id_from_name("GrapNoz1"), scale)) +, x138_grapNoz2Model(CStaticRes(NWeaponTypes::get_asset_id_from_name("GrapNoz2"), scale)) +, x184_grappleArm(g_SimplePool->GetObj(SObjectTag{FOURCC('ANCS'), g_tweakGunRes->x8_grappleArm})) +, x31c_scale(scale) +, x354_grappleSegmentDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xb4_grappleSegment})) +, x360_grappleClawDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xb8_grappleClaw})) +, x36c_grappleHitDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xbc_grappleHit})) +, x378_grappleMuzzleDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xc0_grappleMuzzle})) +, x384_grappleSwooshDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), g_tweakGunRes->xc4_grappleSwoosh})) +, x390_grappleSegmentGen(std::make_unique(x354_grappleSegmentDesc)) +, x394_grappleClawGen(std::make_unique(x360_grappleClawDesc)) +, x398_grappleHitGen(std::make_unique(x36c_grappleHitDesc)) +, x39c_grappleMuzzleGen(std::make_unique(x378_grappleMuzzleDesc)) +, x3a0_grappleSwooshGen(std::make_unique(x384_grappleSwooshDesc, 0)) +, x3a4_rainSplashGenerator(std::make_unique(scale, 20, 2, 0.f, 0.125f)) { + x0_grappleArmModel->SetSortThermal(true); + xa0_grappleGearModel.SetSortThermal(true); + xec_grapNoz1Model.SetSortThermal(true); + x138_grapNoz2Model.SetSortThermal(true); - g_GrappleBeamAnglePhaseDelta = g_tweakPlayer->GetGrappleBeamAnglePhaseDelta(); - g_GrappleBeamXWaveAmplitude = g_tweakPlayer->GetGrappleBeamXWaveAmplitude(); - g_GrappleBeamZWaveAmplitude = g_tweakPlayer->GetGrappleBeamZWaveAmplitude(); - g_GrappleBeamSpeed = g_tweakPlayer->GetGrappleBeamSpeed(); + g_GrappleBeamAnglePhaseDelta = g_tweakPlayer->GetGrappleBeamAnglePhaseDelta(); + g_GrappleBeamXWaveAmplitude = g_tweakPlayer->GetGrappleBeamXWaveAmplitude(); + g_GrappleBeamZWaveAmplitude = g_tweakPlayer->GetGrappleBeamZWaveAmplitude(); + g_GrappleBeamSpeed = g_tweakPlayer->GetGrappleBeamSpeed(); - x39c_grappleMuzzleGen->SetParticleEmission(false); - x390_grappleSegmentGen->SetParticleEmission(false); - x3a0_grappleSwooshGen->DoGrappleWarmup(); + x39c_grappleMuzzleGen->SetParticleEmission(false); + x390_grappleSegmentGen->SetParticleEmission(false); + x3a0_grappleSwooshGen->DoGrappleWarmup(); - BuildSuitDependencyList(); - LoadAnimations(); + BuildSuitDependencyList(); + LoadAnimations(); } -static const char* skDependencyNames[] = -{ - "PowerSuit_DGRP", - "GravitySuit_DGRP", - "VariaSuit_DGRP", - "PhazonSuit_DGRP", - "FusionSuit_DGRP", - "FusionSuitG_DGRP", - "FusionSuitV_DGRP", - "FusionSuitP_DGRP", +static const char* skDependencyNames[] = { + "PowerSuit_DGRP", "GravitySuit_DGRP", "VariaSuit_DGRP", "PhazonSuit_DGRP", + "FusionSuit_DGRP", "FusionSuitG_DGRP", "FusionSuitV_DGRP", "FusionSuitP_DGRP", }; -void CGrappleArm::FillTokenVector(const std::vector& tags, std::vector& objects) -{ - objects.reserve(tags.size()); - for (const SObjectTag& tag : tags) - objects.push_back(g_SimplePool->GetObj(tag)); +void CGrappleArm::FillTokenVector(const std::vector& tags, std::vector& objects) { + objects.reserve(tags.size()); + for (const SObjectTag& tag : tags) + objects.push_back(g_SimplePool->GetObj(tag)); } -void CGrappleArm::BuildSuitDependencyList() -{ - x184_grappleArm.Lock(); - for (const char* name : skDependencyNames) - { - TLockedToken dgrp = g_SimplePool->GetObj(name); - x19c_suitDeps.emplace_back(); - std::vector& depsOut = x19c_suitDeps.back(); - FillTokenVector(dgrp->GetObjectTagVector(), depsOut); - } +void CGrappleArm::BuildSuitDependencyList() { + x184_grappleArm.Lock(); + for (const char* name : skDependencyNames) { + TLockedToken dgrp = g_SimplePool->GetObj(name); + x19c_suitDeps.emplace_back(); + std::vector& depsOut = x19c_suitDeps.back(); + FillTokenVector(dgrp->GetObjectTagVector(), depsOut); + } } -void CGrappleArm::LoadAnimations() -{ - NWeaponTypes::get_token_vector(*x0_grappleArmModel->GetAnimationData(), 0, 42, x18c_anims, true); - x0_grappleArmModel = std::experimental::nullopt; +void CGrappleArm::LoadAnimations() { + NWeaponTypes::get_token_vector(*x0_grappleArmModel->GetAnimationData(), 0, 42, x18c_anims, true); + x0_grappleArmModel = std::experimental::nullopt; } -void CGrappleArm::AsyncLoadSuit(CStateManager& mgr) -{ - CPlayerState::EPlayerSuit suit = NWeaponTypes::get_current_suit(mgr); - if (suit == x3a8_loadedSuit) - return; +void CGrappleArm::AsyncLoadSuit(CStateManager& mgr) { + CPlayerState::EPlayerSuit suit = NWeaponTypes::get_current_suit(mgr); + if (suit == x3a8_loadedSuit) + return; - x0_grappleArmModel = std::experimental::nullopt; - x3b2_29_suitLoading = true; - if (x3a8_loadedSuit != CPlayerState::EPlayerSuit::Invalid) - { - NWeaponTypes::unlock_tokens(x19c_suitDeps[int(x3a8_loadedSuit)]); - x19c_suitDeps[int(x3a8_loadedSuit)].clear(); - } + x0_grappleArmModel = std::experimental::nullopt; + x3b2_29_suitLoading = true; + if (x3a8_loadedSuit != CPlayerState::EPlayerSuit::Invalid) { + NWeaponTypes::unlock_tokens(x19c_suitDeps[int(x3a8_loadedSuit)]); + x19c_suitDeps[int(x3a8_loadedSuit)].clear(); + } - if (suit < CPlayerState::EPlayerSuit::Power || suit > CPlayerState::EPlayerSuit::FusionPhazon) - x3a8_loadedSuit = CPlayerState::EPlayerSuit::Power; - else - x3a8_loadedSuit = suit; + if (suit < CPlayerState::EPlayerSuit::Power || suit > CPlayerState::EPlayerSuit::FusionPhazon) + x3a8_loadedSuit = CPlayerState::EPlayerSuit::Power; + else + x3a8_loadedSuit = suit; - NWeaponTypes::lock_tokens(x19c_suitDeps[int(x3a8_loadedSuit)]); + NWeaponTypes::lock_tokens(x19c_suitDeps[int(x3a8_loadedSuit)]); } -void CGrappleArm::ResetAuxParams(bool resetGunController) -{ - x3b2_24_active = false; - x3b2_27_armMoving = false; - x2e0_auxXf = zeus::CTransform::Identity(); - if (resetGunController) - x328_gunController->Reset(); +void CGrappleArm::ResetAuxParams(bool resetGunController) { + x3b2_24_active = false; + x3b2_27_armMoving = false; + x2e0_auxXf = zeus::CTransform::Identity(); + if (resetGunController) + x328_gunController->Reset(); } -void CGrappleArm::DisconnectGrappleBeam() -{ - x394_grappleClawGen->SetParticleEmission(false); +void CGrappleArm::DisconnectGrappleBeam() { + x394_grappleClawGen->SetParticleEmission(false); + x3b2_25_beamActive = false; + GrappleBeamDisconnected(); +} + +void CGrappleArm::SetAnimState(EArmState state) { + if (x334_animState == state) + return; + + x0_grappleArmModel->AnimationData()->EnableLooping(false); + x3b2_28_isGrappling = true; + + switch (state) { + case EArmState::IntoGrapple: { + ResetAuxParams(true); + CAnimPlaybackParms parms(0, -1, 1.f, true); + x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); x3b2_25_beamActive = false; - GrappleBeamDisconnected(); + x3b2_24_active = true; + break; + } + case EArmState::IntoGrappleIdle: { + CAnimPlaybackParms parms(1, -1, 1.f, true); + x0_grappleArmModel->AnimationData()->EnableLooping(true); + x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); + break; + } + case EArmState::FireGrapple: { + CAnimPlaybackParms parms(2, -1, 1.f, true); + x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); + break; + } + case EArmState::ConnectGrapple: { + CAnimPlaybackParms parms(3, -1, 1.f, true); + x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); + break; + } + case EArmState::Connected: { + CAnimPlaybackParms parms(3, -1, 1.f, true); + x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); + break; + } + case EArmState::OutOfGrapple: { + CAnimPlaybackParms parms(4, -1, 1.f, true); + x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); + DisconnectGrappleBeam(); + break; + } + case EArmState::Done: + x3b2_28_isGrappling = false; + break; + default: + break; + } + + x334_animState = state; } -void CGrappleArm::SetAnimState(EArmState state) -{ - if (x334_animState == state) - return; - - x0_grappleArmModel->AnimationData()->EnableLooping(false); - x3b2_28_isGrappling = true; - - switch (state) - { - case EArmState::IntoGrapple: - { - ResetAuxParams(true); - CAnimPlaybackParms parms(0, -1, 1.f, true); - x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); - x3b2_25_beamActive = false; - x3b2_24_active = true; - break; - } - case EArmState::IntoGrappleIdle: - { - CAnimPlaybackParms parms(1, -1, 1.f, true); - x0_grappleArmModel->AnimationData()->EnableLooping(true); - x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); - break; - } - case EArmState::FireGrapple: - { - CAnimPlaybackParms parms(2, -1, 1.f, true); - x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); - break; - } - case EArmState::ConnectGrapple: - { - CAnimPlaybackParms parms(3, -1, 1.f, true); - x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); - break; - } - case EArmState::Connected: - { - CAnimPlaybackParms parms(3, -1, 1.f, true); - x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); - break; - } - case EArmState::OutOfGrapple: - { - CAnimPlaybackParms parms(4, -1, 1.f, true); - x0_grappleArmModel->AnimationData()->SetAnimation(parms, false); - DisconnectGrappleBeam(); - break; - } - case EArmState::Done: - x3b2_28_isGrappling = false; - break; - default: - break; - } - - x334_animState = state; +void CGrappleArm::Activate(bool intoGrapple) { + SetAnimState(intoGrapple ? EArmState::IntoGrapple : EArmState::OutOfGrapple); } -void CGrappleArm::Activate(bool intoGrapple) -{ - SetAnimState(intoGrapple ? EArmState::IntoGrapple : EArmState::OutOfGrapple); +void CGrappleArm::GrappleBeamDisconnected() { + if (x32c_grappleLoopSfx) { + CSfxManager::SfxStop(x32c_grappleLoopSfx); + x32c_grappleLoopSfx.reset(); + } } -void CGrappleArm::GrappleBeamDisconnected() -{ - if (x32c_grappleLoopSfx) - { - CSfxManager::SfxStop(x32c_grappleLoopSfx); - x32c_grappleLoopSfx.reset(); - } +void CGrappleArm::GrappleBeamConnected() { + if (!x32c_grappleLoopSfx) + x32c_grappleLoopSfx = NWeaponTypes::play_sfx(SFXsam_grapple_lp, false, true, -0.15f); } -void CGrappleArm::GrappleBeamConnected() -{ - if (!x32c_grappleLoopSfx) - x32c_grappleLoopSfx = NWeaponTypes::play_sfx(SFXsam_grapple_lp, false, true, -0.15f); +void CGrappleArm::RenderGrappleBeam(const CStateManager& mgr, const zeus::CVector3f& pos) { + if (x3b2_24_active && !x3b2_29_suitLoading) { + zeus::CTransform tmpXf = zeus::CTransform::Translate(pos) * x220_xf; + if (x3b2_25_beamActive) { + if (x3b2_26_grappleHit) + x398_grappleHitGen->Render(); + x394_grappleClawGen->Render(); + x3a0_grappleSwooshGen->Render(); + x390_grappleSegmentGen->Render(); + zeus::CTransform backupViewMtx = CGraphics::g_ViewMatrix; + CGraphics::SetViewPointMatrix(tmpXf.inverse() * backupViewMtx); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + x39c_grappleMuzzleGen->Render(); + CGraphics::SetViewPointMatrix(backupViewMtx); + } + } } -void CGrappleArm::RenderGrappleBeam(const CStateManager& mgr, const zeus::CVector3f& pos) -{ - if (x3b2_24_active && !x3b2_29_suitLoading) - { - zeus::CTransform tmpXf = zeus::CTransform::Translate(pos) * x220_xf; - if (x3b2_25_beamActive) - { - if (x3b2_26_grappleHit) - x398_grappleHitGen->Render(); - x394_grappleClawGen->Render(); - x3a0_grappleSwooshGen->Render(); - x390_grappleSegmentGen->Render(); - zeus::CTransform backupViewMtx = CGraphics::g_ViewMatrix; - CGraphics::SetViewPointMatrix(tmpXf.inverse() * backupViewMtx); - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - x39c_grappleMuzzleGen->Render(); - CGraphics::SetViewPointMatrix(backupViewMtx); - } +void CGrappleArm::TouchModel(const CStateManager& mgr) const { + if (x3b2_24_active && !x3b2_29_suitLoading) { + x0_grappleArmModel->Touch(mgr, 0); + if (x50_grappleArmSkeletonModel) + x50_grappleArmSkeletonModel->Touch(mgr, 0); + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam)) { + xa0_grappleGearModel.Touch(mgr, 0); + xec_grapNoz1Model.Touch(mgr, 0); + x138_grapNoz2Model.Touch(mgr, 0); } + } } -void CGrappleArm::TouchModel(const CStateManager& mgr) const -{ - if (x3b2_24_active && !x3b2_29_suitLoading) - { - x0_grappleArmModel->Touch(mgr, 0); - if (x50_grappleArmSkeletonModel) - x50_grappleArmSkeletonModel->Touch(mgr, 0); - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam)) - { - xa0_grappleGearModel.Touch(mgr, 0); - xec_grapNoz1Model.Touch(mgr, 0); - x138_grapNoz2Model.Touch(mgr, 0); - } - } +void CGrappleArm::LoadSuitPoll() { + if (NWeaponTypes::are_tokens_ready(x19c_suitDeps[int(x3a8_loadedSuit)])) { + x0_grappleArmModel.emplace(CAnimRes(g_tweakGunRes->x8_grappleArm, int(x3a8_loadedSuit), x31c_scale, 41, false)); + x0_grappleArmModel->SetSortThermal(true); + x328_gunController = std::make_unique(*x0_grappleArmModel); + x3b2_29_suitLoading = false; + } } -void CGrappleArm::LoadSuitPoll() -{ - if (NWeaponTypes::are_tokens_ready(x19c_suitDeps[int(x3a8_loadedSuit)])) - { - x0_grappleArmModel.emplace(CAnimRes(g_tweakGunRes->x8_grappleArm, int(x3a8_loadedSuit), x31c_scale, 41, false)); - x0_grappleArmModel->SetSortThermal(true); - x328_gunController = std::make_unique(*x0_grappleArmModel); - x3b2_29_suitLoading = false; - } +void CGrappleArm::BuildXRayModel() { + x50_grappleArmSkeletonModel.emplace(CAnimRes(g_tweakGunRes->x8_grappleArm, 8, x31c_scale, + !x328_gunController ? 41 : x328_gunController->GetCurAnimId(), false)); + x50_grappleArmSkeletonModel->SetSortThermal(true); } -void CGrappleArm::BuildXRayModel() -{ - x50_grappleArmSkeletonModel.emplace(CAnimRes(g_tweakGunRes->x8_grappleArm, 8, x31c_scale, - !x328_gunController ? 41 : x328_gunController->GetCurAnimId(), false)); - x50_grappleArmSkeletonModel->SetSortThermal(true); -} - -void CGrappleArm::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type) -{ - switch (type) - { - case EUserEventType::Projectile: - if (x3b2_27_armMoving) - return; - x3b2_25_beamActive = true; - x398_grappleHitGen = std::make_unique(x36c_grappleHitDesc); - x39c_grappleMuzzleGen = std::make_unique(x378_grappleMuzzleDesc); - x338_beamT = 0.f; - x33c_beamDist = 0.f; - x340_anglePhase = 0.f; - x344_xAmplitude = g_GrappleBeamXWaveAmplitude; - x348_zAmplitude = g_GrappleBeamZWaveAmplitude; - x398_grappleHitGen->SetParticleEmission(false); - x394_grappleClawGen->SetParticleEmission(true); - NWeaponTypes::play_sfx(SFXsam_grapple_fire, false, false, -0.15f); - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerGrappleFire, 1.f, ERumblePriority::Three); - break; - default: - break; - } -} - -void CGrappleArm::DoUserAnimEvents(CStateManager& mgr) -{ - zeus::CVector3f armToCam = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation() - x220_xf.origin; - const CAnimData& animData = *x0_grappleArmModel->GetAnimationData(); - for (int i=0 ; iUpdate(dt, mgr)) - ResetAuxParams(false); -} - -void CGrappleArm::UpdateGrappleBeamFx(const zeus::CVector3f& beamGunPos, - const zeus::CVector3f& beamAirPos, CStateManager& mgr) -{ - x394_grappleClawGen->SetTranslation(beamAirPos); - x390_grappleSegmentGen->SetParticleEmission(true); - - zeus::CVector3f segmentDelta = beamAirPos - beamGunPos; - zeus::CVector3f swooshSegmentDelta = segmentDelta * 0.02f; - int numSegments = int(2.f * segmentDelta.magnitude() + 1.f); - segmentDelta = (1.f / float(numSegments)) * segmentDelta; - - zeus::CVector3f segmentPos = beamGunPos; - zeus::CTransform rotation = x220_xf.getRotation(); - for (int i=0 ; i 0) - vec = rotation * zeus::CVector3f(std::cos(i + x340_anglePhase) * x344_xAmplitude, 0.f, - std::sin(float(i)) * x348_zAmplitude); - x390_grappleSegmentGen->SetTranslation(vec * segmentPos); - x390_grappleSegmentGen->ForceParticleCreation(1); - segmentPos += segmentDelta; - } - - x390_grappleSegmentGen->SetParticleEmission(false); - x3a0_grappleSwooshGen->DoGrappleUpdate(beamGunPos, rotation, x340_anglePhase, x344_xAmplitude, - x348_zAmplitude, swooshSegmentDelta); -} - -bool CGrappleArm::UpdateGrappleBeam(float dt, const zeus::CTransform& beamLoc, CStateManager& mgr) -{ - bool beamConnected = false; - if (TCastToConstPtr act = mgr.GetObjectById(mgr.GetPlayer().GetOrbitTargetId())) - x310_grapplePointPos = act->GetTranslation(); - else - x310_grapplePointPos = x220_xf.origin; - - zeus::CVector3f beamGunPos = (x220_xf * beamLoc).origin; - zeus::CVector3f beamAirPos = beamGunPos * (1.f - x338_beamT) + x310_grapplePointPos * x338_beamT; - - switch (x334_animState) - { - case EArmState::FireGrapple: - case EArmState::Three: - { - float gunToPointMag = (x310_grapplePointPos - beamGunPos).magnitude(); - if (gunToPointMag > 0.f) - x338_beamT = x33c_beamDist / gunToPointMag; - else - x338_beamT = 1.f; - float speedMult = - mgr.GetPlayer().GetPlayerMovementState() != CPlayer::EPlayerMovementState::OnGround ? 2.f : 1.f; - x33c_beamDist += speedMult * (dt * g_GrappleBeamSpeed); - if (x338_beamT >= 1.f) - { - x338_beamT = 1.f; - beamConnected = true; - } - break; - } - case EArmState::ConnectGrapple: - { - float delta = 4.f * dt; - x344_xAmplitude -= delta; - x348_zAmplitude -= delta; - if (x344_xAmplitude < 0.f) - x344_xAmplitude = 0.f; - if (x348_zAmplitude < 0.f) - x348_zAmplitude = 0.f; - break; - } - default: - break; - } - - if (x3b2_25_beamActive) - { - x340_anglePhase += g_GrappleBeamAnglePhaseDelta; - UpdateGrappleBeamFx(beamGunPos, beamAirPos, mgr); - x394_grappleClawGen->Update(dt); - x390_grappleSegmentGen->Update(dt); - } - - return beamConnected; -} - -void CGrappleArm::UpdateSwingAction(float grappleSwingT, float dt, CStateManager& mgr) -{ - if (x3b2_29_suitLoading) - return; - - if (x334_animState == EArmState::FireGrapple) - DoUserAnimEvents(mgr); - - zeus::CTransform beamLocXf = x0_grappleArmModel->GetScaledLocatorTransform("LGBeam"); - bool grappleConnected = UpdateGrappleBeam(dt, beamLocXf, mgr); - - if ((grappleSwingT > 0.175f && grappleSwingT < 0.3f) || - (grappleSwingT > 0.7f && grappleSwingT < 0.9f)) - { - if (!CSfxManager::IsPlaying(x330_swooshSfx)) - { - x330_swooshSfx = NWeaponTypes::play_sfx(SFXsam_grapple_swoosh, false, false, -0.15f); - if (x3b0_rumbleHandle != -1) - mgr.GetRumbleManager().StopRumble(x3b0_rumbleHandle); - x3b0_rumbleHandle = mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerGrappleSwoosh, 1.f, ERumblePriority::Three); - } - } - - if (!x0_grappleArmModel->GetAnimationData()->IsAnimTimeRemaining(dt, "Whole Body")) - { - switch (x334_animState) - { - case EArmState::IntoGrapple: - case EArmState::Seven: - SetAnimState(EArmState::IntoGrappleIdle); - break; - case EArmState::FireGrapple: - if (grappleConnected) - { - SetAnimState(EArmState::ConnectGrapple); - x3b2_26_grappleHit = true; - x398_grappleHitGen->SetParticleEmission(true); - GrappleBeamConnected(); - if (x3b0_rumbleHandle != -1) - mgr.GetRumbleManager().StopRumble(x3b0_rumbleHandle); - } - break; - case EArmState::ConnectGrapple: - if (x344_xAmplitude == 0.f) - SetAnimState(EArmState::Connected); - break; - case EArmState::OutOfGrapple: - if (x3b0_rumbleHandle != -1) - mgr.GetRumbleManager().StopRumble(x3b0_rumbleHandle); - SetAnimState(EArmState::Done); - x3b2_24_active = false; - break; - default: - break; - } - } - - if (x3b2_25_beamActive) - { - x39c_grappleMuzzleGen->SetTranslation(beamLocXf.origin); - x39c_grappleMuzzleGen->Update(dt); - if (x3b2_26_grappleHit) - { - x3b2_26_grappleHit = !x398_grappleHitGen->IsSystemDeletable(); - x398_grappleHitGen->SetTranslation(x310_grapplePointPos); - x398_grappleHitGen->Update(dt); - } - } -} - -void CGrappleArm::Update(float grappleSwingT, float dt, CStateManager& mgr) -{ - if (!(x3b2_24_active && !x3b2_29_suitLoading)) - { - if (x3b2_29_suitLoading) - LoadSuitPoll(); - return; - } - - if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) - { - if (!x50_grappleArmSkeletonModel) - BuildXRayModel(); - } - else - { - if (x50_grappleArmSkeletonModel) - x50_grappleArmSkeletonModel = std::experimental::nullopt; - } - - float speed = 1.f; - if (!x3b2_27_armMoving) - speed = (mgr.GetPlayer().GetPlayerMovementState() != CPlayer::EPlayerMovementState::OnGround && - x334_animState != EArmState::OutOfGrapple) ? 4.f : 1.f; - x0_grappleArmModel->AdvanceAnimation(speed * dt, mgr, kInvalidAreaId, true); - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam)) - { - x250_grapLocatorXf = x0_grappleArmModel->GetScaledLocatorTransformDynamic("grapLocator_SDK", nullptr); - x280_grapNozLoc1Xf = x0_grappleArmModel->GetScaledLocatorTransform("gNozLoc1_SDK"); - x2b0_grapNozLoc2Xf = x0_grappleArmModel->GetScaledLocatorTransform("gNozLoc1_SDK"); - } - +void CGrappleArm::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type) { + switch (type) { + case EUserEventType::Projectile: if (x3b2_27_armMoving) - UpdateArmMovement(dt, mgr); - else - UpdateSwingAction(grappleSwingT, dt, mgr); - - if (x3a4_rainSplashGenerator) - x3a4_rainSplashGenerator->Update(dt, mgr); + return; + x3b2_25_beamActive = true; + x398_grappleHitGen = std::make_unique(x36c_grappleHitDesc); + x39c_grappleMuzzleGen = std::make_unique(x378_grappleMuzzleDesc); + x338_beamT = 0.f; + x33c_beamDist = 0.f; + x340_anglePhase = 0.f; + x344_xAmplitude = g_GrappleBeamXWaveAmplitude; + x348_zAmplitude = g_GrappleBeamZWaveAmplitude; + x398_grappleHitGen->SetParticleEmission(false); + x394_grappleClawGen->SetParticleEmission(true); + NWeaponTypes::play_sfx(SFXsam_grapple_fire, false, false, -0.15f); + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerGrappleFire, 1.f, ERumblePriority::Three); + break; + default: + break; + } } -void CGrappleArm::PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos) -{ - if (x3b2_24_active && !x3b2_29_suitLoading) - { - x0_grappleArmModel->AnimationData()->PreRender(); - if (x50_grappleArmSkeletonModel) - x50_grappleArmSkeletonModel->AnimationData()->PreRender(); +void CGrappleArm::DoUserAnimEvents(CStateManager& mgr) { + zeus::CVector3f armToCam = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation() - x220_xf.origin; + const CAnimData& animData = *x0_grappleArmModel->GetAnimationData(); + for (int i = 0; i < animData.GetPassedSoundPOICount(); ++i) { + const CSoundPOINode& node = CAnimData::g_SoundPOINodes[i]; + if (node.GetPoiType() != EPOIType::Sound || + (node.GetCharacterIndex() != -1 && animData.x204_charIdx != node.GetCharacterIndex())) + continue; + NWeaponTypes::do_sound_event(x34c_animSfx, x3ac_pitchBend, false, node.GetSfxId(), node.GetWeight(), + node.GetFlags(), node.GetFalloff(), node.GetMaxDist(), 0.16f, 1.f, armToCam, + x220_xf.origin, mgr.GetPlayer().GetAreaIdAlways(), mgr); + } + for (int i = 0; i < animData.GetPassedIntPOICount(); ++i) { + const CInt32POINode& node = CAnimData::g_Int32POINodes[i]; + switch (node.GetPoiType()) { + case EPOIType::UserEvent: + DoUserAnimEvent(mgr, node, EUserEventType(node.GetValue())); + break; + case EPOIType::SoundInt32: + if (node.GetCharacterIndex() != -1 && animData.x204_charIdx != node.GetCharacterIndex()) + break; + NWeaponTypes::do_sound_event(x34c_animSfx, x3ac_pitchBend, false, u32(node.GetValue()), node.GetWeight(), + node.GetFlags(), 0.1f, 150.f, 0.16f, 1.f, armToCam, x220_xf.origin, + mgr.GetPlayer().GetAreaIdAlways(), mgr); + break; + default: + break; } + } +} +void CGrappleArm::UpdateArmMovement(float dt, CStateManager& mgr) { + DoUserAnimEvents(mgr); + if (x328_gunController->Update(dt, mgr)) + ResetAuxParams(false); +} + +void CGrappleArm::UpdateGrappleBeamFx(const zeus::CVector3f& beamGunPos, const zeus::CVector3f& beamAirPos, + CStateManager& mgr) { + x394_grappleClawGen->SetTranslation(beamAirPos); + x390_grappleSegmentGen->SetParticleEmission(true); + + zeus::CVector3f segmentDelta = beamAirPos - beamGunPos; + zeus::CVector3f swooshSegmentDelta = segmentDelta * 0.02f; + int numSegments = int(2.f * segmentDelta.magnitude() + 1.f); + segmentDelta = (1.f / float(numSegments)) * segmentDelta; + + zeus::CVector3f segmentPos = beamGunPos; + zeus::CTransform rotation = x220_xf.getRotation(); + for (int i = 0; i < numSegments; ++i) { + zeus::CVector3f vec; + if (i > 0) + vec = rotation * + zeus::CVector3f(std::cos(i + x340_anglePhase) * x344_xAmplitude, 0.f, std::sin(float(i)) * x348_zAmplitude); + x390_grappleSegmentGen->SetTranslation(vec * segmentPos); + x390_grappleSegmentGen->ForceParticleCreation(1); + segmentPos += segmentDelta; + } + + x390_grappleSegmentGen->SetParticleEmission(false); + x3a0_grappleSwooshGen->DoGrappleUpdate(beamGunPos, rotation, x340_anglePhase, x344_xAmplitude, x348_zAmplitude, + swooshSegmentDelta); +} + +bool CGrappleArm::UpdateGrappleBeam(float dt, const zeus::CTransform& beamLoc, CStateManager& mgr) { + bool beamConnected = false; + if (TCastToConstPtr act = mgr.GetObjectById(mgr.GetPlayer().GetOrbitTargetId())) + x310_grapplePointPos = act->GetTranslation(); + else + x310_grapplePointPos = x220_xf.origin; + + zeus::CVector3f beamGunPos = (x220_xf * beamLoc).origin; + zeus::CVector3f beamAirPos = beamGunPos * (1.f - x338_beamT) + x310_grapplePointPos * x338_beamT; + + switch (x334_animState) { + case EArmState::FireGrapple: + case EArmState::Three: { + float gunToPointMag = (x310_grapplePointPos - beamGunPos).magnitude(); + if (gunToPointMag > 0.f) + x338_beamT = x33c_beamDist / gunToPointMag; + else + x338_beamT = 1.f; + float speedMult = mgr.GetPlayer().GetPlayerMovementState() != CPlayer::EPlayerMovementState::OnGround ? 2.f : 1.f; + x33c_beamDist += speedMult * (dt * g_GrappleBeamSpeed); + if (x338_beamT >= 1.f) { + x338_beamT = 1.f; + beamConnected = true; + } + break; + } + case EArmState::ConnectGrapple: { + float delta = 4.f * dt; + x344_xAmplitude -= delta; + x348_zAmplitude -= delta; + if (x344_xAmplitude < 0.f) + x344_xAmplitude = 0.f; + if (x348_zAmplitude < 0.f) + x348_zAmplitude = 0.f; + break; + } + default: + break; + } + + if (x3b2_25_beamActive) { + x340_anglePhase += g_GrappleBeamAnglePhaseDelta; + UpdateGrappleBeamFx(beamGunPos, beamAirPos, mgr); + x394_grappleClawGen->Update(dt); + x390_grappleSegmentGen->Update(dt); + } + + return beamConnected; +} + +void CGrappleArm::UpdateSwingAction(float grappleSwingT, float dt, CStateManager& mgr) { + if (x3b2_29_suitLoading) + return; + + if (x334_animState == EArmState::FireGrapple) + DoUserAnimEvents(mgr); + + zeus::CTransform beamLocXf = x0_grappleArmModel->GetScaledLocatorTransform("LGBeam"); + bool grappleConnected = UpdateGrappleBeam(dt, beamLocXf, mgr); + + if ((grappleSwingT > 0.175f && grappleSwingT < 0.3f) || (grappleSwingT > 0.7f && grappleSwingT < 0.9f)) { + if (!CSfxManager::IsPlaying(x330_swooshSfx)) { + x330_swooshSfx = NWeaponTypes::play_sfx(SFXsam_grapple_swoosh, false, false, -0.15f); + if (x3b0_rumbleHandle != -1) + mgr.GetRumbleManager().StopRumble(x3b0_rumbleHandle); + x3b0_rumbleHandle = + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerGrappleSwoosh, 1.f, ERumblePriority::Three); + } + } + + if (!x0_grappleArmModel->GetAnimationData()->IsAnimTimeRemaining(dt, "Whole Body")) { + switch (x334_animState) { + case EArmState::IntoGrapple: + case EArmState::Seven: + SetAnimState(EArmState::IntoGrappleIdle); + break; + case EArmState::FireGrapple: + if (grappleConnected) { + SetAnimState(EArmState::ConnectGrapple); + x3b2_26_grappleHit = true; + x398_grappleHitGen->SetParticleEmission(true); + GrappleBeamConnected(); + if (x3b0_rumbleHandle != -1) + mgr.GetRumbleManager().StopRumble(x3b0_rumbleHandle); + } + break; + case EArmState::ConnectGrapple: + if (x344_xAmplitude == 0.f) + SetAnimState(EArmState::Connected); + break; + case EArmState::OutOfGrapple: + if (x3b0_rumbleHandle != -1) + mgr.GetRumbleManager().StopRumble(x3b0_rumbleHandle); + SetAnimState(EArmState::Done); + x3b2_24_active = false; + break; + default: + break; + } + } + + if (x3b2_25_beamActive) { + x39c_grappleMuzzleGen->SetTranslation(beamLocXf.origin); + x39c_grappleMuzzleGen->Update(dt); + if (x3b2_26_grappleHit) { + x3b2_26_grappleHit = !x398_grappleHitGen->IsSystemDeletable(); + x398_grappleHitGen->SetTranslation(x310_grapplePointPos); + x398_grappleHitGen->Update(dt); + } + } +} + +void CGrappleArm::Update(float grappleSwingT, float dt, CStateManager& mgr) { + if (!(x3b2_24_active && !x3b2_29_suitLoading)) { + if (x3b2_29_suitLoading) + LoadSuitPoll(); + return; + } + + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) { + if (!x50_grappleArmSkeletonModel) + BuildXRayModel(); + } else { + if (x50_grappleArmSkeletonModel) + x50_grappleArmSkeletonModel = std::experimental::nullopt; + } + + float speed = 1.f; + if (!x3b2_27_armMoving) + speed = (mgr.GetPlayer().GetPlayerMovementState() != CPlayer::EPlayerMovementState::OnGround && + x334_animState != EArmState::OutOfGrapple) + ? 4.f + : 1.f; + x0_grappleArmModel->AdvanceAnimation(speed * dt, mgr, kInvalidAreaId, true); + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam)) { + x250_grapLocatorXf = x0_grappleArmModel->GetScaledLocatorTransformDynamic("grapLocator_SDK", nullptr); + x280_grapNozLoc1Xf = x0_grappleArmModel->GetScaledLocatorTransform("gNozLoc1_SDK"); + x2b0_grapNozLoc2Xf = x0_grappleArmModel->GetScaledLocatorTransform("gNozLoc1_SDK"); + } + + if (x3b2_27_armMoving) + UpdateArmMovement(dt, mgr); + else + UpdateSwingAction(grappleSwingT, dt, mgr); + + if (x3a4_rainSplashGenerator) + x3a4_rainSplashGenerator->Update(dt, mgr); +} + +void CGrappleArm::PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos) { + if (x3b2_24_active && !x3b2_29_suitLoading) { + x0_grappleArmModel->AnimationData()->PreRender(); + if (x50_grappleArmSkeletonModel) + x50_grappleArmSkeletonModel->AnimationData()->PreRender(); + } } void CGrappleArm::RenderXRayModel(const CStateManager& mgr, const zeus::CTransform& modelXf, - const CModelFlags& flags) const -{ - CGraphics::SetModelMatrix(modelXf * zeus::CTransform::Scale(x0_grappleArmModel->GetScale())); - //CGraphics::DisableAllLights(); - //g_Renderer->SetAmbientColor(zeus::CColor::skWhite); - CSkinnedModel& model = - const_cast(*x50_grappleArmSkeletonModel->GetAnimationData()->GetModelData()); - model.GetModelInst()->ActivateLights({CLight::BuildLocalAmbient({}, zeus::CColor::skWhite)}); - const_cast(this)->x0_grappleArmModel->AnimationData()->Render(model, flags, {}, nullptr); - //g_Renderer->SetAmbientColor(zeus::CColor::skWhite); - //CGraphics::DisableAllLights(); + const CModelFlags& flags) const { + CGraphics::SetModelMatrix(modelXf * zeus::CTransform::Scale(x0_grappleArmModel->GetScale())); + // CGraphics::DisableAllLights(); + // g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + CSkinnedModel& model = const_cast(*x50_grappleArmSkeletonModel->GetAnimationData()->GetModelData()); + model.GetModelInst()->ActivateLights({CLight::BuildLocalAmbient({}, zeus::CColor::skWhite)}); + const_cast(this)->x0_grappleArmModel->AnimationData()->Render(model, flags, {}, nullptr); + // g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + // CGraphics::DisableAllLights(); } -void CGrappleArm::PointGenerator(void* ctx, const std::vector>& vn) -{ - reinterpret_cast(ctx)->GeneratePoints(vn); +void CGrappleArm::PointGenerator(void* ctx, const std::vector>& vn) { + reinterpret_cast(ctx)->GeneratePoints(vn); } -void CGrappleArm::Render(const CStateManager& mgr, const zeus::CVector3f& pos, - const CModelFlags& flags, const CActorLights* lights) const -{ - if (x3b2_24_active && !x3b2_29_suitLoading) - { - zeus::CTransform modelXf = zeus::CTransform::Translate(pos) * x220_xf * x2e0_auxXf; - if (x50_grappleArmSkeletonModel) - RenderXRayModel(mgr, modelXf, flags); +void CGrappleArm::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags, + const CActorLights* lights) const { + if (x3b2_24_active && !x3b2_29_suitLoading) { + zeus::CTransform modelXf = zeus::CTransform::Translate(pos) * x220_xf * x2e0_auxXf; + if (x50_grappleArmSkeletonModel) + RenderXRayModel(mgr, modelXf, flags); - CModelFlags useFlags; - const CActorLights* useLights; - if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) - { - useFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, 0.25f)); - useLights = nullptr; - } - else - { - useFlags = flags; - useLights = lights; - } - - if (x3a4_rainSplashGenerator && x3a4_rainSplashGenerator->IsRaining()) - CSkinnedModel::SetPointGeneratorFunc(x3a4_rainSplashGenerator.get(), PointGenerator); - - x0_grappleArmModel->Render(mgr, modelXf, useLights, useFlags); - - if (x3a4_rainSplashGenerator && x3a4_rainSplashGenerator->IsRaining()) - { - CSkinnedModel::ClearPointGeneratorFunc(); - x3a4_rainSplashGenerator->Draw(modelXf); - } - - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam)) - { - xa0_grappleGearModel.Render(mgr, modelXf * x250_grapLocatorXf, useLights, useFlags); - xec_grapNoz1Model.Render(mgr, modelXf * x280_grapNozLoc1Xf, useLights, useFlags); - x138_grapNoz2Model.Render(mgr, modelXf * x2b0_grapNozLoc2Xf, useLights, useFlags); - } - } -} - -void CGrappleArm::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Registered) - AsyncLoadSuit(mgr); -} - -void CGrappleArm::EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool notInFreeLook) -{ - if (x3b2_29_suitLoading) - return; - - if (x3b2_28_isGrappling) - { - DisconnectGrappleBeam(); - x3b2_28_isGrappling = false; + CModelFlags useFlags; + const CActorLights* useLights; + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) { + useFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, 0.25f)); + useLights = nullptr; + } else { + useFlags = flags; + useLights = lights; } - if (!x3b2_27_armMoving) - { - x3b2_24_active = true; - x3b2_27_armMoving = true; - x334_animState = EArmState::GunControllerAnimation; + if (x3a4_rainSplashGenerator && x3a4_rainSplashGenerator->IsRaining()) + CSkinnedModel::SetPointGeneratorFunc(x3a4_rainSplashGenerator.get(), PointGenerator); + + x0_grappleArmModel->Render(mgr, modelXf, useLights, useFlags); + + if (x3a4_rainSplashGenerator && x3a4_rainSplashGenerator->IsRaining()) { + CSkinnedModel::ClearPointGeneratorFunc(); + x3a4_rainSplashGenerator->Draw(modelXf); } - x328_gunController->EnterStruck(mgr, angle, bigStrike, notInFreeLook); + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam)) { + xa0_grappleGearModel.Render(mgr, modelXf * x250_grapLocatorXf, useLights, useFlags); + xec_grapNoz1Model.Render(mgr, modelXf * x280_grapNozLoc1Xf, useLights, useFlags); + x138_grapNoz2Model.Render(mgr, modelXf * x2b0_grapNozLoc2Xf, useLights, useFlags); + } + } } -void CGrappleArm::EnterIdle(CStateManager& mgr) -{ - if (x3b2_29_suitLoading) - return; - - x328_gunController->EnterIdle(mgr); +void CGrappleArm::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Registered) + AsyncLoadSuit(mgr); } -void CGrappleArm::EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 gunId, s32 animSet) -{ - if (x3b2_29_suitLoading) - return; +void CGrappleArm::EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool notInFreeLook) { + if (x3b2_29_suitLoading) + return; + if (x3b2_28_isGrappling) { + DisconnectGrappleBeam(); + x3b2_28_isGrappling = false; + } + + if (!x3b2_27_armMoving) { x3b2_24_active = true; x3b2_27_armMoving = true; x334_animState = EArmState::GunControllerAnimation; + } - x328_gunController->EnterFidget(mgr, s32(type), gunId, animSet); + x328_gunController->EnterStruck(mgr, angle, bigStrike, notInFreeLook); } -void CGrappleArm::EnterFreeLook(s32 gunId, s32 setId, CStateManager& mgr) -{ - if (x3b2_29_suitLoading) - return; +void CGrappleArm::EnterIdle(CStateManager& mgr) { + if (x3b2_29_suitLoading) + return; - x3b2_24_active = true; - x3b2_27_armMoving = true; - x334_animState = EArmState::GunControllerAnimation; - - x328_gunController->EnterFreeLook(mgr, gunId, setId); + x328_gunController->EnterIdle(mgr); } -void CGrappleArm::EnterComboFire(s32 gunId, CStateManager& mgr) -{ - if (x3b2_29_suitLoading) - return; +void CGrappleArm::EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 gunId, s32 animSet) { + if (x3b2_29_suitLoading) + return; - x3b2_24_active = true; - x3b2_27_armMoving = true; - x334_animState = EArmState::GunControllerAnimation; + x3b2_24_active = true; + x3b2_27_armMoving = true; + x334_animState = EArmState::GunControllerAnimation; - x328_gunController->EnterComboFire(mgr, gunId); + x328_gunController->EnterFidget(mgr, s32(type), gunId, animSet); } -void CGrappleArm::ReturnToDefault(CStateManager& mgr, float dt, bool setState) -{ - if (x3b2_29_suitLoading) - return; +void CGrappleArm::EnterFreeLook(s32 gunId, s32 setId, CStateManager& mgr) { + if (x3b2_29_suitLoading) + return; - x328_gunController->ReturnToDefault(mgr, dt, setState); + x3b2_24_active = true; + x3b2_27_armMoving = true; + x334_animState = EArmState::GunControllerAnimation; + + x328_gunController->EnterFreeLook(mgr, gunId, setId); } +void CGrappleArm::EnterComboFire(s32 gunId, CStateManager& mgr) { + if (x3b2_29_suitLoading) + return; + + x3b2_24_active = true; + x3b2_27_armMoving = true; + x334_animState = EArmState::GunControllerAnimation; + + x328_gunController->EnterComboFire(mgr, gunId); } + +void CGrappleArm::ReturnToDefault(CStateManager& mgr, float dt, bool setState) { + if (x3b2_29_suitLoading) + return; + + x328_gunController->ReturnToDefault(mgr, dt, setState); +} + +} // namespace urde diff --git a/Runtime/Weapon/CGrappleArm.hpp b/Runtime/Weapon/CGrappleArm.hpp index c2e32460d..5fafe00ab 100644 --- a/Runtime/Weapon/CGrappleArm.hpp +++ b/Runtime/Weapon/CGrappleArm.hpp @@ -8,136 +8,131 @@ #include "CGunController.hpp" #include "CGunMotion.hpp" -namespace urde -{ +namespace urde { class CStateManager; struct CModelFlags; class CActorLights; -class CGrappleArm -{ +class CGrappleArm { public: - enum class EArmState - { - IntoGrapple, - IntoGrappleIdle, - FireGrapple, - Three, - ConnectGrapple, - Five, - Connected, - Seven, - OutOfGrapple, - GunControllerAnimation, - Done - }; + enum class EArmState { + IntoGrapple, + IntoGrappleIdle, + FireGrapple, + Three, + ConnectGrapple, + Five, + Connected, + Seven, + OutOfGrapple, + GunControllerAnimation, + Done + }; + private: - std::experimental::optional x0_grappleArmModel; - std::experimental::optional x50_grappleArmSkeletonModel; - CModelData xa0_grappleGearModel; - CModelData xec_grapNoz1Model; - CModelData x138_grapNoz2Model; - TCachedToken x184_grappleArm; - std::vector x18c_anims; - rstl::reserved_vector, 8> x19c_suitDeps; - zeus::CTransform x220_xf; - zeus::CTransform x250_grapLocatorXf; - zeus::CTransform x280_grapNozLoc1Xf; - zeus::CTransform x2b0_grapNozLoc2Xf; - zeus::CTransform x2e0_auxXf; - zeus::CVector3f x310_grapplePointPos; - zeus::CVector3f x31c_scale; - std::unique_ptr x328_gunController; - CSfxHandle x32c_grappleLoopSfx; - CSfxHandle x330_swooshSfx; - EArmState x334_animState = EArmState::Done; - float x338_beamT = 0.f; - float x33c_beamDist = 0.f; - float x340_anglePhase = 0.f; - float x344_xAmplitude = 0.f; - float x348_zAmplitude = 0.f; - std::pair x34c_animSfx = {0xffff, {}}; - TCachedToken x354_grappleSegmentDesc; - TCachedToken x360_grappleClawDesc; - TCachedToken x36c_grappleHitDesc; - TCachedToken x378_grappleMuzzleDesc; - TCachedToken x384_grappleSwooshDesc; - std::unique_ptr x390_grappleSegmentGen; - std::unique_ptr x394_grappleClawGen; - std::unique_ptr x398_grappleHitGen; - std::unique_ptr x39c_grappleMuzzleGen; - std::unique_ptr x3a0_grappleSwooshGen; - std::unique_ptr x3a4_rainSplashGenerator; - CPlayerState::EPlayerSuit x3a8_loadedSuit = CPlayerState::EPlayerSuit::Invalid; - float x3ac_pitchBend = 0.f; - s16 x3b0_rumbleHandle = -1; - union - { - struct - { - bool x3b2_24_active : 1; - bool x3b2_25_beamActive : 1; - bool x3b2_26_grappleHit : 1; - bool x3b2_27_armMoving : 1; - bool x3b2_28_isGrappling : 1; - bool x3b2_29_suitLoading : 1; - }; - u32 _dummy = 0; + std::experimental::optional x0_grappleArmModel; + std::experimental::optional x50_grappleArmSkeletonModel; + CModelData xa0_grappleGearModel; + CModelData xec_grapNoz1Model; + CModelData x138_grapNoz2Model; + TCachedToken x184_grappleArm; + std::vector x18c_anims; + rstl::reserved_vector, 8> x19c_suitDeps; + zeus::CTransform x220_xf; + zeus::CTransform x250_grapLocatorXf; + zeus::CTransform x280_grapNozLoc1Xf; + zeus::CTransform x2b0_grapNozLoc2Xf; + zeus::CTransform x2e0_auxXf; + zeus::CVector3f x310_grapplePointPos; + zeus::CVector3f x31c_scale; + std::unique_ptr x328_gunController; + CSfxHandle x32c_grappleLoopSfx; + CSfxHandle x330_swooshSfx; + EArmState x334_animState = EArmState::Done; + float x338_beamT = 0.f; + float x33c_beamDist = 0.f; + float x340_anglePhase = 0.f; + float x344_xAmplitude = 0.f; + float x348_zAmplitude = 0.f; + std::pair x34c_animSfx = {0xffff, {}}; + TCachedToken x354_grappleSegmentDesc; + TCachedToken x360_grappleClawDesc; + TCachedToken x36c_grappleHitDesc; + TCachedToken x378_grappleMuzzleDesc; + TCachedToken x384_grappleSwooshDesc; + std::unique_ptr x390_grappleSegmentGen; + std::unique_ptr x394_grappleClawGen; + std::unique_ptr x398_grappleHitGen; + std::unique_ptr x39c_grappleMuzzleGen; + std::unique_ptr x3a0_grappleSwooshGen; + std::unique_ptr x3a4_rainSplashGenerator; + CPlayerState::EPlayerSuit x3a8_loadedSuit = CPlayerState::EPlayerSuit::Invalid; + float x3ac_pitchBend = 0.f; + s16 x3b0_rumbleHandle = -1; + union { + struct { + bool x3b2_24_active : 1; + bool x3b2_25_beamActive : 1; + bool x3b2_26_grappleHit : 1; + bool x3b2_27_armMoving : 1; + bool x3b2_28_isGrappling : 1; + bool x3b2_29_suitLoading : 1; }; + u32 _dummy = 0; + }; - static float g_GrappleBeamAnglePhaseDelta; - static float g_GrappleBeamXWaveAmplitude; - static float g_GrappleBeamZWaveAmplitude; - static float g_GrappleBeamSpeed; + static float g_GrappleBeamAnglePhaseDelta; + static float g_GrappleBeamXWaveAmplitude; + static float g_GrappleBeamZWaveAmplitude; + static float g_GrappleBeamSpeed; - void FillTokenVector(const std::vector& tags, std::vector& objects); - void BuildSuitDependencyList(); - void LoadAnimations(); - void ResetAuxParams(bool resetGunController); - void DisconnectGrappleBeam(); - void LoadSuitPoll(); - void BuildXRayModel(); - void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type); - void DoUserAnimEvents(CStateManager& mgr); - void UpdateArmMovement(float dt, CStateManager& mgr); - void UpdateGrappleBeamFx(const zeus::CVector3f& beamGunPos, const zeus::CVector3f& beamAirPos, CStateManager& mgr); - bool UpdateGrappleBeam(float dt, const zeus::CTransform& beamLoc, CStateManager& mgr); - void UpdateSwingAction(float grappleSwingT, float dt, CStateManager& mgr); - void RenderXRayModel(const CStateManager& mgr, const zeus::CTransform& modelXf, const CModelFlags& flags) const; + void FillTokenVector(const std::vector& tags, std::vector& objects); + void BuildSuitDependencyList(); + void LoadAnimations(); + void ResetAuxParams(bool resetGunController); + void DisconnectGrappleBeam(); + void LoadSuitPoll(); + void BuildXRayModel(); + void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type); + void DoUserAnimEvents(CStateManager& mgr); + void UpdateArmMovement(float dt, CStateManager& mgr); + void UpdateGrappleBeamFx(const zeus::CVector3f& beamGunPos, const zeus::CVector3f& beamAirPos, CStateManager& mgr); + bool UpdateGrappleBeam(float dt, const zeus::CTransform& beamLoc, CStateManager& mgr); + void UpdateSwingAction(float grappleSwingT, float dt, CStateManager& mgr); + void RenderXRayModel(const CStateManager& mgr, const zeus::CTransform& modelXf, const CModelFlags& flags) const; - static void PointGenerator(void* ctx, const std::vector>& vn); + static void PointGenerator(void* ctx, const std::vector>& vn); public: - explicit CGrappleArm(const zeus::CVector3f& scale); - void AsyncLoadSuit(CStateManager& mgr); - void SetTransform(const zeus::CTransform& xf) { x220_xf = xf; } - const zeus::CTransform& GetTransform() const { return x220_xf; } - zeus::CTransform& AuxTransform() { return x2e0_auxXf; } - void SetAnimState(EArmState state); - EArmState GetAnimState() const { return x334_animState; } - bool GetActive() const { return x3b2_24_active; } - bool BeamActive() const { return x3b2_25_beamActive; } - bool IsArmMoving() const { return x3b2_27_armMoving; } - bool IsGrappling() const { return x3b2_28_isGrappling; } - bool IsSuitLoading() const { return x3b2_29_suitLoading; } - void Activate(bool); - void GrappleBeamDisconnected(); - void GrappleBeamConnected(); - void RenderGrappleBeam(const CStateManager& mgr, const zeus::CVector3f& pos); - void TouchModel(const CStateManager& mgr) const; - void Update(float grappleSwingT, float dt, CStateManager& mgr); - void PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos); - void Render(const CStateManager& mgr, const zeus::CVector3f& pos, - const CModelFlags& flags, const CActorLights* lights) const; - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool notInFreeLook); - void EnterIdle(CStateManager& mgr); - void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 gunId, s32 animSet); - void EnterFreeLook(s32 gunId, s32 setId, CStateManager& mgr); - void EnterComboFire(s32 gunId, CStateManager& mgr); - void ReturnToDefault(CStateManager& mgr, float dt, bool setState); - CGunController* GunController() { return x328_gunController.get(); } + explicit CGrappleArm(const zeus::CVector3f& scale); + void AsyncLoadSuit(CStateManager& mgr); + void SetTransform(const zeus::CTransform& xf) { x220_xf = xf; } + const zeus::CTransform& GetTransform() const { return x220_xf; } + zeus::CTransform& AuxTransform() { return x2e0_auxXf; } + void SetAnimState(EArmState state); + EArmState GetAnimState() const { return x334_animState; } + bool GetActive() const { return x3b2_24_active; } + bool BeamActive() const { return x3b2_25_beamActive; } + bool IsArmMoving() const { return x3b2_27_armMoving; } + bool IsGrappling() const { return x3b2_28_isGrappling; } + bool IsSuitLoading() const { return x3b2_29_suitLoading; } + void Activate(bool); + void GrappleBeamDisconnected(); + void GrappleBeamConnected(); + void RenderGrappleBeam(const CStateManager& mgr, const zeus::CVector3f& pos); + void TouchModel(const CStateManager& mgr) const; + void Update(float grappleSwingT, float dt, CStateManager& mgr); + void PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos); + void Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags, + const CActorLights* lights) const; + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool notInFreeLook); + void EnterIdle(CStateManager& mgr); + void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 gunId, s32 animSet); + void EnterFreeLook(s32 gunId, s32 setId, CStateManager& mgr); + void EnterComboFire(s32 gunId, CStateManager& mgr); + void ReturnToDefault(CStateManager& mgr, float dt, bool setState); + CGunController* GunController() { return x328_gunController.get(); } }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CGunController.cpp b/Runtime/Weapon/CGunController.cpp index cd5b62bd2..35443dd89 100644 --- a/Runtime/Weapon/CGunController.cpp +++ b/Runtime/Weapon/CGunController.cpp @@ -3,193 +3,172 @@ #include "Character/CPASAnimParmData.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { -void CGunController::LoadFidgetAnimAsync(CStateManager& mgr, s32 type, s32 gunId, s32 animSet) -{ - x30_fidget.LoadAnimAsync(*x0_modelData.AnimationData(), type, gunId, animSet, mgr); +void CGunController::LoadFidgetAnimAsync(CStateManager& mgr, s32 type, s32 gunId, s32 animSet) { + x30_fidget.LoadAnimAsync(*x0_modelData.AnimationData(), type, gunId, animSet, mgr); } -void CGunController::EnterFidget(CStateManager& mgr, s32 type, s32 gunId, s32 animSet) -{ - x54_curAnimId = x30_fidget.SetAnim(*x0_modelData.AnimationData(), type, gunId, animSet, mgr); - x50_gunState = EGunState::Fidget; +void CGunController::EnterFidget(CStateManager& mgr, s32 type, s32 gunId, s32 animSet) { + x54_curAnimId = x30_fidget.SetAnim(*x0_modelData.AnimationData(), type, gunId, animSet, mgr); + x50_gunState = EGunState::Fidget; } -void CGunController::EnterFreeLook(CStateManager& mgr, s32 gunId, s32 setId) -{ - if (x50_gunState != EGunState::ComboFire && !x58_25_enteredComboFire) - x54_curAnimId = x4_freeLook.SetAnim(*x0_modelData.AnimationData(), gunId, setId, 0, mgr, 0.f); - else - x4_freeLook.SetLoopState(x1c_comboFire.GetLoopState()); +void CGunController::EnterFreeLook(CStateManager& mgr, s32 gunId, s32 setId) { + if (x50_gunState != EGunState::ComboFire && !x58_25_enteredComboFire) + x54_curAnimId = x4_freeLook.SetAnim(*x0_modelData.AnimationData(), gunId, setId, 0, mgr, 0.f); + else + x4_freeLook.SetLoopState(x1c_comboFire.GetLoopState()); + x50_gunState = EGunState::FreeLook; +} + +void CGunController::EnterComboFire(CStateManager& mgr, s32 gunId) { + if (x50_gunState != EGunState::FreeLook) + x54_curAnimId = x1c_comboFire.SetAnim(*x0_modelData.AnimationData(), gunId, 0, mgr, 0.f); + else + x1c_comboFire.SetLoopState(x4_freeLook.GetLoopState()); + x50_gunState = EGunState::ComboFire; + x58_25_enteredComboFire = true; +} + +void CGunController::EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool b2) { + switch (x50_gunState) { + case EGunState::Default: + case EGunState::ComboFire: + case EGunState::Idle: + case EGunState::Strike: + case EGunState::BigStrike: + return; + case EGunState::FreeLook: + x4_freeLook.SetIdle(true); + break; + default: + break; + } + + const CPASDatabase& pasDatabase = x0_modelData.AnimationData()->GetCharacterInfo().GetPASDatabase(); + CPASAnimParmData parms(2, CPASAnimParm::FromInt32(x4_freeLook.GetGunId()), CPASAnimParm::FromReal32(angle), + CPASAnimParm::FromBool(bigStrike), CPASAnimParm::FromBool(b2)); + std::pair anim = pasDatabase.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + x0_modelData.AnimationData()->EnableLooping(false); + CAnimPlaybackParms aparms(anim.second, -1, 1.f, true); + x0_modelData.AnimationData()->SetAnimation(aparms, false); + x54_curAnimId = anim.second; + x58_25_enteredComboFire = false; + x50_gunState = bigStrike ? EGunState::BigStrike : EGunState::Strike; +} + +void CGunController::EnterIdle(CStateManager& mgr) { + CPASAnimParm parm = CPASAnimParm::NoParameter(); + switch (x50_gunState) { + case EGunState::FreeLook: + parm = CPASAnimParm::FromEnum(1); + x4_freeLook.SetIdle(true); + break; + case EGunState::ComboFire: + parm = CPASAnimParm::FromEnum(1); + x1c_comboFire.SetIdle(true); + break; + default: + return; + } + + const CPASDatabase& pasDatabase = x0_modelData.AnimationData()->GetCharacterInfo().GetPASDatabase(); + CPASAnimParmData parms(5, parm); + std::pair anim = pasDatabase.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + x0_modelData.AnimationData()->EnableLooping(false); + CAnimPlaybackParms aparms(anim.second, -1, 1.f, true); + x0_modelData.AnimationData()->SetAnimation(aparms, false); + x54_curAnimId = anim.second; + x50_gunState = EGunState::Idle; + x58_25_enteredComboFire = false; +} + +bool CGunController::Update(float dt, CStateManager& mgr) { + CAnimData& animData = *x0_modelData.AnimationData(); + switch (x50_gunState) { + case EGunState::FreeLook: { + x58_24_animDone = x4_freeLook.Update(animData, dt, mgr); + if (!x58_24_animDone || !x58_25_enteredComboFire) + break; + + EnterComboFire(mgr, x4_freeLook.GetGunId()); + x58_24_animDone = false; + break; + } + case EGunState::ComboFire: + x58_24_animDone = x1c_comboFire.Update(animData, dt, mgr); + break; + case EGunState::Fidget: + x58_24_animDone = x30_fidget.Update(animData, dt, mgr); + break; + case EGunState::Strike: { + if (animData.IsAnimTimeRemaining(0.001f, "Whole Body")) + break; + x54_curAnimId = x4_freeLook.SetAnim(animData, x4_freeLook.GetGunId(), x4_freeLook.GetSetId(), 0, mgr, 0.f); x50_gunState = EGunState::FreeLook; + break; + } + case EGunState::BigStrike: + x58_24_animDone = !animData.IsAnimTimeRemaining(0.001f, "Whole Body"); + break; + default: + break; + } + + if (!x58_24_animDone) + return false; + + x50_gunState = EGunState::Inactive; + x58_25_enteredComboFire = false; + + return true; } -void CGunController::EnterComboFire(CStateManager& mgr, s32 gunId) -{ - if (x50_gunState != EGunState::FreeLook) - x54_curAnimId = x1c_comboFire.SetAnim(*x0_modelData.AnimationData(), gunId, 0, mgr, 0.f); - else - x1c_comboFire.SetLoopState(x4_freeLook.GetLoopState()); - x50_gunState = EGunState::ComboFire; - x58_25_enteredComboFire = true; -} - -void CGunController::EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool b2) -{ - switch (x50_gunState) - { - case EGunState::Default: - case EGunState::ComboFire: - case EGunState::Idle: - case EGunState::Strike: - case EGunState::BigStrike: - return; - case EGunState::FreeLook: - x4_freeLook.SetIdle(true); - break; - default: - break; - } - - const CPASDatabase& pasDatabase = x0_modelData.AnimationData()->GetCharacterInfo().GetPASDatabase(); - CPASAnimParmData parms(2, CPASAnimParm::FromInt32(x4_freeLook.GetGunId()), - CPASAnimParm::FromReal32(angle), CPASAnimParm::FromBool(bigStrike), - CPASAnimParm::FromBool(b2)); - std::pair anim = - pasDatabase.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - x0_modelData.AnimationData()->EnableLooping(false); - CAnimPlaybackParms aparms(anim.second, -1, 1.f, true); - x0_modelData.AnimationData()->SetAnimation(aparms, false); - x54_curAnimId = anim.second; - x58_25_enteredComboFire = false; - x50_gunState = bigStrike ? EGunState::BigStrike : EGunState::Strike; -} - -void CGunController::EnterIdle(CStateManager& mgr) -{ - CPASAnimParm parm = CPASAnimParm::NoParameter(); - switch (x50_gunState) - { - case EGunState::FreeLook: - parm = CPASAnimParm::FromEnum(1); - x4_freeLook.SetIdle(true); - break; - case EGunState::ComboFire: - parm = CPASAnimParm::FromEnum(1); - x1c_comboFire.SetIdle(true); - break; - default: - return; - } - - const CPASDatabase& pasDatabase = x0_modelData.AnimationData()->GetCharacterInfo().GetPASDatabase(); - CPASAnimParmData parms(5, parm); - std::pair anim = - pasDatabase.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - x0_modelData.AnimationData()->EnableLooping(false); - CAnimPlaybackParms aparms(anim.second, -1, 1.f, true); - x0_modelData.AnimationData()->SetAnimation(aparms, false); - x54_curAnimId = anim.second; - x50_gunState = EGunState::Idle; - x58_25_enteredComboFire = false; -} - -bool CGunController::Update(float dt, CStateManager& mgr) -{ - CAnimData& animData = *x0_modelData.AnimationData(); - switch (x50_gunState) - { - case EGunState::FreeLook: - { - x58_24_animDone = x4_freeLook.Update(animData, dt, mgr); - if (!x58_24_animDone || !x58_25_enteredComboFire) - break; - - EnterComboFire(mgr, x4_freeLook.GetGunId()); - x58_24_animDone = false; - break; - } - case EGunState::ComboFire: - x58_24_animDone = x1c_comboFire.Update(animData, dt, mgr); - break; - case EGunState::Fidget: - x58_24_animDone = x30_fidget.Update(animData, dt, mgr); - break; - case EGunState::Strike: - { - if (animData.IsAnimTimeRemaining(0.001f, "Whole Body")) - break; - x54_curAnimId = x4_freeLook.SetAnim(animData, x4_freeLook.GetGunId(), x4_freeLook.GetSetId(), 0, mgr, 0.f); - x50_gunState = EGunState::FreeLook; - break; - } - case EGunState::BigStrike: - x58_24_animDone = !animData.IsAnimTimeRemaining(0.001f, "Whole Body"); - break; - default: - break; - } - - if (!x58_24_animDone) - return false; - - x50_gunState = EGunState::Inactive; - x58_25_enteredComboFire = false; - - return true; -} - -void CGunController::ReturnToDefault(CStateManager& mgr, float dt, bool setState) -{ - CAnimData& animData = *x0_modelData.AnimationData(); - - switch (x50_gunState) - { - case EGunState::Strike: - x50_gunState = EGunState::FreeLook; - case EGunState::Idle: - x4_freeLook.SetIdle(false); - case EGunState::FreeLook: - if (setState) - break; - x54_curAnimId = x4_freeLook.SetAnim(animData, x4_freeLook.GetGunId(), x4_freeLook.GetSetId(), 2, mgr, dt); - x58_25_enteredComboFire = false; - break; - case EGunState::ComboFire: - x54_curAnimId = x1c_comboFire.SetAnim(animData, x1c_comboFire.GetGunId(), 2, mgr, dt); - break; - case EGunState::Fidget: - ReturnToBasePosition(mgr, dt); - break; - case EGunState::BigStrike: - x4_freeLook.SetIdle(false); - break; - default: - break; - } +void CGunController::ReturnToDefault(CStateManager& mgr, float dt, bool setState) { + CAnimData& animData = *x0_modelData.AnimationData(); + switch (x50_gunState) { + case EGunState::Strike: + x50_gunState = EGunState::FreeLook; + case EGunState::Idle: + x4_freeLook.SetIdle(false); + case EGunState::FreeLook: if (setState) - x50_gunState = EGunState::Default; + break; + x54_curAnimId = x4_freeLook.SetAnim(animData, x4_freeLook.GetGunId(), x4_freeLook.GetSetId(), 2, mgr, dt); + x58_25_enteredComboFire = false; + break; + case EGunState::ComboFire: + x54_curAnimId = x1c_comboFire.SetAnim(animData, x1c_comboFire.GetGunId(), 2, mgr, dt); + break; + case EGunState::Fidget: + ReturnToBasePosition(mgr, dt); + break; + case EGunState::BigStrike: + x4_freeLook.SetIdle(false); + break; + default: + break; + } + + if (setState) + x50_gunState = EGunState::Default; } -void CGunController::ReturnToBasePosition(CStateManager& mgr, float) -{ - const CPASDatabase& pasDatabase = x0_modelData.AnimationData()->GetCharacterInfo().GetPASDatabase(); - std::pair anim = - pasDatabase.FindBestAnimation(CPASAnimParmData(6), *mgr.GetActiveRandom(), -1); - x0_modelData.AnimationData()->EnableLooping(false); - CAnimPlaybackParms parms(anim.second, -1, 1.f, true); - x0_modelData.AnimationData()->SetAnimation(parms, false); - x54_curAnimId = anim.second; - x58_25_enteredComboFire = false; +void CGunController::ReturnToBasePosition(CStateManager& mgr, float) { + const CPASDatabase& pasDatabase = x0_modelData.AnimationData()->GetCharacterInfo().GetPASDatabase(); + std::pair anim = pasDatabase.FindBestAnimation(CPASAnimParmData(6), *mgr.GetActiveRandom(), -1); + x0_modelData.AnimationData()->EnableLooping(false); + CAnimPlaybackParms parms(anim.second, -1, 1.f, true); + x0_modelData.AnimationData()->SetAnimation(parms, false); + x54_curAnimId = anim.second; + x58_25_enteredComboFire = false; } -void CGunController::Reset() -{ - x58_24_animDone = true; - x58_25_enteredComboFire = false; - x50_gunState = EGunState::Inactive; -} +void CGunController::Reset() { + x58_24_animDone = true; + x58_25_enteredComboFire = false; + x50_gunState = EGunState::Inactive; } +} // namespace urde diff --git a/Runtime/Weapon/CGunController.hpp b/Runtime/Weapon/CGunController.hpp index bf76ec3d6..e21a137e8 100644 --- a/Runtime/Weapon/CGunController.hpp +++ b/Runtime/Weapon/CGunController.hpp @@ -5,54 +5,39 @@ #include "CGSComboFire.hpp" #include "CGSFidget.hpp" -namespace urde -{ -enum class EGunState -{ - Inactive, - Default, - FreeLook, - ComboFire, - Idle, - Fidget, - Strike, - BigStrike -}; +namespace urde { +enum class EGunState { Inactive, Default, FreeLook, ComboFire, Idle, Fidget, Strike, BigStrike }; -class CGunController -{ - CModelData& x0_modelData; - CGSFreeLook x4_freeLook; - CGSComboFire x1c_comboFire; - CGSFidget x30_fidget; - EGunState x50_gunState = EGunState::Inactive; - s32 x54_curAnimId = -1; - bool x58_24_animDone : 1; - bool x58_25_enteredComboFire : 1; +class CGunController { + CModelData& x0_modelData; + CGSFreeLook x4_freeLook; + CGSComboFire x1c_comboFire; + CGSFidget x30_fidget; + EGunState x50_gunState = EGunState::Inactive; + s32 x54_curAnimId = -1; + bool x58_24_animDone : 1; + bool x58_25_enteredComboFire : 1; public: - CGunController(CModelData& modelData) - : x0_modelData(modelData) - { - x58_24_animDone = true; - x58_25_enteredComboFire = false; - } + CGunController(CModelData& modelData) : x0_modelData(modelData) { + x58_24_animDone = true; + x58_25_enteredComboFire = false; + } - void UnLoadFidget() { x30_fidget.UnLoadAnim(); } - void LoadFidgetAnimAsync(CStateManager& mgr, s32 type, s32 gunId, s32 animSet); - void EnterFidget(CStateManager& mgr, s32 type, s32 gunId, s32 animSet); - bool IsFidgetLoaded() const { return x30_fidget.IsAnimLoaded(); } - s32 GetFreeLookSetId() const { return x4_freeLook.GetSetId(); } - bool IsComboOver() const { return x1c_comboFire.IsComboOver(); } - void EnterFreeLook(CStateManager& mgr, s32 gunId, s32 setId); - void EnterComboFire(CStateManager& mgr, s32 gunId); - void EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool b2); - void EnterIdle(CStateManager& mgr); - bool Update(float dt, CStateManager& mgr); - void ReturnToDefault(CStateManager& mgr, float dt, bool setState); - void ReturnToBasePosition(CStateManager&, float); - void Reset(); - s32 GetCurAnimId() const { return x54_curAnimId; } + void UnLoadFidget() { x30_fidget.UnLoadAnim(); } + void LoadFidgetAnimAsync(CStateManager& mgr, s32 type, s32 gunId, s32 animSet); + void EnterFidget(CStateManager& mgr, s32 type, s32 gunId, s32 animSet); + bool IsFidgetLoaded() const { return x30_fidget.IsAnimLoaded(); } + s32 GetFreeLookSetId() const { return x4_freeLook.GetSetId(); } + bool IsComboOver() const { return x1c_comboFire.IsComboOver(); } + void EnterFreeLook(CStateManager& mgr, s32 gunId, s32 setId); + void EnterComboFire(CStateManager& mgr, s32 gunId); + void EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool b2); + void EnterIdle(CStateManager& mgr); + bool Update(float dt, CStateManager& mgr); + void ReturnToDefault(CStateManager& mgr, float dt, bool setState); + void ReturnToBasePosition(CStateManager&, float); + void Reset(); + s32 GetCurAnimId() const { return x54_curAnimId; } }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CGunMotion.cpp b/Runtime/Weapon/CGunMotion.cpp index 2d7c71201..f016c5091 100644 --- a/Runtime/Weapon/CGunMotion.cpp +++ b/Runtime/Weapon/CGunMotion.cpp @@ -3,102 +3,87 @@ #include "CStateManager.hpp" #include "Character/CPASAnimParmData.hpp" -namespace urde -{ +namespace urde { CGunMotion::CGunMotion(CAssetId ancsId, const zeus::CVector3f& scale) -: x0_modelData(CAnimRes(ancsId, 0, scale, 0, false), 1), - x4c_gunController(x0_modelData) -{ - xb8_24_animPlaying = false; - LoadAnimations(); +: x0_modelData(CAnimRes(ancsId, 0, scale, 0, false), 1), x4c_gunController(x0_modelData) { + xb8_24_animPlaying = false; + LoadAnimations(); } -void CGunMotion::LoadAnimations() -{ - NWeaponTypes::get_token_vector(*x0_modelData.AnimationData(), 0, 14, xa8_anims, true); +void CGunMotion::LoadAnimations() { + NWeaponTypes::get_token_vector(*x0_modelData.AnimationData(), 0, 14, xa8_anims, true); } -bool CGunMotion::PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle, bool bigStrike) -{ - const CPASDatabase& pas = x0_modelData.GetAnimationData()->GetCharacterInfo().GetPASDatabase(); +bool CGunMotion::PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle, bool bigStrike) { + const CPASDatabase& pas = x0_modelData.GetAnimationData()->GetCharacterInfo().GetPASDatabase(); - s32 animId = -1; - bool loop = true; - switch (state) - { - case SamusGun::EAnimationState::Wander: - { - CPASAnimParmData parms((s32(state))); - auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - animId = anim.second; - break; - } - case SamusGun::EAnimationState::Idle: - { - CPASAnimParmData parms(s32(state), CPASAnimParm::FromEnum(0)); - auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - animId = anim.second; - break; - } - case SamusGun::EAnimationState::Struck: - { - CPASAnimParmData parms(s32(state), CPASAnimParm::FromInt32(0), CPASAnimParm::FromReal32(angle), - CPASAnimParm::FromBool(bigStrike), CPASAnimParm::FromBool(false)); - auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); - animId = anim.second; - loop = false; - break; - } - case SamusGun::EAnimationState::FreeLook: - x4c_gunController.EnterFreeLook(mgr, 0, -1); - break; - case SamusGun::EAnimationState::ComboFire: - x4c_gunController.EnterComboFire(mgr, 0); - break; - default: - break; - } + s32 animId = -1; + bool loop = true; + switch (state) { + case SamusGun::EAnimationState::Wander: { + CPASAnimParmData parms((s32(state))); + auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + animId = anim.second; + break; + } + case SamusGun::EAnimationState::Idle: { + CPASAnimParmData parms(s32(state), CPASAnimParm::FromEnum(0)); + auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + animId = anim.second; + break; + } + case SamusGun::EAnimationState::Struck: { + CPASAnimParmData parms(s32(state), CPASAnimParm::FromInt32(0), CPASAnimParm::FromReal32(angle), + CPASAnimParm::FromBool(bigStrike), CPASAnimParm::FromBool(false)); + auto anim = pas.FindBestAnimation(parms, *mgr.GetActiveRandom(), -1); + animId = anim.second; + loop = false; + break; + } + case SamusGun::EAnimationState::FreeLook: + x4c_gunController.EnterFreeLook(mgr, 0, -1); + break; + case SamusGun::EAnimationState::ComboFire: + x4c_gunController.EnterComboFire(mgr, 0); + break; + default: + break; + } - if (animId != -1) - { - x0_modelData.AnimationData()->EnableLooping(loop); - CAnimPlaybackParms aparms(animId, -1, 1.f, true); - x0_modelData.AnimationData()->SetAnimation(aparms, false); - } - - return loop; -} - -void CGunMotion::ReturnToDefault(CStateManager& mgr, bool setState) -{ - x4c_gunController.ReturnToDefault(mgr, 0.f, setState); -} - -void CGunMotion::BasePosition(bool bigStrikeReset) -{ - x0_modelData.AnimationData()->EnableLooping(false); - CAnimPlaybackParms aparms(bigStrikeReset ? 6 : 0, -1, 1.f, true); + if (animId != -1) { + x0_modelData.AnimationData()->EnableLooping(loop); + CAnimPlaybackParms aparms(animId, -1, 1.f, true); x0_modelData.AnimationData()->SetAnimation(aparms, false); + } + + return loop; } -void CGunMotion::EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2) -{ - xb8_24_animPlaying = true; - x4c_gunController.EnterFidget(mgr, s32(type), 0, parm2); +void CGunMotion::ReturnToDefault(CStateManager& mgr, bool setState) { + x4c_gunController.ReturnToDefault(mgr, 0.f, setState); } -void CGunMotion::Update(float dt, CStateManager& mgr) -{ - x0_modelData.AdvanceAnimation(dt, mgr, kInvalidAreaId, true); - if (x4c_gunController.Update(dt, mgr)) - xb8_24_animPlaying = false; +void CGunMotion::BasePosition(bool bigStrikeReset) { + x0_modelData.AnimationData()->EnableLooping(false); + CAnimPlaybackParms aparms(bigStrikeReset ? 6 : 0, -1, 1.f, true); + x0_modelData.AnimationData()->SetAnimation(aparms, false); } -void CGunMotion::Draw(const CStateManager& mgr, const zeus::CTransform& xf) const -{ - CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); - x0_modelData.Render(mgr, xf, nullptr, flags); +void CGunMotion::EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2) { + xb8_24_animPlaying = true; + x4c_gunController.EnterFidget(mgr, s32(type), 0, parm2); } +void CGunMotion::Update(float dt, CStateManager& mgr) { + x0_modelData.AdvanceAnimation(dt, mgr, kInvalidAreaId, true); + if (x4c_gunController.Update(dt, mgr)) + xb8_24_animPlaying = false; } + +void CGunMotion::Draw(const CStateManager& mgr, const zeus::CTransform& xf) const { + CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + x0_modelData.Render(mgr, xf, nullptr, flags); +} + +} // namespace urde diff --git a/Runtime/Weapon/CGunMotion.hpp b/Runtime/Weapon/CGunMotion.hpp index 95fc2c240..10be7eed2 100644 --- a/Runtime/Weapon/CGunMotion.hpp +++ b/Runtime/Weapon/CGunMotion.hpp @@ -5,51 +5,33 @@ #include "Character/CModelData.hpp" #include "CGunController.hpp" -namespace urde -{ +namespace urde { -namespace SamusGun -{ -enum class EAnimationState -{ - Wander, - Fidget, - Struck, - FreeLook, - ComboFire, - Idle, - BasePosition -}; -enum class EFidgetType -{ - Invalid = -1, - Minor, - Major -}; -} +namespace SamusGun { +enum class EAnimationState { Wander, Fidget, Struck, FreeLook, ComboFire, Idle, BasePosition }; +enum class EFidgetType { Invalid = -1, Minor, Major }; +} // namespace SamusGun -class CGunMotion -{ - CModelData x0_modelData; - CGunController x4c_gunController; - std::vector xa8_anims; - bool xb8_24_animPlaying : 1; +class CGunMotion { + CModelData x0_modelData; + CGunController x4c_gunController; + std::vector xa8_anims; + bool xb8_24_animPlaying : 1; - void LoadAnimations(); + void LoadAnimations(); public: - CGunMotion(CAssetId ancsId, const zeus::CVector3f& scale); - const CModelData& GetModelData() const { return x0_modelData; } - bool PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle, bool bigStrike); - void ReturnToDefault(CStateManager& mgr, bool setState); - void BasePosition(bool bigStrikeReset); - void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2); - void Update(float dt, CStateManager& mgr); - void Draw(const CStateManager& mgr, const zeus::CTransform& xf) const; - s32 GetFreeLookSetId() const { return x4c_gunController.GetFreeLookSetId(); } - CGunController& GunController() { return x4c_gunController; } - bool IsAnimPlaying() const { return xb8_24_animPlaying; } + CGunMotion(CAssetId ancsId, const zeus::CVector3f& scale); + const CModelData& GetModelData() const { return x0_modelData; } + bool PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle, bool bigStrike); + void ReturnToDefault(CStateManager& mgr, bool setState); + void BasePosition(bool bigStrikeReset); + void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2); + void Update(float dt, CStateManager& mgr); + void Draw(const CStateManager& mgr, const zeus::CTransform& xf) const; + s32 GetFreeLookSetId() const { return x4c_gunController.GetFreeLookSetId(); } + CGunController& GunController() { return x4c_gunController; } + bool IsAnimPlaying() const { return xb8_24_animPlaying; } }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CGunWeapon.cpp b/Runtime/Weapon/CGunWeapon.cpp index 77ceb6a3a..2e309b1b0 100644 --- a/Runtime/Weapon/CGunWeapon.cpp +++ b/Runtime/Weapon/CGunWeapon.cpp @@ -8,722 +8,552 @@ #include "Graphics/CSkinnedModel.hpp" #include "Graphics/CVertexMorphEffect.hpp" -namespace urde -{ -static const char* skBeamXferNames[] = -{ - "PowerXfer", - "IceXfer", - "WaveXfer", - "PlasmaXfer", - "PhazonXfer" +namespace urde { +static const char* skBeamXferNames[] = {"PowerXfer", "IceXfer", "WaveXfer", "PlasmaXfer", "PhazonXfer"}; + +static const char* skSuitArmNames[] = { + "PowerArm", "GravityArm", "VariaArm", "PhazonArm", "FusionArm", "FusionArmG", "FusionArmV", "FusionArmP", }; -static const char* skSuitArmNames[] = -{ - "PowerArm", - "GravityArm", - "VariaArm", - "PhazonArm", - "FusionArm", - "FusionArmG", - "FusionArmV", - "FusionArmP", -}; +static const char* skMuzzleNames[] = {"PowerMuzzle", "PowerCharge", "IceMuzzle", "IceCharge", "PowerMuzzle", + "WaveCharge", "PlasmaMuzzle", "PlasmaCharge", "PhazonMuzzle", "EmptyMuzzle"}; -static const char* skMuzzleNames[] = -{ - "PowerMuzzle", - "PowerCharge", - "IceMuzzle", - "IceCharge", - "PowerMuzzle", - "WaveCharge", - "PlasmaMuzzle", - "PlasmaCharge", - "PhazonMuzzle", - "EmptyMuzzle" -}; +static const char* skFrozenNames[] = {"powerFrozen", "Ice2nd_2", "iceFrozen", "Ice2nd_2", "waveFrozen", + "Ice2nd_2", "plasmaFrozen", "Ice2nd_2", "iceFrozen", "Ice2nd_2"}; -static const char* skFrozenNames[] = -{ - "powerFrozen", - "Ice2nd_2", - "iceFrozen", - "Ice2nd_2", - "waveFrozen", - "Ice2nd_2", - "plasmaFrozen", - "Ice2nd_2", - "iceFrozen", - "Ice2nd_2" -}; +static const char* skDependencyNames[] = {"Power_DGRP", "Ice_DGRP", "Wave_DGRP", "Plasma_DGRP", "Phazon_DGRP"}; -static const char* skDependencyNames[] = -{ - "Power_DGRP", - "Ice_DGRP", - "Wave_DGRP", - "Plasma_DGRP", - "Phazon_DGRP" -}; +static const char* skAnimDependencyNames[] = {"Power_Anim_DGRP", "Ice_Anim_DGRP", "Wave_Anim_DGRP", "Plasma_Anim_DGRP", + "Phazon_Anim_DGRP"}; -static const char* skAnimDependencyNames[] = -{ - "Power_Anim_DGRP", - "Ice_Anim_DGRP", - "Wave_Anim_DGRP", - "Plasma_Anim_DGRP", - "Phazon_Anim_DGRP" -}; - -CPlayerState::EBeamId GetWeaponIndex(EWeaponType type) -{ - if (type == EWeaponType::Power) - return CPlayerState::EBeamId::Power; - else if (type == EWeaponType::Ice) - return CPlayerState::EBeamId::Ice; - else if (type == EWeaponType::Wave) - return CPlayerState::EBeamId::Wave; - else if (type == EWeaponType::Plasma) - return CPlayerState::EBeamId::Plasma; - else if (type == EWeaponType::Phazon) - return CPlayerState::EBeamId::Phazon; +CPlayerState::EBeamId GetWeaponIndex(EWeaponType type) { + if (type == EWeaponType::Power) return CPlayerState::EBeamId::Power; + else if (type == EWeaponType::Ice) + return CPlayerState::EBeamId::Ice; + else if (type == EWeaponType::Wave) + return CPlayerState::EBeamId::Wave; + else if (type == EWeaponType::Plasma) + return CPlayerState::EBeamId::Plasma; + else if (type == EWeaponType::Phazon) + return CPlayerState::EBeamId::Phazon; + return CPlayerState::EBeamId::Power; } -CGunWeapon::CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale) -: x4_scale(scale), - x104_gunCharacter(g_SimplePool->GetObj(SObjectTag{FOURCC('ANCS'), ancsId})), - x13c_armCharacter(g_SimplePool->GetObj(skSuitArmNames[0])), - x160_xferEffect(g_SimplePool->GetObj(skBeamXferNames[int(GetWeaponIndex(type))])), - x1c0_weaponType(type), - x1c4_playerId(playerId), - x1c8_playerMaterial(playerMaterial), - x200_beamId(GetWeaponIndex(type)), - x20c_shaderIdx(u32(x200_beamId)), - x214_ancsId(ancsId) -{ - AllocResPools(x200_beamId); - BuildDependencyList(x200_beamId); +CGunWeapon::CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale) +: x4_scale(scale) +, x104_gunCharacter(g_SimplePool->GetObj(SObjectTag{FOURCC('ANCS'), ancsId})) +, x13c_armCharacter(g_SimplePool->GetObj(skSuitArmNames[0])) +, x160_xferEffect(g_SimplePool->GetObj(skBeamXferNames[int(GetWeaponIndex(type))])) +, x1c0_weaponType(type) +, x1c4_playerId(playerId) +, x1c8_playerMaterial(playerMaterial) +, x200_beamId(GetWeaponIndex(type)) +, x20c_shaderIdx(u32(x200_beamId)) +, x214_ancsId(ancsId) { + AllocResPools(x200_beamId); + BuildDependencyList(x200_beamId); } -void CGunWeapon::AllocResPools(CPlayerState::EBeamId beam) -{ - const CAssetId* wPair = g_tweakGunRes->GetWeaponPair(beam); - const char** muzzleNames = &skMuzzleNames[int(beam) * 2]; - const char** frozenNames = &skFrozenNames[int(beam) * 2]; - for (int i=0 ; i<2 ; ++i) - { - x16c_muzzleEffects.push_back(g_SimplePool->GetObj(muzzleNames[i])); - x144_weapons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('WPSC'), wPair[i]})); - x188_frozenEffects.push_back(g_SimplePool->GetObj(frozenNames[i])); +void CGunWeapon::AllocResPools(CPlayerState::EBeamId beam) { + const CAssetId* wPair = g_tweakGunRes->GetWeaponPair(beam); + const char** muzzleNames = &skMuzzleNames[int(beam) * 2]; + const char** frozenNames = &skFrozenNames[int(beam) * 2]; + for (int i = 0; i < 2; ++i) { + x16c_muzzleEffects.push_back(g_SimplePool->GetObj(muzzleNames[i])); + x144_weapons.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('WPSC'), wPair[i]})); + x188_frozenEffects.push_back(g_SimplePool->GetObj(frozenNames[i])); + } +} + +void CGunWeapon::FreeResPools() { + x160_xferEffect.Unlock(); + for (int i = 0; i < 2; ++i) { + x16c_muzzleEffects[i].Unlock(); + x144_weapons[i].Unlock(); + x188_frozenEffects[i].Unlock(); + } + x10c_anims.clear(); + x1a4_muzzleGenerators.clear(); + x1d0_velInfo.Clear(); +} + +void CGunWeapon::FillTokenVector(const std::vector& tags, std::vector& objects) { + for (const SObjectTag& tag : tags) + objects.push_back(g_SimplePool->GetObj(tag)); +} + +void CGunWeapon::BuildDependencyList(CPlayerState::EBeamId beam) { + TLockedToken deps = g_SimplePool->GetObj(skDependencyNames[int(beam)]); + TLockedToken animDeps = g_SimplePool->GetObj(skAnimDependencyNames[int(beam)]); + x12c_deps.reserve(deps->GetObjectTagVector().size() + animDeps->GetObjectTagVector().size()); + FillTokenVector(deps->GetObjectTagVector(), x12c_deps); + FillTokenVector(animDeps->GetObjectTagVector(), x12c_deps); +} + +void CGunWeapon::AsyncLoadSuitArm(CStateManager& mgr) { + + xb0_suitArmModelData = std::experimental::nullopt; + x13c_armCharacter = g_SimplePool->GetObj(skSuitArmNames[int(NWeaponTypes::get_current_suit(mgr))]); + x13c_armCharacter.Lock(); + x218_28_suitArmLocked = true; +} + +void CGunWeapon::Reset(CStateManager& mgr) { + if (!x218_26_loaded) + return; + + x10_solidModelData->AnimationData()->EnableLooping(false); + if (x218_25_enableCharge) + x218_25_enableCharge = false; + else + x100_gunController->Reset(); +} + +static const s32 skAnimTypeList[] = {0, 4, 1, 2, 3, 5, 6, 7, 8, 9, 10}; + +void CGunWeapon::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) { + if (x218_26_loaded && type >= NWeaponTypes::EGunAnimType::BasePosition && + type <= NWeaponTypes::EGunAnimType::ToBeam) { + x10_solidModelData->AnimationData()->EnableLooping(loop); + CAnimPlaybackParms parms(skAnimTypeList[int(type)], -1, 1.f, true); + x10_solidModelData->AnimationData()->SetAnimation(parms, false); + } +} + +void CGunWeapon::PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + // Empty +} + +void CGunWeapon::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + if (x218_26_loaded && x1b8_frozenGenerator && x204_frozenEffect != EFrozenFxType::None) + x1b8_frozenGenerator->Render(); +} + +void CGunWeapon::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) { + if (x218_26_loaded && x204_frozenEffect != EFrozenFxType::None) { + if (x204_frozenEffect == EFrozenFxType::Thawed) { + if (x1b8_frozenGenerator->IsSystemDeletable()) { + x1b8_frozenGenerator.reset(); + } else { + x1b8_frozenGenerator->SetTranslation(xf.origin); + x1b8_frozenGenerator->SetOrientation(xf.getRotation()); + } + } else { + x1b8_frozenGenerator->SetGlobalOrientAndTrans(xf); } + if (x1b8_frozenGenerator) + x1b8_frozenGenerator->Update(dt); + } } -void CGunWeapon::FreeResPools() -{ - x160_xferEffect.Unlock(); - for (int i=0 ; i<2 ; ++i) - { - x16c_muzzleEffects[i].Unlock(); - x144_weapons[i].Unlock(); - x188_frozenEffects[i].Unlock(); - } - x10c_anims.clear(); - x1a4_muzzleGenerators.clear(); - x1d0_velInfo.Clear(); -} - -void CGunWeapon::FillTokenVector(const std::vector& tags, std::vector& objects) -{ - for (const SObjectTag& tag : tags) - objects.push_back(g_SimplePool->GetObj(tag)); -} - -void CGunWeapon::BuildDependencyList(CPlayerState::EBeamId beam) -{ - TLockedToken deps = g_SimplePool->GetObj(skDependencyNames[int(beam)]); - TLockedToken animDeps = g_SimplePool->GetObj(skAnimDependencyNames[int(beam)]); - x12c_deps.reserve(deps->GetObjectTagVector().size() + animDeps->GetObjectTagVector().size()); - FillTokenVector(deps->GetObjectTagVector(), x12c_deps); - FillTokenVector(animDeps->GetObjectTagVector(), x12c_deps); -} - -void CGunWeapon::AsyncLoadSuitArm(CStateManager& mgr) -{ - - xb0_suitArmModelData = std::experimental::nullopt; - x13c_armCharacter = g_SimplePool->GetObj(skSuitArmNames[int(NWeaponTypes::get_current_suit(mgr))]); - x13c_armCharacter.Lock(); - x218_28_suitArmLocked = true; -} - -void CGunWeapon::Reset(CStateManager& mgr) -{ - if (!x218_26_loaded) - return; - - x10_solidModelData->AnimationData()->EnableLooping(false); - if (x218_25_enableCharge) - x218_25_enableCharge = false; - else - x100_gunController->Reset(); -} - -static const s32 skAnimTypeList[] = { 0, 4, 1, 2, 3, 5, 6, 7, 8, 9, 10 }; - -void CGunWeapon::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) -{ - if (x218_26_loaded && type >= NWeaponTypes::EGunAnimType::BasePosition && - type <= NWeaponTypes::EGunAnimType::ToBeam) - { - x10_solidModelData->AnimationData()->EnableLooping(loop); - CAnimPlaybackParms parms(skAnimTypeList[int(type)], -1, 1.f, true); - x10_solidModelData->AnimationData()->SetAnimation(parms, false); - } -} - -void CGunWeapon::PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - // Empty -} - -void CGunWeapon::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x218_26_loaded && x1b8_frozenGenerator && x204_frozenEffect != EFrozenFxType::None) - x1b8_frozenGenerator->Render(); -} - -void CGunWeapon::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x218_26_loaded && x204_frozenEffect != EFrozenFxType::None) - { - if (x204_frozenEffect == EFrozenFxType::Thawed) - { - if (x1b8_frozenGenerator->IsSystemDeletable()) - { - x1b8_frozenGenerator.reset(); - } - else - { - x1b8_frozenGenerator->SetTranslation(xf.origin); - x1b8_frozenGenerator->SetOrientation(xf.getRotation()); - } - } - else - { - x1b8_frozenGenerator->SetGlobalOrientAndTrans(xf); - } - if (x1b8_frozenGenerator) - x1b8_frozenGenerator->Update(dt); - } -} - -const s32 CGunWeapon::skShootAnim[2] = { 4, 3 }; +const s32 CGunWeapon::skShootAnim[2] = {4, 3}; void CGunWeapon::Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) -{ - CDamageInfo dInfo = GetDamageInfo(mgr, chargeState, chargeFactor1); - zeus::CVector3f scale(chargeState == EChargeState::Normal ? 1.f : chargeFactor2); - bool partialCharge = chargeState == EChargeState::Normal ? false : !zeus::close_enough(chargeFactor1, 1.f); - EProjectileAttrib attribs = EProjectileAttrib::ArmCannon; - if (partialCharge) - attribs |= EProjectileAttrib::PartialCharge; - if (chargeState == EChargeState::Charged) - attribs |= EProjectileAttrib::Charged; + CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) { + CDamageInfo dInfo = GetDamageInfo(mgr, chargeState, chargeFactor1); + zeus::CVector3f scale(chargeState == EChargeState::Normal ? 1.f : chargeFactor2); + bool partialCharge = chargeState == EChargeState::Normal ? false : !zeus::close_enough(chargeFactor1, 1.f); + EProjectileAttrib attribs = EProjectileAttrib::ArmCannon; + if (partialCharge) + attribs |= EProjectileAttrib::PartialCharge; + if (chargeState == EChargeState::Charged) + attribs |= EProjectileAttrib::Charged; - CEnergyProjectile* proj = new CEnergyProjectile(true, x144_weapons[int(chargeState)], x1c0_weaponType, - xf, x1c8_playerMaterial, dInfo, mgr.AllocateUniqueId(), - kInvalidAreaId, x1c4_playerId, homingTarget, attribs, - underwater, scale, {}, -1, false); - mgr.AddObject(proj); - proj->Think(dt, mgr); + CEnergyProjectile* proj = new CEnergyProjectile( + true, x144_weapons[int(chargeState)], x1c0_weaponType, xf, x1c8_playerMaterial, dInfo, mgr.AllocateUniqueId(), + kInvalidAreaId, x1c4_playerId, homingTarget, attribs, underwater, scale, {}, -1, false); + mgr.AddObject(proj); + proj->Think(dt, mgr); - if (chargeState == EChargeState::Charged) - { - x218_25_enableCharge = true; - mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::skChargedShotCameraShakeData, false); + if (chargeState == EChargeState::Charged) { + x218_25_enableCharge = true; + mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::skChargedShotCameraShakeData, false); + } + + x10_solidModelData->AnimationData()->EnableLooping(false); + CAnimPlaybackParms parms(skShootAnim[int(chargeState)], -1, 1.f, true); + x10_solidModelData->AnimationData()->SetAnimation(parms, false); +} + +void CGunWeapon::EnableFx(bool enable) { + // Empty +} + +void CGunWeapon::EnableSecondaryFx(ESecondaryFxType type) { x1cc_enabledSecondaryEffect = type; } + +void CGunWeapon::EnableFrozenEffect(EFrozenFxType type) { + switch (type) { + case EFrozenFxType::Thawed: + if (x204_frozenEffect == EFrozenFxType::Thawed) + break; + x1b8_frozenGenerator = std::make_unique(x188_frozenEffects[1]); + x1b8_frozenGenerator->SetGlobalScale(x4_scale); + break; + case EFrozenFxType::Frozen: + if (x204_frozenEffect == EFrozenFxType::Frozen) + break; + x1b8_frozenGenerator = std::make_unique(x188_frozenEffects[0]); + x1b8_frozenGenerator->SetGlobalScale(x4_scale); + break; + default: + break; + } + x204_frozenEffect = type; +} + +void CGunWeapon::ActivateCharge(bool enable, bool resetEffect) { + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetParticleEmission(false); + x208_muzzleEffectIdx = u32(enable); + if (enable || resetEffect) { + x1a4_muzzleGenerators[x208_muzzleEffectIdx] = + std::make_unique(x16c_muzzleEffects[x208_muzzleEffectIdx]); + } +} + +void CGunWeapon::Touch(const CStateManager& mgr) { + if (x10_solidModelData) { + x10_solidModelData->Touch(mgr, x20c_shaderIdx); + if (xb0_suitArmModelData) + xb0_suitArmModelData->Touch(mgr, 0); + } +} + +void CGunWeapon::TouchHolo(const CStateManager& mgr) { + if (x60_holoModelData) + x60_holoModelData->Touch(mgr, 0); +} + +void CGunWeapon::PointGenerator(void* ctx, const std::vector>& vn) { + reinterpret_cast(ctx)->GeneratePoints(vn); +} + +void CGunWeapon::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags, + const CActorLights* lights) const { + if (!x218_26_loaded) + return; + + zeus::CTransform armXf = xf * x10_solidModelData->GetScaledLocatorTransform("elbow"); + + if (x1bc_rainSplashGenerator && x1bc_rainSplashGenerator->IsRaining()) + CSkinnedModel::SetPointGeneratorFunc(x1bc_rainSplashGenerator, PointGenerator); + + if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot && x200_beamId != CPlayerState::EBeamId::Ice) { + /* Hot Draw */ + zeus::CColor mulColor(flags.x4_color.a(), flags.x4_color.a()); + zeus::CColor addColor(0.25f, 0.25f); + if (x218_29_drawHologram) { + DrawHologram(mgr, xf, flags); + } else { + CModelFlags useFlags(0, 0, 3, zeus::CColor::skWhite); + x10_solidModelData->RenderThermal(xf, mulColor, addColor, useFlags); } - x10_solidModelData->AnimationData()->EnableLooping(false); - CAnimPlaybackParms parms(skShootAnim[int(chargeState)], -1, 1.f, true); - x10_solidModelData->AnimationData()->SetAnimation(parms, false); -} - -void CGunWeapon::EnableFx(bool enable) -{ - // Empty -} - -void CGunWeapon::EnableSecondaryFx(ESecondaryFxType type) -{ - x1cc_enabledSecondaryEffect = type; -} - -void CGunWeapon::EnableFrozenEffect(EFrozenFxType type) -{ - switch (type) - { - case EFrozenFxType::Thawed: - if (x204_frozenEffect == EFrozenFxType::Thawed) - break; - x1b8_frozenGenerator = std::make_unique(x188_frozenEffects[1]); - x1b8_frozenGenerator->SetGlobalScale(x4_scale); - break; - case EFrozenFxType::Frozen: - if (x204_frozenEffect == EFrozenFxType::Frozen) - break; - x1b8_frozenGenerator = std::make_unique(x188_frozenEffects[0]); - x1b8_frozenGenerator->SetGlobalScale(x4_scale); - break; - default: - break; + if (drawSuitArm && xb0_suitArmModelData) { + CModelFlags useFlags(0, 0, 3, zeus::CColor::skWhite); + xb0_suitArmModelData->RenderThermal(xf, mulColor, addColor, useFlags); } - x204_frozenEffect = type; -} - -void CGunWeapon::ActivateCharge(bool enable, bool resetEffect) -{ - x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetParticleEmission(false); - x208_muzzleEffectIdx = u32(enable); - if (enable || resetEffect) - { - x1a4_muzzleGenerators[x208_muzzleEffectIdx] = - std::make_unique(x16c_muzzleEffects[x208_muzzleEffectIdx]); - } -} - -void CGunWeapon::Touch(const CStateManager& mgr) -{ - if (x10_solidModelData) - { - x10_solidModelData->Touch(mgr, x20c_shaderIdx); - if (xb0_suitArmModelData) - xb0_suitArmModelData->Touch(mgr, 0); - } -} - -void CGunWeapon::TouchHolo(const CStateManager& mgr) -{ - if (x60_holoModelData) - x60_holoModelData->Touch(mgr, 0); -} - -void CGunWeapon::PointGenerator(void* ctx, const std::vector>& vn) -{ - reinterpret_cast(ctx)->GeneratePoints(vn); -} - -void CGunWeapon::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, - const CModelFlags& flags, const CActorLights* lights) const -{ - if (!x218_26_loaded) - return; - - zeus::CTransform armXf = xf * x10_solidModelData->GetScaledLocatorTransform("elbow"); - - if (x1bc_rainSplashGenerator && x1bc_rainSplashGenerator->IsRaining()) - CSkinnedModel::SetPointGeneratorFunc(x1bc_rainSplashGenerator, PointGenerator); - - if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot && x200_beamId != CPlayerState::EBeamId::Ice) - { - /* Hot Draw */ - zeus::CColor mulColor(flags.x4_color.a(), flags.x4_color.a()); - zeus::CColor addColor(0.25f, 0.25f); - if (x218_29_drawHologram) - { - DrawHologram(mgr, xf, flags); - } - else - { - CModelFlags useFlags(0, 0, 3, zeus::CColor::skWhite); - x10_solidModelData->RenderThermal(xf, mulColor, addColor, useFlags); - } - - if (drawSuitArm && xb0_suitArmModelData) - { - CModelFlags useFlags(0, 0, 3, zeus::CColor::skWhite); - xb0_suitArmModelData->RenderThermal(xf, mulColor, addColor, useFlags); - } - } - else - { - /* Cold Draw */ - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay && !x218_29_drawHologram) - { - CModelFlags useFlags = flags; - useFlags.x1_matSetIdx = u8(x20c_shaderIdx); - x10_solidModelData->Render(mgr, xf, lights, useFlags); - } - else - { - DrawHologram(mgr, xf, flags); - } - - if (drawSuitArm && xb0_suitArmModelData) - { - xb0_suitArmModelData->Render(mgr, armXf, lights, flags); - } + } else { + /* Cold Draw */ + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay && !x218_29_drawHologram) { + CModelFlags useFlags = flags; + useFlags.x1_matSetIdx = u8(x20c_shaderIdx); + x10_solidModelData->Render(mgr, xf, lights, useFlags); + } else { + DrawHologram(mgr, xf, flags); } - if (x1bc_rainSplashGenerator && x1bc_rainSplashGenerator->IsRaining()) - { - CSkinnedModel::ClearPointGeneratorFunc(); - x1bc_rainSplashGenerator->Draw(xf); + if (drawSuitArm && xb0_suitArmModelData) { + xb0_suitArmModelData->Render(mgr, armXf, lights, flags); } + } + + if (x1bc_rainSplashGenerator && x1bc_rainSplashGenerator->IsRaining()) { + CSkinnedModel::ClearPointGeneratorFunc(); + x1bc_rainSplashGenerator->Draw(xf); + } } -void CGunWeapon::DrawMuzzleFx(const CStateManager& mgr) const -{ - if (const CElementGen* effect = x1a4_muzzleGenerators[x208_muzzleEffectIdx].get()) - { - if (x200_beamId != CPlayerState::EBeamId::Ice && - mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) - { - CElementGen::SetSubtractBlend(true); - const_cast(effect)->Render(); - CElementGen::SetSubtractBlend(false); - } - else - { - const_cast(effect)->Render(); - } +void CGunWeapon::DrawMuzzleFx(const CStateManager& mgr) const { + if (const CElementGen* effect = x1a4_muzzleGenerators[x208_muzzleEffectIdx].get()) { + if (x200_beamId != CPlayerState::EBeamId::Ice && + mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) { + CElementGen::SetSubtractBlend(true); + const_cast(effect)->Render(); + CElementGen::SetSubtractBlend(false); + } else { + const_cast(effect)->Render(); } + } } -void CGunWeapon::LoadSuitArm(CStateManager& mgr) -{ - if (x13c_armCharacter.IsLoaded()) - { - CAssetId armId = NWeaponTypes::get_asset_id_from_name(skSuitArmNames[int(NWeaponTypes::get_current_suit(mgr))]); - xb0_suitArmModelData.emplace(CStaticRes(armId, x4_scale)); - xb0_suitArmModelData->SetSortThermal(true); - x218_28_suitArmLocked = false; - x13c_armCharacter.Unlock(); - } -} - -void CGunWeapon::LoadGunModels(CStateManager& mgr) -{ - s32 defaultAnim = x218_27_subtypeBasePose ? 0 : 9; - x10_solidModelData.emplace(CAnimRes(x214_ancsId, 0, x4_scale, defaultAnim, false)); - x60_holoModelData.emplace(CAnimRes(x214_ancsId, 1, x4_scale, defaultAnim, false)); - CAnimPlaybackParms parms(defaultAnim, -1, 1.f, true); - x10_solidModelData->AnimationData()->SetAnimation(parms, true); - LoadSuitArm(mgr); - x10_solidModelData->SetSortThermal(true); - x60_holoModelData->SetSortThermal(true); - x100_gunController = std::make_unique(*x10_solidModelData); -} - -void CGunWeapon::LoadAnimations() -{ - NWeaponTypes::get_token_vector(*x10_solidModelData->GetAnimationData(), 0, 15, x10c_anims, true); -} - -bool CGunWeapon::IsAnimsLoaded() const -{ - for (const CToken& tok : x10c_anims) - if (!tok.IsLoaded()) - return false; - return true; -} - -void CGunWeapon::LoadMuzzleFx(float dt) -{ - for (int i=0 ; i<2 ; ++i) - { - x1a4_muzzleGenerators.push_back(std::make_unique(x16c_muzzleEffects[i])); - x1a4_muzzleGenerators.back()->SetParticleEmission(false); - x1a4_muzzleGenerators.back()->Update(dt); - } -} - -void CGunWeapon::LoadProjectileData(CStateManager& mgr) -{ - CRandom16 random(mgr.GetUpdateFrameIndex()); - CGlobalRandom grand(random); - for (int i=0 ; i<2 ; ++i) - { - zeus::CVector3f weaponVel; - if (const CVectorElement* ivec = x144_weapons[i]->x4_IVEC.get()) - ivec->GetValue(0, weaponVel); - x1d0_velInfo.x0_vel.push_back(weaponVel); - float tratVal = 0.f; - if (const CRealElement* trat = x144_weapons[i]->x30_TRAT.get()) - trat->GetValue(0, tratVal); - x1d0_velInfo.x24_trat.push_back(tratVal); - x1d0_velInfo.x1c_targetHoming.push_back(x144_weapons[i]->x29_HOMG); - if (weaponVel.y() > 0.f) - x1d0_velInfo.x0_vel.back() *= zeus::CVector3f(60.f); - else - x1d0_velInfo.x0_vel.back() = zeus::CVector3f::skForward; - } -} - -void CGunWeapon::LoadFxIdle(float dt, CStateManager& mgr) -{ - if (NWeaponTypes::are_tokens_ready(x12c_deps)) - { - if ((x210_loadFlags & 0x2) != 0 && (x210_loadFlags & 0x4) != 0 && (x210_loadFlags & 0x10) != 0) - return; - bool loaded = true; - for (int i=0 ; i<2 ; ++i) - { - if (!x16c_muzzleEffects[i].IsLoaded()) - { - loaded = false; - break; - } - if (!x144_weapons[i].IsLoaded()) - { - loaded = false; - break; - } - } - - for (int i=0 ; i<2 ; ++i) - { - if (!x188_frozenEffects[i].IsLoaded()) - { - loaded = false; - break; - } - } - - if (!x160_xferEffect.IsLoaded()) - loaded = false; - - if (loaded) - { - if ((x210_loadFlags & 0x2) != 0x2) - { - LoadMuzzleFx(dt); - x210_loadFlags |= 0x2; - } - x210_loadFlags |= 0x10; - if ((x210_loadFlags & 0x4) != 0x4) - { - LoadProjectileData(mgr); - x210_loadFlags |= 0x4; - } - } - } -} - -void CGunWeapon::Update(float dt, CStateManager& mgr) -{ - if (x218_26_loaded) - { - x10_solidModelData->AdvanceAnimation(dt, mgr, kInvalidAreaId, true); - x100_gunController->Update(dt, mgr); - if (x218_28_suitArmLocked) - LoadSuitArm(mgr); - } - else - { - if (x104_gunCharacter) - { - if (x104_gunCharacter.IsLoaded()) - { - if ((x210_loadFlags & 0x1) != 0x1) - { - LoadGunModels(mgr); - LoadAnimations(); - x210_loadFlags |= 0x1; - } - if ((x210_loadFlags & 0x8) != 0x8) - { - if (IsAnimsLoaded()) - x210_loadFlags |= 0x8; - } - } - - LoadFxIdle(dt, mgr); - if ((x210_loadFlags & 0x1f) == 0x1f) - { - if (x10_solidModelData->PickAnimatedModel(CModelData::EWhichModel::Normal).GetModel()-> - IsLoaded(x20c_shaderIdx) && xb0_suitArmModelData->IsLoaded(0)) - x218_26_loaded = true; - } - } - } -} - -void CGunWeapon::LockTokens(CStateManager& mgr) -{ - AsyncLoadSuitArm(mgr); - NWeaponTypes::lock_tokens(x12c_deps); -} - -void CGunWeapon::UnlockTokens() -{ +void CGunWeapon::LoadSuitArm(CStateManager& mgr) { + if (x13c_armCharacter.IsLoaded()) { + CAssetId armId = NWeaponTypes::get_asset_id_from_name(skSuitArmNames[int(NWeaponTypes::get_current_suit(mgr))]); + xb0_suitArmModelData.emplace(CStaticRes(armId, x4_scale)); + xb0_suitArmModelData->SetSortThermal(true); + x218_28_suitArmLocked = false; x13c_armCharacter.Unlock(); - NWeaponTypes::unlock_tokens(x12c_deps); + } } -void CGunWeapon::Load(CStateManager& mgr, bool subtypeBasePose) -{ - LockTokens(mgr); - x218_27_subtypeBasePose = subtypeBasePose; - x204_frozenEffect = EFrozenFxType::None; - x1b8_frozenGenerator.reset(); - x104_gunCharacter.Lock(); - x160_xferEffect.Lock(); - for (int i=0 ; i<2 ; ++i) - { - x16c_muzzleEffects[i].Lock(); - x144_weapons[i].Lock(); - } - for (int i=0 ; i<2 ; ++i) - x188_frozenEffects[i].Lock(); +void CGunWeapon::LoadGunModels(CStateManager& mgr) { + s32 defaultAnim = x218_27_subtypeBasePose ? 0 : 9; + x10_solidModelData.emplace(CAnimRes(x214_ancsId, 0, x4_scale, defaultAnim, false)); + x60_holoModelData.emplace(CAnimRes(x214_ancsId, 1, x4_scale, defaultAnim, false)); + CAnimPlaybackParms parms(defaultAnim, -1, 1.f, true); + x10_solidModelData->AnimationData()->SetAnimation(parms, true); + LoadSuitArm(mgr); + x10_solidModelData->SetSortThermal(true); + x60_holoModelData->SetSortThermal(true); + x100_gunController = std::make_unique(*x10_solidModelData); } -void CGunWeapon::Unload(CStateManager& mgr) -{ - UnlockTokens(); - x210_loadFlags = 0; - x204_frozenEffect = EFrozenFxType::None; - x10_solidModelData = std::experimental::nullopt; - x60_holoModelData = std::experimental::nullopt; - xb0_suitArmModelData = std::experimental::nullopt; - x100_gunController.reset(); - x1bc_rainSplashGenerator = nullptr; - x1b8_frozenGenerator.reset(); - FreeResPools(); - x104_gunCharacter.Unlock(); - x218_26_loaded = false; +void CGunWeapon::LoadAnimations() { + NWeaponTypes::get_token_vector(*x10_solidModelData->GetAnimationData(), 0, 15, x10c_anims, true); } -bool CGunWeapon::IsLoaded() const -{ - return x218_26_loaded; +bool CGunWeapon::IsAnimsLoaded() const { + for (const CToken& tok : x10c_anims) + if (!tok.IsLoaded()) + return false; + return true; } -void CGunWeapon::DrawHologram(const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags) const -{ - if (!x218_26_loaded) - return; +void CGunWeapon::LoadMuzzleFx(float dt) { + for (int i = 0; i < 2; ++i) { + x1a4_muzzleGenerators.push_back(std::make_unique(x16c_muzzleEffects[i])); + x1a4_muzzleGenerators.back()->SetParticleEmission(false); + x1a4_muzzleGenerators.back()->Update(dt); + } +} - if (x218_29_drawHologram) - { - CModelFlags useFlags = flags; - useFlags.m_extendedShader = EExtendedShader::Flat; - x60_holoModelData->Render(CModelData::EWhichModel::Normal, xf, nullptr, useFlags); - } +void CGunWeapon::LoadProjectileData(CStateManager& mgr) { + CRandom16 random(mgr.GetUpdateFrameIndex()); + CGlobalRandom grand(random); + for (int i = 0; i < 2; ++i) { + zeus::CVector3f weaponVel; + if (const CVectorElement* ivec = x144_weapons[i]->x4_IVEC.get()) + ivec->GetValue(0, weaponVel); + x1d0_velInfo.x0_vel.push_back(weaponVel); + float tratVal = 0.f; + if (const CRealElement* trat = x144_weapons[i]->x30_TRAT.get()) + trat->GetValue(0, tratVal); + x1d0_velInfo.x24_trat.push_back(tratVal); + x1d0_velInfo.x1c_targetHoming.push_back(x144_weapons[i]->x29_HOMG); + if (weaponVel.y() > 0.f) + x1d0_velInfo.x0_vel.back() *= zeus::CVector3f(60.f); else - { - CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x10_solidModelData->GetScale())); - //CGraphics::DisableAllLights(); - //g_Renderer->SetAmbientColor(zeus::CColor::skWhite); - CSkinnedModel& model = - const_cast(*x60_holoModelData->GetAnimationData()->GetModelData()); - model.GetModelInst()->ActivateLights({CLight::BuildLocalAmbient({}, zeus::CColor::skWhite)}); - const_cast(this)->x10_solidModelData->AnimationData()->Render(model, flags, {}, nullptr); - //g_Renderer->SetAmbientColor(zeus::CColor::skWhite); - //CGraphics::DisableAllLights(); + x1d0_velInfo.x0_vel.back() = zeus::CVector3f::skForward; + } +} + +void CGunWeapon::LoadFxIdle(float dt, CStateManager& mgr) { + if (NWeaponTypes::are_tokens_ready(x12c_deps)) { + if ((x210_loadFlags & 0x2) != 0 && (x210_loadFlags & 0x4) != 0 && (x210_loadFlags & 0x10) != 0) + return; + bool loaded = true; + for (int i = 0; i < 2; ++i) { + if (!x16c_muzzleEffects[i].IsLoaded()) { + loaded = false; + break; + } + if (!x144_weapons[i].IsLoaded()) { + loaded = false; + break; + } } -} -void CGunWeapon::UpdateMuzzleFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, bool emitting) -{ - x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetGlobalTranslation(pos); - x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetGlobalScale(scale); - x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetParticleEmission(emitting); - x1a4_muzzleGenerators[x208_muzzleEffectIdx]->Update(dt); -} - -void CGunWeapon::ReturnToDefault(CStateManager& mgr) -{ - x100_gunController->ReturnToDefault(mgr, 0.f, false); -} - -bool CGunWeapon::PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle) -{ - switch (state) - { - case SamusGun::EAnimationState::ComboFire: - x100_gunController->EnterComboFire(mgr, s32(x200_beamId)); - return true; - default: - return false; - case SamusGun::EAnimationState::Wander: - return true; + for (int i = 0; i < 2; ++i) { + if (!x188_frozenEffects[i].IsLoaded()) { + loaded = false; + break; + } } -} -void CGunWeapon::UnLoadFidget() -{ - x100_gunController->UnLoadFidget(); -} + if (!x160_xferEffect.IsLoaded()) + loaded = false; -bool CGunWeapon::IsFidgetLoaded() const -{ - return x100_gunController->IsFidgetLoaded(); -} - -void CGunWeapon::AsyncLoadFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 animSet) -{ - x100_gunController->LoadFidgetAnimAsync(mgr, s32(type), s32(x200_beamId), animSet); -} - -void CGunWeapon::EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2) -{ - x100_gunController->EnterFidget(mgr, s32(type), s32(x200_beamId), parm2); -} - -CDamageInfo CGunWeapon::GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr) -{ - CDamageInfo ret(shotParam); - if (g_GameState->GetHardMode()) - ret.MultiplyDamage(g_GameState->GetHardModeWeaponMultiplier()); - return ret; -} - -CDamageInfo CGunWeapon::GetDamageInfo(CStateManager& mgr, EChargeState chargeState, float chargeFactor) const -{ - const SWeaponInfo& wInfo = GetWeaponInfo(); - if (chargeState == EChargeState::Normal) - { - return GetShotDamageInfo(wInfo.x4_normal, mgr); + if (loaded) { + if ((x210_loadFlags & 0x2) != 0x2) { + LoadMuzzleFx(dt); + x210_loadFlags |= 0x2; + } + x210_loadFlags |= 0x10; + if ((x210_loadFlags & 0x4) != 0x4) { + LoadProjectileData(mgr); + x210_loadFlags |= 0x4; + } } - else - { - SShotParam param = wInfo.x20_charged; - param.damage *= chargeFactor; - param.radiusDamage *= chargeFactor; - param.radius *= chargeFactor; - param.knockback *= chargeFactor; - param.noImmunity = false; - return GetShotDamageInfo(param, mgr); + } +} + +void CGunWeapon::Update(float dt, CStateManager& mgr) { + if (x218_26_loaded) { + x10_solidModelData->AdvanceAnimation(dt, mgr, kInvalidAreaId, true); + x100_gunController->Update(dt, mgr); + if (x218_28_suitArmLocked) + LoadSuitArm(mgr); + } else { + if (x104_gunCharacter) { + if (x104_gunCharacter.IsLoaded()) { + if ((x210_loadFlags & 0x1) != 0x1) { + LoadGunModels(mgr); + LoadAnimations(); + x210_loadFlags |= 0x1; + } + if ((x210_loadFlags & 0x8) != 0x8) { + if (IsAnimsLoaded()) + x210_loadFlags |= 0x8; + } + } + + LoadFxIdle(dt, mgr); + if ((x210_loadFlags & 0x1f) == 0x1f) { + if (x10_solidModelData->PickAnimatedModel(CModelData::EWhichModel::Normal) + .GetModel() + ->IsLoaded(x20c_shaderIdx) && + xb0_suitArmModelData->IsLoaded(0)) + x218_26_loaded = true; + } } + } } -const SWeaponInfo& CGunWeapon::GetWeaponInfo() const -{ - return g_tweakPlayerGun->GetBeamInfo(s32(x200_beamId)); +void CGunWeapon::LockTokens(CStateManager& mgr) { + AsyncLoadSuitArm(mgr); + NWeaponTypes::lock_tokens(x12c_deps); } -zeus::CAABox CGunWeapon::GetBounds() const -{ - if (x10_solidModelData) - return x10_solidModelData->GetBounds(); - return zeus::CAABox::skNullBox; +void CGunWeapon::UnlockTokens() { + x13c_armCharacter.Unlock(); + NWeaponTypes::unlock_tokens(x12c_deps); } -zeus::CAABox CGunWeapon::GetBounds(const zeus::CTransform& xf) const -{ - if (x10_solidModelData) - return x10_solidModelData->GetBounds(xf); - return zeus::CAABox::skNullBox; +void CGunWeapon::Load(CStateManager& mgr, bool subtypeBasePose) { + LockTokens(mgr); + x218_27_subtypeBasePose = subtypeBasePose; + x204_frozenEffect = EFrozenFxType::None; + x1b8_frozenGenerator.reset(); + x104_gunCharacter.Lock(); + x160_xferEffect.Lock(); + for (int i = 0; i < 2; ++i) { + x16c_muzzleEffects[i].Lock(); + x144_weapons[i].Lock(); + } + for (int i = 0; i < 2; ++i) + x188_frozenEffects[i].Lock(); } -bool CGunWeapon::IsChargeAnimOver() const -{ - return !(x218_25_enableCharge && x10_solidModelData->GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body")); +void CGunWeapon::Unload(CStateManager& mgr) { + UnlockTokens(); + x210_loadFlags = 0; + x204_frozenEffect = EFrozenFxType::None; + x10_solidModelData = std::experimental::nullopt; + x60_holoModelData = std::experimental::nullopt; + xb0_suitArmModelData = std::experimental::nullopt; + x100_gunController.reset(); + x1bc_rainSplashGenerator = nullptr; + x1b8_frozenGenerator.reset(); + FreeResPools(); + x104_gunCharacter.Unlock(); + x218_26_loaded = false; } +bool CGunWeapon::IsLoaded() const { return x218_26_loaded; } + +void CGunWeapon::DrawHologram(const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags) const { + if (!x218_26_loaded) + return; + + if (x218_29_drawHologram) { + CModelFlags useFlags = flags; + useFlags.m_extendedShader = EExtendedShader::Flat; + x60_holoModelData->Render(CModelData::EWhichModel::Normal, xf, nullptr, useFlags); + } else { + CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x10_solidModelData->GetScale())); + // CGraphics::DisableAllLights(); + // g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + CSkinnedModel& model = const_cast(*x60_holoModelData->GetAnimationData()->GetModelData()); + model.GetModelInst()->ActivateLights({CLight::BuildLocalAmbient({}, zeus::CColor::skWhite)}); + const_cast(this)->x10_solidModelData->AnimationData()->Render(model, flags, {}, nullptr); + // g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + // CGraphics::DisableAllLights(); + } } + +void CGunWeapon::UpdateMuzzleFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, bool emitting) { + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetGlobalTranslation(pos); + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetGlobalScale(scale); + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->SetParticleEmission(emitting); + x1a4_muzzleGenerators[x208_muzzleEffectIdx]->Update(dt); +} + +void CGunWeapon::ReturnToDefault(CStateManager& mgr) { x100_gunController->ReturnToDefault(mgr, 0.f, false); } + +bool CGunWeapon::PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle) { + switch (state) { + case SamusGun::EAnimationState::ComboFire: + x100_gunController->EnterComboFire(mgr, s32(x200_beamId)); + return true; + default: + return false; + case SamusGun::EAnimationState::Wander: + return true; + } +} + +void CGunWeapon::UnLoadFidget() { x100_gunController->UnLoadFidget(); } + +bool CGunWeapon::IsFidgetLoaded() const { return x100_gunController->IsFidgetLoaded(); } + +void CGunWeapon::AsyncLoadFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 animSet) { + x100_gunController->LoadFidgetAnimAsync(mgr, s32(type), s32(x200_beamId), animSet); +} + +void CGunWeapon::EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2) { + x100_gunController->EnterFidget(mgr, s32(type), s32(x200_beamId), parm2); +} + +CDamageInfo CGunWeapon::GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr) { + CDamageInfo ret(shotParam); + if (g_GameState->GetHardMode()) + ret.MultiplyDamage(g_GameState->GetHardModeWeaponMultiplier()); + return ret; +} + +CDamageInfo CGunWeapon::GetDamageInfo(CStateManager& mgr, EChargeState chargeState, float chargeFactor) const { + const SWeaponInfo& wInfo = GetWeaponInfo(); + if (chargeState == EChargeState::Normal) { + return GetShotDamageInfo(wInfo.x4_normal, mgr); + } else { + SShotParam param = wInfo.x20_charged; + param.damage *= chargeFactor; + param.radiusDamage *= chargeFactor; + param.radius *= chargeFactor; + param.knockback *= chargeFactor; + param.noImmunity = false; + return GetShotDamageInfo(param, mgr); + } +} + +const SWeaponInfo& CGunWeapon::GetWeaponInfo() const { return g_tweakPlayerGun->GetBeamInfo(s32(x200_beamId)); } + +zeus::CAABox CGunWeapon::GetBounds() const { + if (x10_solidModelData) + return x10_solidModelData->GetBounds(); + return zeus::CAABox::skNullBox; +} + +zeus::CAABox CGunWeapon::GetBounds(const zeus::CTransform& xf) const { + if (x10_solidModelData) + return x10_solidModelData->GetBounds(xf); + return zeus::CAABox::skNullBox; +} + +bool CGunWeapon::IsChargeAnimOver() const { + return !(x218_25_enableCharge && x10_solidModelData->GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body")); +} + +} // namespace urde diff --git a/Runtime/Weapon/CGunWeapon.hpp b/Runtime/Weapon/CGunWeapon.hpp index 926a025a5..0752c127b 100644 --- a/Runtime/Weapon/CGunWeapon.hpp +++ b/Runtime/Weapon/CGunWeapon.hpp @@ -14,166 +14,146 @@ #include "CGunMotion.hpp" #include "World/CDamageInfo.hpp" -namespace urde -{ +namespace urde { class CActorLights; struct CModelFlags; class CWeaponDescription; -enum class EChargeState -{ - Normal, - Charged -}; +enum class EChargeState { Normal, Charged }; using SWeaponInfo = DataSpec::SWeaponInfo; using SShotParam = DataSpec::SShotParam; using SChargedShotParam = DataSpec::SChargedShotParam; -class CVelocityInfo -{ - friend class CGunWeapon; - rstl::reserved_vector x0_vel; - rstl::reserved_vector x1c_targetHoming; - rstl::reserved_vector x24_trat; +class CVelocityInfo { + friend class CGunWeapon; + rstl::reserved_vector x0_vel; + rstl::reserved_vector x1c_targetHoming; + rstl::reserved_vector x24_trat; + public: - const zeus::CVector3f& GetVelocity(int i) const { return x0_vel[i]; } - bool GetTargetHoming(int i) const { return x1c_targetHoming[i]; } - void Clear() - { - x0_vel.clear(); - x1c_targetHoming.clear(); - x24_trat.clear(); - } + const zeus::CVector3f& GetVelocity(int i) const { return x0_vel[i]; } + bool GetTargetHoming(int i) const { return x1c_targetHoming[i]; } + void Clear() { + x0_vel.clear(); + x1c_targetHoming.clear(); + x24_trat.clear(); + } }; -class CGunWeapon -{ +class CGunWeapon { public: - enum class ESecondaryFxType - { - None, - Charge, - ToCombo, - CancelCharge - }; - enum class EFrozenFxType - { - None, - Frozen, - Thawed - }; + enum class ESecondaryFxType { None, Charge, ToCombo, CancelCharge }; + enum class EFrozenFxType { None, Frozen, Thawed }; + protected: - static const s32 skShootAnim[2]; - zeus::CVector3f x4_scale; - std::experimental::optional x10_solidModelData; - std::experimental::optional x60_holoModelData; - std::experimental::optional xb0_suitArmModelData; - std::unique_ptr x100_gunController; - TToken x104_gunCharacter; - std::vector x10c_anims; - std::vector x12c_deps; - TToken x13c_armCharacter; - rstl::reserved_vector, 2> x144_weapons; - TCachedToken x160_xferEffect; - rstl::reserved_vector, 2> x16c_muzzleEffects; - rstl::reserved_vector, 2> x188_frozenEffects; - rstl::reserved_vector, 2> x1a4_muzzleGenerators; - std::unique_ptr x1b8_frozenGenerator; - CRainSplashGenerator* x1bc_rainSplashGenerator = nullptr; - EWeaponType x1c0_weaponType; - TUniqueId x1c4_playerId; - EMaterialTypes x1c8_playerMaterial; - ESecondaryFxType x1cc_enabledSecondaryEffect = ESecondaryFxType::None; - CVelocityInfo x1d0_velInfo; - CPlayerState::EBeamId x200_beamId; - EFrozenFxType x204_frozenEffect = EFrozenFxType::None; - u32 x208_muzzleEffectIdx = 0; - u32 x20c_shaderIdx; - // 0x1: load request, 0x2: muzzle fx, 0x4: projectile data, 0x8: anims, 0x10: everything else - u32 x210_loadFlags = 0; - CAssetId x214_ancsId; - union - { - struct - { - bool x218_24 : 1; - bool x218_25_enableCharge : 1; - bool x218_26_loaded : 1; - // Initialize in selected beam's pose, rather than power beam's pose - bool x218_27_subtypeBasePose : 1; - bool x218_28_suitArmLocked : 1; - bool x218_29_drawHologram : 1; - }; - u32 _dummy = 0; + static const s32 skShootAnim[2]; + zeus::CVector3f x4_scale; + std::experimental::optional x10_solidModelData; + std::experimental::optional x60_holoModelData; + std::experimental::optional xb0_suitArmModelData; + std::unique_ptr x100_gunController; + TToken x104_gunCharacter; + std::vector x10c_anims; + std::vector x12c_deps; + TToken x13c_armCharacter; + rstl::reserved_vector, 2> x144_weapons; + TCachedToken x160_xferEffect; + rstl::reserved_vector, 2> x16c_muzzleEffects; + rstl::reserved_vector, 2> x188_frozenEffects; + rstl::reserved_vector, 2> x1a4_muzzleGenerators; + std::unique_ptr x1b8_frozenGenerator; + CRainSplashGenerator* x1bc_rainSplashGenerator = nullptr; + EWeaponType x1c0_weaponType; + TUniqueId x1c4_playerId; + EMaterialTypes x1c8_playerMaterial; + ESecondaryFxType x1cc_enabledSecondaryEffect = ESecondaryFxType::None; + CVelocityInfo x1d0_velInfo; + CPlayerState::EBeamId x200_beamId; + EFrozenFxType x204_frozenEffect = EFrozenFxType::None; + u32 x208_muzzleEffectIdx = 0; + u32 x20c_shaderIdx; + // 0x1: load request, 0x2: muzzle fx, 0x4: projectile data, 0x8: anims, 0x10: everything else + u32 x210_loadFlags = 0; + CAssetId x214_ancsId; + union { + struct { + bool x218_24 : 1; + bool x218_25_enableCharge : 1; + bool x218_26_loaded : 1; + // Initialize in selected beam's pose, rather than power beam's pose + bool x218_27_subtypeBasePose : 1; + bool x218_28_suitArmLocked : 1; + bool x218_29_drawHologram : 1; }; + u32 _dummy = 0; + }; - void AllocResPools(CPlayerState::EBeamId beam); - void FreeResPools(); - void FillTokenVector(const std::vector& tags, std::vector& objects); - void BuildDependencyList(CPlayerState::EBeamId beam); - void LoadSuitArm(CStateManager& mgr); - void LoadGunModels(CStateManager& mgr); - void LoadAnimations(); - bool IsAnimsLoaded() const; - void LoadMuzzleFx(float dt); - void LoadProjectileData(CStateManager& mgr); - void LoadFxIdle(float dt, CStateManager& mgr); - void LockTokens(CStateManager& mgr); - void UnlockTokens(); + void AllocResPools(CPlayerState::EBeamId beam); + void FreeResPools(); + void FillTokenVector(const std::vector& tags, std::vector& objects); + void BuildDependencyList(CPlayerState::EBeamId beam); + void LoadSuitArm(CStateManager& mgr); + void LoadGunModels(CStateManager& mgr); + void LoadAnimations(); + bool IsAnimsLoaded() const; + void LoadMuzzleFx(float dt); + void LoadProjectileData(CStateManager& mgr); + void LoadFxIdle(float dt, CStateManager& mgr); + void LockTokens(CStateManager& mgr); + void UnlockTokens(); - static void PointGenerator(void* ctx, const std::vector>& vn); + static void PointGenerator(void* ctx, const std::vector>& vn); public: - CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, - const zeus::CVector3f& scale); - void AsyncLoadSuitArm(CStateManager& mgr); - virtual void Reset(CStateManager& mgr); - virtual void PlayAnim(NWeaponTypes::EGunAnimType type, bool loop); - virtual void PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - virtual void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - virtual void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); - virtual void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); - virtual void EnableFx(bool enable); - virtual void EnableSecondaryFx(ESecondaryFxType type); - void EnableFrozenEffect(EFrozenFxType type); - void ActivateCharge(bool enable, bool resetEffect); - void Touch(const CStateManager& mgr); - void TouchHolo(const CStateManager& mgr); - virtual void Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, - const CModelFlags& flags, const CActorLights* lights) const; - virtual void DrawMuzzleFx(const CStateManager& mgr) const; - virtual void Update(float dt, CStateManager& mgr); - virtual void Load(CStateManager& mgr, bool subtypeBasePose); - virtual void Unload(CStateManager& mgr); - virtual bool IsLoaded() const; - void DrawHologram(const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags) const; - void UpdateMuzzleFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, bool emitting); - const CVelocityInfo& GetVelocityInfo() const { return x1d0_velInfo; } - void SetRainSplashGenerator(CRainSplashGenerator* g) { x1bc_rainSplashGenerator = g; } - CElementGen* GetChargeMuzzleFx() const { return x1a4_muzzleGenerators[1].get(); } - const TToken& GetComboXferDescr() const { return x160_xferEffect; } - void ReturnToDefault(CStateManager& mgr); - bool PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle); - void UnLoadFidget(); - bool IsFidgetLoaded() const; - void AsyncLoadFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 animSet); - void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2); - bool HasSolidModelData() const { return x10_solidModelData.operator bool(); } - CModelData& GetSolidModelData() { return *x10_solidModelData; } - const SWeaponInfo& GetWeaponInfo() const; - CDamageInfo GetDamageInfo(CStateManager& mgr, EChargeState chargeState, float chargeFactor) const; - EWeaponType GetWeaponType() const { return x1c0_weaponType; } - zeus::CAABox GetBounds() const; - zeus::CAABox GetBounds(const zeus::CTransform& xf) const; - bool ComboFireOver() const { return x100_gunController->IsComboOver(); } - bool IsChargeAnimOver() const; - void SetDrawHologram(bool d) { x218_29_drawHologram = d; } - void EnableCharge(bool c) { x218_25_enableCharge = c; } + CGunWeapon(CAssetId ancsId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale); + void AsyncLoadSuitArm(CStateManager& mgr); + virtual void Reset(CStateManager& mgr); + virtual void PlayAnim(NWeaponTypes::EGunAnimType type, bool loop); + virtual void PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + virtual void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + virtual void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); + virtual void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, CStateManager& mgr, + TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); + virtual void EnableFx(bool enable); + virtual void EnableSecondaryFx(ESecondaryFxType type); + void EnableFrozenEffect(EFrozenFxType type); + void ActivateCharge(bool enable, bool resetEffect); + void Touch(const CStateManager& mgr); + void TouchHolo(const CStateManager& mgr); + virtual void Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags, + const CActorLights* lights) const; + virtual void DrawMuzzleFx(const CStateManager& mgr) const; + virtual void Update(float dt, CStateManager& mgr); + virtual void Load(CStateManager& mgr, bool subtypeBasePose); + virtual void Unload(CStateManager& mgr); + virtual bool IsLoaded() const; + void DrawHologram(const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags) const; + void UpdateMuzzleFx(float dt, const zeus::CVector3f& scale, const zeus::CVector3f& pos, bool emitting); + const CVelocityInfo& GetVelocityInfo() const { return x1d0_velInfo; } + void SetRainSplashGenerator(CRainSplashGenerator* g) { x1bc_rainSplashGenerator = g; } + CElementGen* GetChargeMuzzleFx() const { return x1a4_muzzleGenerators[1].get(); } + const TToken& GetComboXferDescr() const { return x160_xferEffect; } + void ReturnToDefault(CStateManager& mgr); + bool PlayPasAnim(SamusGun::EAnimationState state, CStateManager& mgr, float angle); + void UnLoadFidget(); + bool IsFidgetLoaded() const; + void AsyncLoadFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 animSet); + void EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 parm2); + bool HasSolidModelData() const { return x10_solidModelData.operator bool(); } + CModelData& GetSolidModelData() { return *x10_solidModelData; } + const SWeaponInfo& GetWeaponInfo() const; + CDamageInfo GetDamageInfo(CStateManager& mgr, EChargeState chargeState, float chargeFactor) const; + EWeaponType GetWeaponType() const { return x1c0_weaponType; } + zeus::CAABox GetBounds() const; + zeus::CAABox GetBounds(const zeus::CTransform& xf) const; + bool ComboFireOver() const { return x100_gunController->IsComboOver(); } + bool IsChargeAnimOver() const; + void SetDrawHologram(bool d) { x218_29_drawHologram = d; } + void EnableCharge(bool c) { x218_25_enableCharge = c; } - static CDamageInfo GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr); + static CDamageInfo GetShotDamageInfo(const SShotParam& shotParam, CStateManager& mgr); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CIceBeam.cpp b/Runtime/Weapon/CIceBeam.cpp index 2a590777b..acc662340 100644 --- a/Runtime/Weapon/CIceBeam.cpp +++ b/Runtime/Weapon/CIceBeam.cpp @@ -2,168 +2,141 @@ #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" -namespace urde -{ +namespace urde { -CIceBeam::CIceBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale) -: CGunWeapon(characterId, type, playerId, playerMaterial, scale) -{ - x21c_iceSmoke = g_SimplePool->GetObj("IceSmoke"); - x228_ice2nd1 = g_SimplePool->GetObj("Ice2nd_1"); - x234_ice2nd2 = g_SimplePool->GetObj("Ice2nd_2"); - x248_24_loaded = false; - x248_25_inEndFx = false; +CIceBeam::CIceBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale) +: CGunWeapon(characterId, type, playerId, playerMaterial, scale) { + x21c_iceSmoke = g_SimplePool->GetObj("IceSmoke"); + x228_ice2nd1 = g_SimplePool->GetObj("Ice2nd_1"); + x234_ice2nd2 = g_SimplePool->GetObj("Ice2nd_2"); + x248_24_loaded = false; + x248_25_inEndFx = false; } -void CIceBeam::PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - // Empty +void CIceBeam::PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + // Empty } -void CIceBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - bool subtractBlend = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot; - if (subtractBlend) - CElementGen::SetSubtractBlend(true); - if (x240_smokeGen) - x240_smokeGen->Render(); - if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x244_chargeFx) - x244_chargeFx->Render(); - CGunWeapon::PostRenderGunFx(mgr, xf); - if (subtractBlend) - CElementGen::SetSubtractBlend(false); +void CIceBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + bool subtractBlend = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot; + if (subtractBlend) + CElementGen::SetSubtractBlend(true); + if (x240_smokeGen) + x240_smokeGen->Render(); + if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x244_chargeFx) + x244_chargeFx->Render(); + CGunWeapon::PostRenderGunFx(mgr, xf); + if (subtractBlend) + CElementGen::SetSubtractBlend(false); } -void CIceBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x240_smokeGen) - { - zeus::CTransform beamLoc = x10_solidModelData->GetScaledLocatorTransform("LBEAM"); - x240_smokeGen->SetTranslation(beamLoc.origin); - x240_smokeGen->SetOrientation(beamLoc.getRotation()); - x240_smokeGen->Update(dt); +void CIceBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) { + if (x240_smokeGen) { + zeus::CTransform beamLoc = x10_solidModelData->GetScaledLocatorTransform("LBEAM"); + x240_smokeGen->SetTranslation(beamLoc.origin); + x240_smokeGen->SetOrientation(beamLoc.getRotation()); + x240_smokeGen->Update(dt); + } + + if (x244_chargeFx) { + if (x248_25_inEndFx && x244_chargeFx->IsSystemDeletable()) { + x1cc_enabledSecondaryEffect = ESecondaryFxType::None; + x244_chargeFx.reset(); } - - if (x244_chargeFx) - { - if (x248_25_inEndFx && x244_chargeFx->IsSystemDeletable()) - { - x1cc_enabledSecondaryEffect = ESecondaryFxType::None; - x244_chargeFx.reset(); - } - if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None) - { - if (x248_25_inEndFx) - { - x244_chargeFx->SetTranslation(xf.origin); - x244_chargeFx->SetOrientation(xf.getRotation()); - } - else - { - x244_chargeFx->SetGlobalOrientAndTrans(xf); - } - x244_chargeFx->Update(dt); - } + if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None) { + if (x248_25_inEndFx) { + x244_chargeFx->SetTranslation(xf.origin); + x244_chargeFx->SetOrientation(xf.getRotation()); + } else { + x244_chargeFx->SetGlobalOrientAndTrans(xf); + } + x244_chargeFx->Update(dt); } + } - CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); + CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); } -static const u16 kSoundId[] = { SFXwpn_fire_ice_normal, SFXwpn_fire_ice_charged }; +static const u16 kSoundId[] = {SFXwpn_fire_ice_normal, SFXwpn_fire_ice_charged}; -void CIceBeam::Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) -{ - CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); - NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); +void CIceBeam::Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, CStateManager& mgr, + TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) { + CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); + NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); } -void CIceBeam::EnableFx(bool enable) -{ - if (x240_smokeGen) - x240_smokeGen->SetParticleEmission(enable); +void CIceBeam::EnableFx(bool enable) { + if (x240_smokeGen) + x240_smokeGen->SetParticleEmission(enable); } -void CIceBeam::EnableSecondaryFx(ESecondaryFxType type) -{ - switch (type) - { - case ESecondaryFxType::CancelCharge: +void CIceBeam::EnableSecondaryFx(ESecondaryFxType type) { + switch (type) { + case ESecondaryFxType::CancelCharge: + case ESecondaryFxType::None: + if (x1cc_enabledSecondaryEffect == ESecondaryFxType::None) + break; + default: + switch (type) { case ESecondaryFxType::None: - if (x1cc_enabledSecondaryEffect == ESecondaryFxType::None) - break; - default: - switch (type) - { - case ESecondaryFxType::None: - case ESecondaryFxType::ToCombo: - case ESecondaryFxType::CancelCharge: - if (!x248_25_inEndFx) - { - x244_chargeFx = std::make_unique(x234_ice2nd2); - x244_chargeFx->SetGlobalScale(x4_scale); - x248_25_inEndFx = true; - x1cc_enabledSecondaryEffect = ESecondaryFxType::CancelCharge; - } - break; - case ESecondaryFxType::Charge: - x244_chargeFx = std::make_unique(x228_ice2nd1); - x244_chargeFx->SetGlobalScale(x4_scale); - x248_25_inEndFx = false; - x1cc_enabledSecondaryEffect = type; - break; - } - break; + case ESecondaryFxType::ToCombo: + case ESecondaryFxType::CancelCharge: + if (!x248_25_inEndFx) { + x244_chargeFx = std::make_unique(x234_ice2nd2); + x244_chargeFx->SetGlobalScale(x4_scale); + x248_25_inEndFx = true; + x1cc_enabledSecondaryEffect = ESecondaryFxType::CancelCharge; + } + break; + case ESecondaryFxType::Charge: + x244_chargeFx = std::make_unique(x228_ice2nd1); + x244_chargeFx->SetGlobalScale(x4_scale); + x248_25_inEndFx = false; + x1cc_enabledSecondaryEffect = type; + break; } + break; + } } -void CIceBeam::Update(float dt, CStateManager& mgr) -{ - CGunWeapon::Update(dt, mgr); +void CIceBeam::Update(float dt, CStateManager& mgr) { + CGunWeapon::Update(dt, mgr); - if (!x248_24_loaded) - { - x248_24_loaded = x21c_iceSmoke.IsLoaded() && x228_ice2nd1.IsLoaded() && x234_ice2nd2.IsLoaded(); - if (x248_24_loaded) - { - x240_smokeGen = std::make_unique(x21c_iceSmoke); - x240_smokeGen->SetGlobalScale(x4_scale); - x240_smokeGen->SetParticleEmission(false); - } + if (!x248_24_loaded) { + x248_24_loaded = x21c_iceSmoke.IsLoaded() && x228_ice2nd1.IsLoaded() && x234_ice2nd2.IsLoaded(); + if (x248_24_loaded) { + x240_smokeGen = std::make_unique(x21c_iceSmoke); + x240_smokeGen->SetGlobalScale(x4_scale); + x240_smokeGen->SetParticleEmission(false); } + } } -void CIceBeam::Load(CStateManager& mgr, bool subtypeBasePose) -{ - CGunWeapon::Load(mgr, subtypeBasePose); - x21c_iceSmoke.Lock(); - x228_ice2nd1.Lock(); - x234_ice2nd2.Lock(); - x248_25_inEndFx = false; +void CIceBeam::Load(CStateManager& mgr, bool subtypeBasePose) { + CGunWeapon::Load(mgr, subtypeBasePose); + x21c_iceSmoke.Lock(); + x228_ice2nd1.Lock(); + x234_ice2nd2.Lock(); + x248_25_inEndFx = false; } -void CIceBeam::ReInitVariables() -{ - x240_smokeGen.reset(); - x244_chargeFx.reset(); - x248_24_loaded = false; - x248_25_inEndFx = false; - x1cc_enabledSecondaryEffect = ESecondaryFxType::None; +void CIceBeam::ReInitVariables() { + x240_smokeGen.reset(); + x244_chargeFx.reset(); + x248_24_loaded = false; + x248_25_inEndFx = false; + x1cc_enabledSecondaryEffect = ESecondaryFxType::None; } -void CIceBeam::Unload(CStateManager& mgr) -{ - CGunWeapon::Unload(mgr); - x234_ice2nd2.Unlock(); - x228_ice2nd1.Unlock(); - x21c_iceSmoke.Unlock(); - ReInitVariables(); +void CIceBeam::Unload(CStateManager& mgr) { + CGunWeapon::Unload(mgr); + x234_ice2nd2.Unlock(); + x228_ice2nd1.Unlock(); + x21c_iceSmoke.Unlock(); + ReInitVariables(); } -bool CIceBeam::IsLoaded() const -{ - return CGunWeapon::IsLoaded() && x248_24_loaded; -} +bool CIceBeam::IsLoaded() const { return CGunWeapon::IsLoaded() && x248_24_loaded; } -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/Weapon/CIceBeam.hpp b/Runtime/Weapon/CIceBeam.hpp index 83d65889e..cb6294e85 100644 --- a/Runtime/Weapon/CIceBeam.hpp +++ b/Runtime/Weapon/CIceBeam.hpp @@ -2,35 +2,33 @@ #include "CGunWeapon.hpp" -namespace urde -{ +namespace urde { + +class CIceBeam final : public CGunWeapon { + TCachedToken x21c_iceSmoke; + TCachedToken x228_ice2nd1; + TCachedToken x234_ice2nd2; + std::unique_ptr x240_smokeGen; + std::unique_ptr x244_chargeFx; + bool x248_24_loaded : 1; + bool x248_25_inEndFx : 1; + void ReInitVariables(); -class CIceBeam final : public CGunWeapon -{ - TCachedToken x21c_iceSmoke; - TCachedToken x228_ice2nd1; - TCachedToken x234_ice2nd2; - std::unique_ptr x240_smokeGen; - std::unique_ptr x244_chargeFx; - bool x248_24_loaded : 1; - bool x248_25_inEndFx : 1; - void ReInitVariables(); public: - CIceBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale); + CIceBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale); - void PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); - void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); - void EnableFx(bool enable); - void EnableSecondaryFx(ESecondaryFxType type); - void Update(float dt, CStateManager& mgr); - void Load(CStateManager& mgr, bool subtypeBasePose); - void Unload(CStateManager& mgr); - bool IsLoaded() const; + void PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); + void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, CStateManager& mgr, + TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); + void EnableFx(bool enable); + void EnableSecondaryFx(ESecondaryFxType type); + void Update(float dt, CStateManager& mgr); + void Load(CStateManager& mgr, bool subtypeBasePose); + void Unload(CStateManager& mgr); + bool IsLoaded() const; }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CNewFlameThrower.cpp b/Runtime/Weapon/CNewFlameThrower.cpp index e21fb148e..3ce0a8505 100644 --- a/Runtime/Weapon/CNewFlameThrower.cpp +++ b/Runtime/Weapon/CNewFlameThrower.cpp @@ -4,105 +4,91 @@ #include "CStateManager.hpp" #include "World/CGameLight.hpp" -namespace urde -{ +namespace urde { CNewFlameThrower::CNewFlameThrower(const TToken& desc, std::string_view name, EWeaponType wType, const CAssetId resInfo[8], const zeus::CTransform& xf, EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, EProjectileAttrib attribs) - : CGameProjectile(false, desc, name, wType, xf, matType, dInfo, uid, aid, owner, kInvalidUniqueId, attribs, false, - zeus::CVector3f::skOne, {}, -1, false), - x304_mainFire(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[0]})), - x310_mainSmoke(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[1]})), - x31c_secondarySmoke(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[4]})), - x328_secondaryFire(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[5]})), - x334_secondarySparks(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[6]})), - x340_swooshCenter(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), resInfo[2]})), - x34c_swooshFire(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), resInfo[3]})) -{ - x304_mainFire.GetObj(); - x310_mainSmoke.GetObj(); - x31c_secondarySmoke.GetObj(); - x328_secondaryFire.GetObj(); - x334_secondarySparks.GetObj(); - x340_swooshCenter.GetObj(); - x34c_swooshFire.GetObj(); - x37c_24_renderAuxEffects = false; - x37c_25_firing = false; - x37c_26_ = false; - x37c_27_ = true; - x37c_28_ = false; - x380_.resize(3); +: CGameProjectile(false, desc, name, wType, xf, matType, dInfo, uid, aid, owner, kInvalidUniqueId, attribs, false, + zeus::CVector3f::skOne, {}, -1, false) +, x304_mainFire(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[0]})) +, x310_mainSmoke(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[1]})) +, x31c_secondarySmoke(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[4]})) +, x328_secondaryFire(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[5]})) +, x334_secondarySparks(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), resInfo[6]})) +, x340_swooshCenter(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), resInfo[2]})) +, x34c_swooshFire(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), resInfo[3]})) { + x304_mainFire.GetObj(); + x310_mainSmoke.GetObj(); + x31c_secondarySmoke.GetObj(); + x328_secondaryFire.GetObj(); + x334_secondarySparks.GetObj(); + x340_swooshCenter.GetObj(); + x34c_swooshFire.GetObj(); + x37c_24_renderAuxEffects = false; + x37c_25_firing = false; + x37c_26_ = false; + x37c_27_ = true; + x37c_28_ = false; + x380_.resize(3); } -void CNewFlameThrower::DeleteLightObjects(CStateManager& mgr) -{ - for (TUniqueId id : x3b8_lightIds) - mgr.FreeScriptObject(id); - x3b8_lightIds.clear(); +void CNewFlameThrower::DeleteLightObjects(CStateManager& mgr) { + for (TUniqueId id : x3b8_lightIds) + mgr.FreeScriptObject(id); + x3b8_lightIds.clear(); } -void CNewFlameThrower::CreateLightObjects(CStateManager& mgr) -{ - DeleteLightObjects(mgr); - for (int i=0 ; i<4 ; ++i) - { - TUniqueId uid = mgr.AllocateUniqueId(); - CLight lObj = x358_mainFireGen->GetLight(); - CGameLight* light = new CGameLight(uid, GetAreaId(), false, "FlamethrowerLight", zeus::CTransform::Identity(), - x8_uid, lObj, u32(reinterpret_cast(this) + (i & 0x1)), 0, 0.f); - mgr.AddObject(light); - x3b8_lightIds.push_back(uid); - } +void CNewFlameThrower::CreateLightObjects(CStateManager& mgr) { + DeleteLightObjects(mgr); + for (int i = 0; i < 4; ++i) { + TUniqueId uid = mgr.AllocateUniqueId(); + CLight lObj = x358_mainFireGen->GetLight(); + CGameLight* light = new CGameLight(uid, GetAreaId(), false, "FlamethrowerLight", zeus::CTransform::Identity(), + x8_uid, lObj, u32(reinterpret_cast(this) + (i & 0x1)), 0, 0.f); + mgr.AddObject(light); + x3b8_lightIds.push_back(uid); + } } -void CNewFlameThrower::EnableFx(CStateManager& mgr) -{ - DeleteProjectileLight(mgr); - x358_mainFireGen = std::make_unique(x304_mainFire); - x35c_mainSmokeGen = std::make_unique(x310_mainSmoke); - x360_secondarySmokeGen = std::make_unique(x31c_secondarySmoke); - x364_secondaryFireGen = std::make_unique(x328_secondaryFire); - x368_secondarySparksGen = std::make_unique(x334_secondarySparks); - x36c_swooshCenterGen = std::make_unique(x340_swooshCenter, 0); - x36c_swooshCenterGen->SetRenderGaps(true); - x370_swooshFireGen = std::make_unique(x34c_swooshFire, 0); - x370_swooshFireGen->SetRenderGaps(true); - if (x358_mainFireGen && x358_mainFireGen->SystemHasLight() && x3b8_lightIds.empty()) - CreateLightObjects(mgr); +void CNewFlameThrower::EnableFx(CStateManager& mgr) { + DeleteProjectileLight(mgr); + x358_mainFireGen = std::make_unique(x304_mainFire); + x35c_mainSmokeGen = std::make_unique(x310_mainSmoke); + x360_secondarySmokeGen = std::make_unique(x31c_secondarySmoke); + x364_secondaryFireGen = std::make_unique(x328_secondaryFire); + x368_secondarySparksGen = std::make_unique(x334_secondarySparks); + x36c_swooshCenterGen = std::make_unique(x340_swooshCenter, 0); + x36c_swooshCenterGen->SetRenderGaps(true); + x370_swooshFireGen = std::make_unique(x34c_swooshFire, 0); + x370_swooshFireGen->SetRenderGaps(true); + if (x358_mainFireGen && x358_mainFireGen->SystemHasLight() && x3b8_lightIds.empty()) + CreateLightObjects(mgr); } -void CNewFlameThrower::StartFiring(const zeus::CTransform& xf, CStateManager& mgr) -{ - SetActive(true); - x37c_25_firing = true; - x37c_24_renderAuxEffects = true; - x374_ = 1; - EnableFx(mgr); +void CNewFlameThrower::StartFiring(const zeus::CTransform& xf, CStateManager& mgr) { + SetActive(true); + x37c_25_firing = true; + x37c_24_renderAuxEffects = true; + x374_ = 1; + EnableFx(mgr); } -bool CNewFlameThrower::AreEffectsFinished() const -{ - if (x358_mainFireGen && x358_mainFireGen->GetParticleCount() != 0) - return false; - if (x35c_mainSmokeGen && x35c_mainSmokeGen->GetParticleCount() != 0) - return false; - if (x360_secondarySmokeGen && x360_secondarySmokeGen->GetParticleCount() != 0) - return false; - if (x364_secondaryFireGen && x364_secondaryFireGen->GetParticleCount() != 0) - return false; - return !(x368_secondarySparksGen && x368_secondarySparksGen->GetParticleCount() != 0); +bool CNewFlameThrower::AreEffectsFinished() const { + if (x358_mainFireGen && x358_mainFireGen->GetParticleCount() != 0) + return false; + if (x35c_mainSmokeGen && x35c_mainSmokeGen->GetParticleCount() != 0) + return false; + if (x360_secondarySmokeGen && x360_secondarySmokeGen->GetParticleCount() != 0) + return false; + if (x364_secondaryFireGen && x364_secondaryFireGen->GetParticleCount() != 0) + return false; + return !(x368_secondarySparksGen && x368_secondarySparksGen->GetParticleCount() != 0); } -void CNewFlameThrower::UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr) -{ +void CNewFlameThrower::UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr) {} -} +void CNewFlameThrower::Reset(CStateManager& mgr, bool deactivate) {} -void CNewFlameThrower::Reset(CStateManager& mgr, bool deactivate) -{ - -} - -} +} // namespace urde diff --git a/Runtime/Weapon/CNewFlameThrower.hpp b/Runtime/Weapon/CNewFlameThrower.hpp index 53e57bf66..f4c8e8fbb 100644 --- a/Runtime/Weapon/CNewFlameThrower.hpp +++ b/Runtime/Weapon/CNewFlameThrower.hpp @@ -2,62 +2,60 @@ #include "CGameProjectile.hpp" -namespace urde -{ +namespace urde { + +class CNewFlameThrower : public CGameProjectile { + CRandom16 x2e8_rand = {99}; + float x2ec_ = 0.f; + float x2f0_ = 0.f; + bool x300_ = false; + TCachedToken x304_mainFire; + TCachedToken x310_mainSmoke; + TCachedToken x31c_secondarySmoke; + TCachedToken x328_secondaryFire; + TCachedToken x334_secondarySparks; + TCachedToken x340_swooshCenter; + TCachedToken x34c_swooshFire; + std::unique_ptr x358_mainFireGen; + std::unique_ptr x35c_mainSmokeGen; + std::unique_ptr x360_secondarySmokeGen; + std::unique_ptr x364_secondaryFireGen; + std::unique_ptr x368_secondarySparksGen; + std::unique_ptr x36c_swooshCenterGen; + std::unique_ptr x370_swooshFireGen; + u32 x374_ = 0; + TAreaId x378_ = kInvalidAreaId; + bool x37c_24_renderAuxEffects : 1; + bool x37c_25_firing : 1; + bool x37c_26_ : 1; + bool x37c_27_ : 1; + bool x37c_28_ : 1; + rstl::reserved_vector>, 3> x380_; + u32 x3b4_ = 0; + rstl::reserved_vector x3b8_lightIds; + void DeleteLightObjects(CStateManager& mgr); + void CreateLightObjects(CStateManager& mgr); + void EnableFx(CStateManager& mgr); -class CNewFlameThrower : public CGameProjectile -{ - CRandom16 x2e8_rand = {99}; - float x2ec_ = 0.f; - float x2f0_ = 0.f; - bool x300_ = false; - TCachedToken x304_mainFire; - TCachedToken x310_mainSmoke; - TCachedToken x31c_secondarySmoke; - TCachedToken x328_secondaryFire; - TCachedToken x334_secondarySparks; - TCachedToken x340_swooshCenter; - TCachedToken x34c_swooshFire; - std::unique_ptr x358_mainFireGen; - std::unique_ptr x35c_mainSmokeGen; - std::unique_ptr x360_secondarySmokeGen; - std::unique_ptr x364_secondaryFireGen; - std::unique_ptr x368_secondarySparksGen; - std::unique_ptr x36c_swooshCenterGen; - std::unique_ptr x370_swooshFireGen; - u32 x374_ = 0; - TAreaId x378_ = kInvalidAreaId; - bool x37c_24_renderAuxEffects : 1; - bool x37c_25_firing : 1; - bool x37c_26_ : 1; - bool x37c_27_ : 1; - bool x37c_28_ : 1; - rstl::reserved_vector>, 3> x380_; - u32 x3b4_ = 0; - rstl::reserved_vector x3b8_lightIds; - void DeleteLightObjects(CStateManager& mgr); - void CreateLightObjects(CStateManager& mgr); - void EnableFx(CStateManager& mgr); public: - // Resinfo: - // NFTMainFire - // NFTMainSmoke - // NFTSwooshCenter - // NFTSwooshFire - // NFTSecondarySmoke - // NFTSecondaryFire - // NFTSecondarySparks - // - CNewFlameThrower(const TToken& desc, std::string_view name, EWeaponType wType, - const CAssetId resInfo[8], const zeus::CTransform& xf, EMaterialTypes matType, - const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, EProjectileAttrib attribs); - void StartFiring(const zeus::CTransform& xf, CStateManager& mgr); - bool CanRenderAuxEffects() const { return x37c_24_renderAuxEffects; } - bool IsFiring() const { return x37c_25_firing; } - bool AreEffectsFinished() const; - void UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr); - void Reset(CStateManager& mgr, bool deactivate); + // Resinfo: + // NFTMainFire + // NFTMainSmoke + // NFTSwooshCenter + // NFTSwooshFire + // NFTSecondarySmoke + // NFTSecondaryFire + // NFTSecondarySparks + // + CNewFlameThrower(const TToken& desc, std::string_view name, EWeaponType wType, + const CAssetId resInfo[8], const zeus::CTransform& xf, EMaterialTypes matType, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, EProjectileAttrib attribs); + void StartFiring(const zeus::CTransform& xf, CStateManager& mgr); + bool CanRenderAuxEffects() const { return x37c_24_renderAuxEffects; } + bool IsFiring() const { return x37c_25_firing; } + bool AreEffectsFinished() const; + void UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr); + void Reset(CStateManager& mgr, bool deactivate); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CPhazonBeam.cpp b/Runtime/Weapon/CPhazonBeam.cpp index 12d259531..373a082bd 100644 --- a/Runtime/Weapon/CPhazonBeam.cpp +++ b/Runtime/Weapon/CPhazonBeam.cpp @@ -6,260 +6,216 @@ #include "CProjectileWeapon.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { -CPhazonBeam::CPhazonBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale) -: CGunWeapon(characterId, type, playerId, playerMaterial, scale), - x238_aaBoxScale(zeus::CVector3f(-0.14664599f, 0.f, -0.14909725f) * scale.y(), - zeus::CVector3f(0.14664599f, 0.64619601f, 0.14909725f) * scale.y()), - x250_aaBoxTranslate(zeus::CVector3f(-0.0625f, 0.f, -0.09375f) * scale.y(), - zeus::CVector3f(0.0625f, -0.25f, 0.09375f) * scale.y()) -{ - x21c_phazonVeins = g_SimplePool->GetObj("PhazonVeins"); - x228_phazon2nd1 = g_SimplePool->GetObj("Phazon2nd_1"); - x274_24_loaded = false; - x274_25_clipWipeActive = true; - x274_26_veinsAlphaActive = false; - x274_27_phazonVeinsIdx = false; - m_aaboxShaderScale.setAABB(x238_aaBoxScale); - m_aaboxShaderTranslate.setAABB(x250_aaBoxTranslate); +CPhazonBeam::CPhazonBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale) +: CGunWeapon(characterId, type, playerId, playerMaterial, scale) +, x238_aaBoxScale(zeus::CVector3f(-0.14664599f, 0.f, -0.14909725f) * scale.y(), + zeus::CVector3f(0.14664599f, 0.64619601f, 0.14909725f) * scale.y()) +, x250_aaBoxTranslate(zeus::CVector3f(-0.0625f, 0.f, -0.09375f) * scale.y(), + zeus::CVector3f(0.0625f, -0.25f, 0.09375f) * scale.y()) { + x21c_phazonVeins = g_SimplePool->GetObj("PhazonVeins"); + x228_phazon2nd1 = g_SimplePool->GetObj("Phazon2nd_1"); + x274_24_loaded = false; + x274_25_clipWipeActive = true; + x274_26_veinsAlphaActive = false; + x274_27_phazonVeinsIdx = false; + m_aaboxShaderScale.setAABB(x238_aaBoxScale); + m_aaboxShaderTranslate.setAABB(x250_aaBoxTranslate); } -void CPhazonBeam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - TAreaId aid = mgr.GetPlayer().GetAreaIdAlways(); - if (msg == EScriptObjectMessage::Deleted && aid != kInvalidAreaId) - mgr.WorldNC()->GetArea(aid)->SetWeaponWorldLighting(4.f, 1.f); +void CPhazonBeam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + TAreaId aid = mgr.GetPlayer().GetAreaIdAlways(); + if (msg == EScriptObjectMessage::Deleted && aid != kInvalidAreaId) + mgr.WorldNC()->GetArea(aid)->SetWeaponWorldLighting(4.f, 1.f); } -void CPhazonBeam::StopBeam(CStateManager& mgr, bool b1) -{ - if (x234_chargeFxGen) - x234_chargeFxGen->SetParticleEmission(false); +void CPhazonBeam::StopBeam(CStateManager& mgr, bool b1) { + if (x234_chargeFxGen) + x234_chargeFxGen->SetParticleEmission(false); } -void CPhazonBeam::UpdateBeam(float dt, const zeus::CTransform& targetXf, - const zeus::CVector3f& localBeamPos, CStateManager& mgr) -{ - if (x234_chargeFxGen) - x234_chargeFxGen->SetParticleEmission(IsFiring()); - CGunWeapon::UpdateMuzzleFx(dt, x4_scale, localBeamPos, IsFiring()); +void CPhazonBeam::UpdateBeam(float dt, const zeus::CTransform& targetXf, const zeus::CVector3f& localBeamPos, + CStateManager& mgr) { + if (x234_chargeFxGen) + x234_chargeFxGen->SetParticleEmission(IsFiring()); + CGunWeapon::UpdateMuzzleFx(dt, x4_scale, localBeamPos, IsFiring()); } -void CPhazonBeam::CreateBeam(CStateManager& mgr) -{ - x234_chargeFxGen = std::make_unique(x228_phazon2nd1); - if (x234_chargeFxGen) - { - x234_chargeFxGen->SetGlobalScale(x4_scale); - x234_chargeFxGen->SetParticleEmission(false); - } +void CPhazonBeam::CreateBeam(CStateManager& mgr) { + x234_chargeFxGen = std::make_unique(x228_phazon2nd1); + if (x234_chargeFxGen) { + x234_chargeFxGen->SetGlobalScale(x4_scale); + x234_chargeFxGen->SetParticleEmission(false); + } } -void CPhazonBeam::PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (IsFiring()) - { - zeus::CTransform backupView = CGraphics::g_ViewMatrix; - CGraphics::SetViewPointMatrix(xf.inverse() * backupView); - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - CGunWeapon::DrawMuzzleFx(mgr); - CGraphics::SetViewPointMatrix(backupView); - } +void CPhazonBeam::PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + if (IsFiring()) { + zeus::CTransform backupView = CGraphics::g_ViewMatrix; + CGraphics::SetViewPointMatrix(xf.inverse() * backupView); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + CGunWeapon::DrawMuzzleFx(mgr); + CGraphics::SetViewPointMatrix(backupView); + } } -void CPhazonBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x234_chargeFxGen) - x234_chargeFxGen->Render(); - CGunWeapon::PostRenderGunFx(mgr, xf); +void CPhazonBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + if (x234_chargeFxGen) + x234_chargeFxGen->Render(); + CGunWeapon::PostRenderGunFx(mgr, xf); } -void CPhazonBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x234_chargeFxGen) - { - x234_chargeFxGen->SetGlobalOrientAndTrans(xf); - x234_chargeFxGen->Update(dt); - } +void CPhazonBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) { + if (x234_chargeFxGen) { + x234_chargeFxGen->SetGlobalOrientAndTrans(xf); + x234_chargeFxGen->Update(dt); + } - CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); + CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); } -static const u16 kSoundId[] = { SFXwpn_fire_phazon_normal, SFXwpn_fire_power_charged }; +static const u16 kSoundId[] = {SFXwpn_fire_phazon_normal, SFXwpn_fire_power_charged}; void CPhazonBeam::Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) -{ - if (chargeState == EChargeState::Normal) - { - ActivateCharge(false, false); - int count = x278_fireTime > 1.f / 3.f ? 5 : 2; - int seedOffset = 0; - for (int i=0 ; i 1.f / 3.f ? 5 : 2; + int seedOffset = 0; + for (int i = 0; i < count; ++i, seedOffset += 1000) { + CProjectileWeapon::SetGlobalSeed(u16(mgr.GetUpdateFrameIndex() + seedOffset)); + CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); + CProjectileWeapon::SetGlobalSeed(u16(mgr.GetUpdateFrameIndex())); } + x278_fireTime = 0.f; + } else { + CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); + } + + NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); +} + +void CPhazonBeam::Update(float dt, CStateManager& mgr) { + CGunWeapon::Update(dt, mgr); + x278_fireTime += dt; + TAreaId aid = mgr.GetPlayer().GetAreaIdAlways(); + if (aid != kInvalidAreaId) { + CGameArea* area = mgr.WorldNC()->GetArea(aid); + if (x278_fireTime > 1.f / 6.f) + area->SetWeaponWorldLighting(4.f, 1.f); else - { - CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); + area->SetWeaponWorldLighting(4.f, 0.9f); + } + + if (!IsLoaded()) { + if (CGunWeapon::IsLoaded() && !x274_24_loaded) { + x274_24_loaded = x228_phazon2nd1.IsLoaded() && x21c_phazonVeins.IsLoaded(); + if (x274_24_loaded) { + CreateBeam(mgr); + x224_phazonVeinsData = std::make_unique(CStaticRes( + NWeaponTypes::get_asset_id_from_name(x274_27_phazonVeinsIdx ? "PhazonVeins_2" : "PhazonVeins"), x4_scale)); + x21c_phazonVeins.Unlock(); + x274_25_clipWipeActive = true; + } } + } - NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); -} - -void CPhazonBeam::Update(float dt, CStateManager& mgr) -{ - CGunWeapon::Update(dt, mgr); - x278_fireTime += dt; - TAreaId aid = mgr.GetPlayer().GetAreaIdAlways(); - if (aid != kInvalidAreaId) - { - CGameArea* area = mgr.WorldNC()->GetArea(aid); - if (x278_fireTime > 1.f / 6.f) - area->SetWeaponWorldLighting(4.f, 1.f); - else - area->SetWeaponWorldLighting(4.f, 0.9f); + if (x274_25_clipWipeActive) { + x268_clipWipeScale += 0.75f * dt; + if (x268_clipWipeScale > 1.f) + x268_clipWipeScale = 1.f; + if (x268_clipWipeScale > 0.4f) { + if (x26c_clipWipeTranslate < 0.5f) + x26c_clipWipeTranslate += 0.75f * dt; + else + x274_25_clipWipeActive = false; } + } else if (x274_26_veinsAlphaActive) { + x270_indirectAlpha = x10_solidModelData->GetLocatorTransform("phazonScale_LCTR_SDK").origin.y(); + } +} - if (!IsLoaded()) - { - if (CGunWeapon::IsLoaded() && !x274_24_loaded) - { - x274_24_loaded = x228_phazon2nd1.IsLoaded() && x21c_phazonVeins.IsLoaded(); - if (x274_24_loaded) - { - CreateBeam(mgr); - x224_phazonVeinsData = std::make_unique( - CStaticRes(NWeaponTypes::get_asset_id_from_name(x274_27_phazonVeinsIdx ? - "PhazonVeins_2" : "PhazonVeins"), x4_scale)); - x21c_phazonVeins.Unlock(); - x274_25_clipWipeActive = true; - } - } +void CPhazonBeam::Load(CStateManager& mgr, bool subtypeBasePose) { + CGunWeapon::Load(mgr, subtypeBasePose); + x228_phazon2nd1.Lock(); + x274_27_phazonVeinsIdx = (mgr.GetActiveRandom()->Next() & 0x2) != 0; + x21c_phazonVeins = g_SimplePool->GetObj(x274_27_phazonVeinsIdx ? "PhazonVeins_2" : "PhazonVeins"); + x21c_phazonVeins.Lock(); +} + +void CPhazonBeam::ReInitVariables() { + x268_clipWipeScale = 0.f; + x26c_clipWipeTranslate = 0.f; + x270_indirectAlpha = 1.f; + x234_chargeFxGen.reset(); + x224_phazonVeinsData.reset(); + x274_24_loaded = false; + x274_25_clipWipeActive = true; + x274_26_veinsAlphaActive = false; + x1cc_enabledSecondaryEffect = ESecondaryFxType::None; +} + +void CPhazonBeam::Unload(CStateManager& mgr) { + CGunWeapon::Unload(mgr); + x228_phazon2nd1.Unlock(); + x21c_phazonVeins.Unlock(); + ReInitVariables(); +} + +bool CPhazonBeam::IsLoaded() const { return CGunWeapon::IsLoaded() && x274_24_loaded; } + +void CPhazonBeam::DrawClipScaleCube() const { + // Render AABB as completely transparent object, only modifying Z-buffer + m_aaboxShaderScale.draw(zeus::CColor::skClear); +} + +void CPhazonBeam::DrawClipTranslateCube() const { + // Render AABB as completely transparent object, only modifying Z-buffer + m_aaboxShaderTranslate.draw(zeus::CColor::skClear); +} + +void CPhazonBeam::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags, + const CActorLights* lights) const { + CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); + bool drawIndirect = visor == CPlayerState::EPlayerVisor::Combat || visor == CPlayerState::EPlayerVisor::Scan; + + if (drawIndirect) { + CGraphics::ResolveSpareTexture(g_Viewport); + CModelFlags tmpFlags = flags; + tmpFlags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + CGunWeapon::Draw(drawSuitArm, mgr, xf, tmpFlags, lights); + } + + CGunWeapon::Draw(drawSuitArm, mgr, xf, flags, lights); + + if (drawIndirect) { + g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.3f * x270_indirectAlpha, 0.6f * x270_indirectAlpha, + x270_indirectAlpha, 0.5f * x270_indirectAlpha), + {}, zeus::CColor::skWhite, 1.f, 0.f, 0.f, 0.f); + } + + if (x224_phazonVeinsData) { + zeus::CTransform modelXf = xf * x10_solidModelData->GetScaledLocatorTransform("elbow"); + if (x274_25_clipWipeActive) { + CGraphics::SetModelMatrix(modelXf * zeus::CTransform::Scale(1.f - x268_clipWipeScale)); + DrawClipScaleCube(); + CGraphics::SetModelMatrix(modelXf * zeus::CTransform::Translate(0.f, x26c_clipWipeTranslate, 0.f)); + DrawClipTranslateCube(); } - - if (x274_25_clipWipeActive) - { - x268_clipWipeScale += 0.75f * dt; - if (x268_clipWipeScale > 1.f) - x268_clipWipeScale = 1.f; - if (x268_clipWipeScale > 0.4f) - { - if (x26c_clipWipeTranslate < 0.5f) - x26c_clipWipeTranslate += 0.75f * dt; - else - x274_25_clipWipeActive = false; - } - } - else if (x274_26_veinsAlphaActive) - { - x270_indirectAlpha = x10_solidModelData->GetLocatorTransform("phazonScale_LCTR_SDK").origin.y(); + if (x274_26_veinsAlphaActive) { + CModelFlags useFlags(5, 0, 3, zeus::CColor(1.f, 0.5f * x270_indirectAlpha)); + x224_phazonVeinsData->Render(mgr, xf, lights, useFlags); + } else { + x224_phazonVeinsData->Render(mgr, xf, lights, flags); } + } } -void CPhazonBeam::Load(CStateManager& mgr, bool subtypeBasePose) -{ - CGunWeapon::Load(mgr, subtypeBasePose); - x228_phazon2nd1.Lock(); - x274_27_phazonVeinsIdx = (mgr.GetActiveRandom()->Next() & 0x2) != 0; - x21c_phazonVeins = g_SimplePool->GetObj(x274_27_phazonVeinsIdx ? "PhazonVeins_2" : "PhazonVeins"); - x21c_phazonVeins.Lock(); +void CPhazonBeam::DrawMuzzleFx(const CStateManager& mgr) const { + if (IsFiring()) + CGunWeapon::DrawMuzzleFx(mgr); } -void CPhazonBeam::ReInitVariables() -{ - x268_clipWipeScale = 0.f; - x26c_clipWipeTranslate = 0.f; - x270_indirectAlpha = 1.f; - x234_chargeFxGen.reset(); - x224_phazonVeinsData.reset(); - x274_24_loaded = false; - x274_25_clipWipeActive = true; - x274_26_veinsAlphaActive = false; - x1cc_enabledSecondaryEffect = ESecondaryFxType::None; -} - -void CPhazonBeam::Unload(CStateManager& mgr) -{ - CGunWeapon::Unload(mgr); - x228_phazon2nd1.Unlock(); - x21c_phazonVeins.Unlock(); - ReInitVariables(); -} - -bool CPhazonBeam::IsLoaded() const -{ - return CGunWeapon::IsLoaded() && x274_24_loaded; -} - -void CPhazonBeam::DrawClipScaleCube() const -{ - // Render AABB as completely transparent object, only modifying Z-buffer - m_aaboxShaderScale.draw(zeus::CColor::skClear); -} - -void CPhazonBeam::DrawClipTranslateCube() const -{ - // Render AABB as completely transparent object, only modifying Z-buffer - m_aaboxShaderTranslate.draw(zeus::CColor::skClear); -} - -void CPhazonBeam::Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, - const CModelFlags& flags, const CActorLights* lights) const -{ - CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); - bool drawIndirect = visor == CPlayerState::EPlayerVisor::Combat || visor == CPlayerState::EPlayerVisor::Scan; - - if (drawIndirect) - { - CGraphics::ResolveSpareTexture(g_Viewport); - CModelFlags tmpFlags = flags; - tmpFlags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - CGunWeapon::Draw(drawSuitArm, mgr, xf, tmpFlags, lights); - } - - CGunWeapon::Draw(drawSuitArm, mgr, xf, flags, lights); - - if (drawIndirect) - { - g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.3f * x270_indirectAlpha, 0.6f * x270_indirectAlpha, - x270_indirectAlpha, 0.5f * x270_indirectAlpha), - {}, zeus::CColor::skWhite, 1.f, 0.f, 0.f, 0.f); - } - - if (x224_phazonVeinsData) - { - zeus::CTransform modelXf = xf * x10_solidModelData->GetScaledLocatorTransform("elbow"); - if (x274_25_clipWipeActive) - { - CGraphics::SetModelMatrix(modelXf * zeus::CTransform::Scale(1.f - x268_clipWipeScale)); - DrawClipScaleCube(); - CGraphics::SetModelMatrix(modelXf * zeus::CTransform::Translate(0.f, x26c_clipWipeTranslate, 0.f)); - DrawClipTranslateCube(); - } - if (x274_26_veinsAlphaActive) - { - CModelFlags useFlags(5, 0, 3, zeus::CColor(1.f, 0.5f * x270_indirectAlpha)); - x224_phazonVeinsData->Render(mgr, xf, lights, useFlags); - } - else - { - x224_phazonVeinsData->Render(mgr, xf, lights, flags); - } - } -} - -void CPhazonBeam::DrawMuzzleFx(const CStateManager& mgr) const -{ - if (IsFiring()) - CGunWeapon::DrawMuzzleFx(mgr); -} - -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/Weapon/CPhazonBeam.hpp b/Runtime/Weapon/CPhazonBeam.hpp index 1e5c608b9..711c009a9 100644 --- a/Runtime/Weapon/CPhazonBeam.hpp +++ b/Runtime/Weapon/CPhazonBeam.hpp @@ -3,55 +3,52 @@ #include "CGunWeapon.hpp" #include "Graphics/Shaders/CAABoxShader.hpp" -namespace urde -{ +namespace urde { + +class CPhazonBeam final : public CGunWeapon { + TCachedToken x21c_phazonVeins; + std::unique_ptr x224_phazonVeinsData; + TCachedToken x228_phazon2nd1; + std::unique_ptr x234_chargeFxGen; + zeus::CAABox x238_aaBoxScale; + zeus::CAABox x250_aaBoxTranslate; + float x268_clipWipeScale = 0.f; + float x26c_clipWipeTranslate = 0.f; + float x270_indirectAlpha = 1.f; + bool x274_24_loaded : 1; + bool x274_25_clipWipeActive : 1; + bool x274_26_veinsAlphaActive : 1; + bool x274_27_phazonVeinsIdx : 1; + float x278_fireTime = 1.f / 3.f; + mutable CAABoxShader m_aaboxShaderScale = {true}; + mutable CAABoxShader m_aaboxShaderTranslate = {true}; + void ReInitVariables(); + void DrawClipScaleCube() const; + void DrawClipTranslateCube() const; -class CPhazonBeam final : public CGunWeapon -{ - TCachedToken x21c_phazonVeins; - std::unique_ptr x224_phazonVeinsData; - TCachedToken x228_phazon2nd1; - std::unique_ptr x234_chargeFxGen; - zeus::CAABox x238_aaBoxScale; - zeus::CAABox x250_aaBoxTranslate; - float x268_clipWipeScale = 0.f; - float x26c_clipWipeTranslate = 0.f; - float x270_indirectAlpha = 1.f; - bool x274_24_loaded : 1; - bool x274_25_clipWipeActive : 1; - bool x274_26_veinsAlphaActive : 1; - bool x274_27_phazonVeinsIdx : 1; - float x278_fireTime = 1.f / 3.f; - mutable CAABoxShader m_aaboxShaderScale = {true}; - mutable CAABoxShader m_aaboxShaderTranslate = {true}; - void ReInitVariables(); - void DrawClipScaleCube() const; - void DrawClipTranslateCube() const; public: - CPhazonBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - bool IsFiring() const { return x278_fireTime < 1.f / 6.f; } - void SetClipWipeActive(bool b) { x274_25_clipWipeActive = b; } - void SetVeinsAlphaActive(bool b) { x274_26_veinsAlphaActive = b; } - void StopBeam(CStateManager& mgr, bool b1); - void UpdateBeam(float dt, const zeus::CTransform& targetXf, - const zeus::CVector3f& localBeamPos, CStateManager& mgr); - void CreateBeam(CStateManager& mgr); + CPhazonBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + bool IsFiring() const { return x278_fireTime < 1.f / 6.f; } + void SetClipWipeActive(bool b) { x274_25_clipWipeActive = b; } + void SetVeinsAlphaActive(bool b) { x274_26_veinsAlphaActive = b; } + void StopBeam(CStateManager& mgr, bool b1); + void UpdateBeam(float dt, const zeus::CTransform& targetXf, const zeus::CVector3f& localBeamPos, CStateManager& mgr); + void CreateBeam(CStateManager& mgr); - void PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); - void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); - void Update(float dt, CStateManager& mgr); - void Load(CStateManager& mgr, bool subtypeBasePose); - void Unload(CStateManager& mgr); - bool IsLoaded() const; - void Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, - const CModelFlags& flags, const CActorLights* lights) const; - void DrawMuzzleFx(const CStateManager& mgr) const; + void PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); + void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, CStateManager& mgr, + TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); + void Update(float dt, CStateManager& mgr); + void Load(CStateManager& mgr, bool subtypeBasePose); + void Unload(CStateManager& mgr); + bool IsLoaded() const; + void Draw(bool drawSuitArm, const CStateManager& mgr, const zeus::CTransform& xf, const CModelFlags& flags, + const CActorLights* lights) const; + void DrawMuzzleFx(const CStateManager& mgr) const; }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CPlasmaBeam.cpp b/Runtime/Weapon/CPlasmaBeam.cpp index f6cf4d56c..2a4d75ac7 100644 --- a/Runtime/Weapon/CPlasmaBeam.cpp +++ b/Runtime/Weapon/CPlasmaBeam.cpp @@ -4,165 +4,140 @@ #include "World/CPlayer.hpp" #include "World/CWorld.hpp" -namespace urde -{ +namespace urde { -CPlasmaBeam::CPlasmaBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale) -: CGunWeapon(characterId, type, playerId, playerMaterial, scale) -{ - x21c_plasma2nd1 = g_SimplePool->GetObj("Plasma2nd_1"); - x22c_24_loaded = false; - x22c_25_worldLighingDim = false; +CPlasmaBeam::CPlasmaBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale) +: CGunWeapon(characterId, type, playerId, playerMaterial, scale) { + x21c_plasma2nd1 = g_SimplePool->GetObj("Plasma2nd_1"); + x22c_24_loaded = false; + x22c_25_worldLighingDim = false; } -void CPlasmaBeam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Deleted) - DeleteBeam(mgr); +void CPlasmaBeam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Deleted) + DeleteBeam(mgr); } -void CPlasmaBeam::SetWorldLighting(CStateManager& mgr, TAreaId aid, float speed, float target) -{ - if (x22c_25_worldLighingDim && x23c_stateArea != aid && x23c_stateArea != kInvalidAreaId) - { - CGameArea* area = mgr.WorldNC()->GetArea(x23c_stateArea); - if (area->IsPostConstructed()) - area->SetWeaponWorldLighting(2.f, 1.f); - } +void CPlasmaBeam::SetWorldLighting(CStateManager& mgr, TAreaId aid, float speed, float target) { + if (x22c_25_worldLighingDim && x23c_stateArea != aid && x23c_stateArea != kInvalidAreaId) { + CGameArea* area = mgr.WorldNC()->GetArea(x23c_stateArea); + if (area->IsPostConstructed()) + area->SetWeaponWorldLighting(2.f, 1.f); + } - x23c_stateArea = aid; - x22c_25_worldLighingDim = target != 1.f; + x23c_stateArea = aid; + x22c_25_worldLighingDim = target != 1.f; - if (x23c_stateArea != kInvalidAreaId) - { - CGameArea* area = mgr.WorldNC()->GetArea(x23c_stateArea); - if (area->IsPostConstructed()) - area->SetWeaponWorldLighting(speed, target); - } + if (x23c_stateArea != kInvalidAreaId) { + CGameArea* area = mgr.WorldNC()->GetArea(x23c_stateArea); + if (area->IsPostConstructed()) + area->SetWeaponWorldLighting(speed, target); + } } -void CPlasmaBeam::DeleteBeam(CStateManager& mgr) -{ - if (x22c_25_worldLighingDim) - SetWorldLighting(mgr, mgr.GetPlayer().GetAreaIdAlways(), 2.f, 1.f); +void CPlasmaBeam::DeleteBeam(CStateManager& mgr) { + if (x22c_25_worldLighingDim) + SetWorldLighting(mgr, mgr.GetPlayer().GetAreaIdAlways(), 2.f, 1.f); } -void CPlasmaBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x228_chargeFx && x1cc_enabledSecondaryEffect != ESecondaryFxType::None) - x228_chargeFx->Render(); - CGunWeapon::PostRenderGunFx(mgr, xf); +void CPlasmaBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + if (x228_chargeFx && x1cc_enabledSecondaryEffect != ESecondaryFxType::None) + x228_chargeFx->Render(); + CGunWeapon::PostRenderGunFx(mgr, xf); } -void CPlasmaBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x228_chargeFx && x1cc_enabledSecondaryEffect != ESecondaryFxType::None) - { - if (x228_chargeFx->IsSystemDeletable()) - x1cc_enabledSecondaryEffect = ESecondaryFxType::None; - x228_chargeFx->SetTranslation(xf.origin); - x228_chargeFx->SetOrientation(xf.getRotation()); - x228_chargeFx->Update(dt); - } - CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); +void CPlasmaBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) { + if (x228_chargeFx && x1cc_enabledSecondaryEffect != ESecondaryFxType::None) { + if (x228_chargeFx->IsSystemDeletable()) + x1cc_enabledSecondaryEffect = ESecondaryFxType::None; + x228_chargeFx->SetTranslation(xf.origin); + x228_chargeFx->SetOrientation(xf.getRotation()); + x228_chargeFx->Update(dt); + } + CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); } -static const CCameraShakeData CameraShaker = { 0.125f, 0.25f }; -static const u16 kSoundId[] = { SFXwpn_fire_plasma_normal, SFXwpn_fire_plasma_charged }; +static const CCameraShakeData CameraShaker = {0.125f, 0.25f}; +static const u16 kSoundId[] = {SFXwpn_fire_plasma_normal, SFXwpn_fire_plasma_charged}; void CPlasmaBeam::Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) -{ - bool fired = false; - if (chargeState == EChargeState::Normal) - { - if (x230_fireShotDelayTimer < 0.01f) - { - ActivateCharge(false, true); - CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); - x230_fireShotDelayTimer += 0.33f; - x234_fireShotDelay = 0.33f; - fired = true; - } - } - else - { - CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, 1.f); - mgr.GetCameraManager()->AddCameraShaker(CameraShaker, false); - x238_lightingResetDelayTimer = 0.65f; - SetWorldLighting(mgr, mgr.GetPlayer().GetAreaIdAlways(), 8.f, 0.7f); - fired = true; + CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) { + bool fired = false; + if (chargeState == EChargeState::Normal) { + if (x230_fireShotDelayTimer < 0.01f) { + ActivateCharge(false, true); + CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); + x230_fireShotDelayTimer += 0.33f; + x234_fireShotDelay = 0.33f; + fired = true; } + } else { + CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, 1.f); + mgr.GetCameraManager()->AddCameraShaker(CameraShaker, false); + x238_lightingResetDelayTimer = 0.65f; + SetWorldLighting(mgr, mgr.GetPlayer().GetAreaIdAlways(), 8.f, 0.7f); + fired = true; + } - if (fired) - NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); + if (fired) + NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); } -void CPlasmaBeam::EnableSecondaryFx(ESecondaryFxType type) -{ - switch (type) - { - case ESecondaryFxType::CancelCharge: - if (x1cc_enabledSecondaryEffect == ESecondaryFxType::None || !x228_chargeFx) - return; - x228_chargeFx->SetParticleEmission(false); - break; - case ESecondaryFxType::Charge: - x228_chargeFx = std::make_unique(x21c_plasma2nd1); - x228_chargeFx->SetGlobalScale(x4_scale); - default: - break; - } - x1cc_enabledSecondaryEffect = type; +void CPlasmaBeam::EnableSecondaryFx(ESecondaryFxType type) { + switch (type) { + case ESecondaryFxType::CancelCharge: + if (x1cc_enabledSecondaryEffect == ESecondaryFxType::None || !x228_chargeFx) + return; + x228_chargeFx->SetParticleEmission(false); + break; + case ESecondaryFxType::Charge: + x228_chargeFx = std::make_unique(x21c_plasma2nd1); + x228_chargeFx->SetGlobalScale(x4_scale); + default: + break; + } + x1cc_enabledSecondaryEffect = type; } -void CPlasmaBeam::Update(float dt, CStateManager& mgr) -{ - CGunWeapon::Update(dt, mgr); - x230_fireShotDelayTimer = std::max(0.f, x230_fireShotDelayTimer - dt); - x238_lightingResetDelayTimer -= dt; - if ((mgr.GetPlayer().GetPlayerGun()->IsCharging() ? - mgr.GetPlayer().GetPlayerGun()->GetChargeBeamFactor() : 0.f) > 0.5f) - SetWorldLighting(mgr, mgr.GetPlayer().GetAreaIdAlways(), 0.2f, 0.8f); - else if (x238_lightingResetDelayTimer < 0.f && x22c_25_worldLighingDim) - SetWorldLighting(mgr, mgr.GetPlayer().GetAreaIdAlways(), 2.f, 1.f); +void CPlasmaBeam::Update(float dt, CStateManager& mgr) { + CGunWeapon::Update(dt, mgr); + x230_fireShotDelayTimer = std::max(0.f, x230_fireShotDelayTimer - dt); + x238_lightingResetDelayTimer -= dt; + if ((mgr.GetPlayer().GetPlayerGun()->IsCharging() ? mgr.GetPlayer().GetPlayerGun()->GetChargeBeamFactor() : 0.f) > + 0.5f) + SetWorldLighting(mgr, mgr.GetPlayer().GetAreaIdAlways(), 0.2f, 0.8f); + else if (x238_lightingResetDelayTimer < 0.f && x22c_25_worldLighingDim) + SetWorldLighting(mgr, mgr.GetPlayer().GetAreaIdAlways(), 2.f, 1.f); - if (IsLoaded()) - return; + if (IsLoaded()) + return; - if (CGunWeapon::IsLoaded() && !x22c_24_loaded) - { - x22c_24_loaded = x21c_plasma2nd1.IsLoaded(); - if (x22c_24_loaded) - CreateBeam(mgr); - } + if (CGunWeapon::IsLoaded() && !x22c_24_loaded) { + x22c_24_loaded = x21c_plasma2nd1.IsLoaded(); + if (x22c_24_loaded) + CreateBeam(mgr); + } } -void CPlasmaBeam::Load(CStateManager& mgr, bool subtypeBasePose) -{ - CGunWeapon::Load(mgr, subtypeBasePose); - x21c_plasma2nd1.Lock(); +void CPlasmaBeam::Load(CStateManager& mgr, bool subtypeBasePose) { + CGunWeapon::Load(mgr, subtypeBasePose); + x21c_plasma2nd1.Lock(); } -void CPlasmaBeam::ReInitVariables() -{ - x228_chargeFx.reset(); - x22c_24_loaded = false; - x1cc_enabledSecondaryEffect = ESecondaryFxType::None; +void CPlasmaBeam::ReInitVariables() { + x228_chargeFx.reset(); + x22c_24_loaded = false; + x1cc_enabledSecondaryEffect = ESecondaryFxType::None; } -void CPlasmaBeam::Unload(CStateManager& mgr) -{ - CGunWeapon::Unload(mgr); - x21c_plasma2nd1.Unlock(); - DeleteBeam(mgr); - ReInitVariables(); +void CPlasmaBeam::Unload(CStateManager& mgr) { + CGunWeapon::Unload(mgr); + x21c_plasma2nd1.Unlock(); + DeleteBeam(mgr); + ReInitVariables(); } -bool CPlasmaBeam::IsLoaded() const -{ - return CGunWeapon::IsLoaded() && x22c_24_loaded; -} +bool CPlasmaBeam::IsLoaded() const { return CGunWeapon::IsLoaded() && x22c_24_loaded; } -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/Weapon/CPlasmaBeam.hpp b/Runtime/Weapon/CPlasmaBeam.hpp index 8479e8e98..1546ed978 100644 --- a/Runtime/Weapon/CPlasmaBeam.hpp +++ b/Runtime/Weapon/CPlasmaBeam.hpp @@ -2,42 +2,43 @@ #include "CGunWeapon.hpp" -namespace urde -{ +namespace urde { + +class CPlasmaBeam final : public CGunWeapon { + TCachedToken x21c_plasma2nd1; + std::unique_ptr x228_chargeFx; + bool x22c_24_loaded : 1; + bool x22c_25_worldLighingDim : 1; + float x230_fireShotDelayTimer = 0.f; + float x234_fireShotDelay = 0.f; + float x238_lightingResetDelayTimer = 0.f; + TAreaId x23c_stateArea = kInvalidAreaId; + void ReInitVariables(); + void SetWorldLighting(CStateManager& mgr, TAreaId aid, float speed, float target); -class CPlasmaBeam final : public CGunWeapon -{ - TCachedToken x21c_plasma2nd1; - std::unique_ptr x228_chargeFx; - bool x22c_24_loaded : 1; - bool x22c_25_worldLighingDim : 1; - float x230_fireShotDelayTimer = 0.f; - float x234_fireShotDelay = 0.f; - float x238_lightingResetDelayTimer = 0.f; - TAreaId x23c_stateArea = kInvalidAreaId; - void ReInitVariables(); - void SetWorldLighting(CStateManager& mgr, TAreaId aid, float speed, float target); public: - CPlasmaBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - bool IsFiring() const { return x234_fireShotDelay > 0.f; } - void StopBeam(CStateManager& mgr, bool b1) { /* Empty */ } - void CreateBeam(CStateManager& mgr) { /* Empty */ } - void UpdateBeam(float dt, const zeus::CTransform& targetXf, - const zeus::CVector3f& localBeamPos, CStateManager& mgr) { /* Empty */ } - void DeleteBeam(CStateManager& mgr); + CPlasmaBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + bool IsFiring() const { return x234_fireShotDelay > 0.f; } + void StopBeam(CStateManager& mgr, bool b1) { /* Empty */ + } + void CreateBeam(CStateManager& mgr) { /* Empty */ + } + void UpdateBeam(float dt, const zeus::CTransform& targetXf, const zeus::CVector3f& localBeamPos, + CStateManager& mgr) { /* Empty */ + } + void DeleteBeam(CStateManager& mgr); - void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); - void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); - void EnableSecondaryFx(ESecondaryFxType type); - void Update(float dt, CStateManager& mgr); - void Load(CStateManager& mgr, bool subtypeBasePose); - void Unload(CStateManager& mgr); - bool IsLoaded() const; + void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); + void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, CStateManager& mgr, + TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); + void EnableSecondaryFx(ESecondaryFxType type); + void Update(float dt, CStateManager& mgr); + void Load(CStateManager& mgr, bool subtypeBasePose); + void Unload(CStateManager& mgr); + bool IsLoaded() const; }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CPlasmaProjectile.cpp b/Runtime/Weapon/CPlasmaProjectile.cpp index a4a6edf71..fde8abf6d 100644 --- a/Runtime/Weapon/CPlasmaProjectile.cpp +++ b/Runtime/Weapon/CPlasmaProjectile.cpp @@ -1,26 +1,17 @@ #include "CPlasmaProjectile.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CPlasmaProjectile::CPlasmaProjectile(const TToken& wDesc, std::string_view name, - EWeaponType wType, const CBeamInfo& bInfo, const zeus::CTransform& xf, - EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, - TUniqueId owner, u32 w1, bool b1, EProjectileAttrib attribs) -: CBeamProjectile(wDesc, name, wType, xf, bInfo.x18_, bInfo.x1c_, bInfo.x38_, matType, - dInfo, uid, aid, owner, attribs, b1) -{ -} +CPlasmaProjectile::CPlasmaProjectile(const TToken& wDesc, std::string_view name, EWeaponType wType, + const CBeamInfo& bInfo, const zeus::CTransform& xf, EMaterialTypes matType, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, u32 w1, + bool b1, EProjectileAttrib attribs) +: CBeamProjectile(wDesc, name, wType, xf, bInfo.x18_, bInfo.x1c_, bInfo.x38_, matType, dInfo, uid, aid, owner, attribs, + b1) {} -void CPlasmaProjectile::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CPlasmaProjectile::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CPlasmaProjectile::Fire(const zeus::CTransform&, CStateManager&, bool) -{ - SetActive(true); -} +void CPlasmaProjectile::Fire(const zeus::CTransform&, CStateManager&, bool) { SetActive(true); } -} +} // namespace urde diff --git a/Runtime/Weapon/CPlasmaProjectile.hpp b/Runtime/Weapon/CPlasmaProjectile.hpp index 6898efbdc..8b8bf76dc 100644 --- a/Runtime/Weapon/CPlasmaProjectile.hpp +++ b/Runtime/Weapon/CPlasmaProjectile.hpp @@ -4,20 +4,17 @@ #include "Weapon/CBeamInfo.hpp" #include "World/CDamageInfo.hpp" -namespace urde -{ -class CPlasmaProjectile : public CBeamProjectile -{ +namespace urde { +class CPlasmaProjectile : public CBeamProjectile { public: - CPlasmaProjectile(const TToken& wDesc, std::string_view name, - EWeaponType wType, const CBeamInfo& bInfo, const zeus::CTransform& xf, - EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, - TUniqueId owner, u32 w1, bool b1, EProjectileAttrib attribs); + CPlasmaProjectile(const TToken& wDesc, std::string_view name, EWeaponType wType, + const CBeamInfo& bInfo, const zeus::CTransform& xf, EMaterialTypes matType, + const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, u32 w1, bool b1, + EProjectileAttrib attribs); - void Accept(IVisitor& visitor); + void Accept(IVisitor& visitor); - void UpdateFx(const zeus::CTransform&, float, CStateManager&) {} - void Fire(const zeus::CTransform&, CStateManager&, bool); + void UpdateFx(const zeus::CTransform&, float, CStateManager&) {} + void Fire(const zeus::CTransform&, CStateManager&, bool); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CPlayerGun.cpp b/Runtime/Weapon/CPlayerGun.cpp index bf479ae5f..40a69dca1 100644 --- a/Runtime/Weapon/CPlayerGun.cpp +++ b/Runtime/Weapon/CPlayerGun.cpp @@ -12,1241 +12,1045 @@ #include "Graphics/CBooRenderer.hpp" #include "Camera/CGameCamera.hpp" -namespace urde -{ +namespace urde { static const zeus::CVector3f sGunScale(2.f); -static float kVerticalAngleTable[] = { -30.f, 0.f, 30.f }; -static float kHorizontalAngleTable[] = { 30.f, 30.f, 30.f }; -static float kVerticalVarianceTable[] = { 30.f, 30.f, 30.f }; +static float kVerticalAngleTable[] = {-30.f, 0.f, 30.f}; +static float kHorizontalAngleTable[] = {30.f, 30.f, 30.f}; +static float kVerticalVarianceTable[] = {30.f, 30.f, 30.f}; float CPlayerGun::CMotionState::gGunExtendDistance = 0.125f; float CPlayerGun::skTractorBeamFactor = 0.5f / CPlayerState::GetMissileComboChargeFactor(); CPlayerGun::CPlayerGun(TUniqueId playerId) -: x0_lights(8, zeus::CVector3f{-30.f, 0.f, 30.f}, 4, 4, 0, 0, 0, 0.1f), x538_playerId(playerId), - x550_camBob(CPlayerCameraBob::ECameraBobType::One, +: x0_lights(8, zeus::CVector3f{-30.f, 0.f, 30.f}, 4, 4, 0, 0, 0, 0.1f) +, x538_playerId(playerId) +, x550_camBob(CPlayerCameraBob::ECameraBobType::One, zeus::CVector2f(CPlayerCameraBob::kCameraBobExtentX, CPlayerCameraBob::kCameraBobExtentY), - CPlayerCameraBob::kCameraBobPeriod), - x678_morph(g_tweakPlayerGun->GetGunTransformTime(), g_tweakPlayerGun->GetHoloHoldTime()), - x6c8_hologramClipCube(zeus::CVector3f(-0.29329199f, 0.f, -0.2481945f), - zeus::CVector3f(0.29329199f, 1.292392f, 0.2481945f)), - x6e0_rightHandModel(CAnimRes(g_tweakGunRes->xc_rightHand, 0, zeus::CVector3f(3.f), 0, true)) -{ - x354_bombFuseTime = g_tweakPlayerGun->GetBombFuseTime(); - x358_bombDropDelayTime = g_tweakPlayerGun->GetBombDropDelayTime(); - x668_aimVerticalSpeed = g_tweakPlayerGun->GetAimVerticalSpeed(); - x66c_aimHorizontalSpeed = g_tweakPlayerGun->GetAimHorizontalSpeed(); + CPlayerCameraBob::kCameraBobPeriod) +, x678_morph(g_tweakPlayerGun->GetGunTransformTime(), g_tweakPlayerGun->GetHoloHoldTime()) +, x6c8_hologramClipCube(zeus::CVector3f(-0.29329199f, 0.f, -0.2481945f), + zeus::CVector3f(0.29329199f, 1.292392f, 0.2481945f)) +, x6e0_rightHandModel(CAnimRes(g_tweakGunRes->xc_rightHand, 0, zeus::CVector3f(3.f), 0, true)) { + x354_bombFuseTime = g_tweakPlayerGun->GetBombFuseTime(); + x358_bombDropDelayTime = g_tweakPlayerGun->GetBombDropDelayTime(); + x668_aimVerticalSpeed = g_tweakPlayerGun->GetAimVerticalSpeed(); + x66c_aimHorizontalSpeed = g_tweakPlayerGun->GetAimHorizontalSpeed(); - x73c_gunMotion = std::make_unique(g_tweakGunRes->x4_gunMotion, sGunScale); - x740_grappleArm = std::make_unique(sGunScale); - x744_auxWeapon = std::make_unique(playerId); - x748_rainSplashGenerator = std::make_unique(sGunScale, 20, 2, 0.f, 0.125f); - x74c_powerBeam = std::make_unique(g_tweakGunRes->x10_powerBeam, EWeaponType::Power, - playerId, EMaterialTypes::Player, sGunScale); - x750_iceBeam = std::make_unique(g_tweakGunRes->x14_iceBeam, EWeaponType::Ice, - playerId, EMaterialTypes::Player, sGunScale); - x754_waveBeam = std::make_unique(g_tweakGunRes->x18_waveBeam, EWeaponType::Wave, - playerId, EMaterialTypes::Player, sGunScale); - x758_plasmaBeam = std::make_unique(g_tweakGunRes->x1c_plasmaBeam, EWeaponType::Plasma, - playerId, EMaterialTypes::Player, sGunScale); - x75c_phazonBeam = std::make_unique(g_tweakGunRes->x20_phazonBeam, EWeaponType::Phazon, - playerId, EMaterialTypes::Player, sGunScale); - x774_holoTransitionGen = std::make_unique( - g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x24_holoTransition})); - x82c_shadow = std::make_unique(256, 256, true); + x73c_gunMotion = std::make_unique(g_tweakGunRes->x4_gunMotion, sGunScale); + x740_grappleArm = std::make_unique(sGunScale); + x744_auxWeapon = std::make_unique(playerId); + x748_rainSplashGenerator = std::make_unique(sGunScale, 20, 2, 0.f, 0.125f); + x74c_powerBeam = std::make_unique(g_tweakGunRes->x10_powerBeam, EWeaponType::Power, playerId, + EMaterialTypes::Player, sGunScale); + x750_iceBeam = std::make_unique(g_tweakGunRes->x14_iceBeam, EWeaponType::Ice, playerId, + EMaterialTypes::Player, sGunScale); + x754_waveBeam = std::make_unique(g_tweakGunRes->x18_waveBeam, EWeaponType::Wave, playerId, + EMaterialTypes::Player, sGunScale); + x758_plasmaBeam = std::make_unique(g_tweakGunRes->x1c_plasmaBeam, EWeaponType::Plasma, playerId, + EMaterialTypes::Player, sGunScale); + x75c_phazonBeam = std::make_unique(g_tweakGunRes->x20_phazonBeam, EWeaponType::Phazon, playerId, + EMaterialTypes::Player, sGunScale); + x774_holoTransitionGen = std::make_unique( + g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x24_holoTransition})); + x82c_shadow = std::make_unique(256, 256, true); - x832_31_inRestPose = true; - x833_24_notFidgeting = true; - x833_30_canShowAuxMuzzleEffect = true; - x6e0_rightHandModel.SetSortThermal(true); + x832_31_inRestPose = true; + x833_24_notFidgeting = true; + x833_30_canShowAuxMuzzleEffect = true; + x6e0_rightHandModel.SetSortThermal(true); - kVerticalAngleTable[2] = g_tweakPlayerGun->GetUpLookAngle(); - kVerticalAngleTable[0] = g_tweakPlayerGun->GetDownLookAngle(); - kHorizontalAngleTable[1] = g_tweakPlayerGun->GetHorizontalSpread(); - kHorizontalAngleTable[2] = g_tweakPlayerGun->GetHighHorizontalSpread(); - kHorizontalAngleTable[0] = g_tweakPlayerGun->GetLowHorizontalSpread(); - kVerticalVarianceTable[1] = g_tweakPlayerGun->GetVerticalSpread(); - kVerticalVarianceTable[2] = g_tweakPlayerGun->GetHighVerticalSpread(); - kVerticalVarianceTable[0] = g_tweakPlayerGun->GetLowVerticalSpread(); - CMotionState::SetExtendDistance(g_tweakPlayerGun->GetGunExtendDistance()); + kVerticalAngleTable[2] = g_tweakPlayerGun->GetUpLookAngle(); + kVerticalAngleTable[0] = g_tweakPlayerGun->GetDownLookAngle(); + kHorizontalAngleTable[1] = g_tweakPlayerGun->GetHorizontalSpread(); + kHorizontalAngleTable[2] = g_tweakPlayerGun->GetHighHorizontalSpread(); + kHorizontalAngleTable[0] = g_tweakPlayerGun->GetLowHorizontalSpread(); + kVerticalVarianceTable[1] = g_tweakPlayerGun->GetVerticalSpread(); + kVerticalVarianceTable[2] = g_tweakPlayerGun->GetHighVerticalSpread(); + kVerticalVarianceTable[0] = g_tweakPlayerGun->GetLowVerticalSpread(); + CMotionState::SetExtendDistance(g_tweakPlayerGun->GetGunExtendDistance()); - InitBeamData(); - InitBombData(); - InitMuzzleData(); - InitCTData(); - LoadHandAnimTokens(); - x550_camBob.SetPlayerVelocity(zeus::CVector3f::skZero); - x550_camBob.SetBobMagnitude(0.f); - x550_camBob.SetBobTimeScale(0.f); + InitBeamData(); + InitBombData(); + InitMuzzleData(); + InitCTData(); + LoadHandAnimTokens(); + x550_camBob.SetPlayerVelocity(zeus::CVector3f::skZero); + x550_camBob.SetBobMagnitude(0.f); + x550_camBob.SetBobTimeScale(0.f); - m_aaboxShader.setAABB(x6c8_hologramClipCube); + m_aaboxShader.setAABB(x6c8_hologramClipCube); } -void CPlayerGun::InitBeamData() -{ - x760_selectableBeams[0] = x74c_powerBeam.get(); - x760_selectableBeams[1] = x750_iceBeam.get(); - x760_selectableBeams[2] = x754_waveBeam.get(); - x760_selectableBeams[3] = x758_plasmaBeam.get(); - x72c_currentBeam = x760_selectableBeams[0]; - x738_nextBeam = x72c_currentBeam; - x774_holoTransitionGen->SetParticleEmission(true); +void CPlayerGun::InitBeamData() { + x760_selectableBeams[0] = x74c_powerBeam.get(); + x760_selectableBeams[1] = x750_iceBeam.get(); + x760_selectableBeams[2] = x754_waveBeam.get(); + x760_selectableBeams[3] = x758_plasmaBeam.get(); + x72c_currentBeam = x760_selectableBeams[0]; + x738_nextBeam = x72c_currentBeam; + x774_holoTransitionGen->SetParticleEmission(true); } -void CPlayerGun::InitBombData() -{ - x784_bombEffects.resize(2); - x784_bombEffects[0].push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x28_bombSet})); - x784_bombEffects[0].push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x2c_bombExplode})); - TLockedToken pbExplode = - g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x30_powerBombExplode}); - x784_bombEffects[1].push_back(pbExplode); - x784_bombEffects[1].push_back(pbExplode); +void CPlayerGun::InitBombData() { + x784_bombEffects.resize(2); + x784_bombEffects[0].push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x28_bombSet})); + x784_bombEffects[0].push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x2c_bombExplode})); + TLockedToken pbExplode = + g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->x30_powerBombExplode}); + x784_bombEffects[1].push_back(pbExplode); + x784_bombEffects[1].push_back(pbExplode); } -void CPlayerGun::InitMuzzleData() -{ - for (int i=0 ; i<5 ; ++i) - { - x7c0_auxMuzzleEffects.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), - g_tweakGunRes->xa4_auxMuzzle[i]})); - x800_auxMuzzleGenerators.emplace_back(new CElementGen(x7c0_auxMuzzleEffects.back())); - x800_auxMuzzleGenerators.back()->SetParticleEmission(false); +void CPlayerGun::InitMuzzleData() { + for (int i = 0; i < 5; ++i) { + x7c0_auxMuzzleEffects.push_back(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xa4_auxMuzzle[i]})); + x800_auxMuzzleGenerators.emplace_back(new CElementGen(x7c0_auxMuzzleEffects.back())); + x800_auxMuzzleGenerators.back()->SetParticleEmission(false); + } +} + +void CPlayerGun::InitCTData() { x77c_comboXferGen.reset(); } + +void CPlayerGun::LoadHandAnimTokens() { + std::set prims; + for (int i = 0; i < 3; ++i) { + CAnimPlaybackParms parms(i, -1, 1.f, true); + x6e0_rightHandModel.GetAnimationData()->GetAnimationPrimitives(parms, prims); + } + CAnimData::PrimitiveSetToTokenVector(prims, x540_handAnimTokens, true); +} + +void CPlayerGun::TakeDamage(bool bigStrike, bool notFromMetroid, CStateManager& mgr) { + bool hasStrikeAngle = false; + float angle = 0.f; + if (x398_damageAmt >= 10.f && !bigStrike && (x2f8_stateFlags & 0x10) != 0x10 && !x832_26_comboFiring && + x384_gunStrikeDelayTimer <= 0.f) { + x384_gunStrikeDelayTimer = 20.f; + x364_gunStrikeCoolTimer = 0.75f; + if (x678_morph.GetGunState() == CGunMorph::EGunState::OutWipeDone) { + zeus::CVector3f localDamageLoc = mgr.GetPlayer().GetTransform().transposeRotate(x3dc_damageLocation); + angle = zeus::CRelAngle(std::atan2(localDamageLoc.y(), localDamageLoc.x())).asDegrees(); + hasStrikeAngle = true; } -} + } -void CPlayerGun::InitCTData() -{ - x77c_comboXferGen.reset(); -} - -void CPlayerGun::LoadHandAnimTokens() -{ - std::set prims; - for (int i=0 ; i<3 ; ++i) - { - CAnimPlaybackParms parms(i, -1, 1.f, true); - x6e0_rightHandModel.GetAnimationData()->GetAnimationPrimitives(parms, prims); + if (hasStrikeAngle || bigStrike) { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) { + x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Struck, mgr, angle, bigStrike); + if ((bigStrike && notFromMetroid) || x833_31_inFreeLook) + x740_grappleArm->EnterStruck(mgr, angle, bigStrike, !x833_31_inFreeLook); } - CAnimData::PrimitiveSetToTokenVector(prims, x540_handAnimTokens, true); + } + + x398_damageAmt = 0.f; + x3dc_damageLocation = zeus::CVector3f::skZero; } -void CPlayerGun::TakeDamage(bool bigStrike, bool notFromMetroid, CStateManager& mgr) -{ - bool hasStrikeAngle = false; - float angle = 0.f; - if (x398_damageAmt >= 10.f && !bigStrike && (x2f8_stateFlags & 0x10) != 0x10 && - !x832_26_comboFiring && x384_gunStrikeDelayTimer <= 0.f) - { - x384_gunStrikeDelayTimer = 20.f; - x364_gunStrikeCoolTimer = 0.75f; - if (x678_morph.GetGunState() == CGunMorph::EGunState::OutWipeDone) - { - zeus::CVector3f localDamageLoc = mgr.GetPlayer().GetTransform().transposeRotate(x3dc_damageLocation); - angle = zeus::CRelAngle(std::atan2(localDamageLoc.y(), localDamageLoc.x())).asDegrees(); - hasStrikeAngle = true; - } - } - - if (hasStrikeAngle || bigStrike) - { - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - { - x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Struck, mgr, angle, bigStrike); - if ((bigStrike && notFromMetroid) || x833_31_inFreeLook) - x740_grappleArm->EnterStruck(mgr, angle, bigStrike, !x833_31_inFreeLook); - } - } - - x398_damageAmt = 0.f; - x3dc_damageLocation = zeus::CVector3f::skZero; +void CPlayerGun::CreateGunLight(CStateManager& mgr) { + if (x53c_lightId != kInvalidUniqueId) + return; + x53c_lightId = mgr.AllocateUniqueId(); + CGameLight* light = new CGameLight(x53c_lightId, kInvalidAreaId, false, "GunLite", x3e8_xf, x538_playerId, + CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skBlack), + x53c_lightId.Value(), 0, 0.f); + mgr.AddObject(light); } -void CPlayerGun::CreateGunLight(CStateManager& mgr) -{ - if (x53c_lightId != kInvalidUniqueId) - return; - x53c_lightId = mgr.AllocateUniqueId(); - CGameLight* light = new CGameLight(x53c_lightId, kInvalidAreaId, false, "GunLite", x3e8_xf, x538_playerId, - CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skBlack), - x53c_lightId.Value(), 0, 0.f); - mgr.AddObject(light); +void CPlayerGun::DeleteGunLight(CStateManager& mgr) { + if (x53c_lightId == kInvalidUniqueId) + return; + mgr.FreeScriptObject(x53c_lightId); + x53c_lightId = kInvalidUniqueId; } -void CPlayerGun::DeleteGunLight(CStateManager& mgr) -{ - if (x53c_lightId == kInvalidUniqueId) - return; - mgr.FreeScriptObject(x53c_lightId); - x53c_lightId = kInvalidUniqueId; +void CPlayerGun::UpdateGunLight(const zeus::CTransform& xf, CStateManager& mgr) { + if (x53c_lightId == kInvalidUniqueId || x32c_chargePhase == EChargePhase::NotCharging) + return; + + if (TCastToPtr light = mgr.ObjectById(x53c_lightId)) { + if (light->GetActive()) { + CElementGen* chargeFx = x72c_currentBeam->GetChargeMuzzleFx(); + light->SetTransform(xf); + light->SetTranslation(xf.origin); + if (chargeFx && chargeFx->SystemHasLight()) { + CLight l = chargeFx->GetLight(); + l.SetColor(zeus::CColor::lerp(zeus::CColor::skClear, l.GetColor(), x340_chargeBeamFactor)); + light->SetLight(l); + } + } + } } -void CPlayerGun::UpdateGunLight(const zeus::CTransform& xf, CStateManager& mgr) -{ - if (x53c_lightId == kInvalidUniqueId || x32c_chargePhase == EChargePhase::NotCharging) - return; +void CPlayerGun::SetGunLightActive(bool active, CStateManager& mgr) { + if (x53c_lightId == kInvalidUniqueId) + return; - if (TCastToPtr light = mgr.ObjectById(x53c_lightId)) - { - if (light->GetActive()) - { - CElementGen* chargeFx = x72c_currentBeam->GetChargeMuzzleFx(); - light->SetTransform(xf); - light->SetTranslation(xf.origin); - if (chargeFx && chargeFx->SystemHasLight()) - { - CLight l = chargeFx->GetLight(); - l.SetColor(zeus::CColor::lerp(zeus::CColor::skClear, l.GetColor(), x340_chargeBeamFactor)); - light->SetLight(l); - } + if (TCastToPtr light = mgr.ObjectById(x53c_lightId)) { + light->SetActive(active); + if (active) { + if (CElementGen* gen = x72c_currentBeam->GetChargeMuzzleFx()) { + if (gen->SystemHasLight()) { + CLight genLight = gen->GetLight(); + genLight.SetColor(zeus::CColor::skBlack); + light->SetLight(genLight); } + } } + } } -void CPlayerGun::SetGunLightActive(bool active, CStateManager& mgr) -{ - if (x53c_lightId == kInvalidUniqueId) - return; +static const u32 skBeamAnimIds[] = {0, 1, 2, 1}; - if (TCastToPtr light = mgr.ObjectById(x53c_lightId)) - { - light->SetActive(active); - if (active) - { - if (CElementGen* gen = x72c_currentBeam->GetChargeMuzzleFx()) - { - if (gen->SystemHasLight()) - { - CLight genLight = gen->GetLight(); - genLight.SetColor(zeus::CColor::skBlack); - light->SetLight(genLight); - } - } +void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + const CPlayer& player = mgr.GetPlayer(); + bool isUnmorphed = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed; + switch (msg) { + case EScriptObjectMessage::Registered: { + CreateGunLight(mgr); + x320_currentAuxBeam = x314_nextBeam = x310_currentBeam = mgr.GetPlayerState()->GetCurrentBeam(); + x72c_currentBeam = x738_nextBeam = x760_selectableBeams[int(x310_currentBeam)]; + x72c_currentBeam->Load(mgr, true); + x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); + x744_auxWeapon->Load(x310_currentBeam, mgr); + CAnimPlaybackParms parms(skBeamAnimIds[int(mgr.GetPlayerState()->GetCurrentBeam())], -1, 1.f, true); + x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false); + break; + } + case EScriptObjectMessage::Deleted: + DeleteGunLight(mgr); + break; + case EScriptObjectMessage::UpdateSplashInhabitant: + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed) { + if (TCastToConstPtr water = mgr.GetObjectById(sender)) { + if (water->GetFluidPlane().GetFluidType() == EFluidType::PhazonFluid) { + x835_24_canFirePhazon = true; + x835_25_inPhazonBeam = true; } + } } + if (player.GetDistanceUnderWater() > player.GetEyeHeight()) { + x834_27_underwater = true; + if (x744_auxWeapon->IsComboFxActive(mgr) && x310_currentBeam != CPlayerState::EBeamId::Wave) + StopContinuousBeam(mgr, false); + } else { + x834_27_underwater = false; + } + break; + case EScriptObjectMessage::RemoveSplashInhabitant: + x834_27_underwater = false; + x835_24_canFirePhazon = false; + break; + case EScriptObjectMessage::AddPhazonPoolInhabitant: + x835_30_inPhazonPool = true; + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed) + x835_24_canFirePhazon = true; + break; + case EScriptObjectMessage::UpdatePhazonPoolInhabitant: + x835_30_inPhazonPool = true; + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed) { + x835_24_canFirePhazon = true; + x835_25_inPhazonBeam = true; + if (x833_28_phazonBeamActive && static_cast(x72c_currentBeam)->IsFiring()) + if (TCastToPtr ent = mgr.ObjectById(sender)) + mgr.SendScriptMsg(ent.GetPtr(), x538_playerId, EScriptObjectMessage::Decrement); + } + break; + case EScriptObjectMessage::RemovePhazonPoolInhabitant: + x835_30_inPhazonPool = false; + x835_24_canFirePhazon = false; + break; + case EScriptObjectMessage::Damage: { + bool bigStrike = false; + bool metroidAttached = false; + if (TCastToConstPtr proj = mgr.GetObjectById(sender)) { + if ((proj->GetAttribField() & EProjectileAttrib::BigStrike) == EProjectileAttrib::BigStrike) { + x394_damageTimer = proj->GetDamageDuration(); + bigStrike = true; + } + } else if (TCastToConstPtr ai = mgr.GetObjectById(sender)) { + if (ai->IsMakingBigStrike()) { + x394_damageTimer = ai->GetDamageDuration(); + bigStrike = true; + if (player.GetAttachedActor() != kInvalidUniqueId) + metroidAttached = CPatterned::CastTo(mgr.GetObjectById(player.GetAttachedActor())) != nullptr; + } + } + if (!x834_30_inBigStrike) { + if (bigStrike) { + x834_31_gunMotionInFidgetBasePosition = false; + CancelFiring(mgr); + } + TakeDamage(bigStrike, !metroidAttached, mgr); + x834_30_inBigStrike = bigStrike; + } + break; + } + case EScriptObjectMessage::OnFloor: + if (player.GetControlsFrozen() && !x834_30_inBigStrike) { + x2f4_fireButtonStates = 0; + x2ec_lastFireButtonStates = 0; + CancelFiring(mgr); + TakeDamage(true, false, mgr); + x394_damageTimer = 0.75f; + x834_30_inBigStrike = true; + } + break; + default: + break; + } + + x740_grappleArm->AcceptScriptMsg(msg, sender, mgr); + x758_plasmaBeam->AcceptScriptMsg(msg, sender, mgr); + x75c_phazonBeam->AcceptScriptMsg(msg, sender, mgr); + x744_auxWeapon->AcceptScriptMsg(msg, sender, mgr); } -static const u32 skBeamAnimIds[] = { 0, 1, 2, 1 }; +void CPlayerGun::AsyncLoadSuit(CStateManager& mgr) { + x72c_currentBeam->AsyncLoadSuitArm(mgr); + x740_grappleArm->AsyncLoadSuit(mgr); +} -void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - const CPlayer& player = mgr.GetPlayer(); - bool isUnmorphed = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed; - switch (msg) - { - case EScriptObjectMessage::Registered: - { - CreateGunLight(mgr); - x320_currentAuxBeam = x314_nextBeam = x310_currentBeam = mgr.GetPlayerState()->GetCurrentBeam(); - x72c_currentBeam = x738_nextBeam = x760_selectableBeams[int(x310_currentBeam)]; - x72c_currentBeam->Load(mgr, true); - x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); - x744_auxWeapon->Load(x310_currentBeam, mgr); - CAnimPlaybackParms parms(skBeamAnimIds[int(mgr.GetPlayerState()->GetCurrentBeam())], -1, 1.f, true); - x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false); - break; - } - case EScriptObjectMessage::Deleted: - DeleteGunLight(mgr); - break; - case EScriptObjectMessage::UpdateSplashInhabitant: - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed) - { - if (TCastToConstPtr water = mgr.GetObjectById(sender)) - { - if (water->GetFluidPlane().GetFluidType() == EFluidType::PhazonFluid) - { - x835_24_canFirePhazon = true; - x835_25_inPhazonBeam = true; - } - } - } - if (player.GetDistanceUnderWater() > player.GetEyeHeight()) - { - x834_27_underwater = true; - if (x744_auxWeapon->IsComboFxActive(mgr) && x310_currentBeam != CPlayerState::EBeamId::Wave) - StopContinuousBeam(mgr, false); - } - else - { - x834_27_underwater = false; - } - break; - case EScriptObjectMessage::RemoveSplashInhabitant: - x834_27_underwater = false; - x835_24_canFirePhazon = false; - break; - case EScriptObjectMessage::AddPhazonPoolInhabitant: - x835_30_inPhazonPool = true; - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed) - x835_24_canFirePhazon = true; - break; - case EScriptObjectMessage::UpdatePhazonPoolInhabitant: - x835_30_inPhazonPool = true; - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && isUnmorphed) - { - x835_24_canFirePhazon = true; - x835_25_inPhazonBeam = true; - if (x833_28_phazonBeamActive && static_cast(x72c_currentBeam)->IsFiring()) - if (TCastToPtr ent = mgr.ObjectById(sender)) - mgr.SendScriptMsg(ent.GetPtr(), x538_playerId, EScriptObjectMessage::Decrement); - } - break; - case EScriptObjectMessage::RemovePhazonPoolInhabitant: - x835_30_inPhazonPool = false; - x835_24_canFirePhazon = false; - break; - case EScriptObjectMessage::Damage: - { - bool bigStrike = false; - bool metroidAttached = false; - if (TCastToConstPtr proj = mgr.GetObjectById(sender)) - { - if ((proj->GetAttribField() & EProjectileAttrib::BigStrike) == EProjectileAttrib::BigStrike) - { - x394_damageTimer = proj->GetDamageDuration(); - bigStrike = true; - } - } - else if (TCastToConstPtr ai = mgr.GetObjectById(sender)) - { - if (ai->IsMakingBigStrike()) - { - x394_damageTimer = ai->GetDamageDuration(); - bigStrike = true; - if (player.GetAttachedActor() != kInvalidUniqueId) - metroidAttached = CPatterned::CastTo( - mgr.GetObjectById(player.GetAttachedActor())) != nullptr; - } - } - if (!x834_30_inBigStrike) - { - if (bigStrike) - { - x834_31_gunMotionInFidgetBasePosition = false; - CancelFiring(mgr); - } - TakeDamage(bigStrike, !metroidAttached, mgr); - x834_30_inBigStrike = bigStrike; - } - break; - } - case EScriptObjectMessage::OnFloor: - if (player.GetControlsFrozen() && !x834_30_inBigStrike) - { - x2f4_fireButtonStates = 0; - x2ec_lastFireButtonStates = 0; - CancelFiring(mgr); - TakeDamage(true, false, mgr); - x394_damageTimer = 0.75f; - x834_30_inBigStrike = true; - } - break; +void CPlayerGun::TouchModel(const CStateManager& mgr) { + if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) { + x73c_gunMotion->GetModelData().Touch(mgr, 0); + switch (x33c_phazonBeamState) { + case EPhazonBeamState::Entering: + if (x75c_phazonBeam) + x75c_phazonBeam->Touch(mgr); + break; + case EPhazonBeamState::Exiting: + if (x738_nextBeam) + x738_nextBeam->Touch(mgr); + break; default: - break; + if (!x833_28_phazonBeamActive) + x72c_currentBeam->Touch(mgr); + else + x75c_phazonBeam->Touch(mgr); + break; } + x72c_currentBeam->TouchHolo(mgr); + x740_grappleArm->TouchModel(mgr); + x6e0_rightHandModel.Touch(mgr, 0); + } - x740_grappleArm->AcceptScriptMsg(msg, sender, mgr); - x758_plasmaBeam->AcceptScriptMsg(msg, sender, mgr); - x75c_phazonBeam->AcceptScriptMsg(msg, sender, mgr); - x744_auxWeapon->AcceptScriptMsg(msg, sender, mgr); + if (x734_loadingBeam) { + x734_loadingBeam->Touch(mgr); + x734_loadingBeam->TouchHolo(mgr); + } } -void CPlayerGun::AsyncLoadSuit(CStateManager& mgr) -{ - x72c_currentBeam->AsyncLoadSuitArm(mgr); - x740_grappleArm->AsyncLoadSuit(mgr); +void CPlayerGun::DamageRumble(const zeus::CVector3f& location, float damage, const CStateManager& mgr) { + x398_damageAmt = damage; + x3dc_damageLocation = location; } -void CPlayerGun::TouchModel(const CStateManager& mgr) -{ - if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) - { - x73c_gunMotion->GetModelData().Touch(mgr, 0); - switch (x33c_phazonBeamState) - { - case EPhazonBeamState::Entering: - if (x75c_phazonBeam) - x75c_phazonBeam->Touch(mgr); - break; - case EPhazonBeamState::Exiting: - if (x738_nextBeam) - x738_nextBeam->Touch(mgr); - break; - default: - if (!x833_28_phazonBeamActive) - x72c_currentBeam->Touch(mgr); - else - x75c_phazonBeam->Touch(mgr); - break; - } - x72c_currentBeam->TouchHolo(mgr); - x740_grappleArm->TouchModel(mgr); - x6e0_rightHandModel.Touch(mgr, 0); - } - - if (x734_loadingBeam) - { - x734_loadingBeam->Touch(mgr); - x734_loadingBeam->TouchHolo(mgr); - } +void CPlayerGun::StopChargeSound(CStateManager& mgr) { + if (x2e0_chargeSfx) { + CSfxManager::SfxStop(x2e0_chargeSfx); + x2e0_chargeSfx.reset(); + } + if (x830_chargeRumbleHandle != -1) { + mgr.GetRumbleManager().StopRumble(x830_chargeRumbleHandle); + x830_chargeRumbleHandle = -1; + } } -void CPlayerGun::DamageRumble(const zeus::CVector3f& location, float damage, const CStateManager& mgr) -{ - x398_damageAmt = damage; - x3dc_damageLocation = location; +void CPlayerGun::ResetCharge(CStateManager& mgr, bool resetBeam) { + if (x32c_chargePhase != EChargePhase::NotCharging) + StopChargeSound(mgr); + + if ((x2f8_stateFlags & 0x8) != 0x8 && (x2f8_stateFlags & 0x10) != 0x10) { + bool doResetBeam = + mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed || resetBeam; + if (x832_27_chargeAnimStarted || doResetBeam) + PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); + if (doResetBeam) + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); + if ((x2f8_stateFlags & 0x2) != 0x2 || x330_chargeState != EChargeState::Normal) { + if ((x2f8_stateFlags & 0x8) != 0x8) { + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; + } + x318_comboAmmoIdx = 0; + x31c_missileMode = EMissleMode::Inactive; + } + } + + x32c_chargePhase = EChargePhase::NotCharging; + x330_chargeState = EChargeState::Normal; + x320_currentAuxBeam = x310_currentBeam; + x833_30_canShowAuxMuzzleEffect = true; + x832_27_chargeAnimStarted = false; + x832_26_comboFiring = false; + x344_comboXferTimer = 0.f; } -void CPlayerGun::StopChargeSound(CStateManager& mgr) -{ - if (x2e0_chargeSfx) - { - CSfxManager::SfxStop(x2e0_chargeSfx); - x2e0_chargeSfx.reset(); - } - if (x830_chargeRumbleHandle != -1) - { - mgr.GetRumbleManager().StopRumble(x830_chargeRumbleHandle); - x830_chargeRumbleHandle = -1; - } -} - -void CPlayerGun::ResetCharge(CStateManager& mgr, bool resetBeam) -{ - if (x32c_chargePhase != EChargePhase::NotCharging) - StopChargeSound(mgr); - - if ((x2f8_stateFlags & 0x8) != 0x8 && (x2f8_stateFlags & 0x10) != 0x10) - { - bool doResetBeam = mgr.GetPlayer().GetMorphballTransitionState() == - CPlayer::EPlayerMorphBallState::Morphed || resetBeam; - if (x832_27_chargeAnimStarted || doResetBeam) - PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); - if (doResetBeam) - x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); - if ((x2f8_stateFlags & 0x2) != 0x2 || x330_chargeState != EChargeState::Normal) - { - if ((x2f8_stateFlags & 0x8) != 0x8) - { - x2f8_stateFlags |= 0x1; - x2f8_stateFlags &= 0xFFE9; - } - x318_comboAmmoIdx = 0; - x31c_missileMode = EMissleMode::Inactive; - } - } - - x32c_chargePhase = EChargePhase::NotCharging; - x330_chargeState = EChargeState::Normal; - x320_currentAuxBeam = x310_currentBeam; - x833_30_canShowAuxMuzzleEffect = true; - x832_27_chargeAnimStarted = false; - x832_26_comboFiring = false; - x344_comboXferTimer = 0.f; -} - -bool CPlayerGun::ExitMissile() -{ - if ((x2f8_stateFlags & 0x1) == 0x1) - return true; - if ((x2f8_stateFlags & 0x10) == 0x10 || x338_nextState == ENextState::ExitMissile) - return false; - x338_nextState = ENextState::ExitMissile; - PlayAnim(NWeaponTypes::EGunAnimType::FromMissile, false); +bool CPlayerGun::ExitMissile() { + if ((x2f8_stateFlags & 0x1) == 0x1) + return true; + if ((x2f8_stateFlags & 0x10) == 0x10 || x338_nextState == ENextState::ExitMissile) return false; + x338_nextState = ENextState::ExitMissile; + PlayAnim(NWeaponTypes::EGunAnimType::FromMissile, false); + return false; } -static const CPlayerState::EItemType skBeamArr[] = -{ - CPlayerState::EItemType::PowerBeam, - CPlayerState::EItemType::IceBeam, - CPlayerState::EItemType::WaveBeam, - CPlayerState::EItemType::PlasmaBeam -}; +static const CPlayerState::EItemType skBeamArr[] = {CPlayerState::EItemType::PowerBeam, + CPlayerState::EItemType::IceBeam, CPlayerState::EItemType::WaveBeam, + CPlayerState::EItemType::PlasmaBeam}; -static const CPlayerState::EItemType skBeamComboArr[] = -{ - CPlayerState::EItemType::SuperMissile, - CPlayerState::EItemType::IceSpreader, - CPlayerState::EItemType::Wavebuster, - CPlayerState::EItemType::Flamethrower -}; +static const CPlayerState::EItemType skBeamComboArr[] = { + CPlayerState::EItemType::SuperMissile, CPlayerState::EItemType::IceSpreader, CPlayerState::EItemType::Wavebuster, + CPlayerState::EItemType::Flamethrower}; -static const ControlMapper::ECommands mBeamCtrlCmd[] = -{ +static const ControlMapper::ECommands mBeamCtrlCmd[] = { ControlMapper::ECommands::PowerBeam, ControlMapper::ECommands::IceBeam, ControlMapper::ECommands::WaveBeam, ControlMapper::ECommands::PlasmaBeam, }; -void CPlayerGun::HandleBeamChange(const CFinalInput& input, CStateManager& mgr) -{ - CPlayerState& playerState = *mgr.GetPlayerState(); - float maxBeamInput = 0.f; - CPlayerState::EBeamId selectBeam = CPlayerState::EBeamId::Invalid; - for (int i=0 ; i<4 ; ++i) - { - if (playerState.HasPowerUp(skBeamArr[i])) - { - float inputVal = ControlMapper::GetAnalogInput(mBeamCtrlCmd[i], input); - if (inputVal > 0.65f && inputVal > maxBeamInput) - { - maxBeamInput = inputVal; - selectBeam = CPlayerState::EBeamId(i); - } - } +void CPlayerGun::HandleBeamChange(const CFinalInput& input, CStateManager& mgr) { + CPlayerState& playerState = *mgr.GetPlayerState(); + float maxBeamInput = 0.f; + CPlayerState::EBeamId selectBeam = CPlayerState::EBeamId::Invalid; + for (int i = 0; i < 4; ++i) { + if (playerState.HasPowerUp(skBeamArr[i])) { + float inputVal = ControlMapper::GetAnalogInput(mBeamCtrlCmd[i], input); + if (inputVal > 0.65f && inputVal > maxBeamInput) { + maxBeamInput = inputVal; + selectBeam = CPlayerState::EBeamId(i); + } } + } - if (selectBeam == CPlayerState::EBeamId::Invalid) - return; + if (selectBeam == CPlayerState::EBeamId::Invalid) + return; - x833_25_ = true; - if (x310_currentBeam != selectBeam && playerState.HasPowerUp(skBeamArr[int(selectBeam)])) - { - x314_nextBeam = selectBeam; - u32 flags = 0; - if ((x2f8_stateFlags & 0x10) == 0x10) - flags = 0x10; - flags |= 0x8; - x2f8_stateFlags = flags; - PlayAnim(NWeaponTypes::EGunAnimType::FromBeam, false); - if (x833_31_inFreeLook || x744_auxWeapon->IsComboFxActive(mgr) || x832_26_comboFiring) - { - x832_30_requestReturnToDefault = true; - x740_grappleArm->EnterIdle(mgr); - } - x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); - x338_nextState = ENextState::ChangeWeapon; - x2e4_invalidSfx.reset(); + x833_25_ = true; + if (x310_currentBeam != selectBeam && playerState.HasPowerUp(skBeamArr[int(selectBeam)])) { + x314_nextBeam = selectBeam; + u32 flags = 0; + if ((x2f8_stateFlags & 0x10) == 0x10) + flags = 0x10; + flags |= 0x8; + x2f8_stateFlags = flags; + PlayAnim(NWeaponTypes::EGunAnimType::FromBeam, false); + if (x833_31_inFreeLook || x744_auxWeapon->IsComboFxActive(mgr) || x832_26_comboFiring) { + x832_30_requestReturnToDefault = true; + x740_grappleArm->EnterIdle(mgr); } - else if (playerState.HasPowerUp(skBeamArr[int(selectBeam)])) - { - if (ExitMissile()) - { - if (!CSfxManager::IsPlaying(x2e4_invalidSfx)) - x2e4_invalidSfx = NWeaponTypes::play_sfx(SFXwpn_empty_action, x834_27_underwater, false, 0.165f); - } - else - { - x2e4_invalidSfx.reset(); - } + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); + x338_nextState = ENextState::ChangeWeapon; + x2e4_invalidSfx.reset(); + } else if (playerState.HasPowerUp(skBeamArr[int(selectBeam)])) { + if (ExitMissile()) { + if (!CSfxManager::IsPlaying(x2e4_invalidSfx)) + x2e4_invalidSfx = NWeaponTypes::play_sfx(SFXwpn_empty_action, x834_27_underwater, false, 0.165f); + } else { + x2e4_invalidSfx.reset(); } + } } -void CPlayerGun::SetPhazonBeamMorph(bool intoPhazonBeam) -{ - x39c_phazonMorphT = intoPhazonBeam ? 0.f : 1.f; - x835_27_intoPhazonBeam = intoPhazonBeam; - x835_26_phazonBeamMorphing = true; +void CPlayerGun::SetPhazonBeamMorph(bool intoPhazonBeam) { + x39c_phazonMorphT = intoPhazonBeam ? 0.f : 1.f; + x835_27_intoPhazonBeam = intoPhazonBeam; + x835_26_phazonBeamMorphing = true; } -void CPlayerGun::Reset(CStateManager& mgr, bool b1) -{ - x72c_currentBeam->Reset(mgr); - x832_25_chargeEffectVisible = false; - x832_24_cancellingCharge = false; - x833_26_ = false; - x348_chargeCancelTimer = 0.f; - SetGunLightActive(false, mgr); - if ((x2f8_stateFlags & 0x10) != 0x10) - { - if (!b1 && (x2f8_stateFlags & 0x2) != 0x2) - { - if ((x2f8_stateFlags & 0x8) != 0x8) - { - x2f8_stateFlags |= 0x1; - x2f8_stateFlags &= 0xFFE9; - } - x318_comboAmmoIdx = 0; - x31c_missileMode = EMissleMode::Inactive; - } - } - else - { - x2f8_stateFlags &= ~0x7; +void CPlayerGun::Reset(CStateManager& mgr, bool b1) { + x72c_currentBeam->Reset(mgr); + x832_25_chargeEffectVisible = false; + x832_24_cancellingCharge = false; + x833_26_ = false; + x348_chargeCancelTimer = 0.f; + SetGunLightActive(false, mgr); + if ((x2f8_stateFlags & 0x10) != 0x10) { + if (!b1 && (x2f8_stateFlags & 0x2) != 0x2) { + if ((x2f8_stateFlags & 0x8) != 0x8) { + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; + } + x318_comboAmmoIdx = 0; + x31c_missileMode = EMissleMode::Inactive; } + } else { + x2f8_stateFlags &= ~0x7; + } } -void CPlayerGun::ResetBeamParams(CStateManager& mgr, const CPlayerState& playerState, bool playSelectionSfx) -{ +void CPlayerGun::ResetBeamParams(CStateManager& mgr, const CPlayerState& playerState, bool playSelectionSfx) { + StopContinuousBeam(mgr, true); + if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam)) + ResetCharge(mgr, false); + CAnimPlaybackParms parms(skBeamAnimIds[int(x314_nextBeam)], -1, 1.f, true); + x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false); + Reset(mgr, false); + if (playSelectionSfx) + CSfxManager::SfxStart(SFXwpn_morph_out_wipe, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); + x2ec_lastFireButtonStates &= ~0x1; + x320_currentAuxBeam = x310_currentBeam; + x833_30_canShowAuxMuzzleEffect = true; +} + +static const u16 skFromMissileSound[] = {SFXwpn_from_missile_power, SFXwpn_from_missile_ice, SFXwpn_from_missile_wave, + SFXwpn_from_missile_plasma}; +static const u16 skFromBeamSound[] = {SFXsfx0000, SFXwpn_from_beam_ice, SFXwpn_from_beam_wave, SFXwpn_from_beam_plasma}; +static const u16 skToMissileSound[] = {SFXwpn_to_missile_power, SFXwpn_to_missile_ice, SFXwpn_to_missile_wave, + SFXwpn_to_missile_plasma}; + +void CPlayerGun::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) { + if (x338_nextState != ENextState::ChangeWeapon) + x72c_currentBeam->PlayAnim(type, loop); + + u16 sfx = 0xffff; + switch (type) { + case NWeaponTypes::EGunAnimType::FromMissile: + x2f8_stateFlags &= ~0x4; + sfx = skFromMissileSound[int(x310_currentBeam)]; + break; + case NWeaponTypes::EGunAnimType::MissileReload: + sfx = SFXwpn_reload_missile; + break; + case NWeaponTypes::EGunAnimType::FromBeam: + sfx = skFromBeamSound[int(x310_currentBeam)]; + break; + case NWeaponTypes::EGunAnimType::ToMissile: + x2f8_stateFlags &= ~0x1; + sfx = skToMissileSound[int(x310_currentBeam)]; + break; + default: + break; + } + + if (sfx != 0xffff) + NWeaponTypes::play_sfx(sfx, x834_27_underwater, false, 0.165f); +} + +void CPlayerGun::CancelCharge(CStateManager& mgr, bool withEffect) { + if (withEffect) { + x32c_chargePhase = EChargePhase::ChargeCancelled; + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::CancelCharge); + } else { + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); + } + + x834_24_charging = false; + x348_chargeCancelTimer = 0.f; + x72c_currentBeam->ActivateCharge(false, false); + SetGunLightActive(false, mgr); +} + +void CPlayerGun::HandlePhazonBeamChange(CStateManager& mgr) { + bool inMorph = false; + switch (x33c_phazonBeamState) { + case EPhazonBeamState::Inactive: + SetPhazonBeamMorph(true); + x338_nextState = ENextState::EnterPhazonBeam; + inMorph = true; + break; + case EPhazonBeamState::Active: + if (!x835_25_inPhazonBeam) { + SetPhazonBeamMorph(true); + x338_nextState = ENextState::ExitPhazonBeam; + inMorph = true; + if (x75c_phazonBeam) { + x75c_phazonBeam->SetClipWipeActive(false); + x75c_phazonBeam->SetVeinsAlphaActive(true); + } + } + break; + default: + break; + } + + if (inMorph) { + ResetBeamParams(mgr, *mgr.GetPlayerState(), true); + x2f8_stateFlags = 0x8; + PlayAnim(NWeaponTypes::EGunAnimType::FromBeam, false); + if (x833_31_inFreeLook) { + x832_30_requestReturnToDefault = true; + x740_grappleArm->EnterIdle(mgr); + } + CancelCharge(mgr, false); + } +} + +void CPlayerGun::HandleWeaponChange(const CFinalInput& input, CStateManager& mgr) { + x833_25_ = false; + if (ControlMapper::GetPressInput(ControlMapper::ECommands::Morph, input)) StopContinuousBeam(mgr, true); - if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam)) - ResetCharge(mgr, false); - CAnimPlaybackParms parms(skBeamAnimIds[int(x314_nextBeam)], -1, 1.f, true); - x6e0_rightHandModel.AnimationData()->SetAnimation(parms, false); - Reset(mgr, false); - if (playSelectionSfx) - CSfxManager::SfxStart(SFXwpn_morph_out_wipe, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); - x2ec_lastFireButtonStates &= ~0x1; - x320_currentAuxBeam = x310_currentBeam; - x833_30_canShowAuxMuzzleEffect = true; -} - -static const u16 skFromMissileSound[] = { SFXwpn_from_missile_power, SFXwpn_from_missile_ice, - SFXwpn_from_missile_wave, SFXwpn_from_missile_plasma }; -static const u16 skFromBeamSound[] = { SFXsfx0000, SFXwpn_from_beam_ice, - SFXwpn_from_beam_wave, SFXwpn_from_beam_plasma }; -static const u16 skToMissileSound[] = { SFXwpn_to_missile_power, SFXwpn_to_missile_ice, - SFXwpn_to_missile_wave, SFXwpn_to_missile_plasma }; - -void CPlayerGun::PlayAnim(NWeaponTypes::EGunAnimType type, bool loop) -{ - if (x338_nextState != ENextState::ChangeWeapon) - x72c_currentBeam->PlayAnim(type, loop); - - u16 sfx = 0xffff; - switch (type) - { - case NWeaponTypes::EGunAnimType::FromMissile: - x2f8_stateFlags &= ~0x4; - sfx = skFromMissileSound[int(x310_currentBeam)]; - break; - case NWeaponTypes::EGunAnimType::MissileReload: - sfx = SFXwpn_reload_missile; - break; - case NWeaponTypes::EGunAnimType::FromBeam: - sfx = skFromBeamSound[int(x310_currentBeam)]; - break; - case NWeaponTypes::EGunAnimType::ToMissile: - x2f8_stateFlags &= ~0x1; - sfx = skToMissileSound[int(x310_currentBeam)]; - break; - default: - break; - } - - if (sfx != 0xffff) - NWeaponTypes::play_sfx(sfx, x834_27_underwater, false, 0.165f); -} - -void CPlayerGun::CancelCharge(CStateManager& mgr, bool withEffect) -{ - if (withEffect) - { - x32c_chargePhase = EChargePhase::ChargeCancelled; - x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::CancelCharge); - } + if ((x2f8_stateFlags & 0x8) != 0x8) { + if (!x835_25_inPhazonBeam) + HandleBeamChange(input, mgr); else - { - x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); - } + HandlePhazonBeamChange(mgr); + } +} - x834_24_charging = false; - x348_chargeCancelTimer = 0.f; +void CPlayerGun::ProcessInput(const CFinalInput& input, CStateManager& mgr) { + CPlayerState& state = *mgr.GetPlayerState(); + bool damageNotMorphed = + (x834_30_inBigStrike && mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed); + if (x832_24_cancellingCharge || damageNotMorphed || (x2f8_stateFlags & 0x8) == 0x8) + return; + if (state.HasPowerUp(CPlayerState::EItemType::ChargeBeam)) { + if (!state.ItemEnabled(CPlayerState::EItemType::ChargeBeam)) + state.EnableItem(CPlayerState::EItemType::ChargeBeam); + } else if (state.ItemEnabled(CPlayerState::EItemType::ChargeBeam)) { + state.DisableItem(CPlayerState::EItemType::ChargeBeam); + ResetCharge(mgr, false); + } + switch (mgr.GetPlayer().GetMorphballTransitionState()) { + default: + x2f4_fireButtonStates = 0; + break; + case CPlayer::EPlayerMorphBallState::Unmorphed: + if ((x2f8_stateFlags & 0x10) != 0x10) + HandleWeaponChange(input, mgr); + case CPlayer::EPlayerMorphBallState::Morphed: + x2f4_fireButtonStates = ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) ? 1 : 0; + x2f4_fireButtonStates |= + ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) ? 2 : 0; + break; + } +} + +void CPlayerGun::UnLoadFidget() { + if ((x2fc_fidgetAnimBits & 0x1) == 0x1) + x73c_gunMotion->GunController().UnLoadFidget(); + if ((x2fc_fidgetAnimBits & 0x2) == 0x2) + x72c_currentBeam->UnLoadFidget(); + if ((x2fc_fidgetAnimBits & 0x4) == 0x4) + if (CGunController* gc = x740_grappleArm->GunController()) + gc->UnLoadFidget(); + x2fc_fidgetAnimBits = 0; +} + +void CPlayerGun::ReturnArmAndGunToDefault(CStateManager& mgr, bool returnToDefault) { + if (returnToDefault || !x833_31_inFreeLook) { + x73c_gunMotion->ReturnToDefault(mgr, false); + x740_grappleArm->ReturnToDefault(mgr, 0.f, false); + } + if (!x834_25_gunMotionFidgeting) + x72c_currentBeam->ReturnToDefault(mgr); + x834_25_gunMotionFidgeting = false; +} + +void CPlayerGun::ReturnToRestPose() { + if (x832_31_inRestPose) + return; + if ((x2f8_stateFlags & 0x1) == 0x1) + PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); + else if ((x2f8_stateFlags & 0x4) == 0x4) + PlayAnim(NWeaponTypes::EGunAnimType::ToMissile, false); + x832_31_inRestPose = true; +} + +void CPlayerGun::ResetIdle(CStateManager& mgr) { + x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::GunFireNoBob, mgr); + if (x3a4_fidget.GetState() != CFidget::EState::NoFidget) { + if (x3a4_fidget.GetState() == CFidget::EState::Loading) + UnLoadFidget(); + ReturnArmAndGunToDefault(mgr, true); + } + x3a4_fidget.ResetAll(); + ReturnToRestPose(); + if (x324_idleState != EIdleState::NotIdle) + x324_idleState = EIdleState::NotIdle; + if (!x740_grappleArm->GetActive()) + x834_26_animPlaying = false; +} + +void CPlayerGun::CancelFiring(CStateManager& mgr) { + if (x32c_chargePhase == EChargePhase::ComboFireDone) + ReturnArmAndGunToDefault(mgr, true); + if ((x2f8_stateFlags & 0x10) == 0x10) { + StopContinuousBeam(mgr, true); + if ((x2f8_stateFlags & 0x8) == 0x8) { + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; + } + x318_comboAmmoIdx = 0; + x31c_missileMode = EMissleMode::Inactive; + } + if (x32c_chargePhase != EChargePhase::NotCharging) { x72c_currentBeam->ActivateCharge(false, false); SetGunLightActive(false, mgr); + ResetCharge(mgr, true); + } + Reset(mgr, (x2f8_stateFlags & 0x2) == 0x2); } -void CPlayerGun::HandlePhazonBeamChange(CStateManager& mgr) -{ - bool inMorph = false; - switch (x33c_phazonBeamState) - { - case EPhazonBeamState::Inactive: - SetPhazonBeamMorph(true); - x338_nextState = ENextState::EnterPhazonBeam; - inMorph = true; - break; - case EPhazonBeamState::Active: - if (!x835_25_inPhazonBeam) - { - SetPhazonBeamMorph(true); - x338_nextState = ENextState::ExitPhazonBeam; - inMorph = true; - if (x75c_phazonBeam) - { - x75c_phazonBeam->SetClipWipeActive(false); - x75c_phazonBeam->SetVeinsAlphaActive(true); - } - } - break; +float CPlayerGun::GetBeamVelocity() const { + if (x72c_currentBeam->IsLoaded()) + return x72c_currentBeam->GetVelocityInfo().GetVelocity(int(x330_chargeState)).y(); + return 10.f; +} + +void CPlayerGun::StopContinuousBeam(CStateManager& mgr, bool b1) { + if ((x2f8_stateFlags & 0x10) == 0x10) { + ReturnArmAndGunToDefault(mgr, false); + x744_auxWeapon->StopComboFx(mgr, b1); + switch (x310_currentBeam) { + case CPlayerState::EBeamId::Power: + case CPlayerState::EBeamId::Wave: + case CPlayerState::EBeamId::Plasma: + // All except ice + if (x310_currentBeam != CPlayerState::EBeamId::Power || x833_28_phazonBeamActive) { + x72c_currentBeam->EnableSecondaryFx(b1 ? CGunWeapon::ESecondaryFxType::None + : CGunWeapon::ESecondaryFxType::CancelCharge); + } + break; default: - break; + break; } + } else if (x833_28_phazonBeamActive) { + if (static_cast(x72c_currentBeam)->IsFiring()) + static_cast(x72c_currentBeam)->StopBeam(mgr, b1); + } else if (x310_currentBeam == CPlayerState::EBeamId::Plasma) // Plasma + { + if (static_cast(x72c_currentBeam)->IsFiring()) + static_cast(x72c_currentBeam)->StopBeam(mgr, b1); + } +} - if (inMorph) - { - ResetBeamParams(mgr, *mgr.GetPlayerState(), true); - x2f8_stateFlags = 0x8; - PlayAnim(NWeaponTypes::EGunAnimType::FromBeam, false); - if (x833_31_inFreeLook) - { - x832_30_requestReturnToDefault = true; - x740_grappleArm->EnterIdle(mgr); +void CPlayerGun::CMotionState::Update(bool firing, float dt, zeus::CTransform& xf, CStateManager& mgr) { + if (firing) { + x24_fireState = EFireState::StartFire; + x8_fireTime = 0.f; + } else if (x24_fireState != EFireState::NotFiring) { + if (x8_fireTime > dt) + x24_fireState = EFireState::Firing; + x8_fireTime += dt; + } + + if (x0_24_extendParabola && x20_state == EMotionState::LockOn) { + float extendT = xc_curExtendDist / gGunExtendDistance; + xf = xf * zeus::CTransform::RotateZ(zeus::degToRad(extendT * -4.f * (extendT - 1.f) * 15.f)); + } else { + if (x24_fireState == EFireState::StartFire || x24_fireState == EFireState::Firing) { + if (std::fabs(x14_rotationT - 1.f) < 0.1f) { + x18_startRotation = x1c_endRotation; + x14_rotationT = 0.f; + if (x24_fireState == EFireState::StartFire) { + x1c_endRotation = mgr.GetActiveRandom()->Next() % 15; + x1c_endRotation *= (mgr.GetActiveRandom()->Next() % 100) > 45 ? 1.f : -1.f; + } else { + x1c_endRotation = 0.f; + if (x18_startRotation == x1c_endRotation) { + x10_curRotation = x1c_endRotation; + x24_fireState = EFireState::NotFiring; + } } - CancelCharge(mgr, false); + } else { + x10_curRotation = (x1c_endRotation - x18_startRotation) * x14_rotationT + x18_startRotation; + } + + x14_rotationT += (1.f - x14_rotationT) * 0.8f * (10.f * dt); + zeus::CTransform tmpXf = + zeus::CQuaternion::fromAxisAngle(xf.basis[1], zeus::degToRad(x10_curRotation)).toTransform() * + xf.getRotation(); + tmpXf.origin = xf.origin; + xf = tmpXf * zeus::CTransform::Translate(0.f, xc_curExtendDist, 0.f); + } else { + xf = xf * zeus::CTransform::Translate(0.f, xc_curExtendDist, 0.f); } + } + + switch (x20_state) { + case EMotionState::LockOn: + xc_curExtendDist += 3.f * dt; + if (xc_curExtendDist > gGunExtendDistance) { + xc_curExtendDist = gGunExtendDistance; + x20_state = EMotionState::One; + x0_24_extendParabola = false; + } + break; + case EMotionState::CancelLockOn: + xc_curExtendDist -= 3.f * dt; + if (xc_curExtendDist < 0.f) { + xc_curExtendDist = 0.f; + x20_state = EMotionState::Zero; + } + break; + default: + break; + } + + if (!x0_24_extendParabola) { + if (x4_extendParabolaDelayTimer < 30.f) { + x4_extendParabolaDelayTimer += dt; + } else { + x0_24_extendParabola = true; + x4_extendParabolaDelayTimer = 0.f; + } + } } -void CPlayerGun::HandleWeaponChange(const CFinalInput& input, CStateManager& mgr) -{ - x833_25_ = false; - if (ControlMapper::GetPressInput(ControlMapper::ECommands::Morph, input)) - StopContinuousBeam(mgr, true); - if ((x2f8_stateFlags & 0x8) != 0x8) - { - if (!x835_25_inPhazonBeam) - HandleBeamChange(input, mgr); - else - HandlePhazonBeamChange(mgr); - } -} +void CPlayerGun::ChangeWeapon(const CPlayerState& playerState, CStateManager& mgr) { + if (x730_outgoingBeam != nullptr && x72c_currentBeam != x730_outgoingBeam) + x730_outgoingBeam->Unload(mgr); -void CPlayerGun::ProcessInput(const CFinalInput& input, CStateManager& mgr) -{ - CPlayerState& state = *mgr.GetPlayerState(); - bool damageNotMorphed = (x834_30_inBigStrike && - mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed); - if (x832_24_cancellingCharge || damageNotMorphed || (x2f8_stateFlags & 0x8) == 0x8) - return; - if (state.HasPowerUp(CPlayerState::EItemType::ChargeBeam)) - { - if (!state.ItemEnabled(CPlayerState::EItemType::ChargeBeam)) - state.EnableItem(CPlayerState::EItemType::ChargeBeam); - } - else if (state.ItemEnabled(CPlayerState::EItemType::ChargeBeam)) - { - state.DisableItem(CPlayerState::EItemType::ChargeBeam); - ResetCharge(mgr, false); - } - switch (mgr.GetPlayer().GetMorphballTransitionState()) - { - default: - x2f4_fireButtonStates = 0; - break; - case CPlayer::EPlayerMorphBallState::Unmorphed: - if ((x2f8_stateFlags & 0x10) != 0x10) - HandleWeaponChange(input, mgr); - case CPlayer::EPlayerMorphBallState::Morphed: - x2f4_fireButtonStates = - ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) ? 1 : 0; - x2f4_fireButtonStates |= - ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) ? 2 : 0; - break; - } -} + x734_loadingBeam = x760_selectableBeams[int(x314_nextBeam)]; + if (x734_loadingBeam && x72c_currentBeam != x734_loadingBeam) { + x734_loadingBeam->Load(mgr, false); + x744_auxWeapon->Load(x314_nextBeam, mgr); + } -void CPlayerGun::UnLoadFidget() -{ - if ((x2fc_fidgetAnimBits & 0x1) == 0x1) - x73c_gunMotion->GunController().UnLoadFidget(); - if ((x2fc_fidgetAnimBits & 0x2) == 0x2) - x72c_currentBeam->UnLoadFidget(); - if ((x2fc_fidgetAnimBits & 0x4) == 0x4) - if (CGunController* gc = x740_grappleArm->GunController()) - gc->UnLoadFidget(); - x2fc_fidgetAnimBits = 0; -} - -void CPlayerGun::ReturnArmAndGunToDefault(CStateManager& mgr, bool returnToDefault) -{ - if (returnToDefault || !x833_31_inFreeLook) - { - x73c_gunMotion->ReturnToDefault(mgr, false); - x740_grappleArm->ReturnToDefault(mgr, 0.f, false); - } - if (!x834_25_gunMotionFidgeting) - x72c_currentBeam->ReturnToDefault(mgr); - x834_25_gunMotionFidgeting = false; -} - -void CPlayerGun::ReturnToRestPose() -{ - if (x832_31_inRestPose) - return; - if ((x2f8_stateFlags & 0x1) == 0x1) - PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); - else if ((x2f8_stateFlags & 0x4) == 0x4) - PlayAnim(NWeaponTypes::EGunAnimType::ToMissile, false); - x832_31_inRestPose = true; -} - -void CPlayerGun::ResetIdle(CStateManager& mgr) -{ - x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::GunFireNoBob, mgr); - if (x3a4_fidget.GetState() != CFidget::EState::NoFidget) - { - if (x3a4_fidget.GetState() == CFidget::EState::Loading) - UnLoadFidget(); - ReturnArmAndGunToDefault(mgr, true); - } - x3a4_fidget.ResetAll(); - ReturnToRestPose(); - if (x324_idleState != EIdleState::NotIdle) - x324_idleState = EIdleState::NotIdle; - if (!x740_grappleArm->GetActive()) - x834_26_animPlaying = false; -} - -void CPlayerGun::CancelFiring(CStateManager& mgr) -{ - if (x32c_chargePhase == EChargePhase::ComboFireDone) - ReturnArmAndGunToDefault(mgr, true); - if ((x2f8_stateFlags & 0x10) == 0x10) - { - StopContinuousBeam(mgr, true); - if ((x2f8_stateFlags & 0x8) == 0x8) - { - x2f8_stateFlags |= 0x1; - x2f8_stateFlags &= 0xFFE9; - } - x318_comboAmmoIdx = 0; - x31c_missileMode = EMissleMode::Inactive; - } - if (x32c_chargePhase != EChargePhase::NotCharging) - { - x72c_currentBeam->ActivateCharge(false, false); - SetGunLightActive(false, mgr); - ResetCharge(mgr, true); - } - Reset(mgr, (x2f8_stateFlags & 0x2) == 0x2); -} - -float CPlayerGun::GetBeamVelocity() const -{ - if (x72c_currentBeam->IsLoaded()) - return x72c_currentBeam->GetVelocityInfo().GetVelocity(int(x330_chargeState)).y(); - return 10.f; -} - -void CPlayerGun::StopContinuousBeam(CStateManager& mgr, bool b1) -{ - if ((x2f8_stateFlags & 0x10) == 0x10) - { - ReturnArmAndGunToDefault(mgr, false); - x744_auxWeapon->StopComboFx(mgr, b1); - switch (x310_currentBeam) - { - case CPlayerState::EBeamId::Power: - case CPlayerState::EBeamId::Wave: - case CPlayerState::EBeamId::Plasma: - // All except ice - if (x310_currentBeam != CPlayerState::EBeamId::Power || x833_28_phazonBeamActive) - { - x72c_currentBeam->EnableSecondaryFx( - b1 ? CGunWeapon::ESecondaryFxType::None : CGunWeapon::ESecondaryFxType::CancelCharge); - } - break; - default: - break; - } - } - else if (x833_28_phazonBeamActive) - { - if (static_cast(x72c_currentBeam)->IsFiring()) - static_cast(x72c_currentBeam)->StopBeam(mgr, b1); - } - else if (x310_currentBeam == CPlayerState::EBeamId::Plasma) // Plasma - { - if (static_cast(x72c_currentBeam)->IsFiring()) - static_cast(x72c_currentBeam)->StopBeam(mgr, b1); - } -} - -void CPlayerGun::CMotionState::Update(bool firing, float dt, zeus::CTransform& xf, CStateManager& mgr) -{ - if (firing) - { - x24_fireState = EFireState::StartFire; - x8_fireTime = 0.f; - } - else if (x24_fireState != EFireState::NotFiring) - { - if (x8_fireTime > dt) - x24_fireState = EFireState::Firing; - x8_fireTime += dt; - } - - if (x0_24_extendParabola && x20_state == EMotionState::LockOn) - { - float extendT = xc_curExtendDist / gGunExtendDistance; - xf = xf * zeus::CTransform::RotateZ(zeus::degToRad(extendT * -4.f * (extendT - 1.f) * 15.f)); - } - else - { - if (x24_fireState == EFireState::StartFire || x24_fireState == EFireState::Firing) - { - if (std::fabs(x14_rotationT - 1.f) < 0.1f) - { - x18_startRotation = x1c_endRotation; - x14_rotationT = 0.f; - if (x24_fireState == EFireState::StartFire) - { - x1c_endRotation = mgr.GetActiveRandom()->Next() % 15; - x1c_endRotation *= (mgr.GetActiveRandom()->Next() % 100) > 45 ? 1.f : -1.f; - } - else - { - x1c_endRotation = 0.f; - if (x18_startRotation == x1c_endRotation) - { - x10_curRotation = x1c_endRotation; - x24_fireState = EFireState::NotFiring; - } - } - } - else - { - x10_curRotation = (x1c_endRotation - x18_startRotation) * x14_rotationT + x18_startRotation; - } - - x14_rotationT += (1.f - x14_rotationT) * 0.8f * (10.f * dt); - zeus::CTransform tmpXf = - zeus::CQuaternion::fromAxisAngle(xf.basis[1], zeus::degToRad(x10_curRotation)).toTransform() * - xf.getRotation(); - tmpXf.origin = xf.origin; - xf = tmpXf * zeus::CTransform::Translate(0.f, xc_curExtendDist, 0.f); - } - else - { - xf = xf * zeus::CTransform::Translate(0.f, xc_curExtendDist, 0.f); - } - } - - switch (x20_state) - { - case EMotionState::LockOn: - xc_curExtendDist += 3.f * dt; - if (xc_curExtendDist > gGunExtendDistance) - { - xc_curExtendDist = gGunExtendDistance; - x20_state = EMotionState::One; - x0_24_extendParabola = false; - } - break; - case EMotionState::CancelLockOn: - xc_curExtendDist -= 3.f * dt; - if (xc_curExtendDist < 0.f) - { - xc_curExtendDist = 0.f; - x20_state = EMotionState::Zero; - } - break; - default: - break; - } - - if (!x0_24_extendParabola) - { - if (x4_extendParabolaDelayTimer < 30.f) - { - x4_extendParabolaDelayTimer += dt; - } - else - { - x0_24_extendParabola = true; - x4_extendParabolaDelayTimer = 0.f; - } - } -} - -void CPlayerGun::ChangeWeapon(const CPlayerState& playerState, CStateManager& mgr) -{ - if (x730_outgoingBeam != nullptr && x72c_currentBeam != x730_outgoingBeam) - x730_outgoingBeam->Unload(mgr); - - x734_loadingBeam = x760_selectableBeams[int(x314_nextBeam)]; - if (x734_loadingBeam && x72c_currentBeam != x734_loadingBeam) - { - x734_loadingBeam->Load(mgr, false); - x744_auxWeapon->Load(x314_nextBeam, mgr); - } - - x72c_currentBeam->EnableFx(false); - x834_28_requestImmediateRecharge = x32c_chargePhase != EChargePhase::NotCharging; - ResetBeamParams(mgr, playerState, true); - x678_morph.StartWipe(CGunMorph::EDir::In); + x72c_currentBeam->EnableFx(false); + x834_28_requestImmediateRecharge = x32c_chargePhase != EChargePhase::NotCharging; + ResetBeamParams(mgr, playerState, true); + x678_morph.StartWipe(CGunMorph::EDir::In); } void CPlayerGun::GetLctrWithShake(zeus::CTransform& xfOut, const CModelData& mData, std::string_view lctrName, - bool shake, bool dyn) -{ - if (dyn) - xfOut = mData.GetScaledLocatorTransformDynamic(lctrName, nullptr); - else - xfOut = mData.GetScaledLocatorTransform(lctrName); + bool shake, bool dyn) { + if (dyn) + xfOut = mData.GetScaledLocatorTransformDynamic(lctrName, nullptr); + else + xfOut = mData.GetScaledLocatorTransform(lctrName); - if (x834_24_charging && shake) - xfOut.origin += zeus::CVector3f(x34c_shakeX, 0.f, x350_shakeZ); + if (x834_24_charging && shake) + xfOut.origin += zeus::CVector3f(x34c_shakeX, 0.f, x350_shakeZ); } -void CPlayerGun::UpdateLeftArmTransform(const CModelData& mData, const CStateManager& mgr) -{ - if (x834_26_animPlaying) - x740_grappleArm->AuxTransform() = zeus::CTransform::Identity(); - else - GetLctrWithShake(x740_grappleArm->AuxTransform(), mData, "elbow", true, false); +void CPlayerGun::UpdateLeftArmTransform(const CModelData& mData, const CStateManager& mgr) { + if (x834_26_animPlaying) + x740_grappleArm->AuxTransform() = zeus::CTransform::Identity(); + else + GetLctrWithShake(x740_grappleArm->AuxTransform(), mData, "elbow", true, false); - x740_grappleArm->AuxTransform().origin = x740_grappleArm->AuxTransform() * zeus::CVector3f(-0.9f, -0.4f, 0.4f); - x740_grappleArm->SetTransform(x3e8_xf); + x740_grappleArm->AuxTransform().origin = x740_grappleArm->AuxTransform() * zeus::CVector3f(-0.9f, -0.4f, 0.4f); + x740_grappleArm->SetTransform(x3e8_xf); } -CPlayerGun::CGunMorph::EMorphEvent CPlayerGun::CGunMorph::Update(float inY, float outY, float dt) -{ - EMorphEvent ret = EMorphEvent::None; +CPlayerGun::CGunMorph::EMorphEvent CPlayerGun::CGunMorph::Update(float inY, float outY, float dt) { + EMorphEvent ret = EMorphEvent::None; - if (x20_gunState == EGunState::InWipeDone) - { - x14_remHoldTime -= dt; - if (x14_remHoldTime <= 0.f && x24_25_weaponChanged) - { - StartWipe(EDir::Out); - x24_25_weaponChanged = false; - x14_remHoldTime = 0.f; - ret = EMorphEvent::InWipeDone; - } + if (x20_gunState == EGunState::InWipeDone) { + x14_remHoldTime -= dt; + if (x14_remHoldTime <= 0.f && x24_25_weaponChanged) { + StartWipe(EDir::Out); + x24_25_weaponChanged = false; + x14_remHoldTime = 0.f; + ret = EMorphEvent::InWipeDone; + } + } + + if (x24_24_morphing) { + float omt = x8_remTime * xc_speed; + float t = 1.f - omt; + if (x1c_dir == EDir::In) { + x0_yLerp = omt * outY + t * inY; + x18_transitionFactor = omt; + } else { + x0_yLerp = omt * inY + t * outY; + x18_transitionFactor = t; } - if (x24_24_morphing) - { - float omt = x8_remTime * xc_speed; - float t = 1.f - omt; - if (x1c_dir == EDir::In) - { - x0_yLerp = omt * outY + t * inY; - x18_transitionFactor = omt; - } - else - { - x0_yLerp = omt * inY + t * outY; - x18_transitionFactor = t; - } - - if (x8_remTime <= 0.f) - { - x24_24_morphing = false; - x8_remTime = 0.f; - if (x1c_dir == EDir::In) - { - x20_gunState = EGunState::InWipeDone; - x18_transitionFactor = 0.f; - } - else - { - x18_transitionFactor = 1.f; - x20_gunState = EGunState::OutWipeDone; - x1c_dir = EDir::Done; - ret = EMorphEvent::OutWipeDone; - } - } - else - { - x8_remTime -= dt; - } + if (x8_remTime <= 0.f) { + x24_24_morphing = false; + x8_remTime = 0.f; + if (x1c_dir == EDir::In) { + x20_gunState = EGunState::InWipeDone; + x18_transitionFactor = 0.f; + } else { + x18_transitionFactor = 1.f; + x20_gunState = EGunState::OutWipeDone; + x1c_dir = EDir::Done; + ret = EMorphEvent::OutWipeDone; + } + } else { + x8_remTime -= dt; } + } - return ret; + return ret; } -void CPlayerGun::CGunMorph::StartWipe(EDir dir) -{ - x14_remHoldTime = x10_holoHoldTime; - if (dir == EDir::In && x20_gunState == EGunState::InWipeDone) - return; +void CPlayerGun::CGunMorph::StartWipe(EDir dir) { + x14_remHoldTime = x10_holoHoldTime; + if (dir == EDir::In && x20_gunState == EGunState::InWipeDone) + return; - if (dir != x1c_dir && x20_gunState != EGunState::OutWipe) - { - x8_remTime = x4_gunTransformTime; - xc_speed = 1.f / x4_gunTransformTime; - } - else if (x20_gunState != EGunState::InWipe) - { - x8_remTime = x4_gunTransformTime - x8_remTime; - } + if (dir != x1c_dir && x20_gunState != EGunState::OutWipe) { + x8_remTime = x4_gunTransformTime; + xc_speed = 1.f / x4_gunTransformTime; + } else if (x20_gunState != EGunState::InWipe) { + x8_remTime = x4_gunTransformTime - x8_remTime; + } - x1c_dir = dir; - x20_gunState = x1c_dir == EDir::In ? EGunState::InWipe : EGunState::OutWipe; - x24_24_morphing = true; + x1c_dir = dir; + x20_gunState = x1c_dir == EDir::In ? EGunState::InWipe : EGunState::OutWipe; + x24_24_morphing = true; } -static const u16 skIntoBeamSound[] = { SFXsfx0000, SFXwpn_into_beam_ice, - SFXwpn_into_beam_wave, SFXwpn_into_beam_plasma }; +static const u16 skIntoBeamSound[] = {SFXsfx0000, SFXwpn_into_beam_ice, SFXwpn_into_beam_wave, SFXwpn_into_beam_plasma}; -void CPlayerGun::ProcessGunMorph(float dt, CStateManager& mgr) -{ - bool isUnmorphed = mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed; - switch (x678_morph.GetGunState()) - { - case CGunMorph::EGunState::InWipeDone: - if (x310_currentBeam != x314_nextBeam && x734_loadingBeam != nullptr) - { - if (!isUnmorphed) - x734_loadingBeam->Touch(mgr); - if (x734_loadingBeam->IsLoaded() && x744_auxWeapon->IsLoaded()) - { - x730_outgoingBeam = (x734_loadingBeam == x72c_currentBeam ? nullptr : x72c_currentBeam); - x734_loadingBeam = nullptr; - x310_currentBeam = x314_nextBeam; - x320_currentAuxBeam = x314_nextBeam; - x833_30_canShowAuxMuzzleEffect = true; - x72c_currentBeam = x760_selectableBeams[int(x314_nextBeam)]; - x738_nextBeam = x72c_currentBeam; - x678_morph.SetWeaponChanged(); - mgr.GetPlayerState()->SetCurrentBeam(x314_nextBeam); - } - } - break; - case CGunMorph::EGunState::InWipe: - case CGunMorph::EGunState::OutWipe: - x774_holoTransitionGen->SetGlobalScale(sGunScale); - x774_holoTransitionGen->SetGlobalTranslation(zeus::CVector3f(0.f, x678_morph.GetYLerp(), 0.f)); - x774_holoTransitionGen->Update(dt); - break; - default: - break; +void CPlayerGun::ProcessGunMorph(float dt, CStateManager& mgr) { + bool isUnmorphed = mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed; + switch (x678_morph.GetGunState()) { + case CGunMorph::EGunState::InWipeDone: + if (x310_currentBeam != x314_nextBeam && x734_loadingBeam != nullptr) { + if (!isUnmorphed) + x734_loadingBeam->Touch(mgr); + if (x734_loadingBeam->IsLoaded() && x744_auxWeapon->IsLoaded()) { + x730_outgoingBeam = (x734_loadingBeam == x72c_currentBeam ? nullptr : x72c_currentBeam); + x734_loadingBeam = nullptr; + x310_currentBeam = x314_nextBeam; + x320_currentAuxBeam = x314_nextBeam; + x833_30_canShowAuxMuzzleEffect = true; + x72c_currentBeam = x760_selectableBeams[int(x314_nextBeam)]; + x738_nextBeam = x72c_currentBeam; + x678_morph.SetWeaponChanged(); + mgr.GetPlayerState()->SetCurrentBeam(x314_nextBeam); + } } + break; + case CGunMorph::EGunState::InWipe: + case CGunMorph::EGunState::OutWipe: + x774_holoTransitionGen->SetGlobalScale(sGunScale); + x774_holoTransitionGen->SetGlobalTranslation(zeus::CVector3f(0.f, x678_morph.GetYLerp(), 0.f)); + x774_holoTransitionGen->Update(dt); + break; + default: + break; + } - switch (x678_morph.Update(0.2f, 1.292392f, dt)) - { - case CGunMorph::EMorphEvent::InWipeDone: - CSfxManager::SfxStart(SFXwpn_morph_in_wipe_done, 1.f, 0.f, true, 0x74, false, kInvalidAreaId); - break; - case CGunMorph::EMorphEvent::OutWipeDone: - if (x730_outgoingBeam != nullptr && x72c_currentBeam != x730_outgoingBeam) - { - x730_outgoingBeam->Unload(mgr); - x730_outgoingBeam = nullptr; - } - if (isUnmorphed) - NWeaponTypes::play_sfx(skIntoBeamSound[int(x310_currentBeam)], x834_27_underwater, false, 0.165f); - x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); - x72c_currentBeam->EnableFx(true); - PlayAnim(NWeaponTypes::EGunAnimType::ToBeam, false); - if (x833_31_inFreeLook) - EnterFreeLook(mgr); - else if (x832_30_requestReturnToDefault) - ReturnArmAndGunToDefault(mgr, false); - if (x834_28_requestImmediateRecharge || (x2ec_lastFireButtonStates & 0x1) != 0) - { - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - x32c_chargePhase = EChargePhase::ChargeRequested; - x834_28_requestImmediateRecharge = false; - } - x832_30_requestReturnToDefault = false; - x338_nextState = ENextState::SetupBeam; - break; - default: - break; + switch (x678_morph.Update(0.2f, 1.292392f, dt)) { + case CGunMorph::EMorphEvent::InWipeDone: + CSfxManager::SfxStart(SFXwpn_morph_in_wipe_done, 1.f, 0.f, true, 0x74, false, kInvalidAreaId); + break; + case CGunMorph::EMorphEvent::OutWipeDone: + if (x730_outgoingBeam != nullptr && x72c_currentBeam != x730_outgoingBeam) { + x730_outgoingBeam->Unload(mgr); + x730_outgoingBeam = nullptr; } -} - -void CPlayerGun::SetPhazonBeamFeedback(bool active) -{ - const char16_t* str = g_MainStringTable->GetString(21); // Hyper-mode - CHUDMemoParms parms(5.f, true, !active, false); - MP1::CSamusHud::DisplayHudMemo(str, parms); - if (CSfxManager::IsPlaying(x2e8_phazonBeamSfx)) - CSfxManager::SfxStop(x2e8_phazonBeamSfx); - x2e8_phazonBeamSfx.reset(); - if (active) - x2e8_phazonBeamSfx = NWeaponTypes::play_sfx(SFXphg_charge_lp, x834_27_underwater, false, 0.165f); -} - -void CPlayerGun::StartPhazonBeamTransition(bool active, CStateManager& mgr, CPlayerState& playerState) -{ - if (x833_28_phazonBeamActive == active) - return; - x760_selectableBeams[int(x310_currentBeam)]->Unload(mgr); - x760_selectableBeams[int(x310_currentBeam)] = active ? x75c_phazonBeam.get() : x738_nextBeam; - ResetBeamParams(mgr, playerState, false); - x72c_currentBeam = x760_selectableBeams[int(x310_currentBeam)]; - x833_28_phazonBeamActive = active; - SetPhazonBeamFeedback(active); + if (isUnmorphed) + NWeaponTypes::play_sfx(skIntoBeamSound[int(x310_currentBeam)], x834_27_underwater, false, 0.165f); x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); x72c_currentBeam->EnableFx(true); - x72c_currentBeam->SetDrawHologram(false); PlayAnim(NWeaponTypes::EGunAnimType::ToBeam, false); if (x833_31_inFreeLook) - EnterFreeLook(mgr); + EnterFreeLook(mgr); else if (x832_30_requestReturnToDefault) - ReturnArmAndGunToDefault(mgr, false); + ReturnArmAndGunToDefault(mgr, false); + if (x834_28_requestImmediateRecharge || (x2ec_lastFireButtonStates & 0x1) != 0) { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) + x32c_chargePhase = EChargePhase::ChargeRequested; + x834_28_requestImmediateRecharge = false; + } x832_30_requestReturnToDefault = false; + x338_nextState = ENextState::SetupBeam; + break; + default: + break; + } } -void CPlayerGun::ProcessPhazonGunMorph(float dt, CStateManager& mgr) -{ - if (x835_26_phazonBeamMorphing) - { - if (x835_27_intoPhazonBeam) - { - x39c_phazonMorphT += 15.f * dt; - if (x39c_phazonMorphT > 1.f) - x39c_phazonMorphT = 1.f; - } - else - { - x39c_phazonMorphT -= 2.f * dt; - if (x39c_phazonMorphT < 0.f) - { - x835_26_phazonBeamMorphing = false; - x39c_phazonMorphT = 0.f; - } - } - } - - switch (x33c_phazonBeamState) - { - case EPhazonBeamState::Entering: - if (x75c_phazonBeam) - { - x75c_phazonBeam->Update(dt, mgr); - if (x75c_phazonBeam->IsLoaded()) - { - StartPhazonBeamTransition(true, mgr, *mgr.GetPlayerState()); - SetPhazonBeamMorph(false); - x33c_phazonBeamState = EPhazonBeamState::Active; - x338_nextState = ENextState::SetupBeam; - } - } - break; - case EPhazonBeamState::Exiting: - if (x738_nextBeam) - { - x738_nextBeam->Update(dt, mgr); - if (x738_nextBeam->IsLoaded()) - { - x835_25_inPhazonBeam = false; - StartPhazonBeamTransition(false, mgr, *mgr.GetPlayerState()); - SetPhazonBeamMorph(false); - x33c_phazonBeamState = EPhazonBeamState::Inactive; - x338_nextState = ENextState::SetupBeam; - } - } - break; - default: - break; - } +void CPlayerGun::SetPhazonBeamFeedback(bool active) { + const char16_t* str = g_MainStringTable->GetString(21); // Hyper-mode + CHUDMemoParms parms(5.f, true, !active, false); + MP1::CSamusHud::DisplayHudMemo(str, parms); + if (CSfxManager::IsPlaying(x2e8_phazonBeamSfx)) + CSfxManager::SfxStop(x2e8_phazonBeamSfx); + x2e8_phazonBeamSfx.reset(); + if (active) + x2e8_phazonBeamSfx = NWeaponTypes::play_sfx(SFXphg_charge_lp, x834_27_underwater, false, 0.165f); } -void CPlayerGun::EnableChargeFx(EChargeState state, CStateManager& mgr) -{ - x72c_currentBeam->ActivateCharge(true, false); - SetGunLightActive(true, mgr); - x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Charge); - StopContinuousBeam(mgr, false); +void CPlayerGun::StartPhazonBeamTransition(bool active, CStateManager& mgr, CPlayerState& playerState) { + if (x833_28_phazonBeamActive == active) + return; + x760_selectableBeams[int(x310_currentBeam)]->Unload(mgr); + x760_selectableBeams[int(x310_currentBeam)] = active ? x75c_phazonBeam.get() : x738_nextBeam; + ResetBeamParams(mgr, playerState, false); + x72c_currentBeam = x760_selectableBeams[int(x310_currentBeam)]; + x833_28_phazonBeamActive = active; + SetPhazonBeamFeedback(active); + x72c_currentBeam->SetRainSplashGenerator(x748_rainSplashGenerator.get()); + x72c_currentBeam->EnableFx(true); + x72c_currentBeam->SetDrawHologram(false); + PlayAnim(NWeaponTypes::EGunAnimType::ToBeam, false); + if (x833_31_inFreeLook) + EnterFreeLook(mgr); + else if (x832_30_requestReturnToDefault) + ReturnArmAndGunToDefault(mgr, false); + x832_30_requestReturnToDefault = false; +} - switch (x310_currentBeam) - { - case CPlayerState::EBeamId::Plasma: - case CPlayerState::EBeamId::Power: - x832_25_chargeEffectVisible = true; - default: - break; +void CPlayerGun::ProcessPhazonGunMorph(float dt, CStateManager& mgr) { + if (x835_26_phazonBeamMorphing) { + if (x835_27_intoPhazonBeam) { + x39c_phazonMorphT += 15.f * dt; + if (x39c_phazonMorphT > 1.f) + x39c_phazonMorphT = 1.f; + } else { + x39c_phazonMorphT -= 2.f * dt; + if (x39c_phazonMorphT < 0.f) { + x835_26_phazonBeamMorphing = false; + x39c_phazonMorphT = 0.f; + } } + } - x2f8_stateFlags |= 0x7; - x318_comboAmmoIdx = 1; - x338_nextState = ENextState::StatusQuo; - x833_30_canShowAuxMuzzleEffect = true; + switch (x33c_phazonBeamState) { + case EPhazonBeamState::Entering: + if (x75c_phazonBeam) { + x75c_phazonBeam->Update(dt, mgr); + if (x75c_phazonBeam->IsLoaded()) { + StartPhazonBeamTransition(true, mgr, *mgr.GetPlayerState()); + SetPhazonBeamMorph(false); + x33c_phazonBeamState = EPhazonBeamState::Active; + x338_nextState = ENextState::SetupBeam; + } + } + break; + case EPhazonBeamState::Exiting: + if (x738_nextBeam) { + x738_nextBeam->Update(dt, mgr); + if (x738_nextBeam->IsLoaded()) { + x835_25_inPhazonBeam = false; + StartPhazonBeamTransition(false, mgr, *mgr.GetPlayerState()); + SetPhazonBeamMorph(false); + x33c_phazonBeamState = EPhazonBeamState::Inactive; + x338_nextState = ENextState::SetupBeam; + } + } + break; + default: + break; + } +} - x800_auxMuzzleGenerators[int(x320_currentAuxBeam)] = - std::make_unique(x7c0_auxMuzzleEffects[int(x320_currentAuxBeam)]); +void CPlayerGun::EnableChargeFx(EChargeState state, CStateManager& mgr) { + x72c_currentBeam->ActivateCharge(true, false); + SetGunLightActive(true, mgr); + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::Charge); + StopContinuousBeam(mgr, false); - x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]->SetParticleEmission(true); + switch (x310_currentBeam) { + case CPlayerState::EBeamId::Plasma: + case CPlayerState::EBeamId::Power: + x832_25_chargeEffectVisible = true; + default: + break; + } + + x2f8_stateFlags |= 0x7; + x318_comboAmmoIdx = 1; + x338_nextState = ENextState::StatusQuo; + x833_30_canShowAuxMuzzleEffect = true; + + x800_auxMuzzleGenerators[int(x320_currentAuxBeam)] = + std::make_unique(x7c0_auxMuzzleEffects[int(x320_currentAuxBeam)]); + + x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]->SetParticleEmission(true); } static constexpr float kChargeSpeed = 1.f / CPlayerState::GetMissileComboChargeFactor(); @@ -1254,1379 +1058,1171 @@ static constexpr float kChargeFxStart = 1.f / CPlayerState::GetMissileComboCharg static constexpr float kChargeAnimStart = 0.25f / CPlayerState::GetMissileComboChargeFactor(); static constexpr float kChargeStart = 0.025f / CPlayerState::GetMissileComboChargeFactor(); -static const u16 skBeamChargeUpSound[] = { SFXwpn_chargeup_power, SFXwpn_chargeup_ice, - SFXwpn_chargeup_wave, SFXwpn_chargeup_plasma }; +static const u16 skBeamChargeUpSound[] = {SFXwpn_chargeup_power, SFXwpn_chargeup_ice, SFXwpn_chargeup_wave, + SFXwpn_chargeup_plasma}; -void CPlayerGun::UpdateChargeState(float dt, CStateManager& mgr) -{ - switch (x32c_chargePhase) - { - case EChargePhase::ChargeRequested: - x340_chargeBeamFactor = 0.f; - x330_chargeState = EChargeState::Normal; +void CPlayerGun::UpdateChargeState(float dt, CStateManager& mgr) { + switch (x32c_chargePhase) { + case EChargePhase::ChargeRequested: + x340_chargeBeamFactor = 0.f; + x330_chargeState = EChargeState::Normal; + x832_27_chargeAnimStarted = false; + x834_24_charging = true; + x32c_chargePhase = EChargePhase::AnimAndSfx; + break; + case EChargePhase::AnimAndSfx: + if (!x832_27_chargeAnimStarted) { + if (x340_chargeBeamFactor > kChargeStart && x832_25_chargeEffectVisible) + x832_25_chargeEffectVisible = false; + if (x340_chargeBeamFactor > kChargeAnimStart) { + PlayAnim(NWeaponTypes::EGunAnimType::ChargeUp, false); + if (!x2e0_chargeSfx) + x2e0_chargeSfx = + NWeaponTypes::play_sfx(skBeamChargeUpSound[int(x310_currentBeam)], x834_27_underwater, true, 0.165f); + if (x830_chargeRumbleHandle == -1) + x830_chargeRumbleHandle = + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerGunCharge, 1.f, ERumblePriority::Three); + x832_27_chargeAnimStarted = true; + } + } else { + if (x340_chargeBeamFactor >= kChargeFxStart && (x2f8_stateFlags & 0x8) != 0x8) { + x832_25_chargeEffectVisible = true; x832_27_chargeAnimStarted = false; - x834_24_charging = true; - x32c_chargePhase = EChargePhase::AnimAndSfx; - break; - case EChargePhase::AnimAndSfx: - if (!x832_27_chargeAnimStarted) - { - if (x340_chargeBeamFactor > kChargeStart && x832_25_chargeEffectVisible) - x832_25_chargeEffectVisible = false; - if (x340_chargeBeamFactor > kChargeAnimStart) - { - PlayAnim(NWeaponTypes::EGunAnimType::ChargeUp, false); - if (!x2e0_chargeSfx) - x2e0_chargeSfx = NWeaponTypes::play_sfx(skBeamChargeUpSound[int(x310_currentBeam)], - x834_27_underwater, true, 0.165f); - if (x830_chargeRumbleHandle == -1) - x830_chargeRumbleHandle = mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerGunCharge, 1.f, - ERumblePriority::Three); - x832_27_chargeAnimStarted = true; - } - } - else - { - if (x340_chargeBeamFactor >= kChargeFxStart && (x2f8_stateFlags & 0x8) != 0x8) - { - x832_25_chargeEffectVisible = true; - x832_27_chargeAnimStarted = false; - x32c_chargePhase = EChargePhase::FxGrowing; - x330_chargeState = EChargeState::Charged; - EnableChargeFx(EChargeState::Charged, mgr); - PlayAnim(NWeaponTypes::EGunAnimType::ChargeLoop, true); - } - } - break; - case EChargePhase::FxGrowing: - if (x340_chargeBeamFactor >= 1.f) - x32c_chargePhase = EChargePhase::FxGrown; - break; - case EChargePhase::ComboXfer: - if (x344_comboXferTimer >= 1.f) - { - x32c_chargePhase = EChargePhase::ComboXferDone; - x832_25_chargeEffectVisible = false; - } - break; - case EChargePhase::ComboXferDone: - x32c_chargePhase = EChargePhase::ComboFire; - x348_chargeCancelTimer = 0.f; - break; - case EChargePhase::ComboFire: - x740_grappleArm->EnterComboFire(s32(x310_currentBeam), mgr); - x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::ComboFire, mgr, 0.f, false); - x72c_currentBeam->PlayPasAnim(SamusGun::EAnimationState::ComboFire, mgr, 0.f); - x833_31_inFreeLook = false; - x32c_chargePhase = EChargePhase::ComboFireDone; - break; - case EChargePhase::ChargeCancelled: - if ((x2f8_stateFlags & 0x10) != 0x10) - { - x348_chargeCancelTimer += dt; - if (x348_chargeCancelTimer >= 0.3f && x72c_currentBeam->IsChargeAnimOver()) - x32c_chargePhase = EChargePhase::ChargeDone; - } - else - { - x832_24_cancellingCharge = false; - } - break; - case EChargePhase::ChargeDone: - ResetCharge(mgr, false); - Reset(mgr, false); - break; - default: - break; + x32c_chargePhase = EChargePhase::FxGrowing; + x330_chargeState = EChargeState::Charged; + EnableChargeFx(EChargeState::Charged, mgr); + PlayAnim(NWeaponTypes::EGunAnimType::ChargeLoop, true); + } } - - if (x2e0_chargeSfx) - CSfxManager::PitchBend(x2e0_chargeSfx, x834_27_underwater ? -1.f : 0.f); - if (x32c_chargePhase > EChargePhase::NotCharging && x32c_chargePhase < EChargePhase::FxGrown) - { - x340_chargeBeamFactor += kChargeSpeed * dt; - if (x340_chargeBeamFactor > 1.f) - x340_chargeBeamFactor = 1.f; + break; + case EChargePhase::FxGrowing: + if (x340_chargeBeamFactor >= 1.f) + x32c_chargePhase = EChargePhase::FxGrown; + break; + case EChargePhase::ComboXfer: + if (x344_comboXferTimer >= 1.f) { + x32c_chargePhase = EChargePhase::ComboXferDone; + x832_25_chargeEffectVisible = false; } -} - -void CPlayerGun::UpdateAuxWeapons(float dt, const zeus::CTransform& targetXf, CStateManager& mgr) -{ - zeus::CVector3f firePoint = - x4a8_gunWorldXf * x418_beamLocalXf.origin + mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); - bool done = x744_auxWeapon->UpdateComboFx(dt, sGunScale, firePoint, targetXf, mgr); - if ((x2f8_stateFlags & 0x10) == 0x10) - { - if (x310_currentBeam == CPlayerState::EBeamId::Wave && x744_auxWeapon->HasTarget(mgr) == kInvalidUniqueId) - { - TUniqueId targetId = GetTargetId(mgr); - if (targetId == kInvalidUniqueId) - targetId = mgr.GetPlayer().GetAimTarget(); - x744_auxWeapon->SetNewTarget(targetId, mgr); - } - if (done) - return; - done = x310_currentBeam == CPlayerState::EBeamId::Wave || x310_currentBeam == CPlayerState::EBeamId::Plasma; - if (!done) - if (x72c_currentBeam->ComboFireOver()) - done = true; - x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::CancelCharge); - if (done) - { - x32c_chargePhase = EChargePhase::ChargeDone; - ReturnArmAndGunToDefault(mgr, false); - if ((x2f8_stateFlags & 0x8) != 0x8) - { - x2f8_stateFlags |= 0x1; - x2f8_stateFlags &= 0xFFE9; - } - x318_comboAmmoIdx = 0; - x31c_missileMode = EMissleMode::Inactive; - } - } - else if (x833_28_phazonBeamActive) - { - static_cast(x72c_currentBeam)->UpdateBeam(dt, targetXf, x418_beamLocalXf.origin, mgr); - } - else if (x310_currentBeam == CPlayerState::EBeamId::Plasma) - { - static_cast(x72c_currentBeam)->UpdateBeam(dt, targetXf, x418_beamLocalXf.origin, mgr); - } -} - -void CPlayerGun::DoUserAnimEvent(float dt, CStateManager& mgr, const CInt32POINode& node, EUserEventType type) -{ - switch (type) - { - case EUserEventType::Projectile: - if (x32c_chargePhase != EChargePhase::ComboFireDone) - return; - bool doFireSecondary; - if (x310_currentBeam != CPlayerState::EBeamId::Wave && x310_currentBeam != CPlayerState::EBeamId::Plasma) - doFireSecondary = true; - else - doFireSecondary = (x2ec_lastFireButtonStates & 0x1) != 0; - if (doFireSecondary) - FireSecondary(dt, mgr); - if ((x2f8_stateFlags & 0x10) != 0x10) - x2f8_stateFlags |= 0x10; - CancelCharge(mgr, true); - if (doFireSecondary) - x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::ToCombo); - break; - default: - break; - } -} - -void CPlayerGun::DoUserAnimEvents(float dt, CStateManager& mgr) -{ - zeus::CVector3f posToCam = - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation() - x3e8_xf.origin; - const CAnimData& animData = *x72c_currentBeam->GetSolidModelData().GetAnimationData(); - for (int i=0 ; i act = mgr.GetObjectById(ret)) - if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Target)) - ret = kInvalidUniqueId; - return ret; -} - -void CPlayerGun::CancelLockOn() -{ - if (x832_29_lockedOn) - { - x832_29_lockedOn = false; - x6a0_motionState.SetState(CMotionState::EMotionState::CancelLockOn); - if (x32c_chargePhase == EChargePhase::NotCharging && x318_comboAmmoIdx != 1) - PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); - } -} - -static const CPlayerState::EItemType skItemArr[] = -{ - CPlayerState::EItemType::Invalid, - CPlayerState::EItemType::Missiles -}; - -static const u16 skItemEmptySound[] = { SFXsfx0000, SFXwpn_empty_action }; - -void CPlayerGun::FireSecondary(float dt, CStateManager& mgr) -{ - if (mgr.GetCameraManager()->IsInCinematicCamera()) - return; - - if (x835_25_inPhazonBeam || x318_comboAmmoIdx == 0 || - !mgr.GetPlayerState()->HasPowerUp(skItemArr[x318_comboAmmoIdx]) || (x2f8_stateFlags & 0x4) != 0x4) - { - NWeaponTypes::play_sfx(SFXwpn_invalid_action, x834_27_underwater, false, 0.165f); - return; - } - - bool comboFired = false; - if (x318_comboAmmoIdx == 1) - { - x300_remainingMissiles = mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles); - if (mgr.GetWeaponIdCount(x538_playerId, EWeaponType::Missile) < 3 && x300_remainingMissiles != 0) - { - mgr.GetPlayerState()->DecrPickup(CPlayerState::EItemType::Missiles, - x832_26_comboFiring ? - mgr.GetPlayerState()->GetMissileCostForAltAttack() : 1); - comboFired = true; - } - if (x300_remainingMissiles > 5) - x300_remainingMissiles = 5; - else - x300_remainingMissiles -= 1; - } - - if (comboFired) - { - TUniqueId targetId = GetTargetId(mgr); - if (x832_26_comboFiring && targetId == kInvalidUniqueId && x310_currentBeam == CPlayerState::EBeamId::Wave) - targetId = mgr.GetPlayer().GetAimTarget(); - zeus::CTransform fireXf = x833_29_pointBlankWorldSurface ? - x448_elbowWorldXf : x4a8_gunWorldXf * x418_beamLocalXf; - if (!x833_29_pointBlankWorldSurface && x364_gunStrikeCoolTimer <= 0.f) - { - zeus::CVector3f backupOrigin = fireXf.origin; - fireXf = x478_assistAimXf; - fireXf.origin = backupOrigin; - } - fireXf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); - x744_auxWeapon->Fire(dt, x834_27_underwater, x310_currentBeam, x330_chargeState, fireXf, - mgr, x72c_currentBeam->GetWeaponType(), targetId); - mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::PlayerFire); - x3a0_missileExitTimer = 7.f; - if (!x832_26_comboFiring) - { - PlayAnim(NWeaponTypes::EGunAnimType::MissileShoot, false); - x338_nextState = x300_remainingMissiles > 0 ? ENextState::MissileReload : ENextState::MissileShotDone; - x2f8_stateFlags &= ~0x4; - } - } - else - { - NWeaponTypes::play_sfx(skItemEmptySound[x318_comboAmmoIdx], x834_27_underwater, false, 0.165f); - } -} - -void CPlayerGun::ResetCharged(float dt, CStateManager& mgr) -{ - if (x832_26_comboFiring) - return; - if (x32c_chargePhase >= EChargePhase::FxGrowing) - { - x833_30_canShowAuxMuzzleEffect = false; - UpdateNormalShotCycle(dt, mgr); - x832_24_cancellingCharge = true; - CancelCharge(mgr, true); - } - else if (x32c_chargePhase != EChargePhase::NotCharging) - { - x320_currentAuxBeam = x310_currentBeam; - x833_30_canShowAuxMuzzleEffect = true; + break; + case EChargePhase::ComboXferDone: + x32c_chargePhase = EChargePhase::ComboFire; + x348_chargeCancelTimer = 0.f; + break; + case EChargePhase::ComboFire: + x740_grappleArm->EnterComboFire(s32(x310_currentBeam), mgr); + x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::ComboFire, mgr, 0.f, false); + x72c_currentBeam->PlayPasAnim(SamusGun::EAnimationState::ComboFire, mgr, 0.f); + x833_31_inFreeLook = false; + x32c_chargePhase = EChargePhase::ComboFireDone; + break; + case EChargePhase::ChargeCancelled: + if ((x2f8_stateFlags & 0x10) != 0x10) { + x348_chargeCancelTimer += dt; + if (x348_chargeCancelTimer >= 0.3f && x72c_currentBeam->IsChargeAnimOver()) x32c_chargePhase = EChargePhase::ChargeDone; + } else { + x832_24_cancellingCharge = false; } - StopChargeSound(mgr); -} - -void CPlayerGun::ActivateCombo(CStateManager& mgr) -{ - if (x832_26_comboFiring) - return; - - if (mgr.GetPlayerState()->GetItemAmount(skItemArr[x318_comboAmmoIdx]) >= - mgr.GetPlayerState()->GetMissileCostForAltAttack()) - { - bool canFire = true; - if (x310_currentBeam == CPlayerState::EBeamId::Plasma) - canFire = !x834_27_underwater; - if (canFire) - { - x832_26_comboFiring = true; - const auto& xferEffect = x72c_currentBeam->GetComboXferDescr(); - if (xferEffect.IsLoaded()) - { - x77c_comboXferGen = - std::make_unique(xferEffect); - x77c_comboXferGen->SetGlobalScale(sGunScale); - } - x72c_currentBeam->EnableCharge(true); - StopChargeSound(mgr); - NWeaponTypes::play_sfx(SFXwpn_combo_xfer, x834_27_underwater, false, 0.165f); - x32c_chargePhase = EChargePhase::ComboXfer; - } - } - else - { - NWeaponTypes::play_sfx(SFXwpn_invalid_action, x834_27_underwater, false, 0.165f); - } -} - -void CPlayerGun::ProcessChargeState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt) -{ - if ((releasedStates & 0x1) != 0) - ResetCharged(dt, mgr); - if ((pressedStates & 0x1) != 0) - { - if (x32c_chargePhase == EChargePhase::NotCharging && (pressedStates & 0x1) != 0 && - x348_chargeCancelTimer == 0.f && x832_28_readyForShot) - { - UpdateNormalShotCycle(dt, mgr); - x32c_chargePhase = EChargePhase::ChargeRequested; - } - } - else if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::Missiles) && (pressedStates & 0x2) != 0) - { - if (x32c_chargePhase >= EChargePhase::FxGrown) - { - if (mgr.GetPlayerState()->HasPowerUp(skBeamComboArr[int(x310_currentBeam)])) - ActivateCombo(mgr); - } - else if (x32c_chargePhase == EChargePhase::NotCharging) - { - FireSecondary(dt, mgr); - } - } -} - -void CPlayerGun::ResetNormal(CStateManager& mgr) -{ + break; + case EChargePhase::ChargeDone: + ResetCharge(mgr, false); Reset(mgr, false); - x832_28_readyForShot = false; + break; + default: + break; + } + + if (x2e0_chargeSfx) + CSfxManager::PitchBend(x2e0_chargeSfx, x834_27_underwater ? -1.f : 0.f); + if (x32c_chargePhase > EChargePhase::NotCharging && x32c_chargePhase < EChargePhase::FxGrown) { + x340_chargeBeamFactor += kChargeSpeed * dt; + if (x340_chargeBeamFactor > 1.f) + x340_chargeBeamFactor = 1.f; + } } -void CPlayerGun::UpdateNormalShotCycle(float dt, CStateManager& mgr) -{ - if (!ExitMissile()) - return; - if (mgr.GetCameraManager()->IsInCinematicCamera()) - return; - x832_25_chargeEffectVisible = x833_28_phazonBeamActive || x310_currentBeam != CPlayerState::EBeamId::Plasma || - x32c_chargePhase != EChargePhase::NotCharging; - x30c_rapidFireShots += 1; - zeus::CTransform xf = x833_29_pointBlankWorldSurface ? x448_elbowWorldXf : x4a8_gunWorldXf * x418_beamLocalXf; - if (!x833_29_pointBlankWorldSurface && x364_gunStrikeCoolTimer <= 0.f) - { - zeus::CVector3f oldOrigin = xf.origin; - xf = x478_assistAimXf; - xf.origin = oldOrigin; +void CPlayerGun::UpdateAuxWeapons(float dt, const zeus::CTransform& targetXf, CStateManager& mgr) { + zeus::CVector3f firePoint = + x4a8_gunWorldXf * x418_beamLocalXf.origin + mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); + bool done = x744_auxWeapon->UpdateComboFx(dt, sGunScale, firePoint, targetXf, mgr); + if ((x2f8_stateFlags & 0x10) == 0x10) { + if (x310_currentBeam == CPlayerState::EBeamId::Wave && x744_auxWeapon->HasTarget(mgr) == kInvalidUniqueId) { + TUniqueId targetId = GetTargetId(mgr); + if (targetId == kInvalidUniqueId) + targetId = mgr.GetPlayer().GetAimTarget(); + x744_auxWeapon->SetNewTarget(targetId, mgr); } - xf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); - x38c_muzzleEffectVisTimer = 0.0625f; - TUniqueId homingTarget; - if (x72c_currentBeam->GetVelocityInfo().GetTargetHoming(int(x330_chargeState))) - homingTarget = GetTargetId(mgr); + if (done) + return; + done = x310_currentBeam == CPlayerState::EBeamId::Wave || x310_currentBeam == CPlayerState::EBeamId::Plasma; + if (!done) + if (x72c_currentBeam->ComboFireOver()) + done = true; + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::CancelCharge); + if (done) { + x32c_chargePhase = EChargePhase::ChargeDone; + ReturnArmAndGunToDefault(mgr, false); + if ((x2f8_stateFlags & 0x8) != 0x8) { + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; + } + x318_comboAmmoIdx = 0; + x31c_missileMode = EMissleMode::Inactive; + } + } else if (x833_28_phazonBeamActive) { + static_cast(x72c_currentBeam)->UpdateBeam(dt, targetXf, x418_beamLocalXf.origin, mgr); + } else if (x310_currentBeam == CPlayerState::EBeamId::Plasma) { + static_cast(x72c_currentBeam)->UpdateBeam(dt, targetXf, x418_beamLocalXf.origin, mgr); + } +} + +void CPlayerGun::DoUserAnimEvent(float dt, CStateManager& mgr, const CInt32POINode& node, EUserEventType type) { + switch (type) { + case EUserEventType::Projectile: + if (x32c_chargePhase != EChargePhase::ComboFireDone) + return; + bool doFireSecondary; + if (x310_currentBeam != CPlayerState::EBeamId::Wave && x310_currentBeam != CPlayerState::EBeamId::Plasma) + doFireSecondary = true; else - homingTarget = kInvalidUniqueId; - x72c_currentBeam->Fire(x834_27_underwater, dt, x330_chargeState, xf, mgr, homingTarget, - x340_chargeBeamFactor, x340_chargeBeamFactor); - mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::PlayerFire); + doFireSecondary = (x2ec_lastFireButtonStates & 0x1) != 0; + if (doFireSecondary) + FireSecondary(dt, mgr); + if ((x2f8_stateFlags & 0x10) != 0x10) + x2f8_stateFlags |= 0x10; + CancelCharge(mgr, true); + if (doFireSecondary) + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::ToCombo); + break; + default: + break; + } } -void CPlayerGun::ProcessNormalState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt) -{ - if ((releasedStates & 0x1) != 0) - ResetNormal(mgr); - if ((pressedStates & 0x1) != 0 && x348_chargeCancelTimer == 0.f && x832_28_readyForShot) - UpdateNormalShotCycle(dt, mgr); - else if ((pressedStates & 0x2) != 0) - FireSecondary(dt, mgr); -} - -void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CStateManager& mgr) -{ - u32 oldFiring = x2ec_lastFireButtonStates; - x2ec_lastFireButtonStates = x2f4_fireButtonStates; - u32 pressedStates = x2f4_fireButtonStates & (oldFiring ^ x2f4_fireButtonStates); - x2f0_pressedFireButtonStates = pressedStates; - u32 releasedStates = oldFiring & (oldFiring ^ x2f4_fireButtonStates); - x832_28_readyForShot = false; - - CPlayer& player = mgr.GetPlayer(); - if (!x832_24_cancellingCharge && !x834_30_inBigStrike) - { - float coolDown = x72c_currentBeam->GetWeaponInfo().x0_coolDown; - if ((pressedStates & 0x1) == 0) - { - if (x390_cooldown >= coolDown) - { - x390_cooldown = coolDown; - if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && - mgr.GetPlayerState()->ItemEnabled(CPlayerState::EItemType::ChargeBeam) && - player.GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn && - player.GetGrappleState() == CPlayer::EGrappleState::None && - mgr.GetPlayerState()->GetTransitioningVisor() != CPlayerState::EPlayerVisor::Scan && - mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan && - (x2ec_lastFireButtonStates & 0x1) != 0 && x32c_chargePhase == EChargePhase::NotCharging) - { - x832_28_readyForShot = true; - pressedStates |= 0x1; - x390_cooldown = 0.f; - } - } - } - else if (x390_cooldown >= coolDown) - { - x832_28_readyForShot = true; - x390_cooldown = 0.f; - } - x390_cooldown += dt; - } - - if (x834_28_requestImmediateRecharge) - x834_28_requestImmediateRecharge = (x2ec_lastFireButtonStates & 0x1) != 0; - - if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) - { - x835_28_bombReady = false; - x835_29_powerBombReady = false; - if (!x835_31_actorAttached) - { - x835_28_bombReady = true; - if (x53a_powerBomb != kInvalidUniqueId && - !mgr.CanCreateProjectile(x538_playerId, EWeaponType::PowerBomb, 1)) - { - auto* pb = static_cast(mgr.GetObjectById(x53a_powerBomb)); - if (pb && pb->GetCurTime() <= 4.25f) - x835_28_bombReady = false; - else - x53a_powerBomb = kInvalidUniqueId; - } - if (((pressedStates & 0x1) != 0 || x32c_chargePhase != EChargePhase::NotCharging) && - mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::MorphBallBombs)) - { - if (x835_28_bombReady) - DropBomb(EBWeapon::Bomb, mgr); - } - else if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PowerBombs) && - mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::PowerBombs) > 0) - { - x835_29_powerBombReady = mgr.CanCreateProjectile(x538_playerId, EWeaponType::PowerBomb, 1) && - mgr.CanCreateProjectile(x538_playerId, EWeaponType::Bomb, 1); - if ((pressedStates & 0x2) != 0 && x835_29_powerBombReady) - DropBomb(EBWeapon::PowerBomb, mgr); - } - } - } - else if ((x2f8_stateFlags & 0x8) != 0x8 && - player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) - { - if ((pressedStates & 0x2) != 0 && x318_comboAmmoIdx == 0 && - (x2f8_stateFlags & 0x2) != 0x2 && x32c_chargePhase == EChargePhase::NotCharging) - { - u32 missileCount = mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles); - if (x338_nextState != ENextState::EnterMissile && x338_nextState != ENextState::ExitMissile) - { - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::Missiles) && missileCount > 0) - { - x300_remainingMissiles = missileCount; - if (x300_remainingMissiles > 5) - x300_remainingMissiles = 5; - if (!x835_25_inPhazonBeam) - { - x2f8_stateFlags &= ~0x1; - x2f8_stateFlags |= 0x6; - x318_comboAmmoIdx = 1; - x31c_missileMode = EMissleMode::Active; - } - FireSecondary(dt, mgr); - } - else - { - if (!CSfxManager::IsPlaying(x2e4_invalidSfx)) - x2e4_invalidSfx = NWeaponTypes::play_sfx(SFXwpn_invalid_action, x834_27_underwater, false, 0.165f); - else - x2e4_invalidSfx.reset(); - } - } - } - else - { - if (x3a4_fidget.GetState() == CFidget::EState::NoFidget) - { - if ((x2f8_stateFlags & 0x10) == 0x10 && x744_auxWeapon->IsComboFxActive(mgr)) - { - if (x2ec_lastFireButtonStates == 0 || - (x310_currentBeam == CPlayerState::EBeamId::Wave && x833_29_pointBlankWorldSurface)) - { - StopContinuousBeam(mgr, (x2f8_stateFlags & 0x8) == 0x8); - } - } - else - { - if (mgr.GetPlayerState()->ItemEnabled(CPlayerState::EItemType::ChargeBeam) && - x33c_phazonBeamState == EPhazonBeamState::Inactive) - ProcessChargeState(releasedStates, pressedStates, mgr, dt); - else - ProcessNormalState(releasedStates, pressedStates, mgr, dt); - } - } - } - } -} - -void CPlayerGun::EnterFreeLook(CStateManager& mgr) -{ - if (!x832_30_requestReturnToDefault) - x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::FreeLook, mgr, 0.f, false); - x740_grappleArm->EnterFreeLook(x835_25_inPhazonBeam ? 1 : s32(x310_currentBeam), - x73c_gunMotion->GetFreeLookSetId(), mgr); -} - -void CPlayerGun::SetFidgetAnimBits(int animSet, bool beamOnly) -{ - x2fc_fidgetAnimBits = 0; - if (beamOnly) - { - x2fc_fidgetAnimBits = 2; - return; - } - - switch (x3a4_fidget.GetType()) - { - case SamusGun::EFidgetType::Minor: - x2fc_fidgetAnimBits = 1; - if (animSet != 1) - return; - x2fc_fidgetAnimBits |= 4; - break; - case SamusGun::EFidgetType::Major: - if (animSet >= 6 || animSet < 4) - x2fc_fidgetAnimBits = 2; - else - x2fc_fidgetAnimBits = 1; - x2fc_fidgetAnimBits |= 4; +void CPlayerGun::DoUserAnimEvents(float dt, CStateManager& mgr) { + zeus::CVector3f posToCam = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation() - x3e8_xf.origin; + const CAnimData& animData = *x72c_currentBeam->GetSolidModelData().GetAnimationData(); + for (int i = 0; i < animData.GetPassedSoundPOICount(); ++i) { + const CSoundPOINode& node = CAnimData::g_SoundPOINodes[i]; + if (node.GetPoiType() != EPOIType::Sound || + (node.GetCharacterIndex() != -1 && animData.x204_charIdx != node.GetCharacterIndex())) + continue; + NWeaponTypes::do_sound_event(x670_animSfx, x328_animSfxPitch, false, node.GetSfxId(), node.GetWeight(), + node.GetFlags(), node.GetFalloff(), node.GetMaxDist(), 0.16f, 1.f, posToCam, + x3e8_xf.origin, mgr.GetPlayer().GetAreaIdAlways(), mgr); + } + for (int i = 0; i < animData.GetPassedIntPOICount(); ++i) { + const CInt32POINode& node = CAnimData::g_Int32POINodes[i]; + switch (node.GetPoiType()) { + case EPOIType::UserEvent: + DoUserAnimEvent(dt, mgr, node, EUserEventType(node.GetValue())); + break; + case EPOIType::SoundInt32: + if (node.GetCharacterIndex() != -1 && animData.x204_charIdx != node.GetCharacterIndex()) break; + NWeaponTypes::do_sound_event(x670_animSfx, x328_animSfxPitch, false, u32(node.GetValue()), node.GetWeight(), + node.GetFlags(), 0.1f, 150.f, 0.16f, 1.f, posToCam, x3e8_xf.origin, + mgr.GetPlayer().GetAreaIdAlways(), mgr); + break; default: - break; + break; } + } } -void CPlayerGun::AsyncLoadFidget(CStateManager& mgr) -{ - SetFidgetAnimBits(x3a4_fidget.GetAnimSet(), x3a4_fidget.GetState() == CFidget::EState::HolsterBeam); - if ((x2fc_fidgetAnimBits & 0x1) == 0x1) - x73c_gunMotion->GunController().LoadFidgetAnimAsync(mgr, s32(x3a4_fidget.GetType()), - s32(x310_currentBeam), x3a4_fidget.GetAnimSet()); - if ((x2fc_fidgetAnimBits & 0x2) == 0x2) - { - x72c_currentBeam->AsyncLoadFidget(mgr, (x3a4_fidget.GetState() == CFidget::EState::HolsterBeam ? - SamusGun::EFidgetType::Minor : x3a4_fidget.GetType()), x3a4_fidget.GetAnimSet()); - x832_31_inRestPose = false; - } - if ((x2fc_fidgetAnimBits & 0x4) == 0x4) - if (CGunController* gc = x740_grappleArm->GunController()) - gc->LoadFidgetAnimAsync(mgr, s32(x3a4_fidget.GetType()), - x3a4_fidget.GetType() != SamusGun::EFidgetType::Minor ? s32(x310_currentBeam) : 0, - x3a4_fidget.GetAnimSet()); +TUniqueId CPlayerGun::GetTargetId(CStateManager& mgr) const { + TUniqueId ret = mgr.GetPlayer().GetOrbitTargetId(); + if (x832_26_comboFiring && ret == kInvalidUniqueId && x310_currentBeam == CPlayerState::EBeamId::Wave) + ret = mgr.GetPlayer().GetOrbitNextTargetId(); + if (ret == kInvalidUniqueId) + return ret; + if (TCastToConstPtr act = mgr.GetObjectById(ret)) + if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Target)) + ret = kInvalidUniqueId; + return ret; } -bool CPlayerGun::IsFidgetLoaded() const -{ - int loadFlags = 0; - if ((x2fc_fidgetAnimBits & 0x1) == 0x1 && x73c_gunMotion->GunController().IsFidgetLoaded()) - loadFlags |= 0x1; - if ((x2fc_fidgetAnimBits & 0x2) == 0x2 && x72c_currentBeam->IsFidgetLoaded()) - loadFlags |= 0x2; - if ((x2fc_fidgetAnimBits & 0x4) == 0x4) - if (CGunController* gc = x740_grappleArm->GunController()) - if (gc->IsFidgetLoaded()) - loadFlags |= 0x4; - return x2fc_fidgetAnimBits == loadFlags; +void CPlayerGun::CancelLockOn() { + if (x832_29_lockedOn) { + x832_29_lockedOn = false; + x6a0_motionState.SetState(CMotionState::EMotionState::CancelLockOn); + if (x32c_chargePhase == EChargePhase::NotCharging && x318_comboAmmoIdx != 1) + PlayAnim(NWeaponTypes::EGunAnimType::BasePosition, false); + } } -void CPlayerGun::EnterFidget(CStateManager& mgr) -{ - if ((x2fc_fidgetAnimBits & 0x1) == 0x1) - { - x73c_gunMotion->EnterFidget(mgr, x3a4_fidget.GetType(), x3a4_fidget.GetAnimSet()); - x834_25_gunMotionFidgeting = true; +static const CPlayerState::EItemType skItemArr[] = {CPlayerState::EItemType::Invalid, + CPlayerState::EItemType::Missiles}; + +static const u16 skItemEmptySound[] = {SFXsfx0000, SFXwpn_empty_action}; + +void CPlayerGun::FireSecondary(float dt, CStateManager& mgr) { + if (mgr.GetCameraManager()->IsInCinematicCamera()) + return; + + if (x835_25_inPhazonBeam || x318_comboAmmoIdx == 0 || + !mgr.GetPlayerState()->HasPowerUp(skItemArr[x318_comboAmmoIdx]) || (x2f8_stateFlags & 0x4) != 0x4) { + NWeaponTypes::play_sfx(SFXwpn_invalid_action, x834_27_underwater, false, 0.165f); + return; + } + + bool comboFired = false; + if (x318_comboAmmoIdx == 1) { + x300_remainingMissiles = mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles); + if (mgr.GetWeaponIdCount(x538_playerId, EWeaponType::Missile) < 3 && x300_remainingMissiles != 0) { + mgr.GetPlayerState()->DecrPickup(CPlayerState::EItemType::Missiles, + x832_26_comboFiring ? mgr.GetPlayerState()->GetMissileCostForAltAttack() : 1); + comboFired = true; } + if (x300_remainingMissiles > 5) + x300_remainingMissiles = 5; else - { - x834_25_gunMotionFidgeting = false; + x300_remainingMissiles -= 1; + } + + if (comboFired) { + TUniqueId targetId = GetTargetId(mgr); + if (x832_26_comboFiring && targetId == kInvalidUniqueId && x310_currentBeam == CPlayerState::EBeamId::Wave) + targetId = mgr.GetPlayer().GetAimTarget(); + zeus::CTransform fireXf = x833_29_pointBlankWorldSurface ? x448_elbowWorldXf : x4a8_gunWorldXf * x418_beamLocalXf; + if (!x833_29_pointBlankWorldSurface && x364_gunStrikeCoolTimer <= 0.f) { + zeus::CVector3f backupOrigin = fireXf.origin; + fireXf = x478_assistAimXf; + fireXf.origin = backupOrigin; } - - if ((x2fc_fidgetAnimBits & 0x2) == 0x2) - x72c_currentBeam->EnterFidget(mgr, x3a4_fidget.GetType(), x3a4_fidget.GetAnimSet()); - - if ((x2fc_fidgetAnimBits & 0x4) == 0x4) - x740_grappleArm->EnterFidget(mgr, x3a4_fidget.GetType(), - x3a4_fidget.GetType() != SamusGun::EFidgetType::Minor ? s32(x310_currentBeam) : 0, - x3a4_fidget.GetAnimSet()); - - UnLoadFidget(); - x3a4_fidget.DoneLoading(); + fireXf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); + x744_auxWeapon->Fire(dt, x834_27_underwater, x310_currentBeam, x330_chargeState, fireXf, mgr, + x72c_currentBeam->GetWeaponType(), targetId); + mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::PlayerFire); + x3a0_missileExitTimer = 7.f; + if (!x832_26_comboFiring) { + PlayAnim(NWeaponTypes::EGunAnimType::MissileShoot, false); + x338_nextState = x300_remainingMissiles > 0 ? ENextState::MissileReload : ENextState::MissileShotDone; + x2f8_stateFlags &= ~0x4; + } + } else { + NWeaponTypes::play_sfx(skItemEmptySound[x318_comboAmmoIdx], x834_27_underwater, false, 0.165f); + } } -void CPlayerGun::UpdateGunIdle(bool inStrikeCooldown, float camBobT, float dt, CStateManager& mgr) -{ - CPlayer& player = mgr.GetPlayer(); - if (player.IsInFreeLook() && !x832_29_lockedOn && !x740_grappleArm->IsGrappling() && - x3a4_fidget.GetState() != CFidget::EState::HolsterBeam && - player.GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn && !x834_30_inBigStrike) - { - if ((x2f8_stateFlags & 0x8) != 0x8) - { - if (!x833_31_inFreeLook && !x834_26_animPlaying) - { - if (x388_enterFreeLookDelayTimer < 0.25f) - x388_enterFreeLookDelayTimer += dt; - if (x388_enterFreeLookDelayTimer >= 0.25f && !x740_grappleArm->IsSuitLoading()) - { - EnterFreeLook(mgr); - x833_31_inFreeLook = true; - } - } - else - { - x388_enterFreeLookDelayTimer = 0.f; - if (x834_26_animPlaying) - ResetIdle(mgr); - } - } +void CPlayerGun::ResetCharged(float dt, CStateManager& mgr) { + if (x832_26_comboFiring) + return; + if (x32c_chargePhase >= EChargePhase::FxGrowing) { + x833_30_canShowAuxMuzzleEffect = false; + UpdateNormalShotCycle(dt, mgr); + x832_24_cancellingCharge = true; + CancelCharge(mgr, true); + } else if (x32c_chargePhase != EChargePhase::NotCharging) { + x320_currentAuxBeam = x310_currentBeam; + x833_30_canShowAuxMuzzleEffect = true; + x32c_chargePhase = EChargePhase::ChargeDone; + } + StopChargeSound(mgr); +} + +void CPlayerGun::ActivateCombo(CStateManager& mgr) { + if (x832_26_comboFiring) + return; + + if (mgr.GetPlayerState()->GetItemAmount(skItemArr[x318_comboAmmoIdx]) >= + mgr.GetPlayerState()->GetMissileCostForAltAttack()) { + bool canFire = true; + if (x310_currentBeam == CPlayerState::EBeamId::Plasma) + canFire = !x834_27_underwater; + if (canFire) { + x832_26_comboFiring = true; + const auto& xferEffect = x72c_currentBeam->GetComboXferDescr(); + if (xferEffect.IsLoaded()) { + x77c_comboXferGen = std::make_unique(xferEffect); + x77c_comboXferGen->SetGlobalScale(sGunScale); + } + x72c_currentBeam->EnableCharge(true); + StopChargeSound(mgr); + NWeaponTypes::play_sfx(SFXwpn_combo_xfer, x834_27_underwater, false, 0.165f); + x32c_chargePhase = EChargePhase::ComboXfer; } - else - { - if (x833_31_inFreeLook) - { - if ((x2f8_stateFlags & 0x10) != 0x10) - { - x73c_gunMotion->ReturnToDefault(mgr, x834_30_inBigStrike); - x740_grappleArm->ReturnToDefault(mgr, 0.f, false); - } - x833_31_inFreeLook = false; + } else { + NWeaponTypes::play_sfx(SFXwpn_invalid_action, x834_27_underwater, false, 0.165f); + } +} + +void CPlayerGun::ProcessChargeState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt) { + if ((releasedStates & 0x1) != 0) + ResetCharged(dt, mgr); + if ((pressedStates & 0x1) != 0) { + if (x32c_chargePhase == EChargePhase::NotCharging && (pressedStates & 0x1) != 0 && x348_chargeCancelTimer == 0.f && + x832_28_readyForShot) { + UpdateNormalShotCycle(dt, mgr); + x32c_chargePhase = EChargePhase::ChargeRequested; + } + } else if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::Missiles) && (pressedStates & 0x2) != 0) { + if (x32c_chargePhase >= EChargePhase::FxGrown) { + if (mgr.GetPlayerState()->HasPowerUp(skBeamComboArr[int(x310_currentBeam)])) + ActivateCombo(mgr); + } else if (x32c_chargePhase == EChargePhase::NotCharging) { + FireSecondary(dt, mgr); + } + } +} + +void CPlayerGun::ResetNormal(CStateManager& mgr) { + Reset(mgr, false); + x832_28_readyForShot = false; +} + +void CPlayerGun::UpdateNormalShotCycle(float dt, CStateManager& mgr) { + if (!ExitMissile()) + return; + if (mgr.GetCameraManager()->IsInCinematicCamera()) + return; + x832_25_chargeEffectVisible = x833_28_phazonBeamActive || x310_currentBeam != CPlayerState::EBeamId::Plasma || + x32c_chargePhase != EChargePhase::NotCharging; + x30c_rapidFireShots += 1; + zeus::CTransform xf = x833_29_pointBlankWorldSurface ? x448_elbowWorldXf : x4a8_gunWorldXf * x418_beamLocalXf; + if (!x833_29_pointBlankWorldSurface && x364_gunStrikeCoolTimer <= 0.f) { + zeus::CVector3f oldOrigin = xf.origin; + xf = x478_assistAimXf; + xf.origin = oldOrigin; + } + xf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); + x38c_muzzleEffectVisTimer = 0.0625f; + TUniqueId homingTarget; + if (x72c_currentBeam->GetVelocityInfo().GetTargetHoming(int(x330_chargeState))) + homingTarget = GetTargetId(mgr); + else + homingTarget = kInvalidUniqueId; + x72c_currentBeam->Fire(x834_27_underwater, dt, x330_chargeState, xf, mgr, homingTarget, x340_chargeBeamFactor, + x340_chargeBeamFactor); + mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::PlayerFire); +} + +void CPlayerGun::ProcessNormalState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt) { + if ((releasedStates & 0x1) != 0) + ResetNormal(mgr); + if ((pressedStates & 0x1) != 0 && x348_chargeCancelTimer == 0.f && x832_28_readyForShot) + UpdateNormalShotCycle(dt, mgr); + else if ((pressedStates & 0x2) != 0) + FireSecondary(dt, mgr); +} + +void CPlayerGun::UpdateWeaponFire(float dt, const CPlayerState& playerState, CStateManager& mgr) { + u32 oldFiring = x2ec_lastFireButtonStates; + x2ec_lastFireButtonStates = x2f4_fireButtonStates; + u32 pressedStates = x2f4_fireButtonStates & (oldFiring ^ x2f4_fireButtonStates); + x2f0_pressedFireButtonStates = pressedStates; + u32 releasedStates = oldFiring & (oldFiring ^ x2f4_fireButtonStates); + x832_28_readyForShot = false; + + CPlayer& player = mgr.GetPlayer(); + if (!x832_24_cancellingCharge && !x834_30_inBigStrike) { + float coolDown = x72c_currentBeam->GetWeaponInfo().x0_coolDown; + if ((pressedStates & 0x1) == 0) { + if (x390_cooldown >= coolDown) { + x390_cooldown = coolDown; + if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && + mgr.GetPlayerState()->ItemEnabled(CPlayerState::EItemType::ChargeBeam) && + player.GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn && + player.GetGrappleState() == CPlayer::EGrappleState::None && + mgr.GetPlayerState()->GetTransitioningVisor() != CPlayerState::EPlayerVisor::Scan && + mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan && + (x2ec_lastFireButtonStates & 0x1) != 0 && x32c_chargePhase == EChargePhase::NotCharging) { + x832_28_readyForShot = true; + pressedStates |= 0x1; + x390_cooldown = 0.f; } + } + } else if (x390_cooldown >= coolDown) { + x832_28_readyForShot = true; + x390_cooldown = 0.f; + } + x390_cooldown += dt; + } + + if (x834_28_requestImmediateRecharge) + x834_28_requestImmediateRecharge = (x2ec_lastFireButtonStates & 0x1) != 0; + + if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) { + x835_28_bombReady = false; + x835_29_powerBombReady = false; + if (!x835_31_actorAttached) { + x835_28_bombReady = true; + if (x53a_powerBomb != kInvalidUniqueId && !mgr.CanCreateProjectile(x538_playerId, EWeaponType::PowerBomb, 1)) { + auto* pb = static_cast(mgr.GetObjectById(x53a_powerBomb)); + if (pb && pb->GetCurTime() <= 4.25f) + x835_28_bombReady = false; + else + x53a_powerBomb = kInvalidUniqueId; + } + if (((pressedStates & 0x1) != 0 || x32c_chargePhase != EChargePhase::NotCharging) && + mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::MorphBallBombs)) { + if (x835_28_bombReady) + DropBomb(EBWeapon::Bomb, mgr); + } else if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PowerBombs) && + mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::PowerBombs) > 0) { + x835_29_powerBombReady = mgr.CanCreateProjectile(x538_playerId, EWeaponType::PowerBomb, 1) && + mgr.CanCreateProjectile(x538_playerId, EWeaponType::Bomb, 1); + if ((pressedStates & 0x2) != 0 && x835_29_powerBombReady) + DropBomb(EBWeapon::PowerBomb, mgr); + } + } + } else if ((x2f8_stateFlags & 0x8) != 0x8 && + player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) { + if ((pressedStates & 0x2) != 0 && x318_comboAmmoIdx == 0 && (x2f8_stateFlags & 0x2) != 0x2 && + x32c_chargePhase == EChargePhase::NotCharging) { + u32 missileCount = mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::Missiles); + if (x338_nextState != ENextState::EnterMissile && x338_nextState != ENextState::ExitMissile) { + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::Missiles) && missileCount > 0) { + x300_remainingMissiles = missileCount; + if (x300_remainingMissiles > 5) + x300_remainingMissiles = 5; + if (!x835_25_inPhazonBeam) { + x2f8_stateFlags &= ~0x1; + x2f8_stateFlags |= 0x6; + x318_comboAmmoIdx = 1; + x31c_missileMode = EMissleMode::Active; + } + FireSecondary(dt, mgr); + } else { + if (!CSfxManager::IsPlaying(x2e4_invalidSfx)) + x2e4_invalidSfx = NWeaponTypes::play_sfx(SFXwpn_invalid_action, x834_27_underwater, false, 0.165f); + else + x2e4_invalidSfx.reset(); + } + } + } else { + if (x3a4_fidget.GetState() == CFidget::EState::NoFidget) { + if ((x2f8_stateFlags & 0x10) == 0x10 && x744_auxWeapon->IsComboFxActive(mgr)) { + if (x2ec_lastFireButtonStates == 0 || + (x310_currentBeam == CPlayerState::EBeamId::Wave && x833_29_pointBlankWorldSurface)) { + StopContinuousBeam(mgr, (x2f8_stateFlags & 0x8) == 0x8); + } + } else { + if (mgr.GetPlayerState()->ItemEnabled(CPlayerState::EItemType::ChargeBeam) && + x33c_phazonBeamState == EPhazonBeamState::Inactive) + ProcessChargeState(releasedStates, pressedStates, mgr, dt); + else + ProcessNormalState(releasedStates, pressedStates, mgr, dt); + } + } + } + } +} + +void CPlayerGun::EnterFreeLook(CStateManager& mgr) { + if (!x832_30_requestReturnToDefault) + x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::FreeLook, mgr, 0.f, false); + x740_grappleArm->EnterFreeLook(x835_25_inPhazonBeam ? 1 : s32(x310_currentBeam), x73c_gunMotion->GetFreeLookSetId(), + mgr); +} + +void CPlayerGun::SetFidgetAnimBits(int animSet, bool beamOnly) { + x2fc_fidgetAnimBits = 0; + if (beamOnly) { + x2fc_fidgetAnimBits = 2; + return; + } + + switch (x3a4_fidget.GetType()) { + case SamusGun::EFidgetType::Minor: + x2fc_fidgetAnimBits = 1; + if (animSet != 1) + return; + x2fc_fidgetAnimBits |= 4; + break; + case SamusGun::EFidgetType::Major: + if (animSet >= 6 || animSet < 4) + x2fc_fidgetAnimBits = 2; + else + x2fc_fidgetAnimBits = 1; + x2fc_fidgetAnimBits |= 4; + break; + default: + break; + } +} + +void CPlayerGun::AsyncLoadFidget(CStateManager& mgr) { + SetFidgetAnimBits(x3a4_fidget.GetAnimSet(), x3a4_fidget.GetState() == CFidget::EState::HolsterBeam); + if ((x2fc_fidgetAnimBits & 0x1) == 0x1) + x73c_gunMotion->GunController().LoadFidgetAnimAsync(mgr, s32(x3a4_fidget.GetType()), s32(x310_currentBeam), + x3a4_fidget.GetAnimSet()); + if ((x2fc_fidgetAnimBits & 0x2) == 0x2) { + x72c_currentBeam->AsyncLoadFidget( + mgr, + (x3a4_fidget.GetState() == CFidget::EState::HolsterBeam ? SamusGun::EFidgetType::Minor : x3a4_fidget.GetType()), + x3a4_fidget.GetAnimSet()); + x832_31_inRestPose = false; + } + if ((x2fc_fidgetAnimBits & 0x4) == 0x4) + if (CGunController* gc = x740_grappleArm->GunController()) + gc->LoadFidgetAnimAsync(mgr, s32(x3a4_fidget.GetType()), + x3a4_fidget.GetType() != SamusGun::EFidgetType::Minor ? s32(x310_currentBeam) : 0, + x3a4_fidget.GetAnimSet()); +} + +bool CPlayerGun::IsFidgetLoaded() const { + int loadFlags = 0; + if ((x2fc_fidgetAnimBits & 0x1) == 0x1 && x73c_gunMotion->GunController().IsFidgetLoaded()) + loadFlags |= 0x1; + if ((x2fc_fidgetAnimBits & 0x2) == 0x2 && x72c_currentBeam->IsFidgetLoaded()) + loadFlags |= 0x2; + if ((x2fc_fidgetAnimBits & 0x4) == 0x4) + if (CGunController* gc = x740_grappleArm->GunController()) + if (gc->IsFidgetLoaded()) + loadFlags |= 0x4; + return x2fc_fidgetAnimBits == loadFlags; +} + +void CPlayerGun::EnterFidget(CStateManager& mgr) { + if ((x2fc_fidgetAnimBits & 0x1) == 0x1) { + x73c_gunMotion->EnterFidget(mgr, x3a4_fidget.GetType(), x3a4_fidget.GetAnimSet()); + x834_25_gunMotionFidgeting = true; + } else { + x834_25_gunMotionFidgeting = false; + } + + if ((x2fc_fidgetAnimBits & 0x2) == 0x2) + x72c_currentBeam->EnterFidget(mgr, x3a4_fidget.GetType(), x3a4_fidget.GetAnimSet()); + + if ((x2fc_fidgetAnimBits & 0x4) == 0x4) + x740_grappleArm->EnterFidget(mgr, x3a4_fidget.GetType(), + x3a4_fidget.GetType() != SamusGun::EFidgetType::Minor ? s32(x310_currentBeam) : 0, + x3a4_fidget.GetAnimSet()); + + UnLoadFidget(); + x3a4_fidget.DoneLoading(); +} + +void CPlayerGun::UpdateGunIdle(bool inStrikeCooldown, float camBobT, float dt, CStateManager& mgr) { + CPlayer& player = mgr.GetPlayer(); + if (player.IsInFreeLook() && !x832_29_lockedOn && !x740_grappleArm->IsGrappling() && + x3a4_fidget.GetState() != CFidget::EState::HolsterBeam && + player.GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn && !x834_30_inBigStrike) { + if ((x2f8_stateFlags & 0x8) != 0x8) { + if (!x833_31_inFreeLook && !x834_26_animPlaying) { + if (x388_enterFreeLookDelayTimer < 0.25f) + x388_enterFreeLookDelayTimer += dt; + if (x388_enterFreeLookDelayTimer >= 0.25f && !x740_grappleArm->IsSuitLoading()) { + EnterFreeLook(mgr); + x833_31_inFreeLook = true; + } + } else { x388_enterFreeLookDelayTimer = 0.f; - if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) - { - x833_24_notFidgeting = !(player.GetSurfaceRestraint() != CPlayer::ESurfaceRestraints::Water && - mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan && - (x2f4_fireButtonStates & 0x3) == 0 && x32c_chargePhase == EChargePhase::NotCharging && - !x832_29_lockedOn && (x2f8_stateFlags & 0x8) != 0x8 && x364_gunStrikeCoolTimer <= 0.f && - player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround && - !player.IsInFreeLook() && !player.GetFreeLookStickState() && x304_ == 0 && - std::fabs(player.GetAngularVelocityOR().angle()) <= 0.1f && camBobT <= 0.01f && - !mgr.GetCameraManager()->IsInCinematicCamera() && - player.GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn && - player.GetGrappleState() == CPlayer::EGrappleState::None && !x834_30_inBigStrike && - !x835_25_inPhazonBeam); - if (x833_24_notFidgeting) - { - if (!x834_30_inBigStrike) - { - bool doWander = camBobT > 0.01f && (x2f4_fireButtonStates & 0x3) == 0; - if (doWander) - { - x370_gunMotionSpeedMult = 1.f; - x374_ = 0.f; - if (x364_gunStrikeCoolTimer <= 0.f && x368_idleWanderDelayTimer <= 0.f) - { - x368_idleWanderDelayTimer = 8.f; - x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Wander, mgr, 0.f, false); - x324_idleState = EIdleState::Wander; - x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::Walk, mgr); - } - x368_idleWanderDelayTimer -= dt; - x360_ -= dt; - } - if (!doWander || x834_26_animPlaying) - ResetIdle(mgr); - } - else if (x394_damageTimer > 0.f) - { - x394_damageTimer -= dt; - } - else if (!x834_31_gunMotionInFidgetBasePosition) - { - x394_damageTimer = 0.f; - x834_31_gunMotionInFidgetBasePosition = true; - x73c_gunMotion->BasePosition(true); - } - else if (!x73c_gunMotion->GetModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body")) - { - x834_30_inBigStrike = false; - x834_31_gunMotionInFidgetBasePosition = false; - } - } - else - { - switch (x3a4_fidget.Update(x2ec_lastFireButtonStates, camBobT > 0.01f, inStrikeCooldown, dt, mgr)) - { - case CFidget::EState::NoFidget: - if (x324_idleState != EIdleState::Idle) - { - x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Idle, mgr, 0.f, false); - x324_idleState = EIdleState::Idle; - } - x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::WalkNoBob, mgr); - break; - case CFidget::EState::MinorFidget: - case CFidget::EState::MajorFidget: - case CFidget::EState::HolsterBeam: - if (x324_idleState != EIdleState::NotIdle) - { - x73c_gunMotion->BasePosition(false); - x324_idleState = EIdleState::NotIdle; - } - AsyncLoadFidget(mgr); - break; - case CFidget::EState::Loading: - if (IsFidgetLoaded()) - EnterFidget(mgr); - break; - case CFidget::EState::StillMinorFidget: - case CFidget::EState::StillMajorFidget: - x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::Walk, mgr); - x833_24_notFidgeting = false; - x834_26_animPlaying = x834_25_gunMotionFidgeting ? x73c_gunMotion->IsAnimPlaying() : - x72c_currentBeam->GetSolidModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body"); - if (!x834_26_animPlaying) - { - x3a4_fidget.ResetMinor(); - ReturnToRestPose(); - } - break; - default: - break; - } - } - x550_camBob.Update(dt, mgr); - } + if (x834_26_animPlaying) + ResetIdle(mgr); + } } + } else { + if (x833_31_inFreeLook) { + if ((x2f8_stateFlags & 0x10) != 0x10) { + x73c_gunMotion->ReturnToDefault(mgr, x834_30_inBigStrike); + x740_grappleArm->ReturnToDefault(mgr, 0.f, false); + } + x833_31_inFreeLook = false; + } + x388_enterFreeLookDelayTimer = 0.f; + if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) { + x833_24_notFidgeting = + !(player.GetSurfaceRestraint() != CPlayer::ESurfaceRestraints::Water && + mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan && + (x2f4_fireButtonStates & 0x3) == 0 && x32c_chargePhase == EChargePhase::NotCharging && !x832_29_lockedOn && + (x2f8_stateFlags & 0x8) != 0x8 && x364_gunStrikeCoolTimer <= 0.f && + player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround && !player.IsInFreeLook() && + !player.GetFreeLookStickState() && x304_ == 0 && std::fabs(player.GetAngularVelocityOR().angle()) <= 0.1f && + camBobT <= 0.01f && !mgr.GetCameraManager()->IsInCinematicCamera() && + player.GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn && + player.GetGrappleState() == CPlayer::EGrappleState::None && !x834_30_inBigStrike && !x835_25_inPhazonBeam); + if (x833_24_notFidgeting) { + if (!x834_30_inBigStrike) { + bool doWander = camBobT > 0.01f && (x2f4_fireButtonStates & 0x3) == 0; + if (doWander) { + x370_gunMotionSpeedMult = 1.f; + x374_ = 0.f; + if (x364_gunStrikeCoolTimer <= 0.f && x368_idleWanderDelayTimer <= 0.f) { + x368_idleWanderDelayTimer = 8.f; + x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Wander, mgr, 0.f, false); + x324_idleState = EIdleState::Wander; + x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::Walk, mgr); + } + x368_idleWanderDelayTimer -= dt; + x360_ -= dt; + } + if (!doWander || x834_26_animPlaying) + ResetIdle(mgr); + } else if (x394_damageTimer > 0.f) { + x394_damageTimer -= dt; + } else if (!x834_31_gunMotionInFidgetBasePosition) { + x394_damageTimer = 0.f; + x834_31_gunMotionInFidgetBasePosition = true; + x73c_gunMotion->BasePosition(true); + } else if (!x73c_gunMotion->GetModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body")) { + x834_30_inBigStrike = false; + x834_31_gunMotionInFidgetBasePosition = false; + } + } else { + switch (x3a4_fidget.Update(x2ec_lastFireButtonStates, camBobT > 0.01f, inStrikeCooldown, dt, mgr)) { + case CFidget::EState::NoFidget: + if (x324_idleState != EIdleState::Idle) { + x73c_gunMotion->PlayPasAnim(SamusGun::EAnimationState::Idle, mgr, 0.f, false); + x324_idleState = EIdleState::Idle; + } + x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::WalkNoBob, mgr); + break; + case CFidget::EState::MinorFidget: + case CFidget::EState::MajorFidget: + case CFidget::EState::HolsterBeam: + if (x324_idleState != EIdleState::NotIdle) { + x73c_gunMotion->BasePosition(false); + x324_idleState = EIdleState::NotIdle; + } + AsyncLoadFidget(mgr); + break; + case CFidget::EState::Loading: + if (IsFidgetLoaded()) + EnterFidget(mgr); + break; + case CFidget::EState::StillMinorFidget: + case CFidget::EState::StillMajorFidget: + x550_camBob.SetState(CPlayerCameraBob::ECameraBobState::Walk, mgr); + x833_24_notFidgeting = false; + x834_26_animPlaying = + x834_25_gunMotionFidgeting + ? x73c_gunMotion->IsAnimPlaying() + : x72c_currentBeam->GetSolidModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body"); + if (!x834_26_animPlaying) { + x3a4_fidget.ResetMinor(); + ReturnToRestPose(); + } + break; + default: + break; + } + } + x550_camBob.Update(dt, mgr); + } + } } -static const float chargeShakeTbl[] = { -0.001f, 0.f, 0.001f }; +static const float chargeShakeTbl[] = {-0.001f, 0.f, 0.001f}; static const CMaterialFilter sAimFilter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough}); -void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateManager& mgr) -{ - CPlayer& player = mgr.GetPlayer(); - CPlayerState& playerState = *mgr.GetPlayerState(); - bool isUnmorphed = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed; +void CPlayerGun::Update(float grappleSwingT, float cameraBobT, float dt, CStateManager& mgr) { + CPlayer& player = mgr.GetPlayer(); + CPlayerState& playerState = *mgr.GetPlayerState(); + bool isUnmorphed = player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed; - bool becameFrozen; - if (isUnmorphed) - becameFrozen = !x834_29_frozen && player.GetFrozenState(); - else - becameFrozen = false; + bool becameFrozen; + if (isUnmorphed) + becameFrozen = !x834_29_frozen && player.GetFrozenState(); + else + becameFrozen = false; - bool becameThawed; - if (isUnmorphed) - becameThawed = x834_29_frozen && !player.GetFrozenState(); - else - becameThawed = false; + bool becameThawed; + if (isUnmorphed) + becameThawed = x834_29_frozen && !player.GetFrozenState(); + else + becameThawed = false; - x834_29_frozen = isUnmorphed && player.GetFrozenState(); - float advDt; - if (x834_29_frozen) - advDt = 0.f; - else - advDt = dt; + x834_29_frozen = isUnmorphed && player.GetFrozenState(); + float advDt; + if (x834_29_frozen) + advDt = 0.f; + else + advDt = dt; - bool r23 = x678_morph.GetGunState() != CGunMorph::EGunState::OutWipeDone; - if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay || r23) - x6e0_rightHandModel.AdvanceAnimation(advDt, mgr, kInvalidAreaId, true); - if (r23 && x734_loadingBeam != 0 && x734_loadingBeam != x72c_currentBeam) - { - x744_auxWeapon->LoadIdle(); - x734_loadingBeam->Update(advDt, mgr); - } - if (!x744_auxWeapon->IsLoaded()) - x744_auxWeapon->LoadIdle(); + bool r23 = x678_morph.GetGunState() != CGunMorph::EGunState::OutWipeDone; + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay || r23) + x6e0_rightHandModel.AdvanceAnimation(advDt, mgr, kInvalidAreaId, true); + if (r23 && x734_loadingBeam != 0 && x734_loadingBeam != x72c_currentBeam) { + x744_auxWeapon->LoadIdle(); + x734_loadingBeam->Update(advDt, mgr); + } + if (!x744_auxWeapon->IsLoaded()) + x744_auxWeapon->LoadIdle(); - if (becameFrozen) - { - x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); - x72c_currentBeam->EnableFrozenEffect(CGunWeapon::EFrozenFxType::Frozen); - } - else if (becameThawed) - { - x72c_currentBeam->EnableFrozenEffect(CGunWeapon::EFrozenFxType::Thawed); - } + if (becameFrozen) { + x72c_currentBeam->EnableSecondaryFx(CGunWeapon::ESecondaryFxType::None); + x72c_currentBeam->EnableFrozenEffect(CGunWeapon::EFrozenFxType::Frozen); + } else if (becameThawed) { + x72c_currentBeam->EnableFrozenEffect(CGunWeapon::EFrozenFxType::Thawed); + } - if (becameFrozen || becameThawed) - { - x2f4_fireButtonStates = 0; - x2ec_lastFireButtonStates = 0; - CancelFiring(mgr); - } + if (becameFrozen || becameThawed) { + x2f4_fireButtonStates = 0; + x2ec_lastFireButtonStates = 0; + CancelFiring(mgr); + } - x72c_currentBeam->Update(advDt, mgr); - x73c_gunMotion->Update(advDt * x370_gunMotionSpeedMult, mgr); - x740_grappleArm->Update(grappleSwingT, advDt, mgr); + x72c_currentBeam->Update(advDt, mgr); + x73c_gunMotion->Update(advDt * x370_gunMotionSpeedMult, mgr); + x740_grappleArm->Update(grappleSwingT, advDt, mgr); - if (x338_nextState != ENextState::StatusQuo) - { - if (x678_morph.GetGunState() == CGunMorph::EGunState::InWipeDone) - { - if (x338_nextState == ENextState::ChangeWeapon) - { - ChangeWeapon(playerState, mgr); - x338_nextState = ENextState::StatusQuo; - } - } - else if (!x72c_currentBeam->GetSolidModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body") || - x832_30_requestReturnToDefault) - { - bool statusQuo = true; - switch (x338_nextState) - { - case ENextState::EnterMissile: - x2f8_stateFlags &= ~0x1; - x2f8_stateFlags |= 0x6; - x318_comboAmmoIdx = 1; - x31c_missileMode = EMissleMode::Active; - break; - case ENextState::ExitMissile: - if ((x2f8_stateFlags & 0x8) != 0x8) - { - x2f8_stateFlags |= 0x1; - x2f8_stateFlags &= 0xFFE9; - } - x318_comboAmmoIdx = 0; - x31c_missileMode = EMissleMode::Inactive; - x390_cooldown = x72c_currentBeam->GetWeaponInfo().x0_coolDown; - break; - case ENextState::MissileReload: - PlayAnim(NWeaponTypes::EGunAnimType::MissileReload, false); - x338_nextState = ENextState::MissileShotDone; - statusQuo = false; - break; - case ENextState::MissileShotDone: - x2f8_stateFlags |= 0x4; - break; - case ENextState::ChangeWeapon: - ChangeWeapon(playerState, mgr); - break; - case ENextState::SetupBeam: - x390_cooldown = x72c_currentBeam->GetWeaponInfo().x0_coolDown; - x2f8_stateFlags &= ~0x8; - if ((x2f8_stateFlags & 0x8) != 0x8) - { - x2f8_stateFlags |= 0x1; - x2f8_stateFlags &= 0xFFE9; - } - x318_comboAmmoIdx = 0; - x31c_missileMode = EMissleMode::Inactive; - break; - case ENextState::EnterPhazonBeam: - if (x75c_phazonBeam->IsLoaded()) - break; - x72c_currentBeam->SetDrawHologram(true); - x75c_phazonBeam->Load(mgr, false); - x33c_phazonBeamState = EPhazonBeamState::Entering; - break; - case ENextState::ExitPhazonBeam: - if (x738_nextBeam->IsLoaded()) - break; - x72c_currentBeam->SetDrawHologram(true); - x738_nextBeam->Load(mgr, false); - x33c_phazonBeamState = EPhazonBeamState::Exiting; - break; - default: - break; - } - - if (statusQuo) - x338_nextState = ENextState::StatusQuo; - } - } - - if (x37c_rapidFireShotsDecayTimer < 0.2f) - { - x37c_rapidFireShotsDecayTimer += advDt; - } - else - { - x37c_rapidFireShotsDecayTimer = 0.f; - if (x30c_rapidFireShots > 0) - x30c_rapidFireShots -= 1; - } - - if (x32c_chargePhase != EChargePhase::NotCharging && !player.GetFrozenState()) - { - x34c_shakeX = chargeShakeTbl[mgr.GetActiveRandom()->Next() % 3] * x340_chargeBeamFactor; - x350_shakeZ = chargeShakeTbl[mgr.GetActiveRandom()->Next() % 3] * x340_chargeBeamFactor; - } - - if (!x72c_currentBeam->IsLoaded()) - return; - - GetLctrWithShake(x4d8_gunLocalXf, x73c_gunMotion->GetModelData(), "GBSE_SDK", true, true); - GetLctrWithShake(x418_beamLocalXf, x72c_currentBeam->GetSolidModelData(), "LBEAM", false, true); - GetLctrWithShake(x508_elbowLocalXf, x72c_currentBeam->GetSolidModelData(), "elbow", false, false); - x4a8_gunWorldXf = x3e8_xf * x4d8_gunLocalXf * x550_camBob.GetCameraBobTransformation(); - - if (x740_grappleArm->GetActive() && !x740_grappleArm->IsGrappling()) - UpdateLeftArmTransform(x72c_currentBeam->GetSolidModelData(), mgr); - - x6a0_motionState.Update(x2f0_pressedFireButtonStates != 0 && x832_28_readyForShot && - x32c_chargePhase < EChargePhase::AnimAndSfx && - !player.IsInFreeLook(), advDt, x4a8_gunWorldXf, mgr); - - x72c_currentBeam->GetSolidModelData().AdvanceParticles(x4a8_gunWorldXf, advDt, mgr); - x72c_currentBeam->UpdateGunFx(x380_shotSmokeTimer > 2.f && x378_shotSmokeStartTimer > 0.15f, - dt, mgr, x508_elbowLocalXf); - - zeus::CTransform beamWorldXf = x4a8_gunWorldXf * x418_beamLocalXf; - - if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && - !mgr.GetCameraManager()->IsInCinematicCamera()) - { - rstl::reserved_vector nearList; - zeus::CAABox aabb = x72c_currentBeam->GetBounds().getTransformedAABox(x4a8_gunWorldXf); - mgr.BuildNearList(nearList, aabb, sAimFilter, &player); - TUniqueId bestId = kInvalidUniqueId; - zeus::CVector3f dir = x4a8_gunWorldXf.basis[1].normalized(); - zeus::CVector3f pos = dir * -0.5f + x4a8_gunWorldXf.origin; - CRayCastResult result = mgr.RayWorldIntersection(bestId, pos, dir, 3.5f, sAimFilter, nearList); - x833_29_pointBlankWorldSurface = result.IsValid(); - if (result.IsValid()) - { - x448_elbowWorldXf = x4a8_gunWorldXf * x508_elbowLocalXf; - x448_elbowWorldXf.origin += dir * -0.5f; - beamWorldXf.origin = result.GetPoint(); - } - } - else - { - x833_29_pointBlankWorldSurface = false; - } - - zeus::CTransform beamTargetXf = x833_29_pointBlankWorldSurface ? x448_elbowWorldXf : beamWorldXf; - - zeus::CVector3f camTrans = mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); - beamWorldXf.origin += camTrans; - beamTargetXf.origin += camTrans; - - if (x832_25_chargeEffectVisible) - { - bool emitting = x833_30_canShowAuxMuzzleEffect ? x344_comboXferTimer < 1.f : false; - zeus::CVector3f scale((emitting && x832_26_comboFiring) ? (1.f - x344_comboXferTimer) * 2.f : 2.f); - x72c_currentBeam->UpdateMuzzleFx(advDt, scale, x418_beamLocalXf.origin, emitting); - CElementGen& gen = *x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]; - gen.SetGlobalOrientAndTrans(x418_beamLocalXf); - gen.SetGlobalScale(scale); - gen.SetParticleEmission(emitting); - gen.Update(advDt); - } - - if (x748_rainSplashGenerator) - x748_rainSplashGenerator->Update(advDt, mgr); - - UpdateGunLight(beamWorldXf, mgr); - ProcessGunMorph(advDt, mgr); - if (x835_26_phazonBeamMorphing) - ProcessPhazonGunMorph(advDt, mgr); - - if (x832_26_comboFiring && x77c_comboXferGen) - { - x77c_comboXferGen->SetGlobalTranslation(x418_beamLocalXf.origin); - x77c_comboXferGen->SetGlobalOrientation(x418_beamLocalXf.getRotation()); - x77c_comboXferGen->Update(advDt); - x344_comboXferTimer += advDt * 4.f; - } - - if (x35c_bombTime > 0.f) - { - x35c_bombTime -= advDt; - if (x35c_bombTime <= 0.f) - x308_bombCount = 3; - } - - if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam) && x32c_chargePhase != EChargePhase::NotCharging) - { - UpdateChargeState(advDt, mgr); - } - else - { - x340_chargeBeamFactor -= advDt; - if (x340_chargeBeamFactor < 0.f) - x340_chargeBeamFactor = 0.f; - } - - UpdateAuxWeapons(advDt, beamTargetXf, mgr); - DoUserAnimEvents(advDt, mgr); - - if (x304_ == 1 && GetTargetId(mgr) != kInvalidUniqueId) - { - if (!x832_29_lockedOn && !x832_26_comboFiring && (x2f8_stateFlags & 0x10) != 0x10) - { - x832_29_lockedOn = true; - x6a0_motionState.SetState(CMotionState::EMotionState::LockOn); - ReturnArmAndGunToDefault(mgr, true); - } - } - else - { - CancelLockOn(); - } - - UpdateWeaponFire(advDt, playerState, mgr); - UpdateGunIdle(x364_gunStrikeCoolTimer > 0.f, cameraBobT, advDt, mgr); - - if ((x2ec_lastFireButtonStates & 0x1) == 0x1) - { - x378_shotSmokeStartTimer = 0.f; - } - else if (x378_shotSmokeStartTimer < 2.f) - { - x378_shotSmokeStartTimer += advDt; - if (x378_shotSmokeStartTimer > 1.f) - { - x30c_rapidFireShots = 0; - x380_shotSmokeTimer = 0.f; - } - } - - if (x38c_muzzleEffectVisTimer > 0.f) - x38c_muzzleEffectVisTimer -= advDt; - - if (x30c_rapidFireShots > 5 && x380_shotSmokeTimer < 2.f) - x380_shotSmokeTimer += advDt; - - if (x384_gunStrikeDelayTimer > 0.f) - x384_gunStrikeDelayTimer -= advDt; - - if (x364_gunStrikeCoolTimer > 0.f) - { - x2f4_fireButtonStates = 0; - x364_gunStrikeCoolTimer -= advDt; - } - - if (isUnmorphed && (x2f8_stateFlags & 0x4) == 0x4) - { - x3a0_missileExitTimer -= advDt; - if (x3a0_missileExitTimer < 0.f) - { - x3a0_missileExitTimer = 0.f; - ExitMissile(); - } - } -} - -void CPlayerGun::PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos) -{ - const CPlayerState& playerState = *mgr.GetPlayerState(); - if (playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan) - return; - - CPlayerState::EPlayerVisor activeVisor = playerState.GetActiveVisor(mgr); - switch (activeVisor) - { - case CPlayerState::EPlayerVisor::Thermal: - x0_lights.BuildConstantAmbientLighting( - zeus::CColor(zeus::clamp(0.6f, 0.5f * x380_shotSmokeTimer + 0.6f - x378_shotSmokeStartTimer, 1.f), 1.f)); + if (x338_nextState != ENextState::StatusQuo) { + if (x678_morph.GetGunState() == CGunMorph::EGunState::InWipeDone) { + if (x338_nextState == ENextState::ChangeWeapon) { + ChangeWeapon(playerState, mgr); + x338_nextState = ENextState::StatusQuo; + } + } else if (!x72c_currentBeam->GetSolidModelData().GetAnimationData()->IsAnimTimeRemaining(0.001f, "Whole Body") || + x832_30_requestReturnToDefault) { + bool statusQuo = true; + switch (x338_nextState) { + case ENextState::EnterMissile: + x2f8_stateFlags &= ~0x1; + x2f8_stateFlags |= 0x6; + x318_comboAmmoIdx = 1; + x31c_missileMode = EMissleMode::Active; break; - case CPlayerState::EPlayerVisor::Combat: - { - zeus::CAABox aabb = x72c_currentBeam->GetBounds(zeus::CTransform::Translate(camPos) * x4a8_gunWorldXf); - if (mgr.GetNextAreaId() != kInvalidAreaId) - { - x0_lights.SetFindShadowLight(true); - x0_lights.SetShadowDynamicRangeThreshold(0.25f); - x0_lights.BuildAreaLightList(mgr, *mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()), aabb); - } - x0_lights.BuildDynamicLightList(mgr, aabb); - if (x0_lights.HasShadowLight()) - { - if (x72c_currentBeam->IsLoaded()) - { - x82c_shadow->BuildLightShadowTexture(mgr, mgr.GetNextAreaId(), - x0_lights.GetShadowLightIndex(), aabb, true, false); - } - } - else - { - x82c_shadow->ResetBlur(); + case ENextState::ExitMissile: + if ((x2f8_stateFlags & 0x8) != 0x8) { + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; } + x318_comboAmmoIdx = 0; + x31c_missileMode = EMissleMode::Inactive; + x390_cooldown = x72c_currentBeam->GetWeaponInfo().x0_coolDown; break; - } - default: + case ENextState::MissileReload: + PlayAnim(NWeaponTypes::EGunAnimType::MissileReload, false); + x338_nextState = ENextState::MissileShotDone; + statusQuo = false; break; + case ENextState::MissileShotDone: + x2f8_stateFlags |= 0x4; + break; + case ENextState::ChangeWeapon: + ChangeWeapon(playerState, mgr); + break; + case ENextState::SetupBeam: + x390_cooldown = x72c_currentBeam->GetWeaponInfo().x0_coolDown; + x2f8_stateFlags &= ~0x8; + if ((x2f8_stateFlags & 0x8) != 0x8) { + x2f8_stateFlags |= 0x1; + x2f8_stateFlags &= 0xFFE9; + } + x318_comboAmmoIdx = 0; + x31c_missileMode = EMissleMode::Inactive; + break; + case ENextState::EnterPhazonBeam: + if (x75c_phazonBeam->IsLoaded()) + break; + x72c_currentBeam->SetDrawHologram(true); + x75c_phazonBeam->Load(mgr, false); + x33c_phazonBeamState = EPhazonBeamState::Entering; + break; + case ENextState::ExitPhazonBeam: + if (x738_nextBeam->IsLoaded()) + break; + x72c_currentBeam->SetDrawHologram(true); + x738_nextBeam->Load(mgr, false); + x33c_phazonBeamState = EPhazonBeamState::Exiting; + break; + default: + break; + } + + if (statusQuo) + x338_nextState = ENextState::StatusQuo; } + } - if (x740_grappleArm->GetActive()) - x740_grappleArm->PreRender(mgr, frustum, camPos); + if (x37c_rapidFireShotsDecayTimer < 0.2f) { + x37c_rapidFireShotsDecayTimer += advDt; + } else { + x37c_rapidFireShotsDecayTimer = 0.f; + if (x30c_rapidFireShots > 0) + x30c_rapidFireShots -= 1; + } - if (x678_morph.GetGunState() != CGunMorph::EGunState::OutWipeDone || - activeVisor == CPlayerState::EPlayerVisor::XRay) - x6e0_rightHandModel.AnimationData()->PreRender(); + if (x32c_chargePhase != EChargePhase::NotCharging && !player.GetFrozenState()) { + x34c_shakeX = chargeShakeTbl[mgr.GetActiveRandom()->Next() % 3] * x340_chargeBeamFactor; + x350_shakeZ = chargeShakeTbl[mgr.GetActiveRandom()->Next() % 3] * x340_chargeBeamFactor; + } - if (x833_28_phazonBeamActive) - g_Renderer->AllocatePhazonSuitMaskTexture(); + if (!x72c_currentBeam->IsLoaded()) + return; + + GetLctrWithShake(x4d8_gunLocalXf, x73c_gunMotion->GetModelData(), "GBSE_SDK", true, true); + GetLctrWithShake(x418_beamLocalXf, x72c_currentBeam->GetSolidModelData(), "LBEAM", false, true); + GetLctrWithShake(x508_elbowLocalXf, x72c_currentBeam->GetSolidModelData(), "elbow", false, false); + x4a8_gunWorldXf = x3e8_xf * x4d8_gunLocalXf * x550_camBob.GetCameraBobTransformation(); + + if (x740_grappleArm->GetActive() && !x740_grappleArm->IsGrappling()) + UpdateLeftArmTransform(x72c_currentBeam->GetSolidModelData(), mgr); + + x6a0_motionState.Update(x2f0_pressedFireButtonStates != 0 && x832_28_readyForShot && + x32c_chargePhase < EChargePhase::AnimAndSfx && !player.IsInFreeLook(), + advDt, x4a8_gunWorldXf, mgr); + + x72c_currentBeam->GetSolidModelData().AdvanceParticles(x4a8_gunWorldXf, advDt, mgr); + x72c_currentBeam->UpdateGunFx(x380_shotSmokeTimer > 2.f && x378_shotSmokeStartTimer > 0.15f, dt, mgr, + x508_elbowLocalXf); + + zeus::CTransform beamWorldXf = x4a8_gunWorldXf * x418_beamLocalXf; + + if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && + !mgr.GetCameraManager()->IsInCinematicCamera()) { + rstl::reserved_vector nearList; + zeus::CAABox aabb = x72c_currentBeam->GetBounds().getTransformedAABox(x4a8_gunWorldXf); + mgr.BuildNearList(nearList, aabb, sAimFilter, &player); + TUniqueId bestId = kInvalidUniqueId; + zeus::CVector3f dir = x4a8_gunWorldXf.basis[1].normalized(); + zeus::CVector3f pos = dir * -0.5f + x4a8_gunWorldXf.origin; + CRayCastResult result = mgr.RayWorldIntersection(bestId, pos, dir, 3.5f, sAimFilter, nearList); + x833_29_pointBlankWorldSurface = result.IsValid(); + if (result.IsValid()) { + x448_elbowWorldXf = x4a8_gunWorldXf * x508_elbowLocalXf; + x448_elbowWorldXf.origin += dir * -0.5f; + beamWorldXf.origin = result.GetPoint(); + } + } else { + x833_29_pointBlankWorldSurface = false; + } + + zeus::CTransform beamTargetXf = x833_29_pointBlankWorldSurface ? x448_elbowWorldXf : beamWorldXf; + + zeus::CVector3f camTrans = mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr); + beamWorldXf.origin += camTrans; + beamTargetXf.origin += camTrans; + + if (x832_25_chargeEffectVisible) { + bool emitting = x833_30_canShowAuxMuzzleEffect ? x344_comboXferTimer < 1.f : false; + zeus::CVector3f scale((emitting && x832_26_comboFiring) ? (1.f - x344_comboXferTimer) * 2.f : 2.f); + x72c_currentBeam->UpdateMuzzleFx(advDt, scale, x418_beamLocalXf.origin, emitting); + CElementGen& gen = *x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]; + gen.SetGlobalOrientAndTrans(x418_beamLocalXf); + gen.SetGlobalScale(scale); + gen.SetParticleEmission(emitting); + gen.Update(advDt); + } + + if (x748_rainSplashGenerator) + x748_rainSplashGenerator->Update(advDt, mgr); + + UpdateGunLight(beamWorldXf, mgr); + ProcessGunMorph(advDt, mgr); + if (x835_26_phazonBeamMorphing) + ProcessPhazonGunMorph(advDt, mgr); + + if (x832_26_comboFiring && x77c_comboXferGen) { + x77c_comboXferGen->SetGlobalTranslation(x418_beamLocalXf.origin); + x77c_comboXferGen->SetGlobalOrientation(x418_beamLocalXf.getRotation()); + x77c_comboXferGen->Update(advDt); + x344_comboXferTimer += advDt * 4.f; + } + + if (x35c_bombTime > 0.f) { + x35c_bombTime -= advDt; + if (x35c_bombTime <= 0.f) + x308_bombCount = 3; + } + + if (playerState.ItemEnabled(CPlayerState::EItemType::ChargeBeam) && x32c_chargePhase != EChargePhase::NotCharging) { + UpdateChargeState(advDt, mgr); + } else { + x340_chargeBeamFactor -= advDt; + if (x340_chargeBeamFactor < 0.f) + x340_chargeBeamFactor = 0.f; + } + + UpdateAuxWeapons(advDt, beamTargetXf, mgr); + DoUserAnimEvents(advDt, mgr); + + if (x304_ == 1 && GetTargetId(mgr) != kInvalidUniqueId) { + if (!x832_29_lockedOn && !x832_26_comboFiring && (x2f8_stateFlags & 0x10) != 0x10) { + x832_29_lockedOn = true; + x6a0_motionState.SetState(CMotionState::EMotionState::LockOn); + ReturnArmAndGunToDefault(mgr, true); + } + } else { + CancelLockOn(); + } + + UpdateWeaponFire(advDt, playerState, mgr); + UpdateGunIdle(x364_gunStrikeCoolTimer > 0.f, cameraBobT, advDt, mgr); + + if ((x2ec_lastFireButtonStates & 0x1) == 0x1) { + x378_shotSmokeStartTimer = 0.f; + } else if (x378_shotSmokeStartTimer < 2.f) { + x378_shotSmokeStartTimer += advDt; + if (x378_shotSmokeStartTimer > 1.f) { + x30c_rapidFireShots = 0; + x380_shotSmokeTimer = 0.f; + } + } + + if (x38c_muzzleEffectVisTimer > 0.f) + x38c_muzzleEffectVisTimer -= advDt; + + if (x30c_rapidFireShots > 5 && x380_shotSmokeTimer < 2.f) + x380_shotSmokeTimer += advDt; + + if (x384_gunStrikeDelayTimer > 0.f) + x384_gunStrikeDelayTimer -= advDt; + + if (x364_gunStrikeCoolTimer > 0.f) { + x2f4_fireButtonStates = 0; + x364_gunStrikeCoolTimer -= advDt; + } + + if (isUnmorphed && (x2f8_stateFlags & 0x4) == 0x4) { + x3a0_missileExitTimer -= advDt; + if (x3a0_missileExitTimer < 0.f) { + x3a0_missileExitTimer = 0.f; + ExitMissile(); + } + } } -static const CModelFlags kThermalFlags[] = -{ - {0, 0, 3, zeus::CColor::skWhite}, - {5, 0, 3, zeus::CColor(0.f, 0.5f)}, - {0, 0, 3, zeus::CColor::skWhite}, - {0, 0, 3, zeus::CColor::skWhite} -}; +void CPlayerGun::PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos) { + const CPlayerState& playerState = *mgr.GetPlayerState(); + if (playerState.GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan) + return; -void CPlayerGun::RenderEnergyDrainEffects(const CStateManager& mgr) const -{ - if (TCastToConstPtr player = mgr.GetObjectById(x538_playerId)) - { - for (const auto& source : player->GetEnergyDrain().GetEnergyDrainSources()) - { - if (auto* metroid = - CPatterned::CastTo(mgr.GetObjectById(source.GetEnergyDrainSourceId()))) - { - metroid->RenderHitGunEffect(); - return; - } - } + CPlayerState::EPlayerVisor activeVisor = playerState.GetActiveVisor(mgr); + switch (activeVisor) { + case CPlayerState::EPlayerVisor::Thermal: + x0_lights.BuildConstantAmbientLighting( + zeus::CColor(zeus::clamp(0.6f, 0.5f * x380_shotSmokeTimer + 0.6f - x378_shotSmokeStartTimer, 1.f), 1.f)); + break; + case CPlayerState::EPlayerVisor::Combat: { + zeus::CAABox aabb = x72c_currentBeam->GetBounds(zeus::CTransform::Translate(camPos) * x4a8_gunWorldXf); + if (mgr.GetNextAreaId() != kInvalidAreaId) { + x0_lights.SetFindShadowLight(true); + x0_lights.SetShadowDynamicRangeThreshold(0.25f); + x0_lights.BuildAreaLightList(mgr, *mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()), aabb); } + x0_lights.BuildDynamicLightList(mgr, aabb); + if (x0_lights.HasShadowLight()) { + if (x72c_currentBeam->IsLoaded()) { + x82c_shadow->BuildLightShadowTexture(mgr, mgr.GetNextAreaId(), x0_lights.GetShadowLightIndex(), aabb, true, + false); + } + } else { + x82c_shadow->ResetBlur(); + } + break; + } + default: + break; + } + + if (x740_grappleArm->GetActive()) + x740_grappleArm->PreRender(mgr, frustum, camPos); + + if (x678_morph.GetGunState() != CGunMorph::EGunState::OutWipeDone || activeVisor == CPlayerState::EPlayerVisor::XRay) + x6e0_rightHandModel.AnimationData()->PreRender(); + + if (x833_28_phazonBeamActive) + g_Renderer->AllocatePhazonSuitMaskTexture(); } -void CPlayerGun::DrawArm(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const -{ - const CPlayer& player = mgr.GetPlayer(); - if (!x740_grappleArm->GetActive() || x740_grappleArm->GetAnimState() == CGrappleArm::EArmState::Done) +static const CModelFlags kThermalFlags[] = {{0, 0, 3, zeus::CColor::skWhite}, + {5, 0, 3, zeus::CColor(0.f, 0.5f)}, + {0, 0, 3, zeus::CColor::skWhite}, + {0, 0, 3, zeus::CColor::skWhite}}; + +void CPlayerGun::RenderEnergyDrainEffects(const CStateManager& mgr) const { + if (TCastToConstPtr player = mgr.GetObjectById(x538_playerId)) { + for (const auto& source : player->GetEnergyDrain().GetEnergyDrainSources()) { + if (auto* metroid = CPatterned::CastTo(mgr.GetObjectById(source.GetEnergyDrainSourceId()))) { + metroid->RenderHitGunEffect(); return; - - if (player.GetGrappleState() != CPlayer::EGrappleState::None || - x740_grappleArm->GetTransform().basis[1].dot(player.GetTransform().basis[1]) > 0.1f) - { - CModelFlags useFlags; - if (x740_grappleArm->IsArmMoving()) - useFlags = flags; - else - useFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); - - x740_grappleArm->Render(mgr, pos, useFlags, &x0_lights); + } } + } } -zeus::CVector3f CPlayerGun::ConvertToScreenSpace(const zeus::CVector3f& pos, const CGameCamera& cam) const -{ - return cam.ConvertToScreenSpace(pos); +void CPlayerGun::DrawArm(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const { + const CPlayer& player = mgr.GetPlayer(); + if (!x740_grappleArm->GetActive() || x740_grappleArm->GetAnimState() == CGrappleArm::EArmState::Done) + return; + + if (player.GetGrappleState() != CPlayer::EGrappleState::None || + x740_grappleArm->GetTransform().basis[1].dot(player.GetTransform().basis[1]) > 0.1f) { + CModelFlags useFlags; + if (x740_grappleArm->IsArmMoving()) + useFlags = flags; + else + useFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); + + x740_grappleArm->Render(mgr, pos, useFlags, &x0_lights); + } } -void CPlayerGun::CopyScreenTex() -{ - // Copy lower right quadrant to gpCopyTexBuf as RGBA8 - CGraphics::ResolveSpareTexture(g_Viewport); +zeus::CVector3f CPlayerGun::ConvertToScreenSpace(const zeus::CVector3f& pos, const CGameCamera& cam) const { + return cam.ConvertToScreenSpace(pos); } -void CPlayerGun::DrawScreenTex(float z) const -{ - // Use CopyScreenTex rendering to draw over framebuffer pixels in front of `z` - // This is accomplished using orthographic projection quad with sweeping `y` coordinates - // Depth is set to GEQUAL to obscure pixels in front rather than behind - m_screenQuad.draw(zeus::CColor::skWhite, 1.f, CTexturedQuadFilter::DefaultRect, z); +void CPlayerGun::CopyScreenTex() { + // Copy lower right quadrant to gpCopyTexBuf as RGBA8 + CGraphics::ResolveSpareTexture(g_Viewport); } -void CPlayerGun::DrawClipCube(const zeus::CAABox& aabb) const -{ - // Render AABB as completely transparent object, only modifying Z-buffer - // AABB has already been set in constructor (since it's constant) - m_aaboxShader.draw(zeus::CColor::skClear); +void CPlayerGun::DrawScreenTex(float z) const { + // Use CopyScreenTex rendering to draw over framebuffer pixels in front of `z` + // This is accomplished using orthographic projection quad with sweeping `y` coordinates + // Depth is set to GEQUAL to obscure pixels in front rather than behind + m_screenQuad.draw(zeus::CColor::skWhite, 1.f, CTexturedQuadFilter::DefaultRect, z); +} + +void CPlayerGun::DrawClipCube(const zeus::CAABox& aabb) const { + // Render AABB as completely transparent object, only modifying Z-buffer + // AABB has already been set in constructor (since it's constant) + m_aaboxShader.draw(zeus::CColor::skClear); } static const CModelFlags kHandThermalFlag = {7, 0, 3, zeus::CColor::skWhite}; static const CModelFlags kHandHoloFlag = {1, 0, 3, zeus::CColor(0.75f, 0.5f, 0.f, 1.f)}; -void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const -{ - CGraphics::CProjectionState projState = CGraphics::GetProjectionState(); - CModelFlags useFlags = flags; +void CPlayerGun::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const { + CGraphics::CProjectionState projState = CGraphics::GetProjectionState(); + CModelFlags useFlags = flags; + if (x0_lights.HasShadowLight()) + useFlags.m_extendedShader = EExtendedShader::WorldShadow; + CModelFlags beamFlags = useFlags; + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal) + beamFlags = kThermalFlags[int(x310_currentBeam)]; + else if (x835_26_phazonBeamMorphing) + beamFlags.x4_color = zeus::CColor::lerp(zeus::CColor::skWhite, zeus::CColor::skBlack, x39c_phazonMorphT); + + const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + CGraphics::SetDepthRange(DEPTH_GUN, DEPTH_WORLD); + zeus::CTransform offsetWorldXf = zeus::CTransform::Translate(pos) * x4a8_gunWorldXf; + zeus::CTransform elbowOffsetXf = offsetWorldXf * x508_elbowLocalXf; + if (x32c_chargePhase != EChargePhase::NotCharging && (x2f8_stateFlags & 0x10) != 0x10) + offsetWorldXf.origin += zeus::CVector3f(x34c_shakeX, 0.f, x350_shakeZ); + + zeus::CTransform oldViewMtx = CGraphics::g_ViewMatrix; + CGraphics::SetViewPointMatrix(offsetWorldXf.inverse() * oldViewMtx); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + if (x32c_chargePhase >= EChargePhase::FxGrown && x32c_chargePhase < EChargePhase::ComboXfer) + x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]->Render(); + + if (x832_25_chargeEffectVisible && (x38c_muzzleEffectVisTimer > 0.f || x32c_chargePhase > EChargePhase::AnimAndSfx)) + x72c_currentBeam->DrawMuzzleFx(mgr); + + if (x678_morph.GetGunState() == CGunMorph::EGunState::InWipe || + x678_morph.GetGunState() == CGunMorph::EGunState::OutWipe) + x774_holoTransitionGen->Render(); + + CGraphics::SetViewPointMatrix(oldViewMtx); + if ((x2f8_stateFlags & 0x10) == 0x10) + x744_auxWeapon->RenderMuzzleFx(); + + x72c_currentBeam->PreRenderGunFx(mgr, offsetWorldXf); + bool drawSuitArm = + !x740_grappleArm->IsGrappling() && mgr.GetPlayer().GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn; + x73c_gunMotion->Draw(mgr, offsetWorldXf); + + switch (x678_morph.GetGunState()) { + case CGunMorph::EGunState::OutWipeDone: if (x0_lights.HasShadowLight()) - useFlags.m_extendedShader = EExtendedShader::WorldShadow; - CModelFlags beamFlags = useFlags; - if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal) - beamFlags = kThermalFlags[int(x310_currentBeam)]; - else if (x835_26_phazonBeamMorphing) - beamFlags.x4_color = zeus::CColor::lerp(zeus::CColor::skWhite, zeus::CColor::skBlack, x39c_phazonMorphT); + x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) { + x6e0_rightHandModel.Render(mgr, elbowOffsetXf * zeus::CTransform::Translate(0.f, -0.2f, 0.02f), &x0_lights, + mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal + ? kHandThermalFlag + : kHandHoloFlag); + } + DrawArm(mgr, pos, useFlags); + x72c_currentBeam->Draw(drawSuitArm, mgr, offsetWorldXf, beamFlags, &x0_lights); + x82c_shadow->DisableModelProjectedShadow(); + break; + case CGunMorph::EGunState::InWipeDone: + case CGunMorph::EGunState::InWipe: + case CGunMorph::EGunState::OutWipe: + if (x678_morph.GetGunState() != CGunMorph::EGunState::InWipeDone) { + zeus::CTransform morphXf = elbowOffsetXf * zeus::CTransform::Translate(0.f, x678_morph.GetYLerp(), 0.f); + CopyScreenTex(); + x6e0_rightHandModel.Render(mgr, elbowOffsetXf * zeus::CTransform::Translate(0.f, -0.2f, 0.02f), &x0_lights, + mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal + ? kHandThermalFlag + : kHandHoloFlag); + x72c_currentBeam->DrawHologram(mgr, offsetWorldXf, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); + DrawScreenTex(ConvertToScreenSpace(morphXf.origin, *cam).z()); + if (x0_lights.HasShadowLight()) + x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); + CGraphics::SetModelMatrix(morphXf); + DrawClipCube(x6c8_hologramClipCube); + x72c_currentBeam->Draw(drawSuitArm, mgr, offsetWorldXf, beamFlags, &x0_lights); + x82c_shadow->DisableModelProjectedShadow(); + } else { + x6e0_rightHandModel.Render(mgr, elbowOffsetXf * zeus::CTransform::Translate(0.f, -0.2f, 0.02f), &x0_lights, + mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal + ? kHandThermalFlag + : kHandHoloFlag); + x72c_currentBeam->DrawHologram(mgr, offsetWorldXf, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); + if (x0_lights.HasShadowLight()) + x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); + DrawArm(mgr, pos, useFlags); + x82c_shadow->DisableModelProjectedShadow(); + } + break; + } - const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - CGraphics::SetDepthRange(DEPTH_GUN, DEPTH_WORLD); - zeus::CTransform offsetWorldXf = zeus::CTransform::Translate(pos) * x4a8_gunWorldXf; - zeus::CTransform elbowOffsetXf = offsetWorldXf * x508_elbowLocalXf; - if (x32c_chargePhase != EChargePhase::NotCharging && (x2f8_stateFlags & 0x10) != 0x10) - offsetWorldXf.origin += zeus::CVector3f(x34c_shakeX, 0.f, x350_shakeZ); + oldViewMtx = CGraphics::g_ViewMatrix; + CGraphics::SetViewPointMatrix(offsetWorldXf.inverse() * oldViewMtx); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + x72c_currentBeam->PostRenderGunFx(mgr, offsetWorldXf); + if (x832_26_comboFiring && x77c_comboXferGen) + x77c_comboXferGen->Render(); + CGraphics::SetViewPointMatrix(oldViewMtx); - zeus::CTransform oldViewMtx = CGraphics::g_ViewMatrix; - CGraphics::SetViewPointMatrix(offsetWorldXf.inverse() * oldViewMtx); - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - if (x32c_chargePhase >= EChargePhase::FxGrown && x32c_chargePhase < EChargePhase::ComboXfer) - x800_auxMuzzleGenerators[int(x320_currentAuxBeam)]->Render(); + RenderEnergyDrainEffects(mgr); - if (x832_25_chargeEffectVisible && - (x38c_muzzleEffectVisTimer > 0.f || x32c_chargePhase > EChargePhase::AnimAndSfx)) - x72c_currentBeam->DrawMuzzleFx(mgr); + CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); + CGraphics::SetProjectionState(projState); +} - if (x678_morph.GetGunState() == CGunMorph::EGunState::InWipe || - x678_morph.GetGunState() == CGunMorph::EGunState::OutWipe) - x774_holoTransitionGen->Render(); +void CPlayerGun::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + if (x72c_currentBeam->HasSolidModelData()) + x72c_currentBeam->GetSolidModelData().RenderParticles(frustum); +} - CGraphics::SetViewPointMatrix(oldViewMtx); - if ((x2f8_stateFlags & 0x10) == 0x10) - x744_auxWeapon->RenderMuzzleFx(); - - x72c_currentBeam->PreRenderGunFx(mgr, offsetWorldXf); - bool drawSuitArm = !x740_grappleArm->IsGrappling() && - mgr.GetPlayer().GetGunHolsterState() == CPlayer::EGunHolsterState::Drawn; - x73c_gunMotion->Draw(mgr, offsetWorldXf); - - switch (x678_morph.GetGunState()) - { - case CGunMorph::EGunState::OutWipeDone: - if (x0_lights.HasShadowLight()) - x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); - if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) - { - x6e0_rightHandModel.Render(mgr, elbowOffsetXf * zeus::CTransform::Translate(0.f, -0.2f, 0.02f), &x0_lights, - mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal ? - kHandThermalFlag : kHandHoloFlag); - } - DrawArm(mgr, pos, useFlags); - x72c_currentBeam->Draw(drawSuitArm, mgr, offsetWorldXf, beamFlags, &x0_lights); - x82c_shadow->DisableModelProjectedShadow(); - break; - case CGunMorph::EGunState::InWipeDone: - case CGunMorph::EGunState::InWipe: - case CGunMorph::EGunState::OutWipe: - if (x678_morph.GetGunState() != CGunMorph::EGunState::InWipeDone) - { - zeus::CTransform morphXf = elbowOffsetXf * zeus::CTransform::Translate(0.f, x678_morph.GetYLerp(), 0.f); - CopyScreenTex(); - x6e0_rightHandModel.Render(mgr, elbowOffsetXf * zeus::CTransform::Translate(0.f, -0.2f, 0.02f), &x0_lights, - mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal ? - kHandThermalFlag : kHandHoloFlag); - x72c_currentBeam->DrawHologram(mgr, offsetWorldXf, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); - DrawScreenTex(ConvertToScreenSpace(morphXf.origin, *cam).z()); - if (x0_lights.HasShadowLight()) - x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); - CGraphics::SetModelMatrix(morphXf); - DrawClipCube(x6c8_hologramClipCube); - x72c_currentBeam->Draw(drawSuitArm, mgr, offsetWorldXf, beamFlags, &x0_lights); - x82c_shadow->DisableModelProjectedShadow(); - } - else - { - x6e0_rightHandModel.Render(mgr, elbowOffsetXf * zeus::CTransform::Translate(0.f, -0.2f, 0.02f), &x0_lights, - mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal ? - kHandThermalFlag : kHandHoloFlag); - x72c_currentBeam->DrawHologram(mgr, offsetWorldXf, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); - if (x0_lights.HasShadowLight()) - x82c_shadow->EnableModelProjectedShadow(offsetWorldXf, x0_lights.GetShadowLightArrIndex(), 2.15f); - DrawArm(mgr, pos, useFlags); - x82c_shadow->DisableModelProjectedShadow(); - } - break; +void CPlayerGun::DropBomb(EBWeapon weapon, CStateManager& mgr) { + if (weapon == EBWeapon::Bomb) { + if (x32c_chargePhase != EChargePhase::NotCharging) { + x32c_chargePhase = EChargePhase::ChargeDone; + return; } - oldViewMtx = CGraphics::g_ViewMatrix; - CGraphics::SetViewPointMatrix(offsetWorldXf.inverse() * oldViewMtx); - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - x72c_currentBeam->PostRenderGunFx(mgr, offsetWorldXf); - if (x832_26_comboFiring && x77c_comboXferGen) - x77c_comboXferGen->Render(); - CGraphics::SetViewPointMatrix(oldViewMtx); + if (x308_bombCount <= 0) + return; - RenderEnergyDrainEffects(mgr); + zeus::CVector3f plPos = mgr.GetPlayer().GetTranslation(); + zeus::CTransform xf = + zeus::CTransform::Translate({plPos.x(), plPos.y(), plPos.z() + g_tweakPlayer->GetPlayerBallHalfExtent()}); + CBomb* bomb = + new CBomb(x784_bombEffects[u32(weapon)][0], x784_bombEffects[u32(weapon)][1], mgr.AllocateUniqueId(), + mgr.GetPlayer().GetAreaId(), x538_playerId, x354_bombFuseTime, xf, g_tweakPlayerGun->GetBombInfo()); + mgr.AddObject(bomb); - CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); - CGraphics::SetProjectionState(projState); + if (x308_bombCount == 3) + x35c_bombTime = x358_bombDropDelayTime; + + --x308_bombCount; + if (TCastToPtr plat = mgr.ObjectById(mgr.GetPlayer().GetRidingPlatformId())) + plat->AddSlave(bomb->GetUniqueId(), mgr); + } else if (weapon == EBWeapon::PowerBomb) { + mgr.GetPlayerState()->DecrPickup(CPlayerState::EItemType::PowerBombs, 1); + x53a_powerBomb = DropPowerBomb(mgr); + } } -void CPlayerGun::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - if (x72c_currentBeam->HasSolidModelData()) - x72c_currentBeam->GetSolidModelData().RenderParticles(frustum); -} - -void CPlayerGun::DropBomb(EBWeapon weapon, CStateManager& mgr) -{ - if (weapon == EBWeapon::Bomb) - { - if (x32c_chargePhase != EChargePhase::NotCharging) - { - x32c_chargePhase = EChargePhase::ChargeDone; - return; - } - - if (x308_bombCount <= 0) - return; - - zeus::CVector3f plPos = mgr.GetPlayer().GetTranslation(); - zeus::CTransform xf = zeus::CTransform::Translate({plPos.x(), - plPos.y(), plPos.z() + g_tweakPlayer->GetPlayerBallHalfExtent()}); - CBomb* bomb = - new CBomb(x784_bombEffects[u32(weapon)][0], x784_bombEffects[u32(weapon)][1], mgr.AllocateUniqueId(), - mgr.GetPlayer().GetAreaId(), x538_playerId, x354_bombFuseTime, xf,g_tweakPlayerGun->GetBombInfo()); - mgr.AddObject(bomb); - - if (x308_bombCount == 3) - x35c_bombTime = x358_bombDropDelayTime; - - --x308_bombCount; - if (TCastToPtr plat = mgr.ObjectById(mgr.GetPlayer().GetRidingPlatformId())) - plat->AddSlave(bomb->GetUniqueId(), mgr); - } - else if (weapon == EBWeapon::PowerBomb) - { - mgr.GetPlayerState()->DecrPickup(CPlayerState::EItemType::PowerBombs, 1); - x53a_powerBomb = DropPowerBomb(mgr); - } -} - -TUniqueId CPlayerGun::DropPowerBomb(CStateManager& mgr) -{ - CDamageInfo dInfo = (mgr.GetPlayer().GetDeathTime() <= 0.f ? g_tweakPlayerGun->GetPowerBombInfo() - : CDamageInfo(CWeaponMode::PowerBomb(), 0.f, 0.f, 0.f)); - - TUniqueId uid = mgr.AllocateUniqueId(); - zeus::CVector3f plVec = mgr.GetPlayer().GetTranslation(); - zeus::CTransform xf = zeus::CTransform::Translate({plVec.x(), - plVec.y(), - plVec.z() + g_tweakPlayer->GetPlayerBallHalfExtent()}); - CPowerBomb* pBomb = new CPowerBomb(x784_bombEffects[1][0], uid, kInvalidAreaId, x538_playerId, xf, dInfo); - mgr.AddObject(*pBomb); - return uid; -} +TUniqueId CPlayerGun::DropPowerBomb(CStateManager& mgr) { + CDamageInfo dInfo = (mgr.GetPlayer().GetDeathTime() <= 0.f ? g_tweakPlayerGun->GetPowerBombInfo() + : CDamageInfo(CWeaponMode::PowerBomb(), 0.f, 0.f, 0.f)); + + TUniqueId uid = mgr.AllocateUniqueId(); + zeus::CVector3f plVec = mgr.GetPlayer().GetTranslation(); + zeus::CTransform xf = + zeus::CTransform::Translate({plVec.x(), plVec.y(), plVec.z() + g_tweakPlayer->GetPlayerBallHalfExtent()}); + CPowerBomb* pBomb = new CPowerBomb(x784_bombEffects[1][0], uid, kInvalidAreaId, x538_playerId, xf, dInfo); + mgr.AddObject(*pBomb); + return uid; } +} // namespace urde diff --git a/Runtime/Weapon/CPlayerGun.hpp b/Runtime/Weapon/CPlayerGun.hpp index f6b557594..9fd57782e 100644 --- a/Runtime/Weapon/CPlayerGun.hpp +++ b/Runtime/Weapon/CPlayerGun.hpp @@ -22,395 +22,340 @@ #include "Graphics/Shaders/CTexturedQuadFilter.hpp" #include "Graphics/Shaders/CAABoxShader.hpp" -namespace urde -{ +namespace urde { struct CFinalInput; -class CPlayerGun -{ +class CPlayerGun { public: - static float skTractorBeamFactor; - enum class EMissleMode - { - Inactive, - Active - }; - enum class EBWeapon - { - Bomb, - PowerBomb - }; - enum class EPhazonBeamState - { - Inactive, - Entering, - Exiting, - Active - }; - enum class EChargePhase - { - NotCharging, - ChargeRequested, - AnimAndSfx, - FxGrowing, - FxGrown, - ComboXfer, - ComboXferDone, - ComboFire, - ComboFireDone, - ChargeCancelled, - ChargeDone - }; - enum class ENextState - { - StatusQuo, - EnterMissile, - ExitMissile, - MissileShotDone, - MissileReload, - ChangeWeapon, - SetupBeam, - Seven, - EnterPhazonBeam, - ExitPhazonBeam - }; - enum class EIdleState - { - NotIdle, - Wander, - Idle, - Three, - Four - }; + static float skTractorBeamFactor; + enum class EMissleMode { Inactive, Active }; + enum class EBWeapon { Bomb, PowerBomb }; + enum class EPhazonBeamState { Inactive, Entering, Exiting, Active }; + enum class EChargePhase { + NotCharging, + ChargeRequested, + AnimAndSfx, + FxGrowing, + FxGrown, + ComboXfer, + ComboXferDone, + ComboFire, + ComboFireDone, + ChargeCancelled, + ChargeDone + }; + enum class ENextState { + StatusQuo, + EnterMissile, + ExitMissile, + MissileShotDone, + MissileReload, + ChangeWeapon, + SetupBeam, + Seven, + EnterPhazonBeam, + ExitPhazonBeam + }; + enum class EIdleState { NotIdle, Wander, Idle, Three, Four }; + private: - class CGunMorph - { - public: - enum class EGunState - { - InWipeDone, - OutWipeDone, - InWipe, - OutWipe - }; - enum class EMorphEvent - { - None, - InWipeDone, - OutWipeDone - }; - enum class EDir - { - In, - Out, - Done - }; - private: - float x0_yLerp = 0.f; - float x4_gunTransformTime; - float x8_remTime = 0.f; - float xc_speed = 0.1f; - float x10_holoHoldTime; - float x14_remHoldTime = 2.f; - float x18_transitionFactor = 1.f; - EDir x1c_dir = EDir::Done; - EGunState x20_gunState = EGunState::OutWipeDone; + class CGunMorph { + public: + enum class EGunState { InWipeDone, OutWipeDone, InWipe, OutWipe }; + enum class EMorphEvent { None, InWipeDone, OutWipeDone }; + enum class EDir { In, Out, Done }; - union - { - struct - { - bool x24_24_morphing : 1; - bool x24_25_weaponChanged : 1; - }; - u32 _dummy = 0; - }; + private: + float x0_yLerp = 0.f; + float x4_gunTransformTime; + float x8_remTime = 0.f; + float xc_speed = 0.1f; + float x10_holoHoldTime; + float x14_remHoldTime = 2.f; + float x18_transitionFactor = 1.f; + EDir x1c_dir = EDir::Done; + EGunState x20_gunState = EGunState::OutWipeDone; - public: - CGunMorph(float gunTransformTime, float holoHoldTime) - : x4_gunTransformTime(gunTransformTime), x10_holoHoldTime(std::fabs(holoHoldTime)) {} - float GetYLerp() const { return x0_yLerp; } - float GetTransitionFactor() const { return x18_transitionFactor; } - EGunState GetGunState() const { return x20_gunState; } - void SetWeaponChanged() { x24_25_weaponChanged = true; } - EMorphEvent Update(float inY, float outY, float dt); - void StartWipe(EDir dir); + union { + struct { + bool x24_24_morphing : 1; + bool x24_25_weaponChanged : 1; + }; + u32 _dummy = 0; }; - class CMotionState - { - public: - enum class EMotionState - { - Zero, - One, - LockOn, - CancelLockOn - }; - enum class EFireState - { - NotFiring, - StartFire, - Firing - }; - private: - static float gGunExtendDistance; - bool x0_24_extendParabola = true; - float x4_extendParabolaDelayTimer = 0.f; - float x8_fireTime = 0.f; - float xc_curExtendDist = 0.f; - float x10_curRotation = 0.f; - float x14_rotationT = 0.f; - float x18_startRotation = 0.f; - float x1c_endRotation = 0.f; - EMotionState x20_state = EMotionState::Zero; - EFireState x24_fireState = EFireState::NotFiring; - public: - static void SetExtendDistance(float d) { gGunExtendDistance = d; } - void SetState(EMotionState state) { x20_state = state; } - void Update(bool firing, float dt, zeus::CTransform& xf, CStateManager& mgr); + public: + CGunMorph(float gunTransformTime, float holoHoldTime) + : x4_gunTransformTime(gunTransformTime), x10_holoHoldTime(std::fabs(holoHoldTime)) {} + float GetYLerp() const { return x0_yLerp; } + float GetTransitionFactor() const { return x18_transitionFactor; } + EGunState GetGunState() const { return x20_gunState; } + void SetWeaponChanged() { x24_25_weaponChanged = true; } + EMorphEvent Update(float inY, float outY, float dt); + void StartWipe(EDir dir); + }; + + class CMotionState { + public: + enum class EMotionState { Zero, One, LockOn, CancelLockOn }; + enum class EFireState { NotFiring, StartFire, Firing }; + + private: + static float gGunExtendDistance; + bool x0_24_extendParabola = true; + float x4_extendParabolaDelayTimer = 0.f; + float x8_fireTime = 0.f; + float xc_curExtendDist = 0.f; + float x10_curRotation = 0.f; + float x14_rotationT = 0.f; + float x18_startRotation = 0.f; + float x1c_endRotation = 0.f; + EMotionState x20_state = EMotionState::Zero; + EFireState x24_fireState = EFireState::NotFiring; + + public: + static void SetExtendDistance(float d) { gGunExtendDistance = d; } + void SetState(EMotionState state) { x20_state = state; } + void Update(bool firing, float dt, zeus::CTransform& xf, CStateManager& mgr); + }; + + CActorLights x0_lights; + CSfxHandle x2e0_chargeSfx; + CSfxHandle x2e4_invalidSfx; + CSfxHandle x2e8_phazonBeamSfx; + // 0x1: FireOrBomb, 0x2: MissileOrPowerBomb + u32 x2ec_lastFireButtonStates = 0; + u32 x2f0_pressedFireButtonStates = 0; + u32 x2f4_fireButtonStates = 0; + // 0x1: beam mode, 0x2: missile mode, 0x4: missile ready, 0x8: morphing, 0x10: combo fire + u32 x2f8_stateFlags = 0x1; + u32 x2fc_fidgetAnimBits = 0; + u32 x300_remainingMissiles = 0; + u32 x304_ = 0; + u32 x308_bombCount = 3; + u32 x30c_rapidFireShots = 0; + CPlayerState::EBeamId x310_currentBeam = CPlayerState::EBeamId::Power; + CPlayerState::EBeamId x314_nextBeam = CPlayerState::EBeamId::Power; + u32 x318_comboAmmoIdx = 0; + EMissleMode x31c_missileMode = EMissleMode::Inactive; + CPlayerState::EBeamId x320_currentAuxBeam = CPlayerState::EBeamId::Power; + EIdleState x324_idleState = EIdleState::Four; + float x328_animSfxPitch = 0.f; + EChargePhase x32c_chargePhase = EChargePhase::NotCharging; + EChargeState x330_chargeState = EChargeState::Normal; + u32 x334_ = 0; + ENextState x338_nextState = ENextState::StatusQuo; + EPhazonBeamState x33c_phazonBeamState = EPhazonBeamState::Inactive; + float x340_chargeBeamFactor = 0.f; + float x344_comboXferTimer = 0.f; + float x348_chargeCancelTimer = 0.f; + float x34c_shakeX = 0.f; + float x350_shakeZ = 0.f; + float x354_bombFuseTime; + float x358_bombDropDelayTime; + float x35c_bombTime = 0.f; + float x360_ = 0.f; + float x364_gunStrikeCoolTimer = 0.f; + float x368_idleWanderDelayTimer = 0.f; + float x36c_ = 1.f; + float x370_gunMotionSpeedMult = 1.f; + float x374_ = 0.f; + float x378_shotSmokeStartTimer = 0.f; + float x37c_rapidFireShotsDecayTimer = 0.f; + float x380_shotSmokeTimer = 0.f; + float x384_gunStrikeDelayTimer = 0.f; + float x388_enterFreeLookDelayTimer = 0.f; + float x38c_muzzleEffectVisTimer = 0.f; + float x390_cooldown = 0.f; + float x394_damageTimer = 0.f; + float x398_damageAmt = 0.f; + float x39c_phazonMorphT = 0.f; + float x3a0_missileExitTimer = 0.f; + CFidget x3a4_fidget; + zeus::CVector3f x3dc_damageLocation; + zeus::CTransform x3e8_xf; + zeus::CTransform x418_beamLocalXf; + zeus::CTransform x448_elbowWorldXf; + zeus::CTransform x478_assistAimXf; + zeus::CTransform x4a8_gunWorldXf; + zeus::CTransform x4d8_gunLocalXf; + zeus::CTransform x508_elbowLocalXf; + TUniqueId x538_playerId; + TUniqueId x53a_powerBomb = kInvalidUniqueId; + TUniqueId x53c_lightId = kInvalidUniqueId; + std::vector x540_handAnimTokens; + CPlayerCameraBob x550_camBob; + u32 x658_ = 1; + float x65c_ = 0.f; + float x660_ = 0.f; + float x664_ = 0.f; + float x668_aimVerticalSpeed; + float x66c_aimHorizontalSpeed; + std::pair x670_animSfx = {0xffff, {}}; + CGunMorph x678_morph; + CMotionState x6a0_motionState; + zeus::CAABox x6c8_hologramClipCube; + CModelData x6e0_rightHandModel; + CGunWeapon* x72c_currentBeam = nullptr; + CGunWeapon* x730_outgoingBeam = nullptr; + CGunWeapon* x734_loadingBeam = nullptr; + CGunWeapon* x738_nextBeam = nullptr; + std::unique_ptr x73c_gunMotion; + std::unique_ptr x740_grappleArm; + std::unique_ptr x744_auxWeapon; + std::unique_ptr x748_rainSplashGenerator; + std::unique_ptr x74c_powerBeam; + std::unique_ptr x750_iceBeam; + std::unique_ptr x754_waveBeam; + std::unique_ptr x758_plasmaBeam; + std::unique_ptr x75c_phazonBeam; + CGunWeapon* x760_selectableBeams[4] = {}; // Used to be reserved_vector + std::unique_ptr x774_holoTransitionGen; + std::unique_ptr x77c_comboXferGen; + rstl::reserved_vector, 2>, 2> x784_bombEffects; + rstl::reserved_vector, 5> x7c0_auxMuzzleEffects; + rstl::reserved_vector, 5> x800_auxMuzzleGenerators; + std::unique_ptr x82c_shadow; + s16 x830_chargeRumbleHandle = -1; + + union { + struct { + bool x832_24_cancellingCharge : 1; + bool x832_25_chargeEffectVisible : 1; + bool x832_26_comboFiring : 1; + bool x832_27_chargeAnimStarted : 1; + bool x832_28_readyForShot : 1; + bool x832_29_lockedOn : 1; + bool x832_30_requestReturnToDefault : 1; + bool x832_31_inRestPose : 1; + + bool x833_24_notFidgeting : 1; + bool x833_25_ : 1; + bool x833_26_ : 1; + bool x833_27_ : 1; + bool x833_28_phazonBeamActive : 1; + bool x833_29_pointBlankWorldSurface : 1; + bool x833_30_canShowAuxMuzzleEffect : 1; + bool x833_31_inFreeLook : 1; + + bool x834_24_charging : 1; + bool x834_25_gunMotionFidgeting : 1; + bool x834_26_animPlaying : 1; + bool x834_27_underwater : 1; + bool x834_28_requestImmediateRecharge : 1; + bool x834_29_frozen : 1; + bool x834_30_inBigStrike : 1; + bool x834_31_gunMotionInFidgetBasePosition : 1; + + bool x835_24_canFirePhazon : 1; + bool x835_25_inPhazonBeam : 1; + bool x835_26_phazonBeamMorphing : 1; + bool x835_27_intoPhazonBeam : 1; + bool x835_28_bombReady : 1; + bool x835_29_powerBombReady : 1; + bool x835_30_inPhazonPool : 1; + bool x835_31_actorAttached : 1; }; + u32 _dummy = 0; + }; - CActorLights x0_lights; - CSfxHandle x2e0_chargeSfx; - CSfxHandle x2e4_invalidSfx; - CSfxHandle x2e8_phazonBeamSfx; - // 0x1: FireOrBomb, 0x2: MissileOrPowerBomb - u32 x2ec_lastFireButtonStates = 0; - u32 x2f0_pressedFireButtonStates = 0; - u32 x2f4_fireButtonStates = 0; - // 0x1: beam mode, 0x2: missile mode, 0x4: missile ready, 0x8: morphing, 0x10: combo fire - u32 x2f8_stateFlags = 0x1; - u32 x2fc_fidgetAnimBits = 0; - u32 x300_remainingMissiles = 0; - u32 x304_ = 0; - u32 x308_bombCount = 3; - u32 x30c_rapidFireShots = 0; - CPlayerState::EBeamId x310_currentBeam = CPlayerState::EBeamId::Power; - CPlayerState::EBeamId x314_nextBeam = CPlayerState::EBeamId::Power; - u32 x318_comboAmmoIdx = 0; - EMissleMode x31c_missileMode = EMissleMode::Inactive; - CPlayerState::EBeamId x320_currentAuxBeam = CPlayerState::EBeamId::Power; - EIdleState x324_idleState = EIdleState::Four; - float x328_animSfxPitch = 0.f; - EChargePhase x32c_chargePhase = EChargePhase::NotCharging; - EChargeState x330_chargeState = EChargeState::Normal; - u32 x334_ = 0; - ENextState x338_nextState = ENextState::StatusQuo; - EPhazonBeamState x33c_phazonBeamState = EPhazonBeamState::Inactive; - float x340_chargeBeamFactor = 0.f; - float x344_comboXferTimer = 0.f; - float x348_chargeCancelTimer = 0.f; - float x34c_shakeX = 0.f; - float x350_shakeZ = 0.f; - float x354_bombFuseTime; - float x358_bombDropDelayTime; - float x35c_bombTime = 0.f; - float x360_ = 0.f; - float x364_gunStrikeCoolTimer = 0.f; - float x368_idleWanderDelayTimer = 0.f; - float x36c_ = 1.f; - float x370_gunMotionSpeedMult = 1.f; - float x374_ = 0.f; - float x378_shotSmokeStartTimer = 0.f; - float x37c_rapidFireShotsDecayTimer = 0.f; - float x380_shotSmokeTimer = 0.f; - float x384_gunStrikeDelayTimer = 0.f; - float x388_enterFreeLookDelayTimer = 0.f; - float x38c_muzzleEffectVisTimer = 0.f; - float x390_cooldown = 0.f; - float x394_damageTimer = 0.f; - float x398_damageAmt = 0.f; - float x39c_phazonMorphT = 0.f; - float x3a0_missileExitTimer = 0.f; - CFidget x3a4_fidget; - zeus::CVector3f x3dc_damageLocation; - zeus::CTransform x3e8_xf; - zeus::CTransform x418_beamLocalXf; - zeus::CTransform x448_elbowWorldXf; - zeus::CTransform x478_assistAimXf; - zeus::CTransform x4a8_gunWorldXf; - zeus::CTransform x4d8_gunLocalXf; - zeus::CTransform x508_elbowLocalXf; - TUniqueId x538_playerId; - TUniqueId x53a_powerBomb = kInvalidUniqueId; - TUniqueId x53c_lightId = kInvalidUniqueId; - std::vector x540_handAnimTokens; - CPlayerCameraBob x550_camBob; - u32 x658_ = 1; - float x65c_ = 0.f; - float x660_ = 0.f; - float x664_ = 0.f; - float x668_aimVerticalSpeed; - float x66c_aimHorizontalSpeed; - std::pair x670_animSfx = {0xffff, {}}; - CGunMorph x678_morph; - CMotionState x6a0_motionState; - zeus::CAABox x6c8_hologramClipCube; - CModelData x6e0_rightHandModel; - CGunWeapon* x72c_currentBeam = nullptr; - CGunWeapon* x730_outgoingBeam = nullptr; - CGunWeapon* x734_loadingBeam = nullptr; - CGunWeapon* x738_nextBeam = nullptr; - std::unique_ptr x73c_gunMotion; - std::unique_ptr x740_grappleArm; - std::unique_ptr x744_auxWeapon; - std::unique_ptr x748_rainSplashGenerator; - std::unique_ptr x74c_powerBeam; - std::unique_ptr x750_iceBeam; - std::unique_ptr x754_waveBeam; - std::unique_ptr x758_plasmaBeam; - std::unique_ptr x75c_phazonBeam; - CGunWeapon* x760_selectableBeams[4] = {}; // Used to be reserved_vector - std::unique_ptr x774_holoTransitionGen; - std::unique_ptr x77c_comboXferGen; - rstl::reserved_vector, 2>, 2> x784_bombEffects; - rstl::reserved_vector, 5> x7c0_auxMuzzleEffects; - rstl::reserved_vector, 5> x800_auxMuzzleGenerators; - std::unique_ptr x82c_shadow; - s16 x830_chargeRumbleHandle = -1; + mutable CTexturedQuadFilter m_screenQuad = {EFilterType::Blend, CGraphics::g_SpareTexture.get(), + CTexturedQuadFilter::ZTest::GEqualZWrite}; + mutable CAABoxShader m_aaboxShader = {true}; - union - { - struct - { - bool x832_24_cancellingCharge : 1; - bool x832_25_chargeEffectVisible : 1; - bool x832_26_comboFiring : 1; - bool x832_27_chargeAnimStarted : 1; - bool x832_28_readyForShot : 1; - bool x832_29_lockedOn : 1; - bool x832_30_requestReturnToDefault : 1; - bool x832_31_inRestPose : 1; - - bool x833_24_notFidgeting : 1; - bool x833_25_ : 1; - bool x833_26_ : 1; - bool x833_27_ : 1; - bool x833_28_phazonBeamActive : 1; - bool x833_29_pointBlankWorldSurface : 1; - bool x833_30_canShowAuxMuzzleEffect : 1; - bool x833_31_inFreeLook : 1; - - bool x834_24_charging : 1; - bool x834_25_gunMotionFidgeting : 1; - bool x834_26_animPlaying : 1; - bool x834_27_underwater : 1; - bool x834_28_requestImmediateRecharge : 1; - bool x834_29_frozen : 1; - bool x834_30_inBigStrike : 1; - bool x834_31_gunMotionInFidgetBasePosition : 1; - - bool x835_24_canFirePhazon : 1; - bool x835_25_inPhazonBeam : 1; - bool x835_26_phazonBeamMorphing : 1; - bool x835_27_intoPhazonBeam : 1; - bool x835_28_bombReady : 1; - bool x835_29_powerBombReady : 1; - bool x835_30_inPhazonPool : 1; - bool x835_31_actorAttached : 1; - }; - u32 _dummy = 0; - }; - - mutable CTexturedQuadFilter m_screenQuad = {EFilterType::Blend, CGraphics::g_SpareTexture.get(), - CTexturedQuadFilter::ZTest::GEqualZWrite}; - mutable CAABoxShader m_aaboxShader = {true}; - - void InitBeamData(); - void InitBombData(); - void InitMuzzleData(); - void InitCTData(); - void LoadHandAnimTokens(); - void CreateGunLight(CStateManager& mgr); - void DeleteGunLight(CStateManager& mgr); - void UpdateGunLight(const zeus::CTransform& xf, CStateManager& mgr); - void SetGunLightActive(bool active, CStateManager& mgr); - void SetPhazonBeamMorph(bool intoPhazonBeam); - void Reset(CStateManager& mgr, bool b1); - void ResetBeamParams(CStateManager& mgr, const CPlayerState& playerState, bool playSelectionSfx); - void PlayAnim(NWeaponTypes::EGunAnimType type, bool loop); - void CancelCharge(CStateManager& mgr, bool withEffect); - bool ExitMissile(); - void StopChargeSound(CStateManager& mgr); - void UnLoadFidget(); - void ReturnArmAndGunToDefault(CStateManager& mgr, bool returnToDefault); - void ReturnToRestPose(); - void ChangeWeapon(const CPlayerState& playerState, CStateManager& mgr); - void GetLctrWithShake(zeus::CTransform& xfOut, const CModelData& mData, std::string_view lctrName, - bool shake, bool dyn); - void UpdateLeftArmTransform(const CModelData& mData, const CStateManager& mgr); - void ProcessGunMorph(float dt, CStateManager& mgr); - void SetPhazonBeamFeedback(bool active); - void StartPhazonBeamTransition(bool active, CStateManager& mgr, CPlayerState& playerState); - void ProcessPhazonGunMorph(float dt, CStateManager& mgr); - void EnableChargeFx(EChargeState state, CStateManager& mgr); - void UpdateChargeState(float dt, CStateManager& mgr); - void UpdateAuxWeapons(float dt, const zeus::CTransform& targetXf, CStateManager& mgr); - void DoUserAnimEvent(float dt, CStateManager& mgr, const CInt32POINode& node, EUserEventType type); - void DoUserAnimEvents(float dt, CStateManager& mgr); - TUniqueId GetTargetId(CStateManager& mgr) const; - void CancelLockOn(); - void FireSecondary(float dt, CStateManager& mgr); - void ResetCharged(float dt, CStateManager& mgr); - void ActivateCombo(CStateManager& mgr); - void ProcessChargeState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt); - void ResetNormal(CStateManager& mgr); - void UpdateNormalShotCycle(float dt, CStateManager& mgr); - void ProcessNormalState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt); - void UpdateWeaponFire(float dt, const CPlayerState& playerState, CStateManager& mgr); - void EnterFreeLook(CStateManager& mgr); - void SetFidgetAnimBits(int animSet, bool beamOnly); - void AsyncLoadFidget(CStateManager& mgr); - bool IsFidgetLoaded() const; - void EnterFidget(CStateManager& mgr); - void UpdateGunIdle(bool inStrikeCooldown, float camBobT, float dt, CStateManager& mgr); - void RenderEnergyDrainEffects(const CStateManager& mgr) const; - void DrawArm(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const; - zeus::CVector3f ConvertToScreenSpace(const zeus::CVector3f& pos, const CGameCamera& cam) const; - static void CopyScreenTex(); - void DrawScreenTex(float z) const; - void DrawClipCube(const zeus::CAABox& aabb) const; + void InitBeamData(); + void InitBombData(); + void InitMuzzleData(); + void InitCTData(); + void LoadHandAnimTokens(); + void CreateGunLight(CStateManager& mgr); + void DeleteGunLight(CStateManager& mgr); + void UpdateGunLight(const zeus::CTransform& xf, CStateManager& mgr); + void SetGunLightActive(bool active, CStateManager& mgr); + void SetPhazonBeamMorph(bool intoPhazonBeam); + void Reset(CStateManager& mgr, bool b1); + void ResetBeamParams(CStateManager& mgr, const CPlayerState& playerState, bool playSelectionSfx); + void PlayAnim(NWeaponTypes::EGunAnimType type, bool loop); + void CancelCharge(CStateManager& mgr, bool withEffect); + bool ExitMissile(); + void StopChargeSound(CStateManager& mgr); + void UnLoadFidget(); + void ReturnArmAndGunToDefault(CStateManager& mgr, bool returnToDefault); + void ReturnToRestPose(); + void ChangeWeapon(const CPlayerState& playerState, CStateManager& mgr); + void GetLctrWithShake(zeus::CTransform& xfOut, const CModelData& mData, std::string_view lctrName, bool shake, + bool dyn); + void UpdateLeftArmTransform(const CModelData& mData, const CStateManager& mgr); + void ProcessGunMorph(float dt, CStateManager& mgr); + void SetPhazonBeamFeedback(bool active); + void StartPhazonBeamTransition(bool active, CStateManager& mgr, CPlayerState& playerState); + void ProcessPhazonGunMorph(float dt, CStateManager& mgr); + void EnableChargeFx(EChargeState state, CStateManager& mgr); + void UpdateChargeState(float dt, CStateManager& mgr); + void UpdateAuxWeapons(float dt, const zeus::CTransform& targetXf, CStateManager& mgr); + void DoUserAnimEvent(float dt, CStateManager& mgr, const CInt32POINode& node, EUserEventType type); + void DoUserAnimEvents(float dt, CStateManager& mgr); + TUniqueId GetTargetId(CStateManager& mgr) const; + void CancelLockOn(); + void FireSecondary(float dt, CStateManager& mgr); + void ResetCharged(float dt, CStateManager& mgr); + void ActivateCombo(CStateManager& mgr); + void ProcessChargeState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt); + void ResetNormal(CStateManager& mgr); + void UpdateNormalShotCycle(float dt, CStateManager& mgr); + void ProcessNormalState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt); + void UpdateWeaponFire(float dt, const CPlayerState& playerState, CStateManager& mgr); + void EnterFreeLook(CStateManager& mgr); + void SetFidgetAnimBits(int animSet, bool beamOnly); + void AsyncLoadFidget(CStateManager& mgr); + bool IsFidgetLoaded() const; + void EnterFidget(CStateManager& mgr); + void UpdateGunIdle(bool inStrikeCooldown, float camBobT, float dt, CStateManager& mgr); + void RenderEnergyDrainEffects(const CStateManager& mgr) const; + void DrawArm(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const; + zeus::CVector3f ConvertToScreenSpace(const zeus::CVector3f& pos, const CGameCamera& cam) const; + static void CopyScreenTex(); + void DrawScreenTex(float z) const; + void DrawClipCube(const zeus::CAABox& aabb) const; public: - explicit CPlayerGun(TUniqueId playerId); - void TakeDamage(bool bigStrike, bool notFromMetroid, CStateManager& mgr); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void AsyncLoadSuit(CStateManager& mgr); - void TouchModel(const CStateManager& stateMgr); - EMissleMode GetMissleMode() const { return x31c_missileMode; } - bool IsFidgeting() const { return x833_24_notFidgeting; } - bool IsCharging() const { return x834_24_charging; } - float GetChargeBeamFactor() const { return x340_chargeBeamFactor; } - bool IsBombReady() const { return x835_28_bombReady; } - u32 GetBombCount() const { return x308_bombCount; } - bool IsPowerBombReady() const { return x835_29_powerBombReady; } - CPlayerState::EBeamId GetCurrentBeam() const { return x310_currentBeam; } - CPlayerState::EBeamId GetNextBeam() const { return x314_nextBeam; } - const CGunMorph& GetGunMorph() const { return x678_morph; } - float GetHoloTransitionFactor() const { return x678_morph.GetTransitionFactor(); } - void SetTransform(const zeus::CTransform& xf) { x3e8_xf = xf; } - void SetAssistAimTransform(const zeus::CTransform& xf) { x478_assistAimXf = xf; } - CGrappleArm& GetGrappleArm() { return *x740_grappleArm; } - void DamageRumble(const zeus::CVector3f& location, float damage, const CStateManager& mgr); - void ResetCharge(CStateManager& mgr, bool resetBeam); - void HandleBeamChange(const CFinalInput& input, CStateManager& mgr); - void HandlePhazonBeamChange(CStateManager& mgr); - void HandleWeaponChange(const CFinalInput& input, CStateManager& mgr); - void ProcessInput(const CFinalInput& input, CStateManager& mgr); - void ResetIdle(CStateManager& mgr); - void CancelFiring(CStateManager& mgr); - float GetBeamVelocity() const; - void StopContinuousBeam(CStateManager& mgr, bool b1); - void Update(float grappleSwingT, float cameraBobT, float dt, CStateManager& mgr); - void PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos); - void Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const; - void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; - u32 GetLastFireButtonStates() const { return x2ec_lastFireButtonStates; } - void DropBomb(EBWeapon weapon, CStateManager& mgr); - TUniqueId DropPowerBomb(CStateManager& mgr); - void SetActorAttached(bool b) { x835_31_actorAttached = b; } + explicit CPlayerGun(TUniqueId playerId); + void TakeDamage(bool bigStrike, bool notFromMetroid, CStateManager& mgr); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void AsyncLoadSuit(CStateManager& mgr); + void TouchModel(const CStateManager& stateMgr); + EMissleMode GetMissleMode() const { return x31c_missileMode; } + bool IsFidgeting() const { return x833_24_notFidgeting; } + bool IsCharging() const { return x834_24_charging; } + float GetChargeBeamFactor() const { return x340_chargeBeamFactor; } + bool IsBombReady() const { return x835_28_bombReady; } + u32 GetBombCount() const { return x308_bombCount; } + bool IsPowerBombReady() const { return x835_29_powerBombReady; } + CPlayerState::EBeamId GetCurrentBeam() const { return x310_currentBeam; } + CPlayerState::EBeamId GetNextBeam() const { return x314_nextBeam; } + const CGunMorph& GetGunMorph() const { return x678_morph; } + float GetHoloTransitionFactor() const { return x678_morph.GetTransitionFactor(); } + void SetTransform(const zeus::CTransform& xf) { x3e8_xf = xf; } + void SetAssistAimTransform(const zeus::CTransform& xf) { x478_assistAimXf = xf; } + CGrappleArm& GetGrappleArm() { return *x740_grappleArm; } + void DamageRumble(const zeus::CVector3f& location, float damage, const CStateManager& mgr); + void ResetCharge(CStateManager& mgr, bool resetBeam); + void HandleBeamChange(const CFinalInput& input, CStateManager& mgr); + void HandlePhazonBeamChange(CStateManager& mgr); + void HandleWeaponChange(const CFinalInput& input, CStateManager& mgr); + void ProcessInput(const CFinalInput& input, CStateManager& mgr); + void ResetIdle(CStateManager& mgr); + void CancelFiring(CStateManager& mgr); + float GetBeamVelocity() const; + void StopContinuousBeam(CStateManager& mgr, bool b1); + void Update(float grappleSwingT, float cameraBobT, float dt, CStateManager& mgr); + void PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos); + void Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags) const; + void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; + u32 GetLastFireButtonStates() const { return x2ec_lastFireButtonStates; } + void DropBomb(EBWeapon weapon, CStateManager& mgr); + TUniqueId DropPowerBomb(CStateManager& mgr); + void SetActorAttached(bool b) { x835_31_actorAttached = b; } }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CPowerBeam.cpp b/Runtime/Weapon/CPowerBeam.cpp index ead6de88c..d1069f469 100644 --- a/Runtime/Weapon/CPowerBeam.cpp +++ b/Runtime/Weapon/CPowerBeam.cpp @@ -2,160 +2,134 @@ #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" -namespace urde -{ +namespace urde { -CPowerBeam::CPowerBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale) -: CGunWeapon(characterId, type, playerId, playerMaterial, scale) -{ - x21c_shotSmoke = g_SimplePool->GetObj("ShotSmoke"); - x228_power2nd1 = g_SimplePool->GetObj("Power2nd_1"); - x244_24 = false; - x244_25_loaded = false; +CPowerBeam::CPowerBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale) +: CGunWeapon(characterId, type, playerId, playerMaterial, scale) { + x21c_shotSmoke = g_SimplePool->GetObj("ShotSmoke"); + x228_power2nd1 = g_SimplePool->GetObj("Power2nd_1"); + x244_24 = false; + x244_25_loaded = false; } -void CPowerBeam::PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - zeus::CTransform backupView = CGraphics::g_ViewMatrix; - CGraphics::SetViewPointMatrix(xf.inverse() * backupView); - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - if (x234_shotSmokeGen) - x234_shotSmokeGen->Render(); - CGraphics::SetViewPointMatrix(backupView); +void CPowerBeam::PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + zeus::CTransform backupView = CGraphics::g_ViewMatrix; + CGraphics::SetViewPointMatrix(xf.inverse() * backupView); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + if (x234_shotSmokeGen) + x234_shotSmokeGen->Render(); + CGraphics::SetViewPointMatrix(backupView); } -void CPowerBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x238_power2ndGen) - x238_power2ndGen->Render(); - CGunWeapon::PostRenderGunFx(mgr, xf); +void CPowerBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x238_power2ndGen) + x238_power2ndGen->Render(); + CGunWeapon::PostRenderGunFx(mgr, xf); } -void CPowerBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) -{ - switch (x240_smokeState) - { - case ESmokeState::Inactive: - if (shotSmoke) - { - if (x234_shotSmokeGen) - x234_shotSmokeGen->SetParticleEmission(true); - x23c_smokeTimer = 2.f; - x240_smokeState = ESmokeState::Active; - } - break; - case ESmokeState::Active: - if (x23c_smokeTimer > 0.f) - { - x23c_smokeTimer -= dt; - } - else - { - if (x234_shotSmokeGen) - x234_shotSmokeGen->SetParticleEmission(false); - x240_smokeState = ESmokeState::Done; - } - case ESmokeState::Done: - if (x234_shotSmokeGen) - { - zeus::CTransform locator = x10_solidModelData->GetScaledLocatorTransform("LBEAM"); - x234_shotSmokeGen->SetGlobalTranslation(locator.origin); - x234_shotSmokeGen->Update(dt); - if (x240_smokeState == ESmokeState::Done && x234_shotSmokeGen->GetSystemCount() == 0) - x240_smokeState = ESmokeState::Inactive; - } - else - { - x240_smokeState = ESmokeState::Inactive; - } - break; +void CPowerBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) { + switch (x240_smokeState) { + case ESmokeState::Inactive: + if (shotSmoke) { + if (x234_shotSmokeGen) + x234_shotSmokeGen->SetParticleEmission(true); + x23c_smokeTimer = 2.f; + x240_smokeState = ESmokeState::Active; } - - if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x238_power2ndGen) - { - x238_power2ndGen->SetGlobalOrientAndTrans(xf); - x238_power2ndGen->Update(dt); + break; + case ESmokeState::Active: + if (x23c_smokeTimer > 0.f) { + x23c_smokeTimer -= dt; + } else { + if (x234_shotSmokeGen) + x234_shotSmokeGen->SetParticleEmission(false); + x240_smokeState = ESmokeState::Done; } + case ESmokeState::Done: + if (x234_shotSmokeGen) { + zeus::CTransform locator = x10_solidModelData->GetScaledLocatorTransform("LBEAM"); + x234_shotSmokeGen->SetGlobalTranslation(locator.origin); + x234_shotSmokeGen->Update(dt); + if (x240_smokeState == ESmokeState::Done && x234_shotSmokeGen->GetSystemCount() == 0) + x240_smokeState = ESmokeState::Inactive; + } else { + x240_smokeState = ESmokeState::Inactive; + } + break; + } - CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); + if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x238_power2ndGen) { + x238_power2ndGen->SetGlobalOrientAndTrans(xf); + x238_power2ndGen->Update(dt); + } + + CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); } -static const u16 skSoundId[] = { SFXwpn_fire_power_normal, SFXwpn_fire_power_charged }; +static const u16 skSoundId[] = {SFXwpn_fire_power_normal, SFXwpn_fire_power_charged}; void CPowerBeam::Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) -{ - CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); - NWeaponTypes::play_sfx(skSoundId[int(chargeState)], underwater, false, 0.165f); + CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) { + CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); + NWeaponTypes::play_sfx(skSoundId[int(chargeState)], underwater, false, 0.165f); } -void CPowerBeam::EnableSecondaryFx(ESecondaryFxType type) -{ - switch (type) - { - case ESecondaryFxType::None: - case ESecondaryFxType::ToCombo: - case ESecondaryFxType::CancelCharge: - if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x238_power2ndGen) - x238_power2ndGen->SetParticleEmission(false); - x1cc_enabledSecondaryEffect = ESecondaryFxType::None; - break; - case ESecondaryFxType::Charge: - x238_power2ndGen = std::make_unique(x228_power2nd1); - x238_power2ndGen->SetGlobalScale(x4_scale); - x1cc_enabledSecondaryEffect = type; - break; - default: - break; - } -} - -void CPowerBeam::Update(float dt, CStateManager& mgr) -{ - CGunWeapon::Update(dt, mgr); - if (IsLoaded()) - return; - if (CGunWeapon::IsLoaded() && !x244_25_loaded) - { - x244_25_loaded = x21c_shotSmoke.IsLoaded() && x228_power2nd1.IsLoaded(); - if (x244_25_loaded) - { - x234_shotSmokeGen = std::make_unique(x21c_shotSmoke); - x234_shotSmokeGen->SetParticleEmission(false); - } - } -} - -void CPowerBeam::Load(CStateManager& mgr, bool subtypeBasePose) -{ - CGunWeapon::Load(mgr, subtypeBasePose); - x21c_shotSmoke.Lock(); - x228_power2nd1.Lock(); -} - -void CPowerBeam::ReInitVariables() -{ - x234_shotSmokeGen.reset(); - x238_power2ndGen.reset(); - x23c_smokeTimer = 0.f; - x240_smokeState = ESmokeState::Inactive; - x244_24 = false; - x244_25_loaded = false; +void CPowerBeam::EnableSecondaryFx(ESecondaryFxType type) { + switch (type) { + case ESecondaryFxType::None: + case ESecondaryFxType::ToCombo: + case ESecondaryFxType::CancelCharge: + if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None && x238_power2ndGen) + x238_power2ndGen->SetParticleEmission(false); x1cc_enabledSecondaryEffect = ESecondaryFxType::None; + break; + case ESecondaryFxType::Charge: + x238_power2ndGen = std::make_unique(x228_power2nd1); + x238_power2ndGen->SetGlobalScale(x4_scale); + x1cc_enabledSecondaryEffect = type; + break; + default: + break; + } } -void CPowerBeam::Unload(CStateManager& mgr) -{ - CGunWeapon::Unload(mgr); - x228_power2nd1.Unlock(); - x21c_shotSmoke.Unlock(); - ReInitVariables(); +void CPowerBeam::Update(float dt, CStateManager& mgr) { + CGunWeapon::Update(dt, mgr); + if (IsLoaded()) + return; + if (CGunWeapon::IsLoaded() && !x244_25_loaded) { + x244_25_loaded = x21c_shotSmoke.IsLoaded() && x228_power2nd1.IsLoaded(); + if (x244_25_loaded) { + x234_shotSmokeGen = std::make_unique(x21c_shotSmoke); + x234_shotSmokeGen->SetParticleEmission(false); + } + } } -bool CPowerBeam::IsLoaded() const -{ - return CGunWeapon::IsLoaded() && x244_25_loaded; +void CPowerBeam::Load(CStateManager& mgr, bool subtypeBasePose) { + CGunWeapon::Load(mgr, subtypeBasePose); + x21c_shotSmoke.Lock(); + x228_power2nd1.Lock(); } +void CPowerBeam::ReInitVariables() { + x234_shotSmokeGen.reset(); + x238_power2ndGen.reset(); + x23c_smokeTimer = 0.f; + x240_smokeState = ESmokeState::Inactive; + x244_24 = false; + x244_25_loaded = false; + x1cc_enabledSecondaryEffect = ESecondaryFxType::None; } + +void CPowerBeam::Unload(CStateManager& mgr) { + CGunWeapon::Unload(mgr); + x228_power2nd1.Unlock(); + x21c_shotSmoke.Unlock(); + ReInitVariables(); +} + +bool CPowerBeam::IsLoaded() const { return CGunWeapon::IsLoaded() && x244_25_loaded; } + +} // namespace urde diff --git a/Runtime/Weapon/CPowerBeam.hpp b/Runtime/Weapon/CPowerBeam.hpp index bbe295eda..5fc1c84b8 100644 --- a/Runtime/Weapon/CPowerBeam.hpp +++ b/Runtime/Weapon/CPowerBeam.hpp @@ -2,41 +2,34 @@ #include "CGunWeapon.hpp" -namespace urde -{ +namespace urde { + +class CPowerBeam final : public CGunWeapon { + enum class ESmokeState { Inactive, Active, Done }; + TCachedToken x21c_shotSmoke; + TCachedToken x228_power2nd1; + std::unique_ptr x234_shotSmokeGen; + std::unique_ptr x238_power2ndGen; + float x23c_smokeTimer = 0.f; + ESmokeState x240_smokeState = ESmokeState::Inactive; + bool x244_24 : 1; + bool x244_25_loaded : 1; + void ReInitVariables(); -class CPowerBeam final : public CGunWeapon -{ - enum class ESmokeState - { - Inactive, - Active, - Done - }; - TCachedToken x21c_shotSmoke; - TCachedToken x228_power2nd1; - std::unique_ptr x234_shotSmokeGen; - std::unique_ptr x238_power2ndGen; - float x23c_smokeTimer = 0.f; - ESmokeState x240_smokeState = ESmokeState::Inactive; - bool x244_24 : 1; - bool x244_25_loaded : 1; - void ReInitVariables(); public: - CPowerBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale); + CPowerBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale); - void PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); - void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); - void EnableSecondaryFx(ESecondaryFxType type); - void Update(float dt, CStateManager& mgr); - void Load(CStateManager& mgr, bool subtypeBasePose); - void Unload(CStateManager& mgr); - bool IsLoaded() const; + void PreRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); + void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, CStateManager& mgr, + TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); + void EnableSecondaryFx(ESecondaryFxType type); + void Update(float dt, CStateManager& mgr); + void Load(CStateManager& mgr, bool subtypeBasePose); + void Unload(CStateManager& mgr); + bool IsLoaded() const; }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CPowerBomb.cpp b/Runtime/Weapon/CPowerBomb.cpp index 5846f5de0..b5e5115f0 100644 --- a/Runtime/Weapon/CPowerBomb.cpp +++ b/Runtime/Weapon/CPowerBomb.cpp @@ -9,110 +9,88 @@ #include "DataSpec/DNAMP1/SFX/Weapons.h" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { const zeus::CColor CPowerBomb::kFadeColor(COLOR(0xffffff7)); -CPowerBomb::CPowerBomb(const TToken& particle, TUniqueId uid, TAreaId aid, - TUniqueId playerId, const zeus::CTransform& xf, const CDamageInfo& dInfo) -: CWeapon(uid, aid, true, playerId, EWeaponType::PowerBomb, "PowerBomb", xf, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Immovable, - EMaterialTypes::Trigger}, - {EMaterialTypes::Projectile, EMaterialTypes::PowerBomb}), - {EMaterialTypes::Projectile, EMaterialTypes::PowerBomb}, dInfo, EProjectileAttrib::PowerBombs, - CModelData::CModelDataNull()) +CPowerBomb::CPowerBomb(const TToken& particle, TUniqueId uid, TAreaId aid, TUniqueId playerId, + const zeus::CTransform& xf, const CDamageInfo& dInfo) +: CWeapon( + uid, aid, true, playerId, EWeaponType::PowerBomb, "PowerBomb", xf, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Immovable, EMaterialTypes::Trigger}, + {EMaterialTypes::Projectile, EMaterialTypes::PowerBomb}), + {EMaterialTypes::Projectile, EMaterialTypes::PowerBomb}, dInfo, EProjectileAttrib::PowerBombs, + CModelData::CModelDataNull()) , x158_24_canStartFilter(true) , x158_25_filterEnabled(false) , x164_radiusIncrement(dInfo.GetRadius() / 2.5f) , x168_particle(new CElementGen(particle)) -, x16c_radius(dInfo.GetRadius()) -{ - x168_particle->SetGlobalTranslation(GetTranslation()); +, x16c_radius(dInfo.GetRadius()) { + x168_particle->SetGlobalTranslation(GetTranslation()); } -void CPowerBomb::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CPowerBomb::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CPowerBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Registered) { + mgr.AddWeaponId(xec_ownerId, xf0_weaponType); + if (mgr.GetPlayerState()->IsPlayerAlive()) { + CSfxManager::AddEmitter(SFXsfx0710, GetTranslation(), {}, true, false, 0x7f, -1); + mgr.InformListeners(GetTranslation(), EListenNoiseType::BombExplode); + } else { + auto handle = CSfxManager::AddEmitter(SFXsfx073F, GetTranslation(), {}, true, false, 0x7f, -1); + mgr.Player()->ApplySubmergedPitchBend(handle); + } + } else if (msg == EScriptObjectMessage::Deleted) { + if (x15c_curTime > 0.7f) + mgr.GetCameraFilterPass(6).DisableFilter(0.f); + + mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); + } + CActor::AcceptScriptMsg(msg, uid, mgr); } -void CPowerBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Registered) - { - mgr.AddWeaponId(xec_ownerId, xf0_weaponType); - if (mgr.GetPlayerState()->IsPlayerAlive()) - { - CSfxManager::AddEmitter(SFXsfx0710, GetTranslation(), {}, true, false, 0x7f, -1); - mgr.InformListeners(GetTranslation(), EListenNoiseType::BombExplode); - } - else - { - auto handle = CSfxManager::AddEmitter(SFXsfx073F, GetTranslation(), {}, true, false, 0x7f, -1); - mgr.Player()->ApplySubmergedPitchBend(handle); - } +void CPowerBomb::Think(float dt, CStateManager& mgr) { + CWeapon::Think(dt, mgr); + if (x158_24_canStartFilter) { + if (x15c_curTime > 1.f && !x158_25_filterEnabled) { + mgr.GetCameraFilterPass(6).SetFilter(EFilterType::Add, EFilterShape::Fullscreen, 1.5f, kFadeColor, -1); + x158_25_filterEnabled = true; } - else if (msg == EScriptObjectMessage::Deleted) - { - if (x15c_curTime > 0.7f) - mgr.GetCameraFilterPass(6).DisableFilter(0.f); - mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType); - } - CActor::AcceptScriptMsg(msg, uid, mgr); + if (x15c_curTime > 2.5f) + x158_24_canStartFilter = false; + } else if (x15c_curTime > 3.75 && x158_25_filterEnabled) { + mgr.GetCameraFilterPass(6).DisableFilter(.5f); + x158_25_filterEnabled = false; + } + + if (x15c_curTime > 7.f) { + if (x168_particle->IsSystemDeletable()) + mgr.FreeScriptObject(GetUniqueId()); + } + + if (x15c_curTime > 30.f) { + mgr.FreeScriptObject(GetUniqueId()); + return; + } + + if (x15c_curTime > 1.f && x15c_curTime < 4.f) { + x110_origDamageInfo.SetRadius(x160_curRadius); + ApplyDynamicDamage(GetTranslation(), mgr); + x160_curRadius += x164_radiusIncrement; + } + + x168_particle->Update(dt); + x15c_curTime += dt; } -void CPowerBomb::Think(float dt, CStateManager& mgr) -{ - CWeapon::Think(dt, mgr); - if (x158_24_canStartFilter) - { - if (x15c_curTime > 1.f && !x158_25_filterEnabled) - { - mgr.GetCameraFilterPass(6).SetFilter(EFilterType::Add, EFilterShape::Fullscreen, 1.5f, kFadeColor, -1); - x158_25_filterEnabled = true; - } - - if (x15c_curTime > 2.5f) - x158_24_canStartFilter = false; - } - else if (x15c_curTime > 3.75 && x158_25_filterEnabled) - { - mgr.GetCameraFilterPass(6).DisableFilter(.5f); - x158_25_filterEnabled = false; - } - - if (x15c_curTime > 7.f) - { - if (x168_particle->IsSystemDeletable()) - mgr.FreeScriptObject(GetUniqueId()); - } - - if (x15c_curTime > 30.f) - { - mgr.FreeScriptObject(GetUniqueId()); - return; - } - - if (x15c_curTime > 1.f && x15c_curTime < 4.f) - { - x110_origDamageInfo.SetRadius(x160_curRadius); - ApplyDynamicDamage(GetTranslation(), mgr); - x160_curRadius += x164_radiusIncrement; - } - - x168_particle->Update(dt); - x15c_curTime += dt; +void CPowerBomb::AddToRenderer(const zeus::CFrustum&, const CStateManager&) const { + g_Renderer->AddParticleGen(*x168_particle); } -void CPowerBomb::AddToRenderer(const zeus::CFrustum&, const CStateManager&) const -{ - g_Renderer->AddParticleGen(*x168_particle); +void CPowerBomb::ApplyDynamicDamage(const zeus::CVector3f& pos, urde::CStateManager& mgr) { + mgr.ApplyDamageToWorld(xec_ownerId, *this, pos, x12c_curDamageInfo, xf8_filter); } -void CPowerBomb::ApplyDynamicDamage(const zeus::CVector3f& pos, urde::CStateManager& mgr) -{ - mgr.ApplyDamageToWorld(xec_ownerId, *this, pos, x12c_curDamageInfo, xf8_filter); -} - -} +} // namespace urde diff --git a/Runtime/Weapon/CPowerBomb.hpp b/Runtime/Weapon/CPowerBomb.hpp index ca24725c0..9125661ee 100644 --- a/Runtime/Weapon/CPowerBomb.hpp +++ b/Runtime/Weapon/CPowerBomb.hpp @@ -3,34 +3,33 @@ #include "CWeapon.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class CElementGen; -class CPowerBomb : public CWeapon -{ - static const zeus::CColor kFadeColor; - bool x158_24_canStartFilter : 1; - bool x158_25_filterEnabled : 1; - float x15c_curTime = 0.f; - float x160_curRadius = 0.f; - float x164_radiusIncrement; - std::unique_ptr x168_particle; - float x16c_radius; -public: - CPowerBomb(const TToken& particle, TUniqueId uid, TAreaId aid, - TUniqueId playerId, const zeus::CTransform& xf, const CDamageInfo& dInfo); +class CPowerBomb : public CWeapon { + static const zeus::CColor kFadeColor; + bool x158_24_canStartFilter : 1; + bool x158_25_filterEnabled : 1; + float x15c_curTime = 0.f; + float x160_curRadius = 0.f; + float x164_radiusIncrement; + std::unique_ptr x168_particle; + float x16c_radius; - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - void Render(const CStateManager&) const {} - std::experimental::optional GetTouchBounds() const { return {}; } - void Touch(CActor&, CStateManager&) { /*x158_24_canStartFilter; */} - float GetCurTime() const { return x15c_curTime; } - void ApplyDynamicDamage(const zeus::CVector3f&, CStateManager&); +public: + CPowerBomb(const TToken& particle, TUniqueId uid, TAreaId aid, TUniqueId playerId, + const zeus::CTransform& xf, const CDamageInfo& dInfo); + + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const {} + std::experimental::optional GetTouchBounds() const { return {}; } + void Touch(CActor&, CStateManager&) { /*x158_24_canStartFilter; */ + } + float GetCurTime() const { return x15c_curTime; } + void ApplyDynamicDamage(const zeus::CVector3f&, CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CProjectileInfo.cpp b/Runtime/Weapon/CProjectileInfo.cpp index 662abb444..ff7628523 100644 --- a/Runtime/Weapon/CProjectileInfo.cpp +++ b/Runtime/Weapon/CProjectileInfo.cpp @@ -3,24 +3,17 @@ #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" -namespace urde -{ +namespace urde { CProjectileInfo::CProjectileInfo(urde::CInputStream& in) -: x0_weaponDescription(g_SimplePool->GetObj({SBIG('WPSC'), CAssetId(in)})) -, xc_damageInfo(in) -{ +: x0_weaponDescription(g_SimplePool->GetObj({SBIG('WPSC'), CAssetId(in)})), xc_damageInfo(in) {} + +CProjectileInfo::CProjectileInfo(CAssetId proj, const CDamageInfo& dInfo) +: x0_weaponDescription(g_SimplePool->GetObj({SBIG('WPSC'), proj})), xc_damageInfo(dInfo) {} + +zeus::CVector3f CProjectileInfo::PredictInterceptPos(const zeus::CVector3f&, const zeus::CVector3f&, const CPlayer&, + bool) { + return {}; } -CProjectileInfo::CProjectileInfo(CAssetId proj, const CDamageInfo & dInfo) -: x0_weaponDescription(g_SimplePool->GetObj({SBIG('WPSC'), proj})) -, xc_damageInfo(dInfo) -{ -} - -zeus::CVector3f CProjectileInfo::PredictInterceptPos(const zeus::CVector3f &, const zeus::CVector3f &, const CPlayer &, bool) -{ - return {}; -} - -} +} // namespace urde diff --git a/Runtime/Weapon/CProjectileInfo.hpp b/Runtime/Weapon/CProjectileInfo.hpp index 27d75e878..d49d8c587 100644 --- a/Runtime/Weapon/CProjectileInfo.hpp +++ b/Runtime/Weapon/CProjectileInfo.hpp @@ -5,20 +5,19 @@ #include "World/CDamageInfo.hpp" #include "Particle/CWeaponDescription.hpp" -namespace urde -{ +namespace urde { class CPlayer; -class CProjectileInfo -{ - TToken x0_weaponDescription; - CDamageInfo xc_damageInfo; +class CProjectileInfo { + TToken x0_weaponDescription; + CDamageInfo xc_damageInfo; + public: - CProjectileInfo(CInputStream&); - CProjectileInfo(CAssetId, const CDamageInfo&); + CProjectileInfo(CInputStream&); + CProjectileInfo(CAssetId, const CDamageInfo&); - zeus::CVector3f PredictInterceptPos(const zeus::CVector3f&, const zeus::CVector3f&, const CPlayer&, bool); + zeus::CVector3f PredictInterceptPos(const zeus::CVector3f&, const zeus::CVector3f&, const CPlayer&, bool); - CDamageInfo GetDamage() const { return xc_damageInfo; } - const TToken& Token() { return x0_weaponDescription; } + CDamageInfo GetDamage() const { return xc_damageInfo; } + const TToken& Token() { return x0_weaponDescription; } }; -} +} // namespace urde diff --git a/Runtime/Weapon/CProjectileWeapon.cpp b/Runtime/Weapon/CProjectileWeapon.cpp index 6899a05f7..a95394e91 100644 --- a/Runtime/Weapon/CProjectileWeapon.cpp +++ b/Runtime/Weapon/CProjectileWeapon.cpp @@ -4,506 +4,430 @@ #include "GameGlobalObjects.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { u16 CProjectileWeapon::g_GlobalSeed = 99; CProjectileWeapon::CProjectileWeapon(const TToken& wDesc, const zeus::CVector3f& worldOffset, const zeus::CTransform& localToWorld, const zeus::CVector3f& scale, s32 flags) -: x4_weaponDesc(wDesc), x10_random(g_GlobalSeed), x14_localToWorldXf(localToWorld), x74_worldOffset(worldOffset), - xe4_flags(flags) -{ - x124_24_active = true; - CGlobalRandom gr(x10_random); - x124_31_VMD2 = x4_weaponDesc->x10_VMD2; - x124_25_APSO = x4_weaponDesc->x28_APSO; - if (x4_weaponDesc->x34_APSM) - { - xfc_APSMGen = std::make_unique(x4_weaponDesc->x34_APSM.m_token, - CElementGen::EModelOrientationType::Normal, - (xe4_flags & 0x1) == 0x1 ? - CElementGen::EOptionalSystemFlags::Two : - CElementGen::EOptionalSystemFlags::One); - xfc_APSMGen->SetGlobalScale(scale); - } - if (x4_weaponDesc->x44_APS2) - { - x100_APS2Gen = std::make_unique(x4_weaponDesc->x44_APS2.m_token, - CElementGen::EModelOrientationType::Normal, - (xe4_flags & 0x1) == 0x1 ? - CElementGen::EOptionalSystemFlags::Two : - CElementGen::EOptionalSystemFlags::One); - x100_APS2Gen->SetGlobalScale(scale); - } - if (x4_weaponDesc->x54_ASW1) - { - x118_swoosh1 = std::make_unique(x4_weaponDesc->x54_ASW1.m_token, 0); - x118_swoosh1->SetGlobalScale(scale); - } - if (x4_weaponDesc->x64_ASW2) - { - x11c_swoosh2 = std::make_unique(x4_weaponDesc->x64_ASW2.m_token, 0); - x11c_swoosh2->SetGlobalScale(scale); - } - if (x4_weaponDesc->x74_ASW3) - { - x120_swoosh3 = std::make_unique(x4_weaponDesc->x74_ASW3.m_token, 0); - x120_swoosh3->SetGlobalScale(scale); - } - if (CIntElement* pslt = x4_weaponDesc->x14_PSLT.get()) - pslt->GetValue(0, xe8_lifetime); - else - xe8_lifetime = 0x7FFFFF; - if (CVectorElement* ivec = x4_weaponDesc->x4_IVEC.get()) - ivec->GetValue(0, xb0_velocity); - if (CVectorElement* iorn = x4_weaponDesc->x0_IORN.get()) - { - zeus::CTransform xf; - zeus::CVector3f orn; - iorn->GetValue(0, orn); - xf.rotateLocalX(zeus::degToRad(orn.x())); - xf.rotateLocalY(zeus::degToRad(orn.y())); - xf.rotateLocalZ(zeus::degToRad(orn.z())); - SetRelativeOrientation(xf); - } - else - { - SetRelativeOrientation(zeus::CTransform::Identity()); - } - if (x4_weaponDesc->x84_OHEF) - x108_model.emplace(x4_weaponDesc->x84_OHEF.m_token); - x124_26_AP11 = x4_weaponDesc->x2a_AP11; - x124_27_AP21 = x4_weaponDesc->x2b_AP21; - x124_28_AS11 = x4_weaponDesc->x2c_AS11; - x124_29_AS12 = x4_weaponDesc->x2d_AS12; - x124_30_AS13 = x4_weaponDesc->x2e_AS13; - UpdateChildParticleSystems(1.f / 60.f); +: x4_weaponDesc(wDesc) +, x10_random(g_GlobalSeed) +, x14_localToWorldXf(localToWorld) +, x74_worldOffset(worldOffset) +, xe4_flags(flags) { + x124_24_active = true; + CGlobalRandom gr(x10_random); + x124_31_VMD2 = x4_weaponDesc->x10_VMD2; + x124_25_APSO = x4_weaponDesc->x28_APSO; + if (x4_weaponDesc->x34_APSM) { + xfc_APSMGen = std::make_unique( + x4_weaponDesc->x34_APSM.m_token, CElementGen::EModelOrientationType::Normal, + (xe4_flags & 0x1) == 0x1 ? CElementGen::EOptionalSystemFlags::Two : CElementGen::EOptionalSystemFlags::One); + xfc_APSMGen->SetGlobalScale(scale); + } + if (x4_weaponDesc->x44_APS2) { + x100_APS2Gen = std::make_unique( + x4_weaponDesc->x44_APS2.m_token, CElementGen::EModelOrientationType::Normal, + (xe4_flags & 0x1) == 0x1 ? CElementGen::EOptionalSystemFlags::Two : CElementGen::EOptionalSystemFlags::One); + x100_APS2Gen->SetGlobalScale(scale); + } + if (x4_weaponDesc->x54_ASW1) { + x118_swoosh1 = std::make_unique(x4_weaponDesc->x54_ASW1.m_token, 0); + x118_swoosh1->SetGlobalScale(scale); + } + if (x4_weaponDesc->x64_ASW2) { + x11c_swoosh2 = std::make_unique(x4_weaponDesc->x64_ASW2.m_token, 0); + x11c_swoosh2->SetGlobalScale(scale); + } + if (x4_weaponDesc->x74_ASW3) { + x120_swoosh3 = std::make_unique(x4_weaponDesc->x74_ASW3.m_token, 0); + x120_swoosh3->SetGlobalScale(scale); + } + if (CIntElement* pslt = x4_weaponDesc->x14_PSLT.get()) + pslt->GetValue(0, xe8_lifetime); + else + xe8_lifetime = 0x7FFFFF; + if (CVectorElement* ivec = x4_weaponDesc->x4_IVEC.get()) + ivec->GetValue(0, xb0_velocity); + if (CVectorElement* iorn = x4_weaponDesc->x0_IORN.get()) { + zeus::CTransform xf; + zeus::CVector3f orn; + iorn->GetValue(0, orn); + xf.rotateLocalX(zeus::degToRad(orn.x())); + xf.rotateLocalY(zeus::degToRad(orn.y())); + xf.rotateLocalZ(zeus::degToRad(orn.z())); + SetRelativeOrientation(xf); + } else { + SetRelativeOrientation(zeus::CTransform::Identity()); + } + if (x4_weaponDesc->x84_OHEF) + x108_model.emplace(x4_weaponDesc->x84_OHEF.m_token); + x124_26_AP11 = x4_weaponDesc->x2a_AP11; + x124_27_AP21 = x4_weaponDesc->x2b_AP21; + x124_28_AS11 = x4_weaponDesc->x2c_AS11; + x124_29_AS12 = x4_weaponDesc->x2d_AS12; + x124_30_AS13 = x4_weaponDesc->x2e_AS13; + UpdateChildParticleSystems(1.f / 60.f); } -zeus::CTransform CProjectileWeapon::GetTransform() const -{ - return x14_localToWorldXf * x44_localXf; +zeus::CTransform CProjectileWeapon::GetTransform() const { return x14_localToWorldXf * x44_localXf; } + +zeus::CVector3f CProjectileWeapon::GetTranslation() const { + return x14_localToWorldXf * (x44_localXf * x8c_projOffset + x80_localOffset) + x74_worldOffset; } -zeus::CVector3f CProjectileWeapon::GetTranslation() const -{ - return x14_localToWorldXf * (x44_localXf * x8c_projOffset + x80_localOffset) + x74_worldOffset; +std::experimental::optional CProjectileWeapon::GetBounds() const { + zeus::CAABox aabb; + bool ret = false; + + if (xfc_APSMGen) { + if (auto b = xfc_APSMGen->GetBounds()) { + aabb.accumulateBounds(*b); + ret = true; + } + } + + if (x100_APS2Gen) { + if (auto b = x100_APS2Gen->GetBounds()) { + aabb.accumulateBounds(*b); + ret = true; + } + } + + if (x118_swoosh1) { + if (auto b = x118_swoosh1->GetBounds()) { + aabb.accumulateBounds(*b); + ret = true; + } + } + + if (x11c_swoosh2) { + if (auto b = x11c_swoosh2->GetBounds()) { + aabb.accumulateBounds(*b); + ret = true; + } + } + + if (x120_swoosh3) { + if (auto b = x120_swoosh3->GetBounds()) { + aabb.accumulateBounds(*b); + ret = true; + } + } + + if (ret) + return {aabb}; + return {}; } -std::experimental::optional CProjectileWeapon::GetBounds() const -{ - zeus::CAABox aabb; - bool ret = false; - - if (xfc_APSMGen) - { - if (auto b = xfc_APSMGen->GetBounds()) - { - aabb.accumulateBounds(*b); - ret = true; - } - } - - if (x100_APS2Gen) - { - if (auto b = x100_APS2Gen->GetBounds()) - { - aabb.accumulateBounds(*b); - ret = true; - } - } - - if (x118_swoosh1) - { - if (auto b = x118_swoosh1->GetBounds()) - { - aabb.accumulateBounds(*b); - ret = true; - } - } - - if (x11c_swoosh2) - { - if (auto b = x11c_swoosh2->GetBounds()) - { - aabb.accumulateBounds(*b); - ret = true; - } - } - - if (x120_swoosh3) - { - if (auto b = x120_swoosh3->GetBounds()) - { - aabb.accumulateBounds(*b); - ret = true; - } - } - - if (ret) - return {aabb}; - return {}; +float CProjectileWeapon::GetAudibleFallOff() const { + if (!x4_weaponDesc->x94_COLR) + return 0.f; + return x4_weaponDesc->x94_COLR.m_res->GetAudibleFallOff(); } -float CProjectileWeapon::GetAudibleFallOff() const -{ - if (!x4_weaponDesc->x94_COLR) - return 0.f; - return x4_weaponDesc->x94_COLR.m_res->GetAudibleFallOff(); -} - -float CProjectileWeapon::GetAudibleRange() const -{ - if (!x4_weaponDesc->x94_COLR) - return 0.f; - return x4_weaponDesc->x94_COLR.m_res->GetAudibleRange(); +float CProjectileWeapon::GetAudibleRange() const { + if (!x4_weaponDesc->x94_COLR) + return 0.f; + return x4_weaponDesc->x94_COLR.m_res->GetAudibleRange(); } std::experimental::optional> -CProjectileWeapon::GetDecalForCollision(EWeaponCollisionResponseTypes type) const -{ - if (!x4_weaponDesc->x94_COLR) - return {}; - return x4_weaponDesc->x94_COLR.m_res->GetDecalDescription(type); +CProjectileWeapon::GetDecalForCollision(EWeaponCollisionResponseTypes type) const { + if (!x4_weaponDesc->x94_COLR) + return {}; + return x4_weaponDesc->x94_COLR.m_res->GetDecalDescription(type); } -s32 CProjectileWeapon::GetSoundIdForCollision(EWeaponCollisionResponseTypes type) const -{ - if (!x4_weaponDesc->x94_COLR) - return -1; - return x4_weaponDesc->x94_COLR.m_res->GetSoundEffectId(type); +s32 CProjectileWeapon::GetSoundIdForCollision(EWeaponCollisionResponseTypes type) const { + if (!x4_weaponDesc->x94_COLR) + return -1; + return x4_weaponDesc->x94_COLR.m_res->GetSoundEffectId(type); } -std::experimental::optional> -CProjectileWeapon::CollisionOccured(EWeaponCollisionResponseTypes type, bool deflected, bool useTarget, - const zeus::CVector3f& pos, const zeus::CVector3f& normal, - const zeus::CVector3f& target) -{ - x80_localOffset = x14_localToWorldXf.transposeRotate(pos - x74_worldOffset) - x8c_projOffset; - zeus::CVector3f posToTarget = target - GetTranslation(); - if (deflected) - { - if (useTarget && posToTarget.canBeNormalized()) - { - SetWorldSpaceOrientation(zeus::lookAt(zeus::CVector3f::skZero, posToTarget.normalized())); - } +std::experimental::optional> CProjectileWeapon::CollisionOccured( + EWeaponCollisionResponseTypes type, bool deflected, bool useTarget, const zeus::CVector3f& pos, + const zeus::CVector3f& normal, const zeus::CVector3f& target) { + x80_localOffset = x14_localToWorldXf.transposeRotate(pos - x74_worldOffset) - x8c_projOffset; + zeus::CVector3f posToTarget = target - GetTranslation(); + if (deflected) { + if (useTarget && posToTarget.canBeNormalized()) { + SetWorldSpaceOrientation(zeus::lookAt(zeus::CVector3f::skZero, posToTarget.normalized())); + } else { + zeus::CTransform xf = GetTransform(); + SetWorldSpaceOrientation( + zeus::lookAt(zeus::CVector3f::skZero, xf.basis[1] - normal * (normal.dot(xf.basis[1]) * 2.f), normal)); + } + return {}; + } else { + x124_24_active = false; + if (xfc_APSMGen) + xfc_APSMGen->SetParticleEmission(false); + if (x100_APS2Gen) + x100_APS2Gen->SetParticleEmission(false); + if (x118_swoosh1) + x118_swoosh1->SetParticleEmission(false); + if (x11c_swoosh2) + x11c_swoosh2->SetParticleEmission(false); + if (x120_swoosh3) + x120_swoosh3->SetParticleEmission(false); + if (!x4_weaponDesc->x94_COLR) + return {}; + return x4_weaponDesc->x94_COLR.m_res->GetParticleDescription(type); + } +} + +void CProjectileWeapon::RenderParticles() const { + if (xfc_APSMGen) + xfc_APSMGen->Render(); + if (x100_APS2Gen) + x100_APS2Gen->Render(); + if (x118_swoosh1) + x118_swoosh1->Render(); + if (x11c_swoosh2) + x11c_swoosh2->Render(); + if (x120_swoosh3) + x120_swoosh3->Render(); + if (x104_) + x104_->Render(); +} + +void CProjectileWeapon::AddToRenderer() const { + if (xfc_APSMGen) + g_Renderer->AddParticleGen(*xfc_APSMGen); + if (x100_APS2Gen) + g_Renderer->AddParticleGen(*x100_APS2Gen); + if (x118_swoosh1) + g_Renderer->AddParticleGen(*x118_swoosh1); + if (x11c_swoosh2) + g_Renderer->AddParticleGen(*x11c_swoosh2); + if (x120_swoosh3) + g_Renderer->AddParticleGen(*x120_swoosh3); + if (x104_) + g_Renderer->AddParticleGen(*x104_); +} + +void CProjectileWeapon::Render() const { + if (xf4_curFrame > xe8_lifetime || !x124_24_active || !x108_model) + return; + + CGraphics::SetModelMatrix( + zeus::CTransform::Translate(x74_worldOffset) * x14_localToWorldXf * + zeus::CTransform::Translate(x44_localXf * x8c_projOffset + x80_localOffset + xa4_localOffset2) * + zeus::CTransform::Scale(x98_scale) * x44_localXf); + + std::vector useLights; + useLights.push_back(CLight::BuildLocalAmbient({}, xc8_ambientLightColor)); + const_cast(**x108_model).GetInstance().ActivateLights(useLights); + CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + (*x108_model)->Draw(flags); +} + +bool CProjectileWeapon::IsSystemDeletable() const { + if (xfc_APSMGen && !xfc_APSMGen->IsSystemDeletable()) + return false; + if (x100_APS2Gen && !x100_APS2Gen->IsSystemDeletable()) + return false; + if (x118_swoosh1 && !x118_swoosh1->IsSystemDeletable()) + return false; + if (x11c_swoosh2 && !x11c_swoosh2->IsSystemDeletable()) + return false; + if (x120_swoosh3 && !x120_swoosh3->IsSystemDeletable()) + return false; + if (x104_ && !x104_->IsSystemDeletable()) + return false; + if (x124_24_active) + return xf4_curFrame >= xe8_lifetime; + return true; +} + +void CProjectileWeapon::UpdateChildParticleSystems(float dt) { + double useDt; + if (zeus::close_enough(dt, 1.f / 60.f)) + useDt = 1.0 / 60.0; + else + useDt = dt; + + if (xfc_APSMGen) { + if (xf8_lastParticleFrame != xf4_curFrame) { + if (xf4_curFrame > xe8_lifetime) { + xfc_APSMGen->SetParticleEmission(false); + xfc_APSMGen->EndLifetime(); + } else { + if (x124_26_AP11) + xfc_APSMGen->SetGlobalTranslation(GetTranslation()); else - { - zeus::CTransform xf = GetTransform(); - SetWorldSpaceOrientation( - zeus::lookAt(zeus::CVector3f::skZero, xf.basis[1] - normal * (normal.dot(xf.basis[1]) * 2.f), normal)); - } - return {}; + xfc_APSMGen->SetTranslation(GetTranslation()); + if (x124_25_APSO) + xfc_APSMGen->SetOrientation(GetTransform()); + } } - else - { - x124_24_active = false; - if (xfc_APSMGen) - xfc_APSMGen->SetParticleEmission(false); - if (x100_APS2Gen) - x100_APS2Gen->SetParticleEmission(false); - if (x118_swoosh1) - x118_swoosh1->SetParticleEmission(false); - if (x11c_swoosh2) - x11c_swoosh2->SetParticleEmission(false); - if (x120_swoosh3) - x120_swoosh3->SetParticleEmission(false); - if (!x4_weaponDesc->x94_COLR) - return {}; - return x4_weaponDesc->x94_COLR.m_res->GetParticleDescription(type); + xfc_APSMGen->Update(useDt); + if (xfc_APSMGen->IsSystemDeletable()) + xfc_APSMGen.reset(); + } + + if (x100_APS2Gen) { + if (xf8_lastParticleFrame != xf4_curFrame) { + if (xf4_curFrame > xe8_lifetime) { + x100_APS2Gen->SetParticleEmission(false); + x100_APS2Gen->EndLifetime(); + } else { + if (x124_27_AP21) + x100_APS2Gen->SetGlobalTranslation(GetTranslation()); + else + x100_APS2Gen->SetTranslation(GetTranslation()); + if (x124_25_APSO) + x100_APS2Gen->SetOrientation(GetTransform()); + } } + x100_APS2Gen->Update(useDt); + if (x100_APS2Gen->IsSystemDeletable()) + x100_APS2Gen.reset(); + } + + if (x118_swoosh1) { + if (xf8_lastParticleFrame != xf4_curFrame) { + if (xf4_curFrame > xe8_lifetime) { + x118_swoosh1->SetParticleEmission(false); + } else { + if (x124_28_AS11) + x118_swoosh1->SetGlobalTranslation(GetTranslation()); + else + x118_swoosh1->SetTranslation(GetTranslation()); + x118_swoosh1->SetOrientation(GetTransform()); + } + } + x118_swoosh1->DoWarmupUpdate(); + if (x118_swoosh1->IsSystemDeletable()) + x118_swoosh1.reset(); + } + + if (x11c_swoosh2) { + if (xf8_lastParticleFrame != xf4_curFrame) { + if (xf4_curFrame > xe8_lifetime) { + x11c_swoosh2->SetParticleEmission(false); + } else { + if (x124_29_AS12) + x11c_swoosh2->SetGlobalTranslation(GetTranslation()); + else + x11c_swoosh2->SetTranslation(GetTranslation()); + x11c_swoosh2->SetOrientation(GetTransform()); + } + } + x11c_swoosh2->DoWarmupUpdate(); + if (x11c_swoosh2->IsSystemDeletable()) + x11c_swoosh2.reset(); + } + + if (x120_swoosh3) { + if (xf8_lastParticleFrame != xf4_curFrame) { + if (xf4_curFrame > xe8_lifetime) { + x120_swoosh3->SetParticleEmission(false); + } else { + if (x124_30_AS13) + x120_swoosh3->SetGlobalTranslation(GetTranslation()); + else + x120_swoosh3->SetTranslation(GetTranslation()); + x120_swoosh3->SetOrientation(GetTransform()); + } + } + x120_swoosh3->DoWarmupUpdate(); + if (x120_swoosh3->IsSystemDeletable()) + x120_swoosh3.reset(); + } + + if (x104_) { + x104_->Update(useDt); + if (x104_->IsSystemDeletable()) + x104_.reset(); + } + + xf8_lastParticleFrame = xf4_curFrame; } -void CProjectileWeapon::RenderParticles() const -{ - if (xfc_APSMGen) - xfc_APSMGen->Render(); - if (x100_APS2Gen) - x100_APS2Gen->Render(); - if (x118_swoosh1) - x118_swoosh1->Render(); - if (x11c_swoosh2) - x11c_swoosh2->Render(); - if (x120_swoosh3) - x120_swoosh3->Render(); - if (x104_) - x104_->Render(); +void CProjectileWeapon::UpdatePSTranslationAndOrientation() { + if (xe8_lifetime < xf4_curFrame || !x124_24_active) + return; + + if (CModVectorElement* psvm = x4_weaponDesc->xc_PSVM.get()) + psvm->GetValue(xf4_curFrame, xb0_velocity, x80_localOffset); + + if (x124_31_VMD2) + x80_localOffset += x44_localXf * xb0_velocity; + else + x80_localOffset += xb0_velocity; + + xb0_velocity += xbc_gravity / 60.f; + + if (CVectorElement* psov = x4_weaponDesc->x8_PSOV.get()) { + zeus::CVector3f orient; + psov->GetValue(xf4_curFrame, orient); + + zeus::CTransform xf = x44_localXf; + xf.rotateLocalX(zeus::degToRad(orient.x())); + xf.rotateLocalY(zeus::degToRad(orient.y())); + xf.rotateLocalZ(zeus::degToRad(orient.z())); + SetRelativeOrientation(xf); + } + + if (CVectorElement* pscl = x4_weaponDesc->x18_PSCL.get()) + pscl->GetValue(xf4_curFrame, x98_scale); + + if (CColorElement* pcol = x4_weaponDesc->x1c_PCOL.get()) + pcol->GetValue(xf4_curFrame, xc8_ambientLightColor); + + if (CVectorElement* pofs = x4_weaponDesc->x20_POFS.get()) + pofs->GetValue(xf4_curFrame, xa4_localOffset2); + + if (CVectorElement* ofst = x4_weaponDesc->x24_OFST.get()) + ofst->GetValue(xf4_curFrame, x8c_projOffset); } -void CProjectileWeapon::AddToRenderer() const -{ - if (xfc_APSMGen) - g_Renderer->AddParticleGen(*xfc_APSMGen); - if (x100_APS2Gen) - g_Renderer->AddParticleGen(*x100_APS2Gen); - if (x118_swoosh1) - g_Renderer->AddParticleGen(*x118_swoosh1); - if (x11c_swoosh2) - g_Renderer->AddParticleGen(*x11c_swoosh2); - if (x120_swoosh3) - g_Renderer->AddParticleGen(*x120_swoosh3); - if (x104_) - g_Renderer->AddParticleGen(*x104_); +void CProjectileWeapon::SetWorldSpaceOrientation(const zeus::CTransform& xf) { + x44_localXf = x14_localToWorldXf.inverse() * xf; } -void CProjectileWeapon::Render() const -{ - if (xf4_curFrame > xe8_lifetime || !x124_24_active || !x108_model) - return; - - CGraphics::SetModelMatrix(zeus::CTransform::Translate(x74_worldOffset) * x14_localToWorldXf * - zeus::CTransform::Translate(x44_localXf * x8c_projOffset + x80_localOffset + xa4_localOffset2) * - zeus::CTransform::Scale(x98_scale) * x44_localXf); - - std::vector useLights; - useLights.push_back(CLight::BuildLocalAmbient({}, xc8_ambientLightColor)); - const_cast(**x108_model).GetInstance().ActivateLights(useLights); - CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); - (*x108_model)->Draw(flags); +void CProjectileWeapon::UpdateParticleFX() { + for (int i = 0; i < xec_childSystemUpdateRate; ++i) + UpdateChildParticleSystems(1.f / 60.f); } -bool CProjectileWeapon::IsSystemDeletable() const -{ - if (xfc_APSMGen && !xfc_APSMGen->IsSystemDeletable()) - return false; - if (x100_APS2Gen && !x100_APS2Gen->IsSystemDeletable()) - return false; - if (x118_swoosh1 && !x118_swoosh1->IsSystemDeletable()) - return false; - if (x11c_swoosh2 && !x11c_swoosh2->IsSystemDeletable()) - return false; - if (x120_swoosh3 && !x120_swoosh3->IsSystemDeletable()) - return false; - if (x104_ && !x104_->IsSystemDeletable()) - return false; - if (x124_24_active) - return xf4_curFrame >= xe8_lifetime; - return true; -} +void CProjectileWeapon::Update(float dt) { + CGlobalRandom gr(x10_random); + xec_childSystemUpdateRate = 0; + double useDt; + if (zeus::close_enough(dt, 1.f / 60.f)) + useDt = 1.0 / 60.0; + else + useDt = dt; + useDt = std::max(0.0, useDt); + xd0_curTime += useDt; -void CProjectileWeapon::UpdateChildParticleSystems(float dt) -{ - double useDt; - if (zeus::close_enough(dt, 1.f / 60.f)) - useDt = 1.0 / 60.0; - else - useDt = dt; + double actualTime = xf4_curFrame * (1.0 / 60.0); - if (xfc_APSMGen) - { - if (xf8_lastParticleFrame != xf4_curFrame) - { - if (xf4_curFrame > xe8_lifetime) - { - xfc_APSMGen->SetParticleEmission(false); - xfc_APSMGen->EndLifetime(); - } - else - { - if (x124_26_AP11) - xfc_APSMGen->SetGlobalTranslation(GetTranslation()); - else - xfc_APSMGen->SetTranslation(GetTranslation()); - if (x124_25_APSO) - xfc_APSMGen->SetOrientation(GetTransform()); - } - } - xfc_APSMGen->Update(useDt); - if (xfc_APSMGen->IsSystemDeletable()) - xfc_APSMGen.reset(); + while (actualTime < xd0_curTime && !zeus::close_enough(actualTime, xd0_curTime)) { + if (xf4_curFrame < xe8_lifetime) { + CParticleGlobals::SetEmitterTime(xf4_curFrame); + CParticleGlobals::SetParticleLifetime(xe8_lifetime); + CParticleGlobals::UpdateParticleLifetimeTweenValues(xf4_curFrame); + UpdatePSTranslationAndOrientation(); } + actualTime += (1.0 / 60.0); + ++xf4_curFrame; + ++xec_childSystemUpdateRate; + } - if (x100_APS2Gen) - { - if (xf8_lastParticleFrame != xf4_curFrame) - { - if (xf4_curFrame > xe8_lifetime) - { - x100_APS2Gen->SetParticleEmission(false); - x100_APS2Gen->EndLifetime(); - } - else - { - if (x124_27_AP21) - x100_APS2Gen->SetGlobalTranslation(GetTranslation()); - else - x100_APS2Gen->SetTranslation(GetTranslation()); - if (x124_25_APSO) - x100_APS2Gen->SetOrientation(GetTransform()); - } - } - x100_APS2Gen->Update(useDt); - if (x100_APS2Gen->IsSystemDeletable()) - x100_APS2Gen.reset(); - } + if (zeus::close_enough(actualTime, xd0_curTime)) + xd0_curTime = actualTime; - if (x118_swoosh1) - { - if (xf8_lastParticleFrame != xf4_curFrame) - { - if (xf4_curFrame > xe8_lifetime) - { - x118_swoosh1->SetParticleEmission(false); - } - else - { - if (x124_28_AS11) - x118_swoosh1->SetGlobalTranslation(GetTranslation()); - else - x118_swoosh1->SetTranslation(GetTranslation()); - x118_swoosh1->SetOrientation(GetTransform()); - } - } - x118_swoosh1->DoWarmupUpdate(); - if (x118_swoosh1->IsSystemDeletable()) - x118_swoosh1.reset(); - } + xd8_remainderTime = (actualTime - xd0_curTime) * 60.0; - if (x11c_swoosh2) - { - if (xf8_lastParticleFrame != xf4_curFrame) - { - if (xf4_curFrame > xe8_lifetime) - { - x11c_swoosh2->SetParticleEmission(false); - } - else - { - if (x124_29_AS12) - x11c_swoosh2->SetGlobalTranslation(GetTranslation()); - else - x11c_swoosh2->SetTranslation(GetTranslation()); - x11c_swoosh2->SetOrientation(GetTransform()); - } - } - x11c_swoosh2->DoWarmupUpdate(); - if (x11c_swoosh2->IsSystemDeletable()) - x11c_swoosh2.reset(); - } - - if (x120_swoosh3) - { - if (xf8_lastParticleFrame != xf4_curFrame) - { - if (xf4_curFrame > xe8_lifetime) - { - x120_swoosh3->SetParticleEmission(false); - } - else - { - if (x124_30_AS13) - x120_swoosh3->SetGlobalTranslation(GetTranslation()); - else - x120_swoosh3->SetTranslation(GetTranslation()); - x120_swoosh3->SetOrientation(GetTransform()); - } - } - x120_swoosh3->DoWarmupUpdate(); - if (x120_swoosh3->IsSystemDeletable()) - x120_swoosh3.reset(); - } - - if (x104_) - { - x104_->Update(useDt); - if (x104_->IsSystemDeletable()) - x104_.reset(); - } - - xf8_lastParticleFrame = xf4_curFrame; + if (xf4_curFrame < xe8_lifetime) { + xe0_maxTurnRate = 0.f; + if (CRealElement* trat = x4_weaponDesc->x30_TRAT.get()) + trat->GetValue(0, xe0_maxTurnRate); + } } -void CProjectileWeapon::UpdatePSTranslationAndOrientation() -{ - if (xe8_lifetime < xf4_curFrame || !x124_24_active) - return; - - if (CModVectorElement* psvm = x4_weaponDesc->xc_PSVM.get()) - psvm->GetValue(xf4_curFrame, xb0_velocity, x80_localOffset); - - if (x124_31_VMD2) - x80_localOffset += x44_localXf * xb0_velocity; - else - x80_localOffset += xb0_velocity; - - xb0_velocity += xbc_gravity / 60.f; - - if (CVectorElement* psov = x4_weaponDesc->x8_PSOV.get()) - { - zeus::CVector3f orient; - psov->GetValue(xf4_curFrame, orient); - - zeus::CTransform xf = x44_localXf; - xf.rotateLocalX(zeus::degToRad(orient.x())); - xf.rotateLocalY(zeus::degToRad(orient.y())); - xf.rotateLocalZ(zeus::degToRad(orient.z())); - SetRelativeOrientation(xf); - } - - if (CVectorElement* pscl = x4_weaponDesc->x18_PSCL.get()) - pscl->GetValue(xf4_curFrame, x98_scale); - - if (CColorElement* pcol = x4_weaponDesc->x1c_PCOL.get()) - pcol->GetValue(xf4_curFrame, xc8_ambientLightColor); - - if (CVectorElement* pofs = x4_weaponDesc->x20_POFS.get()) - pofs->GetValue(xf4_curFrame, xa4_localOffset2); - - if (CVectorElement* ofst = x4_weaponDesc->x24_OFST.get()) - ofst->GetValue(xf4_curFrame, x8c_projOffset); -} - -void CProjectileWeapon::SetWorldSpaceOrientation(const zeus::CTransform& xf) -{ - x44_localXf = x14_localToWorldXf.inverse() * xf; -} - -void CProjectileWeapon::UpdateParticleFX() -{ - for (int i=0 ; ix30_TRAT.get()) - trat->GetValue(0, xe0_maxTurnRate); - } -} - -} +} // namespace urde diff --git a/Runtime/Weapon/CProjectileWeapon.hpp b/Runtime/Weapon/CProjectileWeapon.hpp index f7970def0..5bed9280f 100644 --- a/Runtime/Weapon/CProjectileWeapon.hpp +++ b/Runtime/Weapon/CProjectileWeapon.hpp @@ -11,93 +11,90 @@ #include "Particle/CWeaponDescription.hpp" #include "Collision/CCollisionResponseData.hpp" -namespace urde -{ +namespace urde { class CModel; class CDecalDescription; class CGenDescription; -class CProjectileWeapon -{ - static u16 g_GlobalSeed; - TLockedToken x4_weaponDesc; - CRandom16 x10_random; - zeus::CTransform x14_localToWorldXf; - zeus::CTransform x44_localXf; - zeus::CVector3f x74_worldOffset; - zeus::CVector3f x80_localOffset = zeus::CVector3f::skZero; - zeus::CVector3f x8c_projOffset = zeus::CVector3f::skZero; - zeus::CVector3f x98_scale = zeus::CVector3f::skOne; - zeus::CVector3f xa4_localOffset2 = zeus::CVector3f::skZero; - zeus::CVector3f xb0_velocity = zeus::CVector3f::skZero; - zeus::CVector3f xbc_gravity = zeus::CVector3f::skZero; - zeus::CColor xc8_ambientLightColor = zeus::CColor::skWhite; - double xd0_curTime = 0.0; - double xd8_remainderTime = 0.0; - float xe0_maxTurnRate = 0.f; - int xe4_flags; - int xe8_lifetime = 0; - int xec_childSystemUpdateRate = 0; - int xf0_ = 0; - int xf4_curFrame = 0; - int xf8_lastParticleFrame = -1; - std::unique_ptr xfc_APSMGen; - std::unique_ptr x100_APS2Gen; - std::unique_ptr x104_; - std::experimental::optional> x108_model; - std::unique_ptr x118_swoosh1; - std::unique_ptr x11c_swoosh2; - std::unique_ptr x120_swoosh3; - union - { - struct - { - bool x124_24_active : 1; - bool x124_25_APSO : 1; - bool x124_26_AP11 : 1; - bool x124_27_AP21 : 1; - bool x124_28_AS11 : 1; - bool x124_29_AS12 : 1; - bool x124_30_AS13 : 1; - bool x124_31_VMD2 : 1; - }; - u32 _dummy = 0; +class CProjectileWeapon { + static u16 g_GlobalSeed; + TLockedToken x4_weaponDesc; + CRandom16 x10_random; + zeus::CTransform x14_localToWorldXf; + zeus::CTransform x44_localXf; + zeus::CVector3f x74_worldOffset; + zeus::CVector3f x80_localOffset = zeus::CVector3f::skZero; + zeus::CVector3f x8c_projOffset = zeus::CVector3f::skZero; + zeus::CVector3f x98_scale = zeus::CVector3f::skOne; + zeus::CVector3f xa4_localOffset2 = zeus::CVector3f::skZero; + zeus::CVector3f xb0_velocity = zeus::CVector3f::skZero; + zeus::CVector3f xbc_gravity = zeus::CVector3f::skZero; + zeus::CColor xc8_ambientLightColor = zeus::CColor::skWhite; + double xd0_curTime = 0.0; + double xd8_remainderTime = 0.0; + float xe0_maxTurnRate = 0.f; + int xe4_flags; + int xe8_lifetime = 0; + int xec_childSystemUpdateRate = 0; + int xf0_ = 0; + int xf4_curFrame = 0; + int xf8_lastParticleFrame = -1; + std::unique_ptr xfc_APSMGen; + std::unique_ptr x100_APS2Gen; + std::unique_ptr x104_; + std::experimental::optional> x108_model; + std::unique_ptr x118_swoosh1; + std::unique_ptr x11c_swoosh2; + std::unique_ptr x120_swoosh3; + union { + struct { + bool x124_24_active : 1; + bool x124_25_APSO : 1; + bool x124_26_AP11 : 1; + bool x124_27_AP21 : 1; + bool x124_28_AS11 : 1; + bool x124_29_AS12 : 1; + bool x124_30_AS13 : 1; + bool x124_31_VMD2 : 1; }; + u32 _dummy = 0; + }; public: - CProjectileWeapon(const TToken& wDesc, const zeus::CVector3f& worldOffset, - const zeus::CTransform& orient, const zeus::CVector3f& scale, s32); - virtual ~CProjectileWeapon() = default; - bool IsProjectileActive() const { return x124_24_active; } - std::experimental::optional GetBounds() const; - const zeus::CVector3f& GetVelocity() const { return xb0_velocity; } - void SetVelocity(const zeus::CVector3f& vel) { xb0_velocity = vel; } - float GetMaxTurnRate() const { return xe0_maxTurnRate; } - float GetAudibleFallOff() const; - float GetAudibleRange() const; - std::experimental::optional> - GetDecalForCollision(EWeaponCollisionResponseTypes type) const; - s32 GetSoundIdForCollision(EWeaponCollisionResponseTypes type) const; - std::experimental::optional> - CollisionOccured(EWeaponCollisionResponseTypes type, bool deflected, bool useTarget, const zeus::CVector3f& pos, - const zeus::CVector3f& normal, const zeus::CVector3f& target); - TLockedToken GetWeaponDescription() const { return x4_weaponDesc; } - void RenderParticles() const; - virtual void AddToRenderer() const; - virtual void Render() const; - bool IsSystemDeletable() const; - void UpdateChildParticleSystems(float); - void UpdatePSTranslationAndOrientation(); - void SetWorldSpaceOrientation(const zeus::CTransform& xf); - void SetRelativeOrientation(const zeus::CTransform& xf) { x44_localXf = xf; } - virtual zeus::CVector3f GetTranslation() const; - virtual zeus::CTransform GetTransform() const; - void UpdateParticleFX(); - virtual void Update(float dt); - void SetGravity(const zeus::CVector3f& grav) { xbc_gravity = grav; } - static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; } - CElementGen* GetAttachedPS1() const { return xfc_APSMGen.get(); } - double GameTime() const { return xd0_curTime; } + CProjectileWeapon(const TToken& wDesc, const zeus::CVector3f& worldOffset, + const zeus::CTransform& orient, const zeus::CVector3f& scale, s32); + virtual ~CProjectileWeapon() = default; + bool IsProjectileActive() const { return x124_24_active; } + std::experimental::optional GetBounds() const; + const zeus::CVector3f& GetVelocity() const { return xb0_velocity; } + void SetVelocity(const zeus::CVector3f& vel) { xb0_velocity = vel; } + float GetMaxTurnRate() const { return xe0_maxTurnRate; } + float GetAudibleFallOff() const; + float GetAudibleRange() const; + std::experimental::optional> + GetDecalForCollision(EWeaponCollisionResponseTypes type) const; + s32 GetSoundIdForCollision(EWeaponCollisionResponseTypes type) const; + std::experimental::optional> CollisionOccured(EWeaponCollisionResponseTypes type, + bool deflected, bool useTarget, + const zeus::CVector3f& pos, + const zeus::CVector3f& normal, + const zeus::CVector3f& target); + TLockedToken GetWeaponDescription() const { return x4_weaponDesc; } + void RenderParticles() const; + virtual void AddToRenderer() const; + virtual void Render() const; + bool IsSystemDeletable() const; + void UpdateChildParticleSystems(float); + void UpdatePSTranslationAndOrientation(); + void SetWorldSpaceOrientation(const zeus::CTransform& xf); + void SetRelativeOrientation(const zeus::CTransform& xf) { x44_localXf = xf; } + virtual zeus::CVector3f GetTranslation() const; + virtual zeus::CTransform GetTransform() const; + void UpdateParticleFX(); + virtual void Update(float dt); + void SetGravity(const zeus::CVector3f& grav) { xbc_gravity = grav; } + static void SetGlobalSeed(u16 seed) { g_GlobalSeed = seed; } + CElementGen* GetAttachedPS1() const { return xfc_APSMGen.get(); } + double GameTime() const { return xd0_curTime; } }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CTargetableProjectile.cpp b/Runtime/Weapon/CTargetableProjectile.cpp index 3c358426f..e8850b951 100644 --- a/Runtime/Weapon/CTargetableProjectile.cpp +++ b/Runtime/Weapon/CTargetableProjectile.cpp @@ -1,22 +1,19 @@ #include "CTargetableProjectile.hpp" -namespace urde -{ +namespace urde { CTargetableProjectile::CTargetableProjectile( - const TToken& desc, EWeaponType type, - const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage, - const CDamageInfo& damage2, TUniqueId uid, TAreaId aid, TUniqueId owner, + const TToken& desc, EWeaponType type, const zeus::CTransform& xf, EMaterialTypes materials, + const CDamageInfo& damage, const CDamageInfo& damage2, TUniqueId uid, TAreaId aid, TUniqueId owner, TUniqueId homingTarget, EProjectileAttrib attribs, - const std::experimental::optional>& visorParticle, - u16 visorSfx, bool sendCollideMsg) + const std::experimental::optional>& visorParticle, u16 visorSfx, bool sendCollideMsg) : CEnergyProjectile(true, desc, type, xf, materials, damage, uid, aid, owner, homingTarget, attribs | EProjectileAttrib::BigProjectile | EProjectileAttrib::PartialCharge | - EProjectileAttrib::PlasmaProjectile, false, zeus::CVector3f::skOne, visorParticle, - visorSfx, sendCollideMsg), x3e0_dInfo2(damage2) -{ - x68_material.Add(EMaterialTypes::Target); - x68_material.Add(EMaterialTypes::Orbit); + EProjectileAttrib::PlasmaProjectile, + false, zeus::CVector3f::skOne, visorParticle, visorSfx, sendCollideMsg) +, x3e0_dInfo2(damage2) { + x68_material.Add(EMaterialTypes::Target); + x68_material.Add(EMaterialTypes::Orbit); } -} +} // namespace urde diff --git a/Runtime/Weapon/CTargetableProjectile.hpp b/Runtime/Weapon/CTargetableProjectile.hpp index 2a08188c3..e709f5503 100644 --- a/Runtime/Weapon/CTargetableProjectile.hpp +++ b/Runtime/Weapon/CTargetableProjectile.hpp @@ -2,20 +2,17 @@ #include "CEnergyProjectile.hpp" -namespace urde -{ +namespace urde { + +class CTargetableProjectile : public CEnergyProjectile { + CDamageInfo x3e0_dInfo2; -class CTargetableProjectile : public CEnergyProjectile -{ - CDamageInfo x3e0_dInfo2; public: - CTargetableProjectile(const TToken& desc, EWeaponType type, - const zeus::CTransform& xf, EMaterialTypes materials, const CDamageInfo& damage, - const CDamageInfo& damage2, TUniqueId uid, TAreaId aid, TUniqueId owner, - TUniqueId homingTarget, EProjectileAttrib attribs, - const std::experimental::optional>& visorParticle, - u16 visorSfx, bool sendCollideMsg); + CTargetableProjectile(const TToken& desc, EWeaponType type, const zeus::CTransform& xf, + EMaterialTypes materials, const CDamageInfo& damage, const CDamageInfo& damage2, TUniqueId uid, + TAreaId aid, TUniqueId owner, TUniqueId homingTarget, EProjectileAttrib attribs, + const std::experimental::optional>& visorParticle, u16 visorSfx, + bool sendCollideMsg); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CWaveBeam.cpp b/Runtime/Weapon/CWaveBeam.cpp index 92ae5e67d..e37fc141e 100644 --- a/Runtime/Weapon/CWaveBeam.cpp +++ b/Runtime/Weapon/CWaveBeam.cpp @@ -3,187 +3,158 @@ #include "CSimplePool.hpp" #include "CEnergyProjectile.hpp" -namespace urde -{ +namespace urde { -CWaveBeam::CWaveBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale) -: CGunWeapon(characterId, type, playerId, playerMaterial, scale) -{ - x21c_waveBeam = g_SimplePool->GetObj("WaveBeam"); - x228_wave2nd1 = g_SimplePool->GetObj("Wave2nd_1"); - x234_wave2nd2 = g_SimplePool->GetObj("Wave2nd_2"); - x240_wave2nd3 = g_SimplePool->GetObj("Wave2nd_3"); - x258_24_loaded = false; - x258_25_effectTimerActive = false; +CWaveBeam::CWaveBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale) +: CGunWeapon(characterId, type, playerId, playerMaterial, scale) { + x21c_waveBeam = g_SimplePool->GetObj("WaveBeam"); + x228_wave2nd1 = g_SimplePool->GetObj("Wave2nd_1"); + x234_wave2nd2 = g_SimplePool->GetObj("Wave2nd_2"); + x240_wave2nd3 = g_SimplePool->GetObj("Wave2nd_3"); + x258_24_loaded = false; + x258_25_effectTimerActive = false; } -void CWaveBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None) - { - if (x254_chargeFx) - x254_chargeFx->Render(); - if (x250_chargeElec) - x250_chargeElec->Render(); - } - CGunWeapon::PostRenderGunFx(mgr, xf); +void CWaveBeam::PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf) { + if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None) { + if (x254_chargeFx) + x254_chargeFx->Render(); + if (x250_chargeElec) + x250_chargeElec->Render(); + } + CGunWeapon::PostRenderGunFx(mgr, xf); } -void CWaveBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) -{ - if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None) - { - if (x258_25_effectTimerActive && x24c_effectTimer < 0.f) - { - x1cc_enabledSecondaryEffect = ESecondaryFxType::None; - x24c_effectTimer = 0.f; - x258_25_effectTimerActive = false; - } - else - { - if (x254_chargeFx) - { - x254_chargeFx->SetGlobalTranslation(xf.origin); - x254_chargeFx->SetGlobalOrientation(xf.getRotation()); - x254_chargeFx->Update(dt); - } - if (x250_chargeElec) - { - x250_chargeElec->SetGlobalTranslation(xf.origin); - x250_chargeElec->SetGlobalOrientation(xf.getRotation()); - x250_chargeElec->Update(dt); - } - } - if (x258_25_effectTimerActive && x24c_effectTimer > 0.f) - x24c_effectTimer -= 0.f; +void CWaveBeam::UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf) { + if (x1cc_enabledSecondaryEffect != ESecondaryFxType::None) { + if (x258_25_effectTimerActive && x24c_effectTimer < 0.f) { + x1cc_enabledSecondaryEffect = ESecondaryFxType::None; + x24c_effectTimer = 0.f; + x258_25_effectTimerActive = false; + } else { + if (x254_chargeFx) { + x254_chargeFx->SetGlobalTranslation(xf.origin); + x254_chargeFx->SetGlobalOrientation(xf.getRotation()); + x254_chargeFx->Update(dt); + } + if (x250_chargeElec) { + x250_chargeElec->SetGlobalTranslation(xf.origin); + x250_chargeElec->SetGlobalOrientation(xf.getRotation()); + x250_chargeElec->Update(dt); + } } - CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); + if (x258_25_effectTimerActive && x24c_effectTimer > 0.f) + x24c_effectTimer -= 0.f; + } + CGunWeapon::UpdateGunFx(shotSmoke, dt, mgr, xf); } static const float skShotAnglePitch = 120.f; -static const u16 kSoundId[] = { SFXwpn_fire_wave_normal, SFXwpn_fire_wave_charged }; +static const u16 kSoundId[] = {SFXwpn_fire_wave_normal, SFXwpn_fire_wave_charged}; void CWaveBeam::Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) -{ - if (chargeState == EChargeState::Charged) - { - CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); - } - else - { - float randAng = mgr.GetActiveRandom()->Float() * 360.f; - auto& weaponDesc = x144_weapons[int(chargeState)]; - for (int i=0 ; i<3 ; ++i) - { - zeus::CTransform shotXf = xf * zeus::CTransform::RotateY(zeus::degToRad((randAng + i) * skShotAnglePitch)); - CEnergyProjectile* proj = new CEnergyProjectile(true, weaponDesc, x1c0_weaponType, shotXf, - x1c8_playerMaterial, GetDamageInfo(mgr, chargeState, chargeFactor1),mgr.AllocateUniqueId(), - kInvalidAreaId, x1c4_playerId, homingTarget, EProjectileAttrib::ArmCannon, underwater, - zeus::CVector3f::skOne, {}, -1, false); - mgr.AddObject(proj); - proj->Think(dt, mgr); - } + CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2) { + if (chargeState == EChargeState::Charged) { + CGunWeapon::Fire(underwater, dt, chargeState, xf, mgr, homingTarget, chargeFactor1, chargeFactor2); + } else { + float randAng = mgr.GetActiveRandom()->Float() * 360.f; + auto& weaponDesc = x144_weapons[int(chargeState)]; + for (int i = 0; i < 3; ++i) { + zeus::CTransform shotXf = xf * zeus::CTransform::RotateY(zeus::degToRad((randAng + i) * skShotAnglePitch)); + CEnergyProjectile* proj = new CEnergyProjectile( + true, weaponDesc, x1c0_weaponType, shotXf, x1c8_playerMaterial, + GetDamageInfo(mgr, chargeState, chargeFactor1), mgr.AllocateUniqueId(), kInvalidAreaId, x1c4_playerId, + homingTarget, EProjectileAttrib::ArmCannon, underwater, zeus::CVector3f::skOne, {}, -1, false); + mgr.AddObject(proj); + proj->Think(dt, mgr); } + } - if (chargeState == EChargeState::Charged) - x218_25_enableCharge = true; + if (chargeState == EChargeState::Charged) + x218_25_enableCharge = true; - NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); - CAnimPlaybackParms parms(skShootAnim[int(chargeState)], -1, 1.f, true); - x10_solidModelData->AnimationData()->EnableLooping(false); - x10_solidModelData->AnimationData()->SetAnimation(parms, false); + NWeaponTypes::play_sfx(kSoundId[int(chargeState)], underwater, false, 0.165f); + CAnimPlaybackParms parms(skShootAnim[int(chargeState)], -1, 1.f, true); + x10_solidModelData->AnimationData()->EnableLooping(false); + x10_solidModelData->AnimationData()->SetAnimation(parms, false); } -void CWaveBeam::EnableSecondaryFx(ESecondaryFxType type) -{ - switch (type) - { - case ESecondaryFxType::None: - x1cc_enabledSecondaryEffect = ESecondaryFxType::None; - break; - case ESecondaryFxType::CancelCharge: - if (x1cc_enabledSecondaryEffect == ESecondaryFxType::None) - break; - default: - if (x1cc_enabledSecondaryEffect != ESecondaryFxType::ToCombo) - { - auto& fx = type == ESecondaryFxType::Charge ? x228_wave2nd1 : x234_wave2nd2; - x250_chargeElec = std::make_unique(fx); - x250_chargeElec->SetGlobalScale(x4_scale); - } - switch (type) - { - case ESecondaryFxType::Charge: - x254_chargeFx.reset(); - break; - case ESecondaryFxType::CancelCharge: - if (x1cc_enabledSecondaryEffect != ESecondaryFxType::CancelCharge) - { - x258_25_effectTimerActive = true; - x24c_effectTimer = 3.f; - if (x254_chargeFx) - x254_chargeFx->SetParticleEmission(false); - } - break; - case ESecondaryFxType::ToCombo: - x254_chargeFx = std::make_unique(x240_wave2nd3); - x254_chargeFx->SetGlobalScale(x4_scale); - x24c_effectTimer = 0.f; - x258_25_effectTimerActive = true; - default: - break; - } - x1cc_enabledSecondaryEffect = type; - } -} - -void CWaveBeam::Update(float dt, CStateManager& mgr) -{ - CGunWeapon::Update(dt, mgr); - if (IsLoaded()) - return; - - if (CGunWeapon::IsLoaded() && !x258_24_loaded) - { - x258_24_loaded = x228_wave2nd1.IsLoaded() && x234_wave2nd2.IsLoaded() && - x240_wave2nd3.IsLoaded() && x21c_waveBeam.IsLoaded(); - } -} - -void CWaveBeam::Load(CStateManager& mgr, bool subtypeBasePose) -{ - CGunWeapon::Load(mgr, subtypeBasePose); - x228_wave2nd1.Lock(); - x234_wave2nd2.Lock(); - x240_wave2nd3.Lock(); - x21c_waveBeam.Lock(); -} - -void CWaveBeam::ReInitVariables() -{ - x24c_effectTimer = 0.f; - x250_chargeElec.reset(); - x254_chargeFx.reset(); - x258_24_loaded = false; - x258_25_effectTimerActive = false; +void CWaveBeam::EnableSecondaryFx(ESecondaryFxType type) { + switch (type) { + case ESecondaryFxType::None: x1cc_enabledSecondaryEffect = ESecondaryFxType::None; + break; + case ESecondaryFxType::CancelCharge: + if (x1cc_enabledSecondaryEffect == ESecondaryFxType::None) + break; + default: + if (x1cc_enabledSecondaryEffect != ESecondaryFxType::ToCombo) { + auto& fx = type == ESecondaryFxType::Charge ? x228_wave2nd1 : x234_wave2nd2; + x250_chargeElec = std::make_unique(fx); + x250_chargeElec->SetGlobalScale(x4_scale); + } + switch (type) { + case ESecondaryFxType::Charge: + x254_chargeFx.reset(); + break; + case ESecondaryFxType::CancelCharge: + if (x1cc_enabledSecondaryEffect != ESecondaryFxType::CancelCharge) { + x258_25_effectTimerActive = true; + x24c_effectTimer = 3.f; + if (x254_chargeFx) + x254_chargeFx->SetParticleEmission(false); + } + break; + case ESecondaryFxType::ToCombo: + x254_chargeFx = std::make_unique(x240_wave2nd3); + x254_chargeFx->SetGlobalScale(x4_scale); + x24c_effectTimer = 0.f; + x258_25_effectTimerActive = true; + default: + break; + } + x1cc_enabledSecondaryEffect = type; + } } -void CWaveBeam::Unload(CStateManager& mgr) -{ - CGunWeapon::Unload(mgr); - x21c_waveBeam.Unlock(); - x240_wave2nd3.Unlock(); - x234_wave2nd2.Unlock(); - x228_wave2nd1.Unlock(); - ReInitVariables(); +void CWaveBeam::Update(float dt, CStateManager& mgr) { + CGunWeapon::Update(dt, mgr); + if (IsLoaded()) + return; + + if (CGunWeapon::IsLoaded() && !x258_24_loaded) { + x258_24_loaded = + x228_wave2nd1.IsLoaded() && x234_wave2nd2.IsLoaded() && x240_wave2nd3.IsLoaded() && x21c_waveBeam.IsLoaded(); + } } -bool CWaveBeam::IsLoaded() const -{ - return CGunWeapon::IsLoaded() && x258_24_loaded; +void CWaveBeam::Load(CStateManager& mgr, bool subtypeBasePose) { + CGunWeapon::Load(mgr, subtypeBasePose); + x228_wave2nd1.Lock(); + x234_wave2nd2.Lock(); + x240_wave2nd3.Lock(); + x21c_waveBeam.Lock(); } -} \ No newline at end of file +void CWaveBeam::ReInitVariables() { + x24c_effectTimer = 0.f; + x250_chargeElec.reset(); + x254_chargeFx.reset(); + x258_24_loaded = false; + x258_25_effectTimerActive = false; + x1cc_enabledSecondaryEffect = ESecondaryFxType::None; +} + +void CWaveBeam::Unload(CStateManager& mgr) { + CGunWeapon::Unload(mgr); + x21c_waveBeam.Unlock(); + x240_wave2nd3.Unlock(); + x234_wave2nd2.Unlock(); + x228_wave2nd1.Unlock(); + ReInitVariables(); +} + +bool CWaveBeam::IsLoaded() const { return CGunWeapon::IsLoaded() && x258_24_loaded; } + +} // namespace urde \ No newline at end of file diff --git a/Runtime/Weapon/CWaveBeam.hpp b/Runtime/Weapon/CWaveBeam.hpp index 25a12bc41..83c6f73e5 100644 --- a/Runtime/Weapon/CWaveBeam.hpp +++ b/Runtime/Weapon/CWaveBeam.hpp @@ -2,35 +2,33 @@ #include "CGunWeapon.hpp" -namespace urde -{ +namespace urde { + +class CWaveBeam final : public CGunWeapon { + TCachedToken x21c_waveBeam; + TCachedToken x228_wave2nd1; + TCachedToken x234_wave2nd2; + TCachedToken x240_wave2nd3; + float x24c_effectTimer = 0.f; + std::unique_ptr x250_chargeElec; + std::unique_ptr x254_chargeFx; + bool x258_24_loaded : 1; + bool x258_25_effectTimerActive : 1; + void ReInitVariables(); -class CWaveBeam final : public CGunWeapon -{ - TCachedToken x21c_waveBeam; - TCachedToken x228_wave2nd1; - TCachedToken x234_wave2nd2; - TCachedToken x240_wave2nd3; - float x24c_effectTimer = 0.f; - std::unique_ptr x250_chargeElec; - std::unique_ptr x254_chargeFx; - bool x258_24_loaded : 1; - bool x258_25_effectTimerActive : 1; - void ReInitVariables(); public: - CWaveBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, - EMaterialTypes playerMaterial, const zeus::CVector3f& scale); + CWaveBeam(CAssetId characterId, EWeaponType type, TUniqueId playerId, EMaterialTypes playerMaterial, + const zeus::CVector3f& scale); - void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); - void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); - void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, - CStateManager& mgr, TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); - void EnableSecondaryFx(ESecondaryFxType type); - void Update(float dt, CStateManager& mgr); - void Load(CStateManager& mgr, bool subtypeBasePose); - void Unload(CStateManager& mgr); - bool IsLoaded() const; + void PostRenderGunFx(const CStateManager& mgr, const zeus::CTransform& xf); + void UpdateGunFx(bool shotSmoke, float dt, const CStateManager& mgr, const zeus::CTransform& xf); + void Fire(bool underwater, float dt, EChargeState chargeState, const zeus::CTransform& xf, CStateManager& mgr, + TUniqueId homingTarget, float chargeFactor1, float chargeFactor2); + void EnableSecondaryFx(ESecondaryFxType type); + void Update(float dt, CStateManager& mgr); + void Load(CStateManager& mgr, bool subtypeBasePose); + void Unload(CStateManager& mgr); + bool IsLoaded() const; }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CWaveBuster.cpp b/Runtime/Weapon/CWaveBuster.cpp index 6ab29abc2..38afb020e 100644 --- a/Runtime/Weapon/CWaveBuster.cpp +++ b/Runtime/Weapon/CWaveBuster.cpp @@ -2,49 +2,38 @@ #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" -namespace urde -{ +namespace urde { CWaveBuster::CWaveBuster(const TToken& desc, EWeaponType type, const zeus::CTransform& xf, - EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, - TUniqueId owner, TUniqueId homingTarget, EProjectileAttrib attrib) + EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, + TUniqueId homingTarget, EProjectileAttrib attrib) : CGameProjectile(true, desc, "WaveBuster", type, xf, matType, dInfo, uid, aid, owner, homingTarget, attrib, false, - zeus::CVector3f::skOne, {}, -1, false), - x2e8_originalXf(xf), - x348_targetPoint(x2e8_originalXf.basis[1].normalized() * 25.f + x2e8_originalXf.origin), - x354_busterSwoosh1(g_SimplePool->GetObj("BusterSwoosh1")), - x360_busterSwoosh2(g_SimplePool->GetObj("BusterSwoosh2")), - x36c_busterSparks(g_SimplePool->GetObj("BusterSparks")), - x378_busterLight(g_SimplePool->GetObj("BusterLight")) -{ - x354_busterSwoosh1.GetObj(); - x360_busterSwoosh2.GetObj(); - x36c_busterSparks.GetObj(); - x378_busterLight.GetObj(); - x384_busterSwoosh1Gen = std::make_unique(x354_busterSwoosh1, 0); - x388_busterSwoosh2Gen = std::make_unique(x360_busterSwoosh2, 0); - x38c_busterSparksGen = std::make_unique(x36c_busterSparks); - x390_busterLightGen = std::make_unique(x378_busterLight); - x3d0_24_firing = true; - x3d0_25_ = true; - x3d0_26_ = false; - x3d0_27_ = false; - x3d0_28_ = true; + zeus::CVector3f::skOne, {}, -1, false) +, x2e8_originalXf(xf) +, x348_targetPoint(x2e8_originalXf.basis[1].normalized() * 25.f + x2e8_originalXf.origin) +, x354_busterSwoosh1(g_SimplePool->GetObj("BusterSwoosh1")) +, x360_busterSwoosh2(g_SimplePool->GetObj("BusterSwoosh2")) +, x36c_busterSparks(g_SimplePool->GetObj("BusterSparks")) +, x378_busterLight(g_SimplePool->GetObj("BusterLight")) { + x354_busterSwoosh1.GetObj(); + x360_busterSwoosh2.GetObj(); + x36c_busterSparks.GetObj(); + x378_busterLight.GetObj(); + x384_busterSwoosh1Gen = std::make_unique(x354_busterSwoosh1, 0); + x388_busterSwoosh2Gen = std::make_unique(x360_busterSwoosh2, 0); + x38c_busterSparksGen = std::make_unique(x36c_busterSparks); + x390_busterLightGen = std::make_unique(x378_busterLight); + x3d0_24_firing = true; + x3d0_25_ = true; + x3d0_26_ = false; + x3d0_27_ = false; + x3d0_28_ = true; } -void CWaveBuster::UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr) -{ +void CWaveBuster::UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr) {} -} +void CWaveBuster::ResetBeam(bool deactivate) {} -void CWaveBuster::ResetBeam(bool deactivate) -{ +void CWaveBuster::SetNewTarget(TUniqueId id) {} -} - -void CWaveBuster::SetNewTarget(TUniqueId id) -{ - -} - -} +} // namespace urde diff --git a/Runtime/Weapon/CWaveBuster.hpp b/Runtime/Weapon/CWaveBuster.hpp index 8219cf2f2..2c1e6afb9 100644 --- a/Runtime/Weapon/CWaveBuster.hpp +++ b/Runtime/Weapon/CWaveBuster.hpp @@ -2,53 +2,51 @@ #include "CGameProjectile.hpp" -namespace urde -{ +namespace urde { + +class CWaveBuster : public CGameProjectile { + zeus::CTransform x2e8_originalXf; + zeus::CVector3f x318_; + zeus::CVector3f x324_; + zeus::CVector3f x330_; + zeus::CVector3f x33c_; + zeus::CVector3f x348_targetPoint; + TCachedToken x354_busterSwoosh1; + TCachedToken x360_busterSwoosh2; + TCachedToken x36c_busterSparks; + TCachedToken x378_busterLight; + std::unique_ptr x384_busterSwoosh1Gen; + std::unique_ptr x388_busterSwoosh2Gen; + std::unique_ptr x38c_busterSparksGen; + std::unique_ptr x390_busterLightGen; + CRandom16 x394_rand = {99}; + float x39c_ = 0.5f; + float x3a0_ = 0.5f; + float x3a4_ = 0.f; + float x3a8_ = 0.f; + float x3ac_ = 0.f; + float x3b0_ = 0.f; + float x3b4_ = 0.f; + float x3b8_ = 0.f; + float x3bc_ = 0.f; + float x3c0_ = 0.f; + float x3c4_ = 0.f; + float x3c8_ = 0.f; + u32 x3cc_ = 0; + bool x3d0_24_firing : 1; + bool x3d0_25_ : 1; + bool x3d0_26_ : 1; + bool x3d0_27_ : 1; + bool x3d0_28_ : 1; -class CWaveBuster : public CGameProjectile -{ - zeus::CTransform x2e8_originalXf; - zeus::CVector3f x318_; - zeus::CVector3f x324_; - zeus::CVector3f x330_; - zeus::CVector3f x33c_; - zeus::CVector3f x348_targetPoint; - TCachedToken x354_busterSwoosh1; - TCachedToken x360_busterSwoosh2; - TCachedToken x36c_busterSparks; - TCachedToken x378_busterLight; - std::unique_ptr x384_busterSwoosh1Gen; - std::unique_ptr x388_busterSwoosh2Gen; - std::unique_ptr x38c_busterSparksGen; - std::unique_ptr x390_busterLightGen; - CRandom16 x394_rand = {99}; - float x39c_ = 0.5f; - float x3a0_ = 0.5f; - float x3a4_ = 0.f; - float x3a8_ = 0.f; - float x3ac_ = 0.f; - float x3b0_ = 0.f; - float x3b4_ = 0.f; - float x3b8_ = 0.f; - float x3bc_ = 0.f; - float x3c0_ = 0.f; - float x3c4_ = 0.f; - float x3c8_ = 0.f; - u32 x3cc_ = 0; - bool x3d0_24_firing : 1; - bool x3d0_25_ : 1; - bool x3d0_26_ : 1; - bool x3d0_27_ : 1; - bool x3d0_28_ : 1; public: - CWaveBuster(const TToken& desc, EWeaponType type, const zeus::CTransform& xf, - EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, - TUniqueId owner, TUniqueId homingTarget, EProjectileAttrib attrib); - bool IsFiring() const { return x3d0_24_firing; } - void UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr); - void ResetBeam(bool deactivate); - void SetNewTarget(TUniqueId id); + CWaveBuster(const TToken& desc, EWeaponType type, const zeus::CTransform& xf, + EMaterialTypes matType, const CDamageInfo& dInfo, TUniqueId uid, TAreaId aid, TUniqueId owner, + TUniqueId homingTarget, EProjectileAttrib attrib); + bool IsFiring() const { return x3d0_24_firing; } + void UpdateFx(const zeus::CTransform& xf, float dt, CStateManager& mgr); + void ResetBeam(bool deactivate); + void SetNewTarget(TUniqueId id); }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CWeapon.cpp b/Runtime/Weapon/CWeapon.cpp index a0e2ecf46..69a5b6e9a 100644 --- a/Runtime/Weapon/CWeapon.cpp +++ b/Runtime/Weapon/CWeapon.cpp @@ -4,111 +4,96 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CWeapon::CWeapon(TUniqueId uid, TAreaId aid, bool active, TUniqueId owner, EWeaponType type, - std::string_view name, const zeus::CTransform& xf, const CMaterialFilter& filter, - const CMaterialList& mList, const CDamageInfo& dInfo, EProjectileAttrib attribs, CModelData&& mData) +CWeapon::CWeapon(TUniqueId uid, TAreaId aid, bool active, TUniqueId owner, EWeaponType type, std::string_view name, + const zeus::CTransform& xf, const CMaterialFilter& filter, const CMaterialList& mList, + const CDamageInfo& dInfo, EProjectileAttrib attribs, CModelData&& mData) : CActor(uid, active, name, CEntityInfo(aid, CEntity::NullConnectionList), xf, std::move(mData), mList, - CActorParameters::None(), kInvalidUniqueId), - xe8_projectileAttribs(attribs), xec_ownerId(owner), xf0_weaponType(type), xf8_filter(filter), - x110_origDamageInfo(dInfo), x12c_curDamageInfo(dInfo) -{ + CActorParameters::None(), kInvalidUniqueId) +, xe8_projectileAttribs(attribs) +, xec_ownerId(owner) +, xf0_weaponType(type) +, xf8_filter(filter) +, x110_origDamageInfo(dInfo) +, x12c_curDamageInfo(dInfo) {} + +void CWeapon::Accept(urde::IVisitor& visitor) { visitor.Visit(this); } + +void CWeapon::Think(float dt, CStateManager& mgr) { + x148_curTime += dt; + if ((xe8_projectileAttribs & EProjectileAttrib::DamageFalloff) == EProjectileAttrib::DamageFalloff) { + float damMul = std::max(0.f, 1.f - x148_curTime * x14c_damageFalloffSpeed); + x12c_curDamageInfo.SetDamage(x110_origDamageInfo.GetDamage() * damMul); + x12c_curDamageInfo.SetRadius(x110_origDamageInfo.GetRadius() * damMul); + x12c_curDamageInfo.SetKnockBackPower(x110_origDamageInfo.GetKnockBackPower() * damMul); + x12c_curDamageInfo.SetWeaponMode(x110_origDamageInfo.GetWeaponMode()); + x12c_curDamageInfo.SetNoImmunity(false); + } else { + x12c_curDamageInfo = x110_origDamageInfo; + } + CEntity::Think(dt, mgr); } -void CWeapon::Accept(urde::IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CWeapon::Think(float dt, CStateManager& mgr) -{ - x148_curTime += dt; - if ((xe8_projectileAttribs & EProjectileAttrib::DamageFalloff) == EProjectileAttrib::DamageFalloff) - { - float damMul = std::max(0.f, 1.f - x148_curTime * x14c_damageFalloffSpeed); - x12c_curDamageInfo.SetDamage(x110_origDamageInfo.GetDamage() * damMul); - x12c_curDamageInfo.SetRadius(x110_origDamageInfo.GetRadius() * damMul); - x12c_curDamageInfo.SetKnockBackPower(x110_origDamageInfo.GetKnockBackPower() * damMul); - x12c_curDamageInfo.SetWeaponMode(x110_origDamageInfo.GetWeaponMode()); - x12c_curDamageInfo.SetNoImmunity(false); - } - else - { - x12c_curDamageInfo = x110_origDamageInfo; - } - CEntity::Think(dt, mgr); -} - -void CWeapon::Render(const CStateManager&) const -{ - // Empty +void CWeapon::Render(const CStateManager&) const { + // Empty } EWeaponCollisionResponseTypes CWeapon::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const -{ - return EWeaponCollisionResponseTypes::Projectile; + const CWeaponMode&, EProjectileAttrib) const { + return EWeaponCollisionResponseTypes::Projectile; } -void CWeapon::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager& mgr) -{ - bool doRipple = true; - float mag = 0.f; - switch (xf0_weaponType) - { - case EWeaponType::Power: - mag = 0.1f; - break; - case EWeaponType::Ice: - mag = 0.3f; - break; - case EWeaponType::Wave: - mag = 0.1f; - break; - case EWeaponType::Plasma: - break; - case EWeaponType::Missile: - mag = 0.5f; - break; - case EWeaponType::Phazon: - mag = 0.1f; - break; - default: +void CWeapon::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager& mgr) { + bool doRipple = true; + float mag = 0.f; + switch (xf0_weaponType) { + case EWeaponType::Power: + mag = 0.1f; + break; + case EWeaponType::Ice: + mag = 0.3f; + break; + case EWeaponType::Wave: + mag = 0.1f; + break; + case EWeaponType::Plasma: + break; + case EWeaponType::Missile: + mag = 0.5f; + break; + case EWeaponType::Phazon: + mag = 0.1f; + break; + default: + doRipple = false; + break; + } + + if ((xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::None && + state != EFluidState::InFluid) + mag += 0.5f; + if ((xe8_projectileAttribs & EProjectileAttrib::Charged) != EProjectileAttrib::None) + mag += 0.25f; + if (mag > 1.f) + mag = 1.f; + + if (doRipple) { + zeus::CVector3f pos = GetTranslation(); + pos.z() = float(water.GetTriggerBoundsWR().max.z()); + if ((xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::None) { + if (!water.CanRippleAtPoint(pos)) doRipple = false; - break; + } else if (state == EFluidState::InFluid) { + doRipple = false; } - if ((xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::None && - state != EFluidState::InFluid) - mag += 0.5f; - if ((xe8_projectileAttribs & EProjectileAttrib::Charged) != EProjectileAttrib::None) - mag += 0.25f; - if (mag > 1.f) - mag = 1.f; - - if (doRipple) - { - zeus::CVector3f pos = GetTranslation(); - pos.z() = float(water.GetTriggerBoundsWR().max.z()); - if ((xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::None) - { - if (!water.CanRippleAtPoint(pos)) - doRipple = false; - } - else if (state == EFluidState::InFluid) - { - doRipple = false; - } - - if (doRipple) - { - water.GetFluidPlane().AddRipple(mag, x8_uid, pos, water, mgr); - mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, pos, mag, - state == EFluidState::EnteredFluid || state == EFluidState::LeftFluid); - } + if (doRipple) { + water.GetFluidPlane().AddRipple(mag, x8_uid, pos, water, mgr); + mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, pos, mag, + state == EFluidState::EnteredFluid || state == EFluidState::LeftFluid); } + } } -} +} // namespace urde diff --git a/Runtime/Weapon/CWeapon.hpp b/Runtime/Weapon/CWeapon.hpp index ebaa860a8..79e8accf4 100644 --- a/Runtime/Weapon/CWeapon.hpp +++ b/Runtime/Weapon/CWeapon.hpp @@ -5,45 +5,43 @@ #include "World/CDamageInfo.hpp" #include "Collision/CMaterialFilter.hpp" -namespace urde -{ -class CWeapon : public CActor -{ +namespace urde { +class CWeapon : public CActor { protected: - EProjectileAttrib xe8_projectileAttribs; - TUniqueId xec_ownerId; - EWeaponType xf0_weaponType; - CMaterialFilter xf8_filter; - CDamageInfo x110_origDamageInfo; - CDamageInfo x12c_curDamageInfo; - float x148_curTime = 0.f; - float x14c_damageFalloffSpeed = 0.f; - float x150_damageDuration = 0.f; - float x154_interferenceDuration = 0.f; + EProjectileAttrib xe8_projectileAttribs; + TUniqueId xec_ownerId; + EWeaponType xf0_weaponType; + CMaterialFilter xf8_filter; + CDamageInfo x110_origDamageInfo; + CDamageInfo x12c_curDamageInfo; + float x148_curTime = 0.f; + float x14c_damageFalloffSpeed = 0.f; + float x150_damageDuration = 0.f; + float x154_interferenceDuration = 0.f; + public: - CWeapon(TUniqueId uid, TAreaId aid, bool active, TUniqueId owner, EWeaponType type, - std::string_view name, const zeus::CTransform& xf, const CMaterialFilter& filter, - const CMaterialList& mList, const CDamageInfo&, EProjectileAttrib attribs, CModelData&& mData); + CWeapon(TUniqueId uid, TAreaId aid, bool active, TUniqueId owner, EWeaponType type, std::string_view name, + const zeus::CTransform& xf, const CMaterialFilter& filter, const CMaterialList& mList, const CDamageInfo&, + EProjectileAttrib attribs, CModelData&& mData); - virtual void Accept(IVisitor &visitor); - bool HasAttrib(EProjectileAttrib attrib) const - { return (int(xe8_projectileAttribs) & int(attrib)) == int(attrib); } - EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; } - const CMaterialFilter& GetFilter() const { return xf8_filter; } - void SetFilter(const CMaterialFilter& filter) { xf8_filter = filter; } - TUniqueId GetOwnerId() const { return xec_ownerId; } - void SetOwnerId(TUniqueId oid) { xec_ownerId = oid; } - EWeaponType GetType() const { return xf0_weaponType; } - const CDamageInfo& GetDamageInfo() const { return x12c_curDamageInfo; } - CDamageInfo& DamageInfo() { return x12c_curDamageInfo; } - void SetDamageInfo(const CDamageInfo& dInfo) { x12c_curDamageInfo = dInfo; } - float GetDamageDuration() const { return x150_damageDuration; } - float GetInterferenceDuration() const { return x154_interferenceDuration; } + virtual void Accept(IVisitor& visitor); + bool HasAttrib(EProjectileAttrib attrib) const { return (int(xe8_projectileAttribs) & int(attrib)) == int(attrib); } + EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; } + const CMaterialFilter& GetFilter() const { return xf8_filter; } + void SetFilter(const CMaterialFilter& filter) { xf8_filter = filter; } + TUniqueId GetOwnerId() const { return xec_ownerId; } + void SetOwnerId(TUniqueId oid) { xec_ownerId = oid; } + EWeaponType GetType() const { return xf0_weaponType; } + const CDamageInfo& GetDamageInfo() const { return x12c_curDamageInfo; } + CDamageInfo& DamageInfo() { return x12c_curDamageInfo; } + void SetDamageInfo(const CDamageInfo& dInfo) { x12c_curDamageInfo = dInfo; } + float GetDamageDuration() const { return x150_damageDuration; } + float GetInterferenceDuration() const { return x154_interferenceDuration; } - void Think(float, CStateManager &); - void Render(const CStateManager&) const; - EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const; - void FluidFXThink(EFluidState state, CScriptWater& water, CStateManager& mgr); + void Think(float, CStateManager&); + void Render(const CStateManager&) const; + EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, + const CWeaponMode&, EProjectileAttrib) const; + void FluidFXThink(EFluidState state, CScriptWater& water, CStateManager& mgr); }; -} +} // namespace urde diff --git a/Runtime/Weapon/CWeaponMgr.cpp b/Runtime/Weapon/CWeaponMgr.cpp index a26ba9390..4ec1ca896 100644 --- a/Runtime/Weapon/CWeaponMgr.cpp +++ b/Runtime/Weapon/CWeaponMgr.cpp @@ -1,56 +1,49 @@ #include "CWeaponMgr.hpp" -namespace urde -{ +namespace urde { -void CWeaponMgr::Add(TUniqueId uid, EWeaponType type) -{ - x0_weapons.insert(std::make_pair(uid, rstl::reserved_vector())); - x0_weapons[uid].resize(10); - ++x0_weapons[uid][u32(type)]; +void CWeaponMgr::Add(TUniqueId uid, EWeaponType type) { + x0_weapons.insert(std::make_pair(uid, rstl::reserved_vector())); + x0_weapons[uid].resize(10); + ++x0_weapons[uid][u32(type)]; } -void CWeaponMgr::Remove(TUniqueId uid) -{ - s32 totalActive = 0; - for (u32 i = 0; i < 10; ++i) - totalActive += x0_weapons[uid][i]; +void CWeaponMgr::Remove(TUniqueId uid) { + s32 totalActive = 0; + for (u32 i = 0; i < 10; ++i) + totalActive += x0_weapons[uid][i]; - if (totalActive == 0) - x0_weapons.erase(uid); + if (totalActive == 0) + x0_weapons.erase(uid); } -void CWeaponMgr::IncrCount(TUniqueId uid, EWeaponType type) -{ - if (GetIndex(uid) < 0) - Add(uid, type); - else - x0_weapons[uid][u32(type)]++; +void CWeaponMgr::IncrCount(TUniqueId uid, EWeaponType type) { + if (GetIndex(uid) < 0) + Add(uid, type); + else + x0_weapons[uid][u32(type)]++; } -void CWeaponMgr::DecrCount(TUniqueId uid, EWeaponType type) -{ - if (GetIndex(uid) < 0) - return; +void CWeaponMgr::DecrCount(TUniqueId uid, EWeaponType type) { + if (GetIndex(uid) < 0) + return; - x0_weapons[uid][u32(type)]--; - if (x0_weapons[uid][u32(type)] <= 0) - Remove(uid); + x0_weapons[uid][u32(type)]--; + if (x0_weapons[uid][u32(type)] <= 0) + Remove(uid); } -s32 CWeaponMgr::GetNumActive(TUniqueId uid, EWeaponType type) const -{ - if (GetIndex(uid) < 0) - return 0; +s32 CWeaponMgr::GetNumActive(TUniqueId uid, EWeaponType type) const { + if (GetIndex(uid) < 0) + return 0; - return x0_weapons.at(uid)[u32(type)]; + return x0_weapons.at(uid)[u32(type)]; } -s32 CWeaponMgr::GetIndex(TUniqueId uid) const -{ - if (x0_weapons.find(uid) == x0_weapons.end()) - return -1; - return s32(std::distance(x0_weapons.begin(), x0_weapons.find(uid))); +s32 CWeaponMgr::GetIndex(TUniqueId uid) const { + if (x0_weapons.find(uid) == x0_weapons.end()) + return -1; + return s32(std::distance(x0_weapons.begin(), x0_weapons.find(uid))); } -} +} // namespace urde diff --git a/Runtime/Weapon/CWeaponMgr.hpp b/Runtime/Weapon/CWeaponMgr.hpp index c25984cb5..1c596a785 100644 --- a/Runtime/Weapon/CWeaponMgr.hpp +++ b/Runtime/Weapon/CWeaponMgr.hpp @@ -3,20 +3,18 @@ #include "RetroTypes.hpp" #include "WeaponCommon.hpp" -namespace urde -{ +namespace urde { + +class CWeaponMgr { + std::map> x0_weapons; -class CWeaponMgr -{ - std::map> x0_weapons; public: - void Add(TUniqueId, EWeaponType); - void Remove(TUniqueId); - void IncrCount(TUniqueId, EWeaponType); - void DecrCount(TUniqueId, EWeaponType); - s32 GetNumActive(TUniqueId, EWeaponType) const; - s32 GetIndex(TUniqueId) const; + void Add(TUniqueId, EWeaponType); + void Remove(TUniqueId); + void IncrCount(TUniqueId, EWeaponType); + void DecrCount(TUniqueId, EWeaponType); + s32 GetNumActive(TUniqueId, EWeaponType) const; + s32 GetIndex(TUniqueId) const; }; -} - +} // namespace urde diff --git a/Runtime/Weapon/CWeaponMode.hpp b/Runtime/Weapon/CWeaponMode.hpp index f6776cd70..cd6cf6513 100644 --- a/Runtime/Weapon/CWeaponMode.hpp +++ b/Runtime/Weapon/CWeaponMode.hpp @@ -2,33 +2,35 @@ #include "WeaponCommon.hpp" -namespace urde -{ -class CWeaponMode -{ - EWeaponType x0_weaponType = EWeaponType::None; - bool x4_24_charged : 1; - bool x4_25_comboed : 1; - bool x4_26_instantKill : 1; +namespace urde { +class CWeaponMode { + EWeaponType x0_weaponType = EWeaponType::None; + bool x4_24_charged : 1; + bool x4_25_comboed : 1; + bool x4_26_instantKill : 1; public: - CWeaponMode() { x4_24_charged = false; x4_25_comboed = false; x4_26_instantKill = false; } - CWeaponMode(EWeaponType type, bool charged = false, bool comboed = false, bool instaKill = false) - : x0_weaponType(type), x4_24_charged(charged), x4_25_comboed(comboed), x4_26_instantKill(instaKill) {} - EWeaponType GetType() const { return x0_weaponType; } + CWeaponMode() { + x4_24_charged = false; + x4_25_comboed = false; + x4_26_instantKill = false; + } + CWeaponMode(EWeaponType type, bool charged = false, bool comboed = false, bool instaKill = false) + : x0_weaponType(type), x4_24_charged(charged), x4_25_comboed(comboed), x4_26_instantKill(instaKill) {} + EWeaponType GetType() const { return x0_weaponType; } - bool IsCharged() const { return x4_24_charged; } - bool IsComboed() const { return x4_25_comboed; } - bool IsInstantKill() const { return x4_26_instantKill; } + bool IsCharged() const { return x4_24_charged; } + bool IsComboed() const { return x4_25_comboed; } + bool IsInstantKill() const { return x4_26_instantKill; } - static CWeaponMode Invalid() { return CWeaponMode(EWeaponType::None); } - static CWeaponMode Phazon() { return CWeaponMode(EWeaponType::Phazon); } - static CWeaponMode Plasma() { return CWeaponMode(EWeaponType::Plasma); } - static CWeaponMode Wave() { return CWeaponMode(EWeaponType::Wave); } - static CWeaponMode BoostBall() { return CWeaponMode(EWeaponType::BoostBall); } - static CWeaponMode Ice() { return CWeaponMode(EWeaponType::Ice); } - static CWeaponMode Power() { return CWeaponMode(EWeaponType::Power); } - static CWeaponMode Bomb() { return CWeaponMode(EWeaponType::Bomb); } - static CWeaponMode PowerBomb() { return CWeaponMode(EWeaponType::PowerBomb); } + static CWeaponMode Invalid() { return CWeaponMode(EWeaponType::None); } + static CWeaponMode Phazon() { return CWeaponMode(EWeaponType::Phazon); } + static CWeaponMode Plasma() { return CWeaponMode(EWeaponType::Plasma); } + static CWeaponMode Wave() { return CWeaponMode(EWeaponType::Wave); } + static CWeaponMode BoostBall() { return CWeaponMode(EWeaponType::BoostBall); } + static CWeaponMode Ice() { return CWeaponMode(EWeaponType::Ice); } + static CWeaponMode Power() { return CWeaponMode(EWeaponType::Power); } + static CWeaponMode Bomb() { return CWeaponMode(EWeaponType::Bomb); } + static CWeaponMode PowerBomb() { return CWeaponMode(EWeaponType::PowerBomb); } }; -} +} // namespace urde diff --git a/Runtime/Weapon/WeaponCommon.cpp b/Runtime/Weapon/WeaponCommon.cpp index 868e0010c..25441b4c3 100644 --- a/Runtime/Weapon/WeaponCommon.cpp +++ b/Runtime/Weapon/WeaponCommon.cpp @@ -6,181 +6,155 @@ #include "Audio/CSfxManager.hpp" #include "CStateManager.hpp" -namespace urde::NWeaponTypes -{ +namespace urde::NWeaponTypes { void primitive_set_to_token_vector(const CAnimData& animData, const std::set& primSet, - std::vector& tokensOut, bool preLock) -{ - int eventCount = 0; - for (const CPrimitive& prim : primSet) - if (animData.GetEventResourceIdForAnimResourceId(prim.GetAnimResId()).IsValid()) - ++eventCount; + std::vector& tokensOut, bool preLock) { + int eventCount = 0; + for (const CPrimitive& prim : primSet) + if (animData.GetEventResourceIdForAnimResourceId(prim.GetAnimResId()).IsValid()) + ++eventCount; - tokensOut.clear(); - tokensOut.reserve(primSet.size() + eventCount); + tokensOut.clear(); + tokensOut.reserve(primSet.size() + eventCount); - SObjectTag atag{FOURCC('ANIM'), 0}; - SObjectTag etag{FOURCC('EVNT'), 0}; - for (const CPrimitive& prim : primSet) - { - CAssetId eId = animData.GetEventResourceIdForAnimResourceId(prim.GetAnimResId()); - if (eId.IsValid()) - { - etag.id = prim.GetAnimResId(); - tokensOut.push_back(g_SimplePool->GetObj(etag)); - if (preLock) - tokensOut.back().Lock(); - } - atag.id = prim.GetAnimResId(); - tokensOut.push_back(g_SimplePool->GetObj(atag)); - if (preLock) - tokensOut.back().Lock(); + SObjectTag atag{FOURCC('ANIM'), 0}; + SObjectTag etag{FOURCC('EVNT'), 0}; + for (const CPrimitive& prim : primSet) { + CAssetId eId = animData.GetEventResourceIdForAnimResourceId(prim.GetAnimResId()); + if (eId.IsValid()) { + etag.id = prim.GetAnimResId(); + tokensOut.push_back(g_SimplePool->GetObj(etag)); + if (preLock) + tokensOut.back().Lock(); } + atag.id = prim.GetAnimResId(); + tokensOut.push_back(g_SimplePool->GetObj(atag)); + if (preLock) + tokensOut.back().Lock(); + } } -void unlock_tokens(std::vector& anims) -{ - for (CToken& tok : anims) - tok.Unlock(); +void unlock_tokens(std::vector& anims) { + for (CToken& tok : anims) + tok.Unlock(); } -void lock_tokens(std::vector& anims) -{ - for (CToken& tok : anims) - tok.Lock(); +void lock_tokens(std::vector& anims) { + for (CToken& tok : anims) + tok.Lock(); } -bool are_tokens_ready(const std::vector& anims) -{ - for (const CToken& tok : anims) - if (!tok.IsLoaded()) - return false; - return true; +bool are_tokens_ready(const std::vector& anims) { + for (const CToken& tok : anims) + if (!tok.IsLoaded()) + return false; + return true; } -void get_token_vector(const CAnimData& animData, int begin, int end, std::vector& tokensOut, bool preLock) -{ - std::set prims; - for (int i=begin ; i& tokensOut, bool preLock) -{ - std::set prims; - CAnimPlaybackParms parms(animIdx, -1, 1.f, true); +void get_token_vector(const CAnimData& animData, int begin, int end, std::vector& tokensOut, bool preLock) { + std::set prims; + for (int i = begin; i < end; ++i) { + CAnimPlaybackParms parms(i, -1, 1.f, true); animData.GetAnimationPrimitives(parms, prims); - primitive_set_to_token_vector(animData, prims, tokensOut, preLock); + } + primitive_set_to_token_vector(animData, prims, tokensOut, preLock); } -void do_sound_event(std::pair& sfxHandle, float& pitch, bool doPitchBend, u32 soundId, - float weight, u32 flags, float falloff, float maxDist, float minVol, float maxVol, - const zeus::CVector3f& posToCam, const zeus::CVector3f& pos, TAreaId aid, - CStateManager& mgr) -{ - if (posToCam.magSquared() >= maxDist * maxDist) - return; +void get_token_vector(const CAnimData& animData, int animIdx, std::vector& tokensOut, bool preLock) { + std::set prims; + CAnimPlaybackParms parms(animIdx, -1, 1.f, true); + animData.GetAnimationPrimitives(parms, prims); + primitive_set_to_token_vector(animData, prims, tokensOut, preLock); +} - u16 useSfxId = CSfxManager::TranslateSFXID(u16(soundId)); - u32 useFlags = 0x1; // Continuous parameter update - if ((flags & 0x8) != 0) - useFlags |= 0x8; // Doppler effect - bool useAcoustics = (flags & 0x80) == 0; +void do_sound_event(std::pair& sfxHandle, float& pitch, bool doPitchBend, u32 soundId, float weight, + u32 flags, float falloff, float maxDist, float minVol, float maxVol, + const zeus::CVector3f& posToCam, const zeus::CVector3f& pos, TAreaId aid, CStateManager& mgr) { + if (posToCam.magSquared() >= maxDist * maxDist) + return; - CAudioSys::C3DEmitterParmData parms; - parms.x0_pos = pos; - parms.xc_dir = zeus::CVector3f::skUp; - parms.x18_maxDist = maxDist; - parms.x1c_distComp = falloff; - parms.x20_flags = useFlags; - parms.x24_sfxId = useSfxId; - parms.x26_maxVol = maxVol; - parms.x27_minVol = minVol; - parms.x28_important = false; - parms.x29_prio = 0x7f; + u16 useSfxId = CSfxManager::TranslateSFXID(u16(soundId)); + u32 useFlags = 0x1; // Continuous parameter update + if ((flags & 0x8) != 0) + useFlags |= 0x8; // Doppler effect + bool useAcoustics = (flags & 0x80) == 0; - if (mgr.GetActiveRandom()->Float() <= weight) - { - if ((soundId & 0x80000000) != 0) - { - if (!sfxHandle.second) - { - CSfxHandle hnd; - if ((soundId & 0x40000000) != 0) - hnd = CSfxManager::SfxStart(useSfxId, 1.f, 0.f, true, 0x7f, true, aid); - else - hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); - if (hnd) - { - sfxHandle.first = useSfxId; - sfxHandle.second = hnd; - if (doPitchBend) - CSfxManager::PitchBend(hnd, pitch); - } - } - else - { - if (sfxHandle.first == useSfxId) - { - CSfxManager::UpdateEmitter(sfxHandle.second, parms.x0_pos, parms.xc_dir, parms.x26_maxVol); - } - else if ((flags & 0x4) != 0) // Pausable - { - CSfxManager::RemoveEmitter(sfxHandle.second); - CSfxHandle hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); - if (hnd) - { - sfxHandle.first = useSfxId; - sfxHandle.second = hnd; - if (doPitchBend) - CSfxManager::PitchBend(hnd, pitch); - } - } - } - } + CAudioSys::C3DEmitterParmData parms; + parms.x0_pos = pos; + parms.xc_dir = zeus::CVector3f::skUp; + parms.x18_maxDist = maxDist; + parms.x1c_distComp = falloff; + parms.x20_flags = useFlags; + parms.x24_sfxId = useSfxId; + parms.x26_maxVol = maxVol; + parms.x27_minVol = minVol; + parms.x28_important = false; + parms.x29_prio = 0x7f; + + if (mgr.GetActiveRandom()->Float() <= weight) { + if ((soundId & 0x80000000) != 0) { + if (!sfxHandle.second) { + CSfxHandle hnd; + if ((soundId & 0x40000000) != 0) + hnd = CSfxManager::SfxStart(useSfxId, 1.f, 0.f, true, 0x7f, true, aid); else - { - CSfxHandle hnd; - if ((soundId & 0x40000000) != 0) - hnd = CSfxManager::SfxStart(useSfxId, 1.f, 0.f, true, 0x7f, false, aid); - else - hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, false, aid); - if (doPitchBend) - CSfxManager::PitchBend(hnd, pitch); + hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); + if (hnd) { + sfxHandle.first = useSfxId; + sfxHandle.second = hnd; + if (doPitchBend) + CSfxManager::PitchBend(hnd, pitch); } + } else { + if (sfxHandle.first == useSfxId) { + CSfxManager::UpdateEmitter(sfxHandle.second, parms.x0_pos, parms.xc_dir, parms.x26_maxVol); + } else if ((flags & 0x4) != 0) // Pausable + { + CSfxManager::RemoveEmitter(sfxHandle.second); + CSfxHandle hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); + if (hnd) { + sfxHandle.first = useSfxId; + sfxHandle.second = hnd; + if (doPitchBend) + CSfxManager::PitchBend(hnd, pitch); + } + } + } + } else { + CSfxHandle hnd; + if ((soundId & 0x40000000) != 0) + hnd = CSfxManager::SfxStart(useSfxId, 1.f, 0.f, true, 0x7f, false, aid); + else + hnd = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, false, aid); + if (doPitchBend) + CSfxManager::PitchBend(hnd, pitch); } + } } -CAssetId get_asset_id_from_name(const char* name) -{ - const SObjectTag* tag = g_ResFactory->GetResourceIdByName(name); - if (!tag) - return {}; - return tag->id; +CAssetId get_asset_id_from_name(const char* name) { + const SObjectTag* tag = g_ResFactory->GetResourceIdByName(name); + if (!tag) + return {}; + return tag->id; } -CPlayerState::EPlayerSuit get_current_suit(const CStateManager& mgr) -{ - CPlayerState::EPlayerSuit suit = mgr.GetPlayerState()->GetCurrentSuit(); - if (suit < CPlayerState::EPlayerSuit::Power || suit > CPlayerState::EPlayerSuit::FusionGravity) - suit = CPlayerState::EPlayerSuit::Power; - if (suit == CPlayerState::EPlayerSuit::FusionPower) - suit = CPlayerState::EPlayerSuit(int(suit) + int(mgr.GetPlayerState()->GetCurrentSuitRaw())); - return suit; +CPlayerState::EPlayerSuit get_current_suit(const CStateManager& mgr) { + CPlayerState::EPlayerSuit suit = mgr.GetPlayerState()->GetCurrentSuit(); + if (suit < CPlayerState::EPlayerSuit::Power || suit > CPlayerState::EPlayerSuit::FusionGravity) + suit = CPlayerState::EPlayerSuit::Power; + if (suit == CPlayerState::EPlayerSuit::FusionPower) + suit = CPlayerState::EPlayerSuit(int(suit) + int(mgr.GetPlayerState()->GetCurrentSuitRaw())); + return suit; } -CSfxHandle play_sfx(u16 sfx, bool underwater, bool looped, float pan) -{ - CSfxHandle hnd = CSfxManager::SfxStart(sfx, 1.f, pan, true, 0x7f, looped, kInvalidAreaId); - CSfxManager::SfxSpan(hnd, 0.f); - if (underwater) - CSfxManager::PitchBend(hnd, -1.f); - return hnd; +CSfxHandle play_sfx(u16 sfx, bool underwater, bool looped, float pan) { + CSfxHandle hnd = CSfxManager::SfxStart(sfx, 1.f, pan, true, 0x7f, looped, kInvalidAreaId); + CSfxManager::SfxSpan(hnd, 0.f); + if (underwater) + CSfxManager::PitchBend(hnd, -1.f); + return hnd; } -} +} // namespace urde::NWeaponTypes diff --git a/Runtime/Weapon/WeaponCommon.hpp b/Runtime/Weapon/WeaponCommon.hpp index a6e4bff5d..12166c38e 100644 --- a/Runtime/Weapon/WeaponCommon.hpp +++ b/Runtime/Weapon/WeaponCommon.hpp @@ -6,73 +6,68 @@ #include #include -namespace urde -{ +namespace urde { class CAnimData; class CToken; class CPrimitive; class CStateManager; -enum class EWeaponType -{ - None = -1, - Power = 0, - Ice = 1, - Wave = 2, - Plasma = 3, - Bomb = 4, - PowerBomb = 5, - Missile = 6, - BoostBall = 7, - Phazon = 8, - AI = 9, - PoisonWater = 10, - Lava = 11, - Heat = 12, - Unused1 = 13, - OrangePhazon = 14 +enum class EWeaponType { + None = -1, + Power = 0, + Ice = 1, + Wave = 2, + Plasma = 3, + Bomb = 4, + PowerBomb = 5, + Missile = 6, + BoostBall = 7, + Phazon = 8, + AI = 9, + PoisonWater = 10, + Lava = 11, + Heat = 12, + Unused1 = 13, + OrangePhazon = 14 }; -enum class EProjectileAttrib -{ - None = 0, - PartialCharge = (1 << 0), - PlasmaProjectile = (1 << 1), - Charged = (1 << 2), - Ice = (1 << 3), - Wave = (1 << 4), - Plasma = (1 << 5), - Phazon = (1 << 6), - ComboShot = (1 << 7), - Bombs = (1 << 8), - PowerBombs = (1 << 9), - BigProjectile = (1 << 10), - ArmCannon = (1 << 11), - BigStrike = (1 << 12), - DamageFalloff = (1 << 13), - StaticInterference = (1 << 14), - PlayerUnFreeze = (1 << 15), - ParticleOPTS = (1 << 16), - KeepInCinematic = (1 << 17), +enum class EProjectileAttrib { + None = 0, + PartialCharge = (1 << 0), + PlasmaProjectile = (1 << 1), + Charged = (1 << 2), + Ice = (1 << 3), + Wave = (1 << 4), + Plasma = (1 << 5), + Phazon = (1 << 6), + ComboShot = (1 << 7), + Bombs = (1 << 8), + PowerBombs = (1 << 9), + BigProjectile = (1 << 10), + ArmCannon = (1 << 11), + BigStrike = (1 << 12), + DamageFalloff = (1 << 13), + StaticInterference = (1 << 14), + PlayerUnFreeze = (1 << 15), + ParticleOPTS = (1 << 16), + KeepInCinematic = (1 << 17), }; ENABLE_BITWISE_ENUM(EProjectileAttrib) -namespace NWeaponTypes -{ +namespace NWeaponTypes { -enum class EGunAnimType -{ - BasePosition, - Shoot, - ChargeUp, - ChargeLoop, - ChargeShoot, - FromMissile, - ToMissile, - MissileShoot, - MissileReload, - FromBeam, - ToBeam +enum class EGunAnimType { + BasePosition, + Shoot, + ChargeUp, + ChargeLoop, + ChargeShoot, + FromMissile, + ToMissile, + MissileShoot, + MissileReload, + FromBeam, + ToBeam }; void primitive_set_to_token_vector(const CAnimData& animData, const std::set& primSet, @@ -82,14 +77,13 @@ void lock_tokens(std::vector& anims); bool are_tokens_ready(const std::vector& anims); void get_token_vector(const CAnimData& animData, int begin, int end, std::vector& tokensOut, bool preLock); void get_token_vector(const CAnimData& animData, int animIdx, std::vector& tokensOut, bool preLock); -void do_sound_event(std::pair& sfxHandle, float& pitch, bool doPitchBend, u32 soundId, - float weight, u32 flags, float falloff, float maxDist, float minVol, float maxVol, - const zeus::CVector3f& posToCam, const zeus::CVector3f& pos, TAreaId aid, - CStateManager& mgr); +void do_sound_event(std::pair& sfxHandle, float& pitch, bool doPitchBend, u32 soundId, float weight, + u32 flags, float falloff, float maxDist, float minVol, float maxVol, + const zeus::CVector3f& posToCam, const zeus::CVector3f& pos, TAreaId aid, CStateManager& mgr); CAssetId get_asset_id_from_name(const char* name); CPlayerState::EPlayerSuit get_current_suit(const CStateManager& mgr); CSfxHandle play_sfx(u16 sfx, bool underwater, bool looped, float pan); -} +} // namespace NWeaponTypes -} +} // namespace urde diff --git a/Runtime/World/CActor.cpp b/Runtime/World/CActor.cpp index 28438fac4..0fbe1fb55 100644 --- a/Runtime/World/CActor.cpp +++ b/Runtime/World/CActor.cpp @@ -14,16 +14,14 @@ #include "CTimeProvider.hpp" #include "Graphics/CSkinnedModel.hpp" -namespace urde -{ -static CMaterialList MakeActorMaterialList(const CMaterialList& materialList, const CActorParameters& params) -{ - CMaterialList ret = materialList; - if (params.GetVisorParameters().x0_4_b1) - ret.Add(EMaterialTypes::Unknown46); - if (params.GetVisorParameters().x0_5_scanPassthrough) - ret.Add(EMaterialTypes::ScanPassthrough); - return ret; +namespace urde { +static CMaterialList MakeActorMaterialList(const CMaterialList& materialList, const CActorParameters& params) { + CMaterialList ret = materialList; + if (params.GetVisorParameters().x0_4_b1) + ret.Add(EMaterialTypes::Unknown46); + if (params.GetVisorParameters().x0_5_scanPassthrough) + ret.Add(EMaterialTypes::ScanPassthrough); + return ret; } CActor::CActor(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, @@ -32,324 +30,275 @@ CActor::CActor(TUniqueId uid, bool active, std::string_view name, const CEntityI , x34_transform(xf) , x68_material(MakeActorMaterialList(list, params)) , x70_materialFilter(CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull})) -, xc6_nextDrawNode(otherUid) -{ - x90_actorLights = mData.IsNull() ? std::unique_ptr() : params.x0_lightParms.MakeActorLights(); - if (mData.x10_animData || mData.x1c_normalModel) - x64_modelData = std::make_unique(std::move(mData)); - xd0_damageMag = params.x64_thermalMag; - xd8_nonLoopingSfxHandles.resize(2); - xe4_27_notInSortedLists = true; - xe4_28_transformDirty = true; - xe4_29_actorLightsDirty = true; - xe4_31_calculateLighting = true; - xe5_27_useInSortedLists = true; - xe5_28_callTouch = true; - xe5_29_globalTimeProvider = params.x58_24_globalTimeProvider; - xe5_30_renderUnsorted = params.x58_26_renderUnsorted; - xe6_27_thermalVisorFlags = u8(params.x58_25_thermalHeat ? 2 : 1); - xe6_29_renderParticleDBInside = true; - xe6_31_targetableVisorFlags = params.GetVisorParameters().GetMask(); - xe7_27_enableRender = true; - xe7_29_drawEnabled = active; - xe7_30_doTargetDistanceTest = true; - xe7_31_targetable = true; - if (x64_modelData) - { - if (params.x44_xrayAssets.first.IsValid()) - x64_modelData->SetXRayModel(params.x44_xrayAssets); - if (params.x4c_thermalAssets.first.IsValid()) - x64_modelData->SetInfraModel(params.x4c_thermalAssets); - if (!params.x0_lightParms.x1c_makeLights || params.x0_lightParms.x3c_maxAreaLights == 0) - x64_modelData->x18_ambientColor = params.x0_lightParms.x18_noLightsAmbient; - x64_modelData->x14_25_sortThermal = !params.x58_27_noSortThermal; - } +, xc6_nextDrawNode(otherUid) { + x90_actorLights = mData.IsNull() ? std::unique_ptr() : params.x0_lightParms.MakeActorLights(); + if (mData.x10_animData || mData.x1c_normalModel) + x64_modelData = std::make_unique(std::move(mData)); + xd0_damageMag = params.x64_thermalMag; + xd8_nonLoopingSfxHandles.resize(2); + xe4_27_notInSortedLists = true; + xe4_28_transformDirty = true; + xe4_29_actorLightsDirty = true; + xe4_31_calculateLighting = true; + xe5_27_useInSortedLists = true; + xe5_28_callTouch = true; + xe5_29_globalTimeProvider = params.x58_24_globalTimeProvider; + xe5_30_renderUnsorted = params.x58_26_renderUnsorted; + xe6_27_thermalVisorFlags = u8(params.x58_25_thermalHeat ? 2 : 1); + xe6_29_renderParticleDBInside = true; + xe6_31_targetableVisorFlags = params.GetVisorParameters().GetMask(); + xe7_27_enableRender = true; + xe7_29_drawEnabled = active; + xe7_30_doTargetDistanceTest = true; + xe7_31_targetable = true; + if (x64_modelData) { + if (params.x44_xrayAssets.first.IsValid()) + x64_modelData->SetXRayModel(params.x44_xrayAssets); + if (params.x4c_thermalAssets.first.IsValid()) + x64_modelData->SetInfraModel(params.x4c_thermalAssets); + if (!params.x0_lightParms.x1c_makeLights || params.x0_lightParms.x3c_maxAreaLights == 0) + x64_modelData->x18_ambientColor = params.x0_lightParms.x18_noLightsAmbient; + x64_modelData->x14_25_sortThermal = !params.x58_27_noSortThermal; + } - if (params.x40_scanParms.GetScanId().IsValid()) - x98_scanObjectInfo = g_SimplePool->GetObj(SObjectTag{FOURCC('SCAN'), params.x40_scanParms.GetScanId()}); + if (params.x40_scanParms.GetScanId().IsValid()) + x98_scanObjectInfo = g_SimplePool->GetObj(SObjectTag{FOURCC('SCAN'), params.x40_scanParms.GetScanId()}); } -void CActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Activate: - { - if (!x30_24_active) - xbc_time = CGraphics::GetSecondsMod900(); - break; - } - case EScriptObjectMessage::Deactivate: - RemoveEmitter(); - break; - case EScriptObjectMessage::Deleted: // 34 - { - RemoveEmitter(); - if (HasModelData() && x64_modelData->AnimationData() && x64_modelData->GetNormalModel()) - x64_modelData->AnimationData()->GetParticleDB().DeleteAllLights(mgr); - break; - } - case EScriptObjectMessage::Registered: // 33 - { - if (x98_scanObjectInfo) - AddMaterial(EMaterialTypes::Scannable, mgr); - else - RemoveMaterial(EMaterialTypes::Scannable, mgr); - - if (HasModelData() && x64_modelData->AnimationData()) - { - TAreaId aid = GetAreaId(); - x64_modelData->AnimationData()->InitializeEffects(mgr, aid, x64_modelData->GetScale()); - } - break; - } - case EScriptObjectMessage::UpdateSplashInhabitant: // 37 - SetInFluid(true, uid); - break; - case EScriptObjectMessage::RemoveSplashInhabitant: // 39 - SetInFluid(false, kInvalidUniqueId); - break; - case EScriptObjectMessage::InitializedInArea: // 35 - { - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Default) - continue; - - const CActor* act = TCastToConstPtr(mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))); - if (act && xc6_nextDrawNode == kInvalidUniqueId) - xc6_nextDrawNode = act->GetUniqueId(); - } - break; - } - default: - break; - } - CEntity::AcceptScriptMsg(msg, uid, mgr); -} - -void CActor::PreRender(CStateManager& mgr, const zeus::CFrustum& planes) -{ - if (!x64_modelData || x64_modelData->IsNull()) - return; - - xe4_30_outOfFrustum = !planes.aabbFrustumTest(x9c_renderBounds); - if (!xe4_30_outOfFrustum) - { - xe7_28_worldLightingDirty = true; - - bool lightsDirty = false; - if (xe4_29_actorLightsDirty) - { - xe4_29_actorLightsDirty = false; - lightsDirty = true; - xe5_25_shadowDirty = true; - } - else if (xe7_28_worldLightingDirty) - { - lightsDirty = true; - } - else if (x90_actorLights && x90_actorLights->GetIsDirty()) - { - lightsDirty = true; - } - - if (xe5_25_shadowDirty && xe5_24_shadowEnabled && x94_simpleShadow) - { - x94_simpleShadow->Calculate(x64_modelData->GetBounds(), x34_transform, mgr); - xe5_25_shadowDirty = false; - } - - if (xe4_31_calculateLighting && x90_actorLights) - { - zeus::CAABox bounds = x64_modelData->GetBounds(x34_transform); - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) - { - x90_actorLights->BuildConstantAmbientLighting(); - } - else - { - if (lightsDirty && x4_areaId != kInvalidAreaId) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); - if (area->IsPostConstructed()) - if (x90_actorLights->BuildAreaLightList(mgr, *area, bounds)) - xe7_28_worldLightingDirty = false; - } - x90_actorLights->BuildDynamicLightList(mgr, bounds); - } - } - - if (x64_modelData->HasAnimData()) - x64_modelData->AnimationData()->PreRender(); - } +void CActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Activate: { + if (!x30_24_active) + xbc_time = CGraphics::GetSecondsMod900(); + break; + } + case EScriptObjectMessage::Deactivate: + RemoveEmitter(); + break; + case EScriptObjectMessage::Deleted: // 34 + { + RemoveEmitter(); + if (HasModelData() && x64_modelData->AnimationData() && x64_modelData->GetNormalModel()) + x64_modelData->AnimationData()->GetParticleDB().DeleteAllLights(mgr); + break; + } + case EScriptObjectMessage::Registered: // 33 + { + if (x98_scanObjectInfo) + AddMaterial(EMaterialTypes::Scannable, mgr); else - { - if (xe4_29_actorLightsDirty) - { - xe4_29_actorLightsDirty = false; - xe5_25_shadowDirty = true; - } + RemoveMaterial(EMaterialTypes::Scannable, mgr); - if (xe5_25_shadowDirty && xe5_24_shadowEnabled && x94_simpleShadow) - { - zeus::CAABox bounds = x64_modelData->GetBounds(x34_transform); - if (planes.aabbFrustumTest(x94_simpleShadow->GetMaxShadowBox(bounds))) - { - x94_simpleShadow->Calculate(x64_modelData->GetBounds(), x34_transform, mgr); - xe5_25_shadowDirty = false; - } - } + if (HasModelData() && x64_modelData->AnimationData()) { + TAreaId aid = GetAreaId(); + x64_modelData->AnimationData()->InitializeEffects(mgr, aid, x64_modelData->GetScale()); } + break; + } + case EScriptObjectMessage::UpdateSplashInhabitant: // 37 + SetInFluid(true, uid); + break; + case EScriptObjectMessage::RemoveSplashInhabitant: // 39 + SetInFluid(false, kInvalidUniqueId); + break; + case EScriptObjectMessage::InitializedInArea: // 35 + { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Default) + continue; + + const CActor* act = TCastToConstPtr(mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))); + if (act && xc6_nextDrawNode == kInvalidUniqueId) + xc6_nextDrawNode = act->GetUniqueId(); + } + break; + } + default: + break; + } + CEntity::AcceptScriptMsg(msg, uid, mgr); } -void CActor::AddToRenderer(const zeus::CFrustum& planes, const CStateManager& mgr) const -{ - if (!x64_modelData || x64_modelData->IsNull()) - return; +void CActor::PreRender(CStateManager& mgr, const zeus::CFrustum& planes) { + if (!x64_modelData || x64_modelData->IsNull()) + return; - if (xe6_29_renderParticleDBInside) - x64_modelData->RenderParticles(planes); + xe4_30_outOfFrustum = !planes.aabbFrustumTest(x9c_renderBounds); + if (!xe4_30_outOfFrustum) { + xe7_28_worldLightingDirty = true; - if (!xe4_30_outOfFrustum) - { - if (CanRenderUnsorted(mgr)) - Render(mgr); - else - EnsureRendered(mgr); + bool lightsDirty = false; + if (xe4_29_actorLightsDirty) { + xe4_29_actorLightsDirty = false; + lightsDirty = true; + xe5_25_shadowDirty = true; + } else if (xe7_28_worldLightingDirty) { + lightsDirty = true; + } else if (x90_actorLights && x90_actorLights->GetIsDirty()) { + lightsDirty = true; } - if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay && - mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal && - xe5_24_shadowEnabled && x94_simpleShadow->Valid() && - planes.aabbFrustumTest(x94_simpleShadow->GetBounds())) - g_Renderer->AddDrawable(x94_simpleShadow.get(), x94_simpleShadow->GetTransform().origin, - x94_simpleShadow->GetBounds(), 1, CBooRenderer::EDrawableSorting::SortedCallback); -} - -void CActor::DrawTouchBounds() const -{ - // Empty -} - -void CActor::RenderInternal(const CStateManager& mgr) const -{ - CModelData::EWhichModel which = CModelData::GetRenderingModel(mgr); - if (which == CModelData::EWhichModel::ThermalHot) - { - if (x64_modelData->GetSortThermal()) - { - float addMag; - float mulMag = 1.f; - if (xd0_damageMag <= 1.f) - { - mulMag = xd0_damageMag; - addMag = 0.f; - } - else if (xd0_damageMag < 2.f) - { - addMag = xd0_damageMag - 1.f; - } - else - { - addMag = 1.f; - } - - zeus::CColor mulColor(mulMag * xb4_drawFlags.x4_color.a(), xb4_drawFlags.x4_color.a()); - zeus::CColor addColor(addMag, xb4_drawFlags.x4_color.a() / 4.f); - x64_modelData->RenderThermal(x34_transform, mulColor, addColor, xb4_drawFlags); - return; - } - else if (mgr.GetThermalColdScale2() > 0.00001f && !xb4_drawFlags.x0_blendMode) - { - zeus::CColor color(zeus::clamp(0.f, - std::min((mgr.GetThermalColdScale2() + mgr.GetThermalColdScale1()) * mgr.GetThermalColdScale2(), - mgr.GetThermalColdScale2()), 1.f), 1.f); - CModelFlags flags(2, xb4_drawFlags.x1_matSetIdx, xb4_drawFlags.x2_flags, color); - x64_modelData->Render(mgr, x34_transform, x90_actorLights.get(), flags); - return; - } + if (xe5_25_shadowDirty && xe5_24_shadowEnabled && x94_simpleShadow) { + x94_simpleShadow->Calculate(x64_modelData->GetBounds(), x34_transform, mgr); + xe5_25_shadowDirty = false; } - x64_modelData->Render(which, x34_transform, x90_actorLights.get(), xb4_drawFlags); -} -bool CActor::IsModelOpaque(const CStateManager& mgr) const -{ - if (xe5_31_pointGeneratorParticles) - return false; - if (!x64_modelData || x64_modelData->IsNull()) - return true; - if (xb4_drawFlags.x0_blendMode > 4) - return false; - return x64_modelData->IsDefinitelyOpaque(CModelData::GetRenderingModel(mgr)); -} - -void CActor::Render(const CStateManager& mgr) const -{ - if (x64_modelData && !x64_modelData->IsNull()) - { - bool renderPrePostParticles = xe6_29_renderParticleDBInside && x64_modelData && x64_modelData->HasAnimData(); - if (renderPrePostParticles) - x64_modelData->AnimationData()->GetParticleDB().RenderSystemsToBeDrawnFirst(); - - if (xe7_27_enableRender) - { - if (xe5_31_pointGeneratorParticles) - mgr.SetupParticleHook(*this); - if (xe5_29_globalTimeProvider) - { - RenderInternal(mgr); - } - else - { - float timeSince = CGraphics::GetSecondsMod900() - xbc_time; - float tpTime = timeSince - std::floor(timeSince / 900.f) * 900.f; - CTimeProvider tp(tpTime); - RenderInternal(mgr); - } - if (xe5_31_pointGeneratorParticles) - { - CSkinnedModel::ClearPointGeneratorFunc(); - mgr.GetActorModelParticles()->Render(*this); - } + if (xe4_31_calculateLighting && x90_actorLights) { + zeus::CAABox bounds = x64_modelData->GetBounds(x34_transform); + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) { + x90_actorLights->BuildConstantAmbientLighting(); + } else { + if (lightsDirty && x4_areaId != kInvalidAreaId) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); + if (area->IsPostConstructed()) + if (x90_actorLights->BuildAreaLightList(mgr, *area, bounds)) + xe7_28_worldLightingDirty = false; } - - if (renderPrePostParticles) - x64_modelData->AnimationData()->GetParticleDB().RenderSystemsToBeDrawnLast(); + x90_actorLights->BuildDynamicLightList(mgr, bounds); + } } - DrawTouchBounds(); + + if (x64_modelData->HasAnimData()) + x64_modelData->AnimationData()->PreRender(); + } else { + if (xe4_29_actorLightsDirty) { + xe4_29_actorLightsDirty = false; + xe5_25_shadowDirty = true; + } + + if (xe5_25_shadowDirty && xe5_24_shadowEnabled && x94_simpleShadow) { + zeus::CAABox bounds = x64_modelData->GetBounds(x34_transform); + if (planes.aabbFrustumTest(x94_simpleShadow->GetMaxShadowBox(bounds))) { + x94_simpleShadow->Calculate(x64_modelData->GetBounds(), x34_transform, mgr); + xe5_25_shadowDirty = false; + } + } + } } -bool CActor::CanRenderUnsorted(const CStateManager& mgr) const -{ - if (x64_modelData && x64_modelData->HasAnimData() && - x64_modelData->GetAnimationData()->GetParticleDB().AreAnySystemsDrawnWithModel() && - xe6_29_renderParticleDBInside) - return false; - else if (xe5_30_renderUnsorted || IsModelOpaque(mgr)) - return true; +void CActor::AddToRenderer(const zeus::CFrustum& planes, const CStateManager& mgr) const { + if (!x64_modelData || x64_modelData->IsNull()) + return; + + if (xe6_29_renderParticleDBInside) + x64_modelData->RenderParticles(planes); + + if (!xe4_30_outOfFrustum) { + if (CanRenderUnsorted(mgr)) + Render(mgr); + else + EnsureRendered(mgr); + } + + if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay && + mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal && xe5_24_shadowEnabled && + x94_simpleShadow->Valid() && planes.aabbFrustumTest(x94_simpleShadow->GetBounds())) + g_Renderer->AddDrawable(x94_simpleShadow.get(), x94_simpleShadow->GetTransform().origin, + x94_simpleShadow->GetBounds(), 1, CBooRenderer::EDrawableSorting::SortedCallback); +} + +void CActor::DrawTouchBounds() const { + // Empty +} + +void CActor::RenderInternal(const CStateManager& mgr) const { + CModelData::EWhichModel which = CModelData::GetRenderingModel(mgr); + if (which == CModelData::EWhichModel::ThermalHot) { + if (x64_modelData->GetSortThermal()) { + float addMag; + float mulMag = 1.f; + if (xd0_damageMag <= 1.f) { + mulMag = xd0_damageMag; + addMag = 0.f; + } else if (xd0_damageMag < 2.f) { + addMag = xd0_damageMag - 1.f; + } else { + addMag = 1.f; + } + + zeus::CColor mulColor(mulMag * xb4_drawFlags.x4_color.a(), xb4_drawFlags.x4_color.a()); + zeus::CColor addColor(addMag, xb4_drawFlags.x4_color.a() / 4.f); + x64_modelData->RenderThermal(x34_transform, mulColor, addColor, xb4_drawFlags); + return; + } else if (mgr.GetThermalColdScale2() > 0.00001f && !xb4_drawFlags.x0_blendMode) { + zeus::CColor color( + zeus::clamp(0.f, + std::min((mgr.GetThermalColdScale2() + mgr.GetThermalColdScale1()) * mgr.GetThermalColdScale2(), + mgr.GetThermalColdScale2()), + 1.f), + 1.f); + CModelFlags flags(2, xb4_drawFlags.x1_matSetIdx, xb4_drawFlags.x2_flags, color); + x64_modelData->Render(mgr, x34_transform, x90_actorLights.get(), flags); + return; + } + } + x64_modelData->Render(which, x34_transform, x90_actorLights.get(), xb4_drawFlags); +} + +bool CActor::IsModelOpaque(const CStateManager& mgr) const { + if (xe5_31_pointGeneratorParticles) return false; + if (!x64_modelData || x64_modelData->IsNull()) + return true; + if (xb4_drawFlags.x0_blendMode > 4) + return false; + return x64_modelData->IsDefinitelyOpaque(CModelData::GetRenderingModel(mgr)); } -void CActor::CalculateRenderBounds() -{ - if (x64_modelData && (x64_modelData->AnimationData() || x64_modelData->GetNormalModel())) - x9c_renderBounds = x64_modelData->GetBounds(x34_transform); - else - x9c_renderBounds = zeus::CAABox(x34_transform.origin, x34_transform.origin); +void CActor::Render(const CStateManager& mgr) const { + if (x64_modelData && !x64_modelData->IsNull()) { + bool renderPrePostParticles = xe6_29_renderParticleDBInside && x64_modelData && x64_modelData->HasAnimData(); + if (renderPrePostParticles) + x64_modelData->AnimationData()->GetParticleDB().RenderSystemsToBeDrawnFirst(); + + if (xe7_27_enableRender) { + if (xe5_31_pointGeneratorParticles) + mgr.SetupParticleHook(*this); + if (xe5_29_globalTimeProvider) { + RenderInternal(mgr); + } else { + float timeSince = CGraphics::GetSecondsMod900() - xbc_time; + float tpTime = timeSince - std::floor(timeSince / 900.f) * 900.f; + CTimeProvider tp(tpTime); + RenderInternal(mgr); + } + if (xe5_31_pointGeneratorParticles) { + CSkinnedModel::ClearPointGeneratorFunc(); + mgr.GetActorModelParticles()->Render(*this); + } + } + + if (renderPrePostParticles) + x64_modelData->AnimationData()->GetParticleDB().RenderSystemsToBeDrawnLast(); + } + DrawTouchBounds(); +} + +bool CActor::CanRenderUnsorted(const CStateManager& mgr) const { + if (x64_modelData && x64_modelData->HasAnimData() && + x64_modelData->GetAnimationData()->GetParticleDB().AreAnySystemsDrawnWithModel() && xe6_29_renderParticleDBInside) + return false; + else if (xe5_30_renderUnsorted || IsModelOpaque(mgr)) + return true; + return false; +} + +void CActor::CalculateRenderBounds() { + if (x64_modelData && (x64_modelData->AnimationData() || x64_modelData->GetNormalModel())) + x9c_renderBounds = x64_modelData->GetBounds(x34_transform); + else + x9c_renderBounds = zeus::CAABox(x34_transform.origin, x34_transform.origin); } CHealthInfo* CActor::HealthInfo(CStateManager&) { return nullptr; } -const CDamageVulnerability* CActor::GetDamageVulnerability() const -{ - return &CDamageVulnerability::NormalVulnerabilty(); +const CDamageVulnerability* CActor::GetDamageVulnerability() const { + return &CDamageVulnerability::NormalVulnerabilty(); } const CDamageVulnerability* CActor::GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, - const CDamageInfo&) const -{ - return GetDamageVulnerability(); + const CDamageInfo&) const { + return GetDamageVulnerability(); } std::experimental::optional CActor::GetTouchBounds() const { return {}; } @@ -362,146 +311,123 @@ zeus::CVector3f CActor::GetAimPosition(const CStateManager&, float) const { retu zeus::CVector3f CActor::GetHomingPosition(const CStateManager& mgr, float f) const { return GetAimPosition(mgr, f); } -zeus::CVector3f CActor::GetScanObjectIndicatorPosition(const CStateManager& mgr) const -{ - const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - zeus::CVector3f orbitPos = GetOrbitPosition(mgr); - float camToOrbitPos = (cam->GetTranslation() - orbitPos).magnitude(); - const zeus::CVector3f boundsExtent = x9c_renderBounds.max - x9c_renderBounds.min; - float distFac = std::min(std::max(boundsExtent.x(), std::max(boundsExtent.y(), boundsExtent.z())) * 0.5f, - camToOrbitPos - cam->GetNearClipDistance() - 0.1f); - return orbitPos - (orbitPos - cam->GetTranslation()).normalized() * distFac; +zeus::CVector3f CActor::GetScanObjectIndicatorPosition(const CStateManager& mgr) const { + const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + zeus::CVector3f orbitPos = GetOrbitPosition(mgr); + float camToOrbitPos = (cam->GetTranslation() - orbitPos).magnitude(); + const zeus::CVector3f boundsExtent = x9c_renderBounds.max - x9c_renderBounds.min; + float distFac = std::min(std::max(boundsExtent.x(), std::max(boundsExtent.y(), boundsExtent.z())) * 0.5f, + camToOrbitPos - cam->GetNearClipDistance() - 0.1f); + return orbitPos - (orbitPos - cam->GetTranslation()).normalized() * distFac; } -void CActor::RemoveEmitter() -{ - if (x8c_loopingSfxHandle) - { - CSfxManager::RemoveEmitter(x8c_loopingSfxHandle); - x88_sfxId = -1; - x8c_loopingSfxHandle.reset(); - } +void CActor::RemoveEmitter() { + if (x8c_loopingSfxHandle) { + CSfxManager::RemoveEmitter(x8c_loopingSfxHandle); + x88_sfxId = -1; + x8c_loopingSfxHandle.reset(); + } } -void CActor::SetVolume(float vol) -{ - if (x8c_loopingSfxHandle) - CSfxManager::UpdateEmitter(x8c_loopingSfxHandle, GetTranslation(), zeus::CVector3f::skZero, vol); - xd4_maxVol = vol; +void CActor::SetVolume(float vol) { + if (x8c_loopingSfxHandle) + CSfxManager::UpdateEmitter(x8c_loopingSfxHandle, GetTranslation(), zeus::CVector3f::skZero, vol); + xd4_maxVol = vol; } -const zeus::CTransform CActor::GetScaledLocatorTransform(std::string_view segName) const -{ - return x64_modelData->GetScaledLocatorTransform(segName); +const zeus::CTransform CActor::GetScaledLocatorTransform(std::string_view segName) const { + return x64_modelData->GetScaledLocatorTransform(segName); } -const zeus::CTransform CActor::GetLocatorTransform(std::string_view segName) const -{ - return x64_modelData->GetLocatorTransform(segName); +const zeus::CTransform CActor::GetLocatorTransform(std::string_view segName) const { + return x64_modelData->GetLocatorTransform(segName); } EWeaponCollisionResponseTypes CActor::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const -{ - return EWeaponCollisionResponseTypes::OtherProjectile; + const CWeaponMode&, EProjectileAttrib) const { + return EWeaponCollisionResponseTypes::OtherProjectile; } void CActor::FluidFXThink(CActor::EFluidState, CScriptWater&, CStateManager&) {} -void CActor::OnScanStateChanged(EScanState state, CStateManager& mgr) -{ - if (state == EScanState::Start) - SendScriptMsgs(EScriptObjectState::ScanStart, mgr, EScriptObjectMessage::None); - else if (state == EScanState::Processing) - SendScriptMsgs(EScriptObjectState::ScanProcessing, mgr, EScriptObjectMessage::None); - else if (state == EScanState::Done) - SendScriptMsgs(EScriptObjectState::ScanDone, mgr, EScriptObjectMessage::None); +void CActor::OnScanStateChanged(EScanState state, CStateManager& mgr) { + if (state == EScanState::Start) + SendScriptMsgs(EScriptObjectState::ScanStart, mgr, EScriptObjectMessage::None); + else if (state == EScanState::Processing) + SendScriptMsgs(EScriptObjectState::ScanProcessing, mgr, EScriptObjectMessage::None); + else if (state == EScanState::Done) + SendScriptMsgs(EScriptObjectState::ScanDone, mgr, EScriptObjectMessage::None); } zeus::CAABox CActor::GetSortingBounds(const CStateManager&) const { return x9c_renderBounds; } -void CActor::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType event, float dt) -{ - if (event == EUserEventType::LoopedSoundStop) - RemoveEmitter(); +void CActor::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType event, float dt) { + if (event == EUserEventType::LoopedSoundStop) + RemoveEmitter(); } void CActor::RemoveMaterial(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4, - CStateManager& mgr) -{ - x68_material.Remove(t1); - RemoveMaterial(t2, t3, t4, mgr); + CStateManager& mgr) { + x68_material.Remove(t1); + RemoveMaterial(t2, t3, t4, mgr); } -void CActor::RemoveMaterial(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, CStateManager& mgr) -{ - x68_material.Remove(t1); - RemoveMaterial(t2, t3, mgr); +void CActor::RemoveMaterial(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, CStateManager& mgr) { + x68_material.Remove(t1); + RemoveMaterial(t2, t3, mgr); } -void CActor::RemoveMaterial(EMaterialTypes t1, EMaterialTypes t2, CStateManager& mgr) -{ - x68_material.Remove(t1); - RemoveMaterial(t2, mgr); +void CActor::RemoveMaterial(EMaterialTypes t1, EMaterialTypes t2, CStateManager& mgr) { + x68_material.Remove(t1); + RemoveMaterial(t2, mgr); } -void CActor::RemoveMaterial(EMaterialTypes t, CStateManager& mgr) -{ - x68_material.Remove(t); - mgr.UpdateObjectInLists(*this); +void CActor::RemoveMaterial(EMaterialTypes t, CStateManager& mgr) { + x68_material.Remove(t); + mgr.UpdateObjectInLists(*this); } void CActor::AddMaterial(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4, EMaterialTypes t5, - CStateManager& mgr) -{ - x68_material.Add(t1); - AddMaterial(t2, t3, t4, t5, mgr); + CStateManager& mgr) { + x68_material.Add(t1); + AddMaterial(t2, t3, t4, t5, mgr); } -void CActor::AddMaterial(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4, CStateManager& mgr) -{ - x68_material.Add(t1); - AddMaterial(t2, t3, t4, mgr); +void CActor::AddMaterial(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, EMaterialTypes t4, + CStateManager& mgr) { + x68_material.Add(t1); + AddMaterial(t2, t3, t4, mgr); } -void CActor::AddMaterial(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, CStateManager& mgr) -{ - x68_material.Add(t1); - AddMaterial(t2, t3, mgr); +void CActor::AddMaterial(EMaterialTypes t1, EMaterialTypes t2, EMaterialTypes t3, CStateManager& mgr) { + x68_material.Add(t1); + AddMaterial(t2, t3, mgr); } -void CActor::AddMaterial(EMaterialTypes t1, EMaterialTypes t2, CStateManager& mgr) -{ - x68_material.Add(t1); - AddMaterial(t2, mgr); +void CActor::AddMaterial(EMaterialTypes t1, EMaterialTypes t2, CStateManager& mgr) { + x68_material.Add(t1); + AddMaterial(t2, mgr); } -void CActor::AddMaterial(EMaterialTypes type, CStateManager& mgr) -{ - x68_material.Add(type); - mgr.UpdateObjectInLists(*this); +void CActor::AddMaterial(EMaterialTypes type, CStateManager& mgr) { + x68_material.Add(type); + mgr.UpdateObjectInLists(*this); } -void CActor::AddMaterial(const CMaterialList& l) -{ - x68_material.Add(l); +void CActor::AddMaterial(const CMaterialList& l) { x68_material.Add(l); } + +void CActor::CreateShadow(bool b) { + if (b) { + _CreateShadow(); + if (!xe5_24_shadowEnabled && x94_simpleShadow) + xe5_25_shadowDirty = true; + } + xe5_24_shadowEnabled = b; } -void CActor::CreateShadow(bool b) -{ - if (b) - { - _CreateShadow(); - if (!xe5_24_shadowEnabled && x94_simpleShadow) - xe5_25_shadowDirty = true; - } - xe5_24_shadowEnabled = b; -} - -void CActor::_CreateShadow() -{ - if (!x94_simpleShadow && x64_modelData && (x64_modelData->HasAnimData() || x64_modelData->HasNormalModel())) - x94_simpleShadow.reset(new CSimpleShadow(1.f, 1.f, 20.f, 0.05f)); +void CActor::_CreateShadow() { + if (!x94_simpleShadow && x64_modelData && (x64_modelData->HasAnimData() || x64_modelData->HasNormalModel())) + x94_simpleShadow.reset(new CSimpleShadow(1.f, 1.f, 20.f, 0.05f)); } void CActor::SetCallTouch(bool callTouch) { xe5_28_callTouch = callTouch; } @@ -512,58 +438,50 @@ void CActor::SetUseInSortedLists(bool use) { xe5_27_useInSortedLists = use; } bool CActor::GetUseInSortedLists() const { return xe5_27_useInSortedLists; } -void CActor::SetInFluid(bool in, TUniqueId uid) -{ - if (in) - { - xe6_24_fluidCounter += 1; - xc4_fluidId = uid; - } - else - { - if (!xe6_24_fluidCounter) - return; +void CActor::SetInFluid(bool in, TUniqueId uid) { + if (in) { + xe6_24_fluidCounter += 1; + xc4_fluidId = uid; + } else { + if (!xe6_24_fluidCounter) + return; - xe6_24_fluidCounter -= 1; - if (xe6_24_fluidCounter == 0) - xc4_fluidId = kInvalidUniqueId; - } + xe6_24_fluidCounter -= 1; + if (xe6_24_fluidCounter == 0) + xc4_fluidId = kInvalidUniqueId; + } } bool CActor::HasModelData() const { return bool(x64_modelData); } -void CActor::SetSoundEventPitchBend(s32 val) -{ - xe6_30_enablePitchBend = true; - xc0_pitchBend = val / 8192.f - 1.f; - if (!x8c_loopingSfxHandle) - return; +void CActor::SetSoundEventPitchBend(s32 val) { + xe6_30_enablePitchBend = true; + xc0_pitchBend = val / 8192.f - 1.f; + if (!x8c_loopingSfxHandle) + return; - CSfxManager::PitchBend(x8c_loopingSfxHandle, xc0_pitchBend); + CSfxManager::PitchBend(x8c_loopingSfxHandle, xc0_pitchBend); } -void CActor::SetRotation(const zeus::CQuaternion &q) -{ - x34_transform = q.toTransform(x34_transform.origin); - xe4_27_notInSortedLists = true; - xe4_28_transformDirty = true; - xe4_29_actorLightsDirty = true; +void CActor::SetRotation(const zeus::CQuaternion& q) { + x34_transform = q.toTransform(x34_transform.origin); + xe4_27_notInSortedLists = true; + xe4_28_transformDirty = true; + xe4_29_actorLightsDirty = true; } -void CActor::SetTranslation(const zeus::CVector3f& tr) -{ - x34_transform.origin = tr; - xe4_27_notInSortedLists = true; - xe4_28_transformDirty = true; - xe4_29_actorLightsDirty = true; +void CActor::SetTranslation(const zeus::CVector3f& tr) { + x34_transform.origin = tr; + xe4_27_notInSortedLists = true; + xe4_28_transformDirty = true; + xe4_29_actorLightsDirty = true; } -void CActor::SetTransform(const zeus::CTransform& tr) -{ - x34_transform = tr; - xe4_27_notInSortedLists = true; - xe4_28_transformDirty = true; - xe4_29_actorLightsDirty = true; +void CActor::SetTransform(const zeus::CTransform& tr) { + x34_transform = tr; + xe4_27_notInSortedLists = true; + xe4_28_transformDirty = true; + xe4_29_actorLightsDirty = true; } void CActor::SetAddedToken(u32 tok) { xcc_addedToken = tok; } @@ -572,235 +490,197 @@ float CActor::GetPitch() const { return zeus::CQuaternion(x34_transform.buildMat float CActor::GetYaw() const { return zeus::CQuaternion(x34_transform.buildMatrix3f()).yaw(); } -void CActor::EnsureRendered(const CStateManager& mgr) const -{ - zeus::CAABox aabb = GetSortingBounds(mgr); - EnsureRendered(mgr, aabb.closestPointAlongVector(CGraphics::g_ViewMatrix.basis[1]), aabb); +void CActor::EnsureRendered(const CStateManager& mgr) const { + zeus::CAABox aabb = GetSortingBounds(mgr); + EnsureRendered(mgr, aabb.closestPointAlongVector(CGraphics::g_ViewMatrix.basis[1]), aabb); } -void CActor::EnsureRendered(const CStateManager& stateMgr, const zeus::CVector3f& pos, - const zeus::CAABox& aabb) const -{ - if (x64_modelData) - { - x64_modelData->RenderUnsortedParts(x64_modelData->GetRenderingModel(stateMgr), - x34_transform, x90_actorLights.get(), xb4_drawFlags); - } - stateMgr.AddDrawableActor(*this, pos, aabb); +void CActor::EnsureRendered(const CStateManager& stateMgr, const zeus::CVector3f& pos, const zeus::CAABox& aabb) const { + if (x64_modelData) { + x64_modelData->RenderUnsortedParts(x64_modelData->GetRenderingModel(stateMgr), x34_transform, x90_actorLights.get(), + xb4_drawFlags); + } + stateMgr.AddDrawableActor(*this, pos, aabb); } -void CActor::UpdateSfxEmitters() -{ - for (CSfxHandle& sfx : xd8_nonLoopingSfxHandles) - CSfxManager::UpdateEmitter(sfx, x34_transform.origin, zeus::CVector3f::skZero, xd4_maxVol); +void CActor::UpdateSfxEmitters() { + for (CSfxHandle& sfx : xd8_nonLoopingSfxHandles) + CSfxManager::UpdateEmitter(sfx, x34_transform.origin, zeus::CVector3f::skZero, xd4_maxVol); } -void CActor::ProcessSoundEvent(u32 sfxId, float weight, u32 flags, float falloff, float maxDist, - float minVol, float maxVol, const zeus::CVector3f& toListener, - const zeus::CVector3f& position, TAreaId aid, CStateManager& mgr, - bool translateId) -{ - if (toListener.magSquared() >= maxDist * maxDist) - return; - u16 id = translateId ? CSfxManager::TranslateSFXID(sfxId) : sfxId; +void CActor::ProcessSoundEvent(u32 sfxId, float weight, u32 flags, float falloff, float maxDist, float minVol, + float maxVol, const zeus::CVector3f& toListener, const zeus::CVector3f& position, + TAreaId aid, CStateManager& mgr, bool translateId) { + if (toListener.magSquared() >= maxDist * maxDist) + return; + u16 id = translateId ? CSfxManager::TranslateSFXID(sfxId) : sfxId; - u32 musyxFlags = 0x1; // Continuous parameter update - if (flags & 0x8) - musyxFlags |= 0x8; // Doppler FX + u32 musyxFlags = 0x1; // Continuous parameter update + if (flags & 0x8) + musyxFlags |= 0x8; // Doppler FX - CAudioSys::C3DEmitterParmData parms; - parms.x0_pos = position; - parms.xc_dir = zeus::CVector3f::skZero; - parms.x18_maxDist = maxDist; - parms.x1c_distComp = falloff; - parms.x20_flags = musyxFlags; - parms.x24_sfxId = id; - parms.x26_maxVol = maxVol; - parms.x27_minVol = minVol; - parms.x28_important = false; - parms.x29_prio = 0x7f; + CAudioSys::C3DEmitterParmData parms; + parms.x0_pos = position; + parms.xc_dir = zeus::CVector3f::skZero; + parms.x18_maxDist = maxDist; + parms.x1c_distComp = falloff; + parms.x20_flags = musyxFlags; + parms.x24_sfxId = id; + parms.x26_maxVol = maxVol; + parms.x27_minVol = minVol; + parms.x28_important = false; + parms.x29_prio = 0x7f; - bool useAcoustics = (flags & 0x80) == 0; - bool looping = (sfxId & 0x80000000) != 0; - bool nonEmitter = (sfxId & 0x40000000) != 0; - bool continuousUpdate = (sfxId & 0x20000000) != 0; + bool useAcoustics = (flags & 0x80) == 0; + bool looping = (sfxId & 0x80000000) != 0; + bool nonEmitter = (sfxId & 0x40000000) != 0; + bool continuousUpdate = (sfxId & 0x20000000) != 0; - if (mgr.GetActiveRandom()->Float() > weight) - return; - - if (looping) - { - u16 curId = x88_sfxId; - if (!x8c_loopingSfxHandle) - { - CSfxHandle handle; - if (nonEmitter) - handle = CSfxManager::SfxStart(id, 1.f, 0.f, true, 0x7f, true, aid); - else - handle = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); - if (handle) - { - x88_sfxId = id; - x8c_loopingSfxHandle = handle; - if (xe6_30_enablePitchBend) - CSfxManager::PitchBend(handle, xc0_pitchBend); - } - } - else if (curId == id) - { - CSfxManager::UpdateEmitter(x8c_loopingSfxHandle, position, zeus::CVector3f::skZero, maxVol); - } - else if (flags & 0x4) - { - CSfxManager::RemoveEmitter(x8c_loopingSfxHandle); - CSfxHandle handle = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); - if (handle) - { - x88_sfxId = id; - x8c_loopingSfxHandle = handle; - if (xe6_30_enablePitchBend) - CSfxManager::PitchBend(handle, xc0_pitchBend); - } - } - } - else - { - CSfxHandle handle; - if (nonEmitter) - handle = CSfxManager::SfxStart(id, 1.f, 0.f, useAcoustics, 0x7f, false, aid); - else - handle = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, false, aid); - - if (continuousUpdate) - { - xd8_nonLoopingSfxHandles[xe4_24_nextNonLoopingSfxHandle] = handle; - xe4_24_nextNonLoopingSfxHandle = (xe4_24_nextNonLoopingSfxHandle + 1) % xd8_nonLoopingSfxHandles.size(); - } + if (mgr.GetActiveRandom()->Float() > weight) + return; + if (looping) { + u16 curId = x88_sfxId; + if (!x8c_loopingSfxHandle) { + CSfxHandle handle; + if (nonEmitter) + handle = CSfxManager::SfxStart(id, 1.f, 0.f, true, 0x7f, true, aid); + else + handle = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); + if (handle) { + x88_sfxId = id; + x8c_loopingSfxHandle = handle; if (xe6_30_enablePitchBend) - CSfxManager::PitchBend(handle, xc0_pitchBend); + CSfxManager::PitchBend(handle, xc0_pitchBend); + } + } else if (curId == id) { + CSfxManager::UpdateEmitter(x8c_loopingSfxHandle, position, zeus::CVector3f::skZero, maxVol); + } else if (flags & 0x4) { + CSfxManager::RemoveEmitter(x8c_loopingSfxHandle); + CSfxHandle handle = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, true, aid); + if (handle) { + x88_sfxId = id; + x8c_loopingSfxHandle = handle; + if (xe6_30_enablePitchBend) + CSfxManager::PitchBend(handle, xc0_pitchBend); + } } -} - -SAdvancementDeltas CActor::UpdateAnimation(float dt, CStateManager& mgr, bool advTree) -{ - SAdvancementDeltas deltas = x64_modelData->AdvanceAnimation(dt, mgr, GetAreaId(), advTree); - x64_modelData->AdvanceParticles(x34_transform, dt, mgr); - UpdateSfxEmitters(); - if (x64_modelData && x64_modelData->HasAnimData()) - { - zeus::CVector3f toCamera = - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation() - x34_transform.origin; - - for (int i=0 ; iGetAnimationData()->GetPassedSoundPOICount() ; ++i) - { - CSoundPOINode& poi = CAnimData::g_SoundPOINodes[i]; - if (poi.GetPoiType() != EPOIType::Sound) - continue; - if (xe5_26_muted) - continue; - if (poi.GetCharacterIndex() != -1 && - x64_modelData->GetAnimationData()->GetCharacterIndex() != poi.GetCharacterIndex()) - continue; - ProcessSoundEvent(poi.GetSfxId(), poi.GetWeight(), poi.GetFlags(), poi.GetFalloff(), - poi.GetMaxDist(), 0.16f, xd4_maxVol, toCamera, x34_transform.origin, x4_areaId, - mgr, true); - } - - for (int i=0 ; iGetAnimationData()->GetPassedIntPOICount() ; ++i) - { - CInt32POINode& poi = CAnimData::g_Int32POINodes[i]; - if (poi.GetPoiType() == EPOIType::SoundInt32) - { - if (xe5_26_muted) - continue; - if (poi.GetCharacterIndex() != -1 && - x64_modelData->GetAnimationData()->GetCharacterIndex() != poi.GetCharacterIndex()) - continue; - ProcessSoundEvent(poi.GetValue(), poi.GetWeight(), poi.GetFlags(), 0.1f, - 150.f, 0.16f, xd4_maxVol, toCamera, x34_transform.origin, x4_areaId, - mgr, true); - } - else if (poi.GetPoiType() == EPOIType::UserEvent) - { - DoUserAnimEvent(mgr, poi, EUserEventType(poi.GetValue()), dt); - } - } - - for (int i=0 ; iGetAnimationData()->GetPassedParticlePOICount() ; ++i) - { - CParticlePOINode& poi = CAnimData::g_ParticlePOINodes[i]; - if (poi.GetCharacterIndex() != -1 && - x64_modelData->GetAnimationData()->GetCharacterIndex() != poi.GetCharacterIndex()) - continue; - x64_modelData->AnimationData()->GetParticleDB().SetParticleEffectState(poi.GetString(), true, mgr); - } - } - return deltas; -} - -void CActor::SetActorLights(std::unique_ptr&& lights) -{ - x90_actorLights = std::move(lights); - xe4_31_calculateLighting = true; -} - -bool CActor::CanDrawStatic() const -{ - if (!x30_24_active) - return false; - - if (x64_modelData && x64_modelData->HasNormalModel()) - return xb4_drawFlags.x0_blendMode <= 4; - - return false; -} - -const CScannableObjectInfo* CActor::GetScannableObjectInfo() const -{ - if (!x98_scanObjectInfo || !x98_scanObjectInfo.IsLoaded()) - return nullptr; - return x98_scanObjectInfo.GetObj(); -} - -void CActor::SetCalculateLighting(bool c) -{ - if (!x90_actorLights) - x90_actorLights = std::make_unique(8, zeus::CVector3f::skZero, - 4, 4, false, false, false, 0.1f); - xe4_31_calculateLighting = c; -} - -float CActor::GetAverageAnimVelocity(int anim) const -{ - if (HasModelData() && GetModelData()->HasAnimData()) - return GetModelData()->GetAnimationData()->GetAverageVelocity(anim); - return 0.f; -} - -void CActor::SetModelData(std::unique_ptr&& mData) -{ - if (mData->IsNull()) - x64_modelData.reset(); + } else { + CSfxHandle handle; + if (nonEmitter) + handle = CSfxManager::SfxStart(id, 1.f, 0.f, useAcoustics, 0x7f, false, aid); else - x64_modelData = std::move(mData); + handle = CSfxManager::AddEmitter(parms, useAcoustics, 0x7f, false, aid); + + if (continuousUpdate) { + xd8_nonLoopingSfxHandles[xe4_24_nextNonLoopingSfxHandle] = handle; + xe4_24_nextNonLoopingSfxHandle = (xe4_24_nextNonLoopingSfxHandle + 1) % xd8_nonLoopingSfxHandles.size(); + } + + if (xe6_30_enablePitchBend) + CSfxManager::PitchBend(handle, xc0_pitchBend); + } } -void CActor::SetMuted(bool muted) -{ - xe5_26_muted = muted; - RemoveEmitter(); +SAdvancementDeltas CActor::UpdateAnimation(float dt, CStateManager& mgr, bool advTree) { + SAdvancementDeltas deltas = x64_modelData->AdvanceAnimation(dt, mgr, GetAreaId(), advTree); + x64_modelData->AdvanceParticles(x34_transform, dt, mgr); + UpdateSfxEmitters(); + if (x64_modelData && x64_modelData->HasAnimData()) { + zeus::CVector3f toCamera = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation() - x34_transform.origin; + + for (int i = 0; i < x64_modelData->GetAnimationData()->GetPassedSoundPOICount(); ++i) { + CSoundPOINode& poi = CAnimData::g_SoundPOINodes[i]; + if (poi.GetPoiType() != EPOIType::Sound) + continue; + if (xe5_26_muted) + continue; + if (poi.GetCharacterIndex() != -1 && + x64_modelData->GetAnimationData()->GetCharacterIndex() != poi.GetCharacterIndex()) + continue; + ProcessSoundEvent(poi.GetSfxId(), poi.GetWeight(), poi.GetFlags(), poi.GetFalloff(), poi.GetMaxDist(), 0.16f, + xd4_maxVol, toCamera, x34_transform.origin, x4_areaId, mgr, true); + } + + for (int i = 0; i < x64_modelData->GetAnimationData()->GetPassedIntPOICount(); ++i) { + CInt32POINode& poi = CAnimData::g_Int32POINodes[i]; + if (poi.GetPoiType() == EPOIType::SoundInt32) { + if (xe5_26_muted) + continue; + if (poi.GetCharacterIndex() != -1 && + x64_modelData->GetAnimationData()->GetCharacterIndex() != poi.GetCharacterIndex()) + continue; + ProcessSoundEvent(poi.GetValue(), poi.GetWeight(), poi.GetFlags(), 0.1f, 150.f, 0.16f, xd4_maxVol, toCamera, + x34_transform.origin, x4_areaId, mgr, true); + } else if (poi.GetPoiType() == EPOIType::UserEvent) { + DoUserAnimEvent(mgr, poi, EUserEventType(poi.GetValue()), dt); + } + } + + for (int i = 0; i < x64_modelData->GetAnimationData()->GetPassedParticlePOICount(); ++i) { + CParticlePOINode& poi = CAnimData::g_ParticlePOINodes[i]; + if (poi.GetCharacterIndex() != -1 && + x64_modelData->GetAnimationData()->GetCharacterIndex() != poi.GetCharacterIndex()) + continue; + x64_modelData->AnimationData()->GetParticleDB().SetParticleEffectState(poi.GetString(), true, mgr); + } + } + return deltas; } -void CActor::MoveScannableObjectInfoToActor(CActor* act, CStateManager& mgr) -{ - if (!act) - return; - - if (act->GetScannableObjectInfo() != GetScannableObjectInfo()) - act->x98_scanObjectInfo = x98_scanObjectInfo; - - act->AddMaterial(EMaterialTypes::Scannable, mgr); - RemoveMaterial(EMaterialTypes::Scannable, mgr); +void CActor::SetActorLights(std::unique_ptr&& lights) { + x90_actorLights = std::move(lights); + xe4_31_calculateLighting = true; } + +bool CActor::CanDrawStatic() const { + if (!x30_24_active) + return false; + + if (x64_modelData && x64_modelData->HasNormalModel()) + return xb4_drawFlags.x0_blendMode <= 4; + + return false; } + +const CScannableObjectInfo* CActor::GetScannableObjectInfo() const { + if (!x98_scanObjectInfo || !x98_scanObjectInfo.IsLoaded()) + return nullptr; + return x98_scanObjectInfo.GetObj(); +} + +void CActor::SetCalculateLighting(bool c) { + if (!x90_actorLights) + x90_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f); + xe4_31_calculateLighting = c; +} + +float CActor::GetAverageAnimVelocity(int anim) const { + if (HasModelData() && GetModelData()->HasAnimData()) + return GetModelData()->GetAnimationData()->GetAverageVelocity(anim); + return 0.f; +} + +void CActor::SetModelData(std::unique_ptr&& mData) { + if (mData->IsNull()) + x64_modelData.reset(); + else + x64_modelData = std::move(mData); +} + +void CActor::SetMuted(bool muted) { + xe5_26_muted = muted; + RemoveEmitter(); +} + +void CActor::MoveScannableObjectInfoToActor(CActor* act, CStateManager& mgr) { + if (!act) + return; + + if (act->GetScannableObjectInfo() != GetScannableObjectInfo()) + act->x98_scanObjectInfo = x98_scanObjectInfo; + + act->AddMaterial(EMaterialTypes::Scannable, mgr); + RemoveMaterial(EMaterialTypes::Scannable, mgr); +} +} // namespace urde diff --git a/Runtime/World/CActor.hpp b/Runtime/World/CActor.hpp index 41ec49cc8..91e33e6d1 100644 --- a/Runtime/World/CActor.hpp +++ b/Runtime/World/CActor.hpp @@ -12,8 +12,7 @@ #include "CScannableObjectInfo.hpp" #include "Weapon/WeaponCommon.hpp" -namespace urde -{ +namespace urde { class CActorParameters; class CWeaponMode; @@ -24,184 +23,174 @@ class CLightParameters; class CScriptWater; class CSimpleShadow; -class CActor : public CEntity -{ - friend class CStateManager; +class CActor : public CEntity { + friend class CStateManager; + protected: - zeus::CTransform x34_transform; - std::unique_ptr x64_modelData; - CMaterialList x68_material; - CMaterialFilter x70_materialFilter; - s16 x88_sfxId = -1; - CSfxHandle x8c_loopingSfxHandle; - std::unique_ptr x90_actorLights; - std::unique_ptr x94_simpleShadow; - TLockedToken x98_scanObjectInfo; - zeus::CAABox x9c_renderBounds; - CModelFlags xb4_drawFlags; - float xbc_time = 0.f; - float xc0_pitchBend = 0.f; - TUniqueId xc4_fluidId = kInvalidUniqueId; - TUniqueId xc6_nextDrawNode; - int xc8_drawnToken = -1; - int xcc_addedToken = -1; - float xd0_damageMag; - float xd4_maxVol = 1.f; - rstl::reserved_vector xd8_nonLoopingSfxHandles; - union - { - struct - { - u8 xe4_24_nextNonLoopingSfxHandle : 3; - bool xe4_27_notInSortedLists : 1; - bool xe4_28_transformDirty : 1; - bool xe4_29_actorLightsDirty : 1; - bool xe4_30_outOfFrustum : 1; - bool xe4_31_calculateLighting : 1; - bool xe5_24_shadowEnabled : 1; - bool xe5_25_shadowDirty : 1; - bool xe5_26_muted : 1; - bool xe5_27_useInSortedLists : 1; - bool xe5_28_callTouch : 1; - bool xe5_29_globalTimeProvider : 1; - bool xe5_30_renderUnsorted : 1; - bool xe5_31_pointGeneratorParticles : 1; - u8 xe6_24_fluidCounter : 3; - u8 xe6_27_thermalVisorFlags : 2; // 1: thermal cold, 2: thermal hot - bool xe6_29_renderParticleDBInside : 1; - bool xe6_30_enablePitchBend : 1; - u8 xe6_31_targetableVisorFlags : 4; - bool xe7_27_enableRender : 1; - bool xe7_28_worldLightingDirty : 1; - bool xe7_29_drawEnabled : 1; - bool xe7_30_doTargetDistanceTest : 1; - bool xe7_31_targetable : 1; - }; - u32 dummy = 0; + zeus::CTransform x34_transform; + std::unique_ptr x64_modelData; + CMaterialList x68_material; + CMaterialFilter x70_materialFilter; + s16 x88_sfxId = -1; + CSfxHandle x8c_loopingSfxHandle; + std::unique_ptr x90_actorLights; + std::unique_ptr x94_simpleShadow; + TLockedToken x98_scanObjectInfo; + zeus::CAABox x9c_renderBounds; + CModelFlags xb4_drawFlags; + float xbc_time = 0.f; + float xc0_pitchBend = 0.f; + TUniqueId xc4_fluidId = kInvalidUniqueId; + TUniqueId xc6_nextDrawNode; + int xc8_drawnToken = -1; + int xcc_addedToken = -1; + float xd0_damageMag; + float xd4_maxVol = 1.f; + rstl::reserved_vector xd8_nonLoopingSfxHandles; + union { + struct { + u8 xe4_24_nextNonLoopingSfxHandle : 3; + bool xe4_27_notInSortedLists : 1; + bool xe4_28_transformDirty : 1; + bool xe4_29_actorLightsDirty : 1; + bool xe4_30_outOfFrustum : 1; + bool xe4_31_calculateLighting : 1; + bool xe5_24_shadowEnabled : 1; + bool xe5_25_shadowDirty : 1; + bool xe5_26_muted : 1; + bool xe5_27_useInSortedLists : 1; + bool xe5_28_callTouch : 1; + bool xe5_29_globalTimeProvider : 1; + bool xe5_30_renderUnsorted : 1; + bool xe5_31_pointGeneratorParticles : 1; + u8 xe6_24_fluidCounter : 3; + u8 xe6_27_thermalVisorFlags : 2; // 1: thermal cold, 2: thermal hot + bool xe6_29_renderParticleDBInside : 1; + bool xe6_30_enablePitchBend : 1; + u8 xe6_31_targetableVisorFlags : 4; + bool xe7_27_enableRender : 1; + bool xe7_28_worldLightingDirty : 1; + bool xe7_29_drawEnabled : 1; + bool xe7_30_doTargetDistanceTest : 1; + bool xe7_31_targetable : 1; }; - void _CreateShadow(); - void UpdateSfxEmitters(); - void DrawTouchBounds() const; - void RenderInternal(const CStateManager& mgr) const; - bool IsModelOpaque(const CStateManager& mgr) const; + u32 dummy = 0; + }; + void _CreateShadow(); + void UpdateSfxEmitters(); + void DrawTouchBounds() const; + void RenderInternal(const CStateManager& mgr) const; + bool IsModelOpaque(const CStateManager& mgr) const; public: - enum class EFluidState - { - EnteredFluid, - InFluid, - LeftFluid - }; + enum class EFluidState { EnteredFluid, InFluid, LeftFluid }; - enum class EScanState - { - Start, - Processing, - Done, - }; + enum class EScanState { + Start, + Processing, + Done, + }; - CActor(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform&, - CModelData&& mData, const CMaterialList& list, const CActorParameters& params, TUniqueId otherUid); + CActor(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform&, + CModelData&& mData, const CMaterialList& list, const CActorParameters& params, TUniqueId otherUid); - virtual void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - virtual void SetActive(bool active) - { - xe4_27_notInSortedLists = true; - xe4_28_transformDirty = true; - xe4_29_actorLightsDirty = true; - xe7_29_drawEnabled = active; - CEntity::SetActive(active); - } - virtual void PreRender(CStateManager&, const zeus::CFrustum&); - virtual void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - virtual void Render(const CStateManager&) const; - virtual bool CanRenderUnsorted(const CStateManager&) const; - virtual void CalculateRenderBounds(); - virtual CHealthInfo* HealthInfo(CStateManager&); - virtual const CDamageVulnerability* GetDamageVulnerability() const; - virtual const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, - const CDamageInfo&) const; - virtual std::experimental::optional GetTouchBounds() const; - virtual void Touch(CActor&, CStateManager&); - virtual zeus::CVector3f GetOrbitPosition(const CStateManager&) const; - virtual zeus::CVector3f GetAimPosition(const CStateManager&, float) const; - virtual zeus::CVector3f GetHomingPosition(const CStateManager&, float) const; - virtual zeus::CVector3f GetScanObjectIndicatorPosition(const CStateManager&) const; - virtual EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const; - virtual void FluidFXThink(EFluidState, CScriptWater&, CStateManager&); - virtual void OnScanStateChanged(EScanState, CStateManager&); - virtual zeus::CAABox GetSortingBounds(const CStateManager&) const; - virtual void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt); + virtual void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + virtual void SetActive(bool active) { + xe4_27_notInSortedLists = true; + xe4_28_transformDirty = true; + xe4_29_actorLightsDirty = true; + xe7_29_drawEnabled = active; + CEntity::SetActive(active); + } + virtual void PreRender(CStateManager&, const zeus::CFrustum&); + virtual void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + virtual void Render(const CStateManager&) const; + virtual bool CanRenderUnsorted(const CStateManager&) const; + virtual void CalculateRenderBounds(); + virtual CHealthInfo* HealthInfo(CStateManager&); + virtual const CDamageVulnerability* GetDamageVulnerability() const; + virtual const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&, + const CDamageInfo&) const; + virtual std::experimental::optional GetTouchBounds() const; + virtual void Touch(CActor&, CStateManager&); + virtual zeus::CVector3f GetOrbitPosition(const CStateManager&) const; + virtual zeus::CVector3f GetAimPosition(const CStateManager&, float) const; + virtual zeus::CVector3f GetHomingPosition(const CStateManager&, float) const; + virtual zeus::CVector3f GetScanObjectIndicatorPosition(const CStateManager&) const; + virtual EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, + const CWeaponMode&, EProjectileAttrib) const; + virtual void FluidFXThink(EFluidState, CScriptWater&, CStateManager&); + virtual void OnScanStateChanged(EScanState, CStateManager&); + virtual zeus::CAABox GetSortingBounds(const CStateManager&) const; + virtual void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt); - void RemoveEmitter(); - void SetVolume(float vol); - void SetMuted(bool); - const zeus::CTransform& GetTransform() const { return x34_transform; } - const zeus::CVector3f& GetTranslation() const { return x34_transform.origin; } - const zeus::CTransform GetScaledLocatorTransform(std::string_view segName) const; - const zeus::CTransform GetLocatorTransform(std::string_view segName) const; - void RemoveMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); - void RemoveMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); - void RemoveMaterial(EMaterialTypes, EMaterialTypes, CStateManager&); - void RemoveMaterial(EMaterialTypes, CStateManager&); - void AddMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); - void AddMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); - void AddMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); - void AddMaterial(EMaterialTypes, EMaterialTypes, CStateManager&); - void AddMaterial(EMaterialTypes, CStateManager&); - void AddMaterial(const CMaterialList& l); + void RemoveEmitter(); + void SetVolume(float vol); + void SetMuted(bool); + const zeus::CTransform& GetTransform() const { return x34_transform; } + const zeus::CVector3f& GetTranslation() const { return x34_transform.origin; } + const zeus::CTransform GetScaledLocatorTransform(std::string_view segName) const; + const zeus::CTransform GetLocatorTransform(std::string_view segName) const; + void RemoveMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); + void RemoveMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); + void RemoveMaterial(EMaterialTypes, EMaterialTypes, CStateManager&); + void RemoveMaterial(EMaterialTypes, CStateManager&); + void AddMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); + void AddMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); + void AddMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); + void AddMaterial(EMaterialTypes, EMaterialTypes, CStateManager&); + void AddMaterial(EMaterialTypes, CStateManager&); + void AddMaterial(const CMaterialList& l); - void CreateShadow(bool); - void SetCallTouch(bool callTouch); - bool GetCallTouch() const; - void SetUseInSortedLists(bool use); - bool GetUseInSortedLists() const; - const CMaterialFilter& GetMaterialFilter() const { return x70_materialFilter; } - void SetMaterialFilter(const CMaterialFilter& filter) { x70_materialFilter = filter; } - const CMaterialList& GetMaterialList() const { return x68_material; } - void SetMaterialList(const CMaterialList& list) { x68_material = list; } - void SetInFluid(bool in, TUniqueId uid); - bool HasModelData() const; - const CSfxHandle& GetSfxHandle() const { return x8c_loopingSfxHandle; } - void SetSoundEventPitchBend(s32); - void SetRotation(const zeus::CQuaternion& q); - void SetTranslation(const zeus::CVector3f& tr); - void SetTransform(const zeus::CTransform& tr); - void SetAddedToken(u32 tok); - float GetPitch() const; - float GetYaw() const; - const CModelData* GetModelData() const { return x64_modelData.get(); } - CModelData* ModelData() { return x64_modelData.get(); } - void EnsureRendered(const CStateManager&) const; - void EnsureRendered(const CStateManager&, const zeus::CVector3f&, const zeus::CAABox&) const; - void ProcessSoundEvent(u32 sfxId, float weight, u32 flags, float falloff, float maxDist, - float minVol, float maxVol, const zeus::CVector3f& toListener, - const zeus::CVector3f& position, TAreaId aid, CStateManager& mgr, - bool translateId); - SAdvancementDeltas UpdateAnimation(float, CStateManager&, bool); - void SetActorLights(std::unique_ptr&& lights); - const CActorLights* GetActorLights() const { return x90_actorLights.get(); } - CActorLights* ActorLights() { return x90_actorLights.get(); } - bool CanDrawStatic() const; - bool IsDrawEnabled() const { return xe7_29_drawEnabled; } - void SetWorldLightingDirty(bool b) { xe7_28_worldLightingDirty = b; } - const CScannableObjectInfo* GetScannableObjectInfo() const; - const CHealthInfo* GetHealthInfo(const CStateManager& mgr) const - { return const_cast(this)->HealthInfo(const_cast(mgr)); } - bool GetDoTargetDistanceTest() const { return xe7_30_doTargetDistanceTest; } - void SetCalculateLighting(bool c); - float GetAverageAnimVelocity(int anim) const; - u8 GetTargetableVisorFlags() const { return xe6_31_targetableVisorFlags; } - bool GetIsTargetable() const { return xe7_31_targetable; } - void SetDrawFlags(const CModelFlags& flags) { xb4_drawFlags = flags; } - void SetModelData(std::unique_ptr&& mData); - u8 GetFluidCounter() const { return xe6_24_fluidCounter; } - TUniqueId GetFluidId() const { return xc4_fluidId; } - bool GetPointGeneratorParticles() const { return xe5_31_pointGeneratorParticles; } - void SetPointGeneratorParticles(bool s) { xe5_31_pointGeneratorParticles = s; } - CSimpleShadow* Shadow() { return x94_simpleShadow.get(); } - void MoveScannableObjectInfoToActor(CActor*, CStateManager&); + void CreateShadow(bool); + void SetCallTouch(bool callTouch); + bool GetCallTouch() const; + void SetUseInSortedLists(bool use); + bool GetUseInSortedLists() const; + const CMaterialFilter& GetMaterialFilter() const { return x70_materialFilter; } + void SetMaterialFilter(const CMaterialFilter& filter) { x70_materialFilter = filter; } + const CMaterialList& GetMaterialList() const { return x68_material; } + void SetMaterialList(const CMaterialList& list) { x68_material = list; } + void SetInFluid(bool in, TUniqueId uid); + bool HasModelData() const; + const CSfxHandle& GetSfxHandle() const { return x8c_loopingSfxHandle; } + void SetSoundEventPitchBend(s32); + void SetRotation(const zeus::CQuaternion& q); + void SetTranslation(const zeus::CVector3f& tr); + void SetTransform(const zeus::CTransform& tr); + void SetAddedToken(u32 tok); + float GetPitch() const; + float GetYaw() const; + const CModelData* GetModelData() const { return x64_modelData.get(); } + CModelData* ModelData() { return x64_modelData.get(); } + void EnsureRendered(const CStateManager&) const; + void EnsureRendered(const CStateManager&, const zeus::CVector3f&, const zeus::CAABox&) const; + void ProcessSoundEvent(u32 sfxId, float weight, u32 flags, float falloff, float maxDist, float minVol, float maxVol, + const zeus::CVector3f& toListener, const zeus::CVector3f& position, TAreaId aid, + CStateManager& mgr, bool translateId); + SAdvancementDeltas UpdateAnimation(float, CStateManager&, bool); + void SetActorLights(std::unique_ptr&& lights); + const CActorLights* GetActorLights() const { return x90_actorLights.get(); } + CActorLights* ActorLights() { return x90_actorLights.get(); } + bool CanDrawStatic() const; + bool IsDrawEnabled() const { return xe7_29_drawEnabled; } + void SetWorldLightingDirty(bool b) { xe7_28_worldLightingDirty = b; } + const CScannableObjectInfo* GetScannableObjectInfo() const; + const CHealthInfo* GetHealthInfo(const CStateManager& mgr) const { + return const_cast(this)->HealthInfo(const_cast(mgr)); + } + bool GetDoTargetDistanceTest() const { return xe7_30_doTargetDistanceTest; } + void SetCalculateLighting(bool c); + float GetAverageAnimVelocity(int anim) const; + u8 GetTargetableVisorFlags() const { return xe6_31_targetableVisorFlags; } + bool GetIsTargetable() const { return xe7_31_targetable; } + void SetDrawFlags(const CModelFlags& flags) { xb4_drawFlags = flags; } + void SetModelData(std::unique_ptr&& mData); + u8 GetFluidCounter() const { return xe6_24_fluidCounter; } + TUniqueId GetFluidId() const { return xc4_fluidId; } + bool GetPointGeneratorParticles() const { return xe5_31_pointGeneratorParticles; } + void SetPointGeneratorParticles(bool s) { xe5_31_pointGeneratorParticles = s; } + CSimpleShadow* Shadow() { return x94_simpleShadow.get(); } + void MoveScannableObjectInfoToActor(CActor*, CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CActorModelParticles.cpp b/Runtime/World/CActorModelParticles.cpp index 000112499..6a3437dfc 100644 --- a/Runtime/World/CActorModelParticles.cpp +++ b/Runtime/World/CActorModelParticles.cpp @@ -12,113 +12,97 @@ #include "World/CScriptPlayerActor.hpp" #include "CPatterned.hpp" -namespace urde -{ +namespace urde { -static bool IsMediumOrLarge(CActor& act) -{ - if (TCastToConstPtr pat = act) - return pat->GetKnockBackController().GetVariant() != EKnockBackVariant::Small; - return false; +static bool IsMediumOrLarge(CActor& act) { + if (TCastToConstPtr pat = act) + return pat->GetKnockBackController().GetVariant() != EKnockBackVariant::Small; + return false; } CActorModelParticles::CItem::CItem(const CEntity& ent, CActorModelParticles& parent) -: x0_id(ent.GetUniqueId()), x4_areaId(ent.GetAreaIdAlways()), - xdc_ashy(parent.x48_ashy), x128_parent(parent) -{ - x8_thermalHotParticles.resize(8); +: x0_id(ent.GetUniqueId()), x4_areaId(ent.GetAreaIdAlways()), xdc_ashy(parent.x48_ashy), x128_parent(parent) { + x8_thermalHotParticles.resize(8); } -u32 GetNextBestPt(s32 start, const std::vector>& vn, CRandom16& rnd) -{ - const zeus::CVector3f& startVec = vn[start].first; - u32 ret; - float lastMag = 0.f; - for (s32 i = 0; i < 10; ++i) - { - u32 idx = u32(rnd.Range(0, s32(vn.size()) - 1)); - const zeus::CVector3f& rndVec = vn[idx].first; - float mag = (startVec - rndVec).magSquared(); - if (mag > lastMag) - { - ret = idx; - lastMag = mag; - } +u32 GetNextBestPt(s32 start, const std::vector>& vn, CRandom16& rnd) { + const zeus::CVector3f& startVec = vn[start].first; + u32 ret; + float lastMag = 0.f; + for (s32 i = 0; i < 10; ++i) { + u32 idx = u32(rnd.Range(0, s32(vn.size()) - 1)); + const zeus::CVector3f& rndVec = vn[idx].first; + float mag = (startVec - rndVec).magSquared(); + if (mag > lastMag) { + ret = idx; + lastMag = mag; } - return ret; + } + return ret; } -void CActorModelParticles::CItem::GeneratePoints(const std::vector>& vn) -{ - for (std::pair, u32>& pair: x8_thermalHotParticles) - { - if (pair.first) - { - CRandom16 rnd(pair.second); - const zeus::CVector3f& vec = vn[u32(rnd.Float() * (vn.size() - 1))].first; - pair.first->SetTranslation(xec_ * vec); - } +void CActorModelParticles::CItem::GeneratePoints(const std::vector>& vn) { + for (std::pair, u32>& pair : x8_thermalHotParticles) { + if (pair.first) { + CRandom16 rnd(pair.second); + const zeus::CVector3f& vec = vn[u32(rnd.Float() * (vn.size() - 1))].first; + pair.first->SetTranslation(xec_ * vec); } + } - if (x84_ > 0) - { - CRandom16 rnd(x88_seed1); - u32 count = (x84_ >= 16 ? 16 : x84_); - u32 idx = x80_; - for (u32 i = 0; i < count; ++i) - { - idx = GetNextBestPt(idx, vn, rnd); - x78_->SetTranslation(xec_ * vn[idx].first); - zeus::CVector3f v = vn[idx].second; - if (v.canBeNormalized()) - { - v.normalize(); - x78_->SetOrientation(zeus::CTransform{zeus::CVector3f::skUp.cross(v), v, zeus::CVector3f::skUp, - zeus::CVector3f::skZero}); - } - x78_->ForceParticleCreation(1); - } - x84_ -= count; - x88_seed1 = rnd.GetSeed(); + if (x84_ > 0) { + CRandom16 rnd(x88_seed1); + u32 count = (x84_ >= 16 ? 16 : x84_); + u32 idx = x80_; + for (u32 i = 0; i < count; ++i) { + idx = GetNextBestPt(idx, vn, rnd); + x78_->SetTranslation(xec_ * vn[idx].first); + zeus::CVector3f v = vn[idx].second; + if (v.canBeNormalized()) { + v.normalize(); + x78_->SetOrientation( + zeus::CTransform{zeus::CVector3f::skUp.cross(v), v, zeus::CVector3f::skUp, zeus::CVector3f::skZero}); + } + x78_->ForceParticleCreation(1); } + x84_ -= count; + x88_seed1 = rnd.GetSeed(); + } - if (xb0_ != -1) - { - CRandom16 rnd(xb4_seed2); + if (xb0_ != -1) { + CRandom16 rnd(xb4_seed2); - std::unique_ptr iceGen = x128_parent.MakeIceGen(); - iceGen->SetGlobalOrientAndTrans(xf8_); + std::unique_ptr iceGen = x128_parent.MakeIceGen(); + iceGen->SetGlobalOrientAndTrans(xf8_); - u32 next = GetNextBestPt(xb0_, vn, rnd); - iceGen->SetTranslation(xec_ * vn[next].first); + u32 next = GetNextBestPt(xb0_, vn, rnd); + iceGen->SetTranslation(xec_ * vn[next].first); - iceGen->SetOrientation(zeus::CTransform::MakeRotationsBasedOnY(zeus::CUnitVector3f(vn[next].second))); + iceGen->SetOrientation(zeus::CTransform::MakeRotationsBasedOnY(zeus::CUnitVector3f(vn[next].second))); - x8c_thermalColdParticles.push_back(std::move(iceGen)); - xb0_ = (x8c_thermalColdParticles.size() == 4 ? -1 : next); - } -// TODO: Verify behavior - if (xc0_particleElectric && xc0_particleElectric->GetParticleEmission()) - { - CRandom16 rnd(xcc_seed3); - u32 end = 1; + x8c_thermalColdParticles.push_back(std::move(iceGen)); + xb0_ = (x8c_thermalColdParticles.size() == 4 ? -1 : next); + } + // TODO: Verify behavior + if (xc0_particleElectric && xc0_particleElectric->GetParticleEmission()) { + CRandom16 rnd(xcc_seed3); + u32 end = 1; #if 0 if (4 < 1) end = 4; #endif - u32 lastRnd; - for (u32 i = 0; i < end; ++i) - { - xc0_particleElectric->SetOverrideIPos(vn[u32(rnd.Range(0, s32(vn.size()) - 1))].first * xec_); - lastRnd = u32(rnd.Range(0, s32(vn.size()) - 1)); - xc0_particleElectric->SetOverrideFPos(vn[lastRnd].first * xec_); - xc0_particleElectric->ForceParticleCreation(1); - } - - xcc_seed3 = rnd.GetSeed(); - xc8_ = lastRnd; + u32 lastRnd; + for (u32 i = 0; i < end; ++i) { + xc0_particleElectric->SetOverrideIPos(vn[u32(rnd.Range(0, s32(vn.size()) - 1))].first * xec_); + lastRnd = u32(rnd.Range(0, s32(vn.size()) - 1)); + xc0_particleElectric->SetOverrideFPos(vn[lastRnd].first * xec_); + xc0_particleElectric->ForceParticleCreation(1); } - // TODO: Finish + xcc_seed3 = rnd.GetSeed(); + xc8_ = lastRnd; + } + + // TODO: Finish #if 0 if (xd4_) { @@ -127,497 +111,388 @@ void CActorModelParticles::CItem::GeneratePoints(const std::vector= 4) - r26 = false; - } - if (r26) - { - for (auto& p : x8_thermalHotParticles) - { - if (!p.first) - { - p.second = mgr.GetActiveRandom()->Next(); - p.first = x128_parent.MakeOnFireGen(); - x6c_onFireDelayTimer = 0.3f; - break; - } - } - } - if (!x74_sfx) - { - x74_sfx = CSfxManager::AddEmitter(SFXsfx0480 + (IsMediumOrLarge(*actor) ? 1 : 0), - actor->GetTranslation(), zeus::CVector3f::skZero, true, true, 0x7f, kInvalidAreaId); - } - x70_onFire = false; - } - for (auto& p : x8_thermalHotParticles) - { - if (p.first) - { - if (p.first->IsSystemDeletable()) - p.first.reset(); - else if (actor) - p.first->SetGlobalOrientAndTrans(actor->GetTransform()); - p.first->Update(dt); - r30 = true; - r31 = true; - } +bool CActorModelParticles::CItem::UpdateOnFire(float dt, CActor* actor, CStateManager& mgr) { + bool r30 = false; + bool r31 = false; + x6c_onFireDelayTimer -= dt; + if (x6c_onFireDelayTimer < 0.f) + x6c_onFireDelayTimer = 0.f; + if (x134_lockDeps & 0x1) { + if (x128_parent.xe6_bits2 & 0x1) { + if (x70_onFire && actor) { + bool r26 = true; + if (x78_ || xdc_ashy) { + r26 = false; + } else if (!IsMediumOrLarge(*actor)) { + int r3 = 0; + for (const auto& p : x8_thermalHotParticles) + if (p.first) + ++r3; + if (r3 >= 4) + r26 = false; + } + if (r26) { + for (auto& p : x8_thermalHotParticles) { + if (!p.first) { + p.second = mgr.GetActiveRandom()->Next(); + p.first = x128_parent.MakeOnFireGen(); + x6c_onFireDelayTimer = 0.3f; + break; } + } } - else - { - r30 = true; + if (!x74_sfx) { + x74_sfx = CSfxManager::AddEmitter(SFXsfx0480 + (IsMediumOrLarge(*actor) ? 1 : 0), actor->GetTranslation(), + zeus::CVector3f::skZero, true, true, 0x7f, kInvalidAreaId); } - } - if (x74_sfx) - { - if (r31) - { - CSfxManager::UpdateEmitter(x74_sfx, xf8_.origin, zeus::CVector3f::skZero, 1.f); - } - else - { - CSfxManager::RemoveEmitter(x74_sfx); - x74_sfx.reset(); + x70_onFire = false; + } + for (auto& p : x8_thermalHotParticles) { + if (p.first) { + if (p.first->IsSystemDeletable()) + p.first.reset(); + else if (actor) + p.first->SetGlobalOrientAndTrans(actor->GetTransform()); + p.first->Update(dt); + r30 = true; + r31 = true; } + } + } else { + r30 = true; } - if (!r30) - { - Unlock(EDependency::OnFire); + } + if (x74_sfx) { + if (r31) { + CSfxManager::UpdateEmitter(x74_sfx, xf8_.origin, zeus::CVector3f::skZero, 1.f); + } else { + CSfxManager::RemoveEmitter(x74_sfx); + x74_sfx.reset(); } - return r30; + } + if (!r30) { + Unlock(EDependency::OnFire); + } + return r30; } -bool CActorModelParticles::CItem::UpdateAsh(float dt, CActor* actor, CStateManager& mgr) -{ - return false; -} +bool CActorModelParticles::CItem::UpdateAsh(float dt, CActor* actor, CStateManager& mgr) { return false; } -bool CActorModelParticles::CItem::sub_801e65bc(float dt, CActor* actor, CStateManager& mgr) -{ - return false; -} +bool CActorModelParticles::CItem::sub_801e65bc(float dt, CActor* actor, CStateManager& mgr) { return false; } -bool CActorModelParticles::CItem::UpdateFirePop(float dt, CActor* actor, CStateManager& mgr) -{ - return false; -} +bool CActorModelParticles::CItem::UpdateFirePop(float dt, CActor* actor, CStateManager& mgr) { return false; } -bool CActorModelParticles::CItem::UpdateElectric(float dt, CActor* actor, CStateManager& mgr) -{ - return false; -} +bool CActorModelParticles::CItem::UpdateElectric(float dt, CActor* actor, CStateManager& mgr) { return false; } -bool CActorModelParticles::CItem::sub_801e69f0(float dt, CActor* actor, CStateManager& mgr) -{ - return false; -} +bool CActorModelParticles::CItem::sub_801e69f0(float dt, CActor* actor, CStateManager& mgr) { return false; } -bool CActorModelParticles::CItem::sub_801e5e98(float dt, CActor* actor, CStateManager& mgr) -{ - return false; -} +bool CActorModelParticles::CItem::sub_801e5e98(float dt, CActor* actor, CStateManager& mgr) { return false; } -bool CActorModelParticles::CItem::UpdateIcePop(float dt, CActor* actor, CStateManager& mgr) -{ - return false; -} +bool CActorModelParticles::CItem::UpdateIcePop(float dt, CActor* actor, CStateManager& mgr) { return false; } -bool CActorModelParticles::CItem::Update(float dt, CStateManager& mgr) -{ - CActor* act = static_cast(mgr.ObjectById(x0_id)); - if (act && act->HasModelData() && !act->ModelData()->IsNull()) - { - xec_ = act->ModelData()->GetScale(); - xf8_ = act->GetTransform(); - x4_areaId = act->GetAreaIdAlways(); +bool CActorModelParticles::CItem::Update(float dt, CStateManager& mgr) { + CActor* act = static_cast(mgr.ObjectById(x0_id)); + if (act && act->HasModelData() && !act->ModelData()->IsNull()) { + xec_ = act->ModelData()->GetScale(); + xf8_ = act->GetTransform(); + x4_areaId = act->GetAreaIdAlways(); + } else { + x0_id = kInvalidUniqueId; + x84_ = 0; + xb0_ = -1; + if (xc0_particleElectric) + xc0_particleElectric->SetParticleEmission(false); + if (x74_sfx) { + CSfxManager::RemoveEmitter(x74_sfx); + x74_sfx.reset(); } - else - { - x0_id = kInvalidUniqueId; - x84_ = 0; - xb0_ = -1; - if (xc0_particleElectric) - xc0_particleElectric->SetParticleEmission(false); - if (x74_sfx) - { - CSfxManager::RemoveEmitter(x74_sfx); - x74_sfx.reset(); - } - x130_ -= dt; - if (x130_ <= 0.f) - return false; - } - bool ret = false; - if (UpdateOnFire(dt, act, mgr)) - ret = true; - if (UpdateAsh(dt, act, mgr)) - ret = true; - if (sub_801e65bc(dt, act, mgr)) - ret = true; - if (UpdateFirePop(dt, act, mgr)) - ret = true; - if (UpdateElectric(dt, act, mgr)) - ret = true; - if (sub_801e69f0(dt, act, mgr)) - ret = true; - if (sub_801e5e98(dt, act, mgr)) - ret = true; - if (UpdateIcePop(dt, act, mgr)) - ret = true; - return ret; + x130_ -= dt; + if (x130_ <= 0.f) + return false; + } + bool ret = false; + if (UpdateOnFire(dt, act, mgr)) + ret = true; + if (UpdateAsh(dt, act, mgr)) + ret = true; + if (sub_801e65bc(dt, act, mgr)) + ret = true; + if (UpdateFirePop(dt, act, mgr)) + ret = true; + if (UpdateElectric(dt, act, mgr)) + ret = true; + if (sub_801e69f0(dt, act, mgr)) + ret = true; + if (sub_801e5e98(dt, act, mgr)) + ret = true; + if (UpdateIcePop(dt, act, mgr)) + ret = true; + return ret; } -void CActorModelParticles::CItem::Lock(EDependency d) -{ - if (!(x134_lockDeps & (1 << int(d)))) - { - x128_parent.IncrementDependency(d); - x134_lockDeps |= (1 << int(d)); - } +void CActorModelParticles::CItem::Lock(EDependency d) { + if (!(x134_lockDeps & (1 << int(d)))) { + x128_parent.IncrementDependency(d); + x134_lockDeps |= (1 << int(d)); + } } -void CActorModelParticles::CItem::Unlock(EDependency d) -{ - if (x134_lockDeps & (1 << int(d))) - { - x128_parent.DecrementDependency(d); - x134_lockDeps &= ~(1 << int(d)); - } +void CActorModelParticles::CItem::Unlock(EDependency d) { + if (x134_lockDeps & (1 << int(d))) { + x128_parent.DecrementDependency(d); + x134_lockDeps &= ~(1 << int(d)); + } } -void CActorModelParticles::DecrementDependency(EDependency d) -{ - Dependency& dep = x50_dgrps[int(d)]; - dep.Decrement(); - if (dep.x10_refCount == 0) - { - xe4_bits &= ~(1 << int(d)); - xe6_bits2 &= ~(1 << int(d)); - xe5_bits1 &= ~(1 << int(d)); - } +void CActorModelParticles::DecrementDependency(EDependency d) { + Dependency& dep = x50_dgrps[int(d)]; + dep.Decrement(); + if (dep.x10_refCount == 0) { + xe4_bits &= ~(1 << int(d)); + xe6_bits2 &= ~(1 << int(d)); + xe5_bits1 &= ~(1 << int(d)); + } } -void CActorModelParticles::IncrementDependency(EDependency d) -{ - x50_dgrps[int(d)].Increment(); - if (!(xe6_bits2 & (1 << int(d)))) - xe4_bits |= (1 << int(d)); +void CActorModelParticles::IncrementDependency(EDependency d) { + x50_dgrps[int(d)].Increment(); + if (!(xe6_bits2 & (1 << int(d)))) + xe4_bits |= (1 << int(d)); } -static const char* ParticleDGRPs[] = -{ - "Effect_OnFire_DGRP", - "Effect_Ash_DGRP", - "Effect_IceBreak_DGRP", - "Effect_FirePop_DGRP", - "Effect_IcePop_DGRP", - "Effect_Electric_DGRP", +static const char* ParticleDGRPs[] = { + "Effect_OnFire_DGRP", "Effect_Ash_DGRP", "Effect_IceBreak_DGRP", + "Effect_FirePop_DGRP", "Effect_IcePop_DGRP", "Effect_Electric_DGRP", }; -CActorModelParticles::Dependency -CActorModelParticles::GetParticleDGRPTokens(const char* name) -{ - Dependency ret = {}; - TToken dgrp = g_SimplePool->GetObj(name); - const auto& vector = dgrp->GetObjectTagVector(); - ret.x0_tokens.reserve(vector.size()); - for (const SObjectTag& tag : vector) - ret.x0_tokens.push_back(g_SimplePool->GetObj(tag)); - return ret; +CActorModelParticles::Dependency CActorModelParticles::GetParticleDGRPTokens(const char* name) { + Dependency ret = {}; + TToken dgrp = g_SimplePool->GetObj(name); + const auto& vector = dgrp->GetObjectTagVector(); + ret.x0_tokens.reserve(vector.size()); + for (const SObjectTag& tag : vector) + ret.x0_tokens.push_back(g_SimplePool->GetObj(tag)); + return ret; } -void CActorModelParticles::LoadParticleDGRPs() -{ - for (int i=0 ; i<6 ; ++i) - x50_dgrps.push_back(GetParticleDGRPTokens(ParticleDGRPs[i])); +void CActorModelParticles::LoadParticleDGRPs() { + for (int i = 0; i < 6; ++i) + x50_dgrps.push_back(GetParticleDGRPTokens(ParticleDGRPs[i])); } -std::unique_ptr CActorModelParticles::MakeOnFireGen() const -{ - return std::make_unique(x18_onFire); +std::unique_ptr CActorModelParticles::MakeOnFireGen() const { + return std::make_unique(x18_onFire); } -std::unique_ptr CActorModelParticles::MakeAshGen() const -{ - return std::make_unique(x20_ash); +std::unique_ptr CActorModelParticles::MakeAshGen() const { return std::make_unique(x20_ash); } + +std::unique_ptr CActorModelParticles::MakeIceGen() const { + return std::make_unique(x28_iceBreak); } -std::unique_ptr CActorModelParticles::MakeIceGen() const -{ - return std::make_unique(x28_iceBreak); +std::unique_ptr CActorModelParticles::MakeFirePopGen() const { + return std::make_unique(x30_firePop); } -std::unique_ptr CActorModelParticles::MakeFirePopGen() const -{ - return std::make_unique(x30_firePop); +std::unique_ptr CActorModelParticles::MakeIcePopGen() const { + return std::make_unique(x38_icePop); } -std::unique_ptr CActorModelParticles::MakeIcePopGen() const -{ - return std::make_unique(x38_icePop); +std::unique_ptr CActorModelParticles::MakeElectricGen() const { + return std::make_unique(x40_electric); } -std::unique_ptr CActorModelParticles::MakeElectricGen() const -{ - return std::make_unique(x40_electric); +CActorModelParticles::CActorModelParticles() { + x18_onFire = g_SimplePool->GetObj("Effect_OnFire"); + x20_ash = g_SimplePool->GetObj("Effect_Ash"); + x28_iceBreak = g_SimplePool->GetObj("Effect_IceBreak"); + x30_firePop = g_SimplePool->GetObj("Effect_FirePop"); + x38_icePop = g_SimplePool->GetObj("Effect_IcePop"); + x40_electric = g_SimplePool->GetObj("Effect_Electric"); + x48_ashy = g_SimplePool->GetObj("TXTR_Ashy"); + LoadParticleDGRPs(); } -CActorModelParticles::CActorModelParticles() -{ - x18_onFire = g_SimplePool->GetObj("Effect_OnFire"); - x20_ash = g_SimplePool->GetObj("Effect_Ash"); - x28_iceBreak = g_SimplePool->GetObj("Effect_IceBreak"); - x30_firePop = g_SimplePool->GetObj("Effect_FirePop"); - x38_icePop = g_SimplePool->GetObj("Effect_IcePop"); - x40_electric = g_SimplePool->GetObj("Effect_Electric"); - x48_ashy = g_SimplePool->GetObj("TXTR_Ashy"); - LoadParticleDGRPs(); -} +void CActorModelParticles::AddStragglersToRenderer(const CStateManager& mgr) { + bool isNotCold = mgr.GetThermalDrawFlag() != EThermalDrawFlag::Cold; + bool isNotHot = mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot; -void CActorModelParticles::AddStragglersToRenderer(const CStateManager& mgr) -{ - bool isNotCold = mgr.GetThermalDrawFlag() != EThermalDrawFlag::Cold; - bool isNotHot = mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot; - - for (CItem& item : x0_items) - { - if (item.x4_areaId != kInvalidAreaId) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(item.x4_areaId); - if (!area->IsPostConstructed()) - continue; - CGameArea::EOcclusionState occState = area->GetPostConstructed()->x10dc_occlusionState; - if (occState == CGameArea::EOcclusionState::Occluded) - continue; - } - if (mgr.GetObjectById(item.x0_id) && - ((isNotCold && item.x12c_24_thermalCold) || (isNotHot && item.x12c_25_thermalHot))) - { - item.x12c_24_thermalCold = false; - item.x12c_25_thermalHot = false; - continue; - } - if (isNotCold) - { - /* Hot Draw */ - for (int i=0 ; i<8 ; ++i) - { - std::unique_ptr& gen = item.x8_thermalHotParticles[i].first; - if (gen) - g_Renderer->AddParticleGen(*gen); - } - if (mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot && item.x78_) - g_Renderer->AddParticleGen(*item.x78_); - if (item.xb8_) - g_Renderer->AddParticleGen(*item.xb8_); - if (item.xc0_particleElectric) - g_Renderer->AddParticleGen(*item.xc0_particleElectric); - } - if (isNotHot) - { - /* Cold Draw */ - for (std::unique_ptr& gen : item.x8c_thermalColdParticles) - g_Renderer->AddParticleGen(*gen); - if (item.xe4_) - g_Renderer->AddParticleGen(*item.xe4_); - } - if (isNotCold) - { - /* Thermal Reset */ - item.x12c_24_thermalCold = false; - item.x12c_25_thermalHot = false; - } + for (CItem& item : x0_items) { + if (item.x4_areaId != kInvalidAreaId) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(item.x4_areaId); + if (!area->IsPostConstructed()) + continue; + CGameArea::EOcclusionState occState = area->GetPostConstructed()->x10dc_occlusionState; + if (occState == CGameArea::EOcclusionState::Occluded) + continue; } + if (mgr.GetObjectById(item.x0_id) && + ((isNotCold && item.x12c_24_thermalCold) || (isNotHot && item.x12c_25_thermalHot))) { + item.x12c_24_thermalCold = false; + item.x12c_25_thermalHot = false; + continue; + } + if (isNotCold) { + /* Hot Draw */ + for (int i = 0; i < 8; ++i) { + std::unique_ptr& gen = item.x8_thermalHotParticles[i].first; + if (gen) + g_Renderer->AddParticleGen(*gen); + } + if (mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot && item.x78_) + g_Renderer->AddParticleGen(*item.x78_); + if (item.xb8_) + g_Renderer->AddParticleGen(*item.xb8_); + if (item.xc0_particleElectric) + g_Renderer->AddParticleGen(*item.xc0_particleElectric); + } + if (isNotHot) { + /* Cold Draw */ + for (std::unique_ptr& gen : item.x8c_thermalColdParticles) + g_Renderer->AddParticleGen(*gen); + if (item.xe4_) + g_Renderer->AddParticleGen(*item.xe4_); + } + if (isNotCold) { + /* Thermal Reset */ + item.x12c_24_thermalCold = false; + item.x12c_25_thermalHot = false; + } + } } -void CActorModelParticles::Update(float dt, CStateManager& mgr) -{ - -} +void CActorModelParticles::Update(float dt, CStateManager& mgr) {} void CActorModelParticles::PointGenerator(void* ctx, - const std::vector>& vn) -{ - reinterpret_cast(ctx)->GeneratePoints(vn); + const std::vector>& vn) { + reinterpret_cast(ctx)->GeneratePoints(vn); } -void CActorModelParticles::SetupHook(TUniqueId uid) -{ - auto search = FindSystem(uid); - if (search != x0_items.cend()) - CSkinnedModel::SetPointGeneratorFunc((void*)&*search, PointGenerator); +void CActorModelParticles::SetupHook(TUniqueId uid) { + auto search = FindSystem(uid); + if (search != x0_items.cend()) + CSkinnedModel::SetPointGeneratorFunc((void*)&*search, PointGenerator); } -std::list::const_iterator CActorModelParticles::FindSystem(TUniqueId uid) const -{ - for (auto it = x0_items.cbegin() ; it != x0_items.cend() ; ++it) - if (it->x0_id == uid) - return it; - return x0_items.cend(); +std::list::const_iterator CActorModelParticles::FindSystem(TUniqueId uid) const { + for (auto it = x0_items.cbegin(); it != x0_items.cend(); ++it) + if (it->x0_id == uid) + return it; + return x0_items.cend(); } -std::list::iterator CActorModelParticles::FindOrCreateSystem(CActor& act) -{ - if (act.GetPointGeneratorParticles()) - { - for (auto it = x0_items.begin() ; it != x0_items.end() ; ++it) - if (it->x0_id == act.GetUniqueId()) - return it; - } +std::list::iterator CActorModelParticles::FindOrCreateSystem(CActor& act) { + if (act.GetPointGeneratorParticles()) { + for (auto it = x0_items.begin(); it != x0_items.end(); ++it) + if (it->x0_id == act.GetUniqueId()) + return it; + } - act.SetPointGeneratorParticles(true); - return x0_items.emplace(x0_items.end(), act, *this); + act.SetPointGeneratorParticles(true); + return x0_items.emplace(x0_items.end(), act, *this); } -void CActorModelParticles::StartIce(CActor& act) -{ - auto iter = FindOrCreateSystem(act); - iter->Lock(EDependency::Ash); +void CActorModelParticles::StartIce(CActor& act) { + auto iter = FindOrCreateSystem(act); + iter->Lock(EDependency::Ash); } -void CActorModelParticles::StartElectric(CActor& act) -{ - auto iter = FindOrCreateSystem(act); - if (iter->xc0_particleElectric && !iter->xc0_particleElectric->GetParticleEmission()) - iter->xc0_particleElectric->SetParticleEmission(true); +void CActorModelParticles::StartElectric(CActor& act) { + auto iter = FindOrCreateSystem(act); + if (iter->xc0_particleElectric && !iter->xc0_particleElectric->GetParticleEmission()) + iter->xc0_particleElectric->SetParticleEmission(true); } -void CActorModelParticles::StopElectric(CActor& act) -{ - if (act.GetPointGeneratorParticles()) - { - auto iter = FindSystem(act.GetUniqueId()); - if (iter != x0_items.cend() && iter->xc0_particleElectric) - iter->xc0_particleElectric->SetParticleEmission(false); - } -} - -void CActorModelParticles::sub_801e51d0(CActor& act) -{ - auto iter = FindOrCreateSystem(act); - if (!iter->xc0_particleElectric) - iter->Lock(EDependency::IcePop); - else - { - if (!iter->xc0_particleElectric->GetParticleEmission()) - iter->xc0_particleElectric->SetParticleEmission(true); - } -} - -void CActorModelParticles::StopThermalHotParticles(CActor& act) -{ - if (act.GetPointGeneratorParticles()) - { - auto iter = FindSystem(act.GetUniqueId()); - if (iter != x0_items.cend()) - { - for (auto& part : iter->x8_thermalHotParticles) - if (part.first) - part.first->SetParticleEmission(false); - } - } -} - -void CActorModelParticles::StartBurnDeath(CActor& act) -{ - auto iter = FindOrCreateSystem(act); - u16 sfx = SFXeff_x_smallburndeath_lp_00 - s16(IsMediumOrLarge(act)); - CSfxManager::AddEmitter(sfx, act.GetTranslation(), zeus::CVector3f::skZero, true, false, 0x7f, kInvalidAreaId); - iter->xdc_ashy.Lock(); -} - -void CActorModelParticles::EnsureElectricLoaded(CActor& act) -{ - auto iter = FindOrCreateSystem(act); - iter->Lock(EDependency::Electric); -} - -void CActorModelParticles::EnsureFirePopLoaded(CActor& act) -{ - auto iter = FindOrCreateSystem(act); - iter->Lock(EDependency::FirePop); -} - -void CActorModelParticles::EnsureIceBreakLoaded(CActor& act) -{ - auto iter = FindOrCreateSystem(act); - iter->Lock(EDependency::IceBreak); -} - -void CActorModelParticles::LightDudeOnFire(CActor& act) -{ - auto iter = FindOrCreateSystem(act); - iter->Lock(EDependency::OnFire); - if (iter->x6c_onFireDelayTimer <= 0.f) - iter->x70_onFire = true; -} - -const CTexture* CActorModelParticles::GetAshyTexture(const CActor& act) -{ +void CActorModelParticles::StopElectric(CActor& act) { + if (act.GetPointGeneratorParticles()) { auto iter = FindSystem(act.GetUniqueId()); - if (iter != x0_items.cend() && iter->xdc_ashy && iter->xdc_ashy.IsLoaded()) - { - iter->xdc_ashy->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge); - return iter->xdc_ashy.GetObj(); + if (iter != x0_items.cend() && iter->xc0_particleElectric) + iter->xc0_particleElectric->SetParticleEmission(false); + } +} + +void CActorModelParticles::sub_801e51d0(CActor& act) { + auto iter = FindOrCreateSystem(act); + if (!iter->xc0_particleElectric) + iter->Lock(EDependency::IcePop); + else { + if (!iter->xc0_particleElectric->GetParticleEmission()) + iter->xc0_particleElectric->SetParticleEmission(true); + } +} + +void CActorModelParticles::StopThermalHotParticles(CActor& act) { + if (act.GetPointGeneratorParticles()) { + auto iter = FindSystem(act.GetUniqueId()); + if (iter != x0_items.cend()) { + for (auto& part : iter->x8_thermalHotParticles) + if (part.first) + part.first->SetParticleEmission(false); } - return nullptr; + } } -void CActorModelParticles::AddRainSplashGenerator(CActor& act, CStateManager& mgr, u32 maxSplashes, - u32 genRate, float minZ) -{ - auto it = FindOrCreateSystem(act); - if (it->xd4_rainSplashGenerator) - return; - - if (act.GetModelData() && !act.GetModelData()->IsNull()) - it->xd4_rainSplashGenerator = std::make_unique(act.GetModelData()->GetScale(), - maxSplashes, genRate, minZ, 0.1875f); +void CActorModelParticles::StartBurnDeath(CActor& act) { + auto iter = FindOrCreateSystem(act); + u16 sfx = SFXeff_x_smallburndeath_lp_00 - s16(IsMediumOrLarge(act)); + CSfxManager::AddEmitter(sfx, act.GetTranslation(), zeus::CVector3f::skZero, true, false, 0x7f, kInvalidAreaId); + iter->xdc_ashy.Lock(); } -void CActorModelParticles::RemoveRainSplashGenerator(CActor& act) -{ - auto it = FindOrCreateSystem(act); - it->xd4_rainSplashGenerator.reset(); +void CActorModelParticles::EnsureElectricLoaded(CActor& act) { + auto iter = FindOrCreateSystem(act); + iter->Lock(EDependency::Electric); } -void CActorModelParticles::Render(const CActor& actor) const -{ - +void CActorModelParticles::EnsureFirePopLoaded(CActor& act) { + auto iter = FindOrCreateSystem(act); + iter->Lock(EDependency::FirePop); } +void CActorModelParticles::EnsureIceBreakLoaded(CActor& act) { + auto iter = FindOrCreateSystem(act); + iter->Lock(EDependency::IceBreak); } + +void CActorModelParticles::LightDudeOnFire(CActor& act) { + auto iter = FindOrCreateSystem(act); + iter->Lock(EDependency::OnFire); + if (iter->x6c_onFireDelayTimer <= 0.f) + iter->x70_onFire = true; +} + +const CTexture* CActorModelParticles::GetAshyTexture(const CActor& act) { + auto iter = FindSystem(act.GetUniqueId()); + if (iter != x0_items.cend() && iter->xdc_ashy && iter->xdc_ashy.IsLoaded()) { + iter->xdc_ashy->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge); + return iter->xdc_ashy.GetObj(); + } + return nullptr; +} + +void CActorModelParticles::AddRainSplashGenerator(CActor& act, CStateManager& mgr, u32 maxSplashes, u32 genRate, + float minZ) { + auto it = FindOrCreateSystem(act); + if (it->xd4_rainSplashGenerator) + return; + + if (act.GetModelData() && !act.GetModelData()->IsNull()) + it->xd4_rainSplashGenerator = + std::make_unique(act.GetModelData()->GetScale(), maxSplashes, genRate, minZ, 0.1875f); +} + +void CActorModelParticles::RemoveRainSplashGenerator(CActor& act) { + auto it = FindOrCreateSystem(act); + it->xd4_rainSplashGenerator.reset(); +} + +void CActorModelParticles::Render(const CActor& actor) const {} + +} // namespace urde diff --git a/Runtime/World/CActorModelParticles.hpp b/Runtime/World/CActorModelParticles.hpp index cb99e34fc..e0ddad7aa 100644 --- a/Runtime/World/CActorModelParticles.hpp +++ b/Runtime/World/CActorModelParticles.hpp @@ -8,8 +8,7 @@ #include "Particle/CParticleSwoosh.hpp" #include "Graphics/CRainSplashGenerator.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CEntity; class CElementGen; @@ -18,160 +17,142 @@ class CGenDescription; class CActor; class CScriptPlayerActor; -class CActorModelParticles -{ +class CActorModelParticles { public: - enum class EDependency - { - OnFire, - Ash, - IceBreak, - FirePop, - IcePop, - Electric - }; + enum class EDependency { OnFire, Ash, IceBreak, FirePop, IcePop, Electric }; - class CItem - { - friend class CActorModelParticles; - TUniqueId x0_id; - TAreaId x4_areaId; - rstl::reserved_vector, u32>, 8> x8_thermalHotParticles; - float x6c_onFireDelayTimer = 0.f; - bool x70_onFire = false; - CSfxHandle x74_sfx; - std::unique_ptr x78_; - u32 x80_ = 0; - s32 x84_ = -1; - u32 x88_seed1 = 99; - rstl::reserved_vector, 4> x8c_thermalColdParticles; - s32 xb0_ = -1; - u32 xb4_seed2 = 99; - std::unique_ptr xb8_; - std::unique_ptr xc0_particleElectric; - u32 xc8_ = 0; - u32 xcc_seed3 = 99; - zeus::CColor xd0_; - std::unique_ptr xd4_rainSplashGenerator; - TToken xdc_ashy; - std::unique_ptr xe4_; - zeus::CVector3f xec_ = zeus::CVector3f::skOne; - zeus::CTransform xf8_; - CActorModelParticles& x128_parent; - union - { - struct - { - bool x12c_24_thermalCold : 1; - bool x12c_25_thermalHot : 1; - }; - u16 _dummy = 0; - }; - float x130_ = 10.f; - u8 x134_lockDeps = 0; - void sub_801e59a8(EDependency i); - bool UpdateOnFire(float dt, CActor* actor, CStateManager& mgr); - bool UpdateAsh(float dt, CActor* actor, CStateManager& mgr); - bool sub_801e65bc(float dt, CActor* actor, CStateManager& mgr); - bool UpdateFirePop(float dt, CActor* actor, CStateManager& mgr); - bool UpdateElectric(float dt, CActor* actor, CStateManager& mgr); - bool sub_801e69f0(float dt, CActor* actor, CStateManager& mgr); - bool sub_801e5e98(float dt, CActor* actor, CStateManager& mgr); - bool UpdateIcePop(float dt, CActor* actor, CStateManager& mgr); - public: - CItem(const CEntity& ent, CActorModelParticles& parent); - void GeneratePoints(const std::vector>& vn); - bool Update(float dt, CStateManager& mgr); - void Lock(EDependency i); - void Unlock(EDependency i); + class CItem { + friend class CActorModelParticles; + TUniqueId x0_id; + TAreaId x4_areaId; + rstl::reserved_vector, u32>, 8> x8_thermalHotParticles; + float x6c_onFireDelayTimer = 0.f; + bool x70_onFire = false; + CSfxHandle x74_sfx; + std::unique_ptr x78_; + u32 x80_ = 0; + s32 x84_ = -1; + u32 x88_seed1 = 99; + rstl::reserved_vector, 4> x8c_thermalColdParticles; + s32 xb0_ = -1; + u32 xb4_seed2 = 99; + std::unique_ptr xb8_; + std::unique_ptr xc0_particleElectric; + u32 xc8_ = 0; + u32 xcc_seed3 = 99; + zeus::CColor xd0_; + std::unique_ptr xd4_rainSplashGenerator; + TToken xdc_ashy; + std::unique_ptr xe4_; + zeus::CVector3f xec_ = zeus::CVector3f::skOne; + zeus::CTransform xf8_; + CActorModelParticles& x128_parent; + union { + struct { + bool x12c_24_thermalCold : 1; + bool x12c_25_thermalHot : 1; + }; + u16 _dummy = 0; }; + float x130_ = 10.f; + u8 x134_lockDeps = 0; + void sub_801e59a8(EDependency i); + bool UpdateOnFire(float dt, CActor* actor, CStateManager& mgr); + bool UpdateAsh(float dt, CActor* actor, CStateManager& mgr); + bool sub_801e65bc(float dt, CActor* actor, CStateManager& mgr); + bool UpdateFirePop(float dt, CActor* actor, CStateManager& mgr); + bool UpdateElectric(float dt, CActor* actor, CStateManager& mgr); + bool sub_801e69f0(float dt, CActor* actor, CStateManager& mgr); + bool sub_801e5e98(float dt, CActor* actor, CStateManager& mgr); + bool UpdateIcePop(float dt, CActor* actor, CStateManager& mgr); + + public: + CItem(const CEntity& ent, CActorModelParticles& parent); + void GeneratePoints(const std::vector>& vn); + bool Update(float dt, CStateManager& mgr); + void Lock(EDependency i); + void Unlock(EDependency i); + }; private: - friend class CItem; - std::list x0_items; - TToken x18_onFire; - TToken x20_ash; - TToken x28_iceBreak; - TToken x30_firePop; - TToken x38_icePop; - TToken x40_electric; - TToken x48_ashy; - struct Dependency - { - std::vector x0_tokens; - int x10_refCount = 0; - bool x14_loaded = false; - void Increment() - { - ++x10_refCount; - if (x10_refCount == 1) - Load(); - } - void Decrement() - { - --x10_refCount; - if (x10_refCount <= 0) - Unload(); - } - void Load() - { - bool loading = false; - for (CToken& tok : x0_tokens) - { - tok.Lock(); - if (!tok.IsLoaded()) - loading = true; - } - if (!loading) - x14_loaded = true; - } - void Unload() - { - for (CToken& tok : x0_tokens) - tok.Unlock(); - x14_loaded = false; - } - }; - rstl::reserved_vector x50_dgrps; - u8 xe4_bits = 0; - u8 xe5_bits1 = 0; - u8 xe6_bits2 = 0; + friend class CItem; + std::list x0_items; + TToken x18_onFire; + TToken x20_ash; + TToken x28_iceBreak; + TToken x30_firePop; + TToken x38_icePop; + TToken x40_electric; + TToken x48_ashy; + struct Dependency { + std::vector x0_tokens; + int x10_refCount = 0; + bool x14_loaded = false; + void Increment() { + ++x10_refCount; + if (x10_refCount == 1) + Load(); + } + void Decrement() { + --x10_refCount; + if (x10_refCount <= 0) + Unload(); + } + void Load() { + bool loading = false; + for (CToken& tok : x0_tokens) { + tok.Lock(); + if (!tok.IsLoaded()) + loading = true; + } + if (!loading) + x14_loaded = true; + } + void Unload() { + for (CToken& tok : x0_tokens) + tok.Unlock(); + x14_loaded = false; + } + }; + rstl::reserved_vector x50_dgrps; + u8 xe4_bits = 0; + u8 xe5_bits1 = 0; + u8 xe6_bits2 = 0; - Dependency GetParticleDGRPTokens(const char* name); - void LoadParticleDGRPs(); + Dependency GetParticleDGRPTokens(const char* name); + void LoadParticleDGRPs(); - std::unique_ptr MakeOnFireGen() const; - std::unique_ptr MakeAshGen() const; - std::unique_ptr MakeIceGen() const; - std::unique_ptr MakeFirePopGen() const; - std::unique_ptr MakeIcePopGen() const; - std::unique_ptr MakeElectricGen() const; + std::unique_ptr MakeOnFireGen() const; + std::unique_ptr MakeAshGen() const; + std::unique_ptr MakeIceGen() const; + std::unique_ptr MakeFirePopGen() const; + std::unique_ptr MakeIcePopGen() const; + std::unique_ptr MakeElectricGen() const; + + void DecrementDependency(EDependency d); + void IncrementDependency(EDependency d); - void DecrementDependency(EDependency d); - void IncrementDependency(EDependency d); public: - CActorModelParticles(); - static void PointGenerator(void* item, const std::vector>& vn); - void AddStragglersToRenderer(const CStateManager& mgr); - void Update(float dt, CStateManager& mgr); - void SetupHook(TUniqueId uid); - std::list::const_iterator FindSystem(TUniqueId uid) const; - std::list::iterator FindOrCreateSystem(CActor& act); - void StartIce(CActor& actor); - void AddRainSplashGenerator(CActor& act, CStateManager& mgr, u32 maxSplashes, - u32 genRate, float minZ); - void RemoveRainSplashGenerator(CActor& act); - void Render(const CActor& actor) const; - void StartElectric(CActor& act); - void StopElectric(CActor& act); - void sub_801e51d0(CActor& act); - void StopThermalHotParticles(CActor& act); - void StartBurnDeath(CActor& act); - void EnsureElectricLoaded(CActor& act); - void EnsureFirePopLoaded(CActor& act); - void EnsureIceBreakLoaded(CActor& act); - void LightDudeOnFire(CActor& act); - const CTexture* GetAshyTexture(const CActor& act); + CActorModelParticles(); + static void PointGenerator(void* item, const std::vector>& vn); + void AddStragglersToRenderer(const CStateManager& mgr); + void Update(float dt, CStateManager& mgr); + void SetupHook(TUniqueId uid); + std::list::const_iterator FindSystem(TUniqueId uid) const; + std::list::iterator FindOrCreateSystem(CActor& act); + void StartIce(CActor& actor); + void AddRainSplashGenerator(CActor& act, CStateManager& mgr, u32 maxSplashes, u32 genRate, float minZ); + void RemoveRainSplashGenerator(CActor& act); + void Render(const CActor& actor) const; + void StartElectric(CActor& act); + void StopElectric(CActor& act); + void sub_801e51d0(CActor& act); + void StopThermalHotParticles(CActor& act); + void StartBurnDeath(CActor& act); + void EnsureElectricLoaded(CActor& act); + void EnsureFirePopLoaded(CActor& act); + void EnsureIceBreakLoaded(CActor& act); + void LightDudeOnFire(CActor& act); + const CTexture* GetAshyTexture(const CActor& act); }; -} - +} // namespace urde diff --git a/Runtime/World/CActorParameters.hpp b/Runtime/World/CActorParameters.hpp index 59c98a6b6..94935b0de 100644 --- a/Runtime/World/CActorParameters.hpp +++ b/Runtime/World/CActorParameters.hpp @@ -4,76 +4,68 @@ #include "CScannableParameters.hpp" #include "CVisorParameters.hpp" -namespace urde -{ +namespace urde { -class CActorParameters -{ - friend class ScriptLoader; - friend class CActor; - friend class CScriptActor; - CLightParameters x0_lightParms; - CScannableParameters x40_scanParms; - std::pair x44_xrayAssets = {}; - std::pair x4c_thermalAssets = {}; - CVisorParameters x54_visorParms; - union - { - struct - { - bool x58_24_globalTimeProvider : 1; - bool x58_25_thermalHeat : 1; - bool x58_26_renderUnsorted : 1; - bool x58_27_noSortThermal : 1; - }; - u32 _dummy = 0; +class CActorParameters { + friend class ScriptLoader; + friend class CActor; + friend class CScriptActor; + CLightParameters x0_lightParms; + CScannableParameters x40_scanParms; + std::pair x44_xrayAssets = {}; + std::pair x4c_thermalAssets = {}; + CVisorParameters x54_visorParms; + union { + struct { + bool x58_24_globalTimeProvider : 1; + bool x58_25_thermalHeat : 1; + bool x58_26_renderUnsorted : 1; + bool x58_27_noSortThermal : 1; }; - float x5c_fadeInTime = 0.f; - float x60_fadeOutTime = 0.f; - float x64_thermalMag = 0.f; + u32 _dummy = 0; + }; + float x5c_fadeInTime = 0.f; + float x60_fadeOutTime = 0.f; + float x64_thermalMag = 0.f; public: - CActorParameters() : x58_24_globalTimeProvider(true), x58_25_thermalHeat(false), - x58_26_renderUnsorted(false), x58_27_noSortThermal(false) {} - CActorParameters(const CLightParameters& lightParms, const CScannableParameters& scanParms, - const std::pair& xrayAssets, - const std::pair& thermalAssets, - const CVisorParameters& visorParms, bool globalTimeProvider, bool thermalHeat, - bool renderUnsorted, bool noSortThermal, - float fadeInTime, float fadeOutTime, float thermalMag) - : x0_lightParms(lightParms) - , x40_scanParms(scanParms) - , x44_xrayAssets(xrayAssets) - , x4c_thermalAssets(thermalAssets) - , x54_visorParms(visorParms) - , x58_24_globalTimeProvider(globalTimeProvider) - , x58_25_thermalHeat(thermalHeat) - , x58_26_renderUnsorted(renderUnsorted) - , x58_27_noSortThermal(noSortThermal) - , x5c_fadeInTime(fadeInTime) - , x60_fadeOutTime(fadeOutTime) - , x64_thermalMag(thermalMag) - { - } - CActorParameters Scannable(const CScannableParameters& sParms) const - { - CActorParameters aParms = *this; - aParms.x40_scanParms = sParms; - return aParms; - } + CActorParameters() + : x58_24_globalTimeProvider(true) + , x58_25_thermalHeat(false) + , x58_26_renderUnsorted(false) + , x58_27_noSortThermal(false) {} + CActorParameters(const CLightParameters& lightParms, const CScannableParameters& scanParms, + const std::pair& xrayAssets, const std::pair& thermalAssets, + const CVisorParameters& visorParms, bool globalTimeProvider, bool thermalHeat, bool renderUnsorted, + bool noSortThermal, float fadeInTime, float fadeOutTime, float thermalMag) + : x0_lightParms(lightParms) + , x40_scanParms(scanParms) + , x44_xrayAssets(xrayAssets) + , x4c_thermalAssets(thermalAssets) + , x54_visorParms(visorParms) + , x58_24_globalTimeProvider(globalTimeProvider) + , x58_25_thermalHeat(thermalHeat) + , x58_26_renderUnsorted(renderUnsorted) + , x58_27_noSortThermal(noSortThermal) + , x5c_fadeInTime(fadeInTime) + , x60_fadeOutTime(fadeOutTime) + , x64_thermalMag(thermalMag) {} + CActorParameters Scannable(const CScannableParameters& sParms) const { + CActorParameters aParms = *this; + aParms.x40_scanParms = sParms; + return aParms; + } - static CActorParameters None() { return CActorParameters(); } - CActorParameters HotInThermal(bool hot) const - { - CActorParameters ret = *this; - ret.x58_25_thermalHeat = hot; - return ret; - } - void SetVisorParameters(const CVisorParameters& vParams) { x54_visorParms = vParams; } - const CVisorParameters& GetVisorParameters() const { return x54_visorParms; } - const CLightParameters& GetLightParameters() const { return x0_lightParms; } - bool HasThermalHeat() const { return x58_25_thermalHeat; } - float GetThermalMag() const { return x64_thermalMag; } + static CActorParameters None() { return CActorParameters(); } + CActorParameters HotInThermal(bool hot) const { + CActorParameters ret = *this; + ret.x58_25_thermalHeat = hot; + return ret; + } + void SetVisorParameters(const CVisorParameters& vParams) { x54_visorParms = vParams; } + const CVisorParameters& GetVisorParameters() const { return x54_visorParms; } + const CLightParameters& GetLightParameters() const { return x0_lightParms; } + bool HasThermalHeat() const { return x58_25_thermalHeat; } + float GetThermalMag() const { return x64_thermalMag; } }; -} - +} // namespace urde diff --git a/Runtime/World/CAi.cpp b/Runtime/World/CAi.cpp index dd71815a8..9d13905ea 100644 --- a/Runtime/World/CAi.cpp +++ b/Runtime/World/CAi.cpp @@ -6,86 +6,75 @@ #include "CSimplePool.hpp" #include "CScriptWater.hpp" -namespace urde -{ +namespace urde { -static CMaterialList MakeAiMaterialList(const CMaterialList& in) -{ - CMaterialList ret = in; - ret.Add(EMaterialTypes::AIBlock); - ret.Add(EMaterialTypes::CameraPassthrough); - return ret; +static CMaterialList MakeAiMaterialList(const CMaterialList& in) { + CMaterialList ret = in; + ret.Add(EMaterialTypes::AIBlock); + ret.Add(EMaterialTypes::CameraPassthrough); + return ret; } CAi::CAi(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& box, float mass, const CHealthInfo& hInfo, - const CDamageVulnerability& dmgVuln, const CMaterialList& list, CAssetId fsm, const CActorParameters& actorParams, - float stepUp, float stepDown) + const CDamageVulnerability& dmgVuln, const CMaterialList& list, CAssetId fsm, + const CActorParameters& actorParams, float stepUp, float stepDown) : CPhysicsActor(uid, active, name, info, xf, std::move(mData), MakeAiMaterialList(list), box, SMoverData(mass), actorParams, stepUp, stepDown) , x258_healthInfo(hInfo) , x260_damageVulnerability(dmgVuln) -, x2c8_stateMachine(g_SimplePool->GetObj({FOURCC('AFSM'), fsm})) -{ - _CreateShadow(); +, x2c8_stateMachine(g_SimplePool->GetObj({FOURCC('AFSM'), fsm})) { + _CreateShadow(); - if (x94_simpleShadow) - { - CreateShadow(true); - x94_simpleShadow->SetAlwaysCalculateRadius(false); - } + if (x94_simpleShadow) { + CreateShadow(true); + x94_simpleShadow->SetAlwaysCalculateRadius(false); + } - if (x90_actorLights) - x90_actorLights->SetCastShadows(true); + if (x90_actorLights) + x90_actorLights->SetCastShadows(true); } -void CAi::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::InitializedInArea) - { - CMaterialList exclude = GetMaterialFilter().GetExcludeList(); - CMaterialList include = GetMaterialFilter().GetIncludeList(); - include.Add(EMaterialTypes::AIBlock); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); - } +void CAi::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::InitializedInArea) { + CMaterialList exclude = GetMaterialFilter().GetExcludeList(); + CMaterialList include = GetMaterialFilter().GetIncludeList(); + include.Add(EMaterialTypes::AIBlock); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); + } - CActor::AcceptScriptMsg(msg, uid, mgr); + CActor::AcceptScriptMsg(msg, uid, mgr); } EWeaponCollisionResponseTypes CAi::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const urde::CWeaponMode&, urde::EProjectileAttrib) const -{ - return EWeaponCollisionResponseTypes::EnemyNormal; + const urde::CWeaponMode&, urde::EProjectileAttrib) const { + return EWeaponCollisionResponseTypes::EnemyNormal; } -void CAi::FluidFXThink(EFluidState state, CScriptWater& water, urde::CStateManager& mgr) -{ - if (state == EFluidState::EnteredFluid || state == EFluidState::LeftFluid) - { - float dt = mgr.GetFluidPlaneManager()->GetLastSplashDeltaTime(GetUniqueId()); - if (dt >= 0.02f) - { - float vel = (0.5f * GetMass()) * GetVelocity().magSquared(); +void CAi::FluidFXThink(EFluidState state, CScriptWater& water, urde::CStateManager& mgr) { + if (state == EFluidState::EnteredFluid || state == EFluidState::LeftFluid) { + float dt = mgr.GetFluidPlaneManager()->GetLastSplashDeltaTime(GetUniqueId()); + if (dt >= 0.02f) { + float vel = (0.5f * GetMass()) * GetVelocity().magSquared(); - if (vel > 500.f) - { - zeus::CVector3f pos = x34_transform.origin; - pos.z() = float(water.GetTriggerBoundsWR().max.z()); - mgr.GetFluidPlaneManager()->CreateSplash(GetUniqueId(), mgr, water, pos, - 0.1f + ((0.4f * zeus::min(vel, 30000.f) - 500.f) / 29500.f), - true); - } - } + if (vel > 500.f) { + zeus::CVector3f pos = x34_transform.origin; + pos.z() = float(water.GetTriggerBoundsWR().max.z()); + mgr.GetFluidPlaneManager()->CreateSplash(GetUniqueId(), mgr, water, pos, + 0.1f + ((0.4f * zeus::min(vel, 30000.f) - 500.f) / 29500.f), true); + } } + } - if (mgr.GetFluidPlaneManager()->GetLastRippleDeltaTime(GetUniqueId()) < (GetHealthInfo(mgr)->GetHP() > 0.f ? 0.2f : 0.7f)) - return; + if (mgr.GetFluidPlaneManager()->GetLastRippleDeltaTime(GetUniqueId()) < + (GetHealthInfo(mgr)->GetHP() > 0.f ? 0.2f : 0.7f)) + return; - zeus::CVector3f pos = x34_transform.origin; - zeus::CVector3f center = pos; - center.z() = float(water.GetTriggerBoundsWR().max.z()); - pos.normalize(); - water.GetFluidPlane().AddRipple(GetMass(), GetUniqueId(), center, GetVelocity(), water, mgr, pos); + zeus::CVector3f pos = x34_transform.origin; + zeus::CVector3f center = pos; + center.z() = float(water.GetTriggerBoundsWR().max.z()); + pos.normalize(); + water.GetFluidPlane().AddRipple(GetMass(), GetUniqueId(), center, GetVelocity(), water, mgr, pos); } CAiStateFunc CAi::GetStateFunc(const char* func) { return m_FuncMap->GetStateFunc(func); } @@ -95,4 +84,4 @@ CAiTriggerFunc CAi::GetTrigerFunc(const char* func) { return m_FuncMap->GetTrigg const CStateMachine* CAi::GetStateMachine() const { return x2c8_stateMachine.GetObj(); } void CAi::CreateFuncLookup(CAiFuncMap* funcMap) { m_FuncMap = funcMap; } CAiFuncMap* CAi::m_FuncMap = nullptr; -} +} // namespace urde diff --git a/Runtime/World/CAi.hpp b/Runtime/World/CAi.hpp index f4909f227..1cdfac67e 100644 --- a/Runtime/World/CAi.hpp +++ b/Runtime/World/CAi.hpp @@ -12,180 +12,173 @@ #include "zeus/zeus.hpp" -namespace urde -{ +namespace urde { -enum class EListenNoiseType -{ - PlayerFire, - BombExplode, - ProjectileExplode -}; +enum class EListenNoiseType { PlayerFire, BombExplode, ProjectileExplode }; class CAiFuncMap; class CStateManager; class CScriptWater; class CTeamAiRole; -class CAi : public CPhysicsActor -{ - static CAiFuncMap* m_FuncMap; - CHealthInfo x258_healthInfo; - CDamageVulnerability x260_damageVulnerability; - TLockedToken x2c8_stateMachine; -public: +class CAi : public CPhysicsActor { + static CAiFuncMap* m_FuncMap; + CHealthInfo x258_healthInfo; + CDamageVulnerability x260_damageVulnerability; + TLockedToken x2c8_stateMachine; +public: CAi(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& box, float mass, const CHealthInfo& hInfo, const CDamageVulnerability&, const CMaterialList& list, CAssetId fsm, const CActorParameters&, float f1, float f2); - static void CreateFuncLookup(CAiFuncMap* funcMap); - static CAiStateFunc GetStateFunc(const char* func); - static CAiTriggerFunc GetTrigerFunc(const char* func); + static void CreateFuncLookup(CAiFuncMap* funcMap); + static CAiStateFunc GetStateFunc(const char* func); + static CAiTriggerFunc GetTrigerFunc(const char* func); - const CStateMachine* GetStateMachine() const; + const CStateMachine* GetStateMachine() const; - virtual void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - virtual CHealthInfo* HealthInfo(CStateManager&) { return &x258_healthInfo; } - virtual void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state)=0; - virtual void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, - EKnockBackType type, bool inDeferred, float magnitude)=0; - virtual const CDamageVulnerability* GetDamageVulnerability() const { return &x260_damageVulnerability; } - virtual void TakeDamage(const zeus::CVector3f& direction, float magnitude) {} - virtual bool CanBeShot(const CStateManager&, int) { return true; } - virtual bool IsListening() const { return false; } - virtual bool Listen(const zeus::CVector3f&, EListenNoiseType) { return 0; } - virtual EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const; - void FluidFXThink(EFluidState, CScriptWater&, CStateManager&); + virtual void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + virtual CHealthInfo* HealthInfo(CStateManager&) { return &x258_healthInfo; } + virtual void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state) = 0; + virtual void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, EKnockBackType type, + bool inDeferred, float magnitude) = 0; + virtual const CDamageVulnerability* GetDamageVulnerability() const { return &x260_damageVulnerability; } + virtual void TakeDamage(const zeus::CVector3f& direction, float magnitude) {} + virtual bool CanBeShot(const CStateManager&, int) { return true; } + virtual bool IsListening() const { return false; } + virtual bool Listen(const zeus::CVector3f&, EListenNoiseType) { return 0; } + virtual EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, + const CWeaponMode&, EProjectileAttrib) const; + void FluidFXThink(EFluidState, CScriptWater&, CStateManager&); - virtual zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const - { return x34_transform.origin; } - virtual void Patrol(CStateManager&, EStateMsg, float) {} - virtual void FollowPattern(CStateManager&, EStateMsg, float) {} - virtual void Dead(CStateManager&, EStateMsg, float) {} - virtual void PathFind(CStateManager&, EStateMsg, float) {} - virtual void Start(CStateManager&, EStateMsg, float) {} - virtual void SelectTarget(CStateManager&, EStateMsg, float) {} - virtual void TargetPatrol(CStateManager&, EStateMsg, float) {} - virtual void TargetPlayer(CStateManager&, EStateMsg, float) {} - virtual void TargetCover(CStateManager&, EStateMsg, float) {} - virtual void Halt(CStateManager&, EStateMsg, float) {} - virtual void Walk(CStateManager&, EStateMsg, float) {} - virtual void Run(CStateManager&, EStateMsg, float) {} - virtual void Generate(CStateManager&, EStateMsg, float) {} - virtual void Deactivate(CStateManager&, EStateMsg, float) {} - virtual void Attack(CStateManager&, EStateMsg, float) {} - virtual void LoopedAttack(CStateManager&, EStateMsg, float) {} - virtual void JumpBack(CStateManager&, EStateMsg, float) {} - virtual void DoubleSnap(CStateManager&, EStateMsg, float) {} - virtual void Shuffle(CStateManager&, EStateMsg, float) {} - virtual void TurnAround(CStateManager&, EStateMsg, float) {} - virtual void Skid(CStateManager&, EStateMsg, float) {} - virtual void Active(CStateManager&, EStateMsg, float) {} - virtual void InActive(CStateManager&, EStateMsg, float) {} - virtual void CoverAttack(CStateManager&, EStateMsg, float) {} - virtual void Crouch(CStateManager&, EStateMsg, float) {} - virtual void FadeIn(CStateManager&, EStateMsg, float) {} - virtual void FadeOut(CStateManager&, EStateMsg, float) {} - virtual void GetUp(CStateManager&, EStateMsg, float) {} - virtual void Taunt(CStateManager&, EStateMsg, float) {} - virtual void Suck(CStateManager&, EStateMsg, float) {} - virtual void Flee(CStateManager&, EStateMsg, float) {} - virtual void Lurk(CStateManager&, EStateMsg, float) {} - virtual void ProjectileAttack(CStateManager&, EStateMsg, float) {} - virtual void Flinch(CStateManager&, EStateMsg, float) {} - virtual void Hurled(CStateManager&, EStateMsg, float) {} - virtual void TelegraphAttack(CStateManager&, EStateMsg, float) {} - virtual void Jump(CStateManager&, EStateMsg, float) {} - virtual void Explode(CStateManager&, EStateMsg, float) {} - virtual void Dodge(CStateManager&, EStateMsg, float) {} - virtual void Retreat(CStateManager&, EStateMsg, float) {} - virtual void Cover(CStateManager&, EStateMsg, float) {} - virtual void Approach(CStateManager&, EStateMsg, float) {} - virtual void WallHang(CStateManager&, EStateMsg, float) {} - virtual void WallDetach(CStateManager&, EStateMsg, float) {} - virtual void Enraged(CStateManager&, EStateMsg, float) {} - virtual void SpecialAttack(CStateManager&, EStateMsg, float) {} - virtual void Growth(CStateManager&, EStateMsg, float) {} - virtual void Faint(CStateManager&, EStateMsg, float) {} - virtual void Land(CStateManager&, EStateMsg, float) {} - virtual void Bounce(CStateManager&, EStateMsg, float) {} - virtual void PathFindEx(CStateManager&, EStateMsg, float) {} - virtual void Dizzy(CStateManager&, EStateMsg, float) {} - virtual void CallForBackup(CStateManager&, EStateMsg, float) {} - virtual void BulbAttack(CStateManager&, EStateMsg, float) {} - virtual void PodAttack(CStateManager&, EStateMsg, float) {} + virtual zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const { + return x34_transform.origin; + } + virtual void Patrol(CStateManager&, EStateMsg, float) {} + virtual void FollowPattern(CStateManager&, EStateMsg, float) {} + virtual void Dead(CStateManager&, EStateMsg, float) {} + virtual void PathFind(CStateManager&, EStateMsg, float) {} + virtual void Start(CStateManager&, EStateMsg, float) {} + virtual void SelectTarget(CStateManager&, EStateMsg, float) {} + virtual void TargetPatrol(CStateManager&, EStateMsg, float) {} + virtual void TargetPlayer(CStateManager&, EStateMsg, float) {} + virtual void TargetCover(CStateManager&, EStateMsg, float) {} + virtual void Halt(CStateManager&, EStateMsg, float) {} + virtual void Walk(CStateManager&, EStateMsg, float) {} + virtual void Run(CStateManager&, EStateMsg, float) {} + virtual void Generate(CStateManager&, EStateMsg, float) {} + virtual void Deactivate(CStateManager&, EStateMsg, float) {} + virtual void Attack(CStateManager&, EStateMsg, float) {} + virtual void LoopedAttack(CStateManager&, EStateMsg, float) {} + virtual void JumpBack(CStateManager&, EStateMsg, float) {} + virtual void DoubleSnap(CStateManager&, EStateMsg, float) {} + virtual void Shuffle(CStateManager&, EStateMsg, float) {} + virtual void TurnAround(CStateManager&, EStateMsg, float) {} + virtual void Skid(CStateManager&, EStateMsg, float) {} + virtual void Active(CStateManager&, EStateMsg, float) {} + virtual void InActive(CStateManager&, EStateMsg, float) {} + virtual void CoverAttack(CStateManager&, EStateMsg, float) {} + virtual void Crouch(CStateManager&, EStateMsg, float) {} + virtual void FadeIn(CStateManager&, EStateMsg, float) {} + virtual void FadeOut(CStateManager&, EStateMsg, float) {} + virtual void GetUp(CStateManager&, EStateMsg, float) {} + virtual void Taunt(CStateManager&, EStateMsg, float) {} + virtual void Suck(CStateManager&, EStateMsg, float) {} + virtual void Flee(CStateManager&, EStateMsg, float) {} + virtual void Lurk(CStateManager&, EStateMsg, float) {} + virtual void ProjectileAttack(CStateManager&, EStateMsg, float) {} + virtual void Flinch(CStateManager&, EStateMsg, float) {} + virtual void Hurled(CStateManager&, EStateMsg, float) {} + virtual void TelegraphAttack(CStateManager&, EStateMsg, float) {} + virtual void Jump(CStateManager&, EStateMsg, float) {} + virtual void Explode(CStateManager&, EStateMsg, float) {} + virtual void Dodge(CStateManager&, EStateMsg, float) {} + virtual void Retreat(CStateManager&, EStateMsg, float) {} + virtual void Cover(CStateManager&, EStateMsg, float) {} + virtual void Approach(CStateManager&, EStateMsg, float) {} + virtual void WallHang(CStateManager&, EStateMsg, float) {} + virtual void WallDetach(CStateManager&, EStateMsg, float) {} + virtual void Enraged(CStateManager&, EStateMsg, float) {} + virtual void SpecialAttack(CStateManager&, EStateMsg, float) {} + virtual void Growth(CStateManager&, EStateMsg, float) {} + virtual void Faint(CStateManager&, EStateMsg, float) {} + virtual void Land(CStateManager&, EStateMsg, float) {} + virtual void Bounce(CStateManager&, EStateMsg, float) {} + virtual void PathFindEx(CStateManager&, EStateMsg, float) {} + virtual void Dizzy(CStateManager&, EStateMsg, float) {} + virtual void CallForBackup(CStateManager&, EStateMsg, float) {} + virtual void BulbAttack(CStateManager&, EStateMsg, float) {} + virtual void PodAttack(CStateManager&, EStateMsg, float) {} - virtual bool InAttackPosition(CStateManager&, float) { return false; } - virtual bool Leash(CStateManager&, float) { return false; } - virtual bool OffLine(CStateManager&, float) { return false; } - virtual bool Attacked(CStateManager&, float) { return false; } - virtual bool PathShagged(CStateManager&, float) { return false; } - virtual bool PathOver(CStateManager&, float) { return false; } - virtual bool PathFound(CStateManager&, float) { return false; } - virtual bool TooClose(CStateManager&, float) { return false; } - virtual bool InRange(CStateManager&, float) { return false; } - virtual bool InMaxRange(CStateManager&, float) { return false; } - virtual bool InDetectionRange(CStateManager&, float) { return false; } - virtual bool SpotPlayer(CStateManager&, float) { return false; } - virtual bool PlayerSpot(CStateManager&, float) { return false; } - virtual bool PatternOver(CStateManager&, float) { return false; } - virtual bool PatternShagged(CStateManager&, float) { return false; } - virtual bool HasAttackPattern(CStateManager&, float) { return false; } - virtual bool HasPatrolPath(CStateManager&, float) { return false; } - virtual bool HasRetreatPattern(CStateManager&, float) { return false; } - virtual bool Delay(CStateManager&,float) { return false; } - virtual bool RandomDelay(CStateManager&, float) { return false; } - virtual bool FixedDelay(CStateManager&, float) { return false; } - virtual bool Default(CStateManager&, float) { return false; } - virtual bool AnimOver(CStateManager&, float) { return false; } - virtual bool ShouldAttack(CStateManager&, float) { return false; } - virtual bool ShouldDoubleSnap(CStateManager&, float) { return false; } - virtual bool InPosition(CStateManager&, float) { return false; } - virtual bool ShouldTurn(CStateManager&, float) { return false; } - virtual bool HitSomething(CStateManager&, float) { return false; } - virtual bool ShouldJumpBack(CStateManager&, float) { return false; } - virtual bool Stuck(CStateManager&, float) { return false; } - virtual bool NoPathNodes(CStateManager&, float) { return false; } - virtual bool Landed(CStateManager&, float) { return false; } - virtual bool HearShot(CStateManager&, float) { return false; } - virtual bool HearPlayer(CStateManager&, float) { return false; } - virtual bool CoverCheck(CStateManager&, float) { return false; } - virtual bool CoverFind(CStateManager&, float) { return false; } - virtual bool CoverBlown(CStateManager&, float) { return false; } - virtual bool CoverNearlyBlown(CStateManager&, float) { return false; } - virtual bool CoveringFire(CStateManager&, float) { return false; } - virtual bool GotUp(CStateManager&, float) { return false; } - virtual bool LineOfSight(CStateManager&, float) { return false; } - virtual bool AggressionCheck(CStateManager&, float) { return false; } - virtual bool AttackOver(CStateManager&, float) { return false; } - virtual bool ShouldTaunt(CStateManager&,float) { return false; } - virtual bool Inside(CStateManager&, float) { return false; } - virtual bool ShouldFire(CStateManager&, float) { return false; } - virtual bool ShouldFlinch(CStateManager&, float) { return false; } - virtual bool PatrolPathOver(CStateManager&, float) { return false; } - virtual bool ShouldDodge(CStateManager&, float) { return false; } - virtual bool ShouldRetreat(CStateManager&, float) { return false; } - virtual bool ShouldCrouch(CStateManager&, float) { return false; } - virtual bool ShouldMove(CStateManager&, float) { return false; } - virtual bool ShotAt(CStateManager&, float) { return false; } - virtual bool HasTargetingPoint(CStateManager&, float) { return false; } - virtual bool ShouldWallHang(CStateManager&, float) { return false; } - virtual bool SetAIStage(CStateManager&, float) { return false; } - virtual bool AIStage(CStateManager&, float) { return false; } - virtual bool StartAttack(CStateManager&, float) { return false; } - virtual bool BreakAttack(CStateManager&, float) { return false; } - virtual bool ShouldStrafe(CStateManager&, float) { return false; } - virtual bool ShouldSpecialAttack(CStateManager&, float) { return false; } - virtual bool LostInterest(CStateManager&, float) { return false; } - virtual bool CodeTrigger(CStateManager&, float) { return false; } - virtual bool BounceFind(CStateManager&, float) { return false; } - virtual bool Random(CStateManager&, float) { return false; } - virtual bool FixedRandom(CStateManager&, float) { return false; } - virtual bool IsDizzy(CStateManager&, float) { return false; } - virtual bool ShouldCallForBackup(CStateManager&, float) { return false; } + virtual bool InAttackPosition(CStateManager&, float) { return false; } + virtual bool Leash(CStateManager&, float) { return false; } + virtual bool OffLine(CStateManager&, float) { return false; } + virtual bool Attacked(CStateManager&, float) { return false; } + virtual bool PathShagged(CStateManager&, float) { return false; } + virtual bool PathOver(CStateManager&, float) { return false; } + virtual bool PathFound(CStateManager&, float) { return false; } + virtual bool TooClose(CStateManager&, float) { return false; } + virtual bool InRange(CStateManager&, float) { return false; } + virtual bool InMaxRange(CStateManager&, float) { return false; } + virtual bool InDetectionRange(CStateManager&, float) { return false; } + virtual bool SpotPlayer(CStateManager&, float) { return false; } + virtual bool PlayerSpot(CStateManager&, float) { return false; } + virtual bool PatternOver(CStateManager&, float) { return false; } + virtual bool PatternShagged(CStateManager&, float) { return false; } + virtual bool HasAttackPattern(CStateManager&, float) { return false; } + virtual bool HasPatrolPath(CStateManager&, float) { return false; } + virtual bool HasRetreatPattern(CStateManager&, float) { return false; } + virtual bool Delay(CStateManager&, float) { return false; } + virtual bool RandomDelay(CStateManager&, float) { return false; } + virtual bool FixedDelay(CStateManager&, float) { return false; } + virtual bool Default(CStateManager&, float) { return false; } + virtual bool AnimOver(CStateManager&, float) { return false; } + virtual bool ShouldAttack(CStateManager&, float) { return false; } + virtual bool ShouldDoubleSnap(CStateManager&, float) { return false; } + virtual bool InPosition(CStateManager&, float) { return false; } + virtual bool ShouldTurn(CStateManager&, float) { return false; } + virtual bool HitSomething(CStateManager&, float) { return false; } + virtual bool ShouldJumpBack(CStateManager&, float) { return false; } + virtual bool Stuck(CStateManager&, float) { return false; } + virtual bool NoPathNodes(CStateManager&, float) { return false; } + virtual bool Landed(CStateManager&, float) { return false; } + virtual bool HearShot(CStateManager&, float) { return false; } + virtual bool HearPlayer(CStateManager&, float) { return false; } + virtual bool CoverCheck(CStateManager&, float) { return false; } + virtual bool CoverFind(CStateManager&, float) { return false; } + virtual bool CoverBlown(CStateManager&, float) { return false; } + virtual bool CoverNearlyBlown(CStateManager&, float) { return false; } + virtual bool CoveringFire(CStateManager&, float) { return false; } + virtual bool GotUp(CStateManager&, float) { return false; } + virtual bool LineOfSight(CStateManager&, float) { return false; } + virtual bool AggressionCheck(CStateManager&, float) { return false; } + virtual bool AttackOver(CStateManager&, float) { return false; } + virtual bool ShouldTaunt(CStateManager&, float) { return false; } + virtual bool Inside(CStateManager&, float) { return false; } + virtual bool ShouldFire(CStateManager&, float) { return false; } + virtual bool ShouldFlinch(CStateManager&, float) { return false; } + virtual bool PatrolPathOver(CStateManager&, float) { return false; } + virtual bool ShouldDodge(CStateManager&, float) { return false; } + virtual bool ShouldRetreat(CStateManager&, float) { return false; } + virtual bool ShouldCrouch(CStateManager&, float) { return false; } + virtual bool ShouldMove(CStateManager&, float) { return false; } + virtual bool ShotAt(CStateManager&, float) { return false; } + virtual bool HasTargetingPoint(CStateManager&, float) { return false; } + virtual bool ShouldWallHang(CStateManager&, float) { return false; } + virtual bool SetAIStage(CStateManager&, float) { return false; } + virtual bool AIStage(CStateManager&, float) { return false; } + virtual bool StartAttack(CStateManager&, float) { return false; } + virtual bool BreakAttack(CStateManager&, float) { return false; } + virtual bool ShouldStrafe(CStateManager&, float) { return false; } + virtual bool ShouldSpecialAttack(CStateManager&, float) { return false; } + virtual bool LostInterest(CStateManager&, float) { return false; } + virtual bool CodeTrigger(CStateManager&, float) { return false; } + virtual bool BounceFind(CStateManager&, float) { return false; } + virtual bool Random(CStateManager&, float) { return false; } + virtual bool FixedRandom(CStateManager&, float) { return false; } + virtual bool IsDizzy(CStateManager&, float) { return false; } + virtual bool ShouldCallForBackup(CStateManager&, float) { return false; } }; -} - +} // namespace urde diff --git a/Runtime/World/CAiFuncMap.cpp b/Runtime/World/CAiFuncMap.cpp index be5476b78..ecc5c99e1 100644 --- a/Runtime/World/CAiFuncMap.cpp +++ b/Runtime/World/CAiFuncMap.cpp @@ -2,149 +2,145 @@ #include "CAi.hpp" #include "CStateManager.hpp" -namespace urde -{ -CAiFuncMap::CAiFuncMap() -{ - /* Ai States */ - x0_stateFuncs["Patrol"] = &CAi::Patrol; - x0_stateFuncs["FollowPattern"] = &CAi::FollowPattern; - x0_stateFuncs["Dead"] = &CAi::Dead; - x0_stateFuncs["PathFind"] = &CAi::PathFind; - x0_stateFuncs["Start"] = &CAi::Start; - x0_stateFuncs["SelectTarget"] = &CAi::SelectTarget; - x0_stateFuncs["TargetPatrol"] = &CAi::TargetPatrol; - x0_stateFuncs["TargetPlayer"] = &CAi::TargetPlayer; - x0_stateFuncs["TargetCover"] = &CAi::TargetCover; - x0_stateFuncs["Halt"] = &CAi::Halt; - x0_stateFuncs["Walk"] = &CAi::Walk; - x0_stateFuncs["Run"] = &CAi::Run; - x0_stateFuncs["Generate"] = &CAi::Generate; - x0_stateFuncs["Deactivate"] = &CAi::Deactivate; - x0_stateFuncs["Attack"] = &CAi::Attack; - x0_stateFuncs["LoopedAttack"] = &CAi::LoopedAttack; - x0_stateFuncs["JumpBack"] = &CAi::JumpBack; - x0_stateFuncs["DoubleSnap"] = &CAi::DoubleSnap; - x0_stateFuncs["Shuffle"] = &CAi::Shuffle; - x0_stateFuncs["TurnAround"] = &CAi::TurnAround; - x0_stateFuncs["Skid"] = &CAi::Skid; - x0_stateFuncs["Active"] = &CAi::Active; - x0_stateFuncs["InActive"] = &CAi::InActive; - x0_stateFuncs["CoverAttack"] = &CAi::CoverAttack; - x0_stateFuncs["Crouch"] = &CAi::Crouch; - x0_stateFuncs["FadeIn"] = &CAi::FadeIn; - x0_stateFuncs["FadeOut"] = &CAi::FadeOut; - x0_stateFuncs["GetUp"] = &CAi::GetUp; - x0_stateFuncs["Taunt"] = &CAi::Taunt; - x0_stateFuncs["Suck"] = &CAi::Suck; - x0_stateFuncs["Flee"] = &CAi::Flee; - x0_stateFuncs["Lurk"] = &CAi::Lurk; - x0_stateFuncs["ProjectileAttack"] = &CAi::ProjectileAttack; - x0_stateFuncs["Flinch"] = &CAi::Flinch; - x0_stateFuncs["Hurled"] = &CAi::Hurled; - x0_stateFuncs["TelegraphAttack"] = &CAi::TelegraphAttack; - x0_stateFuncs["Jump"] = &CAi::Jump; - x0_stateFuncs["Explode"] = &CAi::Explode; - x0_stateFuncs["Dodge"] = &CAi::Dodge; - x0_stateFuncs["Retreat"] = &CAi::Retreat; - x0_stateFuncs["Cover"] = &CAi::Cover; - x0_stateFuncs["Approach"] = &CAi::Approach; - x0_stateFuncs["WallHang"] = &CAi::WallHang; - x0_stateFuncs["WallDetach"] = &CAi::WallDetach; - x0_stateFuncs["Enraged"] = &CAi::Enraged; - x0_stateFuncs["SpecialAttack"] = &CAi::SpecialAttack; - x0_stateFuncs["Growth"] = &CAi::Growth; - x0_stateFuncs["Faint"] = &CAi::Faint; - x0_stateFuncs["Land"] = &CAi::Land; - x0_stateFuncs["Bounce"] = &CAi::Bounce; - x0_stateFuncs["PathFindEx"] = &CAi::PathFindEx; - x0_stateFuncs["Dizzy"] = &CAi::Dizzy; - x0_stateFuncs["CallForBackup"] = &CAi::CallForBackup; - x0_stateFuncs["BulbAttack"] = &CAi::BulbAttack; - x0_stateFuncs["PodAttack"] = &CAi::PodAttack; +namespace urde { +CAiFuncMap::CAiFuncMap() { + /* Ai States */ + x0_stateFuncs["Patrol"] = &CAi::Patrol; + x0_stateFuncs["FollowPattern"] = &CAi::FollowPattern; + x0_stateFuncs["Dead"] = &CAi::Dead; + x0_stateFuncs["PathFind"] = &CAi::PathFind; + x0_stateFuncs["Start"] = &CAi::Start; + x0_stateFuncs["SelectTarget"] = &CAi::SelectTarget; + x0_stateFuncs["TargetPatrol"] = &CAi::TargetPatrol; + x0_stateFuncs["TargetPlayer"] = &CAi::TargetPlayer; + x0_stateFuncs["TargetCover"] = &CAi::TargetCover; + x0_stateFuncs["Halt"] = &CAi::Halt; + x0_stateFuncs["Walk"] = &CAi::Walk; + x0_stateFuncs["Run"] = &CAi::Run; + x0_stateFuncs["Generate"] = &CAi::Generate; + x0_stateFuncs["Deactivate"] = &CAi::Deactivate; + x0_stateFuncs["Attack"] = &CAi::Attack; + x0_stateFuncs["LoopedAttack"] = &CAi::LoopedAttack; + x0_stateFuncs["JumpBack"] = &CAi::JumpBack; + x0_stateFuncs["DoubleSnap"] = &CAi::DoubleSnap; + x0_stateFuncs["Shuffle"] = &CAi::Shuffle; + x0_stateFuncs["TurnAround"] = &CAi::TurnAround; + x0_stateFuncs["Skid"] = &CAi::Skid; + x0_stateFuncs["Active"] = &CAi::Active; + x0_stateFuncs["InActive"] = &CAi::InActive; + x0_stateFuncs["CoverAttack"] = &CAi::CoverAttack; + x0_stateFuncs["Crouch"] = &CAi::Crouch; + x0_stateFuncs["FadeIn"] = &CAi::FadeIn; + x0_stateFuncs["FadeOut"] = &CAi::FadeOut; + x0_stateFuncs["GetUp"] = &CAi::GetUp; + x0_stateFuncs["Taunt"] = &CAi::Taunt; + x0_stateFuncs["Suck"] = &CAi::Suck; + x0_stateFuncs["Flee"] = &CAi::Flee; + x0_stateFuncs["Lurk"] = &CAi::Lurk; + x0_stateFuncs["ProjectileAttack"] = &CAi::ProjectileAttack; + x0_stateFuncs["Flinch"] = &CAi::Flinch; + x0_stateFuncs["Hurled"] = &CAi::Hurled; + x0_stateFuncs["TelegraphAttack"] = &CAi::TelegraphAttack; + x0_stateFuncs["Jump"] = &CAi::Jump; + x0_stateFuncs["Explode"] = &CAi::Explode; + x0_stateFuncs["Dodge"] = &CAi::Dodge; + x0_stateFuncs["Retreat"] = &CAi::Retreat; + x0_stateFuncs["Cover"] = &CAi::Cover; + x0_stateFuncs["Approach"] = &CAi::Approach; + x0_stateFuncs["WallHang"] = &CAi::WallHang; + x0_stateFuncs["WallDetach"] = &CAi::WallDetach; + x0_stateFuncs["Enraged"] = &CAi::Enraged; + x0_stateFuncs["SpecialAttack"] = &CAi::SpecialAttack; + x0_stateFuncs["Growth"] = &CAi::Growth; + x0_stateFuncs["Faint"] = &CAi::Faint; + x0_stateFuncs["Land"] = &CAi::Land; + x0_stateFuncs["Bounce"] = &CAi::Bounce; + x0_stateFuncs["PathFindEx"] = &CAi::PathFindEx; + x0_stateFuncs["Dizzy"] = &CAi::Dizzy; + x0_stateFuncs["CallForBackup"] = &CAi::CallForBackup; + x0_stateFuncs["BulbAttack"] = &CAi::BulbAttack; + x0_stateFuncs["PodAttack"] = &CAi::PodAttack; - /* Ai Triggers */ - x10_triggerFuncs["InAttackPosition"] = &CAi::InAttackPosition; - x10_triggerFuncs["Leash"] = &CAi::Leash; - x10_triggerFuncs["OffLine"] = &CAi::OffLine; - x10_triggerFuncs["Attacked"] = &CAi::Attacked; - x10_triggerFuncs["PathShagged"] = &CAi::PathShagged; - x10_triggerFuncs["TooClose"] = &CAi::TooClose; - x10_triggerFuncs["InRange"] = &CAi::InRange; - x10_triggerFuncs["InMaxRange"] = &CAi::InMaxRange; - x10_triggerFuncs["InDetectionRange"] = &CAi::InDetectionRange; - x10_triggerFuncs["SpotPlayer"] = &CAi::SpotPlayer; - x10_triggerFuncs["PlayerSpot"] = &CAi::PlayerSpot; - x10_triggerFuncs["PatternOver"] = &CAi::PatternOver; - x10_triggerFuncs["PatternShagged"] = &CAi::PatternShagged; - x10_triggerFuncs["HasAttackPattern"] = &CAi::HasAttackPattern; - x10_triggerFuncs["HasPatrolPath"] = &CAi::HasPatrolPath; - x10_triggerFuncs["HasRetreatPattern"] = &CAi::HasRetreatPattern; - x10_triggerFuncs["Delay"] = &CAi::Delay; - x10_triggerFuncs["RandomDelay"] = &CAi::RandomDelay; - x10_triggerFuncs["FixedDelay"] = &CAi::FixedDelay; - x10_triggerFuncs["Default"] = &CAi::Default; - x10_triggerFuncs["AnimOver"] = &CAi::AnimOver; - x10_triggerFuncs["ShouldAttack"] = &CAi::ShouldAttack; - x10_triggerFuncs["ShouldDoubleSnap"] = &CAi::ShouldDoubleSnap; - x10_triggerFuncs["InPosition"] = &CAi::InPosition; - x10_triggerFuncs["ShouldTurn"] = &CAi::ShouldTurn; - x10_triggerFuncs["HitSomething"] = &CAi::HitSomething; - x10_triggerFuncs["ShouldJumpBack"] = &CAi::ShouldJumpBack; - x10_triggerFuncs["Stuck"] = &CAi::Stuck; - x10_triggerFuncs["NoPathNodes"] = &CAi::NoPathNodes; - x10_triggerFuncs["Landed"] = &CAi::Landed; - x10_triggerFuncs["HearShot"] = &CAi::HearShot; - x10_triggerFuncs["HearPlayer"] = &CAi::HearPlayer; - x10_triggerFuncs["CoverCheck"] = &CAi::CoverCheck; - x10_triggerFuncs["CoverFind"] = &CAi::CoverFind; - x10_triggerFuncs["CoverBlown"] = &CAi::CoverBlown; - x10_triggerFuncs["CoverNearlyBlown"] = &CAi::CoverNearlyBlown; - x10_triggerFuncs["CoveringFire"] = &CAi::CoveringFire; - x10_triggerFuncs["GotUp"] = &CAi::GotUp; - x10_triggerFuncs["LineOfSight"] = &CAi::LineOfSight; - x10_triggerFuncs["AggressionCheck"] = &CAi::AggressionCheck; - x10_triggerFuncs["AttackOver"] = &CAi::AttackOver; - x10_triggerFuncs["ShouldTaunt"] = &CAi::ShouldTaunt; - x10_triggerFuncs["Inside"] = &CAi::Inside; - x10_triggerFuncs["ShouldFire"] = &CAi::ShouldFire; - x10_triggerFuncs["ShouldFlinch"] = &CAi::ShouldFlinch; - x10_triggerFuncs["PatrolPathOver"] = &CAi::PatrolPathOver; - x10_triggerFuncs["ShouldDodge"] = &CAi::ShouldDodge; - x10_triggerFuncs["ShouldRetreat"] = &CAi::ShouldRetreat; - x10_triggerFuncs["ShouldCrouch"] = &CAi::ShouldCrouch; - x10_triggerFuncs["ShouldMove"] = &CAi::ShouldMove; - x10_triggerFuncs["ShotAt"] = &CAi::ShotAt; - x10_triggerFuncs["HasTargetingPoint"] = &CAi::HasTargetingPoint; - x10_triggerFuncs["ShouldWallHang"] = &CAi::ShouldWallHang; - x10_triggerFuncs["SetAIStage"] = &CAi::SetAIStage; - x10_triggerFuncs["AIStage"] = &CAi::AIStage; - x10_triggerFuncs["StartAttack"] = &CAi::StartAttack; - x10_triggerFuncs["BreakAttack"] = &CAi::BreakAttack; - x10_triggerFuncs["ShouldStrafe"] = &CAi::ShouldStrafe; - x10_triggerFuncs["ShouldSpecialAttack"] = &CAi::ShouldSpecialAttack; - x10_triggerFuncs["LostInterest"] = &CAi::LostInterest; - x10_triggerFuncs["CodeTrigger"] = &CAi::CodeTrigger; - x10_triggerFuncs["BounceFind"] = &CAi::BounceFind; - x10_triggerFuncs["Random"] = &CAi::Random; - x10_triggerFuncs["FixedRandom"] = &CAi::FixedRandom; - x10_triggerFuncs["IsDizzy"] = &CAi::IsDizzy; - x10_triggerFuncs["ShouldCallForBackup"] = &CAi::ShouldCallForBackup; + /* Ai Triggers */ + x10_triggerFuncs["InAttackPosition"] = &CAi::InAttackPosition; + x10_triggerFuncs["Leash"] = &CAi::Leash; + x10_triggerFuncs["OffLine"] = &CAi::OffLine; + x10_triggerFuncs["Attacked"] = &CAi::Attacked; + x10_triggerFuncs["PathShagged"] = &CAi::PathShagged; + x10_triggerFuncs["TooClose"] = &CAi::TooClose; + x10_triggerFuncs["InRange"] = &CAi::InRange; + x10_triggerFuncs["InMaxRange"] = &CAi::InMaxRange; + x10_triggerFuncs["InDetectionRange"] = &CAi::InDetectionRange; + x10_triggerFuncs["SpotPlayer"] = &CAi::SpotPlayer; + x10_triggerFuncs["PlayerSpot"] = &CAi::PlayerSpot; + x10_triggerFuncs["PatternOver"] = &CAi::PatternOver; + x10_triggerFuncs["PatternShagged"] = &CAi::PatternShagged; + x10_triggerFuncs["HasAttackPattern"] = &CAi::HasAttackPattern; + x10_triggerFuncs["HasPatrolPath"] = &CAi::HasPatrolPath; + x10_triggerFuncs["HasRetreatPattern"] = &CAi::HasRetreatPattern; + x10_triggerFuncs["Delay"] = &CAi::Delay; + x10_triggerFuncs["RandomDelay"] = &CAi::RandomDelay; + x10_triggerFuncs["FixedDelay"] = &CAi::FixedDelay; + x10_triggerFuncs["Default"] = &CAi::Default; + x10_triggerFuncs["AnimOver"] = &CAi::AnimOver; + x10_triggerFuncs["ShouldAttack"] = &CAi::ShouldAttack; + x10_triggerFuncs["ShouldDoubleSnap"] = &CAi::ShouldDoubleSnap; + x10_triggerFuncs["InPosition"] = &CAi::InPosition; + x10_triggerFuncs["ShouldTurn"] = &CAi::ShouldTurn; + x10_triggerFuncs["HitSomething"] = &CAi::HitSomething; + x10_triggerFuncs["ShouldJumpBack"] = &CAi::ShouldJumpBack; + x10_triggerFuncs["Stuck"] = &CAi::Stuck; + x10_triggerFuncs["NoPathNodes"] = &CAi::NoPathNodes; + x10_triggerFuncs["Landed"] = &CAi::Landed; + x10_triggerFuncs["HearShot"] = &CAi::HearShot; + x10_triggerFuncs["HearPlayer"] = &CAi::HearPlayer; + x10_triggerFuncs["CoverCheck"] = &CAi::CoverCheck; + x10_triggerFuncs["CoverFind"] = &CAi::CoverFind; + x10_triggerFuncs["CoverBlown"] = &CAi::CoverBlown; + x10_triggerFuncs["CoverNearlyBlown"] = &CAi::CoverNearlyBlown; + x10_triggerFuncs["CoveringFire"] = &CAi::CoveringFire; + x10_triggerFuncs["GotUp"] = &CAi::GotUp; + x10_triggerFuncs["LineOfSight"] = &CAi::LineOfSight; + x10_triggerFuncs["AggressionCheck"] = &CAi::AggressionCheck; + x10_triggerFuncs["AttackOver"] = &CAi::AttackOver; + x10_triggerFuncs["ShouldTaunt"] = &CAi::ShouldTaunt; + x10_triggerFuncs["Inside"] = &CAi::Inside; + x10_triggerFuncs["ShouldFire"] = &CAi::ShouldFire; + x10_triggerFuncs["ShouldFlinch"] = &CAi::ShouldFlinch; + x10_triggerFuncs["PatrolPathOver"] = &CAi::PatrolPathOver; + x10_triggerFuncs["ShouldDodge"] = &CAi::ShouldDodge; + x10_triggerFuncs["ShouldRetreat"] = &CAi::ShouldRetreat; + x10_triggerFuncs["ShouldCrouch"] = &CAi::ShouldCrouch; + x10_triggerFuncs["ShouldMove"] = &CAi::ShouldMove; + x10_triggerFuncs["ShotAt"] = &CAi::ShotAt; + x10_triggerFuncs["HasTargetingPoint"] = &CAi::HasTargetingPoint; + x10_triggerFuncs["ShouldWallHang"] = &CAi::ShouldWallHang; + x10_triggerFuncs["SetAIStage"] = &CAi::SetAIStage; + x10_triggerFuncs["AIStage"] = &CAi::AIStage; + x10_triggerFuncs["StartAttack"] = &CAi::StartAttack; + x10_triggerFuncs["BreakAttack"] = &CAi::BreakAttack; + x10_triggerFuncs["ShouldStrafe"] = &CAi::ShouldStrafe; + x10_triggerFuncs["ShouldSpecialAttack"] = &CAi::ShouldSpecialAttack; + x10_triggerFuncs["LostInterest"] = &CAi::LostInterest; + x10_triggerFuncs["CodeTrigger"] = &CAi::CodeTrigger; + x10_triggerFuncs["BounceFind"] = &CAi::BounceFind; + x10_triggerFuncs["Random"] = &CAi::Random; + x10_triggerFuncs["FixedRandom"] = &CAi::FixedRandom; + x10_triggerFuncs["IsDizzy"] = &CAi::IsDizzy; + x10_triggerFuncs["ShouldCallForBackup"] = &CAi::ShouldCallForBackup; - CAi::CreateFuncLookup(this); + CAi::CreateFuncLookup(this); } -CAiStateFunc CAiFuncMap::GetStateFunc(const char* func) -{ - if (x0_stateFuncs.find(func) == x0_stateFuncs.end()) - return nullptr; - return x0_stateFuncs[func]; +CAiStateFunc CAiFuncMap::GetStateFunc(const char* func) { + if (x0_stateFuncs.find(func) == x0_stateFuncs.end()) + return nullptr; + return x0_stateFuncs[func]; } -CAiTriggerFunc CAiFuncMap::GetTriggerFunc(const char* func) -{ - if (x10_triggerFuncs.find(func) == x10_triggerFuncs.end()) - return nullptr; - return x10_triggerFuncs[func]; -} +CAiTriggerFunc CAiFuncMap::GetTriggerFunc(const char* func) { + if (x10_triggerFuncs.find(func) == x10_triggerFuncs.end()) + return nullptr; + return x10_triggerFuncs[func]; } +} // namespace urde diff --git a/Runtime/World/CAiFuncMap.hpp b/Runtime/World/CAiFuncMap.hpp index 515fd2d6a..e5b6e4a77 100644 --- a/Runtime/World/CAiFuncMap.hpp +++ b/Runtime/World/CAiFuncMap.hpp @@ -3,29 +3,22 @@ #include "RetroTypes.hpp" #include -namespace urde -{ -enum class EStateMsg -{ - Activate = 0, - Update = 1, - Deactivate = 2 -}; +namespace urde { +enum class EStateMsg { Activate = 0, Update = 1, Deactivate = 2 }; class CStateManager; class CAi; typedef void (CAi::*CAiStateFunc)(CStateManager&, EStateMsg, float); typedef bool (CAi::*CAiTriggerFunc)(CStateManager&, float); -class CAiFuncMap -{ - static const std::vector gkStateNames; - std::unordered_map x0_stateFuncs; - std::unordered_map x10_triggerFuncs; -public: - CAiFuncMap(); - CAiStateFunc GetStateFunc(const char*); - CAiTriggerFunc GetTriggerFunc(const char*); -}; -} +class CAiFuncMap { + static const std::vector gkStateNames; + std::unordered_map x0_stateFuncs; + std::unordered_map x10_triggerFuncs; +public: + CAiFuncMap(); + CAiStateFunc GetStateFunc(const char*); + CAiTriggerFunc GetTriggerFunc(const char*); +}; +} // namespace urde diff --git a/Runtime/World/CAmbientAI.cpp b/Runtime/World/CAmbientAI.cpp index 5a9bdec2f..d2ab31e1c 100644 --- a/Runtime/World/CAmbientAI.cpp +++ b/Runtime/World/CAmbientAI.cpp @@ -3,13 +3,12 @@ #include "CPlayer.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CAmbientAI::CAmbientAI(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& aabox, const CMaterialList& matList, float mass, - const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, - const CActorParameters& aParms, float alertRange, float impactRange, s32 alertAnim, s32 impactAnim, bool active) + const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, const CActorParameters& aParms, + float alertRange, float impactRange, s32 alertAnim, s32 impactAnim, bool active) : CPhysicsActor(uid, active, name, info, xf, std::move(mData), matList, aabox, SMoverData(mass), aParms, 0.3f, 0.1f) , x258_initialHealthInfo(hInfo) , x260_healthInfo(hInfo) @@ -18,146 +17,119 @@ CAmbientAI::CAmbientAI(TUniqueId uid, std::string_view name, const CEntityInfo& , x2d8_impactRange(impactRange) , x2dc_defaultAnim(GetModelData()->GetAnimationData()->GetDefaultAnimation()) , x2e0_alertAnim(alertAnim) -, x2e4_impactAnim(impactAnim) -{ - ModelData()->AnimationData()->EnableLooping(true); +, x2e4_impactAnim(impactAnim) { + ModelData()->AnimationData()->EnableLooping(true); } +void CAmbientAI::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CAmbientAI::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CAmbientAI::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; + + if (GetModelData() && GetModelData()->GetAnimationData()) { + bool hasAnimTime = GetModelData()->GetAnimationData()->IsAnimTimeRemaining(dt - FLT_EPSILON, "Whole Body"sv); + bool isLooping = GetModelData()->GetIsLoop(); + + if (hasAnimTime || isLooping) { + x2e8_25_animating = true; + SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, x2e8_25_animating); + MoveToOR(deltas.x0_posDelta, dt); + RotateToOR(deltas.xc_rotDelta, dt); + } + + if (!hasAnimTime || (x2e8_25_animating && !isLooping)) { + SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); + x2e8_25_animating = false; + } + } + + bool inAlertRange = (mgr.GetPlayer().GetTranslation() - GetTranslation()).magnitude() < x2d4_alertRange; + bool inImpactRange = (mgr.GetPlayer().GetTranslation() - GetTranslation()).magnitude() < x2d8_impactRange; + + switch (x2d0_animState) { + case EAnimationState::Ready: { + if (inAlertRange) { + x2d0_animState = EAnimationState::Alert; + ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2e0_alertAnim, -1, 1.f, true), false); + ModelData()->EnableLooping(true); + RandomizePlaybackRate(mgr); + } + break; + } + case EAnimationState::Alert: { + if (!inAlertRange) { + x2d0_animState = EAnimationState::Ready; + ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2dc_defaultAnim, -1, 1.f, true), false); + ModelData()->EnableLooping(true); + RandomizePlaybackRate(mgr); + } else if (inImpactRange) { + SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); + SetActive(false); + } + break; + } + case EAnimationState::Impact: { + if (!x2e8_25_animating) { + x2d0_animState = EAnimationState::Ready; + ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2dc_defaultAnim, -1, 1.f, true), false); + ModelData()->EnableLooping(true); + RandomizePlaybackRate(mgr); + } + break; + } + } + + if (!x2e8_24_dead) { + CHealthInfo* hInfo = HealthInfo(mgr); + if (hInfo->GetHP() <= 0.f) { + x2e8_24_dead = true; + SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); + RemoveEmitter(); + SetActive(false); + } + } } -void CAmbientAI::Think(float dt, CStateManager& mgr) -{ +void CAmbientAI::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Reset: { if (!GetActive()) - return; - - if (GetModelData() && GetModelData()->GetAnimationData()) - { - bool hasAnimTime = GetModelData()->GetAnimationData()->IsAnimTimeRemaining(dt - FLT_EPSILON, "Whole Body"sv); - bool isLooping = GetModelData()->GetIsLoop(); - - if (hasAnimTime || isLooping) - { - x2e8_25_animating = true; - SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, x2e8_25_animating); - MoveToOR(deltas.x0_posDelta, dt); - RotateToOR(deltas.xc_rotDelta, dt); - } - - if (!hasAnimTime || (x2e8_25_animating && !isLooping)) - { - SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); - x2e8_25_animating = false; - } - } - - bool inAlertRange = (mgr.GetPlayer().GetTranslation() - GetTranslation()).magnitude() < x2d4_alertRange; - bool inImpactRange = (mgr.GetPlayer().GetTranslation() - GetTranslation()).magnitude() < x2d8_impactRange; - - switch(x2d0_animState) - { - case EAnimationState::Ready: - { - if (inAlertRange) - { - x2d0_animState = EAnimationState::Alert; - ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2e0_alertAnim, -1, 1.f, true), false); - ModelData()->EnableLooping(true); - RandomizePlaybackRate(mgr); - } - break; - } - case EAnimationState::Alert: - { - if (!inAlertRange) - { - x2d0_animState = EAnimationState::Ready; - ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2dc_defaultAnim, -1, 1.f, true), false); - ModelData()->EnableLooping(true); - RandomizePlaybackRate(mgr); - } - else if (inImpactRange) - { - SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); - SetActive(false); - } - break; - } - case EAnimationState::Impact: - { - if (!x2e8_25_animating) - { - x2d0_animState = EAnimationState::Ready; - ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2dc_defaultAnim, -1, 1.f, true), false); - ModelData()->EnableLooping(true); - RandomizePlaybackRate(mgr); - } - break; - } - } - - if (!x2e8_24_dead) - { - CHealthInfo* hInfo = HealthInfo(mgr); - if (hInfo->GetHP() <= 0.f) - { - x2e8_24_dead = true; - SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); - RemoveEmitter(); - SetActive(false); - } + SetActive(true); + x2d0_animState = EAnimationState::Ready; + ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2dc_defaultAnim, -1, 1.f, true), false); + ModelData()->AnimationData()->EnableLooping(true); + RandomizePlaybackRate(mgr); + x2e8_24_dead = false; + x260_healthInfo = x258_initialHealthInfo; + break; + } + case EScriptObjectMessage::Damage: { + if (GetActive()) { + x2d0_animState = EAnimationState::Impact; + ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2e4_impactAnim, -1, 1.f, true), false); + ModelData()->AnimationData()->EnableLooping(false); + RandomizePlaybackRate(mgr); } + break; + } + case EScriptObjectMessage::InitializedInArea: + RandomizePlaybackRate(mgr); + break; + default: + break; + } + CPhysicsActor::AcceptScriptMsg(msg, uid, mgr); } -void CAmbientAI::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - switch(msg) - { - case EScriptObjectMessage::Reset: - { - if (!GetActive()) - SetActive(true); - x2d0_animState = EAnimationState::Ready; - ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2dc_defaultAnim, -1, 1.f, true), false); - ModelData()->AnimationData()->EnableLooping(true); - RandomizePlaybackRate(mgr); - x2e8_24_dead = false; - x260_healthInfo = x258_initialHealthInfo; - break; - } - case EScriptObjectMessage::Damage: - { - if (GetActive()) - { - x2d0_animState = EAnimationState::Impact; - ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(x2e4_impactAnim, -1, 1.f, true), false); - ModelData()->AnimationData()->EnableLooping(false); - RandomizePlaybackRate(mgr); - } - break; - } - case EScriptObjectMessage::InitializedInArea: - RandomizePlaybackRate(mgr); - break; - default: - break; - } - CPhysicsActor::AcceptScriptMsg(msg, uid, mgr); +std::experimental::optional CAmbientAI::GetTouchBounds() const { + if (GetActive()) + return {GetBoundingBox()}; + return {}; } -std::experimental::optional CAmbientAI::GetTouchBounds() const -{ - if (GetActive()) - return {GetBoundingBox()}; - return {}; +void CAmbientAI::RandomizePlaybackRate(CStateManager& mgr) { + ModelData()->AnimationData()->MultiplyPlaybackRate(0.4f * mgr.GetActiveRandom()->Float() + 0.8f); } -void CAmbientAI::RandomizePlaybackRate(CStateManager& mgr) -{ - ModelData()->AnimationData()->MultiplyPlaybackRate(0.4f * mgr.GetActiveRandom()->Float() + 0.8f); -} - -} +} // namespace urde diff --git a/Runtime/World/CAmbientAI.hpp b/Runtime/World/CAmbientAI.hpp index 6c5e0e535..cdff8c74a 100644 --- a/Runtime/World/CAmbientAI.hpp +++ b/Runtime/World/CAmbientAI.hpp @@ -2,46 +2,41 @@ #include "CPhysicsActor.hpp" #include "CDamageVulnerability.hpp" -namespace urde -{ -class CAmbientAI : public CPhysicsActor -{ - enum class EAnimationState - { - Ready, - Alert, - Impact - }; +namespace urde { +class CAmbientAI : public CPhysicsActor { + enum class EAnimationState { Ready, Alert, Impact }; - CHealthInfo x258_initialHealthInfo; - CHealthInfo x260_healthInfo; - CDamageVulnerability x268_dVuln; - EAnimationState x2d0_animState= EAnimationState::Ready; - float x2d4_alertRange; - float x2d8_impactRange; - s32 x2dc_defaultAnim; - s32 x2e0_alertAnim; - s32 x2e4_impactAnim; + CHealthInfo x258_initialHealthInfo; + CHealthInfo x260_healthInfo; + CDamageVulnerability x268_dVuln; + EAnimationState x2d0_animState = EAnimationState::Ready; + float x2d4_alertRange; + float x2d8_impactRange; + s32 x2dc_defaultAnim; + s32 x2e0_alertAnim; + s32 x2e4_impactAnim; - union - { - struct { bool x2e8_24_dead : 1; bool x2e8_25_animating : 1; }; - u32 _dummy = 0; + union { + struct { + bool x2e8_24_dead : 1; + bool x2e8_25_animating : 1; }; + u32 _dummy = 0; + }; public: - CAmbientAI(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, - CModelData&&, const zeus::CAABox&, const CMaterialList&, float, const CHealthInfo&, const CDamageVulnerability&, - const CActorParameters&, float, float, s32, s32, bool); + CAmbientAI(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const zeus::CAABox&, const CMaterialList&, float, const CHealthInfo&, const CDamageVulnerability&, + const CActorParameters&, float, float, s32, s32, bool); - void Accept(IVisitor&); - void Think(float, CStateManager&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - CHealthInfo* HealthInfo(CStateManager&) { return &x260_healthInfo; } - const CDamageVulnerability* GetDamageVulnerability() const { return &x268_dVuln; } - std::experimental::optional GetTouchBounds() const; - void Touch(CActor&, CStateManager&) {} - void RandomizePlaybackRate(CStateManager&); + void Accept(IVisitor&); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + CHealthInfo* HealthInfo(CStateManager&) { return &x260_healthInfo; } + const CDamageVulnerability* GetDamageVulnerability() const { return &x268_dVuln; } + std::experimental::optional GetTouchBounds() const; + void Touch(CActor&, CStateManager&) {} + void RandomizePlaybackRate(CStateManager&); }; -} +} // namespace urde diff --git a/Runtime/World/CAnimationParameters.hpp b/Runtime/World/CAnimationParameters.hpp index ff43da50d..a87138d9f 100644 --- a/Runtime/World/CAnimationParameters.hpp +++ b/Runtime/World/CAnimationParameters.hpp @@ -2,28 +2,24 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { + +class CAnimationParameters { + CAssetId x0_ancs; + u32 x4_charIdx = -1; + u32 x8_defaultAnim = -1; -class CAnimationParameters -{ - CAssetId x0_ancs; - u32 x4_charIdx = -1; - u32 x8_defaultAnim = -1; public: - CAnimationParameters() = default; - CAnimationParameters(CAssetId ancs, u32 charIdx, u32 defaultAnim) - : x0_ancs(ancs), x4_charIdx(charIdx), x8_defaultAnim(defaultAnim) {} - CAnimationParameters(CInputStream& in) - : x0_ancs(in.readUint32Big()), - x4_charIdx(in.readUint32Big()), - x8_defaultAnim(in.readUint32Big()) {} + CAnimationParameters() = default; + CAnimationParameters(CAssetId ancs, u32 charIdx, u32 defaultAnim) + : x0_ancs(ancs), x4_charIdx(charIdx), x8_defaultAnim(defaultAnim) {} + CAnimationParameters(CInputStream& in) + : x0_ancs(in.readUint32Big()), x4_charIdx(in.readUint32Big()), x8_defaultAnim(in.readUint32Big()) {} - CAssetId GetACSFile() const { return x0_ancs; } - u32 GetCharacter() const { return x4_charIdx; } - u32 GetInitialAnimation() const { return x8_defaultAnim; } - void SetCharacter(u32 charIdx) { x4_charIdx = charIdx; } + CAssetId GetACSFile() const { return x0_ancs; } + u32 GetCharacter() const { return x4_charIdx; } + u32 GetInitialAnimation() const { return x8_defaultAnim; } + void SetCharacter(u32 charIdx) { x4_charIdx = charIdx; } }; -} - +} // namespace urde diff --git a/Runtime/World/CDamageInfo.cpp b/Runtime/World/CDamageInfo.cpp index efbe5070b..bc73b5286 100644 --- a/Runtime/World/CDamageInfo.cpp +++ b/Runtime/World/CDamageInfo.cpp @@ -2,8 +2,7 @@ #include "CDamageVulnerability.hpp" #include "DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp" -namespace urde -{ +namespace urde { CDamageInfo::CDamageInfo(const DataSpec::SShotParam& other) : x0_weaponMode(CWeaponMode(EWeaponType(other.weaponType), other.charged, other.combo, other.instaKill)) @@ -11,50 +10,44 @@ CDamageInfo::CDamageInfo(const DataSpec::SShotParam& other) , xc_radiusDamage(other.radiusDamage) , x10_radius(other.radius) , x14_knockback(other.knockback) -, x18_noImmunity(other.noImmunity) -{ +, x18_noImmunity(other.noImmunity) {} + +CDamageInfo& CDamageInfo::operator=(const DataSpec::SShotParam& other) { + x0_weaponMode = CWeaponMode(EWeaponType(other.weaponType), other.charged, other.combo, other.instaKill); + x8_damage = other.damage; + xc_radiusDamage = other.radiusDamage; + x10_radius = other.radius; + x14_knockback = other.knockback; + x18_noImmunity = other.noImmunity; + return *this; } -CDamageInfo& CDamageInfo::operator=(const DataSpec::SShotParam& other) -{ - x0_weaponMode = CWeaponMode(EWeaponType(other.weaponType), other.charged, other.combo, other.instaKill); - x8_damage = other.damage; - xc_radiusDamage = other.radiusDamage; - x10_radius = other.radius; - x14_knockback = other.knockback; - x18_noImmunity = other.noImmunity; - return *this; +float CDamageInfo::GetDamage(const CDamageVulnerability& dVuln) const { + EVulnerability vuln = dVuln.GetVulnerability(x0_weaponMode, false); + if (vuln == EVulnerability::Deflect) + return 0.f; + else if (vuln == EVulnerability::Weak) + return 2.f * x8_damage; + + return x8_damage; } -float CDamageInfo::GetDamage(const CDamageVulnerability& dVuln) const -{ - EVulnerability vuln = dVuln.GetVulnerability(x0_weaponMode, false); - if (vuln == EVulnerability::Deflect) - return 0.f; - else if (vuln == EVulnerability::Weak) - return 2.f * x8_damage; +float CDamageInfo::GetRadiusDamage(const CDamageVulnerability& dVuln) const { + EVulnerability vuln = dVuln.GetVulnerability(x0_weaponMode, false); + if (vuln == EVulnerability::Deflect) + return 0.f; + else if (vuln == EVulnerability::Weak) + return 2.f * xc_radiusDamage; - return x8_damage; + return xc_radiusDamage; } -float CDamageInfo::GetRadiusDamage(const CDamageVulnerability& dVuln) const -{ - EVulnerability vuln = dVuln.GetVulnerability(x0_weaponMode, false); - if (vuln == EVulnerability::Deflect) - return 0.f; - else if (vuln == EVulnerability::Weak) - return 2.f * xc_radiusDamage; - - return xc_radiusDamage; -} - -CDamageInfo::CDamageInfo(const CDamageInfo& other, float dt) -{ - x0_weaponMode = other.x0_weaponMode; - x8_damage = other.x8_damage * (60.f * dt); - xc_radiusDamage = x8_damage; - x10_radius = other.x10_radius; - x14_knockback = other.x14_knockback; - x18_noImmunity = true; -} +CDamageInfo::CDamageInfo(const CDamageInfo& other, float dt) { + x0_weaponMode = other.x0_weaponMode; + x8_damage = other.x8_damage * (60.f * dt); + xc_radiusDamage = x8_damage; + x10_radius = other.x10_radius; + x14_knockback = other.x14_knockback; + x18_noImmunity = true; } +} // namespace urde diff --git a/Runtime/World/CDamageInfo.hpp b/Runtime/World/CDamageInfo.hpp index 7796e2232..855aba973 100644 --- a/Runtime/World/CDamageInfo.hpp +++ b/Runtime/World/CDamageInfo.hpp @@ -4,70 +4,61 @@ #include "Weapon/CWeaponMgr.hpp" #include "Weapon/CWeaponMode.hpp" -namespace DataSpec -{ +namespace DataSpec { struct SShotParam; } -namespace urde -{ +namespace urde { class CDamageVulnerability; -class CDamageInfo -{ - CWeaponMode x0_weaponMode; - float x8_damage = 0.f; - float xc_radiusDamage = 0.f; - float x10_radius = 0.f; - float x14_knockback = 0.f; - bool x18_noImmunity = false; +class CDamageInfo { + CWeaponMode x0_weaponMode; + float x8_damage = 0.f; + float xc_radiusDamage = 0.f; + float x10_radius = 0.f; + float x14_knockback = 0.f; + bool x18_noImmunity = false; public: - CDamageInfo() = default; - CDamageInfo(CInputStream& in) - { - in.readUint32Big(); - x0_weaponMode = CWeaponMode(EWeaponType(in.readUint32Big())); - x8_damage = in.readFloatBig(); - xc_radiusDamage = x8_damage; - x10_radius = in.readFloatBig(); - x14_knockback = in.readFloatBig(); - } - CDamageInfo(const CWeaponMode& mode, float damage, float radius, float knockback) - : x0_weaponMode(mode), x8_damage(damage), xc_radiusDamage(damage), x10_radius(radius), x14_knockback(knockback) - { - } + CDamageInfo() = default; + CDamageInfo(CInputStream& in) { + in.readUint32Big(); + x0_weaponMode = CWeaponMode(EWeaponType(in.readUint32Big())); + x8_damage = in.readFloatBig(); + xc_radiusDamage = x8_damage; + x10_radius = in.readFloatBig(); + x14_knockback = in.readFloatBig(); + } + CDamageInfo(const CWeaponMode& mode, float damage, float radius, float knockback) + : x0_weaponMode(mode), x8_damage(damage), xc_radiusDamage(damage), x10_radius(radius), x14_knockback(knockback) {} - CDamageInfo(const CDamageInfo& other) = default; - CDamageInfo(const CDamageInfo&, float); - CDamageInfo(const DataSpec::SShotParam& other); - CDamageInfo& operator=(const DataSpec::SShotParam& other); + CDamageInfo(const CDamageInfo& other) = default; + CDamageInfo(const CDamageInfo&, float); + CDamageInfo(const DataSpec::SShotParam& other); + CDamageInfo& operator=(const DataSpec::SShotParam& other); - const CWeaponMode& GetWeaponMode() const { return x0_weaponMode; } - void SetWeaponMode(const CWeaponMode& mode) { x0_weaponMode = mode; } - float GetRadius() const { return x10_radius; } - void SetRadius(float r) { x10_radius = r; } - float GetKnockBackPower() const { return x14_knockback; } - void SetKnockBackPower(float k) { x14_knockback = k; } - float GetDamage() const { return x8_damage; } - void SetDamage(float d) { x8_damage = d; } - float GetDamage(const CDamageVulnerability& dVuln) const; - float GetRadiusDamage() const { return xc_radiusDamage; } - float GetRadiusDamage(const CDamageVulnerability& dVuln) const; - bool NoImmunity() const { return x18_noImmunity; } - void SetNoImmunity(bool b) { x18_noImmunity = b; } - void MultiplyDamage(float m) - { - x8_damage *= m; - xc_radiusDamage *= m; - x14_knockback *= m; - } - void MultiplyDamageAndRadius(float m) - { - x8_damage *= m; - xc_radiusDamage *= m; - x10_radius *= m; - x14_knockback *= m; - } + const CWeaponMode& GetWeaponMode() const { return x0_weaponMode; } + void SetWeaponMode(const CWeaponMode& mode) { x0_weaponMode = mode; } + float GetRadius() const { return x10_radius; } + void SetRadius(float r) { x10_radius = r; } + float GetKnockBackPower() const { return x14_knockback; } + void SetKnockBackPower(float k) { x14_knockback = k; } + float GetDamage() const { return x8_damage; } + void SetDamage(float d) { x8_damage = d; } + float GetDamage(const CDamageVulnerability& dVuln) const; + float GetRadiusDamage() const { return xc_radiusDamage; } + float GetRadiusDamage(const CDamageVulnerability& dVuln) const; + bool NoImmunity() const { return x18_noImmunity; } + void SetNoImmunity(bool b) { x18_noImmunity = b; } + void MultiplyDamage(float m) { + x8_damage *= m; + xc_radiusDamage *= m; + x14_knockback *= m; + } + void MultiplyDamageAndRadius(float m) { + x8_damage *= m; + xc_radiusDamage *= m; + x10_radius *= m; + x14_knockback *= m; + } }; -} - +} // namespace urde diff --git a/Runtime/World/CDamageVulnerability.cpp b/Runtime/World/CDamageVulnerability.cpp index 3801ceb9b..4a1fca361 100644 --- a/Runtime/World/CDamageVulnerability.cpp +++ b/Runtime/World/CDamageVulnerability.cpp @@ -1,7 +1,6 @@ #include "World/CDamageVulnerability.hpp" -namespace urde -{ +namespace urde { const CDamageVulnerability CDamageVulnerability::sNormalVulnerability( EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, @@ -35,84 +34,74 @@ const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability( EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::Weak); -static inline bool is_not_immune(EVulnerability vuln) -{ - return vuln != EVulnerability::Immune && vuln != EVulnerability::DirectImmune; +static inline bool is_not_immune(EVulnerability vuln) { + return vuln != EVulnerability::Immune && vuln != EVulnerability::DirectImmune; } -static inline bool is_normal_or_weak(EVulnerability vuln) -{ - return vuln == EVulnerability::Normal || vuln == EVulnerability::Weak; +static inline bool is_normal_or_weak(EVulnerability vuln) { + return vuln == EVulnerability::Normal || vuln == EVulnerability::Weak; } -void CDamageVulnerability::ConstructNew(CInputStream& in, int propCount) -{ - propCount -= 3; +void CDamageVulnerability::ConstructNew(CInputStream& in, int propCount) { + propCount -= 3; + EVulnerability* vulns = &x0_power; + for (int i = 0; i < std::min(propCount, 15); ++i) + vulns[i] = EVulnerability(in.readUint32Big()); + + if (propCount < 15) { + for (int i = propCount; i < 15; ++i) + vulns[i] = EVulnerability::Deflect; + } + + for (int i = 15; i < propCount; ++i) + in.readUint32Big(); + + x5c_deflected = EVulnerability(in.readUint32Big()); + EVulnerability* vulns2 = &x3c_chargedPower; + in.readUint32Big(); + for (int i = 0; i < 4; ++i) + vulns2[i] = EVulnerability(in.readUint32Big()); + + x60_chargedDeflected = EVulnerability(in.readUint32Big()); + EVulnerability* vulns3 = &x4c_superMissile; + in.readUint32Big(); + for (int i = 0; i < 4; ++i) + vulns3[i] = EVulnerability(in.readUint32Big()); + + x64_comboDeflected = EVulnerability(in.readUint32Big()); +} + +CDamageVulnerability::CDamageVulnerability(CInputStream& in) { + u32 propCount = in.readUint32Big(); + if (propCount == 11) { EVulnerability* vulns = &x0_power; - for (int i = 0; i < std::min(propCount, 15); ++i) - vulns[i] = EVulnerability(in.readUint32Big()); + for (int i = 0; i < 15; ++i) + vulns[i] = EVulnerability(in.readUint32Big()); - if (propCount < 15) - { - for (int i = propCount; i < 15; ++i) - vulns[i] = EVulnerability::Deflect; - } - - for (int i = 15; i < propCount; ++i) - in.readUint32Big(); - - x5c_deflected = EVulnerability(in.readUint32Big()); - EVulnerability* vulns2 = &x3c_chargedPower; - in.readUint32Big(); - for (int i = 0; i < 4; ++i) - vulns2[i] = EVulnerability(in.readUint32Big()); - - x60_chargedDeflected = EVulnerability(in.readUint32Big()); - EVulnerability* vulns3 = &x4c_superMissile; - in.readUint32Big(); - for (int i = 0; i < 4; ++i) - vulns3[i] = EVulnerability(in.readUint32Big()); - - x64_comboDeflected = EVulnerability(in.readUint32Big()); -} - -CDamageVulnerability::CDamageVulnerability(CInputStream& in) -{ - u32 propCount = in.readUint32Big(); - if (propCount == 11) - { - EVulnerability* vulns = &x0_power; - for (int i = 0; i < 15; ++i) - vulns[i] = EVulnerability(in.readUint32Big()); - - if (propCount == 15) - x5c_deflected = EVulnerability::Weak; - else - x5c_deflected = EVulnerability(in.readUint32Big()); - - x3c_chargedPower = x0_power; - x4c_superMissile = x0_power; - x40_chargedIce = x4_ice; - x50_iceSpreader = x4_ice; - x44_chargedWave = x8_wave; - x54_wavebuster = x8_wave; - x48_chargedPlasma = xc_plasma; - x58_flamethrower = xc_plasma; - } + if (propCount == 15) + x5c_deflected = EVulnerability::Weak; else - ConstructNew(in, propCount); + x5c_deflected = EVulnerability(in.readUint32Big()); + + x3c_chargedPower = x0_power; + x4c_superMissile = x0_power; + x40_chargedIce = x4_ice; + x50_iceSpreader = x4_ice; + x44_chargedWave = x8_wave; + x54_wavebuster = x8_wave; + x48_chargedPlasma = xc_plasma; + x58_flamethrower = xc_plasma; + } else + ConstructNew(in, propCount); } -CDamageVulnerability::CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, - EVulnerability plasma, EVulnerability bomb, EVulnerability powerBomb, - EVulnerability missile, EVulnerability boostBall, EVulnerability phazon, - EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3, - EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2, - EVulnerability chargedPower, EVulnerability chargedIce, - EVulnerability chargedWave, EVulnerability chargedPlasma, - EVulnerability superMissile, EVulnerability iceSpreader, - EVulnerability waveBuster, EVulnerability flameThrower, - EVulnerability deflected) +CDamageVulnerability::CDamageVulnerability( + EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma, EVulnerability bomb, + EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall, EVulnerability phazon, + EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3, EVulnerability enemyWp4, + EVulnerability v1, EVulnerability v2, EVulnerability chargedPower, EVulnerability chargedIce, + EVulnerability chargedWave, EVulnerability chargedPlasma, EVulnerability superMissile, EVulnerability iceSpreader, + EVulnerability waveBuster, EVulnerability flameThrower, EVulnerability deflected) : x0_power(power) , x4_ice(ice) , x8_wave(wave) @@ -136,142 +125,123 @@ CDamageVulnerability::CDamageVulnerability(EVulnerability power, EVulnerability , x50_iceSpreader(iceSpreader) , x54_wavebuster(waveBuster) , x58_flamethrower(flameThrower) -, x5c_deflected(deflected) -{ +, x5c_deflected(deflected) {} + +EVulnerability CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const { + if (mode.IsCharged()) + return x60_chargedDeflected; + if (mode.IsComboed()) + return x64_comboDeflected; + return x5c_deflected; } -EVulnerability CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const -{ - if (mode.IsCharged()) - return x60_chargedDeflected; - if (mode.IsComboed()) - return x64_comboDeflected; - return x5c_deflected; -} - -bool CDamageVulnerability::WeaponHurts(const CWeaponMode& mode, bool ignoreDirect) const -{ - if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) - return false; - if (mode.IsInstantKill()) - return true; - - EVulnerability normalVuln = (&x0_power)[u32(mode.GetType())]; - bool normalHurts = true; - if (ignoreDirect) - { - normalHurts = is_normal_or_weak(normalVuln); - } - else - { - if (!is_normal_or_weak(normalVuln) && - (normalVuln != EVulnerability::DirectWeak && normalVuln != EVulnerability::DirectNormal)) - normalHurts = false; - } - - bool chargedHurts = true; - bool comboedHurts = true; - if (mode.GetType() < EWeaponType::Bomb) - { - EVulnerability chargedVuln = (&x3c_chargedPower)[u32(mode.GetType())]; - EVulnerability comboedVuln = (&x4c_superMissile)[u32(mode.GetType())]; - if (ignoreDirect) - { - chargedHurts = is_normal_or_weak(chargedVuln); - comboedHurts = is_normal_or_weak(comboedVuln); - } - else - { - if (!is_normal_or_weak(chargedVuln) && - (chargedVuln != EVulnerability::DirectWeak && chargedVuln != EVulnerability::DirectNormal)) - chargedHurts = false; - if (!is_normal_or_weak(comboedVuln) && - (comboedVuln != EVulnerability::DirectWeak && comboedVuln != EVulnerability::DirectNormal)) - comboedHurts = false; - } - } - - if (normalHurts && !mode.IsCharged() && !mode.IsComboed()) - return true; - if (chargedHurts && mode.IsCharged()) - return true; - return comboedHurts && mode.IsComboed(); -} - -bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect) const -{ - if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) - return false; - if (mode.IsInstantKill()) - return true; - - bool normalVuln; - if (!checkDirect) - normalVuln = (&x0_power)[u32(mode.GetType())] != EVulnerability::Immune; - else - normalVuln = is_not_immune((&x0_power)[u32(mode.GetType())]); - - bool chargedVuln = true; - bool comboedVuln = true; - - if (mode.GetType() < EWeaponType::Bomb) - { - if (!checkDirect) - { - chargedVuln = (&x3c_chargedPower)[u32(mode.GetType())] != EVulnerability::Immune; - comboedVuln = (&x4c_superMissile)[u32(mode.GetType())] != EVulnerability::Immune; - } - else - { - chargedVuln = is_not_immune((&x3c_chargedPower)[u32(mode.GetType())]); - comboedVuln = is_not_immune((&x4c_superMissile)[u32(mode.GetType())]); - } - } - - if (normalVuln && !mode.IsCharged() && !mode.IsComboed()) - return true; - if (chargedVuln && mode.IsCharged()) - return true; - if (comboedVuln && mode.IsComboed()) - return true; +bool CDamageVulnerability::WeaponHurts(const CWeaponMode& mode, bool ignoreDirect) const { + if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) return false; + if (mode.IsInstantKill()) + return true; + + EVulnerability normalVuln = (&x0_power)[u32(mode.GetType())]; + bool normalHurts = true; + if (ignoreDirect) { + normalHurts = is_normal_or_weak(normalVuln); + } else { + if (!is_normal_or_weak(normalVuln) && + (normalVuln != EVulnerability::DirectWeak && normalVuln != EVulnerability::DirectNormal)) + normalHurts = false; + } + + bool chargedHurts = true; + bool comboedHurts = true; + if (mode.GetType() < EWeaponType::Bomb) { + EVulnerability chargedVuln = (&x3c_chargedPower)[u32(mode.GetType())]; + EVulnerability comboedVuln = (&x4c_superMissile)[u32(mode.GetType())]; + if (ignoreDirect) { + chargedHurts = is_normal_or_weak(chargedVuln); + comboedHurts = is_normal_or_weak(comboedVuln); + } else { + if (!is_normal_or_weak(chargedVuln) && + (chargedVuln != EVulnerability::DirectWeak && chargedVuln != EVulnerability::DirectNormal)) + chargedHurts = false; + if (!is_normal_or_weak(comboedVuln) && + (comboedVuln != EVulnerability::DirectWeak && comboedVuln != EVulnerability::DirectNormal)) + comboedHurts = false; + } + } + + if (normalHurts && !mode.IsCharged() && !mode.IsComboed()) + return true; + if (chargedHurts && mode.IsCharged()) + return true; + return comboedHurts && mode.IsComboed(); } -EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const -{ - if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) - return EVulnerability::Deflect; +bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect) const { + if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) + return false; + if (mode.IsInstantKill()) + return true; - if (mode.IsInstantKill()) - return EVulnerability::Normal; + bool normalVuln; + if (!checkDirect) + normalVuln = (&x0_power)[u32(mode.GetType())] != EVulnerability::Immune; + else + normalVuln = is_not_immune((&x0_power)[u32(mode.GetType())]); - EVulnerability vuln = (&x0_power)[u32(mode.GetType())]; - if (mode.IsCharged()) - { - if (mode.GetType() < EWeaponType::Bomb) - vuln = (&x3c_chargedPower)[u32(mode.GetType())]; - else - vuln = EVulnerability::Normal; + bool chargedVuln = true; + bool comboedVuln = true; + + if (mode.GetType() < EWeaponType::Bomb) { + if (!checkDirect) { + chargedVuln = (&x3c_chargedPower)[u32(mode.GetType())] != EVulnerability::Immune; + comboedVuln = (&x4c_superMissile)[u32(mode.GetType())] != EVulnerability::Immune; + } else { + chargedVuln = is_not_immune((&x3c_chargedPower)[u32(mode.GetType())]); + comboedVuln = is_not_immune((&x4c_superMissile)[u32(mode.GetType())]); } + } - if (mode.IsComboed()) - { - if (mode.GetType() < EWeaponType::Bomb) - vuln = (&x3c_chargedPower)[u32(mode.GetType())]; - else - vuln = EVulnerability::Normal; - } + if (normalVuln && !mode.IsCharged() && !mode.IsComboed()) + return true; + if (chargedVuln && mode.IsCharged()) + return true; + if (comboedVuln && mode.IsComboed()) + return true; + return false; +} - if (ignoreDirect) - return vuln; +EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const { + if (mode.GetType() == EWeaponType::None || mode.GetType() > EWeaponType::OrangePhazon) + return EVulnerability::Deflect; - if (vuln == EVulnerability::DirectWeak) - return EVulnerability::Weak; - else if (vuln == EVulnerability::DirectNormal) - return EVulnerability::Normal; - else if (vuln == EVulnerability::DirectImmune) - return EVulnerability::Immune; + if (mode.IsInstantKill()) + return EVulnerability::Normal; + EVulnerability vuln = (&x0_power)[u32(mode.GetType())]; + if (mode.IsCharged()) { + if (mode.GetType() < EWeaponType::Bomb) + vuln = (&x3c_chargedPower)[u32(mode.GetType())]; + else + vuln = EVulnerability::Normal; + } + + if (mode.IsComboed()) { + if (mode.GetType() < EWeaponType::Bomb) + vuln = (&x3c_chargedPower)[u32(mode.GetType())]; + else + vuln = EVulnerability::Normal; + } + + if (ignoreDirect) return vuln; + + if (vuln == EVulnerability::DirectWeak) + return EVulnerability::Weak; + else if (vuln == EVulnerability::DirectNormal) + return EVulnerability::Normal; + else if (vuln == EVulnerability::DirectImmune) + return EVulnerability::Immune; + + return vuln; } -} +} // namespace urde diff --git a/Runtime/World/CDamageVulnerability.hpp b/Runtime/World/CDamageVulnerability.hpp index 547b7dd77..df0b5975e 100644 --- a/Runtime/World/CDamageVulnerability.hpp +++ b/Runtime/World/CDamageVulnerability.hpp @@ -3,81 +3,67 @@ #include "RetroTypes.hpp" #include "Weapon/CWeaponMode.hpp" -namespace urde -{ +namespace urde { -enum class EVulnerability -{ - Weak, - Normal, - Deflect, - Immune, - PassThrough, - DirectWeak, - DirectNormal, - DirectImmune -}; +enum class EVulnerability { Weak, Normal, Deflect, Immune, PassThrough, DirectWeak, DirectNormal, DirectImmune }; -class CDamageVulnerability -{ - EVulnerability x0_power; - EVulnerability x4_ice; - EVulnerability x8_wave; - EVulnerability xc_plasma; - EVulnerability x10_bomb; - EVulnerability x14_powerbomb; - EVulnerability x18_missile; - EVulnerability x1c_boostBall; - EVulnerability x20_phazon; - EVulnerability x24_enemyWp1; - EVulnerability x28_enemyWp2Poison; - EVulnerability x2c_enemyWp3Lava; - EVulnerability x30_enemyWp4; - EVulnerability x34_unk1; - EVulnerability x38_unk2; +class CDamageVulnerability { + EVulnerability x0_power; + EVulnerability x4_ice; + EVulnerability x8_wave; + EVulnerability xc_plasma; + EVulnerability x10_bomb; + EVulnerability x14_powerbomb; + EVulnerability x18_missile; + EVulnerability x1c_boostBall; + EVulnerability x20_phazon; + EVulnerability x24_enemyWp1; + EVulnerability x28_enemyWp2Poison; + EVulnerability x2c_enemyWp3Lava; + EVulnerability x30_enemyWp4; + EVulnerability x34_unk1; + EVulnerability x38_unk2; - EVulnerability x3c_chargedPower; - EVulnerability x40_chargedIce; - EVulnerability x44_chargedWave; - EVulnerability x48_chargedPlasma; + EVulnerability x3c_chargedPower; + EVulnerability x40_chargedIce; + EVulnerability x44_chargedWave; + EVulnerability x48_chargedPlasma; - EVulnerability x4c_superMissile; - EVulnerability x50_iceSpreader; - EVulnerability x54_wavebuster; - EVulnerability x58_flamethrower; + EVulnerability x4c_superMissile; + EVulnerability x50_iceSpreader; + EVulnerability x54_wavebuster; + EVulnerability x58_flamethrower; - EVulnerability x5c_deflected; - EVulnerability x60_chargedDeflected; - EVulnerability x64_comboDeflected; + EVulnerability x5c_deflected; + EVulnerability x60_chargedDeflected; + EVulnerability x64_comboDeflected; - void ConstructNew(CInputStream& in, int propCount); + void ConstructNew(CInputStream& in, int propCount); - static const CDamageVulnerability sNormalVulnerability; - static const CDamageVulnerability sImmuneVulnerability; - static const CDamageVulnerability sReflectVulnerability; - static const CDamageVulnerability sPassThroughVulnerability; + static const CDamageVulnerability sNormalVulnerability; + static const CDamageVulnerability sImmuneVulnerability; + static const CDamageVulnerability sReflectVulnerability; + static const CDamageVulnerability sPassThroughVulnerability; public: - CDamageVulnerability(CInputStream& in); - CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma, - EVulnerability bomb, EVulnerability powerBomb, EVulnerability missile, - EVulnerability boostBall, EVulnerability phazon, EVulnerability enemyWp1, - EVulnerability enemyWp2, EVulnerability enemyWp3, EVulnerability enemyWp4, EVulnerability v1, - EVulnerability v2, EVulnerability chargedPower, EVulnerability chargedIce, - EVulnerability chargedWave, EVulnerability chargedPlasma, EVulnerability superMissile, - EVulnerability iceSpreader, EVulnerability waveBuster, EVulnerability flameThrower, - EVulnerability deflected); + CDamageVulnerability(CInputStream& in); + CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma, + EVulnerability bomb, EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall, + EVulnerability phazon, EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3, + EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2, EVulnerability chargedPower, + EVulnerability chargedIce, EVulnerability chargedWave, EVulnerability chargedPlasma, + EVulnerability superMissile, EVulnerability iceSpreader, EVulnerability waveBuster, + EVulnerability flameThrower, EVulnerability deflected); - EVulnerability GetDeflectionType(const CWeaponMode& mode) const; + EVulnerability GetDeflectionType(const CWeaponMode& mode) const; - bool WeaponHurts(const CWeaponMode&, bool ignoreDirect) const; - bool WeaponHits(const CWeaponMode& mode, bool checkDirect) const; - EVulnerability GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const; + bool WeaponHurts(const CWeaponMode&, bool ignoreDirect) const; + bool WeaponHits(const CWeaponMode& mode, bool checkDirect) const; + EVulnerability GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const; - static const CDamageVulnerability& NormalVulnerabilty() { return sNormalVulnerability; } - static const CDamageVulnerability& ImmuneVulnerabilty() { return sImmuneVulnerability; } - static const CDamageVulnerability& ReflectVulnerabilty() { return sReflectVulnerability; } - static const CDamageVulnerability& PasshThroughVulnerabilty() { return sPassThroughVulnerability; } + static const CDamageVulnerability& NormalVulnerabilty() { return sNormalVulnerability; } + static const CDamageVulnerability& ImmuneVulnerabilty() { return sImmuneVulnerability; } + static const CDamageVulnerability& ReflectVulnerabilty() { return sReflectVulnerability; } + static const CDamageVulnerability& PasshThroughVulnerabilty() { return sPassThroughVulnerability; } }; -} - +} // namespace urde diff --git a/Runtime/World/CDestroyableRock.cpp b/Runtime/World/CDestroyableRock.cpp index 5739147f3..99e6072c6 100644 --- a/Runtime/World/CDestroyableRock.cpp +++ b/Runtime/World/CDestroyableRock.cpp @@ -1,16 +1,13 @@ #include "CDestroyableRock.hpp" -namespace urde -{ +namespace urde { CDestroyableRock::CDestroyableRock(TUniqueId id, bool active, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& modelData, float mass, const CHealthInfo& health, - const CDamageVulnerability& vulnerability, const CMaterialList& matList, CAssetId fsm, - const CActorParameters& actParams, const CModelData& modelData2) -: CAi(id, active, name, info, xf, std::move(modelData), modelData.GetBounds(), - mass, health, vulnerability, matList, fsm, actParams, 0.3f, 0.8f) -{ + const zeus::CTransform& xf, CModelData&& modelData, float mass, + const CHealthInfo& health, const CDamageVulnerability& vulnerability, + const CMaterialList& matList, CAssetId fsm, const CActorParameters& actParams, + const CModelData& modelData2) +: CAi(id, active, name, info, xf, std::move(modelData), modelData.GetBounds(), mass, health, vulnerability, matList, + fsm, actParams, 0.3f, 0.8f) {} -} - -} +} // namespace urde diff --git a/Runtime/World/CDestroyableRock.hpp b/Runtime/World/CDestroyableRock.hpp index e47f8253a..df5269be5 100644 --- a/Runtime/World/CDestroyableRock.hpp +++ b/Runtime/World/CDestroyableRock.hpp @@ -2,17 +2,14 @@ #include "CAi.hpp" -namespace urde -{ +namespace urde { -class CDestroyableRock : public CAi -{ +class CDestroyableRock : public CAi { public: - CDestroyableRock(TUniqueId id, bool active, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& modelData, float mass, const CHealthInfo& health, - const CDamageVulnerability& vulnerability, const CMaterialList& matList, CAssetId fsm, - const CActorParameters& actParams, const CModelData& modelData2); + CDestroyableRock(TUniqueId id, bool active, std::string_view name, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& modelData, float mass, const CHealthInfo& health, + const CDamageVulnerability& vulnerability, const CMaterialList& matList, CAssetId fsm, + const CActorParameters& actParams, const CModelData& modelData2); }; -} - +} // namespace urde diff --git a/Runtime/World/CEffect.cpp b/Runtime/World/CEffect.cpp index 3f9d5924c..431f300d2 100644 --- a/Runtime/World/CEffect.cpp +++ b/Runtime/World/CEffect.cpp @@ -1,13 +1,10 @@ #include "CEffect.hpp" #include "CActorParameters.hpp" -namespace urde -{ +namespace urde { CEffect::CEffect(TUniqueId uid, const CEntityInfo& info, bool active, std::string_view name, const zeus::CTransform& xf) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic), - CActorParameters::None(), kInvalidUniqueId) -{ -} + CActorParameters::None(), kInvalidUniqueId) {} -} +} // namespace urde diff --git a/Runtime/World/CEffect.hpp b/Runtime/World/CEffect.hpp index edc97d86f..9a1d68f76 100644 --- a/Runtime/World/CEffect.hpp +++ b/Runtime/World/CEffect.hpp @@ -2,18 +2,14 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { -class CEffect : public CActor -{ +class CEffect : public CActor { public: - CEffect(TUniqueId uid, const CEntityInfo& info, bool active, std::string_view name, - const zeus::CTransform& xf); + CEffect(TUniqueId uid, const CEntityInfo& info, bool active, std::string_view name, const zeus::CTransform& xf); - virtual void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} - virtual void Render(const CStateManager&) const {} + virtual void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} + virtual void Render(const CStateManager&) const {} }; -} - +} // namespace urde diff --git a/Runtime/World/CEnergyDrainSource.cpp b/Runtime/World/CEnergyDrainSource.cpp index b5934bcd7..72e84a351 100644 --- a/Runtime/World/CEnergyDrainSource.cpp +++ b/Runtime/World/CEnergyDrainSource.cpp @@ -1,12 +1,7 @@ #include "CEnergyDrainSource.hpp" -namespace urde -{ +namespace urde { -CEnergyDrainSource::CEnergyDrainSource(TUniqueId src, float intensity) - : x0_source(src) - , x4_intensity(intensity) -{ -} +CEnergyDrainSource::CEnergyDrainSource(TUniqueId src, float intensity) : x0_source(src), x4_intensity(intensity) {} -} +} // namespace urde diff --git a/Runtime/World/CEnergyDrainSource.hpp b/Runtime/World/CEnergyDrainSource.hpp index 865774dfb..4d2cdfe35 100644 --- a/Runtime/World/CEnergyDrainSource.hpp +++ b/Runtime/World/CEnergyDrainSource.hpp @@ -2,16 +2,15 @@ #include "RetroTypes.hpp" -namespace urde -{ -class CEnergyDrainSource -{ - TUniqueId x0_source; - float x4_intensity; +namespace urde { +class CEnergyDrainSource { + TUniqueId x0_source; + float x4_intensity; + public: - CEnergyDrainSource(TUniqueId src, float intensity); - TUniqueId GetEnergyDrainSourceId() const { return x0_source; } - void SetEnergyDrainIntensity(float in) { x4_intensity = in; } - float GetEnergyDrainIntensity() const { return x4_intensity; } + CEnergyDrainSource(TUniqueId src, float intensity); + TUniqueId GetEnergyDrainSourceId() const { return x0_source; } + void SetEnergyDrainIntensity(float in) { x4_intensity = in; } + float GetEnergyDrainIntensity() const { return x4_intensity; } }; -} +} // namespace urde diff --git a/Runtime/World/CEntity.cpp b/Runtime/World/CEntity.cpp index f50587be0..a48433cba 100644 --- a/Runtime/World/CEntity.cpp +++ b/Runtime/World/CEntity.cpp @@ -1,56 +1,50 @@ #include "CEntity.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { const std::vector CEntity::NullConnectionList; CEntity::CEntity(TUniqueId uniqueId, const CEntityInfo& info, bool active, std::string_view name) -: x4_areaId(info.GetAreaId()), x8_uid(uniqueId), xc_editorId(info.GetEditorId()), x10_name(name), - x20_conns(info.GetConnectionList()) -{ - x30_24_active = active; - x30_27_inUse = x4_areaId != kInvalidAreaId; +: x4_areaId(info.GetAreaId()) +, x8_uid(uniqueId) +, xc_editorId(info.GetEditorId()) +, x10_name(name) +, x20_conns(info.GetConnectionList()) { + x30_24_active = active; + x30_27_inUse = x4_areaId != kInvalidAreaId; } -void CEntity::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - switch (msg) - { - case EScriptObjectMessage::Activate: - if (!GetActive()) - { - SetActive(true); - SendScriptMsgs(EScriptObjectState::Active, stateMgr, EScriptObjectMessage::None); - } - break; - case EScriptObjectMessage::Deactivate: - if (GetActive()) - { - SetActive(false); - SendScriptMsgs(EScriptObjectState::Inactive, stateMgr, EScriptObjectMessage::None); - } - break; - case EScriptObjectMessage::ToggleActive: - if (GetActive()) - { - SetActive(false); - SendScriptMsgs(EScriptObjectState::Inactive, stateMgr, EScriptObjectMessage::None); - } - else - { - SetActive(true); - SendScriptMsgs(EScriptObjectState::Active, stateMgr, EScriptObjectMessage::None); - } - break; - default: break; +void CEntity::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + switch (msg) { + case EScriptObjectMessage::Activate: + if (!GetActive()) { + SetActive(true); + SendScriptMsgs(EScriptObjectState::Active, stateMgr, EScriptObjectMessage::None); } + break; + case EScriptObjectMessage::Deactivate: + if (GetActive()) { + SetActive(false); + SendScriptMsgs(EScriptObjectState::Inactive, stateMgr, EScriptObjectMessage::None); + } + break; + case EScriptObjectMessage::ToggleActive: + if (GetActive()) { + SetActive(false); + SendScriptMsgs(EScriptObjectState::Inactive, stateMgr, EScriptObjectMessage::None); + } else { + SetActive(true); + SendScriptMsgs(EScriptObjectState::Active, stateMgr, EScriptObjectMessage::None); + } + break; + default: + break; + } } -void CEntity::SendScriptMsgs(EScriptObjectState state, CStateManager& stateMgr, EScriptObjectMessage skipMsg) -{ - for (const SConnection& conn : x20_conns) - if (conn.x0_state == state && conn.x4_msg != skipMsg) - stateMgr.SendScriptMsg(x8_uid, conn.x8_objId, conn.x4_msg, state); -} +void CEntity::SendScriptMsgs(EScriptObjectState state, CStateManager& stateMgr, EScriptObjectMessage skipMsg) { + for (const SConnection& conn : x20_conns) + if (conn.x0_state == state && conn.x4_msg != skipMsg) + stateMgr.SendScriptMsg(x8_uid, conn.x8_objId, conn.x4_msg, state); } +} // namespace urde diff --git a/Runtime/World/CEntity.hpp b/Runtime/World/CEntity.hpp index fe477f147..ad1f9aa21 100644 --- a/Runtime/World/CEntity.hpp +++ b/Runtime/World/CEntity.hpp @@ -4,72 +4,64 @@ #include "ScriptObjectSupport.hpp" #include "CEntityInfo.hpp" -namespace urde -{ +namespace urde { class CStateManager; class IVisitor; -class CEntity -{ - friend class CStateManager; - friend class CObjectList; -protected: - TAreaId x4_areaId; - TUniqueId x8_uid; - TEditorId xc_editorId; - std::string x10_name; - std::vector x20_conns; +class CEntity { + friend class CStateManager; + friend class CObjectList; - union - { - struct - { - bool x30_24_active : 1; - bool x30_25_inGraveyard : 1; - bool x30_26_scriptingBlocked : 1; - bool x30_27_inUse : 1; - }; - u8 _dummy = 0; +protected: + TAreaId x4_areaId; + TUniqueId x8_uid; + TEditorId xc_editorId; + std::string x10_name; + std::vector x20_conns; + + union { + struct { + bool x30_24_active : 1; + bool x30_25_inGraveyard : 1; + bool x30_26_scriptingBlocked : 1; + bool x30_27_inUse : 1; }; + u8 _dummy = 0; + }; public: - static const std::vector NullConnectionList; - virtual ~CEntity() = default; - CEntity(TUniqueId uid, const CEntityInfo& info, bool active, std::string_view name); - virtual void Accept(IVisitor& visitor)=0; - virtual void PreThink(float, CStateManager&) {} - virtual void Think(float, CStateManager&) {} - virtual void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); - virtual void SetActive(bool active) {x30_24_active = active;} + static const std::vector NullConnectionList; + virtual ~CEntity() = default; + CEntity(TUniqueId uid, const CEntityInfo& info, bool active, std::string_view name); + virtual void Accept(IVisitor& visitor) = 0; + virtual void PreThink(float, CStateManager&) {} + virtual void Think(float, CStateManager&) {} + virtual void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + virtual void SetActive(bool active) { x30_24_active = active; } - bool GetActive() const {return x30_24_active;} - void ToggleActive() - { - x30_24_active ^= 1; - } + bool GetActive() const { return x30_24_active; } + void ToggleActive() { x30_24_active ^= 1; } - bool IsInGraveyard() const { return x30_25_inGraveyard; } - void SetIsInGraveyard(bool in) { x30_25_inGraveyard = in; } - bool IsScriptingBlocked() const { return x30_26_scriptingBlocked; } - void SetIsScriptingBlocked(bool blocked) { x30_26_scriptingBlocked = blocked; } - bool IsInUse() const { return x30_27_inUse; } + bool IsInGraveyard() const { return x30_25_inGraveyard; } + void SetIsInGraveyard(bool in) { x30_25_inGraveyard = in; } + bool IsScriptingBlocked() const { return x30_26_scriptingBlocked; } + void SetIsScriptingBlocked(bool blocked) { x30_26_scriptingBlocked = blocked; } + bool IsInUse() const { return x30_27_inUse; } - TAreaId GetAreaId() const - { - if (x30_27_inUse) - return x4_areaId; - return kInvalidAreaId; - } - TAreaId GetAreaIdAlways() const { return x4_areaId; } - TUniqueId GetUniqueId() const {return x8_uid;} - TEditorId GetEditorId() const {return xc_editorId;} - void SendScriptMsgs(EScriptObjectState state, CStateManager& stateMgr, EScriptObjectMessage msg); + TAreaId GetAreaId() const { + if (x30_27_inUse) + return x4_areaId; + return kInvalidAreaId; + } + TAreaId GetAreaIdAlways() const { return x4_areaId; } + TUniqueId GetUniqueId() const { return x8_uid; } + TEditorId GetEditorId() const { return xc_editorId; } + void SendScriptMsgs(EScriptObjectState state, CStateManager& stateMgr, EScriptObjectMessage msg); - const std::vector& GetConnectionList() const { return x20_conns; } - std::vector& ConnectionList() { return x20_conns; } + const std::vector& GetConnectionList() const { return x20_conns; } + std::vector& ConnectionList() { return x20_conns; } - std::string_view GetName() const { return x10_name; } + std::string_view GetName() const { return x10_name; } }; -} - +} // namespace urde diff --git a/Runtime/World/CEntityInfo.hpp b/Runtime/World/CEntityInfo.hpp index f7a9804d1..51758e6fe 100644 --- a/Runtime/World/CEntityInfo.hpp +++ b/Runtime/World/CEntityInfo.hpp @@ -5,26 +5,23 @@ #include "RetroTypes.hpp" #include "World/ScriptObjectSupport.hpp" -namespace urde -{ -struct SConnection -{ - EScriptObjectState x0_state; - EScriptObjectMessage x4_msg; - TEditorId x8_objId; +namespace urde { +struct SConnection { + EScriptObjectState x0_state; + EScriptObjectMessage x4_msg; + TEditorId x8_objId; }; -class CEntityInfo -{ - TAreaId x0_areaId; - std::vector x4_conns; - TEditorId x14_editorId; +class CEntityInfo { + TAreaId x0_areaId; + std::vector x4_conns; + TEditorId x14_editorId; + public: - CEntityInfo(TAreaId aid, const std::vector& conns, TEditorId eid = kInvalidEditorId) - : x0_areaId(aid), x4_conns(conns), x14_editorId(eid) {} - TAreaId GetAreaId() const {return x0_areaId;} - std::vector GetConnectionList() const { return x4_conns; } - TEditorId GetEditorId() const { return x14_editorId; } + CEntityInfo(TAreaId aid, const std::vector& conns, TEditorId eid = kInvalidEditorId) + : x0_areaId(aid), x4_conns(conns), x14_editorId(eid) {} + TAreaId GetAreaId() const { return x0_areaId; } + std::vector GetConnectionList() const { return x4_conns; } + TEditorId GetEditorId() const { return x14_editorId; } }; -} - +} // namespace urde diff --git a/Runtime/World/CEnvFxManager.cpp b/Runtime/World/CEnvFxManager.cpp index bd4053010..5030e2810 100644 --- a/Runtime/World/CEnvFxManager.cpp +++ b/Runtime/World/CEnvFxManager.cpp @@ -15,690 +15,592 @@ #include "World/CScriptWater.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { static rstl::reserved_vector g_SnowForces; CEnvFxManagerGrid::CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus::CVector2i& extent, const std::vector& initialParticles, int reserve, CEnvFxManager& parent, boo::IGraphicsDataFactory::Context& ctx) -: x4_position(position), xc_extent(extent), x1c_particles(initialParticles), - m_instBuf(parent.m_instPool.allocateBlock(CGraphics::g_BooFactory, reserve)), - m_uniformBuf(parent.m_uniformPool.allocateBlock(CGraphics::g_BooFactory)), - m_lineRenderer(ctx, CLineRenderer::EPrimitiveMode::Lines, reserve * 2, - parent.x40_txtrEnvGradient->GetBooTexture(), true, true) -{ - x1c_particles.reserve(reserve); - CEnvFxShaders::BuildShaderDataBinding(ctx, parent, *this); +: x4_position(position) +, xc_extent(extent) +, x1c_particles(initialParticles) +, m_instBuf(parent.m_instPool.allocateBlock(CGraphics::g_BooFactory, reserve)) +, m_uniformBuf(parent.m_uniformPool.allocateBlock(CGraphics::g_BooFactory)) +, m_lineRenderer(ctx, CLineRenderer::EPrimitiveMode::Lines, reserve * 2, parent.x40_txtrEnvGradient->GetBooTexture(), + true, true) { + x1c_particles.reserve(reserve); + CEnvFxShaders::BuildShaderDataBinding(ctx, parent, *this); } -CEnvFxManager::CEnvFxManager() -{ - x40_txtrEnvGradient = g_SimplePool->GetObj("TXTR_EnvGradient"); - x40_txtrEnvGradient->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge); - xb58_envRainSplash = g_SimplePool->GetObj("PART_EnvRainSplash"); - xb74_txtrSnowFlake = g_SimplePool->GetObj("TXTR_SnowFlake"); - xc48_underwaterFlake = g_SimplePool->GetObj("TXTR_UnderwaterFlake"); - CRandom16 random(0); - CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) - { - m_fogUniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(CGraphics::g_Fog), 1); - for (int i = 0; i < 8; ++i) - for (int j = 0; j < 8; ++j) - x50_grids.emplace_back(zeus::CVector2i{j * 2048, i * 2048}, zeus::CVector2i{2048, 2048}, - std::vector{}, 171, *this, ctx); - return true; - } BooTrace); - for (int i = 0; i < 16; ++i) - xb84_snowZDeltas.emplace_back(0.f, 0.f, random.Range(-2.f, -4.f)); -} - -void CEnvFxManager::SetSplashEffectRate(float rate, const CStateManager& mgr) -{ - if (TCastToPtr splashEffect = mgr.ObjectById(xb68_envRainSplashId)) - if (splashEffect->IsElementGen()) - splashEffect->GetParticleGen()->SetGeneratorRate(rate); -} - -/* Used to be MIDI scale */ -static float CalcRainVolume(float f) -{ - if (f < 0.1f) - return (f / 0.1f * 74.f) / 127.f; - else - return (f / 0.9f * 21.f + 74.f) / 127.f; -} - -/* Used to be MIDI scale */ -static float CalcRainPitch(float f) -{ - return f - 1.f; -} - -void CEnvFxManager::UpdateRainSounds(const CStateManager& mgr) -{ - if (mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain) - { - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - float rainVol = CalcRainVolume(x30_fxDensity); - if (!xb6a_rainSoundActive) - { - xb6c_leftRainSound = CSfxManager::AddEmitter(SFXsfx09F0, - zeus::CVector3f::skZero, zeus::CVector3f::skZero, - false, true, 0xff, kInvalidAreaId); - xb70_rightRainSound = CSfxManager::AddEmitter(SFXsfx09F1, - zeus::CVector3f::skZero, zeus::CVector3f::skZero, - false, true, 0xff, kInvalidAreaId); - xb6a_rainSoundActive = true; - } - CSfxManager::UpdateEmitter(xb6c_leftRainSound, camXf.origin - camXf.basis[0], camXf.basis[0], rainVol); - CSfxManager::UpdateEmitter(xb70_rightRainSound, camXf.origin + camXf.basis[0], -camXf.basis[0], rainVol); - float rainPitch = CalcRainPitch(x30_fxDensity); - CSfxManager::PitchBend(xb6c_leftRainSound, rainPitch); - CSfxManager::PitchBend(xb70_rightRainSound, rainPitch); - } - else if (xb6a_rainSoundActive) - { - CSfxManager::RemoveEmitter(xb6c_leftRainSound); - CSfxManager::RemoveEmitter(xb70_rightRainSound); - xb6a_rainSoundActive = false; - } -} - -zeus::CVector3f CEnvFxManager::GetParticleBoundsToWorldScale() const -{ - return (x0_particleBounds.max - x0_particleBounds.min) / 127.f; -} - -zeus::CTransform CEnvFxManager::GetParticleBoundsToWorldTransform() const -{ - return zeus::CTransform::Translate(x18_focusCellPosition) - * zeus::CTransform::Translate(zeus::CVector3f(-31.75f)) - * zeus::CTransform::Scale(GetParticleBoundsToWorldScale()); -} - -void CEnvFxManager::UpdateVisorSplash(CStateManager& mgr, float dt, const zeus::CTransform& camXf) -{ - EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx(); - if (xb68_envRainSplashId != kInvalidUniqueId) - if (TCastToPtr splashEffect = mgr.ObjectById(xb68_envRainSplashId)) - mgr.SetActorAreaId(*splashEffect, mgr.GetNextAreaId()); - float camUpness = camXf.basis[1].dot(zeus::CVector3f::skUp); - float splashRateFactor; - if (x24_enableSplash) - splashRateFactor = std::max(0.f, camUpness) * x30_fxDensity; - else - splashRateFactor = 0.f; - float forwardRateFactor = 0.f; - if (x24_enableSplash && camUpness >= -0.1f) - { - zeus::CVector3f pRelVel = mgr.GetPlayer().GetTransform().transposeRotate(mgr.GetPlayer().GetVelocity()); - if (pRelVel.canBeNormalized()) - { - float velMag = pRelVel.magnitude(); - zeus::CVector3f normRelVel = pRelVel * (1.f / velMag); - forwardRateFactor = std::min(velMag / 60.f, 1.f) * normRelVel.dot(zeus::CVector3f::skForward); - } - } - float additionalFactor; - if (fxType == EEnvFxType::Rain) - additionalFactor = splashRateFactor + forwardRateFactor; - else - additionalFactor = 0.f; - SetSplashEffectRate(xb54_baseSplashRate + additionalFactor, mgr); - xb54_baseSplashRate = 0.f; -} - -void CEnvFxManager::MoveWrapCells(s32 moveX, s32 moveY) -{ - if (moveX == 0 && moveY == 0) - return; - bool r5 = std::fabs(moveX) >= 1.f || std::fabs(moveY) >= 1.f; - s32 moveXMaj = moveX << 11; - s32 moveYMaj = moveY << 11; +CEnvFxManager::CEnvFxManager() { + x40_txtrEnvGradient = g_SimplePool->GetObj("TXTR_EnvGradient"); + x40_txtrEnvGradient->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge); + xb58_envRainSplash = g_SimplePool->GetObj("PART_EnvRainSplash"); + xb74_txtrSnowFlake = g_SimplePool->GetObj("TXTR_SnowFlake"); + xc48_underwaterFlake = g_SimplePool->GetObj("TXTR_UnderwaterFlake"); + CRandom16 random(0); + CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) { + m_fogUniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(CGraphics::g_Fog), 1); for (int i = 0; i < 8; ++i) - { - s32 r28 = i - moveY; - for (int j = 0; j < 8; ++j) - { - CEnvFxManagerGrid& grid = x50_grids[i * 8 + j]; - s32 r3 = j - moveX; - if (!r5) - { - CEnvFxManagerGrid& otherGrid = x50_grids[r28 * 8 + r3]; - grid.x14_block = otherGrid.x14_block; - } - else - { - grid.x0_24_blockDirty = true; - } - grid.x4_position = zeus::CVector2i((moveXMaj + grid.x4_position.x) & 0x3fff, - (moveYMaj + grid.x4_position.y) & 0x3fff); - } + for (int j = 0; j < 8; ++j) + x50_grids.emplace_back(zeus::CVector2i{j * 2048, i * 2048}, zeus::CVector2i{2048, 2048}, + std::vector{}, 171, *this, ctx); + return true; + } BooTrace); + for (int i = 0; i < 16; ++i) + xb84_snowZDeltas.emplace_back(0.f, 0.f, random.Range(-2.f, -4.f)); +} + +void CEnvFxManager::SetSplashEffectRate(float rate, const CStateManager& mgr) { + if (TCastToPtr splashEffect = mgr.ObjectById(xb68_envRainSplashId)) + if (splashEffect->IsElementGen()) + splashEffect->GetParticleGen()->SetGeneratorRate(rate); +} + +/* Used to be MIDI scale */ +static float CalcRainVolume(float f) { + if (f < 0.1f) + return (f / 0.1f * 74.f) / 127.f; + else + return (f / 0.9f * 21.f + 74.f) / 127.f; +} + +/* Used to be MIDI scale */ +static float CalcRainPitch(float f) { return f - 1.f; } + +void CEnvFxManager::UpdateRainSounds(const CStateManager& mgr) { + if (mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain) { + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + float rainVol = CalcRainVolume(x30_fxDensity); + if (!xb6a_rainSoundActive) { + xb6c_leftRainSound = CSfxManager::AddEmitter(SFXsfx09F0, zeus::CVector3f::skZero, zeus::CVector3f::skZero, false, + true, 0xff, kInvalidAreaId); + xb70_rightRainSound = CSfxManager::AddEmitter(SFXsfx09F1, zeus::CVector3f::skZero, zeus::CVector3f::skZero, false, + true, 0xff, kInvalidAreaId); + xb6a_rainSoundActive = true; } + CSfxManager::UpdateEmitter(xb6c_leftRainSound, camXf.origin - camXf.basis[0], camXf.basis[0], rainVol); + CSfxManager::UpdateEmitter(xb70_rightRainSound, camXf.origin + camXf.basis[0], -camXf.basis[0], rainVol); + float rainPitch = CalcRainPitch(x30_fxDensity); + CSfxManager::PitchBend(xb6c_leftRainSound, rainPitch); + CSfxManager::PitchBend(xb70_rightRainSound, rainPitch); + } else if (xb6a_rainSoundActive) { + CSfxManager::RemoveEmitter(xb6c_leftRainSound); + CSfxManager::RemoveEmitter(xb70_rightRainSound); + xb6a_rainSoundActive = false; + } +} + +zeus::CVector3f CEnvFxManager::GetParticleBoundsToWorldScale() const { + return (x0_particleBounds.max - x0_particleBounds.min) / 127.f; +} + +zeus::CTransform CEnvFxManager::GetParticleBoundsToWorldTransform() const { + return zeus::CTransform::Translate(x18_focusCellPosition) * zeus::CTransform::Translate(zeus::CVector3f(-31.75f)) * + zeus::CTransform::Scale(GetParticleBoundsToWorldScale()); +} + +void CEnvFxManager::UpdateVisorSplash(CStateManager& mgr, float dt, const zeus::CTransform& camXf) { + EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx(); + if (xb68_envRainSplashId != kInvalidUniqueId) + if (TCastToPtr splashEffect = mgr.ObjectById(xb68_envRainSplashId)) + mgr.SetActorAreaId(*splashEffect, mgr.GetNextAreaId()); + float camUpness = camXf.basis[1].dot(zeus::CVector3f::skUp); + float splashRateFactor; + if (x24_enableSplash) + splashRateFactor = std::max(0.f, camUpness) * x30_fxDensity; + else + splashRateFactor = 0.f; + float forwardRateFactor = 0.f; + if (x24_enableSplash && camUpness >= -0.1f) { + zeus::CVector3f pRelVel = mgr.GetPlayer().GetTransform().transposeRotate(mgr.GetPlayer().GetVelocity()); + if (pRelVel.canBeNormalized()) { + float velMag = pRelVel.magnitude(); + zeus::CVector3f normRelVel = pRelVel * (1.f / velMag); + forwardRateFactor = std::min(velMag / 60.f, 1.f) * normRelVel.dot(zeus::CVector3f::skForward); + } + } + float additionalFactor; + if (fxType == EEnvFxType::Rain) + additionalFactor = splashRateFactor + forwardRateFactor; + else + additionalFactor = 0.f; + SetSplashEffectRate(xb54_baseSplashRate + additionalFactor, mgr); + xb54_baseSplashRate = 0.f; +} + +void CEnvFxManager::MoveWrapCells(s32 moveX, s32 moveY) { + if (moveX == 0 && moveY == 0) + return; + bool r5 = std::fabs(moveX) >= 1.f || std::fabs(moveY) >= 1.f; + s32 moveXMaj = moveX << 11; + s32 moveYMaj = moveY << 11; + for (int i = 0; i < 8; ++i) { + s32 r28 = i - moveY; + for (int j = 0; j < 8; ++j) { + CEnvFxManagerGrid& grid = x50_grids[i * 8 + j]; + s32 r3 = j - moveX; + if (!r5) { + CEnvFxManagerGrid& otherGrid = x50_grids[r28 * 8 + r3]; + grid.x14_block = otherGrid.x14_block; + } else { + grid.x0_24_blockDirty = true; + } + grid.x4_position = + zeus::CVector2i((moveXMaj + grid.x4_position.x) & 0x3fff, (moveYMaj + grid.x4_position.y) & 0x3fff); + } + } } void CEnvFxManager::CalculateSnowForces(const CVectorFixed8_8& zVec, - rstl::reserved_vector& snowForces, - EEnvFxType type, const zeus::CVector3f& oopbtws, float dt) -{ - if (type == EEnvFxType::Snow) - { - CVectorFixed8_8 vecf; - zeus::CVector3f vec; - for (int i = 255; i >= 0; --i) - { - const zeus::CVector2f& force = g_SnowForces[i]; - zeus::CVector3f delta = zeus::CVector3f(force * dt) * oopbtws; - vec += delta; - CVectorFixed8_8 vecf2(vec); - snowForces.push_back(vecf2 - vecf); - vecf = vecf2; - } - - for (int i = 0; i < snowForces.size(); ++i) - snowForces[i] = snowForces[i] + zVec + CVectorFixed8_8(xb84_snowZDeltas[i & 0xf] * dt * oopbtws); + rstl::reserved_vector& snowForces, EEnvFxType type, + const zeus::CVector3f& oopbtws, float dt) { + if (type == EEnvFxType::Snow) { + CVectorFixed8_8 vecf; + zeus::CVector3f vec; + for (int i = 255; i >= 0; --i) { + const zeus::CVector2f& force = g_SnowForces[i]; + zeus::CVector3f delta = zeus::CVector3f(force * dt) * oopbtws; + vec += delta; + CVectorFixed8_8 vecf2(vec); + snowForces.push_back(vecf2 - vecf); + vecf = vecf2; } + + for (int i = 0; i < snowForces.size(); ++i) + snowForces[i] = snowForces[i] + zVec + CVectorFixed8_8(xb84_snowZDeltas[i & 0xf] * dt * oopbtws); + } } -void CEnvFxManager::BuildBlockObjectList(rstl::reserved_vector& list, CStateManager& mgr) -{ - for (CEntity* ent : mgr.GetAllObjectList()) - { - if (TCastToPtr trig = ent) - { - if ((trig->GetTriggerFlags() & ETriggerFlags::BlockEnvironmentalEffects) != ETriggerFlags::None) - list.push_back(ent->GetUniqueId()); - } - else if (TCastToPtr water = ent) - { - list.push_back(ent->GetUniqueId()); - } +void CEnvFxManager::BuildBlockObjectList(rstl::reserved_vector& list, CStateManager& mgr) { + for (CEntity* ent : mgr.GetAllObjectList()) { + if (TCastToPtr trig = ent) { + if ((trig->GetTriggerFlags() & ETriggerFlags::BlockEnvironmentalEffects) != ETriggerFlags::None) + list.push_back(ent->GetUniqueId()); + } else if (TCastToPtr water = ent) { + list.push_back(ent->GetUniqueId()); } + } } void CEnvFxManager::UpdateBlockedGrids(CStateManager& mgr, EEnvFxType type, const zeus::CTransform& camXf, - const zeus::CTransform& xf, const zeus::CTransform& invXf) -{ - zeus::CVector3f playerPos; - if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) - playerPos = camXf.origin; - else - playerPos = mgr.GetPlayer().GetBallPosition(); - zeus::CVector2i localPlayerPos((invXf * playerPos * 256.f).toVec2f()); + const zeus::CTransform& xf, const zeus::CTransform& invXf) { + zeus::CVector3f playerPos; + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) + playerPos = camXf.origin; + else + playerPos = mgr.GetPlayer().GetBallPosition(); + zeus::CVector2i localPlayerPos((invXf * playerPos * 256.f).toVec2f()); + x2c_lastBlockedGridIdx = -1; + x24_enableSplash = false; + rstl::reserved_vector blockList; + bool blockListBuilt = false; + int blockedGrids = 0; + for (int i = 0; i < x50_grids.size(); ++i) { + CEnvFxManagerGrid& grid = x50_grids[i]; + if (blockedGrids < 8 && grid.x0_24_blockDirty) { + if (type == EEnvFxType::UnderwaterFlake) { + grid.x14_block = std::make_pair(true, float(-FLT_MAX)); + } else { + CMaterialFilter filter = + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Trigger}, + {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::SeeThrough}); + zeus::CVector3f pos = xf * zeus::CVector3f((grid.x4_position + grid.xc_extent * 0).toVec2f() / 256.f) + + zeus::CVector3f::skUp * 500.f; + CRayCastResult result = + CGameCollision::RayStaticIntersection(mgr, pos, zeus::CVector3f::skDown, 1000.f, filter); + if (result.IsValid()) { + if (!blockListBuilt) { + BuildBlockObjectList(blockList, mgr); + blockListBuilt = true; + } + for (TUniqueId id : blockList) { + if (TCastToConstPtr trig = mgr.GetObjectById(id)) { + if (auto tb = trig->GetTouchBounds()) { + CCollidableAABox caabb(*tb, {EMaterialTypes::Trigger}); + CRayCastResult result2 = caabb.CastRayInternal({pos, zeus::CVector3f::skDown, 1000.f, {}, filter}); + if (result2.IsValid() && result2.GetT() < result.GetT()) + result = result2; + } + } + } + } + ++blockedGrids; + grid.x14_block = std::make_pair(result.IsValid(), result.GetPoint().z()); + } + grid.x0_24_blockDirty = false; + } + zeus::CVector2i gridEnd = grid.x4_position + grid.xc_extent; + if (localPlayerPos.x >= grid.x4_position.x && localPlayerPos.y >= grid.x4_position.y && + localPlayerPos.x < gridEnd.x && localPlayerPos.y < gridEnd.y && grid.x14_block.first && + grid.x14_block.second <= playerPos.z()) { + x24_enableSplash = true; + x2c_lastBlockedGridIdx = i; + } + } +} + +void CEnvFxManager::CreateNewParticles(EEnvFxType type) { + int maxCellParticleCount; + if (type == EEnvFxType::Snow) + maxCellParticleCount = 0x1c98; + else if (type == EEnvFxType::Rain) + maxCellParticleCount = 0x2af8; + else if (type == EEnvFxType::UnderwaterFlake) + maxCellParticleCount = 0x1fd6; + else + maxCellParticleCount = 0; + maxCellParticleCount >>= 6; + int cellParticleCount = maxCellParticleCount * x30_fxDensity; + static u32 seedStash = 0; + CRandom16 random(seedStash); + for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) { + if (it->x14_block.first) { + if (cellParticleCount > it->x1c_particles.size()) { + if (cellParticleCount > it->x1c_particles.capacity()) + it->x1c_particles.reserve(maxCellParticleCount); + int remCellParticleCount = cellParticleCount - it->x1c_particles.size(); + for (int i = 0; i < remCellParticleCount; ++i) { + int x = random.Range(0.f, float(it->xc_extent.x)); + int y = random.Range(0.f, float(it->xc_extent.y)); + int z = 256.f * random.Range(0.f, 63.f); + it->x1c_particles.emplace_back(x, y, z); + } + } else { + it->x1c_particles.resize(cellParticleCount); + } + } + } + seedStash = random.GetSeed(); +} + +void CEnvFxManager::UpdateSnowParticles(const rstl::reserved_vector& snowForces) { + for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) { + int forceIt = int(x28_firstSnowForce); + if (it->x14_block.first) { + for (auto pit = it->x1c_particles.rbegin(); pit != it->x1c_particles.rend(); ++pit) { + const CVectorFixed8_8& force = snowForces[forceIt]; + forceIt = (forceIt + 1) & 0xff; + *pit = *pit + force; + pit->z = s16(pit->z & 0x3fff); + } + } + } +} + +void CEnvFxManager::UpdateRainParticles(const CVectorFixed8_8& zVec, const zeus::CVector3f& oopbtws, float dt) { + s16 deltaZ = zVec.z + s16(-40.f * dt * oopbtws.z() * 256.f); + for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) + for (auto pit = it->x1c_particles.rbegin(); pit != it->x1c_particles.rend(); ++pit) + pit->z = s16((pit->z + deltaZ) & 0x3fff); +} + +void CEnvFxManager::UpdateUnderwaterParticles(const CVectorFixed8_8& zVec) { + for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) + for (auto pit = it->x1c_particles.rbegin(); pit != it->x1c_particles.rend(); ++pit) + pit->z = s16((pit->z + zVec.z) & 0x3fff); +} + +void CEnvFxManager::Update(float dt, CStateManager& mgr) { + EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx(); + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + if (mgr.GetCameraManager()->GetFluidCounter() != 0) { x2c_lastBlockedGridIdx = -1; x24_enableSplash = false; - rstl::reserved_vector blockList; - bool blockListBuilt = false; - int blockedGrids = 0; - for (int i = 0; i < x50_grids.size(); ++i) - { - CEnvFxManagerGrid& grid = x50_grids[i]; - if (blockedGrids < 8 && grid.x0_24_blockDirty) - { - if (type == EEnvFxType::UnderwaterFlake) - { - grid.x14_block = std::make_pair(true, float(-FLT_MAX)); - } - else - { - CMaterialFilter filter = - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Trigger}, - {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::SeeThrough}); - zeus::CVector3f pos = xf * zeus::CVector3f((grid.x4_position + grid.xc_extent * 0).toVec2f() / 256.f) + - zeus::CVector3f::skUp * 500.f; - CRayCastResult result = - CGameCollision::RayStaticIntersection(mgr, pos, zeus::CVector3f::skDown, 1000.f, filter); - if (result.IsValid()) - { - if (!blockListBuilt) - { - BuildBlockObjectList(blockList, mgr); - blockListBuilt = true; - } - for (TUniqueId id : blockList) - { - if (TCastToConstPtr trig = mgr.GetObjectById(id)) - { - if (auto tb = trig->GetTouchBounds()) - { - CCollidableAABox caabb(*tb, {EMaterialTypes::Trigger}); - CRayCastResult result2 = - caabb.CastRayInternal({pos, zeus::CVector3f::skDown, 1000.f, {}, filter}); - if (result2.IsValid() && result2.GetT() < result.GetT()) - result = result2; - } - } - } - } - ++blockedGrids; - grid.x14_block = std::make_pair(result.IsValid(), result.GetPoint().z()); - } - grid.x0_24_blockDirty = false; - } - zeus::CVector2i gridEnd = grid.x4_position + grid.xc_extent; - if (localPlayerPos.x >= grid.x4_position.x && localPlayerPos.y >= grid.x4_position.y && - localPlayerPos.x < gridEnd.x && localPlayerPos.y < gridEnd.y && grid.x14_block.first && - grid.x14_block.second <= playerPos.z()) - { - x24_enableSplash = true; - x2c_lastBlockedGridIdx = i; - } + SetSplashEffectRate(0.f, mgr); + } + UpdateRainSounds(mgr); + UpdateVisorSplash(mgr, dt, camXf); + if (fxType == EEnvFxType::None) { + for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) + if (it->x14_block.first) + it->x1c_particles = std::vector(); + } else { + float densityDelta = x34_targetFxDensity - x30_fxDensity; + float densityDeltaDamper = std::min(std::fabs(densityDelta) / 0.15f, 1.f); + float maxDensityDelta = x38_maxDensityDeltaSpeed / 11000.f * dt; + if (std::fabs(densityDelta) > maxDensityDelta) + densityDelta = (densityDelta > 0.f ? 1.f : -1.f) * maxDensityDelta; + x30_fxDensity += densityDeltaDamper * densityDelta; + zeus::CVector3f pbtws = GetParticleBoundsToWorldScale(); + zeus::CVector3f oopbtws = 1.f / pbtws; + zeus::CVector3f forwardPoint = camXf.basis[1] * 23.8125f + camXf.origin; + float modX = std::fmod(forwardPoint.x(), 7.9375f); + float modY = std::fmod(forwardPoint.y(), 7.9375f); + s32 moveX = (x18_focusCellPosition.x() - (forwardPoint.x() - modX)) / 7.9375f; + x18_focusCellPosition.x() = forwardPoint.x() - modX; + s32 moveY = (x18_focusCellPosition.y() - (forwardPoint.y() - modY)) / 7.9375f; + x18_focusCellPosition.y() = forwardPoint.y() - modY; + float deltaZ = x18_focusCellPosition.z() - forwardPoint.z(); + x18_focusCellPosition.z() = float(forwardPoint.z()); + MoveWrapCells(moveX, moveY); + CVectorFixed8_8 zVec(oopbtws * zeus::CVector3f(0.f, 0.f, deltaZ)); + if (fxType == EEnvFxType::UnderwaterFlake) + zVec.z += s16(256.f * 0.5f * dt); + rstl::reserved_vector snowForces; + CalculateSnowForces(zVec, snowForces, fxType, oopbtws, dt); + zeus::CTransform xf = GetParticleBoundsToWorldTransform(); + zeus::CTransform invXf = xf.inverse(); + UpdateBlockedGrids(mgr, fxType, camXf, xf, invXf); + CreateNewParticles(fxType); + switch (fxType) { + case EEnvFxType::Snow: + UpdateSnowParticles(snowForces); + break; + case EEnvFxType::Rain: + UpdateRainParticles(zVec, oopbtws, dt); + break; + case EEnvFxType::UnderwaterFlake: + UpdateUnderwaterParticles(zVec); + break; + default: + break; } -} - -void CEnvFxManager::CreateNewParticles(EEnvFxType type) -{ - int maxCellParticleCount; - if (type == EEnvFxType::Snow) - maxCellParticleCount = 0x1c98; - else if (type == EEnvFxType::Rain) - maxCellParticleCount = 0x2af8; - else if (type == EEnvFxType::UnderwaterFlake) - maxCellParticleCount = 0x1fd6; + if (fxType == EEnvFxType::Snow) + x28_firstSnowForce = std::fmod(1.f + x28_firstSnowForce, 256.f); else - maxCellParticleCount = 0; - maxCellParticleCount >>= 6; - int cellParticleCount = maxCellParticleCount * x30_fxDensity; - static u32 seedStash = 0; - CRandom16 random(seedStash); - for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) - { - if (it->x14_block.first) - { - if (cellParticleCount > it->x1c_particles.size()) - { - if (cellParticleCount > it->x1c_particles.capacity()) - it->x1c_particles.reserve(maxCellParticleCount); - int remCellParticleCount = cellParticleCount - it->x1c_particles.size(); - for (int i = 0; i < remCellParticleCount; ++i) - { - int x = random.Range(0.f, float(it->xc_extent.x)); - int y = random.Range(0.f, float(it->xc_extent.y)); - int z = 256.f * random.Range(0.f, 63.f); - it->x1c_particles.emplace_back(x, y, z); - } - } - else - { - it->x1c_particles.resize(cellParticleCount); - } - } + x28_firstSnowForce = std::fmod(0.125f + x28_firstSnowForce, 256.f); + } +} + +static zeus::CColor GetFlakeColor(const zeus::CMatrix4f& mvp, const CEnvFxShaders::Instance& inst) { + float screenHeight = + std::fabs(mvp.multiplyOneOverW(inst.positions[1]).y() - mvp.multiplyOneOverW(inst.positions[0]).y()) / 2.f; + screenHeight -= (32.f / 480.f); + screenHeight /= (32.f / 480.f); + return zeus::CColor(1.f - zeus::clamp(0.f, screenHeight, 1.f), 1.f); +} + +void CEnvFxManagerGrid::RenderSnowParticles(const zeus::CTransform& camXf) const { + zeus::CVector3f xVec = 0.2f * camXf.basis[0]; + zeus::CVector3f zVec = 0.2f * camXf.basis[2]; + zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(false) * CGraphics::g_GXModelView.toMatrix4f(); + auto* bufOut = m_instBuf.access(); + for (const auto& particle : x1c_particles) { + bufOut->positions[0] = particle.toVec3f(); + bufOut->uvs[0] = zeus::CVector2f(0.f, 0.f); + bufOut->positions[1] = bufOut->positions[0] + zVec; + bufOut->uvs[1] = zeus::CVector2f(0.f, 1.f); + bufOut->positions[3] = bufOut->positions[1] + xVec; + bufOut->uvs[3] = zeus::CVector2f(1.f, 1.f); + bufOut->positions[2] = bufOut->positions[3] - zVec; + bufOut->uvs[2] = zeus::CVector2f(1.f, 0.f); + bufOut->color = GetFlakeColor(mvp, *bufOut); + ++bufOut; + } + CGraphics::SetShaderDataBinding(m_snowBinding); + CGraphics::DrawInstances(0, 4, x1c_particles.size()); +} + +void CEnvFxManagerGrid::RenderRainParticles(const zeus::CTransform& camXf) const { + m_lineRenderer.Reset(); + float zOffset = 2.f * (1.f - std::fabs(camXf.basis[2].dot(zeus::CVector3f::skUp))) + 1.f; + zeus::CColor color0(1.f, 10.f / 15.f); + for (const auto& particle : x1c_particles) { + zeus::CVector3f pos0 = particle.toVec3f(); + zeus::CVector3f pos1 = pos0; + pos1.z() += zOffset; + float uvy0 = pos0.z() * 10.f + m_uvyOffset; + float uvy1 = pos1.z() * 10.f + m_uvyOffset; + m_lineRenderer.AddVertex(pos0, zeus::CColor::skWhite, 1.f, {0.f, uvy0}); + m_lineRenderer.AddVertex(pos1, zeus::CColor::skClear, 1.f, {0.f, uvy1}); + } + m_lineRenderer.Render(zeus::CColor(1.f, 0.15f)); +} + +void CEnvFxManagerGrid::RenderUnderwaterParticles(const zeus::CTransform& camXf) const { + zeus::CVector3f xVec = 0.5f * camXf.basis[0]; + zeus::CVector3f zVec = 0.5f * camXf.basis[2]; + zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(false) * CGraphics::g_GXModelView.toMatrix4f(); + auto* bufOut = m_instBuf.access(); + for (const auto& particle : x1c_particles) { + bufOut->positions[0] = particle.toVec3f(); + bufOut->uvs[0] = zeus::CVector2f(0.f, 0.f); + bufOut->positions[1] = bufOut->positions[0] + zVec; + bufOut->uvs[1] = zeus::CVector2f(0.f, 1.f); + bufOut->positions[3] = bufOut->positions[1] + xVec; + bufOut->uvs[3] = zeus::CVector2f(1.f, 1.f); + bufOut->positions[2] = bufOut->positions[3] - zVec; + bufOut->uvs[2] = zeus::CVector2f(1.f, 0.f); + bufOut->color = GetFlakeColor(mvp, *bufOut); + ++bufOut; + } + CGraphics::SetShaderDataBinding(m_underwaterBinding); + CGraphics::DrawInstances(0, 4, x1c_particles.size()); +} + +void CEnvFxManagerGrid::Render(const zeus::CTransform& xf, const zeus::CTransform& invXf, const zeus::CTransform& camXf, + float fxDensity, EEnvFxType fxType, const CEnvFxManager& parent) const { + if (!x1c_particles.empty() && x14_block.first) { + CGraphics::SetModelMatrix(xf * zeus::CTransform::Translate(x4_position.toVec2f() / 256.f)); + parent.m_uniformData.mv = CGraphics::g_GXModelView.toMatrix4f(); + parent.m_uniformData.proj = CGraphics::GetPerspectiveProjectionMatrix(true); + switch (fxType) { + case EEnvFxType::Snow: + case EEnvFxType::Rain: { + zeus::CMatrix4f envTexMtx(true); + envTexMtx[2][1] = 10.f; + envTexMtx[3][1] = 0.5f - (invXf * (zeus::CVector3f::skUp * x14_block.second)).z() * 10.f; + m_uvyOffset = envTexMtx[3][1]; + parent.m_uniformData.envMtx = envTexMtx; + break; } - seedStash = random.GetSeed(); -} - -void CEnvFxManager::UpdateSnowParticles(const rstl::reserved_vector& snowForces) -{ - for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) - { - int forceIt = int(x28_firstSnowForce); - if (it->x14_block.first) - { - for (auto pit = it->x1c_particles.rbegin(); pit != it->x1c_particles.rend(); ++pit) - { - const CVectorFixed8_8& force = snowForces[forceIt]; - forceIt = (forceIt + 1) & 0xff; - *pit = *pit + force; - pit->z = s16(pit->z & 0x3fff); - } - } + default: + break; } -} - -void CEnvFxManager::UpdateRainParticles(const CVectorFixed8_8& zVec, const zeus::CVector3f& oopbtws, float dt) -{ - s16 deltaZ = zVec.z + s16(-40.f * dt * oopbtws.z() * 256.f); - for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) - for (auto pit = it->x1c_particles.rbegin(); pit != it->x1c_particles.rend(); ++pit) - pit->z = s16((pit->z + deltaZ) & 0x3fff); -} - -void CEnvFxManager::UpdateUnderwaterParticles(const CVectorFixed8_8& zVec) -{ - for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) - for (auto pit = it->x1c_particles.rbegin(); pit != it->x1c_particles.rend(); ++pit) - pit->z = s16((pit->z + zVec.z) & 0x3fff); -} - -void CEnvFxManager::Update(float dt, CStateManager& mgr) -{ - EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx(); - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - if (mgr.GetCameraManager()->GetFluidCounter() != 0) - { - x2c_lastBlockedGridIdx = -1; - x24_enableSplash = false; - SetSplashEffectRate(0.f, mgr); + m_uniformBuf.access() = parent.m_uniformData; + switch (fxType) { + case EEnvFxType::Snow: + RenderSnowParticles(camXf); + break; + case EEnvFxType::Rain: + RenderRainParticles(camXf); + break; + case EEnvFxType::UnderwaterFlake: + RenderUnderwaterParticles(camXf); + break; + default: + break; } - UpdateRainSounds(mgr); - UpdateVisorSplash(mgr, dt, camXf); - if (fxType == EEnvFxType::None) - { - for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it) - if (it->x14_block.first) - it->x1c_particles = std::vector(); - } - else - { - float densityDelta = x34_targetFxDensity - x30_fxDensity; - float densityDeltaDamper = std::min(std::fabs(densityDelta) / 0.15f, 1.f); - float maxDensityDelta = x38_maxDensityDeltaSpeed / 11000.f * dt; - if (std::fabs(densityDelta) > maxDensityDelta) - densityDelta = (densityDelta > 0.f ? 1.f : -1.f) * maxDensityDelta; - x30_fxDensity += densityDeltaDamper * densityDelta; - zeus::CVector3f pbtws = GetParticleBoundsToWorldScale(); - zeus::CVector3f oopbtws = 1.f / pbtws; - zeus::CVector3f forwardPoint = camXf.basis[1] * 23.8125f + camXf.origin; - float modX = std::fmod(forwardPoint.x(), 7.9375f); - float modY = std::fmod(forwardPoint.y(), 7.9375f); - s32 moveX = (x18_focusCellPosition.x() - (forwardPoint.x() - modX)) / 7.9375f; - x18_focusCellPosition.x() = forwardPoint.x() - modX; - s32 moveY = (x18_focusCellPosition.y() - (forwardPoint.y() - modY)) / 7.9375f; - x18_focusCellPosition.y() = forwardPoint.y() - modY; - float deltaZ = x18_focusCellPosition.z() - forwardPoint.z(); - x18_focusCellPosition.z() = float(forwardPoint.z()); - MoveWrapCells(moveX, moveY); - CVectorFixed8_8 zVec(oopbtws * zeus::CVector3f(0.f, 0.f, deltaZ)); - if (fxType == EEnvFxType::UnderwaterFlake) - zVec.z += s16(256.f * 0.5f * dt); - rstl::reserved_vector snowForces; - CalculateSnowForces(zVec, snowForces, fxType, oopbtws, dt); - zeus::CTransform xf = GetParticleBoundsToWorldTransform(); - zeus::CTransform invXf = xf.inverse(); - UpdateBlockedGrids(mgr, fxType, camXf, xf, invXf); - CreateNewParticles(fxType); - switch (fxType) - { - case EEnvFxType::Snow: - UpdateSnowParticles(snowForces); - break; - case EEnvFxType::Rain: - UpdateRainParticles(zVec, oopbtws, dt); - break; - case EEnvFxType::UnderwaterFlake: - UpdateUnderwaterParticles(zVec); - break; - default: - break; - } - if (fxType == EEnvFxType::Snow) - x28_firstSnowForce = std::fmod(1.f + x28_firstSnowForce, 256.f); - else - x28_firstSnowForce = std::fmod(0.125f + x28_firstSnowForce, 256.f); + } +} + +void CEnvFxManager::SetupSnowTevs(const CStateManager& mgr) const { + mgr.GetCameraManager()->GetCurrentCamera(mgr); + if (mgr.GetCameraManager()->GetFluidCounter() != 0) { + g_Renderer->SetWorldFog(ERglFogMode::PerspExp, 0.f, 35.f, zeus::CColor::skBlack); + m_uniformData.moduColor = zeus::CColor(1.f, 0.5f); + } else { + g_Renderer->SetWorldFog(ERglFogMode::PerspLin, 52.f, 57.f, zeus::CColor::skBlack); + } + + // Blend One One + // 2 stages + + // xb74_txtrSnowFlake + // Texcoord0: 2x4, TEX0, GX_IDENTITY, no norm, GX_PTTIDENTITY + // 0: Standard alpha, map0, tcg0 + // Color: Zero, Konst, TexC, Zero + // Alpha: Zero, Konst, TexA, Zero + + // x40_txtrEnvGradient + // Texcoord1: 2x4, POS, GX_TEXMTX5, no norm, GX_PTTIDENTITY + // 0: Standard alpha, map0, tcg0 + // Color: Zero, TexC, CPrev, Zero + // Alpha: Zero, Zero, Zero, TexA +} + +void CEnvFxManager::SetupRainTevs() const { + // Line-width 1px + // Blend SrcAlpha One + + // x40_txtrEnvGradient + // Texcoord0: 2x4, POS, GX_TEXMTX5, no norm, GX_PTTIDENTITY + // 0: Standard alpha, map0, tcg0 + // Color: Zero, Zero, Zero, TexC + // Alpha: Zero, RasA, Konst, Zero + // Ras vertex color + // KAlpha 0.15 +} + +void CEnvFxManager::SetupUnderwaterTevs(const zeus::CTransform& invXf, const CStateManager& mgr) const { + // Blend SrcAlpha InvSrcAlpha + + // xc48_underwaterFlake + // Texcoord0: 2x4, TEX0, GX_IDENTITY, no norm, GX_PTTIDENTITY + // Color: Zero, Zero, Zero, TexC + // Alpha: Zero, Zero, Zero, TexA + + float waterTop = FLT_MAX; + for (CEntity* ent : mgr.GetAllObjectList()) + if (TCastToPtr water = ent) + if (auto tb = water->GetTouchBounds()) + waterTop = std::min(waterTop, float(tb->max.z())); + zeus::CVector3f localWaterTop = invXf * (zeus::CVector3f::skUp * waterTop); + zeus::CMatrix4f envTexMtx(true); + envTexMtx[2][1] = -10.f; + envTexMtx[3][1] = localWaterTop.z() * -10.f + 0.5f; + // Load into texmtx5 + + // x40_txtrEnvGradient + // Texcoord1: 2x4, POS, GX_TEXMTX5, no norm, GX_PTTIDENTITY + // MTX: y-scale -10.0 of Z, y-trans -10.0 * () + // 1: Standard alpha, map1, tcg1 + // Color: Zero, One, CPrev, Zero + // Alpha: Zero, TexA, APrev, Zero + // Swap: RGBR +} + +void CEnvFxManager::Render(const CStateManager& mgr) const { + EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx(); + if (fxType != EEnvFxType::None) { + if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed || + (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Thermal && + (fxType != EEnvFxType::Snow || mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay))) { + // No Cull + // ZTest, No ZWrite + zeus::CTransform xf = GetParticleBoundsToWorldTransform(); + zeus::CTransform invXf = xf.inverse(); + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + m_uniformData.moduColor = zeus::CColor::skWhite; + switch (fxType) { + case EEnvFxType::Snow: + SetupSnowTevs(mgr); + break; + case EEnvFxType::Rain: + SetupRainTevs(); + break; + case EEnvFxType::UnderwaterFlake: + SetupUnderwaterTevs(invXf, mgr); + break; + default: + break; + } + m_fogUniformBuf->load(&CGraphics::g_Fog, sizeof(CGraphics::g_Fog)); + for (const auto& grid : x50_grids) + grid.Render(xf, invXf, camXf, x30_fxDensity, fxType, *this); + // Backface cull + + m_uniformPool.updateBuffers(); + m_instPool.updateBuffers(); } + } } -static zeus::CColor GetFlakeColor(const zeus::CMatrix4f& mvp, const CEnvFxShaders::Instance& inst) -{ - float screenHeight = std::fabs(mvp.multiplyOneOverW(inst.positions[1]).y() - - mvp.multiplyOneOverW(inst.positions[0]).y()) / 2.f; - screenHeight -= (32.f / 480.f); - screenHeight /= (32.f / 480.f); - return zeus::CColor(1.f - zeus::clamp(0.f, screenHeight, 1.f), 1.f); +void CEnvFxManager::AsyncLoadResources(CStateManager& mgr) { + xb68_envRainSplashId = mgr.AllocateUniqueId(); + CHUDBillboardEffect* effect = + new CHUDBillboardEffect(xb58_envRainSplash, {}, xb68_envRainSplashId, true, "VisorRainSplashes", + CHUDBillboardEffect::GetNearClipDistance(mgr), CHUDBillboardEffect::GetScaleForPOV(mgr), + zeus::CColor::skWhite, zeus::CVector3f::skOne, zeus::CVector3f::skZero); + effect->SetRunIndefinitely(true); + mgr.AddObject(effect); } -void CEnvFxManagerGrid::RenderSnowParticles(const zeus::CTransform& camXf) const -{ - zeus::CVector3f xVec = 0.2f * camXf.basis[0]; - zeus::CVector3f zVec = 0.2f * camXf.basis[2]; - zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(false) * - CGraphics::g_GXModelView.toMatrix4f(); - auto* bufOut = m_instBuf.access(); - for (const auto& particle : x1c_particles) - { - bufOut->positions[0] = particle.toVec3f(); - bufOut->uvs[0] = zeus::CVector2f(0.f, 0.f); - bufOut->positions[1] = bufOut->positions[0] + zVec; - bufOut->uvs[1] = zeus::CVector2f(0.f, 1.f); - bufOut->positions[3] = bufOut->positions[1] + xVec; - bufOut->uvs[3] = zeus::CVector2f(1.f, 1.f); - bufOut->positions[2] = bufOut->positions[3] - zVec; - bufOut->uvs[2] = zeus::CVector2f(1.f, 0.f); - bufOut->color = GetFlakeColor(mvp, *bufOut); - ++bufOut; - } - CGraphics::SetShaderDataBinding(m_snowBinding); - CGraphics::DrawInstances(0, 4, x1c_particles.size()); +void CEnvFxManager::SetFxDensity(s32 val, float density) { + x34_targetFxDensity = density; + x38_maxDensityDeltaSpeed = val; } -void CEnvFxManagerGrid::RenderRainParticles(const zeus::CTransform& camXf) const -{ - m_lineRenderer.Reset(); - float zOffset = 2.f * (1.f - std::fabs(camXf.basis[2].dot(zeus::CVector3f::skUp))) + 1.f; - zeus::CColor color0(1.f, 10.f / 15.f); - for (const auto& particle : x1c_particles) - { - zeus::CVector3f pos0 = particle.toVec3f(); - zeus::CVector3f pos1 = pos0; - pos1.z() += zOffset; - float uvy0 = pos0.z() * 10.f + m_uvyOffset; - float uvy1 = pos1.z() * 10.f + m_uvyOffset; - m_lineRenderer.AddVertex(pos0, zeus::CColor::skWhite, 1.f, {0.f, uvy0}); - m_lineRenderer.AddVertex(pos1, zeus::CColor::skClear, 1.f, {0.f, uvy1}); - } - m_lineRenderer.Render(zeus::CColor(1.f, 0.15f)); +void CEnvFxManager::AreaLoaded() { + for (CEnvFxManagerGrid& grid : x50_grids) + grid.x0_24_blockDirty = true; } -void CEnvFxManagerGrid::RenderUnderwaterParticles(const zeus::CTransform& camXf) const -{ - zeus::CVector3f xVec = 0.5f * camXf.basis[0]; - zeus::CVector3f zVec = 0.5f * camXf.basis[2]; - zeus::CMatrix4f mvp = CGraphics::GetPerspectiveProjectionMatrix(false) * - CGraphics::g_GXModelView.toMatrix4f(); - auto* bufOut = m_instBuf.access(); - for (const auto& particle : x1c_particles) - { - bufOut->positions[0] = particle.toVec3f(); - bufOut->uvs[0] = zeus::CVector2f(0.f, 0.f); - bufOut->positions[1] = bufOut->positions[0] + zVec; - bufOut->uvs[1] = zeus::CVector2f(0.f, 1.f); - bufOut->positions[3] = bufOut->positions[1] + xVec; - bufOut->uvs[3] = zeus::CVector2f(1.f, 1.f); - bufOut->positions[2] = bufOut->positions[3] - zVec; - bufOut->uvs[2] = zeus::CVector2f(1.f, 0.f); - bufOut->color = GetFlakeColor(mvp, *bufOut); - ++bufOut; - } - CGraphics::SetShaderDataBinding(m_underwaterBinding); - CGraphics::DrawInstances(0, 4, x1c_particles.size()); +void CEnvFxManager::Cleanup() { + xb68_envRainSplashId = kInvalidUniqueId; + xb6a_rainSoundActive = false; + xb6c_leftRainSound.reset(); + xb70_rightRainSound.reset(); } -void CEnvFxManagerGrid::Render(const zeus::CTransform& xf, const zeus::CTransform& invXf, - const zeus::CTransform& camXf, float fxDensity, EEnvFxType fxType, - const CEnvFxManager& parent) const -{ - if (!x1c_particles.empty() && x14_block.first) - { - CGraphics::SetModelMatrix(xf * zeus::CTransform::Translate(x4_position.toVec2f() / 256.f)); - parent.m_uniformData.mv = CGraphics::g_GXModelView.toMatrix4f(); - parent.m_uniformData.proj = CGraphics::GetPerspectiveProjectionMatrix(true); - switch (fxType) - { - case EEnvFxType::Snow: - case EEnvFxType::Rain: - { - zeus::CMatrix4f envTexMtx(true); - envTexMtx[2][1] = 10.f; - envTexMtx[3][1] = 0.5f - (invXf * (zeus::CVector3f::skUp * x14_block.second)).z() * 10.f; - m_uvyOffset = envTexMtx[3][1]; - parent.m_uniformData.envMtx = envTexMtx; - break; - } - default: - break; - } - m_uniformBuf.access() = parent.m_uniformData; - switch (fxType) - { - case EEnvFxType::Snow: - RenderSnowParticles(camXf); - break; - case EEnvFxType::Rain: - RenderRainParticles(camXf); - break; - case EEnvFxType::UnderwaterFlake: - RenderUnderwaterParticles(camXf); - break; - default: - break; - } - } +void CEnvFxManager::Initialize() { + const SObjectTag* tag = g_ResFactory->GetResourceIdByName("DUMB_SnowForces"); + std::unique_ptr data = g_ResFactory->LoadResourceSync(*tag); + athena::io::MemoryReader r(data.get(), 2048); + for (int i = 0; i < 256; ++i) + g_SnowForces.push_back(r.readVec2fBig()); } -void CEnvFxManager::SetupSnowTevs(const CStateManager& mgr) const -{ - mgr.GetCameraManager()->GetCurrentCamera(mgr); - if (mgr.GetCameraManager()->GetFluidCounter() != 0) - { - g_Renderer->SetWorldFog(ERglFogMode::PerspExp, 0.f, 35.f, zeus::CColor::skBlack); - m_uniformData.moduColor = zeus::CColor(1.f, 0.5f); - } - else - { - g_Renderer->SetWorldFog(ERglFogMode::PerspLin, 52.f, 57.f, zeus::CColor::skBlack); - } - - // Blend One One - // 2 stages - - // xb74_txtrSnowFlake - // Texcoord0: 2x4, TEX0, GX_IDENTITY, no norm, GX_PTTIDENTITY - // 0: Standard alpha, map0, tcg0 - // Color: Zero, Konst, TexC, Zero - // Alpha: Zero, Konst, TexA, Zero - - // x40_txtrEnvGradient - // Texcoord1: 2x4, POS, GX_TEXMTX5, no norm, GX_PTTIDENTITY - // 0: Standard alpha, map0, tcg0 - // Color: Zero, TexC, CPrev, Zero - // Alpha: Zero, Zero, Zero, TexA -} - -void CEnvFxManager::SetupRainTevs() const -{ - // Line-width 1px - // Blend SrcAlpha One - - // x40_txtrEnvGradient - // Texcoord0: 2x4, POS, GX_TEXMTX5, no norm, GX_PTTIDENTITY - // 0: Standard alpha, map0, tcg0 - // Color: Zero, Zero, Zero, TexC - // Alpha: Zero, RasA, Konst, Zero - // Ras vertex color - // KAlpha 0.15 -} - -void CEnvFxManager::SetupUnderwaterTevs(const zeus::CTransform& invXf, const CStateManager& mgr) const -{ - // Blend SrcAlpha InvSrcAlpha - - // xc48_underwaterFlake - // Texcoord0: 2x4, TEX0, GX_IDENTITY, no norm, GX_PTTIDENTITY - // Color: Zero, Zero, Zero, TexC - // Alpha: Zero, Zero, Zero, TexA - - float waterTop = FLT_MAX; - for (CEntity* ent : mgr.GetAllObjectList()) - if (TCastToPtr water = ent) - if (auto tb = water->GetTouchBounds()) - waterTop = std::min(waterTop, float(tb->max.z())); - zeus::CVector3f localWaterTop = invXf * (zeus::CVector3f::skUp * waterTop); - zeus::CMatrix4f envTexMtx(true); - envTexMtx[2][1] = -10.f; - envTexMtx[3][1] = localWaterTop.z() * -10.f + 0.5f; - // Load into texmtx5 - - // x40_txtrEnvGradient - // Texcoord1: 2x4, POS, GX_TEXMTX5, no norm, GX_PTTIDENTITY - // MTX: y-scale -10.0 of Z, y-trans -10.0 * () - // 1: Standard alpha, map1, tcg1 - // Color: Zero, One, CPrev, Zero - // Alpha: Zero, TexA, APrev, Zero - // Swap: RGBR -} - -void CEnvFxManager::Render(const CStateManager& mgr) const -{ - EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx(); - if (fxType != EEnvFxType::None) - { - if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed || - (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Thermal && - (fxType != EEnvFxType::Snow || - mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay))) - { - // No Cull - // ZTest, No ZWrite - zeus::CTransform xf = GetParticleBoundsToWorldTransform(); - zeus::CTransform invXf = xf.inverse(); - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - m_uniformData.moduColor = zeus::CColor::skWhite; - switch (fxType) - { - case EEnvFxType::Snow: - SetupSnowTevs(mgr); - break; - case EEnvFxType::Rain: - SetupRainTevs(); - break; - case EEnvFxType::UnderwaterFlake: - SetupUnderwaterTevs(invXf, mgr); - break; - default: - break; - } - m_fogUniformBuf->load(&CGraphics::g_Fog, sizeof(CGraphics::g_Fog)); - for (const auto& grid : x50_grids) - grid.Render(xf, invXf, camXf, x30_fxDensity, fxType, *this); - // Backface cull - - m_uniformPool.updateBuffers(); - m_instPool.updateBuffers(); - } - } -} - -void CEnvFxManager::AsyncLoadResources(CStateManager& mgr) -{ - xb68_envRainSplashId = mgr.AllocateUniqueId(); - CHUDBillboardEffect* effect = - new CHUDBillboardEffect(xb58_envRainSplash, {}, xb68_envRainSplashId, true, "VisorRainSplashes", - CHUDBillboardEffect::GetNearClipDistance(mgr), - CHUDBillboardEffect::GetScaleForPOV(mgr), zeus::CColor::skWhite, - zeus::CVector3f::skOne, zeus::CVector3f::skZero); - effect->SetRunIndefinitely(true); - mgr.AddObject(effect); -} - -void CEnvFxManager::SetFxDensity(s32 val, float density) -{ - x34_targetFxDensity = density; - x38_maxDensityDeltaSpeed = val; -} - -void CEnvFxManager::AreaLoaded() -{ - for (CEnvFxManagerGrid& grid : x50_grids) - grid.x0_24_blockDirty = true; -} - -void CEnvFxManager::Cleanup() -{ - xb68_envRainSplashId = kInvalidUniqueId; - xb6a_rainSoundActive = false; - xb6c_leftRainSound.reset(); - xb70_rightRainSound.reset(); -} - -void CEnvFxManager::Initialize() -{ - const SObjectTag* tag = g_ResFactory->GetResourceIdByName("DUMB_SnowForces"); - std::unique_ptr data = g_ResFactory->LoadResourceSync(*tag); - athena::io::MemoryReader r(data.get(), 2048); - for (int i = 0; i < 256; ++i) - g_SnowForces.push_back(r.readVec2fBig()); -} - -} +} // namespace urde diff --git a/Runtime/World/CEnvFxManager.hpp b/Runtime/World/CEnvFxManager.hpp index 8615fe170..d48f03c2b 100644 --- a/Runtime/World/CEnvFxManager.hpp +++ b/Runtime/World/CEnvFxManager.hpp @@ -10,158 +10,140 @@ #include "hecl/VertexBufferPool.hpp" #include "hecl/UniformBufferPool.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CTexture; class CActor; -enum class EEnvFxType -{ - None, - Snow, - Rain, - UnderwaterFlake -}; +enum class EEnvFxType { None, Snow, Rain, UnderwaterFlake }; -enum class EPhazonType -{ - None, - Blue, - Orange -}; +enum class EPhazonType { None, Blue, Orange }; -class CVectorFixed8_8 -{ +class CVectorFixed8_8 { public: - union { - struct - { - s16 x, y, z; - }; - s16 v[3]; + union { + struct { + s16 x, y, z; }; - CVectorFixed8_8() { x = y = z = 0; } - CVectorFixed8_8(s16 xi, s16 yi, s16 zi) { x = xi; y = yi; z = zi; } - CVectorFixed8_8(const zeus::CVector3f& vec) - { - zeus::simd_floats f(vec.mSimd); - x = s16(f[0] * 256.f); - y = s16(f[1] * 256.f); - z = s16(f[2] * 256.f); - } - CVectorFixed8_8 operator+(const CVectorFixed8_8& other) const - { - return {s16(x + other.x), s16(y + other.y), s16(z + other.z)}; - } - CVectorFixed8_8 operator-(const CVectorFixed8_8& other) const - { - return {s16(x - other.x), s16(y - other.y), s16(z - other.z)}; - } - zeus::CVector3f toVec3f() const - { - return {x / 256.f, y / 256.f, z / 256.f}; - } + s16 v[3]; + }; + CVectorFixed8_8() { x = y = z = 0; } + CVectorFixed8_8(s16 xi, s16 yi, s16 zi) { + x = xi; + y = yi; + z = zi; + } + CVectorFixed8_8(const zeus::CVector3f& vec) { + zeus::simd_floats f(vec.mSimd); + x = s16(f[0] * 256.f); + y = s16(f[1] * 256.f); + z = s16(f[2] * 256.f); + } + CVectorFixed8_8 operator+(const CVectorFixed8_8& other) const { + return {s16(x + other.x), s16(y + other.y), s16(z + other.z)}; + } + CVectorFixed8_8 operator-(const CVectorFixed8_8& other) const { + return {s16(x - other.x), s16(y - other.y), s16(z - other.z)}; + } + zeus::CVector3f toVec3f() const { return {x / 256.f, y / 256.f, z / 256.f}; } }; -class CEnvFxManagerGrid -{ - friend class CEnvFxManager; - friend class CEnvFxShaders; - bool x0_24_blockDirty = true; - zeus::CVector2i x4_position; /* 8.8 fixed point */ - zeus::CVector2i xc_extent; /* 8.8 fixed point */ - std::pair x14_block = {false, FLT_MAX}; /* Blocked-bool, Z-coordinate */ - std::vector x1c_particles; +class CEnvFxManagerGrid { + friend class CEnvFxManager; + friend class CEnvFxShaders; + bool x0_24_blockDirty = true; + zeus::CVector2i x4_position; /* 8.8 fixed point */ + zeus::CVector2i xc_extent; /* 8.8 fixed point */ + std::pair x14_block = {false, FLT_MAX}; /* Blocked-bool, Z-coordinate */ + std::vector x1c_particles; - mutable hecl::VertexBufferPool::Token m_instBuf; - mutable hecl::UniformBufferPool::Token m_uniformBuf; - mutable CLineRenderer m_lineRenderer; + mutable hecl::VertexBufferPool::Token m_instBuf; + mutable hecl::UniformBufferPool::Token m_uniformBuf; + mutable CLineRenderer m_lineRenderer; - boo::ObjToken m_snowBinding; - boo::ObjToken m_underwaterBinding; + boo::ObjToken m_snowBinding; + boo::ObjToken m_underwaterBinding; - mutable float m_uvyOffset = 0.f; + mutable float m_uvyOffset = 0.f; + + void RenderSnowParticles(const zeus::CTransform& camXf) const; + void RenderRainParticles(const zeus::CTransform& camXf) const; + void RenderUnderwaterParticles(const zeus::CTransform& camXf) const; - void RenderSnowParticles(const zeus::CTransform& camXf) const; - void RenderRainParticles(const zeus::CTransform& camXf) const; - void RenderUnderwaterParticles(const zeus::CTransform& camXf) const; public: - CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus::CVector2i& extent, - const std::vector& initialParticles, int reserve, - CEnvFxManager& parent, boo::IGraphicsDataFactory::Context& ctx); - void Render(const zeus::CTransform& xf, const zeus::CTransform& invXf, - const zeus::CTransform& camXf, float fxDensity, EEnvFxType fxType, - const CEnvFxManager& parent) const; + CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus::CVector2i& extent, + const std::vector& initialParticles, int reserve, CEnvFxManager& parent, + boo::IGraphicsDataFactory::Context& ctx); + void Render(const zeus::CTransform& xf, const zeus::CTransform& invXf, const zeus::CTransform& camXf, float fxDensity, + EEnvFxType fxType, const CEnvFxManager& parent) const; }; -class CEnvFxManager -{ - friend class CEnvFxManagerGrid; - friend class CEnvFxShaders; +class CEnvFxManager { + friend class CEnvFxManagerGrid; + friend class CEnvFxShaders; - mutable hecl::VertexBufferPool m_instPool; - mutable hecl::UniformBufferPool m_uniformPool; - mutable CEnvFxShaders::Uniform m_uniformData; - boo::ObjToken m_fogUniformBuf; + mutable hecl::VertexBufferPool m_instPool; + mutable hecl::UniformBufferPool m_uniformPool; + mutable CEnvFxShaders::Uniform m_uniformData; + boo::ObjToken m_fogUniformBuf; - zeus::CAABox x0_particleBounds = zeus::CAABox(-63.5f, 63.5f); - zeus::CVector3f x18_focusCellPosition = zeus::CVector3f::skZero; - bool x24_enableSplash = false; - float x28_firstSnowForce = 0.f; - s32 x2c_lastBlockedGridIdx = -1; - float x30_fxDensity = 0.f; - float x34_targetFxDensity = 0.f; - float x38_maxDensityDeltaSpeed = 0.f; - //bool x3c_snowflakeTextureMipBlanked = false; /* Shader simulates this texture mod */ - TLockedToken x40_txtrEnvGradient; - rstl::reserved_vector x50_grids; - float xb54_baseSplashRate; - TLockedToken xb58_envRainSplash; - bool xb64_ = true; - TUniqueId xb68_envRainSplashId = kInvalidUniqueId; - bool xb6a_rainSoundActive = false; - CSfxHandle xb6c_leftRainSound; - CSfxHandle xb70_rightRainSound; - TLockedToken xb74_txtrSnowFlake; - bool xb80_ = true; - rstl::reserved_vector xb84_snowZDeltas; - TLockedToken xc48_underwaterFlake; - bool xc54_ = true; + zeus::CAABox x0_particleBounds = zeus::CAABox(-63.5f, 63.5f); + zeus::CVector3f x18_focusCellPosition = zeus::CVector3f::skZero; + bool x24_enableSplash = false; + float x28_firstSnowForce = 0.f; + s32 x2c_lastBlockedGridIdx = -1; + float x30_fxDensity = 0.f; + float x34_targetFxDensity = 0.f; + float x38_maxDensityDeltaSpeed = 0.f; + // bool x3c_snowflakeTextureMipBlanked = false; /* Shader simulates this texture mod */ + TLockedToken x40_txtrEnvGradient; + rstl::reserved_vector x50_grids; + float xb54_baseSplashRate; + TLockedToken xb58_envRainSplash; + bool xb64_ = true; + TUniqueId xb68_envRainSplashId = kInvalidUniqueId; + bool xb6a_rainSoundActive = false; + CSfxHandle xb6c_leftRainSound; + CSfxHandle xb70_rightRainSound; + TLockedToken xb74_txtrSnowFlake; + bool xb80_ = true; + rstl::reserved_vector xb84_snowZDeltas; + TLockedToken xc48_underwaterFlake; + bool xc54_ = true; + + void SetSplashEffectRate(float f, const CStateManager& mgr); + void UpdateRainSounds(const CStateManager& mgr); + zeus::CVector3f GetParticleBoundsToWorldScale() const; + zeus::CTransform GetParticleBoundsToWorldTransform() const; + void UpdateVisorSplash(CStateManager& mgr, float dt, const zeus::CTransform& camXf); + void MoveWrapCells(s32, s32); + void CalculateSnowForces(const CVectorFixed8_8& zVec, rstl::reserved_vector& snowForces, + EEnvFxType type, const zeus::CVector3f& oopbtws, float dt); + static void BuildBlockObjectList(rstl::reserved_vector& list, CStateManager& mgr); + void UpdateBlockedGrids(CStateManager& mgr, EEnvFxType type, const zeus::CTransform& camXf, + const zeus::CTransform& xf, const zeus::CTransform& invXf); + void CreateNewParticles(EEnvFxType type); + void UpdateSnowParticles(const rstl::reserved_vector& snowForces); + void UpdateRainParticles(const CVectorFixed8_8& zVec, const zeus::CVector3f& oopbtws, float dt); + void UpdateUnderwaterParticles(const CVectorFixed8_8& zVec); + void SetupSnowTevs(const CStateManager& mgr) const; + void SetupRainTevs() const; + void SetupUnderwaterTevs(const zeus::CTransform& invXf, const CStateManager& mgr) const; - void SetSplashEffectRate(float f, const CStateManager& mgr); - void UpdateRainSounds(const CStateManager& mgr); - zeus::CVector3f GetParticleBoundsToWorldScale() const; - zeus::CTransform GetParticleBoundsToWorldTransform() const; - void UpdateVisorSplash(CStateManager& mgr, float dt, const zeus::CTransform& camXf); - void MoveWrapCells(s32, s32); - void CalculateSnowForces(const CVectorFixed8_8& zVec, rstl::reserved_vector& snowForces, - EEnvFxType type, const zeus::CVector3f& oopbtws, float dt); - static void BuildBlockObjectList(rstl::reserved_vector& list, CStateManager& mgr); - void UpdateBlockedGrids(CStateManager& mgr, EEnvFxType type, const zeus::CTransform& camXf, - const zeus::CTransform& xf, const zeus::CTransform& invXf); - void CreateNewParticles(EEnvFxType type); - void UpdateSnowParticles(const rstl::reserved_vector& snowForces); - void UpdateRainParticles(const CVectorFixed8_8& zVec, const zeus::CVector3f& oopbtws, float dt); - void UpdateUnderwaterParticles(const CVectorFixed8_8& zVec); - void SetupSnowTevs(const CStateManager& mgr) const; - void SetupRainTevs() const; - void SetupUnderwaterTevs(const zeus::CTransform& invXf, const CStateManager& mgr) const; public: - CEnvFxManager(); - void AsyncLoadResources(CStateManager& mgr); + CEnvFxManager(); + void AsyncLoadResources(CStateManager& mgr); - void Update(float, CStateManager& mgr); - void Render(const CStateManager& mgr) const; - void SetFxDensity(s32, float); - void AreaLoaded(); - void SetSplashRate(float f) { xb54_baseSplashRate = f; } - bool IsSplashActive() const { return x24_enableSplash; } - float GetRainMagnitude() const { return x30_fxDensity; } - void Cleanup(); + void Update(float, CStateManager& mgr); + void Render(const CStateManager& mgr) const; + void SetFxDensity(s32, float); + void AreaLoaded(); + void SetSplashRate(float f) { xb54_baseSplashRate = f; } + bool IsSplashActive() const { return x24_enableSplash; } + float GetRainMagnitude() const { return x30_fxDensity; } + void Cleanup(); - static void Initialize(); + static void Initialize(); }; -} - +} // namespace urde diff --git a/Runtime/World/CExplosion.cpp b/Runtime/World/CExplosion.cpp index ab63c28e1..78dac3b59 100644 --- a/Runtime/World/CExplosion.cpp +++ b/Runtime/World/CExplosion.cpp @@ -5,138 +5,117 @@ #include "Graphics/CBooRenderer.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { CExplosion::CExplosion(const TLockedToken& particle, TUniqueId uid, bool active, - const CEntityInfo& info, std::string_view name, const zeus::CTransform& xf, - u32 flags, const zeus::CVector3f& scale, const zeus::CColor& color) -: CEffect(uid, info, active, name, xf) -{ - xe8_particleGen = std::make_unique(particle, CElementGen::EModelOrientationType::Normal, - flags & 0x2 ? CElementGen::EOptionalSystemFlags::Two : - CElementGen::EOptionalSystemFlags::One); - xf0_particleDesc = particle.GetObj(); - xf4_24_renderThermalHot = flags & 0x4; - xf4_25_ = true; - xf4_26_renderXray = flags & 0x8; - xe6_27_thermalVisorFlags = flags & 0x1 ? 1 : 2; - xe8_particleGen->SetGlobalTranslation(xf.origin); - xe8_particleGen->SetOrientation(xf.getRotation()); - xe8_particleGen->SetGlobalScale(scale); - xe8_particleGen->SetModulationColor(color); + const CEntityInfo& info, std::string_view name, const zeus::CTransform& xf, u32 flags, + const zeus::CVector3f& scale, const zeus::CColor& color) +: CEffect(uid, info, active, name, xf) { + xe8_particleGen = std::make_unique(particle, CElementGen::EModelOrientationType::Normal, + flags & 0x2 ? CElementGen::EOptionalSystemFlags::Two + : CElementGen::EOptionalSystemFlags::One); + xf0_particleDesc = particle.GetObj(); + xf4_24_renderThermalHot = flags & 0x4; + xf4_25_ = true; + xf4_26_renderXray = flags & 0x8; + xe6_27_thermalVisorFlags = flags & 0x1 ? 1 : 2; + xe8_particleGen->SetGlobalTranslation(xf.origin); + xe8_particleGen->SetOrientation(xf.getRotation()); + xe8_particleGen->SetGlobalScale(scale); + xe8_particleGen->SetModulationColor(color); } CExplosion::CExplosion(const TLockedToken& electric, TUniqueId uid, bool active, - const CEntityInfo& info, std::string_view name, const zeus::CTransform& xf, - u32 flags, const zeus::CVector3f& scale, const zeus::CColor& color) -: CEffect(uid, info, active, name, xf) -{ - xe8_particleGen = std::make_unique(electric); - xf0_electricDesc = electric.GetObj(); - xf4_24_renderThermalHot = flags & 0x4; - xf4_25_ = true; - xf4_26_renderXray = flags & 0x8; - xe6_27_thermalVisorFlags = flags & 0x1 ? 1 : 2; - xe8_particleGen->SetGlobalTranslation(xf.origin); - xe8_particleGen->SetOrientation(xf.getRotation()); - xe8_particleGen->SetGlobalScale(scale); - xe8_particleGen->SetModulationColor(color); + const CEntityInfo& info, std::string_view name, const zeus::CTransform& xf, u32 flags, + const zeus::CVector3f& scale, const zeus::CColor& color) +: CEffect(uid, info, active, name, xf) { + xe8_particleGen = std::make_unique(electric); + xf0_electricDesc = electric.GetObj(); + xf4_24_renderThermalHot = flags & 0x4; + xf4_25_ = true; + xf4_26_renderXray = flags & 0x8; + xe6_27_thermalVisorFlags = flags & 0x1 ? 1 : 2; + xe8_particleGen->SetGlobalTranslation(xf.origin); + xe8_particleGen->SetOrientation(xf.getRotation()); + xe8_particleGen->SetGlobalScale(scale); + xe8_particleGen->SetModulationColor(color); } -void CExplosion::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CExplosion::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Deleted) - { - if (xec_explosionLight != kInvalidUniqueId) - mgr.FreeScriptObject(xec_explosionLight); - } - else if (msg == EScriptObjectMessage::Registered) - { - if (xe8_particleGen->SystemHasLight()) - { - xec_explosionLight = mgr.AllocateUniqueId(); - mgr.AddObject(new CGameLight(xec_explosionLight, GetAreaIdAlways(), true, "ExplodePLight_" + x10_name, x34_transform, - GetUniqueId(), xe8_particleGen->GetLight(), 1, /*xf0_particleDesc*/ 0, 0.f)); - } - } - - CActor::AcceptScriptMsg(msg, sender, mgr); +void CExplosion::Accept(IVisitor& visitor) { visitor.Visit(this); } +void CExplosion::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Deleted) { if (xec_explosionLight != kInvalidUniqueId) - mgr.SendScriptMsgAlways(sender, xec_explosionLight, msg); + mgr.FreeScriptObject(xec_explosionLight); + } else if (msg == EScriptObjectMessage::Registered) { + if (xe8_particleGen->SystemHasLight()) { + xec_explosionLight = mgr.AllocateUniqueId(); + mgr.AddObject(new CGameLight(xec_explosionLight, GetAreaIdAlways(), true, "ExplodePLight_" + x10_name, + x34_transform, GetUniqueId(), xe8_particleGen->GetLight(), 1, /*xf0_particleDesc*/ 0, + 0.f)); + } + } + + CActor::AcceptScriptMsg(msg, sender, mgr); + + if (xec_explosionLight != kInvalidUniqueId) + mgr.SendScriptMsgAlways(sender, xec_explosionLight, msg); } -void CExplosion::Think(float dt, CStateManager& mgr) -{ - if (xe4_28_transformDirty) - { - xe8_particleGen->SetGlobalTranslation(GetTranslation()); - xe8_particleGen->SetGlobalOrientation(GetTransform().getRotation()); - xe4_28_transformDirty = false; - } - xe8_particleGen->Update(dt); +void CExplosion::Think(float dt, CStateManager& mgr) { + if (xe4_28_transformDirty) { + xe8_particleGen->SetGlobalTranslation(GetTranslation()); + xe8_particleGen->SetGlobalOrientation(GetTransform().getRotation()); + xe4_28_transformDirty = false; + } + xe8_particleGen->Update(dt); - if (xec_explosionLight != kInvalidUniqueId) - { - TCastToPtr light = mgr.ObjectById(xec_explosionLight); - if (light && x30_24_active) - light->SetLight(xe8_particleGen->GetLight()); - } + if (xec_explosionLight != kInvalidUniqueId) { + TCastToPtr light = mgr.ObjectById(xec_explosionLight); + if (light && x30_24_active) + light->SetLight(xe8_particleGen->GetLight()); + } - xf8_time += dt; + xf8_time += dt; - if (xf8_time > 15.f || xe8_particleGen->IsSystemDeletable()) - mgr.FreeScriptObject(GetUniqueId()); + if (xf8_time > 15.f || xe8_particleGen->IsSystemDeletable()) + mgr.FreeScriptObject(GetUniqueId()); } -void CExplosion::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - CActor::PreRender(mgr, frustum); - xe4_30_outOfFrustum = !xf4_25_ || !frustum.aabbFrustumTest(x9c_renderBounds); +void CExplosion::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + CActor::PreRender(mgr, frustum); + xe4_30_outOfFrustum = !xf4_25_ || !frustum.aabbFrustumTest(x9c_renderBounds); } -void CExplosion::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - if (xe4_30_outOfFrustum) - return; +void CExplosion::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + if (xe4_30_outOfFrustum) + return; - if (!(xf4_24_renderThermalHot && mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) - && !(xf4_26_renderXray && mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay)) - { - g_Renderer->AddParticleGen(*xe8_particleGen.get()); - return; - } + if (!(xf4_24_renderThermalHot && mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) && + !(xf4_26_renderXray && mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay)) { + g_Renderer->AddParticleGen(*xe8_particleGen.get()); + return; + } - EnsureRendered(mgr); + EnsureRendered(mgr); } -void CExplosion::Render(const CStateManager& mgr) const -{ - if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot && xf4_24_renderThermalHot) - { - CElementGen::SetSubtractBlend(true); - CBooModel::SetRenderModelBlack(true); - xe8_particleGen->Render(); - CBooModel::SetRenderModelBlack(false); - CElementGen::SetSubtractBlend(false); - return; - } - - CElementGen::SetSubtractBlend(xf4_24_renderThermalHot); - CGraphics::SetFog(ERglFogMode::PerspLin, 0.f, 74.f, zeus::CColor::skBlack); +void CExplosion::Render(const CStateManager& mgr) const { + if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot && xf4_24_renderThermalHot) { + CElementGen::SetSubtractBlend(true); + CBooModel::SetRenderModelBlack(true); xe8_particleGen->Render(); - mgr.SetupFogForArea(GetAreaIdAlways()); + CBooModel::SetRenderModelBlack(false); CElementGen::SetSubtractBlend(false); + return; + } + + CElementGen::SetSubtractBlend(xf4_24_renderThermalHot); + CGraphics::SetFog(ERglFogMode::PerspLin, 0.f, 74.f, zeus::CColor::skBlack); + xe8_particleGen->Render(); + mgr.SetupFogForArea(GetAreaIdAlways()); + CElementGen::SetSubtractBlend(false); } -bool CExplosion::CanRenderUnsorted(const CStateManager &) const -{ - return false; -} -} +bool CExplosion::CanRenderUnsorted(const CStateManager&) const { return false; } +} // namespace urde diff --git a/Runtime/World/CExplosion.hpp b/Runtime/World/CExplosion.hpp index a11bb06cd..a97893ce8 100644 --- a/Runtime/World/CExplosion.hpp +++ b/Runtime/World/CExplosion.hpp @@ -4,39 +4,35 @@ #include "Particle/CElementGen.hpp" #include "Particle/CGenDescription.hpp" -namespace urde -{ +namespace urde { -class CExplosion : public CEffect -{ - std::unique_ptr xe8_particleGen; - TUniqueId xec_explosionLight = kInvalidUniqueId; - union - { - const CGenDescription* xf0_particleDesc; - const CElectricDescription* xf0_electricDesc; - }; - bool xf4_24_renderThermalHot:1; - bool xf4_25_:1; - bool xf4_26_renderXray:1; - float xf8_time = 0.f; +class CExplosion : public CEffect { + std::unique_ptr xe8_particleGen; + TUniqueId xec_explosionLight = kInvalidUniqueId; + union { + const CGenDescription* xf0_particleDesc; + const CElectricDescription* xf0_electricDesc; + }; + bool xf4_24_renderThermalHot : 1; + bool xf4_25_ : 1; + bool xf4_26_renderXray : 1; + float xf8_time = 0.f; public: - CExplosion(const TLockedToken& particle, TUniqueId uid, bool active, - const CEntityInfo& info, std::string_view name, const zeus::CTransform& xf, - u32, const zeus::CVector3f& scale, const zeus::CColor& color); - CExplosion(const TLockedToken& electric, TUniqueId uid, bool active, - const CEntityInfo& info, std::string_view name, const zeus::CTransform& xf, - u32, const zeus::CVector3f& scale, const zeus::CColor& color); + CExplosion(const TLockedToken& particle, TUniqueId uid, bool active, const CEntityInfo& info, + std::string_view name, const zeus::CTransform& xf, u32, const zeus::CVector3f& scale, + const zeus::CColor& color); + CExplosion(const TLockedToken& electric, TUniqueId uid, bool active, const CEntityInfo& info, + std::string_view name, const zeus::CTransform& xf, u32, const zeus::CVector3f& scale, + const zeus::CColor& color); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - void PreRender(CStateManager&, const zeus::CFrustum&); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - void Render(const CStateManager&) const; - bool CanRenderUnsorted(const CStateManager&) const; + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void PreRender(CStateManager&, const zeus::CFrustum&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const; + bool CanRenderUnsorted(const CStateManager&) const; }; -} - +} // namespace urde diff --git a/Runtime/World/CFire.cpp b/Runtime/World/CFire.cpp index 0db903e79..c7a6d13fb 100644 --- a/Runtime/World/CFire.cpp +++ b/Runtime/World/CFire.cpp @@ -7,109 +7,97 @@ #include "Graphics/CBooRenderer.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CFire::CFire(TToken effect, TUniqueId uid, TAreaId aId, bool active, TUniqueId owner, - const zeus::CTransform& xf, const CDamageInfo& dInfo, const zeus::CAABox& aabox, const zeus::CVector3f& vec, - bool b1, CAssetId visorEffect, bool b2, bool b3, bool b4, float f1, float f2, float f3, float f4) + const zeus::CTransform& xf, const CDamageInfo& dInfo, const zeus::CAABox& aabox, + const zeus::CVector3f& vec, bool b1, CAssetId visorEffect, bool b2, bool b3, bool b4, float f1, float f2, + float f3, float f4) : CActor(uid, active, "Fire"sv, CEntityInfo(aId, NullConnectionList), xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Projectile), CActorParameters::None(), owner) - , xe8_(new CElementGen(effect)) - , xec_ownerId(owner) - , xf0_damageInfo(dInfo) - , x10c_damageInfo(dInfo) - , x128_(aabox) - , x144_(f1) - , x148_24_(b2) - , x148_25_(b3) - , x148_26_(b4) - , x148_27_(b4 && b3 && b2) - , x148_28_(false) - , x148_29_(b1) - , x14c_(f2) - , x150_(visorEffect) - , x154_(f3) - , x158_(f4) -{ - xe8_->SetGlobalScale(vec); - xe8_->SetTranslation(xf.origin); +, xe8_(new CElementGen(effect)) +, xec_ownerId(owner) +, xf0_damageInfo(dInfo) +, x10c_damageInfo(dInfo) +, x128_(aabox) +, x144_(f1) +, x148_24_(b2) +, x148_25_(b3) +, x148_26_(b4) +, x148_27_(b4 && b3 && b2) +, x148_28_(false) +, x148_29_(b1) +, x14c_(f2) +, x150_(visorEffect) +, x154_(f3) +, x158_(f4) { + xe8_->SetGlobalScale(vec); + xe8_->SetTranslation(xf.origin); } -void CFire::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CFire::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CFire::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); + + if (msg == EScriptObjectMessage::Registered) { + xe8_->SetParticleEmission(true); + SetActive(true); + } } -void CFire::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); +void CFire::Think(float dt, CStateManager& mgr) { + float particleCount = xe8_->GetParticleCount() / xe8_->GetMaxParticles(); + if (GetActive()) { + xe8_->Update(dt * x144_); + x10c_damageInfo = CDamageInfo(xf0_damageInfo, dt * std::max(0.5f, particleCount)); + } - if (msg == EScriptObjectMessage::Registered) - { - xe8_->SetParticleEmission(true); - SetActive(true); - } + bool doFree = false; + if (xe8_->IsSystemDeletable()) + doFree = true; + + if (x148_29_) { + auto playerBounds = mgr.GetPlayer().GetTouchBounds(); + auto bounds = GetTouchBounds(); + if (playerBounds->intersects(*bounds) && doFree && particleCount > 0.5f) + mgr.GetPlayer().SetVisorSteam(particleCount * x14c_, x154_, x158_, x150_, true); + else + mgr.GetPlayer().SetVisorSteam(0.f, 1.f, 1.f, {}, true); + } + + x15c_ += dt; + + if (x15c_ > 45.f) + doFree = true; + + if (doFree) + mgr.FreeScriptObject(GetUniqueId()); } -void CFire::Think(float dt, CStateManager& mgr) -{ - float particleCount = xe8_->GetParticleCount() / xe8_->GetMaxParticles(); - if (GetActive()) - { - xe8_->Update(dt * x144_); - x10c_damageInfo = CDamageInfo(xf0_damageInfo, dt * std::max(0.5f, particleCount)); - } +void CFire::Touch(CActor& act, CStateManager& mgr) { + if (act.GetUniqueId() == xec_ownerId) + return; - bool doFree = false; - if (xe8_->IsSystemDeletable()) - doFree = true; - - if (x148_29_) - { - auto playerBounds = mgr.GetPlayer().GetTouchBounds(); - auto bounds = GetTouchBounds(); - if (playerBounds->intersects(*bounds) && doFree && particleCount > 0.5f) - mgr.GetPlayer().SetVisorSteam(particleCount * x14c_, x154_, x158_, x150_, true); - else - mgr.GetPlayer().SetVisorSteam(0.f, 1.f, 1.f, {}, true); - } - - x15c_ += dt; - - if (x15c_ > 45.f) - doFree = true; - - if (doFree) - mgr.FreeScriptObject(GetUniqueId()); + mgr.ApplyDamage(GetUniqueId(), act.GetUniqueId(), GetUniqueId(), x10c_damageInfo, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); } -void CFire::Touch(CActor& act, CStateManager& mgr) -{ - if (act.GetUniqueId() == xec_ownerId) - return; +void CFire::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + bool drawParticles = true; + if (!x148_27_) { + using EPlayerVisor = CPlayerState::EPlayerVisor; + CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); + if (visor == EPlayerVisor::Combat || visor == EPlayerVisor::Scan) + drawParticles = x148_24_; + else if (visor == EPlayerVisor::XRay) + drawParticles = x148_26_; + else if (visor == EPlayerVisor::Thermal) + drawParticles = x148_25_; + } - mgr.ApplyDamage(GetUniqueId(), act.GetUniqueId(), GetUniqueId(), x10c_damageInfo, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + if (drawParticles) + g_Renderer->AddParticleGen(*xe8_); + CActor::AddToRenderer(frustum, mgr); } -void CFire::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - bool drawParticles = true; - if (!x148_27_) - { - using EPlayerVisor = CPlayerState::EPlayerVisor; - CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); - if (visor == EPlayerVisor::Combat || visor == EPlayerVisor::Scan) - drawParticles = x148_24_; - else if (visor == EPlayerVisor::XRay) - drawParticles = x148_26_; - else if (visor == EPlayerVisor::Thermal) - drawParticles = x148_25_; - } - - if (drawParticles) - g_Renderer->AddParticleGen(*xe8_); - CActor::AddToRenderer(frustum, mgr); -} - -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/World/CFire.hpp b/Runtime/World/CFire.hpp index d2e70fd6d..ffd816971 100644 --- a/Runtime/World/CFire.hpp +++ b/Runtime/World/CFire.hpp @@ -3,44 +3,42 @@ #include "CActor.hpp" #include "CDamageInfo.hpp" -namespace urde -{ +namespace urde { class CElementGen; -class CFire : public CActor -{ - std::unique_ptr xe8_; - TUniqueId xec_ownerId; - CDamageInfo xf0_damageInfo; - CDamageInfo x10c_damageInfo; - std::experimental::optional x128_; - float x144_; - bool x148_24_ : 1; - bool x148_25_ : 1; - bool x148_26_ : 1; - bool x148_27_ : 1; - bool x148_28_ : 1; - bool x148_29_ : 1; - float x14c_; - CAssetId x150_; - float x154_; - float x158_; - float x15c_ = 0.f; +class CFire : public CActor { + std::unique_ptr xe8_; + TUniqueId xec_ownerId; + CDamageInfo xf0_damageInfo; + CDamageInfo x10c_damageInfo; + std::experimental::optional x128_; + float x144_; + bool x148_24_ : 1; + bool x148_25_ : 1; + bool x148_26_ : 1; + bool x148_27_ : 1; + bool x148_28_ : 1; + bool x148_29_ : 1; + float x14c_; + CAssetId x150_; + float x154_; + float x158_; + float x15c_ = 0.f; + public: - CFire(TToken, TUniqueId, TAreaId, bool, TUniqueId, const zeus::CTransform&, const CDamageInfo&, - const zeus::CAABox&, const zeus::CVector3f&, bool, CAssetId, bool, bool, bool, float, float, float, float); + CFire(TToken, TUniqueId, TAreaId, bool, TUniqueId, const zeus::CTransform&, const CDamageInfo&, + const zeus::CAABox&, const zeus::CVector3f&, bool, CAssetId, bool, bool, bool, float, float, float, float); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - std::experimental::optional GetTouchBounds() const - { - if (GetActive()) - return x128_; + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + std::experimental::optional GetTouchBounds() const { + if (GetActive()) + return x128_; - return {}; - } + return {}; + } - void Touch(CActor&, CStateManager&); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Touch(CActor&, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; }; -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/World/CFishCloud.cpp b/Runtime/World/CFishCloud.cpp index 25fecd664..c6e28e32e 100644 --- a/Runtime/World/CFishCloud.cpp +++ b/Runtime/World/CFishCloud.cpp @@ -2,8 +2,7 @@ #include "CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CFishCloud::CFishCloud(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& scale, const zeus::CTransform& xf, CModelData&& mData, @@ -11,36 +10,17 @@ CFishCloud::CFishCloud(TUniqueId uid, bool active, std::string_view name, const float f7, float f8, float f9, float f10, float f11, float f12, float f13, u32 w2, const zeus::CColor& color, bool b1, float f14, CAssetId part1, u32 w3, CAssetId part2, u32 w4, CAssetId part3, u32 w5, CAssetId part4, u32 w6, u32 w7, bool b2, bool b3) -: CActor(uid, active, name, info, xf, std::move(mData), {EMaterialTypes::NoStepLogic}, - CActorParameters::None(), kInvalidUniqueId) -{ +: CActor(uid, active, name, info, xf, std::move(mData), {EMaterialTypes::NoStepLogic}, CActorParameters::None(), + kInvalidUniqueId) {} -} +void CFishCloud::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CFishCloud::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CFishCloud::RemoveRepulsor(TUniqueId) {} -void CFishCloud::RemoveRepulsor(TUniqueId) -{ +void CFishCloud::RemoveAttractor(TUniqueId) {} -} +void CFishCloud::AddRepulsor(TUniqueId, float, float) {} -void CFishCloud::RemoveAttractor(TUniqueId) -{ - -} - -void CFishCloud::AddRepulsor(TUniqueId, float, float) -{ - -} - -void CFishCloud::AddAttractor(TUniqueId, float, float) -{ - -} - -} +void CFishCloud::AddAttractor(TUniqueId, float, float) {} +} // namespace urde diff --git a/Runtime/World/CFishCloud.hpp b/Runtime/World/CFishCloud.hpp index f69cfa330..6b34719e8 100644 --- a/Runtime/World/CFishCloud.hpp +++ b/Runtime/World/CFishCloud.hpp @@ -2,44 +2,40 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { -class CFishCloud : public CActor -{ - class CModifierSource - { - TUniqueId x0_source; - float x4_; - float x8_; - bool xc_; - bool xd_; - public: - CModifierSource(TUniqueId, bool, float, float); - void SetAffectPriority(float); - void SetAffectRadius(float); - float GetAffectPriority() const; - float GetAffectRadius() const; - bool IsRepulsor(); - TUniqueId GetSource() const; +class CFishCloud : public CActor { + class CModifierSource { + TUniqueId x0_source; + float x4_; + float x8_; + bool xc_; + bool xd_; - bool operator<(const CModifierSource& other) const { return x0_source < other.x0_source; } - }; + public: + CModifierSource(TUniqueId, bool, float, float); + void SetAffectPriority(float); + void SetAffectRadius(float); + float GetAffectPriority() const; + float GetAffectRadius() const; + bool IsRepulsor(); + TUniqueId GetSource() const; + + bool operator<(const CModifierSource& other) const { return x0_source < other.x0_source; } + }; public: - CFishCloud(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, - const zeus::CVector3f& scale, const zeus::CTransform& xf, CModelData&& mData, - const CAnimRes& aRes, u32 w1, float f1, float f2, float f3, float f4, float f5, float f6, - float f7, float f8, float f9, float f10, float f11, float f12, float f13, u32 w2, - const zeus::CColor& color, bool b1, float f14, CAssetId part1, u32 w3, CAssetId part2, u32 w4, - CAssetId part3, u32 w5, CAssetId part4, u32 w6, u32 w7, bool b2, bool b3); + CFishCloud(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& scale, + const zeus::CTransform& xf, CModelData&& mData, const CAnimRes& aRes, u32 w1, float f1, float f2, float f3, + float f4, float f5, float f6, float f7, float f8, float f9, float f10, float f11, float f12, float f13, + u32 w2, const zeus::CColor& color, bool b1, float f14, CAssetId part1, u32 w3, CAssetId part2, u32 w4, + CAssetId part3, u32 w5, CAssetId part4, u32 w6, u32 w7, bool b2, bool b3); - void Accept(IVisitor& visitor); - void RemoveRepulsor(TUniqueId); - void RemoveAttractor(TUniqueId); - void AddRepulsor(TUniqueId, float, float); - void AddAttractor(TUniqueId, float, float); + void Accept(IVisitor& visitor); + void RemoveRepulsor(TUniqueId); + void RemoveAttractor(TUniqueId); + void AddRepulsor(TUniqueId, float, float); + void AddAttractor(TUniqueId, float, float); }; -} - +} // namespace urde diff --git a/Runtime/World/CFishCloudModifier.cpp b/Runtime/World/CFishCloudModifier.cpp index 1b7235642..8e9800c70 100644 --- a/Runtime/World/CFishCloudModifier.cpp +++ b/Runtime/World/CFishCloudModifier.cpp @@ -4,65 +4,52 @@ #include "CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CFishCloudModifier::CFishCloudModifier(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& eInfo, - const zeus::CVector3f& pos, bool b2, bool b3, float f1, float f2) - : CActor(uid, active, name, eInfo, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(), {EMaterialTypes::NoStepLogic}, - CActorParameters::None(), kInvalidUniqueId) - , xe8_(f1) - , xec_(f2) - , xf0_isRepulsor(b2) - , xf1_(b3) -{ + const zeus::CVector3f& pos, bool b2, bool b3, float f1, float f2) +: CActor(uid, active, name, eInfo, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(), + {EMaterialTypes::NoStepLogic}, CActorParameters::None(), kInvalidUniqueId) +, xe8_(f1) +, xec_(f2) +, xf0_isRepulsor(b2) +, xf1_(b3) {} + +void CFishCloudModifier::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CFishCloudModifier::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); + + if ((msg == EScriptObjectMessage::Activate || msg == EScriptObjectMessage::InitializedInArea) && GetActive()) + AddSelf(mgr); + else if (msg == EScriptObjectMessage::Deactivate || msg == EScriptObjectMessage::Deleted) + RemoveSelf(mgr); } -void CFishCloudModifier::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CFishCloudModifier::AddSelf(CStateManager& mgr) { + for (const SConnection& conn : GetConnectionList()) { + if (conn.x0_state != EScriptObjectState::Modify || conn.x4_msg != EScriptObjectMessage::Follow) + continue; -void CFishCloudModifier::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); - - if ((msg == EScriptObjectMessage::Activate || msg == EScriptObjectMessage::InitializedInArea) && GetActive()) - AddSelf(mgr); - else if (msg == EScriptObjectMessage::Deactivate || msg == EScriptObjectMessage::Deleted) - RemoveSelf(mgr); -} - -void CFishCloudModifier::AddSelf(CStateManager& mgr) -{ - for (const SConnection& conn : GetConnectionList()) - { - if (conn.x0_state != EScriptObjectState::Modify || conn.x4_msg != EScriptObjectMessage::Follow) - continue; - - if (TCastToPtr fishCloud = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) - { - if (xf0_isRepulsor) - fishCloud->AddRepulsor(GetUniqueId(), xe8_, xec_); - else - fishCloud->AddAttractor(GetUniqueId(), xe8_, xec_); - } + if (TCastToPtr fishCloud = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) { + if (xf0_isRepulsor) + fishCloud->AddRepulsor(GetUniqueId(), xe8_, xec_); + else + fishCloud->AddAttractor(GetUniqueId(), xe8_, xec_); } + } } -void CFishCloudModifier::RemoveSelf(CStateManager& mgr) -{ - for (const SConnection& conn : GetConnectionList()) - { - if (conn.x0_state != EScriptObjectState::Modify || conn.x4_msg != EScriptObjectMessage::Follow) - continue; +void CFishCloudModifier::RemoveSelf(CStateManager& mgr) { + for (const SConnection& conn : GetConnectionList()) { + if (conn.x0_state != EScriptObjectState::Modify || conn.x4_msg != EScriptObjectMessage::Follow) + continue; - if (TCastToPtr fishCloud = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) - { - if (xf0_isRepulsor) - fishCloud->RemoveRepulsor(GetUniqueId()); - else - fishCloud->RemoveAttractor(GetUniqueId()); - } + if (TCastToPtr fishCloud = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) { + if (xf0_isRepulsor) + fishCloud->RemoveRepulsor(GetUniqueId()); + else + fishCloud->RemoveAttractor(GetUniqueId()); } + } } -} +} // namespace urde diff --git a/Runtime/World/CFishCloudModifier.hpp b/Runtime/World/CFishCloudModifier.hpp index 4e980ca8c..0fafc349b 100644 --- a/Runtime/World/CFishCloudModifier.hpp +++ b/Runtime/World/CFishCloudModifier.hpp @@ -2,21 +2,20 @@ #include "CActor.hpp" -namespace urde -{ -class CFishCloudModifier : public CActor -{ - float xe8_; - float xec_; - bool xf0_isRepulsor; - bool xf1_; +namespace urde { +class CFishCloudModifier : public CActor { + float xe8_; + float xec_; + bool xf0_isRepulsor; + bool xf1_; + public: - CFishCloudModifier(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, bool, bool, float, float); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + CFishCloudModifier(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, bool, bool, float, + float); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void AddSelf(CStateManager&); - void RemoveSelf(CStateManager&); + void AddSelf(CStateManager&); + void RemoveSelf(CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CFluidPlane.cpp b/Runtime/World/CFluidPlane.cpp index aa669822b..d640d29bb 100644 --- a/Runtime/World/CFluidPlane.cpp +++ b/Runtime/World/CFluidPlane.cpp @@ -5,574 +5,483 @@ #include "CScriptWater.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { CFluidPlane::CFluidPlane(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, float alpha, EFluidType fluidType, float rippleIntensity, const CFluidUVMotion& motion) -: x4_texPattern1Id(texPattern1), x8_texPattern2Id(texPattern2), xc_texColorId(texColor), x40_alpha(alpha), - x44_fluidType(fluidType), x48_rippleIntensity(rippleIntensity), x4c_uvMotion(motion) -{ - if (g_ResFactory->GetResourceTypeById(texPattern1) == FOURCC('TXTR')) - x10_texPattern1 = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern1}); - if (g_ResFactory->GetResourceTypeById(texPattern2) == FOURCC('TXTR')) - x20_texPattern2 = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern2}); - if (g_ResFactory->GetResourceTypeById(texColor) == FOURCC('TXTR')) - x30_texColor = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texColor}); +: x4_texPattern1Id(texPattern1) +, x8_texPattern2Id(texPattern2) +, xc_texColorId(texColor) +, x40_alpha(alpha) +, x44_fluidType(fluidType) +, x48_rippleIntensity(rippleIntensity) +, x4c_uvMotion(motion) { + if (g_ResFactory->GetResourceTypeById(texPattern1) == FOURCC('TXTR')) + x10_texPattern1 = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern1}); + if (g_ResFactory->GetResourceTypeById(texPattern2) == FOURCC('TXTR')) + x20_texPattern2 = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern2}); + if (g_ResFactory->GetResourceTypeById(texColor) == FOURCC('TXTR')) + x30_texColor = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texColor}); } -float CFluidPlane::ProjectRippleVelocity(float baseI, float velDot) const -{ - float tmp = 0.5f * baseI * velDot * velDot; - if (tmp != 0.f) - tmp = std::sqrt(tmp); - if (tmp >= 160.f) - return 1.f; - return tmp / 160.f; +float CFluidPlane::ProjectRippleVelocity(float baseI, float velDot) const { + float tmp = 0.5f * baseI * velDot * velDot; + if (tmp != 0.f) + tmp = std::sqrt(tmp); + if (tmp >= 160.f) + return 1.f; + return tmp / 160.f; } -float CFluidPlane::CalculateRippleIntensity(float baseI) const -{ - float mul; - switch (x44_fluidType) - { - case EFluidType::NormalWater: - mul = g_tweakGame->GetRippleIntensityNormal(); - break; - case EFluidType::PoisonWater: - mul = g_tweakGame->GetRippleIntensityPoison(); - break; - case EFluidType::Lava: - mul = g_tweakGame->GetRippleIntensityLava(); - break; - case EFluidType::PhazonFluid: - case EFluidType::Four: - mul = 0.8f; - break; - case EFluidType::ThickLava: - mul = 1.f; - break; - } +float CFluidPlane::CalculateRippleIntensity(float baseI) const { + float mul; + switch (x44_fluidType) { + case EFluidType::NormalWater: + mul = g_tweakGame->GetRippleIntensityNormal(); + break; + case EFluidType::PoisonWater: + mul = g_tweakGame->GetRippleIntensityPoison(); + break; + case EFluidType::Lava: + mul = g_tweakGame->GetRippleIntensityLava(); + break; + case EFluidType::PhazonFluid: + case EFluidType::Four: + mul = 0.8f; + break; + case EFluidType::ThickLava: + mul = 1.f; + break; + } - return zeus::clamp(0.f, baseI * mul * (1.f - x48_rippleIntensity + 0.5f), 1.f); + return zeus::clamp(0.f, baseI * mul * (1.f - x48_rippleIntensity + 0.5f), 1.f); } -void CFluidPlane::AddRipple(float mag, TUniqueId rippler, const zeus::CVector3f& center, - CScriptWater& water, CStateManager& mgr) -{ - if (!water.CanRippleAtPoint(center)) - return; +void CFluidPlane::AddRipple(float mag, TUniqueId rippler, const zeus::CVector3f& center, CScriptWater& water, + CStateManager& mgr) { + if (!water.CanRippleAtPoint(center)) + return; - mag = CalculateRippleIntensity(mag); - mgr.GetFluidPlaneManager()->RippleManager().AddRipple(CRipple(rippler, center, mag)); + mag = CalculateRippleIntensity(mag); + mgr.GetFluidPlaneManager()->RippleManager().AddRipple(CRipple(rippler, center, mag)); } void CFluidPlane::AddRipple(float intensity, TUniqueId rippler, const zeus::CVector3f& center, const zeus::CVector3f& velocity, const CScriptWater& water, CStateManager& mgr, - const zeus::CVector3f& upVec) -{ - if (!water.CanRippleAtPoint(center)) - return; + const zeus::CVector3f& upVec) { + if (!water.CanRippleAtPoint(center)) + return; - intensity = CalculateRippleIntensity(ProjectRippleVelocity(intensity, upVec.dot(velocity))); - mgr.GetFluidPlaneManager()->RippleManager().AddRipple(CRipple(rippler, center, intensity)); + intensity = CalculateRippleIntensity(ProjectRippleVelocity(intensity, upVec.dot(velocity))); + mgr.GetFluidPlaneManager()->RippleManager().AddRipple(CRipple(rippler, center, intensity)); } -void CFluidPlane::AddRipple(const CRipple& ripple, const CScriptWater& water, CStateManager& mgr) -{ - if (!water.CanRippleAtPoint(ripple.GetCenter())) - return; - mgr.GetFluidPlaneManager()->RippleManager().AddRipple(ripple); +void CFluidPlane::AddRipple(const CRipple& ripple, const CScriptWater& water, CStateManager& mgr) { + if (!water.CanRippleAtPoint(ripple.GetCenter())) + return; + mgr.GetFluidPlaneManager()->RippleManager().AddRipple(ripple); } -void CFluidPlane::RenderStripWithRipples(float curY, - const CFluidPlaneRender::SHFieldSample (&heights)[46][46], +void CFluidPlane::RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9], int startYDiv, const CFluidPlaneRender::SPatchInfo& info, std::vector& vOut, - std::vector& pvOut) const -{ - m_shader->bindRegular(); + std::vector& pvOut) const { + m_shader->bindRegular(); - int yTile = (startYDiv + CFluidPlaneRender::numSubdivisionsInTile - 1) / - CFluidPlaneRender::numSubdivisionsInTile; - int endXTile = (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) / - CFluidPlaneRender::numSubdivisionsInTile; + int yTile = (startYDiv + CFluidPlaneRender::numSubdivisionsInTile - 1) / CFluidPlaneRender::numSubdivisionsInTile; + int endXTile = + (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) / CFluidPlaneRender::numSubdivisionsInTile; - int midDiv = CFluidPlaneRender::numSubdivisionsInTile / 2; - float tileMid = info.x18_rippleResolution * midDiv; - float yMin = curY; - float yMid = curY + tileMid; + int midDiv = CFluidPlaneRender::numSubdivisionsInTile / 2; + float tileMid = info.x18_rippleResolution * midDiv; + float yMin = curY; + float yMid = curY + tileMid; - float curX = info.x4_localMin.x(); - int gridCell = info.x28_tileX + info.x2a_gridDimX * (info.x2e_tileY + yTile - 1); - int xTile = 1; - int tileSpan; - for (int i = 1 ; i < info.x0_xSubdivs - 2 ; - i += CFluidPlaneRender::numSubdivisionsInTile * tileSpan, gridCell += tileSpan, - xTile += tileSpan, curX += info.x14_tileSize * tileSpan) - { - tileSpan = 1; - if (info.x30_gridFlags && !info.x30_gridFlags[gridCell]) - continue; + float curX = info.x4_localMin.x(); + int gridCell = info.x28_tileX + info.x2a_gridDimX * (info.x2e_tileY + yTile - 1); + int xTile = 1; + int tileSpan; + for (int i = 1; i < info.x0_xSubdivs - 2; i += CFluidPlaneRender::numSubdivisionsInTile * tileSpan, + gridCell += tileSpan, xTile += tileSpan, curX += info.x14_tileSize * tileSpan) { + tileSpan = 1; + if (info.x30_gridFlags && !info.x30_gridFlags[gridCell]) + continue; - if ((flags[yTile][xTile] & 0x1f) == 0x1f) - { - for (; xTile+tileSpan<=endXTile ; ++tileSpan) - { - if ((flags[yTile][xTile+tileSpan] & 0x1f) != 0x1f) - break; - if (info.x30_gridFlags && !info.x30_gridFlags[gridCell+tileSpan]) - break; - } + if ((flags[yTile][xTile] & 0x1f) == 0x1f) { + for (; xTile + tileSpan <= endXTile; ++tileSpan) { + if ((flags[yTile][xTile + tileSpan] & 0x1f) != 0x1f) + break; + if (info.x30_gridFlags && !info.x30_gridFlags[gridCell + tileSpan]) + break; + } - int stripDivCount = tileSpan * CFluidPlaneRender::numSubdivisionsInTile + 1; - int remSubdivs = CFluidPlaneRender::numSubdivisionsInTile; - std::function func; + int stripDivCount = tileSpan * CFluidPlaneRender::numSubdivisionsInTile + 1; + int remSubdivs = CFluidPlaneRender::numSubdivisionsInTile; + std::function func; - switch (info.x37_normalMode) - { - case CFluidPlaneRender::NormalMode::None: - func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) - { - vOut.emplace_back(zeus::CVector3f(x, y, samp.height)); - }; - break; - case CFluidPlaneRender::NormalMode::NoNormals: - func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) - { - vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info)); - }; - break; - case CFluidPlaneRender::NormalMode::Normals: - func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) - { - vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), - samp.MakeColor(info)); - }; - break; - case CFluidPlaneRender::NormalMode::NBT: - func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) - { - vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), - samp.MakeBinormal(), samp.MakeTangent(), samp.MakeColor(info)); - }; - break; - } + switch (info.x37_normalMode) { + case CFluidPlaneRender::NormalMode::None: + func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) { + vOut.emplace_back(zeus::CVector3f(x, y, samp.height)); + }; + break; + case CFluidPlaneRender::NormalMode::NoNormals: + func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) { + vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info)); + }; + break; + case CFluidPlaneRender::NormalMode::Normals: + func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) { + vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), samp.MakeColor(info)); + }; + break; + case CFluidPlaneRender::NormalMode::NBT: + func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) { + vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), samp.MakeBinormal(), + samp.MakeTangent(), samp.MakeColor(info)); + }; + break; + } - float curTileY = yMin; - int curYDiv = startYDiv; - for (; remSubdivs>0 ; --remSubdivs, ++curYDiv, curTileY+=info.x18_rippleResolution) - { - size_t start = vOut.size(); - float curTileX = curX; - for (int v=0 ; v 0; --remSubdivs, ++curYDiv, curTileY += info.x18_rippleResolution) { + size_t start = vOut.size(); + float curTileX = curX; + for (int v = 0; v < stripDivCount; ++v) { + func(curTileX, curTileY, heights[curYDiv][i + v]); + func(curTileX, curTileY + info.x18_rippleResolution, heights[curYDiv + 1][i + v]); + curTileX += info.x18_rippleResolution; } - else - { - bool r19 = (flags[yTile+1][xTile] & 0x2) != 0; // North - bool r16 = (flags[yTile][xTile-1] & 0x8) != 0; // West - bool r18 = (flags[yTile][xTile+1] & 0x4) != 0; // East - bool r17 = (flags[yTile-1][xTile] & 0x1) != 0; // South + CGraphics::DrawArray(start, vOut.size() - start); + } + } else { + bool r19 = (flags[yTile + 1][xTile] & 0x2) != 0; // North + bool r16 = (flags[yTile][xTile - 1] & 0x8) != 0; // West + bool r18 = (flags[yTile][xTile + 1] & 0x4) != 0; // East + bool r17 = (flags[yTile - 1][xTile] & 0x1) != 0; // South - int r6 = (r19 ? CFluidPlaneRender::numSubdivisionsInTile : 1) + 2; - r6 += r18 ? CFluidPlaneRender::numSubdivisionsInTile : 1; - r6 += r17 ? CFluidPlaneRender::numSubdivisionsInTile : 1; - r6 += r16 ? CFluidPlaneRender::numSubdivisionsInTile : 1; + int r6 = (r19 ? CFluidPlaneRender::numSubdivisionsInTile : 1) + 2; + r6 += r18 ? CFluidPlaneRender::numSubdivisionsInTile : 1; + r6 += r17 ? CFluidPlaneRender::numSubdivisionsInTile : 1; + r6 += r16 ? CFluidPlaneRender::numSubdivisionsInTile : 1; - if (r6 == 6 && (info.x37_normalMode == CFluidPlaneRender::NormalMode::Normals || - info.x37_normalMode == CFluidPlaneRender::NormalMode::NBT)) - { - for (; xTile+tileSpan<=endXTile ; ++tileSpan) - { - if ((flags[yTile][xTile+tileSpan] & 0x1f) == 0x1f) - break; - if (info.x30_gridFlags && !info.x30_gridFlags[gridCell+tileSpan]) - break; - if ((flags[yTile+1][xTile+tileSpan] & 0x2) != 0x0) - break; - if ((flags[yTile][xTile+tileSpan+1] & 0x4) != 0x0) - break; - if ((flags[yTile-1][xTile+tileSpan] & 0x1) != 0x0) - break; - } - - int stripDivCount = tileSpan + 1; - size_t start = vOut.size(); - switch (info.x37_normalMode) - { - case CFluidPlaneRender::NormalMode::Normals: - { - int curYDiv0 = startYDiv; - int curYDiv1 = startYDiv + CFluidPlaneRender::numSubdivisionsInTile; - float curTileX = curX; - for (int v=0 ; v toStrip(vOut); - std::function func; - - switch (info.x37_normalMode) - { - case CFluidPlaneRender::NormalMode::None: - func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) - { - toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height)); - }; - break; - case CFluidPlaneRender::NormalMode::NoNormals: - func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) - { - toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info)); - }; - break; - case CFluidPlaneRender::NormalMode::Normals: - func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) - { - toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), - samp.MakeColor(info)); - }; - break; - case CFluidPlaneRender::NormalMode::NBT: - func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) - { - toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), - samp.MakeBinormal(), samp.MakeTangent(), samp.MakeColor(info)); - }; - break; - } - - func(tileMid + curX, yMid, heights[startYDiv+midDiv][i+midDiv]); - - int curXDiv = i; - int curYDiv = startYDiv + CFluidPlaneRender::numSubdivisionsInTile; - float curTileX = curX; - float curTileY = yMin + info.x14_tileSize; - for (int v=0 ; v<(r19 ? CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v) - { - const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv][curXDiv+v]; - func(curTileX, curTileY, samp); - curTileX += info.x18_rippleResolution; - } - - curXDiv = i + CFluidPlaneRender::numSubdivisionsInTile; - curYDiv = startYDiv + CFluidPlaneRender::numSubdivisionsInTile; - curTileX = curX + info.x14_tileSize; - curTileY = yMin + info.x14_tileSize; - for (int v=0 ; v<(r18 ? CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v) - { - const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv-v][curXDiv]; - func(curTileX, curTileY, samp); - curTileY -= info.x18_rippleResolution; - } - - curXDiv = i + CFluidPlaneRender::numSubdivisionsInTile; - curYDiv = startYDiv; - curTileX = curX + info.x14_tileSize; - curTileY = yMin; - for (int v=0 ; v<(r17 ? CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v) - { - const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv][curXDiv-v]; - func(curTileX, curTileY, samp); - curTileX -= info.x18_rippleResolution; - } - - curXDiv = i; - curYDiv = startYDiv; - curTileX = curX; - curTileY = yMin; - if (r16) - { - for (int v=0 ; v toStrip(vOut); + std::function func; + + switch (info.x37_normalMode) { + case CFluidPlaneRender::NormalMode::None: + func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) { + toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height)); + }; + break; + case CFluidPlaneRender::NormalMode::NoNormals: + func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) { + toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info)); + }; + break; + case CFluidPlaneRender::NormalMode::Normals: + func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) { + toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), samp.MakeColor(info)); + }; + break; + case CFluidPlaneRender::NormalMode::NBT: + func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp) { + toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), samp.MakeBinormal(), + samp.MakeTangent(), samp.MakeColor(info)); + }; + break; + } + + func(tileMid + curX, yMid, heights[startYDiv + midDiv][i + midDiv]); + + int curXDiv = i; + int curYDiv = startYDiv + CFluidPlaneRender::numSubdivisionsInTile; + float curTileX = curX; + float curTileY = yMin + info.x14_tileSize; + for (int v = 0; v < (r19 ? CFluidPlaneRender::numSubdivisionsInTile : 1); ++v) { + const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv][curXDiv + v]; + func(curTileX, curTileY, samp); + curTileX += info.x18_rippleResolution; + } + + curXDiv = i + CFluidPlaneRender::numSubdivisionsInTile; + curYDiv = startYDiv + CFluidPlaneRender::numSubdivisionsInTile; + curTileX = curX + info.x14_tileSize; + curTileY = yMin + info.x14_tileSize; + for (int v = 0; v < (r18 ? CFluidPlaneRender::numSubdivisionsInTile : 1); ++v) { + const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv - v][curXDiv]; + func(curTileX, curTileY, samp); + curTileY -= info.x18_rippleResolution; + } + + curXDiv = i + CFluidPlaneRender::numSubdivisionsInTile; + curYDiv = startYDiv; + curTileX = curX + info.x14_tileSize; + curTileY = yMin; + for (int v = 0; v < (r17 ? CFluidPlaneRender::numSubdivisionsInTile : 1); ++v) { + const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv][curXDiv - v]; + func(curTileX, curTileY, samp); + curTileX -= info.x18_rippleResolution; + } + + curXDiv = i; + curYDiv = startYDiv; + curTileX = curX; + curTileY = yMin; + if (r16) { + for (int v = 0; v < CFluidPlaneRender::numSubdivisionsInTile + 1; ++v) { + const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv + v][curXDiv]; + func(curTileX, curTileY, samp); + curTileY += info.x18_rippleResolution; + } + } else { + { + const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv][curXDiv]; + func(curTileX, curTileY, samp); + } + curTileY += info.x14_tileSize; + { + const CFluidPlaneRender::SHFieldSample& samp = + heights[curYDiv + CFluidPlaneRender::numSubdivisionsInTile][curXDiv]; + func(curTileX, curTileY, samp); + } + } + + toStrip.Draw(); + } } + } } void CFluidPlane::RenderPatch(const CFluidPlaneRender::SPatchInfo& info, - const CFluidPlaneRender::SHFieldSample (&heights)[46][46], - const u8 (&flags)[9][9], bool noRipples, bool flagIs1, - std::vector& vOut, - std::vector& pvOut) const -{ - if (noRipples) - { - m_shader->bindRegular(); + const CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9], + bool noRipples, bool flagIs1, std::vector& vOut, + std::vector& pvOut) const { + if (noRipples) { + m_shader->bindRegular(); - float xMin = info.x4_localMin.x(); - float yMin = info.x4_localMin.y(); - float xMax = info.x18_rippleResolution * (info.x0_xSubdivs - 2) + xMin; - float yMax = info.x18_rippleResolution * (info.x1_ySubdivs - 2) + yMin; + float xMin = info.x4_localMin.x(); + float yMin = info.x4_localMin.y(); + float xMax = info.x18_rippleResolution * (info.x0_xSubdivs - 2) + xMin; + float yMax = info.x18_rippleResolution * (info.x1_ySubdivs - 2) + yMin; - switch (info.x37_normalMode) - { - case CFluidPlaneRender::NormalMode::None: - { - size_t start = vOut.size(); - vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f)); - vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f)); - vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f)); - vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f)); - CGraphics::DrawArray(start, 4); - break; - } - case CFluidPlaneRender::NormalMode::NoNormals: - { - size_t start = vOut.size(); - vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f), zeus::CColor::skBlack); - vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f), zeus::CColor::skBlack); - vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CColor::skBlack); - vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CColor::skBlack); - CGraphics::DrawArray(start, 4); - break; - } - case CFluidPlaneRender::NormalMode::Normals: - { - int yTiles = (info.x1_ySubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1; - int xTiles = (info.x0_xSubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1; - int xTileStart = info.x28_tileX + info.x2e_tileY * info.x2a_gridDimX; - yMax = yMin; - for (int curYTile=yTiles ; curYTile>0 ; --curYTile, - yMax += info.x14_tileSize, xTileStart += info.x2a_gridDimX) - { - xMax = xMin; - int nextXTile; - for (int curXTile=0 ; curXTile toStrip(vOut); - - toStrip.EmplaceVert(zeus::CVector3f(xMax + 0.5f * info.x14_tileSize, - yMax + 0.5f * info.x14_tileSize, 0.f), - zeus::CVector3f::skUp, zeus::CColor::skBlack); - - float tmp = xMax; - for (int v=0 ; v<((curYTile == 1) ? - CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v) - { - toStrip.EmplaceVert(zeus::CVector3f(tmp, yMax + info.x14_tileSize, 0.f), - zeus::CVector3f::skUp, zeus::CColor::skBlack); - tmp += info.x18_rippleResolution; - } - - tmp = yMax + info.x14_tileSize; - for (int v=0 ; v<((xTiles - 1 == curXTile) ? - CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v) - { - toStrip.EmplaceVert(zeus::CVector3f(xMax + info.x14_tileSize, tmp, 0.f), - zeus::CVector3f::skUp, zeus::CColor::skBlack); - tmp -= info.x18_rippleResolution; - } - - tmp = xMax + info.x14_tileSize; - for (int v=0 ; v<((curYTile == yTiles) ? - CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v) - { - toStrip.EmplaceVert(zeus::CVector3f(tmp, yMax, 0.f), - zeus::CVector3f::skUp, zeus::CColor::skBlack); - tmp -= info.x18_rippleResolution; - } - - tmp = yMax; - for (int v=0 ; v<((curXTile == 0) ? - CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v) - { - toStrip.EmplaceVert(zeus::CVector3f(xMax, tmp, 0.f), - zeus::CVector3f::skUp, zeus::CColor::skBlack); - tmp += info.x18_rippleResolution; - } - - toStrip.EmplaceVert(zeus::CVector3f(xMax, yMax + info.x14_tileSize, 0.f), - zeus::CVector3f::skUp, zeus::CColor::skBlack); - - toStrip.Draw(); - - nextXTile = curXTile + 1; - xMax += info.x14_tileSize; - } - else - { - nextXTile = curXTile + 1; - while (nextXTile < xTiles - 1 && - (!info.x30_gridFlags || info.x30_gridFlags[xTileStart+nextXTile])) - ++nextXTile; - - size_t start = vOut.size(); - for (int v = 0 ; v < nextXTile - curXTile + 1 ; ++v) - { - vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), - zeus::CVector3f::skUp, zeus::CColor::skBlack); - vOut.emplace_back(zeus::CVector3f(xMax, yMax + info.x14_tileSize, 0.f), - zeus::CVector3f::skUp, zeus::CColor::skBlack); - xMax += info.x14_tileSize; - } - CGraphics::DrawArray(start, vOut.size() - start); - - ++nextXTile; - if (nextXTile == xTiles) - { - --nextXTile; - xMax -= info.x14_tileSize; - } - } - } - else - { - nextXTile = curXTile + 1; - xMax += info.x14_tileSize; - while (nextXTile < xTiles && !info.x30_gridFlags[xTileStart+nextXTile]) - { - xMax += info.x14_tileSize; - ++nextXTile; - } - } - } - } - break; - } - case CFluidPlaneRender::NormalMode::NBT: - { - if (flagIs1 || !info.x30_gridFlags) - { - size_t start = vOut.size(); - vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f), zeus::CVector3f::skUp, - zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack); - vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f), zeus::CVector3f::skUp, - zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack); - vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CVector3f::skUp, - zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack); - vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CVector3f::skUp, - zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack); - CGraphics::DrawArray(start, 4); - } - else - { - int xTiles = (info.x0_xSubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1; - int yTiles = (info.x1_ySubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1; - int xTileStart = info.x28_tileX + info.x2e_tileY * info.x2a_gridDimX; - for (; yTiles>0 ; --yTiles, yMin += info.x14_tileSize, xTileStart += info.x2a_gridDimX) - { - xMax = xMin; - int nextXTile; - for (int curXTile=0 ; curXTile 0; + --curYTile, yMax += info.x14_tileSize, xTileStart += info.x2a_gridDimX) { + xMax = xMin; + int nextXTile; + for (int curXTile = 0; curXTile < xTiles; curXTile = nextXTile) { + if (!info.x30_gridFlags || info.x30_gridFlags[xTileStart + curXTile]) { + if (curYTile == yTiles || curYTile == 1 || curXTile == 0 || xTiles - 1 == curXTile) { + TriFanToStrip toStrip(vOut); + + toStrip.EmplaceVert( + zeus::CVector3f(xMax + 0.5f * info.x14_tileSize, yMax + 0.5f * info.x14_tileSize, 0.f), + zeus::CVector3f::skUp, zeus::CColor::skBlack); + + float tmp = xMax; + for (int v = 0; v < ((curYTile == 1) ? CFluidPlaneRender::numSubdivisionsInTile : 1); ++v) { + toStrip.EmplaceVert(zeus::CVector3f(tmp, yMax + info.x14_tileSize, 0.f), zeus::CVector3f::skUp, + zeus::CColor::skBlack); + tmp += info.x18_rippleResolution; + } + + tmp = yMax + info.x14_tileSize; + for (int v = 0; v < ((xTiles - 1 == curXTile) ? CFluidPlaneRender::numSubdivisionsInTile : 1); ++v) { + toStrip.EmplaceVert(zeus::CVector3f(xMax + info.x14_tileSize, tmp, 0.f), zeus::CVector3f::skUp, + zeus::CColor::skBlack); + tmp -= info.x18_rippleResolution; + } + + tmp = xMax + info.x14_tileSize; + for (int v = 0; v < ((curYTile == yTiles) ? CFluidPlaneRender::numSubdivisionsInTile : 1); ++v) { + toStrip.EmplaceVert(zeus::CVector3f(tmp, yMax, 0.f), zeus::CVector3f::skUp, zeus::CColor::skBlack); + tmp -= info.x18_rippleResolution; + } + + tmp = yMax; + for (int v = 0; v < ((curXTile == 0) ? CFluidPlaneRender::numSubdivisionsInTile : 1); ++v) { + toStrip.EmplaceVert(zeus::CVector3f(xMax, tmp, 0.f), zeus::CVector3f::skUp, zeus::CColor::skBlack); + tmp += info.x18_rippleResolution; + } + + toStrip.EmplaceVert(zeus::CVector3f(xMax, yMax + info.x14_tileSize, 0.f), zeus::CVector3f::skUp, + zeus::CColor::skBlack); + + toStrip.Draw(); + + nextXTile = curXTile + 1; + xMax += info.x14_tileSize; + } else { + nextXTile = curXTile + 1; + while (nextXTile < xTiles - 1 && (!info.x30_gridFlags || info.x30_gridFlags[xTileStart + nextXTile])) + ++nextXTile; + + size_t start = vOut.size(); + for (int v = 0; v < nextXTile - curXTile + 1; ++v) { + vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CVector3f::skUp, zeus::CColor::skBlack); + vOut.emplace_back(zeus::CVector3f(xMax, yMax + info.x14_tileSize, 0.f), zeus::CVector3f::skUp, + zeus::CColor::skBlack); + xMax += info.x14_tileSize; + } + CGraphics::DrawArray(start, vOut.size() - start); + + ++nextXTile; + if (nextXTile == xTiles) { + --nextXTile; + xMax -= info.x14_tileSize; + } + } + } else { + nextXTile = curXTile + 1; + xMax += info.x14_tileSize; + while (nextXTile < xTiles && !info.x30_gridFlags[xTileStart + nextXTile]) { + xMax += info.x14_tileSize; + ++nextXTile; + } + } + } + } + break; + } + case CFluidPlaneRender::NormalMode::NBT: { + if (flagIs1 || !info.x30_gridFlags) { + size_t start = vOut.size(); + vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f), zeus::CVector3f::skUp, zeus::CVector3f::skForward, + zeus::CVector3f::skRight, zeus::CColor::skBlack); + vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f), zeus::CVector3f::skUp, zeus::CVector3f::skForward, + zeus::CVector3f::skRight, zeus::CColor::skBlack); + vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CVector3f::skUp, zeus::CVector3f::skForward, + zeus::CVector3f::skRight, zeus::CColor::skBlack); + vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CVector3f::skUp, zeus::CVector3f::skForward, + zeus::CVector3f::skRight, zeus::CColor::skBlack); + CGraphics::DrawArray(start, 4); + } else { + int xTiles = (info.x0_xSubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1; + int yTiles = (info.x1_ySubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1; + int xTileStart = info.x28_tileX + info.x2e_tileY * info.x2a_gridDimX; + for (; yTiles > 0; --yTiles, yMin += info.x14_tileSize, xTileStart += info.x2a_gridDimX) { + xMax = xMin; + int nextXTile; + for (int curXTile = 0; curXTile < xTiles; curXTile = nextXTile) { + if (info.x30_gridFlags[xTileStart + curXTile]) { + nextXTile = curXTile + 1; + int tile = xTileStart + nextXTile; + while (nextXTile < xTiles && info.x30_gridFlags[tile]) { + ++nextXTile; + ++tile; + } + + size_t start = vOut.size(); + for (int v = 0; v < nextXTile - curXTile + 1; ++v) { + vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CVector3f::skUp, zeus::CVector3f::skForward, + zeus::CVector3f::skRight, zeus::CColor::skBlack); + vOut.emplace_back(zeus::CVector3f(xMax, yMin + info.x14_tileSize, 0.f), zeus::CVector3f::skUp, + zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack); + xMax += info.x14_tileSize; + } + CGraphics::DrawArray(start, vOut.size() - start); + } else { + nextXTile = curXTile + 1; + xMax += info.x14_tileSize; + int tile = xTileStart + nextXTile; + while (nextXTile < xTiles && !info.x30_gridFlags[tile]) { + xMax += info.x14_tileSize; + ++nextXTile; + ++tile; + } + } + } + } + } + break; + } + } + } else { + float curY = info.x4_localMin.y(); + for (int startYDiv = 1; startYDiv < info.x1_ySubdivs - 2; + startYDiv += CFluidPlaneRender::numSubdivisionsInTile, curY += info.x14_tileSize) + RenderStripWithRipples(curY, heights, flags, startYDiv, info, vOut, pvOut); + } } -} +} // namespace urde diff --git a/Runtime/World/CFluidPlane.hpp b/Runtime/World/CFluidPlane.hpp index ea62c09e1..3676c1e55 100644 --- a/Runtime/World/CFluidPlane.hpp +++ b/Runtime/World/CFluidPlane.hpp @@ -8,179 +8,162 @@ #include "zeus/CFrustum.hpp" #include "Graphics/Shaders/CFluidPlaneShader.hpp" -namespace urde -{ +namespace urde { class CFluidUVMotion; class CRippleManager; class CScriptWater; class CStateManager; class CRipple; -class CFluidPlaneRender -{ +class CFluidPlaneRender { public: - enum class NormalMode - { - None, - NoNormals, - Normals, - NBT - }; + enum class NormalMode { None, NoNormals, Normals, NBT }; - static int numTilesInHField; - static int numSubdivisionsInTile; - static int numSubdivisionsInHField; + static int numTilesInHField; + static int numSubdivisionsInTile; + static int numSubdivisionsInHField; - struct SPatchInfo - { - u8 x0_xSubdivs, x1_ySubdivs; - zeus::CVector2f x4_localMin, xc_globalMin; - float x14_tileSize; - float x18_rippleResolution; - float x1c_tileHypRadius; - float x20_ooTileSize; - float x24_ooRippleResolution; - u16 x28_tileX; - u16 x2a_gridDimX; - u16 x2c_gridDimY; - u16 x2e_tileY; - const bool* x30_gridFlags; - u8 x34_redShift; - u8 x35_greenShift; - u8 x36_blueShift; - NormalMode x37_normalMode; - float x38_wavecapIntensityScale; - public: - SPatchInfo(const zeus::CVector3f& localMin, const zeus::CVector3f& localMax, const zeus::CVector3f& pos, - float rippleResolution, float tileSize, float wavecapIntensityScale, int numSubdivisionsInHField, - NormalMode normalMode, int redShift, int greenShift, int blueShift, u32 tileX, u32 gridDimX, - u32 gridDimY, u32 tileY, const bool* gridFlags) - { - x0_xSubdivs = std::min(s16((localMax.x() - localMin.x()) / rippleResolution + 1.f - FLT_EPSILON) + 2, - numSubdivisionsInHField + 2); - x1_ySubdivs = std::min(s16((localMax.y() - localMin.y()) / rippleResolution + 1.f - FLT_EPSILON) + 2, - numSubdivisionsInHField + 2); - float tileHypRadius = tileSize * tileSize * 2 * 0.25f; - x4_localMin = localMin.toVec2f(); - xc_globalMin = x4_localMin + pos.toVec2f(); - x14_tileSize = tileSize; - x18_rippleResolution = rippleResolution; - if (tileHypRadius != 0.f) - tileHypRadius = std::sqrt(tileHypRadius); - x1c_tileHypRadius = tileHypRadius; - x20_ooTileSize = 1.f / x14_tileSize; - x24_ooRippleResolution = 1.f / x18_rippleResolution; - x28_tileX = u16(tileX); - x2a_gridDimX = u16(gridDimX); - x2c_gridDimY = u16(gridDimY); - x2e_tileY = u16(tileY); - x30_gridFlags = gridFlags; - x34_redShift = u8(redShift); - x35_greenShift = u8(greenShift); - x36_blueShift = u8(blueShift); - x37_normalMode = normalMode; - x38_wavecapIntensityScale = wavecapIntensityScale; - } - }; + struct SPatchInfo { + u8 x0_xSubdivs, x1_ySubdivs; + zeus::CVector2f x4_localMin, xc_globalMin; + float x14_tileSize; + float x18_rippleResolution; + float x1c_tileHypRadius; + float x20_ooTileSize; + float x24_ooRippleResolution; + u16 x28_tileX; + u16 x2a_gridDimX; + u16 x2c_gridDimY; + u16 x2e_tileY; + const bool* x30_gridFlags; + u8 x34_redShift; + u8 x35_greenShift; + u8 x36_blueShift; + NormalMode x37_normalMode; + float x38_wavecapIntensityScale; - struct SRippleInfo - { - const CRipple& x0_ripple; - int x4_fromX; - int x8_toX; - int xc_fromY; - int x10_toY; - int x14_gfromX; - int x18_gtoX; - int x1c_gfromY; - int x20_gtoY; - public: - SRippleInfo(const CRipple& ripple, int fromX, int toX, int fromY, int toY) - : x0_ripple(ripple), x14_gfromX(fromX), x18_gtoX(toX), x1c_gfromY(fromY), x20_gtoY(toY) {} - }; + public: + SPatchInfo(const zeus::CVector3f& localMin, const zeus::CVector3f& localMax, const zeus::CVector3f& pos, + float rippleResolution, float tileSize, float wavecapIntensityScale, int numSubdivisionsInHField, + NormalMode normalMode, int redShift, int greenShift, int blueShift, u32 tileX, u32 gridDimX, + u32 gridDimY, u32 tileY, const bool* gridFlags) { + x0_xSubdivs = std::min(s16((localMax.x() - localMin.x()) / rippleResolution + 1.f - FLT_EPSILON) + 2, + numSubdivisionsInHField + 2); + x1_ySubdivs = std::min(s16((localMax.y() - localMin.y()) / rippleResolution + 1.f - FLT_EPSILON) + 2, + numSubdivisionsInHField + 2); + float tileHypRadius = tileSize * tileSize * 2 * 0.25f; + x4_localMin = localMin.toVec2f(); + xc_globalMin = x4_localMin + pos.toVec2f(); + x14_tileSize = tileSize; + x18_rippleResolution = rippleResolution; + if (tileHypRadius != 0.f) + tileHypRadius = std::sqrt(tileHypRadius); + x1c_tileHypRadius = tileHypRadius; + x20_ooTileSize = 1.f / x14_tileSize; + x24_ooRippleResolution = 1.f / x18_rippleResolution; + x28_tileX = u16(tileX); + x2a_gridDimX = u16(gridDimX); + x2c_gridDimY = u16(gridDimY); + x2e_tileY = u16(tileY); + x30_gridFlags = gridFlags; + x34_redShift = u8(redShift); + x35_greenShift = u8(greenShift); + x36_blueShift = u8(blueShift); + x37_normalMode = normalMode; + x38_wavecapIntensityScale = wavecapIntensityScale; + } + }; - struct SHFieldSample - { - float height; - s8 nx; - s8 ny; - s8 nz; - u8 wavecapIntensity; + struct SRippleInfo { + const CRipple& x0_ripple; + int x4_fromX; + int x8_toX; + int xc_fromY; + int x10_toY; + int x14_gfromX; + int x18_gtoX; + int x1c_gfromY; + int x20_gtoY; - zeus::CVector3f MakeNormal() const { return zeus::CVector3f{nx / 63.f, ny / 63.f, nz / 63.f}.normalized(); } - zeus::CVector3f MakeBinormal() const { return zeus::CVector3f{nx / 63.f, nz / 63.f, -ny / 63.f}.normalized(); } - zeus::CVector3f MakeTangent() const { return zeus::CVector3f{nz / 63.f, ny / 63.f, -nx / 63.f}.normalized(); } - zeus::CColor MakeColor(const CFluidPlaneRender::SPatchInfo& info) const - { - return {(wavecapIntensity >> info.x34_redShift) / 255.f, - (wavecapIntensity >> info.x35_greenShift) / 255.f, - (wavecapIntensity >> info.x36_blueShift) / 255.f}; - } - }; + public: + SRippleInfo(const CRipple& ripple, int fromX, int toX, int fromY, int toY) + : x0_ripple(ripple), x14_gfromX(fromX), x18_gtoX(toX), x1c_gfromY(fromY), x20_gtoY(toY) {} + }; + + struct SHFieldSample { + float height; + s8 nx; + s8 ny; + s8 nz; + u8 wavecapIntensity; + + zeus::CVector3f MakeNormal() const { return zeus::CVector3f{nx / 63.f, ny / 63.f, nz / 63.f}.normalized(); } + zeus::CVector3f MakeBinormal() const { return zeus::CVector3f{nx / 63.f, nz / 63.f, -ny / 63.f}.normalized(); } + zeus::CVector3f MakeTangent() const { return zeus::CVector3f{nz / 63.f, ny / 63.f, -nx / 63.f}.normalized(); } + zeus::CColor MakeColor(const CFluidPlaneRender::SPatchInfo& info) const { + return {(wavecapIntensity >> info.x34_redShift) / 255.f, (wavecapIntensity >> info.x35_greenShift) / 255.f, + (wavecapIntensity >> info.x36_blueShift) / 255.f}; + } + }; }; -class CFluidPlane -{ +class CFluidPlane { protected: - CAssetId x4_texPattern1Id; - CAssetId x8_texPattern2Id; - CAssetId xc_texColorId; - TLockedToken x10_texPattern1; - TLockedToken x20_texPattern2; - TLockedToken x30_texColor; - float x40_alpha; - EFluidType x44_fluidType; - float x48_rippleIntensity; - CFluidUVMotion x4c_uvMotion; + CAssetId x4_texPattern1Id; + CAssetId x8_texPattern2Id; + CAssetId xc_texColorId; + TLockedToken x10_texPattern1; + TLockedToken x20_texPattern2; + TLockedToken x30_texColor; + float x40_alpha; + EFluidType x44_fluidType; + float x48_rippleIntensity; + CFluidUVMotion x4c_uvMotion; - mutable std::vector m_verts; - mutable std::vector m_pVerts; - mutable std::experimental::optional m_shader; + mutable std::vector m_verts; + mutable std::vector m_pVerts; + mutable std::experimental::optional m_shader; - float ProjectRippleVelocity(float baseI, float velDot) const; - float CalculateRippleIntensity(float baseI) const; + float ProjectRippleVelocity(float baseI, float velDot) const; + float CalculateRippleIntensity(float baseI) const; - virtual void RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], - const u8 (&flags)[9][9], int startYDiv, - const CFluidPlaneRender::SPatchInfo& info, - std::vector& vOut, - std::vector& pvOut) const; - void RenderPatch(const CFluidPlaneRender::SPatchInfo& info, - const CFluidPlaneRender::SHFieldSample (&heights)[46][46], - const u8 (&flags)[9][9], bool noRipples, bool flagIs1, - std::vector& vOut, - std::vector& pvOut) const; + virtual void RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], + const u8 (&flags)[9][9], int startYDiv, const CFluidPlaneRender::SPatchInfo& info, + std::vector& vOut, + std::vector& pvOut) const; + void RenderPatch(const CFluidPlaneRender::SPatchInfo& info, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], + const u8 (&flags)[9][9], bool noRipples, bool flagIs1, std::vector& vOut, + std::vector& pvOut) const; public: - virtual ~CFluidPlane() = default; - CFluidPlane(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, float alpha, - EFluidType fluidType, float rippleIntensity, const CFluidUVMotion& motion); + virtual ~CFluidPlane() = default; + CFluidPlane(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, float alpha, EFluidType fluidType, + float rippleIntensity, const CFluidUVMotion& motion); - // Called by CPlayer, CMorphBall, CWeapon, CPuddleSpore, CMagdolite - virtual void AddRipple(float mag, TUniqueId rippler, const zeus::CVector3f& center, - CScriptWater& water, CStateManager& mgr); + // Called by CPlayer, CMorphBall, CWeapon, CPuddleSpore, CMagdolite + virtual void AddRipple(float mag, TUniqueId rippler, const zeus::CVector3f& center, CScriptWater& water, + CStateManager& mgr); - // Called by CAi - virtual void AddRipple(float intensity, TUniqueId rippler, const zeus::CVector3f& center, - const zeus::CVector3f& velocity, const CScriptWater& water, CStateManager& mgr, - const zeus::CVector3f& upVec); + // Called by CAi + virtual void AddRipple(float intensity, TUniqueId rippler, const zeus::CVector3f& center, + const zeus::CVector3f& velocity, const CScriptWater& water, CStateManager& mgr, + const zeus::CVector3f& upVec); - virtual void AddRipple(const CRipple& ripple, const CScriptWater& water, CStateManager& mgr); + virtual void AddRipple(const CRipple& ripple, const CScriptWater& water, CStateManager& mgr); - virtual void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, - const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum, - const std::experimental::optional& rippleManager, TUniqueId waterId, - const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const {} + virtual void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, + const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum, + const std::experimental::optional& rippleManager, TUniqueId waterId, + const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const {} - float GetAlpha() const { return x40_alpha; } - EFluidType GetFluidType() const { return x44_fluidType; } - const CFluidUVMotion& GetUVMotion() const { return x4c_uvMotion; } - const CTexture& GetColorTexture() const { return *x30_texColor; } - bool HasColorTexture() const { return x30_texColor.operator bool(); } - const CTexture& GetTexturePattern1() const { return *x10_texPattern1; } - bool HasTexturePattern1() const { return x10_texPattern1.operator bool(); } - const CTexture& GetTexturePattern2() const { return *x20_texPattern2; } - bool HasTexturePattern2() const { return x20_texPattern2.operator bool(); } + float GetAlpha() const { return x40_alpha; } + EFluidType GetFluidType() const { return x44_fluidType; } + const CFluidUVMotion& GetUVMotion() const { return x4c_uvMotion; } + const CTexture& GetColorTexture() const { return *x30_texColor; } + bool HasColorTexture() const { return x30_texColor.operator bool(); } + const CTexture& GetTexturePattern1() const { return *x10_texPattern1; } + bool HasTexturePattern1() const { return x10_texPattern1.operator bool(); } + const CTexture& GetTexturePattern2() const { return *x20_texPattern2; } + bool HasTexturePattern2() const { return x20_texPattern2.operator bool(); } }; -} - +} // namespace urde diff --git a/Runtime/World/CFluidPlaneCPU.cpp b/Runtime/World/CFluidPlaneCPU.cpp index b4101e410..4e25de38d 100644 --- a/Runtime/World/CFluidPlaneCPU.cpp +++ b/Runtime/World/CFluidPlaneCPU.cpp @@ -10,37 +10,40 @@ #define kTableSize 2048 -namespace urde -{ -CFluidPlaneCPU::CTurbulence::CTurbulence(float speed, float distance, float freqMax, float freqMin, - float phaseMax, float phaseMin, float amplitudeMax, float amplitudeMin) -: x0_speed(speed), x4_distance(distance), x8_freqMax(freqMax), xc_freqMin(freqMin), - x10_phaseMax(phaseMax), x14_phaseMin(phaseMin), x18_amplitudeMax(amplitudeMax), x1c_amplitudeMin(amplitudeMin), - x2c_ooTurbSpeed(1.f / x0_speed), x30_ooTurbDistance(1.f / x4_distance) -{ - if (x18_amplitudeMax != 0.f || x1c_amplitudeMin != 0.f) - { - x24_tableCount = kTableSize; - x28_heightSelPitch = x24_tableCount; - x20_table.reset(new float[x24_tableCount]); - float anglePitch = 2.f * M_PIF / x28_heightSelPitch; - float freqConstant = 0.5f * (x8_freqMax + xc_freqMin); - float freqLinear = 0.5f * (x8_freqMax - xc_freqMin); - float phaseConstant = 0.5f * (x10_phaseMax + x14_phaseMin); - float phaseLinear = 0.5f * (x10_phaseMax - x14_phaseMin); - float amplitudeConstant = 0.5f * (x18_amplitudeMax + x1c_amplitudeMin); - float amplitudeLinear = 0.5f * (x18_amplitudeMax - x1c_amplitudeMin); +namespace urde { +CFluidPlaneCPU::CTurbulence::CTurbulence(float speed, float distance, float freqMax, float freqMin, float phaseMax, + float phaseMin, float amplitudeMax, float amplitudeMin) +: x0_speed(speed) +, x4_distance(distance) +, x8_freqMax(freqMax) +, xc_freqMin(freqMin) +, x10_phaseMax(phaseMax) +, x14_phaseMin(phaseMin) +, x18_amplitudeMax(amplitudeMax) +, x1c_amplitudeMin(amplitudeMin) +, x2c_ooTurbSpeed(1.f / x0_speed) +, x30_ooTurbDistance(1.f / x4_distance) { + if (x18_amplitudeMax != 0.f || x1c_amplitudeMin != 0.f) { + x24_tableCount = kTableSize; + x28_heightSelPitch = x24_tableCount; + x20_table.reset(new float[x24_tableCount]); + float anglePitch = 2.f * M_PIF / x28_heightSelPitch; + float freqConstant = 0.5f * (x8_freqMax + xc_freqMin); + float freqLinear = 0.5f * (x8_freqMax - xc_freqMin); + float phaseConstant = 0.5f * (x10_phaseMax + x14_phaseMin); + float phaseLinear = 0.5f * (x10_phaseMax - x14_phaseMin); + float amplitudeConstant = 0.5f * (x18_amplitudeMax + x1c_amplitudeMin); + float amplitudeLinear = 0.5f * (x18_amplitudeMax - x1c_amplitudeMin); - float curAng = 0.f; - for (int i=0 ; iGetResourceTypeById(xa0_texIdBumpMap) == FOURCC('TXTR')) - xb0_bumpMap = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa0_texIdBumpMap}); - if (g_ResFactory->GetResourceTypeById(xa4_texIdEnvMap) == FOURCC('TXTR')) - xc0_envMap = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa4_texIdEnvMap}); - if (g_ResFactory->GetResourceTypeById(xa8_texIdEnvBumpMap) == FOURCC('TXTR')) - xd0_envBumpMap = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa8_texIdEnvBumpMap}); - if (g_ResFactory->GetResourceTypeById(xac_texId4) == FOURCC('TXTR')) - xe0_lightmap = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xac_texId4}); +: CFluidPlane(texPattern1, texPattern2, texColor, alpha, fluidType, rippleIntensity, mot) +, xa0_texIdBumpMap(bumpMap) +, xa4_texIdEnvMap(envMap) +, xa8_texIdEnvBumpMap(envBumpMap) +, xac_texId4(lightMap) +, xf0_bumpLightDir(bumpLightDir) +, xfc_bumpScale(bumpScale) +, x100_tileSize(tileSize) +, x104_tileSubdivisions(tileSubdivisions & ~0x1) +, x108_rippleResolution(x100_tileSize / float(x104_tileSubdivisions)) +, x10c_specularMin(specularMin) +, x110_specularMax(specularMax) +, x114_reflectionBlend(reflectionBlend) +, x118_reflectionSize(reflectionSize) +, x11c_unitsPerLightmapTexel(unitsPerLightmapTexel) +, x120_turbulence(turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax, turbPhaseMin, turbAmplitudeMax, + turbAmplitudeMin) +, m_maxVertCount(maxVertCount) { + if (g_ResFactory->GetResourceTypeById(xa0_texIdBumpMap) == FOURCC('TXTR')) + xb0_bumpMap = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa0_texIdBumpMap}); + if (g_ResFactory->GetResourceTypeById(xa4_texIdEnvMap) == FOURCC('TXTR')) + xc0_envMap = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa4_texIdEnvMap}); + if (g_ResFactory->GetResourceTypeById(xa8_texIdEnvBumpMap) == FOURCC('TXTR')) + xd0_envBumpMap = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa8_texIdEnvBumpMap}); + if (g_ResFactory->GetResourceTypeById(xac_texId4) == FOURCC('TXTR')) + xe0_lightmap = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xac_texId4}); } -void CFluidPlaneCPU::CreateRipple(const CRipple& ripple, CStateManager& mgr) -{ - -} +void CFluidPlaneCPU::CreateRipple(const CRipple& ripple, CStateManager& mgr) {} void CFluidPlaneCPU::CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf, - const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const -{ - int width = GetLightMap().GetWidth(); - int height = GetLightMap().GetHeight(); + const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const { + int width = GetLightMap().GetWidth(); + int height = GetLightMap().GetHeight(); - zeus::CTransform toLocal = areaXf.getRotation().inverse(); - zeus::CAABox areaLocalAABB = aabb.getTransformedAABox(toLocal); - float f26 = (areaLocalAABB.max.x() - areaLocalAABB.min.x()) / (width * x11c_unitsPerLightmapTexel); - float f25 = (areaLocalAABB.max.y() - areaLocalAABB.min.y()) / (height * x11c_unitsPerLightmapTexel); - float f24 = (1.f + std::fmod(areaLocalAABB.min.x() + xf.origin.x(), x11c_unitsPerLightmapTexel)) / width; - float f23 = (2.f - std::fmod(areaLocalAABB.max.x() + xf.origin.x(), x11c_unitsPerLightmapTexel)) / width; - float f29 = (1.f + std::fmod(areaLocalAABB.min.y() + xf.origin.y(), x11c_unitsPerLightmapTexel)) / height; - float f6 = (2.f - std::fmod(areaLocalAABB.max.y() + xf.origin.y(), x11c_unitsPerLightmapTexel)) / height; + zeus::CTransform toLocal = areaXf.getRotation().inverse(); + zeus::CAABox areaLocalAABB = aabb.getTransformedAABox(toLocal); + float f26 = (areaLocalAABB.max.x() - areaLocalAABB.min.x()) / (width * x11c_unitsPerLightmapTexel); + float f25 = (areaLocalAABB.max.y() - areaLocalAABB.min.y()) / (height * x11c_unitsPerLightmapTexel); + float f24 = (1.f + std::fmod(areaLocalAABB.min.x() + xf.origin.x(), x11c_unitsPerLightmapTexel)) / width; + float f23 = (2.f - std::fmod(areaLocalAABB.max.x() + xf.origin.x(), x11c_unitsPerLightmapTexel)) / width; + float f29 = (1.f + std::fmod(areaLocalAABB.min.y() + xf.origin.y(), x11c_unitsPerLightmapTexel)) / height; + float f6 = (2.f - std::fmod(areaLocalAABB.max.y() + xf.origin.y(), x11c_unitsPerLightmapTexel)) / height; - float scaleX = (f26 - f24 - f23) / (areaLocalAABB.max.x() - areaLocalAABB.min.x()); - float scaleY = -(f25 - f29 - f6) / (areaLocalAABB.max.y() - areaLocalAABB.min.y()); - float offX = f24 + f26 * -areaLocalAABB.min.x() / (areaLocalAABB.max.x() - areaLocalAABB.min.x()); - float offY = f25 * areaLocalAABB.min.y() / (areaLocalAABB.max.y() - areaLocalAABB.min.y()) - f6; - mtxOut = (zeus::CTransform(zeus::CMatrix3f(zeus::CVector3f(scaleX, scaleY, 0.f)), - zeus::CVector3f(offX, offY, 0.f)) * toLocal).toMatrix4f(); + float scaleX = (f26 - f24 - f23) / (areaLocalAABB.max.x() - areaLocalAABB.min.x()); + float scaleY = -(f25 - f29 - f6) / (areaLocalAABB.max.y() - areaLocalAABB.min.y()); + float offX = f24 + f26 * -areaLocalAABB.min.x() / (areaLocalAABB.max.x() - areaLocalAABB.min.x()); + float offY = f25 * areaLocalAABB.min.y() / (areaLocalAABB.max.y() - areaLocalAABB.min.y()) - f6; + mtxOut = (zeus::CTransform(zeus::CMatrix3f(zeus::CVector3f(scaleX, scaleY, 0.f)), zeus::CVector3f(offX, offY, 0.f)) * + toLocal) + .toMatrix4f(); } static bool sSineWaveInitialized = false; static float sGlobalSineWave[256] = {}; -static const float* InitializeSineWave() -{ - if (sSineWaveInitialized) - return sGlobalSineWave; - for (int i=0 ; i<256 ; ++i) - sGlobalSineWave[i] = std::sin(2.f * M_PIF * (i / 256.f)); - sSineWaveInitialized = true; +static const float* InitializeSineWave() { + if (sSineWaveInitialized) return sGlobalSineWave; + for (int i = 0; i < 256; ++i) + sGlobalSineWave[i] = std::sin(2.f * M_PIF * (i / 256.f)); + sSineWaveInitialized = true; + return sGlobalSineWave; } #define kEnableWaterBumpMaps true -CFluidPlaneShader::RenderSetupInfo -CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::CTransform& xf, - const zeus::CTransform& areaXf, const zeus::CAABox& aabb, const CScriptWater* water) const -{ - CFluidPlaneShader::RenderSetupInfo out; +CFluidPlaneShader::RenderSetupInfo CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, + const zeus::CTransform& xf, + const zeus::CTransform& areaXf, const zeus::CAABox& aabb, + const CScriptWater* water) const { + CFluidPlaneShader::RenderSetupInfo out; - float uvT = mgr.GetFluidPlaneManager()->GetUVT(); - bool hasBumpMap = HasBumpMap() && kEnableWaterBumpMaps; - bool doubleLightmapBlend = false; - bool hasEnvMap = mgr.GetCameraManager()->GetFluidCounter() == 0 && HasEnvMap(); - bool hasEnvBumpMap = HasEnvBumpMap(); - InitializeSineWave(); - CGraphics::SetModelMatrix(xf); + float uvT = mgr.GetFluidPlaneManager()->GetUVT(); + bool hasBumpMap = HasBumpMap() && kEnableWaterBumpMaps; + bool doubleLightmapBlend = false; + bool hasEnvMap = mgr.GetCameraManager()->GetFluidCounter() == 0 && HasEnvMap(); + bool hasEnvBumpMap = HasEnvBumpMap(); + InitializeSineWave(); + CGraphics::SetModelMatrix(xf); - if (hasBumpMap) - { - // Build 50% grey directional light with xf0_bumpLightDir and load into LIGHT_3 - // Light 3 in channel 1 - // Vertex colors in channel 0 - out.lights.resize(4); - out.lights[3] = CLight::BuildDirectional(xf0_bumpLightDir, zeus::CColor::skGrey); - } + if (hasBumpMap) { + // Build 50% grey directional light with xf0_bumpLightDir and load into LIGHT_3 + // Light 3 in channel 1 + // Vertex colors in channel 0 + out.lights.resize(4); + out.lights[3] = CLight::BuildDirectional(xf0_bumpLightDir, zeus::CColor::skGrey); + } else { + // Normal light mask in channel 1 + // Vertex colors in channel 0 + out.lights = water->GetActorLights()->BuildLightVector(); + } + + int curTex = 3; + int bumpMapId; + int envMapId; + int envBumpMapId; + int lightmapId; + + if (hasBumpMap) { + // Load into next + bumpMapId = curTex++; + } + + if (hasEnvMap) { + // Load into next + envMapId = curTex++; + } + + if (hasEnvBumpMap) { + // Load into next + envBumpMapId = curTex++; + } + + float fluidUVs[3][2]; + x4c_uvMotion.CalculateFluidTextureOffset(uvT, fluidUVs); + + out.texMtxs[0][0][0] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); + out.texMtxs[0][1][1] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); + out.texMtxs[0][3][0] = fluidUVs[1][0]; + out.texMtxs[0][3][1] = fluidUVs[1][1]; + + out.texMtxs[1][0][0] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale(); + out.texMtxs[1][1][1] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale(); + out.texMtxs[1][3][0] = fluidUVs[2][0]; + out.texMtxs[1][3][1] = fluidUVs[2][1]; + + out.texMtxs[2][0][0] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); + out.texMtxs[2][1][1] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); + out.texMtxs[2][3][0] = fluidUVs[0][0]; + out.texMtxs[2][3][1] = fluidUVs[0][1]; + + // Load normal mtx 0 with + out.normMtx = (zeus::CTransform::Scale(xfc_bumpScale) * CGraphics::g_ViewMatrix.getRotation().inverse()).toMatrix4f(); + + // Setup TCGs + int nextTexMtx = 3; + + if (hasEnvBumpMap) { + float pttScale; + if (hasEnvMap) + pttScale = 0.5f * (1.f - x118_reflectionSize); else - { - // Normal light mask in channel 1 - // Vertex colors in channel 0 - out.lights = water->GetActorLights()->BuildLightVector(); - } + pttScale = g_tweakGame->GetFluidEnvBumpScale() * x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); - int curTex = 3; - int bumpMapId; - int envMapId; - int envBumpMapId; - int lightmapId; + // Load GX_TEXMTX3 with identity + zeus::CMatrix4f& texMtx = out.texMtxs[nextTexMtx++]; + texMtx[0][0] = pttScale; + texMtx[1][1] = pttScale; + texMtx[3][0] = 0.5f; + texMtx[3][1] = 0.5f; + // Load GX_PTTEXMTX0 with scale of pttScale + // Next: GX_TG_MTX2x4 GX_TG_NRM, GX_TEXMTX3, true, GX_PTTEXMTX0 - if (hasBumpMap) - { - // Load into next - bumpMapId = curTex++; - } + out.indScale = 0.5f * (hasEnvMap ? x118_reflectionSize : 1.f); + // Load ind mtx with scale of (indScale, -indScale) + // Load envBumpMap into ind stage 0 with previous TCG + } - if (hasEnvMap) - { - // Load into next - envMapId = curTex++; - } + if (hasEnvMap) { + float scale = std::max(aabb.max.x() - aabb.min.x(), aabb.max.y() - aabb.min.y()); + zeus::CMatrix4f& texMtx = out.texMtxs[nextTexMtx++]; + texMtx[0][0] = 1.f / scale; + texMtx[1][1] = 1.f / scale; + zeus::CVector3f center = aabb.center(); + texMtx[3][0] = 0.5f + -center.x() / scale; + texMtx[3][1] = 0.5f + -center.y() / scale; + // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY + } - if (hasEnvBumpMap) - { - // Load into next - envBumpMapId = curTex++; - } - - float fluidUVs[3][2]; - x4c_uvMotion.CalculateFluidTextureOffset(uvT, fluidUVs); - - out.texMtxs[0][0][0] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); - out.texMtxs[0][1][1] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); - out.texMtxs[0][3][0] = fluidUVs[1][0]; - out.texMtxs[0][3][1] = fluidUVs[1][1]; - - out.texMtxs[1][0][0] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale(); - out.texMtxs[1][1][1] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale(); - out.texMtxs[1][3][0] = fluidUVs[2][0]; - out.texMtxs[1][3][1] = fluidUVs[2][1]; - - out.texMtxs[2][0][0] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); - out.texMtxs[2][1][1] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); - out.texMtxs[2][3][0] = fluidUVs[0][0]; - out.texMtxs[2][3][1] = fluidUVs[0][1]; - - // Load normal mtx 0 with - out.normMtx = - (zeus::CTransform::Scale(xfc_bumpScale) * CGraphics::g_ViewMatrix.getRotation().inverse()).toMatrix4f(); - - // Setup TCGs - int nextTexMtx = 3; - - if (hasEnvBumpMap) - { - float pttScale; - if (hasEnvMap) - pttScale = 0.5f * (1.f - x118_reflectionSize); - else - pttScale = g_tweakGame->GetFluidEnvBumpScale() * x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); - - // Load GX_TEXMTX3 with identity - zeus::CMatrix4f& texMtx = out.texMtxs[nextTexMtx++]; - texMtx[0][0] = pttScale; - texMtx[1][1] = pttScale; - texMtx[3][0] = 0.5f; - texMtx[3][1] = 0.5f; - // Load GX_PTTEXMTX0 with scale of pttScale - // Next: GX_TG_MTX2x4 GX_TG_NRM, GX_TEXMTX3, true, GX_PTTEXMTX0 - - out.indScale = 0.5f * (hasEnvMap ? x118_reflectionSize : 1.f); - // Load ind mtx with scale of (indScale, -indScale) - // Load envBumpMap into ind stage 0 with previous TCG - } - - if (hasEnvMap) - { - float scale = std::max(aabb.max.x() - aabb.min.x(), aabb.max.y() - aabb.min.y()); - zeus::CMatrix4f& texMtx = out.texMtxs[nextTexMtx++]; - texMtx[0][0] = 1.f / scale; - texMtx[1][1] = 1.f / scale; - zeus::CVector3f center = aabb.center(); - texMtx[3][0] = 0.5f + -center.x() / scale; - texMtx[3][1] = 0.5f + -center.y() / scale; + if (HasLightMap()) { + float lowLightBlend = 1.f; + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()); + float lightLevel = area->GetPostConstructed()->x1128_worldLightingLevel; + const CScriptWater* nextWater = water->GetNextConnectedWater(mgr); + if (std::fabs(water->GetMorphFactor()) < 0.00001f || !nextWater || !nextWater->GetFluidPlane().HasLightMap()) { + lightmapId = curTex; + // Load lightmap + CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); + // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY + } else if (nextWater && nextWater->GetFluidPlane().HasLightMap()) { + if (std::fabs(water->GetMorphFactor() - 1.f) < 0.00001f) { + lightmapId = curTex; + // Load lightmap + CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY + } else { + lightmapId = curTex; + // Load lightmap + CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); + // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY + // Load lightmap + CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); + // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY + + float lum = lightLevel * water->GetMorphFactor(); + out.kColors[3] = zeus::CColor(lum, 1.f); + lowLightBlend = (1.f - water->GetMorphFactor()) / (1.f - lum); + doubleLightmapBlend = true; + } } - if (HasLightMap()) - { - float lowLightBlend = 1.f; - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()); - float lightLevel = area->GetPostConstructed()->x1128_worldLightingLevel; - const CScriptWater* nextWater = water->GetNextConnectedWater(mgr); - if (std::fabs(water->GetMorphFactor()) < 0.00001f || !nextWater || - !nextWater->GetFluidPlane().HasLightMap()) - { - lightmapId = curTex; - // Load lightmap - CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); - // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY - } - else if (nextWater && nextWater->GetFluidPlane().HasLightMap()) - { - if (std::fabs(water->GetMorphFactor() - 1.f) < 0.00001f) - { - lightmapId = curTex; - // Load lightmap - CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); - // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY - } - else - { - lightmapId = curTex; - // Load lightmap - CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); - // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY - // Load lightmap - CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); - // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY + out.kColors[2] = zeus::CColor(lowLightBlend * lightLevel, 1.f); + } - float lum = lightLevel * water->GetMorphFactor(); - out.kColors[3] = zeus::CColor(lum, 1.f); - lowLightBlend = (1.f - water->GetMorphFactor()) / (1.f - lum); - doubleLightmapBlend = true; - } - } + float waterPlaneOrthoDot = xf.transposeRotate(zeus::CVector3f::skUp) + .dot(CGraphics::g_ViewMatrix.inverse().transposeRotate(zeus::CVector3f::skForward)); + if (waterPlaneOrthoDot < 0.f) + waterPlaneOrthoDot = -waterPlaneOrthoDot; - out.kColors[2] = zeus::CColor(lowLightBlend * lightLevel, 1.f); - } + out.kColors[0] = + zeus::CColor((1.f - waterPlaneOrthoDot) * (x110_specularMax - x10c_specularMin) + x10c_specularMin, alpha); + out.kColors[1] = zeus::CColor(x114_reflectionBlend, 1.f); - float waterPlaneOrthoDot = xf.transposeRotate(zeus::CVector3f::skUp). - dot(CGraphics::g_ViewMatrix.inverse().transposeRotate(zeus::CVector3f::skForward)); - if (waterPlaneOrthoDot < 0.f) - waterPlaneOrthoDot = -waterPlaneOrthoDot; + if (!m_shader || m_cachedDoubleLightmapBlend != doubleLightmapBlend || + m_cachedAdditive != (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot)) { + m_cachedDoubleLightmapBlend = doubleLightmapBlend; + m_cachedAdditive = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot; + m_shader.emplace(x44_fluidType, x10_texPattern1, x20_texPattern2, x30_texColor, xb0_bumpMap, xc0_envMap, + xd0_envBumpMap, xe0_lightmap, + m_tessellation ? CFluidPlaneManager::RippleMapTex : boo::ObjToken{}, + m_cachedDoubleLightmapBlend, m_cachedAdditive, m_maxVertCount); + } - out.kColors[0] = - zeus::CColor((1.f - waterPlaneOrthoDot) * (x110_specularMax - x10c_specularMin) + x10c_specularMin, alpha); - out.kColors[1] = zeus::CColor(x114_reflectionBlend, 1.f); - - if (!m_shader || m_cachedDoubleLightmapBlend != doubleLightmapBlend || - m_cachedAdditive != (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot)) - { - m_cachedDoubleLightmapBlend = doubleLightmapBlend; - m_cachedAdditive = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot; - m_shader.emplace(x44_fluidType, - x10_texPattern1, x20_texPattern2, x30_texColor, xb0_bumpMap, xc0_envMap, - xd0_envBumpMap, xe0_lightmap, - m_tessellation ? CFluidPlaneManager::RippleMapTex : boo::ObjToken{}, - m_cachedDoubleLightmapBlend, m_cachedAdditive, m_maxVertCount); - } - - return out; + return out; } int CFluidPlaneRender::numTilesInHField; @@ -298,518 +285,455 @@ int CFluidPlaneRender::numSubdivisionsInTile; int CFluidPlaneRender::numSubdivisionsInHField; bool CFluidPlaneCPU::PrepareRipple(const CRipple& ripple, const CFluidPlaneRender::SPatchInfo& info, - CFluidPlaneRender::SRippleInfo& rippleOut) -{ - auto lifeIdx = int((1.f - (ripple.GetTimeFalloff() - ripple.GetTime()) / ripple.GetTimeFalloff()) * 64.f); - float dist = CFluidPlaneManager::RippleMaxs[lifeIdx] * (ripple.GetDistanceFalloff() / 256.f); - dist *= dist; - if (dist != 0) - dist = std::sqrt(dist); - dist = info.x24_ooRippleResolution * dist + 1.f; - float centerX = info.x24_ooRippleResolution * (ripple.GetCenter().x() - info.xc_globalMin.x()); - float centerY = info.x24_ooRippleResolution * (ripple.GetCenter().y() - info.xc_globalMin.y()); - int fromX = int(centerX - dist) - 1; - int toX = int(centerX + dist) + 1; - int fromY = int(centerY - dist) - 1; - int toY = int(centerY + dist) + 1; - rippleOut.x4_fromX = std::max(0, fromX); - rippleOut.x8_toX = std::min(int(info.x0_xSubdivs), toX); - rippleOut.xc_fromY = std::max(0, fromY); - rippleOut.x10_toY = std::min(int(info.x1_ySubdivs), toY); - rippleOut.x14_gfromX = std::max(rippleOut.x14_gfromX, fromX); - rippleOut.x18_gtoX = std::min(rippleOut.x18_gtoX, toX); - rippleOut.x1c_gfromY = std::max(rippleOut.x1c_gfromY, fromY); - rippleOut.x20_gtoY = std::min(rippleOut.x20_gtoY, toY); - return !(rippleOut.x14_gfromX > rippleOut.x18_gtoX || rippleOut.x1c_gfromY > rippleOut.x20_gtoY); + CFluidPlaneRender::SRippleInfo& rippleOut) { + auto lifeIdx = int((1.f - (ripple.GetTimeFalloff() - ripple.GetTime()) / ripple.GetTimeFalloff()) * 64.f); + float dist = CFluidPlaneManager::RippleMaxs[lifeIdx] * (ripple.GetDistanceFalloff() / 256.f); + dist *= dist; + if (dist != 0) + dist = std::sqrt(dist); + dist = info.x24_ooRippleResolution * dist + 1.f; + float centerX = info.x24_ooRippleResolution * (ripple.GetCenter().x() - info.xc_globalMin.x()); + float centerY = info.x24_ooRippleResolution * (ripple.GetCenter().y() - info.xc_globalMin.y()); + int fromX = int(centerX - dist) - 1; + int toX = int(centerX + dist) + 1; + int fromY = int(centerY - dist) - 1; + int toY = int(centerY + dist) + 1; + rippleOut.x4_fromX = std::max(0, fromX); + rippleOut.x8_toX = std::min(int(info.x0_xSubdivs), toX); + rippleOut.xc_fromY = std::max(0, fromY); + rippleOut.x10_toY = std::min(int(info.x1_ySubdivs), toY); + rippleOut.x14_gfromX = std::max(rippleOut.x14_gfromX, fromX); + rippleOut.x18_gtoX = std::min(rippleOut.x18_gtoX, toX); + rippleOut.x1c_gfromY = std::max(rippleOut.x1c_gfromY, fromY); + rippleOut.x20_gtoY = std::min(rippleOut.x20_gtoY, toY); + return !(rippleOut.x14_gfromX > rippleOut.x18_gtoX || rippleOut.x1c_gfromY > rippleOut.x20_gtoY); } void CFluidPlaneCPU::ApplyTurbulence(float t, CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9], const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info, - const zeus::CVector3f& areaCenter) const -{ - if (!HasTurbulence()) - { - memset(&heights, 0, sizeof(heights)); - return; - } + const zeus::CVector3f& areaCenter) const { + if (!HasTurbulence()) { + memset(&heights, 0, sizeof(heights)); + return; + } - float scaledT = t * GetOOTurbulenceSpeed(); - float curY = info.x4_localMin.y() - info.x18_rippleResolution - areaCenter.y(); - int xDivs = (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) / - CFluidPlaneRender::numSubdivisionsInTile * CFluidPlaneRender::numSubdivisionsInTile + 2; - int yDivs = (info.x1_ySubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) / - CFluidPlaneRender::numSubdivisionsInTile * CFluidPlaneRender::numSubdivisionsInTile + 2; - for (int i=0 ; i<=yDivs ; ++i) - { - float curYSq = curY * curY; - float curX = info.x4_localMin.x() - info.x18_rippleResolution - areaCenter.x(); - for (int j=0 ; j<=xDivs ; ++j) - { - float distFac = curX * curX + curYSq; - if (distFac != 0.f) - distFac = std::sqrt(distFac); - heights[i][j].height = - GetTurbulenceHeight(GetOOTurbulenceDistance() * distFac + scaledT); - curX += info.x18_rippleResolution; - } - curY += info.x18_rippleResolution; + float scaledT = t * GetOOTurbulenceSpeed(); + float curY = info.x4_localMin.y() - info.x18_rippleResolution - areaCenter.y(); + int xDivs = (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) / + CFluidPlaneRender::numSubdivisionsInTile * CFluidPlaneRender::numSubdivisionsInTile + + 2; + int yDivs = (info.x1_ySubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) / + CFluidPlaneRender::numSubdivisionsInTile * CFluidPlaneRender::numSubdivisionsInTile + + 2; + for (int i = 0; i <= yDivs; ++i) { + float curYSq = curY * curY; + float curX = info.x4_localMin.x() - info.x18_rippleResolution - areaCenter.x(); + for (int j = 0; j <= xDivs; ++j) { + float distFac = curX * curX + curYSq; + if (distFac != 0.f) + distFac = std::sqrt(distFac); + heights[i][j].height = GetTurbulenceHeight(GetOOTurbulenceDistance() * distFac + scaledT); + curX += info.x18_rippleResolution; } + curY += info.x18_rippleResolution; + } } void CFluidPlaneCPU::ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo, - CFluidPlaneRender::SHFieldSample (&heights)[46][46], - u8 (&flags)[9][9], const float sineWave[256], - const CFluidPlaneRender::SPatchInfo& info) const -{ - float lookupT = 256.f * (1.f - rippleInfo.x0_ripple.GetTime() * rippleInfo.x0_ripple.GetOOTimeFalloff() * - rippleInfo.x0_ripple.GetOOTimeFalloff()) * rippleInfo.x0_ripple.GetFrequency(); - auto lifeIdx = int(64.f * rippleInfo.x0_ripple.GetTime() * rippleInfo.x0_ripple.GetOOTimeFalloff()); - float distMul = rippleInfo.x0_ripple.GetDistanceFalloff() / 255.f; - float minDist = CFluidPlaneManager::RippleMins[lifeIdx] * distMul; - float minDistSq = minDist * minDist; - if (minDistSq != 0.f) - minDist = std::sqrt(minDistSq); - float maxDist = CFluidPlaneManager::RippleMaxs[lifeIdx] * distMul; - float maxDistSq = maxDist * maxDist; - if (maxDistSq != 0.f) - maxDist = std::sqrt(maxDistSq); - int fromY = (rippleInfo.x1c_gfromY + CFluidPlaneRender::numSubdivisionsInTile - 1) / - CFluidPlaneRender::numSubdivisionsInTile; - int fromX = (rippleInfo.x14_gfromX + CFluidPlaneRender::numSubdivisionsInTile - 1) / - CFluidPlaneRender::numSubdivisionsInTile; - int toY = (rippleInfo.x20_gtoY + CFluidPlaneRender::numSubdivisionsInTile - 1) / - CFluidPlaneRender::numSubdivisionsInTile; - int toX = (rippleInfo.x18_gtoX + CFluidPlaneRender::numSubdivisionsInTile - 1) / - CFluidPlaneRender::numSubdivisionsInTile; + CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], + const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info) const { + float lookupT = 256.f * + (1.f - rippleInfo.x0_ripple.GetTime() * rippleInfo.x0_ripple.GetOOTimeFalloff() * + rippleInfo.x0_ripple.GetOOTimeFalloff()) * + rippleInfo.x0_ripple.GetFrequency(); + auto lifeIdx = int(64.f * rippleInfo.x0_ripple.GetTime() * rippleInfo.x0_ripple.GetOOTimeFalloff()); + float distMul = rippleInfo.x0_ripple.GetDistanceFalloff() / 255.f; + float minDist = CFluidPlaneManager::RippleMins[lifeIdx] * distMul; + float minDistSq = minDist * minDist; + if (minDistSq != 0.f) + minDist = std::sqrt(minDistSq); + float maxDist = CFluidPlaneManager::RippleMaxs[lifeIdx] * distMul; + float maxDistSq = maxDist * maxDist; + if (maxDistSq != 0.f) + maxDist = std::sqrt(maxDistSq); + int fromY = + (rippleInfo.x1c_gfromY + CFluidPlaneRender::numSubdivisionsInTile - 1) / CFluidPlaneRender::numSubdivisionsInTile; + int fromX = + (rippleInfo.x14_gfromX + CFluidPlaneRender::numSubdivisionsInTile - 1) / CFluidPlaneRender::numSubdivisionsInTile; + int toY = + (rippleInfo.x20_gtoY + CFluidPlaneRender::numSubdivisionsInTile - 1) / CFluidPlaneRender::numSubdivisionsInTile; + int toX = + (rippleInfo.x18_gtoX + CFluidPlaneRender::numSubdivisionsInTile - 1) / CFluidPlaneRender::numSubdivisionsInTile; - float curY = rippleInfo.x0_ripple.GetCenter().y() - info.xc_globalMin.y() - - (0.5f * info.x14_tileSize + (fromY - 1) * info.x14_tileSize); - int curGridY = info.x2a_gridDimX * (info.x2e_tileY + fromY - 1); - int startGridX = (info.x28_tileX + fromX - 1); - int gridCells = info.x2a_gridDimX * info.x2c_gridDimY; - float distFalloff = 64.f * rippleInfo.x0_ripple.GetOODistanceFalloff(); - int curYDiv = rippleInfo.xc_fromY; + float curY = rippleInfo.x0_ripple.GetCenter().y() - info.xc_globalMin.y() - + (0.5f * info.x14_tileSize + (fromY - 1) * info.x14_tileSize); + int curGridY = info.x2a_gridDimX * (info.x2e_tileY + fromY - 1); + int startGridX = (info.x28_tileX + fromX - 1); + int gridCells = info.x2a_gridDimX * info.x2c_gridDimY; + float distFalloff = 64.f * rippleInfo.x0_ripple.GetOODistanceFalloff(); + int curYDiv = rippleInfo.xc_fromY; - for (int i=fromY ; i<=toY ; ++i, curY -= info.x14_tileSize) - { - int nextYDiv = (i+1) * CFluidPlaneRender::numSubdivisionsInTile; - float curYSq = curY * curY; - int curGridX = startGridX; - int curXDiv = rippleInfo.x4_fromX; - float curX = rippleInfo.x0_ripple.GetCenter().x() - info.xc_globalMin.x() - - (0.5f * info.x14_tileSize + (fromX - 1) * info.x14_tileSize); - for (int j=fromX ; j<=toX ; ++j, curX -= info.x14_tileSize, ++curGridX) - { - float dist = curX * curX + curYSq; - if (dist != 0.f) - dist = std::sqrt(dist); - if (maxDist < dist - info.x1c_tileHypRadius || minDist > dist + info.x1c_tileHypRadius) - continue; + for (int i = fromY; i <= toY; ++i, curY -= info.x14_tileSize) { + int nextYDiv = (i + 1) * CFluidPlaneRender::numSubdivisionsInTile; + float curYSq = curY * curY; + int curGridX = startGridX; + int curXDiv = rippleInfo.x4_fromX; + float curX = rippleInfo.x0_ripple.GetCenter().x() - info.xc_globalMin.x() - + (0.5f * info.x14_tileSize + (fromX - 1) * info.x14_tileSize); + for (int j = fromX; j <= toX; ++j, curX -= info.x14_tileSize, ++curGridX) { + float dist = curX * curX + curYSq; + if (dist != 0.f) + dist = std::sqrt(dist); + if (maxDist < dist - info.x1c_tileHypRadius || minDist > dist + info.x1c_tileHypRadius) + continue; - bool addedRipple = false; - int nextXDiv = (j+1) * CFluidPlaneRender::numSubdivisionsInTile; - float curXMod = - (rippleInfo.x0_ripple.GetCenter().x() - info.xc_globalMin.x()) - info.x18_rippleResolution * curXDiv; - float curYMod = - (rippleInfo.x0_ripple.GetCenter().y() - info.xc_globalMin.y()) - info.x18_rippleResolution * curYDiv; + bool addedRipple = false; + int nextXDiv = (j + 1) * CFluidPlaneRender::numSubdivisionsInTile; + float curXMod = + (rippleInfo.x0_ripple.GetCenter().x() - info.xc_globalMin.x()) - info.x18_rippleResolution * curXDiv; + float curYMod = + (rippleInfo.x0_ripple.GetCenter().y() - info.xc_globalMin.y()) - info.x18_rippleResolution * curYDiv; - if (!info.x30_gridFlags || (info.x30_gridFlags && curGridY >= 0 && curGridY < gridCells && curGridX >= 0 && - curGridX < info.x2a_gridDimX && info.x30_gridFlags[curGridX + curGridY])) - { - for (int k=curYDiv ; k<=std::min(rippleInfo.x10_toY, nextYDiv-1) ; ++k, - curYMod -= info.x18_rippleResolution) - { - float tmpXMod = curXMod; - float curYModSq = curYMod * curYMod; - for (int l=curXDiv ; l<=std::min(rippleInfo.x8_toX, nextXDiv-1) ; ++l, - tmpXMod -= info.x18_rippleResolution) - { - float divDistSq = tmpXMod * tmpXMod + curYModSq; - if (divDistSq < minDistSq || divDistSq > maxDistSq) - continue; + if (!info.x30_gridFlags || (info.x30_gridFlags && curGridY >= 0 && curGridY < gridCells && curGridX >= 0 && + curGridX < info.x2a_gridDimX && info.x30_gridFlags[curGridX + curGridY])) { + for (int k = curYDiv; k <= std::min(rippleInfo.x10_toY, nextYDiv - 1); + ++k, curYMod -= info.x18_rippleResolution) { + float tmpXMod = curXMod; + float curYModSq = curYMod * curYMod; + for (int l = curXDiv; l <= std::min(rippleInfo.x8_toX, nextXDiv - 1); + ++l, tmpXMod -= info.x18_rippleResolution) { + float divDistSq = tmpXMod * tmpXMod + curYModSq; + if (divDistSq < minDistSq || divDistSq > maxDistSq) + continue; - if (m_tessellation) - { - /* This will be evaluated in tessellation shader instead */ - addedRipple = true; - break; - } - - float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f; - if (u8 rippleV = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * distFalloff)]) - { - heights[k][l].height += rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() * - sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff]; - } - else - { - heights[k][l].height += 0.f; - } - addedRipple = true; - } - } - - if (addedRipple) - flags[i][j] = 0x1f; + if (m_tessellation) { + /* This will be evaluated in tessellation shader instead */ + addedRipple = true; + break; } - else - { - int yMin = nextYDiv - 1; - int yMax = nextYDiv - CFluidPlaneRender::numSubdivisionsInTile + 1; - int xMin = nextXDiv - 1; - int xMax = nextXDiv - CFluidPlaneRender::numSubdivisionsInTile + 1; - if (curGridX >= 0.f && curGridX < info.x2a_gridDimX && curGridY - info.x2a_gridDimX >= 0 && - !info.x30_gridFlags[curGridX + curGridY - info.x2a_gridDimX]) - yMax -= 2; - - if (curGridX >= 0.f && curGridX < info.x2a_gridDimX && curGridY + info.x2a_gridDimX < gridCells && - !info.x30_gridFlags[curGridX + info.x2a_gridDimX]) - yMin += 2; - - if (curGridY >= 0 && curGridY < info.x2c_gridDimY && curGridX > 0 && - !info.x30_gridFlags[curGridX - 1]) - xMax -= 2; - - if (curGridY >= 0 && curGridY < info.x2c_gridDimY && curGridX + 1 < info.x2a_gridDimX && - !info.x30_gridFlags[curGridX + 1]) - xMin += 2; - - for (int k=curYDiv ; k<=std::min(rippleInfo.x10_toY, nextYDiv-1) ; ++k, - curYMod -= info.x18_rippleResolution) - { - float tmpXMod = curXMod; - float curYModSq = curYMod * curYMod; - for (int l=curXDiv ; l<=std::min(rippleInfo.x8_toX, nextXDiv-1) ; ++l, - tmpXMod -= info.x18_rippleResolution) - { - if (k <= yMax || k >= yMin || l <= xMax || l >= xMin) - { - float divDistSq = tmpXMod * tmpXMod + curYModSq; - if (divDistSq < minDistSq || divDistSq > maxDistSq) - continue; - - if (m_tessellation) - { - /* This will be evaluated in tessellation shader instead */ - addedRipple = true; - break; - } - - float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f; - if (u8 rippleV = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * distFalloff)]) - { - heights[k][l].height += rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() * - sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff]; - } - else - { - heights[k][l].height += 0.f; - } - addedRipple = true; - } - } - - if (m_tessellation && addedRipple) - break; - } - - if (addedRipple) - flags[i][j] = 0xf; + float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f; + if (u8 rippleV = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * distFalloff)]) { + heights[k][l].height += rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() * + sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff]; + } else { + heights[k][l].height += 0.f; } - curXDiv = nextXDiv; + addedRipple = true; + } } - curYDiv = nextYDiv; - curGridY += info.x2a_gridDimX; + if (addedRipple) + flags[i][j] = 0x1f; + } else { + int yMin = nextYDiv - 1; + int yMax = nextYDiv - CFluidPlaneRender::numSubdivisionsInTile + 1; + int xMin = nextXDiv - 1; + int xMax = nextXDiv - CFluidPlaneRender::numSubdivisionsInTile + 1; + + if (curGridX >= 0.f && curGridX < info.x2a_gridDimX && curGridY - info.x2a_gridDimX >= 0 && + !info.x30_gridFlags[curGridX + curGridY - info.x2a_gridDimX]) + yMax -= 2; + + if (curGridX >= 0.f && curGridX < info.x2a_gridDimX && curGridY + info.x2a_gridDimX < gridCells && + !info.x30_gridFlags[curGridX + info.x2a_gridDimX]) + yMin += 2; + + if (curGridY >= 0 && curGridY < info.x2c_gridDimY && curGridX > 0 && !info.x30_gridFlags[curGridX - 1]) + xMax -= 2; + + if (curGridY >= 0 && curGridY < info.x2c_gridDimY && curGridX + 1 < info.x2a_gridDimX && + !info.x30_gridFlags[curGridX + 1]) + xMin += 2; + + for (int k = curYDiv; k <= std::min(rippleInfo.x10_toY, nextYDiv - 1); + ++k, curYMod -= info.x18_rippleResolution) { + float tmpXMod = curXMod; + float curYModSq = curYMod * curYMod; + for (int l = curXDiv; l <= std::min(rippleInfo.x8_toX, nextXDiv - 1); + ++l, tmpXMod -= info.x18_rippleResolution) { + if (k <= yMax || k >= yMin || l <= xMax || l >= xMin) { + float divDistSq = tmpXMod * tmpXMod + curYModSq; + if (divDistSq < minDistSq || divDistSq > maxDistSq) + continue; + + if (m_tessellation) { + /* This will be evaluated in tessellation shader instead */ + addedRipple = true; + break; + } + + float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f; + if (u8 rippleV = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * distFalloff)]) { + heights[k][l].height += rippleV * rippleInfo.x0_ripple.GetLookupAmplitude() * + sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff]; + } else { + heights[k][l].height += 0.f; + } + addedRipple = true; + } + } + + if (m_tessellation && addedRipple) + break; + } + + if (addedRipple) + flags[i][j] = 0xf; + } + curXDiv = nextXDiv; } + + curYDiv = nextYDiv; + curGridY += info.x2a_gridDimX; + } } void CFluidPlaneCPU::ApplyRipples(const rstl::reserved_vector& rippleInfos, CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], - const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info) const -{ - for (const CFluidPlaneRender::SRippleInfo& rippleInfo : rippleInfos) - ApplyRipple(rippleInfo, heights, flags, sineWave, info); - for (int i=0 ; i 0.f) - sample.wavecapIntensity = - u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); - else - sample.wavecapIntensity = 0; - } - } - } +void CFluidPlaneCPU::UpdatePatchNoNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9], + const CFluidPlaneRender::SPatchInfo& info) { + for (int i = 1; i <= (info.x1_ySubdivs + CFluidPlaneRender::numSubdivisionsInTile - 2) / + CFluidPlaneRender::numSubdivisionsInTile; + ++i) { + int r10 = i * CFluidPlaneRender::numSubdivisionsInTile + 1; + int r9 = std::max(0, r10 - CFluidPlaneRender::numSubdivisionsInTile); + int x24 = std::min(r10, info.x1_ySubdivs + 1); + for (int j = 1; j <= (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 2) / + CFluidPlaneRender::numSubdivisionsInTile; + ++j) { + int r29 = j * CFluidPlaneRender::numSubdivisionsInTile + 1; + int r11 = std::max(0, r29 - CFluidPlaneRender::numSubdivisionsInTile); + int x28 = std::min(r29, info.x0_xSubdivs + 1); + if ((flags[i][j] & 0x1f) == 0x1f) { + for (int k = r9; k < x24; ++k) { + for (int l = r11; l < x28; ++l) { + CFluidPlaneRender::SHFieldSample& sample = heights[k][l]; + if (sample.height > 0.f) + sample.wavecapIntensity = u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); else - { - if (i > 0 && i < CFluidPlaneRender::numTilesInHField + 1 && - j > 0 && j < CFluidPlaneRender::numTilesInHField + 1) - { - int halfSubdivs = CFluidPlaneRender::numSubdivisionsInTile / 2; - CFluidPlaneRender::SHFieldSample& sample = heights[halfSubdivs + r9][halfSubdivs + r11]; - if (sample.height > 0.f) - sample.wavecapIntensity = - u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); - else - sample.wavecapIntensity = 0; - } - - if (i != 0) - { - for (int l=r11 ; l 0.f) - sample.wavecapIntensity = - u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); - else - sample.wavecapIntensity = 0; - } - } - - if (j != 0) - { - for (int k=r9+1 ; k 0.f) - sample.wavecapIntensity = - u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); - else - sample.wavecapIntensity = 0; - } - } - } + sample.wavecapIntensity = 0; + } } + } else { + if (i > 0 && i < CFluidPlaneRender::numTilesInHField + 1 && j > 0 && + j < CFluidPlaneRender::numTilesInHField + 1) { + int halfSubdivs = CFluidPlaneRender::numSubdivisionsInTile / 2; + CFluidPlaneRender::SHFieldSample& sample = heights[halfSubdivs + r9][halfSubdivs + r11]; + if (sample.height > 0.f) + sample.wavecapIntensity = u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); + else + sample.wavecapIntensity = 0; + } + + if (i != 0) { + for (int l = r11; l < x28; ++l) { + CFluidPlaneRender::SHFieldSample& sample = heights[r9][l]; + if (sample.height > 0.f) + sample.wavecapIntensity = u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); + else + sample.wavecapIntensity = 0; + } + } + + if (j != 0) { + for (int k = r9 + 1; k < x24; ++k) { + CFluidPlaneRender::SHFieldSample& sample = heights[k][r11]; + if (sample.height > 0.f) + sample.wavecapIntensity = u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); + else + sample.wavecapIntensity = 0; + } + } + } } + } } -void CFluidPlaneCPU::UpdatePatchWithNormals(CFluidPlaneRender::SHFieldSample (& heights)[46][46], - const u8 (& flags)[9][9], - const CFluidPlaneRender::SPatchInfo& info) -{ - float normalScale = -(2.f * info.x18_rippleResolution); - float nz = 0.25f * 2.f * info.x18_rippleResolution; - int curGridY = info.x2e_tileY * info.x2a_gridDimX - 1 + info.x28_tileX; - for (int i=1 ; i <= (info.x1_ySubdivs + CFluidPlaneRender::numSubdivisionsInTile - 2) / - CFluidPlaneRender::numSubdivisionsInTile ; ++i, curGridY += info.x2a_gridDimX) - { - int r11 = i * CFluidPlaneRender::numSubdivisionsInTile + 1; - int r9 = std::max(0, r11 - CFluidPlaneRender::numSubdivisionsInTile); - int x38 = std::min(r11, info.x1_ySubdivs + 1); - for (int j=1 ; j <= (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 2) / - CFluidPlaneRender::numSubdivisionsInTile ; ++j) - { - int r12 = j * CFluidPlaneRender::numSubdivisionsInTile + 1; - int x3c = std::min(r12, info.x0_xSubdivs + 1); - r12 -= CFluidPlaneRender::numSubdivisionsInTile; - if ((flags[i][j] & 0x1f) == 0x1f) - { - for (int k=r9 ; k 0.f) - sample.wavecapIntensity = - u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); - else - sample.wavecapIntensity = 0; - } - } - } +void CFluidPlaneCPU::UpdatePatchWithNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46], + const u8 (&flags)[9][9], const CFluidPlaneRender::SPatchInfo& info) { + float normalScale = -(2.f * info.x18_rippleResolution); + float nz = 0.25f * 2.f * info.x18_rippleResolution; + int curGridY = info.x2e_tileY * info.x2a_gridDimX - 1 + info.x28_tileX; + for (int i = 1; i <= (info.x1_ySubdivs + CFluidPlaneRender::numSubdivisionsInTile - 2) / + CFluidPlaneRender::numSubdivisionsInTile; + ++i, curGridY += info.x2a_gridDimX) { + int r11 = i * CFluidPlaneRender::numSubdivisionsInTile + 1; + int r9 = std::max(0, r11 - CFluidPlaneRender::numSubdivisionsInTile); + int x38 = std::min(r11, info.x1_ySubdivs + 1); + for (int j = 1; j <= (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 2) / + CFluidPlaneRender::numSubdivisionsInTile; + ++j) { + int r12 = j * CFluidPlaneRender::numSubdivisionsInTile + 1; + int x3c = std::min(r12, info.x0_xSubdivs + 1); + r12 -= CFluidPlaneRender::numSubdivisionsInTile; + if ((flags[i][j] & 0x1f) == 0x1f) { + for (int k = r9; k < x38; ++k) { + for (int l = r12; l < x3c; ++l) { + CFluidPlaneRender::SHFieldSample& sample = heights[k][l]; + CFluidPlaneRender::SHFieldSample& up = heights[k + 1][l]; + CFluidPlaneRender::SHFieldSample& down = heights[k - 1][l]; + CFluidPlaneRender::SHFieldSample& right = heights[k][l + 1]; + CFluidPlaneRender::SHFieldSample& left = heights[k][l - 1]; + float nx = (right.height - left.height) * normalScale; + float ny = (up.height - down.height) * normalScale; + float normalizer = ny * ny + nx * nx + nz * nz; + if (normalizer != 0.f) + normalizer = std::sqrt(normalizer); + normalizer = 63.f / normalizer; + sample.nx = s8(nx * normalizer); + sample.ny = s8(ny * normalizer); + sample.nz = s8(nz * normalizer); + if (sample.height > 0.f) + sample.wavecapIntensity = u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); else - { - if (!info.x30_gridFlags || info.x30_gridFlags[curGridY+j]) - { - if (i > 0 && i < CFluidPlaneRender::numTilesInHField + 1 && - j > 0 && j < CFluidPlaneRender::numTilesInHField + 1) - { - int halfSubdivs = CFluidPlaneRender::numSubdivisionsInTile / 2; - int k = halfSubdivs + r9; - int l = halfSubdivs + r12; - CFluidPlaneRender::SHFieldSample& sample = heights[k][l]; - CFluidPlaneRender::SHFieldSample& up = heights[k+1][l]; - CFluidPlaneRender::SHFieldSample& down = heights[k-1][l]; - CFluidPlaneRender::SHFieldSample& right = heights[k][l+1]; - CFluidPlaneRender::SHFieldSample& left = heights[k][l-1]; - float nx = (right.height - left.height) * normalScale; - float ny = (up.height - down.height) * normalScale; - float normalizer = ny * ny + nx * nx + nz * nz; - if (normalizer != 0.f) - normalizer = std::sqrt(normalizer); - normalizer = 63.f / normalizer; - sample.nx = s8(nx * normalizer); - sample.ny = s8(ny * normalizer); - sample.nz = s8(nz * normalizer); - if (sample.height > 0.f) - sample.wavecapIntensity = - u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); - else - sample.wavecapIntensity = 0; - } - } - - if (j != 0 && i != 0) - { - if ((flags[i][j] & 2) != 0 || (flags[i-1][j] & 1) != 0 || - (flags[i][j] & 4) != 0 || (flags[i][j-1] & 8) != 0) - { - for (int l=r12 ; l 0.f) - sample.wavecapIntensity = - u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); - else - sample.wavecapIntensity = 0; - } - - for (int k=r9 ; k 0.f) - sample.wavecapIntensity = - u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); - else - sample.wavecapIntensity = 0; - } - } - else - { - CFluidPlaneRender::SHFieldSample& sample = heights[r9][r12]; - CFluidPlaneRender::SHFieldSample& up = heights[r9+1][r12]; - CFluidPlaneRender::SHFieldSample& down = heights[r9-1][r12]; - CFluidPlaneRender::SHFieldSample& right = heights[r9][r12+1]; - CFluidPlaneRender::SHFieldSample& left = heights[r9][r12-1]; - float nx = (right.height - left.height) * normalScale; - float ny = (up.height - down.height) * normalScale; - float normalizer = ny * ny + nx * nx + nz * nz; - if (normalizer != 0.f) - normalizer = std::sqrt(normalizer); - normalizer = 63.f / normalizer; - sample.nx = s8(nx * normalizer); - sample.ny = s8(ny * normalizer); - sample.nz = s8(nz * normalizer); - if (sample.height > 0.f) - sample.wavecapIntensity = - u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); - else - sample.wavecapIntensity = 0; - } - } - } + sample.wavecapIntensity = 0; + } } + } else { + if (!info.x30_gridFlags || info.x30_gridFlags[curGridY + j]) { + if (i > 0 && i < CFluidPlaneRender::numTilesInHField + 1 && j > 0 && + j < CFluidPlaneRender::numTilesInHField + 1) { + int halfSubdivs = CFluidPlaneRender::numSubdivisionsInTile / 2; + int k = halfSubdivs + r9; + int l = halfSubdivs + r12; + CFluidPlaneRender::SHFieldSample& sample = heights[k][l]; + CFluidPlaneRender::SHFieldSample& up = heights[k + 1][l]; + CFluidPlaneRender::SHFieldSample& down = heights[k - 1][l]; + CFluidPlaneRender::SHFieldSample& right = heights[k][l + 1]; + CFluidPlaneRender::SHFieldSample& left = heights[k][l - 1]; + float nx = (right.height - left.height) * normalScale; + float ny = (up.height - down.height) * normalScale; + float normalizer = ny * ny + nx * nx + nz * nz; + if (normalizer != 0.f) + normalizer = std::sqrt(normalizer); + normalizer = 63.f / normalizer; + sample.nx = s8(nx * normalizer); + sample.ny = s8(ny * normalizer); + sample.nz = s8(nz * normalizer); + if (sample.height > 0.f) + sample.wavecapIntensity = u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); + else + sample.wavecapIntensity = 0; + } + } + + if (j != 0 && i != 0) { + if ((flags[i][j] & 2) != 0 || (flags[i - 1][j] & 1) != 0 || (flags[i][j] & 4) != 0 || + (flags[i][j - 1] & 8) != 0) { + for (int l = r12; l < x3c; ++l) { + CFluidPlaneRender::SHFieldSample& sample = heights[r9][l]; + CFluidPlaneRender::SHFieldSample& up = heights[r9 + 1][l]; + CFluidPlaneRender::SHFieldSample& down = heights[r9 - 1][l]; + CFluidPlaneRender::SHFieldSample& right = heights[r9][l + 1]; + CFluidPlaneRender::SHFieldSample& left = heights[r9][l - 1]; + float nx = (right.height - left.height) * normalScale; + float ny = (up.height - down.height) * normalScale; + float normalizer = ny * ny + nx * nx + nz * nz; + if (normalizer != 0.f) + normalizer = std::sqrt(normalizer); + normalizer = 63.f / normalizer; + sample.nx = s8(nx * normalizer); + sample.ny = s8(ny * normalizer); + sample.nz = s8(nz * normalizer); + if (sample.height > 0.f) + sample.wavecapIntensity = u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); + else + sample.wavecapIntensity = 0; + } + + for (int k = r9; k < x38; ++k) { + CFluidPlaneRender::SHFieldSample& sample = heights[k][r12]; + CFluidPlaneRender::SHFieldSample& up = heights[k + 1][r12]; + CFluidPlaneRender::SHFieldSample& down = heights[k - 1][r12]; + CFluidPlaneRender::SHFieldSample& right = heights[k][r12 + 1]; + CFluidPlaneRender::SHFieldSample& left = heights[k][r12 - 1]; + float nx = (right.height - left.height) * normalScale; + float ny = (up.height - down.height) * normalScale; + float normalizer = ny * ny + nx * nx + nz * nz; + if (normalizer != 0.f) + normalizer = std::sqrt(normalizer); + normalizer = 63.f / normalizer; + sample.nx = s8(nx * normalizer); + sample.ny = s8(ny * normalizer); + sample.nz = s8(nz * normalizer); + if (sample.height > 0.f) + sample.wavecapIntensity = u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); + else + sample.wavecapIntensity = 0; + } + } else { + CFluidPlaneRender::SHFieldSample& sample = heights[r9][r12]; + CFluidPlaneRender::SHFieldSample& up = heights[r9 + 1][r12]; + CFluidPlaneRender::SHFieldSample& down = heights[r9 - 1][r12]; + CFluidPlaneRender::SHFieldSample& right = heights[r9][r12 + 1]; + CFluidPlaneRender::SHFieldSample& left = heights[r9][r12 - 1]; + float nx = (right.height - left.height) * normalScale; + float ny = (up.height - down.height) * normalScale; + float normalizer = ny * ny + nx * nx + nz * nz; + if (normalizer != 0.f) + normalizer = std::sqrt(normalizer); + normalizer = 63.f / normalizer; + sample.nx = s8(nx * normalizer); + sample.ny = s8(ny * normalizer); + sample.nz = s8(nz * normalizer); + if (sample.height > 0.f) + sample.wavecapIntensity = u8(std::min(255, int(info.x38_wavecapIntensityScale * sample.height))); + else + sample.wavecapIntensity = 0; + } + } + } } + } } bool CFluidPlaneCPU::UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info, CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], const zeus::CVector3f& areaCenter, - const std::experimental::optional& rippleManager, - int fromX, int toX, int fromY, int toY) const -{ - rstl::reserved_vector rippleInfos; - if (rippleManager) - { - for (const CRipple& ripple : rippleManager->GetRipples()) - { - if (ripple.GetTime() >= ripple.GetTimeFalloff()) - continue; - CFluidPlaneRender::SRippleInfo rippleInfo(ripple, fromX, toX, fromY, toY); - if (PrepareRipple(ripple, info, rippleInfo)) - rippleInfos.push_back(rippleInfo); - } + const std::experimental::optional& rippleManager, int fromX, int toX, + int fromY, int toY) const { + rstl::reserved_vector rippleInfos; + if (rippleManager) { + for (const CRipple& ripple : rippleManager->GetRipples()) { + if (ripple.GetTime() >= ripple.GetTimeFalloff()) + continue; + CFluidPlaneRender::SRippleInfo rippleInfo(ripple, fromX, toX, fromY, toY); + if (PrepareRipple(ripple, info, rippleInfo)) + rippleInfos.push_back(rippleInfo); } + } - if (rippleInfos.empty()) - return true; + if (rippleInfos.empty()) + return true; - ApplyTurbulence(time, heights, flags, sGlobalSineWave, info, areaCenter); - ApplyRipples(rippleInfos, heights, flags, sGlobalSineWave, info); - - /* No further action necessary if using tessellation shaders */ - if (m_tessellation) - return false; - - if (info.x37_normalMode == CFluidPlaneRender::NormalMode::NoNormals) - UpdatePatchNoNormals(heights, flags, info); - else - UpdatePatchWithNormals(heights, flags, info); + ApplyTurbulence(time, heights, flags, sGlobalSineWave, info, areaCenter); + ApplyRipples(rippleInfos, heights, flags, sGlobalSineWave, info); + /* No further action necessary if using tessellation shaders */ + if (m_tessellation) return false; + + if (info.x37_normalMode == CFluidPlaneRender::NormalMode::NoNormals) + UpdatePatchNoNormals(heights, flags, info); + else + UpdatePatchWithNormals(heights, flags, info); + + return false; } /* Used to be part of locked cache @@ -820,144 +744,133 @@ static u8 lc_flags[9][9] = {}; void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum, const std::experimental::optional& rippleManager, TUniqueId waterId, - const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const -{ - TCastToConstPtr water = mgr.GetObjectById(waterId); - CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr()); + const bool* gridFlags, u32 gridDimX, u32 gridDimY, + const zeus::CVector3f& areaCenter) const { + TCastToConstPtr water = mgr.GetObjectById(waterId); + CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr()); - CFluidPlaneRender::NormalMode normalMode; - if (xb0_bumpMap && kEnableWaterBumpMaps) - normalMode = CFluidPlaneRender::NormalMode::NBT; - else if (!noNormals) - normalMode = CFluidPlaneRender::NormalMode::Normals; - else - normalMode = CFluidPlaneRender::NormalMode::NoNormals; + CFluidPlaneRender::NormalMode normalMode; + if (xb0_bumpMap && kEnableWaterBumpMaps) + normalMode = CFluidPlaneRender::NormalMode::NBT; + else if (!noNormals) + normalMode = CFluidPlaneRender::NormalMode::Normals; + else + normalMode = CFluidPlaneRender::NormalMode::NoNormals; - // Set Position and color format + // Set Position and color format - switch (normalMode) - { - case CFluidPlaneRender::NormalMode::NBT: - // Set NBT format - break; - case CFluidPlaneRender::NormalMode::Normals: - // Set Normal format - break; - default: - break; - } + switch (normalMode) { + case CFluidPlaneRender::NormalMode::NBT: + // Set NBT format + break; + case CFluidPlaneRender::NormalMode::Normals: + // Set Normal format + break; + default: + break; + } - float rippleResolutionRecip = 1.f / x108_rippleResolution; - CFluidPlaneRender::numSubdivisionsInTile = x104_tileSubdivisions; - CFluidPlaneRender::numTilesInHField = std::min(7, 42 / CFluidPlaneRender::numSubdivisionsInTile); - CFluidPlaneRender::numSubdivisionsInHField = - CFluidPlaneRender::numTilesInHField * CFluidPlaneRender::numSubdivisionsInTile; + float rippleResolutionRecip = 1.f / x108_rippleResolution; + CFluidPlaneRender::numSubdivisionsInTile = x104_tileSubdivisions; + CFluidPlaneRender::numTilesInHField = std::min(7, 42 / CFluidPlaneRender::numSubdivisionsInTile); + CFluidPlaneRender::numSubdivisionsInHField = + CFluidPlaneRender::numTilesInHField * CFluidPlaneRender::numSubdivisionsInTile; - zeus::CVector2f ripplePitch(x108_rippleResolution * CFluidPlaneRender::numSubdivisionsInHField); + zeus::CVector2f ripplePitch(x108_rippleResolution * CFluidPlaneRender::numSubdivisionsInHField); - // Amount to shift intensity values right (for added wavecap color) - int redShift = 0; - int greenShift = 0; - int blueShift = 0; - float wavecapIntensityScale = g_tweakGame->GetWavecapIntensityNormal(); - switch (x44_fluidType) - { - case EFluidType::PoisonWater: - wavecapIntensityScale = g_tweakGame->GetWavecapIntensityPoison(); - redShift = 1; - blueShift = 1; - break; - case EFluidType::Lava: - case EFluidType::ThickLava: - wavecapIntensityScale = g_tweakGame->GetWavecapIntensityLava(); - blueShift = 8; - greenShift = 8; - break; - default: - break; - } + // Amount to shift intensity values right (for added wavecap color) + int redShift = 0; + int greenShift = 0; + int blueShift = 0; + float wavecapIntensityScale = g_tweakGame->GetWavecapIntensityNormal(); + switch (x44_fluidType) { + case EFluidType::PoisonWater: + wavecapIntensityScale = g_tweakGame->GetWavecapIntensityPoison(); + redShift = 1; + blueShift = 1; + break; + case EFluidType::Lava: + case EFluidType::ThickLava: + wavecapIntensityScale = g_tweakGame->GetWavecapIntensityLava(); + blueShift = 8; + greenShift = 8; + break; + default: + break; + } - if (water) - { - float cameraPenetration = - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation().dot(zeus::CVector3f::skUp) - - water->GetTriggerBoundsWR().max.z(); - wavecapIntensityScale *= (cameraPenetration >= 0.5f || cameraPenetration < 0.f) ? 1.f : 2.f * cameraPenetration; - } + if (water) { + float cameraPenetration = + mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation().dot(zeus::CVector3f::skUp) - + water->GetTriggerBoundsWR().max.z(); + wavecapIntensityScale *= (cameraPenetration >= 0.5f || cameraPenetration < 0.f) ? 1.f : 2.f * cameraPenetration; + } - u32 patchDimX = (water && water->GetPatchDimensionX()) ? water->GetPatchDimensionX() : 128; - u32 patchDimY = (water && water->GetPatchDimensionY()) ? water->GetPatchDimensionY() : 128; + u32 patchDimX = (water && water->GetPatchDimensionX()) ? water->GetPatchDimensionX() : 128; + u32 patchDimY = (water && water->GetPatchDimensionY()) ? water->GetPatchDimensionY() : 128; - m_verts.clear(); - m_pVerts.clear(); - if (m_tessellation) - { - /* Additional uniform data for tessellation evaluation shader */ - zeus::CColor colorMul; - colorMul.r() = wavecapIntensityScale / 255.f / float(1 << redShift); - colorMul.g() = wavecapIntensityScale / 255.f / float(1 << greenShift); - colorMul.b() = wavecapIntensityScale / 255.f / float(1 << blueShift); - m_shader->prepareDraw(setupInfo, xf.origin, *rippleManager, colorMul, x108_rippleResolution / 4.f); - } - else - { - m_shader->prepareDraw(setupInfo); - } + m_verts.clear(); + m_pVerts.clear(); + if (m_tessellation) { + /* Additional uniform data for tessellation evaluation shader */ + zeus::CColor colorMul; + colorMul.r() = wavecapIntensityScale / 255.f / float(1 << redShift); + colorMul.g() = wavecapIntensityScale / 255.f / float(1 << greenShift); + colorMul.b() = wavecapIntensityScale / 255.f / float(1 << blueShift); + m_shader->prepareDraw(setupInfo, xf.origin, *rippleManager, colorMul, x108_rippleResolution / 4.f); + } else { + m_shader->prepareDraw(setupInfo); + } - u32 tileY = 0; - float curY = aabb.min.y(); - for (int i=0 ; curY < aabb.max.y() && iGetPatchRenderFlags(j, i)) - { - s16 remDivsX = std::min(s16((aabb.max.x() - curX) * rippleResolutionRecip), - s16(CFluidPlaneRender::numSubdivisionsInHField)); - s16 remDivsY = std::min(s16(_remDivsY), s16(CFluidPlaneRender::numSubdivisionsInHField)); - zeus::CVector3f localMax(x108_rippleResolution * remDivsX + curX, - x108_rippleResolution * remDivsY + curY, aabb.max.z()); - zeus::CVector3f localMin(curX, curY, aabb.min.z()); - zeus::CAABox testaabb(localMin + xf.origin, localMax + xf.origin); - if (frustum.aabbFrustumTest(testaabb)) - { - CFluidPlaneRender::SPatchInfo info(localMin, localMax, xf.origin, x108_rippleResolution, - x100_tileSize, wavecapIntensityScale, - CFluidPlaneRender::numSubdivisionsInHField, normalMode, - redShift, greenShift, blueShift, tileX, gridDimX, gridDimY, - tileY, gridFlags); + u32 tileY = 0; + float curY = aabb.min.y(); + for (int i = 0; curY < aabb.max.y() && i < patchDimY; ++i) { + u32 tileX = 0; + float curX = aabb.min.x(); + float _remDivsY = (aabb.max.y() - curY) * rippleResolutionRecip; + for (int j = 0; curX < aabb.max.x() && j < patchDimX; ++j) { + if (u8 renderFlags = water->GetPatchRenderFlags(j, i)) { + s16 remDivsX = std::min(s16((aabb.max.x() - curX) * rippleResolutionRecip), + s16(CFluidPlaneRender::numSubdivisionsInHField)); + s16 remDivsY = std::min(s16(_remDivsY), s16(CFluidPlaneRender::numSubdivisionsInHField)); + zeus::CVector3f localMax(x108_rippleResolution * remDivsX + curX, x108_rippleResolution * remDivsY + curY, + aabb.max.z()); + zeus::CVector3f localMin(curX, curY, aabb.min.z()); + zeus::CAABox testaabb(localMin + xf.origin, localMax + xf.origin); + if (frustum.aabbFrustumTest(testaabb)) { + CFluidPlaneRender::SPatchInfo info(localMin, localMax, xf.origin, x108_rippleResolution, x100_tileSize, + wavecapIntensityScale, CFluidPlaneRender::numSubdivisionsInHField, + normalMode, redShift, greenShift, blueShift, tileX, gridDimX, gridDimY, + tileY, gridFlags); - int fromX = tileX != 0 ? (2 - CFluidPlaneRender::numSubdivisionsInTile) : 0; - int toX; - if (tileX != gridDimX - 1) - toX = info.x0_xSubdivs + (CFluidPlaneRender::numSubdivisionsInTile - 2); - else - toX = info.x0_xSubdivs; + int fromX = tileX != 0 ? (2 - CFluidPlaneRender::numSubdivisionsInTile) : 0; + int toX; + if (tileX != gridDimX - 1) + toX = info.x0_xSubdivs + (CFluidPlaneRender::numSubdivisionsInTile - 2); + else + toX = info.x0_xSubdivs; - int fromY = tileY != 0 ? (2 - CFluidPlaneRender::numSubdivisionsInTile) : 0; - int toY; - if (tileY != gridDimY - 1) - toY = info.x1_ySubdivs + (CFluidPlaneRender::numSubdivisionsInTile - 2); - else - toY = info.x1_ySubdivs; + int fromY = tileY != 0 ? (2 - CFluidPlaneRender::numSubdivisionsInTile) : 0; + int toY; + if (tileY != gridDimY - 1) + toY = info.x1_ySubdivs + (CFluidPlaneRender::numSubdivisionsInTile - 2); + else + toY = info.x1_ySubdivs; - bool noRipples = UpdatePatch(mgr.GetFluidPlaneManager()->GetUVT(), info, lc_heights, lc_flags, - areaCenter, rippleManager, fromX, toX, fromY, toY); - RenderPatch(info, lc_heights, lc_flags, noRipples, renderFlags == 1, m_verts, m_pVerts); - } - } - curX += ripplePitch.x(); - tileX += CFluidPlaneRender::numTilesInHField; + bool noRipples = UpdatePatch(mgr.GetFluidPlaneManager()->GetUVT(), info, lc_heights, lc_flags, areaCenter, + rippleManager, fromX, toX, fromY, toY); + RenderPatch(info, lc_heights, lc_flags, noRipples, renderFlags == 1, m_verts, m_pVerts); } - curY += ripplePitch.y(); - tileY += CFluidPlaneRender::numTilesInHField; + } + curX += ripplePitch.x(); + tileX += CFluidPlaneRender::numTilesInHField; } + curY += ripplePitch.y(); + tileY += CFluidPlaneRender::numTilesInHField; + } - m_shader->loadVerts(m_verts, m_pVerts); - m_shader->doneDrawing(); + m_shader->loadVerts(m_verts, m_pVerts); + m_shader->doneDrawing(); } -} +} // namespace urde diff --git a/Runtime/World/CFluidPlaneCPU.hpp b/Runtime/World/CFluidPlaneCPU.hpp index 389e0f7c2..ecf28a20f 100644 --- a/Runtime/World/CFluidPlaneCPU.hpp +++ b/Runtime/World/CFluidPlaneCPU.hpp @@ -3,129 +3,120 @@ #include "CFluidPlane.hpp" #include "CRipple.hpp" -namespace urde -{ +namespace urde { class CFluidUVMotion; -class CFluidPlaneCPU : public CFluidPlane -{ +class CFluidPlaneCPU : public CFluidPlane { protected: - class CTurbulence - { - float x0_speed; - float x4_distance; - float x8_freqMax; - float xc_freqMin; - float x10_phaseMax; - float x14_phaseMin; - float x18_amplitudeMax; - float x1c_amplitudeMin; - std::unique_ptr x20_table; // x140 - u32 x24_tableCount = 0; // x144 - float x28_heightSelPitch = 0.f; // x148 - float x2c_ooTurbSpeed; // x14c - float x30_ooTurbDistance; // x150 - bool x34_hasTurbulence = false; // x154 - public: - CTurbulence(float speed, float distance, float freqMax, float freqMin, - float phaseMax, float phaseMin, float amplitudeMax, float amplitudeMin); - float GetHeight(float sel) const { return x20_table[(x24_tableCount - 1) & int(sel * x28_heightSelPitch)]; } - float GetOODistance() const { return x30_ooTurbDistance; } - float GetOOSpeed() const { return x2c_ooTurbSpeed; } - bool HasTurbulence() const { return x34_hasTurbulence; } - }; + class CTurbulence { + float x0_speed; + float x4_distance; + float x8_freqMax; + float xc_freqMin; + float x10_phaseMax; + float x14_phaseMin; + float x18_amplitudeMax; + float x1c_amplitudeMin; + std::unique_ptr x20_table; // x140 + u32 x24_tableCount = 0; // x144 + float x28_heightSelPitch = 0.f; // x148 + float x2c_ooTurbSpeed; // x14c + float x30_ooTurbDistance; // x150 + bool x34_hasTurbulence = false; // x154 + public: + CTurbulence(float speed, float distance, float freqMax, float freqMin, float phaseMax, float phaseMin, + float amplitudeMax, float amplitudeMin); + float GetHeight(float sel) const { return x20_table[(x24_tableCount - 1) & int(sel * x28_heightSelPitch)]; } + float GetOODistance() const { return x30_ooTurbDistance; } + float GetOOSpeed() const { return x2c_ooTurbSpeed; } + bool HasTurbulence() const { return x34_hasTurbulence; } + }; - CAssetId xa0_texIdBumpMap; - CAssetId xa4_texIdEnvMap; - CAssetId xa8_texIdEnvBumpMap; - CAssetId xac_texId4; - TLockedToken xb0_bumpMap; - TLockedToken xc0_envMap; - TLockedToken xd0_envBumpMap; - TLockedToken xe0_lightmap; - zeus::CVector3f xf0_bumpLightDir; - float xfc_bumpScale; - float x100_tileSize; - int x104_tileSubdivisions; - float x108_rippleResolution; - float x10c_specularMin; - float x110_specularMax; - float x114_reflectionBlend; - float x118_reflectionSize; - float x11c_unitsPerLightmapTexel; - CTurbulence x120_turbulence; + CAssetId xa0_texIdBumpMap; + CAssetId xa4_texIdEnvMap; + CAssetId xa8_texIdEnvBumpMap; + CAssetId xac_texId4; + TLockedToken xb0_bumpMap; + TLockedToken xc0_envMap; + TLockedToken xd0_envBumpMap; + TLockedToken xe0_lightmap; + zeus::CVector3f xf0_bumpLightDir; + float xfc_bumpScale; + float x100_tileSize; + int x104_tileSubdivisions; + float x108_rippleResolution; + float x10c_specularMin; + float x110_specularMax; + float x114_reflectionBlend; + float x118_reflectionSize; + float x11c_unitsPerLightmapTexel; + CTurbulence x120_turbulence; - u32 m_maxVertCount; - bool m_tessellation = false; + u32 m_maxVertCount; + bool m_tessellation = false; - mutable bool m_cachedDoubleLightmapBlend; - mutable bool m_cachedAdditive; + mutable bool m_cachedDoubleLightmapBlend; + mutable bool m_cachedAdditive; - static bool PrepareRipple(const CRipple& ripple, const CFluidPlaneRender::SPatchInfo& info, - CFluidPlaneRender::SRippleInfo& rippleOut); - void ApplyTurbulence(float t, CFluidPlaneRender::SHFieldSample (&heights)[46][46], - const u8 (&flags)[9][9], const float sineWave[256], - const CFluidPlaneRender::SPatchInfo& info, - const zeus::CVector3f& areaCenter) const; - void ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo, - CFluidPlaneRender::SHFieldSample (&heights)[46][46], - u8 (&flags)[9][9], const float sineWave[256], - const CFluidPlaneRender::SPatchInfo& info) const; - void ApplyRipples(const rstl::reserved_vector& rippleInfos, - CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], - const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info) const; - static void UpdatePatchNoNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46], - const u8 (&flags)[9][9], + static bool PrepareRipple(const CRipple& ripple, const CFluidPlaneRender::SPatchInfo& info, + CFluidPlaneRender::SRippleInfo& rippleOut); + void ApplyTurbulence(float t, CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9], + const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info, + const zeus::CVector3f& areaCenter) const; + void ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo, + CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], const float sineWave[256], + const CFluidPlaneRender::SPatchInfo& info) const; + void ApplyRipples(const rstl::reserved_vector& rippleInfos, + CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], const float sineWave[256], + const CFluidPlaneRender::SPatchInfo& info) const; + static void UpdatePatchNoNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9], + const CFluidPlaneRender::SPatchInfo& info); + static void UpdatePatchWithNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9], const CFluidPlaneRender::SPatchInfo& info); - static void UpdatePatchWithNormals(CFluidPlaneRender::SHFieldSample (& heights)[46][46], - const u8 (& flags)[9][9], - const CFluidPlaneRender::SPatchInfo& info); - bool UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info, - CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], - const zeus::CVector3f& areaCenter, - const std::experimental::optional& rippleManager, - int fromX, int toX, int fromY, int toY) const; + bool UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info, + CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9], + const zeus::CVector3f& areaCenter, const std::experimental::optional& rippleManager, + int fromX, int toX, int fromY, int toY) const; public: - CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap, - CAssetId envBumpMap, CAssetId lightMap, float unitsPerLightmapTexel, float tileSize, - u32 tileSubdivisions, EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir, - float bumpScale, const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax, - float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, - float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend, - float reflectionSize, float rippleIntensity, u32 maxVertCount); - void CreateRipple(const CRipple& ripple, CStateManager& mgr); - void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf, - const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const; - CFluidPlaneShader::RenderSetupInfo RenderSetup(const CStateManager& mgr, float, const zeus::CTransform& xf, - const zeus::CTransform& areaXf, const zeus::CAABox& aabb, - const CScriptWater* water) const; - void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, - const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum, - const std::experimental::optional& rippleManager, TUniqueId waterId, - const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const; - float GetReflectionBlend() const { return x114_reflectionBlend; } - float GetSpecularMax() const { return x110_specularMax; } - float GetSpecularMin() const { return x10c_specularMin; } - float GetReflectionSize() const { return x118_reflectionSize; } - float GetBumpScale() const { return xfc_bumpScale; } - bool HasBumpMap() const { return xb0_bumpMap.operator bool(); } - const CTexture& GetBumpMap() const { return *xb0_bumpMap; } - bool HasEnvMap() const { return xc0_envMap.operator bool(); } - const CTexture& GetEnvMap() const { return *xc0_envMap; } - bool HasEnvBumpMap() const { return xd0_envBumpMap.operator bool(); } - const CTexture& GetEnvBumpMap() const { return *xd0_envBumpMap; } - bool HasLightMap() const { return xe0_lightmap.operator bool(); } - const CTexture& GetLightMap() const { return *xe0_lightmap; } - const zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; } - float GetTileSize() const { return x100_tileSize; } - int GetTileSubdivisions() const { return x104_tileSubdivisions; } - float GetRippleResolution() const { return x108_rippleResolution; } - float GetTurbulenceHeight(float sel) const { return x120_turbulence.GetHeight(sel); } - float GetOOTurbulenceDistance() const { return x120_turbulence.GetOODistance(); } - float GetOOTurbulenceSpeed() const { return x120_turbulence.GetOOSpeed(); } - bool HasTurbulence() const { return x120_turbulence.HasTurbulence(); } + CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap, + CAssetId envBumpMap, CAssetId lightMap, float unitsPerLightmapTexel, float tileSize, + u32 tileSubdivisions, EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir, + float bumpScale, const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax, + float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, + float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend, + float reflectionSize, float rippleIntensity, u32 maxVertCount); + void CreateRipple(const CRipple& ripple, CStateManager& mgr); + void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf, const zeus::CAABox& aabb, + zeus::CMatrix4f& mtxOut) const; + CFluidPlaneShader::RenderSetupInfo RenderSetup(const CStateManager& mgr, float, const zeus::CTransform& xf, + const zeus::CTransform& areaXf, const zeus::CAABox& aabb, + const CScriptWater* water) const; + void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, + const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum, + const std::experimental::optional& rippleManager, TUniqueId waterId, + const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const; + float GetReflectionBlend() const { return x114_reflectionBlend; } + float GetSpecularMax() const { return x110_specularMax; } + float GetSpecularMin() const { return x10c_specularMin; } + float GetReflectionSize() const { return x118_reflectionSize; } + float GetBumpScale() const { return xfc_bumpScale; } + bool HasBumpMap() const { return xb0_bumpMap.operator bool(); } + const CTexture& GetBumpMap() const { return *xb0_bumpMap; } + bool HasEnvMap() const { return xc0_envMap.operator bool(); } + const CTexture& GetEnvMap() const { return *xc0_envMap; } + bool HasEnvBumpMap() const { return xd0_envBumpMap.operator bool(); } + const CTexture& GetEnvBumpMap() const { return *xd0_envBumpMap; } + bool HasLightMap() const { return xe0_lightmap.operator bool(); } + const CTexture& GetLightMap() const { return *xe0_lightmap; } + const zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; } + float GetTileSize() const { return x100_tileSize; } + int GetTileSubdivisions() const { return x104_tileSubdivisions; } + float GetRippleResolution() const { return x108_rippleResolution; } + float GetTurbulenceHeight(float sel) const { return x120_turbulence.GetHeight(sel); } + float GetOOTurbulenceDistance() const { return x120_turbulence.GetOODistance(); } + float GetOOTurbulenceSpeed() const { return x120_turbulence.GetOOSpeed(); } + bool HasTurbulence() const { return x120_turbulence.HasTurbulence(); } }; -} - +} // namespace urde diff --git a/Runtime/World/CFluidPlaneDoor.cpp b/Runtime/World/CFluidPlaneDoor.cpp index ae5cbcc9c..3abfa296b 100644 --- a/Runtime/World/CFluidPlaneDoor.cpp +++ b/Runtime/World/CFluidPlaneDoor.cpp @@ -2,55 +2,53 @@ #include "CFluidPlaneCPU.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { CFluidPlaneDoor::CFluidPlaneDoor(CAssetId patternTex1, CAssetId patternTex2, CAssetId colorTex, float tileSize, u32 tileSubdivisions, EFluidType fluidType, float alpha, const CFluidUVMotion& uvMotion) -: CFluidPlane(patternTex1, patternTex2, colorTex, alpha, fluidType, 0.5f, uvMotion), xa0_tileSize(tileSize), - xa4_tileSubdivisions(tileSubdivisions & ~0x1), xa8_rippleResolution(xa0_tileSize / float(xa4_tileSubdivisions)) -{} +: CFluidPlane(patternTex1, patternTex2, colorTex, alpha, fluidType, 0.5f, uvMotion) +, xa0_tileSize(tileSize) +, xa4_tileSubdivisions(tileSubdivisions & ~0x1) +, xa8_rippleResolution(xa0_tileSize / float(xa4_tileSubdivisions)) {} -CFluidPlaneShader::RenderSetupInfo -CFluidPlaneDoor::RenderSetup(const CStateManager& mgr, float alpha, const zeus::CTransform& xf, - const zeus::CAABox& aabb, bool noNormals) const -{ - CFluidPlaneShader::RenderSetupInfo out; +CFluidPlaneShader::RenderSetupInfo CFluidPlaneDoor::RenderSetup(const CStateManager& mgr, float alpha, + const zeus::CTransform& xf, const zeus::CAABox& aabb, + bool noNormals) const { + CFluidPlaneShader::RenderSetupInfo out; - float uvT = mgr.GetFluidPlaneManager()->GetUVT(); - CGraphics::SetModelMatrix(xf); + float uvT = mgr.GetFluidPlaneManager()->GetUVT(); + CGraphics::SetModelMatrix(xf); - float fluidUVs[3][2]; - x4c_uvMotion.CalculateFluidTextureOffset(uvT, fluidUVs); + float fluidUVs[3][2]; + x4c_uvMotion.CalculateFluidTextureOffset(uvT, fluidUVs); - out.texMtxs[0][0][0] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); - out.texMtxs[0][1][1] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); - out.texMtxs[0][3][0] = fluidUVs[1][0]; - out.texMtxs[0][3][1] = fluidUVs[1][1]; + out.texMtxs[0][0][0] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); + out.texMtxs[0][1][1] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale(); + out.texMtxs[0][3][0] = fluidUVs[1][0]; + out.texMtxs[0][3][1] = fluidUVs[1][1]; - out.texMtxs[1][0][0] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale(); - out.texMtxs[1][1][1] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale(); - out.texMtxs[1][3][0] = fluidUVs[2][0]; - out.texMtxs[1][3][1] = fluidUVs[2][1]; + out.texMtxs[1][0][0] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale(); + out.texMtxs[1][1][1] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale(); + out.texMtxs[1][3][0] = fluidUVs[2][0]; + out.texMtxs[1][3][1] = fluidUVs[2][1]; - out.texMtxs[2][0][0] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); - out.texMtxs[2][1][1] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); - out.texMtxs[2][3][0] = fluidUVs[0][0]; - out.texMtxs[2][3][1] = fluidUVs[0][1]; + out.texMtxs[2][0][0] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); + out.texMtxs[2][1][1] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale(); + out.texMtxs[2][3][0] = fluidUVs[0][0]; + out.texMtxs[2][3][1] = fluidUVs[0][1]; - out.kColors[0] = zeus::CColor(1.f, alpha); + out.kColors[0] = zeus::CColor(1.f, alpha); - if (!m_shader) - { - auto gridDimX = u32((xa0_tileSize + aabb.max.x() - aabb.min.x() - 0.01f) / xa0_tileSize); - auto gridDimY = u32((xa0_tileSize + aabb.max.y() - aabb.min.y() - 0.01f) / xa0_tileSize); - u32 gridCellCount = (gridDimX + 1) * (gridDimY + 1); - u32 maxVerts = gridCellCount * ((std::max(2, xa4_tileSubdivisions) * 4 + 2) * 4); - m_shader.emplace(x10_texPattern1, x20_texPattern2, x30_texColor, maxVerts); - } + if (!m_shader) { + auto gridDimX = u32((xa0_tileSize + aabb.max.x() - aabb.min.x() - 0.01f) / xa0_tileSize); + auto gridDimY = u32((xa0_tileSize + aabb.max.y() - aabb.min.y() - 0.01f) / xa0_tileSize); + u32 gridCellCount = (gridDimX + 1) * (gridDimY + 1); + u32 maxVerts = gridCellCount * ((std::max(2, xa4_tileSubdivisions) * 4 + 2) * 4); + m_shader.emplace(x10_texPattern1, x20_texPattern2, x30_texColor, maxVerts); + } - return out; + return out; } /* Used to be part of locked cache @@ -58,50 +56,45 @@ CFluidPlaneDoor::RenderSetup(const CStateManager& mgr, float alpha, const zeus:: static CFluidPlaneRender::SHFieldSample lc_heights[46][46] = {}; static u8 lc_flags[9][9] = {}; -void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, - const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum, +void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, + const zeus::CTransform& xf, const zeus::CTransform& areaXf, bool noNormals, + const zeus::CFrustum& frustum, const std::experimental::optional& rippleManager, TUniqueId waterId, - const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const -{ - CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, aabb, noNormals); - CFluidPlaneRender::numSubdivisionsInTile = xa4_tileSubdivisions; - CFluidPlaneRender::numTilesInHField = 42 / xa4_tileSubdivisions; - CFluidPlaneRender::numSubdivisionsInHField = CFluidPlaneRender::numTilesInHField * xa4_tileSubdivisions; - zeus::CVector2f centerPlane(aabb.center().x(), aabb.center().y()); - float patchSize = xa8_rippleResolution * CFluidPlaneRender::numSubdivisionsInHField; - float ooSubdivSize = 1.f / xa8_rippleResolution; + const bool* gridFlags, u32 gridDimX, u32 gridDimY, + const zeus::CVector3f& areaCenter) const { + CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, aabb, noNormals); + CFluidPlaneRender::numSubdivisionsInTile = xa4_tileSubdivisions; + CFluidPlaneRender::numTilesInHField = 42 / xa4_tileSubdivisions; + CFluidPlaneRender::numSubdivisionsInHField = CFluidPlaneRender::numTilesInHField * xa4_tileSubdivisions; + zeus::CVector2f centerPlane(aabb.center().x(), aabb.center().y()); + float patchSize = xa8_rippleResolution * CFluidPlaneRender::numSubdivisionsInHField; + float ooSubdivSize = 1.f / xa8_rippleResolution; - m_verts.clear(); - m_pVerts.clear(); - m_shader->prepareDraw(setupInfo); + m_verts.clear(); + m_pVerts.clear(); + m_shader->prepareDraw(setupInfo); - for (float curX = aabb.min.x() ; curX < aabb.max.x() ; curX += patchSize) - { - float remSubdivsX = (aabb.max.x() - curX) * ooSubdivSize; - for (float curY = aabb.min.y() ; curY < aabb.max.y() ; curY += patchSize) - { - float remSubdivsY = (aabb.max.y() - curY) * ooSubdivSize; - int remSubdivsXi = std::min(CFluidPlaneRender::numSubdivisionsInHField, int(remSubdivsX)); - int remSubdivsYi = std::min(CFluidPlaneRender::numSubdivisionsInHField, int(remSubdivsY)); - zeus::CAABox aabb2(aabb.min, zeus::CVector3f(xa8_rippleResolution * remSubdivsXi + curX, - xa8_rippleResolution * remSubdivsYi + curY, - aabb.max.z())); - if (frustum.aabbFrustumTest(aabb2.getTransformedAABox(xf))) - { - CFluidPlaneRender::SPatchInfo patchInfo(zeus::CVector3f(curX, curY, aabb.min.z()), - aabb2.max, xf.origin, xa8_rippleResolution, - xa0_tileSize, 0.f, - CFluidPlaneRender::numSubdivisionsInHField, - CFluidPlaneRender::NormalMode::None, - 0, 0, 0, 0, 0, 0, 0, nullptr); + for (float curX = aabb.min.x(); curX < aabb.max.x(); curX += patchSize) { + float remSubdivsX = (aabb.max.x() - curX) * ooSubdivSize; + for (float curY = aabb.min.y(); curY < aabb.max.y(); curY += patchSize) { + float remSubdivsY = (aabb.max.y() - curY) * ooSubdivSize; + int remSubdivsXi = std::min(CFluidPlaneRender::numSubdivisionsInHField, int(remSubdivsX)); + int remSubdivsYi = std::min(CFluidPlaneRender::numSubdivisionsInHField, int(remSubdivsY)); + zeus::CAABox aabb2(aabb.min, zeus::CVector3f(xa8_rippleResolution * remSubdivsXi + curX, + xa8_rippleResolution * remSubdivsYi + curY, aabb.max.z())); + if (frustum.aabbFrustumTest(aabb2.getTransformedAABox(xf))) { + CFluidPlaneRender::SPatchInfo patchInfo(zeus::CVector3f(curX, curY, aabb.min.z()), aabb2.max, xf.origin, + xa8_rippleResolution, xa0_tileSize, 0.f, + CFluidPlaneRender::numSubdivisionsInHField, + CFluidPlaneRender::NormalMode::None, 0, 0, 0, 0, 0, 0, 0, nullptr); - RenderPatch(patchInfo, lc_heights, lc_flags, true, true, m_verts, m_pVerts); - } - } + RenderPatch(patchInfo, lc_heights, lc_flags, true, true, m_verts, m_pVerts); + } } + } - m_shader->loadVerts(m_verts, m_pVerts); - m_shader->doneDrawing(); + m_shader->loadVerts(m_verts, m_pVerts); + m_shader->doneDrawing(); } -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/World/CFluidPlaneDoor.hpp b/Runtime/World/CFluidPlaneDoor.hpp index be0406e31..47bac0061 100644 --- a/Runtime/World/CFluidPlaneDoor.hpp +++ b/Runtime/World/CFluidPlaneDoor.hpp @@ -3,32 +3,28 @@ #include "CFluidPlane.hpp" #include "Graphics/Shaders/CFluidPlaneShader.hpp" -namespace urde -{ -class CFluidPlaneDoor final : public CFluidPlane -{ - float xa0_tileSize; - int xa4_tileSubdivisions; - float xa8_rippleResolution; +namespace urde { +class CFluidPlaneDoor final : public CFluidPlane { + float xa0_tileSize; + int xa4_tileSubdivisions; + float xa8_rippleResolution; + + CFluidPlaneShader::RenderSetupInfo RenderSetup(const CStateManager& mgr, float alpha, const zeus::CTransform& xf, + const zeus::CAABox& aabb, bool noNormals) const; - CFluidPlaneShader::RenderSetupInfo - RenderSetup(const CStateManager& mgr, float alpha, const zeus::CTransform& xf, - const zeus::CAABox& aabb, bool noNormals) const; public: - CFluidPlaneDoor(CAssetId patternTex1, CAssetId patternTex2, CAssetId colorTex, float tileSize, u32 tileSubdivisions, - EFluidType fluidType, float alpha, const CFluidUVMotion& uvMotion); - void AddRipple(float mag, TUniqueId rippler, const zeus::CVector3f& center, - CScriptWater& water, CStateManager& mgr) {} - void AddRipple(float intensity, TUniqueId rippler, const zeus::CVector3f& center, - const zeus::CVector3f& velocity, const CScriptWater& water, CStateManager& mgr, - const zeus::CVector3f& upVec) {} - void AddRipple(const CRipple& ripple, const CScriptWater& water, CStateManager& mgr) {} + CFluidPlaneDoor(CAssetId patternTex1, CAssetId patternTex2, CAssetId colorTex, float tileSize, u32 tileSubdivisions, + EFluidType fluidType, float alpha, const CFluidUVMotion& uvMotion); + void AddRipple(float mag, TUniqueId rippler, const zeus::CVector3f& center, CScriptWater& water, CStateManager& mgr) { + } + void AddRipple(float intensity, TUniqueId rippler, const zeus::CVector3f& center, const zeus::CVector3f& velocity, + const CScriptWater& water, CStateManager& mgr, const zeus::CVector3f& upVec) {} + void AddRipple(const CRipple& ripple, const CScriptWater& water, CStateManager& mgr) {} - void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, - const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum, - const std::experimental::optional& rippleManager, TUniqueId waterId, - const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const; + void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf, + const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum, + const std::experimental::optional& rippleManager, TUniqueId waterId, + const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const; }; -} - +} // namespace urde diff --git a/Runtime/World/CFluidPlaneGPU.cpp b/Runtime/World/CFluidPlaneGPU.cpp index f61d88b29..1bab07312 100644 --- a/Runtime/World/CFluidPlaneGPU.cpp +++ b/Runtime/World/CFluidPlaneGPU.cpp @@ -1,7 +1,6 @@ #include "CFluidPlaneGPU.hpp" -namespace urde -{ +namespace urde { CFluidPlaneGPU::CFluidPlaneGPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap, CAssetId envBumpMap, CAssetId lightMap, float unitsPerLightmapTexel, @@ -13,81 +12,71 @@ CFluidPlaneGPU::CFluidPlaneGPU(CAssetId texPattern1, CAssetId texPattern2, CAsse float rippleIntensity, u32 maxVertCount) : CFluidPlaneCPU(texPattern1, texPattern2, texColor, bumpMap, envMap, envBumpMap, lightMap, unitsPerLightmapTexel, tileSize, tileSubdivisions, fluidType, alpha, bumpLightDir, bumpScale, mot, turbSpeed, turbDistance, - turbFreqMax, turbFreqMin, turbPhaseMax, turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, - specularMin, specularMax, reflectionBlend, reflectionSize, rippleIntensity, maxVertCount) -{ - m_tessellation = true; + turbFreqMax, turbFreqMin, turbPhaseMax, turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin, + specularMax, reflectionBlend, reflectionSize, rippleIntensity, maxVertCount) { + m_tessellation = true; } void CFluidPlaneGPU::RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9], int startYDiv, const CFluidPlaneRender::SPatchInfo& info, std::vector& vOut, - std::vector& pvOut) const -{ - m_shader->bindTessellation(); + std::vector& pvOut) const { + m_shader->bindTessellation(); - int yTile = (startYDiv + CFluidPlaneRender::numSubdivisionsInTile - 1) / - CFluidPlaneRender::numSubdivisionsInTile; - int endXTile = (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) / - CFluidPlaneRender::numSubdivisionsInTile; + int yTile = (startYDiv + CFluidPlaneRender::numSubdivisionsInTile - 1) / CFluidPlaneRender::numSubdivisionsInTile; + int endXTile = + (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) / CFluidPlaneRender::numSubdivisionsInTile; - float yMin = curY; - float subdivF = CFluidPlaneRender::numSubdivisionsInTile; + float yMin = curY; + float subdivF = CFluidPlaneRender::numSubdivisionsInTile; - float curX = info.x4_localMin.x(); - int gridCell = info.x28_tileX + info.x2a_gridDimX * (info.x2e_tileY + yTile - 1); - int xTile = 1; - int tileSpan; - for (int i = 1 ; i < info.x0_xSubdivs - 2 ; - i += CFluidPlaneRender::numSubdivisionsInTile * tileSpan, gridCell += tileSpan, - xTile += tileSpan, curX += info.x14_tileSize * tileSpan) - { - tileSpan = 1; - if (info.x30_gridFlags && !info.x30_gridFlags[gridCell]) - continue; + float curX = info.x4_localMin.x(); + int gridCell = info.x28_tileX + info.x2a_gridDimX * (info.x2e_tileY + yTile - 1); + int xTile = 1; + int tileSpan; + for (int i = 1; i < info.x0_xSubdivs - 2; i += CFluidPlaneRender::numSubdivisionsInTile * tileSpan, + gridCell += tileSpan, xTile += tileSpan, curX += info.x14_tileSize * tileSpan) { + tileSpan = 1; + if (info.x30_gridFlags && !info.x30_gridFlags[gridCell]) + continue; - CFluidPlaneShader::PatchVertex pv; - size_t start = pvOut.size(); + CFluidPlaneShader::PatchVertex pv; + size_t start = pvOut.size(); - if ((flags[yTile][xTile] & 0x1f) == 0x1f) - { - for (; xTile+tileSpan<=endXTile ; ++tileSpan) - { - if ((flags[yTile][xTile+tileSpan] & 0x1f) != 0x1f) - break; - if (info.x30_gridFlags && !info.x30_gridFlags[gridCell+tileSpan]) - break; - } + if ((flags[yTile][xTile] & 0x1f) == 0x1f) { + for (; xTile + tileSpan <= endXTile; ++tileSpan) { + if ((flags[yTile][xTile + tileSpan] & 0x1f) != 0x1f) + break; + if (info.x30_gridFlags && !info.x30_gridFlags[gridCell + tileSpan]) + break; + } - std::fill(std::begin(pv.m_outerLevels), std::end(pv.m_outerLevels), subdivF); - std::fill(std::begin(pv.m_innerLevels), std::end(pv.m_innerLevels), subdivF); - } - else - { - bool r19 = (flags[yTile+1][xTile] & 0x2) != 0; // North - bool r16 = (flags[yTile][xTile-1] & 0x8) != 0; // West - bool r18 = (flags[yTile][xTile+1] & 0x4) != 0; // East - bool r17 = (flags[yTile-1][xTile] & 0x1) != 0; // South + std::fill(std::begin(pv.m_outerLevels), std::end(pv.m_outerLevels), subdivF); + std::fill(std::begin(pv.m_innerLevels), std::end(pv.m_innerLevels), subdivF); + } else { + bool r19 = (flags[yTile + 1][xTile] & 0x2) != 0; // North + bool r16 = (flags[yTile][xTile - 1] & 0x8) != 0; // West + bool r18 = (flags[yTile][xTile + 1] & 0x4) != 0; // East + bool r17 = (flags[yTile - 1][xTile] & 0x1) != 0; // South - pv.m_outerLevels[0] = r16 ? subdivF : 1.f; - pv.m_outerLevels[1] = r17 ? subdivF : 1.f; - pv.m_outerLevels[2] = r18 ? subdivF : 1.f; - pv.m_outerLevels[3] = r19 ? subdivF : 1.f; - std::fill(std::begin(pv.m_innerLevels), std::end(pv.m_innerLevels), subdivF); - } - - float curTileY = yMin; - float curTileX = curX; - for (int t=0 ; t& vOut, - std::vector& pvOut) const; + void RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46], + const u8 (&flags)[9][9], int startYDiv, const CFluidPlaneRender::SPatchInfo& info, + std::vector& vOut, + std::vector& pvOut) const; }; -} - +} // namespace urde diff --git a/Runtime/World/CFluidPlaneManager.cpp b/Runtime/World/CFluidPlaneManager.cpp index 772f4802c..a9c10f616 100644 --- a/Runtime/World/CFluidPlaneManager.cpp +++ b/Runtime/World/CFluidPlaneManager.cpp @@ -3,93 +3,78 @@ #include "CExplosion.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { CFluidPlaneManager::CFluidProfile CFluidPlaneManager::sProfile = {}; -CFluidPlaneManager::CFluidPlaneManager() -: x0_rippleManager(20, 0.5f) -{ - sProfile.Clear(); - SetupRippleMap(); +CFluidPlaneManager::CFluidPlaneManager() : x0_rippleManager(20, 0.5f) { + sProfile.Clear(); + SetupRippleMap(); } -void CFluidPlaneManager::CFluidProfile::Clear() -{ - x0_ = 0.f; - x4_ = 0.f; - x8_ = 0.f; - xc_ = 0.f; - x10_ = 0.f; +void CFluidPlaneManager::CFluidProfile::Clear() { + x0_ = 0.f; + x4_ = 0.f; + x8_ = 0.f; + xc_ = 0.f; + x10_ = 0.f; } -void CFluidPlaneManager::StartFrame(bool b) -{ - x121_ = b; - sProfile.Clear(); +void CFluidPlaneManager::StartFrame(bool b) { + x121_ = b; + sProfile.Clear(); } -void CFluidPlaneManager::Update(float dt) -{ - x11c_uvT += dt; - x0_rippleManager.Update(dt); - for (CSplashRecord& record : x18_splashes) - { - record.SetTime(record.GetTime() + dt); - if (record.GetTime() > 9999.f) - record.SetTime(9999.f); - } +void CFluidPlaneManager::Update(float dt) { + x11c_uvT += dt; + x0_rippleManager.Update(dt); + for (CSplashRecord& record : x18_splashes) { + record.SetTime(record.GetTime() + dt); + if (record.GetTime() > 9999.f) + record.SetTime(9999.f); + } } -float CFluidPlaneManager::GetLastRippleDeltaTime(TUniqueId rippler) const -{ - return x0_rippleManager.GetLastRippleDeltaTime(rippler); +float CFluidPlaneManager::GetLastRippleDeltaTime(TUniqueId rippler) const { + return x0_rippleManager.GetLastRippleDeltaTime(rippler); } -float CFluidPlaneManager::GetLastSplashDeltaTime(TUniqueId splasher) const -{ - float newestTime = 9999.f; - for (const CSplashRecord& record : x18_splashes) - if (record.GetUniqueId() == splasher && newestTime > record.GetTime()) - newestTime = record.GetTime(); - return newestTime; +float CFluidPlaneManager::GetLastSplashDeltaTime(TUniqueId splasher) const { + float newestTime = 9999.f; + for (const CSplashRecord& record : x18_splashes) + if (record.GetUniqueId() == splasher && newestTime > record.GetTime()) + newestTime = record.GetTime(); + return newestTime; } void CFluidPlaneManager::CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water, - const zeus::CVector3f& pos, float factor, bool sfx) -{ - if (water.CanRippleAtPoint(pos)) - { - float oldestTime = 0.f; - CSplashRecord* oldestRecord = nullptr; - for (CSplashRecord& record : x18_splashes) - { - if (record.GetTime() > oldestTime) - { - oldestRecord = &record; - oldestTime = record.GetTime(); - } - } - if (oldestRecord) - *oldestRecord = CSplashRecord(0.f, splasher); - else - x18_splashes.emplace_back(0.f, splasher); - float splashScale = water.GetSplashEffectScale(factor); - if (water.GetSplashEffect(factor)) - { - CExplosion* expl = new CExplosion(*water.GetSplashEffect(factor), mgr.AllocateUniqueId(), true, - CEntityInfo(water.GetAreaIdAlways(), CEntity::NullConnectionList), - "Splash", zeus::CTransform(zeus::CMatrix3f::skIdentityMatrix3f, pos), - 1, zeus::CVector3f{splashScale}, water.GetSplashColor()); - mgr.AddObject(expl); - } - if (sfx) - { - CSfxManager::AddEmitter(water.GetSplashSound(factor), pos, zeus::CVector3f::skUp, - true, false, 0x7f, kInvalidAreaId); - } + const zeus::CVector3f& pos, float factor, bool sfx) { + if (water.CanRippleAtPoint(pos)) { + float oldestTime = 0.f; + CSplashRecord* oldestRecord = nullptr; + for (CSplashRecord& record : x18_splashes) { + if (record.GetTime() > oldestTime) { + oldestRecord = &record; + oldestTime = record.GetTime(); + } } + if (oldestRecord) + *oldestRecord = CSplashRecord(0.f, splasher); + else + x18_splashes.emplace_back(0.f, splasher); + float splashScale = water.GetSplashEffectScale(factor); + if (water.GetSplashEffect(factor)) { + CExplosion* expl = new CExplosion(*water.GetSplashEffect(factor), mgr.AllocateUniqueId(), true, + CEntityInfo(water.GetAreaIdAlways(), CEntity::NullConnectionList), "Splash", + zeus::CTransform(zeus::CMatrix3f::skIdentityMatrix3f, pos), 1, + zeus::CVector3f{splashScale}, water.GetSplashColor()); + mgr.AddObject(expl); + } + if (sfx) { + CSfxManager::AddEmitter(water.GetSplashSound(factor), pos, zeus::CVector3f::skUp, true, false, 0x7f, + kInvalidAreaId); + } + } } static bool g_RippleMapSetup = false; @@ -98,63 +83,58 @@ u8 CFluidPlaneManager::RippleMins[64] = {}; u8 CFluidPlaneManager::RippleMaxs[64] = {}; boo::ObjToken CFluidPlaneManager::RippleMapTex; -void CFluidPlaneManager::SetupRippleMap() -{ - if (g_RippleMapSetup) - return; - g_RippleMapSetup = true; +void CFluidPlaneManager::SetupRippleMap() { + if (g_RippleMapSetup) + return; + g_RippleMapSetup = true; - float curX = 0.f; - for (int i=0 ; i<64 ; ++i) - { - float curY = 0.f; - float minY = 1.f; - float maxY = 0.f; - for (int j=0 ; j<64 ; ++j) - { - float rVal = 1.f - curY; - float minX = curY; - float maxX = 1.25f * (0.25f * rVal + 0.1f) + curY; - if (curY < 0.f) - minX = 0.f; - else if (maxX > 1.f) - maxX = 1.f; + float curX = 0.f; + for (int i = 0; i < 64; ++i) { + float curY = 0.f; + float minY = 1.f; + float maxY = 0.f; + for (int j = 0; j < 64; ++j) { + float rVal = 1.f - curY; + float minX = curY; + float maxX = 1.25f * (0.25f * rVal + 0.1f) + curY; + if (curY < 0.f) + minX = 0.f; + else if (maxX > 1.f) + maxX = 1.f; - float val = 0.f; - if (curX >= minX && curX <= maxX) - { - float t = (curX - minX) / (maxX - minX); - if (t < 0.4f) - val = 2.5f * t; - else if (t > 0.75f) - val = 4.f * (1.f - t); - else - val = 1.f; - } + float val = 0.f; + if (curX >= minX && curX <= maxX) { + float t = (curX - minX) / (maxX - minX); + if (t < 0.4f) + val = 2.5f * t; + else if (t > 0.75f) + val = 4.f * (1.f - t); + else + val = 1.f; + } - auto valA = u8(std::max(int(255.f * val * rVal * rVal) - 1, 0)); - RippleValues[i][j] = valA; - if (valA != 0 && curY < minY) - minY = curY; - if (valA != 0 && curY > maxY) - maxY = curY; + auto valA = u8(std::max(int(255.f * val * rVal * rVal) - 1, 0)); + RippleValues[i][j] = valA; + if (valA != 0 && curY < minY) + minY = curY; + if (valA != 0 && curY > maxY) + maxY = curY; - curY += (1.f / 63.f); - } - - auto valB = u8(std::max(int(255.f * minY) - 1, 0)); - auto valC = u8(std::min(int(255.f * maxY) + 1, 255)); - RippleMins[i] = valB; - RippleMaxs[i] = valC; - curX += (1.f / 63.f); + curY += (1.f / 63.f); } - CGraphics::CommitResources([](boo::IGraphicsDataFactory::Context& ctx) - { - RippleMapTex = ctx.newStaticTexture(64, 64, 1, boo::TextureFormat::I8, - boo::TextureClampMode::ClampToBlack, RippleValues, 64 * 64); - return true; - } BooTrace); + auto valB = u8(std::max(int(255.f * minY) - 1, 0)); + auto valC = u8(std::min(int(255.f * maxY) + 1, 255)); + RippleMins[i] = valB; + RippleMaxs[i] = valC; + curX += (1.f / 63.f); + } + + CGraphics::CommitResources([](boo::IGraphicsDataFactory::Context& ctx) { + RippleMapTex = ctx.newStaticTexture(64, 64, 1, boo::TextureFormat::I8, boo::TextureClampMode::ClampToBlack, + RippleValues, 64 * 64); + return true; + } BooTrace); } -} +} // namespace urde diff --git a/Runtime/World/CFluidPlaneManager.hpp b/Runtime/World/CFluidPlaneManager.hpp index 246b6208f..39603029f 100644 --- a/Runtime/World/CFluidPlaneManager.hpp +++ b/Runtime/World/CFluidPlaneManager.hpp @@ -4,63 +4,61 @@ #include "CRippleManager.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CScriptWater; -class CFluidPlaneManager -{ - class CSplashRecord - { - float x0_time = 0.f; - TUniqueId x4_id; - public: - CSplashRecord(float time, TUniqueId id) : x0_time(time), x4_id(id) {} - void SetTime(float t) { x0_time = t; } - float GetTime() const { return x0_time; } - void SetUniqueId(TUniqueId id) { x4_id = id; } - TUniqueId GetUniqueId() const { return x4_id; } - }; +class CFluidPlaneManager { + class CSplashRecord { + float x0_time = 0.f; + TUniqueId x4_id; - CRippleManager x0_rippleManager; - rstl::reserved_vector x18_splashes; - float x11c_uvT = 0.f; - bool x120_ = false; - bool x121_ = false; + public: + CSplashRecord(float time, TUniqueId id) : x0_time(time), x4_id(id) {} + void SetTime(float t) { x0_time = t; } + float GetTime() const { return x0_time; } + void SetUniqueId(TUniqueId id) { x4_id = id; } + TUniqueId GetUniqueId() const { return x4_id; } + }; + + CRippleManager x0_rippleManager; + rstl::reserved_vector x18_splashes; + float x11c_uvT = 0.f; + bool x120_ = false; + bool x121_ = false; + + class CFluidProfile { + float x0_ = 0.f; + float x4_ = 0.f; + float x8_ = 0.f; + float xc_ = 0.f; + float x10_ = 0.f; + + public: + void Clear(); + }; + static CFluidProfile sProfile; + static void SetupRippleMap(); - class CFluidProfile - { - float x0_ = 0.f; - float x4_ = 0.f; - float x8_ = 0.f; - float xc_ = 0.f; - float x10_ = 0.f; - public: - void Clear(); - }; - static CFluidProfile sProfile; - static void SetupRippleMap(); public: - static u8 RippleValues[64][64]; - static u8 RippleMins[64]; - static u8 RippleMaxs[64]; - static boo::ObjToken RippleMapTex; + static u8 RippleValues[64][64]; + static u8 RippleMins[64]; + static u8 RippleMaxs[64]; + static boo::ObjToken RippleMapTex; - CFluidPlaneManager(); - void StartFrame(bool); - void EndFrame() { x121_ = false; } - void Update(float dt); - float GetUVT() const { return x11c_uvT; } - float GetLastRippleDeltaTime(TUniqueId rippler) const; - float GetLastSplashDeltaTime(TUniqueId splasher) const; - void CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water, - const zeus::CVector3f& pos, float factor, bool sfx); - rstl::reserved_vector& SplashRecords() { return x18_splashes; } - const CRippleManager& GetRippleManager() const { return x0_rippleManager; } - CRippleManager& RippleManager() { return x0_rippleManager; } + CFluidPlaneManager(); + void StartFrame(bool); + void EndFrame() { x121_ = false; } + void Update(float dt); + float GetUVT() const { return x11c_uvT; } + float GetLastRippleDeltaTime(TUniqueId rippler) const; + float GetLastSplashDeltaTime(TUniqueId splasher) const; + void CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water, const zeus::CVector3f& pos, + float factor, bool sfx); + rstl::reserved_vector& SplashRecords() { return x18_splashes; } + const CRippleManager& GetRippleManager() const { return x0_rippleManager; } + CRippleManager& RippleManager() { return x0_rippleManager; } }; -} - +} // namespace urde diff --git a/Runtime/World/CFluidUVMotion.cpp b/Runtime/World/CFluidUVMotion.cpp index 2171e6182..dcb45f87f 100644 --- a/Runtime/World/CFluidUVMotion.cpp +++ b/Runtime/World/CFluidUVMotion.cpp @@ -1,78 +1,62 @@ #include "CFluidUVMotion.hpp" #include "zeus/Math.hpp" -namespace urde -{ +namespace urde { -CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation, - const CFluidUVMotion::SFluidLayerMotion& colorLayer, +CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation, const CFluidUVMotion::SFluidLayerMotion& colorLayer, const CFluidUVMotion::SFluidLayerMotion& pattern1Layer, const CFluidUVMotion::SFluidLayerMotion& pattern2Layer) -: x4c_ooTimeToWrap(1.f / timeToWrap) -, x50_orientation(orientation) -{ - x0_fluidLayers.resize(3); - x0_fluidLayers[0] = colorLayer; - x0_fluidLayers[1] = pattern1Layer; - x0_fluidLayers[2] = pattern2Layer; +: x4c_ooTimeToWrap(1.f / timeToWrap), x50_orientation(orientation) { + x0_fluidLayers.resize(3); + x0_fluidLayers[0] = colorLayer; + x0_fluidLayers[1] = pattern1Layer; + x0_fluidLayers[2] = pattern2Layer; } CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation) -: x4c_ooTimeToWrap(1.f / timeToWrap), x50_orientation(orientation) -{ - x0_fluidLayers.resize(3); - x0_fluidLayers[0].x4_ooTimeToWrap = 0.001f; - x0_fluidLayers[1].x4_ooTimeToWrap = 0.33333334f; - x0_fluidLayers[2].x4_ooTimeToWrap = 0.2f; - x0_fluidLayers[2].x8_orientation = 0.78539819f; +: x4c_ooTimeToWrap(1.f / timeToWrap), x50_orientation(orientation) { + x0_fluidLayers.resize(3); + x0_fluidLayers[0].x4_ooTimeToWrap = 0.001f; + x0_fluidLayers[1].x4_ooTimeToWrap = 0.33333334f; + x0_fluidLayers[2].x4_ooTimeToWrap = 0.2f; + x0_fluidLayers[2].x8_orientation = 0.78539819f; } -void CFluidUVMotion::CalculateFluidTextureOffset(float t, float offsets[3][2]) const -{ - float totalYOffset = t * x4c_ooTimeToWrap * std::cos(x50_orientation); - float totalXOffset = t * x4c_ooTimeToWrap * std::sin(x50_orientation); +void CFluidUVMotion::CalculateFluidTextureOffset(float t, float offsets[3][2]) const { + float totalYOffset = t * x4c_ooTimeToWrap * std::cos(x50_orientation); + float totalXOffset = t * x4c_ooTimeToWrap * std::sin(x50_orientation); - for (u32 i = 0 ; i x0_fluidLayers; - float x4c_ooTimeToWrap; - float x50_orientation; -public: - CFluidUVMotion(float timeToWrap, float orientation, const SFluidLayerMotion& colorLayer, - const SFluidLayerMotion& pattern1Layer, const SFluidLayerMotion& pattern2Layer); - CFluidUVMotion(float timeToWrap, float orientation); + rstl::reserved_vector x0_fluidLayers; + float x4c_ooTimeToWrap; + float x50_orientation; - const rstl::reserved_vector& GetFluidLayers() const { return x0_fluidLayers; } - float GetOrientation() const { return x50_orientation; } - float GetOOTimeToWrapTexPage() const { return x4c_ooTimeToWrap; } - void CalculateFluidTextureOffset(float, float[3][2]) const; +public: + CFluidUVMotion(float timeToWrap, float orientation, const SFluidLayerMotion& colorLayer, + const SFluidLayerMotion& pattern1Layer, const SFluidLayerMotion& pattern2Layer); + CFluidUVMotion(float timeToWrap, float orientation); + + const rstl::reserved_vector& GetFluidLayers() const { return x0_fluidLayers; } + float GetOrientation() const { return x50_orientation; } + float GetOOTimeToWrapTexPage() const { return x4c_ooTimeToWrap; } + void CalculateFluidTextureOffset(float, float[3][2]) const; }; -} +} // namespace urde diff --git a/Runtime/World/CGameArea.cpp b/Runtime/World/CGameArea.cpp index 1f6ae60e1..9119d5b8a 100644 --- a/Runtime/World/CGameArea.cpp +++ b/Runtime/World/CGameArea.cpp @@ -8,1402 +8,1178 @@ #include "DataSpec/DNAMP1/MREA.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("CGameArea"); -CAreaRenderOctTree::CAreaRenderOctTree(const u8* buf) -: x0_buf(buf) -{ - CMemoryInStream r(x0_buf + 8, INT32_MAX); - x8_bitmapCount = r.readUint32Big(); - xc_meshCount = r.readUint32Big(); - x10_nodeCount = r.readUint32Big(); - x14_bitmapWordCount = (xc_meshCount + 31) / 32; - x18_aabb.readBoundingBoxBig(r); +CAreaRenderOctTree::CAreaRenderOctTree(const u8* buf) : x0_buf(buf) { + CMemoryInStream r(x0_buf + 8, INT32_MAX); + x8_bitmapCount = r.readUint32Big(); + xc_meshCount = r.readUint32Big(); + x10_nodeCount = r.readUint32Big(); + x14_bitmapWordCount = (xc_meshCount + 31) / 32; + x18_aabb.readBoundingBoxBig(r); - x30_bitmaps = reinterpret_cast(x0_buf + 64); - u32 wc = x14_bitmapWordCount * x8_bitmapCount; - for (u32 i=0 ; i(x30_bitmaps)[i] = hecl::SBig(x30_bitmaps[i]); + x30_bitmaps = reinterpret_cast(x0_buf + 64); + u32 wc = x14_bitmapWordCount * x8_bitmapCount; + for (u32 i = 0; i < wc; ++i) + const_cast(x30_bitmaps)[i] = hecl::SBig(x30_bitmaps[i]); - x34_indirectionTable = x30_bitmaps + wc; - x38_entries = reinterpret_cast(x34_indirectionTable + x10_nodeCount); - for (u32 i=0 ; i(x34_indirectionTable)[i] = hecl::SBig(x34_indirectionTable[i]); - Node* n = reinterpret_cast(const_cast(x38_entries) + x34_indirectionTable[i]); - n->x0_bitmapIdx = hecl::SBig(n->x0_bitmapIdx); - n->x2_flags = hecl::SBig(n->x2_flags); - if (n->x2_flags) - { - u32 childCount = n->GetChildCount(); - for (u32 c=0 ; cx4_children[c] = hecl::SBig(n->x4_children[c]); - } + x34_indirectionTable = x30_bitmaps + wc; + x38_entries = reinterpret_cast(x34_indirectionTable + x10_nodeCount); + for (u32 i = 0; i < x10_nodeCount; ++i) { + const_cast(x34_indirectionTable)[i] = hecl::SBig(x34_indirectionTable[i]); + Node* n = reinterpret_cast(const_cast(x38_entries) + x34_indirectionTable[i]); + n->x0_bitmapIdx = hecl::SBig(n->x0_bitmapIdx); + n->x2_flags = hecl::SBig(n->x2_flags); + if (n->x2_flags) { + u32 childCount = n->GetChildCount(); + for (u32 c = 0; c < childCount; ++c) + n->x4_children[c] = hecl::SBig(n->x4_children[c]); } + } } -static const u32 ChildCounts[] = { 0, 2, 2, 4, 2, 4, 4, 8 }; -u32 CAreaRenderOctTree::Node::GetChildCount() const -{ - return ChildCounts[x2_flags]; -} +static const u32 ChildCounts[] = {0, 2, 2, 4, 2, 4, 4, 8}; +u32 CAreaRenderOctTree::Node::GetChildCount() const { return ChildCounts[x2_flags]; } -zeus::CAABox CAreaRenderOctTree::Node::GetNodeBounds(const zeus::CAABox& curAABB, int idx) const -{ - zeus::CVector3f center = curAABB.center(); - switch (x2_flags) - { +zeus::CAABox CAreaRenderOctTree::Node::GetNodeBounds(const zeus::CAABox& curAABB, int idx) const { + zeus::CVector3f center = curAABB.center(); + switch (x2_flags) { + case 0: + default: + return curAABB; + case 1: + if (idx == 0) + return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), center.x(), curAABB.max.y(), curAABB.max.z()}; + else + return {center.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; + case 2: + if (idx == 0) + return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), center.y(), curAABB.max.z()}; + else + return {curAABB.min.x(), center.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; + case 3: { + switch (idx) { case 0: default: - return curAABB; + return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), center.x(), center.y(), curAABB.max.z()}; case 1: - if (idx == 0) - return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), center.x(), curAABB.max.y(), curAABB.max.z()}; - else - return {center.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; + return {center.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), center.y(), curAABB.max.z()}; case 2: - if (idx == 0) - return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), center.y(), curAABB.max.z()}; - else - return {curAABB.min.x(), center.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; + return {curAABB.min.x(), center.y(), curAABB.min.z(), center.x(), curAABB.max.y(), curAABB.max.z()}; case 3: - { - switch (idx) - { - case 0: - default: - return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), center.x(), center.y(), curAABB.max.z()}; - case 1: - return {center.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), center.y(), curAABB.max.z()}; - case 2: - return {curAABB.min.x(), center.y(), curAABB.min.z(), center.x(), curAABB.max.y(), curAABB.max.z()}; - case 3: - return {center.x(), center.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; - } - } - case 4: - if (idx == 0) - return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), center.z()}; - else - return {curAABB.min.x(), curAABB.min.y(), center.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; - case 5: - { - switch (idx) - { - case 0: - default: - return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), center.x(), curAABB.max.y(), center.z()}; - case 1: - return {center.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), center.z()}; - case 2: - return {curAABB.min.x(), curAABB.min.y(), center.z(), center.x(), curAABB.max.y(), curAABB.max.z()}; - case 3: - return {center.x(), curAABB.min.y(), center.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; - } - } - case 6: - { - switch (idx) - { - case 0: - default: - return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), center.y(), center.z()}; - case 1: - return {curAABB.min.x(), center.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), center.z()}; - case 2: - return {curAABB.min.x(), curAABB.min.y(), center.z(), curAABB.max.x(), center.y(), curAABB.max.z()}; - case 3: - return {curAABB.min.x(), center.y(), center.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; - } - } - case 7: - { - switch (idx) - { - case 0: - default: - return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), center.x(), center.y(), center.z()}; - case 1: - return {center.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), center.y(), center.z()}; - case 2: - return {curAABB.min.x(), center.y(), curAABB.min.z(), center.x(), curAABB.max.y(), center.z()}; - case 3: - return {center.x(), center.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), center.z()}; - case 4: - return {curAABB.min.x(), curAABB.min.y(), center.z(), center.x(), center.y(), curAABB.max.z()}; - case 5: - return {center.x(), curAABB.min.y(), center.z(), curAABB.max.x(), center.y(), curAABB.max.z()}; - case 6: - return {curAABB.min.x(), center.y(), center.z(), center.x(), curAABB.max.y(), curAABB.max.z()}; - case 7: - return {center.x(), center.y(), center.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; - } - } - } -} - -void CAreaRenderOctTree::Node::RecursiveBuildOverlaps(u32* bmpOut, - const CAreaRenderOctTree& parent, - const zeus::CAABox& curAABB, - const zeus::CAABox& testAABB) const -{ - if (testAABB.intersects(curAABB)) - { - u32 childCount = GetChildCount(); // HACK: Always return the smallest set of intersections - if (curAABB.inside(testAABB) || childCount == 0) - { - const u32* bmp = &parent.x30_bitmaps[x0_bitmapIdx * parent.x14_bitmapWordCount]; - for (u32 c=0 ; c(parent.x38_entries + parent.x34_indirectionTable[x4_children[c]])-> - RecursiveBuildOverlaps(bmpOut, parent, childAABB, testAABB); - } - } - } -} - -void CAreaRenderOctTree::FindOverlappingModels(std::vector& out, const zeus::CAABox& testAABB) const -{ - out.resize(x14_bitmapWordCount); - reinterpret_cast(x38_entries + x34_indirectionTable[0])-> - RecursiveBuildOverlaps(out.data(), *this, x18_aabb, testAABB); -} - -void CAreaRenderOctTree::FindOverlappingModels(u32* out, const zeus::CAABox& testAABB) const -{ - reinterpret_cast(x38_entries + x34_indirectionTable[0])-> - RecursiveBuildOverlaps(out, *this, x18_aabb, testAABB); -} - -void CGameArea::CAreaFog::SetCurrent() const -{ - g_Renderer->SetWorldFog(x0_fogMode, x4_rangeCur[0], x4_rangeCur[1], x1c_colorCur); -} - -void CGameArea::CAreaFog::Update(float dt) -{ - if (x0_fogMode == ERglFogMode::None) - return; - if (x1c_colorCur == x28_colorTarget && x4_rangeCur == xc_rangeTarget) - return; - - float colorDelta = x34_colorDelta * dt; - zeus::CVector2f rangeDelta = x14_rangeDelta * dt; - - for (u32 i=0 ; i<3 ; ++i) - { - float delta = x28_colorTarget[i] - x1c_colorCur[i]; - if (std::fabs(delta) <= colorDelta) - { - x1c_colorCur[i] = float(x28_colorTarget[i]); - } - else - { - if (delta < 0.f) - x1c_colorCur[i] -= colorDelta; - else - x1c_colorCur[i] += colorDelta; - } - } - - for (u32 i=0 ; i<2 ; ++i) - { - float delta = xc_rangeTarget[i] - x4_rangeCur[i]; - if (std::fabs(delta) <= rangeDelta[i]) - { - x4_rangeCur[i] = float(xc_rangeTarget[i]); - } - else - { - if (delta < 0.f) - x4_rangeCur[i] -= rangeDelta[i]; - else - x4_rangeCur[i] += rangeDelta[i]; - } - } -} - -void CGameArea::CAreaFog::RollFogOut(float rangeDelta, float colorDelta, const zeus::CColor& color) -{ - x14_rangeDelta = {rangeDelta, rangeDelta * 2.f}; - xc_rangeTarget = {4096.f, 4096.f}; - x34_colorDelta = colorDelta; - x28_colorTarget = color; -} - -void CGameArea::CAreaFog::FadeFog(ERglFogMode mode, - const zeus::CColor& color, const zeus::CVector2f& vec1, - float speed, const zeus::CVector2f& vec2) -{ - if (x0_fogMode == ERglFogMode::None) - { - x1c_colorCur = color; - x28_colorTarget = color; - x4_rangeCur = {vec1[1], vec1[1]}; - xc_rangeTarget = vec1; + return {center.x(), center.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; } + } + case 4: + if (idx == 0) + return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), center.z()}; else - { - x28_colorTarget = color; - xc_rangeTarget = vec1; + return {curAABB.min.x(), curAABB.min.y(), center.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; + case 5: { + switch (idx) { + case 0: + default: + return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), center.x(), curAABB.max.y(), center.z()}; + case 1: + return {center.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), center.z()}; + case 2: + return {curAABB.min.x(), curAABB.min.y(), center.z(), center.x(), curAABB.max.y(), curAABB.max.z()}; + case 3: + return {center.x(), curAABB.min.y(), center.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; } - x0_fogMode = mode; - x34_colorDelta = speed; - x14_rangeDelta = vec2; + } + case 6: { + switch (idx) { + case 0: + default: + return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), center.y(), center.z()}; + case 1: + return {curAABB.min.x(), center.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), center.z()}; + case 2: + return {curAABB.min.x(), curAABB.min.y(), center.z(), curAABB.max.x(), center.y(), curAABB.max.z()}; + case 3: + return {curAABB.min.x(), center.y(), center.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; + } + } + case 7: { + switch (idx) { + case 0: + default: + return {curAABB.min.x(), curAABB.min.y(), curAABB.min.z(), center.x(), center.y(), center.z()}; + case 1: + return {center.x(), curAABB.min.y(), curAABB.min.z(), curAABB.max.x(), center.y(), center.z()}; + case 2: + return {curAABB.min.x(), center.y(), curAABB.min.z(), center.x(), curAABB.max.y(), center.z()}; + case 3: + return {center.x(), center.y(), curAABB.min.z(), curAABB.max.x(), curAABB.max.y(), center.z()}; + case 4: + return {curAABB.min.x(), curAABB.min.y(), center.z(), center.x(), center.y(), curAABB.max.z()}; + case 5: + return {center.x(), curAABB.min.y(), center.z(), curAABB.max.x(), center.y(), curAABB.max.z()}; + case 6: + return {curAABB.min.x(), center.y(), center.z(), center.x(), curAABB.max.y(), curAABB.max.z()}; + case 7: + return {center.x(), center.y(), center.z(), curAABB.max.x(), curAABB.max.y(), curAABB.max.z()}; + } + } + } } -void CGameArea::CAreaFog::SetFogExplicit(ERglFogMode mode, const zeus::CColor& color, const zeus::CVector2f& range) -{ - x0_fogMode = mode; +void CAreaRenderOctTree::Node::RecursiveBuildOverlaps(u32* bmpOut, const CAreaRenderOctTree& parent, + const zeus::CAABox& curAABB, const zeus::CAABox& testAABB) const { + if (testAABB.intersects(curAABB)) { + u32 childCount = GetChildCount(); // HACK: Always return the smallest set of intersections + if (curAABB.inside(testAABB) || childCount == 0) { + const u32* bmp = &parent.x30_bitmaps[x0_bitmapIdx * parent.x14_bitmapWordCount]; + for (u32 c = 0; c < parent.x14_bitmapWordCount; ++c) + bmpOut[c] |= bmp[c]; + } else { + for (u32 c = 0; c < childCount; ++c) { + zeus::CAABox childAABB = GetNodeBounds(curAABB, c); + reinterpret_cast(parent.x38_entries + parent.x34_indirectionTable[x4_children[c]]) + ->RecursiveBuildOverlaps(bmpOut, parent, childAABB, testAABB); + } + } + } +} + +void CAreaRenderOctTree::FindOverlappingModels(std::vector& out, const zeus::CAABox& testAABB) const { + out.resize(x14_bitmapWordCount); + reinterpret_cast(x38_entries + x34_indirectionTable[0]) + ->RecursiveBuildOverlaps(out.data(), *this, x18_aabb, testAABB); +} + +void CAreaRenderOctTree::FindOverlappingModels(u32* out, const zeus::CAABox& testAABB) const { + reinterpret_cast(x38_entries + x34_indirectionTable[0]) + ->RecursiveBuildOverlaps(out, *this, x18_aabb, testAABB); +} + +void CGameArea::CAreaFog::SetCurrent() const { + g_Renderer->SetWorldFog(x0_fogMode, x4_rangeCur[0], x4_rangeCur[1], x1c_colorCur); +} + +void CGameArea::CAreaFog::Update(float dt) { + if (x0_fogMode == ERglFogMode::None) + return; + if (x1c_colorCur == x28_colorTarget && x4_rangeCur == xc_rangeTarget) + return; + + float colorDelta = x34_colorDelta * dt; + zeus::CVector2f rangeDelta = x14_rangeDelta * dt; + + for (u32 i = 0; i < 3; ++i) { + float delta = x28_colorTarget[i] - x1c_colorCur[i]; + if (std::fabs(delta) <= colorDelta) { + x1c_colorCur[i] = float(x28_colorTarget[i]); + } else { + if (delta < 0.f) + x1c_colorCur[i] -= colorDelta; + else + x1c_colorCur[i] += colorDelta; + } + } + + for (u32 i = 0; i < 2; ++i) { + float delta = xc_rangeTarget[i] - x4_rangeCur[i]; + if (std::fabs(delta) <= rangeDelta[i]) { + x4_rangeCur[i] = float(xc_rangeTarget[i]); + } else { + if (delta < 0.f) + x4_rangeCur[i] -= rangeDelta[i]; + else + x4_rangeCur[i] += rangeDelta[i]; + } + } +} + +void CGameArea::CAreaFog::RollFogOut(float rangeDelta, float colorDelta, const zeus::CColor& color) { + x14_rangeDelta = {rangeDelta, rangeDelta * 2.f}; + xc_rangeTarget = {4096.f, 4096.f}; + x34_colorDelta = colorDelta; + x28_colorTarget = color; +} + +void CGameArea::CAreaFog::FadeFog(ERglFogMode mode, const zeus::CColor& color, const zeus::CVector2f& vec1, float speed, + const zeus::CVector2f& vec2) { + if (x0_fogMode == ERglFogMode::None) { x1c_colorCur = color; x28_colorTarget = color; - x4_rangeCur = range; - xc_rangeTarget = range; + x4_rangeCur = {vec1[1], vec1[1]}; + xc_rangeTarget = vec1; + } else { + x28_colorTarget = color; + xc_rangeTarget = vec1; + } + x0_fogMode = mode; + x34_colorDelta = speed; + x14_rangeDelta = vec2; } -bool CGameArea::CAreaFog::IsFogDisabled() const -{ - return x0_fogMode == ERglFogMode::None; +void CGameArea::CAreaFog::SetFogExplicit(ERglFogMode mode, const zeus::CColor& color, const zeus::CVector2f& range) { + x0_fogMode = mode; + x1c_colorCur = color; + x28_colorTarget = color; + x4_rangeCur = range; + xc_rangeTarget = range; } -void CGameArea::CAreaFog::DisableFog() -{ - x0_fogMode = ERglFogMode::None; +bool CGameArea::CAreaFog::IsFogDisabled() const { return x0_fogMode == ERglFogMode::None; } + +void CGameArea::CAreaFog::DisableFog() { x0_fogMode = ERglFogMode::None; } + +static std::vector ReadDependencyList(CInputStream& in) { + std::vector ret; + u32 count = in.readUint32Big(); + ret.reserve(count); + for (u32 i = 0; i < count; ++i) { + ret.emplace_back(); + ret.back().readMLVL(in); + } + return ret; } -static std::vector ReadDependencyList(CInputStream& in) -{ - std::vector ret; - u32 count = in.readUint32Big(); - ret.reserve(count); - for (u32 i=0 ; i, s32> GetScriptingMemoryAlways(const IGameArea& area) { + SObjectTag tag = {SBIG('MREA'), area.IGetAreaAssetId()}; + std::unique_ptr data = g_ResFactory->LoadNewResourcePartSync(tag, 0, 96); -std::pair, s32> GetScriptingMemoryAlways(const IGameArea& area) -{ - SObjectTag tag = {SBIG('MREA'), area.IGetAreaAssetId()}; - std::unique_ptr data = g_ResFactory->LoadNewResourcePartSync(tag, 0, 96); - - if (*reinterpret_cast(data.get()) != SBIG(0xDEADBEEF)) - return {}; - - SMREAHeader header; - CMemoryInStream r(data.get() + 4, 96 - 4); - u32 version = r.readUint32Big(); - if (!(version & 0x10000)) - Log.report(logvisor::Fatal, "Attempted to load non-URDE MREA"); - - version &= ~0x10000; - header.version = (version >= 12 && version <= 15) ? version : 0; - if (!header.version) - return {}; - - header.xf.read34RowMajor(r); - header.modelCount = r.readUint32Big(); - header.secCount = r.readUint32Big(); - header.geomSecIdx = r.readUint32Big(); - header.sclySecIdx = r.readUint32Big(); - header.collisionSecIdx = r.readUint32Big(); - header.unkSecIdx = r.readUint32Big(); - header.lightSecIdx = r.readUint32Big(); - header.visiSecIdx = r.readUint32Big(); - header.pathSecIdx = r.readUint32Big(); - header.arotSecIdx = r.readUint32Big(); - - u32 dataLen = ROUND_UP_32(header.secCount * 4); - - data = g_ResFactory->LoadNewResourcePartSync(tag, 96, dataLen); - - r = CMemoryInStream(data.get(), dataLen); - - std::vector secSizes(header.secCount); - u32 lastSize; - for (u32 i = 0; i < header.secCount; ++i) - { - lastSize = r.readUint32Big(); - secSizes.push_back(lastSize); - } - - // TODO: Finish + if (*reinterpret_cast(data.get()) != SBIG(0xDEADBEEF)) return {}; + + SMREAHeader header; + CMemoryInStream r(data.get() + 4, 96 - 4); + u32 version = r.readUint32Big(); + if (!(version & 0x10000)) + Log.report(logvisor::Fatal, "Attempted to load non-URDE MREA"); + + version &= ~0x10000; + header.version = (version >= 12 && version <= 15) ? version : 0; + if (!header.version) + return {}; + + header.xf.read34RowMajor(r); + header.modelCount = r.readUint32Big(); + header.secCount = r.readUint32Big(); + header.geomSecIdx = r.readUint32Big(); + header.sclySecIdx = r.readUint32Big(); + header.collisionSecIdx = r.readUint32Big(); + header.unkSecIdx = r.readUint32Big(); + header.lightSecIdx = r.readUint32Big(); + header.visiSecIdx = r.readUint32Big(); + header.pathSecIdx = r.readUint32Big(); + header.arotSecIdx = r.readUint32Big(); + + u32 dataLen = ROUND_UP_32(header.secCount * 4); + + data = g_ResFactory->LoadNewResourcePartSync(tag, 96, dataLen); + + r = CMemoryInStream(data.get(), dataLen); + + std::vector secSizes(header.secCount); + u32 lastSize; + for (u32 i = 0; i < header.secCount; ++i) { + lastSize = r.readUint32Big(); + secSizes.push_back(lastSize); + } + + // TODO: Finish + return {}; } -CDummyGameArea::CDummyGameArea(CInputStream& in, int idx, int mlvlVersion) -{ - x8_nameSTRG = in.readUint32Big(); - x14_transform.read34RowMajor(in); - zeus::CAABox aabb; - aabb.readBoundingBoxBig(in); - xc_mrea = in.readUint32Big(); - if (mlvlVersion > 15) - x10_areaId = in.readUint32Big(); +CDummyGameArea::CDummyGameArea(CInputStream& in, int idx, int mlvlVersion) { + x8_nameSTRG = in.readUint32Big(); + x14_transform.read34RowMajor(in); + zeus::CAABox aabb; + aabb.readBoundingBoxBig(in); + xc_mrea = in.readUint32Big(); + if (mlvlVersion > 15) + x10_areaId = in.readUint32Big(); - u32 attachAreaCount = in.readUint32Big(); - x44_attachedAreaIndices.reserve(attachAreaCount); - for (u32 i=0 ; i 13) - { - u32 depCount = in.readUint32Big(); - for (u32 i=0 ; i 13) { + u32 depCount = in.readUint32Big(); + for (u32 i = 0; i < depCount; ++i) + in.readUint32Big(); + } - u32 dockCount = in.readUint32Big(); - x54_docks.reserve(dockCount); - for (u32 i=0 ; i, s32> CDummyGameArea::IGetScriptingMemoryAlways() const -{ - return GetScriptingMemoryAlways(*this); +std::pair, s32> CDummyGameArea::IGetScriptingMemoryAlways() const { + return GetScriptingMemoryAlways(*this); } -TAreaId CDummyGameArea::IGetAreaId() const -{ - return x10_areaId; +TAreaId CDummyGameArea::IGetAreaId() const { return x10_areaId; } + +CAssetId CDummyGameArea::IGetAreaAssetId() const { return xc_mrea; } + +bool CDummyGameArea::IIsActive() const { return true; } + +TAreaId CDummyGameArea::IGetAttachedAreaId(int idx) const { return x44_attachedAreaIndices[idx]; } + +u32 CDummyGameArea::IGetNumAttachedAreas() const { return x44_attachedAreaIndices.size(); } + +CAssetId CDummyGameArea::IGetStringTableAssetId() const { return x8_nameSTRG; } + +const zeus::CTransform& CDummyGameArea::IGetTM() const { return x14_transform; } + +CGameArea::CGameArea(CInputStream& in, int idx, int mlvlVersion) : x4_selfIdx(idx) { + xf0_24_postConstructed = false; + xf0_25_active = true; + xf0_26_tokensReady = false; + xf0_27_loadPaused = false; + xf0_28_validated = false; + x8_nameSTRG = in.readUint32Big(); + xc_transform.read34RowMajor(in); + x3c_invTransform = xc_transform.inverse(); + x6c_aabb.readBoundingBoxBig(in); + + x84_mrea = in.readUint32Big(); + if (mlvlVersion > 15) + x88_areaId = in.readInt32Big(); + else + x88_areaId = -1; + + u32 attachedCount = in.readUint32Big(); + x8c_attachedAreaIndices.reserve(attachedCount); + for (u32 i = 0; i < attachedCount; ++i) + x8c_attachedAreaIndices.push_back(in.readUint16Big()); + + x9c_deps1 = ::urde::ReadDependencyList(in); + xac_deps2 = ::urde::ReadDependencyList(in); + + zeus::CAABox aabb = x6c_aabb.getTransformedAABox(xc_transform); + x6c_aabb = aabb; + + if (mlvlVersion > 13) { + u32 depCount = in.readUint32Big(); + xbc_layerDepOffsets.reserve(depCount); + for (u32 i = 0; i < depCount; ++i) + xbc_layerDepOffsets.push_back(in.readUint32Big()); + } + + u32 dockCount = in.readUint32Big(); + xcc_docks.reserve(dockCount); + for (u32 i = 0; i < dockCount; ++i) + xcc_docks.push_back({in, xc_transform}); + + ClearTokenList(); + + for (CToken& tok : xdc_tokens) + xec_totalResourcesSize += g_ResFactory->ResourceSize(*tok.GetObjectTag()); + + xec_totalResourcesSize += g_ResFactory->ResourceSize(SObjectTag{FOURCC('MREA'), x84_mrea}); } -CAssetId CDummyGameArea::IGetAreaAssetId() const -{ - return xc_mrea; +CGameArea::CGameArea(CAssetId mreaId) : x84_mrea(mreaId) { + xf0_24_postConstructed = false; + xf0_25_active = false; + xf0_26_tokensReady = false; + xf0_27_loadPaused = false; + xf0_28_validated = false; + + while (StartStreamingMainArea()) + for (auto& req : xf8_loadTransactions) + req->WaitUntilComplete(); + + SMREAHeader header = VerifyHeader(); + x12c_postConstructed->x4c_insts.resize(header.modelCount); + + FillInStaticGeometry(false); + + CBooModel::SetDummyTextures(true); + CBooModel::EnableShadowMaps(g_Renderer->x220_sphereRamp.get(), zeus::CTransform::Identity()); + CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState(); + zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix; + zeus::CTransform backupModel = CGraphics::g_GXModelMatrix; + CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -2048.f, 0.f)); + CGraphics::SetOrtho(-2048.f, 2048.f, 2048.f, -2048.f, 0.f, 4096.f); + CModelFlags defaultFlags; + for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) { + CGraphics::SetModelMatrix(zeus::CTransform::Translate(-inst.x34_aabb.center())); + inst.m_instance->UpdateUniformData(defaultFlags, nullptr, nullptr); + inst.m_instance->WarmupDrawSurfaces(); + } + CGraphics::SetProjectionState(backupProj); + CGraphics::SetViewPointMatrix(backupViewPoint); + CGraphics::SetModelMatrix(backupModel); + CBooModel::DisableShadowMaps(); + CBooModel::SetDummyTextures(false); } -bool CDummyGameArea::IIsActive() const -{ +CGameArea::~CGameArea() { + for (auto& lt : xf8_loadTransactions) + lt->PostCancelRequest(); + + if (xf0_24_postConstructed) + RemoveStaticGeometry(); + else + while (!Invalidate(nullptr)) {} +} + +bool CGameArea::IsFinishedOccluding() const { + if (x12c_postConstructed->x10dc_occlusionState != EOcclusionState::Occluded) return true; + + return x12c_postConstructed->x1108_27_; } -TAreaId CDummyGameArea::IGetAttachedAreaId(int idx) const -{ - return x44_attachedAreaIndices[idx]; +std::pair, s32> CGameArea::IGetScriptingMemoryAlways() const { + return GetScriptingMemoryAlways(*this); } -u32 CDummyGameArea::IGetNumAttachedAreas() const -{ - return x44_attachedAreaIndices.size(); +bool CGameArea::IIsActive() const { return xf0_25_active; } + +TAreaId CGameArea::IGetAttachedAreaId(int idx) const { return x8c_attachedAreaIndices[idx]; } + +u32 CGameArea::IGetNumAttachedAreas() const { return x8c_attachedAreaIndices.size(); } + +CAssetId CGameArea::IGetStringTableAssetId() const { return x8_nameSTRG; } + +const zeus::CTransform& CGameArea::IGetTM() const { return xc_transform; } + +void CGameArea::SetLoadPauseState(bool paused) { + if (xf0_26_tokensReady) + return; + xf0_27_loadPaused = paused; + if (!paused) + return; + + for (CToken& tok : xdc_tokens) + if (!tok.IsLoaded()) + tok.Unlock(); } -CAssetId CDummyGameArea::IGetStringTableAssetId() const -{ - return x8_nameSTRG; +void CGameArea::SetXRaySpeedAndTarget(float f1, float f2) { + x12c_postConstructed->x112c_xraySpeed = f1; + x12c_postConstructed->x1130_xrayTarget = f2; } -const zeus::CTransform& CDummyGameArea::IGetTM() const -{ - return x14_transform; +void CGameArea::SetThermalSpeedAndTarget(float speed, float target) { + x12c_postConstructed->x1120_thermalSpeed = speed; + x12c_postConstructed->x1124_thermalTarget = target; } -CGameArea::CGameArea(CInputStream& in, int idx, int mlvlVersion) -: x4_selfIdx(idx) -{ - xf0_24_postConstructed = false; - xf0_25_active = true; - xf0_26_tokensReady = false; - xf0_27_loadPaused = false; - xf0_28_validated = false; - x8_nameSTRG = in.readUint32Big(); - xc_transform.read34RowMajor(in); - x3c_invTransform = xc_transform.inverse(); - x6c_aabb.readBoundingBoxBig(in); - - x84_mrea = in.readUint32Big(); - if (mlvlVersion > 15) - x88_areaId = in.readInt32Big(); - else - x88_areaId = -1; - - u32 attachedCount = in.readUint32Big(); - x8c_attachedAreaIndices.reserve(attachedCount); - for (u32 i=0 ; i 13) - { - u32 depCount = in.readUint32Big(); - xbc_layerDepOffsets.reserve(depCount); - for (u32 i=0 ; iResourceSize(*tok.GetObjectTag()); - - xec_totalResourcesSize += g_ResFactory->ResourceSize(SObjectTag{FOURCC('MREA'), x84_mrea}); +void CGameArea::SetWeaponWorldLighting(float speed, float target) { + x12c_postConstructed->x1134_weaponWorldLightingSpeed = speed; + x12c_postConstructed->x1138_weaponWorldLightingTarget = target; } -CGameArea::CGameArea(CAssetId mreaId) -: x84_mrea(mreaId) -{ - xf0_24_postConstructed = false; - xf0_25_active = false; - xf0_26_tokensReady = false; - xf0_27_loadPaused = false; - xf0_28_validated = false; - - while (StartStreamingMainArea()) - for (auto& req : xf8_loadTransactions) - req->WaitUntilComplete(); - - SMREAHeader header = VerifyHeader(); - x12c_postConstructed->x4c_insts.resize(header.modelCount); - - FillInStaticGeometry(false); - - CBooModel::SetDummyTextures(true); - CBooModel::EnableShadowMaps(g_Renderer->x220_sphereRamp.get(), zeus::CTransform::Identity()); - CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState(); - zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix; - zeus::CTransform backupModel = CGraphics::g_GXModelMatrix; - CGraphics::SetViewPointMatrix(zeus::CTransform::Translate(0.f, -2048.f, 0.f)); - CGraphics::SetOrtho(-2048.f, 2048.f, 2048.f, -2048.f, 0.f, 4096.f); - CModelFlags defaultFlags; - for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) - { - CGraphics::SetModelMatrix(zeus::CTransform::Translate(-inst.x34_aabb.center())); - inst.m_instance->UpdateUniformData(defaultFlags, nullptr, nullptr); - inst.m_instance->WarmupDrawSurfaces(); - } - CGraphics::SetProjectionState(backupProj); - CGraphics::SetViewPointMatrix(backupViewPoint); - CGraphics::SetModelMatrix(backupModel); - CBooModel::DisableShadowMaps(); - CBooModel::SetDummyTextures(false); +float CGameArea::GetXRayFogDistance() const { + const CScriptAreaAttributes* attrs = x12c_postConstructed->x10d8_areaAttributes; + if (attrs) + return attrs->GetXRayFogDistance(); + return 1.f; } -CGameArea::~CGameArea() -{ - for (auto& lt : xf8_loadTransactions) - lt->PostCancelRequest(); +EEnvFxType CGameArea::DoesAreaNeedEnvFx() const { + const CPostConstructed* postConstructed = GetPostConstructed(); + if (!postConstructed) + return EEnvFxType::None; - if (xf0_24_postConstructed) - RemoveStaticGeometry(); - else - while (!Invalidate(nullptr)) {} + const CScriptAreaAttributes* attrs = postConstructed->x10d8_areaAttributes; + if (!attrs) + return EEnvFxType::None; + if (postConstructed->x10dc_occlusionState == EOcclusionState::Occluded) + return EEnvFxType::None; + return attrs->GetEnvFxType(); } -bool CGameArea::IsFinishedOccluding() const -{ - if (x12c_postConstructed->x10dc_occlusionState != EOcclusionState::Occluded) - return true; +bool CGameArea::DoesAreaNeedSkyNow() const { + const CPostConstructed* postConstructed = GetPostConstructed(); + if (!postConstructed) + return false; - return x12c_postConstructed->x1108_27_; + const CScriptAreaAttributes* attrs = postConstructed->x10d8_areaAttributes; + if (!attrs) + return false; + + return attrs->GetNeedsSky(); } -std::pair, s32> CGameArea::IGetScriptingMemoryAlways() const -{ - return GetScriptingMemoryAlways(*this); +void CGameArea::UpdateFog(float dt) { + CAreaFog* fog = GetPostConstructed()->x10c4_areaFog.get(); + if (fog) + fog->Update(dt); } -bool CGameArea::IIsActive() const -{ - return xf0_25_active; +void CGameArea::OtherAreaOcclusionChanged() { + if (GetPostConstructed()->x10e0_ == 3 && GetPostConstructed()->x10dc_occlusionState == EOcclusionState::Visible) { + x12c_postConstructed->x1108_27_ = false; + } else if (GetPostConstructed()->x10dc_occlusionState == EOcclusionState::Visible) { + ReloadAllUnloadedTextures(); + } } -TAreaId CGameArea::IGetAttachedAreaId(int idx) const -{ - return x8c_attachedAreaIndices[idx]; -} +void CGameArea::PingOcclusionState() { + if (GetOcclusionState() == EOcclusionState::Occluded && GetPostConstructed()->x10e0_ < 2) { + x12c_postConstructed->x10e0_ += 1; + return; + } -u32 CGameArea::IGetNumAttachedAreas() const -{ - return x8c_attachedAreaIndices.size(); -} - -CAssetId CGameArea::IGetStringTableAssetId() const -{ - return x8_nameSTRG; -} - -const zeus::CTransform& CGameArea::IGetTM() const -{ - return xc_transform; -} - -void CGameArea::SetLoadPauseState(bool paused) -{ - if (xf0_26_tokensReady) - return; - xf0_27_loadPaused = paused; - if (!paused) - return; - - for (CToken& tok : xdc_tokens) - if (!tok.IsLoaded()) - tok.Unlock(); -} - -void CGameArea::SetXRaySpeedAndTarget(float f1, float f2) -{ - x12c_postConstructed->x112c_xraySpeed = f1; - x12c_postConstructed->x1130_xrayTarget = f2; -} - -void CGameArea::SetThermalSpeedAndTarget(float speed, float target) -{ - x12c_postConstructed->x1120_thermalSpeed = speed; - x12c_postConstructed->x1124_thermalTarget = target; -} - -void CGameArea::SetWeaponWorldLighting(float speed, float target) -{ - x12c_postConstructed->x1134_weaponWorldLightingSpeed = speed; - x12c_postConstructed->x1138_weaponWorldLightingTarget = target; -} - -float CGameArea::GetXRayFogDistance() const -{ - const CScriptAreaAttributes* attrs = x12c_postConstructed->x10d8_areaAttributes; - if (attrs) - return attrs->GetXRayFogDistance(); - return 1.f; -} - -EEnvFxType CGameArea::DoesAreaNeedEnvFx() const -{ - const CPostConstructed* postConstructed = GetPostConstructed(); - if (!postConstructed) - return EEnvFxType::None; - - const CScriptAreaAttributes* attrs = postConstructed->x10d8_areaAttributes; - if (!attrs) - return EEnvFxType::None; - if (postConstructed->x10dc_occlusionState == EOcclusionState::Occluded) - return EEnvFxType::None; - return attrs->GetEnvFxType(); -} - -bool CGameArea::DoesAreaNeedSkyNow() const -{ - const CPostConstructed* postConstructed = GetPostConstructed(); - if (!postConstructed) - return false; - - const CScriptAreaAttributes* attrs = postConstructed->x10d8_areaAttributes; - if (!attrs) - return false; - - return attrs->GetNeedsSky(); -} - -void CGameArea::UpdateFog(float dt) -{ - CAreaFog* fog = GetPostConstructed()->x10c4_areaFog.get(); - if (fog) - fog->Update(dt); -} - -void CGameArea::OtherAreaOcclusionChanged() -{ - if (GetPostConstructed()->x10e0_ == 3 && GetPostConstructed()->x10dc_occlusionState == EOcclusionState::Visible) - { - x12c_postConstructed->x1108_27_ = false; - } - else if (GetPostConstructed()->x10dc_occlusionState == EOcclusionState::Visible) - { - ReloadAllUnloadedTextures(); - } -} - -void CGameArea::PingOcclusionState() -{ - if (GetOcclusionState() == EOcclusionState::Occluded && GetPostConstructed()->x10e0_ < 2) - { - x12c_postConstructed->x10e0_ += 1; - return; - } - - x12c_postConstructed->x10e0_ = 3; - if (!x12c_postConstructed->x1108_27_) - { - bool unloaded = true; - bool transferred = true; + x12c_postConstructed->x10e0_ = 3; + if (!x12c_postConstructed->x1108_27_) { + bool unloaded = true; + bool transferred = true; #if 0 unloaded = UnloadAllloadedTextures(); transferred = TransferTokens(); #endif - if (unloaded && transferred) - x12c_postConstructed->x1108_27_ = true; + if (unloaded && transferred) + x12c_postConstructed->x1108_27_ = true; + } + x12c_postConstructed->x1108_26_ = true; +} + +void CGameArea::PreRender() { + if (!xf0_24_postConstructed) + return; + + if (x12c_postConstructed->x1108_28_occlusionPinged) + x12c_postConstructed->x1108_28_occlusionPinged = false; + else + PingOcclusionState(); +} + +void CGameArea::UpdateThermalVisor(float dt) { + if (x12c_postConstructed->x1120_thermalSpeed == 0.f) + return; + + float influence = x12c_postConstructed->x111c_thermalCurrent; + + float delta = x12c_postConstructed->x1120_thermalSpeed * dt; + if (std::fabs(x12c_postConstructed->x1124_thermalTarget - x12c_postConstructed->x111c_thermalCurrent) < delta) { + influence = x12c_postConstructed->x1124_thermalTarget; + x12c_postConstructed->x1120_thermalSpeed = 0.f; + } else if (x12c_postConstructed->x1124_thermalTarget < influence) + influence -= delta; + else + influence += delta; + + x12c_postConstructed->x111c_thermalCurrent = influence; +} + +void CGameArea::UpdateWeaponWorldLighting(float dt) { + float newLightingLevel = x12c_postConstructed->x1128_worldLightingLevel; + if (x12c_postConstructed->x112c_xraySpeed != 0.f) { + float speed = dt * x12c_postConstructed->x112c_xraySpeed; + if (std::fabs(x12c_postConstructed->x1130_xrayTarget - newLightingLevel) < speed) { + newLightingLevel = x12c_postConstructed->x1130_xrayTarget; + x12c_postConstructed->x1134_weaponWorldLightingSpeed = 0.f; + } else if (x12c_postConstructed->x1130_xrayTarget < newLightingLevel) { + newLightingLevel -= speed; + } else { + newLightingLevel += speed; } + } + + if (x12c_postConstructed->x1134_weaponWorldLightingSpeed != 0.f) { + float newWeaponWorldLightingLevel = x12c_postConstructed->x1128_worldLightingLevel; + float speed = dt * x12c_postConstructed->x1134_weaponWorldLightingSpeed; + if (std::fabs(x12c_postConstructed->x1138_weaponWorldLightingTarget - newLightingLevel) < speed) { + newWeaponWorldLightingLevel = x12c_postConstructed->x1138_weaponWorldLightingTarget; + x12c_postConstructed->x1134_weaponWorldLightingSpeed = 0.f; + } else if (x12c_postConstructed->x1138_weaponWorldLightingTarget < newWeaponWorldLightingLevel) { + newWeaponWorldLightingLevel -= speed; + } else { + newWeaponWorldLightingLevel += speed; + } + if (x12c_postConstructed->x112c_xraySpeed != 0.f) { + newLightingLevel = std::min(newLightingLevel, newWeaponWorldLightingLevel); + } else { + newLightingLevel = newWeaponWorldLightingLevel; + } + } + + if (std::fabs(x12c_postConstructed->x1128_worldLightingLevel - newLightingLevel) >= 0.00001f) { + x12c_postConstructed->x1128_worldLightingLevel = newLightingLevel; + for (CEntity* ent : *x12c_postConstructed->x10c0_areaObjs) + if (TCastToPtr act = ent) + act->SetWorldLightingDirty(true); + } +} + +void CGameArea::AliveUpdate(float dt) { + if (x12c_postConstructed->x10dc_occlusionState == EOcclusionState::Occluded) + x12c_postConstructed->x10e4_occludedTime += dt; + else + x12c_postConstructed->x10e4_occludedTime = 0.f; + UpdateFog(dt); + UpdateThermalVisor(dt); + UpdateWeaponWorldLighting(dt); +} + +void CGameArea::SetOcclusionState(EOcclusionState state) { + if (!xf0_24_postConstructed || x12c_postConstructed->x10dc_occlusionState == state) + return; + + if (state != EOcclusionState::Occluded) { + ReloadAllUnloadedTextures(); + AddStaticGeometry(); + } else { x12c_postConstructed->x1108_26_ = true; + x12c_postConstructed->x1108_27_ = false; + RemoveStaticGeometry(); + } } -void CGameArea::PreRender() -{ - if (!xf0_24_postConstructed) - return; - - if (x12c_postConstructed->x1108_28_occlusionPinged) - x12c_postConstructed->x1108_28_occlusionPinged = false; - else - PingOcclusionState(); +void CGameArea::RemoveStaticGeometry() { + if (!xf0_24_postConstructed || !x12c_postConstructed || + x12c_postConstructed->x10dc_occlusionState == EOcclusionState::Occluded) + return; + x12c_postConstructed->x10e0_ = 0; + x12c_postConstructed->x10dc_occlusionState = EOcclusionState::Occluded; + g_Renderer->RemoveStaticGeometry(&x12c_postConstructed->x4c_insts); } -void CGameArea::UpdateThermalVisor(float dt) -{ - if (x12c_postConstructed->x1120_thermalSpeed == 0.f) - return; - - float influence = x12c_postConstructed->x111c_thermalCurrent; - - float delta = x12c_postConstructed->x1120_thermalSpeed * dt; - if (std::fabs(x12c_postConstructed->x1124_thermalTarget - - x12c_postConstructed->x111c_thermalCurrent) < delta) - { - influence = x12c_postConstructed->x1124_thermalTarget; - x12c_postConstructed->x1120_thermalSpeed = 0.f; - } - else if (x12c_postConstructed->x1124_thermalTarget < influence) - influence -= delta; - else - influence += delta; - - x12c_postConstructed->x111c_thermalCurrent = influence; -} - -void CGameArea::UpdateWeaponWorldLighting(float dt) -{ - float newLightingLevel = x12c_postConstructed->x1128_worldLightingLevel; - if (x12c_postConstructed->x112c_xraySpeed != 0.f) - { - float speed = dt * x12c_postConstructed->x112c_xraySpeed; - if (std::fabs(x12c_postConstructed->x1130_xrayTarget - newLightingLevel) < speed) - { - newLightingLevel = x12c_postConstructed->x1130_xrayTarget; - x12c_postConstructed->x1134_weaponWorldLightingSpeed = 0.f; - } - else if (x12c_postConstructed->x1130_xrayTarget < newLightingLevel) - { - newLightingLevel -= speed; - } - else - { - newLightingLevel += speed; - } - } - - if (x12c_postConstructed->x1134_weaponWorldLightingSpeed != 0.f) - { - float newWeaponWorldLightingLevel = x12c_postConstructed->x1128_worldLightingLevel; - float speed = dt * x12c_postConstructed->x1134_weaponWorldLightingSpeed; - if (std::fabs(x12c_postConstructed->x1138_weaponWorldLightingTarget - newLightingLevel) < speed) - { - newWeaponWorldLightingLevel = x12c_postConstructed->x1138_weaponWorldLightingTarget; - x12c_postConstructed->x1134_weaponWorldLightingSpeed = 0.f; - } - else if (x12c_postConstructed->x1138_weaponWorldLightingTarget < newWeaponWorldLightingLevel) - { - newWeaponWorldLightingLevel -= speed; - } - else - { - newWeaponWorldLightingLevel += speed; - } - if (x12c_postConstructed->x112c_xraySpeed != 0.f) - { - newLightingLevel = std::min(newLightingLevel, newWeaponWorldLightingLevel); - } - else - { - newLightingLevel = newWeaponWorldLightingLevel; - } - } - - if (std::fabs(x12c_postConstructed->x1128_worldLightingLevel - newLightingLevel) >= 0.00001f) - { - x12c_postConstructed->x1128_worldLightingLevel = newLightingLevel; - for (CEntity* ent : *x12c_postConstructed->x10c0_areaObjs) - if (TCastToPtr act = ent) - act->SetWorldLightingDirty(true); - } -} - -void CGameArea::AliveUpdate(float dt) -{ - if (x12c_postConstructed->x10dc_occlusionState == EOcclusionState::Occluded) - x12c_postConstructed->x10e4_occludedTime += dt; - else - x12c_postConstructed->x10e4_occludedTime = 0.f; - UpdateFog(dt); - UpdateThermalVisor(dt); - UpdateWeaponWorldLighting(dt); -} - -void CGameArea::SetOcclusionState(EOcclusionState state) -{ - if (!xf0_24_postConstructed || x12c_postConstructed->x10dc_occlusionState == state) - return; - - if (state != EOcclusionState::Occluded) - { - ReloadAllUnloadedTextures(); - AddStaticGeometry(); - } - else - { - x12c_postConstructed->x1108_26_ = true; - x12c_postConstructed->x1108_27_ = false; - RemoveStaticGeometry(); - } -} - -void CGameArea::RemoveStaticGeometry() -{ - if (!xf0_24_postConstructed || !x12c_postConstructed || - x12c_postConstructed->x10dc_occlusionState == EOcclusionState::Occluded) - return; +void CGameArea::AddStaticGeometry() { + if (x12c_postConstructed->x10dc_occlusionState != EOcclusionState::Visible) { x12c_postConstructed->x10e0_ = 0; - x12c_postConstructed->x10dc_occlusionState = EOcclusionState::Occluded; - g_Renderer->RemoveStaticGeometry(&x12c_postConstructed->x4c_insts); + x12c_postConstructed->x10dc_occlusionState = EOcclusionState::Visible; + if (!x12c_postConstructed->x1108_25_modelsConstructed) + FillInStaticGeometry(); + g_Renderer->AddStaticGeometry(&x12c_postConstructed->x4c_insts, + x12c_postConstructed->xc_octTree ? &*x12c_postConstructed->xc_octTree : nullptr, + x4_selfIdx, &x12c_postConstructed->m_materialSet); + } } -void CGameArea::AddStaticGeometry() -{ - if (x12c_postConstructed->x10dc_occlusionState != EOcclusionState::Visible) - { - x12c_postConstructed->x10e0_ = 0; - x12c_postConstructed->x10dc_occlusionState = EOcclusionState::Visible; - if (!x12c_postConstructed->x1108_25_modelsConstructed) - FillInStaticGeometry(); - g_Renderer->AddStaticGeometry(&x12c_postConstructed->x4c_insts, - x12c_postConstructed->xc_octTree ? - &*x12c_postConstructed->xc_octTree : nullptr, - x4_selfIdx, &x12c_postConstructed->m_materialSet); - } +EChain CGameArea::SetChain(CGameArea* next, EChain setChain) { + if (x138_curChain == setChain) + return x138_curChain; + + if (x134_prev) + x134_prev->x130_next = x130_next; + if (x130_next) + x130_next->x134_prev = x134_prev; + + x134_prev = nullptr; + x130_next = next; + if (next) + next->x134_prev = this; + + EChain ret = x138_curChain; + x138_curChain = setChain; + return ret; } -EChain CGameArea::SetChain(CGameArea* next, EChain setChain) -{ - if (x138_curChain == setChain) - return x138_curChain; +bool CGameArea::StartStreamingMainArea() { + if (xf0_24_postConstructed) + return false; - if (x134_prev) - x134_prev->x130_next = x130_next; - if (x130_next) - x130_next->x134_prev = x134_prev; + switch (xf4_phase) { + case EPhase::LoadHeader: { + x110_mreaSecBufs.reserve(3); + AllocNewAreaData(0, 96); + x12c_postConstructed.reset(new CPostConstructed()); + xf4_phase = EPhase::LoadSecSizes; + break; + } + case EPhase::LoadSecSizes: { + CullDeadAreaRequests(); + if (xf8_loadTransactions.size()) + break; + SMREAHeader header = VerifyHeader(); + AllocNewAreaData(x110_mreaSecBufs[0].second, ROUND_UP_32(header.secCount * 4)); + xf4_phase = EPhase::ReserveSections; + break; + } + case EPhase::ReserveSections: { + CullDeadAreaRequests(); + if (xf8_loadTransactions.size()) + break; + // x110_mreaSecBufs.reserve(GetNumPartSizes() + 2); + x124_secCount = 0; + x128_mreaDataOffset = x110_mreaSecBufs[0].second + x110_mreaSecBufs[1].second; + xf4_phase = EPhase::LoadDataSections; + break; + } + case EPhase::LoadDataSections: { + CullDeadAreaRequests(); - x134_prev = nullptr; - x130_next = next; - if (next) - next->x134_prev = this; + u32 totalSz = 0; + u32 secCount = GetNumPartSizes(); + for (u32 i = 0; i < secCount; ++i) + totalSz += hecl::SBig(reinterpret_cast(x110_mreaSecBufs[1].first.get())[i]); - EChain ret = x138_curChain; - x138_curChain = setChain; - return ret; + AllocNewAreaData(x128_mreaDataOffset, totalSz); + + m_resolvedBufs.reserve(secCount); + m_resolvedBufs.emplace_back(x110_mreaSecBufs[0].first.get(), x110_mreaSecBufs[0].second); + m_resolvedBufs.emplace_back(x110_mreaSecBufs[1].first.get(), x110_mreaSecBufs[1].second); + + u32 curOff = 0; + for (u32 i = 0; i < secCount; ++i) { + u32 size = hecl::SBig(reinterpret_cast(x110_mreaSecBufs[1].first.get())[i]); + m_resolvedBufs.emplace_back(x110_mreaSecBufs[2].first.get() + curOff, size); + curOff += size; + } + + xf4_phase = EPhase::WaitForFinish; + break; + } + case EPhase::WaitForFinish: { + CullDeadAreaRequests(); + if (xf8_loadTransactions.size()) + break; + return false; + } + default: + break; + } + + return true; } -bool CGameArea::StartStreamingMainArea() -{ - if (xf0_24_postConstructed) - return false; +void CGameArea::ReloadAllUnloadedTextures() {} - switch (xf4_phase) - { - case EPhase::LoadHeader: - { - x110_mreaSecBufs.reserve(3); - AllocNewAreaData(0, 96); - x12c_postConstructed.reset(new CPostConstructed()); - xf4_phase = EPhase::LoadSecSizes; - break; - } - case EPhase::LoadSecSizes: - { - CullDeadAreaRequests(); - if (xf8_loadTransactions.size()) - break; - SMREAHeader header = VerifyHeader(); - AllocNewAreaData(x110_mreaSecBufs[0].second, ROUND_UP_32(header.secCount * 4)); - xf4_phase = EPhase::ReserveSections; - break; - } - case EPhase::ReserveSections: - { - CullDeadAreaRequests(); - if (xf8_loadTransactions.size()) - break; - //x110_mreaSecBufs.reserve(GetNumPartSizes() + 2); - x124_secCount = 0; - x128_mreaDataOffset = x110_mreaSecBufs[0].second + x110_mreaSecBufs[1].second; - xf4_phase = EPhase::LoadDataSections; - break; - } - case EPhase::LoadDataSections: - { - CullDeadAreaRequests(); +u32 CGameArea::GetNumPartSizes() const { + return hecl::SBig(*reinterpret_cast(x110_mreaSecBufs[0].first.get() + 60)); +} - u32 totalSz = 0; - u32 secCount = GetNumPartSizes(); - for (u32 i=0 ; i(x110_mreaSecBufs[1].first.get())[i]); +void CGameArea::AllocNewAreaData(int offset, int size) { + x110_mreaSecBufs.emplace_back(std::unique_ptr(new u8[size]), size); + xf8_loadTransactions.push_back(g_ResFactory->LoadResourcePartAsync(SObjectTag{FOURCC('MREA'), x84_mrea}, offset, size, + x110_mreaSecBufs.back().first.get())); +} - AllocNewAreaData(x128_mreaDataOffset, totalSz); +bool CGameArea::Invalidate(CStateManager* mgr) { + if (!xf0_24_postConstructed) { + ClearTokenList(); - m_resolvedBufs.reserve(secCount); - m_resolvedBufs.emplace_back(x110_mreaSecBufs[0].first.get(), x110_mreaSecBufs[0].second); - m_resolvedBufs.emplace_back(x110_mreaSecBufs[1].first.get(), x110_mreaSecBufs[1].second); - - u32 curOff = 0; - for (u32 i=0 ; i(x110_mreaSecBufs[1].first.get())[i]); - m_resolvedBufs.emplace_back(x110_mreaSecBufs[2].first.get() + curOff, size); - curOff += size; - } - - xf4_phase = EPhase::WaitForFinish; - break; - } - case EPhase::WaitForFinish: - { - CullDeadAreaRequests(); - if (xf8_loadTransactions.size()) - break; - return false; - } - default: break; + for (auto it = xf8_loadTransactions.begin(); it != xf8_loadTransactions.end();) { + if (!(*it)->IsComplete()) { + (*it)->PostCancelRequest(); + ++it; + continue; + } + it = xf8_loadTransactions.erase(it); } + if (xf8_loadTransactions.size() != 0) + return false; + + x12c_postConstructed.reset(); + KillmAreaData(); return true; -} + } -void CGameArea::ReloadAllUnloadedTextures() -{ -} - -u32 CGameArea::GetNumPartSizes() const -{ - return hecl::SBig(*reinterpret_cast(x110_mreaSecBufs[0].first.get() + 60)); -} - -void CGameArea::AllocNewAreaData(int offset, int size) -{ - x110_mreaSecBufs.emplace_back(std::unique_ptr(new u8[size]), size); - xf8_loadTransactions.push_back(g_ResFactory-> - LoadResourcePartAsync(SObjectTag{FOURCC('MREA'), x84_mrea}, offset, size, - x110_mreaSecBufs.back().first.get())); -} - -bool CGameArea::Invalidate(CStateManager* mgr) -{ - if (!xf0_24_postConstructed) - { - ClearTokenList(); - - for (auto it = xf8_loadTransactions.begin(); it != xf8_loadTransactions.end(); ) - { - if (!(*it)->IsComplete()) - { - (*it)->PostCancelRequest(); - ++it; - continue; - } - it = xf8_loadTransactions.erase(it); - } - if (xf8_loadTransactions.size() != 0) - return false; - - x12c_postConstructed.reset(); - KillmAreaData(); - - return true; - } - - if (mgr) - mgr->PrepareAreaUnload(GetAreaId()); + if (mgr) + mgr->PrepareAreaUnload(GetAreaId()); #if 0 dword_805a8eb0 -= GetPostConstructedSize(); #endif - RemoveStaticGeometry(); - x12c_postConstructed.reset(); - xf0_24_postConstructed = false; - xf0_28_validated = false; - xf4_phase = EPhase::LoadHeader; - xf8_loadTransactions.clear(); - CullDeadAreaRequests(); - KillmAreaData(); - ClearTokenList(); - if (mgr) - mgr->AreaUnloaded(GetAreaId()); + RemoveStaticGeometry(); + x12c_postConstructed.reset(); + xf0_24_postConstructed = false; + xf0_28_validated = false; + xf4_phase = EPhase::LoadHeader; + xf8_loadTransactions.clear(); + CullDeadAreaRequests(); + KillmAreaData(); + ClearTokenList(); + if (mgr) + mgr->AreaUnloaded(GetAreaId()); - return true; + return true; } -void CGameArea::KillmAreaData() -{ - m_resolvedBufs.clear(); - x110_mreaSecBufs.clear(); +void CGameArea::KillmAreaData() { + m_resolvedBufs.clear(); + x110_mreaSecBufs.clear(); } -void CGameArea::CullDeadAreaRequests() -{ - for (auto it = xf8_loadTransactions.begin() ; it != xf8_loadTransactions.end() ;) - { - if ((*it)->IsComplete()) - { - it = xf8_loadTransactions.erase(it); - continue; - } - ++it; +void CGameArea::CullDeadAreaRequests() { + for (auto it = xf8_loadTransactions.begin(); it != xf8_loadTransactions.end();) { + if ((*it)->IsComplete()) { + it = xf8_loadTransactions.erase(it); + continue; } + ++it; + } } -void CGameArea::StartStreamIn(CStateManager& mgr) -{ - if (xf0_24_postConstructed || xf0_27_loadPaused) - return; +void CGameArea::StartStreamIn(CStateManager& mgr) { + if (xf0_24_postConstructed || xf0_27_loadPaused) + return; + VerifyTokenList(mgr); + + if (!xf0_26_tokensReady) { + u32 notLoaded = 0; + for (CToken& tok : xdc_tokens) { + tok.Lock(); + if (!tok.IsLoaded()) + ++notLoaded; + } + if (notLoaded) + return; + xf0_26_tokensReady = true; + } + + StartStreamingMainArea(); + if (xf4_phase != EPhase::WaitForFinish) + return; + CullDeadAreaRequests(); + if (xf8_loadTransactions.size()) + return; + Validate(mgr); +} + +void CGameArea::Validate(CStateManager& mgr) { + if (xf0_24_postConstructed) + return; + + while (StartStreamingMainArea()) {} + + for (auto& req : xf8_loadTransactions) + req->WaitUntilComplete(); + + if (xdc_tokens.empty()) { VerifyTokenList(mgr); + for (CToken& tok : xdc_tokens) + tok.Lock(); + for (CToken& tok : xdc_tokens) + tok.GetObj(); + xf0_26_tokensReady = true; + } - if (!xf0_26_tokensReady) - { - u32 notLoaded = 0; - for (CToken& tok : xdc_tokens) - { - tok.Lock(); - if (!tok.IsLoaded()) - ++notLoaded; - } - if (notLoaded) - return; - xf0_26_tokensReady = true; + xf8_loadTransactions.clear(); + + PostConstructArea(); + if (x4_selfIdx != kInvalidAreaId) + mgr.WorldNC()->MoveAreaToAliveChain(x4_selfIdx); + + LoadScriptObjects(mgr); + + CPVSAreaSet* pvs = x12c_postConstructed->xa0_pvs.get(); + if (pvs && x12c_postConstructed->x1108_29_pvsHasActors) { + for (int i = 0; i < pvs->GetNumActors(); ++i) { + TEditorId entId = pvs->GetEntityIdByIndex(i) | (x4_selfIdx << 16); + TUniqueId id = mgr.GetIdForScript(entId); + if (id != kInvalidUniqueId) { + CPostConstructed::MapEntry& ent = x12c_postConstructed->xa8_pvsEntityMap[id.Value()]; + ent.x0_id = i + (pvs->GetNumFeatures() - pvs->GetNumActors()); + ent.x4_uid = id; + } } + } - StartStreamingMainArea(); - if (xf4_phase != EPhase::WaitForFinish) - return; - CullDeadAreaRequests(); - if (xf8_loadTransactions.size()) - return; - Validate(mgr); + xf0_28_validated = true; + mgr.AreaLoaded(x4_selfIdx); } -void CGameArea::Validate(CStateManager& mgr) -{ - if (xf0_24_postConstructed) - return; - - while (StartStreamingMainArea()) {} - - for (auto& req : xf8_loadTransactions) - req->WaitUntilComplete(); - - if (xdc_tokens.empty()) - { - VerifyTokenList(mgr); - for (CToken& tok : xdc_tokens) - tok.Lock(); - for (CToken& tok : xdc_tokens) - tok.GetObj(); - xf0_26_tokensReady = true; +void CGameArea::LoadScriptObjects(CStateManager& mgr) { + CWorldLayerState& layerState = *mgr.LayerState(); + u32 layerCount = layerState.GetAreaLayerCount(x4_selfIdx); + std::vector objIds; + for (u32 i = 0; i < layerCount; ++i) { + if (layerState.IsLayerActive(x4_selfIdx, i)) { + auto layerBuf = GetLayerScriptBuffer(i); + CMemoryInStream r(layerBuf.first, layerBuf.second); + mgr.LoadScriptObjects(x4_selfIdx, r, objIds); } - - xf8_loadTransactions.clear(); - - PostConstructArea(); - if (x4_selfIdx != kInvalidAreaId) - mgr.WorldNC()->MoveAreaToAliveChain(x4_selfIdx); - - LoadScriptObjects(mgr); - - CPVSAreaSet* pvs = x12c_postConstructed->xa0_pvs.get(); - if (pvs && x12c_postConstructed->x1108_29_pvsHasActors) - { - for (int i=0 ; iGetNumActors() ; ++i) - { - TEditorId entId = pvs->GetEntityIdByIndex(i) | (x4_selfIdx << 16); - TUniqueId id = mgr.GetIdForScript(entId); - if (id != kInvalidUniqueId) - { - CPostConstructed::MapEntry& ent = x12c_postConstructed->xa8_pvsEntityMap[id.Value()]; - ent.x0_id = i + (pvs->GetNumFeatures() - pvs->GetNumActors()); - ent.x4_uid = id; - } - } - } - - xf0_28_validated = true; - mgr.AreaLoaded(x4_selfIdx); + } + mgr.InitScriptObjects(objIds); } -void CGameArea::LoadScriptObjects(CStateManager& mgr) -{ - CWorldLayerState& layerState = *mgr.LayerState(); - u32 layerCount = layerState.GetAreaLayerCount(x4_selfIdx); - std::vector objIds; - for (u32 i=0 ; i CGameArea::GetLayerScriptBuffer(int layer) { + if (!xf0_24_postConstructed) + return {}; + return x12c_postConstructed->x110c_layerPtrs[layer]; } -std::pair CGameArea::GetLayerScriptBuffer(int layer) -{ - if (!xf0_24_postConstructed) - return {}; - return x12c_postConstructed->x110c_layerPtrs[layer]; -} +void CGameArea::PostConstructArea() { + SMREAHeader header = VerifyHeader(); -void CGameArea::PostConstructArea() -{ - SMREAHeader header = VerifyHeader(); + auto secIt = m_resolvedBufs.begin() + 2; - auto secIt = m_resolvedBufs.begin() + 2; + /* Materials */ + ++secIt; - /* Materials */ + u32 sec = 3; + + /* Models */ + x12c_postConstructed->x4c_insts.resize(header.modelCount); + for (u32 i = 0; i < header.modelCount; ++i) { + u32 surfCount = hecl::SBig(*reinterpret_cast((secIt + 4)->first)); + secIt += 5 + surfCount; + sec += 5 + surfCount; + } + + /* Render octree */ + if (header.version == 15 && header.arotSecIdx != -1) { + x12c_postConstructed->xc_octTree.emplace(secIt->first); ++secIt; + } - u32 sec = 3; + /* Scriptable layer section */ + x12c_postConstructed->x10c8_sclyBuf = secIt->first; + x12c_postConstructed->x10d0_sclySize = secIt->second; + ++secIt; + + /* Collision section */ + std::unique_ptr collision = CAreaOctTree::MakeFromMemory(secIt->first, secIt->second); + if (collision) { + x12c_postConstructed->x0_collision = std::move(collision); + x12c_postConstructed->x8_collisionSize = secIt->second; + } + ++secIt; + + /* Unknown section */ + ++secIt; + + /* Lights section */ + if (header.version > 6) { + athena::io::MemoryReader r(secIt->first, secIt->second); + u32 magic = r.readUint32Big(); + if (magic == 0xBABEDEAD) { + u32 aCount = r.readUint32Big(); + x12c_postConstructed->x60_lightsA.reserve(aCount); + x12c_postConstructed->x70_gfxLightsA.reserve(aCount); + for (u32 i = 0; i < aCount; ++i) { + x12c_postConstructed->x60_lightsA.emplace_back(r); + x12c_postConstructed->x70_gfxLightsA.push_back(x12c_postConstructed->x60_lightsA.back().GetAsCGraphicsLight()); + } + + u32 bCount = r.readUint32Big(); + x12c_postConstructed->x80_lightsB.reserve(bCount); + x12c_postConstructed->x90_gfxLightsB.reserve(bCount); + for (u32 i = 0; i < bCount; ++i) { + x12c_postConstructed->x80_lightsB.emplace_back(r); + x12c_postConstructed->x90_gfxLightsB.push_back(x12c_postConstructed->x80_lightsB.back().GetAsCGraphicsLight()); + } + } + + ++secIt; + } + + /* PVS section */ + if (header.version > 7) { + athena::io::MemoryReader r(secIt->first, secIt->second); + u32 magic = r.readUint32Big(); + if (magic == 'VISI') { + x12c_postConstructed->x10a8_pvsVersion = r.readUint32Big(); + if (x12c_postConstructed->x10a8_pvsVersion == 2) { + x12c_postConstructed->x1108_29_pvsHasActors = r.readBool(); + x12c_postConstructed->x1108_30_ = r.readBool(); + x12c_postConstructed->xa0_pvs = + std::make_unique(secIt->first + r.position(), secIt->second - r.position()); + } + } + + ++secIt; + } + + /* Pathfinding section */ + if (header.version > 9) { + athena::io::MemoryReader r(secIt->first, secIt->second); + CAssetId pathId = r.readUint32Big(); + x12c_postConstructed->x10ac_pathToken = g_SimplePool->GetObj(SObjectTag{FOURCC('PATH'), pathId}); + x12c_postConstructed->x10bc_pathArea = x12c_postConstructed->x10ac_pathToken.GetObj(); + ++secIt; + } + + x12c_postConstructed->x10c0_areaObjs.reset(new CAreaObjectList(x4_selfIdx)); + x12c_postConstructed->x10c4_areaFog.reset(new CAreaFog()); + + xf0_24_postConstructed = true; + + /* Resolve layer pointers */ + if (x12c_postConstructed->x10c8_sclyBuf) { + athena::io::MemoryReader r(x12c_postConstructed->x10c8_sclyBuf, x12c_postConstructed->x10d0_sclySize); + u32 magic = r.readUint32Big(); + if (magic == 'SCLY') { + r.readUint32Big(); + u32 layerCount = r.readUint32Big(); + x12c_postConstructed->x110c_layerPtrs.resize(layerCount); + for (u32 l = 0; l < layerCount; ++l) + x12c_postConstructed->x110c_layerPtrs[l].second = r.readUint32Big(); + const u8* ptr = x12c_postConstructed->x10c8_sclyBuf + r.position(); + for (u32 l = 0; l < layerCount; ++l) { + x12c_postConstructed->x110c_layerPtrs[l].first = ptr; + ptr += x12c_postConstructed->x110c_layerPtrs[l].second; + } + } + } +} + +void CGameArea::FillInStaticGeometry(bool textures) { + if (!x12c_postConstructed->x4c_insts.empty()) + for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) + inst.Clear(); + + /* Materials */ + SShader& matSet = x12c_postConstructed->m_materialSet; + auto secIt = m_resolvedBufs.begin() + 2; + { + athena::io::MemoryReader r(secIt->first, secIt->second); + matSet.m_matSet.read(r); + if (textures) + CBooModel::MakeTexturesFromMats(matSet.m_matSet, matSet.x0_textures, *g_SimplePool); + matSet.InitializeLayout(nullptr); + ++secIt; + } + + CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) { + /* Shared geometry uniform buffer - one for normal render, one for shadow render */ + for (int i = 0; i < 2; ++i) + matSet.m_geomLayout->m_sharedBuffer[i] = + ctx.newDynamicBuffer(boo::BufferUse::Uniform, matSet.m_geomLayout->m_geomBufferSize, 1); /* Models */ - x12c_postConstructed->x4c_insts.resize(header.modelCount); - for (u32 i=0 ; i((secIt+4)->first)); - secIt += 5 + surfCount; - sec += 5 + surfCount; - } - - /* Render octree */ - if (header.version == 15 && header.arotSecIdx != -1) - { - x12c_postConstructed->xc_octTree.emplace(secIt->first); - ++secIt; - } - - /* Scriptable layer section */ - x12c_postConstructed->x10c8_sclyBuf = secIt->first; - x12c_postConstructed->x10d0_sclySize = secIt->second; - ++secIt; - - /* Collision section */ - std::unique_ptr collision = CAreaOctTree::MakeFromMemory(secIt->first, secIt->second); - if (collision) - { - x12c_postConstructed->x0_collision = std::move(collision); - x12c_postConstructed->x8_collisionSize = secIt->second; - } - ++secIt; - - /* Unknown section */ - ++secIt; - - /* Lights section */ - if (header.version > 6) - { + for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) { + { + DataSpec::DNAMP1::MREA::MeshHeader header; athena::io::MemoryReader r(secIt->first, secIt->second); - u32 magic = r.readUint32Big(); - if (magic == 0xBABEDEAD) - { - u32 aCount = r.readUint32Big(); - x12c_postConstructed->x60_lightsA.reserve(aCount); - x12c_postConstructed->x70_gfxLightsA.reserve(aCount); - for (u32 i=0 ; ix60_lightsA.emplace_back(r); - x12c_postConstructed->x70_gfxLightsA.push_back( - x12c_postConstructed->x60_lightsA.back().GetAsCGraphicsLight()); - } - - u32 bCount = r.readUint32Big(); - x12c_postConstructed->x80_lightsB.reserve(bCount); - x12c_postConstructed->x90_gfxLightsB.reserve(bCount); - for (u32 i=0 ; ix80_lightsB.emplace_back(r); - x12c_postConstructed->x90_gfxLightsB.push_back( - x12c_postConstructed->x80_lightsB.back().GetAsCGraphicsLight()); - } - } - + header.read(r); + inst.x0_visorFlags = header.visorFlags.flags; + inst.x4_xf = header.xfMtx; + inst.x34_aabb = zeus::CAABox(header.aabb[0], header.aabb[1]); ++secIt; - } + } - /* PVS section */ - if (header.version > 7) - { + { athena::io::MemoryReader r(secIt->first, secIt->second); - u32 magic = r.readUint32Big(); - if (magic == 'VISI') - { - x12c_postConstructed->x10a8_pvsVersion = r.readUint32Big(); - if (x12c_postConstructed->x10a8_pvsVersion == 2) - { - x12c_postConstructed->x1108_29_pvsHasActors = r.readBool(); - x12c_postConstructed->x1108_30_ = r.readBool(); - x12c_postConstructed->xa0_pvs = std::make_unique(secIt->first + r.position(), - secIt->second - r.position()); - } - } + inst.m_hmdlMeta.read(r); + } + ++secIt; - ++secIt; - } + boo::ObjToken vbo; + boo::ObjToken ibo; + vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, secIt->first, inst.m_hmdlMeta.vertStride, + inst.m_hmdlMeta.vertCount); + ++secIt; + ibo = ctx.newStaticBuffer(boo::BufferUse::Index, secIt->first, 4, inst.m_hmdlMeta.indexCount); + ++secIt; - /* Pathfinding section */ - if (header.version > 9) - { + u32 surfCount = hecl::SBig(*reinterpret_cast(secIt->first)); + inst.m_surfaces.reserve(surfCount); + inst.m_shaders.reserve(surfCount); + ++secIt; + for (u32 j = 0; j < surfCount; ++j) { + inst.m_surfaces.emplace_back(); + CBooSurface& surf = inst.m_surfaces.back(); + surf.selfIdx = j; athena::io::MemoryReader r(secIt->first, secIt->second); - CAssetId pathId = r.readUint32Big(); - x12c_postConstructed->x10ac_pathToken = g_SimplePool->GetObj(SObjectTag{FOURCC('PATH'), pathId}); - x12c_postConstructed->x10bc_pathArea = x12c_postConstructed->x10ac_pathToken.GetObj(); + surf.m_data.read(r); ++secIt; + } + + TToken nullModel; + inst.m_instance = std::make_unique(nullModel, nullptr, &inst.m_surfaces, matSet, vbo, ibo, + inst.x34_aabb, inst.x0_visorFlags, 0, nullptr); } - x12c_postConstructed->x10c0_areaObjs.reset(new CAreaObjectList(x4_selfIdx)); - x12c_postConstructed->x10c4_areaFog.reset(new CAreaFog()); + return true; + } BooTrace); - xf0_24_postConstructed = true; - - /* Resolve layer pointers */ - if (x12c_postConstructed->x10c8_sclyBuf) - { - athena::io::MemoryReader r(x12c_postConstructed->x10c8_sclyBuf, x12c_postConstructed->x10d0_sclySize); - u32 magic = r.readUint32Big(); - if (magic == 'SCLY') - { - r.readUint32Big(); - u32 layerCount = r.readUint32Big(); - x12c_postConstructed->x110c_layerPtrs.resize(layerCount); - for (u32 l=0 ; lx110c_layerPtrs[l].second = r.readUint32Big(); - const u8* ptr = x12c_postConstructed->x10c8_sclyBuf + r.position(); - for (u32 l=0 ; lx110c_layerPtrs[l].first = ptr; - ptr += x12c_postConstructed->x110c_layerPtrs[l].second; - } - } + for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) { + for (CBooSurface& surf : inst.m_surfaces) { + auto& shad = inst.m_shaders[surf.m_data.matIdx]; + if (!shad) + shad = matSet.BuildShader(inst.m_hmdlMeta, matSet.m_matSet.materials[surf.m_data.matIdx]); } + inst.m_instance->RemapMaterialData(matSet, inst.m_shaders); + } + + x12c_postConstructed->x1108_25_modelsConstructed = true; } -void CGameArea::FillInStaticGeometry(bool textures) -{ - if (!x12c_postConstructed->x4c_insts.empty()) - for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) - inst.Clear(); +void CGameArea::VerifyTokenList(CStateManager& stateMgr) { + if (xdc_tokens.size()) + return; + ClearTokenList(); - /* Materials */ - SShader& matSet = x12c_postConstructed->m_materialSet; - auto secIt = m_resolvedBufs.begin() + 2; - { - athena::io::MemoryReader r(secIt->first, secIt->second); - matSet.m_matSet.read(r); - if (textures) - CBooModel::MakeTexturesFromMats(matSet.m_matSet, matSet.x0_textures, *g_SimplePool); - matSet.InitializeLayout(nullptr); - ++secIt; + if (xac_deps2.empty()) + return; + + auto end = xac_deps2.end(); + for (int lidx = int(xbc_layerDepOffsets.size() - 1); lidx >= 0; --lidx) { + auto begin = xac_deps2.begin() + xbc_layerDepOffsets[lidx]; + if (stateMgr.LayerState()->IsLayerActive(x4_selfIdx, lidx)) { + for (auto it = begin; it != end; ++it) { + xdc_tokens.push_back(g_SimplePool->GetObj(*it)); + xdc_tokens.back().Lock(); + } } - - CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) - { - /* Shared geometry uniform buffer - one for normal render, one for shadow render */ - for (int i=0 ; i<2 ; ++i) - matSet.m_geomLayout->m_sharedBuffer[i] = - ctx.newDynamicBuffer(boo::BufferUse::Uniform, matSet.m_geomLayout->m_geomBufferSize, 1); - - /* Models */ - for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) - { - { - DataSpec::DNAMP1::MREA::MeshHeader header; - athena::io::MemoryReader r(secIt->first, secIt->second); - header.read(r); - inst.x0_visorFlags = header.visorFlags.flags; - inst.x4_xf = header.xfMtx; - inst.x34_aabb = zeus::CAABox(header.aabb[0], header.aabb[1]); - ++secIt; - } - - { - athena::io::MemoryReader r(secIt->first, secIt->second); - inst.m_hmdlMeta.read(r); - } - ++secIt; - - boo::ObjToken vbo; - boo::ObjToken ibo; - vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, secIt->first, inst.m_hmdlMeta.vertStride, - inst.m_hmdlMeta.vertCount); - ++secIt; - ibo = ctx.newStaticBuffer(boo::BufferUse::Index, secIt->first, 4, inst.m_hmdlMeta.indexCount); - ++secIt; - - u32 surfCount = hecl::SBig(*reinterpret_cast(secIt->first)); - inst.m_surfaces.reserve(surfCount); - inst.m_shaders.reserve(surfCount); - ++secIt; - for (u32 j=0 ; jfirst, secIt->second); - surf.m_data.read(r); - ++secIt; - } - - TToken nullModel; - inst.m_instance = std::make_unique - (nullModel, nullptr, &inst.m_surfaces, matSet, vbo, ibo, - inst.x34_aabb, inst.x0_visorFlags, 0, nullptr); - } - - return true; - } BooTrace); - - for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) - { - for (CBooSurface& surf : inst.m_surfaces) - { - auto& shad = inst.m_shaders[surf.m_data.matIdx]; - if (!shad) - shad = matSet.BuildShader(inst.m_hmdlMeta, matSet.m_matSet.materials[surf.m_data.matIdx]); - } - inst.m_instance->RemapMaterialData(matSet, inst.m_shaders); - } - - x12c_postConstructed->x1108_25_modelsConstructed = true; + end = begin; + } } -void CGameArea::VerifyTokenList(CStateManager& stateMgr) -{ - if (xdc_tokens.size()) - return; - ClearTokenList(); +void CGameArea::ClearTokenList() { + if (xdc_tokens.empty()) + xdc_tokens.reserve(xac_deps2.size()); + else + xdc_tokens.clear(); - if (xac_deps2.empty()) - return; - - auto end = xac_deps2.end(); - for (int lidx = int(xbc_layerDepOffsets.size() - 1) ; lidx >= 0 ; --lidx) - { - auto begin = xac_deps2.begin() + xbc_layerDepOffsets[lidx]; - if (stateMgr.LayerState()->IsLayerActive(x4_selfIdx, lidx)) - { - for (auto it = begin ; it != end ; ++it) - { - xdc_tokens.push_back(g_SimplePool->GetObj(*it)); - xdc_tokens.back().Lock(); - } - } - end = begin; - } + xf0_26_tokensReady = false; } -void CGameArea::ClearTokenList() -{ - if (xdc_tokens.empty()) - xdc_tokens.reserve(xac_deps2.size()); - else - xdc_tokens.clear(); +u32 CGameArea::GetPreConstructedSize() const { return 0; } - xf0_26_tokensReady = false; +SMREAHeader CGameArea::VerifyHeader() const { + if (x110_mreaSecBufs.empty()) + return {}; + if (*reinterpret_cast(x110_mreaSecBufs[0].first.get()) != SBIG(0xDEADBEEF)) + return {}; + + SMREAHeader header; + CMemoryInStream r(x110_mreaSecBufs[0].first.get() + 4, x110_mreaSecBufs[0].second - 4); + u32 version = r.readUint32Big(); + if (!(version & 0x10000)) + Log.report(logvisor::Fatal, "Attempted to load non-URDE MREA"); + version &= ~0x10000; + header.version = (version >= 12 && version <= 15) ? version : 0; + if (!header.version) + return {}; + + header.xf.read34RowMajor(r); + header.modelCount = r.readUint32Big(); + header.secCount = r.readUint32Big(); + header.geomSecIdx = r.readUint32Big(); + header.sclySecIdx = r.readUint32Big(); + header.collisionSecIdx = r.readUint32Big(); + header.unkSecIdx = r.readUint32Big(); + header.lightSecIdx = r.readUint32Big(); + header.visiSecIdx = r.readUint32Big(); + header.pathSecIdx = r.readUint32Big(); + header.arotSecIdx = r.readUint32Big(); + + return header; } -u32 CGameArea::GetPreConstructedSize() const -{ - return 0; +TUniqueId CGameArea::LookupPVSUniqueID(TUniqueId id) const { + return x12c_postConstructed->xa8_pvsEntityMap[id.Value()].x4_uid; } -SMREAHeader CGameArea::VerifyHeader() const -{ - if (x110_mreaSecBufs.empty()) - return {}; - if (*reinterpret_cast(x110_mreaSecBufs[0].first.get()) != SBIG(0xDEADBEEF)) - return {}; +s16 CGameArea::LookupPVSID(TUniqueId id) const { return x12c_postConstructed->xa8_pvsEntityMap[id.Value()].x0_id; } - SMREAHeader header; - CMemoryInStream r(x110_mreaSecBufs[0].first.get() + 4, x110_mreaSecBufs[0].second - 4); - u32 version = r.readUint32Big(); - if (!(version & 0x10000)) - Log.report(logvisor::Fatal, "Attempted to load non-URDE MREA"); - version &= ~0x10000; - header.version = (version >= 12 && version <= 15) ? version : 0; - if (!header.version) - return {}; +void CGameArea::SetAreaAttributes(const CScriptAreaAttributes* areaAttributes) { + x12c_postConstructed->x10d8_areaAttributes = areaAttributes; + if (areaAttributes == nullptr) + return; - header.xf.read34RowMajor(r); - header.modelCount = r.readUint32Big(); - header.secCount = r.readUint32Big(); - header.geomSecIdx = r.readUint32Big(); - header.sclySecIdx = r.readUint32Big(); - header.collisionSecIdx = r.readUint32Big(); - header.unkSecIdx = r.readUint32Big(); - header.lightSecIdx = r.readUint32Big(); - header.visiSecIdx = r.readUint32Big(); - header.pathSecIdx = r.readUint32Big(); - header.arotSecIdx = r.readUint32Big(); - - return header; + x12c_postConstructed->x111c_thermalCurrent = areaAttributes->GetThermalHeat(); + x12c_postConstructed->x1128_worldLightingLevel = areaAttributes->GetWorldLightingLevel(); } -TUniqueId CGameArea::LookupPVSUniqueID(TUniqueId id) const -{ - return x12c_postConstructed->xa8_pvsEntityMap[id.Value()].x4_uid; +bool CGameArea::CAreaObjectList::IsQualified(const CEntity& ent) { return (ent.GetAreaIdAlways() == x200c_areaIdx); } +void CGameArea::WarmupShaders(const SObjectTag& mreaTag) { + // Calling this version of the constructor performs warmup implicitly + CGameArea area(mreaTag.id); } -s16 CGameArea::LookupPVSID(TUniqueId id) const -{ - return x12c_postConstructed->xa8_pvsEntityMap[id.Value()].x0_id; -} - -void CGameArea::SetAreaAttributes(const CScriptAreaAttributes* areaAttributes) -{ - x12c_postConstructed->x10d8_areaAttributes = areaAttributes; - if (areaAttributes == nullptr) - return; - - x12c_postConstructed->x111c_thermalCurrent = areaAttributes->GetThermalHeat(); - x12c_postConstructed->x1128_worldLightingLevel = areaAttributes->GetWorldLightingLevel(); -} - -bool CGameArea::CAreaObjectList::IsQualified(const CEntity& ent) -{ - return (ent.GetAreaIdAlways() == x200c_areaIdx); -} -void CGameArea::WarmupShaders(const SObjectTag& mreaTag) -{ - // Calling this version of the constructor performs warmup implicitly - CGameArea area(mreaTag.id); -} - -} +} // namespace urde diff --git a/Runtime/World/CGameArea.hpp b/Runtime/World/CGameArea.hpp index e4f671a89..6c5efe9fe 100644 --- a/Runtime/World/CGameArea.hpp +++ b/Runtime/World/CGameArea.hpp @@ -18,362 +18,350 @@ #include "Editor/ProjectResourceFactoryBase.hpp" #include "World/CEnvFxManager.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CScriptAreaAttributes; -struct SMREAHeader -{ - u32 version = 0; - zeus::CTransform xf; - u32 modelCount; - u32 secCount; - u32 geomSecIdx; - u32 sclySecIdx; - u32 collisionSecIdx; - u32 unkSecIdx; - u32 lightSecIdx; - u32 visiSecIdx; - u32 pathSecIdx; - u32 arotSecIdx; +struct SMREAHeader { + u32 version = 0; + zeus::CTransform xf; + u32 modelCount; + u32 secCount; + u32 geomSecIdx; + u32 sclySecIdx; + u32 collisionSecIdx; + u32 unkSecIdx; + u32 lightSecIdx; + u32 visiSecIdx; + u32 pathSecIdx; + u32 arotSecIdx; }; -class CDummyGameArea final : public IGameArea -{ - friend class CDummyWorld; +class CDummyGameArea final : public IGameArea { + friend class CDummyWorld; - int x4_mlvlVersion; - CAssetId x8_nameSTRG; - CAssetId xc_mrea; - TAreaId x10_areaId; - zeus::CTransform x14_transform; - std::vector x44_attachedAreaIndices; - std::vector x54_docks; + int x4_mlvlVersion; + CAssetId x8_nameSTRG; + CAssetId xc_mrea; + TAreaId x10_areaId; + zeus::CTransform x14_transform; + std::vector x44_attachedAreaIndices; + std::vector x54_docks; public: - CDummyGameArea(CInputStream& in, int idx, int mlvlVersion); + CDummyGameArea(CInputStream& in, int idx, int mlvlVersion); - std::pair, s32> IGetScriptingMemoryAlways() const; - TAreaId IGetAreaId() const; - CAssetId IGetAreaAssetId() const; - bool IIsActive() const; - TAreaId IGetAttachedAreaId(int) const; - u32 IGetNumAttachedAreas() const; - CAssetId IGetStringTableAssetId() const; - const zeus::CTransform& IGetTM() const; + std::pair, s32> IGetScriptingMemoryAlways() const; + TAreaId IGetAreaId() const; + CAssetId IGetAreaAssetId() const; + bool IIsActive() const; + TAreaId IGetAttachedAreaId(int) const; + u32 IGetNumAttachedAreas() const; + CAssetId IGetStringTableAssetId() const; + const zeus::CTransform& IGetTM() const; }; -struct CAreaRenderOctTree -{ - struct Node - { - u16 x0_bitmapIdx; - u16 x2_flags; - u16 x4_children[]; +struct CAreaRenderOctTree { + struct Node { + u16 x0_bitmapIdx; + u16 x2_flags; + u16 x4_children[]; - u32 GetChildCount() const; - zeus::CAABox GetNodeBounds(const zeus::CAABox& curAABB, int idx) const; + u32 GetChildCount() const; + zeus::CAABox GetNodeBounds(const zeus::CAABox& curAABB, int idx) const; - void RecursiveBuildOverlaps(u32* out, const CAreaRenderOctTree& parent, const zeus::CAABox& curAABB, - const zeus::CAABox& testAABB) const; - }; + void RecursiveBuildOverlaps(u32* out, const CAreaRenderOctTree& parent, const zeus::CAABox& curAABB, + const zeus::CAABox& testAABB) const; + }; - const u8* x0_buf; - u32 x8_bitmapCount; - u32 xc_meshCount; - u32 x10_nodeCount; - u32 x14_bitmapWordCount; - zeus::CAABox x18_aabb; - const u32* x30_bitmaps; - const u32* x34_indirectionTable; - const u8* x38_entries; + const u8* x0_buf; + u32 x8_bitmapCount; + u32 xc_meshCount; + u32 x10_nodeCount; + u32 x14_bitmapWordCount; + zeus::CAABox x18_aabb; + const u32* x30_bitmaps; + const u32* x34_indirectionTable; + const u8* x38_entries; - CAreaRenderOctTree(const u8* buf); + CAreaRenderOctTree(const u8* buf); - void FindOverlappingModels(std::vector& out, const zeus::CAABox& testAABB) const; - void FindOverlappingModels(u32* out, const zeus::CAABox& testAABB) const; + void FindOverlappingModels(std::vector& out, const zeus::CAABox& testAABB) const; + void FindOverlappingModels(u32* out, const zeus::CAABox& testAABB) const; }; -class CGameArea final : public IGameArea -{ - friend class CWorld; - friend class CStateManager; +class CGameArea final : public IGameArea { + friend class CWorld; + friend class CStateManager; - TAreaId x4_selfIdx; - CAssetId x8_nameSTRG; - zeus::CTransform xc_transform; - zeus::CTransform x3c_invTransform; - zeus::CAABox x6c_aabb; - CAssetId x84_mrea; - s32 x88_areaId; - std::vector x8c_attachedAreaIndices; - std::vector x9c_deps1; - std::vector xac_deps2; + TAreaId x4_selfIdx; + CAssetId x8_nameSTRG; + zeus::CTransform xc_transform; + zeus::CTransform x3c_invTransform; + zeus::CAABox x6c_aabb; + CAssetId x84_mrea; + s32 x88_areaId; + std::vector x8c_attachedAreaIndices; + std::vector x9c_deps1; + std::vector xac_deps2; - std::vector xbc_layerDepOffsets; - std::vector xcc_docks; - std::vector xdc_tokens; + std::vector xbc_layerDepOffsets; + std::vector xcc_docks; + std::vector xdc_tokens; - u32 xec_totalResourcesSize = 0; + u32 xec_totalResourcesSize = 0; - bool xf0_24_postConstructed : 1; - bool xf0_25_active : 1; - bool xf0_26_tokensReady : 1; - bool xf0_27_loadPaused : 1; - bool xf0_28_validated : 1; + bool xf0_24_postConstructed : 1; + bool xf0_25_active : 1; + bool xf0_26_tokensReady : 1; + bool xf0_27_loadPaused : 1; + bool xf0_28_validated : 1; - enum class EPhase - { - LoadHeader, - LoadSecSizes, - ReserveSections, - LoadDataSections, - WaitForFinish - } xf4_phase = EPhase::LoadHeader; + enum class EPhase { + LoadHeader, + LoadSecSizes, + ReserveSections, + LoadDataSections, + WaitForFinish + } xf4_phase = EPhase::LoadHeader; - std::list> xf8_loadTransactions; + std::list> xf8_loadTransactions; public: + class CChainIterator { + CGameArea* m_area; - class CChainIterator - { - CGameArea* m_area; - public: - CChainIterator(CGameArea* area) : m_area(area) {} - CGameArea& operator*() const { return *m_area; } - CGameArea* operator->() const { return m_area; } - CChainIterator& operator++() { m_area = m_area->GetNext(); return *this; } - bool operator!=(const CChainIterator& other) const { return m_area != other.m_area; } - bool operator==(const CChainIterator& other) const { return m_area == other.m_area; } - }; - - class CConstChainIterator - { - const CGameArea* m_area; - public: - CConstChainIterator(const CGameArea* area) : m_area(area) {} - const CGameArea& operator*() const { return *m_area; } - const CGameArea* operator->() const { return m_area; } - CConstChainIterator& operator++() { m_area = m_area->GetNext(); return *this; } - bool operator!=(const CConstChainIterator& other) const { return m_area != other.m_area; } - bool operator==(const CConstChainIterator& other) const { return m_area == other.m_area; } - }; - - class CAreaObjectList : public CObjectList - { - private: - TAreaId x200c_areaIdx = 0; - public: - CAreaObjectList(TAreaId areaIdx) - : CObjectList(EGameObjectList::Invalid) - , x200c_areaIdx(areaIdx) - { - } - - bool IsQualified(const CEntity& ent); - }; - - enum class EOcclusionState - { - Occluded, - Visible - }; - - class CAreaFog - { - ERglFogMode x0_fogMode = ERglFogMode::None; - zeus::CVector2f x4_rangeCur = {0.f, 1024.f}; - zeus::CVector2f xc_rangeTarget = {0.f, 1024.f}; - zeus::CVector2f x14_rangeDelta; - zeus::CColor x1c_colorCur = {0.5f, 0.5f, 0.5f, 1.f}; - zeus::CColor x28_colorTarget = {0.5f, 0.5f, 0.5f, 1.f}; - float x34_colorDelta = 0.f; - public: - void SetCurrent() const; - void Update(float dt); - void RollFogOut(float rangeDelta, float colorDelta, const zeus::CColor& color); - void FadeFog(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec1, - float, const zeus::CVector2f& vec2); - void SetFogExplicit(ERglFogMode mode, const zeus::CColor& color, const zeus::CVector2f& range); - bool IsFogDisabled() const; - void DisableFog(); - }; - - struct CPostConstructed - { - std::unique_ptr x0_collision; - u32 x8_collisionSize = 0; - std::experimental::optional xc_octTree; - std::vector x4c_insts; - SShader m_materialSet = {0}; - //std::unique_ptr x5c_; - std::vector x60_lightsA; - std::vector x70_gfxLightsA; - std::vector x80_lightsB; - std::vector x90_gfxLightsB; - std::unique_ptr xa0_pvs; - u32 xa4_elemCount = 1024; - struct MapEntry - { - s16 x0_id = -1; - TUniqueId x4_uid = kInvalidUniqueId; - } xa8_pvsEntityMap[1024]; - u32 x10a8_pvsVersion = 0; - TLockedToken x10ac_pathToken; - // bool x10b8_ = 0; optional flag for CToken - CPFArea* x10bc_pathArea = nullptr; - std::unique_ptr x10c0_areaObjs; - std::unique_ptr x10c4_areaFog; - const u8* x10c8_sclyBuf = nullptr; - u32 x10d0_sclySize = 0; - u32 x10d4_ = 0; - const CScriptAreaAttributes* x10d8_areaAttributes = nullptr; - EOcclusionState x10dc_occlusionState = EOcclusionState::Occluded; - u32 x10e0_ = 0; - float x10e4_occludedTime = 5.f; - u32 x10e8_ = -1; - u32 x10ec_ = 0; - // std::vector x10f0_tokens; - u32 x1100_ = 0; - u32 x1104_ = 0; - union - { - struct - { - bool x1108_24_ : 1; - bool x1108_25_modelsConstructed : 1; - bool x1108_26_ : 1; - bool x1108_27_ : 1; - bool x1108_28_occlusionPinged : 1; - bool x1108_29_pvsHasActors : 1; - bool x1108_30_ : 1; - }; - u32 _dummy = 0; - }; - std::vector> x110c_layerPtrs; - float x111c_thermalCurrent = 0.f; - float x1120_thermalSpeed = 0.f; - float x1124_thermalTarget = 0.f; - float x1128_worldLightingLevel = 1.f; - float x112c_xraySpeed = 0.f; - float x1130_xrayTarget = 1.f; - float x1134_weaponWorldLightingSpeed = 0.f; - float x1138_weaponWorldLightingTarget = 1.f; - u32 x113c_playerActorsLoading = 0; - }; -private: - std::vector, int>> x110_mreaSecBufs; - std::vector> m_resolvedBufs; - u32 x124_secCount = 0; - u32 x128_mreaDataOffset = 0; - std::unique_ptr x12c_postConstructed; - - CGameArea* x130_next = nullptr; - CGameArea* x134_prev = nullptr; - EChain x138_curChain = EChain::ToDeallocate; - - void UpdateFog(float dt); - void UpdateThermalVisor(float dt); - void UpdateWeaponWorldLighting(float dt); - -public: - - CGameArea(CInputStream& in, int idx, int mlvlVersion); - CGameArea(CAssetId mreaId); // Warmup constructor - ~CGameArea(); - - bool IsFinishedOccluding() const; - void ReadDependencyList(); - void SetLoadPauseState(bool paused); - - std::pair, s32> IGetScriptingMemoryAlways() const; - TAreaId GetAreaId() const { return x4_selfIdx; } - TAreaId IGetAreaId() const { return x4_selfIdx; } - CAssetId IGetAreaAssetId() const { return x84_mrea; } - bool IIsActive() const; - TAreaId IGetAttachedAreaId(int) const; - u32 IGetNumAttachedAreas() const; - CAssetId IGetStringTableAssetId() const; - const zeus::CTransform& IGetTM() const; - - void SetXRaySpeedAndTarget(float speed, float target); - void SetThermalSpeedAndTarget(float speed, float target); - void SetWeaponWorldLighting(float speed, float target); - - CAssetId GetAreaAssetId() const { return x84_mrea; } - const CAreaFog* GetAreaFog() const { return GetPostConstructed()->x10c4_areaFog.get(); } - CAreaFog* AreaFog() { return const_cast(GetAreaFog()); } - float GetXRayFogDistance() const; - EEnvFxType DoesAreaNeedEnvFx() const; - bool DoesAreaNeedSkyNow() const; - void OtherAreaOcclusionChanged(); - void PingOcclusionState(); - void PreRender(); - void AliveUpdate(float dt); - void SetOcclusionState(EOcclusionState state); - EOcclusionState GetOcclusionState() const { return GetPostConstructed()->x10dc_occlusionState; } - void RemoveStaticGeometry(); - void AddStaticGeometry(); - //void TransferTokensToARAM(); - //void TransferARAMTokensOver(); - EChain SetChain(CGameArea* prev, EChain chain); - bool StartStreamingMainArea(); - //void UnloadAllLoadedTextures(); - //void ReloadAllLoadedTextures(); - void ReloadAllUnloadedTextures(); - u32 GetNumPartSizes() const; - void AllocNewAreaData(int, int); - bool Invalidate(CStateManager* mgr); - void KillmAreaData(); - void CullDeadAreaRequests(); - void StartStreamIn(CStateManager& mgr); - void Validate(CStateManager& mgr); - void LoadScriptObjects(CStateManager& mgr); - std::pair GetLayerScriptBuffer(int layer); - void PostConstructArea(); - void FillInStaticGeometry(bool textures = true); - void VerifyTokenList(CStateManager& stateMgr); - void ClearTokenList(); - u32 GetPreConstructedSize() const; - SMREAHeader VerifyHeader() const; - TUniqueId LookupPVSUniqueID(TUniqueId id) const; - s16 LookupPVSID(TUniqueId id) const; - const CPVSAreaSet* GetAreaVisSet() const { return GetPostConstructed()->xa0_pvs.get(); } - u32 Get1stPVSLightFeature(u32 lightIdx) const - { return GetAreaVisSet() ? GetAreaVisSet()->Get1stLightIndex(lightIdx) : -1; } - u32 Get2ndPVSLightFeature(u32 lightIdx) const - { return GetAreaVisSet() ? GetAreaVisSet()->Get2ndLightIndex(lightIdx) : -1; } - - const zeus::CTransform& GetTransform() const {return xc_transform;} - const zeus::CTransform& GetInverseTransform() const {return x3c_invTransform;} - const zeus::CAABox& GetAABB() const {return x6c_aabb;} - - const std::vector& GetDocks() const {return xcc_docks;} - const Dock* GetDock(s32 dock) const { return &xcc_docks[dock]; } - s32 GetDockCount() const { return xcc_docks.size(); } - Dock* DockNC(s32 dock) { return &xcc_docks[dock]; } - - bool IsPostConstructed() const { return xf0_24_postConstructed; } - const CPostConstructed* GetPostConstructed() const - { - if (!x12c_postConstructed) - return nullptr; - return x12c_postConstructed.get(); + public: + CChainIterator(CGameArea* area) : m_area(area) {} + CGameArea& operator*() const { return *m_area; } + CGameArea* operator->() const { return m_area; } + CChainIterator& operator++() { + m_area = m_area->GetNext(); + return *this; } + bool operator!=(const CChainIterator& other) const { return m_area != other.m_area; } + bool operator==(const CChainIterator& other) const { return m_area == other.m_area; } + }; - bool IsValidated() const { return xf0_28_validated; } + class CConstChainIterator { + const CGameArea* m_area; - void SetAreaAttributes(const CScriptAreaAttributes* areaAttributes); - bool GetActive() const { return xf0_25_active; } - void SetActive(bool active) { xf0_25_active = active; } - CObjectList* GetAreaObjects() const { return GetPostConstructed() ? GetPostConstructed()->x10c0_areaObjs.get() : nullptr; } + public: + CConstChainIterator(const CGameArea* area) : m_area(area) {} + const CGameArea& operator*() const { return *m_area; } + const CGameArea* operator->() const { return m_area; } + CConstChainIterator& operator++() { + m_area = m_area->GetNext(); + return *this; + } + bool operator!=(const CConstChainIterator& other) const { return m_area != other.m_area; } + bool operator==(const CConstChainIterator& other) const { return m_area == other.m_area; } + }; - CGameArea* GetNext() const { return x130_next; } + class CAreaObjectList : public CObjectList { + private: + TAreaId x200c_areaIdx = 0; - static void WarmupShaders(const SObjectTag& mreaTag); + public: + CAreaObjectList(TAreaId areaIdx) : CObjectList(EGameObjectList::Invalid), x200c_areaIdx(areaIdx) {} - s32 GetAreaSaveId() const { return x88_areaId; } + bool IsQualified(const CEntity& ent); + }; + + enum class EOcclusionState { Occluded, Visible }; + + class CAreaFog { + ERglFogMode x0_fogMode = ERglFogMode::None; + zeus::CVector2f x4_rangeCur = {0.f, 1024.f}; + zeus::CVector2f xc_rangeTarget = {0.f, 1024.f}; + zeus::CVector2f x14_rangeDelta; + zeus::CColor x1c_colorCur = {0.5f, 0.5f, 0.5f, 1.f}; + zeus::CColor x28_colorTarget = {0.5f, 0.5f, 0.5f, 1.f}; + float x34_colorDelta = 0.f; + + public: + void SetCurrent() const; + void Update(float dt); + void RollFogOut(float rangeDelta, float colorDelta, const zeus::CColor& color); + void FadeFog(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec1, float, + const zeus::CVector2f& vec2); + void SetFogExplicit(ERglFogMode mode, const zeus::CColor& color, const zeus::CVector2f& range); + bool IsFogDisabled() const; + void DisableFog(); + }; + + struct CPostConstructed { + std::unique_ptr x0_collision; + u32 x8_collisionSize = 0; + std::experimental::optional xc_octTree; + std::vector x4c_insts; + SShader m_materialSet = {0}; + // std::unique_ptr x5c_; + std::vector x60_lightsA; + std::vector x70_gfxLightsA; + std::vector x80_lightsB; + std::vector x90_gfxLightsB; + std::unique_ptr xa0_pvs; + u32 xa4_elemCount = 1024; + struct MapEntry { + s16 x0_id = -1; + TUniqueId x4_uid = kInvalidUniqueId; + } xa8_pvsEntityMap[1024]; + u32 x10a8_pvsVersion = 0; + TLockedToken x10ac_pathToken; + // bool x10b8_ = 0; optional flag for CToken + CPFArea* x10bc_pathArea = nullptr; + std::unique_ptr x10c0_areaObjs; + std::unique_ptr x10c4_areaFog; + const u8* x10c8_sclyBuf = nullptr; + u32 x10d0_sclySize = 0; + u32 x10d4_ = 0; + const CScriptAreaAttributes* x10d8_areaAttributes = nullptr; + EOcclusionState x10dc_occlusionState = EOcclusionState::Occluded; + u32 x10e0_ = 0; + float x10e4_occludedTime = 5.f; + u32 x10e8_ = -1; + u32 x10ec_ = 0; + // std::vector x10f0_tokens; + u32 x1100_ = 0; + u32 x1104_ = 0; + union { + struct { + bool x1108_24_ : 1; + bool x1108_25_modelsConstructed : 1; + bool x1108_26_ : 1; + bool x1108_27_ : 1; + bool x1108_28_occlusionPinged : 1; + bool x1108_29_pvsHasActors : 1; + bool x1108_30_ : 1; + }; + u32 _dummy = 0; + }; + std::vector> x110c_layerPtrs; + float x111c_thermalCurrent = 0.f; + float x1120_thermalSpeed = 0.f; + float x1124_thermalTarget = 0.f; + float x1128_worldLightingLevel = 1.f; + float x112c_xraySpeed = 0.f; + float x1130_xrayTarget = 1.f; + float x1134_weaponWorldLightingSpeed = 0.f; + float x1138_weaponWorldLightingTarget = 1.f; + u32 x113c_playerActorsLoading = 0; + }; + +private: + std::vector, int>> x110_mreaSecBufs; + std::vector> m_resolvedBufs; + u32 x124_secCount = 0; + u32 x128_mreaDataOffset = 0; + std::unique_ptr x12c_postConstructed; + + CGameArea* x130_next = nullptr; + CGameArea* x134_prev = nullptr; + EChain x138_curChain = EChain::ToDeallocate; + + void UpdateFog(float dt); + void UpdateThermalVisor(float dt); + void UpdateWeaponWorldLighting(float dt); + +public: + CGameArea(CInputStream& in, int idx, int mlvlVersion); + CGameArea(CAssetId mreaId); // Warmup constructor + ~CGameArea(); + + bool IsFinishedOccluding() const; + void ReadDependencyList(); + void SetLoadPauseState(bool paused); + + std::pair, s32> IGetScriptingMemoryAlways() const; + TAreaId GetAreaId() const { return x4_selfIdx; } + TAreaId IGetAreaId() const { return x4_selfIdx; } + CAssetId IGetAreaAssetId() const { return x84_mrea; } + bool IIsActive() const; + TAreaId IGetAttachedAreaId(int) const; + u32 IGetNumAttachedAreas() const; + CAssetId IGetStringTableAssetId() const; + const zeus::CTransform& IGetTM() const; + + void SetXRaySpeedAndTarget(float speed, float target); + void SetThermalSpeedAndTarget(float speed, float target); + void SetWeaponWorldLighting(float speed, float target); + + CAssetId GetAreaAssetId() const { return x84_mrea; } + const CAreaFog* GetAreaFog() const { return GetPostConstructed()->x10c4_areaFog.get(); } + CAreaFog* AreaFog() { return const_cast(GetAreaFog()); } + float GetXRayFogDistance() const; + EEnvFxType DoesAreaNeedEnvFx() const; + bool DoesAreaNeedSkyNow() const; + void OtherAreaOcclusionChanged(); + void PingOcclusionState(); + void PreRender(); + void AliveUpdate(float dt); + void SetOcclusionState(EOcclusionState state); + EOcclusionState GetOcclusionState() const { return GetPostConstructed()->x10dc_occlusionState; } + void RemoveStaticGeometry(); + void AddStaticGeometry(); + // void TransferTokensToARAM(); + // void TransferARAMTokensOver(); + EChain SetChain(CGameArea* prev, EChain chain); + bool StartStreamingMainArea(); + // void UnloadAllLoadedTextures(); + // void ReloadAllLoadedTextures(); + void ReloadAllUnloadedTextures(); + u32 GetNumPartSizes() const; + void AllocNewAreaData(int, int); + bool Invalidate(CStateManager* mgr); + void KillmAreaData(); + void CullDeadAreaRequests(); + void StartStreamIn(CStateManager& mgr); + void Validate(CStateManager& mgr); + void LoadScriptObjects(CStateManager& mgr); + std::pair GetLayerScriptBuffer(int layer); + void PostConstructArea(); + void FillInStaticGeometry(bool textures = true); + void VerifyTokenList(CStateManager& stateMgr); + void ClearTokenList(); + u32 GetPreConstructedSize() const; + SMREAHeader VerifyHeader() const; + TUniqueId LookupPVSUniqueID(TUniqueId id) const; + s16 LookupPVSID(TUniqueId id) const; + const CPVSAreaSet* GetAreaVisSet() const { return GetPostConstructed()->xa0_pvs.get(); } + u32 Get1stPVSLightFeature(u32 lightIdx) const { + return GetAreaVisSet() ? GetAreaVisSet()->Get1stLightIndex(lightIdx) : -1; + } + u32 Get2ndPVSLightFeature(u32 lightIdx) const { + return GetAreaVisSet() ? GetAreaVisSet()->Get2ndLightIndex(lightIdx) : -1; + } + + const zeus::CTransform& GetTransform() const { return xc_transform; } + const zeus::CTransform& GetInverseTransform() const { return x3c_invTransform; } + const zeus::CAABox& GetAABB() const { return x6c_aabb; } + + const std::vector& GetDocks() const { return xcc_docks; } + const Dock* GetDock(s32 dock) const { return &xcc_docks[dock]; } + s32 GetDockCount() const { return xcc_docks.size(); } + Dock* DockNC(s32 dock) { return &xcc_docks[dock]; } + + bool IsPostConstructed() const { return xf0_24_postConstructed; } + const CPostConstructed* GetPostConstructed() const { + if (!x12c_postConstructed) + return nullptr; + return x12c_postConstructed.get(); + } + + bool IsValidated() const { return xf0_28_validated; } + + void SetAreaAttributes(const CScriptAreaAttributes* areaAttributes); + bool GetActive() const { return xf0_25_active; } + void SetActive(bool active) { xf0_25_active = active; } + CObjectList* GetAreaObjects() const { + return GetPostConstructed() ? GetPostConstructed()->x10c0_areaObjs.get() : nullptr; + } + + CGameArea* GetNext() const { return x130_next; } + + static void WarmupShaders(const SObjectTag& mreaTag); + + s32 GetAreaSaveId() const { return x88_areaId; } }; -} - +} // namespace urde diff --git a/Runtime/World/CGameLight.cpp b/Runtime/World/CGameLight.cpp index b73ab4d46..b39f3982c 100644 --- a/Runtime/World/CGameLight.cpp +++ b/Runtime/World/CGameLight.cpp @@ -3,57 +3,52 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CGameLight::CGameLight(TUniqueId uid, TAreaId aid, bool active, std::string_view name, const zeus::CTransform& xf, TUniqueId parentId, const CLight& light, u32 sourceId, u32 w2, float f1) -: CActor(uid, active, name, CEntityInfo(aid, CEntity::NullConnectionList), xf, - CModelData::CModelDataNull(), CMaterialList(), CActorParameters::None(), kInvalidUniqueId), - xe8_parentId(parentId), xec_light(light), x13c_lightId(sourceId), x140_priority(w2), x144_lifeTime(f1) -{ - xec_light.GetRadius(); - xec_light.GetIntensity(); - SetLightPriorityAndId(); +: CActor(uid, active, name, CEntityInfo(aid, CEntity::NullConnectionList), xf, CModelData::CModelDataNull(), + CMaterialList(), CActorParameters::None(), kInvalidUniqueId) +, xe8_parentId(parentId) +, xec_light(light) +, x13c_lightId(sourceId) +, x140_priority(w2) +, x144_lifeTime(f1) { + xec_light.GetRadius(); + xec_light.GetIntensity(); + SetLightPriorityAndId(); } -void CGameLight::Accept(IVisitor &visitor) -{ - visitor.Visit(this); +void CGameLight::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CGameLight::Think(float dt, CStateManager& mgr) { + if (x144_lifeTime <= 0.f) + return; + x144_lifeTime -= dt; + + if (x144_lifeTime <= 0.f) + mgr.FreeScriptObject(GetUniqueId()); } -void CGameLight::Think(float dt, CStateManager& mgr) -{ - if (x144_lifeTime <= 0.f) - return; - x144_lifeTime -= dt; - - if (x144_lifeTime <= 0.f) - mgr.FreeScriptObject(GetUniqueId()); +void CGameLight::SetLightPriorityAndId() { + xec_light.x3c_priority = x140_priority; + xec_light.x40_lightId = x13c_lightId; } -void CGameLight::SetLightPriorityAndId() -{ - xec_light.x3c_priority = x140_priority; - xec_light.x40_lightId = x13c_lightId; +void CGameLight::SetLight(const CLight& light) { + xec_light = light; + xec_light.GetRadius(); + xec_light.GetIntensity(); + SetLightPriorityAndId(); } -void CGameLight::SetLight(const CLight& light) -{ - xec_light = light; - xec_light.GetRadius(); - xec_light.GetIntensity(); - SetLightPriorityAndId(); -} +CLight CGameLight::GetLight() const { + CLight ret = xec_light; + ret.SetPosition(x34_transform * xec_light.GetPosition()); -CLight CGameLight::GetLight() const -{ - CLight ret = xec_light; - ret.SetPosition(x34_transform * xec_light.GetPosition()); + if (ret.GetType() != ELightType::Point) + ret.SetDirection(x34_transform.rotate(xec_light.GetDirection()).normalized()); - if (ret.GetType() != ELightType::Point) - ret.SetDirection(x34_transform.rotate(xec_light.GetDirection()).normalized()); - - return ret; -} + return ret; } +} // namespace urde diff --git a/Runtime/World/CGameLight.hpp b/Runtime/World/CGameLight.hpp index dcf3c48ac..755d21507 100644 --- a/Runtime/World/CGameLight.hpp +++ b/Runtime/World/CGameLight.hpp @@ -2,25 +2,23 @@ #include "CActor.hpp" -namespace urde -{ -class CGameLight : public CActor -{ - TUniqueId xe8_parentId; - CLight xec_light; - u32 x13c_lightId; - u32 x140_priority; - float x144_lifeTime; +namespace urde { +class CGameLight : public CActor { + TUniqueId xe8_parentId; + CLight xec_light; + u32 x13c_lightId; + u32 x140_priority; + float x144_lifeTime; public: - CGameLight(TUniqueId, TAreaId, bool, std::string_view, const zeus::CTransform&, TUniqueId, const CLight&, - u32 sourceId, u32, float); + CGameLight(TUniqueId, TAreaId, bool, std::string_view, const zeus::CTransform&, TUniqueId, const CLight&, + u32 sourceId, u32, float); - void Accept(IVisitor &visitor); - void Think(float, CStateManager&); - void SetLightPriorityAndId(); - void SetLight(const CLight&); - CLight GetLight() const; - TUniqueId GetParentId() const { return xe8_parentId; } + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void SetLightPriorityAndId(); + void SetLight(const CLight&); + CLight GetLight() const; + TUniqueId GetParentId() const { return xe8_parentId; } }; -} +} // namespace urde diff --git a/Runtime/World/CGrappleParameters.hpp b/Runtime/World/CGrappleParameters.hpp index 035e212b2..18375018c 100644 --- a/Runtime/World/CGrappleParameters.hpp +++ b/Runtime/World/CGrappleParameters.hpp @@ -1,32 +1,38 @@ #pragma once -namespace urde -{ +namespace urde { + +class CGrappleParameters { + float x0_a; + float x4_b; + float x8_c; + float xc_d; + float x10_e; + float x14_f; + float x18_g; + float x1c_h; + float x20_i; + float x24_j; + float x28_k; + bool x2c_lockSwingTurn; -class CGrappleParameters -{ - float x0_a; - float x4_b; - float x8_c; - float xc_d; - float x10_e; - float x14_f; - float x18_g; - float x1c_h; - float x20_i; - float x24_j; - float x28_k; - bool x2c_lockSwingTurn; public: - CGrappleParameters(float a, float b, float c, float d, - float e, float f, float g, float h, - float i, float j, float k, bool lockSwingTurn) - : x0_a(a), x4_b(b), x8_c(c), xc_d(d), - x10_e(e), x14_f(f), x18_g(g), x1c_h(h), - x20_i(i), x24_j(j), x28_k(k), x2c_lockSwingTurn(lockSwingTurn) {} + CGrappleParameters(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, + bool lockSwingTurn) + : x0_a(a) + , x4_b(b) + , x8_c(c) + , xc_d(d) + , x10_e(e) + , x14_f(f) + , x18_g(g) + , x1c_h(h) + , x20_i(i) + , x24_j(j) + , x28_k(k) + , x2c_lockSwingTurn(lockSwingTurn) {} - bool GetLockSwingTurn() const { return x2c_lockSwingTurn; } + bool GetLockSwingTurn() const { return x2c_lockSwingTurn; } }; -} - +} // namespace urde diff --git a/Runtime/World/CHUDBillboardEffect.cpp b/Runtime/World/CHUDBillboardEffect.cpp index dc0d3cba2..a99930b70 100644 --- a/Runtime/World/CHUDBillboardEffect.cpp +++ b/Runtime/World/CHUDBillboardEffect.cpp @@ -7,8 +7,7 @@ #include "World/CPlayer.hpp" #include "World/CWorld.hpp" -namespace urde -{ +namespace urde { u32 CHUDBillboardEffect::g_IndirectTexturedBillboardCount = 0; u32 CHUDBillboardEffect::g_BillboardCount = 0; @@ -18,115 +17,93 @@ CHUDBillboardEffect::CHUDBillboardEffect(const std::experimental::optional(*particle); - if (static_cast(*xe8_generator).IsIndirectTextured()) - ++g_IndirectTexturedBillboardCount; - } - else - { - xe8_generator = std::make_unique(*electric); - } - ++g_BillboardCount; - xe8_generator->SetModulationColor(color); - xe8_generator->SetLocalScale(xf8_localScale); + if (particle) { + x104_26_isElementGen = true; + xe8_generator = std::make_unique(*particle); + if (static_cast(*xe8_generator).IsIndirectTextured()) + ++g_IndirectTexturedBillboardCount; + } else { + xe8_generator = std::make_unique(*electric); + } + ++g_BillboardCount; + xe8_generator->SetModulationColor(color); + xe8_generator->SetLocalScale(xf8_localScale); } -CHUDBillboardEffect::~CHUDBillboardEffect() -{ - --g_BillboardCount; - if (xe8_generator->Get4CharId() == FOURCC('PART')) - if (static_cast(*xe8_generator).IsIndirectTextured()) - --g_IndirectTexturedBillboardCount; +CHUDBillboardEffect::~CHUDBillboardEffect() { + --g_BillboardCount; + if (xe8_generator->Get4CharId() == FOURCC('PART')) + if (static_cast(*xe8_generator).IsIndirectTextured()) + --g_IndirectTexturedBillboardCount; } void CHUDBillboardEffect::Accept(IVisitor& visitor) { visitor.Visit(this); } -float CHUDBillboardEffect::CalcGenRate() -{ - float f1; - if (g_BillboardCount + g_IndirectTexturedBillboardCount <= 4) - f1 = 0.f; - else - f1 = g_BillboardCount * 0.2f + g_IndirectTexturedBillboardCount * 0.1f; - return 1.f - std::min(f1, 0.8f); +float CHUDBillboardEffect::CalcGenRate() { + float f1; + if (g_BillboardCount + g_IndirectTexturedBillboardCount <= 4) + f1 = 0.f; + else + f1 = g_BillboardCount * 0.2f + g_IndirectTexturedBillboardCount * 0.1f; + return 1.f - std::min(f1, 0.8f); } -void CHUDBillboardEffect::Think(float dt, CStateManager& mgr) -{ - if (GetActive()) - { - mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId()); - float oldGenRate = xe8_generator->GetGeneratorRate(); - xe8_generator->SetGeneratorRate(oldGenRate * CalcGenRate()); - xe8_generator->Update(dt); - xe8_generator->SetGeneratorRate(oldGenRate); - if (!x104_27_runIndefinitely) - { - x108_timeoutTimer += dt; - if (x108_timeoutTimer > 30.f) - { - mgr.FreeScriptObject(GetUniqueId()); - return; - } - } - if (xe8_generator->IsSystemDeletable()) - mgr.FreeScriptObject(GetUniqueId()); +void CHUDBillboardEffect::Think(float dt, CStateManager& mgr) { + if (GetActive()) { + mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId()); + float oldGenRate = xe8_generator->GetGeneratorRate(); + xe8_generator->SetGeneratorRate(oldGenRate * CalcGenRate()); + xe8_generator->Update(dt); + xe8_generator->SetGeneratorRate(oldGenRate); + if (!x104_27_runIndefinitely) { + x108_timeoutTimer += dt; + if (x108_timeoutTimer > 30.f) { + mgr.FreeScriptObject(GetUniqueId()); + return; + } } + if (xe8_generator->IsSystemDeletable()) + mgr.FreeScriptObject(GetUniqueId()); + } } -void CHUDBillboardEffect::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - if (x104_25_enableRender && x104_24_renderAsParticleGen) - { - g_Renderer->AddParticleGen(*xe8_generator); - } +void CHUDBillboardEffect::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + if (x104_25_enableRender && x104_24_renderAsParticleGen) { + g_Renderer->AddParticleGen(*xe8_generator); + } } -void CHUDBillboardEffect::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - if (mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) - { - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - xe8_generator->SetGlobalTranslation(camXf * xec_translation); - xe8_generator->SetGlobalOrientation(camXf); - x104_25_enableRender = true; - } - else - { - x104_25_enableRender = false; - } - x104_24_renderAsParticleGen = !mgr.RenderLast(GetUniqueId()); +void CHUDBillboardEffect::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + if (mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) { + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + xe8_generator->SetGlobalTranslation(camXf * xec_translation); + xe8_generator->SetGlobalOrientation(camXf); + x104_25_enableRender = true; + } else { + x104_25_enableRender = false; + } + x104_24_renderAsParticleGen = !mgr.RenderLast(GetUniqueId()); } -void CHUDBillboardEffect::Render(const CStateManager& mgr) const -{ - if (x104_25_enableRender && !x104_24_renderAsParticleGen) - { - xe8_generator->Render(); - } +void CHUDBillboardEffect::Render(const CStateManager& mgr) const { + if (x104_25_enableRender && !x104_24_renderAsParticleGen) { + xe8_generator->Render(); + } } -float CHUDBillboardEffect::GetNearClipDistance(CStateManager& mgr) -{ - return mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetNearClipDistance() + 0.01f; +float CHUDBillboardEffect::GetNearClipDistance(CStateManager& mgr) { + return mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetNearClipDistance() + 0.01f; } -zeus::CVector3f CHUDBillboardEffect::GetScaleForPOV(CStateManager& mgr) -{ - return {0.155f, 1.f, 0.155f}; -} +zeus::CVector3f CHUDBillboardEffect::GetScaleForPOV(CStateManager& mgr) { return {0.155f, 1.f, 0.155f}; } -} +} // namespace urde diff --git a/Runtime/World/CHUDBillboardEffect.hpp b/Runtime/World/CHUDBillboardEffect.hpp index ff3b232f9..126c0057c 100644 --- a/Runtime/World/CHUDBillboardEffect.hpp +++ b/Runtime/World/CHUDBillboardEffect.hpp @@ -7,42 +7,40 @@ #include "Particle/CParticleElectric.hpp" #include "Particle/CParticleSwoosh.hpp" -namespace urde -{ +namespace urde { class CGenDescription; class CElectricDescription; -class CHUDBillboardEffect : public CEffect -{ - std::unique_ptr xe8_generator; - zeus::CVector3f xec_translation; - zeus::CVector3f xf8_localScale; - bool x104_24_renderAsParticleGen : 1; - bool x104_25_enableRender : 1; - bool x104_26_isElementGen : 1; - bool x104_27_runIndefinitely : 1; - float x108_timeoutTimer = 0.f; - static u32 g_IndirectTexturedBillboardCount; - static u32 g_BillboardCount; - static float CalcGenRate(); -public: - CHUDBillboardEffect(const std::experimental::optional>& particle, - const std::experimental::optional>& electric, - TUniqueId uid, bool active, std::string_view name, float dist, const zeus::CVector3f& scale0, - const zeus::CColor& color, const zeus::CVector3f& scale1, const zeus::CVector3f& translation); - ~CHUDBillboardEffect(); - void Accept(IVisitor& visitor); - void Think(float dt, CStateManager& mgr); - void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; - void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); - void Render(const CStateManager& mgr) const; - bool IsElementGen() const { return x104_26_isElementGen; } - void SetRunIndefinitely(bool b) { x104_27_runIndefinitely = b; } - CParticleGen* GetParticleGen() const { return xe8_generator.get(); } +class CHUDBillboardEffect : public CEffect { + std::unique_ptr xe8_generator; + zeus::CVector3f xec_translation; + zeus::CVector3f xf8_localScale; + bool x104_24_renderAsParticleGen : 1; + bool x104_25_enableRender : 1; + bool x104_26_isElementGen : 1; + bool x104_27_runIndefinitely : 1; + float x108_timeoutTimer = 0.f; + static u32 g_IndirectTexturedBillboardCount; + static u32 g_BillboardCount; + static float CalcGenRate(); - static float GetNearClipDistance(CStateManager& mgr); - static zeus::CVector3f GetScaleForPOV(CStateManager& mgr); +public: + CHUDBillboardEffect(const std::experimental::optional>& particle, + const std::experimental::optional>& electric, TUniqueId uid, + bool active, std::string_view name, float dist, const zeus::CVector3f& scale0, + const zeus::CColor& color, const zeus::CVector3f& scale1, const zeus::CVector3f& translation); + ~CHUDBillboardEffect(); + void Accept(IVisitor& visitor); + void Think(float dt, CStateManager& mgr); + void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; + void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); + void Render(const CStateManager& mgr) const; + bool IsElementGen() const { return x104_26_isElementGen; } + void SetRunIndefinitely(bool b) { x104_27_runIndefinitely = b; } + CParticleGen* GetParticleGen() const { return xe8_generator.get(); } + + static float GetNearClipDistance(CStateManager& mgr); + static zeus::CVector3f GetScaleForPOV(CStateManager& mgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CHUDMemoParms.hpp b/Runtime/World/CHUDMemoParms.hpp index 712c6a4a9..fc54b8b3f 100644 --- a/Runtime/World/CHUDMemoParms.hpp +++ b/Runtime/World/CHUDMemoParms.hpp @@ -2,32 +2,27 @@ #include "IOStreams.hpp" -namespace urde -{ +namespace urde { -class CHUDMemoParms -{ - float x0_dispTime = 0.f; - bool x4_clearMemoWindow = false; - bool x5_fadeOutOnly = false; - bool x6_hintMemo = false; +class CHUDMemoParms { + float x0_dispTime = 0.f; + bool x4_clearMemoWindow = false; + bool x5_fadeOutOnly = false; + bool x6_hintMemo = false; public: - CHUDMemoParms() = default; - CHUDMemoParms(float dispTime, bool clearMemoWindow, bool fadeOutOnly, bool hintMemo) - : x0_dispTime(dispTime), x4_clearMemoWindow(clearMemoWindow), - x5_fadeOutOnly(fadeOutOnly), x6_hintMemo(hintMemo) {} - CHUDMemoParms(CInputStream& in) - { - x0_dispTime = in.readFloatBig(); - x4_clearMemoWindow = in.readBool(); - } + CHUDMemoParms() = default; + CHUDMemoParms(float dispTime, bool clearMemoWindow, bool fadeOutOnly, bool hintMemo) + : x0_dispTime(dispTime), x4_clearMemoWindow(clearMemoWindow), x5_fadeOutOnly(fadeOutOnly), x6_hintMemo(hintMemo) {} + CHUDMemoParms(CInputStream& in) { + x0_dispTime = in.readFloatBig(); + x4_clearMemoWindow = in.readBool(); + } - float GetDisplayTime() const { return x0_dispTime; } - bool IsClearMemoWindow() const { return x4_clearMemoWindow; } - bool IsFadeOutOnly() const { return x5_fadeOutOnly; } - bool IsHintMemo() const { return x6_hintMemo; } + float GetDisplayTime() const { return x0_dispTime; } + bool IsClearMemoWindow() const { return x4_clearMemoWindow; } + bool IsFadeOutOnly() const { return x5_fadeOutOnly; } + bool IsHintMemo() const { return x6_hintMemo; } }; -} - +} // namespace urde diff --git a/Runtime/World/CHealthInfo.cpp b/Runtime/World/CHealthInfo.cpp index 7b07fbc69..83ac1f5bc 100644 --- a/Runtime/World/CHealthInfo.cpp +++ b/Runtime/World/CHealthInfo.cpp @@ -1,13 +1,11 @@ #include "CHealthInfo.hpp" -namespace urde -{ +namespace urde { -CHealthInfo::CHealthInfo(CInputStream& in) -{ - in.readUint32Big(); - x0_health = in.readFloatBig(); - x4_knockbackResistance = in.readFloatBig(); +CHealthInfo::CHealthInfo(CInputStream& in) { + in.readUint32Big(); + x0_health = in.readFloatBig(); + x4_knockbackResistance = in.readFloatBig(); } -} +} // namespace urde diff --git a/Runtime/World/CHealthInfo.hpp b/Runtime/World/CHealthInfo.hpp index ce46c5a78..d9d1426f0 100644 --- a/Runtime/World/CHealthInfo.hpp +++ b/Runtime/World/CHealthInfo.hpp @@ -2,30 +2,21 @@ #include "Runtime/RetroTypes.hpp" -namespace urde -{ +namespace urde { + +class CHealthInfo { + float x0_health; + float x4_knockbackResistance; -class CHealthInfo -{ - float x0_health; - float x4_knockbackResistance; public: - CHealthInfo(float hp) - : x0_health(hp), - x4_knockbackResistance(0.f) - { - } + CHealthInfo(float hp) : x0_health(hp), x4_knockbackResistance(0.f) {} - CHealthInfo(float hp, float resist) - : x0_health(hp), - x4_knockbackResistance(resist) - {} + CHealthInfo(float hp, float resist) : x0_health(hp), x4_knockbackResistance(resist) {} - CHealthInfo(CInputStream& in); - void SetHP(float hp) { x0_health = hp; } - float GetHP() const {return x0_health;} - float GetKnockbackResistance() const {return x4_knockbackResistance;} + CHealthInfo(CInputStream& in); + void SetHP(float hp) { x0_health = hp; } + float GetHP() const { return x0_health; } + float GetKnockbackResistance() const { return x4_knockbackResistance; } }; -} - +} // namespace urde diff --git a/Runtime/World/CIceImpact.cpp b/Runtime/World/CIceImpact.cpp index 578ed5daf..87a2cc9c9 100644 --- a/Runtime/World/CIceImpact.cpp +++ b/Runtime/World/CIceImpact.cpp @@ -1,20 +1,13 @@ #include "CIceImpact.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CIceImpact::CIceImpact(const TLockedToken& particle, TUniqueId uid, TAreaId aid, - bool active, std::string_view name, const zeus::CTransform& xf, u32 flags, - const zeus::CVector3f& scale, const zeus::CColor& color) -: CEffect(uid, CEntityInfo(aid, CEntity::NullConnectionList), active, name, xf) -{ +CIceImpact::CIceImpact(const TLockedToken& particle, TUniqueId uid, TAreaId aid, bool active, + std::string_view name, const zeus::CTransform& xf, u32 flags, const zeus::CVector3f& scale, + const zeus::CColor& color) +: CEffect(uid, CEntityInfo(aid, CEntity::NullConnectionList), active, name, xf) {} -} +void CIceImpact::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CIceImpact::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -} +} // namespace urde diff --git a/Runtime/World/CIceImpact.hpp b/Runtime/World/CIceImpact.hpp index f9754e91c..40d205205 100644 --- a/Runtime/World/CIceImpact.hpp +++ b/Runtime/World/CIceImpact.hpp @@ -2,17 +2,14 @@ #include "CEffect.hpp" -namespace urde -{ +namespace urde { -class CIceImpact : public CEffect -{ +class CIceImpact : public CEffect { public: - CIceImpact(const TLockedToken& particle, TUniqueId uid, TAreaId aid, - bool active, std::string_view name, const zeus::CTransform& xf, u32 flags, - const zeus::CVector3f& scale, const zeus::CColor& color); - void Accept(IVisitor& visitor); + CIceImpact(const TLockedToken& particle, TUniqueId uid, TAreaId aid, bool active, + std::string_view name, const zeus::CTransform& xf, u32 flags, const zeus::CVector3f& scale, + const zeus::CColor& color); + void Accept(IVisitor& visitor); }; -} - +} // namespace urde diff --git a/Runtime/World/CKnockBackController.cpp b/Runtime/World/CKnockBackController.cpp index d5e6b4dfa..8f7a7ec56 100644 --- a/Runtime/World/CKnockBackController.cpp +++ b/Runtime/World/CKnockBackController.cpp @@ -3,11 +3,9 @@ #include "CStateManager.hpp" #include "Character/CPASAnimParmData.hpp" -namespace urde -{ +namespace urde { -static const CKnockBackController::KnockBackParms KnockBackParmsTable[3][19][4] = -{ +static const CKnockBackController::KnockBackParms KnockBackParmsTable[3][19][4] = { { { {EKnockBackAnimationState::KnockBack, EKnockBackAnimationFollowUp::None, 0.000000f, -1.000000f}, @@ -358,314 +356,266 @@ static const CKnockBackController::KnockBackParms KnockBackParmsTable[3][19][4] }, }; -CKnockBackController::CKnockBackController(EKnockBackVariant variant) -: x0_variant(variant) -{ - x81_24_autoResetImpulse = true; - x81_25_enableFreeze = true; - x81_27_enableBurn = true; - x81_28_enableBurnDeath = true; - x81_29_enableExplodeDeath = true; - x81_30_enableLaggedBurnDeath = true; - x81_31_ = true; - x82_24_ = true; - for (int i = 0; i < 4; ++i) - { - x24_.push_back(std::make_pair(0.f, FLT_MAX)); - x80_availableStates.set(i); +CKnockBackController::CKnockBackController(EKnockBackVariant variant) : x0_variant(variant) { + x81_24_autoResetImpulse = true; + x81_25_enableFreeze = true; + x81_27_enableBurn = true; + x81_28_enableBurnDeath = true; + x81_29_enableExplodeDeath = true; + x81_30_enableLaggedBurnDeath = true; + x81_31_ = true; + x82_24_ = true; + for (int i = 0; i < 4; ++i) { + x24_.push_back(std::make_pair(0.f, FLT_MAX)); + x80_availableStates.set(i); + } +} + +static const float ImpulseDurationTable[] = {0.1f, 0.3f}; + +void CKnockBackController::ApplyImpulse(float dt, CPatterned& parent) { + x60_impulseRemTime = std::max(0.f, x60_impulseRemTime - dt); + if (!parent.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) && x60_impulseRemTime > 0.f) { + float remFac = 1.f; + if (x20_impulseDurationIdx == 1) + remFac = x60_impulseRemTime / ImpulseDurationTable[x20_impulseDurationIdx]; + parent.ApplyImpulseWR( + parent.GetMoveToORImpulseWR( + parent.GetTransform().transposeRotate( + x50_impulseDir * (remFac * x5c_impulseMag * dt / ImpulseDurationTable[x20_impulseDurationIdx])), + dt), + zeus::CAxisAngle::sIdentity); + } +} + +bool CKnockBackController::TickDeferredTimer(float dt) { + x68_deferRemTime -= dt; + if (x14_deferWeaponType != EWeaponType::None) + return x68_deferRemTime <= 0.f; + return false; +} + +EKnockBackCharacterState CKnockBackController::GetKnockBackCharacterState(CPatterned& parent) { + if (parent.BodyController()->IsFrozen()) + return parent.IsAlive() ? EKnockBackCharacterState::FrozenAlive : EKnockBackCharacterState::FrozenDead; + return parent.IsAlive() ? EKnockBackCharacterState::Alive : EKnockBackCharacterState::Dead; +} + +void CKnockBackController::ValidateState(CPatterned& parent) { + if (x4_activeParms.x0_animState < x18_minAnimState) + x4_activeParms.x0_animState = x18_minAnimState; + else if (x4_activeParms.x0_animState > x1c_maxAnimState) + x4_activeParms.x0_animState = x1c_maxAnimState; + + EKnockBackAnimationState useState = EKnockBackAnimationState::Invalid; + if (parent.IsAlive()) { + if (parent.BodyController()->HasBodyState(pas::EAnimationState::Hurled) && x80_availableStates.test(3) && + x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled) { + useState = EKnockBackAnimationState::Hurled; + } else if (parent.BodyController()->HasBodyState(pas::EAnimationState::KnockBack) && x80_availableStates.test(2) && + x4_activeParms.x0_animState >= EKnockBackAnimationState::KnockBack) { + useState = EKnockBackAnimationState::KnockBack; + } else if (parent.BodyController()->HasBodyState(pas::EAnimationState::AdditiveFlinch) && + x80_availableStates.test(1) && x4_activeParms.x0_animState >= EKnockBackAnimationState::Flinch) { + useState = EKnockBackAnimationState::Flinch; } -} - -static const float ImpulseDurationTable[] = { 0.1f, 0.3f }; - -void CKnockBackController::ApplyImpulse(float dt, CPatterned& parent) -{ - x60_impulseRemTime = std::max(0.f, x60_impulseRemTime - dt); - if (!parent.GetMaterialList().HasMaterial(EMaterialTypes::Immovable) && x60_impulseRemTime > 0.f) - { - float remFac = 1.f; - if (x20_impulseDurationIdx == 1) - remFac = x60_impulseRemTime / ImpulseDurationTable[x20_impulseDurationIdx]; - parent.ApplyImpulseWR( - parent.GetMoveToORImpulseWR( - parent.GetTransform().transposeRotate(x50_impulseDir * - (remFac * x5c_impulseMag * dt / ImpulseDurationTable[x20_impulseDurationIdx])), dt), - zeus::CAxisAngle::sIdentity); + } else { + if (parent.BodyController()->HasBodyState(pas::EAnimationState::Fall) && x80_availableStates.test(4) && + (x4_activeParms.x0_animState >= EKnockBackAnimationState::Fall || + (!parent.BodyController()->HasBodyState(pas::EAnimationState::Hurled) && + x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled))) { + useState = EKnockBackAnimationState::Fall; + } else if (parent.BodyController()->HasBodyState(pas::EAnimationState::Hurled) && x80_availableStates.test(3) && + x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled) { + useState = EKnockBackAnimationState::Hurled; } + } + + x4_activeParms.x0_animState = + (useState != EKnockBackAnimationState::Invalid) ? useState : EKnockBackAnimationState::None; + + bool disableFollowup = false; + switch (x4_activeParms.x4_animFollowup) { + case EKnockBackAnimationFollowUp::Freeze: + disableFollowup = !x81_25_enableFreeze; + break; + case EKnockBackAnimationFollowUp::Shock: + disableFollowup = !x81_26_enableShock; + break; + case EKnockBackAnimationFollowUp::Burn: + disableFollowup = !x81_27_enableBurn; + break; + case EKnockBackAnimationFollowUp::ExplodeDeath: + disableFollowup = !x81_29_enableExplodeDeath; + break; + case EKnockBackAnimationFollowUp::IceDeath: + disableFollowup = !x81_29_enableExplodeDeath; + break; + case EKnockBackAnimationFollowUp::BurnDeath: + disableFollowup = !x81_28_enableBurnDeath; + break; + case EKnockBackAnimationFollowUp::LaggedBurnDeath: + disableFollowup = !x81_30_enableLaggedBurnDeath; + break; + default: + break; + } + + if (disableFollowup) { + x4_activeParms.x4_animFollowup = EKnockBackAnimationFollowUp::None; + x4_activeParms.x8_followupDuration = 0.f; + } } -bool CKnockBackController::TickDeferredTimer(float dt) -{ - x68_deferRemTime -= dt; - if (x14_deferWeaponType != EWeaponType::None) - return x68_deferRemTime <= 0.f; - return false; +float CKnockBackController::CalculateExtraHurlVelocity(CStateManager& mgr, float magnitude, float kbResistance) { + if (magnitude > kbResistance) + return (1.1f - 0.2f * mgr.GetActiveRandom()->Float()) * 2.f * (magnitude - kbResistance); + return 0.f; } -EKnockBackCharacterState CKnockBackController::GetKnockBackCharacterState(CPatterned& parent) -{ - if (parent.BodyController()->IsFrozen()) - return parent.IsAlive() ? EKnockBackCharacterState::FrozenAlive : EKnockBackCharacterState::FrozenDead; - return parent.IsAlive() ? EKnockBackCharacterState::Alive : EKnockBackCharacterState::Dead; -} - -void CKnockBackController::ValidateState(CPatterned& parent) -{ - if (x4_activeParms.x0_animState < x18_minAnimState) - x4_activeParms.x0_animState = x18_minAnimState; - else if (x4_activeParms.x0_animState > x1c_maxAnimState) - x4_activeParms.x0_animState = x1c_maxAnimState; - - EKnockBackAnimationState useState = EKnockBackAnimationState::Invalid; - if (parent.IsAlive()) - { - if (parent.BodyController()->HasBodyState(pas::EAnimationState::Hurled) && - x80_availableStates.test(3) && x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled) - { - useState = EKnockBackAnimationState::Hurled; - } - else if (parent.BodyController()->HasBodyState(pas::EAnimationState::KnockBack) && - x80_availableStates.test(2) && x4_activeParms.x0_animState >= EKnockBackAnimationState::KnockBack) - { - useState = EKnockBackAnimationState::KnockBack; - } - else if (parent.BodyController()->HasBodyState(pas::EAnimationState::AdditiveFlinch) && - x80_availableStates.test(1) && x4_activeParms.x0_animState >= EKnockBackAnimationState::Flinch) - { - useState = EKnockBackAnimationState::Flinch; - } +void CKnockBackController::DoKnockBackAnimation(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, + float magnitude) { + switch (x4_activeParms.x0_animState) { + case EKnockBackAnimationState::Hurled: { + float hurlVel = 5.f; + if (CHealthInfo* hInfo = parent.HealthInfo(mgr)) + hurlVel += CalculateExtraHurlVelocity(mgr, magnitude, hInfo->GetKnockbackResistance()); + hurlVel = std::sqrt(parent.GetGravityConstant() * 0.5f * hurlVel); + zeus::CVector3f backUpVec = backVec + backVec.magnitude() * zeus::CVector3f::skUp; + if (backUpVec.canBeNormalized()) { + parent.BodyController()->GetCommandMgr().DeliverCmd(CBCHurledCmd(-backVec, backUpVec.normalized() * hurlVel)); + parent.SetMomentumWR({0.f, 0.f, parent.GetGravityConstant() * -parent.GetMass()}); } + break; + } + case EKnockBackAnimationState::Fall: { + parent.BodyController()->GetCommandMgr().DeliverCmd(CBCKnockDownCmd(-backVec, x7c_severity)); + break; + } + case EKnockBackAnimationState::KnockBack: { + parent.BodyController()->GetCommandMgr().DeliverCmd(CBCKnockBackCmd(-backVec, x7c_severity)); + break; + } + case EKnockBackAnimationState::Flinch: { + std::pair bestAnim = + parent.BodyController()->GetPASDatabase().FindBestAnimation(CPASAnimParmData(23), *mgr.GetActiveRandom(), -1); + if (bestAnim.first > 0.f) { + parent.ModelData()->AnimationData()->AddAdditiveAnimation(bestAnim.second, 1.f, false, true); + x64_flinchRemTime = + std::max(parent.ModelData()->AnimationData()->GetAnimationDuration(bestAnim.second), x64_flinchRemTime); + } + break; + } + default: + break; + } +} + +void CKnockBackController::ResetKnockBackImpulse(CPatterned& parent, const zeus::CVector3f& backVec, float magnitude) { + if (x81_24_autoResetImpulse && x4_activeParms.x0_animState == EKnockBackAnimationState::KnockBack && + x4_activeParms.x4_animFollowup != EKnockBackAnimationFollowUp::Freeze) { + x50_impulseDir = backVec.canBeNormalized() ? backVec.normalized() : -parent.GetTransform().basis[1]; + if (x60_impulseRemTime <= 0.f) + x5c_impulseMag = magnitude; else - { - if (parent.BodyController()->HasBodyState(pas::EAnimationState::Fall) && x80_availableStates.test(4) && - (x4_activeParms.x0_animState >= EKnockBackAnimationState::Fall || - (!parent.BodyController()->HasBodyState(pas::EAnimationState::Hurled) - && x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled))) - { - useState = EKnockBackAnimationState::Fall; - } - else if (parent.BodyController()->HasBodyState(pas::EAnimationState::Hurled) && - x80_availableStates.test(3) && x4_activeParms.x0_animState >= EKnockBackAnimationState::Hurled) - { - useState = EKnockBackAnimationState::Hurled; - } - } - - x4_activeParms.x0_animState = (useState != EKnockBackAnimationState::Invalid) ? - useState : EKnockBackAnimationState::None; - - bool disableFollowup = false; - switch (x4_activeParms.x4_animFollowup) - { - case EKnockBackAnimationFollowUp::Freeze: - disableFollowup = !x81_25_enableFreeze; - break; - case EKnockBackAnimationFollowUp::Shock: - disableFollowup = !x81_26_enableShock; - break; - case EKnockBackAnimationFollowUp::Burn: - disableFollowup = !x81_27_enableBurn; - break; - case EKnockBackAnimationFollowUp::ExplodeDeath: - disableFollowup = !x81_29_enableExplodeDeath; - break; - case EKnockBackAnimationFollowUp::IceDeath: - disableFollowup = !x81_29_enableExplodeDeath; - break; - case EKnockBackAnimationFollowUp::BurnDeath: - disableFollowup = !x81_28_enableBurnDeath; - break; - case EKnockBackAnimationFollowUp::LaggedBurnDeath: - disableFollowup = !x81_30_enableLaggedBurnDeath; - break; - default: - break; - } - - if (disableFollowup) - { - x4_activeParms.x4_animFollowup = EKnockBackAnimationFollowUp::None; - x4_activeParms.x8_followupDuration = 0.f; - } + x5c_impulseMag += magnitude * (1.f - x60_impulseRemTime / ImpulseDurationTable[x20_impulseDurationIdx]); + x60_impulseRemTime = ImpulseDurationTable[x20_impulseDurationIdx]; + } } -float CKnockBackController::CalculateExtraHurlVelocity(CStateManager& mgr, float magnitude, float kbResistance) -{ - if (magnitude > kbResistance) - return (1.1f - 0.2f * mgr.GetActiveRandom()->Float()) * 2.f * (magnitude - kbResistance); - return 0.f; +void CKnockBackController::DoDeferredKnockBack(CStateManager& mgr, CPatterned& parent) { + if (x14_deferWeaponType == EWeaponType::Wave) { + x4_activeParms = KnockBackParmsTable[int(x0_variant)][int(EKnockBackWeaponType::WaveComboedDirect)] + [int(GetKnockBackCharacterState(parent))]; + ValidateState(parent); + if (CHealthInfo* hInfo = parent.HealthInfo(mgr)) { + zeus::CVector3f backVec = -parent.GetTransform().basis[1]; + DoKnockBackAnimation(backVec, mgr, parent, 10.f); + ResetKnockBackImpulse(parent, backVec, 2.f); + x82_25_inDeferredKnockBack = true; + parent.KnockBack(backVec, mgr, CDamageInfo({x14_deferWeaponType, false, true, false}, 0.f, 0.f, 10.f), + EKnockBackType::Radius, x82_25_inDeferredKnockBack, 10.f); + x82_25_inDeferredKnockBack = false; + } + } + x68_deferRemTime = 0.f; + x4_activeParms = KnockBackParms{}; + x14_deferWeaponType = EWeaponType::None; } -void CKnockBackController::DoKnockBackAnimation(const zeus::CVector3f& backVec, CStateManager& mgr, - CPatterned& parent, float magnitude) -{ - switch (x4_activeParms.x0_animState) - { - case EKnockBackAnimationState::Hurled: - { - float hurlVel = 5.f; - if (CHealthInfo* hInfo = parent.HealthInfo(mgr)) - hurlVel += CalculateExtraHurlVelocity(mgr, magnitude, hInfo->GetKnockbackResistance()); - hurlVel = std::sqrt(parent.GetGravityConstant() * 0.5f * hurlVel); - zeus::CVector3f backUpVec = backVec + backVec.magnitude() * zeus::CVector3f::skUp; - if (backUpVec.canBeNormalized()) - { - parent.BodyController()->GetCommandMgr().DeliverCmd( - CBCHurledCmd(-backVec, backUpVec.normalized() * hurlVel)); - parent.SetMomentumWR({0.f, 0.f, parent.GetGravityConstant() * -parent.GetMass()}); - } - break; - } - case EKnockBackAnimationState::Fall: - { - parent.BodyController()->GetCommandMgr().DeliverCmd(CBCKnockDownCmd(-backVec, x7c_severity)); - break; - } - case EKnockBackAnimationState::KnockBack: - { - parent.BodyController()->GetCommandMgr().DeliverCmd(CBCKnockBackCmd(-backVec, x7c_severity)); - break; - } - case EKnockBackAnimationState::Flinch: - { - std::pair bestAnim = - parent.BodyController()->GetPASDatabase().FindBestAnimation( - CPASAnimParmData(23), *mgr.GetActiveRandom(), -1); - if (bestAnim.first > 0.f) - { - parent.ModelData()->AnimationData()->AddAdditiveAnimation(bestAnim.second, 1.f, false, true); - x64_flinchRemTime = std::max( - parent.ModelData()->AnimationData()->GetAnimationDuration(bestAnim.second), x64_flinchRemTime); - } - break; - } - default: - break; - } +void CKnockBackController::sub80233d40(int i, float f1, float f2) { + if (i < 0 || i > 4) + return; + x24_[i] = std::make_pair(f1, f2); } -void CKnockBackController::ResetKnockBackImpulse(CPatterned& parent, const zeus::CVector3f& backVec, float magnitude) -{ - if (x81_24_autoResetImpulse && x4_activeParms.x0_animState == EKnockBackAnimationState::KnockBack && - x4_activeParms.x4_animFollowup != EKnockBackAnimationFollowUp::Freeze) - { - x50_impulseDir = backVec.canBeNormalized() ? backVec.normalized() : -parent.GetTransform().basis[1]; - if (x60_impulseRemTime <= 0.f) - x5c_impulseMag = magnitude; - else - x5c_impulseMag += magnitude * (1.f - x60_impulseRemTime / ImpulseDurationTable[x20_impulseDurationIdx]); - x60_impulseRemTime = ImpulseDurationTable[x20_impulseDurationIdx]; - } +void CKnockBackController::SetAutoResetImpulse(bool b) { + x81_24_autoResetImpulse = b; + if (!b) { + x5c_impulseMag = 0.f; + x60_impulseRemTime = 0.f; + } } -void CKnockBackController::DoDeferredKnockBack(CStateManager& mgr, CPatterned& parent) -{ - if (x14_deferWeaponType == EWeaponType::Wave) - { - x4_activeParms = KnockBackParmsTable[int(x0_variant)][int(EKnockBackWeaponType::WaveComboedDirect)] - [int(GetKnockBackCharacterState(parent))]; - ValidateState(parent); - if (CHealthInfo* hInfo = parent.HealthInfo(mgr)) - { - zeus::CVector3f backVec = -parent.GetTransform().basis[1]; - DoKnockBackAnimation(backVec, mgr, parent, 10.f); - ResetKnockBackImpulse(parent, backVec, 2.f); - x82_25_inDeferredKnockBack = true; - parent.KnockBack(backVec, mgr, - CDamageInfo({x14_deferWeaponType, false, true, false}, 0.f, 0.f, 10.f), - EKnockBackType::Radius, x82_25_inDeferredKnockBack, 10.f); - x82_25_inDeferredKnockBack = false; - } - } - x68_deferRemTime = 0.f; - x4_activeParms = KnockBackParms{}; - x14_deferWeaponType = EWeaponType::None; -} - -void CKnockBackController::sub80233d40(int i, float f1, float f2) -{ - if (i < 0 || i > 4) - return; - x24_[i] = std::make_pair(f1, f2); -} - -void CKnockBackController::SetAutoResetImpulse(bool b) -{ - x81_24_autoResetImpulse = b; - if (!b) - { - x5c_impulseMag = 0.f; - x60_impulseRemTime = 0.f; - } -} - -void CKnockBackController::Update(float dt, CStateManager& mgr, CPatterned& parent) -{ - ApplyImpulse(dt, parent); - x64_flinchRemTime -= dt; - if (TickDeferredTimer(dt)) - DoDeferredKnockBack(mgr, parent); - if (x82_26_locomotionDuringElectrocution && parent.BodyController()->IsElectrocuting()) - parent.BodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Locomotion)); +void CKnockBackController::Update(float dt, CStateManager& mgr, CPatterned& parent) { + ApplyImpulse(dt, parent); + x64_flinchRemTime -= dt; + if (TickDeferredTimer(dt)) + DoDeferredKnockBack(mgr, parent); + if (x82_26_locomotionDuringElectrocution && parent.BodyController()->IsElectrocuting()) + parent.BodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Locomotion)); } EKnockBackWeaponType CKnockBackController::GetKnockBackWeaponType(const CDamageInfo& info, EWeaponType wType, - EKnockBackType type) -{ - int stacking = 0; - if (info.GetWeaponMode().IsCharged()) - stacking = 1; - else if (info.GetWeaponMode().IsComboed()) - stacking = 2; - if (wType > EWeaponType::Phazon) - return EKnockBackWeaponType::Invalid; - switch (wType) - { - case EWeaponType::Power: - return EKnockBackWeaponType(type != EKnockBackType::Direct ? stacking : stacking + 1); - case EWeaponType::Ice: - return EKnockBackWeaponType(type != EKnockBackType::Direct ? stacking + 8 : stacking + 9); - case EWeaponType::Wave: - return EKnockBackWeaponType(stacking + 4); - case EWeaponType::Plasma: - return EKnockBackWeaponType(stacking + 12); - case EWeaponType::Bomb: - return EKnockBackWeaponType::Bomb; - case EWeaponType::PowerBomb: - return EKnockBackWeaponType::PowerBomb; - case EWeaponType::Missile: - return EKnockBackWeaponType::Missile; - case EWeaponType::Phazon: - return EKnockBackWeaponType::Phazon; - default: - return EKnockBackWeaponType::Invalid; - } + EKnockBackType type) { + int stacking = 0; + if (info.GetWeaponMode().IsCharged()) + stacking = 1; + else if (info.GetWeaponMode().IsComboed()) + stacking = 2; + if (wType > EWeaponType::Phazon) + return EKnockBackWeaponType::Invalid; + switch (wType) { + case EWeaponType::Power: + return EKnockBackWeaponType(type != EKnockBackType::Direct ? stacking : stacking + 1); + case EWeaponType::Ice: + return EKnockBackWeaponType(type != EKnockBackType::Direct ? stacking + 8 : stacking + 9); + case EWeaponType::Wave: + return EKnockBackWeaponType(stacking + 4); + case EWeaponType::Plasma: + return EKnockBackWeaponType(stacking + 12); + case EWeaponType::Bomb: + return EKnockBackWeaponType::Bomb; + case EWeaponType::PowerBomb: + return EKnockBackWeaponType::PowerBomb; + case EWeaponType::Missile: + return EKnockBackWeaponType::Missile; + case EWeaponType::Phazon: + return EKnockBackWeaponType::Phazon; + default: + return EKnockBackWeaponType::Invalid; + } } -void CKnockBackController::SelectDamageState(CPatterned& parent, const CDamageInfo& info, - EWeaponType wType, EKnockBackType type) -{ - EKnockBackWeaponType weaponType = GetKnockBackWeaponType(info, wType, type); - if (weaponType != EKnockBackWeaponType::Invalid) - { - x4_activeParms = KnockBackParmsTable[int(x0_variant)][int(weaponType)] - [int(GetKnockBackCharacterState(parent))]; - ValidateState(parent); - } +void CKnockBackController::SelectDamageState(CPatterned& parent, const CDamageInfo& info, EWeaponType wType, + EKnockBackType type) { + EKnockBackWeaponType weaponType = GetKnockBackWeaponType(info, wType, type); + if (weaponType != EKnockBackWeaponType::Invalid) { + x4_activeParms = KnockBackParmsTable[int(x0_variant)][int(weaponType)][int(GetKnockBackCharacterState(parent))]; + ValidateState(parent); + } } void CKnockBackController::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, - const CDamageInfo& info, EKnockBackType type, float magnitude) -{ - if (!x82_25_inDeferredKnockBack) - { - zeus::CVector3f vec(backVec.toVec2f()); - if (!vec.isMagnitudeSafe()) - vec = -parent.GetTransform().basis[1]; - SelectDamageState(parent, info, info.GetWeaponMode().GetType(), type); - DoKnockBackAnimation(vec, mgr, parent, magnitude); - ResetKnockBackImpulse(parent, vec, 2.f); - } + const CDamageInfo& info, EKnockBackType type, float magnitude) { + if (!x82_25_inDeferredKnockBack) { + zeus::CVector3f vec(backVec.toVec2f()); + if (!vec.isMagnitudeSafe()) + vec = -parent.GetTransform().basis[1]; + SelectDamageState(parent, info, info.GetWeaponMode().GetType(), type); + DoKnockBackAnimation(vec, mgr, parent, magnitude); + ResetKnockBackImpulse(parent, vec, 2.f); + } } -} +} // namespace urde diff --git a/Runtime/World/CKnockBackController.hpp b/Runtime/World/CKnockBackController.hpp index 8f1bf0367..7f3484893 100644 --- a/Runtime/World/CKnockBackController.hpp +++ b/Runtime/World/CKnockBackController.hpp @@ -4,162 +4,139 @@ #include "Character/CharacterCommon.hpp" #include "Weapon/WeaponCommon.hpp" -namespace urde -{ +namespace urde { class CPatterned; class CDamageInfo; -enum class EKnockBackType -{ - Direct, - Radius +enum class EKnockBackType { Direct, Radius }; + +enum class EKnockBackVariant { Small, Medium, Large }; + +enum class EKnockBackWeaponType { + Invalid = -1, + Power, + PowerCharged, + PowerComboed, + PowerComboedDirect, + Wave, + WaveCharged, + WaveComboed, + WaveComboedDirect, + Ice, + IceCharged, + IceComboed, + IceComboedDirect, + Plasma, + PlasmaCharged, + PlasmaComboed, + Missile, + Bomb, + PowerBomb, + Phazon }; -enum class EKnockBackVariant -{ - Small, - Medium, - Large +enum class EKnockBackCharacterState { Alive, Dead, FrozenAlive, FrozenDead }; + +enum class EKnockBackAnimationState { Invalid = -1, None, Flinch, KnockBack, Hurled, Fall }; + +enum class EKnockBackAnimationFollowUp { + Invalid = -1, + None, + Freeze, + Shock, + Burn, + PhazeOut, + Death, + ExplodeDeath, + IceDeath, + BurnDeath, + LaggedBurnDeath }; -enum class EKnockBackWeaponType -{ - Invalid = -1, - Power, - PowerCharged, - PowerComboed, - PowerComboedDirect, - Wave, - WaveCharged, - WaveComboed, - WaveComboedDirect, - Ice, - IceCharged, - IceComboed, - IceComboedDirect, - Plasma, - PlasmaCharged, - PlasmaComboed, - Missile, - Bomb, - PowerBomb, - Phazon -}; - -enum class EKnockBackCharacterState -{ - Alive, - Dead, - FrozenAlive, - FrozenDead -}; - -enum class EKnockBackAnimationState -{ - Invalid = -1, - None, - Flinch, - KnockBack, - Hurled, - Fall -}; - -enum class EKnockBackAnimationFollowUp -{ - Invalid = -1, - None, - Freeze, - Shock, - Burn, - PhazeOut, - Death, - ExplodeDeath, - IceDeath, - BurnDeath, - LaggedBurnDeath -}; - -class CKnockBackController -{ +class CKnockBackController { public: - struct KnockBackParms - { - EKnockBackAnimationState x0_animState; - EKnockBackAnimationFollowUp x4_animFollowup; - float x8_followupDuration; - float xc_intoFreezeDur; - }; + struct KnockBackParms { + EKnockBackAnimationState x0_animState; + EKnockBackAnimationFollowUp x4_animFollowup; + float x8_followupDuration; + float xc_intoFreezeDur; + }; + private: - friend class CPatterned; - EKnockBackVariant x0_variant; - KnockBackParms x4_activeParms; - EWeaponType x14_deferWeaponType = EWeaponType::None; - EKnockBackAnimationState x18_minAnimState = EKnockBackAnimationState::None; - EKnockBackAnimationState x1c_maxAnimState = EKnockBackAnimationState::Fall; - u32 x20_impulseDurationIdx = 0; - rstl::reserved_vector, 4> x24_; - zeus::CVector3f x50_impulseDir; - float x5c_impulseMag = 0.f; - float x60_impulseRemTime = 0.f; - float x64_flinchRemTime = 0.f; - float x68_deferRemTime = 0.f; - u32 x6c_ = 0; - u32 x70_ = 0; - u32 x74_ = 0; - pas::ESeverity x7c_severity = pas::ESeverity::One; - std::bitset<5> x80_availableStates; - union - { - struct - { - bool x81_24_autoResetImpulse : 1; // t - bool x81_25_enableFreeze : 1; // t - bool x81_26_enableShock : 1; - bool x81_27_enableBurn : 1; // t - bool x81_28_enableBurnDeath : 1; // t - bool x81_29_enableExplodeDeath : 1; // t - bool x81_30_enableLaggedBurnDeath : 1; // t - bool x81_31_ : 1; // t - bool x82_24_ : 1; // t - bool x82_25_inDeferredKnockBack : 1; - bool x82_26_locomotionDuringElectrocution : 1; - }; - u32 dummy = 0; + friend class CPatterned; + EKnockBackVariant x0_variant; + KnockBackParms x4_activeParms; + EWeaponType x14_deferWeaponType = EWeaponType::None; + EKnockBackAnimationState x18_minAnimState = EKnockBackAnimationState::None; + EKnockBackAnimationState x1c_maxAnimState = EKnockBackAnimationState::Fall; + u32 x20_impulseDurationIdx = 0; + rstl::reserved_vector, 4> x24_; + zeus::CVector3f x50_impulseDir; + float x5c_impulseMag = 0.f; + float x60_impulseRemTime = 0.f; + float x64_flinchRemTime = 0.f; + float x68_deferRemTime = 0.f; + u32 x6c_ = 0; + u32 x70_ = 0; + u32 x74_ = 0; + pas::ESeverity x7c_severity = pas::ESeverity::One; + std::bitset<5> x80_availableStates; + union { + struct { + bool x81_24_autoResetImpulse : 1; // t + bool x81_25_enableFreeze : 1; // t + bool x81_26_enableShock : 1; + bool x81_27_enableBurn : 1; // t + bool x81_28_enableBurnDeath : 1; // t + bool x81_29_enableExplodeDeath : 1; // t + bool x81_30_enableLaggedBurnDeath : 1; // t + bool x81_31_ : 1; // t + bool x82_24_ : 1; // t + bool x82_25_inDeferredKnockBack : 1; + bool x82_26_locomotionDuringElectrocution : 1; }; - void ApplyImpulse(float dt, CPatterned& parent); - bool TickDeferredTimer(float dt); - EKnockBackCharacterState GetKnockBackCharacterState(CPatterned& parent); - void ValidateState(CPatterned& parent); - float CalculateExtraHurlVelocity(CStateManager& mgr, float magnitude, float kbResistance); - void DoKnockBackAnimation(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, float magnitude); - void ResetKnockBackImpulse(CPatterned& parent, const zeus::CVector3f& backVec, float magnitude); - void DoDeferredKnockBack(CStateManager& mgr, CPatterned& parent); - EKnockBackWeaponType GetKnockBackWeaponType(const CDamageInfo& info, EWeaponType wType, EKnockBackType type); - void SelectDamageState(CPatterned& parent, const CDamageInfo& info, EWeaponType wType, EKnockBackType type); + u32 dummy = 0; + }; + void ApplyImpulse(float dt, CPatterned& parent); + bool TickDeferredTimer(float dt); + EKnockBackCharacterState GetKnockBackCharacterState(CPatterned& parent); + void ValidateState(CPatterned& parent); + float CalculateExtraHurlVelocity(CStateManager& mgr, float magnitude, float kbResistance); + void DoKnockBackAnimation(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, float magnitude); + void ResetKnockBackImpulse(CPatterned& parent, const zeus::CVector3f& backVec, float magnitude); + void DoDeferredKnockBack(CStateManager& mgr, CPatterned& parent); + EKnockBackWeaponType GetKnockBackWeaponType(const CDamageInfo& info, EWeaponType wType, EKnockBackType type); + void SelectDamageState(CPatterned& parent, const CDamageInfo& info, EWeaponType wType, EKnockBackType type); + public: - explicit CKnockBackController(EKnockBackVariant variant); - void SetKnockBackVariant(EKnockBackVariant v) { x0_variant = v; } - void DeferKnockBack(EWeaponType tp) { x14_deferWeaponType = tp; x68_deferRemTime = 0.05f; } - void sub80233d40(int i, float f1, float f2); - void SetAutoResetImpulse(bool b); - void SetImpulseDurationIdx(u32 i) { x20_impulseDurationIdx = i; } - void SetAnimationStateRange(EKnockBackAnimationState a, EKnockBackAnimationState b) - { x18_minAnimState = a; x1c_maxAnimState = b; } - void Update(float dt, CStateManager& mgr, CPatterned& parent); - void KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, - const CDamageInfo& info, EKnockBackType type, float magnitude); - void SetEnableFreeze(bool b) { x81_25_enableFreeze = b; } - void SetEnableShock(bool b) { x81_26_enableShock = b; } - void SetEnableBurn(bool b) { x81_27_enableBurn = b; } - void SetEnableBurnDeath(bool b) { x81_28_enableBurnDeath = b; } - void SetEnableExplodeDeath(bool b) { x81_29_enableExplodeDeath = b; } - void SetEnableLaggedBurnDeath(bool b) { x81_30_enableLaggedBurnDeath = b; } - void SetX81_31(bool b) { x81_31_ = b; } - void SetX82_24(bool b) { x82_24_ = b; } - void SetLocomotionDuringElectrocution(bool b) { x82_26_locomotionDuringElectrocution = b; } - const KnockBackParms& GetActiveParms() const { return x4_activeParms; } - EKnockBackVariant GetVariant() const { return x0_variant; } - float GetFlinchRemTime() const { return x64_flinchRemTime; } + explicit CKnockBackController(EKnockBackVariant variant); + void SetKnockBackVariant(EKnockBackVariant v) { x0_variant = v; } + void DeferKnockBack(EWeaponType tp) { + x14_deferWeaponType = tp; + x68_deferRemTime = 0.05f; + } + void sub80233d40(int i, float f1, float f2); + void SetAutoResetImpulse(bool b); + void SetImpulseDurationIdx(u32 i) { x20_impulseDurationIdx = i; } + void SetAnimationStateRange(EKnockBackAnimationState a, EKnockBackAnimationState b) { + x18_minAnimState = a; + x1c_maxAnimState = b; + } + void Update(float dt, CStateManager& mgr, CPatterned& parent); + void KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, CPatterned& parent, const CDamageInfo& info, + EKnockBackType type, float magnitude); + void SetEnableFreeze(bool b) { x81_25_enableFreeze = b; } + void SetEnableShock(bool b) { x81_26_enableShock = b; } + void SetEnableBurn(bool b) { x81_27_enableBurn = b; } + void SetEnableBurnDeath(bool b) { x81_28_enableBurnDeath = b; } + void SetEnableExplodeDeath(bool b) { x81_29_enableExplodeDeath = b; } + void SetEnableLaggedBurnDeath(bool b) { x81_30_enableLaggedBurnDeath = b; } + void SetX81_31(bool b) { x81_31_ = b; } + void SetX82_24(bool b) { x82_24_ = b; } + void SetLocomotionDuringElectrocution(bool b) { x82_26_locomotionDuringElectrocution = b; } + const KnockBackParms& GetActiveParms() const { return x4_activeParms; } + EKnockBackVariant GetVariant() const { return x0_variant; } + float GetFlinchRemTime() const { return x64_flinchRemTime; } }; -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/World/CLightParameters.hpp b/Runtime/World/CLightParameters.hpp index bd7a811f7..de70085b1 100644 --- a/Runtime/World/CLightParameters.hpp +++ b/Runtime/World/CLightParameters.hpp @@ -4,96 +4,88 @@ #include "zeus/CColor.hpp" #include "Character/CActorLights.hpp" -namespace urde -{ +namespace urde { + +class CLightParameters { + friend class CActor; -class CLightParameters -{ - friend class CActor; public: - enum class EShadowTesselation - { - Zero - }; + enum class EShadowTesselation { Zero }; - enum class EWorldLightingOptions - { - Zero, - NormalWorld, - NoShadowCast, - DisableWorld - }; + enum class EWorldLightingOptions { Zero, NormalWorld, NoShadowCast, DisableWorld }; - enum class ELightRecalculationOptions - { - LargeFrameCount, - EightFrames, - FourFrames, - OneFrame - }; + enum class ELightRecalculationOptions { LargeFrameCount, EightFrames, FourFrames, OneFrame }; private: - bool x4_a = false; - float x8_b = 0.f; - EShadowTesselation xc_shadowTesselation = EShadowTesselation::Zero; - float x10_d = 0.f; - float x14_e = 0.f; - zeus::CColor x18_noLightsAmbient; - bool x1c_makeLights = false; - bool x1d_ambientChannelOverflow = false; - EWorldLightingOptions x20_worldLightingOptions = EWorldLightingOptions::Zero; - ELightRecalculationOptions x24_lightRecalcOpts = ELightRecalculationOptions::EightFrames; - s32 x28_layerIdx = 0; - zeus::CVector3f x2c_actorPosBias; - s32 x38_maxDynamicLights = 4; - s32 x3c_maxAreaLights = 4; + bool x4_a = false; + float x8_b = 0.f; + EShadowTesselation xc_shadowTesselation = EShadowTesselation::Zero; + float x10_d = 0.f; + float x14_e = 0.f; + zeus::CColor x18_noLightsAmbient; + bool x1c_makeLights = false; + bool x1d_ambientChannelOverflow = false; + EWorldLightingOptions x20_worldLightingOptions = EWorldLightingOptions::Zero; + ELightRecalculationOptions x24_lightRecalcOpts = ELightRecalculationOptions::EightFrames; + s32 x28_layerIdx = 0; + zeus::CVector3f x2c_actorPosBias; + s32 x38_maxDynamicLights = 4; + s32 x3c_maxAreaLights = 4; + public: - CLightParameters() = default; - CLightParameters(bool a, float b, EShadowTesselation shadowTess, float d, float e, const zeus::CColor& noLightsAmbient, - bool makeLights, EWorldLightingOptions lightingOpts, ELightRecalculationOptions lightRecalcOpts, - const zeus::CVector3f& actorPosBias, s32 maxDynamicLights, s32 maxAreaLights, bool ambChannelOverflow, s32 layerIdx) - : x4_a(a), x8_b(b), xc_shadowTesselation(shadowTess), x10_d(d), x14_e(e), x18_noLightsAmbient(noLightsAmbient), x1c_makeLights(makeLights), - x1d_ambientChannelOverflow(ambChannelOverflow), x20_worldLightingOptions(lightingOpts), x24_lightRecalcOpts(lightRecalcOpts), - x28_layerIdx(layerIdx), x2c_actorPosBias(actorPosBias), x38_maxDynamicLights(maxDynamicLights), x3c_maxAreaLights(maxAreaLights) - { - if (x38_maxDynamicLights > 4 || x38_maxDynamicLights == -1) - x38_maxDynamicLights = 4; - if (x3c_maxAreaLights > 4 || x3c_maxAreaLights == -1) - x3c_maxAreaLights = 4; - } - static CLightParameters None() {return CLightParameters();} + CLightParameters() = default; + CLightParameters(bool a, float b, EShadowTesselation shadowTess, float d, float e, + const zeus::CColor& noLightsAmbient, bool makeLights, EWorldLightingOptions lightingOpts, + ELightRecalculationOptions lightRecalcOpts, const zeus::CVector3f& actorPosBias, + s32 maxDynamicLights, s32 maxAreaLights, bool ambChannelOverflow, s32 layerIdx) + : x4_a(a) + , x8_b(b) + , xc_shadowTesselation(shadowTess) + , x10_d(d) + , x14_e(e) + , x18_noLightsAmbient(noLightsAmbient) + , x1c_makeLights(makeLights) + , x1d_ambientChannelOverflow(ambChannelOverflow) + , x20_worldLightingOptions(lightingOpts) + , x24_lightRecalcOpts(lightRecalcOpts) + , x28_layerIdx(layerIdx) + , x2c_actorPosBias(actorPosBias) + , x38_maxDynamicLights(maxDynamicLights) + , x3c_maxAreaLights(maxAreaLights) { + if (x38_maxDynamicLights > 4 || x38_maxDynamicLights == -1) + x38_maxDynamicLights = 4; + if (x3c_maxAreaLights > 4 || x3c_maxAreaLights == -1) + x3c_maxAreaLights = 4; + } + static CLightParameters None() { return CLightParameters(); } - static u32 GetFramesBetweenRecalculation(ELightRecalculationOptions opts) - { - if (opts == ELightRecalculationOptions::LargeFrameCount) - return 0x3FFFFFFF; - else if (opts == ELightRecalculationOptions::EightFrames) - return 8; - else if (opts == ELightRecalculationOptions::FourFrames) - return 4; - else if (opts == ELightRecalculationOptions::OneFrame) - return 1; - return 8; - } + static u32 GetFramesBetweenRecalculation(ELightRecalculationOptions opts) { + if (opts == ELightRecalculationOptions::LargeFrameCount) + return 0x3FFFFFFF; + else if (opts == ELightRecalculationOptions::EightFrames) + return 8; + else if (opts == ELightRecalculationOptions::FourFrames) + return 4; + else if (opts == ELightRecalculationOptions::OneFrame) + return 1; + return 8; + } - std::unique_ptr MakeActorLights() const - { - if (!x1c_makeLights) - return {}; + std::unique_ptr MakeActorLights() const { + if (!x1c_makeLights) + return {}; - u32 updateFrames = GetFramesBetweenRecalculation(x24_lightRecalcOpts); - CActorLights* lights = new CActorLights(updateFrames, x2c_actorPosBias, x38_maxDynamicLights, - x3c_maxAreaLights, x1d_ambientChannelOverflow, x28_layerIdx == 1, - x20_worldLightingOptions == EWorldLightingOptions::DisableWorld, - 0.1f); - if (x20_worldLightingOptions == EWorldLightingOptions::NoShadowCast) - lights->SetCastShadows(false); - if (x3c_maxAreaLights == 0) - lights->SetAmbientColor(x18_noLightsAmbient); - return std::unique_ptr(lights); - } - const zeus::CColor& GetNoLightsAmbient() const { return x18_noLightsAmbient; } + u32 updateFrames = GetFramesBetweenRecalculation(x24_lightRecalcOpts); + CActorLights* lights = new CActorLights(updateFrames, x2c_actorPosBias, x38_maxDynamicLights, x3c_maxAreaLights, + x1d_ambientChannelOverflow, x28_layerIdx == 1, + x20_worldLightingOptions == EWorldLightingOptions::DisableWorld, 0.1f); + if (x20_worldLightingOptions == EWorldLightingOptions::NoShadowCast) + lights->SetCastShadows(false); + if (x3c_maxAreaLights == 0) + lights->SetAmbientColor(x18_noLightsAmbient); + return std::unique_ptr(lights); + } + const zeus::CColor& GetNoLightsAmbient() const { return x18_noLightsAmbient; } }; -} - +} // namespace urde diff --git a/Runtime/World/CMorphBall.cpp b/Runtime/World/CMorphBall.cpp index b61bbe9fb..022c3d680 100644 --- a/Runtime/World/CMorphBall.cpp +++ b/Runtime/World/CMorphBall.cpp @@ -16,2628 +16,2120 @@ #include "MP1/World/CMetroidBeta.hpp" #include "Input/ControlMapper.hpp" -namespace urde -{ +namespace urde { static float kSpiderBallCollisionRadius; -const u8 CMorphBall::BallGlowColors[9][3] = -{ - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xd5, 0x19}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, - {0xff, 0xff, 0xff}, +const u8 CMorphBall::BallGlowColors[9][3] = { + {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xd5, 0x19}, + {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, }; -const u8 CMorphBall::BallTransFlashColors[9][3] = -{ - {0xc2, 0x7e, 0x10}, - {0x66, 0xc4, 0xff}, - {0x60, 0xff, 0x90}, - {0x33, 0x33, 0xff}, - {0xff, 0x20, 0x20}, - {0x0, 0x9d, 0xb6}, - {0xd3, 0xf1, 0x0}, - {0xa6, 0x86, 0xd8}, - {0xfb, 0x98, 0x21} -}; +const u8 CMorphBall::BallTransFlashColors[9][3] = {{0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x60, 0xff, 0x90}, + {0x33, 0x33, 0xff}, {0xff, 0x20, 0x20}, {0x0, 0x9d, 0xb6}, + {0xd3, 0xf1, 0x0}, {0xa6, 0x86, 0xd8}, {0xfb, 0x98, 0x21}}; -const u8 CMorphBall::BallAuxGlowColors[9][3] = -{ - {0xc2, 0x7e, 0x10}, - {0x66, 0xc4, 0xff}, - {0x6c, 0xff, 0x61}, - {0x33, 0x33, 0xff}, - {0xff, 0x20, 0x20}, - {0x0, 0x9d, 0xb6}, - {0xd3, 0xf1, 0x0}, - {0xa6, 0x86, 0xd8}, - {0xfb, 0x98, 0x21} -}; +const u8 CMorphBall::BallAuxGlowColors[9][3] = {{0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x6c, 0xff, 0x61}, + {0x33, 0x33, 0xff}, {0xff, 0x20, 0x20}, {0x0, 0x9d, 0xb6}, + {0xd3, 0xf1, 0x0}, {0xa6, 0x86, 0xd8}, {0xfb, 0x98, 0x21}}; CMorphBall::CMorphBall(CPlayer& player, float radius) -: x0_player(player), xc_radius(radius), - x38_collisionSphere({{0.f, 0.f, radius}, radius}, - {EMaterialTypes::Player, EMaterialTypes::Solid, EMaterialTypes::GroundCollider}), - x58_ballModel(GetMorphBallModel("SamusBallANCS", radius)), - x60_spiderBallGlassModel(GetMorphBallModel("SamusSpiderBallGlassCMDL", radius)), - x68_lowPolyBallModel(GetMorphBallModel("SamusBallLowPolyCMDL", radius)), - x70_frozenBallModel(GetMorphBallModel("SamusBallFrozenCMDL", radius)), - x1968_slowBlueTailSwoosh(g_SimplePool->GetObj("SlowBlueTailSwoosh")), - x1970_slowBlueTailSwoosh2(g_SimplePool->GetObj("SlowBlueTailSwoosh2")), - x1978_jaggyTrail(g_SimplePool->GetObj("JaggyTrail")), - x1980_wallSpark(g_SimplePool->GetObj("WallSpark")), - x1988_ballInnerGlow(g_SimplePool->GetObj("BallInnerGlow")), - x1990_spiderBallMagnetEffect(g_SimplePool->GetObj("SpiderBallMagnetEffect")), - x1998_boostBallGlow(g_SimplePool->GetObj("BoostBallGlow")), - x19a0_spiderElectric(g_SimplePool->GetObj("SpiderElectric")), - x19a8_morphBallTransitionFlash(g_SimplePool->GetObj("MorphBallTransitionFlash")), - x19b0_effect_morphBallIceBreak(g_SimplePool->GetObj("Effect_MorphBallIceBreak")) -{ - x19b8_slowBlueTailSwooshGen = std::make_unique(x1968_slowBlueTailSwoosh, 0); - x19bc_slowBlueTailSwooshGen2 = std::make_unique(x1968_slowBlueTailSwoosh, 0); - x19c0_slowBlueTailSwoosh2Gen = std::make_unique(x1970_slowBlueTailSwoosh2, 0); - x19c4_slowBlueTailSwoosh2Gen2 = std::make_unique(x1970_slowBlueTailSwoosh2, 0); - x19c8_jaggyTrailGen = std::make_unique(x1978_jaggyTrail, 0); - x19cc_wallSparkGen = std::make_unique(x1980_wallSpark); - x19d0_ballInnerGlowGen = std::make_unique(x1988_ballInnerGlow); - x19d4_spiderBallMagnetEffectGen = std::make_unique(x1990_spiderBallMagnetEffect); - x19d8_boostBallGlowGen = std::make_unique(x1998_boostBallGlow); - x1c14_worldShadow = std::make_unique(128, 128, false); - x1c18_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f); - x1c1c_rainSplashGen = std::make_unique(x58_ballModel->GetScale(), 40, 2, 0.15f, 0.5f); - x1de4_24_inBoost = false; - x1de4_25_boostEnabled = true; - x1df8_24_inHalfPipeMode = false; - x1df8_25_inHalfPipeModeInAir = false; - x1df8_26_touchedHalfPipeRecently = false; - x1df8_27_ballCloseToCollision = false; +: x0_player(player) +, xc_radius(radius) +, x38_collisionSphere({{0.f, 0.f, radius}, radius}, + {EMaterialTypes::Player, EMaterialTypes::Solid, EMaterialTypes::GroundCollider}) +, x58_ballModel(GetMorphBallModel("SamusBallANCS", radius)) +, x60_spiderBallGlassModel(GetMorphBallModel("SamusSpiderBallGlassCMDL", radius)) +, x68_lowPolyBallModel(GetMorphBallModel("SamusBallLowPolyCMDL", radius)) +, x70_frozenBallModel(GetMorphBallModel("SamusBallFrozenCMDL", radius)) +, x1968_slowBlueTailSwoosh(g_SimplePool->GetObj("SlowBlueTailSwoosh")) +, x1970_slowBlueTailSwoosh2(g_SimplePool->GetObj("SlowBlueTailSwoosh2")) +, x1978_jaggyTrail(g_SimplePool->GetObj("JaggyTrail")) +, x1980_wallSpark(g_SimplePool->GetObj("WallSpark")) +, x1988_ballInnerGlow(g_SimplePool->GetObj("BallInnerGlow")) +, x1990_spiderBallMagnetEffect(g_SimplePool->GetObj("SpiderBallMagnetEffect")) +, x1998_boostBallGlow(g_SimplePool->GetObj("BoostBallGlow")) +, x19a0_spiderElectric(g_SimplePool->GetObj("SpiderElectric")) +, x19a8_morphBallTransitionFlash(g_SimplePool->GetObj("MorphBallTransitionFlash")) +, x19b0_effect_morphBallIceBreak(g_SimplePool->GetObj("Effect_MorphBallIceBreak")) { + x19b8_slowBlueTailSwooshGen = std::make_unique(x1968_slowBlueTailSwoosh, 0); + x19bc_slowBlueTailSwooshGen2 = std::make_unique(x1968_slowBlueTailSwoosh, 0); + x19c0_slowBlueTailSwoosh2Gen = std::make_unique(x1970_slowBlueTailSwoosh2, 0); + x19c4_slowBlueTailSwoosh2Gen2 = std::make_unique(x1970_slowBlueTailSwoosh2, 0); + x19c8_jaggyTrailGen = std::make_unique(x1978_jaggyTrail, 0); + x19cc_wallSparkGen = std::make_unique(x1980_wallSpark); + x19d0_ballInnerGlowGen = std::make_unique(x1988_ballInnerGlow); + x19d4_spiderBallMagnetEffectGen = std::make_unique(x1990_spiderBallMagnetEffect); + x19d8_boostBallGlowGen = std::make_unique(x1998_boostBallGlow); + x1c14_worldShadow = std::make_unique(128, 128, false); + x1c18_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f); + x1c1c_rainSplashGen = std::make_unique(x58_ballModel->GetScale(), 40, 2, 0.15f, 0.5f); + x1de4_24_inBoost = false; + x1de4_25_boostEnabled = true; + x1df8_24_inHalfPipeMode = false; + x1df8_25_inHalfPipeModeInAir = false; + x1df8_26_touchedHalfPipeRecently = false; + x1df8_27_ballCloseToCollision = false; - x19d4_spiderBallMagnetEffectGen->SetParticleEmission(false); - x19d4_spiderBallMagnetEffectGen->Update(1.0 / 60.0); + x19d4_spiderBallMagnetEffectGen->SetParticleEmission(false); + x19d4_spiderBallMagnetEffectGen->Update(1.0 / 60.0); - kSpiderBallCollisionRadius = GetBallRadius() + 0.2f; + kSpiderBallCollisionRadius = GetBallRadius() + 0.2f; - for (int i=0 ; i<32 ; ++i) - x19e4_spiderElectricGens.emplace_back(std::make_unique(x19a0_spiderElectric, 0), false); + for (int i = 0; i < 32; ++i) + x19e4_spiderElectricGens.emplace_back(std::make_unique(x19a0_spiderElectric, 0), false); - LoadAnimationTokens("SamusBallANCS"); - InitializeWakeEffects(); + LoadAnimationTokens("SamusBallANCS"); + InitializeWakeEffects(); } -void CMorphBall::LoadAnimationTokens(std::string_view ancsName) -{ - TToken dgrp = g_SimplePool->GetObj((std::string(ancsName) + "_DGRP").c_str()); - x1958_animationTokens.clear(); - x1958_animationTokens.reserve(dgrp->GetObjectTagVector().size()); - for (const SObjectTag& tag : dgrp->GetObjectTagVector()) - { - if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('CSKR') || tag.type == FOURCC('TXTR')) - continue; - x1958_animationTokens.push_back(g_SimplePool->GetObj(tag)); - x1958_animationTokens.back().Lock(); - } +void CMorphBall::LoadAnimationTokens(std::string_view ancsName) { + TToken dgrp = g_SimplePool->GetObj((std::string(ancsName) + "_DGRP").c_str()); + x1958_animationTokens.clear(); + x1958_animationTokens.reserve(dgrp->GetObjectTagVector().size()); + for (const SObjectTag& tag : dgrp->GetObjectTagVector()) { + if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('CSKR') || tag.type == FOURCC('TXTR')) + continue; + x1958_animationTokens.push_back(g_SimplePool->GetObj(tag)); + x1958_animationTokens.back().Lock(); + } } /* Maps material index to effect in generator array */ -static const s32 skWakeEffectMap[32] = -{ - -1, - -1, - -1, - -1, - -1, - -1, - -1, - 0, // Phazon - 2, // Dirt - 3, // Lava - -1, - 4, // Snow - 5, // MudSlow - -1, - -1, - -1, - -1, - 6, // Sand - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1, - -1 -}; +static const s32 skWakeEffectMap[32] = {-1, -1, -1, -1, -1, -1, -1, + 0, // Phazon + 2, // Dirt + 3, // Lava + -1, + 4, // Snow + 5, // MudSlow + -1, -1, -1, -1, + 6, // Sand + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; -void CMorphBall::InitializeWakeEffects() -{ - TToken nullParticle = - CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::make_unique())); - for (int i=0 ; i<8 ; ++i) - x1b84_wakeEffects.push_back(nullParticle); +void CMorphBall::InitializeWakeEffects() { + TToken nullParticle = + CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::make_unique())); + for (int i = 0; i < 8; ++i) + x1b84_wakeEffects.push_back(nullParticle); - x1b84_wakeEffects[2] = g_SimplePool->GetObj("DirtWake"); - x1b84_wakeEffects[0] = g_SimplePool->GetObj("PhazonWake"); - x1b84_wakeEffects[1] = g_SimplePool->GetObj("PhazonWakeOrange"); - x1b84_wakeEffects[3] = g_SimplePool->GetObj("LavaWake"); - x1b84_wakeEffects[4] = g_SimplePool->GetObj("SnowWake"); - x1b84_wakeEffects[5] = g_SimplePool->GetObj("MudWake"); - x1b84_wakeEffects[6] = g_SimplePool->GetObj("SandWake"); - x1b84_wakeEffects[7] = g_SimplePool->GetObj("RainWake"); + x1b84_wakeEffects[2] = g_SimplePool->GetObj("DirtWake"); + x1b84_wakeEffects[0] = g_SimplePool->GetObj("PhazonWake"); + x1b84_wakeEffects[1] = g_SimplePool->GetObj("PhazonWakeOrange"); + x1b84_wakeEffects[3] = g_SimplePool->GetObj("LavaWake"); + x1b84_wakeEffects[4] = g_SimplePool->GetObj("SnowWake"); + x1b84_wakeEffects[5] = g_SimplePool->GetObj("MudWake"); + x1b84_wakeEffects[6] = g_SimplePool->GetObj("SandWake"); + x1b84_wakeEffects[7] = g_SimplePool->GetObj("RainWake"); - x1bc8_wakeEffectGens.resize(8); - x1bc8_wakeEffectGens[2] = std::make_unique(x1b84_wakeEffects[2]); - x1bc8_wakeEffectGens[0] = std::make_unique(x1b84_wakeEffects[0]); - x1bc8_wakeEffectGens[1] = std::make_unique(x1b84_wakeEffects[1]); - x1bc8_wakeEffectGens[3] = std::make_unique(x1b84_wakeEffects[3]); - x1bc8_wakeEffectGens[4] = std::make_unique(x1b84_wakeEffects[4]); - x1bc8_wakeEffectGens[5] = std::make_unique(x1b84_wakeEffects[5]); - x1bc8_wakeEffectGens[6] = std::make_unique(x1b84_wakeEffects[6]); - x1bc8_wakeEffectGens[7] = std::make_unique(x1b84_wakeEffects[7]); + x1bc8_wakeEffectGens.resize(8); + x1bc8_wakeEffectGens[2] = std::make_unique(x1b84_wakeEffects[2]); + x1bc8_wakeEffectGens[0] = std::make_unique(x1b84_wakeEffects[0]); + x1bc8_wakeEffectGens[1] = std::make_unique(x1b84_wakeEffects[1]); + x1bc8_wakeEffectGens[3] = std::make_unique(x1b84_wakeEffects[3]); + x1bc8_wakeEffectGens[4] = std::make_unique(x1b84_wakeEffects[4]); + x1bc8_wakeEffectGens[5] = std::make_unique(x1b84_wakeEffects[5]); + x1bc8_wakeEffectGens[6] = std::make_unique(x1b84_wakeEffects[6]); + x1bc8_wakeEffectGens[7] = std::make_unique(x1b84_wakeEffects[7]); } -std::unique_ptr CMorphBall::GetMorphBallModel(const char* name, float radius) -{ - const SObjectTag* tag = g_ResFactory->GetResourceIdByName(name); - if (tag->type == FOURCC('CMDL')) - return std::make_unique(CStaticRes(tag->id, zeus::CVector3f(radius * 2.f))); +std::unique_ptr CMorphBall::GetMorphBallModel(const char* name, float radius) { + const SObjectTag* tag = g_ResFactory->GetResourceIdByName(name); + if (tag->type == FOURCC('CMDL')) + return std::make_unique(CStaticRes(tag->id, zeus::CVector3f(radius * 2.f))); + else + return std::make_unique(CAnimRes(tag->id, 0, zeus::CVector3f(radius * 2.f), 0, false)); +} + +void CMorphBall::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Registered: + if (x19d0_ballInnerGlowGen && x19d0_ballInnerGlowGen->SystemHasLight()) { + x1c10_ballInnerGlowLight = mgr.AllocateUniqueId(); + CGameLight* l = new CGameLight(x1c10_ballInnerGlowLight, kInvalidAreaId, false, "BallLight", GetBallToWorld(), + x0_player.GetUniqueId(), x19d0_ballInnerGlowGen->GetLight(), + u32(x1988_ballInnerGlow.GetObjectTag()->id.Value()), 0, 0.f); + mgr.AddObject(l); + } + break; + case EScriptObjectMessage::Deleted: + DeleteLight(mgr); + break; + default: + break; + } +} + +void CMorphBall::DrawBallShadow(const CStateManager& mgr) { + if (!x1e50_shadow) + return; + + float alpha = 1.f; + switch (x0_player.x2f8_morphBallState) { + case CPlayer::EPlayerMorphBallState::Unmorphed: + return; + case CPlayer::EPlayerMorphBallState::Unmorphing: + alpha = 0.f; + if (x0_player.x578_morphDuration != 0.f) + alpha = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); + alpha = 1.f - alpha; + break; + case CPlayer::EPlayerMorphBallState::Morphing: + alpha = 0.f; + if (x0_player.x578_morphDuration != 0.f) + alpha = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); + break; + default: + break; + } + x1e50_shadow->Render(mgr, alpha); +} + +void CMorphBall::DeleteBallShadow() { x1e50_shadow.reset(); } + +void CMorphBall::CreateBallShadow() { x1e50_shadow = std::make_unique(); } + +void CMorphBall::RenderToShadowTex(CStateManager& mgr) { + if (x1e50_shadow) { + zeus::CVector3f center = + x0_player.GetPrimitiveOffset() + x0_player.GetTranslation() + zeus::CVector3f(0.f, 0.f, xc_radius); + zeus::CAABox aabb(center - zeus::CVector3f(1.25f * xc_radius, 1.25f * xc_radius, 10.f), + center + zeus::CVector3f(1.25f * xc_radius, 1.25f * xc_radius, xc_radius)); + x1e50_shadow->RenderIdBuffer(aabb, mgr, x0_player); + } +} + +static const u16 skBallRollSfx[] = {0xFFFF, + SFXsam_ballroll_stone, + SFXsam_ballroll_metal, + SFXsam_ballroll_grass, + SFXice_ballroll_ice, + 0xFFFF, + SFXsam_ballroll_grate, + SFXsam_ballroll_phazon, + SFXsam_ballroll_dirt, + SFXlav_ballroll_lava, + SFXsam_ballroll_lavastone, + SFXice_ballroll_snow, + SFXsam_ballroll_mud, + 0xFFFF, + SFXsam_ballroll_org, + SFXsam_ballroll_metal, + SFXsam_ballroll_metal, + SFXsam_ballroll_dirt, + 0xFFFF, + 0xFFFF, + 0xFFFF, + 0xFFFF, + SFXsam_ballroll_wood, + SFXsam_ballroll_org}; + +static const u16 skBallLandSfx[] = {0xFFFF, + SFXsam_ballland_stone, + SFXsam_ballland_metal, + SFXsam_ballland_grass, + SFXsam_ballland_ice, + 0xFFFF, + SFXsam_ballland_grate, + SFXsam_ballland_phazon, + SFXsam_landdirt_00, + SFXsam_ballland_lava, + SFXsam_ballland_lava, + SFXsam_ballland_snow, + SFXsam_ballland_mud, + 0xFFFF, + SFXsam_ballland_org, + SFXsam_ballland_metal, + SFXsam_ballland_metal, + SFXsam_landdirt_00, + 0xFFFF, + 0xFFFF, + 0xFFFF, + 0xFFFF, + SFXsam_ballland_wood, + SFXsam_ballland_org}; + +void CMorphBall::SelectMorphBallSounds(const CMaterialList& mat) { + u16 rollSfx; + if (x0_player.x9c5_30_selectFluidBallSound) { + if (x0_player.x82c_inLava) + rollSfx = 2186; else - return std::make_unique(CAnimRes(tag->id, 0, zeus::CVector3f(radius * 2.f), 0, false)); + rollSfx = 1481; + } else { + rollSfx = CPlayer::SfxIdFromMaterial(mat, skBallRollSfx, 24, 0xffff); + } + x0_player.x9c5_30_selectFluidBallSound = false; + + if (rollSfx != 0xffff) { + if (x1e34_rollSfx != rollSfx && x1e2c_rollSfxHandle) { + CSfxManager::SfxStop(x1e2c_rollSfxHandle); + x1e2c_rollSfxHandle.reset(); + } + x1e34_rollSfx = rollSfx; + } + + x1e36_landSfx = CPlayer::SfxIdFromMaterial(mat, skBallLandSfx, 24, 0xffff); } -void CMorphBall::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Registered: - if (x19d0_ballInnerGlowGen && x19d0_ballInnerGlowGen->SystemHasLight()) - { - x1c10_ballInnerGlowLight = mgr.AllocateUniqueId(); - CGameLight* l = new CGameLight(x1c10_ballInnerGlowLight, kInvalidAreaId, false, "BallLight", - GetBallToWorld(), x0_player.GetUniqueId(), - x19d0_ballInnerGlowGen->GetLight(), - u32(x1988_ballInnerGlow.GetObjectTag()->id.Value()), 0, 0.f); - mgr.AddObject(l); - } - break; - case EScriptObjectMessage::Deleted: - DeleteLight(mgr); - break; - default: - break; - } -} - -void CMorphBall::DrawBallShadow(const CStateManager& mgr) -{ - if (!x1e50_shadow) - return; - - float alpha = 1.f; - switch (x0_player.x2f8_morphBallState) - { - case CPlayer::EPlayerMorphBallState::Unmorphed: - return; - case CPlayer::EPlayerMorphBallState::Unmorphing: - alpha = 0.f; - if (x0_player.x578_morphDuration != 0.f) - alpha = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); - alpha = 1.f - alpha; - break; - case CPlayer::EPlayerMorphBallState::Morphing: - alpha = 0.f; - if (x0_player.x578_morphDuration != 0.f) - alpha = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); - break; - default: break; - } - x1e50_shadow->Render(mgr, alpha); -} - -void CMorphBall::DeleteBallShadow() -{ - x1e50_shadow.reset(); -} - -void CMorphBall::CreateBallShadow() -{ - x1e50_shadow = std::make_unique(); -} - -void CMorphBall::RenderToShadowTex(CStateManager& mgr) -{ - if (x1e50_shadow) - { - zeus::CVector3f center = - x0_player.GetPrimitiveOffset() + x0_player.GetTranslation() + zeus::CVector3f(0.f, 0.f, xc_radius); - zeus::CAABox aabb(center - zeus::CVector3f(1.25f * xc_radius, 1.25f * xc_radius, 10.f), - center + zeus::CVector3f(1.25f * xc_radius, 1.25f * xc_radius, xc_radius)); - x1e50_shadow->RenderIdBuffer(aabb, mgr, x0_player); - } -} - -static const u16 skBallRollSfx[] = -{ - 0xFFFF, - SFXsam_ballroll_stone, - SFXsam_ballroll_metal, - SFXsam_ballroll_grass, - SFXice_ballroll_ice, - 0xFFFF, - SFXsam_ballroll_grate, - SFXsam_ballroll_phazon, - SFXsam_ballroll_dirt, - SFXlav_ballroll_lava, - SFXsam_ballroll_lavastone, - SFXice_ballroll_snow, - SFXsam_ballroll_mud, - 0xFFFF, - SFXsam_ballroll_org, - SFXsam_ballroll_metal, - SFXsam_ballroll_metal, - SFXsam_ballroll_dirt, - 0xFFFF, - 0xFFFF, - 0xFFFF, - 0xFFFF, - SFXsam_ballroll_wood, - SFXsam_ballroll_org -}; - -static const u16 skBallLandSfx[] = -{ - 0xFFFF, - SFXsam_ballland_stone, - SFXsam_ballland_metal, - SFXsam_ballland_grass, - SFXsam_ballland_ice, - 0xFFFF, - SFXsam_ballland_grate, - SFXsam_ballland_phazon, - SFXsam_landdirt_00, - SFXsam_ballland_lava, - SFXsam_ballland_lava, - SFXsam_ballland_snow, - SFXsam_ballland_mud, - 0xFFFF, - SFXsam_ballland_org, - SFXsam_ballland_metal, - SFXsam_ballland_metal, - SFXsam_landdirt_00, - 0xFFFF, - 0xFFFF, - 0xFFFF, - 0xFFFF, - SFXsam_ballland_wood, - SFXsam_ballland_org -}; - -void CMorphBall::SelectMorphBallSounds(const CMaterialList& mat) -{ - u16 rollSfx; - if (x0_player.x9c5_30_selectFluidBallSound) - { - if (x0_player.x82c_inLava) - rollSfx = 2186; - else - rollSfx = 1481; - } - else - { - rollSfx = CPlayer::SfxIdFromMaterial(mat, skBallRollSfx, 24, 0xffff); - } - x0_player.x9c5_30_selectFluidBallSound = false; - - if (rollSfx != 0xffff) - { - if (x1e34_rollSfx != rollSfx && x1e2c_rollSfxHandle) - { - CSfxManager::SfxStop(x1e2c_rollSfxHandle); - x1e2c_rollSfxHandle.reset(); - } - x1e34_rollSfx = rollSfx; - } - - x1e36_landSfx = CPlayer::SfxIdFromMaterial(mat, skBallLandSfx, 24, 0xffff); -} - -void CMorphBall::UpdateMorphBallSounds(float dt) -{ - zeus::CVector3f velocity = x0_player.GetVelocity(); - if (x187c_spiderBallState != ESpiderBallState::Active) - velocity.z() = 0.f; - - switch (x0_player.GetPlayerMovementState()) - { - case CPlayer::EPlayerMovementState::OnGround: - case CPlayer::EPlayerMovementState::FallingMorphed: - { - float vel = velocity.magnitude(); - if (x187c_spiderBallState == ESpiderBallState::Active) - vel += g_tweakBall->GetBallGravity() * dt * 4.f; - if (vel > 0.8f) - { - if (!x1e2c_rollSfxHandle) - { - if (x1e34_rollSfx != 0xffff) - { - x1e2c_rollSfxHandle = - CSfxManager::AddEmitter(x1e34_rollSfx, x0_player.GetTranslation(), zeus::CVector3f::skZero, - true, true, 0x7f, kInvalidAreaId); - } - x0_player.ApplySubmergedPitchBend(x1e2c_rollSfxHandle); - } - CSfxManager::PitchBend(x1e2c_rollSfxHandle, zeus::clamp(-1.f, vel * 0.122f - 0.831f, 1.f)); - float maxVol = zeus::clamp(0.f, 0.025f * vel + 0.5f, 1.f); - CSfxManager::UpdateEmitter(x1e2c_rollSfxHandle, x0_player.GetTranslation(), - zeus::CVector3f::skZero, maxVol); - break; - } - } - default: - if (x1e2c_rollSfxHandle) - { - CSfxManager::SfxStop(x1e2c_rollSfxHandle); - x1e2c_rollSfxHandle.reset(); - } - break; - } +void CMorphBall::UpdateMorphBallSounds(float dt) { + zeus::CVector3f velocity = x0_player.GetVelocity(); + if (x187c_spiderBallState != ESpiderBallState::Active) + velocity.z() = 0.f; + switch (x0_player.GetPlayerMovementState()) { + case CPlayer::EPlayerMovementState::OnGround: + case CPlayer::EPlayerMovementState::FallingMorphed: { + float vel = velocity.magnitude(); if (x187c_spiderBallState == ESpiderBallState::Active) - { - if (!x1e30_spiderSfxHandle) - { - x1e30_spiderSfxHandle = - CSfxManager::AddEmitter(SFXsam_spider_lp, x0_player.GetTranslation(), zeus::CVector3f::skZero, - true, true, 0xc8, kInvalidAreaId); - x0_player.ApplySubmergedPitchBend(x1e30_spiderSfxHandle); + vel += g_tweakBall->GetBallGravity() * dt * 4.f; + if (vel > 0.8f) { + if (!x1e2c_rollSfxHandle) { + if (x1e34_rollSfx != 0xffff) { + x1e2c_rollSfxHandle = CSfxManager::AddEmitter(x1e34_rollSfx, x0_player.GetTranslation(), + zeus::CVector3f::skZero, true, true, 0x7f, kInvalidAreaId); } - CSfxManager::UpdateEmitter(x1e30_spiderSfxHandle, x0_player.GetTranslation(), - zeus::CVector3f::skZero, 1.f); + x0_player.ApplySubmergedPitchBend(x1e2c_rollSfxHandle); + } + CSfxManager::PitchBend(x1e2c_rollSfxHandle, zeus::clamp(-1.f, vel * 0.122f - 0.831f, 1.f)); + float maxVol = zeus::clamp(0.f, 0.025f * vel + 0.5f, 1.f); + CSfxManager::UpdateEmitter(x1e2c_rollSfxHandle, x0_player.GetTranslation(), zeus::CVector3f::skZero, maxVol); + break; } - else if (x1e30_spiderSfxHandle) - { - CSfxManager::SfxStop(x1e30_spiderSfxHandle); - x1e30_spiderSfxHandle.reset(); + } + default: + if (x1e2c_rollSfxHandle) { + CSfxManager::SfxStop(x1e2c_rollSfxHandle); + x1e2c_rollSfxHandle.reset(); } -} + break; + } -float CMorphBall::GetBallRadius() const -{ - return g_tweakPlayer->GetPlayerBallHalfExtent(); -} - -float CMorphBall::GetBallTouchRadius() const -{ - return g_tweakBall->GetBallTouchRadius(); -} - -float CMorphBall::ForwardInput(const CFinalInput& input) const -{ - if (!IsMovementAllowed()) - return 0.f; - return ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) - - ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); -} - -float CMorphBall::BallTurnInput(const CFinalInput& input) const -{ - if (!IsMovementAllowed()) - return 0.f; - return ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input) - - ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input); -} - -void CMorphBall::ComputeBallMovement(const CFinalInput& input, CStateManager& mgr, float dt) -{ - ComputeBoostBallMovement(input, mgr, dt); - ComputeMarioMovement(input, mgr, dt); -} - -bool CMorphBall::IsMovementAllowed() const -{ - if (!g_tweakPlayer->GetMoveDuringFreeLook() && (x0_player.x3dc_inFreeLook || x0_player.x3dd_lookButtonHeld)) - return false; - if (x0_player.IsMorphBallTransitioning()) - return false; - return x1e00_disableControlCooldown <= 0.f; -} - -void CMorphBall::UpdateSpiderBall(const CFinalInput& input, CStateManager& mgr, float dt) -{ - SetSpiderBallSwingingState(CheckForSwitchToSpiderBallSwinging(mgr)); - if (x18be_spiderBallSwinging) - ApplySpiderBallSwingingForces(input, mgr, dt); - else - ApplySpiderBallRollForces(input, mgr, dt); -} - -void CMorphBall::ApplySpiderBallSwingingForces(const CFinalInput& input, CStateManager& mgr, float dt) -{ - x18b4_linVelDamp = 0.04f; - x18b8_angVelDamp = 0.99f; - x1880_playerToSpiderNormal = x1890_spiderTrackPoint - x0_player.GetTranslation(); - float playerToSpiderDist = x1880_playerToSpiderNormal.magnitude(); - x1880_playerToSpiderNormal = x1880_playerToSpiderNormal * (-1.f / playerToSpiderDist); - float movement = GetSpiderBallControllerMovement(input); - UpdateSpiderBallSwingControllerMovementTimer(movement, dt); - float swingMovement = movement * GetSpiderBallSwingControllerMovementScalar(); - float f29 = playerToSpiderDist * 110000.f / 3.7f; - x0_player.ApplyForceWR( - x1880_playerToSpiderNormal.cross(x18a8_spiderBetweenPoints).cross(x1880_playerToSpiderNormal).normalized() * - f29 * swingMovement * 0.06f, zeus::CAxisAngle::sIdentity); - x0_player.SetMomentumWR({0.f, 0.f, x0_player.GetMass() * g_tweakBall->GetBallGravity()}); - x18fc_refPullVel = (1.f - x188c_spiderPullMovement) * 3.7f + 1.4f; - x1900_playerToSpiderTrackDist = playerToSpiderDist; - zeus::CVector3f playerVel = x0_player.GetVelocity(); - float playerSpeed = playerVel.magnitude(); - playerVel -= x1880_playerToSpiderNormal * playerSpeed * x1880_playerToSpiderNormal.dot(playerVel.normalized()); - float maxPullVel = 0.04f; - if (x188c_spiderPullMovement == 1.f && std::fabs(x1880_playerToSpiderNormal.z()) > 0.8f) - maxPullVel = 0.3f; - playerVel += x1880_playerToSpiderNormal * - zeus::clamp(-maxPullVel, x18fc_refPullVel - playerToSpiderDist, maxPullVel) / dt; - x0_player.SetVelocityWR(playerVel); -} - -zeus::CVector3f CMorphBall::TransformSpiderBallForcesXY(const zeus::CVector2f& forces, CStateManager& mgr) -{ - return mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis * - zeus::CVector3f(forces.x(), forces.y(), 0.f); -} - -zeus::CVector3f CMorphBall::TransformSpiderBallForcesXZ(const zeus::CVector2f& forces, CStateManager& mgr) -{ - return mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis * - zeus::CVector3f(forces.x(), 0.f, forces.y()); -} - -void CMorphBall::ApplySpiderBallRollForces(const CFinalInput& input, CStateManager& mgr, float dt) -{ - zeus::CVector2f surfaceForces = CalculateSpiderBallAttractionSurfaceForces(input); - zeus::CVector3f viewSurfaceForces = TransformSpiderBallForcesXZ(surfaceForces, mgr); - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform(); - zeus::CVector3f spiderDirNorm = x189c_spiderInterpBetweenPoints.normalized(); - float upDot = std::fabs(spiderDirNorm.dot(camXf.basis[2])); - float foreDot = std::fabs(spiderDirNorm.dot(camXf.basis[1])); - if (x0_player.x9c4_29_spiderBallControlXY && upDot < 0.25f && foreDot > 0.25f) - viewSurfaceForces = TransformSpiderBallForcesXY(surfaceForces, mgr); - float forceMag = surfaceForces.magnitude(); - zeus::CVector2f normSurfaceForces; - float trackForceMag = x18c0_isSpiderSurface ? forceMag : viewSurfaceForces.dot(spiderDirNorm); - bool forceApplied = true; - bool continueTrackForce = false; - if (std::fabs(forceMag) > 0.05f) - { - normSurfaceForces = surfaceForces.normalized(); - if (!x18c0_isSpiderSurface && normSurfaceForces.dot(x190c_normSpiderSurfaceForces) > 0.9f) - { - trackForceMag = x1914_spiderTrackForceMag >= 0.f ? forceMag : -forceMag; - continueTrackForce = true; - } - else - { - if (std::fabs(trackForceMag) > 0.05f) - trackForceMag = trackForceMag >= 0.f ? forceMag : -forceMag; - else - forceApplied = false; - } + if (x187c_spiderBallState == ESpiderBallState::Active) { + if (!x1e30_spiderSfxHandle) { + x1e30_spiderSfxHandle = CSfxManager::AddEmitter(SFXsam_spider_lp, x0_player.GetTranslation(), + zeus::CVector3f::skZero, true, true, 0xc8, kInvalidAreaId); + x0_player.ApplySubmergedPitchBend(x1e30_spiderSfxHandle); } - else - { + CSfxManager::UpdateEmitter(x1e30_spiderSfxHandle, x0_player.GetTranslation(), zeus::CVector3f::skZero, 1.f); + } else if (x1e30_spiderSfxHandle) { + CSfxManager::SfxStop(x1e30_spiderSfxHandle); + x1e30_spiderSfxHandle.reset(); + } +} + +float CMorphBall::GetBallRadius() const { return g_tweakPlayer->GetPlayerBallHalfExtent(); } + +float CMorphBall::GetBallTouchRadius() const { return g_tweakBall->GetBallTouchRadius(); } + +float CMorphBall::ForwardInput(const CFinalInput& input) const { + if (!IsMovementAllowed()) + return 0.f; + return ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) - + ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); +} + +float CMorphBall::BallTurnInput(const CFinalInput& input) const { + if (!IsMovementAllowed()) + return 0.f; + return ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input) - + ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input); +} + +void CMorphBall::ComputeBallMovement(const CFinalInput& input, CStateManager& mgr, float dt) { + ComputeBoostBallMovement(input, mgr, dt); + ComputeMarioMovement(input, mgr, dt); +} + +bool CMorphBall::IsMovementAllowed() const { + if (!g_tweakPlayer->GetMoveDuringFreeLook() && (x0_player.x3dc_inFreeLook || x0_player.x3dd_lookButtonHeld)) + return false; + if (x0_player.IsMorphBallTransitioning()) + return false; + return x1e00_disableControlCooldown <= 0.f; +} + +void CMorphBall::UpdateSpiderBall(const CFinalInput& input, CStateManager& mgr, float dt) { + SetSpiderBallSwingingState(CheckForSwitchToSpiderBallSwinging(mgr)); + if (x18be_spiderBallSwinging) + ApplySpiderBallSwingingForces(input, mgr, dt); + else + ApplySpiderBallRollForces(input, mgr, dt); +} + +void CMorphBall::ApplySpiderBallSwingingForces(const CFinalInput& input, CStateManager& mgr, float dt) { + x18b4_linVelDamp = 0.04f; + x18b8_angVelDamp = 0.99f; + x1880_playerToSpiderNormal = x1890_spiderTrackPoint - x0_player.GetTranslation(); + float playerToSpiderDist = x1880_playerToSpiderNormal.magnitude(); + x1880_playerToSpiderNormal = x1880_playerToSpiderNormal * (-1.f / playerToSpiderDist); + float movement = GetSpiderBallControllerMovement(input); + UpdateSpiderBallSwingControllerMovementTimer(movement, dt); + float swingMovement = movement * GetSpiderBallSwingControllerMovementScalar(); + float f29 = playerToSpiderDist * 110000.f / 3.7f; + x0_player.ApplyForceWR( + x1880_playerToSpiderNormal.cross(x18a8_spiderBetweenPoints).cross(x1880_playerToSpiderNormal).normalized() * f29 * + swingMovement * 0.06f, + zeus::CAxisAngle::sIdentity); + x0_player.SetMomentumWR({0.f, 0.f, x0_player.GetMass() * g_tweakBall->GetBallGravity()}); + x18fc_refPullVel = (1.f - x188c_spiderPullMovement) * 3.7f + 1.4f; + x1900_playerToSpiderTrackDist = playerToSpiderDist; + zeus::CVector3f playerVel = x0_player.GetVelocity(); + float playerSpeed = playerVel.magnitude(); + playerVel -= x1880_playerToSpiderNormal * playerSpeed * x1880_playerToSpiderNormal.dot(playerVel.normalized()); + float maxPullVel = 0.04f; + if (x188c_spiderPullMovement == 1.f && std::fabs(x1880_playerToSpiderNormal.z()) > 0.8f) + maxPullVel = 0.3f; + playerVel += + x1880_playerToSpiderNormal * zeus::clamp(-maxPullVel, x18fc_refPullVel - playerToSpiderDist, maxPullVel) / dt; + x0_player.SetVelocityWR(playerVel); +} + +zeus::CVector3f CMorphBall::TransformSpiderBallForcesXY(const zeus::CVector2f& forces, CStateManager& mgr) { + return mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis * + zeus::CVector3f(forces.x(), forces.y(), 0.f); +} + +zeus::CVector3f CMorphBall::TransformSpiderBallForcesXZ(const zeus::CVector2f& forces, CStateManager& mgr) { + return mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis * + zeus::CVector3f(forces.x(), 0.f, forces.y()); +} + +void CMorphBall::ApplySpiderBallRollForces(const CFinalInput& input, CStateManager& mgr, float dt) { + zeus::CVector2f surfaceForces = CalculateSpiderBallAttractionSurfaceForces(input); + zeus::CVector3f viewSurfaceForces = TransformSpiderBallForcesXZ(surfaceForces, mgr); + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform(); + zeus::CVector3f spiderDirNorm = x189c_spiderInterpBetweenPoints.normalized(); + float upDot = std::fabs(spiderDirNorm.dot(camXf.basis[2])); + float foreDot = std::fabs(spiderDirNorm.dot(camXf.basis[1])); + if (x0_player.x9c4_29_spiderBallControlXY && upDot < 0.25f && foreDot > 0.25f) + viewSurfaceForces = TransformSpiderBallForcesXY(surfaceForces, mgr); + float forceMag = surfaceForces.magnitude(); + zeus::CVector2f normSurfaceForces; + float trackForceMag = x18c0_isSpiderSurface ? forceMag : viewSurfaceForces.dot(spiderDirNorm); + bool forceApplied = true; + bool continueTrackForce = false; + if (std::fabs(forceMag) > 0.05f) { + normSurfaceForces = surfaceForces.normalized(); + if (!x18c0_isSpiderSurface && normSurfaceForces.dot(x190c_normSpiderSurfaceForces) > 0.9f) { + trackForceMag = x1914_spiderTrackForceMag >= 0.f ? forceMag : -forceMag; + continueTrackForce = true; + } else { + if (std::fabs(trackForceMag) > 0.05f) + trackForceMag = trackForceMag >= 0.f ? forceMag : -forceMag; + else forceApplied = false; } + } else { + forceApplied = false; + } - if (!continueTrackForce) - { - x190c_normSpiderSurfaceForces = normSurfaceForces; - x1914_spiderTrackForceMag = trackForceMag; - x1920_spiderForcesReset = true; - } + if (!continueTrackForce) { + x190c_normSpiderSurfaceForces = normSurfaceForces; + x1914_spiderTrackForceMag = trackForceMag; + x1920_spiderForcesReset = true; + } - if (!forceApplied) - { - trackForceMag = 0.f; - ResetSpiderBallForces(); - } + if (!forceApplied) { + trackForceMag = 0.f; + ResetSpiderBallForces(); + } - bool moving = true; - if (!forceApplied && x0_player.GetVelocity().magnitude() <= 6.5f) - moving = false; + bool moving = true; + if (!forceApplied && x0_player.GetVelocity().magnitude() <= 6.5f) + moving = false; - zeus::CVector3f moveDelta; - if (x18bd_touchingSpider && forceApplied) - { - if (x18c0_isSpiderSurface) - moveDelta = viewSurfaceForces * 0.1f; - else - moveDelta = x18a8_spiderBetweenPoints.normalized() * 0.1f * (trackForceMag >= 0.f ? 1.f : -1.f); - } - - zeus::CVector3f ballPos = GetBallToWorld().origin + moveDelta; - float distance = 0.f; - if (moving || !x18bd_touchingSpider || x188c_spiderPullMovement != 1.f || x18bf_spiderSwingInAir) - { - if (FindClosestSpiderBallWaypoint(mgr, ballPos, x1890_spiderTrackPoint, x189c_spiderInterpBetweenPoints, - x18a8_spiderBetweenPoints, distance, x1880_playerToSpiderNormal, - x18c0_isSpiderSurface, x18c4_spiderSurfaceTransform)) - { - x18bc_spiderNearby = true; - x18bf_spiderSwingInAir = false; - } - } + zeus::CVector3f moveDelta; + if (x18bd_touchingSpider && forceApplied) { + if (x18c0_isSpiderSurface) + moveDelta = viewSurfaceForces * 0.1f; else - { - x1880_playerToSpiderNormal = x1890_spiderTrackPoint - ballPos; - distance = x1880_playerToSpiderNormal.magnitude(); - x1880_playerToSpiderNormal = x1880_playerToSpiderNormal * (-1.f / distance); - x18bc_spiderNearby = true; - } + moveDelta = x18a8_spiderBetweenPoints.normalized() * 0.1f * (trackForceMag >= 0.f ? 1.f : -1.f); + } - if (x18bc_spiderNearby) - { - if (distance < kSpiderBallCollisionRadius) - x18bd_touchingSpider = true; - if (x18bd_touchingSpider) - { - if (moving) - { - if (!x18c0_isSpiderSurface) - { - x18b4_linVelDamp = 0.4f; - x18b8_angVelDamp = 0.2f; - float viewControlMag = viewSurfaceForces.dot(x189c_spiderInterpBetweenPoints.normalized()); - if (continueTrackForce && x1920_spiderForcesReset) - { - viewControlMag = x1918_spiderViewControlMag; - } - else - { - x1918_spiderViewControlMag = viewControlMag; - x1920_spiderForcesReset = false; - } - float finalForceMag; - if (std::fabs(viewControlMag) > 0.1f) - { - finalForceMag = std::copysign(zeus::clamp(-1.f, forceMag, 1.f), viewControlMag); - } - else - { - finalForceMag = 0.f; - ResetSpiderBallForces(); - } - if (distance > 1.05f) - finalForceMag *= (1.05f - (distance - 1.05f)) / 1.05f; - x0_player.ApplyForceWR(x18a8_spiderBetweenPoints.normalized() * 90000.f * finalForceMag, - zeus::CAxisAngle::sIdentity); - } - else - { - x18b4_linVelDamp = 0.3f; - x18b8_angVelDamp = 0.2f; - float f31 = x18c4_spiderSurfaceTransform.basis[0].dot(viewSurfaceForces); - float f30 = x18c4_spiderSurfaceTransform.basis[2].dot(viewSurfaceForces); - zeus::CVector3f forceVec = (f31 * x18c4_spiderSurfaceTransform.basis[0] + - f30 * x18c4_spiderSurfaceTransform.basis[2]) * 45000.f; - x0_player.ApplyForceWR(forceVec, zeus::CAxisAngle::sIdentity); - if (forceVec.magSquared() > 0.f) - { - float angle = std::atan2(45000.f * f31, 45000.f * f30); - if (angle - x18f4_spiderSurfacePivotAngle > M_PIF / 2.f) - angle = angle - M_PIF; - else if (x18f4_spiderSurfacePivotAngle - angle > M_PIF / 2.f) - angle = angle + M_PIF; - x18f8_spiderSurfacePivotTargetAngle = angle; - } - x18f4_spiderSurfacePivotAngle += - std::copysign(std::min(std::fabs(x18f8_spiderSurfacePivotTargetAngle - - x18f4_spiderSurfacePivotAngle), 0.2f), - x18f8_spiderSurfacePivotTargetAngle - x18f4_spiderSurfacePivotAngle); - x189c_spiderInterpBetweenPoints = - x18c4_spiderSurfaceTransform.rotate( - zeus::CTransform::RotateY(x18f4_spiderSurfacePivotAngle).basis[2]); - } - } - x0_player.ApplyForceWR({0.f, 0.f, - g_tweakBall->GetBallGravity() * x0_player.GetMass() * 8.f * (1.f - x188c_spiderPullMovement)}, - zeus::CAxisAngle::sIdentity); - } - else - { - x18b4_linVelDamp = 0.2f; - x18b8_angVelDamp = 0.2f; - } - x0_player.SetMomentumWR(4.f * x0_player.GetMass() * g_tweakBall->GetBallGravity() * x1880_playerToSpiderNormal); + zeus::CVector3f ballPos = GetBallToWorld().origin + moveDelta; + float distance = 0.f; + if (moving || !x18bd_touchingSpider || x188c_spiderPullMovement != 1.f || x18bf_spiderSwingInAir) { + if (FindClosestSpiderBallWaypoint(mgr, ballPos, x1890_spiderTrackPoint, x189c_spiderInterpBetweenPoints, + x18a8_spiderBetweenPoints, distance, x1880_playerToSpiderNormal, + x18c0_isSpiderSurface, x18c4_spiderSurfaceTransform)) { + x18bc_spiderNearby = true; + x18bf_spiderSwingInAir = false; } + } else { + x1880_playerToSpiderNormal = x1890_spiderTrackPoint - ballPos; + distance = x1880_playerToSpiderNormal.magnitude(); + x1880_playerToSpiderNormal = x1880_playerToSpiderNormal * (-1.f / distance); + x18bc_spiderNearby = true; + } + + if (x18bc_spiderNearby) { + if (distance < kSpiderBallCollisionRadius) + x18bd_touchingSpider = true; + if (x18bd_touchingSpider) { + if (moving) { + if (!x18c0_isSpiderSurface) { + x18b4_linVelDamp = 0.4f; + x18b8_angVelDamp = 0.2f; + float viewControlMag = viewSurfaceForces.dot(x189c_spiderInterpBetweenPoints.normalized()); + if (continueTrackForce && x1920_spiderForcesReset) { + viewControlMag = x1918_spiderViewControlMag; + } else { + x1918_spiderViewControlMag = viewControlMag; + x1920_spiderForcesReset = false; + } + float finalForceMag; + if (std::fabs(viewControlMag) > 0.1f) { + finalForceMag = std::copysign(zeus::clamp(-1.f, forceMag, 1.f), viewControlMag); + } else { + finalForceMag = 0.f; + ResetSpiderBallForces(); + } + if (distance > 1.05f) + finalForceMag *= (1.05f - (distance - 1.05f)) / 1.05f; + x0_player.ApplyForceWR(x18a8_spiderBetweenPoints.normalized() * 90000.f * finalForceMag, + zeus::CAxisAngle::sIdentity); + } else { + x18b4_linVelDamp = 0.3f; + x18b8_angVelDamp = 0.2f; + float f31 = x18c4_spiderSurfaceTransform.basis[0].dot(viewSurfaceForces); + float f30 = x18c4_spiderSurfaceTransform.basis[2].dot(viewSurfaceForces); + zeus::CVector3f forceVec = + (f31 * x18c4_spiderSurfaceTransform.basis[0] + f30 * x18c4_spiderSurfaceTransform.basis[2]) * 45000.f; + x0_player.ApplyForceWR(forceVec, zeus::CAxisAngle::sIdentity); + if (forceVec.magSquared() > 0.f) { + float angle = std::atan2(45000.f * f31, 45000.f * f30); + if (angle - x18f4_spiderSurfacePivotAngle > M_PIF / 2.f) + angle = angle - M_PIF; + else if (x18f4_spiderSurfacePivotAngle - angle > M_PIF / 2.f) + angle = angle + M_PIF; + x18f8_spiderSurfacePivotTargetAngle = angle; + } + x18f4_spiderSurfacePivotAngle += std::copysign( + std::min(std::fabs(x18f8_spiderSurfacePivotTargetAngle - x18f4_spiderSurfacePivotAngle), 0.2f), + x18f8_spiderSurfacePivotTargetAngle - x18f4_spiderSurfacePivotAngle); + x189c_spiderInterpBetweenPoints = + x18c4_spiderSurfaceTransform.rotate(zeus::CTransform::RotateY(x18f4_spiderSurfacePivotAngle).basis[2]); + } + } + x0_player.ApplyForceWR( + {0.f, 0.f, g_tweakBall->GetBallGravity() * x0_player.GetMass() * 8.f * (1.f - x188c_spiderPullMovement)}, + zeus::CAxisAngle::sIdentity); + } else { + x18b4_linVelDamp = 0.2f; + x18b8_angVelDamp = 0.2f; + } + x0_player.SetMomentumWR(4.f * x0_player.GetMass() * g_tweakBall->GetBallGravity() * x1880_playerToSpiderNormal); + } } -zeus::CVector2f CMorphBall::CalculateSpiderBallAttractionSurfaceForces(const CFinalInput& input) const -{ - if (!IsMovementAllowed()) - return zeus::CVector2f(); +zeus::CVector2f CMorphBall::CalculateSpiderBallAttractionSurfaceForces(const CFinalInput& input) const { + if (!IsMovementAllowed()) + return zeus::CVector2f(); - return {ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) - - ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input), - ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) - - ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input)}; + return {ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) - + ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input), + ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) - + ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input)}; } -bool CMorphBall::CheckForSwitchToSpiderBallSwinging(CStateManager& mgr) const -{ - if (!x18bd_touchingSpider) - return false; +bool CMorphBall::CheckForSwitchToSpiderBallSwinging(CStateManager& mgr) const { + if (!x18bd_touchingSpider) + return false; - if (x188c_spiderPullMovement == 1.f) - { - if (x18be_spiderBallSwinging) - { - zeus::CTransform ballToWorld = GetBallToWorld(); - zeus::CVector3f closestPoint, interpDeltaBetweenPoints, deltaBetweenPoints, normal; - float distance = 0.f; - bool isSurface; - zeus::CTransform surfaceTransform; - return !(FindClosestSpiderBallWaypoint(mgr, ballToWorld.origin, closestPoint, interpDeltaBetweenPoints, - deltaBetweenPoints, distance, normal, isSurface, surfaceTransform) - && distance < 2.1f); - } - return false; + if (x188c_spiderPullMovement == 1.f) { + if (x18be_spiderBallSwinging) { + zeus::CTransform ballToWorld = GetBallToWorld(); + zeus::CVector3f closestPoint, interpDeltaBetweenPoints, deltaBetweenPoints, normal; + float distance = 0.f; + bool isSurface; + zeus::CTransform surfaceTransform; + return !(FindClosestSpiderBallWaypoint(mgr, ballToWorld.origin, closestPoint, interpDeltaBetweenPoints, + deltaBetweenPoints, distance, normal, isSurface, surfaceTransform) && + distance < 2.1f); } + return false; + } - if (x18be_spiderBallSwinging) - return true; + if (x18be_spiderBallSwinging) + return true; - return std::fabs(x1880_playerToSpiderNormal.z()) > 0.9f; + return std::fabs(x1880_playerToSpiderNormal.z()) > 0.9f; } bool CMorphBall::FindClosestSpiderBallWaypoint(CStateManager& mgr, const zeus::CVector3f& ballCenter, - zeus::CVector3f& closestPoint, - zeus::CVector3f& interpDeltaBetweenPoints, + zeus::CVector3f& closestPoint, zeus::CVector3f& interpDeltaBetweenPoints, zeus::CVector3f& deltaBetweenPoints, float& distance, zeus::CVector3f& normal, bool& isSurface, - zeus::CTransform& surfaceTransform) const -{ - bool ret = false; - zeus::CAABox aabb(ballCenter - 2.1f, ballCenter + 2.1f); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, aabb, CMaterialFilter::skPassEverything, nullptr); - float minDist = 2.1f; + zeus::CTransform& surfaceTransform) const { + bool ret = false; + zeus::CAABox aabb(ballCenter - 2.1f, ballCenter + 2.1f); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, aabb, CMaterialFilter::skPassEverything, nullptr); + float minDist = 2.1f; - for (TUniqueId id : nearList) - { - if (TCastToConstPtr surface = mgr.GetObjectById(id)) - { - zeus::CUnitVector3f surfaceNorm(surface->GetTransform().basis[1]); - zeus::CPlane plane(surfaceNorm, surface->GetTranslation().dot(surfaceNorm)); - zeus::CVector3f intersectPoint; - if (plane.rayPlaneIntersection(ballCenter + surfaceNorm * 2.1f, - ballCenter - surfaceNorm * 2.1f, intersectPoint)) - { - zeus::CVector3f halfScale = surface->GetScale() * 0.5f; - zeus::CVector3f localPoint = zeus::CTransform::Scale(1.f / halfScale) * - surface->GetTransform().inverse() * intersectPoint; - localPoint.x() = zeus::clamp(-1.f, float(localPoint.x()), 1.f); - localPoint.z() = zeus::clamp(-1.f, float(localPoint.z()), 1.f); - zeus::CVector3f worldPoint = surface->GetTransform() * zeus::CTransform::Scale(halfScale) * localPoint; - zeus::CVector3f finalDelta = worldPoint - ballCenter; - float finalMag = finalDelta.magnitude(); - if (finalMag < minDist) - { - minDist = finalMag; - closestPoint = worldPoint; - distance = finalMag; - normal = finalDelta * (-1.f / finalMag); - isSurface = true; - surfaceTransform = surface->GetTransform(); - ret = true; - } - } + for (TUniqueId id : nearList) { + if (TCastToConstPtr surface = mgr.GetObjectById(id)) { + zeus::CUnitVector3f surfaceNorm(surface->GetTransform().basis[1]); + zeus::CPlane plane(surfaceNorm, surface->GetTranslation().dot(surfaceNorm)); + zeus::CVector3f intersectPoint; + if (plane.rayPlaneIntersection(ballCenter + surfaceNorm * 2.1f, ballCenter - surfaceNorm * 2.1f, + intersectPoint)) { + zeus::CVector3f halfScale = surface->GetScale() * 0.5f; + zeus::CVector3f localPoint = + zeus::CTransform::Scale(1.f / halfScale) * surface->GetTransform().inverse() * intersectPoint; + localPoint.x() = zeus::clamp(-1.f, float(localPoint.x()), 1.f); + localPoint.z() = zeus::clamp(-1.f, float(localPoint.z()), 1.f); + zeus::CVector3f worldPoint = surface->GetTransform() * zeus::CTransform::Scale(halfScale) * localPoint; + zeus::CVector3f finalDelta = worldPoint - ballCenter; + float finalMag = finalDelta.magnitude(); + if (finalMag < minDist) { + minDist = finalMag; + closestPoint = worldPoint; + distance = finalMag; + normal = finalDelta * (-1.f / finalMag); + isSurface = true; + surfaceTransform = surface->GetTransform(); + ret = true; } + } } + } - for (TUniqueId id : nearList) - { - if (TCastToConstPtr wp = mgr.GetObjectById(id)) - { - const CScriptSpiderBallWaypoint* closestWp = nullptr; - zeus::CVector3f worldPoint; - zeus::CVector3f useDeltaBetweenPoints = deltaBetweenPoints; - zeus::CVector3f useInterpDeltaBetweenPoints = interpDeltaBetweenPoints; - wp->GetClosestPointAlongWaypoints(mgr, ballCenter, 2.1f, closestWp, worldPoint, useDeltaBetweenPoints, - 0.8f, useInterpDeltaBetweenPoints); - if (closestWp) - { - zeus::CVector3f ballToPoint = worldPoint - ballCenter; - float ballToPointMag = ballToPoint.magnitude(); - if (ballToPointMag < minDist) - { - minDist = ballToPointMag; - closestPoint = worldPoint; - interpDeltaBetweenPoints = useInterpDeltaBetweenPoints; - deltaBetweenPoints = useDeltaBetweenPoints; - distance = ballToPointMag; - normal = ballToPoint * (-1.f / ballToPointMag); - isSurface = false; - ret = true; - } - } + for (TUniqueId id : nearList) { + if (TCastToConstPtr wp = mgr.GetObjectById(id)) { + const CScriptSpiderBallWaypoint* closestWp = nullptr; + zeus::CVector3f worldPoint; + zeus::CVector3f useDeltaBetweenPoints = deltaBetweenPoints; + zeus::CVector3f useInterpDeltaBetweenPoints = interpDeltaBetweenPoints; + wp->GetClosestPointAlongWaypoints(mgr, ballCenter, 2.1f, closestWp, worldPoint, useDeltaBetweenPoints, 0.8f, + useInterpDeltaBetweenPoints); + if (closestWp) { + zeus::CVector3f ballToPoint = worldPoint - ballCenter; + float ballToPointMag = ballToPoint.magnitude(); + if (ballToPointMag < minDist) { + minDist = ballToPointMag; + closestPoint = worldPoint; + interpDeltaBetweenPoints = useInterpDeltaBetweenPoints; + deltaBetweenPoints = useDeltaBetweenPoints; + distance = ballToPointMag; + normal = ballToPoint * (-1.f / ballToPointMag); + isSurface = false; + ret = true; } + } } + } - return ret; + return ret; } -void CMorphBall::SetSpiderBallSwingingState(bool active) -{ - if (x18be_spiderBallSwinging != active) - { - ResetSpiderBallSwingControllerMovementTimer(); - x18bf_spiderSwingInAir = true; - } - x18be_spiderBallSwinging = active; +void CMorphBall::SetSpiderBallSwingingState(bool active) { + if (x18be_spiderBallSwinging != active) { + ResetSpiderBallSwingControllerMovementTimer(); + x18bf_spiderSwingInAir = true; + } + x18be_spiderBallSwinging = active; } -float CMorphBall::GetSpiderBallControllerMovement(const CFinalInput& input) const -{ - if (!IsMovementAllowed()) - return 0.f; - - float forward = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) - - ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); - float turn = ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) - - ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input); - float angle = zeus::radToDeg(std::atan2(forward, turn)); - float hyp = std::sqrt(forward * forward + turn * turn); - if (angle > -35.f && angle < 125.f) - return hyp; - if (angle < -55.f || angle > 145.f) - return -hyp; +float CMorphBall::GetSpiderBallControllerMovement(const CFinalInput& input) const { + if (!IsMovementAllowed()) return 0.f; + + float forward = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) - + ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); + float turn = ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) - + ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input); + float angle = zeus::radToDeg(std::atan2(forward, turn)); + float hyp = std::sqrt(forward * forward + turn * turn); + if (angle > -35.f && angle < 125.f) + return hyp; + if (angle < -55.f || angle > 145.f) + return -hyp; + return 0.f; } -void CMorphBall::ResetSpiderBallSwingControllerMovementTimer() -{ - x1904_swingControlDir = 0.f; - x1908_swingControlTime = 0.f; +void CMorphBall::ResetSpiderBallSwingControllerMovementTimer() { + x1904_swingControlDir = 0.f; + x1908_swingControlTime = 0.f; } -void CMorphBall::UpdateSpiderBallSwingControllerMovementTimer(float movement, float dt) -{ - if (std::fabs(movement) < 0.05f) - { - ResetSpiderBallSwingControllerMovementTimer(); +void CMorphBall::UpdateSpiderBallSwingControllerMovementTimer(float movement, float dt) { + if (std::fabs(movement) < 0.05f) { + ResetSpiderBallSwingControllerMovementTimer(); + } else { + if ((movement >= 0.f ? 1.f : -1.f) != x1904_swingControlDir) { + ResetSpiderBallSwingControllerMovementTimer(); + x1904_swingControlDir = (movement >= 0.f ? 1.f : -1.f); + } else { + x1908_swingControlTime += dt; } - else - { - if ((movement >= 0.f ? 1.f : -1.f) != x1904_swingControlDir) - { - ResetSpiderBallSwingControllerMovementTimer(); - x1904_swingControlDir = (movement >= 0.f ? 1.f : -1.f); - } - else - { - x1908_swingControlTime += dt; - } + } +} + +float CMorphBall::GetSpiderBallSwingControllerMovementScalar() const { + if (x1908_swingControlTime < 1.2f) + return 1.f; + return std::max(0.f, (2.4f - x1908_swingControlTime) / 1.2f); +} + +void CMorphBall::CreateSpiderBallParticles(const zeus::CVector3f& ballPos, const zeus::CVector3f& trackPoint) { + x19d4_spiderBallMagnetEffectGen->SetParticleEmission(true); + zeus::CVector3f ballToTrack = trackPoint - ballPos; + float ballToTrackMag = ballToTrack.magnitude(); + int subCount = int(ballToTrackMag / 0.2f + 1.f); + ballToTrack = ballToTrack * (1.f / float(subCount)); + int count = int(8.f * (ballToTrackMag / 2.1f)); + for (int i = count; i >= 0; --i) { + zeus::CVector3f translation = ballPos; + for (int j = 0; j < subCount; ++j) { + x19d4_spiderBallMagnetEffectGen->SetTranslation(translation); + x19d4_spiderBallMagnetEffectGen->ForceParticleCreation(1); + translation += ballToTrack; } + } + x19d4_spiderBallMagnetEffectGen->SetParticleEmission(false); } -float CMorphBall::GetSpiderBallSwingControllerMovementScalar() const -{ - if (x1908_swingControlTime < 1.2f) - return 1.f; - return std::max(0.f, (2.4f - x1908_swingControlTime) / 1.2f); +void CMorphBall::ResetSpiderBallForces() { + x190c_normSpiderSurfaceForces = zeus::CVector2f(); + x1914_spiderTrackForceMag = 0.f; + x1918_spiderViewControlMag = 0.f; + x1920_spiderForcesReset = true; } -void CMorphBall::CreateSpiderBallParticles(const zeus::CVector3f& ballPos, const zeus::CVector3f& trackPoint) -{ - x19d4_spiderBallMagnetEffectGen->SetParticleEmission(true); - zeus::CVector3f ballToTrack = trackPoint - ballPos; - float ballToTrackMag = ballToTrack.magnitude(); - int subCount = int(ballToTrackMag / 0.2f + 1.f); - ballToTrack = ballToTrack * (1.f / float(subCount)); - int count = int(8.f * (ballToTrackMag / 2.1f)); - for (int i=count ; i>=0 ; --i) - { - zeus::CVector3f translation = ballPos; - for (int j=0 ; jSetTranslation(translation); - x19d4_spiderBallMagnetEffectGen->ForceParticleCreation(1); - translation += ballToTrack; - } +void CMorphBall::ComputeMarioMovement(const CFinalInput& input, CStateManager& mgr, float dt) { + x1c_controlForce = zeus::CVector3f::skZero; + x10_boostControlForce = zeus::CVector3f::skZero; + if (!IsMovementAllowed()) + return; + + x188c_spiderPullMovement = + (ControlMapper::GetAnalogInput(ControlMapper::ECommands::SpiderBall, input) >= 0.5f / 100.f) ? 1.f : 0.f; + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall) && x188c_spiderPullMovement != 0.f && + x191c_damageTimer == 0.f) { + if (x187c_spiderBallState != ESpiderBallState::Active) { + x18bd_touchingSpider = false; + x187c_spiderBallState = ESpiderBallState::Active; + x18a8_spiderBetweenPoints = x189c_spiderInterpBetweenPoints = x0_player.GetTransform().basis[2]; } - x19d4_spiderBallMagnetEffectGen->SetParticleEmission(false); -} + UpdateSpiderBall(input, mgr, dt); -void CMorphBall::ResetSpiderBallForces() -{ - x190c_normSpiderSurfaceForces = zeus::CVector2f(); - x1914_spiderTrackForceMag = 0.f; - x1918_spiderViewControlMag = 0.f; - x1920_spiderForcesReset = true; -} - -void CMorphBall::ComputeMarioMovement(const CFinalInput& input, CStateManager& mgr, float dt) -{ - x1c_controlForce = zeus::CVector3f::skZero; - x10_boostControlForce = zeus::CVector3f::skZero; - if (!IsMovementAllowed()) - return; - - x188c_spiderPullMovement = - (ControlMapper::GetAnalogInput(ControlMapper::ECommands::SpiderBall, input) >= 0.5f / 100.f) ? 1.f : 0.f; - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall) && - x188c_spiderPullMovement != 0.f && x191c_damageTimer == 0.f) - { - if (x187c_spiderBallState != ESpiderBallState::Active) - { - x18bd_touchingSpider = false; - x187c_spiderBallState = ESpiderBallState::Active; - x18a8_spiderBetweenPoints = x189c_spiderInterpBetweenPoints = x0_player.GetTransform().basis[2]; - } - UpdateSpiderBall(input, mgr, dt); - - if (!x18bc_spiderNearby) - { - x187c_spiderBallState = ESpiderBallState::Inactive; - ResetSpiderBallForces(); - } + if (!x18bc_spiderNearby) { + x187c_spiderBallState = ESpiderBallState::Inactive; + ResetSpiderBallForces(); } - else - { - x187c_spiderBallState = ESpiderBallState::Inactive; - ResetSpiderBallForces(); + } else { + x187c_spiderBallState = ESpiderBallState::Inactive; + ResetSpiderBallForces(); + } + + if (x187c_spiderBallState != ESpiderBallState::Active) { + float forward = ForwardInput(input); + float turn = -BallTurnInput(input); + float maxSpeed = ComputeMaxSpeed(); + float curSpeed = x0_player.GetVelocity().magnitude(); + zeus::CTransform controlXf = zeus::lookAt(zeus::CVector3f::skZero, x0_player.x54c_controlDirFlat); + zeus::CVector3f controlFrameVel = controlXf.transposeRotate(x0_player.GetVelocity()); + float fwdAcc = 0.f; + float turnAcc = 0.f; + if (std::fabs(turn) > 0.1f) { + float controlTurn = turn * maxSpeed; + float controlTurnDelta = controlTurn - controlFrameVel.x(); + float accFactor = zeus::clamp(0.f, std::fabs(controlTurnDelta) / maxSpeed, 1.f); + float maxAcc; + if ((controlFrameVel.x() > 0.f ? 1.f : -1.f) != (controlTurn > 0.f ? 1.f : -1.f) && curSpeed > 0.8f * maxSpeed) + maxAcc = g_tweakBall->GetBallForwardBrakingAcceleration(int(x0_player.GetSurfaceRestraint())); + else + maxAcc = g_tweakBall->GetMaxBallTranslationAcceleration(int(x0_player.GetSurfaceRestraint())); + if (controlTurnDelta < 0.f) + turnAcc = -maxAcc * accFactor; + else + turnAcc = maxAcc * accFactor; + } + if (std::fabs(forward) > 0.1f) { + float controlFwd = forward * maxSpeed; + float controlFwdDelta = controlFwd - controlFrameVel.y(); + float accFactor = zeus::clamp(0.f, std::fabs(controlFwdDelta) / maxSpeed, 1.f); + float maxAcc; + if ((controlFrameVel.y() > 0.f ? 1.f : -1.f) != (controlFwd > 0.f ? 1.f : -1.f) && curSpeed > 0.8f * maxSpeed) + maxAcc = g_tweakBall->GetBallForwardBrakingAcceleration(int(x0_player.GetSurfaceRestraint())); + else + maxAcc = g_tweakBall->GetMaxBallTranslationAcceleration(int(x0_player.GetSurfaceRestraint())); + if (controlFwdDelta < 0.f) + fwdAcc = -maxAcc * accFactor; + else + fwdAcc = maxAcc * accFactor; } - if (x187c_spiderBallState != ESpiderBallState::Active) - { - float forward = ForwardInput(input); - float turn = -BallTurnInput(input); - float maxSpeed = ComputeMaxSpeed(); - float curSpeed = x0_player.GetVelocity().magnitude(); - zeus::CTransform controlXf = zeus::lookAt(zeus::CVector3f::skZero, x0_player.x54c_controlDirFlat); - zeus::CVector3f controlFrameVel = controlXf.transposeRotate(x0_player.GetVelocity()); - float fwdAcc = 0.f; - float turnAcc = 0.f; - if (std::fabs(turn) > 0.1f) - { - float controlTurn = turn * maxSpeed; - float controlTurnDelta = controlTurn - controlFrameVel.x(); - float accFactor = zeus::clamp(0.f, std::fabs(controlTurnDelta) / maxSpeed, 1.f); - float maxAcc; - if ((controlFrameVel.x() > 0.f ? 1.f : -1.f) != (controlTurn > 0.f ? 1.f : -1.f) && - curSpeed > 0.8f * maxSpeed) - maxAcc = g_tweakBall->GetBallForwardBrakingAcceleration(int(x0_player.GetSurfaceRestraint())); - else - maxAcc = g_tweakBall->GetMaxBallTranslationAcceleration(int(x0_player.GetSurfaceRestraint())); - if (controlTurnDelta < 0.f) - turnAcc = -maxAcc * accFactor; - else - turnAcc = maxAcc * accFactor; + if (fwdAcc != 0.f || turnAcc != 0.f || x1de4_24_inBoost || GetIsInHalfPipeMode()) { + zeus::CVector3f controlForce = controlXf.rotate({0.f, fwdAcc, 0.f}) + controlXf.rotate({turnAcc, 0.f, 0.f}); + x1c_controlForce = controlForce; + if (x1de4_24_inBoost && !GetIsInHalfPipeMode()) + controlForce = x1924_surfaceToWorld.rotate({x1924_surfaceToWorld.transposeRotate(controlForce).x(), 0.f, 0.f}); + + if (GetIsInHalfPipeMode() && controlForce.magnitude() > FLT_EPSILON) { + if (GetIsInHalfPipeModeInAir() && curSpeed <= 15.f && + controlForce.dot(x1924_surfaceToWorld.basis[2]) / controlForce.magnitude() < -0.85f) { + DisableHalfPipeStatus(); + x1e00_disableControlCooldown = 0.2f; + x0_player.ApplyImpulseWR(x1924_surfaceToWorld.basis[2] * (x0_player.GetMass() * -7.5f), + zeus::CAxisAngle::sIdentity); } - if (std::fabs(forward) > 0.1f) - { - float controlFwd = forward * maxSpeed; - float controlFwdDelta = controlFwd - controlFrameVel.y(); - float accFactor = zeus::clamp(0.f, std::fabs(controlFwdDelta) / maxSpeed, 1.f); - float maxAcc; - if ((controlFrameVel.y() > 0.f ? 1.f : -1.f) != (controlFwd > 0.f ? 1.f : -1.f) && - curSpeed > 0.8f * maxSpeed) - maxAcc = g_tweakBall->GetBallForwardBrakingAcceleration(int(x0_player.GetSurfaceRestraint())); - else - maxAcc = g_tweakBall->GetMaxBallTranslationAcceleration(int(x0_player.GetSurfaceRestraint())); - if (controlFwdDelta < 0.f) - fwdAcc = -maxAcc * accFactor; - else - fwdAcc = maxAcc * accFactor; + if (GetIsInHalfPipeMode()) { + controlForce -= controlForce.dot(x1924_surfaceToWorld.basis[2]) * x1924_surfaceToWorld.basis[2]; + zeus::CVector3f controlForceSurfaceLocal = x1924_surfaceToWorld.transposeRotate(controlForce); + controlForceSurfaceLocal.x() *= 0.6f; + controlForceSurfaceLocal.y() *= (x1de4_24_inBoost ? 0.f : 0.35f) * 1.4f; + controlForce = x1924_surfaceToWorld.rotate(controlForceSurfaceLocal); + if (maxSpeed > 95.f) + x0_player.SetVelocityWR(x0_player.GetVelocity() * 0.99f); } + } - if (fwdAcc != 0.f || turnAcc != 0.f || x1de4_24_inBoost || GetIsInHalfPipeMode()) - { - zeus::CVector3f controlForce = controlXf.rotate({0.f, fwdAcc, 0.f}) + controlXf.rotate({turnAcc, 0.f, 0.f}); - x1c_controlForce = controlForce; - if (x1de4_24_inBoost && !GetIsInHalfPipeMode()) - controlForce = - x1924_surfaceToWorld.rotate({x1924_surfaceToWorld.transposeRotate(controlForce).x(), 0.f, 0.f}); - - if (GetIsInHalfPipeMode() && controlForce.magnitude() > FLT_EPSILON) - { - if (GetIsInHalfPipeModeInAir() && curSpeed <= 15.f && - controlForce.dot(x1924_surfaceToWorld.basis[2]) / controlForce.magnitude() < -0.85f) - { - DisableHalfPipeStatus(); - x1e00_disableControlCooldown = 0.2f; - x0_player.ApplyImpulseWR(x1924_surfaceToWorld.basis[2] * (x0_player.GetMass() * -7.5f), - zeus::CAxisAngle::sIdentity); - } - if (GetIsInHalfPipeMode()) - { - controlForce -= controlForce.dot(x1924_surfaceToWorld.basis[2]) * x1924_surfaceToWorld.basis[2]; - zeus::CVector3f controlForceSurfaceLocal = x1924_surfaceToWorld.transposeRotate(controlForce); - controlForceSurfaceLocal.x() *= 0.6f; - controlForceSurfaceLocal.y() *= (x1de4_24_inBoost ? 0.f : 0.35f) * 1.4f; - controlForce = x1924_surfaceToWorld.rotate(controlForceSurfaceLocal); - if (maxSpeed > 95.f) - x0_player.SetVelocityWR(x0_player.GetVelocity() * 0.99f); - } - } - - if (GetTouchedHalfPipeRecently()) - { - float hpNormComp = x1e08_prevHalfPipeNormal.dot(x1e14_halfPipeNormal); - if (hpNormComp < 0.99f && hpNormComp > 0.5f) - { - zeus::CVector3f hpRampAxis = x1e08_prevHalfPipeNormal.cross(x1e14_halfPipeNormal).normalized(); - zeus::CVector3f newVel = x0_player.GetVelocity(); - newVel -= hpRampAxis * hpRampAxis.dot(x0_player.GetVelocity()) * 0.15f; - x0_player.SetVelocityWR(newVel); - } - } - - float speedThres = 0.75f * maxSpeed; - if (curSpeed >= speedThres) - { - float dot = controlForce.dot(x0_player.GetVelocity().normalized()); - if (dot > 0.f) - { - controlForce -= x0_player.GetVelocity().normalized() * - zeus::clamp(0.f, (curSpeed - speedThres) / (maxSpeed - speedThres), 1.f) * dot; - } - } - x10_boostControlForce = controlForce; - x0_player.ApplyForceWR(controlForce, zeus::CAxisAngle::sIdentity); + if (GetTouchedHalfPipeRecently()) { + float hpNormComp = x1e08_prevHalfPipeNormal.dot(x1e14_halfPipeNormal); + if (hpNormComp < 0.99f && hpNormComp > 0.5f) { + zeus::CVector3f hpRampAxis = x1e08_prevHalfPipeNormal.cross(x1e14_halfPipeNormal).normalized(); + zeus::CVector3f newVel = x0_player.GetVelocity(); + newVel -= hpRampAxis * hpRampAxis.dot(x0_player.GetVelocity()) * 0.15f; + x0_player.SetVelocityWR(newVel); } - ComputeLiftForces(x1c_controlForce, x0_player.GetVelocity(), mgr); + } + + float speedThres = 0.75f * maxSpeed; + if (curSpeed >= speedThres) { + float dot = controlForce.dot(x0_player.GetVelocity().normalized()); + if (dot > 0.f) { + controlForce -= x0_player.GetVelocity().normalized() * + zeus::clamp(0.f, (curSpeed - speedThres) / (maxSpeed - speedThres), 1.f) * dot; + } + } + x10_boostControlForce = controlForce; + x0_player.ApplyForceWR(controlForce, zeus::CAxisAngle::sIdentity); } + ComputeLiftForces(x1c_controlForce, x0_player.GetVelocity(), mgr); + } } -zeus::CTransform CMorphBall::GetSwooshToWorld() const -{ - return zeus::CTransform::Translate(x0_player.GetTranslation() + zeus::CVector3f(0.f, 0.f, GetBallRadius())) * - x1924_surfaceToWorld.getRotation() * zeus::CTransform::RotateY(x30_ballTiltAngle); +zeus::CTransform CMorphBall::GetSwooshToWorld() const { + return zeus::CTransform::Translate(x0_player.GetTranslation() + zeus::CVector3f(0.f, 0.f, GetBallRadius())) * + x1924_surfaceToWorld.getRotation() * zeus::CTransform::RotateY(x30_ballTiltAngle); } -zeus::CTransform CMorphBall::GetBallToWorld() const -{ - return zeus::CTransform::Translate(x0_player.GetTranslation() + zeus::CVector3f(0.f, 0.f, GetBallRadius())) * - x0_player.GetTransform().getRotation(); +zeus::CTransform CMorphBall::GetBallToWorld() const { + return zeus::CTransform::Translate(x0_player.GetTranslation() + zeus::CVector3f(0.f, 0.f, GetBallRadius())) * + x0_player.GetTransform().getRotation(); } zeus::CTransform CMorphBall::CalculateSurfaceToWorld(const zeus::CVector3f& trackNormal, const zeus::CVector3f& trackPoint, - const zeus::CVector3f& ballDir) const -{ - if (ballDir.canBeNormalized()) - { - zeus::CVector3f forward = ballDir.normalized(); - zeus::CVector3f right = ballDir.cross(trackNormal); - if (right.canBeNormalized()) - return zeus::CTransform(right, forward, right.cross(forward).normalized(), trackPoint); - } - return zeus::CTransform::Identity(); + const zeus::CVector3f& ballDir) const { + if (ballDir.canBeNormalized()) { + zeus::CVector3f forward = ballDir.normalized(); + zeus::CVector3f right = ballDir.cross(trackNormal); + if (right.canBeNormalized()) + return zeus::CTransform(right, forward, right.cross(forward).normalized(), trackPoint); + } + return zeus::CTransform::Identity(); } -bool CMorphBall::CalculateBallContactInfo(zeus::CVector3f& normal, zeus::CVector3f& point) const -{ - if (x74_collisionInfos.GetCount() != 0) - { - normal = x74_collisionInfos.Front().GetNormalLeft(); - point = x74_collisionInfos.Front().GetPoint(); - return true; - } - return false; +bool CMorphBall::CalculateBallContactInfo(zeus::CVector3f& normal, zeus::CVector3f& point) const { + if (x74_collisionInfos.GetCount() != 0) { + normal = x74_collisionInfos.Front().GetNormalLeft(); + point = x74_collisionInfos.Front().GetPoint(); + return true; + } + return false; } -void CMorphBall::UpdateBallDynamics(CStateManager& mgr, float dt) -{ - x0_player.SetAngularVelocityWR(x0_player.GetAngularVelocityWR().getVector() * 0.95f); - x1df8_27_ballCloseToCollision = BallCloseToCollision(mgr, kSpiderBallCollisionRadius, - CMaterialFilter::MakeInclude(EMaterialTypes::Solid)); - UpdateHalfPipeStatus(mgr, dt); - x1e00_disableControlCooldown -= dt; - x1e00_disableControlCooldown = std::max(0.f, x1e00_disableControlCooldown); - x191c_damageTimer -= dt; - x191c_damageTimer = std::max(0.f, x191c_damageTimer); - if (x187c_spiderBallState == ESpiderBallState::Active) - { - x1924_surfaceToWorld = CalculateSurfaceToWorld(x1880_playerToSpiderNormal, - x1890_spiderTrackPoint, x189c_spiderInterpBetweenPoints); - x2c_tireLeanAngle = 0.f; - if (!x28_tireMode) - SwitchToTire(); - x1c2c_tireInterpolating = true; - x1c28_tireInterpSpeed = -1.f; - UpdateMarbleDynamics(mgr, dt, x1890_spiderTrackPoint); - } - else - { - if (x0_player.GetSurfaceRestraint() != CPlayer::ESurfaceRestraints::InAir) - { - zeus::CVector3f normal, point; - if (CalculateBallContactInfo(normal, point)) - { - x1924_surfaceToWorld = CalculateSurfaceToWorld(normal, point, x0_player.x500_lookDir); - float speed = x0_player.GetVelocity().magnitude(); - if (speed < g_tweakBall->GetTireToMarbleThresholdSpeed() && x28_tireMode) - SwitchToMarble(); - if (UpdateMarbleDynamics(mgr, dt, point) && - speed >= g_tweakBall->GetMarbleToTireThresholdSpeed() && !x28_tireMode) - SwitchToTire(); - if (x28_tireMode) - { - x2c_tireLeanAngle = x0_player.GetTransform().transposeRotate(x0_player.GetForceOR()).x() / - g_tweakBall->GetMaxBallTranslationAcceleration(int(x0_player.GetSurfaceRestraint())) * - g_tweakBall->GetMaxLeanAngle() * g_tweakBall->GetForceToLeanGain(); - x2c_tireLeanAngle = - zeus::clamp(-g_tweakBall->GetMaxLeanAngle(), x2c_tireLeanAngle, g_tweakBall->GetMaxLeanAngle()); - if (x0_player.GetTransform().basis[0].dot(x1924_surfaceToWorld.basis[0]) < 0.f) - { - x2c_tireLeanAngle = -x2c_tireLeanAngle; - } - } - } - } - else - { - x2c_tireLeanAngle = 0.f; - } - } - - zeus::CRelAngle angle(x2c_tireLeanAngle - x30_ballTiltAngle); - float leanSpeed = std::fabs(angle) * g_tweakBall->GetMaxLeanAngle() * g_tweakBall->GetLeanTrackingGain(); - if (angle.asRadians() > 0.05f) - x30_ballTiltAngle += leanSpeed * dt; - else if (angle.asRadians() < -0.05f) - x30_ballTiltAngle -= leanSpeed * dt; - else - x30_ballTiltAngle = x2c_tireLeanAngle; - - if (x187c_spiderBallState != ESpiderBallState::Active) - ApplyFriction(CalculateSurfaceFriction()); - else - DampLinearAndAngularVelocities(x18b4_linVelDamp, x18b8_angVelDamp); - - if (x187c_spiderBallState != ESpiderBallState::Active) - ApplyGravity(mgr); - - x74_collisionInfos.Clear(); - - x1c3c_ballOrientAvg.AddValue(zeus::CQuaternion(GetBallToWorld().basis)); - x1c90_ballPosAvg.AddValue(GetBallToWorld().origin); -} - -void CMorphBall::SwitchToMarble() -{ - x0_player.SetTransform(x0_player.GetTransform() * zeus::CQuaternion::fromAxisAngle( - x0_player.GetTransform().transposeRotate(x0_player.x500_lookDir), x30_ballTiltAngle).toTransform()); - x28_tireMode = false; +void CMorphBall::UpdateBallDynamics(CStateManager& mgr, float dt) { + x0_player.SetAngularVelocityWR(x0_player.GetAngularVelocityWR().getVector() * 0.95f); + x1df8_27_ballCloseToCollision = + BallCloseToCollision(mgr, kSpiderBallCollisionRadius, CMaterialFilter::MakeInclude(EMaterialTypes::Solid)); + UpdateHalfPipeStatus(mgr, dt); + x1e00_disableControlCooldown -= dt; + x1e00_disableControlCooldown = std::max(0.f, x1e00_disableControlCooldown); + x191c_damageTimer -= dt; + x191c_damageTimer = std::max(0.f, x191c_damageTimer); + if (x187c_spiderBallState == ESpiderBallState::Active) { + x1924_surfaceToWorld = + CalculateSurfaceToWorld(x1880_playerToSpiderNormal, x1890_spiderTrackPoint, x189c_spiderInterpBetweenPoints); + x2c_tireLeanAngle = 0.f; + if (!x28_tireMode) + SwitchToTire(); x1c2c_tireInterpolating = true; x1c28_tireInterpSpeed = -1.f; -} - -void CMorphBall::SwitchToTire() -{ - x28_tireMode = true; - x1c2c_tireInterpolating = true; - x30_ballTiltAngle = 0.f; - x1c28_tireInterpSpeed = 1.f; -} - -void CMorphBall::Update(float dt, CStateManager& mgr) -{ - if (x187c_spiderBallState == ESpiderBallState::Active) - CreateSpiderBallParticles(GetBallToWorld().origin, x1890_spiderTrackPoint); - - if (x0_player.GetDeathTime() <= 0.f) - UpdateEffects(dt, mgr); - - if (x1e44_damageEffect > 0.f) - { - x1e44_damageEffect -= x1e48_damageEffectDecaySpeed * dt; - if (x1e44_damageEffect <= 0.f) - { - x1e44_damageEffect = 0.f; - x1e48_damageEffectDecaySpeed = 0.f; - x1e4c_damageTime = 0.f; - } - else - { - x1e4c_damageTime += dt; + UpdateMarbleDynamics(mgr, dt, x1890_spiderTrackPoint); + } else { + if (x0_player.GetSurfaceRestraint() != CPlayer::ESurfaceRestraints::InAir) { + zeus::CVector3f normal, point; + if (CalculateBallContactInfo(normal, point)) { + x1924_surfaceToWorld = CalculateSurfaceToWorld(normal, point, x0_player.x500_lookDir); + float speed = x0_player.GetVelocity().magnitude(); + if (speed < g_tweakBall->GetTireToMarbleThresholdSpeed() && x28_tireMode) + SwitchToMarble(); + if (UpdateMarbleDynamics(mgr, dt, point) && speed >= g_tweakBall->GetMarbleToTireThresholdSpeed() && + !x28_tireMode) + SwitchToTire(); + if (x28_tireMode) { + x2c_tireLeanAngle = x0_player.GetTransform().transposeRotate(x0_player.GetForceOR()).x() / + g_tweakBall->GetMaxBallTranslationAcceleration(int(x0_player.GetSurfaceRestraint())) * + g_tweakBall->GetMaxLeanAngle() * g_tweakBall->GetForceToLeanGain(); + x2c_tireLeanAngle = + zeus::clamp(-g_tweakBall->GetMaxLeanAngle(), x2c_tireLeanAngle, g_tweakBall->GetMaxLeanAngle()); + if (x0_player.GetTransform().basis[0].dot(x1924_surfaceToWorld.basis[0]) < 0.f) { + x2c_tireLeanAngle = -x2c_tireLeanAngle; + } } + } + } else { + x2c_tireLeanAngle = 0.f; } + } - if (x58_ballModel) - x58_ballModel->AdvanceAnimation(dt, mgr, kInvalidAreaId, true); + zeus::CRelAngle angle(x2c_tireLeanAngle - x30_ballTiltAngle); + float leanSpeed = std::fabs(angle) * g_tweakBall->GetMaxLeanAngle() * g_tweakBall->GetLeanTrackingGain(); + if (angle.asRadians() > 0.05f) + x30_ballTiltAngle += leanSpeed * dt; + else if (angle.asRadians() < -0.05f) + x30_ballTiltAngle -= leanSpeed * dt; + else + x30_ballTiltAngle = x2c_tireLeanAngle; - if (x1c2c_tireInterpolating) - { - x1c20_tireFactor += x1c28_tireInterpSpeed * dt; - if (x1c20_tireFactor < 0.f) - { - x1c2c_tireInterpolating = false; - x1c20_tireFactor = 0.f; - } - else if (x1c20_tireFactor > x1c24_maxTireFactor) - { - x1c2c_tireInterpolating = false; - x1c20_tireFactor = x1c24_maxTireFactor; - } + if (x187c_spiderBallState != ESpiderBallState::Active) + ApplyFriction(CalculateSurfaceFriction()); + else + DampLinearAndAngularVelocities(x18b4_linVelDamp, x18b8_angVelDamp); + + if (x187c_spiderBallState != ESpiderBallState::Active) + ApplyGravity(mgr); + + x74_collisionInfos.Clear(); + + x1c3c_ballOrientAvg.AddValue(zeus::CQuaternion(GetBallToWorld().basis)); + x1c90_ballPosAvg.AddValue(GetBallToWorld().origin); +} + +void CMorphBall::SwitchToMarble() { + x0_player.SetTransform(x0_player.GetTransform() * + zeus::CQuaternion::fromAxisAngle( + x0_player.GetTransform().transposeRotate(x0_player.x500_lookDir), x30_ballTiltAngle) + .toTransform()); + x28_tireMode = false; + x1c2c_tireInterpolating = true; + x1c28_tireInterpSpeed = -1.f; +} + +void CMorphBall::SwitchToTire() { + x28_tireMode = true; + x1c2c_tireInterpolating = true; + x30_ballTiltAngle = 0.f; + x1c28_tireInterpSpeed = 1.f; +} + +void CMorphBall::Update(float dt, CStateManager& mgr) { + if (x187c_spiderBallState == ESpiderBallState::Active) + CreateSpiderBallParticles(GetBallToWorld().origin, x1890_spiderTrackPoint); + + if (x0_player.GetDeathTime() <= 0.f) + UpdateEffects(dt, mgr); + + if (x1e44_damageEffect > 0.f) { + x1e44_damageEffect -= x1e48_damageEffectDecaySpeed * dt; + if (x1e44_damageEffect <= 0.f) { + x1e44_damageEffect = 0.f; + x1e48_damageEffectDecaySpeed = 0.f; + x1e4c_damageTime = 0.f; + } else { + x1e4c_damageTime += dt; } + } - if (x1c1c_rainSplashGen) - x1c1c_rainSplashGen->Update(dt, mgr); + if (x58_ballModel) + x58_ballModel->AdvanceAnimation(dt, mgr, kInvalidAreaId, true); - UpdateMorphBallSounds(dt); -} - -void CMorphBall::DeleteLight(CStateManager& mgr) -{ - if (x1c10_ballInnerGlowLight != kInvalidUniqueId) - { - mgr.FreeScriptObject(x1c10_ballInnerGlowLight); - x1c10_ballInnerGlowLight = kInvalidUniqueId; + if (x1c2c_tireInterpolating) { + x1c20_tireFactor += x1c28_tireInterpSpeed * dt; + if (x1c20_tireFactor < 0.f) { + x1c2c_tireInterpolating = false; + x1c20_tireFactor = 0.f; + } else if (x1c20_tireFactor > x1c24_maxTireFactor) { + x1c2c_tireInterpolating = false; + x1c20_tireFactor = x1c24_maxTireFactor; } + } + + if (x1c1c_rainSplashGen) + x1c1c_rainSplashGen->Update(dt, mgr); + + UpdateMorphBallSounds(dt); } -void CMorphBall::SetBallLightActive(CStateManager& mgr, bool active) -{ - if (x1c10_ballInnerGlowLight != kInvalidUniqueId) - if (TCastToPtr light = mgr.ObjectById(x1c10_ballInnerGlowLight)) - light->SetActive(active); +void CMorphBall::DeleteLight(CStateManager& mgr) { + if (x1c10_ballInnerGlowLight != kInvalidUniqueId) { + mgr.FreeScriptObject(x1c10_ballInnerGlowLight); + x1c10_ballInnerGlowLight = kInvalidUniqueId; + } } -void CMorphBall::EnterMorphBallState(CStateManager& mgr) -{ - x1c20_tireFactor = 0.f; - UpdateEffects(0.f, mgr); - x187c_spiderBallState = ESpiderBallState::Inactive; - CAnimPlaybackParms parms(0, -1, 1.f, true); - x58_ballModel->AnimationData()->SetAnimation(parms, false); - x1e20_ballAnimIdx = 0; - StopEffects(); - x1c30_boostOverLightFactor = 0.f; - x1c34_boostLightFactor = 0.f; - x1c38_spiderLightFactor = 0.f; - DisableHalfPipeStatus(); - x30_ballTiltAngle = 0.f; - x2c_tireLeanAngle = 0.f; +void CMorphBall::SetBallLightActive(CStateManager& mgr, bool active) { + if (x1c10_ballInnerGlowLight != kInvalidUniqueId) + if (TCastToPtr light = mgr.ObjectById(x1c10_ballInnerGlowLight)) + light->SetActive(active); } -void CMorphBall::LeaveMorphBallState(CStateManager& mgr) -{ - LeaveBoosting(); +void CMorphBall::EnterMorphBallState(CStateManager& mgr) { + x1c20_tireFactor = 0.f; + UpdateEffects(0.f, mgr); + x187c_spiderBallState = ESpiderBallState::Inactive; + CAnimPlaybackParms parms(0, -1, 1.f, true); + x58_ballModel->AnimationData()->SetAnimation(parms, false); + x1e20_ballAnimIdx = 0; + StopEffects(); + x1c30_boostOverLightFactor = 0.f; + x1c34_boostLightFactor = 0.f; + x1c38_spiderLightFactor = 0.f; + DisableHalfPipeStatus(); + x30_ballTiltAngle = 0.f; + x2c_tireLeanAngle = 0.f; +} + +void CMorphBall::LeaveMorphBallState(CStateManager& mgr) { + LeaveBoosting(); + CancelBoosting(); + CSfxManager::SfxStop(x1e24_boostSfxHandle); + StopEffects(); +} + +static const u8 skBallInnerGlowColors[9][3] = {{0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x60, 0xff, 0x90}, + {0x33, 0x33, 0xff}, {0xff, 0x80, 0x80}, {0x0, 0x9d, 0xb6}, + {0xd3, 0xf1, 0x0}, {0x60, 0x33, 0xff}, {0xfb, 0x98, 0x21}}; + +void CMorphBall::UpdateEffects(float dt, CStateManager& mgr) { + zeus::CTransform swooshToWorld = GetSwooshToWorld(); + x19b8_slowBlueTailSwooshGen->SetTranslation(swooshToWorld.rotate({0.1f, 0.f, 0.f}) + swooshToWorld.origin); + x19b8_slowBlueTailSwooshGen->SetOrientation(swooshToWorld.getRotation()); + x19b8_slowBlueTailSwooshGen->DoWarmupUpdate(); + x19bc_slowBlueTailSwooshGen2->SetTranslation(swooshToWorld.rotate({-0.1f, 0.f, 0.f}) + swooshToWorld.origin); + x19bc_slowBlueTailSwooshGen2->SetOrientation(swooshToWorld.getRotation()); + x19bc_slowBlueTailSwooshGen2->DoWarmupUpdate(); + x19c0_slowBlueTailSwoosh2Gen->SetTranslation(swooshToWorld.rotate({0.f, 0.f, 0.65f}) + swooshToWorld.origin); + x19c0_slowBlueTailSwoosh2Gen->SetOrientation(swooshToWorld.getRotation()); + x19c0_slowBlueTailSwoosh2Gen->DoWarmupUpdate(); + x19c4_slowBlueTailSwoosh2Gen2->SetTranslation(swooshToWorld.rotate({0.f, 0.f, -0.65f}) + swooshToWorld.origin); + x19c4_slowBlueTailSwoosh2Gen2->SetOrientation(swooshToWorld.getRotation()); + x19c4_slowBlueTailSwoosh2Gen2->DoWarmupUpdate(); + x19c8_jaggyTrailGen->SetTranslation(swooshToWorld.origin); + x19c8_jaggyTrailGen->SetOrientation(swooshToWorld.getRotation()); + x19c8_jaggyTrailGen->DoWarmupUpdate(); + x19cc_wallSparkGen->Update(dt); + x1bc8_wakeEffectGens[7]->Update(dt); + bool emitRainWake = (x0_player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround && + mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain && + mgr.GetEnvFxManager()->GetRainMagnitude() > 0.f && mgr.GetEnvFxManager()->IsSplashActive()); + x1bc8_wakeEffectGens[7]->SetParticleEmission(emitRainWake); + float rainGenRate = std::min(mgr.GetEnvFxManager()->GetRainMagnitude() * 2.f * x0_player.x4fc_flatMoveSpeed / + x0_player.GetBallMaxVelocity(), + 1.f); + x1bc8_wakeEffectGens[7]->SetGeneratorRate(rainGenRate); + x1bc8_wakeEffectGens[7]->SetTranslation(x0_player.GetTranslation()); + if (emitRainWake) { + zeus::CTransform rainOrient = + zeus::lookAt(x0_player.x50c_moveDir + x0_player.GetTranslation(), x0_player.GetTranslation()); + x1bc8_wakeEffectGens[7]->SetOrientation(rainOrient); + } + if (x1c0c_wakeEffectIdx != -1) + x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->Update(dt); + if (x1e38_wallSparkFrameCountdown > 0) { + x1e38_wallSparkFrameCountdown -= 1; + if (x1e38_wallSparkFrameCountdown <= 0) + x19cc_wallSparkGen->SetParticleEmission(false); + } + x19d0_ballInnerGlowGen->SetGlobalTranslation(swooshToWorld.origin); + x19d0_ballInnerGlowGen->Update(dt); + if (x1de8_boostChargeTime == 0.f && x1df4_boostDrainTime == 0.f) { + x19d8_boostBallGlowGen->SetModulationColor(zeus::CColor::skClear); + } else { + x19d8_boostBallGlowGen->SetGlobalTranslation(swooshToWorld.origin); + float t; + if (x1df4_boostDrainTime == 0.f) + t = x1de8_boostChargeTime / g_tweakBall->GetBoostBallMaxChargeTime(); + else + t = 1.f - x1df4_boostDrainTime / g_tweakBall->GetBoostBallDrainTime(); + x19d8_boostBallGlowGen->SetModulationColor( + zeus::CColor::lerp(zeus::CColor::skBlack, zeus::CColor(1.f, 1.f, 0.4f, 1.f), t)); + x19d8_boostBallGlowGen->Update(dt); + } + x19d4_spiderBallMagnetEffectGen->Update(dt); + x1c30_boostOverLightFactor -= 0.03f; + x1c30_boostOverLightFactor = std::max(0.f, x1c30_boostOverLightFactor); + if (x1c30_boostOverLightFactor == 0.f) { + x1c34_boostLightFactor -= 0.04f; + x1c34_boostLightFactor = std::max(0.f, x1c34_boostLightFactor); + } + if (x1de4_24_inBoost) { + x1c30_boostOverLightFactor = 1.f; + x1c34_boostLightFactor = 1.f; + } else { + x1c34_boostLightFactor = + std::max(x1de8_boostChargeTime / g_tweakBall->GetBoostBallMaxChargeTime(), x1c34_boostLightFactor); + x1c34_boostLightFactor = std::min(x1c34_boostLightFactor, 1.f); + } + UpdateMorphBallTransitionFlash(dt); + UpdateIceBreakEffect(dt); + if (x1c10_ballInnerGlowLight != kInvalidUniqueId) { + if (TCastToPtr light = mgr.ObjectById(x1c10_ballInnerGlowLight)) { + light->SetTranslation(swooshToWorld.origin + zeus::CVector3f(0.f, 0.f, GetBallRadius())); + std::experimental::optional lObj; + if (IsMorphBallTransitionFlashValid() && x19dc_morphBallTransitionFlashGen->SystemHasLight()) + lObj.emplace(x19dc_morphBallTransitionFlashGen->GetLight()); + else if (x19d0_ballInnerGlowGen->SystemHasLight()) + lObj.emplace(x19d0_ballInnerGlowGen->GetLight()); + if (lObj) { + const u8* c = skBallInnerGlowColors[x8_ballGlowColorIdx]; + zeus::CColor color(c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f); + lObj->SetColor(lObj->GetColor() * c); + if (x0_player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphing) { + float t = 0.f; + if (x0_player.x578_morphDuration != 0.f) + t = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); + lObj->SetColor(zeus::CColor::lerp(lObj->GetColor(), zeus::CColor::skBlack, t)); + } else if (x0_player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphing) { + float t = 0.f; + if (x0_player.x578_morphDuration != 0.f) + t = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); + if (t < 0.5f) + lObj->SetColor(zeus::CColor::lerp(zeus::CColor::skBlack, lObj->GetColor(), std::min(2.f * t, 1.f))); + } else { + lObj->SetColor(zeus::CColor::lerp(lObj->GetColor(), zeus::CColor::skWhite, x1c34_boostLightFactor)); + } + light->SetLight(*lObj); + } + } + } + + if (x187c_spiderBallState == ESpiderBallState::Active) { + AddSpiderBallElectricalEffect(); + AddSpiderBallElectricalEffect(); + AddSpiderBallElectricalEffect(); + AddSpiderBallElectricalEffect(); + AddSpiderBallElectricalEffect(); + x1c38_spiderLightFactor = std::min(x1c38_spiderLightFactor + 0.25f, 1.f); + } else { + x1c38_spiderLightFactor = std::max(0.f, x1c38_spiderLightFactor - 0.15f); + } + + UpdateSpiderBallElectricalEffects(); +} + +void CMorphBall::ComputeBoostBallMovement(const CFinalInput& input, CStateManager& mgr, float dt) { + if (!IsMovementAllowed() || !mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::BoostBall)) + return; + + if (!x1de4_25_boostEnabled) { CancelBoosting(); - CSfxManager::SfxStop(x1e24_boostSfxHandle); - StopEffects(); -} + LeaveBoosting(); + return; + } -static const u8 skBallInnerGlowColors[9][3] = -{ - {0xc2, 0x7e, 0x10}, - {0x66, 0xc4, 0xff}, - {0x60, 0xff, 0x90}, - {0x33, 0x33, 0xff}, - {0xff, 0x80, 0x80}, - {0x0, 0x9d, 0xb6}, - {0xd3, 0xf1, 0x0}, - {0x60, 0x33, 0xff}, - {0xfb, 0x98, 0x21} -}; - -void CMorphBall::UpdateEffects(float dt, CStateManager& mgr) -{ - zeus::CTransform swooshToWorld = GetSwooshToWorld(); - x19b8_slowBlueTailSwooshGen->SetTranslation(swooshToWorld.rotate({0.1f, 0.f, 0.f}) + swooshToWorld.origin); - x19b8_slowBlueTailSwooshGen->SetOrientation(swooshToWorld.getRotation()); - x19b8_slowBlueTailSwooshGen->DoWarmupUpdate(); - x19bc_slowBlueTailSwooshGen2->SetTranslation(swooshToWorld.rotate({-0.1f, 0.f, 0.f}) + swooshToWorld.origin); - x19bc_slowBlueTailSwooshGen2->SetOrientation(swooshToWorld.getRotation()); - x19bc_slowBlueTailSwooshGen2->DoWarmupUpdate(); - x19c0_slowBlueTailSwoosh2Gen->SetTranslation(swooshToWorld.rotate({0.f, 0.f, 0.65f}) + swooshToWorld.origin); - x19c0_slowBlueTailSwoosh2Gen->SetOrientation(swooshToWorld.getRotation()); - x19c0_slowBlueTailSwoosh2Gen->DoWarmupUpdate(); - x19c4_slowBlueTailSwoosh2Gen2->SetTranslation(swooshToWorld.rotate({0.f, 0.f, -0.65f}) + swooshToWorld.origin); - x19c4_slowBlueTailSwoosh2Gen2->SetOrientation(swooshToWorld.getRotation()); - x19c4_slowBlueTailSwoosh2Gen2->DoWarmupUpdate(); - x19c8_jaggyTrailGen->SetTranslation(swooshToWorld.origin); - x19c8_jaggyTrailGen->SetOrientation(swooshToWorld.getRotation()); - x19c8_jaggyTrailGen->DoWarmupUpdate(); - x19cc_wallSparkGen->Update(dt); - x1bc8_wakeEffectGens[7]->Update(dt); - bool emitRainWake = (x0_player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround && - mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain && - mgr.GetEnvFxManager()->GetRainMagnitude() > 0.f && - mgr.GetEnvFxManager()->IsSplashActive()); - x1bc8_wakeEffectGens[7]->SetParticleEmission(emitRainWake); - float rainGenRate = std::min(mgr.GetEnvFxManager()->GetRainMagnitude() * 2.f * - x0_player.x4fc_flatMoveSpeed / x0_player.GetBallMaxVelocity(), 1.f); - x1bc8_wakeEffectGens[7]->SetGeneratorRate(rainGenRate); - x1bc8_wakeEffectGens[7]->SetTranslation(x0_player.GetTranslation()); - if (emitRainWake) - { - zeus::CTransform rainOrient = zeus::lookAt(x0_player.x50c_moveDir + x0_player.GetTranslation(), - x0_player.GetTranslation()); - x1bc8_wakeEffectGens[7]->SetOrientation(rainOrient); - } - if (x1c0c_wakeEffectIdx != -1) - x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->Update(dt); - if (x1e38_wallSparkFrameCountdown > 0) - { - x1e38_wallSparkFrameCountdown -= 1; - if (x1e38_wallSparkFrameCountdown <= 0) - x19cc_wallSparkGen->SetParticleEmission(false); - } - x19d0_ballInnerGlowGen->SetGlobalTranslation(swooshToWorld.origin); - x19d0_ballInnerGlowGen->Update(dt); - if (x1de8_boostChargeTime == 0.f && x1df4_boostDrainTime == 0.f) - { - x19d8_boostBallGlowGen->SetModulationColor(zeus::CColor::skClear); - } - else - { - x19d8_boostBallGlowGen->SetGlobalTranslation(swooshToWorld.origin); - float t; - if (x1df4_boostDrainTime == 0.f) - t = x1de8_boostChargeTime / g_tweakBall->GetBoostBallMaxChargeTime(); - else - t = 1.f - x1df4_boostDrainTime / g_tweakBall->GetBoostBallDrainTime(); - x19d8_boostBallGlowGen->SetModulationColor( - zeus::CColor::lerp(zeus::CColor::skBlack, zeus::CColor(1.f, 1.f, 0.4f, 1.f), t)); - x19d8_boostBallGlowGen->Update(dt); - } - x19d4_spiderBallMagnetEffectGen->Update(dt); - x1c30_boostOverLightFactor -= 0.03f; - x1c30_boostOverLightFactor = std::max(0.f, x1c30_boostOverLightFactor); - if (x1c30_boostOverLightFactor == 0.f) - { - x1c34_boostLightFactor -= 0.04f; - x1c34_boostLightFactor = std::max(0.f, x1c34_boostLightFactor); - } - if (x1de4_24_inBoost) - { - x1c30_boostOverLightFactor = 1.f; - x1c34_boostLightFactor = 1.f; - } - else - { - x1c34_boostLightFactor = std::max(x1de8_boostChargeTime / g_tweakBall->GetBoostBallMaxChargeTime(), - x1c34_boostLightFactor); - x1c34_boostLightFactor = std::min(x1c34_boostLightFactor, 1.f); - } - UpdateMorphBallTransitionFlash(dt); - UpdateIceBreakEffect(dt); - if (x1c10_ballInnerGlowLight != kInvalidUniqueId) - { - if (TCastToPtr light = mgr.ObjectById(x1c10_ballInnerGlowLight)) - { - light->SetTranslation(swooshToWorld.origin + zeus::CVector3f(0.f, 0.f, GetBallRadius())); - std::experimental::optional lObj; - if (IsMorphBallTransitionFlashValid() && x19dc_morphBallTransitionFlashGen->SystemHasLight()) - lObj.emplace(x19dc_morphBallTransitionFlashGen->GetLight()); - else if (x19d0_ballInnerGlowGen->SystemHasLight()) - lObj.emplace(x19d0_ballInnerGlowGen->GetLight()); - if (lObj) - { - const u8* c = skBallInnerGlowColors[x8_ballGlowColorIdx]; - zeus::CColor color(c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f); - lObj->SetColor(lObj->GetColor() * c); - if (x0_player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphing) - { - float t = 0.f; - if (x0_player.x578_morphDuration != 0.f) - t = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); - lObj->SetColor(zeus::CColor::lerp(lObj->GetColor(), zeus::CColor::skBlack, t)); - } - else if (x0_player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphing) - { - float t = 0.f; - if (x0_player.x578_morphDuration != 0.f) - t = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); - if (t < 0.5f) - lObj->SetColor(zeus::CColor::lerp(zeus::CColor::skBlack, lObj->GetColor(), - std::min(2.f * t, 1.f))); - } - else - { - lObj->SetColor(zeus::CColor::lerp(lObj->GetColor(), zeus::CColor::skWhite, x1c34_boostLightFactor)); - } - light->SetLight(*lObj); - } - } - } - - if (x187c_spiderBallState == ESpiderBallState::Active) - { - AddSpiderBallElectricalEffect(); - AddSpiderBallElectricalEffect(); - AddSpiderBallElectricalEffect(); - AddSpiderBallElectricalEffect(); - AddSpiderBallElectricalEffect(); - x1c38_spiderLightFactor = std::min(x1c38_spiderLightFactor + 0.25f, 1.f); - } - else - { - x1c38_spiderLightFactor = std::max(0.f, x1c38_spiderLightFactor - 0.15f); - } - - UpdateSpiderBallElectricalEffects(); -} - -void CMorphBall::ComputeBoostBallMovement(const CFinalInput& input, CStateManager& mgr, float dt) -{ - if (!IsMovementAllowed() || !mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::BoostBall)) - return; - - if (!x1de4_25_boostEnabled) - { - CancelBoosting(); - LeaveBoosting(); - return; - } - - if (!x1de4_24_inBoost) - { - x1dec_timeNotInBoost += dt; - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) && - x187c_spiderBallState != ESpiderBallState::Active) - { - if (x1e20_ballAnimIdx == 0) - { - CAnimPlaybackParms parms(1, -1, 1.f, true); - x58_ballModel->AnimationData()->SetAnimation(parms, false); - x1e20_ballAnimIdx = 1; - x1e24_boostSfxHandle = CSfxManager::SfxStart(SFXsam_ball_charge_lp, - 1.f, 0.f, true, 0x7f, true, kInvalidAreaId); - } - x1de8_boostChargeTime += dt; - if (x1de8_boostChargeTime > g_tweakBall->GetBoostBallMaxChargeTime()) - x1de8_boostChargeTime = g_tweakBall->GetBoostBallMaxChargeTime(); - } - else - { - if (x1e20_ballAnimIdx == 1) - { - CAnimPlaybackParms parms(0, -1, 1.f, true); - x58_ballModel->AnimationData()->SetAnimation(parms, false); - x1e20_ballAnimIdx = 0; - CSfxManager::RemoveEmitter(x1e24_boostSfxHandle); - if (x1de8_boostChargeTime >= g_tweakBall->GetBoostBallMinChargeTime()) - { - CSfxManager::AddEmitter(SFXsam_ball_boost, x0_player.GetTranslation(), zeus::CVector3f::skZero, - true, false, 0xb4, kInvalidAreaId); - } - } - - if (x1de8_boostChargeTime >= g_tweakBall->GetBoostBallMinChargeTime()) - { - if (GetBallBoostState() == EBallBoostState::BoostAvailable) - { - if (GetIsInHalfPipeMode() || x1df8_27_ballCloseToCollision) - { - EnterBoosting(mgr); - } - else - { - x0_player.ApplyImpulseWR(zeus::CVector3f::skZero, - zeus::CAxisAngle(-x1924_surfaceToWorld.basis[1] * 10000.f)); - CancelBoosting(); - } - } - else if (GetBallBoostState() == EBallBoostState::BoostDisabled) - { - x0_player.SetTransform(zeus::lookAt(x0_player.GetTranslation(), - x0_player.GetTranslation() + GetBallToWorld().basis[1])); - x0_player.ApplyImpulseWR(zeus::CVector3f::skZero, - zeus::CAxisAngle(-x0_player.GetTransform().basis[0] * 10000.f)); - CancelBoosting(); - } - } - else if (x1de8_boostChargeTime > 0.f) - { - CancelBoosting(); - } - } - } - else - { - x1df4_boostDrainTime += dt; - if (x1df4_boostDrainTime > g_tweakBall->GetBoostBallDrainTime()) - LeaveBoosting(); - if (!GetIsInHalfPipeMode() && !x1df8_27_ballCloseToCollision) - { - if (x1df4_boostDrainTime / g_tweakBall->GetBoostBallDrainTime() < 0.3f) - DampLinearAndAngularVelocities(0.5f, 0.01f); - else - LeaveBoosting(); - } - } -} - -void CMorphBall::EnterBoosting(CStateManager& mgr) -{ - x1de4_24_inBoost = true; - float incSpeed = 0.f; - if (x1de8_boostChargeTime <= g_tweakBall->GetBoostBallChargeTimeTable(0)) - incSpeed = g_tweakBall->GetBoostBallIncrementalSpeedTable(0); - else if (x1de8_boostChargeTime <= g_tweakBall->GetBoostBallChargeTimeTable(1)) - incSpeed = g_tweakBall->GetBoostBallIncrementalSpeedTable(1); - else if (x1de8_boostChargeTime <= g_tweakBall->GetBoostBallChargeTimeTable(2)) - incSpeed = g_tweakBall->GetBoostBallIncrementalSpeedTable(2); - - if (GetIsInHalfPipeMode()) - { - float speedMul = x0_player.GetVelocity().magnitude() / 95.f; - if (speedMul > 0.3f) - incSpeed -= (speedMul - 0.3f) * incSpeed; - incSpeed = std::max(0.f, incSpeed); - } - - zeus::CVector3f lookDir = x0_player.x500_lookDir; - float lookMag2d = std::sqrt(lookDir.x() * lookDir.x() + lookDir.y() * lookDir.y()); - float vertLookAngle = zeus::radToDeg(std::atan2(lookDir.z(), lookMag2d)); - if (lookMag2d < 0.001f && x0_player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround) - { - float velMag2d = std::sqrt(x0_player.GetVelocity().x() * x0_player.GetVelocity().x() + - x0_player.GetVelocity().y() * x0_player.GetVelocity().y()); - if (velMag2d < 0.001f && std::fabs(x0_player.GetVelocity().z()) < 2.f) - { - lookDir = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis[1]; - lookMag2d = std::sqrt(lookDir.x() * lookDir.x() + lookDir.y() * lookDir.y()); - vertLookAngle = zeus::radToDeg(std::atan2(lookDir.z(), lookMag2d)); - } - } - - float speedMul = 1.f; - if (vertLookAngle > 40.f) - { - float speedDamp = (vertLookAngle - 40.f) / 50.f; - speedMul = 0.35f * speedDamp + (1.f - speedDamp); - } - - x0_player.ApplyImpulseWR(lookDir * (speedMul * incSpeed * x0_player.GetMass()), zeus::CAxisAngle::sIdentity); - - x1df4_boostDrainTime = 0.f; - x1de8_boostChargeTime = 0.f; - - x0_player.SetTransform(zeus::CTransform(x1924_surfaceToWorld.basis, x0_player.GetTranslation())); - SwitchToTire(); -} - -void CMorphBall::LeaveBoosting() -{ - if (x1de4_24_inBoost) - { - x1dec_timeNotInBoost = 0.f; - x1de8_boostChargeTime = 0.f; - } - x1de4_24_inBoost = false; - x1df4_boostDrainTime = 0.f; -} - -void CMorphBall::CancelBoosting() -{ - x1de8_boostChargeTime = 0.f; - x1df4_boostDrainTime = 0.f; - if (x1e20_ballAnimIdx == 1) - { + if (!x1de4_24_inBoost) { + x1dec_timeNotInBoost += dt; + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) && + x187c_spiderBallState != ESpiderBallState::Active) { + if (x1e20_ballAnimIdx == 0) { + CAnimPlaybackParms parms(1, -1, 1.f, true); + x58_ballModel->AnimationData()->SetAnimation(parms, false); + x1e20_ballAnimIdx = 1; + x1e24_boostSfxHandle = CSfxManager::SfxStart(SFXsam_ball_charge_lp, 1.f, 0.f, true, 0x7f, true, kInvalidAreaId); + } + x1de8_boostChargeTime += dt; + if (x1de8_boostChargeTime > g_tweakBall->GetBoostBallMaxChargeTime()) + x1de8_boostChargeTime = g_tweakBall->GetBoostBallMaxChargeTime(); + } else { + if (x1e20_ballAnimIdx == 1) { CAnimPlaybackParms parms(0, -1, 1.f, true); x58_ballModel->AnimationData()->SetAnimation(parms, false); x1e20_ballAnimIdx = 0; - CSfxManager::SfxStop(x1e24_boostSfxHandle); + CSfxManager::RemoveEmitter(x1e24_boostSfxHandle); + if (x1de8_boostChargeTime >= g_tweakBall->GetBoostBallMinChargeTime()) { + CSfxManager::AddEmitter(SFXsam_ball_boost, x0_player.GetTranslation(), zeus::CVector3f::skZero, true, false, + 0xb4, kInvalidAreaId); + } + } + + if (x1de8_boostChargeTime >= g_tweakBall->GetBoostBallMinChargeTime()) { + if (GetBallBoostState() == EBallBoostState::BoostAvailable) { + if (GetIsInHalfPipeMode() || x1df8_27_ballCloseToCollision) { + EnterBoosting(mgr); + } else { + x0_player.ApplyImpulseWR(zeus::CVector3f::skZero, + zeus::CAxisAngle(-x1924_surfaceToWorld.basis[1] * 10000.f)); + CancelBoosting(); + } + } else if (GetBallBoostState() == EBallBoostState::BoostDisabled) { + x0_player.SetTransform( + zeus::lookAt(x0_player.GetTranslation(), x0_player.GetTranslation() + GetBallToWorld().basis[1])); + x0_player.ApplyImpulseWR(zeus::CVector3f::skZero, + zeus::CAxisAngle(-x0_player.GetTransform().basis[0] * 10000.f)); + CancelBoosting(); + } + } else if (x1de8_boostChargeTime > 0.f) { + CancelBoosting(); + } } + } else { + x1df4_boostDrainTime += dt; + if (x1df4_boostDrainTime > g_tweakBall->GetBoostBallDrainTime()) + LeaveBoosting(); + if (!GetIsInHalfPipeMode() && !x1df8_27_ballCloseToCollision) { + if (x1df4_boostDrainTime / g_tweakBall->GetBoostBallDrainTime() < 0.3f) + DampLinearAndAngularVelocities(0.5f, 0.01f); + else + LeaveBoosting(); + } + } } -bool CMorphBall::UpdateMarbleDynamics(CStateManager& mgr, float dt, const zeus::CVector3f& point) -{ - bool continueForce = false; - float maxAcc = g_tweakBall->GetMaxBallTranslationAcceleration(int(x0_player.GetSurfaceRestraint())); - if (x0_player.GetVelocity().magnitude() < 3.f && x10_boostControlForce.magnitude() > 0.95f * maxAcc) - { - zeus::CVector3f localMomentum = x1924_surfaceToWorld.transposeRotate(x0_player.GetMomentum()); - localMomentum.z() = 0.f; - zeus::CVector3f localControlForce = x1924_surfaceToWorld.transposeRotate(x10_boostControlForce); - localControlForce.z() = 0.f; - if (localMomentum.canBeNormalized() && localControlForce.canBeNormalized()) - if (localMomentum.normalized().dot(localControlForce.normalized()) < -0.9f) - continueForce = true; - } +void CMorphBall::EnterBoosting(CStateManager& mgr) { + x1de4_24_inBoost = true; + float incSpeed = 0.f; + if (x1de8_boostChargeTime <= g_tweakBall->GetBoostBallChargeTimeTable(0)) + incSpeed = g_tweakBall->GetBoostBallIncrementalSpeedTable(0); + else if (x1de8_boostChargeTime <= g_tweakBall->GetBoostBallChargeTimeTable(1)) + incSpeed = g_tweakBall->GetBoostBallIncrementalSpeedTable(1); + else if (x1de8_boostChargeTime <= g_tweakBall->GetBoostBallChargeTimeTable(2)) + incSpeed = g_tweakBall->GetBoostBallIncrementalSpeedTable(2); - if (!continueForce) - { - zeus::CVector3f vel = x0_player.GetVelocity(); - zeus::CVector3f ballToPoint = - point - (x0_player.GetTranslation() + zeus::CVector3f(0.f, 0.f, GetBallRadius())); - zeus::CVector3f addVel = x0_player.GetAngularVelocityWR().getVector().cross(ballToPoint); - zeus::CVector3f velDelta = vel - addVel; - float f28 = x187c_spiderBallState == ESpiderBallState::Active ? -1.f : 0.4f; - float liftSpeed = 0.f; - if (x1cd0_liftSpeedAvg.Size() > 3) - { - liftSpeed = *x1cd0_liftSpeedAvg.GetEntry(0); - liftSpeed = std::min(liftSpeed, *x1cd0_liftSpeedAvg.GetEntry(1)); - liftSpeed = std::min(liftSpeed, *x1cd0_liftSpeedAvg.GetEntry(2)); - } - if (velDelta.magSquared() > 1.f && liftSpeed > f28) - { - if (velDelta.magnitude() > 25.132742f) - velDelta = velDelta.normalized() * M_PIF * 8.f; - zeus::CVector3f newVel = vel + addVel; - if (newVel.canBeNormalized()) - { - float f26 = (x28_tireMode && x187c_spiderBallState != ESpiderBallState::Active) ? 0.25f : 1.f; - zeus::CVector3f f27 = newVel.normalized() * (velDelta.magnitude() * - -g_tweakBall->GetBallSlipFactor(int(x0_player.GetSurfaceRestraint())) * - f26 * 0.5f / GetBallRadius()); - x0_player.ApplyTorqueWR(ballToPoint.normalized().cross(f27)); - } - } - } - else - { - zeus::CVector3f rotAxis = x1924_surfaceToWorld.basis[2].cross(x10_boostControlForce); - if (rotAxis.canBeNormalized()) - SpinToSpeed(25.f / GetBallRadius(), rotAxis.normalized(), 800.f); - } + if (GetIsInHalfPipeMode()) { + float speedMul = x0_player.GetVelocity().magnitude() / 95.f; + if (speedMul > 0.3f) + incSpeed -= (speedMul - 0.3f) * incSpeed; + incSpeed = std::max(0.f, incSpeed); + } - if (x0_player.GetVelocity().magnitude() >= GetMinimumAlignmentSpeed()) - { - zeus::CVector3f axis = x1924_surfaceToWorld.basis[0]; - if (x0_player.GetTransform().basis[0].dot(axis) < 0.f) - axis = -axis; - zeus::CVector3f upVec = x0_player.GetTransform().basis[0].cross(axis); - if (upVec.canBeNormalized()) - { - if (!x28_tireMode) - { - x0_player.SetAngularImpulse( - x0_player.GetAngularImpulse().getVector() + upVec.normalized() * g_tweakBall->GetTireness()); - } - else - { - x0_player.RotateInOneFrameOR( - zeus::CQuaternion::shortestRotationArc(zeus::CVector3f::skRight, - GetBallToWorld().transposeRotate(axis)), dt); - } - } - return upVec.magnitude() < (GetIsInHalfPipeMode() ? 0.2f : 0.05f); + zeus::CVector3f lookDir = x0_player.x500_lookDir; + float lookMag2d = std::sqrt(lookDir.x() * lookDir.x() + lookDir.y() * lookDir.y()); + float vertLookAngle = zeus::radToDeg(std::atan2(lookDir.z(), lookMag2d)); + if (lookMag2d < 0.001f && x0_player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround) { + float velMag2d = std::sqrt(x0_player.GetVelocity().x() * x0_player.GetVelocity().x() + + x0_player.GetVelocity().y() * x0_player.GetVelocity().y()); + if (velMag2d < 0.001f && std::fabs(x0_player.GetVelocity().z()) < 2.f) { + lookDir = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis[1]; + lookMag2d = std::sqrt(lookDir.x() * lookDir.x() + lookDir.y() * lookDir.y()); + vertLookAngle = zeus::radToDeg(std::atan2(lookDir.z(), lookMag2d)); } + } - return false; + float speedMul = 1.f; + if (vertLookAngle > 40.f) { + float speedDamp = (vertLookAngle - 40.f) / 50.f; + speedMul = 0.35f * speedDamp + (1.f - speedDamp); + } + + x0_player.ApplyImpulseWR(lookDir * (speedMul * incSpeed * x0_player.GetMass()), zeus::CAxisAngle::sIdentity); + + x1df4_boostDrainTime = 0.f; + x1de8_boostChargeTime = 0.f; + + x0_player.SetTransform(zeus::CTransform(x1924_surfaceToWorld.basis, x0_player.GetTranslation())); + SwitchToTire(); } -void CMorphBall::ApplyFriction(float f) -{ +void CMorphBall::LeaveBoosting() { + if (x1de4_24_inBoost) { + x1dec_timeNotInBoost = 0.f; + x1de8_boostChargeTime = 0.f; + } + x1de4_24_inBoost = false; + x1df4_boostDrainTime = 0.f; +} + +void CMorphBall::CancelBoosting() { + x1de8_boostChargeTime = 0.f; + x1df4_boostDrainTime = 0.f; + if (x1e20_ballAnimIdx == 1) { + CAnimPlaybackParms parms(0, -1, 1.f, true); + x58_ballModel->AnimationData()->SetAnimation(parms, false); + x1e20_ballAnimIdx = 0; + CSfxManager::SfxStop(x1e24_boostSfxHandle); + } +} + +bool CMorphBall::UpdateMarbleDynamics(CStateManager& mgr, float dt, const zeus::CVector3f& point) { + bool continueForce = false; + float maxAcc = g_tweakBall->GetMaxBallTranslationAcceleration(int(x0_player.GetSurfaceRestraint())); + if (x0_player.GetVelocity().magnitude() < 3.f && x10_boostControlForce.magnitude() > 0.95f * maxAcc) { + zeus::CVector3f localMomentum = x1924_surfaceToWorld.transposeRotate(x0_player.GetMomentum()); + localMomentum.z() = 0.f; + zeus::CVector3f localControlForce = x1924_surfaceToWorld.transposeRotate(x10_boostControlForce); + localControlForce.z() = 0.f; + if (localMomentum.canBeNormalized() && localControlForce.canBeNormalized()) + if (localMomentum.normalized().dot(localControlForce.normalized()) < -0.9f) + continueForce = true; + } + + if (!continueForce) { zeus::CVector3f vel = x0_player.GetVelocity(); - if (f < vel.magnitude()) - vel = vel.normalized() * (vel.magnitude() - f); - else - vel = zeus::CVector3f::skZero; - x0_player.SetVelocityWR(vel); + zeus::CVector3f ballToPoint = point - (x0_player.GetTranslation() + zeus::CVector3f(0.f, 0.f, GetBallRadius())); + zeus::CVector3f addVel = x0_player.GetAngularVelocityWR().getVector().cross(ballToPoint); + zeus::CVector3f velDelta = vel - addVel; + float f28 = x187c_spiderBallState == ESpiderBallState::Active ? -1.f : 0.4f; + float liftSpeed = 0.f; + if (x1cd0_liftSpeedAvg.Size() > 3) { + liftSpeed = *x1cd0_liftSpeedAvg.GetEntry(0); + liftSpeed = std::min(liftSpeed, *x1cd0_liftSpeedAvg.GetEntry(1)); + liftSpeed = std::min(liftSpeed, *x1cd0_liftSpeedAvg.GetEntry(2)); + } + if (velDelta.magSquared() > 1.f && liftSpeed > f28) { + if (velDelta.magnitude() > 25.132742f) + velDelta = velDelta.normalized() * M_PIF * 8.f; + zeus::CVector3f newVel = vel + addVel; + if (newVel.canBeNormalized()) { + float f26 = (x28_tireMode && x187c_spiderBallState != ESpiderBallState::Active) ? 0.25f : 1.f; + zeus::CVector3f f27 = + newVel.normalized() * + (velDelta.magnitude() * -g_tweakBall->GetBallSlipFactor(int(x0_player.GetSurfaceRestraint())) * f26 * 0.5f / + GetBallRadius()); + x0_player.ApplyTorqueWR(ballToPoint.normalized().cross(f27)); + } + } + } else { + zeus::CVector3f rotAxis = x1924_surfaceToWorld.basis[2].cross(x10_boostControlForce); + if (rotAxis.canBeNormalized()) + SpinToSpeed(25.f / GetBallRadius(), rotAxis.normalized(), 800.f); + } + + if (x0_player.GetVelocity().magnitude() >= GetMinimumAlignmentSpeed()) { + zeus::CVector3f axis = x1924_surfaceToWorld.basis[0]; + if (x0_player.GetTransform().basis[0].dot(axis) < 0.f) + axis = -axis; + zeus::CVector3f upVec = x0_player.GetTransform().basis[0].cross(axis); + if (upVec.canBeNormalized()) { + if (!x28_tireMode) { + x0_player.SetAngularImpulse(x0_player.GetAngularImpulse().getVector() + + upVec.normalized() * g_tweakBall->GetTireness()); + } else { + x0_player.RotateInOneFrameOR( + zeus::CQuaternion::shortestRotationArc(zeus::CVector3f::skRight, GetBallToWorld().transposeRotate(axis)), + dt); + } + } + return upVec.magnitude() < (GetIsInHalfPipeMode() ? 0.2f : 0.05f); + } + + return false; } -void CMorphBall::DampLinearAndAngularVelocities(float linDamp, float angDamp) -{ - zeus::CVector3f vel = x0_player.GetVelocity() * (1.f - linDamp); - x0_player.SetVelocityWR(vel); - zeus::CAxisAngle ang = x0_player.GetAngularVelocityWR(); - ang = ang * (1.f - angDamp); - x0_player.SetAngularVelocityWR(ang); +void CMorphBall::ApplyFriction(float f) { + zeus::CVector3f vel = x0_player.GetVelocity(); + if (f < vel.magnitude()) + vel = vel.normalized() * (vel.magnitude() - f); + else + vel = zeus::CVector3f::skZero; + x0_player.SetVelocityWR(vel); } -float CMorphBall::GetMinimumAlignmentSpeed() const -{ - if (x187c_spiderBallState == ESpiderBallState::Active) - return 0.f; - else - return g_tweakBall->GetMinimumAlignmentSpeed(); +void CMorphBall::DampLinearAndAngularVelocities(float linDamp, float angDamp) { + zeus::CVector3f vel = x0_player.GetVelocity() * (1.f - linDamp); + x0_player.SetVelocityWR(vel); + zeus::CAxisAngle ang = x0_player.GetAngularVelocityWR(); + ang = ang * (1.f - angDamp); + x0_player.SetAngularVelocityWR(ang); } -void CMorphBall::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - if (x1c34_boostLightFactor == 1.f) - return; +float CMorphBall::GetMinimumAlignmentSpeed() const { + if (x187c_spiderBallState == ESpiderBallState::Active) + return 0.f; + else + return g_tweakBall->GetMinimumAlignmentSpeed(); +} - x0_player.ActorLights()->SetFindShadowLight(x1e44_damageEffect < 0.25f); - x0_player.ActorLights()->SetShadowDynamicRangeThreshold(0.05f); - x0_player.ActorLights()->SetDirty(); +void CMorphBall::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + if (x1c34_boostLightFactor == 1.f) + return; + x0_player.ActorLights()->SetFindShadowLight(x1e44_damageEffect < 0.25f); + x0_player.ActorLights()->SetShadowDynamicRangeThreshold(0.05f); + x0_player.ActorLights()->SetDirty(); + + CCollidableSphere sphere = x38_collisionSphere; + sphere.SetSphereCenter(zeus::CVector3f::skZero); + zeus::CAABox ballAABB = sphere.CalculateAABox(GetBallToWorld()); + + if (x0_player.GetAreaIdAlways() != kInvalidAreaId) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x0_player.GetAreaIdAlways()); + if (area->IsPostConstructed()) + x0_player.ActorLights()->BuildAreaLightList(mgr, *area, ballAABB); + } + + x0_player.ActorLights()->BuildDynamicLightList(mgr, ballAABB); + if (x0_player.ActorLights()->HasShadowLight()) { CCollidableSphere sphere = x38_collisionSphere; sphere.SetSphereCenter(zeus::CVector3f::skZero); - zeus::CAABox ballAABB = sphere.CalculateAABox(GetBallToWorld()); + x1c14_worldShadow->BuildLightShadowTexture(mgr, x0_player.GetAreaIdAlways(), + x0_player.GetActorLights()->GetShadowLightIndex(), + sphere.CalculateAABox(GetBallToWorld()), false, false); + } else { + x1c14_worldShadow->ResetBlur(); + } - if (x0_player.GetAreaIdAlways() != kInvalidAreaId) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x0_player.GetAreaIdAlways()); - if (area->IsPostConstructed()) - x0_player.ActorLights()->BuildAreaLightList(mgr, *area, ballAABB); - } + zeus::CColor ambColor = x0_player.ActorLights()->GetAmbientColor(); + ambColor.a() = 1.f; + x0_player.ActorLights()->SetAmbientColor(zeus::CColor::lerp(ambColor, zeus::CColor::skWhite, x1c34_boostLightFactor)); + *x1c18_actorLights = *x0_player.GetActorLights(); - x0_player.ActorLights()->BuildDynamicLightList(mgr, ballAABB); - if (x0_player.ActorLights()->HasShadowLight()) - { - CCollidableSphere sphere = x38_collisionSphere; - sphere.SetSphereCenter(zeus::CVector3f::skZero); - x1c14_worldShadow->BuildLightShadowTexture(mgr, x0_player.GetAreaIdAlways(), - x0_player.GetActorLights()->GetShadowLightIndex(), - sphere.CalculateAABox(GetBallToWorld()), false, false); - } - else - { - x1c14_worldShadow->ResetBlur(); - } + ambColor = x0_player.ActorLights()->GetAmbientColor(); + ambColor.a() = 1.f; + x1c18_actorLights->SetAmbientColor( + zeus::CColor::lerp(ambColor, zeus::CColor::skWhite, std::max(x1c38_spiderLightFactor, x1c34_boostLightFactor))); - zeus::CColor ambColor = x0_player.ActorLights()->GetAmbientColor(); - ambColor.a() = 1.f; - x0_player.ActorLights()->SetAmbientColor(zeus::CColor::lerp(ambColor, zeus::CColor::skWhite, - x1c34_boostLightFactor)); - *x1c18_actorLights = *x0_player.GetActorLights(); - - ambColor = x0_player.ActorLights()->GetAmbientColor(); - ambColor.a() = 1.f; - x1c18_actorLights->SetAmbientColor(zeus::CColor::lerp(ambColor, zeus::CColor::skWhite, - std::max(x1c38_spiderLightFactor, x1c34_boostLightFactor))); - - if (CAnimData* animData = x58_ballModel->AnimationData()) - animData->PreRender(); + if (CAnimData* animData = x58_ballModel->AnimationData()) + animData->PreRender(); } -void CMorphBall::PointGenerator(void* ctx, const std::vector>& vn) -{ - reinterpret_cast(ctx)->GeneratePoints(vn); +void CMorphBall::PointGenerator(void* ctx, const std::vector>& vn) { + reinterpret_cast(ctx)->GeneratePoints(vn); } -static const u8 BallSwooshColors[9][3] = -{ - {0xC2, 0x8F, 0x17}, - {0x70, 0xD4, 0xFF}, - {0x6A, 0xFF, 0x8A}, - {0x3D, 0x4D, 0xFF}, - {0xC0, 0x00, 0x00}, - {0x00, 0xBE, 0xDC}, - {0xDF, 0xFF, 0x00}, - {0xC4, 0x9E, 0xFF}, - {0xFF, 0x9A, 0x22}, +static const u8 BallSwooshColors[9][3] = { + {0xC2, 0x8F, 0x17}, {0x70, 0xD4, 0xFF}, {0x6A, 0xFF, 0x8A}, {0x3D, 0x4D, 0xFF}, {0xC0, 0x00, 0x00}, + {0x00, 0xBE, 0xDC}, {0xDF, 0xFF, 0x00}, {0xC4, 0x9E, 0xFF}, {0xFF, 0x9A, 0x22}, }; -static const u8 BallSwooshColorsCharged[9][3] = -{ - {0xFF, 0xE6, 0x00}, - {0xFF, 0xE6, 0x00}, - {0xFF, 0xE6, 0x00}, - {0xFF, 0xE6, 0x00}, - {0xFF, 0x80, 0x20}, - {0xFF, 0xE6, 0x00}, - {0xFF, 0xE6, 0x00}, - {0xFF, 0xE6, 0x00}, - {0xFF, 0xE6, 0x00} -}; +static const u8 BallSwooshColorsCharged[9][3] = {{0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, + {0xFF, 0xE6, 0x00}, {0xFF, 0x80, 0x20}, {0xFF, 0xE6, 0x00}, + {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}}; -static const u8 BallSwooshColorsJaggy[9][3] = -{ - {0xFF, 0xCC, 0x00}, - {0xFF, 0xCC, 0x00}, - {0xFF, 0xCC, 0x00}, - {0xFF, 0xCC, 0x00}, - {0xFF, 0xD5, 0x19}, - {0xFF, 0xCC, 0x00}, - {0xFF, 0xCC, 0x00}, - {0xFF, 0xCC, 0x00}, - {0xFF, 0xCC, 0x00} -}; +static const u8 BallSwooshColorsJaggy[9][3] = {{0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, + {0xFF, 0xCC, 0x00}, {0xFF, 0xD5, 0x19}, {0xFF, 0xCC, 0x00}, + {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}}; -void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) const -{ - zeus::CTransform ballToWorld = GetBallToWorld(); - if (x28_tireMode) - { - ballToWorld = ballToWorld * - zeus::CQuaternion::fromAxisAngle(ballToWorld.transposeRotate(x0_player.x500_lookDir), - x30_ballTiltAngle).toTransform(); +void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) const { + zeus::CTransform ballToWorld = GetBallToWorld(); + if (x28_tireMode) { + ballToWorld = ballToWorld * zeus::CQuaternion::fromAxisAngle(ballToWorld.transposeRotate(x0_player.x500_lookDir), + x30_ballTiltAngle) + .toTransform(); + } + + bool dying = x0_player.x9f4_deathTime > 0.f; + if (dying) { + zeus::CColor modColor(0.f, zeus::clamp(0.f, 1.f - x0_player.x9f4_deathTime / 0.2f * 6.f, 1.f)); + CModelFlags flags(7, u8(x5c_ballModelShader), 1, modColor); + x58_ballModel->Render(mgr, ballToWorld, nullptr, flags); + } + + CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + + if (x1e44_damageEffect > 0.f) + flags = CModelFlags(1, 0, 3, zeus::CColor(1.f, 1.f - x1e44_damageEffect, 1.f - x1e44_damageEffect, 1.f)); + + if (x1c1c_rainSplashGen && x1c1c_rainSplashGen->IsRaining()) + CSkinnedModel::SetPointGeneratorFunc(x1c1c_rainSplashGen.get(), PointGenerator); + + if (x1c34_boostLightFactor != 1.f) { + if (lights->HasShadowLight()) { + x1c14_worldShadow->EnableModelProjectedShadow(ballToWorld, lights->GetShadowLightArrIndex(), 1.f); + flags.m_extendedShader = EExtendedShader::WorldShadow; } + x58_ballModel->Render(mgr, ballToWorld, lights, flags); + x1c14_worldShadow->DisableModelProjectedShadow(); + } else { + // Lights used to be nullptr here, but we keep it due to PC's increased dynamic lighting range + x58_ballModel->Render(mgr, ballToWorld, lights, flags); + } - bool dying = x0_player.x9f4_deathTime > 0.f; - if (dying) - { - zeus::CColor modColor(0.f, zeus::clamp(0.f, 1.f - x0_player.x9f4_deathTime / 0.2f * 6.f, 1.f)); - CModelFlags flags(7, u8(x5c_ballModelShader), 1, modColor); - x58_ballModel->Render(mgr, ballToWorld, nullptr, flags); + if (x1c1c_rainSplashGen && x1c1c_rainSplashGen->IsRaining()) { + CSkinnedModel::ClearPointGeneratorFunc(); + x1c1c_rainSplashGen->Draw(zeus::CTransform::Translate(ballToWorld.origin)); + } + + float speed = x0_player.GetVelocity().magnitude(); + if (x1e44_damageEffect > 0.25f) { + RenderDamageEffects(mgr, ballToWorld); + } else if (x1c30_boostOverLightFactor > 0.f && !dying) { + int count = std::min(int(speed * 0.5f), 5); + for (int i = 0; i < count; ++i) { + zeus::CTransform xf = + zeus::CTransform::Translate(*x1c90_ballPosAvg.GetEntry(i)) * x1c3c_ballOrientAvg.GetEntry(i)->toTransform(); + float alpha = (1.f - i / 5.f) * x1c30_boostOverLightFactor * 0.2f; + if (x68_lowPolyBallModel) { + CModelFlags lpFlags(7, u8(x6c_lowPolyBallModelShader), 1, zeus::CColor(1.f, alpha)); + x68_lowPolyBallModel->Render(mgr, xf, nullptr, lpFlags); + } } + } - CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + const u8* c = BallSwooshColors[x8_ballGlowColorIdx]; + float swooshAlpha = x1c20_tireFactor / x1c24_maxTireFactor; + zeus::CColor color0 = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, swooshAlpha}; + c = BallSwooshColorsCharged[x8_ballGlowColorIdx]; + zeus::CColor color1 = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, swooshAlpha}; + float t = 0.f; + if (x1df4_boostDrainTime > 0.f) + t = zeus::clamp(0.f, (speed - 25.f) / 15.f, 1.f); + zeus::CColor tailColor = zeus::CColor::lerp(color0, color1, t); + x19b8_slowBlueTailSwooshGen->SetModulationColor(tailColor); + x19b8_slowBlueTailSwooshGen->Render(); + x19bc_slowBlueTailSwooshGen2->SetModulationColor(tailColor); + x19bc_slowBlueTailSwooshGen2->Render(); + x19c0_slowBlueTailSwoosh2Gen->SetModulationColor(tailColor); + x19c0_slowBlueTailSwoosh2Gen->Render(); + x19c4_slowBlueTailSwoosh2Gen2->SetModulationColor(tailColor); + x19c4_slowBlueTailSwoosh2Gen2->Render(); - if (x1e44_damageEffect > 0.f) - flags = CModelFlags(1, 0, 3, zeus::CColor(1.f, 1.f - x1e44_damageEffect, 1.f - x1e44_damageEffect, 1.f)); + if (x1df4_boostDrainTime > 0.f && speed > 23.f && swooshAlpha > 0.5f) { + float laggyAlpha = zeus::clamp(0.f, (speed - 23.f) / 17.f, t); + c = BallSwooshColorsJaggy[x8_ballGlowColorIdx]; + zeus::CColor colorJaggy = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, laggyAlpha}; + x19c8_jaggyTrailGen->SetModulationColor(colorJaggy); + x19c8_jaggyTrailGen->Render(); + } - if (x1c1c_rainSplashGen && x1c1c_rainSplashGen->IsRaining()) - CSkinnedModel::SetPointGeneratorFunc(x1c1c_rainSplashGen.get(), PointGenerator); + RenderSpiderBallElectricalEffect(); - if (x1c34_boostLightFactor != 1.f) - { - if (lights->HasShadowLight()) - { - x1c14_worldShadow->EnableModelProjectedShadow(ballToWorld, lights->GetShadowLightArrIndex(), 1.f); - flags.m_extendedShader = EExtendedShader::WorldShadow; - } - x58_ballModel->Render(mgr, ballToWorld, lights, flags); - x1c14_worldShadow->DisableModelProjectedShadow(); + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall) && x60_spiderBallGlassModel) { + float tmp = std::max(x1c38_spiderLightFactor, x1c34_boostLightFactor); + CModelFlags sflags(0, u8(x64_spiderBallGlassModelShader), 3, zeus::CColor::skWhite); + if (tmp != 1.f) { + if (lights->HasShadowLight()) { + x1c14_worldShadow->EnableModelProjectedShadow(ballToWorld, lights->GetShadowLightArrIndex(), 1.f); + sflags.m_extendedShader = EExtendedShader::WorldShadow; + } + x60_spiderBallGlassModel->Render(mgr, ballToWorld, x1c18_actorLights.get(), sflags); + x1c14_worldShadow->DisableModelProjectedShadow(); + } else { + x60_spiderBallGlassModel->Render(mgr, ballToWorld, nullptr, sflags); } - else - { - // Lights used to be nullptr here, but we keep it due to PC's increased dynamic lighting range - x58_ballModel->Render(mgr, ballToWorld, lights, flags); + } + + x19cc_wallSparkGen->Render(); + x1bc8_wakeEffectGens[7]->Render(); + if (x1c0c_wakeEffectIdx != -1) + x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->Render(); + + c = BallGlowColors[x8_ballGlowColorIdx]; + zeus::CColor glowColor = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; + x19d0_ballInnerGlowGen->SetModulationColor(glowColor); + if (x19d0_ballInnerGlowGen->GetNumActiveChildParticles() > 0) { + c = BallTransFlashColors[x8_ballGlowColorIdx]; + glowColor = zeus::CColor{c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; + x19d0_ballInnerGlowGen->GetActiveChildParticle(0).SetModulationColor(glowColor); + if (x19d0_ballInnerGlowGen->GetNumActiveChildParticles() > 1) { + c = BallAuxGlowColors[x8_ballGlowColorIdx]; + glowColor = zeus::CColor{c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; + x19d0_ballInnerGlowGen->GetActiveChildParticle(1).SetModulationColor(glowColor); } + } - if (x1c1c_rainSplashGen && x1c1c_rainSplashGen->IsRaining()) - { - CSkinnedModel::ClearPointGeneratorFunc(); - x1c1c_rainSplashGen->Draw(zeus::CTransform::Translate(ballToWorld.origin)); - } + x19d0_ballInnerGlowGen->Render(); + x19d4_spiderBallMagnetEffectGen->Render(); + RenderEnergyDrainEffects(mgr); + if (x19d8_boostBallGlowGen->GetModulationColor() != zeus::CColor::skClear) + x19d8_boostBallGlowGen->Render(); - float speed = x0_player.GetVelocity().magnitude(); - if (x1e44_damageEffect > 0.25f) - { - RenderDamageEffects(mgr, ballToWorld); - } - else if (x1c30_boostOverLightFactor > 0.f && !dying) - { - int count = std::min(int(speed * 0.5f), 5); - for (int i=0 ; itoTransform(); - float alpha = (1.f - i / 5.f) * x1c30_boostOverLightFactor * 0.2f; - if (x68_lowPolyBallModel) - { - CModelFlags lpFlags(7, u8(x6c_lowPolyBallModelShader), 1, zeus::CColor(1.f, alpha)); - x68_lowPolyBallModel->Render(mgr, xf, nullptr, lpFlags); - } - } - } + RenderMorphBallTransitionFlash(mgr); - const u8* c = BallSwooshColors[x8_ballGlowColorIdx]; - float swooshAlpha = x1c20_tireFactor / x1c24_maxTireFactor; - zeus::CColor color0 = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, swooshAlpha}; - c = BallSwooshColorsCharged[x8_ballGlowColorIdx]; - zeus::CColor color1 = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, swooshAlpha}; - float t = 0.f; - if (x1df4_boostDrainTime > 0.f) - t = zeus::clamp(0.f, (speed - 25.f) / 15.f, 1.f); - zeus::CColor tailColor = zeus::CColor::lerp(color0, color1, t); - x19b8_slowBlueTailSwooshGen->SetModulationColor(tailColor); - x19b8_slowBlueTailSwooshGen->Render(); - x19bc_slowBlueTailSwooshGen2->SetModulationColor(tailColor); - x19bc_slowBlueTailSwooshGen2->Render(); - x19c0_slowBlueTailSwoosh2Gen->SetModulationColor(tailColor); - x19c0_slowBlueTailSwoosh2Gen->Render(); - x19c4_slowBlueTailSwoosh2Gen2->SetModulationColor(tailColor); - x19c4_slowBlueTailSwoosh2Gen2->Render(); + if (x0_player.GetFrozenState()) { + CModelFlags fflags(0, 0, 3, zeus::CColor::skWhite); + x70_frozenBallModel->Render(mgr, zeus::CTransform::Translate(ballToWorld.origin), lights, fflags); + } - if (x1df4_boostDrainTime > 0.f && speed > 23.f && swooshAlpha > 0.5f) - { - float laggyAlpha = zeus::clamp(0.f, (speed - 23.f) / 17.f, t); - c = BallSwooshColorsJaggy[x8_ballGlowColorIdx]; - zeus::CColor colorJaggy = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, laggyAlpha}; - x19c8_jaggyTrailGen->SetModulationColor(colorJaggy); - x19c8_jaggyTrailGen->Render(); - } - - RenderSpiderBallElectricalEffect(); - - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall) && x60_spiderBallGlassModel) - { - float tmp = std::max(x1c38_spiderLightFactor, x1c34_boostLightFactor); - CModelFlags sflags(0, u8(x64_spiderBallGlassModelShader), 3, zeus::CColor::skWhite); - if (tmp != 1.f) - { - if (lights->HasShadowLight()) - { - x1c14_worldShadow->EnableModelProjectedShadow(ballToWorld, lights->GetShadowLightArrIndex(), 1.f); - sflags.m_extendedShader = EExtendedShader::WorldShadow; - } - x60_spiderBallGlassModel->Render(mgr, ballToWorld, x1c18_actorLights.get(), sflags); - x1c14_worldShadow->DisableModelProjectedShadow(); - } - else - { - x60_spiderBallGlassModel->Render(mgr, ballToWorld, nullptr, sflags); - } - } - - x19cc_wallSparkGen->Render(); - x1bc8_wakeEffectGens[7]->Render(); - if (x1c0c_wakeEffectIdx != -1) - x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->Render(); - - c = BallGlowColors[x8_ballGlowColorIdx]; - zeus::CColor glowColor = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; - x19d0_ballInnerGlowGen->SetModulationColor(glowColor); - if (x19d0_ballInnerGlowGen->GetNumActiveChildParticles() > 0) - { - c = BallTransFlashColors[x8_ballGlowColorIdx]; - glowColor = zeus::CColor{c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; - x19d0_ballInnerGlowGen->GetActiveChildParticle(0).SetModulationColor(glowColor); - if (x19d0_ballInnerGlowGen->GetNumActiveChildParticles() > 1) - { - c = BallAuxGlowColors[x8_ballGlowColorIdx]; - glowColor = zeus::CColor{c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; - x19d0_ballInnerGlowGen->GetActiveChildParticle(1).SetModulationColor(glowColor); - } - } - - x19d0_ballInnerGlowGen->Render(); - x19d4_spiderBallMagnetEffectGen->Render(); - RenderEnergyDrainEffects(mgr); - if (x19d8_boostBallGlowGen->GetModulationColor() != zeus::CColor::skClear) - x19d8_boostBallGlowGen->Render(); - - RenderMorphBallTransitionFlash(mgr); - - if (x0_player.GetFrozenState()) - { - CModelFlags fflags(0, 0, 3, zeus::CColor::skWhite); - x70_frozenBallModel->Render(mgr, zeus::CTransform::Translate(ballToWorld.origin), lights, fflags); - } - - RenderIceBreakEffect(mgr); + RenderIceBreakEffect(mgr); } -void CMorphBall::ResetMorphBallTransitionFlash() -{ - x19a8_morphBallTransitionFlash.Lock(); - if (x19dc_morphBallTransitionFlashGen) - x19dc_morphBallTransitionFlashGen.reset(); +void CMorphBall::ResetMorphBallTransitionFlash() { + x19a8_morphBallTransitionFlash.Lock(); + if (x19dc_morphBallTransitionFlashGen) + x19dc_morphBallTransitionFlashGen.reset(); } -void CMorphBall::UpdateMorphBallTransitionFlash(float dt) -{ - if (!x19dc_morphBallTransitionFlashGen && x19a8_morphBallTransitionFlash.IsLoaded()) - { - x19dc_morphBallTransitionFlashGen = std::make_unique(x19a8_morphBallTransitionFlash); - x19dc_morphBallTransitionFlashGen->SetOrientation(x0_player.GetTransform().getRotation()); - } - if (x19dc_morphBallTransitionFlashGen) - { - if (x19dc_morphBallTransitionFlashGen->IsSystemDeletable()) - { - x19dc_morphBallTransitionFlashGen.reset(); - x19a8_morphBallTransitionFlash.Unlock(); - } - else - { - x19dc_morphBallTransitionFlashGen->SetGlobalTranslation(GetBallToWorld().origin); - x19dc_morphBallTransitionFlashGen->Update(dt); - } +void CMorphBall::UpdateMorphBallTransitionFlash(float dt) { + if (!x19dc_morphBallTransitionFlashGen && x19a8_morphBallTransitionFlash.IsLoaded()) { + x19dc_morphBallTransitionFlashGen = std::make_unique(x19a8_morphBallTransitionFlash); + x19dc_morphBallTransitionFlashGen->SetOrientation(x0_player.GetTransform().getRotation()); + } + if (x19dc_morphBallTransitionFlashGen) { + if (x19dc_morphBallTransitionFlashGen->IsSystemDeletable()) { + x19dc_morphBallTransitionFlashGen.reset(); + x19a8_morphBallTransitionFlash.Unlock(); + } else { + x19dc_morphBallTransitionFlashGen->SetGlobalTranslation(GetBallToWorld().origin); + x19dc_morphBallTransitionFlashGen->Update(dt); } + } } -void CMorphBall::RenderMorphBallTransitionFlash(const CStateManager&) const -{ - if (x19dc_morphBallTransitionFlashGen) - { - const u8* c = BallTransFlashColors[x8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; - x19dc_morphBallTransitionFlashGen->SetModulationColor(color); - x19dc_morphBallTransitionFlashGen->Render(); - } +void CMorphBall::RenderMorphBallTransitionFlash(const CStateManager&) const { + if (x19dc_morphBallTransitionFlashGen) { + const u8* c = BallTransFlashColors[x8_ballGlowColorIdx]; + zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; + x19dc_morphBallTransitionFlashGen->SetModulationColor(color); + x19dc_morphBallTransitionFlashGen->Render(); + } } -void CMorphBall::UpdateIceBreakEffect(float dt) -{ - if (!x19e0_effect_morphBallIceBreakGen && x19b0_effect_morphBallIceBreak.IsLoaded()) - { - x19e0_effect_morphBallIceBreakGen = std::make_unique(x19b0_effect_morphBallIceBreak); - x19e0_effect_morphBallIceBreakGen->SetOrientation(x0_player.GetTransform().getRotation()); - } - if (x19e0_effect_morphBallIceBreakGen) - { - if (x19e0_effect_morphBallIceBreakGen->IsSystemDeletable()) - { - x19e0_effect_morphBallIceBreakGen.reset(); - x19b0_effect_morphBallIceBreak.Unlock(); - } - else - { - x19e0_effect_morphBallIceBreakGen->SetGlobalTranslation(GetBallToWorld().origin); - x19e0_effect_morphBallIceBreakGen->Update(dt); - } +void CMorphBall::UpdateIceBreakEffect(float dt) { + if (!x19e0_effect_morphBallIceBreakGen && x19b0_effect_morphBallIceBreak.IsLoaded()) { + x19e0_effect_morphBallIceBreakGen = std::make_unique(x19b0_effect_morphBallIceBreak); + x19e0_effect_morphBallIceBreakGen->SetOrientation(x0_player.GetTransform().getRotation()); + } + if (x19e0_effect_morphBallIceBreakGen) { + if (x19e0_effect_morphBallIceBreakGen->IsSystemDeletable()) { + x19e0_effect_morphBallIceBreakGen.reset(); + x19b0_effect_morphBallIceBreak.Unlock(); + } else { + x19e0_effect_morphBallIceBreakGen->SetGlobalTranslation(GetBallToWorld().origin); + x19e0_effect_morphBallIceBreakGen->Update(dt); } + } } -void CMorphBall::RenderIceBreakEffect(const CStateManager& mgr) const -{ - if (x19e0_effect_morphBallIceBreakGen) - x19e0_effect_morphBallIceBreakGen->Render(); +void CMorphBall::RenderIceBreakEffect(const CStateManager& mgr) const { + if (x19e0_effect_morphBallIceBreakGen) + x19e0_effect_morphBallIceBreakGen->Render(); } -void CMorphBall::RenderDamageEffects(const CStateManager& mgr, const zeus::CTransform& xf) const -{ - CRandom16 rand; - CModelFlags flags(7, 0, 1, zeus::CColor(0.25f * x1e44_damageEffect, 0.1f * x1e44_damageEffect, - 0.1f * x1e44_damageEffect, 1.f)); // No Z update - flags.m_extendedShader = EExtendedShader::SolidColorAdditive; - for (int i=0 ; i<5 ; ++i) - { - rand.Float(); - float translateMag = 0.15f * x1e44_damageEffect * std::sin(30.f * x1e4c_damageTime + rand.Float() * M_PIF); - zeus::CTransform modelXf = +void CMorphBall::RenderDamageEffects(const CStateManager& mgr, const zeus::CTransform& xf) const { + CRandom16 rand; + CModelFlags flags(7, 0, 1, + zeus::CColor(0.25f * x1e44_damageEffect, 0.1f * x1e44_damageEffect, 0.1f * x1e44_damageEffect, + 1.f)); // No Z update + flags.m_extendedShader = EExtendedShader::SolidColorAdditive; + for (int i = 0; i < 5; ++i) { + rand.Float(); + float translateMag = 0.15f * x1e44_damageEffect * std::sin(30.f * x1e4c_damageTime + rand.Float() * M_PIF); + zeus::CTransform modelXf = xf * zeus::CTransform::Translate(translateMag * rand.Float(), translateMag * rand.Float(), translateMag * rand.Float()); - x68_lowPolyBallModel->Render(CModelData::EWhichModel::Normal, modelXf, nullptr, flags); - } + x68_lowPolyBallModel->Render(CModelData::EWhichModel::Normal, modelXf, nullptr, flags); + } } -void CMorphBall::UpdateHalfPipeStatus(CStateManager& mgr, float dt) -{ - x1dfc_touchHalfPipeCooldown -= dt; - x1dfc_touchHalfPipeCooldown = std::max(0.f, x1dfc_touchHalfPipeCooldown); - x1e04_touchHalfPipeRecentCooldown -= dt; - x1e04_touchHalfPipeRecentCooldown = std::max(0.f, x1e04_touchHalfPipeRecentCooldown); - if (x1dfc_touchHalfPipeCooldown > 0.f) - { - float avg = *x1cd0_liftSpeedAvg.GetAverage(); - if (avg > 25.f || (GetIsInHalfPipeMode() && avg > 4.5f)) - { - SetIsInHalfPipeMode(true); - SetIsInHalfPipeModeInAir(!x1df8_27_ballCloseToCollision); - SetTouchedHalfPipeRecently(x1e04_touchHalfPipeRecentCooldown > 0.f); - if (GetIsInHalfPipeModeInAir()) - { - x1e08_prevHalfPipeNormal = zeus::CVector3f::skZero; - x1e14_halfPipeNormal = zeus::CVector3f::skZero; - } - } - else - { - DisableHalfPipeStatus(); - } - } - else - { - DisableHalfPipeStatus(); +void CMorphBall::UpdateHalfPipeStatus(CStateManager& mgr, float dt) { + x1dfc_touchHalfPipeCooldown -= dt; + x1dfc_touchHalfPipeCooldown = std::max(0.f, x1dfc_touchHalfPipeCooldown); + x1e04_touchHalfPipeRecentCooldown -= dt; + x1e04_touchHalfPipeRecentCooldown = std::max(0.f, x1e04_touchHalfPipeRecentCooldown); + if (x1dfc_touchHalfPipeCooldown > 0.f) { + float avg = *x1cd0_liftSpeedAvg.GetAverage(); + if (avg > 25.f || (GetIsInHalfPipeMode() && avg > 4.5f)) { + SetIsInHalfPipeMode(true); + SetIsInHalfPipeModeInAir(!x1df8_27_ballCloseToCollision); + SetTouchedHalfPipeRecently(x1e04_touchHalfPipeRecentCooldown > 0.f); + if (GetIsInHalfPipeModeInAir()) { + x1e08_prevHalfPipeNormal = zeus::CVector3f::skZero; + x1e14_halfPipeNormal = zeus::CVector3f::skZero; + } + } else { + DisableHalfPipeStatus(); } + } else { + DisableHalfPipeStatus(); + } - if (GetIsInHalfPipeMode()) - x0_player.SetCollisionAccuracyModifier(10.f); - else - x0_player.SetCollisionAccuracyModifier(1.f); -} - -void CMorphBall::DisableHalfPipeStatus() -{ - SetIsInHalfPipeMode(false); - SetIsInHalfPipeModeInAir(false); - SetTouchedHalfPipeRecently(false); - x1dfc_touchHalfPipeCooldown = 0.f; - x1e00_disableControlCooldown = 0.f; + if (GetIsInHalfPipeMode()) + x0_player.SetCollisionAccuracyModifier(10.f); + else x0_player.SetCollisionAccuracyModifier(1.f); - x1e08_prevHalfPipeNormal = zeus::CVector3f::skZero; - x1e14_halfPipeNormal = zeus::CVector3f::skZero; } -bool CMorphBall::BallCloseToCollision(const CStateManager& mgr, float dist, const CMaterialFilter& filter) const -{ - CMaterialList playerOrSolid(EMaterialTypes::Player, EMaterialTypes::Solid); - CCollidableSphere sphere(zeus::CSphere(x0_player.GetTranslation() + - zeus::CVector3f(0.f, 0.f, GetBallRadius()), dist), playerOrSolid); - rstl::reserved_vector nearList; - mgr.BuildColliderList(nearList, x0_player, sphere.CalculateLocalAABox()); - if (CGameCollision::DetectStaticCollisionBoolean(mgr, sphere, zeus::CTransform::Identity(), filter)) +void CMorphBall::DisableHalfPipeStatus() { + SetIsInHalfPipeMode(false); + SetIsInHalfPipeModeInAir(false); + SetTouchedHalfPipeRecently(false); + x1dfc_touchHalfPipeCooldown = 0.f; + x1e00_disableControlCooldown = 0.f; + x0_player.SetCollisionAccuracyModifier(1.f); + x1e08_prevHalfPipeNormal = zeus::CVector3f::skZero; + x1e14_halfPipeNormal = zeus::CVector3f::skZero; +} + +bool CMorphBall::BallCloseToCollision(const CStateManager& mgr, float dist, const CMaterialFilter& filter) const { + CMaterialList playerOrSolid(EMaterialTypes::Player, EMaterialTypes::Solid); + CCollidableSphere sphere(zeus::CSphere(x0_player.GetTranslation() + zeus::CVector3f(0.f, 0.f, GetBallRadius()), dist), + playerOrSolid); + rstl::reserved_vector nearList; + mgr.BuildColliderList(nearList, x0_player, sphere.CalculateLocalAABox()); + if (CGameCollision::DetectStaticCollisionBoolean(mgr, sphere, zeus::CTransform::Identity(), filter)) + return true; + for (TUniqueId id : nearList) { + if (TCastToConstPtr act = mgr.GetObjectById(id)) { + if (CCollisionPrimitive::CollideBoolean( + {sphere, filter, zeus::CTransform::Identity()}, + {*act->GetCollisionPrimitive(), CMaterialFilter::skPassEverything, act->GetPrimitiveTransform()})) return true; - for (TUniqueId id : nearList) - { - if (TCastToConstPtr act = mgr.GetObjectById(id)) - { - if (CCollisionPrimitive::CollideBoolean({sphere, filter, zeus::CTransform::Identity()}, - {*act->GetCollisionPrimitive(), CMaterialFilter::skPassEverything, - act->GetPrimitiveTransform()})) - return true; - } } + } + return false; +} + +void CMorphBall::CollidedWith(TUniqueId id, const CCollisionInfoList& list, CStateManager& mgr) { + x74_collisionInfos = list; + CMaterialList allMats; + for (const CCollisionInfo& info : list) + allMats.Add(info.GetMaterialLeft()); + + zeus::CVector3f vel = x0_player.GetVelocity(); + float velMag = vel.magnitude(); + EMaterialTypes wakeMaterial = EMaterialTypes::NoStepLogic; + if (velMag > 7.f && x0_player.GetFluidCounter() == 0) { + bool hitWall = false; + for (const CCollisionInfo& info : list) { + if (!hitWall) { + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Wall)) { + hitWall = true; + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Stone) || + info.GetMaterialLeft().HasMaterial(EMaterialTypes::Metal)) { + x19cc_wallSparkGen->SetTranslation(info.GetPoint()); + x19cc_wallSparkGen->SetParticleEmission(true); + x1e38_wallSparkFrameCountdown = 7; + } + } + } + + if (wakeMaterial == EMaterialTypes::NoStepLogic) { + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Floor)) { + EMaterialTypes tmpMaterial; + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Dirt)) + tmpMaterial = EMaterialTypes::Dirt; + else + tmpMaterial = wakeMaterial; + + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Sand)) + tmpMaterial = EMaterialTypes::Sand; + + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Lava)) + tmpMaterial = EMaterialTypes::Lava; + + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::MudSlow)) + tmpMaterial = EMaterialTypes::MudSlow; + + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Snow)) + tmpMaterial = EMaterialTypes::Snow; + + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Phazon)) + tmpMaterial = EMaterialTypes::Phazon; + + wakeMaterial = tmpMaterial; + if (tmpMaterial != EMaterialTypes::NoStepLogic) { + int mappedIdx = skWakeEffectMap[int(tmpMaterial)]; + if (mappedIdx == 0) // Phazon + { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()); + if (const CScriptAreaAttributes* attribs = area->GetPostConstructed()->x10d8_areaAttributes) + if (attribs->GetPhazonType() == EPhazonType::Orange) + mappedIdx = 1; // Orange Phazon + } + + if (x1c0c_wakeEffectIdx != mappedIdx) { + if (x1c0c_wakeEffectIdx != -1) + x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->SetParticleEmission(false); + x1c0c_wakeEffectIdx = mappedIdx; + } + + x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->SetParticleEmission(true); + x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->SetTranslation(info.GetPoint()); + } + } + } + } + + if (hitWall && !CSfxManager::IsPlaying(x1e28_wallHitSfxHandle)) { + x1e28_wallHitSfxHandle = CSfxManager::AddEmitter(SFXsam_ball_wallhit, x0_player.GetTranslation(), + zeus::CVector3f::skZero, true, false, 0x7f, kInvalidAreaId); + x0_player.ApplySubmergedPitchBend(x1e28_wallHitSfxHandle); + } + } + + if (wakeMaterial == EMaterialTypes::NoStepLogic && x1c0c_wakeEffectIdx != -1) + x1bc8_wakeEffectGens[int(x1c0c_wakeEffectIdx)]->SetParticleEmission(false); + + x1954_isProjectile = false; + + if (allMats.HasMaterial(EMaterialTypes::HalfPipe)) { + x1dfc_touchHalfPipeCooldown = 4.f; + x1e04_touchHalfPipeRecentCooldown = 0.05f; + for (const CCollisionInfo& info : list) { + if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::HalfPipe)) { + if (info.GetNormalLeft().dot(x1e14_halfPipeNormal) < 0.99) { + x1e08_prevHalfPipeNormal = x1e14_halfPipeNormal; + x1e14_halfPipeNormal = info.GetNormalLeft(); + if (zeus::close_enough(x1e08_prevHalfPipeNormal, zeus::CVector3f::skZero, 0.000011920929f)) + x1e08_prevHalfPipeNormal = x1e14_halfPipeNormal; + } + } + } + } + + if (x28_tireMode && allMats.HasMaterial(EMaterialTypes::Floor) && allMats.HasMaterial(EMaterialTypes::Wall)) + SwitchToMarble(); + + if (!GetIsInHalfPipeMode() && x1de4_24_inBoost && velMag > 3.f) { + zeus::CVector3f velNorm = vel.normalized(); + for (const CCollisionInfo& info : list) { + if (!info.GetMaterialLeft().HasMaterial(EMaterialTypes::HalfPipe) && info.GetNormalLeft().dot(velNorm) < -0.4f) { + LeaveBoosting(); + DampLinearAndAngularVelocities(0.4f, 0.01f); + break; + } + } + } + + if (id == kInvalidUniqueId) { + zeus::CVector3f cvel = x0_player.GetVelocity(); + float cvelMag = cvel.magnitude(); + zeus::CVector3f cforce = x1c_controlForce; + if (cforce.magnitude() > 1000.f && cvelMag > 8.f) { + zeus::CVector3f cforceNorm = cforce.normalized(); + zeus::CVector3f cvelNorm = cvel.normalized(); + for (const CCollisionInfo& info : list) { + if (IsClimbable(info) && info.GetNormalLeft().dot(cforceNorm) < -0.4f && + info.GetNormalLeft().dot(cvelNorm) < -0.6f) { + float threeQVel = 0.75f * cvelMag; + float maxSpeed = g_tweakBall->GetBallTranslationMaxSpeed(int(x0_player.GetSurfaceRestraint())); + float f0 = maxSpeed * 0.15f; + float f3 = (threeQVel - f0) < 0.f ? threeQVel : f0; + float f4 = maxSpeed * 0.25f; + f4 = (f3 - f4) < 0.f ? f4 : f3; + zeus::CVector3f newVel = cvel + zeus::CVector3f(0.f, 0.f, f4); + x1dd8_ = newVel; + x0_player.SetVelocityWR(newVel); + x1dc8_failsafeCounter += 1; + break; + } + } + } + } + + if (list.GetCount() > 2 && list.GetItem(0).GetNormalLeft().z() > 0.2f && + std::fabs(x0_player.GetVelocity().dot(list.GetItem(0).GetNormalLeft())) > 2.f) { + float accum = 0.f; + int count = 0; + for (auto it = list.begin() + 1; it != list.end(); ++it) { + const CCollisionInfo& item1 = *it; + for (auto it2 = list.begin() + 1; it2 != list.end(); ++it2) { + const CCollisionInfo& item2 = *it2; + accum += item1.GetNormalLeft().dot(item2.GetNormalLeft()); + count += 1; + } + } + + if (accum / float(count) < 0.5f) + x1dc8_failsafeCounter += 1; + } + + if (list.GetCount() != 0) + SelectMorphBallSounds(list.GetItem(0).GetMaterialLeft()); +} + +bool CMorphBall::IsInFrustum(const zeus::CFrustum& frustum) const { + if (x58_ballModel->IsNull()) return false; -} -void CMorphBall::CollidedWith(TUniqueId id, const CCollisionInfoList& list, CStateManager& mgr) -{ - x74_collisionInfos = list; - CMaterialList allMats; - for (const CCollisionInfo& info : list) - allMats.Add(info.GetMaterialLeft()); + if (x58_ballModel->IsInFrustum(GetBallToWorld(), frustum)) + return true; - zeus::CVector3f vel = x0_player.GetVelocity(); - float velMag = vel.magnitude(); - EMaterialTypes wakeMaterial = EMaterialTypes::NoStepLogic; - if (velMag > 7.f && x0_player.GetFluidCounter() == 0) - { - bool hitWall = false; - for (const CCollisionInfo& info : list) - { - if (!hitWall) - { - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Wall)) - { - hitWall = true; - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Stone) || - info.GetMaterialLeft().HasMaterial(EMaterialTypes::Metal)) - { - x19cc_wallSparkGen->SetTranslation(info.GetPoint()); - x19cc_wallSparkGen->SetParticleEmission(true); - x1e38_wallSparkFrameCountdown = 7; - } - } - } - - if (wakeMaterial == EMaterialTypes::NoStepLogic) - { - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Floor)) - { - EMaterialTypes tmpMaterial; - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Dirt)) - tmpMaterial = EMaterialTypes::Dirt; - else - tmpMaterial = wakeMaterial; - - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Sand)) - tmpMaterial = EMaterialTypes::Sand; - - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Lava)) - tmpMaterial = EMaterialTypes::Lava; - - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::MudSlow)) - tmpMaterial = EMaterialTypes::MudSlow; - - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Snow)) - tmpMaterial = EMaterialTypes::Snow; - - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::Phazon)) - tmpMaterial = EMaterialTypes::Phazon; - - wakeMaterial = tmpMaterial; - if (tmpMaterial != EMaterialTypes::NoStepLogic) - { - int mappedIdx = skWakeEffectMap[int(tmpMaterial)]; - if (mappedIdx == 0) // Phazon - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()); - if (const CScriptAreaAttributes* attribs = - area->GetPostConstructed()->x10d8_areaAttributes) - if (attribs->GetPhazonType() == EPhazonType::Orange) - mappedIdx = 1; // Orange Phazon - } - - if (x1c0c_wakeEffectIdx != mappedIdx) - { - if (x1c0c_wakeEffectIdx != -1) - x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->SetParticleEmission(false); - x1c0c_wakeEffectIdx = mappedIdx; - } - - x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->SetParticleEmission(true); - x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->SetTranslation(info.GetPoint()); - } - } - } - } - - if (hitWall && !CSfxManager::IsPlaying(x1e28_wallHitSfxHandle)) - { - x1e28_wallHitSfxHandle = CSfxManager::AddEmitter(SFXsam_ball_wallhit, x0_player.GetTranslation(), - zeus::CVector3f::skZero, - true, false, 0x7f, kInvalidAreaId); - x0_player.ApplySubmergedPitchBend(x1e28_wallHitSfxHandle); - } - } - - if (wakeMaterial == EMaterialTypes::NoStepLogic && x1c0c_wakeEffectIdx != -1) - x1bc8_wakeEffectGens[int(x1c0c_wakeEffectIdx)]->SetParticleEmission(false); - - x1954_isProjectile = false; - - if (allMats.HasMaterial(EMaterialTypes::HalfPipe)) - { - x1dfc_touchHalfPipeCooldown = 4.f; - x1e04_touchHalfPipeRecentCooldown = 0.05f; - for (const CCollisionInfo& info : list) - { - if (info.GetMaterialLeft().HasMaterial(EMaterialTypes::HalfPipe)) - { - if (info.GetNormalLeft().dot(x1e14_halfPipeNormal) < 0.99) - { - x1e08_prevHalfPipeNormal = x1e14_halfPipeNormal; - x1e14_halfPipeNormal = info.GetNormalLeft(); - if (zeus::close_enough(x1e08_prevHalfPipeNormal, zeus::CVector3f::skZero, 0.000011920929f)) - x1e08_prevHalfPipeNormal = x1e14_halfPipeNormal; - } - } - } - } - - if (x28_tireMode && allMats.HasMaterial(EMaterialTypes::Floor) && allMats.HasMaterial(EMaterialTypes::Wall)) - SwitchToMarble(); - - if (!GetIsInHalfPipeMode() && x1de4_24_inBoost && velMag > 3.f) - { - zeus::CVector3f velNorm = vel.normalized(); - for (const CCollisionInfo& info : list) - { - if (!info.GetMaterialLeft().HasMaterial(EMaterialTypes::HalfPipe) && - info.GetNormalLeft().dot(velNorm) < -0.4f) - { - LeaveBoosting(); - DampLinearAndAngularVelocities(0.4f, 0.01f); - break; - } - } - } - - if (id == kInvalidUniqueId) - { - zeus::CVector3f cvel = x0_player.GetVelocity(); - float cvelMag = cvel.magnitude(); - zeus::CVector3f cforce = x1c_controlForce; - if (cforce.magnitude() > 1000.f && cvelMag > 8.f) - { - zeus::CVector3f cforceNorm = cforce.normalized(); - zeus::CVector3f cvelNorm = cvel.normalized(); - for (const CCollisionInfo& info : list) - { - if (IsClimbable(info) && - info.GetNormalLeft().dot(cforceNorm) < -0.4f && - info.GetNormalLeft().dot(cvelNorm) < -0.6f) - { - float threeQVel = 0.75f * cvelMag; - float maxSpeed = g_tweakBall->GetBallTranslationMaxSpeed(int(x0_player.GetSurfaceRestraint())); - float f0 = maxSpeed * 0.15f; - float f3 = (threeQVel - f0) < 0.f ? threeQVel : f0; - float f4 = maxSpeed * 0.25f; - f4 = (f3 - f4) < 0.f ? f4 : f3; - zeus::CVector3f newVel = cvel + zeus::CVector3f(0.f, 0.f, f4); - x1dd8_ = newVel; - x0_player.SetVelocityWR(newVel); - x1dc8_failsafeCounter += 1; - break; - } - } - } - } - - if (list.GetCount() > 2 && list.GetItem(0).GetNormalLeft().z() > 0.2f && - std::fabs(x0_player.GetVelocity().dot(list.GetItem(0).GetNormalLeft())) > 2.f) - { - float accum = 0.f; - int count = 0; - for (auto it = list.begin() + 1 ; it != list.end() ; ++it) - { - const CCollisionInfo& item1 = *it; - for (auto it2 = list.begin() + 1 ; it2 != list.end() ; ++it2) - { - const CCollisionInfo& item2 = *it2; - accum += item1.GetNormalLeft().dot(item2.GetNormalLeft()); - count += 1; - } - } - - if (accum / float(count) < 0.5f) - x1dc8_failsafeCounter += 1; - } - - if (list.GetCount() != 0) - SelectMorphBallSounds(list.GetItem(0).GetMaterialLeft()); -} - -bool CMorphBall::IsInFrustum(const zeus::CFrustum& frustum) const -{ - if (x58_ballModel->IsNull()) - return false; - - if (x58_ballModel->IsInFrustum(GetBallToWorld(), frustum)) - return true; - - auto swooshBounds = x19b8_slowBlueTailSwooshGen->GetBounds(); - return x19b8_slowBlueTailSwooshGen->GetModulationColor().a() != 0.f && swooshBounds && - frustum.aabbFrustumTest(*swooshBounds); + auto swooshBounds = x19b8_slowBlueTailSwooshGen->GetBounds(); + return x19b8_slowBlueTailSwooshGen->GetModulationColor().a() != 0.f && swooshBounds && + frustum.aabbFrustumTest(*swooshBounds); } void CMorphBall::ComputeLiftForces(const zeus::CVector3f& controlForce, const zeus::CVector3f& velocity, - const CStateManager& mgr) -{ - x1cd0_liftSpeedAvg.AddValue(velocity.magnitude()); - x1d10_liftControlForceAvg.AddValue(controlForce); - zeus::CVector3f avgControlForce = *x1d10_liftControlForceAvg.GetAverage(); - float avgControlForceMag = avgControlForce.magnitude(); - if (avgControlForceMag > 12000.f) - { - float avgLiftSpeed = *x1cd0_liftSpeedAvg.GetAverage(); - if (avgLiftSpeed < 4.f) - { - zeus::CTransform xf = x0_player.GetPrimitiveTransform(); - zeus::CAABox aabb = x0_player.GetCollisionPrimitive()->CalculateAABox(xf); - aabb.min -= zeus::CVector3f(0.1f, 0.1f, -0.05f); - aabb.max += zeus::CVector3f(0.1f, 0.1f, -0.05f); - CCollidableAABox colAABB(aabb, {EMaterialTypes::Solid}); - if (CGameCollision::DetectStaticCollisionBoolean(mgr, colAABB, zeus::CTransform::Identity(), - CMaterialFilter::skPassEverything)) - { - zeus::CVector3f pos = xf.origin + zeus::CVector3f(0.f, 0.f, 1.75f * GetBallRadius()); - zeus::CVector3f dir = avgControlForce * (1.f / avgControlForceMag); - CRayCastResult result = - mgr.RayStaticIntersection(pos, dir, 1.4f, CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); - if (result.IsInvalid()) - { - float mag = 1.f - std::max(0.f, avgLiftSpeed - 3.f); - zeus::CVector3f force(0.f, 0.f, mag * 40000.f); - x0_player.ApplyForceWR(force, zeus::CAxisAngle::sIdentity); - x0_player.ApplyImpulseWR(zeus::CVector3f::skZero, - zeus::CAxisAngle(-x1924_surfaceToWorld.basis[0] * 1000.f * mag)); - } - } + const CStateManager& mgr) { + x1cd0_liftSpeedAvg.AddValue(velocity.magnitude()); + x1d10_liftControlForceAvg.AddValue(controlForce); + zeus::CVector3f avgControlForce = *x1d10_liftControlForceAvg.GetAverage(); + float avgControlForceMag = avgControlForce.magnitude(); + if (avgControlForceMag > 12000.f) { + float avgLiftSpeed = *x1cd0_liftSpeedAvg.GetAverage(); + if (avgLiftSpeed < 4.f) { + zeus::CTransform xf = x0_player.GetPrimitiveTransform(); + zeus::CAABox aabb = x0_player.GetCollisionPrimitive()->CalculateAABox(xf); + aabb.min -= zeus::CVector3f(0.1f, 0.1f, -0.05f); + aabb.max += zeus::CVector3f(0.1f, 0.1f, -0.05f); + CCollidableAABox colAABB(aabb, {EMaterialTypes::Solid}); + if (CGameCollision::DetectStaticCollisionBoolean(mgr, colAABB, zeus::CTransform::Identity(), + CMaterialFilter::skPassEverything)) { + zeus::CVector3f pos = xf.origin + zeus::CVector3f(0.f, 0.f, 1.75f * GetBallRadius()); + zeus::CVector3f dir = avgControlForce * (1.f / avgControlForceMag); + CRayCastResult result = + mgr.RayStaticIntersection(pos, dir, 1.4f, CMaterialFilter::MakeInclude({EMaterialTypes::Solid})); + if (result.IsInvalid()) { + float mag = 1.f - std::max(0.f, avgLiftSpeed - 3.f); + zeus::CVector3f force(0.f, 0.f, mag * 40000.f); + x0_player.ApplyForceWR(force, zeus::CAxisAngle::sIdentity); + x0_player.ApplyImpulseWR(zeus::CVector3f::skZero, + zeus::CAxisAngle(-x1924_surfaceToWorld.basis[0] * 1000.f * mag)); } + } } + } } -float CMorphBall::CalculateSurfaceFriction() const -{ - float friction = g_tweakBall->GetBallTranslationFriction(int(x0_player.GetSurfaceRestraint())); - if (x0_player.GetAttachedActor() != kInvalidUniqueId) - friction *= 2.f; - size_t drainSourceCount = x0_player.GetEnergyDrain().GetEnergyDrainSources().size(); - if (drainSourceCount > 0) - friction *= drainSourceCount * 1.5f; - return friction; +float CMorphBall::CalculateSurfaceFriction() const { + float friction = g_tweakBall->GetBallTranslationFriction(int(x0_player.GetSurfaceRestraint())); + if (x0_player.GetAttachedActor() != kInvalidUniqueId) + friction *= 2.f; + size_t drainSourceCount = x0_player.GetEnergyDrain().GetEnergyDrainSources().size(); + if (drainSourceCount > 0) + friction *= drainSourceCount * 1.5f; + return friction; } -void CMorphBall::ApplyGravity(CStateManager& mgr) -{ - if (x0_player.CheckSubmerged() && !mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) - x0_player.SetMomentumWR(zeus::CVector3f(0.f, 0.f, g_tweakBall->GetBallWaterGravity() * x0_player.GetMass())); - else - x0_player.SetMomentumWR(zeus::CVector3f(0.f, 0.f, g_tweakBall->GetBallGravity() * x0_player.GetMass())); +void CMorphBall::ApplyGravity(CStateManager& mgr) { + if (x0_player.CheckSubmerged() && !mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) + x0_player.SetMomentumWR(zeus::CVector3f(0.f, 0.f, g_tweakBall->GetBallWaterGravity() * x0_player.GetMass())); + else + x0_player.SetMomentumWR(zeus::CVector3f(0.f, 0.f, g_tweakBall->GetBallGravity() * x0_player.GetMass())); } -void CMorphBall::SpinToSpeed(float holdMag, zeus::CVector3f torque, float mag) -{ - x0_player.ApplyTorqueWR(torque * - ((holdMag - x0_player.GetAngularVelocityWR().getVector().magnitude()) * mag)); +void CMorphBall::SpinToSpeed(float holdMag, zeus::CVector3f torque, float mag) { + x0_player.ApplyTorqueWR(torque * ((holdMag - x0_player.GetAngularVelocityWR().getVector().magnitude()) * mag)); } -float CMorphBall::ComputeMaxSpeed() const -{ - if (GetIsInHalfPipeMode()) - return std::min(x0_player.GetVelocity().magnitude() * 1.5f, 95.f); - else - return g_tweakBall->GetBallTranslationMaxSpeed(int(x0_player.GetSurfaceRestraint())); +float CMorphBall::ComputeMaxSpeed() const { + if (GetIsInHalfPipeMode()) + return std::min(x0_player.GetVelocity().magnitude() * 1.5f, 95.f); + else + return g_tweakBall->GetBallTranslationMaxSpeed(int(x0_player.GetSurfaceRestraint())); } -static const CDamageInfo kBallDamage = { CWeaponMode(EWeaponType::BoostBall), 50000.f, 0.f, 0.f }; +static const CDamageInfo kBallDamage = {CWeaponMode(EWeaponType::BoostBall), 50000.f, 0.f, 0.f}; -void CMorphBall::Touch(CActor& actor, CStateManager& mgr) -{ - if (TCastToPtr act = actor) - { - if (x1de4_24_inBoost && - (act->GetVelocity() - x0_player.GetVelocity()).magnitude() > - g_tweakBall->GetBoostBallMinRelativeSpeedForDamage()) - { - mgr.ApplyDamage(x0_player.GetUniqueId(), actor.GetUniqueId(), x0_player.GetUniqueId(), kBallDamage, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::CVector3f::skZero); - } +void CMorphBall::Touch(CActor& actor, CStateManager& mgr) { + if (TCastToPtr act = actor) { + if (x1de4_24_inBoost && (act->GetVelocity() - x0_player.GetVelocity()).magnitude() > + g_tweakBall->GetBoostBallMinRelativeSpeedForDamage()) { + mgr.ApplyDamage(x0_player.GetUniqueId(), actor.GetUniqueId(), x0_player.GetUniqueId(), kBallDamage, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::CVector3f::skZero); } + } } -bool CMorphBall::IsClimbable(const CCollisionInfo& cinfo) const -{ - if (std::fabs(cinfo.GetNormalLeft().z()) < 0.7f) - { - float pointToBall = GetBallToWorld().origin.z() - cinfo.GetPoint().z(); - if (pointToBall > 0.1f && pointToBall < GetBallRadius() - 0.05f) - return true; +bool CMorphBall::IsClimbable(const CCollisionInfo& cinfo) const { + if (std::fabs(cinfo.GetNormalLeft().z()) < 0.7f) { + float pointToBall = GetBallToWorld().origin.z() - cinfo.GetPoint().z(); + if (pointToBall > 0.1f && pointToBall < GetBallRadius() - 0.05f) + return true; + } + return false; +} + +void CMorphBall::FluidFXThink(CActor::EFluidState state, CScriptWater& water, CStateManager& mgr) { + zeus::CVector3f vec = x0_player.GetTranslation(); + vec.z() = float(water.GetTriggerBoundsWR().max.z()); + if (x0_player.x4fc_flatMoveSpeed >= 8.f) { + float maxVel = x0_player.GetBallMaxVelocity(); + if (mgr.GetFluidPlaneManager()->GetLastSplashDeltaTime(x0_player.GetUniqueId()) >= + (maxVel - x0_player.x4fc_flatMoveSpeed) / (maxVel - 8.f) * 0.1f) { + mgr.GetFluidPlaneManager()->CreateSplash(x0_player.GetUniqueId(), mgr, water, vec, 0.f, + state == CActor::EFluidState::EnteredFluid); } - return false; -} - -void CMorphBall::FluidFXThink(CActor::EFluidState state, CScriptWater& water, CStateManager& mgr) -{ - zeus::CVector3f vec = x0_player.GetTranslation(); - vec.z() = float(water.GetTriggerBoundsWR().max.z()); - if (x0_player.x4fc_flatMoveSpeed >= 8.f) - { - float maxVel = x0_player.GetBallMaxVelocity(); - if (mgr.GetFluidPlaneManager()->GetLastSplashDeltaTime(x0_player.GetUniqueId()) >= - (maxVel - x0_player.x4fc_flatMoveSpeed) / (maxVel - 8.f) * 0.1f) - { - mgr.GetFluidPlaneManager()->CreateSplash(x0_player.GetUniqueId(), mgr, water, vec, 0.f, - state == CActor::EFluidState::EnteredFluid); - } + } + if (x0_player.x4fc_flatMoveSpeed >= 0.2f) { + float deltaTime = mgr.GetFluidPlaneManager()->GetLastRippleDeltaTime(x0_player.GetUniqueId()); + float f0; + if (x0_player.x4fc_flatMoveSpeed <= 15.f) { + f0 = 0.13f; + } else { + f0 = std::max(0.1f, 0.13f - 0.03f * (x0_player.x4fc_flatMoveSpeed - 15.f) / + (x0_player.GetBallMaxVelocity() - x0_player.x4fc_flatMoveSpeed)); } - if (x0_player.x4fc_flatMoveSpeed >= 0.2f) - { - float deltaTime = mgr.GetFluidPlaneManager()->GetLastRippleDeltaTime(x0_player.GetUniqueId()); - float f0; - if (x0_player.x4fc_flatMoveSpeed <= 15.f) - { - f0 = 0.13f; - } - else - { - f0 = std::max(0.1f, 0.13f - 0.03f * (x0_player.x4fc_flatMoveSpeed - 15.f) / - (x0_player.GetBallMaxVelocity() - x0_player.x4fc_flatMoveSpeed)); - } - if (deltaTime >= f0) - { - water.GetFluidPlane().AddRipple(0.65f * x0_player.x4fc_flatMoveSpeed / x0_player.GetBallMaxVelocity(), - x0_player.GetUniqueId(), vec, water, mgr); - } + if (deltaTime >= f0) { + water.GetFluidPlane().AddRipple(0.65f * x0_player.x4fc_flatMoveSpeed / x0_player.GetBallMaxVelocity(), + x0_player.GetUniqueId(), vec, water, mgr); } + } } -static const std::pair kBallCharacterTable[] = -{ - {"SamusBallANCS", 0}, - {"SamusBallANCS", 0}, - {"SamusBallANCS", 1}, - {"SamusBallANCS", 0}, - {"SamusFusionBallANCS", 0}, - {"SamusFusionBallANCS", 2}, - {"SamusFusionBallANCS", 1}, - {"SamusFusionBallANCS", 3} -}; +static const std::pair kBallCharacterTable[] = { + {"SamusBallANCS", 0}, {"SamusBallANCS", 0}, {"SamusBallANCS", 1}, {"SamusBallANCS", 0}, + {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}}; -static const std::pair kBallLowPolyTable[] = -{ - {"SamusBallLowPolyCMDL", 0}, - {"SamusBallLowPolyCMDL", 0}, - {"SamusBallLowPolyCMDL", 1}, - {"SamusBallLowPolyCMDL", 0}, - {"SamusBallFusionLowPolyCMDL", 0}, - {"SamusBallFusionLowPolyCMDL", 2}, - {"SamusBallFusionLowPolyCMDL", 1}, - {"SamusBallFusionLowPolyCMDL", 3} -}; +static const std::pair kBallLowPolyTable[] = { + {"SamusBallLowPolyCMDL", 0}, {"SamusBallLowPolyCMDL", 0}, {"SamusBallLowPolyCMDL", 1}, + {"SamusBallLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 2}, + {"SamusBallFusionLowPolyCMDL", 1}, {"SamusBallFusionLowPolyCMDL", 3}}; -static const std::pair kSpiderBallLowPolyTable[] = -{ - {"SamusSpiderBallLowPolyCMDL", 0}, - {"SamusSpiderBallLowPolyCMDL", 0}, - {"SamusSpiderBallLowPolyCMDL", 1}, - {"SamusSpiderBallLowPolyCMDL", 2}, - {"SamusBallFusionLowPolyCMDL", 0}, - {"SamusBallFusionLowPolyCMDL", 2}, - {"SamusBallFusionLowPolyCMDL", 1}, - {"SamusBallFusionLowPolyCMDL", 3} -}; +static const std::pair kSpiderBallLowPolyTable[] = { + {"SamusSpiderBallLowPolyCMDL", 0}, {"SamusSpiderBallLowPolyCMDL", 0}, {"SamusSpiderBallLowPolyCMDL", 1}, + {"SamusSpiderBallLowPolyCMDL", 2}, {"SamusBallFusionLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 2}, + {"SamusBallFusionLowPolyCMDL", 1}, {"SamusBallFusionLowPolyCMDL", 3}}; -static const std::pair kSpiderBallCharacterTable[] = -{ - {"SamusSpiderBallANCS", 0}, - {"SamusSpiderBallANCS", 0}, - {"SamusSpiderBallANCS", 1}, - {"SamusPhazonBallANCS", 0}, - {"SamusFusionBallANCS", 0}, - {"SamusFusionBallANCS", 2}, - {"SamusFusionBallANCS", 1}, - {"SamusFusionBallANCS", 3} -}; +static const std::pair kSpiderBallCharacterTable[] = { + {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 1}, {"SamusPhazonBallANCS", 0}, + {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}}; -static const std::pair kSpiderBallGlassTable[] = -{ - {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 1}, - {"SamusPhazonBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 1}, - {"SamusPhazonBallGlassCMDL", 0} -}; +static const std::pair kSpiderBallGlassTable[] = { + {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 1}, + {"SamusPhazonBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 1}, {"SamusPhazonBallGlassCMDL", 0}}; -static const u32 kSpiderBallGlowColorIdxTable[] = -{ - 3, 3, 2, 4, 5, 7, 6, 8 -}; +static const u32 kSpiderBallGlowColorIdxTable[] = {3, 3, 2, 4, 5, 7, 6, 8}; -static const u32 kBallGlowColorIdxTable[] = -{ - 0, 0, 1, 0, 5, 7, 6, 8 -}; +static const u32 kBallGlowColorIdxTable[] = {0, 0, 1, 0, 5, 7, 6, 8}; -void CMorphBall::LoadMorphBallModel(CStateManager& mgr) -{ - bool spiderBall = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall); +void CMorphBall::LoadMorphBallModel(CStateManager& mgr) { + bool spiderBall = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall); - int modelIdx = int(mgr.GetPlayerState()->GetCurrentSuitRaw()); - if (mgr.GetPlayerState()->IsFusionEnabled()) - modelIdx += 4; + int modelIdx = int(mgr.GetPlayerState()->GetCurrentSuitRaw()); + if (mgr.GetPlayerState()->IsFusionEnabled()) + modelIdx += 4; - int loadModelId = modelIdx; - if (spiderBall) - loadModelId += 4; - if (mgr.GetPlayerState()->IsFusionEnabled()) - loadModelId += 100; + int loadModelId = modelIdx; + if (spiderBall) + loadModelId += 4; + if (mgr.GetPlayerState()->IsFusionEnabled()) + loadModelId += 100; - if (loadModelId != x4_loadedModelId) - { - x4_loadedModelId = loadModelId; - if (spiderBall) - { - x58_ballModel = GetMorphBallModel(kSpiderBallCharacterTable[modelIdx].first, xc_radius); - x5c_ballModelShader = kSpiderBallCharacterTable[modelIdx].second; + if (loadModelId != x4_loadedModelId) { + x4_loadedModelId = loadModelId; + if (spiderBall) { + x58_ballModel = GetMorphBallModel(kSpiderBallCharacterTable[modelIdx].first, xc_radius); + x5c_ballModelShader = kSpiderBallCharacterTable[modelIdx].second; - x68_lowPolyBallModel = GetMorphBallModel(kSpiderBallLowPolyTable[modelIdx].first, xc_radius); - x6c_lowPolyBallModelShader = kSpiderBallLowPolyTable[modelIdx].second; + x68_lowPolyBallModel = GetMorphBallModel(kSpiderBallLowPolyTable[modelIdx].first, xc_radius); + x6c_lowPolyBallModelShader = kSpiderBallLowPolyTable[modelIdx].second; - if (kSpiderBallGlassTable[modelIdx].first) - { - x60_spiderBallGlassModel = GetMorphBallModel(kSpiderBallGlassTable[modelIdx].first, xc_radius); - x64_spiderBallGlassModelShader = kSpiderBallGlassTable[modelIdx].second; - } - else - { - x60_spiderBallGlassModel.reset(); - x64_spiderBallGlassModelShader = 0; - } + if (kSpiderBallGlassTable[modelIdx].first) { + x60_spiderBallGlassModel = GetMorphBallModel(kSpiderBallGlassTable[modelIdx].first, xc_radius); + x64_spiderBallGlassModelShader = kSpiderBallGlassTable[modelIdx].second; + } else { + x60_spiderBallGlassModel.reset(); + x64_spiderBallGlassModelShader = 0; + } - x8_ballGlowColorIdx = kSpiderBallGlowColorIdxTable[modelIdx]; - } - else - { - x58_ballModel = GetMorphBallModel(kBallCharacterTable[modelIdx].first, xc_radius); - x5c_ballModelShader = kBallCharacterTable[modelIdx].second; + x8_ballGlowColorIdx = kSpiderBallGlowColorIdxTable[modelIdx]; + } else { + x58_ballModel = GetMorphBallModel(kBallCharacterTable[modelIdx].first, xc_radius); + x5c_ballModelShader = kBallCharacterTable[modelIdx].second; - x68_lowPolyBallModel = GetMorphBallModel(kBallLowPolyTable[modelIdx].first, xc_radius); - x6c_lowPolyBallModelShader = kBallLowPolyTable[modelIdx].second; + x68_lowPolyBallModel = GetMorphBallModel(kBallLowPolyTable[modelIdx].first, xc_radius); + x6c_lowPolyBallModelShader = kBallLowPolyTable[modelIdx].second; - x8_ballGlowColorIdx = kBallGlowColorIdxTable[modelIdx]; - } - - x58_ballModel->SetScale(zeus::CVector3f(g_tweakPlayer->GetPlayerBallHalfExtent() * 2.f)); - } -} - -void CMorphBall::AddSpiderBallElectricalEffect() -{ - u32 idx = 0; - for (auto& gen : x19e4_spiderElectricGens) - { - if (gen.second) - { - ++idx; - continue; - } - - gen.second = true; - x1b6c_activeSpiderElectricList.emplace_back(idx, x1b80_rand.Range(4, 8)); - - float sign = (x1b80_rand.Next() & 0x100) < 0x80 ? -1.f : 1.f; - float randDir = GetBallRadius() * 0.9f * sign; - float ang0 = zeus::degToRad(40.f - x1b80_rand.Float() * 80.f); - float ang1 = zeus::degToRad(40.f - x1b80_rand.Float() * 80.f + 90.f); - zeus::CVector3f translation(std::sin(ang1) * std::cos(ang0) * sign * 0.6f + randDir * 1.32f, - 0.6f * sign * std::sin(ang0), - 0.6f * sign * std::cos(ang1) * std::cos(ang0)); - zeus::CVector3f transInc = (zeus::CVector3f(randDir, 0.f, 0.f) - translation) * (1.f / 6.f); - gen.first->DoSpiderBallWarmup(translation, transInc); - break; - } -} - -void CMorphBall::UpdateSpiderBallElectricalEffects() -{ - zeus::CTransform ballToWorld = GetBallToWorld(); - zeus::CVector3f ballTranslation = ballToWorld.origin; - ballToWorld.origin = zeus::CVector3f::skZero; - - for (auto it = x1b6c_activeSpiderElectricList.begin() ; it != x1b6c_activeSpiderElectricList.end() ;) - { - CSpiderBallElectricityManager& elec = *it; - if (elec.x8_curFrame >= elec.x4_lifetime) - { - x19e4_spiderElectricGens[elec.x0_effectIdx].second = false; - it = x1b6c_activeSpiderElectricList.erase(it); - continue; - } - - CParticleSwoosh& swoosh = *x19e4_spiderElectricGens[elec.x0_effectIdx].first; - swoosh.SetModulationColor(zeus::CColor(1.f, 1.f - elec.x8_curFrame / elec.x4_lifetime)); - swoosh.SetGlobalTranslation(ballTranslation); - swoosh.SetGlobalOrientation(ballToWorld); - elec.x8_curFrame += 1; - ++it; - } -} - -void CMorphBall::RenderSpiderBallElectricalEffect() const -{ - for (const CSpiderBallElectricityManager& effect : x1b6c_activeSpiderElectricList) - x19e4_spiderElectricGens[effect.x0_effectIdx].first->Render(); -} - -void CMorphBall::RenderEnergyDrainEffects(const CStateManager& mgr) const -{ - for (const CEnergyDrainSource& source : x0_player.x274_energyDrain.GetEnergyDrainSources()) - { - if (const MP1::CMetroidBeta* metroid = - CPatterned::CastTo(mgr.GetObjectById(source.GetEnergyDrainSourceId()))) - { - metroid->RenderHitBallEffect(); - break; - } - } -} - -void CMorphBall::TouchModel(const CStateManager& mgr) const -{ - x58_ballModel->Touch(mgr, x5c_ballModelShader); - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall) && x60_spiderBallGlassModel) - x60_spiderBallGlassModel->Touch(mgr, x64_spiderBallGlassModelShader); - x68_lowPolyBallModel->Touch(mgr, x6c_lowPolyBallModelShader); -} - -void CMorphBall::TakeDamage(float dam) -{ - if (dam <= 0.f) - { - x1e44_damageEffect = 0.f; - x1e48_damageEffectDecaySpeed = 0.f; - return; + x8_ballGlowColorIdx = kBallGlowColorIdxTable[modelIdx]; } - if (dam >= 20.f) - x1e48_damageEffectDecaySpeed = 0.25f; - else if (dam > 5.f) - x1e48_damageEffectDecaySpeed = 1.f - (dam - 5.f) / 15.f * 0.75f; - else - x1e48_damageEffectDecaySpeed = 1.f; - - x1e44_damageEffect = 1.f; + x58_ballModel->SetScale(zeus::CVector3f(g_tweakPlayer->GetPlayerBallHalfExtent() * 2.f)); + } } -void CMorphBall::StartLandingSfx() -{ - if (x0_player.GetVelocity().z() < -5.f && x1e36_landSfx != 0xffff) - { - float vol = zeus::clamp(0.75f, 0.0125f * x0_player.GetLastVelocity().z() + 0.75f, 1.f); - CSfxHandle hnd = CSfxManager::SfxStart(x1e36_landSfx, vol, 0.f, true, 0x7f, false, kInvalidAreaId); - x0_player.ApplySubmergedPitchBend(hnd); +void CMorphBall::AddSpiderBallElectricalEffect() { + u32 idx = 0; + for (auto& gen : x19e4_spiderElectricGens) { + if (gen.second) { + ++idx; + continue; } + + gen.second = true; + x1b6c_activeSpiderElectricList.emplace_back(idx, x1b80_rand.Range(4, 8)); + + float sign = (x1b80_rand.Next() & 0x100) < 0x80 ? -1.f : 1.f; + float randDir = GetBallRadius() * 0.9f * sign; + float ang0 = zeus::degToRad(40.f - x1b80_rand.Float() * 80.f); + float ang1 = zeus::degToRad(40.f - x1b80_rand.Float() * 80.f + 90.f); + zeus::CVector3f translation(std::sin(ang1) * std::cos(ang0) * sign * 0.6f + randDir * 1.32f, + 0.6f * sign * std::sin(ang0), 0.6f * sign * std::cos(ang1) * std::cos(ang0)); + zeus::CVector3f transInc = (zeus::CVector3f(randDir, 0.f, 0.f) - translation) * (1.f / 6.f); + gen.first->DoSpiderBallWarmup(translation, transInc); + break; + } } -void CMorphBall::Stop() -{ - x19b0_effect_morphBallIceBreak.Lock(); - if (x19e0_effect_morphBallIceBreakGen) - x19e0_effect_morphBallIceBreakGen.reset(); -} +void CMorphBall::UpdateSpiderBallElectricalEffects() { + zeus::CTransform ballToWorld = GetBallToWorld(); + zeus::CVector3f ballTranslation = ballToWorld.origin; + ballToWorld.origin = zeus::CVector3f::skZero; -void CMorphBall::StopSounds() -{ - if (x1e2c_rollSfxHandle) - { - CSfxManager::SfxStop(x1e2c_rollSfxHandle); - x1e2c_rollSfxHandle.reset(); + for (auto it = x1b6c_activeSpiderElectricList.begin(); it != x1b6c_activeSpiderElectricList.end();) { + CSpiderBallElectricityManager& elec = *it; + if (elec.x8_curFrame >= elec.x4_lifetime) { + x19e4_spiderElectricGens[elec.x0_effectIdx].second = false; + it = x1b6c_activeSpiderElectricList.erase(it); + continue; } - if (x1e30_spiderSfxHandle) - { - CSfxManager::SfxStop(x1e30_spiderSfxHandle); - x1e30_spiderSfxHandle.reset(); + + CParticleSwoosh& swoosh = *x19e4_spiderElectricGens[elec.x0_effectIdx].first; + swoosh.SetModulationColor(zeus::CColor(1.f, 1.f - elec.x8_curFrame / elec.x4_lifetime)); + swoosh.SetGlobalTranslation(ballTranslation); + swoosh.SetGlobalOrientation(ballToWorld); + elec.x8_curFrame += 1; + ++it; + } +} + +void CMorphBall::RenderSpiderBallElectricalEffect() const { + for (const CSpiderBallElectricityManager& effect : x1b6c_activeSpiderElectricList) + x19e4_spiderElectricGens[effect.x0_effectIdx].first->Render(); +} + +void CMorphBall::RenderEnergyDrainEffects(const CStateManager& mgr) const { + for (const CEnergyDrainSource& source : x0_player.x274_energyDrain.GetEnergyDrainSources()) { + if (const MP1::CMetroidBeta* metroid = + CPatterned::CastTo(mgr.GetObjectById(source.GetEnergyDrainSourceId()))) { + metroid->RenderHitBallEffect(); + break; } + } } -void CMorphBall::StopEffects() -{ - x19cc_wallSparkGen->SetParticleEmission(false); - x1bc8_wakeEffectGens[7]->SetParticleEmission(false); - if (x1c0c_wakeEffectIdx != -1) - x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->SetParticleEmission(false); +void CMorphBall::TouchModel(const CStateManager& mgr) const { + x58_ballModel->Touch(mgr, x5c_ballModelShader); + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall) && x60_spiderBallGlassModel) + x60_spiderBallGlassModel->Touch(mgr, x64_spiderBallGlassModelShader); + x68_lowPolyBallModel->Touch(mgr, x6c_lowPolyBallModelShader); } +void CMorphBall::TakeDamage(float dam) { + if (dam <= 0.f) { + x1e44_damageEffect = 0.f; + x1e48_damageEffectDecaySpeed = 0.f; + return; + } + + if (dam >= 20.f) + x1e48_damageEffectDecaySpeed = 0.25f; + else if (dam > 5.f) + x1e48_damageEffectDecaySpeed = 1.f - (dam - 5.f) / 15.f * 0.75f; + else + x1e48_damageEffectDecaySpeed = 1.f; + + x1e44_damageEffect = 1.f; } + +void CMorphBall::StartLandingSfx() { + if (x0_player.GetVelocity().z() < -5.f && x1e36_landSfx != 0xffff) { + float vol = zeus::clamp(0.75f, 0.0125f * x0_player.GetLastVelocity().z() + 0.75f, 1.f); + CSfxHandle hnd = CSfxManager::SfxStart(x1e36_landSfx, vol, 0.f, true, 0x7f, false, kInvalidAreaId); + x0_player.ApplySubmergedPitchBend(hnd); + } +} + +void CMorphBall::Stop() { + x19b0_effect_morphBallIceBreak.Lock(); + if (x19e0_effect_morphBallIceBreakGen) + x19e0_effect_morphBallIceBreakGen.reset(); +} + +void CMorphBall::StopSounds() { + if (x1e2c_rollSfxHandle) { + CSfxManager::SfxStop(x1e2c_rollSfxHandle); + x1e2c_rollSfxHandle.reset(); + } + if (x1e30_spiderSfxHandle) { + CSfxManager::SfxStop(x1e30_spiderSfxHandle); + x1e30_spiderSfxHandle.reset(); + } +} + +void CMorphBall::StopEffects() { + x19cc_wallSparkGen->SetParticleEmission(false); + x1bc8_wakeEffectGens[7]->SetParticleEmission(false); + if (x1c0c_wakeEffectIdx != -1) + x1bc8_wakeEffectGens[x1c0c_wakeEffectIdx]->SetParticleEmission(false); +} + +} // namespace urde diff --git a/Runtime/World/CMorphBall.hpp b/Runtime/World/CMorphBall.hpp index a3cbf65c9..b3d7d77f6 100644 --- a/Runtime/World/CMorphBall.hpp +++ b/Runtime/World/CMorphBall.hpp @@ -13,8 +13,7 @@ #include "CMorphBallShadow.hpp" #include "Collision/CCollisionInfoList.hpp" -namespace urde -{ +namespace urde { class CActorLights; class CPlayer; class CDamageInfo; @@ -22,284 +21,267 @@ struct CFinalInput; class CScriptWater; class CStateManager; -class CMorphBall -{ +class CMorphBall { public: - enum class EBallBoostState - { - BoostAvailable, - BoostDisabled - }; + enum class EBallBoostState { BoostAvailable, BoostDisabled }; - enum class ESpiderBallState - { - Inactive, - Active - }; + enum class ESpiderBallState { Inactive, Active }; + + enum class EBombJumpState { BombJumpAvailable, BombJumpDisabled }; - enum class EBombJumpState - { - BombJumpAvailable, - BombJumpDisabled - }; private: - struct CSpiderBallElectricityManager - { - u32 x0_effectIdx; - u32 x4_lifetime; - u32 x8_curFrame = 0; - CSpiderBallElectricityManager(u32 effectIdx, u32 lifetime) - : x0_effectIdx(effectIdx), x4_lifetime(lifetime) {} - }; - CPlayer& x0_player; - s32 x4_loadedModelId = -1; - u32 x8_ballGlowColorIdx = 0; - float xc_radius; - zeus::CVector3f x10_boostControlForce; - zeus::CVector3f x1c_controlForce; - bool x28_tireMode = false; - float x2c_tireLeanAngle = 0.f; - float x30_ballTiltAngle = 0.f; - CCollidableSphere x38_collisionSphere; - std::unique_ptr x58_ballModel; - u32 x5c_ballModelShader = 0; - std::unique_ptr x60_spiderBallGlassModel; - u32 x64_spiderBallGlassModelShader = 0; - std::unique_ptr x68_lowPolyBallModel; - u32 x6c_lowPolyBallModelShader = 0; - std::unique_ptr x70_frozenBallModel; - CCollisionInfoList x74_collisionInfos; - u32 xc78_ = 0; - ESpiderBallState x187c_spiderBallState = ESpiderBallState::Inactive; - zeus::CVector3f x1880_playerToSpiderNormal; - float x188c_spiderPullMovement = 1.f; - zeus::CVector3f x1890_spiderTrackPoint; - zeus::CVector3f x189c_spiderInterpBetweenPoints; - zeus::CVector3f x18a8_spiderBetweenPoints; - float x18b4_linVelDamp = 0.f; - float x18b8_angVelDamp = 0.f; - bool x18bc_spiderNearby = false; - bool x18bd_touchingSpider = false; - bool x18be_spiderBallSwinging = false; - bool x18bf_spiderSwingInAir = true; - bool x18c0_isSpiderSurface = false; - zeus::CTransform x18c4_spiderSurfaceTransform; - float x18f4_spiderSurfacePivotAngle = 0.f; - float x18f8_spiderSurfacePivotTargetAngle = 0.f; - float x18fc_refPullVel = 0.f; - float x1900_playerToSpiderTrackDist = 0.f; - float x1904_swingControlDir = 0.f; - float x1908_swingControlTime = 0.f; - zeus::CVector2f x190c_normSpiderSurfaceForces; - float x1914_spiderTrackForceMag = 0.f; - float x1918_spiderViewControlMag = 0.f; - float x191c_damageTimer = 0.f; - bool x1920_spiderForcesReset = false; - zeus::CTransform x1924_surfaceToWorld; - bool x1954_isProjectile = false; - std::vector x1958_animationTokens; - TToken x1968_slowBlueTailSwoosh; - TToken x1970_slowBlueTailSwoosh2; - TToken x1978_jaggyTrail; - TToken x1980_wallSpark; - TToken x1988_ballInnerGlow; - TToken x1990_spiderBallMagnetEffect; - TToken x1998_boostBallGlow; - TToken x19a0_spiderElectric; - TToken x19a8_morphBallTransitionFlash; - TToken x19b0_effect_morphBallIceBreak; - std::unique_ptr x19b8_slowBlueTailSwooshGen; - std::unique_ptr x19bc_slowBlueTailSwooshGen2; - std::unique_ptr x19c0_slowBlueTailSwoosh2Gen; - std::unique_ptr x19c4_slowBlueTailSwoosh2Gen2; - std::unique_ptr x19c8_jaggyTrailGen; - std::unique_ptr x19cc_wallSparkGen; - std::unique_ptr x19d0_ballInnerGlowGen; - std::unique_ptr x19d4_spiderBallMagnetEffectGen; - std::unique_ptr x19d8_boostBallGlowGen; - std::unique_ptr x19dc_morphBallTransitionFlashGen; - std::unique_ptr x19e0_effect_morphBallIceBreakGen; - rstl::reserved_vector, bool>, 32> x19e4_spiderElectricGens; - std::list x1b6c_activeSpiderElectricList; - CRandom16 x1b80_rand = {99}; - rstl::reserved_vector, 8> x1b84_wakeEffects; - rstl::reserved_vector, 8> x1bc8_wakeEffectGens; - s32 x1c0c_wakeEffectIdx = -1; - TUniqueId x1c10_ballInnerGlowLight = kInvalidUniqueId; - std::unique_ptr x1c14_worldShadow; - std::unique_ptr x1c18_actorLights; - std::unique_ptr x1c1c_rainSplashGen; - float x1c20_tireFactor = 0.f; - float x1c24_maxTireFactor = 0.5f; - float x1c28_tireInterpSpeed = 1.f; - bool x1c2c_tireInterpolating = false; - float x1c30_boostOverLightFactor = 0.f; - float x1c34_boostLightFactor = 0.f; - float x1c38_spiderLightFactor = 0.f; - TReservedAverage x1c3c_ballOrientAvg = {{}}; - TReservedAverage x1c90_ballPosAvg = {{}}; - TReservedAverage x1cd0_liftSpeedAvg = {{}}; - TReservedAverage x1d10_liftControlForceAvg = {{}}; - u32 x1dc8_failsafeCounter = 0; - zeus::CVector3f x1dcc_; - zeus::CVector3f x1dd8_; - bool x1de4_24_inBoost : 1; - bool x1de4_25_boostEnabled : 1; - float x1de8_boostChargeTime = 0.f; - float x1dec_timeNotInBoost = 0.f; - float x1df0_ = 0.f; - float x1df4_boostDrainTime = 0.f; - bool x1df8_24_inHalfPipeMode : 1; - bool x1df8_25_inHalfPipeModeInAir : 1; - bool x1df8_26_touchedHalfPipeRecently : 1; - bool x1df8_27_ballCloseToCollision : 1; - float x1dfc_touchHalfPipeCooldown = 0.f; - float x1e00_disableControlCooldown = 0.f; - float x1e04_touchHalfPipeRecentCooldown = 0.f; - zeus::CVector3f x1e08_prevHalfPipeNormal; - zeus::CVector3f x1e14_halfPipeNormal; - u32 x1e20_ballAnimIdx = 0; - CSfxHandle x1e24_boostSfxHandle; - CSfxHandle x1e28_wallHitSfxHandle; - CSfxHandle x1e2c_rollSfxHandle; - CSfxHandle x1e30_spiderSfxHandle; - u16 x1e34_rollSfx = 0xffff; - u16 x1e36_landSfx = 0xffff; - u32 x1e38_wallSparkFrameCountdown = 0; - EBallBoostState x1e3c_boostState = EBallBoostState::BoostAvailable; - EBombJumpState x1e40_bombJumpState = EBombJumpState::BombJumpAvailable; - float x1e44_damageEffect = 0.f; - float x1e48_damageEffectDecaySpeed = 0.f; - float x1e4c_damageTime = 0.f; - std::unique_ptr x1e50_shadow; - void LoadAnimationTokens(std::string_view ancsName); - void InitializeWakeEffects(); - static std::unique_ptr GetMorphBallModel(const char* name, float radius); - void SelectMorphBallSounds(const CMaterialList& mat); - void UpdateMorphBallSounds(float dt); - static zeus::CVector3f TransformSpiderBallForcesXY(const zeus::CVector2f& forces, CStateManager& mgr); - static zeus::CVector3f TransformSpiderBallForcesXZ(const zeus::CVector2f& forces, CStateManager& mgr); - void ResetSpiderBallForces(); - static void PointGenerator(void* ctx, const std::vector>& vn); -public: - CMorphBall(CPlayer& player, float radius); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - const CCollidableSphere& GetCollidableSphere() const { return x38_collisionSphere; } - bool IsProjectile() const { return x1954_isProjectile; } - void GetBallContactMaterials() const {} - void GetWallBumpCounter() const {} - void GetBoostChargeTimer() const {} - bool IsBoosting() const { return false; } - float GetBallRadius() const; - float GetBallTouchRadius() const; - float ForwardInput(const CFinalInput& input) const; - float BallTurnInput(const CFinalInput& input) const; - void ComputeBallMovement(const CFinalInput& input, CStateManager& mgr, float dt); - bool IsMovementAllowed() const; - void UpdateSpiderBall(const CFinalInput& input, CStateManager& mgr, float dt); - void ApplySpiderBallSwingingForces(const CFinalInput& input, CStateManager& mgr, float dt); - void ApplySpiderBallRollForces(const CFinalInput& input, CStateManager& mgr, float dt); - zeus::CVector2f CalculateSpiderBallAttractionSurfaceForces(const CFinalInput& input) const; - bool CheckForSwitchToSpiderBallSwinging(CStateManager& mgr) const; - bool FindClosestSpiderBallWaypoint(CStateManager& mgr, const zeus::CVector3f& ballCenter, - zeus::CVector3f& closestPoint, - zeus::CVector3f& interpDeltaBetweenPoints, - zeus::CVector3f& deltaBetweenPoints, float& distance, - zeus::CVector3f& normal, bool& isSurface, - zeus::CTransform& surfaceTransform) const; - void SetSpiderBallSwingingState(bool active); - float GetSpiderBallControllerMovement(const CFinalInput& input) const; - void ResetSpiderBallSwingControllerMovementTimer(); - void UpdateSpiderBallSwingControllerMovementTimer(float movement, float dt); - float GetSpiderBallSwingControllerMovementScalar() const; - void CreateSpiderBallParticles(const zeus::CVector3f& ballPos, const zeus::CVector3f& trackPoint); - void ComputeMarioMovement(const CFinalInput& input, CStateManager& mgr, float dt); - void SetSpiderBallState(ESpiderBallState state) { x187c_spiderBallState = state; } - zeus::CTransform GetSwooshToWorld() const; - zeus::CTransform GetBallToWorld() const; - zeus::CTransform CalculateSurfaceToWorld(const zeus::CVector3f& trackNormal, - const zeus::CVector3f& trackPoint, - const zeus::CVector3f& ballDir) const; - bool CalculateBallContactInfo(zeus::CVector3f& normal, zeus::CVector3f& point) const; - void UpdateBallDynamics(CStateManager& mgr, float dt); - void SwitchToMarble(); - void SwitchToTire(); - void Update(float dt, CStateManager& mgr); - void DeleteLight(CStateManager& mgr); - void SetBallLightActive(CStateManager& mgr, bool active); - void EnterMorphBallState(CStateManager& mgr); - void LeaveMorphBallState(CStateManager& mgr); - void UpdateEffects(float dt, CStateManager& mgr); - void ComputeBoostBallMovement(const CFinalInput& input, CStateManager& mgr, float dt); - void EnterBoosting(CStateManager& mgr); - void LeaveBoosting(); - void CancelBoosting(); - bool UpdateMarbleDynamics(CStateManager& mgr, float dt, const zeus::CVector3f& point); - void ApplyFriction(float); - void DampLinearAndAngularVelocities(float linDamp, float angDamp); - float GetMinimumAlignmentSpeed() const; - void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); - void Render(const CStateManager& mgr, const CActorLights* lights) const; - void ResetMorphBallTransitionFlash(); - void UpdateMorphBallTransitionFlash(float dt); - void RenderMorphBallTransitionFlash(const CStateManager&) const; - void UpdateIceBreakEffect(float dt); - void RenderIceBreakEffect(const CStateManager& mgr) const; - bool IsMorphBallTransitionFlashValid() const { return x19dc_morphBallTransitionFlashGen != 0; } - void RenderDamageEffects(const CStateManager& mgr, const zeus::CTransform& xf) const; - void UpdateHalfPipeStatus(CStateManager& mgr, float dt); - bool GetIsInHalfPipeMode() const { return x1df8_24_inHalfPipeMode; } - void SetIsInHalfPipeMode(bool b) { x1df8_24_inHalfPipeMode = b; } - bool GetIsInHalfPipeModeInAir() const { return x1df8_25_inHalfPipeModeInAir; } - void SetIsInHalfPipeModeInAir(bool b) { x1df8_25_inHalfPipeModeInAir = b; } - bool GetTouchedHalfPipeRecently() const { return x1df8_26_touchedHalfPipeRecently; } - void SetTouchedHalfPipeRecently(bool b) { x1df8_26_touchedHalfPipeRecently = b; } - void DisableHalfPipeStatus(); - bool BallCloseToCollision(const CStateManager& mgr, float dist, const CMaterialFilter& filter) const; - void CollidedWith(TUniqueId id, const CCollisionInfoList& list, CStateManager& mgr); - bool IsInFrustum(const zeus::CFrustum& frustum) const; - void ComputeLiftForces(const zeus::CVector3f& controlForce, const zeus::CVector3f& velocity, - const CStateManager& mgr); - float CalculateSurfaceFriction() const; - void ApplyGravity(CStateManager& mgr); - void SpinToSpeed(float holdMag, zeus::CVector3f torque, float mag); - float ComputeMaxSpeed() const; - void Touch(CActor& actor, CStateManager& mgr); - bool IsClimbable(const CCollisionInfo& cinfo) const; - void FluidFXThink(CActor::EFluidState state, CScriptWater& water, CStateManager& mgr); - void LoadMorphBallModel(CStateManager& mgr); - void AddSpiderBallElectricalEffect(); - void UpdateSpiderBallElectricalEffects(); - void RenderSpiderBallElectricalEffect() const; - void RenderEnergyDrainEffects(const CStateManager& mgr) const; - void TouchModel(const CStateManager& mgr) const; - void SetAsProjectile() { x1954_isProjectile = true; } - EBallBoostState GetBallBoostState() const { return x1e3c_boostState; } - void SetBallBoostState(EBallBoostState state) { x1e3c_boostState = state; } - EBombJumpState GetBombJumpState() const { return x1e40_bombJumpState; } - void SetBombJumpState(EBombJumpState state) { x1e40_bombJumpState = state; } - void TakeDamage(float dam); - void DrawBallShadow(const CStateManager& mgr); - void DeleteBallShadow(); - void CreateBallShadow(); - void RenderToShadowTex(CStateManager& mgr); - void StartLandingSfx(); - ESpiderBallState GetSpiderBallState() const { return x187c_spiderBallState; } - void SetDamageTimer(float t) { x191c_damageTimer = t; } - void Stop(); - void StopSounds(); - void StopEffects(); - CModelData& GetMorphballModelData() const { return *x58_ballModel; } - u32 GetMorphballModelShader() const { return x5c_ballModelShader; } - bool GetBoostEnabled() const { return x1de4_25_boostEnabled; } - void SetBoostEnabed(bool b) { x1de4_25_boostEnabled = b; } - bool IsInBoost() const { return x1de4_24_inBoost; } - float GetBoostChargeTime() const { return x1de8_boostChargeTime; } + struct CSpiderBallElectricityManager { + u32 x0_effectIdx; + u32 x4_lifetime; + u32 x8_curFrame = 0; + CSpiderBallElectricityManager(u32 effectIdx, u32 lifetime) : x0_effectIdx(effectIdx), x4_lifetime(lifetime) {} + }; + CPlayer& x0_player; + s32 x4_loadedModelId = -1; + u32 x8_ballGlowColorIdx = 0; + float xc_radius; + zeus::CVector3f x10_boostControlForce; + zeus::CVector3f x1c_controlForce; + bool x28_tireMode = false; + float x2c_tireLeanAngle = 0.f; + float x30_ballTiltAngle = 0.f; + CCollidableSphere x38_collisionSphere; + std::unique_ptr x58_ballModel; + u32 x5c_ballModelShader = 0; + std::unique_ptr x60_spiderBallGlassModel; + u32 x64_spiderBallGlassModelShader = 0; + std::unique_ptr x68_lowPolyBallModel; + u32 x6c_lowPolyBallModelShader = 0; + std::unique_ptr x70_frozenBallModel; + CCollisionInfoList x74_collisionInfos; + u32 xc78_ = 0; + ESpiderBallState x187c_spiderBallState = ESpiderBallState::Inactive; + zeus::CVector3f x1880_playerToSpiderNormal; + float x188c_spiderPullMovement = 1.f; + zeus::CVector3f x1890_spiderTrackPoint; + zeus::CVector3f x189c_spiderInterpBetweenPoints; + zeus::CVector3f x18a8_spiderBetweenPoints; + float x18b4_linVelDamp = 0.f; + float x18b8_angVelDamp = 0.f; + bool x18bc_spiderNearby = false; + bool x18bd_touchingSpider = false; + bool x18be_spiderBallSwinging = false; + bool x18bf_spiderSwingInAir = true; + bool x18c0_isSpiderSurface = false; + zeus::CTransform x18c4_spiderSurfaceTransform; + float x18f4_spiderSurfacePivotAngle = 0.f; + float x18f8_spiderSurfacePivotTargetAngle = 0.f; + float x18fc_refPullVel = 0.f; + float x1900_playerToSpiderTrackDist = 0.f; + float x1904_swingControlDir = 0.f; + float x1908_swingControlTime = 0.f; + zeus::CVector2f x190c_normSpiderSurfaceForces; + float x1914_spiderTrackForceMag = 0.f; + float x1918_spiderViewControlMag = 0.f; + float x191c_damageTimer = 0.f; + bool x1920_spiderForcesReset = false; + zeus::CTransform x1924_surfaceToWorld; + bool x1954_isProjectile = false; + std::vector x1958_animationTokens; + TToken x1968_slowBlueTailSwoosh; + TToken x1970_slowBlueTailSwoosh2; + TToken x1978_jaggyTrail; + TToken x1980_wallSpark; + TToken x1988_ballInnerGlow; + TToken x1990_spiderBallMagnetEffect; + TToken x1998_boostBallGlow; + TToken x19a0_spiderElectric; + TToken x19a8_morphBallTransitionFlash; + TToken x19b0_effect_morphBallIceBreak; + std::unique_ptr x19b8_slowBlueTailSwooshGen; + std::unique_ptr x19bc_slowBlueTailSwooshGen2; + std::unique_ptr x19c0_slowBlueTailSwoosh2Gen; + std::unique_ptr x19c4_slowBlueTailSwoosh2Gen2; + std::unique_ptr x19c8_jaggyTrailGen; + std::unique_ptr x19cc_wallSparkGen; + std::unique_ptr x19d0_ballInnerGlowGen; + std::unique_ptr x19d4_spiderBallMagnetEffectGen; + std::unique_ptr x19d8_boostBallGlowGen; + std::unique_ptr x19dc_morphBallTransitionFlashGen; + std::unique_ptr x19e0_effect_morphBallIceBreakGen; + rstl::reserved_vector, bool>, 32> x19e4_spiderElectricGens; + std::list x1b6c_activeSpiderElectricList; + CRandom16 x1b80_rand = {99}; + rstl::reserved_vector, 8> x1b84_wakeEffects; + rstl::reserved_vector, 8> x1bc8_wakeEffectGens; + s32 x1c0c_wakeEffectIdx = -1; + TUniqueId x1c10_ballInnerGlowLight = kInvalidUniqueId; + std::unique_ptr x1c14_worldShadow; + std::unique_ptr x1c18_actorLights; + std::unique_ptr x1c1c_rainSplashGen; + float x1c20_tireFactor = 0.f; + float x1c24_maxTireFactor = 0.5f; + float x1c28_tireInterpSpeed = 1.f; + bool x1c2c_tireInterpolating = false; + float x1c30_boostOverLightFactor = 0.f; + float x1c34_boostLightFactor = 0.f; + float x1c38_spiderLightFactor = 0.f; + TReservedAverage x1c3c_ballOrientAvg = {{}}; + TReservedAverage x1c90_ballPosAvg = {{}}; + TReservedAverage x1cd0_liftSpeedAvg = {{}}; + TReservedAverage x1d10_liftControlForceAvg = {{}}; + u32 x1dc8_failsafeCounter = 0; + zeus::CVector3f x1dcc_; + zeus::CVector3f x1dd8_; + bool x1de4_24_inBoost : 1; + bool x1de4_25_boostEnabled : 1; + float x1de8_boostChargeTime = 0.f; + float x1dec_timeNotInBoost = 0.f; + float x1df0_ = 0.f; + float x1df4_boostDrainTime = 0.f; + bool x1df8_24_inHalfPipeMode : 1; + bool x1df8_25_inHalfPipeModeInAir : 1; + bool x1df8_26_touchedHalfPipeRecently : 1; + bool x1df8_27_ballCloseToCollision : 1; + float x1dfc_touchHalfPipeCooldown = 0.f; + float x1e00_disableControlCooldown = 0.f; + float x1e04_touchHalfPipeRecentCooldown = 0.f; + zeus::CVector3f x1e08_prevHalfPipeNormal; + zeus::CVector3f x1e14_halfPipeNormal; + u32 x1e20_ballAnimIdx = 0; + CSfxHandle x1e24_boostSfxHandle; + CSfxHandle x1e28_wallHitSfxHandle; + CSfxHandle x1e2c_rollSfxHandle; + CSfxHandle x1e30_spiderSfxHandle; + u16 x1e34_rollSfx = 0xffff; + u16 x1e36_landSfx = 0xffff; + u32 x1e38_wallSparkFrameCountdown = 0; + EBallBoostState x1e3c_boostState = EBallBoostState::BoostAvailable; + EBombJumpState x1e40_bombJumpState = EBombJumpState::BombJumpAvailable; + float x1e44_damageEffect = 0.f; + float x1e48_damageEffectDecaySpeed = 0.f; + float x1e4c_damageTime = 0.f; + std::unique_ptr x1e50_shadow; + void LoadAnimationTokens(std::string_view ancsName); + void InitializeWakeEffects(); + static std::unique_ptr GetMorphBallModel(const char* name, float radius); + void SelectMorphBallSounds(const CMaterialList& mat); + void UpdateMorphBallSounds(float dt); + static zeus::CVector3f TransformSpiderBallForcesXY(const zeus::CVector2f& forces, CStateManager& mgr); + static zeus::CVector3f TransformSpiderBallForcesXZ(const zeus::CVector2f& forces, CStateManager& mgr); + void ResetSpiderBallForces(); + static void PointGenerator(void* ctx, const std::vector>& vn); - static const u8 BallGlowColors[9][3]; - static const u8 BallTransFlashColors[9][3]; - static const u8 BallAuxGlowColors[9][3]; +public: + CMorphBall(CPlayer& player, float radius); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + const CCollidableSphere& GetCollidableSphere() const { return x38_collisionSphere; } + bool IsProjectile() const { return x1954_isProjectile; } + void GetBallContactMaterials() const {} + void GetWallBumpCounter() const {} + void GetBoostChargeTimer() const {} + bool IsBoosting() const { return false; } + float GetBallRadius() const; + float GetBallTouchRadius() const; + float ForwardInput(const CFinalInput& input) const; + float BallTurnInput(const CFinalInput& input) const; + void ComputeBallMovement(const CFinalInput& input, CStateManager& mgr, float dt); + bool IsMovementAllowed() const; + void UpdateSpiderBall(const CFinalInput& input, CStateManager& mgr, float dt); + void ApplySpiderBallSwingingForces(const CFinalInput& input, CStateManager& mgr, float dt); + void ApplySpiderBallRollForces(const CFinalInput& input, CStateManager& mgr, float dt); + zeus::CVector2f CalculateSpiderBallAttractionSurfaceForces(const CFinalInput& input) const; + bool CheckForSwitchToSpiderBallSwinging(CStateManager& mgr) const; + bool FindClosestSpiderBallWaypoint(CStateManager& mgr, const zeus::CVector3f& ballCenter, + zeus::CVector3f& closestPoint, zeus::CVector3f& interpDeltaBetweenPoints, + zeus::CVector3f& deltaBetweenPoints, float& distance, zeus::CVector3f& normal, + bool& isSurface, zeus::CTransform& surfaceTransform) const; + void SetSpiderBallSwingingState(bool active); + float GetSpiderBallControllerMovement(const CFinalInput& input) const; + void ResetSpiderBallSwingControllerMovementTimer(); + void UpdateSpiderBallSwingControllerMovementTimer(float movement, float dt); + float GetSpiderBallSwingControllerMovementScalar() const; + void CreateSpiderBallParticles(const zeus::CVector3f& ballPos, const zeus::CVector3f& trackPoint); + void ComputeMarioMovement(const CFinalInput& input, CStateManager& mgr, float dt); + void SetSpiderBallState(ESpiderBallState state) { x187c_spiderBallState = state; } + zeus::CTransform GetSwooshToWorld() const; + zeus::CTransform GetBallToWorld() const; + zeus::CTransform CalculateSurfaceToWorld(const zeus::CVector3f& trackNormal, const zeus::CVector3f& trackPoint, + const zeus::CVector3f& ballDir) const; + bool CalculateBallContactInfo(zeus::CVector3f& normal, zeus::CVector3f& point) const; + void UpdateBallDynamics(CStateManager& mgr, float dt); + void SwitchToMarble(); + void SwitchToTire(); + void Update(float dt, CStateManager& mgr); + void DeleteLight(CStateManager& mgr); + void SetBallLightActive(CStateManager& mgr, bool active); + void EnterMorphBallState(CStateManager& mgr); + void LeaveMorphBallState(CStateManager& mgr); + void UpdateEffects(float dt, CStateManager& mgr); + void ComputeBoostBallMovement(const CFinalInput& input, CStateManager& mgr, float dt); + void EnterBoosting(CStateManager& mgr); + void LeaveBoosting(); + void CancelBoosting(); + bool UpdateMarbleDynamics(CStateManager& mgr, float dt, const zeus::CVector3f& point); + void ApplyFriction(float); + void DampLinearAndAngularVelocities(float linDamp, float angDamp); + float GetMinimumAlignmentSpeed() const; + void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); + void Render(const CStateManager& mgr, const CActorLights* lights) const; + void ResetMorphBallTransitionFlash(); + void UpdateMorphBallTransitionFlash(float dt); + void RenderMorphBallTransitionFlash(const CStateManager&) const; + void UpdateIceBreakEffect(float dt); + void RenderIceBreakEffect(const CStateManager& mgr) const; + bool IsMorphBallTransitionFlashValid() const { return x19dc_morphBallTransitionFlashGen != 0; } + void RenderDamageEffects(const CStateManager& mgr, const zeus::CTransform& xf) const; + void UpdateHalfPipeStatus(CStateManager& mgr, float dt); + bool GetIsInHalfPipeMode() const { return x1df8_24_inHalfPipeMode; } + void SetIsInHalfPipeMode(bool b) { x1df8_24_inHalfPipeMode = b; } + bool GetIsInHalfPipeModeInAir() const { return x1df8_25_inHalfPipeModeInAir; } + void SetIsInHalfPipeModeInAir(bool b) { x1df8_25_inHalfPipeModeInAir = b; } + bool GetTouchedHalfPipeRecently() const { return x1df8_26_touchedHalfPipeRecently; } + void SetTouchedHalfPipeRecently(bool b) { x1df8_26_touchedHalfPipeRecently = b; } + void DisableHalfPipeStatus(); + bool BallCloseToCollision(const CStateManager& mgr, float dist, const CMaterialFilter& filter) const; + void CollidedWith(TUniqueId id, const CCollisionInfoList& list, CStateManager& mgr); + bool IsInFrustum(const zeus::CFrustum& frustum) const; + void ComputeLiftForces(const zeus::CVector3f& controlForce, const zeus::CVector3f& velocity, + const CStateManager& mgr); + float CalculateSurfaceFriction() const; + void ApplyGravity(CStateManager& mgr); + void SpinToSpeed(float holdMag, zeus::CVector3f torque, float mag); + float ComputeMaxSpeed() const; + void Touch(CActor& actor, CStateManager& mgr); + bool IsClimbable(const CCollisionInfo& cinfo) const; + void FluidFXThink(CActor::EFluidState state, CScriptWater& water, CStateManager& mgr); + void LoadMorphBallModel(CStateManager& mgr); + void AddSpiderBallElectricalEffect(); + void UpdateSpiderBallElectricalEffects(); + void RenderSpiderBallElectricalEffect() const; + void RenderEnergyDrainEffects(const CStateManager& mgr) const; + void TouchModel(const CStateManager& mgr) const; + void SetAsProjectile() { x1954_isProjectile = true; } + EBallBoostState GetBallBoostState() const { return x1e3c_boostState; } + void SetBallBoostState(EBallBoostState state) { x1e3c_boostState = state; } + EBombJumpState GetBombJumpState() const { return x1e40_bombJumpState; } + void SetBombJumpState(EBombJumpState state) { x1e40_bombJumpState = state; } + void TakeDamage(float dam); + void DrawBallShadow(const CStateManager& mgr); + void DeleteBallShadow(); + void CreateBallShadow(); + void RenderToShadowTex(CStateManager& mgr); + void StartLandingSfx(); + ESpiderBallState GetSpiderBallState() const { return x187c_spiderBallState; } + void SetDamageTimer(float t) { x191c_damageTimer = t; } + void Stop(); + void StopSounds(); + void StopEffects(); + CModelData& GetMorphballModelData() const { return *x58_ballModel; } + u32 GetMorphballModelShader() const { return x5c_ballModelShader; } + bool GetBoostEnabled() const { return x1de4_25_boostEnabled; } + void SetBoostEnabed(bool b) { x1de4_25_boostEnabled = b; } + bool IsInBoost() const { return x1de4_24_inBoost; } + float GetBoostChargeTime() const { return x1de8_boostChargeTime; } + + static const u8 BallGlowColors[9][3]; + static const u8 BallTransFlashColors[9][3]; + static const u8 BallAuxGlowColors[9][3]; }; -} - +} // namespace urde diff --git a/Runtime/World/CMorphBallShadow.cpp b/Runtime/World/CMorphBallShadow.cpp index dbcb453fc..edfffdf46 100644 --- a/Runtime/World/CMorphBallShadow.cpp +++ b/Runtime/World/CMorphBallShadow.cpp @@ -6,145 +6,134 @@ #include "World/CPlayer.hpp" #include "Particle/CGenDescription.hpp" -namespace urde -{ +namespace urde { -void CMorphBallShadow::GatherAreas(const CStateManager& mgr) -{ - x18_areas.clear(); - for (const CGameArea& area : *mgr.GetWorld()) - { - CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; - if (area.IsPostConstructed()) - occState = area.GetPostConstructed()->x10dc_occlusionState; - if (occState == CGameArea::EOcclusionState::Visible) - x18_areas.push_back(area.GetAreaId()); - } +void CMorphBallShadow::GatherAreas(const CStateManager& mgr) { + x18_areas.clear(); + for (const CGameArea& area : *mgr.GetWorld()) { + CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; + if (area.IsPostConstructed()) + occState = area.GetPostConstructed()->x10dc_occlusionState; + if (occState == CGameArea::EOcclusionState::Visible) + x18_areas.push_back(area.GetAreaId()); + } } -void CMorphBallShadow::RenderIdBuffer(const zeus::CAABox& aabb, const CStateManager& mgr, CPlayer& player) -{ - xb8_shadowVolume = aabb; - x0_actors.clear(); - x18_areas.clear(); - x30_worldModelBits.clear(); - g_Renderer->x318_26_requestRGBA6 = true; +void CMorphBallShadow::RenderIdBuffer(const zeus::CAABox& aabb, const CStateManager& mgr, CPlayer& player) { + xb8_shadowVolume = aabb; + x0_actors.clear(); + x18_areas.clear(); + x30_worldModelBits.clear(); + g_Renderer->x318_26_requestRGBA6 = true; - if (!g_Renderer->x318_27_currentRGBA6) - { - xd0_hasIds = false; - return; - } + if (!g_Renderer->x318_27_currentRGBA6) { + xd0_hasIds = false; + return; + } - GatherAreas(mgr); + GatherAreas(mgr); - SViewport backupVp = g_Viewport; - g_Renderer->BindBallShadowIdTarget(); - CGraphics::g_BooMainCommandQueue->clearTarget(); + SViewport backupVp = g_Viewport; + g_Renderer->BindBallShadowIdTarget(); + CGraphics::g_BooMainCommandQueue->clearTarget(); - zeus::CTransform backupViewMtx = CGraphics::g_ViewMatrix; - CGraphics::CProjectionState backupProjection = CGraphics::g_Proj; - zeus::CVector2f backupDepth = CGraphics::g_CachedDepthRange; - zeus::CTransform viewMtx(zeus::CVector3f::skRight, zeus::CVector3f::skDown, zeus::CVector3f::skForward, - zeus::CVector3f((aabb.min.x() + aabb.max.x()) * 0.5f, - (aabb.min.y() + aabb.max.y()) * 0.5f, - aabb.max.z())); + zeus::CTransform backupViewMtx = CGraphics::g_ViewMatrix; + CGraphics::CProjectionState backupProjection = CGraphics::g_Proj; + zeus::CVector2f backupDepth = CGraphics::g_CachedDepthRange; + zeus::CTransform viewMtx( + zeus::CVector3f::skRight, zeus::CVector3f::skDown, zeus::CVector3f::skForward, + zeus::CVector3f((aabb.min.x() + aabb.max.x()) * 0.5f, (aabb.min.y() + aabb.max.y()) * 0.5f, aabb.max.z())); - CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR); - float vpX = (aabb.max.x() - aabb.min.x()) * 0.5f; - float vpY = (aabb.max.y() - aabb.min.y()) * 0.5f; - float vpZ = (aabb.max.z() - aabb.min.z()) + FLT_EPSILON; - CGraphics::SetOrtho(-vpX, vpX, vpY, -vpY, 0.f, vpZ); + CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR); + float vpX = (aabb.max.x() - aabb.min.x()) * 0.5f; + float vpY = (aabb.max.y() - aabb.min.y()) * 0.5f; + float vpZ = (aabb.max.z() - aabb.min.z()) + FLT_EPSILON; + CGraphics::SetOrtho(-vpX, vpX, vpY, -vpY, 0.f, vpZ); - rstl::reserved_vector nearItems; - mgr.BuildNearList(nearItems, aabb, CMaterialFilter::skPassEverything, &player); + rstl::reserved_vector nearItems; + mgr.BuildNearList(nearItems, aabb, CMaterialFilter::skPassEverything, &player); - CGraphics::SetViewPointMatrix(viewMtx); + CGraphics::SetViewPointMatrix(viewMtx); - int alphaVal = 4; - for (TUniqueId id : nearItems) - { - if (alphaVal > 255) - break; + int alphaVal = 4; + for (TUniqueId id : nearItems) { + if (alphaVal > 255) + break; - const CActor* actor = static_cast(mgr.GetObjectById(id)); - if (!actor || !actor->CanDrawStatic()) - continue; + const CActor* actor = static_cast(mgr.GetObjectById(id)); + if (!actor || !actor->CanDrawStatic()) + continue; - x0_actors.push_back(actor); + x0_actors.push_back(actor); - const CModelData* modelData = actor->GetModelData(); - zeus::CTransform modelXf = actor->GetTransform() * zeus::CTransform::Scale(modelData->GetScale()); - CGraphics::SetModelMatrix(modelXf); + const CModelData* modelData = actor->GetModelData(); + zeus::CTransform modelXf = actor->GetTransform() * zeus::CTransform::Scale(modelData->GetScale()); + CGraphics::SetModelMatrix(modelXf); - CModelFlags flags(0, 0, 3, zeus::CColor{1.f, 1.f, 1.f, alphaVal / 255.f}); - flags.m_extendedShader = EExtendedShader::SolidColor; // Do solid color draw - const CBooModel& model = *modelData->PickStaticModel(CModelData::EWhichModel::Normal); - const_cast(model).VerifyCurrentShader(flags.x1_matSetIdx); - model.DrawNormal(flags, nullptr, nullptr); - alphaVal += 4; - } + CModelFlags flags(0, 0, 3, zeus::CColor{1.f, 1.f, 1.f, alphaVal / 255.f}); + flags.m_extendedShader = EExtendedShader::SolidColor; // Do solid color draw + const CBooModel& model = *modelData->PickStaticModel(CModelData::EWhichModel::Normal); + const_cast(model).VerifyCurrentShader(flags.x1_matSetIdx); + model.DrawNormal(flags, nullptr, nullptr); + alphaVal += 4; + } - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - g_Renderer->FindOverlappingWorldModels(x30_worldModelBits, aabb); - alphaVal = g_Renderer->DrawOverlappingWorldModelIDs(alphaVal, x30_worldModelBits, aabb); + g_Renderer->FindOverlappingWorldModels(x30_worldModelBits, aabb); + alphaVal = g_Renderer->DrawOverlappingWorldModelIDs(alphaVal, x30_worldModelBits, aabb); - g_Renderer->ResolveBallShadowIdTarget(); + g_Renderer->ResolveBallShadowIdTarget(); - g_Renderer->BindMainDrawTarget(); - CGraphics::SetViewPointMatrix(backupViewMtx); - CGraphics::SetProjectionState(backupProjection); - g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height); - CGraphics::SetDepthRange(backupDepth[0], backupDepth[1]); + g_Renderer->BindMainDrawTarget(); + CGraphics::SetViewPointMatrix(backupViewMtx); + CGraphics::SetProjectionState(backupProjection); + g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height); + CGraphics::SetDepthRange(backupDepth[0], backupDepth[1]); - xd0_hasIds = alphaVal != 4; + xd0_hasIds = alphaVal != 4; } -bool CMorphBallShadow::AreasValid(const CStateManager& mgr) const -{ - auto it = x18_areas.begin(); - for (const CGameArea& area : *mgr.GetWorld()) - { - CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; - if (area.IsPostConstructed()) - occState = area.GetPostConstructed()->x10dc_occlusionState; - if (occState != CGameArea::EOcclusionState::Visible) - continue; - if (it == x18_areas.end()) - return false; - if (*it != area.GetAreaId()) - return false; - ++it; - } - return true; +bool CMorphBallShadow::AreasValid(const CStateManager& mgr) const { + auto it = x18_areas.begin(); + for (const CGameArea& area : *mgr.GetWorld()) { + CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; + if (area.IsPostConstructed()) + occState = area.GetPostConstructed()->x10dc_occlusionState; + if (occState != CGameArea::EOcclusionState::Visible) + continue; + if (it == x18_areas.end()) + return false; + if (*it != area.GetAreaId()) + return false; + ++it; + } + return true; } -void CMorphBallShadow::Render(const CStateManager& mgr, float alpha) -{ - if (!xd0_hasIds || !AreasValid(mgr)) - return; +void CMorphBallShadow::Render(const CStateManager& mgr, float alpha) { + if (!xd0_hasIds || !AreasValid(mgr)) + return; - CModelFlags flags; - flags.x4_color.a() = alpha; - flags.m_extendedShader = EExtendedShader::MorphBallShadow; + CModelFlags flags; + flags.x4_color.a() = alpha; + flags.m_extendedShader = EExtendedShader::MorphBallShadow; - int alphaVal = 4; - for (const CActor* actor : x0_actors) - { - const CModelData* modelData = actor->GetModelData(); - zeus::CTransform modelXf = actor->GetTransform() * zeus::CTransform::Scale(modelData->GetScale()); - CGraphics::SetModelMatrix(modelXf); + int alphaVal = 4; + for (const CActor* actor : x0_actors) { + const CModelData* modelData = actor->GetModelData(); + zeus::CTransform modelXf = actor->GetTransform() * zeus::CTransform::Scale(modelData->GetScale()); + CGraphics::SetModelMatrix(modelXf); - flags.x4_color.r() = alphaVal / 255.f; - const CBooModel& model = *modelData->PickStaticModel(CModelData::EWhichModel::Normal); - const_cast(model).VerifyCurrentShader(flags.x1_matSetIdx); - model.DrawNormal(flags, nullptr, nullptr); - alphaVal += 4; - } + flags.x4_color.r() = alphaVal / 255.f; + const CBooModel& model = *modelData->PickStaticModel(CModelData::EWhichModel::Normal); + const_cast(model).VerifyCurrentShader(flags.x1_matSetIdx); + model.DrawNormal(flags, nullptr, nullptr); + alphaVal += 4; + } - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - g_Renderer->DrawOverlappingWorldModelShadows(alphaVal, x30_worldModelBits, xb8_shadowVolume, alpha); + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + g_Renderer->DrawOverlappingWorldModelShadows(alphaVal, x30_worldModelBits, xb8_shadowVolume, alpha); } -} +} // namespace urde diff --git a/Runtime/World/CMorphBallShadow.hpp b/Runtime/World/CMorphBallShadow.hpp index 11c024bec..405873def 100644 --- a/Runtime/World/CMorphBallShadow.hpp +++ b/Runtime/World/CMorphBallShadow.hpp @@ -4,30 +4,28 @@ #include "Graphics/CTexture.hpp" #include "zeus/CAABox.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CPlayer; class CGameArea; class CActor; -class CMorphBallShadow -{ - std::list x0_actors; - std::list x18_areas; - std::vector x30_worldModelBits; - //CTexture x40_; - //TToken xa8_ballFade; - //int xb0_idW; - //int xb4_idH; - zeus::CAABox xb8_shadowVolume; - bool xd0_hasIds = false; - void GatherAreas(const CStateManager& mgr); - bool AreasValid(const CStateManager& mgr) const; +class CMorphBallShadow { + std::list x0_actors; + std::list x18_areas; + std::vector x30_worldModelBits; + // CTexture x40_; + // TToken xa8_ballFade; + // int xb0_idW; + // int xb4_idH; + zeus::CAABox xb8_shadowVolume; + bool xd0_hasIds = false; + void GatherAreas(const CStateManager& mgr); + bool AreasValid(const CStateManager& mgr) const; + public: - void RenderIdBuffer(const zeus::CAABox& aabb, const CStateManager& mgr, CPlayer& player); - void Render(const CStateManager& mgr, float alpha); + void RenderIdBuffer(const zeus::CAABox& aabb, const CStateManager& mgr, CPlayer& player); + void Render(const CStateManager& mgr, float alpha); }; -} - +} // namespace urde diff --git a/Runtime/World/CPathFindArea.cpp b/Runtime/World/CPathFindArea.cpp index a2153a113..9817e491f 100644 --- a/Runtime/World/CPathFindArea.cpp +++ b/Runtime/World/CPathFindArea.cpp @@ -2,309 +2,265 @@ #include "IVParamObj.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("CPathFindArea"); -CPFAreaOctree::CPFAreaOctree(CMemoryInStream& in) -{ - x0_isLeaf = in.readUint32Big(); - x4_aabb.readBoundingBoxBig(in); - x1c_center.readBig(in); - for (int i=0 ; i<8 ; ++i) - x28_children[i] = reinterpret_cast(in.readUint32Big()); - x48_regions.set_size(in.readUint32Big()); - x48_regions.set_data(reinterpret_cast(in.readUint32Big())); +CPFAreaOctree::CPFAreaOctree(CMemoryInStream& in) { + x0_isLeaf = in.readUint32Big(); + x4_aabb.readBoundingBoxBig(in); + x1c_center.readBig(in); + for (int i = 0; i < 8; ++i) + x28_children[i] = reinterpret_cast(in.readUint32Big()); + x48_regions.set_size(in.readUint32Big()); + x48_regions.set_data(reinterpret_cast(in.readUint32Big())); } -void CPFAreaOctree::Fixup(CPFArea& area) -{ - x0_isLeaf = x0_isLeaf != 0 ? 1 : 0; - if (x0_isLeaf) - { - if (x48_regions.empty()) - return; - x48_regions.set_data(&area.x160_octreeRegionLookup[reinterpret_cast(x48_regions.data())]); - return; - } +void CPFAreaOctree::Fixup(CPFArea& area) { + x0_isLeaf = x0_isLeaf != 0 ? 1 : 0; + if (x0_isLeaf) { + if (x48_regions.empty()) + return; + x48_regions.set_data(&area.x160_octreeRegionLookup[reinterpret_cast(x48_regions.data())]); + return; + } - for (int i=0 ; i<8 ; ++i) - { - if ((reinterpret_cast(x28_children[i]) & 0x80000000) == 0) - x28_children[i] = &area.x158_octree[reinterpret_cast(x28_children[i])]; - else - x28_children[i] = nullptr; - } + for (int i = 0; i < 8; ++i) { + if ((reinterpret_cast(x28_children[i]) & 0x80000000) == 0) + x28_children[i] = &area.x158_octree[reinterpret_cast(x28_children[i])]; + else + x28_children[i] = nullptr; + } } -int CPFAreaOctree::GetChildIndex(const zeus::CVector3f& point) const -{ - int idx = 0x0; - if (point.x() > x1c_center.x()) - idx = 0x1; - if (point.y() > x1c_center.y()) - idx |= 0x2; - if (point.z() > x1c_center.z()) - idx |= 0x4; - return idx; +int CPFAreaOctree::GetChildIndex(const zeus::CVector3f& point) const { + int idx = 0x0; + if (point.x() > x1c_center.x()) + idx = 0x1; + if (point.y() > x1c_center.y()) + idx |= 0x2; + if (point.z() > x1c_center.z()) + idx |= 0x4; + return idx; } -rstl::prereserved_vector* CPFAreaOctree::GetRegionList(const zeus::CVector3f& point) -{ - if (x0_isLeaf) - return &x48_regions; - return x28_children[GetChildIndex(point)]->GetRegionList(point); +rstl::prereserved_vector* CPFAreaOctree::GetRegionList(const zeus::CVector3f& point) { + if (x0_isLeaf) + return &x48_regions; + return x28_children[GetChildIndex(point)]->GetRegionList(point); } void CPFAreaOctree::GetRegionListList(rstl::reserved_vector*, 32>& listOut, - const zeus::CVector3f& point, float padding) -{ - if (listOut.size() >= listOut.capacity()) - return; + const zeus::CVector3f& point, float padding) { + if (listOut.size() >= listOut.capacity()) + return; - if (x0_isLeaf) - { - listOut.push_back(&x48_regions); - return; - } + if (x0_isLeaf) { + listOut.push_back(&x48_regions); + return; + } - for (int i=0 ; i<8 ; ++i) - { - CPFAreaOctree* ch = x28_children[i]; - if (ch->IsPointInsidePaddedAABox(point, padding)) - ch->GetRegionListList(listOut, point, padding); - } + for (int i = 0; i < 8; ++i) { + CPFAreaOctree* ch = x28_children[i]; + if (ch->IsPointInsidePaddedAABox(point, padding)) + ch->GetRegionListList(listOut, point, padding); + } } -bool CPFAreaOctree::IsPointInsidePaddedAABox(const zeus::CVector3f& point, float padding) const -{ - return point.x() >= x4_aabb.min.x() - padding && - point.x() <= x4_aabb.max.x() + padding && - point.y() >= x4_aabb.min.y() - padding && - point.y() <= x4_aabb.max.y() + padding && - point.z() >= x4_aabb.min.z() - padding && - point.z() <= x4_aabb.max.z() + padding; +bool CPFAreaOctree::IsPointInsidePaddedAABox(const zeus::CVector3f& point, float padding) const { + return point.x() >= x4_aabb.min.x() - padding && point.x() <= x4_aabb.max.x() + padding && + point.y() >= x4_aabb.min.y() - padding && point.y() <= x4_aabb.max.y() + padding && + point.z() >= x4_aabb.min.z() - padding && point.z() <= x4_aabb.max.z() + padding; } -void CPFOpenList::Clear() -{ - x40_region.Data()->SetOpenMore(&x40_region); - x40_region.Data()->SetOpenLess(&x40_region); - x0_bitSet.Clear(); +void CPFOpenList::Clear() { + x40_region.Data()->SetOpenMore(&x40_region); + x40_region.Data()->SetOpenLess(&x40_region); + x0_bitSet.Clear(); } -void CPFOpenList::Push(CPFRegion* reg) -{ - x0_bitSet.Add(reg->GetIndex()); - CPFRegion* other = x40_region.Data()->GetOpenMore(); - while (other != &x40_region && reg->Data()->GetCost() > other->Data()->GetCost()) - other = other->Data()->GetOpenMore(); - other->Data()->GetOpenLess()->Data()->SetOpenMore(reg); - reg->Data()->SetOpenLess(other->Data()->GetOpenLess()); - other->Data()->SetOpenLess(reg); - reg->Data()->SetOpenMore(other); +void CPFOpenList::Push(CPFRegion* reg) { + x0_bitSet.Add(reg->GetIndex()); + CPFRegion* other = x40_region.Data()->GetOpenMore(); + while (other != &x40_region && reg->Data()->GetCost() > other->Data()->GetCost()) + other = other->Data()->GetOpenMore(); + other->Data()->GetOpenLess()->Data()->SetOpenMore(reg); + reg->Data()->SetOpenLess(other->Data()->GetOpenLess()); + other->Data()->SetOpenLess(reg); + reg->Data()->SetOpenMore(other); } -CPFRegion* CPFOpenList::Pop() -{ - CPFRegion* reg = x40_region.Data()->GetOpenMore(); - if (reg != &x40_region) - { - x0_bitSet.Rmv(reg->GetIndex()); - reg->Data()->GetOpenMore()->Data()->SetOpenLess(reg->Data()->GetOpenLess()); - reg->Data()->GetOpenLess()->Data()->SetOpenMore(reg->Data()->GetOpenMore()); - reg->Data()->SetOpenMore(nullptr); - reg->Data()->SetOpenLess(nullptr); - return reg; - } - return nullptr; -} - -void CPFOpenList::Pop(CPFRegion* reg) -{ +CPFRegion* CPFOpenList::Pop() { + CPFRegion* reg = x40_region.Data()->GetOpenMore(); + if (reg != &x40_region) { x0_bitSet.Rmv(reg->GetIndex()); reg->Data()->GetOpenMore()->Data()->SetOpenLess(reg->Data()->GetOpenLess()); reg->Data()->GetOpenLess()->Data()->SetOpenMore(reg->Data()->GetOpenMore()); reg->Data()->SetOpenMore(nullptr); reg->Data()->SetOpenLess(nullptr); + return reg; + } + return nullptr; } -bool CPFOpenList::Test(CPFRegion* reg) -{ - return x0_bitSet.Test(reg->GetIndex()); +void CPFOpenList::Pop(CPFRegion* reg) { + x0_bitSet.Rmv(reg->GetIndex()); + reg->Data()->GetOpenMore()->Data()->SetOpenLess(reg->Data()->GetOpenLess()); + reg->Data()->GetOpenLess()->Data()->SetOpenMore(reg->Data()->GetOpenMore()); + reg->Data()->SetOpenMore(nullptr); + reg->Data()->SetOpenLess(nullptr); } -CPFArea::CPFArea(std::unique_ptr&& buf, u32 len) -{ - CMemoryInStream r(buf.get(), len); +bool CPFOpenList::Test(CPFRegion* reg) { return x0_bitSet.Test(reg->GetIndex()); } - u32 version = r.readUint32Big(); - if (version != 4) - Log.report(logvisor::Fatal, "Unexpected PATH version %d, should be 4", version); +CPFArea::CPFArea(std::unique_ptr&& buf, u32 len) { + CMemoryInStream r(buf.get(), len); - u32 numNodes = r.readUint32Big(); - x140_nodes.reserve(numNodes); - for (u32 i=0 ; i(r.readUint32Big())); + r.seek(((((numRegions * numRegions) + 31) / 32) - numBitfieldWords) * 2 * sizeof(u32)); - for (CPFRegion*& rl : x160_octreeRegionLookup) - rl = &x150_regions[reinterpret_cast(rl)]; + u32 numRegionLookups = r.readUint32Big(); + x160_octreeRegionLookup.reserve(numRegionLookups); + for (u32 i = 0; i < numRegionLookups; ++i) + x160_octreeRegionLookup.push_back(reinterpret_cast(r.readUint32Big())); - u32 numOctreeNodes = r.readUint32Big(); - x158_octree.reserve(numOctreeNodes); - for (u32 i=0 ; i(rl)]; - for (CPFAreaOctree& node : x158_octree) - node.Fixup(*this); + u32 numOctreeNodes = r.readUint32Big(); + x158_octree.reserve(numOctreeNodes); + for (u32 i = 0; i < numOctreeNodes; ++i) + x158_octree.emplace_back(r); + + for (CPFAreaOctree& node : x158_octree) + node.Fixup(*this); } -rstl::prereserved_vector* CPFArea::GetOctreeRegionList(const zeus::CVector3f& point) -{ - if (x30_hasCachedRegionList && zeus::close_enough(point, x24_cachedRegionListPoint)) - return x20_cachedRegionList; - return x158_octree.back().GetRegionList(point); +rstl::prereserved_vector* CPFArea::GetOctreeRegionList(const zeus::CVector3f& point) { + if (x30_hasCachedRegionList && zeus::close_enough(point, x24_cachedRegionListPoint)) + return x20_cachedRegionList; + return x158_octree.back().GetRegionList(point); } -u32 CPFArea::FindRegions(rstl::reserved_vector& regions, const zeus::CVector3f& point, - u32 flags, u32 indexMask) -{ - bool isFlyer = (flags & 0x2) != 0; - bool isSwimmer = (flags & 0x4) != 0; - for (CPFRegion* region : *GetOctreeRegionList(point)) - { +u32 CPFArea::FindRegions(rstl::reserved_vector& regions, const zeus::CVector3f& point, u32 flags, + u32 indexMask) { + bool isFlyer = (flags & 0x2) != 0; + bool isSwimmer = (flags & 0x4) != 0; + for (CPFRegion* region : *GetOctreeRegionList(point)) { + if (region->GetFlags() & 0xff & flags && (region->GetFlags() >> 16) & 0xff & indexMask && + region->IsPointInside(point) && (isFlyer || isSwimmer || region->PointHeight(point) < 3.f)) { + regions.push_back(region); + if (regions.size() == regions.capacity()) + break; + } + } + return u32(regions.size()); +} + +CPFRegion* CPFArea::FindClosestRegion(const zeus::CVector3f& point, u32 flags, u32 indexMask, float padding) { + rstl::reserved_vector*, 32> regionListList; + x158_octree.back().GetRegionListList(regionListList, point, padding); + bool isFlyer = (flags & 0x2) != 0; + CPFRegion* ret = nullptr; + for (rstl::prereserved_vector* list : regionListList) { + for (CPFRegion* region : *list) { + if (region->Data()->GetCookie() != x34_curCookie) { if (region->GetFlags() & 0xff & flags && (region->GetFlags() >> 16) & 0xff & indexMask && - region->IsPointInside(point) && (isFlyer || isSwimmer || region->PointHeight(point) < 3.f)) - { - regions.push_back(region); - if (regions.size() == regions.capacity()) - break; + region->IsPointInsidePaddedAABox(point, padding) && (isFlyer || region->PointHeight(point) < 3.f)) { + if (region->FindBestPoint(x10_tmpPolyPoints, point, flags, padding * padding)) { + ret = region; + padding = region->Data()->GetBestPointDistanceSquared() == 0.0 + ? 0.f + : std::sqrt(region->Data()->GetBestPointDistanceSquared()); + x4_closestPoint = region->Data()->GetBestPoint(); + } } + region->Data()->SetCookie(x34_curCookie); + } } - return u32(regions.size()); -} - -CPFRegion* CPFArea::FindClosestRegion(const zeus::CVector3f& point, u32 flags, u32 indexMask, float padding) -{ - rstl::reserved_vector*, 32> regionListList; - x158_octree.back().GetRegionListList(regionListList, point, padding); - bool isFlyer = (flags & 0x2) != 0; - CPFRegion* ret = nullptr; - for (rstl::prereserved_vector* list : regionListList) - { - for (CPFRegion* region : *list) - { - if (region->Data()->GetCookie() != x34_curCookie) - { - if (region->GetFlags() & 0xff & flags && - (region->GetFlags() >> 16) & 0xff & indexMask && - region->IsPointInsidePaddedAABox(point, padding) && - (isFlyer || region->PointHeight(point) < 3.f)) - { - if (region->FindBestPoint(x10_tmpPolyPoints, point, flags, padding * padding)) - { - ret = region; - padding = region->Data()->GetBestPointDistanceSquared() == 0.0 ? 0.f : - std::sqrt(region->Data()->GetBestPointDistanceSquared()); - x4_closestPoint = region->Data()->GetBestPoint(); - } - } - region->Data()->SetCookie(x34_curCookie); - } - } - } - return ret; + } + return ret; } zeus::CVector3f CPFArea::FindClosestReachablePoint(rstl::reserved_vector& regs, - const zeus::CVector3f& point, u32 flags, u32 indexMask) -{ - zeus::CVector3f ret; - float closestDistSq = FLT_MAX; - for (CPFRegion& reg : x150_regions) - { - if (reg.GetFlags() & 0xff & flags && (reg.GetFlags() >> 16) & 0xff & indexMask) - { - for (CPFRegion* oreg : regs) - { - if (PathExists(oreg, ®, flags)) - { - float distSq = (reg.GetCentroid() - point).magSquared(); - if (distSq < closestDistSq) - { - closestDistSq = distSq; - ret = reg.GetCentroid(); - break; - } - } - } + const zeus::CVector3f& point, u32 flags, u32 indexMask) { + zeus::CVector3f ret; + float closestDistSq = FLT_MAX; + for (CPFRegion& reg : x150_regions) { + if (reg.GetFlags() & 0xff & flags && (reg.GetFlags() >> 16) & 0xff & indexMask) { + for (CPFRegion* oreg : regs) { + if (PathExists(oreg, ®, flags)) { + float distSq = (reg.GetCentroid() - point).magSquared(); + if (distSq < closestDistSq) { + closestDistSq = distSq; + ret = reg.GetCentroid(); + break; + } } + } } - return ret; + } + return ret; } -bool CPFArea::PathExists(const CPFRegion* r1, const CPFRegion* r2, u32 flags) const -{ - if (r1 == r2 || (flags & 0x4) != 0) - return true; +bool CPFArea::PathExists(const CPFRegion* r1, const CPFRegion* r2, u32 flags) const { + if (r1 == r2 || (flags & 0x4) != 0) + return true; - u32 i1 = r1->GetIndex(); - u32 i2 = r2->GetIndex(); - if (i1 > i2) - std::swap(i1, i2); + u32 i1 = r1->GetIndex(); + u32 i2 = r2->GetIndex(); + if (i1 > i2) + std::swap(i1, i2); - u32 remRegions = u32(x150_regions.size()) - i1; - u32 remConnections = remRegions * (remRegions - 1) / 2; - u32 totalConnections = u32(x150_regions.size()) * (u32(x150_regions.size()) - 1) / 2; - u32 bit = totalConnections - remConnections + i2 - (i1 + 1); + u32 remRegions = u32(x150_regions.size()) - i1; + u32 remConnections = remRegions * (remRegions - 1) / 2; + u32 totalConnections = u32(x150_regions.size()) * (u32(x150_regions.size()) - 1) / 2; + u32 bit = totalConnections - remConnections + i2 - (i1 + 1); - auto d = std::div(bit, 32); - if ((flags & 0x2) != 0) - return ((x170_connectionsFlyers[d.quot] >> d.rem) & 0x1) != 0; - else - return ((x168_connectionsGround[d.quot] >> d.rem) & 0x1) != 0; + auto d = std::div(bit, 32); + if ((flags & 0x2) != 0) + return ((x170_connectionsFlyers[d.quot] >> d.rem) & 0x1) != 0; + else + return ((x168_connectionsGround[d.quot] >> d.rem) & 0x1) != 0; } -CFactoryFnReturn FPathFindAreaFactory(const urde::SObjectTag& tag, - std::unique_ptr&& in, u32 len, - const urde::CVParamTransfer& vparms, - CObjectReference* selfRef) -{ - return TToken::GetIObjObjectFor(std::make_unique(std::move(in), len)); -} +CFactoryFnReturn FPathFindAreaFactory(const urde::SObjectTag& tag, std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms, CObjectReference* selfRef) { + return TToken::GetIObjObjectFor(std::make_unique(std::move(in), len)); } +} // namespace urde diff --git a/Runtime/World/CPathFindArea.hpp b/Runtime/World/CPathFindArea.hpp index 2f220fca1..48014df8d 100644 --- a/Runtime/World/CPathFindArea.hpp +++ b/Runtime/World/CPathFindArea.hpp @@ -6,110 +6,107 @@ #include "IFactory.hpp" #include "CPathFindRegion.hpp" -namespace urde -{ +namespace urde { class CVParamTransfer; class CObjectReference; -class CPFBitSet -{ - u32 x0_bitmap[16] = {}; -public: - void Clear() { for (u32& w : x0_bitmap) w = 0; } - void Add(s32 i) { x0_bitmap[i / 32] |= (1 << (i % 32)); } - bool Test(s32 i) const { return (x0_bitmap[i / 32] & (1 << (i % 32))) != 0; } - void Rmv(s32 i) { x0_bitmap[i / 32] &= ~(1 << (i % 32)); } -}; - -class CPFAreaOctree -{ - u32 x0_isLeaf; - zeus::CAABox x4_aabb; - zeus::CVector3f x1c_center; - CPFAreaOctree* x28_children[8]; - rstl::prereserved_vector x48_regions; -public: - CPFAreaOctree(CMemoryInStream& in); - void Fixup(CPFArea& area); - int GetChildIndex(const zeus::CVector3f& point) const; - rstl::prereserved_vector* GetRegionList(const zeus::CVector3f& point); - void GetRegionListList(rstl::reserved_vector*, 32>& listOut, - const zeus::CVector3f& point, float padding); - bool IsPointInsidePaddedAABox(const zeus::CVector3f& point, float padding) const; - void Render(); -}; - -class CPFOpenList -{ - friend class CPFArea; - CPFBitSet x0_bitSet; - CPFRegion x40_region; - CPFRegionData x90_regionData; +class CPFBitSet { + u32 x0_bitmap[16] = {}; public: - void Clear(); - void Push(CPFRegion* reg); - CPFRegion* Pop(); - void Pop(CPFRegion* reg); - bool Test(CPFRegion* reg); + void Clear() { + for (u32& w : x0_bitmap) + w = 0; + } + void Add(s32 i) { x0_bitmap[i / 32] |= (1 << (i % 32)); } + bool Test(s32 i) const { return (x0_bitmap[i / 32] & (1 << (i % 32))) != 0; } + void Rmv(s32 i) { x0_bitmap[i / 32] &= ~(1 << (i % 32)); } }; -class CPFArea -{ - friend class CPFRegion; - friend class CPFAreaOctree; - friend class CPathFindSearch; +class CPFAreaOctree { + u32 x0_isLeaf; + zeus::CAABox x4_aabb; + zeus::CVector3f x1c_center; + CPFAreaOctree* x28_children[8]; + rstl::prereserved_vector x48_regions; - float x0_ = FLT_MAX; - zeus::CVector3f x4_closestPoint; - std::vector x10_tmpPolyPoints; - rstl::prereserved_vector* x20_cachedRegionList = nullptr; - zeus::CVector3f x24_cachedRegionListPoint; - bool x30_hasCachedRegionList = false; - s32 x34_curCookie = 0; - CPFBitSet x38_closedSet; - CPFOpenList x78_openList; - //u32 x138_; - //std::unique_ptr x13c_data; - /* Used to be prereserved_vectors backed by x13c_data - * This has been changed to meet storage requirements of - * modern systems */ - std::vector x140_nodes; // x140: count, x144: ptr - std::vector x148_links; // x148: count, x14c: ptr - std::vector x150_regions; // x150: count, x154: ptr - std::vector x158_octree; // x158: count, x15c: ptr - std::vector x160_octreeRegionLookup; // x160: count, x164: ptr - std::vector x168_connectionsGround; // x168: word_count, x16c: ptr - std::vector x170_connectionsFlyers; // x170: word_count, x174: ptr - std::vector x178_regionDatas; - zeus::CTransform x188_transform; public: - CPFArea(std::unique_ptr&& buf, u32 len); - - void SetTransform(const zeus::CTransform& xf) { x188_transform = xf; } - const zeus::CTransform& GetTransform() const { return x188_transform; } - const CPFRegion& GetRegion(s32 i) const { return x150_regions[i]; } - const zeus::CVector3f& GetClosestPoint() const { return x4_closestPoint; } - CPFOpenList& OpenList() { return x78_openList; } - CPFBitSet& ClosedSet() { return x38_closedSet; } - const CPFRegionData& GetRegionData(s32 i) const { return x178_regionDatas[i]; } - const CPFLink& GetLink(s32 i) const { return x148_links[i]; } - const CPFNode& GetNode(s32 i) const { return x140_nodes[i]; } - const CPFAreaOctree& GetOctree(s32 i) const { return x158_octree[i]; } - const CPFRegion* GetOctreeRegionPtrs(s32 i) const { return x160_octreeRegionLookup[i]; } - rstl::prereserved_vector* GetOctreeRegionList(const zeus::CVector3f& point); - u32 FindRegions(rstl::reserved_vector& regions, const zeus::CVector3f& point, - u32 flags, u32 indexMask); - CPFRegion* FindClosestRegion(const zeus::CVector3f& point, u32 flags, u32 indexMask, float padding); - zeus::CVector3f FindClosestReachablePoint(rstl::reserved_vector& regs, - const zeus::CVector3f& point, u32 flags, u32 indexMask); - bool PathExists(const CPFRegion* r1, const CPFRegion* r2, u32 flags) const; + CPFAreaOctree(CMemoryInStream& in); + void Fixup(CPFArea& area); + int GetChildIndex(const zeus::CVector3f& point) const; + rstl::prereserved_vector* GetRegionList(const zeus::CVector3f& point); + void GetRegionListList(rstl::reserved_vector*, 32>& listOut, + const zeus::CVector3f& point, float padding); + bool IsPointInsidePaddedAABox(const zeus::CVector3f& point, float padding) const; + void Render(); }; +class CPFOpenList { + friend class CPFArea; + CPFBitSet x0_bitSet; + CPFRegion x40_region; + CPFRegionData x90_regionData; -CFactoryFnReturn FPathFindAreaFactory(const urde::SObjectTag& tag, - std::unique_ptr&& in, u32 len, - const urde::CVParamTransfer& vparms, - CObjectReference* selfRef); -} +public: + void Clear(); + void Push(CPFRegion* reg); + CPFRegion* Pop(); + void Pop(CPFRegion* reg); + bool Test(CPFRegion* reg); +}; +class CPFArea { + friend class CPFRegion; + friend class CPFAreaOctree; + friend class CPathFindSearch; + + float x0_ = FLT_MAX; + zeus::CVector3f x4_closestPoint; + std::vector x10_tmpPolyPoints; + rstl::prereserved_vector* x20_cachedRegionList = nullptr; + zeus::CVector3f x24_cachedRegionListPoint; + bool x30_hasCachedRegionList = false; + s32 x34_curCookie = 0; + CPFBitSet x38_closedSet; + CPFOpenList x78_openList; + // u32 x138_; + // std::unique_ptr x13c_data; + /* Used to be prereserved_vectors backed by x13c_data + * This has been changed to meet storage requirements of + * modern systems */ + std::vector x140_nodes; // x140: count, x144: ptr + std::vector x148_links; // x148: count, x14c: ptr + std::vector x150_regions; // x150: count, x154: ptr + std::vector x158_octree; // x158: count, x15c: ptr + std::vector x160_octreeRegionLookup; // x160: count, x164: ptr + std::vector x168_connectionsGround; // x168: word_count, x16c: ptr + std::vector x170_connectionsFlyers; // x170: word_count, x174: ptr + std::vector x178_regionDatas; + zeus::CTransform x188_transform; + +public: + CPFArea(std::unique_ptr&& buf, u32 len); + + void SetTransform(const zeus::CTransform& xf) { x188_transform = xf; } + const zeus::CTransform& GetTransform() const { return x188_transform; } + const CPFRegion& GetRegion(s32 i) const { return x150_regions[i]; } + const zeus::CVector3f& GetClosestPoint() const { return x4_closestPoint; } + CPFOpenList& OpenList() { return x78_openList; } + CPFBitSet& ClosedSet() { return x38_closedSet; } + const CPFRegionData& GetRegionData(s32 i) const { return x178_regionDatas[i]; } + const CPFLink& GetLink(s32 i) const { return x148_links[i]; } + const CPFNode& GetNode(s32 i) const { return x140_nodes[i]; } + const CPFAreaOctree& GetOctree(s32 i) const { return x158_octree[i]; } + const CPFRegion* GetOctreeRegionPtrs(s32 i) const { return x160_octreeRegionLookup[i]; } + rstl::prereserved_vector* GetOctreeRegionList(const zeus::CVector3f& point); + u32 FindRegions(rstl::reserved_vector& regions, const zeus::CVector3f& point, u32 flags, + u32 indexMask); + CPFRegion* FindClosestRegion(const zeus::CVector3f& point, u32 flags, u32 indexMask, float padding); + zeus::CVector3f FindClosestReachablePoint(rstl::reserved_vector& regs, const zeus::CVector3f& point, + u32 flags, u32 indexMask); + bool PathExists(const CPFRegion* r1, const CPFRegion* r2, u32 flags) const; +}; + +CFactoryFnReturn FPathFindAreaFactory(const urde::SObjectTag& tag, std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms, CObjectReference* selfRef); +} // namespace urde diff --git a/Runtime/World/CPathFindRegion.cpp b/Runtime/World/CPathFindRegion.cpp index d69ff366c..480d26f84 100644 --- a/Runtime/World/CPathFindRegion.cpp +++ b/Runtime/World/CPathFindRegion.cpp @@ -1,258 +1,217 @@ #include "CPathFindRegion.hpp" #include "CPathFindArea.hpp" -namespace urde -{ +namespace urde { -CPFNode::CPFNode(CMemoryInStream& in) -{ - x0_position.readBig(in); - xc_normal.readBig(in); +CPFNode::CPFNode(CMemoryInStream& in) { + x0_position.readBig(in); + xc_normal.readBig(in); } -CPFLink::CPFLink(CMemoryInStream& in) -{ - x0_node = in.readUint32Big(); - x4_region = in.readUint32Big(); - x8_2dWidth = in.readFloatBig(); - xc_oo2dWidth = in.readFloatBig(); +CPFLink::CPFLink(CMemoryInStream& in) { + x0_node = in.readUint32Big(); + x4_region = in.readUint32Big(); + x8_2dWidth = in.readFloatBig(); + xc_oo2dWidth = in.readFloatBig(); } -CPFRegion::CPFRegion(CMemoryInStream& in) -{ - x0_numNodes = in.readUint32Big(); - x4_startNode = reinterpret_cast(in.readUint32Big()); - x8_numLinks = in.readUint32Big(); - xc_startLink = reinterpret_cast(in.readUint32Big()); - x10_flags = in.readUint32Big(); - x14_height = in.readFloatBig(); - x18_normal.readBig(in); - x24_regionIdx = in.readUint32Big(); - x28_centroid.readBig(in); - x34_aabb.readBoundingBoxBig(in); - x4c_regionData = reinterpret_cast(in.readUint32Big()); +CPFRegion::CPFRegion(CMemoryInStream& in) { + x0_numNodes = in.readUint32Big(); + x4_startNode = reinterpret_cast(in.readUint32Big()); + x8_numLinks = in.readUint32Big(); + xc_startLink = reinterpret_cast(in.readUint32Big()); + x10_flags = in.readUint32Big(); + x14_height = in.readFloatBig(); + x18_normal.readBig(in); + x24_regionIdx = in.readUint32Big(); + x28_centroid.readBig(in); + x34_aabb.readBoundingBoxBig(in); + x4c_regionData = reinterpret_cast(in.readUint32Big()); } -const CPFLink* CPFRegion::GetPathLink() const -{ - return &xc_startLink[x4c_regionData->GetPathLink()]; +const CPFLink* CPFRegion::GetPathLink() const { return &xc_startLink[x4c_regionData->GetPathLink()]; } + +void CPFRegion::Fixup(CPFArea& area, u32& maxRegionNodes) { + if (x0_numNodes) + x4_startNode = &area.x140_nodes[reinterpret_cast(x4_startNode)]; + else + x4_startNode = nullptr; + if (x8_numLinks) + xc_startLink = &area.x148_links[reinterpret_cast(xc_startLink)]; + else + xc_startLink = nullptr; + x4c_regionData = &area.x178_regionDatas[x24_regionIdx]; + if (x0_numNodes > maxRegionNodes) + maxRegionNodes = x0_numNodes; } -void CPFRegion::Fixup(CPFArea& area, u32& maxRegionNodes) -{ - if (x0_numNodes) - x4_startNode = &area.x140_nodes[reinterpret_cast(x4_startNode)]; - else - x4_startNode = nullptr; - if (x8_numLinks) - xc_startLink = &area.x148_links[reinterpret_cast(xc_startLink)]; - else - xc_startLink = nullptr; - x4c_regionData = &area.x178_regionDatas[x24_regionIdx]; - if (x0_numNodes > maxRegionNodes) - maxRegionNodes = x0_numNodes; -} - -bool CPFRegion::IsPointInside(const zeus::CVector3f& point) const -{ - if (!x34_aabb.pointInside(point)) - return false; - int i; - for (i=0 ; iGetPos(); - if (i == x0_numNodes && nodeToPoint.dot(x18_normal) >= 0.f) - if ((nodeToPoint - x14_height * zeus::CVector3f::skUp).dot(x18_normal) <= 0.f) - return true; +bool CPFRegion::IsPointInside(const zeus::CVector3f& point) const { + if (!x34_aabb.pointInside(point)) return false; + int i; + for (i = 0; i < x0_numNodes; ++i) { + CPFNode& node = x4_startNode[i]; + if ((point - node.GetPos()).dot(node.GetNormal()) < 0.f) + break; + } + zeus::CVector3f nodeToPoint = point - x4_startNode->GetPos(); + if (i == x0_numNodes && nodeToPoint.dot(x18_normal) >= 0.f) + if ((nodeToPoint - x14_height * zeus::CVector3f::skUp).dot(x18_normal) <= 0.f) + return true; + return false; } -float CPFRegion::PointHeight(const zeus::CVector3f& point) const -{ - return (point - x4_startNode->GetPos()).dot(x18_normal); +float CPFRegion::PointHeight(const zeus::CVector3f& point) const { + return (point - x4_startNode->GetPos()).dot(x18_normal); } -bool CPFRegion::FindClosestPointOnPolygon(const std::vector& polyPoints, - const zeus::CVector3f& normal, - const zeus::CVector3f& point, bool excludePolyPoints) -{ - bool found = false; - int i; - for (i=0 ; i& polyPoints, const zeus::CVector3f& normal, + const zeus::CVector3f& point, bool excludePolyPoints) { + bool found = false; + int i; + for (i = 0; i < polyPoints.size(); ++i) { + const zeus::CVector3f& p0 = polyPoints[i]; + const zeus::CVector3f& p1 = polyPoints[(i + 1) % polyPoints.size()]; + if ((p1 - p0).cross(normal).dot(point - p0) < 0.f) + break; + } + + if (i == polyPoints.size()) { + float distToPoly = (polyPoints.front() - point).dot(normal); + float distToPolySq = distToPoly * distToPoly; + if (distToPolySq < x4c_regionData->GetBestPointDistanceSquared()) { + found = true; + x4c_regionData->SetBestPointDistanceSquared(distToPolySq); + x4c_regionData->SetBestPoint(normal * distToPoly + point); + } + } else { + bool projected = false; + for (i = 0; i < polyPoints.size(); ++i) { + const zeus::CVector3f& p0 = polyPoints[i]; + const zeus::CVector3f& p1 = polyPoints[(i + 1) % polyPoints.size()]; + zeus::CVector3f p0ToP1 = p1 - p0; + zeus::CVector3f p1ToPoint = point - p1; + zeus::CVector3f sum = p1ToPoint + p0ToP1; + if (p0ToP1.cross(normal).dot(p1ToPoint) < 0.f && p0ToP1.dot(p1ToPoint) <= 0.f && sum.dot(p0ToP1) >= 0.f) { + projected = true; + p0ToP1.normalize(); + sum -= p0ToP1.dot(sum) * p0ToP1; + float distSq = sum.magSquared(); + if (distSq < x4c_regionData->GetBestPointDistanceSquared()) { + found = true; + x4c_regionData->SetBestPointDistanceSquared(distSq); + x4c_regionData->SetBestPoint(point - sum); + } + break; + } + } + + if (!projected && !excludePolyPoints) { + for (i = 0; i < polyPoints.size(); ++i) { const zeus::CVector3f& p0 = polyPoints[i]; - const zeus::CVector3f& p1 = polyPoints[(i + 1) % polyPoints.size()]; - if ((p1 - p0).cross(normal).dot(point - p0) < 0.f) - break; - } - - if (i == polyPoints.size()) - { - float distToPoly = (polyPoints.front() - point).dot(normal); - float distToPolySq = distToPoly * distToPoly; - if (distToPolySq < x4c_regionData->GetBestPointDistanceSquared()) - { - found = true; - x4c_regionData->SetBestPointDistanceSquared(distToPolySq); - x4c_regionData->SetBestPoint(normal * distToPoly + point); + float distSq = (point - p0).magSquared(); + if (distSq < x4c_regionData->GetBestPointDistanceSquared()) { + found = true; + x4c_regionData->SetBestPointDistanceSquared(distSq); + x4c_regionData->SetBestPoint(p0); } + } } - else - { - bool projected = false; - for (i=0 ; i= 0.f) - { - projected = true; - p0ToP1.normalize(); - sum -= p0ToP1.dot(sum) * p0ToP1; - float distSq = sum.magSquared(); - if (distSq < x4c_regionData->GetBestPointDistanceSquared()) - { - found = true; - x4c_regionData->SetBestPointDistanceSquared(distSq); - x4c_regionData->SetBestPoint(point - sum); - } - break; - } - } - - if (!projected && !excludePolyPoints) - { - for (i=0 ; iGetBestPointDistanceSquared()) - { - found = true; - x4c_regionData->SetBestPointDistanceSquared(distSq); - x4c_regionData->SetBestPoint(p0); - } - } - } - } - return found; + } + return found; } -bool CPFRegion::FindBestPoint(std::vector& polyPoints, const zeus::CVector3f& point, - u32 flags, float paddingSq) -{ - bool found = false; - bool isFlyer = (flags & 0x2) != 0; - x4c_regionData->SetBestPointDistanceSquared(paddingSq); - if (!isFlyer) - { - for (int i=0 ; i& polyPoints, const zeus::CVector3f& point, u32 flags, + float paddingSq) { + bool found = false; + bool isFlyer = (flags & 0x2) != 0; + x4c_regionData->SetBestPointDistanceSquared(paddingSq); + if (!isFlyer) { + for (int i = 0; i < x0_numNodes; ++i) { + CPFNode& node = x4_startNode[i]; + CPFNode& nextNode = x4_startNode[(i + 1) % x0_numNodes]; + polyPoints.clear(); + polyPoints.push_back(node.GetPos()); + polyPoints.push_back(node.GetPos()); + polyPoints.back().z() += x14_height; + polyPoints.push_back(nextNode.GetPos()); + polyPoints.back().z() += x14_height; + polyPoints.push_back(nextNode.GetPos()); + found |= FindClosestPointOnPolygon(polyPoints, node.GetNormal(), point, true); } + } + polyPoints.clear(); + for (int i = 0; i < x0_numNodes; ++i) { + CPFNode& node = x4_startNode[i]; + polyPoints.push_back(node.GetPos()); + } + found |= FindClosestPointOnPolygon(polyPoints, x18_normal, point, false); + + if (!isFlyer) { polyPoints.clear(); - for (int i=0 ; i= 0; --i) { + CPFNode& node = x4_startNode[i]; + polyPoints.push_back(node.GetPos()); + polyPoints.back().z() += x14_height; } - found |= FindClosestPointOnPolygon(polyPoints, x18_normal, point, false); + found |= FindClosestPointOnPolygon(polyPoints, -x18_normal, point, false); + } - if (!isFlyer) - { - polyPoints.clear(); - for (int i=x0_numNodes-1 ; i>=0 ; --i) - { - CPFNode& node = x4_startNode[i]; - polyPoints.push_back(node.GetPos()); - polyPoints.back().z() += x14_height; - } - found |= FindClosestPointOnPolygon(polyPoints, -x18_normal, point, false); + return found; +} + +void CPFRegion::SetLinkTo(s32 idx) { + if (x8_numLinks <= 0) + return; + for (s32 i = 0; i < x8_numLinks; ++i) + if (xc_startLink[i].GetRegion() == idx) { + Data()->SetPathLink(i); + return; } - - return found; } -void CPFRegion::SetLinkTo(s32 idx) -{ - if (x8_numLinks <= 0) - return; - for (s32 i=0 ; iSetPathLink(i); - return; - } +void CPFRegion::DropToGround(zeus::CVector3f& point) const { + point.z() -= (point - x4_startNode->GetPos()).dot(x18_normal) / x18_normal.z(); } -void CPFRegion::DropToGround(zeus::CVector3f& point) const -{ - point.z() -= (point - x4_startNode->GetPos()).dot(x18_normal) / x18_normal.z(); +zeus::CVector3f CPFRegion::GetLinkMidPoint(const CPFLink& link) const { + const CPFNode& node = x4_startNode[link.GetNode()]; + const CPFNode& nextNode = x4_startNode[(link.GetNode() + 1) % x0_numNodes]; + return (node.GetPos() + nextNode.GetPos()) * 0.5f; } -zeus::CVector3f CPFRegion::GetLinkMidPoint(const CPFLink& link) const -{ - const CPFNode& node = x4_startNode[link.GetNode()]; - const CPFNode& nextNode = x4_startNode[(link.GetNode() + 1) % x0_numNodes]; - return (node.GetPos() + nextNode.GetPos()) * 0.5f; +zeus::CVector3f CPFRegion::FitThroughLink2d(const zeus::CVector3f& p1, const CPFLink& link, const zeus::CVector3f& p2, + float chRadius) const { + CPFNode& node = x4_startNode[link.GetNode()]; + CPFNode& nextNode = x4_startNode[(link.GetNode() + 1) % x0_numNodes]; + zeus::CVector3f nodeDelta = nextNode.GetPos() - node.GetPos(); + float t = 0.5f; + if (chRadius < 0.5f * link.Get2dWidth()) { + zeus::CVector2f delta2d(nodeDelta.x(), nodeDelta.y()); + delta2d *= link.GetOO2dWidth(); + zeus::CVector3f nodeToP1 = p1 - node.GetPos(); + float f27 = nodeToP1.dot(node.GetNormal()); + float f31 = delta2d.dot(zeus::CVector2f(nodeToP1.y(), nodeToP1.y())); + zeus::CVector3f nodeToP2 = p2 - node.GetPos(); + float f26 = -nodeToP2.dot(node.GetNormal()); + float f1b = delta2d.dot(zeus::CVector2f(nodeToP2.y(), nodeToP2.y())); + float f3 = f27 + f26; + if (f3 > FLT_EPSILON) + t = zeus::clamp(chRadius, 1.f / f3 * (f26 * f31 + f27 * f1b), link.Get2dWidth() - chRadius) * link.GetOO2dWidth(); + } + return nodeDelta * t + node.GetPos(); } -zeus::CVector3f CPFRegion::FitThroughLink2d(const zeus::CVector3f& p1, const CPFLink& link, - const zeus::CVector3f& p2, float chRadius) const -{ - CPFNode& node = x4_startNode[link.GetNode()]; - CPFNode& nextNode = x4_startNode[(link.GetNode() + 1) % x0_numNodes]; - zeus::CVector3f nodeDelta = nextNode.GetPos() - node.GetPos(); - float t = 0.5f; - if (chRadius < 0.5f * link.Get2dWidth()) - { - zeus::CVector2f delta2d(nodeDelta.x(), nodeDelta.y()); - delta2d *= link.GetOO2dWidth(); - zeus::CVector3f nodeToP1 = p1 - node.GetPos(); - float f27 = nodeToP1.dot(node.GetNormal()); - float f31 = delta2d.dot(zeus::CVector2f(nodeToP1.y(), nodeToP1.y())); - zeus::CVector3f nodeToP2 = p2 - node.GetPos(); - float f26 = -nodeToP2.dot(node.GetNormal()); - float f1b = delta2d.dot(zeus::CVector2f(nodeToP2.y(), nodeToP2.y())); - float f3 = f27 + f26; - if (f3 > FLT_EPSILON) - t = zeus::clamp(chRadius, 1.f / f3 * (f26 * f31 + f27 * f1b), link.Get2dWidth() - chRadius) * - link.GetOO2dWidth(); - } - return nodeDelta * t + node.GetPos(); -} - -zeus::CVector3f CPFRegion::FitThroughLink3d(const zeus::CVector3f& p1, const CPFLink& link, - float regionHeight, const zeus::CVector3f& p2, - float chRadius, float chHalfHeight) const -{ - CPFNode& node = x4_startNode[link.GetNode()]; - CPFNode& nextNode = x4_startNode[(link.GetNode() + 1) % x0_numNodes]; - zeus::CVector3f nodeDelta = nextNode.GetPos() - node.GetPos(); - float f25 = (p1 - node.GetPos()).dot(node.GetNormal()); - float f24 = (node.GetPos() - p2).dot(node.GetNormal()); - float f23 = f25 + f24; -# if 0 +zeus::CVector3f CPFRegion::FitThroughLink3d(const zeus::CVector3f& p1, const CPFLink& link, float regionHeight, + const zeus::CVector3f& p2, float chRadius, float chHalfHeight) const { + CPFNode& node = x4_startNode[link.GetNode()]; + CPFNode& nextNode = x4_startNode[(link.GetNode() + 1) % x0_numNodes]; + zeus::CVector3f nodeDelta = nextNode.GetPos() - node.GetPos(); + float f25 = (p1 - node.GetPos()).dot(node.GetNormal()); + float f24 = (node.GetPos() - p2).dot(node.GetNormal()); + float f23 = f25 + f24; +#if 0 if (chRadius < 0.5f * link.Get2dWidth()) { zeus::CVector2f delta2d(nodeDelta.x, nodeDelta.y); @@ -268,31 +227,24 @@ zeus::CVector3f CPFRegion::FitThroughLink3d(const zeus::CVector3f& p1, const CPF } } #endif - zeus::CVector3f midPoint = nodeDelta * 0.5f + node.GetPos(); - float z; - if (chHalfHeight < 0.5f * regionHeight) - { - float minZ = chHalfHeight + midPoint.z(); - z = 0.5f * (p1.z() + p2.z()); - if (f23 > FLT_EPSILON) - z = 1.f / f23 * (f24 * p1.z() + f25 * p2.z()); - z = zeus::clamp(minZ, z, regionHeight + midPoint.z() - chHalfHeight); - } - else - { - z = (p1.z() + p2.z()) * 0.5f; - } - return {midPoint.x(), midPoint.y(), z}; + zeus::CVector3f midPoint = nodeDelta * 0.5f + node.GetPos(); + float z; + if (chHalfHeight < 0.5f * regionHeight) { + float minZ = chHalfHeight + midPoint.z(); + z = 0.5f * (p1.z() + p2.z()); + if (f23 > FLT_EPSILON) + z = 1.f / f23 * (f24 * p1.z() + f25 * p2.z()); + z = zeus::clamp(minZ, z, regionHeight + midPoint.z() - chHalfHeight); + } else { + z = (p1.z() + p2.z()) * 0.5f; + } + return {midPoint.x(), midPoint.y(), z}; } -bool CPFRegion::IsPointInsidePaddedAABox(const zeus::CVector3f& point, float padding) const -{ - return point.x() >= x34_aabb.min.x() - padding && - point.x() <= x34_aabb.max.x() + padding && - point.y() >= x34_aabb.min.y() - padding && - point.y() <= x34_aabb.max.y() + padding && - point.z() >= x34_aabb.min.z() - padding && - point.z() <= x34_aabb.max.z() + padding; +bool CPFRegion::IsPointInsidePaddedAABox(const zeus::CVector3f& point, float padding) const { + return point.x() >= x34_aabb.min.x() - padding && point.x() <= x34_aabb.max.x() + padding && + point.y() >= x34_aabb.min.y() - padding && point.y() <= x34_aabb.max.y() + padding && + point.z() >= x34_aabb.min.z() - padding && point.z() <= x34_aabb.max.z() + padding; } -} +} // namespace urde diff --git a/Runtime/World/CPathFindRegion.hpp b/Runtime/World/CPathFindRegion.hpp index b651b9b86..8e000435e 100644 --- a/Runtime/World/CPathFindRegion.hpp +++ b/Runtime/World/CPathFindRegion.hpp @@ -3,126 +3,121 @@ #include "RetroTypes.hpp" #include "zeus/CAABox.hpp" -namespace urde -{ +namespace urde { class CPFArea; class CPFLink; class CPFRegionData; -class CPFNode -{ - zeus::CVector3f x0_position; - zeus::CVector3f xc_normal; -public: - CPFNode(CMemoryInStream& in); - const zeus::CVector3f& GetPos() const { return x0_position; } - const zeus::CVector3f& GetNormal() const { return xc_normal; } -}; - -class CPFLink -{ - u32 x0_node; - u32 x4_region; - float x8_2dWidth; - float xc_oo2dWidth; -public: - CPFLink(CMemoryInStream& in); - u32 GetNode() const { return x0_node; } - u32 GetRegion() const { return x4_region; } - float Get2dWidth() const { return x8_2dWidth; } - float GetOO2dWidth() const { return xc_oo2dWidth; } -}; - -class CPFRegion -{ - u32 x0_numNodes = 0; - CPFNode* x4_startNode = nullptr; - u32 x8_numLinks = 0; - CPFLink* xc_startLink = nullptr; - u32 x10_flags = 0; - float x14_height = 0.f; - zeus::CVector3f x18_normal; - u32 x24_regionIdx = 0; - zeus::CVector3f x28_centroid; - zeus::CAABox x34_aabb; - CPFRegionData* x4c_regionData; -public: - CPFRegion() = default; - CPFRegion(CMemoryInStream& in); - void SetData(CPFRegionData* data) { x4c_regionData = data; } - CPFRegionData* Data() const { return x4c_regionData; } - u32 GetIndex() const { return x24_regionIdx; } - float GetHeight() const { return x14_height; } - const CPFLink* GetPathLink() const; - u32 GetNumLinks() const { return x8_numLinks; } - u32 GetFlags() const { return x10_flags; } - const CPFLink* GetLink(u32 i) const { return xc_startLink + i; } - void SetCentroid(const zeus::CVector3f& c) { x28_centroid = c; } - const zeus::CVector3f& GetCentroid() const { return x28_centroid; } - void Fixup(CPFArea& area, u32& maxRegionNodes); - bool IsPointInside(const zeus::CVector3f& point) const; - const zeus::CVector3f& GetNormal() const { return x18_normal; } - u32 GetNumNodes() const { return x0_numNodes; } - const CPFNode* GetNode(u32 i) const { return x4_startNode + i; } - float PointHeight(const zeus::CVector3f& point) const; - bool FindClosestPointOnPolygon(const std::vector&, const zeus::CVector3f&, - const zeus::CVector3f&, bool); - bool FindBestPoint(std::vector& polyPoints, const zeus::CVector3f& point, u32 flags, float paddingSq); - void SetLinkTo(s32 idx); - void DropToGround(zeus::CVector3f& point) const; - zeus::CVector3f GetLinkMidPoint(const CPFLink& link) const; - zeus::CVector3f FitThroughLink2d(const zeus::CVector3f& p1, const CPFLink& link, - const zeus::CVector3f& p2, float chRadius) const; - zeus::CVector3f FitThroughLink3d(const zeus::CVector3f& p1, const CPFLink& link, - float regionHeight, const zeus::CVector3f& p2, - float chRadius, float chHalfHeight) const; - bool IsPointInsidePaddedAABox(const zeus::CVector3f& point, float padding) const; -}; - -class CPFRegionData -{ - float x0_bestPointDistSq = 0.f; - zeus::CVector3f x4_bestPoint; - s32 x10_cookie = -1; - float x14_cost = 0.f; - float x18_g = 0.f; - float x1c_h = 0.f; - CPFRegion* x20_parent = nullptr; - CPFRegion* x24_openLess = nullptr; - CPFRegion* x28_openMore = nullptr; - s32 x2c_pathLink = 0; +class CPFNode { + zeus::CVector3f x0_position; + zeus::CVector3f xc_normal; public: - CPFRegionData() = default; - void SetOpenLess(CPFRegion* r) { x24_openLess = r; } - void SetOpenMore(CPFRegion* r) { x28_openMore = r; } - CPFRegion* GetOpenLess() const { return x24_openLess; } - CPFRegion* GetOpenMore() const { return x28_openMore; } - float GetCost() const { return x14_cost; } - float GetG() const { return x18_g; } - s32 GetPathLink() const { return x2c_pathLink; } - void SetPathLink(s32 l) { x2c_pathLink = l; } - CPFRegion* GetParent() const { return x20_parent; } - void SetBestPoint(const zeus::CVector3f& bestPoint) { x4_bestPoint = bestPoint; } - const zeus::CVector3f& GetBestPoint() const { return x4_bestPoint; } - void SetBestPointDistanceSquared(float distSq) { x0_bestPointDistSq = distSq; } - float GetBestPointDistanceSquared() const { return x0_bestPointDistSq; } - void SetCookie(s32 c) { x10_cookie = c; } - s32 GetCookie() const { return x10_cookie; } - - void Setup(CPFRegion* parent, float g, float h) - { - x20_parent = parent; - x18_g = g; - x1c_h = h; - x14_cost = x18_g + x1c_h; - } - void Setup(CPFRegion* parent, float g) - { - x20_parent = parent; - x18_g = g; - x14_cost = x18_g + x1c_h; - } + CPFNode(CMemoryInStream& in); + const zeus::CVector3f& GetPos() const { return x0_position; } + const zeus::CVector3f& GetNormal() const { return xc_normal; } }; -} +class CPFLink { + u32 x0_node; + u32 x4_region; + float x8_2dWidth; + float xc_oo2dWidth; + +public: + CPFLink(CMemoryInStream& in); + u32 GetNode() const { return x0_node; } + u32 GetRegion() const { return x4_region; } + float Get2dWidth() const { return x8_2dWidth; } + float GetOO2dWidth() const { return xc_oo2dWidth; } +}; + +class CPFRegion { + u32 x0_numNodes = 0; + CPFNode* x4_startNode = nullptr; + u32 x8_numLinks = 0; + CPFLink* xc_startLink = nullptr; + u32 x10_flags = 0; + float x14_height = 0.f; + zeus::CVector3f x18_normal; + u32 x24_regionIdx = 0; + zeus::CVector3f x28_centroid; + zeus::CAABox x34_aabb; + CPFRegionData* x4c_regionData; + +public: + CPFRegion() = default; + CPFRegion(CMemoryInStream& in); + void SetData(CPFRegionData* data) { x4c_regionData = data; } + CPFRegionData* Data() const { return x4c_regionData; } + u32 GetIndex() const { return x24_regionIdx; } + float GetHeight() const { return x14_height; } + const CPFLink* GetPathLink() const; + u32 GetNumLinks() const { return x8_numLinks; } + u32 GetFlags() const { return x10_flags; } + const CPFLink* GetLink(u32 i) const { return xc_startLink + i; } + void SetCentroid(const zeus::CVector3f& c) { x28_centroid = c; } + const zeus::CVector3f& GetCentroid() const { return x28_centroid; } + void Fixup(CPFArea& area, u32& maxRegionNodes); + bool IsPointInside(const zeus::CVector3f& point) const; + const zeus::CVector3f& GetNormal() const { return x18_normal; } + u32 GetNumNodes() const { return x0_numNodes; } + const CPFNode* GetNode(u32 i) const { return x4_startNode + i; } + float PointHeight(const zeus::CVector3f& point) const; + bool FindClosestPointOnPolygon(const std::vector&, const zeus::CVector3f&, const zeus::CVector3f&, + bool); + bool FindBestPoint(std::vector& polyPoints, const zeus::CVector3f& point, u32 flags, + float paddingSq); + void SetLinkTo(s32 idx); + void DropToGround(zeus::CVector3f& point) const; + zeus::CVector3f GetLinkMidPoint(const CPFLink& link) const; + zeus::CVector3f FitThroughLink2d(const zeus::CVector3f& p1, const CPFLink& link, const zeus::CVector3f& p2, + float chRadius) const; + zeus::CVector3f FitThroughLink3d(const zeus::CVector3f& p1, const CPFLink& link, float regionHeight, + const zeus::CVector3f& p2, float chRadius, float chHalfHeight) const; + bool IsPointInsidePaddedAABox(const zeus::CVector3f& point, float padding) const; +}; + +class CPFRegionData { + float x0_bestPointDistSq = 0.f; + zeus::CVector3f x4_bestPoint; + s32 x10_cookie = -1; + float x14_cost = 0.f; + float x18_g = 0.f; + float x1c_h = 0.f; + CPFRegion* x20_parent = nullptr; + CPFRegion* x24_openLess = nullptr; + CPFRegion* x28_openMore = nullptr; + s32 x2c_pathLink = 0; + +public: + CPFRegionData() = default; + void SetOpenLess(CPFRegion* r) { x24_openLess = r; } + void SetOpenMore(CPFRegion* r) { x28_openMore = r; } + CPFRegion* GetOpenLess() const { return x24_openLess; } + CPFRegion* GetOpenMore() const { return x28_openMore; } + float GetCost() const { return x14_cost; } + float GetG() const { return x18_g; } + s32 GetPathLink() const { return x2c_pathLink; } + void SetPathLink(s32 l) { x2c_pathLink = l; } + CPFRegion* GetParent() const { return x20_parent; } + void SetBestPoint(const zeus::CVector3f& bestPoint) { x4_bestPoint = bestPoint; } + const zeus::CVector3f& GetBestPoint() const { return x4_bestPoint; } + void SetBestPointDistanceSquared(float distSq) { x0_bestPointDistSq = distSq; } + float GetBestPointDistanceSquared() const { return x0_bestPointDistSq; } + void SetCookie(s32 c) { x10_cookie = c; } + s32 GetCookie() const { return x10_cookie; } + + void Setup(CPFRegion* parent, float g, float h) { + x20_parent = parent; + x18_g = g; + x1c_h = h; + x14_cost = x18_g + x1c_h; + } + void Setup(CPFRegion* parent, float g) { + x20_parent = parent; + x18_g = g; + x14_cost = x18_g + x1c_h; + } +}; +} // namespace urde diff --git a/Runtime/World/CPathFindSearch.cpp b/Runtime/World/CPathFindSearch.cpp index a4150c2aa..083f61d92 100644 --- a/Runtime/World/CPathFindSearch.cpp +++ b/Runtime/World/CPathFindSearch.cpp @@ -1,397 +1,351 @@ #include "CPathFindSearch.hpp" -namespace urde -{ +namespace urde { CPathFindSearch::CPathFindSearch(CPFArea* area, u32 flags, u32 index, float chRadius, float chHeight) -: x0_area(area), xd0_chHeight(chHeight), xd4_chRadius(chRadius), xdc_flags(flags), xe0_indexMask(1u << index) -{} +: x0_area(area), xd0_chHeight(chHeight), xd4_chRadius(chRadius), xdc_flags(flags), xe0_indexMask(1u << index) {} -CPathFindSearch::EResult -CPathFindSearch::FindClosestReachablePoint(const zeus::CVector3f& p1, zeus::CVector3f& p2) const -{ - if (!x0_area) - return EResult::InvalidArea; +CPathFindSearch::EResult CPathFindSearch::FindClosestReachablePoint(const zeus::CVector3f& p1, + zeus::CVector3f& p2) const { + if (!x0_area) + return EResult::InvalidArea; - /* Work in local PFArea coordinates */ - zeus::CVector3f localP1 = x0_area->x188_transform.transposeRotate(p1 - x0_area->x188_transform.origin); - zeus::CVector3f localP2 = x0_area->x188_transform.transposeRotate(p2 - x0_area->x188_transform.origin); + /* Work in local PFArea coordinates */ + zeus::CVector3f localP1 = x0_area->x188_transform.transposeRotate(p1 - x0_area->x188_transform.origin); + zeus::CVector3f localP2 = x0_area->x188_transform.transposeRotate(p2 - x0_area->x188_transform.origin); - /* Raise a bit above ground for step-up resolution */ - if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) - { - localP2.z() += 0.3f; - localP1.z() += 0.3f; - } + /* Raise a bit above ground for step-up resolution */ + if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) { + localP2.z() += 0.3f; + localP1.z() += 0.3f; + } - rstl::reserved_vector regions; - if (x0_area->FindRegions(regions, localP1, xdc_flags, xe0_indexMask) == 0) - { - /* Point outside PATH; find nearest region point */ - CPFRegion* region = x0_area->FindClosestRegion(localP1, xdc_flags, xe0_indexMask, xd8_padding); - if (!region) - return EResult::NoSourcePoint; + rstl::reserved_vector regions; + if (x0_area->FindRegions(regions, localP1, xdc_flags, xe0_indexMask) == 0) { + /* Point outside PATH; find nearest region point */ + CPFRegion* region = x0_area->FindClosestRegion(localP1, xdc_flags, xe0_indexMask, xd8_padding); + if (!region) + return EResult::NoSourcePoint; - regions.push_back(region); - } + regions.push_back(region); + } - /* Override dest point to be reachable */ - zeus::CVector3f closestPoint = - x0_area->FindClosestReachablePoint(regions, localP2, xdc_flags, xe0_indexMask) + - zeus::CVector3f(0.f, 0.f, 3.f); - p2 = x0_area->x188_transform * closestPoint; + /* Override dest point to be reachable */ + zeus::CVector3f closestPoint = + x0_area->FindClosestReachablePoint(regions, localP2, xdc_flags, xe0_indexMask) + zeus::CVector3f(0.f, 0.f, 3.f); + p2 = x0_area->x188_transform * closestPoint; - return EResult::Success; + return EResult::Success; } -CPathFindSearch::EResult CPathFindSearch::PathExists(const zeus::CVector3f& p1, const zeus::CVector3f& p2) const -{ - if (!x0_area) - return EResult::InvalidArea; +CPathFindSearch::EResult CPathFindSearch::PathExists(const zeus::CVector3f& p1, const zeus::CVector3f& p2) const { + if (!x0_area) + return EResult::InvalidArea; - /* Work in local PFArea coordinates */ - zeus::CVector3f localP1 = x0_area->x188_transform.transposeRotate(p1 - x0_area->x188_transform.origin); - zeus::CVector3f localP2 = x0_area->x188_transform.transposeRotate(p2 - x0_area->x188_transform.origin); + /* Work in local PFArea coordinates */ + zeus::CVector3f localP1 = x0_area->x188_transform.transposeRotate(p1 - x0_area->x188_transform.origin); + zeus::CVector3f localP2 = x0_area->x188_transform.transposeRotate(p2 - x0_area->x188_transform.origin); - /* Raise a bit above ground for step-up resolution */ - if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) - { - localP2.z() += 0.3f; - localP1.z() += 0.3f; - } + /* Raise a bit above ground for step-up resolution */ + if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) { + localP2.z() += 0.3f; + localP1.z() += 0.3f; + } - rstl::reserved_vector regions1; - if (x0_area->FindRegions(regions1, localP1, xdc_flags, xe0_indexMask) == 0) - return EResult::NoSourcePoint; + rstl::reserved_vector regions1; + if (x0_area->FindRegions(regions1, localP1, xdc_flags, xe0_indexMask) == 0) + return EResult::NoSourcePoint; - rstl::reserved_vector regions2; - if (x0_area->FindRegions(regions2, localP2, xdc_flags, xe0_indexMask) == 0) - return EResult::NoDestPoint; + rstl::reserved_vector regions2; + if (x0_area->FindRegions(regions2, localP2, xdc_flags, xe0_indexMask) == 0) + return EResult::NoDestPoint; - for (CPFRegion* reg1 : regions1) - for (CPFRegion* reg2 : regions2) - if (reg1 == reg2 || x0_area->PathExists(reg1, reg2, xdc_flags)) - return EResult::Success; + for (CPFRegion* reg1 : regions1) + for (CPFRegion* reg2 : regions2) + if (reg1 == reg2 || x0_area->PathExists(reg1, reg2, xdc_flags)) + return EResult::Success; - return EResult::NoPath; + return EResult::NoPath; } -CPathFindSearch::EResult CPathFindSearch::OnPath(const zeus::CVector3f& p1) const -{ - if (!x0_area) - return EResult::InvalidArea; +CPathFindSearch::EResult CPathFindSearch::OnPath(const zeus::CVector3f& p1) const { + if (!x0_area) + return EResult::InvalidArea; - /* Work in local PFArea coordinates */ - zeus::CVector3f localP1 = x0_area->x188_transform.transposeRotate(p1 - x0_area->x188_transform.origin); + /* Work in local PFArea coordinates */ + zeus::CVector3f localP1 = x0_area->x188_transform.transposeRotate(p1 - x0_area->x188_transform.origin); - /* Raise a bit above ground for step-up resolution */ - if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) - localP1.z() += 0.3f; + /* Raise a bit above ground for step-up resolution */ + if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) + localP1.z() += 0.3f; - rstl::reserved_vector regions1; - if (x0_area->FindRegions(regions1, localP1, xdc_flags, xe0_indexMask) == 0) - return EResult::NoSourcePoint; + rstl::reserved_vector regions1; + if (x0_area->FindRegions(regions1, localP1, xdc_flags, xe0_indexMask) == 0) + return EResult::NoSourcePoint; - return EResult::Success; + return EResult::Success; } -CPathFindSearch::EResult CPathFindSearch::Search(const zeus::CVector3f& p1, const zeus::CVector3f& p2) -{ - u32 firstPoint = 0; - u32 flyToOutsidePoint = 0; - x4_waypoints.clear(); - xc8_curWaypoint = 0; +CPathFindSearch::EResult CPathFindSearch::Search(const zeus::CVector3f& p1, const zeus::CVector3f& p2) { + u32 firstPoint = 0; + u32 flyToOutsidePoint = 0; + x4_waypoints.clear(); + xc8_curWaypoint = 0; - if (!x0_area || x0_area->x150_regions.size() > 512) - { - xcc_result = EResult::InvalidArea; - return xcc_result; - } + if (!x0_area || x0_area->x150_regions.size() > 512) { + xcc_result = EResult::InvalidArea; + return xcc_result; + } - if (zeus::close_enough(p1, p2)) - { - /* That was easy */ - x4_waypoints.push_back(p1); - xcc_result = EResult::Success; - return xcc_result; - } - - /* Work in local PFArea coordinates */ - zeus::CVector3f localP1 = x0_area->x188_transform.transposeRotate(p1 - x0_area->x188_transform.origin); - zeus::CVector3f localP2 = x0_area->x188_transform.transposeRotate(p2 - x0_area->x188_transform.origin); - - /* Raise a bit above ground for step-up resolution */ - if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) - { - localP2.z() += 0.3f; - localP1.z() += 0.3f; - } - - rstl::reserved_vector regions1; - rstl::reserved_vector points; - if (x0_area->FindRegions(regions1, localP1, xdc_flags, xe0_indexMask) == 0) - { - /* Point outside PATH; find nearest region point */ - CPFRegion* region = x0_area->FindClosestRegion(localP1, xdc_flags, xe0_indexMask, xd8_padding); - if (!region) - { - xcc_result = EResult::NoSourcePoint; - return xcc_result; - } - - if (xdc_flags & 0x2 || xdc_flags & 0x4) - { - points.push_back(localP1); - firstPoint = 1; - } - regions1.push_back(region); - localP1 = x0_area->GetClosestPoint(); - } - - zeus::CVector3f finalP2 = localP2; - rstl::reserved_vector regions2; - if (x0_area->FindRegions(regions2, localP2, xdc_flags, xe0_indexMask) == 0) - { - /* Point outside PATH; find nearest region point */ - CPFRegion* region = x0_area->FindClosestRegion(localP2, xdc_flags, xe0_indexMask, xd8_padding); - if (!region) - { - xcc_result = EResult::NoDestPoint; - return xcc_result; - } - - if (xdc_flags & 0x2 || xdc_flags & 0x4) - { - flyToOutsidePoint = 1; - } - regions2.push_back(region); - localP2 = x0_area->GetClosestPoint(); - } - - rstl::reserved_vector regions1Uniq; - rstl::reserved_vector regions2Uniq; - bool noPath = true; - for (CPFRegion* reg1 : regions1) - { - for (CPFRegion* reg2 : regions2) - { - if (reg1 == reg2) - { - /* Route within one region */ - if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) - { - reg2->DropToGround(localP1); - reg2->DropToGround(localP2); - } - x4_waypoints.push_back(x0_area->x188_transform * localP1); - if (!zeus::close_enough(localP1, localP2)) - x4_waypoints.push_back(x0_area->x188_transform * localP2); - if (flyToOutsidePoint && !zeus::close_enough(localP2, finalP2)) - x4_waypoints.push_back(x0_area->x188_transform * finalP2); - xcc_result = EResult::Success; - return xcc_result; - } - - if (x0_area->PathExists(reg1, reg2, xdc_flags)) - { - /* Build unique source/dest region lists */ - if (std::find(regions1Uniq.rbegin(), regions1Uniq.rend(), reg1) == regions1Uniq.rend()) - regions1Uniq.push_back(reg1); - if (std::find(regions2Uniq.rbegin(), regions2Uniq.rend(), reg2) == regions2Uniq.rend()) - regions2Uniq.push_back(reg2); - noPath = false; - } - } - } - - /* Perform A* algorithm if path is known to exist */ - if (noPath || !Search(regions1Uniq, localP1, regions2Uniq, localP2)) - { - xcc_result = EResult::NoPath; - return xcc_result; - } - - /* Set forward links with best path */ - CPFRegion* reg = regions2Uniq[0]; - u32 lastPoint = 0; - do { - reg->Data()->GetParent()->SetLinkTo(reg->GetIndex()); - reg = reg->Data()->GetParent(); - ++lastPoint; - } while (reg != regions1Uniq[0]); - - /* Setup point range */ - bool includeP2 = true; - lastPoint -= 1; - firstPoint += 1; - lastPoint += firstPoint; - if (lastPoint > 15) - lastPoint = 15; - if (lastPoint + flyToOutsidePoint + 1 > 15) - includeP2 = false; - - /* Ensure start and finish points are on ground */ - if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) - { - regions1Uniq[0]->DropToGround(localP1); - regions2Uniq[0]->DropToGround(localP2); - } - - /* Gather link points using midpoints */ - float chHalfHeight = 0.5f * xd0_chHeight; - points.push_back(localP1); - reg = regions1Uniq[0]; - for (u32 i=firstPoint ; i<=lastPoint ; ++i) - { - const CPFLink* link = reg->GetPathLink(); - CPFRegion* linkReg = &x0_area->x150_regions[link->GetRegion()]; - zeus::CVector3f midPoint = reg->GetLinkMidPoint(*link); - if (xdc_flags & 0x2 || xdc_flags & 0x4) - { - float minHeight = std::min(reg->GetHeight(), linkReg->GetHeight()); - midPoint.z() = zeus::clamp(chHalfHeight + midPoint.z(), p2.z(), minHeight + midPoint.z() - chHalfHeight); - } - points.push_back(midPoint); - reg = linkReg; - } - - /* Gather finish points */ - if (includeP2) - { - points.push_back(localP2); - if (flyToOutsidePoint) - points.push_back(finalP2); - } - - /* Optimize link points using character radius and height */ - for (int i=0 ; i<2 ; ++i) - { - reg = regions1Uniq[0]; - for (u32 j=firstPoint ; j<=(includeP2 ? lastPoint : lastPoint-1) ; ++j) - { - const CPFLink* link = reg->GetPathLink(); - CPFRegion* linkReg = &x0_area->x150_regions[link->GetRegion()]; - if (xdc_flags & 0x2 || xdc_flags & 0x4) - { - float minHeight = std::min(reg->GetHeight(), linkReg->GetHeight()); - points[j] = reg->FitThroughLink3d(points[j-1], *link, minHeight, points[j+1], - xd4_chRadius, chHalfHeight); - } - else - { - points[j] = reg->FitThroughLink2d(points[j-1], *link, points[j+1], xd4_chRadius); - } - reg = linkReg; - } - } - - /* Write out points */ - for (u32 i=0 ; ix188_transform * points[i]); - - /* Done! */ + if (zeus::close_enough(p1, p2)) { + /* That was easy */ + x4_waypoints.push_back(p1); xcc_result = EResult::Success; return xcc_result; + } + + /* Work in local PFArea coordinates */ + zeus::CVector3f localP1 = x0_area->x188_transform.transposeRotate(p1 - x0_area->x188_transform.origin); + zeus::CVector3f localP2 = x0_area->x188_transform.transposeRotate(p2 - x0_area->x188_transform.origin); + + /* Raise a bit above ground for step-up resolution */ + if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) { + localP2.z() += 0.3f; + localP1.z() += 0.3f; + } + + rstl::reserved_vector regions1; + rstl::reserved_vector points; + if (x0_area->FindRegions(regions1, localP1, xdc_flags, xe0_indexMask) == 0) { + /* Point outside PATH; find nearest region point */ + CPFRegion* region = x0_area->FindClosestRegion(localP1, xdc_flags, xe0_indexMask, xd8_padding); + if (!region) { + xcc_result = EResult::NoSourcePoint; + return xcc_result; + } + + if (xdc_flags & 0x2 || xdc_flags & 0x4) { + points.push_back(localP1); + firstPoint = 1; + } + regions1.push_back(region); + localP1 = x0_area->GetClosestPoint(); + } + + zeus::CVector3f finalP2 = localP2; + rstl::reserved_vector regions2; + if (x0_area->FindRegions(regions2, localP2, xdc_flags, xe0_indexMask) == 0) { + /* Point outside PATH; find nearest region point */ + CPFRegion* region = x0_area->FindClosestRegion(localP2, xdc_flags, xe0_indexMask, xd8_padding); + if (!region) { + xcc_result = EResult::NoDestPoint; + return xcc_result; + } + + if (xdc_flags & 0x2 || xdc_flags & 0x4) { + flyToOutsidePoint = 1; + } + regions2.push_back(region); + localP2 = x0_area->GetClosestPoint(); + } + + rstl::reserved_vector regions1Uniq; + rstl::reserved_vector regions2Uniq; + bool noPath = true; + for (CPFRegion* reg1 : regions1) { + for (CPFRegion* reg2 : regions2) { + if (reg1 == reg2) { + /* Route within one region */ + if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) { + reg2->DropToGround(localP1); + reg2->DropToGround(localP2); + } + x4_waypoints.push_back(x0_area->x188_transform * localP1); + if (!zeus::close_enough(localP1, localP2)) + x4_waypoints.push_back(x0_area->x188_transform * localP2); + if (flyToOutsidePoint && !zeus::close_enough(localP2, finalP2)) + x4_waypoints.push_back(x0_area->x188_transform * finalP2); + xcc_result = EResult::Success; + return xcc_result; + } + + if (x0_area->PathExists(reg1, reg2, xdc_flags)) { + /* Build unique source/dest region lists */ + if (std::find(regions1Uniq.rbegin(), regions1Uniq.rend(), reg1) == regions1Uniq.rend()) + regions1Uniq.push_back(reg1); + if (std::find(regions2Uniq.rbegin(), regions2Uniq.rend(), reg2) == regions2Uniq.rend()) + regions2Uniq.push_back(reg2); + noPath = false; + } + } + } + + /* Perform A* algorithm if path is known to exist */ + if (noPath || !Search(regions1Uniq, localP1, regions2Uniq, localP2)) { + xcc_result = EResult::NoPath; + return xcc_result; + } + + /* Set forward links with best path */ + CPFRegion* reg = regions2Uniq[0]; + u32 lastPoint = 0; + do { + reg->Data()->GetParent()->SetLinkTo(reg->GetIndex()); + reg = reg->Data()->GetParent(); + ++lastPoint; + } while (reg != regions1Uniq[0]); + + /* Setup point range */ + bool includeP2 = true; + lastPoint -= 1; + firstPoint += 1; + lastPoint += firstPoint; + if (lastPoint > 15) + lastPoint = 15; + if (lastPoint + flyToOutsidePoint + 1 > 15) + includeP2 = false; + + /* Ensure start and finish points are on ground */ + if (!(xdc_flags & 0x2) && !(xdc_flags & 0x4)) { + regions1Uniq[0]->DropToGround(localP1); + regions2Uniq[0]->DropToGround(localP2); + } + + /* Gather link points using midpoints */ + float chHalfHeight = 0.5f * xd0_chHeight; + points.push_back(localP1); + reg = regions1Uniq[0]; + for (u32 i = firstPoint; i <= lastPoint; ++i) { + const CPFLink* link = reg->GetPathLink(); + CPFRegion* linkReg = &x0_area->x150_regions[link->GetRegion()]; + zeus::CVector3f midPoint = reg->GetLinkMidPoint(*link); + if (xdc_flags & 0x2 || xdc_flags & 0x4) { + float minHeight = std::min(reg->GetHeight(), linkReg->GetHeight()); + midPoint.z() = zeus::clamp(chHalfHeight + midPoint.z(), p2.z(), minHeight + midPoint.z() - chHalfHeight); + } + points.push_back(midPoint); + reg = linkReg; + } + + /* Gather finish points */ + if (includeP2) { + points.push_back(localP2); + if (flyToOutsidePoint) + points.push_back(finalP2); + } + + /* Optimize link points using character radius and height */ + for (int i = 0; i < 2; ++i) { + reg = regions1Uniq[0]; + for (u32 j = firstPoint; j <= (includeP2 ? lastPoint : lastPoint - 1); ++j) { + const CPFLink* link = reg->GetPathLink(); + CPFRegion* linkReg = &x0_area->x150_regions[link->GetRegion()]; + if (xdc_flags & 0x2 || xdc_flags & 0x4) { + float minHeight = std::min(reg->GetHeight(), linkReg->GetHeight()); + points[j] = reg->FitThroughLink3d(points[j - 1], *link, minHeight, points[j + 1], xd4_chRadius, chHalfHeight); + } else { + points[j] = reg->FitThroughLink2d(points[j - 1], *link, points[j + 1], xd4_chRadius); + } + reg = linkReg; + } + } + + /* Write out points */ + for (u32 i = 0; i < points.size(); ++i) + if (i == points.size() - 1 || !zeus::close_enough(points[i], points[i + 1])) + x4_waypoints.push_back(x0_area->x188_transform * points[i]); + + /* Done! */ + xcc_result = EResult::Success; + return xcc_result; } /* A* search algorithm * Reference: https://en.wikipedia.org/wiki/A*_search_algorithm */ bool CPathFindSearch::Search(rstl::reserved_vector& regs1, const zeus::CVector3f& p1, - rstl::reserved_vector& regs2, const zeus::CVector3f& p2) -{ - /* Reset search sets */ - x0_area->ClosedSet().Clear(); - x0_area->OpenList().Clear(); + rstl::reserved_vector& regs2, const zeus::CVector3f& p2) { + /* Reset search sets */ + x0_area->ClosedSet().Clear(); + x0_area->OpenList().Clear(); - /* Backup dest centroids */ - rstl::reserved_vector centroidBackup2; - for (CPFRegion* reg2 : regs2) - { - centroidBackup2.push_back(reg2->GetCentroid()); - reg2->SetCentroid(p2); - } + /* Backup dest centroids */ + rstl::reserved_vector centroidBackup2; + for (CPFRegion* reg2 : regs2) { + centroidBackup2.push_back(reg2->GetCentroid()); + reg2->SetCentroid(p2); + } - /* Initial heuristic */ - float h = (p2 - p1).magnitude(); + /* Initial heuristic */ + float h = (p2 - p1).magnitude(); - /* Backup source centroids and initialize heuristics */ - rstl::reserved_vector centroidBackup1; - for (CPFRegion* reg1 : regs1) - { - centroidBackup1.push_back(reg1->GetCentroid()); - reg1->SetCentroid(p1); - reg1->Data()->Setup(nullptr, 0.f, h); - x0_area->OpenList().Push(reg1); - } + /* Backup source centroids and initialize heuristics */ + rstl::reserved_vector centroidBackup1; + for (CPFRegion* reg1 : regs1) { + centroidBackup1.push_back(reg1->GetCentroid()); + reg1->SetCentroid(p1); + reg1->Data()->Setup(nullptr, 0.f, h); + x0_area->OpenList().Push(reg1); + } - /* Resolve path */ - CPFRegion* reg; - while ((reg = x0_area->OpenList().Pop())) - { - /* Stop if we're at the destination */ - if (std::find(regs2.begin(), regs2.end(), reg) != regs2.end()) - break; + /* Resolve path */ + CPFRegion* reg; + while ((reg = x0_area->OpenList().Pop())) { + /* Stop if we're at the destination */ + if (std::find(regs2.begin(), regs2.end(), reg) != regs2.end()) + break; - /* Exclude region from further resolves */ - x0_area->ClosedSet().Add(reg->GetIndex()); - for (u32 i=0 ; iGetNumLinks() ; ++i) - { - /* Potential link to follow */ - CPFRegion* linkReg = &x0_area->x150_regions[reg->GetLink(i)->GetRegion()]; - if (linkReg != reg->Data()->GetParent() && linkReg->GetFlags() & 0xff & xdc_flags && - (linkReg->GetFlags() >> 16) & 0xff & xe0_indexMask) - { - /* Next G */ - float g = (linkReg->GetCentroid() - reg->GetCentroid()).magnitude() + reg->Data()->GetG(); - if ((!x0_area->ClosedSet().Test(linkReg->GetIndex()) && !x0_area->OpenList().Test(linkReg)) || - linkReg->Data()->GetG() <= g) - { - if (x0_area->OpenList().Test(linkReg)) - { - /* In rare cases, revisiting a region will yield a lower G (actual cost) */ - x0_area->OpenList().Pop(linkReg); - linkReg->Data()->Setup(reg, g); - } - else - { - /* Compute next heuristic */ - x0_area->ClosedSet().Rmv(linkReg->GetIndex()); - float h = (p2 - linkReg->GetCentroid()).magnitude(); - linkReg->Data()->Setup(reg, g, h); - } + /* Exclude region from further resolves */ + x0_area->ClosedSet().Add(reg->GetIndex()); + for (u32 i = 0; i < reg->GetNumLinks(); ++i) { + /* Potential link to follow */ + CPFRegion* linkReg = &x0_area->x150_regions[reg->GetLink(i)->GetRegion()]; + if (linkReg != reg->Data()->GetParent() && linkReg->GetFlags() & 0xff & xdc_flags && + (linkReg->GetFlags() >> 16) & 0xff & xe0_indexMask) { + /* Next G */ + float g = (linkReg->GetCentroid() - reg->GetCentroid()).magnitude() + reg->Data()->GetG(); + if ((!x0_area->ClosedSet().Test(linkReg->GetIndex()) && !x0_area->OpenList().Test(linkReg)) || + linkReg->Data()->GetG() <= g) { + if (x0_area->OpenList().Test(linkReg)) { + /* In rare cases, revisiting a region will yield a lower G (actual cost) */ + x0_area->OpenList().Pop(linkReg); + linkReg->Data()->Setup(reg, g); + } else { + /* Compute next heuristic */ + x0_area->ClosedSet().Rmv(linkReg->GetIndex()); + float h = (p2 - linkReg->GetCentroid()).magnitude(); + linkReg->Data()->Setup(reg, g, h); + } - /* Make next potential candidate */ - x0_area->OpenList().Push(linkReg); - } - } + /* Make next potential candidate */ + x0_area->OpenList().Push(linkReg); } + } } + } - /* Restore source centroids */ - auto p1It = centroidBackup1.begin(); - for (CPFRegion* r : regs1) - r->SetCentroid(*p1It++); + /* Restore source centroids */ + auto p1It = centroidBackup1.begin(); + for (CPFRegion* r : regs1) + r->SetCentroid(*p1It++); - /* Restore dest centroids */ - auto p2It = centroidBackup2.begin(); - for (CPFRegion* r : regs2) - r->SetCentroid(*p2It++); + /* Restore dest centroids */ + auto p2It = centroidBackup2.begin(); + for (CPFRegion* r : regs2) + r->SetCentroid(*p2It++); - /* Best destination region */ - if (reg) - { - regs2.clear(); - regs2.push_back(reg); - /* Retrace parents to find best source region */ - while (CPFRegion* p = reg->Data()->GetParent()) - reg = p; - regs1.clear(); - regs1.push_back(reg); - } + /* Best destination region */ + if (reg) { + regs2.clear(); + regs2.push_back(reg); + /* Retrace parents to find best source region */ + while (CPFRegion* p = reg->Data()->GetParent()) + reg = p; + regs1.clear(); + regs1.push_back(reg); + } - return reg != nullptr; + return reg != nullptr; } -} +} // namespace urde diff --git a/Runtime/World/CPathFindSearch.hpp b/Runtime/World/CPathFindSearch.hpp index a3c648541..8fca20dd3 100644 --- a/Runtime/World/CPathFindSearch.hpp +++ b/Runtime/World/CPathFindSearch.hpp @@ -3,52 +3,43 @@ #include "RetroTypes.hpp" #include "CPathFindArea.hpp" -namespace urde -{ +namespace urde { -class CPathFindSearch -{ +class CPathFindSearch { public: - enum class EResult - { - Success, - InvalidArea, - NoSourcePoint, - NoDestPoint, - NoPath - }; + enum class EResult { Success, InvalidArea, NoSourcePoint, NoDestPoint, NoPath }; + private: - CPFArea* x0_area; - rstl::reserved_vector x4_waypoints; - u32 xc8_curWaypoint = 0; - EResult xcc_result; - float xd0_chHeight; - float xd4_chRadius; - float xd8_padding = 10.f; - u32 xdc_flags; // 0x2: flyer, 0x4: path-always-exists (swimmers) - u32 xe0_indexMask; - bool Search(rstl::reserved_vector& regs1, const zeus::CVector3f& p1, - rstl::reserved_vector& regs2, const zeus::CVector3f& p2); - void GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1, u32 wpIdx) const; - void GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, - u32 wpIdx, float lookahead) const; + CPFArea* x0_area; + rstl::reserved_vector x4_waypoints; + u32 xc8_curWaypoint = 0; + EResult xcc_result; + float xd0_chHeight; + float xd4_chRadius; + float xd8_padding = 10.f; + u32 xdc_flags; // 0x2: flyer, 0x4: path-always-exists (swimmers) + u32 xe0_indexMask; + bool Search(rstl::reserved_vector& regs1, const zeus::CVector3f& p1, + rstl::reserved_vector& regs2, const zeus::CVector3f& p2); + void GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1, u32 wpIdx) const; + void GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, u32 wpIdx, float lookahead) const; + public: - CPathFindSearch(CPFArea* area, u32 flags, u32 index, float chRadius, float chHeight); - EResult Search(const zeus::CVector3f& p1, const zeus::CVector3f& p2); - EResult FindClosestReachablePoint(const zeus::CVector3f& p1, zeus::CVector3f& p2) const; - EResult PathExists(const zeus::CVector3f& p1, const zeus::CVector3f& p2) const; - EResult OnPath(const zeus::CVector3f& p1) const; - EResult GetResult() const { return xcc_result; } - u32 GetCurrentWaypoint() const { return xc8_curWaypoint; } - void SetCurrentWaypoint(u32 wp) { xc8_curWaypoint = wp; } - const rstl::reserved_vector& GetWaypoints() const { return x4_waypoints; } - bool IsOver() const { return GetCurrentWaypoint() >= x4_waypoints.size(); } - bool IsShagged() const { return GetResult() != EResult::Success; } - bool SegmentOver(const zeus::CVector3f& p1) const; - void GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1) const; - void GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, float lookahead) const; - void SetArea(CPFArea* area) { x0_area = area; } + CPathFindSearch(CPFArea* area, u32 flags, u32 index, float chRadius, float chHeight); + EResult Search(const zeus::CVector3f& p1, const zeus::CVector3f& p2); + EResult FindClosestReachablePoint(const zeus::CVector3f& p1, zeus::CVector3f& p2) const; + EResult PathExists(const zeus::CVector3f& p1, const zeus::CVector3f& p2) const; + EResult OnPath(const zeus::CVector3f& p1) const; + EResult GetResult() const { return xcc_result; } + u32 GetCurrentWaypoint() const { return xc8_curWaypoint; } + void SetCurrentWaypoint(u32 wp) { xc8_curWaypoint = wp; } + const rstl::reserved_vector& GetWaypoints() const { return x4_waypoints; } + bool IsOver() const { return GetCurrentWaypoint() >= x4_waypoints.size(); } + bool IsShagged() const { return GetResult() != EResult::Success; } + bool SegmentOver(const zeus::CVector3f& p1) const; + void GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1) const; + void GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, float lookahead) const; + void SetArea(CPFArea* area) { x0_area = area; } }; -} - +} // namespace urde diff --git a/Runtime/World/CPathFindSpline.cpp b/Runtime/World/CPathFindSpline.cpp index 504f7fba5..24fdcc3a5 100644 --- a/Runtime/World/CPathFindSpline.cpp +++ b/Runtime/World/CPathFindSpline.cpp @@ -1,73 +1,62 @@ #include "CPathFindSearch.hpp" -namespace urde -{ +namespace urde { -bool CPathFindSearch::SegmentOver(const zeus::CVector3f& p1) const -{ - if (x4_waypoints.size() > 1 && xc8_curWaypoint < x4_waypoints.size() - 1) - { - const zeus::CVector3f& wp0 = x4_waypoints[xc8_curWaypoint]; - const zeus::CVector3f& wp1 = x4_waypoints[xc8_curWaypoint + 1]; - const zeus::CVector3f& wp2 = x4_waypoints[std::min(u32(x4_waypoints.size()) - 1, xc8_curWaypoint + 2)]; - return (p1 - wp1).dot(wp2 - wp0) >= 0.f; - } - return true; +bool CPathFindSearch::SegmentOver(const zeus::CVector3f& p1) const { + if (x4_waypoints.size() > 1 && xc8_curWaypoint < x4_waypoints.size() - 1) { + const zeus::CVector3f& wp0 = x4_waypoints[xc8_curWaypoint]; + const zeus::CVector3f& wp1 = x4_waypoints[xc8_curWaypoint + 1]; + const zeus::CVector3f& wp2 = x4_waypoints[std::min(u32(x4_waypoints.size()) - 1, xc8_curWaypoint + 2)]; + return (p1 - wp1).dot(wp2 - wp0) >= 0.f; + } + return true; } -void CPathFindSearch::GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1, u32 wpIdx) const -{ - if (x4_waypoints.size() > 1 && wpIdx < x4_waypoints.size() - 1) - { - zeus::CVector3f a = (wpIdx == 0) ? x4_waypoints[0] * 2.f - x4_waypoints[1] : x4_waypoints[wpIdx-1]; - const zeus::CVector3f& b = x4_waypoints[wpIdx]; - const zeus::CVector3f& c = x4_waypoints[wpIdx+1]; - zeus::CVector3f d = (wpIdx + 2 >= x4_waypoints.size()) ? - x4_waypoints[x4_waypoints.size()-1] * 2.f - x4_waypoints[x4_waypoints.size()-2] : x4_waypoints[wpIdx+2]; - zeus::CVector3f delta = c - b; - if (delta.isMagnitudeSafe()) - pOut = zeus::getCatmullRomSplinePoint(a, b, c, d, (p1 - b).dot(delta) / delta.magSquared()); - else - pOut = b; - } +void CPathFindSearch::GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1, u32 wpIdx) const { + if (x4_waypoints.size() > 1 && wpIdx < x4_waypoints.size() - 1) { + zeus::CVector3f a = (wpIdx == 0) ? x4_waypoints[0] * 2.f - x4_waypoints[1] : x4_waypoints[wpIdx - 1]; + const zeus::CVector3f& b = x4_waypoints[wpIdx]; + const zeus::CVector3f& c = x4_waypoints[wpIdx + 1]; + zeus::CVector3f d = (wpIdx + 2 >= x4_waypoints.size()) + ? x4_waypoints[x4_waypoints.size() - 1] * 2.f - x4_waypoints[x4_waypoints.size() - 2] + : x4_waypoints[wpIdx + 2]; + zeus::CVector3f delta = c - b; + if (delta.isMagnitudeSafe()) + pOut = zeus::getCatmullRomSplinePoint(a, b, c, d, (p1 - b).dot(delta) / delta.magSquared()); + else + pOut = b; + } } -void CPathFindSearch::GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1) const -{ - GetSplinePoint(pOut, p1, xc8_curWaypoint); +void CPathFindSearch::GetSplinePoint(zeus::CVector3f& pOut, const zeus::CVector3f& p1) const { + GetSplinePoint(pOut, p1, xc8_curWaypoint); +} + +void CPathFindSearch::GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, u32 wpIdx, + float lookahead) const { + if (x4_waypoints.size() > 1 && wpIdx < x4_waypoints.size() - 1) { + const zeus::CVector3f& wp0 = x4_waypoints[wpIdx]; + const zeus::CVector3f& wp1 = x4_waypoints[wpIdx + 1]; + zeus::CVector3f delta = wp1 - wp0; + if (delta.isMagnitudeSafe()) { + float deltaMag = delta.magnitude(); + delta = delta * (1.f / deltaMag); + float bToPtProj = (p1 - wp0).dot(delta); + if (bToPtProj + lookahead <= deltaMag) + GetSplinePoint(pOut, delta * lookahead + p1, wpIdx); + else if (wpIdx < x4_waypoints.size() - 2) + GetSplinePointWithLookahead(pOut, wp1, wpIdx + 1, lookahead - (deltaMag - bToPtProj)); + else + pOut = delta * (lookahead - (deltaMag - bToPtProj)) + wp1; + } else { + pOut = wp1; + } + } } void CPathFindSearch::GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, - u32 wpIdx, float lookahead) const -{ - if (x4_waypoints.size() > 1 && wpIdx < x4_waypoints.size() - 1) - { - const zeus::CVector3f& wp0 = x4_waypoints[wpIdx]; - const zeus::CVector3f& wp1 = x4_waypoints[wpIdx+1]; - zeus::CVector3f delta = wp1 - wp0; - if (delta.isMagnitudeSafe()) - { - float deltaMag = delta.magnitude(); - delta = delta * (1.f / deltaMag); - float bToPtProj = (p1 - wp0).dot(delta); - if (bToPtProj + lookahead <= deltaMag) - GetSplinePoint(pOut, delta * lookahead + p1, wpIdx); - else if (wpIdx < x4_waypoints.size() - 2) - GetSplinePointWithLookahead(pOut, wp1, wpIdx + 1, lookahead - (deltaMag - bToPtProj)); - else - pOut = delta * (lookahead - (deltaMag - bToPtProj)) + wp1; - } - else - { - pOut = wp1; - } - } + float lookahead) const { + GetSplinePointWithLookahead(pOut, p1, xc8_curWaypoint, lookahead); } -void CPathFindSearch::GetSplinePointWithLookahead(zeus::CVector3f& pOut, const zeus::CVector3f& p1, - float lookahead) const -{ - GetSplinePointWithLookahead(pOut, p1, xc8_curWaypoint, lookahead); -} - -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index 4a4741c3f..d99f42d7d 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -21,15 +21,13 @@ #include "World/CScriptActorKeyframe.hpp" #include "Weapon/CEnergyProjectile.hpp" -namespace urde -{ +namespace urde { const zeus::CColor CPatterned::skDamageColor(0.5f, 0.f, 0.f); -CMaterialList gkPatternedGroundMaterialList(EMaterialTypes::Character, EMaterialTypes::Solid, - EMaterialTypes::Orbit, EMaterialTypes::GroundCollider, - EMaterialTypes::Target); -CMaterialList gkPatternedFlyerMaterialList(EMaterialTypes::Character, EMaterialTypes::Solid, - EMaterialTypes::Orbit, EMaterialTypes::Target); +CMaterialList gkPatternedGroundMaterialList(EMaterialTypes::Character, EMaterialTypes::Solid, EMaterialTypes::Orbit, + EMaterialTypes::GroundCollider, EMaterialTypes::Target); +CMaterialList gkPatternedFlyerMaterialList(EMaterialTypes::Character, EMaterialTypes::Solid, EMaterialTypes::Orbit, + EMaterialTypes::Target); CPatterned::CPatterned(ECharacter character, TUniqueId uid, std::string_view name, CPatterned::EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, @@ -42,1880 +40,1530 @@ CPatterned::CPatterned(ECharacter character, TUniqueId uid, std::string_view nam zeus::CVector3f{pInfo.xc4_halfExtent, pInfo.xc4_halfExtent, pInfo.xc8_height}), pInfo.x0_mass, pInfo.x54_healthInfo, pInfo.x5c_damageVulnerability, moveType == EMovementType::Flyer ? gkPatternedFlyerMaterialList : gkPatternedGroundMaterialList, - pInfo.xfc_stateMachineId, actorParms, pInfo.xd8_stepUpHeight, 0.8f), -x2fc_minAttackRange(pInfo.x18_minAttackRange), -x300_maxAttackRange(pInfo.x1c_maxAttackRange), -x304_averageAttackTime(pInfo.x20_averageAttackTime), -x308_attackTimeVariation(pInfo.x24_attackTimeVariation), -x34c_character(character), -x388_anim(pInfo.GetAnimationParameters().GetInitialAnimation()), -x3b4_speed(pInfo.x4_speed), -x3b8_turnSpeed(pInfo.x8_turnSpeed), -x3bc_detectionRange(pInfo.xc_detectionRange), -x3c0_detectionHeightRange(pInfo.x10_detectionHeightRange), -x3c4_detectionAngle(std::cos(zeus::degToRad(pInfo.x14_dectectionAngle))), -x3c8_leashRadius(pInfo.x28_leashRadius), -x3cc_playerLeashRadius(pInfo.x2c_playerLeashRadius), -x3d0_playerLeashTime(pInfo.x30_playerLeashTime), -x3d8_xDamageThreshold(pInfo.xdc_xDamage), -x3dc_frozenXDamageThreshold(pInfo.xe0_frozenXDamage), -x3e0_xDamageDelay(pInfo.xe4_xDamageDelay), -x3fc_flavor(flavor), -x460_knockBackController(kbVariant) -{ - x328_25_verticalMovement = moveType == EMovementType::Flyer; - x328_27_onGround = moveType != EMovementType::Flyer; - x328_28_prevOnGround = true; - x328_30_lookAtDeathDir = true; - x329_24_ = true; - x400_25_alive = true; - x400_31_isFlyer = moveType == CPatterned::EMovementType::Flyer; - x402_29_drawParticles = true; - x402_30_updateThermalFrozenState = x402_31_thawed = actorParms.HasThermalHeat(); - x403_25_enableStateMachine = true; - x403_26_stateControlledMassiveDeath = true; - x404_contactDamage = pInfo.x34_contactDamageInfo; - x424_damageWaitTime = pInfo.x50_damageWaitTime; - x454_deathSfx = pInfo.xe8_deathSfx; - x458_iceShatterSfx = pInfo.x134_iceShatterSfx; - x4f4_intoFreezeDur = pInfo.x100_intoFreezeDur; - x4f8_outofFreezeDur = pInfo.x104_outofFreezeDur; - x4fc_ = pInfo.x108_; - x508_colliderType = colliderType; - x50c_baseDamageMag = actorParms.GetThermalMag(); - x514_deathExplosionOffset = pInfo.x110_particle1Scale; - x540_iceDeathExplosionOffset = pInfo.x124_particle2Scale; + pInfo.xfc_stateMachineId, actorParms, pInfo.xd8_stepUpHeight, 0.8f) +, x2fc_minAttackRange(pInfo.x18_minAttackRange) +, x300_maxAttackRange(pInfo.x1c_maxAttackRange) +, x304_averageAttackTime(pInfo.x20_averageAttackTime) +, x308_attackTimeVariation(pInfo.x24_attackTimeVariation) +, x34c_character(character) +, x388_anim(pInfo.GetAnimationParameters().GetInitialAnimation()) +, x3b4_speed(pInfo.x4_speed) +, x3b8_turnSpeed(pInfo.x8_turnSpeed) +, x3bc_detectionRange(pInfo.xc_detectionRange) +, x3c0_detectionHeightRange(pInfo.x10_detectionHeightRange) +, x3c4_detectionAngle(std::cos(zeus::degToRad(pInfo.x14_dectectionAngle))) +, x3c8_leashRadius(pInfo.x28_leashRadius) +, x3cc_playerLeashRadius(pInfo.x2c_playerLeashRadius) +, x3d0_playerLeashTime(pInfo.x30_playerLeashTime) +, x3d8_xDamageThreshold(pInfo.xdc_xDamage) +, x3dc_frozenXDamageThreshold(pInfo.xe0_frozenXDamage) +, x3e0_xDamageDelay(pInfo.xe4_xDamageDelay) +, x3fc_flavor(flavor) +, x460_knockBackController(kbVariant) { + x328_25_verticalMovement = moveType == EMovementType::Flyer; + x328_27_onGround = moveType != EMovementType::Flyer; + x328_28_prevOnGround = true; + x328_30_lookAtDeathDir = true; + x329_24_ = true; + x400_25_alive = true; + x400_31_isFlyer = moveType == CPatterned::EMovementType::Flyer; + x402_29_drawParticles = true; + x402_30_updateThermalFrozenState = x402_31_thawed = actorParms.HasThermalHeat(); + x403_25_enableStateMachine = true; + x403_26_stateControlledMassiveDeath = true; + x404_contactDamage = pInfo.x34_contactDamageInfo; + x424_damageWaitTime = pInfo.x50_damageWaitTime; + x454_deathSfx = pInfo.xe8_deathSfx; + x458_iceShatterSfx = pInfo.x134_iceShatterSfx; + x4f4_intoFreezeDur = pInfo.x100_intoFreezeDur; + x4f8_outofFreezeDur = pInfo.x104_outofFreezeDur; + x4fc_ = pInfo.x108_; + x508_colliderType = colliderType; + x50c_baseDamageMag = actorParms.GetThermalMag(); + x514_deathExplosionOffset = pInfo.x110_particle1Scale; + x540_iceDeathExplosionOffset = pInfo.x124_particle2Scale; - if (pInfo.x11c_particle1.IsValid()) - x520_deathExplosionParticle = { g_SimplePool->GetObj({FOURCC('PART'), pInfo.x11c_particle1})}; + if (pInfo.x11c_particle1.IsValid()) + x520_deathExplosionParticle = {g_SimplePool->GetObj({FOURCC('PART'), pInfo.x11c_particle1})}; - if (pInfo.x120_electric.IsValid()) - x530_deathExplosionElectric = { g_SimplePool->GetObj({FOURCC('ELSC'), pInfo.x120_electric})}; + if (pInfo.x120_electric.IsValid()) + x530_deathExplosionElectric = {g_SimplePool->GetObj({FOURCC('ELSC'), pInfo.x120_electric})}; - if (pInfo.x130_particle2.IsValid()) - x54c_iceDeathExplosionParticle = { g_SimplePool->GetObj({FOURCC('PART'), pInfo.x130_particle2})}; + if (pInfo.x130_particle2.IsValid()) + x54c_iceDeathExplosionParticle = {g_SimplePool->GetObj({FOURCC('PART'), pInfo.x130_particle2})}; - if (x404_contactDamage.GetRadius() > 0.f) - x404_contactDamage.SetRadius(0.f); + if (x404_contactDamage.GetRadius() > 0.f) + x404_contactDamage.SetRadius(0.f); - xe6_29_renderParticleDBInside = false; - x402_27_noXrayModel = !x64_modelData->HasModel(CModelData::EWhichModel::XRay); - BuildBodyController(bodyType); + xe6_29_renderParticleDBInside = false; + x402_27_noXrayModel = !x64_modelData->HasModel(CModelData::EWhichModel::XRay); + BuildBodyController(bodyType); } -void CPatterned::Accept(urde::IVisitor& visitor) -{ - visitor.Visit(this); +void CPatterned::Accept(urde::IVisitor& visitor) { visitor.Visit(this); } + +void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CAi::AcceptScriptMsg(msg, uid, mgr); + + switch (msg) { + case EScriptObjectMessage::Registered: { + if (x508_colliderType != EColliderType::One) { + CMaterialList include = GetMaterialFilter().GetIncludeList(); + CMaterialList exclude = GetMaterialFilter().GetExcludeList(); + include.Remove(EMaterialTypes::Character); + exclude.Add(EMaterialTypes::Character); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); + } + + if (HasModelData() && GetModelData()->HasAnimData() && GetModelData()->GetAnimationData()->GetIceModel()) { + const auto& baseAABB = GetBaseBoundingBox(); + float diagExtent = (baseAABB.max - baseAABB.min).magnitude() * 0.5f; + x510_vertexMorph = std::make_shared(zeus::CVector3f::skRight, zeus::CVector3f{}, diagExtent, + 0.f, *mgr.GetActiveRandom()); + } + + xf8_25_angularEnabled = true; + break; + } + case EScriptObjectMessage::OnFloor: { + if (!x328_25_verticalMovement) { + x150_momentum = {}; + AddMaterial(EMaterialTypes::GroundCollider, mgr); + } + x328_27_onGround = true; + break; + } + case EScriptObjectMessage::Falling: { + if (!x328_25_verticalMovement) { + if (x450_bodyController->GetPercentageFrozen() == 0.f) { + x150_momentum = {0.f, 0.f, -GetWeight()}; + RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + } + } + x328_27_onGround = false; + break; + } + case EScriptObjectMessage::Activate: + x3a0_latestLeashPosition = GetTranslation(); + break; + case EScriptObjectMessage::Deleted: + if (x330_stateMachineState.GetActorState() != nullptr) + x330_stateMachineState.GetActorState()->CallFunc(mgr, *this, EStateMsg::Deactivate, 0.f); + break; + case EScriptObjectMessage::Damage: { + if (TCastToConstPtr proj = mgr.GetObjectById(uid)) { + const CDamageInfo& info = proj->GetDamageInfo(); + if (info.GetWeaponMode().GetType() == EWeaponType::Wave) { + if (x460_knockBackController.x81_26_enableShock && info.GetWeaponMode().IsComboed() && HealthInfo(mgr)) { + x401_31_nextPendingShock = true; + KnockBack(GetTransform().frontVector(), mgr, info, EKnockBackType::Radius, false, info.GetKnockBackPower()); + x460_knockBackController.DeferKnockBack(EWeaponType::Wave); + } + } else if (info.GetWeaponMode().GetType() == EWeaponType::Plasma) { + if (x460_knockBackController.x81_27_enableBurn && info.GetWeaponMode().IsCharged() && HealthInfo(mgr)) { + KnockBack(GetTransform().frontVector(), mgr, info, EKnockBackType::Radius, false, info.GetKnockBackPower()); + x460_knockBackController.DeferKnockBack(EWeaponType::Plasma); + } + } + if (mgr.GetPlayer().GetUniqueId() == proj->GetOwnerId()) + x400_24_hitByPlayerProjectile = true; + } + break; + } + case EScriptObjectMessage::InvulnDamage: { + if (TCastToConstPtr proj = mgr.GetObjectById(uid)) { + if (proj->GetOwnerId() == mgr.GetPlayer().GetUniqueId()) + x400_24_hitByPlayerProjectile = true; + } + break; + } + default: + break; + } } -void CPatterned::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CAi::AcceptScriptMsg(msg, uid, mgr); - - switch (msg) - { - case EScriptObjectMessage::Registered: - { - if (x508_colliderType != EColliderType::One) - { - CMaterialList include = GetMaterialFilter().GetIncludeList(); - CMaterialList exclude = GetMaterialFilter().GetExcludeList(); - include.Remove(EMaterialTypes::Character); - exclude.Add(EMaterialTypes::Character); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); - } - - if (HasModelData() && GetModelData()->HasAnimData() && GetModelData()->GetAnimationData()->GetIceModel()) - { - const auto& baseAABB = GetBaseBoundingBox(); - float diagExtent = (baseAABB.max - baseAABB.min).magnitude() * 0.5f; - x510_vertexMorph = std::make_shared(zeus::CVector3f::skRight, - zeus::CVector3f{}, diagExtent, 0.f, *mgr.GetActiveRandom()); - } - - xf8_25_angularEnabled = true; - break; - } - case EScriptObjectMessage::OnFloor: - { - if (!x328_25_verticalMovement) - { - x150_momentum = {}; - AddMaterial(EMaterialTypes::GroundCollider, mgr); - } - x328_27_onGround = true; - break; - } - case EScriptObjectMessage::Falling: - { - if (!x328_25_verticalMovement) - { - if (x450_bodyController->GetPercentageFrozen() == 0.f) - { - x150_momentum = {0.f, 0.f, -GetWeight()}; - RemoveMaterial(EMaterialTypes::GroundCollider, mgr); - } - } - x328_27_onGround = false; - break; - } - case EScriptObjectMessage::Activate: - x3a0_latestLeashPosition = GetTranslation(); - break; - case EScriptObjectMessage::Deleted: - if (x330_stateMachineState.GetActorState() != nullptr) - x330_stateMachineState.GetActorState()->CallFunc(mgr, *this, EStateMsg::Deactivate, 0.f); - break; - case EScriptObjectMessage::Damage: - { - if (TCastToConstPtr proj = mgr.GetObjectById(uid)) - { - const CDamageInfo& info = proj->GetDamageInfo(); - if (info.GetWeaponMode().GetType() == EWeaponType::Wave) - { - if (x460_knockBackController.x81_26_enableShock && info.GetWeaponMode().IsComboed() && HealthInfo(mgr)) - { - x401_31_nextPendingShock = true; - KnockBack(GetTransform().frontVector(), mgr, info, EKnockBackType::Radius, false, - info.GetKnockBackPower()); - x460_knockBackController.DeferKnockBack(EWeaponType::Wave); - } - } - else if (info.GetWeaponMode().GetType() == EWeaponType::Plasma) - { - if (x460_knockBackController.x81_27_enableBurn && info.GetWeaponMode().IsCharged() && HealthInfo(mgr)) - { - KnockBack(GetTransform().frontVector(), mgr, info, EKnockBackType::Radius, - false, info.GetKnockBackPower()); - x460_knockBackController.DeferKnockBack(EWeaponType::Plasma); - } - } - if (mgr.GetPlayer().GetUniqueId() == proj->GetOwnerId()) - x400_24_hitByPlayerProjectile = true; - } - break; - } - case EScriptObjectMessage::InvulnDamage: - { - if (TCastToConstPtr proj = mgr.GetObjectById(uid)) - { - if (proj->GetOwnerId() == mgr.GetPlayer().GetUniqueId()) - x400_24_hitByPlayerProjectile = true; - } - break; - } - default: break; - } +void CPatterned::UpdateThermalFrozenState(bool thawed) { + x402_31_thawed = thawed; + if (x403_24_keepThermalVisorState) + return; + xe6_27_thermalVisorFlags = u8(thawed ? 2 : 1); } -void CPatterned::UpdateThermalFrozenState(bool thawed) -{ - x402_31_thawed = thawed; - if (x403_24_keepThermalVisorState) - return; - xe6_27_thermalVisorFlags = u8(thawed ? 2 : 1); -} +void CPatterned::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; -void CPatterned::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; + if (x402_30_updateThermalFrozenState) + UpdateThermalFrozenState(x450_bodyController->GetPercentageFrozen() == 0.f); - if (x402_30_updateThermalFrozenState) - UpdateThermalFrozenState(x450_bodyController->GetPercentageFrozen() == 0.f); + if (x64_modelData->GetAnimationData()->GetIceModel()) + x510_vertexMorph->Update(dt); - if (x64_modelData->GetAnimationData()->GetIceModel()) - x510_vertexMorph->Update(dt); + if (x402_26_dieIf80PercFrozen) { + float froz = x450_bodyController->GetPercentageFrozen(); + if (froz > 0.8f) + x400_29_pendingMassiveFrozenDeath = true; + } - if (x402_26_dieIf80PercFrozen) - { - float froz = x450_bodyController->GetPercentageFrozen(); - if (froz > 0.8f) - x400_29_pendingMassiveFrozenDeath = true; + if (!x400_25_alive) { + if ((x400_28_pendingMassiveDeath || x400_29_pendingMassiveFrozenDeath) && x3e0_xDamageDelay <= 0.f) { + if (x400_29_pendingMassiveFrozenDeath) { + SendScriptMsgs(EScriptObjectState::AboutToMassivelyDie, mgr, EScriptObjectMessage::None); + MassiveFrozenDeath(mgr); + } else { + SendScriptMsgs(EScriptObjectState::AboutToMassivelyDie, mgr, EScriptObjectMessage::None); + MassiveDeath(mgr); + } + } else { + x3e0_xDamageDelay -= dt; + if (x403_26_stateControlledMassiveDeath && x330_stateMachineState.GetName()) { + bool isDead = x330_stateMachineState.GetName() == "Dead"sv; + if (isDead && x330_stateMachineState.x8_time > 15.f) + MassiveDeath(mgr); + } } + } - if (!x400_25_alive) - { - if ((x400_28_pendingMassiveDeath || x400_29_pendingMassiveFrozenDeath) && x3e0_xDamageDelay <= 0.f) - { - if (x400_29_pendingMassiveFrozenDeath) - { - SendScriptMsgs(EScriptObjectState::AboutToMassivelyDie, mgr, EScriptObjectMessage::None); - MassiveFrozenDeath(mgr); - } - else - { - SendScriptMsgs(EScriptObjectState::AboutToMassivelyDie, mgr, EScriptObjectMessage::None); - MassiveDeath(mgr); - } - } - else - { - x3e0_xDamageDelay -= dt; - if (x403_26_stateControlledMassiveDeath && x330_stateMachineState.GetName()) - { - bool isDead = x330_stateMachineState.GetName() == "Dead"sv; - if (isDead && x330_stateMachineState.x8_time > 15.f) - MassiveDeath(mgr); - } - } - } + UpdateAlphaDelta(dt, mgr); - UpdateAlphaDelta(dt, mgr); + x3e4_lastHP = HealthInfo(mgr)->GetHP(); + if (!x330_stateMachineState.x4_state) + x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Start"sv); - x3e4_lastHP = HealthInfo(mgr)->GetHP(); - if (!x330_stateMachineState.x4_state) - x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Start"sv); + zeus::CVector3f diffVec = x4e4_latestPredictedTranslation - GetTranslation(); + if (!x328_25_verticalMovement) + diffVec.z() = 0.f; - zeus::CVector3f diffVec = x4e4_latestPredictedTranslation - GetTranslation(); - if (!x328_25_verticalMovement) - diffVec.z() = 0.f; + if (diffVec.magSquared() > (0.1f * dt)) + x4f0_predictedLeashTime += dt; + else + x4f0_predictedLeashTime = 0.f; - if (diffVec.magSquared() > (0.1f * dt)) - x4f0_predictedLeashTime += dt; - else - x4f0_predictedLeashTime = 0.f; + if (x460_knockBackController.x81_26_enableShock) { + /* Shock on logical falling edge */ + if (!x401_31_nextPendingShock && x402_24_pendingShock) + Shock(0.5f + mgr.GetActiveRandom()->Range(0.f, 0.5f), 0.2f); + x402_24_pendingShock = x401_31_nextPendingShock; + x401_31_nextPendingShock = false; - if (x460_knockBackController.x81_26_enableShock) - { - /* Shock on logical falling edge */ - if (!x401_31_nextPendingShock && x402_24_pendingShock) - Shock(0.5f + mgr.GetActiveRandom()->Range(0.f, 0.5f), 0.2f); - x402_24_pendingShock = x401_31_nextPendingShock; - x401_31_nextPendingShock = false; - - if (x450_bodyController->IsElectrocuting()) - { - mgr.GetActorModelParticles()->StartElectric(*this); - if (x3f0_pendingShockDamage > 0.f && x400_25_alive) - { - CDamageInfo dInfo({{EWeaponType::Wave}, x3f0_pendingShockDamage, 0.f, 0.f}, dt); - mgr.ApplyDamage(kInvalidUniqueId, GetUniqueId(), kInvalidUniqueId, dInfo, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); - } - } - else - { - if (x3f0_pendingShockDamage != 0.f) - { - x450_bodyController->StopElectrocution(); - mgr.GetActorModelParticles()->StopElectric(*this); - } - } - } - - if (x450_bodyController->IsOnFire()) - { - if (x400_25_alive) - { - mgr.GetActorModelParticles()->LightDudeOnFire(*this); - CDamageInfo dInfo({{EWeaponType::Plasma}, x3ec_pendingFireDamage, 0.f, 0.f}, dt); - mgr.ApplyDamage(kInvalidUniqueId, GetUniqueId(), kInvalidUniqueId, dInfo, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); - } - } - else - { - if (x3ec_pendingFireDamage > 0.f) - x3ec_pendingFireDamage = 0.f; - if (x450_bodyController->IsFrozen()) - mgr.GetActorModelParticles()->StopThermalHotParticles(*this); - } - - if (x401_27_phazingOut || x401_28_burning) - x3e8_alphaDelta = -0.33333334f; - - if (x401_30_pendingDeath) - { - x401_30_pendingDeath = false; - Death(mgr, GetTransform().frontVector(), EScriptObjectState::DeathRattle); - } - - float thinkDt = (x400_25_alive ? dt : dt * CalcDyingThinkRate()); - - x450_bodyController->Update(thinkDt, mgr); - x450_bodyController->MultiplyPlaybackRate(x3b4_speed); - SAdvancementDeltas deltas = UpdateAnimation(thinkDt, mgr, !x450_bodyController->IsFrozen()); - x434_posDelta = deltas.x0_posDelta; - x440_rotDelta = deltas.xc_rotDelta; - - if (x403_25_enableStateMachine && x450_bodyController->GetPercentageFrozen() < 1.f) - x330_stateMachineState.Update(mgr, *this, thinkDt); - - ThinkAboutMove(thinkDt); - - x460_knockBackController.Update(thinkDt, mgr, *this); - x4e4_latestPredictedTranslation = GetTranslation() + PredictMotion(thinkDt).x0_translation; - x328_26_longJump = false; - if (x420_curDamageRemTime > 0.f) - x420_curDamageRemTime -= dt; - - if (x401_28_burning && x3f4_burnThinkRateTimer > dt) - x3f4_burnThinkRateTimer -= dt; - - xd0_damageMag = x50c_baseDamageMag; - UpdateDamageColor(dt); - - if (!x450_bodyController->IsFrozen()) - { - if (x3a0_latestLeashPosition == zeus::CVector3f()) - x3a0_latestLeashPosition = GetTranslation(); - - if (x3cc_playerLeashRadius != 0.f) - { - zeus::CVector3f diffVec = (GetTranslation() - mgr.GetPlayer().GetTranslation()); - if (diffVec.magSquared() > x3cc_playerLeashRadius) - x3d4_curPlayerLeashTime += dt; - else - x3d4_curPlayerLeashTime = 0.f; - } - } - else - { - RemoveEmitter(); - } - - if (x2f8_waypointPauseRemTime > 0.f) - x2f8_waypointPauseRemTime -= dt; -} - -void CPatterned::Touch(CActor& act, CStateManager& mgr) -{ - if (!x400_25_alive) - return; - - if (TCastToPtr proj = act) - { - if (mgr.GetPlayer().GetUniqueId() == proj->GetOwnerId()) - x400_24_hitByPlayerProjectile = true; - } -} - -std::experimental::optional CPatterned::GetTouchBounds() const -{ - return GetBoundingBox(); -} - -bool CPatterned::CanRenderUnsorted(const urde::CStateManager& mgr) const -{ - return x64_modelData->GetAnimationData()->GetParticleDB().AreAnySystemsDrawnWithModel() ? false : - CActor::CanRenderUnsorted(mgr); -} - -zeus::CVector3f CPatterned::GetAimPosition(const urde::CStateManager& mgr, float dt) const -{ - zeus::CVector3f offset; - if (dt > 0.f) - offset = PredictMotion(dt).x0_translation; - - CSegId segId = GetModelData()->GetAnimationData()->GetLocatorSegId("lockon_target_LCTR"sv); - if (segId != 0xFF) - { - zeus::CTransform xf = GetModelData()->GetAnimationData()->GetLocatorTransform(segId, nullptr); - zeus::CVector3f scaledOrigin = GetModelData()->GetScale() * xf.origin; - if (GetTouchBounds()) - return offset + GetTouchBounds()->clampToBox(x34_transform * scaledOrigin); - - zeus::CAABox aabox = GetBaseBoundingBox(); - - zeus::CAABox primBox(aabox.min + GetPrimitiveOffset(), aabox.max + GetPrimitiveOffset()); - - return offset + (x34_transform * primBox.clampToBox(scaledOrigin)); - } - - return offset + GetBoundingBox().center(); -} - -zeus::CTransform CPatterned::GetLctrTransform(std::string_view name) const -{ - return x34_transform * GetScaledLocatorTransform(name); -} - -zeus::CTransform CPatterned::GetLctrTransform(CSegId id) const -{ - zeus::CTransform xf = x64_modelData->GetAnimationData()->GetLocatorTransform(id, nullptr); - return x34_transform * zeus::CTransform(xf.buildMatrix3f(), x64_modelData->GetScale() * xf.origin); -} - -void CPatterned::DeathDelete(CStateManager& mgr) -{ - SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); - if (x450_bodyController->IsElectrocuting()) - { - x3f0_pendingShockDamage = 0.f; + if (x450_bodyController->IsElectrocuting()) { + mgr.GetActorModelParticles()->StartElectric(*this); + if (x3f0_pendingShockDamage > 0.f && x400_25_alive) { + CDamageInfo dInfo({{EWeaponType::Wave}, x3f0_pendingShockDamage, 0.f, 0.f}, dt); + mgr.ApplyDamage(kInvalidUniqueId, GetUniqueId(), kInvalidUniqueId, dInfo, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + } + } else { + if (x3f0_pendingShockDamage != 0.f) { x450_bodyController->StopElectrocution(); mgr.GetActorModelParticles()->StopElectric(*this); + } } - mgr.FreeScriptObject(GetUniqueId()); + } + + if (x450_bodyController->IsOnFire()) { + if (x400_25_alive) { + mgr.GetActorModelParticles()->LightDudeOnFire(*this); + CDamageInfo dInfo({{EWeaponType::Plasma}, x3ec_pendingFireDamage, 0.f, 0.f}, dt); + mgr.ApplyDamage(kInvalidUniqueId, GetUniqueId(), kInvalidUniqueId, dInfo, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + } + } else { + if (x3ec_pendingFireDamage > 0.f) + x3ec_pendingFireDamage = 0.f; + if (x450_bodyController->IsFrozen()) + mgr.GetActorModelParticles()->StopThermalHotParticles(*this); + } + + if (x401_27_phazingOut || x401_28_burning) + x3e8_alphaDelta = -0.33333334f; + + if (x401_30_pendingDeath) { + x401_30_pendingDeath = false; + Death(mgr, GetTransform().frontVector(), EScriptObjectState::DeathRattle); + } + + float thinkDt = (x400_25_alive ? dt : dt * CalcDyingThinkRate()); + + x450_bodyController->Update(thinkDt, mgr); + x450_bodyController->MultiplyPlaybackRate(x3b4_speed); + SAdvancementDeltas deltas = UpdateAnimation(thinkDt, mgr, !x450_bodyController->IsFrozen()); + x434_posDelta = deltas.x0_posDelta; + x440_rotDelta = deltas.xc_rotDelta; + + if (x403_25_enableStateMachine && x450_bodyController->GetPercentageFrozen() < 1.f) + x330_stateMachineState.Update(mgr, *this, thinkDt); + + ThinkAboutMove(thinkDt); + + x460_knockBackController.Update(thinkDt, mgr, *this); + x4e4_latestPredictedTranslation = GetTranslation() + PredictMotion(thinkDt).x0_translation; + x328_26_longJump = false; + if (x420_curDamageRemTime > 0.f) + x420_curDamageRemTime -= dt; + + if (x401_28_burning && x3f4_burnThinkRateTimer > dt) + x3f4_burnThinkRateTimer -= dt; + + xd0_damageMag = x50c_baseDamageMag; + UpdateDamageColor(dt); + + if (!x450_bodyController->IsFrozen()) { + if (x3a0_latestLeashPosition == zeus::CVector3f()) + x3a0_latestLeashPosition = GetTranslation(); + + if (x3cc_playerLeashRadius != 0.f) { + zeus::CVector3f diffVec = (GetTranslation() - mgr.GetPlayer().GetTranslation()); + if (diffVec.magSquared() > x3cc_playerLeashRadius) + x3d4_curPlayerLeashTime += dt; + else + x3d4_curPlayerLeashTime = 0.f; + } + } else { + RemoveEmitter(); + } + + if (x2f8_waypointPauseRemTime > 0.f) + x2f8_waypointPauseRemTime -= dt; } -void CPatterned::Death(CStateManager& mgr, const zeus::CVector3f& dir, EScriptObjectState state) -{ - if (x400_25_alive) - { - if (!x450_bodyController->IsOnFire()) - { - x402_25_lostMassiveFrozenHP = (x3e4_lastHP - HealthInfo(mgr)->GetHP()) >= - x3dc_frozenXDamageThreshold; - if (x402_25_lostMassiveFrozenHP && x54c_iceDeathExplosionParticle && - x450_bodyController->GetPercentageFrozen() > 0.8f) - { - x400_29_pendingMassiveFrozenDeath = true; - } - else if ((x3e4_lastHP - HealthInfo(mgr)->GetHP()) >= x3d8_xDamageThreshold) - { - x400_28_pendingMassiveDeath = true; - } - } - if (x400_28_pendingMassiveDeath || x400_29_pendingMassiveFrozenDeath) - { - if (x328_30_lookAtDeathDir && x3e0_xDamageDelay <= 0.f && dir != zeus::CVector3f::skZero) - { - SetTransform(zeus::lookAt(GetTranslation(), GetTranslation() - dir) * - zeus::CTransform::RotateX(zeus::degToRad(45.f))); - } - } - else - { - x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Dead"sv); - RemoveMaterial(EMaterialTypes::GroundCollider, mgr); - x328_25_verticalMovement = false; - } - x400_25_alive = false; - if (x450_bodyController->HasBodyState(pas::EAnimationState::Hurled) && - x450_bodyController->GetBodyType() == EBodyType::Flyer) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCHurledCmd(-dir, zeus::CVector3f::skZero)); - } - else if (x450_bodyController->HasBodyState(pas::EAnimationState::Fall)) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockDownCmd(-dir, pas::ESeverity::One)); - } - if (state != EScriptObjectState::Any) - { - SendScriptMsgs(state, mgr, EScriptObjectMessage::None); - } +void CPatterned::Touch(CActor& act, CStateManager& mgr) { + if (!x400_25_alive) + return; + + if (TCastToPtr proj = act) { + if (mgr.GetPlayer().GetUniqueId() == proj->GetOwnerId()) + x400_24_hitByPlayerProjectile = true; + } +} + +std::experimental::optional CPatterned::GetTouchBounds() const { return GetBoundingBox(); } + +bool CPatterned::CanRenderUnsorted(const urde::CStateManager& mgr) const { + return x64_modelData->GetAnimationData()->GetParticleDB().AreAnySystemsDrawnWithModel() + ? false + : CActor::CanRenderUnsorted(mgr); +} + +zeus::CVector3f CPatterned::GetAimPosition(const urde::CStateManager& mgr, float dt) const { + zeus::CVector3f offset; + if (dt > 0.f) + offset = PredictMotion(dt).x0_translation; + + CSegId segId = GetModelData()->GetAnimationData()->GetLocatorSegId("lockon_target_LCTR"sv); + if (segId != 0xFF) { + zeus::CTransform xf = GetModelData()->GetAnimationData()->GetLocatorTransform(segId, nullptr); + zeus::CVector3f scaledOrigin = GetModelData()->GetScale() * xf.origin; + if (GetTouchBounds()) + return offset + GetTouchBounds()->clampToBox(x34_transform * scaledOrigin); + + zeus::CAABox aabox = GetBaseBoundingBox(); + + zeus::CAABox primBox(aabox.min + GetPrimitiveOffset(), aabox.max + GetPrimitiveOffset()); + + return offset + (x34_transform * primBox.clampToBox(scaledOrigin)); + } + + return offset + GetBoundingBox().center(); +} + +zeus::CTransform CPatterned::GetLctrTransform(std::string_view name) const { + return x34_transform * GetScaledLocatorTransform(name); +} + +zeus::CTransform CPatterned::GetLctrTransform(CSegId id) const { + zeus::CTransform xf = x64_modelData->GetAnimationData()->GetLocatorTransform(id, nullptr); + return x34_transform * zeus::CTransform(xf.buildMatrix3f(), x64_modelData->GetScale() * xf.origin); +} + +void CPatterned::DeathDelete(CStateManager& mgr) { + SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); + if (x450_bodyController->IsElectrocuting()) { + x3f0_pendingShockDamage = 0.f; + x450_bodyController->StopElectrocution(); + mgr.GetActorModelParticles()->StopElectric(*this); + } + mgr.FreeScriptObject(GetUniqueId()); +} + +void CPatterned::Death(CStateManager& mgr, const zeus::CVector3f& dir, EScriptObjectState state) { + if (x400_25_alive) { + if (!x450_bodyController->IsOnFire()) { + x402_25_lostMassiveFrozenHP = (x3e4_lastHP - HealthInfo(mgr)->GetHP()) >= x3dc_frozenXDamageThreshold; + if (x402_25_lostMassiveFrozenHP && x54c_iceDeathExplosionParticle && + x450_bodyController->GetPercentageFrozen() > 0.8f) { + x400_29_pendingMassiveFrozenDeath = true; + } else if ((x3e4_lastHP - HealthInfo(mgr)->GetHP()) >= x3d8_xDamageThreshold) { + x400_28_pendingMassiveDeath = true; + } } + if (x400_28_pendingMassiveDeath || x400_29_pendingMassiveFrozenDeath) { + if (x328_30_lookAtDeathDir && x3e0_xDamageDelay <= 0.f && dir != zeus::CVector3f::skZero) { + SetTransform(zeus::lookAt(GetTranslation(), GetTranslation() - dir) * + zeus::CTransform::RotateX(zeus::degToRad(45.f))); + } + } else { + x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Dead"sv); + RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + x328_25_verticalMovement = false; + } + x400_25_alive = false; + if (x450_bodyController->HasBodyState(pas::EAnimationState::Hurled) && + x450_bodyController->GetBodyType() == EBodyType::Flyer) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCHurledCmd(-dir, zeus::CVector3f::skZero)); + } else if (x450_bodyController->HasBodyState(pas::EAnimationState::Fall)) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCKnockDownCmd(-dir, pas::ESeverity::One)); + } + if (state != EScriptObjectState::Any) { + SendScriptMsgs(state, mgr, EScriptObjectMessage::None); + } + } } void CPatterned::KnockBack(const zeus::CVector3f& backVec, CStateManager& mgr, const CDamageInfo& info, - EKnockBackType type, bool inDeferred, float magnitude) -{ - CHealthInfo* hInfo = HealthInfo(mgr); - if (!x401_27_phazingOut && !x401_28_burning && hInfo) - { - x460_knockBackController.KnockBack(backVec, mgr, *this, info, type, magnitude); - if (x450_bodyController->IsFrozen() && x460_knockBackController.GetActiveParms().xc_intoFreezeDur >= 0.f) - x450_bodyController->FrozenBreakout(); - switch (x460_knockBackController.GetActiveParms().x4_animFollowup) - { - case EKnockBackAnimationFollowUp::Freeze: - Freeze(mgr, zeus::CVector3f::skZero, zeus::CUnitVector3f(x34_transform.transposeRotate(backVec)), - x460_knockBackController.GetActiveParms().x8_followupDuration); - break; - case EKnockBackAnimationFollowUp::PhazeOut: - PhazeOut(mgr); - break; - case EKnockBackAnimationFollowUp::Shock: - Shock(x460_knockBackController.GetActiveParms().x8_followupDuration, -1.f); - break; - case EKnockBackAnimationFollowUp::Burn: - Burn(x460_knockBackController.GetActiveParms().x8_followupDuration, 0.25f); - break; - case EKnockBackAnimationFollowUp::LaggedBurnDeath: - x401_29_laggedBurnDeath = true; - case EKnockBackAnimationFollowUp::BurnDeath: - Burn(x460_knockBackController.GetActiveParms().x8_followupDuration, -1.f); - Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle); - x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false; - x400_27_fadeToDeath = x401_28_burning = true; - x3f4_burnThinkRateTimer = 1.5f; - x402_29_drawParticles = false; - x450_bodyController->DouseFlames(); - mgr.GetActorModelParticles()->StopThermalHotParticles(*this); - mgr.GetActorModelParticles()->StartBurnDeath(*this); - if (!x401_29_laggedBurnDeath) - { - mgr.GetActorModelParticles()->EnsureFirePopLoaded(*this); - mgr.GetActorModelParticles()->EnsureIceBreakLoaded(*this); - } - break; - case EKnockBackAnimationFollowUp::Death: - Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle); - break; - case EKnockBackAnimationFollowUp::ExplodeDeath: - Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle); - if (GetDeathExplosionParticle() || x530_deathExplosionElectric) - MassiveDeath(mgr); - else if (x450_bodyController->IsFrozen()) - x450_bodyController->FrozenBreakout(); - break; - case EKnockBackAnimationFollowUp::IceDeath: - Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle); - if (x54c_iceDeathExplosionParticle) - MassiveFrozenDeath(mgr); - else if (x450_bodyController->IsFrozen()) - x450_bodyController->FrozenBreakout(); - default: - break; - } + EKnockBackType type, bool inDeferred, float magnitude) { + CHealthInfo* hInfo = HealthInfo(mgr); + if (!x401_27_phazingOut && !x401_28_burning && hInfo) { + x460_knockBackController.KnockBack(backVec, mgr, *this, info, type, magnitude); + if (x450_bodyController->IsFrozen() && x460_knockBackController.GetActiveParms().xc_intoFreezeDur >= 0.f) + x450_bodyController->FrozenBreakout(); + switch (x460_knockBackController.GetActiveParms().x4_animFollowup) { + case EKnockBackAnimationFollowUp::Freeze: + Freeze(mgr, zeus::CVector3f::skZero, zeus::CUnitVector3f(x34_transform.transposeRotate(backVec)), + x460_knockBackController.GetActiveParms().x8_followupDuration); + break; + case EKnockBackAnimationFollowUp::PhazeOut: + PhazeOut(mgr); + break; + case EKnockBackAnimationFollowUp::Shock: + Shock(x460_knockBackController.GetActiveParms().x8_followupDuration, -1.f); + break; + case EKnockBackAnimationFollowUp::Burn: + Burn(x460_knockBackController.GetActiveParms().x8_followupDuration, 0.25f); + break; + case EKnockBackAnimationFollowUp::LaggedBurnDeath: + x401_29_laggedBurnDeath = true; + case EKnockBackAnimationFollowUp::BurnDeath: + Burn(x460_knockBackController.GetActiveParms().x8_followupDuration, -1.f); + Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle); + x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false; + x400_27_fadeToDeath = x401_28_burning = true; + x3f4_burnThinkRateTimer = 1.5f; + x402_29_drawParticles = false; + x450_bodyController->DouseFlames(); + mgr.GetActorModelParticles()->StopThermalHotParticles(*this); + mgr.GetActorModelParticles()->StartBurnDeath(*this); + if (!x401_29_laggedBurnDeath) { + mgr.GetActorModelParticles()->EnsureFirePopLoaded(*this); + mgr.GetActorModelParticles()->EnsureIceBreakLoaded(*this); + } + break; + case EKnockBackAnimationFollowUp::Death: + Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle); + break; + case EKnockBackAnimationFollowUp::ExplodeDeath: + Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle); + if (GetDeathExplosionParticle() || x530_deathExplosionElectric) + MassiveDeath(mgr); + else if (x450_bodyController->IsFrozen()) + x450_bodyController->FrozenBreakout(); + break; + case EKnockBackAnimationFollowUp::IceDeath: + Death(mgr, zeus::CVector3f::skZero, EScriptObjectState::DeathRattle); + if (x54c_iceDeathExplosionParticle) + MassiveFrozenDeath(mgr); + else if (x450_bodyController->IsFrozen()) + x450_bodyController->FrozenBreakout(); + default: + break; } + } } -void CPatterned::TakeDamage(const zeus::CVector3f&, float arg) -{ - x428_damageCooldownTimer = 0.33f; +void CPatterned::TakeDamage(const zeus::CVector3f&, float arg) { x428_damageCooldownTimer = 0.33f; } + +bool CPatterned::FixedRandom(CStateManager&, float arg) { + return x330_stateMachineState.GetRandom() < x330_stateMachineState.x14_; } -bool CPatterned::FixedRandom(CStateManager&, float arg) -{ - return x330_stateMachineState.GetRandom() < x330_stateMachineState.x14_; +bool CPatterned::Random(CStateManager&, float arg) { return x330_stateMachineState.GetRandom() < arg; } + +bool CPatterned::CodeTrigger(CStateManager&, float arg) { return x330_stateMachineState.x18_24_codeTrigger; } + +bool CPatterned::FixedDelay(CStateManager&, float arg) { + return x330_stateMachineState.GetTime() > x330_stateMachineState.GetDelay(); } -bool CPatterned::Random(CStateManager&, float arg) -{ - return x330_stateMachineState.GetRandom() < arg; +bool CPatterned::RandomDelay(CStateManager&, float arg) { + return x330_stateMachineState.GetTime() > arg * x330_stateMachineState.GetRandom(); } -bool CPatterned::CodeTrigger(CStateManager&, float arg) -{ - return x330_stateMachineState.x18_24_codeTrigger; +bool CPatterned::Delay(CStateManager&, float arg) { return x330_stateMachineState.GetTime() > arg; } + +bool CPatterned::PatrolPathOver(CStateManager&, float arg) { return x2dc_destObj == kInvalidUniqueId; } + +bool CPatterned::Stuck(CStateManager&, float arg) { return x4f0_predictedLeashTime > 0.2f; } + +bool CPatterned::AnimOver(CStateManager&, float arg) { return x32c_animState == EAnimState::Over; } + +bool CPatterned::InPosition(CStateManager&, float arg) { return x328_24_inPosition; } + +bool CPatterned::HasPatrolPath(CStateManager& mgr, float arg) { + return GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow) != kInvalidUniqueId; } -bool CPatterned::FixedDelay(CStateManager&, float arg) -{ - return x330_stateMachineState.GetTime() > x330_stateMachineState.GetDelay(); +bool CPatterned::Attacked(CStateManager&, float arg) { return x400_24_hitByPlayerProjectile; } + +bool CPatterned::PatternShagged(CStateManager&, float arg) { return x400_30_patternShagged; } + +bool CPatterned::PatternOver(CStateManager&, float arg) { return x38c_patterns.size() <= x39c_curPattern; } + +bool CPatterned::HasRetreatPattern(CStateManager& mgr, float arg) { + return GetWaypointForState(mgr, EScriptObjectState::Retreat, EScriptObjectMessage::Follow) != kInvalidUniqueId; } -bool CPatterned::RandomDelay(CStateManager&, float arg) -{ - return x330_stateMachineState.GetTime() > arg * x330_stateMachineState.GetRandom(); +bool CPatterned::HasAttackPattern(CStateManager& mgr, float arg) { + return GetWaypointForState(mgr, EScriptObjectState::Attack, EScriptObjectMessage::Follow) != kInvalidUniqueId; } -bool CPatterned::Delay(CStateManager&, float arg) -{ - return x330_stateMachineState.GetTime() > arg; -} - -bool CPatterned::PatrolPathOver(CStateManager&, float arg) -{ - return x2dc_destObj == kInvalidUniqueId; -} - -bool CPatterned::Stuck(CStateManager&, float arg) -{ - return x4f0_predictedLeashTime > 0.2f; -} - -bool CPatterned::AnimOver(CStateManager&, float arg) -{ - return x32c_animState == EAnimState::Over; -} - -bool CPatterned::InPosition(CStateManager&, float arg) -{ - return x328_24_inPosition; -} - -bool CPatterned::HasPatrolPath(CStateManager& mgr, float arg) -{ - return GetWaypointForState(mgr, EScriptObjectState::Patrol, - EScriptObjectMessage::Follow) != kInvalidUniqueId; -} - -bool CPatterned::Attacked(CStateManager&, float arg) -{ - return x400_24_hitByPlayerProjectile; -} - -bool CPatterned::PatternShagged(CStateManager&, float arg) -{ - return x400_30_patternShagged; -} - -bool CPatterned::PatternOver(CStateManager&, float arg) -{ - return x38c_patterns.size() <= x39c_curPattern; -} - -bool CPatterned::HasRetreatPattern(CStateManager& mgr, float arg) -{ - return GetWaypointForState(mgr, EScriptObjectState::Retreat, - EScriptObjectMessage::Follow) != kInvalidUniqueId; -} - -bool CPatterned::HasAttackPattern(CStateManager& mgr, float arg) -{ - return GetWaypointForState(mgr, EScriptObjectState::Attack, - EScriptObjectMessage::Follow) != kInvalidUniqueId; -} - -bool CPatterned::NoPathNodes(CStateManager&, float arg) -{ - if (CPathFindSearch* search = GetSearchPath()) - return search->OnPath(GetTranslation()) != CPathFindSearch::EResult::Success; - return true; +bool CPatterned::NoPathNodes(CStateManager&, float arg) { + if (CPathFindSearch* search = GetSearchPath()) + return search->OnPath(GetTranslation()) != CPathFindSearch::EResult::Success; + return true; } static const float skActorApproachDistance = 3.f; -bool CPatterned::PathShagged(CStateManager&, float arg) -{ - if (CPathFindSearch* search = GetSearchPath()) - { - if (search->IsShagged()) - return true; - if (search->GetCurrentWaypoint() > 0 && x401_24_pathOverCount == 0) - { - zeus::CVector3f origPoint = GetTranslation() + 0.3f * zeus::CVector3f::skUp; - zeus::CVector3f point = origPoint; - search->GetSplinePoint(point, GetTranslation()); - return (point - origPoint).magSquared() > 4.f * - skActorApproachDistance * skActorApproachDistance; - } +bool CPatterned::PathShagged(CStateManager&, float arg) { + if (CPathFindSearch* search = GetSearchPath()) { + if (search->IsShagged()) + return true; + if (search->GetCurrentWaypoint() > 0 && x401_24_pathOverCount == 0) { + zeus::CVector3f origPoint = GetTranslation() + 0.3f * zeus::CVector3f::skUp; + zeus::CVector3f point = origPoint; + search->GetSplinePoint(point, GetTranslation()); + return (point - origPoint).magSquared() > 4.f * skActorApproachDistance * skActorApproachDistance; } - return false; + } + return false; } -bool CPatterned::PathFound(CStateManager&, float arg) -{ - if (CPathFindSearch* search = GetSearchPath()) - if (!search->IsShagged()) - return true; - return false; +bool CPatterned::PathFound(CStateManager&, float arg) { + if (CPathFindSearch* search = GetSearchPath()) + if (!search->IsShagged()) + return true; + return false; } -bool CPatterned::PathOver(CStateManager&, float arg) -{ - if (CPathFindSearch* search = GetSearchPath()) - if (x328_25_verticalMovement || x328_27_onGround) - if (!search->IsShagged() && search->IsOver()) - return true; - return false; -} - -bool CPatterned::Landed(CStateManager&, float arg) -{ - bool ret = x328_27_onGround && !x328_28_prevOnGround; - x328_28_prevOnGround = x328_27_onGround; - return ret; -} - -bool CPatterned::PlayerSpot(CStateManager& mgr, float arg) -{ - if (mgr.GetPlayer().GetMorphballTransitionState() == - CPlayer::EPlayerMorphBallState::Unmorphed) - { - zeus::CVector3f aimPosition = mgr.GetPlayer().GetAimPosition(mgr, 0.f); - zeus::CVector3f center = GetBoundingBox().center(); - zeus::CVector3f aimToCenter = center - aimPosition; - float aimToCenterMag = aimToCenter.magnitude(); - zeus::CVector3f aimToCenterNorm = aimToCenter * (1.f / aimToCenterMag); - zeus::CVector3f screenSpace = mgr.GetCameraManager()-> - GetFirstPersonCamera()->ConvertToScreenSpace(center); - if (screenSpace.z() > 0.f && - screenSpace.x() * screenSpace.x() < 1.f && - screenSpace.y() * screenSpace.y() < 1.f) - { - CRayCastResult res = - mgr.RayStaticIntersection(aimPosition, aimToCenterNorm, aimToCenterMag, - CMaterialFilter::MakeInclude(EMaterialTypes::Solid)); - return res.IsInvalid(); - } - } - return false; -} - -bool CPatterned::SpotPlayer(CStateManager& mgr, float arg) -{ - zeus::CVector3f gunToPlayer = mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetGunEyePos(); - float lookDot = gunToPlayer.dot(x34_transform.basis[1]); - if (lookDot > 0.f) - return lookDot * lookDot > gunToPlayer.magSquared() * x3c4_detectionAngle; - return false; -} - -bool CPatterned::Leash(CStateManager&, float arg) -{ - bool ret = x3d4_curPlayerLeashTime > x3d0_playerLeashTime; - if (ret) - { - float posToLeashMagSq = (x3a0_latestLeashPosition - GetTranslation()).magSquared(); - if (posToLeashMagSq > x3c8_leashRadius * x3c8_leashRadius) - return true; - } - return ret; -} - -bool CPatterned::InDetectionRange(CStateManager& mgr, float arg) -{ - zeus::CVector3f delta = mgr.GetPlayer().GetTranslation() - GetTranslation(); - if (delta.magSquared() < x3bc_detectionRange * x3bc_detectionRange) - { - if (x3c0_detectionHeightRange > 0.f) - return delta.z() * delta.z() < x3c0_detectionHeightRange * x3c0_detectionHeightRange; +bool CPatterned::PathOver(CStateManager&, float arg) { + if (CPathFindSearch* search = GetSearchPath()) + if (x328_25_verticalMovement || x328_27_onGround) + if (!search->IsShagged() && search->IsOver()) return true; + return false; +} + +bool CPatterned::Landed(CStateManager&, float arg) { + bool ret = x328_27_onGround && !x328_28_prevOnGround; + x328_28_prevOnGround = x328_27_onGround; + return ret; +} + +bool CPatterned::PlayerSpot(CStateManager& mgr, float arg) { + if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) { + zeus::CVector3f aimPosition = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + zeus::CVector3f center = GetBoundingBox().center(); + zeus::CVector3f aimToCenter = center - aimPosition; + float aimToCenterMag = aimToCenter.magnitude(); + zeus::CVector3f aimToCenterNorm = aimToCenter * (1.f / aimToCenterMag); + zeus::CVector3f screenSpace = mgr.GetCameraManager()->GetFirstPersonCamera()->ConvertToScreenSpace(center); + if (screenSpace.z() > 0.f && screenSpace.x() * screenSpace.x() < 1.f && screenSpace.y() * screenSpace.y() < 1.f) { + CRayCastResult res = mgr.RayStaticIntersection(aimPosition, aimToCenterNorm, aimToCenterMag, + CMaterialFilter::MakeInclude(EMaterialTypes::Solid)); + return res.IsInvalid(); } - return false; + } + return false; } -bool CPatterned::InMaxRange(CStateManager& mgr, float arg) -{ - return (mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < - x300_maxAttackRange * x300_maxAttackRange; +bool CPatterned::SpotPlayer(CStateManager& mgr, float arg) { + zeus::CVector3f gunToPlayer = mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetGunEyePos(); + float lookDot = gunToPlayer.dot(x34_transform.basis[1]); + if (lookDot > 0.f) + return lookDot * lookDot > gunToPlayer.magSquared() * x3c4_detectionAngle; + return false; } -bool CPatterned::TooClose(CStateManager& mgr, float arg) -{ - return (mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < - x2fc_minAttackRange * x2fc_minAttackRange; +bool CPatterned::Leash(CStateManager&, float arg) { + bool ret = x3d4_curPlayerLeashTime > x3d0_playerLeashTime; + if (ret) { + float posToLeashMagSq = (x3a0_latestLeashPosition - GetTranslation()).magSquared(); + if (posToLeashMagSq > x3c8_leashRadius * x3c8_leashRadius) + return true; + } + return ret; } -bool CPatterned::InRange(CStateManager& mgr, float arg) -{ - float range = 0.5f * (x2fc_minAttackRange + x300_maxAttackRange); - return (mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < range * range; +bool CPatterned::InDetectionRange(CStateManager& mgr, float arg) { + zeus::CVector3f delta = mgr.GetPlayer().GetTranslation() - GetTranslation(); + if (delta.magSquared() < x3bc_detectionRange * x3bc_detectionRange) { + if (x3c0_detectionHeightRange > 0.f) + return delta.z() * delta.z() < x3c0_detectionHeightRange * x3c0_detectionHeightRange; + return true; + } + return false; } -bool CPatterned::OffLine(CStateManager&, float arg) -{ - zeus::CVector3f curLine = GetTranslation() - x2ec_reflectedDestPos; - zeus::CVector3f pathLine = x2e0_destPos - x2ec_reflectedDestPos; - float distSq; - if (curLine.dot(pathLine) <= 0.f) - { - distSq = curLine.magSquared(); - } - else - { - pathLine.normalize(); - distSq = (curLine - pathLine.dot(curLine) * pathLine).magSquared(); - zeus::CVector3f delta = GetTranslation() - x2e0_destPos; - if (pathLine.dot(delta) > 0.f) - distSq = delta.magSquared(); - } - return distSq > arg * arg; +bool CPatterned::InMaxRange(CStateManager& mgr, float arg) { + return (mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < x300_maxAttackRange * x300_maxAttackRange; } -void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float dt) -{ - if (CPathFindSearch* search = GetSearchPath()) - { - u32 curWp = search->GetCurrentWaypoint(); - const auto& waypoints = search->GetWaypoints(); - switch (msg) - { - case EStateMsg::Activate: - { - if (search->Search(GetTranslation(), x2e0_destPos) == CPathFindSearch::EResult::Success) - { - x2ec_reflectedDestPos = GetTranslation(); - zeus::CVector3f destPos; - if (curWp + 1 < waypoints.size()) - destPos = waypoints[curWp + 1]; - else - destPos = waypoints[curWp]; - SetDestPos(destPos); - x328_24_inPosition = false; - ApproachDest(mgr); - } - break; - } - case EStateMsg::Update: - { - if (curWp < waypoints.size() - 1) - { - if (x328_24_inPosition || x328_27_onGround) - x401_24_pathOverCount += 1; - zeus::CVector3f biasedPos = GetTranslation() + 0.3f * zeus::CVector3f::skUp; - x2ec_reflectedDestPos = biasedPos - (x2e0_destPos - biasedPos); - ApproachDest(mgr); - zeus::CVector3f biasedForward = x34_transform.basis[1] * x64_modelData->GetScale().y() + biasedPos; - search->GetSplinePointWithLookahead(biasedForward, biasedPos, 3.f * x64_modelData->GetScale().y()); - SetDestPos(biasedForward); - if (search->SegmentOver(biasedPos)) - search->SetCurrentWaypoint(search->GetCurrentWaypoint() + 1); - } - break; - } - default: - break; - } - } +bool CPatterned::TooClose(CStateManager& mgr, float arg) { + return (mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < x2fc_minAttackRange * x2fc_minAttackRange; } -void CPatterned::Dead(CStateManager& mgr, EStateMsg msg, float dt) -{ - switch (msg) - { - case EStateMsg::Activate: - x31c_faceVec = zeus::CVector3f::skZero; - break; - case EStateMsg::Update: - x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Die)); - if (!x400_27_fadeToDeath) - { - if (x450_bodyController->GetBodyStateInfo().GetCurrentState()->IsDead()) - { - x400_27_fadeToDeath = true; - x3e8_alphaDelta = -0.333333f; - RemoveMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, - EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); - AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); - } - } - break; - default: - break; - } +bool CPatterned::InRange(CStateManager& mgr, float arg) { + float range = 0.5f * (x2fc_minAttackRange + x300_maxAttackRange); + return (mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < range * range; } -void CPatterned::TargetPlayer(CStateManager& mgr, EStateMsg msg, float dt) -{ - if (msg == EStateMsg::Activate) - { - x2dc_destObj = mgr.GetPlayer().GetUniqueId(); - SetDestPos(mgr.GetPlayer().GetTranslation()); +bool CPatterned::OffLine(CStateManager&, float arg) { + zeus::CVector3f curLine = GetTranslation() - x2ec_reflectedDestPos; + zeus::CVector3f pathLine = x2e0_destPos - x2ec_reflectedDestPos; + float distSq; + if (curLine.dot(pathLine) <= 0.f) { + distSq = curLine.magSquared(); + } else { + pathLine.normalize(); + distSq = (curLine - pathLine.dot(curLine) * pathLine).magSquared(); + zeus::CVector3f delta = GetTranslation() - x2e0_destPos; + if (pathLine.dot(delta) > 0.f) + distSq = delta.magSquared(); + } + return distSq > arg * arg; +} + +void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float dt) { + if (CPathFindSearch* search = GetSearchPath()) { + u32 curWp = search->GetCurrentWaypoint(); + const auto& waypoints = search->GetWaypoints(); + switch (msg) { + case EStateMsg::Activate: { + if (search->Search(GetTranslation(), x2e0_destPos) == CPathFindSearch::EResult::Success) { x2ec_reflectedDestPos = GetTranslation(); - x328_24_inPosition = false; - } -} - -void CPatterned::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) -{ - if (msg == EStateMsg::Activate) - { - x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); - if (TCastToConstPtr act = mgr.GetObjectById(x2dc_destObj)) - SetDestPos(act->GetTranslation()); - x2ec_reflectedDestPos = GetTranslation(); - x328_24_inPosition = false; - } -} - -void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float dt) -{ - switch (msg) - { - case EStateMsg::Activate: - SetupPattern(mgr); - if (x328_29_noPatternShagging || !IsPatternObstructed(mgr, GetTranslation(), x2e0_destPos)) - { - ApproachDest(mgr); - } + zeus::CVector3f destPos; + if (curWp + 1 < waypoints.size()) + destPos = waypoints[curWp + 1]; else - { - x39c_curPattern = x38c_patterns.size(); - x400_30_patternShagged = true; - } - break; - case EStateMsg::Update: - if (x328_24_inPosition) - { - x39c_curPattern += 1; - UpdatePatternDestPos(mgr); - if (!x328_29_noPatternShagging && IsPatternObstructed(mgr, GetTranslation(), x2e0_destPos)) - { - x39c_curPattern = x38c_patterns.size(); - x400_30_patternShagged = true; - } - else if (x39c_curPattern < x38c_patterns.size()) - { - x2ec_reflectedDestPos = GetTranslation(); - x328_24_inPosition = false; - x3b0_moveSpeed = x38c_patterns[x39c_curPattern].GetSpeed(); - x380_behaviour = EBehaviour(x38c_patterns[x39c_curPattern].GetBehaviour()); - x30c_behaviourOrient = EBehaviourOrient(x38c_patterns[x39c_curPattern].GetBehaviourOrient()); - x384_behaviourModifiers = EBehaviourModifiers(x38c_patterns[x39c_curPattern].GetBehaviourModifiers()); - } - } - else - { - UpdatePatternDestPos(mgr); - } + destPos = waypoints[curWp]; + SetDestPos(destPos); + x328_24_inPosition = false; ApproachDest(mgr); - break; - case EStateMsg::Deactivate: - x38c_patterns.clear(); - x400_30_patternShagged = false; + } + break; } + case EStateMsg::Update: { + if (curWp < waypoints.size() - 1) { + if (x328_24_inPosition || x328_27_onGround) + x401_24_pathOverCount += 1; + zeus::CVector3f biasedPos = GetTranslation() + 0.3f * zeus::CVector3f::skUp; + x2ec_reflectedDestPos = biasedPos - (x2e0_destPos - biasedPos); + ApproachDest(mgr); + zeus::CVector3f biasedForward = x34_transform.basis[1] * x64_modelData->GetScale().y() + biasedPos; + search->GetSplinePointWithLookahead(biasedForward, biasedPos, 3.f * x64_modelData->GetScale().y()); + SetDestPos(biasedForward); + if (search->SegmentOver(biasedPos)) + search->SetCurrentWaypoint(search->GetCurrentWaypoint() + 1); + } + break; + } + default: + break; + } + } } -void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float dt) -{ - switch (msg) - { - case EStateMsg::Activate: - if (x3ac_lastPatrolDest == kInvalidUniqueId) - { - x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); - x30c_behaviourOrient = EBehaviourOrient::MoveDir; - x3b0_moveSpeed = 1.f; - if (x2dc_destObj != kInvalidUniqueId) - { - if (TCastToConstPtr wp = mgr.GetObjectById(x2dc_destObj)) - { - x30c_behaviourOrient = EBehaviourOrient(wp->GetBehaviourOrient()); - x3b0_moveSpeed = wp->GetSpeed(); - } - } - } - else - { - x2dc_destObj = x3ac_lastPatrolDest; - } +void CPatterned::Dead(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + x31c_faceVec = zeus::CVector3f::skZero; + break; + case EStateMsg::Update: + x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Die)); + if (!x400_27_fadeToDeath) { + if (x450_bodyController->GetBodyStateInfo().GetCurrentState()->IsDead()) { + x400_27_fadeToDeath = true; + x3e8_alphaDelta = -0.333333f; + RemoveMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, EMaterialTypes::Target, EMaterialTypes::Orbit, + mgr); + AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); + } + } + break; + default: + break; + } +} + +void CPatterned::TargetPlayer(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x2dc_destObj = mgr.GetPlayer().GetUniqueId(); + SetDestPos(mgr.GetPlayer().GetTranslation()); + x2ec_reflectedDestPos = GetTranslation(); + x328_24_inPosition = false; + } +} + +void CPatterned::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) { + if (msg == EStateMsg::Activate) { + x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); + if (TCastToConstPtr act = mgr.GetObjectById(x2dc_destObj)) + SetDestPos(act->GetTranslation()); + x2ec_reflectedDestPos = GetTranslation(); + x328_24_inPosition = false; + } +} + +void CPatterned::FollowPattern(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + SetupPattern(mgr); + if (x328_29_noPatternShagging || !IsPatternObstructed(mgr, GetTranslation(), x2e0_destPos)) { + ApproachDest(mgr); + } else { + x39c_curPattern = x38c_patterns.size(); + x400_30_patternShagged = true; + } + break; + case EStateMsg::Update: + if (x328_24_inPosition) { + x39c_curPattern += 1; + UpdatePatternDestPos(mgr); + if (!x328_29_noPatternShagging && IsPatternObstructed(mgr, GetTranslation(), x2e0_destPos)) { + x39c_curPattern = x38c_patterns.size(); + x400_30_patternShagged = true; + } else if (x39c_curPattern < x38c_patterns.size()) { x2ec_reflectedDestPos = GetTranslation(); x328_24_inPosition = false; + x3b0_moveSpeed = x38c_patterns[x39c_curPattern].GetSpeed(); + x380_behaviour = EBehaviour(x38c_patterns[x39c_curPattern].GetBehaviour()); + x30c_behaviourOrient = EBehaviourOrient(x38c_patterns[x39c_curPattern].GetBehaviourOrient()); + x384_behaviourModifiers = EBehaviourModifiers(x38c_patterns[x39c_curPattern].GetBehaviourModifiers()); + } + } else { + UpdatePatternDestPos(mgr); + } + ApproachDest(mgr); + break; + case EStateMsg::Deactivate: + x38c_patterns.clear(); + x400_30_patternShagged = false; + } +} + +void CPatterned::Patrol(CStateManager& mgr, EStateMsg msg, float dt) { + switch (msg) { + case EStateMsg::Activate: + if (x3ac_lastPatrolDest == kInvalidUniqueId) { + x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Patrol, EScriptObjectMessage::Follow); + x30c_behaviourOrient = EBehaviourOrient::MoveDir; + x3b0_moveSpeed = 1.f; + if (x2dc_destObj != kInvalidUniqueId) { + if (TCastToConstPtr wp = mgr.GetObjectById(x2dc_destObj)) { + x30c_behaviourOrient = EBehaviourOrient(wp->GetBehaviourOrient()); + x3b0_moveSpeed = wp->GetSpeed(); + } + } + } else { + x2dc_destObj = x3ac_lastPatrolDest; + } + x2ec_reflectedDestPos = GetTranslation(); + x328_24_inPosition = false; + x2d8_patrolState = EPatrolState::Patrol; + x2f8_waypointPauseRemTime = 0.f; + break; + case EStateMsg::Update: + switch (x2d8_patrolState) { + case EPatrolState::Patrol: + if (x328_24_inPosition && x2dc_destObj != kInvalidUniqueId) { + if (TCastToConstPtr wp = mgr.GetObjectById(x2dc_destObj)) { + if (wp->GetPause() > 0.f) { + x2f8_waypointPauseRemTime = wp->GetPause(); + x2d8_patrolState = EPatrolState::Pause; + } + } + } + if (x2dc_destObj == kInvalidUniqueId) + x2d8_patrolState = EPatrolState::Done; + UpdateDest(mgr); + ApproachDest(mgr); + break; + case EPatrolState::Pause: + if (x2f8_waypointPauseRemTime <= 0.f) x2d8_patrolState = EPatrolState::Patrol; - x2f8_waypointPauseRemTime = 0.f; - break; - case EStateMsg::Update: - switch (x2d8_patrolState) - { - case EPatrolState::Patrol: - if (x328_24_inPosition && x2dc_destObj != kInvalidUniqueId) - { - if (TCastToConstPtr wp = mgr.GetObjectById(x2dc_destObj)) - { - if (wp->GetPause() > 0.f) - { - x2f8_waypointPauseRemTime = wp->GetPause(); - x2d8_patrolState = EPatrolState::Pause; - } - } - } - if (x2dc_destObj == kInvalidUniqueId) - x2d8_patrolState = EPatrolState::Done; - UpdateDest(mgr); - ApproachDest(mgr); - break; - case EPatrolState::Pause: - if (x2f8_waypointPauseRemTime <= 0.f) - x2d8_patrolState = EPatrolState::Patrol; - break; - case EPatrolState::Done: - if (x2dc_destObj != kInvalidUniqueId) - x2d8_patrolState = EPatrolState::Patrol; - break; - default: - break; - } - break; - case EStateMsg::Deactivate: - x3ac_lastPatrolDest = x2dc_destObj; - x2d8_patrolState = EPatrolState::Invalid; - break; + break; + case EPatrolState::Done: + if (x2dc_destObj != kInvalidUniqueId) + x2d8_patrolState = EPatrolState::Patrol; + break; default: - break; + break; } + break; + case EStateMsg::Deactivate: + x3ac_lastPatrolDest = x2dc_destObj; + x2d8_patrolState = EPatrolState::Invalid; + break; + default: + break; + } } -void CPatterned::TryCommand(CStateManager& mgr, pas::EAnimationState state, - CPatternedTryFunc func, int arg) -{ - if (state == x450_bodyController->GetCurrentStateId()) - x32c_animState = EAnimState::Repeat; - else if (x32c_animState == EAnimState::One) - (this->*func)(mgr, arg); +void CPatterned::TryCommand(CStateManager& mgr, pas::EAnimationState state, CPatternedTryFunc func, int arg) { + if (state == x450_bodyController->GetCurrentStateId()) + x32c_animState = EAnimState::Repeat; + else if (x32c_animState == EAnimState::One) + (this->*func)(mgr, arg); + else + x32c_animState = EAnimState::Over; +} + +void CPatterned::TryLoopReaction(CStateManager& mgr, int arg) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType(arg))); +} + +void CPatterned::TryProjectileAttack(CStateManager&, int arg) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCProjectileAttackCmd(pas::ESeverity(arg), x2e0_destPos, false)); +} + +void CPatterned::TryGenerate(CStateManager& mgr, int arg) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType(arg), x2e0_destPos, true)); +} + +void CPatterned::BuildBodyController(EBodyType bodyType) { + if (x450_bodyController) + return; + + x450_bodyController.reset(new CBodyController(*this, x3b8_turnSpeed, bodyType)); + auto anim = + x450_bodyController->GetPASDatabase().FindBestAnimation(CPASAnimParmData(24, CPASAnimParm::FromEnum(0)), -1); + x460_knockBackController.x81_26_enableShock = anim.first > 0.f; +} + +void CPatterned::GenerateDeathExplosion(CStateManager& mgr) { + if (auto particle = GetDeathExplosionParticle()) { + zeus::CTransform xf(GetTransform()); + xf.origin = GetTransform() * (x64_modelData->GetScale() * x514_deathExplosionOffset); + CExplosion* explo = new CExplosion(*particle, mgr.AllocateUniqueId(), true, + CEntityInfo(GetAreaIdAlways(), CEntity::NullConnectionList), "", xf, 1, + zeus::CVector3f::skOne, zeus::CColor::skWhite); + mgr.AddObject(explo); + } else if (x530_deathExplosionElectric) { + zeus::CTransform xf(GetTransform()); + xf.origin = GetTransform() * (x64_modelData->GetScale() * x514_deathExplosionOffset); + CExplosion* explo = new CExplosion(*x530_deathExplosionElectric, mgr.AllocateUniqueId(), true, + CEntityInfo(GetAreaIdAlways(), CEntity::NullConnectionList), "", xf, 1, + zeus::CVector3f::skOne, zeus::CColor::skWhite); + mgr.AddObject(explo); + } +} + +void CPatterned::MassiveDeath(CStateManager& mgr) { + CSfxManager::AddEmitter(x454_deathSfx, GetTranslation(), zeus::CVector3f::skZero, true, false, 0x7f, kInvalidAreaId); + if (!x401_28_burning) { + SendScriptMsgs(EScriptObjectState::MassiveDeath, mgr, EScriptObjectMessage::None); + GenerateDeathExplosion(mgr); + } + DeathDelete(mgr); + x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false; +} + +void CPatterned::GenerateIceDeathExplosion(CStateManager& mgr) { + if (x54c_iceDeathExplosionParticle) { + zeus::CTransform xf(GetTransform()); + xf.origin = GetTransform() * (x64_modelData->GetScale() * x540_iceDeathExplosionOffset); + CExplosion* explo = new CExplosion(*x54c_iceDeathExplosionParticle, mgr.AllocateUniqueId(), true, + CEntityInfo(GetAreaIdAlways(), CEntity::NullConnectionList), "", xf, 1, + zeus::CVector3f::skOne, zeus::CColor::skWhite); + mgr.AddObject(explo); + } +} + +void CPatterned::MassiveFrozenDeath(CStateManager& mgr) { + if (x458_iceShatterSfx == 0xffff) + x458_iceShatterSfx = x454_deathSfx; + CSfxManager::AddEmitter(x458_iceShatterSfx, GetTranslation(), zeus::CVector3f::skZero, true, false, 0x7f, + kInvalidAreaId); + SendScriptMsgs(EScriptObjectState::MassiveFrozenDeath, mgr, EScriptObjectMessage::None); + GenerateIceDeathExplosion(mgr); + float toPlayerDist = (mgr.GetPlayer().GetTranslation() - GetTranslation()).magnitude(); + if (toPlayerDist < 40.f) + mgr.GetCameraManager()->AddCameraShaker( + CCameraShakeData::BuildPatternedExplodeShakeData(GetTranslation(), 0.25f, 0.3f, 40.f), true); + DeathDelete(mgr); + x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false; +} + +void CPatterned::Burn(float duration, float damage) { + switch (GetDamageVulnerability()->GetVulnerability(CWeaponMode(EWeaponType::Plasma), false)) { + case EVulnerability::Weak: + x450_bodyController->SetOnFire(1.5f * duration); + x3ec_pendingFireDamage = 1.5f * damage; + break; + case EVulnerability::Normal: + x450_bodyController->SetOnFire(duration); + x3ec_pendingFireDamage = damage; + break; + default: + break; + } +} + +void CPatterned::Shock(float duration, float damage) { + switch (GetDamageVulnerability()->GetVulnerability(CWeaponMode(EWeaponType::Wave), false)) { + case EVulnerability::Weak: + x450_bodyController->SetElectrocuting(1.5f * duration); + x3f0_pendingShockDamage = 1.5f * damage; + break; + case EVulnerability::Normal: + x450_bodyController->SetElectrocuting(duration); + x3f0_pendingShockDamage = damage; + break; + default: + break; + } +} + +void CPatterned::Freeze(CStateManager& mgr, const zeus::CVector3f& pos, const zeus::CUnitVector3f& dir, + float frozenDur) { + if (x402_25_lostMassiveFrozenHP) + x402_26_dieIf80PercFrozen = true; + bool playSfx = false; + if (x450_bodyController->IsFrozen()) { + x450_bodyController->Freeze(x460_knockBackController.GetActiveParms().xc_intoFreezeDur, frozenDur, + x4f8_outofFreezeDur); + mgr.GetActorModelParticles()->EnsureElectricLoaded(*this); + playSfx = true; + } else if (!x450_bodyController->IsElectrocuting() && !x450_bodyController->IsOnFire()) { + x450_bodyController->Freeze(x4f4_intoFreezeDur, frozenDur, x4f8_outofFreezeDur); + if (x510_vertexMorph) + x510_vertexMorph->Reset(dir, pos, x4f4_intoFreezeDur); + playSfx = true; + } + + if (playSfx) { + u16 sfx; + if (x460_knockBackController.GetVariant() != EKnockBackVariant::Small && + CPatterned::CastTo(mgr.GetObjectById(GetUniqueId()))) + sfx = SFXsfx0701; else - x32c_animState = EAnimState::Over; + sfx = SFXsfx0708; + CSfxManager::AddEmitter(sfx, GetTranslation(), zeus::CVector3f::skZero, true, false, 0x7f, kInvalidAreaId); + } } -void CPatterned::TryLoopReaction(CStateManager& mgr, int arg) -{ - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopReactionCmd(pas::EReactionType(arg))); +zeus::CVector3f CPatterned::GetGunEyePos() const { + zeus::CVector3f origin = GetTranslation(); + zeus::CAABox baseBox = GetBaseBoundingBox(); + origin.z() = 0.6f * (baseBox.max.z() - baseBox.min.z()) + origin.z(); + return origin; } -void CPatterned::TryProjectileAttack(CStateManager&, int arg) -{ - x450_bodyController->GetCommandMgr().DeliverCmd(CBCProjectileAttackCmd(pas::ESeverity(arg), x2e0_destPos, false)); +void CPatterned::SetupPlayerCollision(bool v) { + CMaterialList include = GetMaterialFilter().GetIncludeList(); + CMaterialList exclude = GetMaterialFilter().GetExcludeList(); + CMaterialList* modList = (v ? &exclude : &include); + modList->Add(EMaterialTypes::Player); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); } -void CPatterned::TryGenerate(CStateManager& mgr, int arg) -{ - x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType(arg), x2e0_destPos, true)); +void CPatterned::LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, + EProjectileAttrib attrib, bool playerHoming, + const std::experimental::optional>& visorParticle, + u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale) { + CProjectileInfo* pInfo = GetProjectileInfo(); + if (pInfo->Token().IsLoaded()) { + if (mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, maxAllowed)) { + TUniqueId homingId = playerHoming ? mgr.GetPlayer().GetUniqueId() : kInvalidUniqueId; + CEnergyProjectile* newProjectile = + new CEnergyProjectile(true, pInfo->Token(), EWeaponType::AI, gunXf, EMaterialTypes::Character, + pInfo->GetDamage(), mgr.AllocateUniqueId(), GetAreaIdAlways(), GetUniqueId(), homingId, + attrib, false, scale, visorParticle, visorSfx, sendCollideMsg); + mgr.AddObject(newProjectile); + } + } } -void CPatterned::BuildBodyController(EBodyType bodyType) -{ - if (x450_bodyController) - return; - - x450_bodyController.reset(new CBodyController(*this, x3b8_turnSpeed, bodyType)); - auto anim = x450_bodyController->GetPASDatabase().FindBestAnimation(CPASAnimParmData(24, - CPASAnimParm::FromEnum(0)), -1); - x460_knockBackController.x81_26_enableShock = anim.first > 0.f; +void CPatterned::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + switch (type) { + case EUserEventType::Projectile: { + zeus::CTransform lctrXf = GetLctrTransform(node.GetLocatorName()); + zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + if ((aimPos - lctrXf.origin).normalized().dot(lctrXf.basis[1]) > 0.f) { + zeus::CTransform gunXf = zeus::lookAt(lctrXf.origin, aimPos); + LaunchProjectile(gunXf, mgr, 1, EProjectileAttrib::None, false, {}, 0xffff, false, zeus::CVector3f::skOne); + } else { + LaunchProjectile(lctrXf, mgr, 1, EProjectileAttrib::None, false, {}, 0xffff, false, zeus::CVector3f::skOne); + } + break; + } + case EUserEventType::DamageOn: { + zeus::CTransform lctrXf = GetLctrTransform(node.GetLocatorName()); + zeus::CVector3f xfOrigin = x34_transform * (x64_modelData->GetScale() * lctrXf.origin); + zeus::CVector3f margin = zeus::CVector3f(1.f, 1.f, 0.5f) * x64_modelData->GetScale(); + if (zeus::CAABox(xfOrigin - margin, xfOrigin + margin).intersects(mgr.GetPlayer().GetBoundingBox())) { + mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), GetContactDamage(), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::CVector3f::skZero); + } + break; + } + case EUserEventType::Delete: { + if (!x400_25_alive) { + if (!x400_27_fadeToDeath) { + x3e8_alphaDelta = -0.333333f; + x400_27_fadeToDeath = true; + } + RemoveMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, EMaterialTypes::Target, EMaterialTypes::Orbit, + mgr); + AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); + } else { + DeathDelete(mgr); + } + break; + } + case EUserEventType::BreakLockOn: { + RemoveMaterial(EMaterialTypes::Character, EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); + break; + } + case EUserEventType::BecomeShootThrough: { + AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); + break; + } + case EUserEventType::RemoveCollision: { + RemoveMaterial(EMaterialTypes::Solid, mgr); + break; + } + default: + break; + } + CActor::DoUserAnimEvent(mgr, node, type, dt); } -void CPatterned::GenerateDeathExplosion(CStateManager& mgr) -{ - if (auto particle = GetDeathExplosionParticle()) - { - zeus::CTransform xf(GetTransform()); - xf.origin = GetTransform() * (x64_modelData->GetScale() * x514_deathExplosionOffset); - CExplosion* explo = new CExplosion(*particle, mgr.AllocateUniqueId(), true, - CEntityInfo(GetAreaIdAlways(), CEntity::NullConnectionList), "", xf, 1, - zeus::CVector3f::skOne, zeus::CColor::skWhite); - mgr.AddObject(explo); - } - else if (x530_deathExplosionElectric) - { - zeus::CTransform xf(GetTransform()); - xf.origin = GetTransform() * (x64_modelData->GetScale() * x514_deathExplosionOffset); - CExplosion* explo = new CExplosion(*x530_deathExplosionElectric, mgr.AllocateUniqueId(), true, - CEntityInfo(GetAreaIdAlways(), CEntity::NullConnectionList), "", xf, 1, - zeus::CVector3f::skOne, zeus::CColor::skWhite); - mgr.AddObject(explo); - } +void CPatterned::UpdateAlphaDelta(float dt, CStateManager& mgr) { + if (x3e8_alphaDelta == 0.f) + return; + + float alpha = dt * x3e8_alphaDelta + x42c_color.a(); + if (alpha > 1.f) { + alpha = 1.f; + x3e8_alphaDelta = 0.f; + } else if (alpha < 0.f) { + alpha = 0.f; + x3e8_alphaDelta = 0.f; + if (x400_27_fadeToDeath) + DeathDelete(mgr); + } + x94_simpleShadow->SetUserAlpha(alpha); + SetModelAlpha(alpha); + x64_modelData->AnimationData()->GetParticleDB().SetModulationColorAllActiveEffects(zeus::CColor(1.f, alpha)); } -void CPatterned::MassiveDeath(CStateManager& mgr) -{ - CSfxManager::AddEmitter(x454_deathSfx, GetTranslation(), zeus::CVector3f::skZero, - true, false, 0x7f, kInvalidAreaId); - if (!x401_28_burning) - { - SendScriptMsgs(EScriptObjectState::MassiveDeath, mgr, EScriptObjectMessage::None); - GenerateDeathExplosion(mgr); - } - DeathDelete(mgr); - x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false; +float CPatterned::CalcDyingThinkRate() { + float f0 = (x401_28_burning ? (x3f4_burnThinkRateTimer / 1.5f) : 1.f); + return zeus::max(0.1f, f0); } -void CPatterned::GenerateIceDeathExplosion(CStateManager& mgr) -{ - if (x54c_iceDeathExplosionParticle) - { - zeus::CTransform xf(GetTransform()); - xf.origin = GetTransform() * (x64_modelData->GetScale() * x540_iceDeathExplosionOffset); - CExplosion* explo = new CExplosion(*x54c_iceDeathExplosionParticle, mgr.AllocateUniqueId(), true, - CEntityInfo(GetAreaIdAlways(), CEntity::NullConnectionList), "", xf, 1, - zeus::CVector3f::skOne, zeus::CColor::skWhite); - mgr.AddObject(explo); - } -} - -void CPatterned::MassiveFrozenDeath(CStateManager& mgr) -{ - if (x458_iceShatterSfx == 0xffff) - x458_iceShatterSfx = x454_deathSfx; - CSfxManager::AddEmitter(x458_iceShatterSfx, GetTranslation(), zeus::CVector3f::skZero, - true, false, 0x7f, kInvalidAreaId); - SendScriptMsgs(EScriptObjectState::MassiveFrozenDeath, mgr, EScriptObjectMessage::None); - GenerateIceDeathExplosion(mgr); - float toPlayerDist = (mgr.GetPlayer().GetTranslation() - GetTranslation()).magnitude(); - if (toPlayerDist < 40.f) - mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::BuildPatternedExplodeShakeData( - GetTranslation(), 0.25f, 0.3f, 40.f), true); - DeathDelete(mgr); - x400_28_pendingMassiveDeath = x400_29_pendingMassiveFrozenDeath = false; -} - -void CPatterned::Burn(float duration, float damage) -{ - switch (GetDamageVulnerability()->GetVulnerability(CWeaponMode(EWeaponType::Plasma), false)) - { - case EVulnerability::Weak: - x450_bodyController->SetOnFire(1.5f * duration); - x3ec_pendingFireDamage = 1.5f * damage; - break; - case EVulnerability::Normal: - x450_bodyController->SetOnFire(duration); - x3ec_pendingFireDamage = damage; - break; - default: - break; - } -} - -void CPatterned::Shock(float duration, float damage) -{ - switch (GetDamageVulnerability()->GetVulnerability(CWeaponMode(EWeaponType::Wave), false)) - { - case EVulnerability::Weak: - x450_bodyController->SetElectrocuting(1.5f * duration); - x3f0_pendingShockDamage = 1.5f * damage; - break; - case EVulnerability::Normal: - x450_bodyController->SetElectrocuting(duration); - x3f0_pendingShockDamage = damage; - break; - default: - break; - } -} - -void CPatterned::Freeze(CStateManager& mgr, const zeus::CVector3f& pos, - const zeus::CUnitVector3f& dir, float frozenDur) -{ - if (x402_25_lostMassiveFrozenHP) - x402_26_dieIf80PercFrozen = true; - bool playSfx = false; - if (x450_bodyController->IsFrozen()) - { - x450_bodyController->Freeze(x460_knockBackController.GetActiveParms().xc_intoFreezeDur, - frozenDur, x4f8_outofFreezeDur); - mgr.GetActorModelParticles()->EnsureElectricLoaded(*this); - playSfx = true; - } - else if (!x450_bodyController->IsElectrocuting() && - !x450_bodyController->IsOnFire()) - { - x450_bodyController->Freeze(x4f4_intoFreezeDur, frozenDur, x4f8_outofFreezeDur); - if (x510_vertexMorph) - x510_vertexMorph->Reset(dir, pos, x4f4_intoFreezeDur); - playSfx = true; - } - - if (playSfx) - { - u16 sfx; - if (x460_knockBackController.GetVariant() != EKnockBackVariant::Small && - CPatterned::CastTo(mgr.GetObjectById(GetUniqueId()))) - sfx = SFXsfx0701; - else - sfx = SFXsfx0708; - CSfxManager::AddEmitter(sfx, GetTranslation(), zeus::CVector3f::skZero, - true, false, 0x7f, kInvalidAreaId); - } -} - -zeus::CVector3f CPatterned::GetGunEyePos() const -{ - zeus::CVector3f origin = GetTranslation(); - zeus::CAABox baseBox = GetBaseBoundingBox(); - origin.z() = 0.6f * (baseBox.max.z() - baseBox.min.z()) + origin.z(); - return origin; -} - -void CPatterned::SetupPlayerCollision(bool v) -{ - CMaterialList include = GetMaterialFilter().GetIncludeList(); - CMaterialList exclude = GetMaterialFilter().GetExcludeList(); - CMaterialList* modList = (v ? &exclude : &include); - modList->Add(EMaterialTypes::Player); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); -} - -void CPatterned::LaunchProjectile( - const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, EProjectileAttrib attrib, - bool playerHoming, const std::experimental::optional>& visorParticle, - u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale) -{ - CProjectileInfo* pInfo = GetProjectileInfo(); - if (pInfo->Token().IsLoaded()) - { - if (mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, maxAllowed)) - { - TUniqueId homingId = playerHoming ? mgr.GetPlayer().GetUniqueId() : kInvalidUniqueId; - CEnergyProjectile* newProjectile = new CEnergyProjectile(true, pInfo->Token(), EWeaponType::AI, - gunXf, EMaterialTypes::Character, pInfo->GetDamage(), mgr.AllocateUniqueId(), GetAreaIdAlways(), - GetUniqueId(), homingId, attrib, false, scale, visorParticle, visorSfx, sendCollideMsg); - mgr.AddObject(newProjectile); - } - } -} - -void CPatterned::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) -{ - switch (type) - { - case EUserEventType::Projectile: - { - zeus::CTransform lctrXf = GetLctrTransform(node.GetLocatorName()); - zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); - if ((aimPos - lctrXf.origin).normalized().dot(lctrXf.basis[1]) > 0.f) - { - zeus::CTransform gunXf = zeus::lookAt(lctrXf.origin, aimPos); - LaunchProjectile(gunXf, mgr, 1, EProjectileAttrib::None, false, {}, 0xffff, false, zeus::CVector3f::skOne); - } - else - { - LaunchProjectile(lctrXf, mgr, 1, EProjectileAttrib::None, false, {}, 0xffff, false, zeus::CVector3f::skOne); - } - break; - } - case EUserEventType::DamageOn: - { - zeus::CTransform lctrXf = GetLctrTransform(node.GetLocatorName()); - zeus::CVector3f xfOrigin = x34_transform * (x64_modelData->GetScale() * lctrXf.origin); - zeus::CVector3f margin = zeus::CVector3f(1.f, 1.f, 0.5f) * x64_modelData->GetScale(); - if (zeus::CAABox(xfOrigin - margin, xfOrigin + margin).intersects(mgr.GetPlayer().GetBoundingBox())) - { - mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), - GetContactDamage(), CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), - zeus::CVector3f::skZero); - } - break; - } - case EUserEventType::Delete: - { - if (!x400_25_alive) - { - if (!x400_27_fadeToDeath) - { - x3e8_alphaDelta = -0.333333f; - x400_27_fadeToDeath = true; - } - RemoveMaterial(EMaterialTypes::Character, EMaterialTypes::Solid, - EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); - AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); - } - else - { - DeathDelete(mgr); - } - break; - } - case EUserEventType::BreakLockOn: - { - RemoveMaterial(EMaterialTypes::Character, - EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); - break; - } - case EUserEventType::BecomeShootThrough: - { - AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr); - break; - } - case EUserEventType::RemoveCollision: - { - RemoveMaterial(EMaterialTypes::Solid, mgr); - break; - } - default: - break; - } - CActor::DoUserAnimEvent(mgr, node, type, dt); -} - -void CPatterned::UpdateAlphaDelta(float dt, CStateManager& mgr) -{ - if (x3e8_alphaDelta == 0.f) - return; - - float alpha = dt * x3e8_alphaDelta + x42c_color.a(); - if (alpha > 1.f) - { - alpha = 1.f; - x3e8_alphaDelta = 0.f; - } - else if (alpha < 0.f) - { - alpha = 0.f; - x3e8_alphaDelta = 0.f; - if (x400_27_fadeToDeath) - DeathDelete(mgr); - } - x94_simpleShadow->SetUserAlpha(alpha); - SetModelAlpha(alpha); - x64_modelData->AnimationData()->GetParticleDB(). - SetModulationColorAllActiveEffects(zeus::CColor(1.f, alpha)); -} - -float CPatterned::CalcDyingThinkRate() -{ - float f0 = (x401_28_burning ? (x3f4_burnThinkRateTimer / 1.5f) : 1.f); - return zeus::max(0.1f, f0); -} - -void CPatterned::UpdateDamageColor(float dt) -{ - if (x428_damageCooldownTimer > 0.f) - { - x428_damageCooldownTimer = std::max(0.f, x428_damageCooldownTimer - dt); - float alpha = x42c_color.a(); - x42c_color = zeus::CColor::lerp(zeus::CColor::skBlack, x430_damageColor, - std::min(x428_damageCooldownTimer / 0.33f, 1.f)); - x42c_color.a() = alpha; - if (!x450_bodyController->IsFrozen()) - xd0_damageMag = x50c_baseDamageMag + x428_damageCooldownTimer; - } +void CPatterned::UpdateDamageColor(float dt) { + if (x428_damageCooldownTimer > 0.f) { + x428_damageCooldownTimer = std::max(0.f, x428_damageCooldownTimer - dt); + float alpha = x42c_color.a(); + x42c_color = + zeus::CColor::lerp(zeus::CColor::skBlack, x430_damageColor, std::min(x428_damageCooldownTimer / 0.33f, 1.f)); + x42c_color.a() = alpha; + if (!x450_bodyController->IsFrozen()) + xd0_damageMag = x50c_baseDamageMag + x428_damageCooldownTimer; + } } TUniqueId CPatterned::GetWaypointForState(CStateManager& mgr, EScriptObjectState state, - EScriptObjectMessage msg) const -{ - rstl::reserved_vector ids; - for (const auto& conn : GetConnectionList()) - { - if (conn.x0_state == state && conn.x4_msg == msg) - { - TUniqueId id = mgr.GetIdForScript(conn.x8_objId); - if (const CEntity* ent = mgr.GetObjectById(id)) - if (ent->GetActive()) - ids.push_back(id); - } + EScriptObjectMessage msg) const { + rstl::reserved_vector ids; + for (const auto& conn : GetConnectionList()) { + if (conn.x0_state == state && conn.x4_msg == msg) { + TUniqueId id = mgr.GetIdForScript(conn.x8_objId); + if (const CEntity* ent = mgr.GetObjectById(id)) + if (ent->GetActive()) + ids.push_back(id); } + } - if (!ids.empty()) - return ids[mgr.GetActiveRandom()->Next() % ids.size()]; + if (!ids.empty()) + return ids[mgr.GetActiveRandom()->Next() % ids.size()]; - return kInvalidUniqueId; + return kInvalidUniqueId; } -void CPatterned::UpdateActorKeyframe(CStateManager& mgr) const -{ - if (TCastToConstPtr wp = mgr.GetObjectById(x2dc_destObj)) - for (const auto& conn : wp->GetConnectionList()) - if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Action) - if (TCastToPtr kf = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) - if (kf->GetActive() && kf->IsPassive()) - kf->UpdateEntity(GetUniqueId(), mgr); +void CPatterned::UpdateActorKeyframe(CStateManager& mgr) const { + if (TCastToConstPtr wp = mgr.GetObjectById(x2dc_destObj)) + for (const auto& conn : wp->GetConnectionList()) + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Action) + if (TCastToPtr kf = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) + if (kf->GetActive() && kf->IsPassive()) + kf->UpdateEntity(GetUniqueId(), mgr); } -pas::EStepDirection CPatterned::GetStepDirection(const zeus::CVector3f& moveVec) const -{ - zeus::CVector3f localMove = x34_transform.transposeRotate(moveVec); - float angle = zeus::CVector3f::getAngleDiff(localMove, zeus::CVector3f::skForward); - if (angle < zeus::degToRad(45.f)) - return pas::EStepDirection::Forward; - else if (angle > zeus::degToRad(135.f)) - return pas::EStepDirection::Backward; - else if (localMove.dot(zeus::CVector3f::skRight) > 0.f) - return pas::EStepDirection::Right; - else - return pas::EStepDirection::Left; +pas::EStepDirection CPatterned::GetStepDirection(const zeus::CVector3f& moveVec) const { + zeus::CVector3f localMove = x34_transform.transposeRotate(moveVec); + float angle = zeus::CVector3f::getAngleDiff(localMove, zeus::CVector3f::skForward); + if (angle < zeus::degToRad(45.f)) + return pas::EStepDirection::Forward; + else if (angle > zeus::degToRad(135.f)) + return pas::EStepDirection::Backward; + else if (localMove.dot(zeus::CVector3f::skRight) > 0.f) + return pas::EStepDirection::Right; + else + return pas::EStepDirection::Left; } -bool CPatterned::IsPatternObstructed(CStateManager& mgr, - const zeus::CVector3f& p0, const zeus::CVector3f& p1) const -{ - CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Character); - zeus::CVector3f delta = p1 - p0; - rstl::reserved_vector nearList; - bool ret = false; - if (delta.canBeNormalized()) - { - zeus::CVector3f deltaNorm = delta.normalized(); - float deltaMag = delta.magnitude(); - mgr.BuildNearList(nearList, p0, deltaNorm, deltaMag, filter, this); - TUniqueId bestId = kInvalidUniqueId; - CRayCastResult res = - mgr.RayWorldIntersection(bestId, p0, deltaNorm, deltaMag, - CMaterialFilter::MakeInclude(EMaterialTypes::Solid), nearList); - ret = res.IsValid(); - } - return ret; +bool CPatterned::IsPatternObstructed(CStateManager& mgr, const zeus::CVector3f& p0, const zeus::CVector3f& p1) const { + CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Character); + zeus::CVector3f delta = p1 - p0; + rstl::reserved_vector nearList; + bool ret = false; + if (delta.canBeNormalized()) { + zeus::CVector3f deltaNorm = delta.normalized(); + float deltaMag = delta.magnitude(); + mgr.BuildNearList(nearList, p0, deltaNorm, deltaMag, filter, this); + TUniqueId bestId = kInvalidUniqueId; + CRayCastResult res = mgr.RayWorldIntersection(bestId, p0, deltaNorm, deltaMag, + CMaterialFilter::MakeInclude(EMaterialTypes::Solid), nearList); + ret = res.IsValid(); + } + return ret; } -void CPatterned::UpdateDest(CStateManager& mgr) -{ - if (x328_24_inPosition && x2dc_destObj != kInvalidUniqueId) - { - if (TCastToPtr wp = mgr.ObjectById(x2dc_destObj)) - { - UpdateActorKeyframe(mgr); - x2dc_destObj = wp->NextWaypoint(mgr); - if (x2dc_destObj != kInvalidUniqueId) - { - x2ec_reflectedDestPos = GetTranslation(); - x328_24_inPosition = false; - if (TCastToConstPtr wp2 = mgr.GetObjectById(x2dc_destObj)) - { - x3b0_moveSpeed = wp->GetSpeed(); - x30c_behaviourOrient = EBehaviourOrient(wp->GetBehaviourOrient()); - if (wp->GetBehaviourModifiers() & 0x2) - { - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCJumpCmd(wp2->GetTranslation(), pas::EJumpType::Normal)); - } - else if (wp->GetBehaviourModifiers() & 0x4) - { - TUniqueId wp3Id = wp2->NextWaypoint(mgr); - if (wp3Id != kInvalidUniqueId) - { - if (TCastToConstPtr wp3 = mgr.GetObjectById(wp3Id)) - { - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCJumpCmd(wp2->GetTranslation(), wp3->GetTranslation(), - pas::EJumpType::Normal)); - } - } - } - } +void CPatterned::UpdateDest(CStateManager& mgr) { + if (x328_24_inPosition && x2dc_destObj != kInvalidUniqueId) { + if (TCastToPtr wp = mgr.ObjectById(x2dc_destObj)) { + UpdateActorKeyframe(mgr); + x2dc_destObj = wp->NextWaypoint(mgr); + if (x2dc_destObj != kInvalidUniqueId) { + x2ec_reflectedDestPos = GetTranslation(); + x328_24_inPosition = false; + if (TCastToConstPtr wp2 = mgr.GetObjectById(x2dc_destObj)) { + x3b0_moveSpeed = wp->GetSpeed(); + x30c_behaviourOrient = EBehaviourOrient(wp->GetBehaviourOrient()); + if (wp->GetBehaviourModifiers() & 0x2) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(wp2->GetTranslation(), pas::EJumpType::Normal)); + } else if (wp->GetBehaviourModifiers() & 0x4) { + TUniqueId wp3Id = wp2->NextWaypoint(mgr); + if (wp3Id != kInvalidUniqueId) { + if (TCastToConstPtr wp3 = mgr.GetObjectById(wp3Id)) { + x450_bodyController->GetCommandMgr().DeliverCmd( + CBCJumpCmd(wp2->GetTranslation(), wp3->GetTranslation(), pas::EJumpType::Normal)); + } } - mgr.SendScriptMsg(wp.GetPtr(), GetUniqueId(), EScriptObjectMessage::Arrived); + } } + } + mgr.SendScriptMsg(wp.GetPtr(), GetUniqueId(), EScriptObjectMessage::Arrived); } + } - if (x2dc_destObj != kInvalidUniqueId) - if (TCastToConstPtr act = mgr.GetObjectById(x2dc_destObj)) - SetDestPos(act->GetTranslation()); + if (x2dc_destObj != kInvalidUniqueId) + if (TCastToConstPtr act = mgr.GetObjectById(x2dc_destObj)) + SetDestPos(act->GetTranslation()); } -void CPatterned::ApproachDest(CStateManager& mgr) -{ - zeus::CVector3f faceVec = mgr.GetPlayer().GetTranslation() - GetTranslation(); - zeus::CVector3f moveVec = x2e0_destPos - GetTranslation(); - if (!x328_25_verticalMovement) - moveVec.z() = 0.f; - zeus::CVector3f pathLine = x2e0_destPos - x2ec_reflectedDestPos; - if (pathLine.dot(moveVec) <= 0.f) - x328_24_inPosition = true; - else if (moveVec.magSquared() < 3.f * 3.f) - moveVec = pathLine; - if (!x328_24_inPosition) - { - if (moveVec.canBeNormalized()) - moveVec.normalize(); - switch (x30c_behaviourOrient) - { - case EBehaviourOrient::MoveDir: - faceVec = moveVec; - break; - case EBehaviourOrient::Destination: - if (x39c_curPattern && x39c_curPattern < x38c_patterns.size()) - { - faceVec = x38c_patterns[x39c_curPattern].GetForward(); - } - else if (x2dc_destObj != kInvalidUniqueId) - { - if (TCastToConstPtr wp = mgr.GetObjectById(x2dc_destObj)) - faceVec = wp->GetTransform().basis[1]; - } - break; - default: - break; - } - x31c_faceVec = faceVec; - x310_moveVec = x3b0_moveSpeed * moveVec; - pas::EStepDirection stepDir; - if (!KnockbackWhenFrozen()) - { - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCLocomotionCmd(x310_moveVec, x31c_faceVec, 1.f)); - } - else if (x30c_behaviourOrient == EBehaviourOrient::MoveDir || - !x450_bodyController->HasBodyState(pas::EAnimationState::Step)) - { - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCLocomotionCmd(x310_moveVec, zeus::CVector3f::skZero, 1.f)); - } - else if ((stepDir = GetStepDirection(x310_moveVec)) != pas::EStepDirection::Forward) - { - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCStepCmd(stepDir, pas::EStepType::Normal)); - } - else - { - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCLocomotionCmd(x310_moveVec, zeus::CVector3f::skZero, 1.f)); - } - x450_bodyController->GetCommandMgr().DeliverTargetVector(x31c_faceVec); +void CPatterned::ApproachDest(CStateManager& mgr) { + zeus::CVector3f faceVec = mgr.GetPlayer().GetTranslation() - GetTranslation(); + zeus::CVector3f moveVec = x2e0_destPos - GetTranslation(); + if (!x328_25_verticalMovement) + moveVec.z() = 0.f; + zeus::CVector3f pathLine = x2e0_destPos - x2ec_reflectedDestPos; + if (pathLine.dot(moveVec) <= 0.f) + x328_24_inPosition = true; + else if (moveVec.magSquared() < 3.f * 3.f) + moveVec = pathLine; + if (!x328_24_inPosition) { + if (moveVec.canBeNormalized()) + moveVec.normalize(); + switch (x30c_behaviourOrient) { + case EBehaviourOrient::MoveDir: + faceVec = moveVec; + break; + case EBehaviourOrient::Destination: + if (x39c_curPattern && x39c_curPattern < x38c_patterns.size()) { + faceVec = x38c_patterns[x39c_curPattern].GetForward(); + } else if (x2dc_destObj != kInvalidUniqueId) { + if (TCastToConstPtr wp = mgr.GetObjectById(x2dc_destObj)) + faceVec = wp->GetTransform().basis[1]; + } + break; + default: + break; } - else if (x450_bodyController->GetBodyStateInfo().GetMaxSpeed() > FLT_EPSILON) - { - x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( - (x138_velocity.magnitude() / x450_bodyController->GetBodyStateInfo().GetMaxSpeed()) * - x34_transform.basis[1], zeus::CVector3f::skZero, 1.f)); + x31c_faceVec = faceVec; + x310_moveVec = x3b0_moveSpeed * moveVec; + pas::EStepDirection stepDir; + if (!KnockbackWhenFrozen()) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(x310_moveVec, x31c_faceVec, 1.f)); + } else if (x30c_behaviourOrient == EBehaviourOrient::MoveDir || + !x450_bodyController->HasBodyState(pas::EAnimationState::Step)) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(x310_moveVec, zeus::CVector3f::skZero, 1.f)); + } else if ((stepDir = GetStepDirection(x310_moveVec)) != pas::EStepDirection::Forward) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCStepCmd(stepDir, pas::EStepType::Normal)); + } else { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(x310_moveVec, zeus::CVector3f::skZero, 1.f)); } + x450_bodyController->GetCommandMgr().DeliverTargetVector(x31c_faceVec); + } else if (x450_bodyController->GetBodyStateInfo().GetMaxSpeed() > FLT_EPSILON) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( + (x138_velocity.magnitude() / x450_bodyController->GetBodyStateInfo().GetMaxSpeed()) * x34_transform.basis[1], + zeus::CVector3f::skZero, 1.f)); + } } -std::pair CPatterned::GetDestWaypoints(CStateManager& mgr) const -{ - std::pair ret {}; - if (TCastToPtr wp = mgr.ObjectById(x2dc_destObj)) - { - ret.first = wp.GetPtr(); - ret.second = TCastToPtr(mgr.ObjectById(wp->FollowWaypoint(mgr))).GetPtr(); - } - return ret; +std::pair CPatterned::GetDestWaypoints(CStateManager& mgr) const { + std::pair ret{}; + if (TCastToPtr wp = mgr.ObjectById(x2dc_destObj)) { + ret.first = wp.GetPtr(); + ret.second = TCastToPtr(mgr.ObjectById(wp->FollowWaypoint(mgr))).GetPtr(); + } + return ret; } -zeus::CQuaternion CPatterned::FindPatternRotation(const zeus::CVector3f& dir) const -{ - zeus::CVector3f wpDeltaFlat = x368_destWPDelta; - wpDeltaFlat.z() = 0.f; - wpDeltaFlat.normalize(); - zeus::CVector3f dirFlat = dir; - dirFlat.z() = 0.f; - dirFlat.normalize(); +zeus::CQuaternion CPatterned::FindPatternRotation(const zeus::CVector3f& dir) const { + zeus::CVector3f wpDeltaFlat = x368_destWPDelta; + wpDeltaFlat.z() = 0.f; + wpDeltaFlat.normalize(); + zeus::CVector3f dirFlat = dir; + dirFlat.z() = 0.f; + dirFlat.normalize(); - zeus::CQuaternion q; - if ((wpDeltaFlat - dirFlat).magSquared() > 3.99f) - q.rotateZ(zeus::degToRad(180.f)); - else - q = zeus::CQuaternion::shortestRotationArc(wpDeltaFlat, dirFlat); + zeus::CQuaternion q; + if ((wpDeltaFlat - dirFlat).magSquared() > 3.99f) + q.rotateZ(zeus::degToRad(180.f)); + else + q = zeus::CQuaternion::shortestRotationArc(wpDeltaFlat, dirFlat); - if (x328_25_verticalMovement) - { - q = zeus::CQuaternion::shortestRotationArc( + if (x328_25_verticalMovement) { + q = zeus::CQuaternion::shortestRotationArc( (q * zeus::CQuaternion(0.f, x368_destWPDelta) * q.inverse()).getImaginary().normalized(), - dir.normalized()) * q; - } + dir.normalized()) * + q; + } - return q; + return q; } -zeus::CVector3f CPatterned::FindPatternDir(CStateManager& mgr) const -{ - zeus::CVector3f ret; - switch (x378_patternOrient) - { - case EPatternOrient::StartToPlayerStart: - ret = x35c_patternStartPlayerPos - x350_patternStartPos; - break; - case EPatternOrient::StartToPlayer: - ret = mgr.GetPlayer().GetTranslation() - x350_patternStartPos; - break; - case EPatternOrient::ReversePlayerForward: - ret = -mgr.GetPlayer().GetTransform().basis[1]; - break; - case EPatternOrient::Forward: - ret = GetTransform().basis[1]; - break; - default: - break; - } - return ret; +zeus::CVector3f CPatterned::FindPatternDir(CStateManager& mgr) const { + zeus::CVector3f ret; + switch (x378_patternOrient) { + case EPatternOrient::StartToPlayerStart: + ret = x35c_patternStartPlayerPos - x350_patternStartPos; + break; + case EPatternOrient::StartToPlayer: + ret = mgr.GetPlayer().GetTranslation() - x350_patternStartPos; + break; + case EPatternOrient::ReversePlayerForward: + ret = -mgr.GetPlayer().GetTransform().basis[1]; + break; + case EPatternOrient::Forward: + ret = GetTransform().basis[1]; + break; + default: + break; + } + return ret; } -void CPatterned::UpdatePatternDestPos(CStateManager& mgr) -{ - if (x39c_curPattern < x38c_patterns.size()) - { +void CPatterned::UpdatePatternDestPos(CStateManager& mgr) { + if (x39c_curPattern < x38c_patterns.size()) { + if (x368_destWPDelta != zeus::CVector3f::skZero) { + zeus::CVector3f patternDir = FindPatternDir(mgr); + SetDestPos(FindPatternRotation(patternDir).transform(x38c_patterns[x39c_curPattern].GetPos())); + if (x37c_patternFit == EPatternFit::Zero) { + float magSq; + if (x328_25_verticalMovement) + magSq = patternDir.magSquared() / x368_destWPDelta.magSquared(); + else + magSq = patternDir.toVec2f().magSquared() / x368_destWPDelta.toVec2f().magSquared(); + SetDestPos(std::sqrt(magSq) * x2e0_destPos); + } + } else { + SetDestPos(x38c_patterns[x39c_curPattern].GetPos()); + } + } + + switch (x374_patternTranslate) { + case EPatternTranslate::RelativeStart: + SetDestPos(x2e0_destPos + x350_patternStartPos); + break; + case EPatternTranslate::RelativePlayerStart: + SetDestPos(x2e0_destPos + x35c_patternStartPlayerPos); + break; + case EPatternTranslate::RelativePlayer: + SetDestPos(x2e0_destPos + mgr.GetPlayer().GetTranslation()); + break; + default: + break; + } +} + +void CPatterned::SetupPattern(CStateManager& mgr) { + EScriptObjectState state = GetDesiredAttackState(mgr); + x2dc_destObj = GetWaypointForState(mgr, state, EScriptObjectMessage::Follow); + if (x2dc_destObj == kInvalidUniqueId && state != EScriptObjectState::Attack) + x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Attack, EScriptObjectMessage::Follow); + x38c_patterns.clear(); + if (x2dc_destObj != kInvalidUniqueId) { + x350_patternStartPos = GetTranslation(); + x35c_patternStartPlayerPos = mgr.GetPlayer().GetTranslation(); + auto destWPs = GetDestWaypoints(mgr); + if (destWPs.first) { + x374_patternTranslate = EPatternTranslate(destWPs.first->GetPatternTranslate()); + x378_patternOrient = EPatternOrient(destWPs.first->GetPatternOrient()); + x37c_patternFit = EPatternFit(destWPs.first->GetPatternFit()); + if (destWPs.second) + x368_destWPDelta = destWPs.second->GetTranslation() - destWPs.first->GetTranslation(); + else + x368_destWPDelta = zeus::CVector3f::skZero; + + int numPatterns = 0; + CScriptWaypoint* curWp = destWPs.first; + do { + ++numPatterns; + curWp = TCastToPtr(mgr.ObjectById(curWp->NextWaypoint(mgr))).GetPtr(); + if (!curWp) + break; + } while (curWp->GetUniqueId() != destWPs.first->GetUniqueId()); + x38c_patterns.reserve(numPatterns); + + zeus::CVector3f basePos; + switch (x374_patternTranslate) { + case EPatternTranslate::RelativePlayerStart: + if (destWPs.second) + basePos = destWPs.second->GetTranslation(); + break; + case EPatternTranslate::Absolute: + break; + default: + basePos = destWPs.first->GetTranslation(); + break; + } + + curWp = destWPs.first; + do { + zeus::CVector3f wpForward = curWp->GetTransform().basis[1]; if (x368_destWPDelta != zeus::CVector3f::skZero) - { - zeus::CVector3f patternDir = FindPatternDir(mgr); - SetDestPos(FindPatternRotation(patternDir).transform(x38c_patterns[x39c_curPattern].GetPos())); - if (x37c_patternFit == EPatternFit::Zero) - { - float magSq; - if (x328_25_verticalMovement) - magSq = patternDir.magSquared() / x368_destWPDelta.magSquared(); - else - magSq = patternDir.toVec2f().magSquared() / x368_destWPDelta.toVec2f().magSquared(); - SetDestPos(std::sqrt(magSq) * x2e0_destPos); - } + wpForward = FindPatternRotation(FindPatternDir(mgr)).transform(wpForward); + x38c_patterns.emplace_back(curWp->GetTranslation() - basePos, wpForward, curWp->GetSpeed(), + curWp->GetBehaviour(), curWp->GetBehaviourOrient(), curWp->GetBehaviourModifiers(), + curWp->GetAnimation()); + curWp = TCastToPtr(mgr.ObjectById(curWp->NextWaypoint(mgr))).GetPtr(); + if (!curWp) + break; + } while (curWp->GetUniqueId() != destWPs.first->GetUniqueId()); + } + } + + x400_30_patternShagged = false; + x39c_curPattern = 0; + x328_24_inPosition = false; + x2ec_reflectedDestPos = GetTranslation(); + if (!x38c_patterns.empty()) { + x3b0_moveSpeed = x38c_patterns.front().GetSpeed(); + x380_behaviour = EBehaviour(x38c_patterns.front().GetBehaviour()); + x30c_behaviourOrient = EBehaviourOrient(x38c_patterns.front().GetBehaviourOrient()); + x384_behaviourModifiers = EBehaviourModifiers(x38c_patterns.front().GetBehaviourModifiers()); + } +} + +EScriptObjectState CPatterned::GetDesiredAttackState(CStateManager& mgr) const { + float deltaMagSq = (GetTranslation() - mgr.GetPlayer().GetTranslation()).magSquared(); + if (deltaMagSq < x2fc_minAttackRange * x2fc_minAttackRange) + return EScriptObjectState::Retreat; + else if (deltaMagSq > x300_maxAttackRange * x300_maxAttackRange) + return EScriptObjectState::CloseIn; + else + return EScriptObjectState::Attack; +} + +float CPatterned::GetAnimationDistance(const CPASAnimParmData& data) const { + auto bestAnim = x64_modelData->GetAnimationData()->GetCharacterInfo().GetPASDatabase().FindBestAnimation(data, -1); + float dist = 1.f; + if (bestAnim.first > FLT_EPSILON) { + dist = x64_modelData->GetAnimationData()->GetAnimationDuration(bestAnim.second) * + x64_modelData->GetAnimationData()->GetAverageVelocity(bestAnim.second); + } + return dist; +} + +void CPatterned::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) { + SetCalculateLighting(false); + x90_actorLights->BuildConstantAmbientLighting(zeus::CColor::skWhite); + } else + SetCalculateLighting(true); + + zeus::CColor col = x42c_color; + u8 alpha = GetModelAlphau8(mgr); + if (x402_27_noXrayModel && mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) + alpha = 76; + + if (alpha < 255) { + if (col.r() == 0.f && col.g() == 0.f && col.b() == 0.f) + col = zeus::CColor::skWhite; /* Not being damaged */ + + if (x401_29_laggedBurnDeath) { + int stripedAlpha = 255; + if (alpha > 127) + stripedAlpha = (alpha - 128) * 2; + xb4_drawFlags = CModelFlags(3, 0, 3, zeus::CColor(0.f, (stripedAlpha * stripedAlpha) / 65025.f)); + } else if (x401_28_burning) { + xb4_drawFlags = CModelFlags(5, 0, 3, zeus::CColor(0.f, 1.f)); + } else { + zeus::CColor col2 = col; + col2.a() = alpha / 255.f; + xb4_drawFlags = CModelFlags(5, 0, 3, col2); + } + } else { + if (col.r() != 0.f || col.g() != 0.f || col.b() != 0.f) { + /* Being damaged */ + zeus::CColor col2 = col; + col2.a() = alpha / 255.f; + xb4_drawFlags = CModelFlags(2, 0, 3, col2); + } else { + xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); + } + } + + CActor::PreRender(mgr, frustum); +} + +void CPatterned::RenderIceModelWithFlags(const CModelFlags& flags) const { + CModelFlags useFlags = flags; + useFlags.x1_matSetIdx = 0; + CAnimData* animData = x64_modelData->AnimationData(); + if (CMorphableSkinnedModel* iceModel = animData->IceModel().GetObj()) + animData->Render(*iceModel, useFlags, {*x510_vertexMorph}, iceModel->GetMorphMagnitudes()); +} + +void CPatterned::Render(const CStateManager& mgr) const { + int mask = 0; + int target = 0; + if (x402_29_drawParticles) { + mgr.GetCharacterRenderMaskAndTarget(x402_31_thawed, mask, target); + x64_modelData->GetAnimationData()->GetParticleDB().RenderSystemsToBeDrawnFirstMasked(mask, target); + } + if ((mgr.GetThermalDrawFlag() == EThermalDrawFlag::Cold && !x402_31_thawed) || + (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot && x402_31_thawed) || + mgr.GetThermalDrawFlag() == EThermalDrawFlag::Bypass) { + if (x401_28_burning) { + const CTexture* ashy = mgr.GetActorModelParticles()->GetAshyTexture(*this); + u8 alpha = GetModelAlphau8(mgr); + if (ashy && ((!x401_29_laggedBurnDeath && alpha <= 255) || alpha <= 127)) { + if (xe5_31_pointGeneratorParticles) + mgr.SetupParticleHook(*this); + zeus::CColor addColor; + if (x401_29_laggedBurnDeath) { + addColor = zeus::CColor::skClear; + } else { + addColor = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot ? zeus::CColor::skWhite : zeus::CColor::skBlack; } - else - { - SetDestPos(x38c_patterns[x39c_curPattern].GetPos()); + x64_modelData->DisintegrateDraw(mgr, GetTransform(), *ashy, addColor, + alpha * (x401_29_laggedBurnDeath ? 0.00787402f : 0.00392157f)); + if (xe5_31_pointGeneratorParticles) { + CSkinnedModel::ClearPointGeneratorFunc(); + mgr.GetActorModelParticles()->Render(*this); } + } else { + CPhysicsActor::Render(mgr); + } + } else { + CPhysicsActor::Render(mgr); } - switch (x374_patternTranslate) - { - case EPatternTranslate::RelativeStart: - SetDestPos(x2e0_destPos + x350_patternStartPos); + if (x450_bodyController->IsFrozen() && !x401_28_burning) { + RenderIceModelWithFlags(CModelFlags(0, 0, 3, zeus::CColor::skWhite)); + } + } + + if (x402_29_drawParticles) { + x64_modelData->GetAnimationData()->GetParticleDB().RenderSystemsToBeDrawnLastMasked(mask, target); + } +} + +void CPatterned::ThinkAboutMove(float dt) { + bool doMove = true; + if (!x328_25_verticalMovement && !x328_27_onGround) { + x310_moveVec.zeroOut(); + doMove = false; + } + + if (doMove && x39c_curPattern < x38c_patterns.size()) { + zeus::CVector3f frontVec = GetTransform().frontVector(); + zeus::CVector3f x31cCpy = x31c_faceVec; + if (x31c_faceVec.magSquared() > 0.1f) + x31cCpy.normalize(); + float mag = frontVec.dot(x31cCpy); + + switch (x3f8_moveState) { + case EMoveState::Zero: + if (!x328_26_longJump) break; - case EPatternTranslate::RelativePlayerStart: - SetDestPos(x2e0_destPos + x35c_patternStartPlayerPos); + case EMoveState::One: + doMove = false; + if (mag > 0.85f) { + doMove = true; + x3f8_moveState = EMoveState::Two; break; - case EPatternTranslate::RelativePlayer: - SetDestPos(x2e0_destPos + mgr.GetPlayer().GetTranslation()); + } + x3f8_moveState = EMoveState::One; + break; + case EMoveState::Two: + x3f8_moveState = EMoveState::Three; + case EMoveState::Three: + doMove = true; + if (!x328_26_longJump) { + x3f8_moveState = EMoveState::Zero; break; + } + if (mag > 0.9f) + x3f8_moveState = EMoveState::Four; + break; + case EMoveState::Four: + x328_24_inPosition = true; + doMove = false; + x3f8_moveState = EMoveState::Zero; + break; default: - break; + break; } + } + + if (!x401_26_disableMove && doMove) { + const CBodyState* state = x450_bodyController->GetBodyStateInfo().GetCurrentState(); + if (state->ApplyAnimationDeltas() && !zeus::close_enough(x2e0_destPos - GetTranslation(), {})) + MoveToOR((x64_modelData->GetScale() * x434_posDelta) * x55c_moveScale, dt); + } + + RotateToOR(x440_rotDelta, dt); } -void CPatterned::SetupPattern(CStateManager& mgr) -{ - EScriptObjectState state = GetDesiredAttackState(mgr); - x2dc_destObj = GetWaypointForState(mgr, state, EScriptObjectMessage::Follow); - if (x2dc_destObj == kInvalidUniqueId && state != EScriptObjectState::Attack) - x2dc_destObj = GetWaypointForState(mgr, EScriptObjectState::Attack, EScriptObjectMessage::Follow); - x38c_patterns.clear(); - if (x2dc_destObj != kInvalidUniqueId) - { - x350_patternStartPos = GetTranslation(); - x35c_patternStartPlayerPos = mgr.GetPlayer().GetTranslation(); - auto destWPs = GetDestWaypoints(mgr); - if (destWPs.first) - { - x374_patternTranslate = EPatternTranslate(destWPs.first->GetPatternTranslate()); - x378_patternOrient = EPatternOrient(destWPs.first->GetPatternOrient()); - x37c_patternFit = EPatternFit(destWPs.first->GetPatternFit()); - if (destWPs.second) - x368_destWPDelta = destWPs.second->GetTranslation() - destWPs.first->GetTranslation(); - else - x368_destWPDelta = zeus::CVector3f::skZero; - - int numPatterns = 0; - CScriptWaypoint* curWp = destWPs.first; - do - { - ++numPatterns; - curWp = TCastToPtr(mgr.ObjectById(curWp->NextWaypoint(mgr))).GetPtr(); - if (!curWp) - break; - } while (curWp->GetUniqueId() != destWPs.first->GetUniqueId()); - x38c_patterns.reserve(numPatterns); - - zeus::CVector3f basePos; - switch (x374_patternTranslate) - { - case EPatternTranslate::RelativePlayerStart: - if (destWPs.second) - basePos = destWPs.second->GetTranslation(); - break; - case EPatternTranslate::Absolute: - break; - default: - basePos = destWPs.first->GetTranslation(); - break; - } - - curWp = destWPs.first; - do - { - zeus::CVector3f wpForward = curWp->GetTransform().basis[1]; - if (x368_destWPDelta != zeus::CVector3f::skZero) - wpForward = FindPatternRotation(FindPatternDir(mgr)).transform(wpForward); - x38c_patterns.emplace_back(curWp->GetTranslation() - basePos, wpForward, - curWp->GetSpeed(), curWp->GetBehaviour(), - curWp->GetBehaviourOrient(), curWp->GetBehaviourModifiers(), - curWp->GetAnimation()); - curWp = TCastToPtr(mgr.ObjectById(curWp->NextWaypoint(mgr))).GetPtr(); - if (!curWp) - break; - } while (curWp->GetUniqueId() != destWPs.first->GetUniqueId()); - } - } - - x400_30_patternShagged = false; - x39c_curPattern = 0; - x328_24_inPosition = false; - x2ec_reflectedDestPos = GetTranslation(); - if (!x38c_patterns.empty()) - { - x3b0_moveSpeed = x38c_patterns.front().GetSpeed(); - x380_behaviour = EBehaviour(x38c_patterns.front().GetBehaviour()); - x30c_behaviourOrient = EBehaviourOrient(x38c_patterns.front().GetBehaviourOrient()); - x384_behaviourModifiers = EBehaviourModifiers(x38c_patterns.front().GetBehaviourModifiers()); - } +void CPatterned::PhazeOut(CStateManager& mgr) { + if (!x400_27_fadeToDeath) + SendScriptMsgs(EScriptObjectState::DeathRattle, mgr, EScriptObjectMessage::None); + x401_27_phazingOut = true; + x450_bodyController->SetPlaybackRate(0.f); + x64_modelData->AnimationData()->GetParticleDB().SetUpdatesEnabled(false); } -EScriptObjectState CPatterned::GetDesiredAttackState(CStateManager& mgr) const -{ - float deltaMagSq = (GetTranslation() - mgr.GetPlayer().GetTranslation()).magSquared(); - if (deltaMagSq < x2fc_minAttackRange * x2fc_minAttackRange) - return EScriptObjectState::Retreat; - else if (deltaMagSq > x300_maxAttackRange * x300_maxAttackRange) - return EScriptObjectState::CloseIn; - else - return EScriptObjectState::Attack; -} - -float CPatterned::GetAnimationDistance(const CPASAnimParmData& data) const -{ - auto bestAnim = - x64_modelData->GetAnimationData()->GetCharacterInfo().GetPASDatabase().FindBestAnimation(data, -1); - float dist = 1.f; - if (bestAnim.first > FLT_EPSILON) - { - dist = x64_modelData->GetAnimationData()->GetAnimationDuration(bestAnim.second) * - x64_modelData->GetAnimationData()->GetAverageVelocity(bestAnim.second); - } - return dist; -} - -void CPatterned::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) - { - SetCalculateLighting(false); - x90_actorLights->BuildConstantAmbientLighting(zeus::CColor::skWhite); - } - else - SetCalculateLighting(true); - - zeus::CColor col = x42c_color; - u8 alpha = GetModelAlphau8(mgr); - if (x402_27_noXrayModel && mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) - alpha = 76; - - if (alpha < 255) - { - if (col.r() == 0.f && col.g() == 0.f && col.b() == 0.f) - col = zeus::CColor::skWhite; /* Not being damaged */ - - if (x401_29_laggedBurnDeath) - { - int stripedAlpha = 255; - if (alpha > 127) - stripedAlpha = (alpha - 128) * 2; - xb4_drawFlags = CModelFlags(3, 0, 3, zeus::CColor(0.f, (stripedAlpha * stripedAlpha) / 65025.f)); - } - else if (x401_28_burning) - { - xb4_drawFlags = CModelFlags(5, 0, 3, zeus::CColor(0.f, 1.f)); - } - else - { - zeus::CColor col2 = col; - col2.a() = alpha / 255.f; - xb4_drawFlags = CModelFlags(5, 0, 3, col2); - } - } - else - { - if (col.r() != 0.f || col.g() != 0.f || col.b() != 0.f) - { - /* Being damaged */ - zeus::CColor col2 = col; - col2.a() = alpha / 255.f; - xb4_drawFlags = CModelFlags(2, 0, 3, col2); - } - else - { - xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); - } - } - - CActor::PreRender(mgr, frustum); -} - -void CPatterned::RenderIceModelWithFlags(const CModelFlags& flags) const -{ - CModelFlags useFlags = flags; - useFlags.x1_matSetIdx = 0; - CAnimData* animData = x64_modelData->AnimationData(); - if (CMorphableSkinnedModel* iceModel = animData->IceModel().GetObj()) - animData->Render(*iceModel, useFlags, {*x510_vertexMorph}, iceModel->GetMorphMagnitudes()); -} - -void CPatterned::Render(const CStateManager& mgr) const -{ - int mask = 0; - int target = 0; - if (x402_29_drawParticles) - { - mgr.GetCharacterRenderMaskAndTarget(x402_31_thawed, mask, target); - x64_modelData->GetAnimationData()->GetParticleDB().RenderSystemsToBeDrawnFirstMasked(mask, target); - } - if ((mgr.GetThermalDrawFlag() == EThermalDrawFlag::Cold && !x402_31_thawed) || - (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot && x402_31_thawed) || - mgr.GetThermalDrawFlag() == EThermalDrawFlag::Bypass) - { - if (x401_28_burning) - { - const CTexture* ashy = mgr.GetActorModelParticles()->GetAshyTexture(*this); - u8 alpha = GetModelAlphau8(mgr); - if (ashy && ((!x401_29_laggedBurnDeath && alpha <= 255) || alpha <= 127)) - { - if (xe5_31_pointGeneratorParticles) - mgr.SetupParticleHook(*this); - zeus::CColor addColor; - if (x401_29_laggedBurnDeath) - { - addColor = zeus::CColor::skClear; - } - else - { - addColor = mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot ? - zeus::CColor::skWhite : zeus::CColor::skBlack; - } - x64_modelData->DisintegrateDraw(mgr, GetTransform(), *ashy, addColor, - alpha * (x401_29_laggedBurnDeath ? 0.00787402f : 0.00392157f)); - if (xe5_31_pointGeneratorParticles) - { - CSkinnedModel::ClearPointGeneratorFunc(); - mgr.GetActorModelParticles()->Render(*this); - } - } - else - { - CPhysicsActor::Render(mgr); - } - } - else - { - CPhysicsActor::Render(mgr); - } - - if (x450_bodyController->IsFrozen() && !x401_28_burning) - { - RenderIceModelWithFlags(CModelFlags(0, 0, 3, zeus::CColor::skWhite)); - } - } - - if (x402_29_drawParticles) - { - x64_modelData->GetAnimationData()->GetParticleDB().RenderSystemsToBeDrawnLastMasked(mask, target); - } -} - -void CPatterned::ThinkAboutMove(float dt) -{ - bool doMove = true; - if (!x328_25_verticalMovement && !x328_27_onGround) - { - x310_moveVec.zeroOut(); - doMove = false; - } - - if (doMove && x39c_curPattern < x38c_patterns.size()) - { - zeus::CVector3f frontVec = GetTransform().frontVector(); - zeus::CVector3f x31cCpy = x31c_faceVec; - if (x31c_faceVec.magSquared() > 0.1f) - x31cCpy.normalize(); - float mag = frontVec.dot(x31cCpy); - - switch (x3f8_moveState) - { - case EMoveState::Zero: - if (!x328_26_longJump) - break; - case EMoveState::One: - doMove = false; - if (mag > 0.85f) - { - doMove = true; - x3f8_moveState = EMoveState::Two; - break; - } - x3f8_moveState = EMoveState::One; - break; - case EMoveState::Two: - x3f8_moveState = EMoveState::Three; - case EMoveState::Three: - doMove = true; - if (!x328_26_longJump) - { - x3f8_moveState = EMoveState::Zero; - break; - } - if (mag > 0.9f) - x3f8_moveState = EMoveState::Four; - break; - case EMoveState::Four: - x328_24_inPosition = true; - doMove = false; - x3f8_moveState = EMoveState::Zero; - break; - default: - break; - } - } - - if (!x401_26_disableMove && doMove) - { - const CBodyState* state = x450_bodyController->GetBodyStateInfo().GetCurrentState(); - if (state->ApplyAnimationDeltas() && !zeus::close_enough(x2e0_destPos - GetTranslation(), {})) - MoveToOR((x64_modelData->GetScale() * x434_posDelta) * x55c_moveScale, dt); - } - - RotateToOR(x440_rotDelta, dt); -} - -void CPatterned::PhazeOut(CStateManager& mgr) -{ - if (!x400_27_fadeToDeath) - SendScriptMsgs(EScriptObjectState::DeathRattle, mgr, EScriptObjectMessage::None); - x401_27_phazingOut = true; - x450_bodyController->SetPlaybackRate(0.f); - x64_modelData->AnimationData()->GetParticleDB().SetUpdatesEnabled(false); -} - -bool CPatterned::ApplyBoneTracking() const -{ - if (x400_25_alive) - return x460_knockBackController.GetFlinchRemTime() <= 0.f; - - return false; -} +bool CPatterned::ApplyBoneTracking() const { + if (x400_25_alive) + return x460_knockBackController.GetFlinchRemTime() <= 0.f; + + return false; } +} // namespace urde diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index 88e1de427..7675d7e95 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -14,457 +14,388 @@ #define DEFINE_PATTERNED(type) static constexpr ECharacter CharacterType = ECharacter::type; #endif -namespace urde -{ +namespace urde { class CPatternedInfo; class CProjectileInfo; class CPathFindSearch; typedef void (CPatterned::*CPatternedTryFunc)(CStateManager&, int); -class CPatterned : public CAi -{ +class CPatterned : public CAi { public: - static const zeus::CColor skDamageColor; - enum class ECharacter - { - AtomicAlpha = 0, - AtomicBeta = 1, - Babygoth = 2, - Beetle = 3, - BloodFlower = 4, - Burrower = 5, - ChozoGhost = 6, - Drone = 7, - ElitePirate = 8, - EyeBall = 9, - FireFlea = 10, - Flaahgra = 11, - FlaahgraTentacle = 12, - FlickerBat = 13, - FlyingPirate = 14, - IceSheeegoth = 15, - JellyZap = 16, - Magdolite = 17, - Metaree = 18, - Metroid = 19, - MetroidBeta = 20, - MetroidPrimeExo = 21, - MetroidPrimeEssence = 22, - NewIntroBoss = 23, - Parasite = 24, - PuddleSpore = 27, - PuddleToad = 28, - Puffer = 29, - Ridley = 30, - Ripper = 31, - Seedling = 32, - SpacePirate = 34, - SpankWeed = 35, - PhazonHealingNodule = 35, - Thardus = 36, - ThardusRockProjectile = 37, - Tryclops = 38, - WarWasp = 39, - EnergyBall = 40 - }; - enum class EFlavorType - { - Zero = 0, - One = 1 - }; - enum class EMovementType - { - Ground = 0, - Flyer = 1 - }; - enum class EColliderType - { - Zero = 0, - One = 1 - }; - enum class EPatternTranslate - { - RelativeStart, - RelativePlayerStart, - RelativePlayer, - Absolute - }; - enum class EPatternOrient - { - StartToPlayer, - StartToPlayerStart, - ReversePlayerForward, - Forward - }; - enum class EPatternFit - { - Zero, - One - }; - enum class EMoveState - { - Zero, - One, - Two, - Three, - Four - }; - enum class EBehaviour - { - Zero - }; - enum class EBehaviourOrient - { - MoveDir, - Constant, - Destination - }; - enum class EBehaviourModifiers - { - Zero - }; - enum class EPatrolState - { - Invalid = -1, - Patrol, - Pause, - Done - }; - enum class EAnimState - { - Zero, - One, - Repeat, - Over - }; - class CPatternNode - { - zeus::CVector3f x0_pos; - zeus::CVector3f xc_forward; - float x18_speed; - u8 x1c_behaviour; - u8 x1d_behaviourOrient; - u16 x1e_behaviourModifiers; - u32 x20_animation; - public: - CPatternNode(const zeus::CVector3f& pos, const zeus::CVector3f& forward, float speed, - u8 behaviour, u8 behaviourOrient, u16 behaviourModifiers, u32 animation) - : x0_pos(pos), xc_forward(forward), x18_speed(speed), x1c_behaviour(behaviour), - x1d_behaviourOrient(behaviourOrient), x1e_behaviourModifiers(behaviourModifiers), - x20_animation(animation) {} - const zeus::CVector3f& GetPos() const { return x0_pos; } - const zeus::CVector3f& GetForward() const { return xc_forward; } - float GetSpeed() const { return x18_speed; } - u8 GetBehaviour() const { return x1c_behaviour; } - u8 GetBehaviourOrient() const { return x1d_behaviourOrient; } - u16 GetBehaviourModifiers() const { return x1e_behaviourModifiers; } - }; + static const zeus::CColor skDamageColor; + enum class ECharacter { + AtomicAlpha = 0, + AtomicBeta = 1, + Babygoth = 2, + Beetle = 3, + BloodFlower = 4, + Burrower = 5, + ChozoGhost = 6, + Drone = 7, + ElitePirate = 8, + EyeBall = 9, + FireFlea = 10, + Flaahgra = 11, + FlaahgraTentacle = 12, + FlickerBat = 13, + FlyingPirate = 14, + IceSheeegoth = 15, + JellyZap = 16, + Magdolite = 17, + Metaree = 18, + Metroid = 19, + MetroidBeta = 20, + MetroidPrimeExo = 21, + MetroidPrimeEssence = 22, + NewIntroBoss = 23, + Parasite = 24, + PuddleSpore = 27, + PuddleToad = 28, + Puffer = 29, + Ridley = 30, + Ripper = 31, + Seedling = 32, + SpacePirate = 34, + SpankWeed = 35, + PhazonHealingNodule = 35, + Thardus = 36, + ThardusRockProjectile = 37, + Tryclops = 38, + WarWasp = 39, + EnergyBall = 40 + }; + enum class EFlavorType { Zero = 0, One = 1 }; + enum class EMovementType { Ground = 0, Flyer = 1 }; + enum class EColliderType { Zero = 0, One = 1 }; + enum class EPatternTranslate { RelativeStart, RelativePlayerStart, RelativePlayer, Absolute }; + enum class EPatternOrient { StartToPlayer, StartToPlayerStart, ReversePlayerForward, Forward }; + enum class EPatternFit { Zero, One }; + enum class EMoveState { Zero, One, Two, Three, Four }; + enum class EBehaviour { Zero }; + enum class EBehaviourOrient { MoveDir, Constant, Destination }; + enum class EBehaviourModifiers { Zero }; + enum class EPatrolState { Invalid = -1, Patrol, Pause, Done }; + enum class EAnimState { Zero, One, Repeat, Over }; + class CPatternNode { + zeus::CVector3f x0_pos; + zeus::CVector3f xc_forward; + float x18_speed; + u8 x1c_behaviour; + u8 x1d_behaviourOrient; + u16 x1e_behaviourModifiers; + u32 x20_animation; + + public: + CPatternNode(const zeus::CVector3f& pos, const zeus::CVector3f& forward, float speed, u8 behaviour, + u8 behaviourOrient, u16 behaviourModifiers, u32 animation) + : x0_pos(pos) + , xc_forward(forward) + , x18_speed(speed) + , x1c_behaviour(behaviour) + , x1d_behaviourOrient(behaviourOrient) + , x1e_behaviourModifiers(behaviourModifiers) + , x20_animation(animation) {} + const zeus::CVector3f& GetPos() const { return x0_pos; } + const zeus::CVector3f& GetForward() const { return xc_forward; } + float GetSpeed() const { return x18_speed; } + u8 GetBehaviour() const { return x1c_behaviour; } + u8 GetBehaviourOrient() const { return x1d_behaviourOrient; } + u16 GetBehaviourModifiers() const { return x1e_behaviourModifiers; } + }; protected: - EPatrolState x2d8_patrolState = EPatrolState::Invalid; - TUniqueId x2dc_destObj = kInvalidUniqueId; - zeus::CVector3f x2e0_destPos; - zeus::CVector3f x2ec_reflectedDestPos; - float x2f8_waypointPauseRemTime = 0.f; - float x2fc_minAttackRange; - float x300_maxAttackRange; - float x304_averageAttackTime; - float x308_attackTimeVariation; - EBehaviourOrient x30c_behaviourOrient = EBehaviourOrient::MoveDir; - zeus::CVector3f x310_moveVec; - zeus::CVector3f x31c_faceVec; - union - { - struct - { - bool x328_24_inPosition : 1; - bool x328_25_verticalMovement : 1; - bool x328_26_longJump : 1; - bool x328_27_onGround : 1; - bool x328_28_prevOnGround : 1; - bool x328_29_noPatternShagging : 1; - bool x328_30_lookAtDeathDir : 1; - bool x328_31_ : 1; - bool x329_24_ : 1; - }; - u32 _dummy = 0; + EPatrolState x2d8_patrolState = EPatrolState::Invalid; + TUniqueId x2dc_destObj = kInvalidUniqueId; + zeus::CVector3f x2e0_destPos; + zeus::CVector3f x2ec_reflectedDestPos; + float x2f8_waypointPauseRemTime = 0.f; + float x2fc_minAttackRange; + float x300_maxAttackRange; + float x304_averageAttackTime; + float x308_attackTimeVariation; + EBehaviourOrient x30c_behaviourOrient = EBehaviourOrient::MoveDir; + zeus::CVector3f x310_moveVec; + zeus::CVector3f x31c_faceVec; + union { + struct { + bool x328_24_inPosition : 1; + bool x328_25_verticalMovement : 1; + bool x328_26_longJump : 1; + bool x328_27_onGround : 1; + bool x328_28_prevOnGround : 1; + bool x328_29_noPatternShagging : 1; + bool x328_30_lookAtDeathDir : 1; + bool x328_31_ : 1; + bool x329_24_ : 1; }; + u32 _dummy = 0; + }; - EAnimState x32c_animState = EAnimState::Zero; - CStateMachineState x330_stateMachineState; - ECharacter x34c_character; - zeus::CVector3f x350_patternStartPos; - zeus::CVector3f x35c_patternStartPlayerPos; - zeus::CVector3f x368_destWPDelta; - EPatternTranslate x374_patternTranslate = EPatternTranslate::RelativeStart; - EPatternOrient x378_patternOrient = EPatternOrient::ReversePlayerForward; - EPatternFit x37c_patternFit = EPatternFit::One; - EBehaviour x380_behaviour = EBehaviour::Zero; - EBehaviourModifiers x384_behaviourModifiers = EBehaviourModifiers::Zero; - s32 x388_anim; - std::vector x38c_patterns; - u32 x39c_curPattern = 0; - zeus::CVector3f x3a0_latestLeashPosition; - TUniqueId x3ac_lastPatrolDest = kInvalidUniqueId; - float x3b0_moveSpeed = 1.f; - float x3b4_speed; - float x3b8_turnSpeed; - float x3bc_detectionRange; - float x3c0_detectionHeightRange; - float x3c4_detectionAngle; - float x3c8_leashRadius; - float x3cc_playerLeashRadius; - float x3d0_playerLeashTime; - float x3d4_curPlayerLeashTime = 0.f; - float x3d8_xDamageThreshold; - float x3dc_frozenXDamageThreshold; - float x3e0_xDamageDelay; - float x3e4_lastHP = 0.f; - float x3e8_alphaDelta = 0.f; - float x3ec_pendingFireDamage = 0.f; - float x3f0_pendingShockDamage = 0.f; - float x3f4_burnThinkRateTimer = 0.f; - EMoveState x3f8_moveState = EMoveState::Zero; - EFlavorType x3fc_flavor; + EAnimState x32c_animState = EAnimState::Zero; + CStateMachineState x330_stateMachineState; + ECharacter x34c_character; + zeus::CVector3f x350_patternStartPos; + zeus::CVector3f x35c_patternStartPlayerPos; + zeus::CVector3f x368_destWPDelta; + EPatternTranslate x374_patternTranslate = EPatternTranslate::RelativeStart; + EPatternOrient x378_patternOrient = EPatternOrient::ReversePlayerForward; + EPatternFit x37c_patternFit = EPatternFit::One; + EBehaviour x380_behaviour = EBehaviour::Zero; + EBehaviourModifiers x384_behaviourModifiers = EBehaviourModifiers::Zero; + s32 x388_anim; + std::vector x38c_patterns; + u32 x39c_curPattern = 0; + zeus::CVector3f x3a0_latestLeashPosition; + TUniqueId x3ac_lastPatrolDest = kInvalidUniqueId; + float x3b0_moveSpeed = 1.f; + float x3b4_speed; + float x3b8_turnSpeed; + float x3bc_detectionRange; + float x3c0_detectionHeightRange; + float x3c4_detectionAngle; + float x3c8_leashRadius; + float x3cc_playerLeashRadius; + float x3d0_playerLeashTime; + float x3d4_curPlayerLeashTime = 0.f; + float x3d8_xDamageThreshold; + float x3dc_frozenXDamageThreshold; + float x3e0_xDamageDelay; + float x3e4_lastHP = 0.f; + float x3e8_alphaDelta = 0.f; + float x3ec_pendingFireDamage = 0.f; + float x3f0_pendingShockDamage = 0.f; + float x3f4_burnThinkRateTimer = 0.f; + EMoveState x3f8_moveState = EMoveState::Zero; + EFlavorType x3fc_flavor; - union - { - struct - { - bool x400_24_hitByPlayerProjectile : 1; - bool x400_25_alive : 1; // t - bool x400_26_ : 1; - bool x400_27_fadeToDeath : 1; - bool x400_28_pendingMassiveDeath : 1; - bool x400_29_pendingMassiveFrozenDeath : 1; - bool x400_30_patternShagged : 1; - bool x400_31_isFlyer : 1; - bool x401_24_pathOverCount : 2; - bool x401_26_disableMove : 1; - bool x401_27_phazingOut : 1; - bool x401_28_burning : 1; - bool x401_29_laggedBurnDeath : 1; - bool x401_30_pendingDeath : 1; - bool x401_31_nextPendingShock : 1; - bool x402_24_pendingShock : 1; - bool x402_25_lostMassiveFrozenHP : 1; - bool x402_26_dieIf80PercFrozen : 1; - bool x402_27_noXrayModel : 1; - bool x402_28_isMakingBigStrike : 1; - bool x402_29_drawParticles : 1; // t - bool x402_30_updateThermalFrozenState : 1; - bool x402_31_thawed : 1; - bool x403_24_keepThermalVisorState : 1; - bool x403_25_enableStateMachine : 1; // t - bool x403_26_stateControlledMassiveDeath : 1; // t - }; - u32 _dummy2 = 0; + union { + struct { + bool x400_24_hitByPlayerProjectile : 1; + bool x400_25_alive : 1; // t + bool x400_26_ : 1; + bool x400_27_fadeToDeath : 1; + bool x400_28_pendingMassiveDeath : 1; + bool x400_29_pendingMassiveFrozenDeath : 1; + bool x400_30_patternShagged : 1; + bool x400_31_isFlyer : 1; + bool x401_24_pathOverCount : 2; + bool x401_26_disableMove : 1; + bool x401_27_phazingOut : 1; + bool x401_28_burning : 1; + bool x401_29_laggedBurnDeath : 1; + bool x401_30_pendingDeath : 1; + bool x401_31_nextPendingShock : 1; + bool x402_24_pendingShock : 1; + bool x402_25_lostMassiveFrozenHP : 1; + bool x402_26_dieIf80PercFrozen : 1; + bool x402_27_noXrayModel : 1; + bool x402_28_isMakingBigStrike : 1; + bool x402_29_drawParticles : 1; // t + bool x402_30_updateThermalFrozenState : 1; + bool x402_31_thawed : 1; + bool x403_24_keepThermalVisorState : 1; + bool x403_25_enableStateMachine : 1; // t + bool x403_26_stateControlledMassiveDeath : 1; // t }; + u32 _dummy2 = 0; + }; - CDamageInfo x404_contactDamage; - float x420_curDamageRemTime = 0.f; - float x424_damageWaitTime; - float x428_damageCooldownTimer = -1.f; - zeus::CColor x42c_color = zeus::CColor::skBlack; - zeus::CColor x430_damageColor = skDamageColor; - zeus::CVector3f x434_posDelta; - zeus::CQuaternion x440_rotDelta; - CSteeringBehaviors x45c_steeringBehaviors; - std::unique_ptr x450_bodyController; - u16 x454_deathSfx; - u16 x458_iceShatterSfx; + CDamageInfo x404_contactDamage; + float x420_curDamageRemTime = 0.f; + float x424_damageWaitTime; + float x428_damageCooldownTimer = -1.f; + zeus::CColor x42c_color = zeus::CColor::skBlack; + zeus::CColor x430_damageColor = skDamageColor; + zeus::CVector3f x434_posDelta; + zeus::CQuaternion x440_rotDelta; + CSteeringBehaviors x45c_steeringBehaviors; + std::unique_ptr x450_bodyController; + u16 x454_deathSfx; + u16 x458_iceShatterSfx; - CKnockBackController x460_knockBackController; - zeus::CVector3f x4e4_latestPredictedTranslation; - float x4f0_predictedLeashTime = 0.f; - float x4f4_intoFreezeDur; - float x4f8_outofFreezeDur; - float x4fc_; - float x500_preThinkDt = 0.f; - float x504_damageDur = 0.f; - EColliderType x508_colliderType; - float x50c_baseDamageMag; - std::shared_ptr x510_vertexMorph; - zeus::CVector3f x514_deathExplosionOffset; - std::experimental::optional> x520_deathExplosionParticle; - std::experimental::optional> x530_deathExplosionElectric; - zeus::CVector3f x540_iceDeathExplosionOffset; - std::experimental::optional> x54c_iceDeathExplosionParticle; - zeus::CVector3f x55c_moveScale = zeus::CVector3f::skOne; + CKnockBackController x460_knockBackController; + zeus::CVector3f x4e4_latestPredictedTranslation; + float x4f0_predictedLeashTime = 0.f; + float x4f4_intoFreezeDur; + float x4f8_outofFreezeDur; + float x4fc_; + float x500_preThinkDt = 0.f; + float x504_damageDur = 0.f; + EColliderType x508_colliderType; + float x50c_baseDamageMag; + std::shared_ptr x510_vertexMorph; + zeus::CVector3f x514_deathExplosionOffset; + std::experimental::optional> x520_deathExplosionParticle; + std::experimental::optional> x530_deathExplosionElectric; + zeus::CVector3f x540_iceDeathExplosionOffset; + std::experimental::optional> x54c_iceDeathExplosionParticle; + zeus::CVector3f x55c_moveScale = zeus::CVector3f::skOne; + + void UpdateThermalFrozenState(bool thawed); + void GenerateIceDeathExplosion(CStateManager& mgr); + void GenerateDeathExplosion(CStateManager& mgr); + void RenderIceModelWithFlags(const CModelFlags& flags) const; + TUniqueId GetWaypointForState(CStateManager& mgr, EScriptObjectState state, EScriptObjectMessage msg) const; + void UpdateActorKeyframe(CStateManager& mgr) const; + pas::EStepDirection GetStepDirection(const zeus::CVector3f& moveVec) const; + bool IsPatternObstructed(CStateManager& mgr, const zeus::CVector3f& p0, const zeus::CVector3f& p1) const; + void UpdateDest(CStateManager& mgr); + void ApproachDest(CStateManager& mgr); + std::pair GetDestWaypoints(CStateManager& mgr) const; + zeus::CQuaternion FindPatternRotation(const zeus::CVector3f& dir) const; + zeus::CVector3f FindPatternDir(CStateManager& mgr) const; + void UpdatePatternDestPos(CStateManager& mgr); + void SetupPattern(CStateManager& mgr); + EScriptObjectState GetDesiredAttackState(CStateManager& mgr) const; + float GetAnimationDistance(const CPASAnimParmData& data) const; - void UpdateThermalFrozenState(bool thawed); - void GenerateIceDeathExplosion(CStateManager& mgr); - void GenerateDeathExplosion(CStateManager& mgr); - void RenderIceModelWithFlags(const CModelFlags& flags) const; - TUniqueId GetWaypointForState(CStateManager& mgr, EScriptObjectState state, EScriptObjectMessage msg) const; - void UpdateActorKeyframe(CStateManager& mgr) const; - pas::EStepDirection GetStepDirection(const zeus::CVector3f& moveVec) const; - bool IsPatternObstructed(CStateManager& mgr, const zeus::CVector3f& p0, const zeus::CVector3f& p1) const; - void UpdateDest(CStateManager& mgr); - void ApproachDest(CStateManager& mgr); - std::pair GetDestWaypoints(CStateManager& mgr) const; - zeus::CQuaternion FindPatternRotation(const zeus::CVector3f& dir) const; - zeus::CVector3f FindPatternDir(CStateManager& mgr) const; - void UpdatePatternDestPos(CStateManager& mgr); - void SetupPattern(CStateManager& mgr); - EScriptObjectState GetDesiredAttackState(CStateManager& mgr) const; - float GetAnimationDistance(const CPASAnimParmData& data) const; public: - CPatterned(ECharacter character, TUniqueId uid, std::string_view name, EFlavorType flavor, - const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, - const CPatternedInfo& pinfo, CPatterned::EMovementType movement, - EColliderType collider, EBodyType body, const CActorParameters& params, - EKnockBackVariant kbVariant); + CPatterned(ECharacter character, TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pinfo, + CPatterned::EMovementType movement, EColliderType collider, EBodyType body, const CActorParameters& params, + EKnockBackVariant kbVariant); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void PreThink(float, CStateManager& mgr) { CEntity::Think(x500_preThinkDt, mgr); } - void Think(float, CStateManager&); - void PreRender(CStateManager&, const zeus::CFrustum&); - void Render(const CStateManager& mgr) const; + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PreThink(float, CStateManager& mgr) { CEntity::Think(x500_preThinkDt, mgr); } + void Think(float, CStateManager&); + void PreRender(CStateManager&, const zeus::CFrustum&); + void Render(const CStateManager& mgr) const; - void Touch(CActor& act, CStateManager& mgr); - std::experimental::optional GetTouchBounds() const; - bool CanRenderUnsorted(const CStateManager& mgr) const; - zeus::CVector3f GetOrbitPosition(const CStateManager& mgr) const - { - return GetAimPosition(mgr, 0.f); - } - zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const; - zeus::CTransform GetLctrTransform(std::string_view name) const; - zeus::CTransform GetLctrTransform(CSegId id) const; + void Touch(CActor& act, CStateManager& mgr); + std::experimental::optional GetTouchBounds() const; + bool CanRenderUnsorted(const CStateManager& mgr) const; + zeus::CVector3f GetOrbitPosition(const CStateManager& mgr) const { return GetAimPosition(mgr, 0.f); } + zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const; + zeus::CTransform GetLctrTransform(std::string_view name) const; + zeus::CTransform GetLctrTransform(CSegId id) const; - bool ApplyBoneTracking() const; + bool ApplyBoneTracking() const; - void DeathDelete(CStateManager& mgr); - void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); - void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, - EKnockBackType type, bool inDeferred, float magnitude); - void TakeDamage(const zeus::CVector3f&, float arg); - bool FixedRandom(CStateManager&, float arg); - bool Random(CStateManager&, float arg); - bool CodeTrigger(CStateManager&, float arg); - bool FixedDelay(CStateManager&, float arg); - bool RandomDelay(CStateManager&, float arg); - bool Delay(CStateManager&, float arg); - bool PatrolPathOver(CStateManager&, float arg); - bool Stuck(CStateManager&, float arg); - bool AnimOver(CStateManager&, float arg); - bool InPosition(CStateManager&, float arg); - bool HasPatrolPath(CStateManager& mgr, float arg); - bool Attacked(CStateManager&, float arg); - bool PatternShagged(CStateManager&, float arg); - bool PatternOver(CStateManager&, float arg); - bool HasRetreatPattern(CStateManager& mgr, float arg); - bool HasAttackPattern(CStateManager& mgr, float arg); - bool NoPathNodes(CStateManager&, float arg); - bool PathShagged(CStateManager&, float arg); - bool PathFound(CStateManager&, float arg); - bool PathOver(CStateManager&, float arg); - bool Landed(CStateManager&, float arg); - bool PlayerSpot(CStateManager&, float arg); - bool SpotPlayer(CStateManager&, float arg); - bool Leash(CStateManager&, float arg); - bool InDetectionRange(CStateManager&, float arg); - bool InMaxRange(CStateManager&, float arg); - bool TooClose(CStateManager&, float arg); - bool InRange(CStateManager&, float arg); - bool OffLine(CStateManager&, float arg); - bool Default(CStateManager&, float arg) { return true; } - void PathFind(CStateManager&, EStateMsg msg, float dt); - void Dead(CStateManager&, EStateMsg msg, float dt); - void TargetPlayer(CStateManager&, EStateMsg msg, float dt); - void TargetPatrol(CStateManager&, EStateMsg msg, float dt); - void FollowPattern(CStateManager&, EStateMsg msg, float dt); - void Patrol(CStateManager&, EStateMsg msg, float dt); - void Start(CStateManager&, EStateMsg msg, float dt) {} + void DeathDelete(CStateManager& mgr); + void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state); + void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, EKnockBackType type, bool inDeferred, + float magnitude); + void TakeDamage(const zeus::CVector3f&, float arg); + bool FixedRandom(CStateManager&, float arg); + bool Random(CStateManager&, float arg); + bool CodeTrigger(CStateManager&, float arg); + bool FixedDelay(CStateManager&, float arg); + bool RandomDelay(CStateManager&, float arg); + bool Delay(CStateManager&, float arg); + bool PatrolPathOver(CStateManager&, float arg); + bool Stuck(CStateManager&, float arg); + bool AnimOver(CStateManager&, float arg); + bool InPosition(CStateManager&, float arg); + bool HasPatrolPath(CStateManager& mgr, float arg); + bool Attacked(CStateManager&, float arg); + bool PatternShagged(CStateManager&, float arg); + bool PatternOver(CStateManager&, float arg); + bool HasRetreatPattern(CStateManager& mgr, float arg); + bool HasAttackPattern(CStateManager& mgr, float arg); + bool NoPathNodes(CStateManager&, float arg); + bool PathShagged(CStateManager&, float arg); + bool PathFound(CStateManager&, float arg); + bool PathOver(CStateManager&, float arg); + bool Landed(CStateManager&, float arg); + bool PlayerSpot(CStateManager&, float arg); + bool SpotPlayer(CStateManager&, float arg); + bool Leash(CStateManager&, float arg); + bool InDetectionRange(CStateManager&, float arg); + bool InMaxRange(CStateManager&, float arg); + bool TooClose(CStateManager&, float arg); + bool InRange(CStateManager&, float arg); + bool OffLine(CStateManager&, float arg); + bool Default(CStateManager&, float arg) { return true; } + void PathFind(CStateManager&, EStateMsg msg, float dt); + void Dead(CStateManager&, EStateMsg msg, float dt); + void TargetPlayer(CStateManager&, EStateMsg msg, float dt); + void TargetPatrol(CStateManager&, EStateMsg msg, float dt); + void FollowPattern(CStateManager&, EStateMsg msg, float dt); + void Patrol(CStateManager&, EStateMsg msg, float dt); + void Start(CStateManager&, EStateMsg msg, float dt) {} - void TryCommand(CStateManager& mgr, pas::EAnimationState state, CPatternedTryFunc func, int arg); - void TryLoopReaction(CStateManager& mgr, int arg); - void TryProjectileAttack(CStateManager& mgr, int arg); - void TryGenerate(CStateManager& mgr, int arg); + void TryCommand(CStateManager& mgr, pas::EAnimationState state, CPatternedTryFunc func, int arg); + void TryLoopReaction(CStateManager& mgr, int arg); + void TryProjectileAttack(CStateManager& mgr, int arg); + void TryGenerate(CStateManager& mgr, int arg); - virtual bool KnockbackWhenFrozen() const { return true; } - virtual void MassiveDeath(CStateManager& mgr); - virtual void MassiveFrozenDeath(CStateManager& mgr); - virtual void Burn(float, float); - virtual void Shock(float, float); - virtual void Freeze(CStateManager& mgr, const zeus::CVector3f& pos, - const zeus::CUnitVector3f& dir, float frozenDur); - virtual void ThinkAboutMove(float); - virtual CPathFindSearch* GetSearchPath() { return nullptr; } - virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; } - virtual u8 GetModelAlphau8(const CStateManager&) const { return u8(x42c_color.a() * 255);} - virtual bool IsOnGround() const { return x328_27_onGround; } - virtual float GetGravityConstant() const { return 24.525002f; } - virtual CProjectileInfo* GetProjectileInfo() { return nullptr; } - virtual void PhazeOut(CStateManager&); - virtual const std::experimental::optional>& - GetDeathExplosionParticle() const { return x520_deathExplosionParticle; } - float GetDamageDuration() const { return x504_damageDur; } - zeus::CVector3f GetGunEyePos() const; - bool IsAlive() const { return x400_25_alive; } + virtual bool KnockbackWhenFrozen() const { return true; } + virtual void MassiveDeath(CStateManager& mgr); + virtual void MassiveFrozenDeath(CStateManager& mgr); + virtual void Burn(float, float); + virtual void Shock(float, float); + virtual void Freeze(CStateManager& mgr, const zeus::CVector3f& pos, const zeus::CUnitVector3f& dir, float frozenDur); + virtual void ThinkAboutMove(float); + virtual CPathFindSearch* GetSearchPath() { return nullptr; } + virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; } + virtual u8 GetModelAlphau8(const CStateManager&) const { return u8(x42c_color.a() * 255); } + virtual bool IsOnGround() const { return x328_27_onGround; } + virtual float GetGravityConstant() const { return 24.525002f; } + virtual CProjectileInfo* GetProjectileInfo() { return nullptr; } + virtual void PhazeOut(CStateManager&); + virtual const std::experimental::optional>& GetDeathExplosionParticle() const { + return x520_deathExplosionParticle; + } + float GetDamageDuration() const { return x504_damageDur; } + zeus::CVector3f GetGunEyePos() const; + bool IsAlive() const { return x400_25_alive; } - void BuildBodyController(EBodyType); - const CBodyController* GetBodyController() const { return x450_bodyController.get(); } - CBodyController* BodyController() { return x450_bodyController.get(); } - const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; } - void SetupPlayerCollision(bool); - void LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, EProjectileAttrib attrib, - bool playerHoming, const std::experimental::optional>& visorParticle, - u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale); - void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); + void BuildBodyController(EBodyType); + const CBodyController* GetBodyController() const { return x450_bodyController.get(); } + CBodyController* BodyController() { return x450_bodyController.get(); } + const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; } + void SetupPlayerCollision(bool); + void LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, EProjectileAttrib attrib, + bool playerHoming, + const std::experimental::optional>& visorParticle, u16 visorSfx, + bool sendCollideMsg, const zeus::CVector3f& scale); + void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt); - void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; } - void UpdateAlphaDelta(float dt, CStateManager& mgr); - void SetModelAlpha(float a) { x42c_color.a() = a; } - float CalcDyingThinkRate(); - void UpdateDamageColor(float dt); + void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; } + void UpdateAlphaDelta(float dt, CStateManager& mgr); + void SetModelAlpha(float a) { x42c_color.a() = a; } + float CalcDyingThinkRate(); + void UpdateDamageColor(float dt); - bool CanLongJump() const { return x328_26_longJump; } - bool IsMakingBigStrike() const { return x402_28_isMakingBigStrike; } + bool CanLongJump() const { return x328_26_longJump; } + bool IsMakingBigStrike() const { return x402_28_isMakingBigStrike; } - void SetKeepInThermalVisor() - { - x403_24_keepThermalVisorState = true; - xe6_27_thermalVisorFlags = 1 | 2; - } + void SetKeepInThermalVisor() { + x403_24_keepThermalVisorState = true; + xe6_27_thermalVisorFlags = 1 | 2; + } - //region Casting Functions + // region Casting Functions - template - static T* CastTo(CEntity* ent) - { - if (TCastToPtr patterned = ent) - return CastTo(patterned.GetPtr()); - return nullptr; - } + template + static T* CastTo(CEntity* ent) { + if (TCastToPtr patterned = ent) + return CastTo(patterned.GetPtr()); + return nullptr; + } - template - static const T* CastTo(const CEntity* ent) - { - if (TCastToConstPtr patterned = ent) - return CastTo(patterned.GetPtr()); - return nullptr; - } + template + static const T* CastTo(const CEntity* ent) { + if (TCastToConstPtr patterned = ent) + return CastTo(patterned.GetPtr()); + return nullptr; + } - template - static T* CastTo(CPatterned* patterned) - { - if (patterned->x34c_character == T::CharacterType) - return static_cast(patterned); - return nullptr; - } + template + static T* CastTo(CPatterned* patterned) { + if (patterned->x34c_character == T::CharacterType) + return static_cast(patterned); + return nullptr; + } - template - static const T* CastTo(const CPatterned* patterned) - { - if (patterned->x34c_character == T::CharacterType) - return static_cast(patterned); - return nullptr; - } + template + static const T* CastTo(const CPatterned* patterned) { + if (patterned->x34c_character == T::CharacterType) + return static_cast(patterned); + return nullptr; + } - //endregion + // endregion }; -} - +} // namespace urde diff --git a/Runtime/World/CPatternedInfo.cpp b/Runtime/World/CPatternedInfo.cpp index a51b74a4a..4ef21edec 100644 --- a/Runtime/World/CPatternedInfo.cpp +++ b/Runtime/World/CPatternedInfo.cpp @@ -1,8 +1,7 @@ #include "CPatternedInfo.hpp" #include "Audio/CSfxManager.hpp" -namespace urde -{ +namespace urde { CPatternedInfo::CPatternedInfo(CInputStream& in, u32 pcount) : x0_mass(in.readFloatBig()) @@ -39,19 +38,17 @@ CPatternedInfo::CPatternedInfo(CInputStream& in, u32 pcount) , x10c_pathfindingIndex(in.readUint32Big()) , x110_particle1Scale(zeus::CVector3f::ReadBig(in)) , x11c_particle1(in) -, x120_electric(in) -{ - if (pcount >= 36) - x124_particle2Scale.readBig(in); - if (pcount >= 37) - x130_particle2 = CAssetId(in); - if (pcount >= 38) - x134_iceShatterSfx = CSfxManager::TranslateSFXID(in.readUint32Big()); +, x120_electric(in) { + if (pcount >= 36) + x124_particle2Scale.readBig(in); + if (pcount >= 37) + x130_particle2 = CAssetId(in); + if (pcount >= 38) + x134_iceShatterSfx = CSfxManager::TranslateSFXID(in.readUint32Big()); } -std::pair CPatternedInfo::HasCorrectParameterCount(CInputStream& in) -{ - u32 pcount = in.readUint32Big(); - return {(pcount >= 35 && pcount <= 38), pcount}; -} +std::pair CPatternedInfo::HasCorrectParameterCount(CInputStream& in) { + u32 pcount = in.readUint32Big(); + return {(pcount >= 35 && pcount <= 38), pcount}; } +} // namespace urde diff --git a/Runtime/World/CPatternedInfo.hpp b/Runtime/World/CPatternedInfo.hpp index 60fb3a532..c4308470b 100644 --- a/Runtime/World/CPatternedInfo.hpp +++ b/Runtime/World/CPatternedInfo.hpp @@ -7,65 +7,62 @@ #include "CAnimationParameters.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { -class CPatternedInfo -{ - friend class CPatterned; - float x0_mass; - float x4_speed; - float x8_turnSpeed; - float xc_detectionRange; - float x10_detectionHeightRange; - float x14_dectectionAngle; - float x18_minAttackRange; - float x1c_maxAttackRange; - float x20_averageAttackTime; - float x24_attackTimeVariation; - float x28_leashRadius; - float x2c_playerLeashRadius; - float x30_playerLeashTime; - CDamageInfo x34_contactDamageInfo; - float x50_damageWaitTime; - CHealthInfo x54_healthInfo; - CDamageVulnerability x5c_damageVulnerability; - float xc4_halfExtent; - float xc8_height; - zeus::CVector3f xcc_bodyOrigin; - float xd8_stepUpHeight; - float xdc_xDamage; - float xe0_frozenXDamage; - float xe4_xDamageDelay; - u16 xe8_deathSfx; - CAnimationParameters xec_animParams; - bool xf8_active; - CAssetId xfc_stateMachineId; - float x100_intoFreezeDur; - float x104_outofFreezeDur; - float x108_; +class CPatternedInfo { + friend class CPatterned; + float x0_mass; + float x4_speed; + float x8_turnSpeed; + float xc_detectionRange; + float x10_detectionHeightRange; + float x14_dectectionAngle; + float x18_minAttackRange; + float x1c_maxAttackRange; + float x20_averageAttackTime; + float x24_attackTimeVariation; + float x28_leashRadius; + float x2c_playerLeashRadius; + float x30_playerLeashTime; + CDamageInfo x34_contactDamageInfo; + float x50_damageWaitTime; + CHealthInfo x54_healthInfo; + CDamageVulnerability x5c_damageVulnerability; + float xc4_halfExtent; + float xc8_height; + zeus::CVector3f xcc_bodyOrigin; + float xd8_stepUpHeight; + float xdc_xDamage; + float xe0_frozenXDamage; + float xe4_xDamageDelay; + u16 xe8_deathSfx; + CAnimationParameters xec_animParams; + bool xf8_active; + CAssetId xfc_stateMachineId; + float x100_intoFreezeDur; + float x104_outofFreezeDur; + float x108_; - u32 x10c_pathfindingIndex; - zeus::CVector3f x110_particle1Scale; - CAssetId x11c_particle1; + u32 x10c_pathfindingIndex; + zeus::CVector3f x110_particle1Scale; + CAssetId x11c_particle1; - CAssetId x120_electric; - zeus::CVector3f x124_particle2Scale; - CAssetId x130_particle2; + CAssetId x120_electric; + zeus::CVector3f x124_particle2Scale; + CAssetId x130_particle2; - u16 x134_iceShatterSfx = 0xffff; + u16 x134_iceShatterSfx = 0xffff; public: - CPatternedInfo(CInputStream& in, u32 pcount); - static std::pair HasCorrectParameterCount(CInputStream& in); + CPatternedInfo(CInputStream& in, u32 pcount); + static std::pair HasCorrectParameterCount(CInputStream& in); - float GetDetectionHeightRange() const { return x10_detectionHeightRange; } - float GetHalfExtent() const { return xc4_halfExtent; } - float GetHeight() const { return xc8_height; } - const CHealthInfo& GetHealthInfo() const { return x54_healthInfo; } - CAnimationParameters& GetAnimationParameters() { return xec_animParams; } - const CAnimationParameters& GetAnimationParameters() const { return xec_animParams; } - u32 GetPathfindingIndex() const { return x10c_pathfindingIndex; } + float GetDetectionHeightRange() const { return x10_detectionHeightRange; } + float GetHalfExtent() const { return xc4_halfExtent; } + float GetHeight() const { return xc8_height; } + const CHealthInfo& GetHealthInfo() const { return x54_healthInfo; } + CAnimationParameters& GetAnimationParameters() { return xec_animParams; } + const CAnimationParameters& GetAnimationParameters() const { return xec_animParams; } + u32 GetPathfindingIndex() const { return x10c_pathfindingIndex; } }; -} - +} // namespace urde diff --git a/Runtime/World/CPhysicsActor.cpp b/Runtime/World/CPhysicsActor.cpp index 10e3f38f0..797cb88dc 100644 --- a/Runtime/World/CPhysicsActor.cpp +++ b/Runtime/World/CPhysicsActor.cpp @@ -1,7 +1,6 @@ #include "CPhysicsActor.hpp" -namespace urde -{ +namespace urde { CPhysicsActor::CPhysicsActor(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CMaterialList& matList, @@ -15,35 +14,32 @@ CPhysicsActor::CPhysicsActor(TUniqueId uid, bool active, std::string_view name, , x1c0_collisionPrimitive(box, matList) , x1f4_lastNonCollidingState(xf.origin, xf.buildMatrix3f()) , x23c_stepUpHeight(stepUp) -, x240_stepDownHeight(stepDown) -{ - xf8_24_movable = true; - SetMass(moverData.x30_mass); - MoveCollisionPrimitive(zeus::CVector3f::skZero); - SetVelocityOR(moverData.x0_velocity); - SetAngularVelocityOR(moverData.xc_angularVelocity); - ComputeDerivedQuantities(); +, x240_stepDownHeight(stepDown) { + xf8_24_movable = true; + SetMass(moverData.x30_mass); + MoveCollisionPrimitive(zeus::CVector3f::skZero); + SetVelocityOR(moverData.x0_velocity); + SetAngularVelocityOR(moverData.xc_angularVelocity); + ComputeDerivedQuantities(); } void CPhysicsActor::Render(const CStateManager& mgr) const { CActor::Render(mgr); } zeus::CVector3f CPhysicsActor::GetOrbitPosition(const CStateManager&) const { return GetBoundingBox().center(); } -zeus::CVector3f CPhysicsActor::GetAimPosition(const CStateManager&, float dt) const -{ - if (dt <= 0.0) - return GetBoundingBox().center(); - zeus::CVector3f trans = PredictMotion(dt).x0_translation; - return GetBoundingBox().center() + trans; +zeus::CVector3f CPhysicsActor::GetAimPosition(const CStateManager&, float dt) const { + if (dt <= 0.0) + return GetBoundingBox().center(); + zeus::CVector3f trans = PredictMotion(dt).x0_translation; + return GetBoundingBox().center() + trans; } void CPhysicsActor::CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager&) {} const CCollisionPrimitive* CPhysicsActor::GetCollisionPrimitive() const { return &x1c0_collisionPrimitive; } -zeus::CTransform CPhysicsActor::GetPrimitiveTransform() const -{ - return zeus::CTransform::Translate(x34_transform.origin + x1e8_primitiveOffset); +zeus::CTransform CPhysicsActor::GetPrimitiveTransform() const { + return zeus::CTransform::Translate(x34_transform.origin + x1e8_primitiveOffset); } float CPhysicsActor::GetStepUpHeight() const { return x23c_stepUpHeight; } @@ -58,296 +54,261 @@ zeus::CVector3f CPhysicsActor::GetPrimitiveOffset() const { return x1e8_primitiv void CPhysicsActor::MoveCollisionPrimitive(const zeus::CVector3f& offset) { x1e8_primitiveOffset = offset; } -void CPhysicsActor::SetBoundingBox(const zeus::CAABox& box) -{ - x1a4_baseBoundingBox = box; - MoveCollisionPrimitive(zeus::CVector3f::skZero); +void CPhysicsActor::SetBoundingBox(const zeus::CAABox& box) { + x1a4_baseBoundingBox = box; + MoveCollisionPrimitive(zeus::CVector3f::skZero); } -zeus::CAABox CPhysicsActor::GetMotionVolume(float dt) const -{ - zeus::CAABox aabox = GetCollisionPrimitive()->CalculateAABox(GetPrimitiveTransform()); - zeus::CVector3f velocity = CalculateNewVelocityWR_UsingImpulses(); +zeus::CAABox CPhysicsActor::GetMotionVolume(float dt) const { + zeus::CAABox aabox = GetCollisionPrimitive()->CalculateAABox(GetPrimitiveTransform()); + zeus::CVector3f velocity = CalculateNewVelocityWR_UsingImpulses(); - const zeus::CVector3f dv = (dt * velocity); - aabox.accumulateBounds(aabox.max + dv); - aabox.accumulateBounds(aabox.min + dv); + const zeus::CVector3f dv = (dt * velocity); + aabox.accumulateBounds(aabox.max + dv); + aabox.accumulateBounds(aabox.min + dv); - float up = GetStepUpHeight(); - up = zeus::max(up, 0.f); - aabox.accumulateBounds(aabox.max + zeus::CVector3f(0.5f, 0.5f, up + 1.f)); + float up = GetStepUpHeight(); + up = zeus::max(up, 0.f); + aabox.accumulateBounds(aabox.max + zeus::CVector3f(0.5f, 0.5f, up + 1.f)); - float down = GetStepDownHeight(); - down = zeus::max(down, 0.f); - aabox.accumulateBounds(aabox.min - zeus::CVector3f(0.5f, 0.5f, down + 1.5f)); - return aabox; + float down = GetStepDownHeight(); + down = zeus::max(down, 0.f); + aabox.accumulateBounds(aabox.min - zeus::CVector3f(0.5f, 0.5f, down + 1.5f)); + return aabox; } -zeus::CVector3f CPhysicsActor::CalculateNewVelocityWR_UsingImpulses() const -{ - return x138_velocity + (xec_massRecip * (x168_impulse + x18c_moveImpulse)); +zeus::CVector3f CPhysicsActor::CalculateNewVelocityWR_UsingImpulses() const { + return x138_velocity + (xec_massRecip * (x168_impulse + x18c_moveImpulse)); } -zeus::CAABox CPhysicsActor::GetBoundingBox() const -{ - return {x1a4_baseBoundingBox.min + x1e8_primitiveOffset + x34_transform.origin, - x1a4_baseBoundingBox.max + x1e8_primitiveOffset + x34_transform.origin}; +zeus::CAABox CPhysicsActor::GetBoundingBox() const { + return {x1a4_baseBoundingBox.min + x1e8_primitiveOffset + x34_transform.origin, + x1a4_baseBoundingBox.max + x1e8_primitiveOffset + x34_transform.origin}; } const zeus::CAABox& CPhysicsActor::GetBaseBoundingBox() const { return x1a4_baseBoundingBox; } -void CPhysicsActor::AddMotionState(const CMotionState& mst) -{ - zeus::CNUQuaternion q{x34_transform.buildMatrix3f()}; - q += mst.xc_orientation; - zeus::CQuaternion quat = zeus::CQuaternion::fromNUQuaternion(q); - SetTransform(zeus::CTransform(quat, x34_transform.origin)); +void CPhysicsActor::AddMotionState(const CMotionState& mst) { + zeus::CNUQuaternion q{x34_transform.buildMatrix3f()}; + q += mst.xc_orientation; + zeus::CQuaternion quat = zeus::CQuaternion::fromNUQuaternion(q); + SetTransform(zeus::CTransform(quat, x34_transform.origin)); - SetTranslation(x34_transform.origin + mst.x0_translation); + SetTranslation(x34_transform.origin + mst.x0_translation); - xfc_constantForce += mst.x1c_velocity; - x108_angularMomentum += mst.x28_angularMomentum; + xfc_constantForce += mst.x1c_velocity; + x108_angularMomentum += mst.x28_angularMomentum; - ComputeDerivedQuantities(); + ComputeDerivedQuantities(); } -CMotionState CPhysicsActor::GetMotionState() const -{ - return {x34_transform.origin, {x34_transform.buildMatrix3f()}, xfc_constantForce, x108_angularMomentum}; +CMotionState CPhysicsActor::GetMotionState() const { + return {x34_transform.origin, {x34_transform.buildMatrix3f()}, xfc_constantForce, x108_angularMomentum}; } -void CPhysicsActor::SetMotionState(const CMotionState& mst) -{ - SetTransform(zeus::CTransform(zeus::CQuaternion::fromNUQuaternion(mst.xc_orientation), x34_transform.origin)); - SetTranslation(mst.x0_translation); +void CPhysicsActor::SetMotionState(const CMotionState& mst) { + SetTransform(zeus::CTransform(zeus::CQuaternion::fromNUQuaternion(mst.xc_orientation), x34_transform.origin)); + SetTranslation(mst.x0_translation); - xfc_constantForce = mst.x1c_velocity; - x108_angularMomentum = mst.x28_angularMomentum; - ComputeDerivedQuantities(); + xfc_constantForce = mst.x1c_velocity; + x108_angularMomentum = mst.x28_angularMomentum; + ComputeDerivedQuantities(); } -void CPhysicsActor::SetInertiaTensorScalar(float tensor) -{ - if (tensor <= 0.0f) - tensor = 1.0f; - xf0_inertiaTensor = tensor; - xf4_inertiaTensorRecip = 1.0f / tensor; +void CPhysicsActor::SetInertiaTensorScalar(float tensor) { + if (tensor <= 0.0f) + tensor = 1.0f; + xf0_inertiaTensor = tensor; + xf4_inertiaTensorRecip = 1.0f / tensor; } -void CPhysicsActor::SetMass(float mass) -{ - xe8_mass = mass; - float tensor = 1.0f; - if (mass > 0.0f) - tensor = 1.0f / mass; +void CPhysicsActor::SetMass(float mass) { + xe8_mass = mass; + float tensor = 1.0f; + if (mass > 0.0f) + tensor = 1.0f / mass; - xec_massRecip = tensor; - SetInertiaTensorScalar(mass / 6.f); + xec_massRecip = tensor; + SetInertiaTensorScalar(mass / 6.f); } -void CPhysicsActor::SetAngularVelocityOR(const zeus::CAxisAngle& angVel) -{ - x144_angularVelocity = x34_transform.rotate(angVel); - x108_angularMomentum = xf0_inertiaTensor * x144_angularVelocity; +void CPhysicsActor::SetAngularVelocityOR(const zeus::CAxisAngle& angVel) { + x144_angularVelocity = x34_transform.rotate(angVel); + x108_angularMomentum = xf0_inertiaTensor * x144_angularVelocity; } -zeus::CAxisAngle CPhysicsActor::GetAngularVelocityOR() const -{ - return x34_transform.transposeRotate(x144_angularVelocity); +zeus::CAxisAngle CPhysicsActor::GetAngularVelocityOR() const { + return x34_transform.transposeRotate(x144_angularVelocity); } -void CPhysicsActor::SetAngularVelocityWR(const zeus::CAxisAngle& angVel) -{ - x144_angularVelocity = angVel; - x108_angularMomentum = xf0_inertiaTensor * x144_angularVelocity; +void CPhysicsActor::SetAngularVelocityWR(const zeus::CAxisAngle& angVel) { + x144_angularVelocity = angVel; + x108_angularMomentum = xf0_inertiaTensor * x144_angularVelocity; } -void CPhysicsActor::SetVelocityWR(const zeus::CVector3f& vel) -{ - x138_velocity = vel; - xfc_constantForce = xe8_mass * x138_velocity; +void CPhysicsActor::SetVelocityWR(const zeus::CVector3f& vel) { + x138_velocity = vel; + xfc_constantForce = xe8_mass * x138_velocity; } void CPhysicsActor::SetVelocityOR(const zeus::CVector3f& vel) { SetVelocityWR(x34_transform.rotate(vel)); } zeus::CVector3f CPhysicsActor::GetTotalForcesWR() const { return x15c_force + x150_momentum; } -void CPhysicsActor::RotateInOneFrameOR(const zeus::CQuaternion& q, float d) -{ - x198_moveAngularImpulse += GetRotateToORAngularMomentumWR(q, d); +void CPhysicsActor::RotateInOneFrameOR(const zeus::CQuaternion& q, float d) { + x198_moveAngularImpulse += GetRotateToORAngularMomentumWR(q, d); } -void CPhysicsActor::MoveInOneFrameOR(const zeus::CVector3f& trans, float d) -{ - x18c_moveImpulse += GetMoveToORImpulseWR(trans, d); +void CPhysicsActor::MoveInOneFrameOR(const zeus::CVector3f& trans, float d) { + x18c_moveImpulse += GetMoveToORImpulseWR(trans, d); } -void CPhysicsActor::RotateToOR(const zeus::CQuaternion& q, float d) -{ - x108_angularMomentum = GetRotateToORAngularMomentumWR(q, d); - ComputeDerivedQuantities(); +void CPhysicsActor::RotateToOR(const zeus::CQuaternion& q, float d) { + x108_angularMomentum = GetRotateToORAngularMomentumWR(q, d); + ComputeDerivedQuantities(); } -void CPhysicsActor::MoveToOR(const zeus::CVector3f& trans, float d) -{ - xfc_constantForce = GetMoveToORImpulseWR(trans, d); - ComputeDerivedQuantities(); +void CPhysicsActor::MoveToOR(const zeus::CVector3f& trans, float d) { + xfc_constantForce = GetMoveToORImpulseWR(trans, d); + ComputeDerivedQuantities(); } -void CPhysicsActor::MoveToInOneFrameWR(const zeus::CVector3f& trans, float d) -{ - x18c_moveImpulse += xe8_mass * (trans - x34_transform.origin) * (1.f / d); +void CPhysicsActor::MoveToInOneFrameWR(const zeus::CVector3f& trans, float d) { + x18c_moveImpulse += xe8_mass * (trans - x34_transform.origin) * (1.f / d); } -void CPhysicsActor::MoveToWR(const zeus::CVector3f& trans, float d) -{ - xfc_constantForce = xe8_mass * (trans - x34_transform.origin) * (1.f / d); - ComputeDerivedQuantities(); +void CPhysicsActor::MoveToWR(const zeus::CVector3f& trans, float d) { + xfc_constantForce = xe8_mass * (trans - x34_transform.origin) * (1.f / d); + ComputeDerivedQuantities(); } -zeus::CAxisAngle CPhysicsActor::GetRotateToORAngularMomentumWR(const zeus::CQuaternion& q, float d) const -{ - if (q.w() > 0.99999976) - return zeus::CAxisAngle::skZero; - return (xf0_inertiaTensor * - (((2.f * std::acos(q.w())) * (1.f / d)) * x34_transform.rotate(q.getImaginary()).normalized())); +zeus::CAxisAngle CPhysicsActor::GetRotateToORAngularMomentumWR(const zeus::CQuaternion& q, float d) const { + if (q.w() > 0.99999976) + return zeus::CAxisAngle::skZero; + return (xf0_inertiaTensor * + (((2.f * std::acos(q.w())) * (1.f / d)) * x34_transform.rotate(q.getImaginary()).normalized())); } -zeus::CVector3f CPhysicsActor::GetMoveToORImpulseWR(const zeus::CVector3f& trans, float d) const -{ - return (xe8_mass * x34_transform.rotate(trans)) * (1.f / d); +zeus::CVector3f CPhysicsActor::GetMoveToORImpulseWR(const zeus::CVector3f& trans, float d) const { + return (xe8_mass * x34_transform.rotate(trans)) * (1.f / d); } -void CPhysicsActor::ClearImpulses() -{ - x18c_moveImpulse = x168_impulse = zeus::CVector3f::skZero; - x198_moveAngularImpulse = x180_angularImpulse = zeus::CAxisAngle::skZero; +void CPhysicsActor::ClearImpulses() { + x18c_moveImpulse = x168_impulse = zeus::CVector3f::skZero; + x198_moveAngularImpulse = x180_angularImpulse = zeus::CAxisAngle::skZero; } -void CPhysicsActor::ClearForcesAndTorques() -{ - x18c_moveImpulse = x168_impulse = x15c_force = zeus::CVector3f::skZero; - x198_moveAngularImpulse = x180_angularImpulse = x174_torque = zeus::CAxisAngle::skZero; +void CPhysicsActor::ClearForcesAndTorques() { + x18c_moveImpulse = x168_impulse = x15c_force = zeus::CVector3f::skZero; + x198_moveAngularImpulse = x180_angularImpulse = x174_torque = zeus::CAxisAngle::skZero; } -void CPhysicsActor::Stop() -{ - ClearForcesAndTorques(); - xfc_constantForce = zeus::CVector3f::skZero; - x108_angularMomentum = zeus::CAxisAngle::skZero; - ComputeDerivedQuantities(); +void CPhysicsActor::Stop() { + ClearForcesAndTorques(); + xfc_constantForce = zeus::CVector3f::skZero; + x108_angularMomentum = zeus::CAxisAngle::skZero; + ComputeDerivedQuantities(); } -void CPhysicsActor::ComputeDerivedQuantities() -{ - x138_velocity = xec_massRecip * xfc_constantForce; - x114_ = x34_transform.buildMatrix3f(); - x144_angularVelocity = xf4_inertiaTensorRecip * x108_angularMomentum; +void CPhysicsActor::ComputeDerivedQuantities() { + x138_velocity = xec_massRecip * xfc_constantForce; + x114_ = x34_transform.buildMatrix3f(); + x144_angularVelocity = xf4_inertiaTensorRecip * x108_angularMomentum; } -bool CPhysicsActor::WillMove(const CStateManager&) -{ - return !zeus::close_enough(zeus::CVector3f::skZero, x138_velocity) || - !zeus::close_enough(zeus::CVector3f::skZero, x168_impulse) || - !zeus::close_enough(zeus::CVector3f::skZero, x174_torque) || - !zeus::close_enough(zeus::CVector3f::skZero, x18c_moveImpulse) || - !zeus::close_enough(zeus::CVector3f::skZero, x144_angularVelocity) || - !zeus::close_enough(zeus::CVector3f::skZero, x180_angularImpulse) || - !zeus::close_enough(zeus::CVector3f::skZero, x198_moveAngularImpulse) || - !zeus::close_enough(zeus::CVector3f::skZero, GetTotalForcesWR()); +bool CPhysicsActor::WillMove(const CStateManager&) { + return !zeus::close_enough(zeus::CVector3f::skZero, x138_velocity) || + !zeus::close_enough(zeus::CVector3f::skZero, x168_impulse) || + !zeus::close_enough(zeus::CVector3f::skZero, x174_torque) || + !zeus::close_enough(zeus::CVector3f::skZero, x18c_moveImpulse) || + !zeus::close_enough(zeus::CVector3f::skZero, x144_angularVelocity) || + !zeus::close_enough(zeus::CVector3f::skZero, x180_angularImpulse) || + !zeus::close_enough(zeus::CVector3f::skZero, x198_moveAngularImpulse) || + !zeus::close_enough(zeus::CVector3f::skZero, GetTotalForcesWR()); } -void CPhysicsActor::SetPhysicsState(const CPhysicsState& state) -{ - SetTranslation(state.GetTranslation()); - SetTransform(zeus::CTransform(state.GetOrientation(), x34_transform.origin)); +void CPhysicsActor::SetPhysicsState(const CPhysicsState& state) { + SetTranslation(state.GetTranslation()); + SetTransform(zeus::CTransform(state.GetOrientation(), x34_transform.origin)); - xfc_constantForce = state.GetConstantForceWR(); - x108_angularMomentum = state.GetAngularMomentumWR(); - x150_momentum = state.GetMomentumWR(); - x15c_force = state.GetForceWR(); - x168_impulse = state.GetImpulseWR(); - x174_torque = state.GetTorque(); - x180_angularImpulse = state.GetAngularImpulseWR(); - ComputeDerivedQuantities(); + xfc_constantForce = state.GetConstantForceWR(); + x108_angularMomentum = state.GetAngularMomentumWR(); + x150_momentum = state.GetMomentumWR(); + x15c_force = state.GetForceWR(); + x168_impulse = state.GetImpulseWR(); + x174_torque = state.GetTorque(); + x180_angularImpulse = state.GetAngularImpulseWR(); + ComputeDerivedQuantities(); } -CPhysicsState CPhysicsActor::GetPhysicsState() const -{ - return {x34_transform.origin, {x34_transform.buildMatrix3f()}, - xfc_constantForce, x108_angularMomentum, - x150_momentum, x15c_force, - x168_impulse, x174_torque, - x180_angularImpulse}; +CPhysicsState CPhysicsActor::GetPhysicsState() const { + return {x34_transform.origin, {x34_transform.buildMatrix3f()}, + xfc_constantForce, x108_angularMomentum, + x150_momentum, x15c_force, + x168_impulse, x174_torque, + x180_angularImpulse}; } -CMotionState CPhysicsActor::PredictMotion_Internal(float dt) const -{ - if (xf8_25_angularEnabled) - return PredictLinearMotion(dt); +CMotionState CPhysicsActor::PredictMotion_Internal(float dt) const { + if (xf8_25_angularEnabled) + return PredictLinearMotion(dt); - CMotionState msl = PredictLinearMotion(dt); - CMotionState msa = PredictAngularMotion(dt); - return {msl.x0_translation, msa.xc_orientation, msl.x1c_velocity, msa.x28_angularMomentum}; + CMotionState msl = PredictLinearMotion(dt); + CMotionState msa = PredictAngularMotion(dt); + return {msl.x0_translation, msa.xc_orientation, msl.x1c_velocity, msa.x28_angularMomentum}; } -CMotionState CPhysicsActor::PredictMotion(float dt) const -{ - CMotionState msl = PredictLinearMotion(dt); - CMotionState msa = PredictAngularMotion(dt); - return {msl.x0_translation, msa.xc_orientation, msl.x1c_velocity, msa.x28_angularMomentum}; +CMotionState CPhysicsActor::PredictMotion(float dt) const { + CMotionState msl = PredictLinearMotion(dt); + CMotionState msa = PredictAngularMotion(dt); + return {msl.x0_translation, msa.xc_orientation, msl.x1c_velocity, msa.x28_angularMomentum}; } -CMotionState CPhysicsActor::PredictLinearMotion(float dt) const -{ - zeus::CVector3f velocity = CalculateNewVelocityWR_UsingImpulses(); - return {velocity * dt, {0.f, zeus::CVector3f::skZero}, ((x15c_force + x150_momentum) * dt) + x168_impulse, - zeus::CAxisAngle::skZero}; +CMotionState CPhysicsActor::PredictLinearMotion(float dt) const { + zeus::CVector3f velocity = CalculateNewVelocityWR_UsingImpulses(); + return {velocity * dt, + {0.f, zeus::CVector3f::skZero}, + ((x15c_force + x150_momentum) * dt) + x168_impulse, + zeus::CAxisAngle::skZero}; } -CMotionState CPhysicsActor::PredictAngularMotion(float dt) const -{ - const zeus::CVector3f v1 = xf4_inertiaTensorRecip * (x180_angularImpulse + x198_moveAngularImpulse); - zeus::CNUQuaternion q = 0.5f * zeus::CNUQuaternion(0.f, x144_angularVelocity.getVector() + v1); - CMotionState ret = {zeus::CVector3f::skZero, (q * zeus::CNUQuaternion(x34_transform.buildMatrix3f())) * dt, - zeus::CVector3f::skZero, (x174_torque * dt) + x180_angularImpulse}; - return ret; +CMotionState CPhysicsActor::PredictAngularMotion(float dt) const { + const zeus::CVector3f v1 = xf4_inertiaTensorRecip * (x180_angularImpulse + x198_moveAngularImpulse); + zeus::CNUQuaternion q = 0.5f * zeus::CNUQuaternion(0.f, x144_angularVelocity.getVector() + v1); + CMotionState ret = {zeus::CVector3f::skZero, (q * zeus::CNUQuaternion(x34_transform.buildMatrix3f())) * dt, + zeus::CVector3f::skZero, (x174_torque * dt) + x180_angularImpulse}; + return ret; } -void CPhysicsActor::ApplyForceOR(const zeus::CVector3f& force, const zeus::CAxisAngle& torque) -{ - x15c_force += x34_transform.rotate(force); - x174_torque += x34_transform.rotate(torque); +void CPhysicsActor::ApplyForceOR(const zeus::CVector3f& force, const zeus::CAxisAngle& torque) { + x15c_force += x34_transform.rotate(force); + x174_torque += x34_transform.rotate(torque); } -void CPhysicsActor::ApplyForceWR(const zeus::CVector3f& force, const zeus::CAxisAngle& torque) -{ - x15c_force += force; - x174_torque += torque; +void CPhysicsActor::ApplyForceWR(const zeus::CVector3f& force, const zeus::CAxisAngle& torque) { + x15c_force += force; + x174_torque += torque; } -void CPhysicsActor::ApplyImpulseOR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angle) -{ - x168_impulse += x34_transform.rotate(impulse); - x180_angularImpulse += x34_transform.rotate(angle); +void CPhysicsActor::ApplyImpulseOR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angle) { + x168_impulse += x34_transform.rotate(impulse); + x180_angularImpulse += x34_transform.rotate(angle); } -void CPhysicsActor::ApplyImpulseWR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angleImp) -{ - x168_impulse += impulse; - x180_angularImpulse += angleImp; +void CPhysicsActor::ApplyImpulseWR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angleImp) { + x168_impulse += impulse; + x180_angularImpulse += angleImp; } void CPhysicsActor::ApplyTorqueWR(const zeus::CVector3f& torque) { x174_torque += torque; } -void CPhysicsActor::UseCollisionImpulses() -{ - xfc_constantForce += x168_impulse; - x108_angularMomentum += x180_angularImpulse; +void CPhysicsActor::UseCollisionImpulses() { + xfc_constantForce += x168_impulse; + x108_angularMomentum += x180_angularImpulse; - x168_impulse = zeus::CVector3f::skZero; - x180_angularImpulse = zeus::CAxisAngle::skZero; - ComputeDerivedQuantities(); + x168_impulse = zeus::CVector3f::skZero; + x180_angularImpulse = zeus::CAxisAngle::skZero; + ComputeDerivedQuantities(); } -} +} // namespace urde diff --git a/Runtime/World/CPhysicsActor.hpp b/Runtime/World/CPhysicsActor.hpp index 48b3c16c1..85bf74a2d 100644 --- a/Runtime/World/CPhysicsActor.hpp +++ b/Runtime/World/CPhysicsActor.hpp @@ -3,210 +3,202 @@ #include "CActor.hpp" #include "Collision/CCollidableAABox.hpp" -namespace urde -{ +namespace urde { class CCollisionInfoList; struct SMoverData; -struct SMoverData -{ - zeus::CVector3f x0_velocity; - zeus::CAxisAngle xc_angularVelocity; - zeus::CVector3f x18_momentum; - zeus::CAxisAngle x24_; - float x30_mass; +struct SMoverData { + zeus::CVector3f x0_velocity; + zeus::CAxisAngle xc_angularVelocity; + zeus::CVector3f x18_momentum; + zeus::CAxisAngle x24_; + float x30_mass; - SMoverData(float mass) : x30_mass(mass) {} + SMoverData(float mass) : x30_mass(mass) {} }; -struct CMotionState -{ - zeus::CVector3f x0_translation; - zeus::CNUQuaternion xc_orientation; - zeus::CVector3f x1c_velocity; - zeus::CAxisAngle x28_angularMomentum; - CMotionState(const zeus::CVector3f& origin, const zeus::CNUQuaternion& orientation, const zeus::CVector3f& velocity, - const zeus::CAxisAngle& angle) - : x0_translation(origin), xc_orientation(orientation), x1c_velocity(velocity), x28_angularMomentum(angle) - {} - CMotionState(const zeus::CVector3f& origin, const zeus::CNUQuaternion& orientation) - : x0_translation(origin), xc_orientation(orientation) - {} +struct CMotionState { + zeus::CVector3f x0_translation; + zeus::CNUQuaternion xc_orientation; + zeus::CVector3f x1c_velocity; + zeus::CAxisAngle x28_angularMomentum; + CMotionState(const zeus::CVector3f& origin, const zeus::CNUQuaternion& orientation, const zeus::CVector3f& velocity, + const zeus::CAxisAngle& angle) + : x0_translation(origin), xc_orientation(orientation), x1c_velocity(velocity), x28_angularMomentum(angle) {} + CMotionState(const zeus::CVector3f& origin, const zeus::CNUQuaternion& orientation) + : x0_translation(origin), xc_orientation(orientation) {} }; -class CPhysicsState -{ - zeus::CVector3f x0_translation; - zeus::CQuaternion xc_orientation; - zeus::CVector3f x1c_constantForce; - zeus::CAxisAngle x28_angularMomentum; - zeus::CVector3f x34_momentum; - zeus::CVector3f x40_force; - zeus::CVector3f x4c_impulse; - zeus::CAxisAngle x58_torque; - zeus::CAxisAngle x64_angularImpulse; +class CPhysicsState { + zeus::CVector3f x0_translation; + zeus::CQuaternion xc_orientation; + zeus::CVector3f x1c_constantForce; + zeus::CAxisAngle x28_angularMomentum; + zeus::CVector3f x34_momentum; + zeus::CVector3f x40_force; + zeus::CVector3f x4c_impulse; + zeus::CAxisAngle x58_torque; + zeus::CAxisAngle x64_angularImpulse; public: - CPhysicsState(const zeus::CVector3f& translation, const zeus::CQuaternion& orient, - const zeus::CVector3f& v2, const zeus::CAxisAngle& a1, const zeus::CVector3f& v3, - const zeus::CVector3f& v4, const zeus::CVector3f& v5, const zeus::CAxisAngle& a2, - const zeus::CAxisAngle& a3) - : x0_translation(translation) - , xc_orientation(orient) - , x1c_constantForce(v2) - , x28_angularMomentum(a1) - , x34_momentum(v3) - , x40_force(v4) - , x4c_impulse(v5) - , x58_torque(a2) - , x64_angularImpulse(a3) - {} + CPhysicsState(const zeus::CVector3f& translation, const zeus::CQuaternion& orient, const zeus::CVector3f& v2, + const zeus::CAxisAngle& a1, const zeus::CVector3f& v3, const zeus::CVector3f& v4, + const zeus::CVector3f& v5, const zeus::CAxisAngle& a2, const zeus::CAxisAngle& a3) + : x0_translation(translation) + , xc_orientation(orient) + , x1c_constantForce(v2) + , x28_angularMomentum(a1) + , x34_momentum(v3) + , x40_force(v4) + , x4c_impulse(v5) + , x58_torque(a2) + , x64_angularImpulse(a3) {} - void SetTranslation(const zeus::CVector3f& tr) { x0_translation = tr; } - void SetOrientation(const zeus::CQuaternion& orient) { xc_orientation = orient; } - const zeus::CQuaternion& GetOrientation() const { return xc_orientation; } - const zeus::CVector3f& GetTranslation() const { return x0_translation; } - const zeus::CVector3f& GetConstantForceWR() const { return x1c_constantForce; } - const zeus::CAxisAngle& GetAngularMomentumWR() const { return x28_angularMomentum; } - const zeus::CVector3f& GetMomentumWR() const { return x34_momentum; } - const zeus::CVector3f& GetForceWR() const { return x40_force; } - const zeus::CVector3f& GetImpulseWR() const { return x4c_impulse; } - const zeus::CAxisAngle& GetTorque() const { return x58_torque; } - const zeus::CAxisAngle& GetAngularImpulseWR() const { return x64_angularImpulse; } + void SetTranslation(const zeus::CVector3f& tr) { x0_translation = tr; } + void SetOrientation(const zeus::CQuaternion& orient) { xc_orientation = orient; } + const zeus::CQuaternion& GetOrientation() const { return xc_orientation; } + const zeus::CVector3f& GetTranslation() const { return x0_translation; } + const zeus::CVector3f& GetConstantForceWR() const { return x1c_constantForce; } + const zeus::CAxisAngle& GetAngularMomentumWR() const { return x28_angularMomentum; } + const zeus::CVector3f& GetMomentumWR() const { return x34_momentum; } + const zeus::CVector3f& GetForceWR() const { return x40_force; } + const zeus::CVector3f& GetImpulseWR() const { return x4c_impulse; } + const zeus::CAxisAngle& GetTorque() const { return x58_torque; } + const zeus::CAxisAngle& GetAngularImpulseWR() const { return x64_angularImpulse; } }; -class CPhysicsActor : public CActor -{ - friend class CGroundMovement; +class CPhysicsActor : public CActor { + friend class CGroundMovement; + protected: - float xe8_mass; - float xec_massRecip; - float xf0_inertiaTensor; - float xf4_inertiaTensorRecip; - union { - struct - { - bool xf8_24_movable : 1; - bool xf8_25_angularEnabled : 1; - }; - u8 _dummy = 0; + float xe8_mass; + float xec_massRecip; + float xf0_inertiaTensor; + float xf4_inertiaTensorRecip; + union { + struct { + bool xf8_24_movable : 1; + bool xf8_25_angularEnabled : 1; }; - bool xf9_standardCollider = false; - zeus::CVector3f xfc_constantForce; - zeus::CAxisAngle x108_angularMomentum; - zeus::CMatrix3f x114_; - zeus::CVector3f x138_velocity; - zeus::CAxisAngle x144_angularVelocity; - zeus::CVector3f x150_momentum; - zeus::CVector3f x15c_force; - zeus::CVector3f x168_impulse; - zeus::CAxisAngle x174_torque; - zeus::CAxisAngle x180_angularImpulse; - zeus::CVector3f x18c_moveImpulse; - zeus::CAxisAngle x198_moveAngularImpulse; - zeus::CAABox x1a4_baseBoundingBox; - CCollidableAABox x1c0_collisionPrimitive; - zeus::CVector3f x1e8_primitiveOffset; - CMotionState x1f4_lastNonCollidingState; - std::experimental::optional x228_lastFloorPlaneNormal; - float x238_maximumCollisionVelocity = 1000000.0f; - float x23c_stepUpHeight; - float x240_stepDownHeight; - float x244_restitutionCoefModifier = 0.f; - float x248_collisionAccuracyModifier = 1.f; - u32 x24c_numTicksStuck; - u32 x250_numTicksPartialUpdate; + u8 _dummy = 0; + }; + bool xf9_standardCollider = false; + zeus::CVector3f xfc_constantForce; + zeus::CAxisAngle x108_angularMomentum; + zeus::CMatrix3f x114_; + zeus::CVector3f x138_velocity; + zeus::CAxisAngle x144_angularVelocity; + zeus::CVector3f x150_momentum; + zeus::CVector3f x15c_force; + zeus::CVector3f x168_impulse; + zeus::CAxisAngle x174_torque; + zeus::CAxisAngle x180_angularImpulse; + zeus::CVector3f x18c_moveImpulse; + zeus::CAxisAngle x198_moveAngularImpulse; + zeus::CAABox x1a4_baseBoundingBox; + CCollidableAABox x1c0_collisionPrimitive; + zeus::CVector3f x1e8_primitiveOffset; + CMotionState x1f4_lastNonCollidingState; + std::experimental::optional x228_lastFloorPlaneNormal; + float x238_maximumCollisionVelocity = 1000000.0f; + float x23c_stepUpHeight; + float x240_stepDownHeight; + float x244_restitutionCoefModifier = 0.f; + float x248_collisionAccuracyModifier = 1.f; + u32 x24c_numTicksStuck; + u32 x250_numTicksPartialUpdate; public: - CPhysicsActor(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CMaterialList&, const zeus::CAABox&, const SMoverData&, const CActorParameters&, float, float); + CPhysicsActor(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CMaterialList&, const zeus::CAABox&, const SMoverData&, const CActorParameters&, float, float); - void Render(const CStateManager& mgr) const; - zeus::CVector3f GetOrbitPosition(const CStateManager&) const; - zeus::CVector3f GetAimPosition(const CStateManager&, float val) const; - virtual const CCollisionPrimitive* GetCollisionPrimitive() const; - virtual zeus::CTransform GetPrimitiveTransform() const; - virtual void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager&); - virtual float GetStepUpHeight() const; - virtual float GetStepDownHeight() const; - virtual float GetWeight() const; + void Render(const CStateManager& mgr) const; + zeus::CVector3f GetOrbitPosition(const CStateManager&) const; + zeus::CVector3f GetAimPosition(const CStateManager&, float val) const; + virtual const CCollisionPrimitive* GetCollisionPrimitive() const; + virtual zeus::CTransform GetPrimitiveTransform() const; + virtual void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager&); + virtual float GetStepUpHeight() const; + virtual float GetStepDownHeight() const; + virtual float GetWeight() const; - float GetMass() const { return xe8_mass; } - void SetPrimitiveOffset(const zeus::CVector2f& offset); - zeus::CVector3f GetPrimitiveOffset() const; - void MoveCollisionPrimitive(const zeus::CVector3f& offset); - void SetBoundingBox(const zeus::CAABox& box); - zeus::CAABox GetMotionVolume(float dt) const; - zeus::CVector3f CalculateNewVelocityWR_UsingImpulses() const; - zeus::CAABox GetBoundingBox() const; - const zeus::CAABox& GetBaseBoundingBox() const; - void AddMotionState(const CMotionState& mst); - CMotionState GetMotionState() const; - const CMotionState& GetLastNonCollidingState() const { return x1f4_lastNonCollidingState; } - void SetLastNonCollidingState(const CMotionState& mst) { x1f4_lastNonCollidingState = mst; } - void SetMotionState(const CMotionState& mst); - float GetMaximumCollisionVelocity() const { return x238_maximumCollisionVelocity; } - void SetMaximumCollisionVelocity(float v) { x238_maximumCollisionVelocity = v; } - void SetInertiaTensorScalar(float tensor); - void SetMass(float mass); - void SetAngularVelocityOR(const zeus::CAxisAngle& angVel); - zeus::CAxisAngle GetAngularVelocityOR() const; - const zeus::CAxisAngle& GetAngularVelocityWR() const { return x144_angularVelocity; } - void SetAngularVelocityWR(const zeus::CAxisAngle& angVel); - const zeus::CVector3f& GetForceOR() const { return x15c_force; } - void SetVelocityWR(const zeus::CVector3f& vel); - void SetVelocityOR(const zeus::CVector3f& vel); - void SetMomentumWR(const zeus::CVector3f& m) { x150_momentum = m; } - const zeus::CVector3f& GetConstantForce() { return xfc_constantForce; } - void SetConstantForce(const zeus::CVector3f& f) { xfc_constantForce = f; } - void SetAngularMomentum(const zeus::CAxisAngle& m) { x108_angularMomentum = m; } - const zeus::CVector3f& GetMomentum() const { return x150_momentum; } - const zeus::CVector3f& GetVelocity() const { return x138_velocity; } - const zeus::CAxisAngle& GetAngularImpulse() const { return x180_angularImpulse; } - void SetAngularImpulse(const zeus::CAxisAngle& i) { x180_angularImpulse = i; } - zeus::CVector3f GetTotalForcesWR() const; - void RotateInOneFrameOR(const zeus::CQuaternion& q, float d); - void MoveInOneFrameOR(const zeus::CVector3f& trans, float d); - void RotateToOR(const zeus::CQuaternion& q, float d); - void MoveToOR(const zeus::CVector3f& trans, float d); - void MoveToInOneFrameWR(const zeus::CVector3f& v1, float d); - void MoveToWR(const zeus::CVector3f& trans, float d); - zeus::CAxisAngle GetRotateToORAngularMomentumWR(const zeus::CQuaternion& q, float d) const; - zeus::CVector3f GetMoveToORImpulseWR(const zeus::CVector3f& trans, float d) const; - void ClearImpulses(); - void ClearForcesAndTorques(); - void Stop(); - void ComputeDerivedQuantities(); - bool WillMove(const CStateManager&); - void SetPhysicsState(const CPhysicsState& state); - CPhysicsState GetPhysicsState() const; - bool IsMovable() const { return xf8_24_movable; } - void SetMovable(bool m) { xf8_24_movable = m; } - bool IsAngularEnabled() const { return xf8_25_angularEnabled; } - void SetAngularEnabled(bool e) { xf8_25_angularEnabled = e; } - float GetCollisionAccuracyModifier() const { return x248_collisionAccuracyModifier; } - void SetCollisionAccuracyModifier(float m) { x248_collisionAccuracyModifier = m; } - float GetCoefficientOfRestitutionModifier() const { return x244_restitutionCoefModifier; } - void SetCoefficientOfRestitutionModifier(float m) { x244_restitutionCoefModifier = m; } - bool IsUseStandardCollider() const { return xf9_standardCollider; } - u32 GetNumTicksPartialUpdate() const { return x250_numTicksPartialUpdate; } - void SetNumTicksPartialUpdate(u32 t) { x250_numTicksPartialUpdate = t; } - u32 GetNumTicksStuck() const { return x24c_numTicksStuck; } - void SetNumTicksStuck(u32 t) { x24c_numTicksStuck = t; } - const std::experimental::optional& GetLastFloorPlaneNormal() const { return x228_lastFloorPlaneNormal; } - void SetLastFloorPlaneNormal(const std::experimental::optional& n) { x228_lastFloorPlaneNormal = n; } + float GetMass() const { return xe8_mass; } + void SetPrimitiveOffset(const zeus::CVector2f& offset); + zeus::CVector3f GetPrimitiveOffset() const; + void MoveCollisionPrimitive(const zeus::CVector3f& offset); + void SetBoundingBox(const zeus::CAABox& box); + zeus::CAABox GetMotionVolume(float dt) const; + zeus::CVector3f CalculateNewVelocityWR_UsingImpulses() const; + zeus::CAABox GetBoundingBox() const; + const zeus::CAABox& GetBaseBoundingBox() const; + void AddMotionState(const CMotionState& mst); + CMotionState GetMotionState() const; + const CMotionState& GetLastNonCollidingState() const { return x1f4_lastNonCollidingState; } + void SetLastNonCollidingState(const CMotionState& mst) { x1f4_lastNonCollidingState = mst; } + void SetMotionState(const CMotionState& mst); + float GetMaximumCollisionVelocity() const { return x238_maximumCollisionVelocity; } + void SetMaximumCollisionVelocity(float v) { x238_maximumCollisionVelocity = v; } + void SetInertiaTensorScalar(float tensor); + void SetMass(float mass); + void SetAngularVelocityOR(const zeus::CAxisAngle& angVel); + zeus::CAxisAngle GetAngularVelocityOR() const; + const zeus::CAxisAngle& GetAngularVelocityWR() const { return x144_angularVelocity; } + void SetAngularVelocityWR(const zeus::CAxisAngle& angVel); + const zeus::CVector3f& GetForceOR() const { return x15c_force; } + void SetVelocityWR(const zeus::CVector3f& vel); + void SetVelocityOR(const zeus::CVector3f& vel); + void SetMomentumWR(const zeus::CVector3f& m) { x150_momentum = m; } + const zeus::CVector3f& GetConstantForce() { return xfc_constantForce; } + void SetConstantForce(const zeus::CVector3f& f) { xfc_constantForce = f; } + void SetAngularMomentum(const zeus::CAxisAngle& m) { x108_angularMomentum = m; } + const zeus::CVector3f& GetMomentum() const { return x150_momentum; } + const zeus::CVector3f& GetVelocity() const { return x138_velocity; } + const zeus::CAxisAngle& GetAngularImpulse() const { return x180_angularImpulse; } + void SetAngularImpulse(const zeus::CAxisAngle& i) { x180_angularImpulse = i; } + zeus::CVector3f GetTotalForcesWR() const; + void RotateInOneFrameOR(const zeus::CQuaternion& q, float d); + void MoveInOneFrameOR(const zeus::CVector3f& trans, float d); + void RotateToOR(const zeus::CQuaternion& q, float d); + void MoveToOR(const zeus::CVector3f& trans, float d); + void MoveToInOneFrameWR(const zeus::CVector3f& v1, float d); + void MoveToWR(const zeus::CVector3f& trans, float d); + zeus::CAxisAngle GetRotateToORAngularMomentumWR(const zeus::CQuaternion& q, float d) const; + zeus::CVector3f GetMoveToORImpulseWR(const zeus::CVector3f& trans, float d) const; + void ClearImpulses(); + void ClearForcesAndTorques(); + void Stop(); + void ComputeDerivedQuantities(); + bool WillMove(const CStateManager&); + void SetPhysicsState(const CPhysicsState& state); + CPhysicsState GetPhysicsState() const; + bool IsMovable() const { return xf8_24_movable; } + void SetMovable(bool m) { xf8_24_movable = m; } + bool IsAngularEnabled() const { return xf8_25_angularEnabled; } + void SetAngularEnabled(bool e) { xf8_25_angularEnabled = e; } + float GetCollisionAccuracyModifier() const { return x248_collisionAccuracyModifier; } + void SetCollisionAccuracyModifier(float m) { x248_collisionAccuracyModifier = m; } + float GetCoefficientOfRestitutionModifier() const { return x244_restitutionCoefModifier; } + void SetCoefficientOfRestitutionModifier(float m) { x244_restitutionCoefModifier = m; } + bool IsUseStandardCollider() const { return xf9_standardCollider; } + u32 GetNumTicksPartialUpdate() const { return x250_numTicksPartialUpdate; } + void SetNumTicksPartialUpdate(u32 t) { x250_numTicksPartialUpdate = t; } + u32 GetNumTicksStuck() const { return x24c_numTicksStuck; } + void SetNumTicksStuck(u32 t) { x24c_numTicksStuck = t; } + const std::experimental::optional& GetLastFloorPlaneNormal() const { + return x228_lastFloorPlaneNormal; + } + void SetLastFloorPlaneNormal(const std::experimental::optional& n) { x228_lastFloorPlaneNormal = n; } - CMotionState PredictMotion_Internal(float) const; - CMotionState PredictMotion(float dt) const; - CMotionState PredictLinearMotion(float dt) const; - CMotionState PredictAngularMotion(float dt) const; - void ApplyForceOR(const zeus::CVector3f& force, const zeus::CAxisAngle& angle); - void ApplyForceWR(const zeus::CVector3f& force, const zeus::CAxisAngle& angle); - void ApplyImpulseOR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angle); - void ApplyImpulseWR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angle); - void ApplyTorqueWR(const zeus::CVector3f& torque); + CMotionState PredictMotion_Internal(float) const; + CMotionState PredictMotion(float dt) const; + CMotionState PredictLinearMotion(float dt) const; + CMotionState PredictAngularMotion(float dt) const; + void ApplyForceOR(const zeus::CVector3f& force, const zeus::CAxisAngle& angle); + void ApplyForceWR(const zeus::CVector3f& force, const zeus::CAxisAngle& angle); + void ApplyImpulseOR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angle); + void ApplyImpulseWR(const zeus::CVector3f& impulse, const zeus::CAxisAngle& angle); + void ApplyTorqueWR(const zeus::CVector3f& torque); - void UseCollisionImpulses(); + void UseCollisionImpulses(); }; -} - +} // namespace urde diff --git a/Runtime/World/CPlayer.cpp b/Runtime/World/CPlayer.cpp index 429c9c9d5..1dac982cc 100644 --- a/Runtime/World/CPlayer.cpp +++ b/Runtime/World/CPlayer.cpp @@ -25,55 +25,44 @@ #include "CScriptPlayerHint.hpp" #include "CScriptAreaAttributes.hpp" -namespace urde -{ +namespace urde { -static const CMaterialFilter SolidMaterialFilter = - CMaterialFilter::MakeInclude(CMaterialList(EMaterialTypes::Solid)); +static const CMaterialFilter SolidMaterialFilter = CMaterialFilter::MakeInclude(CMaterialList(EMaterialTypes::Solid)); -static const CMaterialFilter LineOfSightFilter = - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::ProjectilePassthrough, - EMaterialTypes::ScanPassthrough, - EMaterialTypes::Player}); +static const CMaterialFilter LineOfSightFilter = CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, + {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::ScanPassthrough, EMaterialTypes::Player}); -static const CMaterialFilter OccluderFilter = - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Occluder}, - {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::ScanPassthrough, EMaterialTypes::Player}); +static const CMaterialFilter OccluderFilter = CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid, EMaterialTypes::Occluder}, + {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::ScanPassthrough, EMaterialTypes::Player}); -static CModelData MakePlayerAnimRes(CAssetId resId, const zeus::CVector3f& scale) -{ - return {CAnimRes(resId, 0, scale, 0, true), 1}; +static CModelData MakePlayerAnimRes(CAssetId resId, const zeus::CVector3f& scale) { + return {CAnimRes(resId, 0, scale, 0, true), 1}; } -static uint32_t GetOrbitScreenBoxHalfExtentXScaled(int zone) -{ - return g_tweakPlayer->GetOrbitScreenBoxHalfExtentX(zone) * g_Viewport.x8_width / 640; +static uint32_t GetOrbitScreenBoxHalfExtentXScaled(int zone) { + return g_tweakPlayer->GetOrbitScreenBoxHalfExtentX(zone) * g_Viewport.x8_width / 640; } -static uint32_t GetOrbitScreenBoxHalfExtentYScaled(int zone) -{ - return g_tweakPlayer->GetOrbitScreenBoxHalfExtentY(zone) * g_Viewport.xc_height / 448; +static uint32_t GetOrbitScreenBoxHalfExtentYScaled(int zone) { + return g_tweakPlayer->GetOrbitScreenBoxHalfExtentY(zone) * g_Viewport.xc_height / 448; } -static uint32_t GetOrbitScreenBoxCenterXScaled(int zone) -{ - return g_tweakPlayer->GetOrbitScreenBoxCenterX(zone) * g_Viewport.x8_width / 640; +static uint32_t GetOrbitScreenBoxCenterXScaled(int zone) { + return g_tweakPlayer->GetOrbitScreenBoxCenterX(zone) * g_Viewport.x8_width / 640; } -static uint32_t GetOrbitScreenBoxCenterYScaled(int zone) -{ - return g_tweakPlayer->GetOrbitScreenBoxCenterY(zone) * g_Viewport.xc_height / 448; +static uint32_t GetOrbitScreenBoxCenterYScaled(int zone) { + return g_tweakPlayer->GetOrbitScreenBoxCenterY(zone) * g_Viewport.xc_height / 448; } -static uint32_t GetOrbitZoneIdealXScaled(int zone) -{ - return g_tweakPlayer->GetOrbitZoneIdealX(zone) * g_Viewport.x8_width / 640; +static uint32_t GetOrbitZoneIdealXScaled(int zone) { + return g_tweakPlayer->GetOrbitZoneIdealX(zone) * g_Viewport.x8_width / 640; } -static uint32_t GetOrbitZoneIdealYScaled(int zone) -{ - return g_tweakPlayer->GetOrbitZoneIdealY(zone) * g_Viewport.xc_height / 448; +static uint32_t GetOrbitZoneIdealYScaled(int zone) { + return g_tweakPlayer->GetOrbitZoneIdealY(zone) * g_Viewport.xc_height / 448; } CPlayer::CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox& aabb, CAssetId resId, @@ -81,2626 +70,2197 @@ CPlayer::CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox& const CMaterialList& ml) : CPhysicsActor(uid, true, "CPlayer", CEntityInfo(kInvalidAreaId, CEntity::NullConnectionList), xf, MakePlayerAnimRes(resId, playerScale), ml, aabb, SMoverData(mass), CActorParameters::None(), stepUp, - stepDown), x2d8_fpBounds(aabb), x7d0_animRes(resId, 0, playerScale, 0, true), - x7d8_beamScale(playerScale) -{ - x490_gun.reset(new CPlayerGun(uid)); - x49c_gunHolsterRemTime = g_tweakPlayerGun->GetGunNotFiringTime(); - x4a0_failsafeTest.reset(new CFailsafeTest()); - x76c_cameraBob.reset(new CPlayerCameraBob(CPlayerCameraBob::ECameraBobType::One, - zeus::CVector2f{CPlayerCameraBob::kCameraBobExtentX, - CPlayerCameraBob::kCameraBobExtentY}, - CPlayerCameraBob::kCameraBobPeriod)); - x9c4_26_ = true; - x9c4_27_canEnterMorphBall = true; - x9c4_28_canLeaveMorphBall = true; - x9c5_31_stepCameraZBiasDirty = true; - CAssetId beamId = g_tweakPlayerRes->GetBeamBallTransitionModel(x7ec_beam); - x7f0_ballTransitionBeamModel = std::make_unique(CStaticRes(beamId, playerScale)); - x730_transitionModels.reserve(3); - x768_morphball.reset(new CMorphBall(*this, ballRadius)); + stepDown) +, x2d8_fpBounds(aabb) +, x7d0_animRes(resId, 0, playerScale, 0, true) +, x7d8_beamScale(playerScale) { + x490_gun.reset(new CPlayerGun(uid)); + x49c_gunHolsterRemTime = g_tweakPlayerGun->GetGunNotFiringTime(); + x4a0_failsafeTest.reset(new CFailsafeTest()); + x76c_cameraBob.reset( + new CPlayerCameraBob(CPlayerCameraBob::ECameraBobType::One, + zeus::CVector2f{CPlayerCameraBob::kCameraBobExtentX, CPlayerCameraBob::kCameraBobExtentY}, + CPlayerCameraBob::kCameraBobPeriod)); + x9c4_26_ = true; + x9c4_27_canEnterMorphBall = true; + x9c4_28_canLeaveMorphBall = true; + x9c5_31_stepCameraZBiasDirty = true; + CAssetId beamId = g_tweakPlayerRes->GetBeamBallTransitionModel(x7ec_beam); + x7f0_ballTransitionBeamModel = std::make_unique(CStaticRes(beamId, playerScale)); + x730_transitionModels.reserve(3); + x768_morphball.reset(new CMorphBall(*this, ballRadius)); - SetInertiaTensorScalar(xe8_mass); - x1f4_lastNonCollidingState = GetMotionState(); - x490_gun->SetTransform(x34_transform); - x490_gun->GetGrappleArm().SetTransform(x34_transform); + SetInertiaTensorScalar(xe8_mass); + x1f4_lastNonCollidingState = GetMotionState(); + x490_gun->SetTransform(x34_transform); + x490_gun->GetGrappleArm().SetTransform(x34_transform); - InitializeBallTransition(); - zeus::CAABox ballTransAABB = x64_modelData->GetBounds(); - x2f0_ballTransHeight = ballTransAABB.max.z() - ballTransAABB.min.z(); + InitializeBallTransition(); + zeus::CAABox ballTransAABB = x64_modelData->GetBounds(); + x2f0_ballTransHeight = ballTransAABB.max.z() - ballTransAABB.min.z(); - SetCalculateLighting(true); + SetCalculateLighting(true); - x90_actorLights->SetCastShadows(true); - x50c_moveDir.z() = 0.f; - if (x50c_moveDir.canBeNormalized()) - x50c_moveDir.normalize(); - x2b4_accelerationTable.push_back(20.f); - x2b4_accelerationTable.push_back(80.f); - x2b4_accelerationTable.push_back(80.f); - x2b4_accelerationTable.push_back(270.f); - SetMaximumCollisionVelocity(25.f); - x354_onScreenOrbitObjects.reserve(64); - x344_nearbyOrbitObjects.reserve(64); - x364_offScreenOrbitObjects.reserve(64); - x64_modelData->SetScale(playerScale); - x7f0_ballTransitionBeamModel->SetScale(playerScale); - LoadAnimationTokens(); + x90_actorLights->SetCastShadows(true); + x50c_moveDir.z() = 0.f; + if (x50c_moveDir.canBeNormalized()) + x50c_moveDir.normalize(); + x2b4_accelerationTable.push_back(20.f); + x2b4_accelerationTable.push_back(80.f); + x2b4_accelerationTable.push_back(80.f); + x2b4_accelerationTable.push_back(270.f); + SetMaximumCollisionVelocity(25.f); + x354_onScreenOrbitObjects.reserve(64); + x344_nearbyOrbitObjects.reserve(64); + x364_offScreenOrbitObjects.reserve(64); + x64_modelData->SetScale(playerScale); + x7f0_ballTransitionBeamModel->SetScale(playerScale); + LoadAnimationTokens(); } -void CPlayer::InitializeBallTransition() -{ - if (x64_modelData && x64_modelData->HasAnimData()) - x64_modelData->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false); +void CPlayer::InitializeBallTransition() { + if (x64_modelData && x64_modelData->HasAnimData()) + x64_modelData->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false); } bool CPlayer::IsTransparent() const { return x588_alpha < 1.f; } -float CPlayer::GetTransitionAlpha(const zeus::CVector3f& camPos, float zNear) const -{ - float zLimit = (x2d8_fpBounds.max.x() - x2d8_fpBounds.min.x()) * 0.5f + zNear; - float zStart = 1.f + zLimit; - float dist = (camPos - GetEyePosition()).magnitude(); - if (dist >= zLimit && dist <= zStart) - return (dist - zLimit) / (zStart - zLimit); - else if (dist > zStart) - return 1.f; - else - return 0.f; +float CPlayer::GetTransitionAlpha(const zeus::CVector3f& camPos, float zNear) const { + float zLimit = (x2d8_fpBounds.max.x() - x2d8_fpBounds.min.x()) * 0.5f + zNear; + float zStart = 1.f + zLimit; + float dist = (camPos - GetEyePosition()).magnitude(); + if (dist >= zLimit && dist <= zStart) + return (dist - zLimit) / (zStart - zLimit); + else if (dist > zStart) + return 1.f; + else + return 0.f; } -static const CMaterialFilter BallTransitionCollide = - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::ProjectilePassthrough, - EMaterialTypes::Player, - EMaterialTypes::Character, - EMaterialTypes::CameraPassthrough}); +static const CMaterialFilter BallTransitionCollide = CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Player, EMaterialTypes::Character, + EMaterialTypes::CameraPassthrough}); -s32 CPlayer::ChooseTransitionToAnimation(float dt, CStateManager& mgr) const -{ - if (x258_movementState == EPlayerMovementState::ApplyJump) - return 3; // B_airposetoball_samus - zeus::CVector3f localVel = x34_transform.transposeRotate(x138_velocity); - zeus::CVector3f localVelFlat = localVel; - localVelFlat.z() = 0.f; - float localVelFlatMag = localVelFlat.magnitude(); - if (localVelFlatMag > 1.f) - { - zeus::CRelAngle velAng = std::atan2(localVelFlat.x(), localVelFlat.y()); - float velDeg = velAng.asDegrees(); - if (velDeg < 45.f || velDeg > 315.f) - { - if (localVelFlatMag < 0.5f * GetActualFirstPersonMaxVelocity(dt)) - return 0; // B_forwardtoballforward_samus - else - return 4; // B_runtoballfoward_samus - } - else - { - return 1; // B_readytostationarybackwards_samus - } - } - else - { - return 2; // B_readytoball_samus +s32 CPlayer::ChooseTransitionToAnimation(float dt, CStateManager& mgr) const { + if (x258_movementState == EPlayerMovementState::ApplyJump) + return 3; // B_airposetoball_samus + zeus::CVector3f localVel = x34_transform.transposeRotate(x138_velocity); + zeus::CVector3f localVelFlat = localVel; + localVelFlat.z() = 0.f; + float localVelFlatMag = localVelFlat.magnitude(); + if (localVelFlatMag > 1.f) { + zeus::CRelAngle velAng = std::atan2(localVelFlat.x(), localVelFlat.y()); + float velDeg = velAng.asDegrees(); + if (velDeg < 45.f || velDeg > 315.f) { + if (localVelFlatMag < 0.5f * GetActualFirstPersonMaxVelocity(dt)) + return 0; // B_forwardtoballforward_samus + else + return 4; // B_runtoballfoward_samus + } else { + return 1; // B_readytostationarybackwards_samus } + } else { + return 2; // B_readytoball_samus + } } -void CPlayer::TransitionToMorphBallState(float dt, CStateManager& mgr) -{ - x584_ballTransitionAnim = ChooseTransitionToAnimation(dt, mgr); - x58c_transitionVel = x138_velocity.magnitude(); - if (x64_modelData && x64_modelData->HasAnimData()) - { - CAnimPlaybackParms parms(x584_ballTransitionAnim, -1, 1.f, true); - x64_modelData->AnimationData()->SetAnimation(parms, false); - x64_modelData->AnimationData()->SetAnimDir(CAnimData::EAnimDir::Forward); - - } - x64_modelData->EnableLooping(false); - x64_modelData->Touch(mgr, 0); - x150_momentum = zeus::CVector3f::skZero; - CPhysicsActor::Stop(); - SetMorphBallState(EPlayerMorphBallState::Morphing, mgr); - SetCameraState(EPlayerCameraState::Transitioning, mgr); - x500_lookDir = x34_transform.basis[1]; - x50c_moveDir = x500_lookDir; - x50c_moveDir.z() = 0.f; - if (x50c_moveDir.canBeNormalized()) - { - x50c_moveDir.normalize(); - } - else - { - x500_lookDir = zeus::CVector3f::skForward; - x50c_moveDir = zeus::CVector3f::skForward; - } - CBallCamera* ballCam = mgr.GetCameraManager()->GetBallCamera(); - mgr.GetCameraManager()->SetPlayerCamera(mgr, ballCam->GetUniqueId()); - if (!mgr.GetCameraManager()->HasBallCameraInitialPositionHint(mgr)) - { - mgr.GetCameraManager()->SetupBallCamera(mgr); - ballCam->SetState(CBallCamera::EBallCameraState::ToBall, mgr); - } - else - { - ballCam->SetState(CBallCamera::EBallCameraState::Default, mgr); - SetCameraState(EPlayerCameraState::Ball, mgr); - zeus::CTransform newXf = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform(); - ballCam->SetTransform(newXf); - ballCam->TeleportCamera(newXf.origin, mgr); - mgr.GetCameraManager()->SetupBallCamera(mgr); - ballCam->SetFovInterpolation(mgr.GetCameraManager()->GetFirstPersonCamera()->GetFov(), - CCameraManager::ThirdPersonFOV(), 1.f, 0.f); - } - SetOrbitRequest(EPlayerOrbitRequest::EnterMorphBall, mgr); - x490_gun->CancelFiring(mgr); - HolsterGun(mgr); +void CPlayer::TransitionToMorphBallState(float dt, CStateManager& mgr) { + x584_ballTransitionAnim = ChooseTransitionToAnimation(dt, mgr); + x58c_transitionVel = x138_velocity.magnitude(); + if (x64_modelData && x64_modelData->HasAnimData()) { + CAnimPlaybackParms parms(x584_ballTransitionAnim, -1, 1.f, true); + x64_modelData->AnimationData()->SetAnimation(parms, false); + x64_modelData->AnimationData()->SetAnimDir(CAnimData::EAnimDir::Forward); + } + x64_modelData->EnableLooping(false); + x64_modelData->Touch(mgr, 0); + x150_momentum = zeus::CVector3f::skZero; + CPhysicsActor::Stop(); + SetMorphBallState(EPlayerMorphBallState::Morphing, mgr); + SetCameraState(EPlayerCameraState::Transitioning, mgr); + x500_lookDir = x34_transform.basis[1]; + x50c_moveDir = x500_lookDir; + x50c_moveDir.z() = 0.f; + if (x50c_moveDir.canBeNormalized()) { + x50c_moveDir.normalize(); + } else { + x500_lookDir = zeus::CVector3f::skForward; + x50c_moveDir = zeus::CVector3f::skForward; + } + CBallCamera* ballCam = mgr.GetCameraManager()->GetBallCamera(); + mgr.GetCameraManager()->SetPlayerCamera(mgr, ballCam->GetUniqueId()); + if (!mgr.GetCameraManager()->HasBallCameraInitialPositionHint(mgr)) { + mgr.GetCameraManager()->SetupBallCamera(mgr); + ballCam->SetState(CBallCamera::EBallCameraState::ToBall, mgr); + } else { + ballCam->SetState(CBallCamera::EBallCameraState::Default, mgr); + SetCameraState(EPlayerCameraState::Ball, mgr); + zeus::CTransform newXf = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform(); + ballCam->SetTransform(newXf); + ballCam->TeleportCamera(newXf.origin, mgr); + mgr.GetCameraManager()->SetupBallCamera(mgr); + ballCam->SetFovInterpolation(mgr.GetCameraManager()->GetFirstPersonCamera()->GetFov(), + CCameraManager::ThirdPersonFOV(), 1.f, 0.f); + } + SetOrbitRequest(EPlayerOrbitRequest::EnterMorphBall, mgr); + x490_gun->CancelFiring(mgr); + HolsterGun(mgr); } -void CPlayer::TransitionFromMorphBallState(CStateManager& mgr) -{ - x584_ballTransitionAnim = 14; // B_ball_unfurl - x58c_transitionVel = zeus::CVector2f(x138_velocity.x(), x138_velocity.y()).magnitude(); - if (x58c_transitionVel < 1.f) - x584_ballTransitionAnim = 5; // ballstationarytoready_random - if (x258_movementState != EPlayerMovementState::OnGround) - { - zeus::CVector3f ballPos = GetBallPosition(); - if (mgr.RayCollideWorld(ballPos, ballPos + zeus::CVector3f(0.f, 0.f, -7.f), BallTransitionCollide, this)) - x584_ballTransitionAnim = 7; // B_balljumptoairpose - } +void CPlayer::TransitionFromMorphBallState(CStateManager& mgr) { + x584_ballTransitionAnim = 14; // B_ball_unfurl + x58c_transitionVel = zeus::CVector2f(x138_velocity.x(), x138_velocity.y()).magnitude(); + if (x58c_transitionVel < 1.f) + x584_ballTransitionAnim = 5; // ballstationarytoready_random + if (x258_movementState != EPlayerMovementState::OnGround) { + zeus::CVector3f ballPos = GetBallPosition(); + if (mgr.RayCollideWorld(ballPos, ballPos + zeus::CVector3f(0.f, 0.f, -7.f), BallTransitionCollide, this)) + x584_ballTransitionAnim = 7; // B_balljumptoairpose + } - if (x64_modelData && x64_modelData->HasAnimData()) - { - CAnimPlaybackParms parms(x584_ballTransitionAnim, -1, 1.f, true); - x64_modelData->AnimationData()->SetAnimation(parms, false); - x64_modelData->AnimationData()->SetAnimDir(CAnimData::EAnimDir::Forward); - } + if (x64_modelData && x64_modelData->HasAnimData()) { + CAnimPlaybackParms parms(x584_ballTransitionAnim, -1, 1.f, true); + x64_modelData->AnimationData()->SetAnimation(parms, false); + x64_modelData->AnimationData()->SetAnimDir(CAnimData::EAnimDir::Forward); + } - x64_modelData->EnableLooping(false); - x64_modelData->Touch(mgr, 0); - SetMorphBallState(EPlayerMorphBallState::Unmorphing, mgr); - x768_morphball->LeaveMorphBallState(mgr); - mgr.GetCameraManager()->SetPlayerCamera(mgr, mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId()); - zeus::CVector3f camToPlayer = GetTranslation() - mgr.GetCameraManager()->GetBallCamera()->GetTranslation(); - if (camToPlayer.canBeNormalized()) - { - camToPlayer.normalize(); - zeus::CVector3f vecFlat = x500_lookDir; - vecFlat.z() = 0.f; - zeus::CVector3f f31 = - vecFlat.canBeNormalized() && vecFlat.magnitude() >= 0.1f ? x518_leaveMorphDir : camToPlayer; - if (x9c6_26_outOfBallLookAtHint) - { - if (TCastToConstPtr hint = mgr.GetObjectById(x830_playerHint)) - { - zeus::CVector3f deltaFlat = hint->GetTranslation() - GetTranslation(); - deltaFlat.z() = 0.f; - if (deltaFlat.canBeNormalized()) - f31 = deltaFlat.normalized(); - } - } - if (x9c7_25_outOfBallLookAtHintActor) - { - if (TCastToConstPtr hint = mgr.GetObjectById(x830_playerHint)) - { - if (TCastToConstPtr act = mgr.GetObjectById(hint->GetActorId())) - { - zeus::CVector3f deltaFlat = act->GetOrbitPosition(mgr) - GetTranslation(); - deltaFlat.z() = 0.f; - if (deltaFlat.canBeNormalized()) - f31 = deltaFlat.normalized(); - } - } - } - if (std::acos(zeus::clamp(-1.f, camToPlayer.dot(f31), 1.f)) < M_PIF / 1.2f || x9c7_25_outOfBallLookAtHintActor) - { - SetTransform(zeus::lookAt(GetTranslation(), GetTranslation() + f31)); - } - else - { - SetTransform(zeus::lookAt(GetTranslation(), GetTranslation() + camToPlayer)); - UpdateArmAndGunTransforms(0.01f, mgr); - } + x64_modelData->EnableLooping(false); + x64_modelData->Touch(mgr, 0); + SetMorphBallState(EPlayerMorphBallState::Unmorphing, mgr); + x768_morphball->LeaveMorphBallState(mgr); + mgr.GetCameraManager()->SetPlayerCamera(mgr, mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId()); + zeus::CVector3f camToPlayer = GetTranslation() - mgr.GetCameraManager()->GetBallCamera()->GetTranslation(); + if (camToPlayer.canBeNormalized()) { + camToPlayer.normalize(); + zeus::CVector3f vecFlat = x500_lookDir; + vecFlat.z() = 0.f; + zeus::CVector3f f31 = vecFlat.canBeNormalized() && vecFlat.magnitude() >= 0.1f ? x518_leaveMorphDir : camToPlayer; + if (x9c6_26_outOfBallLookAtHint) { + if (TCastToConstPtr hint = mgr.GetObjectById(x830_playerHint)) { + zeus::CVector3f deltaFlat = hint->GetTranslation() - GetTranslation(); + deltaFlat.z() = 0.f; + if (deltaFlat.canBeNormalized()) + f31 = deltaFlat.normalized(); + } } + if (x9c7_25_outOfBallLookAtHintActor) { + if (TCastToConstPtr hint = mgr.GetObjectById(x830_playerHint)) { + if (TCastToConstPtr act = mgr.GetObjectById(hint->GetActorId())) { + zeus::CVector3f deltaFlat = act->GetOrbitPosition(mgr) - GetTranslation(); + deltaFlat.z() = 0.f; + if (deltaFlat.canBeNormalized()) + f31 = deltaFlat.normalized(); + } + } + } + if (std::acos(zeus::clamp(-1.f, camToPlayer.dot(f31), 1.f)) < M_PIF / 1.2f || x9c7_25_outOfBallLookAtHintActor) { + SetTransform(zeus::lookAt(GetTranslation(), GetTranslation() + f31)); + } else { + SetTransform(zeus::lookAt(GetTranslation(), GetTranslation() + camToPlayer)); + UpdateArmAndGunTransforms(0.01f, mgr); + } + } else { + SetTransform(CreateTransformFromMovementDirection()); + } + + CBallCamera* ballCam = mgr.GetCameraManager()->GetBallCamera(); + if (TCastToConstPtr act = mgr.GetObjectById(ballCam->GetTooCloseActorId())) { + if (ballCam->GetTooCloseActorDistance() < 20.f && ballCam->GetTooCloseActorDistance() > 1.f) { + zeus::CVector3f deltaFlat = act->GetTranslation() - GetTranslation(); + deltaFlat.z() = 0.f; + zeus::CVector3f deltaFlat2 = act->GetTranslation() - ballCam->GetTranslation(); + deltaFlat2.z() = 0.f; + if (deltaFlat.canBeNormalized() && deltaFlat2.canBeNormalized()) { + deltaFlat.normalize(); + zeus::CVector3f camLookFlat = ballCam->GetTransform().basis[1]; + camLookFlat.z() = 0.f; + camLookFlat.normalize(); + deltaFlat2.normalize(); + if (deltaFlat.dot(deltaFlat2) >= 0.3f && deltaFlat2.dot(camLookFlat) >= 0.7f) { + SetTransform(zeus::lookAt(GetTranslation(), GetTranslation() + deltaFlat)); + } + } + } + } + + ForceGunOrientation(x34_transform, mgr); + DrawGun(mgr); + ballCam->SetState(CBallCamera::EBallCameraState::FromBall, mgr); + ClearForcesAndTorques(); + SetAngularVelocityWR(zeus::CAxisAngle::sIdentity); + AddMaterial(EMaterialTypes::GroundCollider, mgr); + x150_momentum = zeus::CVector3f::skZero; + SetCameraState(EPlayerCameraState::Transitioning, mgr); + x824_transitionFilterTimer = 0.01f; + x57c_ = 0; + x580_ = 0; + if (!ballCam->TransitionFromMorphBallState(mgr)) { + x824_transitionFilterTimer = 0.95f; + LeaveMorphBallState(mgr); + } +} + +s32 CPlayer::GetNextBallTransitionAnim(float dt, bool& loopOut, CStateManager& mgr) { + loopOut = false; + zeus::CVector2f vel(x138_velocity.x(), x138_velocity.y()); + if (!vel.canBeNormalized()) + return 12; // B_ball_ready_samus + float velMag = vel.magnitude(); + float maxVel = GetActualFirstPersonMaxVelocity(dt); + if (velMag <= 0.2f * maxVel) + return 12; // B_ball_ready_samus + loopOut = true; + s32 ret = velMag >= maxVel ? 13 : 15; // B_ball_runloop_samus : B_ball_walkloop_samus + if (x50c_moveDir.dot(mgr.GetCameraManager()->GetBallCamera()->GetTransform().basis[1]) < -0.5f) + return 12; // B_ball_ready_samus + return ret; +} + +void CPlayer::UpdateMorphBallTransition(float dt, CStateManager& mgr) { + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Unmorphed: + case EPlayerMorphBallState::Morphed: { + CPlayerState::EPlayerSuit suit = mgr.GetPlayerState()->GetCurrentSuit(); + if (mgr.GetPlayerState()->IsFusionEnabled()) + suit = CPlayerState::EPlayerSuit(int(suit) + 4); + if (x7cc_transitionSuit != suit) { + x7cc_transitionSuit = suit; + CAnimRes useRes = x7d0_animRes; + useRes.SetCharacterNodeId(s32(x7cc_transitionSuit)); + SetModelData(std::make_unique(useRes)); + SetIntoBallReadyAnimation(mgr); + } + return; + } + case EPlayerMorphBallState::Unmorphing: + if (x584_ballTransitionAnim == 14) // B_ball_unfurl + { + float dur = x64_modelData->GetAnimationData()->GetAnimationDuration(x584_ballTransitionAnim); + float facRemaining = x64_modelData->GetAnimationData()->GetAnimTimeRemaining("Whole Body") / dur; + if (facRemaining < 0.5f) { + bool loop = false; + x584_ballTransitionAnim = GetNextBallTransitionAnim(dt, loop, mgr); + if (x64_modelData && x64_modelData->HasAnimData()) { + CAnimPlaybackParms parms(x584_ballTransitionAnim, -1, 1.f, true); + x64_modelData->AnimationData()->SetAnimation(parms, false); + x64_modelData->AnimationData()->EnableLooping(loop); + } + } + } else if (x584_ballTransitionAnim != 5 && x584_ballTransitionAnim != 7) + // ballstationarytoready_random, B_balljumptoairpose + { + float velMag = zeus::CVector2f(x138_velocity.x(), x138_velocity.y()).magnitude(); + if (std::fabs(x58c_transitionVel - velMag) > 0.04f * GetActualFirstPersonMaxVelocity(dt) || velMag < 1.f) { + bool loop = false; + s32 nextAnim = GetNextBallTransitionAnim(dt, loop, mgr); + if (x64_modelData && x64_modelData->HasAnimData() && x584_ballTransitionAnim != nextAnim && + x584_ballTransitionAnim != 7) { + x584_ballTransitionAnim = nextAnim; + CAnimPlaybackParms parms(x584_ballTransitionAnim, -1, 1.f, true); + x64_modelData->AnimationData()->SetAnimation(parms, false); + x64_modelData->AnimationData()->EnableLooping(loop); + x58c_transitionVel = velMag; + } + } + } + break; + default: + break; + } + + SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); + MoveInOneFrameOR(deltas.x0_posDelta, dt); + RotateInOneFrameOR(deltas.xc_rotDelta, dt); + x574_morphTime = std::min(x574_morphTime + dt, x578_morphDuration); + float morphT = x574_morphTime / x578_morphDuration; + if ((morphT >= 0.7f || x574_morphTime <= 2.f * dt) && x730_transitionModels.size() != 0) + x730_transitionModels.erase(x730_transitionModels.begin()); + + for (auto& m : x730_transitionModels) + m->AdvanceAnimation(dt, mgr, kInvalidAreaId, true); + + CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + x588_alpha = GetTransitionAlpha(cam->GetTranslation(), cam->GetNearClipDistance()); + + if (x2f8_morphBallState == EPlayerMorphBallState::Morphing && morphT > 0.93f) { + x588_alpha *= std::min(1.f, 1.f - (morphT - 0.93f) / 0.07f + 0.2f); + xb4_drawFlags = CModelFlags(5, 0, 1, zeus::CColor(1.f, x588_alpha)); + } else if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphing && x588_alpha < 1.f) { + if (x588_alpha > 0.05f) + xb4_drawFlags = CModelFlags(5, 0, 0x21, zeus::CColor(1.f, x588_alpha)); else - { - SetTransform(CreateTransformFromMovementDirection()); - } + xb4_drawFlags = CModelFlags(5, 0, 1, zeus::CColor(1.f, x588_alpha)); + } else { + xb4_drawFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, x588_alpha)); + } - CBallCamera* ballCam = mgr.GetCameraManager()->GetBallCamera(); - if (TCastToConstPtr act = mgr.GetObjectById(ballCam->GetTooCloseActorId())) - { - if (ballCam->GetTooCloseActorDistance() < 20.f && ballCam->GetTooCloseActorDistance() > 1.f) - { - zeus::CVector3f deltaFlat = act->GetTranslation() - GetTranslation(); - deltaFlat.z() = 0.f; - zeus::CVector3f deltaFlat2 = act->GetTranslation() - ballCam->GetTranslation(); - deltaFlat2.z() = 0.f; - if (deltaFlat.canBeNormalized() && deltaFlat2.canBeNormalized()) - { - deltaFlat.normalize(); - zeus::CVector3f camLookFlat = ballCam->GetTransform().basis[1]; - camLookFlat.z() = 0.f; - camLookFlat.normalize(); - deltaFlat2.normalize(); - if (deltaFlat.dot(deltaFlat2) >= 0.3f && deltaFlat2.dot(camLookFlat) >= 0.7f) - { - SetTransform(zeus::lookAt(GetTranslation(), GetTranslation() + deltaFlat)); - } - } - } - } + x594_transisionBeamXfs.AddValue(x7f4_gunWorldXf); + x658_transitionModelXfs.AddValue(x34_transform); + x71c_transitionModelAlphas.AddValue(x588_alpha); - ForceGunOrientation(x34_transform, mgr); - DrawGun(mgr); - ballCam->SetState(CBallCamera::EBallCameraState::FromBall, mgr); + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Unmorphing: + GetCollisionPrimitive()->CalculateAABox(GetPrimitiveTransform()).center(); ClearForcesAndTorques(); SetAngularVelocityWR(zeus::CAxisAngle::sIdentity); - AddMaterial(EMaterialTypes::GroundCollider, mgr); - x150_momentum = zeus::CVector3f::skZero; - SetCameraState(EPlayerCameraState::Transitioning, mgr); - x824_transitionFilterTimer = 0.01f; - x57c_ = 0; - x580_ = 0; - if (!ballCam->TransitionFromMorphBallState(mgr)) - { - x824_transitionFilterTimer = 0.95f; + if (x574_morphTime >= x578_morphDuration || mgr.GetCameraManager()->IsInCinematicCamera()) { + x824_transitionFilterTimer = std::max(x824_transitionFilterTimer, 0.95f); + zeus::CVector3f pos; + if (CanLeaveMorphBallState(mgr, pos)) { + SetTranslation(GetTranslation() + pos); LeaveMorphBallState(mgr); + xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); + } else { + x574_morphTime = x578_morphDuration - x574_morphTime; + TransitionToMorphBallState(dt, mgr); + } } + break; + case EPlayerMorphBallState::Morphing: + ClearForcesAndTorques(); + ClearForcesAndTorques(); + SetAngularVelocityWR(zeus::CAxisAngle::sIdentity); + if (x574_morphTime >= x578_morphDuration || mgr.GetCameraManager()->IsInCinematicCamera()) { + if (CanEnterMorphBallState(mgr, 1.f)) { + ActivateMorphBallCamera(mgr); + EnterMorphBallState(mgr); + xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); + } else { + x574_morphTime = x578_morphDuration - x574_morphTime; + TransitionFromMorphBallState(mgr); + } + } + if (x578_morphDuration != 0.f) { + if (zeus::clamp(0.f, x574_morphTime, 1.f) >= 0.5f) { + if (!x768_morphball->IsMorphBallTransitionFlashValid()) + x768_morphball->ResetMorphBallTransitionFlash(); + } + } + break; + default: + break; + } } -s32 CPlayer::GetNextBallTransitionAnim(float dt, bool& loopOut, CStateManager& mgr) -{ - loopOut = false; - zeus::CVector2f vel(x138_velocity.x(), x138_velocity.y()); - if (!vel.canBeNormalized()) - return 12; // B_ball_ready_samus - float velMag = vel.magnitude(); +void CPlayer::UpdateGunAlpha() { + switch (x498_gunHolsterState) { + case EGunHolsterState::Holstered: + x494_gunAlpha = 0.f; + break; + case EGunHolsterState::Holstering: + x494_gunAlpha = zeus::clamp(0.f, x49c_gunHolsterRemTime / g_tweakPlayerGun->GetGunHolsterTime(), 1.f); + break; + case EGunHolsterState::Drawing: + x494_gunAlpha = 1.f - zeus::clamp(0.f, x49c_gunHolsterRemTime / 0.45f, 1.f); + break; + case EGunHolsterState::Drawn: + x494_gunAlpha = 1.f; + break; + } +} + +void CPlayer::UpdatePlayerSounds(float dt) { + if (x784_damageSfxTimer > 0.f) { + x784_damageSfxTimer -= dt; + if (x784_damageSfxTimer <= 0.f) { + CSfxManager::SfxStop(x770_damageLoopSfx); + x770_damageLoopSfx.reset(); + } + } +} + +void CPlayer::Update(float dt, CStateManager& mgr) { + SetCoefficientOfRestitutionModifier(0.f); + UpdateMorphBallTransition(dt, mgr); + CPlayerState::EBeamId newBeam = mgr.GetPlayerState()->GetCurrentBeam(); + if (newBeam != x7ec_beam) { + x7ec_beam = newBeam; + x7f0_ballTransitionBeamModel.reset( + new CModelData(CStaticRes(g_tweakPlayerRes->GetBeamBallTransitionModel(x7ec_beam), x7d8_beamScale))); + } + + if (!mgr.GetPlayerState()->IsPlayerAlive()) { + if (x9f4_deathTime == 0.f) { + CSfxManager::KillAll(CSfxManager::ESfxChannels::Game); + CStreamAudioManager::StopAll(); + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) { + CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_death, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } + } + + float prevDeathTime = x9f4_deathTime; + x9f4_deathTime += dt; + if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) { + if (x9f4_deathTime >= 1.f && prevDeathTime < 1.f) + xa00_deathPowerBomb = x490_gun->DropPowerBomb(mgr); + if (x9f4_deathTime >= 4.f && prevDeathTime < 4.f) { + CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_death, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } + } + } + + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Unmorphed: + case EPlayerMorphBallState::Morphing: + case EPlayerMorphBallState::Unmorphing: + x7f4_gunWorldXf = x34_transform * x64_modelData->GetScaledLocatorTransform("GUN_LCTR"); + case EPlayerMorphBallState::Morphed: + break; + } + + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) { + UpdateAimTargetTimer(dt); + UpdateAimTarget(mgr); + UpdateOrbitModeTimer(dt); + } + UpdateOrbitPreventionTimer(dt); + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) + x768_morphball->Update(dt, mgr); + else + x768_morphball->StopSounds(); + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphing || + x2f8_morphBallState == EPlayerMorphBallState::Morphing) + x768_morphball->UpdateEffects(dt, mgr); + UpdateGunAlpha(); + UpdateDebugCamera(mgr); + UpdateVisorTransition(dt, mgr); + mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId()); + UpdatePlayerSounds(dt); + if (x26c_attachedActor != kInvalidUniqueId) + x270_attachedActorTime += dt; + + x740_staticTimer = std::max(0.f, x740_staticTimer - dt); + if (x740_staticTimer > 0.f) + x74c_visorStaticAlpha = std::max(0.f, x74c_visorStaticAlpha - x744_staticOutSpeed * dt); + else + x74c_visorStaticAlpha = std::min(1.f, x74c_visorStaticAlpha + x748_staticInSpeed * dt); + + x274_energyDrain.ProcessEnergyDrain(mgr, dt); + x4a4_moveSpeedAvg.AddValue(x4f8_moveSpeed); + + mgr.GetPlayerState()->UpdateStaticInterference(mgr, dt); + if (!ShouldSampleFailsafe(mgr)) + CPhysicsActor::Stop(); + + if (IsEnergyLow(mgr)) + xa30_samusExhaustedVoiceTimer -= dt; + else + xa30_samusExhaustedVoiceTimer = 4.f; + + if (!mgr.GetCameraManager()->IsInCinematicCamera() && xa30_samusExhaustedVoiceTimer <= 0.f) { + StartSamusVoiceSfx(SFXsam_vox_exhausted, 1.f, 7); + xa30_samusExhaustedVoiceTimer = 4.f; + } +} + +static const float skStrafeDistances[] = {11.8f, 11.8f, 11.8f, 5.0f, 6.0f, 5.0f, 5.0f, 6.0f}; + +static const float skDashStrafeDistances[] = {30.0f, 22.6f, 10.0f, 10.0f, 10.0f, 10.0f, 10.0f}; + +static const float skOrbitForwardDistances[] = {11.8f, 11.8f, 11.8f, 5.0f, 6.0f, 5.0f, 5.0f, 6.0f}; + +float CPlayer::UpdateCameraBob(float dt, CStateManager& mgr) { + float bobMag = 0.f; + CPlayerCameraBob::ECameraBobState state; + zeus::CVector3f backupVel = x138_velocity; + if (x304_orbitState == EPlayerOrbitState::NoOrbit) { + bobMag = std::fabs(backupVel.dot(x34_transform.basis[1]) / GetActualFirstPersonMaxVelocity(dt)); + state = CPlayerCameraBob::ECameraBobState::Walk; + if (bobMag < 0.01f) { + bobMag = 0.f; + state = CPlayerCameraBob::ECameraBobState::WalkNoBob; + } + } else { + state = CPlayerCameraBob::ECameraBobState::Orbit; + float f29 = backupVel.dot(x34_transform.basis[0]); + float f30 = backupVel.dot(x34_transform.basis[1]); float maxVel = GetActualFirstPersonMaxVelocity(dt); - if (velMag <= 0.2f * maxVel) - return 12; // B_ball_ready_samus - loopOut = true; - s32 ret = velMag >= maxVel ? 13 : 15; // B_ball_runloop_samus : B_ball_walkloop_samus - if (x50c_moveDir.dot(mgr.GetCameraManager()->GetBallCamera()->GetTransform().basis[1]) < -0.5f) - return 12; // B_ball_ready_samus - return ret; + float strafeDist = + skStrafeDistances[int(x2b0_outOfWaterTicks == 2 ? x2ac_surfaceRestraint : ESurfaceRestraints::Water)]; + bobMag = std::min(std::sqrt(f30 * f30 + f29 * f29) / std::sqrt(strafeDist * strafeDist + maxVel * maxVel) * + CPlayerCameraBob::kOrbitBobScale, + CPlayerCameraBob::kMaxOrbitBobScale); + if (bobMag < 0.01f) + bobMag = 0.f; + } + + if (x258_movementState != EPlayerMovementState::OnGround) { + bobMag = 0.f; + state = CPlayerCameraBob::ECameraBobState::InAir; + } else if (bobMag < 0.01f) { + if (x490_gun->GetLastFireButtonStates() != 0) { + bobMag = 0.f; + state = CPlayerCameraBob::ECameraBobState::GunFireNoBob; + } else if (std::fabs(GetAngularVelocityOR().angle()) > 0.1f) { + bobMag = 0.f; + state = CPlayerCameraBob::ECameraBobState::TurningNoBob; + } + } + + if (x3dc_inFreeLook || x3dd_lookButtonHeld) { + bobMag = 0.f; + state = CPlayerCameraBob::ECameraBobState::FreeLookNoBob; + } + + if (x304_orbitState == EPlayerOrbitState::Grapple) { + bobMag = 0.f; + state = CPlayerCameraBob::ECameraBobState::GrappleNoBob; + } + + if (x3a8_scanState == EPlayerScanState::ScanComplete) { + bobMag = 0.f; + } + + if (x38c_doneSidewaysDashing) { + bobMag *= 0.1f; + state = CPlayerCameraBob::ECameraBobState::FreeLookNoBob; + if (x258_movementState == EPlayerMovementState::OnGround) + x38c_doneSidewaysDashing = false; + } + + if (mgr.GetCameraManager()->IsInCinematicCamera()) + bobMag = 0.f; + + bobMag *= mgr.GetCameraManager()->GetCameraBobMagnitude(); + + x76c_cameraBob->SetPlayerVelocity(backupVel); + x76c_cameraBob->SetState(state, mgr); + x76c_cameraBob->SetBobMagnitude(bobMag); + x76c_cameraBob->SetBobTimeScale((1.f - CPlayerCameraBob::kSlowSpeedPeriodScale) * bobMag + + CPlayerCameraBob::kSlowSpeedPeriodScale); + x76c_cameraBob->Update(dt, mgr); + + return bobMag; } -void CPlayer::UpdateMorphBallTransition(float dt, CStateManager& mgr) -{ - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Unmorphed: - case EPlayerMorphBallState::Morphed: - { - CPlayerState::EPlayerSuit suit = mgr.GetPlayerState()->GetCurrentSuit(); - if (mgr.GetPlayerState()->IsFusionEnabled()) - suit = CPlayerState::EPlayerSuit(int(suit) + 4); - if (x7cc_transitionSuit != suit) - { - x7cc_transitionSuit = suit; - CAnimRes useRes = x7d0_animRes; - useRes.SetCharacterNodeId(s32(x7cc_transitionSuit)); - SetModelData(std::make_unique(useRes)); - SetIntoBallReadyAnimation(mgr); - } - return; - } - case EPlayerMorphBallState::Unmorphing: - if (x584_ballTransitionAnim == 14) // B_ball_unfurl - { - float dur = x64_modelData->GetAnimationData()->GetAnimationDuration(x584_ballTransitionAnim); - float facRemaining = x64_modelData->GetAnimationData()->GetAnimTimeRemaining("Whole Body") / dur; - if (facRemaining < 0.5f) - { - bool loop = false; - x584_ballTransitionAnim = GetNextBallTransitionAnim(dt, loop, mgr); - if (x64_modelData && x64_modelData->HasAnimData()) - { - CAnimPlaybackParms parms(x584_ballTransitionAnim, -1, 1.f, true); - x64_modelData->AnimationData()->SetAnimation(parms, false); - x64_modelData->AnimationData()->EnableLooping(loop); - } - } - } - else if (x584_ballTransitionAnim != 5 && x584_ballTransitionAnim != 7) - // ballstationarytoready_random, B_balljumptoairpose - { - float velMag = zeus::CVector2f(x138_velocity.x(), x138_velocity.y()).magnitude(); - if (std::fabs(x58c_transitionVel - velMag) > 0.04f * GetActualFirstPersonMaxVelocity(dt) || velMag < 1.f) - { - bool loop = false; - s32 nextAnim = GetNextBallTransitionAnim(dt, loop, mgr); - if (x64_modelData && x64_modelData->HasAnimData() && - x584_ballTransitionAnim != nextAnim && x584_ballTransitionAnim != 7) - { - x584_ballTransitionAnim = nextAnim; - CAnimPlaybackParms parms(x584_ballTransitionAnim, -1, 1.f, true); - x64_modelData->AnimationData()->SetAnimation(parms, false); - x64_modelData->AnimationData()->EnableLooping(loop); - x58c_transitionVel = velMag; - } - } - } - break; - default: - break; - } - - SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); - MoveInOneFrameOR(deltas.x0_posDelta, dt); - RotateInOneFrameOR(deltas.xc_rotDelta, dt); - x574_morphTime = std::min(x574_morphTime + dt, x578_morphDuration); - float morphT = x574_morphTime / x578_morphDuration; - if ((morphT >= 0.7f || x574_morphTime <= 2.f * dt) && x730_transitionModels.size() != 0) - x730_transitionModels.erase(x730_transitionModels.begin()); - - for (auto& m : x730_transitionModels) - m->AdvanceAnimation(dt, mgr, kInvalidAreaId, true); - - CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - x588_alpha = GetTransitionAlpha(cam->GetTranslation(), cam->GetNearClipDistance()); - - if (x2f8_morphBallState == EPlayerMorphBallState::Morphing && morphT > 0.93f) - { - x588_alpha *= std::min(1.f, 1.f - (morphT - 0.93f) / 0.07f + 0.2f); - xb4_drawFlags = CModelFlags(5, 0, 1, zeus::CColor(1.f, x588_alpha)); - } - else if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphing && x588_alpha < 1.f) - { - if (x588_alpha > 0.05f) - xb4_drawFlags = CModelFlags(5, 0, 0x21, zeus::CColor(1.f, x588_alpha)); - else - xb4_drawFlags = CModelFlags(5, 0, 1, zeus::CColor(1.f, x588_alpha)); - } - else - { - xb4_drawFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, x588_alpha)); - } - - x594_transisionBeamXfs.AddValue(x7f4_gunWorldXf); - x658_transitionModelXfs.AddValue(x34_transform); - x71c_transitionModelAlphas.AddValue(x588_alpha); - - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Unmorphing: - GetCollisionPrimitive()->CalculateAABox(GetPrimitiveTransform()).center(); - ClearForcesAndTorques(); - SetAngularVelocityWR(zeus::CAxisAngle::sIdentity); - if (x574_morphTime >= x578_morphDuration || mgr.GetCameraManager()->IsInCinematicCamera()) - { - x824_transitionFilterTimer = std::max(x824_transitionFilterTimer, 0.95f); - zeus::CVector3f pos; - if (CanLeaveMorphBallState(mgr, pos)) - { - SetTranslation(GetTranslation() + pos); - LeaveMorphBallState(mgr); - xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); - } - else - { - x574_morphTime = x578_morphDuration - x574_morphTime; - TransitionToMorphBallState(dt, mgr); - } - } - break; - case EPlayerMorphBallState::Morphing: - ClearForcesAndTorques(); - ClearForcesAndTorques(); - SetAngularVelocityWR(zeus::CAxisAngle::sIdentity); - if (x574_morphTime >= x578_morphDuration || mgr.GetCameraManager()->IsInCinematicCamera()) - { - if (CanEnterMorphBallState(mgr, 1.f)) - { - ActivateMorphBallCamera(mgr); - EnterMorphBallState(mgr); - xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); - } else - { - x574_morphTime = x578_morphDuration - x574_morphTime; - TransitionFromMorphBallState(mgr); - } - } - if (x578_morphDuration != 0.f) - { - if (zeus::clamp(0.f, x574_morphTime, 1.f) >= 0.5f) - { - if (!x768_morphball->IsMorphBallTransitionFlashValid()) - x768_morphball->ResetMorphBallTransitionFlash(); - } - } - break; - default: - break; - } +float CPlayer::GetAcceleration() const { + if (x2d0_curAcceleration >= x2b4_accelerationTable.size()) + return x2b4_accelerationTable.back(); + return x2b4_accelerationTable[x2d0_curAcceleration]; } -void CPlayer::UpdateGunAlpha() -{ - switch (x498_gunHolsterState) - { - case EGunHolsterState::Holstered: - x494_gunAlpha = 0.f; - break; - case EGunHolsterState::Holstering: - x494_gunAlpha = zeus::clamp(0.f, x49c_gunHolsterRemTime / g_tweakPlayerGun->GetGunHolsterTime(), 1.f); - break; - case EGunHolsterState::Drawing: - x494_gunAlpha = 1.f - zeus::clamp(0.f, x49c_gunHolsterRemTime / 0.45f, 1.f); - break; - case EGunHolsterState::Drawn: - x494_gunAlpha = 1.f; - break; - } +float CPlayer::CalculateOrbitMinDistance(EPlayerOrbitType type) const { + return zeus::clamp(1.f, std::fabs(x314_orbitPoint.z() - GetTranslation().z()) / 20.f, 4.f) * + g_tweakPlayer->GetOrbitMinDistance(int(type)); } -void CPlayer::UpdatePlayerSounds(float dt) -{ - if (x784_damageSfxTimer > 0.f) - { - x784_damageSfxTimer -= dt; - if (x784_damageSfxTimer <= 0.f) - { - CSfxManager::SfxStop(x770_damageLoopSfx); - x770_damageLoopSfx.reset(); - } - } +void CPlayer::PostUpdate(float dt, CStateManager& mgr) { + UpdateArmAndGunTransforms(dt, mgr); + + float grappleSwingT; + if (x3b8_grappleState != EGrappleState::Swinging) + grappleSwingT = 0.f; + else + grappleSwingT = x3bc_grappleSwingTimer / g_tweakPlayer->GetGrappleSwingPeriod(); + + float cameraBobT = 0.f; + if (mgr.GetCameraManager()->IsInCinematicCamera()) { + zeus::CVector2f bobExtent(CPlayerCameraBob::kCameraBobExtentX, CPlayerCameraBob::kCameraBobExtentY); + x76c_cameraBob.reset( + new CPlayerCameraBob(CPlayerCameraBob::ECameraBobType::One, bobExtent, CPlayerCameraBob::kCameraBobPeriod)); + } else { + cameraBobT = UpdateCameraBob(dt, mgr); + } + + x490_gun->Update(grappleSwingT, cameraBobT, dt, mgr); + UpdateOrbitTarget(mgr); + UpdateOrbitOrientation(mgr); } -void CPlayer::Update(float dt, CStateManager& mgr) -{ - SetCoefficientOfRestitutionModifier(0.f); - UpdateMorphBallTransition(dt, mgr); - CPlayerState::EBeamId newBeam = mgr.GetPlayerState()->GetCurrentBeam(); - if (newBeam != x7ec_beam) - { - x7ec_beam = newBeam; - x7f0_ballTransitionBeamModel.reset( - new CModelData(CStaticRes(g_tweakPlayerRes->GetBeamBallTransitionModel(x7ec_beam), x7d8_beamScale))); - } - - if (!mgr.GetPlayerState()->IsPlayerAlive()) - { - if (x9f4_deathTime == 0.f) - { - CSfxManager::KillAll(CSfxManager::ESfxChannels::Game); - CStreamAudioManager::StopAll(); - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_death, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - } - - float prevDeathTime = x9f4_deathTime; - x9f4_deathTime += dt; - if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) - { - if (x9f4_deathTime >= 1.f && prevDeathTime < 1.f) - xa00_deathPowerBomb = x490_gun->DropPowerBomb(mgr); - if (x9f4_deathTime >= 4.f && prevDeathTime < 4.f) - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_death, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - } - } - - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Unmorphed: - case EPlayerMorphBallState::Morphing: - case EPlayerMorphBallState::Unmorphing: - x7f4_gunWorldXf = x34_transform * x64_modelData->GetScaledLocatorTransform("GUN_LCTR"); - case EPlayerMorphBallState::Morphed: - break; - } - - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) - { - UpdateAimTargetTimer(dt); - UpdateAimTarget(mgr); - UpdateOrbitModeTimer(dt); - } - UpdateOrbitPreventionTimer(dt); - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - x768_morphball->Update(dt, mgr); - else - x768_morphball->StopSounds(); - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphing || - x2f8_morphBallState == EPlayerMorphBallState::Morphing) - x768_morphball->UpdateEffects(dt, mgr); - UpdateGunAlpha(); - UpdateDebugCamera(mgr); - UpdateVisorTransition(dt, mgr); - mgr.SetActorAreaId(*this, mgr.GetWorld()->GetCurrentAreaId()); - UpdatePlayerSounds(dt); - if (x26c_attachedActor != kInvalidUniqueId) - x270_attachedActorTime += dt; - - x740_staticTimer = std::max(0.f, x740_staticTimer - dt); - if (x740_staticTimer > 0.f) - x74c_visorStaticAlpha = std::max(0.f, x74c_visorStaticAlpha - x744_staticOutSpeed * dt); - else - x74c_visorStaticAlpha = std::min(1.f, x74c_visorStaticAlpha + x748_staticInSpeed * dt); - - x274_energyDrain.ProcessEnergyDrain(mgr, dt); - x4a4_moveSpeedAvg.AddValue(x4f8_moveSpeed); - - mgr.GetPlayerState()->UpdateStaticInterference(mgr, dt); - if (!ShouldSampleFailsafe(mgr)) - CPhysicsActor::Stop(); - - if (IsEnergyLow(mgr)) - xa30_samusExhaustedVoiceTimer -= dt; - else - xa30_samusExhaustedVoiceTimer = 4.f; - - if (!mgr.GetCameraManager()->IsInCinematicCamera() && xa30_samusExhaustedVoiceTimer <= 0.f) - { - StartSamusVoiceSfx(SFXsam_vox_exhausted, 1.f, 7); - xa30_samusExhaustedVoiceTimer = 4.f; - } -} - -static const float skStrafeDistances[] = -{ - 11.8f, 11.8f, 11.8f, 5.0f, 6.0f, 5.0f, 5.0f, 6.0f -}; - -static const float skDashStrafeDistances[] = -{ - 30.0f, 22.6f, 10.0f, 10.0f, 10.0f, 10.0f, 10.0f -}; - -static const float skOrbitForwardDistances[] = -{ - 11.8f, 11.8f, 11.8f, 5.0f, 6.0f, 5.0f, 5.0f, 6.0f -}; - -float CPlayer::UpdateCameraBob(float dt, CStateManager& mgr) -{ - float bobMag = 0.f; - CPlayerCameraBob::ECameraBobState state; - zeus::CVector3f backupVel = x138_velocity; - if (x304_orbitState == EPlayerOrbitState::NoOrbit) - { - bobMag = std::fabs(backupVel.dot(x34_transform.basis[1]) / GetActualFirstPersonMaxVelocity(dt)); - state = CPlayerCameraBob::ECameraBobState::Walk; - if (bobMag < 0.01f) - { - bobMag = 0.f; - state = CPlayerCameraBob::ECameraBobState::WalkNoBob; - } - } - else - { - state = CPlayerCameraBob::ECameraBobState::Orbit; - float f29 = backupVel.dot(x34_transform.basis[0]); - float f30 = backupVel.dot(x34_transform.basis[1]); - float maxVel = GetActualFirstPersonMaxVelocity(dt); - float strafeDist = skStrafeDistances[int(x2b0_outOfWaterTicks == 2 ? - x2ac_surfaceRestraint : ESurfaceRestraints::Water)]; - bobMag = std::min(std::sqrt(f30 * f30 + f29 * f29) / std::sqrt(strafeDist * strafeDist + maxVel * maxVel) * - CPlayerCameraBob::kOrbitBobScale, CPlayerCameraBob::kMaxOrbitBobScale); - if (bobMag < 0.01f) - bobMag = 0.f; - } - - if (x258_movementState != EPlayerMovementState::OnGround) - { - bobMag = 0.f; - state = CPlayerCameraBob::ECameraBobState::InAir; - } - else if (bobMag < 0.01f) - { - if (x490_gun->GetLastFireButtonStates() != 0) - { - bobMag = 0.f; - state = CPlayerCameraBob::ECameraBobState::GunFireNoBob; - } - else if (std::fabs(GetAngularVelocityOR().angle()) > 0.1f) - { - bobMag = 0.f; - state = CPlayerCameraBob::ECameraBobState::TurningNoBob; - } - } - - if (x3dc_inFreeLook || x3dd_lookButtonHeld) - { - bobMag = 0.f; - state = CPlayerCameraBob::ECameraBobState::FreeLookNoBob; - } - - if (x304_orbitState == EPlayerOrbitState::Grapple) - { - bobMag = 0.f; - state = CPlayerCameraBob::ECameraBobState::GrappleNoBob; - } - - if (x3a8_scanState == EPlayerScanState::ScanComplete) - { - bobMag = 0.f; - } - - if (x38c_doneSidewaysDashing) - { - bobMag *= 0.1f; - state = CPlayerCameraBob::ECameraBobState::FreeLookNoBob; - if (x258_movementState == EPlayerMovementState::OnGround) - x38c_doneSidewaysDashing = false; - } - - if (mgr.GetCameraManager()->IsInCinematicCamera()) - bobMag = 0.f; - - bobMag *= mgr.GetCameraManager()->GetCameraBobMagnitude(); - - x76c_cameraBob->SetPlayerVelocity(backupVel); - x76c_cameraBob->SetState(state, mgr); - x76c_cameraBob->SetBobMagnitude(bobMag); - x76c_cameraBob->SetBobTimeScale((1.f - CPlayerCameraBob::kSlowSpeedPeriodScale) * bobMag + - CPlayerCameraBob::kSlowSpeedPeriodScale); - x76c_cameraBob->Update(dt, mgr); - - return bobMag; -} - -float CPlayer::GetAcceleration() const -{ - if (x2d0_curAcceleration >= x2b4_accelerationTable.size()) - return x2b4_accelerationTable.back(); - return x2b4_accelerationTable[x2d0_curAcceleration]; -} - -float CPlayer::CalculateOrbitMinDistance(EPlayerOrbitType type) const -{ - return zeus::clamp(1.f, std::fabs(x314_orbitPoint.z() - GetTranslation().z()) / 20.f, 4.f) * - g_tweakPlayer->GetOrbitMinDistance(int(type)); -} - -void CPlayer::PostUpdate(float dt, CStateManager& mgr) -{ - UpdateArmAndGunTransforms(dt, mgr); - - float grappleSwingT; - if (x3b8_grappleState != EGrappleState::Swinging) - grappleSwingT = 0.f; - else - grappleSwingT = x3bc_grappleSwingTimer / g_tweakPlayer->GetGrappleSwingPeriod(); - - float cameraBobT = 0.f; - if (mgr.GetCameraManager()->IsInCinematicCamera()) - { - zeus::CVector2f bobExtent(CPlayerCameraBob::kCameraBobExtentX, - CPlayerCameraBob::kCameraBobExtentY); - x76c_cameraBob.reset(new CPlayerCameraBob(CPlayerCameraBob::ECameraBobType::One, bobExtent, - CPlayerCameraBob::kCameraBobPeriod)); - } - else - { - cameraBobT = UpdateCameraBob(dt, mgr); - } - - x490_gun->Update(grappleSwingT, cameraBobT, dt, mgr); - UpdateOrbitTarget(mgr); - UpdateOrbitOrientation(mgr); -} - -bool CPlayer::StartSamusVoiceSfx(u16 sfx, float vol, int prio) -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - return false; - bool started = true; - if (x77c_samusVoiceSfx) - { - if (CSfxManager::IsPlaying(x77c_samusVoiceSfx)) - { - started = false; - if (prio > x780_samusVoicePriority) - { - CSfxManager::SfxStop(x77c_samusVoiceSfx); - started = true; - } - } - if (started) - { - x77c_samusVoiceSfx = CSfxManager::SfxStart(sfx, vol, 0.f, false, 0x7f, false, kInvalidAreaId); - x780_samusVoicePriority = prio; - } - } - return started; -} - -bool CPlayer::IsPlayerDeadEnough() const -{ - if (x2f8_morphBallState == CPlayer::EPlayerMorphBallState::Unmorphed) - return x9f4_deathTime > 2.5f; - if (x2f8_morphBallState == CPlayer::EPlayerMorphBallState::Morphed) - return x9f4_deathTime > 6.f; - +bool CPlayer::StartSamusVoiceSfx(u16 sfx, float vol, int prio) { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) return false; + bool started = true; + if (x77c_samusVoiceSfx) { + if (CSfxManager::IsPlaying(x77c_samusVoiceSfx)) { + started = false; + if (prio > x780_samusVoicePriority) { + CSfxManager::SfxStop(x77c_samusVoiceSfx); + started = true; + } + } + if (started) { + x77c_samusVoiceSfx = CSfxManager::SfxStart(sfx, vol, 0.f, false, 0x7f, false, kInvalidAreaId); + x780_samusVoicePriority = prio; + } + } + return started; +} + +bool CPlayer::IsPlayerDeadEnough() const { + if (x2f8_morphBallState == CPlayer::EPlayerMorphBallState::Unmorphed) + return x9f4_deathTime > 2.5f; + if (x2f8_morphBallState == CPlayer::EPlayerMorphBallState::Morphed) + return x9f4_deathTime > 6.f; + + return false; } void CPlayer::AsyncLoadSuit(CStateManager& mgr) { x490_gun->AsyncLoadSuit(mgr); } -void CPlayer::LoadAnimationTokens() -{ - TLockedToken transGroup = g_SimplePool->GetObj("BallTransition_DGRP"); - CDependencyGroup& group = *transGroup; - x25c_ballTransitionsRes.reserve(group.GetObjectTagVector().size()); - for (const SObjectTag& tag : group.GetObjectTagVector()) - { - if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('CSKR') || tag.type == FOURCC('TXTR')) - continue; - x25c_ballTransitionsRes.push_back(g_SimplePool->GetObj(tag)); - } +void CPlayer::LoadAnimationTokens() { + TLockedToken transGroup = g_SimplePool->GetObj("BallTransition_DGRP"); + CDependencyGroup& group = *transGroup; + x25c_ballTransitionsRes.reserve(group.GetObjectTagVector().size()); + for (const SObjectTag& tag : group.GetObjectTagVector()) { + if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('CSKR') || tag.type == FOURCC('TXTR')) + continue; + x25c_ballTransitionsRes.push_back(g_SimplePool->GetObj(tag)); + } } -bool CPlayer::HasTransitionBeamModel() const -{ - return x7f0_ballTransitionBeamModel && !x7f0_ballTransitionBeamModel->IsNull(); +bool CPlayer::HasTransitionBeamModel() const { + return x7f0_ballTransitionBeamModel && !x7f0_ballTransitionBeamModel->IsNull(); } bool CPlayer::CanRenderUnsorted(const CStateManager& mgr) const { return false; } const CDamageVulnerability* CPlayer::GetDamageVulnerability(const zeus::CVector3f& v1, const zeus::CVector3f& v2, - const CDamageInfo& info) const -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && x570_immuneTimer > 0.f && !info.NoImmunity()) - return &CDamageVulnerability::ImmuneVulnerabilty(); - return &CDamageVulnerability::NormalVulnerabilty(); + const CDamageInfo& info) const { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && x570_immuneTimer > 0.f && !info.NoImmunity()) + return &CDamageVulnerability::ImmuneVulnerabilty(); + return &CDamageVulnerability::NormalVulnerabilty(); } -const CDamageVulnerability* CPlayer::GetDamageVulnerability() const -{ - CDamageInfo info(CWeaponMode(EWeaponType::Power, false, false, false), 0.f, 0.f, 0.f); - return GetDamageVulnerability(zeus::CVector3f::skZero, zeus::CVector3f::skUp, info); +const CDamageVulnerability* CPlayer::GetDamageVulnerability() const { + CDamageInfo info(CWeaponMode(EWeaponType::Power, false, false, false), 0.f, 0.f, 0.f); + return GetDamageVulnerability(zeus::CVector3f::skZero, zeus::CVector3f::skUp, info); } -zeus::CVector3f CPlayer::GetHomingPosition(const CStateManager& mgr, float dt) const -{ - if (dt > 0.f) - return x34_transform.origin + PredictMotion(dt).x0_translation; - return x34_transform.origin; +zeus::CVector3f CPlayer::GetHomingPosition(const CStateManager& mgr, float dt) const { + if (dt > 0.f) + return x34_transform.origin + PredictMotion(dt).x0_translation; + return x34_transform.origin; } -zeus::CVector3f CPlayer::GetAimPosition(const CStateManager& mgr, float dt) const -{ - zeus::CVector3f ret = x34_transform.origin; - if (dt > 0.f) - { - if (x304_orbitState == EPlayerOrbitState::NoOrbit) - ret += PredictMotion(dt).x0_translation; +zeus::CVector3f CPlayer::GetAimPosition(const CStateManager& mgr, float dt) const { + zeus::CVector3f ret = x34_transform.origin; + if (dt > 0.f) { + if (x304_orbitState == EPlayerOrbitState::NoOrbit) + ret += PredictMotion(dt).x0_translation; + else + ret = CSteeringBehaviors::ProjectOrbitalPosition(ret, x138_velocity, x314_orbitPoint, dt, xa04_preThinkDt); + } + + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) + ret.z() += g_tweakPlayer->GetPlayerBallHalfExtent(); + else + ret.z() += GetEyeHeight(); + + return ret; +} + +void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager& mgr) { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + x768_morphball->FluidFXThink(state, water, mgr); + if (state == EFluidState::InFluid) + x9c5_30_selectFluidBallSound = true; + } else if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) { + if (mgr.GetFluidPlaneManager()->GetLastSplashDeltaTime(x8_uid) >= 0.2f) { + zeus::CVector3f position(x34_transform.origin); + position.z() = float(water.GetTriggerBoundsWR().max.z()); + mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.1f, state == EFluidState::EnteredFluid); + } + } else { + if (mgr.GetFluidPlaneManager()->GetLastSplashDeltaTime(x8_uid) >= 0.2f) { + zeus::CVector3f posOffset = x50c_moveDir; + if (posOffset.canBeNormalized()) + posOffset = posOffset.normalized() * zeus::CVector3f(1.2f, 1.2f, 0.f); + switch (state) { + case EFluidState::EnteredFluid: { + bool doSplash = true; + if (x4fc_flatMoveSpeed > 12.5f) { + zeus::CVector3f lookDir = x34_transform.basis[1].normalized(); + zeus::CVector3f dcVel = GetDampedClampedVelocityWR(); + dcVel.z() = 0.f; + if (lookDir.dot(dcVel.normalized()) > 0.75f) + doSplash = false; + } + if (doSplash) { + zeus::CVector3f position = x34_transform.origin + posOffset; + position.z() = float(water.GetTriggerBoundsWR().max.z()); + mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.3f, true); + if (water.GetFluidPlane().GetFluidType() == EFluidType::NormalWater) { + float velMag = mgr.GetPlayer().GetVelocity().magnitude() / 10.f; + mgr.GetEnvFxManager()->SetSplashRate(10.f * std::max(1.f, velMag)); + } + } + break; + } + case EFluidState::InFluid: { + if (x138_velocity.magnitude() > 1.f && mgr.GetFluidPlaneManager()->GetLastRippleDeltaTime(x8_uid) >= 0.2f) { + zeus::CVector3f position(x34_transform.origin); + position.z() = float(water.GetTriggerBoundsWR().max.z()); + water.GetFluidPlane().AddRipple(0.5f, x8_uid, position, water, mgr); + } + break; + } + case EFluidState::LeftFluid: { + zeus::CVector3f position = x34_transform.origin + posOffset; + position.z() = float(water.GetTriggerBoundsWR().max.z()); + mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.15f, true); + break; + } + default: + break; + } + } + } +} + +void CPlayer::TakeDamage(bool significant, const zeus::CVector3f& location, float dam, EWeaponType type, + CStateManager& mgr) { + if (!significant) + return; + if (dam >= 0.f) { + x570_immuneTimer = 0.5f; + x55c_damageAmt = dam; + x560_prevDamageAmt = (type == EWeaponType::AI && dam == 0.00002f) ? 10.f : dam; + x564_damageLocation = location; + x558_wasDamaged = true; + + bool doRumble = false; + u16 suitDamageSfx = 0, damageLoopSfx = 0, damageSamusVoiceSfx = 0; + + switch (type) { + case EWeaponType::Phazon: + case EWeaponType::OrangePhazon: + damageLoopSfx = SFXphz_damage_lp; + damageSamusVoiceSfx = SFXsam_vox_damage_phazon; + break; + case EWeaponType::PoisonWater: + damageLoopSfx = SFXsam_damage_poison_lp; + damageSamusVoiceSfx = SFXsam_vox_damage_poison; + break; + case EWeaponType::Lava: + damageLoopSfx = SFXpds_lava_damage_lp; + case EWeaponType::Heat: + damageSamusVoiceSfx = SFXsam_vox_damage_heat; + break; + default: + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) { + if (dam > 30.f) + damageSamusVoiceSfx = SFXsam_vox_damage30; + else if (dam > 15.f) + damageSamusVoiceSfx = SFXsam_vox_damage15; else - ret = CSteeringBehaviors::ProjectOrbitalPosition(ret, x138_velocity, x314_orbitPoint, dt, xa04_preThinkDt); + damageSamusVoiceSfx = SFXsam_vox_damage; + suitDamageSfx = SFXsam_suit_damage; + } else { + if (dam > 30.f) + suitDamageSfx = SFXsam_ball_damage30; + else if (dam > 15.f) + suitDamageSfx = SFXsam_ball_damage15; + else + suitDamageSfx = SFXsam_ball_damage; + } + break; } - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - ret.z() += g_tweakPlayer->GetPlayerBallHalfExtent(); - else - ret.z() += GetEyeHeight(); + if (damageSamusVoiceSfx && x774_samusVoiceTimeout <= 0.f) { + StartSamusVoiceSfx(damageSamusVoiceSfx, 1.f, 8); + x774_samusVoiceTimeout = mgr.GetActiveRandom()->Range(3.f, 4.f); + doRumble = true; + } - return ret; + if (damageLoopSfx && !x9c7_24_noDamageLoopSfx && xa2c_damageLoopSfxDelayTicks >= 2) { + if (!x770_damageLoopSfx || x788_damageLoopSfxId != damageLoopSfx) { + if (x770_damageLoopSfx && x788_damageLoopSfxId != damageLoopSfx) + CSfxManager::SfxStop(x770_damageLoopSfx); + x770_damageLoopSfx = CSfxManager::SfxStart(damageLoopSfx, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + x788_damageLoopSfxId = damageLoopSfx; + } + x784_damageSfxTimer = 0.5f; + } + + if (suitDamageSfx) { + if (x770_damageLoopSfx) { + CSfxManager::SfxStop(x770_damageLoopSfx); + x770_damageLoopSfx.reset(); + } + x770_damageLoopSfx = CSfxManager::SfxStart(suitDamageSfx, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + x788_damageLoopSfxId = suitDamageSfx; + xa2c_damageLoopSfxDelayTicks = 0; + doRumble = true; + } + + if (doRumble) { + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) + x490_gun->DamageRumble(location, dam, mgr); + float tmp = x55c_damageAmt / 25.f; + if (std::fabs(tmp) > 1.f) + tmp = tmp > 0.f ? 1.f : -1.f; + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerBump, tmp, ERumblePriority::One); + } + + if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) { + x768_morphball->TakeDamage(x55c_damageAmt); + x768_morphball->SetDamageTimer(0.4f); + } + } + + if (x3b8_grappleState != EGrappleState::None) + BreakGrapple(EPlayerOrbitRequest::DamageOnGrapple, mgr); } -void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager& mgr) -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - x768_morphball->FluidFXThink(state, water, mgr); - if (state == EFluidState::InFluid) - x9c5_30_selectFluidBallSound = true; - } - else if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) - { - if (mgr.GetFluidPlaneManager()->GetLastSplashDeltaTime(x8_uid) >= 0.2f) - { - zeus::CVector3f position(x34_transform.origin); - position.z() = float(water.GetTriggerBoundsWR().max.z()); - mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.1f, - state == EFluidState::EnteredFluid); - } - } - else - { - if (mgr.GetFluidPlaneManager()->GetLastSplashDeltaTime(x8_uid) >= 0.2f) - { - zeus::CVector3f posOffset = x50c_moveDir; - if (posOffset.canBeNormalized()) - posOffset = posOffset.normalized() * zeus::CVector3f(1.2f, 1.2f, 0.f); - switch (state) - { - case EFluidState::EnteredFluid: - { - bool doSplash = true; - if (x4fc_flatMoveSpeed > 12.5f) - { - zeus::CVector3f lookDir = x34_transform.basis[1].normalized(); - zeus::CVector3f dcVel = GetDampedClampedVelocityWR(); - dcVel.z() = 0.f; - if (lookDir.dot(dcVel.normalized()) > 0.75f) - doSplash = false; - } - if (doSplash) - { - zeus::CVector3f position = x34_transform.origin + posOffset; - position.z() = float(water.GetTriggerBoundsWR().max.z()); - mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.3f, true); - if (water.GetFluidPlane().GetFluidType() == EFluidType::NormalWater) - { - float velMag = mgr.GetPlayer().GetVelocity().magnitude() / 10.f; - mgr.GetEnvFxManager()->SetSplashRate(10.f * std::max(1.f, velMag)); - } - } - break; - } - case EFluidState::InFluid: - { - if (x138_velocity.magnitude() > 1.f && - mgr.GetFluidPlaneManager()->GetLastRippleDeltaTime(x8_uid) >= 0.2f) - { - zeus::CVector3f position(x34_transform.origin); - position.z() = float(water.GetTriggerBoundsWR().max.z()); - water.GetFluidPlane().AddRipple(0.5f, x8_uid, position, water, mgr); - } - break; - } - case EFluidState::LeftFluid: - { - zeus::CVector3f position = x34_transform.origin + posOffset; - position.z() = float(water.GetTriggerBoundsWR().max.z()); - mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.15f, true); - break; - } - default: break; - } - } - } -} - -void CPlayer::TakeDamage(bool significant, const zeus::CVector3f& location, - float dam, EWeaponType type, CStateManager& mgr) -{ - if (!significant) - return; - if (dam >= 0.f) - { - x570_immuneTimer = 0.5f; - x55c_damageAmt = dam; - x560_prevDamageAmt = (type == EWeaponType::AI && dam == 0.00002f) ? 10.f : dam; - x564_damageLocation = location; - x558_wasDamaged = true; - - bool doRumble = false; - u16 suitDamageSfx = 0, damageLoopSfx = 0, damageSamusVoiceSfx = 0; - - switch (type) - { - case EWeaponType::Phazon: - case EWeaponType::OrangePhazon: - damageLoopSfx = SFXphz_damage_lp; - damageSamusVoiceSfx = SFXsam_vox_damage_phazon; - break; - case EWeaponType::PoisonWater: - damageLoopSfx = SFXsam_damage_poison_lp; - damageSamusVoiceSfx = SFXsam_vox_damage_poison; - break; - case EWeaponType::Lava: - damageLoopSfx = SFXpds_lava_damage_lp; - case EWeaponType::Heat: - damageSamusVoiceSfx = SFXsam_vox_damage_heat; - break; - default: - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) - { - if (dam > 30.f) - damageSamusVoiceSfx = SFXsam_vox_damage30; - else if (dam > 15.f) - damageSamusVoiceSfx = SFXsam_vox_damage15; - else - damageSamusVoiceSfx = SFXsam_vox_damage; - suitDamageSfx = SFXsam_suit_damage; - } - else - { - if (dam > 30.f) - suitDamageSfx = SFXsam_ball_damage30; - else if (dam > 15.f) - suitDamageSfx = SFXsam_ball_damage15; - else - suitDamageSfx = SFXsam_ball_damage; - } - break; - } - - if (damageSamusVoiceSfx && x774_samusVoiceTimeout <= 0.f) - { - StartSamusVoiceSfx(damageSamusVoiceSfx, 1.f, 8); - x774_samusVoiceTimeout = mgr.GetActiveRandom()->Range(3.f, 4.f); - doRumble = true; - } - - if (damageLoopSfx && !x9c7_24_noDamageLoopSfx && xa2c_damageLoopSfxDelayTicks >= 2) - { - if (!x770_damageLoopSfx || x788_damageLoopSfxId != damageLoopSfx) - { - if (x770_damageLoopSfx && x788_damageLoopSfxId != damageLoopSfx) - CSfxManager::SfxStop(x770_damageLoopSfx); - x770_damageLoopSfx = CSfxManager::SfxStart(damageLoopSfx, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); - x788_damageLoopSfxId = damageLoopSfx; - } - x784_damageSfxTimer = 0.5f; - } - - if (suitDamageSfx) - { - if (x770_damageLoopSfx) - { - CSfxManager::SfxStop(x770_damageLoopSfx); - x770_damageLoopSfx.reset(); - } - x770_damageLoopSfx = CSfxManager::SfxStart(suitDamageSfx, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); - x788_damageLoopSfxId = suitDamageSfx; - xa2c_damageLoopSfxDelayTicks = 0; - doRumble = true; - } - - if (doRumble) - { - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) - x490_gun->DamageRumble(location, dam, mgr); - float tmp = x55c_damageAmt / 25.f; - if (std::fabs(tmp) > 1.f) - tmp = tmp > 0.f ? 1.f : -1.f; - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerBump, tmp, ERumblePriority::One); - } - - if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) - { - x768_morphball->TakeDamage(x55c_damageAmt); - x768_morphball->SetDamageTimer(0.4f); - } - } - - if (x3b8_grappleState != EGrappleState::None) - BreakGrapple(EPlayerOrbitRequest::DamageOnGrapple, mgr); -} - -void CPlayer::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CPlayer::Accept(IVisitor& visitor) { visitor.Visit(this); } CHealthInfo* CPlayer::HealthInfo(CStateManager& mgr) { return &mgr.GetPlayerState()->HealthInfo(); } -bool CPlayer::IsUnderBetaMetroidAttack(CStateManager& mgr) const -{ - if (x274_energyDrain.GetEnergyDrainIntensity() > 0.f) - { - for (const CEnergyDrainSource& source : x274_energyDrain.GetEnergyDrainSources()) - if (CPatterned::CastTo(mgr.GetObjectById(source.GetEnergyDrainSourceId()))) - return true; - } - return false; -} - -std::experimental::optional CPlayer::GetTouchBounds() const -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - float ballTouchRad = x768_morphball->GetBallTouchRadius(); - zeus::CVector3f ballCenter = - GetTranslation() + zeus::CVector3f(0.f, 0.f, x768_morphball->GetBallRadius()); - return zeus::CAABox(ballCenter - ballTouchRad, ballCenter + ballTouchRad); - } - return GetBoundingBox(); -} - -void CPlayer::DoPreThink(float dt, CStateManager& mgr) -{ - PreThink(dt, mgr); - if (CEntity* ent = mgr.ObjectById(xa00_deathPowerBomb)) - ent->PreThink(dt, mgr); -} - -void CPlayer::DoThink(float dt, CStateManager& mgr) -{ - Think(dt, mgr); - if (CEntity* ent = mgr.ObjectById(xa00_deathPowerBomb)) - ent->Think(dt, mgr); -} - -void CPlayer::UpdateScanningState(const CFinalInput& input, CStateManager& mgr, float dt) -{ - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - { - SetScanningState(EPlayerScanState::NotScanning, mgr); - return; - } - - if (x3a8_scanState != EPlayerScanState::NotScanning && x3b4_scanningObject != x310_orbitTargetId && - x310_orbitTargetId != kInvalidUniqueId) - SetScanningState(EPlayerScanState::NotScanning, mgr); - - switch (x3a8_scanState) - { - case EPlayerScanState::NotScanning: - if (ValidateScanning(input, mgr)) - { - if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) - { - const CScannableObjectInfo* scanInfo = act->GetScannableObjectInfo(); - float scanTime = mgr.GetPlayerState()->GetScanTime(scanInfo->GetScannableObjectId()); - if (scanTime >= 1.f) - { - x9c6_30_newScanScanning = false; - scanTime = 1.f; - } - else - { - x9c6_30_newScanScanning = true; - } - - SetScanningState(EPlayerScanState::Scanning, mgr); - x3ac_scanningTime = scanTime * scanInfo->GetTotalDownloadTime(); - x3b0_curScanTime = 0.f; - } - } - break; - case EPlayerScanState::Scanning: - if (ValidateScanning(input, mgr)) - { - if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) - { - if (const CScannableObjectInfo* scanInfo = act->GetScannableObjectInfo()) - { - x3ac_scanningTime = std::min(scanInfo->GetTotalDownloadTime(), x3ac_scanningTime + dt); - x3b0_curScanTime += dt; - mgr.GetPlayerState()->SetScanTime(scanInfo->GetScannableObjectId(), - x3ac_scanningTime / scanInfo->GetTotalDownloadTime()); - if (x3ac_scanningTime >= scanInfo->GetTotalDownloadTime() && - x3b0_curScanTime >= g_tweakGui->GetScanSidesStartTime()) - SetScanningState(EPlayerScanState::ScanComplete, mgr); - } - } - else - { - SetScanningState(EPlayerScanState::NotScanning, mgr); - } - } - else - { - SetScanningState(EPlayerScanState::NotScanning, mgr); - } - break; - case EPlayerScanState::ScanComplete: - if (!ValidateScanning(input, mgr)) - SetScanningState(EPlayerScanState::NotScanning, mgr); - break; - } -} - -bool CPlayer::ValidateScanning(const CFinalInput& input, CStateManager& mgr) -{ - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::ScanItem, input)) - { - if (x304_orbitState == EPlayerOrbitState::OrbitObject) - { - if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) - { - if (act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) - { - zeus::CVector3f targetToPlayer = GetTranslation() - act->GetTranslation(); - if (targetToPlayer.canBeNormalized() && - targetToPlayer.magnitude() < g_tweakPlayer->GetScanningRange()) - return true; - } - } - } - } - - return false; -} - -static bool IsDataLoreResearchScan(CAssetId id) -{ - auto it = g_MemoryCardSys->LookupScanState(id); - if (it == g_MemoryCardSys->GetScanStates().cend()) - return false; - switch (it->second) - { - case CSaveWorld::EScanCategory::Data: - case CSaveWorld::EScanCategory::Lore: - case CSaveWorld::EScanCategory::Research: +bool CPlayer::IsUnderBetaMetroidAttack(CStateManager& mgr) const { + if (x274_energyDrain.GetEnergyDrainIntensity() > 0.f) { + for (const CEnergyDrainSource& source : x274_energyDrain.GetEnergyDrainSources()) + if (CPatterned::CastTo(mgr.GetObjectById(source.GetEnergyDrainSourceId()))) return true; - default: - return false; - } + } + return false; } -static const char* UnlockMessageResBases[] = -{ - "STRG_SlideShow_Unlock1_", - "STRG_SlideShow_Unlock2_" -}; - -static CAssetId UpdatePersistentScanPercent(u32 prevLogScans, u32 logScans, u32 totalLogScans) -{ - if (prevLogScans == logScans) - return {}; - - float scanPercent = logScans / float(totalLogScans) * 100.f; - float prevScanPercent = prevLogScans / float(totalLogScans) * 100.f; - float scanMessageInterval = g_tweakSlideShow->GetScanPercentInterval(); - auto scanPercentProgStep = int(scanPercent / scanMessageInterval); - auto prevScanPercentProgStep = int(prevScanPercent / scanMessageInterval); - bool firstTime = scanPercent > g_GameState->SystemOptions().GetLogScanPercent(); - - if (firstTime) - g_GameState->SystemOptions().SetLogScanPercent(u32(scanPercent)); - - if (scanPercentProgStep > prevScanPercentProgStep) - { - auto message = - std::string(UnlockMessageResBases[zeus::clamp(0, scanPercentProgStep - 1, 1)]) + (firstTime ? '1' : '2'); - auto id = g_ResFactory->GetResourceIdByName(message.c_str()); - if (id != nullptr) - return id->id; - } - - return {}; +std::experimental::optional CPlayer::GetTouchBounds() const { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + float ballTouchRad = x768_morphball->GetBallTouchRadius(); + zeus::CVector3f ballCenter = GetTranslation() + zeus::CVector3f(0.f, 0.f, x768_morphball->GetBallRadius()); + return zeus::CAABox(ballCenter - ballTouchRad, ballCenter + ballTouchRad); + } + return GetBoundingBox(); } -void CPlayer::FinishNewScan(CStateManager& mgr) -{ - if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) - if (act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) - if (auto scanInfo = act->GetScannableObjectInfo()) - if (mgr.GetPlayerState()->GetScanTime(scanInfo->GetScannableObjectId()) >= 1.f) - if (IsDataLoreResearchScan(scanInfo->GetScannableObjectId())) - { - auto scanCompletion = mgr.CalculateScanCompletionRate(); - CAssetId message = UpdatePersistentScanPercent(mgr.GetPlayerState()->GetLogScans(), - scanCompletion.first, scanCompletion.second); - if (message.IsValid()) - mgr.ShowPausedHUDMemo(message, 0.f); - mgr.GetPlayerState()->SetScanCompletionRate(scanCompletion); - } +void CPlayer::DoPreThink(float dt, CStateManager& mgr) { + PreThink(dt, mgr); + if (CEntity* ent = mgr.ObjectById(xa00_deathPowerBomb)) + ent->PreThink(dt, mgr); } -void CPlayer::SetScanningState(EPlayerScanState state, CStateManager& mgr) -{ - if (x3a8_scanState == state) - return; +void CPlayer::DoThink(float dt, CStateManager& mgr) { + Think(dt, mgr); + if (CEntity* ent = mgr.ObjectById(xa00_deathPowerBomb)) + ent->Think(dt, mgr); +} - mgr.SetGameState(CStateManager::EGameState::Running); - if (x3a8_scanState == EPlayerScanState::ScanComplete) - if (TCastToPtr act = mgr.ObjectById(x3b4_scanningObject)) - act->OnScanStateChanged(EScanState::Done, mgr); +void CPlayer::UpdateScanningState(const CFinalInput& input, CStateManager& mgr, float dt) { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) { + SetScanningState(EPlayerScanState::NotScanning, mgr); + return; + } - switch (state) - { - case EPlayerScanState::NotScanning: - if (x3a8_scanState == EPlayerScanState::Scanning || x3a8_scanState == EPlayerScanState::ScanComplete) - if (x9c6_30_newScanScanning) - FinishNewScan(mgr); - x3ac_scanningTime = 0.f; + if (x3a8_scanState != EPlayerScanState::NotScanning && x3b4_scanningObject != x310_orbitTargetId && + x310_orbitTargetId != kInvalidUniqueId) + SetScanningState(EPlayerScanState::NotScanning, mgr); + + switch (x3a8_scanState) { + case EPlayerScanState::NotScanning: + if (ValidateScanning(input, mgr)) { + if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) { + const CScannableObjectInfo* scanInfo = act->GetScannableObjectInfo(); + float scanTime = mgr.GetPlayerState()->GetScanTime(scanInfo->GetScannableObjectId()); + if (scanTime >= 1.f) { + x9c6_30_newScanScanning = false; + scanTime = 1.f; + } else { + x9c6_30_newScanScanning = true; + } + + SetScanningState(EPlayerScanState::Scanning, mgr); + x3ac_scanningTime = scanTime * scanInfo->GetTotalDownloadTime(); x3b0_curScanTime = 0.f; - if (!g_tweakPlayer->GetScanRetention()) - if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) - if (act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) - if (auto scanInfo = act->GetScannableObjectInfo()) - if (mgr.GetPlayerState()->GetScanTime(scanInfo->GetScannableObjectId()) < 1.f) - mgr.GetPlayerState()->SetScanTime(scanInfo->GetScannableObjectId(), 0.f); - x3b4_scanningObject = kInvalidUniqueId; - break; - case EPlayerScanState::Scanning: - x3b4_scanningObject = x310_orbitTargetId; - break; - case EPlayerScanState::ScanComplete: - if (g_tweakPlayer->GetScanFreezesGame()) - mgr.SetGameState(CStateManager::EGameState::SoftPaused); - x3b4_scanningObject = x310_orbitTargetId; - break; + } } - - x3a8_scanState = state; -} - -bool CPlayer::GetExplorationMode() const -{ - switch (x498_gunHolsterState) - { - case EGunHolsterState::Holstering: - case EGunHolsterState::Holstered: - return true; - default: - return false; - } -} - -bool CPlayer::GetCombatMode() const -{ - switch (x498_gunHolsterState) - { - case EGunHolsterState::Drawing: - case EGunHolsterState::Drawn: - return true; - default: - return false; - } -} - -void CPlayer::RenderGun(const CStateManager& mgr, const zeus::CVector3f& pos) const -{ - if (mgr.GetCameraManager()->IsInCinematicCamera()) - return; - - if (x490_gun->GetGrappleArm().GetActive() && - x490_gun->GetGrappleArm().GetAnimState() != CGrappleArm::EArmState::Done) - x490_gun->GetGrappleArm().RenderGrappleBeam(mgr, pos); - - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Scan && - mgr.GetPlayerState()->GetVisorTransitionFactor() >= 1.f) - return; - - if ((mgr.GetCameraManager()->IsInFirstPersonCamera() && x2f4_cameraState == EPlayerCameraState::FirstPerson) || - (x2f8_morphBallState == EPlayerMorphBallState::Morphing && - x498_gunHolsterState == EGunHolsterState::Holstering)) - { - CModelFlags flags(5, 0, 3, zeus::CColor(1.f, x494_gunAlpha)); - x490_gun->Render(mgr, pos, flags); - } -} - -void CPlayer::Render(const CStateManager& mgr) const -{ - bool doRender = x2f4_cameraState != EPlayerCameraState::Spawned; - if (!doRender) - if (TCastToConstPtr cam = mgr.GetCameraManager()->GetCurrentCamera(mgr)) - doRender = (x2f8_morphBallState == EPlayerMorphBallState::Morphed && cam->GetFlags() & 0x40); - if (x2f4_cameraState != EPlayerCameraState::FirstPerson && doRender) - { - bool doTransitionRender = false; - bool doBallRender = false; - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Unmorphed: - x64_modelData->Touch(mgr, 0); - CPhysicsActor::Render(mgr); - if (HasTransitionBeamModel()) - { - x7f0_ballTransitionBeamModel->Touch(mgr, 0); - CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); - x7f0_ballTransitionBeamModel->Render(mgr, x7f4_gunWorldXf, x90_actorLights.get(), flags); - } - break; - case EPlayerMorphBallState::Morphing: - x768_morphball->TouchModel(mgr); - doTransitionRender = true; - doBallRender = true; - break; - case EPlayerMorphBallState::Unmorphing: - x490_gun->TouchModel(mgr); - doTransitionRender = true; - doBallRender = true; - break; - case EPlayerMorphBallState::Morphed: - x64_modelData->Touch(mgr, 0); - x768_morphball->Render(mgr, x90_actorLights.get()); - break; - } - - if (doTransitionRender) - { - CPhysicsActor::Render(mgr); - if (HasTransitionBeamModel()) - { - CModelFlags flags(5, 0, 3, zeus::CColor(1.f, x588_alpha)); - x7f0_ballTransitionBeamModel->Render(CModelData::EWhichModel::Normal, - x7f4_gunWorldXf, x90_actorLights.get(), flags); - } - - float morphFactor = x574_morphTime / x578_morphDuration; - float transitionAlpha; - if (morphFactor < 0.05f) - transitionAlpha = 0.f; - else if (morphFactor < 0.1f) - transitionAlpha = (morphFactor - 0.05f) / 0.05f; - else if (morphFactor < 0.8f) - transitionAlpha = 1.f; - else - transitionAlpha = 1.f - (morphFactor - 0.8f) / 0.2f; - - auto mdsp1 = int(x730_transitionModels.size() + 1); - for (int i=0 ; iRender(CModelData::EWhichModel::Normal, - *x594_transisionBeamXfs.GetEntry(ni), - x90_actorLights.get(), flags); - } - } - } - - if (doBallRender) - { - float morphFactor = x574_morphTime / x578_morphDuration; - float ballAlphaStart = 0.75f; - float ballAlphaMag = 4.f; - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphing) - { - ballAlphaStart = 0.875f; - morphFactor = 1.f - morphFactor; - ballAlphaMag = 8.f; - } - - if (morphFactor > ballAlphaStart) - { - CModelFlags flags(5, u8(x768_morphball->GetMorphballModelShader()), 3, - zeus::CColor(1.f, ballAlphaMag * (morphFactor - ballAlphaStart))); - x768_morphball->GetMorphballModelData().Render(mgr, x768_morphball->GetBallToWorld(), - x90_actorLights.get(), flags); - } - - if (x2f8_morphBallState == EPlayerMorphBallState::Morphing) - { - if (morphFactor > 0.5f) - { - float tmp = (morphFactor - 0.5f) / 0.5f; - float rotate = 1.f - tmp; - float scale = 0.75f * rotate + 1.f; - float ballAlpha; - if (tmp < 0.1f) - ballAlpha = 0.f; - else if (tmp < 0.2f) - ballAlpha = (tmp - 0.1f) / 0.1f; - else if (tmp < 0.9f) - ballAlpha = 1.f; - else - ballAlpha = 1.f - (morphFactor - 0.9f) / 0.1f; - - float theta = zeus::degToRad(360.f * rotate); - ballAlpha *= 0.5f; - if (ballAlpha > 0.f) - { - CModelFlags flags(7, 0, 3, zeus::CColor(1.f, ballAlpha)); - x768_morphball->GetMorphballModelData().Render(mgr, x768_morphball->GetBallToWorld() * - zeus::CTransform::RotateZ(theta) * zeus::CTransform::Scale(scale), - x90_actorLights.get(), flags); - } - } - x768_morphball->RenderMorphBallTransitionFlash(mgr); - } - } + break; + case EPlayerScanState::Scanning: + if (ValidateScanning(input, mgr)) { + if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) { + if (const CScannableObjectInfo* scanInfo = act->GetScannableObjectInfo()) { + x3ac_scanningTime = std::min(scanInfo->GetTotalDownloadTime(), x3ac_scanningTime + dt); + x3b0_curScanTime += dt; + mgr.GetPlayerState()->SetScanTime(scanInfo->GetScannableObjectId(), + x3ac_scanningTime / scanInfo->GetTotalDownloadTime()); + if (x3ac_scanningTime >= scanInfo->GetTotalDownloadTime() && + x3b0_curScanTime >= g_tweakGui->GetScanSidesStartTime()) + SetScanningState(EPlayerScanState::ScanComplete, mgr); } + } else { + SetScanningState(EPlayerScanState::NotScanning, mgr); + } + } else { + SetScanningState(EPlayerScanState::NotScanning, mgr); } + break; + case EPlayerScanState::ScanComplete: + if (!ValidateScanning(input, mgr)) + SetScanningState(EPlayerScanState::NotScanning, mgr); + break; + } } -void CPlayer::RenderReflectedPlayer(CStateManager& mgr) -{ - zeus::CFrustum frustum; - switch (x2f8_morphBallState) - { +bool CPlayer::ValidateScanning(const CFinalInput& input, CStateManager& mgr) { + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::ScanItem, input)) { + if (x304_orbitState == EPlayerOrbitState::OrbitObject) { + if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) { + if (act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) { + zeus::CVector3f targetToPlayer = GetTranslation() - act->GetTranslation(); + if (targetToPlayer.canBeNormalized() && targetToPlayer.magnitude() < g_tweakPlayer->GetScanningRange()) + return true; + } + } + } + } + + return false; +} + +static bool IsDataLoreResearchScan(CAssetId id) { + auto it = g_MemoryCardSys->LookupScanState(id); + if (it == g_MemoryCardSys->GetScanStates().cend()) + return false; + switch (it->second) { + case CSaveWorld::EScanCategory::Data: + case CSaveWorld::EScanCategory::Lore: + case CSaveWorld::EScanCategory::Research: + return true; + default: + return false; + } +} + +static const char* UnlockMessageResBases[] = {"STRG_SlideShow_Unlock1_", "STRG_SlideShow_Unlock2_"}; + +static CAssetId UpdatePersistentScanPercent(u32 prevLogScans, u32 logScans, u32 totalLogScans) { + if (prevLogScans == logScans) + return {}; + + float scanPercent = logScans / float(totalLogScans) * 100.f; + float prevScanPercent = prevLogScans / float(totalLogScans) * 100.f; + float scanMessageInterval = g_tweakSlideShow->GetScanPercentInterval(); + auto scanPercentProgStep = int(scanPercent / scanMessageInterval); + auto prevScanPercentProgStep = int(prevScanPercent / scanMessageInterval); + bool firstTime = scanPercent > g_GameState->SystemOptions().GetLogScanPercent(); + + if (firstTime) + g_GameState->SystemOptions().SetLogScanPercent(u32(scanPercent)); + + if (scanPercentProgStep > prevScanPercentProgStep) { + auto message = + std::string(UnlockMessageResBases[zeus::clamp(0, scanPercentProgStep - 1, 1)]) + (firstTime ? '1' : '2'); + auto id = g_ResFactory->GetResourceIdByName(message.c_str()); + if (id != nullptr) + return id->id; + } + + return {}; +} + +void CPlayer::FinishNewScan(CStateManager& mgr) { + if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) + if (act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) + if (auto scanInfo = act->GetScannableObjectInfo()) + if (mgr.GetPlayerState()->GetScanTime(scanInfo->GetScannableObjectId()) >= 1.f) + if (IsDataLoreResearchScan(scanInfo->GetScannableObjectId())) { + auto scanCompletion = mgr.CalculateScanCompletionRate(); + CAssetId message = UpdatePersistentScanPercent(mgr.GetPlayerState()->GetLogScans(), scanCompletion.first, + scanCompletion.second); + if (message.IsValid()) + mgr.ShowPausedHUDMemo(message, 0.f); + mgr.GetPlayerState()->SetScanCompletionRate(scanCompletion); + } +} + +void CPlayer::SetScanningState(EPlayerScanState state, CStateManager& mgr) { + if (x3a8_scanState == state) + return; + + mgr.SetGameState(CStateManager::EGameState::Running); + if (x3a8_scanState == EPlayerScanState::ScanComplete) + if (TCastToPtr act = mgr.ObjectById(x3b4_scanningObject)) + act->OnScanStateChanged(EScanState::Done, mgr); + + switch (state) { + case EPlayerScanState::NotScanning: + if (x3a8_scanState == EPlayerScanState::Scanning || x3a8_scanState == EPlayerScanState::ScanComplete) + if (x9c6_30_newScanScanning) + FinishNewScan(mgr); + x3ac_scanningTime = 0.f; + x3b0_curScanTime = 0.f; + if (!g_tweakPlayer->GetScanRetention()) + if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) + if (act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) + if (auto scanInfo = act->GetScannableObjectInfo()) + if (mgr.GetPlayerState()->GetScanTime(scanInfo->GetScannableObjectId()) < 1.f) + mgr.GetPlayerState()->SetScanTime(scanInfo->GetScannableObjectId(), 0.f); + x3b4_scanningObject = kInvalidUniqueId; + break; + case EPlayerScanState::Scanning: + x3b4_scanningObject = x310_orbitTargetId; + break; + case EPlayerScanState::ScanComplete: + if (g_tweakPlayer->GetScanFreezesGame()) + mgr.SetGameState(CStateManager::EGameState::SoftPaused); + x3b4_scanningObject = x310_orbitTargetId; + break; + } + + x3a8_scanState = state; +} + +bool CPlayer::GetExplorationMode() const { + switch (x498_gunHolsterState) { + case EGunHolsterState::Holstering: + case EGunHolsterState::Holstered: + return true; + default: + return false; + } +} + +bool CPlayer::GetCombatMode() const { + switch (x498_gunHolsterState) { + case EGunHolsterState::Drawing: + case EGunHolsterState::Drawn: + return true; + default: + return false; + } +} + +void CPlayer::RenderGun(const CStateManager& mgr, const zeus::CVector3f& pos) const { + if (mgr.GetCameraManager()->IsInCinematicCamera()) + return; + + if (x490_gun->GetGrappleArm().GetActive() && x490_gun->GetGrappleArm().GetAnimState() != CGrappleArm::EArmState::Done) + x490_gun->GetGrappleArm().RenderGrappleBeam(mgr, pos); + + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Scan && + mgr.GetPlayerState()->GetVisorTransitionFactor() >= 1.f) + return; + + if ((mgr.GetCameraManager()->IsInFirstPersonCamera() && x2f4_cameraState == EPlayerCameraState::FirstPerson) || + (x2f8_morphBallState == EPlayerMorphBallState::Morphing && + x498_gunHolsterState == EGunHolsterState::Holstering)) { + CModelFlags flags(5, 0, 3, zeus::CColor(1.f, x494_gunAlpha)); + x490_gun->Render(mgr, pos, flags); + } +} + +void CPlayer::Render(const CStateManager& mgr) const { + bool doRender = x2f4_cameraState != EPlayerCameraState::Spawned; + if (!doRender) + if (TCastToConstPtr cam = mgr.GetCameraManager()->GetCurrentCamera(mgr)) + doRender = (x2f8_morphBallState == EPlayerMorphBallState::Morphed && cam->GetFlags() & 0x40); + if (x2f4_cameraState != EPlayerCameraState::FirstPerson && doRender) { + bool doTransitionRender = false; + bool doBallRender = false; + switch (x2f8_morphBallState) { case EPlayerMorphBallState::Unmorphed: + x64_modelData->Touch(mgr, 0); + CPhysicsActor::Render(mgr); + if (HasTransitionBeamModel()) { + x7f0_ballTransitionBeamModel->Touch(mgr, 0); + CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + x7f0_ballTransitionBeamModel->Render(mgr, x7f4_gunWorldXf, x90_actorLights.get(), flags); + } + break; case EPlayerMorphBallState::Morphing: + x768_morphball->TouchModel(mgr); + doTransitionRender = true; + doBallRender = true; + break; case EPlayerMorphBallState::Unmorphing: - SetCalculateLighting(true); - if (x2f4_cameraState == EPlayerCameraState::FirstPerson) - CActor::PreRender(mgr, frustum); - CPhysicsActor::Render(mgr); - if (HasTransitionBeamModel()) - { - CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); - x7f0_ballTransitionBeamModel->Render(mgr, x7f4_gunWorldXf, nullptr, flags); - } - break; + x490_gun->TouchModel(mgr); + doTransitionRender = true; + doBallRender = true; + break; case EPlayerMorphBallState::Morphed: - x768_morphball->Render(mgr, x90_actorLights.get()); - break; + x64_modelData->Touch(mgr, 0); + x768_morphball->Render(mgr, x90_actorLights.get()); + break; } -} -void CPlayer::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - SetCalculateLighting(false); - x768_morphball->PreRender(mgr, frustum); - } - else - { - SetCalculateLighting(true); - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) - { - x490_gun->PreRender(mgr, frustum, - mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr)); + if (doTransitionRender) { + CPhysicsActor::Render(mgr); + if (HasTransitionBeamModel()) { + CModelFlags flags(5, 0, 3, zeus::CColor(1.f, x588_alpha)); + x7f0_ballTransitionBeamModel->Render(CModelData::EWhichModel::Normal, x7f4_gunWorldXf, x90_actorLights.get(), + flags); + } + + float morphFactor = x574_morphTime / x578_morphDuration; + float transitionAlpha; + if (morphFactor < 0.05f) + transitionAlpha = 0.f; + else if (morphFactor < 0.1f) + transitionAlpha = (morphFactor - 0.05f) / 0.05f; + else if (morphFactor < 0.8f) + transitionAlpha = 1.f; + else + transitionAlpha = 1.f - (morphFactor - 0.8f) / 0.2f; + + auto mdsp1 = int(x730_transitionModels.size() + 1); + for (int i = 0; i < x730_transitionModels.size(); ++i) { + int ni = i + 1; + float alpha = transitionAlpha * (1.f - (ni + 1) / float(mdsp1)) * *x71c_transitionModelAlphas.GetEntry(ni); + if (alpha != 0.f) { + CModelData& data = *x730_transitionModels[i]; + CModelFlags flags(5, 0, 3, zeus::CColor(1.f, alpha)); + data.Render(CModelData::GetRenderingModel(mgr), *x658_transitionModelXfs.GetEntry(ni), x90_actorLights.get(), + flags); + if (HasTransitionBeamModel()) { + CModelFlags flags(5, 0, 3, zeus::CColor(1.f, alpha)); + x7f0_ballTransitionBeamModel->Render(CModelData::EWhichModel::Normal, *x594_transisionBeamXfs.GetEntry(ni), + x90_actorLights.get(), flags); + } } - } + } - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed || - mgr.GetCameraManager()->IsInCinematicCamera()) - { - x768_morphball->DeleteBallShadow(); - } - else - { - x768_morphball->CreateBallShadow(); - x768_morphball->RenderToShadowTex(mgr); - } - - for (auto& model : x730_transitionModels) - model->AnimationData()->PreRender(); - - if (x2f4_cameraState != EPlayerCameraState::FirstPerson) - CActor::PreRender(mgr, frustum); -} - -void CPlayer::CalculateRenderBounds() -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - float rad = x768_morphball->GetBallRadius(); - x9c_renderBounds = zeus::CAABox(GetTranslation() - zeus::CVector3f(rad, rad, 0.f), - GetTranslation() + zeus::CVector3f(rad, rad, rad * 2.f)); - } - else - { - CActor::CalculateRenderBounds(); - } -} - -void CPlayer::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - if (x2f4_cameraState != EPlayerCameraState::FirstPerson && - x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - if (x768_morphball->IsInFrustum(frustum)) - CActor::AddToRenderer(frustum, mgr); - else - x768_morphball->TouchModel(mgr); - } - else - { - x490_gun->AddToRenderer(frustum, mgr); - CActor::AddToRenderer(frustum, mgr); - } -} - -void CPlayer::ComputeFreeLook(const CFinalInput& input) -{ - float lookLeft = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input); - float lookRight = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input); - float lookUp = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookUp, input); - float lookDown = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookDown, input); - - if (g_GameState->GameOptions().GetInvertYAxis()) - { - lookUp = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookDown, input); - lookDown = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookUp, input); - } - - if (!g_tweakPlayer->GetStayInFreeLookWhileFiring() && - (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) || - x304_orbitState != EPlayerOrbitState::NoOrbit)) - { - x3e8_horizFreeLookAngleVel = 0.f; - x3f0_vertFreeLookAngleVel = 0.f; - } - else - { - if (x3dc_inFreeLook) - { - x3e8_horizFreeLookAngleVel = (lookLeft - lookRight) * g_tweakPlayer->GetHorizontalFreeLookAngleVel(); - x3f0_vertFreeLookAngleVel = (lookUp - lookDown) * g_tweakPlayer->GetVerticalFreeLookAngleVel(); + if (doBallRender) { + float morphFactor = x574_morphTime / x578_morphDuration; + float ballAlphaStart = 0.75f; + float ballAlphaMag = 4.f; + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphing) { + ballAlphaStart = 0.875f; + morphFactor = 1.f - morphFactor; + ballAlphaMag = 8.f; } - if (!x3de_lookAnalogHeld || !x3dd_lookButtonHeld) - { - x3e8_horizFreeLookAngleVel = 0.f; - x3f0_vertFreeLookAngleVel = 0.f; + + if (morphFactor > ballAlphaStart) { + CModelFlags flags(5, u8(x768_morphball->GetMorphballModelShader()), 3, + zeus::CColor(1.f, ballAlphaMag * (morphFactor - ballAlphaStart))); + x768_morphball->GetMorphballModelData().Render(mgr, x768_morphball->GetBallToWorld(), x90_actorLights.get(), + flags); } - } - if (g_tweakPlayer->GetHoldButtonsForFreeLook()) - { - if ((g_tweakPlayer->GetTwoButtonsForFreeLook() && - (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold1, input) || - !ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold2, input))) || - (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold1, input) && - !ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold2, input))) - { - x3e8_horizFreeLookAngleVel = 0.f; - x3f0_vertFreeLookAngleVel = 0.f; - } - } - - if (IsMorphBallTransitioning()) - { - x3e8_horizFreeLookAngleVel = 0.f; - x3f0_vertFreeLookAngleVel = 0.f; - } -} - -void CPlayer::UpdateFreeLookState(const CFinalInput& input, float dt, CStateManager& mgr) -{ - if (x304_orbitState == EPlayerOrbitState::ForcedOrbitObject || IsMorphBallTransitioning() || - x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || - (x3b8_grappleState != EGrappleState::None && x3b8_grappleState != EGrappleState::Firing)) - { - x3dc_inFreeLook = false; - x3dd_lookButtonHeld = false; - x3de_lookAnalogHeld = false; - x3e8_horizFreeLookAngleVel = 0.f; - x3f0_vertFreeLookAngleVel = 0.f; - x9c4_25_showCrosshairs = false; - return; - } - - if (g_tweakPlayer->GetHoldButtonsForFreeLook()) - { - if ((g_tweakPlayer->GetTwoButtonsForFreeLook() && - (ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold1, input) && - ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold2, input))) || - (!g_tweakPlayer->GetTwoButtonsForFreeLook() && - (ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold1, input) || - ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold2, input)))) - { - if (!x3dd_lookButtonHeld) - { - zeus::CVector3f lookDir = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform().basis[1]; - zeus::CVector3f lookDirFlat = lookDir; - lookDirFlat.z() = 0.f; - x3e4_freeLookYawAngle = 0.f; - if (lookDirFlat.canBeNormalized()) - { - lookDirFlat.normalize(); - x3ec_freeLookPitchAngle = std::acos(zeus::clamp(-1.f, lookDirFlat.dot(lookDir), 1.f)); - if (lookDir.z() < 0.f) - x3ec_freeLookPitchAngle = -x3ec_freeLookPitchAngle; - } - } - x3dc_inFreeLook = true; - x3dd_lookButtonHeld = true; - - x3de_lookAnalogHeld = - (ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input) >= 0.1f || - ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input) >= 0.1f || - ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookDown, input) >= 0.1f || - ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookUp, input) >= 0.1f); - } - else - { - x3dc_inFreeLook = false; - x3dd_lookButtonHeld = false; - x3de_lookAnalogHeld = false; - x3e8_horizFreeLookAngleVel = 0.f; - x3f0_vertFreeLookAngleVel = 0.f; - } - } - else - { - x3de_lookAnalogHeld = - (ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input) >= 0.1f || - ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input) >= 0.1f || - ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookDown, input) >= 0.1f || - ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookUp, input) >= 0.1f); - x3dd_lookButtonHeld = false; - if (std::fabs(x3e4_freeLookYawAngle) < g_tweakPlayer->GetFreeLookCenteredThresholdAngle() && - std::fabs(x3ec_freeLookPitchAngle) < g_tweakPlayer->GetFreeLookCenteredThresholdAngle()) - { - if (x3e0_curFreeLookCenteredTime > g_tweakPlayer->GetFreeLookCenteredTime()) - { - x3dc_inFreeLook = false; - x3e8_horizFreeLookAngleVel = 0.f; - x3f0_vertFreeLookAngleVel = 0.f; - } + if (x2f8_morphBallState == EPlayerMorphBallState::Morphing) { + if (morphFactor > 0.5f) { + float tmp = (morphFactor - 0.5f) / 0.5f; + float rotate = 1.f - tmp; + float scale = 0.75f * rotate + 1.f; + float ballAlpha; + if (tmp < 0.1f) + ballAlpha = 0.f; + else if (tmp < 0.2f) + ballAlpha = (tmp - 0.1f) / 0.1f; + else if (tmp < 0.9f) + ballAlpha = 1.f; else - { - x3e0_curFreeLookCenteredTime += dt; - } - } - else - { - x3dc_inFreeLook = true; - x3e0_curFreeLookCenteredTime = 0.f; - } - } + ballAlpha = 1.f - (morphFactor - 0.9f) / 0.1f; - UpdateCrosshairsState(input); + float theta = zeus::degToRad(360.f * rotate); + ballAlpha *= 0.5f; + if (ballAlpha > 0.f) { + CModelFlags flags(7, 0, 3, zeus::CColor(1.f, ballAlpha)); + x768_morphball->GetMorphballModelData().Render( + mgr, + x768_morphball->GetBallToWorld() * zeus::CTransform::RotateZ(theta) * zeus::CTransform::Scale(scale), + x90_actorLights.get(), flags); + } + } + x768_morphball->RenderMorphBallTransitionFlash(mgr); + } + } + } + } } -void CPlayer::UpdateFreeLook(float dt) -{ - if (GetFrozenState()) - return; - float lookDeltaAngle = dt * g_tweakPlayer->GetFreeLookSpeed(); - if (!x3de_lookAnalogHeld) - lookDeltaAngle = dt * g_tweakPlayer->GetFreeLookSnapSpeed(); - float angleVelP = x3f0_vertFreeLookAngleVel - x3ec_freeLookPitchAngle; - float vertLookDamp = zeus::clamp(0.f, std::fabs(angleVelP / 1.0471976f), 1.f); - float dx = lookDeltaAngle * (2.f * vertLookDamp - std::sin((M_PIF / 2.f) * vertLookDamp)); - if (0.f <= angleVelP) - x3ec_freeLookPitchAngle += dx; +void CPlayer::RenderReflectedPlayer(CStateManager& mgr) { + zeus::CFrustum frustum; + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Unmorphed: + case EPlayerMorphBallState::Morphing: + case EPlayerMorphBallState::Unmorphing: + SetCalculateLighting(true); + if (x2f4_cameraState == EPlayerCameraState::FirstPerson) + CActor::PreRender(mgr, frustum); + CPhysicsActor::Render(mgr); + if (HasTransitionBeamModel()) { + CModelFlags flags(0, 0, 3, zeus::CColor::skWhite); + x7f0_ballTransitionBeamModel->Render(mgr, x7f4_gunWorldXf, nullptr, flags); + } + break; + case EPlayerMorphBallState::Morphed: + x768_morphball->Render(mgr, x90_actorLights.get()); + break; + } +} + +void CPlayer::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + SetCalculateLighting(false); + x768_morphball->PreRender(mgr, frustum); + } else { + SetCalculateLighting(true); + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) { + x490_gun->PreRender(mgr, frustum, mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr)); + } + } + + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed || mgr.GetCameraManager()->IsInCinematicCamera()) { + x768_morphball->DeleteBallShadow(); + } else { + x768_morphball->CreateBallShadow(); + x768_morphball->RenderToShadowTex(mgr); + } + + for (auto& model : x730_transitionModels) + model->AnimationData()->PreRender(); + + if (x2f4_cameraState != EPlayerCameraState::FirstPerson) + CActor::PreRender(mgr, frustum); +} + +void CPlayer::CalculateRenderBounds() { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + float rad = x768_morphball->GetBallRadius(); + x9c_renderBounds = zeus::CAABox(GetTranslation() - zeus::CVector3f(rad, rad, 0.f), + GetTranslation() + zeus::CVector3f(rad, rad, rad * 2.f)); + } else { + CActor::CalculateRenderBounds(); + } +} + +void CPlayer::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + if (x2f4_cameraState != EPlayerCameraState::FirstPerson && x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + if (x768_morphball->IsInFrustum(frustum)) + CActor::AddToRenderer(frustum, mgr); else - x3ec_freeLookPitchAngle -= dx; - angleVelP = x3e8_horizFreeLookAngleVel - x3e4_freeLookYawAngle; - dx = lookDeltaAngle * zeus::clamp(0.f, std::fabs(angleVelP / g_tweakPlayer->GetHorizontalFreeLookAngleVel()), 1.f); - if (0.f <= angleVelP) - x3e4_freeLookYawAngle += dx; - else - x3e4_freeLookYawAngle -= dx; - if (g_tweakPlayer->GetFreeLookTurnsPlayer()) + x768_morphball->TouchModel(mgr); + } else { + x490_gun->AddToRenderer(frustum, mgr); + CActor::AddToRenderer(frustum, mgr); + } +} + +void CPlayer::ComputeFreeLook(const CFinalInput& input) { + float lookLeft = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input); + float lookRight = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input); + float lookUp = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookUp, input); + float lookDown = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookDown, input); + + if (g_GameState->GameOptions().GetInvertYAxis()) { + lookUp = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookDown, input); + lookDown = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookUp, input); + } + + if (!g_tweakPlayer->GetStayInFreeLookWhileFiring() && + (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) || + x304_orbitState != EPlayerOrbitState::NoOrbit)) { + x3e8_horizFreeLookAngleVel = 0.f; + x3f0_vertFreeLookAngleVel = 0.f; + } else { + if (x3dc_inFreeLook) { + x3e8_horizFreeLookAngleVel = (lookLeft - lookRight) * g_tweakPlayer->GetHorizontalFreeLookAngleVel(); + x3f0_vertFreeLookAngleVel = (lookUp - lookDown) * g_tweakPlayer->GetVerticalFreeLookAngleVel(); + } + if (!x3de_lookAnalogHeld || !x3dd_lookButtonHeld) { + x3e8_horizFreeLookAngleVel = 0.f; + x3f0_vertFreeLookAngleVel = 0.f; + } + } + + if (g_tweakPlayer->GetHoldButtonsForFreeLook()) { + if ((g_tweakPlayer->GetTwoButtonsForFreeLook() && + (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold1, input) || + !ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold2, input))) || + (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold1, input) && + !ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold2, input))) { + x3e8_horizFreeLookAngleVel = 0.f; + x3f0_vertFreeLookAngleVel = 0.f; + } + } + + if (IsMorphBallTransitioning()) { + x3e8_horizFreeLookAngleVel = 0.f; + x3f0_vertFreeLookAngleVel = 0.f; + } +} + +void CPlayer::UpdateFreeLookState(const CFinalInput& input, float dt, CStateManager& mgr) { + if (x304_orbitState == EPlayerOrbitState::ForcedOrbitObject || IsMorphBallTransitioning() || + x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || + (x3b8_grappleState != EGrappleState::None && x3b8_grappleState != EGrappleState::Firing)) { + x3dc_inFreeLook = false; + x3dd_lookButtonHeld = false; + x3de_lookAnalogHeld = false; + x3e8_horizFreeLookAngleVel = 0.f; + x3f0_vertFreeLookAngleVel = 0.f; + x9c4_25_showCrosshairs = false; + return; + } + + if (g_tweakPlayer->GetHoldButtonsForFreeLook()) { + if ((g_tweakPlayer->GetTwoButtonsForFreeLook() && + (ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold1, input) && + ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold2, input))) || + (!g_tweakPlayer->GetTwoButtonsForFreeLook() && + (ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold1, input) || + ControlMapper::GetDigitalInput(ControlMapper::ECommands::LookHold2, input)))) { + if (!x3dd_lookButtonHeld) { + zeus::CVector3f lookDir = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform().basis[1]; + zeus::CVector3f lookDirFlat = lookDir; + lookDirFlat.z() = 0.f; x3e4_freeLookYawAngle = 0.f; -} + if (lookDirFlat.canBeNormalized()) { + lookDirFlat.normalize(); + x3ec_freeLookPitchAngle = std::acos(zeus::clamp(-1.f, lookDirFlat.dot(lookDir), 1.f)); + if (lookDir.z() < 0.f) + x3ec_freeLookPitchAngle = -x3ec_freeLookPitchAngle; + } + } + x3dc_inFreeLook = true; + x3dd_lookButtonHeld = true; -float CPlayer::GetMaximumPlayerPositiveVerticalVelocity(CStateManager& mgr) const -{ - return mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::SpaceJumpBoots) ? 14.f : 11.666666f; -} - -void CPlayer::StartLandingControlFreeze() -{ - x760_controlsFrozen = true; - x764_controlsFrozenTimeout = 0.75f; -} - -void CPlayer::EndLandingControlFreeze() -{ - x760_controlsFrozen = false; - x764_controlsFrozenTimeout = 0.f; -} - -void CPlayer::ProcessFrozenInput(float dt, CStateManager& mgr) -{ - x764_controlsFrozenTimeout -= dt; - if (x764_controlsFrozenTimeout <= 0.f) - { - EndLandingControlFreeze(); + x3de_lookAnalogHeld = (ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input) >= 0.1f || + ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input) >= 0.1f || + ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookDown, input) >= 0.1f || + ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookUp, input) >= 0.1f); + } else { + x3dc_inFreeLook = false; + x3dd_lookButtonHeld = false; + x3de_lookAnalogHeld = false; + x3e8_horizFreeLookAngleVel = 0.f; + x3f0_vertFreeLookAngleVel = 0.f; } - else - { - CFinalInput dummy; - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - x768_morphball->ComputeBallMovement(dummy, mgr, dt); - x768_morphball->UpdateBallDynamics(mgr, dt); - } - else - { - ComputeMovement(dummy, mgr, dt); - } + } else { + x3de_lookAnalogHeld = (ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input) >= 0.1f || + ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input) >= 0.1f || + ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookDown, input) >= 0.1f || + ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookUp, input) >= 0.1f); + x3dd_lookButtonHeld = false; + if (std::fabs(x3e4_freeLookYawAngle) < g_tweakPlayer->GetFreeLookCenteredThresholdAngle() && + std::fabs(x3ec_freeLookPitchAngle) < g_tweakPlayer->GetFreeLookCenteredThresholdAngle()) { + if (x3e0_curFreeLookCenteredTime > g_tweakPlayer->GetFreeLookCenteredTime()) { + x3dc_inFreeLook = false; + x3e8_horizFreeLookAngleVel = 0.f; + x3f0_vertFreeLookAngleVel = 0.f; + } else { + x3e0_curFreeLookCenteredTime += dt; + } + } else { + x3dc_inFreeLook = true; + x3e0_curFreeLookCenteredTime = 0.f; } + } + + UpdateCrosshairsState(input); } -void CPlayer::ProcessInput(const CFinalInput& input, CStateManager& mgr) -{ - if (input.ControllerIdx() != 0) - return; +void CPlayer::UpdateFreeLook(float dt) { + if (GetFrozenState()) + return; + float lookDeltaAngle = dt * g_tweakPlayer->GetFreeLookSpeed(); + if (!x3de_lookAnalogHeld) + lookDeltaAngle = dt * g_tweakPlayer->GetFreeLookSnapSpeed(); + float angleVelP = x3f0_vertFreeLookAngleVel - x3ec_freeLookPitchAngle; + float vertLookDamp = zeus::clamp(0.f, std::fabs(angleVelP / 1.0471976f), 1.f); + float dx = lookDeltaAngle * (2.f * vertLookDamp - std::sin((M_PIF / 2.f) * vertLookDamp)); + if (0.f <= angleVelP) + x3ec_freeLookPitchAngle += dx; + else + x3ec_freeLookPitchAngle -= dx; + angleVelP = x3e8_horizFreeLookAngleVel - x3e4_freeLookYawAngle; + dx = lookDeltaAngle * zeus::clamp(0.f, std::fabs(angleVelP / g_tweakPlayer->GetHorizontalFreeLookAngleVel()), 1.f); + if (0.f <= angleVelP) + x3e4_freeLookYawAngle += dx; + else + x3e4_freeLookYawAngle -= dx; + if (g_tweakPlayer->GetFreeLookTurnsPlayer()) + x3e4_freeLookYawAngle = 0.f; +} - if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) - UpdateScanningState(input, mgr, input.DeltaTime()); +float CPlayer::GetMaximumPlayerPositiveVerticalVelocity(CStateManager& mgr) const { + return mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::SpaceJumpBoots) ? 14.f : 11.666666f; +} - if (mgr.GetGameState() != CStateManager::EGameState::Running) - return; +void CPlayer::StartLandingControlFreeze() { + x760_controlsFrozen = true; + x764_controlsFrozenTimeout = 0.75f; +} - if (!mgr.GetPlayerState()->IsPlayerAlive()) - return; +void CPlayer::EndLandingControlFreeze() { + x760_controlsFrozen = false; + x764_controlsFrozenTimeout = 0.f; +} - if (GetFrozenState()) - UpdateFrozenState(input, mgr); +void CPlayer::ProcessFrozenInput(float dt, CStateManager& mgr) { + x764_controlsFrozenTimeout -= dt; + if (x764_controlsFrozenTimeout <= 0.f) { + EndLandingControlFreeze(); + } else { + CFinalInput dummy; + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + x768_morphball->ComputeBallMovement(dummy, mgr, dt); + x768_morphball->UpdateBallDynamics(mgr, dt); + } else { + ComputeMovement(dummy, mgr, dt); + } + } +} - if (GetFrozenState()) - { - if (x258_movementState == EPlayerMovementState::OnGround || - x258_movementState == EPlayerMovementState::FallingMorphed) - return; +void CPlayer::ProcessInput(const CFinalInput& input, CStateManager& mgr) { + if (input.ControllerIdx() != 0) + return; - CFinalInput dummyInput; - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - x768_morphball->ComputeBallMovement(dummyInput, mgr, input.DeltaTime()); - x768_morphball->UpdateBallDynamics(mgr, input.DeltaTime()); - } - else - { - ComputeMovement(dummyInput, mgr, input.DeltaTime()); - } + if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) + UpdateScanningState(input, mgr, input.DeltaTime()); - return; + if (mgr.GetGameState() != CStateManager::EGameState::Running) + return; + + if (!mgr.GetPlayerState()->IsPlayerAlive()) + return; + + if (GetFrozenState()) + UpdateFrozenState(input, mgr); + + if (GetFrozenState()) { + if (x258_movementState == EPlayerMovementState::OnGround || + x258_movementState == EPlayerMovementState::FallingMorphed) + return; + + CFinalInput dummyInput; + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + x768_morphball->ComputeBallMovement(dummyInput, mgr, input.DeltaTime()); + x768_morphball->UpdateBallDynamics(mgr, input.DeltaTime()); + } else { + ComputeMovement(dummyInput, mgr, input.DeltaTime()); } - if (x760_controlsFrozen) - { - ProcessFrozenInput(input.DeltaTime(), mgr); - return; - } + return; + } - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed && x4a0_failsafeTest->Passes()) - { - auto* prim = static_cast(GetCollisionPrimitive()); - zeus::CAABox tmpAABB(prim->GetAABB().min - 0.2f, prim->GetAABB().max + 0.2f); - CCollidableAABox tmpBox(tmpAABB, prim->GetMaterial()); - CPhysicsActor::Stop(); - zeus::CAABox testBounds = prim->GetAABB().getTransformedAABox(x34_transform); - zeus::CAABox expandedBounds(testBounds.min - 3.f, testBounds.max + 3.f); - CAreaCollisionCache cache(expandedBounds); - CGameCollision::BuildAreaCollisionCache(mgr, cache); - rstl::reserved_vector nearList; - mgr.BuildColliderList(nearList, *this, expandedBounds); - std::experimental::optional nonIntVec = + if (x760_controlsFrozen) { + ProcessFrozenInput(input.DeltaTime(), mgr); + return; + } + + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed && x4a0_failsafeTest->Passes()) { + auto* prim = static_cast(GetCollisionPrimitive()); + zeus::CAABox tmpAABB(prim->GetAABB().min - 0.2f, prim->GetAABB().max + 0.2f); + CCollidableAABox tmpBox(tmpAABB, prim->GetMaterial()); + CPhysicsActor::Stop(); + zeus::CAABox testBounds = prim->GetAABB().getTransformedAABox(x34_transform); + zeus::CAABox expandedBounds(testBounds.min - 3.f, testBounds.max + 3.f); + CAreaCollisionCache cache(expandedBounds); + CGameCollision::BuildAreaCollisionCache(mgr, cache); + rstl::reserved_vector nearList; + mgr.BuildColliderList(nearList, *this, expandedBounds); + std::experimental::optional nonIntVec = CGameCollision::FindNonIntersectingVector(mgr, cache, *this, *prim, nearList); - if (nonIntVec) - { - x4a0_failsafeTest->Reset(); - SetTranslation(GetTranslation() + *nonIntVec); - } + if (nonIntVec) { + x4a0_failsafeTest->Reset(); + SetTranslation(GetTranslation() + *nonIntVec); + } + } + + UpdateGrappleState(input, mgr); + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + float leftDiv = g_tweakBall->GetLeftStickDivisor(); + float rightDiv = g_tweakBall->GetRightStickDivisor(); + if (x26c_attachedActor != kInvalidUniqueId || IsUnderBetaMetroidAttack(mgr)) + leftDiv = 2.f; + CFinalInput scaledInput = input.ScaleAnalogueSticks(leftDiv, rightDiv); + x768_morphball->ComputeBallMovement(scaledInput, mgr, input.DeltaTime()); + x768_morphball->UpdateBallDynamics(mgr, input.DeltaTime()); + x4a0_failsafeTest->Reset(); + } else { + if (x304_orbitState == EPlayerOrbitState::Grapple) { + ApplyGrappleForces(input, mgr, input.DeltaTime()); + } else { + CFinalInput scaledInput = input.ScaleAnalogueSticks(IsUnderBetaMetroidAttack(mgr) ? 3.f : 1.f, 1.f); + ComputeMovement(scaledInput, mgr, input.DeltaTime()); } - UpdateGrappleState(input, mgr); - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - float leftDiv = g_tweakBall->GetLeftStickDivisor(); - float rightDiv = g_tweakBall->GetRightStickDivisor(); - if (x26c_attachedActor != kInvalidUniqueId || IsUnderBetaMetroidAttack(mgr)) - leftDiv = 2.f; - CFinalInput scaledInput = input.ScaleAnalogueSticks(leftDiv, rightDiv); - x768_morphball->ComputeBallMovement(scaledInput, mgr, input.DeltaTime()); - x768_morphball->UpdateBallDynamics(mgr, input.DeltaTime()); - x4a0_failsafeTest->Reset(); + if (ShouldSampleFailsafe(mgr)) { + CFailsafeTest::EInputState inputState = CFailsafeTest::EInputState::Moving; + if (x258_movementState == EPlayerMovementState::ApplyJump) + inputState = CFailsafeTest::EInputState::StartingJump; + else if (x258_movementState == EPlayerMovementState::Jump) + inputState = CFailsafeTest::EInputState::Jump; + x4a0_failsafeTest->AddSample(inputState, GetTranslation(), x138_velocity, + zeus::CVector2f(input.ALeftX(), input.ALeftY())); } - else - { - if (x304_orbitState == EPlayerOrbitState::Grapple) - { - ApplyGrappleForces(input, mgr, input.DeltaTime()); - } - else - { - CFinalInput scaledInput = input.ScaleAnalogueSticks(IsUnderBetaMetroidAttack(mgr) ? 3.f : 1.f, 1.f); - ComputeMovement(scaledInput, mgr, input.DeltaTime()); - } + } - if (ShouldSampleFailsafe(mgr)) - { - CFailsafeTest::EInputState inputState = CFailsafeTest::EInputState::Moving; - if (x258_movementState == EPlayerMovementState::ApplyJump) - inputState = CFailsafeTest::EInputState::StartingJump; - else if (x258_movementState == EPlayerMovementState::Jump) - inputState = CFailsafeTest::EInputState::Jump; - x4a0_failsafeTest->AddSample(inputState, GetTranslation(), x138_velocity, - zeus::CVector2f(input.ALeftX(), input.ALeftY())); - } + ComputeFreeLook(input); + UpdateFreeLookState(input, input.DeltaTime(), mgr); + UpdateOrbitInput(input, mgr); + UpdateOrbitZone(mgr); + UpdateGunState(input, mgr); + UpdateVisorState(input, input.DeltaTime(), mgr); + + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed || + (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed && x498_gunHolsterState == EGunHolsterState::Drawn)) { + x490_gun->ProcessInput(input, mgr); + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && x26c_attachedActor != kInvalidUniqueId) { + if (ControlMapper::GetPressInput(ControlMapper::ECommands::TurnLeft, input) || + ControlMapper::GetPressInput(ControlMapper::ECommands::TurnRight, input) || + ControlMapper::GetPressInput(ControlMapper::ECommands::Forward, input) || + ControlMapper::GetPressInput(ControlMapper::ECommands::Backward, input) || + ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) { + xa28_attachedActorStruggle += input.DeltaTime() * 600.f * input.DeltaTime(); + if (xa28_attachedActorStruggle > 1.f) + xa28_attachedActorStruggle = 1.f; + } else { + float tmp = 7.5f * input.DeltaTime(); + xa28_attachedActorStruggle -= input.DeltaTime() * std::min(1.f, xa28_attachedActorStruggle * tmp + tmp); + if (xa28_attachedActorStruggle < 0.f) + xa28_attachedActorStruggle = 0.f; + } } + } - ComputeFreeLook(input); - UpdateFreeLookState(input, input.DeltaTime(), mgr); - UpdateOrbitInput(input, mgr); - UpdateOrbitZone(mgr); - UpdateGunState(input, mgr); - UpdateVisorState(input, input.DeltaTime(), mgr); + UpdateCameraState(mgr); + UpdateMorphBallState(input.DeltaTime(), input, mgr); + UpdateCameraTimers(input.DeltaTime(), input); + UpdateFootstepSounds(input, mgr, input.DeltaTime()); + x2a8_timeSinceJump += input.DeltaTime(); - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed || - (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed && - x498_gunHolsterState == EGunHolsterState::Drawn)) - { - x490_gun->ProcessInput(input, mgr); - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && - x26c_attachedActor != kInvalidUniqueId) - { - if (ControlMapper::GetPressInput(ControlMapper::ECommands::TurnLeft, input) || - ControlMapper::GetPressInput(ControlMapper::ECommands::TurnRight, input) || - ControlMapper::GetPressInput(ControlMapper::ECommands::Forward, input) || - ControlMapper::GetPressInput(ControlMapper::ECommands::Backward, input) || - ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) - { - xa28_attachedActorStruggle += input.DeltaTime() * 600.f * input.DeltaTime(); - if (xa28_attachedActorStruggle > 1.f) - xa28_attachedActorStruggle = 1.f; - } - else - { - float tmp = 7.5f * input.DeltaTime(); - xa28_attachedActorStruggle -= input.DeltaTime() * std::min(1.f, xa28_attachedActorStruggle * tmp + tmp); - if (xa28_attachedActorStruggle < 0.f) - xa28_attachedActorStruggle = 0.f; - } - } - } + if (CheckSubmerged()) + SetSoundEventPitchBend(0); + else + SetSoundEventPitchBend(8192); - UpdateCameraState(mgr); - UpdateMorphBallState(input.DeltaTime(), input, mgr); - UpdateCameraTimers(input.DeltaTime(), input); - UpdateFootstepSounds(input, mgr, input.DeltaTime()); - x2a8_timeSinceJump += input.DeltaTime(); - - if (CheckSubmerged()) - SetSoundEventPitchBend(0); - else - SetSoundEventPitchBend(8192); - - CalculateLeaveMorphBallDirection(input); + CalculateLeaveMorphBallDirection(input); } -bool CPlayer::ShouldSampleFailsafe(CStateManager& mgr) const -{ - TCastToPtr cineCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - if (!mgr.GetPlayerState()->IsPlayerAlive()) - return false; - return x2f4_cameraState != EPlayerCameraState::Spawned || !cineCam || (cineCam->GetFlags() & 0x80) == 0; +bool CPlayer::ShouldSampleFailsafe(CStateManager& mgr) const { + TCastToPtr cineCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + if (!mgr.GetPlayerState()->IsPlayerAlive()) + return false; + return x2f4_cameraState != EPlayerCameraState::Spawned || !cineCam || (cineCam->GetFlags() & 0x80) == 0; } -void CPlayer::CalculateLeaveMorphBallDirection(const CFinalInput& input) -{ - if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) - { +void CPlayer::CalculateLeaveMorphBallDirection(const CFinalInput& input) { + if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) { + x518_leaveMorphDir = x50c_moveDir; + } else { + if (ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) > 0.3f || + ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input) > 0.3f || + ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input) > 0.3f || + ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) > 0.3f) { + if (x138_velocity.magnitude() > 0.5f) x518_leaveMorphDir = x50c_moveDir; } - else - { - if (ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) > 0.3f || - ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input) > 0.3f || - ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input) > 0.3f || - ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) > 0.3f) - { - if (x138_velocity.magnitude() > 0.5f) - x518_leaveMorphDir = x50c_moveDir; - } - } + } } -void CPlayer::CalculatePlayerControlDirection(CStateManager& mgr) -{ - if (x9c4_30_controlDirOverride) - { - if (x9d8_controlDirOverrideDir.canBeNormalized()) - { - x540_controlDir = x9d8_controlDirOverrideDir.normalized(); - x54c_controlDirFlat = x9d8_controlDirOverrideDir; +void CPlayer::CalculatePlayerControlDirection(CStateManager& mgr) { + if (x9c4_30_controlDirOverride) { + if (x9d8_controlDirOverrideDir.canBeNormalized()) { + x540_controlDir = x9d8_controlDirOverrideDir.normalized(); + x54c_controlDirFlat = x9d8_controlDirOverrideDir; + x54c_controlDirFlat.z() = 0.f; + if (x54c_controlDirFlat.canBeNormalized()) + x54c_controlDirFlat.normalize(); + else + x540_controlDir = x54c_controlDirFlat = zeus::CVector3f::skForward; + } else { + x540_controlDir = x54c_controlDirFlat = zeus::CVector3f::skForward; + } + } else { + zeus::CVector3f camToPlayer = GetTranslation() - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation(); + if (!camToPlayer.canBeNormalized()) { + x540_controlDir = x54c_controlDirFlat = zeus::CVector3f::skForward; + } else { + zeus::CVector3f camToPlayerFlat(camToPlayer.x(), camToPlayer.y(), 0.f); + if (camToPlayerFlat.canBeNormalized()) { + if (camToPlayerFlat.magnitude() > g_tweakBall->GetBallCameraControlDistance()) { + x540_controlDir = camToPlayer.normalized(); + if (camToPlayerFlat.canBeNormalized()) { + camToPlayerFlat.normalize(); + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Morphed: + x54c_controlDirFlat = camToPlayerFlat; + break; + default: + x540_controlDir = GetTransform().basis[1]; + x54c_controlDirFlat = x540_controlDir; + x54c_controlDirFlat.z() = 0.f; + if (x54c_controlDirFlat.canBeNormalized()) + x54c_controlDirFlat.normalize(); + } + } else if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) { + x540_controlDir = GetTransform().basis[1]; x54c_controlDirFlat.z() = 0.f; if (x54c_controlDirFlat.canBeNormalized()) - x54c_controlDirFlat.normalize(); - else - x540_controlDir = x54c_controlDirFlat = zeus::CVector3f::skForward; - } - else - { - x540_controlDir = x54c_controlDirFlat = zeus::CVector3f::skForward; - } - } - else - { - zeus::CVector3f camToPlayer = - GetTranslation() - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation(); - if (!camToPlayer.canBeNormalized()) - { - x540_controlDir = x54c_controlDirFlat = zeus::CVector3f::skForward; - } - else - { - zeus::CVector3f camToPlayerFlat(camToPlayer.x(), camToPlayer.y(), 0.f); - if (camToPlayerFlat.canBeNormalized()) - { - if (camToPlayerFlat.magnitude() > g_tweakBall->GetBallCameraControlDistance()) - { - x540_controlDir = camToPlayer.normalized(); - if (camToPlayerFlat.canBeNormalized()) - { - camToPlayerFlat.normalize(); - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Morphed: - x54c_controlDirFlat = camToPlayerFlat; - break; - default: - x540_controlDir = GetTransform().basis[1]; - x54c_controlDirFlat = x540_controlDir; - x54c_controlDirFlat.z() = 0.f; - if (x54c_controlDirFlat.canBeNormalized()) - x54c_controlDirFlat.normalize(); - } - } - else if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) - { - x540_controlDir = GetTransform().basis[1]; - x54c_controlDirFlat.z() = 0.f; - if (x54c_controlDirFlat.canBeNormalized()) - x54c_controlDirFlat.normalize(); - } - } - else - { - if (x4fc_flatMoveSpeed < 0.25f) - { - x540_controlDir = camToPlayer; - x54c_controlDirFlat = camToPlayerFlat; - } - else if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) - { - x540_controlDir = GetTransform().basis[1]; - x54c_controlDirFlat.z() = 0.f; - if (x54c_controlDirFlat.canBeNormalized()) - x54c_controlDirFlat.normalize(); - } - } - } + x54c_controlDirFlat.normalize(); + } + } else { + if (x4fc_flatMoveSpeed < 0.25f) { + x540_controlDir = camToPlayer; + x54c_controlDirFlat = camToPlayerFlat; + } else if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) { + x540_controlDir = GetTransform().basis[1]; + x54c_controlDirFlat.z() = 0.f; + if (x54c_controlDirFlat.canBeNormalized()) + x54c_controlDirFlat.normalize(); + } } + } } + } } -void CPlayer::CalculatePlayerMovementDirection(float dt) -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphing || - x2f8_morphBallState == EPlayerMorphBallState::Unmorphing) - return; +void CPlayer::CalculatePlayerMovementDirection(float dt) { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphing || + x2f8_morphBallState == EPlayerMorphBallState::Unmorphing) + return; - zeus::CVector3f delta = GetTranslation() - x524_lastPosForDirCalc; - if (delta.canBeNormalized() && delta.magnitude() > 0.02f) - { - x53c_timeMoving += dt; - x4f8_moveSpeed = std::fabs(delta.magnitude() / dt); - x500_lookDir = delta.normalized(); - zeus::CVector3f flatDelta(delta.x(), delta.y(), 0.f); - if (flatDelta.canBeNormalized()) - { - x4fc_flatMoveSpeed = std::fabs(flatDelta.magnitude() / dt); - flatDelta.normalize(); - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Morphed: - if (x4fc_flatMoveSpeed > 0.25f) - x50c_moveDir = flatDelta; - x530_gunDir = x50c_moveDir; - x524_lastPosForDirCalc = GetTranslation(); - break; - default: - x500_lookDir = GetTransform().basis[1]; - x50c_moveDir = x500_lookDir; - x50c_moveDir.z() = 0.f; - if (x50c_moveDir.canBeNormalized()) - x50c_moveDir.normalize(); - x530_gunDir = x50c_moveDir; - x524_lastPosForDirCalc = GetTranslation(); - break; - } - } - else - { - if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) - { - x500_lookDir = GetTransform().basis[1]; - x50c_moveDir = x500_lookDir; - x50c_moveDir.z() = 0.f; - if (x50c_moveDir.canBeNormalized()) - x50c_moveDir.normalize(); - x530_gunDir = x50c_moveDir; - x524_lastPosForDirCalc = GetTranslation(); - } - x4fc_flatMoveSpeed = 0.f; - } + zeus::CVector3f delta = GetTranslation() - x524_lastPosForDirCalc; + if (delta.canBeNormalized() && delta.magnitude() > 0.02f) { + x53c_timeMoving += dt; + x4f8_moveSpeed = std::fabs(delta.magnitude() / dt); + x500_lookDir = delta.normalized(); + zeus::CVector3f flatDelta(delta.x(), delta.y(), 0.f); + if (flatDelta.canBeNormalized()) { + x4fc_flatMoveSpeed = std::fabs(flatDelta.magnitude() / dt); + flatDelta.normalize(); + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Morphed: + if (x4fc_flatMoveSpeed > 0.25f) + x50c_moveDir = flatDelta; + x530_gunDir = x50c_moveDir; + x524_lastPosForDirCalc = GetTranslation(); + break; + default: + x500_lookDir = GetTransform().basis[1]; + x50c_moveDir = x500_lookDir; + x50c_moveDir.z() = 0.f; + if (x50c_moveDir.canBeNormalized()) + x50c_moveDir.normalize(); + x530_gunDir = x50c_moveDir; + x524_lastPosForDirCalc = GetTranslation(); + break; + } + } else { + if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) { + x500_lookDir = GetTransform().basis[1]; + x50c_moveDir = x500_lookDir; + x50c_moveDir.z() = 0.f; + if (x50c_moveDir.canBeNormalized()) + x50c_moveDir.normalize(); + x530_gunDir = x50c_moveDir; + x524_lastPosForDirCalc = GetTranslation(); + } + x4fc_flatMoveSpeed = 0.f; } - else - { - x53c_timeMoving = 0.f; - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Morphed: - case EPlayerMorphBallState::Morphing: - case EPlayerMorphBallState::Unmorphing: - x500_lookDir = x50c_moveDir; - break; - default: - x500_lookDir = GetTransform().basis[1]; - x50c_moveDir = x500_lookDir; - x50c_moveDir.z() = 0.f; - if (x50c_moveDir.canBeNormalized()) - x50c_moveDir.normalize(); - x530_gunDir = x50c_moveDir; - x524_lastPosForDirCalc = GetTranslation(); - break; - } - x4f8_moveSpeed = 0.f; - x4fc_flatMoveSpeed = 0.f; + } else { + x53c_timeMoving = 0.f; + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Morphed: + case EPlayerMorphBallState::Morphing: + case EPlayerMorphBallState::Unmorphing: + x500_lookDir = x50c_moveDir; + break; + default: + x500_lookDir = GetTransform().basis[1]; + x50c_moveDir = x500_lookDir; + x50c_moveDir.z() = 0.f; + if (x50c_moveDir.canBeNormalized()) + x50c_moveDir.normalize(); + x530_gunDir = x50c_moveDir; + x524_lastPosForDirCalc = GetTranslation(); + break; } + x4f8_moveSpeed = 0.f; + x4fc_flatMoveSpeed = 0.f; + } - x50c_moveDir.z() = 0.f; - if (x50c_moveDir.canBeNormalized()) - x500_lookDir.normalize(); + x50c_moveDir.z() = 0.f; + if (x50c_moveDir.canBeNormalized()) + x500_lookDir.normalize(); } -void CPlayer::UnFreeze(CStateManager& stateMgr) -{ - if (GetFrozenState()) - { - x750_frozenTimeout = 0.f; - x754_iceBreakJumps = 0; - CPhysicsActor::Stop(); - ClearForcesAndTorques(); - RemoveMaterial(EMaterialTypes::Immovable, stateMgr); - if (!stateMgr.GetCameraManager()->IsInCinematicCamera() && xa0c_iceTextureId.IsValid()) - { - std::experimental::optional> gpsm; - gpsm.emplace(g_SimplePool->GetObj(SObjectTag(FOURCC('PART'), xa0c_iceTextureId))); - CHUDBillboardEffect* effect = new CHUDBillboardEffect(gpsm, {}, stateMgr.AllocateUniqueId(), true, - "FrostExplosion", CHUDBillboardEffect::GetNearClipDistance(stateMgr), - CHUDBillboardEffect::GetScaleForPOV(stateMgr), zeus::CColor::skWhite, - zeus::CVector3f::skOne, zeus::CVector3f::skZero); - stateMgr.AddObject(effect); - CSfxHandle hnd = CSfxManager::SfxStart(SFXcrk_break_final, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - x768_morphball->Stop(); - SetVisorSteam(0.f, 0.42857146f, 0.071428575f, xa08_steamTextureId, false); - } -} - -void CPlayer::Freeze(CStateManager& stateMgr, CAssetId steamTxtr, u16 sfx, CAssetId iceTxtr) -{ - if (stateMgr.GetCameraManager()->IsInCinematicCamera() || GetFrozenState()) - return; - - bool showMsg; - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) - showMsg = g_GameState->SystemOptions().GetShowFrozenFpsMessage(); - else - showMsg = g_GameState->SystemOptions().GetShowFrozenBallMessage(); - - if (showMsg) - { - const char16_t* msg = - g_MainStringTable->GetString(int(x2f8_morphBallState >= EPlayerMorphBallState::Morphed) + 19); - CHUDMemoParms parms(5.f, true, false, false); - MP1::CSamusHud::DisplayHudMemo(msg, parms); - } - - x750_frozenTimeout = x758_frozenTimeoutBias + g_tweakPlayer->GetFrozenTimeout(); - x754_iceBreakJumps = -x75c_additionalIceBreakJumps; - +void CPlayer::UnFreeze(CStateManager& stateMgr) { + if (GetFrozenState()) { + x750_frozenTimeout = 0.f; + x754_iceBreakJumps = 0; CPhysicsActor::Stop(); ClearForcesAndTorques(); - if (x3b8_grappleState != EGrappleState::None) - BreakGrapple(EPlayerOrbitRequest::Freeze, stateMgr); - else - SetOrbitRequest(EPlayerOrbitRequest::Freeze, stateMgr); + RemoveMaterial(EMaterialTypes::Immovable, stateMgr); + if (!stateMgr.GetCameraManager()->IsInCinematicCamera() && xa0c_iceTextureId.IsValid()) { + std::experimental::optional> gpsm; + gpsm.emplace(g_SimplePool->GetObj(SObjectTag(FOURCC('PART'), xa0c_iceTextureId))); + CHUDBillboardEffect* effect = new CHUDBillboardEffect( + gpsm, {}, stateMgr.AllocateUniqueId(), true, "FrostExplosion", + CHUDBillboardEffect::GetNearClipDistance(stateMgr), CHUDBillboardEffect::GetScaleForPOV(stateMgr), + zeus::CColor::skWhite, zeus::CVector3f::skOne, zeus::CVector3f::skZero); + stateMgr.AddObject(effect); + CSfxHandle hnd = CSfxManager::SfxStart(SFXcrk_break_final, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } + x768_morphball->Stop(); + SetVisorSteam(0.f, 0.42857146f, 0.071428575f, xa08_steamTextureId, false); + } +} - AddMaterial(EMaterialTypes::Immovable, stateMgr); - xa08_steamTextureId = steamTxtr; - xa0c_iceTextureId = iceTxtr; - CSfxHandle hnd = CSfxManager::SfxStart(sfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - EndLandingControlFreeze(); +void CPlayer::Freeze(CStateManager& stateMgr, CAssetId steamTxtr, u16 sfx, CAssetId iceTxtr) { + if (stateMgr.GetCameraManager()->IsInCinematicCamera() || GetFrozenState()) + return; + + bool showMsg; + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed) + showMsg = g_GameState->SystemOptions().GetShowFrozenFpsMessage(); + else + showMsg = g_GameState->SystemOptions().GetShowFrozenBallMessage(); + + if (showMsg) { + const char16_t* msg = g_MainStringTable->GetString(int(x2f8_morphBallState >= EPlayerMorphBallState::Morphed) + 19); + CHUDMemoParms parms(5.f, true, false, false); + MP1::CSamusHud::DisplayHudMemo(msg, parms); + } + + x750_frozenTimeout = x758_frozenTimeoutBias + g_tweakPlayer->GetFrozenTimeout(); + x754_iceBreakJumps = -x75c_additionalIceBreakJumps; + + CPhysicsActor::Stop(); + ClearForcesAndTorques(); + if (x3b8_grappleState != EGrappleState::None) + BreakGrapple(EPlayerOrbitRequest::Freeze, stateMgr); + else + SetOrbitRequest(EPlayerOrbitRequest::Freeze, stateMgr); + + AddMaterial(EMaterialTypes::Immovable, stateMgr); + xa08_steamTextureId = steamTxtr; + xa0c_iceTextureId = iceTxtr; + CSfxHandle hnd = CSfxManager::SfxStart(sfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + EndLandingControlFreeze(); } bool CPlayer::GetFrozenState() const { return x750_frozenTimeout > 0.f; } -void CPlayer::UpdateFrozenState(const CFinalInput& input, CStateManager& mgr) -{ - x750_frozenTimeout -= input.DeltaTime(); - if (x750_frozenTimeout > 0.f) - SetVisorSteam(0.7f, 0.42857146f, 0.071428575f, xa08_steamTextureId, false); - else +void CPlayer::UpdateFrozenState(const CFinalInput& input, CStateManager& mgr) { + x750_frozenTimeout -= input.DeltaTime(); + if (x750_frozenTimeout > 0.f) + SetVisorSteam(0.7f, 0.42857146f, 0.071428575f, xa08_steamTextureId, false); + else + UnFreeze(mgr); + if (x258_movementState == EPlayerMovementState::OnGround || + x258_movementState == EPlayerMovementState::FallingMorphed) { + UnFreeze(mgr); + ClearForcesAndTorques(); + } + x7a0_visorSteam.Update(input.DeltaTime()); + + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Morphed: + x490_gun->ProcessInput(input, mgr); + break; + case EPlayerMorphBallState::Unmorphed: + case EPlayerMorphBallState::Morphing: + case EPlayerMorphBallState::Unmorphing: + if (ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) { + if (x754_iceBreakJumps != 0) { + /* Subsequent Breaks */ + CSfxHandle hnd = CSfxManager::SfxStart(SFXcrk_break_subsequent, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } else { + /* Initial Break */ + CSfxHandle hnd = CSfxManager::SfxStart(SFXcrk_break_initial, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } + x754_iceBreakJumps += 1; + if (x754_iceBreakJumps > g_tweakPlayer->GetIceBreakJumpCount()) { + g_GameState->SystemOptions().IncrementFrozenFpsCount(); + CHUDMemoParms info(0.f, true, true, true); + MP1::CSamusHud::DisplayHudMemo(u"", info); UnFreeze(mgr); - if (x258_movementState == EPlayerMovementState::OnGround || - x258_movementState == EPlayerMovementState::FallingMorphed) - { - UnFreeze(mgr); - ClearForcesAndTorques(); + } } - x7a0_visorSteam.Update(input.DeltaTime()); + break; + } +} - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Morphed: - x490_gun->ProcessInput(input, mgr); +void CPlayer::UpdateStepCameraZBias(float dt) { + float newBias = GetTranslation().z() + GetUnbiasedEyeHeight(); + if (x258_movementState == EPlayerMovementState::OnGround && !IsMorphBallTransitioning()) { + float oldBias = newBias; + if (!x9c5_31_stepCameraZBiasDirty) { + float delta = newBias - x9cc_stepCameraZBias; + float newDelta = 5.f * dt; + if (delta > 0.f) { + if (delta > dt * x138_velocity.z() && delta > newDelta) { + if (delta > GetStepUpHeight()) + newDelta += delta - GetStepUpHeight(); + newBias = x9cc_stepCameraZBias + newDelta; + } + } else { + if (delta < dt * x138_velocity.z() && delta < -newDelta) { + if (delta < -GetStepDownHeight()) + newDelta += -delta - GetStepDownHeight(); + newBias = x9cc_stepCameraZBias - newDelta; + } + } + } + x9c8_eyeZBias = newBias - oldBias; + } else { + x9c8_eyeZBias = 0.f; + } + x9cc_stepCameraZBias = newBias; + x9c5_31_stepCameraZBiasDirty = false; +} + +void CPlayer::UpdateWaterSurfaceCameraBias(CStateManager& mgr) { + if (TCastToConstPtr water = mgr.GetObjectById(xc4_fluidId)) { + float waterZ = water->GetTriggerBoundsWR().max.z(); + float biasToEyeDelta = GetEyePosition().z() - x9c8_eyeZBias; + float waterToDeltaDelta = biasToEyeDelta - waterZ; + if (biasToEyeDelta >= waterZ && waterToDeltaDelta <= 0.25f) + x9c8_eyeZBias += waterZ + 0.25f - biasToEyeDelta; + else if (biasToEyeDelta < waterZ && waterToDeltaDelta >= -0.2f) + x9c8_eyeZBias += waterZ - 0.2f - biasToEyeDelta; + } +} + +void CPlayer::UpdatePhazonCameraShake(float dt, CStateManager& mgr) { + xa2c_damageLoopSfxDelayTicks = std::min(2, xa2c_damageLoopSfxDelayTicks + 1); + if (xa10_phazonCounter != 0) { + if (xa14_phazonCameraShakeTimer == 0.f) + mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::BuildPhazonCameraShakeData(1.f, 0.075f), false); + xa14_phazonCameraShakeTimer += dt; + if (xa14_phazonCameraShakeTimer > 2.f) + xa14_phazonCameraShakeTimer = 0.f; + } +} + +void CPlayer::UpdatePhazonDamage(float dt, CStateManager& mgr) { + if (x4_areaId == kInvalidAreaId) + return; + + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); + if (!area->IsPostConstructed()) + return; + + bool touchingPhazon = false; + EPhazonType phazonType; + if (const CScriptAreaAttributes* attr = area->GetPostConstructed()->x10d8_areaAttributes) + phazonType = attr->GetPhazonType(); + else + phazonType = EPhazonType::None; + + if (phazonType == EPhazonType::Orange || + (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && phazonType == EPhazonType::Blue)) { + CMaterialFilter filter = CMaterialFilter::MakeInclude({EMaterialTypes::Phazon}); + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + touchingPhazon = x768_morphball->BallCloseToCollision(mgr, 2.9f, filter); + } else { + CMaterialList primMaterial(EMaterialTypes::Player, EMaterialTypes::Solid); + CCollidableSphere prim(zeus::CSphere(GetCollisionPrimitive()->CalculateAABox(x34_transform).center(), 4.25f), + primMaterial); + rstl::reserved_vector nearList; + mgr.BuildColliderList(nearList, *this, prim.CalculateLocalAABox()); + if (CGameCollision::DetectStaticCollisionBoolean(mgr, prim, zeus::CTransform::Identity(), filter)) { + touchingPhazon = true; + } else { + for (TUniqueId id : nearList) { + if (TCastToConstPtr act = mgr.GetObjectById(id)) { + CInternalCollisionStructure::CPrimDesc prim0(prim, filter, zeus::CTransform::Identity()); + CInternalCollisionStructure::CPrimDesc prim1( + *act->GetCollisionPrimitive(), CMaterialFilter::skPassEverything, act->GetPrimitiveTransform()); + if (CCollisionPrimitive::CollideBoolean(prim0, prim1)) { + touchingPhazon = true; + break; + } + } + } + } + } + } + + if (touchingPhazon) { + xa18_phazonDamageLag += dt; + xa18_phazonDamageLag = std::min(xa18_phazonDamageLag, 3.f); + if (xa18_phazonDamageLag > 0.2f) { + float damage = (xa18_phazonDamageLag - 0.2f) / 3.f * 60.f * dt; + CDamageInfo dInfo( + CWeaponMode(phazonType == EPhazonType::Orange ? EWeaponType::OrangePhazon : EWeaponType::Phazon), damage, 0.f, + 0.f); + mgr.ApplyDamage(kInvalidUniqueId, GetUniqueId(), kInvalidUniqueId, dInfo, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::CVector3f::skZero); + } + } else { + xa18_phazonDamageLag -= dt; + xa18_phazonDamageLag = std::min(0.2f, xa18_phazonDamageLag); + xa18_phazonDamageLag = std::max(0.f, xa18_phazonDamageLag); + } + + xa1c_threatOverride = std::min(1.f, xa18_phazonDamageLag / 0.2f); +} + +void CPlayer::ResetPlayerHintState() { + x9c4_26_ = true; + x9c4_27_canEnterMorphBall = true; + x9c4_28_canLeaveMorphBall = true; + x9c4_30_controlDirOverride = false; + x9c6_24_extendTargetDistance = false; + x9c6_26_outOfBallLookAtHint = false; + x9c4_29_spiderBallControlXY = false; + x9c6_29_disableInput = false; + x9c7_25_outOfBallLookAtHintActor = false; + x768_morphball->SetBoostEnabed(true); + ResetControlDirectionInterpolation(); +} + +bool CPlayer::SetAreaPlayerHint(const CScriptPlayerHint& hint, CStateManager& mgr) { + x9c4_26_ = (hint.GetOverrideFlags() & 0x1) != 0; + x9c4_27_canEnterMorphBall = (hint.GetOverrideFlags() & 0x40) == 0; + x9c4_28_canLeaveMorphBall = (hint.GetOverrideFlags() & 0x20) == 0; + x9c4_30_controlDirOverride = (hint.GetOverrideFlags() & 0x2) != 0; + if (x9c4_30_controlDirOverride) + x9d8_controlDirOverrideDir = hint.GetTransform().basis[1]; + x9c6_24_extendTargetDistance = (hint.GetOverrideFlags() & 0x4) != 0; + x9c6_26_outOfBallLookAtHint = (hint.GetOverrideFlags() & 0x8) != 0; + x9c4_29_spiderBallControlXY = (hint.GetOverrideFlags() & 0x10) != 0; + x9c6_29_disableInput = (hint.GetOverrideFlags() & 0x80) != 0; + x9c7_25_outOfBallLookAtHintActor = (hint.GetOverrideFlags() & 0x4000) != 0; + x768_morphball->SetBoostEnabed((hint.GetOverrideFlags() & 0x100) == 0); + bool switchedVisor = false; + if ((hint.GetOverrideFlags() & 0x200) != 0) { + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::CombatVisor)) + mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Combat); + switchedVisor = true; + } + if ((hint.GetOverrideFlags() & 0x400) != 0) { + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ScanVisor)) + mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Scan); + switchedVisor = true; + } + if ((hint.GetOverrideFlags() & 0x800) != 0) { + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ThermalVisor)) + mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Thermal); + switchedVisor = true; + } + if ((hint.GetOverrideFlags() & 0x1000) != 0) { + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::XRayVisor)) + mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::XRay); + switchedVisor = true; + } + return switchedVisor; +} + +void CPlayer::AddToPlayerHintRemoveList(TUniqueId id, CStateManager& mgr) { + if (TCastToPtr hint = mgr.ObjectById(id)) { + for (TUniqueId existId : x93c_playerHintsToRemove) + if (id == existId) + return; + if (x93c_playerHintsToRemove.size() != 32) + x93c_playerHintsToRemove.push_back(id); + } +} + +void CPlayer::AddToPlayerHintAddList(TUniqueId id, CStateManager& mgr) { + if (TCastToPtr hint = mgr.ObjectById(id)) { + for (TUniqueId existId : x980_playerHintsToAdd) + if (id == existId) + return; + if (x980_playerHintsToAdd.size() != 32) + x980_playerHintsToAdd.push_back(id); + } +} + +void CPlayer::DeactivatePlayerHint(TUniqueId id, CStateManager& mgr) { + if (TCastToPtr hint = mgr.ObjectById(id)) { + for (TUniqueId existId : x93c_playerHintsToRemove) + if (id == existId) + return; + if (x93c_playerHintsToRemove.size() != 32) { + x93c_playerHintsToRemove.push_back(id); + hint->ClearObjectList(); + hint->SetDeactivated(); + } + } +} + +void CPlayer::UpdatePlayerHints(CStateManager& mgr) { + bool removedHint = false; + for (auto it = x838_playerHints.begin(); it != x838_playerHints.end();) { + auto& p = *it; + TCastToPtr hint = mgr.ObjectById(p.second); + if (!hint) { + it = x838_playerHints.erase(it); + removedHint = true; + } else { + ++it; + } + } + + bool needsNewHint = false; + for (TUniqueId id : x93c_playerHintsToRemove) { + for (auto it = x838_playerHints.begin(); it != x838_playerHints.end();) { + if (it->second == id) { + it = x838_playerHints.erase(it); + if (id == x830_playerHint) + needsNewHint = true; break; - case EPlayerMorphBallState::Unmorphed: - case EPlayerMorphBallState::Morphing: - case EPlayerMorphBallState::Unmorphing: - if (ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) - { - if (x754_iceBreakJumps != 0) - { - /* Subsequent Breaks */ - CSfxHandle hnd = CSfxManager::SfxStart(SFXcrk_break_subsequent, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - else - { - /* Initial Break */ - CSfxHandle hnd = CSfxManager::SfxStart(SFXcrk_break_initial, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - x754_iceBreakJumps += 1; - if (x754_iceBreakJumps > g_tweakPlayer->GetIceBreakJumpCount()) - { - g_GameState->SystemOptions().IncrementFrozenFpsCount(); - CHUDMemoParms info(0.f, true, true, true); - MP1::CSamusHud::DisplayHudMemo(u"", info); - UnFreeze(mgr); - } + } + ++it; + } + } + x93c_playerHintsToRemove.clear(); + + bool addedHint = false; + for (TUniqueId id : x980_playerHintsToAdd) { + if (TCastToPtr hint = mgr.ObjectById(id)) { + bool exists = false; + for (auto& p : x838_playerHints) + if (p.second == id) { + exists = true; + break; } - break; + if (!exists) { + x838_playerHints.emplace_back(hint->GetPriority(), id); + addedHint = true; + } } -} + } + x980_playerHintsToAdd.clear(); -void CPlayer::UpdateStepCameraZBias(float dt) -{ - float newBias = GetTranslation().z() + GetUnbiasedEyeHeight(); - if (x258_movementState == EPlayerMovementState::OnGround && !IsMorphBallTransitioning()) - { - float oldBias = newBias; - if (!x9c5_31_stepCameraZBiasDirty) - { - float delta = newBias - x9cc_stepCameraZBias; - float newDelta = 5.f * dt; - if (delta > 0.f) - { - if (delta > dt * x138_velocity.z() && delta > newDelta) - { - if (delta > GetStepUpHeight()) - newDelta += delta - GetStepUpHeight(); - newBias = x9cc_stepCameraZBias + newDelta; - } - } - else - { - if (delta < dt * x138_velocity.z() && delta < -newDelta) - { - if (delta < -GetStepDownHeight()) - newDelta += -delta - GetStepDownHeight(); - newBias = x9cc_stepCameraZBias - newDelta; - } - } + if (needsNewHint || addedHint || removedHint) { + std::sort(x838_playerHints.begin(), x838_playerHints.end(), + [](const auto& a, const auto& b) { return a.first < b.first; }); + + if ((needsNewHint || removedHint) && x838_playerHints.empty()) { + x830_playerHint = kInvalidUniqueId; + x834_playerHintPriority = 1000; + ResetPlayerHintState(); + return; + } + + CScriptPlayerHint* foundHint = nullptr; + bool foundHintInArea = false; + for (auto& p : x838_playerHints) { + if (TCastToPtr hint = mgr.ObjectById(p.second)) { + foundHint = hint.GetPtr(); + if (hint->GetAreaIdAlways() == mgr.GetNextAreaId()) { + foundHintInArea = true; + break; } - x9c8_eyeZBias = newBias - oldBias; + } } - else - { - x9c8_eyeZBias = 0.f; + + if (!foundHintInArea) { + x830_playerHint = kInvalidUniqueId; + x834_playerHintPriority = 1000; + ResetPlayerHintState(); } - x9cc_stepCameraZBias = newBias; - x9c5_31_stepCameraZBiasDirty = false; + + if (foundHint != nullptr && foundHintInArea && x830_playerHint != foundHint->GetUniqueId()) { + x830_playerHint = foundHint->GetUniqueId(); + x834_playerHintPriority = foundHint->GetPriority(); + if (SetAreaPlayerHint(*foundHint, mgr)) + DeactivatePlayerHint(x830_playerHint, mgr); + } + } } -void CPlayer::UpdateWaterSurfaceCameraBias(CStateManager& mgr) -{ - if (TCastToConstPtr water = mgr.GetObjectById(xc4_fluidId)) - { - float waterZ = water->GetTriggerBoundsWR().max.z(); - float biasToEyeDelta = GetEyePosition().z() - x9c8_eyeZBias; - float waterToDeltaDelta = biasToEyeDelta - waterZ; - if (biasToEyeDelta >= waterZ && waterToDeltaDelta <= 0.25f) - x9c8_eyeZBias += waterZ + 0.25f - biasToEyeDelta; - else if (biasToEyeDelta < waterZ && waterToDeltaDelta >= -0.2f) - x9c8_eyeZBias += waterZ - 0.2f - biasToEyeDelta; - } +void CPlayer::UpdateBombJumpStuff() { + if (x9d0_bombJumpCount == 0) + return; + x9d4_bombJumpCheckDelayFrames -= 1; + if (x9d4_bombJumpCheckDelayFrames > 0) + return; + + zeus::CVector3f velFlat = x138_velocity; + velFlat.z() = 0.f; + if (x258_movementState == EPlayerMovementState::OnGround || (velFlat.canBeNormalized() && velFlat.magnitude() > 6.f)) + x9d0_bombJumpCount = 0; } -void CPlayer::UpdatePhazonCameraShake(float dt, CStateManager& mgr) -{ - xa2c_damageLoopSfxDelayTicks = std::min(2, xa2c_damageLoopSfxDelayTicks + 1); - if (xa10_phazonCounter != 0) - { - if (xa14_phazonCameraShakeTimer == 0.f) - mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::BuildPhazonCameraShakeData(1.f, 0.075f), false); - xa14_phazonCameraShakeTimer += dt; - if (xa14_phazonCameraShakeTimer > 2.f) - xa14_phazonCameraShakeTimer = 0.f; - } +void CPlayer::UpdateTransitionFilter(float dt, CStateManager& mgr) { + if (x824_transitionFilterTimer <= 0.f) { + mgr.GetCameraFilterPass(8).DisableFilter(0.f); + return; + } + + x824_transitionFilterTimer += dt; + if (x824_transitionFilterTimer > 1.25f) { + x824_transitionFilterTimer = 0.f; + mgr.GetCameraFilterPass(8).DisableFilter(0.f); + return; + } + + if (x824_transitionFilterTimer < 0.95f) + return; + + float time = x824_transitionFilterTimer - 0.95f; + zeus::CColor color(1.f, 0.87f, 0.54f, 1.f); + if (time < 0.1f) + color.a() = 0.3f * time / 0.1f; + else if (time >= 0.15f) + color.a() = 1.f - zeus::clamp(-1.f, (time - 0.15f) / 0.15f, 1.f) * 0.3f; + else + color.a() = 0.3f; + + mgr.GetCameraFilterPass(8).SetFilter(EFilterType::Add, EFilterShape::ScanLinesEven, 0.f, color, {}); } -void CPlayer::UpdatePhazonDamage(float dt, CStateManager& mgr) -{ - if (x4_areaId == kInvalidAreaId) - return; - - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); - if (!area->IsPostConstructed()) - return; - - bool touchingPhazon = false; - EPhazonType phazonType; - if (const CScriptAreaAttributes* attr = area->GetPostConstructed()->x10d8_areaAttributes) - phazonType = attr->GetPhazonType(); - else - phazonType = EPhazonType::None; - - if (phazonType == EPhazonType::Orange || - (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit) && phazonType == EPhazonType::Blue)) - { - CMaterialFilter filter = CMaterialFilter::MakeInclude({EMaterialTypes::Phazon}); - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - touchingPhazon = x768_morphball->BallCloseToCollision(mgr, 2.9f, filter); - } - else - { - CMaterialList primMaterial(EMaterialTypes::Player, EMaterialTypes::Solid); - CCollidableSphere prim(zeus::CSphere( - GetCollisionPrimitive()->CalculateAABox(x34_transform).center(), 4.25f), primMaterial); - rstl::reserved_vector nearList; - mgr.BuildColliderList(nearList, *this, prim.CalculateLocalAABox()); - if (CGameCollision::DetectStaticCollisionBoolean(mgr, prim, zeus::CTransform::Identity(), filter)) - { - touchingPhazon = true; - } - else - { - for (TUniqueId id : nearList) - { - if (TCastToConstPtr act = mgr.GetObjectById(id)) - { - CInternalCollisionStructure::CPrimDesc prim0(prim, filter, zeus::CTransform::Identity()); - CInternalCollisionStructure::CPrimDesc prim1(*act->GetCollisionPrimitive(), - CMaterialFilter::skPassEverything, - act->GetPrimitiveTransform()); - if (CCollisionPrimitive::CollideBoolean(prim0, prim1)) - { - touchingPhazon = true; - break; - } - } - } - } - } - } - - if (touchingPhazon) - { - xa18_phazonDamageLag += dt; - xa18_phazonDamageLag = std::min(xa18_phazonDamageLag, 3.f); - if (xa18_phazonDamageLag > 0.2f) - { - float damage = (xa18_phazonDamageLag - 0.2f) / 3.f * 60.f * dt; - CDamageInfo dInfo(CWeaponMode(phazonType == EPhazonType::Orange ? - EWeaponType::OrangePhazon : EWeaponType::Phazon), damage, 0.f, 0.f); - mgr.ApplyDamage(kInvalidUniqueId, GetUniqueId(), kInvalidUniqueId, dInfo, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), - zeus::CVector3f::skZero); - } - } - else - { - xa18_phazonDamageLag -= dt; - xa18_phazonDamageLag = std::min(0.2f, xa18_phazonDamageLag); - xa18_phazonDamageLag = std::max(0.f, xa18_phazonDamageLag); - } - - xa1c_threatOverride = std::min(1.f, xa18_phazonDamageLag / 0.2f); +void CPlayer::ResetControlDirectionInterpolation() { + x9c6_25_interpolatingControlDir = false; + x9f8_controlDirInterpTime = 0.f; } -void CPlayer::ResetPlayerHintState() -{ - x9c4_26_ = true; - x9c4_27_canEnterMorphBall = true; - x9c4_28_canLeaveMorphBall = true; - x9c4_30_controlDirOverride = false; - x9c6_24_extendTargetDistance = false; - x9c6_26_outOfBallLookAtHint = false; - x9c4_29_spiderBallControlXY = false; - x9c6_29_disableInput = false; - x9c7_25_outOfBallLookAtHintActor = false; - x768_morphball->SetBoostEnabed(true); - ResetControlDirectionInterpolation(); +void CPlayer::SetControlDirectionInterpolation(float time) { + x9c6_25_interpolatingControlDir = true; + x9f8_controlDirInterpTime = 0.f; + x9fc_controlDirInterpDur = time; } -bool CPlayer::SetAreaPlayerHint(const CScriptPlayerHint& hint, CStateManager& mgr) -{ - x9c4_26_ = (hint.GetOverrideFlags() & 0x1) != 0; - x9c4_27_canEnterMorphBall = (hint.GetOverrideFlags() & 0x40) == 0; - x9c4_28_canLeaveMorphBall = (hint.GetOverrideFlags() & 0x20) == 0; - x9c4_30_controlDirOverride = (hint.GetOverrideFlags() & 0x2) != 0; - if (x9c4_30_controlDirOverride) - x9d8_controlDirOverrideDir = hint.GetTransform().basis[1]; - x9c6_24_extendTargetDistance = (hint.GetOverrideFlags() & 0x4) != 0; - x9c6_26_outOfBallLookAtHint = (hint.GetOverrideFlags() & 0x8) != 0; - x9c4_29_spiderBallControlXY = (hint.GetOverrideFlags() & 0x10) != 0; - x9c6_29_disableInput = (hint.GetOverrideFlags() & 0x80) != 0; - x9c7_25_outOfBallLookAtHintActor = (hint.GetOverrideFlags() & 0x4000) != 0; - x768_morphball->SetBoostEnabed((hint.GetOverrideFlags() & 0x100) == 0); - bool switchedVisor = false; - if ((hint.GetOverrideFlags() & 0x200) != 0) - { - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::CombatVisor)) - mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Combat); - switchedVisor = true; +void CPlayer::UpdatePlayerControlDirection(float dt, CStateManager& mgr) { + zeus::CVector3f oldControlDir = x540_controlDir; + zeus::CVector3f oldControlDirFlat = x54c_controlDirFlat; + CalculatePlayerControlDirection(mgr); + if (x9c6_25_interpolatingControlDir && x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + x9f8_controlDirInterpTime += dt; + if (x9f8_controlDirInterpTime > x9fc_controlDirInterpDur) { + x9f8_controlDirInterpTime = x9fc_controlDirInterpDur; + ResetControlDirectionInterpolation(); } - if ((hint.GetOverrideFlags() & 0x400) != 0) - { - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ScanVisor)) - mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Scan); - switchedVisor = true; - } - if ((hint.GetOverrideFlags() & 0x800) != 0) - { - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::ThermalVisor)) - mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Thermal); - switchedVisor = true; - } - if ((hint.GetOverrideFlags() & 0x1000) != 0) - { - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::XRayVisor)) - mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::XRay); - switchedVisor = true; - } - return switchedVisor; + float t = zeus::clamp(-1.f, x9f8_controlDirInterpTime / x9fc_controlDirInterpDur, 1.f); + x540_controlDir = zeus::CVector3f::lerp(oldControlDir, x540_controlDir, t); + x54c_controlDirFlat = zeus::CVector3f::lerp(oldControlDirFlat, x540_controlDir, t); + } } -void CPlayer::AddToPlayerHintRemoveList(TUniqueId id, CStateManager& mgr) -{ - if (TCastToPtr hint = mgr.ObjectById(id)) - { - for (TUniqueId existId : x93c_playerHintsToRemove) - if (id == existId) - return; - if (x93c_playerHintsToRemove.size() != 32) - x93c_playerHintsToRemove.push_back(id); - } -} +void CPlayer::Think(float dt, CStateManager& mgr) { + UpdateStepCameraZBias(dt); + UpdateWaterSurfaceCameraBias(mgr); + UpdatePhazonCameraShake(dt, mgr); + UpdatePhazonDamage(dt, mgr); + UpdateFreeLook(dt); + UpdatePlayerHints(mgr); -void CPlayer::AddToPlayerHintAddList(TUniqueId id, CStateManager& mgr) -{ - if (TCastToPtr hint = mgr.ObjectById(id)) - { - for (TUniqueId existId : x980_playerHintsToAdd) - if (id == existId) - return; - if (x980_playerHintsToAdd.size() != 32) - x980_playerHintsToAdd.push_back(id); - } -} + if (x2b0_outOfWaterTicks < 2) + x2b0_outOfWaterTicks += 1; -void CPlayer::DeactivatePlayerHint(TUniqueId id, CStateManager& mgr) -{ - if (TCastToPtr hint = mgr.ObjectById(id)) - { - for (TUniqueId existId : x93c_playerHintsToRemove) - if (id == existId) - return; - if (x93c_playerHintsToRemove.size() != 32) - { - x93c_playerHintsToRemove.push_back(id); - hint->ClearObjectList(); - hint->SetDeactivated(); - } - } -} + x9c5_24_ = x9c4_24_visorChangeRequested; + x9c4_31_dampUnderwaterMotion = x9c5_25_splashUpdated; + x9c5_25_splashUpdated = false; + UpdateBombJumpStuff(); -void CPlayer::UpdatePlayerHints(CStateManager& mgr) -{ - bool removedHint = false; - for (auto it = x838_playerHints.begin() ; it != x838_playerHints.end() ;) - { - auto& p = *it; - TCastToPtr hint = mgr.ObjectById(p.second); - if (!hint) - { - it = x838_playerHints.erase(it); - removedHint = true; - } - else - { - ++it; - } - } + if (0.f < x288_startingJumpTimeout) { + x288_startingJumpTimeout -= dt; + if (0.f >= x288_startingJumpTimeout) + SetMoveState(EPlayerMovementState::ApplyJump, mgr); + } - bool needsNewHint = false; - for (TUniqueId id : x93c_playerHintsToRemove) - { - for (auto it = x838_playerHints.begin() ; it != x838_playerHints.end() ;) - { - if (it->second == id) - { - it = x838_playerHints.erase(it); - if (id == x830_playerHint) - needsNewHint = true; - break; - } - ++it; - } - } - x93c_playerHintsToRemove.clear(); + if (x2a0_ > 0.f) + x2a0_ += dt; + if (x774_samusVoiceTimeout > 0.f) + x774_samusVoiceTimeout -= dt; + if (0.f < x28c_sjTimer) + x28c_sjTimer -= dt; - bool addedHint = false; - for (TUniqueId id : x980_playerHintsToAdd) - { - if (TCastToPtr hint = mgr.ObjectById(id)) - { - bool exists = false; - for (auto& p : x838_playerHints) - if (p.second == id) - { - exists = true; - break; - } - if (!exists) - { - x838_playerHints.emplace_back(hint->GetPriority(), id); - addedHint = true; - } - } - } - x980_playerHintsToAdd.clear(); + x300_fallingTime += dt; + if (x258_movementState == EPlayerMovementState::FallingMorphed && x300_fallingTime > 0.4f) + SetMoveState(EPlayerMovementState::ApplyJump, mgr); - if (needsNewHint || addedHint || removedHint) - { - std::sort(x838_playerHints.begin(), x838_playerHints.end(), - [](const auto& a, const auto& b) { return a.first < b.first; }); + if (x570_immuneTimer > 0.f) + x570_immuneTimer -= dt; - if ((needsNewHint || removedHint) && x838_playerHints.empty()) - { - x830_playerHint = kInvalidUniqueId; - x834_playerHintPriority = 1000; - ResetPlayerHintState(); - return; - } - - CScriptPlayerHint* foundHint = nullptr; - bool foundHintInArea = false; - for (auto& p : x838_playerHints) - { - if (TCastToPtr hint = mgr.ObjectById(p.second)) - { - foundHint = hint.GetPtr(); - if (hint->GetAreaIdAlways() == mgr.GetNextAreaId()) - { - foundHintInArea = true; - break; - } - } - } - - if (!foundHintInArea) - { - x830_playerHint = kInvalidUniqueId; - x834_playerHintPriority = 1000; - ResetPlayerHintState(); - } - - if (foundHint != nullptr && foundHintInArea && x830_playerHint != foundHint->GetUniqueId()) - { - x830_playerHint = foundHint->GetUniqueId(); - x834_playerHintPriority = foundHint->GetPriority(); - if (SetAreaPlayerHint(*foundHint, mgr)) - DeactivatePlayerHint(x830_playerHint, mgr); - } - } -} - -void CPlayer::UpdateBombJumpStuff() -{ - if (x9d0_bombJumpCount == 0) - return; - x9d4_bombJumpCheckDelayFrames -= 1; - if (x9d4_bombJumpCheckDelayFrames > 0) - return; - - zeus::CVector3f velFlat = x138_velocity; - velFlat.z() = 0.f; - if (x258_movementState == EPlayerMovementState::OnGround || - (velFlat.canBeNormalized() && velFlat.magnitude() > 6.f)) - x9d0_bombJumpCount = 0; -} - -void CPlayer::UpdateTransitionFilter(float dt, CStateManager& mgr) -{ - if (x824_transitionFilterTimer <= 0.f) - { - mgr.GetCameraFilterPass(8).DisableFilter(0.f); - return; - } - - x824_transitionFilterTimer += dt; - if (x824_transitionFilterTimer > 1.25f) - { - x824_transitionFilterTimer = 0.f; - mgr.GetCameraFilterPass(8).DisableFilter(0.f); - return; - } - - if (x824_transitionFilterTimer < 0.95f) - return; - - float time = x824_transitionFilterTimer - 0.95f; - zeus::CColor color(1.f, 0.87f, 0.54f, 1.f); - if (time < 0.1f) - color.a() = 0.3f * time / 0.1f; - else if (time >= 0.15f) - color.a() = 1.f - zeus::clamp(-1.f, (time - 0.15f) / 0.15f, 1.f) * 0.3f; - else - color.a() = 0.3f; - - mgr.GetCameraFilterPass(8).SetFilter(EFilterType::Add, EFilterShape::ScanLinesEven, 0.f, color, {}); -} - -void CPlayer::ResetControlDirectionInterpolation() -{ - x9c6_25_interpolatingControlDir = false; - x9f8_controlDirInterpTime = 0.f; -} - -void CPlayer::SetControlDirectionInterpolation(float time) -{ - x9c6_25_interpolatingControlDir = true; - x9f8_controlDirInterpTime = 0.f; - x9fc_controlDirInterpDur = time; -} - -void CPlayer::UpdatePlayerControlDirection(float dt, CStateManager& mgr) -{ - zeus::CVector3f oldControlDir = x540_controlDir; - zeus::CVector3f oldControlDirFlat = x54c_controlDirFlat; - CalculatePlayerControlDirection(mgr); - if (x9c6_25_interpolatingControlDir && x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - x9f8_controlDirInterpTime += dt; - if (x9f8_controlDirInterpTime > x9fc_controlDirInterpDur) - { - x9f8_controlDirInterpTime = x9fc_controlDirInterpDur; - ResetControlDirectionInterpolation(); - } - float t = zeus::clamp(-1.f, x9f8_controlDirInterpTime / x9fc_controlDirInterpDur, 1.f); - x540_controlDir = zeus::CVector3f::lerp(oldControlDir, x540_controlDir, t); - x54c_controlDirFlat = zeus::CVector3f::lerp(oldControlDirFlat, x540_controlDir, t); - } -} - -void CPlayer::Think(float dt, CStateManager& mgr) -{ - UpdateStepCameraZBias(dt); - UpdateWaterSurfaceCameraBias(mgr); - UpdatePhazonCameraShake(dt, mgr); - UpdatePhazonDamage(dt, mgr); - UpdateFreeLook(dt); - UpdatePlayerHints(mgr); - - if (x2b0_outOfWaterTicks < 2) - x2b0_outOfWaterTicks += 1; - - x9c5_24_ = x9c4_24_visorChangeRequested; - x9c4_31_dampUnderwaterMotion = x9c5_25_splashUpdated; - x9c5_25_splashUpdated = false; - UpdateBombJumpStuff(); - - if (0.f < x288_startingJumpTimeout) - { - x288_startingJumpTimeout -= dt; - if (0.f >= x288_startingJumpTimeout) - SetMoveState(EPlayerMovementState::ApplyJump, mgr); - } - - if (x2a0_ > 0.f) - x2a0_ += dt; - if (x774_samusVoiceTimeout > 0.f) - x774_samusVoiceTimeout -= dt; - if (0.f < x28c_sjTimer) - x28c_sjTimer -= dt; - - x300_fallingTime += dt; - if (x258_movementState == EPlayerMovementState::FallingMorphed && x300_fallingTime > 0.4f) - SetMoveState(EPlayerMovementState::ApplyJump, mgr); - - if (x570_immuneTimer > 0.f) - x570_immuneTimer -= dt; - - Update(dt, mgr); - UpdateTransitionFilter(dt, mgr); - CalculatePlayerMovementDirection(dt); - UpdatePlayerControlDirection(dt, mgr); + Update(dt, mgr); + UpdateTransitionFilter(dt, mgr); + CalculatePlayerMovementDirection(dt); + UpdatePlayerControlDirection(dt, mgr); #if 0 if (g_factoryManager == 4) @@ -2709,1658 +2269,1395 @@ void CPlayer::Think(float dt, CStateManager& mgr) x2ac_surfaceRestraint = ESurfaceRestraints::Normal; #endif - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed && x9c5_27_camSubmerged && - mgr.GetCameraManager()->GetFluidCounter() == 0) - { - if (auto water = GetVisorRunoffEffect(mgr)) - { - if (const auto& effect = water->GetVisorRunoffEffect()) - { - CHUDBillboardEffect* sheets = new CHUDBillboardEffect(*effect, {}, mgr.AllocateUniqueId(), - true, "WaterSheets", - CHUDBillboardEffect::GetNearClipDistance(mgr), - CHUDBillboardEffect::GetScaleForPOV(mgr), - zeus::CColor::skWhite, zeus::CVector3f::skOne, - zeus::CVector3f::skZero); - mgr.AddObject(sheets); - } - CSfxHandle hnd = CSfxManager::SfxStart(water->GetVisorRunoffSfx(), 1.f, 0.f, - false, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphed && x9c5_27_camSubmerged && + mgr.GetCameraManager()->GetFluidCounter() == 0) { + if (auto water = GetVisorRunoffEffect(mgr)) { + if (const auto& effect = water->GetVisorRunoffEffect()) { + CHUDBillboardEffect* sheets = new CHUDBillboardEffect( + *effect, {}, mgr.AllocateUniqueId(), true, "WaterSheets", CHUDBillboardEffect::GetNearClipDistance(mgr), + CHUDBillboardEffect::GetScaleForPOV(mgr), zeus::CColor::skWhite, zeus::CVector3f::skOne, + zeus::CVector3f::skZero); + mgr.AddObject(sheets); + } + CSfxHandle hnd = CSfxManager::SfxStart(water->GetVisorRunoffSfx(), 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); } - x9c5_27_camSubmerged = mgr.GetCameraManager()->GetFluidCounter() != 0; + } + x9c5_27_camSubmerged = mgr.GetCameraManager()->GetFluidCounter() != 0; + if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) { + if (std::fabs(x34_transform.basis[0].z()) > FLT_EPSILON || std::fabs(x34_transform.basis[1].z()) > FLT_EPSILON) { + zeus::CVector3f backupTranslation = GetTranslation(); + zeus::CVector3f lookDirFlat(x34_transform.basis[1].x(), x34_transform.basis[1].y(), 0.f); + if (lookDirFlat.canBeNormalized()) { + SetTransform(zeus::lookAt(zeus::CVector3f::skZero, lookDirFlat.normalized())); + } else { + SetTransform(zeus::CTransform::Identity()); + } + SetTranslation(backupTranslation); + } + } + + x794_lastVelocity = x138_velocity; +} + +void CPlayer::PreThink(float dt, CStateManager& mgr) { + x558_wasDamaged = false; + x55c_damageAmt = 0.f; + x560_prevDamageAmt = 0.f; + x564_damageLocation = zeus::CVector3f::skZero; + xa04_preThinkDt = dt; +} + +static const u16 skPlayerLandSfxSoft[] = {0xFFFF, + SFXsam_landstone_00, + SFXsam_landmetl_00, + SFXsam_landgrass_00, + SFXsam_landice_00, + 0xFFFF, + SFXsam_landgrate_00, + SFXsam_landphazon_00, + SFXsam_landdirt_00, + SFXlav_landlava_00, + SFXsam_landlavastone_00, + SFXsam_landsnow_00, + SFXsam_landmud_00, + 0xFFFF, + SFXsam_landgrass_00, + SFXsam_landmetl_00, + SFXsam_landmetl_00, + SFXsam_landdirt_00, + 0xFFFF, + 0xFFFF, + 0xFFFF, + 0xFFFF, + SFXsam_landwood_00, + SFXsam_b_landorg_00}; + +static const u16 skPlayerLandSfxHard[] = {0xFFFF, + SFXsam_landstone_02, + SFXsam_b_landmetl_02, + SFXsam_landgrass_02, + SFXsam_landice_02, + 0xFFFF, + SFXsam_landgrate_02, + SFXsam_landphazon_02, + SFXsam_landdirt_02, + SFXlav_landlava_02, + SFXsam_landlavastone_02, + SFXsam_landsnow_02, + SFXsam_landmud_02, + 0xFFFF, + SFXsam_landgrass_02, + SFXsam_b_landmetl_02, + SFXsam_b_landmetl_02, + SFXsam_landdirt_02, + 0xFFFF, + 0xFFFF, + 0xFFFF, + 0xFFFF, + SFXsam_landwood_02, + SFXsam_landorg_02}; + +void CPlayer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::OnFloor: + if (x258_movementState != EPlayerMovementState::OnGround && x2f8_morphBallState != EPlayerMorphBallState::Morphed && + x300_fallingTime > 0.3f) { + if (x258_movementState != EPlayerMovementState::Falling) { + float hardThres = 30.f * 2.f * -g_tweakPlayer->GetNormalGravAccel(); + hardThres = (hardThres != 0.f) ? hardThres * std::sqrt(hardThres) : 0.f; + float landVol = zeus::clamp(95.f, 1.6f * -x794_lastVelocity.z() + 95.f, 127.f) / 127.f; + u16 landSfx; + if (-x794_lastVelocity.z() < hardThres) { + landSfx = GetMaterialSoundUnderPlayer(mgr, skPlayerLandSfxSoft, 24, 0xffff); + } else { + landSfx = GetMaterialSoundUnderPlayer(mgr, skPlayerLandSfxHard, 24, 0xffff); + StartSamusVoiceSfx(SFXsam_voxland_02, 1.f, 5); + x55c_damageAmt = 0.f; + x560_prevDamageAmt = 10.f; + x564_damageLocation = x34_transform.origin; + x558_wasDamaged = true; + mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData::BuildLandingCameraShakeData(0.3f, 1.25f), false); + StartLandingControlFreeze(); + } + CSfxHandle handle = CSfxManager::SfxStart(landSfx, landVol, 0.f, false, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(handle); + + float rumbleMag = -x794_lastVelocity.z() / 110.f; + if (rumbleMag > 0.f) { + if (std::fabs(rumbleMag) > 0.8f) + rumbleMag = (rumbleMag > 0.f) ? 0.8f : -0.8f; + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerLand, rumbleMag, ERumblePriority::One); + } + + x2a0_ = 0.f; + } + } else if (x258_movementState != EPlayerMovementState::OnGround && + x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + if (x138_velocity.z() < -40.f && !x768_morphball->GetIsInHalfPipeMode() && + x258_movementState == EPlayerMovementState::ApplyJump && x300_fallingTime > 0.75f) + SetCoefficientOfRestitutionModifier(0.2f); + x768_morphball->StartLandingSfx(); + if (x138_velocity.z() < -5.f) { + float rumbleMag = -x138_velocity.z() / 110.f * 0.5f; + if (std::fabs(rumbleMag) > 0.8f) + rumbleMag = (rumbleMag > 0.f) ? 0.8f : -0.8f; + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerLand, rumbleMag, ERumblePriority::One); + x2a0_ = 0.f; + } + if (x138_velocity.z() < -30.f) { + float rumbleMag = -x138_velocity.z() / 110.f; + if (std::fabs(rumbleMag) > 0.8f) + rumbleMag = (rumbleMag > 0.f) ? 0.8f : -0.8f; + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerLand, rumbleMag, ERumblePriority::One); + x2a0_ = 0.f; + } + } + x300_fallingTime = 0.f; + SetMoveState(EPlayerMovementState::OnGround, mgr); + break; + case EScriptObjectMessage::Falling: + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) + if (x768_morphball->GetSpiderBallState() == CMorphBall::ESpiderBallState::Active) + break; if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) - { - if (std::fabs(x34_transform.basis[0].z()) > FLT_EPSILON || - std::fabs(x34_transform.basis[1].z()) > FLT_EPSILON) - { - zeus::CVector3f backupTranslation = GetTranslation(); - zeus::CVector3f lookDirFlat(x34_transform.basis[1].x(), x34_transform.basis[1].y(), 0.f); - if (lookDirFlat.canBeNormalized()) - { - SetTransform(zeus::lookAt(zeus::CVector3f::skZero, lookDirFlat.normalized())); - } - else - { - SetTransform(zeus::CTransform::Identity()); - } - SetTranslation(backupTranslation); - } + SetMoveState(EPlayerMovementState::Falling, mgr); + else if (x258_movementState == EPlayerMovementState::OnGround) + SetMoveState(EPlayerMovementState::FallingMorphed, mgr); + break; + case EScriptObjectMessage::LandOnNotFloor: + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && + x768_morphball->GetSpiderBallState() == CMorphBall::ESpiderBallState::Active && + x258_movementState != EPlayerMovementState::ApplyJump) + SetMoveState(EPlayerMovementState::ApplyJump, mgr); + break; + case EScriptObjectMessage::OnIceSurface: + x2ac_surfaceRestraint = ESurfaceRestraints::Ice; + break; + case EScriptObjectMessage::OnMudSlowSurface: + x2ac_surfaceRestraint = ESurfaceRestraints::MudSlow; + break; + case EScriptObjectMessage::OnNormalSurface: + x2ac_surfaceRestraint = ESurfaceRestraints::Normal; + break; + case EScriptObjectMessage::InSnakeWeed: + x2ac_surfaceRestraint = ESurfaceRestraints::SnakeWeed; + break; + case EScriptObjectMessage::AddSplashInhabitant: { + SetInFluid(true, sender); + UpdateSubmerged(mgr); + CRayCastResult result = mgr.RayStaticIntersection(x34_transform.origin, zeus::CVector3f::skDown, + 0.5f * GetEyeHeight(), SolidMaterialFilter); + if (result.IsInvalid()) { + SetVelocityWR(x138_velocity * 0.095f); + xfc_constantForce *= zeus::CVector3f(0.095f); } + break; + } + case EScriptObjectMessage::UpdateSplashInhabitant: + UpdateSubmerged(mgr); + if (CheckSubmerged() && !mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) { + if (TCastToPtr water = mgr.ObjectById(xc4_fluidId)) { + switch (water->GetFluidPlane().GetFluidType()) { + case EFluidType::NormalWater: + x2b0_outOfWaterTicks = 0; + break; + case EFluidType::Lava: + case EFluidType::ThickLava: + x2ac_surfaceRestraint = ESurfaceRestraints::Lava; + break; + case EFluidType::PoisonWater: + x2b0_outOfWaterTicks = 0; + break; + case EFluidType::PhazonFluid: + x2ac_surfaceRestraint = ESurfaceRestraints::PhazonFluid; + break; + default: + break; + } + } + } + x9c5_25_splashUpdated = true; + break; + case EScriptObjectMessage::RemoveSplashInhabitant: + SetInFluid(false, kInvalidUniqueId); + UpdateSubmerged(mgr); + break; + case EScriptObjectMessage::ProjectileCollide: + x378_orbitPreventionTimer = g_tweakPlayer->GetOrbitPreventionTime(); + SetOrbitRequest(EPlayerOrbitRequest::ProjectileCollide, mgr); + break; + case EScriptObjectMessage::AddPlatformRider: + x82e_ridingPlatform = sender; + break; + case EScriptObjectMessage::Damage: + if (TCastToPtr energ = mgr.ObjectById(sender)) { + if ((energ->GetAttribField() & EProjectileAttrib::StaticInterference) != EProjectileAttrib::None) { + mgr.GetPlayerState()->GetStaticInterference().AddSource(GetUniqueId(), 0.3f, energ->GetInterferenceDuration()); + } + } + break; + case EScriptObjectMessage::Deleted: + mgr.GetPlayerState()->ResetVisor(); + x730_transitionModels.clear(); + break; + default: + break; + } - x794_lastVelocity = x138_velocity; + x490_gun->AcceptScriptMsg(msg, sender, mgr); + x768_morphball->AcceptScriptMsg(msg, sender, mgr); + CActor::AcceptScriptMsg(msg, sender, mgr); } -void CPlayer::PreThink(float dt, CStateManager& mgr) -{ - x558_wasDamaged = false; - x55c_damageAmt = 0.f; - x560_prevDamageAmt = 0.f; - x564_damageLocation = zeus::CVector3f::skZero; - xa04_preThinkDt = dt; +void CPlayer::SetVisorSteam(float targetAlpha, float alphaInDur, float alphaOutDur, CAssetId txtr, + bool affectsThermal) { + x7a0_visorSteam.SetSteam(targetAlpha, alphaInDur, alphaOutDur, txtr, affectsThermal); } -static const u16 skPlayerLandSfxSoft[] = -{ - 0xFFFF, - SFXsam_landstone_00, - SFXsam_landmetl_00, - SFXsam_landgrass_00, - SFXsam_landice_00, - 0xFFFF, - SFXsam_landgrate_00, - SFXsam_landphazon_00, - SFXsam_landdirt_00, - SFXlav_landlava_00, - SFXsam_landlavastone_00, - SFXsam_landsnow_00, - SFXsam_landmud_00, - 0xFFFF, - SFXsam_landgrass_00, - SFXsam_landmetl_00, - SFXsam_landmetl_00, - SFXsam_landdirt_00, - 0xFFFF, - 0xFFFF, - 0xFFFF, - 0xFFFF, - SFXsam_landwood_00, - SFXsam_b_landorg_00 -}; +static const u16 skLeftStepSounds[] = {0xFFFF, + SFXsam_wlkstone_00, + SFXsam_wlkmetal_00, + SFXsam_b_wlkgrass_00, + SFXsam_wlkice_00, + 0xFFFF, + SFXsam_wlkgrate_00, + SFXsam_wlkphazon_00, + SFXsam_wlkdirt_00, + SFXlav_wlklava_00, + SFXsam_wlklavastone_00, + SFXsam_wlksnow_00, + SFXsam_wlkmud_00, + 0xFFFF, + SFXsam_b_wlkorg_00, + SFXsam_wlkmetal_00, + SFXsam_wlkmetal_00, + SFXsam_wlkdirt_00, + 0xFFFF, + 0xFFFF, + 0xFFFF, + 0xFFFF, + SFXsam_wlkwood_00, + SFXsam_b_wlkorg_00}; -static const u16 skPlayerLandSfxHard[] = -{ - 0xFFFF, - SFXsam_landstone_02, - SFXsam_b_landmetl_02, - SFXsam_landgrass_02, - SFXsam_landice_02, - 0xFFFF, - SFXsam_landgrate_02, - SFXsam_landphazon_02, - SFXsam_landdirt_02, - SFXlav_landlava_02, - SFXsam_landlavastone_02, - SFXsam_landsnow_02, - SFXsam_landmud_02, - 0xFFFF, - SFXsam_landgrass_02, - SFXsam_b_landmetl_02, - SFXsam_b_landmetl_02, - SFXsam_landdirt_02, - 0xFFFF, - 0xFFFF, - 0xFFFF, - 0xFFFF, - SFXsam_landwood_02, - SFXsam_landorg_02 -}; +static const u16 skRightStepSounds[] = {0xFFFF, + SFXsam_wlkstone_01, + SFXsam_wlkmetal_01, + SFXsam_b_wlkgrass_01, + SFXsam_wlkice_01, + 0xFFFF, + SFXsam_wlkgrate_01, + SFXsam_wlkphazon_01, + SFXsam_wlkdirt_01, + SFXlav_wlklava_01, + SFXsam_wlklavastone_01, + SFXsam_wlksnow_01, + SFXsam_wlkmud_01, + 0xFFFF, + SFXsam_b_wlkorg_01, + SFXsam_wlkmetal_01, + SFXsam_wlkmetal_01, + SFXsam_wlkdirt_01, + 0xFFFF, + 0xFFFF, + 0xFFFF, + 0xFFFF, + SFXsam_wlkwood_01, + SFXsam_b_wlkorg_01}; -void CPlayer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::OnFloor: - if (x258_movementState != EPlayerMovementState::OnGround && - x2f8_morphBallState != EPlayerMorphBallState::Morphed && - x300_fallingTime > 0.3f) - { - if (x258_movementState != EPlayerMovementState::Falling) - { - float hardThres = 30.f * 2.f * -g_tweakPlayer->GetNormalGravAccel(); - hardThres = (hardThres != 0.f) ? hardThres * std::sqrt(hardThres) : 0.f; - float landVol = zeus::clamp(95.f, 1.6f * -x794_lastVelocity.z() + 95.f, 127.f) / 127.f; - u16 landSfx; - if (-x794_lastVelocity.z() < hardThres) - { - landSfx = GetMaterialSoundUnderPlayer(mgr, skPlayerLandSfxSoft, 24, 0xffff); - } - else - { - landSfx = GetMaterialSoundUnderPlayer(mgr, skPlayerLandSfxHard, 24, 0xffff); - StartSamusVoiceSfx(SFXsam_voxland_02, 1.f, 5); - x55c_damageAmt = 0.f; - x560_prevDamageAmt = 10.f; - x564_damageLocation = x34_transform.origin; - x558_wasDamaged = true; - mgr.GetCameraManager()->AddCameraShaker( - CCameraShakeData::BuildLandingCameraShakeData(0.3f, 1.25f), false); - StartLandingControlFreeze(); - } - CSfxHandle handle = - CSfxManager::SfxStart(landSfx, landVol, 0.f, false, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(handle); +void CPlayer::UpdateFootstepSounds(const CFinalInput& input, CStateManager& mgr, float dt) { + if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || x258_movementState != EPlayerMovementState::OnGround || + x3dc_inFreeLook || x3dd_lookButtonHeld) + return; - float rumbleMag = -x794_lastVelocity.z() / 110.f; - if (rumbleMag > 0.f) - { - if (std::fabs(rumbleMag) > 0.8f) - rumbleMag = (rumbleMag > 0.f) ? 0.8f : -0.8f; - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerLand, rumbleMag, ERumblePriority::One); - } - - x2a0_ = 0.f; - } - } - else if (x258_movementState != EPlayerMovementState::OnGround && - x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - if (x138_velocity.z() < -40.f && !x768_morphball->GetIsInHalfPipeMode() && - x258_movementState == EPlayerMovementState::ApplyJump && - x300_fallingTime > 0.75f) - SetCoefficientOfRestitutionModifier(0.2f); - x768_morphball->StartLandingSfx(); - if (x138_velocity.z() < -5.f) - { - float rumbleMag = -x138_velocity.z() / 110.f * 0.5f; - if (std::fabs(rumbleMag) > 0.8f) - rumbleMag = (rumbleMag > 0.f) ? 0.8f : -0.8f; - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerLand, rumbleMag, ERumblePriority::One); - x2a0_ = 0.f; - } - if (x138_velocity.z() < -30.f) - { - float rumbleMag = -x138_velocity.z() / 110.f; - if (std::fabs(rumbleMag) > 0.8f) - rumbleMag = (rumbleMag > 0.f) ? 0.8f : -0.8f; - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerLand, rumbleMag, ERumblePriority::One); - x2a0_ = 0.f; - } - } - x300_fallingTime = 0.f; - SetMoveState(EPlayerMovementState::OnGround, mgr); - break; - case EScriptObjectMessage::Falling: - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - if (x768_morphball->GetSpiderBallState() == CMorphBall::ESpiderBallState::Active) - break; - if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) - SetMoveState(EPlayerMovementState::Falling, mgr); - else if (x258_movementState == EPlayerMovementState::OnGround) - SetMoveState(EPlayerMovementState::FallingMorphed, mgr); - break; - case EScriptObjectMessage::LandOnNotFloor: - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && - x768_morphball->GetSpiderBallState() == CMorphBall::ESpiderBallState::Active && - x258_movementState != EPlayerMovementState::ApplyJump) - SetMoveState(EPlayerMovementState::ApplyJump, mgr); - break; - case EScriptObjectMessage::OnIceSurface: - x2ac_surfaceRestraint = ESurfaceRestraints::Ice; - break; - case EScriptObjectMessage::OnMudSlowSurface: - x2ac_surfaceRestraint = ESurfaceRestraints::MudSlow; - break; - case EScriptObjectMessage::OnNormalSurface: - x2ac_surfaceRestraint = ESurfaceRestraints::Normal; - break; - case EScriptObjectMessage::InSnakeWeed: - x2ac_surfaceRestraint = ESurfaceRestraints::SnakeWeed; - break; - case EScriptObjectMessage::AddSplashInhabitant: - { - SetInFluid(true, sender); - UpdateSubmerged(mgr); - CRayCastResult result = - mgr.RayStaticIntersection(x34_transform.origin, zeus::CVector3f::skDown, - 0.5f * GetEyeHeight(), SolidMaterialFilter); - if (result.IsInvalid()) - { - SetVelocityWR(x138_velocity * 0.095f); - xfc_constantForce *= zeus::CVector3f(0.095f); - } - break; - } - case EScriptObjectMessage::UpdateSplashInhabitant: - UpdateSubmerged(mgr); - if (CheckSubmerged() && !mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) - { - if (TCastToPtr water = mgr.ObjectById(xc4_fluidId)) - { - switch (water->GetFluidPlane().GetFluidType()) - { - case EFluidType::NormalWater: - x2b0_outOfWaterTicks = 0; - break; - case EFluidType::Lava: - case EFluidType::ThickLava: - x2ac_surfaceRestraint = ESurfaceRestraints::Lava; - break; - case EFluidType::PoisonWater: - x2b0_outOfWaterTicks = 0; - break; - case EFluidType::PhazonFluid: - x2ac_surfaceRestraint = ESurfaceRestraints::PhazonFluid; - break; - default: break; - } - } - } - x9c5_25_splashUpdated = true; - break; - case EScriptObjectMessage::RemoveSplashInhabitant: - SetInFluid(false, kInvalidUniqueId); - UpdateSubmerged(mgr); - break; - case EScriptObjectMessage::ProjectileCollide: - x378_orbitPreventionTimer = g_tweakPlayer->GetOrbitPreventionTime(); - SetOrbitRequest(EPlayerOrbitRequest::ProjectileCollide, mgr); - break; - case EScriptObjectMessage::AddPlatformRider: - x82e_ridingPlatform = sender; - break; - case EScriptObjectMessage::Damage: - if (TCastToPtr energ = mgr.ObjectById(sender)) - { - if ((energ->GetAttribField() & EProjectileAttrib::StaticInterference) != - EProjectileAttrib::None) - { - mgr.GetPlayerState()->GetStaticInterference(). - AddSource(GetUniqueId(), 0.3f, energ->GetInterferenceDuration()); - } - } - break; - case EScriptObjectMessage::Deleted: - mgr.GetPlayerState()->ResetVisor(); - x730_transitionModels.clear(); - break; - default: break; + float sfxVol = 1.f; + x78c_footstepSfxTimer += dt; + float turn = TurnInput(input); + float forward = std::fabs(ForwardInput(input, turn)); + turn = std::fabs(turn); + float sfxDelay = 0.f; + if (forward > 0.05f || x304_orbitState != EPlayerOrbitState::NoOrbit) { + float vel = std::min(1.f, x138_velocity.magnitude() / GetActualFirstPersonMaxVelocity(dt)); + if (vel > 0.05f) { + sfxDelay = -0.475f * vel + 0.85f; + if (x790_footstepSfxSel == EFootstepSfx::None) + x790_footstepSfxSel = EFootstepSfx::Left; + } else { + x78c_footstepSfxTimer = 0.f; + x790_footstepSfxSel = EFootstepSfx::None; } - x490_gun->AcceptScriptMsg(msg, sender, mgr); - x768_morphball->AcceptScriptMsg(msg, sender, mgr); - CActor::AcceptScriptMsg(msg, sender, mgr); -} - -void CPlayer::SetVisorSteam(float targetAlpha, float alphaInDur, float alphaOutDur, CAssetId txtr, bool affectsThermal) -{ - x7a0_visorSteam.SetSteam(targetAlpha, alphaInDur, alphaOutDur, txtr, affectsThermal); -} - -static const u16 skLeftStepSounds[] = -{ - 0xFFFF, - SFXsam_wlkstone_00, - SFXsam_wlkmetal_00, - SFXsam_b_wlkgrass_00, - SFXsam_wlkice_00, - 0xFFFF, - SFXsam_wlkgrate_00, - SFXsam_wlkphazon_00, - SFXsam_wlkdirt_00, - SFXlav_wlklava_00, - SFXsam_wlklavastone_00, - SFXsam_wlksnow_00, - SFXsam_wlkmud_00, - 0xFFFF, - SFXsam_b_wlkorg_00, - SFXsam_wlkmetal_00, - SFXsam_wlkmetal_00, - SFXsam_wlkdirt_00, - 0xFFFF, - 0xFFFF, - 0xFFFF, - 0xFFFF, - SFXsam_wlkwood_00, - SFXsam_b_wlkorg_00 -}; - -static const u16 skRightStepSounds[] = -{ - 0xFFFF, - SFXsam_wlkstone_01, - SFXsam_wlkmetal_01, - SFXsam_b_wlkgrass_01, - SFXsam_wlkice_01, - 0xFFFF, - SFXsam_wlkgrate_01, - SFXsam_wlkphazon_01, - SFXsam_wlkdirt_01, - SFXlav_wlklava_01, - SFXsam_wlklavastone_01, - SFXsam_wlksnow_01, - SFXsam_wlkmud_01, - 0xFFFF, - SFXsam_b_wlkorg_01, - SFXsam_wlkmetal_01, - SFXsam_wlkmetal_01, - SFXsam_wlkdirt_01, - 0xFFFF, - 0xFFFF, - 0xFFFF, - 0xFFFF, - SFXsam_wlkwood_01, - SFXsam_b_wlkorg_01 -}; - -void CPlayer::UpdateFootstepSounds(const CFinalInput& input, CStateManager& mgr, float dt) -{ - if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || - x258_movementState != EPlayerMovementState::OnGround || - x3dc_inFreeLook || x3dd_lookButtonHeld) - return; - - float sfxVol = 1.f; - x78c_footstepSfxTimer += dt; - float turn = TurnInput(input); - float forward = std::fabs(ForwardInput(input, turn)); - turn = std::fabs(turn); - float sfxDelay = 0.f; - if (forward > 0.05f || x304_orbitState != EPlayerOrbitState::NoOrbit) - { - float vel = std::min(1.f, x138_velocity.magnitude() / GetActualFirstPersonMaxVelocity(dt)); - if (vel > 0.05f) - { - sfxDelay = -0.475f * vel + 0.85f; - if (x790_footstepSfxSel == EFootstepSfx::None) - x790_footstepSfxSel = EFootstepSfx::Left; - } - else - { - x78c_footstepSfxTimer = 0.f; - x790_footstepSfxSel = EFootstepSfx::None; - } - - sfxVol = 0.3f * vel + 0.7f; - } - else if (turn > 0.05f) - { - if (x790_footstepSfxSel == EFootstepSfx::Left) - sfxDelay = -0.813f * turn + 1.f; - else - sfxDelay = -2.438f * turn + 3.f; - if (x790_footstepSfxSel == EFootstepSfx::None) - { - x790_footstepSfxSel = EFootstepSfx::Left; - sfxDelay = x78c_footstepSfxTimer; - } - sfxVol = 0.75f; - } + sfxVol = 0.3f * vel + 0.7f; + } else if (turn > 0.05f) { + if (x790_footstepSfxSel == EFootstepSfx::Left) + sfxDelay = -0.813f * turn + 1.f; else - { - x78c_footstepSfxTimer = 0.f; - x790_footstepSfxSel = EFootstepSfx::None; + sfxDelay = -2.438f * turn + 3.f; + if (x790_footstepSfxSel == EFootstepSfx::None) { + x790_footstepSfxSel = EFootstepSfx::Left; + sfxDelay = x78c_footstepSfxTimer; } + sfxVol = 0.75f; + } else { + x78c_footstepSfxTimer = 0.f; + x790_footstepSfxSel = EFootstepSfx::None; + } - if (x790_footstepSfxSel != EFootstepSfx::None && x78c_footstepSfxTimer > sfxDelay) - { - static float EarHeight = GetEyeHeight() - 0.1f; - if (xe6_24_fluidCounter != 0 && x828_distanceUnderWater > 0.f && x828_distanceUnderWater < EarHeight) - { - if (x82c_inLava) - { - if (x790_footstepSfxSel == EFootstepSfx::Left) - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXlav_wlklava_00, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - else - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXlav_wlklava_01, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - } - else - { - if (x790_footstepSfxSel == EFootstepSfx::Left) - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_wlkwater_00, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - else - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_wlkwater_01, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - } + if (x790_footstepSfxSel != EFootstepSfx::None && x78c_footstepSfxTimer > sfxDelay) { + static float EarHeight = GetEyeHeight() - 0.1f; + if (xe6_24_fluidCounter != 0 && x828_distanceUnderWater > 0.f && x828_distanceUnderWater < EarHeight) { + if (x82c_inLava) { + if (x790_footstepSfxSel == EFootstepSfx::Left) { + CSfxHandle hnd = CSfxManager::SfxStart(SFXlav_wlklava_00, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } else { + CSfxHandle hnd = CSfxManager::SfxStart(SFXlav_wlklava_01, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); } - else - { - u16 sfx; - if (x790_footstepSfxSel == EFootstepSfx::Left) - sfx = GetMaterialSoundUnderPlayer(mgr, skLeftStepSounds, 24, -1); - else - sfx = GetMaterialSoundUnderPlayer(mgr, skRightStepSounds, 24, -1); - CSfxHandle hnd = CSfxManager::SfxStart(sfx, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); + } else { + if (x790_footstepSfxSel == EFootstepSfx::Left) { + CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_wlkwater_00, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } else { + CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_wlkwater_01, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); } - - x78c_footstepSfxTimer = 0.f; - if (x790_footstepSfxSel == EFootstepSfx::Left) - x790_footstepSfxSel = EFootstepSfx::Right; - else - x790_footstepSfxSel = EFootstepSfx::Left; + } + } else { + u16 sfx; + if (x790_footstepSfxSel == EFootstepSfx::Left) + sfx = GetMaterialSoundUnderPlayer(mgr, skLeftStepSounds, 24, -1); + else + sfx = GetMaterialSoundUnderPlayer(mgr, skRightStepSounds, 24, -1); + CSfxHandle hnd = CSfxManager::SfxStart(sfx, sfxVol, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); } + + x78c_footstepSfxTimer = 0.f; + if (x790_footstepSfxSel == EFootstepSfx::Left) + x790_footstepSfxSel = EFootstepSfx::Right; + else + x790_footstepSfxSel = EFootstepSfx::Left; + } } -u16 CPlayer::GetMaterialSoundUnderPlayer(CStateManager& mgr, const u16* table, u32 length, u16 defId) -{ - u16 ret = defId; - zeus::CAABox aabb = GetBoundingBox(); - aabb.accumulateBounds(x34_transform.origin + zeus::CVector3f::skDown); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, aabb, SolidMaterialFilter, nullptr); - TUniqueId collideId = kInvalidUniqueId; - CRayCastResult result = mgr.RayWorldIntersection(collideId, x34_transform.origin, - zeus::CVector3f::skDown, - 1.5f, SolidMaterialFilter, nearList); - if (result.IsValid()) - ret = SfxIdFromMaterial(result.GetMaterial(), table, length, defId); - return ret; +u16 CPlayer::GetMaterialSoundUnderPlayer(CStateManager& mgr, const u16* table, u32 length, u16 defId) { + u16 ret = defId; + zeus::CAABox aabb = GetBoundingBox(); + aabb.accumulateBounds(x34_transform.origin + zeus::CVector3f::skDown); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, aabb, SolidMaterialFilter, nullptr); + TUniqueId collideId = kInvalidUniqueId; + CRayCastResult result = mgr.RayWorldIntersection(collideId, x34_transform.origin, zeus::CVector3f::skDown, 1.5f, + SolidMaterialFilter, nearList); + if (result.IsValid()) + ret = SfxIdFromMaterial(result.GetMaterial(), table, length, defId); + return ret; } -u16 CPlayer::SfxIdFromMaterial(const CMaterialList& mat, const u16* idList, u32 tableLen, u16 defId) -{ - u16 id = defId; - for (u32 i = 0; i < tableLen; ++i) - { - if (mat.HasMaterial(EMaterialTypes(i)) && idList[i] != 0xFFFF) - id = idList[i]; - } - return id; +u16 CPlayer::SfxIdFromMaterial(const CMaterialList& mat, const u16* idList, u32 tableLen, u16 defId) { + u16 id = defId; + for (u32 i = 0; i < tableLen; ++i) { + if (mat.HasMaterial(EMaterialTypes(i)) && idList[i] != 0xFFFF) + id = idList[i]; + } + return id; } -void CPlayer::UpdateCrosshairsState(const CFinalInput& input) -{ - x9c4_25_showCrosshairs = ControlMapper::GetDigitalInput(ControlMapper::ECommands::ShowCrosshairs, input); +void CPlayer::UpdateCrosshairsState(const CFinalInput& input) { + x9c4_25_showCrosshairs = ControlMapper::GetDigitalInput(ControlMapper::ECommands::ShowCrosshairs, input); } -void CPlayer::UpdateVisorTransition(float dt, CStateManager& mgr) -{ - if (mgr.GetPlayerState()->GetIsVisorTransitioning()) - mgr.GetPlayerState()->UpdateVisorTransition(dt); +void CPlayer::UpdateVisorTransition(float dt, CStateManager& mgr) { + if (mgr.GetPlayerState()->GetIsVisorTransitioning()) + mgr.GetPlayerState()->UpdateVisorTransition(dt); } -static const std::pair skVisorToItemMapping[] = -{ +static const std::pair skVisorToItemMapping[] = { {CPlayerState::EItemType::CombatVisor, ControlMapper::ECommands::NoVisor}, {CPlayerState::EItemType::XRayVisor, ControlMapper::ECommands::XrayVisor}, {CPlayerState::EItemType::ScanVisor, ControlMapper::ECommands::InviroVisor}, - {CPlayerState::EItemType::ThermalVisor, ControlMapper::ECommands::ThermoVisor} -}; + {CPlayerState::EItemType::ThermalVisor, ControlMapper::ECommands::ThermoVisor}}; -void CPlayer::UpdateVisorState(const CFinalInput& input, float dt, CStateManager& mgr) -{ - x7a0_visorSteam.Update(dt); - if (x7a0_visorSteam.AffectsThermal()) - mgr.SetThermalColdScale2(mgr.GetThermalColdScale2() + x7a0_visorSteam.GetAlpha()); +void CPlayer::UpdateVisorState(const CFinalInput& input, float dt, CStateManager& mgr) { + x7a0_visorSteam.Update(dt); + if (x7a0_visorSteam.AffectsThermal()) + mgr.SetThermalColdScale2(mgr.GetThermalColdScale2() + x7a0_visorSteam.GetAlpha()); - if (x304_orbitState == EPlayerOrbitState::Grapple || - TCastToPtr(mgr.ObjectById(x310_orbitTargetId)) || - x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || - mgr.GetPlayerState()->GetIsVisorTransitioning() || - x3a8_scanState != EPlayerScanState::NotScanning) - return; + if (x304_orbitState == EPlayerOrbitState::Grapple || + TCastToPtr(mgr.ObjectById(x310_orbitTargetId)) || + x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || mgr.GetPlayerState()->GetIsVisorTransitioning() || + x3a8_scanState != EPlayerScanState::NotScanning) + return; - if (mgr.GetPlayerState()->GetTransitioningVisor() == CPlayerState::EPlayerVisor::Scan && - (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) || - ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input)) && - mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::CombatVisor)) - { - mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Combat); - DrawGun(mgr); - } + if (mgr.GetPlayerState()->GetTransitioningVisor() == CPlayerState::EPlayerVisor::Scan && + (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) || + ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input)) && + mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::CombatVisor)) { + mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Combat); + DrawGun(mgr); + } - for (int i=0 ; i<4 ; ++i) - { - if (mgr.GetPlayerState()->HasPowerUp(skVisorToItemMapping[i].first) && - ControlMapper::GetPressInput(skVisorToItemMapping[i].second, input)) - { - x9c4_24_visorChangeRequested = true; - CPlayerState::EPlayerVisor visor = CPlayerState::EPlayerVisor(i); - if (mgr.GetPlayerState()->GetTransitioningVisor() != visor) - { - mgr.GetPlayerState()->StartVisorTransition(visor); - if (visor == CPlayerState::EPlayerVisor::Scan) - HolsterGun(mgr); - else - DrawGun(mgr); - } - } - } -} - -void CPlayer::UpdateGunState(const CFinalInput& input, CStateManager& mgr) -{ - switch (x498_gunHolsterState) - { - case EGunHolsterState::Drawn: - { - bool needsHolster = false; - if (g_tweakPlayer->GetGunButtonTogglesHolster()) - { - if (ControlMapper::GetPressInput(ControlMapper::ECommands::ToggleHolster, input)) - needsHolster = true; - if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) && - !ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) && - g_tweakPlayer->GetGunNotFiringHolstersGun()) - { - x49c_gunHolsterRemTime -= input.DeltaTime(); - if (x49c_gunHolsterRemTime <= 0.f) - needsHolster = true; - } - } + for (int i = 0; i < 4; ++i) { + if (mgr.GetPlayerState()->HasPowerUp(skVisorToItemMapping[i].first) && + ControlMapper::GetPressInput(skVisorToItemMapping[i].second, input)) { + x9c4_24_visorChangeRequested = true; + CPlayerState::EPlayerVisor visor = CPlayerState::EPlayerVisor(i); + if (mgr.GetPlayerState()->GetTransitioningVisor() != visor) { + mgr.GetPlayerState()->StartVisorTransition(visor); + if (visor == CPlayerState::EPlayerVisor::Scan) + HolsterGun(mgr); else - { - if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) && - !ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) && - x490_gun->IsFidgeting()) - { - if (g_tweakPlayer->GetGunNotFiringHolstersGun()) - x49c_gunHolsterRemTime -= input.DeltaTime(); - } - else - { - x49c_gunHolsterRemTime = g_tweakPlayerGun->GetGunNotFiringTime(); - } - } - - if (needsHolster) - HolsterGun(mgr); - break; - } - case EGunHolsterState::Drawing: - { - if (x49c_gunHolsterRemTime > 0.f) - { - x49c_gunHolsterRemTime -= input.DeltaTime(); - } else - { - x498_gunHolsterState = EGunHolsterState::Drawn; - x49c_gunHolsterRemTime = g_tweakPlayerGun->GetGunNotFiringTime(); - } - break; - } - case EGunHolsterState::Holstered: - { - bool needsDraw = false; - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) || - ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) || - x3b8_grappleState == EGrappleState::None || - (g_tweakPlayer->GetGunButtonTogglesHolster() && - ControlMapper::GetPressInput(ControlMapper::ECommands::ToggleHolster, input))) - needsDraw = true; - - if (x3b8_grappleState == EGrappleState::None && - (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan || - mgr.GetPlayerState()->GetTransitioningVisor() == CPlayerState::EPlayerVisor::Scan )) - needsDraw = false; - - if (needsDraw) - DrawGun(mgr); - break; - } - case EGunHolsterState::Holstering: - if (x49c_gunHolsterRemTime > 0.f) - x49c_gunHolsterRemTime -= input.DeltaTime(); - else - x498_gunHolsterState = EGunHolsterState::Holstered; - break; + DrawGun(mgr); + } } + } } -void CPlayer::ResetGun(CStateManager& mgr) -{ - x498_gunHolsterState = EGunHolsterState::Holstered; - x49c_gunHolsterRemTime = 0.f; - x490_gun->CancelFiring(mgr); - ResetAimTargetPrediction(kInvalidUniqueId); -} - -void CPlayer::UpdateArmAndGunTransforms(float dt, CStateManager& mgr) -{ - zeus::CVector3f grappleOffset; - zeus::CVector3f gunOffset; - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - { - gunOffset = {0.f, 0.f, 0.6f}; +void CPlayer::UpdateGunState(const CFinalInput& input, CStateManager& mgr) { + switch (x498_gunHolsterState) { + case EGunHolsterState::Drawn: { + bool needsHolster = false; + if (g_tweakPlayer->GetGunButtonTogglesHolster()) { + if (ControlMapper::GetPressInput(ControlMapper::ECommands::ToggleHolster, input)) + needsHolster = true; + if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) && + !ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) && + g_tweakPlayer->GetGunNotFiringHolstersGun()) { + x49c_gunHolsterRemTime -= input.DeltaTime(); + if (x49c_gunHolsterRemTime <= 0.f) + needsHolster = true; + } + } else { + if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) && + !ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) && + x490_gun->IsFidgeting()) { + if (g_tweakPlayer->GetGunNotFiringHolstersGun()) + x49c_gunHolsterRemTime -= input.DeltaTime(); + } else { + x49c_gunHolsterRemTime = g_tweakPlayerGun->GetGunNotFiringTime(); + } } + + if (needsHolster) + HolsterGun(mgr); + break; + } + case EGunHolsterState::Drawing: { + if (x49c_gunHolsterRemTime > 0.f) { + x49c_gunHolsterRemTime -= input.DeltaTime(); + } else { + x498_gunHolsterState = EGunHolsterState::Drawn; + x49c_gunHolsterRemTime = g_tweakPlayerGun->GetGunNotFiringTime(); + } + break; + } + case EGunHolsterState::Holstered: { + bool needsDraw = false; + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) || + ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input) || + x3b8_grappleState == EGrappleState::None || + (g_tweakPlayer->GetGunButtonTogglesHolster() && + ControlMapper::GetPressInput(ControlMapper::ECommands::ToggleHolster, input))) + needsDraw = true; + + if (x3b8_grappleState == EGrappleState::None && + (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan || + mgr.GetPlayerState()->GetTransitioningVisor() == CPlayerState::EPlayerVisor::Scan)) + needsDraw = false; + + if (needsDraw) + DrawGun(mgr); + break; + } + case EGunHolsterState::Holstering: + if (x49c_gunHolsterRemTime > 0.f) + x49c_gunHolsterRemTime -= input.DeltaTime(); else - { - gunOffset = g_tweakPlayerGun->GetGunPosition(); - grappleOffset = x490_gun->GetGrappleArm().IsArmMoving() ? - zeus::CVector3f::skZero : g_tweakPlayerGun->GetGrapplingArmPosition(); - gunOffset.z() += GetEyeHeight(); - grappleOffset.z() += GetEyeHeight(); - } - - UpdateGunTransform(gunOffset + x76c_cameraBob->GetGunBobTransformation().origin, mgr); - UpdateGrappleArmTransform(grappleOffset, mgr, dt); + x498_gunHolsterState = EGunHolsterState::Holstered; + break; + } } -void CPlayer::ForceGunOrientation(const zeus::CTransform& xf, CStateManager& mgr) -{ - ResetGun(mgr); - x530_gunDir = xf.basis[1]; - x490_gun->SetTransform(xf); - UpdateArmAndGunTransforms(0.01f, mgr); +void CPlayer::ResetGun(CStateManager& mgr) { + x498_gunHolsterState = EGunHolsterState::Holstered; + x49c_gunHolsterRemTime = 0.f; + x490_gun->CancelFiring(mgr); + ResetAimTargetPrediction(kInvalidUniqueId); } -void CPlayer::UpdateCameraState(CStateManager& mgr) -{ - UpdateCinematicState(mgr); +void CPlayer::UpdateArmAndGunTransforms(float dt, CStateManager& mgr) { + zeus::CVector3f grappleOffset; + zeus::CVector3f gunOffset; + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) { + gunOffset = {0.f, 0.f, 0.6f}; + } else { + gunOffset = g_tweakPlayerGun->GetGunPosition(); + grappleOffset = + x490_gun->GetGrappleArm().IsArmMoving() ? zeus::CVector3f::skZero : g_tweakPlayerGun->GetGrapplingArmPosition(); + gunOffset.z() += GetEyeHeight(); + grappleOffset.z() += GetEyeHeight(); + } + + UpdateGunTransform(gunOffset + x76c_cameraBob->GetGunBobTransformation().origin, mgr); + UpdateGrappleArmTransform(grappleOffset, mgr, dt); } -void CPlayer::UpdateDebugCamera(CStateManager& mgr) -{ - // Empty +void CPlayer::ForceGunOrientation(const zeus::CTransform& xf, CStateManager& mgr) { + ResetGun(mgr); + x530_gunDir = xf.basis[1]; + x490_gun->SetTransform(xf); + UpdateArmAndGunTransforms(0.01f, mgr); } -void CPlayer::UpdateCameraTimers(float dt, const CFinalInput& input) -{ - if (x3dc_inFreeLook || x3dd_lookButtonHeld) - { - x294_jumpCameraTimer = 0.f; - x29c_fallCameraTimer = 0.f; - return; - } +void CPlayer::UpdateCameraState(CStateManager& mgr) { UpdateCinematicState(mgr); } - if (g_tweakPlayer->GetFiringCancelsCameraPitch()) - { - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) || - ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input)) - { - if (x288_startingJumpTimeout > 0.f) - { - x2a4_cancelCameraPitch = true; - return; - } - } - } - - if (ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) - ++x298_jumpPresses; - - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) && - x294_jumpCameraTimer > 0.f && !x2a4_cancelCameraPitch && x298_jumpPresses <= 2) - x294_jumpCameraTimer += dt; - - if (x29c_fallCameraTimer > 0.f && !x2a4_cancelCameraPitch) - x29c_fallCameraTimer += dt; +void CPlayer::UpdateDebugCamera(CStateManager& mgr) { + // Empty } -void CPlayer::UpdateMorphBallState(float dt, const CFinalInput& input, CStateManager& mgr) -{ - if (!ControlMapper::GetPressInput(ControlMapper::ECommands::Morph, input)) - return; - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Unmorphed: - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::MorphBall) && - CanEnterMorphBallState(mgr, 0.f)) - { - x574_morphTime = 0.f; - x578_morphDuration = 1.f; - TransitionToMorphBallState(dt, mgr); - } - else - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXwpn_invalid_action, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - break; - case EPlayerMorphBallState::Morphed: - { - zeus::CVector3f posDelta; - if (CanLeaveMorphBallState(mgr, posDelta)) - { - SetTranslation(x34_transform.origin + posDelta); - x574_morphTime = 0.f; - x578_morphDuration = 1.f; - TransitionFromMorphBallState(mgr); - } - else - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXwpn_invalid_action, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - break; - } - default: - break; - } -} - -CFirstPersonCamera& CPlayer::GetFirstPersonCamera(CStateManager& mgr) -{ - return *mgr.GetCameraManager()->GetFirstPersonCamera(); -} - -void CPlayer::UpdateGunTransform(const zeus::CVector3f& gunPos, CStateManager& mgr) -{ - float eyeHeight = GetEyeHeight(); - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - zeus::CTransform gunXf = camXf; - - zeus::CVector3f viewGunPos; - if (x2f8_morphBallState == EPlayerMorphBallState::Morphing) - viewGunPos = camXf * (gunPos - zeus::CVector3f(0.f, 0.f, eyeHeight)); - else - viewGunPos = camXf.rotate(gunPos - zeus::CVector3f(0.f, 0.f, eyeHeight)) + GetEyePosition(); - - zeus::CUnitVector3f rightDir(gunXf.basis[0]); - gunXf.origin = viewGunPos; - - switch (x498_gunHolsterState) - { - case EGunHolsterState::Drawing: - { - float liftAngle = zeus::clamp(-1.f, x49c_gunHolsterRemTime / 0.45f, 1.f); - if (liftAngle > 0.01f) - { - gunXf = zeus::CQuaternion::fromAxisAngle(rightDir, -liftAngle * - g_tweakPlayerGun->GetFixedVerticalAim()).toTransform() * - camXf.getRotation(); - gunXf.origin = viewGunPos; - } - break; - } - case EGunHolsterState::Holstered: - { - gunXf = zeus::CQuaternion::fromAxisAngle(rightDir, -g_tweakPlayerGun->GetFixedVerticalAim()).toTransform() * - camXf.getRotation(); - gunXf.origin = viewGunPos; - break; - } - case EGunHolsterState::Holstering: - { - float liftAngle = 1.f - - zeus::clamp(-1.f, x49c_gunHolsterRemTime / g_tweakPlayerGun->GetGunHolsterTime(), 1.f); - if (x2f8_morphBallState == EPlayerMorphBallState::Morphing) - liftAngle = 1.f - zeus::clamp(-1.f, x49c_gunHolsterRemTime / 0.1f, 1.f); - if (liftAngle > 0.01f) - { - gunXf = zeus::CQuaternion::fromAxisAngle(rightDir, -liftAngle * - g_tweakPlayerGun->GetFixedVerticalAim()).toTransform() * - camXf.getRotation(); - gunXf.origin = viewGunPos; - } - break; - } - default: - break; - } - - x490_gun->SetTransform(gunXf); - UpdateAimTargetPrediction(gunXf, mgr); - UpdateAssistedAiming(gunXf, mgr); -} - -void CPlayer::UpdateAssistedAiming(const zeus::CTransform& xf, const CStateManager& mgr) -{ - zeus::CTransform assistXf = xf; - if (TCastToConstPtr target = mgr.GetObjectById(x3f4_aimTarget)) - { - zeus::CVector3f gunToTarget = x480_assistedTargetAim - xf.origin; - zeus::CVector3f gunToTargetFlat = gunToTarget; - gunToTargetFlat.z() = 0.f; - float gunToTargetFlatMag = gunToTargetFlat.magnitude(); - zeus::CVector3f gunDirFlat = xf.basis[1]; - gunDirFlat.z() = 0.f; - float gunDirFlatMag = gunDirFlat.magnitude(); - if (gunToTargetFlat.canBeNormalized() && gunDirFlat.canBeNormalized()) - { - gunToTargetFlat = gunToTargetFlat / gunToTargetFlatMag; - gunDirFlat = gunDirFlat / gunDirFlatMag; - float vAngleDelta = std::atan2(gunToTarget.z(), gunToTargetFlatMag) - - std::atan2(xf.basis[1].z(), gunDirFlatMag); - bool hasVAngleDelta = true; - if (!x9c6_27_aimingAtProjectile && std::fabs(vAngleDelta) > g_tweakPlayer->GetAimAssistVerticalAngle()) - { - if (g_tweakPlayer->GetAssistedAimingIgnoreVertical()) - { - vAngleDelta = 0.f; - hasVAngleDelta = false; - } - else if (vAngleDelta > 0.f) - { - vAngleDelta = g_tweakPlayer->GetAimAssistVerticalAngle(); - } - else - { - vAngleDelta = -g_tweakPlayer->GetAimAssistVerticalAngle(); - } - } - - bool targetToLeft = gunDirFlat.cross(gunToTargetFlat).z() > 0.f; - float hAngleDelta = std::acos(zeus::clamp(-1.f, gunDirFlat.dot(gunToTargetFlat), 1.f)); - bool hasHAngleDelta = true; - if (!x9c6_27_aimingAtProjectile && std::fabs(hAngleDelta) > g_tweakPlayer->GetAimAssistHorizontalAngle()) - { - hAngleDelta = g_tweakPlayer->GetAimAssistHorizontalAngle(); - if (g_tweakPlayer->GetAssistedAimingIgnoreHorizontal()) - { - hAngleDelta = 0.f; - hasHAngleDelta = false; - } - } - - if (targetToLeft) - hAngleDelta = -hAngleDelta; - - if (!hasVAngleDelta || !hasHAngleDelta) - { - vAngleDelta = 0.f; - hAngleDelta = 0.f; - } - - gunToTarget.x() = std::sin(hAngleDelta) * std::cos(vAngleDelta); - gunToTarget.y() = std::cos(hAngleDelta) * std::cos(vAngleDelta); - gunToTarget.z() = std::sin(vAngleDelta); - gunToTarget = xf.rotate(gunToTarget); - assistXf = zeus::lookAt(zeus::CVector3f::skZero, gunToTarget, zeus::CVector3f::skUp); - } - } - - x490_gun->SetAssistAimTransform(assistXf); -} - -void CPlayer::UpdateAimTargetPrediction(const zeus::CTransform& xf, const CStateManager& mgr) -{ - if (x3f4_aimTarget != kInvalidUniqueId) - { - if (TCastToConstPtr target = mgr.GetObjectById(x3f4_aimTarget)) - { - x9c6_27_aimingAtProjectile = TCastToConstPtr(target.GetPtr()); - zeus::CVector3f instantTarget = target->GetAimPosition(mgr, 0.f); - zeus::CVector3f gunToTarget = instantTarget - xf.origin; - float timeToTarget = gunToTarget.magnitude() / x490_gun->GetBeamVelocity(); - zeus::CVector3f predictTarget = target->GetAimPosition(mgr, timeToTarget); - zeus::CVector3f predictOffset = predictTarget - instantTarget; - x3f8_targetAimPosition = instantTarget; - if (predictOffset.magnitude() < 0.1f) - x404_aimTargetAverage.AddValue(zeus::CVector3f::skZero); - else - x404_aimTargetAverage.AddValue(predictOffset); - if (auto avg = x404_aimTargetAverage.GetAverage()) - x480_assistedTargetAim = instantTarget + *avg; - else - x480_assistedTargetAim = predictTarget; - } - } -} - -void CPlayer::ResetAimTargetPrediction(TUniqueId target) -{ - if (target == kInvalidUniqueId || x3f4_aimTarget != target) - x404_aimTargetAverage.Clear(); - x3f4_aimTarget = target; -} - -void CPlayer::DrawGun(CStateManager& mgr) -{ - if (x498_gunHolsterState != EGunHolsterState::Holstered || InGrappleJumpCooldown()) - return; - x498_gunHolsterState = EGunHolsterState::Drawing; - x49c_gunHolsterRemTime = 0.45f; - x490_gun->ResetIdle(mgr); -} - -void CPlayer::HolsterGun(CStateManager& mgr) -{ - if (x498_gunHolsterState == EGunHolsterState::Holstered || - x498_gunHolsterState == EGunHolsterState::Holstering) - return; - float time = x2f8_morphBallState == EPlayerMorphBallState::Morphing ? 0.1f : - g_tweakPlayerGun->GetGunHolsterTime(); - if (x498_gunHolsterState == EGunHolsterState::Drawing) - x49c_gunHolsterRemTime = time * (1.f - x49c_gunHolsterRemTime / 0.45f); - else - x49c_gunHolsterRemTime = time; - x498_gunHolsterState = EGunHolsterState::Holstering; - x490_gun->CancelFiring(mgr); - ResetAimTargetPrediction(kInvalidUniqueId); -} - -bool CPlayer::IsMorphBallTransitioning() const -{ - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Morphing: - case EPlayerMorphBallState::Unmorphing: - return true; - default: - return false; - } -} - -void CPlayer::UpdateGrappleArmTransform(const zeus::CVector3f& offset, CStateManager& mgr, float dt) -{ - zeus::CTransform armXf = x34_transform; - zeus::CVector3f armPosition = x34_transform.rotate(offset) + x34_transform.origin; - armXf.origin = armPosition; - if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) - { - x490_gun->GetGrappleArm().SetTransform(armXf); - } - else if (!x490_gun->GetGrappleArm().IsArmMoving()) - { - zeus::CVector3f lookDir = x34_transform.basis[1]; - zeus::CVector3f armToTarget = x490_gun->GetGrappleArm().GetTransform().basis[1]; - if (lookDir.canBeNormalized()) - { - lookDir.normalize(); - if (x3b8_grappleState != EGrappleState::None) - { - if (TCastToPtr target = mgr.ObjectById(x310_orbitTargetId)) - { - armToTarget = target->GetTranslation() - armPosition; - zeus::CVector3f armToTargetFlat = armToTarget; - armToTargetFlat.z() = 0.f; - if (armToTarget.canBeNormalized()) - armToTarget.normalize(); - if (armToTargetFlat.canBeNormalized() && x3b8_grappleState != EGrappleState::Firing) - { - zeus::CQuaternion adjRot = - zeus::CQuaternion::lookAt(armToTargetFlat.normalized(), lookDir, 2.f * M_PIF); - armToTarget = adjRot.transform(armToTarget); - if (x3bc_grappleSwingTimer >= 0.25f * g_tweakPlayer->GetGrappleSwingPeriod() && - x3bc_grappleSwingTimer < 0.75f * g_tweakPlayer->GetGrappleSwingPeriod()) - armToTarget = x490_gun->GetGrappleArm().GetTransform().basis[1]; - } - } - } - armXf = zeus::lookAt(zeus::CVector3f::skZero, armToTarget, zeus::CVector3f::skUp); - armXf.origin = armPosition; - x490_gun->GetGrappleArm().SetTransform(armXf); - } - } -} - -float CPlayer::GetGravity() const -{ - if (!g_GameState->GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit) && - CheckSubmerged()) - return g_tweakPlayer->GetFluidGravAccel(); - if (x37c_sidewaysDashing) - return -100.f; - return g_tweakPlayer->GetNormalGravAccel(); -} - -void CPlayer::ApplyGrappleForces(const CFinalInput& input, CStateManager& mgr, float dt) -{ - if (TCastToPtr point = mgr.ObjectById(x310_orbitTargetId)) - { - switch (x3b8_grappleState) - { - case EGrappleState::Pull: - { - zeus::CVector3f playerToPoint = point->GetTranslation() - GetTranslation(); - if (playerToPoint.canBeNormalized()) - { - zeus::CVector3f playerToSwingLow = point->GetTranslation() + - zeus::CVector3f(0.f, 0.f, -g_tweakPlayer->GetGrappleSwingLength()) - GetTranslation(); - if (playerToSwingLow.canBeNormalized()) - { - float distToSwingLow = playerToSwingLow.magnitude(); - playerToSwingLow.normalize(); - float timeToLow = - zeus::clamp(-1.f, distToSwingLow / g_tweakPlayer->GetGrapplePullSpeedProportion(), 1.f); - float pullSpeed = timeToLow * (g_tweakPlayer->GetGrapplePullSpeedMax() - - g_tweakPlayer->GetGrapplePullSpeedMin()) + g_tweakPlayer->GetGrapplePullSpeedMin(); - SetVelocityWR(playerToSwingLow * pullSpeed); - - if (distToSwingLow < g_tweakPlayer->GetMaxGrappleLockedTurnAlignDistance()) - { - x3b8_grappleState = EGrappleState::Swinging; - x3bc_grappleSwingTimer = 0.25f * g_tweakPlayer->GetGrappleSwingPeriod(); - x3d8_grappleJumpTimeout = 0.f; - x9c6_28_aligningGrappleSwingTurn = point->GetGrappleParameters().GetLockSwingTurn(); - } - else - { - CMotionState mState = PredictMotion(dt); - zeus::CVector3f lookDirFlat = x34_transform.basis[1]; - lookDirFlat.z() = 0.f; - zeus::CVector3f newPlayerToPointFlat = - point->GetTranslation() - (GetTranslation() + mState.x0_translation); - newPlayerToPointFlat.z() = 0.f; - if (lookDirFlat.canBeNormalized()) - lookDirFlat.normalize(); - if (newPlayerToPointFlat.canBeNormalized()) - newPlayerToPointFlat.normalize(); - float lookToPointAngle = - std::acos(zeus::clamp(-1.f, lookDirFlat.dot(newPlayerToPointFlat), 1.f)); - if (lookToPointAngle > 0.001f) - { - float deltaAngle = dt * g_tweakPlayer->GetGrappleLookCenterSpeed(); - if (lookToPointAngle >= deltaAngle) - { - zeus::CVector3f leftDirFlat(lookDirFlat.y(), -lookDirFlat.x(), 0.f); - if (leftDirFlat.canBeNormalized()) - leftDirFlat.normalize(); - if (newPlayerToPointFlat.dot(leftDirFlat) >= 0.f) - deltaAngle = -deltaAngle; - RotateToOR(zeus::CQuaternion::fromAxisAngle(zeus::CVector3f::skUp, deltaAngle), dt); - } - else if (std::fabs(lookToPointAngle - M_PIF) > 0.001f) - { - RotateToOR(zeus::CQuaternion::shortestRotationArc(lookDirFlat, - newPlayerToPointFlat), dt); - } - } - else - { - SetAngularVelocityWR(zeus::CAxisAngle::sIdentity); - x174_torque = zeus::CAxisAngle::sIdentity; - } - } - } - else - { - x3b8_grappleState = EGrappleState::Swinging; - x3bc_grappleSwingTimer = 0.25f * g_tweakPlayer->GetGrappleSwingPeriod(); - x3d8_grappleJumpTimeout = 0.f; - } - } - break; - } - case EGrappleState::Swinging: - { - float turnAngleSpeed = zeus::degToRad(g_tweakPlayer->GetMaxGrappleTurnSpeed()); - if (g_tweakPlayer->GetInvertGrappleTurn()) - turnAngleSpeed *= -1.f; - zeus::CVector3f pointToPlayer = GetTranslation() - point->GetTranslation(); - float pointToPlayerZProj = - zeus::clamp(-1.f, std::fabs(pointToPlayer.z() / pointToPlayer.magnitude()), 1.f); - - bool enableTurn = false; - if (!point->GetGrappleParameters().GetLockSwingTurn()) - { - if (ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input) > 0.05f) - { - enableTurn = true; - turnAngleSpeed *= -ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input); - } - if (ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) > 0.05f) - { - enableTurn = true; - turnAngleSpeed *= ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input); - } - } - else if (x9c6_28_aligningGrappleSwingTurn) - { - enableTurn = true; - } - - x3bc_grappleSwingTimer += dt; - if (x3bc_grappleSwingTimer > g_tweakPlayer->GetGrappleSwingPeriod()) - x3bc_grappleSwingTimer -= g_tweakPlayer->GetGrappleSwingPeriod(); - - zeus::CVector3f swingAxis = x3c0_grappleSwingAxis; - if (x3bc_grappleSwingTimer < 0.5f * g_tweakPlayer->GetGrappleSwingPeriod()) - swingAxis *= zeus::CVector3f::skNegOne; - - float pullSpeed = std::fabs(zeus::clamp(-1.f, - std::cos(2.f * M_PIF * (x3bc_grappleSwingTimer / g_tweakPlayer->GetGrappleSwingPeriod()) + - (M_PIF / 2.f)), 1.f)) * g_tweakPlayer->GetGrapplePullSpeedMin(); - zeus::CVector3f pullVec = pointToPlayer.normalized().cross(swingAxis) * pullSpeed; - pullVec += pointToPlayer * zeus::clamp(-1.f, (pointToPlayer.magnitude() - - g_tweakPlayer->GetGrappleSwingLength()) / - g_tweakPlayer->GetGrappleSwingLength(), 1.f) * -32.f * pointToPlayerZProj; - zeus::CVector3f backupVel = x138_velocity; - SetVelocityWR(pullVec); - - zeus::CTransform backupXf = x34_transform; - CMotionState predMotion = PredictMotion(dt); - zeus::CVector3f newPos = x34_transform.origin + predMotion.x0_translation; - if (ValidateFPPosition(newPos, mgr)) - { - if (enableTurn) - { - zeus::CQuaternion turnRot; - turnRot.rotateZ(turnAngleSpeed * dt); - if (point->GetGrappleParameters().GetLockSwingTurn() && x9c6_28_aligningGrappleSwingTurn) - { - zeus::CVector3f pointDir = point->GetTransform().basis[1].normalized(); - zeus::CVector3f playerDir = x34_transform.basis[1].normalized(); - float playerPointProj = zeus::clamp(-1.f, playerDir.dot(pointDir), 1.f); - if (std::fabs(playerPointProj) == 1.f) - x9c6_28_aligningGrappleSwingTurn = false; - if (playerPointProj < 0.f) - { - playerPointProj = -playerPointProj; - pointDir = -pointDir; - } - float turnAngleAdj = std::acos(playerPointProj) * dt; - turnRot = zeus::CQuaternion::lookAt(playerDir, pointDir, turnAngleAdj); - } - if (pointToPlayer.magSquared() > 0.04f) - { - zeus::CVector3f pointToPlayerFlat = pointToPlayer; - pointToPlayerFlat.z() = 0.f; - zeus::CVector3f pointAtPlayerHeight = point->GetTranslation(); - pointAtPlayerHeight.z() = GetTranslation().z(); - zeus::CVector3f playerToGrapplePlane = - pointAtPlayerHeight + turnRot.transform(pointToPlayerFlat) - GetTranslation(); - if (playerToGrapplePlane.canBeNormalized()) - pullVec += playerToGrapplePlane / dt; - } - zeus::CVector3f swingAxisBackup = x3c0_grappleSwingAxis; - x3c0_grappleSwingAxis = turnRot.transform(x3c0_grappleSwingAxis); - x3c0_grappleSwingAxis.normalize(); - zeus::CVector3f swingForward(-x3c0_grappleSwingAxis.y(), x3c0_grappleSwingAxis.x(), 0.f); - SetTransform( - zeus::CTransform(x3c0_grappleSwingAxis, swingForward, zeus::CVector3f::skUp, GetTranslation())); - SetVelocityWR(pullVec); - - if (!ValidateFPPosition(GetTranslation(), mgr)) - { - x3c0_grappleSwingAxis = swingAxisBackup; - SetTransform(backupXf); - SetVelocityWR(backupVel); - } - } - } - else - { - BreakGrapple(EPlayerOrbitRequest::InvalidateTarget, mgr); - } - break; - } - case EGrappleState::JumpOff: - { - zeus::CVector3f gravForce = {0.f, 0.f, GetGravity() * xe8_mass}; - ApplyForceOR(gravForce, zeus::CAxisAngle::sIdentity); - break; - } - default: - break; - } - } - - zeus::CVector3f newAngVel = {0.f, 0.f, 0.9f * GetAngularVelocityOR().getVector().z()}; - SetAngularVelocityOR(newAngVel); -} - -bool CPlayer::ValidateFPPosition(const zeus::CVector3f& pos, CStateManager& mgr) -{ - CMaterialFilter solidFilter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid}); - zeus::CAABox aabb(x2d8_fpBounds.min - 1.f + pos, x2d8_fpBounds.max + 1.f + pos); - rstl::reserved_vector nearList; - mgr.BuildColliderList(nearList, *this, aabb); - CCollidableAABox colAABB({GetBaseBoundingBox().min + pos, GetBaseBoundingBox().max + pos}, {}); - return !CGameCollision::DetectCollisionBoolean(mgr, colAABB, zeus::CTransform::Identity(), solidFilter, nearList); -} - -void CPlayer::UpdateGrappleState(const CFinalInput& input, CStateManager& mgr) -{ - if (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam) || - x2f8_morphBallState == EPlayerMorphBallState::Morphed || - mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan || - mgr.GetPlayerState()->GetTransitioningVisor() == CPlayerState::EPlayerVisor::Scan) - return; - - if (x310_orbitTargetId == kInvalidUniqueId) - { - x3b8_grappleState = EGrappleState::None; - AddMaterial(EMaterialTypes::GroundCollider, mgr); - return; - } - - TCastToPtr point = mgr.ObjectById(x310_orbitTargetId); - if (point) - { - zeus::CVector3f eyePosition = GetEyePosition(); - zeus::CVector3f playerToPoint = point->GetTranslation() - eyePosition; - zeus::CVector3f playerToPointFlat = playerToPoint; - playerToPointFlat.z() = 0.f; - if (playerToPoint.canBeNormalized() && playerToPointFlat.canBeNormalized() && - playerToPointFlat.magnitude() > 2.f) - { - switch (x304_orbitState) - { - case EPlayerOrbitState::Grapple: - switch (g_tweakPlayer->GetGrappleJumpMode()) - { - case 0: - case 1: - if (ControlMapper::GetPressInput(ControlMapper::ECommands::FireOrBomb, input)) - { - if (TCastToPtr point2 = mgr.ObjectById(x33c_orbitNextTargetId)) - { - playerToPoint = point2->GetTranslation() - eyePosition; - playerToPoint.z() = 0.f; - if (playerToPoint.canBeNormalized()) - { - x490_gun->GetGrappleArm().GrappleBeamDisconnected(); - x3c0_grappleSwingAxis.x() = float(playerToPoint.y()); - x3c0_grappleSwingAxis.y() = -playerToPoint.x(); - x3c0_grappleSwingAxis.normalize(); - x3bc_grappleSwingTimer = 0.f; - SetOrbitTargetId(x33c_orbitNextTargetId, mgr); - x3b8_grappleState = EGrappleState::Pull; - x33c_orbitNextTargetId = kInvalidUniqueId; - x490_gun->GetGrappleArm().GrappleBeamConnected(); - } - } - else - { - if (g_tweakPlayer->GetGrappleJumpMode() == 0 && x3d8_grappleJumpTimeout <= 0.f) - ApplyGrappleJump(mgr); - BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); - } - } - break; - default: - break; - } - - break; - case EPlayerOrbitState::OrbitObject: - if (playerToPoint.canBeNormalized()) - { - CRayCastResult result = - mgr.RayStaticIntersection(eyePosition, playerToPoint.normalized(), playerToPoint.magnitude(), - LineOfSightFilter); - if (result.IsInvalid()) - { - HolsterGun(mgr); - switch (x3b8_grappleState) - { - case EGrappleState::Firing: - case EGrappleState::Swinging: - switch (g_tweakPlayer->GetGrappleJumpMode()) - { - case 0: - switch (x490_gun->GetGrappleArm().GetAnimState()) - { - case CGrappleArm::EArmState::IntoGrappleIdle: - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input)) - x490_gun->GetGrappleArm().SetAnimState(CGrappleArm::EArmState::FireGrapple); - break; - case CGrappleArm::EArmState::Connected: - BeginGrapple(playerToPoint, mgr); - break; - default: - break; - } - break; - case 1: - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input)) - { - switch (x490_gun->GetGrappleArm().GetAnimState()) - { - case CGrappleArm::EArmState::IntoGrappleIdle: - x490_gun->GetGrappleArm().SetAnimState(CGrappleArm::EArmState::FireGrapple); - break; - case CGrappleArm::EArmState::Connected: - BeginGrapple(playerToPoint, mgr); - break; - default: - break; - } - break; - } - break; - case 2: - switch (x490_gun->GetGrappleArm().GetAnimState()) - { - case CGrappleArm::EArmState::IntoGrappleIdle: - x490_gun->GetGrappleArm().SetAnimState(CGrappleArm::EArmState::FireGrapple); - break; - case CGrappleArm::EArmState::Connected: - BeginGrapple(playerToPoint, mgr); - break; - default: - break; - } - break; - default: - break; - } - break; - case EGrappleState::None: - x3b8_grappleState = EGrappleState::Firing; - x490_gun->GetGrappleArm().Activate(true); - break; - default: - break; - } - } - } - break; - default: - break; - } - } - } - - if (x304_orbitState != EPlayerOrbitState::Grapple) - { - if (x304_orbitState >= EPlayerOrbitState::Grapple) - return; - if (x304_orbitState != EPlayerOrbitState::OrbitObject) - return; - } - else - { - if (!point) - { - BreakGrapple(EPlayerOrbitRequest::Default, mgr); - return; - } - - switch (g_tweakPlayer->GetGrappleJumpMode()) - { - case 0: - if (x3b8_grappleState == EGrappleState::JumpOff) - { - x3d8_grappleJumpTimeout -= input.DeltaTime(); - if (x3d8_grappleJumpTimeout <= 0.f) - { - BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); - SetMoveState(EPlayerMovementState::ApplyJump, mgr); - ComputeMovement(input, mgr, input.DeltaTime()); - PreventFallingCameraPitch(); - } - } - break; - case 1: - switch (x3b8_grappleState) - { - case EGrappleState::Swinging: - if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) && - x3d8_grappleJumpTimeout <= 0.f) - { - x3d8_grappleJumpTimeout = g_tweakPlayer->GetGrappleReleaseTime(); - x3b8_grappleState = EGrappleState::JumpOff; - ApplyGrappleJump(mgr); - } - break; - case EGrappleState::JumpOff: - x3d8_grappleJumpTimeout -= input.DeltaTime(); - if (x3d8_grappleJumpTimeout <= 0.f) - { - SetMoveState(EPlayerMovementState::ApplyJump, mgr); - ComputeMovement(input, mgr, input.DeltaTime()); - BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); - PreventFallingCameraPitch(); - } - break; - case EGrappleState::Firing: - case EGrappleState::Pull: - if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input)) - BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); - break; - default: - break; - } - break; - default: - break; - } - - zeus::CVector3f eyePos = GetEyePosition(); - zeus::CVector3f playerToPoint = point->GetTranslation() - eyePos; - if (playerToPoint.canBeNormalized()) - { - CRayCastResult result = - mgr.RayStaticIntersection(eyePos, playerToPoint.normalized(), playerToPoint.magnitude(), - LineOfSightFilter); - if (result.IsValid()) - { - BreakGrapple(EPlayerOrbitRequest::LostGrappleLineOfSight, mgr); - } - } - return; - } - - if (x490_gun->GetGrappleArm().BeamActive() && g_tweakPlayer->GetGrappleJumpMode() == 1 && - !ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input)) - BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); -} - -void CPlayer::ApplyGrappleJump(CStateManager& mgr) -{ - if (TCastToPtr point = mgr.ObjectById(x310_orbitTargetId)) - { - zeus::CVector3f tmp = x3c0_grappleSwingAxis; - if (x3bc_grappleSwingTimer < 0.5f * g_tweakPlayer->GetGrappleSwingPeriod()) - tmp *= zeus::CVector3f::skNegOne; - zeus::CVector3f pointToPlayer = GetTranslation() - point->GetTranslation(); - zeus::CVector3f cross = pointToPlayer.normalized().cross(tmp); - zeus::CVector3f pointToPlayerFlat(pointToPlayer.x(), pointToPlayer.y(), 0.f); - float dot = 1.f; - if (pointToPlayerFlat.canBeNormalized() && cross.canBeNormalized()) - dot = zeus::clamp(-1.f, std::fabs(cross.normalized().dot(pointToPlayerFlat.normalized())), 1.f); - ApplyForceWR(g_tweakPlayer->GetGrappleJumpForce() * cross * 10000.f * dot, zeus::CAxisAngle::sIdentity); - } -} - -void CPlayer::BeginGrapple(zeus::CVector3f& vec, CStateManager& mgr) -{ - vec.z() = 0.f; - if (vec.canBeNormalized()) - { - x3c0_grappleSwingAxis.x() = float(vec.y()); - x3c0_grappleSwingAxis.y() = -vec.x(); - x3c0_grappleSwingAxis.normalize(); - x3bc_grappleSwingTimer = 0.f; - SetOrbitState(EPlayerOrbitState::Grapple, mgr); - x3b8_grappleState = EGrappleState::Pull; - RemoveMaterial(EMaterialTypes::GroundCollider, mgr); - } -} - -void CPlayer::BreakGrapple(EPlayerOrbitRequest req, CStateManager& mgr) -{ +void CPlayer::UpdateCameraTimers(float dt, const CFinalInput& input) { + if (x3dc_inFreeLook || x3dd_lookButtonHeld) { x294_jumpCameraTimer = 0.f; x29c_fallCameraTimer = 0.f; - if (g_tweakPlayer->GetGrappleJumpMode() == 2 && x3b8_grappleState == EGrappleState::Swinging) - { - ApplyGrappleJump(mgr); - PreventFallingCameraPitch(); - } + return; + } - SetOrbitRequest(req, mgr); + if (g_tweakPlayer->GetFiringCancelsCameraPitch()) { + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) || + ControlMapper::GetDigitalInput(ControlMapper::ECommands::MissileOrPowerBomb, input)) { + if (x288_startingJumpTimeout > 0.f) { + x2a4_cancelCameraPitch = true; + return; + } + } + } + + if (ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) + ++x298_jumpPresses; + + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) && x294_jumpCameraTimer > 0.f && + !x2a4_cancelCameraPitch && x298_jumpPresses <= 2) + x294_jumpCameraTimer += dt; + + if (x29c_fallCameraTimer > 0.f && !x2a4_cancelCameraPitch) + x29c_fallCameraTimer += dt; +} + +void CPlayer::UpdateMorphBallState(float dt, const CFinalInput& input, CStateManager& mgr) { + if (!ControlMapper::GetPressInput(ControlMapper::ECommands::Morph, input)) + return; + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Unmorphed: + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::MorphBall) && CanEnterMorphBallState(mgr, 0.f)) { + x574_morphTime = 0.f; + x578_morphDuration = 1.f; + TransitionToMorphBallState(dt, mgr); + } else { + CSfxHandle hnd = CSfxManager::SfxStart(SFXwpn_invalid_action, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } + break; + case EPlayerMorphBallState::Morphed: { + zeus::CVector3f posDelta; + if (CanLeaveMorphBallState(mgr, posDelta)) { + SetTranslation(x34_transform.origin + posDelta); + x574_morphTime = 0.f; + x578_morphDuration = 1.f; + TransitionFromMorphBallState(mgr); + } else { + CSfxHandle hnd = CSfxManager::SfxStart(SFXwpn_invalid_action, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } + break; + } + default: + break; + } +} + +CFirstPersonCamera& CPlayer::GetFirstPersonCamera(CStateManager& mgr) { + return *mgr.GetCameraManager()->GetFirstPersonCamera(); +} + +void CPlayer::UpdateGunTransform(const zeus::CVector3f& gunPos, CStateManager& mgr) { + float eyeHeight = GetEyeHeight(); + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + zeus::CTransform gunXf = camXf; + + zeus::CVector3f viewGunPos; + if (x2f8_morphBallState == EPlayerMorphBallState::Morphing) + viewGunPos = camXf * (gunPos - zeus::CVector3f(0.f, 0.f, eyeHeight)); + else + viewGunPos = camXf.rotate(gunPos - zeus::CVector3f(0.f, 0.f, eyeHeight)) + GetEyePosition(); + + zeus::CUnitVector3f rightDir(gunXf.basis[0]); + gunXf.origin = viewGunPos; + + switch (x498_gunHolsterState) { + case EGunHolsterState::Drawing: { + float liftAngle = zeus::clamp(-1.f, x49c_gunHolsterRemTime / 0.45f, 1.f); + if (liftAngle > 0.01f) { + gunXf = zeus::CQuaternion::fromAxisAngle(rightDir, -liftAngle * g_tweakPlayerGun->GetFixedVerticalAim()) + .toTransform() * + camXf.getRotation(); + gunXf.origin = viewGunPos; + } + break; + } + case EGunHolsterState::Holstered: { + gunXf = zeus::CQuaternion::fromAxisAngle(rightDir, -g_tweakPlayerGun->GetFixedVerticalAim()).toTransform() * + camXf.getRotation(); + gunXf.origin = viewGunPos; + break; + } + case EGunHolsterState::Holstering: { + float liftAngle = 1.f - zeus::clamp(-1.f, x49c_gunHolsterRemTime / g_tweakPlayerGun->GetGunHolsterTime(), 1.f); + if (x2f8_morphBallState == EPlayerMorphBallState::Morphing) + liftAngle = 1.f - zeus::clamp(-1.f, x49c_gunHolsterRemTime / 0.1f, 1.f); + if (liftAngle > 0.01f) { + gunXf = zeus::CQuaternion::fromAxisAngle(rightDir, -liftAngle * g_tweakPlayerGun->GetFixedVerticalAim()) + .toTransform() * + camXf.getRotation(); + gunXf.origin = viewGunPos; + } + break; + } + default: + break; + } + + x490_gun->SetTransform(gunXf); + UpdateAimTargetPrediction(gunXf, mgr); + UpdateAssistedAiming(gunXf, mgr); +} + +void CPlayer::UpdateAssistedAiming(const zeus::CTransform& xf, const CStateManager& mgr) { + zeus::CTransform assistXf = xf; + if (TCastToConstPtr target = mgr.GetObjectById(x3f4_aimTarget)) { + zeus::CVector3f gunToTarget = x480_assistedTargetAim - xf.origin; + zeus::CVector3f gunToTargetFlat = gunToTarget; + gunToTargetFlat.z() = 0.f; + float gunToTargetFlatMag = gunToTargetFlat.magnitude(); + zeus::CVector3f gunDirFlat = xf.basis[1]; + gunDirFlat.z() = 0.f; + float gunDirFlatMag = gunDirFlat.magnitude(); + if (gunToTargetFlat.canBeNormalized() && gunDirFlat.canBeNormalized()) { + gunToTargetFlat = gunToTargetFlat / gunToTargetFlatMag; + gunDirFlat = gunDirFlat / gunDirFlatMag; + float vAngleDelta = std::atan2(gunToTarget.z(), gunToTargetFlatMag) - std::atan2(xf.basis[1].z(), gunDirFlatMag); + bool hasVAngleDelta = true; + if (!x9c6_27_aimingAtProjectile && std::fabs(vAngleDelta) > g_tweakPlayer->GetAimAssistVerticalAngle()) { + if (g_tweakPlayer->GetAssistedAimingIgnoreVertical()) { + vAngleDelta = 0.f; + hasVAngleDelta = false; + } else if (vAngleDelta > 0.f) { + vAngleDelta = g_tweakPlayer->GetAimAssistVerticalAngle(); + } else { + vAngleDelta = -g_tweakPlayer->GetAimAssistVerticalAngle(); + } + } + + bool targetToLeft = gunDirFlat.cross(gunToTargetFlat).z() > 0.f; + float hAngleDelta = std::acos(zeus::clamp(-1.f, gunDirFlat.dot(gunToTargetFlat), 1.f)); + bool hasHAngleDelta = true; + if (!x9c6_27_aimingAtProjectile && std::fabs(hAngleDelta) > g_tweakPlayer->GetAimAssistHorizontalAngle()) { + hAngleDelta = g_tweakPlayer->GetAimAssistHorizontalAngle(); + if (g_tweakPlayer->GetAssistedAimingIgnoreHorizontal()) { + hAngleDelta = 0.f; + hasHAngleDelta = false; + } + } + + if (targetToLeft) + hAngleDelta = -hAngleDelta; + + if (!hasVAngleDelta || !hasHAngleDelta) { + vAngleDelta = 0.f; + hAngleDelta = 0.f; + } + + gunToTarget.x() = std::sin(hAngleDelta) * std::cos(vAngleDelta); + gunToTarget.y() = std::cos(hAngleDelta) * std::cos(vAngleDelta); + gunToTarget.z() = std::sin(vAngleDelta); + gunToTarget = xf.rotate(gunToTarget); + assistXf = zeus::lookAt(zeus::CVector3f::skZero, gunToTarget, zeus::CVector3f::skUp); + } + } + + x490_gun->SetAssistAimTransform(assistXf); +} + +void CPlayer::UpdateAimTargetPrediction(const zeus::CTransform& xf, const CStateManager& mgr) { + if (x3f4_aimTarget != kInvalidUniqueId) { + if (TCastToConstPtr target = mgr.GetObjectById(x3f4_aimTarget)) { + x9c6_27_aimingAtProjectile = TCastToConstPtr(target.GetPtr()); + zeus::CVector3f instantTarget = target->GetAimPosition(mgr, 0.f); + zeus::CVector3f gunToTarget = instantTarget - xf.origin; + float timeToTarget = gunToTarget.magnitude() / x490_gun->GetBeamVelocity(); + zeus::CVector3f predictTarget = target->GetAimPosition(mgr, timeToTarget); + zeus::CVector3f predictOffset = predictTarget - instantTarget; + x3f8_targetAimPosition = instantTarget; + if (predictOffset.magnitude() < 0.1f) + x404_aimTargetAverage.AddValue(zeus::CVector3f::skZero); + else + x404_aimTargetAverage.AddValue(predictOffset); + if (auto avg = x404_aimTargetAverage.GetAverage()) + x480_assistedTargetAim = instantTarget + *avg; + else + x480_assistedTargetAim = predictTarget; + } + } +} + +void CPlayer::ResetAimTargetPrediction(TUniqueId target) { + if (target == kInvalidUniqueId || x3f4_aimTarget != target) + x404_aimTargetAverage.Clear(); + x3f4_aimTarget = target; +} + +void CPlayer::DrawGun(CStateManager& mgr) { + if (x498_gunHolsterState != EGunHolsterState::Holstered || InGrappleJumpCooldown()) + return; + x498_gunHolsterState = EGunHolsterState::Drawing; + x49c_gunHolsterRemTime = 0.45f; + x490_gun->ResetIdle(mgr); +} + +void CPlayer::HolsterGun(CStateManager& mgr) { + if (x498_gunHolsterState == EGunHolsterState::Holstered || x498_gunHolsterState == EGunHolsterState::Holstering) + return; + float time = x2f8_morphBallState == EPlayerMorphBallState::Morphing ? 0.1f : g_tweakPlayerGun->GetGunHolsterTime(); + if (x498_gunHolsterState == EGunHolsterState::Drawing) + x49c_gunHolsterRemTime = time * (1.f - x49c_gunHolsterRemTime / 0.45f); + else + x49c_gunHolsterRemTime = time; + x498_gunHolsterState = EGunHolsterState::Holstering; + x490_gun->CancelFiring(mgr); + ResetAimTargetPrediction(kInvalidUniqueId); +} + +bool CPlayer::IsMorphBallTransitioning() const { + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Morphing: + case EPlayerMorphBallState::Unmorphing: + return true; + default: + return false; + } +} + +void CPlayer::UpdateGrappleArmTransform(const zeus::CVector3f& offset, CStateManager& mgr, float dt) { + zeus::CTransform armXf = x34_transform; + zeus::CVector3f armPosition = x34_transform.rotate(offset) + x34_transform.origin; + armXf.origin = armPosition; + if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) { + x490_gun->GetGrappleArm().SetTransform(armXf); + } else if (!x490_gun->GetGrappleArm().IsArmMoving()) { + zeus::CVector3f lookDir = x34_transform.basis[1]; + zeus::CVector3f armToTarget = x490_gun->GetGrappleArm().GetTransform().basis[1]; + if (lookDir.canBeNormalized()) { + lookDir.normalize(); + if (x3b8_grappleState != EGrappleState::None) { + if (TCastToPtr target = mgr.ObjectById(x310_orbitTargetId)) { + armToTarget = target->GetTranslation() - armPosition; + zeus::CVector3f armToTargetFlat = armToTarget; + armToTargetFlat.z() = 0.f; + if (armToTarget.canBeNormalized()) + armToTarget.normalize(); + if (armToTargetFlat.canBeNormalized() && x3b8_grappleState != EGrappleState::Firing) { + zeus::CQuaternion adjRot = zeus::CQuaternion::lookAt(armToTargetFlat.normalized(), lookDir, 2.f * M_PIF); + armToTarget = adjRot.transform(armToTarget); + if (x3bc_grappleSwingTimer >= 0.25f * g_tweakPlayer->GetGrappleSwingPeriod() && + x3bc_grappleSwingTimer < 0.75f * g_tweakPlayer->GetGrappleSwingPeriod()) + armToTarget = x490_gun->GetGrappleArm().GetTransform().basis[1]; + } + } + } + armXf = zeus::lookAt(zeus::CVector3f::skZero, armToTarget, zeus::CVector3f::skUp); + armXf.origin = armPosition; + x490_gun->GetGrappleArm().SetTransform(armXf); + } + } +} + +float CPlayer::GetGravity() const { + if (!g_GameState->GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit) && CheckSubmerged()) + return g_tweakPlayer->GetFluidGravAccel(); + if (x37c_sidewaysDashing) + return -100.f; + return g_tweakPlayer->GetNormalGravAccel(); +} + +void CPlayer::ApplyGrappleForces(const CFinalInput& input, CStateManager& mgr, float dt) { + if (TCastToPtr point = mgr.ObjectById(x310_orbitTargetId)) { + switch (x3b8_grappleState) { + case EGrappleState::Pull: { + zeus::CVector3f playerToPoint = point->GetTranslation() - GetTranslation(); + if (playerToPoint.canBeNormalized()) { + zeus::CVector3f playerToSwingLow = point->GetTranslation() + + zeus::CVector3f(0.f, 0.f, -g_tweakPlayer->GetGrappleSwingLength()) - + GetTranslation(); + if (playerToSwingLow.canBeNormalized()) { + float distToSwingLow = playerToSwingLow.magnitude(); + playerToSwingLow.normalize(); + float timeToLow = zeus::clamp(-1.f, distToSwingLow / g_tweakPlayer->GetGrapplePullSpeedProportion(), 1.f); + float pullSpeed = + timeToLow * (g_tweakPlayer->GetGrapplePullSpeedMax() - g_tweakPlayer->GetGrapplePullSpeedMin()) + + g_tweakPlayer->GetGrapplePullSpeedMin(); + SetVelocityWR(playerToSwingLow * pullSpeed); + + if (distToSwingLow < g_tweakPlayer->GetMaxGrappleLockedTurnAlignDistance()) { + x3b8_grappleState = EGrappleState::Swinging; + x3bc_grappleSwingTimer = 0.25f * g_tweakPlayer->GetGrappleSwingPeriod(); + x3d8_grappleJumpTimeout = 0.f; + x9c6_28_aligningGrappleSwingTurn = point->GetGrappleParameters().GetLockSwingTurn(); + } else { + CMotionState mState = PredictMotion(dt); + zeus::CVector3f lookDirFlat = x34_transform.basis[1]; + lookDirFlat.z() = 0.f; + zeus::CVector3f newPlayerToPointFlat = point->GetTranslation() - (GetTranslation() + mState.x0_translation); + newPlayerToPointFlat.z() = 0.f; + if (lookDirFlat.canBeNormalized()) + lookDirFlat.normalize(); + if (newPlayerToPointFlat.canBeNormalized()) + newPlayerToPointFlat.normalize(); + float lookToPointAngle = std::acos(zeus::clamp(-1.f, lookDirFlat.dot(newPlayerToPointFlat), 1.f)); + if (lookToPointAngle > 0.001f) { + float deltaAngle = dt * g_tweakPlayer->GetGrappleLookCenterSpeed(); + if (lookToPointAngle >= deltaAngle) { + zeus::CVector3f leftDirFlat(lookDirFlat.y(), -lookDirFlat.x(), 0.f); + if (leftDirFlat.canBeNormalized()) + leftDirFlat.normalize(); + if (newPlayerToPointFlat.dot(leftDirFlat) >= 0.f) + deltaAngle = -deltaAngle; + RotateToOR(zeus::CQuaternion::fromAxisAngle(zeus::CVector3f::skUp, deltaAngle), dt); + } else if (std::fabs(lookToPointAngle - M_PIF) > 0.001f) { + RotateToOR(zeus::CQuaternion::shortestRotationArc(lookDirFlat, newPlayerToPointFlat), dt); + } + } else { + SetAngularVelocityWR(zeus::CAxisAngle::sIdentity); + x174_torque = zeus::CAxisAngle::sIdentity; + } + } + } else { + x3b8_grappleState = EGrappleState::Swinging; + x3bc_grappleSwingTimer = 0.25f * g_tweakPlayer->GetGrappleSwingPeriod(); + x3d8_grappleJumpTimeout = 0.f; + } + } + break; + } + case EGrappleState::Swinging: { + float turnAngleSpeed = zeus::degToRad(g_tweakPlayer->GetMaxGrappleTurnSpeed()); + if (g_tweakPlayer->GetInvertGrappleTurn()) + turnAngleSpeed *= -1.f; + zeus::CVector3f pointToPlayer = GetTranslation() - point->GetTranslation(); + float pointToPlayerZProj = zeus::clamp(-1.f, std::fabs(pointToPlayer.z() / pointToPlayer.magnitude()), 1.f); + + bool enableTurn = false; + if (!point->GetGrappleParameters().GetLockSwingTurn()) { + if (ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input) > 0.05f) { + enableTurn = true; + turnAngleSpeed *= -ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input); + } + if (ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) > 0.05f) { + enableTurn = true; + turnAngleSpeed *= ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input); + } + } else if (x9c6_28_aligningGrappleSwingTurn) { + enableTurn = true; + } + + x3bc_grappleSwingTimer += dt; + if (x3bc_grappleSwingTimer > g_tweakPlayer->GetGrappleSwingPeriod()) + x3bc_grappleSwingTimer -= g_tweakPlayer->GetGrappleSwingPeriod(); + + zeus::CVector3f swingAxis = x3c0_grappleSwingAxis; + if (x3bc_grappleSwingTimer < 0.5f * g_tweakPlayer->GetGrappleSwingPeriod()) + swingAxis *= zeus::CVector3f::skNegOne; + + float pullSpeed = + std::fabs(zeus::clamp( + -1.f, + std::cos(2.f * M_PIF * (x3bc_grappleSwingTimer / g_tweakPlayer->GetGrappleSwingPeriod()) + (M_PIF / 2.f)), + 1.f)) * + g_tweakPlayer->GetGrapplePullSpeedMin(); + zeus::CVector3f pullVec = pointToPlayer.normalized().cross(swingAxis) * pullSpeed; + pullVec += pointToPlayer * + zeus::clamp(-1.f, + (pointToPlayer.magnitude() - g_tweakPlayer->GetGrappleSwingLength()) / + g_tweakPlayer->GetGrappleSwingLength(), + 1.f) * + -32.f * pointToPlayerZProj; + zeus::CVector3f backupVel = x138_velocity; + SetVelocityWR(pullVec); + + zeus::CTransform backupXf = x34_transform; + CMotionState predMotion = PredictMotion(dt); + zeus::CVector3f newPos = x34_transform.origin + predMotion.x0_translation; + if (ValidateFPPosition(newPos, mgr)) { + if (enableTurn) { + zeus::CQuaternion turnRot; + turnRot.rotateZ(turnAngleSpeed * dt); + if (point->GetGrappleParameters().GetLockSwingTurn() && x9c6_28_aligningGrappleSwingTurn) { + zeus::CVector3f pointDir = point->GetTransform().basis[1].normalized(); + zeus::CVector3f playerDir = x34_transform.basis[1].normalized(); + float playerPointProj = zeus::clamp(-1.f, playerDir.dot(pointDir), 1.f); + if (std::fabs(playerPointProj) == 1.f) + x9c6_28_aligningGrappleSwingTurn = false; + if (playerPointProj < 0.f) { + playerPointProj = -playerPointProj; + pointDir = -pointDir; + } + float turnAngleAdj = std::acos(playerPointProj) * dt; + turnRot = zeus::CQuaternion::lookAt(playerDir, pointDir, turnAngleAdj); + } + if (pointToPlayer.magSquared() > 0.04f) { + zeus::CVector3f pointToPlayerFlat = pointToPlayer; + pointToPlayerFlat.z() = 0.f; + zeus::CVector3f pointAtPlayerHeight = point->GetTranslation(); + pointAtPlayerHeight.z() = GetTranslation().z(); + zeus::CVector3f playerToGrapplePlane = + pointAtPlayerHeight + turnRot.transform(pointToPlayerFlat) - GetTranslation(); + if (playerToGrapplePlane.canBeNormalized()) + pullVec += playerToGrapplePlane / dt; + } + zeus::CVector3f swingAxisBackup = x3c0_grappleSwingAxis; + x3c0_grappleSwingAxis = turnRot.transform(x3c0_grappleSwingAxis); + x3c0_grappleSwingAxis.normalize(); + zeus::CVector3f swingForward(-x3c0_grappleSwingAxis.y(), x3c0_grappleSwingAxis.x(), 0.f); + SetTransform(zeus::CTransform(x3c0_grappleSwingAxis, swingForward, zeus::CVector3f::skUp, GetTranslation())); + SetVelocityWR(pullVec); + + if (!ValidateFPPosition(GetTranslation(), mgr)) { + x3c0_grappleSwingAxis = swingAxisBackup; + SetTransform(backupXf); + SetVelocityWR(backupVel); + } + } + } else { + BreakGrapple(EPlayerOrbitRequest::InvalidateTarget, mgr); + } + break; + } + case EGrappleState::JumpOff: { + zeus::CVector3f gravForce = {0.f, 0.f, GetGravity() * xe8_mass}; + ApplyForceOR(gravForce, zeus::CAxisAngle::sIdentity); + break; + } + default: + break; + } + } + + zeus::CVector3f newAngVel = {0.f, 0.f, 0.9f * GetAngularVelocityOR().getVector().z()}; + SetAngularVelocityOR(newAngVel); +} + +bool CPlayer::ValidateFPPosition(const zeus::CVector3f& pos, CStateManager& mgr) { + CMaterialFilter solidFilter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid}); + zeus::CAABox aabb(x2d8_fpBounds.min - 1.f + pos, x2d8_fpBounds.max + 1.f + pos); + rstl::reserved_vector nearList; + mgr.BuildColliderList(nearList, *this, aabb); + CCollidableAABox colAABB({GetBaseBoundingBox().min + pos, GetBaseBoundingBox().max + pos}, {}); + return !CGameCollision::DetectCollisionBoolean(mgr, colAABB, zeus::CTransform::Identity(), solidFilter, nearList); +} + +void CPlayer::UpdateGrappleState(const CFinalInput& input, CStateManager& mgr) { + if (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam) || + x2f8_morphBallState == EPlayerMorphBallState::Morphed || + mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan || + mgr.GetPlayerState()->GetTransitioningVisor() == CPlayerState::EPlayerVisor::Scan) + return; + + if (x310_orbitTargetId == kInvalidUniqueId) { x3b8_grappleState = EGrappleState::None; AddMaterial(EMaterialTypes::GroundCollider, mgr); - x490_gun->GetGrappleArm().SetAnimState(CGrappleArm::EArmState::OutOfGrapple); - if (!InGrappleJumpCooldown() && x3b8_grappleState != EGrappleState::JumpOff) - DrawGun(mgr); -} + return; + } + + TCastToPtr point = mgr.ObjectById(x310_orbitTargetId); + if (point) { + zeus::CVector3f eyePosition = GetEyePosition(); + zeus::CVector3f playerToPoint = point->GetTranslation() - eyePosition; + zeus::CVector3f playerToPointFlat = playerToPoint; + playerToPointFlat.z() = 0.f; + if (playerToPoint.canBeNormalized() && playerToPointFlat.canBeNormalized() && playerToPointFlat.magnitude() > 2.f) { + switch (x304_orbitState) { + case EPlayerOrbitState::Grapple: + switch (g_tweakPlayer->GetGrappleJumpMode()) { + case 0: + case 1: + if (ControlMapper::GetPressInput(ControlMapper::ECommands::FireOrBomb, input)) { + if (TCastToPtr point2 = mgr.ObjectById(x33c_orbitNextTargetId)) { + playerToPoint = point2->GetTranslation() - eyePosition; + playerToPoint.z() = 0.f; + if (playerToPoint.canBeNormalized()) { + x490_gun->GetGrappleArm().GrappleBeamDisconnected(); + x3c0_grappleSwingAxis.x() = float(playerToPoint.y()); + x3c0_grappleSwingAxis.y() = -playerToPoint.x(); + x3c0_grappleSwingAxis.normalize(); + x3bc_grappleSwingTimer = 0.f; + SetOrbitTargetId(x33c_orbitNextTargetId, mgr); + x3b8_grappleState = EGrappleState::Pull; + x33c_orbitNextTargetId = kInvalidUniqueId; + x490_gun->GetGrappleArm().GrappleBeamConnected(); + } + } else { + if (g_tweakPlayer->GetGrappleJumpMode() == 0 && x3d8_grappleJumpTimeout <= 0.f) + ApplyGrappleJump(mgr); + BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); + } + } + break; + default: + break; + } -void CPlayer::SetOrbitRequest(EPlayerOrbitRequest req, CStateManager& mgr) -{ - x30c_orbitRequest = req; - switch (req) - { - case EPlayerOrbitRequest::ActivateOrbitSource: - ActivateOrbitSource(mgr); break; - case EPlayerOrbitRequest::BadVerticalAngle: - SetOrbitState(EPlayerOrbitState::OrbitPoint, mgr); - x314_orbitPoint = g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)) * - x34_transform.basis[1] + x34_transform.origin; + case EPlayerOrbitState::OrbitObject: + if (playerToPoint.canBeNormalized()) { + CRayCastResult result = mgr.RayStaticIntersection(eyePosition, playerToPoint.normalized(), + playerToPoint.magnitude(), LineOfSightFilter); + if (result.IsInvalid()) { + HolsterGun(mgr); + switch (x3b8_grappleState) { + case EGrappleState::Firing: + case EGrappleState::Swinging: + switch (g_tweakPlayer->GetGrappleJumpMode()) { + case 0: + switch (x490_gun->GetGrappleArm().GetAnimState()) { + case CGrappleArm::EArmState::IntoGrappleIdle: + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input)) + x490_gun->GetGrappleArm().SetAnimState(CGrappleArm::EArmState::FireGrapple); + break; + case CGrappleArm::EArmState::Connected: + BeginGrapple(playerToPoint, mgr); + break; + default: + break; + } + break; + case 1: + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input)) { + switch (x490_gun->GetGrappleArm().GetAnimState()) { + case CGrappleArm::EArmState::IntoGrappleIdle: + x490_gun->GetGrappleArm().SetAnimState(CGrappleArm::EArmState::FireGrapple); + break; + case CGrappleArm::EArmState::Connected: + BeginGrapple(playerToPoint, mgr); + break; + default: + break; + } + break; + } + break; + case 2: + switch (x490_gun->GetGrappleArm().GetAnimState()) { + case CGrappleArm::EArmState::IntoGrappleIdle: + x490_gun->GetGrappleArm().SetAnimState(CGrappleArm::EArmState::FireGrapple); + break; + case CGrappleArm::EArmState::Connected: + BeginGrapple(playerToPoint, mgr); + break; + default: + break; + } + break; + default: + break; + } + break; + case EGrappleState::None: + x3b8_grappleState = EGrappleState::Firing; + x490_gun->GetGrappleArm().Activate(true); + break; + default: + break; + } + } + } break; + default: + break; + } + } + } + + if (x304_orbitState != EPlayerOrbitState::Grapple) { + if (x304_orbitState >= EPlayerOrbitState::Grapple) + return; + if (x304_orbitState != EPlayerOrbitState::OrbitObject) + return; + } else { + if (!point) { + BreakGrapple(EPlayerOrbitRequest::Default, mgr); + return; + } + + switch (g_tweakPlayer->GetGrappleJumpMode()) { + case 0: + if (x3b8_grappleState == EGrappleState::JumpOff) { + x3d8_grappleJumpTimeout -= input.DeltaTime(); + if (x3d8_grappleJumpTimeout <= 0.f) { + BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); + SetMoveState(EPlayerMovementState::ApplyJump, mgr); + ComputeMovement(input, mgr, input.DeltaTime()); + PreventFallingCameraPitch(); + } + } + break; + case 1: + switch (x3b8_grappleState) { + case EGrappleState::Swinging: + if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input) && + x3d8_grappleJumpTimeout <= 0.f) { + x3d8_grappleJumpTimeout = g_tweakPlayer->GetGrappleReleaseTime(); + x3b8_grappleState = EGrappleState::JumpOff; + ApplyGrappleJump(mgr); + } + break; + case EGrappleState::JumpOff: + x3d8_grappleJumpTimeout -= input.DeltaTime(); + if (x3d8_grappleJumpTimeout <= 0.f) { + SetMoveState(EPlayerMovementState::ApplyJump, mgr); + ComputeMovement(input, mgr, input.DeltaTime()); + BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); + PreventFallingCameraPitch(); + } + break; + case EGrappleState::Firing: + case EGrappleState::Pull: + if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input)) + BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); + break; + default: + break; + } + break; default: - SetOrbitState(EPlayerOrbitState::NoOrbit, mgr); - break; + break; } -} -void CPlayer::SetOrbitRequestForTarget(TUniqueId id, EPlayerOrbitRequest req, CStateManager& mgr) -{ - switch (x304_orbitState) - { - case EPlayerOrbitState::OrbitObject: - case EPlayerOrbitState::ForcedOrbitObject: - case EPlayerOrbitState::Grapple: - if (id == x310_orbitTargetId) - SetOrbitRequest(req, mgr); - break; - default: - break; + zeus::CVector3f eyePos = GetEyePosition(); + zeus::CVector3f playerToPoint = point->GetTranslation() - eyePos; + if (playerToPoint.canBeNormalized()) { + CRayCastResult result = + mgr.RayStaticIntersection(eyePos, playerToPoint.normalized(), playerToPoint.magnitude(), LineOfSightFilter); + if (result.IsValid()) { + BreakGrapple(EPlayerOrbitRequest::LostGrappleLineOfSight, mgr); + } } + return; + } + + if (x490_gun->GetGrappleArm().BeamActive() && g_tweakPlayer->GetGrappleJumpMode() == 1 && + !ControlMapper::GetDigitalInput(ControlMapper::ECommands::FireOrBomb, input)) + BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); } -bool CPlayer::InGrappleJumpCooldown() const -{ - if (x258_movementState == EPlayerMovementState::OnGround) - return false; - return x3d8_grappleJumpTimeout > 0.f || x294_jumpCameraTimer == 0.f; +void CPlayer::ApplyGrappleJump(CStateManager& mgr) { + if (TCastToPtr point = mgr.ObjectById(x310_orbitTargetId)) { + zeus::CVector3f tmp = x3c0_grappleSwingAxis; + if (x3bc_grappleSwingTimer < 0.5f * g_tweakPlayer->GetGrappleSwingPeriod()) + tmp *= zeus::CVector3f::skNegOne; + zeus::CVector3f pointToPlayer = GetTranslation() - point->GetTranslation(); + zeus::CVector3f cross = pointToPlayer.normalized().cross(tmp); + zeus::CVector3f pointToPlayerFlat(pointToPlayer.x(), pointToPlayer.y(), 0.f); + float dot = 1.f; + if (pointToPlayerFlat.canBeNormalized() && cross.canBeNormalized()) + dot = zeus::clamp(-1.f, std::fabs(cross.normalized().dot(pointToPlayerFlat.normalized())), 1.f); + ApplyForceWR(g_tweakPlayer->GetGrappleJumpForce() * cross * 10000.f * dot, zeus::CAxisAngle::sIdentity); + } } -void CPlayer::PreventFallingCameraPitch() -{ - x294_jumpCameraTimer = 0.f; - x29c_fallCameraTimer = 0.01f; - x2a4_cancelCameraPitch = true; +void CPlayer::BeginGrapple(zeus::CVector3f& vec, CStateManager& mgr) { + vec.z() = 0.f; + if (vec.canBeNormalized()) { + x3c0_grappleSwingAxis.x() = float(vec.y()); + x3c0_grappleSwingAxis.y() = -vec.x(); + x3c0_grappleSwingAxis.normalize(); + x3bc_grappleSwingTimer = 0.f; + SetOrbitState(EPlayerOrbitState::Grapple, mgr); + x3b8_grappleState = EGrappleState::Pull; + RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + } } -void CPlayer::OrbitCarcass(CStateManager& mgr) -{ - if (x304_orbitState == EPlayerOrbitState::OrbitObject) - { - x308_orbitType = EPlayerOrbitType::Default; - SetOrbitState(EPlayerOrbitState::OrbitCarcass, mgr); - } +void CPlayer::BreakGrapple(EPlayerOrbitRequest req, CStateManager& mgr) { + x294_jumpCameraTimer = 0.f; + x29c_fallCameraTimer = 0.f; + if (g_tweakPlayer->GetGrappleJumpMode() == 2 && x3b8_grappleState == EGrappleState::Swinging) { + ApplyGrappleJump(mgr); + PreventFallingCameraPitch(); + } + + SetOrbitRequest(req, mgr); + x3b8_grappleState = EGrappleState::None; + AddMaterial(EMaterialTypes::GroundCollider, mgr); + x490_gun->GetGrappleArm().SetAnimState(CGrappleArm::EArmState::OutOfGrapple); + if (!InGrappleJumpCooldown() && x3b8_grappleState != EGrappleState::JumpOff) + DrawGun(mgr); } -void CPlayer::OrbitPoint(EPlayerOrbitType type, CStateManager& mgr) -{ - x308_orbitType = type; +void CPlayer::SetOrbitRequest(EPlayerOrbitRequest req, CStateManager& mgr) { + x30c_orbitRequest = req; + switch (req) { + case EPlayerOrbitRequest::ActivateOrbitSource: + ActivateOrbitSource(mgr); + break; + case EPlayerOrbitRequest::BadVerticalAngle: SetOrbitState(EPlayerOrbitState::OrbitPoint, mgr); - SetOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + x314_orbitPoint = + g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)) * x34_transform.basis[1] + x34_transform.origin; + break; + default: + SetOrbitState(EPlayerOrbitState::NoOrbit, mgr); + break; + } } -zeus::CVector3f CPlayer::GetHUDOrbitTargetPosition() const -{ - return x314_orbitPoint + x76c_cameraBob->GetCameraBobTransformation().origin; +void CPlayer::SetOrbitRequestForTarget(TUniqueId id, EPlayerOrbitRequest req, CStateManager& mgr) { + switch (x304_orbitState) { + case EPlayerOrbitState::OrbitObject: + case EPlayerOrbitState::ForcedOrbitObject: + case EPlayerOrbitState::Grapple: + if (id == x310_orbitTargetId) + SetOrbitRequest(req, mgr); + break; + default: + break; + } } -void CPlayer::SetOrbitState(EPlayerOrbitState state, CStateManager& mgr) -{ - x304_orbitState = state; - CFirstPersonCamera* cam = mgr.GetCameraManager()->GetFirstPersonCamera(); - switch (x304_orbitState) - { - case EPlayerOrbitState::OrbitObject: - cam->SetLockCamera(false); - break; - case EPlayerOrbitState::OrbitCarcass: - { - cam->SetLockCamera(true); - zeus::CVector3f playerToPoint = x314_orbitPoint - GetTranslation(); - if (playerToPoint.canBeNormalized()) - x340_ = playerToPoint.magnitude(); - else - x340_ = 0.f; - SetOrbitTargetId(kInvalidUniqueId, mgr); - x33c_orbitNextTargetId = kInvalidUniqueId; - break; - } - case EPlayerOrbitState::NoOrbit: - x32c_orbitModeTimer = g_tweakPlayer->GetOrbitModeTimer(); - x32c_orbitModeTimer = 0.28f; - SetOrbitTargetId(kInvalidUniqueId, mgr); - x33c_orbitNextTargetId = kInvalidUniqueId; - break; - case EPlayerOrbitState::OrbitPoint: - SetOrbitTargetId(kInvalidUniqueId, mgr); - x33c_orbitNextTargetId = kInvalidUniqueId; - break; - default: - break; - } +bool CPlayer::InGrappleJumpCooldown() const { + if (x258_movementState == EPlayerMovementState::OnGround) + return false; + return x3d8_grappleJumpTimeout > 0.f || x294_jumpCameraTimer == 0.f; } -void CPlayer::SetOrbitTargetId(TUniqueId id, CStateManager& mgr) -{ - if (id != kInvalidUniqueId) - { - x394_orbitingEnemy = (TCastToPtr(mgr.ObjectById(id)) || - TCastToPtr(mgr.ObjectById(id)) || - CPatterned::CastTo(mgr.ObjectById(id)) || - TCastToPtr(mgr.ObjectById(id))); - } - - x310_orbitTargetId = id; - if (x310_orbitTargetId == kInvalidUniqueId) - x374_orbitLockEstablished = false; +void CPlayer::PreventFallingCameraPitch() { + x294_jumpCameraTimer = 0.f; + x29c_fallCameraTimer = 0.01f; + x2a4_cancelCameraPitch = true; } -void CPlayer::UpdateOrbitPosition(float dist, CStateManager& mgr) -{ - switch (x304_orbitState) - { - case EPlayerOrbitState::OrbitPoint: - case EPlayerOrbitState::OrbitCarcass: - SetOrbitPosition(dist, mgr); - break; - case EPlayerOrbitState::OrbitObject: - case EPlayerOrbitState::ForcedOrbitObject: - case EPlayerOrbitState::Grapple: - if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) - if (x310_orbitTargetId != kInvalidUniqueId) - x314_orbitPoint = act->GetOrbitPosition(mgr); - break; - default: break; - } +void CPlayer::OrbitCarcass(CStateManager& mgr) { + if (x304_orbitState == EPlayerOrbitState::OrbitObject) { + x308_orbitType = EPlayerOrbitType::Default; + SetOrbitState(EPlayerOrbitState::OrbitCarcass, mgr); + } } -void CPlayer::UpdateOrbitZPosition() -{ - if (x304_orbitState == EPlayerOrbitState::OrbitPoint) - { - if (std::fabs(x320_orbitVector.z()) < g_tweakPlayer->GetOrbitZRange()) - x314_orbitPoint.z() = x320_orbitVector.z() + x34_transform.origin.z() + GetEyeHeight(); - } +void CPlayer::OrbitPoint(EPlayerOrbitType type, CStateManager& mgr) { + x308_orbitType = type; + SetOrbitState(EPlayerOrbitState::OrbitPoint, mgr); + SetOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); } -void CPlayer::UpdateOrbitFixedPosition() -{ - x314_orbitPoint = x34_transform.rotate(x320_orbitVector) + GetEyePosition(); +zeus::CVector3f CPlayer::GetHUDOrbitTargetPosition() const { + return x314_orbitPoint + x76c_cameraBob->GetCameraBobTransformation().origin; } -void CPlayer::SetOrbitPosition(float dist, CStateManager& mgr) -{ - zeus::CTransform camXf = GetFirstPersonCameraTransform(mgr); - if (x304_orbitState == EPlayerOrbitState::OrbitPoint && - x30c_orbitRequest == EPlayerOrbitRequest::BadVerticalAngle) - camXf = x34_transform; - zeus::CVector3f fwd = camXf.basis[1]; - float dot = fwd.normalized().dot(fwd); - if (std::fabs(dot) > 1.f) - dot = (dot > 0.f) ? 1.f : -1.f; - x314_orbitPoint = camXf.rotate(zeus::CVector3f(0.f, dist / dot, 0.f)) + camXf.origin; - x320_orbitVector = zeus::CVector3f(0.f, dist, x314_orbitPoint.z() - camXf.origin.z()); +void CPlayer::SetOrbitState(EPlayerOrbitState state, CStateManager& mgr) { + x304_orbitState = state; + CFirstPersonCamera* cam = mgr.GetCameraManager()->GetFirstPersonCamera(); + switch (x304_orbitState) { + case EPlayerOrbitState::OrbitObject: + cam->SetLockCamera(false); + break; + case EPlayerOrbitState::OrbitCarcass: { + cam->SetLockCamera(true); + zeus::CVector3f playerToPoint = x314_orbitPoint - GetTranslation(); + if (playerToPoint.canBeNormalized()) + x340_ = playerToPoint.magnitude(); + else + x340_ = 0.f; + SetOrbitTargetId(kInvalidUniqueId, mgr); + x33c_orbitNextTargetId = kInvalidUniqueId; + break; + } + case EPlayerOrbitState::NoOrbit: + x32c_orbitModeTimer = g_tweakPlayer->GetOrbitModeTimer(); + x32c_orbitModeTimer = 0.28f; + SetOrbitTargetId(kInvalidUniqueId, mgr); + x33c_orbitNextTargetId = kInvalidUniqueId; + break; + case EPlayerOrbitState::OrbitPoint: + SetOrbitTargetId(kInvalidUniqueId, mgr); + x33c_orbitNextTargetId = kInvalidUniqueId; + break; + default: + break; + } } -void CPlayer::UpdateAimTarget(CStateManager& mgr) -{ - if (!ValidateAimTargetId(x3f4_aimTarget, mgr)) - ResetAimTargetPrediction(kInvalidUniqueId); +void CPlayer::SetOrbitTargetId(TUniqueId id, CStateManager& mgr) { + if (id != kInvalidUniqueId) { + x394_orbitingEnemy = + (TCastToPtr(mgr.ObjectById(id)) || TCastToPtr(mgr.ObjectById(id)) || + CPatterned::CastTo(mgr.ObjectById(id)) || + TCastToPtr(mgr.ObjectById(id))); + } - if (!GetCombatMode()) - { - ResetAimTargetPrediction(kInvalidUniqueId); - x48c_aimTargetTimer = 0.f; - return; - } + x310_orbitTargetId = id; + if (x310_orbitTargetId == kInvalidUniqueId) + x374_orbitLockEstablished = false; +} + +void CPlayer::UpdateOrbitPosition(float dist, CStateManager& mgr) { + switch (x304_orbitState) { + case EPlayerOrbitState::OrbitPoint: + case EPlayerOrbitState::OrbitCarcass: + SetOrbitPosition(dist, mgr); + break; + case EPlayerOrbitState::OrbitObject: + case EPlayerOrbitState::ForcedOrbitObject: + case EPlayerOrbitState::Grapple: + if (TCastToPtr act = mgr.ObjectById(x310_orbitTargetId)) + if (x310_orbitTargetId != kInvalidUniqueId) + x314_orbitPoint = act->GetOrbitPosition(mgr); + break; + default: + break; + } +} + +void CPlayer::UpdateOrbitZPosition() { + if (x304_orbitState == EPlayerOrbitState::OrbitPoint) { + if (std::fabs(x320_orbitVector.z()) < g_tweakPlayer->GetOrbitZRange()) + x314_orbitPoint.z() = x320_orbitVector.z() + x34_transform.origin.z() + GetEyeHeight(); + } +} + +void CPlayer::UpdateOrbitFixedPosition() { + x314_orbitPoint = x34_transform.rotate(x320_orbitVector) + GetEyePosition(); +} + +void CPlayer::SetOrbitPosition(float dist, CStateManager& mgr) { + zeus::CTransform camXf = GetFirstPersonCameraTransform(mgr); + if (x304_orbitState == EPlayerOrbitState::OrbitPoint && x30c_orbitRequest == EPlayerOrbitRequest::BadVerticalAngle) + camXf = x34_transform; + zeus::CVector3f fwd = camXf.basis[1]; + float dot = fwd.normalized().dot(fwd); + if (std::fabs(dot) > 1.f) + dot = (dot > 0.f) ? 1.f : -1.f; + x314_orbitPoint = camXf.rotate(zeus::CVector3f(0.f, dist / dot, 0.f)) + camXf.origin; + x320_orbitVector = zeus::CVector3f(0.f, dist, x314_orbitPoint.z() - camXf.origin.z()); +} + +void CPlayer::UpdateAimTarget(CStateManager& mgr) { + if (!ValidateAimTargetId(x3f4_aimTarget, mgr)) + ResetAimTargetPrediction(kInvalidUniqueId); + + if (!GetCombatMode()) { + ResetAimTargetPrediction(kInvalidUniqueId); + x48c_aimTargetTimer = 0.f; + return; + } #if 0 if (!0 && 0) @@ -4375,661 +3672,535 @@ void CPlayer::UpdateAimTarget(CStateManager& mgr) } #endif - bool needsReset = false; - TCastToPtr act = mgr.ObjectById(x3f4_aimTarget); - CActor* actp = act.GetPtr(); - if (act) - if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Target)) - actp = nullptr; + bool needsReset = false; + TCastToPtr act = mgr.ObjectById(x3f4_aimTarget); + CActor* actp = act.GetPtr(); + if (act) + if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Target)) + actp = nullptr; - if (g_tweakPlayer->GetAimWhenOrbitingPoint()) - { - if (x304_orbitState == EPlayerOrbitState::OrbitObject || - x304_orbitState == EPlayerOrbitState::ForcedOrbitObject) - { - if (ValidateOrbitTargetId(x310_orbitTargetId, mgr) == EOrbitValidationResult::OK) - ResetAimTargetPrediction(x310_orbitTargetId); - else - needsReset = true; - } - else - { - needsReset = true; - } + if (g_tweakPlayer->GetAimWhenOrbitingPoint()) { + if (x304_orbitState == EPlayerOrbitState::OrbitObject || x304_orbitState == EPlayerOrbitState::ForcedOrbitObject) { + if (ValidateOrbitTargetId(x310_orbitTargetId, mgr) == EOrbitValidationResult::OK) + ResetAimTargetPrediction(x310_orbitTargetId); + else + needsReset = true; + } else { + needsReset = true; } + } else { + if (x304_orbitState == EPlayerOrbitState::NoOrbit) + needsReset = true; + } + + if (needsReset) { + if (actp && ValidateObjectForMode(x3f4_aimTarget, mgr)) + ResetAimTargetPrediction(kInvalidUniqueId); else - { - if (x304_orbitState == EPlayerOrbitState::NoOrbit) - needsReset = true; - } - - if (needsReset) - { - if (actp && ValidateObjectForMode(x3f4_aimTarget, mgr)) - ResetAimTargetPrediction(kInvalidUniqueId); - else - ResetAimTargetPrediction(FindAimTargetId(mgr)); - } + ResetAimTargetPrediction(FindAimTargetId(mgr)); + } } -void CPlayer::UpdateAimTargetTimer(float dt) -{ - if (x3f4_aimTarget == kInvalidUniqueId) - return; - if (x48c_aimTargetTimer <= 0.f) - return; - x48c_aimTargetTimer -= dt; +void CPlayer::UpdateAimTargetTimer(float dt) { + if (x3f4_aimTarget == kInvalidUniqueId) + return; + if (x48c_aimTargetTimer <= 0.f) + return; + x48c_aimTargetTimer -= dt; } -bool CPlayer::ValidateAimTargetId(TUniqueId uid, CStateManager& mgr) -{ - if (uid == kInvalidUniqueId) - { - x404_aimTargetAverage.Clear(); - x48c_aimTargetTimer = 0.f; - return false; - } - - TCastToPtr act = mgr.ObjectById(uid); - if (!act || !act->GetMaterialList().HasMaterial(EMaterialTypes::Target) || !act->GetIsTargetable()) - return false; - - if (x304_orbitState == EPlayerOrbitState::OrbitObject || - x304_orbitState == EPlayerOrbitState::ForcedOrbitObject) - { - if (ValidateOrbitTargetId(x310_orbitTargetId, mgr) != EOrbitValidationResult::OK) - { - ResetAimTargetPrediction(kInvalidUniqueId); - x48c_aimTargetTimer = 0.f; - return false; - } - return true; - } - - if (act->GetMaterialList().HasMaterial(EMaterialTypes::Target) && uid != kInvalidUniqueId && - ValidateObjectForMode(uid, mgr)) - { - float vpWHalf = g_Viewport.x8_width / 2; - float vpHHalf = g_Viewport.xc_height / 2; - zeus::CVector3f aimPos = act->GetAimPosition(mgr, 0.f); - zeus::CVector3f eyePos = GetEyePosition(); - zeus::CVector3f eyeToAim = aimPos - eyePos; - zeus::CVector3f screenPos = mgr.GetCameraManager()->GetFirstPersonCamera()->ConvertToScreenSpace(aimPos); - zeus::CVector3f posInBox(vpWHalf + screenPos.x() * vpWHalf, - vpHHalf + screenPos.y() * vpHHalf, - screenPos.z()); - if (WithinOrbitScreenBox(posInBox, x330_orbitZoneMode, x334_orbitType) || - (x330_orbitZoneMode != EPlayerZoneInfo::Targeting && - WithinOrbitScreenBox(posInBox, EPlayerZoneInfo::Targeting, x334_orbitType))) - { - float eyeToAimMag = eyeToAim.magnitude(); - if (eyeToAimMag <= g_tweakPlayer->GetAimMaxDistance()) - { - rstl::reserved_vector nearList; - TUniqueId intersectId = kInvalidUniqueId; - eyeToAim.normalize(); - mgr.BuildNearList(nearList, eyePos, eyeToAim, eyeToAimMag, - OccluderFilter, act); - eyeToAim.normalize(); - CRayCastResult result = - mgr.RayWorldIntersection(intersectId, eyePos, eyeToAim, eyeToAimMag, - LineOfSightFilter, nearList); - if (result.IsInvalid()) - { - x48c_aimTargetTimer = g_tweakPlayer->GetAimTargetTimer(); - return true; - } - } - } - - if (x48c_aimTargetTimer > 0.f) - return true; - } - - ResetAimTargetPrediction(kInvalidUniqueId); +bool CPlayer::ValidateAimTargetId(TUniqueId uid, CStateManager& mgr) { + if (uid == kInvalidUniqueId) { + x404_aimTargetAverage.Clear(); x48c_aimTargetTimer = 0.f; return false; + } + + TCastToPtr act = mgr.ObjectById(uid); + if (!act || !act->GetMaterialList().HasMaterial(EMaterialTypes::Target) || !act->GetIsTargetable()) + return false; + + if (x304_orbitState == EPlayerOrbitState::OrbitObject || x304_orbitState == EPlayerOrbitState::ForcedOrbitObject) { + if (ValidateOrbitTargetId(x310_orbitTargetId, mgr) != EOrbitValidationResult::OK) { + ResetAimTargetPrediction(kInvalidUniqueId); + x48c_aimTargetTimer = 0.f; + return false; + } + return true; + } + + if (act->GetMaterialList().HasMaterial(EMaterialTypes::Target) && uid != kInvalidUniqueId && + ValidateObjectForMode(uid, mgr)) { + float vpWHalf = g_Viewport.x8_width / 2; + float vpHHalf = g_Viewport.xc_height / 2; + zeus::CVector3f aimPos = act->GetAimPosition(mgr, 0.f); + zeus::CVector3f eyePos = GetEyePosition(); + zeus::CVector3f eyeToAim = aimPos - eyePos; + zeus::CVector3f screenPos = mgr.GetCameraManager()->GetFirstPersonCamera()->ConvertToScreenSpace(aimPos); + zeus::CVector3f posInBox(vpWHalf + screenPos.x() * vpWHalf, vpHHalf + screenPos.y() * vpHHalf, screenPos.z()); + if (WithinOrbitScreenBox(posInBox, x330_orbitZoneMode, x334_orbitType) || + (x330_orbitZoneMode != EPlayerZoneInfo::Targeting && + WithinOrbitScreenBox(posInBox, EPlayerZoneInfo::Targeting, x334_orbitType))) { + float eyeToAimMag = eyeToAim.magnitude(); + if (eyeToAimMag <= g_tweakPlayer->GetAimMaxDistance()) { + rstl::reserved_vector nearList; + TUniqueId intersectId = kInvalidUniqueId; + eyeToAim.normalize(); + mgr.BuildNearList(nearList, eyePos, eyeToAim, eyeToAimMag, OccluderFilter, act); + eyeToAim.normalize(); + CRayCastResult result = + mgr.RayWorldIntersection(intersectId, eyePos, eyeToAim, eyeToAimMag, LineOfSightFilter, nearList); + if (result.IsInvalid()) { + x48c_aimTargetTimer = g_tweakPlayer->GetAimTargetTimer(); + return true; + } + } + } + + if (x48c_aimTargetTimer > 0.f) + return true; + } + + ResetAimTargetPrediction(kInvalidUniqueId); + x48c_aimTargetTimer = 0.f; + return false; } -bool CPlayer::ValidateObjectForMode(TUniqueId uid, CStateManager& mgr) const -{ - TCastToPtr act = mgr.ObjectById(uid); - if (!act || uid == kInvalidUniqueId) - return false; +bool CPlayer::ValidateObjectForMode(TUniqueId uid, CStateManager& mgr) const { + TCastToPtr act = mgr.ObjectById(uid); + if (!act || uid == kInvalidUniqueId) + return false; - if (TCastToPtr(mgr.ObjectById(uid))) + if (TCastToPtr(mgr.ObjectById(uid))) + return true; + + if (GetCombatMode()) { + if (CHealthInfo* hInfo = act->HealthInfo(mgr)) { + if (hInfo->GetHP() > 0.f) + return true; + } else { + if (act->GetMaterialList().HasMaterial(EMaterialTypes::Projectile) || + act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) return true; - if (GetCombatMode()) - { - if (CHealthInfo* hInfo = act->HealthInfo(mgr)) - { - if (hInfo->GetHP() > 0.f) - return true; - } - else - { - if (act->GetMaterialList().HasMaterial(EMaterialTypes::Projectile) || - act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) - return true; - - if (TCastToPtr point = mgr.ObjectById(uid)) - { - zeus::CVector3f playerToPoint = point->GetTranslation() - GetTranslation(); - if (playerToPoint.canBeNormalized() && playerToPoint.magnitude() < g_tweakPlayer->GetOrbitDistanceMax()) - return true; - } - } + if (TCastToPtr point = mgr.ObjectById(uid)) { + zeus::CVector3f playerToPoint = point->GetTranslation() - GetTranslation(); + if (playerToPoint.canBeNormalized() && playerToPoint.magnitude() < g_tweakPlayer->GetOrbitDistanceMax()) + return true; + } } + } - if (GetExplorationMode()) - { - if (!act->HealthInfo(mgr)) - { - if (TCastToPtr point = mgr.ObjectById(uid)) - { - zeus::CVector3f playerToPoint = point->GetTranslation() - GetTranslation(); - if (playerToPoint.canBeNormalized() && playerToPoint.magnitude() < g_tweakPlayer->GetOrbitDistanceMax()) - return true; - } - else - { - return true; - } - } - else - { - return true; - } + if (GetExplorationMode()) { + if (!act->HealthInfo(mgr)) { + if (TCastToPtr point = mgr.ObjectById(uid)) { + zeus::CVector3f playerToPoint = point->GetTranslation() - GetTranslation(); + if (playerToPoint.canBeNormalized() && playerToPoint.magnitude() < g_tweakPlayer->GetOrbitDistanceMax()) + return true; + } else { + return true; + } + } else { + return true; } + } - return false; + return false; } -static zeus::CAABox BuildNearListBox(bool cropBottom, const zeus::CTransform& xf, float x, float z, float y) -{ - zeus::CAABox aabb(-x, cropBottom ? 0.f : -y, -z, x, y, z); - return aabb.getTransformedAABox(xf); +static zeus::CAABox BuildNearListBox(bool cropBottom, const zeus::CTransform& xf, float x, float z, float y) { + zeus::CAABox aabb(-x, cropBottom ? 0.f : -y, -z, x, y, z); + return aabb.getTransformedAABox(xf); } -TUniqueId CPlayer::FindAimTargetId(CStateManager& mgr) -{ - float dist = g_tweakPlayer->GetAimMaxDistance(); - if (x9c6_24_extendTargetDistance) - dist *= 5.f; - zeus::CAABox aabb = - BuildNearListBox(true, GetFirstPersonCameraTransform(mgr), g_tweakPlayer->GetAimBoxWidth(), - g_tweakPlayer->GetAimBoxHeight(), dist); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, aabb, CMaterialFilter::MakeInclude({EMaterialTypes::Target}), this); - return CheckEnemiesAgainstOrbitZone(nearList, EPlayerZoneInfo::Targeting, EPlayerZoneType::Ellipse, mgr); +TUniqueId CPlayer::FindAimTargetId(CStateManager& mgr) { + float dist = g_tweakPlayer->GetAimMaxDistance(); + if (x9c6_24_extendTargetDistance) + dist *= 5.f; + zeus::CAABox aabb = BuildNearListBox(true, GetFirstPersonCameraTransform(mgr), g_tweakPlayer->GetAimBoxWidth(), + g_tweakPlayer->GetAimBoxHeight(), dist); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, aabb, CMaterialFilter::MakeInclude({EMaterialTypes::Target}), this); + return CheckEnemiesAgainstOrbitZone(nearList, EPlayerZoneInfo::Targeting, EPlayerZoneType::Ellipse, mgr); } -const zeus::CTransform& CPlayer::GetFirstPersonCameraTransform(const CStateManager& mgr) const -{ - return mgr.GetCameraManager()->GetFirstPersonCamera()->GetGunFollowTransform(); +const zeus::CTransform& CPlayer::GetFirstPersonCameraTransform(const CStateManager& mgr) const { + return mgr.GetCameraManager()->GetFirstPersonCamera()->GetGunFollowTransform(); } TUniqueId CPlayer::CheckEnemiesAgainstOrbitZone(const rstl::reserved_vector& list, - EPlayerZoneInfo info, EPlayerZoneType zone, CStateManager& mgr) const -{ - zeus::CVector3f eyePos = GetEyePosition(); - float minEyeToAimMag = 10000.f; - float minPosInBoxMagSq = 10000.f; - TUniqueId bestId = kInvalidUniqueId; - float vpWHalf = g_Viewport.x8_width / 2; - float vpHHalf = g_Viewport.xc_height / 2; - float boxLeft = (GetOrbitZoneIdealXScaled(int(info)) - vpWHalf) / vpWHalf; - float boxTop = (GetOrbitZoneIdealYScaled(int(info)) - vpHHalf) / vpHHalf; - CFirstPersonCamera* fpCam = mgr.GetCameraManager()->GetFirstPersonCamera(); + EPlayerZoneInfo info, EPlayerZoneType zone, CStateManager& mgr) const { + zeus::CVector3f eyePos = GetEyePosition(); + float minEyeToAimMag = 10000.f; + float minPosInBoxMagSq = 10000.f; + TUniqueId bestId = kInvalidUniqueId; + float vpWHalf = g_Viewport.x8_width / 2; + float vpHHalf = g_Viewport.xc_height / 2; + float boxLeft = (GetOrbitZoneIdealXScaled(int(info)) - vpWHalf) / vpWHalf; + float boxTop = (GetOrbitZoneIdealYScaled(int(info)) - vpHHalf) / vpHHalf; + CFirstPersonCamera* fpCam = mgr.GetCameraManager()->GetFirstPersonCamera(); - for (TUniqueId id : list) - { - if (CActor* act = static_cast(mgr.ObjectById(id))) - { - if (act->GetUniqueId() != GetUniqueId() && ValidateObjectForMode(act->GetUniqueId(), mgr)) - { - zeus::CVector3f aimPos = act->GetAimPosition(mgr, 0.f); - zeus::CVector3f screenPos = fpCam->ConvertToScreenSpace(aimPos); - zeus::CVector3f posInBox(vpWHalf + screenPos.x() * vpWHalf, - vpHHalf + screenPos.y() * vpHHalf, - screenPos.z()); - if (WithinOrbitScreenBox(posInBox, info, zone)) - { - zeus::CVector3f eyeToAim = aimPos - eyePos; - float eyeToAimMag = eyeToAim.magnitude(); - if (eyeToAimMag <= g_tweakPlayer->GetAimMaxDistance()) - { - if (minEyeToAimMag - eyeToAimMag > g_tweakPlayer->GetAimThresholdDistance()) - { - rstl::reserved_vector nearList; - TUniqueId intersectId = kInvalidUniqueId; - eyeToAim.normalize(); - mgr.BuildNearList(nearList, eyePos, eyeToAim, eyeToAimMag, - OccluderFilter, act); - eyeToAim.normalize(); - CRayCastResult result = - mgr.RayWorldIntersection(intersectId, eyePos, eyeToAim, eyeToAimMag, - LineOfSightFilter, nearList); - if (result.IsInvalid()) - { - bestId = act->GetUniqueId(); - float posInBoxLeft = posInBox.x() - boxLeft; - float posInBoxTop = posInBox.y() - boxTop; - minEyeToAimMag = eyeToAimMag; - minPosInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; - } - } - else if (std::fabs(eyeToAimMag - minEyeToAimMag) < g_tweakPlayer->GetAimThresholdDistance()) - { - float posInBoxLeft = posInBox.x() - boxLeft; - float posInBoxTop = posInBox.y() - boxTop; - float posInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; - if (posInBoxMagSq < minPosInBoxMagSq) - { - rstl::reserved_vector nearList; - TUniqueId intersectId = kInvalidUniqueId; - eyeToAim.normalize(); - mgr.BuildNearList(nearList, eyePos, eyeToAim, eyeToAimMag, - OccluderFilter, act); - eyeToAim.normalize(); - CRayCastResult result = - mgr.RayWorldIntersection(intersectId, eyePos, eyeToAim, eyeToAimMag, - LineOfSightFilter, nearList); - if (result.IsInvalid()) - { - bestId = act->GetUniqueId(); - minEyeToAimMag = eyeToAimMag; - minPosInBoxMagSq = posInBoxMagSq; - } - } - } - } + for (TUniqueId id : list) { + if (CActor* act = static_cast(mgr.ObjectById(id))) { + if (act->GetUniqueId() != GetUniqueId() && ValidateObjectForMode(act->GetUniqueId(), mgr)) { + zeus::CVector3f aimPos = act->GetAimPosition(mgr, 0.f); + zeus::CVector3f screenPos = fpCam->ConvertToScreenSpace(aimPos); + zeus::CVector3f posInBox(vpWHalf + screenPos.x() * vpWHalf, vpHHalf + screenPos.y() * vpHHalf, screenPos.z()); + if (WithinOrbitScreenBox(posInBox, info, zone)) { + zeus::CVector3f eyeToAim = aimPos - eyePos; + float eyeToAimMag = eyeToAim.magnitude(); + if (eyeToAimMag <= g_tweakPlayer->GetAimMaxDistance()) { + if (minEyeToAimMag - eyeToAimMag > g_tweakPlayer->GetAimThresholdDistance()) { + rstl::reserved_vector nearList; + TUniqueId intersectId = kInvalidUniqueId; + eyeToAim.normalize(); + mgr.BuildNearList(nearList, eyePos, eyeToAim, eyeToAimMag, OccluderFilter, act); + eyeToAim.normalize(); + CRayCastResult result = + mgr.RayWorldIntersection(intersectId, eyePos, eyeToAim, eyeToAimMag, LineOfSightFilter, nearList); + if (result.IsInvalid()) { + bestId = act->GetUniqueId(); + float posInBoxLeft = posInBox.x() - boxLeft; + float posInBoxTop = posInBox.y() - boxTop; + minEyeToAimMag = eyeToAimMag; + minPosInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; + } + } else if (std::fabs(eyeToAimMag - minEyeToAimMag) < g_tweakPlayer->GetAimThresholdDistance()) { + float posInBoxLeft = posInBox.x() - boxLeft; + float posInBoxTop = posInBox.y() - boxTop; + float posInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; + if (posInBoxMagSq < minPosInBoxMagSq) { + rstl::reserved_vector nearList; + TUniqueId intersectId = kInvalidUniqueId; + eyeToAim.normalize(); + mgr.BuildNearList(nearList, eyePos, eyeToAim, eyeToAimMag, OccluderFilter, act); + eyeToAim.normalize(); + CRayCastResult result = + mgr.RayWorldIntersection(intersectId, eyePos, eyeToAim, eyeToAimMag, LineOfSightFilter, nearList); + if (result.IsInvalid()) { + bestId = act->GetUniqueId(); + minEyeToAimMag = eyeToAimMag; + minPosInBoxMagSq = posInBoxMagSq; } + } } + } } + } } + } - return bestId; + return bestId; } -TUniqueId CPlayer::FindOrbitTargetId(CStateManager& mgr) -{ - return FindBestOrbitableObject(x354_onScreenOrbitObjects, x330_orbitZoneMode, mgr); +TUniqueId CPlayer::FindOrbitTargetId(CStateManager& mgr) { + return FindBestOrbitableObject(x354_onScreenOrbitObjects, x330_orbitZoneMode, mgr); } -void CPlayer::UpdateOrbitableObjects(CStateManager& mgr) -{ - x354_onScreenOrbitObjects.clear(); - x344_nearbyOrbitObjects.clear(); - x364_offScreenOrbitObjects.clear(); +void CPlayer::UpdateOrbitableObjects(CStateManager& mgr) { + x354_onScreenOrbitObjects.clear(); + x344_nearbyOrbitObjects.clear(); + x364_offScreenOrbitObjects.clear(); - if (CheckOrbitDisableSourceList(mgr)) - return; + if (CheckOrbitDisableSourceList(mgr)) + return; - float dist = GetOrbitMaxTargetDistance(mgr); - if (x9c6_24_extendTargetDistance) - dist *= 5.f; - zeus::CAABox nearAABB = - BuildNearListBox(true, GetFirstPersonCameraTransform(mgr), - g_tweakPlayer->GetOrbitNearX(), g_tweakPlayer->GetOrbitNearZ(), dist); + float dist = GetOrbitMaxTargetDistance(mgr); + if (x9c6_24_extendTargetDistance) + dist *= 5.f; + zeus::CAABox nearAABB = BuildNearListBox(true, GetFirstPersonCameraTransform(mgr), g_tweakPlayer->GetOrbitNearX(), + g_tweakPlayer->GetOrbitNearZ(), dist); - CMaterialFilter filter = mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan ? - CMaterialFilter::MakeInclude({EMaterialTypes::Scannable}) : CMaterialFilter::MakeInclude({EMaterialTypes::Orbit}); - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, nearAABB, filter, nullptr); + CMaterialFilter filter = mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan + ? CMaterialFilter::MakeInclude({EMaterialTypes::Scannable}) + : CMaterialFilter::MakeInclude({EMaterialTypes::Orbit}); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, nearAABB, filter, nullptr); - FindOrbitableObjects(nearList, x344_nearbyOrbitObjects, x330_orbitZoneMode, EPlayerZoneType::Always, mgr, true); - FindOrbitableObjects(nearList, x354_onScreenOrbitObjects, x330_orbitZoneMode, x334_orbitType, mgr, true); - FindOrbitableObjects(nearList, x364_offScreenOrbitObjects, x330_orbitZoneMode, x334_orbitType, mgr, false); + FindOrbitableObjects(nearList, x344_nearbyOrbitObjects, x330_orbitZoneMode, EPlayerZoneType::Always, mgr, true); + FindOrbitableObjects(nearList, x354_onScreenOrbitObjects, x330_orbitZoneMode, x334_orbitType, mgr, true); + FindOrbitableObjects(nearList, x364_offScreenOrbitObjects, x330_orbitZoneMode, x334_orbitType, mgr, false); } -TUniqueId CPlayer::FindBestOrbitableObject(const std::vector& ids, - EPlayerZoneInfo info, CStateManager& mgr) const -{ - zeus::CVector3f eyePos = GetEyePosition(); - float minEyeToOrbitMag = 10000.f; - float minPosInBoxMagSq = 10000.f; - TUniqueId bestId = kInvalidUniqueId; - float vpWidthHalf = g_Viewport.x8_width / 2; - float vpHeightHalf = g_Viewport.xc_height / 2; - float boxLeft = (GetOrbitZoneIdealXScaled(int(info)) - vpWidthHalf) / vpWidthHalf; - float boxTop = (GetOrbitZoneIdealYScaled(int(info)) - vpHeightHalf) / vpHeightHalf; +TUniqueId CPlayer::FindBestOrbitableObject(const std::vector& ids, EPlayerZoneInfo info, + CStateManager& mgr) const { + zeus::CVector3f eyePos = GetEyePosition(); + float minEyeToOrbitMag = 10000.f; + float minPosInBoxMagSq = 10000.f; + TUniqueId bestId = kInvalidUniqueId; + float vpWidthHalf = g_Viewport.x8_width / 2; + float vpHeightHalf = g_Viewport.xc_height / 2; + float boxLeft = (GetOrbitZoneIdealXScaled(int(info)) - vpWidthHalf) / vpWidthHalf; + float boxTop = (GetOrbitZoneIdealYScaled(int(info)) - vpHeightHalf) / vpHeightHalf; - CFirstPersonCamera* fpCam = mgr.GetCameraManager()->GetFirstPersonCamera(); + CFirstPersonCamera* fpCam = mgr.GetCameraManager()->GetFirstPersonCamera(); - for (TUniqueId id : ids) - { - if (TCastToPtr act = mgr.ObjectById(id)) - { - zeus::CVector3f orbitPos = act->GetOrbitPosition(mgr); - zeus::CVector3f eyeToOrbit = orbitPos - eyePos; - float eyeToOrbitMag = eyeToOrbit.magnitude(); - zeus::CVector3f orbitPosScreen = fpCam->ConvertToScreenSpace(orbitPos); - if (orbitPosScreen.z() >= 0.f) - { - if (x310_orbitTargetId != id) - { - if (TCastToPtr point = act.GetPtr()) - { - if (x310_orbitTargetId != point->GetUniqueId()) - { - if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam) && - eyeToOrbitMag < minEyeToOrbitMag && - eyeToOrbitMag < g_tweakPlayer->GetOrbitDistanceMax()) - { - rstl::reserved_vector nearList; - TUniqueId intersectId = kInvalidUniqueId; - eyeToOrbit.normalize(); - mgr.BuildNearList(nearList, eyePos, eyeToOrbit, eyeToOrbitMag, - OccluderFilter, act.GetPtr()); - eyeToOrbit.normalize(); - CRayCastResult result = - mgr.RayWorldIntersection(intersectId, eyePos, eyeToOrbit, eyeToOrbitMag, - LineOfSightFilter, nearList); - if (result.IsInvalid()) - { - if (point->GetGrappleParameters().GetLockSwingTurn()) - { - zeus::CVector3f pointToPlayer = - GetTranslation() - point->GetTranslation(); - if (pointToPlayer.canBeNormalized()) - { - pointToPlayer.z() = 0.f; - if (std::fabs(point->GetTransform().basis[1].normalized(). - dot(pointToPlayer.normalized())) <= M_SQRT1_2F) - continue; - } - } - - bestId = act->GetUniqueId(); - float posInBoxLeft = orbitPosScreen.x() - boxLeft; - float posInBoxTop = orbitPosScreen.y() - boxTop; - minEyeToOrbitMag = eyeToOrbitMag; - minPosInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; - } - } - continue; - } - } - - if (minEyeToOrbitMag - eyeToOrbitMag > g_tweakPlayer->GetOrbitDistanceThreshold() && - mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - { - rstl::reserved_vector nearList; - TUniqueId idOut = kInvalidUniqueId; - eyeToOrbit.normalize(); - mgr.BuildNearList(nearList, eyePos, eyeToOrbit, eyeToOrbitMag, - OccluderFilter, act.GetPtr()); - for (auto it = nearList.begin() ; it != nearList.end() ;) - { - if (CEntity* obj = mgr.ObjectById(*it)) - { - if (obj->GetAreaIdAlways() != kInvalidAreaId) - { - if (mgr.GetNextAreaId() != obj->GetAreaIdAlways()) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(obj->GetAreaIdAlways()); - CGameArea::EOcclusionState state = - area->IsPostConstructed() ? area->GetOcclusionState() : - CGameArea::EOcclusionState::Occluded; - if (state == CGameArea::EOcclusionState::Occluded) - { - it = nearList.erase(it); - continue; - } - } - } - else - { - it = nearList.erase(it); - continue; - } - } - ++it; - } - - eyeToOrbit.normalize(); - CRayCastResult result = - mgr.RayWorldIntersection(idOut, eyePos, eyeToOrbit, eyeToOrbitMag, - LineOfSightFilter, nearList); - if (result.IsInvalid()) - { - bestId = act->GetUniqueId(); - float posInBoxLeft = orbitPosScreen.x() - boxLeft; - float posInBoxTop = orbitPosScreen.y() - boxTop; - minEyeToOrbitMag = eyeToOrbitMag; - minPosInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; - } + for (TUniqueId id : ids) { + if (TCastToPtr act = mgr.ObjectById(id)) { + zeus::CVector3f orbitPos = act->GetOrbitPosition(mgr); + zeus::CVector3f eyeToOrbit = orbitPos - eyePos; + float eyeToOrbitMag = eyeToOrbit.magnitude(); + zeus::CVector3f orbitPosScreen = fpCam->ConvertToScreenSpace(orbitPos); + if (orbitPosScreen.z() >= 0.f) { + if (x310_orbitTargetId != id) { + if (TCastToPtr point = act.GetPtr()) { + if (x310_orbitTargetId != point->GetUniqueId()) { + if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam) && + eyeToOrbitMag < minEyeToOrbitMag && eyeToOrbitMag < g_tweakPlayer->GetOrbitDistanceMax()) { + rstl::reserved_vector nearList; + TUniqueId intersectId = kInvalidUniqueId; + eyeToOrbit.normalize(); + mgr.BuildNearList(nearList, eyePos, eyeToOrbit, eyeToOrbitMag, OccluderFilter, act.GetPtr()); + eyeToOrbit.normalize(); + CRayCastResult result = mgr.RayWorldIntersection(intersectId, eyePos, eyeToOrbit, eyeToOrbitMag, + LineOfSightFilter, nearList); + if (result.IsInvalid()) { + if (point->GetGrappleParameters().GetLockSwingTurn()) { + zeus::CVector3f pointToPlayer = GetTranslation() - point->GetTranslation(); + if (pointToPlayer.canBeNormalized()) { + pointToPlayer.z() = 0.f; + if (std::fabs(point->GetTransform().basis[1].normalized().dot(pointToPlayer.normalized())) <= + M_SQRT1_2F) continue; } + } - if (std::fabs(eyeToOrbitMag - minEyeToOrbitMag) < - g_tweakPlayer->GetOrbitDistanceThreshold() || - mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan) - { - float posInBoxLeft = orbitPosScreen.x() - boxLeft; - float posInBoxTop = orbitPosScreen.y() - boxTop; - float posInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; - if (posInBoxMagSq < minPosInBoxMagSq) - { - rstl::reserved_vector nearList; - TUniqueId idOut = kInvalidUniqueId; - eyeToOrbit.normalize(); - mgr.BuildNearList(nearList, eyePos, eyeToOrbit, eyeToOrbitMag, - OccluderFilter, act.GetPtr()); - for (auto it = nearList.begin() ; it != nearList.end() ;) - { - if (CEntity* obj = mgr.ObjectById(*it)) - { - if (obj->GetAreaIdAlways() != kInvalidAreaId) - { - if (mgr.GetNextAreaId() != obj->GetAreaIdAlways()) - { - const CGameArea* area = - mgr.GetWorld()->GetAreaAlways(obj->GetAreaIdAlways()); - CGameArea::EOcclusionState state = - area->IsPostConstructed() ? area->GetOcclusionState() : - CGameArea::EOcclusionState::Occluded; - if (state == CGameArea::EOcclusionState::Occluded) - { - it = nearList.erase(it); - continue; - } - } - } - else - { - it = nearList.erase(it); - continue; - } - } - ++it; - } - - eyeToOrbit.normalize(); - CRayCastResult result = - mgr.RayWorldIntersection(idOut, eyePos, eyeToOrbit, eyeToOrbitMag, - LineOfSightFilter, nearList); - if (result.IsInvalid()) - { - bestId = act->GetUniqueId(); - minPosInBoxMagSq = posInBoxMagSq; - minEyeToOrbitMag = eyeToOrbitMag; - } - } - } + bestId = act->GetUniqueId(); + float posInBoxLeft = orbitPosScreen.x() - boxLeft; + float posInBoxTop = orbitPosScreen.y() - boxTop; + minEyeToOrbitMag = eyeToOrbitMag; + minPosInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; } + } + continue; } - } - } + } - return bestId; + if (minEyeToOrbitMag - eyeToOrbitMag > g_tweakPlayer->GetOrbitDistanceThreshold() && + mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) { + rstl::reserved_vector nearList; + TUniqueId idOut = kInvalidUniqueId; + eyeToOrbit.normalize(); + mgr.BuildNearList(nearList, eyePos, eyeToOrbit, eyeToOrbitMag, OccluderFilter, act.GetPtr()); + for (auto it = nearList.begin(); it != nearList.end();) { + if (CEntity* obj = mgr.ObjectById(*it)) { + if (obj->GetAreaIdAlways() != kInvalidAreaId) { + if (mgr.GetNextAreaId() != obj->GetAreaIdAlways()) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(obj->GetAreaIdAlways()); + CGameArea::EOcclusionState state = + area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; + if (state == CGameArea::EOcclusionState::Occluded) { + it = nearList.erase(it); + continue; + } + } + } else { + it = nearList.erase(it); + continue; + } + } + ++it; + } + + eyeToOrbit.normalize(); + CRayCastResult result = + mgr.RayWorldIntersection(idOut, eyePos, eyeToOrbit, eyeToOrbitMag, LineOfSightFilter, nearList); + if (result.IsInvalid()) { + bestId = act->GetUniqueId(); + float posInBoxLeft = orbitPosScreen.x() - boxLeft; + float posInBoxTop = orbitPosScreen.y() - boxTop; + minEyeToOrbitMag = eyeToOrbitMag; + minPosInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; + } + continue; + } + + if (std::fabs(eyeToOrbitMag - minEyeToOrbitMag) < g_tweakPlayer->GetOrbitDistanceThreshold() || + mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan) { + float posInBoxLeft = orbitPosScreen.x() - boxLeft; + float posInBoxTop = orbitPosScreen.y() - boxTop; + float posInBoxMagSq = posInBoxLeft * posInBoxLeft + posInBoxTop * posInBoxTop; + if (posInBoxMagSq < minPosInBoxMagSq) { + rstl::reserved_vector nearList; + TUniqueId idOut = kInvalidUniqueId; + eyeToOrbit.normalize(); + mgr.BuildNearList(nearList, eyePos, eyeToOrbit, eyeToOrbitMag, OccluderFilter, act.GetPtr()); + for (auto it = nearList.begin(); it != nearList.end();) { + if (CEntity* obj = mgr.ObjectById(*it)) { + if (obj->GetAreaIdAlways() != kInvalidAreaId) { + if (mgr.GetNextAreaId() != obj->GetAreaIdAlways()) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(obj->GetAreaIdAlways()); + CGameArea::EOcclusionState state = + area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; + if (state == CGameArea::EOcclusionState::Occluded) { + it = nearList.erase(it); + continue; + } + } + } else { + it = nearList.erase(it); + continue; + } + } + ++it; + } + + eyeToOrbit.normalize(); + CRayCastResult result = + mgr.RayWorldIntersection(idOut, eyePos, eyeToOrbit, eyeToOrbitMag, LineOfSightFilter, nearList); + if (result.IsInvalid()) { + bestId = act->GetUniqueId(); + minPosInBoxMagSq = posInBoxMagSq; + minEyeToOrbitMag = eyeToOrbitMag; + } + } + } + } + } + } + } + + return bestId; } void CPlayer::FindOrbitableObjects(const rstl::reserved_vector& nearObjects, - std::vector& listOut, EPlayerZoneInfo zone, - EPlayerZoneType type, CStateManager& mgr, bool onScreenTest) const -{ - CFirstPersonCamera* fpCam = mgr.GetCameraManager()->GetFirstPersonCamera(); - zeus::CVector3f eyePos = GetEyePosition(); + std::vector& listOut, EPlayerZoneInfo zone, EPlayerZoneType type, + CStateManager& mgr, bool onScreenTest) const { + CFirstPersonCamera* fpCam = mgr.GetCameraManager()->GetFirstPersonCamera(); + zeus::CVector3f eyePos = GetEyePosition(); - for (TUniqueId id : nearObjects) - { - if (TCastToConstPtr act = mgr.GetObjectById(id)) - { - if (GetUniqueId() == act->GetUniqueId()) - continue; - if (ValidateOrbitTargetId(act->GetUniqueId(), mgr) != EOrbitValidationResult::OK) - continue; - zeus::CVector3f orbitPos = act->GetOrbitPosition(mgr); - zeus::CVector3f screenPos = fpCam->ConvertToScreenSpace(orbitPos); - screenPos.x() = g_Viewport.x8_width * screenPos.x() / 2.f + g_Viewport.x8_width / 2.f; - screenPos.y() = g_Viewport.xc_height * screenPos.y() / 2.f + g_Viewport.xc_height / 2.f; + for (TUniqueId id : nearObjects) { + if (TCastToConstPtr act = mgr.GetObjectById(id)) { + if (GetUniqueId() == act->GetUniqueId()) + continue; + if (ValidateOrbitTargetId(act->GetUniqueId(), mgr) != EOrbitValidationResult::OK) + continue; + zeus::CVector3f orbitPos = act->GetOrbitPosition(mgr); + zeus::CVector3f screenPos = fpCam->ConvertToScreenSpace(orbitPos); + screenPos.x() = g_Viewport.x8_width * screenPos.x() / 2.f + g_Viewport.x8_width / 2.f; + screenPos.y() = g_Viewport.xc_height * screenPos.y() / 2.f + g_Viewport.xc_height / 2.f; - bool pass = false; - if (onScreenTest) - { - if (WithinOrbitScreenBox(screenPos, zone, type)) - pass = true; - } - else - { - if (!WithinOrbitScreenBox(screenPos, zone, type)) - pass = true; - } + bool pass = false; + if (onScreenTest) { + if (WithinOrbitScreenBox(screenPos, zone, type)) + pass = true; + } else { + if (!WithinOrbitScreenBox(screenPos, zone, type)) + pass = true; + } - if (pass && (!act->GetDoTargetDistanceTest() || - (orbitPos - eyePos).magnitude() <= GetOrbitMaxTargetDistance(mgr))) - listOut.push_back(id); - } + if (pass && + (!act->GetDoTargetDistanceTest() || (orbitPos - eyePos).magnitude() <= GetOrbitMaxTargetDistance(mgr))) + listOut.push_back(id); } + } } bool CPlayer::WithinOrbitScreenBox(const zeus::CVector3f& screenCoords, EPlayerZoneInfo zone, - EPlayerZoneType type) const -{ - if (screenCoords.z() >= 1.f) - return false; - - switch (type) - { - case EPlayerZoneType::Box: - return std::fabs(screenCoords.x() - GetOrbitScreenBoxCenterXScaled(int(zone))) < - GetOrbitScreenBoxHalfExtentXScaled(int(zone)) && - std::fabs(screenCoords.y() - GetOrbitScreenBoxCenterYScaled(int(zone))) < - GetOrbitScreenBoxHalfExtentYScaled(int(zone)) && - screenCoords.z() < 1.f; - break; - case EPlayerZoneType::Ellipse: - return WithinOrbitScreenEllipse(screenCoords, zone); - default: - return true; - } - + EPlayerZoneType type) const { + if (screenCoords.z() >= 1.f) return false; + + switch (type) { + case EPlayerZoneType::Box: + return std::fabs(screenCoords.x() - GetOrbitScreenBoxCenterXScaled(int(zone))) < + GetOrbitScreenBoxHalfExtentXScaled(int(zone)) && + std::fabs(screenCoords.y() - GetOrbitScreenBoxCenterYScaled(int(zone))) < + GetOrbitScreenBoxHalfExtentYScaled(int(zone)) && + screenCoords.z() < 1.f; + break; + case EPlayerZoneType::Ellipse: + return WithinOrbitScreenEllipse(screenCoords, zone); + default: + return true; + } + + return false; } -bool CPlayer::WithinOrbitScreenEllipse(const zeus::CVector3f& screenCoords, EPlayerZoneInfo zone) const -{ - if (screenCoords.z() >= 1.f) - return false; +bool CPlayer::WithinOrbitScreenEllipse(const zeus::CVector3f& screenCoords, EPlayerZoneInfo zone) const { + if (screenCoords.z() >= 1.f) + return false; - float heYSq = GetOrbitScreenBoxHalfExtentYScaled(int(zone)); - heYSq *= heYSq; - float heXSq = GetOrbitScreenBoxHalfExtentXScaled(int(zone)); - heXSq *= heXSq; - float tmpY = std::fabs(screenCoords.y() - GetOrbitScreenBoxCenterYScaled(int(zone))); - float tmpX = std::fabs(screenCoords.x() - GetOrbitScreenBoxCenterXScaled(int(zone))); - return tmpX * tmpX <= (1.f - tmpY * tmpY / heYSq) * heXSq; + float heYSq = GetOrbitScreenBoxHalfExtentYScaled(int(zone)); + heYSq *= heYSq; + float heXSq = GetOrbitScreenBoxHalfExtentXScaled(int(zone)); + heXSq *= heXSq; + float tmpY = std::fabs(screenCoords.y() - GetOrbitScreenBoxCenterYScaled(int(zone))); + float tmpX = std::fabs(screenCoords.x() - GetOrbitScreenBoxCenterXScaled(int(zone))); + return tmpX * tmpX <= (1.f - tmpY * tmpY / heYSq) * heXSq; } -bool CPlayer::CheckOrbitDisableSourceList(CStateManager& mgr) -{ - for (auto it = x9e4_orbitDisableList.begin() ; it != x9e4_orbitDisableList.end() ;) - { - if (mgr.GetObjectById(*it) == nullptr) - { - it = x9e4_orbitDisableList.erase(it); - continue; - } - ++it; +bool CPlayer::CheckOrbitDisableSourceList(CStateManager& mgr) { + for (auto it = x9e4_orbitDisableList.begin(); it != x9e4_orbitDisableList.end();) { + if (mgr.GetObjectById(*it) == nullptr) { + it = x9e4_orbitDisableList.erase(it); + continue; } - return !x9e4_orbitDisableList.empty(); + ++it; + } + return !x9e4_orbitDisableList.empty(); } -void CPlayer::RemoveOrbitDisableSource(TUniqueId uid) -{ - for (auto it = x9e4_orbitDisableList.begin() ; it != x9e4_orbitDisableList.end() ;) - { - if (*it == uid) - { - it = x9e4_orbitDisableList.erase(it); - return; - } - ++it; +void CPlayer::RemoveOrbitDisableSource(TUniqueId uid) { + for (auto it = x9e4_orbitDisableList.begin(); it != x9e4_orbitDisableList.end();) { + if (*it == uid) { + it = x9e4_orbitDisableList.erase(it); + return; } + ++it; + } } -void CPlayer::AddOrbitDisableSource(CStateManager& mgr, TUniqueId addId) -{ - if (x9e4_orbitDisableList.size() >= 5) - return; - for (TUniqueId uid : x9e4_orbitDisableList) - if (uid == addId) - return; - x9e4_orbitDisableList.push_back(addId); - ResetAimTargetPrediction(kInvalidUniqueId); - if (!TCastToConstPtr(mgr.GetObjectById(x310_orbitTargetId))) - SetOrbitTargetId(kInvalidUniqueId, mgr); +void CPlayer::AddOrbitDisableSource(CStateManager& mgr, TUniqueId addId) { + if (x9e4_orbitDisableList.size() >= 5) + return; + for (TUniqueId uid : x9e4_orbitDisableList) + if (uid == addId) + return; + x9e4_orbitDisableList.push_back(addId); + ResetAimTargetPrediction(kInvalidUniqueId); + if (!TCastToConstPtr(mgr.GetObjectById(x310_orbitTargetId))) + SetOrbitTargetId(kInvalidUniqueId, mgr); } -void CPlayer::UpdateOrbitPreventionTimer(float dt) -{ - if (x378_orbitPreventionTimer > 0.f) - x378_orbitPreventionTimer -= dt; +void CPlayer::UpdateOrbitPreventionTimer(float dt) { + if (x378_orbitPreventionTimer > 0.f) + x378_orbitPreventionTimer -= dt; } -void CPlayer::UpdateOrbitModeTimer(float dt) -{ - if (x304_orbitState == EPlayerOrbitState::NoOrbit && x32c_orbitModeTimer > 0.f) - x32c_orbitModeTimer -= dt; - x32c_orbitModeTimer = 0.f; +void CPlayer::UpdateOrbitModeTimer(float dt) { + if (x304_orbitState == EPlayerOrbitState::NoOrbit && x32c_orbitModeTimer > 0.f) + x32c_orbitModeTimer -= dt; + x32c_orbitModeTimer = 0.f; } -void CPlayer::UpdateOrbitZone(CStateManager& mgr) -{ - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - { - x334_orbitType = EPlayerZoneType::Ellipse; - x338_ = 1; - x330_orbitZoneMode = EPlayerZoneInfo::Targeting; - } - else - { - x334_orbitType = EPlayerZoneType::Box; - x338_ = 2; - x330_orbitZoneMode = EPlayerZoneInfo::Scan; - } +void CPlayer::UpdateOrbitZone(CStateManager& mgr) { + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) { + x334_orbitType = EPlayerZoneType::Ellipse; + x338_ = 1; + x330_orbitZoneMode = EPlayerZoneInfo::Targeting; + } else { + x334_orbitType = EPlayerZoneType::Box; + x338_ = 2; + x330_orbitZoneMode = EPlayerZoneInfo::Scan; + } } -void CPlayer::UpdateOrbitInput(const CFinalInput& input, CStateManager& mgr) -{ - if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || x378_orbitPreventionTimer > 0.f) - return; +void CPlayer::UpdateOrbitInput(const CFinalInput& input, CStateManager& mgr) { + if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || x378_orbitPreventionTimer > 0.f) + return; - UpdateOrbitableObjects(mgr); - if (x304_orbitState == EPlayerOrbitState::NoOrbit) - x33c_orbitNextTargetId = FindOrbitTargetId(mgr); + UpdateOrbitableObjects(mgr); + if (x304_orbitState == EPlayerOrbitState::NoOrbit) + x33c_orbitNextTargetId = FindOrbitTargetId(mgr); - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitClose, input) || - ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitFar, input) || - ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitObject, input)) - { - switch (x304_orbitState) - { - case EPlayerOrbitState::NoOrbit: - /* Disabled transitions directly from NoOrbit to OrbitObject for better keyboard handling */ + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitClose, input) || + ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitFar, input) || + ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitObject, input)) { + switch (x304_orbitState) { + case EPlayerOrbitState::NoOrbit: + /* Disabled transitions directly from NoOrbit to OrbitObject for better keyboard handling */ #if 0 if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitObject, input)) { @@ -5045,1700 +4216,1462 @@ void CPlayer::UpdateOrbitInput(const CFinalInput& input, CStateManager& mgr) else { #else - m_deferredOrbitObject = ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitObject, input); + m_deferredOrbitObject = ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitObject, input); #endif - if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitFar, input)) - OrbitPoint(EPlayerOrbitType::Far, mgr); - if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitClose, input)) - OrbitPoint(EPlayerOrbitType::Close, mgr); + if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitFar, input)) + OrbitPoint(EPlayerOrbitType::Far, mgr); + if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitClose, input)) + OrbitPoint(EPlayerOrbitType::Close, mgr); #if 0 } #endif - break; - case EPlayerOrbitState::Grapple: - if (x310_orbitTargetId == kInvalidUniqueId) - BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); - break; - case EPlayerOrbitState::OrbitObject: - if (TCastToConstPtr point = mgr.GetObjectById(x310_orbitTargetId)) - { - if (ValidateCurrentOrbitTargetId(mgr) == EOrbitValidationResult::OK) - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - else - BreakGrapple(EPlayerOrbitRequest::InvalidateTarget, mgr); - } - else - { - EOrbitValidationResult result = ValidateCurrentOrbitTargetId(mgr); - if (result == EOrbitValidationResult::OK) - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - else if (result == EOrbitValidationResult::BrokenLookAngle) - OrbitPoint(EPlayerOrbitType::Far, mgr); - else if (result == EOrbitValidationResult::ExtremeHorizonAngle) - SetOrbitRequest(EPlayerOrbitRequest::BadVerticalAngle, mgr); - else - ActivateOrbitSource(mgr); - } - UpdateOrbitSelection(input, mgr); - break; - case EPlayerOrbitState::OrbitPoint: - if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitObject, input) || m_deferredOrbitObject) - { - m_deferredOrbitObject = false; - SetOrbitTargetId(FindOrbitTargetId(mgr), mgr); - if (x310_orbitTargetId != kInvalidUniqueId) - { - if (ValidateAimTargetId(x310_orbitTargetId, mgr)) - ResetAimTargetPrediction(x310_orbitTargetId); - SetOrbitState(EPlayerOrbitState::OrbitObject, mgr); - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - } - } - else - { - switch (x308_orbitType) - { - case EPlayerOrbitType::Far: - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitClose, input)) - { - x308_orbitType = EPlayerOrbitType::Close; - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - } - break; - case EPlayerOrbitType::Close: - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitFar, input) && - !ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitClose, input)) - { - x308_orbitType = EPlayerOrbitType::Far; - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - } - break; - default: - break; - } - } - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - break; - case EPlayerOrbitState::OrbitCarcass: - if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitObject, input) || m_deferredOrbitObject) - { - m_deferredOrbitObject = false; - SetOrbitTargetId(FindOrbitTargetId(mgr), mgr); - if (x310_orbitTargetId != kInvalidUniqueId) - { - if (ValidateAimTargetId(x310_orbitTargetId, mgr)) - ResetAimTargetPrediction(x310_orbitTargetId); - SetOrbitState(EPlayerOrbitState::OrbitObject, mgr); - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - } - } - UpdateOrbitSelection(input, mgr); - break; - case EPlayerOrbitState::ForcedOrbitObject: - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - UpdateOrbitSelection(input, mgr); - break; - } - - if (x304_orbitState == EPlayerOrbitState::Grapple) - { - x33c_orbitNextTargetId = FindOrbitTargetId(mgr); - if (x33c_orbitNextTargetId == x310_orbitTargetId) - x33c_orbitNextTargetId = kInvalidUniqueId; - } - } - else - { - switch (x304_orbitState) - { - case EPlayerOrbitState::NoOrbit: - break; - case EPlayerOrbitState::OrbitObject: - if (TCastToConstPtr point = mgr.GetObjectById(x310_orbitTargetId)) - BreakGrapple(EPlayerOrbitRequest::Default, mgr); - else - SetOrbitRequest(EPlayerOrbitRequest::StopOrbit, mgr); - break; - case EPlayerOrbitState::Grapple: - if (!g_tweakPlayer->GetOrbitReleaseBreaksGrapple()) - { - x33c_orbitNextTargetId = FindOrbitTargetId(mgr); - if (x33c_orbitNextTargetId == x310_orbitTargetId) - x33c_orbitNextTargetId = kInvalidUniqueId; - } - else - { - BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); - } - break; - case EPlayerOrbitState::ForcedOrbitObject: - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - UpdateOrbitSelection(input, mgr); - break; - default: - SetOrbitRequest(EPlayerOrbitRequest::StopOrbit, mgr); - break; - } - } -} - -void CPlayer::ActivateOrbitSource(CStateManager& mgr) -{ - switch (x390_orbitSource) - { - default: - OrbitCarcass(mgr); - break; - case 1: - SetOrbitRequest(EPlayerOrbitRequest::InvalidateTarget, mgr); - break; - case 2: - if (x394_orbitingEnemy) - OrbitPoint(EPlayerOrbitType::Far, mgr); + break; + case EPlayerOrbitState::Grapple: + if (x310_orbitTargetId == kInvalidUniqueId) + BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); + break; + case EPlayerOrbitState::OrbitObject: + if (TCastToConstPtr point = mgr.GetObjectById(x310_orbitTargetId)) { + if (ValidateCurrentOrbitTargetId(mgr) == EOrbitValidationResult::OK) + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); else - OrbitCarcass(mgr); - break; - } -} - -void CPlayer::UpdateOrbitSelection(const CFinalInput& input, CStateManager& mgr) -{ - x33c_orbitNextTargetId = FindOrbitTargetId(mgr); - TCastToConstPtr curPoint = mgr.GetObjectById(x310_orbitTargetId); - TCastToConstPtr nextPoint = mgr.GetObjectById(x33c_orbitNextTargetId); - if (curPoint || (x304_orbitState == EPlayerOrbitState::Grapple && !nextPoint)) - { - x33c_orbitNextTargetId = kInvalidUniqueId; - return; - } - - if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitObject, input) && - x33c_orbitNextTargetId != kInvalidUniqueId) - { - SetOrbitTargetId(x33c_orbitNextTargetId, mgr); - if (ValidateAimTargetId(x310_orbitTargetId, mgr)) + BreakGrapple(EPlayerOrbitRequest::InvalidateTarget, mgr); + } else { + EOrbitValidationResult result = ValidateCurrentOrbitTargetId(mgr); + if (result == EOrbitValidationResult::OK) + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + else if (result == EOrbitValidationResult::BrokenLookAngle) + OrbitPoint(EPlayerOrbitType::Far, mgr); + else if (result == EOrbitValidationResult::ExtremeHorizonAngle) + SetOrbitRequest(EPlayerOrbitRequest::BadVerticalAngle, mgr); + else + ActivateOrbitSource(mgr); + } + UpdateOrbitSelection(input, mgr); + break; + case EPlayerOrbitState::OrbitPoint: + if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitObject, input) || m_deferredOrbitObject) { + m_deferredOrbitObject = false; + SetOrbitTargetId(FindOrbitTargetId(mgr), mgr); + if (x310_orbitTargetId != kInvalidUniqueId) { + if (ValidateAimTargetId(x310_orbitTargetId, mgr)) ResetAimTargetPrediction(x310_orbitTargetId); - SetOrbitState(EPlayerOrbitState::OrbitObject, mgr); - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - } -} - -void CPlayer::UpdateOrbitOrientation(CStateManager& mgr) -{ - if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) - return; - - switch (x304_orbitState) - { - case EPlayerOrbitState::OrbitPoint: - if (x3dc_inFreeLook) - return; - case EPlayerOrbitState::OrbitObject: + SetOrbitState(EPlayerOrbitState::OrbitObject, mgr); + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + } + } else { + switch (x308_orbitType) { + case EPlayerOrbitType::Far: + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitClose, input)) { + x308_orbitType = EPlayerOrbitType::Close; + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + } + break; + case EPlayerOrbitType::Close: + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitFar, input) && + !ControlMapper::GetDigitalInput(ControlMapper::ECommands::OrbitClose, input)) { + x308_orbitType = EPlayerOrbitType::Far; + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + } + break; + default: + break; + } + } + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + break; case EPlayerOrbitState::OrbitCarcass: + if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitObject, input) || m_deferredOrbitObject) { + m_deferredOrbitObject = false; + SetOrbitTargetId(FindOrbitTargetId(mgr), mgr); + if (x310_orbitTargetId != kInvalidUniqueId) { + if (ValidateAimTargetId(x310_orbitTargetId, mgr)) + ResetAimTargetPrediction(x310_orbitTargetId); + SetOrbitState(EPlayerOrbitState::OrbitObject, mgr); + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + } + } + UpdateOrbitSelection(input, mgr); + break; case EPlayerOrbitState::ForcedOrbitObject: - { - zeus::CVector3f playerToPoint = x314_orbitPoint - GetTranslation(); - if (!x374_orbitLockEstablished) - playerToPoint = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform().basis[1]; - playerToPoint.z() = 0.f; - if (playerToPoint.canBeNormalized()) - { - zeus::CTransform xf = zeus::lookAt(zeus::CVector3f::skZero, playerToPoint); - xf.origin = GetTranslation(); - SetTransform(xf); - } - break; + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + UpdateOrbitSelection(input, mgr); + break; } - default: - break; - } -} -void CPlayer::UpdateOrbitTarget(CStateManager& mgr) -{ - if (!ValidateOrbitTargetIdAndPointer(x310_orbitTargetId, mgr)) - SetOrbitTargetId(kInvalidUniqueId, mgr); - if (!ValidateOrbitTargetIdAndPointer(x33c_orbitNextTargetId, mgr)) + if (x304_orbitState == EPlayerOrbitState::Grapple) { + x33c_orbitNextTargetId = FindOrbitTargetId(mgr); + if (x33c_orbitNextTargetId == x310_orbitTargetId) x33c_orbitNextTargetId = kInvalidUniqueId; - zeus::CVector3f playerToPoint = x314_orbitPoint - GetTranslation(); - playerToPoint.z() = 0.f; - float playerToPointMag = playerToPoint.magnitude(); - - switch (x304_orbitState) - { - case EPlayerOrbitState::OrbitObject: - if (auto* ent = static_cast(mgr.GetObjectById(x310_orbitTargetId))) - { - if (ent->GetDoTargetDistanceTest() && - (playerToPointMag >= GetOrbitMaxLockDistance(mgr) || playerToPointMag < 0.5f)) - { - if (playerToPointMag < 0.5f) - SetOrbitRequest(EPlayerOrbitRequest::BadVerticalAngle, mgr); - else - ActivateOrbitSource(mgr); - } - } - UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - break; - case EPlayerOrbitState::OrbitPoint: - { - if (g_tweakPlayer->GetOrbitFixedOffset() && - std::fabs(x320_orbitVector.z()) > g_tweakPlayer->GetOrbitFixedOffsetZDiff()) - { - UpdateOrbitFixedPosition(); - return; - } - if (playerToPointMag < CalculateOrbitMinDistance(x308_orbitType)) - UpdateOrbitPosition(CalculateOrbitMinDistance(x308_orbitType), mgr); - float maxDist = g_tweakPlayer->GetOrbitMaxDistance(int(x308_orbitType)); - if (playerToPointMag > maxDist) - UpdateOrbitPosition(maxDist, mgr); - if (x3dd_lookButtonHeld) - SetOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); - zeus::CVector3f eyeToPoint = x314_orbitPoint - GetEyePosition(); - float angleToPoint = std::asin(zeus::clamp(-1.f, std::fabs(eyeToPoint.z()) / eyeToPoint.magnitude(), 1.f)); - if ((eyeToPoint.z() >= 0.f && angleToPoint >= g_tweakPlayer->GetOrbitUpperAngle()) || - (eyeToPoint.z() < 0.f && angleToPoint >= g_tweakPlayer->GetOrbitLowerAngle())) - SetOrbitRequest(EPlayerOrbitRequest::BadVerticalAngle, mgr); - break; - } - case EPlayerOrbitState::OrbitCarcass: - { - if (x3dd_lookButtonHeld) - SetOrbitPosition(x340_, mgr); - if (playerToPointMag < CalculateOrbitMinDistance(x308_orbitType)) - { - UpdateOrbitPosition(CalculateOrbitMinDistance(x308_orbitType), mgr); - x340_ = CalculateOrbitMinDistance(x308_orbitType); - } - float maxDist = g_tweakPlayer->GetOrbitMaxDistance(int(x308_orbitType)); - if (playerToPointMag > maxDist) - { - UpdateOrbitPosition(maxDist, mgr); - x340_ = g_tweakPlayer->GetOrbitMaxDistance(int(x308_orbitType)); - } - break; } + } else { + switch (x304_orbitState) { case EPlayerOrbitState::NoOrbit: - SetOrbitTargetId(kInvalidUniqueId, mgr); - break; - default: break; + break; + case EPlayerOrbitState::OrbitObject: + if (TCastToConstPtr point = mgr.GetObjectById(x310_orbitTargetId)) + BreakGrapple(EPlayerOrbitRequest::Default, mgr); + else + SetOrbitRequest(EPlayerOrbitRequest::StopOrbit, mgr); + break; + case EPlayerOrbitState::Grapple: + if (!g_tweakPlayer->GetOrbitReleaseBreaksGrapple()) { + x33c_orbitNextTargetId = FindOrbitTargetId(mgr); + if (x33c_orbitNextTargetId == x310_orbitTargetId) + x33c_orbitNextTargetId = kInvalidUniqueId; + } else { + BreakGrapple(EPlayerOrbitRequest::StopOrbit, mgr); + } + break; + case EPlayerOrbitState::ForcedOrbitObject: + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + UpdateOrbitSelection(input, mgr); + break; + default: + SetOrbitRequest(EPlayerOrbitRequest::StopOrbit, mgr); + break; } - UpdateOrbitZPosition(); + } } -float CPlayer::GetOrbitMaxLockDistance(CStateManager& mgr) const -{ - return mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan ? - g_tweakPlayer->GetScanMaxLockDistance() : g_tweakPlayer->GetOrbitMaxLockDistance(); +void CPlayer::ActivateOrbitSource(CStateManager& mgr) { + switch (x390_orbitSource) { + default: + OrbitCarcass(mgr); + break; + case 1: + SetOrbitRequest(EPlayerOrbitRequest::InvalidateTarget, mgr); + break; + case 2: + if (x394_orbitingEnemy) + OrbitPoint(EPlayerOrbitType::Far, mgr); + else + OrbitCarcass(mgr); + break; + } } -float CPlayer::GetOrbitMaxTargetDistance(CStateManager& mgr) const -{ - return mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan ? - g_tweakPlayer->GetScanMaxTargetDistance() : g_tweakPlayer->GetOrbitMaxTargetDistance(); +void CPlayer::UpdateOrbitSelection(const CFinalInput& input, CStateManager& mgr) { + x33c_orbitNextTargetId = FindOrbitTargetId(mgr); + TCastToConstPtr curPoint = mgr.GetObjectById(x310_orbitTargetId); + TCastToConstPtr nextPoint = mgr.GetObjectById(x33c_orbitNextTargetId); + if (curPoint || (x304_orbitState == EPlayerOrbitState::Grapple && !nextPoint)) { + x33c_orbitNextTargetId = kInvalidUniqueId; + return; + } + + if (ControlMapper::GetPressInput(ControlMapper::ECommands::OrbitObject, input) && + x33c_orbitNextTargetId != kInvalidUniqueId) { + SetOrbitTargetId(x33c_orbitNextTargetId, mgr); + if (ValidateAimTargetId(x310_orbitTargetId, mgr)) + ResetAimTargetPrediction(x310_orbitTargetId); + SetOrbitState(EPlayerOrbitState::OrbitObject, mgr); + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + } } -CPlayer::EOrbitValidationResult CPlayer::ValidateOrbitTargetId(TUniqueId uid, CStateManager& mgr) const -{ - if (uid == kInvalidUniqueId) - return EOrbitValidationResult::InvalidTarget; +void CPlayer::UpdateOrbitOrientation(CStateManager& mgr) { + if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) + return; - TCastToConstPtr act = mgr.GetObjectById(uid); - if (!act || !act->GetIsTargetable() || !act->GetActive()) - return EOrbitValidationResult::InvalidTarget; + switch (x304_orbitState) { + case EPlayerOrbitState::OrbitPoint: + if (x3dc_inFreeLook) + return; + case EPlayerOrbitState::OrbitObject: + case EPlayerOrbitState::OrbitCarcass: + case EPlayerOrbitState::ForcedOrbitObject: { + zeus::CVector3f playerToPoint = x314_orbitPoint - GetTranslation(); + if (!x374_orbitLockEstablished) + playerToPoint = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform().basis[1]; + playerToPoint.z() = 0.f; + if (playerToPoint.canBeNormalized()) { + zeus::CTransform xf = zeus::lookAt(zeus::CVector3f::skZero, playerToPoint); + xf.origin = GetTranslation(); + SetTransform(xf); + } + break; + } + default: + break; + } +} - if (x740_staticTimer != 0.f) - return EOrbitValidationResult::PlayerNotReadyToTarget; +void CPlayer::UpdateOrbitTarget(CStateManager& mgr) { + if (!ValidateOrbitTargetIdAndPointer(x310_orbitTargetId, mgr)) + SetOrbitTargetId(kInvalidUniqueId, mgr); + if (!ValidateOrbitTargetIdAndPointer(x33c_orbitNextTargetId, mgr)) + x33c_orbitNextTargetId = kInvalidUniqueId; + zeus::CVector3f playerToPoint = x314_orbitPoint - GetTranslation(); + playerToPoint.z() = 0.f; + float playerToPointMag = playerToPoint.magnitude(); + switch (x304_orbitState) { + case EPlayerOrbitState::OrbitObject: + if (auto* ent = static_cast(mgr.GetObjectById(x310_orbitTargetId))) { + if (ent->GetDoTargetDistanceTest() && + (playerToPointMag >= GetOrbitMaxLockDistance(mgr) || playerToPointMag < 0.5f)) { + if (playerToPointMag < 0.5f) + SetOrbitRequest(EPlayerOrbitRequest::BadVerticalAngle, mgr); + else + ActivateOrbitSource(mgr); + } + } + UpdateOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + break; + case EPlayerOrbitState::OrbitPoint: { + if (g_tweakPlayer->GetOrbitFixedOffset() && + std::fabs(x320_orbitVector.z()) > g_tweakPlayer->GetOrbitFixedOffsetZDiff()) { + UpdateOrbitFixedPosition(); + return; + } + if (playerToPointMag < CalculateOrbitMinDistance(x308_orbitType)) + UpdateOrbitPosition(CalculateOrbitMinDistance(x308_orbitType), mgr); + float maxDist = g_tweakPlayer->GetOrbitMaxDistance(int(x308_orbitType)); + if (playerToPointMag > maxDist) + UpdateOrbitPosition(maxDist, mgr); + if (x3dd_lookButtonHeld) + SetOrbitPosition(g_tweakPlayer->GetOrbitNormalDistance(int(x308_orbitType)), mgr); + zeus::CVector3f eyeToPoint = x314_orbitPoint - GetEyePosition(); + float angleToPoint = std::asin(zeus::clamp(-1.f, std::fabs(eyeToPoint.z()) / eyeToPoint.magnitude(), 1.f)); + if ((eyeToPoint.z() >= 0.f && angleToPoint >= g_tweakPlayer->GetOrbitUpperAngle()) || + (eyeToPoint.z() < 0.f && angleToPoint >= g_tweakPlayer->GetOrbitLowerAngle())) + SetOrbitRequest(EPlayerOrbitRequest::BadVerticalAngle, mgr); + break; + } + case EPlayerOrbitState::OrbitCarcass: { + if (x3dd_lookButtonHeld) + SetOrbitPosition(x340_, mgr); + if (playerToPointMag < CalculateOrbitMinDistance(x308_orbitType)) { + UpdateOrbitPosition(CalculateOrbitMinDistance(x308_orbitType), mgr); + x340_ = CalculateOrbitMinDistance(x308_orbitType); + } + float maxDist = g_tweakPlayer->GetOrbitMaxDistance(int(x308_orbitType)); + if (playerToPointMag > maxDist) { + UpdateOrbitPosition(maxDist, mgr); + x340_ = g_tweakPlayer->GetOrbitMaxDistance(int(x308_orbitType)); + } + break; + } + case EPlayerOrbitState::NoOrbit: + SetOrbitTargetId(kInvalidUniqueId, mgr); + break; + default: + break; + } + UpdateOrbitZPosition(); +} + +float CPlayer::GetOrbitMaxLockDistance(CStateManager& mgr) const { + return mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan + ? g_tweakPlayer->GetScanMaxLockDistance() + : g_tweakPlayer->GetOrbitMaxLockDistance(); +} + +float CPlayer::GetOrbitMaxTargetDistance(CStateManager& mgr) const { + return mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan + ? g_tweakPlayer->GetScanMaxTargetDistance() + : g_tweakPlayer->GetOrbitMaxTargetDistance(); +} + +CPlayer::EOrbitValidationResult CPlayer::ValidateOrbitTargetId(TUniqueId uid, CStateManager& mgr) const { + if (uid == kInvalidUniqueId) + return EOrbitValidationResult::InvalidTarget; + + TCastToConstPtr act = mgr.GetObjectById(uid); + if (!act || !act->GetIsTargetable() || !act->GetActive()) + return EOrbitValidationResult::InvalidTarget; + + if (x740_staticTimer != 0.f) + return EOrbitValidationResult::PlayerNotReadyToTarget; + + zeus::CVector3f eyePos = GetEyePosition(); + zeus::CVector3f eyeToOrbit = act->GetOrbitPosition(mgr) - eyePos; + zeus::CVector3f eyeToOrbitFlat = eyeToOrbit; + eyeToOrbitFlat.z() = 0.f; + + if (eyeToOrbitFlat.canBeNormalized() && eyeToOrbitFlat.magnitude() > 1.f) { + float angleFromHorizon = std::asin(zeus::clamp(-1.f, std::fabs(eyeToOrbit.z()) / eyeToOrbit.magnitude(), 1.f)); + if ((eyeToOrbit.z() >= 0.f && angleFromHorizon >= g_tweakPlayer->GetOrbitUpperAngle()) || + (eyeToOrbit.z() < 0.f && angleFromHorizon >= g_tweakPlayer->GetOrbitLowerAngle())) + return EOrbitValidationResult::ExtremeHorizonAngle; + } else { + return EOrbitValidationResult::ExtremeHorizonAngle; + } + + CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetCurrentVisor(); + u8 flags = act->GetTargetableVisorFlags(); + if (visor == CPlayerState::EPlayerVisor::Combat && (flags & 1) == 0) + return EOrbitValidationResult::PlayerNotReadyToTarget; + if (visor == CPlayerState::EPlayerVisor::Scan && (flags & 2) == 0) + return EOrbitValidationResult::PlayerNotReadyToTarget; + if (visor == CPlayerState::EPlayerVisor::Thermal && (flags & 4) == 0) + return EOrbitValidationResult::PlayerNotReadyToTarget; + if (visor == CPlayerState::EPlayerVisor::XRay && (flags & 8) == 0) + return EOrbitValidationResult::PlayerNotReadyToTarget; + + if (visor == CPlayerState::EPlayerVisor::Scan && act->GetAreaIdAlways() != GetAreaIdAlways()) + return EOrbitValidationResult::TargetingThroughDoor; + + return EOrbitValidationResult::OK; +} + +CPlayer::EOrbitValidationResult CPlayer::ValidateCurrentOrbitTargetId(CStateManager& mgr) { + TCastToConstPtr act = mgr.GetObjectById(x310_orbitTargetId); + if (!act || !act->GetIsTargetable() || !act->GetActive()) + return EOrbitValidationResult::InvalidTarget; + + if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Orbit)) { + if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) + return EOrbitValidationResult::NonTargetableTarget; + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) + return EOrbitValidationResult::NonTargetableTarget; + } + + EOrbitValidationResult type = ValidateOrbitTargetId(x310_orbitTargetId, mgr); + if (type != EOrbitValidationResult::OK) + return type; + + if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan && + act->GetAreaIdAlways() != GetAreaIdAlways()) + return EOrbitValidationResult::TargetingThroughDoor; + + TCastToConstPtr point = mgr.GetObjectById(x310_orbitTargetId); + if ((mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan && + g_tweakPlayer->GetOrbitWhileScanning()) || + point || act->GetAreaIdAlways() != GetAreaIdAlways()) { zeus::CVector3f eyePos = GetEyePosition(); + TUniqueId bestId = kInvalidUniqueId; zeus::CVector3f eyeToOrbit = act->GetOrbitPosition(mgr) - eyePos; + if (eyeToOrbit.canBeNormalized()) { + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, eyePos, eyeToOrbit.normalized(), eyeToOrbit.magnitude(), OccluderFilter, + act.GetPtr()); + for (auto it = nearList.begin(); it != nearList.end();) { + if (const CEntity* ent = mgr.GetObjectById(*it)) { + if (ent->GetAreaIdAlways() != mgr.GetNextAreaId()) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(ent->GetAreaIdAlways()); + CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; + if (area->IsPostConstructed()) + occState = area->GetOcclusionState(); + if (occState == CGameArea::EOcclusionState::Occluded) { + it = nearList.erase(it); + continue; + } + } + } + ++it; + } + + CRayCastResult result = mgr.RayWorldIntersection(bestId, eyePos, eyeToOrbit.normalized(), eyeToOrbit.magnitude(), + LineOfSightFilter, nearList); + if (result.IsValid()) + if (TCastToPtr(mgr.ObjectById(bestId)) || point) + return EOrbitValidationResult::TargetingThroughDoor; + } + zeus::CVector3f eyeToOrbitFlat = eyeToOrbit; eyeToOrbitFlat.z() = 0.f; - - if (eyeToOrbitFlat.canBeNormalized() && eyeToOrbitFlat.magnitude() > 1.f) - { - float angleFromHorizon = - std::asin(zeus::clamp(-1.f, std::fabs(eyeToOrbit.z()) / eyeToOrbit.magnitude(), 1.f)); - if ((eyeToOrbit.z() >= 0.f && angleFromHorizon >= g_tweakPlayer->GetOrbitUpperAngle()) || - (eyeToOrbit.z() < 0.f && angleFromHorizon >= g_tweakPlayer->GetOrbitLowerAngle())) - return EOrbitValidationResult::ExtremeHorizonAngle; - } - else - { - return EOrbitValidationResult::ExtremeHorizonAngle; + if (eyeToOrbitFlat.canBeNormalized()) { + float lookToOrbitAngle = + std::acos(zeus::clamp(-1.f, eyeToOrbitFlat.normalized().dot(GetTransform().basis[1]), 1.f)); + if (x374_orbitLockEstablished) { + if (lookToOrbitAngle >= g_tweakPlayer->GetOrbitHorizAngle()) + return EOrbitValidationResult::BrokenLookAngle; + } else { + if (lookToOrbitAngle <= M_PIF / 180.f) + x374_orbitLockEstablished = true; + } + } else { + return EOrbitValidationResult::BrokenLookAngle; } + } - CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetCurrentVisor(); - u8 flags = act->GetTargetableVisorFlags(); - if (visor == CPlayerState::EPlayerVisor::Combat && (flags & 1) == 0) - return EOrbitValidationResult::PlayerNotReadyToTarget; - if (visor == CPlayerState::EPlayerVisor::Scan && (flags & 2) == 0) - return EOrbitValidationResult::PlayerNotReadyToTarget; - if (visor == CPlayerState::EPlayerVisor::Thermal && (flags & 4) == 0) - return EOrbitValidationResult::PlayerNotReadyToTarget; - if (visor == CPlayerState::EPlayerVisor::XRay && (flags & 8) == 0) - return EOrbitValidationResult::PlayerNotReadyToTarget; - - if (visor == CPlayerState::EPlayerVisor::Scan && act->GetAreaIdAlways() != GetAreaIdAlways()) - return EOrbitValidationResult::TargetingThroughDoor; - - return EOrbitValidationResult::OK; + return EOrbitValidationResult::OK; } -CPlayer::EOrbitValidationResult CPlayer::ValidateCurrentOrbitTargetId(CStateManager& mgr) -{ - TCastToConstPtr act = mgr.GetObjectById(x310_orbitTargetId); - if (!act || !act->GetIsTargetable() || !act->GetActive()) - return EOrbitValidationResult::InvalidTarget; - - if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Orbit)) - { - if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable)) - return EOrbitValidationResult::NonTargetableTarget; - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - return EOrbitValidationResult::NonTargetableTarget; - } - - EOrbitValidationResult type = ValidateOrbitTargetId(x310_orbitTargetId, mgr); - if (type != EOrbitValidationResult::OK) - return type; - - if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan && - act->GetAreaIdAlways() != GetAreaIdAlways()) - return EOrbitValidationResult::TargetingThroughDoor; - - TCastToConstPtr point = mgr.GetObjectById(x310_orbitTargetId); - if ((mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan && - g_tweakPlayer->GetOrbitWhileScanning()) || point || act->GetAreaIdAlways() != GetAreaIdAlways()) - { - zeus::CVector3f eyePos = GetEyePosition(); - TUniqueId bestId = kInvalidUniqueId; - zeus::CVector3f eyeToOrbit = act->GetOrbitPosition(mgr) - eyePos; - if (eyeToOrbit.canBeNormalized()) - { - rstl::reserved_vector nearList; - mgr.BuildNearList(nearList, eyePos, eyeToOrbit.normalized(), eyeToOrbit.magnitude(), OccluderFilter, - act.GetPtr()); - for (auto it = nearList.begin() ; it != nearList.end() ;) - { - if (const CEntity* ent = mgr.GetObjectById(*it)) - { - if (ent->GetAreaIdAlways() != mgr.GetNextAreaId()) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(ent->GetAreaIdAlways()); - CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; - if (area->IsPostConstructed()) - occState = area->GetOcclusionState(); - if (occState == CGameArea::EOcclusionState::Occluded) - { - it = nearList.erase(it); - continue; - } - } - } - ++it; - } - - CRayCastResult result = - mgr.RayWorldIntersection(bestId, eyePos, eyeToOrbit.normalized(), eyeToOrbit.magnitude(), - LineOfSightFilter, nearList); - if (result.IsValid()) - if (TCastToPtr(mgr.ObjectById(bestId)) || point) - return EOrbitValidationResult::TargetingThroughDoor; - } - - zeus::CVector3f eyeToOrbitFlat = eyeToOrbit; - eyeToOrbitFlat.z() = 0.f; - if (eyeToOrbitFlat.canBeNormalized()) - { - float lookToOrbitAngle = - std::acos(zeus::clamp(-1.f, eyeToOrbitFlat.normalized().dot(GetTransform().basis[1]), 1.f)); - if (x374_orbitLockEstablished) - { - if (lookToOrbitAngle >= g_tweakPlayer->GetOrbitHorizAngle()) - return EOrbitValidationResult::BrokenLookAngle; - } - else - { - if (lookToOrbitAngle <= M_PIF / 180.f) - x374_orbitLockEstablished = true; - } - } - else - { - return EOrbitValidationResult::BrokenLookAngle; - } - } - - return EOrbitValidationResult::OK; +bool CPlayer::ValidateOrbitTargetIdAndPointer(TUniqueId uid, CStateManager& mgr) const { + if (uid == kInvalidUniqueId) + return false; + return TCastToConstPtr(mgr.GetObjectById(uid)); } -bool CPlayer::ValidateOrbitTargetIdAndPointer(TUniqueId uid, CStateManager& mgr) const -{ - if (uid == kInvalidUniqueId) - return false; - return TCastToConstPtr(mgr.GetObjectById(uid)); +zeus::CVector3f CPlayer::GetBallPosition() const { + return GetTranslation() + zeus::CVector3f(0.f, 0.f, g_tweakPlayer->GetPlayerBallHalfExtent()); } -zeus::CVector3f CPlayer::GetBallPosition() const -{ - return GetTranslation() + zeus::CVector3f(0.f, 0.f, g_tweakPlayer->GetPlayerBallHalfExtent()); +zeus::CVector3f CPlayer::GetEyePosition() const { return GetTranslation() + zeus::CVector3f(0.f, 0.f, GetEyeHeight()); } + +float CPlayer::GetEyeHeight() const { return x9c8_eyeZBias + (x2d8_fpBounds.max.z() - g_tweakPlayer->GetEyeOffset()); } + +float CPlayer::GetUnbiasedEyeHeight() const { return x2d8_fpBounds.max.z() - g_tweakPlayer->GetEyeOffset(); } + +float CPlayer::GetStepUpHeight() const { + if (x258_movementState == EPlayerMovementState::Jump || x258_movementState == EPlayerMovementState::ApplyJump) + return 0.3f; + return CPhysicsActor::GetStepUpHeight(); } -zeus::CVector3f CPlayer::GetEyePosition() const -{ - return GetTranslation() + zeus::CVector3f(0.f, 0.f, GetEyeHeight()); +float CPlayer::GetStepDownHeight() const { + if (x258_movementState == EPlayerMovementState::Jump) + return -1.f; + if (x258_movementState == EPlayerMovementState::ApplyJump) + return 0.1f; + return CPhysicsActor::GetStepDownHeight(); } -float CPlayer::GetEyeHeight() const -{ - return x9c8_eyeZBias + (x2d8_fpBounds.max.z() - g_tweakPlayer->GetEyeOffset()); +void CPlayer::Teleport(const zeus::CTransform& xf, CStateManager& mgr, bool resetBallCam) { + CPhysicsActor::Stop(); + zeus::CVector3f lookDir = xf.basis[1]; + if (lookDir.canBeNormalized()) { + lookDir.normalize(); + SetTransform(zeus::lookAt(zeus::CVector3f::skZero, lookDir)); + SetTranslation(xf.origin); + x500_lookDir = lookDir; + x50c_moveDir = lookDir; + x530_gunDir = lookDir; + x524_lastPosForDirCalc = xf.origin; + x4f8_moveSpeed = 0.f; + x4fc_flatMoveSpeed = 0.f; + x53c_timeMoving = 0.f; + x4a4_moveSpeedAvg.Clear(); + x540_controlDir = lookDir; + x54c_controlDirFlat = lookDir; + } else { + SetTranslation(xf.origin); + } + + x9c5_31_stepCameraZBiasDirty = true; + x9c8_eyeZBias = 0.f; + x1f4_lastNonCollidingState = GetMotionState(); + SetMoveState(EPlayerMovementState::OnGround, mgr); + zeus::CTransform eyeXf = x34_transform; + eyeXf.origin = GetEyePosition(); + mgr.GetCameraManager()->GetFirstPersonCamera()->Reset(eyeXf, mgr); + if (resetBallCam) + mgr.GetCameraManager()->GetBallCamera()->Reset(eyeXf, mgr); + ForceGunOrientation(x34_transform, mgr); + SetOrbitRequest(EPlayerOrbitRequest::Respawn, mgr); } -float CPlayer::GetUnbiasedEyeHeight() const -{ - return x2d8_fpBounds.max.z() - g_tweakPlayer->GetEyeOffset(); -} - -float CPlayer::GetStepUpHeight() const -{ - if (x258_movementState == EPlayerMovementState::Jump || - x258_movementState == EPlayerMovementState::ApplyJump) - return 0.3f; - return CPhysicsActor::GetStepUpHeight(); -} - -float CPlayer::GetStepDownHeight() const -{ - if (x258_movementState == EPlayerMovementState::Jump) - return -1.f; - if (x258_movementState == EPlayerMovementState::ApplyJump) - return 0.1f; - return CPhysicsActor::GetStepDownHeight(); -} - -void CPlayer::Teleport(const zeus::CTransform& xf, CStateManager& mgr, bool resetBallCam) -{ - CPhysicsActor::Stop(); - zeus::CVector3f lookDir = xf.basis[1]; - if (lookDir.canBeNormalized()) - { - lookDir.normalize(); - SetTransform(zeus::lookAt(zeus::CVector3f::skZero, lookDir)); - SetTranslation(xf.origin); - x500_lookDir = lookDir; - x50c_moveDir = lookDir; - x530_gunDir = lookDir; - x524_lastPosForDirCalc = xf.origin; - x4f8_moveSpeed = 0.f; - x4fc_flatMoveSpeed = 0.f; - x53c_timeMoving = 0.f; - x4a4_moveSpeedAvg.Clear(); - x540_controlDir = lookDir; - x54c_controlDirFlat = lookDir; - } - else - { - SetTranslation(xf.origin); - } - - x9c5_31_stepCameraZBiasDirty = true; - x9c8_eyeZBias = 0.f; - x1f4_lastNonCollidingState = GetMotionState(); - SetMoveState(EPlayerMovementState::OnGround, mgr); - zeus::CTransform eyeXf = x34_transform; - eyeXf.origin = GetEyePosition(); - mgr.GetCameraManager()->GetFirstPersonCamera()->Reset(eyeXf, mgr); - if (resetBallCam) - mgr.GetCameraManager()->GetBallCamera()->Reset(eyeXf, mgr); - ForceGunOrientation(x34_transform, mgr); - SetOrbitRequest(EPlayerOrbitRequest::Respawn, mgr); -} - -void CPlayer::BombJump(const zeus::CVector3f& pos, CStateManager& mgr) -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && - x768_morphball->GetBombJumpState() != CMorphBall::EBombJumpState::BombJumpDisabled) - { - zeus::CVector3f posToBall = - GetTranslation() + zeus::CVector3f(0.f, 0.f, g_tweakPlayer->GetPlayerBallHalfExtent()) - pos; - float maxJump = g_tweakPlayer->GetBombJumpHeight(); - if (posToBall.magSquared() < maxJump * maxJump && - posToBall.dot(zeus::CVector3f::skUp) >= -g_tweakPlayer->GetPlayerBallHalfExtent()) - { - float upVel = std::sqrt(2.f * std::fabs(g_tweakPlayer->GetNormalGravAccel()) * - g_tweakPlayer->GetBombJumpRadius()); - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerBump, 0.3f, ERumblePriority::One); - x2a0_ = 0.01f; - switch (GetSurfaceRestraint()) - { - case ESurfaceRestraints::Water: - upVel *= g_tweakPlayer->GetWaterBallJumpFactor(); - break; - case ESurfaceRestraints::Lava: - upVel *= g_tweakPlayer->GetLavaBallJumpFactor(); - break; - case ESurfaceRestraints::PhazonFluid: - upVel *= g_tweakPlayer->GetPhazonBallJumpFactor(); - break; - default: - break; - } - SetVelocityWR(zeus::CVector3f(0.f, 0.f, upVel)); - x768_morphball->SetDamageTimer(0.1f); - x768_morphball->CancelBoosting(); - if (x9d0_bombJumpCount > 0) - { - if (x9d0_bombJumpCount > 2) - { - x9d0_bombJumpCount = 0; - x9d4_bombJumpCheckDelayFrames = 0; - } - else - { - ++x9d0_bombJumpCount; - } - } - else - { - CBallCamera* ballCam = mgr.GetCameraManager()->GetBallCamera(); - if (ballCam->GetTooCloseActorId() != kInvalidUniqueId && ballCam->GetTooCloseActorDistance() < 5.f) - { - x9d0_bombJumpCount = 1; - x9d4_bombJumpCheckDelayFrames = 2; - } - } - CSfxHandle hnd = CSfxManager::AddEmitter(SFXsam_ball_jump, GetTranslation(), zeus::CVector3f::skZero, - false, false, 0x7f, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - } -} - -zeus::CTransform CPlayer::CreateTransformFromMovementDirection() const -{ - zeus::CVector3f moveDir = x50c_moveDir; - if (moveDir.canBeNormalized()) - moveDir.normalize(); - else - moveDir = zeus::CVector3f::skForward; - - return {zeus::CVector3f(moveDir.y(), -moveDir.x(), 0.f), moveDir, zeus::CVector3f::skUp, GetTranslation()}; -} - -const CCollisionPrimitive* CPlayer::GetCollisionPrimitive() const -{ - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Morphed: - return GetCollidableSphere(); - default: - return CPhysicsActor::GetCollisionPrimitive(); - } -} - -const CCollidableSphere* CPlayer::GetCollidableSphere() const -{ - return &x768_morphball->GetCollidableSphere(); -} - -zeus::CTransform CPlayer::GetPrimitiveTransform() const -{ - return CPhysicsActor::GetPrimitiveTransform(); -} - -void CPlayer::CollidedWith(TUniqueId id, const CCollisionInfoList& list, CStateManager& mgr) -{ - if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) - x768_morphball->CollidedWith(id, list, mgr); -} - -float CPlayer::GetBallMaxVelocity() const -{ - return g_tweakBall->GetBallTranslationMaxSpeed(int(GetSurfaceRestraint())); -} - -float CPlayer::GetActualBallMaxVelocity(float dt) const -{ - ESurfaceRestraints surf = GetSurfaceRestraint(); - float friction = g_tweakBall->GetBallTranslationFriction(int(surf)); - float maxSpeed = g_tweakBall->GetBallTranslationMaxSpeed(int(surf)); - float acceleration = g_tweakBall->GetMaxBallTranslationAcceleration(int(surf)); - return -(friction * xe8_mass * maxSpeed / (acceleration * dt) - maxSpeed - friction); -} - -float CPlayer::GetActualFirstPersonMaxVelocity(float dt) const -{ - ESurfaceRestraints surf = GetSurfaceRestraint(); - float friction = g_tweakPlayer->GetPlayerTranslationFriction(int(surf)); - float maxSpeed = g_tweakPlayer->GetPlayerTranslationMaxSpeed(int(surf)); - float acceleration = g_tweakPlayer->GetMaxTranslationalAcceleration(int(surf)); - return -(friction * xe8_mass * maxSpeed / (acceleration * dt) - maxSpeed - friction); -} - -void CPlayer::SetMoveState(EPlayerMovementState newState, CStateManager& mgr) -{ - switch (newState) - { - case EPlayerMovementState::Jump: - if (x258_movementState == EPlayerMovementState::ApplyJump) - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_b_jump_00, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerBump, 0.2015f, ERumblePriority::One); - x288_startingJumpTimeout = g_tweakPlayer->GetAllowedDoubleJumpTime(); - x290_minJumpTimeout = g_tweakPlayer->GetAllowedDoubleJumpTime() - g_tweakPlayer->GetMinDoubleJumpTime(); - x28c_sjTimer = 0.f; - } - else if (x258_movementState != EPlayerMovementState::Jump) - { - CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_firstjump, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - x2a0_ = 0.01f; - x288_startingJumpTimeout = g_tweakPlayer->GetAllowedJumpTime(); - x290_minJumpTimeout = g_tweakPlayer->GetAllowedJumpTime() - g_tweakPlayer->GetMinJumpTime(); - if (mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::SpaceJumpBoots) != 0) - x28c_sjTimer = g_tweakPlayer->GetMaxDoubleJumpWindow(); - else - x28c_sjTimer = 0.f; - if (x294_jumpCameraTimer <= 0.f && x29c_fallCameraTimer <= 0.f && - !x3dc_inFreeLook && !x3dd_lookButtonHeld) - { - x294_jumpCameraTimer = 0.01f; - x2a4_cancelCameraPitch = false; - } - } - x258_movementState = EPlayerMovementState::Jump; - x2ac_surfaceRestraint = ESurfaceRestraints::InAir; - x2a8_timeSinceJump = 0.f; +void CPlayer::BombJump(const zeus::CVector3f& pos, CStateManager& mgr) { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && + x768_morphball->GetBombJumpState() != CMorphBall::EBombJumpState::BombJumpDisabled) { + zeus::CVector3f posToBall = + GetTranslation() + zeus::CVector3f(0.f, 0.f, g_tweakPlayer->GetPlayerBallHalfExtent()) - pos; + float maxJump = g_tweakPlayer->GetBombJumpHeight(); + if (posToBall.magSquared() < maxJump * maxJump && + posToBall.dot(zeus::CVector3f::skUp) >= -g_tweakPlayer->GetPlayerBallHalfExtent()) { + float upVel = + std::sqrt(2.f * std::fabs(g_tweakPlayer->GetNormalGravAccel()) * g_tweakPlayer->GetBombJumpRadius()); + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerBump, 0.3f, ERumblePriority::One); + x2a0_ = 0.01f; + switch (GetSurfaceRestraint()) { + case ESurfaceRestraints::Water: + upVel *= g_tweakPlayer->GetWaterBallJumpFactor(); break; - case EPlayerMovementState::Falling: - if (x258_movementState == EPlayerMovementState::OnGround) - { - x288_startingJumpTimeout = g_tweakPlayer->GetAllowedLedgeTime(); - x258_movementState = EPlayerMovementState::Falling; - x2a0_ = 0.01f; - if (g_tweakPlayer->GetFallingDoubleJump()) - x28c_sjTimer = g_tweakPlayer->GetMaxDoubleJumpWindow(); - else - x28c_sjTimer = 0.f; + case ESurfaceRestraints::Lava: + upVel *= g_tweakPlayer->GetLavaBallJumpFactor(); + break; + case ESurfaceRestraints::PhazonFluid: + upVel *= g_tweakPlayer->GetPhazonBallJumpFactor(); + break; + default: + break; + } + SetVelocityWR(zeus::CVector3f(0.f, 0.f, upVel)); + x768_morphball->SetDamageTimer(0.1f); + x768_morphball->CancelBoosting(); + if (x9d0_bombJumpCount > 0) { + if (x9d0_bombJumpCount > 2) { + x9d0_bombJumpCount = 0; + x9d4_bombJumpCheckDelayFrames = 0; + } else { + ++x9d0_bombJumpCount; } - break; - case EPlayerMovementState::FallingMorphed: - x258_movementState = EPlayerMovementState::FallingMorphed; - x2ac_surfaceRestraint = ESurfaceRestraints::Normal; - break; - case EPlayerMovementState::OnGround: - x300_fallingTime = 0.f; - x258_movementState = EPlayerMovementState::OnGround; - x288_startingJumpTimeout = 0.f; + } else { + CBallCamera* ballCam = mgr.GetCameraManager()->GetBallCamera(); + if (ballCam->GetTooCloseActorId() != kInvalidUniqueId && ballCam->GetTooCloseActorDistance() < 5.f) { + x9d0_bombJumpCount = 1; + x9d4_bombJumpCheckDelayFrames = 2; + } + } + CSfxHandle hnd = CSfxManager::AddEmitter(SFXsam_ball_jump, GetTranslation(), zeus::CVector3f::skZero, false, + false, 0x7f, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } + } +} + +zeus::CTransform CPlayer::CreateTransformFromMovementDirection() const { + zeus::CVector3f moveDir = x50c_moveDir; + if (moveDir.canBeNormalized()) + moveDir.normalize(); + else + moveDir = zeus::CVector3f::skForward; + + return {zeus::CVector3f(moveDir.y(), -moveDir.x(), 0.f), moveDir, zeus::CVector3f::skUp, GetTranslation()}; +} + +const CCollisionPrimitive* CPlayer::GetCollisionPrimitive() const { + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Morphed: + return GetCollidableSphere(); + default: + return CPhysicsActor::GetCollisionPrimitive(); + } +} + +const CCollidableSphere* CPlayer::GetCollidableSphere() const { return &x768_morphball->GetCollidableSphere(); } + +zeus::CTransform CPlayer::GetPrimitiveTransform() const { return CPhysicsActor::GetPrimitiveTransform(); } + +void CPlayer::CollidedWith(TUniqueId id, const CCollisionInfoList& list, CStateManager& mgr) { + if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed) + x768_morphball->CollidedWith(id, list, mgr); +} + +float CPlayer::GetBallMaxVelocity() const { + return g_tweakBall->GetBallTranslationMaxSpeed(int(GetSurfaceRestraint())); +} + +float CPlayer::GetActualBallMaxVelocity(float dt) const { + ESurfaceRestraints surf = GetSurfaceRestraint(); + float friction = g_tweakBall->GetBallTranslationFriction(int(surf)); + float maxSpeed = g_tweakBall->GetBallTranslationMaxSpeed(int(surf)); + float acceleration = g_tweakBall->GetMaxBallTranslationAcceleration(int(surf)); + return -(friction * xe8_mass * maxSpeed / (acceleration * dt) - maxSpeed - friction); +} + +float CPlayer::GetActualFirstPersonMaxVelocity(float dt) const { + ESurfaceRestraints surf = GetSurfaceRestraint(); + float friction = g_tweakPlayer->GetPlayerTranslationFriction(int(surf)); + float maxSpeed = g_tweakPlayer->GetPlayerTranslationMaxSpeed(int(surf)); + float acceleration = g_tweakPlayer->GetMaxTranslationalAcceleration(int(surf)); + return -(friction * xe8_mass * maxSpeed / (acceleration * dt) - maxSpeed - friction); +} + +void CPlayer::SetMoveState(EPlayerMovementState newState, CStateManager& mgr) { + switch (newState) { + case EPlayerMovementState::Jump: + if (x258_movementState == EPlayerMovementState::ApplyJump) { + CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_b_jump_00, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerBump, 0.2015f, ERumblePriority::One); + x288_startingJumpTimeout = g_tweakPlayer->GetAllowedDoubleJumpTime(); + x290_minJumpTimeout = g_tweakPlayer->GetAllowedDoubleJumpTime() - g_tweakPlayer->GetMinDoubleJumpTime(); + x28c_sjTimer = 0.f; + } else if (x258_movementState != EPlayerMovementState::Jump) { + CSfxHandle hnd = CSfxManager::SfxStart(SFXsam_firstjump, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + x2a0_ = 0.01f; + x288_startingJumpTimeout = g_tweakPlayer->GetAllowedJumpTime(); + x290_minJumpTimeout = g_tweakPlayer->GetAllowedJumpTime() - g_tweakPlayer->GetMinJumpTime(); + if (mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::SpaceJumpBoots) != 0) + x28c_sjTimer = g_tweakPlayer->GetMaxDoubleJumpWindow(); + else x28c_sjTimer = 0.f; - x2ac_surfaceRestraint = ESurfaceRestraints::Normal; - if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) - AddMaterial(EMaterialTypes::GroundCollider); - x294_jumpCameraTimer = 0.f; - x29c_fallCameraTimer = 0.f; + if (x294_jumpCameraTimer <= 0.f && x29c_fallCameraTimer <= 0.f && !x3dc_inFreeLook && !x3dd_lookButtonHeld) { + x294_jumpCameraTimer = 0.01f; x2a4_cancelCameraPitch = false; - x298_jumpPresses = 0; - break; - case EPlayerMovementState::ApplyJump: - x288_startingJumpTimeout = 0.f; - if (x258_movementState != EPlayerMovementState::ApplyJump) - { - x258_movementState = EPlayerMovementState::ApplyJump; - if (x294_jumpCameraTimer <= x288_startingJumpTimeout && - x29c_fallCameraTimer <= x288_startingJumpTimeout && - !x3dc_inFreeLook && !x3dd_lookButtonHeld) - { - x29c_fallCameraTimer = 0.01f; - x2a4_cancelCameraPitch = false; - } - } - x2ac_surfaceRestraint = ESurfaceRestraints::InAir; - break; + } } + x258_movementState = EPlayerMovementState::Jump; + x2ac_surfaceRestraint = ESurfaceRestraints::InAir; + x2a8_timeSinceJump = 0.f; + break; + case EPlayerMovementState::Falling: + if (x258_movementState == EPlayerMovementState::OnGround) { + x288_startingJumpTimeout = g_tweakPlayer->GetAllowedLedgeTime(); + x258_movementState = EPlayerMovementState::Falling; + x2a0_ = 0.01f; + if (g_tweakPlayer->GetFallingDoubleJump()) + x28c_sjTimer = g_tweakPlayer->GetMaxDoubleJumpWindow(); + else + x28c_sjTimer = 0.f; + } + break; + case EPlayerMovementState::FallingMorphed: + x258_movementState = EPlayerMovementState::FallingMorphed; + x2ac_surfaceRestraint = ESurfaceRestraints::Normal; + break; + case EPlayerMovementState::OnGround: + x300_fallingTime = 0.f; + x258_movementState = EPlayerMovementState::OnGround; + x288_startingJumpTimeout = 0.f; + x28c_sjTimer = 0.f; + x2ac_surfaceRestraint = ESurfaceRestraints::Normal; + if (x2f8_morphBallState != EPlayerMorphBallState::Morphed) + AddMaterial(EMaterialTypes::GroundCollider); + x294_jumpCameraTimer = 0.f; + x29c_fallCameraTimer = 0.f; + x2a4_cancelCameraPitch = false; + x298_jumpPresses = 0; + break; + case EPlayerMovementState::ApplyJump: + x288_startingJumpTimeout = 0.f; + if (x258_movementState != EPlayerMovementState::ApplyJump) { + x258_movementState = EPlayerMovementState::ApplyJump; + if (x294_jumpCameraTimer <= x288_startingJumpTimeout && x29c_fallCameraTimer <= x288_startingJumpTimeout && + !x3dc_inFreeLook && !x3dd_lookButtonHeld) { + x29c_fallCameraTimer = 0.01f; + x2a4_cancelCameraPitch = false; + } + } + x2ac_surfaceRestraint = ESurfaceRestraints::InAir; + break; + } } -float CPlayer::JumpInput(const CFinalInput& input, CStateManager& mgr) -{ - if (IsMorphBallTransitioning()) - return GetGravity() * xe8_mass; - float jumpFactor = 1.f; - if (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) - { - ESurfaceRestraints restraints = GetSurfaceRestraint(); - switch (restraints) - { - case ESurfaceRestraints::Water: - jumpFactor = g_tweakPlayer->GetWaterJumpFactor(); - break; - case ESurfaceRestraints::Lava: - jumpFactor = g_tweakPlayer->GetLavaJumpFactor(); - break; - case ESurfaceRestraints::PhazonFluid: - jumpFactor = g_tweakPlayer->GetPhazonJumpFactor(); - break; - default: - break; - } +float CPlayer::JumpInput(const CFinalInput& input, CStateManager& mgr) { + if (IsMorphBallTransitioning()) + return GetGravity() * xe8_mass; + float jumpFactor = 1.f; + if (!mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit)) { + ESurfaceRestraints restraints = GetSurfaceRestraint(); + switch (restraints) { + case ESurfaceRestraints::Water: + jumpFactor = g_tweakPlayer->GetWaterJumpFactor(); + break; + case ESurfaceRestraints::Lava: + jumpFactor = g_tweakPlayer->GetLavaJumpFactor(); + break; + case ESurfaceRestraints::PhazonFluid: + jumpFactor = g_tweakPlayer->GetPhazonJumpFactor(); + break; + default: + break; + } + } + + float vJumpAccel = g_tweakPlayer->GetVerticalJumpAccel(); + float hJumpAccel = g_tweakPlayer->GetHorizontalJumpAccel(); + float doubleJumpImpulse = g_tweakPlayer->GetDoubleJumpImpulse(); + float vDoubleJumpAccel = g_tweakPlayer->GetVerticalDoubleJumpAccel(); + float hDoubleJumpAccel = g_tweakPlayer->GetHorizontalDoubleJumpAccel(); + + if (x37c_sidewaysDashing) { + doubleJumpImpulse = g_tweakPlayer->GetSidewaysDoubleJumpImpulse(); + vDoubleJumpAccel = g_tweakPlayer->GetSidewaysVerticalDoubleJumpAccel(); + hDoubleJumpAccel = g_tweakPlayer->GetSidewaysHorizontalDoubleJumpAccel(); + } + + if (x828_distanceUnderWater >= 0.8f * GetEyeHeight()) + doubleJumpImpulse *= jumpFactor; + + if (x258_movementState == EPlayerMovementState::ApplyJump) { + if (g_tweakPlayer->GetMaxDoubleJumpWindow() - g_tweakPlayer->GetMinDoubleJumpWindow() >= x28c_sjTimer && + 0.f < x28c_sjTimer && ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) { + SetMoveState(EPlayerMovementState::Jump, mgr); + x384_dashTimer = 0.f; + x380_strafeInputAtDash = StrafeInput(input); + if (g_tweakPlayer->GetImpulseDoubleJump()) { + zeus::CVector3f impulse(0.f, 0.f, (doubleJumpImpulse - x138_velocity.z()) * xe8_mass); + ApplyImpulseWR(impulse, zeus::CAxisAngle::sIdentity); + } + + float forwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input); + float backwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); + if (forwards < backwards) + forwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); + return ((vDoubleJumpAccel - (vDoubleJumpAccel - hDoubleJumpAccel) * forwards) * xe8_mass) * jumpFactor; } - float vJumpAccel = g_tweakPlayer->GetVerticalJumpAccel(); - float hJumpAccel = g_tweakPlayer->GetHorizontalJumpAccel(); - float doubleJumpImpulse = g_tweakPlayer->GetDoubleJumpImpulse(); - float vDoubleJumpAccel = g_tweakPlayer->GetVerticalDoubleJumpAccel(); - float hDoubleJumpAccel = g_tweakPlayer->GetHorizontalDoubleJumpAccel(); + return GetGravity() * xe8_mass; + } - if (x37c_sidewaysDashing) - { - doubleJumpImpulse = g_tweakPlayer->GetSidewaysDoubleJumpImpulse(); - vDoubleJumpAccel = g_tweakPlayer->GetSidewaysVerticalDoubleJumpAccel(); - hDoubleJumpAccel = g_tweakPlayer->GetSidewaysHorizontalDoubleJumpAccel(); + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) || + (x258_movementState == EPlayerMovementState::Jump && x290_minJumpTimeout <= x288_startingJumpTimeout)) { + if (x258_movementState != EPlayerMovementState::Jump) { + if (ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) { + SetMoveState(EPlayerMovementState::Jump, mgr); + return (vJumpAccel * xe8_mass) * jumpFactor; + } + return 0.f; } - - if (x828_distanceUnderWater >= 0.8f * GetEyeHeight()) - doubleJumpImpulse *= jumpFactor; - - if (x258_movementState == EPlayerMovementState::ApplyJump) - { - if (g_tweakPlayer->GetMaxDoubleJumpWindow() - g_tweakPlayer->GetMinDoubleJumpWindow() >= x28c_sjTimer && - 0.f < x28c_sjTimer && ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) - { - SetMoveState(EPlayerMovementState::Jump, mgr); - x384_dashTimer = 0.f; - x380_strafeInputAtDash = StrafeInput(input); - if (g_tweakPlayer->GetImpulseDoubleJump()) - { - zeus::CVector3f impulse(0.f, 0.f, (doubleJumpImpulse - x138_velocity.z()) * xe8_mass); - ApplyImpulseWR(impulse, zeus::CAxisAngle::sIdentity); - } - - float forwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input); - float backwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); - if (forwards < backwards) - forwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); - return ((vDoubleJumpAccel - (vDoubleJumpAccel - hDoubleJumpAccel) * forwards) * xe8_mass) * jumpFactor; - } - - return GetGravity() * xe8_mass; - } - - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) || - (x258_movementState == EPlayerMovementState::Jump && x290_minJumpTimeout <= x288_startingJumpTimeout)) - { - if (x258_movementState != EPlayerMovementState::Jump) - { - if (ControlMapper::GetPressInput(ControlMapper::ECommands::JumpOrBoost, input)) - { - SetMoveState(EPlayerMovementState::Jump, mgr); - return (vJumpAccel * xe8_mass) * jumpFactor; - } - return 0.f; - } - float forwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input); - float backwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); - if (forwards < backwards) - forwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); - return ((vJumpAccel - (vJumpAccel - hJumpAccel) * forwards) * xe8_mass) * jumpFactor; - } - - if (x258_movementState == EPlayerMovementState::Jump) - SetMoveState(EPlayerMovementState::ApplyJump, mgr); - - return 0.f; -} - -float CPlayer::TurnInput(const CFinalInput& input) const -{ - if (x304_orbitState == EPlayerOrbitState::OrbitObject || x304_orbitState == EPlayerOrbitState::Grapple) - return 0.f; - if (IsMorphBallTransitioning()) - return 0.f; - - float left = ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input); - float right = ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input); - - if (g_tweakPlayer->GetFreeLookTurnsPlayer()) - { - if (!g_tweakPlayer->GetHoldButtonsForFreeLook() || x3dd_lookButtonHeld) - { - if (left < 0.01f && right < 0.01f) - { - left = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input); - right = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input); - } - } - } - else - { - if (!g_tweakPlayer->GetHoldButtonsForFreeLook() || x3dd_lookButtonHeld) - { - if (left < 0.01f && right < 0.01f) - { - float f31 = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input); - float f1 = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input); - if (f31 > 0.01f || f1 > 0.01f) - return 0.f; - } - } - } - - right = left - right; - if (x32c_orbitModeTimer > 0.f) - right *= (1.f - zeus::clamp(0.f, x32c_orbitModeTimer / g_tweakPlayer->GetOrbitModeTimer(), 1.f) * 0.5f); - return zeus::clamp(-1.f, right, 1.f); -} - -float CPlayer::StrafeInput(const CFinalInput& input) const -{ - if (IsMorphBallTransitioning() || x304_orbitState == EPlayerOrbitState::NoOrbit) - return 0.f; - return ControlMapper::GetAnalogInput(ControlMapper::ECommands::StrafeRight, input) - - ControlMapper::GetAnalogInput(ControlMapper::ECommands::StrafeLeft, input); -} - -float CPlayer::ForwardInput(const CFinalInput& input, float turnInput) const -{ float forwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input); float backwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); - if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || InGrappleJumpCooldown()) - backwards = 0.f; - if (x2f8_morphBallState == EPlayerMorphBallState::Morphing && x584_ballTransitionAnim == 2) - forwards = 0.f; - if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphing && x584_ballTransitionAnim == 5) - forwards = 0.f; - if (forwards >= 0.001f) - { - forwards = zeus::clamp(-1.f, forwards / 0.8f, 1.f); - if (std::fabs(std::atan2(std::fabs(turnInput), forwards)) < M_PIF / 3.6f) - { - zeus::CVector3f x50(std::fabs(turnInput), forwards, 0.f); - if (x50.canBeNormalized()) - forwards = x50.magnitude(); - } - } - if (backwards >= 0.001f) - { - backwards = zeus::clamp(-1.f, backwards / 0.8f, 1.f); - if (std::fabs(std::atan2(std::fabs(turnInput), backwards)) < M_PIF / 3.6f) - { - zeus::CVector3f x5c(std::fabs(turnInput), backwards, 0.f); - if (x5c.canBeNormalized()) - backwards = x5c.magnitude(); - } - } + if (forwards < backwards) + forwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); + return ((vJumpAccel - (vJumpAccel - hJumpAccel) * forwards) * xe8_mass) * jumpFactor; + } - if (!g_tweakPlayer->GetMoveDuringFreeLook()) - { - zeus::CVector3f velFlat = x138_velocity; - velFlat.z() = 0.f; - if (x3dc_inFreeLook || x3dd_lookButtonHeld) - if (x258_movementState == EPlayerMovementState::OnGround || std::fabs(velFlat.magnitude()) < 0.00001f) - return 0.f; - } + if (x258_movementState == EPlayerMovementState::Jump) + SetMoveState(EPlayerMovementState::ApplyJump, mgr); - return zeus::clamp(-1.f, forwards - backwards * g_tweakPlayer->GetBackwardsForceMultiplier(), 1.f); + return 0.f; } -zeus::CVector3f CPlayer::CalculateLeftStickEdgePosition(float strafeInput, float forwardInput) const -{ - float f31 = -1.f; - float f30 = -0.555f; - float f29 = 0.555f; +float CPlayer::TurnInput(const CFinalInput& input) const { + if (x304_orbitState == EPlayerOrbitState::OrbitObject || x304_orbitState == EPlayerOrbitState::Grapple) + return 0.f; + if (IsMorphBallTransitioning()) + return 0.f; - if (strafeInput >= 0.f) - { - f31 = -f31; - f30 = -f30; + float left = ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input); + float right = ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input); + + if (g_tweakPlayer->GetFreeLookTurnsPlayer()) { + if (!g_tweakPlayer->GetHoldButtonsForFreeLook() || x3dd_lookButtonHeld) { + if (left < 0.01f && right < 0.01f) { + left = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input); + right = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input); + } } + } else { + if (!g_tweakPlayer->GetHoldButtonsForFreeLook() || x3dd_lookButtonHeld) { + if (left < 0.01f && right < 0.01f) { + float f31 = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookLeft, input); + float f1 = ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookRight, input); + if (f31 > 0.01f || f1 > 0.01f) + return 0.f; + } + } + } - if (forwardInput < 0.f) - f29 = -0.555f; - - float f4 = zeus::clamp(-1.f, std::atan(std::fabs(forwardInput) / std::fabs(strafeInput)) / (M_PIF / 4.f), 1.f); - return zeus::CVector3f(f30 - f31, f29, 0.f) * f4 + zeus::CVector3f(f31, 0.f, 0.f); + right = left - right; + if (x32c_orbitModeTimer > 0.f) + right *= (1.f - zeus::clamp(0.f, x32c_orbitModeTimer / g_tweakPlayer->GetOrbitModeTimer(), 1.f) * 0.5f); + return zeus::clamp(-1.f, right, 1.f); } -bool CPlayer::SidewaysDashAllowed(float strafeInput, float forwardInput, - const CFinalInput& input, CStateManager& mgr) const -{ - if (x9c5_28_slidingOnWall || x9c5_29_hitWall || x304_orbitState != EPlayerOrbitState::OrbitObject) - return false; +float CPlayer::StrafeInput(const CFinalInput& input) const { + if (IsMorphBallTransitioning() || x304_orbitState == EPlayerOrbitState::NoOrbit) + return 0.f; + return ControlMapper::GetAnalogInput(ControlMapper::ECommands::StrafeRight, input) - + ControlMapper::GetAnalogInput(ControlMapper::ECommands::StrafeLeft, input); +} - if (g_tweakPlayer->GetDashOnButtonRelease()) - { - if (x304_orbitState != EPlayerOrbitState::NoOrbit && g_tweakPlayer->GetDashEnabled() && - x288_startingJumpTimeout > 0.f && - !ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) && - x388_dashButtonHoldTime < g_tweakPlayer->GetDashButtonHoldCancelTime() && - std::fabs(strafeInput) >= std::fabs(forwardInput) && - std::fabs(strafeInput) > g_tweakPlayer->GetDashStrafeInputThreshold()) - return true; +float CPlayer::ForwardInput(const CFinalInput& input, float turnInput) const { + float forwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input); + float backwards = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input); + if (x2f8_morphBallState != EPlayerMorphBallState::Unmorphed || InGrappleJumpCooldown()) + backwards = 0.f; + if (x2f8_morphBallState == EPlayerMorphBallState::Morphing && x584_ballTransitionAnim == 2) + forwards = 0.f; + if (x2f8_morphBallState == EPlayerMorphBallState::Unmorphing && x584_ballTransitionAnim == 5) + forwards = 0.f; + if (forwards >= 0.001f) { + forwards = zeus::clamp(-1.f, forwards / 0.8f, 1.f); + if (std::fabs(std::atan2(std::fabs(turnInput), forwards)) < M_PIF / 3.6f) { + zeus::CVector3f x50(std::fabs(turnInput), forwards, 0.f); + if (x50.canBeNormalized()) + forwards = x50.magnitude(); } - else - { - if (x304_orbitState != EPlayerOrbitState::NoOrbit && g_tweakPlayer->GetDashEnabled() && - ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) && - x288_startingJumpTimeout > 0.f && - std::fabs(strafeInput) >= std::fabs(forwardInput) && - std::fabs(strafeInput) > 0.01f) - { - float threshold = std::sqrt(strafeInput * strafeInput + forwardInput * forwardInput) / - CalculateLeftStickEdgePosition(strafeInput, forwardInput).magnitude(); - if (threshold >= g_tweakPlayer->GetDashStrafeInputThreshold()) - return true; - } + } + if (backwards >= 0.001f) { + backwards = zeus::clamp(-1.f, backwards / 0.8f, 1.f); + if (std::fabs(std::atan2(std::fabs(turnInput), backwards)) < M_PIF / 3.6f) { + zeus::CVector3f x5c(std::fabs(turnInput), backwards, 0.f); + if (x5c.canBeNormalized()) + backwards = x5c.magnitude(); } + } + if (!g_tweakPlayer->GetMoveDuringFreeLook()) { + zeus::CVector3f velFlat = x138_velocity; + velFlat.z() = 0.f; + if (x3dc_inFreeLook || x3dd_lookButtonHeld) + if (x258_movementState == EPlayerMovementState::OnGround || std::fabs(velFlat.magnitude()) < 0.00001f) + return 0.f; + } + + return zeus::clamp(-1.f, forwards - backwards * g_tweakPlayer->GetBackwardsForceMultiplier(), 1.f); +} + +zeus::CVector3f CPlayer::CalculateLeftStickEdgePosition(float strafeInput, float forwardInput) const { + float f31 = -1.f; + float f30 = -0.555f; + float f29 = 0.555f; + + if (strafeInput >= 0.f) { + f31 = -f31; + f30 = -f30; + } + + if (forwardInput < 0.f) + f29 = -0.555f; + + float f4 = zeus::clamp(-1.f, std::atan(std::fabs(forwardInput) / std::fabs(strafeInput)) / (M_PIF / 4.f), 1.f); + return zeus::CVector3f(f30 - f31, f29, 0.f) * f4 + zeus::CVector3f(f31, 0.f, 0.f); +} + +bool CPlayer::SidewaysDashAllowed(float strafeInput, float forwardInput, const CFinalInput& input, + CStateManager& mgr) const { + if (x9c5_28_slidingOnWall || x9c5_29_hitWall || x304_orbitState != EPlayerOrbitState::OrbitObject) return false; + + if (g_tweakPlayer->GetDashOnButtonRelease()) { + if (x304_orbitState != EPlayerOrbitState::NoOrbit && g_tweakPlayer->GetDashEnabled() && + x288_startingJumpTimeout > 0.f && + !ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) && + x388_dashButtonHoldTime < g_tweakPlayer->GetDashButtonHoldCancelTime() && + std::fabs(strafeInput) >= std::fabs(forwardInput) && + std::fabs(strafeInput) > g_tweakPlayer->GetDashStrafeInputThreshold()) + return true; + } else { + if (x304_orbitState != EPlayerOrbitState::NoOrbit && g_tweakPlayer->GetDashEnabled() && + ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input) && + x288_startingJumpTimeout > 0.f && std::fabs(strafeInput) >= std::fabs(forwardInput) && + std::fabs(strafeInput) > 0.01f) { + float threshold = std::sqrt(strafeInput * strafeInput + forwardInput * forwardInput) / + CalculateLeftStickEdgePosition(strafeInput, forwardInput).magnitude(); + if (threshold >= g_tweakPlayer->GetDashStrafeInputThreshold()) + return true; + } + } + + return false; } -void CPlayer::FinishSidewaysDash() -{ +void CPlayer::FinishSidewaysDash() { + if (x37c_sidewaysDashing) + x38c_doneSidewaysDashing = true; + x37c_sidewaysDashing = false; + x380_strafeInputAtDash = 0.f; + x384_dashTimer = 0.f; +} + +void CPlayer::ComputeDash(const CFinalInput& input, float dt, CStateManager& mgr) { + float strafeInput = StrafeInput(input); + float forwardInput = ForwardInput(input, TurnInput(input)); + zeus::CVector3f orbitPointFlattened(x314_orbitPoint.x(), x314_orbitPoint.y(), GetTranslation().z()); + zeus::CVector3f orbitToPlayer = GetTranslation() - orbitPointFlattened; + if (!orbitToPlayer.canBeNormalized()) + return; + zeus::CVector3f useOrbitToPlayer = orbitToPlayer; + ESurfaceRestraints restraints = GetSurfaceRestraint(); + float strafeVel = dt * skStrafeDistances[int(restraints)]; + if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input)) + x388_dashButtonHoldTime += dt; + if (!x37c_sidewaysDashing) { + if (SidewaysDashAllowed(strafeInput, forwardInput, input, mgr)) { + x37c_sidewaysDashing = true; + x380_strafeInputAtDash = strafeInput; + x38c_doneSidewaysDashing = true; + x384_dashTimer = 0.f; + zeus::CVector3f vel = x138_velocity; + if (vel.z() > 0.f) { + vel.z() *= 0.1f; + if (!x9c5_28_slidingOnWall) { + SetVelocityWR(vel); + x778_dashSfx = CSfxManager::SfxStart(SFXsam_dash, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(x778_dashSfx); + mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerBump, 0.24375f, ERumblePriority::One); + } + } + } + strafeVel *= strafeInput; + } else { + x384_dashTimer += dt; + if (x258_movementState == EPlayerMovementState::OnGround || x384_dashTimer >= x3a0_dashDuration || + x9c5_28_slidingOnWall || x9c5_29_hitWall || x304_orbitState != EPlayerOrbitState::OrbitObject) { + FinishSidewaysDash(); + strafeVel *= strafeInput; + CSfxManager::RemoveEmitter(x778_dashSfx); + } else { + if (x39c_noStrafeDashBlend) { + strafeVel = dt * skDashStrafeDistances[int(restraints)] * x398_dashSpeedMultiplier; + } else { + strafeVel = ((skDashStrafeDistances[int(restraints)] - skStrafeDistances[int(restraints)]) * + (1.f - zeus::clamp(-1.f, x384_dashTimer / x3a4_strafeDashBlendDuration, 1.f)) + + skStrafeDistances[int(restraints)]) * + x398_dashSpeedMultiplier * dt; + } + if (x380_strafeInputAtDash < 0.f) + strafeVel = -strafeVel; + } + } + + float f3 = strafeVel / orbitToPlayer.magnitude(); + float f2 = dt * (x37c_sidewaysDashing ? M_PIF : (M_PIF * 2.f / 3.f)); + useOrbitToPlayer = + zeus::CQuaternion::fromAxisAngle(zeus::CVector3f::skUp, zeus::clamp(-f2, f3, f2)).transform(orbitToPlayer); + orbitPointFlattened += useOrbitToPlayer; + if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input)) + x388_dashButtonHoldTime = 0.f; + strafeVel = skOrbitForwardDistances[int(restraints)] * forwardInput * dt; + orbitPointFlattened += -useOrbitToPlayer.normalized() * strafeVel; + zeus::CVector2f velFlat(x138_velocity.x(), x138_velocity.y()); + zeus::CVector3f newVelocity = (orbitPointFlattened - GetTranslation()) / dt; + zeus::CVector3f velDelta(newVelocity.x() - x138_velocity.x(), newVelocity.y() - x138_velocity.y(), 0.f); + strafeVel = velDelta.magnitude(); + if (strafeVel > FLT_EPSILON) { + float accel = dt * GetAcceleration(); + newVelocity = velDelta / strafeVel * accel * zeus::clamp(-1.f, strafeVel / accel, 1.f) + x138_velocity; + if (!x9c5_28_slidingOnWall) + SetVelocityWR(newVelocity); + } +} + +void CPlayer::ComputeMovement(const CFinalInput& input, CStateManager& mgr, float dt) { + ESurfaceRestraints restraints = GetSurfaceRestraint(); + + float jumpInput = JumpInput(input, mgr); + float zRotateInput = TurnInput(input); + float forwardInput = ForwardInput(input, zRotateInput); + SetVelocityWR(GetDampedClampedVelocityWR()); + float turnSpeedMul = g_tweakPlayer->GetTurnSpeedMultiplier(); + if (g_tweakPlayer->GetFreeLookTurnsPlayer()) + if (!g_tweakPlayer->GetHoldButtonsForFreeLook() || x3dd_lookButtonHeld) + turnSpeedMul = g_tweakPlayer->GetFreeLookTurnSpeedMultiplier(); + + if (x304_orbitState == EPlayerOrbitState::NoOrbit || + (x3dd_lookButtonHeld && x304_orbitState != EPlayerOrbitState::OrbitObject && + x304_orbitState != EPlayerOrbitState::Grapple)) { + if (std::fabs(zRotateInput) < 0.00001f) { + float frictionZAngVel = + g_tweakPlayer->GetPlayerRotationFriction(int(restraints)) * GetAngularVelocityOR().getVector().z(); + SetAngularVelocityOR({0.f, 0.f, frictionZAngVel}); + } + + float curZAngVel = GetAngularVelocityOR().getVector().z(); + float maxZAngVel = g_tweakPlayer->GetPlayerRotationMaxSpeed(int(restraints)) * turnSpeedMul; + if (curZAngVel > maxZAngVel) + SetAngularVelocityOR({0.f, 0.f, maxZAngVel}); + else if (-curZAngVel > maxZAngVel) + SetAngularVelocityOR({0.f, 0.f, -maxZAngVel}); + } + + float f26 = g_tweakPlayer->GetPlayerRotationMaxSpeed(int(restraints)) * zRotateInput * turnSpeedMul; + f26 -= GetAngularVelocityOR().getVector().z(); + float remainVel = zeus::clamp( + 0.f, std::fabs(f26) / (turnSpeedMul * g_tweakPlayer->GetPlayerRotationMaxSpeed(int(restraints))), 1.f); + if (f26 < 0.f) + zRotateInput = remainVel * -g_tweakPlayer->GetMaxRotationalAcceleration(int(restraints)); + else + zRotateInput = remainVel * g_tweakPlayer->GetMaxRotationalAcceleration(int(restraints)); + + float forwardForce; + if (std::fabs(forwardInput) >= 0.00001f) { + float maxSpeed = g_tweakPlayer->GetPlayerTranslationMaxSpeed(int(restraints)); + float calcSpeed = g_tweakPlayer->GetPlayerTranslationFriction(int(restraints)) * xe8_mass / + (dt * g_tweakPlayer->GetMaxTranslationalAcceleration(int(restraints))) * maxSpeed; + float f28 = (forwardInput > 0.f ? 1.f : -1.f) * calcSpeed + (maxSpeed - calcSpeed) * forwardInput; + forwardForce = zeus::clamp(-1.f, (f28 - x34_transform.transposeRotate(x138_velocity).y()) / maxSpeed, 1.f) * + g_tweakPlayer->GetMaxTranslationalAcceleration(int(restraints)); + } else { + forwardForce = 0.f; + } + + if (x304_orbitState != EPlayerOrbitState::NoOrbit && x3dd_lookButtonHeld) + forwardForce = 0.f; + + if (x304_orbitState == EPlayerOrbitState::NoOrbit || x3dd_lookButtonHeld) { + ApplyForceOR({0.f, forwardForce, jumpInput}, zeus::CAxisAngle::sIdentity); + if (zRotateInput != 0.f) + ApplyForceOR(zeus::CVector3f::skZero, zeus::CAxisAngle({0.f, 0.f, 1.f}, zRotateInput)); if (x37c_sidewaysDashing) - x38c_doneSidewaysDashing = true; + x38c_doneSidewaysDashing = true; x37c_sidewaysDashing = false; x380_strafeInputAtDash = 0.f; x384_dashTimer = 0.f; -} - -void CPlayer::ComputeDash(const CFinalInput& input, float dt, CStateManager& mgr) -{ - float strafeInput = StrafeInput(input); - float forwardInput = ForwardInput(input, TurnInput(input)); - zeus::CVector3f orbitPointFlattened(x314_orbitPoint.x(), x314_orbitPoint.y(), GetTranslation().z()); - zeus::CVector3f orbitToPlayer = GetTranslation() - orbitPointFlattened; - if (!orbitToPlayer.canBeNormalized()) - return; - zeus::CVector3f useOrbitToPlayer = orbitToPlayer; - ESurfaceRestraints restraints = GetSurfaceRestraint(); - float strafeVel = dt * skStrafeDistances[int(restraints)]; - if (ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input)) - x388_dashButtonHoldTime += dt; - if (!x37c_sidewaysDashing) - { - if (SidewaysDashAllowed(strafeInput, forwardInput, input, mgr)) - { - x37c_sidewaysDashing = true; - x380_strafeInputAtDash = strafeInput; - x38c_doneSidewaysDashing = true; - x384_dashTimer = 0.f; - zeus::CVector3f vel = x138_velocity; - if (vel.z() > 0.f) - { - vel.z() *= 0.1f; - if (!x9c5_28_slidingOnWall) - { - SetVelocityWR(vel); - x778_dashSfx = CSfxManager::SfxStart(SFXsam_dash, 1.f, 0.f, true, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(x778_dashSfx); - mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerBump, 0.24375f, ERumblePriority::One); - } - } - } - strafeVel *= strafeInput; + } else { + switch (x304_orbitState) { + case EPlayerOrbitState::OrbitObject: + case EPlayerOrbitState::OrbitPoint: + case EPlayerOrbitState::OrbitCarcass: + case EPlayerOrbitState::ForcedOrbitObject: + if (!InGrappleJumpCooldown()) + ComputeDash(input, dt, mgr); + break; + default: + break; } - else - { - x384_dashTimer += dt; - if (x258_movementState == EPlayerMovementState::OnGround || x384_dashTimer >= x3a0_dashDuration || - x9c5_28_slidingOnWall || x9c5_29_hitWall || x304_orbitState != EPlayerOrbitState::OrbitObject) - { - FinishSidewaysDash(); - strafeVel *= strafeInput; - CSfxManager::RemoveEmitter(x778_dashSfx); - } - else - { - if (x39c_noStrafeDashBlend) - { - strafeVel = dt * skDashStrafeDistances[int(restraints)] * x398_dashSpeedMultiplier; - } - else - { - strafeVel = ((skDashStrafeDistances[int(restraints)] - skStrafeDistances[int(restraints)]) * - (1.f - zeus::clamp(-1.f, x384_dashTimer / x3a4_strafeDashBlendDuration, 1.f)) + - skStrafeDistances[int(restraints)]) * x398_dashSpeedMultiplier * dt; - } - if (x380_strafeInputAtDash < 0.f) - strafeVel = -strafeVel; - } + ApplyForceOR({0.f, 0.f, jumpInput}, zeus::CAxisAngle::sIdentity); + } + + if (x3dc_inFreeLook || x3dd_lookButtonHeld) { + if (!x9c5_28_slidingOnWall && x258_movementState == EPlayerMovementState::OnGround) { + zeus::CVector3f revVelFlat(-x138_velocity.x(), -x138_velocity.y(), 0.f); + float revVelFlatMag = revVelFlat.magnitude(); + if (revVelFlatMag > FLT_EPSILON) { + float accel = 0.2f * dt * GetAcceleration(); + float damp = zeus::clamp(-1.f, revVelFlatMag / accel, 1.f); + SetVelocityWR(revVelFlat / revVelFlatMag * accel * damp + x138_velocity); + } } + } - float f3 = strafeVel / orbitToPlayer.magnitude(); - float f2 = dt * (x37c_sidewaysDashing ? M_PIF : (M_PIF * 2.f / 3.f)); - useOrbitToPlayer = zeus::CQuaternion::fromAxisAngle(zeus::CVector3f::skUp, - zeus::clamp(-f2, f3, f2)).transform(orbitToPlayer); - orbitPointFlattened += useOrbitToPlayer; - if (!ControlMapper::GetDigitalInput(ControlMapper::ECommands::JumpOrBoost, input)) - x388_dashButtonHoldTime = 0.f; - strafeVel = skOrbitForwardDistances[int(restraints)] * forwardInput * dt; - orbitPointFlattened += -useOrbitToPlayer.normalized() * strafeVel; - zeus::CVector2f velFlat(x138_velocity.x(), x138_velocity.y()); - zeus::CVector3f newVelocity = (orbitPointFlattened - GetTranslation()) / dt; - zeus::CVector3f velDelta(newVelocity.x() - x138_velocity.x(), newVelocity.y() - x138_velocity.y(), 0.f); - strafeVel = velDelta.magnitude(); - if (strafeVel > FLT_EPSILON) - { - float accel = dt * GetAcceleration(); - newVelocity = velDelta / strafeVel * accel * zeus::clamp(-1.f, strafeVel / accel, 1.f) + x138_velocity; - if (!x9c5_28_slidingOnWall) - SetVelocityWR(newVelocity); - } -} - -void CPlayer::ComputeMovement(const CFinalInput& input, CStateManager& mgr, float dt) -{ - ESurfaceRestraints restraints = GetSurfaceRestraint(); - - float jumpInput = JumpInput(input, mgr); - float zRotateInput = TurnInput(input); - float forwardInput = ForwardInput(input, zRotateInput); - SetVelocityWR(GetDampedClampedVelocityWR()); - float turnSpeedMul = g_tweakPlayer->GetTurnSpeedMultiplier(); - if (g_tweakPlayer->GetFreeLookTurnsPlayer()) - if (!g_tweakPlayer->GetHoldButtonsForFreeLook() || x3dd_lookButtonHeld) - turnSpeedMul = g_tweakPlayer->GetFreeLookTurnSpeedMultiplier(); - - if (x304_orbitState == EPlayerOrbitState::NoOrbit || - (x3dd_lookButtonHeld && x304_orbitState != EPlayerOrbitState::OrbitObject && - x304_orbitState != EPlayerOrbitState::Grapple)) - { - if (std::fabs(zRotateInput) < 0.00001f) - { - float frictionZAngVel = g_tweakPlayer->GetPlayerRotationFriction(int(restraints)) * - GetAngularVelocityOR().getVector().z(); - SetAngularVelocityOR({0.f, 0.f, frictionZAngVel}); - } - - float curZAngVel = GetAngularVelocityOR().getVector().z(); - float maxZAngVel = g_tweakPlayer->GetPlayerRotationMaxSpeed(int(restraints)) * turnSpeedMul; - if (curZAngVel > maxZAngVel) - SetAngularVelocityOR({0.f, 0.f, maxZAngVel}); - else if (-curZAngVel > maxZAngVel) - SetAngularVelocityOR({0.f, 0.f, -maxZAngVel}); - } - - float f26 = g_tweakPlayer->GetPlayerRotationMaxSpeed(int(restraints)) * zRotateInput * turnSpeedMul; - f26 -= GetAngularVelocityOR().getVector().z(); - float remainVel = zeus::clamp(0.f, std::fabs(f26) / - (turnSpeedMul * g_tweakPlayer->GetPlayerRotationMaxSpeed(int(restraints))), 1.f); - if (f26 < 0.f) - zRotateInput = remainVel * -g_tweakPlayer->GetMaxRotationalAcceleration(int(restraints)); - else - zRotateInput = remainVel * g_tweakPlayer->GetMaxRotationalAcceleration(int(restraints)); - - float forwardForce; - if (std::fabs(forwardInput) >= 0.00001f) - { - float maxSpeed = g_tweakPlayer->GetPlayerTranslationMaxSpeed(int(restraints)); - float calcSpeed = g_tweakPlayer->GetPlayerTranslationFriction(int(restraints)) * xe8_mass / - (dt * g_tweakPlayer->GetMaxTranslationalAcceleration(int(restraints))) * maxSpeed; - float f28 = (forwardInput > 0.f ? 1.f : -1.f) * calcSpeed + (maxSpeed - calcSpeed) * forwardInput; - forwardForce = zeus::clamp(-1.f, (f28 - x34_transform.transposeRotate(x138_velocity).y()) / maxSpeed, 1.f) * - g_tweakPlayer->GetMaxTranslationalAcceleration(int(restraints)); - } - else - { - forwardForce = 0.f; - } - - if (x304_orbitState != EPlayerOrbitState::NoOrbit && x3dd_lookButtonHeld) - forwardForce = 0.f; - - if (x304_orbitState == EPlayerOrbitState::NoOrbit || x3dd_lookButtonHeld) - { - ApplyForceOR({0.f, forwardForce, jumpInput}, zeus::CAxisAngle::sIdentity); - if (zRotateInput != 0.f) - ApplyForceOR(zeus::CVector3f::skZero, zeus::CAxisAngle({0.f, 0.f, 1.f}, zRotateInput)); - if (x37c_sidewaysDashing) - x38c_doneSidewaysDashing = true; - x37c_sidewaysDashing = false; - x380_strafeInputAtDash = 0.f; - x384_dashTimer = 0.f; - } - else - { - switch (x304_orbitState) - { - case EPlayerOrbitState::OrbitObject: - case EPlayerOrbitState::OrbitPoint: - case EPlayerOrbitState::OrbitCarcass: - case EPlayerOrbitState::ForcedOrbitObject: - if (!InGrappleJumpCooldown()) - ComputeDash(input, dt, mgr); - break; - default: - break; - } - ApplyForceOR({0.f, 0.f, jumpInput}, zeus::CAxisAngle::sIdentity); - } - - if (x3dc_inFreeLook || x3dd_lookButtonHeld) - { - if (!x9c5_28_slidingOnWall && x258_movementState == EPlayerMovementState::OnGround) - { - zeus::CVector3f revVelFlat(-x138_velocity.x(), -x138_velocity.y(), 0.f); - float revVelFlatMag = revVelFlat.magnitude(); - if (revVelFlatMag > FLT_EPSILON) - { - float accel = 0.2f * dt * GetAcceleration(); - float damp = zeus::clamp(-1.f, revVelFlatMag / accel, 1.f); - SetVelocityWR(revVelFlat / revVelFlatMag * accel * damp + x138_velocity); - } - } - } - - x9c5_29_hitWall = false; - if (x2d4_accelerationChangeTimer > 0.f) - x2d0_curAcceleration = 0; - else - x2d0_curAcceleration += 1; - x2d4_accelerationChangeTimer -= dt; - x2d4_accelerationChangeTimer = std::max(0.f, x2d4_accelerationChangeTimer); + x9c5_29_hitWall = false; + if (x2d4_accelerationChangeTimer > 0.f) + x2d0_curAcceleration = 0; + else + x2d0_curAcceleration += 1; + x2d4_accelerationChangeTimer -= dt; + x2d4_accelerationChangeTimer = std::max(0.f, x2d4_accelerationChangeTimer); } float CPlayer::GetWeight() const { return xe8_mass * -GetGravity(); } -zeus::CVector3f CPlayer::GetDampedClampedVelocityWR() const -{ - zeus::CVector3f localVel = x34_transform.transposeRotate(x138_velocity); - if ((x258_movementState != EPlayerMovementState::ApplyJump || - GetSurfaceRestraint() != ESurfaceRestraints::InAir) && - x304_orbitState == EPlayerOrbitState::NoOrbit) - { - float friction = g_tweakPlayer->GetPlayerTranslationFriction(int(GetSurfaceRestraint())); - if (localVel.y() > 0.f) - localVel.y() = std::max(0.f, localVel.y() - friction); - else - localVel.y() = std::min(0.f, localVel.y() + friction); - if (localVel.x() > 0.f) - localVel.x() = std::max(0.f, localVel.x() - friction); - else - localVel.x() = std::min(0.f, localVel.x() + friction); - } - - float maxSpeed = g_tweakPlayer->GetPlayerTranslationMaxSpeed(int(GetSurfaceRestraint())); - localVel.y() = zeus::clamp(-maxSpeed, float(localVel.y()), maxSpeed); - if (x258_movementState == EPlayerMovementState::OnGround) - localVel.z() = 0.f; - return x34_transform.rotate(localVel); -} - -const CScriptWater* CPlayer::GetVisorRunoffEffect(const CStateManager& mgr) const -{ - if (xc4_fluidId == kInvalidUniqueId) - return nullptr; - return TCastToConstPtr(mgr.GetObjectById(xc4_fluidId)).GetPtr(); -} - -void CPlayer::SetMorphBallState(EPlayerMorphBallState state, CStateManager& mgr) -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && - state != EPlayerMorphBallState::Morphed) - x9c5_26_ = x9c4_31_dampUnderwaterMotion; - - x2f8_morphBallState = state; - xf9_standardCollider = state == EPlayerMorphBallState::Morphed; - - switch (x2f8_morphBallState) - { - case EPlayerMorphBallState::Unmorphed: - if (x9c5_26_ && mgr.GetCameraManager()->GetFluidCounter() == 0) - { - if (auto water = GetVisorRunoffEffect(mgr)) - { - if (const auto& effect = water->GetUnmorphVisorRunoffEffect()) - { - CHUDBillboardEffect* sheets = new CHUDBillboardEffect(*effect, {}, mgr.AllocateUniqueId(), - true, "WaterSheets", CHUDBillboardEffect::GetNearClipDistance(mgr), - CHUDBillboardEffect::GetScaleForPOV(mgr), zeus::CColor::skWhite, - zeus::CVector3f::skOne, zeus::CVector3f::skZero); - mgr.AddObject(sheets); - } - CSfxHandle hnd = CSfxManager::SfxStart(water->GetUnmorphVisorRunoffSfx(), 1.f, 0.f, - false, 0x7f, false, kInvalidAreaId); - ApplySubmergedPitchBend(hnd); - } - } - break; - case EPlayerMorphBallState::Morphed: - case EPlayerMorphBallState::Morphing: - x768_morphball->LoadMorphBallModel(mgr); - break; - default: - break; - } -} - -bool CPlayer::CanLeaveMorphBallState(CStateManager& mgr, zeus::CVector3f& pos) const -{ - if (x768_morphball->IsProjectile() || !x590_ || - (IsUnderBetaMetroidAttack(mgr) && x2f8_morphBallState == EPlayerMorphBallState::Morphed)) - return false; - if (!x9c4_28_canLeaveMorphBall) - return false; - CMaterialFilter filter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid}); - zeus::CAABox aabb(x2d8_fpBounds.min - zeus::CVector3f(1.f) + GetTranslation(), - x2d8_fpBounds.max + zeus::CVector3f(1.f) + GetTranslation()); - rstl::reserved_vector nearList; - mgr.BuildColliderList(nearList, *this, aabb); - const zeus::CAABox& baseAABB = GetBaseBoundingBox(); - pos = zeus::CVector3f::skZero; - for (int i=0 ; i<8 ; ++i) - { - zeus::CAABox aabb(baseAABB.min + pos + GetTranslation(), - baseAABB.max + pos + GetTranslation()); - CCollidableAABox cAABB(aabb, CMaterialList()); - if (!CGameCollision::DetectCollisionBoolean(mgr, cAABB, zeus::CTransform::Identity(), filter, nearList)) - return true; - pos.z() += 0.1f; - } - return false; -} - -void CPlayer::SetHudDisable(float staticTimer, float outSpeed, float inSpeed) -{ - x740_staticTimer = staticTimer; - x744_staticOutSpeed = outSpeed; - x748_staticInSpeed = inSpeed; - if (x744_staticOutSpeed != 0.f) - return; - if (x740_staticTimer == 0.f) - x74c_visorStaticAlpha = 1.f; +zeus::CVector3f CPlayer::GetDampedClampedVelocityWR() const { + zeus::CVector3f localVel = x34_transform.transposeRotate(x138_velocity); + if ((x258_movementState != EPlayerMovementState::ApplyJump || GetSurfaceRestraint() != ESurfaceRestraints::InAir) && + x304_orbitState == EPlayerOrbitState::NoOrbit) { + float friction = g_tweakPlayer->GetPlayerTranslationFriction(int(GetSurfaceRestraint())); + if (localVel.y() > 0.f) + localVel.y() = std::max(0.f, localVel.y() - friction); else - x74c_visorStaticAlpha = 0.f; -} - -void CPlayer::SetIntoBallReadyAnimation(CStateManager& mgr) -{ - CAnimPlaybackParms parms(2, -1, 1.f, true); - x64_modelData->AnimationData()->SetAnimation(parms, false); - x64_modelData->AnimationData()->EnableLooping(false); - x64_modelData->AdvanceAnimation(0.f, mgr, kInvalidAreaId, true); - x64_modelData->AnimationData()->EnableAnimation(false); -} - -void CPlayer::LeaveMorphBallState(CStateManager& mgr) -{ - x730_transitionModels.clear(); - AddMaterial(EMaterialTypes::GroundCollider, mgr); - x150_momentum = zeus::CVector3f::skZero; - SetMorphBallState(EPlayerMorphBallState::Unmorphed, mgr); - SetHudDisable(FLT_EPSILON, 0.f, 2.f); - SetHudDisable(FLT_EPSILON, 0.f, 2.f); - SetIntoBallReadyAnimation(mgr); - CPhysicsActor::Stop(); - x3e4_freeLookYawAngle = 0.f; - x3e8_horizFreeLookAngleVel = 0.f; - x3ec_freeLookPitchAngle = 0.f; - x3f0_vertFreeLookAngleVel = 0.f; - x768_morphball->LeaveMorphBallState(mgr); - mgr.GetCameraManager()->SetPlayerCamera(mgr, mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId()); - mgr.GetCameraManager()->GetBallCamera()->SetState(CBallCamera::EBallCameraState::Default, mgr); - SetCameraState(EPlayerCameraState::FirstPerson, mgr); - mgr.GetCameraManager()->GetFirstPersonCamera()->DeferBallTransitionProcessing(); - mgr.GetCameraManager()->GetFirstPersonCamera()->Think(0.f, mgr); - ForceGunOrientation(x34_transform, mgr); - DrawGun(mgr); -} - -bool CPlayer::CanEnterMorphBallState(CStateManager& mgr, float f1) const -{ - if (x3b8_grappleState != EGrappleState::None || - (IsUnderBetaMetroidAttack(mgr) && x2f8_morphBallState == EPlayerMorphBallState::Unmorphed)) - return false; - return x9c4_27_canEnterMorphBall; -} - -void CPlayer::EnterMorphBallState(CStateManager& mgr) -{ - SetMorphBallState(EPlayerMorphBallState::Morphed, mgr); - RemoveMaterial(EMaterialTypes::GroundCollider, mgr); - x730_transitionModels.clear(); - SetAngularVelocityOR(zeus::CAxisAngle( - zeus::CVector3f(x138_velocity.magnitude() / g_tweakPlayer->GetPlayerBallHalfExtent(), 0.f, 0.f))); - x768_morphball->EnterMorphBallState(mgr); - x768_morphball->TakeDamage(-1.f); - x768_morphball->SetDamageTimer(0.f); - mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Combat); -} - -void CPlayer::ActivateMorphBallCamera(CStateManager& mgr) -{ - SetCameraState(EPlayerCameraState::Ball, mgr); - mgr.GetCameraManager()->GetBallCamera()->SetState(CBallCamera::EBallCameraState::Default, mgr); -} - -void CPlayer::UpdateCinematicState(CStateManager& mgr) -{ - if (mgr.GetCameraManager()->IsInCinematicCamera()) - { - if (x2f4_cameraState != EPlayerCameraState::Spawned) - { - x2fc_spawnedMorphBallState = x2f8_morphBallState; - if (x2fc_spawnedMorphBallState == EPlayerMorphBallState::Unmorphing) - x2fc_spawnedMorphBallState = EPlayerMorphBallState::Unmorphed; - if (x2fc_spawnedMorphBallState == EPlayerMorphBallState::Morphing) - x2fc_spawnedMorphBallState = EPlayerMorphBallState::Morphed; - SetCameraState(EPlayerCameraState::Spawned, mgr); - } - } + localVel.y() = std::min(0.f, localVel.y() + friction); + if (localVel.x() > 0.f) + localVel.x() = std::max(0.f, localVel.x() - friction); else - { - if (x2f4_cameraState == EPlayerCameraState::Spawned) - { - if (x2fc_spawnedMorphBallState == x2f8_morphBallState) - { - switch (x2fc_spawnedMorphBallState) - { - case EPlayerMorphBallState::Morphed: - SetCameraState(EPlayerCameraState::Ball, mgr); - break; - case EPlayerMorphBallState::Unmorphed: - SetCameraState(EPlayerCameraState::FirstPerson, mgr); - if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) - { - ForceGunOrientation(x34_transform, mgr); - DrawGun(mgr); - } - default: - break; - } - } - else - { - CPhysicsActor::Stop(); - SetOrbitRequest(EPlayerOrbitRequest::Respawn, mgr); - switch (x2fc_spawnedMorphBallState) - { - case EPlayerMorphBallState::Unmorphed: - { - zeus::CVector3f vec; - if (CanLeaveMorphBallState(mgr, vec)) - { - SetTranslation(GetTranslation() + vec); - LeaveMorphBallState(mgr); - SetCameraState(EPlayerCameraState::FirstPerson, mgr); - ForceGunOrientation(x34_transform, mgr); - DrawGun(mgr); - } - break; - } - case EPlayerMorphBallState::Morphed: - EnterMorphBallState(mgr); - ActivateMorphBallCamera(mgr); - mgr.GetCameraManager()->SetupBallCamera(mgr); - mgr.GetCameraManager()->GetBallCamera()->Reset( - CreateTransformFromMovementDirection(), mgr); - default: - break; - } - } + localVel.x() = std::min(0.f, localVel.x() + friction); + } + + float maxSpeed = g_tweakPlayer->GetPlayerTranslationMaxSpeed(int(GetSurfaceRestraint())); + localVel.y() = zeus::clamp(-maxSpeed, float(localVel.y()), maxSpeed); + if (x258_movementState == EPlayerMovementState::OnGround) + localVel.z() = 0.f; + return x34_transform.rotate(localVel); +} + +const CScriptWater* CPlayer::GetVisorRunoffEffect(const CStateManager& mgr) const { + if (xc4_fluidId == kInvalidUniqueId) + return nullptr; + return TCastToConstPtr(mgr.GetObjectById(xc4_fluidId)).GetPtr(); +} + +void CPlayer::SetMorphBallState(EPlayerMorphBallState state, CStateManager& mgr) { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed && state != EPlayerMorphBallState::Morphed) + x9c5_26_ = x9c4_31_dampUnderwaterMotion; + + x2f8_morphBallState = state; + xf9_standardCollider = state == EPlayerMorphBallState::Morphed; + + switch (x2f8_morphBallState) { + case EPlayerMorphBallState::Unmorphed: + if (x9c5_26_ && mgr.GetCameraManager()->GetFluidCounter() == 0) { + if (auto water = GetVisorRunoffEffect(mgr)) { + if (const auto& effect = water->GetUnmorphVisorRunoffEffect()) { + CHUDBillboardEffect* sheets = new CHUDBillboardEffect( + *effect, {}, mgr.AllocateUniqueId(), true, "WaterSheets", CHUDBillboardEffect::GetNearClipDistance(mgr), + CHUDBillboardEffect::GetScaleForPOV(mgr), zeus::CColor::skWhite, zeus::CVector3f::skOne, + zeus::CVector3f::skZero); + mgr.AddObject(sheets); } + CSfxHandle hnd = + CSfxManager::SfxStart(water->GetUnmorphVisorRunoffSfx(), 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + ApplySubmergedPitchBend(hnd); + } } + break; + case EPlayerMorphBallState::Morphed: + case EPlayerMorphBallState::Morphing: + x768_morphball->LoadMorphBallModel(mgr); + break; + default: + break; + } } -void CPlayer::SetCameraState(EPlayerCameraState camState, CStateManager& stateMgr) -{ - if (x2f4_cameraState == camState) - return; - x2f4_cameraState = camState; - CCameraManager* camMgr = stateMgr.GetCameraManager(); - switch (camState) - { - case EPlayerCameraState::FirstPerson: - camMgr->SetCurrentCameraId(camMgr->GetFirstPersonCamera()->GetUniqueId(), stateMgr); - x768_morphball->SetBallLightActive(stateMgr, false); - break; - case EPlayerCameraState::Ball: - case EPlayerCameraState::Transitioning: - camMgr->SetCurrentCameraId(camMgr->GetBallCamera()->GetUniqueId(), stateMgr); - x768_morphball->SetBallLightActive(stateMgr, true); - break; - case EPlayerCameraState::Two: - break; - case EPlayerCameraState::Spawned: - { - bool ballLight = false; - if (TCastToPtr cineCam = camMgr->GetCurrentCamera(stateMgr)) - ballLight = x2f8_morphBallState == EPlayerMorphBallState::Morphed && cineCam->GetFlags() & 0x40; - x768_morphball->SetBallLightActive(stateMgr, ballLight); - break; - } - } -} - -bool CPlayer::IsEnergyLow(const CStateManager& mgr) const -{ - float lowThreshold = mgr.GetPlayerState()->GetItemCapacity(CPlayerState::EItemType::EnergyTanks) < 4 ? 30.f : 100.f; - return GetHealthInfo(mgr)->GetHP() < lowThreshold; -} - -bool CPlayer::ObjectInScanningRange(TUniqueId id, const CStateManager& mgr) const -{ - const CEntity* ent = mgr.GetObjectById(id); - if (TCastToConstPtr act = ent) - { - zeus::CVector3f delta = act->GetTranslation() - GetTranslation(); - if (delta.canBeNormalized()) - return delta.magnitude() < g_tweakPlayer->GetScanningRange(); - } +bool CPlayer::CanLeaveMorphBallState(CStateManager& mgr, zeus::CVector3f& pos) const { + if (x768_morphball->IsProjectile() || !x590_ || + (IsUnderBetaMetroidAttack(mgr) && x2f8_morphBallState == EPlayerMorphBallState::Morphed)) return false; + if (!x9c4_28_canLeaveMorphBall) + return false; + CMaterialFilter filter = CMaterialFilter::MakeInclude({EMaterialTypes::Solid}); + zeus::CAABox aabb(x2d8_fpBounds.min - zeus::CVector3f(1.f) + GetTranslation(), + x2d8_fpBounds.max + zeus::CVector3f(1.f) + GetTranslation()); + rstl::reserved_vector nearList; + mgr.BuildColliderList(nearList, *this, aabb); + const zeus::CAABox& baseAABB = GetBaseBoundingBox(); + pos = zeus::CVector3f::skZero; + for (int i = 0; i < 8; ++i) { + zeus::CAABox aabb(baseAABB.min + pos + GetTranslation(), baseAABB.max + pos + GetTranslation()); + CCollidableAABox cAABB(aabb, CMaterialList()); + if (!CGameCollision::DetectCollisionBoolean(mgr, cAABB, zeus::CTransform::Identity(), filter, nearList)) + return true; + pos.z() += 0.1f; + } + return false; } -void CPlayer::SetPlayerHitWallDuringMove() -{ - x9c5_29_hitWall = true; - x2d0_curAcceleration = 1; +void CPlayer::SetHudDisable(float staticTimer, float outSpeed, float inSpeed) { + x740_staticTimer = staticTimer; + x744_staticOutSpeed = outSpeed; + x748_staticInSpeed = inSpeed; + if (x744_staticOutSpeed != 0.f) + return; + if (x740_staticTimer == 0.f) + x74c_visorStaticAlpha = 1.f; + else + x74c_visorStaticAlpha = 0.f; } -void CPlayer::Touch(CActor& actor, CStateManager& mgr) -{ - if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) - x768_morphball->Touch(actor, mgr); +void CPlayer::SetIntoBallReadyAnimation(CStateManager& mgr) { + CAnimPlaybackParms parms(2, -1, 1.f, true); + x64_modelData->AnimationData()->SetAnimation(parms, false); + x64_modelData->AnimationData()->EnableLooping(false); + x64_modelData->AdvanceAnimation(0.f, mgr, kInvalidAreaId, true); + x64_modelData->AnimationData()->EnableAnimation(false); } -void CPlayer::CVisorSteam::SetSteam(float targetAlpha, float alphaInDur, float alphaOutDur, - CAssetId txtr, bool affectsThermal) -{ - if (x1c_txtr.IsValid() || targetAlpha > x10_nextTargetAlpha) - { - x10_nextTargetAlpha = targetAlpha; - x14_nextAlphaInDur = alphaInDur; - x18_nextAlphaOutDur = alphaOutDur; - x1c_txtr = txtr; +void CPlayer::LeaveMorphBallState(CStateManager& mgr) { + x730_transitionModels.clear(); + AddMaterial(EMaterialTypes::GroundCollider, mgr); + x150_momentum = zeus::CVector3f::skZero; + SetMorphBallState(EPlayerMorphBallState::Unmorphed, mgr); + SetHudDisable(FLT_EPSILON, 0.f, 2.f); + SetHudDisable(FLT_EPSILON, 0.f, 2.f); + SetIntoBallReadyAnimation(mgr); + CPhysicsActor::Stop(); + x3e4_freeLookYawAngle = 0.f; + x3e8_horizFreeLookAngleVel = 0.f; + x3ec_freeLookPitchAngle = 0.f; + x3f0_vertFreeLookAngleVel = 0.f; + x768_morphball->LeaveMorphBallState(mgr); + mgr.GetCameraManager()->SetPlayerCamera(mgr, mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId()); + mgr.GetCameraManager()->GetBallCamera()->SetState(CBallCamera::EBallCameraState::Default, mgr); + SetCameraState(EPlayerCameraState::FirstPerson, mgr); + mgr.GetCameraManager()->GetFirstPersonCamera()->DeferBallTransitionProcessing(); + mgr.GetCameraManager()->GetFirstPersonCamera()->Think(0.f, mgr); + ForceGunOrientation(x34_transform, mgr); + DrawGun(mgr); +} + +bool CPlayer::CanEnterMorphBallState(CStateManager& mgr, float f1) const { + if (x3b8_grappleState != EGrappleState::None || + (IsUnderBetaMetroidAttack(mgr) && x2f8_morphBallState == EPlayerMorphBallState::Unmorphed)) + return false; + return x9c4_27_canEnterMorphBall; +} + +void CPlayer::EnterMorphBallState(CStateManager& mgr) { + SetMorphBallState(EPlayerMorphBallState::Morphed, mgr); + RemoveMaterial(EMaterialTypes::GroundCollider, mgr); + x730_transitionModels.clear(); + SetAngularVelocityOR(zeus::CAxisAngle( + zeus::CVector3f(x138_velocity.magnitude() / g_tweakPlayer->GetPlayerBallHalfExtent(), 0.f, 0.f))); + x768_morphball->EnterMorphBallState(mgr); + x768_morphball->TakeDamage(-1.f); + x768_morphball->SetDamageTimer(0.f); + mgr.GetPlayerState()->StartVisorTransition(CPlayerState::EPlayerVisor::Combat); +} + +void CPlayer::ActivateMorphBallCamera(CStateManager& mgr) { + SetCameraState(EPlayerCameraState::Ball, mgr); + mgr.GetCameraManager()->GetBallCamera()->SetState(CBallCamera::EBallCameraState::Default, mgr); +} + +void CPlayer::UpdateCinematicState(CStateManager& mgr) { + if (mgr.GetCameraManager()->IsInCinematicCamera()) { + if (x2f4_cameraState != EPlayerCameraState::Spawned) { + x2fc_spawnedMorphBallState = x2f8_morphBallState; + if (x2fc_spawnedMorphBallState == EPlayerMorphBallState::Unmorphing) + x2fc_spawnedMorphBallState = EPlayerMorphBallState::Unmorphed; + if (x2fc_spawnedMorphBallState == EPlayerMorphBallState::Morphing) + x2fc_spawnedMorphBallState = EPlayerMorphBallState::Morphed; + SetCameraState(EPlayerCameraState::Spawned, mgr); } - x28_affectsThermal = affectsThermal; + } else { + if (x2f4_cameraState == EPlayerCameraState::Spawned) { + if (x2fc_spawnedMorphBallState == x2f8_morphBallState) { + switch (x2fc_spawnedMorphBallState) { + case EPlayerMorphBallState::Morphed: + SetCameraState(EPlayerCameraState::Ball, mgr); + break; + case EPlayerMorphBallState::Unmorphed: + SetCameraState(EPlayerCameraState::FirstPerson, mgr); + if (mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Scan) { + ForceGunOrientation(x34_transform, mgr); + DrawGun(mgr); + } + default: + break; + } + } else { + CPhysicsActor::Stop(); + SetOrbitRequest(EPlayerOrbitRequest::Respawn, mgr); + switch (x2fc_spawnedMorphBallState) { + case EPlayerMorphBallState::Unmorphed: { + zeus::CVector3f vec; + if (CanLeaveMorphBallState(mgr, vec)) { + SetTranslation(GetTranslation() + vec); + LeaveMorphBallState(mgr); + SetCameraState(EPlayerCameraState::FirstPerson, mgr); + ForceGunOrientation(x34_transform, mgr); + DrawGun(mgr); + } + break; + } + case EPlayerMorphBallState::Morphed: + EnterMorphBallState(mgr); + ActivateMorphBallCamera(mgr); + mgr.GetCameraManager()->SetupBallCamera(mgr); + mgr.GetCameraManager()->GetBallCamera()->Reset(CreateTransformFromMovementDirection(), mgr); + default: + break; + } + } + } + } +} + +void CPlayer::SetCameraState(EPlayerCameraState camState, CStateManager& stateMgr) { + if (x2f4_cameraState == camState) + return; + x2f4_cameraState = camState; + CCameraManager* camMgr = stateMgr.GetCameraManager(); + switch (camState) { + case EPlayerCameraState::FirstPerson: + camMgr->SetCurrentCameraId(camMgr->GetFirstPersonCamera()->GetUniqueId(), stateMgr); + x768_morphball->SetBallLightActive(stateMgr, false); + break; + case EPlayerCameraState::Ball: + case EPlayerCameraState::Transitioning: + camMgr->SetCurrentCameraId(camMgr->GetBallCamera()->GetUniqueId(), stateMgr); + x768_morphball->SetBallLightActive(stateMgr, true); + break; + case EPlayerCameraState::Two: + break; + case EPlayerCameraState::Spawned: { + bool ballLight = false; + if (TCastToPtr cineCam = camMgr->GetCurrentCamera(stateMgr)) + ballLight = x2f8_morphBallState == EPlayerMorphBallState::Morphed && cineCam->GetFlags() & 0x40; + x768_morphball->SetBallLightActive(stateMgr, ballLight); + break; + } + } +} + +bool CPlayer::IsEnergyLow(const CStateManager& mgr) const { + float lowThreshold = mgr.GetPlayerState()->GetItemCapacity(CPlayerState::EItemType::EnergyTanks) < 4 ? 30.f : 100.f; + return GetHealthInfo(mgr)->GetHP() < lowThreshold; +} + +bool CPlayer::ObjectInScanningRange(TUniqueId id, const CStateManager& mgr) const { + const CEntity* ent = mgr.GetObjectById(id); + if (TCastToConstPtr act = ent) { + zeus::CVector3f delta = act->GetTranslation() - GetTranslation(); + if (delta.canBeNormalized()) + return delta.magnitude() < g_tweakPlayer->GetScanningRange(); + } + return false; +} + +void CPlayer::SetPlayerHitWallDuringMove() { + x9c5_29_hitWall = true; + x2d0_curAcceleration = 1; +} + +void CPlayer::Touch(CActor& actor, CStateManager& mgr) { + if (x2f8_morphBallState == EPlayerMorphBallState::Morphed) + x768_morphball->Touch(actor, mgr); +} + +void CPlayer::CVisorSteam::SetSteam(float targetAlpha, float alphaInDur, float alphaOutDur, CAssetId txtr, + bool affectsThermal) { + if (x1c_txtr.IsValid() || targetAlpha > x10_nextTargetAlpha) { + x10_nextTargetAlpha = targetAlpha; + x14_nextAlphaInDur = alphaInDur; + x18_nextAlphaOutDur = alphaOutDur; + x1c_txtr = txtr; + } + x28_affectsThermal = affectsThermal; } CAssetId CPlayer::CVisorSteam::GetTextureId() const { return xc_tex; } -void CPlayer::CVisorSteam::Update(float dt) -{ - if (!x1c_txtr.IsValid()) - x0_curTargetAlpha = 0.f; - else - { - x0_curTargetAlpha = x10_nextTargetAlpha; - x4_curAlphaInDur = x14_nextAlphaInDur; - x8_curAlphaOutDur = x18_nextAlphaOutDur; - xc_tex = x1c_txtr; +void CPlayer::CVisorSteam::Update(float dt) { + if (!x1c_txtr.IsValid()) + x0_curTargetAlpha = 0.f; + else { + x0_curTargetAlpha = x10_nextTargetAlpha; + x4_curAlphaInDur = x14_nextAlphaInDur; + x8_curAlphaOutDur = x18_nextAlphaOutDur; + xc_tex = x1c_txtr; + } + + x1c_txtr.Reset(); + if ((x20_alpha - x0_curTargetAlpha) < 0.000009999f || std::fabs(x20_alpha) > 0.000009999f) + return; + + if (x20_alpha > x0_curTargetAlpha) { + if (x24_delayTimer <= 0.f) { + x20_alpha -= dt / x8_curAlphaOutDur; + x20_alpha = std::min(x20_alpha, x0_curTargetAlpha); + } else { + x24_delayTimer = x0_curTargetAlpha - dt; + x24_delayTimer = zeus::max(0.f, x24_delayTimer); } + return; + } - x1c_txtr.Reset(); - if ((x20_alpha - x0_curTargetAlpha) < 0.000009999f || std::fabs(x20_alpha) > 0.000009999f) - return; + CToken tmpTex = g_SimplePool->GetObj({SBIG('TXTR'), xc_tex}); + if (!tmpTex) + return; - if (x20_alpha > x0_curTargetAlpha) - { - if (x24_delayTimer <= 0.f) - { - x20_alpha -= dt / x8_curAlphaOutDur; - x20_alpha = std::min(x20_alpha, x0_curTargetAlpha); - } - else - { - x24_delayTimer = x0_curTargetAlpha - dt; - x24_delayTimer = zeus::max(0.f, x24_delayTimer); - } - return; - } + x20_alpha += dt / x4_curAlphaInDur; + if (x20_alpha > x0_curTargetAlpha) + x20_alpha = x0_curTargetAlpha; - CToken tmpTex = g_SimplePool->GetObj({SBIG('TXTR'), xc_tex}); - if (!tmpTex) - return; - - x20_alpha += dt / x4_curAlphaInDur; - if (x20_alpha > x0_curTargetAlpha) - x20_alpha = x0_curTargetAlpha; - - x24_delayTimer = 0.1f; + x24_delayTimer = 0.1f; } -void CPlayer::CFailsafeTest::Reset() -{ - x0_stateSamples.clear(); - x54_posSamples.clear(); - x148_velSamples.clear(); - x23c_inputSamples.clear(); +void CPlayer::CFailsafeTest::Reset() { + x0_stateSamples.clear(); + x54_posSamples.clear(); + x148_velSamples.clear(); + x23c_inputSamples.clear(); } -void CPlayer::CFailsafeTest::AddSample(EInputState state, const zeus::CVector3f& pos, - const zeus::CVector3f& vel, const zeus::CVector2f& input) -{ - if (x0_stateSamples.size() >= 20) - x0_stateSamples.resize(19); - x0_stateSamples.insert(x0_stateSamples.begin(), state); - if (x54_posSamples.size() >= 20) - x54_posSamples.resize(19); - x54_posSamples.insert(x54_posSamples.begin(), pos); - if (x148_velSamples.size() >= 20) - x148_velSamples.resize(19); - x148_velSamples.insert(x148_velSamples.begin(), vel); - if (x23c_inputSamples.size() >= 20) - x23c_inputSamples.resize(19); - x23c_inputSamples.insert(x23c_inputSamples.begin(), input); +void CPlayer::CFailsafeTest::AddSample(EInputState state, const zeus::CVector3f& pos, const zeus::CVector3f& vel, + const zeus::CVector2f& input) { + if (x0_stateSamples.size() >= 20) + x0_stateSamples.resize(19); + x0_stateSamples.insert(x0_stateSamples.begin(), state); + if (x54_posSamples.size() >= 20) + x54_posSamples.resize(19); + x54_posSamples.insert(x54_posSamples.begin(), pos); + if (x148_velSamples.size() >= 20) + x148_velSamples.resize(19); + x148_velSamples.insert(x148_velSamples.begin(), vel); + if (x23c_inputSamples.size() >= 20) + x23c_inputSamples.resize(19); + x23c_inputSamples.insert(x23c_inputSamples.begin(), input); } -bool CPlayer::CFailsafeTest::Passes() const -{ - if (x0_stateSamples.size() != 20) - return false; - float posMag = 0.f; - - zeus::CAABox velAABB(x148_velSamples[0], x148_velSamples[0]); - zeus::CAABox posAABB(x54_posSamples[0], x54_posSamples[0]); - zeus::CVector3f inputVec(x23c_inputSamples[0].x(), x23c_inputSamples[0].y(), 0.f); - zeus::CAABox inputAABB(inputVec, inputVec); - - float maxVelMag = x148_velSamples[0].magnitude(); - float minVelMag = maxVelMag; - u32 notEqualStates = 0; - - for (int i=1 ; i<20 ; ++i) - { - float mag = (x54_posSamples[i-1] - x54_posSamples[i]).magSquared(); - if (mag > FLT_EPSILON) - posMag += std::sqrt(mag); - - posAABB.accumulateBounds(x54_posSamples[i]); - velAABB.accumulateBounds(x148_velSamples[i]); - float velMag = x148_velSamples[i].magnitude(); - minVelMag = std::min(minVelMag, velMag); - maxVelMag = std::max(maxVelMag, velMag); - - zeus::CVector3f inputVec2(x23c_inputSamples[i].x(), x23c_inputSamples[i].y(), 0.f); - inputAABB.accumulateBounds(inputVec2); - - if (x0_stateSamples[i] != x0_stateSamples[i-1]) - notEqualStates += 1; - } - - bool test1 = true; - if (posMag >= 1.f / 30.f && posMag >= minVelMag / 30.f) - test1 = false; - - if (notEqualStates == 0 && x0_stateSamples[0] == EInputState::StartingJump) - { - float inputMag = (inputAABB.max - inputAABB.min).magnitude(); - zeus::CAABox inputFrom0AABB(inputAABB); - inputFrom0AABB.accumulateBounds(zeus::CVector3f::skZero); - bool test2 = true; - if ((inputFrom0AABB.max - inputFrom0AABB.min).magnitude() >= 0.01f && - inputMag <= 1.5f) - test2 = false; - return test1 && test2; - } - +bool CPlayer::CFailsafeTest::Passes() const { + if (x0_stateSamples.size() != 20) return false; + float posMag = 0.f; + + zeus::CAABox velAABB(x148_velSamples[0], x148_velSamples[0]); + zeus::CAABox posAABB(x54_posSamples[0], x54_posSamples[0]); + zeus::CVector3f inputVec(x23c_inputSamples[0].x(), x23c_inputSamples[0].y(), 0.f); + zeus::CAABox inputAABB(inputVec, inputVec); + + float maxVelMag = x148_velSamples[0].magnitude(); + float minVelMag = maxVelMag; + u32 notEqualStates = 0; + + for (int i = 1; i < 20; ++i) { + float mag = (x54_posSamples[i - 1] - x54_posSamples[i]).magSquared(); + if (mag > FLT_EPSILON) + posMag += std::sqrt(mag); + + posAABB.accumulateBounds(x54_posSamples[i]); + velAABB.accumulateBounds(x148_velSamples[i]); + float velMag = x148_velSamples[i].magnitude(); + minVelMag = std::min(minVelMag, velMag); + maxVelMag = std::max(maxVelMag, velMag); + + zeus::CVector3f inputVec2(x23c_inputSamples[i].x(), x23c_inputSamples[i].y(), 0.f); + inputAABB.accumulateBounds(inputVec2); + + if (x0_stateSamples[i] != x0_stateSamples[i - 1]) + notEqualStates += 1; + } + + bool test1 = true; + if (posMag >= 1.f / 30.f && posMag >= minVelMag / 30.f) + test1 = false; + + if (notEqualStates == 0 && x0_stateSamples[0] == EInputState::StartingJump) { + float inputMag = (inputAABB.max - inputAABB.min).magnitude(); + zeus::CAABox inputFrom0AABB(inputAABB); + inputFrom0AABB.accumulateBounds(zeus::CVector3f::skZero); + bool test2 = true; + if ((inputFrom0AABB.max - inputFrom0AABB.min).magnitude() >= 0.01f && inputMag <= 1.5f) + test2 = false; + return test1 && test2; + } + + return false; } -void CPlayer::SetSpawnedMorphBallState(EPlayerMorphBallState state, CStateManager& mgr) -{ - x2fc_spawnedMorphBallState = state; - SetCameraState(EPlayerCameraState::Spawned, mgr); - if (x2fc_spawnedMorphBallState != x2f8_morphBallState) - { - CPhysicsActor::Stop(); - SetOrbitRequest(EPlayerOrbitRequest::Respawn, mgr); - switch (x2fc_spawnedMorphBallState) - { - case EPlayerMorphBallState::Unmorphed: - { - zeus::CVector3f pos; - if (CanLeaveMorphBallState(mgr, pos)) - { - SetTranslation(GetTranslation() + pos); - LeaveMorphBallState(mgr); - ForceGunOrientation(x34_transform, mgr); - DrawGun(mgr); - } - break; - } - case EPlayerMorphBallState::Morphed: - EnterMorphBallState(mgr); - ActivateMorphBallCamera(mgr); - mgr.GetCameraManager()->SetupBallCamera(mgr); - mgr.GetCameraManager()->GetBallCamera()->Reset(CreateTransformFromMovementDirection(), mgr); - break; - default: - break; - } +void CPlayer::SetSpawnedMorphBallState(EPlayerMorphBallState state, CStateManager& mgr) { + x2fc_spawnedMorphBallState = state; + SetCameraState(EPlayerCameraState::Spawned, mgr); + if (x2fc_spawnedMorphBallState != x2f8_morphBallState) { + CPhysicsActor::Stop(); + SetOrbitRequest(EPlayerOrbitRequest::Respawn, mgr); + switch (x2fc_spawnedMorphBallState) { + case EPlayerMorphBallState::Unmorphed: { + zeus::CVector3f pos; + if (CanLeaveMorphBallState(mgr, pos)) { + SetTranslation(GetTranslation() + pos); + LeaveMorphBallState(mgr); + ForceGunOrientation(x34_transform, mgr); + DrawGun(mgr); + } + break; } -} - -void CPlayer::DecrementPhazon() -{ - if (xa10_phazonCounter == 0) - return; - - xa10_phazonCounter--; -} - -void CPlayer::IncrementPhazon() -{ - if (xa10_phazonCounter != 0) - xa10_phazonCounter++; - else - xa14_phazonCameraShakeTimer = 0.f; -} - -bool CPlayer::CheckSubmerged() const -{ - if (xe6_24_fluidCounter == 0) - return false; - - return x828_distanceUnderWater >= (x2f8_morphBallState == EPlayerMorphBallState::Morphed ? - 2.f * g_tweakPlayer->GetPlayerBallHalfExtent() : 0.5f * GetEyeHeight()); -} - -void CPlayer::UpdateSubmerged(CStateManager& mgr) -{ - x82c_inLava = false; - x828_distanceUnderWater = 0.f; - if (xe6_24_fluidCounter != 0) - { - if (TCastToPtr water = mgr.ObjectById(xc4_fluidId)) - { - x828_distanceUnderWater = - -(zeus::CVector3f::skUp.dot(x34_transform.origin) - water->GetTriggerBoundsWR().max.z()); - EFluidType fluidType = water->GetFluidPlane().GetFluidType(); - x82c_inLava = (fluidType == EFluidType::Lava || fluidType == EFluidType::ThickLava); - CheckSubmerged(); - } + case EPlayerMorphBallState::Morphed: + EnterMorphBallState(mgr); + ActivateMorphBallCamera(mgr); + mgr.GetCameraManager()->SetupBallCamera(mgr); + mgr.GetCameraManager()->GetBallCamera()->Reset(CreateTransformFromMovementDirection(), mgr); + break; + default: + break; } + } } -void CPlayer::ApplySubmergedPitchBend(CSfxHandle& sfx) -{ - if (CheckSubmerged()) - CSfxManager::PitchBend(sfx, -1.f); +void CPlayer::DecrementPhazon() { + if (xa10_phazonCounter == 0) + return; + + xa10_phazonCounter--; } -void CPlayer::DetachActorFromPlayer() -{ - x26c_attachedActor = kInvalidUniqueId; +void CPlayer::IncrementPhazon() { + if (xa10_phazonCounter != 0) + xa10_phazonCounter++; + else + xa14_phazonCameraShakeTimer = 0.f; +} + +bool CPlayer::CheckSubmerged() const { + if (xe6_24_fluidCounter == 0) + return false; + + return x828_distanceUnderWater >= (x2f8_morphBallState == EPlayerMorphBallState::Morphed + ? 2.f * g_tweakPlayer->GetPlayerBallHalfExtent() + : 0.5f * GetEyeHeight()); +} + +void CPlayer::UpdateSubmerged(CStateManager& mgr) { + x82c_inLava = false; + x828_distanceUnderWater = 0.f; + if (xe6_24_fluidCounter != 0) { + if (TCastToPtr water = mgr.ObjectById(xc4_fluidId)) { + x828_distanceUnderWater = + -(zeus::CVector3f::skUp.dot(x34_transform.origin) - water->GetTriggerBoundsWR().max.z()); + EFluidType fluidType = water->GetFluidPlane().GetFluidType(); + x82c_inLava = (fluidType == EFluidType::Lava || fluidType == EFluidType::ThickLava); + CheckSubmerged(); + } + } +} + +void CPlayer::ApplySubmergedPitchBend(CSfxHandle& sfx) { + if (CheckSubmerged()) + CSfxManager::PitchBend(sfx, -1.f); +} + +void CPlayer::DetachActorFromPlayer() { + x26c_attachedActor = kInvalidUniqueId; + x270_attachedActorTime = 0.f; + xa28_attachedActorStruggle = 0.f; + x490_gun->SetActorAttached(false); +} + +bool CPlayer::AttachActorToPlayer(TUniqueId id, bool disableGun) { + if (x26c_attachedActor == kInvalidUniqueId) { + if (disableGun) + x490_gun->SetActorAttached(true); + x26c_attachedActor = id; x270_attachedActorTime = 0.f; xa28_attachedActorStruggle = 0.f; - x490_gun->SetActorAttached(false); + x768_morphball->StopEffects(); + return true; + } + + return false; } -bool CPlayer::AttachActorToPlayer(TUniqueId id, bool disableGun) -{ - if (x26c_attachedActor == kInvalidUniqueId) - { - if (disableGun) - x490_gun->SetActorAttached(true); - x26c_attachedActor = id; - x270_attachedActorTime = 0.f; - xa28_attachedActorStruggle = 0.f; - x768_morphball->StopEffects(); - return true; - } - - return false; -} - -} +} // namespace urde diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp index 720683d0e..458c0625e 100644 --- a/Runtime/World/CPlayer.hpp +++ b/Runtime/World/CPlayer.hpp @@ -8,8 +8,7 @@ #include "Weapon/CPlayerGun.hpp" #include "CMorphBall.hpp" -namespace urde -{ +namespace urde { class CMaterialList; class CMorphBall; class CPlayerGun; @@ -22,674 +21,594 @@ class CFirstPersonCamera; class CCollidableSphere; class CScriptPlayerHint; -class CPlayer : public CPhysicsActor -{ - friend class CStateManager; - friend class CFirstPersonCamera; - friend class CPlayerCameraBob; - friend class CMorphBall; - friend class CGroundMovement; +class CPlayer : public CPhysicsActor { + friend class CStateManager; + friend class CFirstPersonCamera; + friend class CPlayerCameraBob; + friend class CMorphBall; + friend class CGroundMovement; public: - enum class EPlayerScanState - { - NotScanning, - Scanning, - ScanComplete - }; + enum class EPlayerScanState { NotScanning, Scanning, ScanComplete }; - enum class EPlayerOrbitType - { - Close, - Far, - Default - }; + enum class EPlayerOrbitType { Close, Far, Default }; - enum class EPlayerOrbitState - { - NoOrbit, - OrbitObject, - OrbitPoint, - OrbitCarcass, - ForcedOrbitObject, // For CMetroidBeta attack - Grapple - }; + enum class EPlayerOrbitState { + NoOrbit, + OrbitObject, + OrbitPoint, + OrbitCarcass, + ForcedOrbitObject, // For CMetroidBeta attack + Grapple + }; - enum class EPlayerOrbitRequest - { - StopOrbit, - Respawn, - EnterMorphBall, - Default, - Four, - Five, - InvalidateTarget, - BadVerticalAngle, - ActivateOrbitSource, - ProjectileCollide, - Freeze, - DamageOnGrapple, - LostGrappleLineOfSight - }; + enum class EPlayerOrbitRequest { + StopOrbit, + Respawn, + EnterMorphBall, + Default, + Four, + Five, + InvalidateTarget, + BadVerticalAngle, + ActivateOrbitSource, + ProjectileCollide, + Freeze, + DamageOnGrapple, + LostGrappleLineOfSight + }; - enum class EOrbitValidationResult - { - OK, - InvalidTarget, - PlayerNotReadyToTarget, - NonTargetableTarget, - ExtremeHorizonAngle, - BrokenLookAngle, - TargetingThroughDoor - }; + enum class EOrbitValidationResult { + OK, + InvalidTarget, + PlayerNotReadyToTarget, + NonTargetableTarget, + ExtremeHorizonAngle, + BrokenLookAngle, + TargetingThroughDoor + }; - enum class EPlayerZoneInfo - { - Targeting, - Scan - }; + enum class EPlayerZoneInfo { Targeting, Scan }; - enum class EPlayerZoneType - { - Always = -1, - Box = 0, - Ellipse - }; + enum class EPlayerZoneType { Always = -1, Box = 0, Ellipse }; - enum class EPlayerMovementState - { - OnGround, - Jump, - ApplyJump, - Falling, - FallingMorphed - }; + enum class EPlayerMovementState { OnGround, Jump, ApplyJump, Falling, FallingMorphed }; - enum class EPlayerMorphBallState - { - Unmorphed, - Morphed, - Morphing, - Unmorphing - }; + enum class EPlayerMorphBallState { Unmorphed, Morphed, Morphing, Unmorphing }; - enum class EPlayerCameraState - { - FirstPerson, - Ball, - Two, - Transitioning, - Spawned - }; + enum class EPlayerCameraState { FirstPerson, Ball, Two, Transitioning, Spawned }; - enum class ESurfaceRestraints - { - Normal, - InAir, - Ice, - MudSlow, - Water, - Lava, - PhazonFluid, - SnakeWeed - }; + enum class ESurfaceRestraints { Normal, InAir, Ice, MudSlow, Water, Lava, PhazonFluid, SnakeWeed }; - enum class EFootstepSfx - { - None, - Left, - Right - }; + enum class EFootstepSfx { None, Left, Right }; - enum class EGrappleState - { - None, - Firing, - Pull, - Swinging, - JumpOff - }; + enum class EGrappleState { None, Firing, Pull, Swinging, JumpOff }; - enum class EGunHolsterState - { - Holstered, - Drawing, - Drawn, - Holstering - }; + enum class EGunHolsterState { Holstered, Drawing, Drawn, Holstering }; private: - struct CVisorSteam - { - float x0_curTargetAlpha; - float x4_curAlphaInDur; - float x8_curAlphaOutDur; - CAssetId xc_tex; - float x10_nextTargetAlpha = 0.f; - float x14_nextAlphaInDur = 0.f; - float x18_nextAlphaOutDur = 0.f; - CAssetId x1c_txtr; - float x20_alpha = 0.f; - float x24_delayTimer = 0.f; - bool x28_affectsThermal = false; + struct CVisorSteam { + float x0_curTargetAlpha; + float x4_curAlphaInDur; + float x8_curAlphaOutDur; + CAssetId xc_tex; + float x10_nextTargetAlpha = 0.f; + float x14_nextAlphaInDur = 0.f; + float x18_nextAlphaOutDur = 0.f; + CAssetId x1c_txtr; + float x20_alpha = 0.f; + float x24_delayTimer = 0.f; + bool x28_affectsThermal = false; - public: - CVisorSteam(float targetAlpha, float alphaInDur, float alphaOutDur, CAssetId tex) - : x0_curTargetAlpha(targetAlpha), x4_curAlphaInDur(alphaInDur), x8_curAlphaOutDur(alphaOutDur), xc_tex(tex) {} - CAssetId GetTextureId() const; - void SetSteam(float targetAlpha, float alphaInDur, float alphaOutDur, CAssetId txtr, bool affectsThermal); - void Update(float dt); - float GetAlpha() const { return x20_alpha; } - bool AffectsThermal() const { return x28_affectsThermal; } + public: + CVisorSteam(float targetAlpha, float alphaInDur, float alphaOutDur, CAssetId tex) + : x0_curTargetAlpha(targetAlpha), x4_curAlphaInDur(alphaInDur), x8_curAlphaOutDur(alphaOutDur), xc_tex(tex) {} + CAssetId GetTextureId() const; + void SetSteam(float targetAlpha, float alphaInDur, float alphaOutDur, CAssetId txtr, bool affectsThermal); + void Update(float dt); + float GetAlpha() const { return x20_alpha; } + bool AffectsThermal() const { return x28_affectsThermal; } + }; + + class CFailsafeTest { + public: + enum class EInputState { Jump, StartingJump, Moving }; + + private: + rstl::reserved_vector x0_stateSamples; + rstl::reserved_vector x54_posSamples; + rstl::reserved_vector x148_velSamples; + rstl::reserved_vector x23c_inputSamples; + + public: + void Reset(); + void AddSample(EInputState state, const zeus::CVector3f& pos, const zeus::CVector3f& vel, + const zeus::CVector2f& input); + bool Passes() const; + }; + + EPlayerMovementState x258_movementState = EPlayerMovementState::OnGround; + std::vector x25c_ballTransitionsRes; + TUniqueId x26c_attachedActor = kInvalidUniqueId; + float x270_attachedActorTime = 0.f; + CPlayerEnergyDrain x274_energyDrain = CPlayerEnergyDrain(4); + float x288_startingJumpTimeout = 0.f; + float x28c_sjTimer = 0.f; + float x290_minJumpTimeout = 0.f; + float x294_jumpCameraTimer = 0.f; + u32 x298_jumpPresses = 0; + float x29c_fallCameraTimer = 0.f; + float x2a0_ = 0.f; + bool x2a4_cancelCameraPitch = false; + float x2a8_timeSinceJump = 1000.f; + ESurfaceRestraints x2ac_surfaceRestraint = ESurfaceRestraints::Normal; + u32 x2b0_outOfWaterTicks = 2; + rstl::reserved_vector x2b4_accelerationTable; + u32 x2d0_curAcceleration = 3; + float x2d4_accelerationChangeTimer = 0.f; + zeus::CAABox x2d8_fpBounds; + float x2f0_ballTransHeight = 0.f; + EPlayerCameraState x2f4_cameraState = EPlayerCameraState::FirstPerson; + EPlayerMorphBallState x2f8_morphBallState = EPlayerMorphBallState::Unmorphed; + EPlayerMorphBallState x2fc_spawnedMorphBallState = EPlayerMorphBallState::Unmorphed; + float x300_fallingTime = 0.f; + EPlayerOrbitState x304_orbitState = EPlayerOrbitState::NoOrbit; + EPlayerOrbitType x308_orbitType = EPlayerOrbitType::Close; + EPlayerOrbitRequest x30c_orbitRequest = EPlayerOrbitRequest::Default; + TUniqueId x310_orbitTargetId = kInvalidUniqueId; + zeus::CVector3f x314_orbitPoint; + zeus::CVector3f x320_orbitVector; + float x32c_orbitModeTimer = 0.f; + EPlayerZoneInfo x330_orbitZoneMode = EPlayerZoneInfo::Targeting; + EPlayerZoneType x334_orbitType = EPlayerZoneType::Ellipse; + u32 x338_ = 1; + TUniqueId x33c_orbitNextTargetId = kInvalidUniqueId; + bool m_deferredOrbitObject = false; + float x340_ = 0.f; + std::vector x344_nearbyOrbitObjects; + std::vector x354_onScreenOrbitObjects; + std::vector x364_offScreenOrbitObjects; + bool x374_orbitLockEstablished = false; + float x378_orbitPreventionTimer = 0.f; + bool x37c_sidewaysDashing = false; + float x380_strafeInputAtDash = 0.f; + float x384_dashTimer = 0.f; + float x388_dashButtonHoldTime = 0.f; + bool x38c_doneSidewaysDashing = false; + u32 x390_orbitSource = 2; + bool x394_orbitingEnemy = false; + float x398_dashSpeedMultiplier = 1.5f; + bool x39c_noStrafeDashBlend = false; + float x3a0_dashDuration = 0.5f; + float x3a4_strafeDashBlendDuration = 0.449f; + EPlayerScanState x3a8_scanState = EPlayerScanState::NotScanning; + float x3ac_scanningTime = 0.f; + float x3b0_curScanTime = 0.f; + TUniqueId x3b4_scanningObject = kInvalidUniqueId; + EGrappleState x3b8_grappleState = EGrappleState::None; + float x3bc_grappleSwingTimer = 0.f; + zeus::CVector3f x3c0_grappleSwingAxis = zeus::CVector3f::skRight; + float x3cc_ = 0.f; + float x3d0_ = 0.f; + float x3d4_ = 0.f; + float x3d8_grappleJumpTimeout = 0.f; + bool x3dc_inFreeLook = false; + bool x3dd_lookButtonHeld = false; + bool x3de_lookAnalogHeld = false; + float x3e0_curFreeLookCenteredTime = 0.f; + float x3e4_freeLookYawAngle = 0.f; + float x3e8_horizFreeLookAngleVel = 0.f; + float x3ec_freeLookPitchAngle = 0.f; + float x3f0_vertFreeLookAngleVel = 0.f; + TUniqueId x3f4_aimTarget = kInvalidUniqueId; + zeus::CVector3f x3f8_targetAimPosition = zeus::CVector3f::skZero; + TReservedAverage x404_aimTargetAverage; + zeus::CVector3f x480_assistedTargetAim = zeus::CVector3f::skZero; + float x48c_aimTargetTimer = 0.f; + std::unique_ptr x490_gun; + float x494_gunAlpha = 1.f; + EGunHolsterState x498_gunHolsterState = EGunHolsterState::Drawn; + float x49c_gunHolsterRemTime; + std::unique_ptr x4a0_failsafeTest; + TReservedAverage x4a4_moveSpeedAvg; + float x4f8_moveSpeed = 0.f; + float x4fc_flatMoveSpeed = 0.f; + zeus::CVector3f x500_lookDir = x34_transform.basis[1]; + zeus::CVector3f x50c_moveDir = x34_transform.basis[1]; + zeus::CVector3f x518_leaveMorphDir = x34_transform.basis[1]; + zeus::CVector3f x524_lastPosForDirCalc = x34_transform.basis[1]; + zeus::CVector3f x530_gunDir = x34_transform.basis[1]; + float x53c_timeMoving = 0.f; + zeus::CVector3f x540_controlDir = x34_transform.basis[1]; + zeus::CVector3f x54c_controlDirFlat = x34_transform.basis[1]; + bool x558_wasDamaged = false; + float x55c_damageAmt = 0.f; + float x560_prevDamageAmt = 0.f; + zeus::CVector3f x564_damageLocation; + float x570_immuneTimer = 0.f; + float x574_morphTime = 0.f; + float x578_morphDuration = 0.f; + u32 x57c_ = 0; + u32 x580_ = 0; + int x584_ballTransitionAnim = -1; + float x588_alpha = 1.f; + float x58c_transitionVel = 0.f; + bool x590_ = true; + TReservedAverage x594_transisionBeamXfs; + TReservedAverage x658_transitionModelXfs; + TReservedAverage x71c_transitionModelAlphas; + std::vector> x730_transitionModels; + float x740_staticTimer = 0.f; + float x744_staticOutSpeed = 0.f; + float x748_staticInSpeed = 0.f; + float x74c_visorStaticAlpha = 1.f; + float x750_frozenTimeout = 0.f; + s32 x754_iceBreakJumps = 0; + float x758_frozenTimeoutBias = 0.f; + s32 x75c_additionalIceBreakJumps = 0; + bool x760_controlsFrozen = false; + float x764_controlsFrozenTimeout = 0.f; + std::unique_ptr x768_morphball; + std::unique_ptr x76c_cameraBob; + CSfxHandle x770_damageLoopSfx; + float x774_samusVoiceTimeout = 0.f; + CSfxHandle x778_dashSfx; + CSfxHandle x77c_samusVoiceSfx; + int x780_samusVoicePriority = 0; + float x784_damageSfxTimer = 0.f; + u16 x788_damageLoopSfxId = 0; + float x78c_footstepSfxTimer = 0.f; + EFootstepSfx x790_footstepSfxSel = EFootstepSfx::None; + zeus::CVector3f x794_lastVelocity; + CVisorSteam x7a0_visorSteam = CVisorSteam(0.f, 0.f, 0.f, CAssetId() /*kInvalidAssetId*/); + CPlayerState::EPlayerSuit x7cc_transitionSuit; + CAnimRes x7d0_animRes; + zeus::CVector3f x7d8_beamScale; + bool x7e4_ = true; + u32 x7e8_ = 0; + CPlayerState::EBeamId x7ec_beam = CPlayerState::EBeamId::Power; + std::unique_ptr x7f0_ballTransitionBeamModel; + zeus::CTransform x7f4_gunWorldXf; + float x824_transitionFilterTimer = 0.f; + float x828_distanceUnderWater = 0.f; + bool x82c_inLava = false; + TUniqueId x82e_ridingPlatform = kInvalidUniqueId; + TUniqueId x830_playerHint = kInvalidUniqueId; + u32 x834_playerHintPriority = 1000; + rstl::reserved_vector, 32> x838_playerHints; + rstl::reserved_vector x93c_playerHintsToRemove; + rstl::reserved_vector x980_playerHintsToAdd; + + union { + struct { + bool x9c4_24_visorChangeRequested : 1; + bool x9c4_25_showCrosshairs : 1; + bool x9c4_26_ : 1; + bool x9c4_27_canEnterMorphBall : 1; + bool x9c4_28_canLeaveMorphBall : 1; + bool x9c4_29_spiderBallControlXY : 1; + bool x9c4_30_controlDirOverride : 1; + bool x9c4_31_dampUnderwaterMotion : 1; + bool x9c5_24_ : 1; + bool x9c5_25_splashUpdated : 1; + bool x9c5_26_ : 1; + bool x9c5_27_camSubmerged : 1; + bool x9c5_28_slidingOnWall : 1; + bool x9c5_29_hitWall : 1; + bool x9c5_30_selectFluidBallSound : 1; + bool x9c5_31_stepCameraZBiasDirty : 1; + bool x9c6_24_extendTargetDistance : 1; + bool x9c6_25_interpolatingControlDir : 1; + bool x9c6_26_outOfBallLookAtHint : 1; + bool x9c6_27_aimingAtProjectile : 1; + bool x9c6_28_aligningGrappleSwingTurn : 1; + bool x9c6_29_disableInput : 1; + bool x9c6_30_newScanScanning : 1; + bool x9c6_31_overrideRadarRadius : 1; + bool x9c7_24_noDamageLoopSfx : 1; + bool x9c7_25_outOfBallLookAtHintActor : 1; }; + u32 _dummy = 0; + }; - class CFailsafeTest - { - public: - enum class EInputState - { - Jump, - StartingJump, - Moving - }; - private: - rstl::reserved_vector x0_stateSamples; - rstl::reserved_vector x54_posSamples; - rstl::reserved_vector x148_velSamples; - rstl::reserved_vector x23c_inputSamples; - public: - void Reset(); - void AddSample(EInputState state, const zeus::CVector3f& pos, - const zeus::CVector3f& vel, const zeus::CVector2f& input); - bool Passes() const; - }; + float x9c8_eyeZBias = 0.f; + float x9cc_stepCameraZBias = 0.f; + u32 x9d0_bombJumpCount = 0; + u32 x9d4_bombJumpCheckDelayFrames = 0; + zeus::CVector3f x9d8_controlDirOverrideDir = zeus::CVector3f::skForward; + rstl::reserved_vector x9e4_orbitDisableList; - EPlayerMovementState x258_movementState = EPlayerMovementState::OnGround; - std::vector x25c_ballTransitionsRes; - TUniqueId x26c_attachedActor = kInvalidUniqueId; - float x270_attachedActorTime = 0.f; - CPlayerEnergyDrain x274_energyDrain = CPlayerEnergyDrain(4); - float x288_startingJumpTimeout = 0.f; - float x28c_sjTimer = 0.f; - float x290_minJumpTimeout = 0.f; - float x294_jumpCameraTimer = 0.f; - u32 x298_jumpPresses = 0; - float x29c_fallCameraTimer = 0.f; - float x2a0_ = 0.f; - bool x2a4_cancelCameraPitch = false; - float x2a8_timeSinceJump = 1000.f; - ESurfaceRestraints x2ac_surfaceRestraint = ESurfaceRestraints::Normal; - u32 x2b0_outOfWaterTicks = 2; - rstl::reserved_vector x2b4_accelerationTable; - u32 x2d0_curAcceleration = 3; - float x2d4_accelerationChangeTimer = 0.f; - zeus::CAABox x2d8_fpBounds; - float x2f0_ballTransHeight = 0.f; - EPlayerCameraState x2f4_cameraState = EPlayerCameraState::FirstPerson; - EPlayerMorphBallState x2f8_morphBallState = EPlayerMorphBallState::Unmorphed; - EPlayerMorphBallState x2fc_spawnedMorphBallState = EPlayerMorphBallState::Unmorphed; - float x300_fallingTime = 0.f; - EPlayerOrbitState x304_orbitState = EPlayerOrbitState::NoOrbit; - EPlayerOrbitType x308_orbitType = EPlayerOrbitType::Close; - EPlayerOrbitRequest x30c_orbitRequest = EPlayerOrbitRequest::Default; - TUniqueId x310_orbitTargetId = kInvalidUniqueId; - zeus::CVector3f x314_orbitPoint; - zeus::CVector3f x320_orbitVector; - float x32c_orbitModeTimer = 0.f; - EPlayerZoneInfo x330_orbitZoneMode = EPlayerZoneInfo::Targeting; - EPlayerZoneType x334_orbitType = EPlayerZoneType::Ellipse; - u32 x338_ = 1; - TUniqueId x33c_orbitNextTargetId = kInvalidUniqueId; - bool m_deferredOrbitObject = false; - float x340_ = 0.f; - std::vector x344_nearbyOrbitObjects; - std::vector x354_onScreenOrbitObjects; - std::vector x364_offScreenOrbitObjects; - bool x374_orbitLockEstablished = false; - float x378_orbitPreventionTimer = 0.f; - bool x37c_sidewaysDashing = false; - float x380_strafeInputAtDash = 0.f; - float x384_dashTimer = 0.f; - float x388_dashButtonHoldTime = 0.f; - bool x38c_doneSidewaysDashing = false; - u32 x390_orbitSource = 2; - bool x394_orbitingEnemy = false; - float x398_dashSpeedMultiplier = 1.5f; - bool x39c_noStrafeDashBlend = false; - float x3a0_dashDuration = 0.5f; - float x3a4_strafeDashBlendDuration = 0.449f; - EPlayerScanState x3a8_scanState = EPlayerScanState::NotScanning; - float x3ac_scanningTime = 0.f; - float x3b0_curScanTime = 0.f; - TUniqueId x3b4_scanningObject = kInvalidUniqueId; - EGrappleState x3b8_grappleState = EGrappleState::None; - float x3bc_grappleSwingTimer = 0.f; - zeus::CVector3f x3c0_grappleSwingAxis = zeus::CVector3f::skRight; - float x3cc_ = 0.f; - float x3d0_ = 0.f; - float x3d4_ = 0.f; - float x3d8_grappleJumpTimeout = 0.f; - bool x3dc_inFreeLook = false; - bool x3dd_lookButtonHeld = false; - bool x3de_lookAnalogHeld = false; - float x3e0_curFreeLookCenteredTime = 0.f; - float x3e4_freeLookYawAngle = 0.f; - float x3e8_horizFreeLookAngleVel = 0.f; - float x3ec_freeLookPitchAngle = 0.f; - float x3f0_vertFreeLookAngleVel = 0.f; - TUniqueId x3f4_aimTarget = kInvalidUniqueId; - zeus::CVector3f x3f8_targetAimPosition = zeus::CVector3f::skZero; - TReservedAverage x404_aimTargetAverage; - zeus::CVector3f x480_assistedTargetAim = zeus::CVector3f::skZero; - float x48c_aimTargetTimer = 0.f; - std::unique_ptr x490_gun; - float x494_gunAlpha = 1.f; - EGunHolsterState x498_gunHolsterState = EGunHolsterState::Drawn; - float x49c_gunHolsterRemTime; - std::unique_ptr x4a0_failsafeTest; - TReservedAverage x4a4_moveSpeedAvg; - float x4f8_moveSpeed = 0.f; - float x4fc_flatMoveSpeed = 0.f; - zeus::CVector3f x500_lookDir = x34_transform.basis[1]; - zeus::CVector3f x50c_moveDir = x34_transform.basis[1]; - zeus::CVector3f x518_leaveMorphDir = x34_transform.basis[1]; - zeus::CVector3f x524_lastPosForDirCalc = x34_transform.basis[1]; - zeus::CVector3f x530_gunDir = x34_transform.basis[1]; - float x53c_timeMoving = 0.f; - zeus::CVector3f x540_controlDir = x34_transform.basis[1]; - zeus::CVector3f x54c_controlDirFlat = x34_transform.basis[1]; - bool x558_wasDamaged = false; - float x55c_damageAmt = 0.f; - float x560_prevDamageAmt = 0.f; - zeus::CVector3f x564_damageLocation; - float x570_immuneTimer = 0.f; - float x574_morphTime = 0.f; - float x578_morphDuration = 0.f; - u32 x57c_ = 0; - u32 x580_ = 0; - int x584_ballTransitionAnim = -1; - float x588_alpha = 1.f; - float x58c_transitionVel = 0.f; - bool x590_ = true; - TReservedAverage x594_transisionBeamXfs; - TReservedAverage x658_transitionModelXfs; - TReservedAverage x71c_transitionModelAlphas; - std::vector> x730_transitionModels; - float x740_staticTimer = 0.f; - float x744_staticOutSpeed = 0.f; - float x748_staticInSpeed = 0.f; - float x74c_visorStaticAlpha = 1.f; - float x750_frozenTimeout = 0.f; - s32 x754_iceBreakJumps = 0; - float x758_frozenTimeoutBias = 0.f; - s32 x75c_additionalIceBreakJumps = 0; - bool x760_controlsFrozen = false; - float x764_controlsFrozenTimeout = 0.f; - std::unique_ptr x768_morphball; - std::unique_ptr x76c_cameraBob; - CSfxHandle x770_damageLoopSfx; - float x774_samusVoiceTimeout = 0.f; - CSfxHandle x778_dashSfx; - CSfxHandle x77c_samusVoiceSfx; - int x780_samusVoicePriority = 0; - float x784_damageSfxTimer = 0.f; - u16 x788_damageLoopSfxId = 0; - float x78c_footstepSfxTimer = 0.f; - EFootstepSfx x790_footstepSfxSel = EFootstepSfx::None; - zeus::CVector3f x794_lastVelocity; - CVisorSteam x7a0_visorSteam = CVisorSteam(0.f, 0.f, 0.f, CAssetId()/*kInvalidAssetId*/); - CPlayerState::EPlayerSuit x7cc_transitionSuit; - CAnimRes x7d0_animRes; - zeus::CVector3f x7d8_beamScale; - bool x7e4_ = true; - u32 x7e8_ = 0; - CPlayerState::EBeamId x7ec_beam = CPlayerState::EBeamId::Power; - std::unique_ptr x7f0_ballTransitionBeamModel; - zeus::CTransform x7f4_gunWorldXf; - float x824_transitionFilterTimer = 0.f; - float x828_distanceUnderWater = 0.f; - bool x82c_inLava = false; - TUniqueId x82e_ridingPlatform = kInvalidUniqueId; - TUniqueId x830_playerHint = kInvalidUniqueId; - u32 x834_playerHintPriority = 1000; - rstl::reserved_vector, 32> x838_playerHints; - rstl::reserved_vector x93c_playerHintsToRemove; - rstl::reserved_vector x980_playerHintsToAdd; + float x9f4_deathTime = 0.f; + float x9f8_controlDirInterpTime = 0.f; + float x9fc_controlDirInterpDur = 0.f; + TUniqueId xa00_deathPowerBomb = kInvalidUniqueId; + float xa04_preThinkDt = 0.f; + CAssetId xa08_steamTextureId; + CAssetId xa0c_iceTextureId; + u32 xa10_phazonCounter = 0; + float xa14_phazonCameraShakeTimer = 0.f; + float xa18_phazonDamageLag = 0.f; + float xa1c_threatOverride = 0.f; + float xa20_radarXYRadiusOverride = 1.f; + float xa24_radarZRadiusOverride = 1.f; + float xa28_attachedActorStruggle = 0.f; + int xa2c_damageLoopSfxDelayTicks = 2; + float xa30_samusExhaustedVoiceTimer = 4.f; - union - { - struct - { - bool x9c4_24_visorChangeRequested : 1; - bool x9c4_25_showCrosshairs : 1; - bool x9c4_26_ : 1; - bool x9c4_27_canEnterMorphBall : 1; - bool x9c4_28_canLeaveMorphBall : 1; - bool x9c4_29_spiderBallControlXY : 1; - bool x9c4_30_controlDirOverride : 1; - bool x9c4_31_dampUnderwaterMotion : 1; - bool x9c5_24_ : 1; - bool x9c5_25_splashUpdated : 1; - bool x9c5_26_ : 1; - bool x9c5_27_camSubmerged : 1; - bool x9c5_28_slidingOnWall : 1; - bool x9c5_29_hitWall : 1; - bool x9c5_30_selectFluidBallSound : 1; - bool x9c5_31_stepCameraZBiasDirty : 1; - bool x9c6_24_extendTargetDistance : 1; - bool x9c6_25_interpolatingControlDir : 1; - bool x9c6_26_outOfBallLookAtHint : 1; - bool x9c6_27_aimingAtProjectile : 1; - bool x9c6_28_aligningGrappleSwingTurn : 1; - bool x9c6_29_disableInput : 1; - bool x9c6_30_newScanScanning : 1; - bool x9c6_31_overrideRadarRadius : 1; - bool x9c7_24_noDamageLoopSfx : 1; - bool x9c7_25_outOfBallLookAtHintActor : 1; - }; - u32 _dummy = 0; - }; - - float x9c8_eyeZBias = 0.f; - float x9cc_stepCameraZBias = 0.f; - u32 x9d0_bombJumpCount = 0; - u32 x9d4_bombJumpCheckDelayFrames = 0; - zeus::CVector3f x9d8_controlDirOverrideDir = zeus::CVector3f::skForward; - rstl::reserved_vector x9e4_orbitDisableList; - - float x9f4_deathTime = 0.f; - float x9f8_controlDirInterpTime = 0.f; - float x9fc_controlDirInterpDur = 0.f; - TUniqueId xa00_deathPowerBomb = kInvalidUniqueId; - float xa04_preThinkDt = 0.f; - CAssetId xa08_steamTextureId; - CAssetId xa0c_iceTextureId; - u32 xa10_phazonCounter = 0; - float xa14_phazonCameraShakeTimer = 0.f; - float xa18_phazonDamageLag = 0.f; - float xa1c_threatOverride = 0.f; - float xa20_radarXYRadiusOverride = 1.f; - float xa24_radarZRadiusOverride = 1.f; - float xa28_attachedActorStruggle = 0.f; - int xa2c_damageLoopSfxDelayTicks = 2; - float xa30_samusExhaustedVoiceTimer = 4.f; - - void StartLandingControlFreeze(); - void EndLandingControlFreeze(); - void ProcessFrozenInput(float dt, CStateManager& mgr); - bool CheckSubmerged() const; - void UpdateSubmerged(CStateManager& mgr); - void InitializeBallTransition(); - float UpdateCameraBob(float dt, CStateManager& mgr); - float GetAcceleration() const; - float CalculateOrbitMinDistance(EPlayerOrbitType type) const; + void StartLandingControlFreeze(); + void EndLandingControlFreeze(); + void ProcessFrozenInput(float dt, CStateManager& mgr); + bool CheckSubmerged() const; + void UpdateSubmerged(CStateManager& mgr); + void InitializeBallTransition(); + float UpdateCameraBob(float dt, CStateManager& mgr); + float GetAcceleration() const; + float CalculateOrbitMinDistance(EPlayerOrbitType type) const; public: - CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox& aabb, CAssetId resId, - const zeus::CVector3f& playerScale, float mass, float stepUp, float stepDown, float ballRadius, - const CMaterialList& ml); + CPlayer(TUniqueId uid, const zeus::CTransform& xf, const zeus::CAABox& aabb, CAssetId resId, + const zeus::CVector3f& playerScale, float mass, float stepUp, float stepDown, float ballRadius, + const CMaterialList& ml); - bool IsTransparent() const; - bool GetControlsFrozen() const { return x760_controlsFrozen; } - float GetTransitionAlpha(const zeus::CVector3f& camPos, float zNear) const; - s32 ChooseTransitionToAnimation(float dt, CStateManager& mgr) const; - void TransitionToMorphBallState(float dt, CStateManager& mgr); - void TransitionFromMorphBallState(CStateManager& mgr); - s32 GetNextBallTransitionAnim(float dt, bool& loopOut, CStateManager& mgr); - void UpdateMorphBallTransition(float dt, CStateManager& mgr); - void UpdateGunAlpha(); - void UpdatePlayerSounds(float dt); - void Update(float, CStateManager& mgr); - void PostUpdate(float, CStateManager& mgr); - bool StartSamusVoiceSfx(u16 sfx, float vol, int prio); - bool IsPlayerDeadEnough() const; - void AsyncLoadSuit(CStateManager& mgr); - void LoadAnimationTokens(); - bool HasTransitionBeamModel() const; - bool CanRenderUnsorted(const CStateManager& mgr) const; - const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f& v1, const zeus::CVector3f& v2, - const CDamageInfo& info) const; - const CDamageVulnerability* GetDamageVulnerability() const; - zeus::CVector3f GetHomingPosition(const CStateManager& mgr, float) const; - zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const; - void FluidFXThink(CActor::EFluidState, CScriptWater& water, CStateManager& mgr); - zeus::CVector3f GetDamageLocationWR() const { return x564_damageLocation; } - float GetPrevDamageAmount() const { return x560_prevDamageAmt; } - float GetDamageAmount() const { return x55c_damageAmt; } - bool WasDamaged() const { return x558_wasDamaged; } - void TakeDamage(bool, const zeus::CVector3f&, float, EWeaponType, CStateManager& mgr); - void Accept(IVisitor& visitor); - CHealthInfo* HealthInfo(CStateManager& mgr); - bool IsUnderBetaMetroidAttack(CStateManager& mgr) const; - std::experimental::optional GetTouchBounds() const; - void Touch(CActor& actor, CStateManager& mgr); - void DoPreThink(float dt, CStateManager& mgr); - void DoThink(float dt, CStateManager& mgr); - void UpdateScanningState(const CFinalInput& input, CStateManager& mgr, float); - bool ValidateScanning(const CFinalInput& input, CStateManager& mgr); - void FinishNewScan(CStateManager& mgr); - void SetScanningState(EPlayerScanState, CStateManager& mgr); - void SetSpawnedMorphBallState(EPlayerMorphBallState, CStateManager&); - bool GetExplorationMode() const; - bool GetCombatMode() const; - void RenderGun(const CStateManager& mgr, const zeus::CVector3f&) const; - void Render(const CStateManager& mgr) const; - void RenderReflectedPlayer(CStateManager& mgr); - void PreRender(CStateManager& mgr, const zeus::CFrustum&); - void CalculateRenderBounds(); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - void ComputeFreeLook(const CFinalInput& input); - void UpdateFreeLookState(const CFinalInput&, float dt, CStateManager&); - void UpdateFreeLook(float dt); - float GetMaximumPlayerPositiveVerticalVelocity(CStateManager&) const; - void ProcessInput(const CFinalInput&, CStateManager&); - bool ShouldSampleFailsafe(CStateManager& mgr) const; - void CalculateLeaveMorphBallDirection(const CFinalInput& input); - void CalculatePlayerControlDirection(CStateManager& mgr); - void CalculatePlayerMovementDirection(float dt); - void UnFreeze(CStateManager& stateMgr); - void Freeze(CStateManager& stateMgr, CAssetId steamTxtr, u16 sfx, CAssetId iceTxtr); - bool GetFrozenState() const; - void UpdateFrozenState(const CFinalInput& input, CStateManager& mgr); - void UpdateStepCameraZBias(float dt); - void UpdateWaterSurfaceCameraBias(CStateManager& mgr); - void UpdatePhazonCameraShake(float dt, CStateManager& mgr); - void UpdatePhazonDamage(float dt, CStateManager& mgr); - void ResetPlayerHintState(); - bool SetAreaPlayerHint(const CScriptPlayerHint& hint, CStateManager& mgr); - void AddToPlayerHintRemoveList(TUniqueId id, CStateManager& mgr); - void AddToPlayerHintAddList(TUniqueId id, CStateManager& mgr); - void DeactivatePlayerHint(TUniqueId id, CStateManager& mgr); - void UpdatePlayerHints(CStateManager& mgr); - void UpdateBombJumpStuff(); - void UpdateTransitionFilter(float dt, CStateManager& mgr); - void ResetControlDirectionInterpolation(); - void SetControlDirectionInterpolation(float time); - void UpdatePlayerControlDirection(float dt, CStateManager& mgr); - void Think(float, CStateManager&); - void PreThink(float, CStateManager&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void SetVisorSteam(float, float, float, CAssetId, bool); - void UpdateFootstepSounds(const CFinalInput& input, CStateManager&, float); - u16 GetMaterialSoundUnderPlayer(CStateManager& mgr, const u16*, u32, u16); - static u16 SfxIdFromMaterial(const CMaterialList&, const u16*, u32, u16); - void UpdateCrosshairsState(const CFinalInput&); - void UpdateVisorTransition(float, CStateManager& mgr); - void UpdateVisorState(const CFinalInput&, float, CStateManager& mgr); - void UpdateGunState(const CFinalInput&, CStateManager& mgr); - void ResetGun(CStateManager& mgr); - void UpdateArmAndGunTransforms(float dt, CStateManager& mgr); - void ForceGunOrientation(const zeus::CTransform&, CStateManager& mgr); - void UpdateCameraState(CStateManager& mgr); - void UpdateDebugCamera(CStateManager& mgr); - void UpdateCameraTimers(float dt, const CFinalInput& input); - void UpdateMorphBallState(float dt, const CFinalInput&, CStateManager& mgr); - CFirstPersonCamera& GetFirstPersonCamera(CStateManager& mgr); - void UpdateGunTransform(const zeus::CVector3f&, CStateManager& mgr); - void UpdateAssistedAiming(const zeus::CTransform& xf, const CStateManager& mgr); - void UpdateAimTargetPrediction(const zeus::CTransform& xf, const CStateManager& mgr); - void ResetAimTargetPrediction(TUniqueId target); - void DrawGun(CStateManager& mgr); - void HolsterGun(CStateManager& mgr); - EPlayerCameraState GetCameraState() const { return x2f4_cameraState; } - EPlayerMorphBallState GetMorphballTransitionState() const { return x2f8_morphBallState; } - EGunHolsterState GetGunHolsterState() const { return x498_gunHolsterState; } - EPlayerMovementState GetPlayerMovementState() const { return x258_movementState; } - bool IsMorphBallTransitioning() const; - void UpdateGrappleArmTransform(const zeus::CVector3f&, CStateManager& mgr, float); - float GetGravity() const; - void ApplyGrappleForces(const CFinalInput& input, CStateManager& mgr, float); - bool ValidateFPPosition(const zeus::CVector3f& pos, CStateManager& mgr); - void UpdateGrappleState(const CFinalInput& input, CStateManager& mgr); - void ApplyGrappleJump(CStateManager& mgr); - void BeginGrapple(zeus::CVector3f&, CStateManager& mgr); - void BreakGrapple(EPlayerOrbitRequest, CStateManager& mgr); - void SetOrbitRequest(EPlayerOrbitRequest req, CStateManager& mgr); - void SetOrbitRequestForTarget(TUniqueId id, EPlayerOrbitRequest req, CStateManager& mgr); - bool InGrappleJumpCooldown() const; - void PreventFallingCameraPitch(); - void OrbitCarcass(CStateManager&); - void OrbitPoint(EPlayerOrbitType, CStateManager& mgr); - zeus::CVector3f GetHUDOrbitTargetPosition() const; - void SetOrbitState(EPlayerOrbitState, CStateManager& mgr); - void SetOrbitTargetId(TUniqueId, CStateManager& mgr); - void UpdateOrbitPosition(float, CStateManager& mgr); - void UpdateOrbitZPosition(); - void UpdateOrbitFixedPosition(); - void SetOrbitPosition(float, CStateManager& mgr); - void UpdateAimTarget(CStateManager& mgr); - void UpdateAimTargetTimer(float); - bool ValidateAimTargetId(TUniqueId, CStateManager& mgr); - bool ValidateObjectForMode(TUniqueId, CStateManager& mgr) const; - TUniqueId FindAimTargetId(CStateManager& mgr); - TUniqueId GetAimTarget() const { return x3f4_aimTarget; } - TUniqueId CheckEnemiesAgainstOrbitZone(const rstl::reserved_vector&, EPlayerZoneInfo, - EPlayerZoneType, CStateManager& mgr) const; - TUniqueId FindOrbitTargetId(CStateManager& mgr); - void UpdateOrbitableObjects(CStateManager& mgr); - TUniqueId FindBestOrbitableObject(const std::vector&, EPlayerZoneInfo, CStateManager& mgr) const; - void FindOrbitableObjects(const rstl::reserved_vector&, std::vector&, - EPlayerZoneInfo, EPlayerZoneType, CStateManager& mgr, bool) const; - bool WithinOrbitScreenBox(const zeus::CVector3f&, EPlayerZoneInfo, EPlayerZoneType) const; - bool WithinOrbitScreenEllipse(const zeus::CVector3f&, EPlayerZoneInfo) const; - bool CheckOrbitDisableSourceList(CStateManager& mgr); - bool CheckOrbitDisableSourceList() const { return !x9e4_orbitDisableList.empty(); } - void RemoveOrbitDisableSource(TUniqueId); - void AddOrbitDisableSource(CStateManager& mgr, TUniqueId); - void UpdateOrbitPreventionTimer(float); - void UpdateOrbitModeTimer(float); - void UpdateOrbitZone(CStateManager& mgr); - void UpdateOrbitInput(const CFinalInput& input, CStateManager& mgr); - void ActivateOrbitSource(CStateManager& mgr); - void UpdateOrbitSelection(const CFinalInput& input, CStateManager& mgr); - void UpdateOrbitOrientation(CStateManager& mgr); - void UpdateOrbitTarget(CStateManager& mgr); - float GetOrbitMaxLockDistance(CStateManager& mgr) const; - float GetOrbitMaxTargetDistance(CStateManager& mgr) const; - EOrbitValidationResult ValidateOrbitTargetId(TUniqueId uid, CStateManager& mgr) const; - EOrbitValidationResult ValidateCurrentOrbitTargetId(CStateManager& mgr); - bool ValidateOrbitTargetIdAndPointer(TUniqueId, CStateManager& mgr) const; - zeus::CVector3f GetBallPosition() const; - zeus::CVector3f GetEyePosition() const; - float GetEyeHeight() const; - float GetUnbiasedEyeHeight() const; - float GetStepUpHeight() const; - float GetStepDownHeight() const; - void Teleport(const zeus::CTransform& xf, CStateManager& mgr, bool resetBallCam); - void BombJump(const zeus::CVector3f& pos, CStateManager& mgr); - zeus::CTransform CreateTransformFromMovementDirection() const; - const CCollisionPrimitive* GetCollisionPrimitive() const; - const CCollidableSphere* GetCollidableSphere() const; - zeus::CTransform GetPrimitiveTransform() const; - void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr); - float GetBallMaxVelocity() const; - float GetActualBallMaxVelocity(float dt) const; - float GetActualFirstPersonMaxVelocity(float dt) const; - void SetMoveState(EPlayerMovementState, CStateManager& mgr); - float JumpInput(const CFinalInput& input, CStateManager& mgr); - float TurnInput(const CFinalInput& input) const; - float StrafeInput(const CFinalInput& input) const; - float ForwardInput(const CFinalInput& input, float) const; - zeus::CVector3f CalculateLeftStickEdgePosition(float strafeInput, float forwardInput) const; - bool SidewaysDashAllowed(float strafeInput, float forwardInput, - const CFinalInput& input, CStateManager& mgr) const; - void FinishSidewaysDash(); - void ComputeDash(const CFinalInput& input, float dt, CStateManager& mgr); - void ComputeMovement(const CFinalInput& input, CStateManager& mgr, float dt); - float GetWeight() const; - zeus::CVector3f GetDampedClampedVelocityWR() const; - const CVisorSteam& GetVisorSteam() const { return x7a0_visorSteam; } - float GetVisorStaticAlpha() const { return x74c_visorStaticAlpha; } - float GetGunAlpha() const { return x494_gunAlpha; } - const CScriptWater* GetVisorRunoffEffect(const CStateManager& mgr) const; - void SetMorphBallState(EPlayerMorphBallState state, CStateManager& mgr); - bool CanLeaveMorphBallState(CStateManager& mgr, zeus::CVector3f& pos) const; - void SetHudDisable(float staticTimer, float outSpeed, float inSpeed); - void SetIntoBallReadyAnimation(CStateManager& mgr); - void LeaveMorphBallState(CStateManager& mgr); - bool CanEnterMorphBallState(CStateManager& mgr, float f1) const; - void EnterMorphBallState(CStateManager& mgr); - void ActivateMorphBallCamera(CStateManager& mgr); - void UpdateCinematicState(CStateManager& mgr); - void SetCameraState(EPlayerCameraState camState, CStateManager& stateMgr); - bool IsEnergyLow(const CStateManager& mgr) const; - EPlayerOrbitState GetOrbitState() const { return x304_orbitState; } - EPlayerScanState GetScanningState() const { return x3a8_scanState; } - float GetScanningTime() const { return x3ac_scanningTime; } - TUniqueId GetOrbitTargetId() const { return x310_orbitTargetId; } - TUniqueId GetOrbitNextTargetId() const { return x33c_orbitNextTargetId; } - TUniqueId GetScanningObjectId() const { return x3b4_scanningObject; } - EGrappleState GetGrappleState() const { return x3b8_grappleState; } - bool IsNewScanScanning() const { return x9c6_30_newScanScanning; } - float GetThreatOverride() const { return xa1c_threatOverride; } - bool IsOverrideRadarRadius() const { return x9c6_31_overrideRadarRadius; } - float GetRadarXYRadiusOverride() const { return xa20_radarXYRadiusOverride; } - float GetRadarZRadiusOverride() const { return xa24_radarZRadiusOverride; } - bool ObjectInScanningRange(TUniqueId id, const CStateManager& mgr) const; - float GetMorphTime() const { return x574_morphTime; } - float GetMorphDuration() const { return x578_morphDuration; } - float GetMorphFactor() const - { - if (0.f != x578_morphDuration) - return zeus::clamp(0.f, x574_morphTime / x578_morphDuration, 1.f); - return 0.f; - } - bool IsInFreeLook() const { return x3dc_inFreeLook; } - bool GetFreeLookStickState() const { return x3de_lookAnalogHeld; } - CPlayerGun* GetPlayerGun() const { return x490_gun.get(); } - CMorphBall* GetMorphBall() const { return x768_morphball.get(); } - CPlayerCameraBob* GetCameraBob() const { return x76c_cameraBob.get(); } - float GetStaticTimer() const { return x740_staticTimer; } - float GetDeathTime() const { return x9f4_deathTime; } - const CPlayerEnergyDrain& GetEnergyDrain() const { return x274_energyDrain; } - EPlayerZoneInfo GetOrbitZone() const { return x330_orbitZoneMode; } - EPlayerZoneType GetOrbitType() const { return x334_orbitType; } - const zeus::CTransform& GetFirstPersonCameraTransform(const CStateManager& mgr) const; - const std::vector& GetNearbyOrbitObjects() const { return x344_nearbyOrbitObjects; } - const std::vector& GetOnScreenOrbitObjects() const { return x354_onScreenOrbitObjects; } - const std::vector& GetOffScreenOrbitObjects() const { return x364_offScreenOrbitObjects; } - void SetPlayerHitWallDuringMove(); - ESurfaceRestraints GetCurrentSurfaceRestraint() const { return x2ac_surfaceRestraint; } - ESurfaceRestraints GetSurfaceRestraint() const - { return x2b0_outOfWaterTicks == 2 ? GetCurrentSurfaceRestraint() : ESurfaceRestraints::Water; } - void DecrementPhazon(); - void IncrementPhazon(); - void ApplySubmergedPitchBend(CSfxHandle& sfx); - void DetachActorFromPlayer(); - bool AttachActorToPlayer(TUniqueId id, bool disableGun); - TUniqueId GetAttachedActor() const { return x26c_attachedActor; } - float GetAttachedActorStruggle() const { return xa28_attachedActorStruggle; } - float GetDistanceUnderWater() const { return x828_distanceUnderWater; } - TUniqueId GetRidingPlatformId() const { return x82e_ridingPlatform; } - const zeus::CVector3f& GetLastVelocity() const { return x794_lastVelocity; } - const zeus::CVector3f& GetMoveDir() const { return x50c_moveDir; } - const zeus::CVector3f& GetLeaveMorphDir() const { return x518_leaveMorphDir; } - u32 GetBombJumpCount() const { return x9d0_bombJumpCount; } - float GetMoveSpeed() const { return x4f8_moveSpeed; } - EPlayerOrbitRequest GetOrbitRequest() const { return x30c_orbitRequest; } - bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; } - bool IsSidewaysDashing() const { return x37c_sidewaysDashing; } - void Set_X590(bool b) { x590_ = b; } + bool IsTransparent() const; + bool GetControlsFrozen() const { return x760_controlsFrozen; } + float GetTransitionAlpha(const zeus::CVector3f& camPos, float zNear) const; + s32 ChooseTransitionToAnimation(float dt, CStateManager& mgr) const; + void TransitionToMorphBallState(float dt, CStateManager& mgr); + void TransitionFromMorphBallState(CStateManager& mgr); + s32 GetNextBallTransitionAnim(float dt, bool& loopOut, CStateManager& mgr); + void UpdateMorphBallTransition(float dt, CStateManager& mgr); + void UpdateGunAlpha(); + void UpdatePlayerSounds(float dt); + void Update(float, CStateManager& mgr); + void PostUpdate(float, CStateManager& mgr); + bool StartSamusVoiceSfx(u16 sfx, float vol, int prio); + bool IsPlayerDeadEnough() const; + void AsyncLoadSuit(CStateManager& mgr); + void LoadAnimationTokens(); + bool HasTransitionBeamModel() const; + bool CanRenderUnsorted(const CStateManager& mgr) const; + const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f& v1, const zeus::CVector3f& v2, + const CDamageInfo& info) const; + const CDamageVulnerability* GetDamageVulnerability() const; + zeus::CVector3f GetHomingPosition(const CStateManager& mgr, float) const; + zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const; + void FluidFXThink(CActor::EFluidState, CScriptWater& water, CStateManager& mgr); + zeus::CVector3f GetDamageLocationWR() const { return x564_damageLocation; } + float GetPrevDamageAmount() const { return x560_prevDamageAmt; } + float GetDamageAmount() const { return x55c_damageAmt; } + bool WasDamaged() const { return x558_wasDamaged; } + void TakeDamage(bool, const zeus::CVector3f&, float, EWeaponType, CStateManager& mgr); + void Accept(IVisitor& visitor); + CHealthInfo* HealthInfo(CStateManager& mgr); + bool IsUnderBetaMetroidAttack(CStateManager& mgr) const; + std::experimental::optional GetTouchBounds() const; + void Touch(CActor& actor, CStateManager& mgr); + void DoPreThink(float dt, CStateManager& mgr); + void DoThink(float dt, CStateManager& mgr); + void UpdateScanningState(const CFinalInput& input, CStateManager& mgr, float); + bool ValidateScanning(const CFinalInput& input, CStateManager& mgr); + void FinishNewScan(CStateManager& mgr); + void SetScanningState(EPlayerScanState, CStateManager& mgr); + void SetSpawnedMorphBallState(EPlayerMorphBallState, CStateManager&); + bool GetExplorationMode() const; + bool GetCombatMode() const; + void RenderGun(const CStateManager& mgr, const zeus::CVector3f&) const; + void Render(const CStateManager& mgr) const; + void RenderReflectedPlayer(CStateManager& mgr); + void PreRender(CStateManager& mgr, const zeus::CFrustum&); + void CalculateRenderBounds(); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void ComputeFreeLook(const CFinalInput& input); + void UpdateFreeLookState(const CFinalInput&, float dt, CStateManager&); + void UpdateFreeLook(float dt); + float GetMaximumPlayerPositiveVerticalVelocity(CStateManager&) const; + void ProcessInput(const CFinalInput&, CStateManager&); + bool ShouldSampleFailsafe(CStateManager& mgr) const; + void CalculateLeaveMorphBallDirection(const CFinalInput& input); + void CalculatePlayerControlDirection(CStateManager& mgr); + void CalculatePlayerMovementDirection(float dt); + void UnFreeze(CStateManager& stateMgr); + void Freeze(CStateManager& stateMgr, CAssetId steamTxtr, u16 sfx, CAssetId iceTxtr); + bool GetFrozenState() const; + void UpdateFrozenState(const CFinalInput& input, CStateManager& mgr); + void UpdateStepCameraZBias(float dt); + void UpdateWaterSurfaceCameraBias(CStateManager& mgr); + void UpdatePhazonCameraShake(float dt, CStateManager& mgr); + void UpdatePhazonDamage(float dt, CStateManager& mgr); + void ResetPlayerHintState(); + bool SetAreaPlayerHint(const CScriptPlayerHint& hint, CStateManager& mgr); + void AddToPlayerHintRemoveList(TUniqueId id, CStateManager& mgr); + void AddToPlayerHintAddList(TUniqueId id, CStateManager& mgr); + void DeactivatePlayerHint(TUniqueId id, CStateManager& mgr); + void UpdatePlayerHints(CStateManager& mgr); + void UpdateBombJumpStuff(); + void UpdateTransitionFilter(float dt, CStateManager& mgr); + void ResetControlDirectionInterpolation(); + void SetControlDirectionInterpolation(float time); + void UpdatePlayerControlDirection(float dt, CStateManager& mgr); + void Think(float, CStateManager&); + void PreThink(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void SetVisorSteam(float, float, float, CAssetId, bool); + void UpdateFootstepSounds(const CFinalInput& input, CStateManager&, float); + u16 GetMaterialSoundUnderPlayer(CStateManager& mgr, const u16*, u32, u16); + static u16 SfxIdFromMaterial(const CMaterialList&, const u16*, u32, u16); + void UpdateCrosshairsState(const CFinalInput&); + void UpdateVisorTransition(float, CStateManager& mgr); + void UpdateVisorState(const CFinalInput&, float, CStateManager& mgr); + void UpdateGunState(const CFinalInput&, CStateManager& mgr); + void ResetGun(CStateManager& mgr); + void UpdateArmAndGunTransforms(float dt, CStateManager& mgr); + void ForceGunOrientation(const zeus::CTransform&, CStateManager& mgr); + void UpdateCameraState(CStateManager& mgr); + void UpdateDebugCamera(CStateManager& mgr); + void UpdateCameraTimers(float dt, const CFinalInput& input); + void UpdateMorphBallState(float dt, const CFinalInput&, CStateManager& mgr); + CFirstPersonCamera& GetFirstPersonCamera(CStateManager& mgr); + void UpdateGunTransform(const zeus::CVector3f&, CStateManager& mgr); + void UpdateAssistedAiming(const zeus::CTransform& xf, const CStateManager& mgr); + void UpdateAimTargetPrediction(const zeus::CTransform& xf, const CStateManager& mgr); + void ResetAimTargetPrediction(TUniqueId target); + void DrawGun(CStateManager& mgr); + void HolsterGun(CStateManager& mgr); + EPlayerCameraState GetCameraState() const { return x2f4_cameraState; } + EPlayerMorphBallState GetMorphballTransitionState() const { return x2f8_morphBallState; } + EGunHolsterState GetGunHolsterState() const { return x498_gunHolsterState; } + EPlayerMovementState GetPlayerMovementState() const { return x258_movementState; } + bool IsMorphBallTransitioning() const; + void UpdateGrappleArmTransform(const zeus::CVector3f&, CStateManager& mgr, float); + float GetGravity() const; + void ApplyGrappleForces(const CFinalInput& input, CStateManager& mgr, float); + bool ValidateFPPosition(const zeus::CVector3f& pos, CStateManager& mgr); + void UpdateGrappleState(const CFinalInput& input, CStateManager& mgr); + void ApplyGrappleJump(CStateManager& mgr); + void BeginGrapple(zeus::CVector3f&, CStateManager& mgr); + void BreakGrapple(EPlayerOrbitRequest, CStateManager& mgr); + void SetOrbitRequest(EPlayerOrbitRequest req, CStateManager& mgr); + void SetOrbitRequestForTarget(TUniqueId id, EPlayerOrbitRequest req, CStateManager& mgr); + bool InGrappleJumpCooldown() const; + void PreventFallingCameraPitch(); + void OrbitCarcass(CStateManager&); + void OrbitPoint(EPlayerOrbitType, CStateManager& mgr); + zeus::CVector3f GetHUDOrbitTargetPosition() const; + void SetOrbitState(EPlayerOrbitState, CStateManager& mgr); + void SetOrbitTargetId(TUniqueId, CStateManager& mgr); + void UpdateOrbitPosition(float, CStateManager& mgr); + void UpdateOrbitZPosition(); + void UpdateOrbitFixedPosition(); + void SetOrbitPosition(float, CStateManager& mgr); + void UpdateAimTarget(CStateManager& mgr); + void UpdateAimTargetTimer(float); + bool ValidateAimTargetId(TUniqueId, CStateManager& mgr); + bool ValidateObjectForMode(TUniqueId, CStateManager& mgr) const; + TUniqueId FindAimTargetId(CStateManager& mgr); + TUniqueId GetAimTarget() const { return x3f4_aimTarget; } + TUniqueId CheckEnemiesAgainstOrbitZone(const rstl::reserved_vector&, EPlayerZoneInfo, + EPlayerZoneType, CStateManager& mgr) const; + TUniqueId FindOrbitTargetId(CStateManager& mgr); + void UpdateOrbitableObjects(CStateManager& mgr); + TUniqueId FindBestOrbitableObject(const std::vector&, EPlayerZoneInfo, CStateManager& mgr) const; + void FindOrbitableObjects(const rstl::reserved_vector&, std::vector&, EPlayerZoneInfo, + EPlayerZoneType, CStateManager& mgr, bool) const; + bool WithinOrbitScreenBox(const zeus::CVector3f&, EPlayerZoneInfo, EPlayerZoneType) const; + bool WithinOrbitScreenEllipse(const zeus::CVector3f&, EPlayerZoneInfo) const; + bool CheckOrbitDisableSourceList(CStateManager& mgr); + bool CheckOrbitDisableSourceList() const { return !x9e4_orbitDisableList.empty(); } + void RemoveOrbitDisableSource(TUniqueId); + void AddOrbitDisableSource(CStateManager& mgr, TUniqueId); + void UpdateOrbitPreventionTimer(float); + void UpdateOrbitModeTimer(float); + void UpdateOrbitZone(CStateManager& mgr); + void UpdateOrbitInput(const CFinalInput& input, CStateManager& mgr); + void ActivateOrbitSource(CStateManager& mgr); + void UpdateOrbitSelection(const CFinalInput& input, CStateManager& mgr); + void UpdateOrbitOrientation(CStateManager& mgr); + void UpdateOrbitTarget(CStateManager& mgr); + float GetOrbitMaxLockDistance(CStateManager& mgr) const; + float GetOrbitMaxTargetDistance(CStateManager& mgr) const; + EOrbitValidationResult ValidateOrbitTargetId(TUniqueId uid, CStateManager& mgr) const; + EOrbitValidationResult ValidateCurrentOrbitTargetId(CStateManager& mgr); + bool ValidateOrbitTargetIdAndPointer(TUniqueId, CStateManager& mgr) const; + zeus::CVector3f GetBallPosition() const; + zeus::CVector3f GetEyePosition() const; + float GetEyeHeight() const; + float GetUnbiasedEyeHeight() const; + float GetStepUpHeight() const; + float GetStepDownHeight() const; + void Teleport(const zeus::CTransform& xf, CStateManager& mgr, bool resetBallCam); + void BombJump(const zeus::CVector3f& pos, CStateManager& mgr); + zeus::CTransform CreateTransformFromMovementDirection() const; + const CCollisionPrimitive* GetCollisionPrimitive() const; + const CCollidableSphere* GetCollidableSphere() const; + zeus::CTransform GetPrimitiveTransform() const; + void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr); + float GetBallMaxVelocity() const; + float GetActualBallMaxVelocity(float dt) const; + float GetActualFirstPersonMaxVelocity(float dt) const; + void SetMoveState(EPlayerMovementState, CStateManager& mgr); + float JumpInput(const CFinalInput& input, CStateManager& mgr); + float TurnInput(const CFinalInput& input) const; + float StrafeInput(const CFinalInput& input) const; + float ForwardInput(const CFinalInput& input, float) const; + zeus::CVector3f CalculateLeftStickEdgePosition(float strafeInput, float forwardInput) const; + bool SidewaysDashAllowed(float strafeInput, float forwardInput, const CFinalInput& input, CStateManager& mgr) const; + void FinishSidewaysDash(); + void ComputeDash(const CFinalInput& input, float dt, CStateManager& mgr); + void ComputeMovement(const CFinalInput& input, CStateManager& mgr, float dt); + float GetWeight() const; + zeus::CVector3f GetDampedClampedVelocityWR() const; + const CVisorSteam& GetVisorSteam() const { return x7a0_visorSteam; } + float GetVisorStaticAlpha() const { return x74c_visorStaticAlpha; } + float GetGunAlpha() const { return x494_gunAlpha; } + const CScriptWater* GetVisorRunoffEffect(const CStateManager& mgr) const; + void SetMorphBallState(EPlayerMorphBallState state, CStateManager& mgr); + bool CanLeaveMorphBallState(CStateManager& mgr, zeus::CVector3f& pos) const; + void SetHudDisable(float staticTimer, float outSpeed, float inSpeed); + void SetIntoBallReadyAnimation(CStateManager& mgr); + void LeaveMorphBallState(CStateManager& mgr); + bool CanEnterMorphBallState(CStateManager& mgr, float f1) const; + void EnterMorphBallState(CStateManager& mgr); + void ActivateMorphBallCamera(CStateManager& mgr); + void UpdateCinematicState(CStateManager& mgr); + void SetCameraState(EPlayerCameraState camState, CStateManager& stateMgr); + bool IsEnergyLow(const CStateManager& mgr) const; + EPlayerOrbitState GetOrbitState() const { return x304_orbitState; } + EPlayerScanState GetScanningState() const { return x3a8_scanState; } + float GetScanningTime() const { return x3ac_scanningTime; } + TUniqueId GetOrbitTargetId() const { return x310_orbitTargetId; } + TUniqueId GetOrbitNextTargetId() const { return x33c_orbitNextTargetId; } + TUniqueId GetScanningObjectId() const { return x3b4_scanningObject; } + EGrappleState GetGrappleState() const { return x3b8_grappleState; } + bool IsNewScanScanning() const { return x9c6_30_newScanScanning; } + float GetThreatOverride() const { return xa1c_threatOverride; } + bool IsOverrideRadarRadius() const { return x9c6_31_overrideRadarRadius; } + float GetRadarXYRadiusOverride() const { return xa20_radarXYRadiusOverride; } + float GetRadarZRadiusOverride() const { return xa24_radarZRadiusOverride; } + bool ObjectInScanningRange(TUniqueId id, const CStateManager& mgr) const; + float GetMorphTime() const { return x574_morphTime; } + float GetMorphDuration() const { return x578_morphDuration; } + float GetMorphFactor() const { + if (0.f != x578_morphDuration) + return zeus::clamp(0.f, x574_morphTime / x578_morphDuration, 1.f); + return 0.f; + } + bool IsInFreeLook() const { return x3dc_inFreeLook; } + bool GetFreeLookStickState() const { return x3de_lookAnalogHeld; } + CPlayerGun* GetPlayerGun() const { return x490_gun.get(); } + CMorphBall* GetMorphBall() const { return x768_morphball.get(); } + CPlayerCameraBob* GetCameraBob() const { return x76c_cameraBob.get(); } + float GetStaticTimer() const { return x740_staticTimer; } + float GetDeathTime() const { return x9f4_deathTime; } + const CPlayerEnergyDrain& GetEnergyDrain() const { return x274_energyDrain; } + EPlayerZoneInfo GetOrbitZone() const { return x330_orbitZoneMode; } + EPlayerZoneType GetOrbitType() const { return x334_orbitType; } + const zeus::CTransform& GetFirstPersonCameraTransform(const CStateManager& mgr) const; + const std::vector& GetNearbyOrbitObjects() const { return x344_nearbyOrbitObjects; } + const std::vector& GetOnScreenOrbitObjects() const { return x354_onScreenOrbitObjects; } + const std::vector& GetOffScreenOrbitObjects() const { return x364_offScreenOrbitObjects; } + void SetPlayerHitWallDuringMove(); + ESurfaceRestraints GetCurrentSurfaceRestraint() const { return x2ac_surfaceRestraint; } + ESurfaceRestraints GetSurfaceRestraint() const { + return x2b0_outOfWaterTicks == 2 ? GetCurrentSurfaceRestraint() : ESurfaceRestraints::Water; + } + void DecrementPhazon(); + void IncrementPhazon(); + void ApplySubmergedPitchBend(CSfxHandle& sfx); + void DetachActorFromPlayer(); + bool AttachActorToPlayer(TUniqueId id, bool disableGun); + TUniqueId GetAttachedActor() const { return x26c_attachedActor; } + float GetAttachedActorStruggle() const { return xa28_attachedActorStruggle; } + float GetDistanceUnderWater() const { return x828_distanceUnderWater; } + TUniqueId GetRidingPlatformId() const { return x82e_ridingPlatform; } + const zeus::CVector3f& GetLastVelocity() const { return x794_lastVelocity; } + const zeus::CVector3f& GetMoveDir() const { return x50c_moveDir; } + const zeus::CVector3f& GetLeaveMorphDir() const { return x518_leaveMorphDir; } + u32 GetBombJumpCount() const { return x9d0_bombJumpCount; } + float GetMoveSpeed() const { return x4f8_moveSpeed; } + EPlayerOrbitRequest GetOrbitRequest() const { return x30c_orbitRequest; } + bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; } + bool IsSidewaysDashing() const { return x37c_sidewaysDashing; } + void Set_X590(bool b) { x590_ = b; } }; -} - +} // namespace urde diff --git a/Runtime/World/CPlayerCameraBob.cpp b/Runtime/World/CPlayerCameraBob.cpp index 9da1af986..4b2575f52 100644 --- a/Runtime/World/CPlayerCameraBob.cpp +++ b/Runtime/World/CPlayerCameraBob.cpp @@ -5,8 +5,7 @@ #include "zeus/Math.hpp" #include "Particle/CGenDescription.hpp" -namespace urde -{ +namespace urde { float CPlayerCameraBob::kCameraBobExtentX = 0.071f; float CPlayerCameraBob::kCameraBobExtentY = 0.142f; float CPlayerCameraBob::kCameraBobPeriod = 0.47f; @@ -27,37 +26,30 @@ const float CPlayerCameraBob::kLandingBobDamping2 = 4.f * std::sqrt(40.f); const float CPlayerCameraBob::kCameraDamping = 6.f * std::sqrt(80.f); CPlayerCameraBob::CPlayerCameraBob(ECameraBobType type, const zeus::CVector2f& vec, float bobPeriod) -: x0_type(type), x4_vec(vec), xc_bobPeriod(bobPeriod) -{ - std::fill(std::begin(x7c_wanderPoints), std::end(x7c_wanderPoints), zeus::CVector3f::skForward); +: x0_type(type), x4_vec(vec), xc_bobPeriod(bobPeriod) { + std::fill(std::begin(x7c_wanderPoints), std::end(x7c_wanderPoints), zeus::CVector3f::skForward); } zeus::CTransform CPlayerCameraBob::GetViewWanderTransform() const { return xd0_viewWanderXf; } -zeus::CVector3f CPlayerCameraBob::GetHelmetBobTranslation() const -{ - return {kHelmetBobMagnitude * x2c_cameraBobTransform.origin.x(), - kHelmetBobMagnitude * x2c_cameraBobTransform.origin.y(), - kHelmetBobMagnitude * (x2c_cameraBobTransform.origin.z() - x78_camTranslation)}; +zeus::CVector3f CPlayerCameraBob::GetHelmetBobTranslation() const { + return {kHelmetBobMagnitude * x2c_cameraBobTransform.origin.x(), + kHelmetBobMagnitude * x2c_cameraBobTransform.origin.y(), + kHelmetBobMagnitude * (x2c_cameraBobTransform.origin.z() - x78_camTranslation)}; } -zeus::CTransform CPlayerCameraBob::GetGunBobTransformation() const -{ - return zeus::CTransform::Translate((1.f + kGunBobMagnitude) * x2c_cameraBobTransform.origin); +zeus::CTransform CPlayerCameraBob::GetGunBobTransformation() const { + return zeus::CTransform::Translate((1.f + kGunBobMagnitude) * x2c_cameraBobTransform.origin); } zeus::CTransform CPlayerCameraBob::GetCameraBobTransformation() const { return x2c_cameraBobTransform; } -void CPlayerCameraBob::SetPlayerVelocity(const zeus::CVector3f& velocity) -{ - x5c_playerVelocity = velocity; - x68_playerPeakFallVel = zeus::min(x68_playerPeakFallVel, velocity.z()); +void CPlayerCameraBob::SetPlayerVelocity(const zeus::CVector3f& velocity) { + x5c_playerVelocity = velocity; + x68_playerPeakFallVel = zeus::min(x68_playerPeakFallVel, velocity.z()); } -void CPlayerCameraBob::SetBobMagnitude(float magnitude) -{ - x10_targetBobMagnitude = zeus::clamp(0.f, magnitude, 1.f); -} +void CPlayerCameraBob::SetBobMagnitude(float magnitude) { x10_targetBobMagnitude = zeus::clamp(0.f, magnitude, 1.f); } void CPlayerCameraBob::SetBobTimeScale(float ts) { x18_bobTimeScale = zeus::clamp(0.f, ts, 1.f); } @@ -65,190 +57,171 @@ void CPlayerCameraBob::ResetCameraBobTime() { x1c_bobTime = 0.f; } void CPlayerCameraBob::SetCameraBobTransform(const zeus::CTransform& xf) { x2c_cameraBobTransform = xf; } -void CPlayerCameraBob::SetState(CPlayerCameraBob::ECameraBobState state, CStateManager& mgr) -{ - if (x24_curState == state) - return; +void CPlayerCameraBob::SetState(CPlayerCameraBob::ECameraBobState state, CStateManager& mgr) { + if (x24_curState == state) + return; - x20_oldState = x24_curState; - x24_curState = state; - if (x20_oldState == ECameraBobState::InAir) - { - x28_applyLandingTrans = true; - x68_playerPeakFallVel = std::max(x68_playerPeakFallVel, -35.f); - x29_hardLand = x68_playerPeakFallVel < -30.f; - if (x29_hardLand) - x74_camVelocity += x68_playerPeakFallVel; - x6c_landingVelocity += x68_playerPeakFallVel; - x68_playerPeakFallVel = 0.f; - } + x20_oldState = x24_curState; + x24_curState = state; + if (x20_oldState == ECameraBobState::InAir) { + x28_applyLandingTrans = true; + x68_playerPeakFallVel = std::max(x68_playerPeakFallVel, -35.f); + x29_hardLand = x68_playerPeakFallVel < -30.f; + if (x29_hardLand) + x74_camVelocity += x68_playerPeakFallVel; + x6c_landingVelocity += x68_playerPeakFallVel; + x68_playerPeakFallVel = 0.f; + } - if (x24_curState == ECameraBobState::WalkNoBob && x100_wanderMagnitude != 0.f) - InitViewWander(mgr); + if (x24_curState == ECameraBobState::WalkNoBob && x100_wanderMagnitude != 0.f) + InitViewWander(mgr); } -void CPlayerCameraBob::InitViewWander(CStateManager& mgr) -{ - x7c_wanderPoints[0] = {0.f, 1.f, 0.f}; - x7c_wanderPoints[1] = x7c_wanderPoints[0]; - x7c_wanderPoints[2] = x7c_wanderPoints[0]; - x7c_wanderPoints[3] = CalculateRandomViewWanderPosition(mgr); - xb0_wanderPitches[0] = 0.f; - xb0_wanderPitches[1] = xb0_wanderPitches[0]; - xb0_wanderPitches[2] = xb0_wanderPitches[0]; - xb0_wanderPitches[3] = CalculateRandomViewWanderPitch(mgr); +void CPlayerCameraBob::InitViewWander(CStateManager& mgr) { + x7c_wanderPoints[0] = {0.f, 1.f, 0.f}; + x7c_wanderPoints[1] = x7c_wanderPoints[0]; + x7c_wanderPoints[2] = x7c_wanderPoints[0]; + x7c_wanderPoints[3] = CalculateRandomViewWanderPosition(mgr); + xb0_wanderPitches[0] = 0.f; + xb0_wanderPitches[1] = xb0_wanderPitches[0]; + xb0_wanderPitches[2] = xb0_wanderPitches[0]; + xb0_wanderPitches[3] = CalculateRandomViewWanderPitch(mgr); + xc8_viewWanderSpeed = (kViewWanderSpeedMax - kViewWanderRadius) * kViewWanderRadius + mgr.GetActiveRandom()->Float(); + xc4_wanderTime = 0.f; + xcc_wanderIndex = 0; +} + +void CPlayerCameraBob::UpdateViewWander(float dt, CStateManager& mgr) { + zeus::CVector3f pt = zeus::getCatmullRomSplinePoint( + x7c_wanderPoints[xcc_wanderIndex], x7c_wanderPoints[(xcc_wanderIndex + 1) & 3], + x7c_wanderPoints[(xcc_wanderIndex + 2) & 3], x7c_wanderPoints[(xcc_wanderIndex + 3) & 3], xc4_wanderTime); + + pt.x() *= x100_wanderMagnitude; + pt.z() *= x100_wanderMagnitude; + zeus::CTransform orient = zeus::CTransform::RotateY( + (zeus::getCatmullRomSplinePoint(xb0_wanderPitches[xcc_wanderIndex], xb0_wanderPitches[(xcc_wanderIndex + 1) & 3], + xb0_wanderPitches[(xcc_wanderIndex + 2) & 3], + xb0_wanderPitches[(xcc_wanderIndex + 3) & 3], xc4_wanderTime) * + x100_wanderMagnitude)); + xd0_viewWanderXf = zeus::lookAt(zeus::CVector3f::skZero, pt, zeus::CVector3f::skUp) * orient; + + xc4_wanderTime += xc8_viewWanderSpeed * dt; + if (xc4_wanderTime >= 1.f) { + x7c_wanderPoints[xcc_wanderIndex] = CalculateRandomViewWanderPosition(mgr); + xb0_wanderPitches[xcc_wanderIndex] = CalculateRandomViewWanderPitch(mgr); xc8_viewWanderSpeed = - (kViewWanderSpeedMax - kViewWanderRadius) * kViewWanderRadius + mgr.GetActiveRandom()->Float(); - xc4_wanderTime = 0.f; - xcc_wanderIndex = 0; + ((kViewWanderSpeedMax - kViewWanderSpeedMin) * kViewWanderSpeedMin) + mgr.GetActiveRandom()->Float(); + xcc_wanderIndex = (xcc_wanderIndex + 1) & 3; + xc4_wanderTime -= 1.f; + } } -void CPlayerCameraBob::UpdateViewWander(float dt, CStateManager& mgr) -{ - zeus::CVector3f pt = zeus::getCatmullRomSplinePoint( - x7c_wanderPoints[xcc_wanderIndex], x7c_wanderPoints[(xcc_wanderIndex + 1) & 3], - x7c_wanderPoints[(xcc_wanderIndex + 2) & 3], x7c_wanderPoints[(xcc_wanderIndex + 3) & 3], xc4_wanderTime); +void CPlayerCameraBob::Update(float dt, CStateManager& mgr) { + x1c_bobTime += dt * x18_bobTimeScale; - pt.x() *= x100_wanderMagnitude; - pt.z() *= x100_wanderMagnitude; - zeus::CTransform orient = zeus::CTransform::RotateY(( - zeus::getCatmullRomSplinePoint(xb0_wanderPitches[xcc_wanderIndex], xb0_wanderPitches[(xcc_wanderIndex + 1) & 3], - xb0_wanderPitches[(xcc_wanderIndex + 2) & 3], - xb0_wanderPitches[(xcc_wanderIndex + 3) & 3], xc4_wanderTime) * - x100_wanderMagnitude)); - xd0_viewWanderXf = zeus::lookAt(zeus::CVector3f::skZero, pt, zeus::CVector3f::skUp) * orient; - - xc4_wanderTime += xc8_viewWanderSpeed * dt; - if (xc4_wanderTime >= 1.f) - { - x7c_wanderPoints[xcc_wanderIndex] = CalculateRandomViewWanderPosition(mgr); - xb0_wanderPitches[xcc_wanderIndex] = CalculateRandomViewWanderPitch(mgr); - xc8_viewWanderSpeed = - ((kViewWanderSpeedMax - kViewWanderSpeedMin) * kViewWanderSpeedMin) + mgr.GetActiveRandom()->Float(); - xcc_wanderIndex = (xcc_wanderIndex + 1) & 3; - xc4_wanderTime -= 1.f; + if (x28_applyLandingTrans) { + float landDampen = kLandingBobDamping; + float landSpring = kLandingBobSpringConstant; + if (x29_hardLand) { + landDampen = kLandingBobDamping2; + landSpring = kLandingBobSpringConstant2; } + + x6c_landingVelocity += dt * (-(landDampen * x6c_landingVelocity) - landSpring * x70_landingTranslation); + x70_landingTranslation += x6c_landingVelocity * dt; + x74_camVelocity += dt * (-(kCameraDamping * x74_camVelocity) - 80.f * x78_camTranslation); + x78_camTranslation += x74_camVelocity * dt; + + if (std::fabs(x6c_landingVelocity) < 0.005f && std::fabs(x70_landingTranslation) < 0.005f && + std::fabs(x74_camVelocity) < 0.005f && std::fabs(x78_camTranslation) < 0.005f) { + x28_applyLandingTrans = false; + x70_landingTranslation = 0.f; + x78_camTranslation = 0.f; + } + } + + if (x24_curState == ECameraBobState::WalkNoBob) + x104_targetWanderMagnitude = 1.f; + else + x104_targetWanderMagnitude = 0.f; + + float mag = mgr.GetCameraManager()->GetCameraBobMagnitude(); + x70_landingTranslation *= mag; + x78_camTranslation *= mag; + x104_targetWanderMagnitude *= mag; + if (mgr.GetPlayer().x38c_doneSidewaysDashing) { + x70_landingTranslation *= 0.2f; + x78_camTranslation *= 0.2f; + x104_targetWanderMagnitude *= 0.2f; + } + + x100_wanderMagnitude += kTargetMagnitudeTrackingRate * (x104_targetWanderMagnitude - x100_wanderMagnitude); + x100_wanderMagnitude = std::max(x100_wanderMagnitude, 0.f); + x14_bobMagnitude += kTargetMagnitudeTrackingRate * (x10_targetBobMagnitude - x14_bobMagnitude); + UpdateViewWander(dt, mgr); + + x2c_cameraBobTransform = CalculateCameraBobTransformation() * GetViewWanderTransform() * + zeus::lookAt(zeus::CVector3f::skZero, {0.f, 2.f, x78_camTranslation}, zeus::CVector3f::skUp); } -void CPlayerCameraBob::Update(float dt, CStateManager& mgr) -{ - x1c_bobTime += dt * x18_bobTimeScale; +zeus::CVector3f CPlayerCameraBob::CalculateRandomViewWanderPosition(CStateManager& mgr) { + const float angle = (2.f * (M_PIF * mgr.GetActiveRandom()->Float())); + const float bias = kViewWanderRadius * mgr.GetActiveRandom()->Float(); + return {(bias * std::sin(angle)), 1.f, (bias * std::cos(angle))}; +} - if (x28_applyLandingTrans) - { - float landDampen = kLandingBobDamping; - float landSpring = kLandingBobSpringConstant; - if (x29_hardLand) - { - landDampen = kLandingBobDamping2; - landSpring = kLandingBobSpringConstant2; - } +float CPlayerCameraBob::CalculateRandomViewWanderPitch(CStateManager& mgr) { + return zeus::degToRad((2.f * (mgr.GetActiveRandom()->Float() - 0.5f)) * kViewWanderRollVariation); +} - x6c_landingVelocity += dt * (-(landDampen * x6c_landingVelocity) - landSpring * x70_landingTranslation); - x70_landingTranslation += x6c_landingVelocity * dt; - x74_camVelocity += dt * (-(kCameraDamping * x74_camVelocity) - 80.f * x78_camTranslation); - x78_camTranslation += x74_camVelocity * dt; - - if (std::fabs(x6c_landingVelocity) < 0.005f && std::fabs(x70_landingTranslation) < 0.005f && - std::fabs(x74_camVelocity) < 0.005f && std::fabs(x78_camTranslation) < 0.005f) - { - x28_applyLandingTrans = false; - x70_landingTranslation = 0.f; - x78_camTranslation = 0.f; - } - } - - if (x24_curState == ECameraBobState::WalkNoBob) - x104_targetWanderMagnitude = 1.f; +void CPlayerCameraBob::CalculateMovingTranslation(float& x, float& y) const { + if (x0_type == ECameraBobType::Zero) { + double c = ((M_PIF * 2.f) * std::fmod(x1c_bobTime, 2.0f * xc_bobPeriod) / xc_bobPeriod); + x = (x14_bobMagnitude * x4_vec.x()) * float(std::sin(c)); + y = (x14_bobMagnitude * x4_vec.y()) * float(std::fabs(std::cos(c * .5)) * std::cos(c * .5)); + } else if (x0_type == ECameraBobType::One) { + float fX = std::fmod(x1c_bobTime, 2.f * xc_bobPeriod); + if (fX > xc_bobPeriod) + x = (2.f - (fX / xc_bobPeriod)) * (x14_bobMagnitude * x4_vec.x()); else - x104_targetWanderMagnitude = 0.f; + x = ((fX / xc_bobPeriod)) * (x14_bobMagnitude * x4_vec.x()); - float mag = mgr.GetCameraManager()->GetCameraBobMagnitude(); - x70_landingTranslation *= mag; - x78_camTranslation *= mag; - x104_targetWanderMagnitude *= mag; - if (mgr.GetPlayer().x38c_doneSidewaysDashing) - { - x70_landingTranslation *= 0.2f; - x78_camTranslation *= 0.2f; - x104_targetWanderMagnitude *= 0.2f; - } - - x100_wanderMagnitude += kTargetMagnitudeTrackingRate * (x104_targetWanderMagnitude - x100_wanderMagnitude); - x100_wanderMagnitude = std::max(x100_wanderMagnitude, 0.f); - x14_bobMagnitude += kTargetMagnitudeTrackingRate * (x10_targetBobMagnitude - x14_bobMagnitude); - UpdateViewWander(dt, mgr); - - x2c_cameraBobTransform = CalculateCameraBobTransformation() * GetViewWanderTransform() * - zeus::lookAt(zeus::CVector3f::skZero, {0.f, 2.f, x78_camTranslation}, zeus::CVector3f::skUp); -} - -zeus::CVector3f CPlayerCameraBob::CalculateRandomViewWanderPosition(CStateManager& mgr) -{ - const float angle = (2.f * (M_PIF * mgr.GetActiveRandom()->Float())); - const float bias = kViewWanderRadius * mgr.GetActiveRandom()->Float(); - return {(bias * std::sin(angle)), 1.f, (bias * std::cos(angle))}; -} - -float CPlayerCameraBob::CalculateRandomViewWanderPitch(CStateManager& mgr) -{ - return zeus::degToRad((2.f * (mgr.GetActiveRandom()->Float() - 0.5f)) * kViewWanderRollVariation); -} - -void CPlayerCameraBob::CalculateMovingTranslation(float& x, float& y) const -{ - if (x0_type == ECameraBobType::Zero) - { - double c = ((M_PIF * 2.f) * std::fmod(x1c_bobTime, 2.0f * xc_bobPeriod) / xc_bobPeriod); - x = (x14_bobMagnitude * x4_vec.x()) * float(std::sin(c)); - y = (x14_bobMagnitude * x4_vec.y()) * float(std::fabs(std::cos(c * .5)) * std::cos(c * .5)); - } - else if (x0_type == ECameraBobType::One) - { - float fX = std::fmod(x1c_bobTime, 2.f * xc_bobPeriod); - if (fX > xc_bobPeriod) - x = (2.f - (fX / xc_bobPeriod)) * (x14_bobMagnitude * x4_vec.x()); - else - x = ((fX / xc_bobPeriod)) * (x14_bobMagnitude * x4_vec.x()); - - auto sY = float(std::sin(std::fmod((M_PI * fX) / xc_bobPeriod, M_PI))); - y = (1.f - sY) * (x14_bobMagnitude * x4_vec.y()) * 0.5f + - (0.5f * -((sY * sY) - 1.f) * (x14_bobMagnitude * x4_vec.y())); - } + auto sY = float(std::sin(std::fmod((M_PI * fX) / xc_bobPeriod, M_PI))); + y = (1.f - sY) * (x14_bobMagnitude * x4_vec.y()) * 0.5f + + (0.5f * -((sY * sY) - 1.f) * (x14_bobMagnitude * x4_vec.y())); + } } float CPlayerCameraBob::CalculateLandingTranslation() const { return x70_landingTranslation; } -zeus::CTransform CPlayerCameraBob::CalculateCameraBobTransformation() const -{ - float x = 0.f; - float y = 0.f; - CalculateMovingTranslation(x, y); - if (x28_applyLandingTrans) - y += CalculateLandingTranslation(); +zeus::CTransform CPlayerCameraBob::CalculateCameraBobTransformation() const { + float x = 0.f; + float y = 0.f; + CalculateMovingTranslation(x, y); + if (x28_applyLandingTrans) + y += CalculateLandingTranslation(); - return zeus::CTransform::Translate(x, 0.f, y); + return zeus::CTransform::Translate(x, 0.f, y); } -void CPlayerCameraBob::ReadTweaks(CInputStream& in) -{ - if (in.hasError()) - return; +void CPlayerCameraBob::ReadTweaks(CInputStream& in) { + if (in.hasError()) + return; - kCameraBobExtentX = in.readFloatBig(); - kCameraBobExtentY = in.readFloatBig(); - kCameraBobPeriod = in.readFloatBig(); - kOrbitBobScale = in.readFloatBig(); - kMaxOrbitBobScale = in.readFloatBig(); - kSlowSpeedPeriodScale = in.readFloatBig(); - kTargetMagnitudeTrackingRate = in.readFloatBig(); - kLandingBobSpringConstant = in.readFloatBig(); - kViewWanderRadius = in.readFloatBig(); - kViewWanderSpeedMin = in.readFloatBig(); - kViewWanderSpeedMax = in.readFloatBig(); - kViewWanderRollVariation = in.readFloatBig(); - kGunBobMagnitude = in.readFloatBig(); - kHelmetBobMagnitude = in.readFloatBig(); -} + kCameraBobExtentX = in.readFloatBig(); + kCameraBobExtentY = in.readFloatBig(); + kCameraBobPeriod = in.readFloatBig(); + kOrbitBobScale = in.readFloatBig(); + kMaxOrbitBobScale = in.readFloatBig(); + kSlowSpeedPeriodScale = in.readFloatBig(); + kTargetMagnitudeTrackingRate = in.readFloatBig(); + kLandingBobSpringConstant = in.readFloatBig(); + kViewWanderRadius = in.readFloatBig(); + kViewWanderSpeedMin = in.readFloatBig(); + kViewWanderSpeedMax = in.readFloatBig(); + kViewWanderRollVariation = in.readFloatBig(); + kGunBobMagnitude = in.readFloatBig(); + kHelmetBobMagnitude = in.readFloatBig(); } +} // namespace urde diff --git a/Runtime/World/CPlayerCameraBob.hpp b/Runtime/World/CPlayerCameraBob.hpp index c288fa1fa..a596ce8a5 100644 --- a/Runtime/World/CPlayerCameraBob.hpp +++ b/Runtime/World/CPlayerCameraBob.hpp @@ -5,101 +5,93 @@ #include "zeus/CVector2f.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class CPlayerCameraBob -{ +class CPlayerCameraBob { public: - enum class ECameraBobType - { - Zero, - One - }; + enum class ECameraBobType { Zero, One }; - enum class ECameraBobState - { - Walk, - Orbit, - InAir, - WalkNoBob, - GunFireNoBob, - TurningNoBob, - FreeLookNoBob, - GrappleNoBob, - Unspecified - }; + enum class ECameraBobState { + Walk, + Orbit, + InAir, + WalkNoBob, + GunFireNoBob, + TurningNoBob, + FreeLookNoBob, + GrappleNoBob, + Unspecified + }; - static float kCameraBobExtentX; - static float kCameraBobExtentY; - static float kCameraBobPeriod; - static float kOrbitBobScale; - static float kMaxOrbitBobScale; - static float kSlowSpeedPeriodScale; - static float kTargetMagnitudeTrackingRate; - static float kLandingBobSpringConstant; - static float kLandingBobSpringConstant2; - static float kViewWanderRadius; - static float kViewWanderSpeedMin; - static float kViewWanderSpeedMax; - static float kViewWanderRollVariation; - static float kGunBobMagnitude; - static float kHelmetBobMagnitude; - static const float kLandingBobDamping; - static const float kLandingBobDamping2; - static const float kCameraDamping; + static float kCameraBobExtentX; + static float kCameraBobExtentY; + static float kCameraBobPeriod; + static float kOrbitBobScale; + static float kMaxOrbitBobScale; + static float kSlowSpeedPeriodScale; + static float kTargetMagnitudeTrackingRate; + static float kLandingBobSpringConstant; + static float kLandingBobSpringConstant2; + static float kViewWanderRadius; + static float kViewWanderSpeedMin; + static float kViewWanderSpeedMax; + static float kViewWanderRollVariation; + static float kGunBobMagnitude; + static float kHelmetBobMagnitude; + static const float kLandingBobDamping; + static const float kLandingBobDamping2; + static const float kCameraDamping; private: - ECameraBobType x0_type; - zeus::CVector2f x4_vec; - float xc_bobPeriod; - float x10_targetBobMagnitude = 0.f; - float x14_bobMagnitude = 0.f; - float x18_bobTimeScale = 0.f; - float x1c_bobTime = 0.f; - ECameraBobState x20_oldState = ECameraBobState::Unspecified; - ECameraBobState x24_curState = ECameraBobState::Unspecified; - bool x28_applyLandingTrans = false; - bool x29_hardLand = false; - zeus::CTransform x2c_cameraBobTransform; - zeus::CVector3f x5c_playerVelocity; - float x68_playerPeakFallVel = 0.f; - float x6c_landingVelocity = 0.f; - float x70_landingTranslation = 0.f; - float x74_camVelocity = 0.f; - float x78_camTranslation = 0.f; - zeus::CVector3f x7c_wanderPoints[4]; - float xb0_wanderPitches[4] = {}; - float xc4_wanderTime = 0.f; - float xc8_viewWanderSpeed = kViewWanderSpeedMin; - u32 xcc_wanderIndex = 0; - zeus::CTransform xd0_viewWanderXf; - float x100_wanderMagnitude = FLT_EPSILON; - float x104_targetWanderMagnitude = 0.f; + ECameraBobType x0_type; + zeus::CVector2f x4_vec; + float xc_bobPeriod; + float x10_targetBobMagnitude = 0.f; + float x14_bobMagnitude = 0.f; + float x18_bobTimeScale = 0.f; + float x1c_bobTime = 0.f; + ECameraBobState x20_oldState = ECameraBobState::Unspecified; + ECameraBobState x24_curState = ECameraBobState::Unspecified; + bool x28_applyLandingTrans = false; + bool x29_hardLand = false; + zeus::CTransform x2c_cameraBobTransform; + zeus::CVector3f x5c_playerVelocity; + float x68_playerPeakFallVel = 0.f; + float x6c_landingVelocity = 0.f; + float x70_landingTranslation = 0.f; + float x74_camVelocity = 0.f; + float x78_camTranslation = 0.f; + zeus::CVector3f x7c_wanderPoints[4]; + float xb0_wanderPitches[4] = {}; + float xc4_wanderTime = 0.f; + float xc8_viewWanderSpeed = kViewWanderSpeedMin; + u32 xcc_wanderIndex = 0; + zeus::CTransform xd0_viewWanderXf; + float x100_wanderMagnitude = FLT_EPSILON; + float x104_targetWanderMagnitude = 0.f; public: - CPlayerCameraBob(ECameraBobType type, const zeus::CVector2f& vec, float bobPeriod); + CPlayerCameraBob(ECameraBobType type, const zeus::CVector2f& vec, float bobPeriod); - zeus::CTransform GetViewWanderTransform() const; - zeus::CVector3f GetHelmetBobTranslation() const; - zeus::CTransform GetGunBobTransformation() const; - zeus::CTransform GetCameraBobTransformation() const; - void SetPlayerVelocity(const zeus::CVector3f& velocity); - void SetBobMagnitude(float); - void SetBobTimeScale(float); - void ResetCameraBobTime(); - void SetCameraBobTransform(const zeus::CTransform&); - void SetState(ECameraBobState, CStateManager&); - void InitViewWander(CStateManager&); - void UpdateViewWander(float, CStateManager&); - void Update(float, CStateManager&); - zeus::CVector3f CalculateRandomViewWanderPosition(CStateManager&); - float CalculateRandomViewWanderPitch(CStateManager&); - void CalculateMovingTranslation(float& x, float& y) const; - float CalculateLandingTranslation() const; - zeus::CTransform CalculateCameraBobTransformation() const; - static void ReadTweaks(CInputStream& in); + zeus::CTransform GetViewWanderTransform() const; + zeus::CVector3f GetHelmetBobTranslation() const; + zeus::CTransform GetGunBobTransformation() const; + zeus::CTransform GetCameraBobTransformation() const; + void SetPlayerVelocity(const zeus::CVector3f& velocity); + void SetBobMagnitude(float); + void SetBobTimeScale(float); + void ResetCameraBobTime(); + void SetCameraBobTransform(const zeus::CTransform&); + void SetState(ECameraBobState, CStateManager&); + void InitViewWander(CStateManager&); + void UpdateViewWander(float, CStateManager&); + void Update(float, CStateManager&); + zeus::CVector3f CalculateRandomViewWanderPosition(CStateManager&); + float CalculateRandomViewWanderPitch(CStateManager&); + void CalculateMovingTranslation(float& x, float& y) const; + float CalculateLandingTranslation() const; + zeus::CTransform CalculateCameraBobTransformation() const; + static void ReadTweaks(CInputStream& in); }; -} - +} // namespace urde diff --git a/Runtime/World/CPlayerEnergyDrain.cpp b/Runtime/World/CPlayerEnergyDrain.cpp index d00402b0c..77300c3f6 100644 --- a/Runtime/World/CPlayerEnergyDrain.cpp +++ b/Runtime/World/CPlayerEnergyDrain.cpp @@ -1,44 +1,39 @@ #include "CPlayerEnergyDrain.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { CPlayerEnergyDrain::CPlayerEnergyDrain(u32 capacity) { x0_sources.reserve(capacity); } void CPlayerEnergyDrain::AddEnergyDrainSource(TUniqueId id, float intensity) { x0_sources.emplace_back(id, intensity); } -void CPlayerEnergyDrain::RemoveEnergyDrainSource(TUniqueId id) -{ - auto it = rstl::binary_find(x0_sources.begin(), x0_sources.end(), id, - [](const CEnergyDrainSource& item) {return item.GetEnergyDrainSourceId();}); - if (it != x0_sources.end()) - x0_sources.erase(it); +void CPlayerEnergyDrain::RemoveEnergyDrainSource(TUniqueId id) { + auto it = rstl::binary_find(x0_sources.begin(), x0_sources.end(), id, + [](const CEnergyDrainSource& item) { return item.GetEnergyDrainSourceId(); }); + if (it != x0_sources.end()) + x0_sources.erase(it); } -float CPlayerEnergyDrain::GetEnergyDrainIntensity() const -{ - float intensity = 0.f; +float CPlayerEnergyDrain::GetEnergyDrainIntensity() const { + float intensity = 0.f; - for (const CEnergyDrainSource& src : x0_sources) - intensity += src.GetEnergyDrainIntensity(); + for (const CEnergyDrainSource& src : x0_sources) + intensity += src.GetEnergyDrainIntensity(); - return intensity; + return intensity; } -void CPlayerEnergyDrain::ProcessEnergyDrain(const CStateManager& mgr, float dt) -{ - auto it = x0_sources.begin(); +void CPlayerEnergyDrain::ProcessEnergyDrain(const CStateManager& mgr, float dt) { + auto it = x0_sources.begin(); - for (; it != x0_sources.end(); ++it) - { - if (mgr.GetObjectById((*it).GetEnergyDrainSourceId()) == nullptr) - RemoveEnergyDrainSource((*it).GetEnergyDrainSourceId()); - } + for (; it != x0_sources.end(); ++it) { + if (mgr.GetObjectById((*it).GetEnergyDrainSourceId()) == nullptr) + RemoveEnergyDrainSource((*it).GetEnergyDrainSourceId()); + } - if (x0_sources.empty()) - x10_energyDrainTime = 0.f; - else - x10_energyDrainTime += dt; -} + if (x0_sources.empty()) + x10_energyDrainTime = 0.f; + else + x10_energyDrainTime += dt; } +} // namespace urde diff --git a/Runtime/World/CPlayerEnergyDrain.hpp b/Runtime/World/CPlayerEnergyDrain.hpp index bb03ed231..55fe5a562 100644 --- a/Runtime/World/CPlayerEnergyDrain.hpp +++ b/Runtime/World/CPlayerEnergyDrain.hpp @@ -3,21 +3,19 @@ #include "RetroTypes.hpp" #include "CEnergyDrainSource.hpp" -namespace urde -{ +namespace urde { class CStateManager; -class CPlayerEnergyDrain -{ - std::vector x0_sources; - float x10_energyDrainTime; +class CPlayerEnergyDrain { + std::vector x0_sources; + float x10_energyDrainTime; public: - CPlayerEnergyDrain(u32); - const std::vector& GetEnergyDrainSources() const { return x0_sources; } - void AddEnergyDrainSource(TUniqueId, float); - void RemoveEnergyDrainSource(TUniqueId id); - float GetEnergyDrainIntensity() const; - float GetEnergyDrainTime() const { return x10_energyDrainTime; } - void ProcessEnergyDrain(const CStateManager&, float); + CPlayerEnergyDrain(u32); + const std::vector& GetEnergyDrainSources() const { return x0_sources; } + void AddEnergyDrainSource(TUniqueId, float); + void RemoveEnergyDrainSource(TUniqueId id); + float GetEnergyDrainIntensity() const; + float GetEnergyDrainTime() const { return x10_energyDrainTime; } + void ProcessEnergyDrain(const CStateManager&, float); }; -} +} // namespace urde diff --git a/Runtime/World/CProjectedShadow.cpp b/Runtime/World/CProjectedShadow.cpp index 3771a84ce..43a7dd53a 100644 --- a/Runtime/World/CProjectedShadow.cpp +++ b/Runtime/World/CProjectedShadow.cpp @@ -1,27 +1,14 @@ #include "World/CProjectedShadow.hpp" -namespace urde -{ +namespace urde { CProjectedShadow::CProjectedShadow(u32 w, u32 h, bool persistent) - : x0_texture(CTexture(ETexelFormat::I4, w, h, 1)) - , x81_persistent(persistent) -{ -} +: x0_texture(CTexture(ETexelFormat::I4, w, h, 1)), x81_persistent(persistent) {} -zeus::CAABox CProjectedShadow::CalculateRenderBounds() -{ - return {}; -} +zeus::CAABox CProjectedShadow::CalculateRenderBounds() { return {}; } -void CProjectedShadow::Render(const CStateManager& mgr) -{ +void CProjectedShadow::Render(const CStateManager& mgr) {} -} - -void CProjectedShadow::RenderShadowBuffer(const CStateManager&, const CModelData&, - const zeus::CTransform&, s32, - const zeus::CVector3f&, float, float) -{ -} -} +void CProjectedShadow::RenderShadowBuffer(const CStateManager&, const CModelData&, const zeus::CTransform&, s32, + const zeus::CVector3f&, float, float) {} +} // namespace urde diff --git a/Runtime/World/CProjectedShadow.hpp b/Runtime/World/CProjectedShadow.hpp index b06c1fd62..8ae3bcf22 100644 --- a/Runtime/World/CProjectedShadow.hpp +++ b/Runtime/World/CProjectedShadow.hpp @@ -4,29 +4,26 @@ #include "zeus/CTransform.hpp" #include "zeus/CAABox.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CModelData; -class CProjectedShadow -{ - CTexture x0_texture; - zeus::CAABox x68_ = zeus::CAABox::skInvertedBox; - bool x80_; - bool x81_persistent; - float x84_ = 1.f; - zeus::CVector3f x88_ = zeus::CVector3f::skZero; - float x94_zDistanceAdjust = 0.f; - float x98_ = 1.f; +class CProjectedShadow { + CTexture x0_texture; + zeus::CAABox x68_ = zeus::CAABox::skInvertedBox; + bool x80_; + bool x81_persistent; + float x84_ = 1.f; + zeus::CVector3f x88_ = zeus::CVector3f::skZero; + float x94_zDistanceAdjust = 0.f; + float x98_ = 1.f; public: - CProjectedShadow() = default; - CProjectedShadow(u32, u32, bool); + CProjectedShadow() = default; + CProjectedShadow(u32, u32, bool); - zeus::CAABox CalculateRenderBounds(); - void Render(const CStateManager& mgr); - void RenderShadowBuffer(const CStateManager&, const CModelData&, - const zeus::CTransform&, s32, - const zeus::CVector3f&, float, float); + zeus::CAABox CalculateRenderBounds(); + void Render(const CStateManager& mgr); + void RenderShadowBuffer(const CStateManager&, const CModelData&, const zeus::CTransform&, s32, const zeus::CVector3f&, + float, float); }; -} +} // namespace urde diff --git a/Runtime/World/CRepulsor.cpp b/Runtime/World/CRepulsor.cpp index 0e908d9de..49f65c5c5 100644 --- a/Runtime/World/CRepulsor.cpp +++ b/Runtime/World/CRepulsor.cpp @@ -2,23 +2,16 @@ #include "CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CRepulsor::CRepulsor(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, float radius) : CActor(uid, active, name, info, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(), CMaterialList(), CActorParameters::None(), kInvalidUniqueId) -, xe8_affectRadius(radius) -{ -} +, xe8_affectRadius(radius) {} -void CRepulsor::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CRepulsor::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CRepulsor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CActor::AcceptScriptMsg(msg, objId, stateMgr); -} +void CRepulsor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CActor::AcceptScriptMsg(msg, objId, stateMgr); } +} // namespace urde diff --git a/Runtime/World/CRepulsor.hpp b/Runtime/World/CRepulsor.hpp index f8025d116..e17f5e238 100644 --- a/Runtime/World/CRepulsor.hpp +++ b/Runtime/World/CRepulsor.hpp @@ -1,18 +1,16 @@ #pragma once #include "CActor.hpp" -namespace urde -{ -class CRepulsor : public CActor -{ - float xe8_affectRadius; +namespace urde { +class CRepulsor : public CActor { + float xe8_affectRadius; public: - CRepulsor(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, float); + CRepulsor(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, float); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - float GetAffectRadius() const { return xe8_affectRadius; } + float GetAffectRadius() const { return xe8_affectRadius; } }; -} +} // namespace urde diff --git a/Runtime/World/CRipple.cpp b/Runtime/World/CRipple.cpp index b6e3f5c39..e2636bf91 100644 --- a/Runtime/World/CRipple.cpp +++ b/Runtime/World/CRipple.cpp @@ -1,28 +1,23 @@ #include "CRipple.hpp" #include "CRandom16.hpp" -namespace urde -{ +namespace urde { static CRandom16 sRippleRandom(0xABBA); -CRipple::CRipple(TUniqueId id, const zeus::CVector3f& center, float intensity) -: x0_id(id), x8_center(center) -{ - if (intensity >= 0.f && intensity <= 1.f) - { - float tmp = - 2.f * std::min(1.f, std::max(0.f, intensity * (sRippleRandom.Float() - 0.5f) * 2.f * 0.1f + intensity)); - x14_timeFalloff = 0.5f * tmp + 1.5f; - x18_distFalloff = 4.f * tmp + 8.f; - x1c_frequency = 2.f + tmp; - x20_amplitude = 0.15f * tmp + 0.1f; - x24_lookupAmplitude = x20_amplitude / 255.f; - } +CRipple::CRipple(TUniqueId id, const zeus::CVector3f& center, float intensity) : x0_id(id), x8_center(center) { + if (intensity >= 0.f && intensity <= 1.f) { + float tmp = 2.f * std::min(1.f, std::max(0.f, intensity * (sRippleRandom.Float() - 0.5f) * 2.f * 0.1f + intensity)); + x14_timeFalloff = 0.5f * tmp + 1.5f; + x18_distFalloff = 4.f * tmp + 8.f; + x1c_frequency = 2.f + tmp; + x20_amplitude = 0.15f * tmp + 0.1f; + x24_lookupAmplitude = x20_amplitude / 255.f; + } - x28_ooTimeFalloff = 1.f / x14_timeFalloff; - x2c_ooDistFalloff = 1.f / x18_distFalloff; - x30_ooPhase = x18_distFalloff / 2.5f; - x34_phase = 1.f / x30_ooPhase; - x38_lookupPhase = 256.f * x34_phase; -} + x28_ooTimeFalloff = 1.f / x14_timeFalloff; + x2c_ooDistFalloff = 1.f / x18_distFalloff; + x30_ooPhase = x18_distFalloff / 2.5f; + x34_phase = 1.f / x30_ooPhase; + x38_lookupPhase = 256.f * x34_phase; } +} // namespace urde diff --git a/Runtime/World/CRipple.hpp b/Runtime/World/CRipple.hpp index 593329e11..70daf611c 100644 --- a/Runtime/World/CRipple.hpp +++ b/Runtime/World/CRipple.hpp @@ -3,41 +3,39 @@ #include "RetroTypes.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ -class CRipple -{ +namespace urde { +class CRipple { private: - TUniqueId x0_id; - float x4_time = 0.f; - zeus::CVector3f x8_center; - float x14_timeFalloff = 2.f; - float x18_distFalloff = 12.f; - float x1c_frequency = 3.f; - float x20_amplitude = 0.25f; - float x24_lookupAmplitude = 0.00098039221f; - float x28_ooTimeFalloff = 0.f; - float x2c_ooDistFalloff = 0.f; - float x30_ooPhase = 0.f; - float x34_phase = 0.f; - float x38_lookupPhase = 0.f; - u32 x3c_ = 0; + TUniqueId x0_id; + float x4_time = 0.f; + zeus::CVector3f x8_center; + float x14_timeFalloff = 2.f; + float x18_distFalloff = 12.f; + float x1c_frequency = 3.f; + float x20_amplitude = 0.25f; + float x24_lookupAmplitude = 0.00098039221f; + float x28_ooTimeFalloff = 0.f; + float x2c_ooDistFalloff = 0.f; + float x30_ooPhase = 0.f; + float x34_phase = 0.f; + float x38_lookupPhase = 0.f; + u32 x3c_ = 0; public: - CRipple(TUniqueId id, const zeus::CVector3f& center, float intensity); + CRipple(TUniqueId id, const zeus::CVector3f& center, float intensity); - void SetTime(float t) { x4_time = t; } - float GetTime() const { return x4_time; } - float GetTimeFalloff() const { return x14_timeFalloff; } - TUniqueId GetUniqueId() const { return x0_id; } - float GetFrequency() const { return x1c_frequency; } - float GetAmplitude() const { return x20_amplitude; } - float GetLookupAmplitude() const { return x24_lookupAmplitude; } - float GetOODistanceFalloff() const { return x2c_ooDistFalloff; } - float GetDistanceFalloff() const { return x18_distFalloff; } - const zeus::CVector3f& GetCenter() const { return x8_center; } - float GetOOTimeFalloff() const { return x28_ooTimeFalloff; } - float GetPhase() const { return x34_phase; } - float GetLookupPhase() const { return x38_lookupPhase; } + void SetTime(float t) { x4_time = t; } + float GetTime() const { return x4_time; } + float GetTimeFalloff() const { return x14_timeFalloff; } + TUniqueId GetUniqueId() const { return x0_id; } + float GetFrequency() const { return x1c_frequency; } + float GetAmplitude() const { return x20_amplitude; } + float GetLookupAmplitude() const { return x24_lookupAmplitude; } + float GetOODistanceFalloff() const { return x2c_ooDistFalloff; } + float GetDistanceFalloff() const { return x18_distFalloff; } + const zeus::CVector3f& GetCenter() const { return x8_center; } + float GetOOTimeFalloff() const { return x28_ooTimeFalloff; } + float GetPhase() const { return x34_phase; } + float GetLookupPhase() const { return x38_lookupPhase; } }; -} +} // namespace urde diff --git a/Runtime/World/CRippleManager.cpp b/Runtime/World/CRippleManager.cpp index bf5608034..46a502d65 100644 --- a/Runtime/World/CRippleManager.cpp +++ b/Runtime/World/CRippleManager.cpp @@ -1,57 +1,45 @@ #include "CRippleManager.hpp" -namespace urde -{ +namespace urde { -CRippleManager::CRippleManager(int maxRipples, float alpha) -: x14_alpha(alpha) -{ - Init(maxRipples); +CRippleManager::CRippleManager(int maxRipples, float alpha) : x14_alpha(alpha) { Init(maxRipples); } + +void CRippleManager::Init(int maxRipples) { + x4_ripples.resize(maxRipples, CRipple(kInvalidUniqueId, zeus::CVector3f::skZero, 0.f)); + for (CRipple& r : x4_ripples) + r.SetTime(9999.f); } -void CRippleManager::Init(int maxRipples) -{ - x4_ripples.resize(maxRipples, CRipple(kInvalidUniqueId, zeus::CVector3f::skZero, 0.f)); - for (CRipple& r : x4_ripples) - r.SetTime(9999.f); +void CRippleManager::Update(float dt) { + for (CRipple& ripple : x4_ripples) { + ripple.SetTime(ripple.GetTime() + dt); + if (ripple.GetTime() > 9999.f) + ripple.SetTime(9999.f); + } } -void CRippleManager::Update(float dt) -{ - for (CRipple& ripple : x4_ripples) - { - ripple.SetTime(ripple.GetTime() + dt); - if (ripple.GetTime() > 9999.f) - ripple.SetTime(9999.f); +float CRippleManager::GetLastRippleDeltaTime(TUniqueId rippler) const { + float res = 9999.f; + for (const CRipple& r : x4_ripples) + if (r.GetUniqueId() == rippler) + if (r.GetTime() < res) + res = r.GetTime(); + return res; +} + +void CRippleManager::AddRipple(const CRipple& ripple) { + float maxTime = 0.f; + auto oldestRipple = x4_ripples.end(); + for (auto it = x4_ripples.begin(); it != x4_ripples.end(); ++it) + if (it->GetTime() > maxTime) { + oldestRipple = it; + maxTime = it->GetTime(); } + + if (oldestRipple != x4_ripples.end()) { + *oldestRipple = ripple; + x0_maxTimeFalloff = std::max(x0_maxTimeFalloff, ripple.GetTimeFalloff()); + } } -float CRippleManager::GetLastRippleDeltaTime(TUniqueId rippler) const -{ - float res = 9999.f; - for (const CRipple& r : x4_ripples) - if (r.GetUniqueId() == rippler) - if (r.GetTime() < res) - res = r.GetTime(); - return res; -} - -void CRippleManager::AddRipple(const CRipple& ripple) -{ - float maxTime = 0.f; - auto oldestRipple = x4_ripples.end(); - for (auto it = x4_ripples.begin() ; it != x4_ripples.end() ; ++it) - if (it->GetTime() > maxTime) - { - oldestRipple = it; - maxTime = it->GetTime(); - } - - if (oldestRipple != x4_ripples.end()) - { - *oldestRipple = ripple; - x0_maxTimeFalloff = std::max(x0_maxTimeFalloff, ripple.GetTimeFalloff()); - } -} - -} +} // namespace urde diff --git a/Runtime/World/CRippleManager.hpp b/Runtime/World/CRippleManager.hpp index 048972772..9c970b03d 100644 --- a/Runtime/World/CRippleManager.hpp +++ b/Runtime/World/CRippleManager.hpp @@ -3,27 +3,25 @@ #include "RetroTypes.hpp" #include "CRipple.hpp" -namespace urde -{ +namespace urde { + +class CRippleManager { + float x0_maxTimeFalloff = 0.f; + std::vector x4_ripples; + float x14_alpha; -class CRippleManager -{ - float x0_maxTimeFalloff = 0.f; - std::vector x4_ripples; - float x14_alpha; public: - CRippleManager(int maxRipples, float alpha); - void Init(int maxRipples); - std::vector& Ripples() { return x4_ripples; } - const std::vector& GetRipples() const { return x4_ripples; } - void Update(float dt); - float GetLastRippleDeltaTime(TUniqueId rippler) const; - void AddRipple(const CRipple& ripple); - void SetMaxTimeFalloff(float time) { x0_maxTimeFalloff = time; } - float GetMaxTimeFalloff() const { return x0_maxTimeFalloff; } - void SetAlpha(float a) { x14_alpha = a; } - float GetAlpha() const { return x14_alpha; } + CRippleManager(int maxRipples, float alpha); + void Init(int maxRipples); + std::vector& Ripples() { return x4_ripples; } + const std::vector& GetRipples() const { return x4_ripples; } + void Update(float dt); + float GetLastRippleDeltaTime(TUniqueId rippler) const; + void AddRipple(const CRipple& ripple); + void SetMaxTimeFalloff(float time) { x0_maxTimeFalloff = time; } + float GetMaxTimeFalloff() const { return x0_maxTimeFalloff; } + void SetAlpha(float a) { x14_alpha = a; } + float GetAlpha() const { return x14_alpha; } }; -} -; +}; // namespace urde diff --git a/Runtime/World/CScannableParameters.hpp b/Runtime/World/CScannableParameters.hpp index ace276fa7..e2fa4261d 100644 --- a/Runtime/World/CScannableParameters.hpp +++ b/Runtime/World/CScannableParameters.hpp @@ -2,17 +2,14 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -class CScannableParameters -{ - CAssetId x0_scanId; +class CScannableParameters { + CAssetId x0_scanId; public: - CScannableParameters() = default; - CScannableParameters(CAssetId id) : x0_scanId(id) {} - CAssetId GetScanId() const { return x0_scanId; } + CScannableParameters() = default; + CScannableParameters(CAssetId id) : x0_scanId(id) {} + CAssetId GetScanId() const { return x0_scanId; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptActor.cpp b/Runtime/World/CScriptActor.cpp index a85392add..19dae5dcf 100644 --- a/Runtime/World/CScriptActor.cpp +++ b/Runtime/World/CScriptActor.cpp @@ -9,8 +9,7 @@ #include "TCastTo.hpp" #include "CActorParameters.hpp" -namespace urde -{ +namespace urde { CScriptActor::CScriptActor(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& aabb, float mass, float zMomentum, @@ -24,191 +23,166 @@ CScriptActor::CScriptActor(TUniqueId uid, std::string_view name, const CEntityIn , x2d0_fadeInTime(actParms.x5c_fadeInTime) , x2d4_fadeOutTime(actParms.x60_fadeOutTime) , x2d8_shaderIdx(shaderIdx) -, x2dc_xrayAlpha(xrayAlpha) -{ - x2e2_24_noThermalHotZ = noThermalHotZ; - x2e2_25_dead = false; - x2e2_26_animating = true; - x2e2_27_xrayAlphaEnabled = !zeus::close_enough(1.f, xrayAlpha); - x2e2_28_inXrayAlpha = false; - x2e2_29_processModelFlags = (x2e2_27_xrayAlphaEnabled || x2e2_24_noThermalHotZ || x2d8_shaderIdx != 0); - x2e2_30_scaleAdvancementDelta = scaleAdvancementDelta; - x2e2_31_materialFlag54 = materialFlag54; - x2e3_24_isPlayerActor = false; +, x2dc_xrayAlpha(xrayAlpha) { + x2e2_24_noThermalHotZ = noThermalHotZ; + x2e2_25_dead = false; + x2e2_26_animating = true; + x2e2_27_xrayAlphaEnabled = !zeus::close_enough(1.f, xrayAlpha); + x2e2_28_inXrayAlpha = false; + x2e2_29_processModelFlags = (x2e2_27_xrayAlphaEnabled || x2e2_24_noThermalHotZ || x2d8_shaderIdx != 0); + x2e2_30_scaleAdvancementDelta = scaleAdvancementDelta; + x2e2_31_materialFlag54 = materialFlag54; + x2e3_24_isPlayerActor = false; - if (x64_modelData && (x64_modelData->HasAnimData() || x64_modelData->HasNormalModel()) && castsShadow) - CreateShadow(true); + if (x64_modelData && (x64_modelData->HasAnimData() || x64_modelData->HasNormalModel()) && castsShadow) + CreateShadow(true); - if (x64_modelData && x64_modelData->HasAnimData()) - x64_modelData->EnableLooping(looping); + if (x64_modelData && x64_modelData->HasAnimData()) + x64_modelData->EnableLooping(looping); - x150_momentum = zeus::CVector3f(0.f, 0.f, zMomentum); + x150_momentum = zeus::CVector3f(0.f, 0.f, zMomentum); } void CScriptActor::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::InitializedInArea: - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::InheritBounds || conn.x4_msg != EScriptObjectMessage::Activate) - continue; +void CScriptActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::InitializedInArea: + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::InheritBounds || conn.x4_msg != EScriptObjectMessage::Activate) + continue; - auto search = mgr.GetIdListForScript(conn.x8_objId); - for (auto it = search.first; it != search.second; ++it) - { - if (TCastToConstPtr(mgr.GetObjectById(it->second))) - { - x2e0_triggerId = it->second; - break; - } - } + auto search = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) { + if (TCastToConstPtr(mgr.GetObjectById(it->second))) { + x2e0_triggerId = it->second; + break; } - - if (x2e2_31_materialFlag54) - CActor::AddMaterial(EMaterialTypes::Unknown54, mgr); - break; - case EScriptObjectMessage::Reset: - x2e2_25_dead = false; - x260_currentHealth = x258_initialHealth; - break; - case EScriptObjectMessage::Increment: - if (!GetActive()) - { - mgr.SendScriptMsg(this, x8_uid, EScriptObjectMessage::Activate); - CScriptColorModulate::FadeInHelper(mgr, x8_uid, x2d0_fadeInTime); - } - break; - case EScriptObjectMessage::Decrement: - CScriptColorModulate::FadeOutHelper(mgr, x8_uid, x2d4_fadeOutTime); - break; - default: - break; + } } - CActor::AcceptScriptMsg(msg, uid, mgr); + if (x2e2_31_materialFlag54) + CActor::AddMaterial(EMaterialTypes::Unknown54, mgr); + break; + case EScriptObjectMessage::Reset: + x2e2_25_dead = false; + x260_currentHealth = x258_initialHealth; + break; + case EScriptObjectMessage::Increment: + if (!GetActive()) { + mgr.SendScriptMsg(this, x8_uid, EScriptObjectMessage::Activate); + CScriptColorModulate::FadeInHelper(mgr, x8_uid, x2d0_fadeInTime); + } + break; + case EScriptObjectMessage::Decrement: + CScriptColorModulate::FadeOutHelper(mgr, x8_uid, x2d4_fadeOutTime); + break; + default: + break; + } + + CActor::AcceptScriptMsg(msg, uid, mgr); } -void CScriptActor::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; +void CScriptActor::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; - if (HasModelData() && x64_modelData->HasAnimData()) - { - bool timeRemaining = x64_modelData->GetAnimationData()->IsAnimTimeRemaining(dt - FLT_EPSILON, "Whole Body"); - bool loop = x64_modelData->GetIsLoop(); + if (HasModelData() && x64_modelData->HasAnimData()) { + bool timeRemaining = x64_modelData->GetAnimationData()->IsAnimTimeRemaining(dt - FLT_EPSILON, "Whole Body"); + bool loop = x64_modelData->GetIsLoop(); - SAdvancementDeltas deltas = CActor::UpdateAnimation(dt, mgr, true); + SAdvancementDeltas deltas = CActor::UpdateAnimation(dt, mgr, true); - if (timeRemaining || loop) - { - x2e2_26_animating = true; + if (timeRemaining || loop) { + x2e2_26_animating = true; - if (x2e2_30_scaleAdvancementDelta) - MoveToOR( - x34_transform.rotate(x64_modelData->GetScale() * x34_transform.transposeRotate(deltas.x0_posDelta)), - dt); - else - MoveToOR(deltas.x0_posDelta, dt); + if (x2e2_30_scaleAdvancementDelta) + MoveToOR(x34_transform.rotate(x64_modelData->GetScale() * x34_transform.transposeRotate(deltas.x0_posDelta)), + dt); + else + MoveToOR(deltas.x0_posDelta, dt); - RotateToOR(deltas.xc_rotDelta, dt); - } - - if (!timeRemaining && x2e2_26_animating && !loop) - { - SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); - x2e2_26_animating = false; - } + RotateToOR(deltas.xc_rotDelta, dt); } - if (!x2e2_25_dead && HealthInfo(mgr)->GetHP() <= 0.f) - { - x2e2_25_dead = true; - SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); + if (!timeRemaining && x2e2_26_animating && !loop) { + SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); + x2e2_26_animating = false; } + } + + if (!x2e2_25_dead && HealthInfo(mgr)->GetHP() <= 0.f) { + x2e2_25_dead = true; + SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); + } } -void CScriptActor::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - CActor::PreRender(mgr, frustum); +void CScriptActor::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + CActor::PreRender(mgr, frustum); - if (xe4_30_outOfFrustum && TCastToPtr(mgr.GetCameraManager()->GetCurrentCamera(mgr))) - xe4_30_outOfFrustum = false; + if (xe4_30_outOfFrustum && TCastToPtr(mgr.GetCameraManager()->GetCurrentCamera(mgr))) + xe4_30_outOfFrustum = false; - if (!xe4_30_outOfFrustum && x2e2_29_processModelFlags) - { - if (x2e2_27_xrayAlphaEnabled) - { - zeus::CColor col(1.f, x2dc_xrayAlpha); - CModelFlags xrayFlags(5, 0, 3, col); - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) - { - xb4_drawFlags = xrayFlags; - x2e2_28_inXrayAlpha = true; - } - else if (x2e2_28_inXrayAlpha) - { - x2e2_28_inXrayAlpha = false; - if (xb4_drawFlags == xrayFlags) - xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); - } - } - - if (x2e2_24_noThermalHotZ && xe6_27_thermalVisorFlags == 2) - { - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) - xb4_drawFlags.x2_flags &= ~3; // Disable Z test/update - else - xb4_drawFlags.x2_flags |= 3; // Enable Z test/update - } - - if (x2d8_shaderIdx != 0) - xb4_drawFlags.x1_matSetIdx = u8(x2d8_shaderIdx); + if (!xe4_30_outOfFrustum && x2e2_29_processModelFlags) { + if (x2e2_27_xrayAlphaEnabled) { + zeus::CColor col(1.f, x2dc_xrayAlpha); + CModelFlags xrayFlags(5, 0, 3, col); + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) { + xb4_drawFlags = xrayFlags; + x2e2_28_inXrayAlpha = true; + } else if (x2e2_28_inXrayAlpha) { + x2e2_28_inXrayAlpha = false; + if (xb4_drawFlags == xrayFlags) + xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); + } } - if (mgr.GetObjectById(x2e0_triggerId) == nullptr) - x2e0_triggerId = kInvalidUniqueId; -} - -zeus::CAABox CScriptActor::GetSortingBounds(const CStateManager& mgr) const -{ - if (x2e0_triggerId != kInvalidUniqueId) - { - TCastToConstPtr trigger(mgr.GetObjectById(x2e0_triggerId)); - if (trigger) - return trigger->GetTriggerBoundsWR(); + if (x2e2_24_noThermalHotZ && xe6_27_thermalVisorFlags == 2) { + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) + xb4_drawFlags.x2_flags &= ~3; // Disable Z test/update + else + xb4_drawFlags.x2_flags |= 3; // Enable Z test/update } - return CActor::GetSortingBounds(mgr); + if (x2d8_shaderIdx != 0) + xb4_drawFlags.x1_matSetIdx = u8(x2d8_shaderIdx); + } + + if (mgr.GetObjectById(x2e0_triggerId) == nullptr) + x2e0_triggerId = kInvalidUniqueId; } -EWeaponCollisionResponseTypes -CScriptActor::GetCollisionResponseType(const zeus::CVector3f& v1, const zeus::CVector3f& v2, const - CWeaponMode& wMode, EProjectileAttrib w) const -{ - const CDamageVulnerability* dVuln = GetDamageVulnerability(); - if (dVuln->GetVulnerability(wMode, false) == EVulnerability::Deflect) - { - EVulnerability phazonVuln = dVuln->GetDeflectionType(wMode); - if (phazonVuln < EVulnerability::PassThrough && phazonVuln >= EVulnerability::Normal) - return EWeaponCollisionResponseTypes::Unknown15; - } - return CActor::GetCollisionResponseType(v1, v2, wMode, w); +zeus::CAABox CScriptActor::GetSortingBounds(const CStateManager& mgr) const { + if (x2e0_triggerId != kInvalidUniqueId) { + TCastToConstPtr trigger(mgr.GetObjectById(x2e0_triggerId)); + if (trigger) + return trigger->GetTriggerBoundsWR(); + } + + return CActor::GetSortingBounds(mgr); } -std::experimental::optional CScriptActor::GetTouchBounds() const -{ - if (GetActive() && x68_material.HasMaterial(EMaterialTypes::Solid)) - return {CPhysicsActor::GetBoundingBox()}; - return {}; +EWeaponCollisionResponseTypes CScriptActor::GetCollisionResponseType(const zeus::CVector3f& v1, + const zeus::CVector3f& v2, + const CWeaponMode& wMode, + EProjectileAttrib w) const { + const CDamageVulnerability* dVuln = GetDamageVulnerability(); + if (dVuln->GetVulnerability(wMode, false) == EVulnerability::Deflect) { + EVulnerability phazonVuln = dVuln->GetDeflectionType(wMode); + if (phazonVuln < EVulnerability::PassThrough && phazonVuln >= EVulnerability::Normal) + return EWeaponCollisionResponseTypes::Unknown15; + } + return CActor::GetCollisionResponseType(v1, v2, wMode, w); } -void CScriptActor::Touch(CActor&, CStateManager&) -{ - // Empty +std::experimental::optional CScriptActor::GetTouchBounds() const { + if (GetActive() && x68_material.HasMaterial(EMaterialTypes::Solid)) + return {CPhysicsActor::GetBoundingBox()}; + return {}; } + +void CScriptActor::Touch(CActor&, CStateManager&) { + // Empty } +} // namespace urde diff --git a/Runtime/World/CScriptActor.hpp b/Runtime/World/CScriptActor.hpp index 0ea943d5f..9e39cf645 100644 --- a/Runtime/World/CScriptActor.hpp +++ b/Runtime/World/CScriptActor.hpp @@ -4,48 +4,45 @@ #include "CHealthInfo.hpp" #include "CDamageVulnerability.hpp" -namespace urde -{ +namespace urde { -class CScriptActor : public CPhysicsActor -{ +class CScriptActor : public CPhysicsActor { protected: - CHealthInfo x258_initialHealth; - CHealthInfo x260_currentHealth; - CDamageVulnerability x268_damageVulnerability; - float x2d0_fadeInTime; - float x2d4_fadeOutTime; - s32 x2d8_shaderIdx; - float x2dc_xrayAlpha; - TUniqueId x2e0_triggerId = kInvalidUniqueId; - bool x2e2_24_noThermalHotZ : 1; - bool x2e2_25_dead : 1; - bool x2e2_26_animating : 1; - bool x2e2_27_xrayAlphaEnabled : 1; - bool x2e2_28_inXrayAlpha : 1; - bool x2e2_29_processModelFlags : 1; - bool x2e2_30_scaleAdvancementDelta : 1; - bool x2e2_31_materialFlag54 : 1; - bool x2e3_24_isPlayerActor : 1; + CHealthInfo x258_initialHealth; + CHealthInfo x260_currentHealth; + CDamageVulnerability x268_damageVulnerability; + float x2d0_fadeInTime; + float x2d4_fadeOutTime; + s32 x2d8_shaderIdx; + float x2dc_xrayAlpha; + TUniqueId x2e0_triggerId = kInvalidUniqueId; + bool x2e2_24_noThermalHotZ : 1; + bool x2e2_25_dead : 1; + bool x2e2_26_animating : 1; + bool x2e2_27_xrayAlphaEnabled : 1; + bool x2e2_28_inXrayAlpha : 1; + bool x2e2_29_processModelFlags : 1; + bool x2e2_30_scaleAdvancementDelta : 1; + bool x2e2_31_materialFlag54 : 1; + bool x2e3_24_isPlayerActor : 1; public: - CScriptActor(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const zeus::CAABox& aabb, float mass, float zMomentum, - const CMaterialList& matList, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, - const CActorParameters& actParms, bool looping, bool active, s32 shaderIdx, float xrayAlpha, - bool noThermalHotZ, bool castsShadow, bool scaleAdvancementDelta, bool materialFlag54); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - void PreRender(CStateManager&, const zeus::CFrustum&); - zeus::CAABox GetSortingBounds(const CStateManager&) const; - EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const; - std::experimental::optional GetTouchBounds() const; - void Touch(CActor&, CStateManager&); - const CDamageVulnerability* GetDamageVulnerability() const { return &x268_damageVulnerability; } - CHealthInfo* HealthInfo(CStateManager&) { return &x260_currentHealth; } - bool IsPlayerActor() const { return x2e3_24_isPlayerActor; } + CScriptActor(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const zeus::CAABox& aabb, float mass, float zMomentum, const CMaterialList& matList, + const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, const CActorParameters& actParms, + bool looping, bool active, s32 shaderIdx, float xrayAlpha, bool noThermalHotZ, bool castsShadow, + bool scaleAdvancementDelta, bool materialFlag54); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void PreRender(CStateManager&, const zeus::CFrustum&); + zeus::CAABox GetSortingBounds(const CStateManager&) const; + EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, + const CWeaponMode&, EProjectileAttrib) const; + std::experimental::optional GetTouchBounds() const; + void Touch(CActor&, CStateManager&); + const CDamageVulnerability* GetDamageVulnerability() const { return &x268_damageVulnerability; } + CHealthInfo* HealthInfo(CStateManager&) { return &x260_currentHealth; } + bool IsPlayerActor() const { return x2e3_24_isPlayerActor; } }; -}; - +}; // namespace urde diff --git a/Runtime/World/CScriptActorKeyframe.cpp b/Runtime/World/CScriptActorKeyframe.cpp index 5295c222a..a3aa61152 100644 --- a/Runtime/World/CScriptActorKeyframe.cpp +++ b/Runtime/World/CScriptActorKeyframe.cpp @@ -5,8 +5,7 @@ #include "World/CPatterned.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptActorKeyframe::CScriptActorKeyframe(TUniqueId uid, std::string_view name, const CEntityInfo& info, s32 animId, bool looping, float lifetime, bool isPassive, u32 fadeOut, bool active, float totalPlayback) @@ -14,145 +13,112 @@ CScriptActorKeyframe::CScriptActorKeyframe(TUniqueId uid, std::string_view name, , x34_animationId(animId) , x38_initialLifetime(lifetime) , x3c_playbackRate(totalPlayback) -, x40_lifetime(lifetime) -{ - x44_24_looping = looping; - x44_25_isPassive = isPassive; - x44_26_fadeOut = fadeOut; - x44_27_timedLoop = fadeOut; - x44_28_playing = false; - x44_29_ = false; +, x40_lifetime(lifetime) { + x44_24_looping = looping; + x44_25_isPassive = isPassive; + x44_26_fadeOut = fadeOut; + x44_27_timedLoop = fadeOut; + x44_28_playing = false; + x44_29_ = false; } -void CScriptActorKeyframe::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptActorKeyframe::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptActorKeyframe::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Action) - { - if (GetActive()) - { - if (!x44_25_isPassive) - { - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Play) - continue; - - auto search = mgr.GetIdListForScript(conn.x8_objId); - for (auto it = search.first; it != search.second; ++it) - UpdateEntity(it->second, mgr); - } - } - - x44_28_playing = true; - SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); - } - } - else if (msg == EScriptObjectMessage::InitializedInArea) - { - if (x34_animationId == -1) - x34_animationId = 0; - } - - CEntity::AcceptScriptMsg(msg, uid, mgr); -} - -void CScriptActorKeyframe::Think(float dt, CStateManager& mgr) -{ - if (x44_25_isPassive || !x44_24_looping || !x44_27_timedLoop || !x44_28_playing || x40_lifetime <= 0.f) - { - CEntity::Think(dt, mgr); - return; - } - - x40_lifetime -= dt; - if (x40_lifetime > 0.f) - { - CEntity::Think(dt, mgr); - return; - } - - x44_28_playing = false; - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Play) +void CScriptActorKeyframe::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Action) { + if (GetActive()) { + if (!x44_25_isPassive) { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Play) continue; - CEntity* ent = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId)); - if (TCastToPtr act = ent) - { - if (act->HasModelData() && act->GetModelData()->HasAnimData()) - { - CAnimData* animData = act->ModelData()->AnimationData(); - if (animData->IsAdditiveAnimation(x34_animationId)) - animData->DelAdditiveAnimation(x34_animationId); - if (animData->GetDefaultAnimation() == x34_animationId) - animData->EnableLooping(false); - } - } - else if (TCastToPtr ai = ent) - { - CAnimData* animData = ai->ModelData()->AnimationData(); - if (animData->IsAdditiveAnimation(x34_animationId)) - { - animData->DelAdditiveAnimation(x34_animationId); - } - else if (ai->GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Scripted && - animData->GetDefaultAnimation() == x34_animationId) - { - ai->BodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); - } + auto search = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) + UpdateEntity(it->second, mgr); } + } + + x44_28_playing = true; + SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); } + } else if (msg == EScriptObjectMessage::InitializedInArea) { + if (x34_animationId == -1) + x34_animationId = 0; + } + CEntity::AcceptScriptMsg(msg, uid, mgr); +} + +void CScriptActorKeyframe::Think(float dt, CStateManager& mgr) { + if (x44_25_isPassive || !x44_24_looping || !x44_27_timedLoop || !x44_28_playing || x40_lifetime <= 0.f) { CEntity::Think(dt, mgr); -} + return; + } -void CScriptActorKeyframe::UpdateEntity(TUniqueId uid, CStateManager& mgr) -{ - CEntity* ent = mgr.ObjectById(uid); - CActor* act = nullptr; - if (TCastToPtr tmp = ent) - act = tmp; - else if (TCastToPtr tmp = ent) - act = tmp; + x40_lifetime -= dt; + if (x40_lifetime > 0.f) { + CEntity::Think(dt, mgr); + return; + } - if (act) - { - if (!act->GetActive()) - mgr.SendScriptMsg(act, GetUniqueId(), EScriptObjectMessage::Activate); - act->SetDrawFlags({0, 0, 3, zeus::CColor::skWhite}); - if (act->HasModelData() && act->GetModelData()->HasAnimData()) - { - CAnimData* animData = act->ModelData()->AnimationData(); - if (animData->IsAdditiveAnimation(x34_animationId)) - { - animData->AddAdditiveAnimation(x34_animationId, 1.f, x44_24_looping, x44_26_fadeOut); - } - else - { - animData->SetAnimation(CAnimPlaybackParms(x34_animationId, -1, 1.f, true), false); - act->ModelData()->EnableLooping(x44_24_looping); - animData->MultiplyPlaybackRate(x3c_playbackRate); - } - } - } - else if (TCastToPtr ai = ent) - { - CAnimData* animData = ai->ModelData()->AnimationData(); + x44_28_playing = false; + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Play) + continue; + CEntity* ent = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId)); + if (TCastToPtr act = ent) { + if (act->HasModelData() && act->GetModelData()->HasAnimData()) { + CAnimData* animData = act->ModelData()->AnimationData(); if (animData->IsAdditiveAnimation(x34_animationId)) - { - animData->AddAdditiveAnimation(x34_animationId, 1.f, x44_24_looping, x44_26_fadeOut); - } - else - { - ai->BodyController()->GetCommandMgr().DeliverCmd( - CBCScriptedCmd(x34_animationId, x44_24_looping, x44_27_timedLoop, x38_initialLifetime)); - } + animData->DelAdditiveAnimation(x34_animationId); + + if (animData->GetDefaultAnimation() == x34_animationId) + animData->EnableLooping(false); + } + } else if (TCastToPtr ai = ent) { + CAnimData* animData = ai->ModelData()->AnimationData(); + if (animData->IsAdditiveAnimation(x34_animationId)) { + animData->DelAdditiveAnimation(x34_animationId); + } else if (ai->GetBodyController()->GetCurrentStateId() == pas::EAnimationState::Scripted && + animData->GetDefaultAnimation() == x34_animationId) { + ai->BodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); + } } + } + + CEntity::Think(dt, mgr); } + +void CScriptActorKeyframe::UpdateEntity(TUniqueId uid, CStateManager& mgr) { + CEntity* ent = mgr.ObjectById(uid); + CActor* act = nullptr; + if (TCastToPtr tmp = ent) + act = tmp; + else if (TCastToPtr tmp = ent) + act = tmp; + + if (act) { + if (!act->GetActive()) + mgr.SendScriptMsg(act, GetUniqueId(), EScriptObjectMessage::Activate); + act->SetDrawFlags({0, 0, 3, zeus::CColor::skWhite}); + if (act->HasModelData() && act->GetModelData()->HasAnimData()) { + CAnimData* animData = act->ModelData()->AnimationData(); + if (animData->IsAdditiveAnimation(x34_animationId)) { + animData->AddAdditiveAnimation(x34_animationId, 1.f, x44_24_looping, x44_26_fadeOut); + } else { + animData->SetAnimation(CAnimPlaybackParms(x34_animationId, -1, 1.f, true), false); + act->ModelData()->EnableLooping(x44_24_looping); + animData->MultiplyPlaybackRate(x3c_playbackRate); + } + } + } else if (TCastToPtr ai = ent) { + CAnimData* animData = ai->ModelData()->AnimationData(); + if (animData->IsAdditiveAnimation(x34_animationId)) { + animData->AddAdditiveAnimation(x34_animationId, 1.f, x44_24_looping, x44_26_fadeOut); + } else { + ai->BodyController()->GetCommandMgr().DeliverCmd( + CBCScriptedCmd(x34_animationId, x44_24_looping, x44_27_timedLoop, x38_initialLifetime)); + } + } } +} // namespace urde diff --git a/Runtime/World/CScriptActorKeyframe.hpp b/Runtime/World/CScriptActorKeyframe.hpp index 62ea97d7d..1761a9de4 100644 --- a/Runtime/World/CScriptActorKeyframe.hpp +++ b/Runtime/World/CScriptActorKeyframe.hpp @@ -2,38 +2,33 @@ #include "CEntity.hpp" -namespace urde -{ -class CScriptActorKeyframe : public CEntity -{ +namespace urde { +class CScriptActorKeyframe : public CEntity { private: - s32 x34_animationId; - float x38_initialLifetime; - float x3c_playbackRate; - float x40_lifetime; - union { - struct - { - bool x44_24_looping : 1; - bool x44_25_isPassive : 1; - bool x44_26_fadeOut : 1; - bool x44_27_timedLoop : 1; - bool x44_28_playing : 1; - bool x44_29_ : 1; - }; - u8 _dummy = 0; + s32 x34_animationId; + float x38_initialLifetime; + float x3c_playbackRate; + float x40_lifetime; + union { + struct { + bool x44_24_looping : 1; + bool x44_25_isPassive : 1; + bool x44_26_fadeOut : 1; + bool x44_27_timedLoop : 1; + bool x44_28_playing : 1; + bool x44_29_ : 1; }; + u8 _dummy = 0; + }; public: - CScriptActorKeyframe(TUniqueId uid, std::string_view name, const CEntityInfo& info, s32 animId, - bool looping, float lifetime, bool isPassive, u32 fadeOut, bool active, - float totalPlayback); + CScriptActorKeyframe(TUniqueId uid, std::string_view name, const CEntityInfo& info, s32 animId, bool looping, + float lifetime, bool isPassive, u32 fadeOut, bool active, float totalPlayback); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); - void Think(float, CStateManager&); - void UpdateEntity(TUniqueId, CStateManager&); - bool IsPassive() const { return x44_25_isPassive; } + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Think(float, CStateManager&); + void UpdateEntity(TUniqueId, CStateManager&); + bool IsPassive() const { return x44_25_isPassive; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptActorRotate.cpp b/Runtime/World/CScriptActorRotate.cpp index bbfcc6b51..5f000f307 100644 --- a/Runtime/World/CScriptActorRotate.cpp +++ b/Runtime/World/CScriptActorRotate.cpp @@ -4,8 +4,7 @@ #include "CScriptSpiderBallWaypoint.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptActorRotate::CScriptActorRotate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& rotation, float maxTime, bool updateActors, bool updateOnCreation, bool active) @@ -15,153 +14,125 @@ CScriptActorRotate::CScriptActorRotate(TUniqueId uid, std::string_view name, con , x58_24_updateRotation(false) , x58_25_skipSpiderBallWaypoints(false) , x58_26_updateActors(updateActors) -, x58_27_updateOnCreation(updateOnCreation) -{ -} +, x58_27_updateOnCreation(updateOnCreation) {} -void CScriptActorRotate::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CScriptActorRotate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Activate) - { - CEntity::AcceptScriptMsg(msg, uid, mgr); - return; - } - - if (msg == EScriptObjectMessage::Action || msg == EScriptObjectMessage::Next - || (msg == EScriptObjectMessage::Registered && x58_27_updateOnCreation)) - UpdateActors(msg == EScriptObjectMessage::Next, mgr); +void CScriptActorRotate::Accept(IVisitor& visitor) { visitor.Visit(this); } +void CScriptActorRotate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Activate) { CEntity::AcceptScriptMsg(msg, uid, mgr); + return; + } + + if (msg == EScriptObjectMessage::Action || msg == EScriptObjectMessage::Next || + (msg == EScriptObjectMessage::Registered && x58_27_updateOnCreation)) + UpdateActors(msg == EScriptObjectMessage::Next, mgr); + + CEntity::AcceptScriptMsg(msg, uid, mgr); } -void CScriptActorRotate::Think(float dt, CStateManager& mgr) -{ - if (x58_24_updateRotation && GetActive()) - { - x44_currentTime += dt; - if (x44_currentTime >= x40_maxTime) - { - x58_24_updateRotation = false; - x44_currentTime = x40_maxTime; - } - - float timeOffset = x44_currentTime / x40_maxTime; - - for (const auto& actorPair : x48_actors) - { - if (TCastToPtr act = mgr.ObjectById(actorPair.first)) - { - zeus::CTransform xf = - zeus::CTransform::RotateZ(zeus::degToRad(timeOffset * x34_rotation.z())) * - zeus::CTransform::RotateY(zeus::degToRad(timeOffset * x34_rotation.y())) * - zeus::CTransform::RotateX(zeus::degToRad(timeOffset * x34_rotation.x())); - zeus::CTransform localRot = actorPair.second * xf; - localRot.origin = act->GetTranslation(); - act->SetTransform(localRot); - - if (TCastToPtr plat = mgr.ObjectById(actorPair.first)) - UpdatePlatformRiders(*plat.GetPtr(), xf, mgr); - } - } - - if (x58_24_updateRotation) - { - if (!x58_25_skipSpiderBallWaypoints) - UpdateSpiderBallWaypoints(mgr); - - if (x58_26_updateActors) - UpdateActors(false, mgr); - } +void CScriptActorRotate::Think(float dt, CStateManager& mgr) { + if (x58_24_updateRotation && GetActive()) { + x44_currentTime += dt; + if (x44_currentTime >= x40_maxTime) { + x58_24_updateRotation = false; + x44_currentTime = x40_maxTime; } + + float timeOffset = x44_currentTime / x40_maxTime; + + for (const auto& actorPair : x48_actors) { + if (TCastToPtr act = mgr.ObjectById(actorPair.first)) { + zeus::CTransform xf = zeus::CTransform::RotateZ(zeus::degToRad(timeOffset * x34_rotation.z())) * + zeus::CTransform::RotateY(zeus::degToRad(timeOffset * x34_rotation.y())) * + zeus::CTransform::RotateX(zeus::degToRad(timeOffset * x34_rotation.x())); + zeus::CTransform localRot = actorPair.second * xf; + localRot.origin = act->GetTranslation(); + act->SetTransform(localRot); + + if (TCastToPtr plat = mgr.ObjectById(actorPair.first)) + UpdatePlatformRiders(*plat.GetPtr(), xf, mgr); + } + } + + if (x58_24_updateRotation) { + if (!x58_25_skipSpiderBallWaypoints) + UpdateSpiderBallWaypoints(mgr); + + if (x58_26_updateActors) + UpdateActors(false, mgr); + } + } } -void CScriptActorRotate::UpdatePlatformRiders(CScriptPlatform& plat, const zeus::CTransform& xf, CStateManager& mgr) -{ - UpdatePlatformRiders(plat.GetStaticSlaves(), plat, xf, mgr); - UpdatePlatformRiders(plat.GetDynamicSlaves(), plat, xf, mgr); +void CScriptActorRotate::UpdatePlatformRiders(CScriptPlatform& plat, const zeus::CTransform& xf, CStateManager& mgr) { + UpdatePlatformRiders(plat.GetStaticSlaves(), plat, xf, mgr); + UpdatePlatformRiders(plat.GetDynamicSlaves(), plat, xf, mgr); } void CScriptActorRotate::UpdatePlatformRiders(std::vector& riders, CScriptPlatform& plat, - const zeus::CTransform& xf, CStateManager& mgr) -{ - for (SRiders& rider : riders) - { - if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) - { - zeus::CTransform& riderXf = rider.x8_transform; - act->SetTransform(rider.x8_transform); - act->SetTranslation(act->GetTranslation() + plat.GetTranslation()); + const zeus::CTransform& xf, CStateManager& mgr) { + for (SRiders& rider : riders) { + if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) { + zeus::CTransform& riderXf = rider.x8_transform; + act->SetTransform(rider.x8_transform); + act->SetTranslation(act->GetTranslation() + plat.GetTranslation()); - if (x58_24_updateRotation) - { - riderXf = {act->GetTransform().basis, act->GetTranslation() - plat.GetTranslation()}; + if (x58_24_updateRotation) { + riderXf = {act->GetTransform().basis, act->GetTranslation() - plat.GetTranslation()}; - if (TCastToPtr wp = act.GetPtr()) - x58_25_skipSpiderBallWaypoints = true; - } + if (TCastToPtr wp = act.GetPtr()) + x58_25_skipSpiderBallWaypoints = true; + } - if (TCastToPtr plat2 = mgr.ObjectById(rider.x0_uid)) - UpdatePlatformRiders(*plat2.GetPtr(), xf, mgr); - } + if (TCastToPtr plat2 = mgr.ObjectById(rider.x0_uid)) + UpdatePlatformRiders(*plat2.GetPtr(), xf, mgr); } + } } -void CScriptActorRotate::UpdateActors(bool next, CStateManager& mgr) -{ - if (x58_24_updateRotation) - return; +void CScriptActorRotate::UpdateActors(bool next, CStateManager& mgr) { + if (x58_24_updateRotation) + return; - x48_actors.clear(); + x48_actors.clear(); - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state == EScriptObjectState::Play && conn.x4_msg == EScriptObjectMessage::Play) - { - auto search = mgr.GetIdListForScript(conn.x8_objId); - for (auto it = search.first ; it != search.second ; ++it) - { - if (TCastToPtr act = mgr.ObjectById(it->second)) - x48_actors[it->second] = act->GetTransform().getRotation(); - } - } + for (const SConnection& conn : x20_conns) { + if (conn.x0_state == EScriptObjectState::Play && conn.x4_msg == EScriptObjectMessage::Play) { + auto search = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) { + if (TCastToPtr act = mgr.ObjectById(it->second)) + x48_actors[it->second] = act->GetTransform().getRotation(); + } } + } - SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); + SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); - if (!x48_actors.empty()) - { - x58_24_updateRotation = true; - x44_currentTime = (next ? x40_maxTime : 0.f); - } + if (!x48_actors.empty()) { + x58_24_updateRotation = true; + x44_currentTime = (next ? x40_maxTime : 0.f); + } } -void CScriptActorRotate::UpdateSpiderBallWaypoints(CStateManager& mgr) -{ - rstl::reserved_vector waypointIds; - CObjectList& objectList = mgr.GetAllObjectList(); - for (CEntity* ent : objectList) - { - if (TCastToPtr wp = ent) - waypointIds.push_back(wp->GetUniqueId()); - } +void CScriptActorRotate::UpdateSpiderBallWaypoints(CStateManager& mgr) { + rstl::reserved_vector waypointIds; + CObjectList& objectList = mgr.GetAllObjectList(); + for (CEntity* ent : objectList) { + if (TCastToPtr wp = ent) + waypointIds.push_back(wp->GetUniqueId()); + } - for (const TUniqueId& uid : waypointIds) - { - CScriptSpiderBallWaypoint* wp = static_cast(mgr.ObjectById(uid)); - if (wp) - { + for (const TUniqueId& uid : waypointIds) { + CScriptSpiderBallWaypoint* wp = static_cast(mgr.ObjectById(uid)); + if (wp) { #if 0 wp->sub_801187B4(mgr); wp->xe4_27_ = true; #endif - } } + } - x58_25_skipSpiderBallWaypoints = false; -} + x58_25_skipSpiderBallWaypoints = false; } +} // namespace urde diff --git a/Runtime/World/CScriptActorRotate.hpp b/Runtime/World/CScriptActorRotate.hpp index 663d4ee05..ef639bf1e 100644 --- a/Runtime/World/CScriptActorRotate.hpp +++ b/Runtime/World/CScriptActorRotate.hpp @@ -3,43 +3,36 @@ #include "CEntity.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { struct SRiders; class CScriptPlatform; -class CScriptActorRotate : public CEntity -{ - zeus::CVector3f x34_rotation; - float x40_maxTime; - float x44_currentTime = 0.f; - std::map x48_actors; +class CScriptActorRotate : public CEntity { + zeus::CVector3f x34_rotation; + float x40_maxTime; + float x44_currentTime = 0.f; + std::map x48_actors; - union - { - struct - { - bool x58_24_updateRotation : 1; - bool x58_25_skipSpiderBallWaypoints : 1; - bool x58_26_updateActors : 1; - bool x58_27_updateOnCreation : 1; - }; - u32 dummy = 0; + union { + struct { + bool x58_24_updateRotation : 1; + bool x58_25_skipSpiderBallWaypoints : 1; + bool x58_26_updateActors : 1; + bool x58_27_updateOnCreation : 1; }; + u32 dummy = 0; + }; + + void UpdateActors(bool, CStateManager&); + void UpdateSpiderBallWaypoints(CStateManager&); + void UpdatePlatformRiders(CScriptPlatform&, const zeus::CTransform&, CStateManager&); + void UpdatePlatformRiders(std::vector&, CScriptPlatform&, const zeus::CTransform&, CStateManager&); - void UpdateActors(bool, CStateManager&); - void UpdateSpiderBallWaypoints(CStateManager&); - void UpdatePlatformRiders(CScriptPlatform&, const zeus::CTransform&, CStateManager&); - void UpdatePlatformRiders(std::vector&, CScriptPlatform&, - const zeus::CTransform&, CStateManager&); public: - CScriptActorRotate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CVector3f&, float, bool, bool, - bool); - - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); + CScriptActorRotate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CVector3f&, float, bool, bool, bool); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptAiJumpPoint.cpp b/Runtime/World/CScriptAiJumpPoint.cpp index 2f75cad3d..137d8288d 100644 --- a/Runtime/World/CScriptAiJumpPoint.cpp +++ b/Runtime/World/CScriptAiJumpPoint.cpp @@ -4,60 +4,49 @@ #include "CScriptWaypoint.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptAiJumpPoint::CScriptAiJumpPoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, zeus::CTransform& xf, bool active, float f1) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic), CActorParameters::None(), kInvalidUniqueId) , xe8_(f1) -, xec_touchBounds(xf.origin, xf.origin) -{ +, xec_touchBounds(xf.origin, xf.origin) {} + +void CScriptAiJumpPoint::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptAiJumpPoint::Think(float dt, CStateManager&) { + if (x110_timeRemaining <= 0) + return; + + x110_timeRemaining -= dt; } -void CScriptAiJumpPoint::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptAiJumpPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, other, mgr); -void CScriptAiJumpPoint::Think(float dt, CStateManager&) -{ - if (x110_timeRemaining <= 0) - return; + if (msg != EScriptObjectMessage::InitializedInArea) + return; - x110_timeRemaining -= dt; -} + for (SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Arrived || conn.x4_msg != EScriptObjectMessage::Next) + continue; -void CScriptAiJumpPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, other, mgr); - - if (msg != EScriptObjectMessage::InitializedInArea) - return; - - for (SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Arrived || conn.x4_msg != EScriptObjectMessage::Next) - continue; - - const CScriptWaypoint* wpnt = - static_cast(mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))); - if (wpnt) - { - x10c_currentWaypoint = wpnt->GetUniqueId(); - x10e_nextWaypoint = wpnt->NextWaypoint(mgr); - } + const CScriptWaypoint* wpnt = + static_cast(mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))); + if (wpnt) { + x10c_currentWaypoint = wpnt->GetUniqueId(); + x10e_nextWaypoint = wpnt->NextWaypoint(mgr); } + } } std::experimental::optional CScriptAiJumpPoint::GetTouchBounds() const { return xec_touchBounds; } -bool CScriptAiJumpPoint::GetInUse(TUniqueId uid) const -{ - if (x108_24 || x110_timeRemaining > 0.f || x10a_occupant != kInvalidUniqueId || uid != kInvalidUniqueId || - uid != x10a_occupant) - return true; +bool CScriptAiJumpPoint::GetInUse(TUniqueId uid) const { + if (x108_24 || x110_timeRemaining > 0.f || x10a_occupant != kInvalidUniqueId || uid != kInvalidUniqueId || + uid != x10a_occupant) + return true; - return false; -} + return false; } +} // namespace urde diff --git a/Runtime/World/CScriptAiJumpPoint.hpp b/Runtime/World/CScriptAiJumpPoint.hpp index fb7499c19..2410bacc0 100644 --- a/Runtime/World/CScriptAiJumpPoint.hpp +++ b/Runtime/World/CScriptAiJumpPoint.hpp @@ -2,34 +2,31 @@ #include "CActor.hpp" -namespace urde -{ -class CScriptAiJumpPoint : public CActor -{ +namespace urde { +class CScriptAiJumpPoint : public CActor { private: - float xe8_; - zeus::CAABox xec_touchBounds; - union { - struct - { - bool x108_24 : 1; - }; - u8 dummy = 0; + float xe8_; + zeus::CAABox xec_touchBounds; + union { + struct { + bool x108_24 : 1; }; - TUniqueId x10a_occupant = kInvalidUniqueId; - TUniqueId x10c_currentWaypoint = kInvalidUniqueId; - TUniqueId x10e_nextWaypoint = kInvalidUniqueId; - float x110_timeRemaining = 0.f; + u8 dummy = 0; + }; + TUniqueId x10a_occupant = kInvalidUniqueId; + TUniqueId x10c_currentWaypoint = kInvalidUniqueId; + TUniqueId x10e_nextWaypoint = kInvalidUniqueId; + float x110_timeRemaining = 0.f; public: - CScriptAiJumpPoint(TUniqueId, std::string_view, const CEntityInfo&, zeus::CTransform&, bool, float); + CScriptAiJumpPoint(TUniqueId, std::string_view, const CEntityInfo&, zeus::CTransform&, bool, float); - void Accept(IVisitor& visitor); - void Think(float, CStateManager&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} - void Render(const CStateManager&) const {} - std::experimental::optional GetTouchBounds() const; - bool GetInUse(TUniqueId uid) const; + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} + void Render(const CStateManager&) const {} + std::experimental::optional GetTouchBounds() const; + bool GetInUse(TUniqueId uid) const; }; -} +} // namespace urde diff --git a/Runtime/World/CScriptAreaAttributes.cpp b/Runtime/World/CScriptAreaAttributes.cpp index f9e5e9528..b95b71dd2 100644 --- a/Runtime/World/CScriptAreaAttributes.cpp +++ b/Runtime/World/CScriptAreaAttributes.cpp @@ -4,8 +4,7 @@ #include "CWorld.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptAreaAttributes::CScriptAreaAttributes(TUniqueId uid, const CEntityInfo& info, bool showSkybox, EEnvFxType fxType, float envFxDensity, float thermalHeat, float xrayFogDistance, @@ -18,36 +17,27 @@ CScriptAreaAttributes::CScriptAreaAttributes(TUniqueId uid, const CEntityInfo& i , x44_xrayFogDistance(xrayFogDistance) , x48_worldLightingLevel(worldLightingLevel) , x4c_skybox(skybox) -, x50_phazon(phazonType) -{ +, x50_phazon(phazonType) {} + +void CScriptAreaAttributes::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptAreaAttributes::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); + if (x4_areaId == kInvalidAreaId) + return; + + if (msg == EScriptObjectMessage::InitializedInArea) { + CGameArea* area = stateMgr.WorldNC()->GetArea(x4_areaId); + area->SetAreaAttributes(this); + stateMgr.GetEnvFxManager()->SetFxDensity(500, x3c_envFxDensity); + } else if (msg == EScriptObjectMessage::Deleted) { + CGameArea* area = stateMgr.WorldNC()->GetArea(x4_areaId); + + if (!area->IsPostConstructed()) + return; + + area->SetAreaAttributes(nullptr); + } } -void CScriptAreaAttributes::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CScriptAreaAttributes::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CEntity::AcceptScriptMsg(msg, objId, stateMgr); - if (x4_areaId == kInvalidAreaId) - return; - - if (msg == EScriptObjectMessage::InitializedInArea) - { - CGameArea* area = stateMgr.WorldNC()->GetArea(x4_areaId); - area->SetAreaAttributes(this); - stateMgr.GetEnvFxManager()->SetFxDensity(500, x3c_envFxDensity); - } - else if (msg == EScriptObjectMessage::Deleted) - { - CGameArea* area = stateMgr.WorldNC()->GetArea(x4_areaId); - - if (!area->IsPostConstructed()) - return; - - area->SetAreaAttributes(nullptr); - } -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptAreaAttributes.hpp b/Runtime/World/CScriptAreaAttributes.hpp index 0658df17f..759da32a2 100644 --- a/Runtime/World/CScriptAreaAttributes.hpp +++ b/Runtime/World/CScriptAreaAttributes.hpp @@ -3,37 +3,33 @@ #include "CEntity.hpp" #include "CEnvFxManager.hpp" -namespace urde -{ -class CScriptAreaAttributes : public CEntity -{ - bool x34_24_showSkybox : 1; - EEnvFxType x38_envFx; - float x3c_envFxDensity; - float x40_thermalHeat; - float x44_xrayFogDistance; - float x48_worldLightingLevel; - CAssetId x4c_skybox; - EPhazonType x50_phazon; +namespace urde { +class CScriptAreaAttributes : public CEntity { + bool x34_24_showSkybox : 1; + EEnvFxType x38_envFx; + float x3c_envFxDensity; + float x40_thermalHeat; + float x44_xrayFogDistance; + float x48_worldLightingLevel; + CAssetId x4c_skybox; + EPhazonType x50_phazon; public: - CScriptAreaAttributes(TUniqueId uid, const CEntityInfo& info, bool showSkybox, EEnvFxType fxType, - float envFxDensity, float thermalHeat, float xrayFogDistance, float worldLightingLevel, - CAssetId skybox, EPhazonType phazonType); + CScriptAreaAttributes(TUniqueId uid, const CEntityInfo& info, bool showSkybox, EEnvFxType fxType, float envFxDensity, + float thermalHeat, float xrayFogDistance, float worldLightingLevel, CAssetId skybox, + EPhazonType phazonType); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); - - bool GetNeedsSky() const { return x34_24_showSkybox; } - bool GetNeedsEnvFx() const { return x38_envFx != EEnvFxType::None; } - CAssetId GetSkyModel() const { return x4c_skybox; } - EEnvFxType GetEnvFxType() const { return x38_envFx; } - float GetEnvFxDensity() const { return x3c_envFxDensity; } - float GetThermalHeat() const { return x40_thermalHeat; } - float GetXRayFogDistance() const { return x44_xrayFogDistance; } - float GetWorldLightingLevel() const { return x48_worldLightingLevel; } - EPhazonType GetPhazonType() const { return x50_phazon; } + bool GetNeedsSky() const { return x34_24_showSkybox; } + bool GetNeedsEnvFx() const { return x38_envFx != EEnvFxType::None; } + CAssetId GetSkyModel() const { return x4c_skybox; } + EEnvFxType GetEnvFxType() const { return x38_envFx; } + float GetEnvFxDensity() const { return x3c_envFxDensity; } + float GetThermalHeat() const { return x40_thermalHeat; } + float GetXRayFogDistance() const { return x44_xrayFogDistance; } + float GetWorldLightingLevel() const { return x48_worldLightingLevel; } + EPhazonType GetPhazonType() const { return x50_phazon; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptBallTrigger.cpp b/Runtime/World/CScriptBallTrigger.cpp index 0ad49e00d..97fe80d91 100644 --- a/Runtime/World/CScriptBallTrigger.cpp +++ b/Runtime/World/CScriptBallTrigger.cpp @@ -6,102 +6,86 @@ #include "DNAMP1/Tweaks/CTweakPlayer.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -static zeus::CAABox calculate_ball_aabox() -{ - float extent = 0.33f * g_tweakPlayer->GetPlayerBallHalfExtent(); - return {-extent, extent}; +static zeus::CAABox calculate_ball_aabox() { + float extent = 0.33f * g_tweakPlayer->GetPlayerBallHalfExtent(); + return {-extent, extent}; } CScriptBallTrigger::CScriptBallTrigger(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CVector3f& pos, const zeus::CVector3f& scale, - bool active, float f1, float f2, float f3, const zeus::CVector3f& vec, bool b2) - : CScriptTrigger(uid, name, info, pos, calculate_ball_aabox(), CDamageInfo(CWeaponMode::Power(), 0.f, 0.f, 0.f), zeus::CVector3f::skZero, ETriggerFlags::DetectMorphedPlayer, active, false, false) - , x150_force(f1) - , x154_minAngle(f2) - , x158_maxDistance(f3) - , x168_24_canApplyForce(false) - , x168_25_stopPlayer(b2) -{ + const zeus::CVector3f& pos, const zeus::CVector3f& scale, bool active, float f1, + float f2, float f3, const zeus::CVector3f& vec, bool b2) +: CScriptTrigger(uid, name, info, pos, calculate_ball_aabox(), CDamageInfo(CWeaponMode::Power(), 0.f, 0.f, 0.f), + zeus::CVector3f::skZero, ETriggerFlags::DetectMorphedPlayer, active, false, false) +, x150_force(f1) +, x154_minAngle(f2) +, x158_maxDistance(f3) +, x168_24_canApplyForce(false) +, x168_25_stopPlayer(b2) { - if (vec.canBeNormalized()) - x15c_forceAngle = vec.normalized(); + if (vec.canBeNormalized()) + x15c_forceAngle = vec.normalized(); } -void CScriptBallTrigger::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptBallTrigger::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptBallTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Deactivate && GetActive()) { + mgr.GetPlayer().GetMorphBall()->SetBallBoostState(CMorphBall::EBallBoostState::BoostAvailable); + x168_24_canApplyForce = false; + } + + CScriptTrigger::AcceptScriptMsg(msg, uid, mgr); } -void CScriptBallTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager & mgr) -{ - if (msg == EScriptObjectMessage::Deactivate && GetActive()) - { - mgr.GetPlayer().GetMorphBall()->SetBallBoostState(CMorphBall::EBallBoostState::BoostAvailable); - x168_24_canApplyForce = false; +void CScriptBallTrigger::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; + CScriptTrigger::Think(dt, mgr); + CPlayer& player = mgr.GetPlayer(); + + if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) { + x168_24_canApplyForce = false; + return; + } + + const float ballRadius = player.GetMorphBall()->GetBallRadius(); + const zeus::CVector3f radiusPosDif = + (player.GetTranslation() - (player.GetTranslation() + zeus::CVector3f{0.f, 0.f, ballRadius})); + const float distance = radiusPosDif.magnitude(); + + if (!x168_24_canApplyForce) { + if (distance < ballRadius) + x168_24_canApplyForce = true; + else { + zeus::CVector3f offset = radiusPosDif.normalized(); + if (std::cos(zeus::degToRad(x154_minAngle)) < (-offset).dot(x15c_forceAngle) && distance < x158_maxDistance) { + float force = zeus::min((1.f / dt * distance), x150_force * (distance * distance)); + player.ApplyForceWR(force * (player.GetMass() * offset), zeus::CAxisAngle::sIdentity); + } } + } - CScriptTrigger::AcceptScriptMsg(msg, uid, mgr); + if (x148_28_playerTriggerProc) { + zeus::CVector3f offset = GetTranslation() - zeus::CVector3f(0.f, 0.f, ballRadius); + if (x168_25_stopPlayer) + player.Stop(); + player.MoveToWR(offset, dt); + } else + x168_24_canApplyForce = false; } -void CScriptBallTrigger::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; - CScriptTrigger::Think(dt, mgr); - CPlayer& player = mgr.GetPlayer(); - - if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) - { - x168_24_canApplyForce = false; - return; - } - - const float ballRadius = player.GetMorphBall()->GetBallRadius(); - const zeus::CVector3f radiusPosDif = (player.GetTranslation() - (player.GetTranslation() + zeus::CVector3f{0.f, 0.f, ballRadius})); - const float distance = radiusPosDif.magnitude(); - - if (!x168_24_canApplyForce) - { - if (distance < ballRadius) - x168_24_canApplyForce = true; - else - { - zeus::CVector3f offset = radiusPosDif.normalized(); - if (std::cos(zeus::degToRad(x154_minAngle)) < (-offset).dot(x15c_forceAngle) && distance < x158_maxDistance) - { - float force = zeus::min((1.f / dt * distance), x150_force * (distance * distance)); - player.ApplyForceWR(force * (player.GetMass() * offset), zeus::CAxisAngle::sIdentity); - } - } - } - - if (x148_28_playerTriggerProc) - { - zeus::CVector3f offset = GetTranslation() - zeus::CVector3f(0.f, 0.f, ballRadius); - if (x168_25_stopPlayer) - player.Stop(); - player.MoveToWR(offset, dt); - } - else - x168_24_canApplyForce = false; +void CScriptBallTrigger::InhabitantAdded(CActor& act, CStateManager& /*mgr*/) { + if (TCastToPtr player = act) + player->GetMorphBall()->SetBallBoostState(CMorphBall::EBallBoostState::BoostDisabled); } -void CScriptBallTrigger::InhabitantAdded(CActor& act, CStateManager& /*mgr*/) -{ - if (TCastToPtr player = act) - player->GetMorphBall()->SetBallBoostState(CMorphBall::EBallBoostState::BoostDisabled); +void CScriptBallTrigger::InhabitantExited(CActor& act, CStateManager&) { + if (TCastToPtr player = act) { + player->GetMorphBall()->SetBallBoostState(CMorphBall::EBallBoostState::BoostAvailable); + x168_24_canApplyForce = false; + } } -void CScriptBallTrigger::InhabitantExited(CActor& act, CStateManager &) -{ - if (TCastToPtr player = act) - { - player->GetMorphBall()->SetBallBoostState(CMorphBall::EBallBoostState::BoostAvailable); - x168_24_canApplyForce = false; - } -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptBallTrigger.hpp b/Runtime/World/CScriptBallTrigger.hpp index b330c7d63..b213b8f23 100644 --- a/Runtime/World/CScriptBallTrigger.hpp +++ b/Runtime/World/CScriptBallTrigger.hpp @@ -2,24 +2,23 @@ #include "CScriptTrigger.hpp" -namespace urde -{ -class CScriptBallTrigger : public CScriptTrigger -{ - float x150_force; - float x154_minAngle; - float x158_maxDistance; - zeus::CVector3f x15c_forceAngle = zeus::CVector3f::skZero; - bool x168_24_canApplyForce : 1; - bool x168_25_stopPlayer : 1; -public: - CScriptBallTrigger(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CVector3f&, - const zeus::CVector3f&, bool, float, float, float, const zeus::CVector3f&, bool); +namespace urde { +class CScriptBallTrigger : public CScriptTrigger { + float x150_force; + float x154_minAngle; + float x158_maxDistance; + zeus::CVector3f x15c_forceAngle = zeus::CVector3f::skZero; + bool x168_24_canApplyForce : 1; + bool x168_25_stopPlayer : 1; - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager& mgr); - void InhabitantAdded(CActor&, CStateManager&); - void InhabitantExited(CActor&, CStateManager&); +public: + CScriptBallTrigger(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CVector3f&, const zeus::CVector3f&, + bool, float, float, float, const zeus::CVector3f&, bool); + + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager& mgr); + void InhabitantAdded(CActor&, CStateManager&); + void InhabitantExited(CActor&, CStateManager&); }; -} +} // namespace urde diff --git a/Runtime/World/CScriptBeam.cpp b/Runtime/World/CScriptBeam.cpp index 1bd973335..3249c83d1 100644 --- a/Runtime/World/CScriptBeam.cpp +++ b/Runtime/World/CScriptBeam.cpp @@ -5,8 +5,7 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptBeam::CScriptBeam(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, const TToken& weaponDesc, const CBeamInfo& bInfo, @@ -15,47 +14,31 @@ CScriptBeam::CScriptBeam(TUniqueId uid, std::string_view name, const CEntityInfo kInvalidUniqueId) , xe8_weaponDescription(weaponDesc) , xf4_beamInfo(bInfo) -, x138_damageInfo(dInfo) -{ +, x138_damageInfo(dInfo) {} + +void CScriptBeam::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptBeam::Think(float dt, CStateManager& mgr) { + CPlasmaProjectile* proj = static_cast(mgr.ObjectById(x154_projectileId)); + if (proj) { + if (proj->GetActive()) + proj->UpdateFx(x34_transform, dt, mgr); + } else + x154_projectileId = kInvalidUniqueId; } -void CScriptBeam::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptBeam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Increment) { + } else if (msg == EScriptObjectMessage::Decrement) { + } else if (msg == EScriptObjectMessage::Registered) { + x154_projectileId = mgr.AllocateUniqueId(); + mgr.AddObject(new CPlasmaProjectile(xe8_weaponDescription, x10_name + "-Projectile", + x138_damageInfo.GetWeaponMode().GetType(), xf4_beamInfo, x34_transform, + EMaterialTypes::Projectile, x138_damageInfo, x8_uid, x4_areaId, + x154_projectileId, 8, false, EProjectileAttrib::PlasmaProjectile)); + } else if (msg == EScriptObjectMessage::Deleted) { + } -void CScriptBeam::Think(float dt, CStateManager& mgr) -{ - CPlasmaProjectile* proj = static_cast(mgr.ObjectById(x154_projectileId)); - if (proj) - { - if (proj->GetActive()) - proj->UpdateFx(x34_transform, dt, mgr); - } - else - x154_projectileId = kInvalidUniqueId; -} - -void CScriptBeam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Increment) - { - } - else if (msg == EScriptObjectMessage::Decrement) - { - } - else if (msg == EScriptObjectMessage::Registered) - { - x154_projectileId = mgr.AllocateUniqueId(); - mgr.AddObject(new CPlasmaProjectile(xe8_weaponDescription, x10_name + "-Projectile", - x138_damageInfo.GetWeaponMode().GetType(), xf4_beamInfo, x34_transform, - EMaterialTypes::Projectile, x138_damageInfo, x8_uid, x4_areaId, - x154_projectileId, 8, false, EProjectileAttrib::PlasmaProjectile)); - } - else if (msg == EScriptObjectMessage::Deleted) - { - } - - CActor::AcceptScriptMsg(msg, objId, mgr); -} + CActor::AcceptScriptMsg(msg, objId, mgr); } +} // namespace urde diff --git a/Runtime/World/CScriptBeam.hpp b/Runtime/World/CScriptBeam.hpp index 170b77e6d..aefd05ce4 100644 --- a/Runtime/World/CScriptBeam.hpp +++ b/Runtime/World/CScriptBeam.hpp @@ -4,21 +4,20 @@ #include "Weapon/CBeamInfo.hpp" #include "CDamageInfo.hpp" -namespace urde -{ +namespace urde { class CWeaponDescription; -class CScriptBeam : public CActor -{ - TCachedToken xe8_weaponDescription; - CBeamInfo xf4_beamInfo; - CDamageInfo x138_damageInfo; - TUniqueId x154_projectileId; -public: - CScriptBeam(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, - const TToken&, const CBeamInfo&, const CDamageInfo&); +class CScriptBeam : public CActor { + TCachedToken xe8_weaponDescription; + CBeamInfo xf4_beamInfo; + CDamageInfo x138_damageInfo; + TUniqueId x154_projectileId; - void Accept(IVisitor& visitor); - void Think(float, CStateManager &); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); +public: + CScriptBeam(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, + const TToken&, const CBeamInfo&, const CDamageInfo&); + + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); }; -} +} // namespace urde diff --git a/Runtime/World/CScriptCameraBlurKeyframe.cpp b/Runtime/World/CScriptCameraBlurKeyframe.cpp index d902bb115..12255c565 100644 --- a/Runtime/World/CScriptCameraBlurKeyframe.cpp +++ b/Runtime/World/CScriptCameraBlurKeyframe.cpp @@ -2,38 +2,34 @@ #include "TCastTo.hpp" #include "CStateManager.hpp" -namespace urde -{ -CScriptCameraBlurKeyframe::CScriptCameraBlurKeyframe(TUniqueId uid, std::string_view name, - const CEntityInfo& info, EBlurType type, - float amount, u32 unk, float timeIn, - float timeOut, bool active) -: CEntity(uid, info, active, name), x34_type(type), x38_amount(amount), x3c_(unk), - x40_timeIn(timeIn), x44_timeOut(timeOut) -{ +namespace urde { +CScriptCameraBlurKeyframe::CScriptCameraBlurKeyframe(TUniqueId uid, std::string_view name, const CEntityInfo& info, + EBlurType type, float amount, u32 unk, float timeIn, float timeOut, + bool active) +: CEntity(uid, info, active, name) +, x34_type(type) +, x38_amount(amount) +, x3c_(unk) +, x40_timeIn(timeIn) +, x44_timeOut(timeOut) {} + +void CScriptCameraBlurKeyframe::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); + + switch (msg) { + case EScriptObjectMessage::Increment: + if (GetActive()) + stateMgr.GetCameraBlurPass(3).SetBlur(x34_type, x38_amount, x40_timeIn); + break; + case EScriptObjectMessage::Decrement: + if (GetActive()) + stateMgr.GetCameraBlurPass(3).DisableBlur(x44_timeOut); + break; + default: + break; + } } -void CScriptCameraBlurKeyframe::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CEntity::AcceptScriptMsg(msg, objId, stateMgr); +void CScriptCameraBlurKeyframe::Accept(IVisitor& visitor) { visitor.Visit(this); } - switch (msg) - { - case EScriptObjectMessage::Increment: - if (GetActive()) - stateMgr.GetCameraBlurPass(3).SetBlur(x34_type, x38_amount, x40_timeIn); - break; - case EScriptObjectMessage::Decrement: - if (GetActive()) - stateMgr.GetCameraBlurPass(3).DisableBlur(x44_timeOut); - break; - default: break; - } -} - -void CScriptCameraBlurKeyframe::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptCameraBlurKeyframe.hpp b/Runtime/World/CScriptCameraBlurKeyframe.hpp index 3c6ad39da..94d4c746c 100644 --- a/Runtime/World/CScriptCameraBlurKeyframe.hpp +++ b/Runtime/World/CScriptCameraBlurKeyframe.hpp @@ -3,23 +3,19 @@ #include "CEntity.hpp" #include "Camera/CCameraFilter.hpp" -namespace urde -{ -class CScriptCameraBlurKeyframe : public CEntity -{ - EBlurType x34_type; - float x38_amount; - u32 x3c_; - float x40_timeIn; - float x44_timeOut; +namespace urde { +class CScriptCameraBlurKeyframe : public CEntity { + EBlurType x34_type; + float x38_amount; + u32 x3c_; + float x40_timeIn; + float x44_timeOut; + public: - CScriptCameraBlurKeyframe(TUniqueId uid, std::string_view name, - const CEntityInfo& info, EBlurType type, - float amount, u32 unk, float timeIn, - float timeOut, bool active); + CScriptCameraBlurKeyframe(TUniqueId uid, std::string_view name, const CEntityInfo& info, EBlurType type, float amount, + u32 unk, float timeIn, float timeOut, bool active); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); - void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Accept(IVisitor& visitor); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptCameraFilterKeyframe.cpp b/Runtime/World/CScriptCameraFilterKeyframe.cpp index 06b6d0416..692bad7c9 100644 --- a/Runtime/World/CScriptCameraFilterKeyframe.cpp +++ b/Runtime/World/CScriptCameraFilterKeyframe.cpp @@ -2,42 +2,42 @@ #include "TCastTo.hpp" #include "CStateManager.hpp" -namespace urde -{ -CScriptCameraFilterKeyframe::CScriptCameraFilterKeyframe(TUniqueId uid, std::string_view name, - const CEntityInfo& info, EFilterType type, EFilterShape shape, - u32 filterIdx, u32 unk, const zeus::CColor& color, - float timeIn, float timeOut, CAssetId txtr, bool active) -: CEntity(uid, info, active, name), x34_type(type), x38_shape(shape), x3c_filterIdx(filterIdx), x40_(unk), - x44_color(color), x48_timeIn(timeIn), x4c_timeOut(timeOut), x50_txtr(txtr) -{ +namespace urde { +CScriptCameraFilterKeyframe::CScriptCameraFilterKeyframe(TUniqueId uid, std::string_view name, const CEntityInfo& info, + EFilterType type, EFilterShape shape, u32 filterIdx, u32 unk, + const zeus::CColor& color, float timeIn, float timeOut, + CAssetId txtr, bool active) +: CEntity(uid, info, active, name) +, x34_type(type) +, x38_shape(shape) +, x3c_filterIdx(filterIdx) +, x40_(unk) +, x44_color(color) +, x48_timeIn(timeIn) +, x4c_timeOut(timeOut) +, x50_txtr(txtr) {} + +void CScriptCameraFilterKeyframe::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + switch (msg) { + case EScriptObjectMessage::Increment: + if (GetActive()) + stateMgr.GetCameraFilterPass(x3c_filterIdx).SetFilter(x34_type, x38_shape, x48_timeIn, x44_color, x50_txtr); + break; + case EScriptObjectMessage::Decrement: + if (GetActive()) + stateMgr.GetCameraFilterPass(x3c_filterIdx).DisableFilter(x4c_timeOut); + break; + case EScriptObjectMessage::Deactivate: + if (GetActive()) + stateMgr.GetCameraFilterPass(x3c_filterIdx).DisableFilter(0.f); + break; + default: + break; + } + + CEntity::AcceptScriptMsg(msg, objId, stateMgr); } -void CScriptCameraFilterKeyframe::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - switch (msg) - { - case EScriptObjectMessage::Increment: - if (GetActive()) - stateMgr.GetCameraFilterPass(x3c_filterIdx).SetFilter(x34_type, x38_shape, x48_timeIn, x44_color, x50_txtr); - break; - case EScriptObjectMessage::Decrement: - if (GetActive()) - stateMgr.GetCameraFilterPass(x3c_filterIdx).DisableFilter(x4c_timeOut); - break; - case EScriptObjectMessage::Deactivate: - if (GetActive()) - stateMgr.GetCameraFilterPass(x3c_filterIdx).DisableFilter(0.f); - break; - default: break; - } +void CScriptCameraFilterKeyframe::Accept(IVisitor& visitor) { visitor.Visit(this); } - CEntity::AcceptScriptMsg(msg, objId, stateMgr); -} - -void CScriptCameraFilterKeyframe::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptCameraFilterKeyframe.hpp b/Runtime/World/CScriptCameraFilterKeyframe.hpp index bd43cc4c6..5457e1c5f 100644 --- a/Runtime/World/CScriptCameraFilterKeyframe.hpp +++ b/Runtime/World/CScriptCameraFilterKeyframe.hpp @@ -4,27 +4,23 @@ #include "zeus/CColor.hpp" #include "Camera/CCameraFilter.hpp" -namespace urde -{ -class CScriptCameraFilterKeyframe : public CEntity -{ - EFilterType x34_type; - EFilterShape x38_shape; - u32 x3c_filterIdx; - u32 x40_; - zeus::CColor x44_color; - float x48_timeIn; - float x4c_timeOut; - CAssetId x50_txtr; +namespace urde { +class CScriptCameraFilterKeyframe : public CEntity { + EFilterType x34_type; + EFilterShape x38_shape; + u32 x3c_filterIdx; + u32 x40_; + zeus::CColor x44_color; + float x48_timeIn; + float x4c_timeOut; + CAssetId x50_txtr; public: - CScriptCameraFilterKeyframe(TUniqueId uid, std::string_view name, - const CEntityInfo& info, EFilterType type, EFilterShape shape, - u32 filterIdx, u32 unk, const zeus::CColor& color, - float timeIn, float timeOut, CAssetId txtr, bool active); + CScriptCameraFilterKeyframe(TUniqueId uid, std::string_view name, const CEntityInfo& info, EFilterType type, + EFilterShape shape, u32 filterIdx, u32 unk, const zeus::CColor& color, float timeIn, + float timeOut, CAssetId txtr, bool active); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); - void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Accept(IVisitor& visitor); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptCameraHint.cpp b/Runtime/World/CScriptCameraHint.cpp index 96e0ea17a..fdc61f13c 100644 --- a/Runtime/World/CScriptCameraHint.cpp +++ b/Runtime/World/CScriptCameraHint.cpp @@ -3,8 +3,7 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptCameraHint::CScriptCameraHint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, s32 priority, @@ -15,126 +14,103 @@ CScriptCameraHint::CScriptCameraHint(TUniqueId uid, std::string_view name, const float clampVelRange, float clampRotRange, float elevation, float interpolateTime, float clampVelTime, float controlInterpDur) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic), - CActorParameters::None(), kInvalidUniqueId), xe8_priority(priority), - xec_hint(overrideFlags, behaviour, minDist, maxDist, backwardsDist, lookAtOffset, chaseLookAtOffset, ballToCam, - fov, attitudeRange, azimuthRange, anglePerSecond, clampVelRange, clampRotRange, elevation, interpolateTime, - clampVelTime, controlInterpDur), - x168_origXf(xf) -{ -} + CActorParameters::None(), kInvalidUniqueId) +, xe8_priority(priority) +, xec_hint(overrideFlags, behaviour, minDist, maxDist, backwardsDist, lookAtOffset, chaseLookAtOffset, ballToCam, fov, + attitudeRange, azimuthRange, anglePerSecond, clampVelRange, clampRotRange, elevation, interpolateTime, + clampVelTime, controlInterpDur) +, x168_origXf(xf) {} -void CScriptCameraHint::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptCameraHint::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptCameraHint::InitializeInArea(CStateManager& mgr) -{ - x164_delegatedCamera = kInvalidUniqueId; - for (CEntity* ent : mgr.GetAllObjectList()) - { - for (const SConnection& conn : ent->GetConnectionList()) - { - if (mgr.GetIdForScript(conn.x8_objId) != GetUniqueId()) - continue; - if (conn.x4_msg != EScriptObjectMessage::Increment && - conn.x4_msg != EScriptObjectMessage::Decrement) - continue; +void CScriptCameraHint::InitializeInArea(CStateManager& mgr) { + x164_delegatedCamera = kInvalidUniqueId; + for (CEntity* ent : mgr.GetAllObjectList()) { + for (const SConnection& conn : ent->GetConnectionList()) { + if (mgr.GetIdForScript(conn.x8_objId) != GetUniqueId()) + continue; + if (conn.x4_msg != EScriptObjectMessage::Increment && conn.x4_msg != EScriptObjectMessage::Decrement) + continue; - for (auto it = ent->GetConnectionList().begin() ; it != ent->GetConnectionList().cend() ; ++it) - { - const SConnection& conn2 = *it; - if (conn2.x4_msg != EScriptObjectMessage::Increment && - conn2.x4_msg != EScriptObjectMessage::Decrement) - continue; - TUniqueId id = mgr.GetIdForScript(conn2.x8_objId); - if (TCastToPtr(mgr.ObjectById(id)) || - TCastToPtr(mgr.ObjectById((id)))) - { - ent->ConnectionList().erase(it); - if (x164_delegatedCamera != id) - x164_delegatedCamera = id; - break; - } - } - break; + for (auto it = ent->GetConnectionList().begin(); it != ent->GetConnectionList().cend(); ++it) { + const SConnection& conn2 = *it; + if (conn2.x4_msg != EScriptObjectMessage::Increment && conn2.x4_msg != EScriptObjectMessage::Decrement) + continue; + TUniqueId id = mgr.GetIdForScript(conn2.x8_objId); + if (TCastToPtr(mgr.ObjectById(id)) || TCastToPtr(mgr.ObjectById((id)))) { + ent->ConnectionList().erase(it); + if (x164_delegatedCamera != id) + x164_delegatedCamera = id; + break; } + } + break; } + } } -void CScriptCameraHint::AddHelper(TUniqueId id) -{ - auto search = std::find_if(x150_helpers.begin(), x150_helpers.end(), - [id](TUniqueId tid) { return tid == id; }); - if (search == x150_helpers.end()) - x150_helpers.push_back(id); +void CScriptCameraHint::AddHelper(TUniqueId id) { + auto search = std::find_if(x150_helpers.begin(), x150_helpers.end(), [id](TUniqueId tid) { return tid == id; }); + if (search == x150_helpers.end()) + x150_helpers.push_back(id); } -void CScriptCameraHint::RemoveHelper(TUniqueId id) -{ - auto search = std::find_if(x150_helpers.begin(), x150_helpers.end(), - [id](TUniqueId tid) { return tid == id; }); - if (search != x150_helpers.end()) - x150_helpers.erase(search); - else - x150_helpers.pop_front(); +void CScriptCameraHint::RemoveHelper(TUniqueId id) { + auto search = std::find_if(x150_helpers.begin(), x150_helpers.end(), [id](TUniqueId tid) { return tid == id; }); + if (search != x150_helpers.end()) + x150_helpers.erase(search); + else + x150_helpers.pop_front(); } -void CScriptCameraHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Deleted: - case EScriptObjectMessage::Deactivate: - mgr.GetCameraManager()->DeleteCameraHint(GetUniqueId(), mgr); - break; - case EScriptObjectMessage::InitializedInArea: - InitializeInArea(mgr); - break; +void CScriptCameraHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Deleted: + case EScriptObjectMessage::Deactivate: + mgr.GetCameraManager()->DeleteCameraHint(GetUniqueId(), mgr); + break; + case EScriptObjectMessage::InitializedInArea: + InitializeInArea(mgr); + break; + default: + break; + } + + if (GetActive()) { + switch (msg) { + case EScriptObjectMessage::Increment: + AddHelper(sender); + mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr); + x166_inactive = false; + break; + case EScriptObjectMessage::Decrement: + RemoveHelper(sender); + mgr.GetCameraManager()->AddInactiveCameraHint(GetUniqueId(), mgr); + break; default: - break; + break; } + } - if (GetActive()) - { - switch (msg) - { - case EScriptObjectMessage::Increment: - AddHelper(sender); - mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr); - x166_inactive = false; - break; - case EScriptObjectMessage::Decrement: - RemoveHelper(sender); - mgr.GetCameraManager()->AddInactiveCameraHint(GetUniqueId(), mgr); - break; - default: - break; - } + if (msg == EScriptObjectMessage::Follow) { + if (!GetActive()) { + if (TCastToConstPtr act = mgr.GetObjectById(sender)) { + zeus::CVector3f followerToThisFlat = x168_origXf.origin - act->GetTranslation(); + followerToThisFlat.z() = 0.f; + if (followerToThisFlat.canBeNormalized()) + followerToThisFlat.normalize(); + else + followerToThisFlat = act->GetTransform().basis[1]; + zeus::CVector3f target = act->GetTranslation() + followerToThisFlat; + target.z() = x168_origXf.origin.z() + followerToThisFlat.z(); + SetTransform(zeus::lookAt(act->GetTranslation(), target)); + } } + AddHelper(sender); + mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr); + } - if (msg == EScriptObjectMessage::Follow) - { - if (!GetActive()) - { - if (TCastToConstPtr act = mgr.GetObjectById(sender)) - { - zeus::CVector3f followerToThisFlat = x168_origXf.origin - act->GetTranslation(); - followerToThisFlat.z() = 0.f; - if (followerToThisFlat.canBeNormalized()) - followerToThisFlat.normalize(); - else - followerToThisFlat = act->GetTransform().basis[1]; - zeus::CVector3f target = act->GetTranslation() + followerToThisFlat; - target.z() = x168_origXf.origin.z() + followerToThisFlat.z(); - SetTransform(zeus::lookAt(act->GetTranslation(), target)); - } - } - AddHelper(sender); - mgr.GetCameraManager()->AddActiveCameraHint(GetUniqueId(), mgr); - } - - CActor::AcceptScriptMsg(msg, sender, mgr); + CActor::AcceptScriptMsg(msg, sender, mgr); } -} +} // namespace urde diff --git a/Runtime/World/CScriptCameraHint.hpp b/Runtime/World/CScriptCameraHint.hpp index f1598d05b..fcbe47a63 100644 --- a/Runtime/World/CScriptCameraHint.hpp +++ b/Runtime/World/CScriptCameraHint.hpp @@ -3,94 +3,103 @@ #include "CActor.hpp" #include "Camera/CBallCamera.hpp" -namespace urde -{ +namespace urde { -class CCameraHint -{ - u32 x4_overrideFlags; - CBallCamera::EBallCameraBehaviour x8_behaviour; - float xc_minDist; - float x10_maxDist; - float x14_backwardsDist; - zeus::CVector3f x18_lookAtOffset; - zeus::CVector3f x24_chaseLookAtOffset; - zeus::CVector3f x30_ballToCam; - float x3c_fov; - float x40_attitudeRange; - float x44_azimuthRange; - float x48_anglePerSecond; - float x4c_clampVelRange; - float x50_clampRotRange; - float x54_elevation; - float x58_interpolateTime; - float x5c_clampVelTime; - float x60_controlInterpDur; +class CCameraHint { + u32 x4_overrideFlags; + CBallCamera::EBallCameraBehaviour x8_behaviour; + float xc_minDist; + float x10_maxDist; + float x14_backwardsDist; + zeus::CVector3f x18_lookAtOffset; + zeus::CVector3f x24_chaseLookAtOffset; + zeus::CVector3f x30_ballToCam; + float x3c_fov; + float x40_attitudeRange; + float x44_azimuthRange; + float x48_anglePerSecond; + float x4c_clampVelRange; + float x50_clampRotRange; + float x54_elevation; + float x58_interpolateTime; + float x5c_clampVelTime; + float x60_controlInterpDur; public: - CCameraHint(u32 overrideFlags, CBallCamera::EBallCameraBehaviour behaviour, float minDist, float maxDist, - float backwardsDist, const zeus::CVector3f& lookAtOffset, const zeus::CVector3f& chaseLookAtOffset, - const zeus::CVector3f& ballToCam, float fov, float attitudeRange, float azimuthRange, - float anglePerSecond, float clampVelRange, float clampRotRange, float elevation, float interpolateTime, - float clampVelTime, float controlInterpDur) - : x4_overrideFlags(overrideFlags), x8_behaviour(behaviour), xc_minDist(minDist), x10_maxDist(maxDist), - x14_backwardsDist(backwardsDist), x18_lookAtOffset(lookAtOffset), x24_chaseLookAtOffset(chaseLookAtOffset), - x30_ballToCam(ballToCam), x3c_fov(fov), x40_attitudeRange(attitudeRange), x44_azimuthRange(azimuthRange), - x48_anglePerSecond(anglePerSecond), x4c_clampVelRange(clampVelRange), x50_clampRotRange(clampRotRange), - x54_elevation(elevation), x58_interpolateTime(interpolateTime), x5c_clampVelTime(clampVelTime), - x60_controlInterpDur(controlInterpDur) {} + CCameraHint(u32 overrideFlags, CBallCamera::EBallCameraBehaviour behaviour, float minDist, float maxDist, + float backwardsDist, const zeus::CVector3f& lookAtOffset, const zeus::CVector3f& chaseLookAtOffset, + const zeus::CVector3f& ballToCam, float fov, float attitudeRange, float azimuthRange, + float anglePerSecond, float clampVelRange, float clampRotRange, float elevation, float interpolateTime, + float clampVelTime, float controlInterpDur) + : x4_overrideFlags(overrideFlags) + , x8_behaviour(behaviour) + , xc_minDist(minDist) + , x10_maxDist(maxDist) + , x14_backwardsDist(backwardsDist) + , x18_lookAtOffset(lookAtOffset) + , x24_chaseLookAtOffset(chaseLookAtOffset) + , x30_ballToCam(ballToCam) + , x3c_fov(fov) + , x40_attitudeRange(attitudeRange) + , x44_azimuthRange(azimuthRange) + , x48_anglePerSecond(anglePerSecond) + , x4c_clampVelRange(clampVelRange) + , x50_clampRotRange(clampRotRange) + , x54_elevation(elevation) + , x58_interpolateTime(interpolateTime) + , x5c_clampVelTime(clampVelTime) + , x60_controlInterpDur(controlInterpDur) {} - u32 GetOverrideFlags() const { return x4_overrideFlags; } - CBallCamera::EBallCameraBehaviour GetBehaviourType() const { return x8_behaviour; } - float GetMinDist() const { return xc_minDist; } - float GetMaxDist() const { return x10_maxDist; } - float GetBackwardsDist() const { return x14_backwardsDist; } - const zeus::CVector3f& GetLookAtOffset() const { return x18_lookAtOffset; } - const zeus::CVector3f& GetChaseLookAtOffset() const { return x24_chaseLookAtOffset; } - const zeus::CVector3f& GetBallToCam() const { return x30_ballToCam; } - float GetFov() const { return x3c_fov; } - float GetAttitudeRange() const { return x40_attitudeRange; } - float GetAzimuthRange() const { return x44_azimuthRange; } - float GetAnglePerSecond() const { return x48_anglePerSecond; } - float GetClampVelRange() const { return x4c_clampVelRange; } - float GetClampRotRange() const { return x50_clampRotRange; } - float GetElevation() const { return x54_elevation; } - float GetInterpolateTime() const { return x58_interpolateTime; } - float GetClampVelTime() const { return x5c_clampVelTime; } - float GetControlInterpDur() const { return x60_controlInterpDur; } + u32 GetOverrideFlags() const { return x4_overrideFlags; } + CBallCamera::EBallCameraBehaviour GetBehaviourType() const { return x8_behaviour; } + float GetMinDist() const { return xc_minDist; } + float GetMaxDist() const { return x10_maxDist; } + float GetBackwardsDist() const { return x14_backwardsDist; } + const zeus::CVector3f& GetLookAtOffset() const { return x18_lookAtOffset; } + const zeus::CVector3f& GetChaseLookAtOffset() const { return x24_chaseLookAtOffset; } + const zeus::CVector3f& GetBallToCam() const { return x30_ballToCam; } + float GetFov() const { return x3c_fov; } + float GetAttitudeRange() const { return x40_attitudeRange; } + float GetAzimuthRange() const { return x44_azimuthRange; } + float GetAnglePerSecond() const { return x48_anglePerSecond; } + float GetClampVelRange() const { return x4c_clampVelRange; } + float GetClampRotRange() const { return x50_clampRotRange; } + float GetElevation() const { return x54_elevation; } + float GetInterpolateTime() const { return x58_interpolateTime; } + float GetClampVelTime() const { return x5c_clampVelTime; } + float GetControlInterpDur() const { return x60_controlInterpDur; } }; -class CScriptCameraHint : public CActor -{ - s32 xe8_priority; - CCameraHint xec_hint; - rstl::reserved_vector x150_helpers; - TUniqueId x164_delegatedCamera = kInvalidUniqueId; - bool x166_inactive = false; - zeus::CTransform x168_origXf; - void InitializeInArea(CStateManager& mgr); - void AddHelper(TUniqueId id); - void RemoveHelper(TUniqueId id); +class CScriptCameraHint : public CActor { + s32 xe8_priority; + CCameraHint xec_hint; + rstl::reserved_vector x150_helpers; + TUniqueId x164_delegatedCamera = kInvalidUniqueId; + bool x166_inactive = false; + zeus::CTransform x168_origXf; + void InitializeInArea(CStateManager& mgr); + void AddHelper(TUniqueId id); + void RemoveHelper(TUniqueId id); + public: - CScriptCameraHint(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - bool active, s32 priority, CBallCamera::EBallCameraBehaviour behaviour, u32 overrideFlags, - float minDist, float maxDist, float backwardsDist, const zeus::CVector3f& lookAtOffset, - const zeus::CVector3f& chaseLookAtOffset, const zeus::CVector3f& ballToCam, float fov, - float attitudeRange, float azimuthRange, float anglePerSecond, float clampVelRange, - float clampRotRange, float elevation, float interpolateTime, float clampVelTime, - float controlInterpDur); + CScriptCameraHint(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, + s32 priority, CBallCamera::EBallCameraBehaviour behaviour, u32 overrideFlags, float minDist, + float maxDist, float backwardsDist, const zeus::CVector3f& lookAtOffset, + const zeus::CVector3f& chaseLookAtOffset, const zeus::CVector3f& ballToCam, float fov, + float attitudeRange, float azimuthRange, float anglePerSecond, float clampVelRange, + float clampRotRange, float elevation, float interpolateTime, float clampVelTime, + float controlInterpDur); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - void ClearIdList() { x150_helpers.clear(); } - void SetInactive(bool inactive) { x166_inactive = inactive; } - bool GetInactive() const { return x166_inactive; } - size_t GetHelperCount() const { return x150_helpers.size(); } - TUniqueId GetFirstHelper() const { return x150_helpers.empty() ? kInvalidUniqueId : x150_helpers[0]; } - s32 GetPriority() const { return xe8_priority; } - const CCameraHint& GetHint() const { return xec_hint; } - TUniqueId GetDelegatedCamera() const { return x164_delegatedCamera; } + void ClearIdList() { x150_helpers.clear(); } + void SetInactive(bool inactive) { x166_inactive = inactive; } + bool GetInactive() const { return x166_inactive; } + size_t GetHelperCount() const { return x150_helpers.size(); } + TUniqueId GetFirstHelper() const { return x150_helpers.empty() ? kInvalidUniqueId : x150_helpers[0]; } + s32 GetPriority() const { return xe8_priority; } + const CCameraHint& GetHint() const { return xec_hint; } + TUniqueId GetDelegatedCamera() const { return x164_delegatedCamera; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptCameraHintTrigger.cpp b/Runtime/World/CScriptCameraHintTrigger.cpp index db0ea3713..d4099eeb0 100644 --- a/Runtime/World/CScriptCameraHintTrigger.cpp +++ b/Runtime/World/CScriptCameraHintTrigger.cpp @@ -2,8 +2,7 @@ #include "CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptCameraHintTrigger::CScriptCameraHintTrigger(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& scale, @@ -11,15 +10,11 @@ CScriptCameraHintTrigger::CScriptCameraHintTrigger(TUniqueId uid, bool active, s : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Trigger), CActorParameters::None(), kInvalidUniqueId) , xe8_obb(xf, scale) -, x124_scale(scale) -{ - x130_24_ = b2; - x130_25_ = b3; +, x124_scale(scale) { + x130_24_ = b2; + x130_25_ = b3; } -void CScriptCameraHintTrigger::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptCameraHintTrigger::Accept(IVisitor& visitor) { visitor.Visit(this); } -} +} // namespace urde diff --git a/Runtime/World/CScriptCameraHintTrigger.hpp b/Runtime/World/CScriptCameraHintTrigger.hpp index 66d6c44bd..383908561 100644 --- a/Runtime/World/CScriptCameraHintTrigger.hpp +++ b/Runtime/World/CScriptCameraHintTrigger.hpp @@ -3,27 +3,24 @@ #include "CActor.hpp" #include "zeus/COBBox.hpp" -namespace urde -{ -class CScriptCameraHintTrigger : public CActor -{ - zeus::COBBox xe8_obb; - zeus::CVector3f x124_scale; - union { - struct - { - bool x130_24_ : 1; - bool x130_25_ : 1; - bool x130_26_ : 1; - bool x130_27_ : 1; - }; - u8 _dummy = 0; +namespace urde { +class CScriptCameraHintTrigger : public CActor { + zeus::COBBox xe8_obb; + zeus::CVector3f x124_scale; + union { + struct { + bool x130_24_ : 1; + bool x130_25_ : 1; + bool x130_26_ : 1; + bool x130_27_ : 1; }; + u8 _dummy = 0; + }; public: - CScriptCameraHintTrigger(TUniqueId, bool, std::string_view name, const CEntityInfo&, const zeus::CVector3f&, - const zeus::CTransform&, bool, bool); + CScriptCameraHintTrigger(TUniqueId, bool, std::string_view name, const CEntityInfo&, const zeus::CVector3f&, + const zeus::CTransform&, bool, bool); - void Accept(IVisitor& visitor); + void Accept(IVisitor& visitor); }; -} +} // namespace urde diff --git a/Runtime/World/CScriptCameraPitchVolume.cpp b/Runtime/World/CScriptCameraPitchVolume.cpp index 14cacbd99..527702270 100644 --- a/Runtime/World/CScriptCameraPitchVolume.cpp +++ b/Runtime/World/CScriptCameraPitchVolume.cpp @@ -7,8 +7,7 @@ #include "Particle/CGenDescription.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { const zeus::CVector3f CScriptCameraPitchVolume::skScaleFactor = zeus::CVector3f(0.5f); CScriptCameraPitchVolume::CScriptCameraPitchVolume(TUniqueId uid, bool active, std::string_view name, @@ -21,55 +20,45 @@ CScriptCameraPitchVolume::CScriptCameraPitchVolume(TUniqueId uid, bool active, s , x124_upPitch(r1) , x128_downPitch(r2) , x12c_scale(scale * skScaleFactor) -, x138_maxInterpDistance(maxInterpDistance) -{ +, x138_maxInterpDistance(maxInterpDistance) {} + +void CScriptCameraPitchVolume::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptCameraPitchVolume::Think(float, CStateManager& mgr) { + if (!GetActive()) + return; + + if (x13c_24_entered && !x13c_25_occupied) + Entered(mgr); + else if (!x13c_24_entered && x13c_25_occupied) + Exited(mgr); + + x13c_24_entered = false; } -void CScriptCameraPitchVolume::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +std::experimental::optional CScriptCameraPitchVolume::GetTouchBounds() const { + return {xe8_obbox.calculateAABox(zeus::CTransform::Identity())}; } -void CScriptCameraPitchVolume::Think(float, CStateManager& mgr) -{ - if (!GetActive()) - return; +void CScriptCameraPitchVolume::Touch(CActor& act, CStateManager& mgr) { + TCastToPtr pl(act); + if (!pl) + return; - if (x13c_24_entered && !x13c_25_occupied) - Entered(mgr); - else if (!x13c_24_entered && x13c_25_occupied) - Exited(mgr); + auto plBox = pl->GetTouchBounds(); + if (!plBox) + return; - x13c_24_entered = false; + x13c_24_entered = xe8_obbox.AABoxIntersectsBox(plBox.value()); } -std::experimental::optional CScriptCameraPitchVolume::GetTouchBounds() const -{ - return {xe8_obbox.calculateAABox(zeus::CTransform::Identity())}; +void CScriptCameraPitchVolume::Entered(urde::CStateManager& mgr) { + x13c_25_occupied = true; + mgr.GetCameraManager()->GetFirstPersonCamera()->SetScriptPitchId(GetUniqueId()); } -void CScriptCameraPitchVolume::Touch(CActor& act, CStateManager& mgr) -{ - TCastToPtr pl(act); - if (!pl) - return; - - auto plBox = pl->GetTouchBounds(); - if (!plBox) - return; - - x13c_24_entered = xe8_obbox.AABoxIntersectsBox(plBox.value()); -} - -void CScriptCameraPitchVolume::Entered(urde::CStateManager& mgr) -{ - x13c_25_occupied = true; - mgr.GetCameraManager()->GetFirstPersonCamera()->SetScriptPitchId(GetUniqueId()); -} - -void CScriptCameraPitchVolume::Exited(CStateManager& mgr) -{ - x13c_25_occupied = false; - mgr.GetCameraManager()->GetFirstPersonCamera()->SetScriptPitchId(kInvalidUniqueId); -} +void CScriptCameraPitchVolume::Exited(CStateManager& mgr) { + x13c_25_occupied = false; + mgr.GetCameraManager()->GetFirstPersonCamera()->SetScriptPitchId(kInvalidUniqueId); } +} // namespace urde diff --git a/Runtime/World/CScriptCameraPitchVolume.hpp b/Runtime/World/CScriptCameraPitchVolume.hpp index 225d5a31e..91a199feb 100644 --- a/Runtime/World/CScriptCameraPitchVolume.hpp +++ b/Runtime/World/CScriptCameraPitchVolume.hpp @@ -4,39 +4,36 @@ #include "zeus/CRelAngle.hpp" #include "zeus/COBBox.hpp" -namespace urde -{ -class CScriptCameraPitchVolume : public CActor -{ - static const zeus::CVector3f skScaleFactor; - zeus::COBBox xe8_obbox; - zeus::CRelAngle x124_upPitch; - zeus::CRelAngle x128_downPitch; - zeus::CVector3f x12c_scale; - float x138_maxInterpDistance; +namespace urde { +class CScriptCameraPitchVolume : public CActor { + static const zeus::CVector3f skScaleFactor; + zeus::COBBox xe8_obbox; + zeus::CRelAngle x124_upPitch; + zeus::CRelAngle x128_downPitch; + zeus::CVector3f x12c_scale; + float x138_maxInterpDistance; - union { - struct - { - bool x13c_24_entered : 1; - bool x13c_25_occupied : 1; - }; - u32 _dummy = 0; + union { + struct { + bool x13c_24_entered : 1; + bool x13c_25_occupied : 1; }; + u32 _dummy = 0; + }; public: - CScriptCameraPitchVolume(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, - const zeus::CTransform&, const zeus::CRelAngle&, const zeus::CRelAngle&, float); + CScriptCameraPitchVolume(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, + const zeus::CTransform&, const zeus::CRelAngle&, const zeus::CRelAngle&, float); - void Accept(IVisitor& visitor); - void Think(float, CStateManager&); - std::experimental::optional GetTouchBounds() const; - void Touch(CActor&, CStateManager&); - float GetUpPitch() const { return x124_upPitch; } - float GetDownPitch() const { return x128_downPitch; } - const zeus::CVector3f& GetScale() const { return x12c_scale; } - float GetMaxInterpolationDistance() const { return x138_maxInterpDistance; } - void Entered(CStateManager&); - void Exited(CStateManager&); + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + std::experimental::optional GetTouchBounds() const; + void Touch(CActor&, CStateManager&); + float GetUpPitch() const { return x124_upPitch; } + float GetDownPitch() const { return x128_downPitch; } + const zeus::CVector3f& GetScale() const { return x12c_scale; } + float GetMaxInterpolationDistance() const { return x138_maxInterpDistance; } + void Entered(CStateManager&); + void Exited(CStateManager&); }; -} +} // namespace urde diff --git a/Runtime/World/CScriptCameraShaker.cpp b/Runtime/World/CScriptCameraShaker.cpp index 45fae00a5..d50bc852b 100644 --- a/Runtime/World/CScriptCameraShaker.cpp +++ b/Runtime/World/CScriptCameraShaker.cpp @@ -3,46 +3,37 @@ #include "CStateManager.hpp" #include "CWorld.hpp" -namespace urde -{ +namespace urde { -CScriptCameraShaker::CScriptCameraShaker(TUniqueId uid, std::string_view name, const CEntityInfo& info, - bool active, const CCameraShakeData& shakeData) -: CEntity(uid, info, active, name), x34_shakeData(shakeData) -{} +CScriptCameraShaker::CScriptCameraShaker(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, + const CCameraShakeData& shakeData) +: CEntity(uid, info, active, name), x34_shakeData(shakeData) {} -void CScriptCameraShaker::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptCameraShaker::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptCameraShaker::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + switch (msg) { + case EScriptObjectMessage::Action: { + TAreaId aid = GetAreaIdAlways(); + if (GetActive() && aid != kInvalidAreaId) { + const CGameArea* area = stateMgr.GetWorld()->GetAreaAlways(aid); + CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; + if (area->IsPostConstructed()) + occState = area->GetPostConstructed()->x10dc_occlusionState; + if (occState == CGameArea::EOcclusionState::Visible) + x34_shakeData.SetShakerId(stateMgr.GetCameraManager()->AddCameraShaker(x34_shakeData, false)); + } + break; + } + case EScriptObjectMessage::Deactivate: { + if (GetActive()) + stateMgr.GetCameraManager()->RemoveCameraShaker(x34_shakeData.GetShakerId()); + break; + } + default: + break; + } + CEntity::AcceptScriptMsg(msg, objId, stateMgr); } -void CScriptCameraShaker::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - switch (msg) - { - case EScriptObjectMessage::Action: - { - TAreaId aid = GetAreaIdAlways(); - if (GetActive() && aid != kInvalidAreaId) - { - const CGameArea* area = stateMgr.GetWorld()->GetAreaAlways(aid); - CGameArea::EOcclusionState occState = CGameArea::EOcclusionState::Occluded; - if (area->IsPostConstructed()) - occState = area->GetPostConstructed()->x10dc_occlusionState; - if (occState == CGameArea::EOcclusionState::Visible) - x34_shakeData.SetShakerId(stateMgr.GetCameraManager()->AddCameraShaker(x34_shakeData, false)); - } - break; - } - case EScriptObjectMessage::Deactivate: - { - if (GetActive()) - stateMgr.GetCameraManager()->RemoveCameraShaker(x34_shakeData.GetShakerId()); - break; - } - default: break; - } - CEntity::AcceptScriptMsg(msg, objId, stateMgr); -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptCameraShaker.hpp b/Runtime/World/CScriptCameraShaker.hpp index 9c72ac6c5..227538d2a 100644 --- a/Runtime/World/CScriptCameraShaker.hpp +++ b/Runtime/World/CScriptCameraShaker.hpp @@ -3,18 +3,16 @@ #include "CEntity.hpp" #include "Camera/CCameraShakeData.hpp" -namespace urde -{ +namespace urde { + +class CScriptCameraShaker : public CEntity { + CCameraShakeData x34_shakeData; -class CScriptCameraShaker : public CEntity -{ - CCameraShakeData x34_shakeData; public: - CScriptCameraShaker(TUniqueId uid, std::string_view name, const CEntityInfo& info, - bool active, const CCameraShakeData& shakeData); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + CScriptCameraShaker(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, + const CCameraShakeData& shakeData); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptCameraWaypoint.cpp b/Runtime/World/CScriptCameraWaypoint.cpp index 8812444d5..6f0109b14 100644 --- a/Runtime/World/CScriptCameraWaypoint.cpp +++ b/Runtime/World/CScriptCameraWaypoint.cpp @@ -3,49 +3,38 @@ #include "TCastTo.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { CScriptCameraWaypoint::CScriptCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, float hfov, u32 w1) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic), CActorParameters::None(), kInvalidUniqueId) , xe8_hfov(hfov) -, xec_(w1) -{ +, xec_(w1) {} +void CScriptCameraWaypoint::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptCameraWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); + if (!GetActive() && msg == EScriptObjectMessage::Arrived) + SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); } -void CScriptCameraWaypoint::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CScriptCameraWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); - if (!GetActive() && msg == EScriptObjectMessage::Arrived) - SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); -} - -TUniqueId CScriptCameraWaypoint::GetRandomNextWaypointId(CStateManager& mgr) const -{ - std::vector candidateIds; - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) - { - TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); - if (uid == kInvalidUniqueId) - continue; - candidateIds.push_back(uid); - } +TUniqueId CScriptCameraWaypoint::GetRandomNextWaypointId(CStateManager& mgr) const { + std::vector candidateIds; + for (const SConnection& conn : x20_conns) { + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) { + TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); + if (uid == kInvalidUniqueId) + continue; + candidateIds.push_back(uid); } + } - if (candidateIds.empty()) - return kInvalidUniqueId; + if (candidateIds.empty()) + return kInvalidUniqueId; - return candidateIds[mgr.GetActiveRandom()->Range(0, s32(candidateIds.size() - 1))]; + return candidateIds[mgr.GetActiveRandom()->Range(0, s32(candidateIds.size() - 1))]; } -} +} // namespace urde diff --git a/Runtime/World/CScriptCameraWaypoint.hpp b/Runtime/World/CScriptCameraWaypoint.hpp index 072930346..4f468afe0 100644 --- a/Runtime/World/CScriptCameraWaypoint.hpp +++ b/Runtime/World/CScriptCameraWaypoint.hpp @@ -2,24 +2,22 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { + +class CScriptCameraWaypoint : public CActor { + float xe8_hfov; + u32 xec_; -class CScriptCameraWaypoint : public CActor -{ - float xe8_hfov; - u32 xec_; public: - CScriptCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, float hfov, u32); + CScriptCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + bool active, float hfov, u32); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} - void Render(const CStateManager&) const {} - TUniqueId GetRandomNextWaypointId(CStateManager& mgr) const; - float GetHFov() const { return xe8_hfov; } + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} + void Render(const CStateManager&) const {} + TUniqueId GetRandomNextWaypointId(CStateManager& mgr) const; + float GetHFov() const { return xe8_hfov; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptColorModulate.cpp b/Runtime/World/CScriptColorModulate.cpp index b1c35cdad..0f36cd3d5 100644 --- a/Runtime/World/CScriptColorModulate.cpp +++ b/Runtime/World/CScriptColorModulate.cpp @@ -3,336 +3,274 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptColorModulate::CScriptColorModulate(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CColor& colorA, const zeus::CColor& colorB, - EBlendMode blendMode, float timeA2B, float timeB2A, bool doReverse, - bool resetTargetWhenDone, bool depthCompare, bool depthUpdate, - bool depthBackwards, bool active) -: CEntity(uid, info, active, name), - x40_colorA(colorA), - x44_colorB(colorB), - x48_blendMode(blendMode), - x4c_timeA2B(timeA2B), - x50_timeB2A(timeB2A) -{ - x54_24_doReverse = doReverse; - x54_25_resetTargetWhenDone = resetTargetWhenDone; - x54_26_depthCompare = depthCompare; - x54_27_depthUpdate = depthUpdate; - x54_28_depthBackwards = depthBackwards; - x54_29_reversing = false; - x54_30_enable = false; - x54_31_dieOnEnd = false; - x55_24_isFadeOutHelper = false; + const zeus::CColor& colorA, const zeus::CColor& colorB, EBlendMode blendMode, + float timeA2B, float timeB2A, bool doReverse, bool resetTargetWhenDone, + bool depthCompare, bool depthUpdate, bool depthBackwards, bool active) +: CEntity(uid, info, active, name) +, x40_colorA(colorA) +, x44_colorB(colorB) +, x48_blendMode(blendMode) +, x4c_timeA2B(timeA2B) +, x50_timeB2A(timeB2A) { + x54_24_doReverse = doReverse; + x54_25_resetTargetWhenDone = resetTargetWhenDone; + x54_26_depthCompare = depthCompare; + x54_27_depthUpdate = depthUpdate; + x54_28_depthBackwards = depthBackwards; + x54_29_reversing = false; + x54_30_enable = false; + x54_31_dieOnEnd = false; + x55_24_isFadeOutHelper = false; } -void CScriptColorModulate::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptColorModulate::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptColorModulate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) { + CEntity::AcceptScriptMsg(msg, objId, mgr); + + if (!GetActive()) + return; + + switch (msg) { + case EScriptObjectMessage::Increment: + if (x54_29_reversing) { + x38_fadeState = x38_fadeState == EFadeState::A2B ? EFadeState::B2A : EFadeState::A2B; + x54_29_reversing = false; + return; + } else if (x54_30_enable) { + if (x38_fadeState == EFadeState::A2B) + x3c_curTime = 0.f; + else + x3c_curTime = x4c_timeA2B - x4c_timeA2B * (x3c_curTime / x50_timeB2A); + } else + SetTargetFlags(mgr, CalculateFlags(x40_colorA)); + + x54_30_enable = true; + x38_fadeState = EFadeState::A2B; + break; + case EScriptObjectMessage::Decrement: + if (x54_29_reversing) { + x38_fadeState = x38_fadeState == EFadeState::A2B ? EFadeState::B2A : EFadeState::A2B; + x54_29_reversing = false; + return; + } else if (x54_30_enable) { + if (x38_fadeState == EFadeState::A2B) + x3c_curTime = 0.f; + else + x3c_curTime = x50_timeB2A - x50_timeB2A * (x3c_curTime / x4c_timeA2B); + } else + SetTargetFlags(mgr, CalculateFlags(x44_colorB)); + + x54_30_enable = true; + x38_fadeState = EFadeState::B2A; + break; + default: + break; + } } -void CScriptColorModulate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) -{ - CEntity::AcceptScriptMsg(msg, objId, mgr); +void CScriptColorModulate::Think(float dt, CStateManager& mgr) { + if (!GetActive() || !x54_30_enable) + return; - if (!GetActive()) - return; - - switch (msg) - { - case EScriptObjectMessage::Increment: - if (x54_29_reversing) - { - x38_fadeState = x38_fadeState == EFadeState::A2B ? EFadeState::B2A : EFadeState::A2B; - x54_29_reversing = false; - return; - } - else if (x54_30_enable) - { - if (x38_fadeState == EFadeState::A2B) - x3c_curTime = 0.f; - else - x3c_curTime = x4c_timeA2B - x4c_timeA2B * (x3c_curTime / x50_timeB2A); - } - else - SetTargetFlags(mgr, CalculateFlags(x40_colorA)); - - x54_30_enable = true; - x38_fadeState = EFadeState::A2B; - break; - case EScriptObjectMessage::Decrement: - if (x54_29_reversing) - { - x38_fadeState = x38_fadeState == EFadeState::A2B ? EFadeState::B2A : EFadeState::A2B; - x54_29_reversing = false; - return; - } - else if (x54_30_enable) - { - if (x38_fadeState == EFadeState::A2B) - x3c_curTime = 0.f; - else - x3c_curTime = x50_timeB2A - x50_timeB2A * (x3c_curTime / x4c_timeA2B); - } - else - SetTargetFlags(mgr, CalculateFlags(x44_colorB)); - - x54_30_enable = true; - x38_fadeState = EFadeState::B2A; - break; - default: - break; - } -} - -void CScriptColorModulate::Think(float dt, CStateManager& mgr) -{ - if (!GetActive() || !x54_30_enable) - return; - - x3c_curTime += dt; - if (x38_fadeState == EFadeState::A2B) - { - float t; - if (zeus::close_enough(x4c_timeA2B, 0.f)) - t = 1.f; - else - { - t = x3c_curTime / x4c_timeA2B; - if (t >= 1.f) - t = 1.f; - } - - zeus::CColor lerpedCol = zeus::CColor::lerp(x40_colorA, x44_colorB, t); - CModelFlags flags = CalculateFlags(lerpedCol); - SetTargetFlags(mgr, flags); - - if (x3c_curTime <= x4c_timeA2B) - return; - - End(mgr); - } - else if (x38_fadeState == EFadeState::B2A) - { - float t; - if (zeus::close_enough(x50_timeB2A, 0.f)) - t = 1.f; - else - { - t = x3c_curTime / x50_timeB2A; - if (t >= 1.f) - t = 1.f; - } - - zeus::CColor lerpedCol = zeus::CColor::lerp(x44_colorB, x40_colorA, t); - CModelFlags flags = CalculateFlags(lerpedCol); - SetTargetFlags(mgr, flags); - - if (x3c_curTime <= x50_timeB2A) - return; - - End(mgr); - } -} - -CModelFlags CScriptColorModulate::CalculateFlags(const zeus::CColor& col) const -{ - CModelFlags ret; - if (x54_28_depthBackwards) - { - if (x48_blendMode == EBlendMode::Alpha) - { - ret.x0_blendMode = 5; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 3 | 8; - ret.x4_color = col; - } - else if (x48_blendMode == EBlendMode::Additive) - { - ret.x0_blendMode = 7; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 0x8; - ret.x4_color = col; - } - else if (x48_blendMode == EBlendMode::Additive2) - { - ret.x0_blendMode = 8; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 0x8; - ret.x4_color = col; - } - else if (x48_blendMode == EBlendMode::Opaque) - { - ret.x0_blendMode = 1; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 0x8; - ret.x4_color = col; - } - else if (x48_blendMode == EBlendMode::Opaque2) - { - ret.x0_blendMode = 2; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 0x8; - ret.x4_color = col; - } - else - { - ret.x2_flags = 3; - ret.x4_color = zeus::CColor::skWhite; - } - } - else - { - if (x48_blendMode == EBlendMode::Alpha) - { - if (col == zeus::CColor::skWhite) - { - ret.x0_blendMode = 3; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; - ret.x4_color = zeus::CColor::skWhite; - } - else - { - ret.x0_blendMode = 5; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; - ret.x4_color = col; - } - } - else if (x48_blendMode == EBlendMode::Additive) - { - ret.x0_blendMode = 7; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; - ret.x4_color = col; - } - else if (x48_blendMode == EBlendMode::Additive2) - { - ret.x0_blendMode = 8; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; - ret.x4_color = col; - } - else if (x48_blendMode == EBlendMode::Opaque) - { - if (col == zeus::CColor::skWhite) - { - ret.x0_blendMode = 3; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; - ret.x4_color = zeus::CColor::skWhite; - } - else - { - ret.x0_blendMode = 1; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; - ret.x4_color = col; - } - } - else if (x48_blendMode == EBlendMode::Opaque2) - { - ret.x0_blendMode = 2; - ret.x1_matSetIdx = 0; - ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; - ret.x4_color = col; - } - else - { - ret.x2_flags = 3; - ret.x4_color = zeus::CColor::skWhite; - } - } - return ret; -} - -void CScriptColorModulate::SetTargetFlags(CStateManager& stateMgr, const CModelFlags& flags) -{ - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) - continue; - - auto search = stateMgr.GetIdListForScript(conn.x8_objId); - for (auto it = search.first ; it != search.second ; ++it) - { - CEntity* ent = stateMgr.ObjectById(it->second); - if (CActor* act = TCastToPtr(ent)) - act->SetDrawFlags(flags); - } + x3c_curTime += dt; + if (x38_fadeState == EFadeState::A2B) { + float t; + if (zeus::close_enough(x4c_timeA2B, 0.f)) + t = 1.f; + else { + t = x3c_curTime / x4c_timeA2B; + if (t >= 1.f) + t = 1.f; } - if (x34_parent != kInvalidUniqueId) - { - CEntity* ent = stateMgr.ObjectById(x34_parent); - if (CActor* act = TCastToPtr(ent)) - act->SetDrawFlags(flags); - } -} + zeus::CColor lerpedCol = zeus::CColor::lerp(x40_colorA, x44_colorB, t); + CModelFlags flags = CalculateFlags(lerpedCol); + SetTargetFlags(mgr, flags); -TUniqueId CScriptColorModulate::FadeOutHelper(CStateManager& mgr, TUniqueId parent, float fadeTime) -{ - TAreaId aId = mgr.GetNextAreaId(); - if (const CEntity* ent = mgr.GetObjectById(parent)) - aId = ent->GetAreaIdAlways(); + if (x3c_curTime <= x4c_timeA2B) + return; - TUniqueId ret = mgr.AllocateUniqueId(); - CScriptColorModulate* colMod = new CScriptColorModulate(ret, "", CEntityInfo(aId, CEntity::NullConnectionList), - zeus::CColor(1.f, 1.f, 1.f, 1.f), zeus::CColor(1.f, 1.f, 1.f, 0.f), EBlendMode::Alpha, fadeTime, 0.f, - false, false, true, true, false, true); - mgr.AddObject(colMod); - colMod->x34_parent = parent; - colMod->x54_30_enable = true; - colMod->x54_31_dieOnEnd = true; - colMod->x55_24_isFadeOutHelper = true; - - colMod->Think(0.f, mgr); - return ret; -} - -TUniqueId CScriptColorModulate::FadeInHelper(CStateManager& mgr, TUniqueId parent, float fadeTime) -{ - TAreaId aId = mgr.GetNextAreaId(); - if (const CEntity* ent = mgr.GetObjectById(parent)) - aId = ent->GetAreaIdAlways(); - - TUniqueId ret = mgr.AllocateUniqueId(); - CScriptColorModulate* colMod = new CScriptColorModulate(ret, "", CEntityInfo(aId, CEntity::NullConnectionList), - zeus::CColor(1.f, 1.f, 1.f, 0.f), zeus::CColor(1.f, 1.f, 1.f, 1.f), EBlendMode::Alpha, fadeTime, 0.f, - false, false, true, true, false, true); - mgr.AddObject(colMod); - colMod->x34_parent = parent; - colMod->x54_30_enable = true; - colMod->x54_31_dieOnEnd = true; - - colMod->Think(0.f, mgr); - return ret; -} - -void CScriptColorModulate::End(CStateManager& stateMgr) -{ - x3c_curTime = 0.f; - if (x54_24_doReverse && !x54_29_reversing) - { - x54_29_reversing = true; - x38_fadeState = x38_fadeState == EFadeState::A2B ? EFadeState::B2A : EFadeState::A2B; - return; + End(mgr); + } else if (x38_fadeState == EFadeState::B2A) { + float t; + if (zeus::close_enough(x50_timeB2A, 0.f)) + t = 1.f; + else { + t = x3c_curTime / x50_timeB2A; + if (t >= 1.f) + t = 1.f; } - x54_30_enable = false; - x54_29_reversing = false; - if (x54_25_resetTargetWhenDone) - SetTargetFlags(stateMgr, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); + zeus::CColor lerpedCol = zeus::CColor::lerp(x44_colorB, x40_colorA, t); + CModelFlags flags = CalculateFlags(lerpedCol); + SetTargetFlags(mgr, flags); - if (x55_24_isFadeOutHelper) - stateMgr.SendScriptMsgAlways(x34_parent, x8_uid, EScriptObjectMessage::Deactivate); + if (x3c_curTime <= x50_timeB2A) + return; - CEntity::SendScriptMsgs(EScriptObjectState::MaxReached, stateMgr, EScriptObjectMessage::None); - - if (x54_31_dieOnEnd) - stateMgr.FreeScriptObject(GetUniqueId()); + End(mgr); + } } + +CModelFlags CScriptColorModulate::CalculateFlags(const zeus::CColor& col) const { + CModelFlags ret; + if (x54_28_depthBackwards) { + if (x48_blendMode == EBlendMode::Alpha) { + ret.x0_blendMode = 5; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 3 | 8; + ret.x4_color = col; + } else if (x48_blendMode == EBlendMode::Additive) { + ret.x0_blendMode = 7; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 0x8; + ret.x4_color = col; + } else if (x48_blendMode == EBlendMode::Additive2) { + ret.x0_blendMode = 8; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 0x8; + ret.x4_color = col; + } else if (x48_blendMode == EBlendMode::Opaque) { + ret.x0_blendMode = 1; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 0x8; + ret.x4_color = col; + } else if (x48_blendMode == EBlendMode::Opaque2) { + ret.x0_blendMode = 2; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1 | 0x8; + ret.x4_color = col; + } else { + ret.x2_flags = 3; + ret.x4_color = zeus::CColor::skWhite; + } + } else { + if (x48_blendMode == EBlendMode::Alpha) { + if (col == zeus::CColor::skWhite) { + ret.x0_blendMode = 3; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; + ret.x4_color = zeus::CColor::skWhite; + } else { + ret.x0_blendMode = 5; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; + ret.x4_color = col; + } + } else if (x48_blendMode == EBlendMode::Additive) { + ret.x0_blendMode = 7; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; + ret.x4_color = col; + } else if (x48_blendMode == EBlendMode::Additive2) { + ret.x0_blendMode = 8; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; + ret.x4_color = col; + } else if (x48_blendMode == EBlendMode::Opaque) { + if (col == zeus::CColor::skWhite) { + ret.x0_blendMode = 3; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; + ret.x4_color = zeus::CColor::skWhite; + } else { + ret.x0_blendMode = 1; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; + ret.x4_color = col; + } + } else if (x48_blendMode == EBlendMode::Opaque2) { + ret.x0_blendMode = 2; + ret.x1_matSetIdx = 0; + ret.x2_flags = x54_26_depthCompare << 0 | x54_27_depthUpdate << 1; + ret.x4_color = col; + } else { + ret.x2_flags = 3; + ret.x4_color = zeus::CColor::skWhite; + } + } + return ret; } + +void CScriptColorModulate::SetTargetFlags(CStateManager& stateMgr, const CModelFlags& flags) { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) + continue; + + auto search = stateMgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) { + CEntity* ent = stateMgr.ObjectById(it->second); + if (CActor* act = TCastToPtr(ent)) + act->SetDrawFlags(flags); + } + } + + if (x34_parent != kInvalidUniqueId) { + CEntity* ent = stateMgr.ObjectById(x34_parent); + if (CActor* act = TCastToPtr(ent)) + act->SetDrawFlags(flags); + } +} + +TUniqueId CScriptColorModulate::FadeOutHelper(CStateManager& mgr, TUniqueId parent, float fadeTime) { + TAreaId aId = mgr.GetNextAreaId(); + if (const CEntity* ent = mgr.GetObjectById(parent)) + aId = ent->GetAreaIdAlways(); + + TUniqueId ret = mgr.AllocateUniqueId(); + CScriptColorModulate* colMod = new CScriptColorModulate( + ret, "", CEntityInfo(aId, CEntity::NullConnectionList), zeus::CColor(1.f, 1.f, 1.f, 1.f), + zeus::CColor(1.f, 1.f, 1.f, 0.f), EBlendMode::Alpha, fadeTime, 0.f, false, false, true, true, false, true); + mgr.AddObject(colMod); + colMod->x34_parent = parent; + colMod->x54_30_enable = true; + colMod->x54_31_dieOnEnd = true; + colMod->x55_24_isFadeOutHelper = true; + + colMod->Think(0.f, mgr); + return ret; +} + +TUniqueId CScriptColorModulate::FadeInHelper(CStateManager& mgr, TUniqueId parent, float fadeTime) { + TAreaId aId = mgr.GetNextAreaId(); + if (const CEntity* ent = mgr.GetObjectById(parent)) + aId = ent->GetAreaIdAlways(); + + TUniqueId ret = mgr.AllocateUniqueId(); + CScriptColorModulate* colMod = new CScriptColorModulate( + ret, "", CEntityInfo(aId, CEntity::NullConnectionList), zeus::CColor(1.f, 1.f, 1.f, 0.f), + zeus::CColor(1.f, 1.f, 1.f, 1.f), EBlendMode::Alpha, fadeTime, 0.f, false, false, true, true, false, true); + mgr.AddObject(colMod); + colMod->x34_parent = parent; + colMod->x54_30_enable = true; + colMod->x54_31_dieOnEnd = true; + + colMod->Think(0.f, mgr); + return ret; +} + +void CScriptColorModulate::End(CStateManager& stateMgr) { + x3c_curTime = 0.f; + if (x54_24_doReverse && !x54_29_reversing) { + x54_29_reversing = true; + x38_fadeState = x38_fadeState == EFadeState::A2B ? EFadeState::B2A : EFadeState::A2B; + return; + } + + x54_30_enable = false; + x54_29_reversing = false; + if (x54_25_resetTargetWhenDone) + SetTargetFlags(stateMgr, CModelFlags(0, 0, 3, zeus::CColor::skWhite)); + + if (x55_24_isFadeOutHelper) + stateMgr.SendScriptMsgAlways(x34_parent, x8_uid, EScriptObjectMessage::Deactivate); + + CEntity::SendScriptMsgs(EScriptObjectState::MaxReached, stateMgr, EScriptObjectMessage::None); + + if (x54_31_dieOnEnd) + stateMgr.FreeScriptObject(GetUniqueId()); +} +} // namespace urde diff --git a/Runtime/World/CScriptColorModulate.hpp b/Runtime/World/CScriptColorModulate.hpp index 928ac61c9..b1d5666b7 100644 --- a/Runtime/World/CScriptColorModulate.hpp +++ b/Runtime/World/CScriptColorModulate.hpp @@ -3,66 +3,55 @@ #include "CEntity.hpp" #include "zeus/CColor.hpp" -namespace urde -{ +namespace urde { struct CModelFlags; -class CScriptColorModulate : public CEntity -{ +class CScriptColorModulate : public CEntity { public: - enum class EBlendMode - { - Alpha, - Additive, - Additive2, - Opaque, - Opaque2, - }; - enum class EFadeState - { - A2B, - B2A - }; + enum class EBlendMode { + Alpha, + Additive, + Additive2, + Opaque, + Opaque2, + }; + enum class EFadeState { A2B, B2A }; private: - TUniqueId x34_parent = kInvalidUniqueId; - EFadeState x38_fadeState = EFadeState::A2B; - float x3c_curTime = 0.f; - zeus::CColor x40_colorA; - zeus::CColor x44_colorB; - EBlendMode x48_blendMode; - float x4c_timeA2B; - float x50_timeB2A; - union - { - struct - { - bool x54_24_doReverse : 1; - bool x54_25_resetTargetWhenDone : 1; - bool x54_26_depthCompare : 1; - bool x54_27_depthUpdate : 1; - bool x54_28_depthBackwards : 1; - bool x54_29_reversing : 1; - bool x54_30_enable : 1; - bool x54_31_dieOnEnd : 1; - bool x55_24_isFadeOutHelper : 1; - }; - u32 _dummy = 0; + TUniqueId x34_parent = kInvalidUniqueId; + EFadeState x38_fadeState = EFadeState::A2B; + float x3c_curTime = 0.f; + zeus::CColor x40_colorA; + zeus::CColor x44_colorB; + EBlendMode x48_blendMode; + float x4c_timeA2B; + float x50_timeB2A; + union { + struct { + bool x54_24_doReverse : 1; + bool x54_25_resetTargetWhenDone : 1; + bool x54_26_depthCompare : 1; + bool x54_27_depthUpdate : 1; + bool x54_28_depthBackwards : 1; + bool x54_29_reversing : 1; + bool x54_30_enable : 1; + bool x54_31_dieOnEnd : 1; + bool x55_24_isFadeOutHelper : 1; }; + u32 _dummy = 0; + }; public: - CScriptColorModulate(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CColor& colorA, const zeus::CColor& colorB, - EBlendMode blendMode, float timeA2B, float timeB2A, bool doReverse, - bool resetTargetWhenDone, bool depthCompare, bool depthUpdate, - bool depthBackwards, bool active); + CScriptColorModulate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CColor& colorA, + const zeus::CColor& colorB, EBlendMode blendMode, float timeA2B, float timeB2A, bool doReverse, + bool resetTargetWhenDone, bool depthCompare, bool depthUpdate, bool depthBackwards, bool active); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); - void Think(float, CStateManager &); - CModelFlags CalculateFlags(const zeus::CColor&) const; - void SetTargetFlags(CStateManager&, const CModelFlags&); - static TUniqueId FadeOutHelper(CStateManager& mgr, TUniqueId obj, float fadetime); - static TUniqueId FadeInHelper(CStateManager& mgr, TUniqueId obj, float fadetime); - void End(CStateManager&); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Think(float, CStateManager&); + CModelFlags CalculateFlags(const zeus::CColor&) const; + void SetTargetFlags(CStateManager&, const CModelFlags&); + static TUniqueId FadeOutHelper(CStateManager& mgr, TUniqueId obj, float fadetime); + static TUniqueId FadeInHelper(CStateManager& mgr, TUniqueId obj, float fadetime); + void End(CStateManager&); }; -} +} // namespace urde diff --git a/Runtime/World/CScriptControllerAction.cpp b/Runtime/World/CScriptControllerAction.cpp index a69b8b84a..7d2a53b98 100644 --- a/Runtime/World/CScriptControllerAction.cpp +++ b/Runtime/World/CScriptControllerAction.cpp @@ -3,52 +3,38 @@ #include "CStateManager.hpp" #include "Input/ControlMapper.hpp" -namespace urde -{ +namespace urde { -CScriptControllerAction::CScriptControllerAction(TUniqueId uid, std::string_view name, - const CEntityInfo& info, bool active, - ControlMapper::ECommands command, bool mapScreenResponse, u32 w1, bool deactivateOnClose) -: CEntity(uid, info, active, name), x34_command(command), x38_mapScreenSubaction(w1) -{ - x3c_24_mapScreenResponse = mapScreenResponse; - x3c_25_deactivateOnClose = deactivateOnClose; +CScriptControllerAction::CScriptControllerAction(TUniqueId uid, std::string_view name, const CEntityInfo& info, + bool active, ControlMapper::ECommands command, bool mapScreenResponse, + u32 w1, bool deactivateOnClose) +: CEntity(uid, info, active, name), x34_command(command), x38_mapScreenSubaction(w1) { + x3c_24_mapScreenResponse = mapScreenResponse; + x3c_25_deactivateOnClose = deactivateOnClose; } -void CScriptControllerAction::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptControllerAction::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptControllerAction::Think(float, CStateManager& stateMgr) -{ - bool oldPressed = x3c_26_pressed; - if (x3c_24_mapScreenResponse) - { - if (x38_mapScreenSubaction == 0) - x3c_26_pressed = stateMgr.GetInMapScreen(); - } - else - { - x3c_26_pressed = ControlMapper::GetDigitalInput(x34_command, stateMgr.GetFinalInput()); - } - - if (GetActive() && x3c_26_pressed != oldPressed) - { - if (x3c_26_pressed) - { - SendScriptMsgs(EScriptObjectState::Open, stateMgr, EScriptObjectMessage::None); - } - else - { - SendScriptMsgs(EScriptObjectState::Closed, stateMgr, EScriptObjectMessage::None); - if (x3c_25_deactivateOnClose) - { - SetActive(false); - SendScriptMsgs(EScriptObjectState::Inactive, stateMgr, EScriptObjectMessage::None); - } - } +void CScriptControllerAction::Think(float, CStateManager& stateMgr) { + bool oldPressed = x3c_26_pressed; + if (x3c_24_mapScreenResponse) { + if (x38_mapScreenSubaction == 0) + x3c_26_pressed = stateMgr.GetInMapScreen(); + } else { + x3c_26_pressed = ControlMapper::GetDigitalInput(x34_command, stateMgr.GetFinalInput()); + } + + if (GetActive() && x3c_26_pressed != oldPressed) { + if (x3c_26_pressed) { + SendScriptMsgs(EScriptObjectState::Open, stateMgr, EScriptObjectMessage::None); + } else { + SendScriptMsgs(EScriptObjectState::Closed, stateMgr, EScriptObjectMessage::None); + if (x3c_25_deactivateOnClose) { + SetActive(false); + SendScriptMsgs(EScriptObjectState::Inactive, stateMgr, EScriptObjectMessage::None); + } } + } } -} +} // namespace urde diff --git a/Runtime/World/CScriptControllerAction.hpp b/Runtime/World/CScriptControllerAction.hpp index 4f2d45b83..d18b02cb0 100644 --- a/Runtime/World/CScriptControllerAction.hpp +++ b/Runtime/World/CScriptControllerAction.hpp @@ -3,29 +3,25 @@ #include "CEntity.hpp" #include "Input/ControlMapper.hpp" -namespace urde -{ +namespace urde { -class CScriptControllerAction : public CEntity -{ - ControlMapper::ECommands x34_command; - u32 x38_mapScreenSubaction; - union - { - struct - { - bool x3c_24_mapScreenResponse : 1; - bool x3c_25_deactivateOnClose : 1; - bool x3c_26_pressed : 1; - }; - u8 _dummy = 0; +class CScriptControllerAction : public CEntity { + ControlMapper::ECommands x34_command; + u32 x38_mapScreenSubaction; + union { + struct { + bool x3c_24_mapScreenResponse : 1; + bool x3c_25_deactivateOnClose : 1; + bool x3c_26_pressed : 1; }; + u8 _dummy = 0; + }; + public: - CScriptControllerAction(TUniqueId uid, std::string_view name, const CEntityInfo& info, - bool active, ControlMapper::ECommands command, bool b1, u32 w1, bool b2); - void Accept(IVisitor& visitor); - void Think(float, CStateManager&); + CScriptControllerAction(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, + ControlMapper::ECommands command, bool b1, u32 w1, bool b2); + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptCounter.cpp b/Runtime/World/CScriptCounter.cpp index 03f7e50c3..2fc4fd54d 100644 --- a/Runtime/World/CScriptCounter.cpp +++ b/Runtime/World/CScriptCounter.cpp @@ -2,81 +2,67 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CScriptCounter::CScriptCounter(TUniqueId uid, std::string_view name, const CEntityInfo& info, - s32 initial, s32 max, bool autoReset, bool active) +CScriptCounter::CScriptCounter(TUniqueId uid, std::string_view name, const CEntityInfo& info, s32 initial, s32 max, + bool autoReset, bool active) : CEntity(uid, info, active, name) , x34_initial(initial) , x38_current(initial) , x3c_max(max) -, x40_autoReset(autoReset) -{ -} +, x40_autoReset(autoReset) {} -void CScriptCounter::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptCounter::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptCounter::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - switch(msg) - { - case EScriptObjectMessage::SetToZero: - if (GetActive()) - { - x38_current = 0; - SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); +void CScriptCounter::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + switch (msg) { + case EScriptObjectMessage::SetToZero: + if (GetActive()) { + x38_current = 0; + SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); - if (x40_autoReset) - x38_current = x34_initial; - } - break; - case EScriptObjectMessage::SetToMax: - if (GetActive()) - { - x38_current = x3c_max; - SendScriptMsgs(EScriptObjectState::MaxReached, stateMgr, EScriptObjectMessage::None); - - if (x40_autoReset) - x38_current = x34_initial; - } - break; - case EScriptObjectMessage::Decrement: - if (GetActive() && x38_current > 0) - { - --x38_current; - if (x38_current == 0) - { - SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); - if (x40_autoReset) - x38_current = x34_initial; - } - } - break; - case EScriptObjectMessage::Increment: - if (GetActive() && x38_current < x3c_max) - { - ++x38_current; - if (x38_current >= x3c_max) - { - SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); - if (x40_autoReset) - x38_current = x34_initial; - } - } - break; - case EScriptObjectMessage::Reset: - if (GetActive()) - x38_current = x34_initial; - break; - default: - break; + if (x40_autoReset) + x38_current = x34_initial; } + break; + case EScriptObjectMessage::SetToMax: + if (GetActive()) { + x38_current = x3c_max; + SendScriptMsgs(EScriptObjectState::MaxReached, stateMgr, EScriptObjectMessage::None); - CEntity::AcceptScriptMsg(msg, objId, stateMgr); + if (x40_autoReset) + x38_current = x34_initial; + } + break; + case EScriptObjectMessage::Decrement: + if (GetActive() && x38_current > 0) { + --x38_current; + if (x38_current == 0) { + SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); + if (x40_autoReset) + x38_current = x34_initial; + } + } + break; + case EScriptObjectMessage::Increment: + if (GetActive() && x38_current < x3c_max) { + ++x38_current; + if (x38_current >= x3c_max) { + SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); + if (x40_autoReset) + x38_current = x34_initial; + } + } + break; + case EScriptObjectMessage::Reset: + if (GetActive()) + x38_current = x34_initial; + break; + default: + break; + } + + CEntity::AcceptScriptMsg(msg, objId, stateMgr); } -} +} // namespace urde diff --git a/Runtime/World/CScriptCounter.hpp b/Runtime/World/CScriptCounter.hpp index 69e39bdb9..6f66fb2d4 100644 --- a/Runtime/World/CScriptCounter.hpp +++ b/Runtime/World/CScriptCounter.hpp @@ -2,22 +2,19 @@ #include "CEntity.hpp" -namespace urde -{ +namespace urde { + +class CScriptCounter : public CEntity { + s32 x34_initial; + s32 x38_current; + s32 x3c_max; + bool x40_autoReset; -class CScriptCounter : public CEntity -{ - s32 x34_initial; - s32 x38_current; - s32 x3c_max; - bool x40_autoReset; public: - CScriptCounter(TUniqueId, std::string_view name, const CEntityInfo& info, - s32, s32, bool, bool); + CScriptCounter(TUniqueId, std::string_view name, const CEntityInfo& info, s32, s32, bool, bool); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptCoverPoint.cpp b/Runtime/World/CScriptCoverPoint.cpp index de6fa233b..7ea8ed6ba 100644 --- a/Runtime/World/CScriptCoverPoint.cpp +++ b/Runtime/World/CScriptCoverPoint.cpp @@ -3,99 +3,81 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ -CScriptCoverPoint::CScriptCoverPoint(TUniqueId uid, std::string_view name, const CEntityInfo &info, - zeus::CTransform xf, bool active, u32 flags, bool crouch, - float horizontalAngle, float verticalAngle, float coverTime) - : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), - CMaterialList(EMaterialTypes::NoStepLogic), CActorParameters::None(), kInvalidUniqueId), - xe8_flags(flags), - xf4_coverTime(coverTime) -{ - xf8_24_crouch = crouch; - xec_cosHorizontalAngle = std::cos(zeus::degToRad(horizontalAngle) * 0.5f); - xf0_sinVerticalAngle = std::sin(zeus::degToRad(verticalAngle) * 0.5f); - x100_touchBounds.emplace(xf.origin, xf.origin); +namespace urde { +CScriptCoverPoint::CScriptCoverPoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, zeus::CTransform xf, + bool active, u32 flags, bool crouch, float horizontalAngle, float verticalAngle, + float coverTime) +: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic), + CActorParameters::None(), kInvalidUniqueId) +, xe8_flags(flags) +, xf4_coverTime(coverTime) { + xf8_24_crouch = crouch; + xec_cosHorizontalAngle = std::cos(zeus::degToRad(horizontalAngle) * 0.5f); + xf0_sinVerticalAngle = std::sin(zeus::degToRad(verticalAngle) * 0.5f); + x100_touchBounds.emplace(xf.origin, xf.origin); } -void CScriptCoverPoint::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptCoverPoint::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptCoverPoint::Think(float delta, CStateManager&) { + if (x11c_timeLeft <= 0.f) + return; + x11c_timeLeft -= delta; } -void CScriptCoverPoint::Think(float delta, CStateManager&) -{ - if (x11c_timeLeft <= 0.f) - return; - x11c_timeLeft -= delta; +std::experimental::optional CScriptCoverPoint::GetTouchBounds() const { + if (x100_touchBounds) + return x100_touchBounds; + + return {}; } -std::experimental::optional CScriptCoverPoint::GetTouchBounds() const -{ - if (x100_touchBounds) - return x100_touchBounds; - - return {}; +void CScriptCoverPoint::SetInUse(bool inUse) { + xf8_25_inUse = inUse; + if (inUse) + x11c_timeLeft = xf4_coverTime; } -void CScriptCoverPoint::SetInUse(bool inUse) -{ - xf8_25_inUse = inUse; - if (inUse) - x11c_timeLeft = xf4_coverTime; -} - -bool CScriptCoverPoint::GetInUse(TUniqueId uid) const -{ - if (xf8_25_inUse || x11c_timeLeft > 0.f) - return true; - - if (xfa_occupant == kInvalidUniqueId || uid == kInvalidUniqueId || xfa_occupant == uid) - return false; - +bool CScriptCoverPoint::GetInUse(TUniqueId uid) const { + if (xf8_25_inUse || x11c_timeLeft > 0.f) return true; -} - -bool CScriptCoverPoint::Blown(const zeus::CVector3f& point) const -{ - if (!x30_24_active) - return true; - - if (ShouldWallHang()) - { - zeus::CVector3f posDif = point - x34_transform.origin; - posDif *= zeus::CVector3f(1.f / posDif.magnitude()); - zeus::CVector3f normDif = posDif.normalized(); - - zeus::CVector3f frontVec = x34_transform.frontVector(); - frontVec.normalize(); - - if (frontVec.dot(normDif) <= GetCosHorizontalAngle() || (posDif.z() * posDif.z()) >= GetSinSqVerticalAngle()) - return true; - } + if (xfa_occupant == kInvalidUniqueId || uid == kInvalidUniqueId || xfa_occupant == uid) return false; + + return true; } -float CScriptCoverPoint::GetSinSqVerticalAngle() const -{ - return xf0_sinVerticalAngle * xf0_sinVerticalAngle; +bool CScriptCoverPoint::Blown(const zeus::CVector3f& point) const { + if (!x30_24_active) + return true; + + if (ShouldWallHang()) { + zeus::CVector3f posDif = point - x34_transform.origin; + posDif *= zeus::CVector3f(1.f / posDif.magnitude()); + zeus::CVector3f normDif = posDif.normalized(); + + zeus::CVector3f frontVec = x34_transform.frontVector(); + frontVec.normalize(); + + if (frontVec.dot(normDif) <= GetCosHorizontalAngle() || (posDif.z() * posDif.z()) >= GetSinSqVerticalAngle()) + return true; + } + return false; } -void CScriptCoverPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); +float CScriptCoverPoint::GetSinSqVerticalAngle() const { return xf0_sinVerticalAngle * xf0_sinVerticalAngle; } - if (msg == EScriptObjectMessage::WorldInitialized) - { - for (const SConnection& con : x20_conns) - if (con.x0_state == EScriptObjectState::Retreat) - { - xfc_retreating = mgr.GetIdForScript(con.x8_objId); - break; - } - } +void CScriptCoverPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); + + if (msg == EScriptObjectMessage::WorldInitialized) { + for (const SConnection& con : x20_conns) + if (con.x0_state == EScriptObjectState::Retreat) { + xfc_retreating = mgr.GetIdForScript(con.x8_objId); + break; + } + } } -} +} // namespace urde diff --git a/Runtime/World/CScriptCoverPoint.hpp b/Runtime/World/CScriptCoverPoint.hpp index 3bda51ccd..99b195530 100644 --- a/Runtime/World/CScriptCoverPoint.hpp +++ b/Runtime/World/CScriptCoverPoint.hpp @@ -2,58 +2,52 @@ #include "CActor.hpp" -namespace urde -{ -class CScriptCoverPoint : public CActor -{ - union - { - struct - { - bool xe8_26_landHere : 1; - bool xe8_27_wallHang : 1; - bool xe8_28_stay : 1; - }; - u32 xe8_flags; +namespace urde { +class CScriptCoverPoint : public CActor { + union { + struct { + bool xe8_26_landHere : 1; + bool xe8_27_wallHang : 1; + bool xe8_28_stay : 1; }; + u32 xe8_flags; + }; - float xec_cosHorizontalAngle; - float xf0_sinVerticalAngle; - float xf4_coverTime; - union - { - struct - { - bool xf8_24_crouch : 1; - bool xf8_25_inUse : 1; - }; - u32 xf8_flags = 0; + float xec_cosHorizontalAngle; + float xf0_sinVerticalAngle; + float xf4_coverTime; + union { + struct { + bool xf8_24_crouch : 1; + bool xf8_25_inUse : 1; }; - TUniqueId xfa_occupant = kInvalidUniqueId; - TUniqueId xfc_retreating = kInvalidUniqueId; - std::experimental::optional x100_touchBounds; - float x11c_timeLeft = 0.f; + u32 xf8_flags = 0; + }; + TUniqueId xfa_occupant = kInvalidUniqueId; + TUniqueId xfc_retreating = kInvalidUniqueId; + std::experimental::optional x100_touchBounds; + float x11c_timeLeft = 0.f; + public: - CScriptCoverPoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - zeus::CTransform xf, bool active, u32 flags, bool crouch, float horizontalAngle, float verticalAngle, float coverTime); + CScriptCoverPoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, zeus::CTransform xf, bool active, + u32 flags, bool crouch, float horizontalAngle, float verticalAngle, float coverTime); - void Accept(IVisitor& visitor); - void Think(float, CStateManager &); - void AddToRenderer(const zeus::CFrustum &, const CStateManager &) const {} - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); - void Render(const CStateManager &) const {} - std::experimental::optional GetTouchBounds() const; - void SetInUse(bool inUse); - bool GetInUse(TUniqueId uid) const; - bool ShouldLandHere() const { return xe8_26_landHere; } - bool ShouldWallHang() const { return xe8_27_wallHang; } - bool ShouldStay() const { return xe8_28_stay; } - bool ShouldCrouch() const { return xf8_24_crouch; } - bool Blown(const zeus::CVector3f& pos) const; - float GetSinSqVerticalAngle() const; - float GetCosHorizontalAngle() const { return xec_cosHorizontalAngle; } - u32 GetAttackDirection() const { return xe8_flags; } - void Reserve(TUniqueId id) { xfa_occupant = id; } + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Render(const CStateManager&) const {} + std::experimental::optional GetTouchBounds() const; + void SetInUse(bool inUse); + bool GetInUse(TUniqueId uid) const; + bool ShouldLandHere() const { return xe8_26_landHere; } + bool ShouldWallHang() const { return xe8_27_wallHang; } + bool ShouldStay() const { return xe8_28_stay; } + bool ShouldCrouch() const { return xf8_24_crouch; } + bool Blown(const zeus::CVector3f& pos) const; + float GetSinSqVerticalAngle() const; + float GetCosHorizontalAngle() const { return xec_cosHorizontalAngle; } + u32 GetAttackDirection() const { return xe8_flags; } + void Reserve(TUniqueId id) { xfa_occupant = id; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptDamageableTrigger.cpp b/Runtime/World/CScriptDamageableTrigger.cpp index 7d7c7b0d1..e3c84e664 100644 --- a/Runtime/World/CScriptDamageableTrigger.cpp +++ b/Runtime/World/CScriptDamageableTrigger.cpp @@ -5,25 +5,21 @@ #include "CWorld.hpp" #include "CScriptActor.hpp" -namespace urde -{ -CActorParameters MakeDamageableTriggerActorParms(const CActorParameters& aParams, const CVisorParameters& vParams) -{ - CActorParameters ret = aParams; - ret.SetVisorParameters(vParams); - return ret; +namespace urde { +CActorParameters MakeDamageableTriggerActorParms(const CActorParameters& aParams, const CVisorParameters& vParams) { + CActorParameters ret = aParams; + ret.SetVisorParameters(vParams); + return ret; } -CMaterialList MakeDamageableTriggerMaterial(CScriptDamageableTrigger::ECanOrbit canOrbit) -{ - if (canOrbit == CScriptDamageableTrigger::ECanOrbit::Orbit) - return CMaterialList(EMaterialTypes::Orbit, EMaterialTypes::Trigger, EMaterialTypes::Immovable, - EMaterialTypes::NonSolidDamageable, EMaterialTypes::ExcludeFromLineOfSightTest); - return CMaterialList(EMaterialTypes::Trigger, EMaterialTypes::Immovable, +CMaterialList MakeDamageableTriggerMaterial(CScriptDamageableTrigger::ECanOrbit canOrbit) { + if (canOrbit == CScriptDamageableTrigger::ECanOrbit::Orbit) + return CMaterialList(EMaterialTypes::Orbit, EMaterialTypes::Trigger, EMaterialTypes::Immovable, EMaterialTypes::NonSolidDamageable, EMaterialTypes::ExcludeFromLineOfSightTest); + return CMaterialList(EMaterialTypes::Trigger, EMaterialTypes::Immovable, EMaterialTypes::NonSolidDamageable, + EMaterialTypes::ExcludeFromLineOfSightTest); } - CScriptDamageableTrigger::CScriptDamageableTrigger(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& position, const zeus::CVector3f& extent, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, @@ -32,207 +28,172 @@ CScriptDamageableTrigger::CScriptDamageableTrigger(TUniqueId uid, std::string_vi const CVisorParameters& vParams) : CActor(uid, active, name, info, zeus::CTransform::Translate(position), CModelData::CModelDataNull(), MakeDamageableTriggerMaterial(canOrbit), MakeDamageableTriggerActorParms(CActorParameters::None(), vParams), - kInvalidUniqueId), - x14c_bounds(-extent * 0.5f, extent * 0.5f), - x164_origHInfo(hInfo), x16c_hInfo(hInfo), x174_dVuln(dVuln), x1dc_faceFlag(faceFlag), - x254_fluidPlane(patternTex1, patternTex2, colorTex, 1.f, 2, - EFluidType::NormalWater, 1.f, CFluidUVMotion(6.f, 0.f)) -{ - x300_28_canOrbit = canOrbit == ECanOrbit::Orbit; - if (x1dc_faceFlag & 0x1) - { - x244_faceTranslate = zeus::CVector3f(0.f, x14c_bounds.max.y(), 0.f); - x1e4_faceDir = zeus::CTransform::RotateX(-M_PIF / 2.f); - } - else if (x1dc_faceFlag & 0x2) - { - x244_faceTranslate = zeus::CVector3f(0.f, x14c_bounds.min.y(), 0.f); - x1e4_faceDir = zeus::CTransform::RotateX(M_PIF / 2.f); - } - else if (x1dc_faceFlag & 0x4) - { - x244_faceTranslate = zeus::CVector3f(x14c_bounds.min.x(), 0.f, 0.f); - x1e4_faceDir = zeus::CTransform::RotateY(-M_PIF / 2.f); - } - else if (x1dc_faceFlag & 0x8) - { - x244_faceTranslate = zeus::CVector3f(x14c_bounds.max.x(), 0.f, 0.f); - x1e4_faceDir = zeus::CTransform::RotateY(M_PIF / 2.f); - } - else if (x1dc_faceFlag & 0x10) - { - x244_faceTranslate = zeus::CVector3f(0.f, 0.f, x14c_bounds.max.z()); - x1e4_faceDir = zeus::CTransform::Identity(); - } - else if (x1dc_faceFlag & 0x20) - { - x244_faceTranslate = zeus::CVector3f(0.f, 0.f, x14c_bounds.min.z()); - x1e4_faceDir = zeus::CTransform::RotateY(M_PIF); - } + kInvalidUniqueId) +, x14c_bounds(-extent * 0.5f, extent * 0.5f) +, x164_origHInfo(hInfo) +, x16c_hInfo(hInfo) +, x174_dVuln(dVuln) +, x1dc_faceFlag(faceFlag) +, x254_fluidPlane(patternTex1, patternTex2, colorTex, 1.f, 2, EFluidType::NormalWater, 1.f, CFluidUVMotion(6.f, 0.f)) { + x300_28_canOrbit = canOrbit == ECanOrbit::Orbit; + if (x1dc_faceFlag & 0x1) { + x244_faceTranslate = zeus::CVector3f(0.f, x14c_bounds.max.y(), 0.f); + x1e4_faceDir = zeus::CTransform::RotateX(-M_PIF / 2.f); + } else if (x1dc_faceFlag & 0x2) { + x244_faceTranslate = zeus::CVector3f(0.f, x14c_bounds.min.y(), 0.f); + x1e4_faceDir = zeus::CTransform::RotateX(M_PIF / 2.f); + } else if (x1dc_faceFlag & 0x4) { + x244_faceTranslate = zeus::CVector3f(x14c_bounds.min.x(), 0.f, 0.f); + x1e4_faceDir = zeus::CTransform::RotateY(-M_PIF / 2.f); + } else if (x1dc_faceFlag & 0x8) { + x244_faceTranslate = zeus::CVector3f(x14c_bounds.max.x(), 0.f, 0.f); + x1e4_faceDir = zeus::CTransform::RotateY(M_PIF / 2.f); + } else if (x1dc_faceFlag & 0x10) { + x244_faceTranslate = zeus::CVector3f(0.f, 0.f, x14c_bounds.max.z()); + x1e4_faceDir = zeus::CTransform::Identity(); + } else if (x1dc_faceFlag & 0x20) { + x244_faceTranslate = zeus::CVector3f(0.f, 0.f, x14c_bounds.min.z()); + x1e4_faceDir = zeus::CTransform::RotateY(M_PIF); + } - x214_faceDirInv = x1e4_faceDir.inverse(); + x214_faceDirInv = x1e4_faceDir.inverse(); } -void CScriptDamageableTrigger::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptDamageableTrigger::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptDamageableTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Deactivate: - if (x30_24_active && x300_25_alphaOut) - return; - [[fallthrough]]; - case EScriptObjectMessage::Activate: - if (!x30_24_active || x300_25_alphaOut) - { - x250_alphaTimer = 0.f; - x16c_hInfo = x164_origHInfo; - x300_25_alphaOut = false; - if (x300_28_canOrbit) - AddMaterial(EMaterialTypes::Orbit, mgr); - SetLinkedObjectAlpha(0.f, mgr); - x1e0_alpha = 0.f; - } - break; - case EScriptObjectMessage::Damage: - if (x300_27_invulnerable) - x16c_hInfo = x164_origHInfo; - break; - case EScriptObjectMessage::Increment: - x300_27_invulnerable = true; - break; - case EScriptObjectMessage::Decrement: - x300_27_invulnerable = false; - break; - default: - break; +void CScriptDamageableTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Deactivate: + if (x30_24_active && x300_25_alphaOut) + return; + [[fallthrough]]; + case EScriptObjectMessage::Activate: + if (!x30_24_active || x300_25_alphaOut) { + x250_alphaTimer = 0.f; + x16c_hInfo = x164_origHInfo; + x300_25_alphaOut = false; + if (x300_28_canOrbit) + AddMaterial(EMaterialTypes::Orbit, mgr); + SetLinkedObjectAlpha(0.f, mgr); + x1e0_alpha = 0.f; } + break; + case EScriptObjectMessage::Damage: + if (x300_27_invulnerable) + x16c_hInfo = x164_origHInfo; + break; + case EScriptObjectMessage::Increment: + x300_27_invulnerable = true; + break; + case EScriptObjectMessage::Decrement: + x300_27_invulnerable = false; + break; + default: + break; + } - CActor::AcceptScriptMsg(msg, sender, mgr); + CActor::AcceptScriptMsg(msg, sender, mgr); } -EWeaponCollisionResponseTypes -CScriptDamageableTrigger::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode& weapMode, EProjectileAttrib) const -{ - return x174_dVuln.WeaponHurts(weapMode, false) ? EWeaponCollisionResponseTypes::OtherProjectile : - EWeaponCollisionResponseTypes::Unknown15; +EWeaponCollisionResponseTypes CScriptDamageableTrigger::GetCollisionResponseType(const zeus::CVector3f&, + const zeus::CVector3f&, + const CWeaponMode& weapMode, + EProjectileAttrib) const { + return x174_dVuln.WeaponHurts(weapMode, false) ? EWeaponCollisionResponseTypes::OtherProjectile + : EWeaponCollisionResponseTypes::Unknown15; } -void CScriptDamageableTrigger::Render(const CStateManager& mgr) const -{ - if (x30_24_active && x1dc_faceFlag != 0 && std::fabs(x1e0_alpha) >= 0.00001f) - { - zeus::CAABox aabb = x14c_bounds.getTransformedAABox(x214_faceDirInv); - zeus::CTransform xf = x34_transform * zeus::CTransform::Translate(x244_faceTranslate) * x1e4_faceDir; - x254_fluidPlane.Render(mgr, x1e0_alpha, aabb, xf, zeus::CTransform::Identity(), false, - xe8_frustum, {}, kInvalidUniqueId, nullptr, 0, 0, zeus::CVector3f::skZero); +void CScriptDamageableTrigger::Render(const CStateManager& mgr) const { + if (x30_24_active && x1dc_faceFlag != 0 && std::fabs(x1e0_alpha) >= 0.00001f) { + zeus::CAABox aabb = x14c_bounds.getTransformedAABox(x214_faceDirInv); + zeus::CTransform xf = x34_transform * zeus::CTransform::Translate(x244_faceTranslate) * x1e4_faceDir; + x254_fluidPlane.Render(mgr, x1e0_alpha, aabb, xf, zeus::CTransform::Identity(), false, xe8_frustum, {}, + kInvalidUniqueId, nullptr, 0, 0, zeus::CVector3f::skZero); + } + + CActor::Render(mgr); +} + +void CScriptDamageableTrigger::AddToRenderer(const zeus::CFrustum& /*frustum*/, const CStateManager& mgr) const { + if (x300_26_outOfFrustum) + return; + EnsureRendered(mgr, GetTranslation() - x244_faceTranslate, GetSortingBounds(mgr)); +} + +void CScriptDamageableTrigger::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + x300_26_outOfFrustum = !frustum.aabbFrustumTest(x14c_bounds.getTransformedAABox(x34_transform)); + if (!x300_26_outOfFrustum) { + xe8_frustum = frustum; + CActor::PreRender(mgr, frustum); + } +} + +void CScriptDamageableTrigger::SetLinkedObjectAlpha(float a, CStateManager& mgr) { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::MaxReached || conn.x4_msg != EScriptObjectMessage::Activate) + continue; + if (TCastToPtr act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) { + if (!act->GetActive()) + act->SetActive(true); + act->SetDrawFlags(CModelFlags(5, 0, 3, zeus::CColor(1.f, a))); } - - CActor::Render(mgr); + } } -void CScriptDamageableTrigger::AddToRenderer(const zeus::CFrustum& /*frustum*/, const CStateManager& mgr) const -{ - if (x300_26_outOfFrustum) - return; - EnsureRendered(mgr, GetTranslation() - x244_faceTranslate, GetSortingBounds(mgr)); +float CScriptDamageableTrigger::GetPuddleAlphaScale() const { + if (x250_alphaTimer <= 0.75f) { + if (x300_25_alphaOut) + return 1.f - x250_alphaTimer / 0.75f; + return x250_alphaTimer / 0.75f; + } + + if (x300_25_alphaOut) + return 0.f; + return 1.f; } -void CScriptDamageableTrigger::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - x300_26_outOfFrustum = !frustum.aabbFrustumTest(x14c_bounds.getTransformedAABox(x34_transform)); - if (!x300_26_outOfFrustum) - { - xe8_frustum = frustum; - CActor::PreRender(mgr, frustum); - } -} +void CScriptDamageableTrigger::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; -void CScriptDamageableTrigger::SetLinkedObjectAlpha(float a, CStateManager& mgr) -{ - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::MaxReached || - conn.x4_msg != EScriptObjectMessage::Activate) - continue; + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); + CGameArea::EOcclusionState occState = + area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; + x300_24_notOccluded = occState == CGameArea::EOcclusionState::Visible; + + if (x300_25_alphaOut) { + if (x250_alphaTimer >= 0.75f) { + SetActive(false); + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::MaxReached || conn.x4_msg != EScriptObjectMessage::Activate) + continue; if (TCastToPtr act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) - { - if (!act->GetActive()) - act->SetActive(true); - act->SetDrawFlags(CModelFlags(5, 0, 3, zeus::CColor(1.f, a))); - } + act->SetActive(false); + } + + SetLinkedObjectAlpha(0.f, mgr); + x300_25_alphaOut = false; + return; } + } else if (x16c_hInfo.GetHP() <= 0.f && x30_24_active) { + SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); + RemoveMaterial(EMaterialTypes::Orbit, mgr); + x300_25_alphaOut = true; + x250_alphaTimer = 0.f; + } + + if (x250_alphaTimer <= 0.75f) + x250_alphaTimer += dt; + + float objAlpha = GetPuddleAlphaScale(); + x1e0_alpha = 0.2f * objAlpha; + SetLinkedObjectAlpha(objAlpha, mgr); } -float CScriptDamageableTrigger::GetPuddleAlphaScale() const -{ - if (x250_alphaTimer <= 0.75f) - { - if (x300_25_alphaOut) - return 1.f - x250_alphaTimer / 0.75f; - return x250_alphaTimer / 0.75f; - } - - if (x300_25_alphaOut) - return 0.f; - return 1.f; +std::experimental::optional CScriptDamageableTrigger::GetTouchBounds() const { + if (x30_24_active && x300_24_notOccluded) + return {zeus::CAABox(x14c_bounds.min + GetTranslation(), x14c_bounds.max + GetTranslation())}; + return {}; } -void CScriptDamageableTrigger::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; - - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); - CGameArea::EOcclusionState occState = - area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; - x300_24_notOccluded = occState == CGameArea::EOcclusionState::Visible; - - if (x300_25_alphaOut) - { - if (x250_alphaTimer >= 0.75f) - { - SetActive(false); - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::MaxReached || - conn.x4_msg != EScriptObjectMessage::Activate) - continue; - if (TCastToPtr act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) - act->SetActive(false); - } - - SetLinkedObjectAlpha(0.f, mgr); - x300_25_alphaOut = false; - return; - } - } - else if (x16c_hInfo.GetHP() <= 0.f && x30_24_active) - { - SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); - RemoveMaterial(EMaterialTypes::Orbit, mgr); - x300_25_alphaOut = true; - x250_alphaTimer = 0.f; - } - - if (x250_alphaTimer <= 0.75f) - x250_alphaTimer += dt; - - float objAlpha = GetPuddleAlphaScale(); - x1e0_alpha = 0.2f * objAlpha; - SetLinkedObjectAlpha(objAlpha, mgr); -} - -std::experimental::optional CScriptDamageableTrigger::GetTouchBounds() const -{ - if (x30_24_active && x300_24_notOccluded) - return {zeus::CAABox(x14c_bounds.min + GetTranslation(), x14c_bounds.max + GetTranslation())}; - return {}; -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptDamageableTrigger.hpp b/Runtime/World/CScriptDamageableTrigger.hpp index 5d6af0e99..31fbaf492 100644 --- a/Runtime/World/CScriptDamageableTrigger.hpp +++ b/Runtime/World/CScriptDamageableTrigger.hpp @@ -5,63 +5,56 @@ #include "CHealthInfo.hpp" #include "CDamageVulnerability.hpp" -namespace urde -{ +namespace urde { class CVisorParameters; -class CScriptDamageableTrigger : public CActor -{ +class CScriptDamageableTrigger : public CActor { public: - enum class ECanOrbit - { - NoOrbit, - Orbit, - }; + enum class ECanOrbit { + NoOrbit, + Orbit, + }; - zeus::CFrustum xe8_frustum; - zeus::CAABox x14c_bounds; - CHealthInfo x164_origHInfo; - CHealthInfo x16c_hInfo; - CDamageVulnerability x174_dVuln; - u32 x1dc_faceFlag; - float x1e0_alpha = 1.f; - zeus::CTransform x1e4_faceDir; - zeus::CTransform x214_faceDirInv; - zeus::CVector3f x244_faceTranslate; - float x250_alphaTimer = 0.f; - CFluidPlaneDoor x254_fluidPlane; - union - { - struct - { - bool x300_24_notOccluded : 1; - bool x300_25_alphaOut : 1; - bool x300_26_outOfFrustum : 1; - bool x300_27_invulnerable : 1; - bool x300_28_canOrbit : 1; - }; - u32 _dummy = 0; + zeus::CFrustum xe8_frustum; + zeus::CAABox x14c_bounds; + CHealthInfo x164_origHInfo; + CHealthInfo x16c_hInfo; + CDamageVulnerability x174_dVuln; + u32 x1dc_faceFlag; + float x1e0_alpha = 1.f; + zeus::CTransform x1e4_faceDir; + zeus::CTransform x214_faceDirInv; + zeus::CVector3f x244_faceTranslate; + float x250_alphaTimer = 0.f; + CFluidPlaneDoor x254_fluidPlane; + union { + struct { + bool x300_24_notOccluded : 1; + bool x300_25_alphaOut : 1; + bool x300_26_outOfFrustum : 1; + bool x300_27_invulnerable : 1; + bool x300_28_canOrbit : 1; }; - void SetLinkedObjectAlpha(float a, CStateManager& mgr); - float GetPuddleAlphaScale() const; + u32 _dummy = 0; + }; + void SetLinkedObjectAlpha(float a, CStateManager& mgr); + float GetPuddleAlphaScale() const; + public: - CScriptDamageableTrigger(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CVector3f& position, const zeus::CVector3f& extent, - const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, - u32 faceFlag, CAssetId patternTex1, CAssetId patternTex2, - CAssetId colorTex, ECanOrbit canOrbit, bool active, - const CVisorParameters& vParams); + CScriptDamageableTrigger(TUniqueId uid, std::string_view name, const CEntityInfo& info, + const zeus::CVector3f& position, const zeus::CVector3f& extent, const CHealthInfo& hInfo, + const CDamageVulnerability& dVuln, u32 faceFlag, CAssetId patternTex1, CAssetId patternTex2, + CAssetId colorTex, ECanOrbit canOrbit, bool active, const CVisorParameters& vParams); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const; - void Render(const CStateManager& mgr) const; - void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; - void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); - const CDamageVulnerability* GetDamageVulnerability() const { return &x174_dVuln; } - CHealthInfo* HealthInfo(CStateManager&) { return &x16c_hInfo; } - void Think(float, CStateManager&); - std::experimental::optional GetTouchBounds() const; + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, + const CWeaponMode&, EProjectileAttrib) const; + void Render(const CStateManager& mgr) const; + void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; + void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); + const CDamageVulnerability* GetDamageVulnerability() const { return &x174_dVuln; } + CHealthInfo* HealthInfo(CStateManager&) { return &x16c_hInfo; } + void Think(float, CStateManager&); + std::experimental::optional GetTouchBounds() const; }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptDebris.cpp b/Runtime/World/CScriptDebris.cpp index 5b6d9bcd6..ced24600d 100644 --- a/Runtime/World/CScriptDebris.cpp +++ b/Runtime/World/CScriptDebris.cpp @@ -7,8 +7,7 @@ #include "CStateManager.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& aParams, CAssetId particleId, @@ -17,41 +16,47 @@ CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntity EScaleType scaleType, bool b1, bool randomAngImpulse, bool active) : CPhysicsActor(uid, active, name, info, xf, std::move(mData), CMaterialList(EMaterialTypes::Solid, EMaterialTypes::Debris), mData.GetBounds(xf.getRotation()), - SMoverData(mass), aParams, 0.3f, 0.1f), x258_velocity(velocity), x264_color(1.f, 0.5f, 0.5f, 1.f), - x268_endsColor(endsColor), x26c_zImpulse(zImpulse), x274_duration(duration >= 0.f ? duration : 0.5f), - x278_ooDuration(1.f / x274_duration), x27c_restitution(restitution), - x280_scaleType(scaleType), x2b0_scale(mData.GetScale()), x2e0_speedAvg(2.f) -{ - x281_24_randomAngImpulse = randomAngImpulse; - if (scaleType == EScaleType::NoScale) - x2bc_endScale = mData.GetScale(); - else if (scaleType == EScaleType::EndsToZero) - x2bc_endScale = zeus::CVector3f::skZero; - else - x2bc_endScale.splat(5.f); + SMoverData(mass), aParams, 0.3f, 0.1f) +, x258_velocity(velocity) +, x264_color(1.f, 0.5f, 0.5f, 1.f) +, x268_endsColor(endsColor) +, x26c_zImpulse(zImpulse) +, x274_duration(duration >= 0.f ? duration : 0.5f) +, x278_ooDuration(1.f / x274_duration) +, x27c_restitution(restitution) +, x280_scaleType(scaleType) +, x2b0_scale(mData.GetScale()) +, x2e0_speedAvg(2.f) { + x281_24_randomAngImpulse = randomAngImpulse; + if (scaleType == EScaleType::NoScale) + x2bc_endScale = mData.GetScale(); + else if (scaleType == EScaleType::EndsToZero) + x2bc_endScale = zeus::CVector3f::skZero; + else + x2bc_endScale.splat(5.f); - xe7_30_doTargetDistanceTest = false; + xe7_30_doTargetDistanceTest = false; - if (x90_actorLights) - x90_actorLights->SetAreaUpdateFramePeriod(x90_actorLights->GetAreaUpdateFramePeriod() * 2); + if (x90_actorLights) + x90_actorLights->SetAreaUpdateFramePeriod(x90_actorLights->GetAreaUpdateFramePeriod() * 2); - SetUseInSortedLists(false); + SetUseInSortedLists(false); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::Debris, EMaterialTypes::Character, EMaterialTypes::Player, EMaterialTypes::Projectile})); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, + {EMaterialTypes::Debris, EMaterialTypes::Character, EMaterialTypes::Player, EMaterialTypes::Projectile})); - if (g_ResFactory->GetResourceTypeById(particleId)) - { - TToken desc = g_SimplePool->GetObj({FOURCC('PART'), particleId}); - x2d4_particleGens[0] = std::make_unique(desc, CElementGen::EModelOrientationType::Normal, - CElementGen::EOptionalSystemFlags::One); - x2d4_particleGens[0]->SetGlobalScale(particleScale); - } + if (g_ResFactory->GetResourceTypeById(particleId)) { + TToken desc = g_SimplePool->GetObj({FOURCC('PART'), particleId}); + x2d4_particleGens[0] = std::make_unique(desc, CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One); + x2d4_particleGens[0]->SetGlobalScale(particleScale); + } - x150_momentum = zeus::CVector3f(0.f, 0.f, -24.525f * xe8_mass); + x150_momentum = zeus::CVector3f(0.f, 0.f, -24.525f * xe8_mass); - if (x90_actorLights) - x90_actorLights->SetAmbienceGenerated(true); + if (x90_actorLights) + x90_actorLights->SetAmbienceGenerated(true); } CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, @@ -61,367 +66,321 @@ CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntity float scaleOutStartT, const zeus::CVector3f& scale, const zeus::CVector3f& endScale, float restitution, float downwardSpeed, const zeus::CVector3f& localOffset, CAssetId particle1, const zeus::CVector3f& particle1Scale, bool particle1GlobalTranslation, - bool deferDeleteTillParticle1Done, EOrientationType particle1Or, - CAssetId particle2, const zeus::CVector3f& particle2Scale, bool particle2GlobalTranslation, - bool deferDeleteTillParticle2Done, EOrientationType particle2Or, - CAssetId particle3, const zeus::CVector3f& particle3Scale, EOrientationType particle3Or, - bool solid, bool dieOnProjectile, bool noBounce, bool active) + bool deferDeleteTillParticle1Done, EOrientationType particle1Or, CAssetId particle2, + const zeus::CVector3f& particle2Scale, bool particle2GlobalTranslation, + bool deferDeleteTillParticle2Done, EOrientationType particle2Or, CAssetId particle3, + const zeus::CVector3f& particle3Scale, EOrientationType particle3Or, bool solid, + bool dieOnProjectile, bool noBounce, bool active) : CPhysicsActor( uid, active, name, info, xf, std::move(mData), CMaterialList(EMaterialTypes::Solid, EMaterialTypes::Debris), (mData.HasAnimData() || mData.HasNormalModel() ? mData.GetBounds(xf.getRotation()) : zeus::CAABox{-0.5f, 0.5f}), - SMoverData(1.f), aParams, 0.3f, 0.1f), x264_color(color), x268_endsColor(endsColor), - x27c_restitution(restitution), x288_linConeAngle(linConeAngle), x28c_linMinMag(linMinMag), x290_linMaxMag(linMaxMag), - x294_angMinMag(angMinMag), x298_angMaxMag(angMaxMag), x29c_minDuration(minDuration), x2a0_maxDuration(maxDuration), - x2a4_colorInT(colorInT / 100.f), x2a8_colorOutT(colorOutT / 100.f), x2ac_scaleOutStartT(scaleOutStartT / 100.f), - x2b0_scale(scale), x2bc_endScale(scale * endScale), x2e0_speedAvg(2.f) -{ - x281_25_particle1GlobalTranslation = particle1GlobalTranslation; - x281_26_deferDeleteTillParticle1Done = deferDeleteTillParticle1Done; - x281_27_particle2GlobalTranslation = particle2GlobalTranslation; - x281_28_deferDeleteTillParticle2Done = deferDeleteTillParticle2Done; - x281_30_debrisExtended = true; - x281_31_dieOnProjectile = dieOnProjectile; - x282_24_noBounce = noBounce; - x283_particleOrs[0] = particle1Or; - x283_particleOrs[1] = particle2Or; - x283_particleOrs[2] = particle3Or; + SMoverData(1.f), aParams, 0.3f, 0.1f) +, x264_color(color) +, x268_endsColor(endsColor) +, x27c_restitution(restitution) +, x288_linConeAngle(linConeAngle) +, x28c_linMinMag(linMinMag) +, x290_linMaxMag(linMaxMag) +, x294_angMinMag(angMinMag) +, x298_angMaxMag(angMaxMag) +, x29c_minDuration(minDuration) +, x2a0_maxDuration(maxDuration) +, x2a4_colorInT(colorInT / 100.f) +, x2a8_colorOutT(colorOutT / 100.f) +, x2ac_scaleOutStartT(scaleOutStartT / 100.f) +, x2b0_scale(scale) +, x2bc_endScale(scale * endScale) +, x2e0_speedAvg(2.f) { + x281_25_particle1GlobalTranslation = particle1GlobalTranslation; + x281_26_deferDeleteTillParticle1Done = deferDeleteTillParticle1Done; + x281_27_particle2GlobalTranslation = particle2GlobalTranslation; + x281_28_deferDeleteTillParticle2Done = deferDeleteTillParticle2Done; + x281_30_debrisExtended = true; + x281_31_dieOnProjectile = dieOnProjectile; + x282_24_noBounce = noBounce; + x283_particleOrs[0] = particle1Or; + x283_particleOrs[1] = particle2Or; + x283_particleOrs[2] = particle3Or; - SetUseInSortedLists(false); + SetUseInSortedLists(false); - SetTranslation(x34_transform.rotate(localOffset) + x34_transform.origin); + SetTranslation(x34_transform.rotate(localOffset) + x34_transform.origin); - if (solid) - { - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, - {EMaterialTypes::Debris, EMaterialTypes::Character, EMaterialTypes::Player})); - } - else - { - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude({}, - {EMaterialTypes::Debris, EMaterialTypes::Character, EMaterialTypes::Player, - EMaterialTypes::Projectile, EMaterialTypes::Solid})); - } + if (solid) { + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + {EMaterialTypes::Solid}, {EMaterialTypes::Debris, EMaterialTypes::Character, EMaterialTypes::Player})); + } else { + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude({}, {EMaterialTypes::Debris, EMaterialTypes::Character, + EMaterialTypes::Player, EMaterialTypes::Projectile, + EMaterialTypes::Solid})); + } - if (g_ResFactory->GetResourceTypeById(particle1)) - { - TToken desc = g_SimplePool->GetObj({FOURCC('PART'), particle1}); - x2d4_particleGens[0] = std::make_unique(desc, CElementGen::EModelOrientationType::Normal, - CElementGen::EOptionalSystemFlags::One); - x2d4_particleGens[0]->SetGlobalScale(particle1Scale); - } + if (g_ResFactory->GetResourceTypeById(particle1)) { + TToken desc = g_SimplePool->GetObj({FOURCC('PART'), particle1}); + x2d4_particleGens[0] = std::make_unique(desc, CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One); + x2d4_particleGens[0]->SetGlobalScale(particle1Scale); + } - if (g_ResFactory->GetResourceTypeById(particle2)) - { - TToken desc = g_SimplePool->GetObj({FOURCC('PART'), particle2}); - x2d4_particleGens[1] = std::make_unique(desc, CElementGen::EModelOrientationType::Normal, - CElementGen::EOptionalSystemFlags::One); - x2d4_particleGens[1]->SetGlobalScale(particle2Scale); - } + if (g_ResFactory->GetResourceTypeById(particle2)) { + TToken desc = g_SimplePool->GetObj({FOURCC('PART'), particle2}); + x2d4_particleGens[1] = std::make_unique(desc, CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One); + x2d4_particleGens[1]->SetGlobalScale(particle2Scale); + } - if (g_ResFactory->GetResourceTypeById(particle3)) - { - TToken desc = g_SimplePool->GetObj({FOURCC('PART'), particle3}); - x2d4_particleGens[2] = std::make_unique(desc, CElementGen::EModelOrientationType::Normal, - CElementGen::EOptionalSystemFlags::One); - x2d4_particleGens[2]->SetGlobalScale(particle3Scale); - } + if (g_ResFactory->GetResourceTypeById(particle3)) { + TToken desc = g_SimplePool->GetObj({FOURCC('PART'), particle3}); + x2d4_particleGens[2] = std::make_unique(desc, CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One); + x2d4_particleGens[2]->SetGlobalScale(particle3Scale); + } - x150_momentum = zeus::CVector3f(0.f, 0.f, -downwardSpeed * xe8_mass); + x150_momentum = zeus::CVector3f(0.f, 0.f, -downwardSpeed * xe8_mass); } void CScriptDebris::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptDebris::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - if (x2d4_particleGens[0]) - if (x270_curTime < x274_duration || x281_26_deferDeleteTillParticle1Done) - g_Renderer->AddParticleGen(*x2d4_particleGens[0]); +void CScriptDebris::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + if (x2d4_particleGens[0]) + if (x270_curTime < x274_duration || x281_26_deferDeleteTillParticle1Done) + g_Renderer->AddParticleGen(*x2d4_particleGens[0]); - if (x2d4_particleGens[1]) - if (x270_curTime < x274_duration || x281_28_deferDeleteTillParticle2Done) - g_Renderer->AddParticleGen(*x2d4_particleGens[1]); + if (x2d4_particleGens[1]) + if (x270_curTime < x274_duration || x281_28_deferDeleteTillParticle2Done) + g_Renderer->AddParticleGen(*x2d4_particleGens[1]); - if (x281_29_particle3Active) - g_Renderer->AddParticleGen(*x2d4_particleGens[2]); + if (x281_29_particle3Active) + g_Renderer->AddParticleGen(*x2d4_particleGens[2]); - if (x64_modelData && !x64_modelData->IsNull()) - if (x270_curTime < x274_duration) - CActor::AddToRenderer(frustum, mgr); + if (x64_modelData && !x64_modelData->IsNull()) + if (x270_curTime < x274_duration) + CActor::AddToRenderer(frustum, mgr); } -static zeus::CVector3f debris_cone(CStateManager& mgr, float coneAng, float minMag, float maxMag) -{ - float mag = mgr.GetActiveRandom()->Float() * (maxMag - minMag) + minMag; - float side = 1.f - (1.f - std::cos(zeus::degToRad(coneAng * 0.5f))) * mgr.GetActiveRandom()->Float(); - float hyp = std::max(0.f, 1.f - side * side); - if (hyp != 0.f) - hyp = std::sqrt(hyp); - hyp *= mag; - float ang = mgr.GetActiveRandom()->Float() * 2.f * M_PIF; - return {std::cos(ang) * hyp, std::sin(ang) * hyp, mag * side}; +static zeus::CVector3f debris_cone(CStateManager& mgr, float coneAng, float minMag, float maxMag) { + float mag = mgr.GetActiveRandom()->Float() * (maxMag - minMag) + minMag; + float side = 1.f - (1.f - std::cos(zeus::degToRad(coneAng * 0.5f))) * mgr.GetActiveRandom()->Float(); + float hyp = std::max(0.f, 1.f - side * side); + if (hyp != 0.f) + hyp = std::sqrt(hyp); + hyp *= mag; + float ang = mgr.GetActiveRandom()->Float() * 2.f * M_PIF; + return {std::cos(ang) * hyp, std::sin(ang) * hyp, mag * side}; } -void CScriptDebris::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Activate: - if (!x281_30_debrisExtended) - { - zeus::CVector3f linImpulse; - linImpulse.z() = std::fabs(mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * - xe8_mass * x258_velocity.z() + x26c_zImpulse; - linImpulse.y() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * - xe8_mass * x258_velocity.y(); - linImpulse.x() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * - xe8_mass * x258_velocity.x(); - linImpulse += x34_transform.basis[2]; - zeus::CAxisAngle angImpulse; - if (x281_24_randomAngImpulse) - { - if (mgr.GetActiveRandom()->Next() % 100 < 50) - { - zeus::CVector3f rotVec; - rotVec.x() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * 45.f; - rotVec.y() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * 15.f; - rotVec.z() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * 35.f; - angImpulse = zeus::CAxisAngle(rotVec); - } - } - ApplyImpulseWR(linImpulse, angImpulse); +void CScriptDebris::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Activate: + if (!x281_30_debrisExtended) { + zeus::CVector3f linImpulse; + linImpulse.z() = + std::fabs(mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * xe8_mass * x258_velocity.z() + + x26c_zImpulse; + linImpulse.y() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * xe8_mass * x258_velocity.y(); + linImpulse.x() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * xe8_mass * x258_velocity.x(); + linImpulse += x34_transform.basis[2]; + zeus::CAxisAngle angImpulse; + if (x281_24_randomAngImpulse) { + if (mgr.GetActiveRandom()->Next() % 100 < 50) { + zeus::CVector3f rotVec; + rotVec.x() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * 45.f; + rotVec.y() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * 15.f; + rotVec.z() = (mgr.GetActiveRandom()->Next() % 32767 / 16383.5f - 1.f) * 35.f; + angImpulse = zeus::CAxisAngle(rotVec); } - else - { - zeus::CVector3f linImpulse = debris_cone(mgr, x288_linConeAngle, x28c_linMinMag, x290_linMaxMag); - zeus::CVector3f angImpulse = debris_cone(mgr, 360.f, x294_angMinMag, x298_angMaxMag); - ApplyImpulseOR(linImpulse, angImpulse); - x274_duration = mgr.GetActiveRandom()->Float() * (x2a0_maxDuration - x29c_minDuration) + x29c_minDuration; - } - - if (x2d4_particleGens[0]) - x2d4_particleGens[0]->SetParticleEmission(true); - if (x2d4_particleGens[1]) - x2d4_particleGens[1]->SetParticleEmission(true); - break; - case EScriptObjectMessage::OnFloor: - if (!x282_24_noBounce) - ApplyImpulseWR(-x27c_restitution * xfc_constantForce, -x27c_restitution * x108_angularMomentum); - break; - default: - break; + } + ApplyImpulseWR(linImpulse, angImpulse); + } else { + zeus::CVector3f linImpulse = debris_cone(mgr, x288_linConeAngle, x28c_linMinMag, x290_linMaxMag); + zeus::CVector3f angImpulse = debris_cone(mgr, 360.f, x294_angMinMag, x298_angMaxMag); + ApplyImpulseOR(linImpulse, angImpulse); + x274_duration = mgr.GetActiveRandom()->Float() * (x2a0_maxDuration - x29c_minDuration) + x29c_minDuration; } - CActor::AcceptScriptMsg(msg, sender, mgr); -} - -void CScriptDebris::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; - - x270_curTime += dt; - bool done = x270_curTime >= x274_duration; - if (x2d4_particleGens[0]) - { - if (x270_curTime >= x274_duration) - { - x2d4_particleGens[0]->SetParticleEmission(false); - } - else - { - if (x281_25_particle1GlobalTranslation) - x2d4_particleGens[0]->SetGlobalTranslation(GetTranslation()); - else - x2d4_particleGens[0]->SetTranslation(GetTranslation()); - - if (x283_particleOrs[0] == EOrientationType::AlongVelocity) - { - if (x138_velocity.canBeNormalized()) - { - zeus::CVector3f normVel = x138_velocity.normalized(); - zeus::CTransform orient = - zeus::lookAt(zeus::CVector3f::skZero, normVel, - std::fabs(normVel.z()) < 0.99f ? zeus::CVector3f::skUp : zeus::CVector3f::skForward); - x2d4_particleGens[0]->SetOrientation(orient); - } - } - else if (x283_particleOrs[0] == EOrientationType::ToObject) - { - x2d4_particleGens[0]->SetOrientation(x34_transform.getRotation()); - } - } - - if (x281_26_deferDeleteTillParticle1Done && x2d4_particleGens[0]->GetParticleCount() != 0) - done = false; - - if (x270_curTime < x274_duration || x281_26_deferDeleteTillParticle1Done) - x2d4_particleGens[0]->Update(dt); - } - + x2d4_particleGens[0]->SetParticleEmission(true); if (x2d4_particleGens[1]) - { - if (x270_curTime >= x274_duration) - { - x2d4_particleGens[1]->SetParticleEmission(false); - } - else - { - if (x281_27_particle2GlobalTranslation) - x2d4_particleGens[1]->SetGlobalTranslation(GetTranslation()); - else - x2d4_particleGens[1]->SetTranslation(GetTranslation()); + x2d4_particleGens[1]->SetParticleEmission(true); + break; + case EScriptObjectMessage::OnFloor: + if (!x282_24_noBounce) + ApplyImpulseWR(-x27c_restitution * xfc_constantForce, -x27c_restitution * x108_angularMomentum); + break; + default: + break; + } - if (x283_particleOrs[1] == EOrientationType::AlongVelocity) - { - if (x138_velocity.canBeNormalized()) - { - zeus::CVector3f normVel = x138_velocity.normalized(); - zeus::CTransform orient = - zeus::lookAt(zeus::CVector3f::skZero, normVel, - std::fabs(normVel.z()) < 0.99f ? zeus::CVector3f::skUp : zeus::CVector3f::skForward); - x2d4_particleGens[1]->SetOrientation(orient); - } - } - else if (x283_particleOrs[1] == EOrientationType::ToObject) - { - x2d4_particleGens[1]->SetOrientation(x34_transform.getRotation()); - } - } - - if (x281_28_deferDeleteTillParticle2Done && x2d4_particleGens[1]->GetParticleCount() != 0) - done = false; - - if (x270_curTime < x274_duration || x281_28_deferDeleteTillParticle2Done) - x2d4_particleGens[1]->Update(dt); - } - - /* End particle */ - if (x2d4_particleGens[2]) - { - if (x270_curTime >= x274_duration && !x281_29_particle3Active) - { - x2d4_particleGens[2]->SetGlobalTranslation(GetTranslation()); - - if (x283_particleOrs[2] == EOrientationType::AlongVelocity) - { - if (x138_velocity.canBeNormalized()) - { - zeus::CVector3f normVel = x138_velocity.normalized(); - zeus::CTransform orient = - zeus::lookAt(zeus::CVector3f::skZero, normVel, - std::fabs(normVel.z()) < 0.99f ? zeus::CVector3f::skUp : zeus::CVector3f::skForward); - x2d4_particleGens[2]->SetOrientation(orient); - } - } - else if (x283_particleOrs[2] == EOrientationType::ToObject) - { - x2d4_particleGens[2]->SetOrientation(x34_transform.getRotation()); - } - else if (x283_particleOrs[2] == EOrientationType::AlongCollisionNormal) - { - if (x2c8_collisionNormal.magSquared() == 0.f) - x2c8_collisionNormal = zeus::CVector3f::skUp; - zeus::CTransform orient = - zeus::lookAt(zeus::CVector3f::skZero, x2c8_collisionNormal, - std::fabs(x2c8_collisionNormal.dot(zeus::CVector3f::skUp)) > 0.99f ? - zeus::CVector3f::skRight : zeus::CVector3f::skUp); - x2d4_particleGens[2]->SetOrientation(orient); - } - - x281_29_particle3Active = true; - } - - if (x281_29_particle3Active) - { - x2d4_particleGens[2]->Update(dt); - if (!x2d4_particleGens[2]->IsSystemDeletable()) - done = false; - } - } - - if (x64_modelData && !x64_modelData->IsNull()) - { - float t = x270_curTime / x274_duration > x2ac_scaleOutStartT ? - (x270_curTime - x2ac_scaleOutStartT * x274_duration) / ((1.f - x2ac_scaleOutStartT) * x274_duration) : 0.f; - x64_modelData->SetScale(zeus::CVector3f::lerp(x2b0_scale, x2bc_endScale, t)); - } - - if (x270_curTime >= x274_duration) - { - x150_momentum = zeus::CVector3f::skZero; - SetMaterialFilter(CMaterialFilter::MakeExclude({EMaterialTypes::Debris, EMaterialTypes::Character, - EMaterialTypes::Player, EMaterialTypes::Projectile})); - - if (done) - { - mgr.FreeScriptObject(x8_uid); - return; - } - } - - if (xf8_24_movable) - { - float speed = x138_velocity.magnitude(); - x2e0_speedAvg.AddValue(speed); - if (x2e0_speedAvg.GetAverage() < 0.1f) - xf8_24_movable = false; - } + CActor::AcceptScriptMsg(msg, sender, mgr); } -void CScriptDebris::Touch(CActor& other, CStateManager& mgr) -{ - if (x281_31_dieOnProjectile) - { - if (TCastToPtr(other)) - { - SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); - mgr.FreeScriptObject(x8_uid); +void CScriptDebris::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; + + x270_curTime += dt; + bool done = x270_curTime >= x274_duration; + + if (x2d4_particleGens[0]) { + if (x270_curTime >= x274_duration) { + x2d4_particleGens[0]->SetParticleEmission(false); + } else { + if (x281_25_particle1GlobalTranslation) + x2d4_particleGens[0]->SetGlobalTranslation(GetTranslation()); + else + x2d4_particleGens[0]->SetTranslation(GetTranslation()); + + if (x283_particleOrs[0] == EOrientationType::AlongVelocity) { + if (x138_velocity.canBeNormalized()) { + zeus::CVector3f normVel = x138_velocity.normalized(); + zeus::CTransform orient = + zeus::lookAt(zeus::CVector3f::skZero, normVel, + std::fabs(normVel.z()) < 0.99f ? zeus::CVector3f::skUp : zeus::CVector3f::skForward); + x2d4_particleGens[0]->SetOrientation(orient); } + } else if (x283_particleOrs[0] == EOrientationType::ToObject) { + x2d4_particleGens[0]->SetOrientation(x34_transform.getRotation()); + } } -} -std::experimental::optional CScriptDebris::GetTouchBounds() const -{ - if (x281_31_dieOnProjectile) - return {GetBoundingBox()}; - return {}; -} + if (x281_26_deferDeleteTillParticle1Done && x2d4_particleGens[0]->GetParticleCount() != 0) + done = false; -void CScriptDebris::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - CActor::PreRender(mgr, frustum); + if (x270_curTime < x274_duration || x281_26_deferDeleteTillParticle1Done) + x2d4_particleGens[0]->Update(dt); + } - float t = x270_curTime / x274_duration; - if (t < x2a4_colorInT) - t = x2a4_colorInT > 0.f ? 1.f - x270_curTime / (x274_duration * x2a4_colorInT) : 0.f; - else if (t > x2a8_colorOutT) - t = (x270_curTime - x274_duration * x2a8_colorOutT) / (x274_duration * (1.f - x2a8_colorOutT)); - else - t = 0.f; + if (x2d4_particleGens[1]) { + if (x270_curTime >= x274_duration) { + x2d4_particleGens[1]->SetParticleEmission(false); + } else { + if (x281_27_particle2GlobalTranslation) + x2d4_particleGens[1]->SetGlobalTranslation(GetTranslation()); + else + x2d4_particleGens[1]->SetTranslation(GetTranslation()); - xb4_drawFlags = CModelFlags(5, 0, 3, zeus::CColor::lerp(zeus::CColor::skWhite, x268_endsColor, t)); -} - -void CScriptDebris::Render(const CStateManager& mgr) const -{ - CPhysicsActor::Render(mgr); -} - -void CScriptDebris::CollidedWith(TUniqueId, const CCollisionInfoList& colList, CStateManager&) -{ - if (colList.GetCount() == 0) - return; - - if (x282_24_noBounce) - { - x274_duration = x270_curTime; - SetVelocityWR(zeus::CVector3f::skZero); + if (x283_particleOrs[1] == EOrientationType::AlongVelocity) { + if (x138_velocity.canBeNormalized()) { + zeus::CVector3f normVel = x138_velocity.normalized(); + zeus::CTransform orient = + zeus::lookAt(zeus::CVector3f::skZero, normVel, + std::fabs(normVel.z()) < 0.99f ? zeus::CVector3f::skUp : zeus::CVector3f::skForward); + x2d4_particleGens[1]->SetOrientation(orient); + } + } else if (x283_particleOrs[1] == EOrientationType::ToObject) { + x2d4_particleGens[1]->SetOrientation(x34_transform.getRotation()); + } } - else - { - x2c8_collisionNormal = colList.GetItem(0).GetNormalLeft(); + + if (x281_28_deferDeleteTillParticle2Done && x2d4_particleGens[1]->GetParticleCount() != 0) + done = false; + + if (x270_curTime < x274_duration || x281_28_deferDeleteTillParticle2Done) + x2d4_particleGens[1]->Update(dt); + } + + /* End particle */ + if (x2d4_particleGens[2]) { + if (x270_curTime >= x274_duration && !x281_29_particle3Active) { + x2d4_particleGens[2]->SetGlobalTranslation(GetTranslation()); + + if (x283_particleOrs[2] == EOrientationType::AlongVelocity) { + if (x138_velocity.canBeNormalized()) { + zeus::CVector3f normVel = x138_velocity.normalized(); + zeus::CTransform orient = + zeus::lookAt(zeus::CVector3f::skZero, normVel, + std::fabs(normVel.z()) < 0.99f ? zeus::CVector3f::skUp : zeus::CVector3f::skForward); + x2d4_particleGens[2]->SetOrientation(orient); + } + } else if (x283_particleOrs[2] == EOrientationType::ToObject) { + x2d4_particleGens[2]->SetOrientation(x34_transform.getRotation()); + } else if (x283_particleOrs[2] == EOrientationType::AlongCollisionNormal) { + if (x2c8_collisionNormal.magSquared() == 0.f) + x2c8_collisionNormal = zeus::CVector3f::skUp; + zeus::CTransform orient = + zeus::lookAt(zeus::CVector3f::skZero, x2c8_collisionNormal, + std::fabs(x2c8_collisionNormal.dot(zeus::CVector3f::skUp)) > 0.99f ? zeus::CVector3f::skRight + : zeus::CVector3f::skUp); + x2d4_particleGens[2]->SetOrientation(orient); + } + + x281_29_particle3Active = true; } + + if (x281_29_particle3Active) { + x2d4_particleGens[2]->Update(dt); + if (!x2d4_particleGens[2]->IsSystemDeletable()) + done = false; + } + } + + if (x64_modelData && !x64_modelData->IsNull()) { + float t = x270_curTime / x274_duration > x2ac_scaleOutStartT + ? (x270_curTime - x2ac_scaleOutStartT * x274_duration) / ((1.f - x2ac_scaleOutStartT) * x274_duration) + : 0.f; + x64_modelData->SetScale(zeus::CVector3f::lerp(x2b0_scale, x2bc_endScale, t)); + } + + if (x270_curTime >= x274_duration) { + x150_momentum = zeus::CVector3f::skZero; + SetMaterialFilter(CMaterialFilter::MakeExclude( + {EMaterialTypes::Debris, EMaterialTypes::Character, EMaterialTypes::Player, EMaterialTypes::Projectile})); + + if (done) { + mgr.FreeScriptObject(x8_uid); + return; + } + } + + if (xf8_24_movable) { + float speed = x138_velocity.magnitude(); + x2e0_speedAvg.AddValue(speed); + if (x2e0_speedAvg.GetAverage() < 0.1f) + xf8_24_movable = false; + } +} + +void CScriptDebris::Touch(CActor& other, CStateManager& mgr) { + if (x281_31_dieOnProjectile) { + if (TCastToPtr(other)) { + SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); + mgr.FreeScriptObject(x8_uid); + } + } +} + +std::experimental::optional CScriptDebris::GetTouchBounds() const { + if (x281_31_dieOnProjectile) + return {GetBoundingBox()}; + return {}; +} + +void CScriptDebris::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + CActor::PreRender(mgr, frustum); + + float t = x270_curTime / x274_duration; + if (t < x2a4_colorInT) + t = x2a4_colorInT > 0.f ? 1.f - x270_curTime / (x274_duration * x2a4_colorInT) : 0.f; + else if (t > x2a8_colorOutT) + t = (x270_curTime - x274_duration * x2a8_colorOutT) / (x274_duration * (1.f - x2a8_colorOutT)); + else + t = 0.f; + + xb4_drawFlags = CModelFlags(5, 0, 3, zeus::CColor::lerp(zeus::CColor::skWhite, x268_endsColor, t)); +} + +void CScriptDebris::Render(const CStateManager& mgr) const { CPhysicsActor::Render(mgr); } + +void CScriptDebris::CollidedWith(TUniqueId, const CCollisionInfoList& colList, CStateManager&) { + if (colList.GetCount() == 0) + return; + + if (x282_24_noBounce) { + x274_duration = x270_curTime; + SetVelocityWR(zeus::CVector3f::skZero); + } else { + x2c8_collisionNormal = colList.GetItem(0).GetNormalLeft(); + } } } // namespace urde diff --git a/Runtime/World/CScriptDebris.hpp b/Runtime/World/CScriptDebris.hpp index 0136c4a76..9c332d044 100644 --- a/Runtime/World/CScriptDebris.hpp +++ b/Runtime/World/CScriptDebris.hpp @@ -2,99 +2,83 @@ #include "CPhysicsActor.hpp" -namespace urde -{ +namespace urde { class CElementGen; -class CScriptDebris : public CPhysicsActor -{ +class CScriptDebris : public CPhysicsActor { public: - enum class EScaleType - { - NoScale, - EndsToZero - }; + enum class EScaleType { NoScale, EndsToZero }; - enum class EOrientationType - { - NotOriented, - AlongVelocity, - ToObject, - AlongCollisionNormal - }; + enum class EOrientationType { NotOriented, AlongVelocity, ToObject, AlongCollisionNormal }; private: - zeus::CVector3f x258_velocity; - zeus::CColor x264_color; - zeus::CColor x268_endsColor; - float x26c_zImpulse = 0.f; - float x270_curTime = 0.f; - float x274_duration = 0.f; - float x278_ooDuration = 0.f; - float x27c_restitution; - CScriptDebris::EScaleType x280_scaleType = CScriptDebris::EScaleType::NoScale; - union - { - struct - { - bool x281_24_randomAngImpulse : 1; - bool x281_25_particle1GlobalTranslation : 1; - bool x281_26_deferDeleteTillParticle1Done : 1; - bool x281_27_particle2GlobalTranslation : 1; - bool x281_28_deferDeleteTillParticle2Done : 1; - bool x281_29_particle3Active : 1; - bool x281_30_debrisExtended : 1; - bool x281_31_dieOnProjectile : 1; - bool x282_24_noBounce : 1; - }; - u32 _dummy = 0; + zeus::CVector3f x258_velocity; + zeus::CColor x264_color; + zeus::CColor x268_endsColor; + float x26c_zImpulse = 0.f; + float x270_curTime = 0.f; + float x274_duration = 0.f; + float x278_ooDuration = 0.f; + float x27c_restitution; + CScriptDebris::EScaleType x280_scaleType = CScriptDebris::EScaleType::NoScale; + union { + struct { + bool x281_24_randomAngImpulse : 1; + bool x281_25_particle1GlobalTranslation : 1; + bool x281_26_deferDeleteTillParticle1Done : 1; + bool x281_27_particle2GlobalTranslation : 1; + bool x281_28_deferDeleteTillParticle2Done : 1; + bool x281_29_particle3Active : 1; + bool x281_30_debrisExtended : 1; + bool x281_31_dieOnProjectile : 1; + bool x282_24_noBounce : 1; }; - EOrientationType x283_particleOrs[3] = {}; - float x288_linConeAngle = 0.f; - float x28c_linMinMag = 0.f; - float x290_linMaxMag = 0.f; - float x294_angMinMag = 0.f; - float x298_angMaxMag = 0.f; - float x29c_minDuration = 0.f; - float x2a0_maxDuration = 0.f; - float x2a4_colorInT = 0.f; - float x2a8_colorOutT = 0.f; - float x2ac_scaleOutStartT = 0.f; - zeus::CVector3f x2b0_scale; - zeus::CVector3f x2bc_endScale; - zeus::CVector3f x2c8_collisionNormal; - std::unique_ptr x2d4_particleGens[3]; /* x2d4, x2d8, x2dc */ - TReservedAverage x2e0_speedAvg; + u32 _dummy = 0; + }; + EOrientationType x283_particleOrs[3] = {}; + float x288_linConeAngle = 0.f; + float x28c_linMinMag = 0.f; + float x290_linMaxMag = 0.f; + float x294_angMinMag = 0.f; + float x298_angMaxMag = 0.f; + float x29c_minDuration = 0.f; + float x2a0_maxDuration = 0.f; + float x2a4_colorInT = 0.f; + float x2a8_colorOutT = 0.f; + float x2ac_scaleOutStartT = 0.f; + zeus::CVector3f x2b0_scale; + zeus::CVector3f x2bc_endScale; + zeus::CVector3f x2c8_collisionNormal; + std::unique_ptr x2d4_particleGens[3]; /* x2d4, x2d8, x2dc */ + TReservedAverage x2e0_speedAvg; public: - CScriptDebris(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const CActorParameters& aParams, CAssetId particleId, - const zeus::CVector3f& particleScale, float zImpulse, const zeus::CVector3f& velocity, - const zeus::CColor& endsColor, float mass, float restitution, float duration, - EScaleType scaleType, bool b1, bool randomAngImpulse, bool active); + CScriptDebris(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CActorParameters& aParams, CAssetId particleId, + const zeus::CVector3f& particleScale, float zImpulse, const zeus::CVector3f& velocity, + const zeus::CColor& endsColor, float mass, float restitution, float duration, EScaleType scaleType, + bool b1, bool randomAngImpulse, bool active); - CScriptDebris(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CModelData&& mData, const CActorParameters& aParams, float linConeAngle, float linMinMag, - float linMaxMag, float angMinMag, float angMaxMag, float minDuration, float maxDuration, - float colorInT, float colorOutT, const zeus::CColor& color, const zeus::CColor& endsColor, - float scaleOutStartT, const zeus::CVector3f& scale, const zeus::CVector3f& endScale, - float restitution, float downwardSpeed, const zeus::CVector3f& localOffset, - CAssetId particle1, const zeus::CVector3f& particle1Scale, bool particle1GlobalTranslation, - bool deferDeleteTillParticle1Done, EOrientationType particle1Or, - CAssetId particle2, const zeus::CVector3f& particle2Scale, bool particle2GlobalTranslation, - bool deferDeleteTillParticle2Done, EOrientationType particle2Or, - CAssetId particle3, const zeus::CVector3f& particle3Scale, EOrientationType particle3Or, - bool solid, bool dieOnProjectile, bool noBounce, bool active); + CScriptDebris(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CActorParameters& aParams, float linConeAngle, float linMinMag, + float linMaxMag, float angMinMag, float angMaxMag, float minDuration, float maxDuration, float colorInT, + float colorOutT, const zeus::CColor& color, const zeus::CColor& endsColor, float scaleOutStartT, + const zeus::CVector3f& scale, const zeus::CVector3f& endScale, float restitution, float downwardSpeed, + const zeus::CVector3f& localOffset, CAssetId particle1, const zeus::CVector3f& particle1Scale, + bool particle1GlobalTranslation, bool deferDeleteTillParticle1Done, EOrientationType particle1Or, + CAssetId particle2, const zeus::CVector3f& particle2Scale, bool particle2GlobalTranslation, + bool deferDeleteTillParticle2Done, EOrientationType particle2Or, CAssetId particle3, + const zeus::CVector3f& particle3Scale, EOrientationType particle3Or, bool solid, bool dieOnProjectile, + bool noBounce, bool active); - void Accept(IVisitor& visitor); - void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - void Think(float dt, CStateManager& mgr); - void Touch(CActor& other, CStateManager& mgr); - std::experimental::optional GetTouchBounds() const; - void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); - void Render(const CStateManager& mgr) const; + void Accept(IVisitor& visitor); + void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const; + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + void Think(float dt, CStateManager& mgr); + void Touch(CActor& other, CStateManager& mgr); + std::experimental::optional GetTouchBounds() const; + void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum); + void Render(const CStateManager& mgr) const; - void CollidedWith(TUniqueId uid, const CCollisionInfoList&, CStateManager&); + void CollidedWith(TUniqueId uid, const CCollisionInfoList&, CStateManager&); }; } // namespace urde - diff --git a/Runtime/World/CScriptDebugCameraWaypoint.cpp b/Runtime/World/CScriptDebugCameraWaypoint.cpp index adf29cd5e..51d4ff9be 100644 --- a/Runtime/World/CScriptDebugCameraWaypoint.cpp +++ b/Runtime/World/CScriptDebugCameraWaypoint.cpp @@ -2,19 +2,14 @@ #include "CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptDebugCameraWaypoint::CScriptDebugCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, u32 w1) : CActor(uid, true, name, info, xf, CModelData::CModelDataNull(), {EMaterialTypes::NoStepLogic}, - CActorParameters::None(), kInvalidUniqueId), xe8_w1(w1) -{ -} + CActorParameters::None(), kInvalidUniqueId) +, xe8_w1(w1) {} -void CScriptDebugCameraWaypoint::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptDebugCameraWaypoint::Accept(IVisitor& visitor) { visitor.Visit(this); } -} +} // namespace urde diff --git a/Runtime/World/CScriptDebugCameraWaypoint.hpp b/Runtime/World/CScriptDebugCameraWaypoint.hpp index 8fb97e6ba..09b58c001 100644 --- a/Runtime/World/CScriptDebugCameraWaypoint.hpp +++ b/Runtime/World/CScriptDebugCameraWaypoint.hpp @@ -2,18 +2,16 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { + +class CScriptDebugCameraWaypoint : public CActor { + u32 xe8_w1; -class CScriptDebugCameraWaypoint : public CActor -{ - u32 xe8_w1; public: - CScriptDebugCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, u32 w1); + CScriptDebugCameraWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + u32 w1); - void Accept(IVisitor&); + void Accept(IVisitor&); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptDistanceFog.cpp b/Runtime/World/CScriptDistanceFog.cpp index baf194350..cda871b23 100644 --- a/Runtime/World/CScriptDistanceFog.cpp +++ b/Runtime/World/CScriptDistanceFog.cpp @@ -3,77 +3,65 @@ #include "CWorld.hpp" #include "TCastTo.hpp" -namespace urde -{ -CScriptDistanceFog::CScriptDistanceFog(TUniqueId uid, std::string_view name, const CEntityInfo& info, - ERglFogMode mode, const zeus::CColor& color, - const zeus::CVector2f& range, float colorDelta, - const zeus::CVector2f& rangeDelta, bool expl, bool active, - float thermalTarget, float thermalSpeed, float xrayTarget, float xraySpeed) - : CEntity(uid, info, active, name), - x34_mode(mode), - x38_color(color), - x3c_range(range), - x44_colorDelta(colorDelta), - x48_rangeDelta(rangeDelta), - x50_thermalTarget(thermalTarget), - x54_thermalSpeed(thermalSpeed), - x58_xrayTarget(xrayTarget), - x5c_xraySpeed(xraySpeed), - x60_explicit(expl) +namespace urde { +CScriptDistanceFog::CScriptDistanceFog(TUniqueId uid, std::string_view name, const CEntityInfo& info, ERglFogMode mode, + const zeus::CColor& color, const zeus::CVector2f& range, float colorDelta, + const zeus::CVector2f& rangeDelta, bool expl, bool active, float thermalTarget, + float thermalSpeed, float xrayTarget, float xraySpeed) +: CEntity(uid, info, active, name) +, x34_mode(mode) +, x38_color(color) +, x3c_range(range) +, x44_colorDelta(colorDelta) +, x48_rangeDelta(rangeDelta) +, x50_thermalTarget(thermalTarget) +, x54_thermalSpeed(thermalSpeed) +, x58_xrayTarget(xrayTarget) +, x5c_xraySpeed(xraySpeed) +, x60_explicit(expl) { - if (zeus::close_enough(rangeDelta, zeus::CVector2f::skZero) && zeus::close_enough(colorDelta, 0.f)) - x61_nonZero = false; + if (zeus::close_enough(rangeDelta, zeus::CVector2f::skZero) && zeus::close_enough(colorDelta, 0.f)) + x61_nonZero = false; + else + x61_nonZero = true; +} + +void CScriptDistanceFog::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptDistanceFog::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); + + if (x4_areaId == kInvalidAreaId || !GetActive()) + return; + + if (msg == EScriptObjectMessage::InitializedInArea) { + if (!x60_explicit) + return; + CGameArea::CAreaFog* fog = stateMgr.WorldNC()->GetArea(x4_areaId)->AreaFog(); + if (x34_mode == ERglFogMode::None) + fog->DisableFog(); else - x61_nonZero = true; -} + fog->SetFogExplicit(x34_mode, x38_color, x3c_range); + } else if (msg == EScriptObjectMessage::Action) { + if (!x61_nonZero) + return; -void CScriptDistanceFog::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} + CGameArea::CAreaFog* fog = stateMgr.WorldNC()->GetArea(x4_areaId)->AreaFog(); + if (x34_mode == ERglFogMode::None) + fog->RollFogOut(x48_rangeDelta.x(), x44_colorDelta, x38_color); + else + fog->FadeFog(x34_mode, x38_color, x3c_range, x44_colorDelta, x48_rangeDelta); -void CScriptDistanceFog::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CEntity::AcceptScriptMsg(msg, objId, stateMgr); - - if (x4_areaId == kInvalidAreaId || !GetActive()) - return; - - if (msg == EScriptObjectMessage::InitializedInArea) - { - if (!x60_explicit) - return; - CGameArea::CAreaFog* fog = stateMgr.WorldNC()->GetArea(x4_areaId)->AreaFog(); - if (x34_mode == ERglFogMode::None) - fog->DisableFog(); - else - fog->SetFogExplicit(x34_mode, x38_color, x3c_range); - } - else if (msg == EScriptObjectMessage::Action) - { - if (!x61_nonZero) - return; - - CGameArea::CAreaFog* fog = stateMgr.WorldNC()->GetArea(x4_areaId)->AreaFog(); - if (x34_mode == ERglFogMode::None) - fog->RollFogOut(x48_rangeDelta.x(), x44_colorDelta, x38_color); - else - fog->FadeFog(x34_mode, x38_color, x3c_range, x44_colorDelta, x48_rangeDelta); - - if (zeus::close_enough(x54_thermalSpeed, 0.f) && !zeus::close_enough(x5c_xraySpeed, 0.f)) - { - CWorld* world = stateMgr.WorldNC(); - CGameArea* area = world->GetArea(x4_areaId); - area->SetXRaySpeedAndTarget(x5c_xraySpeed, x58_xrayTarget); - } - else - { - CWorld* world = stateMgr.WorldNC(); - CGameArea* area = world->GetArea(x4_areaId); - area->SetThermalSpeedAndTarget(x54_thermalSpeed, x50_thermalTarget); - } + if (zeus::close_enough(x54_thermalSpeed, 0.f) && !zeus::close_enough(x5c_xraySpeed, 0.f)) { + CWorld* world = stateMgr.WorldNC(); + CGameArea* area = world->GetArea(x4_areaId); + area->SetXRaySpeedAndTarget(x5c_xraySpeed, x58_xrayTarget); + } else { + CWorld* world = stateMgr.WorldNC(); + CGameArea* area = world->GetArea(x4_areaId); + area->SetThermalSpeedAndTarget(x54_thermalSpeed, x50_thermalTarget); } + } } -} +} // namespace urde diff --git a/Runtime/World/CScriptDistanceFog.hpp b/Runtime/World/CScriptDistanceFog.hpp index 96f24f91a..6bba135ea 100644 --- a/Runtime/World/CScriptDistanceFog.hpp +++ b/Runtime/World/CScriptDistanceFog.hpp @@ -3,28 +3,25 @@ #include "Graphics/CGraphics.hpp" #include "CEntity.hpp" -namespace urde -{ -class CScriptDistanceFog : public CEntity -{ - ERglFogMode x34_mode; - zeus::CColor x38_color; - zeus::CVector2f x3c_range; - float x44_colorDelta; - zeus::CVector2f x48_rangeDelta; - float x50_thermalTarget; - float x54_thermalSpeed; - float x58_xrayTarget; - float x5c_xraySpeed; - bool x60_explicit; - bool x61_nonZero; +namespace urde { +class CScriptDistanceFog : public CEntity { + ERglFogMode x34_mode; + zeus::CColor x38_color; + zeus::CVector2f x3c_range; + float x44_colorDelta; + zeus::CVector2f x48_rangeDelta; + float x50_thermalTarget; + float x54_thermalSpeed; + float x58_xrayTarget; + float x5c_xraySpeed; + bool x60_explicit; + bool x61_nonZero; + public: - CScriptDistanceFog(TUniqueId, std::string_view, const CEntityInfo&, ERglFogMode, - const zeus::CColor&, const zeus::CVector2f&, float, const zeus::CVector2f&, - bool, bool, float, float, float, float); + CScriptDistanceFog(TUniqueId, std::string_view, const CEntityInfo&, ERglFogMode, const zeus::CColor&, + const zeus::CVector2f&, float, const zeus::CVector2f&, bool, bool, float, float, float, float); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptDock.cpp b/Runtime/World/CScriptDock.cpp index 1ee360c94..cd5f1cd16 100644 --- a/Runtime/World/CScriptDock.cpp +++ b/Runtime/World/CScriptDock.cpp @@ -9,15 +9,13 @@ #include "Particle/CGenDescription.hpp" #include "TCastTo.hpp" -namespace urde -{ -CMaterialList MakeDockMaterialList() -{ - CMaterialList list; - list.Add(EMaterialTypes::Trigger); - list.Add(EMaterialTypes::Immovable); - list.Add(EMaterialTypes::AIBlock); - return list; +namespace urde { +CMaterialList MakeDockMaterialList() { + CMaterialList list; + list.Add(EMaterialTypes::Trigger); + list.Add(EMaterialTypes::Immovable); + list.Add(EMaterialTypes::AIBlock); + return list; } CScriptDock::CScriptDock(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f position, @@ -28,233 +26,201 @@ CScriptDock::CScriptDock(TUniqueId uid, std::string_view name, const CEntityInfo SMoverData(1.f), CActorParameters::None(), 0.3f, 0.1f) , x258_dockReferenceCount(dockReferenceCount) , x25c_dock(dock) -, x260_area(area) -{ - x268_25_loadConnected = loadConnected; +, x260_area(area) { + x268_25_loadConnected = loadConnected; } void CScriptDock::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptDock::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - { - UpdateAreaActivateFlags(mgr); - x268_24_dockReferenced = false; - } +void CScriptDock::Think(float dt, CStateManager& mgr) { + if (!GetActive()) { + UpdateAreaActivateFlags(mgr); + x268_24_dockReferenced = false; + } - const IGameArea::Dock* gameDock = mgr.WorldNC()->GetArea(x260_area)->GetDock(x25c_dock); - TAreaId connArea = gameDock->GetConnectedAreaId(gameDock->GetReferenceCount()); - if (connArea != kInvalidAreaId) - { - bool connPostConstructed = mgr.WorldNC()->GetArea(connArea)->IsPostConstructed(); - if (x268_26_areaPostConstructed != connPostConstructed) - { - x268_26_areaPostConstructed = connPostConstructed; - if (connPostConstructed) - CEntity::SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); - else - CEntity::SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + const IGameArea::Dock* gameDock = mgr.WorldNC()->GetArea(x260_area)->GetDock(x25c_dock); + TAreaId connArea = gameDock->GetConnectedAreaId(gameDock->GetReferenceCount()); + if (connArea != kInvalidAreaId) { + bool connPostConstructed = mgr.WorldNC()->GetArea(connArea)->IsPostConstructed(); + if (x268_26_areaPostConstructed != connPostConstructed) { + x268_26_areaPostConstructed = connPostConstructed; + if (connPostConstructed) + CEntity::SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); + else + CEntity::SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + } + } + + if (mgr.GetNextAreaId() != x260_area) + x264_dockState = EDockState::Three; + else if (x264_dockState == EDockState::Three) + x264_dockState = EDockState::Idle; + else if (x264_dockState == EDockState::PlayerTouched) + x264_dockState = EDockState::EnterNextArea; + else if (x264_dockState == EDockState::EnterNextArea) { + CPlayer& player = mgr.GetPlayer(); + if (HasPointCrossedDock(mgr, player.GetTranslation())) { + IGameArea::Dock* dock = mgr.WorldNC()->GetArea(mgr.GetNextAreaId())->DockNC(x25c_dock); + TAreaId aid = dock->GetConnectedAreaId(dock->GetReferenceCount()); + if (aid != kInvalidAreaId && mgr.WorldNC()->GetArea(aid)->GetActive()) { + mgr.SetCurrentAreaId(aid); + s32 otherDock = dock->GetOtherDockNumber(dock->GetReferenceCount()); + + if (CObjectList* objs = mgr.WorldNC()->GetArea(aid)->GetAreaObjects()) { + for (CEntity* ent : *objs) { + TCastToPtr dock(ent); + if (dock && dock->GetDockId() == otherDock) + dock->SetLoadConnected(mgr, true); + } } + } } + x264_dockState = EDockState::Idle; + } +} + +void CScriptDock::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Registered: { + CGameArea* area = mgr.WorldNC()->GetArea(x260_area); + if (area->GetDockCount() < x25c_dock) + return; + IGameArea::Dock* dock = area->DockNC(x25c_dock); + if (!dock->IsReferenced()) + dock->SetReferenceCount(x258_dockReferenceCount); + } break; + case EScriptObjectMessage::Deleted: + CleanUp(); + break; + case EScriptObjectMessage::InitializedInArea: + AreaLoaded(mgr); + break; + case EScriptObjectMessage::WorldInitialized: { + UpdateAreaActivateFlags(mgr); + CMaterialList exclude = GetMaterialFilter().GetExcludeList(); + CMaterialList include = GetMaterialFilter().GetIncludeList(); + include.Add(EMaterialTypes::AIBlock); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); + } break; + case EScriptObjectMessage::SetToZero: { if (mgr.GetNextAreaId() != x260_area) - x264_dockState = EDockState::Three; - else if (x264_dockState == EDockState::Three) - x264_dockState = EDockState::Idle; - else if (x264_dockState == EDockState::PlayerTouched) - x264_dockState = EDockState::EnterNextArea; - else if (x264_dockState == EDockState::EnterNextArea) - { - CPlayer& player = mgr.GetPlayer(); - if (HasPointCrossedDock(mgr, player.GetTranslation())) - { - IGameArea::Dock* dock = mgr.WorldNC()->GetArea(mgr.GetNextAreaId())->DockNC(x25c_dock); - TAreaId aid = dock->GetConnectedAreaId(dock->GetReferenceCount()); - if (aid != kInvalidAreaId && mgr.WorldNC()->GetArea(aid)->GetActive()) - { - mgr.SetCurrentAreaId(aid); - s32 otherDock = dock->GetOtherDockNumber(dock->GetReferenceCount()); + return; - if (CObjectList* objs = mgr.WorldNC()->GetArea(aid)->GetAreaObjects()) - { - for (CEntity* ent : *objs) - { - TCastToPtr dock(ent); - if (dock && dock->GetDockId() == otherDock) - dock->SetLoadConnected(mgr, true); - } - } - } - } - - x264_dockState = EDockState::Idle; - } -} - -void CScriptDock::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Registered: - { - CGameArea* area = mgr.WorldNC()->GetArea(x260_area); - if (area->GetDockCount() < x25c_dock) - return; - IGameArea::Dock* dock = area->DockNC(x25c_dock); - if (!dock->IsReferenced()) - dock->SetReferenceCount(x258_dockReferenceCount); - } - break; - case EScriptObjectMessage::Deleted: - CleanUp(); - break; - case EScriptObjectMessage::InitializedInArea: - AreaLoaded(mgr); - break; - case EScriptObjectMessage::WorldInitialized: - { - UpdateAreaActivateFlags(mgr); - CMaterialList exclude = GetMaterialFilter().GetExcludeList(); - CMaterialList include = GetMaterialFilter().GetIncludeList(); - include.Add(EMaterialTypes::AIBlock); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); - } - break; - case EScriptObjectMessage::SetToZero: - { - if (mgr.GetNextAreaId() != x260_area) - return; - - SetLoadConnected(mgr, false); - - CGameArea* area = mgr.WorldNC()->GetArea(x260_area); - IGameArea::Dock* dock = area->DockNC(x25c_dock); - - TAreaId aid = dock->GetConnectedAreaId(dock->GetReferenceCount()); - - CPlatformAndDoorList& lst = mgr.GetPlatformAndDoorObjectList(); - for (CEntity* ent : lst) - { - TCastToPtr door(ent); - if (door && door->IsConnectedToArea(mgr, aid)) - door->ForceClosed(mgr); - } - } - break; - case EScriptObjectMessage::SetToMax: - if (mgr.GetNextAreaId() != x260_area) - return; - - SetLoadConnected(mgr, true); - break; - case EScriptObjectMessage::Increment: - SetLoadConnected(mgr, true); - [[fallthrough]]; - case EScriptObjectMessage::Decrement: - { - TAreaId aid = x260_area; - if (mgr.GetNextAreaId() == x260_area) - { - IGameArea::Dock* dock = mgr.WorldNC()->GetArea(x260_area)->DockNC(x25c_dock); - aid = dock->GetConnectedAreaId(dock->GetReferenceCount()); - } - - if (aid >= 0 && aid < mgr.GetWorld()->GetNumAreas() && mgr.WorldNC()->GetArea(aid)->GetActive()) - CWorld::PropogateAreaChain(CGameArea::EOcclusionState(msg == EScriptObjectMessage::Increment), - mgr.WorldNC()->GetArea(aid), mgr.WorldNC()); - } - break; - default: - CPhysicsActor::AcceptScriptMsg(msg, uid, mgr); - break; - } -} - -std::experimental::optional CScriptDock::GetTouchBounds() const -{ - if (x264_dockState == EDockState::Three) - return {}; - - return GetBoundingBox(); -} - -void CScriptDock::Touch(CActor& act, CStateManager&) -{ - if (x264_dockState == EDockState::Three) - return; - - if (TCastToPtr(act)) - x264_dockState = EDockState::PlayerTouched; -} - -zeus::CPlane CScriptDock::GetPlane(const CStateManager& mgr) const -{ - const IGameArea::Dock* dock = mgr.GetWorld()->GetAreaAlways(x260_area)->GetDock(x25c_dock); - return zeus::CPlane(dock->GetPoint(0), dock->GetPoint(1), dock->GetPoint(2)); -} - -void CScriptDock::SetDockReference(CStateManager& mgr, s32 ref) -{ - mgr.WorldNC()->GetArea(x260_area)->DockNC(x25c_dock)->SetReferenceCount(ref); - x268_24_dockReferenced = true; -} - -s32 CScriptDock::GetDockReference(const CStateManager& mgr) const -{ - return mgr.GetWorld()->GetAreaAlways(x260_area)->GetDock(x25c_dock)->GetReferenceCount(); -} - -TAreaId CScriptDock::GetCurrentConnectedAreaId(const CStateManager& mgr) const -{ - if (x260_area >= mgr.GetWorld()->GetNumAreas()) - return kInvalidAreaId; - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x260_area); - if (x25c_dock >= area->GetDockCount()) - return kInvalidAreaId; - - const IGameArea::Dock* dock = area->GetDock(x25c_dock); - return dock->GetConnectedAreaId(dock->GetReferenceCount()); -} - -void CScriptDock::UpdateAreaActivateFlags(CStateManager& mgr) -{ - CWorld* world = mgr.WorldNC(); - if (x260_area >= world->GetNumAreas()) - return; - - CGameArea* area = world->GetArea(x260_area); - - if (x25c_dock >= area->GetDockCount()) - return; + SetLoadConnected(mgr, false); + CGameArea* area = mgr.WorldNC()->GetArea(x260_area); IGameArea::Dock* dock = area->DockNC(x25c_dock); - for (s32 i = 0; i < dock->GetDockRefs().size(); ++i) - { - s32 dockRefCount = dock->GetReferenceCount(); - TAreaId aid = dock->GetConnectedAreaId(i); - if (aid != kInvalidAreaId) - world->GetArea(aid)->SetActive(i == dockRefCount); + TAreaId aid = dock->GetConnectedAreaId(dock->GetReferenceCount()); + + CPlatformAndDoorList& lst = mgr.GetPlatformAndDoorObjectList(); + for (CEntity* ent : lst) { + TCastToPtr door(ent); + if (door && door->IsConnectedToArea(mgr, aid)) + door->ForceClosed(mgr); } - mgr.SetCurrentAreaId(mgr.GetNextAreaId()); + } break; + case EScriptObjectMessage::SetToMax: + if (mgr.GetNextAreaId() != x260_area) + return; + + SetLoadConnected(mgr, true); + break; + case EScriptObjectMessage::Increment: + SetLoadConnected(mgr, true); + [[fallthrough]]; + case EScriptObjectMessage::Decrement: { + TAreaId aid = x260_area; + if (mgr.GetNextAreaId() == x260_area) { + IGameArea::Dock* dock = mgr.WorldNC()->GetArea(x260_area)->DockNC(x25c_dock); + aid = dock->GetConnectedAreaId(dock->GetReferenceCount()); + } + + if (aid >= 0 && aid < mgr.GetWorld()->GetNumAreas() && mgr.WorldNC()->GetArea(aid)->GetActive()) + CWorld::PropogateAreaChain(CGameArea::EOcclusionState(msg == EScriptObjectMessage::Increment), + mgr.WorldNC()->GetArea(aid), mgr.WorldNC()); + } break; + default: + CPhysicsActor::AcceptScriptMsg(msg, uid, mgr); + break; + } } -bool CScriptDock::HasPointCrossedDock(const CStateManager& mgr, const zeus::CVector3f& point) const -{ - const zeus::CPlane plane = GetPlane(mgr); - return plane.pointToPlaneDist(point) >= 0.f; +std::experimental::optional CScriptDock::GetTouchBounds() const { + if (x264_dockState == EDockState::Three) + return {}; + + return GetBoundingBox(); +} + +void CScriptDock::Touch(CActor& act, CStateManager&) { + if (x264_dockState == EDockState::Three) + return; + + if (TCastToPtr(act)) + x264_dockState = EDockState::PlayerTouched; +} + +zeus::CPlane CScriptDock::GetPlane(const CStateManager& mgr) const { + const IGameArea::Dock* dock = mgr.GetWorld()->GetAreaAlways(x260_area)->GetDock(x25c_dock); + return zeus::CPlane(dock->GetPoint(0), dock->GetPoint(1), dock->GetPoint(2)); +} + +void CScriptDock::SetDockReference(CStateManager& mgr, s32 ref) { + mgr.WorldNC()->GetArea(x260_area)->DockNC(x25c_dock)->SetReferenceCount(ref); + x268_24_dockReferenced = true; +} + +s32 CScriptDock::GetDockReference(const CStateManager& mgr) const { + return mgr.GetWorld()->GetAreaAlways(x260_area)->GetDock(x25c_dock)->GetReferenceCount(); +} + +TAreaId CScriptDock::GetCurrentConnectedAreaId(const CStateManager& mgr) const { + if (x260_area >= mgr.GetWorld()->GetNumAreas()) + return kInvalidAreaId; + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x260_area); + if (x25c_dock >= area->GetDockCount()) + return kInvalidAreaId; + + const IGameArea::Dock* dock = area->GetDock(x25c_dock); + return dock->GetConnectedAreaId(dock->GetReferenceCount()); +} + +void CScriptDock::UpdateAreaActivateFlags(CStateManager& mgr) { + CWorld* world = mgr.WorldNC(); + if (x260_area >= world->GetNumAreas()) + return; + + CGameArea* area = world->GetArea(x260_area); + + if (x25c_dock >= area->GetDockCount()) + return; + + IGameArea::Dock* dock = area->DockNC(x25c_dock); + + for (s32 i = 0; i < dock->GetDockRefs().size(); ++i) { + s32 dockRefCount = dock->GetReferenceCount(); + TAreaId aid = dock->GetConnectedAreaId(i); + if (aid != kInvalidAreaId) + world->GetArea(aid)->SetActive(i == dockRefCount); + } + mgr.SetCurrentAreaId(mgr.GetNextAreaId()); +} + +bool CScriptDock::HasPointCrossedDock(const CStateManager& mgr, const zeus::CVector3f& point) const { + const zeus::CPlane plane = GetPlane(mgr); + return plane.pointToPlaneDist(point) >= 0.f; } void CScriptDock::AreaLoaded(CStateManager& mgr) { SetLoadConnected(mgr, x268_25_loadConnected); } -void CScriptDock::SetLoadConnected(CStateManager& mgr, bool loadOther) -{ - IGameArea::Dock* dock = mgr.WorldNC()->GetArea(x260_area)->DockNC(x25c_dock); - bool cur = dock->GetShouldLoadOther(dock->GetReferenceCount()); - if (cur == loadOther) - return; +void CScriptDock::SetLoadConnected(CStateManager& mgr, bool loadOther) { + IGameArea::Dock* dock = mgr.WorldNC()->GetArea(x260_area)->DockNC(x25c_dock); + bool cur = dock->GetShouldLoadOther(dock->GetReferenceCount()); + if (cur == loadOther) + return; - dock->SetShouldLoadOther(dock->GetReferenceCount(), loadOther); + dock->SetShouldLoadOther(dock->GetReferenceCount(), loadOther); } } // namespace urde diff --git a/Runtime/World/CScriptDock.hpp b/Runtime/World/CScriptDock.hpp index 9232f092d..c0a254a48 100644 --- a/Runtime/World/CScriptDock.hpp +++ b/Runtime/World/CScriptDock.hpp @@ -2,55 +2,46 @@ #include "CPhysicsActor.hpp" -namespace urde -{ +namespace urde { -class CScriptDock : public CPhysicsActor -{ - enum EDockState - { - Idle, - PlayerTouched, - EnterNextArea, - Three - }; +class CScriptDock : public CPhysicsActor { + enum EDockState { Idle, PlayerTouched, EnterNextArea, Three }; - friend class CScriptDoor; - s32 x258_dockReferenceCount; - s32 x25c_dock; - TAreaId x260_area; - EDockState x264_dockState = EDockState::Three; - union { - struct - { - bool x268_24_dockReferenced : 1; - bool x268_25_loadConnected : 1; - bool x268_26_areaPostConstructed : 1; - }; - u8 dummy = 0; + friend class CScriptDoor; + s32 x258_dockReferenceCount; + s32 x25c_dock; + TAreaId x260_area; + EDockState x264_dockState = EDockState::Three; + union { + struct { + bool x268_24_dockReferenced : 1; + bool x268_25_loadConnected : 1; + bool x268_26_areaPostConstructed : 1; }; + u8 dummy = 0; + }; public: - CScriptDock(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f position, - const zeus::CVector3f& extent, s32 dock, TAreaId area, bool active, - s32 dockReferenceCount, bool loadConnected); + CScriptDock(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f position, + const zeus::CVector3f& extent, s32 dock, TAreaId area, bool active, s32 dockReferenceCount, + bool loadConnected); - void Accept(IVisitor& visitor); - void Think(float, CStateManager&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - std::experimental::optional GetTouchBounds() const; - void Touch(CActor&, CStateManager&); - void CleanUp() {} - zeus::CPlane GetPlane(const CStateManager&) const; - TAreaId GetAreaId() const { return x260_area; } - s32 GetDockId() const { return x25c_dock; } - void SetDockReference(CStateManager& mgr, s32); - s32 GetDockReference(const CStateManager& mgr) const; - TAreaId GetCurrentConnectedAreaId(const CStateManager&) const; - void UpdateAreaActivateFlags(CStateManager&); - bool HasPointCrossedDock(const CStateManager&, const zeus::CVector3f&) const; - void AreaLoaded(CStateManager&); - void AreaUnloaded(CStateManager&); - void SetLoadConnected(CStateManager&, bool); + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + std::experimental::optional GetTouchBounds() const; + void Touch(CActor&, CStateManager&); + void CleanUp() {} + zeus::CPlane GetPlane(const CStateManager&) const; + TAreaId GetAreaId() const { return x260_area; } + s32 GetDockId() const { return x25c_dock; } + void SetDockReference(CStateManager& mgr, s32); + s32 GetDockReference(const CStateManager& mgr) const; + TAreaId GetCurrentConnectedAreaId(const CStateManager&) const; + void UpdateAreaActivateFlags(CStateManager&); + bool HasPointCrossedDock(const CStateManager&, const zeus::CVector3f&) const; + void AreaLoaded(CStateManager&); + void AreaUnloaded(CStateManager&); + void SetLoadConnected(CStateManager&, bool); }; -} +} // namespace urde diff --git a/Runtime/World/CScriptDockAreaChange.cpp b/Runtime/World/CScriptDockAreaChange.cpp index 861686356..361dccd2a 100644 --- a/Runtime/World/CScriptDockAreaChange.cpp +++ b/Runtime/World/CScriptDockAreaChange.cpp @@ -3,41 +3,31 @@ #include "World/CScriptDock.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptDockAreaChange::CScriptDockAreaChange(TUniqueId uid, std::string_view name, const CEntityInfo& info, s32 w1, bool active) -: CEntity(uid, info, active, name), x34_dockReference(w1) -{ -} +: CEntity(uid, info, active, name), x34_dockReference(w1) {} -void CScriptDockAreaChange::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptDockAreaChange::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptDockAreaChange::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - if (msg == EScriptObjectMessage::Action && GetActive()) - { - for (SConnection conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play) - continue; +void CScriptDockAreaChange::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + if (msg == EScriptObjectMessage::Action && GetActive()) { + for (SConnection conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play) + continue; - auto search = stateMgr.GetIdListForScript(conn.x8_objId); - for (auto it = search.first ; it != search.second ; ++it) - { - TUniqueId id = it->second; - TCastToPtr dock(stateMgr.ObjectById(id)); - if (dock) - dock->SetDockReference(stateMgr, x34_dockReference); - } - } - - SendScriptMsgs(EScriptObjectState::Play, stateMgr, EScriptObjectMessage::None); + auto search = stateMgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) { + TUniqueId id = it->second; + TCastToPtr dock(stateMgr.ObjectById(id)); + if (dock) + dock->SetDockReference(stateMgr, x34_dockReference); + } } - CEntity::AcceptScriptMsg(msg, objId, stateMgr); -} + SendScriptMsgs(EScriptObjectState::Play, stateMgr, EScriptObjectMessage::None); + } + + CEntity::AcceptScriptMsg(msg, objId, stateMgr); } +} // namespace urde diff --git a/Runtime/World/CScriptDockAreaChange.hpp b/Runtime/World/CScriptDockAreaChange.hpp index 873bbb399..4660b21bd 100644 --- a/Runtime/World/CScriptDockAreaChange.hpp +++ b/Runtime/World/CScriptDockAreaChange.hpp @@ -2,16 +2,14 @@ #include "CEntity.hpp" -namespace urde -{ -class CScriptDockAreaChange : public CEntity -{ - s32 x34_dockReference; +namespace urde { +class CScriptDockAreaChange : public CEntity { + s32 x34_dockReference; + public: - CScriptDockAreaChange(TUniqueId, std::string_view, const CEntityInfo&, s32, bool); + CScriptDockAreaChange(TUniqueId, std::string_view, const CEntityInfo&, s32, bool); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptDoor.cpp b/Runtime/World/CScriptDoor.cpp index 511d61ca9..434bc8dbe 100644 --- a/Runtime/World/CScriptDoor.cpp +++ b/Runtime/World/CScriptDoor.cpp @@ -10,414 +10,361 @@ #include "Camera/CBallCamera.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -static CMaterialList MakeDoorMaterialList(bool open) -{ - CMaterialList ret; - ret.Add(EMaterialTypes::Solid); - ret.Add(EMaterialTypes::Immovable); - ret.Add(EMaterialTypes::Orbit); - if (!open) - ret.Add(EMaterialTypes::Occluder); +static CMaterialList MakeDoorMaterialList(bool open) { + CMaterialList ret; + ret.Add(EMaterialTypes::Solid); + ret.Add(EMaterialTypes::Immovable); + ret.Add(EMaterialTypes::Orbit); + if (!open) + ret.Add(EMaterialTypes::Occluder); - return ret; + return ret; } -CScriptDoor::CScriptDoor(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, - const zeus::CVector3f& orbitPos, const zeus::CAABox& aabb, bool active, - bool open, bool projectilesCollide, float animLen, bool ballDoor) -: CPhysicsActor(uid, active, name, info, xf, std::move(mData), MakeDoorMaterialList(open), - aabb, SMoverData(1.f), actParms, 0.3f, 0.1f) -{ - x258_animLen = animLen; - x2a8_24_closing = false; - x2a8_25_wasOpen = open; - x2a8_26_isOpen = open; - x2a8_27_conditionsMet = false; - x2a8_28_projectilesCollide = projectilesCollide; - x2a8_29_ballDoor = ballDoor; - x2a8_30_doClose = false; - x264_ = GetBoundingBox(); - x284_modelBounds = x64_modelData->GetBounds(xf.getRotation()); - x29c_orbitPos = orbitPos; +CScriptDoor::CScriptDoor(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CActorParameters& actParms, const zeus::CVector3f& orbitPos, + const zeus::CAABox& aabb, bool active, bool open, bool projectilesCollide, float animLen, + bool ballDoor) +: CPhysicsActor(uid, active, name, info, xf, std::move(mData), MakeDoorMaterialList(open), aabb, SMoverData(1.f), + actParms, 0.3f, 0.1f) { + x258_animLen = animLen; + x2a8_24_closing = false; + x2a8_25_wasOpen = open; + x2a8_26_isOpen = open; + x2a8_27_conditionsMet = false; + x2a8_28_projectilesCollide = projectilesCollide; + x2a8_29_ballDoor = ballDoor; + x2a8_30_doClose = false; + x264_ = GetBoundingBox(); + x284_modelBounds = x64_modelData->GetBounds(xf.getRotation()); + x29c_orbitPos = orbitPos; - xe6_27_thermalVisorFlags = 1; - if (open) - SetDoorAnimation(EDoorAnimType::Open); + xe6_27_thermalVisorFlags = 1; + if (open) + SetDoorAnimation(EDoorAnimType::Open); - SetMass(0.f); + SetMass(0.f); } -void CScriptDoor::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptDoor::Accept(IVisitor& visitor) { visitor.Visit(this); } /* ORIGINAL 0-00 OFFSET: 8007F054 */ -zeus::CVector3f CScriptDoor::GetOrbitPosition(const CStateManager& /*mgr*/) const -{ - return x34_transform.origin + x29c_orbitPos; +zeus::CVector3f CScriptDoor::GetOrbitPosition(const CStateManager& /*mgr*/) const { + return x34_transform.origin + x29c_orbitPos; } /* ORIGINAL 0-00 OFFSET: 8007E550 */ -void CScriptDoor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager &mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Close: - { - if (!GetActive()) - return; - - if (x27c_partner1 != kInvalidUniqueId && x27c_partner1 != uid) - return; - - if (x2a8_26_isOpen) - { - if (x27e_partner2 != kInvalidUniqueId) - if (CEntity* ent = mgr.ObjectById(x27e_partner2)) - mgr.SendScriptMsg(ent, GetUniqueId(), EScriptObjectMessage::Close); - x2a8_26_isOpen = false; - SetDoorAnimation(EDoorAnimType::Close); - mgr.GetCameraManager()->GetBallCamera()->DoorClosing(GetUniqueId()); - } - else if (x2a8_27_conditionsMet) - { - x2a8_27_conditionsMet = false; - SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); - } - break; - } - case EScriptObjectMessage::Action: - { - if (x27c_partner1 != kInvalidUniqueId) - { - if (TCastToPtr door = mgr.ObjectById(x27c_partner1)) - { - if (!x2a8_26_isOpen) - return; - x2a8_30_doClose = true; - mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close); - } - } - else if (x2a8_26_isOpen) - { - x2a8_30_doClose = true; - if (TCastToPtr door = mgr.ObjectById(x27e_partner2)) - { - mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close); - x2a8_30_doClose = true; - } - x2a8_26_isOpen = false; - SetDoorAnimation(EDoorAnimType::Close); - mgr.GetCameraManager()->GetBallCamera()->DoorClosing(GetUniqueId()); - } - break; - } - case EScriptObjectMessage::Open: - { - if (!GetActive() || x2a8_26_isOpen) - return; - - u32 doorCond = TCastToConstPtr(mgr.GetObjectById(uid)) ? 2 : GetDoorOpenCondition(mgr); - switch (doorCond) - { - case 1: - x2a8_27_conditionsMet = true; - x280_prevDoor = uid; - break; - case 2: - OpenDoor(uid, mgr); - break; - default: - x2a8_25_wasOpen = false; - x2a8_24_closing = true; - break; - } - break; - } - case EScriptObjectMessage::InitializedInArea: - { - for (const SConnection& conn : x20_conns) - { - if (conn.x4_msg == EScriptObjectMessage::Increment) - { - TUniqueId dock = mgr.GetIdForScript(conn.x8_objId); - if (TCastToConstPtr d = mgr.GetObjectById(dock)) - { - x282_dockId = d->GetUniqueId(); - break; - } - } - } - break; - } - case EScriptObjectMessage::SetToZero: - { - x2a8_28_projectilesCollide = true; - mgr.MapWorldInfo()->SetDoorVisited(mgr.GetEditorIdForUniqueId(GetUniqueId()), true); - break; - } - case EScriptObjectMessage::SetToMax: - { - x2a8_28_projectilesCollide = false; - break; - } - default: - CActor::AcceptScriptMsg(msg, uid, mgr); - } -} - - -void CScriptDoor::Think(float dt, CStateManager& mgr) -{ +void CScriptDoor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Close: { if (!GetActive()) - return; + return; - if (!x2a8_26_isOpen && x25c_animTime < 0.5f) - x25c_animTime += dt; + if (x27c_partner1 != kInvalidUniqueId && x27c_partner1 != uid) + return; - if (x2a8_27_conditionsMet && GetDoorOpenCondition(mgr) == 2) - { - x2a8_27_conditionsMet = false; - OpenDoor(x280_prevDoor, mgr); + if (x2a8_26_isOpen) { + if (x27e_partner2 != kInvalidUniqueId) + if (CEntity* ent = mgr.ObjectById(x27e_partner2)) + mgr.SendScriptMsg(ent, GetUniqueId(), EScriptObjectMessage::Close); + x2a8_26_isOpen = false; + SetDoorAnimation(EDoorAnimType::Close); + mgr.GetCameraManager()->GetBallCamera()->DoorClosing(GetUniqueId()); + } else if (x2a8_27_conditionsMet) { + x2a8_27_conditionsMet = false; + SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); } - - if (x2a8_24_closing) - { - x2a8_25_wasOpen = false; - mgr.GetCameraManager()->GetBallCamera()->DoorClosed(GetUniqueId()); - x2a8_28_projectilesCollide = false; - x2a8_24_closing = false; - SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::Decrement); - x25c_animTime = 0.f; - x2a8_30_doClose = false; + break; + } + case EScriptObjectMessage::Action: { + if (x27c_partner1 != kInvalidUniqueId) { + if (TCastToPtr door = mgr.ObjectById(x27c_partner1)) { + if (!x2a8_26_isOpen) + return; + x2a8_30_doClose = true; + mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close); + } + } else if (x2a8_26_isOpen) { + x2a8_30_doClose = true; + if (TCastToPtr door = mgr.ObjectById(x27e_partner2)) { + mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close); + x2a8_30_doClose = true; + } + x2a8_26_isOpen = false; + SetDoorAnimation(EDoorAnimType::Close); + mgr.GetCameraManager()->GetBallCamera()->DoorClosing(GetUniqueId()); } + break; + } + case EScriptObjectMessage::Open: { + if (!GetActive() || x2a8_26_isOpen) + return; - if (x2a8_26_isOpen && !x64_modelData->IsAnimating()) - RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::Occluder, EMaterialTypes::Orbit, EMaterialTypes::Scannable, mgr); - else - { - if (x2a8_25_wasOpen && !x64_modelData->IsAnimating()) - { - x2a8_25_wasOpen = false; - mgr.GetCameraManager()->GetBallCamera()->DoorClosed(GetUniqueId()); - x2a8_28_projectilesCollide = false; - x2a8_27_conditionsMet = false; - SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); + u32 doorCond = TCastToConstPtr(mgr.GetObjectById(uid)) ? 2 : GetDoorOpenCondition(mgr); + switch (doorCond) { + case 1: + x2a8_27_conditionsMet = true; + x280_prevDoor = uid; + break; + case 2: + OpenDoor(uid, mgr); + break; + default: + x2a8_25_wasOpen = false; + x2a8_24_closing = true; + break; + } + break; + } + case EScriptObjectMessage::InitializedInArea: { + for (const SConnection& conn : x20_conns) { + if (conn.x4_msg == EScriptObjectMessage::Increment) { + TUniqueId dock = mgr.GetIdForScript(conn.x8_objId); + if (TCastToConstPtr d = mgr.GetObjectById(dock)) { + x282_dockId = d->GetUniqueId(); + break; } - - if (GetScannableObjectInfo()) - AddMaterial(EMaterialTypes::Solid, EMaterialTypes::Metal, EMaterialTypes::Occluder, EMaterialTypes::Orbit, EMaterialTypes::Scannable, mgr); - else - AddMaterial(EMaterialTypes::Solid, EMaterialTypes::Metal, EMaterialTypes::Occluder, EMaterialTypes::Orbit, mgr); + } } - - if (x64_modelData->IsAnimating()) - UpdateAnimation((x64_modelData->GetAnimationDuration(s32(x260_doorAnimState)) / x258_animLen) * dt, mgr, true); - - xe7_31_targetable = mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan; + break; + } + case EScriptObjectMessage::SetToZero: { + x2a8_28_projectilesCollide = true; + mgr.MapWorldInfo()->SetDoorVisited(mgr.GetEditorIdForUniqueId(GetUniqueId()), true); + break; + } + case EScriptObjectMessage::SetToMax: { + x2a8_28_projectilesCollide = false; + break; + } + default: + CActor::AcceptScriptMsg(msg, uid, mgr); + } } -void CScriptDoor::AddToRenderer(const zeus::CFrustum& /*frustum*/, const CStateManager &mgr) const -{ - if (!xe4_30_outOfFrustum) - CPhysicsActor::Render(mgr); +void CScriptDoor::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; + + if (!x2a8_26_isOpen && x25c_animTime < 0.5f) + x25c_animTime += dt; + + if (x2a8_27_conditionsMet && GetDoorOpenCondition(mgr) == 2) { + x2a8_27_conditionsMet = false; + OpenDoor(x280_prevDoor, mgr); + } + + if (x2a8_24_closing) { + x2a8_25_wasOpen = false; + mgr.GetCameraManager()->GetBallCamera()->DoorClosed(GetUniqueId()); + x2a8_28_projectilesCollide = false; + x2a8_24_closing = false; + SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::Decrement); + x25c_animTime = 0.f; + x2a8_30_doClose = false; + } + + if (x2a8_26_isOpen && !x64_modelData->IsAnimating()) + RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::Occluder, EMaterialTypes::Orbit, EMaterialTypes::Scannable, + mgr); + else { + if (x2a8_25_wasOpen && !x64_modelData->IsAnimating()) { + x2a8_25_wasOpen = false; + mgr.GetCameraManager()->GetBallCamera()->DoorClosed(GetUniqueId()); + x2a8_28_projectilesCollide = false; + x2a8_27_conditionsMet = false; + SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); + } + + if (GetScannableObjectInfo()) + AddMaterial(EMaterialTypes::Solid, EMaterialTypes::Metal, EMaterialTypes::Occluder, EMaterialTypes::Orbit, + EMaterialTypes::Scannable, mgr); + else + AddMaterial(EMaterialTypes::Solid, EMaterialTypes::Metal, EMaterialTypes::Occluder, EMaterialTypes::Orbit, mgr); + } + + if (x64_modelData->IsAnimating()) + UpdateAnimation((x64_modelData->GetAnimationDuration(s32(x260_doorAnimState)) / x258_animLen) * dt, mgr, true); + + xe7_31_targetable = mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan; +} + +void CScriptDoor::AddToRenderer(const zeus::CFrustum& /*frustum*/, const CStateManager& mgr) const { + if (!xe4_30_outOfFrustum) + CPhysicsActor::Render(mgr); } /* ORIGINAL 0-00 OFFSET: 8007E0BC */ -void CScriptDoor::ForceClosed(CStateManager & mgr) -{ - if (x2a8_26_isOpen) - { - x2a8_26_isOpen = false; - x2a8_25_wasOpen = false; +void CScriptDoor::ForceClosed(CStateManager& mgr) { + if (x2a8_26_isOpen) { + x2a8_26_isOpen = false; + x2a8_25_wasOpen = false; - mgr.GetCameraManager()->GetBallCamera()->DoorClosing(x8_uid); - mgr.GetCameraManager()->GetBallCamera()->DoorClosed(x8_uid); + mgr.GetCameraManager()->GetBallCamera()->DoorClosing(x8_uid); + mgr.GetCameraManager()->GetBallCamera()->DoorClosed(x8_uid); - SetDoorAnimation(EDoorAnimType::Close); - SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); + SetDoorAnimation(EDoorAnimType::Close); + SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); - x25c_animTime = 0.f; - x2a8_27_conditionsMet = false; - x2a8_30_doClose = false; - } - else if (x2a8_27_conditionsMet) - { - x2a8_27_conditionsMet = false; - x2a8_30_doClose = false; - SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); - } + x25c_animTime = 0.f; + x2a8_27_conditionsMet = false; + x2a8_30_doClose = false; + } else if (x2a8_27_conditionsMet) { + x2a8_27_conditionsMet = false; + x2a8_30_doClose = false; + SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); + } } /* ORIGINAL 0-00 OFFSET: 8007E1C4 */ -bool CScriptDoor::IsConnectedToArea(const CStateManager& mgr, TAreaId areaId) -{ - const CScriptDock* dockEnt = TCastToConstPtr(mgr.GetObjectById(x282_dockId)); - if (dockEnt) - { - if (dockEnt->GetAreaId() == areaId) - return true; +bool CScriptDoor::IsConnectedToArea(const CStateManager& mgr, TAreaId areaId) { + const CScriptDock* dockEnt = TCastToConstPtr(mgr.GetObjectById(x282_dockId)); + if (dockEnt) { + if (dockEnt->GetAreaId() == areaId) + return true; - const CWorld* world = mgr.GetWorld(); - const CGameArea* area = world->GetAreaAlways(dockEnt->GetAreaId()); - const CGameArea::Dock* dock = area->GetDock(dockEnt->GetDockId()); - if (dock->GetConnectedAreaId(dockEnt->GetDockReference(mgr)) == areaId) - return true; - } - return false; + const CWorld* world = mgr.GetWorld(); + const CGameArea* area = world->GetAreaAlways(dockEnt->GetAreaId()); + const CGameArea::Dock* dock = area->GetDock(dockEnt->GetDockId()); + if (dock->GetConnectedAreaId(dockEnt->GetDockReference(mgr)) == areaId) + return true; + } + return false; } /* ORIGINAL 0-00 OFFSET: 8007EA64 */ -void CScriptDoor::OpenDoor(TUniqueId uid, CStateManager& mgr) -{ - TEditorId eid = mgr.GetEditorIdForUniqueId(uid); - mgr.MapWorldInfo()->SetDoorVisited(eid, true); - x2a8_26_isOpen = true; - x2a8_25_wasOpen = true; - x2a8_27_conditionsMet = false; - x27c_partner1 = kInvalidUniqueId; - x27e_partner2 = kInvalidUniqueId; +void CScriptDoor::OpenDoor(TUniqueId uid, CStateManager& mgr) { + TEditorId eid = mgr.GetEditorIdForUniqueId(uid); + mgr.MapWorldInfo()->SetDoorVisited(eid, true); + x2a8_26_isOpen = true; + x2a8_25_wasOpen = true; + x2a8_27_conditionsMet = false; + x27c_partner1 = kInvalidUniqueId; + x27e_partner2 = kInvalidUniqueId; - if (const CScriptDoor* door = TCastToConstPtr(mgr.GetObjectById(uid))) - x27c_partner1 = door->GetUniqueId(); + if (const CScriptDoor* door = TCastToConstPtr(mgr.GetObjectById(uid))) + x27c_partner1 = door->GetUniqueId(); - SetDoorAnimation(EDoorAnimType::Open); - if (x27c_partner1 == kInvalidUniqueId) - SendScriptMsgs(EScriptObjectState::Open, mgr, EScriptObjectMessage::None); - else - SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); + SetDoorAnimation(EDoorAnimType::Open); + if (x27c_partner1 == kInvalidUniqueId) + SendScriptMsgs(EScriptObjectState::Open, mgr, EScriptObjectMessage::None); + else + SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); - if (TCastToConstPtr dock1 = mgr.GetObjectById(x282_dockId)) - { - for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) - { - TCastToConstPtr door = ent; - if (!door || door->GetUniqueId() == uid) - continue; + if (TCastToConstPtr dock1 = mgr.GetObjectById(x282_dockId)) { + for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) { + TCastToConstPtr door = ent; + if (!door || door->GetUniqueId() == uid) + continue; - if (TCastToConstPtr dock2 = mgr.GetObjectById(door->x282_dockId)) - { - if (dock1->GetCurrentConnectedAreaId(mgr) == dock2->GetAreaId() && - dock2->GetCurrentConnectedAreaId(mgr) == dock1->GetAreaId()) - { - x27e_partner2 = door->GetUniqueId(); - mgr.SendScriptMsg(ent, GetUniqueId(), EScriptObjectMessage::Open); - } - } + if (TCastToConstPtr dock2 = mgr.GetObjectById(door->x282_dockId)) { + if (dock1->GetCurrentConnectedAreaId(mgr) == dock2->GetAreaId() && + dock2->GetCurrentConnectedAreaId(mgr) == dock1->GetAreaId()) { + x27e_partner2 = door->GetUniqueId(); + mgr.SendScriptMsg(ent, GetUniqueId(), EScriptObjectMessage::Open); } + } } + } - if (x27c_partner1 == kInvalidUniqueId && x27e_partner2 == kInvalidUniqueId) - { - for (const SConnection& conn : x20_conns) - { - if (conn.x4_msg != EScriptObjectMessage::Open) - continue; - if (TCastToConstPtr door = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) - { - x27e_partner2 = door->GetUniqueId(); - break; - } - } + if (x27c_partner1 == kInvalidUniqueId && x27e_partner2 == kInvalidUniqueId) { + for (const SConnection& conn : x20_conns) { + if (conn.x4_msg != EScriptObjectMessage::Open) + continue; + if (TCastToConstPtr door = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) { + x27e_partner2 = door->GetUniqueId(); + break; + } } + } } /* ORIGINAL 0-00 OFFSET: 8007ED4C */ -u32 CScriptDoor::GetDoorOpenCondition(CStateManager& mgr) -{ - const TCastToPtr dock = mgr.ObjectById(x282_dockId); - if (!dock) - return 2; - - if (x25c_animTime < 0.05f || x2a8_30_doClose) - return 1; - - TAreaId destArea = dock->GetAreaId(); - if (destArea < 0 || destArea >= mgr.GetWorld()->GetNumAreas()) - return 0; - - if (!mgr.GetWorld()->GetAreaAlways(destArea)->IsPostConstructed()) - return 1; - - if (!mgr.GetWorld()->AreSkyNeedsMet()) - return 1; - - TAreaId connArea = mgr.GetWorld()->GetAreaAlways( - dock->GetAreaId())->GetDock( - dock->GetDockId())->GetConnectedAreaId(dock->GetDockReference(mgr)); - - if (connArea == kInvalidAreaId) - return 0; - - const CWorld* world = mgr.GetWorld(); - const CGameArea* area = world->GetAreaAlways(connArea); - - if (!area->IsPostConstructed()) - { - mgr.SendScriptMsg(dock, GetUniqueId(), EScriptObjectMessage::SetToMax); - return 1; - } - - if (area->GetPostConstructed()->x113c_playerActorsLoading != 0) - return 1; - - for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) - { - TCastToPtr door(ent); - if (!door || door->GetUniqueId() == GetUniqueId()) - continue; - - if (door->GetAreaIdAlways() == GetAreaIdAlways() && door->x2a8_25_wasOpen) - { - if (door->x282_dockId != kInvalidUniqueId) - return 1; - } - } - - for (const CGameArea& aliveArea : *world) - { - if (aliveArea.GetAreaId() == area->GetAreaId()) - continue; - - if (!aliveArea.IsFinishedOccluding()) - return 1; - } - - //if (area->TryTakingOutOfARAM()) - { - if (world->GetMapWorld()->IsMapAreasStreaming()) - return 1; - } - +u32 CScriptDoor::GetDoorOpenCondition(CStateManager& mgr) { + const TCastToPtr dock = mgr.ObjectById(x282_dockId); + if (!dock) return 2; + + if (x25c_animTime < 0.05f || x2a8_30_doClose) + return 1; + + TAreaId destArea = dock->GetAreaId(); + if (destArea < 0 || destArea >= mgr.GetWorld()->GetNumAreas()) + return 0; + + if (!mgr.GetWorld()->GetAreaAlways(destArea)->IsPostConstructed()) + return 1; + + if (!mgr.GetWorld()->AreSkyNeedsMet()) + return 1; + + TAreaId connArea = mgr.GetWorld() + ->GetAreaAlways(dock->GetAreaId()) + ->GetDock(dock->GetDockId()) + ->GetConnectedAreaId(dock->GetDockReference(mgr)); + + if (connArea == kInvalidAreaId) + return 0; + + const CWorld* world = mgr.GetWorld(); + const CGameArea* area = world->GetAreaAlways(connArea); + + if (!area->IsPostConstructed()) { + mgr.SendScriptMsg(dock, GetUniqueId(), EScriptObjectMessage::SetToMax); + return 1; + } + + if (area->GetPostConstructed()->x113c_playerActorsLoading != 0) + return 1; + + for (CEntity* ent : mgr.GetPlatformAndDoorObjectList()) { + TCastToPtr door(ent); + if (!door || door->GetUniqueId() == GetUniqueId()) + continue; + + if (door->GetAreaIdAlways() == GetAreaIdAlways() && door->x2a8_25_wasOpen) { + if (door->x282_dockId != kInvalidUniqueId) + return 1; + } + } + + for (const CGameArea& aliveArea : *world) { + if (aliveArea.GetAreaId() == area->GetAreaId()) + continue; + + if (!aliveArea.IsFinishedOccluding()) + return 1; + } + + // if (area->TryTakingOutOfARAM()) + { + if (world->GetMapWorld()->IsMapAreasStreaming()) + return 1; + } + + return 2; } /* ORIGINAL 0-00 OFFSET: 8007E9D0 */ -void CScriptDoor::SetDoorAnimation(CScriptDoor::EDoorAnimType type) -{ - x260_doorAnimState = type; - CModelData* modelData = x64_modelData.get(); - if (modelData && modelData->AnimationData()) - modelData->AnimationData()->SetAnimation(CAnimPlaybackParms(s32(type), -1, 1.f, true), false); +void CScriptDoor::SetDoorAnimation(CScriptDoor::EDoorAnimType type) { + x260_doorAnimState = type; + CModelData* modelData = x64_modelData.get(); + if (modelData && modelData->AnimationData()) + modelData->AnimationData()->SetAnimation(CAnimPlaybackParms(s32(type), -1, 1.f, true), false); } -std::experimental::optional CScriptDoor::GetTouchBounds() const -{ - if (GetActive() && GetMaterialList().HasMaterial(EMaterialTypes::Solid)) - return {CPhysicsActor::GetBoundingBox()}; - return {}; +std::experimental::optional CScriptDoor::GetTouchBounds() const { + if (GetActive() && GetMaterialList().HasMaterial(EMaterialTypes::Solid)) + return {CPhysicsActor::GetBoundingBox()}; + return {}; } -std::experimental::optional CScriptDoor::GetProjectileBounds() const -{ - if (x2a8_28_projectilesCollide) - return {{x284_modelBounds.min + GetTranslation(), x284_modelBounds.max + GetTranslation()}}; - return {}; +std::experimental::optional CScriptDoor::GetProjectileBounds() const { + if (x2a8_28_projectilesCollide) + return {{x284_modelBounds.min + GetTranslation(), x284_modelBounds.max + GetTranslation()}}; + return {}; } -} +} // namespace urde diff --git a/Runtime/World/CScriptDoor.hpp b/Runtime/World/CScriptDoor.hpp index 85e28d419..acc184f46 100644 --- a/Runtime/World/CScriptDoor.hpp +++ b/Runtime/World/CScriptDoor.hpp @@ -2,58 +2,54 @@ #include "CPhysicsActor.hpp" -namespace urde -{ +namespace urde { -class CScriptDoor : public CPhysicsActor -{ +class CScriptDoor : public CPhysicsActor { public: - enum class EDoorAnimType - { - Open, - Close, - Ready, - }; + enum class EDoorAnimType { + Open, + Close, + Ready, + }; - float x258_animLen; - float x25c_animTime = 0.f; - EDoorAnimType x260_doorAnimState = EDoorAnimType::Open; - zeus::CAABox x264_; - TUniqueId x27c_partner1 = kInvalidUniqueId; - TUniqueId x27e_partner2 = kInvalidUniqueId; - TUniqueId x280_prevDoor = kInvalidUniqueId; - TUniqueId x282_dockId = kInvalidUniqueId; - zeus::CAABox x284_modelBounds; - zeus::CVector3f x29c_orbitPos; + float x258_animLen; + float x25c_animTime = 0.f; + EDoorAnimType x260_doorAnimState = EDoorAnimType::Open; + zeus::CAABox x264_; + TUniqueId x27c_partner1 = kInvalidUniqueId; + TUniqueId x27e_partner2 = kInvalidUniqueId; + TUniqueId x280_prevDoor = kInvalidUniqueId; + TUniqueId x282_dockId = kInvalidUniqueId; + zeus::CAABox x284_modelBounds; + zeus::CVector3f x29c_orbitPos; + + bool x2a8_24_closing : 1; + bool x2a8_25_wasOpen : 1; + bool x2a8_26_isOpen : 1; + bool x2a8_27_conditionsMet : 1; + bool x2a8_28_projectilesCollide : 1; + bool x2a8_29_ballDoor : 1; + bool x2a8_30_doClose : 1; - bool x2a8_24_closing : 1; - bool x2a8_25_wasOpen : 1; - bool x2a8_26_isOpen : 1; - bool x2a8_27_conditionsMet : 1; - bool x2a8_28_projectilesCollide : 1; - bool x2a8_29_ballDoor : 1; - bool x2a8_30_doClose : 1; public: - CScriptDoor(TUniqueId, std::string_view name, const CEntityInfo& info, - const zeus::CTransform&, CModelData&&, const CActorParameters&, - const zeus::CVector3f&, const zeus::CAABox&, - bool active, bool open, bool, float, bool ballDoor); + CScriptDoor(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const zeus::CVector3f&, const zeus::CAABox&, bool active, bool open, bool, float, + bool ballDoor); - zeus::CVector3f GetOrbitPosition(const CStateManager& mgr) const; - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); - void Think(float, CStateManager& mgr); - void AddToRenderer(const zeus::CFrustum&, const CStateManager& mgr) const; - void Render(const CStateManager&) const {} - void ForceClosed(CStateManager&); - bool IsConnectedToArea(const CStateManager& mgr, TAreaId area); - void OpenDoor(TUniqueId, CStateManager&); - u32 GetDoorOpenCondition(CStateManager& mgr); - void SetDoorAnimation(EDoorAnimType); - std::experimental::optional GetTouchBounds() const; - std::experimental::optional GetProjectileBounds() const; - bool IsOpen() const { return x2a8_26_isOpen; } + zeus::CVector3f GetOrbitPosition(const CStateManager& mgr) const; + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); + void Think(float, CStateManager& mgr); + void AddToRenderer(const zeus::CFrustum&, const CStateManager& mgr) const; + void Render(const CStateManager&) const {} + void ForceClosed(CStateManager&); + bool IsConnectedToArea(const CStateManager& mgr, TAreaId area); + void OpenDoor(TUniqueId, CStateManager&); + u32 GetDoorOpenCondition(CStateManager& mgr); + void SetDoorAnimation(EDoorAnimType); + std::experimental::optional GetTouchBounds() const; + std::experimental::optional GetProjectileBounds() const; + bool IsOpen() const { return x2a8_26_isOpen; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptEMPulse.cpp b/Runtime/World/CScriptEMPulse.cpp index bd504ecc8..8e2298b8d 100644 --- a/Runtime/World/CScriptEMPulse.cpp +++ b/Runtime/World/CScriptEMPulse.cpp @@ -9,97 +9,82 @@ #include "Graphics/CBooRenderer.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptEMPulse::CScriptEMPulse(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, float initialRadius, float finalRadius, - float duration, - float interferenceDur, float f5, float interferenceMag, float f7, CAssetId partId) - : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Projectile), - CActorParameters::None().HotInThermal(true), kInvalidUniqueId), xe8_duration(duration), - xec_finalRadius(finalRadius), xf0_currentRadius(initialRadius), xf4_initialRadius(initialRadius), - xf8_interferenceDur(interferenceDur), xfc_(f5), x100_interferenceMag(interferenceMag), x104_(f7), - x108_particleDesc(g_SimplePool->GetObj({SBIG('PART'), partId})) -{ + float duration, float interferenceDur, float f5, float interferenceMag, float f7, + CAssetId partId) +: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Projectile), + CActorParameters::None().HotInThermal(true), kInvalidUniqueId) +, xe8_duration(duration) +, xec_finalRadius(finalRadius) +, xf0_currentRadius(initialRadius) +, xf4_initialRadius(initialRadius) +, xf8_interferenceDur(interferenceDur) +, xfc_(f5) +, x100_interferenceMag(interferenceMag) +, x104_(f7) +, x108_particleDesc(g_SimplePool->GetObj({SBIG('PART'), partId})) {} + +void CScriptEMPulse::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptEMPulse::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; + + xf0_currentRadius += ((xec_finalRadius - xf4_initialRadius) / xe8_duration) * dt; + if (xf0_currentRadius < xec_finalRadius) + mgr.FreeScriptObject(GetUniqueId()); + + x114_particleGen->Update(dt); } -void CScriptEMPulse::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptEMPulse::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); + if (msg == EScriptObjectMessage::Activate) { + x114_particleGen.reset(new CElementGen(x108_particleDesc, CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One)); + + x114_particleGen->SetOrientation(GetTransform().getRotation()); + x114_particleGen->SetGlobalTranslation(GetTranslation()); + x114_particleGen->SetParticleEmission(true); + mgr.GetPlayerState()->GetStaticInterference().AddSource(GetUniqueId(), x100_interferenceMag, xf8_interferenceDur); + } } -void CScriptEMPulse::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; - - xf0_currentRadius += ((xec_finalRadius - xf4_initialRadius) / xe8_duration) * dt; - if (xf0_currentRadius < xec_finalRadius) - mgr.FreeScriptObject(GetUniqueId()); - - x114_particleGen->Update(dt); +void CScriptEMPulse::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) const { + CActor::AddToRenderer(frustum, mgr); + if (GetActive()) + g_Renderer->AddParticleGen(*x114_particleGen); } -void CScriptEMPulse::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); - if (msg == EScriptObjectMessage::Activate) - { - x114_particleGen.reset(new CElementGen(x108_particleDesc, CElementGen::EModelOrientationType::Normal, - CElementGen::EOptionalSystemFlags::One)); +void CScriptEMPulse::CalculateRenderBounds() { x9c_renderBounds = CalculateBoundingBox(); } - x114_particleGen->SetOrientation(GetTransform().getRotation()); - x114_particleGen->SetGlobalTranslation(GetTranslation()); - x114_particleGen->SetParticleEmission(true); - mgr.GetPlayerState()->GetStaticInterference().AddSource(GetUniqueId(), x100_interferenceMag, - xf8_interferenceDur); +std::experimental::optional CScriptEMPulse::GetTouchBounds() const { return {CalculateBoundingBox()}; } + +void CScriptEMPulse::Touch(CActor& act, CStateManager& mgr) { + if (!GetActive()) + return; + + if (TCastToPtr pl = act) { + zeus::CVector3f posDiff = GetTranslation() - pl->GetTranslation(); + if (posDiff.magnitude() < xec_finalRadius) { + float dur = + ((1.f - (posDiff.magnitude() / xec_finalRadius)) * (xfc_ - xf8_interferenceDur)) + xf8_interferenceDur; + float mag = + ((1.f - (posDiff.magnitude() / xec_finalRadius)) * (x104_ - xf8_interferenceDur)) + x100_interferenceMag; + + if (dur > pl->GetStaticTimer()) + pl->SetHudDisable(dur, 0.5f, 2.5f); + else + mgr.GetPlayerState()->GetStaticInterference().AddSource(GetUniqueId(), mag, dur); } + } } -void CScriptEMPulse::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) const -{ - CActor::AddToRenderer(frustum, mgr); - if (GetActive()) - g_Renderer->AddParticleGen(*x114_particleGen); +zeus::CAABox CScriptEMPulse::CalculateBoundingBox() const { + return zeus::CAABox(GetTranslation() - xf0_currentRadius, GetTranslation() + xf0_currentRadius); } -void CScriptEMPulse::CalculateRenderBounds() -{ - x9c_renderBounds = CalculateBoundingBox(); -} - -std::experimental::optional CScriptEMPulse::GetTouchBounds() const -{ - return {CalculateBoundingBox()}; -} - -void CScriptEMPulse::Touch(CActor& act, CStateManager& mgr) -{ - if (!GetActive()) - return; - - if (TCastToPtr pl = act) - { - zeus::CVector3f posDiff = GetTranslation() - pl->GetTranslation(); - if (posDiff.magnitude() < xec_finalRadius) - { - float dur = - ((1.f - (posDiff.magnitude() / xec_finalRadius)) * (xfc_ - xf8_interferenceDur)) + xf8_interferenceDur; - float mag = ((1.f - (posDiff.magnitude() / xec_finalRadius)) * (x104_ - xf8_interferenceDur)) + - x100_interferenceMag; - - if (dur > pl->GetStaticTimer()) - pl->SetHudDisable(dur, 0.5f, 2.5f); - else - mgr.GetPlayerState()->GetStaticInterference().AddSource(GetUniqueId(), mag, dur); - } - } -} - -zeus::CAABox CScriptEMPulse::CalculateBoundingBox() const -{ - return zeus::CAABox(GetTranslation() - xf0_currentRadius, GetTranslation() + xf0_currentRadius); -} - -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/World/CScriptEMPulse.hpp b/Runtime/World/CScriptEMPulse.hpp index bd17aa070..a7f78bf84 100644 --- a/Runtime/World/CScriptEMPulse.hpp +++ b/Runtime/World/CScriptEMPulse.hpp @@ -3,34 +3,33 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { class CGenDescription; class CElementGen; -class CScriptEMPulse : public CActor -{ - float xe8_duration; - float xec_finalRadius; - float xf0_currentRadius; - float xf4_initialRadius; - float xf8_interferenceDur; - float xfc_; - float x100_interferenceMag; - float x104_; - TCachedToken x108_particleDesc; - std::unique_ptr x114_particleGen; - zeus::CAABox CalculateBoundingBox() const; -public: - CScriptEMPulse(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, float, float, float, - float, float, float, float, CAssetId); +class CScriptEMPulse : public CActor { + float xe8_duration; + float xec_finalRadius; + float xf0_currentRadius; + float xf4_initialRadius; + float xf8_interferenceDur; + float xfc_; + float x100_interferenceMag; + float x104_; + TCachedToken x108_particleDesc; + std::unique_ptr x114_particleGen; + zeus::CAABox CalculateBoundingBox() const; - void Accept(IVisitor&); - void Think(float, CStateManager&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void AddToRenderer(const zeus::CFrustum&, CStateManager&) const; - void CalculateRenderBounds(); - std::experimental::optional GetTouchBounds() const; - void Touch(CActor&, CStateManager&); +public: + CScriptEMPulse(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, float, float, float, + float, float, float, float, CAssetId); + + void Accept(IVisitor&); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, CStateManager&) const; + void CalculateRenderBounds(); + std::experimental::optional GetTouchBounds() const; + void Touch(CActor&, CStateManager&); }; -} +} // namespace urde #endif // __URDE_CSCRIPTEMPULSE_HPP__ \ No newline at end of file diff --git a/Runtime/World/CScriptEffect.cpp b/Runtime/World/CScriptEffect.cpp index 6ea511359..6f5cd3d54 100644 --- a/Runtime/World/CScriptEffect.cpp +++ b/Runtime/World/CScriptEffect.cpp @@ -14,21 +14,19 @@ #include "CScriptTrigger.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { u32 CScriptEffect::g_NumParticlesUpdating = 0; u32 CScriptEffect::g_NumParticlesRendered = 0; -CScriptEffect::CScriptEffect(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, const zeus::CVector3f& scale, - CAssetId partId, CAssetId elscId, bool hotInThermal, bool noTimerUnlessAreaOccluded, - bool rebuildSystemsOnActivate, bool active, bool useRateInverseCamDist, - float rateInverseCamDist, float rateInverseCamDistRate, float duration, - float durationResetWhileVisible, bool useRateCamDistRange, float rateCamDistRangeMin, - float rateCamDistRangeMax, float rateCamDistRangeFarRate, bool combatVisorVisible, - bool thermalVisorVisible, bool xrayVisorVisible, const CLightParameters& lParms, - bool dieWhenSystemsDone) +CScriptEffect::CScriptEffect(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + const zeus::CVector3f& scale, CAssetId partId, CAssetId elscId, bool hotInThermal, + bool noTimerUnlessAreaOccluded, bool rebuildSystemsOnActivate, bool active, + bool useRateInverseCamDist, float rateInverseCamDist, float rateInverseCamDistRate, + float duration, float durationResetWhileVisible, bool useRateCamDistRange, + float rateCamDistRangeMin, float rateCamDistRangeMax, float rateCamDistRangeFarRate, + bool combatVisorVisible, bool thermalVisorVisible, bool xrayVisorVisible, + const CLightParameters& lParms, bool dieWhenSystemsDone) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(), CActorParameters::None().HotInThermal(hotInThermal), kInvalidUniqueId) , x10c_partId(partId) @@ -41,379 +39,326 @@ CScriptEffect::CScriptEffect(TUniqueId uid, std::string_view name, const CEntity , x12c_remTime(duration) , x130_duration(duration) , x134_durationResetWhileVisible(durationResetWhileVisible) -, x138_actorLights(lParms.MakeActorLights()) -{ - x110_24_enable = active; - x110_25_noTimerUnlessAreaOccluded = noTimerUnlessAreaOccluded; - x110_26_rebuildSystemsOnActivate = rebuildSystemsOnActivate; - x110_27_useRateInverseCamDist = useRateInverseCamDist; - x110_28_combatVisorVisible = combatVisorVisible; - x110_29_thermalVisorVisible = thermalVisorVisible; - x110_30_xrayVisorVisible = xrayVisorVisible; - x110_31_anyVisorVisible = xrayVisorVisible && thermalVisorVisible && combatVisorVisible; - x111_24_useRateCamDistRange = useRateCamDistRange; - x111_25_dieWhenSystemsDone = dieWhenSystemsDone; - x111_26_canRender = false; +, x138_actorLights(lParms.MakeActorLights()) { + x110_24_enable = active; + x110_25_noTimerUnlessAreaOccluded = noTimerUnlessAreaOccluded; + x110_26_rebuildSystemsOnActivate = rebuildSystemsOnActivate; + x110_27_useRateInverseCamDist = useRateInverseCamDist; + x110_28_combatVisorVisible = combatVisorVisible; + x110_29_thermalVisorVisible = thermalVisorVisible; + x110_30_xrayVisorVisible = xrayVisorVisible; + x110_31_anyVisorVisible = xrayVisorVisible && thermalVisorVisible && combatVisorVisible; + x111_24_useRateCamDistRange = useRateCamDistRange; + x111_25_dieWhenSystemsDone = dieWhenSystemsDone; + x111_26_canRender = false; - if (partId.IsValid()) - { - xf8_particleSystemToken = g_SimplePool->GetObj({FOURCC('PART'), partId}); + if (partId.IsValid()) { + xf8_particleSystemToken = g_SimplePool->GetObj({FOURCC('PART'), partId}); + x104_particleSystem.reset(new CElementGen(xf8_particleSystemToken)); + zeus::CTransform newXf = xf; + newXf.origin = zeus::CVector3f::skZero; + x104_particleSystem->SetOrientation(newXf); + x104_particleSystem->SetGlobalTranslation(xf.origin); + x104_particleSystem->SetLocalScale(scale); + x104_particleSystem->SetParticleEmission(active); + x104_particleSystem->SetModulationColor(lParms.GetNoLightsAmbient()); + x104_particleSystem->SetModelsUseLights(x138_actorLights != nullptr); + } + + if (elscId.IsValid()) { + xe8_electricToken = g_SimplePool->GetObj({FOURCC('ELSC'), elscId}); + xf4_electric.reset(new CParticleElectric(xe8_electricToken)); + zeus::CTransform newXf = xf; + newXf.origin = zeus::CVector3f::skZero; + xf4_electric->SetOrientation(newXf); + xf4_electric->SetGlobalTranslation(xf.origin); + xf4_electric->SetLocalScale(scale); + xf4_electric->SetParticleEmission(active); + } + xe7_29_drawEnabled = true; +} + +void CScriptEffect::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptEffect::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + bool oldActive = GetActive(); + + switch (msg) { + case EScriptObjectMessage::Activate: + if (x110_26_rebuildSystemsOnActivate) { + if (x104_particleSystem) { + zeus::CVector3f scale = x104_particleSystem->GetGlobalScale(); + zeus::CColor color = x104_particleSystem->GetModulationColor(); x104_particleSystem.reset(new CElementGen(xf8_particleSystemToken)); - zeus::CTransform newXf = xf; + zeus::CTransform newXf = GetTransform(); newXf.origin = zeus::CVector3f::skZero; x104_particleSystem->SetOrientation(newXf); - x104_particleSystem->SetGlobalTranslation(xf.origin); + x104_particleSystem->SetGlobalTranslation(GetTranslation()); x104_particleSystem->SetLocalScale(scale); - x104_particleSystem->SetParticleEmission(active); - x104_particleSystem->SetModulationColor(lParms.GetNoLightsAmbient()); + x104_particleSystem->SetParticleEmission(oldActive); + x104_particleSystem->SetModulationColor(color); x104_particleSystem->SetModelsUseLights(x138_actorLights != nullptr); - } + } - - if (elscId.IsValid()) - { - xe8_electricToken = g_SimplePool->GetObj({FOURCC('ELSC'), elscId}); + if (xf4_electric) { + zeus::CVector3f scale = xf4_electric->GetGlobalScale(); + zeus::CColor color = xf4_electric->GetModulationColor(); xf4_electric.reset(new CParticleElectric(xe8_electricToken)); - zeus::CTransform newXf = xf; + zeus::CTransform newXf = GetTransform(); newXf.origin = zeus::CVector3f::skZero; xf4_electric->SetOrientation(newXf); - xf4_electric->SetGlobalTranslation(xf.origin); + xf4_electric->SetGlobalTranslation(GetTranslation()); xf4_electric->SetLocalScale(scale); - xf4_electric->SetParticleEmission(active); + xf4_electric->SetParticleEmission(oldActive); + xf4_electric->SetModulationColor(color); + } } - xe7_29_drawEnabled = true; -} - -void CScriptEffect::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CScriptEffect::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - bool oldActive = GetActive(); - - switch (msg) - { - case EScriptObjectMessage::Activate: - if (x110_26_rebuildSystemsOnActivate) - { - if (x104_particleSystem) - { - zeus::CVector3f scale = x104_particleSystem->GetGlobalScale(); - zeus::CColor color = x104_particleSystem->GetModulationColor(); - x104_particleSystem.reset(new CElementGen(xf8_particleSystemToken)); - zeus::CTransform newXf = GetTransform(); - newXf.origin = zeus::CVector3f::skZero; - x104_particleSystem->SetOrientation(newXf); - x104_particleSystem->SetGlobalTranslation(GetTranslation()); - x104_particleSystem->SetLocalScale(scale); - x104_particleSystem->SetParticleEmission(oldActive); - x104_particleSystem->SetModulationColor(color); - x104_particleSystem->SetModelsUseLights(x138_actorLights != nullptr); - } - - if (xf4_electric) - { - zeus::CVector3f scale = xf4_electric->GetGlobalScale(); - zeus::CColor color = xf4_electric->GetModulationColor(); - xf4_electric.reset(new CParticleElectric(xe8_electricToken)); - zeus::CTransform newXf = GetTransform(); - newXf.origin = zeus::CVector3f::skZero; - xf4_electric->SetOrientation(newXf); - xf4_electric->SetGlobalTranslation(GetTranslation()); - xf4_electric->SetLocalScale(scale); - xf4_electric->SetParticleEmission(oldActive); - xf4_electric->SetModulationColor(color); - } + break; + case EScriptObjectMessage::Registered: + if (x104_particleSystem && x104_particleSystem->SystemHasLight()) { + x108_lightId = mgr.AllocateUniqueId(); + mgr.AddObject(new CGameLight(x108_lightId, GetAreaIdAlways(), GetActive(), + std::string("EffectPLight_") + GetName().data(), x34_transform, GetUniqueId(), + x104_particleSystem->GetLight(), x10c_partId.Value(), 1, 0.f)); + } + break; + case EScriptObjectMessage::Deleted: + if (x108_lightId != kInvalidUniqueId) { + mgr.FreeScriptObject(x108_lightId); + x108_lightId = kInvalidUniqueId; + } + break; + case EScriptObjectMessage::InitializedInArea: + for (const SConnection& conn : x20_conns) { + if ((conn.x0_state == EScriptObjectState::Modify && conn.x4_msg == EScriptObjectMessage::Follow) || + (conn.x0_state == EScriptObjectState::InheritBounds && conn.x4_msg == EScriptObjectMessage::Activate)) { + auto search = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) { + if (TCastToConstPtr(mgr.GetObjectById(it->second))) + x13c_triggerId = it->second; } - break; - case EScriptObjectMessage::Registered: - if (x104_particleSystem && x104_particleSystem->SystemHasLight()) - { - x108_lightId = mgr.AllocateUniqueId(); - mgr.AddObject(new CGameLight(x108_lightId, GetAreaIdAlways(), GetActive(), - std::string("EffectPLight_") + GetName().data(), x34_transform, GetUniqueId(), - x104_particleSystem->GetLight(), x10c_partId.Value(), 1, 0.f)); - } - break; - case EScriptObjectMessage::Deleted: - if (x108_lightId != kInvalidUniqueId) - { - mgr.FreeScriptObject(x108_lightId); - x108_lightId = kInvalidUniqueId; - } - break; - case EScriptObjectMessage::InitializedInArea: - for (const SConnection& conn : x20_conns) - { - if ((conn.x0_state == EScriptObjectState::Modify && conn.x4_msg == EScriptObjectMessage::Follow) || - (conn.x0_state == EScriptObjectState::InheritBounds && conn.x4_msg == EScriptObjectMessage::Activate)) - { - auto search = mgr.GetIdListForScript(conn.x8_objId); - for (auto it = search.first; it != search.second; ++it) - { - if (TCastToConstPtr(mgr.GetObjectById(it->second))) - x13c_triggerId = it->second; - } - } - } - break; - default: - break; + } + } + break; + default: + break; + } + + CActor::AcceptScriptMsg(msg, uid, mgr); + + TCastToPtr light = mgr.ObjectById(x108_lightId); + mgr.SendScriptMsg(light, uid, msg); + + if (oldActive != GetActive()) { + std::vector playIds; + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) + continue; + + TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); + if (uid != kInvalidUniqueId) + playIds.push_back(uid); } - CActor::AcceptScriptMsg(msg, uid, mgr); - - TCastToPtr light = mgr.ObjectById(x108_lightId); - mgr.SendScriptMsg(light, uid, msg); - - if (oldActive != GetActive()) - { - std::vector playIds; - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) - continue; - - TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); - if (uid != kInvalidUniqueId) - playIds.push_back(uid); - } - - if (playIds.size() > 0) - { - TCastToConstPtr otherAct = - mgr.GetObjectById(playIds[u32(0.99f * playIds.size() * mgr.GetActiveRandom()->Float())]); - if (otherAct) - light->SetTransform(otherAct->GetTransform()); - else - light->SetTransform(GetTransform()); - } - x110_24_enable = true; - if (x104_particleSystem) - x104_particleSystem->SetParticleEmission(GetActive()); - if (xf4_electric) - xf4_electric->SetParticleEmission(GetActive()); - - if (GetActive()) - x12c_remTime = zeus::max(x12c_remTime, x130_duration); + if (playIds.size() > 0) { + TCastToConstPtr otherAct = + mgr.GetObjectById(playIds[u32(0.99f * playIds.size() * mgr.GetActiveRandom()->Float())]); + if (otherAct) + light->SetTransform(otherAct->GetTransform()); + else + light->SetTransform(GetTransform()); } -} - -void CScriptEffect::PreRender(CStateManager& mgr, const zeus::CFrustum&) -{ - if (x110_27_useRateInverseCamDist || x111_24_useRateCamDistRange) - { - float genRate = 1.f; - const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - float camMagSq = (cam->GetTranslation() - GetTranslation()).magSquared(); - - float camMag = 0.f; - if (camMagSq > 0.001f) - camMag = std::sqrt(camMagSq); - if (x110_27_useRateInverseCamDist && camMagSq < x118_rateInverseCamDistSq) - genRate = (1.f - x11c_rateInverseCamDistRate) * (camMag / x114_rateInverseCamDist) + - x11c_rateInverseCamDistRate; - if (x111_24_useRateCamDistRange) - { - float t = zeus::min(1.f, zeus::max(0.f, camMag - x120_rateCamDistRangeMin) / - (x124_rateCamDistRangeMax - x120_rateCamDistRangeMin)); - genRate = (1.f - t) * genRate + t * x128_rateCamDistRangeFarRate; - } - - x104_particleSystem->SetGeneratorRate(genRate); - } - - if (!mgr.GetObjectById(x13c_triggerId)) - x13c_triggerId = kInvalidUniqueId; -} - -void CScriptEffect::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - if (!x111_26_canRender) - { - const_cast(*this).x12c_remTime = zeus::max(x12c_remTime, x134_durationResetWhileVisible); - return; - } - - if (!frustum.aabbFrustumTest(x9c_renderBounds)) - return; - const_cast(*this).x12c_remTime = zeus::max(x12c_remTime, x134_durationResetWhileVisible); - - if (x110_31_anyVisorVisible) - { - bool visible = false; - const CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); - if (visor == CPlayerState::EPlayerVisor::Combat || visor == CPlayerState::EPlayerVisor::Scan) - visible = x110_28_combatVisorVisible; - else if (visor == CPlayerState::EPlayerVisor::XRay) - visible = x110_30_xrayVisorVisible; - else if (visor == CPlayerState::EPlayerVisor::Thermal) - visible = x110_29_thermalVisorVisible; - - if (visible && x138_actorLights) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); - const_cast(*this).x138_actorLights->BuildAreaLightList( - mgr, *area, zeus::CAABox{x9c_renderBounds.center(), x9c_renderBounds.center()}); - const_cast(*this).x138_actorLights->BuildDynamicLightList(mgr, x9c_renderBounds); - } - EnsureRendered(mgr); - } -} - -void CScriptEffect::Render(const CStateManager& mgr) const -{ - /* The following code is kept for reference, this is now performed in CElementGen - if (x138_actorLights) - x138_actorLights->ActivateLights(); - */ - if (x104_particleSystem && x104_particleSystem->GetParticleCountAll() > 0) - { - g_NumParticlesRendered += x104_particleSystem->GetParticleCountAll(); - x104_particleSystem->Render(GetActorLights()); - } - - if (xf4_electric && xf4_electric->GetParticleCount() > 0) - { - g_NumParticlesRendered += xf4_electric->GetParticleCount(); - xf4_electric->Render(GetActorLights()); - } -} - -void CScriptEffect::Think(float dt, CStateManager& mgr) -{ - if (xe4_28_transformDirty) - { - if (x104_particleSystem) - { - zeus::CTransform newXf = x34_transform; - newXf.origin = zeus::CVector3f::skZero; - x104_particleSystem->SetOrientation(newXf); - x104_particleSystem->SetGlobalTranslation(x34_transform.origin); - } - if (xf4_electric) - { - zeus::CTransform newXf = x34_transform; - newXf.origin = zeus::CVector3f::skZero; - xf4_electric->SetOrientation(newXf); - xf4_electric->SetGlobalTranslation(x34_transform.origin); - } - - if (TCastToPtr act = mgr.ObjectById(x108_lightId)) - act->SetTransform(GetTransform()); - - xe4_28_transformDirty = false; - } - - if (x110_25_noTimerUnlessAreaOccluded) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); - CGameArea::EOcclusionState visible = area->IsPostConstructed() ? area->GetOcclusionState() : - CGameArea::EOcclusionState::Occluded; - - if (visible == CGameArea::EOcclusionState::Occluded && x12c_remTime <= 0.f) - return; - } - else if (x12c_remTime <= 0.f) - return; - - x12c_remTime -= dt; - - if (x110_24_enable) - { - if (x104_particleSystem) - { - x104_particleSystem->Update(dt); - g_NumParticlesUpdating += x104_particleSystem->GetParticleCountAll(); - } - - if (xf4_electric) - { - xf4_electric->Update(dt); - g_NumParticlesUpdating += xf4_electric->GetParticleCount(); - } - - if (x108_lightId != kInvalidUniqueId) - { - if (TCastToPtr light = mgr.ObjectById(x108_lightId)) - { - if (x30_24_active) - light->SetLight(x104_particleSystem->GetLight()); - } - } - - if (x111_25_dieWhenSystemsDone) - { - x140_destroyDelayTimer += dt; - if (x140_destroyDelayTimer > 15.f || AreBothSystemsDeleteable()) - { - mgr.FreeScriptObject(GetUniqueId()); - return; - } - } - } - + x110_24_enable = true; if (x104_particleSystem) - { - if (xb4_drawFlags.x0_blendMode != 0) - x104_particleSystem->SetModulationColor(xb4_drawFlags.x4_color); - else - x104_particleSystem->SetModulationColor(zeus::CColor::skWhite); - } -} - -void CScriptEffect::CalculateRenderBounds() -{ - std::experimental::optional particleBounds; - if (x104_particleSystem) - particleBounds = x104_particleSystem->GetBounds(); - - std::experimental::optional electricBounds; + x104_particleSystem->SetParticleEmission(GetActive()); if (xf4_electric) - electricBounds = xf4_electric->GetBounds(); + xf4_electric->SetParticleEmission(GetActive()); - if (particleBounds || electricBounds) - { - zeus::CAABox renderBounds = zeus::CAABox::skInvertedBox; - if (particleBounds) - { - renderBounds.accumulateBounds(particleBounds->min); - renderBounds.accumulateBounds(particleBounds->max); - } - if (electricBounds) - { - renderBounds.accumulateBounds(electricBounds->min); - renderBounds.accumulateBounds(electricBounds->max); - } - x9c_renderBounds = renderBounds; - x111_26_canRender = true; + if (GetActive()) + x12c_remTime = zeus::max(x12c_remTime, x130_duration); + } +} + +void CScriptEffect::PreRender(CStateManager& mgr, const zeus::CFrustum&) { + if (x110_27_useRateInverseCamDist || x111_24_useRateCamDistRange) { + float genRate = 1.f; + const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + float camMagSq = (cam->GetTranslation() - GetTranslation()).magSquared(); + + float camMag = 0.f; + if (camMagSq > 0.001f) + camMag = std::sqrt(camMagSq); + if (x110_27_useRateInverseCamDist && camMagSq < x118_rateInverseCamDistSq) + genRate = (1.f - x11c_rateInverseCamDistRate) * (camMag / x114_rateInverseCamDist) + x11c_rateInverseCamDistRate; + if (x111_24_useRateCamDistRange) { + float t = zeus::min(1.f, zeus::max(0.f, camMag - x120_rateCamDistRangeMin) / + (x124_rateCamDistRangeMax - x120_rateCamDistRangeMin)); + genRate = (1.f - t) * genRate + t * x128_rateCamDistRangeFarRate; } - else - { - x9c_renderBounds = {GetTranslation(), GetTranslation()}; - x111_26_canRender = false; + + x104_particleSystem->SetGeneratorRate(genRate); + } + + if (!mgr.GetObjectById(x13c_triggerId)) + x13c_triggerId = kInvalidUniqueId; +} + +void CScriptEffect::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + if (!x111_26_canRender) { + const_cast(*this).x12c_remTime = zeus::max(x12c_remTime, x134_durationResetWhileVisible); + return; + } + + if (!frustum.aabbFrustumTest(x9c_renderBounds)) + return; + const_cast(*this).x12c_remTime = zeus::max(x12c_remTime, x134_durationResetWhileVisible); + + if (x110_31_anyVisorVisible) { + bool visible = false; + const CPlayerState::EPlayerVisor visor = mgr.GetPlayerState()->GetActiveVisor(mgr); + if (visor == CPlayerState::EPlayerVisor::Combat || visor == CPlayerState::EPlayerVisor::Scan) + visible = x110_28_combatVisorVisible; + else if (visor == CPlayerState::EPlayerVisor::XRay) + visible = x110_30_xrayVisorVisible; + else if (visor == CPlayerState::EPlayerVisor::Thermal) + visible = x110_29_thermalVisorVisible; + + if (visible && x138_actorLights) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); + const_cast(*this).x138_actorLights->BuildAreaLightList( + mgr, *area, zeus::CAABox{x9c_renderBounds.center(), x9c_renderBounds.center()}); + const_cast(*this).x138_actorLights->BuildDynamicLightList(mgr, x9c_renderBounds); } + EnsureRendered(mgr); + } } -zeus::CAABox CScriptEffect::GetSortingBounds(const CStateManager& mgr) const -{ - if (x13c_triggerId == kInvalidUniqueId) - return x9c_renderBounds; +void CScriptEffect::Render(const CStateManager& mgr) const { + /* The following code is kept for reference, this is now performed in CElementGen + if (x138_actorLights) + x138_actorLights->ActivateLights(); + */ + if (x104_particleSystem && x104_particleSystem->GetParticleCountAll() > 0) { + g_NumParticlesRendered += x104_particleSystem->GetParticleCountAll(); + x104_particleSystem->Render(GetActorLights()); + } + + if (xf4_electric && xf4_electric->GetParticleCount() > 0) { + g_NumParticlesRendered += xf4_electric->GetParticleCount(); + xf4_electric->Render(GetActorLights()); + } +} + +void CScriptEffect::Think(float dt, CStateManager& mgr) { + if (xe4_28_transformDirty) { + if (x104_particleSystem) { + zeus::CTransform newXf = x34_transform; + newXf.origin = zeus::CVector3f::skZero; + x104_particleSystem->SetOrientation(newXf); + x104_particleSystem->SetGlobalTranslation(x34_transform.origin); + } + if (xf4_electric) { + zeus::CTransform newXf = x34_transform; + newXf.origin = zeus::CVector3f::skZero; + xf4_electric->SetOrientation(newXf); + xf4_electric->SetGlobalTranslation(x34_transform.origin); + } + + if (TCastToPtr act = mgr.ObjectById(x108_lightId)) + act->SetTransform(GetTransform()); + + xe4_28_transformDirty = false; + } + + if (x110_25_noTimerUnlessAreaOccluded) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); + CGameArea::EOcclusionState visible = + area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; + + if (visible == CGameArea::EOcclusionState::Occluded && x12c_remTime <= 0.f) + return; + } else if (x12c_remTime <= 0.f) + return; + + x12c_remTime -= dt; + + if (x110_24_enable) { + if (x104_particleSystem) { + x104_particleSystem->Update(dt); + g_NumParticlesUpdating += x104_particleSystem->GetParticleCountAll(); + } + + if (xf4_electric) { + xf4_electric->Update(dt); + g_NumParticlesUpdating += xf4_electric->GetParticleCount(); + } + + if (x108_lightId != kInvalidUniqueId) { + if (TCastToPtr light = mgr.ObjectById(x108_lightId)) { + if (x30_24_active) + light->SetLight(x104_particleSystem->GetLight()); + } + } + + if (x111_25_dieWhenSystemsDone) { + x140_destroyDelayTimer += dt; + if (x140_destroyDelayTimer > 15.f || AreBothSystemsDeleteable()) { + mgr.FreeScriptObject(GetUniqueId()); + return; + } + } + } + + if (x104_particleSystem) { + if (xb4_drawFlags.x0_blendMode != 0) + x104_particleSystem->SetModulationColor(xb4_drawFlags.x4_color); else - return static_cast(mgr.GetObjectById(x13c_triggerId))->GetTriggerBoundsWR(); + x104_particleSystem->SetModulationColor(zeus::CColor::skWhite); + } } -bool CScriptEffect::AreBothSystemsDeleteable() -{ - bool ret = true; - if (x104_particleSystem && !x104_particleSystem->IsSystemDeletable()) - ret = false; +void CScriptEffect::CalculateRenderBounds() { + std::experimental::optional particleBounds; + if (x104_particleSystem) + particleBounds = x104_particleSystem->GetBounds(); - if (xf4_electric && !xf4_electric->IsSystemDeletable()) - ret = false; + std::experimental::optional electricBounds; + if (xf4_electric) + electricBounds = xf4_electric->GetBounds(); - return ret; + if (particleBounds || electricBounds) { + zeus::CAABox renderBounds = zeus::CAABox::skInvertedBox; + if (particleBounds) { + renderBounds.accumulateBounds(particleBounds->min); + renderBounds.accumulateBounds(particleBounds->max); + } + if (electricBounds) { + renderBounds.accumulateBounds(electricBounds->min); + renderBounds.accumulateBounds(electricBounds->max); + } + x9c_renderBounds = renderBounds; + x111_26_canRender = true; + } else { + x9c_renderBounds = {GetTranslation(), GetTranslation()}; + x111_26_canRender = false; + } } + +zeus::CAABox CScriptEffect::GetSortingBounds(const CStateManager& mgr) const { + if (x13c_triggerId == kInvalidUniqueId) + return x9c_renderBounds; + else + return static_cast(mgr.GetObjectById(x13c_triggerId))->GetTriggerBoundsWR(); } + +bool CScriptEffect::AreBothSystemsDeleteable() { + bool ret = true; + if (x104_particleSystem && !x104_particleSystem->IsSystemDeletable()) + ret = false; + + if (xf4_electric && !xf4_electric->IsSystemDeletable()) + ret = false; + + return ret; +} +} // namespace urde diff --git a/Runtime/World/CScriptEffect.hpp b/Runtime/World/CScriptEffect.hpp index fdd5e3924..d1e1795b0 100644 --- a/Runtime/World/CScriptEffect.hpp +++ b/Runtime/World/CScriptEffect.hpp @@ -2,82 +2,74 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { class CElementGen; class CParticleElectric; -class CScriptEffect : public CActor -{ - static u32 g_NumParticlesUpdating; - static u32 g_NumParticlesRendered; - TLockedToken xe8_electricToken; - std::unique_ptr xf4_electric; - TLockedToken xf8_particleSystemToken; - std::unique_ptr x104_particleSystem; - TUniqueId x108_lightId = kInvalidUniqueId; - CAssetId x10c_partId; - union - { - struct - { - bool x110_24_enable : 1; - bool x110_25_noTimerUnlessAreaOccluded : 1; - bool x110_26_rebuildSystemsOnActivate : 1; - bool x110_27_useRateInverseCamDist : 1; - bool x110_28_combatVisorVisible : 1; - bool x110_29_thermalVisorVisible : 1; - bool x110_30_xrayVisorVisible : 1; - bool x110_31_anyVisorVisible : 1; - bool x111_24_useRateCamDistRange : 1; - bool x111_25_dieWhenSystemsDone : 1; - bool x111_26_canRender : 1; - }; - u32 _dummy = 0; +class CScriptEffect : public CActor { + static u32 g_NumParticlesUpdating; + static u32 g_NumParticlesRendered; + TLockedToken xe8_electricToken; + std::unique_ptr xf4_electric; + TLockedToken xf8_particleSystemToken; + std::unique_ptr x104_particleSystem; + TUniqueId x108_lightId = kInvalidUniqueId; + CAssetId x10c_partId; + union { + struct { + bool x110_24_enable : 1; + bool x110_25_noTimerUnlessAreaOccluded : 1; + bool x110_26_rebuildSystemsOnActivate : 1; + bool x110_27_useRateInverseCamDist : 1; + bool x110_28_combatVisorVisible : 1; + bool x110_29_thermalVisorVisible : 1; + bool x110_30_xrayVisorVisible : 1; + bool x110_31_anyVisorVisible : 1; + bool x111_24_useRateCamDistRange : 1; + bool x111_25_dieWhenSystemsDone : 1; + bool x111_26_canRender : 1; }; - float x114_rateInverseCamDist; - float x118_rateInverseCamDistSq; - float x11c_rateInverseCamDistRate; - float x120_rateCamDistRangeMin; - float x124_rateCamDistRangeMax; - float x128_rateCamDistRangeFarRate; - float x12c_remTime; - float x130_duration; - float x134_durationResetWhileVisible; - std::unique_ptr x138_actorLights; - TUniqueId x13c_triggerId = kInvalidUniqueId; - float x140_destroyDelayTimer = 0.f; -public: - CScriptEffect(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, const zeus::CVector3f& scale, - CAssetId partId, CAssetId elscId, bool hotInThermal, bool noTimerUnlessAreaOccluded, - bool rebuildSystemsOnActivate, bool active, bool useRateInverseCamDist, - float rateInverseCamDist, float rateInverseCamDistRate, float duration, - float durationResetWhileVisible, bool useRateCamDistRange, float rateCamDistRangeMin, - float rateCamDistRangeMax, float rateCamDistRangeFarRate, bool combatVisorVisible, - bool thermalVisorVisible, bool xrayVisorVisible, const CLightParameters& lParms, - bool dieWhenSystemsDone); + u32 _dummy = 0; + }; + float x114_rateInverseCamDist; + float x118_rateInverseCamDistSq; + float x11c_rateInverseCamDistRate; + float x120_rateCamDistRangeMin; + float x124_rateCamDistRangeMax; + float x128_rateCamDistRangeFarRate; + float x12c_remTime; + float x130_duration; + float x134_durationResetWhileVisible; + std::unique_ptr x138_actorLights; + TUniqueId x13c_triggerId = kInvalidUniqueId; + float x140_destroyDelayTimer = 0.f; - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void PreRender(CStateManager&, const zeus::CFrustum&); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - void Render(const CStateManager&) const; - void Think(float, CStateManager&); - bool CanRenderUnsorted(const CStateManager&) const { return false; } - void SetActive(bool active) - { - CActor::SetActive(active); - xe7_29_drawEnabled = true; - } - void CalculateRenderBounds(); - zeus::CAABox GetSortingBounds(const CStateManager&) const; - bool AreBothSystemsDeleteable(); - static void ResetParticleCounts() - { - g_NumParticlesUpdating = 0; - g_NumParticlesRendered = 0; - } +public: + CScriptEffect(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + const zeus::CVector3f& scale, CAssetId partId, CAssetId elscId, bool hotInThermal, + bool noTimerUnlessAreaOccluded, bool rebuildSystemsOnActivate, bool active, bool useRateInverseCamDist, + float rateInverseCamDist, float rateInverseCamDistRate, float duration, float durationResetWhileVisible, + bool useRateCamDistRange, float rateCamDistRangeMin, float rateCamDistRangeMax, + float rateCamDistRangeFarRate, bool combatVisorVisible, bool thermalVisorVisible, bool xrayVisorVisible, + const CLightParameters& lParms, bool dieWhenSystemsDone); + + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PreRender(CStateManager&, const zeus::CFrustum&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const; + void Think(float, CStateManager&); + bool CanRenderUnsorted(const CStateManager&) const { return false; } + void SetActive(bool active) { + CActor::SetActive(active); + xe7_29_drawEnabled = true; + } + void CalculateRenderBounds(); + zeus::CAABox GetSortingBounds(const CStateManager&) const; + bool AreBothSystemsDeleteable(); + static void ResetParticleCounts() { + g_NumParticlesUpdating = 0; + g_NumParticlesRendered = 0; + } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptGenerator.cpp b/Runtime/World/CScriptGenerator.cpp index 8470f9450..f33c91f0d 100644 --- a/Runtime/World/CScriptGenerator.cpp +++ b/Runtime/World/CScriptGenerator.cpp @@ -3,8 +3,7 @@ #include "CWallCrawlerSwarm.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptGenerator::CScriptGenerator(TUniqueId uid, std::string_view name, const CEntityInfo& info, u32 spawnCount, bool noReuseFollowers, const zeus::CVector3f& vec1, bool noInheritXf, bool active, @@ -15,125 +14,111 @@ CScriptGenerator::CScriptGenerator(TUniqueId uid, std::string_view name, const C , x38_25_noInheritTransform(noInheritXf) , x3c_offset(vec1) , x48_minScale(minScale) -, x4c_maxScale(maxScale) -{ -} +, x4c_maxScale(maxScale) {} void CScriptGenerator::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptGenerator::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& stateMgr) -{ - switch (msg) - { - case EScriptObjectMessage::SetToZero: - { - if (!GetActive()) - break; +void CScriptGenerator::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& stateMgr) { + switch (msg) { + case EScriptObjectMessage::SetToZero: { + if (!GetActive()) + break; - std::vector follows; - follows.reserve(x20_conns.size()); - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Zero || conn.x4_msg != EScriptObjectMessage::Follow) - continue; + std::vector follows; + follows.reserve(x20_conns.size()); + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Zero || conn.x4_msg != EScriptObjectMessage::Follow) + continue; - TUniqueId uid = stateMgr.GetIdForScript(conn.x8_objId); - if (stateMgr.GetObjectById(uid) != nullptr) - follows.push_back(uid); - } - - if (follows.empty()) - follows.push_back(sender); - - std::vector> activates; - activates.reserve(x20_conns.size()); - - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Zero) - continue; - - TUniqueId uid = stateMgr.GetIdForScript(conn.x8_objId); - if (uid == kInvalidUniqueId) - continue; - - if (conn.x4_msg == EScriptObjectMessage::Activate) - { - if (!stateMgr.GetObjectById(uid)) - continue; - activates.emplace_back(uid, conn.x8_objId); - } - - stateMgr.SendScriptMsgAlways(GetUniqueId(), uid, conn.x4_msg); - } - - if (activates.empty()) - break; - - for (u32 i = 0; i < x34_spawnCount; ++i) - { - if (activates.size() == 0 || follows.size() == 0) - break; - - u32 activatesRand = 0.99f * (stateMgr.GetActiveRandom()->Float() * activates.size()); - u32 followsRand = 0.99f * (stateMgr.GetActiveRandom()->Float() * follows.size()); - - for (u32 j = 0; j < activates.size(); ++j) - if (TCastToConstPtr(stateMgr.GetObjectById(activates[j].first))) - activatesRand = j; - - std::pair idPair = activates[activatesRand]; - CEntity* activate = stateMgr.ObjectById(idPair.first); - CEntity* follow = stateMgr.ObjectById(follows[followsRand]); - - if (!activate || !follow) - break; - - bool oldGeneratingObject = stateMgr.GetIsGeneratingObject(); - stateMgr.SetIsGeneratingObject(true); - std::pair objId = stateMgr.GenerateObject(idPair.second); - stateMgr.SetIsGeneratingObject(oldGeneratingObject); - - if (objId.second != kInvalidUniqueId) - { - if (CEntity* genObj = stateMgr.ObjectById(objId.second)) - { - TCastToPtr activateActor(genObj); - TCastToPtr followActor(follow); - TCastToPtr wallCrawlerSwarm(follow); - - if (activateActor && wallCrawlerSwarm) - { - if (!x38_25_noInheritTransform) - activateActor->SetTransform(wallCrawlerSwarm->GetTransform()); - activateActor->SetTranslation(wallCrawlerSwarm->GetLastKilledOffset() + x3c_offset); - } - else if (activateActor && followActor) - { - if (!x38_25_noInheritTransform) - activateActor->SetTransform(followActor->GetTransform()); - activateActor->SetTranslation(followActor->GetTranslation() + x3c_offset); - } - - float rnd = stateMgr.GetActiveRandom()->Range(x48_minScale, x4c_maxScale); - CModelData* mData = activateActor->ModelData(); - if (mData && !mData->IsNull()) - mData->SetScale(rnd * mData->GetScale()); - - stateMgr.SendScriptMsg(genObj, GetUniqueId(), EScriptObjectMessage::Activate); - } - } - - activates.erase(std::find(activates.begin(), activates.end(), idPair)); - if (x38_24_noReuseFollowers) - follows.erase(std::find(follows.begin(), follows.end(), follows[followsRand])); - } - break; - } - default: - break; + TUniqueId uid = stateMgr.GetIdForScript(conn.x8_objId); + if (stateMgr.GetObjectById(uid) != nullptr) + follows.push_back(uid); } - CEntity::AcceptScriptMsg(msg, sender, stateMgr); + if (follows.empty()) + follows.push_back(sender); + + std::vector> activates; + activates.reserve(x20_conns.size()); + + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Zero) + continue; + + TUniqueId uid = stateMgr.GetIdForScript(conn.x8_objId); + if (uid == kInvalidUniqueId) + continue; + + if (conn.x4_msg == EScriptObjectMessage::Activate) { + if (!stateMgr.GetObjectById(uid)) + continue; + activates.emplace_back(uid, conn.x8_objId); + } + + stateMgr.SendScriptMsgAlways(GetUniqueId(), uid, conn.x4_msg); + } + + if (activates.empty()) + break; + + for (u32 i = 0; i < x34_spawnCount; ++i) { + if (activates.size() == 0 || follows.size() == 0) + break; + + u32 activatesRand = 0.99f * (stateMgr.GetActiveRandom()->Float() * activates.size()); + u32 followsRand = 0.99f * (stateMgr.GetActiveRandom()->Float() * follows.size()); + + for (u32 j = 0; j < activates.size(); ++j) + if (TCastToConstPtr(stateMgr.GetObjectById(activates[j].first))) + activatesRand = j; + + std::pair idPair = activates[activatesRand]; + CEntity* activate = stateMgr.ObjectById(idPair.first); + CEntity* follow = stateMgr.ObjectById(follows[followsRand]); + + if (!activate || !follow) + break; + + bool oldGeneratingObject = stateMgr.GetIsGeneratingObject(); + stateMgr.SetIsGeneratingObject(true); + std::pair objId = stateMgr.GenerateObject(idPair.second); + stateMgr.SetIsGeneratingObject(oldGeneratingObject); + + if (objId.second != kInvalidUniqueId) { + if (CEntity* genObj = stateMgr.ObjectById(objId.second)) { + TCastToPtr activateActor(genObj); + TCastToPtr followActor(follow); + TCastToPtr wallCrawlerSwarm(follow); + + if (activateActor && wallCrawlerSwarm) { + if (!x38_25_noInheritTransform) + activateActor->SetTransform(wallCrawlerSwarm->GetTransform()); + activateActor->SetTranslation(wallCrawlerSwarm->GetLastKilledOffset() + x3c_offset); + } else if (activateActor && followActor) { + if (!x38_25_noInheritTransform) + activateActor->SetTransform(followActor->GetTransform()); + activateActor->SetTranslation(followActor->GetTranslation() + x3c_offset); + } + + float rnd = stateMgr.GetActiveRandom()->Range(x48_minScale, x4c_maxScale); + CModelData* mData = activateActor->ModelData(); + if (mData && !mData->IsNull()) + mData->SetScale(rnd * mData->GetScale()); + + stateMgr.SendScriptMsg(genObj, GetUniqueId(), EScriptObjectMessage::Activate); + } + } + + activates.erase(std::find(activates.begin(), activates.end(), idPair)); + if (x38_24_noReuseFollowers) + follows.erase(std::find(follows.begin(), follows.end(), follows[followsRand])); + } + break; + } + default: + break; + } + + CEntity::AcceptScriptMsg(msg, sender, stateMgr); } } // namespace urde diff --git a/Runtime/World/CScriptGenerator.hpp b/Runtime/World/CScriptGenerator.hpp index 38fb02b28..b2afade9d 100644 --- a/Runtime/World/CScriptGenerator.hpp +++ b/Runtime/World/CScriptGenerator.hpp @@ -3,31 +3,26 @@ #include "CEntity.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { -class CScriptGenerator : public CEntity -{ - u32 x34_spawnCount; - union { - struct - { - bool x38_24_noReuseFollowers : 1; - bool x38_25_noInheritTransform : 1; - }; - u8 dummy1 = 0; +class CScriptGenerator : public CEntity { + u32 x34_spawnCount; + union { + struct { + bool x38_24_noReuseFollowers : 1; + bool x38_25_noInheritTransform : 1; }; - zeus::CVector3f x3c_offset; - float x48_minScale; - float x4c_maxScale; + u8 dummy1 = 0; + }; + zeus::CVector3f x3c_offset; + float x48_minScale; + float x4c_maxScale; public: - CScriptGenerator(TUniqueId uid, std::string_view name, const CEntityInfo& info, u32 spawnCount, - bool noReuseFollowers, const zeus::CVector3f& vec1, bool noInheritXf, bool active, - float minScale, float maxScale); + CScriptGenerator(TUniqueId uid, std::string_view name, const CEntityInfo& info, u32 spawnCount, bool noReuseFollowers, + const zeus::CVector3f& vec1, bool noInheritXf, bool active, float minScale, float maxScale); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptGrapplePoint.cpp b/Runtime/World/CScriptGrapplePoint.cpp index ee8dc281e..84f0b31b9 100644 --- a/Runtime/World/CScriptGrapplePoint.cpp +++ b/Runtime/World/CScriptGrapplePoint.cpp @@ -4,65 +4,48 @@ #include "CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptGrapplePoint::CScriptGrapplePoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform &transform, bool active, - const CGrappleParameters ¶ms) + const zeus::CTransform& transform, bool active, + const CGrappleParameters& params) : CActor(uid, active, name, info, transform, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Orbit), - CActorParameters::None(), - kInvalidUniqueId), - xe8_touchBounds(x34_transform.origin - 0.5f, x34_transform.origin + 0.5f), - x100_parameters(params) -{ -} + CActorParameters::None(), kInvalidUniqueId) +, xe8_touchBounds(x34_transform.origin - 0.5f, x34_transform.origin + 0.5f) +, x100_parameters(params) {} -void CScriptGrapplePoint::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptGrapplePoint::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptGrapplePoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Activate: - if (!GetActive()) - { - AddMaterial(EMaterialTypes::Orbit, mgr); - SetActive(true); - } - break; - case EScriptObjectMessage::Deactivate: - if (GetActive()) - { - RemoveMaterial(EMaterialTypes::Orbit, mgr); - SetActive(false); - } - break; - default: - break; +void CScriptGrapplePoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Activate: + if (!GetActive()) { + AddMaterial(EMaterialTypes::Orbit, mgr); + SetActive(true); } + break; + case EScriptObjectMessage::Deactivate: + if (GetActive()) { + RemoveMaterial(EMaterialTypes::Orbit, mgr); + SetActive(false); + } + break; + default: + break; + } } -void CScriptGrapplePoint::Think(float, CStateManager&) -{ - // Empty +void CScriptGrapplePoint::Think(float, CStateManager&) { + // Empty } -void CScriptGrapplePoint::Render(const CStateManager&) const -{ - // Empty +void CScriptGrapplePoint::Render(const CStateManager&) const { + // Empty } -std::experimental::optional CScriptGrapplePoint::GetTouchBounds() const -{ - return {xe8_touchBounds}; +std::experimental::optional CScriptGrapplePoint::GetTouchBounds() const { return {xe8_touchBounds}; } + +void CScriptGrapplePoint::AddToRenderer(const zeus::CFrustum&, const CStateManager& mgr) const { + CActor::EnsureRendered(mgr); } -void CScriptGrapplePoint::AddToRenderer(const zeus::CFrustum&, const CStateManager& mgr) const -{ - CActor::EnsureRendered(mgr); -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptGrapplePoint.hpp b/Runtime/World/CScriptGrapplePoint.hpp index 0864fc607..f74707422 100644 --- a/Runtime/World/CScriptGrapplePoint.hpp +++ b/Runtime/World/CScriptGrapplePoint.hpp @@ -3,23 +3,21 @@ #include "CActor.hpp" #include "CGrappleParameters.hpp" -namespace urde -{ -class CScriptGrapplePoint : public CActor -{ - zeus::CAABox xe8_touchBounds; - CGrappleParameters x100_parameters; +namespace urde { +class CScriptGrapplePoint : public CActor { + zeus::CAABox xe8_touchBounds; + CGrappleParameters x100_parameters; + public: - CScriptGrapplePoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& transform, bool active, const CGrappleParameters& params); + CScriptGrapplePoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& transform, + bool active, const CGrappleParameters& params); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - void Render(const CStateManager&) const; - std::experimental::optional GetTouchBounds() const; - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - const CGrappleParameters& GetGrappleParameters() const { return x100_parameters; } + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void Render(const CStateManager&) const; + std::experimental::optional GetTouchBounds() const; + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + const CGrappleParameters& GetGrappleParameters() const { return x100_parameters; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptGunTurret.cpp b/Runtime/World/CScriptGunTurret.cpp index a37fc5fd3..066363c9e 100644 --- a/Runtime/World/CScriptGunTurret.cpp +++ b/Runtime/World/CScriptGunTurret.cpp @@ -11,135 +11,104 @@ #include "Character/CPASAnimParmData.hpp" #include "Graphics/CBooRenderer.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -static const CMaterialList skGunMaterialList = { EMaterialTypes::Solid, EMaterialTypes::Character, - EMaterialTypes::Orbit, EMaterialTypes::Target }; -static const CMaterialList skTurretMaterialList = { EMaterialTypes::Character }; +static const CMaterialList skGunMaterialList = {EMaterialTypes::Solid, EMaterialTypes::Character, EMaterialTypes::Orbit, + EMaterialTypes::Target}; +static const CMaterialList skTurretMaterialList = {EMaterialTypes::Character}; CScriptGunTurretData::CScriptGunTurretData(CInputStream& in, s32 propCount) -: x0_(in.readFloatBig()), - x4_(in.readFloatBig()), - x8_(in.readFloatBig()), - xc_(in.readFloatBig()), - x10_(in.readFloatBig()), - x14_(in.readFloatBig()), - x1c_(zeus::degToRad(in.readFloatBig())), - x20_(zeus::degToRad(in.readFloatBig())), - x24_(zeus::degToRad(in.readFloatBig())), - x28_(zeus::degToRad(in.readFloatBig())), - x2c_(in.readFloatBig()), - x30_(in.readFloatBig()), - x34_(in.readFloatBig()), - x38_(in.readFloatBig()), - x3c_(propCount >= 48 ? in.readBool() : false), - x40_projectileRes(in), - x44_projectileDamage(in), - x60_(in.readUint32Big()), - x64_(in.readUint32Big()), - x68_(in.readUint32Big()), - x6c_(in.readUint32Big()), - x70_(in.readUint32Big()), - x74_(in.readUint32Big()), - x78_(propCount >= 44 ? in.readUint32Big() : -1), - x7c_(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)), - x7e_(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)), - x80_unfreezeSound(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)), - x82_(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)), - x84_(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)), - x86_(propCount >= 45 ? CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF) : -1), - x88_(in.readUint32Big()), - x8c_(in.readUint32Big()), - x90_(in.readUint32Big()), - x94_(in.readUint32Big()), - x98_(in.readUint32Big()), - x9c_(propCount >= 47 ? in.readFloatBig() : 3.f), - xa0_(propCount >= 46 ? in.readBool() : false) -{ -} +: x0_(in.readFloatBig()) +, x4_(in.readFloatBig()) +, x8_(in.readFloatBig()) +, xc_(in.readFloatBig()) +, x10_(in.readFloatBig()) +, x14_(in.readFloatBig()) +, x1c_(zeus::degToRad(in.readFloatBig())) +, x20_(zeus::degToRad(in.readFloatBig())) +, x24_(zeus::degToRad(in.readFloatBig())) +, x28_(zeus::degToRad(in.readFloatBig())) +, x2c_(in.readFloatBig()) +, x30_(in.readFloatBig()) +, x34_(in.readFloatBig()) +, x38_(in.readFloatBig()) +, x3c_(propCount >= 48 ? in.readBool() : false) +, x40_projectileRes(in) +, x44_projectileDamage(in) +, x60_(in.readUint32Big()) +, x64_(in.readUint32Big()) +, x68_(in.readUint32Big()) +, x6c_(in.readUint32Big()) +, x70_(in.readUint32Big()) +, x74_(in.readUint32Big()) +, x78_(propCount >= 44 ? in.readUint32Big() : -1) +, x7c_(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)) +, x7e_(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)) +, x80_unfreezeSound(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)) +, x82_(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)) +, x84_(CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF)) +, x86_(propCount >= 45 ? CSfxManager::TranslateSFXID(in.readUint32Big() & 0xFFFF) : -1) +, x88_(in.readUint32Big()) +, x8c_(in.readUint32Big()) +, x90_(in.readUint32Big()) +, x94_(in.readUint32Big()) +, x98_(in.readUint32Big()) +, x9c_(propCount >= 47 ? in.readFloatBig() : 3.f) +, xa0_(propCount >= 46 ? in.readBool() : false) {} -const SBurst CScriptGunTurret::skBurst2InfoTemplate[] = -{ - {3, {1, 2, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {3, {7, 6, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {4, {3, 5, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {60, {16, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {30, {4, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, +const SBurst CScriptGunTurret::skBurst2InfoTemplate[] = { + {3, {1, 2, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {3, {7, 6, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {4, {3, 5, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {60, {16, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {30, {4, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}; + +const SBurst CScriptGunTurret::skBurst3InfoTemplate[] = { + {30, {4, 5, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {30, {2, 3, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {30, {3, 4, 5, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {5, {16, 1, 2, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {5, {8, 7, 6, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}; + +const SBurst CScriptGunTurret::skBurst4InfoTemplate[] = { + {5, {16, 1, 2, 3, 0, 0, 0, 0}, 0.150000, 0.050000}, {5, {9, 8, 7, 6, 0, 0, 0, 0}, 0.150000, 0.050000}, + {15, {2, 3, 4, 5, 0, 0, 0, 0}, 0.150000, 0.050000}, {15, {5, 4, 3, 2, 0, 0, 0, 0}, 0.150000, 0.050000}, + {15, {10, 11, 4, 13, 0, 0, 0, 0}, 0.150000, 0.050000}, {15, {14, 13, 4, 11, 0, 0, 0, 0}, 0.150000, 0.050000}, + {30, {2, 4, 4, 6, 0, 0, 0, 0}, 0.150000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}; + +const SBurst CScriptGunTurret::skOOVBurst2InfoTemplate[] = { + {20, {16, 15, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {20, {8, 9, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {20, {13, 11, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {20, {2, 6, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {20, {3, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}; + +const SBurst CScriptGunTurret::skOOVBurst3InfoTemplate[] = { + {10, {14, 4, 10, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {10, {15, 13, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {10, {9, 11, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {35, {15, 13, 11, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {35, {9, 11, 13, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, +}; + +const SBurst CScriptGunTurret::skOOVBurst4InfoTemplate[] = { + {10, {14, 13, 4, 11, 0, 0, 0, 0}, 0.150000, 0.050000}, {30, {1, 15, 13, 11, 0, 0, 0, 0}, 0.150000, 0.050000}, + {20, {16, 15, 14, 13, 0, 0, 0, 0}, 0.150000, 0.050000}, {10, {8, 9, 11, 4, 0, 0, 0, 0}, 0.150000, 0.050000}, + {10, {1, 15, 13, 4, 0, 0, 0, 0}, 0.150000, 0.050000}, {20, {8, 9, 10, 11, 0, 0, 0, 0}, 0.150000, 0.050000}, {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, }; -const SBurst CScriptGunTurret::skBurst3InfoTemplate[] = -{ - {30, {4, 5, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {30, {2, 3, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {30, {3, 4, 5, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {5, {16, 1, 2, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {5, {8, 7, 6, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, -}; - -const SBurst CScriptGunTurret::skBurst4InfoTemplate[] = -{ - {5, {16, 1, 2, 3, 0, 0, 0, 0}, 0.150000, 0.050000}, - {5, {9, 8, 7, 6, 0, 0, 0, 0}, 0.150000, 0.050000}, - {15, {2, 3, 4, 5, 0, 0, 0, 0}, 0.150000, 0.050000}, - {15, {5, 4, 3, 2, 0, 0, 0, 0}, 0.150000, 0.050000}, - {15, {10, 11, 4, 13, 0, 0, 0, 0}, 0.150000, 0.050000}, - {15, {14, 13, 4, 11, 0, 0, 0, 0}, 0.150000, 0.050000}, - {30, {2, 4, 4, 6, 0, 0, 0, 0}, 0.150000, 0.050000}, - {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, -}; - -const SBurst CScriptGunTurret::skOOVBurst2InfoTemplate[] = -{ - {20, {16, 15, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {20, {8, 9, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {20, {13, 11, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {20, {2, 6, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {20, {3, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, -}; - -const SBurst CScriptGunTurret::skOOVBurst3InfoTemplate[] = -{ - {10, {14, 4, 10, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {10, {15, 13, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {10, {9, 11, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {35, {15, 13, 11, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {35, {9, 11, 13, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, - {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, -}; - -const SBurst CScriptGunTurret::skOOVBurst4InfoTemplate[] = -{ - {10, {14, 13, 4, 11, 0, 0, 0, 0}, 0.150000, 0.050000}, - {30, {1, 15, 13, 11, 0, 0, 0, 0}, 0.150000, 0.050000}, - {20, {16, 15, 14, 13, 0, 0, 0, 0}, 0.150000, 0.050000}, - {10, {8, 9, 11, 4, 0, 0, 0, 0}, 0.150000, 0.050000}, - {10, {1, 15, 13, 4, 0, 0, 0, 0}, 0.150000, 0.050000}, - {20, {8, 9, 10, 11, 0, 0, 0, 0}, 0.150000, 0.050000}, - {0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000}, -}; - -const SBurst* CScriptGunTurret::skBursts[] = -{ - skBurst2InfoTemplate, - skBurst3InfoTemplate, - skBurst4InfoTemplate, - skOOVBurst2InfoTemplate, - skOOVBurst3InfoTemplate, - skOOVBurst4InfoTemplate, - nullptr -}; +const SBurst* CScriptGunTurret::skBursts[] = {skBurst2InfoTemplate, + skBurst3InfoTemplate, + skBurst4InfoTemplate, + skOOVBurst2InfoTemplate, + skOOVBurst3InfoTemplate, + skOOVBurst4InfoTemplate, + nullptr}; CScriptGunTurret::CScriptGunTurret(TUniqueId uid, std::string_view name, ETurretComponent comp, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& aabb, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, const CActorParameters& aParms, const CScriptGunTurretData& turretData) : CPhysicsActor(uid, true, name, info, xf, std::move(mData), - comp == ETurretComponent::Base ? skTurretMaterialList : skGunMaterialList, - aabb, SMoverData(1000.f), aParms, 0.3f, 0.1f) + comp == ETurretComponent::Base ? skTurretMaterialList : skGunMaterialList, aabb, SMoverData(1000.f), + aParms, 0.3f, 0.1f) , x258_type(comp) , x264_healthInfo(hInfo) , x26c_damageVuln(dVuln) @@ -151,986 +120,809 @@ CScriptGunTurret::CScriptGunTurret(TUniqueId uid, std::string_view name, ETurret , x428_(g_SimplePool->GetObj({SBIG('PART'), turretData.x68_})) , x434_(g_SimplePool->GetObj({SBIG('PART'), turretData.x6c_})) , x440_(g_SimplePool->GetObj({SBIG('PART'), turretData.x70_})) -, x44c_(g_SimplePool->GetObj({SBIG('PART'), turretData.x74_})) -{ - if (turretData.x78_.IsValid()) - x458_ = g_SimplePool->GetObj({SBIG('PART'), turretData.x78_}); - x468_.reset(new CElementGen(x410_)); - x470_.reset(new CElementGen(x41c_)); - x478_.reset(new CElementGen(x428_)); - x480_.reset(new CElementGen(x434_)); - x488_.reset(new CElementGen(x440_)); - x490_.reset(new CElementGen(x44c_)); - x4fc_ = xf.origin; - x514_ = xf.frontVector(); - x544_ = xf.frontVector(); - x550_ = xf.rightVector(); - x560_24_ = false; - x560_25_ = false; - x560_26_ = false; - x560_27_ = false; - x560_28_ = false; - x560_29_ = false; - x560_30_ = true; - x560_31_ = false; +, x44c_(g_SimplePool->GetObj({SBIG('PART'), turretData.x74_})) { + if (turretData.x78_.IsValid()) + x458_ = g_SimplePool->GetObj({SBIG('PART'), turretData.x78_}); + x468_.reset(new CElementGen(x410_)); + x470_.reset(new CElementGen(x41c_)); + x478_.reset(new CElementGen(x428_)); + x480_.reset(new CElementGen(x434_)); + x488_.reset(new CElementGen(x440_)); + x490_.reset(new CElementGen(x44c_)); + x4fc_ = xf.origin; + x514_ = xf.frontVector(); + x544_ = xf.frontVector(); + x550_ = xf.rightVector(); + x560_24_ = false; + x560_25_ = false; + x560_26_ = false; + x560_27_ = false; + x560_28_ = false; + x560_29_ = false; + x560_30_ = true; + x560_31_ = false; - if (comp == ETurretComponent::Base && HasModelData() && GetModelData()->HasAnimData()) - ModelData()->EnableLooping(true); + if (comp == ETurretComponent::Base && HasModelData() && GetModelData()->HasAnimData()) + ModelData()->EnableLooping(true); - const_cast*>(&x37c_projectileInfo.Token())->Lock(); + const_cast*>(&x37c_projectileInfo.Token())->Lock(); } -void CScriptGunTurret::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptGunTurret::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptGunTurret::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); +void CScriptGunTurret::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); - switch(msg) - { - case EScriptObjectMessage::Activate: - if (x49c_collisionManager) - x49c_collisionManager->SetActive(mgr, true); - break; - case EScriptObjectMessage::Deactivate: - if (x49c_collisionManager) - x49c_collisionManager->SetActive(mgr, false); - break; - case EScriptObjectMessage::Registered: - if (x258_type == ETurretComponent::Gun) - { - if (x478_->SystemHasLight()) - { - x498_lightId = mgr.AllocateUniqueId(); - mgr.AddObject(new CGameLight(x498_lightId, GetAreaIdAlways(), GetActive(), - std::string("ParticleLight_") + GetName().data(), GetTransform(), - GetUniqueId(), x478_->GetLight(), 0, 1, 0.f)); - } - SetupCollisionManager(mgr); - } - else if (x258_type == ETurretComponent::Base) - { - zeus::CVector3f scale = GetModelData()->GetScale(); - if (x2d4_data.x88_.IsValid()) - { - CModelData mData(CStaticRes(x2d4_data.x88_, scale)); - x4a4_.emplace(std::move(mData)); - x4f4_ = x4a4_->GetBounds().max.z() - x4a4_->GetBounds().min.z(); - } - sub80219b18(5, mgr); - } - break; - case EScriptObjectMessage::Deleted: - { - if (x258_type == ETurretComponent::Gun) - { - if (x498_lightId != kInvalidUniqueId) - mgr.FreeScriptObject(x498_lightId); - } - if (x50c_) - CSfxManager::RemoveEmitter(x50c_); - - if (x49c_collisionManager) - x49c_collisionManager->Destroy(mgr); - break; + switch (msg) { + case EScriptObjectMessage::Activate: + if (x49c_collisionManager) + x49c_collisionManager->SetActive(mgr, true); + break; + case EScriptObjectMessage::Deactivate: + if (x49c_collisionManager) + x49c_collisionManager->SetActive(mgr, false); + break; + case EScriptObjectMessage::Registered: + if (x258_type == ETurretComponent::Gun) { + if (x478_->SystemHasLight()) { + x498_lightId = mgr.AllocateUniqueId(); + mgr.AddObject(new CGameLight(x498_lightId, GetAreaIdAlways(), GetActive(), + std::string("ParticleLight_") + GetName().data(), GetTransform(), GetUniqueId(), + x478_->GetLight(), 0, 1, 0.f)); + } + SetupCollisionManager(mgr); + } else if (x258_type == ETurretComponent::Base) { + zeus::CVector3f scale = GetModelData()->GetScale(); + if (x2d4_data.x88_.IsValid()) { + CModelData mData(CStaticRes(x2d4_data.x88_, scale)); + x4a4_.emplace(std::move(mData)); + x4f4_ = x4a4_->GetBounds().max.z() - x4a4_->GetBounds().min.z(); + } + sub80219b18(5, mgr); } - case EScriptObjectMessage::Start: - if (x258_type == ETurretComponent::Base && x520_ == 5) - x560_29_ = true; - break; - case EScriptObjectMessage::Stop: - if (x258_type == ETurretComponent::Base && x520_ != 1 && x520_ != 2 && x520_ != 3) - sub80219b18((!x560_28_ ? 3 : 4), mgr); - break; - case EScriptObjectMessage::Action: - { - if (x258_type == ETurretComponent::Gun) - sub80217408(mgr); - else if (x258_type == ETurretComponent::Base) - sub802172b8(mgr); - break; + break; + case EScriptObjectMessage::Deleted: { + if (x258_type == ETurretComponent::Gun) { + if (x498_lightId != kInvalidUniqueId) + mgr.FreeScriptObject(x498_lightId); } - case EScriptObjectMessage::SetToMax: - { - x560_25_ = false; - SetMuted(false); - break; - } - case EScriptObjectMessage::SetToZero: - { - x560_25_ = true; - SetMuted(true); - break; - } - case EScriptObjectMessage::InitializedInArea: - { - if (x258_type == ETurretComponent::Base) - { - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) - continue; - - if (TCastToConstPtr gun = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) - { - x25c_gunId = mgr.GetIdForScript(conn.x8_objId); - x260_ = gun->GetHealthInfo(mgr)->GetHP(); - return; - } - } - } - break; - } - case EScriptObjectMessage::Damage: - { - if (x258_type == ETurretComponent::Gun && GetHealthInfo(mgr)->GetHP() > 0.f) - { - if (TCastToConstPtr proj = mgr.GetObjectById(uid)) - { - if ((proj->GetAttribField() & EProjectileAttrib::Wave) == EProjectileAttrib::Wave) - { - x520_ = 12; - RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); - mgr.GetPlayer().SetOrbitRequestForTarget(GetUniqueId(), - CPlayer::EPlayerOrbitRequest::ActivateOrbitSource, mgr); - x53c_ = 0.f; - } - } - } - break; - } - default: - break; - } -} - -void CScriptGunTurret::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; - - if (x258_type == ETurretComponent::Base) - { - if (!x560_25_) - { - sub80219a00(dt, mgr); - sub802189c8(); - sub80217f5c(dt, mgr); - zeus::CVector3f vec = sub80217e34(dt); - SAdvancementDeltas advancementDeltas = UpdateAnimation(dt, mgr, true); - SetTranslation(vec + advancementDeltas.x0_posDelta + GetTranslation()); - RotateToOR(advancementDeltas.xc_rotDelta, dt); - } else - Stop(); - - sub80216288(dt); - } - else if (x258_type == ETurretComponent::Gun) - { - UpdateGunParticles(dt, mgr); - SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); - MoveToOR(deltas.x0_posDelta, dt); - RotateToOR(deltas.xc_rotDelta, dt); - UpdateGunCollisionManager(dt, mgr); - GetUnFreezeSoundId(dt, mgr); - } -} - -void CScriptGunTurret::Touch(CActor& act, CStateManager& mgr) -{ - if (x258_type != ETurretComponent::Gun) - return; - if (TCastToPtr proj = act) - { - const CPlayer& player = mgr.GetPlayer(); - if (proj->GetOwnerId() == player.GetUniqueId()) - { - const CDamageVulnerability* dVuln = GetDamageVulnerability(); - if (!x560_24_ && x520_ != 12 && (proj->GetAttribField() & EProjectileAttrib::Ice) == EProjectileAttrib::Ice - && dVuln->WeaponHits(CWeaponMode::Ice(), false)) - { - x560_24_ = true; - SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); - x53c_ = mgr.GetActiveRandom()->Float() * x2d4_data.x38_ + x2d4_data.x34_; - SetMuted(true); - } - SendScriptMsgs(EScriptObjectState::Damage, mgr, EScriptObjectMessage::None); - } - } -} - -std::experimental::optional CScriptGunTurret::GetTouchBounds() const -{ - if (GetActive() && GetMaterialList().HasMaterial(EMaterialTypes::Solid)) - return {GetBoundingBox()}; - return {}; -} - -zeus::CVector3f CScriptGunTurret::GetOrbitPosition(const CStateManager& mgr) const -{ - return GetAimPosition(mgr, 0.f); -} - -zeus::CVector3f CScriptGunTurret::GetAimPosition(const CStateManager &, float) const -{ - if (x258_type == ETurretComponent::Base) - return GetTranslation() + x34_transform.rotate(GetLocatorTransform("Gun_SDK"sv).origin); - - return GetTranslation(); -} - -void CScriptGunTurret::SetupCollisionManager(CStateManager& mgr) -{ - std::vector jointDescs; - jointDescs.reserve(2); - const CAnimData* animData = GetModelData()->GetAnimationData(); - x508_gunSDKSeg = animData->GetLocatorSegId("Gun_SDK"sv); - CSegId blastLCTR = animData->GetLocatorSegId("Blast_LCTR"sv); - jointDescs.push_back(CJointCollisionDescription::SphereSubdivideCollision(x508_gunSDKSeg, blastLCTR, 0.6f, 1.f, - CJointCollisionDescription::EOrientationType::One, - "Gun_SDK"sv, 1000.f)); - jointDescs.push_back(CJointCollisionDescription::SphereCollision(blastLCTR, 0.3f, "Blast_LCTR"sv, 1000.f)); - - x49c_collisionManager.reset(new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), jointDescs, true)); -} - -void CScriptGunTurret::sub80219b18(s32 w1, CStateManager& mgr) -{ - - if (w1 < 0 || w1 > 12) - return; - - if (x520_ != -1) - sub8021998c(2, mgr, 0.f); - - - x520_ = w1; - x524_ = 0.f; - sub8021998c(0, mgr, 0.f); -} - -void CScriptGunTurret::sub80217408(CStateManager&) -{ - -} - -void CScriptGunTurret::sub802172b8(CStateManager& mgr) -{ - auto pair = ModelData()->AnimationData()->GetCharacterInfo().GetPASDatabase().FindBestAnimation(CPASAnimParmData(23), - *mgr.GetActiveRandom(), - -1); - if (pair.first > 0.f) - ModelData()->AnimationData()->AddAdditiveAnimation(pair.second, 1.f, false, true); -} - -void CScriptGunTurret::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) -{ - CActor::AddToRenderer(frustum, mgr); - - if (x258_type != ETurretComponent::Gun) - return; - - if (!x560_25_) - { - if (x520_ == 6 || (x520_ >= 9 && x520_ <= 12)) - { - g_Renderer->AddParticleGen(*x478_); - if (x520_ == 10 || x520_ == 12) - g_Renderer->AddParticleGen(*x488_); - } - else if (x520_ == 5) - { - g_Renderer->AddParticleGen(*x468_); - } - else if (x520_ >= 1) - { - g_Renderer->AddParticleGen(*x470_); - } - } - else - { - g_Renderer->AddParticleGen(*x480_); - } -} - -void CScriptGunTurret::Render(const CStateManager& mgr) const -{ - CPhysicsActor::Render(mgr); + if (x50c_) + CSfxManager::RemoveEmitter(x50c_); + if (x49c_collisionManager) + x49c_collisionManager->Destroy(mgr); + break; + } + case EScriptObjectMessage::Start: + if (x258_type == ETurretComponent::Base && x520_ == 5) + x560_29_ = true; + break; + case EScriptObjectMessage::Stop: + if (x258_type == ETurretComponent::Base && x520_ != 1 && x520_ != 2 && x520_ != 3) + sub80219b18((!x560_28_ ? 3 : 4), mgr); + break; + case EScriptObjectMessage::Action: { if (x258_type == ETurretComponent::Gun) - { - if (!x560_25_) - { - if (x520_ == 6 || (x520_ >= 9 && x520_ <= 12)) - { - x478_->Render(x90_actorLights.get()); - if (x520_ == 10) - x488_->Render(x90_actorLights.get()); - } - else if (x520_ == 5) - x468_->Render(x90_actorLights.get()); - else if (x520_ >= 1) - x470_->Render(x90_actorLights.get()); - } - } + sub80217408(mgr); else if (x258_type == ETurretComponent::Base) - { - if (x4a4_ && x4f8_ > 0.f) - { - zeus::CTransform xf = GetTransform(); - xf.origin = x4fc_ + (x4f4_ * 0.5f * zeus::CVector3f::skDown); - CModelFlags flags; - flags.x2_flags = 3; - flags.x1_matSetIdx = 0; - flags.x4_color = zeus::CColor::skWhite; - x4a4_->Render(mgr, xf, x90_actorLights.get(), flags); - } + sub802172b8(mgr); + break; + } + case EScriptObjectMessage::SetToMax: { + x560_25_ = false; + SetMuted(false); + break; + } + case EScriptObjectMessage::SetToZero: { + x560_25_ = true; + SetMuted(true); + break; + } + case EScriptObjectMessage::InitializedInArea: { + if (x258_type == ETurretComponent::Base) { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) + continue; + if (TCastToConstPtr gun = mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))) { + x25c_gunId = mgr.GetIdForScript(conn.x8_objId); + x260_ = gun->GetHealthInfo(mgr)->GetHP(); + return; + } + } } + break; + } + case EScriptObjectMessage::Damage: { + if (x258_type == ETurretComponent::Gun && GetHealthInfo(mgr)->GetHP() > 0.f) { + if (TCastToConstPtr proj = mgr.GetObjectById(uid)) { + if ((proj->GetAttribField() & EProjectileAttrib::Wave) == EProjectileAttrib::Wave) { + x520_ = 12; + RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); + mgr.GetPlayer().SetOrbitRequestForTarget(GetUniqueId(), CPlayer::EPlayerOrbitRequest::ActivateOrbitSource, + mgr); + x53c_ = 0.f; + } + } + } + break; + } + default: + break; + } } -void CScriptGunTurret::UpdateGunCollisionManager(float dt, CStateManager& mgr) -{ - if (TCastToPtr colAct = mgr.ObjectById(x4a0_)) - colAct->SetActive(mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed); +void CScriptGunTurret::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; - x49c_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); + if (x258_type == ETurretComponent::Base) { + if (!x560_25_) { + sub80219a00(dt, mgr); + sub802189c8(); + sub80217f5c(dt, mgr); + zeus::CVector3f vec = sub80217e34(dt); + SAdvancementDeltas advancementDeltas = UpdateAnimation(dt, mgr, true); + SetTranslation(vec + advancementDeltas.x0_posDelta + GetTranslation()); + RotateToOR(advancementDeltas.xc_rotDelta, dt); + } else + Stop(); + + sub80216288(dt); + } else if (x258_type == ETurretComponent::Gun) { + UpdateGunParticles(dt, mgr); + SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); + MoveToOR(deltas.x0_posDelta, dt); + RotateToOR(deltas.xc_rotDelta, dt); + UpdateGunCollisionManager(dt, mgr); + GetUnFreezeSoundId(dt, mgr); + } } -void CScriptGunTurret::GetUnFreezeSoundId(float dt, CStateManager& mgr) -{ - if (x560_25_) - { - if (x53c_ <= 0.f) - { - SendScriptMsgs(EScriptObjectState::UnFrozen, mgr, EScriptObjectMessage::None); - CSfxManager::AddEmitter(x2d4_data.x80_unfreezeSound, GetTranslation(), zeus::CVector3f::skUp, false, false, - 0x7f, GetAreaIdAlways()); - SetMuted(false); - } - else if (x2d4_data.x3c_) - x53c_ -= dt; +void CScriptGunTurret::Touch(CActor& act, CStateManager& mgr) { + if (x258_type != ETurretComponent::Gun) + return; + if (TCastToPtr proj = act) { + const CPlayer& player = mgr.GetPlayer(); + if (proj->GetOwnerId() == player.GetUniqueId()) { + const CDamageVulnerability* dVuln = GetDamageVulnerability(); + if (!x560_24_ && x520_ != 12 && (proj->GetAttribField() & EProjectileAttrib::Ice) == EProjectileAttrib::Ice && + dVuln->WeaponHits(CWeaponMode::Ice(), false)) { + x560_24_ = true; + SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + x53c_ = mgr.GetActiveRandom()->Float() * x2d4_data.x38_ + x2d4_data.x34_; + SetMuted(true); + } + SendScriptMsgs(EScriptObjectState::Damage, mgr, EScriptObjectMessage::None); } - else - x53c_ = 0.f; + } } -void CScriptGunTurret::UpdateGunParticles(float dt, CStateManager& mgr) -{ - CGameLight* light = nullptr; - if (x498_lightId != kInvalidUniqueId) - light = TCastToPtr(mgr.ObjectById(x498_lightId)); - - if (!x560_25_) - { - zeus::CTransform lightXf = GetLocatorTransform("light_LCTR"sv); - zeus::CVector3f pos = x34_transform.rotate(lightXf.origin); - pos += GetTranslation(); - if (light) - light->SetActive(true); - - if (x520_ == 6 || (x520_ >= 9 && x520_ <= 12)) - { - bool doEmission = false; - if (x520_ != 10 && x520_ != 12) - doEmission = true; - - x468_->SetParticleEmission(false); - x470_->SetParticleEmission(false); - x478_->SetParticleEmission(true); - x480_->SetParticleEmission(false); - x488_->SetParticleEmission(doEmission); - x478_->SetOrientation(GetTransform().getRotation()); - x478_->SetGlobalTranslation(pos); - x478_->SetGlobalScale(GetModelData()->GetScale()); - x478_->Update(dt); - if (x478_->SystemHasLight()) - light->SetLight(x478_->GetLight()); - else - light->SetActive(false); - - if (doEmission) - { - zeus::CTransform blastXf = GetLocatorTransform("Blast_LCTR"sv); - zeus::CVector3f blastPos = GetTransform().rotate(blastXf.origin); - blastPos += GetTranslation(); - x488_->SetOrientation(GetTransform().getRotation()); - x488_->SetGlobalTranslation(blastPos); - x488_->SetGlobalScale(GetModelData()->GetScale()); - x488_->Update(dt); - } - } - else if (x520_ == 5) - { - x468_->SetParticleEmission(true); - x470_->SetParticleEmission(false); - x478_->SetParticleEmission(false); - x480_->SetParticleEmission(false); - x488_->SetParticleEmission(false); - x490_->SetParticleEmission(false); - x468_->SetOrientation(GetTransform().getRotation()); - x468_->SetGlobalTranslation(pos); - x468_->SetGlobalScale(GetModelData()->GetScale()); - } - else if (x520_ > 0 && x520_ < 5) - { - x468_->SetParticleEmission(false); - x470_->SetParticleEmission(true); - x478_->SetParticleEmission(false); - x480_->SetParticleEmission(false); - x488_->SetParticleEmission(false); - x490_->SetParticleEmission(false); - x470_->SetOrientation(GetTransform().getRotation()); - x470_->SetGlobalTranslation(pos); - x470_->SetGlobalScale(GetModelData()->GetScale()); - x470_->Update(dt); - if (light && x470_->SystemHasLight()) - light->SetLight(x470_->GetLight()); - } - else - { - x468_->SetParticleEmission(false); - x470_->SetParticleEmission(false); - x478_->SetParticleEmission(false); - x480_->SetParticleEmission(false); - x488_->SetParticleEmission(false); - x490_->SetParticleEmission(false); - x480_->SetOrientation(GetTransform().getRotation()); - x480_->SetGlobalTranslation(GetTranslation()); - x480_->SetGlobalScale(GetModelData()->GetScale()); - x480_->Update(dt); - if (light) - light->SetActive(false); - } - } - else - { - x468_->SetParticleEmission(false); - x470_->SetParticleEmission(false); - x478_->SetParticleEmission(false); - x480_->SetParticleEmission(false); - x488_->SetParticleEmission(false); - x490_->SetParticleEmission(false); - x480_->SetOrientation(GetTransform().getRotation()); - x480_->SetGlobalTranslation(GetTranslation()); - x480_->SetGlobalScale(GetModelData()->GetScale()); - x480_->Update(dt); - if (light) - light->SetActive(false); - } +std::experimental::optional CScriptGunTurret::GetTouchBounds() const { + if (GetActive() && GetMaterialList().HasMaterial(EMaterialTypes::Solid)) + return {GetBoundingBox()}; + return {}; } -void CScriptGunTurret::sub80219a00(float dt, CStateManager& mgr) -{ - sub80219b18(1, mgr); - x524_ += dt; - sub80217124(mgr); - if (x25c_gunId != kInvalidUniqueId) - { - if (TCastToPtr gunTurret = mgr.ObjectById(x25c_gunId)) - { - if (gunTurret->x520_ != 12) - gunTurret->x520_ = x520_; - else if (x520_ != 12) - { - sub80219b18(12, mgr); - gunTurret->RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); - mgr.GetPlayer().SetOrbitRequestForTarget(GetUniqueId(), - CPlayer::EPlayerOrbitRequest::ActivateOrbitSource, mgr); - } - } - } +zeus::CVector3f CScriptGunTurret::GetOrbitPosition(const CStateManager& mgr) const { return GetAimPosition(mgr, 0.f); } + +zeus::CVector3f CScriptGunTurret::GetAimPosition(const CStateManager&, float) const { + if (x258_type == ETurretComponent::Base) + return GetTranslation() + x34_transform.rotate(GetLocatorTransform("Gun_SDK"sv).origin); + + return GetTranslation(); } -void CScriptGunTurret::sub802189c8() -{ - if (!HasModelData() || !GetModelData()->HasAnimData()) - return; - - if (x520_ > 12) - return; - - static const u32 animIds[13] = {5, 7, 9, 0, 1, 0, 1, 2, 3, 1, 1, 1, 1}; - CPASAnimParmData parmData = CPASAnimParmData(5, CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(animIds[x520_])); - auto pair = GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase().FindBestAnimation(parmData, -1); - - if (pair.first > 0.f && pair.second != x540_) - { - ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(pair.second, -1, 1.f, true), false); - ModelData()->AnimationData()->EnableLooping(true); - x540_ = pair.second; - } +void CScriptGunTurret::SetupCollisionManager(CStateManager& mgr) { + std::vector jointDescs; + jointDescs.reserve(2); + const CAnimData* animData = GetModelData()->GetAnimationData(); + x508_gunSDKSeg = animData->GetLocatorSegId("Gun_SDK"sv); + CSegId blastLCTR = animData->GetLocatorSegId("Blast_LCTR"sv); + jointDescs.push_back(CJointCollisionDescription::SphereSubdivideCollision( + x508_gunSDKSeg, blastLCTR, 0.6f, 1.f, CJointCollisionDescription::EOrientationType::One, "Gun_SDK"sv, 1000.f)); + jointDescs.push_back(CJointCollisionDescription::SphereCollision(blastLCTR, 0.3f, "Blast_LCTR"sv, 1000.f)); + x49c_collisionManager.reset(new CCollisionActorManager(mgr, GetUniqueId(), GetAreaIdAlways(), jointDescs, true)); } -void CScriptGunTurret::sub8021998c(s32 w1, CStateManager& mgr, float dt) -{ - switch(x520_) - { - case 3: - case 4: - sub80219938(w1, mgr); - break; - case 5: - sub802196c4(w1, mgr, dt); - break; - case 6: - sub802195bc(w1, mgr, dt); - break; - case 7: - case 8: - sub8021942c(w1, mgr, dt); - break; - case 9: - case 10: - sub80218f50(w1, mgr, dt); - break; - case 11: - sub80218e34(w1, mgr); - break; - case 12: - sub80218bb4(w1, mgr, dt); - break; - default: - break; - } +void CScriptGunTurret::sub80219b18(s32 w1, CStateManager& mgr) { + + if (w1 < 0 || w1 > 12) + return; + + if (x520_ != -1) + sub8021998c(2, mgr, 0.f); + + x520_ = w1; + x524_ = 0.f; + sub8021998c(0, mgr, 0.f); } -void CScriptGunTurret::sub80219938(s32 w1, CStateManager& mgr) -{ - if (w1 == 1) - { - float f1 = x524_; - float f0 = x2d4_data.x0_; - if (f1 >= f0 && x560_28_) - w1 = 2; +void CScriptGunTurret::sub80217408(CStateManager&) {} - sub80219b18(w1, mgr); - } +void CScriptGunTurret::sub802172b8(CStateManager& mgr) { + auto pair = ModelData()->AnimationData()->GetCharacterInfo().GetPASDatabase().FindBestAnimation( + CPASAnimParmData(23), *mgr.GetActiveRandom(), -1); + if (pair.first > 0.f) + ModelData()->AnimationData()->AddAdditiveAnimation(pair.second, 1.f, false, true); } -void CScriptGunTurret::sub802196c4(s32 w1, CStateManager& mgr, float dt) -{ - if (w1 == 0) - { - x528_ = 0.f; - x560_27_ = false; - if (TCastToPtr gunTurret = mgr.ObjectById(x25c_gunId)) - x260_ = gunTurret->HealthInfo(mgr)->GetHP(); - } - else if (w1 == 1) - { - } - else if (w1 == 2) - { - x560_28_ = true; - x468_->SetParticleEmission(false); +void CScriptGunTurret::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) { + CActor::AddToRenderer(frustum, mgr); - if (TCastToPtr gunTurret = mgr.ObjectById(x25c_gunId)) - x260_ = gunTurret->GetHealthInfo(mgr)->GetHP(); + if (x258_type != ETurretComponent::Gun) + return; + + if (!x560_25_) { + if (x520_ == 6 || (x520_ >= 9 && x520_ <= 12)) { + g_Renderer->AddParticleGen(*x478_); + if (x520_ == 10 || x520_ == 12) + g_Renderer->AddParticleGen(*x488_); + } else if (x520_ == 5) { + g_Renderer->AddParticleGen(*x468_); + } else if (x520_ >= 1) { + g_Renderer->AddParticleGen(*x470_); } + } else { + g_Renderer->AddParticleGen(*x480_); + } } -void CScriptGunTurret::sub802195bc(s32 w1, CStateManager& mgr, float dt) -{ - if (w1 == 0) - { - x52c_ = 0.f; - } - else if (w1 == 1) - { - x52c_ += dt; - if (x52c_ < x2d4_data.x10_) - return; +void CScriptGunTurret::Render(const CStateManager& mgr) const { + CPhysicsActor::Render(mgr); - if (sub80217ad8(mgr) && sub802179a4(mgr)) - { - sub80219b18(9, mgr); - CSfxManager::AddEmitter(x2d4_data.x7e_, GetTranslation(), zeus::CVector3f::skUp, false, false, 0x7f, - GetAreaIdAlways()); - } - else - { - sub80219b18(7, mgr); - x530_ = 0.f; - } + if (x258_type == ETurretComponent::Gun) { + if (!x560_25_) { + if (x520_ == 6 || (x520_ >= 9 && x520_ <= 12)) { + x478_->Render(x90_actorLights.get()); + if (x520_ == 10) + x488_->Render(x90_actorLights.get()); + } else if (x520_ == 5) + x468_->Render(x90_actorLights.get()); + else if (x520_ >= 1) + x470_->Render(x90_actorLights.get()); } + } else if (x258_type == ETurretComponent::Base) { + if (x4a4_ && x4f8_ > 0.f) { + zeus::CTransform xf = GetTransform(); + xf.origin = x4fc_ + (x4f4_ * 0.5f * zeus::CVector3f::skDown); + CModelFlags flags; + flags.x2_flags = 3; + flags.x1_matSetIdx = 0; + flags.x4_color = zeus::CColor::skWhite; + x4a4_->Render(mgr, xf, x90_actorLights.get(), flags); + } + } } -void CScriptGunTurret::sub8021942c(s32 state, CStateManager& mgr, float dt) -{ - if (state == 0) - { - x52c_ = 0.f; - } - else if (state == 1) - { - if (sub80217ad8(mgr) && sub802179a4(mgr)) - { - sub80219b18(9, mgr); - CSfxManager::AddEmitter(x2d4_data.x7e_, GetTranslation(), zeus::CVector3f::skUp, false, false, 0x7f, - GetAreaIdAlways()); - } - else - { - x52c_ += dt; - x530_ += dt; - if (x530_ >= x2d4_data.x18_ && !x4a4_ && !x2d4_data.xa0_) - sub80219b18(5, mgr); - else if (x52c_ >= x2d4_data.x14_) - sub80219b18(x520_ != 7 ? 7 : 8, mgr); - } - } +void CScriptGunTurret::UpdateGunCollisionManager(float dt, CStateManager& mgr) { + if (TCastToPtr colAct = mgr.ObjectById(x4a0_)) + colAct->SetActive(mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed); + + x49c_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace); } -void CScriptGunTurret::sub80218f50(s32 state, CStateManager& mgr, float dt) -{ - if (state == 0) - { - x52c_ = 0.f; - } - else if (state == 1) - { - if (!x560_26_) - { - if (sub802179a4(mgr)) - { - sub80218830(dt, mgr); - if (x25c_gunId != kInvalidUniqueId) - { - if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) - { - zeus::CVector3f vec = x404_; - if (sub80217ad8(mgr)) - { - zeus::CTransform blastXf = gun->GetLocatorTransform("Blast_LCTR"sv); - zeus::CVector3f rotatedBlastVec = GetTransform().rotate(blastXf.origin) + GetTranslation(); - x404_ = mgr.GetPlayer().GetAimPosition(mgr, 0.f); - vec = x37c_projectileInfo.PredictInterceptPos(rotatedBlastVec, - mgr.GetPlayer().GetAimPosition(mgr, dt), - mgr.GetPlayer(), false); - } - - zeus::CVector3f compensated = x3a4_burstFire.GetDistanceCompensatedError( - (x404_ - gun->GetTranslation()).magnitude(), 20.f); - - compensated = gun->GetTransform().rotate(compensated); - - gun->x404_ = x404_ + (vec - x404_) + compensated; - } - } - - zeus::CVector3f diffVec = x404_ - GetTranslation(); - if (diffVec.canBeNormalized()) - { - zeus::CVector3f normDiff = diffVec.normalized(); - float angDif = zeus::CVector3f::getAngleDiff(normDiff, GetTransform().frontVector()); - zeus::CQuaternion quat = zeus::CQuaternion::lookAt(GetTransform().frontVector(), normDiff, - std::min(angDif, (dt * x2d4_data.x28_))); - - quat.setImaginary(GetTransform().transposeRotate(quat.getImaginary())); - RotateInOneFrameOR(quat, dt); - } - } - - if (sub80217950(mgr)) - { - SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); - x560_26_ = true; - } - - x52c_ = 0.f; - } - else - { - x52c_ += dt; - if (x52c_ >= 10.f) - sub80219b18(11, mgr); - } - } - else if (state == 2) - { - x560_30_ = true; - } +void CScriptGunTurret::GetUnFreezeSoundId(float dt, CStateManager& mgr) { + if (x560_25_) { + if (x53c_ <= 0.f) { + SendScriptMsgs(EScriptObjectState::UnFrozen, mgr, EScriptObjectMessage::None); + CSfxManager::AddEmitter(x2d4_data.x80_unfreezeSound, GetTranslation(), zeus::CVector3f::skUp, false, false, 0x7f, + GetAreaIdAlways()); + SetMuted(false); + } else if (x2d4_data.x3c_) + x53c_ -= dt; + } else + x53c_ = 0.f; } -void CScriptGunTurret::sub80218e34(s32 state, CStateManager& mgr) -{ - if (state != 1 || x25c_gunId == kInvalidUniqueId) - return; +void CScriptGunTurret::UpdateGunParticles(float dt, CStateManager& mgr) { + CGameLight* light = nullptr; + if (x498_lightId != kInvalidUniqueId) + light = TCastToPtr(mgr.ObjectById(x498_lightId)); - if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) - { - zeus::CTransform gunXf = GetTransform() * GetLocatorTransform("Gun_SDK"sv); + if (!x560_25_) { + zeus::CTransform lightXf = GetLocatorTransform("light_LCTR"sv); + zeus::CVector3f pos = x34_transform.rotate(lightXf.origin); + pos += GetTranslation(); + if (light) + light->SetActive(true); - if (zeus::CVector3f::getAngleDiff(gun->GetTransform().frontVector(), x544_) < zeus::degToRad(0.9f)) - sub80219b18(6, mgr); + if (x520_ == 6 || (x520_ >= 9 && x520_ <= 12)) { + bool doEmission = false; + if (x520_ != 10 && x520_ != 12) + doEmission = true; + + x468_->SetParticleEmission(false); + x470_->SetParticleEmission(false); + x478_->SetParticleEmission(true); + x480_->SetParticleEmission(false); + x488_->SetParticleEmission(doEmission); + x478_->SetOrientation(GetTransform().getRotation()); + x478_->SetGlobalTranslation(pos); + x478_->SetGlobalScale(GetModelData()->GetScale()); + x478_->Update(dt); + if (x478_->SystemHasLight()) + light->SetLight(x478_->GetLight()); + else + light->SetActive(false); + + if (doEmission) { + zeus::CTransform blastXf = GetLocatorTransform("Blast_LCTR"sv); + zeus::CVector3f blastPos = GetTransform().rotate(blastXf.origin); + blastPos += GetTranslation(); + x488_->SetOrientation(GetTransform().getRotation()); + x488_->SetGlobalTranslation(blastPos); + x488_->SetGlobalScale(GetModelData()->GetScale()); + x488_->Update(dt); + } + } else if (x520_ == 5) { + x468_->SetParticleEmission(true); + x470_->SetParticleEmission(false); + x478_->SetParticleEmission(false); + x480_->SetParticleEmission(false); + x488_->SetParticleEmission(false); + x490_->SetParticleEmission(false); + x468_->SetOrientation(GetTransform().getRotation()); + x468_->SetGlobalTranslation(pos); + x468_->SetGlobalScale(GetModelData()->GetScale()); + } else if (x520_ > 0 && x520_ < 5) { + x468_->SetParticleEmission(false); + x470_->SetParticleEmission(true); + x478_->SetParticleEmission(false); + x480_->SetParticleEmission(false); + x488_->SetParticleEmission(false); + x490_->SetParticleEmission(false); + x470_->SetOrientation(GetTransform().getRotation()); + x470_->SetGlobalTranslation(pos); + x470_->SetGlobalScale(GetModelData()->GetScale()); + x470_->Update(dt); + if (light && x470_->SystemHasLight()) + light->SetLight(x470_->GetLight()); + } else { + x468_->SetParticleEmission(false); + x470_->SetParticleEmission(false); + x478_->SetParticleEmission(false); + x480_->SetParticleEmission(false); + x488_->SetParticleEmission(false); + x490_->SetParticleEmission(false); + x480_->SetOrientation(GetTransform().getRotation()); + x480_->SetGlobalTranslation(GetTranslation()); + x480_->SetGlobalScale(GetModelData()->GetScale()); + x480_->Update(dt); + if (light) + light->SetActive(false); } + } else { + x468_->SetParticleEmission(false); + x470_->SetParticleEmission(false); + x478_->SetParticleEmission(false); + x480_->SetParticleEmission(false); + x488_->SetParticleEmission(false); + x490_->SetParticleEmission(false); + x480_->SetOrientation(GetTransform().getRotation()); + x480_->SetGlobalTranslation(GetTranslation()); + x480_->SetGlobalScale(GetModelData()->GetScale()); + x480_->Update(dt); + if (light) + light->SetActive(false); + } } -void CScriptGunTurret::sub80218bb4(s32 state, CStateManager& mgr, float dt) -{ - if (state == 0) - { - x560_31_ = mgr.GetActiveRandom()->Float() < 0.f; - x534_ = 0.15f; - RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); +void CScriptGunTurret::sub80219a00(float dt, CStateManager& mgr) { + sub80219b18(1, mgr); + x524_ += dt; + sub80217124(mgr); + if (x25c_gunId != kInvalidUniqueId) { + if (TCastToPtr gunTurret = mgr.ObjectById(x25c_gunId)) { + if (gunTurret->x520_ != 12) + gunTurret->x520_ = x520_; + else if (x520_ != 12) { + sub80219b18(12, mgr); + gunTurret->RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); mgr.GetPlayer().SetOrbitRequestForTarget(GetUniqueId(), CPlayer::EPlayerOrbitRequest::ActivateOrbitSource, mgr); - } else if (state == 1) - { - if (x524_ >= x2d4_data.x9c_) - { - sub80219b18(0, mgr); - if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) - gun->x520_ = 0; - return; - } - - zeus::CVector3f frontVec = GetTransform().frontVector(); - if (x560_31_ && x550_.magSquared() < 0.f && - zeus::CVector3f::getAngleDiff(x544_, frontVec) >= zeus::degToRad(45.f)) - { - x560_31_ = false; - } else if (!x560_31_ && x550_.magSquared() < 0.f && - zeus::CVector3f::getAngleDiff(x544_, frontVec) >= zeus::degToRad(45.f)) - { - x560_31_ = true; - } - - if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) - { - x534_ -= dt; - if (x534_ >= 0.f) - return; - - x404_ = gun->GetTranslation() + (100.f * gun->GetTransform().frontVector()); - SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); - x534_ = 0.15f; - } + } } + } } -bool CScriptGunTurret::sub80217ad8(CStateManager& mgr) -{ - zeus::CVector3f posDif = mgr.GetPlayer().GetTranslation() - GetTranslation(); - zeus::CVector3f someVec(posDif.x(), posDif.y(), 0.f); - if (x550_.dot(posDif) >= 0.f) - return zeus::CVector3f::getAngleDiff(x544_, someVec) <= x2d4_data.x20_; +void CScriptGunTurret::sub802189c8() { + if (!HasModelData() || !GetModelData()->HasAnimData()) + return; - if (zeus::CVector3f::getAngleDiff(x544_, someVec) <= x2d4_data.x20_) - return true; + if (x520_ > 12) + return; - float biasedAngle = zeus::CVector3f::getAngleDiff(posDif, zeus::CVector3f::skUp) - zeus::degToRad(90.f); + static const u32 animIds[13] = {5, 7, 9, 0, 1, 0, 1, 2, 3, 1, 1, 1, 1}; + CPASAnimParmData parmData = CPASAnimParmData(5, CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(animIds[x520_])); + auto pair = GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase().FindBestAnimation(parmData, -1); - return (biasedAngle >= zeus::degToRad(-20.f) && biasedAngle <= x2d4_data.x24_); + if (pair.first > 0.f && pair.second != x540_) { + ModelData()->AnimationData()->SetAnimation(CAnimPlaybackParms(pair.second, -1, 1.f, true), false); + ModelData()->AnimationData()->EnableLooping(true); + x540_ = pair.second; + } } -bool CScriptGunTurret::sub802179a4(CStateManager&) -{ - return false; +void CScriptGunTurret::sub8021998c(s32 w1, CStateManager& mgr, float dt) { + switch (x520_) { + case 3: + case 4: + sub80219938(w1, mgr); + break; + case 5: + sub802196c4(w1, mgr, dt); + break; + case 6: + sub802195bc(w1, mgr, dt); + break; + case 7: + case 8: + sub8021942c(w1, mgr, dt); + break; + case 9: + case 10: + sub80218f50(w1, mgr, dt); + break; + case 11: + sub80218e34(w1, mgr); + break; + case 12: + sub80218bb4(w1, mgr, dt); + break; + default: + break; + } } -zeus::CVector3f CScriptGunTurret::sub80217e34(float dt) -{ - if (!x4a4_) - return {}; +void CScriptGunTurret::sub80219938(s32 w1, CStateManager& mgr) { + if (w1 == 1) { + float f1 = x524_; + float f0 = x2d4_data.x0_; + if (f1 >= f0 && x560_28_) + w1 = 2; - if (x520_ >= 7 && x520_ < 12) - x4f8_ = std::min(0.9f, x4f8_ + 1.5f * dt); - else if ((x520_ >= 0 && x520_ < 3) || x520_ == 5 || x520_ == 13) - x4f8_ = std::max(0.f, x4f8_ - 1.f * dt); - - return (x4fc_ + (x2d4_data.x8c_ * x4f8_ * zeus::CVector3f::skDown)) - GetTranslation(); + sub80219b18(w1, mgr); + } } -void CScriptGunTurret::sub80217f5c(float dt, CStateManager& mgr) -{ - /* TODO: Finish */ - if (x25c_gunId == kInvalidUniqueId) +void CScriptGunTurret::sub802196c4(s32 w1, CStateManager& mgr, float dt) { + if (w1 == 0) { + x528_ = 0.f; + x560_27_ = false; + if (TCastToPtr gunTurret = mgr.ObjectById(x25c_gunId)) + x260_ = gunTurret->HealthInfo(mgr)->GetHP(); + } else if (w1 == 1) { + } else if (w1 == 2) { + x560_28_ = true; + x468_->SetParticleEmission(false); + + if (TCastToPtr gunTurret = mgr.ObjectById(x25c_gunId)) + x260_ = gunTurret->GetHealthInfo(mgr)->GetHP(); + } +} + +void CScriptGunTurret::sub802195bc(s32 w1, CStateManager& mgr, float dt) { + if (w1 == 0) { + x52c_ = 0.f; + } else if (w1 == 1) { + x52c_ += dt; + if (x52c_ < x2d4_data.x10_) + return; + + if (sub80217ad8(mgr) && sub802179a4(mgr)) { + sub80219b18(9, mgr); + CSfxManager::AddEmitter(x2d4_data.x7e_, GetTranslation(), zeus::CVector3f::skUp, false, false, 0x7f, + GetAreaIdAlways()); + } else { + sub80219b18(7, mgr); + x530_ = 0.f; + } + } +} + +void CScriptGunTurret::sub8021942c(s32 state, CStateManager& mgr, float dt) { + if (state == 0) { + x52c_ = 0.f; + } else if (state == 1) { + if (sub80217ad8(mgr) && sub802179a4(mgr)) { + sub80219b18(9, mgr); + CSfxManager::AddEmitter(x2d4_data.x7e_, GetTranslation(), zeus::CVector3f::skUp, false, false, 0x7f, + GetAreaIdAlways()); + } else { + x52c_ += dt; + x530_ += dt; + if (x530_ >= x2d4_data.x18_ && !x4a4_ && !x2d4_data.xa0_) + sub80219b18(5, mgr); + else if (x52c_ >= x2d4_data.x14_) + sub80219b18(x520_ != 7 ? 7 : 8, mgr); + } + } +} + +void CScriptGunTurret::sub80218f50(s32 state, CStateManager& mgr, float dt) { + if (state == 0) { + x52c_ = 0.f; + } else if (state == 1) { + if (!x560_26_) { + if (sub802179a4(mgr)) { + sub80218830(dt, mgr); + if (x25c_gunId != kInvalidUniqueId) { + if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) { + zeus::CVector3f vec = x404_; + if (sub80217ad8(mgr)) { + zeus::CTransform blastXf = gun->GetLocatorTransform("Blast_LCTR"sv); + zeus::CVector3f rotatedBlastVec = GetTransform().rotate(blastXf.origin) + GetTranslation(); + x404_ = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + vec = x37c_projectileInfo.PredictInterceptPos(rotatedBlastVec, mgr.GetPlayer().GetAimPosition(mgr, dt), + mgr.GetPlayer(), false); + } + + zeus::CVector3f compensated = + x3a4_burstFire.GetDistanceCompensatedError((x404_ - gun->GetTranslation()).magnitude(), 20.f); + + compensated = gun->GetTransform().rotate(compensated); + + gun->x404_ = x404_ + (vec - x404_) + compensated; + } + } + + zeus::CVector3f diffVec = x404_ - GetTranslation(); + if (diffVec.canBeNormalized()) { + zeus::CVector3f normDiff = diffVec.normalized(); + float angDif = zeus::CVector3f::getAngleDiff(normDiff, GetTransform().frontVector()); + zeus::CQuaternion quat = zeus::CQuaternion::lookAt(GetTransform().frontVector(), normDiff, + std::min(angDif, (dt * x2d4_data.x28_))); + + quat.setImaginary(GetTransform().transposeRotate(quat.getImaginary())); + RotateInOneFrameOR(quat, dt); + } + } + + if (sub80217950(mgr)) { + SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); + x560_26_ = true; + } + + x52c_ = 0.f; + } else { + x52c_ += dt; + if (x52c_ >= 10.f) + sub80219b18(11, mgr); + } + } else if (state == 2) { + x560_30_ = true; + } +} + +void CScriptGunTurret::sub80218e34(s32 state, CStateManager& mgr) { + if (state != 1 || x25c_gunId == kInvalidUniqueId) + return; + + if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) { + zeus::CTransform gunXf = GetTransform() * GetLocatorTransform("Gun_SDK"sv); + + if (zeus::CVector3f::getAngleDiff(gun->GetTransform().frontVector(), x544_) < zeus::degToRad(0.9f)) + sub80219b18(6, mgr); + } +} + +void CScriptGunTurret::sub80218bb4(s32 state, CStateManager& mgr, float dt) { + if (state == 0) { + x560_31_ = mgr.GetActiveRandom()->Float() < 0.f; + x534_ = 0.15f; + RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::Orbit, mgr); + mgr.GetPlayer().SetOrbitRequestForTarget(GetUniqueId(), CPlayer::EPlayerOrbitRequest::ActivateOrbitSource, mgr); + } else if (state == 1) { + if (x524_ >= x2d4_data.x9c_) { + sub80219b18(0, mgr); + if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) + gun->x520_ = 0; + return; + } + + zeus::CVector3f frontVec = GetTransform().frontVector(); + if (x560_31_ && x550_.magSquared() < 0.f && + zeus::CVector3f::getAngleDiff(x544_, frontVec) >= zeus::degToRad(45.f)) { + x560_31_ = false; + } else if (!x560_31_ && x550_.magSquared() < 0.f && + zeus::CVector3f::getAngleDiff(x544_, frontVec) >= zeus::degToRad(45.f)) { + x560_31_ = true; + } + + if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) { + x534_ -= dt; + if (x534_ >= 0.f) return; - if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) - { - zeus::CTransform xf = GetLocatorTransform("Gun_SDK"sv); - xf = GetTransform() * xf; - - switch(x520_) - { - case 11: - { - zeus::CVector3f frontVec = GetTransform().frontVector(); - zeus::CVector3f gunFrontVec = gun->GetTransform().frontVector(); - zeus::CQuaternion quat = zeus::CQuaternion::lookAt(gunFrontVec, frontVec, 0.3f * dt * x2d4_data.x28_); - zeus::CVector3f xposVec = gun->GetTransform().transposeRotate(quat.getImaginary()); - quat.setImaginary(xposVec); - gun->RotateInOneFrameOR(quat, dt); - RotateInOneFrameOR(quat, dt); - break; - } - case 12: - break; - default: - gun->SetTransform(xf); - break; - } + x404_ = gun->GetTranslation() + (100.f * gun->GetTransform().frontVector()); + SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); + x534_ = 0.15f; } + } } -void CScriptGunTurret::sub80216288(float dt) -{ - x510_ += dt; - float angleDiff2D = zeus::CVector2f::getAngleDiff(x514_.toVec2f(), GetTransform().frontVector().toVec2f()); +bool CScriptGunTurret::sub80217ad8(CStateManager& mgr) { + zeus::CVector3f posDif = mgr.GetPlayer().GetTranslation() - GetTranslation(); + zeus::CVector3f someVec(posDif.x(), posDif.y(), 0.f); + if (x550_.dot(posDif) >= 0.f) + return zeus::CVector3f::getAngleDiff(x544_, someVec) <= x2d4_data.x20_; - if (x560_30_ && angleDiff2D < zeus::degToRad(20.f) && (x520_ == 9 || x520_ == 10)) - { - if (!x560_25_) - CSfxManager::AddEmitter(x2d4_data.x82_, GetTranslation(), zeus::CVector3f::skUp, false, false, 127, - GetAreaIdAlways()); - x560_30_ = false; + if (zeus::CVector3f::getAngleDiff(x544_, someVec) <= x2d4_data.x20_) + return true; + + float biasedAngle = zeus::CVector3f::getAngleDiff(posDif, zeus::CVector3f::skUp) - zeus::degToRad(90.f); + + return (biasedAngle >= zeus::degToRad(-20.f) && biasedAngle <= x2d4_data.x24_); +} + +bool CScriptGunTurret::sub802179a4(CStateManager&) { return false; } + +zeus::CVector3f CScriptGunTurret::sub80217e34(float dt) { + if (!x4a4_) + return {}; + + if (x520_ >= 7 && x520_ < 12) + x4f8_ = std::min(0.9f, x4f8_ + 1.5f * dt); + else if ((x520_ >= 0 && x520_ < 3) || x520_ == 5 || x520_ == 13) + x4f8_ = std::max(0.f, x4f8_ - 1.f * dt); + + return (x4fc_ + (x2d4_data.x8c_ * x4f8_ * zeus::CVector3f::skDown)) - GetTranslation(); +} + +void CScriptGunTurret::sub80217f5c(float dt, CStateManager& mgr) { + /* TODO: Finish */ + if (x25c_gunId == kInvalidUniqueId) + return; + + if (TCastToPtr gun = mgr.ObjectById(x25c_gunId)) { + zeus::CTransform xf = GetLocatorTransform("Gun_SDK"sv); + xf = GetTransform() * xf; + + switch (x520_) { + case 11: { + zeus::CVector3f frontVec = GetTransform().frontVector(); + zeus::CVector3f gunFrontVec = gun->GetTransform().frontVector(); + zeus::CQuaternion quat = zeus::CQuaternion::lookAt(gunFrontVec, frontVec, 0.3f * dt * x2d4_data.x28_); + zeus::CVector3f xposVec = gun->GetTransform().transposeRotate(quat.getImaginary()); + quat.setImaginary(xposVec); + gun->RotateInOneFrameOR(quat, dt); + RotateInOneFrameOR(quat, dt); + break; } - - if (x510_ >= 0.5f && !x560_25_) - { - if (x520_ == 9 || x520_ == 10 || x520_ == 12) - { - bool res = sub80217c24(dt); - if (!res && !x50c_) - x50c_ = CSfxManager::AddEmitter(x2d4_data.x7c_, GetTranslation(), zeus::CVector3f::skUp, false, true, - 127, GetAreaIdAlways()); - else if (res && x50c_) - { - CSfxManager::RemoveEmitter(x50c_); - x50c_.reset(); - x510_ = 0.f; - } - - if (x50c_) - { - float bendScale = dt * x2d4_data.x28_; - CSfxManager::PitchBend(x50c_, - std::max(1.f, 8192.f * (bendScale > 0.f ? angleDiff2D / bendScale : 0.f)) + - 8192); - } - } + case 12: + break; + default: + gun->SetTransform(xf); + break; } - else if (x560_25_ && x50c_) - { + } +} + +void CScriptGunTurret::sub80216288(float dt) { + x510_ += dt; + float angleDiff2D = zeus::CVector2f::getAngleDiff(x514_.toVec2f(), GetTransform().frontVector().toVec2f()); + + if (x560_30_ && angleDiff2D < zeus::degToRad(20.f) && (x520_ == 9 || x520_ == 10)) { + if (!x560_25_) + CSfxManager::AddEmitter(x2d4_data.x82_, GetTranslation(), zeus::CVector3f::skUp, false, false, 127, + GetAreaIdAlways()); + x560_30_ = false; + } + + if (x510_ >= 0.5f && !x560_25_) { + if (x520_ == 9 || x520_ == 10 || x520_ == 12) { + bool res = sub80217c24(dt); + if (!res && !x50c_) + x50c_ = CSfxManager::AddEmitter(x2d4_data.x7c_, GetTranslation(), zeus::CVector3f::skUp, false, true, 127, + GetAreaIdAlways()); + else if (res && x50c_) { CSfxManager::RemoveEmitter(x50c_); x50c_.reset(); - } + x510_ = 0.f; + } - x514_ = GetTransform().frontVector(); + if (x50c_) { + float bendScale = dt * x2d4_data.x28_; + CSfxManager::PitchBend(x50c_, std::max(1.f, 8192.f * (bendScale > 0.f ? angleDiff2D / bendScale : 0.f)) + 8192); + } + } + } else if (x560_25_ && x50c_) { + CSfxManager::RemoveEmitter(x50c_); + x50c_.reset(); + } + + x514_ = GetTransform().frontVector(); } -void CScriptGunTurret::sub80217124(CStateManager& mgr) -{ - if (x520_ == 10) - { - if (x55c_ != -1) - return; +void CScriptGunTurret::sub80217124(CStateManager& mgr) { + if (x520_ == 10) { + if (x55c_ != -1) + return; - auto pair = ModelData()->AnimationData()->GetCharacterInfo().GetPASDatabase().FindBestAnimation( - CPASAnimParmData(24, CPASAnimParm::FromEnum(2)), *mgr.GetActiveRandom(), -1); - if (pair.first > 0.f) - { - x55c_ = pair.second; - ModelData()->AnimationData()->AddAdditiveAnimation(pair.second, 1.f, true, false); - } - } - else if (x55c_ != -1) - { - ModelData()->AnimationData()->DelAdditiveAnimation(x55c_); - x55c_ = -1; + auto pair = ModelData()->AnimationData()->GetCharacterInfo().GetPASDatabase().FindBestAnimation( + CPASAnimParmData(24, CPASAnimParm::FromEnum(2)), *mgr.GetActiveRandom(), -1); + if (pair.first > 0.f) { + x55c_ = pair.second; + ModelData()->AnimationData()->AddAdditiveAnimation(pair.second, 1.f, true, false); } + } else if (x55c_ != -1) { + ModelData()->AnimationData()->DelAdditiveAnimation(x55c_); + x55c_ = -1; + } } -void CScriptGunTurret::sub80218830(float dt, CStateManager& mgr) -{ - if (mgr.GetCameraManager()->IsInCinematicCamera()) - { - x534_ = mgr.GetActiveRandom()->Float() * x2d4_data.xc_ + x2d4_data.x8_; - x538_ = 0.5f * x534_; +void CScriptGunTurret::sub80218830(float dt, CStateManager& mgr) { + if (mgr.GetCameraManager()->IsInCinematicCamera()) { + x534_ = mgr.GetActiveRandom()->Float() * x2d4_data.xc_ + x2d4_data.x8_; + x538_ = 0.5f * x534_; + } + + if (x534_ > 0.f) { + x534_ -= dt; + if (x534_ < x538_ && x520_ != 10) { + CSfxManager::AddEmitter(x2d4_data.x84_, GetTranslation(), zeus::CVector3f::skUp, false, false, 0x7f, + GetAreaIdAlways()); + sub80219b18(10, mgr); + return; } - if (x534_ > 0.f) - { - x534_ -= dt; - if (x534_ < x538_ && x520_ != 10) - { - CSfxManager::AddEmitter(x2d4_data.x84_, GetTranslation(), zeus::CVector3f::skUp, false, false, 0x7f, GetAreaIdAlways()); - sub80219b18(10, mgr); - return; - } + if (x520_ != 9) + sub80219b18(9, mgr); - if (x520_ != 9) - sub80219b18(9, mgr); - - if (x2d4_data.x18_ == 0) - { - sub80216594(mgr); - x534_ = mgr.GetActiveRandom()->Float() * x2d4_data.xc_ + x2d4_data.x8_; - x538_ = 0.5f * x534_; - return; - } - - x3a4_burstFire.Update(mgr, dt); + if (x2d4_data.x18_ == 0) { + sub80216594(mgr); + x534_ = mgr.GetActiveRandom()->Float() * x2d4_data.xc_ + x2d4_data.x8_; + x538_ = 0.5f * x534_; + return; } + + x3a4_burstFire.Update(mgr, dt); + } } -void CScriptGunTurret::sub80216594(CStateManager& mgr) -{ - if (x560_27_) - { - u32 r0 = 1; - if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) - { - zeus::CVector3f frontVec = GetTransform().frontVector(); - zeus::CVector3f plFrontVec = mgr.GetPlayer().GetTransform().frontVector(); - float dot = frontVec.dot(plFrontVec); +void CScriptGunTurret::sub80216594(CStateManager& mgr) { + if (x560_27_) { + u32 r0 = 1; + if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) { + zeus::CVector3f frontVec = GetTransform().frontVector(); + zeus::CVector3f plFrontVec = mgr.GetPlayer().GetTransform().frontVector(); + float dot = frontVec.dot(plFrontVec); - if (dot > 0.f) - r0 = 0; - } - bool r29 = r0 != 0; - u32 r3 = mgr.GetActiveRandom()->Range(0, 3); - r3 += 2; - if (r3 > 2 && x2d4_data.x98_ < 3) - r0 = 0; - else if (r3 > 5 || r3 > 3) - r0 = 2; - else - r0 = 1; - - x3a4_burstFire.SetBurstType(r0 + r29); + if (dot > 0.f) + r0 = 0; } + bool r29 = r0 != 0; + u32 r3 = mgr.GetActiveRandom()->Range(0, 3); + r3 += 2; + if (r3 > 2 && x2d4_data.x98_ < 3) + r0 = 0; + else if (r3 > 5 || r3 > 3) + r0 = 2; else - { - u32 r3 = x2d4_data.x90_ - 2; - x3a4_burstFire.SetBurstType(r3); - x3a4_burstFire.SetFirstBurstIndex(x2d4_data.x94_); - } + r0 = 1; + x3a4_burstFire.SetBurstType(r0 + r29); + } else { + u32 r3 = x2d4_data.x90_ - 2; + x3a4_burstFire.SetBurstType(r3); + x3a4_burstFire.SetFirstBurstIndex(x2d4_data.x94_); + } - x3a4_burstFire.Start(mgr); - x560_26_ = false; - x560_27_ = true; + x3a4_burstFire.Start(mgr); + x560_26_ = false; + x560_27_ = true; } -bool CScriptGunTurret::sub80217950(CStateManager& mgr) -{ - if (x520_ == 9 && x534_ <= 0.f && x3a4_burstFire.ShouldFire()) - return sub80217ad8(mgr); +bool CScriptGunTurret::sub80217950(CStateManager& mgr) { + if (x520_ == 9 && x534_ <= 0.f && x3a4_burstFire.ShouldFire()) + return sub80217ad8(mgr); - return false; + return false; } -bool CScriptGunTurret::sub80217c24(float) -{ - return zeus::CVector2f::getAngleDiff(x514_.toVec2f(), GetTransform().frontVector().toVec2f()) < zeus::degToRad(20.f); +bool CScriptGunTurret::sub80217c24(float) { + return zeus::CVector2f::getAngleDiff(x514_.toVec2f(), GetTransform().frontVector().toVec2f()) < zeus::degToRad(20.f); } - -} +} // namespace urde diff --git a/Runtime/World/CScriptGunTurret.hpp b/Runtime/World/CScriptGunTurret.hpp index 66269325c..9584530fb 100644 --- a/Runtime/World/CScriptGunTurret.hpp +++ b/Runtime/World/CScriptGunTurret.hpp @@ -8,191 +8,187 @@ #include "Weapon/CProjectileInfo.hpp" #include "Weapon/CBurstFire.hpp" -namespace urde -{ +namespace urde { class CCollisionActorManager; -class CScriptGunTurretData -{ - friend class CScriptGunTurret; - float x0_; - float x4_; - float x8_; - float xc_; - float x10_; - float x14_; - float x18_ = 30.f; - float x1c_; - float x20_; - float x24_; - float x28_; - float x2c_; - float x30_; - float x34_; - float x38_; - bool x3c_; - CAssetId x40_projectileRes; - CDamageInfo x44_projectileDamage; - CAssetId x60_; - CAssetId x64_; - CAssetId x68_; - CAssetId x6c_; - CAssetId x70_; - CAssetId x74_; - CAssetId x78_; - u16 x7c_; - u16 x7e_; - u16 x80_unfreezeSound; - u16 x82_; - u16 x84_; - u16 x86_; - CAssetId x88_; - float x8c_; - u32 x90_; - u32 x94_; - u32 x98_; - float x9c_; - bool xa0_; - static constexpr s32 skMinProperties = 43; +class CScriptGunTurretData { + friend class CScriptGunTurret; + float x0_; + float x4_; + float x8_; + float xc_; + float x10_; + float x14_; + float x18_ = 30.f; + float x1c_; + float x20_; + float x24_; + float x28_; + float x2c_; + float x30_; + float x34_; + float x38_; + bool x3c_; + CAssetId x40_projectileRes; + CDamageInfo x44_projectileDamage; + CAssetId x60_; + CAssetId x64_; + CAssetId x68_; + CAssetId x6c_; + CAssetId x70_; + CAssetId x74_; + CAssetId x78_; + u16 x7c_; + u16 x7e_; + u16 x80_unfreezeSound; + u16 x82_; + u16 x84_; + u16 x86_; + CAssetId x88_; + float x8c_; + u32 x90_; + u32 x94_; + u32 x98_; + float x9c_; + bool xa0_; + static constexpr s32 skMinProperties = 43; + public: - CScriptGunTurretData(CInputStream&, s32); - CAssetId GetPanningEffectRes() const; - CAssetId GetChargingEffectRes() const; - CAssetId GetFrozenEffectRes() const; - CAssetId GetTargettingLightRes() const; - CAssetId GetDeactivateLightRes() const; - CAssetId GetIdleLightRes() const; - const CDamageInfo& GetProjectileDamage() const { return x44_projectileDamage; } - CAssetId GetProjectileRes() const { return x40_projectileRes; } - u16 GetUnFreezeSoundId() const; - float GetIntoDeactivateDelay() const; - static s32 GetMinProperties() { return skMinProperties; } + CScriptGunTurretData(CInputStream&, s32); + CAssetId GetPanningEffectRes() const; + CAssetId GetChargingEffectRes() const; + CAssetId GetFrozenEffectRes() const; + CAssetId GetTargettingLightRes() const; + CAssetId GetDeactivateLightRes() const; + CAssetId GetIdleLightRes() const; + const CDamageInfo& GetProjectileDamage() const { return x44_projectileDamage; } + CAssetId GetProjectileRes() const { return x40_projectileRes; } + u16 GetUnFreezeSoundId() const; + float GetIntoDeactivateDelay() const; + static s32 GetMinProperties() { return skMinProperties; } }; -class CScriptGunTurret : public CPhysicsActor -{ - static const SBurst skOOVBurst4InfoTemplate[]; - static const SBurst skOOVBurst3InfoTemplate[]; - static const SBurst skOOVBurst2InfoTemplate[]; - static const SBurst skBurst4InfoTemplate[]; - static const SBurst skBurst3InfoTemplate[]; - static const SBurst skBurst2InfoTemplate[]; - static const SBurst* skBursts[]; -public: - enum class ETurretComponent - { - Base, - Gun - }; - enum class ETurretState - { - - }; -private: - - ETurretComponent x258_type; - TUniqueId x25c_gunId = kInvalidUniqueId; - float x260_ = 0.f; - CHealthInfo x264_healthInfo; - CDamageVulnerability x26c_damageVuln; - CScriptGunTurretData x2d4_data; - TUniqueId x378_ = kInvalidUniqueId; - CProjectileInfo x37c_projectileInfo; - CBurstFire x3a4_burstFire; - zeus::CVector3f x404_; - TToken x410_; - TToken x41c_; - TToken x428_; - TToken x434_; - TToken x440_; - TToken x44c_; - TLockedToken x458_; - std::unique_ptr x468_; - std::unique_ptr x470_; - std::unique_ptr x478_; - std::unique_ptr x480_; - std::unique_ptr x488_; - std::unique_ptr x490_; - TUniqueId x498_lightId = kInvalidUniqueId; - std::unique_ptr x49c_collisionManager; - TUniqueId x4a0_ = kInvalidUniqueId; - std::experimental::optional x4a4_; - float x4f4_ = 0.f; - float x4f8_ = 0.f; - zeus::CVector3f x4fc_; - u8 x508_gunSDKSeg = 0xFF; - CSfxHandle x50c_; - float x510_ = 0.f; - zeus::CVector3f x514_; - s32 x520_ = -1; - float x524_ = 0.f; - float x528_ = 0.f; - float x52c_ = 0.f; - float x530_ = 0.f; - float x534_ = 0.f; - float x538_ = 0.f; - float x53c_ = 0.f; - s32 x540_ = -1; - zeus::CVector3f x544_; - zeus::CVector3f x550_; - s32 x55c_ = -1; - union - { - struct - { - bool x560_24_ : 1; bool x560_25_ : 1; bool x560_26_ : 1; - bool x560_27_ : 1; bool x560_28_ : 1; bool x560_29_ : 1; - bool x560_30_ : 1; bool x560_31_ : 1; - }; - u32 _dummy = 0; - }; -private: - - void SetupCollisionManager(CStateManager&); +class CScriptGunTurret : public CPhysicsActor { + static const SBurst skOOVBurst4InfoTemplate[]; + static const SBurst skOOVBurst3InfoTemplate[]; + static const SBurst skOOVBurst2InfoTemplate[]; + static const SBurst skBurst4InfoTemplate[]; + static const SBurst skBurst3InfoTemplate[]; + static const SBurst skBurst2InfoTemplate[]; + static const SBurst* skBursts[]; public: - CScriptGunTurret(TUniqueId uid, std::string_view name, ETurretComponent comp, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& aabb, - const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, - const CActorParameters& aParms, const CScriptGunTurretData& turretData); + enum class ETurretComponent { Base, Gun }; + enum class ETurretState { - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); - void Touch(CActor&, CStateManager&); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&); - void Render(const CStateManager&) const; - std::experimental::optional GetTouchBounds() const; - zeus::CVector3f GetOrbitPosition(const CStateManager&) const; - zeus::CVector3f GetAimPosition(const CStateManager&, float) const; + }; - CHealthInfo* HealthInfo(CStateManager&) { return &x264_healthInfo; } - const CDamageVulnerability* GetDamageVulnerability() const { return &x26c_damageVuln; } - void sub80219b18(s32, CStateManager&); - void sub8021998c(s32, CStateManager&, float); - void sub80217408(CStateManager&); - void sub802172b8(CStateManager&); - void sub80219a00(float, CStateManager&); - void sub802189c8(); - void UpdateGunCollisionManager(float, CStateManager&); - void GetUnFreezeSoundId(float, CStateManager&); - void UpdateGunParticles(float, CStateManager&); - void sub80219938(s32, CStateManager&); - void sub802196c4(s32, CStateManager&, float); - void sub802195bc(s32, CStateManager&, float); - void sub8021942c(s32, CStateManager&, float); - void sub80218f50(s32, CStateManager&, float); - void sub80218e34(s32, CStateManager&); - void sub80218bb4(s32, CStateManager&, float); - bool sub80217ad8(CStateManager&); - bool sub802179a4(CStateManager&); - void sub80217f5c(float, CStateManager&); - zeus::CVector3f sub80217e34(float); - void sub80216288(float); - void sub80217124(CStateManager&); - void sub80218830(float, CStateManager&); - void sub80216594(CStateManager&); - bool sub80217950(CStateManager&); - bool sub80217c24(float); +private: + ETurretComponent x258_type; + TUniqueId x25c_gunId = kInvalidUniqueId; + float x260_ = 0.f; + CHealthInfo x264_healthInfo; + CDamageVulnerability x26c_damageVuln; + CScriptGunTurretData x2d4_data; + TUniqueId x378_ = kInvalidUniqueId; + CProjectileInfo x37c_projectileInfo; + CBurstFire x3a4_burstFire; + zeus::CVector3f x404_; + TToken x410_; + TToken x41c_; + TToken x428_; + TToken x434_; + TToken x440_; + TToken x44c_; + TLockedToken x458_; + std::unique_ptr x468_; + std::unique_ptr x470_; + std::unique_ptr x478_; + std::unique_ptr x480_; + std::unique_ptr x488_; + std::unique_ptr x490_; + TUniqueId x498_lightId = kInvalidUniqueId; + std::unique_ptr x49c_collisionManager; + TUniqueId x4a0_ = kInvalidUniqueId; + std::experimental::optional x4a4_; + float x4f4_ = 0.f; + float x4f8_ = 0.f; + zeus::CVector3f x4fc_; + u8 x508_gunSDKSeg = 0xFF; + CSfxHandle x50c_; + float x510_ = 0.f; + zeus::CVector3f x514_; + s32 x520_ = -1; + float x524_ = 0.f; + float x528_ = 0.f; + float x52c_ = 0.f; + float x530_ = 0.f; + float x534_ = 0.f; + float x538_ = 0.f; + float x53c_ = 0.f; + s32 x540_ = -1; + zeus::CVector3f x544_; + zeus::CVector3f x550_; + s32 x55c_ = -1; + union { + struct { + bool x560_24_ : 1; + bool x560_25_ : 1; + bool x560_26_ : 1; + bool x560_27_ : 1; + bool x560_28_ : 1; + bool x560_29_ : 1; + bool x560_30_ : 1; + bool x560_31_ : 1; + }; + u32 _dummy = 0; + }; + +private: + void SetupCollisionManager(CStateManager&); + +public: + CScriptGunTurret(TUniqueId uid, std::string_view name, ETurretComponent comp, const CEntityInfo& info, + const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& aabb, const CHealthInfo& hInfo, + const CDamageVulnerability& dVuln, const CActorParameters& aParms, + const CScriptGunTurretData& turretData); + + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void Touch(CActor&, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&); + void Render(const CStateManager&) const; + std::experimental::optional GetTouchBounds() const; + zeus::CVector3f GetOrbitPosition(const CStateManager&) const; + zeus::CVector3f GetAimPosition(const CStateManager&, float) const; + + CHealthInfo* HealthInfo(CStateManager&) { return &x264_healthInfo; } + const CDamageVulnerability* GetDamageVulnerability() const { return &x26c_damageVuln; } + void sub80219b18(s32, CStateManager&); + void sub8021998c(s32, CStateManager&, float); + void sub80217408(CStateManager&); + void sub802172b8(CStateManager&); + void sub80219a00(float, CStateManager&); + void sub802189c8(); + void UpdateGunCollisionManager(float, CStateManager&); + void GetUnFreezeSoundId(float, CStateManager&); + void UpdateGunParticles(float, CStateManager&); + void sub80219938(s32, CStateManager&); + void sub802196c4(s32, CStateManager&, float); + void sub802195bc(s32, CStateManager&, float); + void sub8021942c(s32, CStateManager&, float); + void sub80218f50(s32, CStateManager&, float); + void sub80218e34(s32, CStateManager&); + void sub80218bb4(s32, CStateManager&, float); + bool sub80217ad8(CStateManager&); + bool sub802179a4(CStateManager&); + void sub80217f5c(float, CStateManager&); + zeus::CVector3f sub80217e34(float); + void sub80216288(float); + void sub80217124(CStateManager&); + void sub80218830(float, CStateManager&); + void sub80216594(CStateManager&); + bool sub80217950(CStateManager&); + bool sub80217c24(float); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptHUDMemo.cpp b/Runtime/World/CScriptHUDMemo.cpp index a3925559f..810f79e43 100644 --- a/Runtime/World/CScriptHUDMemo.cpp +++ b/Runtime/World/CScriptHUDMemo.cpp @@ -5,46 +5,33 @@ #include "MP1/CSamusHud.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptHUDMemo::CScriptHUDMemo(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CHUDMemoParms& parms, EDisplayType disp, CAssetId msg, bool active) -: CEntity(uid, info, active, name) -, x34_parms(parms) -, x3c_dispType(disp) -, x40_stringTableId(msg) -{ - if (msg.IsValid()) - x44_stringTable.emplace(g_SimplePool->GetObj({FOURCC('STRG'), msg})); +: CEntity(uid, info, active, name), x34_parms(parms), x3c_dispType(disp), x40_stringTableId(msg) { + if (msg.IsValid()) + x44_stringTable.emplace(g_SimplePool->GetObj({FOURCC('STRG'), msg})); } -void CScriptHUDMemo::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptHUDMemo::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptHUDMemo::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::SetToZero) - { - if (GetActive()) - { - if (x3c_dispType == EDisplayType::MessageBox) - mgr.ShowPausedHUDMemo(x40_stringTableId, x34_parms.GetDisplayTime()); - else if (x3c_dispType == EDisplayType::StatusMessage) - { - if (x44_stringTable) - MP1::CSamusHud::DisplayHudMemo((*x44_stringTable)->GetString(0), x34_parms); - else - MP1::CSamusHud::DisplayHudMemo(u"", x34_parms); - } - } +void CScriptHUDMemo::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::SetToZero) { + if (GetActive()) { + if (x3c_dispType == EDisplayType::MessageBox) + mgr.ShowPausedHUDMemo(x40_stringTableId, x34_parms.GetDisplayTime()); + else if (x3c_dispType == EDisplayType::StatusMessage) { + if (x44_stringTable) + MP1::CSamusHud::DisplayHudMemo((*x44_stringTable)->GetString(0), x34_parms); + else + MP1::CSamusHud::DisplayHudMemo(u"", x34_parms); + } } - else if (msg == EScriptObjectMessage::Deactivate && GetActive() && x3c_dispType == EDisplayType::StatusMessage) - MP1::CSamusHud::DisplayHudMemo(u"", CHUDMemoParms(0.f, false, true, false)); + } else if (msg == EScriptObjectMessage::Deactivate && GetActive() && x3c_dispType == EDisplayType::StatusMessage) + MP1::CSamusHud::DisplayHudMemo(u"", CHUDMemoParms(0.f, false, true, false)); - CEntity::AcceptScriptMsg(msg, uid, mgr); + CEntity::AcceptScriptMsg(msg, uid, mgr); } -} +} // namespace urde diff --git a/Runtime/World/CScriptHUDMemo.hpp b/Runtime/World/CScriptHUDMemo.hpp index 446941e4b..346af18f5 100644 --- a/Runtime/World/CScriptHUDMemo.hpp +++ b/Runtime/World/CScriptHUDMemo.hpp @@ -3,28 +3,25 @@ #include "CEntity.hpp" #include "CHUDMemoParms.hpp" #include "CToken.hpp" -namespace urde -{ +namespace urde { class CStringTable; -class CScriptHUDMemo : public CEntity -{ +class CScriptHUDMemo : public CEntity { public: - enum class EDisplayType - { - StatusMessage, - MessageBox, - }; - CHUDMemoParms x34_parms; - EDisplayType x3c_dispType; - CAssetId x40_stringTableId; - std::experimental::optional> x44_stringTable; + enum class EDisplayType { + StatusMessage, + MessageBox, + }; + CHUDMemoParms x34_parms; + EDisplayType x3c_dispType; + CAssetId x40_stringTableId; + std::experimental::optional> x44_stringTable; + private: public: - CScriptHUDMemo(TUniqueId, std::string_view, const CEntityInfo&, const CHUDMemoParms&, - CScriptHUDMemo::EDisplayType, CAssetId, bool); + CScriptHUDMemo(TUniqueId, std::string_view, const CEntityInfo&, const CHUDMemoParms&, CScriptHUDMemo::EDisplayType, + CAssetId, bool); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptMazeNode.cpp b/Runtime/World/CScriptMazeNode.cpp index 2394bda9a..33732fa0d 100644 --- a/Runtime/World/CScriptMazeNode.cpp +++ b/Runtime/World/CScriptMazeNode.cpp @@ -4,8 +4,7 @@ #include "CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { atUint32 CScriptMazeNode::sMazeSeeds[300] = {0}; @@ -19,23 +18,18 @@ CScriptMazeNode::CScriptMazeNode(TUniqueId uid, std::string_view name, const CEn , xf0_(w2) , x100_(vec1) , x110_(vec2) -, x120_(vec3) -{ - x13c_24_ = true; +, x120_(vec3) { + x13c_24_ = true; } -void CScriptMazeNode::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptMazeNode::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptMazeNode::LoadMazeSeeds() -{ - const SObjectTag* tag = g_ResFactory->GetResourceIdByName("DUMB_MazeSeeds"); - u32 resSize = g_ResFactory->ResourceSize(*tag); - std::unique_ptr buf = g_ResFactory->LoadResourceSync(*tag); - CMemoryInStream in(buf.get(), resSize); - for (u32 i = 0; i<300 ; ++i) - sMazeSeeds[i] = in.readUint32Big(); -} +void CScriptMazeNode::LoadMazeSeeds() { + const SObjectTag* tag = g_ResFactory->GetResourceIdByName("DUMB_MazeSeeds"); + u32 resSize = g_ResFactory->ResourceSize(*tag); + std::unique_ptr buf = g_ResFactory->LoadResourceSync(*tag); + CMemoryInStream in(buf.get(), resSize); + for (u32 i = 0; i < 300; ++i) + sMazeSeeds[i] = in.readUint32Big(); } +} // namespace urde diff --git a/Runtime/World/CScriptMazeNode.hpp b/Runtime/World/CScriptMazeNode.hpp index 70ee7ba15..9bb18f724 100644 --- a/Runtime/World/CScriptMazeNode.hpp +++ b/Runtime/World/CScriptMazeNode.hpp @@ -2,41 +2,37 @@ #include "CActor.hpp" -namespace urde -{ -class CScriptMazeNode : public CActor -{ - static u32 sMazeSeeds[300]; - s32 xe8_; - s32 xec_; - s32 xf0_; - TUniqueId xf4_ = kInvalidUniqueId; - float xf8_ = 0.f; - TUniqueId xfc_ = kInvalidUniqueId; - zeus::CVector3f x100_; - TUniqueId x10c_ = kInvalidUniqueId; - zeus::CVector3f x110_; - TUniqueId x11c_ = kInvalidUniqueId; - zeus::CVector3f x120_; - s32 x130_ = 0; - s32 x134_ = 0; - s32 x138_ = 0; - union - { - struct - { - bool x13c_24_ : 1; - bool x13c_25_ : 1; - bool x13c_26_ : 1; - }; - u8 dummy = 0; +namespace urde { +class CScriptMazeNode : public CActor { + static u32 sMazeSeeds[300]; + s32 xe8_; + s32 xec_; + s32 xf0_; + TUniqueId xf4_ = kInvalidUniqueId; + float xf8_ = 0.f; + TUniqueId xfc_ = kInvalidUniqueId; + zeus::CVector3f x100_; + TUniqueId x10c_ = kInvalidUniqueId; + zeus::CVector3f x110_; + TUniqueId x11c_ = kInvalidUniqueId; + zeus::CVector3f x120_; + s32 x130_ = 0; + s32 x134_ = 0; + s32 x138_ = 0; + union { + struct { + bool x13c_24_ : 1; + bool x13c_25_ : 1; + bool x13c_26_ : 1; }; + u8 dummy = 0; + }; + public: - CScriptMazeNode(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, s32, s32, s32, - const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&); + CScriptMazeNode(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, s32, s32, s32, + const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CVector3f&); - void Accept(IVisitor &visitor); - static void LoadMazeSeeds(); + void Accept(IVisitor& visitor); + static void LoadMazeSeeds(); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptMemoryRelay.cpp b/Runtime/World/CScriptMemoryRelay.cpp index 25607a8e1..efaca0583 100644 --- a/Runtime/World/CScriptMemoryRelay.cpp +++ b/Runtime/World/CScriptMemoryRelay.cpp @@ -3,43 +3,33 @@ #include "CRelayTracker.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptMemoryRelay::CScriptMemoryRelay(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool b1, bool skipSendActive, bool ignoreMessages) - : CEntity(uid, info, true, name), - x34_24_(b1), - x34_25_skipSendActive(skipSendActive), - x34_26_ignoreMessages(ignoreMessages) -{ +: CEntity(uid, info, true, name) +, x34_24_(b1) +, x34_25_skipSendActive(skipSendActive) +, x34_26_ignoreMessages(ignoreMessages) {} + +void CScriptMemoryRelay::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptMemoryRelay::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + if (x34_26_ignoreMessages) + return; + + if (msg == EScriptObjectMessage::Deactivate) { + stateMgr.GetRelayTracker()->RemoveRelay(xc_editorId); + return; + } else if (msg == EScriptObjectMessage::Activate) { + stateMgr.GetRelayTracker()->AddRelay(xc_editorId); + if (!x34_25_skipSendActive) + SendScriptMsgs(EScriptObjectState::Active, stateMgr, EScriptObjectMessage::None); + + return; + } + + CEntity::AcceptScriptMsg(msg, objId, stateMgr); } -void CScriptMemoryRelay::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CScriptMemoryRelay::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr) -{ - if (x34_26_ignoreMessages) - return; - - if (msg == EScriptObjectMessage::Deactivate) - { - stateMgr.GetRelayTracker()->RemoveRelay(xc_editorId); - return; - } - else if (msg == EScriptObjectMessage::Activate) - { - stateMgr.GetRelayTracker()->AddRelay(xc_editorId); - if (!x34_25_skipSendActive) - SendScriptMsgs(EScriptObjectState::Active, stateMgr, EScriptObjectMessage::None); - - return; - } - - CEntity::AcceptScriptMsg(msg, objId, stateMgr); -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptMemoryRelay.hpp b/Runtime/World/CScriptMemoryRelay.hpp index 8aaea974d..4779cacbd 100644 --- a/Runtime/World/CScriptMemoryRelay.hpp +++ b/Runtime/World/CScriptMemoryRelay.hpp @@ -2,24 +2,20 @@ #include "CEntity.hpp" -namespace urde -{ -class CScriptMemoryRelay : public CEntity -{ - union - { - struct - { - bool x34_24_; - bool x34_25_skipSendActive; - bool x34_26_ignoreMessages; - }; - u8 dummy = 0; +namespace urde { +class CScriptMemoryRelay : public CEntity { + union { + struct { + bool x34_24_; + bool x34_25_skipSendActive; + bool x34_26_ignoreMessages; }; -public: - CScriptMemoryRelay(TUniqueId, std::string_view name, const CEntityInfo&, bool, bool, bool); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); -}; -} + u8 dummy = 0; + }; +public: + CScriptMemoryRelay(TUniqueId, std::string_view name, const CEntityInfo&, bool, bool, bool); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); +}; +} // namespace urde diff --git a/Runtime/World/CScriptMidi.cpp b/Runtime/World/CScriptMidi.cpp index f720fea16..21f0b81c5 100644 --- a/Runtime/World/CScriptMidi.cpp +++ b/Runtime/World/CScriptMidi.cpp @@ -6,84 +6,69 @@ #include "MP1/CInGameGuiManager.hpp" #include "CInGameTweakManagerBase.hpp" -namespace urde -{ +namespace urde { -CScriptMidi::CScriptMidi(TUniqueId id, const CEntityInfo& info, std::string_view name, - bool active, CAssetId csng, float fadeIn, float fadeOut, s32 volume) -: CEntity(id, info, active, name), x40_fadeInTime(fadeIn), x44_fadeOutTime(fadeOut), - x48_volume(volume) -{ - x34_song = g_SimplePool->GetObj(SObjectTag{FOURCC('CSNG'), csng}); +CScriptMidi::CScriptMidi(TUniqueId id, const CEntityInfo& info, std::string_view name, bool active, CAssetId csng, + float fadeIn, float fadeOut, s32 volume) +: CEntity(id, info, active, name), x40_fadeInTime(fadeIn), x44_fadeOutTime(fadeOut), x48_volume(volume) { + x34_song = g_SimplePool->GetObj(SObjectTag{FOURCC('CSNG'), csng}); } -void CScriptMidi::StopInternal(float fadeTime) -{ - if (x3c_handle) - { - CMidiManager::Stop(x3c_handle, fadeTime); - x3c_handle.reset(); - } +void CScriptMidi::StopInternal(float fadeTime) { + if (x3c_handle) { + CMidiManager::Stop(x3c_handle, fadeTime); + x3c_handle.reset(); + } } -void CScriptMidi::Stop(CStateManager& mgr, float fadeTime) -{ - const CWorld* wld = mgr.GetWorld(); - const CGameArea* area = wld->GetAreaAlways(x4_areaId); - std::string twkName = CInGameTweakManagerBase::GetIdentifierForMidiEvent(wld->IGetWorldAssetId(), - area->GetAreaAssetId(), - x10_name); - if (g_TweakManager->HasTweakValue(twkName)) - { - const CTweakValue::Audio& audio = g_TweakManager->GetTweakValue(twkName)->GetAudio(); - fadeTime = audio.GetFadeOut(); - } +void CScriptMidi::Stop(CStateManager& mgr, float fadeTime) { + const CWorld* wld = mgr.GetWorld(); + const CGameArea* area = wld->GetAreaAlways(x4_areaId); + std::string twkName = + CInGameTweakManagerBase::GetIdentifierForMidiEvent(wld->IGetWorldAssetId(), area->GetAreaAssetId(), x10_name); + if (g_TweakManager->HasTweakValue(twkName)) { + const CTweakValue::Audio& audio = g_TweakManager->GetTweakValue(twkName)->GetAudio(); + fadeTime = audio.GetFadeOut(); + } - StopInternal(fadeTime); + StopInternal(fadeTime); } -void CScriptMidi::Play(CStateManager& mgr, float fadeTime) -{ - u32 volume = x48_volume; - const CWorld* wld = mgr.GetWorld(); - const CGameArea* area = wld->GetAreaAlways(x4_areaId); - std::string twkName = CInGameTweakManagerBase::GetIdentifierForMidiEvent(wld->IGetWorldAssetId(), - area->GetAreaAssetId(), - x10_name); - if (g_TweakManager->HasTweakValue(twkName)) - { - const CTweakValue::Audio& audio = g_TweakManager->GetTweakValue(twkName)->GetAudio(); - x34_song = g_SimplePool->GetObj(SObjectTag{FOURCC('CSNG'), audio.GetResId()}); - fadeTime = audio.GetFadeIn(); - volume = audio.GetVolume() * 127.f; - } +void CScriptMidi::Play(CStateManager& mgr, float fadeTime) { + u32 volume = x48_volume; + const CWorld* wld = mgr.GetWorld(); + const CGameArea* area = wld->GetAreaAlways(x4_areaId); + std::string twkName = + CInGameTweakManagerBase::GetIdentifierForMidiEvent(wld->IGetWorldAssetId(), area->GetAreaAssetId(), x10_name); + if (g_TweakManager->HasTweakValue(twkName)) { + const CTweakValue::Audio& audio = g_TweakManager->GetTweakValue(twkName)->GetAudio(); + x34_song = g_SimplePool->GetObj(SObjectTag{FOURCC('CSNG'), audio.GetResId()}); + fadeTime = audio.GetFadeIn(); + volume = audio.GetVolume() * 127.f; + } - x3c_handle = CMidiManager::Play(*x34_song, fadeTime, false, volume / 127.f); + x3c_handle = CMidiManager::Play(*x34_song, fadeTime, false, volume / 127.f); } -void CScriptMidi::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptMidi::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptMidi::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); + switch (msg) { + case EScriptObjectMessage::Play: + if (GetActive()) + Play(stateMgr, x40_fadeInTime); + break; + case EScriptObjectMessage::Stop: + if (GetActive()) + Stop(stateMgr, x44_fadeOutTime); + break; + case EScriptObjectMessage::Deactivate: + StopInternal(0.f); + break; + default: + break; + } } -void CScriptMidi::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CEntity::AcceptScriptMsg(msg, objId, stateMgr); - switch (msg) - { - case EScriptObjectMessage::Play: - if (GetActive()) - Play(stateMgr, x40_fadeInTime); - break; - case EScriptObjectMessage::Stop: - if (GetActive()) - Stop(stateMgr, x44_fadeOutTime); - break; - case EScriptObjectMessage::Deactivate: - StopInternal(0.f); - break; - default: break; - } -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptMidi.hpp b/Runtime/World/CScriptMidi.hpp index ecbeb8669..5512c7c12 100644 --- a/Runtime/World/CScriptMidi.hpp +++ b/Runtime/World/CScriptMidi.hpp @@ -4,28 +4,25 @@ #include "CToken.hpp" #include "Audio/CMidiManager.hpp" -namespace urde -{ +namespace urde { -class CScriptMidi : public CEntity -{ - TToken x34_song; - CMidiHandle x3c_handle; - float x40_fadeInTime; - float x44_fadeOutTime; - u16 x48_volume; +class CScriptMidi : public CEntity { + TToken x34_song; + CMidiHandle x3c_handle; + float x40_fadeInTime; + float x44_fadeOutTime; + u16 x48_volume; - void StopInternal(float fadeTime); + void StopInternal(float fadeTime); public: - CScriptMidi(TUniqueId id, const CEntityInfo& info, std::string_view name, - bool active, CAssetId csng, float, float, s32); + CScriptMidi(TUniqueId id, const CEntityInfo& info, std::string_view name, bool active, CAssetId csng, float, float, + s32); - void Stop(CStateManager& mgr, float fadeTime); - void Play(CStateManager& mgr, float fadeTime); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Stop(CStateManager& mgr, float fadeTime); + void Play(CStateManager& mgr, float fadeTime); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptPickup.cpp b/Runtime/World/CScriptPickup.cpp index c66eba47c..806dc022a 100644 --- a/Runtime/World/CScriptPickup.cpp +++ b/Runtime/World/CScriptPickup.cpp @@ -12,12 +12,11 @@ #include "GuiSys/CStringTable.hpp" #include "Camera/CFirstPersonCamera.hpp" -namespace urde -{ -CScriptPickup::CScriptPickup(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& aParams, - const zeus::CAABox& aabb, CPlayerState::EItemType itemType, s32 amount, s32 capacity, - CAssetId explosionEffect, float possibility, float f2, float f3, float f4, bool active) +namespace urde { +CScriptPickup::CScriptPickup(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CActorParameters& aParams, const zeus::CAABox& aabb, + CPlayerState::EItemType itemType, s32 amount, s32 capacity, CAssetId explosionEffect, + float possibility, float f2, float f3, float f4, bool active) : CPhysicsActor(uid, active, name, info, xf, std::move(mData), CMaterialList(), aabb, SMoverData(1.f), aParams, 0.3f, 0.1f) , x258_itemType(itemType) @@ -29,172 +28,144 @@ CScriptPickup::CScriptPickup(TUniqueId uid, std::string_view name, const CEntity , x278_(f4) , x28c_24_(false) , x28c_25_(false) -, x28c_26_(false) -{ - if (explosionEffect.IsValid()) - x27c_explosionDesc = g_SimplePool->GetObj({SBIG('PART'), explosionEffect}); +, x28c_26_(false) { + if (explosionEffect.IsValid()) + x27c_explosionDesc = g_SimplePool->GetObj({SBIG('PART'), explosionEffect}); - if (x64_modelData && x64_modelData->AnimationData()) - x64_modelData->AnimationData()->SetAnimation(CAnimPlaybackParms(0, -1, 1.f, true), false); + if (x64_modelData && x64_modelData->AnimationData()) + x64_modelData->AnimationData()->SetAnimation(CAnimPlaybackParms(0, -1, 1.f, true), false); - if (x278_ != 0.f) - { - xb4_drawFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, 1.f, 1.f, 0.f)); - xb4_drawFlags.x2_flags &= 0xFFFC; - xb4_drawFlags.x2_flags |= 1; - } + if (x278_ != 0.f) { + xb4_drawFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, 1.f, 1.f, 0.f)); + xb4_drawFlags.x2_flags &= 0xFFFC; + xb4_drawFlags.x2_flags |= 1; + } } void CScriptPickup::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptPickup::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; +void CScriptPickup::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; - if (x278_ >= 0.f) - { - CPhysicsActor::Stop(); - x278_ -= dt; - return; + if (x278_ >= 0.f) { + CPhysicsActor::Stop(); + x278_ -= dt; + return; + } + + x270_ += dt; + if (x28c_25_ && (x270_ - x26c_) < 2.f) + x270_ = zeus::max(2.f * dt - x270_, (2.f - x26c_) - FLT_EPSILON); + + CModelFlags drawFlags{0, 0, 3, zeus::CColor(1.f, 1.f, 1.f, 1.f)}; + + if (x268_ != 0.f) { + if (x270_ < x268_) { + drawFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, 1.f, x270_ / x268_)); + drawFlags.x2_flags &= 0xFFFC; + drawFlags.x2_flags |= 1; + } else + x268_ = 0.f; + } else if (x26c_ != 0.f) { + float alpha = 1.f; + if (x26c_ < 2.f) + alpha = 1.f - (x26c_ / x270_); + else if ((x270_ - x26c_) < 2.f) + alpha = (x270_ - x26c_) * 0.5f; + + drawFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, 1.f, 1.f, alpha)); + drawFlags.x2_flags &= 0xFFFC; + drawFlags.x2_flags |= 1; + } + + xb4_drawFlags = drawFlags; + + if (x64_modelData) { + if (x64_modelData->HasAnimData()) { + SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); + MoveToOR(deltas.x0_posDelta, dt); + RotateToOR(deltas.xc_rotDelta, dt); } - x270_ += dt; - if (x28c_25_ && (x270_ - x26c_) < 2.f) - x270_ = zeus::max(2.f * dt - x270_, (2.f - x26c_) - FLT_EPSILON); + if (x28c_25_) { + zeus::CVector3f posVec = GetTranslation() - mgr.GetPlayer().GetTranslation() + (2.f * zeus::CVector3f::skUp); + posVec = (20.f * (0.5f * zeus::max(2.f, x274_ + dt))) * posVec.normalized(); - CModelFlags drawFlags{0, 0, 3, zeus::CColor(1.f, 1.f, 1.f, 1.f)}; + float chargeFactor = 0.f; + if (x28c_26_ && mgr.GetPlayer().GetPlayerGun()->IsCharging()) + chargeFactor = mgr.GetPlayer().GetPlayerGun()->GetChargeBeamFactor(); - if (x268_ != 0.f) - { - if (x270_ < x268_) - { - drawFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, 1.f, x270_ / x268_)); - drawFlags.x2_flags &= 0xFFFC; - drawFlags.x2_flags |= 1; + if (chargeFactor < CPlayerGun::skTractorBeamFactor) { + x28c_26_ = false; + x28c_25_ = false; + posVec.zeroOut(); + } + SetVelocityOR(posVec); + } else if (x28c_24_) { + float chargeFactor = + mgr.GetPlayer().GetPlayerGun()->IsCharging() ? mgr.GetPlayer().GetPlayerGun()->GetChargeBeamFactor() : 0.f; + + if (chargeFactor > CPlayerGun::skTractorBeamFactor) { + zeus::CVector3f posVec = + (GetTranslation() - mgr.GetCameraManager()->GetFirstPersonCamera()->GetTranslation()).normalized(); + float relFov = zeus::CRelAngle(zeus::degToRad(g_tweakGame->GetFirstPersonFOV())); + if (mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform().upVector().dot(posVec) > std::cos(relFov) && + posVec.magSquared() < (30.f * 30.f)) { + x28c_25_ = true; + x28c_26_ = true; + x274_ = 0.f; } - else - x268_ = 0.f; + } } - else if (x26c_ != 0.f) - { - float alpha = 1.f; - if (x26c_ < 2.f) - alpha = 1.f - (x26c_ / x270_); - else if ((x270_ - x26c_) < 2.f) - alpha = (x270_ - x26c_) * 0.5f; - - drawFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, 1.f, 1.f, alpha)); - drawFlags.x2_flags &= 0xFFFC; - drawFlags.x2_flags |= 1; - } - - xb4_drawFlags = drawFlags; - - if (x64_modelData) - { - if (x64_modelData->HasAnimData()) - { - SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); - MoveToOR(deltas.x0_posDelta, dt); - RotateToOR(deltas.xc_rotDelta, dt); - } - - if (x28c_25_) - { - zeus::CVector3f posVec = - GetTranslation() - mgr.GetPlayer().GetTranslation() + (2.f * zeus::CVector3f::skUp); - posVec = (20.f * (0.5f * zeus::max(2.f, x274_ + dt))) * posVec.normalized(); - - float chargeFactor = 0.f; - if (x28c_26_ && mgr.GetPlayer().GetPlayerGun()->IsCharging()) - chargeFactor = mgr.GetPlayer().GetPlayerGun()->GetChargeBeamFactor(); - - if (chargeFactor < CPlayerGun::skTractorBeamFactor) - { - x28c_26_ = false; - x28c_25_ = false; - posVec.zeroOut(); - } - SetVelocityOR(posVec); - } - else if (x28c_24_) - { - float chargeFactor = mgr.GetPlayer().GetPlayerGun()->IsCharging() - ? mgr.GetPlayer().GetPlayerGun()->GetChargeBeamFactor() - : 0.f; - - if (chargeFactor > CPlayerGun::skTractorBeamFactor) - { - zeus::CVector3f posVec = - (GetTranslation() - mgr.GetCameraManager()->GetFirstPersonCamera()->GetTranslation()).normalized(); - float relFov = zeus::CRelAngle(zeus::degToRad(g_tweakGame->GetFirstPersonFOV())); - if (mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform().upVector().dot(posVec) > - std::cos(relFov) && posVec.magSquared() < (30.f * 30.f)) - { - x28c_25_ = true; - x28c_26_ = true; - x274_ = 0.f; - } - } - } - } - - if (x26c_ != 0.f && x270_ > x26c_) - mgr.FreeScriptObject(GetUniqueId()); + } + if (x26c_ != 0.f && x270_ > x26c_) + mgr.FreeScriptObject(GetUniqueId()); } -void CScriptPickup::Touch(CActor& act, CStateManager& mgr) -{ - if (GetActive() && x278_ < 0.f && TCastToPtr(act)) - { - if (x258_itemType >= CPlayerState::EItemType::Truth && x258_itemType <= CPlayerState::EItemType::Newborn) - { - CAssetId id = MP1::CArtifactDoll::GetArtifactHeadScanFromItemType(x258_itemType); - if (id.IsValid()) - mgr.GetPlayerState()->SetScanTime(id, 0.5f); - } - - if (x27c_explosionDesc) - { - if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal) - { - mgr.AddObject(new CExplosion( - x27c_explosionDesc, mgr.AllocateUniqueId(), true, - CEntityInfo(GetAreaIdAlways(), CEntity::NullConnectionList, kInvalidEditorId), - "Explosion - Pickup Effect", x34_transform, 0, zeus::CVector3f::skOne, zeus::CColor::skWhite)); - } - } - - mgr.GetPlayerState()->InitializePowerUp(x258_itemType, x260_capacity); - mgr.GetPlayerState()->IncrPickup(x258_itemType, x25c_amount); - mgr.FreeScriptObject(GetUniqueId()); - SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); - - if (x260_capacity > 0) - { - u32 total = mgr.GetPlayerState()->GetPickupTotal(); - u32 colRate = mgr.GetPlayerState()->CalculateItemCollectionRate(); - if (total == colRate) - { - CPersistentOptions& opts = g_GameState->SystemOptions(); - mgr.QueueMessage(mgr.GetHUDMessageFrameCount() + 1, - g_ResFactory - ->GetResourceIdByName(opts.GetAllItemsCollected() ? "STRG_AllPickupsFound_2" - : "STRG_AllPickupsFound_1") - ->id, - 0.f); - opts.SetAllItemsCollected(true); - } - } - - if (x258_itemType == CPlayerState::EItemType::PowerBombs && - g_GameState->SystemOptions().GetShowPowerBombAmmoMessage()) - { - g_GameState->SystemOptions().IncrementPowerBombAmmoCount(); - MP1::CSamusHud::DisplayHudMemo(g_MainStringTable->GetString(109), {0.5f, true, false, false}); - } +void CScriptPickup::Touch(CActor& act, CStateManager& mgr) { + if (GetActive() && x278_ < 0.f && TCastToPtr(act)) { + if (x258_itemType >= CPlayerState::EItemType::Truth && x258_itemType <= CPlayerState::EItemType::Newborn) { + CAssetId id = MP1::CArtifactDoll::GetArtifactHeadScanFromItemType(x258_itemType); + if (id.IsValid()) + mgr.GetPlayerState()->SetScanTime(id, 0.5f); } + + if (x27c_explosionDesc) { + if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Thermal) { + mgr.AddObject(new CExplosion(x27c_explosionDesc, mgr.AllocateUniqueId(), true, + CEntityInfo(GetAreaIdAlways(), CEntity::NullConnectionList, kInvalidEditorId), + "Explosion - Pickup Effect", x34_transform, 0, zeus::CVector3f::skOne, + zeus::CColor::skWhite)); + } + } + + mgr.GetPlayerState()->InitializePowerUp(x258_itemType, x260_capacity); + mgr.GetPlayerState()->IncrPickup(x258_itemType, x25c_amount); + mgr.FreeScriptObject(GetUniqueId()); + SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); + + if (x260_capacity > 0) { + u32 total = mgr.GetPlayerState()->GetPickupTotal(); + u32 colRate = mgr.GetPlayerState()->CalculateItemCollectionRate(); + if (total == colRate) { + CPersistentOptions& opts = g_GameState->SystemOptions(); + mgr.QueueMessage( + mgr.GetHUDMessageFrameCount() + 1, + g_ResFactory + ->GetResourceIdByName(opts.GetAllItemsCollected() ? "STRG_AllPickupsFound_2" : "STRG_AllPickupsFound_1") + ->id, + 0.f); + opts.SetAllItemsCollected(true); + } + } + + if (x258_itemType == CPlayerState::EItemType::PowerBombs && + g_GameState->SystemOptions().GetShowPowerBombAmmoMessage()) { + g_GameState->SystemOptions().IncrementPowerBombAmmoCount(); + MP1::CSamusHud::DisplayHudMemo(g_MainStringTable->GetString(109), {0.5f, true, false, false}); + } + } } -} +} // namespace urde diff --git a/Runtime/World/CScriptPickup.hpp b/Runtime/World/CScriptPickup.hpp index 5b99260b3..a2f84ade6 100644 --- a/Runtime/World/CScriptPickup.hpp +++ b/Runtime/World/CScriptPickup.hpp @@ -3,39 +3,33 @@ #include "CPhysicsActor.hpp" #include "CPlayerState.hpp" -namespace urde -{ -class CScriptPickup : public CPhysicsActor -{ - CPlayerState::EItemType x258_itemType; - u32 x25c_amount; - u32 x260_capacity; - float x264_possibility; - float x268_; - float x26c_; - float x270_ = 0.f; - float x274_; - float x278_; - TLockedToken x27c_explosionDesc; +namespace urde { +class CScriptPickup : public CPhysicsActor { + CPlayerState::EItemType x258_itemType; + u32 x25c_amount; + u32 x260_capacity; + float x264_possibility; + float x268_; + float x26c_; + float x270_ = 0.f; + float x274_; + float x278_; + TLockedToken x27c_explosionDesc; - u8 x28c_24_ : 1; - u8 x28c_25_ : 1; - u8 x28c_26_ : 1; + u8 x28c_24_ : 1; + u8 x28c_25_ : 1; + u8 x28c_26_ : 1; public: - CScriptPickup(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, - const CActorParameters&, const zeus::CAABox&, CPlayerState::EItemType, s32, s32, CAssetId, float, - float, float, float, bool); + CScriptPickup(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, + const CActorParameters&, const zeus::CAABox&, CPlayerState::EItemType, s32, s32, CAssetId, float, float, + float, float, bool); - void Accept(IVisitor& visitor); - void Think(float, CStateManager&); - void Touch(CActor &, CStateManager &); - std::experimental::optional GetTouchBounds() const - { - return CPhysicsActor::GetBoundingBox(); - } - float GetPossibility() const { return x264_possibility; } - CPlayerState::EItemType GetItem() { return x258_itemType; } + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void Touch(CActor&, CStateManager&); + std::experimental::optional GetTouchBounds() const { return CPhysicsActor::GetBoundingBox(); } + float GetPossibility() const { return x264_possibility; } + CPlayerState::EItemType GetItem() { return x258_itemType; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptPickupGenerator.cpp b/Runtime/World/CScriptPickupGenerator.cpp index cae1df597..fd847e128 100644 --- a/Runtime/World/CScriptPickupGenerator.cpp +++ b/Runtime/World/CScriptPickupGenerator.cpp @@ -1,39 +1,29 @@ #include "CScriptPickupGenerator.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptPickupGenerator::CScriptPickupGenerator(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, float frequency, bool active) -: CEntity(uid, info, active, name), x34_position(pos), x40_frequency(frequency) -{ -} +: CEntity(uid, info, active, name), x34_position(pos), x40_frequency(frequency) {} -void CScriptPickupGenerator::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptPickupGenerator::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptPickupGenerator::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - if (msg == EScriptObjectMessage::SetToZero && x30_24_active && x44_ != 100.f) - { - x44_ -= 1.f; - if (x44_ < 0.000009f) - sub8015E220(); - else - { - } +void CScriptPickupGenerator::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + if (msg == EScriptObjectMessage::SetToZero && x30_24_active && x44_ != 100.f) { + x44_ -= 1.f; + if (x44_ < 0.000009f) + sub8015E220(); + else { } + } - CEntity::AcceptScriptMsg(msg, objId, stateMgr); + CEntity::AcceptScriptMsg(msg, objId, stateMgr); } -void CScriptPickupGenerator::sub8015E220() -{ - if (x40_frequency > 0.f) - x44_ = (100.f / x40_frequency) + 100.f; - else - x44_ = std::numeric_limits::max(); -} +void CScriptPickupGenerator::sub8015E220() { + if (x40_frequency > 0.f) + x44_ = (100.f / x40_frequency) + 100.f; + else + x44_ = std::numeric_limits::max(); } +} // namespace urde diff --git a/Runtime/World/CScriptPickupGenerator.hpp b/Runtime/World/CScriptPickupGenerator.hpp index 45db034c0..78753533a 100644 --- a/Runtime/World/CScriptPickupGenerator.hpp +++ b/Runtime/World/CScriptPickupGenerator.hpp @@ -3,18 +3,17 @@ #include "CEntity.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ -class CScriptPickupGenerator : public CEntity -{ - zeus::CVector3f x34_position; - float x40_frequency; - float x44_ = 0.f; - void sub8015E220(); -public: - CScriptPickupGenerator(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CVector3f&, float, bool); +namespace urde { +class CScriptPickupGenerator : public CEntity { + zeus::CVector3f x34_position; + float x40_frequency; + float x44_ = 0.f; + void sub8015E220(); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); +public: + CScriptPickupGenerator(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CVector3f&, float, bool); + + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); }; -} +} // namespace urde diff --git a/Runtime/World/CScriptPlatform.cpp b/Runtime/World/CScriptPlatform.cpp index 061271ad0..b1fe812f3 100644 --- a/Runtime/World/CScriptPlatform.cpp +++ b/Runtime/World/CScriptPlatform.cpp @@ -11,619 +11,514 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -static CMaterialList MakePlatformMaterialList() -{ - CMaterialList ret; - ret.Add(EMaterialTypes::Solid); - ret.Add(EMaterialTypes::Immovable); - ret.Add(EMaterialTypes::Platform); - ret.Add(EMaterialTypes::Occluder); - return ret; +static CMaterialList MakePlatformMaterialList() { + CMaterialList ret; + ret.Add(EMaterialTypes::Solid); + ret.Add(EMaterialTypes::Immovable); + ret.Add(EMaterialTypes::Platform); + ret.Add(EMaterialTypes::Occluder); + return ret; } -CScriptPlatform::CScriptPlatform(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, - const zeus::CAABox& aabb, float speed, bool detectCollision, float xrayAlpha, - bool active, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, - const std::experimental::optional>& dcln, - bool rainSplashes, u32 maxRainSplashes, u32 rainGenRate) +CScriptPlatform::CScriptPlatform( + TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, + const CActorParameters& actParms, const zeus::CAABox& aabb, float speed, bool detectCollision, float xrayAlpha, + bool active, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, + const std::experimental::optional>& dcln, bool rainSplashes, + u32 maxRainSplashes, u32 rainGenRate) : CPhysicsActor(uid, active, name, info, xf, std::move(mData), MakePlatformMaterialList(), aabb, SMoverData(15000.f), actParms, 0.3f, 0.1f) , x25c_currentSpeed(speed) , x28c_initialHealth(hInfo) , x294_health(hInfo) , x29c_damageVuln(dVuln) -, x304_treeGroupContainer(dcln) -{ - x348_xrayAlpha = xrayAlpha; - x34c_maxRainSplashes = maxRainSplashes; - x350_rainGenRate = rainGenRate; - x356_24_dead = false;; - x356_25_notAnimating = false; - x356_26_detectCollision = detectCollision; - x356_27_squishedRider = false; - x356_28_rainSplashes = rainSplashes; - x356_29_setXrayDrawFlags = false; - x356_30_disableXrayAlpha = false; - x356_31_xrayFog = true; - CActor::SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( - CMaterialList(EMaterialTypes::Solid), - CMaterialList(EMaterialTypes::NoStaticCollision, EMaterialTypes::NoPlatformCollision, EMaterialTypes::Platform))); - xf8_24_movable = false; - if (HasModelData() && ModelData()->HasAnimData()) - ModelData()->AnimationData()->EnableLooping(true); - if (x304_treeGroupContainer) - x314_treeGroup = std::make_unique(x304_treeGroupContainer->GetObj(), x68_material); +, x304_treeGroupContainer(dcln) { + x348_xrayAlpha = xrayAlpha; + x34c_maxRainSplashes = maxRainSplashes; + x350_rainGenRate = rainGenRate; + x356_24_dead = false; + ; + x356_25_notAnimating = false; + x356_26_detectCollision = detectCollision; + x356_27_squishedRider = false; + x356_28_rainSplashes = rainSplashes; + x356_29_setXrayDrawFlags = false; + x356_30_disableXrayAlpha = false; + x356_31_xrayFog = true; + CActor::SetMaterialFilter(CMaterialFilter::MakeIncludeExclude( + CMaterialList(EMaterialTypes::Solid), + CMaterialList(EMaterialTypes::NoStaticCollision, EMaterialTypes::NoPlatformCollision, EMaterialTypes::Platform))); + xf8_24_movable = false; + if (HasModelData() && ModelData()->HasAnimData()) + ModelData()->AnimationData()->EnableLooping(true); + if (x304_treeGroupContainer) + x314_treeGroup = std::make_unique(x304_treeGroupContainer->GetObj(), x68_material); } void CScriptPlatform::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptPlatform::DragSlave(CStateManager& mgr, rstl::reserved_vector& draggedSet, - CActor* actor, const zeus::CVector3f& delta) -{ - if (std::find(draggedSet.begin(), draggedSet.end(), actor->GetUniqueId().Value()) == draggedSet.end()) - { - draggedSet.push_back(actor->GetUniqueId().Value()); - zeus::CTransform newXf = actor->GetTransform(); - newXf.origin += delta; - actor->SetTransform(newXf); - if (TCastToPtr plat = actor) - plat->DragSlaves(mgr, draggedSet, delta); - } +void CScriptPlatform::DragSlave(CStateManager& mgr, rstl::reserved_vector& draggedSet, CActor* actor, + const zeus::CVector3f& delta) { + if (std::find(draggedSet.begin(), draggedSet.end(), actor->GetUniqueId().Value()) == draggedSet.end()) { + draggedSet.push_back(actor->GetUniqueId().Value()); + zeus::CTransform newXf = actor->GetTransform(); + newXf.origin += delta; + actor->SetTransform(newXf); + if (TCastToPtr plat = actor) + plat->DragSlaves(mgr, draggedSet, delta); + } } void CScriptPlatform::DragSlaves(CStateManager& mgr, rstl::reserved_vector& draggedSet, - const zeus::CVector3f& delta) -{ - for (SRiders& rider : x328_slavesStatic) - if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) - DragSlave(mgr, draggedSet, act.GetPtr(), delta); - for (auto it = x338_slavesDynamic.begin() ; it != x338_slavesDynamic.end() ;) - { - if (TCastToPtr act = mgr.ObjectById(it->x0_uid)) - { - DragSlave(mgr, draggedSet, act.GetPtr(), delta); - ++it; - } - else - it = x338_slavesDynamic.erase(it); - } + const zeus::CVector3f& delta) { + for (SRiders& rider : x328_slavesStatic) + if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) + DragSlave(mgr, draggedSet, act.GetPtr(), delta); + for (auto it = x338_slavesDynamic.begin(); it != x338_slavesDynamic.end();) { + if (TCastToPtr act = mgr.ObjectById(it->x0_uid)) { + DragSlave(mgr, draggedSet, act.GetPtr(), delta); + ++it; + } else + it = x338_slavesDynamic.erase(it); + } } -void CScriptPlatform::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - switch(msg) - { - case EScriptObjectMessage::InitializedInArea: - BuildSlaveList(mgr); - break; - case EScriptObjectMessage::AddPlatformRider: - AddRider(x318_riders, uid, this, mgr); - break; - case EScriptObjectMessage::Stop: - { - x25c_currentSpeed = 0.f; - Stop(); - break; - } - case EScriptObjectMessage::Next: - { - x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr); - if (x25a_targetWaypoint == kInvalidUniqueId) - mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop); - else if (TCastToPtr wp = mgr.ObjectById(x25a_targetWaypoint)) - { - x25c_currentSpeed = 0.f; - Stop(); - x270_dragDelta = wp->GetTranslation() - GetTranslation(); - SetTranslation(wp->GetTranslation()); +void CScriptPlatform::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::InitializedInArea: + BuildSlaveList(mgr); + break; + case EScriptObjectMessage::AddPlatformRider: + AddRider(x318_riders, uid, this, mgr); + break; + case EScriptObjectMessage::Stop: { + x25c_currentSpeed = 0.f; + Stop(); + break; + } + case EScriptObjectMessage::Next: { + x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr); + if (x25a_targetWaypoint == kInvalidUniqueId) + mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop); + else if (TCastToPtr wp = mgr.ObjectById(x25a_targetWaypoint)) { + x25c_currentSpeed = 0.f; + Stop(); + x270_dragDelta = wp->GetTranslation() - GetTranslation(); + SetTranslation(wp->GetTranslation()); - x258_currentWaypoint = x25a_targetWaypoint; - x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr); - mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived); - if (!x328_slavesStatic.empty() || !x338_slavesDynamic.empty()) - { - rstl::reserved_vector draggedSet; - DragSlaves(mgr, draggedSet, x270_dragDelta); - } - x270_dragDelta = zeus::CVector3f::skZero; - } - break; - } - case EScriptObjectMessage::Start: - { - x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr); - if (x25a_targetWaypoint == kInvalidUniqueId) - mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop); - else if (TCastToPtr wp = mgr.ObjectById(x25a_targetWaypoint)) - x25c_currentSpeed = wp->GetSpeed(); - break; - } - case EScriptObjectMessage::Reset: - { - x356_24_dead = false; - x294_health = x28c_initialHealth; - break; - } - case EScriptObjectMessage::Increment: - { - if (GetActive()) - CScriptColorModulate::FadeInHelper(mgr, GetUniqueId(), x268_fadeInTime); - else - mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Activate); - break; - } - case EScriptObjectMessage::Decrement: - CScriptColorModulate::FadeOutHelper(mgr, GetUniqueId(), x26c_fadeOutTime); - break; - case EScriptObjectMessage::Deleted: - DecayRiders(x318_riders, 0.f, mgr); - break; - default: - break; + x258_currentWaypoint = x25a_targetWaypoint; + x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr); + mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived); + if (!x328_slavesStatic.empty() || !x338_slavesDynamic.empty()) { + rstl::reserved_vector draggedSet; + DragSlaves(mgr, draggedSet, x270_dragDelta); + } + x270_dragDelta = zeus::CVector3f::skZero; } + break; + } + case EScriptObjectMessage::Start: { + x25a_targetWaypoint = GetNext(x258_currentWaypoint, mgr); + if (x25a_targetWaypoint == kInvalidUniqueId) + mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop); + else if (TCastToPtr wp = mgr.ObjectById(x25a_targetWaypoint)) + x25c_currentSpeed = wp->GetSpeed(); + break; + } + case EScriptObjectMessage::Reset: { + x356_24_dead = false; + x294_health = x28c_initialHealth; + break; + } + case EScriptObjectMessage::Increment: { + if (GetActive()) + CScriptColorModulate::FadeInHelper(mgr, GetUniqueId(), x268_fadeInTime); + else + mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Activate); + break; + } + case EScriptObjectMessage::Decrement: + CScriptColorModulate::FadeOutHelper(mgr, GetUniqueId(), x26c_fadeOutTime); + break; + case EScriptObjectMessage::Deleted: + DecayRiders(x318_riders, 0.f, mgr); + break; + default: + break; + } - CPhysicsActor::AcceptScriptMsg(msg, uid, mgr); + CPhysicsActor::AcceptScriptMsg(msg, uid, mgr); } -void CScriptPlatform::DecayRiders(std::vector& riders, float dt, CStateManager& mgr) -{ - for (auto it = riders.begin() ; it != riders.end() ;) - { - it->x4_decayTimer -= dt; - if (it->x4_decayTimer <= 0.f) - { - mgr.SendScriptMsgAlways(it->x0_uid, kInvalidUniqueId, EScriptObjectMessage::AddPlatformRider); - it = riders.erase(it); - continue; - } - ++it; +void CScriptPlatform::DecayRiders(std::vector& riders, float dt, CStateManager& mgr) { + for (auto it = riders.begin(); it != riders.end();) { + it->x4_decayTimer -= dt; + if (it->x4_decayTimer <= 0.f) { + mgr.SendScriptMsgAlways(it->x0_uid, kInvalidUniqueId, EScriptObjectMessage::AddPlatformRider); + it = riders.erase(it); + continue; } + ++it; + } } void CScriptPlatform::MoveRiders(CStateManager& mgr, float dt, bool active, std::vector& riders, std::vector& collidedRiders, const zeus::CTransform& oldXf, const zeus::CTransform& newXf, const zeus::CVector3f& dragDelta, - const zeus::CQuaternion& rotDelta) -{ - for (auto it = riders.begin() ; it != riders.end() ;) - { - if (active) - { - if (TCastToPtr act = mgr.ObjectById(it->x0_uid)) - { - if (act->GetActive()) - { - zeus::CVector3f delta = newXf.rotate(it->x8_transform.origin) - - oldXf.rotate(it->x8_transform.origin) + dragDelta; - zeus::CVector3f newPos = act->GetTranslation() + delta; - act->MoveCollisionPrimitive(delta); - bool collision = CGameCollision::DetectStaticCollisionBoolean(mgr, *act->GetCollisionPrimitive(), - act->GetPrimitiveTransform(), - act->GetMaterialFilter()); - act->MoveCollisionPrimitive(zeus::CVector3f::skZero); - if (collision) - { - AddRider(collidedRiders, act->GetUniqueId(), act.GetPtr(), mgr); - it = riders.erase(it); - continue; - } - act->SetTranslation(newPos); - if (TCastToPtr player = act.GetPtr()) - { - if (player->GetOrbitState() != CPlayer::EPlayerOrbitState::NoOrbit) - { - ++it; - continue; - } - } - zeus::CTransform xf = (rotDelta * zeus::CQuaternion(act->GetTransform().basis)).toTransform(); - xf.origin = act->GetTranslation(); - act->SetTransform(xf); - } + const zeus::CQuaternion& rotDelta) { + for (auto it = riders.begin(); it != riders.end();) { + if (active) { + if (TCastToPtr act = mgr.ObjectById(it->x0_uid)) { + if (act->GetActive()) { + zeus::CVector3f delta = + newXf.rotate(it->x8_transform.origin) - oldXf.rotate(it->x8_transform.origin) + dragDelta; + zeus::CVector3f newPos = act->GetTranslation() + delta; + act->MoveCollisionPrimitive(delta); + bool collision = CGameCollision::DetectStaticCollisionBoolean( + mgr, *act->GetCollisionPrimitive(), act->GetPrimitiveTransform(), act->GetMaterialFilter()); + act->MoveCollisionPrimitive(zeus::CVector3f::skZero); + if (collision) { + AddRider(collidedRiders, act->GetUniqueId(), act.GetPtr(), mgr); + it = riders.erase(it); + continue; + } + act->SetTranslation(newPos); + if (TCastToPtr player = act.GetPtr()) { + if (player->GetOrbitState() != CPlayer::EPlayerOrbitState::NoOrbit) { + ++it; + continue; } + } + zeus::CTransform xf = (rotDelta * zeus::CQuaternion(act->GetTransform().basis)).toTransform(); + xf.origin = act->GetTranslation(); + act->SetTransform(xf); } - ++it; + } } + ++it; + } } -rstl::reserved_vector CScriptPlatform::BuildNearListFromRiders - (CStateManager& mgr, const std::vector& movedRiders) -{ - rstl::reserved_vector ret; - for (const SRiders& rider : movedRiders) - if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) - ret.push_back(act->GetUniqueId()); - return ret; +rstl::reserved_vector +CScriptPlatform::BuildNearListFromRiders(CStateManager& mgr, const std::vector& movedRiders) { + rstl::reserved_vector ret; + for (const SRiders& rider : movedRiders) + if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) + ret.push_back(act->GetUniqueId()); + return ret; } -void CScriptPlatform::PreThink(float dt, CStateManager& mgr) -{ - DecayRiders(x318_riders, dt, mgr); - x264_collisionRecoverDelay -= dt; - x260_moveDelay -= dt; - if (x260_moveDelay <= 0.f) - { +void CScriptPlatform::PreThink(float dt, CStateManager& mgr) { + DecayRiders(x318_riders, dt, mgr); + x264_collisionRecoverDelay -= dt; + x260_moveDelay -= dt; + if (x260_moveDelay <= 0.f) { + x270_dragDelta = zeus::CVector3f::skZero; + zeus::CTransform oldXf = x34_transform; + CMotionState mState = GetMotionState(); + if (GetActive()) { + for (SRiders& rider : x318_riders) + if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) + rider.x8_transform.origin = x34_transform.transposeRotate(act->GetTranslation() - GetTranslation()); + x27c_rotDelta = Move(dt, mgr); + } + + x270_dragDelta = x34_transform.origin - oldXf.origin; + + std::vector collidedRiders; + MoveRiders(mgr, dt, GetActive(), x318_riders, collidedRiders, oldXf, x34_transform, x270_dragDelta, x27c_rotDelta); + x356_27_squishedRider = false; + if (!collidedRiders.empty()) { + rstl::reserved_vector nearList = BuildNearListFromRiders(mgr, collidedRiders); + if (CGameCollision::DetectDynamicCollisionBoolean(*GetCollisionPrimitive(), GetPrimitiveTransform(), nearList, + mgr)) { + SetMotionState(mState); + Stop(); + x260_moveDelay = 0.035f; + MoveRiders(mgr, dt, GetActive(), x318_riders, collidedRiders, x34_transform, oldXf, -x270_dragDelta, + x27c_rotDelta.inverse()); x270_dragDelta = zeus::CVector3f::skZero; - zeus::CTransform oldXf = x34_transform; - CMotionState mState = GetMotionState(); - if (GetActive()) - { - for (SRiders& rider : x318_riders) - if (TCastToPtr act = mgr.ObjectById(rider.x0_uid)) - rider.x8_transform.origin = x34_transform.transposeRotate(act->GetTranslation() - GetTranslation()); - x27c_rotDelta = Move(dt, mgr); - } - - x270_dragDelta = x34_transform.origin - oldXf.origin; - - std::vector collidedRiders; - MoveRiders(mgr, dt, GetActive(), x318_riders, collidedRiders, oldXf, - x34_transform, x270_dragDelta, x27c_rotDelta); - x356_27_squishedRider = false; - if (!collidedRiders.empty()) - { - rstl::reserved_vector nearList = BuildNearListFromRiders(mgr, collidedRiders); - if (CGameCollision::DetectDynamicCollisionBoolean(*GetCollisionPrimitive(), GetPrimitiveTransform(), - nearList, mgr)) - { - SetMotionState(mState); - Stop(); - x260_moveDelay = 0.035f; - MoveRiders(mgr, dt, GetActive(), x318_riders, collidedRiders, x34_transform, oldXf, - -x270_dragDelta, x27c_rotDelta.inverse()); - x270_dragDelta = zeus::CVector3f::skZero; - SendScriptMsgs(EScriptObjectState::Modify, mgr, EScriptObjectMessage::None); - x356_27_squishedRider = true; - } - } + SendScriptMsgs(EScriptObjectState::Modify, mgr, EScriptObjectMessage::None); + x356_27_squishedRider = true; + } } + } } -void CScriptPlatform::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; +void CScriptPlatform::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; - if (HasModelData() && GetModelData()->HasAnimData()) - { - if (!x356_25_notAnimating) - UpdateAnimation(dt, mgr, true); - if (x356_28_rainSplashes && mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain) - { - if (HasModelData() && !GetModelData()->IsNull() && mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f) - mgr.GetActorModelParticles()->AddRainSplashGenerator - (*this, mgr, x34c_maxRainSplashes, x350_rainGenRate, 0.f); - } + if (HasModelData() && GetModelData()->HasAnimData()) { + if (!x356_25_notAnimating) + UpdateAnimation(dt, mgr, true); + if (x356_28_rainSplashes && mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain) { + if (HasModelData() && !GetModelData()->IsNull() && mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f) + mgr.GetActorModelParticles()->AddRainSplashGenerator(*this, mgr, x34c_maxRainSplashes, x350_rainGenRate, 0.f); } + } - if (!x328_slavesStatic.empty() || !x338_slavesDynamic.empty()) - { - rstl::reserved_vector draggedSet; - DragSlaves(mgr, draggedSet, x270_dragDelta); + if (!x328_slavesStatic.empty() || !x338_slavesDynamic.empty()) { + rstl::reserved_vector draggedSet; + DragSlaves(mgr, draggedSet, x270_dragDelta); + } + + if (x356_24_dead) + return; + + if (HealthInfo(mgr)->GetHP() <= 0.f) { + x356_24_dead = true; + SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); + } +} + +void CScriptPlatform::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + CActor::PreRender(mgr, frustum); + if (!xe4_30_outOfFrustum && !zeus::close_enough(x348_xrayAlpha, 1.f)) { + CModelFlags flags(5, 0, 3, {1.f, x348_xrayAlpha}); + if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay && !x356_30_disableXrayAlpha) { + xb4_drawFlags = flags; + x356_29_setXrayDrawFlags = true; + } else if (x356_29_setXrayDrawFlags) { + x356_29_setXrayDrawFlags = false; + if (xb4_drawFlags == flags && !x356_30_disableXrayAlpha) + xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); } + } + if (!mgr.GetObjectById(x354_boundsTrigger)) + x354_boundsTrigger = kInvalidUniqueId; +} - if (x356_24_dead) - return; +void CScriptPlatform::Render(const CStateManager& mgr) const { + bool xray = mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay; + if (xray && !x356_31_xrayFog) + g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::CColor::skBlack); + CPhysicsActor::Render(mgr); + if (xray && !x356_31_xrayFog) + mgr.SetupFogForArea(x4_areaId); +} - if (HealthInfo(mgr)->GetHP() <= 0.f) - { - x356_24_dead = true; - SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); +std::experimental::optional CScriptPlatform::GetTouchBounds() const { + if (x314_treeGroup) + return {x314_treeGroup->CalculateAABox(GetTransform())}; + + return {CPhysicsActor::GetBoundingBox()}; +} + +zeus::CTransform CScriptPlatform::GetPrimitiveTransform() const { + zeus::CTransform ret = GetTransform(); + ret.origin += GetPrimitiveOffset(); + return ret; +} + +const CCollisionPrimitive* CScriptPlatform::GetCollisionPrimitive() const { + if (!x314_treeGroup) + return CPhysicsActor::GetCollisionPrimitive(); + return x314_treeGroup.get(); +} + +zeus::CVector3f CScriptPlatform::GetOrbitPosition(const CStateManager& mgr) const { return GetAimPosition(mgr, 0.f); } + +zeus::CVector3f CScriptPlatform::GetAimPosition(const CStateManager& mgr, float dt) const { + if (auto tb = GetTouchBounds()) + return {tb->center()}; + return CPhysicsActor::GetAimPosition(mgr, dt); +} + +zeus::CAABox CScriptPlatform::GetSortingBounds(const CStateManager& mgr) const { + if (x354_boundsTrigger != kInvalidUniqueId) + if (TCastToConstPtr trig = mgr.GetObjectById(x354_boundsTrigger)) + return trig->GetTriggerBoundsWR(); + return CActor::GetSortingBounds(mgr); +} + +bool CScriptPlatform::IsRider(TUniqueId id) const { + for (const SRiders& rider : x318_riders) + if (rider.x0_uid == id) + return true; + return false; +} + +bool CScriptPlatform::IsSlave(TUniqueId id) const { + auto search = std::find_if(x328_slavesStatic.begin(), x328_slavesStatic.end(), + [id](const SRiders& rider) { return rider.x0_uid == id; }); + if (search != x328_slavesStatic.end()) + return true; + search = std::find_if(x338_slavesDynamic.begin(), x338_slavesDynamic.end(), + [id](const SRiders& rider) { return rider.x0_uid == id; }); + return search != x338_slavesDynamic.end(); +} + +void CScriptPlatform::BuildSlaveList(CStateManager& mgr) { + x328_slavesStatic.reserve(GetConnectionList().size()); + for (const SConnection& conn : GetConnectionList()) { + if (conn.x0_state == EScriptObjectState::Play && conn.x4_msg == EScriptObjectMessage::Activate) { + if (TCastToPtr act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) { + act->AddMaterial(EMaterialTypes::PlatformSlave, mgr); + zeus::CTransform xf = act->GetTransform(); + xf.origin = act->GetTranslation() - GetTranslation(); + x328_slavesStatic.emplace_back(act->GetUniqueId(), 0.166667f, xf); + } + } else if (conn.x0_state == EScriptObjectState::InheritBounds && conn.x4_msg == EScriptObjectMessage::Activate) { + auto list = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = list.first; it != list.second; ++it) + if (TCastToConstPtr(mgr.GetObjectById(it->second))) + x354_boundsTrigger = it->second; } + } } -void CScriptPlatform::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - CActor::PreRender(mgr, frustum); - if (!xe4_30_outOfFrustum && !zeus::close_enough(x348_xrayAlpha, 1.f)) - { - CModelFlags flags(5, 0, 3, {1.f, x348_xrayAlpha}); - if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay && !x356_30_disableXrayAlpha) - { - xb4_drawFlags = flags; - x356_29_setXrayDrawFlags = true; - } - else if (x356_29_setXrayDrawFlags) - { - x356_29_setXrayDrawFlags = false; - if (xb4_drawFlags == flags && !x356_30_disableXrayAlpha) - xb4_drawFlags = CModelFlags(0, 0, 3, zeus::CColor::skWhite); - } +void CScriptPlatform::AddRider(std::vector& riders, TUniqueId riderId, const CPhysicsActor* ridee, + CStateManager& mgr) { + auto search = std::find_if(riders.begin(), riders.end(), [riderId](const SRiders& r) { return r.x0_uid == riderId; }); + if (search == riders.end()) { + zeus::CTransform xf; + if (TCastToPtr act = mgr.ObjectById(riderId)) { + xf.origin = ridee->GetTransform().transposeRotate(act->GetTranslation() - ridee->GetTranslation()); + mgr.SendScriptMsg(act.GetPtr(), ridee->GetUniqueId(), EScriptObjectMessage::AddPlatformRider); } - if (!mgr.GetObjectById(x354_boundsTrigger)) - x354_boundsTrigger = kInvalidUniqueId; + riders.emplace_back(riderId, 0.166667f, xf); + } else { + search->x4_decayTimer = 0.166667f; + } } -void CScriptPlatform::Render(const CStateManager& mgr) const -{ - bool xray = mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay; - if (xray && !x356_31_xrayFog) - g_Renderer->SetWorldFog(ERglFogMode::None, 0.f, 1.f, zeus::CColor::skBlack); - CPhysicsActor::Render(mgr); - if (xray && !x356_31_xrayFog) - mgr.SetupFogForArea(x4_areaId); -} - -std::experimental::optional CScriptPlatform::GetTouchBounds() const -{ - if (x314_treeGroup) - return {x314_treeGroup->CalculateAABox(GetTransform())}; - - return {CPhysicsActor::GetBoundingBox()}; -} - -zeus::CTransform CScriptPlatform::GetPrimitiveTransform() const -{ - zeus::CTransform ret = GetTransform(); - ret.origin += GetPrimitiveOffset(); - return ret; -} - -const CCollisionPrimitive* CScriptPlatform::GetCollisionPrimitive() const -{ - if (!x314_treeGroup) - return CPhysicsActor::GetCollisionPrimitive(); - return x314_treeGroup.get(); -} - -zeus::CVector3f CScriptPlatform::GetOrbitPosition(const CStateManager& mgr) const -{ - return GetAimPosition(mgr, 0.f); -} - -zeus::CVector3f CScriptPlatform::GetAimPosition(const CStateManager& mgr, float dt) const -{ - if (auto tb = GetTouchBounds()) - return {tb->center()}; - return CPhysicsActor::GetAimPosition(mgr, dt); -} - -zeus::CAABox CScriptPlatform::GetSortingBounds(const CStateManager& mgr) const -{ - if (x354_boundsTrigger != kInvalidUniqueId) - if (TCastToConstPtr trig = mgr.GetObjectById(x354_boundsTrigger)) - return trig->GetTriggerBoundsWR(); - return CActor::GetSortingBounds(mgr); -} - -bool CScriptPlatform::IsRider(TUniqueId id) const -{ - for (const SRiders& rider : x318_riders) - if (rider.x0_uid == id) - return true; - return false; -} - -bool CScriptPlatform::IsSlave(TUniqueId id) const -{ - auto search = std::find_if(x328_slavesStatic.begin(), x328_slavesStatic.end(), - [id](const SRiders& rider){ return rider.x0_uid == id; }); - if (search != x328_slavesStatic.end()) - return true; - search = std::find_if(x338_slavesDynamic.begin(), x338_slavesDynamic.end(), - [id](const SRiders& rider){ return rider.x0_uid == id; }); - return search != x338_slavesDynamic.end(); -} - -void CScriptPlatform::BuildSlaveList(CStateManager& mgr) -{ - x328_slavesStatic.reserve(GetConnectionList().size()); - for (const SConnection& conn : GetConnectionList()) - { - if (conn.x0_state == EScriptObjectState::Play && conn.x4_msg == EScriptObjectMessage::Activate) - { - if (TCastToPtr act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) - { - act->AddMaterial(EMaterialTypes::PlatformSlave, mgr); - zeus::CTransform xf = act->GetTransform(); - xf.origin = act->GetTranslation() - GetTranslation(); - x328_slavesStatic.emplace_back(act->GetUniqueId(), 0.166667f, xf); - } - } - else if (conn.x0_state == EScriptObjectState::InheritBounds && conn.x4_msg == EScriptObjectMessage::Activate) - { - auto list = mgr.GetIdListForScript(conn.x8_objId); - for (auto it = list.first ; it != list.second ; ++it) - if (TCastToConstPtr(mgr.GetObjectById(it->second))) - x354_boundsTrigger = it->second; - } +void CScriptPlatform::AddSlave(TUniqueId id, CStateManager& mgr) { + auto search = std::find_if(x338_slavesDynamic.begin(), x338_slavesDynamic.end(), + [id](const SRiders& r) { return r.x0_uid == id; }); + if (search == x338_slavesDynamic.end()) { + if (TCastToPtr act = mgr.ObjectById(id)) { + act->AddMaterial(EMaterialTypes::PlatformSlave, mgr); + zeus::CTransform localXf = x34_transform.inverse() * act->GetTransform(); + x338_slavesDynamic.emplace_back(id, 0.166667f, localXf); } + } } -void CScriptPlatform::AddRider(std::vector& riders, TUniqueId riderId, - const CPhysicsActor* ridee, CStateManager& mgr) -{ - auto search = std::find_if(riders.begin(), riders.end(), - [riderId](const SRiders& r) { return r.x0_uid == riderId; }); - if (search == riders.end()) - { - zeus::CTransform xf; - if (TCastToPtr act = mgr.ObjectById(riderId)) - { - xf.origin = ridee->GetTransform().transposeRotate(act->GetTranslation() - ridee->GetTranslation()); - mgr.SendScriptMsg(act.GetPtr(), ridee->GetUniqueId(), EScriptObjectMessage::AddPlatformRider); - } - riders.emplace_back(riderId, 0.166667f, xf); - } - else - { - search->x4_decayTimer = 0.166667f; - } +TUniqueId CScriptPlatform::GetNext(TUniqueId uid, CStateManager& mgr) { + TCastToConstPtr nextWp = mgr.GetObjectById(uid); + if (!nextWp) + return GetWaypoint(mgr); + + TUniqueId next = nextWp->NextWaypoint(mgr); + if (TCastToConstPtr wp = mgr.GetObjectById(next)) + x25c_currentSpeed = wp->GetSpeed(); + + return next; } -void CScriptPlatform::AddSlave(TUniqueId id, CStateManager& mgr) -{ - auto search = std::find_if(x338_slavesDynamic.begin(), x338_slavesDynamic.end(), - [id](const SRiders& r) { return r.x0_uid == id; }); - if (search == x338_slavesDynamic.end()) - { - if (TCastToPtr act = mgr.ObjectById(id)) - { - act->AddMaterial(EMaterialTypes::PlatformSlave, mgr); - zeus::CTransform localXf = x34_transform.inverse() * act->GetTransform(); - x338_slavesDynamic.emplace_back(id, 0.166667f, localXf); - } - } +TUniqueId CScriptPlatform::GetWaypoint(CStateManager& mgr) { + for (const SConnection& conn : x20_conns) { + if (conn.x4_msg == EScriptObjectMessage::Follow) + return mgr.GetIdForScript(conn.x8_objId); + } + + return kInvalidUniqueId; } -TUniqueId CScriptPlatform::GetNext(TUniqueId uid, CStateManager& mgr) -{ - TCastToConstPtr nextWp = mgr.GetObjectById(uid); - if (!nextWp) - return GetWaypoint(mgr); - - TUniqueId next = nextWp->NextWaypoint(mgr); - if (TCastToConstPtr wp = mgr.GetObjectById(next)) - x25c_currentSpeed = wp->GetSpeed(); - - return next; +void CScriptPlatform::SplashThink(const zeus::CAABox&, const CFluidPlane&, float, CStateManager&) const { + // Empty } -TUniqueId CScriptPlatform::GetWaypoint(CStateManager& mgr) -{ - for (const SConnection& conn : x20_conns) - { - if (conn.x4_msg == EScriptObjectMessage::Follow) - return mgr.GetIdForScript(conn.x8_objId); - } - - return kInvalidUniqueId; -} - -void CScriptPlatform::SplashThink(const zeus::CAABox &, const CFluidPlane &, float, CStateManager &) const -{ - // Empty -} - -zeus::CQuaternion CScriptPlatform::Move(float dt, CStateManager& mgr) -{ - TUniqueId nextWaypoint = x25a_targetWaypoint; - if (x25a_targetWaypoint == kInvalidUniqueId) - nextWaypoint = GetNext(x258_currentWaypoint, mgr); - - TCastToPtr wp = mgr.ObjectById(nextWaypoint); - if (x258_currentWaypoint != kInvalidUniqueId && wp && !wp->GetActive()) - { - nextWaypoint = GetNext(x258_currentWaypoint, mgr); - if (nextWaypoint == kInvalidUniqueId) - if (TCastToPtr wp = mgr.ObjectById(x258_currentWaypoint)) - if (wp->GetActive()) - nextWaypoint = x258_currentWaypoint; - } +zeus::CQuaternion CScriptPlatform::Move(float dt, CStateManager& mgr) { + TUniqueId nextWaypoint = x25a_targetWaypoint; + if (x25a_targetWaypoint == kInvalidUniqueId) + nextWaypoint = GetNext(x258_currentWaypoint, mgr); + TCastToPtr wp = mgr.ObjectById(nextWaypoint); + if (x258_currentWaypoint != kInvalidUniqueId && wp && !wp->GetActive()) { + nextWaypoint = GetNext(x258_currentWaypoint, mgr); if (nextWaypoint == kInvalidUniqueId) - return zeus::CQuaternion::skNoRotation; + if (TCastToPtr wp = mgr.ObjectById(x258_currentWaypoint)) + if (wp->GetActive()) + nextWaypoint = x258_currentWaypoint; + } - while (nextWaypoint != kInvalidUniqueId) - { - if (TCastToPtr wp = mgr.ObjectById(nextWaypoint)) - { - zeus::CVector3f platToWp = wp->GetTranslation() - GetTranslation(); - if (zeus::close_enough(platToWp, zeus::CVector3f::skZero)) - { - x258_currentWaypoint = nextWaypoint; - mgr.SendScriptMsg(wp.GetPtr(), GetUniqueId(), EScriptObjectMessage::Arrived); - if (zeus::close_enough(x25c_currentSpeed, 0.f, 0.02)) - { - nextWaypoint = GetNext(x258_currentWaypoint, mgr); - x25c_currentSpeed = 0.f; - Stop(); - } - else - { - nextWaypoint = GetNext(x258_currentWaypoint, mgr); - } - - if (nextWaypoint != kInvalidUniqueId) - continue; - - mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop); - } - - if (zeus::close_enough(platToWp, zeus::CVector3f::skZero)) - { - x270_dragDelta = wp->GetTranslation() - GetTranslation(); - MoveToWR(GetTranslation(), dt); - - } - else if ((platToWp.normalized() * x25c_currentSpeed * dt).magSquared() > platToWp.magSquared()) - { - x270_dragDelta = wp->GetTranslation() - GetTranslation(); - MoveToWR(wp->GetTranslation(), dt); - } - else - { - x270_dragDelta = platToWp.normalized() * x25c_currentSpeed * dt; - MoveToWR(GetTranslation() + x270_dragDelta, dt); - } - - rstl::reserved_vector nearList; - mgr.BuildColliderList(nearList, *this, GetMotionVolume(dt)); - rstl::reserved_vector nonRiders; - for (TUniqueId id : nearList) - if (!IsRider(id) && !IsSlave(id)) - nonRiders.push_back(id); - - if (x356_26_detectCollision) - { - CMotionState mState = PredictMotion(dt); - MoveCollisionPrimitive(mState.x0_translation); - bool collision = CGameCollision::DetectDynamicCollisionBoolean - (*GetCollisionPrimitive(), GetPrimitiveTransform(), nonRiders, mgr); - MoveCollisionPrimitive(zeus::CVector3f::skZero); - if (collision || x356_27_squishedRider) - { - if (x356_26_detectCollision) - { - if (x264_collisionRecoverDelay <= 0.f && !x356_27_squishedRider) - { - x264_collisionRecoverDelay = 0.035f; - break; - } - else - { - x356_27_squishedRider = false; - TUniqueId prevWaypoint = nextWaypoint; - nextWaypoint = GetNext(nextWaypoint, mgr); - if (x25a_targetWaypoint == nextWaypoint || x25a_targetWaypoint == prevWaypoint) - { - x260_moveDelay = 0.035f; - break; - } - } - } - else - { - break; - } - } - else - { - AddMotionState(mState); - break; - } - } - else - { - xf8_24_movable = true; - CGameCollision::Move(mgr, *this, dt, &nonRiders); - xf8_24_movable = false; - break; - } - } - else - { - nextWaypoint = kInvalidUniqueId; - break; - } - } - - x25a_targetWaypoint = nextWaypoint; + if (nextWaypoint == kInvalidUniqueId) return zeus::CQuaternion::skNoRotation; + + while (nextWaypoint != kInvalidUniqueId) { + if (TCastToPtr wp = mgr.ObjectById(nextWaypoint)) { + zeus::CVector3f platToWp = wp->GetTranslation() - GetTranslation(); + if (zeus::close_enough(platToWp, zeus::CVector3f::skZero)) { + x258_currentWaypoint = nextWaypoint; + mgr.SendScriptMsg(wp.GetPtr(), GetUniqueId(), EScriptObjectMessage::Arrived); + if (zeus::close_enough(x25c_currentSpeed, 0.f, 0.02)) { + nextWaypoint = GetNext(x258_currentWaypoint, mgr); + x25c_currentSpeed = 0.f; + Stop(); + } else { + nextWaypoint = GetNext(x258_currentWaypoint, mgr); + } + + if (nextWaypoint != kInvalidUniqueId) + continue; + + mgr.SendScriptMsg(this, GetUniqueId(), EScriptObjectMessage::Stop); + } + + if (zeus::close_enough(platToWp, zeus::CVector3f::skZero)) { + x270_dragDelta = wp->GetTranslation() - GetTranslation(); + MoveToWR(GetTranslation(), dt); + + } else if ((platToWp.normalized() * x25c_currentSpeed * dt).magSquared() > platToWp.magSquared()) { + x270_dragDelta = wp->GetTranslation() - GetTranslation(); + MoveToWR(wp->GetTranslation(), dt); + } else { + x270_dragDelta = platToWp.normalized() * x25c_currentSpeed * dt; + MoveToWR(GetTranslation() + x270_dragDelta, dt); + } + + rstl::reserved_vector nearList; + mgr.BuildColliderList(nearList, *this, GetMotionVolume(dt)); + rstl::reserved_vector nonRiders; + for (TUniqueId id : nearList) + if (!IsRider(id) && !IsSlave(id)) + nonRiders.push_back(id); + + if (x356_26_detectCollision) { + CMotionState mState = PredictMotion(dt); + MoveCollisionPrimitive(mState.x0_translation); + bool collision = CGameCollision::DetectDynamicCollisionBoolean(*GetCollisionPrimitive(), + GetPrimitiveTransform(), nonRiders, mgr); + MoveCollisionPrimitive(zeus::CVector3f::skZero); + if (collision || x356_27_squishedRider) { + if (x356_26_detectCollision) { + if (x264_collisionRecoverDelay <= 0.f && !x356_27_squishedRider) { + x264_collisionRecoverDelay = 0.035f; + break; + } else { + x356_27_squishedRider = false; + TUniqueId prevWaypoint = nextWaypoint; + nextWaypoint = GetNext(nextWaypoint, mgr); + if (x25a_targetWaypoint == nextWaypoint || x25a_targetWaypoint == prevWaypoint) { + x260_moveDelay = 0.035f; + break; + } + } + } else { + break; + } + } else { + AddMotionState(mState); + break; + } + } else { + xf8_24_movable = true; + CGameCollision::Move(mgr, *this, dt, &nonRiders); + xf8_24_movable = false; + break; + } + } else { + nextWaypoint = kInvalidUniqueId; + break; + } + } + + x25a_targetWaypoint = nextWaypoint; + return zeus::CQuaternion::skNoRotation; } -} +} // namespace urde diff --git a/Runtime/World/CScriptPlatform.hpp b/Runtime/World/CScriptPlatform.hpp index d3c474735..f409a397e 100644 --- a/Runtime/World/CScriptPlatform.hpp +++ b/Runtime/World/CScriptPlatform.hpp @@ -6,113 +6,105 @@ #include "CHealthInfo.hpp" #include "CDamageVulnerability.hpp" -namespace urde -{ +namespace urde { class CCollidableOBBTreeGroup; class CCollidableOBBTreeGroupContainer; class CFluidPlane; -struct SRiders -{ - TUniqueId x0_uid; - float x4_decayTimer; - zeus::CTransform x8_transform; +struct SRiders { + TUniqueId x0_uid; + float x4_decayTimer; + zeus::CTransform x8_transform; - SRiders(TUniqueId id, float decayTimer, const zeus::CTransform& xf) - : x0_uid(id), x4_decayTimer(decayTimer), x8_transform(xf) {} + SRiders(TUniqueId id, float decayTimer, const zeus::CTransform& xf) + : x0_uid(id), x4_decayTimer(decayTimer), x8_transform(xf) {} }; -class CScriptPlatform : public CPhysicsActor -{ - u32 x254_; - TUniqueId x258_currentWaypoint = kInvalidUniqueId; - TUniqueId x25a_targetWaypoint = kInvalidUniqueId; - float x25c_currentSpeed; - float x260_moveDelay = 0.f; - float x264_collisionRecoverDelay = 0.f; - float x268_fadeInTime = 0.f; - float x26c_fadeOutTime = 0.f; - zeus::CVector3f x270_dragDelta; - zeus::CQuaternion x27c_rotDelta; - CHealthInfo x28c_initialHealth; - CHealthInfo x294_health; - CDamageVulnerability x29c_damageVuln; - std::experimental::optional> x304_treeGroupContainer; - std::unique_ptr x314_treeGroup; - std::vector x318_riders; - std::vector x328_slavesStatic; - std::vector x338_slavesDynamic; - float x348_xrayAlpha; - u32 x34c_maxRainSplashes; - u32 x350_rainGenRate; - TUniqueId x354_boundsTrigger = kInvalidUniqueId; - union - { - struct - { - bool x356_24_dead : 1; - bool x356_25_notAnimating : 1; - bool x356_26_detectCollision : 1; - bool x356_27_squishedRider : 1; - bool x356_28_rainSplashes : 1; - bool x356_29_setXrayDrawFlags : 1; - bool x356_30_disableXrayAlpha : 1; - bool x356_31_xrayFog : 1; - }; - u32 x356_dummy = 0; +class CScriptPlatform : public CPhysicsActor { + u32 x254_; + TUniqueId x258_currentWaypoint = kInvalidUniqueId; + TUniqueId x25a_targetWaypoint = kInvalidUniqueId; + float x25c_currentSpeed; + float x260_moveDelay = 0.f; + float x264_collisionRecoverDelay = 0.f; + float x268_fadeInTime = 0.f; + float x26c_fadeOutTime = 0.f; + zeus::CVector3f x270_dragDelta; + zeus::CQuaternion x27c_rotDelta; + CHealthInfo x28c_initialHealth; + CHealthInfo x294_health; + CDamageVulnerability x29c_damageVuln; + std::experimental::optional> x304_treeGroupContainer; + std::unique_ptr x314_treeGroup; + std::vector x318_riders; + std::vector x328_slavesStatic; + std::vector x338_slavesDynamic; + float x348_xrayAlpha; + u32 x34c_maxRainSplashes; + u32 x350_rainGenRate; + TUniqueId x354_boundsTrigger = kInvalidUniqueId; + union { + struct { + bool x356_24_dead : 1; + bool x356_25_notAnimating : 1; + bool x356_26_detectCollision : 1; + bool x356_27_squishedRider : 1; + bool x356_28_rainSplashes : 1; + bool x356_29_setXrayDrawFlags : 1; + bool x356_30_disableXrayAlpha : 1; + bool x356_31_xrayFog : 1; }; + u32 x356_dummy = 0; + }; - void DragSlave(CStateManager& mgr, rstl::reserved_vector& draggedSet, - CActor* actor, const zeus::CVector3f& delta); - void DragSlaves(CStateManager& mgr, rstl::reserved_vector& draggedSet, - const zeus::CVector3f& delta); - static void DecayRiders(std::vector& riders, float dt, CStateManager& mgr); - static void MoveRiders(CStateManager& mgr, float dt, bool active, std::vector& riders, - std::vector& collidedRiders, const zeus::CTransform& oldXf, - const zeus::CTransform& newXf, const zeus::CVector3f& dragDelta, - const zeus::CQuaternion& rotDelta); - static rstl::reserved_vector BuildNearListFromRiders - (CStateManager& mgr, const std::vector& movedRiders); + void DragSlave(CStateManager& mgr, rstl::reserved_vector& draggedSet, CActor* actor, + const zeus::CVector3f& delta); + void DragSlaves(CStateManager& mgr, rstl::reserved_vector& draggedSet, const zeus::CVector3f& delta); + static void DecayRiders(std::vector& riders, float dt, CStateManager& mgr); + static void MoveRiders(CStateManager& mgr, float dt, bool active, std::vector& riders, + std::vector& collidedRiders, const zeus::CTransform& oldXf, + const zeus::CTransform& newXf, const zeus::CVector3f& dragDelta, + const zeus::CQuaternion& rotDelta); + static rstl::reserved_vector BuildNearListFromRiders(CStateManager& mgr, + const std::vector& movedRiders); public: - CScriptPlatform(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParms, - const zeus::CAABox& aabb, float speed, bool detectCollision, float xrayAlpha, - bool active, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, - const std::experimental::optional>& dcln, - bool rainSplashes, u32 maxRainSplashes, u32 rainGenRate); + CScriptPlatform(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CModelData&& mData, const CActorParameters& actParms, const zeus::CAABox& aabb, float speed, + bool detectCollision, float xrayAlpha, bool active, const CHealthInfo& hInfo, + const CDamageVulnerability& dVuln, + const std::experimental::optional>& dcln, + bool rainSplashes, u32 maxRainSplashes, u32 rainGenRate); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void PreThink(float, CStateManager&); - void Think(float, CStateManager&); - void PreRender(CStateManager&, const zeus::CFrustum&); - void Render(const CStateManager&) const; - std::experimental::optional GetTouchBounds() const; - zeus::CTransform GetPrimitiveTransform() const; - const CCollisionPrimitive* GetCollisionPrimitive() const; - zeus::CVector3f GetOrbitPosition(const CStateManager& mgr) const; - zeus::CVector3f GetAimPosition(const CStateManager& mgr, float dt) const; - zeus::CAABox GetSortingBounds(const CStateManager& mgr) const; - bool IsRider(TUniqueId id) const; - bool IsSlave(TUniqueId id) const; - std::vector& GetStaticSlaves() { return x328_slavesStatic; } - const std::vector& GetStaticSlaves() const { return x328_slavesStatic; } - std::vector& GetDynamicSlaves() { return x338_slavesDynamic; } - const std::vector& GetDynamicSlaves() const { return x338_slavesDynamic; } - bool HasComplexCollision() const { return x314_treeGroup.operator bool(); } - void BuildSlaveList(CStateManager&); - static void AddRider(std::vector& riders, TUniqueId riderId, - const CPhysicsActor* ridee, CStateManager& mgr); - void AddSlave(TUniqueId, CStateManager&); - TUniqueId GetNext(TUniqueId, CStateManager&); - TUniqueId GetWaypoint(CStateManager&); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PreThink(float, CStateManager&); + void Think(float, CStateManager&); + void PreRender(CStateManager&, const zeus::CFrustum&); + void Render(const CStateManager&) const; + std::experimental::optional GetTouchBounds() const; + zeus::CTransform GetPrimitiveTransform() const; + const CCollisionPrimitive* GetCollisionPrimitive() const; + zeus::CVector3f GetOrbitPosition(const CStateManager& mgr) const; + zeus::CVector3f GetAimPosition(const CStateManager& mgr, float dt) const; + zeus::CAABox GetSortingBounds(const CStateManager& mgr) const; + bool IsRider(TUniqueId id) const; + bool IsSlave(TUniqueId id) const; + std::vector& GetStaticSlaves() { return x328_slavesStatic; } + const std::vector& GetStaticSlaves() const { return x328_slavesStatic; } + std::vector& GetDynamicSlaves() { return x338_slavesDynamic; } + const std::vector& GetDynamicSlaves() const { return x338_slavesDynamic; } + bool HasComplexCollision() const { return x314_treeGroup.operator bool(); } + void BuildSlaveList(CStateManager&); + static void AddRider(std::vector& riders, TUniqueId riderId, const CPhysicsActor* ridee, CStateManager& mgr); + void AddSlave(TUniqueId, CStateManager&); + TUniqueId GetNext(TUniqueId, CStateManager&); + TUniqueId GetWaypoint(CStateManager&); - const CDamageVulnerability* GetDamageVulnerability() const { return &x29c_damageVuln; } - CHealthInfo* HealthInfo(CStateManager&) { return &x294_health; } + const CDamageVulnerability* GetDamageVulnerability() const { return &x29c_damageVuln; } + CHealthInfo* HealthInfo(CStateManager&) { return &x294_health; } - virtual void SplashThink(const zeus::CAABox&, const CFluidPlane&, float, CStateManager&) const; - virtual zeus::CQuaternion Move(float, CStateManager&); + virtual void SplashThink(const zeus::CAABox&, const CFluidPlane&, float, CStateManager&) const; + virtual zeus::CQuaternion Move(float, CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptPlayerActor.cpp b/Runtime/World/CScriptPlayerActor.cpp index 0ab1901d2..13b8ad5dd 100644 --- a/Runtime/World/CScriptPlayerActor.cpp +++ b/Runtime/World/CScriptPlayerActor.cpp @@ -12,498 +12,420 @@ #include "TCastTo.hpp" #include "Camera/CGameCamera.hpp" -namespace urde -{ +namespace urde { CScriptPlayerActor::CScriptPlayerActor(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, const CAnimRes& animRes, CModelData&& mData, - const zeus::CAABox& aabox, bool setBoundingBox, const CMaterialList& list, float mass, - float zMomentum, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, - const CActorParameters& aParams, bool loop, bool active, u32 flags, - CPlayerState::EBeamId beam) + const zeus::CAABox& aabox, bool setBoundingBox, const CMaterialList& list, + float mass, float zMomentum, const CHealthInfo& hInfo, + const CDamageVulnerability& dVuln, const CActorParameters& aParams, bool loop, + bool active, u32 flags, CPlayerState::EBeamId beam) : CScriptActor(uid, name, info, xf, std::move(mData), aabox, mass, zMomentum, list, hInfo, dVuln, aParams, loop, active, 0, 1.f, false, false, false, false) , x2e8_suitRes(animRes) , x304_beam(beam) -, x350_flags(flags) -{ - x354_24_setBoundingBox = setBoundingBox; - x354_29_loading = true; - x354_30_enableLoading = true; - CMaterialList exclude = GetMaterialFilter().GetExcludeList(); - CMaterialList include = GetMaterialFilter().GetIncludeList(); - include.Add(EMaterialTypes::Player); - SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); +, x350_flags(flags) { + x354_24_setBoundingBox = setBoundingBox; + x354_29_loading = true; + x354_30_enableLoading = true; + CMaterialList exclude = GetMaterialFilter().GetExcludeList(); + CMaterialList include = GetMaterialFilter().GetIncludeList(); + include.Add(EMaterialTypes::Player); + SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); - SetActorLights(aParams.GetLightParameters().MakeActorLights()); - xe7_29_drawEnabled = true; - x2e3_24_isPlayerActor = true; + SetActorLights(aParams.GetLightParameters().MakeActorLights()); + xe7_29_drawEnabled = true; + x2e3_24_isPlayerActor = true; } -u32 CScriptPlayerActor::GetSuitCharIdx(const CStateManager& mgr, CPlayerState::EPlayerSuit suit) const -{ - if (mgr.GetPlayerState()->IsFusionEnabled()) - { - switch (suit) - { - case CPlayerState::EPlayerSuit::Power: - return 4; - case CPlayerState::EPlayerSuit::Varia: - return 7; - case CPlayerState::EPlayerSuit::Gravity: - return 6; - case CPlayerState::EPlayerSuit::Phazon: - return 8; - default: - break; - } - } - return u32(suit); -} - -u32 CScriptPlayerActor::GetNextSuitCharIdx(const CStateManager& mgr) const -{ - CPlayerState::EPlayerSuit nextSuit = CPlayerState::EPlayerSuit::Phazon; - - if (x350_flags & 0x2) - { - switch (x308_suit) - { - case CPlayerState::EPlayerSuit::Gravity: - nextSuit = CPlayerState::EPlayerSuit::Varia; - break; - case CPlayerState::EPlayerSuit::Phazon: - nextSuit = CPlayerState::EPlayerSuit::Gravity; - break; - case CPlayerState::EPlayerSuit::Varia: - default: - nextSuit = CPlayerState::EPlayerSuit::Power; - break; - } - } - else - { - switch (x308_suit) - { - case CPlayerState::EPlayerSuit::Power: - nextSuit = CPlayerState::EPlayerSuit::Varia; - break; - case CPlayerState::EPlayerSuit::Varia: - nextSuit = CPlayerState::EPlayerSuit::Gravity; - break; - case CPlayerState::EPlayerSuit::Gravity: - nextSuit = CPlayerState::EPlayerSuit::Phazon; - break; - default: - break; - } - } - - return GetSuitCharIdx(mgr, nextSuit); -} - -void CScriptPlayerActor::LoadSuit(u32 charIdx) -{ - if (charIdx != x310_loadedCharIdx) - { - TToken fac = g_CharFactoryBuilder->GetFactory(x2e8_suitRes); - const CCharacterInfo& chInfo = fac->GetCharInfo(charIdx); - x320_suitModel = g_SimplePool->GetObj({FOURCC('CMDL'), chInfo.GetModelId()}); - x324_suitSkin = g_SimplePool->GetObj({FOURCC('CSKR'), chInfo.GetSkinRulesId()}); - x354_28_suitModelLoading = true; - x310_loadedCharIdx = charIdx; - } -} - -void CScriptPlayerActor::LoadBeam(CPlayerState::EBeamId beam) -{ - if (beam != x30c_setBeamId) - { - x31c_beamModel = g_SimplePool->GetObj({FOURCC('CMDL'), g_tweakPlayerRes->GetBeamCineModel(beam)}); - x354_27_beamModelLoading = true; - x30c_setBeamId = beam; - } -} - -void CScriptPlayerActor::PumpBeamModel(CStateManager& mgr) -{ - if (!x31c_beamModel || !x31c_beamModel.IsLoaded()) - return; - BuildBeamModelData(); - x314_beamModelData->Touch(mgr, 0); - mgr.WorldNC()->CycleLoadPauseState(); - x31c_beamModel = TLockedToken(); - x354_27_beamModelLoading = false; -} - -void CScriptPlayerActor::BuildBeamModelData() -{ - x314_beamModelData = std::make_unique( - CStaticRes(g_tweakPlayerRes->GetBeamCineModel(x30c_setBeamId), x2e8_suitRes.GetScale())); -} - -void CScriptPlayerActor::PumpSuitModel(CStateManager& mgr) -{ - if (!x320_suitModel || !x320_suitModel.IsLoaded() || - !x324_suitSkin || !x324_suitSkin.IsLoaded()) - return; - - x320_suitModel->Touch(0); - mgr.WorldNC()->CycleLoadPauseState(); - - bool didSetup = false; - if (x354_26_deferOfflineModelData) - { - didSetup = true; - x354_26_deferOfflineModelData = false; - SetupOfflineModelData(); - } - else if (x354_25_deferOnlineModelData) - { - didSetup = true; - x354_25_deferOnlineModelData = false; - SetupOnlineModelData(); - } - - if (didSetup) - { - x354_28_suitModelLoading = false; - x320_suitModel = TLockedToken(); - x324_suitSkin = TLockedToken(); - } -} - -void CScriptPlayerActor::SetupOfflineModelData() -{ - x2e8_suitRes.SetCharacterNodeId(x310_loadedCharIdx); - x318_suitModelData = std::make_unique(x2e8_suitRes); - if (!static_cast(*g_Main).GetScreenFading()) - { - x328_backupModelData = x64_modelData->AnimationData()->GetModelData(); - x348_deallocateBackupCountdown = 2; - } - x64_modelData->AnimationData()->SubstituteModelData(x318_suitModelData->AnimationData()->GetModelData()); -} - -void CScriptPlayerActor::SetupOnlineModelData() -{ - if (x310_loadedCharIdx != x2e8_suitRes.GetCharacterNodeId() || - !x64_modelData || !x64_modelData->HasAnimData()) - { - x2e8_suitRes.SetCharacterNodeId(x310_loadedCharIdx); - SetModelData(std::make_unique(x2e8_suitRes)); - CAnimPlaybackParms parms(x2e8_suitRes.GetDefaultAnim(), -1, 1.f, true); - x64_modelData->AnimationData()->SetAnimation(parms, false); - if (x354_24_setBoundingBox) - SetBoundingBox(x64_modelData->GetBounds(GetTransform().getRotation())); - } -} - -void CScriptPlayerActor::Think(float dt, CStateManager& mgr) -{ - auto& pState = *mgr.GetPlayerState(); - - if (x354_31_deferOnlineLoad) - { - x354_25_deferOnlineModelData = true; - x354_31_deferOnlineLoad = false; - x308_suit = pState.GetCurrentSuitRaw(); - LoadSuit(GetSuitCharIdx(mgr, x308_suit)); - } - - if (x354_30_enableLoading) - { - if (!(x350_flags & 0x1)) - { - u32 tmpIdx = GetSuitCharIdx(mgr, pState.GetCurrentSuitRaw()); - if (tmpIdx != x310_loadedCharIdx) - { - SetModelData(std::make_unique(CModelData::CModelDataNull())); - LoadSuit(tmpIdx); - x354_25_deferOnlineModelData = true; - } - } - - LoadBeam(x304_beam != CPlayerState::EBeamId::Invalid ? x304_beam : pState.GetCurrentBeam()); - - if (x354_27_beamModelLoading) - PumpBeamModel(mgr); - - if (x354_28_suitModelLoading) - PumpSuitModel(mgr); - - if (!x354_29_loading) - { - if (x354_28_suitModelLoading || x354_27_beamModelLoading || !x64_modelData || - x64_modelData->IsNull() || !x64_modelData->IsLoaded(0)) - x354_29_loading = true; - } - - if (x354_29_loading && !x354_28_suitModelLoading && !x354_27_beamModelLoading && - x64_modelData && !x64_modelData->IsNull() && x64_modelData->IsLoaded(0)) - { - if (x355_24_areaTrackingLoad) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); - --const_cast(area->GetPostConstructed())->x113c_playerActorsLoading; - x355_24_areaTrackingLoad = false; - } - x354_29_loading = false; - SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); - } - } - - if (x2e8_suitRes.GetCharacterNodeId() == 3) - { - if (!x338_phazonIndirectTexture) - x338_phazonIndirectTexture = g_SimplePool->GetObj("PhazonIndirectTexture"); - } - else - { - if (x338_phazonIndirectTexture) - x338_phazonIndirectTexture = TLockedToken(); - } - - if (x338_phazonIndirectTexture) - { - x34c_phazonOffsetAngle += 0.03f; - x34c_phazonOffsetAngle = zeus::CRelAngle::FromRadians(x34c_phazonOffsetAngle); - } - - CScriptActor::Think(dt, mgr); -} - -void CScriptPlayerActor::SetupEnvFx(CStateManager& mgr, bool set) -{ - if (set) - { - if (mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain) - if (x64_modelData && !x64_modelData->IsNull()) - if (mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f) - mgr.GetActorModelParticles()->AddRainSplashGenerator(*this, mgr, 250, 10, 1.2f); - } - else - { - mgr.GetActorModelParticles()->RemoveRainSplashGenerator(*this); - } -} - -void CScriptPlayerActor::SetIntoStateManager(CStateManager& mgr, bool set) -{ - if (!set && mgr.GetPlayerActorHead() == x8_uid) - { - mgr.SetPlayerActorHead(x356_nextPlayerActor); - x356_nextPlayerActor = kInvalidUniqueId; - } - else - { - TUniqueId paId = mgr.GetPlayerActorHead(); - CScriptPlayerActor* other = nullptr; - while (paId != kInvalidUniqueId) - { - if (paId == x8_uid) - { - if (!set && other) - { - other->x356_nextPlayerActor = x356_nextPlayerActor; - x356_nextPlayerActor = kInvalidUniqueId; - } - return; - } - - TCastToPtr act = mgr.ObjectById(paId); - if (act && act->IsPlayerActor()) - { - other = static_cast(act.GetPtr()); - paId = other->x356_nextPlayerActor; - } - else - { - paId = kInvalidUniqueId; - x356_nextPlayerActor = kInvalidUniqueId; - } - } - - if (set) - { - x356_nextPlayerActor = mgr.GetPlayerActorHead(); - mgr.SetPlayerActorHead(x8_uid); - } - } -} - -void CScriptPlayerActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::InitializedInArea: - x354_31_deferOnlineLoad = true; - if (x350_flags & 0x8) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); - ++const_cast(area->GetPostConstructed())->x113c_playerActorsLoading; - x355_24_areaTrackingLoad = true; - } - if (GetActive()) - { - SetupEnvFx(mgr, true); - SetIntoStateManager(mgr, true); - } - break; - case EScriptObjectMessage::Activate: - if (!GetActive()) - { - if (x350_flags & 0x1) - LoadSuit(GetNextSuitCharIdx(mgr)); - SetIntoStateManager(mgr, true); - SetupEnvFx(mgr, true); - x354_30_enableLoading = true; - } - break; - case EScriptObjectMessage::Increment: - if (x350_flags & 0x1) - { - x354_25_deferOnlineModelData = false; - x354_26_deferOfflineModelData = true; - mgr.GetPlayer().AsyncLoadSuit(mgr); - } - break; - case EScriptObjectMessage::Deactivate: - if (GetActive()) - { - if (!(x350_flags & 0x10)) - SetIntoStateManager(mgr, false); - SetupEnvFx(mgr, false); - } - if (!(x350_flags & 0x4)) - break; - case EScriptObjectMessage::Reset: - if (GetActive() || msg == EScriptObjectMessage::Reset) - { - x30c_setBeamId = CPlayerState::EBeamId::Invalid; - x310_loadedCharIdx = -1; - x314_beamModelData.reset(); - x318_suitModelData.reset(); - x31c_beamModel = TLockedToken(); - x320_suitModel = TLockedToken(); - x324_suitSkin = TLockedToken(); - x328_backupModelData = TLockedToken(); - x338_phazonIndirectTexture = TLockedToken(); - x348_deallocateBackupCountdown = 0; - x350_flags &= ~0x1; - x354_25_deferOnlineModelData = false; - x354_26_deferOfflineModelData = false; - x354_27_beamModelLoading = false; - x354_28_suitModelLoading = false; - x354_30_enableLoading = false; - SetModelData(std::make_unique(CModelData::CModelDataNull())); - } - break; - case EScriptObjectMessage::Deleted: - SetIntoStateManager(mgr, false); - break; +u32 CScriptPlayerActor::GetSuitCharIdx(const CStateManager& mgr, CPlayerState::EPlayerSuit suit) const { + if (mgr.GetPlayerState()->IsFusionEnabled()) { + switch (suit) { + case CPlayerState::EPlayerSuit::Power: + return 4; + case CPlayerState::EPlayerSuit::Varia: + return 7; + case CPlayerState::EPlayerSuit::Gravity: + return 6; + case CPlayerState::EPlayerSuit::Phazon: + return 8; default: - break; + break; + } + } + return u32(suit); +} + +u32 CScriptPlayerActor::GetNextSuitCharIdx(const CStateManager& mgr) const { + CPlayerState::EPlayerSuit nextSuit = CPlayerState::EPlayerSuit::Phazon; + + if (x350_flags & 0x2) { + switch (x308_suit) { + case CPlayerState::EPlayerSuit::Gravity: + nextSuit = CPlayerState::EPlayerSuit::Varia; + break; + case CPlayerState::EPlayerSuit::Phazon: + nextSuit = CPlayerState::EPlayerSuit::Gravity; + break; + case CPlayerState::EPlayerSuit::Varia: + default: + nextSuit = CPlayerState::EPlayerSuit::Power; + break; + } + } else { + switch (x308_suit) { + case CPlayerState::EPlayerSuit::Power: + nextSuit = CPlayerState::EPlayerSuit::Varia; + break; + case CPlayerState::EPlayerSuit::Varia: + nextSuit = CPlayerState::EPlayerSuit::Gravity; + break; + case CPlayerState::EPlayerSuit::Gravity: + nextSuit = CPlayerState::EPlayerSuit::Phazon; + break; + default: + break; + } + } + + return GetSuitCharIdx(mgr, nextSuit); +} + +void CScriptPlayerActor::LoadSuit(u32 charIdx) { + if (charIdx != x310_loadedCharIdx) { + TToken fac = g_CharFactoryBuilder->GetFactory(x2e8_suitRes); + const CCharacterInfo& chInfo = fac->GetCharInfo(charIdx); + x320_suitModel = g_SimplePool->GetObj({FOURCC('CMDL'), chInfo.GetModelId()}); + x324_suitSkin = g_SimplePool->GetObj({FOURCC('CSKR'), chInfo.GetSkinRulesId()}); + x354_28_suitModelLoading = true; + x310_loadedCharIdx = charIdx; + } +} + +void CScriptPlayerActor::LoadBeam(CPlayerState::EBeamId beam) { + if (beam != x30c_setBeamId) { + x31c_beamModel = g_SimplePool->GetObj({FOURCC('CMDL'), g_tweakPlayerRes->GetBeamCineModel(beam)}); + x354_27_beamModelLoading = true; + x30c_setBeamId = beam; + } +} + +void CScriptPlayerActor::PumpBeamModel(CStateManager& mgr) { + if (!x31c_beamModel || !x31c_beamModel.IsLoaded()) + return; + BuildBeamModelData(); + x314_beamModelData->Touch(mgr, 0); + mgr.WorldNC()->CycleLoadPauseState(); + x31c_beamModel = TLockedToken(); + x354_27_beamModelLoading = false; +} + +void CScriptPlayerActor::BuildBeamModelData() { + x314_beamModelData = std::make_unique( + CStaticRes(g_tweakPlayerRes->GetBeamCineModel(x30c_setBeamId), x2e8_suitRes.GetScale())); +} + +void CScriptPlayerActor::PumpSuitModel(CStateManager& mgr) { + if (!x320_suitModel || !x320_suitModel.IsLoaded() || !x324_suitSkin || !x324_suitSkin.IsLoaded()) + return; + + x320_suitModel->Touch(0); + mgr.WorldNC()->CycleLoadPauseState(); + + bool didSetup = false; + if (x354_26_deferOfflineModelData) { + didSetup = true; + x354_26_deferOfflineModelData = false; + SetupOfflineModelData(); + } else if (x354_25_deferOnlineModelData) { + didSetup = true; + x354_25_deferOnlineModelData = false; + SetupOnlineModelData(); + } + + if (didSetup) { + x354_28_suitModelLoading = false; + x320_suitModel = TLockedToken(); + x324_suitSkin = TLockedToken(); + } +} + +void CScriptPlayerActor::SetupOfflineModelData() { + x2e8_suitRes.SetCharacterNodeId(x310_loadedCharIdx); + x318_suitModelData = std::make_unique(x2e8_suitRes); + if (!static_cast(*g_Main).GetScreenFading()) { + x328_backupModelData = x64_modelData->AnimationData()->GetModelData(); + x348_deallocateBackupCountdown = 2; + } + x64_modelData->AnimationData()->SubstituteModelData(x318_suitModelData->AnimationData()->GetModelData()); +} + +void CScriptPlayerActor::SetupOnlineModelData() { + if (x310_loadedCharIdx != x2e8_suitRes.GetCharacterNodeId() || !x64_modelData || !x64_modelData->HasAnimData()) { + x2e8_suitRes.SetCharacterNodeId(x310_loadedCharIdx); + SetModelData(std::make_unique(x2e8_suitRes)); + CAnimPlaybackParms parms(x2e8_suitRes.GetDefaultAnim(), -1, 1.f, true); + x64_modelData->AnimationData()->SetAnimation(parms, false); + if (x354_24_setBoundingBox) + SetBoundingBox(x64_modelData->GetBounds(GetTransform().getRotation())); + } +} + +void CScriptPlayerActor::Think(float dt, CStateManager& mgr) { + auto& pState = *mgr.GetPlayerState(); + + if (x354_31_deferOnlineLoad) { + x354_25_deferOnlineModelData = true; + x354_31_deferOnlineLoad = false; + x308_suit = pState.GetCurrentSuitRaw(); + LoadSuit(GetSuitCharIdx(mgr, x308_suit)); + } + + if (x354_30_enableLoading) { + if (!(x350_flags & 0x1)) { + u32 tmpIdx = GetSuitCharIdx(mgr, pState.GetCurrentSuitRaw()); + if (tmpIdx != x310_loadedCharIdx) { + SetModelData(std::make_unique(CModelData::CModelDataNull())); + LoadSuit(tmpIdx); + x354_25_deferOnlineModelData = true; + } } - CScriptActor::AcceptScriptMsg(msg, uid, mgr); -} + LoadBeam(x304_beam != CPlayerState::EBeamId::Invalid ? x304_beam : pState.GetCurrentBeam()); -void CScriptPlayerActor::SetActive(bool active) -{ - CActor::SetActive(active); - xe7_29_drawEnabled = true; -} + if (x354_27_beamModelLoading) + PumpBeamModel(mgr); -void CScriptPlayerActor::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - if (x328_backupModelData) - { - if (x348_deallocateBackupCountdown == 0) - x328_backupModelData = TLockedToken(); - else - --x348_deallocateBackupCountdown; - } - if (x2e8_suitRes.GetCharacterNodeId() == 3) - g_Renderer->AllocatePhazonSuitMaskTexture(); - CScriptActor::PreRender(mgr, frustum); -} + if (x354_28_suitModelLoading) + PumpSuitModel(mgr); -void CScriptPlayerActor::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - const_cast(this)->TouchModels_Internal(mgr); - if (GetActive()) - CActor::AddToRenderer(frustum, mgr); -} - -void CScriptPlayerActor::Render(const CStateManager& mgr) const -{ - bool phazonSuit = x2e8_suitRes.GetCharacterNodeId() == 3; - if (phazonSuit) - { - // Draw into alpha buffer - CModelFlags flags = xb4_drawFlags; - flags.x4_color = zeus::CColor::skWhite; - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - CModelData::EWhichModel which = CModelData::GetRenderingModel(mgr); - x64_modelData->Render(which, x34_transform, x90_actorLights.get(), flags); + if (!x354_29_loading) { + if (x354_28_suitModelLoading || x354_27_beamModelLoading || !x64_modelData || x64_modelData->IsNull() || + !x64_modelData->IsLoaded(0)) + x354_29_loading = true; } - CPhysicsActor::Render(mgr); - - if (x314_beamModelData && !x314_beamModelData->IsNull() && - x64_modelData && !x64_modelData->IsNull()) - { - zeus::CTransform modelXf = GetTransform() * x64_modelData->GetScaledLocatorTransform("GUN_LCTR"); - CModelFlags flags(5, 0, 3, zeus::CColor::skWhite); - flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; - x314_beamModelData->Render(mgr, modelXf, x90_actorLights.get(), flags); - flags.m_extendedShader = EExtendedShader::Lighting; - flags.x4_color = zeus::CColor{1.f, xb4_drawFlags.x4_color.a()}; - x314_beamModelData->Render(mgr, modelXf, x90_actorLights.get(), flags); + if (x354_29_loading && !x354_28_suitModelLoading && !x354_27_beamModelLoading && x64_modelData && + !x64_modelData->IsNull() && x64_modelData->IsLoaded(0)) { + if (x355_24_areaTrackingLoad) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); + --const_cast(area->GetPostConstructed())->x113c_playerActorsLoading; + x355_24_areaTrackingLoad = false; + } + x354_29_loading = false; + SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); } + } - if (phazonSuit) - { - zeus::CVector3f vecFromCam = - GetBoundingBox().center() - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation(); - float radius = zeus::clamp(0.25f, (6.f - vecFromCam.magnitude()) / 6.f, 2.f); - float offsetX = std::sin(x34c_phazonOffsetAngle); - float offsetY = std::sin(x34c_phazonOffsetAngle) * 0.5f; - g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.1f, 1.f), x338_phazonIndirectTexture, - zeus::CColor::skWhite, radius, 0.05f, offsetX, offsetY); - } + if (x2e8_suitRes.GetCharacterNodeId() == 3) { + if (!x338_phazonIndirectTexture) + x338_phazonIndirectTexture = g_SimplePool->GetObj("PhazonIndirectTexture"); + } else { + if (x338_phazonIndirectTexture) + x338_phazonIndirectTexture = TLockedToken(); + } + + if (x338_phazonIndirectTexture) { + x34c_phazonOffsetAngle += 0.03f; + x34c_phazonOffsetAngle = zeus::CRelAngle::FromRadians(x34c_phazonOffsetAngle); + } + + CScriptActor::Think(dt, mgr); } -void CScriptPlayerActor::TouchModels_Internal(const CStateManager& mgr) const -{ - if (x64_modelData && !x64_modelData->IsNull()) - x64_modelData->Touch(mgr, 0); - - if (x318_suitModelData && !x318_suitModelData->IsNull()) - x318_suitModelData->Touch(mgr, 0); - - if (!x354_27_beamModelLoading) - if (x314_beamModelData && !x314_beamModelData->IsNull()) - x314_beamModelData->Touch(mgr, 0); +void CScriptPlayerActor::SetupEnvFx(CStateManager& mgr, bool set) { + if (set) { + if (mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain) + if (x64_modelData && !x64_modelData->IsNull()) + if (mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f) + mgr.GetActorModelParticles()->AddRainSplashGenerator(*this, mgr, 250, 10, 1.2f); + } else { + mgr.GetActorModelParticles()->RemoveRainSplashGenerator(*this); + } } -void CScriptPlayerActor::TouchModels(const CStateManager& mgr) const -{ - TouchModels_Internal(mgr); - TUniqueId paId = x356_nextPlayerActor; - while (paId != kInvalidUniqueId) - { - TCastToConstPtr act = mgr.GetObjectById(paId); - if (act && act->IsPlayerActor()) - { - const auto* pa = static_cast(act.GetPtr()); - pa->TouchModels_Internal(mgr); - paId = pa->x356_nextPlayerActor; - } - else - { - paId = kInvalidUniqueId; +void CScriptPlayerActor::SetIntoStateManager(CStateManager& mgr, bool set) { + if (!set && mgr.GetPlayerActorHead() == x8_uid) { + mgr.SetPlayerActorHead(x356_nextPlayerActor); + x356_nextPlayerActor = kInvalidUniqueId; + } else { + TUniqueId paId = mgr.GetPlayerActorHead(); + CScriptPlayerActor* other = nullptr; + while (paId != kInvalidUniqueId) { + if (paId == x8_uid) { + if (!set && other) { + other->x356_nextPlayerActor = x356_nextPlayerActor; + x356_nextPlayerActor = kInvalidUniqueId; } + return; + } + + TCastToPtr act = mgr.ObjectById(paId); + if (act && act->IsPlayerActor()) { + other = static_cast(act.GetPtr()); + paId = other->x356_nextPlayerActor; + } else { + paId = kInvalidUniqueId; + x356_nextPlayerActor = kInvalidUniqueId; + } } + + if (set) { + x356_nextPlayerActor = mgr.GetPlayerActorHead(); + mgr.SetPlayerActorHead(x8_uid); + } + } } + +void CScriptPlayerActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::InitializedInArea: + x354_31_deferOnlineLoad = true; + if (x350_flags & 0x8) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); + ++const_cast(area->GetPostConstructed())->x113c_playerActorsLoading; + x355_24_areaTrackingLoad = true; + } + if (GetActive()) { + SetupEnvFx(mgr, true); + SetIntoStateManager(mgr, true); + } + break; + case EScriptObjectMessage::Activate: + if (!GetActive()) { + if (x350_flags & 0x1) + LoadSuit(GetNextSuitCharIdx(mgr)); + SetIntoStateManager(mgr, true); + SetupEnvFx(mgr, true); + x354_30_enableLoading = true; + } + break; + case EScriptObjectMessage::Increment: + if (x350_flags & 0x1) { + x354_25_deferOnlineModelData = false; + x354_26_deferOfflineModelData = true; + mgr.GetPlayer().AsyncLoadSuit(mgr); + } + break; + case EScriptObjectMessage::Deactivate: + if (GetActive()) { + if (!(x350_flags & 0x10)) + SetIntoStateManager(mgr, false); + SetupEnvFx(mgr, false); + } + if (!(x350_flags & 0x4)) + break; + case EScriptObjectMessage::Reset: + if (GetActive() || msg == EScriptObjectMessage::Reset) { + x30c_setBeamId = CPlayerState::EBeamId::Invalid; + x310_loadedCharIdx = -1; + x314_beamModelData.reset(); + x318_suitModelData.reset(); + x31c_beamModel = TLockedToken(); + x320_suitModel = TLockedToken(); + x324_suitSkin = TLockedToken(); + x328_backupModelData = TLockedToken(); + x338_phazonIndirectTexture = TLockedToken(); + x348_deallocateBackupCountdown = 0; + x350_flags &= ~0x1; + x354_25_deferOnlineModelData = false; + x354_26_deferOfflineModelData = false; + x354_27_beamModelLoading = false; + x354_28_suitModelLoading = false; + x354_30_enableLoading = false; + SetModelData(std::make_unique(CModelData::CModelDataNull())); + } + break; + case EScriptObjectMessage::Deleted: + SetIntoStateManager(mgr, false); + break; + default: + break; + } + + CScriptActor::AcceptScriptMsg(msg, uid, mgr); } + +void CScriptPlayerActor::SetActive(bool active) { + CActor::SetActive(active); + xe7_29_drawEnabled = true; +} + +void CScriptPlayerActor::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + if (x328_backupModelData) { + if (x348_deallocateBackupCountdown == 0) + x328_backupModelData = TLockedToken(); + else + --x348_deallocateBackupCountdown; + } + if (x2e8_suitRes.GetCharacterNodeId() == 3) + g_Renderer->AllocatePhazonSuitMaskTexture(); + CScriptActor::PreRender(mgr, frustum); +} + +void CScriptPlayerActor::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + const_cast(this)->TouchModels_Internal(mgr); + if (GetActive()) + CActor::AddToRenderer(frustum, mgr); +} + +void CScriptPlayerActor::Render(const CStateManager& mgr) const { + bool phazonSuit = x2e8_suitRes.GetCharacterNodeId() == 3; + if (phazonSuit) { + // Draw into alpha buffer + CModelFlags flags = xb4_drawFlags; + flags.x4_color = zeus::CColor::skWhite; + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + CModelData::EWhichModel which = CModelData::GetRenderingModel(mgr); + x64_modelData->Render(which, x34_transform, x90_actorLights.get(), flags); + } + + CPhysicsActor::Render(mgr); + + if (x314_beamModelData && !x314_beamModelData->IsNull() && x64_modelData && !x64_modelData->IsNull()) { + zeus::CTransform modelXf = GetTransform() * x64_modelData->GetScaledLocatorTransform("GUN_LCTR"); + CModelFlags flags(5, 0, 3, zeus::CColor::skWhite); + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + x314_beamModelData->Render(mgr, modelXf, x90_actorLights.get(), flags); + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = zeus::CColor{1.f, xb4_drawFlags.x4_color.a()}; + x314_beamModelData->Render(mgr, modelXf, x90_actorLights.get(), flags); + } + + if (phazonSuit) { + zeus::CVector3f vecFromCam = + GetBoundingBox().center() - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation(); + float radius = zeus::clamp(0.25f, (6.f - vecFromCam.magnitude()) / 6.f, 2.f); + float offsetX = std::sin(x34c_phazonOffsetAngle); + float offsetY = std::sin(x34c_phazonOffsetAngle) * 0.5f; + g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.1f, 1.f), x338_phazonIndirectTexture, zeus::CColor::skWhite, + radius, 0.05f, offsetX, offsetY); + } +} + +void CScriptPlayerActor::TouchModels_Internal(const CStateManager& mgr) const { + if (x64_modelData && !x64_modelData->IsNull()) + x64_modelData->Touch(mgr, 0); + + if (x318_suitModelData && !x318_suitModelData->IsNull()) + x318_suitModelData->Touch(mgr, 0); + + if (!x354_27_beamModelLoading) + if (x314_beamModelData && !x314_beamModelData->IsNull()) + x314_beamModelData->Touch(mgr, 0); +} + +void CScriptPlayerActor::TouchModels(const CStateManager& mgr) const { + TouchModels_Internal(mgr); + TUniqueId paId = x356_nextPlayerActor; + while (paId != kInvalidUniqueId) { + TCastToConstPtr act = mgr.GetObjectById(paId); + if (act && act->IsPlayerActor()) { + const auto* pa = static_cast(act.GetPtr()); + pa->TouchModels_Internal(mgr); + paId = pa->x356_nextPlayerActor; + } else { + paId = kInvalidUniqueId; + } + } +} +} // namespace urde diff --git a/Runtime/World/CScriptPlayerActor.hpp b/Runtime/World/CScriptPlayerActor.hpp index fae8b48c8..e45f3f1b3 100644 --- a/Runtime/World/CScriptPlayerActor.hpp +++ b/Runtime/World/CScriptPlayerActor.hpp @@ -3,73 +3,68 @@ #include "CScriptActor.hpp" #include "CPlayerState.hpp" -namespace urde -{ -class CScriptPlayerActor : public CScriptActor -{ - CAnimRes x2e8_suitRes; - CPlayerState::EBeamId x304_beam; - CPlayerState::EPlayerSuit x308_suit = CPlayerState::EPlayerSuit::Invalid; - CPlayerState::EBeamId x30c_setBeamId = CPlayerState::EBeamId::Invalid; - s32 x310_loadedCharIdx = -1; - std::unique_ptr x314_beamModelData; - std::unique_ptr x318_suitModelData; - TLockedToken x31c_beamModel; // Used to be single_ptr - TLockedToken x320_suitModel; // Used to be single_ptr - TLockedToken x324_suitSkin; // Used to be single_ptr - TLockedToken x328_backupModelData; // Used to be optional - TLockedToken x338_phazonIndirectTexture; // Used to be optional - u32 x348_deallocateBackupCountdown = 0; - float x34c_phazonOffsetAngle = 0.f; - u32 x350_flags; /* 0x1: suit transition, 0x2: previous suit, 0x4: force reset - * 0x8: track in area data, 0x10: keep in state manager */ - union - { - struct - { - bool x354_24_setBoundingBox : 1; - bool x354_25_deferOnlineModelData : 1; - bool x354_26_deferOfflineModelData : 1; - bool x354_27_beamModelLoading : 1; - bool x354_28_suitModelLoading : 1; - bool x354_29_loading : 1; - bool x354_30_enableLoading : 1; - bool x354_31_deferOnlineLoad : 1; - bool x355_24_areaTrackingLoad : 1; - }; - u32 _dummy = 0; +namespace urde { +class CScriptPlayerActor : public CScriptActor { + CAnimRes x2e8_suitRes; + CPlayerState::EBeamId x304_beam; + CPlayerState::EPlayerSuit x308_suit = CPlayerState::EPlayerSuit::Invalid; + CPlayerState::EBeamId x30c_setBeamId = CPlayerState::EBeamId::Invalid; + s32 x310_loadedCharIdx = -1; + std::unique_ptr x314_beamModelData; + std::unique_ptr x318_suitModelData; + TLockedToken x31c_beamModel; // Used to be single_ptr + TLockedToken x320_suitModel; // Used to be single_ptr + TLockedToken x324_suitSkin; // Used to be single_ptr + TLockedToken x328_backupModelData; // Used to be optional + TLockedToken x338_phazonIndirectTexture; // Used to be optional + u32 x348_deallocateBackupCountdown = 0; + float x34c_phazonOffsetAngle = 0.f; + u32 x350_flags; /* 0x1: suit transition, 0x2: previous suit, 0x4: force reset + * 0x8: track in area data, 0x10: keep in state manager */ + union { + struct { + bool x354_24_setBoundingBox : 1; + bool x354_25_deferOnlineModelData : 1; + bool x354_26_deferOfflineModelData : 1; + bool x354_27_beamModelLoading : 1; + bool x354_28_suitModelLoading : 1; + bool x354_29_loading : 1; + bool x354_30_enableLoading : 1; + bool x354_31_deferOnlineLoad : 1; + bool x355_24_areaTrackingLoad : 1; }; - TUniqueId x356_nextPlayerActor = kInvalidUniqueId; + u32 _dummy = 0; + }; + TUniqueId x356_nextPlayerActor = kInvalidUniqueId; - u32 GetSuitCharIdx(const CStateManager& mgr, CPlayerState::EPlayerSuit suit) const; - u32 GetNextSuitCharIdx(const CStateManager& mgr) const; - void LoadSuit(u32 charIdx); - void LoadBeam(CPlayerState::EBeamId beam); - void PumpBeamModel(CStateManager& mgr); - void BuildBeamModelData(); - void PumpSuitModel(CStateManager& mgr); - void SetupOfflineModelData(); - void SetupOnlineModelData(); + u32 GetSuitCharIdx(const CStateManager& mgr, CPlayerState::EPlayerSuit suit) const; + u32 GetNextSuitCharIdx(const CStateManager& mgr) const; + void LoadSuit(u32 charIdx); + void LoadBeam(CPlayerState::EBeamId beam); + void PumpBeamModel(CStateManager& mgr); + void BuildBeamModelData(); + void PumpSuitModel(CStateManager& mgr); + void SetupOfflineModelData(); + void SetupOnlineModelData(); - void SetupEnvFx(CStateManager& mgr, bool set); - void SetIntoStateManager(CStateManager& mgr, bool set); + void SetupEnvFx(CStateManager& mgr, bool set); + void SetIntoStateManager(CStateManager& mgr, bool set); - void TouchModels_Internal(const CStateManager& mgr) const; + void TouchModels_Internal(const CStateManager& mgr) const; public: - CScriptPlayerActor(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, const CAnimRes& animRes, CModelData&& mData, - const zeus::CAABox& aabox, bool setBoundingBox, const CMaterialList& list, float mass, - float zMomentum, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, - const CActorParameters& aParams, bool loop, bool active, u32 flags, CPlayerState::EBeamId beam); + CScriptPlayerActor(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + const CAnimRes& animRes, CModelData&& mData, const zeus::CAABox& aabox, bool setBoundingBox, + const CMaterialList& list, float mass, float zMomentum, const CHealthInfo& hInfo, + const CDamageVulnerability& dVuln, const CActorParameters& aParams, bool loop, bool active, + u32 flags, CPlayerState::EBeamId beam); - void Think(float, CStateManager &); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); - void SetActive(bool active); - void PreRender(CStateManager &, const zeus::CFrustum &); - void AddToRenderer(const zeus::CFrustum &, const CStateManager &) const; - void Render(const CStateManager &mgr) const; - void TouchModels(const CStateManager& mgr) const; + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void SetActive(bool active); + void PreRender(CStateManager&, const zeus::CFrustum&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager& mgr) const; + void TouchModels(const CStateManager& mgr) const; }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptPlayerHint.cpp b/Runtime/World/CScriptPlayerHint.cpp index a3c44931b..0f619ecce 100644 --- a/Runtime/World/CScriptPlayerHint.cpp +++ b/Runtime/World/CScriptPlayerHint.cpp @@ -5,91 +5,77 @@ #include "CPlayer.hpp" #include "MP1/World/CMetroidPrimeRelay.hpp" -namespace urde -{ +namespace urde { CScriptPlayerHint::CScriptPlayerHint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, u32 priority, u32 overrideFlags) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), {EMaterialTypes::NoStepLogic}, - CActorParameters::None(), kInvalidUniqueId), x100_priority(priority), x104_overrideFlags(overrideFlags) -{} + CActorParameters::None(), kInvalidUniqueId) +, x100_priority(priority) +, x104_overrideFlags(overrideFlags) {} -void CScriptPlayerHint::Accept(IVisitor& visit) -{ - visit.Visit(this); +void CScriptPlayerHint::Accept(IVisitor& visit) { visit.Visit(this); } + +void CScriptPlayerHint::AddToObjectList(TUniqueId uid) { + for (TUniqueId existId : xe8_objectList) + if (uid == existId) + return; + if (xe8_objectList.size() != 8) + xe8_objectList.push_back(uid); } -void CScriptPlayerHint::AddToObjectList(TUniqueId uid) -{ - for (TUniqueId existId : xe8_objectList) - if (uid == existId) - return; - if (xe8_objectList.size() != 8) - xe8_objectList.push_back(uid); -} - -void CScriptPlayerHint::RemoveFromObjectList(TUniqueId uid) -{ - for (auto it = xe8_objectList.begin() ; it != xe8_objectList.end() ; ++it) - { - if (*it == uid) - { - xe8_objectList.erase(it); - return; - } +void CScriptPlayerHint::RemoveFromObjectList(TUniqueId uid) { + for (auto it = xe8_objectList.begin(); it != xe8_objectList.end(); ++it) { + if (*it == uid) { + xe8_objectList.erase(it); + return; } + } } -void CScriptPlayerHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Deactivate: - case EScriptObjectMessage::Deleted: - RemoveFromObjectList(sender); - mgr.GetPlayer().AddToPlayerHintRemoveList(GetUniqueId(), mgr); - xfc_deactivated = true; - break; +void CScriptPlayerHint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Deactivate: + case EScriptObjectMessage::Deleted: + RemoveFromObjectList(sender); + mgr.GetPlayer().AddToPlayerHintRemoveList(GetUniqueId(), mgr); + xfc_deactivated = true; + break; + case EScriptObjectMessage::Increment: + x108_mpId = kInvalidUniqueId; + if ((x104_overrideFlags & 0x4000) != 0) { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play) + continue; + x108_mpId = mgr.GetIdForScript(conn.x8_objId); + if (TCastToConstPtr mpRelay = mgr.GetObjectById(x108_mpId)) { + x108_mpId = mpRelay->GetMetroidPrimeExoId(); + break; + } + } + } + break; + default: + break; + } + + if (x30_24_active) { + switch (msg) { case EScriptObjectMessage::Increment: - x108_mpId = kInvalidUniqueId; - if ((x104_overrideFlags & 0x4000) != 0) - { - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play) - continue; - x108_mpId = mgr.GetIdForScript(conn.x8_objId); - if (TCastToConstPtr mpRelay = mgr.GetObjectById(x108_mpId)) - { - x108_mpId = mpRelay->GetMetroidPrimeExoId(); - break; - } - } - } - break; + AddToObjectList(sender); + mgr.GetPlayer().AddToPlayerHintAddList(GetUniqueId(), mgr); + xfc_deactivated = false; + break; + case EScriptObjectMessage::Decrement: + RemoveFromObjectList(sender); + mgr.GetPlayer().AddToPlayerHintRemoveList(GetUniqueId(), mgr); + break; default: - break; + break; } + } - if (x30_24_active) - { - switch (msg) - { - case EScriptObjectMessage::Increment: - AddToObjectList(sender); - mgr.GetPlayer().AddToPlayerHintAddList(GetUniqueId(), mgr); - xfc_deactivated = false; - break; - case EScriptObjectMessage::Decrement: - RemoveFromObjectList(sender); - mgr.GetPlayer().AddToPlayerHintRemoveList(GetUniqueId(), mgr); - break; - default: - break; - } - } - - CActor::AcceptScriptMsg(msg, sender, mgr); + CActor::AcceptScriptMsg(msg, sender, mgr); } -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/World/CScriptPlayerHint.hpp b/Runtime/World/CScriptPlayerHint.hpp index ff20b481a..92cf85d6a 100644 --- a/Runtime/World/CScriptPlayerHint.hpp +++ b/Runtime/World/CScriptPlayerHint.hpp @@ -2,29 +2,27 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { + +class CScriptPlayerHint : public CActor { + rstl::reserved_vector xe8_objectList; + bool xfc_deactivated = false; + u32 x100_priority; + u32 x104_overrideFlags; + TUniqueId x108_mpId = kInvalidUniqueId; + void AddToObjectList(TUniqueId uid); + void RemoveFromObjectList(TUniqueId uid); -class CScriptPlayerHint : public CActor -{ - rstl::reserved_vector xe8_objectList; - bool xfc_deactivated = false; - u32 x100_priority; - u32 x104_overrideFlags; - TUniqueId x108_mpId = kInvalidUniqueId; - void AddToObjectList(TUniqueId uid); - void RemoveFromObjectList(TUniqueId uid); public: - CScriptPlayerHint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, u32 priority, u32 overrideFlags); - void Accept(IVisitor& visit); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - u32 GetPriority() const { return x100_priority; } - u32 GetOverrideFlags() const { return x104_overrideFlags; } - TUniqueId GetActorId() const { return x108_mpId; } - void ClearObjectList() { xe8_objectList.clear(); } - void SetDeactivated() { xfc_deactivated = true; } + CScriptPlayerHint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + bool active, u32 priority, u32 overrideFlags); + void Accept(IVisitor& visit); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + u32 GetPriority() const { return x100_priority; } + u32 GetOverrideFlags() const { return x104_overrideFlags; } + TUniqueId GetActorId() const { return x108_mpId; } + void ClearObjectList() { xe8_objectList.clear(); } + void SetDeactivated() { xfc_deactivated = true; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptPlayerStateChange.cpp b/Runtime/World/CScriptPlayerStateChange.cpp index 3ab59d9bb..ff767e300 100644 --- a/Runtime/World/CScriptPlayerStateChange.cpp +++ b/Runtime/World/CScriptPlayerStateChange.cpp @@ -4,8 +4,7 @@ #include "Input/ControlMapper.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptPlayerStateChange::CScriptPlayerStateChange(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, u32 itemType, u32 itemCount, u32 itemCapacity, EControl control, EControlCommandOption controlCmdOpt) @@ -14,37 +13,29 @@ CScriptPlayerStateChange::CScriptPlayerStateChange(TUniqueId uid, std::string_vi , x38_itemCount(itemCount) , x3c_itemCapacity(itemCapacity) , x40_ctrl(control) -, x44_ctrlCmdOpt(controlCmdOpt) -{ -} +, x44_ctrlCmdOpt(controlCmdOpt) {} -void CScriptPlayerStateChange::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptPlayerStateChange::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptPlayerStateChange::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - if (GetActive() && msg == EScriptObjectMessage::SetToZero) - { - stateMgr.GetPlayerState()->InitializePowerUp(CPlayerState::EItemType(x34_itemType), x3c_itemCapacity); - stateMgr.GetPlayerState()->IncrPickup(CPlayerState::EItemType(x34_itemType), x38_itemCount); +void CScriptPlayerStateChange::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + if (GetActive() && msg == EScriptObjectMessage::SetToZero) { + stateMgr.GetPlayerState()->InitializePowerUp(CPlayerState::EItemType(x34_itemType), x3c_itemCapacity); + stateMgr.GetPlayerState()->IncrPickup(CPlayerState::EItemType(x34_itemType), x38_itemCount); - if (x44_ctrlCmdOpt == EControlCommandOption::Filtered && x40_ctrl == EControl::Filtered) - { - bool filtered = x44_ctrlCmdOpt != EControlCommandOption::Unfiltered; - ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitClose, filtered); - ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitConfirm, filtered); - ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitDown, filtered); - ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitFar, filtered); - ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitLeft, filtered); - ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitObject, filtered); - ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitRight, filtered); - ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitSelect, filtered); - ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitUp, filtered); - } + if (x44_ctrlCmdOpt == EControlCommandOption::Filtered && x40_ctrl == EControl::Filtered) { + bool filtered = x44_ctrlCmdOpt != EControlCommandOption::Unfiltered; + ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitClose, filtered); + ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitConfirm, filtered); + ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitDown, filtered); + ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitFar, filtered); + ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitLeft, filtered); + ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitObject, filtered); + ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitRight, filtered); + ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitSelect, filtered); + ControlMapper::SetCommandFiltered(ControlMapper::ECommands::OrbitUp, filtered); } + } - CEntity::AcceptScriptMsg(msg, objId, stateMgr); + CEntity::AcceptScriptMsg(msg, objId, stateMgr); } -} \ No newline at end of file +} // namespace urde \ No newline at end of file diff --git a/Runtime/World/CScriptPlayerStateChange.hpp b/Runtime/World/CScriptPlayerStateChange.hpp index ecae068c1..58917a45c 100644 --- a/Runtime/World/CScriptPlayerStateChange.hpp +++ b/Runtime/World/CScriptPlayerStateChange.hpp @@ -2,33 +2,23 @@ #include "World/CEntity.hpp" -namespace urde -{ -class CScriptPlayerStateChange : public CEntity -{ +namespace urde { +class CScriptPlayerStateChange : public CEntity { public: - enum class EControl - { - Unfiltered, - Filtered - }; - enum class EControlCommandOption - { - Unfiltered, - Filtered - }; + enum class EControl { Unfiltered, Filtered }; + enum class EControlCommandOption { Unfiltered, Filtered }; + private: - u32 x34_itemType; - u32 x38_itemCount; - u32 x3c_itemCapacity; - EControl x40_ctrl; - EControlCommandOption x44_ctrlCmdOpt; + u32 x34_itemType; + u32 x38_itemCount; + u32 x3c_itemCapacity; + EControl x40_ctrl; + EControlCommandOption x44_ctrlCmdOpt; + public: - CScriptPlayerStateChange(TUniqueId, std::string_view, const CEntityInfo&, bool, u32, u32, u32, EControl, - EControlCommandOption); - void Accept(IVisitor& visit); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + CScriptPlayerStateChange(TUniqueId, std::string_view, const CEntityInfo&, bool, u32, u32, u32, EControl, + EControlCommandOption); + void Accept(IVisitor& visit); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); }; -} - - +} // namespace urde diff --git a/Runtime/World/CScriptPointOfInterest.cpp b/Runtime/World/CScriptPointOfInterest.cpp index c384eaeb7..8a0fd0ccb 100644 --- a/Runtime/World/CScriptPointOfInterest.cpp +++ b/Runtime/World/CScriptPointOfInterest.cpp @@ -4,52 +4,38 @@ #include "CPlayerState.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptPointOfInterest::CScriptPointOfInterest(TUniqueId uid, std::string_view name, const CEntityInfo info, const zeus::CTransform& xf, bool active, const CScannableParameters& parms, float f1) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(u64(EMaterialTypes::Orbit)), CActorParameters::None().Scannable(parms), kInvalidUniqueId) -, xe8_pointSize(f1) -{ +, xe8_pointSize(f1) {} + +void CScriptPointOfInterest::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptPointOfInterest::Think(float dt, CStateManager& mgr) { + xe7_31_targetable = mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan; + CEntity::Think(dt, mgr); } -void CScriptPointOfInterest::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptPointOfInterest::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); } -void CScriptPointOfInterest::Think(float dt, CStateManager& mgr) -{ - xe7_31_targetable = mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan; - CEntity::Think(dt, mgr); +void CScriptPointOfInterest::AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} + +void CScriptPointOfInterest::Render(const CStateManager&) const {} + +void CScriptPointOfInterest::CalculateRenderBounds() { + if (xe8_pointSize == 0.f) + CActor::CalculateRenderBounds(); + else + x9c_renderBounds = zeus::CAABox(x34_transform.origin - xe8_pointSize, x34_transform.origin + xe8_pointSize); } -void CScriptPointOfInterest::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); -} - -void CScriptPointOfInterest::AddToRenderer(const zeus::CFrustum&, const CStateManager&) const -{ -} - -void CScriptPointOfInterest::Render(const CStateManager&) const -{ -} - -void CScriptPointOfInterest::CalculateRenderBounds() -{ - if (xe8_pointSize == 0.f) - CActor::CalculateRenderBounds(); - else - x9c_renderBounds = zeus::CAABox(x34_transform.origin - xe8_pointSize, x34_transform.origin + xe8_pointSize); -} - -std::experimental::optional CScriptPointOfInterest::GetTouchBounds() const -{ - return {zeus::CAABox{x34_transform.origin, x34_transform.origin}}; -} +std::experimental::optional CScriptPointOfInterest::GetTouchBounds() const { + return {zeus::CAABox{x34_transform.origin, x34_transform.origin}}; } +} // namespace urde diff --git a/Runtime/World/CScriptPointOfInterest.hpp b/Runtime/World/CScriptPointOfInterest.hpp index aab4b9a80..f2f3fc111 100644 --- a/Runtime/World/CScriptPointOfInterest.hpp +++ b/Runtime/World/CScriptPointOfInterest.hpp @@ -2,23 +2,22 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { class CScannableParameters; -class CScriptPointOfInterest : public CActor -{ +class CScriptPointOfInterest : public CActor { private: - float xe8_pointSize; -public: - CScriptPointOfInterest(TUniqueId, std::string_view, const CEntityInfo, const zeus::CTransform&, bool, - const CScannableParameters&, float); + float xe8_pointSize; - void Accept(IVisitor& visitor); - void Think(float, CStateManager &); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); - void AddToRenderer(const zeus::CFrustum &, const CStateManager &) const; - void Render(const CStateManager &) const; - void CalculateRenderBounds(); - std::experimental::optional GetTouchBounds() const; +public: + CScriptPointOfInterest(TUniqueId, std::string_view, const CEntityInfo, const zeus::CTransform&, bool, + const CScannableParameters&, float); + + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const; + void CalculateRenderBounds(); + std::experimental::optional GetTouchBounds() const; }; -} +} // namespace urde diff --git a/Runtime/World/CScriptRandomRelay.cpp b/Runtime/World/CScriptRandomRelay.cpp index b654c5e5d..9207202ca 100644 --- a/Runtime/World/CScriptRandomRelay.cpp +++ b/Runtime/World/CScriptRandomRelay.cpp @@ -2,40 +2,30 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ -CScriptRandomRelay::CScriptRandomRelay(TUniqueId uid, std::string_view name, const CEntityInfo& info, s32 connCount, s32 variance, - bool clamp, bool active) - : CEntity(uid, info, active, name), - x34_connectionCount((clamp && connCount > 100) ? 100 : connCount), - x38_variance(variance), - x3c_clamp(clamp) -{ +namespace urde { +CScriptRandomRelay::CScriptRandomRelay(TUniqueId uid, std::string_view name, const CEntityInfo& info, s32 connCount, + s32 variance, bool clamp, bool active) +: CEntity(uid, info, active, name) +, x34_connectionCount((clamp && connCount > 100) ? 100 : connCount) +, x38_variance(variance) +, x3c_clamp(clamp) {} + +void CScriptRandomRelay::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptRandomRelay::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); + if (msg == EScriptObjectMessage::SetToZero) { + if (!x30_24_active) + return; + SendLocalScriptMsgs(EScriptObjectState::Zero, stateMgr); + } } -void CScriptRandomRelay::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CScriptRandomRelay::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CEntity::AcceptScriptMsg(msg, objId, stateMgr); - if (msg == EScriptObjectMessage::SetToZero) - { - if (!x30_24_active) - return; - SendLocalScriptMsgs(EScriptObjectState::Zero, stateMgr); - } -} - -void CScriptRandomRelay::SendLocalScriptMsgs(EScriptObjectState state, CStateManager &stateMgr) -{ - if (state != EScriptObjectState::Zero) - { - SendScriptMsgs(state, stateMgr, EScriptObjectMessage::None); - return; - } +void CScriptRandomRelay::SendLocalScriptMsgs(EScriptObjectState state, CStateManager& stateMgr) { + if (state != EScriptObjectState::Zero) { + SendScriptMsgs(state, stateMgr, EScriptObjectMessage::None); + return; + } #if 0 std::vector> objs; @@ -60,4 +50,4 @@ void CScriptRandomRelay::SendLocalScriptMsgs(EScriptObjectState state, CStateMan #endif } -} +} // namespace urde diff --git a/Runtime/World/CScriptRandomRelay.hpp b/Runtime/World/CScriptRandomRelay.hpp index 6265f24e6..e4f67d516 100644 --- a/Runtime/World/CScriptRandomRelay.hpp +++ b/Runtime/World/CScriptRandomRelay.hpp @@ -2,19 +2,17 @@ #include "CEntity.hpp" -namespace urde -{ -class CScriptRandomRelay : public CEntity -{ - u32 x34_connectionCount; - u32 x38_variance; - bool x3c_clamp; +namespace urde { +class CScriptRandomRelay : public CEntity { + u32 x34_connectionCount; + u32 x38_variance; + bool x3c_clamp; + public: - CScriptRandomRelay(TUniqueId, std::string_view, const CEntityInfo&, s32, s32, bool, bool); + CScriptRandomRelay(TUniqueId, std::string_view, const CEntityInfo&, s32, s32, bool, bool); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); - void SendLocalScriptMsgs(EScriptObjectState state, CStateManager& stateMgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void SendLocalScriptMsgs(EScriptObjectState state, CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptRelay.cpp b/Runtime/World/CScriptRelay.cpp index 7d65bd845..8861c2c92 100644 --- a/Runtime/World/CScriptRelay.cpp +++ b/Runtime/World/CScriptRelay.cpp @@ -2,81 +2,63 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptRelay::CScriptRelay(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active) - : CEntity(uid, info, active, name) -{ -} +: CEntity(uid, info, active, name) {} -void CScriptRelay::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptRelay::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptRelay::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr) -{ - CEntity::AcceptScriptMsg(msg, objId, stateMgr); - if (msg == EScriptObjectMessage::Deleted) - { - UpdateObjectRef(stateMgr); - } - else if (msg == EScriptObjectMessage::SetToZero) - { - if (!x30_24_active) - return; - - x38_sendCount++; - TUniqueId tmp = stateMgr.GetLastRelayId(); - while (tmp != GetUniqueId() && tmp != kInvalidUniqueId) - { - const CScriptRelay* obj = static_cast(stateMgr.GetObjectById(tmp)); - if (!obj) - { - tmp = kInvalidUniqueId; - break; - } - - tmp = obj->x34_nextRelay; - } - - if (tmp == kInvalidUniqueId) - { - x34_nextRelay = stateMgr.GetLastRelayId(); - stateMgr.SetLastRelayId(GetUniqueId()); - } - } -} - -void CScriptRelay::Think(float, CStateManager& stateMgr) -{ - if (x38_sendCount == 0) - return; - - while (x38_sendCount != 0) - { - x38_sendCount--; - SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); - } +void CScriptRelay::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); + if (msg == EScriptObjectMessage::Deleted) { UpdateObjectRef(stateMgr); -} + } else if (msg == EScriptObjectMessage::SetToZero) { + if (!x30_24_active) + return; -void CScriptRelay::UpdateObjectRef(CStateManager& stateMgr) -{ - TUniqueId* tmp = stateMgr.GetLastRelayIdPtr(); - while (tmp != nullptr && *tmp != kInvalidUniqueId) - { - if (*tmp == GetUniqueId()) - { - *tmp = x34_nextRelay; - return; - } - CScriptRelay* obj = static_cast(stateMgr.ObjectById(*tmp)); - if (obj == nullptr) - return; - tmp = &obj->x34_nextRelay; + x38_sendCount++; + TUniqueId tmp = stateMgr.GetLastRelayId(); + while (tmp != GetUniqueId() && tmp != kInvalidUniqueId) { + const CScriptRelay* obj = static_cast(stateMgr.GetObjectById(tmp)); + if (!obj) { + tmp = kInvalidUniqueId; + break; + } + + tmp = obj->x34_nextRelay; } + + if (tmp == kInvalidUniqueId) { + x34_nextRelay = stateMgr.GetLastRelayId(); + stateMgr.SetLastRelayId(GetUniqueId()); + } + } } +void CScriptRelay::Think(float, CStateManager& stateMgr) { + if (x38_sendCount == 0) + return; + + while (x38_sendCount != 0) { + x38_sendCount--; + SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); + } + UpdateObjectRef(stateMgr); } + +void CScriptRelay::UpdateObjectRef(CStateManager& stateMgr) { + TUniqueId* tmp = stateMgr.GetLastRelayIdPtr(); + while (tmp != nullptr && *tmp != kInvalidUniqueId) { + if (*tmp == GetUniqueId()) { + *tmp = x34_nextRelay; + return; + } + CScriptRelay* obj = static_cast(stateMgr.ObjectById(*tmp)); + if (obj == nullptr) + return; + tmp = &obj->x34_nextRelay; + } +} + +} // namespace urde diff --git a/Runtime/World/CScriptRelay.hpp b/Runtime/World/CScriptRelay.hpp index c4468a2fc..839cf3e13 100644 --- a/Runtime/World/CScriptRelay.hpp +++ b/Runtime/World/CScriptRelay.hpp @@ -2,19 +2,17 @@ #include "CEntity.hpp" -namespace urde -{ -class CScriptRelay : public CEntity -{ - TUniqueId x34_nextRelay = kInvalidUniqueId; - u32 x38_sendCount = 0; +namespace urde { +class CScriptRelay : public CEntity { + TUniqueId x34_nextRelay = kInvalidUniqueId; + u32 x38_sendCount = 0; + public: - CScriptRelay(TUniqueId, std::string_view, const CEntityInfo&, bool); + CScriptRelay(TUniqueId, std::string_view, const CEntityInfo&, bool); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); - void Think(float, CStateManager& stateMgr); - void UpdateObjectRef(CStateManager& stateMgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Think(float, CStateManager& stateMgr); + void UpdateObjectRef(CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptRipple.cpp b/Runtime/World/CScriptRipple.cpp index 83ae7fe06..a1c56dcd5 100644 --- a/Runtime/World/CScriptRipple.cpp +++ b/Runtime/World/CScriptRipple.cpp @@ -3,44 +3,32 @@ #include "CScriptWater.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CScriptRipple::CScriptRipple(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CVector3f& vec, bool active, float f1) -: CEntity(uid, info, active, name) -, x34_magnitude(f1 >= 0.f ? f1 : 0.5f) -, x38_center(vec) -{ -} +CScriptRipple::CScriptRipple(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& vec, + bool active, float f1) +: CEntity(uid, info, active, name), x34_magnitude(f1 >= 0.f ? f1 : 0.5f), x38_center(vec) {} -void CScriptRipple::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptRipple::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptRipple::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Play) - { - if (!GetActive()) - return; +void CScriptRipple::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Play) { + if (!GetActive()) + return; - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Active || conn.x4_msg != EScriptObjectMessage::Next) - continue; + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Active || conn.x4_msg != EScriptObjectMessage::Next) + continue; - auto search = mgr.GetIdListForScript(conn.x8_objId); - for (auto it = search.first; it != search.second; ++it) - { - if (TCastToPtr water = mgr.ObjectById(it->second)) - water->GetFluidPlane().AddRipple(x34_magnitude, GetUniqueId(), x38_center, *water, mgr); - } - } - - return; + auto search = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) { + if (TCastToPtr water = mgr.ObjectById(it->second)) + water->GetFluidPlane().AddRipple(x34_magnitude, GetUniqueId(), x38_center, *water, mgr); + } } - CEntity::AcceptScriptMsg(msg, uid, mgr); -} + + return; + } + CEntity::AcceptScriptMsg(msg, uid, mgr); } +} // namespace urde diff --git a/Runtime/World/CScriptRipple.hpp b/Runtime/World/CScriptRipple.hpp index 984d56326..e5e9b4262 100644 --- a/Runtime/World/CScriptRipple.hpp +++ b/Runtime/World/CScriptRipple.hpp @@ -3,17 +3,16 @@ #include "CEntity.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ -class CScriptRipple : public CEntity -{ - float x34_magnitude; - zeus::CVector3f x38_center; -public: - CScriptRipple(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CVector3f&, bool, float); +namespace urde { +class CScriptRipple : public CEntity { + float x34_magnitude; + zeus::CVector3f x38_center; - void Accept(IVisitor&); - void Think(float, CStateManager&) {} - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); +public: + CScriptRipple(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CVector3f&, bool, float); + + void Accept(IVisitor&); + void Think(float, CStateManager&) {} + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); }; -} +} // namespace urde diff --git a/Runtime/World/CScriptRoomAcoustics.cpp b/Runtime/World/CScriptRoomAcoustics.cpp index 1626e73f4..c6376405a 100644 --- a/Runtime/World/CScriptRoomAcoustics.cpp +++ b/Runtime/World/CScriptRoomAcoustics.cpp @@ -2,88 +2,79 @@ #include "TCastTo.hpp" #include "Audio/CSfxManager.hpp" -namespace urde -{ +namespace urde { static TAreaId s_ActiveAcousticsAreaId = kInvalidAreaId; -CScriptRoomAcoustics::CScriptRoomAcoustics(TUniqueId uid, std::string_view name, - const CEntityInfo& info, bool active, u32 volScale, - bool revHi, bool revHiDis, float revHiColoration, float revHiMix, - float revHiTime, float revHiDamping, float revHiPreDelay, float revHiCrosstalk, - bool chorus, float baseDelay, float variation, float period, - bool revStd, bool revStdDis, float revStdColoration, float revStdMix, - float revStdTime, float revStdDamping, float revStdPreDelay, - bool delay, u32 delayL, u32 delayR, u32 delayS, - u32 feedbackL, u32 feedbackR, u32 feedbackS, - u32 outputL, u32 outputR, u32 outputS) -: CEntity(uid, info, active, name), x34_volumeScale(volScale), - x38_revHi(revHi), x39_revHiDis(revHiDis), - x3c_revHiInfo(revHiColoration, revHiMix, revHiTime, revHiDamping, revHiPreDelay, revHiCrosstalk), - x54_chorus(chorus), x58_chorusInfo(baseDelay, variation, period), - x64_revStd(revStd), x65_revStdDis(revStdDis), - x68_revStdInfo(revStdColoration, revStdMix, revStdTime, revStdDamping, revStdPreDelay), - x7c_delay(delay), x80_delayInfo(delayL, delayR, delayS, feedbackL, feedbackR, feedbackS, outputL, outputR, outputS) -{} +CScriptRoomAcoustics::CScriptRoomAcoustics(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, + u32 volScale, bool revHi, bool revHiDis, float revHiColoration, + float revHiMix, float revHiTime, float revHiDamping, float revHiPreDelay, + float revHiCrosstalk, bool chorus, float baseDelay, float variation, + float period, bool revStd, bool revStdDis, float revStdColoration, + float revStdMix, float revStdTime, float revStdDamping, float revStdPreDelay, + bool delay, u32 delayL, u32 delayR, u32 delayS, u32 feedbackL, u32 feedbackR, + u32 feedbackS, u32 outputL, u32 outputR, u32 outputS) +: CEntity(uid, info, active, name) +, x34_volumeScale(volScale) +, x38_revHi(revHi) +, x39_revHiDis(revHiDis) +, x3c_revHiInfo(revHiColoration, revHiMix, revHiTime, revHiDamping, revHiPreDelay, revHiCrosstalk) +, x54_chorus(chorus) +, x58_chorusInfo(baseDelay, variation, period) +, x64_revStd(revStd) +, x65_revStdDis(revStdDis) +, x68_revStdInfo(revStdColoration, revStdMix, revStdTime, revStdDamping, revStdPreDelay) +, x7c_delay(delay) +, x80_delayInfo(delayL, delayR, delayS, feedbackL, feedbackR, feedbackS, outputL, outputR, outputS) {} -void CScriptRoomAcoustics::DisableAuxCallbacks() -{ - CSfxManager::DisableAuxProcessing(); - s_ActiveAcousticsAreaId = kInvalidAreaId; - CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale()); +void CScriptRoomAcoustics::DisableAuxCallbacks() { + CSfxManager::DisableAuxProcessing(); + s_ActiveAcousticsAreaId = kInvalidAreaId; + CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale()); } -void CScriptRoomAcoustics::EnableAuxCallbacks() -{ - if (!x30_24_active) - return; +void CScriptRoomAcoustics::EnableAuxCallbacks() { + if (!x30_24_active) + return; - bool applied = true; - if (x38_revHi) - CSfxManager::PrepareReverbHiCallback(x3c_revHiInfo); - else if (x54_chorus) - CSfxManager::PrepareChorusCallback(x58_chorusInfo); - else if (x64_revStd) - CSfxManager::PrepareReverbStdCallback(x68_revStdInfo); - else if (x7c_delay) - CSfxManager::PrepareDelayCallback(x80_delayInfo); - else - applied = false; + bool applied = true; + if (x38_revHi) + CSfxManager::PrepareReverbHiCallback(x3c_revHiInfo); + else if (x54_chorus) + CSfxManager::PrepareChorusCallback(x58_chorusInfo); + else if (x64_revStd) + CSfxManager::PrepareReverbStdCallback(x68_revStdInfo); + else if (x7c_delay) + CSfxManager::PrepareDelayCallback(x80_delayInfo); + else + applied = false; - if (applied) - CAudioSys::SetVolumeScale(x34_volumeScale); - s_ActiveAcousticsAreaId = x4_areaId; + if (applied) + CAudioSys::SetVolumeScale(x34_volumeScale); + s_ActiveAcousticsAreaId = x4_areaId; } -void CScriptRoomAcoustics::Think(float dt, CStateManager& stateMgr) -{ - /* Intentionally empty */ -} +void CScriptRoomAcoustics::Think(float dt, CStateManager& stateMgr) { /* Intentionally empty */ } -void CScriptRoomAcoustics::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CEntity::AcceptScriptMsg(msg, objId, stateMgr); +void CScriptRoomAcoustics::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); - switch (msg) - { - case EScriptObjectMessage::Activate: - EnableAuxCallbacks(); - break; - case EScriptObjectMessage::Deactivate: - if (s_ActiveAcousticsAreaId == x4_areaId) - { - s_ActiveAcousticsAreaId = kInvalidAreaId; - CSfxManager::DisableAuxProcessing(); - CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale()); - } - break; - default: break; + switch (msg) { + case EScriptObjectMessage::Activate: + EnableAuxCallbacks(); + break; + case EScriptObjectMessage::Deactivate: + if (s_ActiveAcousticsAreaId == x4_areaId) { + s_ActiveAcousticsAreaId = kInvalidAreaId; + CSfxManager::DisableAuxProcessing(); + CAudioSys::SetVolumeScale(CAudioSys::GetDefaultVolumeScale()); } + break; + default: + break; + } } -void CScriptRoomAcoustics::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptRoomAcoustics::Accept(IVisitor& visitor) { visitor.Visit(this); } -} +} // namespace urde diff --git a/Runtime/World/CScriptRoomAcoustics.hpp b/Runtime/World/CScriptRoomAcoustics.hpp index bd8c50730..8e17c44dc 100644 --- a/Runtime/World/CScriptRoomAcoustics.hpp +++ b/Runtime/World/CScriptRoomAcoustics.hpp @@ -5,43 +5,37 @@ #include "amuse/EffectDelay.hpp" #include "amuse/EffectReverb.hpp" -namespace urde -{ +namespace urde { -class CScriptRoomAcoustics : public CEntity -{ - u32 x34_volumeScale; +class CScriptRoomAcoustics : public CEntity { + u32 x34_volumeScale; - bool x38_revHi, x39_revHiDis; - amuse::EffectReverbHiInfo x3c_revHiInfo; + bool x38_revHi, x39_revHiDis; + amuse::EffectReverbHiInfo x3c_revHiInfo; - bool x54_chorus; - amuse::EffectChorusInfo x58_chorusInfo; + bool x54_chorus; + amuse::EffectChorusInfo x58_chorusInfo; - bool x64_revStd, x65_revStdDis; - amuse::EffectReverbStdInfo x68_revStdInfo; + bool x64_revStd, x65_revStdDis; + amuse::EffectReverbStdInfo x68_revStdInfo; - bool x7c_delay; - amuse::EffectDelayInfo x80_delayInfo; + bool x7c_delay; + amuse::EffectDelayInfo x80_delayInfo; public: - CScriptRoomAcoustics(TUniqueId uid, std::string_view name, - const CEntityInfo& info, bool active, u32 volScale, - bool revHi, bool revHiDis, float revHiColoration, float revHiMix, - float revHiTime, float revHiDamping, float revHiPreDelay, float revHiCrosstalk, - bool chorus, float baseDelay, float variation, float period, - bool revStd, bool revStdDis, float revStdColoration, float revStdMix, - float revStdTime, float revStdDamping, float revStdPreDelay, - bool delay, u32 delayL, u32 delayR, u32 delayS, - u32 feedbackL, u32 feedbackR, u32 feedbackS, - u32 outputL, u32 outputR, u32 outputS); - void Think(float dt, CStateManager& stateMgr); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); - void Accept(IVisitor& visitor); - void EnableAuxCallbacks(); + CScriptRoomAcoustics(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, u32 volScale, + bool revHi, bool revHiDis, float revHiColoration, float revHiMix, float revHiTime, + float revHiDamping, float revHiPreDelay, float revHiCrosstalk, bool chorus, float baseDelay, + float variation, float period, bool revStd, bool revStdDis, float revStdColoration, + float revStdMix, float revStdTime, float revStdDamping, float revStdPreDelay, bool delay, + u32 delayL, u32 delayR, u32 delayS, u32 feedbackL, u32 feedbackR, u32 feedbackS, u32 outputL, + u32 outputR, u32 outputS); + void Think(float dt, CStateManager& stateMgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Accept(IVisitor& visitor); + void EnableAuxCallbacks(); - static void DisableAuxCallbacks(); + static void DisableAuxCallbacks(); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptShadowProjector.cpp b/Runtime/World/CScriptShadowProjector.cpp index 58d2c1fd8..a749927bb 100644 --- a/Runtime/World/CScriptShadowProjector.cpp +++ b/Runtime/World/CScriptShadowProjector.cpp @@ -4,8 +4,7 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptShadowProjector::CScriptShadowProjector(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, const zeus::CVector3f& offset, @@ -18,80 +17,64 @@ CScriptShadowProjector::CScriptShadowProjector(TUniqueId uid, std::string_view n , xf8_zOffsetAdjust(f2) , xfc_opacity(opacity) , x100_opacityRecip(opacity < 0.00001 ? 1.f : opacityQ / opacity) -, x10c_textureSize(textureSize) -{ - x110_24_persistent = b2; +, x10c_textureSize(textureSize) { + x110_24_persistent = b2; } -void CScriptShadowProjector::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptShadowProjector::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptShadowProjector::Think(float dt, CStateManager& mgr) { + if (GetActive() && x110_25_shadowInvalidated) { + xfc_opacity = (x100_opacityRecip * xfc_opacity) - dt; + if (dt > 0.f) + return; + + x108_projectedShadow.reset(); + + x110_25_shadowInvalidated = false; + SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + } } -void CScriptShadowProjector::Think(float dt, CStateManager& mgr) -{ - if (GetActive() && x110_25_shadowInvalidated) - { - xfc_opacity = (x100_opacityRecip * xfc_opacity) - dt; - if (dt > 0.f) - return; +void CScriptShadowProjector::CreateProjectedShadow() { + if (!GetActive() || x104_target == kInvalidUniqueId || xfc_opacity <= 0.f) + x108_projectedShadow.reset(); + else + x108_projectedShadow.reset(new CProjectedShadow(x10c_textureSize, x10c_textureSize, x110_24_persistent)); +} - x108_projectedShadow.reset(); +void CScriptShadowProjector::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); + if (msg == EScriptObjectMessage::Decrement) { + if (x110_24_persistent) + return; - x110_25_shadowInvalidated = false; - SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + if (xfc_opacity <= 0.f) + return; + + x110_25_shadowInvalidated = true; + } else if (msg == EScriptObjectMessage::InitializedInArea) { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play) + continue; + + const CActor* act = TCastToConstPtr(mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))); + if (!act) + continue; + const CModelData* mData = act->GetModelData(); + if (!mData || (!mData->GetAnimationData() && !mData->GetNormalModel())) + continue; + + x104_target = act->GetUniqueId(); } -} - -void CScriptShadowProjector::CreateProjectedShadow() -{ - if (!GetActive() || x104_target == kInvalidUniqueId || xfc_opacity <= 0.f) - x108_projectedShadow.reset(); + if (x104_target == kInvalidUniqueId) + mgr.FreeScriptObject(GetUniqueId()); else - x108_projectedShadow.reset(new CProjectedShadow(x10c_textureSize, x10c_textureSize, x110_24_persistent)); + CreateProjectedShadow(); + + } else if (msg == EScriptObjectMessage::Activate) + CreateProjectedShadow(); } -void CScriptShadowProjector::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); - if (msg == EScriptObjectMessage::Decrement) - { - if (x110_24_persistent) - return; - - if (xfc_opacity <= 0.f) - return; - - x110_25_shadowInvalidated = true; - } - else if (msg == EScriptObjectMessage::InitializedInArea) - { - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play) - continue; - - const CActor* act = TCastToConstPtr(mgr.GetObjectById(mgr.GetIdForScript(conn.x8_objId))); - if (!act) - continue; - const CModelData* mData = act->GetModelData(); - if (!mData || (!mData->GetAnimationData() && !mData->GetNormalModel())) - continue; - - x104_target = act->GetUniqueId(); - } - if (x104_target == kInvalidUniqueId) - mgr.FreeScriptObject(GetUniqueId()); - else - CreateProjectedShadow(); - - } - else if (msg == EScriptObjectMessage::Activate) - CreateProjectedShadow(); -} - -void CScriptShadowProjector::PreRender(CStateManager&, const zeus::CFrustum &) -{ - -} -} +void CScriptShadowProjector::PreRender(CStateManager&, const zeus::CFrustum&) {} +} // namespace urde diff --git a/Runtime/World/CScriptShadowProjector.hpp b/Runtime/World/CScriptShadowProjector.hpp index 6d4e77a66..c770c6c4f 100644 --- a/Runtime/World/CScriptShadowProjector.hpp +++ b/Runtime/World/CScriptShadowProjector.hpp @@ -2,39 +2,35 @@ #include "World/CActor.hpp" -namespace urde -{ +namespace urde { class CProjectedShadow; -class CScriptShadowProjector : public CActor -{ - float xe8_scale; - zeus::CVector3f xec_offset; - float xf8_zOffsetAdjust; - float xfc_opacity; - float x100_opacityRecip; - TUniqueId x104_target; - std::unique_ptr x108_projectedShadow; - u32 x10c_textureSize; +class CScriptShadowProjector : public CActor { + float xe8_scale; + zeus::CVector3f xec_offset; + float xf8_zOffsetAdjust; + float xfc_opacity; + float x100_opacityRecip; + TUniqueId x104_target; + std::unique_ptr x108_projectedShadow; + u32 x10c_textureSize; - union { - struct - { - bool x110_24_persistent : 1; - bool x110_25_shadowInvalidated : 1; - }; - u8 x110_dummy = 0; + union { + struct { + bool x110_24_persistent : 1; + bool x110_25_shadowInvalidated : 1; }; + u8 x110_dummy = 0; + }; public: - CScriptShadowProjector(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, - const zeus::CVector3f&, bool, float, float, float, float, s32); + CScriptShadowProjector(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, + const zeus::CVector3f&, bool, float, float, float, float, s32); - void Accept(IVisitor& visitor); - void Think(float, CStateManager &); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); - void PreRender(CStateManager &, const zeus::CFrustum &); - void AddToRenderer(const zeus::CFrustum &, const CStateManager &) const {} - void CreateProjectedShadow(); + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PreRender(CStateManager&, const zeus::CFrustum&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} + void CreateProjectedShadow(); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptSound.cpp b/Runtime/World/CScriptSound.cpp index bff79da0a..32f0336a5 100644 --- a/Runtime/World/CScriptSound.cpp +++ b/Runtime/World/CScriptSound.cpp @@ -6,8 +6,7 @@ #include "CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { bool CScriptSound::sFirstInFrame = false; CScriptSound::CScriptSound(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, @@ -26,235 +25,188 @@ CScriptSound::CScriptSound(TUniqueId uid, std::string_view name, const CEntityIn , x112_prio(s16(prio)) , x114_pan(pan / 64.f - 1.f) , x116_(w6) -, x118_pitch(pitch / 8192.f) -{ - x11c_25_looped = looped; - x11c_26_nonEmitter = nonEmitter; - x11c_27_autoStart = autoStart; - x11c_28_occlusionTest = occlusionTest; - x11c_29_acoustics = acoustics; - x11c_30_worldSfx = worldSfx; - x11d_24_allowDuplicates = allowDuplicates; - if (x11c_30_worldSfx && (!x11c_26_nonEmitter || !x11c_25_looped)) - x11c_30_worldSfx = false; +, x118_pitch(pitch / 8192.f) { + x11c_25_looped = looped; + x11c_26_nonEmitter = nonEmitter; + x11c_27_autoStart = autoStart; + x11c_28_occlusionTest = occlusionTest; + x11c_29_acoustics = acoustics; + x11c_30_worldSfx = worldSfx; + x11d_24_allowDuplicates = allowDuplicates; + if (x11c_30_worldSfx && (!x11c_26_nonEmitter || !x11c_25_looped)) + x11c_30_worldSfx = false; } void CScriptSound::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptSound::PreThink(float dt, CStateManager& mgr) -{ - CEntity::PreThink(dt, mgr); - sFirstInFrame = true; - x11d_25_processedThisFrame = false; +void CScriptSound::PreThink(float dt, CStateManager& mgr) { + CEntity::PreThink(dt, mgr); + sFirstInFrame = true; + x11d_25_processedThisFrame = false; } static const CMaterialFilter kSolidFilter = CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::ProjectilePassthrough}); -float CScriptSound::GetOccludedVolumeAmount(const zeus::CVector3f& pos, const CStateManager& mgr) -{ - zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); - zeus::CVector3f soundToCam = camXf.origin - pos; - float soundToCamMag = soundToCam.magnitude(); - zeus::CVector3f soundToCamNorm = soundToCam * (1.f / soundToCamMag); - zeus::CVector3f thirdEdge = zeus::CVector3f::skUp - soundToCamNorm * soundToCamNorm.dot(zeus::CVector3f::skUp); - zeus::CVector3f cross = soundToCamNorm.cross(thirdEdge); - static float kInfluenceAmount = 3.f / soundToCamMag; - static float kInfluenceIncrement = kInfluenceAmount; +float CScriptSound::GetOccludedVolumeAmount(const zeus::CVector3f& pos, const CStateManager& mgr) { + zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr); + zeus::CVector3f soundToCam = camXf.origin - pos; + float soundToCamMag = soundToCam.magnitude(); + zeus::CVector3f soundToCamNorm = soundToCam * (1.f / soundToCamMag); + zeus::CVector3f thirdEdge = zeus::CVector3f::skUp - soundToCamNorm * soundToCamNorm.dot(zeus::CVector3f::skUp); + zeus::CVector3f cross = soundToCamNorm.cross(thirdEdge); + static float kInfluenceAmount = 3.f / soundToCamMag; + static float kInfluenceIncrement = kInfluenceAmount; - int totalCount = 0; - int invalCount = 0; - float f17 = -kInfluenceAmount; - while (f17 <= kInfluenceAmount) - { - zeus::CVector3f angledDir = thirdEdge * f17 + soundToCamNorm; - float f16 = -kInfluenceAmount; - while (f16 <= kInfluenceAmount) - { - if (mgr.RayStaticIntersection(pos, (cross * f16 + angledDir).normalized(), - soundToCamMag, kSolidFilter).IsInvalid()) - ++invalCount; - ++totalCount; - f16 += kInfluenceIncrement; - } - f17 += kInfluenceIncrement; + int totalCount = 0; + int invalCount = 0; + float f17 = -kInfluenceAmount; + while (f17 <= kInfluenceAmount) { + zeus::CVector3f angledDir = thirdEdge * f17 + soundToCamNorm; + float f16 = -kInfluenceAmount; + while (f16 <= kInfluenceAmount) { + if (mgr.RayStaticIntersection(pos, (cross * f16 + angledDir).normalized(), soundToCamMag, kSolidFilter) + .IsInvalid()) + ++invalCount; + ++totalCount; + f16 += kInfluenceIncrement; } + f17 += kInfluenceIncrement; + } - return invalCount / float(totalCount) * 0.42f + 0.58f; + return invalCount / float(totalCount) * 0.42f + 0.58f; } -void CScriptSound::Think(float dt, CStateManager& mgr) -{ - if (x11c_31_selfFree && (!GetActive() || x11c_25_looped || !x11c_27_autoStart)) - { - mgr.FreeScriptObject(GetUniqueId()); - } - else if (GetActive()) - { - if (!x11c_25_looped && x11c_27_autoStart && !x11c_24_playRequested && - xec_sfxHandle && !CSfxManager::IsPlaying(xec_sfxHandle)) - mgr.FreeScriptObject(GetUniqueId()); +void CScriptSound::Think(float dt, CStateManager& mgr) { + if (x11c_31_selfFree && (!GetActive() || x11c_25_looped || !x11c_27_autoStart)) { + mgr.FreeScriptObject(GetUniqueId()); + } else if (GetActive()) { + if (!x11c_25_looped && x11c_27_autoStart && !x11c_24_playRequested && xec_sfxHandle && + !CSfxManager::IsPlaying(xec_sfxHandle)) + mgr.FreeScriptObject(GetUniqueId()); - if (!x11c_26_nonEmitter && xec_sfxHandle) - { - if (xf8_updateTimer <= 0.f) - { - xf8_updateTimer = 0.25f; - CSfxManager::UpdateEmitter(xec_sfxHandle, GetTranslation(), zeus::CVector3f::skZero, xf2_maxVolUpd); - } + if (!x11c_26_nonEmitter && xec_sfxHandle) { + if (xf8_updateTimer <= 0.f) { + xf8_updateTimer = 0.25f; + CSfxManager::UpdateEmitter(xec_sfxHandle, GetTranslation(), zeus::CVector3f::skZero, xf2_maxVolUpd); + } else { + xf8_updateTimer -= dt; + } + } + + if (xec_sfxHandle && !x11c_26_nonEmitter && x11c_28_occlusionTest) { + if (xe8_occUpdateTimer <= 0.f && sFirstInFrame) { + sFirstInFrame = false; + float occVol = GetOccludedVolumeAmount(GetTranslation(), mgr); + float newMaxVol = std::max(occVol * x10e_vol, x10c_minVol); + if (newMaxVol != xf0_maxVol) { + xf0_maxVol = newMaxVol; + float delta = xf0_maxVol - xf2_maxVolUpd; + xf4_maxVolUpdDelta = delta / 10.5f; + if (xf4_maxVolUpdDelta == 0.f) { + if (xf2_maxVolUpd < xf0_maxVol) + xf4_maxVolUpdDelta = 1.f / 127.f; else - { - xf8_updateTimer -= dt; - } + xf4_maxVolUpdDelta = -1.f / 127.f; + } } + xe8_occUpdateTimer = 0.5f; + } else { + xe8_occUpdateTimer -= dt; + } - if (xec_sfxHandle && !x11c_26_nonEmitter && x11c_28_occlusionTest) - { - if (xe8_occUpdateTimer <= 0.f && sFirstInFrame) - { - sFirstInFrame = false; - float occVol = GetOccludedVolumeAmount(GetTranslation(), mgr); - float newMaxVol = std::max(occVol * x10e_vol, x10c_minVol); - if (newMaxVol != xf0_maxVol) - { - xf0_maxVol = newMaxVol; - float delta = xf0_maxVol - xf2_maxVolUpd; - xf4_maxVolUpdDelta = delta / 10.5f; - if (xf4_maxVolUpdDelta == 0.f) - { - if (xf2_maxVolUpd < xf0_maxVol) - xf4_maxVolUpdDelta = 1.f / 127.f; - else - xf4_maxVolUpdDelta = -1.f / 127.f; - } - } - xe8_occUpdateTimer = 0.5f; - } - else - { - xe8_occUpdateTimer -= dt; - } - - if (xf2_maxVolUpd != xf0_maxVol) - { - xf2_maxVolUpd += xf4_maxVolUpdDelta; - if (xf4_maxVolUpdDelta > 0.f && xf2_maxVolUpd > xf0_maxVol) - xf2_maxVolUpd = xf0_maxVol; - if (xf4_maxVolUpdDelta < 0.f && xf2_maxVolUpd < xf0_maxVol) - xf2_maxVolUpd = xf0_maxVol; - CSfxManager::UpdateEmitter(xec_sfxHandle, GetTranslation(), zeus::CVector3f::skZero, xf2_maxVolUpd); - } - } - - if (x11c_24_playRequested) - { - xfc_startDelay -= dt; - if (xfc_startDelay <= 0.f) - { - x11c_24_playRequested = false; - PlaySound(mgr); - } - } - - if (x118_pitch != 0.f && xec_sfxHandle) - CSfxManager::PitchBend(xec_sfxHandle, x118_pitch); + if (xf2_maxVolUpd != xf0_maxVol) { + xf2_maxVolUpd += xf4_maxVolUpdDelta; + if (xf4_maxVolUpdDelta > 0.f && xf2_maxVolUpd > xf0_maxVol) + xf2_maxVolUpd = xf0_maxVol; + if (xf4_maxVolUpdDelta < 0.f && xf2_maxVolUpd < xf0_maxVol) + xf2_maxVolUpd = xf0_maxVol; + CSfxManager::UpdateEmitter(xec_sfxHandle, GetTranslation(), zeus::CVector3f::skZero, xf2_maxVolUpd); + } } + + if (x11c_24_playRequested) { + xfc_startDelay -= dt; + if (xfc_startDelay <= 0.f) { + x11c_24_playRequested = false; + PlaySound(mgr); + } + } + + if (x118_pitch != 0.f && xec_sfxHandle) + CSfxManager::PitchBend(xec_sfxHandle, x118_pitch); + } } -void CScriptSound::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); +void CScriptSound::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); - switch (msg) - { - case EScriptObjectMessage::Registered: - { - if (GetActive() && x11c_27_autoStart) - x11c_24_playRequested = true; - x11c_31_selfFree = mgr.GetIsGeneratingObject(); - } + switch (msg) { + case EScriptObjectMessage::Registered: { + if (GetActive() && x11c_27_autoStart) + x11c_24_playRequested = true; + x11c_31_selfFree = mgr.GetIsGeneratingObject(); + } break; + case EScriptObjectMessage::Play: { + if (GetActive()) + PlaySound(mgr); + } break; + case EScriptObjectMessage::Stop: { + if (GetActive()) + StopSound(mgr); + } break; + case EScriptObjectMessage::Deactivate: { + if (GetActive()) + StopSound(mgr); + } break; + case EScriptObjectMessage::Activate: { + if (GetActive()) + x11c_24_playRequested = true; + } break; + case EScriptObjectMessage::Deleted: { + if (!x11c_30_worldSfx) + StopSound(mgr); + } break; + default: break; - case EScriptObjectMessage::Play: - { - if (GetActive()) - PlaySound(mgr); - } - break; - case EScriptObjectMessage::Stop: - { - if (GetActive()) - StopSound(mgr); - } - break; - case EScriptObjectMessage::Deactivate: - { - if (GetActive()) - StopSound(mgr); - } - break; - case EScriptObjectMessage::Activate: - { - if (GetActive()) - x11c_24_playRequested = true; - } - break; - case EScriptObjectMessage::Deleted: - { - if (!x11c_30_worldSfx) - StopSound(mgr); - } - break; - default:break; - } + } } -void CScriptSound::PlaySound(CStateManager& mgr) -{ - if ((x11d_24_allowDuplicates || !xec_sfxHandle || xec_sfxHandle->IsClosed()) && !x11d_25_processedThisFrame) - { - x11d_25_processedThisFrame = true; - if (x11c_26_nonEmitter) - { - if (!x11c_30_worldSfx || !mgr.GetWorld()->HasGlobalSound(x100_soundId)) - { - xec_sfxHandle = CSfxManager::SfxStart(x100_soundId, x10e_vol, x114_pan, - x11c_29_acoustics, x112_prio, x11c_25_looped, - x11c_30_worldSfx ? kInvalidAreaId : GetAreaIdAlways()); - if (x11c_30_worldSfx) - mgr.WorldNC()->AddGlobalSound(xec_sfxHandle); - } - } - else - { - float occVol = x11c_28_occlusionTest ? GetOccludedVolumeAmount(GetTranslation(), mgr) : 1.f; - xf0_maxVol = xf2_maxVolUpd = x10e_vol * occVol; - CAudioSys::C3DEmitterParmData data = {}; - data.x0_pos = GetTranslation(); - data.x18_maxDist = x104_maxDist; - data.x1c_distComp = x108_distComp; - data.x20_flags = 1; // Continuous parameter update - data.x24_sfxId = x100_soundId; - data.x26_maxVol = xf0_maxVol; - data.x27_minVol = x10c_minVol; - data.x29_prio = 0x7f; - xec_sfxHandle = CSfxManager::AddEmitter(data, x11c_29_acoustics, x112_prio, - x11c_25_looped, GetAreaIdAlways()); - } +void CScriptSound::PlaySound(CStateManager& mgr) { + if ((x11d_24_allowDuplicates || !xec_sfxHandle || xec_sfxHandle->IsClosed()) && !x11d_25_processedThisFrame) { + x11d_25_processedThisFrame = true; + if (x11c_26_nonEmitter) { + if (!x11c_30_worldSfx || !mgr.GetWorld()->HasGlobalSound(x100_soundId)) { + xec_sfxHandle = CSfxManager::SfxStart(x100_soundId, x10e_vol, x114_pan, x11c_29_acoustics, x112_prio, + x11c_25_looped, x11c_30_worldSfx ? kInvalidAreaId : GetAreaIdAlways()); + if (x11c_30_worldSfx) + mgr.WorldNC()->AddGlobalSound(xec_sfxHandle); + } + } else { + float occVol = x11c_28_occlusionTest ? GetOccludedVolumeAmount(GetTranslation(), mgr) : 1.f; + xf0_maxVol = xf2_maxVolUpd = x10e_vol * occVol; + CAudioSys::C3DEmitterParmData data = {}; + data.x0_pos = GetTranslation(); + data.x18_maxDist = x104_maxDist; + data.x1c_distComp = x108_distComp; + data.x20_flags = 1; // Continuous parameter update + data.x24_sfxId = x100_soundId; + data.x26_maxVol = xf0_maxVol; + data.x27_minVol = x10c_minVol; + data.x29_prio = 0x7f; + xec_sfxHandle = CSfxManager::AddEmitter(data, x11c_29_acoustics, x112_prio, x11c_25_looped, GetAreaIdAlways()); } + } } -void CScriptSound::StopSound(CStateManager& mgr) -{ - x11c_24_playRequested = false; - if (x11c_30_worldSfx && x11c_26_nonEmitter) - { - mgr.WorldNC()->StopGlobalSound(x100_soundId); - xec_sfxHandle.reset(); - } - else if (xec_sfxHandle) - { - CSfxManager::RemoveEmitter(xec_sfxHandle); - xec_sfxHandle.reset(); - } -} +void CScriptSound::StopSound(CStateManager& mgr) { + x11c_24_playRequested = false; + if (x11c_30_worldSfx && x11c_26_nonEmitter) { + mgr.WorldNC()->StopGlobalSound(x100_soundId); + xec_sfxHandle.reset(); + } else if (xec_sfxHandle) { + CSfxManager::RemoveEmitter(xec_sfxHandle); + xec_sfxHandle.reset(); + } } +} // namespace urde diff --git a/Runtime/World/CScriptSound.hpp b/Runtime/World/CScriptSound.hpp index e919845d7..942fc6710 100644 --- a/Runtime/World/CScriptSound.hpp +++ b/Runtime/World/CScriptSound.hpp @@ -2,63 +2,58 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { -class CScriptSound : public CActor -{ - static bool sFirstInFrame; +class CScriptSound : public CActor { + static bool sFirstInFrame; - float xe8_occUpdateTimer = 0.f; - CSfxHandle xec_sfxHandle; - float xf0_maxVol = 0.f; - float xf2_maxVolUpd = 0.f; - float xf4_maxVolUpdDelta = 0.f; - float xf8_updateTimer = 0.f; - float xfc_startDelay; - u16 x100_soundId; - float x104_maxDist; - float x108_distComp; - float x10c_minVol; - float x10e_vol; - s16 x110_; - s16 x112_prio; - float x114_pan; - bool x116_; - float x118_pitch; - union - { - struct - { - bool x11c_24_playRequested : 1; - bool x11c_25_looped : 1; - bool x11c_26_nonEmitter : 1; - bool x11c_27_autoStart : 1; - bool x11c_28_occlusionTest : 1; - bool x11c_29_acoustics : 1; - bool x11c_30_worldSfx : 1; - bool x11c_31_selfFree : 1; - bool x11d_24_allowDuplicates : 1; - bool x11d_25_processedThisFrame : 1; - }; - u32 x11c_dummy = 0; + float xe8_occUpdateTimer = 0.f; + CSfxHandle xec_sfxHandle; + float xf0_maxVol = 0.f; + float xf2_maxVolUpd = 0.f; + float xf4_maxVolUpdDelta = 0.f; + float xf8_updateTimer = 0.f; + float xfc_startDelay; + u16 x100_soundId; + float x104_maxDist; + float x108_distComp; + float x10c_minVol; + float x10e_vol; + s16 x110_; + s16 x112_prio; + float x114_pan; + bool x116_; + float x118_pitch; + union { + struct { + bool x11c_24_playRequested : 1; + bool x11c_25_looped : 1; + bool x11c_26_nonEmitter : 1; + bool x11c_27_autoStart : 1; + bool x11c_28_occlusionTest : 1; + bool x11c_29_acoustics : 1; + bool x11c_30_worldSfx : 1; + bool x11c_31_selfFree : 1; + bool x11d_24_allowDuplicates : 1; + bool x11d_25_processedThisFrame : 1; }; + u32 x11c_dummy = 0; + }; - static float GetOccludedVolumeAmount(const zeus::CVector3f& pos, const CStateManager& mgr); + static float GetOccludedVolumeAmount(const zeus::CVector3f& pos, const CStateManager& mgr); public: - CScriptSound(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - u16 soundId, bool active, float maxDist, float distComp, float startDelay, u32 minVol, - u32 vol, u32 w3, u32 prio, u32 pan, u32 w6, bool looped, bool nonEmitter, bool autoStart, - bool occlusionTest, bool acoustics, bool worldSfx, bool allowDuplicates, s32 pitch); + CScriptSound(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, u16 soundId, + bool active, float maxDist, float distComp, float startDelay, u32 minVol, u32 vol, u32 w3, u32 prio, + u32 pan, u32 w6, bool looped, bool nonEmitter, bool autoStart, bool occlusionTest, bool acoustics, + bool worldSfx, bool allowDuplicates, s32 pitch); - void Accept(IVisitor& visitor); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} - void PreThink(float, CStateManager&); - void Think(float, CStateManager&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void PlaySound(CStateManager&); - void StopSound(CStateManager&); + void Accept(IVisitor& visitor); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} + void PreThink(float, CStateManager&); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PlaySound(CStateManager&); + void StopSound(CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptSpawnPoint.cpp b/Runtime/World/CScriptSpawnPoint.cpp index b13aa8b66..dda0a83d2 100644 --- a/Runtime/World/CScriptSpawnPoint.cpp +++ b/Runtime/World/CScriptSpawnPoint.cpp @@ -5,88 +5,73 @@ #include "Particle/CGenDescription.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CScriptSpawnPoint::CScriptSpawnPoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, +CScriptSpawnPoint::CScriptSpawnPoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, + const zeus::CTransform& xf, const rstl::reserved_vector& itemCounts, bool defaultSpawn, bool active, bool morphed) -: CEntity(uid, info, active, name), x34_xf(xf), x64_itemCounts(itemCounts) -{ +: CEntity(uid, info, active, name), x34_xf(xf), x64_itemCounts(itemCounts) { #ifndef NDEBUG - x64_itemCounts[int(CPlayerState::EItemType::GravitySuit)] = 1; - x64_itemCounts[int(CPlayerState::EItemType::ThermalVisor)] = 1; - x64_itemCounts[int(CPlayerState::EItemType::XRayVisor)] = 1; - x64_itemCounts[int(CPlayerState::EItemType::GrappleBeam)] = 1; - x64_itemCounts[int(CPlayerState::EItemType::BoostBall)] = 1; - x64_itemCounts[int(CPlayerState::EItemType::ChargeBeam)] = 1; - x64_itemCounts[int(CPlayerState::EItemType::PowerBombs)] = 8; + x64_itemCounts[int(CPlayerState::EItemType::GravitySuit)] = 1; + x64_itemCounts[int(CPlayerState::EItemType::ThermalVisor)] = 1; + x64_itemCounts[int(CPlayerState::EItemType::XRayVisor)] = 1; + x64_itemCounts[int(CPlayerState::EItemType::GrappleBeam)] = 1; + x64_itemCounts[int(CPlayerState::EItemType::BoostBall)] = 1; + x64_itemCounts[int(CPlayerState::EItemType::ChargeBeam)] = 1; + x64_itemCounts[int(CPlayerState::EItemType::PowerBombs)] = 8; #endif - x10c_24_firstSpawn = defaultSpawn; - x10c_25_morphed = morphed; + x10c_24_firstSpawn = defaultSpawn; + x10c_25_morphed = morphed; } -void CScriptSpawnPoint::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptSpawnPoint::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptSpawnPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CEntity::AcceptScriptMsg(msg, objId, stateMgr); +void CScriptSpawnPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); - if (msg == EScriptObjectMessage::SetToZero || msg == EScriptObjectMessage::Reset) - { - if (msg == EScriptObjectMessage::Reset) - { - using EPlayerItemType = CPlayerState::EItemType; - const std::shared_ptr& plState = stateMgr.GetPlayerState(); - for (u32 i = 0; i < u32(EPlayerItemType::Max); ++i) - { - plState->ReInitalizePowerUp(EPlayerItemType(i), GetPowerup(EPlayerItemType(i))); - plState->ResetAndIncrPickUp(EPlayerItemType(i), GetPowerup(EPlayerItemType(i))); - } - } - - if (GetActive()) - { - CPlayer* player = stateMgr.Player(); - - if (x4_areaId != stateMgr.GetNextAreaId()) - { - CGameArea* area = stateMgr.WorldNC()->GetArea(x4_areaId); - if (area->IsPostConstructed() && area->GetOcclusionState() == CGameArea::EOcclusionState::Occluded) - { - /* while (!area->TryTakingOutOfARAM()) {} */ - CWorld::PropogateAreaChain(CGameArea::EOcclusionState::Visible, area, stateMgr.WorldNC()); - } - - stateMgr.SetCurrentAreaId(x4_areaId); - stateMgr.SetActorAreaId(*stateMgr.Player(), x4_areaId); - player->Teleport(GetTransform(), stateMgr, true); - player->SetSpawnedMorphBallState(CPlayer::EPlayerMorphBallState(x10c_25_morphed), stateMgr); - - if (area->IsPostConstructed() && area->GetOcclusionState() == CGameArea::EOcclusionState::Visible) - CWorld::PropogateAreaChain(CGameArea::EOcclusionState::Occluded, - stateMgr.WorldNC()->GetArea(stateMgr.GetNextAreaId()), - stateMgr.WorldNC()); - } - else - { - player->Teleport(GetTransform(), stateMgr, true); - player->SetSpawnedMorphBallState(CPlayer::EPlayerMorphBallState(x10c_25_morphed), stateMgr); - } - } - - CEntity::SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); + if (msg == EScriptObjectMessage::SetToZero || msg == EScriptObjectMessage::Reset) { + if (msg == EScriptObjectMessage::Reset) { + using EPlayerItemType = CPlayerState::EItemType; + const std::shared_ptr& plState = stateMgr.GetPlayerState(); + for (u32 i = 0; i < u32(EPlayerItemType::Max); ++i) { + plState->ReInitalizePowerUp(EPlayerItemType(i), GetPowerup(EPlayerItemType(i))); + plState->ResetAndIncrPickUp(EPlayerItemType(i), GetPowerup(EPlayerItemType(i))); + } } + + if (GetActive()) { + CPlayer* player = stateMgr.Player(); + + if (x4_areaId != stateMgr.GetNextAreaId()) { + CGameArea* area = stateMgr.WorldNC()->GetArea(x4_areaId); + if (area->IsPostConstructed() && area->GetOcclusionState() == CGameArea::EOcclusionState::Occluded) { + /* while (!area->TryTakingOutOfARAM()) {} */ + CWorld::PropogateAreaChain(CGameArea::EOcclusionState::Visible, area, stateMgr.WorldNC()); + } + + stateMgr.SetCurrentAreaId(x4_areaId); + stateMgr.SetActorAreaId(*stateMgr.Player(), x4_areaId); + player->Teleport(GetTransform(), stateMgr, true); + player->SetSpawnedMorphBallState(CPlayer::EPlayerMorphBallState(x10c_25_morphed), stateMgr); + + if (area->IsPostConstructed() && area->GetOcclusionState() == CGameArea::EOcclusionState::Visible) + CWorld::PropogateAreaChain(CGameArea::EOcclusionState::Occluded, + stateMgr.WorldNC()->GetArea(stateMgr.GetNextAreaId()), stateMgr.WorldNC()); + } else { + player->Teleport(GetTransform(), stateMgr, true); + player->SetSpawnedMorphBallState(CPlayer::EPlayerMorphBallState(x10c_25_morphed), stateMgr); + } + } + + CEntity::SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); + } } -u32 CScriptSpawnPoint::GetPowerup(CPlayerState::EItemType item) const -{ - int idx = int(item); - if (idx >= int(CPlayerState::EItemType::Max) || idx < 0) - return x64_itemCounts.front(); - return x64_itemCounts[idx]; -} +u32 CScriptSpawnPoint::GetPowerup(CPlayerState::EItemType item) const { + int idx = int(item); + if (idx >= int(CPlayerState::EItemType::Max) || idx < 0) + return x64_itemCounts.front(); + return x64_itemCounts[idx]; } +} // namespace urde diff --git a/Runtime/World/CScriptSpawnPoint.hpp b/Runtime/World/CScriptSpawnPoint.hpp index 68b1b47c7..e998fc0d0 100644 --- a/Runtime/World/CScriptSpawnPoint.hpp +++ b/Runtime/World/CScriptSpawnPoint.hpp @@ -4,33 +4,28 @@ #include "zeus/CTransform.hpp" #include "CPlayerState.hpp" -namespace urde -{ +namespace urde { -class CScriptSpawnPoint : public CEntity -{ - zeus::CTransform x34_xf; - rstl::reserved_vector x64_itemCounts; - union - { - struct - { - bool x10c_24_firstSpawn : 1; - bool x10c_25_morphed : 1; - }; - u8 _dummy = 0; +class CScriptSpawnPoint : public CEntity { + zeus::CTransform x34_xf; + rstl::reserved_vector x64_itemCounts; + union { + struct { + bool x10c_24_firstSpawn : 1; + bool x10c_25_morphed : 1; }; -public: - CScriptSpawnPoint(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - const rstl::reserved_vector& itemCounts, - bool, bool, bool); + u8 _dummy = 0; + }; - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); - bool FirstSpawn() const { return x10c_24_firstSpawn; } - const zeus::CTransform& GetTransform() const { return x34_xf; } - u32 GetPowerup(CPlayerState::EItemType item) const; +public: + CScriptSpawnPoint(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + const rstl::reserved_vector& itemCounts, bool, bool, bool); + + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + bool FirstSpawn() const { return x10c_24_firstSpawn; } + const zeus::CTransform& GetTransform() const { return x34_xf; } + u32 GetPowerup(CPlayerState::EItemType item) const; }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptSpecialFunction.cpp b/Runtime/World/CScriptSpecialFunction.cpp index 8254b6d99..ecbd9545e 100644 --- a/Runtime/World/CScriptSpecialFunction.cpp +++ b/Runtime/World/CScriptSpecialFunction.cpp @@ -15,15 +15,14 @@ #include "hecl/CVarManager.hpp" -namespace urde -{ +namespace urde { CScriptSpecialFunction::CScriptSpecialFunction(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, ESpecialFunction func, std::string_view lcName, float f1, float f2, float f3, float f4, const zeus::CVector3f& vec, const zeus::CColor& col, bool active, - const CDamageInfo& dInfo, s32 aId1, s32 aId2, CPlayerState::EItemType itemType, - s16 sId1, s16 sId2, s16 sId3) + const CDamageInfo& dInfo, s32 aId1, s32 aId2, + CPlayerState::EItemType itemType, s16 sId1, s16 sId2, s16 sId3) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(), CActorParameters::None(), kInvalidUniqueId) , xe8_function(func) @@ -40,464 +39,403 @@ CScriptSpecialFunction::CScriptSpecialFunction(TUniqueId uid, std::string_view n , x174_(CSfxManager::TranslateSFXID(sId3)) , x1bc_areaSaveId(aId1) , x1c0_layerIdx(aId2) -, x1c4_item(itemType) -{ - x1e4_26_ = true; - if (xe8_function == ESpecialFunction::HUDTarget) - x1c8_ = {{zeus::CVector3f(-1.f), zeus::CVector3f(1.f)}}; +, x1c4_item(itemType) { + x1e4_26_ = true; + if (xe8_function == ESpecialFunction::HUDTarget) + x1c8_ = {{zeus::CVector3f(-1.f), zeus::CVector3f(1.f)}}; } void CScriptSpecialFunction::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptSpecialFunction::Think(float dt, CStateManager& mgr) -{ - switch(xe8_function) - { - case ESpecialFunction::PlayerFollowLocator: ThinkPlayerFollowLocator(dt, mgr); break; - case ESpecialFunction::SpinnerController: ThinkSpinnerController(dt, mgr, ESpinnerControllerMode::Zero); break; - case ESpecialFunction::ShotSpinnerController: ThinkSpinnerController(dt, mgr, ESpinnerControllerMode::One); break; - case ESpecialFunction::ObjectFollowLocator: ThinkObjectFollowLocator(dt, mgr); break; - case ESpecialFunction::ObjectFollowObject: ThinkObjectFollowObject(dt, mgr); break; - case ESpecialFunction::ChaffTarget: ThinkChaffTarget(dt, mgr); break; - case ESpecialFunction::ViewFrustumTester: - { - if (x1e4_28_frustumEntered) - { - x1e4_28_frustumEntered = false; - SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); - } - if (x1e4_29_frustumExited) - { - x1e4_29_frustumExited = false; - SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); - } - break; +void CScriptSpecialFunction::Think(float dt, CStateManager& mgr) { + switch (xe8_function) { + case ESpecialFunction::PlayerFollowLocator: + ThinkPlayerFollowLocator(dt, mgr); + break; + case ESpecialFunction::SpinnerController: + ThinkSpinnerController(dt, mgr, ESpinnerControllerMode::Zero); + break; + case ESpecialFunction::ShotSpinnerController: + ThinkSpinnerController(dt, mgr, ESpinnerControllerMode::One); + break; + case ESpecialFunction::ObjectFollowLocator: + ThinkObjectFollowLocator(dt, mgr); + break; + case ESpecialFunction::ObjectFollowObject: + ThinkObjectFollowObject(dt, mgr); + break; + case ESpecialFunction::ChaffTarget: + ThinkChaffTarget(dt, mgr); + break; + case ESpecialFunction::ViewFrustumTester: { + if (x1e4_28_frustumEntered) { + x1e4_28_frustumEntered = false; + SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); } - case ESpecialFunction::SaveStation: ThinkSaveStation(dt, mgr); break; - case ESpecialFunction::IntroBossRingController: ThinkIntroBossRingController(dt, mgr); break; - case ESpecialFunction::RainSimulator: ThinkRainSimulator(dt, mgr); break; - case ESpecialFunction::AreaDamage: ThinkAreaDamage(dt, mgr); break; - case ESpecialFunction::ScaleActor: ThinkActorScale(dt, mgr); break; - case ESpecialFunction::PlayerInAreaRelay: ThinkPlayerInArea(dt, mgr); break; - case ESpecialFunction::Billboard: - { - if (x1e8_ && x1e5_26_displayBillboard) - { - SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); - x1e5_26_displayBillboard = false; - } - break; + if (x1e4_29_frustumExited) { + x1e4_29_frustumExited = false; + SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); } - default: break; + break; + } + case ESpecialFunction::SaveStation: + ThinkSaveStation(dt, mgr); + break; + case ESpecialFunction::IntroBossRingController: + ThinkIntroBossRingController(dt, mgr); + break; + case ESpecialFunction::RainSimulator: + ThinkRainSimulator(dt, mgr); + break; + case ESpecialFunction::AreaDamage: + ThinkAreaDamage(dt, mgr); + break; + case ESpecialFunction::ScaleActor: + ThinkActorScale(dt, mgr); + break; + case ESpecialFunction::PlayerInAreaRelay: + ThinkPlayerInArea(dt, mgr); + break; + case ESpecialFunction::Billboard: { + if (x1e8_ && x1e5_26_displayBillboard) { + SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); + x1e5_26_displayBillboard = false; } + break; + } + default: + break; + } } -static const ERumbleFxId fxTranslation[6] = -{ - ERumbleFxId::Twenty, - ERumbleFxId::One, - ERumbleFxId::TwentyOne, - ERumbleFxId::TwentyTwo, - ERumbleFxId::TwentyThree, - ERumbleFxId::Zero -}; +static const ERumbleFxId fxTranslation[6] = {ERumbleFxId::Twenty, ERumbleFxId::One, ERumbleFxId::TwentyOne, + ERumbleFxId::TwentyTwo, ERumbleFxId::TwentyThree, ERumbleFxId::Zero}; -void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (GetActive() && msg == EScriptObjectMessage::Deactivate && xe8_function == ESpecialFunction::Billboard) - { - mgr.SetPendingOnScreenTex(CAssetId(), zeus::CVector2i(), zeus::CVector2i()); - if (x1e8_) - x1e8_ = TLockedToken(); - x1e5_26_displayBillboard = false; +void CScriptSpecialFunction::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (GetActive() && msg == EScriptObjectMessage::Deactivate && xe8_function == ESpecialFunction::Billboard) { + mgr.SetPendingOnScreenTex(CAssetId(), zeus::CVector2i(), zeus::CVector2i()); + if (x1e8_) + x1e8_ = TLockedToken(); + x1e5_26_displayBillboard = false; + } + CActor::AcceptScriptMsg(msg, uid, mgr); + + if (xe8_function == ESpecialFunction::ChaffTarget && msg == EScriptObjectMessage::InitializedInArea) + AddMaterial(EMaterialTypes::Target, mgr); + + if (GetActive()) { + switch (xe8_function) { + case ESpecialFunction::HUDFadeIn: { + if (msg == EScriptObjectMessage::Action) + mgr.Player()->SetHudDisable(xfc_, 0.f, 0.5f); + break; } - CActor::AcceptScriptMsg(msg, uid, mgr); + case ESpecialFunction::EscapeSequence: { + if (msg == EScriptObjectMessage::Action && xfc_ >= 0.f) + mgr.ResetEscapeSequenceTimer(xfc_); + break; + } + case ESpecialFunction::SpinnerController: { + switch (msg) { + case EScriptObjectMessage::Stop: { + x1e4_25_spinnerCanMove = false; + break; + } + case EScriptObjectMessage::Play: { + x1e4_25_spinnerCanMove = true; + mgr.Player()->SetAngularVelocityWR(zeus::CAxisAngle::sIdentity); + break; + } + case EScriptObjectMessage::Deactivate: + DeleteEmitter(x178_sfxHandle); + break; + default: + break; + } + break; + } + case ESpecialFunction::ShotSpinnerController: { + switch (msg) { + case EScriptObjectMessage::Increment: { + x16c_ = zeus::clamp(0.f, x16c_ + 1.f, 1.f); + SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); + break; + } + case EScriptObjectMessage::SetToMax: { + SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); + break; + } + case EScriptObjectMessage::SetToZero: { + x16c_ = -0.5f * x104_; + break; + } + default: + break; + } + break; + } + case ESpecialFunction::MapStation: { + if (msg == EScriptObjectMessage::Action) { + mgr.MapWorldInfo()->SetMapStationUsed(true); + const_cast(*mgr.WorldNC()->GetMapWorld()) + .RecalculateWorldSphere(*mgr.MapWorldInfo(), *mgr.GetWorld()); + } + break; + } + case ESpecialFunction::MissileStation: { + if (msg == EScriptObjectMessage::Action) { + CPlayerState& pState = *mgr.GetPlayerState().get(); + pState.ResetAndIncrPickUp(CPlayerState::EItemType::Missiles, + pState.GetItemCapacity(CPlayerState::EItemType::Missiles)); + } + break; + } + case ESpecialFunction::PowerBombStation: { + if (msg == EScriptObjectMessage::Action) { + CPlayerState& pState = *mgr.GetPlayerState().get(); + pState.ResetAndIncrPickUp(CPlayerState::EItemType::PowerBombs, + pState.GetItemCapacity(CPlayerState::EItemType::PowerBombs)); + } + break; + } + case ESpecialFunction::SaveStation: { + if (msg == EScriptObjectMessage::Action) { + g_GameState->GetPlayerState()->IncrPickup(CPlayerState::EItemType::EnergyTanks, 1); + if (g_GameState->GetCardSerial() == 0) + SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); + else { + mgr.DeferStateTransition(EStateManagerTransition::SaveGame); + x1e5_24_doSave = true; + } + } + break; + } + case ESpecialFunction::IntroBossRingController: { + if (x1a8_ != 3) { + switch (msg) { + case EScriptObjectMessage::Play: { + if (x1a8_ != 0) + RingScramble(mgr); - if (xe8_function == ESpecialFunction::ChaffTarget && msg == EScriptObjectMessage::InitializedInArea) - AddMaterial(EMaterialTypes::Target, mgr); + for (SRingController& cont : x198_ringControllers) { + if (TCastToPtr act = mgr.ObjectById(cont.x0_id)) + cont.xc_ = act->GetTransform().frontVector(); + else + cont.xc_ = zeus::CVector3f::skForward; + } - if (GetActive()) - { - switch(xe8_function) - { - case ESpecialFunction::HUDFadeIn: - { - if (msg == EScriptObjectMessage::Action) - mgr.Player()->SetHudDisable(xfc_, 0.f, 0.5f); - break; + x1a8_ = 3; + break; } - case ESpecialFunction::EscapeSequence: - { - if (msg == EScriptObjectMessage::Action && xfc_ >= 0.f) - mgr.ResetEscapeSequenceTimer(xfc_); - break; + case EScriptObjectMessage::SetToZero: { + x1a8_ = 1; + x1ac_ = GetTranslation() - mgr.GetPlayer().GetTranslation(); + x1ac_.z() = 0.f; + x1ac_.normalize(); + break; } - case ESpecialFunction::SpinnerController: - { - switch(msg) - { - case EScriptObjectMessage::Stop: - { - x1e4_25_spinnerCanMove = false; - break; - } - case EScriptObjectMessage::Play: - { - x1e4_25_spinnerCanMove = true; - mgr.Player()->SetAngularVelocityWR(zeus::CAxisAngle::sIdentity); - break; - } - case EScriptObjectMessage::Deactivate: - DeleteEmitter(x178_sfxHandle); - break; - default: - break; - } - break; + case EScriptObjectMessage::Action: { + RingScramble(mgr); + break; } - case ESpecialFunction::ShotSpinnerController: - { - switch(msg) - { - case EScriptObjectMessage::Increment: - { - x16c_ = zeus::clamp(0.f, x16c_ + 1.f, 1.f); - SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); - break; - } - case EScriptObjectMessage::SetToMax: - { - SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None); - break; - } - case EScriptObjectMessage::SetToZero: - { - x16c_ = -0.5f * x104_; - break; - } - default: - break; - } - break; - } - case ESpecialFunction::MapStation: - { - if (msg == EScriptObjectMessage::Action) - { - mgr.MapWorldInfo()->SetMapStationUsed(true); - const_cast(*mgr.WorldNC()->GetMapWorld()).RecalculateWorldSphere - (*mgr.MapWorldInfo(), *mgr.GetWorld()); - } - break; - } - case ESpecialFunction::MissileStation: - { - if (msg == EScriptObjectMessage::Action) - { - CPlayerState& pState = *mgr.GetPlayerState().get(); - pState.ResetAndIncrPickUp(CPlayerState::EItemType::Missiles, - pState.GetItemCapacity(CPlayerState::EItemType::Missiles)); - } - break; - } - case ESpecialFunction::PowerBombStation: - { - if (msg == EScriptObjectMessage::Action) - { - CPlayerState& pState = *mgr.GetPlayerState().get(); - pState.ResetAndIncrPickUp(CPlayerState::EItemType::PowerBombs, - pState.GetItemCapacity(CPlayerState::EItemType::PowerBombs)); - } - break; - } - case ESpecialFunction::SaveStation: - { - if (msg == EScriptObjectMessage::Action) - { - g_GameState->GetPlayerState()->IncrPickup(CPlayerState::EItemType::EnergyTanks, 1); - if (g_GameState->GetCardSerial() == 0) - SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); - else - { - mgr.DeferStateTransition(EStateManagerTransition::SaveGame); - x1e5_24_doSave = true; - } - } - break; - } - case ESpecialFunction::IntroBossRingController: - { - if (x1a8_ != 3) - { - switch(msg) - { - case EScriptObjectMessage::Play: - { - if (x1a8_ != 0) - RingScramble(mgr); + case EScriptObjectMessage::InitializedInArea: { + x198_ringControllers.reserve(3); + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) + continue; - for (SRingController& cont : x198_ringControllers) - { - if (TCastToPtr act = mgr.ObjectById(cont.x0_id)) - cont.xc_ = act->GetTransform().frontVector(); - else - cont.xc_ = zeus::CVector3f::skForward; - } + auto search = mgr.GetIdListForScript(conn.x8_objId); + for (auto it = search.first; it != search.second; ++it) { + if (TCastToPtr act = mgr.ObjectById(it->second)) { + x198_ringControllers.push_back(SRingController(it->second, 0.f, false)); + act->RemoveMaterial(EMaterialTypes::Occluder, mgr); + } + } - x1a8_ = 3; - break; - } - case EScriptObjectMessage::SetToZero: - { - x1a8_ = 1; - x1ac_ = GetTranslation() - mgr.GetPlayer().GetTranslation(); - x1ac_.z() = 0.f; - x1ac_.normalize(); - break; - } - case EScriptObjectMessage::Action: - { - RingScramble(mgr); - break; - } - case EScriptObjectMessage::InitializedInArea: - { - x198_ringControllers.reserve(3); - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) - continue; - - auto search = mgr.GetIdListForScript(conn.x8_objId); - for (auto it = search.first; it != search.second; ++it) - { - if (TCastToPtr act = mgr.ObjectById(it->second)) - { - x198_ringControllers.push_back(SRingController(it->second, 0.f, false)); - act->RemoveMaterial(EMaterialTypes::Occluder, mgr); - } - } - - //std::sort(x198_ringControllers.begin(), x198_ringControllers.end()); - } - break; - } - default: - break; - } - } - break; - } - case ESpecialFunction::RadialDamage: - { - if (msg == EScriptObjectMessage::Action) - { - CDamageInfo dInfo = x11c_damageInfo; - dInfo.SetRadius(xfc_); - mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), dInfo, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull})); - } - break; - } - case ESpecialFunction::BossEnergyBar: - { - if (msg == EScriptObjectMessage::Increment) - mgr.SetBossParams(uid, xfc_, u32(x100_) + 86); - else if (msg == EScriptObjectMessage::Decrement) - mgr.SetBossParams(kInvalidUniqueId, 0.f, 0); - break; - } - case ESpecialFunction::EndGame: - { - if (msg == EScriptObjectMessage::Action) - { - switch (GetSpecialEnding(mgr)) - { - case 0: - g_Main->SetFlowState(EFlowState::WinBad); - break; - case 1: - g_Main->SetFlowState(EFlowState::WinGood); - break; - case 2: - g_Main->SetFlowState(EFlowState::WinBest); - break; - } - mgr.SetShouldQuitGame(true); - } - break; - } - case ESpecialFunction::CinematicSkip: - { - if (msg == EScriptObjectMessage::Increment) - { - if (ShouldSkipCinematic(mgr)) - mgr.SetSkipCinematicSpecialFunction(GetUniqueId()); - } - else if (msg == EScriptObjectMessage::Decrement) - { - mgr.SetSkipCinematicSpecialFunction(kInvalidUniqueId); - g_GameState->SystemOptions().SetCinematicState(mgr.GetWorld()->GetWorldAssetId(), GetEditorId(), true); - - } - break; - } - case ESpecialFunction::ScriptLayerController: - { - if (msg == EScriptObjectMessage::Decrement || msg == EScriptObjectMessage::Increment) - { - if (x1bc_areaSaveId != -1 && x1c0_layerIdx != -1) - { - TAreaId aId = mgr.GetWorld()->GetAreaIdForSaveId(x1bc_areaSaveId); - std::shared_ptr worldLayerState; - if (aId != kInvalidAreaId) - worldLayerState = mgr.WorldLayerStateNC(); - else - { - std::pair worldAreaPair = g_MemoryCardSys->GetAreaAndWorldIdForSaveId(x1bc_areaSaveId); - if (worldAreaPair.first.IsValid()) - { - worldLayerState = g_GameState->StateForWorld(worldAreaPair.first).GetLayerState(); - aId = worldAreaPair.second; - } - } - - if (aId != kInvalidAreaId) - worldLayerState->SetLayerActive(aId, x1c0_layerIdx, msg == EScriptObjectMessage::Increment); - } - } - break; - } - /* - For some bizarre reason ScriptLayerController drops into EnvFxDensityController - [[fallthrough]]; - We won't do that though - */ - case ESpecialFunction::EnvFxDensityController: - { - if (msg == EScriptObjectMessage::Action) - mgr.GetEnvFxManager()->SetFxDensity(s32(x100_), xfc_); - break; - } - case ESpecialFunction::RumbleEffect: - if (msg == EScriptObjectMessage::Action) - { - s32 rumbFx = s32(x100_); - /* Retro originally did not check the upper bounds, this could potentially cause a crash - * with some runtimes, so let's make sure we're not out of bounds in either direction - */ - if (rumbFx < 0 || rumbFx >= 6) - break; - - mgr.GetRumbleManager().Rumble(mgr, fxTranslation[rumbFx], 1.f, ERumblePriority::One); - } - break; - case ESpecialFunction::InventoryActivator: - { - if (msg == EScriptObjectMessage::Action && mgr.GetPlayerState()->HasPowerUp(x1c4_item)) - SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); - break; - } - case ESpecialFunction::FusionRelay: - { - if (msg == EScriptObjectMessage::Action && mgr.GetPlayerState()->IsFusionEnabled()) - SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); - break; - } - case ESpecialFunction::AreaDamage: - { - if ((msg == EScriptObjectMessage::Deleted || msg == EScriptObjectMessage::Deactivate) && x1e4_31_) - { - x1e4_31_ = false; - mgr.GetPlayer().DecrementPhazon(); - mgr.SetIsFullThreat(false); - } - break; - } - case ESpecialFunction::DropBomb: - { - if (msg == EScriptObjectMessage::Action) - { - if (xfc_ >= 1.f) - mgr.GetPlayer().GetPlayerGun()->DropBomb(CPlayerGun::EBWeapon::PowerBomb, mgr); - else - mgr.GetPlayer().GetPlayerGun()->DropBomb(CPlayerGun::EBWeapon::Bomb, mgr); - } - break; - } - case ESpecialFunction::RedundantHintSystem: - { - CHintOptions& hintOptions = g_GameState->HintOptions(); - if (msg == EScriptObjectMessage::Action) - hintOptions.ActivateContinueDelayHintTimer(xec_locatorName.c_str()); - else if (msg == EScriptObjectMessage::Increment) - hintOptions.ActivateImmediateHintTimer(xec_locatorName.c_str()); - else if (msg == EScriptObjectMessage::Decrement) - hintOptions.DelayHint(xec_locatorName.c_str()); - break; - } - case ESpecialFunction::Billboard: - { - if (msg == EScriptObjectMessage::Increment) - { - const SObjectTag* objectTag = g_ResFactory->GetResourceIdByName(xec_locatorName); - CAssetId assetId = objectTag ? objectTag->id : CAssetId(); - - mgr.SetPendingOnScreenTex(assetId, {int(x104_), int(x108_)}, {int(xfc_), int(x100_)}); - if (objectTag) - { - x1e8_ = g_SimplePool->GetObj(*objectTag); - x1e5_26_displayBillboard = true; - } - } - else if (msg == EScriptObjectMessage::Decrement) - { - mgr.SetPendingOnScreenTex({}, {int(x104_), int(x108_)}, {int(xfc_), int(x100_)}); - if (x1e8_) - x1e8_ = TLockedToken(); - x1e5_26_displayBillboard = false; - } - break; - } - case ESpecialFunction::PlayerInAreaRelay: - { - if ((msg == EScriptObjectMessage::Action || msg == EScriptObjectMessage::SetToZero) && - GetAreaIdAlways() == mgr.GetPlayer().GetAreaIdAlways()) - { - SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); - } - break; - } - case ESpecialFunction::HUDTarget: - { - if (msg == EScriptObjectMessage::Increment) - AddMaterial(EMaterialTypes::Target, EMaterialTypes::RadarObject, mgr); - else if (msg == EScriptObjectMessage::Decrement) - RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::RadarObject, mgr); - break; - } - case ESpecialFunction::FogFader: - { - if (msg == EScriptObjectMessage::Increment) - mgr.GetCameraManager()->SetFogDensity(x100_, xfc_); - else if (msg == EScriptObjectMessage::Decrement) - mgr.GetCameraManager()->SetFogDensity(x100_, 1.f); - break; - } - case ESpecialFunction::EnterLogbook: - { - if (msg == EScriptObjectMessage::Action) - mgr.DeferStateTransition(EStateManagerTransition::LogBook); - break; - } - case ESpecialFunction::Ending: - { - if (msg == EScriptObjectMessage::Action && GetSpecialEnding(mgr) == u32(xfc_)) - SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + // std::sort(x198_ringControllers.begin(), x198_ringControllers.end()); + } + break; } default: - break; + break; } + } + break; } + case ESpecialFunction::RadialDamage: { + if (msg == EScriptObjectMessage::Action) { + CDamageInfo dInfo = x11c_damageInfo; + dInfo.SetRadius(xfc_); + mgr.ApplyDamageToWorld(GetUniqueId(), *this, GetTranslation(), dInfo, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull})); + } + break; + } + case ESpecialFunction::BossEnergyBar: { + if (msg == EScriptObjectMessage::Increment) + mgr.SetBossParams(uid, xfc_, u32(x100_) + 86); + else if (msg == EScriptObjectMessage::Decrement) + mgr.SetBossParams(kInvalidUniqueId, 0.f, 0); + break; + } + case ESpecialFunction::EndGame: { + if (msg == EScriptObjectMessage::Action) { + switch (GetSpecialEnding(mgr)) { + case 0: + g_Main->SetFlowState(EFlowState::WinBad); + break; + case 1: + g_Main->SetFlowState(EFlowState::WinGood); + break; + case 2: + g_Main->SetFlowState(EFlowState::WinBest); + break; + } + mgr.SetShouldQuitGame(true); + } + break; + } + case ESpecialFunction::CinematicSkip: { + if (msg == EScriptObjectMessage::Increment) { + if (ShouldSkipCinematic(mgr)) + mgr.SetSkipCinematicSpecialFunction(GetUniqueId()); + } else if (msg == EScriptObjectMessage::Decrement) { + mgr.SetSkipCinematicSpecialFunction(kInvalidUniqueId); + g_GameState->SystemOptions().SetCinematicState(mgr.GetWorld()->GetWorldAssetId(), GetEditorId(), true); + } + break; + } + case ESpecialFunction::ScriptLayerController: { + if (msg == EScriptObjectMessage::Decrement || msg == EScriptObjectMessage::Increment) { + if (x1bc_areaSaveId != -1 && x1c0_layerIdx != -1) { + TAreaId aId = mgr.GetWorld()->GetAreaIdForSaveId(x1bc_areaSaveId); + std::shared_ptr worldLayerState; + if (aId != kInvalidAreaId) + worldLayerState = mgr.WorldLayerStateNC(); + else { + std::pair worldAreaPair = g_MemoryCardSys->GetAreaAndWorldIdForSaveId(x1bc_areaSaveId); + if (worldAreaPair.first.IsValid()) { + worldLayerState = g_GameState->StateForWorld(worldAreaPair.first).GetLayerState(); + aId = worldAreaPair.second; + } + } + + if (aId != kInvalidAreaId) + worldLayerState->SetLayerActive(aId, x1c0_layerIdx, msg == EScriptObjectMessage::Increment); + } + } + break; + } + /* + For some bizarre reason ScriptLayerController drops into EnvFxDensityController + [[fallthrough]]; + We won't do that though + */ + case ESpecialFunction::EnvFxDensityController: { + if (msg == EScriptObjectMessage::Action) + mgr.GetEnvFxManager()->SetFxDensity(s32(x100_), xfc_); + break; + } + case ESpecialFunction::RumbleEffect: + if (msg == EScriptObjectMessage::Action) { + s32 rumbFx = s32(x100_); + /* Retro originally did not check the upper bounds, this could potentially cause a crash + * with some runtimes, so let's make sure we're not out of bounds in either direction + */ + if (rumbFx < 0 || rumbFx >= 6) + break; + + mgr.GetRumbleManager().Rumble(mgr, fxTranslation[rumbFx], 1.f, ERumblePriority::One); + } + break; + case ESpecialFunction::InventoryActivator: { + if (msg == EScriptObjectMessage::Action && mgr.GetPlayerState()->HasPowerUp(x1c4_item)) + SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + break; + } + case ESpecialFunction::FusionRelay: { + if (msg == EScriptObjectMessage::Action && mgr.GetPlayerState()->IsFusionEnabled()) + SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + break; + } + case ESpecialFunction::AreaDamage: { + if ((msg == EScriptObjectMessage::Deleted || msg == EScriptObjectMessage::Deactivate) && x1e4_31_) { + x1e4_31_ = false; + mgr.GetPlayer().DecrementPhazon(); + mgr.SetIsFullThreat(false); + } + break; + } + case ESpecialFunction::DropBomb: { + if (msg == EScriptObjectMessage::Action) { + if (xfc_ >= 1.f) + mgr.GetPlayer().GetPlayerGun()->DropBomb(CPlayerGun::EBWeapon::PowerBomb, mgr); + else + mgr.GetPlayer().GetPlayerGun()->DropBomb(CPlayerGun::EBWeapon::Bomb, mgr); + } + break; + } + case ESpecialFunction::RedundantHintSystem: { + CHintOptions& hintOptions = g_GameState->HintOptions(); + if (msg == EScriptObjectMessage::Action) + hintOptions.ActivateContinueDelayHintTimer(xec_locatorName.c_str()); + else if (msg == EScriptObjectMessage::Increment) + hintOptions.ActivateImmediateHintTimer(xec_locatorName.c_str()); + else if (msg == EScriptObjectMessage::Decrement) + hintOptions.DelayHint(xec_locatorName.c_str()); + break; + } + case ESpecialFunction::Billboard: { + if (msg == EScriptObjectMessage::Increment) { + const SObjectTag* objectTag = g_ResFactory->GetResourceIdByName(xec_locatorName); + CAssetId assetId = objectTag ? objectTag->id : CAssetId(); + + mgr.SetPendingOnScreenTex(assetId, {int(x104_), int(x108_)}, {int(xfc_), int(x100_)}); + if (objectTag) { + x1e8_ = g_SimplePool->GetObj(*objectTag); + x1e5_26_displayBillboard = true; + } + } else if (msg == EScriptObjectMessage::Decrement) { + mgr.SetPendingOnScreenTex({}, {int(x104_), int(x108_)}, {int(xfc_), int(x100_)}); + if (x1e8_) + x1e8_ = TLockedToken(); + x1e5_26_displayBillboard = false; + } + break; + } + case ESpecialFunction::PlayerInAreaRelay: { + if ((msg == EScriptObjectMessage::Action || msg == EScriptObjectMessage::SetToZero) && + GetAreaIdAlways() == mgr.GetPlayer().GetAreaIdAlways()) { + SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + } + break; + } + case ESpecialFunction::HUDTarget: { + if (msg == EScriptObjectMessage::Increment) + AddMaterial(EMaterialTypes::Target, EMaterialTypes::RadarObject, mgr); + else if (msg == EScriptObjectMessage::Decrement) + RemoveMaterial(EMaterialTypes::Target, EMaterialTypes::RadarObject, mgr); + break; + } + case ESpecialFunction::FogFader: { + if (msg == EScriptObjectMessage::Increment) + mgr.GetCameraManager()->SetFogDensity(x100_, xfc_); + else if (msg == EScriptObjectMessage::Decrement) + mgr.GetCameraManager()->SetFogDensity(x100_, 1.f); + break; + } + case ESpecialFunction::EnterLogbook: { + if (msg == EScriptObjectMessage::Action) + mgr.DeferStateTransition(EStateManagerTransition::LogBook); + break; + } + case ESpecialFunction::Ending: { + if (msg == EScriptObjectMessage::Action && GetSpecialEnding(mgr) == u32(xfc_)) + SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + } + default: + break; + } + } } void CScriptSpecialFunction::PreRender(CStateManager&, const zeus::CFrustum&) {} @@ -506,160 +444,106 @@ void CScriptSpecialFunction::AddToRenderer(const zeus::CFrustum&, const CStateMa void CScriptSpecialFunction::Render(const CStateManager&) const {} -void CScriptSpecialFunction::SkipCinematic(CStateManager& stateMgr) -{ - SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); - stateMgr.SetSkipCinematicSpecialFunction(kInvalidUniqueId); +void CScriptSpecialFunction::SkipCinematic(CStateManager& stateMgr) { + SendScriptMsgs(EScriptObjectState::Zero, stateMgr, EScriptObjectMessage::None); + stateMgr.SetSkipCinematicSpecialFunction(kInvalidUniqueId); } -void CScriptSpecialFunction::RingMoveCloser(CStateManager &, float) -{ +void CScriptSpecialFunction::RingMoveCloser(CStateManager&, float) {} -} +void CScriptSpecialFunction::RingMoveAway(CStateManager&, float) {} -void CScriptSpecialFunction::RingMoveAway(CStateManager &, float) -{ +void CScriptSpecialFunction::ThinkRingPuller(float, CStateManager&) {} -} +void CScriptSpecialFunction::RingScramble(CStateManager&) {} -void CScriptSpecialFunction::ThinkRingPuller(float, CStateManager &) -{ +void CScriptSpecialFunction::ThinkIntroBossRingController(float, CStateManager&) {} -} +void CScriptSpecialFunction::ThinkPlayerFollowLocator(float, CStateManager&) {} -void CScriptSpecialFunction::RingScramble(CStateManager &) -{ +void CScriptSpecialFunction::ThinkSpinnerController(float, CStateManager&, + CScriptSpecialFunction::ESpinnerControllerMode) {} -} +void CScriptSpecialFunction::ThinkObjectFollowLocator(float, CStateManager&) {} -void CScriptSpecialFunction::ThinkIntroBossRingController(float, CStateManager &) -{ +void CScriptSpecialFunction::ThinkObjectFollowObject(float, CStateManager&) {} -} +void CScriptSpecialFunction::ThinkChaffTarget(float, CStateManager&) {} -void CScriptSpecialFunction::ThinkPlayerFollowLocator(float, CStateManager &) -{ +void CScriptSpecialFunction::ThinkActorScale(float dt, CStateManager& mgr) { + float deltaScale = dt * xfc_; -} + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) + continue; + if (TCastToPtr act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) { + CModelData* mData = act->ModelData(); + if (mData && (mData->HasAnimData() || mData->HasNormalModel())) { + zeus::CVector3f scale = mData->GetScale(); -void CScriptSpecialFunction::ThinkSpinnerController(float, CStateManager &, CScriptSpecialFunction::ESpinnerControllerMode) -{ - -} - -void CScriptSpecialFunction::ThinkObjectFollowLocator(float, CStateManager &) -{ - -} - -void CScriptSpecialFunction::ThinkObjectFollowObject(float, CStateManager &) -{ - -} - -void CScriptSpecialFunction::ThinkChaffTarget(float, CStateManager &) -{ - -} - -void CScriptSpecialFunction::ThinkActorScale(float dt, CStateManager& mgr) -{ - float deltaScale = dt * xfc_; - - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) - continue; - if (TCastToPtr act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) - { - CModelData* mData = act->ModelData(); - if (mData && (mData->HasAnimData() || mData->HasNormalModel())) - { - zeus::CVector3f scale = mData->GetScale(); - - if (deltaScale > 0.f) - scale = zeus::min(zeus::CVector3f(deltaScale) + scale, zeus::CVector3f(x100_)); - else - scale = zeus::max(zeus::CVector3f(deltaScale) + scale, zeus::CVector3f(x100_)); - - mData->SetScale(scale); - } - } - } -} - -void CScriptSpecialFunction::ThinkSaveStation(float, CStateManager& mgr) -{ - if (x1e5_24_doSave && mgr.GetDeferredStateTransition() != EStateManagerTransition::SaveGame) - { - x1e5_24_doSave = false; - if (mgr.GetInSaveUI()) - SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); + if (deltaScale > 0.f) + scale = zeus::min(zeus::CVector3f(deltaScale) + scale, zeus::CVector3f(x100_)); else - SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + scale = zeus::max(zeus::CVector3f(deltaScale) + scale, zeus::CVector3f(x100_)); + + mData->SetScale(scale); + } } + } } -void CScriptSpecialFunction::ThinkRainSimulator(float, CStateManager& mgr) -{ - if ((float(mgr.GetInputFrameIdx()) / 3600.f) < 0.5f) - SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); +void CScriptSpecialFunction::ThinkSaveStation(float, CStateManager& mgr) { + if (x1e5_24_doSave && mgr.GetDeferredStateTransition() != EStateManagerTransition::SaveGame) { + x1e5_24_doSave = false; + if (mgr.GetInSaveUI()) + SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); else - SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + } } -void CScriptSpecialFunction::ThinkAreaDamage(float, CStateManager &) -{ - +void CScriptSpecialFunction::ThinkRainSimulator(float, CStateManager& mgr) { + if ((float(mgr.GetInputFrameIdx()) / 3600.f) < 0.5f) + SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None); + else + SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); } -void CScriptSpecialFunction::ThinkPlayerInArea(float dt, CStateManager& mgr) -{ - if (mgr.GetPlayer().GetAreaIdAlways() == GetAreaIdAlways()) - { - if (x1e5_25_playerInArea) - return; +void CScriptSpecialFunction::ThinkAreaDamage(float, CStateManager&) {} - x1e5_25_playerInArea = true; - SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); - } - else if (x1e5_25_playerInArea) - { - x1e5_25_playerInArea = false; - SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); - } +void CScriptSpecialFunction::ThinkPlayerInArea(float dt, CStateManager& mgr) { + if (mgr.GetPlayer().GetAreaIdAlways() == GetAreaIdAlways()) { + if (x1e5_25_playerInArea) + return; + + x1e5_25_playerInArea = true; + SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); + } else if (x1e5_25_playerInArea) { + x1e5_25_playerInArea = false; + SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None); + } } -bool CScriptSpecialFunction::ShouldSkipCinematic(CStateManager& stateMgr) const -{ - if (hecl::com_developer->toBoolean()) - return true; - return g_GameState->SystemOptions().GetCinematicState(stateMgr.GetWorld()->IGetWorldAssetId(), GetEditorId()); +bool CScriptSpecialFunction::ShouldSkipCinematic(CStateManager& stateMgr) const { + if (hecl::com_developer->toBoolean()) + return true; + return g_GameState->SystemOptions().GetCinematicState(stateMgr.GetWorld()->IGetWorldAssetId(), GetEditorId()); } -void CScriptSpecialFunction::DeleteEmitter(const CSfxHandle& handle) -{ - if (handle) - CSfxManager::RemoveEmitter(handle); +void CScriptSpecialFunction::DeleteEmitter(const CSfxHandle& handle) { + if (handle) + CSfxManager::RemoveEmitter(handle); } -u32 CScriptSpecialFunction::GetSpecialEnding(const CStateManager& mgr) const -{ - const u32 rate = (mgr.GetPlayerState()->CalculateItemCollectionRate() * 100) / - mgr.GetPlayerState()->GetPickupTotal(); - if (rate < 75) - return 0; - else if (rate < 100) - return 1; - return 2; +u32 CScriptSpecialFunction::GetSpecialEnding(const CStateManager& mgr) const { + const u32 rate = (mgr.GetPlayerState()->CalculateItemCollectionRate() * 100) / mgr.GetPlayerState()->GetPickupTotal(); + if (rate < 75) + return 0; + else if (rate < 100) + return 1; + return 2; } -CScriptSpecialFunction::SRingController::SRingController(TUniqueId uid, float f, bool b) - : x0_id(uid) - , x4_(f) - , x8_(b) -{ +CScriptSpecialFunction::SRingController::SRingController(TUniqueId uid, float f, bool b) : x0_id(uid), x4_(f), x8_(b) {} -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptSpecialFunction.hpp b/Runtime/World/CScriptSpecialFunction.hpp index 67fcd3563..3626f990d 100644 --- a/Runtime/World/CScriptSpecialFunction.hpp +++ b/Runtime/World/CScriptSpecialFunction.hpp @@ -5,148 +5,140 @@ #include "zeus/CTransform.hpp" #include "zeus/CColor.hpp" -namespace urde -{ -class CScriptSpecialFunction : public CActor -{ +namespace urde { +class CScriptSpecialFunction : public CActor { public: - enum class ESpecialFunction - { - What = 0, - PlayerFollowLocator = 1, - SpinnerController = 2, - ObjectFollowLocator = 3, - ChaffTarget = 4, - InventoryActivator = 5, - MapStation = 6, - SaveStation = 7, - IntroBossRingController = 8, - ViewFrustumTester = 9, - ShotSpinnerController = 10, - EscapeSequence = 11, - BossEnergyBar = 12, - EndGame = 13, - HUDFadeIn = 14, - CinematicSkip = 15, - ScriptLayerController = 16, - RainSimulator = 17, - AreaDamage = 18, - ObjectFollowObject = 19, - RedundantHintSystem = 20, - DropBomb = 21, - ScaleActor = 22, - MissileStation = 23, - Billboard = 24, - PlayerInAreaRelay = 25, - HUDTarget = 26, - FogFader = 27, - EnterLogbook = 28, - PowerBombStation = 29, - Ending = 30, - FusionRelay = 31, - WeaponSwitch = 32, - FogVolume = 47, - RadialDamage = 48, - EnvFxDensityController = 49, - RumbleEffect = 50 - }; + enum class ESpecialFunction { + What = 0, + PlayerFollowLocator = 1, + SpinnerController = 2, + ObjectFollowLocator = 3, + ChaffTarget = 4, + InventoryActivator = 5, + MapStation = 6, + SaveStation = 7, + IntroBossRingController = 8, + ViewFrustumTester = 9, + ShotSpinnerController = 10, + EscapeSequence = 11, + BossEnergyBar = 12, + EndGame = 13, + HUDFadeIn = 14, + CinematicSkip = 15, + ScriptLayerController = 16, + RainSimulator = 17, + AreaDamage = 18, + ObjectFollowObject = 19, + RedundantHintSystem = 20, + DropBomb = 21, + ScaleActor = 22, + MissileStation = 23, + Billboard = 24, + PlayerInAreaRelay = 25, + HUDTarget = 26, + FogFader = 27, + EnterLogbook = 28, + PowerBombStation = 29, + Ending = 30, + FusionRelay = 31, + WeaponSwitch = 32, + FogVolume = 47, + RadialDamage = 48, + EnvFxDensityController = 49, + RumbleEffect = 50 + }; - enum class ESpinnerControllerMode - { - Zero, - One, - }; + enum class ESpinnerControllerMode { + Zero, + One, + }; - struct SRingController - { - TUniqueId x0_id; - float x4_; - bool x8_; - zeus::CVector3f xc_; - SRingController(TUniqueId uid, float f, bool b); - }; + struct SRingController { + TUniqueId x0_id; + float x4_; + bool x8_; + zeus::CVector3f xc_; + SRingController(TUniqueId uid, float f, bool b); + }; private: - ESpecialFunction xe8_function; - std::string xec_locatorName; - float xfc_; - float x100_; - float x104_; - float x108_; - zeus::CVector3f x10c_; - zeus::CColor x118_; - CDamageInfo x11c_damageInfo; - float x138_ = 0.f; - zeus::CTransform x13c_ = zeus::CTransform::Identity(); - float x16c_ = 0.f; - s16 x170_; - s16 x172_; - s16 x174_; - CSfxHandle x178_sfxHandle; - u32 x17c_; - float x180_ = 0.f; - std::vector x184_; - float x194_ = 0.f; - std::vector x198_ringControllers; - u32 x1a8_ = 2; - zeus::CVector3f x1ac_ = zeus::CVector3f::skZero; - bool x1b8_ = true; - s32 x1bc_areaSaveId; - s32 x1c0_layerIdx; - CPlayerState::EItemType x1c4_item; - std::experimental::optional x1c8_; - union - { - struct - { - bool x1e4_24_ : 1; - bool x1e4_25_spinnerCanMove : 1; - bool x1e4_26_ : 1; - bool x1e4_27_ : 1; - bool x1e4_28_frustumEntered : 1; - bool x1e4_29_frustumExited : 1; - bool x1e4_30_ : 1; - bool x1e4_31_ : 1; - bool x1e5_24_doSave : 1; - bool x1e5_25_playerInArea : 1; - bool x1e5_26_displayBillboard : 1; - }; - u32 x1e4_dummy = 0; + ESpecialFunction xe8_function; + std::string xec_locatorName; + float xfc_; + float x100_; + float x104_; + float x108_; + zeus::CVector3f x10c_; + zeus::CColor x118_; + CDamageInfo x11c_damageInfo; + float x138_ = 0.f; + zeus::CTransform x13c_ = zeus::CTransform::Identity(); + float x16c_ = 0.f; + s16 x170_; + s16 x172_; + s16 x174_; + CSfxHandle x178_sfxHandle; + u32 x17c_; + float x180_ = 0.f; + std::vector x184_; + float x194_ = 0.f; + std::vector x198_ringControllers; + u32 x1a8_ = 2; + zeus::CVector3f x1ac_ = zeus::CVector3f::skZero; + bool x1b8_ = true; + s32 x1bc_areaSaveId; + s32 x1c0_layerIdx; + CPlayerState::EItemType x1c4_item; + std::experimental::optional x1c8_; + union { + struct { + bool x1e4_24_ : 1; + bool x1e4_25_spinnerCanMove : 1; + bool x1e4_26_ : 1; + bool x1e4_27_ : 1; + bool x1e4_28_frustumEntered : 1; + bool x1e4_29_frustumExited : 1; + bool x1e4_30_ : 1; + bool x1e4_31_ : 1; + bool x1e5_24_doSave : 1; + bool x1e5_25_playerInArea : 1; + bool x1e5_26_displayBillboard : 1; }; - TLockedToken x1e8_; // Used to be optional + u32 x1e4_dummy = 0; + }; + TLockedToken x1e8_; // Used to be optional public: - CScriptSpecialFunction(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, ESpecialFunction, - std::string_view, float, float, float, float, const zeus::CVector3f&, const zeus::CColor&, - bool, const CDamageInfo&, s32, s32, CPlayerState::EItemType, s16, s16, s16); + CScriptSpecialFunction(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, ESpecialFunction, + std::string_view, float, float, float, float, const zeus::CVector3f&, const zeus::CColor&, + bool, const CDamageInfo&, s32, s32, CPlayerState::EItemType, s16, s16, s16); - void Accept(IVisitor& visitor); - void Think(float, CStateManager &); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); - void PreRender(CStateManager &, const zeus::CFrustum &); - void AddToRenderer(const zeus::CFrustum &, const CStateManager &) const; - void Render(const CStateManager &) const; + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PreRender(CStateManager&, const zeus::CFrustum&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const; - void SkipCinematic(CStateManager&); - void RingMoveCloser(CStateManager&, float); - void RingMoveAway(CStateManager&, float); - void ThinkRingPuller(float, CStateManager&); - void RingScramble(CStateManager&); - void ThinkIntroBossRingController(float, CStateManager&); - void ThinkPlayerFollowLocator(float, CStateManager&); - void ThinkSpinnerController(float, CStateManager&, ESpinnerControllerMode); - void ThinkObjectFollowLocator(float, CStateManager&); - void ThinkObjectFollowObject(float, CStateManager&); - void ThinkChaffTarget(float, CStateManager&); - void ThinkActorScale(float, CStateManager&); - void ThinkSaveStation(float, CStateManager&); - void ThinkRainSimulator(float, CStateManager&); - void ThinkAreaDamage(float, CStateManager&); - void ThinkPlayerInArea(float, CStateManager&); + void SkipCinematic(CStateManager&); + void RingMoveCloser(CStateManager&, float); + void RingMoveAway(CStateManager&, float); + void ThinkRingPuller(float, CStateManager&); + void RingScramble(CStateManager&); + void ThinkIntroBossRingController(float, CStateManager&); + void ThinkPlayerFollowLocator(float, CStateManager&); + void ThinkSpinnerController(float, CStateManager&, ESpinnerControllerMode); + void ThinkObjectFollowLocator(float, CStateManager&); + void ThinkObjectFollowObject(float, CStateManager&); + void ThinkChaffTarget(float, CStateManager&); + void ThinkActorScale(float, CStateManager&); + void ThinkSaveStation(float, CStateManager&); + void ThinkRainSimulator(float, CStateManager&); + void ThinkAreaDamage(float, CStateManager&); + void ThinkPlayerInArea(float, CStateManager&); - bool ShouldSkipCinematic(CStateManager& stateMgr) const; + bool ShouldSkipCinematic(CStateManager& stateMgr) const; - void DeleteEmitter(const CSfxHandle& handle); - u32 GetSpecialEnding(const CStateManager&) const; + void DeleteEmitter(const CSfxHandle& handle); + u32 GetSpecialEnding(const CStateManager&) const; }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptSpiderBallAttractionSurface.cpp b/Runtime/World/CScriptSpiderBallAttractionSurface.cpp index 7062910f9..e8519711d 100644 --- a/Runtime/World/CScriptSpiderBallAttractionSurface.cpp +++ b/Runtime/World/CScriptSpiderBallAttractionSurface.cpp @@ -2,43 +2,36 @@ #include "CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -CScriptSpiderBallAttractionSurface::CScriptSpiderBallAttractionSurface( - TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, const zeus::CVector3f& scale, bool active) +CScriptSpiderBallAttractionSurface::CScriptSpiderBallAttractionSurface(TUniqueId uid, std::string_view name, + const CEntityInfo& info, + const zeus::CTransform& xf, + const zeus::CVector3f& scale, bool active) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), {EMaterialTypes::NoStepLogic}, - CActorParameters::None(), kInvalidUniqueId), xe8_scale(scale), - xf4_aabb(zeus::CAABox(scale * -0.5f, scale * 0.5f).getTransformedAABox(xf.getRotation())) -{ + CActorParameters::None(), kInvalidUniqueId) +, xe8_scale(scale) +, xf4_aabb(zeus::CAABox(scale * -0.5f, scale * 0.5f).getTransformedAABox(xf.getRotation())) {} + +void CScriptSpiderBallAttractionSurface::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptSpiderBallAttractionSurface::Think(float dt, CStateManager& mgr) { + // Empty } -void CScriptSpiderBallAttractionSurface::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptSpiderBallAttractionSurface::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, + CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, sender, mgr); } -void CScriptSpiderBallAttractionSurface::Think(float dt, CStateManager& mgr) -{ - // Empty +std::experimental::optional CScriptSpiderBallAttractionSurface::GetTouchBounds() const { + if (GetActive()) + return {zeus::CAABox(xf4_aabb.min + GetTranslation(), xf4_aabb.max + GetTranslation())}; + return {}; } -void CScriptSpiderBallAttractionSurface::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, sender, mgr); +void CScriptSpiderBallAttractionSurface::Touch(CActor& actor, CStateManager& mgr) { + // Empty } -std::experimental::optional CScriptSpiderBallAttractionSurface::GetTouchBounds() const -{ - if (GetActive()) - return {zeus::CAABox(xf4_aabb.min + GetTranslation(), xf4_aabb.max + GetTranslation())}; - return {}; -} - -void CScriptSpiderBallAttractionSurface::Touch(CActor& actor, CStateManager& mgr) -{ - // Empty -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptSpiderBallAttractionSurface.hpp b/Runtime/World/CScriptSpiderBallAttractionSurface.hpp index aecd6297f..6bae1c5f7 100644 --- a/Runtime/World/CScriptSpiderBallAttractionSurface.hpp +++ b/Runtime/World/CScriptSpiderBallAttractionSurface.hpp @@ -2,23 +2,21 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { + +class CScriptSpiderBallAttractionSurface : public CActor { + zeus::CVector3f xe8_scale; + zeus::CAABox xf4_aabb; -class CScriptSpiderBallAttractionSurface : public CActor -{ - zeus::CVector3f xe8_scale; - zeus::CAABox xf4_aabb; public: - CScriptSpiderBallAttractionSurface(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, const zeus::CVector3f& scale, bool active); - void Accept(IVisitor& visitor); - void Think(float dt, CStateManager& mgr); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - std::experimental::optional GetTouchBounds() const; - void Touch(CActor& actor, CStateManager& mgr); - const zeus::CVector3f& GetScale() const { return xe8_scale; } + CScriptSpiderBallAttractionSurface(TUniqueId uid, std::string_view name, const CEntityInfo& info, + const zeus::CTransform& xf, const zeus::CVector3f& scale, bool active); + void Accept(IVisitor& visitor); + void Think(float dt, CStateManager& mgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + std::experimental::optional GetTouchBounds() const; + void Touch(CActor& actor, CStateManager& mgr); + const zeus::CVector3f& GetScale() const { return xe8_scale; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptSpiderBallWaypoint.cpp b/Runtime/World/CScriptSpiderBallWaypoint.cpp index 672cd6694..2b623ac16 100644 --- a/Runtime/World/CScriptSpiderBallWaypoint.cpp +++ b/Runtime/World/CScriptSpiderBallWaypoint.cpp @@ -3,226 +3,188 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptSpiderBallWaypoint::CScriptSpiderBallWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, u32 w1) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic), CActorParameters::None(), kInvalidUniqueId) -, xe8_(w1) -{ +, xe8_(w1) {} +void CScriptSpiderBallWaypoint::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptSpiderBallWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); + + if (msg == EScriptObjectMessage::InitializedInArea) + BuildWaypointListAndBounds(mgr); + else if (msg == EScriptObjectMessage::Arrived) + SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); } -void CScriptSpiderBallWaypoint::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptSpiderBallWaypoint::AccumulateBounds(const zeus::CVector3f& v) { + if (!xfc_aabox) + xfc_aabox.emplace(v, v); + xfc_aabox->accumulateBounds(v); } -void CScriptSpiderBallWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); +void CScriptSpiderBallWaypoint::BuildWaypointListAndBounds(CStateManager& mgr) { + u32 validConnections = 0; + for (const SConnection& conn : x20_conns) { + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) { + TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); + if (uid != kInvalidUniqueId) { + static_cast(mgr.ObjectById(uid))->AddPreviousWaypoint(GetUniqueId()); + ++validConnections; + } + } + } - if (msg == EScriptObjectMessage::InitializedInArea) - BuildWaypointListAndBounds(mgr); - else if (msg == EScriptObjectMessage::Arrived) - SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); -} - -void CScriptSpiderBallWaypoint::AccumulateBounds(const zeus::CVector3f& v) -{ - if (!xfc_aabox) - xfc_aabox.emplace(v, v); - xfc_aabox->accumulateBounds(v); -} - -void CScriptSpiderBallWaypoint::BuildWaypointListAndBounds(CStateManager& mgr) -{ - u32 validConnections = 0; - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) - { - TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); - if (uid != kInvalidUniqueId) - { - static_cast(mgr.ObjectById(uid))->AddPreviousWaypoint(GetUniqueId()); - ++validConnections; - } - } + if (validConnections == 0) + AccumulateBounds(x34_transform.origin); + else { + CScriptSpiderBallWaypoint* curWaypoint = this; + TUniqueId uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck); + while (uid != kInvalidUniqueId) { + curWaypoint = static_cast(mgr.ObjectById(uid)); + uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck); } - if (validConnections == 0) - AccumulateBounds(x34_transform.origin); - else - { - CScriptSpiderBallWaypoint* curWaypoint = this; - TUniqueId uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck); - while (uid != kInvalidUniqueId) - { - curWaypoint = static_cast(mgr.ObjectById(uid)); - uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck); - } - - curWaypoint->AccumulateBounds(x34_transform.origin); - } + curWaypoint->AccumulateBounds(x34_transform.origin); + } } -void CScriptSpiderBallWaypoint::AddPreviousWaypoint(TUniqueId uid) -{ - xec_waypoints.push_back(uid); +void CScriptSpiderBallWaypoint::AddPreviousWaypoint(TUniqueId uid) { xec_waypoints.push_back(uid); } + +TUniqueId CScriptSpiderBallWaypoint::PreviousWaypoint(const CStateManager& mgr, + ECheckActiveWaypoint checkActive) const { + for (TUniqueId id : xec_waypoints) { + if (const CEntity* ent = mgr.GetObjectById(id)) { + if (checkActive == ECheckActiveWaypoint::SkipCheck) + return id; + else if (ent->GetActive()) + return id; + } + } + + return kInvalidUniqueId; } -TUniqueId CScriptSpiderBallWaypoint::PreviousWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const -{ - for (TUniqueId id : xec_waypoints) - { - if (const CEntity* ent = mgr.GetObjectById(id)) - { - if (checkActive == ECheckActiveWaypoint::SkipCheck) - return id; - else if (ent->GetActive()) - return id; +TUniqueId CScriptSpiderBallWaypoint::NextWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) { + TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); + if (uid != kInvalidUniqueId) { + if (const CEntity* ent = mgr.GetObjectById(uid)) { + if (checkActive == ECheckActiveWaypoint::SkipCheck) + return ent->GetUniqueId(); + else if (ent->GetActive()) + return ent->GetUniqueId(); } + } } + } - return kInvalidUniqueId; -} - -TUniqueId CScriptSpiderBallWaypoint::NextWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const -{ - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) - { - TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); - if (uid != kInvalidUniqueId) - { - if (const CEntity* ent = mgr.GetObjectById(uid)) - { - if (checkActive == ECheckActiveWaypoint::SkipCheck) - return ent->GetUniqueId(); - else if (ent->GetActive()) - return ent->GetUniqueId(); - } - } - } - } - - return kInvalidUniqueId; + return kInvalidUniqueId; } void CScriptSpiderBallWaypoint::GetClosestPointAlongWaypoints(CStateManager& mgr, const zeus::CVector3f& ballPos, - float maxPointToBallDist, const CScriptSpiderBallWaypoint*& closestWaypoint, zeus::CVector3f& closestPoint, - zeus::CVector3f& deltaBetweenPoints, float deltaBetweenInterpDist, zeus::CVector3f& interpDeltaBetweenPoints) const -{ - const CScriptSpiderBallWaypoint* wp = this; - while (wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck) != kInvalidUniqueId) + float maxPointToBallDist, + const CScriptSpiderBallWaypoint*& closestWaypoint, + zeus::CVector3f& closestPoint, + zeus::CVector3f& deltaBetweenPoints, + float deltaBetweenInterpDist, + zeus::CVector3f& interpDeltaBetweenPoints) const { + const CScriptSpiderBallWaypoint* wp = this; + while (wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck) != kInvalidUniqueId) + wp = static_cast( + mgr.GetObjectById(wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck))); + float minPointToBallDistSq = maxPointToBallDist * maxPointToBallDist; + float deltaBetweenInterpDistSq = deltaBetweenInterpDist * deltaBetweenInterpDist; + zeus::CVector3f lastPoint = wp->GetTranslation(); + zeus::CVector3f lastDelta; + bool computeDelta = wp->GetActive(); + while (true) { + if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId) { + if (computeDelta) { + const CScriptSpiderBallWaypoint* prevWp = wp; wp = static_cast( - mgr.GetObjectById(wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck))); - float minPointToBallDistSq = maxPointToBallDist * maxPointToBallDist; - float deltaBetweenInterpDistSq = deltaBetweenInterpDist * deltaBetweenInterpDist; - zeus::CVector3f lastPoint = wp->GetTranslation(); - zeus::CVector3f lastDelta; - bool computeDelta = wp->GetActive(); - while (true) - { - if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId) - { - if (computeDelta) - { - const CScriptSpiderBallWaypoint* prevWp = wp; - wp = static_cast( - mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check))); - zeus::CVector3f thisDelta = wp->GetTranslation() - lastPoint; - zeus::CVector3f lastPointToBall = ballPos - lastPoint; - if (prevWp->PreviousWaypoint(mgr, ECheckActiveWaypoint::Check) == kInvalidUniqueId) - lastDelta = thisDelta; - float pointToBallDistSq = lastPointToBall.magSquared(); - if (pointToBallDistSq < minPointToBallDistSq) - { - minPointToBallDistSq = pointToBallDistSq; - closestPoint = lastPoint; - deltaBetweenPoints = thisDelta; - interpDeltaBetweenPoints = (thisDelta.normalized() + lastDelta.normalized()) * 0.5f; - closestWaypoint = wp; - } - float projectedT = lastPointToBall.dot(thisDelta); - if (projectedT >= 0.f) - { - float normT = projectedT / thisDelta.magSquared(); - if (normT < 1.f) - { - zeus::CVector3f projectedPoint = zeus::CVector3f::lerp(lastPoint, wp->GetTranslation(), normT); - float projToBallDistSq = (ballPos - projectedPoint).magSquared(); - if (projToBallDistSq < minPointToBallDistSq) - { - minPointToBallDistSq = projToBallDistSq; - closestPoint = projectedPoint; - deltaBetweenPoints = thisDelta; - interpDeltaBetweenPoints = deltaBetweenPoints; - closestWaypoint = wp; - float lastToProjDist = (lastPoint - projectedPoint).magnitude(); - if (lastToProjDist < deltaBetweenInterpDistSq) - { - interpDeltaBetweenPoints = - zeus::CVector3f::lerp(0.5f * (thisDelta.normalized() + lastDelta.normalized()), - thisDelta.normalized(), lastToProjDist / deltaBetweenInterpDist); - } - else if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId) - { - lastToProjDist = (projectedPoint - wp->GetTranslation()).magnitude(); - if (lastToProjDist < deltaBetweenInterpDist) - { - float t = lastToProjDist / deltaBetweenInterpDist; - interpDeltaBetweenPoints = - zeus::CVector3f::lerp(((static_cast( - mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check)))-> - GetTranslation() - wp->GetTranslation()).normalized() + - thisDelta.normalized()) * 0.5f, thisDelta.normalized(), t); - } - } - } - } - } - lastDelta = thisDelta; - lastPoint = wp->GetTranslation(); - computeDelta = true; - } - else - { - wp = static_cast( - mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check))); - lastPoint = wp->GetTranslation(); - computeDelta = true; - } + mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check))); + zeus::CVector3f thisDelta = wp->GetTranslation() - lastPoint; + zeus::CVector3f lastPointToBall = ballPos - lastPoint; + if (prevWp->PreviousWaypoint(mgr, ECheckActiveWaypoint::Check) == kInvalidUniqueId) + lastDelta = thisDelta; + float pointToBallDistSq = lastPointToBall.magSquared(); + if (pointToBallDistSq < minPointToBallDistSq) { + minPointToBallDistSq = pointToBallDistSq; + closestPoint = lastPoint; + deltaBetweenPoints = thisDelta; + interpDeltaBetweenPoints = (thisDelta.normalized() + lastDelta.normalized()) * 0.5f; + closestWaypoint = wp; } - else - { - if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck) != kInvalidUniqueId) - { - wp = static_cast( - mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck))); - computeDelta = false; - } - else - { - break; + float projectedT = lastPointToBall.dot(thisDelta); + if (projectedT >= 0.f) { + float normT = projectedT / thisDelta.magSquared(); + if (normT < 1.f) { + zeus::CVector3f projectedPoint = zeus::CVector3f::lerp(lastPoint, wp->GetTranslation(), normT); + float projToBallDistSq = (ballPos - projectedPoint).magSquared(); + if (projToBallDistSq < minPointToBallDistSq) { + minPointToBallDistSq = projToBallDistSq; + closestPoint = projectedPoint; + deltaBetweenPoints = thisDelta; + interpDeltaBetweenPoints = deltaBetweenPoints; + closestWaypoint = wp; + float lastToProjDist = (lastPoint - projectedPoint).magnitude(); + if (lastToProjDist < deltaBetweenInterpDistSq) { + interpDeltaBetweenPoints = + zeus::CVector3f::lerp(0.5f * (thisDelta.normalized() + lastDelta.normalized()), + thisDelta.normalized(), lastToProjDist / deltaBetweenInterpDist); + } else if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId) { + lastToProjDist = (projectedPoint - wp->GetTranslation()).magnitude(); + if (lastToProjDist < deltaBetweenInterpDist) { + float t = lastToProjDist / deltaBetweenInterpDist; + interpDeltaBetweenPoints = + zeus::CVector3f::lerp(((static_cast( + mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check))) + ->GetTranslation() - + wp->GetTranslation()) + .normalized() + + thisDelta.normalized()) * + 0.5f, + thisDelta.normalized(), t); + } + } } + } } + lastDelta = thisDelta; + lastPoint = wp->GetTranslation(); + computeDelta = true; + } else { + wp = static_cast( + mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check))); + lastPoint = wp->GetTranslation(); + computeDelta = true; + } + } else { + if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck) != kInvalidUniqueId) { + wp = static_cast( + mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck))); + computeDelta = false; + } else { + break; + } } + } - if ((ballPos - lastPoint).magSquared() < minPointToBallDistSq) - { - closestPoint = lastPoint; - if (wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId) - { - wp = static_cast( - mgr.GetObjectById(wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck))); - deltaBetweenPoints = lastPoint - wp->GetTranslation(); - interpDeltaBetweenPoints = deltaBetweenPoints; - } - closestWaypoint = wp; + if ((ballPos - lastPoint).magSquared() < minPointToBallDistSq) { + closestPoint = lastPoint; + if (wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId) { + wp = static_cast( + mgr.GetObjectById(wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck))); + deltaBetweenPoints = lastPoint - wp->GetTranslation(); + interpDeltaBetweenPoints = deltaBetweenPoints; } + closestWaypoint = wp; + } } -} +} // namespace urde diff --git a/Runtime/World/CScriptSpiderBallWaypoint.hpp b/Runtime/World/CScriptSpiderBallWaypoint.hpp index 827442a0b..0e3a6aa0a 100644 --- a/Runtime/World/CScriptSpiderBallWaypoint.hpp +++ b/Runtime/World/CScriptSpiderBallWaypoint.hpp @@ -2,34 +2,28 @@ #include "CActor.hpp" -namespace urde -{ -class CScriptSpiderBallWaypoint : public CActor -{ - enum class ECheckActiveWaypoint - { - Check, - SkipCheck - }; - u32 xe8_; - std::vector xec_waypoints; - std::experimental::optional xfc_aabox; -public: - CScriptSpiderBallWaypoint(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, u32); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Render(const CStateManager& mgr) const { CActor::Render(mgr); } - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} - std::experimental::optional GetTouchBounds() const { return xfc_aabox; } - void AccumulateBounds(const zeus::CVector3f& v); - void BuildWaypointListAndBounds(CStateManager& mgr); - void AddPreviousWaypoint(TUniqueId uid); - TUniqueId PreviousWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const; - TUniqueId NextWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const; - void GetClosestPointAlongWaypoints(CStateManager& mgr, const zeus::CVector3f& ballPos, - float maxPointToBallDist, const CScriptSpiderBallWaypoint*& closestWaypoint, - zeus::CVector3f& closestPoint, zeus::CVector3f& deltaBetweenPoints, - float deltaBetweenInterpDist, zeus::CVector3f& interpDeltaBetweenPoints) const; -}; -} +namespace urde { +class CScriptSpiderBallWaypoint : public CActor { + enum class ECheckActiveWaypoint { Check, SkipCheck }; + u32 xe8_; + std::vector xec_waypoints; + std::experimental::optional xfc_aabox; +public: + CScriptSpiderBallWaypoint(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool, u32); + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Render(const CStateManager& mgr) const { CActor::Render(mgr); } + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} + std::experimental::optional GetTouchBounds() const { return xfc_aabox; } + void AccumulateBounds(const zeus::CVector3f& v); + void BuildWaypointListAndBounds(CStateManager& mgr); + void AddPreviousWaypoint(TUniqueId uid); + TUniqueId PreviousWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const; + TUniqueId NextWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const; + void GetClosestPointAlongWaypoints(CStateManager& mgr, const zeus::CVector3f& ballPos, float maxPointToBallDist, + const CScriptSpiderBallWaypoint*& closestWaypoint, zeus::CVector3f& closestPoint, + zeus::CVector3f& deltaBetweenPoints, float deltaBetweenInterpDist, + zeus::CVector3f& interpDeltaBetweenPoints) const; +}; +} // namespace urde diff --git a/Runtime/World/CScriptSpindleCamera.cpp b/Runtime/World/CScriptSpindleCamera.cpp index 4c25cc3c1..e3c3ab515 100644 --- a/Runtime/World/CScriptSpindleCamera.cpp +++ b/Runtime/World/CScriptSpindleCamera.cpp @@ -5,17 +5,19 @@ #include "Camera/CBallCamera.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { SSpindleProperty::SSpindleProperty(CInputStream& in) -: x0_(in.readUint32Big()), x4_paramFlags(ScriptLoader::LoadParameterFlags(in)), - x8_(in.readFloatBig()), xc_(in.readFloatBig()), x10_(in.readFloatBig()), x14_(in.readFloatBig()) -{} +: x0_(in.readUint32Big()) +, x4_paramFlags(ScriptLoader::LoadParameterFlags(in)) +, x8_(in.readFloatBig()) +, xc_(in.readFloatBig()) +, x10_(in.readFloatBig()) +, x14_(in.readFloatBig()) {} CScriptSpindleCamera::CScriptSpindleCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, u32 r9, - float f1, float f2, float f3, float f4, const SSpindleProperty& seg1, + const zeus::CTransform& xf, bool active, u32 r9, float f1, float f2, + float f3, float f4, const SSpindleProperty& seg1, const SSpindleProperty& seg2, const SSpindleProperty& seg3, const SSpindleProperty& seg4, const SSpindleProperty& seg5, const SSpindleProperty& seg6, const SSpindleProperty& seg7, @@ -24,37 +26,42 @@ CScriptSpindleCamera::CScriptSpindleCamera(TUniqueId uid, std::string_view name, const SSpindleProperty& seg12, const SSpindleProperty& seg13, const SSpindleProperty& seg14, const SSpindleProperty& seg15) : CGameCamera(uid, active, name, info, xf, CCameraManager::ThirdPersonFOV(), CCameraManager::NearPlane(), - CCameraManager::FarPlane(), CCameraManager::Aspect(), kInvalidUniqueId, false, 0), - x188_r9(r9), x1b0_f1(f1), x1b4_f2(f2), x1b8_f3(f2), x1bc_f4(f4), x1c0_seg1(seg1), x1d8_seg2(seg2), - x1f0_seg3(seg3), x208_seg4(seg4), x220_seg5(seg5), x238_seg6(seg6), x250_seg7(seg7), - x268_seg8(seg8), x280_seg9(seg9), x298_seg10(seg10), x2b0_seg11(seg11), x2c8_seg12(seg12), - x2e0_seg13(seg13), x2f8_seg14(seg14), x310_seg15(seg15), x330_lookDir(xf.basis[1]) -{ + CCameraManager::FarPlane(), CCameraManager::Aspect(), kInvalidUniqueId, false, 0) +, x188_r9(r9) +, x1b0_f1(f1) +, x1b4_f2(f2) +, x1b8_f3(f2) +, x1bc_f4(f4) +, x1c0_seg1(seg1) +, x1d8_seg2(seg2) +, x1f0_seg3(seg3) +, x208_seg4(seg4) +, x220_seg5(seg5) +, x238_seg6(seg6) +, x250_seg7(seg7) +, x268_seg8(seg8) +, x280_seg9(seg9) +, x298_seg10(seg10) +, x2b0_seg11(seg11) +, x2c8_seg12(seg12) +, x2e0_seg13(seg13) +, x2f8_seg14(seg14) +, x310_seg15(seg15) +, x330_lookDir(xf.basis[1]) {} +void CScriptSpindleCamera::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptSpindleCamera::ProcessInput(const CFinalInput& input, CStateManager& mgr) {} + +void CScriptSpindleCamera::Reset(const zeus::CTransform& xf, CStateManager& mgr) { + const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr); + if (!GetActive() || hint == nullptr) + return; + + x33c_24_ = true; + mgr.GetCameraManager()->GetBallCamera()->UpdateLookAtPosition(0.01f, mgr); } -void CScriptSpindleCamera::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptSpindleCamera::Think(float, CStateManager&) {} -void CScriptSpindleCamera::ProcessInput(const CFinalInput& input, CStateManager& mgr) -{ - -} - -void CScriptSpindleCamera::Reset(const zeus::CTransform& xf, CStateManager& mgr) -{ - const CScriptCameraHint* hint = mgr.GetCameraManager()->GetCameraHint(mgr); - if (!GetActive() || hint == nullptr) - return; - - x33c_24_ = true; - mgr.GetCameraManager()->GetBallCamera()->UpdateLookAtPosition(0.01f, mgr); -} - -void CScriptSpindleCamera::Think(float, CStateManager&) -{ -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptSpindleCamera.hpp b/Runtime/World/CScriptSpindleCamera.hpp index f81f14d68..39781babb 100644 --- a/Runtime/World/CScriptSpindleCamera.hpp +++ b/Runtime/World/CScriptSpindleCamera.hpp @@ -2,70 +2,63 @@ #include "Camera/CGameCamera.hpp" -namespace urde -{ +namespace urde { -struct SSpindleProperty -{ - u32 x0_; - u32 x4_paramFlags; - float x8_; - float xc_; - float x10_; - float x14_; +struct SSpindleProperty { + u32 x0_; + u32 x4_paramFlags; + float x8_; + float xc_; + float x10_; + float x14_; - SSpindleProperty(CInputStream& in); - void FixupAngles() - { - x8_ = zeus::degToRad(x8_); - xc_ = zeus::degToRad(xc_); - } + SSpindleProperty(CInputStream& in); + void FixupAngles() { + x8_ = zeus::degToRad(x8_); + xc_ = zeus::degToRad(xc_); + } }; -class CScriptSpindleCamera : public CGameCamera -{ - u32 x188_r9; - u32 x18c_ = 0; - float x1b0_f1; - float x1b4_f2; - float x1b8_f3; - float x1bc_f4; - SSpindleProperty x1c0_seg1; - SSpindleProperty x1d8_seg2; - SSpindleProperty x1f0_seg3; - SSpindleProperty x208_seg4; - SSpindleProperty x220_seg5; - SSpindleProperty x238_seg6; - SSpindleProperty x250_seg7; - SSpindleProperty x268_seg8; - SSpindleProperty x280_seg9; - SSpindleProperty x298_seg10; - SSpindleProperty x2b0_seg11; - SSpindleProperty x2c8_seg12; - SSpindleProperty x2e0_seg13; - SSpindleProperty x2f8_seg14; - SSpindleProperty x310_seg15; - float x328_ = 0.f; - bool x32c_24 = false; - zeus::CVector3f x330_lookDir; - bool x33c_24_; +class CScriptSpindleCamera : public CGameCamera { + u32 x188_r9; + u32 x18c_ = 0; + float x1b0_f1; + float x1b4_f2; + float x1b8_f3; + float x1bc_f4; + SSpindleProperty x1c0_seg1; + SSpindleProperty x1d8_seg2; + SSpindleProperty x1f0_seg3; + SSpindleProperty x208_seg4; + SSpindleProperty x220_seg5; + SSpindleProperty x238_seg6; + SSpindleProperty x250_seg7; + SSpindleProperty x268_seg8; + SSpindleProperty x280_seg9; + SSpindleProperty x298_seg10; + SSpindleProperty x2b0_seg11; + SSpindleProperty x2c8_seg12; + SSpindleProperty x2e0_seg13; + SSpindleProperty x2f8_seg14; + SSpindleProperty x310_seg15; + float x328_ = 0.f; + bool x32c_24 = false; + zeus::CVector3f x330_lookDir; + bool x33c_24_; + public: - CScriptSpindleCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, u32 r9, - float f1, float f2, float f3, float f4, const SSpindleProperty& seg1, - const SSpindleProperty& seg2, const SSpindleProperty& seg3, - const SSpindleProperty& seg4, const SSpindleProperty& seg5, - const SSpindleProperty& seg6, const SSpindleProperty& seg7, - const SSpindleProperty& seg8, const SSpindleProperty& seg9, - const SSpindleProperty& seg10, const SSpindleProperty& seg11, - const SSpindleProperty& seg12, const SSpindleProperty& seg13, - const SSpindleProperty& seg14, const SSpindleProperty& seg15); + CScriptSpindleCamera(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + bool active, u32 r9, float f1, float f2, float f3, float f4, const SSpindleProperty& seg1, + const SSpindleProperty& seg2, const SSpindleProperty& seg3, const SSpindleProperty& seg4, + const SSpindleProperty& seg5, const SSpindleProperty& seg6, const SSpindleProperty& seg7, + const SSpindleProperty& seg8, const SSpindleProperty& seg9, const SSpindleProperty& seg10, + const SSpindleProperty& seg11, const SSpindleProperty& seg12, const SSpindleProperty& seg13, + const SSpindleProperty& seg14, const SSpindleProperty& seg15); - void Accept(IVisitor& visitor); - void Think(float, CStateManager&); - void Reset(const zeus::CTransform& xf, CStateManager& mgr); - void ProcessInput(const CFinalInput& input, CStateManager& mgr); + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void Reset(const zeus::CTransform& xf, CStateManager& mgr); + void ProcessInput(const CFinalInput& input, CStateManager& mgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptSteam.cpp b/Runtime/World/CScriptSteam.cpp index 927856061..55961ccc0 100644 --- a/Runtime/World/CScriptSteam.cpp +++ b/Runtime/World/CScriptSteam.cpp @@ -3,8 +3,7 @@ #include "CPlayer.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptSteam::CScriptSteam(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, const zeus::CAABox& aabb, const CDamageInfo& dInfo, const zeus::CVector3f& orientedForce, @@ -15,50 +14,42 @@ CScriptSteam::CScriptSteam(TUniqueId uid, std::string_view name, const CEntityIn , x154_texture(texture) , x158_(f1) , x15c_alphaInDur(f2 / f1) -, x160_alphaOutDur(f3 / f1) -{ - float r3 = (aabb.max.z() < aabb.max.y() ? aabb.max.z() : aabb.max.y()); - r3 = (r3 < aabb.max.x() ? r3 : aabb.max.x()); +, x160_alphaOutDur(f3 / f1) { + float r3 = (aabb.max.z() < aabb.max.y() ? aabb.max.z() : aabb.max.y()); + r3 = (r3 < aabb.max.x() ? r3 : aabb.max.x()); - if (f4 - 0.f >= 0.000009999999747378752f) - r3 = (r3 < f2 ? r3 : f4); + if (f4 - 0.f >= 0.000009999999747378752f) + r3 = (r3 < f2 ? r3 : f4); - x164_ = r3; - x168_ = 1.f / x164_; + x164_ = r3; + x168_ = 1.f / x164_; } -void CScriptSteam::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptSteam::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptSteam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (msg == EScriptObjectMessage::Deactivate) + mgr.Player()->SetVisorSteam(0.f, x158_, x160_alphaOutDur, CAssetId(), x150_); + + CScriptTrigger::AcceptScriptMsg(msg, uid, mgr); } -void CScriptSteam::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (msg == EScriptObjectMessage::Deactivate) - mgr.Player()->SetVisorSteam(0.f, x158_, x160_alphaOutDur, CAssetId(), x150_); +void CScriptSteam::Think(float dt, CStateManager& mgr) { + if (!GetActive()) + return; - CScriptTrigger::AcceptScriptMsg(msg, uid, mgr); + CScriptTrigger::Think(dt, mgr); + + if (x148_28_playerTriggerProc && mgr.GetCameraManager()->GetFluidCounter() == 0) { + zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); + zeus::CVector3f posDiff = (GetTranslation() - eyePos); + float mag = posDiff.magnitude(); + float distance = (mag >= x164_ ? 0.f : std::cos((1.5707964f * mag) * x168_) * x158_); + mgr.Player()->SetVisorSteam(distance, x15c_alphaInDur, x160_alphaOutDur, x154_texture, x150_); + if (x150_) + mgr.GetEnvFxManager()->SetSplashRate(2.f * distance); + } else + mgr.Player()->SetVisorSteam(0.f, x15c_alphaInDur, x160_alphaOutDur, CAssetId(), x150_); } -void CScriptSteam::Think(float dt, CStateManager& mgr) -{ - if (!GetActive()) - return; - - CScriptTrigger::Think(dt, mgr); - - if (x148_28_playerTriggerProc && mgr.GetCameraManager()->GetFluidCounter() == 0) - { - zeus::CVector3f eyePos = mgr.GetPlayer().GetEyePosition(); - zeus::CVector3f posDiff = (GetTranslation() - eyePos); - float mag = posDiff.magnitude(); - float distance = (mag >= x164_ ? 0.f : std::cos((1.5707964f * mag) * x168_) * x158_); - mgr.Player()->SetVisorSteam(distance, x15c_alphaInDur, x160_alphaOutDur, x154_texture, x150_); - if (x150_) - mgr.GetEnvFxManager()->SetSplashRate(2.f * distance); - } - else - mgr.Player()->SetVisorSteam(0.f, x15c_alphaInDur, x160_alphaOutDur, CAssetId(), x150_); -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptSteam.hpp b/Runtime/World/CScriptSteam.hpp index 88c891005..8643762e9 100644 --- a/Runtime/World/CScriptSteam.hpp +++ b/Runtime/World/CScriptSteam.hpp @@ -2,27 +2,25 @@ #include "CScriptTrigger.hpp" -namespace urde -{ +namespace urde { + +class CScriptSteam : public CScriptTrigger { + bool x150_; + CAssetId x154_texture; + float x158_; + float x15c_alphaInDur; + float x160_alphaOutDur; + float x164_ = 0.f; + float x168_ = 0.f; -class CScriptSteam : public CScriptTrigger -{ - bool x150_; - CAssetId x154_texture; - float x158_; - float x15c_alphaInDur; - float x160_alphaOutDur; - float x164_ = 0.f; - float x168_ = 0.f; public: - CScriptSteam(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, - const zeus::CAABox&, const CDamageInfo& dInfo, const zeus::CVector3f& orientedForce, - ETriggerFlags flags, bool active, CAssetId, float, float, float, float, bool); + CScriptSteam(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, + const zeus::CAABox&, const CDamageInfo& dInfo, const zeus::CVector3f& orientedForce, ETriggerFlags flags, + bool active, CAssetId, float, float, float, float, bool); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void Think(float, CStateManager&); + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptStreamedMusic.cpp b/Runtime/World/CScriptStreamedMusic.cpp index 08c0f838d..03a9be3bf 100644 --- a/Runtime/World/CScriptStreamedMusic.cpp +++ b/Runtime/World/CScriptStreamedMusic.cpp @@ -7,98 +7,87 @@ #include "GameGlobalObjects.hpp" #include "Audio/CStreamAudioManager.hpp" -namespace urde -{ +namespace urde { -bool CScriptStreamedMusic::IsDSPFile(std::string_view fileName) -{ - if (!CStringExtras::CompareCaseInsensitive(fileName, "sw")) - return true; - return CStringExtras::IndexOfSubstring(fileName, ".dsp") != -1; +bool CScriptStreamedMusic::IsDSPFile(std::string_view fileName) { + if (!CStringExtras::CompareCaseInsensitive(fileName, "sw")) + return true; + return CStringExtras::IndexOfSubstring(fileName, ".dsp") != -1; } -void CScriptStreamedMusic::StopStream(CStateManager& mgr) -{ - CStreamAudioManager::Stop(!x46_loop, x34_fileName); +void CScriptStreamedMusic::StopStream(CStateManager& mgr) { CStreamAudioManager::Stop(!x46_loop, x34_fileName); } + +void CScriptStreamedMusic::StartStream(CStateManager& mgr) { + CStreamAudioManager::Start(!x46_loop, x34_fileName, x50_volume / 127.f, x47_music, x48_fadeIn, x4c_fadeOut); } -void CScriptStreamedMusic::StartStream(CStateManager& mgr) -{ - CStreamAudioManager::Start(!x46_loop, x34_fileName, x50_volume / 127.f, - x47_music, x48_fadeIn, x4c_fadeOut); +void CScriptStreamedMusic::TweakOverride(CStateManager& mgr) { + const CWorld* wld = mgr.GetWorld(); + const CGameArea* area = wld->GetAreaAlways(x4_areaId); + std::string twkName = + hecl::Format("Area %8.8x MusicObject: %s", u32(area->GetAreaAssetId().Value()), x10_name.c_str()); + if (g_TweakManager->HasTweakValue(twkName)) { + const CTweakValue::Audio& audio = g_TweakManager->GetTweakValue(twkName)->GetAudio(); + x34_fileName = audio.GetFileName(); + x45_fileIsDsp = IsDSPFile(x34_fileName); + x48_fadeIn = audio.GetFadeIn(); + x4c_fadeOut = audio.GetFadeOut(); + x50_volume = audio.GetVolume() * 127.f; + } } -void CScriptStreamedMusic::TweakOverride(CStateManager& mgr) -{ - const CWorld* wld = mgr.GetWorld(); - const CGameArea* area = wld->GetAreaAlways(x4_areaId); - std::string twkName = hecl::Format("Area %8.8x MusicObject: %s", - u32(area->GetAreaAssetId().Value()), x10_name.c_str()); - if (g_TweakManager->HasTweakValue(twkName)) - { - const CTweakValue::Audio& audio = g_TweakManager->GetTweakValue(twkName)->GetAudio(); - x34_fileName = audio.GetFileName(); - x45_fileIsDsp = IsDSPFile(x34_fileName); - x48_fadeIn = audio.GetFadeIn(); - x4c_fadeOut = audio.GetFadeOut(); - x50_volume = audio.GetVolume() * 127.f; - } +CScriptStreamedMusic::CScriptStreamedMusic(TUniqueId id, const CEntityInfo& info, std::string_view name, bool active, + std::string_view fileName, bool noStopOnDeactivate, float fadeIn, + float fadeOut, u32 volume, bool loop, bool music) +: CEntity(id, info, active, name) +, x34_fileName(fileName) +, x44_noStopOnDeactivate(noStopOnDeactivate) +, x45_fileIsDsp(IsDSPFile(fileName)) +, x46_loop(loop) +, x47_music(music) +, x48_fadeIn(fadeIn) +, x4c_fadeOut(fadeOut) +, x50_volume(volume) { + size_t pos; + while ((pos = x34_fileName.find("audio/")) != std::string::npos) + x34_fileName.replace(pos, 6, "Audio/"); } -CScriptStreamedMusic::CScriptStreamedMusic(TUniqueId id, const CEntityInfo& info, std::string_view name, - bool active, std::string_view fileName, bool noStopOnDeactivate, - float fadeIn, float fadeOut, u32 volume, bool loop, bool music) -: CEntity(id, info, active, name), x34_fileName(fileName), x44_noStopOnDeactivate(noStopOnDeactivate), - x45_fileIsDsp(IsDSPFile(fileName)), x46_loop(loop), x47_music(music), - x48_fadeIn(fadeIn), x4c_fadeOut(fadeOut), x50_volume(volume) -{ - size_t pos; - while ((pos = x34_fileName.find("audio/")) != std::string::npos) - x34_fileName.replace(pos, 6, "Audio/"); +void CScriptStreamedMusic::Stop(CStateManager& mgr) { + if (x45_fileIsDsp) + StopStream(mgr); } -void CScriptStreamedMusic::Stop(CStateManager& mgr) -{ +void CScriptStreamedMusic::Play(CStateManager& mgr) { + TweakOverride(mgr); + if (x45_fileIsDsp) + StartStream(mgr); +} + +void CScriptStreamedMusic::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptStreamedMusic::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); + switch (msg) { + case EScriptObjectMessage::Play: + if (x30_24_active) + Play(stateMgr); + break; + case EScriptObjectMessage::Stop: + if (x30_24_active) + Stop(stateMgr); + break; + case EScriptObjectMessage::Increment: if (x45_fileIsDsp) - StopStream(mgr); -} - -void CScriptStreamedMusic::Play(CStateManager& mgr) -{ - TweakOverride(mgr); + CStreamAudioManager::FadeBackIn(!x46_loop, x48_fadeIn); + break; + case EScriptObjectMessage::Decrement: if (x45_fileIsDsp) - StartStream(mgr); + CStreamAudioManager::TemporaryFadeOut(!x46_loop, x4c_fadeOut); + break; + default: + break; + } } -void CScriptStreamedMusic::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CScriptStreamedMusic::AcceptScriptMsg(EScriptObjectMessage msg, - TUniqueId objId, CStateManager& stateMgr) -{ - CEntity::AcceptScriptMsg(msg, objId, stateMgr); - switch (msg) - { - case EScriptObjectMessage::Play: - if (x30_24_active) - Play(stateMgr); - break; - case EScriptObjectMessage::Stop: - if (x30_24_active) - Stop(stateMgr); - break; - case EScriptObjectMessage::Increment: - if (x45_fileIsDsp) - CStreamAudioManager::FadeBackIn(!x46_loop, x48_fadeIn); - break; - case EScriptObjectMessage::Decrement: - if (x45_fileIsDsp) - CStreamAudioManager::TemporaryFadeOut(!x46_loop, x4c_fadeOut); - break; - default: break; - } -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptStreamedMusic.hpp b/Runtime/World/CScriptStreamedMusic.hpp index 8e0df1687..1fd93f9fd 100644 --- a/Runtime/World/CScriptStreamedMusic.hpp +++ b/Runtime/World/CScriptStreamedMusic.hpp @@ -2,34 +2,31 @@ #include "CEntity.hpp" -namespace urde -{ +namespace urde { -class CScriptStreamedMusic : public CEntity -{ - std::string x34_fileName; - bool x44_noStopOnDeactivate; - bool x45_fileIsDsp; // As opposed to .adp for DTK streaming - bool x46_loop; - bool x47_music; - float x48_fadeIn; - float x4c_fadeOut; - u32 x50_volume; - static bool IsDSPFile(std::string_view fileName); - void StopStream(CStateManager& mgr); - void StartStream(CStateManager& mgr); - void TweakOverride(CStateManager& mgr); +class CScriptStreamedMusic : public CEntity { + std::string x34_fileName; + bool x44_noStopOnDeactivate; + bool x45_fileIsDsp; // As opposed to .adp for DTK streaming + bool x46_loop; + bool x47_music; + float x48_fadeIn; + float x4c_fadeOut; + u32 x50_volume; + static bool IsDSPFile(std::string_view fileName); + void StopStream(CStateManager& mgr); + void StartStream(CStateManager& mgr); + void TweakOverride(CStateManager& mgr); public: - CScriptStreamedMusic(TUniqueId id, const CEntityInfo& info, std::string_view name, - bool active, std::string_view fileName, bool noStopOnDeactivate, - float fadeIn, float fadeOut, u32 volume, bool loop, bool music); + CScriptStreamedMusic(TUniqueId id, const CEntityInfo& info, std::string_view name, bool active, + std::string_view fileName, bool noStopOnDeactivate, float fadeIn, float fadeOut, u32 volume, + bool loop, bool music); - void Stop(CStateManager& mgr); - void Play(CStateManager& mgr); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void Stop(CStateManager& mgr); + void Play(CStateManager& mgr); + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptSwitch.cpp b/Runtime/World/CScriptSwitch.cpp index b604fc76d..de82e78e1 100644 --- a/Runtime/World/CScriptSwitch.cpp +++ b/Runtime/World/CScriptSwitch.cpp @@ -2,40 +2,29 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptSwitch::CScriptSwitch(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, bool opened, bool closeOnOpened) -: CEntity(uid, info, active, name), x34_opened(opened), x35_closeOnOpened(closeOnOpened) -{ -} +: CEntity(uid, info, active, name), x34_opened(opened), x35_closeOnOpened(closeOnOpened) {} -void CScriptSwitch::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptSwitch::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptSwitch::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) -{ - if (GetActive()) - { - if (msg == EScriptObjectMessage::Open) - x34_opened = true; - else if (msg == EScriptObjectMessage::Close) - x34_opened = false; - else if (msg == EScriptObjectMessage::SetToZero) - { - if (x34_opened) - { - SendScriptMsgs(EScriptObjectState::Open, mgr, EScriptObjectMessage::None); - if (x35_closeOnOpened) - x34_opened = false; - } - else - SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); - } +void CScriptSwitch::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) { + if (GetActive()) { + if (msg == EScriptObjectMessage::Open) + x34_opened = true; + else if (msg == EScriptObjectMessage::Close) + x34_opened = false; + else if (msg == EScriptObjectMessage::SetToZero) { + if (x34_opened) { + SendScriptMsgs(EScriptObjectState::Open, mgr, EScriptObjectMessage::None); + if (x35_closeOnOpened) + x34_opened = false; + } else + SendScriptMsgs(EScriptObjectState::Closed, mgr, EScriptObjectMessage::None); } + } - CEntity::AcceptScriptMsg(msg, objId, mgr); -} + CEntity::AcceptScriptMsg(msg, objId, mgr); } +} // namespace urde diff --git a/Runtime/World/CScriptSwitch.hpp b/Runtime/World/CScriptSwitch.hpp index d1fe0a009..0aa91c2ff 100644 --- a/Runtime/World/CScriptSwitch.hpp +++ b/Runtime/World/CScriptSwitch.hpp @@ -2,16 +2,15 @@ #include "CEntity.hpp" -namespace urde -{ -class CScriptSwitch : public CEntity -{ - bool x34_opened; - bool x35_closeOnOpened; -public: - CScriptSwitch(TUniqueId, std::string_view, const CEntityInfo&, bool, bool, bool); +namespace urde { +class CScriptSwitch : public CEntity { + bool x34_opened; + bool x35_closeOnOpened; - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); +public: + CScriptSwitch(TUniqueId, std::string_view, const CEntityInfo&, bool, bool, bool); + + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); }; -} +} // namespace urde diff --git a/Runtime/World/CScriptTargetingPoint.cpp b/Runtime/World/CScriptTargetingPoint.cpp index 9954821da..7539f4303 100644 --- a/Runtime/World/CScriptTargetingPoint.cpp +++ b/Runtime/World/CScriptTargetingPoint.cpp @@ -2,33 +2,28 @@ #include "World/CActorParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptTargetingPoint::CScriptTargetingPoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active) : CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic), - CActorParameters::None(), kInvalidUniqueId) -{ -} + CActorParameters::None(), kInvalidUniqueId) {} void CScriptTargetingPoint::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptTargetingPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, uid, mgr); +void CScriptTargetingPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, uid, mgr); - if (msg == EScriptObjectMessage::Deactivate || msg == EScriptObjectMessage::Activate) - CEntity::SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); + if (msg == EScriptObjectMessage::Deactivate || msg == EScriptObjectMessage::Activate) + CEntity::SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None); } -void CScriptTargetingPoint::Think(float dt, CStateManager&) -{ - if (xec_time <= 0.f) - return; +void CScriptTargetingPoint::Think(float dt, CStateManager&) { + if (xec_time <= 0.f) + return; - xec_time -= dt; + xec_time -= dt; } bool CScriptTargetingPoint::GetLocked() const { return !x20_conns.empty(); } -} +} // namespace urde diff --git a/Runtime/World/CScriptTargetingPoint.hpp b/Runtime/World/CScriptTargetingPoint.hpp index bab805a15..d1bb1c833 100644 --- a/Runtime/World/CScriptTargetingPoint.hpp +++ b/Runtime/World/CScriptTargetingPoint.hpp @@ -2,31 +2,26 @@ #include "World/CActor.hpp" -namespace urde -{ -class CScriptTargetingPoint : public CActor -{ +namespace urde { +class CScriptTargetingPoint : public CActor { private: - union - { - struct - { - bool xe8_e4_ : 1; - }; - u8 xe8_dummy = 0; + union { + struct { + bool xe8_e4_ : 1; }; - TUniqueId xea_; - float xec_time = 0.f; + u8 xe8_dummy = 0; + }; + TUniqueId xea_; + float xec_time = 0.f; public: - CScriptTargetingPoint(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool); + CScriptTargetingPoint(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, bool); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); - void Think(float, CStateManager &); - void Render(const CStateManager &) const {} + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Think(float, CStateManager&); + void Render(const CStateManager&) const {} - bool GetLocked() const; + bool GetLocked() const; }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptTimer.cpp b/Runtime/World/CScriptTimer.cpp index d2f90a4bb..690d03586 100644 --- a/Runtime/World/CScriptTimer.cpp +++ b/Runtime/World/CScriptTimer.cpp @@ -2,8 +2,7 @@ #include "CStateManager.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptTimer::CScriptTimer(TUniqueId uid, std::string_view name, const CEntityInfo& info, float startTime, float maxRandDelay, bool loop, bool autoStart, bool active) @@ -13,78 +12,57 @@ CScriptTimer::CScriptTimer(TUniqueId uid, std::string_view name, const CEntityIn , x3c_maxRandDelay(maxRandDelay) , x40_loop(loop) , x41_autoStart(autoStart) -, x42_isTiming(autoStart) -{ +, x42_isTiming(autoStart) {} + +void CScriptTimer::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptTimer::Think(float dt, CStateManager& mgr) { + if (GetActive() && IsTiming()) + ApplyTime(dt, mgr); } -void CScriptTimer::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} - -void CScriptTimer::Think(float dt, CStateManager& mgr) -{ - if (GetActive() && IsTiming()) - ApplyTime(dt, mgr); -} - -void CScriptTimer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - if (GetActive()) - { - if (msg == EScriptObjectMessage::Start) - { - StartTiming(true); - } - else if (msg == EScriptObjectMessage::Stop) - { - StartTiming(false); - } - else if (msg == EScriptObjectMessage::ResetAndStart) - { - Reset(stateMgr); - StartTiming(true); - } - else if (msg == EScriptObjectMessage::Reset) - { - Reset(stateMgr); - } - else if (msg == EScriptObjectMessage::StopAndReset) - { - Reset(stateMgr); - StartTiming(false); - } +void CScriptTimer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + if (GetActive()) { + if (msg == EScriptObjectMessage::Start) { + StartTiming(true); + } else if (msg == EScriptObjectMessage::Stop) { + StartTiming(false); + } else if (msg == EScriptObjectMessage::ResetAndStart) { + Reset(stateMgr); + StartTiming(true); + } else if (msg == EScriptObjectMessage::Reset) { + Reset(stateMgr); + } else if (msg == EScriptObjectMessage::StopAndReset) { + Reset(stateMgr); + StartTiming(false); } - CEntity::AcceptScriptMsg(msg, objId, stateMgr); + } + CEntity::AcceptScriptMsg(msg, objId, stateMgr); } bool CScriptTimer::IsTiming() const { return x42_isTiming; } void CScriptTimer::StartTiming(bool isTiming) { x42_isTiming = isTiming; } -void CScriptTimer::Reset(CStateManager& mgr) -{ - float rDt = mgr.GetActiveRandom()->Float(); - x34_time = (x3c_maxRandDelay * rDt) + x38_startTime; +void CScriptTimer::Reset(CStateManager& mgr) { + float rDt = mgr.GetActiveRandom()->Float(); + x34_time = (x3c_maxRandDelay * rDt) + x38_startTime; } -void CScriptTimer::ApplyTime(float dt, CStateManager& mgr) -{ - if (x34_time <= 0.f || !GetActive()) - return; +void CScriptTimer::ApplyTime(float dt, CStateManager& mgr) { + if (x34_time <= 0.f || !GetActive()) + return; - x34_time -= dt; - if (x34_time <= 0.f) - { - SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); + x34_time -= dt; + if (x34_time <= 0.f) { + SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None); - x42_isTiming = false; - if (x40_loop) - { - Reset(mgr); - if (x41_autoStart) - x42_isTiming = true; - } + x42_isTiming = false; + if (x40_loop) { + Reset(mgr); + if (x41_autoStart) + x42_isTiming = true; } + } } -} +} // namespace urde diff --git a/Runtime/World/CScriptTimer.hpp b/Runtime/World/CScriptTimer.hpp index fa3dfd49d..a12f6c824 100644 --- a/Runtime/World/CScriptTimer.hpp +++ b/Runtime/World/CScriptTimer.hpp @@ -2,29 +2,26 @@ #include "CEntity.hpp" -namespace urde -{ +namespace urde { + +class CScriptTimer : public CEntity { + float x34_time; + float x38_startTime; + float x3c_maxRandDelay; + bool x40_loop; + bool x41_autoStart; + bool x42_isTiming; -class CScriptTimer : public CEntity -{ - float x34_time; - float x38_startTime; - float x3c_maxRandDelay; - bool x40_loop; - bool x41_autoStart; - bool x42_isTiming; public: - CScriptTimer(TUniqueId, std::string_view name, const CEntityInfo& info, - float, float, bool, bool, bool); + CScriptTimer(TUniqueId, std::string_view name, const CEntityInfo& info, float, float, bool, bool, bool); - void Accept(IVisitor& visitor); - void Think(float, CStateManager &); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager &stateMgr); - bool IsTiming() const; - void StartTiming(bool isTiming); - void Reset(CStateManager&); - void ApplyTime(float, CStateManager&); + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + bool IsTiming() const; + void StartTiming(bool isTiming); + void Reset(CStateManager&); + void ApplyTime(float, CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptTrigger.cpp b/Runtime/World/CScriptTrigger.cpp index d8e3be19d..ec2156cdd 100644 --- a/Runtime/World/CScriptTrigger.cpp +++ b/Runtime/World/CScriptTrigger.cpp @@ -6,8 +6,7 @@ #include "Weapon/CGameProjectile.hpp" #include "Camera/CGameCamera.hpp" -namespace urde -{ +namespace urde { CScriptTrigger::CScriptTrigger(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, const zeus::CAABox& bounds, const CDamageInfo& dInfo, @@ -19,339 +18,271 @@ CScriptTrigger::CScriptTrigger(TUniqueId uid, std::string_view name, const CEnti , x11c_forceField(forceField) , x128_forceMagnitude(forceField.magnitude()) , x12c_flags(triggerFlags) -, x130_bounds(bounds) -{ - x148_24_detectCamera = false; - x148_25_camSubmerged = false; - x148_26_deactivateOnEntered = deactivateOnEntered; - x148_27_deactivateOnExited = deactivateOnExited; - x148_28_playerTriggerProc = false; - x148_29_didPhazonDamage = false; - SetCallTouch(false); +, x130_bounds(bounds) { + x148_24_detectCamera = false; + x148_25_camSubmerged = false; + x148_26_deactivateOnEntered = deactivateOnEntered; + x148_27_deactivateOnExited = deactivateOnExited; + x148_28_playerTriggerProc = false; + x148_29_didPhazonDamage = false; + SetCallTouch(false); } void CScriptTrigger::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptTrigger::Think(float dt, CStateManager& mgr) -{ - if (GetActive()) - UpdateInhabitants(dt, mgr); +void CScriptTrigger::Think(float dt, CStateManager& mgr) { + if (GetActive()) + UpdateInhabitants(dt, mgr); } -void CScriptTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (GetActive() && (msg == EScriptObjectMessage::Deactivate || msg == EScriptObjectMessage::Deleted)) - { - if (msg == EScriptObjectMessage::Deactivate) - { - xe8_inhabitants.clear(); - x148_25_camSubmerged = false; - } +void CScriptTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (GetActive() && (msg == EScriptObjectMessage::Deactivate || msg == EScriptObjectMessage::Deleted)) { + if (msg == EScriptObjectMessage::Deactivate) { + xe8_inhabitants.clear(); + x148_25_camSubmerged = false; + } - if (x148_28_playerTriggerProc) - { + if (x148_28_playerTriggerProc) { + x148_28_playerTriggerProc = false; + if (x148_29_didPhazonDamage) { + mgr.Player()->DecrementPhazon(); + x148_29_didPhazonDamage = false; + } + + if (x8_uid == mgr.GetLastTriggerId()) + mgr.SetLastTriggerId(kInvalidUniqueId); + } + } + + CEntity::AcceptScriptMsg(msg, uid, mgr); +} + +CScriptTrigger::CObjectTracker* CScriptTrigger::FindObject(TUniqueId id) { + auto& inhabitants = GetInhabitants(); + const auto& iter = std::find(inhabitants.begin(), inhabitants.end(), id); + + if (iter != inhabitants.end()) + return &(*iter); + return nullptr; +} + +void CScriptTrigger::UpdateInhabitants(float dt, CStateManager& mgr) { + bool sendInside = false; + bool sendExited = false; + std::list::iterator nextIt; + for (auto it = xe8_inhabitants.begin(); it != xe8_inhabitants.end(); it = nextIt) { + nextIt = it; + ++nextIt; + if (TCastToPtr act = mgr.ObjectById(it->GetObjectId())) { + bool playerValid = true; + if (it->GetObjectId() == mgr.GetPlayer().GetUniqueId()) { + if ((x12c_flags & ETriggerFlags::DetectPlayer) == ETriggerFlags::None && + ((mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && + (x12c_flags & ETriggerFlags::DetectUnmorphedPlayer) != ETriggerFlags::None) || + (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && + (x12c_flags & ETriggerFlags::DetectMorphedPlayer) != ETriggerFlags::None))) { + playerValid = false; + } + if (!playerValid) { + xe8_inhabitants.erase(it); + sendExited = true; + if (x148_28_playerTriggerProc) { x148_28_playerTriggerProc = false; - if (x148_29_didPhazonDamage) - { - mgr.Player()->DecrementPhazon(); - x148_29_didPhazonDamage = false; + if (x148_29_didPhazonDamage) { + mgr.GetPlayer().DecrementPhazon(); + x148_29_didPhazonDamage = false; } - if (x8_uid == mgr.GetLastTriggerId()) - mgr.SetLastTriggerId(kInvalidUniqueId); + if (mgr.GetLastTriggerId() == GetUniqueId()) + mgr.SetLastTriggerId(kInvalidUniqueId); + } + + InhabitantExited(*act, mgr); + continue; } + } + + auto touchBounds = GetTouchBounds(); + auto actTouchBounds = act->GetTouchBounds(); + if (touchBounds && actTouchBounds && touchBounds->intersects(*actTouchBounds)) { + sendInside = true; + InhabitantIdle(*act, mgr); + if (act->HealthInfo(mgr) && x100_damageInfo.GetDamage() > 0.f) + mgr.ApplyDamage(GetUniqueId(), act->GetUniqueId(), GetUniqueId(), {x100_damageInfo, dt}, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::CVector3f::skZero); + + if (x128_forceMagnitude > 0.f) { + if (TCastToPtr pact = act.GetPtr()) { + float forceMult = 1.f; + if ((x12c_flags & ETriggerFlags::UseBooleanIntersection) != ETriggerFlags::None) + forceMult = touchBounds->booleanIntersection(*actTouchBounds).volume() / actTouchBounds->volume(); + + zeus::CVector3f force = forceMult * x11c_forceField; + if ((x12c_flags & ETriggerFlags::UseCollisionImpulses) != ETriggerFlags::None) { + pact->ApplyImpulseWR(force, zeus::CAxisAngle::sIdentity); + pact->UseCollisionImpulses(); + } else + pact->ApplyForceWR(force, zeus::CAxisAngle::sIdentity); + } + } + } else { + TUniqueId tmpId = it->GetObjectId(); + xe8_inhabitants.erase(it); + sendExited = true; + if (mgr.GetPlayer().GetUniqueId() == tmpId && x148_28_playerTriggerProc) { + x148_28_playerTriggerProc = false; + if (x148_29_didPhazonDamage) { + mgr.Player()->DecrementPhazon(); + x148_29_didPhazonDamage = false; + } + + if (mgr.GetLastTriggerId() == GetUniqueId()) + mgr.SetLastTriggerId(kInvalidUniqueId); + } + + InhabitantExited(*act, mgr); + } + } else { + TUniqueId tmpId = it->GetObjectId(); + xe8_inhabitants.erase(it); + if (mgr.GetPlayer().GetUniqueId() == tmpId && x148_28_playerTriggerProc) { + x148_28_playerTriggerProc = false; + if (x148_29_didPhazonDamage) { + mgr.Player()->DecrementPhazon(); + x148_29_didPhazonDamage = false; + } + + if (mgr.GetLastTriggerId() == GetUniqueId()) + mgr.SetLastTriggerId(kInvalidUniqueId); + } } + } - CEntity::AcceptScriptMsg(msg, uid, mgr); -} - -CScriptTrigger::CObjectTracker* CScriptTrigger::FindObject(TUniqueId id) -{ - auto& inhabitants = GetInhabitants(); - const auto& iter = std::find(inhabitants.begin(), inhabitants.end(), id); - - if (iter != inhabitants.end()) - return &(*iter); - return nullptr; -} - -void CScriptTrigger::UpdateInhabitants(float dt, CStateManager& mgr) -{ - bool sendInside = false; - bool sendExited = false; - std::list::iterator nextIt; - for (auto it = xe8_inhabitants.begin(); it != xe8_inhabitants.end(); it = nextIt) - { - nextIt = it; - ++nextIt; - if (TCastToPtr act = mgr.ObjectById(it->GetObjectId())) - { - bool playerValid = true; - if (it->GetObjectId() == mgr.GetPlayer().GetUniqueId()) - { - if ((x12c_flags & ETriggerFlags::DetectPlayer) == ETriggerFlags::None && - ((mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && - (x12c_flags & ETriggerFlags::DetectUnmorphedPlayer) != ETriggerFlags::None) || - (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed && - (x12c_flags & ETriggerFlags::DetectMorphedPlayer) != ETriggerFlags::None))) - { - playerValid = false; - } - if (!playerValid) - { - xe8_inhabitants.erase(it); - sendExited = true; - if (x148_28_playerTriggerProc) - { - x148_28_playerTriggerProc = false; - if (x148_29_didPhazonDamage) - { - mgr.GetPlayer().DecrementPhazon(); - x148_29_didPhazonDamage = false; - } - - if (mgr.GetLastTriggerId() == GetUniqueId()) - mgr.SetLastTriggerId(kInvalidUniqueId); - } - - InhabitantExited(*act, mgr); - continue; - } - } - - auto touchBounds = GetTouchBounds(); - auto actTouchBounds = act->GetTouchBounds(); - if (touchBounds && actTouchBounds && touchBounds->intersects(*actTouchBounds)) - { - sendInside = true; - InhabitantIdle(*act, mgr); - if (act->HealthInfo(mgr) && x100_damageInfo.GetDamage() > 0.f) - mgr.ApplyDamage(GetUniqueId(), act->GetUniqueId(), GetUniqueId(), {x100_damageInfo, dt}, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), - zeus::CVector3f::skZero); - - if (x128_forceMagnitude > 0.f) - { - if (TCastToPtr pact = act.GetPtr()) - { - float forceMult = 1.f; - if ((x12c_flags & ETriggerFlags::UseBooleanIntersection) != ETriggerFlags::None) - forceMult = - touchBounds->booleanIntersection(*actTouchBounds).volume() / actTouchBounds->volume(); - - zeus::CVector3f force = forceMult * x11c_forceField; - if ((x12c_flags & ETriggerFlags::UseCollisionImpulses) != ETriggerFlags::None) - { - pact->ApplyImpulseWR(force, zeus::CAxisAngle::sIdentity); - pact->UseCollisionImpulses(); - } - else - pact->ApplyForceWR(force, zeus::CAxisAngle::sIdentity); - } - } - } - else - { - TUniqueId tmpId = it->GetObjectId(); - xe8_inhabitants.erase(it); - sendExited = true; - if (mgr.GetPlayer().GetUniqueId() == tmpId && x148_28_playerTriggerProc) - { - x148_28_playerTriggerProc = false; - if (x148_29_didPhazonDamage) - { - mgr.Player()->DecrementPhazon(); - x148_29_didPhazonDamage = false; - } - - if (mgr.GetLastTriggerId() == GetUniqueId()) - mgr.SetLastTriggerId(kInvalidUniqueId); - } - - InhabitantExited(*act, mgr); - } + if ((x12c_flags & ETriggerFlags::DetectCamera) != ETriggerFlags::None || x148_24_detectCamera) { + CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + bool camInTrigger = GetTriggerBoundsWR().pointInside(cam->GetTranslation()); + if (x148_25_camSubmerged) { + if (!camInTrigger) { + x148_25_camSubmerged = false; + if ((x12c_flags & ETriggerFlags::DetectCamera) != ETriggerFlags::None) { + sendExited = true; + InhabitantExited(*cam, mgr); } - else - { - TUniqueId tmpId = it->GetObjectId(); - xe8_inhabitants.erase(it); - if (mgr.GetPlayer().GetUniqueId() == tmpId && x148_28_playerTriggerProc) - { - x148_28_playerTriggerProc = false; - if (x148_29_didPhazonDamage) - { - mgr.Player()->DecrementPhazon(); - x148_29_didPhazonDamage = false; - } - - if (mgr.GetLastTriggerId() == GetUniqueId()) - mgr.SetLastTriggerId(kInvalidUniqueId); - } + } else { + if ((x12c_flags & ETriggerFlags::DetectCamera) != ETriggerFlags::None) { + InhabitantIdle(*cam, mgr); + sendInside = true; } + } + } else { + if (camInTrigger) { + x148_25_camSubmerged = true; + if ((x12c_flags & ETriggerFlags::DetectCamera) != ETriggerFlags::None) { + InhabitantAdded(*cam, mgr); + SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::Activate); + } + } } + } - if ((x12c_flags & ETriggerFlags::DetectCamera) != ETriggerFlags::None || x148_24_detectCamera) - { - CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - bool camInTrigger = GetTriggerBoundsWR().pointInside(cam->GetTranslation()); - if (x148_25_camSubmerged) - { - if (!camInTrigger) - { - x148_25_camSubmerged = false; - if ((x12c_flags & ETriggerFlags::DetectCamera) != ETriggerFlags::None) - { - sendExited = true; - InhabitantExited(*cam, mgr); - } - } - else - { - if ((x12c_flags & ETriggerFlags::DetectCamera) != ETriggerFlags::None) - { - InhabitantIdle(*cam, mgr); - sendInside = true; - } - } - } - else - { - if (camInTrigger) - { - x148_25_camSubmerged = true; - if ((x12c_flags & ETriggerFlags::DetectCamera) != ETriggerFlags::None) - { - InhabitantAdded(*cam, mgr); - SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::Activate); - } - } - } - } + if (sendInside) { + SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::Activate); + } - if (sendInside) - { - SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::Activate); - } - - if (sendExited) - { - SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::Activate); - if (x148_27_deactivateOnExited) - { - mgr.SendScriptMsg(GetUniqueId(), mgr.GetEditorIdForUniqueId(GetUniqueId()), - EScriptObjectMessage::Deactivate, EScriptObjectState::Exited); - } + if (sendExited) { + SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::Activate); + if (x148_27_deactivateOnExited) { + mgr.SendScriptMsg(GetUniqueId(), mgr.GetEditorIdForUniqueId(GetUniqueId()), EScriptObjectMessage::Deactivate, + EScriptObjectState::Exited); } + } } std::list& CScriptTrigger::GetInhabitants() { return xe8_inhabitants; } -std::experimental::optional CScriptTrigger::GetTouchBounds() const -{ - if (x30_24_active) - return {GetTriggerBoundsWR()}; - return {}; +std::experimental::optional CScriptTrigger::GetTouchBounds() const { + if (x30_24_active) + return {GetTriggerBoundsWR()}; + return {}; } static const CWeaponMode sktonOHurtWeaponMode = CWeaponMode(EWeaponType::Power, false, false, true); -void CScriptTrigger::Touch(CActor& act, CStateManager& mgr) -{ - if (!act.GetActive() || act.GetMaterialList().HasMaterial(EMaterialTypes::Trigger)) - return; +void CScriptTrigger::Touch(CActor& act, CStateManager& mgr) { + if (!act.GetActive() || act.GetMaterialList().HasMaterial(EMaterialTypes::Trigger)) + return; - if (FindObject(act.GetUniqueId()) == nullptr) - { - ETriggerFlags testFlags = ETriggerFlags::None; - TCastToPtr pl(act); - if (pl) - { - if (x128_forceMagnitude > 0.f && (x12c_flags & ETriggerFlags::DetectPlayer) != ETriggerFlags::None && - mgr.GetLastTriggerId() == kInvalidUniqueId) - mgr.SetLastTriggerId(x8_uid); + if (FindObject(act.GetUniqueId()) == nullptr) { + ETriggerFlags testFlags = ETriggerFlags::None; + TCastToPtr pl(act); + if (pl) { + if (x128_forceMagnitude > 0.f && (x12c_flags & ETriggerFlags::DetectPlayer) != ETriggerFlags::None && + mgr.GetLastTriggerId() == kInvalidUniqueId) + mgr.SetLastTriggerId(x8_uid); - testFlags |= ETriggerFlags::DetectPlayer; - if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) - testFlags |= ETriggerFlags::DetectUnmorphedPlayer; - else if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) - testFlags |= ETriggerFlags::DetectMorphedPlayer; - } - else if (TCastToPtr(act)) - { - testFlags |= ETriggerFlags::DetectAI; - } - else if (TCastToPtr(act)) - { - testFlags |= ETriggerFlags::DetectProjectiles1 | ETriggerFlags::DetectProjectiles2 | - ETriggerFlags::DetectProjectiles3 | ETriggerFlags::DetectProjectiles4 | - ETriggerFlags::DetectProjectiles5 | ETriggerFlags::DetectProjectiles6 | - ETriggerFlags::DetectProjectiles7; - } - else if (CWeapon* weap = TCastToPtr(act)) - { - if ((weap->GetAttribField() & EProjectileAttrib::Bombs) == EProjectileAttrib::Bombs) - testFlags |= ETriggerFlags::DetectBombs; - else if ((weap->GetAttribField() & EProjectileAttrib::PowerBombs) == EProjectileAttrib::PowerBombs) - testFlags |= ETriggerFlags::DetectPowerBombs; - } - - if ((testFlags & x12c_flags) != ETriggerFlags::None) - { - xe8_inhabitants.push_back(act.GetUniqueId()); - InhabitantAdded(act, mgr); - - if (pl) - { - if (!x148_28_playerTriggerProc) - { - x148_28_playerTriggerProc = true; - if (x148_29_didPhazonDamage) - { - mgr.Player()->DecrementPhazon(); - x148_29_didPhazonDamage = false; - } - else if (x100_damageInfo.GetDamage() > 0.f) - { - const CDamageVulnerability* dVuln = mgr.Player()->GetDamageVulnerability(); - if (dVuln->WeaponHurts(x100_damageInfo.GetWeaponMode(), 0) && - x100_damageInfo.GetWeaponMode().GetType() == EWeaponType::Phazon && - !mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit)) - { - pl->IncrementPhazon(); - x148_29_didPhazonDamage = true; - } - } - } - } - - SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); - - if (x148_26_deactivateOnEntered) - { - mgr.SendScriptMsg(x8_uid, mgr.GetEditorIdForUniqueId(x8_uid), EScriptObjectMessage::Deactivate, - EScriptObjectState::Entered); - if (act.HealthInfo(mgr) && x100_damageInfo.GetDamage() > 0.f) - { - mgr.ApplyDamage(x8_uid, act.GetUniqueId(), x8_uid, x100_damageInfo, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull}), - zeus::CVector3f::skZero); - } - } - - if ((x12c_flags & ETriggerFlags::KillOnEnter) != ETriggerFlags::None && act.HealthInfo(mgr)) - { - CHealthInfo* hInfo = act.HealthInfo(mgr); - mgr.ApplyDamage( - x8_uid, act.GetUniqueId(), x8_uid, {sktonOHurtWeaponMode, 10.f * hInfo->GetHP(), 0.f, 0.f}, - CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull}), zeus::CVector3f::skZero); - } - } - else - InhabitantRejected(act, mgr); + testFlags |= ETriggerFlags::DetectPlayer; + if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) + testFlags |= ETriggerFlags::DetectUnmorphedPlayer; + else if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) + testFlags |= ETriggerFlags::DetectMorphedPlayer; + } else if (TCastToPtr(act)) { + testFlags |= ETriggerFlags::DetectAI; + } else if (TCastToPtr(act)) { + testFlags |= ETriggerFlags::DetectProjectiles1 | ETriggerFlags::DetectProjectiles2 | + ETriggerFlags::DetectProjectiles3 | ETriggerFlags::DetectProjectiles4 | + ETriggerFlags::DetectProjectiles5 | ETriggerFlags::DetectProjectiles6 | + ETriggerFlags::DetectProjectiles7; + } else if (CWeapon* weap = TCastToPtr(act)) { + if ((weap->GetAttribField() & EProjectileAttrib::Bombs) == EProjectileAttrib::Bombs) + testFlags |= ETriggerFlags::DetectBombs; + else if ((weap->GetAttribField() & EProjectileAttrib::PowerBombs) == EProjectileAttrib::PowerBombs) + testFlags |= ETriggerFlags::DetectPowerBombs; } + + if ((testFlags & x12c_flags) != ETriggerFlags::None) { + xe8_inhabitants.push_back(act.GetUniqueId()); + InhabitantAdded(act, mgr); + + if (pl) { + if (!x148_28_playerTriggerProc) { + x148_28_playerTriggerProc = true; + if (x148_29_didPhazonDamage) { + mgr.Player()->DecrementPhazon(); + x148_29_didPhazonDamage = false; + } else if (x100_damageInfo.GetDamage() > 0.f) { + const CDamageVulnerability* dVuln = mgr.Player()->GetDamageVulnerability(); + if (dVuln->WeaponHurts(x100_damageInfo.GetWeaponMode(), 0) && + x100_damageInfo.GetWeaponMode().GetType() == EWeaponType::Phazon && + !mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::PhazonSuit)) { + pl->IncrementPhazon(); + x148_29_didPhazonDamage = true; + } + } + } + } + + SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None); + + if (x148_26_deactivateOnEntered) { + mgr.SendScriptMsg(x8_uid, mgr.GetEditorIdForUniqueId(x8_uid), EScriptObjectMessage::Deactivate, + EScriptObjectState::Entered); + if (act.HealthInfo(mgr) && x100_damageInfo.GetDamage() > 0.f) { + mgr.ApplyDamage(x8_uid, act.GetUniqueId(), x8_uid, x100_damageInfo, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull}), + zeus::CVector3f::skZero); + } + } + + if ((x12c_flags & ETriggerFlags::KillOnEnter) != ETriggerFlags::None && act.HealthInfo(mgr)) { + CHealthInfo* hInfo = act.HealthInfo(mgr); + mgr.ApplyDamage(x8_uid, act.GetUniqueId(), x8_uid, {sktonOHurtWeaponMode, 10.f * hInfo->GetHP(), 0.f, 0.f}, + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {0ull}), zeus::CVector3f::skZero); + } + } else + InhabitantRejected(act, mgr); + } } -zeus::CAABox CScriptTrigger::GetTriggerBoundsWR() const -{ - return {x130_bounds.min + x34_transform.origin, x130_bounds.max + x34_transform.origin}; -} +zeus::CAABox CScriptTrigger::GetTriggerBoundsWR() const { + return {x130_bounds.min + x34_transform.origin, x130_bounds.max + x34_transform.origin}; } +} // namespace urde diff --git a/Runtime/World/CScriptTrigger.hpp b/Runtime/World/CScriptTrigger.hpp index 9b683db2c..5b52940cf 100644 --- a/Runtime/World/CScriptTrigger.hpp +++ b/Runtime/World/CScriptTrigger.hpp @@ -3,92 +3,86 @@ #include "CActor.hpp" #include "CDamageInfo.hpp" -namespace urde -{ +namespace urde { // TODO - Phil: Figure out what each of the DetectProjectiles actually mean -enum class ETriggerFlags : u32 -{ - None = 0, - DetectPlayer = (1 << 0), - DetectAI = (1 << 1), - DetectProjectiles1 = (1 << 2), - DetectProjectiles2 = (1 << 3), - DetectProjectiles3 = (1 << 4), - DetectProjectiles4 = (1 << 5), - DetectBombs = (1 << 6), - DetectPowerBombs = (1 << 7), - DetectProjectiles5 = (1 << 8), - DetectProjectiles6 = (1 << 9), - DetectProjectiles7 = (1 << 10), - KillOnEnter = (1 << 11), - DetectMorphedPlayer = (1 << 12), - UseCollisionImpulses = (1 << 13), - DetectCamera = (1 << 14), - UseBooleanIntersection = (1 << 15), - DetectUnmorphedPlayer = (1 << 16), - BlockEnvironmentalEffects = (1 << 17) +enum class ETriggerFlags : u32 { + None = 0, + DetectPlayer = (1 << 0), + DetectAI = (1 << 1), + DetectProjectiles1 = (1 << 2), + DetectProjectiles2 = (1 << 3), + DetectProjectiles3 = (1 << 4), + DetectProjectiles4 = (1 << 5), + DetectBombs = (1 << 6), + DetectPowerBombs = (1 << 7), + DetectProjectiles5 = (1 << 8), + DetectProjectiles6 = (1 << 9), + DetectProjectiles7 = (1 << 10), + KillOnEnter = (1 << 11), + DetectMorphedPlayer = (1 << 12), + UseCollisionImpulses = (1 << 13), + DetectCamera = (1 << 14), + UseBooleanIntersection = (1 << 15), + DetectUnmorphedPlayer = (1 << 16), + BlockEnvironmentalEffects = (1 << 17) }; ENABLE_BITWISE_ENUM(ETriggerFlags) -class CScriptTrigger : public CActor -{ +class CScriptTrigger : public CActor { public: - class CObjectTracker - { - TUniqueId x0_id; + class CObjectTracker { + TUniqueId x0_id; - public: - CObjectTracker(TUniqueId id) : x0_id(id) {} + public: + CObjectTracker(TUniqueId id) : x0_id(id) {} - TUniqueId GetObjectId() const { return x0_id; } - bool operator==(const CObjectTracker& other) const { return x0_id == other.x0_id; } - }; + TUniqueId GetObjectId() const { return x0_id; } + bool operator==(const CObjectTracker& other) const { return x0_id == other.x0_id; } + }; protected: - std::list xe8_inhabitants; - CDamageInfo x100_damageInfo; - zeus::CVector3f x11c_forceField; - float x128_forceMagnitude; - ETriggerFlags x12c_flags; - zeus::CAABox x130_bounds; + std::list xe8_inhabitants; + CDamageInfo x100_damageInfo; + zeus::CVector3f x11c_forceField; + float x128_forceMagnitude; + ETriggerFlags x12c_flags; + zeus::CAABox x130_bounds; - union { - struct - { - bool x148_24_detectCamera : 1; - bool x148_25_camSubmerged : 1; - bool x148_26_deactivateOnEntered : 1; - bool x148_27_deactivateOnExited : 1; - bool x148_28_playerTriggerProc : 1; - bool x148_29_didPhazonDamage : 1; - }; - u8 dummy = 0; + union { + struct { + bool x148_24_detectCamera : 1; + bool x148_25_camSubmerged : 1; + bool x148_26_deactivateOnEntered : 1; + bool x148_27_deactivateOnExited : 1; + bool x148_28_playerTriggerProc : 1; + bool x148_29_didPhazonDamage : 1; }; + u8 dummy = 0; + }; public: - CScriptTrigger(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, - const zeus::CAABox&, const CDamageInfo& dInfo, const zeus::CVector3f& orientedForce, - ETriggerFlags triggerFlags, bool, bool, bool); + CScriptTrigger(TUniqueId, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, + const zeus::CAABox&, const CDamageInfo& dInfo, const zeus::CVector3f& orientedForce, + ETriggerFlags triggerFlags, bool, bool, bool); - void Accept(IVisitor& visitor); - void Think(float, CStateManager &); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &); - virtual void InhabitantRejected(CActor&, CStateManager&) {} - virtual void InhabitantExited(CActor&, CStateManager&) {} - virtual void InhabitantIdle(CActor&, CStateManager&) {} - virtual void InhabitantAdded(CActor&, CStateManager&) {} - CObjectTracker* FindObject(TUniqueId); - void UpdateInhabitants(float, CStateManager&); - std::list& GetInhabitants(); - std::experimental::optional GetTouchBounds() const; - void Touch(CActor &, CStateManager &); - const zeus::CAABox& GetTriggerBoundsOR() const { return x130_bounds; } - zeus::CAABox GetTriggerBoundsWR() const; - const CDamageInfo& GetDamageInfo() const { return x100_damageInfo; } - ETriggerFlags GetTriggerFlags() const { return x12c_flags; } - float GetForceMagnitude() const { return x128_forceMagnitude; } - const zeus::CVector3f& GetForceVector() const { return x11c_forceField; } + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + virtual void InhabitantRejected(CActor&, CStateManager&) {} + virtual void InhabitantExited(CActor&, CStateManager&) {} + virtual void InhabitantIdle(CActor&, CStateManager&) {} + virtual void InhabitantAdded(CActor&, CStateManager&) {} + CObjectTracker* FindObject(TUniqueId); + void UpdateInhabitants(float, CStateManager&); + std::list& GetInhabitants(); + std::experimental::optional GetTouchBounds() const; + void Touch(CActor&, CStateManager&); + const zeus::CAABox& GetTriggerBoundsOR() const { return x130_bounds; } + zeus::CAABox GetTriggerBoundsWR() const; + const CDamageInfo& GetDamageInfo() const { return x100_damageInfo; } + ETriggerFlags GetTriggerFlags() const { return x12c_flags; } + float GetForceMagnitude() const { return x128_forceMagnitude; } + const zeus::CVector3f& GetForceVector() const { return x11c_forceField; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptVisorFlare.cpp b/Runtime/World/CScriptVisorFlare.cpp index 2419da7df..a9b285e1f 100644 --- a/Runtime/World/CScriptVisorFlare.cpp +++ b/Runtime/World/CScriptVisorFlare.cpp @@ -5,50 +5,38 @@ #include "CPlayer.hpp" #include "Particle/CGenDescription.hpp" -namespace urde -{ +namespace urde { -CScriptVisorFlare::CScriptVisorFlare(TUniqueId uid, std::string_view name, const CEntityInfo& info, - bool active, const zeus::CVector3f& pos, CVisorFlare::EBlendMode blendMode, - bool b1, float f1, float f2, float f3, u32 w1, u32 w2, - const std::vector& flares) +CScriptVisorFlare::CScriptVisorFlare(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, + const zeus::CVector3f& pos, CVisorFlare::EBlendMode blendMode, bool b1, float f1, + float f2, float f3, u32 w1, u32 w2, + const std::vector& flares) : CActor(uid, active, name, info, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(), - CMaterialList(EMaterialTypes::NoStepLogic), CActorParameters::None(), kInvalidUniqueId), - xe8_flare(blendMode, b1, f1, f2, f3, w1, w2, flares) -{ - xe6_27_thermalVisorFlags = 2; + CMaterialList(EMaterialTypes::NoStepLogic), CActorParameters::None(), kInvalidUniqueId) +, xe8_flare(blendMode, b1, f1, f2, f3, w1, w2, flares) { + xe6_27_thermalVisorFlags = 2; } -void CScriptVisorFlare::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptVisorFlare::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptVisorFlare::Think(float dt, CStateManager& stateMgr) { + if (GetActive()) + xe8_flare.Update(dt, GetTranslation(), this, stateMgr); } -void CScriptVisorFlare::Think(float dt, CStateManager& stateMgr) -{ - if (GetActive()) - xe8_flare.Update(dt, GetTranslation(), this, stateMgr); +void CScriptVisorFlare::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) { + CActor::AcceptScriptMsg(msg, objId, stateMgr); } -void CScriptVisorFlare::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) -{ - CActor::AcceptScriptMsg(msg, objId, stateMgr); +void CScriptVisorFlare::PreRender(CStateManager& stateMgr, const zeus::CFrustum&) { + x11c_notInRenderLast = !stateMgr.RenderLast(x8_uid); } -void CScriptVisorFlare::PreRender(CStateManager& stateMgr, const zeus::CFrustum&) -{ - x11c_notInRenderLast = !stateMgr.RenderLast(x8_uid); +void CScriptVisorFlare::AddToRenderer(const zeus::CFrustum&, const CStateManager& stateMgr) const { + if (x11c_notInRenderLast) + EnsureRendered(stateMgr, stateMgr.GetPlayer().GetTranslation(), GetSortingBounds(stateMgr)); } -void CScriptVisorFlare::AddToRenderer(const zeus::CFrustum&, const CStateManager& stateMgr) const -{ - if (x11c_notInRenderLast) - EnsureRendered(stateMgr, stateMgr.GetPlayer().GetTranslation(), GetSortingBounds(stateMgr)); -} +void CScriptVisorFlare::Render(const CStateManager& stateMgr) const { xe8_flare.Render(GetTranslation(), stateMgr); } -void CScriptVisorFlare::Render(const CStateManager& stateMgr) const -{ - xe8_flare.Render(GetTranslation(), stateMgr); -} - -} +} // namespace urde diff --git a/Runtime/World/CScriptVisorFlare.hpp b/Runtime/World/CScriptVisorFlare.hpp index 6965f0dc1..59c5b29c8 100644 --- a/Runtime/World/CScriptVisorFlare.hpp +++ b/Runtime/World/CScriptVisorFlare.hpp @@ -3,27 +3,23 @@ #include "CActor.hpp" #include "CVisorFlare.hpp" -namespace urde -{ +namespace urde { -class CScriptVisorFlare : public CActor -{ - CVisorFlare xe8_flare; - bool x11c_notInRenderLast = true; +class CScriptVisorFlare : public CActor { + CVisorFlare xe8_flare; + bool x11c_notInRenderLast = true; public: - CScriptVisorFlare(TUniqueId, std::string_view name, const CEntityInfo& info, - bool, const zeus::CVector3f&, CVisorFlare::EBlendMode blendMode, - bool, float, float, float, u32, u32, - const std::vector& flares); + CScriptVisorFlare(TUniqueId, std::string_view name, const CEntityInfo& info, bool, const zeus::CVector3f&, + CVisorFlare::EBlendMode blendMode, bool, float, float, float, u32, u32, + const std::vector& flares); - void Accept(IVisitor& visitor); - void Think(float, CStateManager& stateMgr); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); - void PreRender(CStateManager&, const zeus::CFrustum&); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - void Render(const CStateManager&) const; + void Accept(IVisitor& visitor); + void Think(float, CStateManager& stateMgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void PreRender(CStateManager&, const zeus::CFrustum&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const; }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptVisorGoo.cpp b/Runtime/World/CScriptVisorGoo.cpp index 7edc5d521..1da8824d9 100644 --- a/Runtime/World/CScriptVisorGoo.cpp +++ b/Runtime/World/CScriptVisorGoo.cpp @@ -7,136 +7,111 @@ #include "CPlayer.hpp" #include "CHUDBillboardEffect.hpp" -namespace urde -{ +namespace urde { CScriptVisorGoo::CScriptVisorGoo(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, CAssetId particle, CAssetId electric, - float minDist, float maxDist, float nearProb, float farProb, - const zeus::CColor& color, int sfx, bool forceShow, bool active) -: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), {}, CActorParameters::None(), kInvalidUniqueId), - xe8_particleDesc(CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject({}))), - xf0_electricDesc(CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject({}))), - xf8_sfx(CSfxManager::TranslateSFXID(sfx)), xfc_particleId(particle), x100_electricId(electric), - x104_minDist(minDist), x108_maxDist(std::max(maxDist, minDist + 0.01f)), x10c_nearProb(nearProb), - x110_farProb(farProb), x114_color(color) -{ - x118_24_angleTest = !forceShow; - if (particle.IsValid()) - xe8_particleDesc = g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), particle}); - if (electric.IsValid()) - xf0_electricDesc = g_SimplePool->GetObj(SObjectTag{FOURCC('ELSC'), electric}); + const zeus::CTransform& xf, CAssetId particle, CAssetId electric, float minDist, + float maxDist, float nearProb, float farProb, const zeus::CColor& color, int sfx, + bool forceShow, bool active) +: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), {}, CActorParameters::None(), kInvalidUniqueId) +, xe8_particleDesc(CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject({}))) +, xf0_electricDesc(CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject({}))) +, xf8_sfx(CSfxManager::TranslateSFXID(sfx)) +, xfc_particleId(particle) +, x100_electricId(electric) +, x104_minDist(minDist) +, x108_maxDist(std::max(maxDist, minDist + 0.01f)) +, x10c_nearProb(nearProb) +, x110_farProb(farProb) +, x114_color(color) { + x118_24_angleTest = !forceShow; + if (particle.IsValid()) + xe8_particleDesc = g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), particle}); + if (electric.IsValid()) + xf0_electricDesc = g_SimplePool->GetObj(SObjectTag{FOURCC('ELSC'), electric}); } -void CScriptVisorGoo::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptVisorGoo::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptVisorGoo::Think(float, CStateManager& mgr) -{ - if (GetActive()) - { - bool loaded = false; - if (xfc_particleId.IsValid()) - { - if (xe8_particleDesc.IsLoaded()) - { - if (x100_electricId.IsValid()) - loaded = xf0_electricDesc.IsLoaded(); - else - loaded = true; - } - } - else - { - loaded = xf0_electricDesc.IsLoaded(); - } - - if (loaded) - { - bool showGoo = false; - if (mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) - { - zeus::CVector3f eyeToGoo = GetTranslation() - mgr.GetPlayer().GetEyePosition(); - float eyeToGooDist = eyeToGoo.magnitude(); - if (eyeToGooDist >= x104_minDist && eyeToGooDist <= x108_maxDist) - { - if (x118_24_angleTest) - { - float angle = zeus::radToDeg( - std::acos(mgr.GetCameraManager()->GetCurrentCameraTransform(mgr).basis[1]. - normalized().dot(eyeToGoo.normalized()))); - float angleThresh = 45.f; - if (eyeToGooDist < 4.f) - { - angleThresh *= 4.f / eyeToGooDist; - angleThresh = std::min(90.f, angleThresh); - } - if (angle <= angleThresh) - showGoo = true; - } - else - { - showGoo = true; - } - if (showGoo) - { - float t = (x108_maxDist - eyeToGooDist) / (x108_maxDist - x104_minDist); - if (mgr.GetActiveRandom()->Float() * 100.f <= (1.f - t) * x110_farProb + t * x10c_nearProb) - { - mgr.AddObject(new CHUDBillboardEffect( - xfc_particleId.IsValid() ? xe8_particleDesc : - std::experimental::optional>(), - x100_electricId.IsValid() ? xf0_electricDesc : - std::experimental::optional>(), - mgr.AllocateUniqueId(), true, "VisorGoo", - CHUDBillboardEffect::GetNearClipDistance(mgr), - CHUDBillboardEffect::GetScaleForPOV(mgr), - x114_color, zeus::CVector3f::skOne, zeus::CVector3f::skZero)); - CSfxManager::SfxStart(xf8_sfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } - } - } - } - mgr.FreeScriptObject(GetUniqueId()); - } - } -} - -void CScriptVisorGoo::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Activate: - if (xfc_particleId.IsValid()) - xe8_particleDesc.Lock(); +void CScriptVisorGoo::Think(float, CStateManager& mgr) { + if (GetActive()) { + bool loaded = false; + if (xfc_particleId.IsValid()) { + if (xe8_particleDesc.IsLoaded()) { if (x100_electricId.IsValid()) - xf0_electricDesc.Lock(); - default: - break; + loaded = xf0_electricDesc.IsLoaded(); + else + loaded = true; + } + } else { + loaded = xf0_electricDesc.IsLoaded(); } - CActor::AcceptScriptMsg(msg, objId, mgr); + + if (loaded) { + bool showGoo = false; + if (mgr.GetPlayer().GetCameraState() == CPlayer::EPlayerCameraState::FirstPerson) { + zeus::CVector3f eyeToGoo = GetTranslation() - mgr.GetPlayer().GetEyePosition(); + float eyeToGooDist = eyeToGoo.magnitude(); + if (eyeToGooDist >= x104_minDist && eyeToGooDist <= x108_maxDist) { + if (x118_24_angleTest) { + float angle = zeus::radToDeg( + std::acos(mgr.GetCameraManager()->GetCurrentCameraTransform(mgr).basis[1].normalized().dot( + eyeToGoo.normalized()))); + float angleThresh = 45.f; + if (eyeToGooDist < 4.f) { + angleThresh *= 4.f / eyeToGooDist; + angleThresh = std::min(90.f, angleThresh); + } + if (angle <= angleThresh) + showGoo = true; + } else { + showGoo = true; + } + if (showGoo) { + float t = (x108_maxDist - eyeToGooDist) / (x108_maxDist - x104_minDist); + if (mgr.GetActiveRandom()->Float() * 100.f <= (1.f - t) * x110_farProb + t * x10c_nearProb) { + mgr.AddObject(new CHUDBillboardEffect( + xfc_particleId.IsValid() ? xe8_particleDesc : std::experimental::optional>(), + x100_electricId.IsValid() ? xf0_electricDesc + : std::experimental::optional>(), + mgr.AllocateUniqueId(), true, "VisorGoo", CHUDBillboardEffect::GetNearClipDistance(mgr), + CHUDBillboardEffect::GetScaleForPOV(mgr), x114_color, zeus::CVector3f::skOne, + zeus::CVector3f::skZero)); + CSfxManager::SfxStart(xf8_sfx, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + } + } + } + mgr.FreeScriptObject(GetUniqueId()); + } + } } -void CScriptVisorGoo::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const -{ - // Empty +void CScriptVisorGoo::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Activate: + if (xfc_particleId.IsValid()) + xe8_particleDesc.Lock(); + if (x100_electricId.IsValid()) + xf0_electricDesc.Lock(); + default: + break; + } + CActor::AcceptScriptMsg(msg, objId, mgr); } -void CScriptVisorGoo::Render(const CStateManager& mgr) const -{ - // Empty +void CScriptVisorGoo::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const { + // Empty } -std::experimental::optional CScriptVisorGoo::GetTouchBounds() const -{ - return {}; +void CScriptVisorGoo::Render(const CStateManager& mgr) const { + // Empty } -void CScriptVisorGoo::Touch(CActor& other, CStateManager& mgr) -{ - // Empty +std::experimental::optional CScriptVisorGoo::GetTouchBounds() const { return {}; } + +void CScriptVisorGoo::Touch(CActor& other, CStateManager& mgr) { + // Empty } -} +} // namespace urde diff --git a/Runtime/World/CScriptVisorGoo.hpp b/Runtime/World/CScriptVisorGoo.hpp index 0178d2d52..ffd3f2da4 100644 --- a/Runtime/World/CScriptVisorGoo.hpp +++ b/Runtime/World/CScriptVisorGoo.hpp @@ -2,35 +2,33 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { + +class CScriptVisorGoo : public CActor { + TToken xe8_particleDesc; + TToken xf0_electricDesc; + u16 xf8_sfx; + CAssetId xfc_particleId; + CAssetId x100_electricId; + float x104_minDist; + float x108_maxDist; + float x10c_nearProb; + float x110_farProb; + zeus::CColor x114_color; + bool x118_24_angleTest : 1; -class CScriptVisorGoo : public CActor -{ - TToken xe8_particleDesc; - TToken xf0_electricDesc; - u16 xf8_sfx; - CAssetId xfc_particleId; - CAssetId x100_electricId; - float x104_minDist; - float x108_maxDist; - float x10c_nearProb; - float x110_farProb; - zeus::CColor x114_color; - bool x118_24_angleTest : 1; public: - CScriptVisorGoo(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, - CAssetId particle, CAssetId electric, float minDist, float maxDist, float nearProb, float farProb, - const zeus::CColor& color, int sfx, bool forceShow, bool active); + CScriptVisorGoo(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + CAssetId particle, CAssetId electric, float minDist, float maxDist, float nearProb, float farProb, + const zeus::CColor& color, int sfx, bool forceShow, bool active); - void Accept(IVisitor& visitor); - void Think(float, CStateManager& stateMgr); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - void Render(const CStateManager&) const; - std::experimental::optional GetTouchBounds() const; - void Touch(CActor&, CStateManager&); + void Accept(IVisitor& visitor); + void Think(float, CStateManager& stateMgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const; + std::experimental::optional GetTouchBounds() const; + void Touch(CActor&, CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptWater.cpp b/Runtime/World/CScriptWater.cpp index bfb8a6565..b81b78e03 100644 --- a/Runtime/World/CScriptWater.cpp +++ b/Runtime/World/CScriptWater.cpp @@ -8,627 +8,546 @@ #include "Camera/CGameCamera.hpp" #include "CFluidPlaneGPU.hpp" -namespace urde -{ +namespace urde { -const float CScriptWater::kSplashScales[6] = -{ - 1.0f, 3.0f, 0.709f, - 1.19f, 0.709f, 1.f -}; +const float CScriptWater::kSplashScales[6] = {1.0f, 3.0f, 0.709f, 1.19f, 0.709f, 1.f}; -CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo, - zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool thermalCold, - bool allowRender, CAssetId patternMap1, CAssetId patternMap2, CAssetId colorMap, - CAssetId bumpMap, CAssetId envMap, CAssetId envBumpMap, CAssetId unusedMap, - const zeus::CVector3f& bumpLightDir, float bumpScale, float morphInTime, float morphOutTime, - bool active, EFluidType fluidType, bool b4, float alpha, - const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax, - float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, - float turbAmplitudeMin, const zeus::CColor& splashColor, const zeus::CColor& insideFogColor, - CAssetId splashParticle1, CAssetId splashParticle2, CAssetId splashParticle3, - CAssetId visorRunoffParticle, CAssetId unmorphVisorRunoffparticle, s32 visorRunoffSfx, - s32 unmorphVisorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize, - u32 tileSubdivisions, float specularMin, float specularMax, float reflectionSize, - float rippleIntensity, float reflectionBlend, float fogBias, float fogMagnitude, - float fogSpeed, const zeus::CColor& fogColor, CAssetId lightmapId, - float unitsPerLightmapTexel, float alphaInTime, float alphaOutTime, u32, u32, bool, s32, - s32, std::unique_ptr&& u32Arr) -: CScriptTrigger(uid, name, info, pos, box, dInfo, orientedForce, triggerFlags, active, false, false), - x1b8_positionMorphed(pos), x1c4_extentMorphed(box.max - box.min), x1d0_morphInTime(morphInTime), x1d4_positionOrig(pos), - x1e0_extentOrig(box.max - box.min), x1ec_damageOrig(dInfo.GetDamage()), x1f0_damageMorphed(dInfo.GetDamage()), - x1f4_morphOutTime(morphOutTime), x214_fogBias(fogBias), x218_fogMagnitude(fogMagnitude), x21c_origFogBias(fogBias), - x220_origFogMagnitude(fogMagnitude), x224_fogSpeed(fogSpeed), x228_fogColor(fogColor), - x22c_splashParticle1Id(splashParticle1), x230_splashParticle2Id(splashParticle2), - x234_splashParticle3Id(splashParticle3), x238_visorRunoffParticleId(visorRunoffParticle), - x24c_unmorphVisorRunoffParticleId(unmorphVisorRunoffparticle), - x260_visorRunoffSfx(CSfxManager::TranslateSFXID(visorRunoffSfx)), - x262_unmorphVisorRunoffSfx(CSfxManager::TranslateSFXID(unmorphVisorRunoffSfx)), - x2a4_splashColor(splashColor), x2a8_insideFogColor(insideFogColor), x2ac_alphaInTime(alphaInTime), - x2b0_alphaOutTime(alphaOutTime), x2b4_alphaInRecip((alphaInTime != 0.f) ? 1.f / alphaInTime : 0.f), - x2b8_alphaOutRecip((alphaOutTime != 0.f) ? 1.f / alphaOutTime : 0.f), x2bc_alpha(alpha), x2c0_tileSize(tileSize) -{ - zeus::CAABox triggerAABB = GetTriggerBoundsWR(); - x2c4_gridDimX = u32((x2c0_tileSize + triggerAABB.max.x() - triggerAABB.min.x() - 0.01f) / x2c0_tileSize); - x2c8_gridDimY = u32((x2c0_tileSize + triggerAABB.max.y() - triggerAABB.min.y() - 0.01f) / x2c0_tileSize); - x2cc_gridCellCount = (x2c4_gridDimX + 1) * (x2c8_gridDimY + 1); - x2e8_24_b4 = b4; - x2e8_27_allowRender = allowRender; - x2e8_28_recomputeClipping = true; +CScriptWater::CScriptWater( + CStateManager& mgr, TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, + const zeus::CAABox& box, const urde::CDamageInfo& dInfo, zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, + bool thermalCold, bool allowRender, CAssetId patternMap1, CAssetId patternMap2, CAssetId colorMap, CAssetId bumpMap, + CAssetId envMap, CAssetId envBumpMap, CAssetId unusedMap, const zeus::CVector3f& bumpLightDir, float bumpScale, + float morphInTime, float morphOutTime, bool active, EFluidType fluidType, bool b4, float alpha, + const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin, + float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin, + const zeus::CColor& splashColor, const zeus::CColor& insideFogColor, CAssetId splashParticle1, + CAssetId splashParticle2, CAssetId splashParticle3, CAssetId visorRunoffParticle, + CAssetId unmorphVisorRunoffparticle, s32 visorRunoffSfx, s32 unmorphVisorRunoffSfx, s32 splashSfx1, s32 splashSfx2, + s32 splashSfx3, float tileSize, u32 tileSubdivisions, float specularMin, float specularMax, float reflectionSize, + float rippleIntensity, float reflectionBlend, float fogBias, float fogMagnitude, float fogSpeed, + const zeus::CColor& fogColor, CAssetId lightmapId, float unitsPerLightmapTexel, float alphaInTime, + float alphaOutTime, u32, u32, bool, s32, s32, std::unique_ptr&& u32Arr) +: CScriptTrigger(uid, name, info, pos, box, dInfo, orientedForce, triggerFlags, active, false, false) +, x1b8_positionMorphed(pos) +, x1c4_extentMorphed(box.max - box.min) +, x1d0_morphInTime(morphInTime) +, x1d4_positionOrig(pos) +, x1e0_extentOrig(box.max - box.min) +, x1ec_damageOrig(dInfo.GetDamage()) +, x1f0_damageMorphed(dInfo.GetDamage()) +, x1f4_morphOutTime(morphOutTime) +, x214_fogBias(fogBias) +, x218_fogMagnitude(fogMagnitude) +, x21c_origFogBias(fogBias) +, x220_origFogMagnitude(fogMagnitude) +, x224_fogSpeed(fogSpeed) +, x228_fogColor(fogColor) +, x22c_splashParticle1Id(splashParticle1) +, x230_splashParticle2Id(splashParticle2) +, x234_splashParticle3Id(splashParticle3) +, x238_visorRunoffParticleId(visorRunoffParticle) +, x24c_unmorphVisorRunoffParticleId(unmorphVisorRunoffparticle) +, x260_visorRunoffSfx(CSfxManager::TranslateSFXID(visorRunoffSfx)) +, x262_unmorphVisorRunoffSfx(CSfxManager::TranslateSFXID(unmorphVisorRunoffSfx)) +, x2a4_splashColor(splashColor) +, x2a8_insideFogColor(insideFogColor) +, x2ac_alphaInTime(alphaInTime) +, x2b0_alphaOutTime(alphaOutTime) +, x2b4_alphaInRecip((alphaInTime != 0.f) ? 1.f / alphaInTime : 0.f) +, x2b8_alphaOutRecip((alphaOutTime != 0.f) ? 1.f / alphaOutTime : 0.f) +, x2bc_alpha(alpha) +, x2c0_tileSize(tileSize) { + zeus::CAABox triggerAABB = GetTriggerBoundsWR(); + x2c4_gridDimX = u32((x2c0_tileSize + triggerAABB.max.x() - triggerAABB.min.x() - 0.01f) / x2c0_tileSize); + x2c8_gridDimY = u32((x2c0_tileSize + triggerAABB.max.y() - triggerAABB.min.y() - 0.01f) / x2c0_tileSize); + x2cc_gridCellCount = (x2c4_gridDimX + 1) * (x2c8_gridDimY + 1); + x2e8_24_b4 = b4; + x2e8_27_allowRender = allowRender; + x2e8_28_recomputeClipping = true; - uint32_t maxPatchSize; - if (CGraphics::g_BooFactory->isTessellationSupported(maxPatchSize)) - x1b4_fluidPlane = std::make_unique(patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap, - lightmapId, unitsPerLightmapTexel, tileSize, tileSubdivisions * 2, - fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot, - turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax, - turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin, - specularMax, reflectionBlend, reflectionSize, rippleIntensity, - x2cc_gridCellCount * - ((std::max(u32(2), tileSubdivisions * 2) * 4 + 2) * 4)); - else - x1b4_fluidPlane = std::make_unique(patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap, - lightmapId, unitsPerLightmapTexel, tileSize, tileSubdivisions, - fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot, - turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax, - turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin, - specularMax, reflectionBlend, reflectionSize, rippleIntensity, - x2cc_gridCellCount * - ((std::max(u32(2), tileSubdivisions) * 4 + 2) * 4)); - u32Arr.reset(); - x264_splashEffects.resize(3); - if (x22c_splashParticle1Id.IsValid()) - x264_splashEffects[0].emplace(g_SimplePool->GetObj({FOURCC('PART'), x22c_splashParticle1Id})); - if (x230_splashParticle2Id.IsValid()) - x264_splashEffects[1].emplace(g_SimplePool->GetObj({FOURCC('PART'), x230_splashParticle2Id})); - if (x234_splashParticle3Id.IsValid()) - x264_splashEffects[2].emplace(g_SimplePool->GetObj({FOURCC('PART'), x234_splashParticle3Id})); - if (x238_visorRunoffParticleId.IsValid()) - x23c_visorRunoffEffect.emplace(g_SimplePool->GetObj({FOURCC('PART'), x238_visorRunoffParticleId})); - if (x24c_unmorphVisorRunoffParticleId.IsValid()) - x250_unmorphVisorRunoffEffect.emplace(g_SimplePool->GetObj({FOURCC('PART'), x24c_unmorphVisorRunoffParticleId})); - x298_splashSounds.push_back(CSfxManager::TranslateSFXID(splashSfx1)); - x298_splashSounds.push_back(CSfxManager::TranslateSFXID(splashSfx2)); - x298_splashSounds.push_back(CSfxManager::TranslateSFXID(splashSfx3)); - SetCalculateLighting(true); - if (lightmapId.IsValid()) - x90_actorLights->DisableAreaLights(); - x90_actorLights->SetMaxDynamicLights(4); - x90_actorLights->SetCastShadows(false); - x90_actorLights->SetAmbienceGenerated(false); - x90_actorLights->SetFindNearestDynamicLights(true); - x148_24_detectCamera = true; - CalculateRenderBounds(); - xe6_27_thermalVisorFlags = u8(thermalCold ? 2 : 1); - if (!x30_24_active) - { - x2bc_alpha = 0.f; - x214_fogBias = 0.f; - x218_fogMagnitude = 0.f; - } - SetupGrid(true); + uint32_t maxPatchSize; + if (CGraphics::g_BooFactory->isTessellationSupported(maxPatchSize)) + x1b4_fluidPlane = std::make_unique( + patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap, lightmapId, unitsPerLightmapTexel, tileSize, + tileSubdivisions * 2, fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot, turbSpeed, turbDistance, + turbFreqMax, turbFreqMin, turbPhaseMax, turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin, + specularMax, reflectionBlend, reflectionSize, rippleIntensity, + x2cc_gridCellCount * ((std::max(u32(2), tileSubdivisions * 2) * 4 + 2) * 4)); + else + x1b4_fluidPlane = std::make_unique( + patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap, lightmapId, unitsPerLightmapTexel, tileSize, + tileSubdivisions, fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot, turbSpeed, turbDistance, turbFreqMax, + turbFreqMin, turbPhaseMax, turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin, specularMax, + reflectionBlend, reflectionSize, rippleIntensity, + x2cc_gridCellCount * ((std::max(u32(2), tileSubdivisions) * 4 + 2) * 4)); + u32Arr.reset(); + x264_splashEffects.resize(3); + if (x22c_splashParticle1Id.IsValid()) + x264_splashEffects[0].emplace(g_SimplePool->GetObj({FOURCC('PART'), x22c_splashParticle1Id})); + if (x230_splashParticle2Id.IsValid()) + x264_splashEffects[1].emplace(g_SimplePool->GetObj({FOURCC('PART'), x230_splashParticle2Id})); + if (x234_splashParticle3Id.IsValid()) + x264_splashEffects[2].emplace(g_SimplePool->GetObj({FOURCC('PART'), x234_splashParticle3Id})); + if (x238_visorRunoffParticleId.IsValid()) + x23c_visorRunoffEffect.emplace(g_SimplePool->GetObj({FOURCC('PART'), x238_visorRunoffParticleId})); + if (x24c_unmorphVisorRunoffParticleId.IsValid()) + x250_unmorphVisorRunoffEffect.emplace(g_SimplePool->GetObj({FOURCC('PART'), x24c_unmorphVisorRunoffParticleId})); + x298_splashSounds.push_back(CSfxManager::TranslateSFXID(splashSfx1)); + x298_splashSounds.push_back(CSfxManager::TranslateSFXID(splashSfx2)); + x298_splashSounds.push_back(CSfxManager::TranslateSFXID(splashSfx3)); + SetCalculateLighting(true); + if (lightmapId.IsValid()) + x90_actorLights->DisableAreaLights(); + x90_actorLights->SetMaxDynamicLights(4); + x90_actorLights->SetCastShadows(false); + x90_actorLights->SetAmbienceGenerated(false); + x90_actorLights->SetFindNearestDynamicLights(true); + x148_24_detectCamera = true; + CalculateRenderBounds(); + xe6_27_thermalVisorFlags = u8(thermalCold ? 2 : 1); + if (!x30_24_active) { + x2bc_alpha = 0.f; + x214_fogBias = 0.f; + x218_fogMagnitude = 0.f; + } + SetupGrid(true); } -void CScriptWater::SetupGrid(bool recomputeClipping) -{ - zeus::CAABox triggerAABB = GetTriggerBoundsWR(); - auto dimX = u32((triggerAABB.max.x() - triggerAABB.min.x() + x2c0_tileSize) / x2c0_tileSize); - auto dimY = u32((triggerAABB.max.y() - triggerAABB.min.y() + x2c0_tileSize) / x2c0_tileSize); - x2e4_computedGridCellCount = x2cc_gridCellCount = (dimX + 1) * (dimY + 1); - x2dc_vertIntersects.reset(); - if (!x2d8_tileIntersects || dimX != x2c4_gridDimX || dimY != x2c8_gridDimY) - x2d8_tileIntersects.reset(new bool[x2cc_gridCellCount]); - x2c4_gridDimX = dimX; - x2c8_gridDimY = dimY; - for (int i=0 ; i= x2cc_gridCellCount) - return; - - if (!x2dc_vertIntersects) - x2dc_vertIntersects.reset(new bool[(x2c4_gridDimX + 1) * (x2c8_gridDimY + 1)]); - zeus::CAABox triggerBounds = GetTriggerBoundsWR(); - zeus::CVector3f basePos = triggerBounds.min; - basePos.z() = triggerBounds.max.z() + 0.8f; - auto gridDiv = std::div(x2e4_computedGridCellCount, x2c4_gridDimX + 1); - float yOffset = x2c0_tileSize * gridDiv.quot; - float xOffset = x2c0_tileSize * gridDiv.rem; - float mag = std::min(120.f, 2.f * (x130_bounds.max.z() - x130_bounds.min.z()) + 0.8f); - for (int i = x2e4_computedGridCellCount; - i < std::min(x2e4_computedGridCellCount + computeVerts, x2cc_gridCellCount); ++i) - { - zeus::CVector3f pos = basePos; - pos.x() += xOffset; - pos.y() += yOffset; - x2dc_vertIntersects[i] = mgr.RayStaticIntersection(pos, zeus::CVector3f::skDown, mag, SolidFilter).IsValid(); - gridDiv.rem += 1; - xOffset += x2c0_tileSize; - if (gridDiv.rem > x2c4_gridDimX) - { - yOffset += x2c0_tileSize; - xOffset = 0.f; - gridDiv.rem = 0; - } - } - x2e4_computedGridCellCount += computeVerts; - if (x2e4_computedGridCellCount < x2cc_gridCellCount) - return; - - x2e4_computedGridCellCount = x2cc_gridCellCount; - x2d8_tileIntersects.reset(new bool[x2cc_gridCellCount]); - - for (int i = 0; i < x2c8_gridDimY; ++i) - { - int rowBase = x2c4_gridDimX * i; - int nextRowBase = (x2c4_gridDimX + 1) * i; - for (int j = 0; j < x2c4_gridDimX; ++j) - { - x2d8_tileIntersects[rowBase + j] = - x2dc_vertIntersects[nextRowBase + j] || - x2dc_vertIntersects[nextRowBase + j + 1] || - x2dc_vertIntersects[nextRowBase + j + x2c4_gridDimX + 1] || - x2dc_vertIntersects[nextRowBase + j + x2c4_gridDimX + 2]; - } - } - - int tilesPerPatch = std::min(42 / x1b4_fluidPlane->GetTileSubdivisions(), 7); - x2d0_patchDimX = (tilesPerPatch + x2c4_gridDimX - 1) / tilesPerPatch; - x2d4_patchDimY = (tilesPerPatch + x2c8_gridDimY - 1) / tilesPerPatch; - x2e0_patchIntersects.reset(new u8[x2d0_patchDimX * x2d4_patchDimY]); - int curTileY = 0; - int nextTileY; - for (int i=0 ; i= x2cc_gridCellCount) + return; + + if (!x2dc_vertIntersects) + x2dc_vertIntersects.reset(new bool[(x2c4_gridDimX + 1) * (x2c8_gridDimY + 1)]); + zeus::CAABox triggerBounds = GetTriggerBoundsWR(); + zeus::CVector3f basePos = triggerBounds.min; + basePos.z() = triggerBounds.max.z() + 0.8f; + auto gridDiv = std::div(x2e4_computedGridCellCount, x2c4_gridDimX + 1); + float yOffset = x2c0_tileSize * gridDiv.quot; + float xOffset = x2c0_tileSize * gridDiv.rem; + float mag = std::min(120.f, 2.f * (x130_bounds.max.z() - x130_bounds.min.z()) + 0.8f); + for (int i = x2e4_computedGridCellCount; i < std::min(x2e4_computedGridCellCount + computeVerts, x2cc_gridCellCount); + ++i) { + zeus::CVector3f pos = basePos; + pos.x() += xOffset; + pos.y() += yOffset; + x2dc_vertIntersects[i] = mgr.RayStaticIntersection(pos, zeus::CVector3f::skDown, mag, SolidFilter).IsValid(); + gridDiv.rem += 1; + xOffset += x2c0_tileSize; + if (gridDiv.rem > x2c4_gridDimX) { + yOffset += x2c0_tileSize; + xOffset = 0.f; + gridDiv.rem = 0; + } + } + x2e4_computedGridCellCount += computeVerts; + if (x2e4_computedGridCellCount < x2cc_gridCellCount) + return; + + x2e4_computedGridCellCount = x2cc_gridCellCount; + x2d8_tileIntersects.reset(new bool[x2cc_gridCellCount]); + + for (int i = 0; i < x2c8_gridDimY; ++i) { + int rowBase = x2c4_gridDimX * i; + int nextRowBase = (x2c4_gridDimX + 1) * i; + for (int j = 0; j < x2c4_gridDimX; ++j) { + x2d8_tileIntersects[rowBase + j] = x2dc_vertIntersects[nextRowBase + j] || + x2dc_vertIntersects[nextRowBase + j + 1] || + x2dc_vertIntersects[nextRowBase + j + x2c4_gridDimX + 1] || + x2dc_vertIntersects[nextRowBase + j + x2c4_gridDimX + 2]; + } + } + + int tilesPerPatch = std::min(42 / x1b4_fluidPlane->GetTileSubdivisions(), 7); + x2d0_patchDimX = (tilesPerPatch + x2c4_gridDimX - 1) / tilesPerPatch; + x2d4_patchDimY = (tilesPerPatch + x2c8_gridDimY - 1) / tilesPerPatch; + x2e0_patchIntersects.reset(new u8[x2d0_patchDimX * x2d4_patchDimY]); + int curTileY = 0; + int nextTileY; + for (int i = 0; i < x2d4_patchDimY; ++i, curTileY = nextTileY) { + nextTileY = curTileY + tilesPerPatch; + int curTileX = 0; + int rowBase = x2d0_patchDimX * i; + for (int j = 0; j < x2d0_patchDimX; ++j) { + int nextTileX = curTileX + tilesPerPatch; + bool allClear = true; + bool allIntersections = true; + for (int k = curTileY; k < std::min(nextTileY, x2c8_gridDimY); ++k) { + if (!allClear && !allIntersections) + break; + for (int l = curTileX; l < std::min(nextTileX, x2c4_gridDimX); ++l) { + if (x2d8_tileIntersects[k * x2c4_gridDimX + l]) { + allClear = false; + if (!allIntersections) + break; + } else { + allIntersections = false; + if (!allClear) + break; + } + } + } + + u8 flag; + if (allIntersections) + flag = 1; + else if (allClear) + flag = 0; + else + flag = 2; + x2e0_patchIntersects[rowBase + j] = flag; + curTileX += tilesPerPatch; + } + } + + x2dc_vertIntersects.reset(); } -void CScriptWater::UpdateSplashInhabitants(CStateManager& mgr) -{ - for (auto it = x1fc_waterInhabitants.begin() ; it != x1fc_waterInhabitants.end() ;) - { - auto& inhab = *it; - TCastToPtr act = mgr.ObjectById(inhab.first); - bool intersects = false; - if (act) - { - if (auto tb = act->GetTouchBounds()) - { - zeus::CAABox thisTb = GetTriggerBoundsWR(); - if (tb->min.z() <= thisTb.max.z() && tb->max.z() >= thisTb.max.z()) - intersects = true; - } - } - - if (act && inhab.second) - { - if (intersects) - act->FluidFXThink(EFluidState::InFluid, *this, mgr); - mgr.SendScriptMsg(act.GetPtr(), GetUniqueId(), EScriptObjectMessage::UpdateSplashInhabitant); - inhab.second = false; - } - else - { - it = x1fc_waterInhabitants.erase(it); - if (act) - { - if (intersects) - act->FluidFXThink(EFluidState::LeftFluid, *this, mgr); - mgr.SendScriptMsg(act.GetPtr(), GetUniqueId(), EScriptObjectMessage::RemoveSplashInhabitant); - } - continue; - } - ++it; +void CScriptWater::UpdateSplashInhabitants(CStateManager& mgr) { + for (auto it = x1fc_waterInhabitants.begin(); it != x1fc_waterInhabitants.end();) { + auto& inhab = *it; + TCastToPtr act = mgr.ObjectById(inhab.first); + bool intersects = false; + if (act) { + if (auto tb = act->GetTouchBounds()) { + zeus::CAABox thisTb = GetTriggerBoundsWR(); + if (tb->min.z() <= thisTb.max.z() && tb->max.z() >= thisTb.max.z()) + intersects = true; + } } + + if (act && inhab.second) { + if (intersects) + act->FluidFXThink(EFluidState::InFluid, *this, mgr); + mgr.SendScriptMsg(act.GetPtr(), GetUniqueId(), EScriptObjectMessage::UpdateSplashInhabitant); + inhab.second = false; + } else { + it = x1fc_waterInhabitants.erase(it); + if (act) { + if (intersects) + act->FluidFXThink(EFluidState::LeftFluid, *this, mgr); + mgr.SendScriptMsg(act.GetPtr(), GetUniqueId(), EScriptObjectMessage::RemoveSplashInhabitant); + } + continue; + } + ++it; + } } -void CScriptWater::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptWater::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptWater::Think(float dt, CStateManager& mgr) -{ - if (!x30_24_active) - return; +void CScriptWater::Think(float dt, CStateManager& mgr) { + if (!x30_24_active) + return; - bool oldCamSubmerged = x148_25_camSubmerged; - CScriptTrigger::Think(dt, mgr); + bool oldCamSubmerged = x148_25_camSubmerged; + CScriptTrigger::Think(dt, mgr); - CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); - if (x148_25_camSubmerged && !oldCamSubmerged) - mgr.SendScriptMsg(curCam, x8_uid, EScriptObjectMessage::AddSplashInhabitant); - else if (!x148_25_camSubmerged && oldCamSubmerged) - mgr.SendScriptMsg(curCam, x8_uid, EScriptObjectMessage::RemoveSplashInhabitant); + CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr); + if (x148_25_camSubmerged && !oldCamSubmerged) + mgr.SendScriptMsg(curCam, x8_uid, EScriptObjectMessage::AddSplashInhabitant); + else if (!x148_25_camSubmerged && oldCamSubmerged) + mgr.SendScriptMsg(curCam, x8_uid, EScriptObjectMessage::RemoveSplashInhabitant); - UpdateSplashInhabitants(mgr); + UpdateSplashInhabitants(mgr); - if (x2e8_30_alphaOut) - { - x2bc_alpha -= x2b8_alphaOutRecip * dt * x1b4_fluidPlane->GetAlpha(); - x214_fogBias -= x2b8_alphaOutRecip * dt * x21c_origFogBias; - x218_fogMagnitude -= x2b8_alphaOutRecip * dt * x220_origFogMagnitude; - if (x2bc_alpha <= 0.f) - { - x218_fogMagnitude = 0.f; - x214_fogBias = 0.f; - x2bc_alpha = 0.f; - x2e8_30_alphaOut = false; - } + if (x2e8_30_alphaOut) { + x2bc_alpha -= x2b8_alphaOutRecip * dt * x1b4_fluidPlane->GetAlpha(); + x214_fogBias -= x2b8_alphaOutRecip * dt * x21c_origFogBias; + x218_fogMagnitude -= x2b8_alphaOutRecip * dt * x220_origFogMagnitude; + if (x2bc_alpha <= 0.f) { + x218_fogMagnitude = 0.f; + x214_fogBias = 0.f; + x2bc_alpha = 0.f; + x2e8_30_alphaOut = false; } - else if (x2e8_29_alphaIn) - { - x2bc_alpha += x2b4_alphaInRecip * dt * x1b4_fluidPlane->GetAlpha(); - x214_fogBias -= x2b4_alphaInRecip * dt * x21c_origFogBias; - x218_fogMagnitude -= x2b4_alphaInRecip * dt * x220_origFogMagnitude; - if (x2bc_alpha > x1b4_fluidPlane->GetAlpha()) - { - x2bc_alpha = x1b4_fluidPlane->GetAlpha(); - x214_fogBias = x21c_origFogBias; - x218_fogMagnitude = x220_origFogMagnitude; - x2e8_29_alphaIn = false; - } + } else if (x2e8_29_alphaIn) { + x2bc_alpha += x2b4_alphaInRecip * dt * x1b4_fluidPlane->GetAlpha(); + x214_fogBias -= x2b4_alphaInRecip * dt * x21c_origFogBias; + x218_fogMagnitude -= x2b4_alphaInRecip * dt * x220_origFogMagnitude; + if (x2bc_alpha > x1b4_fluidPlane->GetAlpha()) { + x2bc_alpha = x1b4_fluidPlane->GetAlpha(); + x214_fogBias = x21c_origFogBias; + x218_fogMagnitude = x220_origFogMagnitude; + x2e8_29_alphaIn = false; + } + } + + if (x2e8_26_morphing) { + bool stillMorphing = true; + if (x2e8_25_morphIn) { + x1f8_morphFactor += dt / x1d0_morphInTime; + if (x1f8_morphFactor > 1.f) { + x1f8_morphFactor = 1.f; + stillMorphing = false; + } + } else { + x1f8_morphFactor -= dt / x1f4_morphOutTime; + if (x1f8_morphFactor < 0.f) { + x1f8_morphFactor = 0.f; + stillMorphing = false; + } } - if (x2e8_26_morphing) - { - bool stillMorphing = true; - if (x2e8_25_morphIn) - { - x1f8_morphFactor += dt / x1d0_morphInTime; - if (x1f8_morphFactor > 1.f) - { - x1f8_morphFactor = 1.f; - stillMorphing = false; - } - } - else - { - x1f8_morphFactor -= dt / x1f4_morphOutTime; - if (x1f8_morphFactor < 0.f) - { - x1f8_morphFactor = 0.f; - stillMorphing = false; - } - } + SetTranslation(zeus::CVector3f::lerp(x1d4_positionOrig, x1b8_positionMorphed, x1f8_morphFactor)); + zeus::CVector3f lerpExtent = zeus::CVector3f::lerp(x1e0_extentOrig, x1c4_extentMorphed, x1f8_morphFactor); + x130_bounds = zeus::CAABox(lerpExtent * -0.5f, lerpExtent * 0.5f); + CalculateRenderBounds(); - SetTranslation(zeus::CVector3f::lerp(x1d4_positionOrig, x1b8_positionMorphed, x1f8_morphFactor)); - zeus::CVector3f lerpExtent = zeus::CVector3f::lerp(x1e0_extentOrig, x1c4_extentMorphed, x1f8_morphFactor); - x130_bounds = zeus::CAABox(lerpExtent * -0.5f, lerpExtent * 0.5f); - CalculateRenderBounds(); - - if (!stillMorphing) - SetMorphing(false); - else - SetupGrid(false); - } - - SetupGridClipping(mgr, 4); -} - -void CScriptWater::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) -{ - switch (msg) - { - case EScriptObjectMessage::Next: - if (!x30_24_active) - break; - x2e8_25_morphIn = !x2e8_25_morphIn; - if (x2e8_25_morphIn) - { - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play || - conn.x4_msg != EScriptObjectMessage::Activate) - continue; - auto list = mgr.GetIdListForScript(conn.x8_objId); - if (list.first == mgr.GetIdListEnd()) - continue; - if (TCastToConstPtr trig = mgr.GetObjectById(list.first->second)) - { - x1b8_positionMorphed = trig->GetTranslation(); - x1c4_extentMorphed = trig->GetTriggerBoundsOR().max - trig->GetTriggerBoundsOR().min; - x1f0_damageMorphed = trig->GetDamageInfo().GetDamage(); - x1d4_positionOrig = GetTranslation(); - x1e0_extentOrig = x130_bounds.max - x130_bounds.min; - x1ec_damageOrig = x100_damageInfo.GetDamage(); - break; - } - } - } - SetMorphing(true); - break; - case EScriptObjectMessage::Activate: - x2e8_30_alphaOut = false; - if (std::fabs(x2ac_alphaInTime) < 0.00001f) - { - x2bc_alpha = x1b4_fluidPlane->GetAlpha(); - x214_fogBias = x21c_origFogBias; - x218_fogMagnitude = x220_origFogMagnitude; - } - else - { - x2e8_29_alphaIn = true; - } - break; - case EScriptObjectMessage::Action: - x2e8_29_alphaIn = false; - if (std::fabs(x2b0_alphaOutTime) < 0.00001f) - { - x2bc_alpha = 0.f; - x214_fogBias = 0.f; - x218_fogMagnitude = 0.f; - } - else - { - x2e8_30_alphaOut = true; - } - break; - default: - break; - } - - CScriptTrigger::AcceptScriptMsg(msg, other, mgr); -} - -void CScriptWater::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) -{ - if (x2e8_27_allowRender) - { - zeus::CAABox aabb = GetSortingBounds(mgr); - xe4_30_outOfFrustum = !frustum.aabbFrustumTest(aabb); - if (!xe4_30_outOfFrustum) - { - if (x4_areaId != kInvalidAreaId) - { - if (x90_actorLights->GetMaxAreaLights() && - (xe4_29_actorLightsDirty || x90_actorLights->GetIsDirty())) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); - if (area->IsPostConstructed()) - { - x90_actorLights->BuildAreaLightList(mgr, *area, GetTriggerBoundsWR()); - xe4_29_actorLightsDirty = false; - } - } - x90_actorLights->BuildDynamicLightList(mgr, GetTriggerBoundsWR()); - } - x150_frustum = frustum; - } - } + if (!stillMorphing) + SetMorphing(false); else - { - xe4_30_outOfFrustum = true; - } + SetupGrid(false); + } + + SetupGridClipping(mgr, 4); } -void CScriptWater::AddToRenderer(const zeus::CFrustum& /*frustum*/, const CStateManager& mgr) const -{ - if (!xe4_30_outOfFrustum) - { - zeus::CPlane plane(zeus::CVector3f::skUp, x34_transform.origin.z() + x130_bounds.max.z()); - zeus::CAABox renderBounds = GetSortingBounds(mgr); - mgr.AddDrawableActorPlane(*this, plane, renderBounds); - } -} - -void CScriptWater::Render(const CStateManager& mgr) const -{ - if (x30_24_active && !xe4_30_outOfFrustum) - { - float zOffset = 0.5f * (x9c_renderBounds.max.z() + x9c_renderBounds.min.z()) - x34_transform.origin.z(); - zeus::CAABox aabb = x9c_renderBounds.getTransformedAABox( - zeus::CTransform::Translate(-x34_transform.origin.x(), -x34_transform.origin.y(), - -x34_transform.origin.z() - zOffset)); - zeus::CTransform xf = x34_transform; - xf.origin.z() += zOffset; - zeus::CVector3f areaCenter = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId())->GetAABB().center(); - std::experimental::optional rippleMan(mgr.GetFluidPlaneManager()->GetRippleManager()); - x1b4_fluidPlane->Render(mgr, x2bc_alpha, aabb, xf, - mgr.GetWorld()->GetAreaAlways(x4_areaId)->GetTransform(), false, - x150_frustum, rippleMan, x8_uid, x2d8_tileIntersects.get(), - x2c4_gridDimX, x2c8_gridDimY, areaCenter); - if (x214_fogBias != 0.f) - { - if (mgr.GetPlayerState()->CanVisorSeeFog(mgr)) - { - float fogLevel = mgr.IntegrateVisorFog(x218_fogMagnitude * - std::sin(x224_fogSpeed * CGraphics::GetSecondsMod900()) + - x214_fogBias); - if (fogLevel > 0.f) - { - zeus::CAABox fogBox = GetTriggerBoundsWR(); - fogBox.min.z() = float(fogBox.max.z()); - fogBox.max.z() += fogLevel; - zeus::CTransform modelXf = zeus::CTransform::Translate(fogBox.center()) * - zeus::CTransform::Scale((fogBox.max - fogBox.min) * 0.5f); - zeus::CAABox renderAABB(zeus::CVector3f::skNegOne, zeus::CVector3f::skOne); - CGraphics::SetModelMatrix(modelXf); - g_Renderer->SetAmbientColor(zeus::CColor::skWhite); - g_Renderer->RenderFogVolume(x228_fogColor, renderAABB, nullptr, nullptr); - } - } - } - CGraphics::DisableAllLights(); - } - CActor::Render(mgr); -} - -void CScriptWater::Touch(CActor& otherAct, CStateManager& mgr) -{ +void CScriptWater::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) { + switch (msg) { + case EScriptObjectMessage::Next: if (!x30_24_active) - return; - - CScriptTrigger::Touch(otherAct, mgr); - if (otherAct.GetMaterialList().HasMaterial(EMaterialTypes::Trigger)) - return; - - for (auto& inhab : x1fc_waterInhabitants) - if (inhab.first == otherAct.GetUniqueId()) - { - inhab.second = true; - return; + break; + x2e8_25_morphIn = !x2e8_25_morphIn; + if (x2e8_25_morphIn) { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) + continue; + auto list = mgr.GetIdListForScript(conn.x8_objId); + if (list.first == mgr.GetIdListEnd()) + continue; + if (TCastToConstPtr trig = mgr.GetObjectById(list.first->second)) { + x1b8_positionMorphed = trig->GetTranslation(); + x1c4_extentMorphed = trig->GetTriggerBoundsOR().max - trig->GetTriggerBoundsOR().min; + x1f0_damageMorphed = trig->GetDamageInfo().GetDamage(); + x1d4_positionOrig = GetTranslation(); + x1e0_extentOrig = x130_bounds.max - x130_bounds.min; + x1ec_damageOrig = x100_damageInfo.GetDamage(); + break; } + } + } + SetMorphing(true); + break; + case EScriptObjectMessage::Activate: + x2e8_30_alphaOut = false; + if (std::fabs(x2ac_alphaInTime) < 0.00001f) { + x2bc_alpha = x1b4_fluidPlane->GetAlpha(); + x214_fogBias = x21c_origFogBias; + x218_fogMagnitude = x220_origFogMagnitude; + } else { + x2e8_29_alphaIn = true; + } + break; + case EScriptObjectMessage::Action: + x2e8_29_alphaIn = false; + if (std::fabs(x2b0_alphaOutTime) < 0.00001f) { + x2bc_alpha = 0.f; + x214_fogBias = 0.f; + x218_fogMagnitude = 0.f; + } else { + x2e8_30_alphaOut = true; + } + break; + default: + break; + } - auto touchBounds = otherAct.GetTouchBounds(); - if (!touchBounds) - return; - - x1fc_waterInhabitants.emplace_back(otherAct.GetUniqueId(), true); - float triggerMaxZ = GetTriggerBoundsWR().max.z(); - if (touchBounds->min.z() <= triggerMaxZ && touchBounds->max.z() >= triggerMaxZ) - otherAct.FluidFXThink(EFluidState::EnteredFluid, *this, mgr); - - mgr.SendScriptMsg(&otherAct, x8_uid, EScriptObjectMessage::AddSplashInhabitant); + CScriptTrigger::AcceptScriptMsg(msg, other, mgr); } -void CScriptWater::CalculateRenderBounds() -{ - zeus::CVector3f aabbMin = x130_bounds.min; - aabbMin.z() = x130_bounds.max.z() - 1.f; - zeus::CVector3f aabbMax = x130_bounds.max; - aabbMax.z() += 1.f; - zeus::CVector3f transAABBMin = aabbMin + GetTranslation(); - zeus::CVector3f transAABBMax = aabbMax + GetTranslation(); - x9c_renderBounds = zeus::CAABox(transAABBMin, transAABBMax); +void CScriptWater::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { + if (x2e8_27_allowRender) { + zeus::CAABox aabb = GetSortingBounds(mgr); + xe4_30_outOfFrustum = !frustum.aabbFrustumTest(aabb); + if (!xe4_30_outOfFrustum) { + if (x4_areaId != kInvalidAreaId) { + if (x90_actorLights->GetMaxAreaLights() && (xe4_29_actorLightsDirty || x90_actorLights->GetIsDirty())) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); + if (area->IsPostConstructed()) { + x90_actorLights->BuildAreaLightList(mgr, *area, GetTriggerBoundsWR()); + xe4_29_actorLightsDirty = false; + } + } + x90_actorLights->BuildDynamicLightList(mgr, GetTriggerBoundsWR()); + } + x150_frustum = frustum; + } + } else { + xe4_30_outOfFrustum = true; + } } -zeus::CAABox CScriptWater::GetSortingBounds(const CStateManager& mgr) const -{ - zeus::CVector3f max = x9c_renderBounds.max; - max.z() = std::max(float(max.z()), x9c_renderBounds.max.z() - 1.f + x214_fogBias + x218_fogMagnitude); - return {x9c_renderBounds.min, max}; +void CScriptWater::AddToRenderer(const zeus::CFrustum& /*frustum*/, const CStateManager& mgr) const { + if (!xe4_30_outOfFrustum) { + zeus::CPlane plane(zeus::CVector3f::skUp, x34_transform.origin.z() + x130_bounds.max.z()); + zeus::CAABox renderBounds = GetSortingBounds(mgr); + mgr.AddDrawableActorPlane(*this, plane, renderBounds); + } +} + +void CScriptWater::Render(const CStateManager& mgr) const { + if (x30_24_active && !xe4_30_outOfFrustum) { + float zOffset = 0.5f * (x9c_renderBounds.max.z() + x9c_renderBounds.min.z()) - x34_transform.origin.z(); + zeus::CAABox aabb = x9c_renderBounds.getTransformedAABox(zeus::CTransform::Translate( + -x34_transform.origin.x(), -x34_transform.origin.y(), -x34_transform.origin.z() - zOffset)); + zeus::CTransform xf = x34_transform; + xf.origin.z() += zOffset; + zeus::CVector3f areaCenter = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId())->GetAABB().center(); + std::experimental::optional rippleMan(mgr.GetFluidPlaneManager()->GetRippleManager()); + x1b4_fluidPlane->Render(mgr, x2bc_alpha, aabb, xf, mgr.GetWorld()->GetAreaAlways(x4_areaId)->GetTransform(), false, + x150_frustum, rippleMan, x8_uid, x2d8_tileIntersects.get(), x2c4_gridDimX, x2c8_gridDimY, + areaCenter); + if (x214_fogBias != 0.f) { + if (mgr.GetPlayerState()->CanVisorSeeFog(mgr)) { + float fogLevel = mgr.IntegrateVisorFog( + x218_fogMagnitude * std::sin(x224_fogSpeed * CGraphics::GetSecondsMod900()) + x214_fogBias); + if (fogLevel > 0.f) { + zeus::CAABox fogBox = GetTriggerBoundsWR(); + fogBox.min.z() = float(fogBox.max.z()); + fogBox.max.z() += fogLevel; + zeus::CTransform modelXf = + zeus::CTransform::Translate(fogBox.center()) * zeus::CTransform::Scale((fogBox.max - fogBox.min) * 0.5f); + zeus::CAABox renderAABB(zeus::CVector3f::skNegOne, zeus::CVector3f::skOne); + CGraphics::SetModelMatrix(modelXf); + g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + g_Renderer->RenderFogVolume(x228_fogColor, renderAABB, nullptr, nullptr); + } + } + } + CGraphics::DisableAllLights(); + } + CActor::Render(mgr); +} + +void CScriptWater::Touch(CActor& otherAct, CStateManager& mgr) { + if (!x30_24_active) + return; + + CScriptTrigger::Touch(otherAct, mgr); + if (otherAct.GetMaterialList().HasMaterial(EMaterialTypes::Trigger)) + return; + + for (auto& inhab : x1fc_waterInhabitants) + if (inhab.first == otherAct.GetUniqueId()) { + inhab.second = true; + return; + } + + auto touchBounds = otherAct.GetTouchBounds(); + if (!touchBounds) + return; + + x1fc_waterInhabitants.emplace_back(otherAct.GetUniqueId(), true); + float triggerMaxZ = GetTriggerBoundsWR().max.z(); + if (touchBounds->min.z() <= triggerMaxZ && touchBounds->max.z() >= triggerMaxZ) + otherAct.FluidFXThink(EFluidState::EnteredFluid, *this, mgr); + + mgr.SendScriptMsg(&otherAct, x8_uid, EScriptObjectMessage::AddSplashInhabitant); +} + +void CScriptWater::CalculateRenderBounds() { + zeus::CVector3f aabbMin = x130_bounds.min; + aabbMin.z() = x130_bounds.max.z() - 1.f; + zeus::CVector3f aabbMax = x130_bounds.max; + aabbMax.z() += 1.f; + zeus::CVector3f transAABBMin = aabbMin + GetTranslation(); + zeus::CVector3f transAABBMax = aabbMax + GetTranslation(); + x9c_renderBounds = zeus::CAABox(transAABBMin, transAABBMax); +} + +zeus::CAABox CScriptWater::GetSortingBounds(const CStateManager& mgr) const { + zeus::CVector3f max = x9c_renderBounds.max; + max.z() = std::max(float(max.z()), x9c_renderBounds.max.z() - 1.f + x214_fogBias + x218_fogMagnitude); + return {x9c_renderBounds.min, max}; } EWeaponCollisionResponseTypes CScriptWater::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const -{ - return EWeaponCollisionResponseTypes::Water; + const CWeaponMode&, EProjectileAttrib) const { + return EWeaponCollisionResponseTypes::Water; } -u16 CScriptWater::GetSplashSound(float mag) const -{ - return x298_splashSounds[GetSplashIndex(mag)]; +u16 CScriptWater::GetSplashSound(float mag) const { return x298_splashSounds[GetSplashIndex(mag)]; } + +const std::experimental::optional>& CScriptWater::GetSplashEffect(float mag) const { + return x264_splashEffects[GetSplashIndex(mag)]; } -const std::experimental::optional>& CScriptWater::GetSplashEffect(float mag) const -{ - return x264_splashEffects[GetSplashIndex(mag)]; +float CScriptWater::GetSplashEffectScale(float dt) const { + if (std::fabs(dt - 1.f) < 0.00001f) + return kSplashScales[5]; + + u32 idx = GetSplashIndex(dt); + float s = dt - std::floor(dt * 3.f); + return ((1.f - s) * (s * kSplashScales[idx * 2])) + kSplashScales[idx]; } -float CScriptWater::GetSplashEffectScale(float dt) const -{ - if (std::fabs(dt - 1.f) < 0.00001f) - return kSplashScales[5]; - - u32 idx = GetSplashIndex(dt); - float s = dt - std::floor(dt * 3.f); - return ((1.f - s) * (s * kSplashScales[idx * 2])) + kSplashScales[idx]; +u32 CScriptWater::GetSplashIndex(float mag) const { + auto idx = u32(mag * 3.f); + return (idx < 3 ? idx : idx - 1); } -u32 CScriptWater::GetSplashIndex(float mag) const -{ - auto idx = u32(mag * 3.f); - return (idx < 3 ? idx : idx - 1); +void CScriptWater::SetMorphing(bool m) { + if (m == x2e8_26_morphing) + return; + x2e8_26_morphing = m; + SetupGrid(!m); } -void CScriptWater::SetMorphing(bool m) -{ - if (m == x2e8_26_morphing) - return; - x2e8_26_morphing = m; - SetupGrid(!m); +const CScriptWater* CScriptWater::GetNextConnectedWater(const CStateManager& mgr) const { + for (const SConnection& conn : x20_conns) { + if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) + continue; + auto its = mgr.GetIdListForScript(conn.x8_objId); + if (its.first != mgr.GetIdListEnd()) + if (TCastToConstPtr water = mgr.GetObjectById(its.first->second)) + return water.GetPtr(); + } + return nullptr; } -const CScriptWater* CScriptWater::GetNextConnectedWater(const CStateManager& mgr) const -{ - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate) - continue; - auto its = mgr.GetIdListForScript(conn.x8_objId); - if (its.first != mgr.GetIdListEnd()) - if (TCastToConstPtr water = mgr.GetObjectById(its.first->second)) - return water.GetPtr(); - } - return nullptr; -} - -bool CScriptWater::CanRippleAtPoint(const zeus::CVector3f& point) const -{ - if (!x2d8_tileIntersects) - return true; - - auto xTile = int((point.x() - GetTriggerBoundsWR().min.x()) / x2c0_tileSize); - if (xTile < 0 || xTile >= x2c4_gridDimX) - return false; - - auto yTile = int((point.y() - GetTriggerBoundsWR().min.y()) / x2c0_tileSize); - if (yTile < 0 || yTile >= x2c8_gridDimY) - return false; - - return x2d8_tileIntersects[yTile * x2c4_gridDimX + xTile]; -} +bool CScriptWater::CanRippleAtPoint(const zeus::CVector3f& point) const { + if (!x2d8_tileIntersects) + return true; + + auto xTile = int((point.x() - GetTriggerBoundsWR().min.x()) / x2c0_tileSize); + if (xTile < 0 || xTile >= x2c4_gridDimX) + return false; + + auto yTile = int((point.y() - GetTriggerBoundsWR().min.y()) / x2c0_tileSize); + if (yTile < 0 || yTile >= x2c8_gridDimY) + return false; + + return x2d8_tileIntersects[yTile * x2c4_gridDimX + xTile]; } +} // namespace urde diff --git a/Runtime/World/CScriptWater.hpp b/Runtime/World/CScriptWater.hpp index 7f5b58705..ca3c1c1fd 100644 --- a/Runtime/World/CScriptWater.hpp +++ b/Runtime/World/CScriptWater.hpp @@ -2,136 +2,132 @@ #include "CScriptTrigger.hpp" #include "CFluidPlaneCPU.hpp" -namespace urde -{ +namespace urde { class CDamageInfo; class CFluidUVMotion; -class CScriptWater : public CScriptTrigger -{ -private: - static const float kSplashScales[6]; - zeus::CFrustum x150_frustum; - std::unique_ptr x1b4_fluidPlane; - zeus::CVector3f x1b8_positionMorphed; - zeus::CVector3f x1c4_extentMorphed; - float x1d0_morphInTime; - zeus::CVector3f x1d4_positionOrig; - zeus::CVector3f x1e0_extentOrig; - float x1ec_damageOrig; - float x1f0_damageMorphed; - float x1f4_morphOutTime; - float x1f8_morphFactor = 0.f; - std::list> x1fc_waterInhabitants; - float x214_fogBias; - float x218_fogMagnitude; - float x21c_origFogBias; - float x220_origFogMagnitude; - float x224_fogSpeed; - zeus::CColor x228_fogColor; - CAssetId x22c_splashParticle1Id; - CAssetId x230_splashParticle2Id; - CAssetId x234_splashParticle3Id; - CAssetId x238_visorRunoffParticleId; - std::experimental::optional> x23c_visorRunoffEffect; - CAssetId x24c_unmorphVisorRunoffParticleId; - std::experimental::optional> x250_unmorphVisorRunoffEffect; - u16 x260_visorRunoffSfx; - u16 x262_unmorphVisorRunoffSfx; - rstl::reserved_vector>, 3> x264_splashEffects; - rstl::reserved_vector x298_splashSounds; - zeus::CColor x2a4_splashColor; - zeus::CColor x2a8_insideFogColor; - float x2ac_alphaInTime; - float x2b0_alphaOutTime; - float x2b4_alphaInRecip; - float x2b8_alphaOutRecip; - float x2bc_alpha; - float x2c0_tileSize; - int x2c4_gridDimX = 0; - int x2c8_gridDimY = 0; - int x2cc_gridCellCount = 0; - int x2d0_patchDimX = 0; - int x2d4_patchDimY = 0; - std::unique_ptr x2d8_tileIntersects; - std::unique_ptr x2dc_vertIntersects; - std::unique_ptr x2e0_patchIntersects; // 0: all clear, 1: all intersect, 2: partial intersect - int x2e4_computedGridCellCount = 0; - union - { - struct - { - bool x2e8_24_b4 : 1; - bool x2e8_25_morphIn : 1; - bool x2e8_26_morphing : 1; - bool x2e8_27_allowRender : 1; - bool x2e8_28_recomputeClipping : 1; - bool x2e8_29_alphaIn : 1; - bool x2e8_30_alphaOut : 1; - }; - u32 _dummy = 0; +class CScriptWater : public CScriptTrigger { + static const float kSplashScales[6]; + zeus::CFrustum x150_frustum; + std::unique_ptr x1b4_fluidPlane; + zeus::CVector3f x1b8_positionMorphed; + zeus::CVector3f x1c4_extentMorphed; + float x1d0_morphInTime; + zeus::CVector3f x1d4_positionOrig; + zeus::CVector3f x1e0_extentOrig; + float x1ec_damageOrig; + float x1f0_damageMorphed; + float x1f4_morphOutTime; + float x1f8_morphFactor = 0.f; + std::list> x1fc_waterInhabitants; + float x214_fogBias; + float x218_fogMagnitude; + float x21c_origFogBias; + float x220_origFogMagnitude; + float x224_fogSpeed; + zeus::CColor x228_fogColor; + CAssetId x22c_splashParticle1Id; + CAssetId x230_splashParticle2Id; + CAssetId x234_splashParticle3Id; + CAssetId x238_visorRunoffParticleId; + std::experimental::optional> x23c_visorRunoffEffect; + CAssetId x24c_unmorphVisorRunoffParticleId; + std::experimental::optional> x250_unmorphVisorRunoffEffect; + u16 x260_visorRunoffSfx; + u16 x262_unmorphVisorRunoffSfx; + rstl::reserved_vector>, 3> x264_splashEffects; + rstl::reserved_vector x298_splashSounds; + zeus::CColor x2a4_splashColor; + zeus::CColor x2a8_insideFogColor; + float x2ac_alphaInTime; + float x2b0_alphaOutTime; + float x2b4_alphaInRecip; + float x2b8_alphaOutRecip; + float x2bc_alpha; + float x2c0_tileSize; + int x2c4_gridDimX = 0; + int x2c8_gridDimY = 0; + int x2cc_gridCellCount = 0; + int x2d0_patchDimX = 0; + int x2d4_patchDimY = 0; + std::unique_ptr x2d8_tileIntersects; + std::unique_ptr x2dc_vertIntersects; + std::unique_ptr x2e0_patchIntersects; // 0: all clear, 1: all intersect, 2: partial intersect + int x2e4_computedGridCellCount = 0; + union { + struct { + bool x2e8_24_b4 : 1; + bool x2e8_25_morphIn : 1; + bool x2e8_26_morphing : 1; + bool x2e8_27_allowRender : 1; + bool x2e8_28_recomputeClipping : 1; + bool x2e8_29_alphaIn : 1; + bool x2e8_30_alphaOut : 1; }; - void SetupGrid(bool recomputeClipping); - void SetupGridClipping(CStateManager& mgr, int computeVerts); - void UpdateSplashInhabitants(CStateManager& mgr); + u32 _dummy = 0; + }; + void SetupGrid(bool recomputeClipping); + void SetupGridClipping(CStateManager& mgr, int computeVerts); + void UpdateSplashInhabitants(CStateManager& mgr); + public: - CScriptWater(CStateManager& mgr, TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo, - zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool thermalCold, - bool allowRender, CAssetId patternMap1, CAssetId patternMap2, CAssetId colorMap, - CAssetId bumpMap, CAssetId envMap, CAssetId envBumpMap, CAssetId unusedMap, - const zeus::CVector3f& bumpLightDir, float bumpScale, float morphInTime, float morphOutTime, - bool active, EFluidType fluidType, bool b4, float alpha, - const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax, - float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, - float turbAmplitudeMin, const zeus::CColor& splashColor, const zeus::CColor& insideFogColor, - CAssetId splashParticle1, CAssetId splashParticle2, CAssetId splashParticle3, - CAssetId visorRunoffParticle, CAssetId unmorphVisorRunoffparticle, s32 visorRunoffSfx, - s32 unmorphVisorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize, - u32 tileSubdivisions, float specularMin, float specularMax, float reflectionSize, - float rippleIntensity, float reflectionBlend, float fogBias, float fogMagnitude, float fogSpeed, - const zeus::CColor& fogColor, CAssetId lightmapId, float unitsPerLightmapTexel, float alphaInTime, - float alphaOutTime, u32, u32, bool, s32, s32, std::unique_ptr&& u32Arr); + CScriptWater(CStateManager& mgr, TUniqueId uid, std::string_view name, const CEntityInfo& info, + const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo, + zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool thermalCold, bool allowRender, + CAssetId patternMap1, CAssetId patternMap2, CAssetId colorMap, CAssetId bumpMap, CAssetId envMap, + CAssetId envBumpMap, CAssetId unusedMap, const zeus::CVector3f& bumpLightDir, float bumpScale, + float morphInTime, float morphOutTime, bool active, EFluidType fluidType, bool b4, float alpha, + const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin, + float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin, + const zeus::CColor& splashColor, const zeus::CColor& insideFogColor, CAssetId splashParticle1, + CAssetId splashParticle2, CAssetId splashParticle3, CAssetId visorRunoffParticle, + CAssetId unmorphVisorRunoffparticle, s32 visorRunoffSfx, s32 unmorphVisorRunoffSfx, s32 splashSfx1, + s32 splashSfx2, s32 splashSfx3, float tileSize, u32 tileSubdivisions, float specularMin, + float specularMax, float reflectionSize, float rippleIntensity, float reflectionBlend, float fogBias, + float fogMagnitude, float fogSpeed, const zeus::CColor& fogColor, CAssetId lightmapId, + float unitsPerLightmapTexel, float alphaInTime, float alphaOutTime, u32, u32, bool, s32, s32, + std::unique_ptr&& u32Arr); - void Accept(IVisitor& visitor); - void Think(float, CStateManager&); - void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); - void PreRender(CStateManager &, const zeus::CFrustum &); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - void Render(const CStateManager&) const; - void Touch(CActor &, CStateManager &); - void CalculateRenderBounds(); - zeus::CAABox GetSortingBounds(const CStateManager&) const; - EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, - const CWeaponMode&, EProjectileAttrib) const; + void Accept(IVisitor& visitor); + void Think(float, CStateManager&); + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void PreRender(CStateManager&, const zeus::CFrustum&); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + void Render(const CStateManager&) const; + void Touch(CActor&, CStateManager&); + void CalculateRenderBounds(); + zeus::CAABox GetSortingBounds(const CStateManager&) const; + EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, + const CWeaponMode&, EProjectileAttrib) const; - u16 GetSplashSound(float) const; - const std::experimental::optional>& GetSplashEffect(float) const; - float GetSplashEffectScale(float) const; - u32 GetSplashIndex(float) const; - CFluidPlaneCPU& FluidPlane() { return *x1b4_fluidPlane; } - zeus::CPlane GetWRSurfacePlane() const; - float GetSurfaceZ() const; - bool IsMorphing() const { return x2e8_26_morphing; } - void SetMorphing(bool); - float GetMorphFactor() const { return x1f8_morphFactor; } - zeus::CColor GetSplashColor() const { return x2a4_splashColor; } - void SetFrustumPlanes(const zeus::CFrustum& frustum) { x150_frustum = frustum; } - const zeus::CFrustum& GetFrustumPlanes() const { return x150_frustum; } - CFluidPlaneCPU& GetFluidPlane() const { return *x1b4_fluidPlane; } - const std::experimental::optional>& GetVisorRunoffEffect() const - { return x23c_visorRunoffEffect; } - u16 GetVisorRunoffSfx() const { return x260_visorRunoffSfx; } - const std::experimental::optional>& GetUnmorphVisorRunoffEffect() const - { return x250_unmorphVisorRunoffEffect; } - u16 GetUnmorphVisorRunoffSfx() const { return x262_unmorphVisorRunoffSfx; } - const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const; - u8 GetPatchRenderFlags(int x, int y) const { return x2e0_patchIntersects[y * x2d0_patchDimX + x]; } - int GetPatchDimensionX() const { return x2d0_patchDimX; } - int GetPatchDimensionY() const { return x2d4_patchDimY; } - bool CanRippleAtPoint(const zeus::CVector3f& point) const; - const zeus::CColor& GetInsideFogColor() const { return x2a8_insideFogColor; } + u16 GetSplashSound(float) const; + const std::experimental::optional>& GetSplashEffect(float) const; + float GetSplashEffectScale(float) const; + u32 GetSplashIndex(float) const; + CFluidPlaneCPU& FluidPlane() { return *x1b4_fluidPlane; } + zeus::CPlane GetWRSurfacePlane() const; + float GetSurfaceZ() const; + bool IsMorphing() const { return x2e8_26_morphing; } + void SetMorphing(bool); + float GetMorphFactor() const { return x1f8_morphFactor; } + zeus::CColor GetSplashColor() const { return x2a4_splashColor; } + void SetFrustumPlanes(const zeus::CFrustum& frustum) { x150_frustum = frustum; } + const zeus::CFrustum& GetFrustumPlanes() const { return x150_frustum; } + CFluidPlaneCPU& GetFluidPlane() const { return *x1b4_fluidPlane; } + const std::experimental::optional>& GetVisorRunoffEffect() const { + return x23c_visorRunoffEffect; + } + u16 GetVisorRunoffSfx() const { return x260_visorRunoffSfx; } + const std::experimental::optional>& GetUnmorphVisorRunoffEffect() const { + return x250_unmorphVisorRunoffEffect; + } + u16 GetUnmorphVisorRunoffSfx() const { return x262_unmorphVisorRunoffSfx; } + const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const; + u8 GetPatchRenderFlags(int x, int y) const { return x2e0_patchIntersects[y * x2d0_patchDimX + x]; } + int GetPatchDimensionX() const { return x2d0_patchDimX; } + int GetPatchDimensionY() const { return x2d4_patchDimY; } + bool CanRippleAtPoint(const zeus::CVector3f& point) const; + const zeus::CColor& GetInsideFogColor() const { return x2a8_insideFogColor; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptWaypoint.cpp b/Runtime/World/CScriptWaypoint.cpp index 18d9ec0c4..4dfe69361 100644 --- a/Runtime/World/CScriptWaypoint.cpp +++ b/Runtime/World/CScriptWaypoint.cpp @@ -3,69 +3,62 @@ #include "TCastTo.hpp" #include "CStateManager.hpp" -namespace urde -{ +namespace urde { CScriptWaypoint::CScriptWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, bool active, float speed, float pause, u32 patternTranslate, u32 patternOrient, u32 patternFit, u32 behaviour, u32 behaviourOrient, u32 behaviourModifiers, u32 animation) -: CActor(uid, active, name, info, xf, CModelData(), CMaterialList(), - CActorParameters::None(), kInvalidUniqueId), - xe8_speed(speed), xec_animation(animation), xf0_pause(pause), - xf4_patternTranslate(patternTranslate), xf5_patternOrient(patternOrient), - xf6_patternFit(patternFit), xf7_behaviour(behaviour), - xf8_behaviourOrient(behaviourOrient), xfa_behaviourModifiers(behaviourModifiers) -{ - SetUseInSortedLists(false); - SetCallTouch(false); +: CActor(uid, active, name, info, xf, CModelData(), CMaterialList(), CActorParameters::None(), kInvalidUniqueId) +, xe8_speed(speed) +, xec_animation(animation) +, xf0_pause(pause) +, xf4_patternTranslate(patternTranslate) +, xf5_patternOrient(patternOrient) +, xf6_patternFit(patternFit) +, xf7_behaviour(behaviour) +, xf8_behaviourOrient(behaviourOrient) +, xfa_behaviourModifiers(behaviourModifiers) { + SetUseInSortedLists(false); + SetCallTouch(false); } -void CScriptWaypoint::Accept(IVisitor& visitor) -{ - visitor.Visit(this); +void CScriptWaypoint::Accept(IVisitor& visitor) { visitor.Visit(this); } + +void CScriptWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { + CActor::AcceptScriptMsg(msg, sender, mgr); + if (GetActive()) + if (msg == EScriptObjectMessage::Arrived) + SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); } -void CScriptWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) -{ - CActor::AcceptScriptMsg(msg, sender, mgr); - if (GetActive()) - if (msg == EScriptObjectMessage::Arrived) - SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); +void CScriptWaypoint::AddToRenderer(const zeus::CFrustum&, const CStateManager&) const { + // Empty } -void CScriptWaypoint::AddToRenderer(const zeus::CFrustum&, const CStateManager&) const -{ - // Empty +TUniqueId CScriptWaypoint::FollowWaypoint(CStateManager& mgr) const { + for (const SConnection& conn : x20_conns) + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Follow) + return mgr.GetIdForScript(conn.x8_objId); + return kInvalidUniqueId; } -TUniqueId CScriptWaypoint::FollowWaypoint(CStateManager& mgr) const -{ - for (const SConnection& conn : x20_conns) - if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Follow) - return mgr.GetIdForScript(conn.x8_objId); - return kInvalidUniqueId; -} - -TUniqueId CScriptWaypoint::NextWaypoint(CStateManager& mgr) const -{ - rstl::reserved_vector ids; - for (const SConnection& conn : x20_conns) - { - if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) - { - TUniqueId id = mgr.GetIdForScript(conn.x8_objId); - if (id != kInvalidUniqueId) - if (TCastToConstPtr wp = mgr.GetObjectById(id)) - if (wp->GetActive()) - ids.push_back(wp->GetUniqueId()); - } +TUniqueId CScriptWaypoint::NextWaypoint(CStateManager& mgr) const { + rstl::reserved_vector ids; + for (const SConnection& conn : x20_conns) { + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) { + TUniqueId id = mgr.GetIdForScript(conn.x8_objId); + if (id != kInvalidUniqueId) + if (TCastToConstPtr wp = mgr.GetObjectById(id)) + if (wp->GetActive()) + ids.push_back(wp->GetUniqueId()); } + } - if (ids.size() == 0) - return kInvalidUniqueId; + if (ids.size() == 0) + return kInvalidUniqueId; - return ids[int(mgr.GetActiveRandom()->Float() * ids.size() * 0.99f)]; + return ids[int(mgr.GetActiveRandom()->Float() * ids.size() * 0.99f)]; } -} +} // namespace urde diff --git a/Runtime/World/CScriptWaypoint.hpp b/Runtime/World/CScriptWaypoint.hpp index dbf2e3adb..fa85aada4 100644 --- a/Runtime/World/CScriptWaypoint.hpp +++ b/Runtime/World/CScriptWaypoint.hpp @@ -2,40 +2,37 @@ #include "CActor.hpp" -namespace urde -{ +namespace urde { + +class CScriptWaypoint : public CActor { + float xe8_speed; + u32 xec_animation; + float xf0_pause; + u8 xf4_patternTranslate; + u8 xf5_patternOrient; + u8 xf6_patternFit; + u8 xf7_behaviour; + u8 xf8_behaviourOrient; + u16 xfa_behaviourModifiers; -class CScriptWaypoint : public CActor -{ - float xe8_speed; - u32 xec_animation; - float xf0_pause; - u8 xf4_patternTranslate; - u8 xf5_patternOrient; - u8 xf6_patternFit; - u8 xf7_behaviour; - u8 xf8_behaviourOrient; - u16 xfa_behaviourModifiers; public: - CScriptWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, - const zeus::CTransform& xf, bool active, float speed, float pause, - u32 patternTranslate, u32 patternOrient, u32 patternFit, u32 behaviour, - u32 behaviourOrient, u32 behaviourModifiers, u32 animation); + CScriptWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, + bool active, float speed, float pause, u32 patternTranslate, u32 patternOrient, u32 patternFit, + u32 behaviour, u32 behaviourOrient, u32 behaviourModifiers, u32 animation); - void Accept(IVisitor& visitor); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); - void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; - TUniqueId FollowWaypoint(CStateManager& mgr) const; - TUniqueId NextWaypoint(CStateManager& mgr) const; - float GetSpeed() const { return xe8_speed; } - u32 GetAnimation() const { return xec_animation; } - float GetPause() const { return xf0_pause; } - u8 GetPatternTranslate() const { return xf4_patternTranslate; } - u8 GetPatternOrient() const { return xf5_patternOrient; } - u8 GetPatternFit() const { return xf6_patternFit; } - u8 GetBehaviour() const { return xf7_behaviour; } - u8 GetBehaviourOrient() const { return xf8_behaviourOrient; } - u16 GetBehaviourModifiers() const { return xfa_behaviourModifiers; } + void Accept(IVisitor& visitor); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr); + void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const; + TUniqueId FollowWaypoint(CStateManager& mgr) const; + TUniqueId NextWaypoint(CStateManager& mgr) const; + float GetSpeed() const { return xe8_speed; } + u32 GetAnimation() const { return xec_animation; } + float GetPause() const { return xf0_pause; } + u8 GetPatternTranslate() const { return xf4_patternTranslate; } + u8 GetPatternOrient() const { return xf5_patternOrient; } + u8 GetPatternFit() const { return xf6_patternFit; } + u8 GetBehaviour() const { return xf7_behaviour; } + u8 GetBehaviourOrient() const { return xf8_behaviourOrient; } + u16 GetBehaviourModifiers() const { return xfa_behaviourModifiers; } }; -} - +} // namespace urde diff --git a/Runtime/World/CScriptWorldTeleporter.cpp b/Runtime/World/CScriptWorldTeleporter.cpp index 296979883..91c996f82 100644 --- a/Runtime/World/CScriptWorldTeleporter.cpp +++ b/Runtime/World/CScriptWorldTeleporter.cpp @@ -6,8 +6,7 @@ #include "IMain.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { CScriptWorldTeleporter::CScriptWorldTeleporter(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, CAssetId worldId, CAssetId areaId) : CEntity(uid, info, active, name) @@ -16,17 +15,14 @@ CScriptWorldTeleporter::CScriptWorldTeleporter(TUniqueId uid, std::string_view n , x3c_type(ETeleporterType::NoTransition) , x40_24_upElevator(false) , x40_25_inTransition(false) -, x40_27_fadeWhite(false) -{ -} +, x40_27_fadeWhite(false) {} CScriptWorldTeleporter::CScriptWorldTeleporter(TUniqueId uid, std::string_view name, const CEntityInfo& info, - bool active, CAssetId worldId, CAssetId areaId, - CAssetId playerAncs, u32 charIdx, u32 defaultAnim, - const zeus::CVector3f& playerScale, CAssetId platformModel, - const zeus::CVector3f& platformScale, CAssetId backgroundModel, - const zeus::CVector3f& backgroundScale, bool upElevator, u16 soundId, - u8 volume, u8 panning) + bool active, CAssetId worldId, CAssetId areaId, CAssetId playerAncs, + u32 charIdx, u32 defaultAnim, const zeus::CVector3f& playerScale, + CAssetId platformModel, const zeus::CVector3f& platformScale, + CAssetId backgroundModel, const zeus::CVector3f& backgroundScale, + bool upElevator, u16 soundId, u8 volume, u8 panning) : CEntity(uid, info, active, name) , x34_worldId(worldId) , x38_areaId(areaId) @@ -42,9 +38,7 @@ CScriptWorldTeleporter::CScriptWorldTeleporter(TUniqueId uid, std::string_view n , x7c_backgroundScale(backgroundScale) , x88_soundId(CSfxManager::TranslateSFXID(soundId)) , x8a_volume(volume) -, x8b_panning(panning) -{ -} +, x8b_panning(panning) {} CScriptWorldTeleporter::CScriptWorldTeleporter(TUniqueId uid, std::string_view name, const CEntityInfo& info, bool active, CAssetId worldId, CAssetId areaId, u16 soundId, u8 volume, @@ -64,89 +58,73 @@ CScriptWorldTeleporter::CScriptWorldTeleporter(TUniqueId uid, std::string_view n , x8a_volume(volume) , x8b_panning(panning) , x8c_fontId(fontId) -, x90_stringId(stringId) -{ -} +, x90_stringId(stringId) {} -void CScriptWorldTeleporter::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CScriptWorldTeleporter::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CScriptWorldTeleporter::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) -{ - if (GetActive()) - { - const std::shared_ptr& transMgr = mgr.WorldTransManager(); - switch(msg) - { - case EScriptObjectMessage::Stop: - x40_25_inTransition = false; - transMgr->DisableTransition(); - transMgr->SfxStop(); - break; - case EScriptObjectMessage::Play: - StartTransition(mgr); - transMgr->SetSfx(x88_soundId, x8a_volume, x8b_panning); - transMgr->SfxStart(); - break; - case EScriptObjectMessage::SetToZero: - { - const auto& world = mgr.WorldNC(); - world->SetLoadPauseState(true); - CAssetId currentWorld = g_GameState->CurrentWorldAssetId(); - g_GameState->SetCurrentWorldId(x34_worldId); +void CScriptWorldTeleporter::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { + if (GetActive()) { + const std::shared_ptr& transMgr = mgr.WorldTransManager(); + switch (msg) { + case EScriptObjectMessage::Stop: + x40_25_inTransition = false; + transMgr->DisableTransition(); + transMgr->SfxStop(); + break; + case EScriptObjectMessage::Play: + StartTransition(mgr); + transMgr->SetSfx(x88_soundId, x8a_volume, x8b_panning); + transMgr->SfxStart(); + break; + case EScriptObjectMessage::SetToZero: { + const auto& world = mgr.WorldNC(); + world->SetLoadPauseState(true); + CAssetId currentWorld = g_GameState->CurrentWorldAssetId(); + g_GameState->SetCurrentWorldId(x34_worldId); - if (g_ResFactory->GetResourceTypeById(x34_worldId) == SBIG('MLVL')) - { - StartTransition(mgr); - g_GameState->SetCurrentWorldId(x34_worldId); - g_GameState->CurrentWorldState().SetDesiredAreaAssetId(x38_areaId); - g_Main->SetFlowState(EFlowState::None); - mgr.SetShouldQuitGame(true); - } - else - { - x40_25_inTransition = false; - transMgr->DisableTransition(); - g_GameState->SetCurrentWorldId(currentWorld); - } - break; - } - default: - break; - } + if (g_ResFactory->GetResourceTypeById(x34_worldId) == SBIG('MLVL')) { + StartTransition(mgr); + g_GameState->SetCurrentWorldId(x34_worldId); + g_GameState->CurrentWorldState().SetDesiredAreaAssetId(x38_areaId); + g_Main->SetFlowState(EFlowState::None); + mgr.SetShouldQuitGame(true); + } else { + x40_25_inTransition = false; + transMgr->DisableTransition(); + g_GameState->SetCurrentWorldId(currentWorld); + } + break; } - CEntity::AcceptScriptMsg(msg, uid, mgr); -} - -void CScriptWorldTeleporter::StartTransition(CStateManager& mgr) -{ - if (!x40_25_inTransition) - { - const auto& transMgr = mgr.WorldTransManager(); - switch(x3c_type) - { - case ETeleporterType::NoTransition: - transMgr->DisableTransition(); - break; - case ETeleporterType::Elevator: - if (x50_playerAnim.GetACSFile().IsValid() && x50_playerAnim.GetCharacter() != u32(-1)) - { - transMgr->EnableTransition(CAnimRes(x50_playerAnim.GetACSFile(), x50_playerAnim.GetCharacter(), - x5c_playerScale, x50_playerAnim.GetInitialAnimation(),true), - x68_platformModel, x6c_platformScale, x78_backgroundModel, - x7c_backgroundScale, x40_24_upElevator); - x40_25_inTransition = true; - } - break; - case ETeleporterType::Text: - transMgr->EnableTransition(x8c_fontId, x90_stringId, 0, x40_27_fadeWhite, x44_charFadeIn, x48_charsPerSecond, - x4c_showDelay); - x40_25_inTransition = true; - break; - } + default: + break; } + } + CEntity::AcceptScriptMsg(msg, uid, mgr); } +void CScriptWorldTeleporter::StartTransition(CStateManager& mgr) { + if (!x40_25_inTransition) { + const auto& transMgr = mgr.WorldTransManager(); + switch (x3c_type) { + case ETeleporterType::NoTransition: + transMgr->DisableTransition(); + break; + case ETeleporterType::Elevator: + if (x50_playerAnim.GetACSFile().IsValid() && x50_playerAnim.GetCharacter() != u32(-1)) { + transMgr->EnableTransition(CAnimRes(x50_playerAnim.GetACSFile(), x50_playerAnim.GetCharacter(), x5c_playerScale, + x50_playerAnim.GetInitialAnimation(), true), + x68_platformModel, x6c_platformScale, x78_backgroundModel, x7c_backgroundScale, + x40_24_upElevator); + x40_25_inTransition = true; + } + break; + case ETeleporterType::Text: + transMgr->EnableTransition(x8c_fontId, x90_stringId, 0, x40_27_fadeWhite, x44_charFadeIn, x48_charsPerSecond, + x4c_showDelay); + x40_25_inTransition = true; + break; + } + } } + +} // namespace urde diff --git a/Runtime/World/CScriptWorldTeleporter.hpp b/Runtime/World/CScriptWorldTeleporter.hpp index 84e505723..a403c85b0 100644 --- a/Runtime/World/CScriptWorldTeleporter.hpp +++ b/Runtime/World/CScriptWorldTeleporter.hpp @@ -4,57 +4,48 @@ #include "CAnimationParameters.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { -class CScriptWorldTeleporter : public CEntity -{ - enum class ETeleporterType - { - NoTransition, - Elevator, - Text +class CScriptWorldTeleporter : public CEntity { + enum class ETeleporterType { NoTransition, Elevator, Text }; + + CAssetId x34_worldId; + CAssetId x38_areaId; + ETeleporterType x3c_type = ETeleporterType::NoTransition; + union { + struct { + bool x40_24_upElevator : 1; + bool x40_25_inTransition : 1; + bool x40_27_fadeWhite : 1; }; + u8 _dummy = 0; + }; - CAssetId x34_worldId; - CAssetId x38_areaId; - ETeleporterType x3c_type = ETeleporterType::NoTransition; - union - { - struct - { - bool x40_24_upElevator : 1; - bool x40_25_inTransition : 1; - bool x40_27_fadeWhite : 1; - }; - u8 _dummy = 0; - }; + float x44_charFadeIn = 0.1f; + float x48_charsPerSecond = 8.0f; + float x4c_showDelay = 0.0f; + CAnimationParameters x50_playerAnim; + zeus::CVector3f x5c_playerScale; + CAssetId x68_platformModel; + zeus::CVector3f x6c_platformScale; + CAssetId x78_backgroundModel; + zeus::CVector3f x7c_backgroundScale; + u16 x88_soundId = -1; + u8 x8a_volume = 0; + u8 x8b_panning = 0; + CAssetId x8c_fontId; + CAssetId x90_stringId; - float x44_charFadeIn = 0.1f; - float x48_charsPerSecond = 8.0f; - float x4c_showDelay = 0.0f; - CAnimationParameters x50_playerAnim; - zeus::CVector3f x5c_playerScale; - CAssetId x68_platformModel; - zeus::CVector3f x6c_platformScale; - CAssetId x78_backgroundModel; - zeus::CVector3f x7c_backgroundScale; - u16 x88_soundId = -1; - u8 x8a_volume = 0; - u8 x8b_panning = 0; - CAssetId x8c_fontId; - CAssetId x90_stringId; public: - CScriptWorldTeleporter(TUniqueId, std::string_view, const CEntityInfo&, bool, CAssetId, CAssetId); - CScriptWorldTeleporter(TUniqueId, std::string_view, const CEntityInfo&, bool, CAssetId, CAssetId, u16, u8, u8, CAssetId, - CAssetId, bool, float, float, float); - CScriptWorldTeleporter(TUniqueId, std::string_view, const CEntityInfo&, bool, CAssetId, CAssetId, CAssetId, u32, u32, - const zeus::CVector3f&, CAssetId, const zeus::CVector3f&, CAssetId, const zeus::CVector3f&, bool, - u16, u8, u8); + CScriptWorldTeleporter(TUniqueId, std::string_view, const CEntityInfo&, bool, CAssetId, CAssetId); + CScriptWorldTeleporter(TUniqueId, std::string_view, const CEntityInfo&, bool, CAssetId, CAssetId, u16, u8, u8, + CAssetId, CAssetId, bool, float, float, float); + CScriptWorldTeleporter(TUniqueId, std::string_view, const CEntityInfo&, bool, CAssetId, CAssetId, CAssetId, u32, u32, + const zeus::CVector3f&, CAssetId, const zeus::CVector3f&, CAssetId, const zeus::CVector3f&, + bool, u16, u8, u8); - void Accept(IVisitor&); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); - void StartTransition(CStateManager&); + void Accept(IVisitor&); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr); + void StartTransition(CStateManager&); }; -} - +} // namespace urde diff --git a/Runtime/World/CSnakeWeedSwarm.cpp b/Runtime/World/CSnakeWeedSwarm.cpp index 8fab461b1..aafcffec8 100644 --- a/Runtime/World/CSnakeWeedSwarm.cpp +++ b/Runtime/World/CSnakeWeedSwarm.cpp @@ -2,25 +2,17 @@ #include "CAnimationParameters.hpp" #include "TCastTo.hpp" -namespace urde -{ - +namespace urde { CSnakeWeedSwarm::CSnakeWeedSwarm(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& pos, const zeus::CVector3f& scale, - const CAnimationParameters& animParms, const CActorParameters& actParms, - float f1, float f2, float f3, float f4, float f5, float f6, float f7, - float f8, float f9, float f10, float f11, float f12, float f13, float f14, - const CDamageInfo&, float /*f15*/, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, - u32 w6, float f16) -: CActor(uid, active, name, info, zeus::CTransform::Translate(pos), - CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Trigger, EMaterialTypes::NonSolidDamageable), actParms, kInvalidUniqueId) -{ -} + const CAnimationParameters& animParms, const CActorParameters& actParms, float f1, + float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, + float f10, float f11, float f12, float f13, float f14, const CDamageInfo&, + float /*f15*/, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, u32 w6, float f16) +: CActor(uid, active, name, info, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(), + CMaterialList(EMaterialTypes::Trigger, EMaterialTypes::NonSolidDamageable), actParms, kInvalidUniqueId) {} -void CSnakeWeedSwarm::Accept(urde::IVisitor& visitor) -{ - visitor.Visit(this); -} +void CSnakeWeedSwarm::Accept(urde::IVisitor& visitor) { visitor.Visit(this); } -} +} // namespace urde diff --git a/Runtime/World/CSnakeWeedSwarm.hpp b/Runtime/World/CSnakeWeedSwarm.hpp index cc7724bd2..f4b239b21 100644 --- a/Runtime/World/CSnakeWeedSwarm.hpp +++ b/Runtime/World/CSnakeWeedSwarm.hpp @@ -3,20 +3,16 @@ #include "World/CActor.hpp" #include "Collision/CCollisionSurface.hpp" -namespace urde -{ +namespace urde { class CAnimationParameters; -class CSnakeWeedSwarm : public CActor -{ +class CSnakeWeedSwarm : public CActor { public: - CSnakeWeedSwarm(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, const zeus::CVector3f&, - const CAnimationParameters&, const CActorParameters&, float, float, float, float, float, float, float, - float, float, float, float, float, float, float, const CDamageInfo&, float, u32, u32, u32, u32, u32, - u32, float); + CSnakeWeedSwarm(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, const zeus::CVector3f&, + const CAnimationParameters&, const CActorParameters&, float, float, float, float, float, float, float, + float, float, float, float, float, float, float, const CDamageInfo&, float, u32, u32, u32, u32, u32, + u32, float); - void Accept(IVisitor&); - void ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, - CStateManager& stateMgr) {} + void Accept(IVisitor&); + void ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& stateMgr) {} }; -} - +} // namespace urde diff --git a/Runtime/World/CStateMachine.cpp b/Runtime/World/CStateMachine.cpp index aa7bcf255..0c9b273a5 100644 --- a/Runtime/World/CStateMachine.cpp +++ b/Runtime/World/CStateMachine.cpp @@ -2,156 +2,134 @@ #include "CAi.hpp" #include "CStateManager.hpp" -namespace urde -{ -CStateMachine::CStateMachine(CInputStream& in) -{ - CAiTrigger* lastTrig = nullptr; - u32 stateCount = in.readUint32Big(); +namespace urde { +CStateMachine::CStateMachine(CInputStream& in) { + CAiTrigger* lastTrig = nullptr; + u32 stateCount = in.readUint32Big(); - x0_states.reserve(stateCount); + x0_states.reserve(stateCount); - for (u32 i = 0; i < stateCount; ++i) - { + for (u32 i = 0; i < stateCount; ++i) { + std::string name = in.readString(31, false); + CAiStateFunc func = CAi::GetStateFunc(name.c_str()); + x0_states.emplace_back(func, name.c_str()); + } + + x10_triggers.reserve(in.readUint32Big()); + + for (u32 i = 0; i < stateCount; ++i) { + x0_states[i].SetNumTriggers(in.readUint32Big()); + if (x0_states[i].GetNumTriggers() == 0) + continue; + CAiTrigger* firstTrig = x10_triggers.data() + x10_triggers.size(); + x0_states[i].SetTriggers(firstTrig); + x10_triggers.resize(x10_triggers.size() + x0_states[i].GetNumTriggers()); + + for (u32 j = 0; j < x0_states[i].GetNumTriggers(); ++j) { + u32 triggerCount = in.readUint32Big(); + u32 lastTriggerIdx = triggerCount - 1; + for (u32 k = 0; k < triggerCount; ++k) { std::string name = in.readString(31, false); - CAiStateFunc func = CAi::GetStateFunc(name.c_str()); - x0_states.emplace_back(func, name.c_str()); - } - - x10_triggers.reserve(in.readUint32Big()); - - for (u32 i = 0; i < stateCount; ++i) - { - x0_states[i].SetNumTriggers(in.readUint32Big()); - if (x0_states[i].GetNumTriggers() == 0) - continue; - CAiTrigger* firstTrig = x10_triggers.data() + x10_triggers.size(); - x0_states[i].SetTriggers(firstTrig); - x10_triggers.resize(x10_triggers.size() + x0_states[i].GetNumTriggers()); - - for (u32 j = 0; j < x0_states[i].GetNumTriggers(); ++j) - { - u32 triggerCount = in.readUint32Big(); - u32 lastTriggerIdx = triggerCount - 1; - for (u32 k = 0; k < triggerCount; ++k) - { - std::string name = in.readString(31, false); - bool isNot = name.front() == '!'; - CAiTriggerFunc func = CAi::GetTrigerFunc(isNot ? name.c_str() + 1 : name.c_str()); - float arg = in.readFloatBig(); - CAiTrigger* newTrig; - if (k < lastTriggerIdx) - { - x10_triggers.emplace_back(); - newTrig = &x10_triggers.back(); - } - else - { - newTrig = &firstTrig[j]; - } - if (k == 0) - newTrig->Setup(func, isNot, arg, &x0_states[in.readUint32Big()]); - else - newTrig->Setup(func, isNot, arg, lastTrig); - lastTrig = newTrig; - } + bool isNot = name.front() == '!'; + CAiTriggerFunc func = CAi::GetTrigerFunc(isNot ? name.c_str() + 1 : name.c_str()); + float arg = in.readFloatBig(); + CAiTrigger* newTrig; + if (k < lastTriggerIdx) { + x10_triggers.emplace_back(); + newTrig = &x10_triggers.back(); + } else { + newTrig = &firstTrig[j]; } + if (k == 0) + newTrig->Setup(func, isNot, arg, &x0_states[in.readUint32Big()]); + else + newTrig->Setup(func, isNot, arg, lastTrig); + lastTrig = newTrig; + } } + } } -s32 CStateMachine::GetStateIndex(std::string_view state) const -{ - auto it = std::find_if(x0_states.begin(), x0_states.end(), [state](const CAiState& st) { - return (strncmp(st.GetName(), state.data(), 31) == 0); - }); - if (it == x0_states.end()) - return 0; +s32 CStateMachine::GetStateIndex(std::string_view state) const { + auto it = std::find_if(x0_states.begin(), x0_states.end(), + [state](const CAiState& st) { return (strncmp(st.GetName(), state.data(), 31) == 0); }); + if (it == x0_states.end()) + return 0; - return it - x0_states.begin(); + return it - x0_states.begin(); } -void CStateMachineState::Update(CStateManager& mgr, CAi& ai, float delta) -{ - if (x4_state) - { - x8_time += delta; - x4_state->CallFunc(mgr, ai, EStateMsg::Update, delta); - for (int i = 0; i < x4_state->GetNumTriggers(); ++i) - { - CAiTrigger* trig = x4_state->GetTrig(i); - CAiState* state = nullptr; - bool andPassed = true; - while (andPassed && trig) - { - andPassed = false; - if (trig->CallFunc(mgr, ai)) - { - andPassed = true; - state = trig->GetState(); - trig = trig->GetAnd(); - } - } - if (andPassed && state) - { - x4_state->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f); - x4_state = state; - x8_time = 0.f; - x18_24_codeTrigger = false; - xc_random = mgr.GetActiveRandom()->Float(); - x4_state->CallFunc(mgr, ai, EStateMsg::Activate, delta); - return; - } +void CStateMachineState::Update(CStateManager& mgr, CAi& ai, float delta) { + if (x4_state) { + x8_time += delta; + x4_state->CallFunc(mgr, ai, EStateMsg::Update, delta); + for (int i = 0; i < x4_state->GetNumTriggers(); ++i) { + CAiTrigger* trig = x4_state->GetTrig(i); + CAiState* state = nullptr; + bool andPassed = true; + while (andPassed && trig) { + andPassed = false; + if (trig->CallFunc(mgr, ai)) { + andPassed = true; + state = trig->GetState(); + trig = trig->GetAnd(); } - } -} - -void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, s32 idx) -{ - CAiState* state = const_cast(&x0_machine->GetStateVector()[idx]); - if (x4_state != state) - { - if (x4_state) - x4_state->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f); + } + if (andPassed && state) { + x4_state->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f); x4_state = state; x8_time = 0.f; - xc_random = mgr.GetActiveRandom()->Float(); x18_24_codeTrigger = false; - x4_state->CallFunc(mgr, ai, EStateMsg::Activate, 0.f); - } -} - -void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, const CStateMachine* machine, std::string_view state) -{ - if (!machine) + xc_random = mgr.GetActiveRandom()->Float(); + x4_state->CallFunc(mgr, ai, EStateMsg::Activate, delta); return; - - if (!x0_machine) - x0_machine = machine; - - s32 idx = machine->GetStateIndex(state); - SetState(mgr, ai, idx); + } + } + } } -const std::vector* CStateMachineState::GetStateVector() const -{ - if (!x0_machine) - return nullptr; - - return &x0_machine->GetStateVector(); -} - -void CStateMachineState::Setup(const CStateMachine* machine) -{ - x0_machine = machine; - x4_state = nullptr; +void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, s32 idx) { + CAiState* state = const_cast(&x0_machine->GetStateVector()[idx]); + if (x4_state != state) { + if (x4_state) + x4_state->CallFunc(mgr, ai, EStateMsg::Deactivate, 0.f); + x4_state = state; x8_time = 0.f; - xc_random = 0.f; - x10_delay = 0.f; + xc_random = mgr.GetActiveRandom()->Float(); + x18_24_codeTrigger = false; + x4_state->CallFunc(mgr, ai, EStateMsg::Activate, 0.f); + } } -CFactoryFnReturn FAiFiniteStateMachineFactory(const SObjectTag &tag, CInputStream &in, const CVParamTransfer &vparms, CObjectReference *) -{ - return TToken::GetIObjObjectFor(std::make_unique(in)); +void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, const CStateMachine* machine, std::string_view state) { + if (!machine) + return; + + if (!x0_machine) + x0_machine = machine; + + s32 idx = machine->GetStateIndex(state); + SetState(mgr, ai, idx); } +const std::vector* CStateMachineState::GetStateVector() const { + if (!x0_machine) + return nullptr; + + return &x0_machine->GetStateVector(); } + +void CStateMachineState::Setup(const CStateMachine* machine) { + x0_machine = machine; + x4_state = nullptr; + x8_time = 0.f; + xc_random = 0.f; + x10_delay = 0.f; +} + +CFactoryFnReturn FAiFiniteStateMachineFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, + CObjectReference*) { + return TToken::GetIObjObjectFor(std::make_unique(in)); +} + +} // namespace urde diff --git a/Runtime/World/CStateMachine.hpp b/Runtime/World/CStateMachine.hpp index 2444391ac..f4b0412d1 100644 --- a/Runtime/World/CStateMachine.hpp +++ b/Runtime/World/CStateMachine.hpp @@ -6,126 +6,115 @@ #include "IOStreams.hpp" #include "IObjFactory.hpp" -namespace urde -{ +namespace urde { class CAiState; class CStateManager; -class CAiTrigger -{ - CAiTriggerFunc x0_func; - float xc_arg = 0.f; - CAiTrigger* x10_andTrig = nullptr; - CAiState* x14_state = nullptr; - bool x18_lNot = false; -public: - CAiTrigger() = default; - CAiTrigger* GetAnd() const { return x10_andTrig; } - CAiState* GetState() const { return x14_state; } - bool CallFunc(CStateManager& mgr, CAi& ai) - { - if (x0_func) - { - bool ret = (ai.*x0_func)(mgr, xc_arg); - return x18_lNot ? !ret : ret; - } - return true; - } +class CAiTrigger { + CAiTriggerFunc x0_func; + float xc_arg = 0.f; + CAiTrigger* x10_andTrig = nullptr; + CAiState* x14_state = nullptr; + bool x18_lNot = false; - void Setup(CAiTriggerFunc func, bool lnot, float arg, CAiTrigger* andTrig) - { - x0_func = func; - x18_lNot = lnot; - xc_arg = arg; - x10_andTrig = andTrig; - } - void Setup(CAiTriggerFunc func, bool lnot, float arg, CAiState* state) - { - x0_func = func; - x18_lNot = lnot; - xc_arg = arg; - x14_state = state; +public: + CAiTrigger() = default; + CAiTrigger* GetAnd() const { return x10_andTrig; } + CAiState* GetState() const { return x14_state; } + bool CallFunc(CStateManager& mgr, CAi& ai) { + if (x0_func) { + bool ret = (ai.*x0_func)(mgr, xc_arg); + return x18_lNot ? !ret : ret; } + return true; + } + + void Setup(CAiTriggerFunc func, bool lnot, float arg, CAiTrigger* andTrig) { + x0_func = func; + x18_lNot = lnot; + xc_arg = arg; + x10_andTrig = andTrig; + } + void Setup(CAiTriggerFunc func, bool lnot, float arg, CAiState* state) { + x0_func = func; + x18_lNot = lnot; + xc_arg = arg; + x14_state = state; + } }; -class CAiState -{ - friend class CStateMachineState; - CAiStateFunc x0_func; - char xc_name[32] = {}; - u32 x2c_numTriggers; - CAiTrigger* x30_firstTrigger; -public: - CAiState(CAiStateFunc func, const char* name) - { - x0_func = func; - strncpy(xc_name, name, 31); - } +class CAiState { + friend class CStateMachineState; + CAiStateFunc x0_func; + char xc_name[32] = {}; + u32 x2c_numTriggers; + CAiTrigger* x30_firstTrigger; - s32 GetNumTriggers() const { return x2c_numTriggers; } - CAiTrigger* GetTrig(s32 i) const { return &x30_firstTrigger[i]; } - const char* GetName() const { return xc_name; } - void SetTriggers(CAiTrigger* triggers) { x30_firstTrigger = triggers; } - void SetNumTriggers(s32 numTriggers) { x2c_numTriggers = numTriggers; } - void CallFunc(CStateManager& mgr, CAi& ai, EStateMsg msg, float delta) const - { - if (x0_func) - (ai.*x0_func)(mgr, msg, delta); - } +public: + CAiState(CAiStateFunc func, const char* name) { + x0_func = func; + strncpy(xc_name, name, 31); + } + + s32 GetNumTriggers() const { return x2c_numTriggers; } + CAiTrigger* GetTrig(s32 i) const { return &x30_firstTrigger[i]; } + const char* GetName() const { return xc_name; } + void SetTriggers(CAiTrigger* triggers) { x30_firstTrigger = triggers; } + void SetNumTriggers(s32 numTriggers) { x2c_numTriggers = numTriggers; } + void CallFunc(CStateManager& mgr, CAi& ai, EStateMsg msg, float delta) const { + if (x0_func) + (ai.*x0_func)(mgr, msg, delta); + } }; -class CStateMachine -{ - std::vector x0_states; - std::vector x10_triggers; -public: - CStateMachine(CInputStream& in); +class CStateMachine { + std::vector x0_states; + std::vector x10_triggers; - s32 GetStateIndex(std::string_view state) const; - const std::vector& GetStateVector() const { return x0_states; } +public: + CStateMachine(CInputStream& in); + + s32 GetStateIndex(std::string_view state) const; + const std::vector& GetStateVector() const { return x0_states; } }; -class CStateMachineState -{ - friend class CPatterned; - const CStateMachine* x0_machine = nullptr; - CAiState* x4_state = nullptr; - float x8_time = 0.f; - float xc_random = 0.f; - float x10_delay = 0.f; - float x14_; - union - { - struct - { - bool x18_24_codeTrigger : 1; - }; - u32 dummy = 0; +class CStateMachineState { + friend class CPatterned; + const CStateMachine* x0_machine = nullptr; + CAiState* x4_state = nullptr; + float x8_time = 0.f; + float xc_random = 0.f; + float x10_delay = 0.f; + float x14_; + union { + struct { + bool x18_24_codeTrigger : 1; }; + u32 dummy = 0; + }; + public: - CStateMachineState()=default; + CStateMachineState() = default; - CAiState* GetActorState() const { return x4_state; } + CAiState* GetActorState() const { return x4_state; } - void Update(CStateManager& mgr, CAi& ai, float delta); - void SetState(CStateManager&, CAi&, s32); - void SetState(CStateManager&, CAi&, const CStateMachine*, std::string_view); - const std::vector* GetStateVector() const; - void Setup(const CStateMachine* machine); - void SetDelay(float delay) { x10_delay = delay; } - float GetTime() const { return x8_time; } - float GetRandom() const { return xc_random; } - float GetDelay() const { return x10_delay; } + void Update(CStateManager& mgr, CAi& ai, float delta); + void SetState(CStateManager&, CAi&, s32); + void SetState(CStateManager&, CAi&, const CStateMachine*, std::string_view); + const std::vector* GetStateVector() const; + void Setup(const CStateMachine* machine); + void SetDelay(float delay) { x10_delay = delay; } + float GetTime() const { return x8_time; } + float GetRandom() const { return xc_random; } + float GetDelay() const { return x10_delay; } - const char* GetName() const - { - if (x4_state) - return x4_state->GetName(); - return nullptr; - } + const char* GetName() const { + if (x4_state) + return x4_state->GetName(); + return nullptr; + } }; CFactoryFnReturn FAiFiniteStateMachineFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& vparms, - CObjectReference*); - -} + CObjectReference*); +} // namespace urde diff --git a/Runtime/World/CTeamAiMgr.cpp b/Runtime/World/CTeamAiMgr.cpp index 7b277f195..40789fcc7 100644 --- a/Runtime/World/CTeamAiMgr.cpp +++ b/Runtime/World/CTeamAiMgr.cpp @@ -3,31 +3,27 @@ #include "CStateManager.hpp" #include "CPlayer.hpp" -namespace urde -{ +namespace urde { -struct TeamAiRoleSorter -{ - zeus::CVector3f x0_pos; - s32 xc_type; - bool operator()(const CTeamAiRole& a, const CTeamAiRole& b) const - { - float aDist = (x0_pos - a.GetTeamPosition()).magSquared(); - float bDist = (x0_pos - b.GetTeamPosition()).magSquared(); - switch (xc_type) - { - case 0: - return a.GetOwnerId() < b.GetOwnerId(); - case 1: - return aDist < bDist; - default: - if (a.GetTeamAiRole() == b.GetTeamAiRole()) - return aDist < bDist; - else - return a.GetTeamAiRole() < b.GetTeamAiRole(); - } +struct TeamAiRoleSorter { + zeus::CVector3f x0_pos; + s32 xc_type; + bool operator()(const CTeamAiRole& a, const CTeamAiRole& b) const { + float aDist = (x0_pos - a.GetTeamPosition()).magSquared(); + float bDist = (x0_pos - b.GetTeamPosition()).magSquared(); + switch (xc_type) { + case 0: + return a.GetOwnerId() < b.GetOwnerId(); + case 1: + return aDist < bDist; + default: + if (a.GetTeamAiRole() == b.GetTeamAiRole()) + return aDist < bDist; + else + return a.GetTeamAiRole() < b.GetTeamAiRole(); } - TeamAiRoleSorter(const zeus::CVector3f& pos, s32 type) : x0_pos(pos), xc_type(type) {} + } + TeamAiRoleSorter(const zeus::CVector3f& pos, s32 type) : x0_pos(pos), xc_type(type) {} }; CTeamAiData::CTeamAiData(CInputStream& in, s32 propCount) @@ -39,411 +35,342 @@ CTeamAiData::CTeamAiData(CInputStream& in, s32 propCount) , x14_maxProjectileAttackerCount(in.readUint32Big()) , x18_positionMode(in.readUint32Big()) , x1c_meleeTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f) -, x20_projectileTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f) -{ -} +, x20_projectileTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f) {} CTeamAiMgr::CTeamAiMgr(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CTeamAiData& data) -: CEntity(uid, info, true, name), x34_data(data) -{ - if (x34_data.x0_aiCount) - x58_roles.reserve(x34_data.x0_aiCount); - if (x34_data.x4_meleeCount) - x68_meleeAttackers.reserve(x34_data.x4_meleeCount); - if (x34_data.x8_projectileCount) - x78_projectileAttackers.reserve(x34_data.x8_projectileCount); +: CEntity(uid, info, true, name), x34_data(data) { + if (x34_data.x0_aiCount) + x58_roles.reserve(x34_data.x0_aiCount); + if (x34_data.x4_meleeCount) + x68_meleeAttackers.reserve(x34_data.x4_meleeCount); + if (x34_data.x8_projectileCount) + x78_projectileAttackers.reserve(x34_data.x8_projectileCount); } -void CTeamAiMgr::Accept(IVisitor& visitor) -{ - visitor.Visit(this); -} +void CTeamAiMgr::Accept(IVisitor& visitor) { visitor.Visit(this); } -void CTeamAiMgr::UpdateTeamCaptain() -{ - int maxPriority = INT_MIN; - x8c_teamCaptainId = kInvalidUniqueId; - for (const auto& role : x58_roles) - { - if (role.x18_captainPriority > maxPriority) - { - maxPriority = role.x18_captainPriority; - x8c_teamCaptainId = role.GetOwnerId(); - } +void CTeamAiMgr::UpdateTeamCaptain() { + int maxPriority = INT_MIN; + x8c_teamCaptainId = kInvalidUniqueId; + for (const auto& role : x58_roles) { + if (role.x18_captainPriority > maxPriority) { + maxPriority = role.x18_captainPriority; + x8c_teamCaptainId = role.GetOwnerId(); } + } } -bool CTeamAiMgr::ShouldUpdateRoles(float dt) -{ - if (x58_roles.empty()) - return false; - - x88_timeDirty += dt; - if (x88_timeDirty >= 1.5f) - return true; - - for (const auto& role : x58_roles) - { - if (role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Initial || - role.GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Unassigned) - return true; - } - +bool CTeamAiMgr::ShouldUpdateRoles(float dt) { + if (x58_roles.empty()) return false; -} -void CTeamAiMgr::ResetRoles(CStateManager& mgr) -{ - for (auto& role : x58_roles) - { - role.x10_curRole = CTeamAiRole::ETeamAiRole::Initial; - role.x14_roleIndex = 0; - if (const CAi* ai = static_cast(mgr.GetObjectById(role.GetOwnerId()))) - role.x1c_position = ai->GetTranslation(); - } -} - -void CTeamAiMgr::SpacingSort(CStateManager& mgr, const zeus::CVector3f& pos) -{ - TeamAiRoleSorter sorter(pos, 2); - std::sort(x58_roles.begin(), x58_roles.end(), sorter); - float tierStagger = 4.5f; - for (const auto& role : x58_roles) - { - if (TCastToPtr ai = mgr.ObjectById(role.GetOwnerId())) - { - float length = (ai->GetBaseBoundingBox().max.y() - ai->GetBaseBoundingBox().min.y()) * 1.5f; - if (length > tierStagger) - tierStagger = length; - } - } - float curTierDist = tierStagger; - int tierTeamSize = 0; - int maxTierTeamSize = 3; - for (auto& role : x58_roles) - { - if (TCastToPtr ai = mgr.ObjectById(role.GetOwnerId())) - { - zeus::CVector3f delta = ai->GetTranslation() - pos; - zeus::CVector3f newPos; - if (delta.canBeNormalized()) - newPos = pos + delta.normalized() * curTierDist; - else - newPos = pos + ai->GetTransform().basis[1] * curTierDist; - role.x1c_position = newPos; - role.x1c_position.z() = ai->GetTranslation().z(); - tierTeamSize += 1; - if (tierTeamSize > maxTierTeamSize) - { - curTierDist += tierStagger; - tierTeamSize = 0; - maxTierTeamSize += 1; - } - } - } - TeamAiRoleSorter sorter2(pos, 0); - std::sort(x58_roles.begin(), x58_roles.end(), sorter2); -} - -void CTeamAiMgr::PositionTeam(CStateManager& mgr) -{ - zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); - switch (x34_data.x18_positionMode) - { - case 1: - SpacingSort(mgr, aimPos); - break; - default: - for (auto& role : x58_roles) - if (TCastToPtr ai = mgr.ObjectById(role.GetOwnerId())) - role.x1c_position = ai->GetOrigin(mgr, role); - break; - } -} - -void CTeamAiMgr::AssignRoles(CTeamAiRole::ETeamAiRole assRole, s32 count) -{ - if (count == 0) - return; - s32 lastIdx = 0; - for (auto& role : x58_roles) - { - if (role.GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Initial) - { - if (role.x4_roleA == assRole || role.x8_roleB == assRole || role.xc_roleC == assRole) - { - role.x10_curRole = assRole; - role.x14_roleIndex = lastIdx++; - if (lastIdx == count) - return; - } - } - } -} - -void CTeamAiMgr::UpdateRoles(CStateManager& mgr) -{ - ResetRoles(mgr); - zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); - TeamAiRoleSorter sorter(aimPos, 1); - std::sort(x58_roles.begin(), x58_roles.end(), sorter); - AssignRoles(CTeamAiRole::ETeamAiRole::Melee, x34_data.x4_meleeCount); - AssignRoles(CTeamAiRole::ETeamAiRole::Projectile, x34_data.x8_projectileCount); - AssignRoles(CTeamAiRole::ETeamAiRole::Unknown, x34_data.xc_unknownCount); - for (auto& role : x58_roles) - { - if (role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Initial || - role.GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Unassigned) - role.SetTeamAiRole(CTeamAiRole::ETeamAiRole::Unassigned); - } - TeamAiRoleSorter sorter2(aimPos, 0); - std::sort(x58_roles.begin(), x58_roles.end(), sorter2); - x88_timeDirty = 0.f; -} - -void CTeamAiMgr::Think(float dt, CStateManager& mgr) -{ - CEntity::Think(dt, mgr); - if (ShouldUpdateRoles(dt)) - UpdateRoles(mgr); - PositionTeam(mgr); - x90_timeSinceMelee += dt; - x94_timeSinceProjectile += dt; -} - -void CTeamAiMgr::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) -{ - CEntity::AcceptScriptMsg(msg, objId, mgr); -} - -CTeamAiRole* CTeamAiMgr::GetTeamAiRole(TUniqueId aiId) -{ - auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, - [](const auto& obj) { return obj.GetOwnerId(); }); - return search != x58_roles.end() ? &*search : nullptr; -} - -bool CTeamAiMgr::IsPartOfTeam(TUniqueId aiId) const -{ - auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, - [](const auto& obj) { return obj.GetOwnerId(); }); - return search != x58_roles.end(); -} - -bool CTeamAiMgr::HasTeamAiRole(TUniqueId aiId) const -{ - auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, - [](const auto& obj) { return obj.GetOwnerId(); }); - return (search != x58_roles.end() && - search->GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Initial && - search->GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Unassigned); -} - -bool CTeamAiMgr::IsMeleeAttacker(TUniqueId aiId) const -{ - auto search = rstl::binary_find(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId); - return search != x68_meleeAttackers.end(); -} - -bool CTeamAiMgr::CanAcceptMeleeAttacker(TUniqueId aiId) const -{ - if (x90_timeSinceMelee >= x34_data.x1c_meleeTimeInterval && - x68_meleeAttackers.size() < x34_data.x10_maxMeleeAttackerCount) - return true; - return IsMeleeAttacker(aiId); -} - -bool CTeamAiMgr::AddMeleeAttacker(TUniqueId aiId) -{ - if (x90_timeSinceMelee >= x34_data.x1c_meleeTimeInterval && - x68_meleeAttackers.size() < x34_data.x10_maxMeleeAttackerCount && HasTeamAiRole(aiId)) - { - auto search = rstl::binary_find(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId); - if (search == x68_meleeAttackers.end()) - { - x68_meleeAttackers.insert(std::lower_bound( - x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId), aiId); - x90_timeSinceMelee = 0.f; - } - return true; - } - return false; -} - -void CTeamAiMgr::RemoveMeleeAttacker(TUniqueId aiId) -{ - auto search = rstl::binary_find(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId); - if (search != x68_meleeAttackers.end()) - x68_meleeAttackers.erase(search); -} - -bool CTeamAiMgr::IsProjectileAttacker(TUniqueId aiId) const -{ - auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId); - return search != x78_projectileAttackers.end(); -} - -bool CTeamAiMgr::CanAcceptProjectileAttacker(TUniqueId aiId) const -{ - if (x94_timeSinceProjectile >= x34_data.x20_projectileTimeInterval && - x78_projectileAttackers.size() < x34_data.x14_maxProjectileAttackerCount) - return true; - return IsProjectileAttacker(aiId); -} - -bool CTeamAiMgr::AddProjectileAttacker(TUniqueId aiId) -{ - if (x94_timeSinceProjectile >= x34_data.x20_projectileTimeInterval && - x78_projectileAttackers.size() < x34_data.x14_maxProjectileAttackerCount && HasTeamAiRole(aiId)) - { - auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId); - if (search == x78_projectileAttackers.end()) - { - x78_projectileAttackers.insert(std::lower_bound( - x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId), aiId); - x94_timeSinceProjectile = 0.f; - } - return true; - } - return false; -} - -void CTeamAiMgr::RemoveProjectileAttacker(TUniqueId aiId) -{ - auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId); - if (search != x78_projectileAttackers.end()) - x78_projectileAttackers.erase(search); -} - -bool CTeamAiMgr::AssignTeamAiRole(const CAi& ai, CTeamAiRole::ETeamAiRole roleA, - CTeamAiRole::ETeamAiRole roleB, CTeamAiRole::ETeamAiRole roleC) -{ - CTeamAiRole newRole(ai.GetUniqueId(), roleA, roleB, roleC); - auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), newRole); - if (search == x58_roles.end()) - { - if (x58_roles.size() >= x58_roles.capacity()) - return false; - x58_roles.insert(std::lower_bound(x58_roles.begin(), x58_roles.end(), newRole), newRole); - } - else - { - *search = newRole; - } - UpdateTeamCaptain(); + x88_timeDirty += dt; + if (x88_timeDirty >= 1.5f) return true; + + for (const auto& role : x58_roles) { + if (role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Initial || + role.GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Unassigned) + return true; + } + + return false; } -void CTeamAiMgr::RemoveTeamAiRole(TUniqueId aiId) -{ - if (IsMeleeAttacker(aiId)) - RemoveMeleeAttacker(aiId); - if (IsProjectileAttacker(aiId)) - RemoveProjectileAttacker(aiId); - auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, - [](const auto& obj) { return obj.GetOwnerId(); }); - x58_roles.erase(search); - UpdateTeamCaptain(); +void CTeamAiMgr::ResetRoles(CStateManager& mgr) { + for (auto& role : x58_roles) { + role.x10_curRole = CTeamAiRole::ETeamAiRole::Initial; + role.x14_roleIndex = 0; + if (const CAi* ai = static_cast(mgr.GetObjectById(role.GetOwnerId()))) + role.x1c_position = ai->GetTranslation(); + } } -void CTeamAiMgr::ClearTeamAiRole(TUniqueId aiId) -{ - auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, - [](const auto& obj) { return obj.GetOwnerId(); }); - if (search != x58_roles.end()) - search->x10_curRole = CTeamAiRole::ETeamAiRole::Initial; -} - -s32 CTeamAiMgr::GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole testRole) const -{ - s32 ret = 0; - for (const auto& role : x58_roles) - if (role.GetTeamAiRole() == testRole) - ++ret; - return ret; -} - -s32 CTeamAiMgr::GetNumAssignedAiRoles() const -{ - s32 ret = 0; - for (const auto& role : x58_roles) - if (role.GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Initial && - role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Unassigned) - ++ret; - return ret; -} - -CTeamAiRole* CTeamAiMgr::GetTeamAiRole(CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId) -{ - if (TCastToPtr aimgr = mgr.ObjectById(mgrId)) - return aimgr->GetTeamAiRole(aiId); - return nullptr; -} - -void CTeamAiMgr::ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId, bool clearRole) -{ - if (TCastToPtr tmgr = mgr.ObjectById(mgrId)) - { - if (tmgr->HasTeamAiRole(aiId)) - { - if (type == EAttackType::Melee) - { - if (tmgr->IsMeleeAttacker(aiId)) - tmgr->RemoveMeleeAttacker(aiId); - } - else if (type == EAttackType::Projectile) - { - if (tmgr->IsProjectileAttacker(aiId)) - tmgr->RemoveProjectileAttacker(aiId); - } - if (clearRole) - tmgr->ClearTeamAiRole(aiId); - } +void CTeamAiMgr::SpacingSort(CStateManager& mgr, const zeus::CVector3f& pos) { + TeamAiRoleSorter sorter(pos, 2); + std::sort(x58_roles.begin(), x58_roles.end(), sorter); + float tierStagger = 4.5f; + for (const auto& role : x58_roles) { + if (TCastToPtr ai = mgr.ObjectById(role.GetOwnerId())) { + float length = (ai->GetBaseBoundingBox().max.y() - ai->GetBaseBoundingBox().min.y()) * 1.5f; + if (length > tierStagger) + tierStagger = length; } -} - -bool CTeamAiMgr::CanAcceptAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId) -{ - if (TCastToPtr tmgr = mgr.ObjectById(mgrId)) - { - if (tmgr->HasTeamAiRole(aiId)) - { - if (type == EAttackType::Melee) - return tmgr->CanAcceptMeleeAttacker(aiId); - else if (type == EAttackType::Projectile) - return tmgr->CanAcceptProjectileAttacker(aiId); - } + } + float curTierDist = tierStagger; + int tierTeamSize = 0; + int maxTierTeamSize = 3; + for (auto& role : x58_roles) { + if (TCastToPtr ai = mgr.ObjectById(role.GetOwnerId())) { + zeus::CVector3f delta = ai->GetTranslation() - pos; + zeus::CVector3f newPos; + if (delta.canBeNormalized()) + newPos = pos + delta.normalized() * curTierDist; + else + newPos = pos + ai->GetTransform().basis[1] * curTierDist; + role.x1c_position = newPos; + role.x1c_position.z() = ai->GetTranslation().z(); + tierTeamSize += 1; + if (tierTeamSize > maxTierTeamSize) { + curTierDist += tierStagger; + tierTeamSize = 0; + maxTierTeamSize += 1; + } } - return false; + } + TeamAiRoleSorter sorter2(pos, 0); + std::sort(x58_roles.begin(), x58_roles.end(), sorter2); } -bool CTeamAiMgr::AddAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId) -{ - if (TCastToPtr tmgr = mgr.ObjectById(mgrId)) - { - if (tmgr->HasTeamAiRole(aiId)) - { - if (type == EAttackType::Melee) - return tmgr->AddMeleeAttacker(aiId); - else if (type == EAttackType::Projectile) - return tmgr->AddProjectileAttacker(aiId); - } +void CTeamAiMgr::PositionTeam(CStateManager& mgr) { + zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + switch (x34_data.x18_positionMode) { + case 1: + SpacingSort(mgr, aimPos); + break; + default: + for (auto& role : x58_roles) + if (TCastToPtr ai = mgr.ObjectById(role.GetOwnerId())) + role.x1c_position = ai->GetOrigin(mgr, role); + break; + } +} + +void CTeamAiMgr::AssignRoles(CTeamAiRole::ETeamAiRole assRole, s32 count) { + if (count == 0) + return; + s32 lastIdx = 0; + for (auto& role : x58_roles) { + if (role.GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Initial) { + if (role.x4_roleA == assRole || role.x8_roleB == assRole || role.xc_roleC == assRole) { + role.x10_curRole = assRole; + role.x14_roleIndex = lastIdx++; + if (lastIdx == count) + return; + } } - return false; + } } -TUniqueId CTeamAiMgr::GetTeamAiMgr(CAi& ai, CStateManager& mgr) -{ - for (const auto& conn : ai.GetConnectionList()) - { - if (conn.x0_state == EScriptObjectState::Active && conn.x4_msg == EScriptObjectMessage::Play) - { - TUniqueId id = mgr.GetIdForScript(conn.x8_objId); - if (TCastToConstPtr aimgr = mgr.GetObjectById(id)) - return aimgr->GetUniqueId(); - } +void CTeamAiMgr::UpdateRoles(CStateManager& mgr) { + ResetRoles(mgr); + zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f); + TeamAiRoleSorter sorter(aimPos, 1); + std::sort(x58_roles.begin(), x58_roles.end(), sorter); + AssignRoles(CTeamAiRole::ETeamAiRole::Melee, x34_data.x4_meleeCount); + AssignRoles(CTeamAiRole::ETeamAiRole::Projectile, x34_data.x8_projectileCount); + AssignRoles(CTeamAiRole::ETeamAiRole::Unknown, x34_data.xc_unknownCount); + for (auto& role : x58_roles) { + if (role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Initial || + role.GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Unassigned) + role.SetTeamAiRole(CTeamAiRole::ETeamAiRole::Unassigned); + } + TeamAiRoleSorter sorter2(aimPos, 0); + std::sort(x58_roles.begin(), x58_roles.end(), sorter2); + x88_timeDirty = 0.f; +} + +void CTeamAiMgr::Think(float dt, CStateManager& mgr) { + CEntity::Think(dt, mgr); + if (ShouldUpdateRoles(dt)) + UpdateRoles(mgr); + PositionTeam(mgr); + x90_timeSinceMelee += dt; + x94_timeSinceProjectile += dt; +} + +void CTeamAiMgr::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) { + CEntity::AcceptScriptMsg(msg, objId, mgr); +} + +CTeamAiRole* CTeamAiMgr::GetTeamAiRole(TUniqueId aiId) { + auto search = + rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, [](const auto& obj) { return obj.GetOwnerId(); }); + return search != x58_roles.end() ? &*search : nullptr; +} + +bool CTeamAiMgr::IsPartOfTeam(TUniqueId aiId) const { + auto search = + rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, [](const auto& obj) { return obj.GetOwnerId(); }); + return search != x58_roles.end(); +} + +bool CTeamAiMgr::HasTeamAiRole(TUniqueId aiId) const { + auto search = + rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, [](const auto& obj) { return obj.GetOwnerId(); }); + return (search != x58_roles.end() && search->GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Initial && + search->GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Unassigned); +} + +bool CTeamAiMgr::IsMeleeAttacker(TUniqueId aiId) const { + auto search = rstl::binary_find(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId); + return search != x68_meleeAttackers.end(); +} + +bool CTeamAiMgr::CanAcceptMeleeAttacker(TUniqueId aiId) const { + if (x90_timeSinceMelee >= x34_data.x1c_meleeTimeInterval && + x68_meleeAttackers.size() < x34_data.x10_maxMeleeAttackerCount) + return true; + return IsMeleeAttacker(aiId); +} + +bool CTeamAiMgr::AddMeleeAttacker(TUniqueId aiId) { + if (x90_timeSinceMelee >= x34_data.x1c_meleeTimeInterval && + x68_meleeAttackers.size() < x34_data.x10_maxMeleeAttackerCount && HasTeamAiRole(aiId)) { + auto search = rstl::binary_find(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId); + if (search == x68_meleeAttackers.end()) { + x68_meleeAttackers.insert(std::lower_bound(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId), aiId); + x90_timeSinceMelee = 0.f; } - return kInvalidUniqueId; + return true; + } + return false; } +void CTeamAiMgr::RemoveMeleeAttacker(TUniqueId aiId) { + auto search = rstl::binary_find(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId); + if (search != x68_meleeAttackers.end()) + x68_meleeAttackers.erase(search); } + +bool CTeamAiMgr::IsProjectileAttacker(TUniqueId aiId) const { + auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId); + return search != x78_projectileAttackers.end(); +} + +bool CTeamAiMgr::CanAcceptProjectileAttacker(TUniqueId aiId) const { + if (x94_timeSinceProjectile >= x34_data.x20_projectileTimeInterval && + x78_projectileAttackers.size() < x34_data.x14_maxProjectileAttackerCount) + return true; + return IsProjectileAttacker(aiId); +} + +bool CTeamAiMgr::AddProjectileAttacker(TUniqueId aiId) { + if (x94_timeSinceProjectile >= x34_data.x20_projectileTimeInterval && + x78_projectileAttackers.size() < x34_data.x14_maxProjectileAttackerCount && HasTeamAiRole(aiId)) { + auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId); + if (search == x78_projectileAttackers.end()) { + x78_projectileAttackers.insert( + std::lower_bound(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId), aiId); + x94_timeSinceProjectile = 0.f; + } + return true; + } + return false; +} + +void CTeamAiMgr::RemoveProjectileAttacker(TUniqueId aiId) { + auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId); + if (search != x78_projectileAttackers.end()) + x78_projectileAttackers.erase(search); +} + +bool CTeamAiMgr::AssignTeamAiRole(const CAi& ai, CTeamAiRole::ETeamAiRole roleA, CTeamAiRole::ETeamAiRole roleB, + CTeamAiRole::ETeamAiRole roleC) { + CTeamAiRole newRole(ai.GetUniqueId(), roleA, roleB, roleC); + auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), newRole); + if (search == x58_roles.end()) { + if (x58_roles.size() >= x58_roles.capacity()) + return false; + x58_roles.insert(std::lower_bound(x58_roles.begin(), x58_roles.end(), newRole), newRole); + } else { + *search = newRole; + } + UpdateTeamCaptain(); + return true; +} + +void CTeamAiMgr::RemoveTeamAiRole(TUniqueId aiId) { + if (IsMeleeAttacker(aiId)) + RemoveMeleeAttacker(aiId); + if (IsProjectileAttacker(aiId)) + RemoveProjectileAttacker(aiId); + auto search = + rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, [](const auto& obj) { return obj.GetOwnerId(); }); + x58_roles.erase(search); + UpdateTeamCaptain(); +} + +void CTeamAiMgr::ClearTeamAiRole(TUniqueId aiId) { + auto search = + rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, [](const auto& obj) { return obj.GetOwnerId(); }); + if (search != x58_roles.end()) + search->x10_curRole = CTeamAiRole::ETeamAiRole::Initial; +} + +s32 CTeamAiMgr::GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole testRole) const { + s32 ret = 0; + for (const auto& role : x58_roles) + if (role.GetTeamAiRole() == testRole) + ++ret; + return ret; +} + +s32 CTeamAiMgr::GetNumAssignedAiRoles() const { + s32 ret = 0; + for (const auto& role : x58_roles) + if (role.GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Initial && + role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Unassigned) + ++ret; + return ret; +} + +CTeamAiRole* CTeamAiMgr::GetTeamAiRole(CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId) { + if (TCastToPtr aimgr = mgr.ObjectById(mgrId)) + return aimgr->GetTeamAiRole(aiId); + return nullptr; +} + +void CTeamAiMgr::ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId, + bool clearRole) { + if (TCastToPtr tmgr = mgr.ObjectById(mgrId)) { + if (tmgr->HasTeamAiRole(aiId)) { + if (type == EAttackType::Melee) { + if (tmgr->IsMeleeAttacker(aiId)) + tmgr->RemoveMeleeAttacker(aiId); + } else if (type == EAttackType::Projectile) { + if (tmgr->IsProjectileAttacker(aiId)) + tmgr->RemoveProjectileAttacker(aiId); + } + if (clearRole) + tmgr->ClearTeamAiRole(aiId); + } + } +} + +bool CTeamAiMgr::CanAcceptAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId) { + if (TCastToPtr tmgr = mgr.ObjectById(mgrId)) { + if (tmgr->HasTeamAiRole(aiId)) { + if (type == EAttackType::Melee) + return tmgr->CanAcceptMeleeAttacker(aiId); + else if (type == EAttackType::Projectile) + return tmgr->CanAcceptProjectileAttacker(aiId); + } + } + return false; +} + +bool CTeamAiMgr::AddAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId) { + if (TCastToPtr tmgr = mgr.ObjectById(mgrId)) { + if (tmgr->HasTeamAiRole(aiId)) { + if (type == EAttackType::Melee) + return tmgr->AddMeleeAttacker(aiId); + else if (type == EAttackType::Projectile) + return tmgr->AddProjectileAttacker(aiId); + } + } + return false; +} + +TUniqueId CTeamAiMgr::GetTeamAiMgr(CAi& ai, CStateManager& mgr) { + for (const auto& conn : ai.GetConnectionList()) { + if (conn.x0_state == EScriptObjectState::Active && conn.x4_msg == EScriptObjectMessage::Play) { + TUniqueId id = mgr.GetIdForScript(conn.x8_objId); + if (TCastToConstPtr aimgr = mgr.GetObjectById(id)) + return aimgr->GetUniqueId(); + } + } + return kInvalidUniqueId; +} + +} // namespace urde diff --git a/Runtime/World/CTeamAiMgr.hpp b/Runtime/World/CTeamAiMgr.hpp index f533263d3..17f51637f 100644 --- a/Runtime/World/CTeamAiMgr.hpp +++ b/Runtime/World/CTeamAiMgr.hpp @@ -3,119 +3,107 @@ #include "CEntity.hpp" #include "zeus/CVector3f.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CAi; -class CTeamAiRole -{ - friend class CTeamAiMgr; +class CTeamAiRole { + friend class CTeamAiMgr; + public: - enum class ETeamAiRole - { - Invalid = -1, - Initial, - Melee, - Projectile, - Unknown, - Unassigned - }; + enum class ETeamAiRole { Invalid = -1, Initial, Melee, Projectile, Unknown, Unassigned }; + private: - TUniqueId x0_ownerId; - ETeamAiRole x4_roleA = ETeamAiRole::Invalid; - ETeamAiRole x8_roleB = ETeamAiRole::Invalid; - ETeamAiRole xc_roleC = ETeamAiRole::Invalid; - ETeamAiRole x10_curRole = ETeamAiRole::Invalid; - s32 x14_roleIndex = -1; - s32 x18_captainPriority = 0; - zeus::CVector3f x1c_position; + TUniqueId x0_ownerId; + ETeamAiRole x4_roleA = ETeamAiRole::Invalid; + ETeamAiRole x8_roleB = ETeamAiRole::Invalid; + ETeamAiRole xc_roleC = ETeamAiRole::Invalid; + ETeamAiRole x10_curRole = ETeamAiRole::Invalid; + s32 x14_roleIndex = -1; + s32 x18_captainPriority = 0; + zeus::CVector3f x1c_position; + public: - CTeamAiRole(TUniqueId ownerId, ETeamAiRole a, ETeamAiRole b, ETeamAiRole c) - : x0_ownerId(ownerId), x4_roleA(a), x8_roleB(b), xc_roleC(c) {} - TUniqueId GetOwnerId() const { return x0_ownerId; } - bool HasTeamAiRole() const { return false; } - ETeamAiRole GetTeamAiRole() const { return x10_curRole; } - void SetTeamAiRole(ETeamAiRole role) { x10_curRole = role; } - s32 GetRoleIndex() const { return x14_roleIndex; } - void SetRoleIndex(s32 idx) { x14_roleIndex = idx; } - const zeus::CVector3f& GetTeamPosition() const { return x1c_position; } - void SetTeamPosition(const zeus::CVector3f& pos) { x1c_position = pos; } - bool operator<(const CTeamAiRole& other) const { return x0_ownerId < other.x0_ownerId; } + CTeamAiRole(TUniqueId ownerId, ETeamAiRole a, ETeamAiRole b, ETeamAiRole c) + : x0_ownerId(ownerId), x4_roleA(a), x8_roleB(b), xc_roleC(c) {} + TUniqueId GetOwnerId() const { return x0_ownerId; } + bool HasTeamAiRole() const { return false; } + ETeamAiRole GetTeamAiRole() const { return x10_curRole; } + void SetTeamAiRole(ETeamAiRole role) { x10_curRole = role; } + s32 GetRoleIndex() const { return x14_roleIndex; } + void SetRoleIndex(s32 idx) { x14_roleIndex = idx; } + const zeus::CVector3f& GetTeamPosition() const { return x1c_position; } + void SetTeamPosition(const zeus::CVector3f& pos) { x1c_position = pos; } + bool operator<(const CTeamAiRole& other) const { return x0_ownerId < other.x0_ownerId; } }; -class CTeamAiData -{ - friend class CTeamAiMgr; - u32 x0_aiCount; - u32 x4_meleeCount; - u32 x8_projectileCount; - u32 xc_unknownCount; - u32 x10_maxMeleeAttackerCount; - u32 x14_maxProjectileAttackerCount; - u32 x18_positionMode; - float x1c_meleeTimeInterval; - float x20_projectileTimeInterval; +class CTeamAiData { + friend class CTeamAiMgr; + u32 x0_aiCount; + u32 x4_meleeCount; + u32 x8_projectileCount; + u32 xc_unknownCount; + u32 x10_maxMeleeAttackerCount; + u32 x14_maxProjectileAttackerCount; + u32 x18_positionMode; + float x1c_meleeTimeInterval; + float x20_projectileTimeInterval; + public: - CTeamAiData(CInputStream& in, s32 propCount); + CTeamAiData(CInputStream& in, s32 propCount); }; -class CTeamAiMgr : public CEntity -{ +class CTeamAiMgr : public CEntity { public: - enum class EAttackType - { - Melee, - Projectile - }; + enum class EAttackType { Melee, Projectile }; + private: - CTeamAiData x34_data; - std::vector x58_roles; - std::vector x68_meleeAttackers; - std::vector x78_projectileAttackers; - float x88_timeDirty = 0.f; - TUniqueId x8c_teamCaptainId = kInvalidUniqueId; - float x90_timeSinceMelee; - float x94_timeSinceProjectile; + CTeamAiData x34_data; + std::vector x58_roles; + std::vector x68_meleeAttackers; + std::vector x78_projectileAttackers; + float x88_timeDirty = 0.f; + TUniqueId x8c_teamCaptainId = kInvalidUniqueId; + float x90_timeSinceMelee; + float x94_timeSinceProjectile; - void UpdateTeamCaptain(); - bool ShouldUpdateRoles(float dt); - void ResetRoles(CStateManager& mgr); - void AssignRoles(CTeamAiRole::ETeamAiRole role, s32 count); - void UpdateRoles(CStateManager& mgr); - void SpacingSort(CStateManager& mgr, const zeus::CVector3f& pos); - void PositionTeam(CStateManager& mgr); - bool IsMeleeAttacker(TUniqueId aiId) const; - bool CanAcceptMeleeAttacker(TUniqueId aiId) const; - bool AddMeleeAttacker(TUniqueId aiId); - void RemoveMeleeAttacker(TUniqueId aiId); - bool IsProjectileAttacker(TUniqueId aiId) const; - bool CanAcceptProjectileAttacker(TUniqueId aiId) const; - bool AddProjectileAttacker(TUniqueId aiId); - void RemoveProjectileAttacker(TUniqueId aiId); + void UpdateTeamCaptain(); + bool ShouldUpdateRoles(float dt); + void ResetRoles(CStateManager& mgr); + void AssignRoles(CTeamAiRole::ETeamAiRole role, s32 count); + void UpdateRoles(CStateManager& mgr); + void SpacingSort(CStateManager& mgr, const zeus::CVector3f& pos); + void PositionTeam(CStateManager& mgr); + bool IsMeleeAttacker(TUniqueId aiId) const; + bool CanAcceptMeleeAttacker(TUniqueId aiId) const; + bool AddMeleeAttacker(TUniqueId aiId); + void RemoveMeleeAttacker(TUniqueId aiId); + bool IsProjectileAttacker(TUniqueId aiId) const; + bool CanAcceptProjectileAttacker(TUniqueId aiId) const; + bool AddProjectileAttacker(TUniqueId aiId); + void RemoveProjectileAttacker(TUniqueId aiId); public: - CTeamAiMgr(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CTeamAiData& data); + CTeamAiMgr(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CTeamAiData& data); - void Accept(IVisitor&); - void Think(float dt, CStateManager& mgr); - void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr); - CTeamAiRole* GetTeamAiRole(TUniqueId aiId); - bool IsPartOfTeam(TUniqueId aiId) const; - bool HasTeamAiRole(TUniqueId aiId) const; - bool AssignTeamAiRole(const CAi& ai, CTeamAiRole::ETeamAiRole roleA, - CTeamAiRole::ETeamAiRole roleB, CTeamAiRole::ETeamAiRole roleC); - void RemoveTeamAiRole(TUniqueId aiId); - void ClearTeamAiRole(TUniqueId aiId); - s32 GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole role) const; - s32 GetNumAssignedAiRoles() const; + void Accept(IVisitor&); + void Think(float dt, CStateManager& mgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr); + CTeamAiRole* GetTeamAiRole(TUniqueId aiId); + bool IsPartOfTeam(TUniqueId aiId) const; + bool HasTeamAiRole(TUniqueId aiId) const; + bool AssignTeamAiRole(const CAi& ai, CTeamAiRole::ETeamAiRole roleA, CTeamAiRole::ETeamAiRole roleB, + CTeamAiRole::ETeamAiRole roleC); + void RemoveTeamAiRole(TUniqueId aiId); + void ClearTeamAiRole(TUniqueId aiId); + s32 GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole role) const; + s32 GetNumAssignedAiRoles() const; - static CTeamAiRole* GetTeamAiRole(CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId); - static void ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId, bool clearRole); - static bool CanAcceptAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId); - static bool AddAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId); + static CTeamAiRole* GetTeamAiRole(CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId); + static void ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId, bool clearRole); + static bool CanAcceptAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId); + static bool AddAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId); - static TUniqueId GetTeamAiMgr(CAi& ai, CStateManager& mgr); + static TUniqueId GetTeamAiMgr(CAi& ai, CStateManager& mgr); }; -} - +} // namespace urde diff --git a/Runtime/World/CTeamAiTypes.hpp b/Runtime/World/CTeamAiTypes.hpp index a0e4c3a56..1b1cc9dbf 100644 --- a/Runtime/World/CTeamAiTypes.hpp +++ b/Runtime/World/CTeamAiTypes.hpp @@ -1,11 +1,7 @@ #pragma once -namespace urde -{ +namespace urde { -class CTeamAiTypes -{ -}; - -} +class CTeamAiTypes {}; +} // namespace urde diff --git a/Runtime/World/CVisorFlare.cpp b/Runtime/World/CVisorFlare.cpp index fc1ffa8ee..3bcd70da0 100644 --- a/Runtime/World/CVisorFlare.cpp +++ b/Runtime/World/CVisorFlare.cpp @@ -2,41 +2,38 @@ #include "CSimplePool.hpp" #include "GameGlobalObjects.hpp" -namespace urde -{ +namespace urde { -std::experimental::optional CVisorFlare::LoadFlareDef(CInputStream& in) -{ - u32 propCount = in.readUint32Big(); - if (propCount != 4) - return {}; +std::experimental::optional CVisorFlare::LoadFlareDef(CInputStream& in) { + u32 propCount = in.readUint32Big(); + if (propCount != 4) + return {}; - CAssetId txtrId = in.readUint32Big(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - zeus::CColor color = zeus::CColor::ReadRGBABig(in); - if (!txtrId.IsValid()) - return {}; + CAssetId txtrId = in.readUint32Big(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + zeus::CColor color = zeus::CColor::ReadRGBABig(in); + if (!txtrId.IsValid()) + return {}; - TToken tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), txtrId}); + TToken tex = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), txtrId}); - return CFlareDef(tex, f1, f2, color); + return CFlareDef(tex, f1, f2, color); } CVisorFlare::CVisorFlare(EBlendMode blendMode, bool b1, float f1, float f2, float f3, u32 w1, u32 w2, const std::vector& flares) -: x0_blendMode(blendMode), x4_flareDefs(flares), x14_b1(b1), x18_f1(std::max(f1, 0.0001f)), - x1c_f2(f2), x20_f3(f3), x2c_w1(w1), x30_w2(w2) -{} +: x0_blendMode(blendMode) +, x4_flareDefs(flares) +, x14_b1(b1) +, x18_f1(std::max(f1, 0.0001f)) +, x1c_f2(f2) +, x20_f3(f3) +, x2c_w1(w1) +, x30_w2(w2) {} -void CVisorFlare::Update(float dt, const zeus::CVector3f& pos, const CActor* act, CStateManager& mgr) -{ +void CVisorFlare::Update(float dt, const zeus::CVector3f& pos, const CActor* act, CStateManager& mgr) {} -} +void CVisorFlare::Render(const zeus::CVector3f& pos, const CStateManager& mgr) const {} -void CVisorFlare::Render(const zeus::CVector3f& pos, const CStateManager& mgr) const -{ - -} - -} +} // namespace urde diff --git a/Runtime/World/CVisorFlare.hpp b/Runtime/World/CVisorFlare.hpp index 1ad251ea5..a606dda7e 100644 --- a/Runtime/World/CVisorFlare.hpp +++ b/Runtime/World/CVisorFlare.hpp @@ -4,52 +4,51 @@ #include "CToken.hpp" #include "zeus/CColor.hpp" -namespace urde -{ +namespace urde { class CTexture; class CActor; class CStateManager; -class CVisorFlare -{ +class CVisorFlare { public: - enum class EBlendMode - { + enum class EBlendMode { - }; - class CFlareDef - { - TToken x0_tex; - float x8_f1; - float xc_f2; - zeus::CColor x10_color; - public: - CFlareDef(const TToken& tex, float f1, float f2, const zeus::CColor& color) - : x0_tex(tex), x8_f1(f1), xc_f2(f2), x10_color(color) { x0_tex.Lock(); } + }; + class CFlareDef { + TToken x0_tex; + float x8_f1; + float xc_f2; + zeus::CColor x10_color; + + public: + CFlareDef(const TToken& tex, float f1, float f2, const zeus::CColor& color) + : x0_tex(tex), x8_f1(f1), xc_f2(f2), x10_color(color) { + x0_tex.Lock(); + } + + TToken GetTexture() const; + zeus::CColor GetColor() { return x10_color; } + float GetScale() const; + float GetPosition() const; + }; - TToken GetTexture() const; - zeus::CColor GetColor() { return x10_color; } - float GetScale() const; - float GetPosition() const; - }; private: - EBlendMode x0_blendMode; - std::vector x4_flareDefs; - bool x14_b1; - float x18_f1; - float x1c_f2; - float x20_f3; - float x24_ = 0.f; - float x28_ = 0.f; - u32 x2c_w1; - u32 x30_w2; + EBlendMode x0_blendMode; + std::vector x4_flareDefs; + bool x14_b1; + float x18_f1; + float x1c_f2; + float x20_f3; + float x24_ = 0.f; + float x28_ = 0.f; + u32 x2c_w1; + u32 x30_w2; + public: - CVisorFlare(EBlendMode blendMode, bool, float, float, float, u32, u32, - const std::vector& flares); - void Update(float dt, const zeus::CVector3f& pos, const CActor* act, CStateManager& mgr); - void Render(const zeus::CVector3f& pos, const CStateManager& mgr) const; - static std::experimental::optional LoadFlareDef(CInputStream& in); + CVisorFlare(EBlendMode blendMode, bool, float, float, float, u32, u32, const std::vector& flares); + void Update(float dt, const zeus::CVector3f& pos, const CActor* act, CStateManager& mgr); + void Render(const zeus::CVector3f& pos, const CStateManager& mgr) const; + static std::experimental::optional LoadFlareDef(CInputStream& in); }; -} - +} // namespace urde diff --git a/Runtime/World/CVisorParameters.hpp b/Runtime/World/CVisorParameters.hpp index af2900fb7..95b4576fc 100644 --- a/Runtime/World/CVisorParameters.hpp +++ b/Runtime/World/CVisorParameters.hpp @@ -2,21 +2,17 @@ #include "RetroTypes.hpp" -namespace urde -{ +namespace urde { -class CVisorParameters -{ +class CVisorParameters { public: - u8 x0_mask : 4; - bool x0_4_b1 : 1; - bool x0_5_scanPassthrough : 1; - CVisorParameters() - : x0_mask(0xf), x0_4_b1(false), x0_5_scanPassthrough(false) {} - CVisorParameters(u8 mask, bool b1, bool scanPassthrough) - : x0_mask(mask), x0_4_b1(b1), x0_5_scanPassthrough(scanPassthrough) {} - u8 GetMask() const { return x0_mask; } + u8 x0_mask : 4; + bool x0_4_b1 : 1; + bool x0_5_scanPassthrough : 1; + CVisorParameters() : x0_mask(0xf), x0_4_b1(false), x0_5_scanPassthrough(false) {} + CVisorParameters(u8 mask, bool b1, bool scanPassthrough) + : x0_mask(mask), x0_4_b1(b1), x0_5_scanPassthrough(scanPassthrough) {} + u8 GetMask() const { return x0_mask; } }; -} - +} // namespace urde diff --git a/Runtime/World/CWallCrawlerSwarm.cpp b/Runtime/World/CWallCrawlerSwarm.cpp index 013b91eaf..213a047ef 100644 --- a/Runtime/World/CWallCrawlerSwarm.cpp +++ b/Runtime/World/CWallCrawlerSwarm.cpp @@ -3,13 +3,11 @@ #include "Collision/CMaterialList.hpp" #include "TCastTo.hpp" -namespace urde -{ +namespace urde { -static CMaterialList MakeMaterialList() -{ - return CMaterialList(EMaterialTypes::Scannable, EMaterialTypes::Trigger, EMaterialTypes::NonSolidDamageable, - EMaterialTypes::ExcludeFromLineOfSightTest); +static CMaterialList MakeMaterialList() { + return CMaterialList(EMaterialTypes::Scannable, EMaterialTypes::Trigger, EMaterialTypes::NonSolidDamageable, + EMaterialTypes::ExcludeFromLineOfSightTest); } CWallCrawlerSwarm::CWallCrawlerSwarm(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info, @@ -18,10 +16,8 @@ CWallCrawlerSwarm::CWallCrawlerSwarm(TUniqueId uid, bool active, std::string_vie float, u32, u32, float, float, float, float, float, float, float, float, float, u32, float, float, float, const CHealthInfo&, const CDamageVulnerability&, u32, u32, const CActorParameters& aParams) -: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), MakeMaterialList(), aParams, kInvalidUniqueId) -{ -} +: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), MakeMaterialList(), aParams, kInvalidUniqueId) {} void CWallCrawlerSwarm::Accept(IVisitor& visitor) { visitor.Visit(this); } -} +} // namespace urde diff --git a/Runtime/World/CWallCrawlerSwarm.hpp b/Runtime/World/CWallCrawlerSwarm.hpp index 12904cd12..45a61c50d 100644 --- a/Runtime/World/CWallCrawlerSwarm.hpp +++ b/Runtime/World/CWallCrawlerSwarm.hpp @@ -3,76 +3,65 @@ #include "World/CActor.hpp" #include "Collision/CCollisionSurface.hpp" -namespace urde -{ -class CWallCrawlerSwarm : public CActor -{ +namespace urde { +class CWallCrawlerSwarm : public CActor { public: - class CBoid - { - zeus::CTransform x0_; - float x30_ = 0.f; - float x34_ = 0.f; - float x38_ = 0.f; - TUniqueId x3c_ = kInvalidUniqueId; - zeus::CColor x40_ = zeus::CColor(0.3f, 0.3f, 0.3f, 1.f); - u32 x44_ = 0; - float x48_ = 0.f; - float x4c_ = 0.f; - CCollisionSurface x50_ = CCollisionSurface(zeus::CVector3f(0.f, 0.f, 1.f), zeus::CVector3f(0.f, 1.f, 0.f), - zeus::CVector3f(1.f, 0.f, 0.f), -1); - union - { - struct - { - u32 x7c_unk1 : 8; - u32 x7c_unk2 : 10; - }; - u32 x7c_; - }; - - union - { - struct - { - bool x80_24_active : 1; - bool x80_25_ : 1; - bool x80_26_ : 1; - bool x80_27_ : 1; - bool x80_28_ : 1; - }; - u32 x80_; - }; - - public: - const zeus::CTransform& GetTransform() const { return x0_; } - const zeus::CVector3f& GetTranslation() const { return x0_.origin; } - bool GetActive() const { return x80_24_active; } + class CBoid { + zeus::CTransform x0_; + float x30_ = 0.f; + float x34_ = 0.f; + float x38_ = 0.f; + TUniqueId x3c_ = kInvalidUniqueId; + zeus::CColor x40_ = zeus::CColor(0.3f, 0.3f, 0.3f, 1.f); + u32 x44_ = 0; + float x48_ = 0.f; + float x4c_ = 0.f; + CCollisionSurface x50_ = CCollisionSurface(zeus::CVector3f(0.f, 0.f, 1.f), zeus::CVector3f(0.f, 1.f, 0.f), + zeus::CVector3f(1.f, 0.f, 0.f), -1); + union { + struct { + u32 x7c_unk1 : 8; + u32 x7c_unk2 : 10; + }; + u32 x7c_; }; + union { + struct { + bool x80_24_active : 1; + bool x80_25_ : 1; + bool x80_26_ : 1; + bool x80_27_ : 1; + bool x80_28_ : 1; + }; + u32 x80_; + }; + + public: + const zeus::CTransform& GetTransform() const { return x0_; } + const zeus::CVector3f& GetTranslation() const { return x0_.origin; } + bool GetActive() const { return x80_24_active; } + }; + private: - zeus::CAABox xe8_aabox = zeus::CAABox::skNullBox; - std::vector x108_boids; - zeus::CVector3f x130_lastKilledOffset; - int x42c_lockOnId = -1; + zeus::CAABox xe8_aabox = zeus::CAABox::skNullBox; + std::vector x108_boids; + zeus::CVector3f x130_lastKilledOffset; + int x42c_lockOnId = -1; public: - CWallCrawlerSwarm(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, - const zeus::CTransform&, u32, const CAnimRes&, u32, u32, u32, u32, u32, u32, const CDamageInfo&, - const CDamageInfo&, float, float, float, float, u32, u32, float, float, float, float, float, - float, float, float, float, u32, float, float, float, const CHealthInfo&, const CDamageVulnerability&, - u32, u32, const CActorParameters&); + CWallCrawlerSwarm(TUniqueId, bool, std::string_view, const CEntityInfo&, const zeus::CVector3f&, + const zeus::CTransform&, u32, const CAnimRes&, u32, u32, u32, u32, u32, u32, const CDamageInfo&, + const CDamageInfo&, float, float, float, float, u32, u32, float, float, float, float, float, float, + float, float, float, u32, float, float, float, const CHealthInfo&, const CDamageVulnerability&, u32, + u32, const CActorParameters&); - void Accept(IVisitor &visitor); - zeus::CVector3f GetLastKilledOffset() const { return x130_lastKilledOffset; } - void ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, - CStateManager& stateMgr) {} - const std::vector& GetBoids() const { return x108_boids; } - int GetCurrentLockOnId() const { return x42c_lockOnId; } - bool GetLockOnLocationValid(int id) const - { return id >= 0 && id < x108_boids.size() && x108_boids[id].GetActive(); } - const zeus::CVector3f& GetLockOnLocation(int id) const - { return x108_boids[id].GetTranslation(); } + void Accept(IVisitor& visitor); + zeus::CVector3f GetLastKilledOffset() const { return x130_lastKilledOffset; } + void ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& stateMgr) {} + const std::vector& GetBoids() const { return x108_boids; } + int GetCurrentLockOnId() const { return x42c_lockOnId; } + bool GetLockOnLocationValid(int id) const { return id >= 0 && id < x108_boids.size() && x108_boids[id].GetActive(); } + const zeus::CVector3f& GetLockOnLocation(int id) const { return x108_boids[id].GetTranslation(); } }; -} - +} // namespace urde diff --git a/Runtime/World/CWallWalker.cpp b/Runtime/World/CWallWalker.cpp index a82625bcb..1c0eed7f4 100644 --- a/Runtime/World/CWallWalker.cpp +++ b/Runtime/World/CWallWalker.cpp @@ -6,216 +6,177 @@ #include "Collision/CMetroidAreaCollider.hpp" #include "Collision/CGameCollision.hpp" -namespace urde -{ +namespace urde { CWallWalker::CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, EFlavorType flavType, - const CEntityInfo& eInfo, const zeus::CTransform& xf, - CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType, - EColliderType colType, EBodyType bType, const CActorParameters& aParms, - float collisionCloseMargin, float alignAngVel, EKnockBackVariant kbVariant, - float advanceWpRadius, EWalkerType wType, float playerObstructionMinDist, bool disableMove) + const CEntityInfo& eInfo, const zeus::CTransform& xf, CModelData&& mData, + const CPatternedInfo& pInfo, EMovementType mType, EColliderType colType, EBodyType bType, + const CActorParameters& aParms, float collisionCloseMargin, float alignAngVel, + EKnockBackVariant kbVariant, float advanceWpRadius, EWalkerType wType, + float playerObstructionMinDist, bool disableMove) : CPatterned(chr, uid, name, flavType, eInfo, xf, std::move(mData), pInfo, mType, colType, bType, aParms, kbVariant) , x590_colSphere(zeus::CSphere(zeus::CVector3f::skZero, pInfo.GetHalfExtent()), x68_material) , x5b0_collisionCloseMargin(collisionCloseMargin) , x5b4_alignAngVel(alignAngVel) , x5c0_advanceWpRadius(advanceWpRadius) , x5c4_playerObstructionMinDist(playerObstructionMinDist) -, x5cc_bendingHackAnim(GetModelData()->GetAnimationData()->GetCharacterInfo().GetAnimationIndex("BendingAnimationHack"sv)) +, x5cc_bendingHackAnim( + GetModelData()->GetAnimationData()->GetCharacterInfo().GetAnimationIndex("BendingAnimationHack"sv)) , x5d0_walkerType(wType) , x5d6_24_alignToFloor(false) , x5d6_25_hasAlignSurface(false) , x5d6_26_playerObstructed(false) , x5d6_27_disableMove(disableMove) , x5d6_28_addBendingWeight(true) -, x5d6_29_applyBendingHack(false) -{ +, x5d6_29_applyBendingHack(false) {} + +void CWallWalker::OrientToSurfaceNormal(const zeus::CVector3f& normal, float clampAngle) { + float dot = x34_transform.basis[2].dot(normal); + if (zeus::close_enough(dot, 1.f) || dot < -0.999f) + return; + zeus::CQuaternion q = zeus::CQuaternion::clampedRotateTo(x34_transform.basis[2], normal, zeus::degToRad(clampAngle)); + q.setImaginary(x34_transform.transposeRotate(q.getImaginary())); + SetTransform((zeus::CQuaternion(x34_transform.basis) * q).normalized().toTransform(GetTranslation())); } -void CWallWalker::OrientToSurfaceNormal(const zeus::CVector3f& normal, float clampAngle) -{ - float dot = x34_transform.basis[2].dot(normal); - if (zeus::close_enough(dot, 1.f) || dot < -0.999f) - return; - zeus::CQuaternion q = - zeus::CQuaternion::clampedRotateTo(x34_transform.basis[2], normal, zeus::degToRad(clampAngle)); - q.setImaginary(x34_transform.transposeRotate(q.getImaginary())); - SetTransform((zeus::CQuaternion(x34_transform.basis) * q).normalized().toTransform(GetTranslation())); +bool CWallWalker::PointOnSurface(const CCollisionSurface& surf, const zeus::CVector3f& point) { + zeus::CVector3f normal = surf.GetNormal(); + zeus::CVector3f projPt = ProjectPointToPlane(point, surf.GetVert(0), normal); + for (int i = 0; i < 3; ++i) { + zeus::CVector3f projDelta = projPt - surf.GetVert(i); + zeus::CVector3f edge = surf.GetVert((i + 2) % 3) - surf.GetVert(i); + if (projDelta.cross(edge).dot(normal) < 0.f) + return false; + } + return true; } -bool CWallWalker::PointOnSurface(const CCollisionSurface& surf, const zeus::CVector3f& point) -{ - zeus::CVector3f normal = surf.GetNormal(); - zeus::CVector3f projPt = ProjectPointToPlane(point, surf.GetVert(0), normal); - for (int i = 0; i < 3; ++i) - { - zeus::CVector3f projDelta = projPt - surf.GetVert(i); - zeus::CVector3f edge = surf.GetVert((i + 2) % 3) - surf.GetVert(i); - if (projDelta.cross(edge).dot(normal) < 0.f) - return false; - } - return true; -} - -void CWallWalker::AlignToFloor(CStateManager& mgr, float radius, const zeus::CVector3f& newPos, float dt) -{ - bool hasSurface = false; - float margin = radius + x5b0_collisionCloseMargin; - zeus::CAABox aabb(newPos - margin, newPos + margin); - CAreaCollisionCache ccache(aabb); - CGameCollision::BuildAreaCollisionCache(mgr, ccache); - if (x5d6_25_hasAlignSurface) - x5d6_25_hasAlignSurface = PointOnSurface(x568_alignNormal, newPos); - if (!x5d6_25_hasAlignSurface || !(x5d4_thinkCounter & 0x3)) - { - for (auto& leaf : ccache) - { - for (auto& node : leaf) - { - CAreaOctTree::TriListReference triArr = node.GetTriangleArray(); - for (u16 i = 0; i < triArr.GetSize(); ++i) - { - u16 triIdx = triArr.GetAt(i); - CCollisionSurface surf = leaf.GetOctTree().GetMasterListTriangle(triIdx); - if (std::fabs(surf.GetPlane().pointToPlaneDist(newPos)) < margin && - PointOnSurface(surf, newPos)) - { - x568_alignNormal = surf; - hasSurface = true; - } - } - } +void CWallWalker::AlignToFloor(CStateManager& mgr, float radius, const zeus::CVector3f& newPos, float dt) { + bool hasSurface = false; + float margin = radius + x5b0_collisionCloseMargin; + zeus::CAABox aabb(newPos - margin, newPos + margin); + CAreaCollisionCache ccache(aabb); + CGameCollision::BuildAreaCollisionCache(mgr, ccache); + if (x5d6_25_hasAlignSurface) + x5d6_25_hasAlignSurface = PointOnSurface(x568_alignNormal, newPos); + if (!x5d6_25_hasAlignSurface || !(x5d4_thinkCounter & 0x3)) { + for (auto& leaf : ccache) { + for (auto& node : leaf) { + CAreaOctTree::TriListReference triArr = node.GetTriangleArray(); + for (u16 i = 0; i < triArr.GetSize(); ++i) { + u16 triIdx = triArr.GetAt(i); + CCollisionSurface surf = leaf.GetOctTree().GetMasterListTriangle(triIdx); + if (std::fabs(surf.GetPlane().pointToPlaneDist(newPos)) < margin && PointOnSurface(surf, newPos)) { + x568_alignNormal = surf; + hasSurface = true; + } } - x5d6_25_hasAlignSurface = hasSurface; + } } - if (x5d6_25_hasAlignSurface) - { - OrientToSurfaceNormal(x568_alignNormal.GetNormal(), x5b4_alignAngVel * dt); - x5b8_tumbleAngle = 0.f; - x5d6_28_addBendingWeight = false; - } - else - { - float angDelta = zeus::radToDeg(x138_velocity.magnitude()) / x590_colSphere.GetSphere().radius * dt; - OrientToSurfaceNormal(x34_transform.basis[1], angDelta); - if (x450_bodyController->HasBodyState(pas::EAnimationState::Step)) - { - x450_bodyController->GetCommandMgr().DeliverCmd( - CBCStepCmd(pas::EStepDirection::Down, pas::EStepType::Normal)); - } - else - { - x5d6_28_addBendingWeight = true; - } - x5b8_tumbleAngle += angDelta; + x5d6_25_hasAlignSurface = hasSurface; + } + if (x5d6_25_hasAlignSurface) { + OrientToSurfaceNormal(x568_alignNormal.GetNormal(), x5b4_alignAngVel * dt); + x5b8_tumbleAngle = 0.f; + x5d6_28_addBendingWeight = false; + } else { + float angDelta = zeus::radToDeg(x138_velocity.magnitude()) / x590_colSphere.GetSphere().radius * dt; + OrientToSurfaceNormal(x34_transform.basis[1], angDelta); + if (x450_bodyController->HasBodyState(pas::EAnimationState::Step)) { + x450_bodyController->GetCommandMgr().DeliverCmd(CBCStepCmd(pas::EStepDirection::Down, pas::EStepType::Normal)); + } else { + x5d6_28_addBendingWeight = true; } + x5b8_tumbleAngle += angDelta; + } } -void CWallWalker::GotoNextWaypoint(CStateManager& mgr) -{ - if (TCastToPtr wp = mgr.ObjectById(x2dc_destObj)) - { - zeus::CVector3f wpPos = wp->GetTranslation(); - if ((wpPos - GetTranslation()).magSquared() < x5c0_advanceWpRadius * x5c0_advanceWpRadius) - { - x2dc_destObj = wp->NextWaypoint(mgr); - if (!zeus::close_enough(wp->GetPause(), 0.f)) - { - x5bc_patrolPauseRemTime = wp->GetPause(); - if (x5d0_walkerType == EWalkerType::Parasite) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); - } - mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived); - } - SetDestPos(wpPos); +void CWallWalker::GotoNextWaypoint(CStateManager& mgr) { + if (TCastToPtr wp = mgr.ObjectById(x2dc_destObj)) { + zeus::CVector3f wpPos = wp->GetTranslation(); + if ((wpPos - GetTranslation()).magSquared() < x5c0_advanceWpRadius * x5c0_advanceWpRadius) { + x2dc_destObj = wp->NextWaypoint(mgr); + if (!zeus::close_enough(wp->GetPause(), 0.f)) { + x5bc_patrolPauseRemTime = wp->GetPause(); + if (x5d0_walkerType == EWalkerType::Parasite) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + } + mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived); } + SetDestPos(wpPos); + } } -void CWallWalker::PreThink(float dt, CStateManager& mgr) -{ - CPatterned::PreThink(dt, mgr); - if (!GetActive() || x5d6_26_playerObstructed || x5bc_patrolPauseRemTime > 0.f || x5d6_27_disableMove || - x450_bodyController->IsFrozen() || !x5d6_24_alignToFloor) - return; +void CWallWalker::PreThink(float dt, CStateManager& mgr) { + CPatterned::PreThink(dt, mgr); + if (!GetActive() || x5d6_26_playerObstructed || x5bc_patrolPauseRemTime > 0.f || x5d6_27_disableMove || + x450_bodyController->IsFrozen() || !x5d6_24_alignToFloor) + return; - zeus::CQuaternion quat(GetTransform().buildMatrix3f()); - AddMotionState(PredictMotion(dt)); - zeus::CQuaternion quat2(GetTransform().buildMatrix3f()); - ClearForcesAndTorques(); - if (x5d6_25_hasAlignSurface) - { - zeus::CPlane plane = x568_alignNormal.GetPlane(); - const float futureDt = (10.f * dt); - SetTranslation(zeus::CVector3f::lerp(GetTranslation(), - GetTranslation() - (plane.pointToPlaneDist(GetTranslation()) - - x590_colSphere.GetSphere().radius - 0.01f) * plane.normal(), futureDt)); - } - MoveCollisionPrimitive(zeus::CVector3f::skZero); + zeus::CQuaternion quat(GetTransform().buildMatrix3f()); + AddMotionState(PredictMotion(dt)); + zeus::CQuaternion quat2(GetTransform().buildMatrix3f()); + ClearForcesAndTorques(); + if (x5d6_25_hasAlignSurface) { + zeus::CPlane plane = x568_alignNormal.GetPlane(); + const float futureDt = (10.f * dt); + SetTranslation(zeus::CVector3f::lerp( + GetTranslation(), + GetTranslation() - + (plane.pointToPlaneDist(GetTranslation()) - x590_colSphere.GetSphere().radius - 0.01f) * plane.normal(), + futureDt)); + } + MoveCollisionPrimitive(zeus::CVector3f::skZero); } -void CWallWalker::Think(float dt, CStateManager& mgr) -{ - if (!x450_bodyController->GetActive()) - x450_bodyController->Activate(mgr); - CPatterned::Think(dt, mgr); +void CWallWalker::Think(float dt, CStateManager& mgr) { + if (!x450_bodyController->GetActive()) + x450_bodyController->Activate(mgr); + CPatterned::Think(dt, mgr); - if (x5cc_bendingHackAnim == -1) - return; + if (x5cc_bendingHackAnim == -1) + return; - if (x5d6_28_addBendingWeight) - { - if (x5c8_bendingHackWeight < 1.f) - { - x5c8_bendingHackWeight += (dt * x138_velocity.magnitude()) / 0.6f; - if (x5c8_bendingHackWeight >= 1.f) - x5c8_bendingHackWeight = 1.f; - } - } - else if (x5c8_bendingHackWeight > 0.f) - { - x5c8_bendingHackWeight -= (dt * x138_velocity.magnitude()) / 1.5f; - if (x5c8_bendingHackWeight < 0.f) - x5c8_bendingHackWeight = 0.f; + if (x5d6_28_addBendingWeight) { + if (x5c8_bendingHackWeight < 1.f) { + x5c8_bendingHackWeight += (dt * x138_velocity.magnitude()) / 0.6f; + if (x5c8_bendingHackWeight >= 1.f) + x5c8_bendingHackWeight = 1.f; } + } else if (x5c8_bendingHackWeight > 0.f) { + x5c8_bendingHackWeight -= (dt * x138_velocity.magnitude()) / 1.5f; + if (x5c8_bendingHackWeight < 0.f) + x5c8_bendingHackWeight = 0.f; + } - if (x5c8_bendingHackWeight <= 0.f && !x5d6_29_applyBendingHack) - return; + if (x5c8_bendingHackWeight <= 0.f && !x5d6_29_applyBendingHack) + return; - if (x5c8_bendingHackWeight > 0.0001f) - { - ModelData()->AnimationData()->AddAdditiveAnimation(x5cc_bendingHackAnim, x5c8_bendingHackWeight, true, false); - x5d6_29_applyBendingHack = true; - } - else - { - ModelData()->AnimationData()->DelAdditiveAnimation(x5cc_bendingHackAnim); - x5d6_29_applyBendingHack = false; - } + if (x5c8_bendingHackWeight > 0.0001f) { + ModelData()->AnimationData()->AddAdditiveAnimation(x5cc_bendingHackAnim, x5c8_bendingHackWeight, true, false); + x5d6_29_applyBendingHack = true; + } else { + ModelData()->AnimationData()->DelAdditiveAnimation(x5cc_bendingHackAnim); + x5d6_29_applyBendingHack = false; + } } -void CWallWalker::Render(const CStateManager& mgr) const -{ - CPatterned::Render(mgr); -} +void CWallWalker::Render(const CStateManager& mgr) const { CPatterned::Render(mgr); } -void CWallWalker::UpdateWPDestination(CStateManager& mgr) -{ - if (TCastToPtr wp = mgr.ObjectById(x2dc_destObj)) - { - zeus::CVector3f wpPos = wp->GetTranslation(); - if ((wpPos - GetTranslation()).magSquared() < x5c0_advanceWpRadius * x5c0_advanceWpRadius) - { - x2dc_destObj = wp->NextWaypoint(mgr); - if (std::fabs(wp->GetPause()) > 0.00001f) - { - x5bc_patrolPauseRemTime = wp->GetPause(); - if (x5d0_walkerType == EWalkerType::Parasite) - x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); - mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived); - } - } - - SetDestPos(wpPos); +void CWallWalker::UpdateWPDestination(CStateManager& mgr) { + if (TCastToPtr wp = mgr.ObjectById(x2dc_destObj)) { + zeus::CVector3f wpPos = wp->GetTranslation(); + if ((wpPos - GetTranslation()).magSquared() < x5c0_advanceWpRadius * x5c0_advanceWpRadius) { + x2dc_destObj = wp->NextWaypoint(mgr); + if (std::fabs(wp->GetPause()) > 0.00001f) { + x5bc_patrolPauseRemTime = wp->GetPause(); + if (x5d0_walkerType == EWalkerType::Parasite) + x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); + mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived); + } } + + SetDestPos(wpPos); + } } -} +} // namespace urde diff --git a/Runtime/World/CWallWalker.hpp b/Runtime/World/CWallWalker.hpp index 207a7b375..a8a65b7f8 100644 --- a/Runtime/World/CWallWalker.hpp +++ b/Runtime/World/CWallWalker.hpp @@ -4,65 +4,54 @@ #include "Collision/CCollisionSurface.hpp" #include "Collision/CCollidableSphere.hpp" -namespace urde -{ -class CWallWalker : public CPatterned -{ +namespace urde { +class CWallWalker : public CPatterned { public: - enum class EWalkerType - { - Parasite = 0, - Oculus = 1, - Geemer = 2, - IceZoomer = 3, - Seedling = 4 - }; -protected: - CCollisionSurface x568_alignNormal = CCollisionSurface(zeus::CVector3f(), - zeus::CVector3f::skForward, - zeus::CVector3f::skRight, -1); - CCollidableSphere x590_colSphere; - float x5b0_collisionCloseMargin; - float x5b4_alignAngVel; - float x5b8_tumbleAngle = 0.f; - float x5bc_patrolPauseRemTime = 0.f; - float x5c0_advanceWpRadius; - float x5c4_playerObstructionMinDist; - float x5c8_bendingHackWeight = 0.f; - s32 x5cc_bendingHackAnim; - EWalkerType x5d0_walkerType; - s16 x5d4_thinkCounter = 0; - bool x5d6_24_alignToFloor : 1; - bool x5d6_25_hasAlignSurface : 1; - bool x5d6_26_playerObstructed : 1; - bool x5d6_27_disableMove : 1; - bool x5d6_28_addBendingWeight : 1; - bool x5d6_29_applyBendingHack : 1; - static zeus::CVector3f ProjectVectorToPlane(const zeus::CVector3f& pt, const zeus::CVector3f& plane) - { - return pt - plane * pt.dot(plane); - } - static zeus::CVector3f ProjectPointToPlane(const zeus::CVector3f& p0, const zeus::CVector3f& p1, - const zeus::CVector3f& plane) - { - return p0 - (p0 - p1).dot(plane) * plane; - } - void OrientToSurfaceNormal(const zeus::CVector3f& normal, float clampAngle); - static bool PointOnSurface(const CCollisionSurface& surf, const zeus::CVector3f& point); - void AlignToFloor(CStateManager&, float, const zeus::CVector3f&, float); - void GotoNextWaypoint(CStateManager& mgr); -public: - CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, EFlavorType flavType, - const CEntityInfo& eInfo, const zeus::CTransform& xf, - CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType, - EColliderType colType, EBodyType bType, const CActorParameters& aParms, - float collisionCloseMargin, float alignAngVel, EKnockBackVariant kbVariant, - float advanceWpRadius, EWalkerType wType, float playerObstructionMinDist, bool disableMove); + enum class EWalkerType { Parasite = 0, Oculus = 1, Geemer = 2, IceZoomer = 3, Seedling = 4 }; - void PreThink(float, CStateManager&); - void Think(float, CStateManager&); - void Render(const CStateManager&) const; - const CCollisionPrimitive* GetCollisionPrimitive() const { return &x590_colSphere; } - void UpdateWPDestination(CStateManager&); +protected: + CCollisionSurface x568_alignNormal = + CCollisionSurface(zeus::CVector3f(), zeus::CVector3f::skForward, zeus::CVector3f::skRight, -1); + CCollidableSphere x590_colSphere; + float x5b0_collisionCloseMargin; + float x5b4_alignAngVel; + float x5b8_tumbleAngle = 0.f; + float x5bc_patrolPauseRemTime = 0.f; + float x5c0_advanceWpRadius; + float x5c4_playerObstructionMinDist; + float x5c8_bendingHackWeight = 0.f; + s32 x5cc_bendingHackAnim; + EWalkerType x5d0_walkerType; + s16 x5d4_thinkCounter = 0; + bool x5d6_24_alignToFloor : 1; + bool x5d6_25_hasAlignSurface : 1; + bool x5d6_26_playerObstructed : 1; + bool x5d6_27_disableMove : 1; + bool x5d6_28_addBendingWeight : 1; + bool x5d6_29_applyBendingHack : 1; + static zeus::CVector3f ProjectVectorToPlane(const zeus::CVector3f& pt, const zeus::CVector3f& plane) { + return pt - plane * pt.dot(plane); + } + static zeus::CVector3f ProjectPointToPlane(const zeus::CVector3f& p0, const zeus::CVector3f& p1, + const zeus::CVector3f& plane) { + return p0 - (p0 - p1).dot(plane) * plane; + } + void OrientToSurfaceNormal(const zeus::CVector3f& normal, float clampAngle); + static bool PointOnSurface(const CCollisionSurface& surf, const zeus::CVector3f& point); + void AlignToFloor(CStateManager&, float, const zeus::CVector3f&, float); + void GotoNextWaypoint(CStateManager& mgr); + +public: + CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, EFlavorType flavType, const CEntityInfo& eInfo, + const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType, + EColliderType colType, EBodyType bType, const CActorParameters& aParms, float collisionCloseMargin, + float alignAngVel, EKnockBackVariant kbVariant, float advanceWpRadius, EWalkerType wType, + float playerObstructionMinDist, bool disableMove); + + void PreThink(float, CStateManager&); + void Think(float, CStateManager&); + void Render(const CStateManager&) const; + const CCollisionPrimitive* GetCollisionPrimitive() const { return &x590_colSphere; } + void UpdateWPDestination(CStateManager&); }; -} +} // namespace urde diff --git a/Runtime/World/CWorld.cpp b/Runtime/World/CWorld.cpp index 41952848a..73d8f4575 100644 --- a/Runtime/World/CWorld.cpp +++ b/Runtime/World/CWorld.cpp @@ -10,25 +10,21 @@ #include "Audio/CStreamAudioManager.hpp" #include "CScriptRoomAcoustics.hpp" -namespace urde -{ +namespace urde { -CWorld::CSoundGroupData::CSoundGroupData(int grpId, CAssetId agsc) : x0_groupId(grpId), x4_agscId(agsc) -{ - x1c_groupData = g_SimplePool->GetObj(SObjectTag{FOURCC('AGSC'), agsc}); +CWorld::CSoundGroupData::CSoundGroupData(int grpId, CAssetId agsc) : x0_groupId(grpId), x4_agscId(agsc) { + x1c_groupData = g_SimplePool->GetObj(SObjectTag{FOURCC('AGSC'), agsc}); } -CDummyWorld::CDummyWorld(CAssetId mlvlId, bool loadMap) : x4_loadMap(loadMap), xc_mlvlId(mlvlId) -{ - SObjectTag tag{FOURCC('MLVL'), mlvlId}; - x34_loadBuf.reset(new u8[g_ResFactory->ResourceSize(tag)]); - x30_loadToken = g_ResFactory->LoadResourceAsync(tag, x34_loadBuf.get()); +CDummyWorld::CDummyWorld(CAssetId mlvlId, bool loadMap) : x4_loadMap(loadMap), xc_mlvlId(mlvlId) { + SObjectTag tag{FOURCC('MLVL'), mlvlId}; + x34_loadBuf.reset(new u8[g_ResFactory->ResourceSize(tag)]); + x30_loadToken = g_ResFactory->LoadResourceAsync(tag, x34_loadBuf.get()); } -CDummyWorld::~CDummyWorld() -{ - if (x30_loadToken) - x30_loadToken->PostCancelRequest(); +CDummyWorld::~CDummyWorld() { + if (x30_loadToken) + x30_loadToken->PostCancelRequest(); } CAssetId CDummyWorld::IGetWorldAssetId() const { return xc_mlvlId; } @@ -45,145 +41,131 @@ const IGameArea* CDummyWorld::IGetAreaAlways(TAreaId id) const { return &x18_are TAreaId CDummyWorld::IGetCurrentAreaId() const { return x3c_curAreaId; } -TAreaId CDummyWorld::IGetAreaId(CAssetId id) const -{ - int ret = 0; - if (!id.IsValid()) - return kInvalidAreaId; - for (const CDummyGameArea& area : x18_areas) - { - if (area.xc_mrea == id) - return ret; - ++ret; - } +TAreaId CDummyWorld::IGetAreaId(CAssetId id) const { + int ret = 0; + if (!id.IsValid()) return kInvalidAreaId; + for (const CDummyGameArea& area : x18_areas) { + if (area.xc_mrea == id) + return ret; + ++ret; + } + return kInvalidAreaId; } -CWorld::CRelay::CRelay(CInputStream& in) -{ - x0_relay = in.readUint32Big(); - x4_target = in.readUint32Big(); - x8_msg = in.readUint16Big(); - xa_active = in.readBool(); +CWorld::CRelay::CRelay(CInputStream& in) { + x0_relay = in.readUint32Big(); + x4_target = in.readUint32Big(); + x8_msg = in.readUint16Big(); + xa_active = in.readBool(); } -std::vector CWorld::CRelay::ReadMemoryRelays(athena::io::MemoryReader& r) -{ - std::vector ret; - u32 count = r.readUint32Big(); - ret.reserve(count); - for (u32 i = 0; i < count; ++i) - ret.emplace_back(r); - return ret; +std::vector CWorld::CRelay::ReadMemoryRelays(athena::io::MemoryReader& r) { + std::vector ret; + u32 count = r.readUint32Big(); + ret.reserve(count); + for (u32 i = 0; i < count; ++i) + ret.emplace_back(r); + return ret; } -void CWorldLayers::ReadWorldLayers(athena::io::MemoryReader& r, int version, CAssetId mlvlId) -{ - if (version <= 14) - return; +void CWorldLayers::ReadWorldLayers(athena::io::MemoryReader& r, int version, CAssetId mlvlId) { + if (version <= 14) + return; - CWorldLayers ret; + CWorldLayers ret; + + u32 areaCount = r.readUint32Big(); + ret.m_areas.reserve(areaCount); + for (u32 i = 0; i < areaCount; ++i) { + ret.m_areas.emplace_back(); + ret.m_areas.back().m_layerCount = r.readUint32Big(); + ret.m_areas.back().m_layerBits = r.readUint64Big(); + } + + u32 nameCount = r.readUint32Big(); + ret.m_names.reserve(nameCount); + for (u32 i = 0; i < nameCount; ++i) + ret.m_names.push_back(r.readString()); + + areaCount = r.readUint32Big(); + for (u32 i = 0; i < areaCount; ++i) + ret.m_areas[i].m_startNameIdx = r.readUint32Big(); + + CWorldState& wldState = g_GameState->StateForWorld(mlvlId); + wldState.GetLayerState()->InitializeWorldLayers(ret.m_areas); +} + +bool CDummyWorld::ICheckWorldComplete() { + switch (x8_phase) { + case Phase::Loading: { + if (x30_loadToken && !x30_loadToken->IsComplete()) + return false; + x30_loadToken.reset(); + athena::io::MemoryReader r(x34_loadBuf.get(), UINT32_MAX, false); + r.readUint32Big(); + int version = r.readUint32Big(); + x10_strgId = r.readUint32Big(); + + if (version >= 15) + x14_savwId = r.readUint32Big(); + if (version >= 12) + r.readUint32Big(); + if (version >= 17) + CWorld::CRelay::ReadMemoryRelays(r); u32 areaCount = r.readUint32Big(); - ret.m_areas.reserve(areaCount); + r.readUint32Big(); + + x18_areas.reserve(areaCount); for (u32 i = 0; i < areaCount; ++i) - { - ret.m_areas.emplace_back(); - ret.m_areas.back().m_layerCount = r.readUint32Big(); - ret.m_areas.back().m_layerBits = r.readUint64Big(); - } + x18_areas.emplace_back(r, i, version); - u32 nameCount = r.readUint32Big(); - ret.m_names.reserve(nameCount); - for (u32 i = 0; i < nameCount; ++i) - ret.m_names.push_back(r.readString()); + x28_mapWorldId = r.readUint32Big(); + if (x4_loadMap) + x2c_mapWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('MAPW'), x28_mapWorldId}); - areaCount = r.readUint32Big(); - for (u32 i = 0; i < areaCount; ++i) - ret.m_areas[i].m_startNameIdx = r.readUint32Big(); + r.readByte(); + r.readUint32Big(); - CWorldState& wldState = g_GameState->StateForWorld(mlvlId); - wldState.GetLayerState()->InitializeWorldLayers(ret.m_areas); -} - -bool CDummyWorld::ICheckWorldComplete() -{ - switch (x8_phase) - { - case Phase::Loading: - { - if (x30_loadToken && !x30_loadToken->IsComplete()) - return false; - x30_loadToken.reset(); - athena::io::MemoryReader r(x34_loadBuf.get(), UINT32_MAX, false); + if (version > 10) { + u32 audioGroupCount = r.readUint32Big(); + for (u32 i = 0; i < audioGroupCount; ++i) { r.readUint32Big(); - int version = r.readUint32Big(); - x10_strgId = r.readUint32Big(); - - if (version >= 15) - x14_savwId = r.readUint32Big(); - if (version >= 12) - r.readUint32Big(); - if (version >= 17) - CWorld::CRelay::ReadMemoryRelays(r); - - u32 areaCount = r.readUint32Big(); r.readUint32Big(); - - x18_areas.reserve(areaCount); - for (u32 i = 0; i < areaCount; ++i) - x18_areas.emplace_back(r, i, version); - - x28_mapWorldId = r.readUint32Big(); - if (x4_loadMap) - x2c_mapWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('MAPW'), x28_mapWorldId}); - - r.readByte(); - r.readUint32Big(); - - if (version > 10) - { - u32 audioGroupCount = r.readUint32Big(); - for (u32 i = 0; i < audioGroupCount; ++i) - { - r.readUint32Big(); - r.readUint32Big(); - } - } - - if (version > 12) - r.readString(); - - CWorldLayers::ReadWorldLayers(r, version, xc_mlvlId); - - if (x4_loadMap) - x8_phase = Phase::LoadingMap; - else - { - x8_phase = Phase::Done; - return false; - } + } } - case Phase::LoadingMap: - { - if (!x2c_mapWorld.IsLoaded() || !x2c_mapWorld.GetObj()) - return false; - x2c_mapWorld->SetWhichMapAreasLoaded(*this, 0, 9999); - x8_phase = Phase::LoadingMapAreas; - } - case Phase::LoadingMapAreas: - { - if (x2c_mapWorld->IsMapAreasStreaming()) - return false; + if (version > 12) + r.readString(); - x8_phase = Phase::Done; - } - case Phase::Done: - return true; - default: - return false; + CWorldLayers::ReadWorldLayers(r, version, xc_mlvlId); + + if (x4_loadMap) + x8_phase = Phase::LoadingMap; + else { + x8_phase = Phase::Done; + return false; } + } + case Phase::LoadingMap: { + if (!x2c_mapWorld.IsLoaded() || !x2c_mapWorld.GetObj()) + return false; + + x2c_mapWorld->SetWhichMapAreasLoaded(*this, 0, 9999); + x8_phase = Phase::LoadingMapAreas; + } + case Phase::LoadingMapAreas: { + if (x2c_mapWorld->IsMapAreasStreaming()) + return false; + + x8_phase = Phase::Done; + } + case Phase::Done: + return true; + default: + return false; + } } std::string CDummyWorld::IGetDefaultAudioTrack() const { return {}; } @@ -191,24 +173,21 @@ std::string CDummyWorld::IGetDefaultAudioTrack() const { return {}; } int CDummyWorld::IGetAreaCount() const { return x18_areas.size(); } CWorld::CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId) -: x8_mlvlId(mlvlId), x60_objectStore(objStore), x64_resFactory(resFactory) -{ - x70_24_currentAreaNeedsAllocation = true; - SObjectTag tag{FOURCC('MLVL'), mlvlId}; - x40_loadBuf.reset(new u8[resFactory.ResourceSize(tag)]); - resFactory.LoadResourceAsync(tag, x40_loadBuf.get()); +: x8_mlvlId(mlvlId), x60_objectStore(objStore), x64_resFactory(resFactory) { + x70_24_currentAreaNeedsAllocation = true; + SObjectTag tag{FOURCC('MLVL'), mlvlId}; + x40_loadBuf.reset(new u8[resFactory.ResourceSize(tag)]); + resFactory.LoadResourceAsync(tag, x40_loadBuf.get()); } -CWorld::~CWorld() -{ - StopSounds(); - if (g_GameState->GetWorldTransitionManager()->IsTransitionEnabled() && - g_Main->GetFlowState() == EFlowState::None) - CStreamAudioManager::StopOneShot(); - else - CStreamAudioManager::StopAll(); - UnloadSoundGroups(); - CScriptRoomAcoustics::DisableAuxCallbacks(); +CWorld::~CWorld() { + StopSounds(); + if (g_GameState->GetWorldTransitionManager()->IsTransitionEnabled() && g_Main->GetFlowState() == EFlowState::None) + CStreamAudioManager::StopOneShot(); + else + CStreamAudioManager::StopAll(); + UnloadSoundGroups(); + CScriptRoomAcoustics::DisableAuxCallbacks(); } CAssetId CWorld::IGetWorldAssetId() const { return GetWorldAssetId(); } @@ -229,354 +208,303 @@ const IGameArea* CWorld::IGetAreaAlways(TAreaId id) const { return GetAreaAlways TAreaId CWorld::IGetCurrentAreaId() const { return x68_curAreaId; } -TAreaId CWorld::IGetAreaId(CAssetId id) const -{ - int ret = 0; - if (!id.IsValid()) - return kInvalidAreaId; - for (const std::unique_ptr& area : x18_areas) - { - if (area->x84_mrea == id) - return ret; - ++ret; - } +TAreaId CWorld::IGetAreaId(CAssetId id) const { + int ret = 0; + if (!id.IsValid()) return kInvalidAreaId; + for (const std::unique_ptr& area : x18_areas) { + if (area->x84_mrea == id) + return ret; + ++ret; + } + return kInvalidAreaId; } -void CWorld::MoveToChain(CGameArea* area, EChain chain) -{ - if (area->x138_curChain == chain) - return; +void CWorld::MoveToChain(CGameArea* area, EChain chain) { + if (area->x138_curChain == chain) + return; - if (area->x138_curChain != EChain::Invalid) - if (x4c_chainHeads[int(area->x138_curChain)] == area) - x4c_chainHeads[int(area->x138_curChain)] = area->x130_next; + if (area->x138_curChain != EChain::Invalid) + if (x4c_chainHeads[int(area->x138_curChain)] == area) + x4c_chainHeads[int(area->x138_curChain)] = area->x130_next; - area->SetChain(x4c_chainHeads[int(chain)], chain); - x4c_chainHeads[int(chain)] = area; + area->SetChain(x4c_chainHeads[int(chain)], chain); + x4c_chainHeads[int(chain)] = area; } -void CWorld::MoveAreaToAliveChain(TAreaId aid) -{ - MoveToChain(x18_areas[aid].get(), EChain::Alive); -} +void CWorld::MoveAreaToAliveChain(TAreaId aid) { MoveToChain(x18_areas[aid].get(), EChain::Alive); } -void CWorld::LoadSoundGroup(int groupId, CAssetId agscId, CSoundGroupData& data) -{ - if (!CAudioSys::SysLoadGroupSet(g_SimplePool, agscId)) - { - auto name = CAudioSys::SysGetGroupSetName(agscId); - CAudioSys::SysAddGroupIntoAmuse(name); - data.xc_name = name; - ++x6c_loadedAudioGrpCount; - } +void CWorld::LoadSoundGroup(int groupId, CAssetId agscId, CSoundGroupData& data) { + if (!CAudioSys::SysLoadGroupSet(g_SimplePool, agscId)) { + auto name = CAudioSys::SysGetGroupSetName(agscId); + CAudioSys::SysAddGroupIntoAmuse(name); + data.xc_name = name; + ++x6c_loadedAudioGrpCount; + } } void CWorld::LoadSoundGroups() {} -void CWorld::UnloadSoundGroups() -{ - for (CSoundGroupData& data : x74_soundGroupData) - { - CAudioSys::SysRemoveGroupFromAmuse(data.xc_name); - CAudioSys::SysUnloadAudioGroupSet(data.xc_name); - } +void CWorld::UnloadSoundGroups() { + for (CSoundGroupData& data : x74_soundGroupData) { + CAudioSys::SysRemoveGroupFromAmuse(data.xc_name); + CAudioSys::SysUnloadAudioGroupSet(data.xc_name); + } } -void CWorld::StopSounds() -{ - for (CSfxHandle& hnd : xc8_globalSfxHandles) - CSfxManager::RemoveEmitter(hnd); - xc8_globalSfxHandles.clear(); +void CWorld::StopSounds() { + for (CSfxHandle& hnd : xc8_globalSfxHandles) + CSfxManager::RemoveEmitter(hnd); + xc8_globalSfxHandles.clear(); } -bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, CAssetId mreaId) -{ - if (mreaId.IsValid()) - { - x68_curAreaId = 0; - TAreaId aid = 0; - for (const std::unique_ptr& area : x18_areas) - { - if (area->x84_mrea == mreaId) - { - x68_curAreaId = aid; - break; - } - ++aid; - } +bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, CAssetId mreaId) { + if (mreaId.IsValid()) { + x68_curAreaId = 0; + TAreaId aid = 0; + for (const std::unique_ptr& area : x18_areas) { + if (area->x84_mrea == mreaId) { + x68_curAreaId = aid; + break; + } + ++aid; } + } else + x68_curAreaId = id; + + switch (x4_phase) { + case Phase::Loading: { + if (!x40_loadBuf) + return false; + athena::io::MemoryReader r(x40_loadBuf.get(), UINT32_MAX); + r.readUint32Big(); + int version = r.readUint32Big(); + xc_strgId = r.readUint32Big(); + + if (version >= 15) + x10_savwId = r.readUint32Big(); + if (version >= 12) { + CAssetId skyboxId = r.readUint32Big(); + if (skyboxId.IsValid() && mgr) + x94_skyboxWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), skyboxId}); + } + if (version >= 17) + x2c_relays = CWorld::CRelay::ReadMemoryRelays(r); + + u32 areaCount = r.readUint32Big(); + r.readUint32Big(); + + x18_areas.reserve(areaCount); + for (u32 i = 0; i < areaCount; ++i) + x18_areas.push_back(std::make_unique(r, i, version)); + + if (x48_chainCount < 5) { + for (int i = x48_chainCount; i < 5; ++i) + x4c_chainHeads[i] = nullptr; + x48_chainCount = 5; + } + + for (std::unique_ptr& area : x18_areas) + MoveToChain(area.get(), EChain::Deallocated); + + x24_mapwId = r.readUint32Big(); + x28_mapWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('MAPW'), x24_mapwId}); + + if (mgr) { + std::vector ids; + mgr->LoadScriptObjects(kInvalidAreaId, r, ids); + mgr->InitScriptObjects(ids); + } + + if (version > 10) { + u32 audioGroupCount = r.readUint32Big(); + x74_soundGroupData.reserve(audioGroupCount); + for (u32 i = 0; i < audioGroupCount; ++i) { + int grpId = r.readUint32Big(); + CAssetId agscId = r.readUint32Big(); + x74_soundGroupData.emplace_back(grpId, agscId); + } + } + + if (version > 12) { + x84_defAudioTrack = r.readString(); + std::string trackKey = hecl::Format("WorldDefault: %8.8x", u32(x8_mlvlId.Value())); + if (g_TweakManager->HasTweakValue(trackKey)) + x84_defAudioTrack = g_TweakManager->GetTweakValue(trackKey)->GetAudio().GetFileName(); + } + + CWorldLayers::ReadWorldLayers(r, version, x8_mlvlId); + + x4_phase = Phase::LoadingMap; + } + case Phase::LoadingMap: { + if (!x28_mapWorld.IsLoaded() || !x28_mapWorld.GetObj()) + return false; + + if (x68_curAreaId == kInvalidAreaId) + x28_mapWorld->SetWhichMapAreasLoaded(*this, 0, 9999); else - x68_curAreaId = id; + x28_mapWorld->SetWhichMapAreasLoaded(*this, x68_curAreaId, 3); - switch (x4_phase) - { - case Phase::Loading: - { - if (!x40_loadBuf) - return false; - athena::io::MemoryReader r(x40_loadBuf.get(), UINT32_MAX); - r.readUint32Big(); - int version = r.readUint32Big(); - xc_strgId = r.readUint32Big(); + x4_phase = Phase::LoadingMapAreas; + } + case Phase::LoadingMapAreas: { + if (x28_mapWorld->IsMapAreasStreaming()) + return false; - if (version >= 15) - x10_savwId = r.readUint32Big(); - if (version >= 12) - { - CAssetId skyboxId = r.readUint32Big(); - if (skyboxId.IsValid() && mgr) - x94_skyboxWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), skyboxId}); - } - if (version >= 17) - x2c_relays = CWorld::CRelay::ReadMemoryRelays(r); + x4_phase = Phase::LoadingSkyBox; + } + case Phase::LoadingSkyBox: { + x70_26_skyboxActive = true; + x70_27_skyboxVisible = false; - u32 areaCount = r.readUint32Big(); - r.readUint32Big(); + if (!x94_skyboxWorld.IsLoaded()) + return false; - x18_areas.reserve(areaCount); - for (u32 i = 0; i < areaCount; ++i) - x18_areas.push_back(std::make_unique(r, i, version)); + CModel* skybox = x94_skyboxWorld.GetObj(); + if (!skybox) + return false; - if (x48_chainCount < 5) - { - for (int i = x48_chainCount; i < 5; ++i) - x4c_chainHeads[i] = nullptr; - x48_chainCount = 5; - } + skybox->GetInstance().Touch(0); + if (!skybox->IsLoaded(0)) + return false; - for (std::unique_ptr& area : x18_areas) - MoveToChain(area.get(), EChain::Deallocated); + xa4_skyboxWorldLoaded = x94_skyboxWorld; - x24_mapwId = r.readUint32Big(); - x28_mapWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('MAPW'), x24_mapwId}); + for (CSoundGroupData& group : x74_soundGroupData) + group.x1c_groupData.Lock(); - if (mgr) - { - std::vector ids; - mgr->LoadScriptObjects(kInvalidAreaId, r, ids); - mgr->InitScriptObjects(ids); - } - - if (version > 10) - { - u32 audioGroupCount = r.readUint32Big(); - x74_soundGroupData.reserve(audioGroupCount); - for (u32 i = 0; i < audioGroupCount; ++i) - { - int grpId = r.readUint32Big(); - CAssetId agscId = r.readUint32Big(); - x74_soundGroupData.emplace_back(grpId, agscId); - } - } - - if (version > 12) - { - x84_defAudioTrack = r.readString(); - std::string trackKey = hecl::Format("WorldDefault: %8.8x", u32(x8_mlvlId.Value())); - if (g_TweakManager->HasTweakValue(trackKey)) - x84_defAudioTrack = g_TweakManager->GetTweakValue(trackKey)->GetAudio().GetFileName(); - } - - CWorldLayers::ReadWorldLayers(r, version, x8_mlvlId); - - x4_phase = Phase::LoadingMap; - } - case Phase::LoadingMap: - { - if (!x28_mapWorld.IsLoaded() || !x28_mapWorld.GetObj()) - return false; - - if (x68_curAreaId == kInvalidAreaId) - x28_mapWorld->SetWhichMapAreasLoaded(*this, 0, 9999); - else - x28_mapWorld->SetWhichMapAreasLoaded(*this, x68_curAreaId, 3); - - x4_phase = Phase::LoadingMapAreas; - } - case Phase::LoadingMapAreas: - { - if (x28_mapWorld->IsMapAreasStreaming()) - return false; - - x4_phase = Phase::LoadingSkyBox; - } - case Phase::LoadingSkyBox: - { - x70_26_skyboxActive = true; - x70_27_skyboxVisible = false; - - if (!x94_skyboxWorld.IsLoaded()) - return false; - - CModel* skybox = x94_skyboxWorld.GetObj(); - if (!skybox) - return false; - - skybox->GetInstance().Touch(0); - if (!skybox->IsLoaded(0)) - return false; - - xa4_skyboxWorldLoaded = x94_skyboxWorld; - - for (CSoundGroupData& group : x74_soundGroupData) - group.x1c_groupData.Lock(); - - x4_phase = Phase::LoadingSoundGroups; - } - case Phase::LoadingSoundGroups: - { - bool allLoaded = true; - for (CSoundGroupData& group : x74_soundGroupData) - { - bool loaded = group.x1c_groupData.IsLoaded(); - allLoaded &= loaded; - if (loaded) - { - CAudioGroupSet* groupData = group.x1c_groupData.GetObj(); - if (groupData) - LoadSoundGroup(group.x0_groupId, group.x4_agscId, group); - } - } - if (!allLoaded) - return false; - - LoadSoundGroups(); - x4_phase = Phase::Done; - } - case Phase::Done: - return true; - default: - return false; + x4_phase = Phase::LoadingSoundGroups; + } + case Phase::LoadingSoundGroups: { + bool allLoaded = true; + for (CSoundGroupData& group : x74_soundGroupData) { + bool loaded = group.x1c_groupData.IsLoaded(); + allLoaded &= loaded; + if (loaded) { + CAudioGroupSet* groupData = group.x1c_groupData.GetObj(); + if (groupData) + LoadSoundGroup(group.x0_groupId, group.x4_agscId, group); + } } + if (!allLoaded) + return false; + LoadSoundGroups(); + x4_phase = Phase::Done; + } + case Phase::Done: + return true; + default: return false; + } + + return false; } -bool CWorld::ScheduleAreaToLoad(CGameArea* area, CStateManager& mgr) -{ - if (!area->IsPostConstructed()) - { - MoveToChain(area, EChain::Loading); - return true; - } - else - { - if (area->x138_curChain != EChain::Alive) - { - if (area->x138_curChain != EChain::AliveJudgement) - { - x70_24_currentAreaNeedsAllocation = true; - } - MoveToChain(area, EChain::Alive); - } - return false; - } -} - -void CWorld::TravelToArea(TAreaId aid, CStateManager& mgr, bool skipLoadOther) -{ - if (aid < 0 || aid >= x18_areas.size()) - return; - x70_24_currentAreaNeedsAllocation = false; - x68_curAreaId = aid; - CGameArea* toDeallocateAreas = x4c_chainHeads[0]; - while (toDeallocateAreas) - { - if (toDeallocateAreas->Invalidate(&mgr)) - { - MoveToChain(toDeallocateAreas, EChain::Deallocated); - break; - } - toDeallocateAreas = toDeallocateAreas->x130_next; - } - - CGameArea* aliveAreas = x4c_chainHeads[3]; - while (aliveAreas) - { - CGameArea* aliveArea = aliveAreas; - aliveAreas = aliveAreas->x130_next; - MoveToChain(aliveArea, EChain::AliveJudgement); - } - CGameArea* loadingAreas = x4c_chainHeads[2]; - while (loadingAreas) - { - CGameArea* loadingArea = loadingAreas; - loadingAreas = loadingAreas->x130_next; - MoveToChain(loadingArea, EChain::ToDeallocate); - } - - CGameArea* area = x18_areas[aid].get(); - if (area->x138_curChain != EChain::AliveJudgement) +bool CWorld::ScheduleAreaToLoad(CGameArea* area, CStateManager& mgr) { + if (!area->IsPostConstructed()) { + MoveToChain(area, EChain::Loading); + return true; + } else { + if (area->x138_curChain != EChain::Alive) { + if (area->x138_curChain != EChain::AliveJudgement) { x70_24_currentAreaNeedsAllocation = true; - area->Validate(mgr); - MoveToChain(area, EChain::Alive); - area->SetOcclusionState(CGameArea::EOcclusionState::Visible); - - CGameArea* otherLoadArea = nullptr; - if (!skipLoadOther) - { - bool otherLoading = false; - for (CGameArea::Dock& dock : area->xcc_docks) - { - u32 dockRefCount = dock.GetDockRefs().size(); - for (u32 i = 0; i < dockRefCount; ++i) - { - if (!dock.ShouldLoadOtherArea(i)) - continue; - TAreaId connArea = dock.GetConnectedAreaId(i); - CGameArea* cArea = x18_areas[connArea].get(); - if (!cArea->xf0_25_active) - continue; - if (!otherLoading) - { - otherLoading = ScheduleAreaToLoad(cArea, mgr); - if (!otherLoading) - continue; - otherLoadArea = cArea; - } - else - ScheduleAreaToLoad(cArea, mgr); - } - } + } + MoveToChain(area, EChain::Alive); } - CGameArea* judgementAreas = x4c_chainHeads[4]; - while (judgementAreas) - { - CGameArea* judgementArea = judgementAreas; - judgementAreas = judgementArea->x130_next; - MoveToChain(judgementArea, EChain::ToDeallocate); - } - - size_t toStreamCount = 0; - toDeallocateAreas = x4c_chainHeads[0]; - while (toDeallocateAreas) - { - toDeallocateAreas->RemoveStaticGeometry(); - toDeallocateAreas = toDeallocateAreas->x130_next; - ++toStreamCount; - } - - if (!toStreamCount && otherLoadArea && !x70_25_loadPaused) - otherLoadArea->StartStreamIn(mgr); - - x28_mapWorld->SetWhichMapAreasLoaded(*this, aid, 3); + return false; + } } -void CWorld::SetLoadPauseState(bool paused) -{ - for (auto it = GetChainHead(EChain::Loading) ; it != AliveAreasEnd() ; ++it) - it->SetLoadPauseState(paused); - x70_25_loadPaused = paused; +void CWorld::TravelToArea(TAreaId aid, CStateManager& mgr, bool skipLoadOther) { + if (aid < 0 || aid >= x18_areas.size()) + return; + x70_24_currentAreaNeedsAllocation = false; + x68_curAreaId = aid; + CGameArea* toDeallocateAreas = x4c_chainHeads[0]; + while (toDeallocateAreas) { + if (toDeallocateAreas->Invalidate(&mgr)) { + MoveToChain(toDeallocateAreas, EChain::Deallocated); + break; + } + toDeallocateAreas = toDeallocateAreas->x130_next; + } + + CGameArea* aliveAreas = x4c_chainHeads[3]; + while (aliveAreas) { + CGameArea* aliveArea = aliveAreas; + aliveAreas = aliveAreas->x130_next; + MoveToChain(aliveArea, EChain::AliveJudgement); + } + CGameArea* loadingAreas = x4c_chainHeads[2]; + while (loadingAreas) { + CGameArea* loadingArea = loadingAreas; + loadingAreas = loadingAreas->x130_next; + MoveToChain(loadingArea, EChain::ToDeallocate); + } + + CGameArea* area = x18_areas[aid].get(); + if (area->x138_curChain != EChain::AliveJudgement) + x70_24_currentAreaNeedsAllocation = true; + area->Validate(mgr); + MoveToChain(area, EChain::Alive); + area->SetOcclusionState(CGameArea::EOcclusionState::Visible); + + CGameArea* otherLoadArea = nullptr; + if (!skipLoadOther) { + bool otherLoading = false; + for (CGameArea::Dock& dock : area->xcc_docks) { + u32 dockRefCount = dock.GetDockRefs().size(); + for (u32 i = 0; i < dockRefCount; ++i) { + if (!dock.ShouldLoadOtherArea(i)) + continue; + TAreaId connArea = dock.GetConnectedAreaId(i); + CGameArea* cArea = x18_areas[connArea].get(); + if (!cArea->xf0_25_active) + continue; + if (!otherLoading) { + otherLoading = ScheduleAreaToLoad(cArea, mgr); + if (!otherLoading) + continue; + otherLoadArea = cArea; + } else + ScheduleAreaToLoad(cArea, mgr); + } + } + } + CGameArea* judgementAreas = x4c_chainHeads[4]; + while (judgementAreas) { + CGameArea* judgementArea = judgementAreas; + judgementAreas = judgementArea->x130_next; + MoveToChain(judgementArea, EChain::ToDeallocate); + } + + size_t toStreamCount = 0; + toDeallocateAreas = x4c_chainHeads[0]; + while (toDeallocateAreas) { + toDeallocateAreas->RemoveStaticGeometry(); + toDeallocateAreas = toDeallocateAreas->x130_next; + ++toStreamCount; + } + + if (!toStreamCount && otherLoadArea && !x70_25_loadPaused) + otherLoadArea->StartStreamIn(mgr); + + x28_mapWorld->SetWhichMapAreasLoaded(*this, aid, 3); } -void CWorld::CycleLoadPauseState() -{ - if (!x70_25_loadPaused) - { - SetLoadPauseState(true); - SetLoadPauseState(false); - } +void CWorld::SetLoadPauseState(bool paused) { + for (auto it = GetChainHead(EChain::Loading); it != AliveAreasEnd(); ++it) + it->SetLoadPauseState(paused); + x70_25_loadPaused = paused; +} + +void CWorld::CycleLoadPauseState() { + if (!x70_25_loadPaused) { + SetLoadPauseState(true); + SetLoadPauseState(false); + } } bool CWorld::ICheckWorldComplete() { return CheckWorldComplete(nullptr, kInvalidAreaId, -1); } @@ -587,211 +515,180 @@ int CWorld::IGetAreaCount() const { return x18_areas.size(); } bool CWorld::DoesAreaExist(TAreaId area) const { return (area >= 0 && area < x18_areas.size()); } -void CWorld::PropogateAreaChain(CGameArea::EOcclusionState occlusionState, CGameArea* area, CWorld* world) -{ - if (!area->GetPostConstructed() || occlusionState == area->GetOcclusionState()) - return; +void CWorld::PropogateAreaChain(CGameArea::EOcclusionState occlusionState, CGameArea* area, CWorld* world) { + if (!area->GetPostConstructed() || occlusionState == area->GetOcclusionState()) + return; - if (occlusionState == CGameArea::EOcclusionState::Visible) - area->SetOcclusionState(CGameArea::EOcclusionState::Visible); + if (occlusionState == CGameArea::EOcclusionState::Visible) + area->SetOcclusionState(CGameArea::EOcclusionState::Visible); - for (CGameArea& areaItr : *world) - { - if (&areaItr == area) - continue; - if (areaItr.IsPostConstructed() && areaItr.GetOcclusionState() == CGameArea::EOcclusionState::Visible) - areaItr.OtherAreaOcclusionChanged(); - } + for (CGameArea& areaItr : *world) { + if (&areaItr == area) + continue; + if (areaItr.IsPostConstructed() && areaItr.GetOcclusionState() == CGameArea::EOcclusionState::Visible) + areaItr.OtherAreaOcclusionChanged(); + } - for (CGameArea& areaItr : *world) - { - if (&areaItr == area) - continue; - if (areaItr.IsPostConstructed() && areaItr.GetOcclusionState() == CGameArea::EOcclusionState::Occluded) - areaItr.OtherAreaOcclusionChanged(); - } + for (CGameArea& areaItr : *world) { + if (&areaItr == area) + continue; + if (areaItr.IsPostConstructed() && areaItr.GetOcclusionState() == CGameArea::EOcclusionState::Occluded) + areaItr.OtherAreaOcclusionChanged(); + } - if (occlusionState == CGameArea::EOcclusionState::Occluded) - area->SetOcclusionState(CGameArea::EOcclusionState::Occluded); + if (occlusionState == CGameArea::EOcclusionState::Occluded) + area->SetOcclusionState(CGameArea::EOcclusionState::Occluded); } -void CWorld::Update(float dt) -{ - xc4_neededFx = EEnvFxType::None; - CAssetId overrideSkyId; - bool needsSky = false; - bool skyVisible = false; +void CWorld::Update(float dt) { + xc4_neededFx = EEnvFxType::None; + CAssetId overrideSkyId; + bool needsSky = false; + bool skyVisible = false; - u32 areaCount = 0; + u32 areaCount = 0; - for (CGameArea* head = x4c_chainHeads[3] ; - head != skGlobalNonConstEnd ; - head = head->x130_next, ++areaCount) - { - head->AliveUpdate(dt); + for (CGameArea* head = x4c_chainHeads[3]; head != skGlobalNonConstEnd; head = head->x130_next, ++areaCount) { + head->AliveUpdate(dt); - if (head->DoesAreaNeedSkyNow()) - { - const CScriptAreaAttributes* attrs = head->GetPostConstructed()->x10d8_areaAttributes; + if (head->DoesAreaNeedSkyNow()) { + const CScriptAreaAttributes* attrs = head->GetPostConstructed()->x10d8_areaAttributes; - if (attrs && attrs->GetSkyModel().IsValid()) - overrideSkyId = attrs->GetSkyModel(); + if (attrs && attrs->GetSkyModel().IsValid()) + overrideSkyId = attrs->GetSkyModel(); - needsSky = true; - CGameArea::EOcclusionState occlusionState = (head->IsPostConstructed() - ? head->GetPostConstructed()->x10dc_occlusionState - : CGameArea::EOcclusionState::Occluded); - if (occlusionState == CGameArea::EOcclusionState::Visible) - skyVisible = true; - } - - EEnvFxType envFxType = head->DoesAreaNeedEnvFx(); - if (envFxType != EEnvFxType::None) - xc4_neededFx = envFxType; - } - - if (areaCount == 0) - return; - - if (overrideSkyId.IsValid() && needsSky) - { - x70_26_skyboxActive = true; - x70_27_skyboxVisible = skyVisible; - xb4_skyboxOverride = g_SimplePool->GetObj({SBIG('CMDL'), overrideSkyId}); - xa4_skyboxWorldLoaded = TLockedToken(); - if (x94_skyboxWorld) - x94_skyboxWorld.Unlock(); - } - else - { - xb4_skyboxOverride = TLockedToken(); - if (!x94_skyboxWorld) - { - x70_26_skyboxActive = false; - x70_27_skyboxVisible = false; - } - else if (!needsSky) - { - xa4_skyboxWorldLoaded = TLockedToken(); - x94_skyboxWorld.Unlock(); - x70_26_skyboxActive = false; - x70_27_skyboxVisible = false; - } - else - { - if (!xa4_skyboxWorldLoaded) - { - x94_skyboxWorld.Lock(); - if (x94_skyboxWorld.IsLoaded()) - { - x94_skyboxWorld->Touch(0); - if (x94_skyboxWorld->IsLoaded(0)) - xa4_skyboxWorldLoaded = x94_skyboxWorld; - } - } - x70_26_skyboxActive = true; - x70_27_skyboxVisible = skyVisible; + needsSky = true; + CGameArea::EOcclusionState occlusionState = + (head->IsPostConstructed() ? head->GetPostConstructed()->x10dc_occlusionState + : CGameArea::EOcclusionState::Occluded); + if (occlusionState == CGameArea::EOcclusionState::Visible) + skyVisible = true; + } + + EEnvFxType envFxType = head->DoesAreaNeedEnvFx(); + if (envFxType != EEnvFxType::None) + xc4_neededFx = envFxType; + } + + if (areaCount == 0) + return; + + if (overrideSkyId.IsValid() && needsSky) { + x70_26_skyboxActive = true; + x70_27_skyboxVisible = skyVisible; + xb4_skyboxOverride = g_SimplePool->GetObj({SBIG('CMDL'), overrideSkyId}); + xa4_skyboxWorldLoaded = TLockedToken(); + if (x94_skyboxWorld) + x94_skyboxWorld.Unlock(); + } else { + xb4_skyboxOverride = TLockedToken(); + if (!x94_skyboxWorld) { + x70_26_skyboxActive = false; + x70_27_skyboxVisible = false; + } else if (!needsSky) { + xa4_skyboxWorldLoaded = TLockedToken(); + x94_skyboxWorld.Unlock(); + x70_26_skyboxActive = false; + x70_27_skyboxVisible = false; + } else { + if (!xa4_skyboxWorldLoaded) { + x94_skyboxWorld.Lock(); + if (x94_skyboxWorld.IsLoaded()) { + x94_skyboxWorld->Touch(0); + if (x94_skyboxWorld->IsLoaded(0)) + xa4_skyboxWorldLoaded = x94_skyboxWorld; } + } + x70_26_skyboxActive = true; + x70_27_skyboxVisible = skyVisible; } + } } -void CWorld::PreRender() -{ - for (CGameArea* head = x4c_chainHeads[3] ; - head != skGlobalNonConstEnd ; - head = head->x130_next) - { - head->PreRender(); - } +void CWorld::PreRender() { + for (CGameArea* head = x4c_chainHeads[3]; head != skGlobalNonConstEnd; head = head->x130_next) { + head->PreRender(); + } } -void CWorld::TouchSky() -{ - if (xa4_skyboxWorldLoaded.IsLoaded()) - xa4_skyboxWorldLoaded->Touch(0); - if (xb4_skyboxOverride.IsLoaded()) - xb4_skyboxOverride->Touch(0); +void CWorld::TouchSky() { + if (xa4_skyboxWorldLoaded.IsLoaded()) + xa4_skyboxWorldLoaded->Touch(0); + if (xb4_skyboxOverride.IsLoaded()) + xb4_skyboxOverride->Touch(0); } -void CWorld::DrawSky(const zeus::CTransform& xf) const -{ - const CModel* model; - if (xa4_skyboxWorldLoaded) - model = xa4_skyboxWorldLoaded.GetObj(); - else if (xb4_skyboxOverride) - model = xb4_skyboxOverride.GetObj(); - else - return; +void CWorld::DrawSky(const zeus::CTransform& xf) const { + const CModel* model; + if (xa4_skyboxWorldLoaded) + model = xa4_skyboxWorldLoaded.GetObj(); + else if (xb4_skyboxOverride) + model = xb4_skyboxOverride.GetObj(); + else + return; - if (!x70_27_skyboxVisible) - return; + if (!x70_27_skyboxVisible) + return; - CGraphics::DisableAllLights(); - CGraphics::SetModelMatrix(xf); - g_Renderer->SetAmbientColor(zeus::CColor::skWhite); - CGraphics::SetDepthRange(DEPTH_SKY, DEPTH_FAR); + CGraphics::DisableAllLights(); + CGraphics::SetModelMatrix(xf); + g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + CGraphics::SetDepthRange(DEPTH_SKY, DEPTH_FAR); - CModelFlags flags(0, 0, 1, zeus::CColor::skWhite); - flags.m_noZWrite = true; - model->Draw(flags); + CModelFlags flags(0, 0, 1, zeus::CColor::skWhite); + flags.m_noZWrite = true; + model->Draw(flags); - CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); + CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR); } -void CWorld::StopGlobalSound(u16 id) -{ - auto search = std::find_if(xc8_globalSfxHandles.begin(), xc8_globalSfxHandles.end(), - [id](CSfxHandle& hnd) { return hnd->GetSfxId() == id; }); - if (search != xc8_globalSfxHandles.end()) - { - CSfxManager::RemoveEmitter(*search); - xc8_globalSfxHandles.erase(search); - } +void CWorld::StopGlobalSound(u16 id) { + auto search = std::find_if(xc8_globalSfxHandles.begin(), xc8_globalSfxHandles.end(), + [id](CSfxHandle& hnd) { return hnd->GetSfxId() == id; }); + if (search != xc8_globalSfxHandles.end()) { + CSfxManager::RemoveEmitter(*search); + xc8_globalSfxHandles.erase(search); + } } -bool CWorld::HasGlobalSound(u16 id) const -{ - auto search = std::find_if(xc8_globalSfxHandles.begin(), xc8_globalSfxHandles.end(), - [id](const CSfxHandle& hnd) { return hnd->GetSfxId() == id; }); - return search != xc8_globalSfxHandles.end(); +bool CWorld::HasGlobalSound(u16 id) const { + auto search = std::find_if(xc8_globalSfxHandles.begin(), xc8_globalSfxHandles.end(), + [id](const CSfxHandle& hnd) { return hnd->GetSfxId() == id; }); + return search != xc8_globalSfxHandles.end(); } -void CWorld::AddGlobalSound(const CSfxHandle& hnd) -{ - if (xc8_globalSfxHandles.size() >= xc8_globalSfxHandles.capacity()) - return; - xc8_globalSfxHandles.push_back(hnd); +void CWorld::AddGlobalSound(const CSfxHandle& hnd) { + if (xc8_globalSfxHandles.size() >= xc8_globalSfxHandles.capacity()) + return; + xc8_globalSfxHandles.push_back(hnd); } -bool CWorld::AreSkyNeedsMet() const -{ - if (!x70_26_skyboxActive) - return true; - if (xb4_skyboxOverride && xb4_skyboxOverride->IsLoaded(0)) - return true; - if (xa4_skyboxWorldLoaded && xa4_skyboxWorldLoaded->IsLoaded(0)) - return true; - if (x94_skyboxWorld && x94_skyboxWorld->IsLoaded(0)) - return true; - return false; +bool CWorld::AreSkyNeedsMet() const { + if (!x70_26_skyboxActive) + return true; + if (xb4_skyboxOverride && xb4_skyboxOverride->IsLoaded(0)) + return true; + if (xa4_skyboxWorldLoaded && xa4_skyboxWorldLoaded->IsLoaded(0)) + return true; + if (x94_skyboxWorld && x94_skyboxWorld->IsLoaded(0)) + return true; + return false; } -TAreaId CWorld::GetAreaIdForSaveId(s32 saveId) const -{ - if (saveId == -1) - return kInvalidAreaId; - - if (x18_areas.size() <= 0) - return kInvalidAreaId; - - TAreaId cur = 0; - for (const auto& area : x18_areas) - { - if (area->x88_areaId == saveId) - return cur; - ++cur; - } - +TAreaId CWorld::GetAreaIdForSaveId(s32 saveId) const { + if (saveId == -1) return kInvalidAreaId; + + if (x18_areas.size() <= 0) + return kInvalidAreaId; + + TAreaId cur = 0; + for (const auto& area : x18_areas) { + if (area->x88_areaId == saveId) + return cur; + ++cur; + } + + return kInvalidAreaId; } -} +} // namespace urde diff --git a/Runtime/World/CWorld.hpp b/Runtime/World/CWorld.hpp index 93e775dab..d4529e401 100644 --- a/Runtime/World/CWorld.hpp +++ b/Runtime/World/CWorld.hpp @@ -8,224 +8,213 @@ #include "AutoMapper/CMapWorld.hpp" #include "CEnvFxManager.hpp" -namespace urde -{ +namespace urde { class CGameArea; class IObjectStore; class CResFactory; class IGameArea; class CAudioGroupSet; -class IWorld -{ +class IWorld { public: - virtual ~IWorld() = default; - virtual CAssetId IGetWorldAssetId() const=0; - virtual CAssetId IGetStringTableAssetId() const=0; - virtual CAssetId IGetSaveWorldAssetId() const=0; - virtual const CMapWorld* IGetMapWorld() const=0; - virtual CMapWorld* IMapWorld()=0; - virtual const IGameArea* IGetAreaAlways(TAreaId id) const=0; - virtual TAreaId IGetCurrentAreaId() const=0; - virtual TAreaId IGetAreaId(CAssetId id) const=0; - virtual bool ICheckWorldComplete()=0; - virtual std::string IGetDefaultAudioTrack() const=0; - virtual int IGetAreaCount() const=0; + virtual ~IWorld() = default; + virtual CAssetId IGetWorldAssetId() const = 0; + virtual CAssetId IGetStringTableAssetId() const = 0; + virtual CAssetId IGetSaveWorldAssetId() const = 0; + virtual const CMapWorld* IGetMapWorld() const = 0; + virtual CMapWorld* IMapWorld() = 0; + virtual const IGameArea* IGetAreaAlways(TAreaId id) const = 0; + virtual TAreaId IGetCurrentAreaId() const = 0; + virtual TAreaId IGetAreaId(CAssetId id) const = 0; + virtual bool ICheckWorldComplete() = 0; + virtual std::string IGetDefaultAudioTrack() const = 0; + virtual int IGetAreaCount() const = 0; }; -class CDummyWorld : public IWorld -{ - bool x4_loadMap; - enum class Phase - { - Loading, - LoadingMap, - LoadingMapAreas, - Done, - } x8_phase = Phase::Loading; - CAssetId xc_mlvlId; - CAssetId x10_strgId; - CAssetId x14_savwId; - std::vector x18_areas; - CAssetId x28_mapWorldId; - TLockedToken x2c_mapWorld; - std::shared_ptr x30_loadToken; - std::unique_ptr x34_loadBuf; - //u32 x38_bufSz; - TAreaId x3c_curAreaId = kInvalidAreaId; +class CDummyWorld : public IWorld { + bool x4_loadMap; + enum class Phase { + Loading, + LoadingMap, + LoadingMapAreas, + Done, + } x8_phase = Phase::Loading; + CAssetId xc_mlvlId; + CAssetId x10_strgId; + CAssetId x14_savwId; + std::vector x18_areas; + CAssetId x28_mapWorldId; + TLockedToken x2c_mapWorld; + std::shared_ptr x30_loadToken; + std::unique_ptr x34_loadBuf; + // u32 x38_bufSz; + TAreaId x3c_curAreaId = kInvalidAreaId; + public: - CDummyWorld(CAssetId mlvlId, bool loadMap); - ~CDummyWorld(); - CAssetId IGetWorldAssetId() const; - CAssetId IGetStringTableAssetId() const; - CAssetId IGetSaveWorldAssetId() const; - const CMapWorld* IGetMapWorld() const; - CMapWorld* IMapWorld(); - const IGameArea* IGetAreaAlways(TAreaId id) const; - TAreaId IGetCurrentAreaId() const; - TAreaId IGetAreaId(CAssetId id) const; - bool ICheckWorldComplete(); - std::string IGetDefaultAudioTrack() const; - int IGetAreaCount() const; + CDummyWorld(CAssetId mlvlId, bool loadMap); + ~CDummyWorld(); + CAssetId IGetWorldAssetId() const; + CAssetId IGetStringTableAssetId() const; + CAssetId IGetSaveWorldAssetId() const; + const CMapWorld* IGetMapWorld() const; + CMapWorld* IMapWorld(); + const IGameArea* IGetAreaAlways(TAreaId id) const; + TAreaId IGetCurrentAreaId() const; + TAreaId IGetAreaId(CAssetId id) const; + bool ICheckWorldComplete(); + std::string IGetDefaultAudioTrack() const; + int IGetAreaCount() const; }; -class CWorld : public IWorld -{ - friend class CStateManager; +class CWorld : public IWorld { + friend class CStateManager; + public: - class CRelay - { - TEditorId x0_relay = kInvalidEditorId; - TEditorId x4_target = kInvalidEditorId; - s16 x8_msg = -1; - bool xa_active = false; - public: - CRelay() = default; - CRelay(CInputStream& in); + class CRelay { + TEditorId x0_relay = kInvalidEditorId; + TEditorId x4_target = kInvalidEditorId; + s16 x8_msg = -1; + bool xa_active = false; - TEditorId GetRelayId() const { return x0_relay; } - TEditorId GetTargetId() const { return x4_target; } - s16 GetMessage() const { return x8_msg; } - bool GetActive() const { return xa_active; } + public: + CRelay() = default; + CRelay(CInputStream& in); - static std::vector ReadMemoryRelays(athena::io::MemoryReader& r); - }; + TEditorId GetRelayId() const { return x0_relay; } + TEditorId GetTargetId() const { return x4_target; } + s16 GetMessage() const { return x8_msg; } + bool GetActive() const { return xa_active; } - struct CSoundGroupData - { - int x0_groupId; - CAssetId x4_agscId; - std::string xc_name; - TCachedToken x1c_groupData; - public: - CSoundGroupData(int grpId, CAssetId agsc); - }; + static std::vector ReadMemoryRelays(athena::io::MemoryReader& r); + }; + + struct CSoundGroupData { + int x0_groupId; + CAssetId x4_agscId; + std::string xc_name; + TCachedToken x1c_groupData; + + public: + CSoundGroupData(int grpId, CAssetId agsc); + }; private: - static constexpr CGameArea* skGlobalEnd = nullptr; - static constexpr CGameArea* skGlobalNonConstEnd = nullptr; - enum class Phase - { - Loading, - LoadingMap, - LoadingMapAreas, - LoadingSkyBox, - LoadingSoundGroups, - Done, - } x4_phase = Phase::Loading; - CAssetId x8_mlvlId; - CAssetId xc_strgId; - CAssetId x10_savwId; - std::vector> x18_areas; - CAssetId x24_mapwId; - TLockedToken x28_mapWorld; - std::vector x2c_relays; - //AsyncTask x3c_loadToken; - std::unique_ptr x40_loadBuf; - //u32 x44_bufSz; - u32 x48_chainCount = 0; - CGameArea* x4c_chainHeads[5] = {}; + static constexpr CGameArea* skGlobalEnd = nullptr; + static constexpr CGameArea* skGlobalNonConstEnd = nullptr; + enum class Phase { + Loading, + LoadingMap, + LoadingMapAreas, + LoadingSkyBox, + LoadingSoundGroups, + Done, + } x4_phase = Phase::Loading; + CAssetId x8_mlvlId; + CAssetId xc_strgId; + CAssetId x10_savwId; + std::vector> x18_areas; + CAssetId x24_mapwId; + TLockedToken x28_mapWorld; + std::vector x2c_relays; + // AsyncTask x3c_loadToken; + std::unique_ptr x40_loadBuf; + // u32 x44_bufSz; + u32 x48_chainCount = 0; + CGameArea* x4c_chainHeads[5] = {}; - IObjectStore& x60_objectStore; - IFactory& x64_resFactory; - TAreaId x68_curAreaId = kInvalidAreaId; - u32 x6c_loadedAudioGrpCount = 0; + IObjectStore& x60_objectStore; + IFactory& x64_resFactory; + TAreaId x68_curAreaId = kInvalidAreaId; + u32 x6c_loadedAudioGrpCount = 0; - union - { - struct - { - bool x70_24_currentAreaNeedsAllocation : 1; - bool x70_25_loadPaused : 1; - bool x70_26_skyboxActive : 1; - bool x70_27_skyboxVisible : 1; - }; - u32 dummy = 0; + union { + struct { + bool x70_24_currentAreaNeedsAllocation : 1; + bool x70_25_loadPaused : 1; + bool x70_26_skyboxActive : 1; + bool x70_27_skyboxVisible : 1; }; - std::vector x74_soundGroupData; - std::string x84_defAudioTrack; - TLockedToken x94_skyboxWorld; - TLockedToken xa4_skyboxWorldLoaded; - TLockedToken xb4_skyboxOverride; - EEnvFxType xc4_neededFx = EEnvFxType::None; - rstl::reserved_vector xc8_globalSfxHandles; + u32 dummy = 0; + }; + std::vector x74_soundGroupData; + std::string x84_defAudioTrack; + TLockedToken x94_skyboxWorld; + TLockedToken xa4_skyboxWorldLoaded; + TLockedToken xb4_skyboxOverride; + EEnvFxType xc4_neededFx = EEnvFxType::None; + rstl::reserved_vector xc8_globalSfxHandles; - void LoadSoundGroup(int groupId, CAssetId agscId, CSoundGroupData& data); - void LoadSoundGroups(); - void UnloadSoundGroups(); - void StopSounds(); + void LoadSoundGroup(int groupId, CAssetId agscId, CSoundGroupData& data); + void LoadSoundGroups(); + void UnloadSoundGroups(); + void StopSounds(); public: + void MoveToChain(CGameArea* area, EChain chain); + void MoveAreaToAliveChain(TAreaId aid); + bool CheckWorldComplete(CStateManager* mgr, TAreaId id, CAssetId mreaId); + CGameArea::CChainIterator GetChainHead(EChain chain) { return {x4c_chainHeads[int(chain)]}; } + CGameArea::CConstChainIterator GetChainHead(EChain chain) const { return {x4c_chainHeads[int(chain)]}; } + CGameArea::CChainIterator begin() { return GetChainHead(EChain::Alive); } + CGameArea::CChainIterator end() { return AliveAreasEnd(); } + CGameArea::CConstChainIterator begin() const { return GetChainHead(EChain::Alive); } + CGameArea::CConstChainIterator end() const { return GetAliveAreasEnd(); } + bool ScheduleAreaToLoad(CGameArea* area, CStateManager& mgr); + void TravelToArea(TAreaId aid, CStateManager& mgr, bool); + void SetLoadPauseState(bool paused); + void CycleLoadPauseState(); - void MoveToChain(CGameArea* area, EChain chain); - void MoveAreaToAliveChain(TAreaId aid); - bool CheckWorldComplete(CStateManager* mgr, TAreaId id, CAssetId mreaId); - CGameArea::CChainIterator GetChainHead(EChain chain) { return {x4c_chainHeads[int(chain)]}; } - CGameArea::CConstChainIterator GetChainHead(EChain chain) const { return {x4c_chainHeads[int(chain)]}; } - CGameArea::CChainIterator begin() { return GetChainHead(EChain::Alive); } - CGameArea::CChainIterator end() { return AliveAreasEnd(); } - CGameArea::CConstChainIterator begin() const { return GetChainHead(EChain::Alive); } - CGameArea::CConstChainIterator end() const { return GetAliveAreasEnd(); } - bool ScheduleAreaToLoad(CGameArea* area, CStateManager& mgr); - void TravelToArea(TAreaId aid, CStateManager& mgr, bool); - void SetLoadPauseState(bool paused); - void CycleLoadPauseState(); + CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId); + ~CWorld(); + bool DoesAreaExist(TAreaId area) const; + const std::vector>& GetGameAreas() const { return x18_areas; } - CWorld(IObjectStore& objStore, IFactory& resFactory, CAssetId mlvlId); - ~CWorld(); - bool DoesAreaExist(TAreaId area) const; - const std::vector>& GetGameAreas() const { return x18_areas; } + const CMapWorld* GetMapWorld() const { return x28_mapWorld.GetObj(); } + u32 GetRelayCount() const { return x2c_relays.size(); } + CRelay GetRelay(u32 idx) const { return x2c_relays[idx]; } - const CMapWorld* GetMapWorld() const { return x28_mapWorld.GetObj(); } - u32 GetRelayCount() const { return x2c_relays.size(); } - CRelay GetRelay(u32 idx) const { return x2c_relays[idx]; } + CAssetId IGetWorldAssetId() const; + CAssetId IGetStringTableAssetId() const; + CAssetId IGetSaveWorldAssetId() const; + const CMapWorld* IGetMapWorld() const; + CMapWorld* IMapWorld(); + const CGameArea* GetAreaAlways(TAreaId) const; + CGameArea* GetArea(TAreaId); + s32 GetNumAreas() const { return x18_areas.size(); } + const IGameArea* IGetAreaAlways(TAreaId id) const; + TAreaId IGetCurrentAreaId() const; + TAreaId GetCurrentAreaId() const { return x68_curAreaId; } + TAreaId IGetAreaId(CAssetId id) const; + bool ICheckWorldComplete(); + std::string IGetDefaultAudioTrack() const; + int IGetAreaCount() const; - CAssetId IGetWorldAssetId() const; - CAssetId IGetStringTableAssetId() const; - CAssetId IGetSaveWorldAssetId() const; - const CMapWorld* IGetMapWorld() const; - CMapWorld* IMapWorld(); - const CGameArea* GetAreaAlways(TAreaId) const; - CGameArea* GetArea(TAreaId); - s32 GetNumAreas() const { return x18_areas.size(); } - const IGameArea* IGetAreaAlways(TAreaId id) const; - TAreaId IGetCurrentAreaId() const; - TAreaId GetCurrentAreaId() const { return x68_curAreaId; } - TAreaId IGetAreaId(CAssetId id) const; - bool ICheckWorldComplete(); - std::string IGetDefaultAudioTrack() const; - int IGetAreaCount() const; + static void PropogateAreaChain(CGameArea::EOcclusionState, CGameArea*, CWorld*); + static CGameArea::CConstChainIterator GetAliveAreasEnd() { return {skGlobalEnd}; } + static CGameArea::CChainIterator AliveAreasEnd() { return {skGlobalNonConstEnd}; } - static void PropogateAreaChain(CGameArea::EOcclusionState, CGameArea*, CWorld*); - static CGameArea::CConstChainIterator GetAliveAreasEnd() { return {skGlobalEnd}; } - static CGameArea::CChainIterator AliveAreasEnd() { return {skGlobalNonConstEnd}; } - - void Update(float dt); - void PreRender(); - void TouchSky(); - void DrawSky(const zeus::CTransform& xf) const; - void StopGlobalSound(u16 id); - bool HasGlobalSound(u16 id) const; - void AddGlobalSound(const CSfxHandle& hnd); - EEnvFxType GetNeededEnvFx() const { return xc4_neededFx; } - CAssetId GetWorldAssetId() const { return x8_mlvlId; } - bool AreSkyNeedsMet() const; - TAreaId GetAreaIdForSaveId(s32 saveId) const; + void Update(float dt); + void PreRender(); + void TouchSky(); + void DrawSky(const zeus::CTransform& xf) const; + void StopGlobalSound(u16 id); + bool HasGlobalSound(u16 id) const; + void AddGlobalSound(const CSfxHandle& hnd); + EEnvFxType GetNeededEnvFx() const { return xc4_neededFx; } + CAssetId GetWorldAssetId() const { return x8_mlvlId; } + bool AreSkyNeedsMet() const; + TAreaId GetAreaIdForSaveId(s32 saveId) const; }; -struct CWorldLayers -{ - struct Area - { - u32 m_startNameIdx; - u32 m_layerCount; - u64 m_layerBits; - }; - std::vector m_areas; - std::vector m_names; - static void ReadWorldLayers(athena::io::MemoryReader& r, int version, CAssetId mlvlId); +struct CWorldLayers { + struct Area { + u32 m_startNameIdx; + u32 m_layerCount; + u64 m_layerBits; + }; + std::vector m_areas; + std::vector m_names; + static void ReadWorldLayers(athena::io::MemoryReader& r, int version, CAssetId mlvlId); }; -} - - +} // namespace urde diff --git a/Runtime/World/CWorldLight.cpp b/Runtime/World/CWorldLight.cpp index cfe43307b..3949a364b 100644 --- a/Runtime/World/CWorldLight.cpp +++ b/Runtime/World/CWorldLight.cpp @@ -1,8 +1,7 @@ #include "CWorldLight.hpp" #include -namespace urde -{ +namespace urde { CWorldLight::CWorldLight(CInputStream& in) : x0_type(EWorldLightType(in.readUint32Big())) , x4_color(zeus::CVector3f::ReadBig(in)) @@ -14,66 +13,59 @@ CWorldLight::CWorldLight(CInputStream& in) , x34_castShadows(in.readBool()) , x38_(in.readFloatBig()) , x3c_falloff(EFalloffType(in.readUint32Big())) -, x40_(in.readFloatBig()) -{ +, x40_(in.readFloatBig()) {} + +std::tuple CalculateLightFalloff(EFalloffType falloff, float q) { + float constant = 0.f; + float linear = 0.f; + float quadratic = 0.f; + + if (falloff == EFalloffType::Constant) + constant = 2.f / q; + else if (falloff == EFalloffType::Linear) + linear = 250.f / q; + else if (falloff == EFalloffType::Quadratic) + quadratic = 25000.f / q; + + return {constant, linear, quadratic}; } -std::tuple CalculateLightFalloff(EFalloffType falloff, float q) -{ - float constant = 0.f; - float linear = 0.f; - float quadratic = 0.f; +CLight CWorldLight::GetAsCGraphicsLight() const { + zeus::CVector3f float_color = x4_color; + float q = x28_q; + if (q < FLT_EPSILON) + q = 0.000001f; - if (falloff == EFalloffType::Constant) - constant = 2.f / q; - else if (falloff == EFalloffType::Linear) - linear = 250.f / q; - else if (falloff == EFalloffType::Quadratic) - quadratic = 25000.f / q; + if (x0_type == EWorldLightType::LocalAmbient) { + float_color *= zeus::CVector3f(q); + if (float_color.x() >= 1.f) + float_color.x() = 1.f; - return {constant, linear, quadratic}; -} - -CLight CWorldLight::GetAsCGraphicsLight() const -{ - zeus::CVector3f float_color = x4_color; - float q = x28_q; - if (q < FLT_EPSILON) - q = 0.000001f; - - if (x0_type == EWorldLightType::LocalAmbient) - { - float_color *= zeus::CVector3f(q); - if (float_color.x() >= 1.f) - float_color.x() = 1.f; - - if (float_color.y() >= 1.f) - float_color.y() = 1.f; - - if (float_color.z() >= 1.f) - float_color.z() = 1.f; - - return CLight::BuildLocalAmbient(x10_position, zeus::CColor(float_color.x(), float_color.y(), float_color.z(), 1.f)); - } - else if (x0_type == EWorldLightType::Directional) - { - return CLight::BuildDirectional(x1c_direction, zeus::CColor{x4_color.x(), x4_color.y(), x4_color.z(), 1.f}); - } - else if (x0_type == EWorldLightType::Spot) - { - CLight light = CLight::BuildSpot(x10_position, x1c_direction.normalized(), - zeus::CColor{x4_color.x(), x4_color.y(), x4_color.z(), 1.f}, x2c_cutoffAngle * .5f); - - float c, l, q; - std::tie(c, l, q) = CalculateLightFalloff(x3c_falloff, x28_q); - - light.SetAttenuation(c, l, q); - return light; - } - float distC, distL, distQ; - std::tie(distC, distL, distQ) = CalculateLightFalloff(x3c_falloff, x28_q); - return CLight::BuildCustom(x10_position, zeus::CVector3f{0.f, 1.f, 0.f}, - zeus::CColor{x4_color.x(), x4_color.y(), x4_color.z(), 1.f}, distC, distL, distQ, 1.f, 0.f, - 0.f); -} + if (float_color.y() >= 1.f) + float_color.y() = 1.f; + + if (float_color.z() >= 1.f) + float_color.z() = 1.f; + + return CLight::BuildLocalAmbient(x10_position, + zeus::CColor(float_color.x(), float_color.y(), float_color.z(), 1.f)); + } else if (x0_type == EWorldLightType::Directional) { + return CLight::BuildDirectional(x1c_direction, zeus::CColor{x4_color.x(), x4_color.y(), x4_color.z(), 1.f}); + } else if (x0_type == EWorldLightType::Spot) { + CLight light = + CLight::BuildSpot(x10_position, x1c_direction.normalized(), + zeus::CColor{x4_color.x(), x4_color.y(), x4_color.z(), 1.f}, x2c_cutoffAngle * .5f); + + float c, l, q; + std::tie(c, l, q) = CalculateLightFalloff(x3c_falloff, x28_q); + + light.SetAttenuation(c, l, q); + return light; + } + float distC, distL, distQ; + std::tie(distC, distL, distQ) = CalculateLightFalloff(x3c_falloff, x28_q); + return CLight::BuildCustom(x10_position, zeus::CVector3f{0.f, 1.f, 0.f}, + zeus::CColor{x4_color.x(), x4_color.y(), x4_color.z(), 1.f}, distC, distL, distQ, 1.f, 0.f, + 0.f); } +} // namespace urde diff --git a/Runtime/World/CWorldLight.hpp b/Runtime/World/CWorldLight.hpp index 89b683c38..6e68075bb 100644 --- a/Runtime/World/CWorldLight.hpp +++ b/Runtime/World/CWorldLight.hpp @@ -2,43 +2,40 @@ #include "Graphics/CLight.hpp" -namespace urde -{ -class CWorldLight -{ +namespace urde { +class CWorldLight { public: - enum class EWorldLightType - { - LocalAmbient, - Directional, - Custom, - Spot, - Spot2, - LocalAmbient2, - }; + enum class EWorldLightType { + LocalAmbient, + Directional, + Custom, + Spot, + Spot2, + LocalAmbient2, + }; private: - EWorldLightType x0_type = EWorldLightType::Spot2; - zeus::CVector3f x4_color; - zeus::CVector3f x10_position; - zeus::CVector3f x1c_direction; - float x28_q = 0.f; - float x2c_cutoffAngle = 0.f; - float x30_ = 0.f; - bool x34_castShadows = false; - float x38_ = 0.f; - EFalloffType x3c_falloff = EFalloffType::Linear; - float x40_ = 0.f; -public: - CWorldLight(const CWorldLight&) = default; - CWorldLight(CInputStream& in); - EWorldLightType GetLightType() const { return x0_type; } - const zeus::CVector3f& GetDirection() const { return x1c_direction; } - const zeus::CVector3f& GetPosition() const { return x10_position; } - bool DoesCastShadows() const { return x34_castShadows; } + EWorldLightType x0_type = EWorldLightType::Spot2; + zeus::CVector3f x4_color; + zeus::CVector3f x10_position; + zeus::CVector3f x1c_direction; + float x28_q = 0.f; + float x2c_cutoffAngle = 0.f; + float x30_ = 0.f; + bool x34_castShadows = false; + float x38_ = 0.f; + EFalloffType x3c_falloff = EFalloffType::Linear; + float x40_ = 0.f; - CLight GetAsCGraphicsLight() const; +public: + CWorldLight(const CWorldLight&) = default; + CWorldLight(CInputStream& in); + EWorldLightType GetLightType() const { return x0_type; } + const zeus::CVector3f& GetDirection() const { return x1c_direction; } + const zeus::CVector3f& GetPosition() const { return x10_position; } + bool DoesCastShadows() const { return x34_castShadows; } + + CLight GetAsCGraphicsLight() const; }; -} - +} // namespace urde diff --git a/Runtime/World/CWorldShadow.cpp b/Runtime/World/CWorldShadow.cpp index 26bf1f08c..f04371509 100644 --- a/Runtime/World/CWorldShadow.cpp +++ b/Runtime/World/CWorldShadow.cpp @@ -3,132 +3,112 @@ #include "CStateManager.hpp" #include "Graphics/CBooRenderer.hpp" -namespace urde -{ +namespace urde { -CWorldShadow::CWorldShadow(u32 w, u32 h, bool rgba8) -: m_shader(w, h) {} +CWorldShadow::CWorldShadow(u32 w, u32 h, bool rgba8) : m_shader(w, h) {} -void CWorldShadow::EnableModelProjectedShadow(const zeus::CTransform& pos, s32 lightIdx, float f1) -{ - zeus::CTransform texTransform = zeus::lookAt(zeus::CVector3f::skZero, x74_lightPos - x68_objPos); - zeus::CTransform posXf = pos; - posXf.origin = zeus::CVector3f::skZero; - texTransform = posXf.inverse() * texTransform; - texTransform = (texTransform * zeus::CTransform::Scale(float(M_SQRT2) * x64_objHalfExtent * f1)).inverse(); - texTransform = zeus::CTransform::Translate(0.5f, 0.f, 0.5f) * texTransform; - CBooModel::EnableShadowMaps(m_shader.GetTexture().get(), texTransform); +void CWorldShadow::EnableModelProjectedShadow(const zeus::CTransform& pos, s32 lightIdx, float f1) { + zeus::CTransform texTransform = zeus::lookAt(zeus::CVector3f::skZero, x74_lightPos - x68_objPos); + zeus::CTransform posXf = pos; + posXf.origin = zeus::CVector3f::skZero; + texTransform = posXf.inverse() * texTransform; + texTransform = (texTransform * zeus::CTransform::Scale(float(M_SQRT2) * x64_objHalfExtent * f1)).inverse(); + texTransform = zeus::CTransform::Translate(0.5f, 0.f, 0.5f) * texTransform; + CBooModel::EnableShadowMaps(m_shader.GetTexture().get(), texTransform); #if CWORLDSHADOW_FEEDBACK - if (!m_feedback) - m_feedback.emplace(EFilterType::Blend, m_shader.GetTexture().get()); + if (!m_feedback) + m_feedback.emplace(EFilterType::Blend, m_shader.GetTexture().get()); - zeus::CRectangle rect(0.4f, 0.4f, 0.2f, 0.2f); - m_feedback->draw(zeus::CColor::skWhite, 1.f, rect); + zeus::CRectangle rect(0.4f, 0.4f, 0.2f, 0.2f); + m_feedback->draw(zeus::CColor::skWhite, 1.f, rect); #endif } -void CWorldShadow::DisableModelProjectedShadow() -{ - CBooModel::DisableShadowMaps(); -} +void CWorldShadow::DisableModelProjectedShadow() { CBooModel::DisableShadowMaps(); } void CWorldShadow::BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid, s32 lightIdx, - const zeus::CAABox& aabb, bool motionBlur, bool lighten) -{ - if (x80_aid != aid || x84_lightIdx != lightIdx) - { - x88_blurReset = true; - x80_aid = aid; - x84_lightIdx = lightIdx; - } - - if (aid != kInvalidAreaId) - { - const CGameArea* area = mgr.GetWorld()->GetAreaAlways(aid); - if (area->IsPostConstructed()) - { - const CWorldLight& light = area->GetPostConstructed()->x60_lightsA[lightIdx]; - zeus::CVector3f centerPoint = aabb.center(); - if (const CPVSAreaSet* pvs = area->GetAreaVisSet()) - { - CPVSVisSet lightSet = pvs->Get1stLightSet(lightIdx); - g_Renderer->EnablePVS(lightSet, aid); - } - else - { - CPVSVisSet visSet; - visSet.Reset(EPVSVisSetState::OutOfBounds); - g_Renderer->EnablePVS(visSet, aid); - } - zeus::CVector3f lightToPoint = centerPoint - light.GetPosition(); - x64_objHalfExtent = (aabb.max - centerPoint).magnitude(); - float distance = lightToPoint.magnitude(); - float fov = zeus::radToDeg(std::atan2(x64_objHalfExtent, distance)) * 2.f; - if (fov >= 0.00001f) - { - lightToPoint.normalize(); - x4_view = zeus::lookAt(light.GetPosition(), centerPoint, zeus::CVector3f::skDown); - x68_objPos = centerPoint; - x74_lightPos = light.GetPosition(); - CGraphics::SetViewPointMatrix(x4_view); - zeus::CFrustum frustum; - frustum.updatePlanes(x4_view, zeus::SProjPersp( - zeus::degToRad(fov), 1.f, 0.1f, distance + x64_objHalfExtent)); - g_Renderer->SetClippingPlanes(frustum); - g_Renderer->SetPerspective(fov, m_shader.GetWidth(), m_shader.GetHeight(), 0.1f, 1000.f); - SViewport backupVp = g_Viewport; - zeus::CVector2f backupDepthRange = CGraphics::g_CachedDepthRange; - m_shader.bindRenderTarget(); - g_Renderer->SetViewport(0, 0, m_shader.GetWidth(), m_shader.GetHeight()); - CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR); - - x34_model = zeus::lookAt(centerPoint - zeus::CVector3f(0.f, 0.f, 0.1f), light.GetPosition()); - CGraphics::SetModelMatrix(x34_model); - - float extent = float(M_SQRT2) * x64_objHalfExtent; - /* Depth test and write */ - /* Color white 100% alpha */ - m_shader.drawBase(extent); - - CGraphics::SetModelMatrix(zeus::CTransform::Identity()); - CBooModel::SetDrawingOccluders(true); - g_Renderer->PrepareDynamicLights({}); - g_Renderer->UpdateAreaUniforms(aid, true); - g_Renderer->DrawUnsortedGeometry(aid, 0, 0, true); - CBooModel::SetDrawingOccluders(false); - - if (lighten) - { - CGraphics::SetModelMatrix(x34_model); - /* No depth test or write */ - /* Color white 25% alpha */ - m_shader.lightenShadow(); - } - - if (motionBlur && !x88_blurReset) - { - /* No depth test or write */ - /* Color white 85% alpha */ - /* Draw in shadow texture */ - m_shader.blendPreviousShadow(); - } - - x88_blurReset = false; - - m_shader.resolveTexture(); - CBooRenderer::BindMainDrawTarget(); - - g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height); - CGraphics::SetDepthRange(backupDepthRange[0], backupDepthRange[1]); - } - } - } -} - -void CWorldShadow::ResetBlur() -{ + const zeus::CAABox& aabb, bool motionBlur, bool lighten) { + if (x80_aid != aid || x84_lightIdx != lightIdx) { x88_blurReset = true; + x80_aid = aid; + x84_lightIdx = lightIdx; + } + + if (aid != kInvalidAreaId) { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(aid); + if (area->IsPostConstructed()) { + const CWorldLight& light = area->GetPostConstructed()->x60_lightsA[lightIdx]; + zeus::CVector3f centerPoint = aabb.center(); + if (const CPVSAreaSet* pvs = area->GetAreaVisSet()) { + CPVSVisSet lightSet = pvs->Get1stLightSet(lightIdx); + g_Renderer->EnablePVS(lightSet, aid); + } else { + CPVSVisSet visSet; + visSet.Reset(EPVSVisSetState::OutOfBounds); + g_Renderer->EnablePVS(visSet, aid); + } + zeus::CVector3f lightToPoint = centerPoint - light.GetPosition(); + x64_objHalfExtent = (aabb.max - centerPoint).magnitude(); + float distance = lightToPoint.magnitude(); + float fov = zeus::radToDeg(std::atan2(x64_objHalfExtent, distance)) * 2.f; + if (fov >= 0.00001f) { + lightToPoint.normalize(); + x4_view = zeus::lookAt(light.GetPosition(), centerPoint, zeus::CVector3f::skDown); + x68_objPos = centerPoint; + x74_lightPos = light.GetPosition(); + CGraphics::SetViewPointMatrix(x4_view); + zeus::CFrustum frustum; + frustum.updatePlanes(x4_view, zeus::SProjPersp(zeus::degToRad(fov), 1.f, 0.1f, distance + x64_objHalfExtent)); + g_Renderer->SetClippingPlanes(frustum); + g_Renderer->SetPerspective(fov, m_shader.GetWidth(), m_shader.GetHeight(), 0.1f, 1000.f); + SViewport backupVp = g_Viewport; + zeus::CVector2f backupDepthRange = CGraphics::g_CachedDepthRange; + m_shader.bindRenderTarget(); + g_Renderer->SetViewport(0, 0, m_shader.GetWidth(), m_shader.GetHeight()); + CGraphics::SetDepthRange(DEPTH_NEAR, DEPTH_FAR); + + x34_model = zeus::lookAt(centerPoint - zeus::CVector3f(0.f, 0.f, 0.1f), light.GetPosition()); + CGraphics::SetModelMatrix(x34_model); + + float extent = float(M_SQRT2) * x64_objHalfExtent; + /* Depth test and write */ + /* Color white 100% alpha */ + m_shader.drawBase(extent); + + CGraphics::SetModelMatrix(zeus::CTransform::Identity()); + CBooModel::SetDrawingOccluders(true); + g_Renderer->PrepareDynamicLights({}); + g_Renderer->UpdateAreaUniforms(aid, true); + g_Renderer->DrawUnsortedGeometry(aid, 0, 0, true); + CBooModel::SetDrawingOccluders(false); + + if (lighten) { + CGraphics::SetModelMatrix(x34_model); + /* No depth test or write */ + /* Color white 25% alpha */ + m_shader.lightenShadow(); + } + + if (motionBlur && !x88_blurReset) { + /* No depth test or write */ + /* Color white 85% alpha */ + /* Draw in shadow texture */ + m_shader.blendPreviousShadow(); + } + + x88_blurReset = false; + + m_shader.resolveTexture(); + CBooRenderer::BindMainDrawTarget(); + + g_Renderer->SetViewport(backupVp.x0_left, backupVp.x4_top, backupVp.x8_width, backupVp.xc_height); + CGraphics::SetDepthRange(backupDepthRange[0], backupDepthRange[1]); + } + } + } } -} +void CWorldShadow::ResetBlur() { x88_blurReset = true; } + +} // namespace urde diff --git a/Runtime/World/CWorldShadow.hpp b/Runtime/World/CWorldShadow.hpp index 2ffdadf2a..053dd7d01 100644 --- a/Runtime/World/CWorldShadow.hpp +++ b/Runtime/World/CWorldShadow.hpp @@ -6,32 +6,29 @@ #define CWORLDSHADOW_FEEDBACK 0 -namespace urde -{ +namespace urde { class CStateManager; -class CWorldShadow -{ - CWorldShadowShader m_shader; - zeus::CTransform x4_view; - zeus::CTransform x34_model; - float x64_objHalfExtent = 1.f; - zeus::CVector3f x68_objPos = {0.f, 1.f, 0.f}; - zeus::CVector3f x74_lightPos; - TAreaId x80_aid; - s32 x84_lightIdx = -1; - bool x88_blurReset = true; +class CWorldShadow { + CWorldShadowShader m_shader; + zeus::CTransform x4_view; + zeus::CTransform x34_model; + float x64_objHalfExtent = 1.f; + zeus::CVector3f x68_objPos = {0.f, 1.f, 0.f}; + zeus::CVector3f x74_lightPos; + TAreaId x80_aid; + s32 x84_lightIdx = -1; + bool x88_blurReset = true; #if CWORLDSHADOW_FEEDBACK - std::experimental::optional m_feedback; + std::experimental::optional m_feedback; #endif public: - CWorldShadow(u32 w, u32 h, bool rgba8); - void EnableModelProjectedShadow(const zeus::CTransform& pos, s32 lightIdx, float f1); - void DisableModelProjectedShadow(); - void BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid, s32 lightIdx, - const zeus::CAABox& aabb, bool motionBlur, bool lighten); - void ResetBlur(); + CWorldShadow(u32 w, u32 h, bool rgba8); + void EnableModelProjectedShadow(const zeus::CTransform& pos, s32 lightIdx, float f1); + void DisableModelProjectedShadow(); + void BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid, s32 lightIdx, const zeus::CAABox& aabb, + bool motionBlur, bool lighten); + void ResetBlur(); }; -} - +} // namespace urde diff --git a/Runtime/World/CWorldTransManager.cpp b/Runtime/World/CWorldTransManager.cpp index 674355c0c..a2b47fdc1 100644 --- a/Runtime/World/CWorldTransManager.cpp +++ b/Runtime/World/CWorldTransManager.cpp @@ -15,493 +15,423 @@ #include "GuiSys/CStringTable.hpp" #include "Audio/CSfxManager.hpp" -namespace urde -{ +namespace urde { -int CWorldTransManager::GetSuitCharIdx() -{ - CPlayerState& state = *g_GameState->GetPlayerState(); - if (state.IsFusionEnabled()) - { - switch (state.x20_currentSuit) - { - case CPlayerState::EPlayerSuit::Power: - return 4; - case CPlayerState::EPlayerSuit::Gravity: - return 6; - case CPlayerState::EPlayerSuit::Varia: - return 7; - case CPlayerState::EPlayerSuit::Phazon: - return 8; - default: break; - } +int CWorldTransManager::GetSuitCharIdx() { + CPlayerState& state = *g_GameState->GetPlayerState(); + if (state.IsFusionEnabled()) { + switch (state.x20_currentSuit) { + case CPlayerState::EPlayerSuit::Power: + return 4; + case CPlayerState::EPlayerSuit::Gravity: + return 6; + case CPlayerState::EPlayerSuit::Varia: + return 7; + case CPlayerState::EPlayerSuit::Phazon: + return 8; + default: + break; } - return int(state.x20_currentSuit); + } + return int(state.x20_currentSuit); } -CWorldTransManager::SModelDatas::SModelDatas(const CAnimRes& samusRes) -: x0_samusRes(samusRes) -{ - x1a0_lights.reserve(8); +CWorldTransManager::SModelDatas::SModelDatas(const CAnimRes& samusRes) : x0_samusRes(samusRes) { + x1a0_lights.reserve(8); } -void CWorldTransManager::UpdateLights(float dt) -{ - if (!x4_modelData) - return; +void CWorldTransManager::UpdateLights(float dt) { + if (!x4_modelData) + return; - x4_modelData->x1a0_lights.clear(); - zeus::CVector3f lightPos(0.f, 10.f, 0.f); - CLight spot = CLight::BuildSpot(lightPos, zeus::CVector3f::skBack, zeus::CColor::skWhite, 90.f); - spot.SetAttenuation(1.f, 0.f, 0.f); + x4_modelData->x1a0_lights.clear(); + zeus::CVector3f lightPos(0.f, 10.f, 0.f); + CLight spot = CLight::BuildSpot(lightPos, zeus::CVector3f::skBack, zeus::CColor::skWhite, 90.f); + spot.SetAttenuation(1.f, 0.f, 0.f); - CLight s1 = spot; - s1.SetPosition(lightPos + zeus::CVector3f{0.f, 0.f, 2.f * x18_bgOffset - x1c_bgHeight}); + CLight s1 = spot; + s1.SetPosition(lightPos + zeus::CVector3f{0.f, 0.f, 2.f * x18_bgOffset - x1c_bgHeight}); - float z = 1.f; - float delta = x1c_bgHeight - x18_bgOffset; - if (!x44_26_goingUp && delta < 2.f) - z = delta * 0.5f; - else if (x44_26_goingUp && x18_bgOffset < 2.f) - z = x18_bgOffset * 0.5f; + float z = 1.f; + float delta = x1c_bgHeight - x18_bgOffset; + if (!x44_26_goingUp && delta < 2.f) + z = delta * 0.5f; + else if (x44_26_goingUp && x18_bgOffset < 2.f) + z = x18_bgOffset * 0.5f; - if (z < 1.f) - { - CLight s2 = spot; - float pos = x44_26_goingUp ? x1c_bgHeight : -x1c_bgHeight; - s2.SetPosition(lightPos + zeus::CVector3f{0.f, 0.f, pos}); - s2.SetColor(zeus::CColor::lerp(zeus::CColor::skBlack, zeus::CColor::skWhite, 1.f - z)); - x4_modelData->x1a0_lights.push_back(std::move(s2)); - s1.SetColor(zeus::CColor::lerp(zeus::CColor::skBlack, zeus::CColor::skWhite, z)); - } + if (z < 1.f) { + CLight s2 = spot; + float pos = x44_26_goingUp ? x1c_bgHeight : -x1c_bgHeight; + s2.SetPosition(lightPos + zeus::CVector3f{0.f, 0.f, pos}); + s2.SetColor(zeus::CColor::lerp(zeus::CColor::skBlack, zeus::CColor::skWhite, 1.f - z)); + x4_modelData->x1a0_lights.push_back(std::move(s2)); + s1.SetColor(zeus::CColor::lerp(zeus::CColor::skBlack, zeus::CColor::skWhite, z)); + } - x4_modelData->x1a0_lights.push_back(std::move(s1)); + x4_modelData->x1a0_lights.push_back(std::move(s1)); } -void CWorldTransManager::UpdateDisabled(float) -{ - if (x0_curTime <= 2.f) - return; - x44_24_transFinished = true; +void CWorldTransManager::UpdateDisabled(float) { + if (x0_curTime <= 2.f) + return; + x44_24_transFinished = true; } -void CWorldTransManager::UpdateEnabled(float dt) -{ - if (x4_modelData && !x4_modelData->x1c_samusModelData.IsNull()) - { - if (x44_25_stopSoon && !x4_modelData->x1dc_dissolveStarted && x0_curTime > 2.f) - { - x4_modelData->x1dc_dissolveStarted = true; - x4_modelData->x1d0_dissolveStartTime = x0_curTime; - x4_modelData->x1d4_dissolveEndTime = 4.f + x0_curTime - 2.f; - x4_modelData->x1d8_transCompleteTime = 5.f + x0_curTime - 2.f; - } - - if (x0_curTime > x4_modelData->x1d8_transCompleteTime && x4_modelData->x1dc_dissolveStarted) - x44_24_transFinished = true; - - x4_modelData->x1c_samusModelData.AdvanceAnimationIgnoreParticles(dt, x20_random, true); - x4_modelData->x170_gunXf = x4_modelData->x1c_samusModelData.GetScaledLocatorTransform("GUN_LCTR"); - - x4_modelData->x1c4_randTimeout -= dt; - - if (x4_modelData->x1c4_randTimeout <= 0.f) - { - x4_modelData->x1c4_randTimeout = x20_random.Range(0.016666668f, 0.1f); - zeus::CVector2f randVec(x20_random.Range(-0.025f, 0.025f), x20_random.Range(-0.075f, 0.075f)); - x4_modelData->x1bc_shakeDelta = (randVec - x4_modelData->x1b4_shakeResult) / x4_modelData->x1c4_randTimeout; - x4_modelData->x1cc_blurDelta = (x20_random.Range(-2.f, 4.f) - x4_modelData->x1c8_blurResult) / x4_modelData->x1c4_randTimeout; - } - - x4_modelData->x1b4_shakeResult += x4_modelData->x1bc_shakeDelta * dt; - x4_modelData->x1c8_blurResult += dt * x4_modelData->x1cc_blurDelta; +void CWorldTransManager::UpdateEnabled(float dt) { + if (x4_modelData && !x4_modelData->x1c_samusModelData.IsNull()) { + if (x44_25_stopSoon && !x4_modelData->x1dc_dissolveStarted && x0_curTime > 2.f) { + x4_modelData->x1dc_dissolveStarted = true; + x4_modelData->x1d0_dissolveStartTime = x0_curTime; + x4_modelData->x1d4_dissolveEndTime = 4.f + x0_curTime - 2.f; + x4_modelData->x1d8_transCompleteTime = 5.f + x0_curTime - 2.f; } - float delta = dt * 50.f; - if (x44_26_goingUp) - delta = -delta; + if (x0_curTime > x4_modelData->x1d8_transCompleteTime && x4_modelData->x1dc_dissolveStarted) + x44_24_transFinished = true; - x18_bgOffset += delta; - if (x18_bgOffset > x1c_bgHeight) - x18_bgOffset -= x1c_bgHeight; - if (x18_bgOffset < 0.f) - x18_bgOffset += x1c_bgHeight; + x4_modelData->x1c_samusModelData.AdvanceAnimationIgnoreParticles(dt, x20_random, true); + x4_modelData->x170_gunXf = x4_modelData->x1c_samusModelData.GetScaledLocatorTransform("GUN_LCTR"); - UpdateLights(dt); + x4_modelData->x1c4_randTimeout -= dt; + + if (x4_modelData->x1c4_randTimeout <= 0.f) { + x4_modelData->x1c4_randTimeout = x20_random.Range(0.016666668f, 0.1f); + zeus::CVector2f randVec(x20_random.Range(-0.025f, 0.025f), x20_random.Range(-0.075f, 0.075f)); + x4_modelData->x1bc_shakeDelta = (randVec - x4_modelData->x1b4_shakeResult) / x4_modelData->x1c4_randTimeout; + x4_modelData->x1cc_blurDelta = + (x20_random.Range(-2.f, 4.f) - x4_modelData->x1c8_blurResult) / x4_modelData->x1c4_randTimeout; + } + + x4_modelData->x1b4_shakeResult += x4_modelData->x1bc_shakeDelta * dt; + x4_modelData->x1c8_blurResult += dt * x4_modelData->x1cc_blurDelta; + } + + float delta = dt * 50.f; + if (x44_26_goingUp) + delta = -delta; + + x18_bgOffset += delta; + if (x18_bgOffset > x1c_bgHeight) + x18_bgOffset -= x1c_bgHeight; + if (x18_bgOffset < 0.f) + x18_bgOffset += x1c_bgHeight; + + UpdateLights(dt); } -void CWorldTransManager::UpdateText(float dt) -{ - if (x44_28_textDirty) - { - if (xc_strTable.IsLoaded()) - { - x8_textData->SetText(xc_strTable->GetString(x40_strIdx)); - x3c_sfxInterval = 0.f; - x44_28_textDirty = false; - } - else if (x0_curTime >= x38_textStartTime) - { - x38_textStartTime += dt; - } +void CWorldTransManager::UpdateText(float dt) { + if (x44_28_textDirty) { + if (xc_strTable.IsLoaded()) { + x8_textData->SetText(xc_strTable->GetString(x40_strIdx)); + x3c_sfxInterval = 0.f; + x44_28_textDirty = false; + } else if (x0_curTime >= x38_textStartTime) { + x38_textStartTime += dt; } + } - if (x0_curTime >= x38_textStartTime) - { - x8_textData->Update(dt); + if (x0_curTime >= x38_textStartTime) { + x8_textData->Update(dt); - float nextSfxInterval = x3c_sfxInterval + g_tweakGui->GetWorldTransManagerCharsPerSfx(); - float printed = x8_textData->GetNumCharsPrinted(); - if (printed >= nextSfxInterval) - { - x3c_sfxInterval = nextSfxInterval; - CSfxManager::SfxStart(SFXsfx059E, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); - } + float nextSfxInterval = x3c_sfxInterval + g_tweakGui->GetWorldTransManagerCharsPerSfx(); + float printed = x8_textData->GetNumCharsPrinted(); + if (printed >= nextSfxInterval) { + x3c_sfxInterval = nextSfxInterval; + CSfxManager::SfxStart(SFXsfx059E, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); } + } - if (x44_25_stopSoon) - { - if (x8_textData->GetTotalAnimationTime() + 1.f < x8_textData->GetCurTime()) - { - /* Done typing + 1 sec */ - if (x0_curTime - x34_stopTime > 1.f) - x44_24_transFinished = true; - } - else - { - x34_stopTime = x0_curTime; - } + if (x44_25_stopSoon) { + if (x8_textData->GetTotalAnimationTime() + 1.f < x8_textData->GetCurTime()) { + /* Done typing + 1 sec */ + if (x0_curTime - x34_stopTime > 1.f) + x44_24_transFinished = true; + } else { + x34_stopTime = x0_curTime; } + } } -void CWorldTransManager::Update(float dt) -{ - x0_curTime += dt; - switch (x30_type) - { - case ETransType::Disabled: - UpdateDisabled(dt); - break; - case ETransType::Enabled: - UpdateEnabled(dt); - break; - case ETransType::Text: - UpdateText(dt); - break; - } +void CWorldTransManager::Update(float dt) { + x0_curTime += dt; + switch (x30_type) { + case ETransType::Disabled: + UpdateDisabled(dt); + break; + case ETransType::Enabled: + UpdateEnabled(dt); + break; + case ETransType::Text: + UpdateText(dt); + break; + } } -void CWorldTransManager::DrawAllModels() -{ - CActorLights lights(0, zeus::CVector3f::skZero, 4, 4, 0, 0, 0, 0.1f); - lights.BuildFakeLightList(x4_modelData->x1a0_lights, zeus::CColor{0.1f, 0.1f, 0.1f, 1.0f}); +void CWorldTransManager::DrawAllModels() { + CActorLights lights(0, zeus::CVector3f::skZero, 4, 4, 0, 0, 0, 0.1f); + lights.BuildFakeLightList(x4_modelData->x1a0_lights, zeus::CColor{0.1f, 0.1f, 0.1f, 1.0f}); - CModelFlags flags = {}; - flags.m_extendedShader = EExtendedShader::Lighting; + CModelFlags flags = {}; + flags.m_extendedShader = EExtendedShader::Lighting; - if (!x4_modelData->x100_bgModelData[0].IsNull()) - { - zeus::CTransform xf0 = zeus::CTransform::Translate(0.f, 0.f, -(2.f * x1c_bgHeight - x18_bgOffset)); - x4_modelData->x100_bgModelData[0].Render(CModelData::EWhichModel::Normal, xf0, &lights, flags); - } - if (!x4_modelData->x100_bgModelData[1].IsNull()) - { - zeus::CTransform xf1 = zeus::CTransform::Translate(0.f, 0.f, x18_bgOffset - x1c_bgHeight); - x4_modelData->x100_bgModelData[1].Render(CModelData::EWhichModel::Normal, xf1, &lights, flags); - } - if (!x4_modelData->x100_bgModelData[2].IsNull()) - { - zeus::CTransform xf2 = zeus::CTransform::Translate(0.f, 0.f, x18_bgOffset); - x4_modelData->x100_bgModelData[2].Render(CModelData::EWhichModel::Normal, xf2, &lights, flags); - } + if (!x4_modelData->x100_bgModelData[0].IsNull()) { + zeus::CTransform xf0 = zeus::CTransform::Translate(0.f, 0.f, -(2.f * x1c_bgHeight - x18_bgOffset)); + x4_modelData->x100_bgModelData[0].Render(CModelData::EWhichModel::Normal, xf0, &lights, flags); + } + if (!x4_modelData->x100_bgModelData[1].IsNull()) { + zeus::CTransform xf1 = zeus::CTransform::Translate(0.f, 0.f, x18_bgOffset - x1c_bgHeight); + x4_modelData->x100_bgModelData[1].Render(CModelData::EWhichModel::Normal, xf1, &lights, flags); + } + if (!x4_modelData->x100_bgModelData[2].IsNull()) { + zeus::CTransform xf2 = zeus::CTransform::Translate(0.f, 0.f, x18_bgOffset); + x4_modelData->x100_bgModelData[2].Render(CModelData::EWhichModel::Normal, xf2, &lights, flags); + } - if (!x4_modelData->xb4_platformModelData.IsNull()) - { - x4_modelData->xb4_platformModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), &lights, flags); - } + if (!x4_modelData->xb4_platformModelData.IsNull()) { + x4_modelData->xb4_platformModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), &lights, + flags); + } - if (!x4_modelData->x1c_samusModelData.IsNull()) - { - x4_modelData->x1c_samusModelData.AnimationData()->PreRender(); - x4_modelData->x1c_samusModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), &lights, flags); + if (!x4_modelData->x1c_samusModelData.IsNull()) { + x4_modelData->x1c_samusModelData.AnimationData()->PreRender(); + x4_modelData->x1c_samusModelData.Render(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), &lights, + flags); - if (!x4_modelData->x68_beamModelData.IsNull()) - { - x4_modelData->x68_beamModelData.Render(CModelData::EWhichModel::Normal, x4_modelData->x170_gunXf, &lights, flags); - } + if (!x4_modelData->x68_beamModelData.IsNull()) { + x4_modelData->x68_beamModelData.Render(CModelData::EWhichModel::Normal, x4_modelData->x170_gunXf, &lights, flags); } + } } -void CWorldTransManager::DrawFirstPass() -{ - zeus::CTransform translateXf = - zeus::CTransform::Translate(x4_modelData->x1b4_shakeResult.x(), - -3.5f * (1.f - zeus::clamp(0.f, x0_curTime / 10.f, 1.f)) - 3.5f, - x4_modelData->x1b4_shakeResult.y() + 2.f); - zeus::CTransform rotateXf = - zeus::CTransform::RotateZ(zeus::degToRad(zeus::clamp(0.f, x0_curTime / 25.f, 100.f) * - 360.f + 180.f - 90.f)); - CGraphics::SetViewPointMatrix(rotateXf * translateXf); - DrawAllModels(); - m_camblur.draw(x4_modelData->x1c8_blurResult); +void CWorldTransManager::DrawFirstPass() { + zeus::CTransform translateXf = zeus::CTransform::Translate( + x4_modelData->x1b4_shakeResult.x(), -3.5f * (1.f - zeus::clamp(0.f, x0_curTime / 10.f, 1.f)) - 3.5f, + x4_modelData->x1b4_shakeResult.y() + 2.f); + zeus::CTransform rotateXf = + zeus::CTransform::RotateZ(zeus::degToRad(zeus::clamp(0.f, x0_curTime / 25.f, 100.f) * 360.f + 180.f - 90.f)); + CGraphics::SetViewPointMatrix(rotateXf * translateXf); + DrawAllModels(); + m_camblur.draw(x4_modelData->x1c8_blurResult); } -void CWorldTransManager::DrawSecondPass() -{ - const zeus::CVector3f& samusScale = x4_modelData->x0_samusRes.GetScale(); - zeus::CTransform translateXf = - zeus::CTransform::Translate(-0.1f * samusScale.x(), - -0.5f * samusScale.y(), - 1.5f * samusScale.z()); - zeus::CTransform rotateXf = - zeus::CTransform::RotateZ(zeus::degToRad(48.f * - zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime + 2.f) / 5.f, 1.f) + 180.f - 24.f)); - CGraphics::SetViewPointMatrix(rotateXf * translateXf); - DrawAllModels(); +void CWorldTransManager::DrawSecondPass() { + const zeus::CVector3f& samusScale = x4_modelData->x0_samusRes.GetScale(); + zeus::CTransform translateXf = + zeus::CTransform::Translate(-0.1f * samusScale.x(), -0.5f * samusScale.y(), 1.5f * samusScale.z()); + zeus::CTransform rotateXf = zeus::CTransform::RotateZ(zeus::degToRad( + 48.f * zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime + 2.f) / 5.f, 1.f) + 180.f - 24.f)); + CGraphics::SetViewPointMatrix(rotateXf * translateXf); + DrawAllModels(); } -void CWorldTransManager::DrawEnabled() -{ - float wsAspect = CWideScreenFilter::SetViewportToMatch(1.f); +void CWorldTransManager::DrawEnabled() { + float wsAspect = CWideScreenFilter::SetViewportToMatch(1.f); - g_Renderer->SetPerspective(CCameraManager::FirstPersonFOV(), - wsAspect, - CCameraManager::NearPlane(), - CCameraManager::FarPlane()); - g_Renderer->x318_26_requestRGBA6 = true; + g_Renderer->SetPerspective(CCameraManager::FirstPersonFOV(), wsAspect, CCameraManager::NearPlane(), + CCameraManager::FarPlane()); + g_Renderer->x318_26_requestRGBA6 = true; - if (x0_curTime <= x4_modelData->x1d0_dissolveStartTime) - DrawFirstPass(); - else if (x0_curTime >= x4_modelData->x1d4_dissolveEndTime) - DrawSecondPass(); - else - { - float t = zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime) / 2.f, 1.f); - DrawFirstPass(); - SClipScreenRect rect(g_Viewport); - CGraphics::ResolveSpareTexture(rect); - CGraphics::g_BooMainCommandQueue->clearTarget(true, true); - DrawSecondPass(); - m_dissolve.drawCropped(zeus::CColor{1.f, 1.f, 1.f, 1.f - t}, 1.f); - } + if (x0_curTime <= x4_modelData->x1d0_dissolveStartTime) + DrawFirstPass(); + else if (x0_curTime >= x4_modelData->x1d4_dissolveEndTime) + DrawSecondPass(); + else { + float t = zeus::clamp(0.f, (x0_curTime - x4_modelData->x1d0_dissolveStartTime) / 2.f, 1.f); + DrawFirstPass(); + SClipScreenRect rect(g_Viewport); + CGraphics::ResolveSpareTexture(rect); + CGraphics::g_BooMainCommandQueue->clearTarget(true, true); + DrawSecondPass(); + m_dissolve.drawCropped(zeus::CColor{1.f, 1.f, 1.f, 1.f - t}, 1.f); + } - CWideScreenFilter::SetViewportToFull(); - m_widescreen.draw(zeus::CColor::skBlack, 1.f); + CWideScreenFilter::SetViewportToFull(); + m_widescreen.draw(zeus::CColor::skBlack, 1.f); - float ftbT = 0.f; - if (x0_curTime < 0.25f) - ftbT = 1.f - x0_curTime / 0.25f; - else if (x0_curTime > x4_modelData->x1d8_transCompleteTime) - ftbT = 1.f; - else if (x0_curTime > x4_modelData->x1d8_transCompleteTime - 0.25f) - ftbT = 1.f - (x4_modelData->x1d8_transCompleteTime - x0_curTime) / 0.25f; - if (ftbT > 0.f) - m_fadeToBlack.draw(zeus::CColor{0.f, 0.f, 0.f, ftbT}); + float ftbT = 0.f; + if (x0_curTime < 0.25f) + ftbT = 1.f - x0_curTime / 0.25f; + else if (x0_curTime > x4_modelData->x1d8_transCompleteTime) + ftbT = 1.f; + else if (x0_curTime > x4_modelData->x1d8_transCompleteTime - 0.25f) + ftbT = 1.f - (x4_modelData->x1d8_transCompleteTime - x0_curTime) / 0.25f; + if (ftbT > 0.f) + m_fadeToBlack.draw(zeus::CColor{0.f, 0.f, 0.f, ftbT}); } -void CWorldTransManager::DrawDisabled() -{ - m_fadeToBlack.draw(zeus::CColor{0.f, 0.f, 0.f, 0.01f}); +void CWorldTransManager::DrawDisabled() { m_fadeToBlack.draw(zeus::CColor{0.f, 0.f, 0.f, 0.01f}); } + +void CWorldTransManager::DrawText() { + float vpAspectRatio = g_Viewport.x8_width / float(g_Viewport.xc_height); + float width = 448.f * vpAspectRatio; + CGraphics::SetOrtho(0.f, width, 448.f, 0.f, -4096.f, 4096.f); + CGraphics::SetViewPointMatrix(zeus::CTransform::Identity()); + CGraphics::SetModelMatrix(zeus::CTransform::Translate((width - 640.f) / 2.f, 0.f, 448.f)); + x8_textData->Render(); + + float filterAlpha = 0.f; + if (x0_curTime < 1.f) + filterAlpha = 1.f - x0_curTime; + else if (x44_25_stopSoon) + filterAlpha = std::min(1.f, x0_curTime - x34_stopTime); + + if (filterAlpha > 0.f) { + zeus::CColor filterColor = x44_27_fadeWhite ? zeus::CColor::skWhite : zeus::CColor::skBlack; + filterColor.a() = filterAlpha; + m_fadeToBlack.draw(filterColor); + } } -void CWorldTransManager::DrawText() -{ - float vpAspectRatio = g_Viewport.x8_width / float(g_Viewport.xc_height); - float width = 448.f * vpAspectRatio; - CGraphics::SetOrtho(0.f, width, 448.f, 0.f, -4096.f, 4096.f); - CGraphics::SetViewPointMatrix(zeus::CTransform::Identity()); - CGraphics::SetModelMatrix(zeus::CTransform::Translate((width - 640.f) / 2.f, 0.f, 448.f)); - x8_textData->Render(); - - float filterAlpha = 0.f; - if (x0_curTime < 1.f) - filterAlpha = 1.f - x0_curTime; - else if (x44_25_stopSoon) - filterAlpha = std::min(1.f, x0_curTime - x34_stopTime); - - if (filterAlpha > 0.f) - { - zeus::CColor filterColor = x44_27_fadeWhite ? zeus::CColor::skWhite : zeus::CColor::skBlack; - filterColor.a() = filterAlpha; - m_fadeToBlack.draw(filterColor); - } +void CWorldTransManager::Draw() { + if (x30_type == ETransType::Disabled) + DrawDisabled(); + else if (x30_type == ETransType::Enabled) + DrawEnabled(); + else if (x30_type == ETransType::Text) + DrawText(); } -void CWorldTransManager::Draw() -{ - if (x30_type == ETransType::Disabled) - DrawDisabled(); - else if (x30_type == ETransType::Enabled) - DrawEnabled(); - else if (x30_type == ETransType::Text) - DrawText(); +void CWorldTransManager::TouchModels() { + if (!x4_modelData) + return; + + if (x4_modelData->x68_beamModelData.IsNull() && x4_modelData->x14c_beamModel.IsLoaded() && + x4_modelData->x14c_beamModel.GetObj()) { + x4_modelData->x68_beamModelData = { + CStaticRes(x4_modelData->x14c_beamModel.GetObjectTag()->id, x4_modelData->x0_samusRes.GetScale()), 2}; + } + + if (x4_modelData->x1c_samusModelData.IsNull() && x4_modelData->x158_suitModel.IsLoaded() && + x4_modelData->x158_suitModel.GetObj() && x4_modelData->x164_suitSkin.IsLoaded() && + x4_modelData->x164_suitSkin.GetObj()) { + CAnimRes animRes(x4_modelData->x0_samusRes.GetId(), GetSuitCharIdx(), x4_modelData->x0_samusRes.GetScale(), + x4_modelData->x0_samusRes.GetDefaultAnim(), true); + x4_modelData->x1c_samusModelData = {animRes, 2}; + + CAnimPlaybackParms aData(animRes.GetDefaultAnim(), -1, 1.f, true); + x4_modelData->x1c_samusModelData.AnimationData()->SetAnimation(aData, false); + } + + if (!x4_modelData->x1c_samusModelData.IsNull()) + x4_modelData->x1c_samusModelData.Touch(CModelData::EWhichModel::Normal, 0); + + if (!x4_modelData->xb4_platformModelData.IsNull()) + x4_modelData->xb4_platformModelData.Touch(CModelData::EWhichModel::Normal, 0); + + if (!x4_modelData->x100_bgModelData[0].IsNull()) + x4_modelData->x100_bgModelData[0].Touch(CModelData::EWhichModel::Normal, 0); + if (!x4_modelData->x100_bgModelData[1].IsNull()) + x4_modelData->x100_bgModelData[1].Touch(CModelData::EWhichModel::Normal, 0); + if (!x4_modelData->x100_bgModelData[2].IsNull()) + x4_modelData->x100_bgModelData[2].Touch(CModelData::EWhichModel::Normal, 0); + + if (!x4_modelData->x68_beamModelData.IsNull()) + x4_modelData->x68_beamModelData.Touch(CModelData::EWhichModel::Normal, 0); } -void CWorldTransManager::TouchModels() -{ - if (!x4_modelData) - return; +void CWorldTransManager::EnableTransition(const CAnimRes& samusRes, CAssetId platRes, const zeus::CVector3f& platScale, + CAssetId bgRes, const zeus::CVector3f& bgScale, bool goingUp) { + x44_25_stopSoon = false; + x44_26_goingUp = goingUp; + x30_type = ETransType::Enabled; + x4_modelData.reset(new SModelDatas(samusRes)); - if (x4_modelData->x68_beamModelData.IsNull() && - x4_modelData->x14c_beamModel.IsLoaded() && - x4_modelData->x14c_beamModel.GetObj()) - { - x4_modelData->x68_beamModelData = {CStaticRes(x4_modelData->x14c_beamModel.GetObjectTag()->id, - x4_modelData->x0_samusRes.GetScale()), 2}; - } + x8_textData.reset(); + x20_random.SetSeed(99); - if (x4_modelData->x1c_samusModelData.IsNull() && - x4_modelData->x158_suitModel.IsLoaded() && - x4_modelData->x158_suitModel.GetObj() && - x4_modelData->x164_suitSkin.IsLoaded() && - x4_modelData->x164_suitSkin.GetObj()) - { - CAnimRes animRes(x4_modelData->x0_samusRes.GetId(), GetSuitCharIdx(), - x4_modelData->x0_samusRes.GetScale(), x4_modelData->x0_samusRes.GetDefaultAnim(), - true); - x4_modelData->x1c_samusModelData = {animRes, 2}; + CAssetId beamModelId = g_tweakPlayerRes->GetBeamCineModel(g_GameState->GetPlayerState()->GetCurrentBeam()); - CAnimPlaybackParms aData(animRes.GetDefaultAnim(), -1, 1.f, true); - x4_modelData->x1c_samusModelData.AnimationData()->SetAnimation(aData, false); - } + x4_modelData->x14c_beamModel = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), beamModelId}); - if (!x4_modelData->x1c_samusModelData.IsNull()) - x4_modelData->x1c_samusModelData.Touch(CModelData::EWhichModel::Normal, 0); + TToken fac = g_CharFactoryBuilder->GetFactory(samusRes); + const CCharacterInfo& info = fac.GetObj()->GetCharInfo(GetSuitCharIdx()); + x4_modelData->x158_suitModel = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), info.GetModelId()}); + x4_modelData->x164_suitSkin = g_SimplePool->GetObj(SObjectTag{FOURCC('CSKR'), info.GetSkinRulesId()}); - if (!x4_modelData->xb4_platformModelData.IsNull()) - x4_modelData->xb4_platformModelData.Touch(CModelData::EWhichModel::Normal, 0); + if (platRes.IsValid()) { + x4_modelData->xb4_platformModelData = {CStaticRes(platRes, platScale), 2}; + x4_modelData->xb4_platformModelData.Touch(CModelData::EWhichModel::Normal, 0); + } - if (!x4_modelData->x100_bgModelData[0].IsNull()) - x4_modelData->x100_bgModelData[0].Touch(CModelData::EWhichModel::Normal, 0); - if (!x4_modelData->x100_bgModelData[1].IsNull()) - x4_modelData->x100_bgModelData[1].Touch(CModelData::EWhichModel::Normal, 0); - if (!x4_modelData->x100_bgModelData[2].IsNull()) - x4_modelData->x100_bgModelData[2].Touch(CModelData::EWhichModel::Normal, 0); + if (bgRes.IsValid()) { + CStaticRes bg(bgRes, bgScale); + x4_modelData->x100_bgModelData[0] = bg; + x4_modelData->x100_bgModelData[0].Touch(CModelData::EWhichModel::Normal, 0); + x4_modelData->x100_bgModelData[1] = bg; + x4_modelData->x100_bgModelData[1].Touch(CModelData::EWhichModel::Normal, 0); + x4_modelData->x100_bgModelData[2] = bg; + x4_modelData->x100_bgModelData[2].Touch(CModelData::EWhichModel::Normal, 0); + zeus::CAABox bounds = x4_modelData->x100_bgModelData[0].GetBounds(); + x1c_bgHeight = (bounds.max.z() - bounds.min.z()) * bgScale.z(); + } else + x1c_bgHeight = 0.f; - if (!x4_modelData->x68_beamModelData.IsNull()) - x4_modelData->x68_beamModelData.Touch(CModelData::EWhichModel::Normal, 0); -} - -void CWorldTransManager::EnableTransition(const CAnimRes& samusRes, - CAssetId platRes, const zeus::CVector3f& platScale, - CAssetId bgRes, const zeus::CVector3f& bgScale, bool goingUp) -{ - x44_25_stopSoon = false; - x44_26_goingUp = goingUp; - x30_type = ETransType::Enabled; - x4_modelData.reset(new SModelDatas(samusRes)); - - x8_textData.reset(); - x20_random.SetSeed(99); - - CAssetId beamModelId = g_tweakPlayerRes->GetBeamCineModel(g_GameState->GetPlayerState()->GetCurrentBeam()); - - x4_modelData->x14c_beamModel = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), beamModelId}); - - TToken fac = g_CharFactoryBuilder->GetFactory(samusRes); - const CCharacterInfo& info = fac.GetObj()->GetCharInfo(GetSuitCharIdx()); - x4_modelData->x158_suitModel = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), info.GetModelId()}); - x4_modelData->x164_suitSkin = g_SimplePool->GetObj(SObjectTag{FOURCC('CSKR'), info.GetSkinRulesId()}); - - if (platRes.IsValid()) - { - x4_modelData->xb4_platformModelData = {CStaticRes(platRes, platScale), 2}; - x4_modelData->xb4_platformModelData.Touch(CModelData::EWhichModel::Normal, 0); - } - - if (bgRes.IsValid()) - { - CStaticRes bg(bgRes, bgScale); - x4_modelData->x100_bgModelData[0] = bg; - x4_modelData->x100_bgModelData[0].Touch(CModelData::EWhichModel::Normal, 0); - x4_modelData->x100_bgModelData[1] = bg; - x4_modelData->x100_bgModelData[1].Touch(CModelData::EWhichModel::Normal, 0); - x4_modelData->x100_bgModelData[2] = bg; - x4_modelData->x100_bgModelData[2].Touch(CModelData::EWhichModel::Normal, 0); - zeus::CAABox bounds = x4_modelData->x100_bgModelData[0].GetBounds(); - x1c_bgHeight = (bounds.max.z() - bounds.min.z()) * bgScale.z(); - } - else - x1c_bgHeight = 0.f; - - StartTransition(); - TouchModels(); + StartTransition(); + TouchModels(); } void CWorldTransManager::EnableTransition(CAssetId fontId, CAssetId stringId, u32 strIdx, bool fadeWhite, - float chFadeTime, float chFadeRate, float textStartTime) -{ - x40_strIdx = strIdx; - x38_textStartTime = textStartTime; - x44_25_stopSoon = false; - x30_type = ETransType::Text; + float chFadeTime, float chFadeRate, float textStartTime) { + x40_strIdx = strIdx; + x38_textStartTime = textStartTime; + x44_25_stopSoon = false; + x30_type = ETransType::Text; - x4_modelData.reset(); - x44_27_fadeWhite = fadeWhite; + x4_modelData.reset(); + x44_27_fadeWhite = fadeWhite; - CGuiTextProperties props(false, true, EJustification::Center, EVerticalJustification::Center); - x8_textData.reset(new CGuiTextSupport(fontId, props, zeus::CColor::skWhite, - zeus::CColor::skBlack, zeus::CColor::skWhite, - 640, 448, g_SimplePool, CGuiWidget::EGuiModelDrawFlags::Additive)); + CGuiTextProperties props(false, true, EJustification::Center, EVerticalJustification::Center); + x8_textData.reset(new CGuiTextSupport(fontId, props, zeus::CColor::skWhite, zeus::CColor::skBlack, + zeus::CColor::skWhite, 640, 448, g_SimplePool, + CGuiWidget::EGuiModelDrawFlags::Additive)); - x8_textData->SetTypeWriteEffectOptions(true, chFadeTime, chFadeRate); - xc_strTable = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), stringId}); - x8_textData->SetText(u""); - StartTransition(); + x8_textData->SetTypeWriteEffectOptions(true, chFadeTime, chFadeRate); + xc_strTable = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), stringId}); + x8_textData->SetText(u""); + StartTransition(); } -void CWorldTransManager::StartTextFadeOut() -{ - if (!x44_25_stopSoon) - x34_stopTime = x0_curTime; - x44_25_stopSoon = true; +void CWorldTransManager::StartTextFadeOut() { + if (!x44_25_stopSoon) + x34_stopTime = x0_curTime; + x44_25_stopSoon = true; } -void CWorldTransManager::DisableTransition() -{ - x30_type = ETransType::Disabled; - x4_modelData.reset(); - x8_textData.reset(); - x44_26_goingUp = false; +void CWorldTransManager::DisableTransition() { + x30_type = ETransType::Disabled; + x4_modelData.reset(); + x8_textData.reset(); + x44_26_goingUp = false; } -void CWorldTransManager::StartTransition() -{ - x0_curTime = 0.f; - x18_bgOffset = 0.f; - x44_24_transFinished = false; - x44_28_textDirty = true; +void CWorldTransManager::StartTransition() { + x0_curTime = 0.f; + x18_bgOffset = 0.f; + x44_24_transFinished = false; + x44_28_textDirty = true; } -void CWorldTransManager::EndTransition() -{ - DisableTransition(); +void CWorldTransManager::EndTransition() { DisableTransition(); } + +bool CWorldTransManager::WaitForModelsAndTextures() { + std::vector tags = g_SimplePool->GetReferencedTags(); + for (const SObjectTag& tag : tags) { + if (tag.type == FOURCC('TXTR') || tag.type == FOURCC('CMDL')) + g_SimplePool->GetObj(tag).GetObj(); + } + return false; } -bool CWorldTransManager::WaitForModelsAndTextures() -{ - std::vector tags = g_SimplePool->GetReferencedTags(); - for (const SObjectTag& tag : tags) - { - if (tag.type == FOURCC('TXTR') || tag.type == FOURCC('CMDL')) - g_SimplePool->GetObj(tag).GetObj(); - } - return false; +void CWorldTransManager::SfxStop() { + if (x28_sfxHandle) { + CSfxManager::SfxStop(x28_sfxHandle); + x28_sfxHandle.reset(); + } } -void CWorldTransManager::SfxStop() -{ - if (x28_sfxHandle) - { - CSfxManager::SfxStop(x28_sfxHandle); - x28_sfxHandle.reset(); - } +void CWorldTransManager::SfxStart() { + if (!x28_sfxHandle && x24_sfx != 0xFFFF) + x28_sfxHandle = CSfxManager::SfxStart(x24_sfx, x2c_volume, x2d_panning, false, 127, true, -1); } -void CWorldTransManager::SfxStart() -{ - if (!x28_sfxHandle && x24_sfx != 0xFFFF) - x28_sfxHandle = CSfxManager::SfxStart(x24_sfx, x2c_volume, x2d_panning, false, 127, true, -1); -} - -} +} // namespace urde diff --git a/Runtime/World/CWorldTransManager.hpp b/Runtime/World/CWorldTransManager.hpp index 37ab2188f..bb7c829df 100644 --- a/Runtime/World/CWorldTransManager.hpp +++ b/Runtime/World/CWorldTransManager.hpp @@ -10,128 +10,114 @@ #include "Graphics/Shaders/CCameraBlurFilter.hpp" #include "Audio/CSfxManager.hpp" -namespace urde -{ +namespace urde { class CSimplePool; class CStringTable; -class CWorldTransManager -{ +class CWorldTransManager { public: - enum class ETransType - { - Disabled, - Enabled, - Text - }; + enum class ETransType { Disabled, Enabled, Text }; - struct SModelDatas - { - CAnimRes x0_samusRes; - CModelData x1c_samusModelData; - CModelData x68_beamModelData; - CModelData xb4_platformModelData; - CModelData x100_bgModelData[3]; - TLockedToken x14c_beamModel; - TLockedToken x158_suitModel; - TLockedToken x164_suitSkin; - zeus::CTransform x170_gunXf; - std::vector x1a0_lights; - //std::unique_ptr x1b0_dissolveTextureBuffer; - zeus::CVector2f x1b4_shakeResult; - zeus::CVector2f x1bc_shakeDelta; - float x1c4_randTimeout = 0.f; - float x1c8_blurResult = 0.f; - float x1cc_blurDelta = 0.f; - float x1d0_dissolveStartTime = 99999.f; - float x1d4_dissolveEndTime = 99999.f; - float x1d8_transCompleteTime = 99999.f; - bool x1dc_dissolveStarted = false; + struct SModelDatas { + CAnimRes x0_samusRes; + CModelData x1c_samusModelData; + CModelData x68_beamModelData; + CModelData xb4_platformModelData; + CModelData x100_bgModelData[3]; + TLockedToken x14c_beamModel; + TLockedToken x158_suitModel; + TLockedToken x164_suitSkin; + zeus::CTransform x170_gunXf; + std::vector x1a0_lights; + // std::unique_ptr x1b0_dissolveTextureBuffer; + zeus::CVector2f x1b4_shakeResult; + zeus::CVector2f x1bc_shakeDelta; + float x1c4_randTimeout = 0.f; + float x1c8_blurResult = 0.f; + float x1cc_blurDelta = 0.f; + float x1d0_dissolveStartTime = 99999.f; + float x1d4_dissolveEndTime = 99999.f; + float x1d8_transCompleteTime = 99999.f; + bool x1dc_dissolveStarted = false; - SModelDatas(const CAnimRes& samusRes); - }; + SModelDatas(const CAnimRes& samusRes); + }; private: - float x0_curTime = 0.f; - std::unique_ptr x4_modelData; - std::unique_ptr x8_textData; - TLockedToken xc_strTable; - u8 x14_ = 0; - float x18_bgOffset; - float x1c_bgHeight; - CRandom16 x20_random = CRandom16(99); - u16 x24_sfx = 1189; - CSfxHandle x28_sfxHandle; - u8 x2c_volume = 127; - u8 x2d_panning = 64; - ETransType x30_type = ETransType::Disabled; - float x34_stopTime; - float x38_textStartTime = 0.f; - float x3c_sfxInterval; - bool x40_strIdx; - union - { - struct - { - bool x44_24_transFinished : 1; - bool x44_25_stopSoon : 1; - bool x44_26_goingUp : 1; - bool x44_27_fadeWhite : 1; - bool x44_28_textDirty : 1; - }; - u8 dummy = 0; + float x0_curTime = 0.f; + std::unique_ptr x4_modelData; + std::unique_ptr x8_textData; + TLockedToken xc_strTable; + u8 x14_ = 0; + float x18_bgOffset; + float x1c_bgHeight; + CRandom16 x20_random = CRandom16(99); + u16 x24_sfx = 1189; + CSfxHandle x28_sfxHandle; + u8 x2c_volume = 127; + u8 x2d_panning = 64; + ETransType x30_type = ETransType::Disabled; + float x34_stopTime; + float x38_textStartTime = 0.f; + float x3c_sfxInterval; + bool x40_strIdx; + union { + struct { + bool x44_24_transFinished : 1; + bool x44_25_stopSoon : 1; + bool x44_26_goingUp : 1; + bool x44_27_fadeWhite : 1; + bool x44_28_textDirty : 1; }; + u8 dummy = 0; + }; - CColoredQuadFilter m_fadeToBlack = { EFilterType::Blend }; - CTexturedQuadFilter m_dissolve = { EFilterType::Blend, - CGraphics::g_SpareTexture.get() }; - CWideScreenFilter m_widescreen = { EFilterType::Blend }; - CCameraBlurFilter m_camblur; + CColoredQuadFilter m_fadeToBlack = {EFilterType::Blend}; + CTexturedQuadFilter m_dissolve = {EFilterType::Blend, CGraphics::g_SpareTexture.get()}; + CWideScreenFilter m_widescreen = {EFilterType::Blend}; + CCameraBlurFilter m_camblur; - static int GetSuitCharIdx(); - void DrawFirstPass(); - void DrawSecondPass(); - void DrawAllModels(); - void UpdateLights(float dt); - void UpdateEnabled(float); - void UpdateDisabled(float); - void UpdateText(float); - void DrawEnabled(); - void DrawDisabled(); - void DrawText(); + static int GetSuitCharIdx(); + void DrawFirstPass(); + void DrawSecondPass(); + void DrawAllModels(); + void UpdateLights(float dt); + void UpdateEnabled(float); + void UpdateDisabled(float); + void UpdateText(float); + void DrawEnabled(); + void DrawDisabled(); + void DrawText(); public: - CWorldTransManager() { x44_24_transFinished = true; } + CWorldTransManager() { x44_24_transFinished = true; } - void Update(float); - void Draw(); + void Update(float); + void Draw(); - void EnableTransition(const CAnimRes& samusRes, - CAssetId platRes, const zeus::CVector3f& platScale, - CAssetId bgRes, const zeus::CVector3f& bgScale, bool goingUp); - void EnableTransition(CAssetId fontId, CAssetId stringId, u32 strIdx, bool fadeWhite, - float chFadeTime, float chFadeRate, float textStartTime); + void EnableTransition(const CAnimRes& samusRes, CAssetId platRes, const zeus::CVector3f& platScale, CAssetId bgRes, + const zeus::CVector3f& bgScale, bool goingUp); + void EnableTransition(CAssetId fontId, CAssetId stringId, u32 strIdx, bool fadeWhite, float chFadeTime, + float chFadeRate, float textStartTime); - void StartTransition(); - void EndTransition(); - bool IsTransitionFinished() const { return x44_24_transFinished; } - void PleaseStopSoon() { x44_25_stopSoon = true; } - void StartTextFadeOut(); - bool IsTransitionEnabled() const { return x30_type != ETransType::Disabled; } - void DisableTransition(); - void TouchModels(); - ETransType GetTransType() { return x30_type; } - void SetSfx(u16 sfx, u8 volume, u8 panning) - { - x24_sfx = sfx; - x2c_volume = volume; - x2d_panning = panning; - } - void SfxStart(); - void SfxStop(); + void StartTransition(); + void EndTransition(); + bool IsTransitionFinished() const { return x44_24_transFinished; } + void PleaseStopSoon() { x44_25_stopSoon = true; } + void StartTextFadeOut(); + bool IsTransitionEnabled() const { return x30_type != ETransType::Disabled; } + void DisableTransition(); + void TouchModels(); + ETransType GetTransType() { return x30_type; } + void SetSfx(u16 sfx, u8 volume, u8 panning) { + x24_sfx = sfx; + x2c_volume = volume; + x2d_panning = panning; + } + void SfxStart(); + void SfxStop(); - static bool WaitForModelsAndTextures(); + static bool WaitForModelsAndTextures(); }; -} - +} // namespace urde diff --git a/Runtime/World/IGameArea.cpp b/Runtime/World/IGameArea.cpp index 2a06fdc30..62640cd60 100644 --- a/Runtime/World/IGameArea.cpp +++ b/Runtime/World/IGameArea.cpp @@ -1,74 +1,64 @@ #include "IGameArea.hpp" -namespace urde -{ -IGameArea::Dock::Dock(urde::CInputStream& in, const zeus::CTransform& xf) -{ - u32 refCount = in.readUint32Big(); - x4_dockReferences.reserve(refCount); - for (u32 i = 0 ; i < refCount ; i++) - { - SDockReference ref; - ref.x0_area = in.readUint32Big(); - ref.x4_dock = in.readUint32Big(); - x4_dockReferences.push_back(ref); - } +namespace urde { +IGameArea::Dock::Dock(urde::CInputStream& in, const zeus::CTransform& xf) { + u32 refCount = in.readUint32Big(); + x4_dockReferences.reserve(refCount); + for (u32 i = 0; i < refCount; i++) { + SDockReference ref; + ref.x0_area = in.readUint32Big(); + ref.x4_dock = in.readUint32Big(); + x4_dockReferences.push_back(ref); + } - u32 vertCount = in.readUint32Big(); + u32 vertCount = in.readUint32Big(); - for (u32 i = 0 ; i < vertCount ; i++) - { - zeus::CVector3f vert; - vert.readBig(in); - x14_planeVertices.push_back(xf * vert); - } + for (u32 i = 0; i < vertCount; i++) { + zeus::CVector3f vert; + vert.readBig(in); + x14_planeVertices.push_back(xf * vert); + } } -TAreaId IGameArea::Dock::GetConnectedAreaId(s32 other) const -{ - if (x4_dockReferences.empty()) - return kInvalidAreaId; +TAreaId IGameArea::Dock::GetConnectedAreaId(s32 other) const { + if (x4_dockReferences.empty()) + return kInvalidAreaId; - return x4_dockReferences[other].x0_area; + return x4_dockReferences[other].x0_area; } -s16 IGameArea::Dock::GetOtherDockNumber(s32 other) const -{ - if (u32(other) >= x4_dockReferences.size() || other < 0) - return -1; +s16 IGameArea::Dock::GetOtherDockNumber(s32 other) const { + if (u32(other) >= x4_dockReferences.size() || other < 0) + return -1; - return x4_dockReferences[other].x4_dock; + return x4_dockReferences[other].x4_dock; } -bool IGameArea::Dock::GetShouldLoadOther(s32 other) const -{ - if (other >= x4_dockReferences.size()) - return false; +bool IGameArea::Dock::GetShouldLoadOther(s32 other) const { + if (other >= x4_dockReferences.size()) + return false; - return x4_dockReferences[other].x6_loadOther; + return x4_dockReferences[other].x6_loadOther; } -void IGameArea::Dock::SetShouldLoadOther(s32 other, bool should) -{ - if (other >= x4_dockReferences.size()) - return; +void IGameArea::Dock::SetShouldLoadOther(s32 other, bool should) { + if (other >= x4_dockReferences.size()) + return; - x4_dockReferences[other].x6_loadOther = should; + x4_dockReferences[other].x6_loadOther = should; } -bool IGameArea::Dock::ShouldLoadOtherArea(s32 other) const -{ - if (x4_dockReferences.size() == 0) - return false; +bool IGameArea::Dock::ShouldLoadOtherArea(s32 other) const { + if (x4_dockReferences.size() == 0) + return false; - return x4_dockReferences[other].x6_loadOther; + return x4_dockReferences[other].x6_loadOther; } -zeus::CVector3f IGameArea::Dock::GetPoint(s32 idx) const -{ - if (idx >= x14_planeVertices.size() || idx < 0) - return zeus::CVector3f(); +zeus::CVector3f IGameArea::Dock::GetPoint(s32 idx) const { + if (idx >= x14_planeVertices.size() || idx < 0) + return zeus::CVector3f(); - return x14_planeVertices[idx]; -} + return x14_planeVertices[idx]; } +} // namespace urde diff --git a/Runtime/World/IGameArea.hpp b/Runtime/World/IGameArea.hpp index dfe985a42..d18f09061 100644 --- a/Runtime/World/IGameArea.hpp +++ b/Runtime/World/IGameArea.hpp @@ -3,63 +3,54 @@ #include "RetroTypes.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { class CEntity; -class IGameArea -{ +class IGameArea { public: - class Dock - { - public: - struct SDockReference - { - u32 x0_area = 0; - s16 x4_dock = 0; - bool x6_loadOther = false; - SDockReference() = default; - }; - private: - u32 x0_referenceCount = 0; - std::vector x4_dockReferences; - rstl::reserved_vector x14_planeVertices; - bool x48_isReferenced; - public: - - const rstl::reserved_vector& GetPlaneVertices() const {return x14_planeVertices;} - u32 GetReferenceCount() const { return x0_referenceCount; } - const std::vector& GetDockRefs() const { return x4_dockReferences; } - Dock(CInputStream& in, const zeus::CTransform& xf); - TAreaId GetConnectedAreaId(s32 other) const; - s16 GetOtherDockNumber(s32 other) const; - bool GetShouldLoadOther(s32 other) const; - void SetShouldLoadOther(s32 other, bool should); - bool ShouldLoadOtherArea(s32 other) const; - zeus::CVector3f GetPoint(s32 idx) const; - bool IsReferenced() const { return x48_isReferenced; } - void SetReferenceCount(s32 v) { x0_referenceCount = v; x48_isReferenced = true; } + class Dock { + public: + struct SDockReference { + u32 x0_area = 0; + s16 x4_dock = 0; + bool x6_loadOther = false; + SDockReference() = default; }; - virtual std::pair, s32> IGetScriptingMemoryAlways() const=0; - virtual TAreaId IGetAreaId() const=0; - virtual CAssetId IGetAreaAssetId() const=0; - virtual bool IIsActive() const=0; - virtual TAreaId IGetAttachedAreaId(int) const=0; - virtual u32 IGetNumAttachedAreas() const=0; - virtual CAssetId IGetStringTableAssetId() const=0; - virtual const zeus::CTransform& IGetTM() const=0; + private: + u32 x0_referenceCount = 0; + std::vector x4_dockReferences; + rstl::reserved_vector x14_planeVertices; + bool x48_isReferenced; + + public: + const rstl::reserved_vector& GetPlaneVertices() const { return x14_planeVertices; } + u32 GetReferenceCount() const { return x0_referenceCount; } + const std::vector& GetDockRefs() const { return x4_dockReferences; } + Dock(CInputStream& in, const zeus::CTransform& xf); + TAreaId GetConnectedAreaId(s32 other) const; + s16 GetOtherDockNumber(s32 other) const; + bool GetShouldLoadOther(s32 other) const; + void SetShouldLoadOther(s32 other, bool should); + bool ShouldLoadOtherArea(s32 other) const; + zeus::CVector3f GetPoint(s32 idx) const; + bool IsReferenced() const { return x48_isReferenced; } + void SetReferenceCount(s32 v) { + x0_referenceCount = v; + x48_isReferenced = true; + } + }; + + virtual std::pair, s32> IGetScriptingMemoryAlways() const = 0; + virtual TAreaId IGetAreaId() const = 0; + virtual CAssetId IGetAreaAssetId() const = 0; + virtual bool IIsActive() const = 0; + virtual TAreaId IGetAttachedAreaId(int) const = 0; + virtual u32 IGetNumAttachedAreas() const = 0; + virtual CAssetId IGetStringTableAssetId() const = 0; + virtual const zeus::CTransform& IGetTM() const = 0; }; -enum class EChain -{ - Invalid = -1, - ToDeallocate, - Deallocated, - Loading, - Alive, - AliveJudgement -}; - -} +enum class EChain { Invalid = -1, ToDeallocate, Deallocated, Loading, Alive, AliveJudgement }; +} // namespace urde diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index 2ae13bed9..be9dbcde0 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -111,3398 +111,3216 @@ #include "MP1/World/CFlickerBat.hpp" #include "Camera/CPathCamera.hpp" -namespace urde -{ +namespace urde { static logvisor::Module Log("urde::ScriptLoader"); static SObjectTag MorphballDoorANCS = {}; -static const SObjectTag& GetMorphballDoorACS() -{ - if (!MorphballDoorANCS) - { - MorphballDoorANCS.type = FOURCC('ANCS'); - MorphballDoorANCS.id = g_ResFactory->TranslateOriginalToNew(0x1F9DA858); - } - return MorphballDoorANCS; +static const SObjectTag& GetMorphballDoorACS() { + if (!MorphballDoorANCS) { + MorphballDoorANCS.type = FOURCC('ANCS'); + MorphballDoorANCS.id = g_ResFactory->TranslateOriginalToNew(0x1F9DA858); + } + return MorphballDoorANCS; } -static bool EnsurePropertyCount(int count, int expected, const char* structName) -{ - if (count < expected) - { - Log.report(logvisor::Warning, "Insufficient number of props (%d/%d) for %s entity", count, expected, - structName); - return false; - } - return true; +static bool EnsurePropertyCount(int count, int expected, const char* structName) { + if (count < expected) { + Log.report(logvisor::Warning, "Insufficient number of props (%d/%d) for %s entity", count, expected, structName); + return false; + } + return true; } -struct SActorHead -{ - std::string x0_name; - zeus::CTransform x10_transform; +struct SActorHead { + std::string x0_name; + zeus::CTransform x10_transform; }; -struct SScaledActorHead : SActorHead -{ - zeus::CVector3f x40_scale; +struct SScaledActorHead : SActorHead { + zeus::CVector3f x40_scale; - SScaledActorHead(SActorHead&& head) : SActorHead(std::move(head)) {} + SScaledActorHead(SActorHead&& head) : SActorHead(std::move(head)) {} }; -static zeus::CTransform LoadEditorTransform(CInputStream& in) -{ - zeus::CVector3f position; - position.readBig(in); - zeus::CVector3f orientation; - orientation.readBig(in); - return ScriptLoader::ConvertEditorEulerToTransform4f(orientation, position); +static zeus::CTransform LoadEditorTransform(CInputStream& in) { + zeus::CVector3f position; + position.readBig(in); + zeus::CVector3f orientation; + orientation.readBig(in); + return ScriptLoader::ConvertEditorEulerToTransform4f(orientation, position); } -static zeus::CTransform LoadEditorTransformPivotOnly(CInputStream& in) -{ - zeus::CVector3f position; - position.readBig(in); - zeus::CVector3f orientation; - orientation.readBig(in); - orientation.x() = 0.f; - orientation.y() = 0.f; - return ScriptLoader::ConvertEditorEulerToTransform4f(orientation, position); +static zeus::CTransform LoadEditorTransformPivotOnly(CInputStream& in) { + zeus::CVector3f position; + position.readBig(in); + zeus::CVector3f orientation; + orientation.readBig(in); + orientation.x() = 0.f; + orientation.y() = 0.f; + return ScriptLoader::ConvertEditorEulerToTransform4f(orientation, position); } -static SActorHead LoadActorHead(CInputStream& in, CStateManager& stateMgr) -{ - SActorHead ret; - ret.x0_name = stateMgr.HashInstanceName(in); - ret.x10_transform = LoadEditorTransform(in); - return ret; +static SActorHead LoadActorHead(CInputStream& in, CStateManager& stateMgr) { + SActorHead ret; + ret.x0_name = stateMgr.HashInstanceName(in); + ret.x10_transform = LoadEditorTransform(in); + return ret; } -static SScaledActorHead LoadScaledActorHead(CInputStream& in, CStateManager& stateMgr) -{ - SScaledActorHead ret = LoadActorHead(in, stateMgr); - ret.x40_scale.readBig(in); - return ret; +static SScaledActorHead LoadScaledActorHead(CInputStream& in, CStateManager& stateMgr) { + SScaledActorHead ret = LoadActorHead(in, stateMgr); + ret.x40_scale.readBig(in); + return ret; } static zeus::CAABox GetCollisionBox(CStateManager& stateMgr, TAreaId id, const zeus::CVector3f& extent, - const zeus::CVector3f& offset) -{ - zeus::CAABox box(-extent * 0.5f + offset, extent * 0.5f + offset); - const zeus::CTransform& rot = stateMgr.WorldNC()->GetGameAreas()[id]->GetTransform().getRotation(); - return box.getTransformedAABox(rot); + const zeus::CVector3f& offset) { + zeus::CAABox box(-extent * 0.5f + offset, extent * 0.5f + offset); + const zeus::CTransform& rot = stateMgr.WorldNC()->GetGameAreas()[id]->GetTransform().getRotation(); + return box.getTransformedAABox(rot); } -u32 ScriptLoader::LoadParameterFlags(CInputStream& in) -{ - u32 count = in.readUint32Big(); - u32 ret = 0; - for (u32 i = 0; i < count; ++i) - if (in.readBool()) - ret |= 1 << i; - return ret; +u32 ScriptLoader::LoadParameterFlags(CInputStream& in) { + u32 count = in.readUint32Big(); + u32 ret = 0; + for (u32 i = 0; i < count; ++i) + if (in.readBool()) + ret |= 1 << i; + return ret; } -CGrappleParameters ScriptLoader::LoadGrappleParameters(CInputStream& in) -{ - float a = in.readFloatBig(); +CGrappleParameters ScriptLoader::LoadGrappleParameters(CInputStream& in) { + float a = in.readFloatBig(); + float b = in.readFloatBig(); + float c = in.readFloatBig(); + float d = in.readFloatBig(); + float e = in.readFloatBig(); + float f = in.readFloatBig(); + float g = in.readFloatBig(); + float h = in.readFloatBig(); + float i = in.readFloatBig(); + float j = in.readFloatBig(); + float k = in.readFloatBig(); + bool l = in.readBool(); + return CGrappleParameters(a, b, c, d, e, f, g, h, i, j, k, l); +} + +CActorParameters ScriptLoader::LoadActorParameters(CInputStream& in) { + u32 propCount = in.readUint32Big(); + if (propCount >= 5 && propCount <= 0xe) { + CLightParameters lParms = ScriptLoader::LoadLightParameters(in); + + CScannableParameters sParams; + if (propCount > 5) + sParams = LoadScannableParameters(in); + + CAssetId xrayModel = in.readUint32Big(); + CAssetId xraySkin = in.readUint32Big(); + CAssetId infraModel = in.readUint32Big(); + CAssetId infraSkin = in.readUint32Big(); + + bool globalTimeProvider = true; + if (propCount > 7) + globalTimeProvider = in.readBool(); + + float fadeInTime = 1.f; + if (propCount > 8) + fadeInTime = in.readFloatBig(); + + float fadeOutTime = 1.f; + if (propCount > 9) + fadeOutTime = in.readFloatBig(); + + CVisorParameters vParms; + if (propCount > 6) + vParms = LoadVisorParameters(in); + + bool thermalHeat = false; + if (propCount > 10) + thermalHeat = in.readBool(); + + bool renderUnsorted = false; + if (propCount > 11) + renderUnsorted = in.readBool(); + + bool noSortThermal = false; + if (propCount > 12) + noSortThermal = in.readBool(); + + float thermalMag = 1.f; + if (propCount > 13) + thermalMag = in.readFloatBig(); + + std::pair xray = {}; + if (g_ResFactory->GetResourceTypeById(xrayModel)) + xray = {xrayModel, xraySkin}; + + std::pair infra = {}; + if (g_ResFactory->GetResourceTypeById(infraModel)) + infra = {infraModel, infraSkin}; + + return CActorParameters(lParms, sParams, xray, infra, vParms, globalTimeProvider, thermalHeat, renderUnsorted, + noSortThermal, fadeInTime, fadeOutTime, thermalMag); + } + return CActorParameters::None(); +} + +CVisorParameters ScriptLoader::LoadVisorParameters(CInputStream& in) { + u32 propCount = in.readUint32Big(); + if (propCount >= 1 && propCount <= 3) { + bool b1 = in.readBool(); + bool scanPassthrough = false; + u8 mask = 0xf; + if (propCount > 2) + scanPassthrough = in.readBool(); + if (propCount >= 2) + mask = u8(in.readUint32Big()); + return CVisorParameters(mask, b1, scanPassthrough); + } + return CVisorParameters(); +} + +CScannableParameters ScriptLoader::LoadScannableParameters(CInputStream& in) { + u32 propCount = in.readUint32Big(); + if (propCount == 1) + return CScannableParameters(in.readUint32Big()); + return CScannableParameters(); +} + +CLightParameters ScriptLoader::LoadLightParameters(CInputStream& in) { + u32 propCount = in.readUint32Big(); + if (propCount == 14) { + bool a = in.readBool(); float b = in.readFloatBig(); - float c = in.readFloatBig(); + CLightParameters::EShadowTesselation shadowTess = CLightParameters::EShadowTesselation(in.readUint32Big()); float d = in.readFloatBig(); float e = in.readFloatBig(); - float f = in.readFloatBig(); - float g = in.readFloatBig(); - float h = in.readFloatBig(); - float i = in.readFloatBig(); - float j = in.readFloatBig(); - float k = in.readFloatBig(); - bool l = in.readBool(); - return CGrappleParameters(a, b, c, d, e, f, g, h, i, j, k, l); -} -CActorParameters ScriptLoader::LoadActorParameters(CInputStream& in) -{ - u32 propCount = in.readUint32Big(); - if (propCount >= 5 && propCount <= 0xe) - { - CLightParameters lParms = ScriptLoader::LoadLightParameters(in); + zeus::CColor noLightsAmbient; + noLightsAmbient.readRGBABig(in); - CScannableParameters sParams; - if (propCount > 5) - sParams = LoadScannableParameters(in); + bool makeLights = in.readBool(); + CLightParameters::EWorldLightingOptions lightOpts = CLightParameters::EWorldLightingOptions(in.readUint32Big()); + CLightParameters::ELightRecalculationOptions recalcOpts = + CLightParameters::ELightRecalculationOptions(in.readUint32Big()); - CAssetId xrayModel = in.readUint32Big(); - CAssetId xraySkin = in.readUint32Big(); - CAssetId infraModel = in.readUint32Big(); - CAssetId infraSkin = in.readUint32Big(); + zeus::CVector3f actorPosBias; + actorPosBias.readBig(in); - bool globalTimeProvider = true; - if (propCount > 7) - globalTimeProvider = in.readBool(); - - float fadeInTime = 1.f; - if (propCount > 8) - fadeInTime = in.readFloatBig(); - - float fadeOutTime = 1.f; - if (propCount > 9) - fadeOutTime = in.readFloatBig(); - - CVisorParameters vParms; - if (propCount > 6) - vParms = LoadVisorParameters(in); - - bool thermalHeat = false; - if (propCount > 10) - thermalHeat = in.readBool(); - - bool renderUnsorted = false; - if (propCount > 11) - renderUnsorted = in.readBool(); - - bool noSortThermal = false; - if (propCount > 12) - noSortThermal = in.readBool(); - - float thermalMag = 1.f; - if (propCount > 13) - thermalMag = in.readFloatBig(); - - std::pair xray = {}; - if (g_ResFactory->GetResourceTypeById(xrayModel)) - xray = {xrayModel, xraySkin}; - - std::pair infra = {}; - if (g_ResFactory->GetResourceTypeById(infraModel)) - infra = {infraModel, infraSkin}; - - return CActorParameters(lParms, sParams, xray, infra, vParms, globalTimeProvider, thermalHeat, - renderUnsorted, noSortThermal, fadeInTime, fadeOutTime, thermalMag); + s32 maxDynamicLights = -1; + s32 maxAreaLights = -1; + if (propCount >= 12) { + maxDynamicLights = in.readUint32Big(); + maxAreaLights = in.readUint32Big(); } - return CActorParameters::None(); + + bool ambientChannelOverflow = false; + if (propCount >= 13) + ambientChannelOverflow = in.readBool(); + + s32 layerIdx = 0; + if (propCount >= 14) + layerIdx = in.readUint32Big(); + + return CLightParameters(a, b, shadowTess, d, e, noLightsAmbient, makeLights, lightOpts, recalcOpts, actorPosBias, + maxDynamicLights, maxAreaLights, ambientChannelOverflow, layerIdx); + } + return CLightParameters::None(); } -CVisorParameters ScriptLoader::LoadVisorParameters(CInputStream& in) -{ - u32 propCount = in.readUint32Big(); - if (propCount >= 1 && propCount <= 3) - { - bool b1 = in.readBool(); - bool scanPassthrough = false; - u8 mask = 0xf; - if (propCount > 2) - scanPassthrough = in.readBool(); - if (propCount >= 2) - mask = u8(in.readUint32Big()); - return CVisorParameters(mask, b1, scanPassthrough); - } - return CVisorParameters(); +CAnimationParameters ScriptLoader::LoadAnimationParameters(CInputStream& in) { + CAssetId ancs = in.readUint32Big(); + s32 charIdx = in.readUint32Big(); + u32 defaultAnim = in.readUint32Big(); + return CAnimationParameters(ancs, charIdx, defaultAnim); } -CScannableParameters ScriptLoader::LoadScannableParameters(CInputStream& in) -{ - u32 propCount = in.readUint32Big(); - if (propCount == 1) - return CScannableParameters(in.readUint32Big()); - return CScannableParameters(); -} +CFluidUVMotion ScriptLoader::LoadFluidUVMotion(CInputStream& in) { + auto motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); + float a = in.readFloatBig(); + float b = in.readFloatBig(); + b = zeus::degToRad(b) - M_PIF; + float c = in.readFloatBig(); + float d = in.readFloatBig(); + CFluidUVMotion::SFluidLayerMotion pattern1Layer(motion, a, b, c, d); -CLightParameters ScriptLoader::LoadLightParameters(CInputStream& in) -{ - u32 propCount = in.readUint32Big(); - if (propCount == 14) - { - bool a = in.readBool(); - float b = in.readFloatBig(); - CLightParameters::EShadowTesselation shadowTess = CLightParameters::EShadowTesselation(in.readUint32Big()); - float d = in.readFloatBig(); - float e = in.readFloatBig(); + motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); + a = in.readFloatBig(); + b = in.readFloatBig(); + b = zeus::degToRad(b) - M_PIF; + c = in.readFloatBig(); + d = in.readFloatBig(); + CFluidUVMotion::SFluidLayerMotion pattern2Layer(motion, a, b, c, d); - zeus::CColor noLightsAmbient; - noLightsAmbient.readRGBABig(in); + motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); + a = in.readFloatBig(); + b = in.readFloatBig(); + b = zeus::degToRad(b) - M_PIF; + c = in.readFloatBig(); + d = in.readFloatBig(); + CFluidUVMotion::SFluidLayerMotion colorLayer(motion, a, b, c, d); - bool makeLights = in.readBool(); - CLightParameters::EWorldLightingOptions lightOpts = CLightParameters::EWorldLightingOptions(in.readUint32Big()); - CLightParameters::ELightRecalculationOptions recalcOpts = - CLightParameters::ELightRecalculationOptions(in.readUint32Big()); + a = in.readFloatBig(); + b = in.readFloatBig(); - zeus::CVector3f actorPosBias; - actorPosBias.readBig(in); + b = zeus::degToRad(b) - M_PIF; - s32 maxDynamicLights = -1; - s32 maxAreaLights = -1; - if (propCount >= 12) - { - maxDynamicLights = in.readUint32Big(); - maxAreaLights = in.readUint32Big(); - } - - bool ambientChannelOverflow = false; - if (propCount >= 13) - ambientChannelOverflow = in.readBool(); - - s32 layerIdx = 0; - if (propCount >= 14) - layerIdx = in.readUint32Big(); - - return CLightParameters(a, b, shadowTess, d, e, noLightsAmbient, makeLights, lightOpts, recalcOpts, - actorPosBias, maxDynamicLights, maxAreaLights, ambientChannelOverflow, layerIdx); - } - return CLightParameters::None(); -} - -CAnimationParameters ScriptLoader::LoadAnimationParameters(CInputStream& in) -{ - CAssetId ancs = in.readUint32Big(); - s32 charIdx = in.readUint32Big(); - u32 defaultAnim = in.readUint32Big(); - return CAnimationParameters(ancs, charIdx, defaultAnim); -} - -CFluidUVMotion ScriptLoader::LoadFluidUVMotion(CInputStream& in) -{ - auto motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); - float a = in.readFloatBig(); - float b = in.readFloatBig(); - b = zeus::degToRad(b) - M_PIF; - float c = in.readFloatBig(); - float d = in.readFloatBig(); - CFluidUVMotion::SFluidLayerMotion pattern1Layer(motion, a, b, c, d); - - motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); - a = in.readFloatBig(); - b = in.readFloatBig(); - b = zeus::degToRad(b) - M_PIF; - c = in.readFloatBig(); - d = in.readFloatBig(); - CFluidUVMotion::SFluidLayerMotion pattern2Layer(motion, a, b, c, d); - - motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); - a = in.readFloatBig(); - b = in.readFloatBig(); - b = zeus::degToRad(b) - M_PIF; - c = in.readFloatBig(); - d = in.readFloatBig(); - CFluidUVMotion::SFluidLayerMotion colorLayer(motion, a, b, c, d); - - a = in.readFloatBig(); - b = in.readFloatBig(); - - b = zeus::degToRad(b) - M_PIF; - - return CFluidUVMotion(a, b, colorLayer, pattern1Layer, pattern2Layer); + return CFluidUVMotion(a, b, colorLayer, pattern1Layer, pattern2Layer); } zeus::CTransform ScriptLoader::ConvertEditorEulerToTransform4f(const zeus::CVector3f& orientation, - const zeus::CVector3f& position) -{ - zeus::simd_floats f(orientation.mSimd); - return zeus::CTransform::RotateZ(zeus::degToRad(f[2])) * - zeus::CTransform::RotateY(zeus::degToRad(f[1])) * - zeus::CTransform::RotateX(zeus::degToRad(f[0])) + - position; + const zeus::CVector3f& position) { + zeus::simd_floats f(orientation.mSimd); + return zeus::CTransform::RotateZ(zeus::degToRad(f[2])) * zeus::CTransform::RotateY(zeus::degToRad(f[1])) * + zeus::CTransform::RotateX(zeus::degToRad(f[0])) + + position; } -CEntity* ScriptLoader::LoadActor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 24, "Actor")) - return nullptr; +CEntity* ScriptLoader::LoadActor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 24, "Actor")) + return nullptr; - SScaledActorHead head = LoadScaledActorHead(in, mgr); + SScaledActorHead head = LoadScaledActorHead(in, mgr); - zeus::CVector3f collisionExtent; - collisionExtent.readBig(in); + zeus::CVector3f collisionExtent; + collisionExtent.readBig(in); - zeus::CVector3f centroid; - centroid.readBig(in); + zeus::CVector3f centroid; + centroid.readBig(in); - float mass = in.readFloatBig(); - float zMomentum = in.readFloatBig(); + float mass = in.readFloatBig(); + float zMomentum = in.readFloatBig(); - CHealthInfo hInfo(in); + CHealthInfo hInfo(in); - CDamageVulnerability dVuln(in); + CDamageVulnerability dVuln(in); - CAssetId staticId = in.readUint32Big(); - CAnimationParameters aParms = LoadAnimationParameters(in); + CAssetId staticId = in.readUint32Big(); + CAnimationParameters aParms = LoadAnimationParameters(in); - CActorParameters actParms = LoadActorParameters(in); + CActorParameters actParms = LoadActorParameters(in); - bool looping = in.readBool(); - bool snow = in.readBool(); - bool solid = in.readBool(); - bool cameraPassthrough = in.readBool(); - bool active = in.readBool(); - u32 shaderIdx = in.readUint32Big(); - float xrayAlpha = in.readFloatBig(); - bool noThermalHotZ = in.readBool(); - bool castsShadow = in.readBool(); - bool scaleAdvancementDelta = in.readBool(); - bool materialFlag54 = in.readBool(); + bool looping = in.readBool(); + bool snow = in.readBool(); + bool solid = in.readBool(); + bool cameraPassthrough = in.readBool(); + bool active = in.readBool(); + u32 shaderIdx = in.readUint32Big(); + float xrayAlpha = in.readFloatBig(); + bool noThermalHotZ = in.readBool(); + bool castsShadow = in.readBool(); + bool scaleAdvancementDelta = in.readBool(); + bool materialFlag54 = in.readBool(); - FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile()); - if (!g_ResFactory->GetResourceTypeById(staticId) && !animType) - return nullptr; + FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile()); + if (!g_ResFactory->GetResourceTypeById(staticId) && !animType) + return nullptr; - zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, centroid); + zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, centroid); - CMaterialList list; - if (snow) // Bool 2 - list.Add(EMaterialTypes::Snow); + CMaterialList list; + if (snow) // Bool 2 + list.Add(EMaterialTypes::Snow); - if (solid) // Bool 3 - list.Add(EMaterialTypes::Solid); + if (solid) // Bool 3 + list.Add(EMaterialTypes::Solid); - if (cameraPassthrough) // Bool 4 - list.Add(EMaterialTypes::CameraPassthrough); + if (cameraPassthrough) // Bool 4 + list.Add(EMaterialTypes::CameraPassthrough); - CModelData data; - if (animType == SBIG('ANCS')) - data = - CAnimRes(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, aParms.GetInitialAnimation(), false); - else - data = CStaticRes(staticId, head.x40_scale); + CModelData data; + if (animType == SBIG('ANCS')) + data = CAnimRes(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, aParms.GetInitialAnimation(), false); + else + data = CStaticRes(staticId, head.x40_scale); - if ((collisionExtent.x() < 0.f || collisionExtent.y() < 0.f || collisionExtent.z() < 0.f) || collisionExtent.isZero()) - aabb = data.GetBounds(head.x10_transform.getRotation()); + if ((collisionExtent.x() < 0.f || collisionExtent.y() < 0.f || collisionExtent.z() < 0.f) || collisionExtent.isZero()) + aabb = data.GetBounds(head.x10_transform.getRotation()); - return new CScriptActor(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(data), aabb, mass, - zMomentum, list, hInfo, dVuln, actParms, looping, active, shaderIdx, xrayAlpha, - noThermalHotZ, castsShadow, scaleAdvancementDelta, materialFlag54); + return new CScriptActor(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(data), aabb, mass, + zMomentum, list, hInfo, dVuln, actParms, looping, active, shaderIdx, xrayAlpha, noThermalHotZ, + castsShadow, scaleAdvancementDelta, materialFlag54); } -CEntity* ScriptLoader::LoadWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 13, "Waypoint")) - return nullptr; +CEntity* ScriptLoader::LoadWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 13, "Waypoint")) + return nullptr; - SActorHead head = LoadActorHead(in, mgr); + SActorHead head = LoadActorHead(in, mgr); - bool active = in.readBool(); - float speed = in.readFloatBig(); - float pause = in.readFloatBig(); - u32 patternTranslate = in.readUint32Big(); - u32 patternOrient = in.readUint32Big(); - u32 patternFit = in.readUint32Big(); - u32 behaviour = in.readUint32Big(); - u32 behaviourOrient = in.readUint32Big(); - u32 behaviourModifiers = in.readUint32Big(); - u32 animation = in.readUint32Big(); + bool active = in.readBool(); + float speed = in.readFloatBig(); + float pause = in.readFloatBig(); + u32 patternTranslate = in.readUint32Big(); + u32 patternOrient = in.readUint32Big(); + u32 patternFit = in.readUint32Big(); + u32 behaviour = in.readUint32Big(); + u32 behaviourOrient = in.readUint32Big(); + u32 behaviourModifiers = in.readUint32Big(); + u32 animation = in.readUint32Big(); - return new CScriptWaypoint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, - active, speed, pause, patternTranslate, patternOrient, patternFit, - behaviour, behaviourOrient, behaviourModifiers, animation); + return new CScriptWaypoint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, speed, pause, + patternTranslate, patternOrient, patternFit, behaviour, behaviourOrient, + behaviourModifiers, animation); } -CEntity* ScriptLoader::LoadDoor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 13, "Door") || propCount > 14) - return nullptr; +CEntity* ScriptLoader::LoadDoor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 13, "Door") || propCount > 14) + return nullptr; - SScaledActorHead head = LoadScaledActorHead(in, mgr); - CAnimationParameters aParms = LoadAnimationParameters(in); - CActorParameters actParms = LoadActorParameters(in); + SScaledActorHead head = LoadScaledActorHead(in, mgr); + CAnimationParameters aParms = LoadAnimationParameters(in); + CActorParameters actParms = LoadActorParameters(in); - zeus::CVector3f orbitPos; - orbitPos.readBig(in); - zeus::CVector3f collisionExtent; - collisionExtent.readBig(in); - zeus::CVector3f offset; - offset.readBig(in); + zeus::CVector3f orbitPos; + orbitPos.readBig(in); + zeus::CVector3f collisionExtent; + collisionExtent.readBig(in); + zeus::CVector3f offset; + offset.readBig(in); - bool active = in.readBool(); - bool open = in.readBool(); - bool projectilesCollide = in.readBool(); - float animationLength = in.readFloatBig(); + bool active = in.readBool(); + bool open = in.readBool(); + bool projectilesCollide = in.readBool(); + float animationLength = in.readFloatBig(); - zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, offset); + zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, offset); - if (!g_ResFactory->GetResourceTypeById(aParms.GetACSFile())) - return nullptr; + if (!g_ResFactory->GetResourceTypeById(aParms.GetACSFile())) + return nullptr; - CModelData mData = - CAnimRes(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, 0, false); - if (collisionExtent.isZero()) - aabb = mData.GetBounds(head.x10_transform.getRotation()); + CModelData mData = CAnimRes(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, 0, false); + if (collisionExtent.isZero()) + aabb = mData.GetBounds(head.x10_transform.getRotation()); - bool isMorphballDoor = false; - if (propCount == 13) - { - if (aParms.GetACSFile() == GetMorphballDoorACS().id) - isMorphballDoor = true; - } else if (propCount == 14) - isMorphballDoor = in.readBool(); + bool isMorphballDoor = false; + if (propCount == 13) { + if (aParms.GetACSFile() == GetMorphballDoorACS().id) + isMorphballDoor = true; + } else if (propCount == 14) + isMorphballDoor = in.readBool(); - return new CScriptDoor(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(mData), actParms, - orbitPos, aabb, active, open, projectilesCollide, animationLength, isMorphballDoor); + return new CScriptDoor(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(mData), actParms, + orbitPos, aabb, active, open, projectilesCollide, animationLength, isMorphballDoor); } -CEntity* ScriptLoader::LoadTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 9, "Trigger")) - return nullptr; +CEntity* ScriptLoader::LoadTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 9, "Trigger")) + return nullptr; - std::string name = mgr.HashInstanceName(in); + std::string name = mgr.HashInstanceName(in); - zeus::CVector3f position = zeus::CVector3f::ReadBig(in); + zeus::CVector3f position = zeus::CVector3f::ReadBig(in); - zeus::CVector3f extent = zeus::CVector3f::ReadBig(in); + zeus::CVector3f extent = zeus::CVector3f::ReadBig(in); - CDamageInfo dInfo(in); + CDamageInfo dInfo(in); - zeus::CVector3f forceVec = zeus::CVector3f::ReadBig(in); + zeus::CVector3f forceVec = zeus::CVector3f::ReadBig(in); - ETriggerFlags - flags = ETriggerFlags(in.readUint32Big()); - bool active = in.readBool(); - bool b2 = in.readBool(); - bool b3 = in.readBool(); + ETriggerFlags flags = ETriggerFlags(in.readUint32Big()); + bool active = in.readBool(); + bool b2 = in.readBool(); + bool b3 = in.readBool(); - zeus::CAABox box(-extent * 0.5f, extent * 0.5f); + zeus::CAABox box(-extent * 0.5f, extent * 0.5f); - const zeus::CTransform& areaXf = mgr.WorldNC()->GetGameAreas()[info.GetAreaId()]->GetTransform(); - zeus::CVector3f orientedForce = areaXf.basis * forceVec; + const zeus::CTransform& areaXf = mgr.WorldNC()->GetGameAreas()[info.GetAreaId()]->GetTransform(); + zeus::CVector3f orientedForce = areaXf.basis * forceVec; - return new CScriptTrigger(mgr.AllocateUniqueId(), name, info, position, box, dInfo, orientedForce, flags, active, - b2, b3); + return new CScriptTrigger(mgr.AllocateUniqueId(), name, info, position, box, dInfo, orientedForce, flags, active, b2, + b3); } -CEntity* ScriptLoader::LoadTimer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 6, "Timer")) - return nullptr; +CEntity* ScriptLoader::LoadTimer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 6, "Timer")) + return nullptr; - std::string name = mgr.HashInstanceName(in); + std::string name = mgr.HashInstanceName(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - bool b1 = in.readBool(); - bool b2 = in.readBool(); - bool b3 = in.readBool(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + bool b1 = in.readBool(); + bool b2 = in.readBool(); + bool b3 = in.readBool(); - return new CScriptTimer(mgr.AllocateUniqueId(), name, info, f1, f2, b1, b2, b3); + return new CScriptTimer(mgr.AllocateUniqueId(), name, info, f1, f2, b1, b2, b3); } -CEntity* ScriptLoader::LoadCounter(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 5, "Counter")) - return nullptr; +CEntity* ScriptLoader::LoadCounter(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 5, "Counter")) + return nullptr; - std::string name = mgr.HashInstanceName(in); + std::string name = mgr.HashInstanceName(in); - u32 w1 = in.readUint32Big(); - u32 w2 = in.readUint32Big(); - bool b1 = in.readBool(); - bool b2 = in.readBool(); + u32 w1 = in.readUint32Big(); + u32 w2 = in.readUint32Big(); + bool b1 = in.readBool(); + bool b2 = in.readBool(); - return new CScriptCounter(mgr.AllocateUniqueId(), name, info, w1, w2, b1, b2); + return new CScriptCounter(mgr.AllocateUniqueId(), name, info, w1, w2, b1, b2); } -CEntity* ScriptLoader::LoadEffect(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 24, "Effect")) - return nullptr; +CEntity* ScriptLoader::LoadEffect(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 24, "Effect")) + return nullptr; - SScaledActorHead head = LoadScaledActorHead(in, mgr); + SScaledActorHead head = LoadScaledActorHead(in, mgr); - CAssetId partId(in); - CAssetId elscId(in); - bool hotInThermal = in.readBool(); - bool noTimerUnlessAreaOccluded = in.readBool(); - bool rebuildSystemsOnActivate = in.readBool(); - bool active = in.readBool(); + CAssetId partId(in); + CAssetId elscId(in); + bool hotInThermal = in.readBool(); + bool noTimerUnlessAreaOccluded = in.readBool(); + bool rebuildSystemsOnActivate = in.readBool(); + bool active = in.readBool(); - if (!partId.IsValid() && !elscId.IsValid()) - return nullptr; + if (!partId.IsValid() && !elscId.IsValid()) + return nullptr; - if (!g_ResFactory->GetResourceTypeById(partId) && !g_ResFactory->GetResourceTypeById(elscId)) - return nullptr; + if (!g_ResFactory->GetResourceTypeById(partId) && !g_ResFactory->GetResourceTypeById(elscId)) + return nullptr; - bool useRateInverseCamDist = in.readBool(); - float rateInverseCamDist = in.readFloatBig(); - float rateInverseCamDistRate = in.readFloatBig(); - float duration = in.readFloatBig(); - float durationResetWhileVisible = in.readFloatBig(); - bool useRateCamDistRange = in.readBool(); - float rateCamDistRangeMin = in.readFloatBig(); - float rateCamDistRangeMax = in.readFloatBig(); - float rateCamDistRangeFarRate = in.readFloatBig(); - bool combatVisorVisible = in.readBool(); - bool thermalVisorVisible = in.readBool(); - bool xrayVisorVisible = in.readBool(); - bool dieWhenSystemsDone = in.readBool(); + bool useRateInverseCamDist = in.readBool(); + float rateInverseCamDist = in.readFloatBig(); + float rateInverseCamDistRate = in.readFloatBig(); + float duration = in.readFloatBig(); + float durationResetWhileVisible = in.readFloatBig(); + bool useRateCamDistRange = in.readBool(); + float rateCamDistRangeMin = in.readFloatBig(); + float rateCamDistRangeMax = in.readFloatBig(); + float rateCamDistRangeFarRate = in.readFloatBig(); + bool combatVisorVisible = in.readBool(); + bool thermalVisorVisible = in.readBool(); + bool xrayVisorVisible = in.readBool(); + bool dieWhenSystemsDone = in.readBool(); - CLightParameters lParms = LoadLightParameters(in); + CLightParameters lParms = LoadLightParameters(in); - return new CScriptEffect(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, head.x40_scale, partId, - elscId, hotInThermal, noTimerUnlessAreaOccluded, rebuildSystemsOnActivate, active, - useRateInverseCamDist, rateInverseCamDist, rateInverseCamDistRate, duration, - durationResetWhileVisible, useRateCamDistRange, rateCamDistRangeMin, rateCamDistRangeMax, - rateCamDistRangeFarRate, combatVisorVisible, thermalVisorVisible, xrayVisorVisible, lParms, - dieWhenSystemsDone); + return new CScriptEffect(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, head.x40_scale, partId, + elscId, hotInThermal, noTimerUnlessAreaOccluded, rebuildSystemsOnActivate, active, + useRateInverseCamDist, rateInverseCamDist, rateInverseCamDistRate, duration, + durationResetWhileVisible, useRateCamDistRange, rateCamDistRangeMin, rateCamDistRangeMax, + rateCamDistRangeFarRate, combatVisorVisible, thermalVisorVisible, xrayVisorVisible, lParms, + dieWhenSystemsDone); } -CEntity* ScriptLoader::LoadPlatform(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 19, "Platform")) - return nullptr; +CEntity* ScriptLoader::LoadPlatform(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 19, "Platform")) + return nullptr; - SScaledActorHead head = LoadScaledActorHead(in, mgr); + SScaledActorHead head = LoadScaledActorHead(in, mgr); - zeus::CVector3f extent; - extent.readBig(in); + zeus::CVector3f extent; + extent.readBig(in); - zeus::CVector3f centroid; - centroid.readBig(in); + zeus::CVector3f centroid; + centroid.readBig(in); - CAssetId staticId = in.readUint32Big(); - CAnimationParameters aParms = LoadAnimationParameters(in); + CAssetId staticId = in.readUint32Big(); + CAnimationParameters aParms = LoadAnimationParameters(in); - CActorParameters actParms = LoadActorParameters(in); + CActorParameters actParms = LoadActorParameters(in); - float speed = in.readFloatBig(); - bool active = in.readBool(); - CAssetId dclnId = in.readUint32Big(); + float speed = in.readFloatBig(); + bool active = in.readBool(); + CAssetId dclnId = in.readUint32Big(); - CHealthInfo hInfo(in); + CHealthInfo hInfo(in); - CDamageVulnerability dInfo(in); + CDamageVulnerability dInfo(in); - bool detectCollision = in.readBool(); - float xrayAlpha = in.readFloatBig(); - bool rainSplashes = in.readBool(); - u32 maxRainSplashes = in.readUint32Big(); - u32 rainGenRate = in.readUint32Big(); + bool detectCollision = in.readBool(); + float xrayAlpha = in.readFloatBig(); + bool rainSplashes = in.readBool(); + u32 maxRainSplashes = in.readUint32Big(); + u32 rainGenRate = in.readUint32Big(); - FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile()); - if (!g_ResFactory->GetResourceTypeById(staticId) && !animType) - return nullptr; + FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile()); + if (!g_ResFactory->GetResourceTypeById(staticId) && !animType) + return nullptr; - zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), extent, centroid); + zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), extent, centroid); - FourCC dclnType = g_ResFactory->GetResourceTypeById(dclnId); - std::experimental::optional> dclnToken; - if (dclnType) - { - dclnToken.emplace(g_SimplePool->GetObj({SBIG('DCLN'), dclnId})); - dclnToken->GetObj(); - } + FourCC dclnType = g_ResFactory->GetResourceTypeById(dclnId); + std::experimental::optional> dclnToken; + if (dclnType) { + dclnToken.emplace(g_SimplePool->GetObj({SBIG('DCLN'), dclnId})); + dclnToken->GetObj(); + } - CModelData data; - if (animType == SBIG('ANCS')) - data = CAnimRes(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, aParms.GetInitialAnimation(), true); - else - data = CStaticRes(staticId, head.x40_scale); + CModelData data; + if (animType == SBIG('ANCS')) + data = CAnimRes(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, aParms.GetInitialAnimation(), true); + else + data = CStaticRes(staticId, head.x40_scale); - if (extent.isZero()) - aabb = data.GetBounds(head.x10_transform.getRotation()); + if (extent.isZero()) + aabb = data.GetBounds(head.x10_transform.getRotation()); - return new CScriptPlatform(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(data), - actParms, aabb, speed, detectCollision, xrayAlpha, active, hInfo, dInfo, - dclnToken, rainSplashes, maxRainSplashes, rainGenRate); + return new CScriptPlatform(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(data), actParms, + aabb, speed, detectCollision, xrayAlpha, active, hInfo, dInfo, dclnToken, rainSplashes, + maxRainSplashes, rainGenRate); } -CEntity* ScriptLoader::LoadSound(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 20, "Sound")) - return nullptr; +CEntity* ScriptLoader::LoadSound(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 20, "Sound")) + return nullptr; - SActorHead head = LoadActorHead(in, mgr); - s32 soundId = in.readInt32Big(); - bool active = in.readBool(); - float maxDist = in.readFloatBig(); - float distComp = in.readFloatBig(); - float startDelay = in.readFloatBig(); - u32 minVol = in.readUint32Big(); - u32 vol = in.readUint32Big(); - u32 prio = in.readUint32Big(); - u32 pan = in.readUint32Big(); - bool loop = in.readBool(); - bool nonEmitter = in.readBool(); - bool autoStart = in.readBool(); - bool occlusionTest = in.readBool(); - bool acoustics = in.readBool(); - bool worldSfx = in.readBool(); - bool allowDuplicates = in.readBool(); - s32 pitch = in.readInt32Big(); + SActorHead head = LoadActorHead(in, mgr); + s32 soundId = in.readInt32Big(); + bool active = in.readBool(); + float maxDist = in.readFloatBig(); + float distComp = in.readFloatBig(); + float startDelay = in.readFloatBig(); + u32 minVol = in.readUint32Big(); + u32 vol = in.readUint32Big(); + u32 prio = in.readUint32Big(); + u32 pan = in.readUint32Big(); + bool loop = in.readBool(); + bool nonEmitter = in.readBool(); + bool autoStart = in.readBool(); + bool occlusionTest = in.readBool(); + bool acoustics = in.readBool(); + bool worldSfx = in.readBool(); + bool allowDuplicates = in.readBool(); + s32 pitch = in.readInt32Big(); - if (soundId < 0) - return nullptr; + if (soundId < 0) + return nullptr; - return new CScriptSound(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, u16(soundId), active, - maxDist, distComp, startDelay, minVol, vol, 0, prio, pan, 0, loop, nonEmitter, autoStart, - occlusionTest, acoustics, worldSfx, allowDuplicates, pitch); + return new CScriptSound(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, u16(soundId), active, maxDist, + distComp, startDelay, minVol, vol, 0, prio, pan, 0, loop, nonEmitter, autoStart, + occlusionTest, acoustics, worldSfx, allowDuplicates, pitch); } -CEntity* ScriptLoader::LoadGenerator(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 8, "Generator")) - return nullptr; +CEntity* ScriptLoader::LoadGenerator(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 8, "Generator")) + return nullptr; - std::string name = mgr.HashInstanceName(in); + std::string name = mgr.HashInstanceName(in); - u32 spawnCount = in.readUint32Big(); - bool noReuseFollowers = in.readBool(); - bool noInheritXf = in.readBool(); + u32 spawnCount = in.readUint32Big(); + bool noReuseFollowers = in.readBool(); + bool noInheritXf = in.readBool(); - zeus::CVector3f offset = zeus::CVector3f::ReadBig(in); + zeus::CVector3f offset = zeus::CVector3f::ReadBig(in); - bool active = in.readBool(); - float minScale = in.readFloatBig(); - float maxScale = in.readFloatBig(); + bool active = in.readBool(); + float minScale = in.readFloatBig(); + float maxScale = in.readFloatBig(); - return new CScriptGenerator(mgr.AllocateUniqueId(), name, info, spawnCount, noReuseFollowers, offset, noInheritXf, - active, minScale, maxScale); + return new CScriptGenerator(mgr.AllocateUniqueId(), name, info, spawnCount, noReuseFollowers, offset, noInheritXf, + active, minScale, maxScale); } -CEntity* ScriptLoader::LoadDock(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 7, "Dock")) - return nullptr; +CEntity* ScriptLoader::LoadDock(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 7, "Dock")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - zeus::CVector3f position; - position.readBig(in); - zeus::CVector3f scale; - scale.readBig(in); - u32 dock = in.readUint32Big(); - TAreaId area = in.readUint32Big(); - bool loadConnected = in.readBool(); - return new CScriptDock(mgr.AllocateUniqueId(), name, info, position, scale, dock, area, active, 0, loadConnected); + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + zeus::CVector3f position; + position.readBig(in); + zeus::CVector3f scale; + scale.readBig(in); + u32 dock = in.readUint32Big(); + TAreaId area = in.readUint32Big(); + bool loadConnected = in.readBool(); + return new CScriptDock(mgr.AllocateUniqueId(), name, info, position, scale, dock, area, active, 0, loadConnected); } -CEntity* ScriptLoader::LoadCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 14, "Camera")) - return nullptr; +CEntity* ScriptLoader::LoadCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 14, "Camera")) + return nullptr; - SActorHead head = LoadActorHead(in, mgr); + SActorHead head = LoadActorHead(in, mgr); - bool active = in.readBool(); - float shotDuration = in.readFloatBig(); - bool lookAtPlayer = in.readBool(); - bool outOfPlayerEye = in.readBool(); - bool intoPlayerEye = in.readBool(); - bool drawPlayer = in.readBool(); - bool disableInput = in.readBool(); - bool b7 = in.readBool(); - bool finishCineSkip = in.readBool(); - float fov = in.readFloatBig(); - bool checkFailsafe = in.readBool(); + bool active = in.readBool(); + float shotDuration = in.readFloatBig(); + bool lookAtPlayer = in.readBool(); + bool outOfPlayerEye = in.readBool(); + bool intoPlayerEye = in.readBool(); + bool drawPlayer = in.readBool(); + bool disableInput = in.readBool(); + bool b7 = in.readBool(); + bool finishCineSkip = in.readBool(); + float fov = in.readFloatBig(); + bool checkFailsafe = in.readBool(); - bool disableOutOfInto = false; - if (propCount > 14) - disableOutOfInto = in.readBool(); + bool disableOutOfInto = false; + if (propCount > 14) + disableOutOfInto = in.readBool(); - s32 flags = s32(lookAtPlayer) | s32(outOfPlayerEye) << 1 | s32(intoPlayerEye) << 2 | s32(b7) << 3 | - s32(finishCineSkip) << 4 | s32(disableInput) << 5 | s32(drawPlayer) << 6 | - s32(checkFailsafe) << 7 | s32(disableOutOfInto) << 9; + s32 flags = s32(lookAtPlayer) | s32(outOfPlayerEye) << 1 | s32(intoPlayerEye) << 2 | s32(b7) << 3 | + s32(finishCineSkip) << 4 | s32(disableInput) << 5 | s32(drawPlayer) << 6 | s32(checkFailsafe) << 7 | + s32(disableOutOfInto) << 9; - return new CCinematicCamera(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, shotDuration, - fov / CCameraManager::Aspect(), CCameraManager::NearPlane(), CCameraManager::FarPlane(), - CCameraManager::Aspect(), flags); + return new CCinematicCamera(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, shotDuration, + fov / CCameraManager::Aspect(), CCameraManager::NearPlane(), CCameraManager::FarPlane(), + CCameraManager::Aspect(), flags); } -CEntity* ScriptLoader::LoadCameraWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 6, "CameraWaypoint")) - return nullptr; +CEntity* ScriptLoader::LoadCameraWaypoint(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 6, "CameraWaypoint")) + return nullptr; - SActorHead head = LoadActorHead(in, mgr); + SActorHead head = LoadActorHead(in, mgr); - bool active = in.readBool(); - float f1 = in.readFloatBig(); - u32 w1 = in.readUint32Big(); + bool active = in.readBool(); + float f1 = in.readFloatBig(); + u32 w1 = in.readUint32Big(); - return new CScriptCameraWaypoint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, f1, w1); + return new CScriptCameraWaypoint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, f1, w1); } -CEntity* ScriptLoader::LoadNewIntroBoss(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 13, "NewIntroBoss")) - return nullptr; +CEntity* ScriptLoader::LoadNewIntroBoss(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 13, "NewIntroBoss")) + return nullptr; - SScaledActorHead head = LoadScaledActorHead(in, mgr); + SScaledActorHead head = LoadScaledActorHead(in, mgr); - std::pair pcount = CPatternedInfo::HasCorrectParameterCount(in); - if (!pcount.first) - return nullptr; + std::pair pcount = CPatternedInfo::HasCorrectParameterCount(in); + if (!pcount.first) + return nullptr; - CPatternedInfo pInfo(in, pcount.second); + CPatternedInfo pInfo(in, pcount.second); - CActorParameters actParms = LoadActorParameters(in); + CActorParameters actParms = LoadActorParameters(in); - float f1 = in.readFloatBig(); - CAssetId w1(in); + float f1 = in.readFloatBig(); + CAssetId w1(in); - CDamageInfo dInfo(in); + CDamageInfo dInfo(in); - CAssetId w2(in); - CAssetId w3(in); - CAssetId w4(in); - CAssetId w5(in); + CAssetId w2(in); + CAssetId w3(in); + CAssetId w4(in); + CAssetId w5(in); - const CAnimationParameters& aParms = pInfo.GetAnimationParameters(); - FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile()); - if (animType != SBIG('ANCS')) - return nullptr; + const CAnimationParameters& aParms = pInfo.GetAnimationParameters(); + FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile()); + if (animType != SBIG('ANCS')) + return nullptr; - CAnimRes res(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, aParms.GetInitialAnimation(), true); + CAnimRes res(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, aParms.GetInitialAnimation(), true); - return new MP1::CNewIntroBoss(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, res, pInfo, actParms, - f1, w1, dInfo, w2, w3, w4, w5); + return new MP1::CNewIntroBoss(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, res, pInfo, actParms, + f1, w1, dInfo, w2, w3, w4, w5); } -CEntity* ScriptLoader::LoadSpawnPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 35, "SpawnPoint")) - return nullptr; +CEntity* ScriptLoader::LoadSpawnPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 35, "SpawnPoint")) + return nullptr; - std::string name = mgr.HashInstanceName(in); + std::string name = mgr.HashInstanceName(in); - zeus::CVector3f position; - position.readBig(in); + zeus::CVector3f position; + position.readBig(in); - zeus::CVector3f rotation; - rotation.readBig(in); + zeus::CVector3f rotation; + rotation.readBig(in); - rstl::reserved_vector itemCounts; - itemCounts.resize(size_t(CPlayerState::EItemType::Max)); - for (int i = 0; i < propCount - 6; ++i) - itemCounts[i] = in.readUint32Big(); + rstl::reserved_vector itemCounts; + itemCounts.resize(size_t(CPlayerState::EItemType::Max)); + for (int i = 0; i < propCount - 6; ++i) + itemCounts[i] = in.readUint32Big(); - bool defaultSpawn = in.readBool(); - bool active = in.readBool(); - bool morphed = false; - if (propCount > 34) - morphed = in.readBool(); + bool defaultSpawn = in.readBool(); + bool active = in.readBool(); + bool morphed = false; + if (propCount > 34) + morphed = in.readBool(); - return new CScriptSpawnPoint(mgr.AllocateUniqueId(), name, info, - ConvertEditorEulerToTransform4f(rotation, position), itemCounts, defaultSpawn, active, - morphed); + return new CScriptSpawnPoint(mgr.AllocateUniqueId(), name, info, ConvertEditorEulerToTransform4f(rotation, position), + itemCounts, defaultSpawn, active, morphed); } -CEntity* ScriptLoader::LoadCameraHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (propCount > 25) - { - Log.report(logvisor::Warning, "Too many props (%d > 25) for CameraHint entity", propCount); - return nullptr; - } +CEntity* ScriptLoader::LoadCameraHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (propCount > 25) { + Log.report(logvisor::Warning, "Too many props (%d > 25) for CameraHint entity", propCount); + return nullptr; + } - SActorHead head = LoadActorHead(in, mgr); + SActorHead head = LoadActorHead(in, mgr); - bool active = in.readBool(); - u32 prio = in.readUint32Big(); - auto behaviour = CBallCamera::EBallCameraBehaviour(in.readUint32Big()); - u32 overrideFlags = LoadParameterFlags(in); - overrideFlags |= in.readBool() << 22; - float minDist = in.readFloatBig(); - overrideFlags |= in.readBool() << 23; - float maxDist = in.readFloatBig(); - overrideFlags |= in.readBool() << 24; - float backwardsDist = in.readFloatBig(); - overrideFlags |= in.readBool() << 25; - zeus::CVector3f lookAtOffset; - lookAtOffset.readBig(in); - overrideFlags |= in.readBool() << 26; - zeus::CVector3f chaseLookAtOffset; - chaseLookAtOffset.readBig(in); - zeus::CVector3f ballToCam; - ballToCam.readBig(in); - overrideFlags |= in.readBool() << 27; - float fov = in.readFloatBig(); - overrideFlags |= in.readBool() << 28; - float attitudeRange = zeus::degToRad(in.readFloatBig()); - overrideFlags |= in.readBool() << 29; - float azimuthRange = zeus::degToRad(in.readFloatBig()); - overrideFlags |= in.readBool() << 30; - float anglePerSecond = zeus::degToRad(in.readFloatBig()); - float clampVelRange = in.readFloatBig(); - float clampRotRange = zeus::degToRad(in.readFloatBig()); - overrideFlags |= in.readBool() << 31; - float elevation = in.readFloatBig(); - float interpolateTime = in.readFloatBig(); - float clampVelTime = in.readFloatBig(); - float controlInterpDur = in.readFloatBig(); + bool active = in.readBool(); + u32 prio = in.readUint32Big(); + auto behaviour = CBallCamera::EBallCameraBehaviour(in.readUint32Big()); + u32 overrideFlags = LoadParameterFlags(in); + overrideFlags |= in.readBool() << 22; + float minDist = in.readFloatBig(); + overrideFlags |= in.readBool() << 23; + float maxDist = in.readFloatBig(); + overrideFlags |= in.readBool() << 24; + float backwardsDist = in.readFloatBig(); + overrideFlags |= in.readBool() << 25; + zeus::CVector3f lookAtOffset; + lookAtOffset.readBig(in); + overrideFlags |= in.readBool() << 26; + zeus::CVector3f chaseLookAtOffset; + chaseLookAtOffset.readBig(in); + zeus::CVector3f ballToCam; + ballToCam.readBig(in); + overrideFlags |= in.readBool() << 27; + float fov = in.readFloatBig(); + overrideFlags |= in.readBool() << 28; + float attitudeRange = zeus::degToRad(in.readFloatBig()); + overrideFlags |= in.readBool() << 29; + float azimuthRange = zeus::degToRad(in.readFloatBig()); + overrideFlags |= in.readBool() << 30; + float anglePerSecond = zeus::degToRad(in.readFloatBig()); + float clampVelRange = in.readFloatBig(); + float clampRotRange = zeus::degToRad(in.readFloatBig()); + overrideFlags |= in.readBool() << 31; + float elevation = in.readFloatBig(); + float interpolateTime = in.readFloatBig(); + float clampVelTime = in.readFloatBig(); + float controlInterpDur = in.readFloatBig(); - return new CScriptCameraHint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, prio, - behaviour, overrideFlags, minDist, maxDist, backwardsDist, lookAtOffset, - chaseLookAtOffset, ballToCam, fov, attitudeRange, azimuthRange, anglePerSecond, - clampVelRange, clampRotRange, elevation, interpolateTime, clampVelTime, - controlInterpDur); + return new CScriptCameraHint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, prio, behaviour, + overrideFlags, minDist, maxDist, backwardsDist, lookAtOffset, chaseLookAtOffset, + ballToCam, fov, attitudeRange, azimuthRange, anglePerSecond, clampVelRange, + clampRotRange, elevation, interpolateTime, clampVelTime, controlInterpDur); } -CEntity* ScriptLoader::LoadPickup(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 18, "Pickup")) - return nullptr; +CEntity* ScriptLoader::LoadPickup(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 18, "Pickup")) + return nullptr; - SScaledActorHead head = LoadScaledActorHead(in, mgr); - zeus::CVector3f extent = zeus::CVector3f::ReadBig(in); - zeus::CVector3f offset = zeus::CVector3f::ReadBig(in); - CPlayerState::EItemType w1 = CPlayerState::EItemType(in.readUint32Big()); - u32 w2 = in.readUint32Big(); - u32 w3 = in.readUint32Big(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - CAssetId staticModel = in.readUint32Big(); - CAnimationParameters animParms = LoadAnimationParameters(in); - CActorParameters actorParms = LoadActorParameters(in); - bool active = in.readBool(); - float f4 = in.readFloatBig(); - CAssetId w4(in); + SScaledActorHead head = LoadScaledActorHead(in, mgr); + zeus::CVector3f extent = zeus::CVector3f::ReadBig(in); + zeus::CVector3f offset = zeus::CVector3f::ReadBig(in); + CPlayerState::EItemType w1 = CPlayerState::EItemType(in.readUint32Big()); + u32 w2 = in.readUint32Big(); + u32 w3 = in.readUint32Big(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + CAssetId staticModel = in.readUint32Big(); + CAnimationParameters animParms = LoadAnimationParameters(in); + CActorParameters actorParms = LoadActorParameters(in); + bool active = in.readBool(); + float f4 = in.readFloatBig(); + CAssetId w4(in); - FourCC acsType = g_ResFactory->GetResourceTypeById(animParms.GetACSFile()); - if (g_ResFactory->GetResourceTypeById(staticModel) == 0 && acsType == 0) - return nullptr; + FourCC acsType = g_ResFactory->GetResourceTypeById(animParms.GetACSFile()); + if (g_ResFactory->GetResourceTypeById(staticModel) == 0 && acsType == 0) + return nullptr; - zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), extent, offset); + zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), extent, offset); - CModelData data; + CModelData data; - if (acsType == SBIG('ANCS')) - data = CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), head.x40_scale, - animParms.GetInitialAnimation(), true); - else - data = CStaticRes(staticModel, head.x40_scale); + if (acsType == SBIG('ANCS')) + data = CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), head.x40_scale, animParms.GetInitialAnimation(), + true); + else + data = CStaticRes(staticModel, head.x40_scale); - if (extent.isZero()) - aabb = data.GetBounds(head.x10_transform.getRotation()); + if (extent.isZero()) + aabb = data.GetBounds(head.x10_transform.getRotation()); - return new CScriptPickup(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(data), - actorParms, aabb, w1, w3, w2, w4, f1, f2, f3, f4, active); + return new CScriptPickup(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(data), actorParms, + aabb, w1, w3, w2, w4, f1, f2, f3, f4, active); } -CEntity* ScriptLoader::LoadMemoryRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 3, "MemoryRelay") || propCount > 4) - return nullptr; +CEntity* ScriptLoader::LoadMemoryRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 3, "MemoryRelay") || propCount > 4) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool b1 = in.readBool(); - bool b2 = in.readBool(); - bool b3 = false; - if (propCount > 3) - b3 = in.readBool(); + std::string name = mgr.HashInstanceName(in); + bool b1 = in.readBool(); + bool b2 = in.readBool(); + bool b3 = false; + if (propCount > 3) + b3 = in.readBool(); - return new CScriptMemoryRelay(mgr.AllocateUniqueId(), name, info, b1, b2, b3); + return new CScriptMemoryRelay(mgr.AllocateUniqueId(), name, info, b1, b2, b3); } -CEntity* ScriptLoader::LoadRandomRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 5, "RandomRelay")) - return nullptr; - std::string name = mgr.HashInstanceName(in); - u32 w1 = in.readUint32Big(); - u32 w2 = in.readUint32Big(); - bool b1 = in.readBool(); - bool b2 = in.readBool(); +CEntity* ScriptLoader::LoadRandomRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 5, "RandomRelay")) + return nullptr; + std::string name = mgr.HashInstanceName(in); + u32 w1 = in.readUint32Big(); + u32 w2 = in.readUint32Big(); + bool b1 = in.readBool(); + bool b2 = in.readBool(); - return new CScriptRandomRelay(mgr.AllocateUniqueId(), name, info, w1, w2, b1, b2); + return new CScriptRandomRelay(mgr.AllocateUniqueId(), name, info, w1, w2, b1, b2); } -CEntity* ScriptLoader::LoadRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 2, "Relay") || propCount > 3) - return nullptr; +CEntity* ScriptLoader::LoadRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 2, "Relay") || propCount > 3) + return nullptr; - std::string name = mgr.HashInstanceName(in); - if (propCount >= 3) - in.readUint32Big(); - bool b1 = in.readBool(); + std::string name = mgr.HashInstanceName(in); + if (propCount >= 3) + in.readUint32Big(); + bool b1 = in.readBool(); - return new CScriptRelay(mgr.AllocateUniqueId(), name, info, b1); + return new CScriptRelay(mgr.AllocateUniqueId(), name, info, b1); } -CEntity* ScriptLoader::LoadBeetle(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 16, "Beetle")) - return nullptr; - std::string name = mgr.HashInstanceName(in); - CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); - zeus::CTransform xfrm = LoadEditorTransform(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - std::pair pcount = CPatternedInfo::HasCorrectParameterCount(in); - if (!pcount.first) - return nullptr; +CEntity* ScriptLoader::LoadBeetle(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 16, "Beetle")) + return nullptr; + std::string name = mgr.HashInstanceName(in); + CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); + zeus::CTransform xfrm = LoadEditorTransform(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + std::pair pcount = CPatternedInfo::HasCorrectParameterCount(in); + if (!pcount.first) + return nullptr; - CPatternedInfo pInfo(in, pcount.second); - CActorParameters aParams = LoadActorParameters(in); - CDamageInfo dInfo(in); - zeus::CVector3f v1 = zeus::CVector3f::ReadBig(in); - float f1 = in.readFloatBig(); - CDamageVulnerability dVuln1(in); - CDamageVulnerability dVuln2(in); - CAssetId abdomen = in.readUint32Big(); - MP1::CBeetle::EEntranceType entrance = MP1::CBeetle::EEntranceType(in.readUint32Big()); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); + CPatternedInfo pInfo(in, pcount.second); + CActorParameters aParams = LoadActorParameters(in); + CDamageInfo dInfo(in); + zeus::CVector3f v1 = zeus::CVector3f::ReadBig(in); + float f1 = in.readFloatBig(); + CDamageVulnerability dVuln1(in); + CDamageVulnerability dVuln2(in); + CAssetId abdomen = in.readUint32Big(); + MP1::CBeetle::EEntranceType entrance = MP1::CBeetle::EEntranceType(in.readUint32Big()); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); - FourCC animType = g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()); - if (animType != SBIG('ANCS')) - return nullptr; + FourCC animType = g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()); + if (animType != SBIG('ANCS')) + return nullptr; - std::experimental::optional abdomenRes; - if (flavor == CPatterned::EFlavorType::One) - abdomenRes.emplace(CStaticRes(abdomen, scale)); + std::experimental::optional abdomenRes; + if (flavor == CPatterned::EFlavorType::One) + abdomenRes.emplace(CStaticRes(abdomen, scale)); - const CAnimationParameters& animParams = pInfo.GetAnimationParameters(); - CAnimRes animRes(animParams.GetACSFile(), animParams.GetCharacter(), scale, animParams.GetInitialAnimation(), true); + const CAnimationParameters& animParams = pInfo.GetAnimationParameters(); + CAnimRes animRes(animParams.GetACSFile(), animParams.GetCharacter(), scale, animParams.GetInitialAnimation(), true); - return new MP1::CBeetle(mgr.AllocateUniqueId(), name, info, xfrm, animRes, pInfo, flavor, entrance, dInfo, dVuln2, - v1, f2, f3, f1, dVuln1, aParams, abdomenRes); + return new MP1::CBeetle(mgr.AllocateUniqueId(), name, info, xfrm, animRes, pInfo, flavor, entrance, dInfo, dVuln2, v1, + f2, f3, f1, dVuln1, aParams, abdomenRes); } -CEntity* ScriptLoader::LoadHUDMemo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (propCount != 5 && !EnsurePropertyCount(propCount, 6, "HUDMemo")) - return 0; - std::string name = mgr.HashInstanceName(in); - CHUDMemoParms hParms(in); - CScriptHUDMemo::EDisplayType displayType = CScriptHUDMemo::EDisplayType::MessageBox; - if (propCount == 6) - displayType = CScriptHUDMemo::EDisplayType(in.readUint32Big()); - CAssetId message = in.readUint32Big(); - bool active = in.readBool(); +CEntity* ScriptLoader::LoadHUDMemo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (propCount != 5 && !EnsurePropertyCount(propCount, 6, "HUDMemo")) + return 0; + std::string name = mgr.HashInstanceName(in); + CHUDMemoParms hParms(in); + CScriptHUDMemo::EDisplayType displayType = CScriptHUDMemo::EDisplayType::MessageBox; + if (propCount == 6) + displayType = CScriptHUDMemo::EDisplayType(in.readUint32Big()); + CAssetId message = in.readUint32Big(); + bool active = in.readBool(); - return new CScriptHUDMemo(mgr.AllocateUniqueId(), name, info, hParms, displayType, message, active); + return new CScriptHUDMemo(mgr.AllocateUniqueId(), name, info, hParms, displayType, message, active); } CEntity* ScriptLoader::LoadCameraFilterKeyframe(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 10, "CameraFilterKeyframe")) - return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - EFilterType ftype = EFilterType(in.readUint32Big()); - EFilterShape shape = EFilterShape(in.readUint32Big()); - u32 filterIdx = in.readUint32Big(); - u32 unk = in.readUint32Big(); - zeus::CColor color; - color.readRGBABig(in); - float timeIn = in.readFloatBig(); - float timeOut = in.readFloatBig(); - CAssetId txtr = in.readUint32Big(); + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 10, "CameraFilterKeyframe")) + return nullptr; + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + EFilterType ftype = EFilterType(in.readUint32Big()); + EFilterShape shape = EFilterShape(in.readUint32Big()); + u32 filterIdx = in.readUint32Big(); + u32 unk = in.readUint32Big(); + zeus::CColor color; + color.readRGBABig(in); + float timeIn = in.readFloatBig(); + float timeOut = in.readFloatBig(); + CAssetId txtr = in.readUint32Big(); - return new CScriptCameraFilterKeyframe(mgr.AllocateUniqueId(), name, info, ftype, shape, filterIdx, unk, color, - timeIn, timeOut, txtr, active); + return new CScriptCameraFilterKeyframe(mgr.AllocateUniqueId(), name, info, ftype, shape, filterIdx, unk, color, + timeIn, timeOut, txtr, active); } CEntity* ScriptLoader::LoadCameraBlurKeyframe(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 7, "CameraBlurKeyframe")) - return nullptr; + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 7, "CameraBlurKeyframe")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - EBlurType type = EBlurType(in.readUint32Big()); - float amount = in.readFloatBig(); - u32 unk = in.readUint32Big(); - float timeIn = in.readFloatBig(); - float timeOut = in.readFloatBig(); + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + EBlurType type = EBlurType(in.readUint32Big()); + float amount = in.readFloatBig(); + u32 unk = in.readUint32Big(); + float timeIn = in.readFloatBig(); + float timeOut = in.readFloatBig(); - return new CScriptCameraBlurKeyframe(mgr.AllocateUniqueId(), name, info, type, amount, unk, timeIn, timeOut, - active); + return new CScriptCameraBlurKeyframe(mgr.AllocateUniqueId(), name, info, type, amount, unk, timeIn, timeOut, active); } -u32 ClassifyVector(const zeus::CVector3f& dir) -{ - zeus::CVector3f absDir(std::fabs(dir.x()), std::fabs(dir.y()), std::fabs(dir.z())); - u32 max = (absDir.x() > absDir.y() ? 0 : 1); - max = (absDir[max] > absDir.z() ? max : 2); +u32 ClassifyVector(const zeus::CVector3f& dir) { + zeus::CVector3f absDir(std::fabs(dir.x()), std::fabs(dir.y()), std::fabs(dir.z())); + u32 max = (absDir.x() > absDir.y() ? 0 : 1); + max = (absDir[max] > absDir.z() ? max : 2); - bool positive = (absDir[max] == dir[max]); - if (max == 0) - return (positive ? 0x08 : 0x04); - else if (max == 1) - return (positive ? 0x01 : 0x02); - else if (max == 2) - return (positive ? 0x10 : 0x20); + bool positive = (absDir[max] == dir[max]); + if (max == 0) + return (positive ? 0x08 : 0x04); + else if (max == 1) + return (positive ? 0x01 : 0x02); + else if (max == 2) + return (positive ? 0x10 : 0x20); - return 0; + return 0; } -u32 TransformDamagableTriggerFlags(CStateManager& mgr, TAreaId aId, u32 flags) -{ - CGameArea* area = mgr.WorldNC()->GetGameAreas().at(u32(aId)).get(); - zeus::CTransform rotation = area->GetTransform().getRotation(); +u32 TransformDamagableTriggerFlags(CStateManager& mgr, TAreaId aId, u32 flags) { + CGameArea* area = mgr.WorldNC()->GetGameAreas().at(u32(aId)).get(); + zeus::CTransform rotation = area->GetTransform().getRotation(); - u32 ret = 0; - if (flags & 0x01) - ret |= ClassifyVector(rotation * zeus::CVector3f::skForward); - if (flags & 0x02) - ret |= ClassifyVector(rotation * zeus::CVector3f::skBack); - if (flags & 0x04) - ret |= ClassifyVector(rotation * zeus::CVector3f::skLeft); - if (flags & 0x08) - ret |= ClassifyVector(rotation * zeus::CVector3f::skRight); - if (flags & 0x10) - ret |= ClassifyVector(rotation * zeus::CVector3f::skUp); - if (flags & 0x20) - ret |= ClassifyVector(rotation * zeus::CVector3f::skDown); - return ret; + u32 ret = 0; + if (flags & 0x01) + ret |= ClassifyVector(rotation * zeus::CVector3f::skForward); + if (flags & 0x02) + ret |= ClassifyVector(rotation * zeus::CVector3f::skBack); + if (flags & 0x04) + ret |= ClassifyVector(rotation * zeus::CVector3f::skLeft); + if (flags & 0x08) + ret |= ClassifyVector(rotation * zeus::CVector3f::skRight); + if (flags & 0x10) + ret |= ClassifyVector(rotation * zeus::CVector3f::skUp); + if (flags & 0x20) + ret |= ClassifyVector(rotation * zeus::CVector3f::skDown); + return ret; } CEntity* ScriptLoader::LoadDamageableTrigger(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 12, "DamageableTrigger")) - return nullptr; + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 12, "DamageableTrigger")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f position(zeus::CVector3f::ReadBig(in)); - zeus::CVector3f volume(zeus::CVector3f::ReadBig(in)); + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f position(zeus::CVector3f::ReadBig(in)); + zeus::CVector3f volume(zeus::CVector3f::ReadBig(in)); - CHealthInfo hInfo(in); - CDamageVulnerability dVuln(in); - u32 triggerFlags = in.readUint32Big(); - triggerFlags = TransformDamagableTriggerFlags(mgr, info.GetAreaId(), triggerFlags); - CAssetId patternTex1 = in.readUint32Big(); - CAssetId patternTex2 = in.readUint32Big(); - CAssetId colorTex = in.readUint32Big(); - CScriptDamageableTrigger::ECanOrbit canOrbit = CScriptDamageableTrigger::ECanOrbit(in.readBool()); - bool active = in.readBool(); - CVisorParameters vParms = LoadVisorParameters(in); - return new CScriptDamageableTrigger(mgr.AllocateUniqueId(), name, info, position, volume, hInfo, dVuln, - triggerFlags, patternTex1, patternTex2, colorTex, canOrbit, active, vParms); + CHealthInfo hInfo(in); + CDamageVulnerability dVuln(in); + u32 triggerFlags = in.readUint32Big(); + triggerFlags = TransformDamagableTriggerFlags(mgr, info.GetAreaId(), triggerFlags); + CAssetId patternTex1 = in.readUint32Big(); + CAssetId patternTex2 = in.readUint32Big(); + CAssetId colorTex = in.readUint32Big(); + CScriptDamageableTrigger::ECanOrbit canOrbit = CScriptDamageableTrigger::ECanOrbit(in.readBool()); + bool active = in.readBool(); + CVisorParameters vParms = LoadVisorParameters(in); + return new CScriptDamageableTrigger(mgr.AllocateUniqueId(), name, info, position, volume, hInfo, dVuln, triggerFlags, + patternTex1, patternTex2, colorTex, canOrbit, active, vParms); } -CEntity* ScriptLoader::LoadDebris(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 18, "Debris")) - return nullptr; +CEntity* ScriptLoader::LoadDebris(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 18, "Debris")) + return nullptr; - SScaledActorHead head = LoadScaledActorHead(in, mgr); - float zImpulse = in.readFloatBig(); - zeus::CVector3f velocity = zeus::CVector3f::ReadBig(in); - zeus::CColor endsColor; - endsColor.readRGBABig(in); - float mass = in.readFloatBig(); - float restitution = in.readFloatBig(); - float duration = in.readFloatBig(); - CScriptDebris::EScaleType scaleType = CScriptDebris::EScaleType(in.readUint32Big()); - bool randomAngImpulse = in.readBool(); - CAssetId model = in.readUint32Big(); - CActorParameters aParams = LoadActorParameters(in); - CAssetId particleId = in.readUint32Big(); - zeus::CVector3f particleScale = zeus::CVector3f::ReadBig(in); - bool b1 = in.readBool(); - bool active = in.readBool(); + SScaledActorHead head = LoadScaledActorHead(in, mgr); + float zImpulse = in.readFloatBig(); + zeus::CVector3f velocity = zeus::CVector3f::ReadBig(in); + zeus::CColor endsColor; + endsColor.readRGBABig(in); + float mass = in.readFloatBig(); + float restitution = in.readFloatBig(); + float duration = in.readFloatBig(); + CScriptDebris::EScaleType scaleType = CScriptDebris::EScaleType(in.readUint32Big()); + bool randomAngImpulse = in.readBool(); + CAssetId model = in.readUint32Big(); + CActorParameters aParams = LoadActorParameters(in); + CAssetId particleId = in.readUint32Big(); + zeus::CVector3f particleScale = zeus::CVector3f::ReadBig(in); + bool b1 = in.readBool(); + bool active = in.readBool(); - if (!g_ResFactory->GetResourceTypeById(model)) - return nullptr; - return new CScriptDebris(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, - CStaticRes(model, head.x40_scale), aParams, particleId, particleScale, zImpulse, velocity, - endsColor, mass, restitution, duration, scaleType, b1, randomAngImpulse, active); + if (!g_ResFactory->GetResourceTypeById(model)) + return nullptr; + return new CScriptDebris(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, + CStaticRes(model, head.x40_scale), aParams, particleId, particleScale, zImpulse, velocity, + endsColor, mass, restitution, duration, scaleType, b1, randomAngImpulse, active); } -CEntity* ScriptLoader::LoadCameraShaker(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 9, "CameraShaker")) - return nullptr; +CEntity* ScriptLoader::LoadCameraShaker(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 9, "CameraShaker")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - CCameraShakeData shakeData = CCameraShakeData::LoadCameraShakeData(in); - bool active = in.readBool(); + std::string name = mgr.HashInstanceName(in); + CCameraShakeData shakeData = CCameraShakeData::LoadCameraShakeData(in); + bool active = in.readBool(); - return new CScriptCameraShaker(mgr.AllocateUniqueId(), name, info, active, shakeData); + return new CScriptCameraShaker(mgr.AllocateUniqueId(), name, info, active, shakeData); } -CEntity* ScriptLoader::LoadActorKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 7, "ActorKeyframe")) - return nullptr; +CEntity* ScriptLoader::LoadActorKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 7, "ActorKeyframe")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - s32 animId = in.readInt32Big(); - bool looping = in.readBool(); - float lifetime = in.readFloatBig(); - bool active = in.readBool(); - u32 fadeOut = in.readUint32Big(); - float totalPlayback = in.readFloatBig(); + std::string name = mgr.HashInstanceName(in); + s32 animId = in.readInt32Big(); + bool looping = in.readBool(); + float lifetime = in.readFloatBig(); + bool active = in.readBool(); + u32 fadeOut = in.readUint32Big(); + float totalPlayback = in.readFloatBig(); - if (animId == -1) - return nullptr; + if (animId == -1) + return nullptr; - return new CScriptActorKeyframe(mgr.AllocateUniqueId(), name, info, animId, looping, lifetime, false, fadeOut, - active, totalPlayback); + return new CScriptActorKeyframe(mgr.AllocateUniqueId(), name, info, animId, looping, lifetime, false, fadeOut, active, + totalPlayback); } -CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 63, "Water")) - return nullptr; +CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 63, "Water")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f position; - position.readBig(in); - zeus::CVector3f extent; - extent.readBig(in); - CDamageInfo dInfo(in); - zeus::CVector3f orientedForce; - orientedForce.readBig(in); - ETriggerFlags - triggerFlags = ETriggerFlags(in.readUint32Big()) | ETriggerFlags::DetectProjectiles1 | - ETriggerFlags::DetectProjectiles2 | ETriggerFlags::DetectProjectiles3 | - ETriggerFlags::DetectProjectiles4 | ETriggerFlags::DetectBombs | - ETriggerFlags::DetectPowerBombs | ETriggerFlags::DetectProjectiles5 | - ETriggerFlags::DetectProjectiles6 | ETriggerFlags::DetectProjectiles7; - bool thermalCold = in.readBool(); - bool displaySurface = in.readBool(); - CAssetId patternMap1 = in.readUint32Big(); - CAssetId patternMap2 = in.readUint32Big(); - CAssetId colorMap = in.readUint32Big(); - CAssetId bumpMap = in.readUint32Big(); - CAssetId _envMap = in.readUint32Big(); - CAssetId _envBumpMap = in.readUint32Big(); - zeus::CVector3f _bumpLightDir; - _bumpLightDir.readBig(in); + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f position; + position.readBig(in); + zeus::CVector3f extent; + extent.readBig(in); + CDamageInfo dInfo(in); + zeus::CVector3f orientedForce; + orientedForce.readBig(in); + ETriggerFlags triggerFlags = ETriggerFlags(in.readUint32Big()) | ETriggerFlags::DetectProjectiles1 | + ETriggerFlags::DetectProjectiles2 | ETriggerFlags::DetectProjectiles3 | + ETriggerFlags::DetectProjectiles4 | ETriggerFlags::DetectBombs | + ETriggerFlags::DetectPowerBombs | ETriggerFlags::DetectProjectiles5 | + ETriggerFlags::DetectProjectiles6 | ETriggerFlags::DetectProjectiles7; + bool thermalCold = in.readBool(); + bool displaySurface = in.readBool(); + CAssetId patternMap1 = in.readUint32Big(); + CAssetId patternMap2 = in.readUint32Big(); + CAssetId colorMap = in.readUint32Big(); + CAssetId bumpMap = in.readUint32Big(); + CAssetId _envMap = in.readUint32Big(); + CAssetId _envBumpMap = in.readUint32Big(); + zeus::CVector3f _bumpLightDir; + _bumpLightDir.readBig(in); - zeus::CVector3f bumpLightDir = _bumpLightDir; - if (!bumpLightDir.canBeNormalized()) - bumpLightDir.assign(0.f, 0.f, -1.f); + zeus::CVector3f bumpLightDir = _bumpLightDir; + if (!bumpLightDir.canBeNormalized()) + bumpLightDir.assign(0.f, 0.f, -1.f); - float bumpScale = 1.f / in.readFloatBig(); - float morphInTime = in.readFloatBig(); - float morphOutTime = in.readFloatBig(); - bool active = in.readBool(); - auto fluidType = EFluidType(in.readUint32Big()); - bool b4 = in.readBool(); - float alpha = in.readFloatBig(); - CFluidUVMotion uvMotion = LoadFluidUVMotion(in); + float bumpScale = 1.f / in.readFloatBig(); + float morphInTime = in.readFloatBig(); + float morphOutTime = in.readFloatBig(); + bool active = in.readBool(); + auto fluidType = EFluidType(in.readUint32Big()); + bool b4 = in.readBool(); + float alpha = in.readFloatBig(); + CFluidUVMotion uvMotion = LoadFluidUVMotion(in); - float turbSpeed = in.readFloatBig(); - float turbDistance = in.readFloatBig(); - float turbFreqMax = in.readFloatBig(); - float turbFreqMin = in.readFloatBig(); - float turbPhaseMax = zeus::degToRad(in.readFloatBig()); - float turbPhaseMin = zeus::degToRad(in.readFloatBig()); - float turbAmplitudeMax = in.readFloatBig(); - float turbAmplitudeMin = in.readFloatBig(); - zeus::CColor splashColor; - splashColor.readRGBABig(in); - zeus::CColor insideFogColor; - insideFogColor.readRGBABig(in); - CAssetId splashParticle1 = in.readUint32Big(); - CAssetId splashParticle2 = in.readUint32Big(); - CAssetId splashParticle3 = in.readUint32Big(); - CAssetId visorRunoffParticle = in.readUint32Big(); - CAssetId unmorphVisorRunoffParticle = in.readUint32Big(); - u32 visorRunoffSfx = in.readUint32Big(); - u32 unmorphVisorRunoffSfx = in.readUint32Big(); - u32 splashSfx1 = in.readUint32Big(); - u32 splashSfx2 = in.readUint32Big(); - u32 splashSfx3 = in.readUint32Big(); - float tileSize = in.readFloatBig(); - u32 tileSubdivisions = in.readUint32Big(); - float specularMin = in.readFloatBig(); - float specularMax = in.readFloatBig(); - float reflectionSize = in.readFloatBig(); - float rippleIntensity = in.readFloatBig(); - float reflectionBlend = in.readFloatBig(); - float fogBias = in.readFloatBig(); - float fogMagnitude = in.readFloatBig(); - float fogSpeed = in.readFloatBig(); - zeus::CColor fogColor; - fogColor.readRGBABig(in); - CAssetId lightmap = in.readUint32Big(); - float unitsPerLightmapTexel = in.readFloatBig(); - float alphaInTime = in.readFloatBig(); - float alphaOutTime = in.readFloatBig(); - u32 w21 = in.readUint32Big(); - u32 w22 = in.readUint32Big(); - bool b5 = in.readBool(); + float turbSpeed = in.readFloatBig(); + float turbDistance = in.readFloatBig(); + float turbFreqMax = in.readFloatBig(); + float turbFreqMin = in.readFloatBig(); + float turbPhaseMax = zeus::degToRad(in.readFloatBig()); + float turbPhaseMin = zeus::degToRad(in.readFloatBig()); + float turbAmplitudeMax = in.readFloatBig(); + float turbAmplitudeMin = in.readFloatBig(); + zeus::CColor splashColor; + splashColor.readRGBABig(in); + zeus::CColor insideFogColor; + insideFogColor.readRGBABig(in); + CAssetId splashParticle1 = in.readUint32Big(); + CAssetId splashParticle2 = in.readUint32Big(); + CAssetId splashParticle3 = in.readUint32Big(); + CAssetId visorRunoffParticle = in.readUint32Big(); + CAssetId unmorphVisorRunoffParticle = in.readUint32Big(); + u32 visorRunoffSfx = in.readUint32Big(); + u32 unmorphVisorRunoffSfx = in.readUint32Big(); + u32 splashSfx1 = in.readUint32Big(); + u32 splashSfx2 = in.readUint32Big(); + u32 splashSfx3 = in.readUint32Big(); + float tileSize = in.readFloatBig(); + u32 tileSubdivisions = in.readUint32Big(); + float specularMin = in.readFloatBig(); + float specularMax = in.readFloatBig(); + float reflectionSize = in.readFloatBig(); + float rippleIntensity = in.readFloatBig(); + float reflectionBlend = in.readFloatBig(); + float fogBias = in.readFloatBig(); + float fogMagnitude = in.readFloatBig(); + float fogSpeed = in.readFloatBig(); + zeus::CColor fogColor; + fogColor.readRGBABig(in); + CAssetId lightmap = in.readUint32Big(); + float unitsPerLightmapTexel = in.readFloatBig(); + float alphaInTime = in.readFloatBig(); + float alphaOutTime = in.readFloatBig(); + u32 w21 = in.readUint32Big(); + u32 w22 = in.readUint32Big(); + bool b5 = in.readBool(); - std::unique_ptr bitset; - u32 bitVal0 = 0; - u32 bitVal1 = 0; + std::unique_ptr bitset; + u32 bitVal0 = 0; + u32 bitVal1 = 0; - if (b5) - { - bitVal0 = in.readUint16Big(); - bitVal1 = in.readUint16Big(); - u32 len = ((bitVal0 * bitVal1) + 31) / 31; - bitset.reset(new u32[len]); - in.readBytesToBuf(bitset.get(), len * 4); - } + if (b5) { + bitVal0 = in.readUint16Big(); + bitVal1 = in.readUint16Big(); + u32 len = ((bitVal0 * bitVal1) + 31) / 31; + bitset.reset(new u32[len]); + in.readBytesToBuf(bitset.get(), len * 4); + } - zeus::CAABox box(-extent * 0.5f, extent * 0.5f); + zeus::CAABox box(-extent * 0.5f, extent * 0.5f); - CAssetId envBumpMap; - if (!bumpMap.IsValid()) - envBumpMap = _envBumpMap; + CAssetId envBumpMap; + if (!bumpMap.IsValid()) + envBumpMap = _envBumpMap; - CAssetId envMap; - if (!bumpMap.IsValid()) - envMap = _envMap; + CAssetId envMap; + if (!bumpMap.IsValid()) + envMap = _envMap; - return new CScriptWater(mgr, mgr.AllocateUniqueId(), name, info, position, box, dInfo, orientedForce, triggerFlags, - thermalCold, displaySurface, patternMap1, patternMap2, colorMap, bumpMap, envMap, - envBumpMap, {}, bumpLightDir, bumpScale, morphInTime, morphOutTime, active, fluidType, b4, - alpha, uvMotion, turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax, - turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, splashColor, insideFogColor, - splashParticle1, - splashParticle2, splashParticle3, visorRunoffParticle, unmorphVisorRunoffParticle, - visorRunoffSfx, unmorphVisorRunoffSfx, splashSfx1, splashSfx2, splashSfx3, tileSize, - tileSubdivisions, specularMin, specularMax, reflectionSize, rippleIntensity, - reflectionBlend, fogBias, fogMagnitude, fogSpeed, fogColor, lightmap, unitsPerLightmapTexel, - alphaInTime, alphaOutTime, w21, w22, b5, bitVal0, bitVal1, std::move(bitset)); + return new CScriptWater(mgr, mgr.AllocateUniqueId(), name, info, position, box, dInfo, orientedForce, triggerFlags, + thermalCold, displaySurface, patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap, + {}, bumpLightDir, bumpScale, morphInTime, morphOutTime, active, fluidType, b4, alpha, + uvMotion, turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax, turbPhaseMin, + turbAmplitudeMax, turbAmplitudeMin, splashColor, insideFogColor, splashParticle1, + splashParticle2, splashParticle3, visorRunoffParticle, unmorphVisorRunoffParticle, + visorRunoffSfx, unmorphVisorRunoffSfx, splashSfx1, splashSfx2, splashSfx3, tileSize, + tileSubdivisions, specularMin, specularMax, reflectionSize, rippleIntensity, reflectionBlend, + fogBias, fogMagnitude, fogSpeed, fogColor, lightmap, unitsPerLightmapTexel, alphaInTime, + alphaOutTime, w21, w22, b5, bitVal0, bitVal1, std::move(bitset)); } -CEntity* ScriptLoader::LoadWarWasp(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 13, "WarWasp")) - return nullptr; +CEntity* ScriptLoader::LoadWarWasp(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 13, "WarWasp")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); - zeus::CTransform xf = LoadEditorTransformPivotOnly(in); - zeus::CVector3f scale; - scale.readBig(in); + std::string name = mgr.HashInstanceName(in); + CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); + zeus::CTransform xf = LoadEditorTransformPivotOnly(in); + zeus::CVector3f scale; + scale.readBig(in); - std::pair verifyPair = CPatternedInfo::HasCorrectParameterCount(in); - if (!verifyPair.first) - return nullptr; + std::pair verifyPair = CPatternedInfo::HasCorrectParameterCount(in); + if (!verifyPair.first) + return nullptr; - CPatternedInfo pInfo(in, verifyPair.second); - CActorParameters actorParms = LoadActorParameters(in); - CPatterned::EColliderType collider = CPatterned::EColliderType(in.readBool()); - CDamageInfo damageInfo1(in); - CAssetId weaponDesc = in.readUint32Big(); - CDamageInfo damageInfo2(in); - CAssetId particle = in.readUint32Big(); - u32 w1 = in.readUint32Big(); + CPatternedInfo pInfo(in, verifyPair.second); + CActorParameters actorParms = LoadActorParameters(in); + CPatterned::EColliderType collider = CPatterned::EColliderType(in.readBool()); + CDamageInfo damageInfo1(in); + CAssetId weaponDesc = in.readUint32Big(); + CDamageInfo damageInfo2(in); + CAssetId particle = in.readUint32Big(); + u32 w1 = in.readUint32Big(); - const CAnimationParameters& aParms = pInfo.GetAnimationParameters(); - FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile()); - if (animType != SBIG('ANCS')) - return nullptr; + const CAnimationParameters& aParms = pInfo.GetAnimationParameters(); + FourCC animType = g_ResFactory->GetResourceTypeById(aParms.GetACSFile()); + if (animType != SBIG('ANCS')) + return nullptr; - CAnimRes res(aParms.GetACSFile(), aParms.GetCharacter(), scale, aParms.GetInitialAnimation(), true); - CModelData mData(res); - return new MP1::CWarWasp(mgr.AllocateUniqueId(), name, info, xf, std::move(mData), pInfo, flavor, collider, - damageInfo1, actorParms, weaponDesc, damageInfo2, particle, w1); + CAnimRes res(aParms.GetACSFile(), aParms.GetCharacter(), scale, aParms.GetInitialAnimation(), true); + CModelData mData(res); + return new MP1::CWarWasp(mgr.AllocateUniqueId(), name, info, xf, std::move(mData), pInfo, flavor, collider, + damageInfo1, actorParms, weaponDesc, damageInfo2, particle, w1); } -CEntity* ScriptLoader::LoadSpacePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 34, "SpacePirate")) - return nullptr; - SScaledActorHead head = LoadScaledActorHead(in, mgr); - std::pair verifyPair = CPatternedInfo::HasCorrectParameterCount(in); - if (!verifyPair.first) - return nullptr; +CEntity* ScriptLoader::LoadSpacePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 34, "SpacePirate")) + return nullptr; + SScaledActorHead head = LoadScaledActorHead(in, mgr); + std::pair verifyPair = CPatternedInfo::HasCorrectParameterCount(in); + if (!verifyPair.first) + return nullptr; - CPatternedInfo pInfo(in, verifyPair.second); - CActorParameters aParams = LoadActorParameters(in); - CAnimationParameters& animParms = pInfo.GetAnimationParameters(); + CPatternedInfo pInfo(in, verifyPair.second); + CActorParameters aParams = LoadActorParameters(in); + CAnimationParameters& animParms = pInfo.GetAnimationParameters(); - if (g_ResFactory->GetResourceTypeById(animParms.GetACSFile()) != SBIG('ANCS')) - return nullptr; + if (g_ResFactory->GetResourceTypeById(animParms.GetACSFile()) != SBIG('ANCS')) + return nullptr; - if (animParms.GetCharacter() == 0) - { - Log.report(logvisor::Warning, - "SpacePirate <%s> has AnimationInformation property with invalid character selected", - head.x0_name.c_str()); - animParms.SetCharacter(2); - } + if (animParms.GetCharacter() == 0) { + Log.report(logvisor::Warning, "SpacePirate <%s> has AnimationInformation property with invalid character selected", + head.x0_name.c_str()); + animParms.SetCharacter(2); + } - CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), head.x40_scale, - animParms.GetInitialAnimation(), true)); + CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), head.x40_scale, + animParms.GetInitialAnimation(), true)); - return new MP1::CSpacePirate(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(mData), - aParams, pInfo, in, propCount); + return new MP1::CSpacePirate(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(mData), + aParams, pInfo, in, propCount); } -CEntity* ScriptLoader::LoadFlyingPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 35, "FlyingPirate")) - return nullptr; +CEntity* ScriptLoader::LoadFlyingPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 35, "FlyingPirate")) + return nullptr; - SScaledActorHead actHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (pair.first) - return nullptr; + SScaledActorHead actHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (pair.first) + return nullptr; - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); - if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) - return nullptr; + if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) + return nullptr; - const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); - CModelData mData( - CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), actHead.x40_scale, animParms.GetInitialAnimation(), - true)); + const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); + CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), actHead.x40_scale, + animParms.GetInitialAnimation(), true)); - return new MP1::CFlyingPirate(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, - std::move(mData), actParms, pInfo, in, propCount); + return new MP1::CFlyingPirate(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData), + actParms, pInfo, in, propCount); } -CEntity* ScriptLoader::LoadElitePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 41, "ElitePirate")) - return nullptr; +CEntity* ScriptLoader::LoadElitePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 41, "ElitePirate")) + return nullptr; - SScaledActorHead actHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; + SScaledActorHead actHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - MP1::CElitePirateData elitePirateData(in, propCount); + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + MP1::CElitePirateData elitePirateData(in, propCount); - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - - return new MP1::CElitePirate(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData), - pInfo, actParms, elitePirateData); + return new MP1::CElitePirate(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData), + pInfo, actParms, elitePirateData); } -CEntity* ScriptLoader::LoadMetroidBeta(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 23, "MetroidBeta")) - return nullptr; +CEntity* ScriptLoader::LoadMetroidBeta(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 23, "MetroidBeta")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - zeus::CTransform xf = LoadEditorTransform(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; + std::string name = mgr.HashInstanceName(in); + zeus::CTransform xf = LoadEditorTransform(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - MP1::CMetroidBetaData metData(in); - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + MP1::CMetroidBetaData metData(in); + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; - const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); - CModelData mData( - CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); + const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); + CModelData mData( + CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); - return new MP1::CMetroidBeta(mgr.AllocateUniqueId(), name, info, xf, std::move(mData), pInfo, actParms, metData); + return new MP1::CMetroidBeta(mgr.AllocateUniqueId(), name, info, xf, std::move(mData), pInfo, actParms, metData); } -CEntity* ScriptLoader::LoadChozoGhost(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 32, "ChozoGhost")) - return nullptr; +CEntity* ScriptLoader::LoadChozoGhost(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 32, "ChozoGhost")) + return nullptr; - SScaledActorHead actorHead = LoadScaledActorHead(in, mgr); + SScaledActorHead actorHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; + if (!pair.first) + return nullptr; - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - CAssetId wpsc1(in); - CDamageInfo dInfo1(in); - CAssetId wpsc2(in); - CDamageInfo dInfo2(in); - MP1::CChozoGhost::CBehaveChance behaveChance1(in); - MP1::CChozoGhost::CBehaveChance behaveChance2(in); - MP1::CChozoGhost::CBehaveChance behaveChance3(in); - s16 sId1 = CSfxManager::TranslateSFXID(in.readUint32Big()); - float f5 = in.readFloatBig(); - s16 sId2 = CSfxManager::TranslateSFXID(in.readUint32Big()); - s16 sId3 = CSfxManager::TranslateSFXID(in.readUint32Big()); - u32 w1 = in.readUint32Big(); - float f6 = in.readFloatBig(); - u32 w2 = in.readUint32Big(); - float f7 = in.readFloatBig(); - CAssetId partId(in); - s16 sId4 = CSfxManager::TranslateSFXID(in.readUint32Big()); - float f8 = in.readFloatBig(); - float f9 = in.readFloatBig(); - u32 w3 = in.readUint32Big(); - u32 w4 = in.readUint32Big(); + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + CAssetId wpsc1(in); + CDamageInfo dInfo1(in); + CAssetId wpsc2(in); + CDamageInfo dInfo2(in); + MP1::CChozoGhost::CBehaveChance behaveChance1(in); + MP1::CChozoGhost::CBehaveChance behaveChance2(in); + MP1::CChozoGhost::CBehaveChance behaveChance3(in); + s16 sId1 = CSfxManager::TranslateSFXID(in.readUint32Big()); + float f5 = in.readFloatBig(); + s16 sId2 = CSfxManager::TranslateSFXID(in.readUint32Big()); + s16 sId3 = CSfxManager::TranslateSFXID(in.readUint32Big()); + u32 w1 = in.readUint32Big(); + float f6 = in.readFloatBig(); + u32 w2 = in.readUint32Big(); + float f7 = in.readFloatBig(); + CAssetId partId(in); + s16 sId4 = CSfxManager::TranslateSFXID(in.readUint32Big()); + float f8 = in.readFloatBig(); + float f9 = in.readFloatBig(); + u32 w3 = in.readUint32Big(); + u32 w4 = in.readUint32Big(); - const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); - if (g_ResFactory->GetResourceTypeById(animParms.GetACSFile()) != SBIG('ANCS')) - return nullptr; + const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); + if (g_ResFactory->GetResourceTypeById(animParms.GetACSFile()) != SBIG('ANCS')) + return nullptr; - CModelData mData(CAnimRes(animParms.GetACSFile(), 0, actorHead.x40_scale, animParms.GetInitialAnimation(), true)); + CModelData mData(CAnimRes(animParms.GetACSFile(), 0, actorHead.x40_scale, animParms.GetInitialAnimation(), true)); - return new MP1::CChozoGhost(mgr.AllocateUniqueId(), actorHead.x0_name, info, actorHead.x10_transform, - std::move(mData), actParms, pInfo, f1, f2, f3, f4, wpsc1, dInfo1, wpsc2, dInfo2, - behaveChance1, behaveChance2, behaveChance3, sId1, f5, sId2, sId3, w1, f6, w2, f7, - partId, sId4, f8, f9, w3, w4); + return new MP1::CChozoGhost(mgr.AllocateUniqueId(), actorHead.x0_name, info, actorHead.x10_transform, + std::move(mData), actParms, pInfo, f1, f2, f3, f4, wpsc1, dInfo1, wpsc2, dInfo2, + behaveChance1, behaveChance2, behaveChance3, sId1, f5, sId2, sId3, w1, f6, w2, f7, partId, + sId4, f8, f9, w3, w4); } -CEntity* ScriptLoader::LoadCoverPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 9, "CoverPoint")) - return nullptr; +CEntity* ScriptLoader::LoadCoverPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 9, "CoverPoint")) + return nullptr; - SActorHead head = LoadActorHead(in, mgr); - bool active = in.readBool(); - u32 flags = in.readUint32Big(); - bool crouch = in.readBool(); - float horizontalAngle = in.readFloatBig(); - float verticalAngle = in.readFloatBig(); - float coverTime = in.readFloatBig(); + SActorHead head = LoadActorHead(in, mgr); + bool active = in.readBool(); + u32 flags = in.readUint32Big(); + bool crouch = in.readBool(); + float horizontalAngle = in.readFloatBig(); + float verticalAngle = in.readFloatBig(); + float coverTime = in.readFloatBig(); - return new CScriptCoverPoint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, flags, crouch, - horizontalAngle, verticalAngle, coverTime); + return new CScriptCoverPoint(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, active, flags, crouch, + horizontalAngle, verticalAngle, coverTime); } CEntity* ScriptLoader::LoadSpiderBallWaypoint(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 5, "SpiderBallWaypoint")) - return nullptr; - - SActorHead actHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - u32 w1 = in.readUint32Big(); - - return new CScriptSpiderBallWaypoint(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, active, - w1); -} - -CEntity* ScriptLoader::LoadBloodFlower(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 18, "BloodFlower")) - return nullptr; - - SScaledActorHead actHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - CAssetId partId1(in); - CAssetId wpsc1(in); - CAssetId wpsc2(in); - CDamageInfo dInfo1(in); - CDamageInfo dInfo2(in); - CDamageInfo dInfo3(in); - CAssetId partId2(in); - CAssetId partId3(in); - CAssetId partId4(in); - float f1 = in.readFloatBig(); - CAssetId partId5(in); - u32 soundId = in.readUint32Big(); - - if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) - return nullptr; - - - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - - return new MP1::CBloodFlower(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData), - pInfo, partId1, wpsc1, actParms, wpsc2, dInfo1, dInfo2, dInfo3, partId2, partId3, - partId4, f1, partId5, soundId); -} - -CEntity* ScriptLoader::LoadFlickerBat(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 10, "FlickerBat")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); - zeus::CTransform xf = LoadEditorTransform(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - bool b1 = in.readBool(); - bool b2 = in.readBool(); - bool b3 = in.readBool(); - - if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) - return nullptr; - - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - return new MP1::CFlickerBat(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, - CPatterned::EColliderType(b1), b2, actParms, b3); -} - -CEntity* ScriptLoader::LoadPathCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (propCount > 15) - { - Log.report(logvisor::Warning, "Too many props (%d > 15) for PathCamera entity", propCount); - return nullptr; - } - - SActorHead aHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - u32 flags = LoadParameterFlags(in); - float lengthExtent = in.readFloatBig(); - float filterMag = in.readFloatBig(); - float filterProportion = in.readFloatBig(); - CPathCamera::EInitialSplinePosition initPos = CPathCamera::EInitialSplinePosition(in.readUint32Big()); - float minEaseDist = in.readFloatBig(); - float maxEaseDist = in.readFloatBig(); - - return new CPathCamera(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, lengthExtent, - filterMag, filterProportion, minEaseDist, maxEaseDist, flags, initPos); -} - -CEntity* ScriptLoader::LoadGrapplePoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 5, "GrapplePoint")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CTransform grappleXf = LoadEditorTransform(in); - bool active = in.readBool(); - CGrappleParameters parameters = LoadGrappleParameters(in); - return new CScriptGrapplePoint(mgr.AllocateUniqueId(), name, info, grappleXf, active, parameters); -} - -CEntity* ScriptLoader::LoadPuddleSpore(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 16, "PuddleSpore")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); - zeus::CTransform xf = LoadEditorTransform(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 5, "SpiderBallWaypoint")) return nullptr; + SActorHead actHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + u32 w1 = in.readUint32Big(); + + return new CScriptSpiderBallWaypoint(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, active, + w1); +} + +CEntity* ScriptLoader::LoadBloodFlower(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 18, "BloodFlower")) + return nullptr; + + SScaledActorHead actHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; + + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + CAssetId partId1(in); + CAssetId wpsc1(in); + CAssetId wpsc2(in); + CDamageInfo dInfo1(in); + CDamageInfo dInfo2(in); + CDamageInfo dInfo3(in); + CAssetId partId2(in); + CAssetId partId3(in); + CAssetId partId4(in); + float f1 = in.readFloatBig(); + CAssetId partId5(in); + u32 soundId = in.readUint32Big(); + + if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) + return nullptr; + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + + return new MP1::CBloodFlower(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData), + pInfo, partId1, wpsc1, actParms, wpsc2, dInfo1, dInfo2, dInfo3, partId2, partId3, + partId4, f1, partId5, soundId); +} + +CEntity* ScriptLoader::LoadFlickerBat(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 10, "FlickerBat")) + return nullptr; + + std::string name = mgr.HashInstanceName(in); + CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); + zeus::CTransform xf = LoadEditorTransform(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; + + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + bool b1 = in.readBool(); + bool b2 = in.readBool(); + bool b3 = in.readBool(); + + if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) + return nullptr; + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + return new MP1::CFlickerBat(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, + CPatterned::EColliderType(b1), b2, actParms, b3); +} + +CEntity* ScriptLoader::LoadPathCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (propCount > 15) { + Log.report(logvisor::Warning, "Too many props (%d > 15) for PathCamera entity", propCount); + return nullptr; + } + + SActorHead aHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + u32 flags = LoadParameterFlags(in); + float lengthExtent = in.readFloatBig(); + float filterMag = in.readFloatBig(); + float filterProportion = in.readFloatBig(); + CPathCamera::EInitialSplinePosition initPos = CPathCamera::EInitialSplinePosition(in.readUint32Big()); + float minEaseDist = in.readFloatBig(); + float maxEaseDist = in.readFloatBig(); + + return new CPathCamera(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, lengthExtent, + filterMag, filterProportion, minEaseDist, maxEaseDist, flags, initPos); +} + +CEntity* ScriptLoader::LoadGrapplePoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 5, "GrapplePoint")) + return nullptr; + + std::string name = mgr.HashInstanceName(in); + zeus::CTransform grappleXf = LoadEditorTransform(in); + bool active = in.readBool(); + CGrappleParameters parameters = LoadGrappleParameters(in); + return new CScriptGrapplePoint(mgr.AllocateUniqueId(), name, info, grappleXf, active, parameters); +} + +CEntity* ScriptLoader::LoadPuddleSpore(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 16, "PuddleSpore")) + return nullptr; + + std::string name = mgr.HashInstanceName(in); + CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); + zeus::CTransform xf = LoadEditorTransform(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; + + CPatternedInfo pInfo(in, pair.second); + + return nullptr; } CEntity* ScriptLoader::LoadDebugCameraWaypoint(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "DebugCameraWaypoint")) - return nullptr; + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "DebugCameraWaypoint")) + return nullptr; - SActorHead actHead = LoadActorHead(in, mgr); - u32 w1 = in.readUint32Big(); - return new CScriptDebugCameraWaypoint(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, w1); + SActorHead actHead = LoadActorHead(in, mgr); + u32 w1 = in.readUint32Big(); + return new CScriptDebugCameraWaypoint(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, w1); } CEntity* ScriptLoader::LoadSpiderBallAttractionSurface(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 5, "SpiderBallAttractionSurface")) - return nullptr; - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - bool active = in.readBool(); - return new CScriptSpiderBallAttractionSurface(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, - aHead.x40_scale, active); -} - -CEntity* ScriptLoader::LoadPuddleToadGamma(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 17, "PuddleToadGamma")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); - zeus::CTransform xf = LoadEditorTransform(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); - float f4 = in.readFloatBig(); - float f5 = in.readFloatBig(); - float f6 = in.readFloatBig(); - CDamageInfo dInfo1(in); - CDamageInfo dInfo2(in); - CAssetId collisionData(in); - const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); - CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, - animParms.GetInitialAnimation(), true)); - return new MP1::CPuddleToadGamma(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, actParms, - f1, f2, f3, vec, f4, f5, f6, dInfo1, dInfo2, collisionData); -} - -CEntity* ScriptLoader::LoadDistanceFog(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 8, "DistanceFog")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - u32 mode = in.readUint32Big(); - zeus::CColor color; - color.readRGBABig(in); - zeus::CVector2f range; - range.readBig(in); - float colorDelta = in.readFloatBig(); - zeus::CVector2f rangeDelta; - rangeDelta.readBig(in); - bool expl = in.readBool(); - bool active = in.readBool(); - ERglFogMode realMode; - - if (mode == 0) - realMode = ERglFogMode::None; - else if (mode == 1) - realMode = ERglFogMode::PerspLin; - else if (mode == 2) - realMode = ERglFogMode::PerspExp; - else if (mode == 3) - realMode = ERglFogMode::PerspExp2; - else if (mode == 4) - realMode = ERglFogMode::PerspRevExp; - else if (mode == 5) - realMode = ERglFogMode::PerspRevExp2; - - return new CScriptDistanceFog(mgr.AllocateUniqueId(), name, info, realMode, color, range, colorDelta, rangeDelta, - expl, active, 0.f, 0.f, 0.f, 0.f); -} - -CEntity* ScriptLoader::LoadFireFlea(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 9, "FireFlea")) - return nullptr; - - SScaledActorHead acthead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - in.readBool(); - in.readBool(); - float f1 = in.readFloatBig(); - - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; - - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - acthead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - - return new MP1::CFireFlea(mgr.AllocateUniqueId(), acthead.x0_name, info, acthead.x10_transform, std::move(mData), - actParms, pInfo, f1); -} - -CEntity* ScriptLoader::LoadMetaree(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 12, "Metaree")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CTransform xf = LoadEditorTransform(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - CActorParameters aParms = LoadActorParameters(in); - CDamageInfo dInfo(in); - float f1 = in.readFloatBig(); - zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - - if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) - return nullptr; - - float f4 = in.readFloatBig(); - - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - return new MP1::CMetaree(mgr.AllocateUniqueId(), name, CPatterned::EFlavorType::Zero, info, xf, std::move(mData), - pInfo, dInfo, f1, vec, f2, EBodyType::Invalid, f3, f4, aParms); -} - -CEntity* ScriptLoader::LoadDockAreaChange(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 3, "DockAreaChange")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - s32 w1 = in.readInt32Big(); - bool active = in.readBool(); - - return new CScriptDockAreaChange(mgr.AllocateUniqueId(), name, info, w1, active); -} - -CEntity* ScriptLoader::LoadActorRotate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 6, "ActorRotate")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f rotation = zeus::CVector3f::ReadBig(in); - float scale = in.readFloatBig(); - bool updateActors = in.readBool(); - bool b2 = in.readBool(); - bool active = in.readBool(); - - return new CScriptActorRotate(mgr.AllocateUniqueId(), name, info, rotation, scale, updateActors, b2, active); -} - -CEntity* ScriptLoader::LoadSpecialFunction(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 15, "SpecialFunction")) - return nullptr; - - SActorHead head = LoadActorHead(in, mgr); - CScriptSpecialFunction::ESpecialFunction specialFunction = - CScriptSpecialFunction::ESpecialFunction(in.readUint32Big()); - std::string str = in.readString(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - u32 w2 = in.readUint32Big(); - u32 w3 = in.readUint32Big(); - CPlayerState::EItemType w4 = CPlayerState::EItemType(in.readUint32Big()); - bool active1 = in.readBool(); - float f4 = in.readFloatBig(); - s16 w5 = in.readUint32Big() & 0xFFFF; - s16 w6 = in.readUint32Big() & 0xFFFF; - s16 w7 = in.readUint32Big() & 0xFFFF; - if (specialFunction == CScriptSpecialFunction::ESpecialFunction::FogVolume || - specialFunction == CScriptSpecialFunction::ESpecialFunction::RadialDamage) - return nullptr; - - return new CScriptSpecialFunction(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, specialFunction, - str, f1, f2, f3, f4, zeus::CVector3f::skZero, zeus::CColor::skBlack, active1, - CDamageInfo(), w2, w3, w4, w5, w6, w7); -} - -CEntity* ScriptLoader::LoadSpankWeed(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 11, "SpankWeed")) - return nullptr; - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - in.readBool(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - - const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); - if (!animParms.GetACSFile().IsValid()) - return nullptr; - - CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), aHead.x40_scale, - animParms.GetInitialAnimation(), true)); - return new MP1::CSpankWeed(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), - actParms, pInfo, f1, f2, f3, f4); -} - -CEntity* ScriptLoader::LoadParasite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 25, "Parasite")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); - zeus::CTransform xf = LoadEditorTransform(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - - std::pair pcount = CPatternedInfo::HasCorrectParameterCount(in); - if (!pcount.first) - return nullptr; - - CPatternedInfo pInfo(in, pcount.second); - CActorParameters aParms = LoadActorParameters(in); - float maxTelegraphReactDist = in.readFloatBig(); - float advanceWpRadius = in.readFloatBig(); - float f3 = in.readFloatBig(); - float alignAngVel = in.readFloatBig(); - float f5 = in.readFloatBig(); - float stuckTimeThreshold = in.readFloatBig(); - float collisionCloseMargin = in.readFloatBig(); - float parasiteSearchRadius = in.readFloatBig(); - float parasiteSeparationDist = in.readFloatBig(); - float parasiteSeparationWeight = in.readFloatBig(); - float parasiteAlignmentWeight = in.readFloatBig(); - float parasiteCohesionWeight = in.readFloatBig(); - float destinationSeekWeight = in.readFloatBig(); - float forwardMoveWeight = in.readFloatBig(); - float playerSeparationDist = in.readFloatBig(); - float playerSeparationWeight = in.readFloatBig(); - float playerObstructionMinDist = in.readFloatBig(); - bool disableMove = in.readBool(); - - if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) - return nullptr; - const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); - CModelData mData( - CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); - return new MP1::CParasite(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, - EBodyType::WallWalker, maxTelegraphReactDist, advanceWpRadius, f3, alignAngVel, f5, - stuckTimeThreshold, collisionCloseMargin, parasiteSearchRadius, parasiteSeparationDist, - parasiteSeparationWeight, parasiteAlignmentWeight, parasiteCohesionWeight, - destinationSeekWeight, forwardMoveWeight, playerSeparationDist, playerSeparationWeight, - playerObstructionMinDist, 0.f, disableMove, CWallWalker::EWalkerType::Parasite, - CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(), - -1, -1, -1, {}, {}, 0.f, aParms); -} - -CEntity* ScriptLoader::LoadPlayerHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 6, "PlayerHint")) - return nullptr; - - SActorHead aHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - u32 w2 = LoadParameterFlags(in); - u32 w1 = in.readUint32Big(); - - return new CScriptPlayerHint(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, w1, w2); -} - -CEntity* ScriptLoader::LoadRipper(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 5, "SpiderBallAttractionSurface")) return nullptr; + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + bool active = in.readBool(); + return new CScriptSpiderBallAttractionSurface(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, + aHead.x40_scale, active); } -CEntity* ScriptLoader::LoadPickupGenerator(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "PickupGenerator")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f pos = zeus::CVector3f::ReadBig(in); - bool active = in.readBool(); - float f1 = in.readFloatBig(); - return new CScriptPickupGenerator(mgr.AllocateUniqueId(), name, info, pos, f1, active); -} - -CEntity* ScriptLoader::LoadAIKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ +CEntity* ScriptLoader::LoadPuddleToadGamma(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 17, "PuddleToadGamma")) return nullptr; -} -CEntity* ScriptLoader::LoadPointOfInterest(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 6, "PointOfInterest")) - return nullptr; - - SActorHead aHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - CScannableParameters sParms = LoadScannableParameters(in); - float f1 = in.readFloatBig(); - - return new CScriptPointOfInterest(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, sParms, - f1); -} - -CEntity* ScriptLoader::LoadDrone(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ + std::string name = mgr.HashInstanceName(in); + CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); + zeus::CTransform xf = LoadEditorTransform(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) return nullptr; + + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); + float f4 = in.readFloatBig(); + float f5 = in.readFloatBig(); + float f6 = in.readFloatBig(); + CDamageInfo dInfo1(in); + CDamageInfo dInfo2(in); + CAssetId collisionData(in); + const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); + CModelData mData( + CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); + return new MP1::CPuddleToadGamma(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, actParms, + f1, f2, f3, vec, f4, f5, f6, dInfo1, dInfo2, collisionData); } -CEntity* ScriptLoader::LoadMetroidAlpha(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ +CEntity* ScriptLoader::LoadDistanceFog(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 8, "DistanceFog")) return nullptr; + + std::string name = mgr.HashInstanceName(in); + u32 mode = in.readUint32Big(); + zeus::CColor color; + color.readRGBABig(in); + zeus::CVector2f range; + range.readBig(in); + float colorDelta = in.readFloatBig(); + zeus::CVector2f rangeDelta; + rangeDelta.readBig(in); + bool expl = in.readBool(); + bool active = in.readBool(); + ERglFogMode realMode; + + if (mode == 0) + realMode = ERglFogMode::None; + else if (mode == 1) + realMode = ERglFogMode::PerspLin; + else if (mode == 2) + realMode = ERglFogMode::PerspExp; + else if (mode == 3) + realMode = ERglFogMode::PerspExp2; + else if (mode == 4) + realMode = ERglFogMode::PerspRevExp; + else if (mode == 5) + realMode = ERglFogMode::PerspRevExp2; + + return new CScriptDistanceFog(mgr.AllocateUniqueId(), name, info, realMode, color, range, colorDelta, rangeDelta, + expl, active, 0.f, 0.f, 0.f, 0.f); } -CEntity* ScriptLoader::LoadDebrisExtended(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 39, "DebrisExtended")) - return nullptr; - - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - - float linConeAngle = in.readFloatBig(); - float linMinMag = in.readFloatBig(); - float linMaxMag = in.readFloatBig(); - float angMinMag = in.readFloatBig(); - float angMaxMag = in.readFloatBig(); - float minDuration = in.readFloatBig(); - float maxDuration = in.readFloatBig(); - float colorInT = in.readFloatBig(); - float colorOutT = in.readFloatBig(); - - zeus::CColor color = zeus::CColor::ReadRGBABig(in); - zeus::CColor endsColor = zeus::CColor::ReadRGBABig(in); - - float scaleOutT = in.readFloatBig(); - - zeus::CVector3f endScale = zeus::CVector3f::ReadBig(in); - - float restitution = in.readFloatBig(); - float downwardSpeed = in.readFloatBig(); - - zeus::CVector3f localOffset = zeus::CVector3f::ReadBig(in); - - CAssetId model = in.readUint32Big(); - - CActorParameters aParam = LoadActorParameters(in); - - CAssetId particle1 = in.readUint32Big(); - zeus::CVector3f particle1Scale = zeus::CVector3f::ReadBig(in); - bool particle1GlobalTranslation = in.readBool(); - bool deferDeleteTillParticle1Done = in.readBool(); - CScriptDebris::EOrientationType particle1Or = CScriptDebris::EOrientationType(in.readUint32Big()); - - CAssetId particle2 = in.readUint32Big(); - zeus::CVector3f particle2Scale = zeus::CVector3f::ReadBig(in); - bool particle2GlobalTranslation = in.readBool(); - bool deferDeleteTillParticle2Done = in.readBool(); - CScriptDebris::EOrientationType particle2Or = CScriptDebris::EOrientationType(in.readUint32Big()); - - CAssetId particle3 = in.readUint32Big(); - zeus::CVector3f particle3Scale = zeus::CVector3f::ReadBig(in); - CScriptDebris::EOrientationType particle3Or = CScriptDebris::EOrientationType(in.readUint32Big()); - - bool solid = in.readBool(); - bool dieOnProjectile = in.readBool(); - bool noBounce = in.readBool(); - bool active = in.readBool(); - - CModelData modelData; - if (g_ResFactory->GetResourceTypeById(model)) - modelData = CModelData(CStaticRes(model, aHead.x40_scale)); - - return new CScriptDebris(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(modelData), - aParam, linConeAngle, linMinMag, linMaxMag, angMinMag, angMaxMag, minDuration, maxDuration, - colorInT, colorOutT, color, endsColor, scaleOutT, aHead.x40_scale, endScale, restitution, - downwardSpeed, localOffset, particle1, particle1Scale, particle1GlobalTranslation, - deferDeleteTillParticle1Done, particle1Or, particle2, particle2Scale, - particle2GlobalTranslation, deferDeleteTillParticle2Done, particle2Or, particle3, - particle3Scale, particle3Or, solid, dieOnProjectile, noBounce, active); -} - -CEntity* ScriptLoader::LoadSteam(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 11, "Steam")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - - zeus::CVector3f v1 = zeus::CVector3f::ReadBig(in); - zeus::CVector3f v2 = zeus::CVector3f::ReadBig(in); - - CDamageInfo dInfo(in); - - zeus::CVector3f v3 = zeus::CVector3f::ReadBig(in); - - ETriggerFlags - w1 = ETriggerFlags(in.readUint32Big()); - bool b1 = in.readBool(); - u32 w2 = in.readUint32Big(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - bool b2 = in.readBool(); - - zeus::CAABox aabb(-v2 * 0.5f, v2 * 0.5f); - - return new CScriptSteam(mgr.AllocateUniqueId(), name, info, v1, aabb, dInfo, v3, w1, b1, w2, f1, f2, f3, f4, b2); -} - -CEntity* ScriptLoader::LoadRipple(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "Ripple")) - return nullptr; - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f center = zeus::CVector3f::ReadBig(in); - bool active = in.readBool(); - float mag = in.readFloatBig(); - return new CScriptRipple(mgr.AllocateUniqueId(), name, info, center, active, mag); -} - -CEntity* ScriptLoader::LoadBallTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 9, "BallTrigger")) - return nullptr; - - std::string name = in.readString(); - zeus::CVector3f pos = zeus::CVector3f::ReadBig(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - - bool b1 = in.readBool(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); - bool b2 = in.readBool(); - return new CScriptBallTrigger(mgr.AllocateUniqueId(), name, info, pos, scale, b1, f1, f2, f3, vec, b2); -} - -CEntity* ScriptLoader::LoadTargetingPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "TargetingPoint")) - return nullptr; - - SActorHead aHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - - return new CScriptTargetingPoint(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active); -} - -CEntity* ScriptLoader::LoadEMPulse(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 12, "EMPulse")) - return nullptr; - - SActorHead actorHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - float f5 = in.readFloatBig(); - float f6 = in.readFloatBig(); - float f7 = in.readFloatBig(); - CAssetId particleId(in); - - return new CScriptEMPulse(mgr.AllocateUniqueId(), actorHead.x0_name, info, actorHead.x10_transform, active, f1, f2, - f3, f4, f5, f6, f7, particleId); -} - -CEntity* ScriptLoader::LoadIceSheegoth(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ +CEntity* ScriptLoader::LoadFireFlea(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 9, "FireFlea")) return nullptr; -} -CEntity* ScriptLoader::LoadPlayerActor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 19, "PlayerActor")) - return nullptr; - - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - zeus::CVector3f extents = zeus::CVector3f::ReadBig(in); - zeus::CVector3f offset = zeus::CVector3f::ReadBig(in); - float mass = in.readFloatBig(); - float zMomentum = in.readFloatBig(); - CHealthInfo hInfo(in); - CDamageVulnerability dVuln(in); - in.readUint32Big(); - CAnimationParameters animParms = LoadAnimationParameters(in); - CActorParameters actParms = LoadActorParameters(in); - bool loop = in.readBool(); - bool snow = in.readBool(); - bool solid = in.readBool(); - bool active = in.readBool(); - u32 flags = LoadParameterFlags(in); - CPlayerState::EBeamId beam = CPlayerState::EBeamId(in.readUint32Big() - 1); - - FourCC fcc = g_ResFactory->GetResourceTypeById(animParms.GetACSFile()); - if (!fcc || fcc != SBIG('ANCS')) - return nullptr; - - zeus::CAABox aabox = GetCollisionBox(mgr, info.GetAreaId(), extents, offset); - CMaterialList list; - if (snow) - list.Add(EMaterialTypes::Snow); - - if (solid) - list.Add(EMaterialTypes::Solid); - - if ((extents.x() < 0.f || extents.y() < 0.f || extents.z() < 0.f) || extents.isZero()) - aabox = zeus::CAABox(-.5f, 0.5f); - - return new CScriptPlayerActor(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, - CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), aHead.x40_scale, - animParms.GetInitialAnimation(), loop), - CModelData::CModelDataNull(), aabox, true, list, mass, zMomentum, hInfo, dVuln, - actParms, loop, active, flags, beam); -} - -CEntity* ScriptLoader::LoadFlaahgra(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ + SScaledActorHead acthead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) return nullptr; + + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + in.readBool(); + in.readBool(); + float f1 = in.readFloatBig(); + + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + acthead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + + return new MP1::CFireFlea(mgr.AllocateUniqueId(), acthead.x0_name, info, acthead.x10_transform, std::move(mData), + actParms, pInfo, f1); } -CEntity* ScriptLoader::LoadAreaAttributes(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 9, "AreaAttributes")) - return nullptr; +CEntity* ScriptLoader::LoadMetaree(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 12, "Metaree")) + return nullptr; - bool load = in.readUint32Big() != 0; - if (!load) - return nullptr; + std::string name = mgr.HashInstanceName(in); + zeus::CTransform xf = LoadEditorTransform(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - bool showSkybox = in.readBool(); - EEnvFxType fxType = EEnvFxType(in.readUint32Big()); - float envFxDensity = in.readFloatBig(); - float thermalHeat = in.readFloatBig(); - float xrayFogDistance = in.readFloatBig(); - float worldLightingLevel = in.readFloatBig(); - CAssetId skybox = in.readUint32Big(); - EPhazonType phazonType = EPhazonType(in.readUint32Big()); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; - return new CScriptAreaAttributes(mgr.AllocateUniqueId(), info, showSkybox, fxType, envFxDensity, thermalHeat, - xrayFogDistance, worldLightingLevel, skybox, phazonType); + CPatternedInfo pInfo(in, pair.second); + CActorParameters aParms = LoadActorParameters(in); + CDamageInfo dInfo(in); + float f1 = in.readFloatBig(); + zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + + if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) + return nullptr; + + float f4 = in.readFloatBig(); + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + return new MP1::CMetaree(mgr.AllocateUniqueId(), name, CPatterned::EFlavorType::Zero, info, xf, std::move(mData), + pInfo, dInfo, f1, vec, f2, EBodyType::Invalid, f3, f4, aParms); } -CEntity* ScriptLoader::LoadFishCloud(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 36, "FishCloud")) - return nullptr; - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - bool b1 = in.readBool(); - CAssetId w1(in); - CAnimationParameters animParms(in); - u32 w5 = u32(in.readFloatBig()); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - float f5 = in.readFloatBig(); - float f6 = in.readFloatBig(); - float f7 = in.readFloatBig(); - float f8 = in.readFloatBig(); - float f9 = in.readFloatBig(); - float f10 = in.readFloatBig(); - float f11 = in.readFloatBig(); - float f12 = in.readFloatBig(); - float f13 = in.readFloatBig(); - u32 w6 = in.readUint32Big(); +CEntity* ScriptLoader::LoadDockAreaChange(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 3, "DockAreaChange")) + return nullptr; - if (!g_ResFactory->GetResourceTypeById(w1)) - return nullptr; + std::string name = mgr.HashInstanceName(in); + s32 w1 = in.readInt32Big(); + bool active = in.readBool(); - zeus::CColor col = zeus::CColor::ReadRGBABig(in); - bool b2 = in.readBool(); - float f14 = in.readFloatBig(); - CAssetId w7 = in.readUint32Big(); - u32 w8 = in.readUint32Big(); - CAssetId w9 = in.readUint32Big(); - u32 w10 = in.readUint32Big(); - CAssetId w11 = in.readUint32Big(); - u32 w12 = in.readUint32Big(); - CAssetId w13 = in.readUint32Big(); - u32 w14 = in.readUint32Big(); - u32 w15 = in.readUint32Big(); - bool b3 = in.readBool(); - bool b4 = in.readBool(); + return new CScriptDockAreaChange(mgr.AllocateUniqueId(), name, info, w1, active); +} - CModelData mData(CStaticRes(w1, zeus::CVector3f::skOne)); - CAnimRes animRes(animParms.GetACSFile(), animParms.GetCharacter(), zeus::CVector3f::skOne, - animParms.GetInitialAnimation(), true); - return new CFishCloud(mgr.AllocateUniqueId(), b1, aHead.x0_name, info, aHead.x40_scale, aHead.x10_transform, - std::move(mData), animRes, w5, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, w6, - col, b2, f14, w7, w8, w9, w10, w11, w12, w13, w14, w15, b3, b4); +CEntity* ScriptLoader::LoadActorRotate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 6, "ActorRotate")) + return nullptr; + + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f rotation = zeus::CVector3f::ReadBig(in); + float scale = in.readFloatBig(); + bool updateActors = in.readBool(); + bool b2 = in.readBool(); + bool active = in.readBool(); + + return new CScriptActorRotate(mgr.AllocateUniqueId(), name, info, rotation, scale, updateActors, b2, active); +} + +CEntity* ScriptLoader::LoadSpecialFunction(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 15, "SpecialFunction")) + return nullptr; + + SActorHead head = LoadActorHead(in, mgr); + CScriptSpecialFunction::ESpecialFunction specialFunction = + CScriptSpecialFunction::ESpecialFunction(in.readUint32Big()); + std::string str = in.readString(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + u32 w2 = in.readUint32Big(); + u32 w3 = in.readUint32Big(); + CPlayerState::EItemType w4 = CPlayerState::EItemType(in.readUint32Big()); + bool active1 = in.readBool(); + float f4 = in.readFloatBig(); + s16 w5 = in.readUint32Big() & 0xFFFF; + s16 w6 = in.readUint32Big() & 0xFFFF; + s16 w7 = in.readUint32Big() & 0xFFFF; + if (specialFunction == CScriptSpecialFunction::ESpecialFunction::FogVolume || + specialFunction == CScriptSpecialFunction::ESpecialFunction::RadialDamage) + return nullptr; + + return new CScriptSpecialFunction(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, specialFunction, + str, f1, f2, f3, f4, zeus::CVector3f::skZero, zeus::CColor::skBlack, active1, + CDamageInfo(), w2, w3, w4, w5, w6, w7); +} + +CEntity* ScriptLoader::LoadSpankWeed(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 11, "SpankWeed")) + return nullptr; + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; + + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + in.readBool(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + + const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); + if (!animParms.GetACSFile().IsValid()) + return nullptr; + + CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), aHead.x40_scale, + animParms.GetInitialAnimation(), true)); + return new MP1::CSpankWeed(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), + actParms, pInfo, f1, f2, f3, f4); +} + +CEntity* ScriptLoader::LoadParasite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 25, "Parasite")) + return nullptr; + + std::string name = mgr.HashInstanceName(in); + CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); + zeus::CTransform xf = LoadEditorTransform(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + + std::pair pcount = CPatternedInfo::HasCorrectParameterCount(in); + if (!pcount.first) + return nullptr; + + CPatternedInfo pInfo(in, pcount.second); + CActorParameters aParms = LoadActorParameters(in); + float maxTelegraphReactDist = in.readFloatBig(); + float advanceWpRadius = in.readFloatBig(); + float f3 = in.readFloatBig(); + float alignAngVel = in.readFloatBig(); + float f5 = in.readFloatBig(); + float stuckTimeThreshold = in.readFloatBig(); + float collisionCloseMargin = in.readFloatBig(); + float parasiteSearchRadius = in.readFloatBig(); + float parasiteSeparationDist = in.readFloatBig(); + float parasiteSeparationWeight = in.readFloatBig(); + float parasiteAlignmentWeight = in.readFloatBig(); + float parasiteCohesionWeight = in.readFloatBig(); + float destinationSeekWeight = in.readFloatBig(); + float forwardMoveWeight = in.readFloatBig(); + float playerSeparationDist = in.readFloatBig(); + float playerSeparationWeight = in.readFloatBig(); + float playerObstructionMinDist = in.readFloatBig(); + bool disableMove = in.readBool(); + + if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) + return nullptr; + const CAnimationParameters& animParms = pInfo.GetAnimationParameters(); + CModelData mData( + CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); + return new MP1::CParasite(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, + EBodyType::WallWalker, maxTelegraphReactDist, advanceWpRadius, f3, alignAngVel, f5, + stuckTimeThreshold, collisionCloseMargin, parasiteSearchRadius, parasiteSeparationDist, + parasiteSeparationWeight, parasiteAlignmentWeight, parasiteCohesionWeight, + destinationSeekWeight, forwardMoveWeight, playerSeparationDist, playerSeparationWeight, + playerObstructionMinDist, 0.f, disableMove, CWallWalker::EWalkerType::Parasite, + CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(), -1, -1, -1, {}, {}, 0.f, aParms); +} + +CEntity* ScriptLoader::LoadPlayerHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 6, "PlayerHint")) + return nullptr; + + SActorHead aHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + u32 w2 = LoadParameterFlags(in); + u32 w1 = in.readUint32Big(); + + return new CScriptPlayerHint(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, w1, w2); +} + +CEntity* ScriptLoader::LoadRipper(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadPickupGenerator(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "PickupGenerator")) + return nullptr; + + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f pos = zeus::CVector3f::ReadBig(in); + bool active = in.readBool(); + float f1 = in.readFloatBig(); + return new CScriptPickupGenerator(mgr.AllocateUniqueId(), name, info, pos, f1, active); +} + +CEntity* ScriptLoader::LoadAIKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadPointOfInterest(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 6, "PointOfInterest")) + return nullptr; + + SActorHead aHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + CScannableParameters sParms = LoadScannableParameters(in); + float f1 = in.readFloatBig(); + + return new CScriptPointOfInterest(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, sParms, + f1); +} + +CEntity* ScriptLoader::LoadDrone(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadMetroidAlpha(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadDebrisExtended(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 39, "DebrisExtended")) + return nullptr; + + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + + float linConeAngle = in.readFloatBig(); + float linMinMag = in.readFloatBig(); + float linMaxMag = in.readFloatBig(); + float angMinMag = in.readFloatBig(); + float angMaxMag = in.readFloatBig(); + float minDuration = in.readFloatBig(); + float maxDuration = in.readFloatBig(); + float colorInT = in.readFloatBig(); + float colorOutT = in.readFloatBig(); + + zeus::CColor color = zeus::CColor::ReadRGBABig(in); + zeus::CColor endsColor = zeus::CColor::ReadRGBABig(in); + + float scaleOutT = in.readFloatBig(); + + zeus::CVector3f endScale = zeus::CVector3f::ReadBig(in); + + float restitution = in.readFloatBig(); + float downwardSpeed = in.readFloatBig(); + + zeus::CVector3f localOffset = zeus::CVector3f::ReadBig(in); + + CAssetId model = in.readUint32Big(); + + CActorParameters aParam = LoadActorParameters(in); + + CAssetId particle1 = in.readUint32Big(); + zeus::CVector3f particle1Scale = zeus::CVector3f::ReadBig(in); + bool particle1GlobalTranslation = in.readBool(); + bool deferDeleteTillParticle1Done = in.readBool(); + CScriptDebris::EOrientationType particle1Or = CScriptDebris::EOrientationType(in.readUint32Big()); + + CAssetId particle2 = in.readUint32Big(); + zeus::CVector3f particle2Scale = zeus::CVector3f::ReadBig(in); + bool particle2GlobalTranslation = in.readBool(); + bool deferDeleteTillParticle2Done = in.readBool(); + CScriptDebris::EOrientationType particle2Or = CScriptDebris::EOrientationType(in.readUint32Big()); + + CAssetId particle3 = in.readUint32Big(); + zeus::CVector3f particle3Scale = zeus::CVector3f::ReadBig(in); + CScriptDebris::EOrientationType particle3Or = CScriptDebris::EOrientationType(in.readUint32Big()); + + bool solid = in.readBool(); + bool dieOnProjectile = in.readBool(); + bool noBounce = in.readBool(); + bool active = in.readBool(); + + CModelData modelData; + if (g_ResFactory->GetResourceTypeById(model)) + modelData = CModelData(CStaticRes(model, aHead.x40_scale)); + + return new CScriptDebris(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(modelData), + aParam, linConeAngle, linMinMag, linMaxMag, angMinMag, angMaxMag, minDuration, maxDuration, + colorInT, colorOutT, color, endsColor, scaleOutT, aHead.x40_scale, endScale, restitution, + downwardSpeed, localOffset, particle1, particle1Scale, particle1GlobalTranslation, + deferDeleteTillParticle1Done, particle1Or, particle2, particle2Scale, + particle2GlobalTranslation, deferDeleteTillParticle2Done, particle2Or, particle3, + particle3Scale, particle3Or, solid, dieOnProjectile, noBounce, active); +} + +CEntity* ScriptLoader::LoadSteam(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 11, "Steam")) + return nullptr; + + std::string name = mgr.HashInstanceName(in); + + zeus::CVector3f v1 = zeus::CVector3f::ReadBig(in); + zeus::CVector3f v2 = zeus::CVector3f::ReadBig(in); + + CDamageInfo dInfo(in); + + zeus::CVector3f v3 = zeus::CVector3f::ReadBig(in); + + ETriggerFlags w1 = ETriggerFlags(in.readUint32Big()); + bool b1 = in.readBool(); + u32 w2 = in.readUint32Big(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + bool b2 = in.readBool(); + + zeus::CAABox aabb(-v2 * 0.5f, v2 * 0.5f); + + return new CScriptSteam(mgr.AllocateUniqueId(), name, info, v1, aabb, dInfo, v3, w1, b1, w2, f1, f2, f3, f4, b2); +} + +CEntity* ScriptLoader::LoadRipple(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "Ripple")) + return nullptr; + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f center = zeus::CVector3f::ReadBig(in); + bool active = in.readBool(); + float mag = in.readFloatBig(); + return new CScriptRipple(mgr.AllocateUniqueId(), name, info, center, active, mag); +} + +CEntity* ScriptLoader::LoadBallTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 9, "BallTrigger")) + return nullptr; + + std::string name = in.readString(); + zeus::CVector3f pos = zeus::CVector3f::ReadBig(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + + bool b1 = in.readBool(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); + bool b2 = in.readBool(); + return new CScriptBallTrigger(mgr.AllocateUniqueId(), name, info, pos, scale, b1, f1, f2, f3, vec, b2); +} + +CEntity* ScriptLoader::LoadTargetingPoint(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "TargetingPoint")) + return nullptr; + + SActorHead aHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + + return new CScriptTargetingPoint(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active); +} + +CEntity* ScriptLoader::LoadEMPulse(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 12, "EMPulse")) + return nullptr; + + SActorHead actorHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + float f5 = in.readFloatBig(); + float f6 = in.readFloatBig(); + float f7 = in.readFloatBig(); + CAssetId particleId(in); + + return new CScriptEMPulse(mgr.AllocateUniqueId(), actorHead.x0_name, info, actorHead.x10_transform, active, f1, f2, + f3, f4, f5, f6, f7, particleId); +} + +CEntity* ScriptLoader::LoadIceSheegoth(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadPlayerActor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 19, "PlayerActor")) + return nullptr; + + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + zeus::CVector3f extents = zeus::CVector3f::ReadBig(in); + zeus::CVector3f offset = zeus::CVector3f::ReadBig(in); + float mass = in.readFloatBig(); + float zMomentum = in.readFloatBig(); + CHealthInfo hInfo(in); + CDamageVulnerability dVuln(in); + in.readUint32Big(); + CAnimationParameters animParms = LoadAnimationParameters(in); + CActorParameters actParms = LoadActorParameters(in); + bool loop = in.readBool(); + bool snow = in.readBool(); + bool solid = in.readBool(); + bool active = in.readBool(); + u32 flags = LoadParameterFlags(in); + CPlayerState::EBeamId beam = CPlayerState::EBeamId(in.readUint32Big() - 1); + + FourCC fcc = g_ResFactory->GetResourceTypeById(animParms.GetACSFile()); + if (!fcc || fcc != SBIG('ANCS')) + return nullptr; + + zeus::CAABox aabox = GetCollisionBox(mgr, info.GetAreaId(), extents, offset); + CMaterialList list; + if (snow) + list.Add(EMaterialTypes::Snow); + + if (solid) + list.Add(EMaterialTypes::Solid); + + if ((extents.x() < 0.f || extents.y() < 0.f || extents.z() < 0.f) || extents.isZero()) + aabox = zeus::CAABox(-.5f, 0.5f); + + return new CScriptPlayerActor(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, + CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), aHead.x40_scale, + animParms.GetInitialAnimation(), loop), + CModelData::CModelDataNull(), aabox, true, list, mass, zMomentum, hInfo, dVuln, + actParms, loop, active, flags, beam); +} + +CEntity* ScriptLoader::LoadFlaahgra(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadAreaAttributes(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 9, "AreaAttributes")) + return nullptr; + + bool load = in.readUint32Big() != 0; + if (!load) + return nullptr; + + bool showSkybox = in.readBool(); + EEnvFxType fxType = EEnvFxType(in.readUint32Big()); + float envFxDensity = in.readFloatBig(); + float thermalHeat = in.readFloatBig(); + float xrayFogDistance = in.readFloatBig(); + float worldLightingLevel = in.readFloatBig(); + CAssetId skybox = in.readUint32Big(); + EPhazonType phazonType = EPhazonType(in.readUint32Big()); + + return new CScriptAreaAttributes(mgr.AllocateUniqueId(), info, showSkybox, fxType, envFxDensity, thermalHeat, + xrayFogDistance, worldLightingLevel, skybox, phazonType); +} + +CEntity* ScriptLoader::LoadFishCloud(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 36, "FishCloud")) + return nullptr; + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + bool b1 = in.readBool(); + CAssetId w1(in); + CAnimationParameters animParms(in); + u32 w5 = u32(in.readFloatBig()); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + float f5 = in.readFloatBig(); + float f6 = in.readFloatBig(); + float f7 = in.readFloatBig(); + float f8 = in.readFloatBig(); + float f9 = in.readFloatBig(); + float f10 = in.readFloatBig(); + float f11 = in.readFloatBig(); + float f12 = in.readFloatBig(); + float f13 = in.readFloatBig(); + u32 w6 = in.readUint32Big(); + + if (!g_ResFactory->GetResourceTypeById(w1)) + return nullptr; + + zeus::CColor col = zeus::CColor::ReadRGBABig(in); + bool b2 = in.readBool(); + float f14 = in.readFloatBig(); + CAssetId w7 = in.readUint32Big(); + u32 w8 = in.readUint32Big(); + CAssetId w9 = in.readUint32Big(); + u32 w10 = in.readUint32Big(); + CAssetId w11 = in.readUint32Big(); + u32 w12 = in.readUint32Big(); + CAssetId w13 = in.readUint32Big(); + u32 w14 = in.readUint32Big(); + u32 w15 = in.readUint32Big(); + bool b3 = in.readBool(); + bool b4 = in.readBool(); + + CModelData mData(CStaticRes(w1, zeus::CVector3f::skOne)); + CAnimRes animRes(animParms.GetACSFile(), animParms.GetCharacter(), zeus::CVector3f::skOne, + animParms.GetInitialAnimation(), true); + return new CFishCloud(mgr.AllocateUniqueId(), b1, aHead.x0_name, info, aHead.x40_scale, aHead.x10_transform, + std::move(mData), animRes, w5, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, w6, col, + b2, f14, w7, w8, w9, w10, w11, w12, w13, w14, w15, b3, b4); } CEntity* ScriptLoader::LoadFishCloudModifier(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (propCount < 6 || !EnsurePropertyCount(propCount, 7, "FishCloudModifier")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); - bool b1 = in.readBool(); - bool b2 = in.readBool(); - bool b3 = propCount > 6 ? in.readBool() : false; - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - return new CFishCloudModifier(mgr.AllocateUniqueId(), b1, name, info, vec, b2, b3, f1, f2); -} - -CEntity* ScriptLoader::LoadVisorFlare(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 14, "VisorFlare")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f pos = zeus::CVector3f::ReadBig(in); - bool b1 = in.readBool(); - CVisorFlare::EBlendMode w1 = CVisorFlare::EBlendMode(in.readUint32Big()); - bool b2 = in.readBool(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - u32 w2 = in.readUint32Big(); - std::vector flares; - flares.reserve(5); - for (int i = 0; i < 5; ++i) - if (auto flare = CVisorFlare::LoadFlareDef(in)) - flares.push_back(*flare); - - return new CScriptVisorFlare(mgr.AllocateUniqueId(), name, info, b1, pos, w1, b2, f1, f2, f3, 2, w2, flares); -} - -CEntity* ScriptLoader::LoadWorldTeleporter(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (propCount < 4 || propCount > 21) - { - Log.report(logvisor::Warning, "Incorrect number of props for WorldTeleporter"); - return nullptr; - } - - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - CAssetId worldId = in.readUint32Big(); - CAssetId areaId = in.readUint32Big(); - - if (propCount == 4) - return new CScriptWorldTeleporter(mgr.AllocateUniqueId(), name, info, active, worldId, areaId); - - CAnimationParameters animParms = LoadAnimationParameters(in); - zeus::CVector3f playerScale = zeus::CVector3f::ReadBig(in); - CAssetId platformModel = in.readUint32Big(); - zeus::CVector3f platformScale = zeus::CVector3f::ReadBig(in); - CAssetId backgroundModel = in.readUint32Big(); - zeus::CVector3f backgroundScale = zeus::CVector3f::ReadBig(in); - bool upElevator = in.readBool(); - - s16 elevatorSound = (propCount < 12 ? s16(-1) : s16(in.readUint32Big())); - u8 volume = (propCount < 13 ? u8(127) : u8(in.readUint32Big())); - u8 panning = (propCount < 14 ? u8(64) : u8(in.readUint32Big())); - bool showText = (propCount < 15 ? false : in.readBool()); - CAssetId fontId = (propCount < 16 ? CAssetId() : in.readUint32Big()); - CAssetId stringId = (propCount < 17 ? CAssetId() : in.readUint32Big()); - bool fadeWhite = (propCount < 18 ? false : in.readBool()); - float charFadeInTime = (propCount < 19 ? 0.1f : in.readFloatBig()); - float charsPerSecond = (propCount < 20 ? 16.f : in.readFloatBig()); - float showDelay = (propCount < 21 ? 0.f : in.readFloatBig()); - - if (showText) - return new CScriptWorldTeleporter(mgr.AllocateUniqueId(), name, info, active, worldId, areaId, elevatorSound, - volume, panning, fontId, stringId, fadeWhite, charFadeInTime, charsPerSecond, - showDelay); - - return new CScriptWorldTeleporter(mgr.AllocateUniqueId(), name, info, active, worldId, areaId, - animParms.GetACSFile(), animParms.GetCharacter(), animParms.GetInitialAnimation(), - playerScale, platformModel, platformScale, backgroundModel, backgroundScale, - upElevator, elevatorSound, volume, panning); -} - -CEntity* ScriptLoader::LoadVisorGoo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 11, "VisorGoo")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f position; - position.readBig(in); - zeus::CTransform xf = zeus::CTransform::Translate(position); - CAssetId particle(in); - CAssetId electric(in); - float minDist = in.readFloatBig(); - float maxDist = in.readFloatBig(); - float nearProb = in.readFloatBig(); - float farProb = in.readFloatBig(); - zeus::CColor color; - color.readRGBABig(in); - s32 sfx = in.readInt32Big(); - bool forceShow = in.readBool(); - - if (!particle.IsValid() && !electric.IsValid()) - return nullptr; - return new CScriptVisorGoo(mgr.AllocateUniqueId(), name, info, xf, particle, electric, minDist, maxDist, - nearProb, farProb, color, sfx, forceShow, false); -} - -CEntity* ScriptLoader::LoadJellyZap(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ + const CEntityInfo& info) { + if (propCount < 6 || !EnsurePropertyCount(propCount, 7, "FishCloudModifier")) return nullptr; + + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f vec = zeus::CVector3f::ReadBig(in); + bool b1 = in.readBool(); + bool b2 = in.readBool(); + bool b3 = propCount > 6 ? in.readBool() : false; + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + return new CFishCloudModifier(mgr.AllocateUniqueId(), b1, name, info, vec, b2, b3, f1, f2); +} + +CEntity* ScriptLoader::LoadVisorFlare(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 14, "VisorFlare")) + return nullptr; + + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f pos = zeus::CVector3f::ReadBig(in); + bool b1 = in.readBool(); + CVisorFlare::EBlendMode w1 = CVisorFlare::EBlendMode(in.readUint32Big()); + bool b2 = in.readBool(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + u32 w2 = in.readUint32Big(); + std::vector flares; + flares.reserve(5); + for (int i = 0; i < 5; ++i) + if (auto flare = CVisorFlare::LoadFlareDef(in)) + flares.push_back(*flare); + + return new CScriptVisorFlare(mgr.AllocateUniqueId(), name, info, b1, pos, w1, b2, f1, f2, f3, 2, w2, flares); +} + +CEntity* ScriptLoader::LoadWorldTeleporter(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (propCount < 4 || propCount > 21) { + Log.report(logvisor::Warning, "Incorrect number of props for WorldTeleporter"); + return nullptr; + } + + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + CAssetId worldId = in.readUint32Big(); + CAssetId areaId = in.readUint32Big(); + + if (propCount == 4) + return new CScriptWorldTeleporter(mgr.AllocateUniqueId(), name, info, active, worldId, areaId); + + CAnimationParameters animParms = LoadAnimationParameters(in); + zeus::CVector3f playerScale = zeus::CVector3f::ReadBig(in); + CAssetId platformModel = in.readUint32Big(); + zeus::CVector3f platformScale = zeus::CVector3f::ReadBig(in); + CAssetId backgroundModel = in.readUint32Big(); + zeus::CVector3f backgroundScale = zeus::CVector3f::ReadBig(in); + bool upElevator = in.readBool(); + + s16 elevatorSound = (propCount < 12 ? s16(-1) : s16(in.readUint32Big())); + u8 volume = (propCount < 13 ? u8(127) : u8(in.readUint32Big())); + u8 panning = (propCount < 14 ? u8(64) : u8(in.readUint32Big())); + bool showText = (propCount < 15 ? false : in.readBool()); + CAssetId fontId = (propCount < 16 ? CAssetId() : in.readUint32Big()); + CAssetId stringId = (propCount < 17 ? CAssetId() : in.readUint32Big()); + bool fadeWhite = (propCount < 18 ? false : in.readBool()); + float charFadeInTime = (propCount < 19 ? 0.1f : in.readFloatBig()); + float charsPerSecond = (propCount < 20 ? 16.f : in.readFloatBig()); + float showDelay = (propCount < 21 ? 0.f : in.readFloatBig()); + + if (showText) + return new CScriptWorldTeleporter(mgr.AllocateUniqueId(), name, info, active, worldId, areaId, elevatorSound, + volume, panning, fontId, stringId, fadeWhite, charFadeInTime, charsPerSecond, + showDelay); + + return new CScriptWorldTeleporter(mgr.AllocateUniqueId(), name, info, active, worldId, areaId, animParms.GetACSFile(), + animParms.GetCharacter(), animParms.GetInitialAnimation(), playerScale, + platformModel, platformScale, backgroundModel, backgroundScale, upElevator, + elevatorSound, volume, panning); +} + +CEntity* ScriptLoader::LoadVisorGoo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 11, "VisorGoo")) + return nullptr; + + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f position; + position.readBig(in); + zeus::CTransform xf = zeus::CTransform::Translate(position); + CAssetId particle(in); + CAssetId electric(in); + float minDist = in.readFloatBig(); + float maxDist = in.readFloatBig(); + float nearProb = in.readFloatBig(); + float farProb = in.readFloatBig(); + zeus::CColor color; + color.readRGBABig(in); + s32 sfx = in.readInt32Big(); + bool forceShow = in.readBool(); + + if (!particle.IsValid() && !electric.IsValid()) + return nullptr; + return new CScriptVisorGoo(mgr.AllocateUniqueId(), name, info, xf, particle, electric, minDist, maxDist, nearProb, + farProb, color, sfx, forceShow, false); +} + +CEntity* ScriptLoader::LoadJellyZap(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; } CEntity* ScriptLoader::LoadControllerAction(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "ControllerAction") || propCount > 6) - return nullptr; + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "ControllerAction") || propCount > 6) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - ControlMapper::ECommands w1 = ControlMapper::ECommands(in.readUint32Big()); - bool b1 = false; - u32 w2 = 0; - if (propCount == 6) - { - b1 = in.readBool(); - w2 = in.readUint32Big(); - } - bool b2 = in.readBool(); + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + ControlMapper::ECommands w1 = ControlMapper::ECommands(in.readUint32Big()); + bool b1 = false; + u32 w2 = 0; + if (propCount == 6) { + b1 = in.readBool(); + w2 = in.readUint32Big(); + } + bool b2 = in.readBool(); - return new CScriptControllerAction(mgr.AllocateUniqueId(), name, info, active, w1, b1, w2, b2); + return new CScriptControllerAction(mgr.AllocateUniqueId(), name, info, active, w1, b1, w2, b2); } -CEntity* ScriptLoader::LoadSwitch(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "Switch")) - return nullptr; +CEntity* ScriptLoader::LoadSwitch(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "Switch")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - bool b2 = in.readBool(); - bool b3 = in.readBool(); + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + bool b2 = in.readBool(); + bool b3 = in.readBool(); - return new CScriptSwitch(mgr.AllocateUniqueId(), name, info, active, b2, b3); + return new CScriptSwitch(mgr.AllocateUniqueId(), name, info, active, b2, b3); } CEntity* ScriptLoader::LoadPlayerStateChange(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 7, "PlayerStateChange")) - return nullptr; + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 7, "PlayerStateChange")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - s32 itemType = in.readUint32Big(); - s32 itemCount = in.readInt32Big(); - s32 itemCapacity = in.readInt32Big(); - CScriptPlayerStateChange::EControl ctrl = CScriptPlayerStateChange::EControl(in.readUint32Big()); - CScriptPlayerStateChange::EControlCommandOption ctrlCmdOpt = - CScriptPlayerStateChange::EControlCommandOption(in.readUint32Big()); - return new CScriptPlayerStateChange(mgr.AllocateUniqueId(), name, info, active, itemType, itemCount, itemCapacity, - ctrl, ctrlCmdOpt); + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + s32 itemType = in.readUint32Big(); + s32 itemCount = in.readInt32Big(); + s32 itemCapacity = in.readInt32Big(); + CScriptPlayerStateChange::EControl ctrl = CScriptPlayerStateChange::EControl(in.readUint32Big()); + CScriptPlayerStateChange::EControlCommandOption ctrlCmdOpt = + CScriptPlayerStateChange::EControlCommandOption(in.readUint32Big()); + return new CScriptPlayerStateChange(mgr.AllocateUniqueId(), name, info, active, itemType, itemCount, itemCapacity, + ctrl, ctrlCmdOpt); } -CEntity* ScriptLoader::LoadThardus(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - return nullptr; +CEntity* ScriptLoader::LoadThardus(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; } CEntity* ScriptLoader::LoadWallCrawlerSwarm(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 39, "WallCrawlerSwarm")) - return nullptr; + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 39, "WallCrawlerSwarm")) + return nullptr; - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - bool active = in.readBool(); - CActorParameters aParams = LoadActorParameters(in); - u32 w1 = in.readUint32Big(); - u32 w2 = in.readUint32Big(); - u32 w3 = in.readUint32Big(); - u32 w4 = in.readUint32Big(); - u32 w5 = in.readUint32Big(); - u32 w6 = in.readUint32Big(); - u32 w7 = in.readUint32Big(); - u32 w8 = in.readUint32Big(); - u32 w9 = in.readUint32Big(); - u32 w10 = in.readUint32Big(); - CDamageInfo dInfo1(in); - float f1 = in.readFloatBig(); - CDamageInfo dInfo2(in); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - float f5 = in.readFloatBig(); - u32 w11 = in.readUint32Big(); - u32 w12 = in.readUint32Big(); - float f6 = in.readFloatBig(); - float f7 = in.readFloatBig(); - float f8 = in.readFloatBig(); - float f9 = in.readFloatBig(); - float f10 = in.readFloatBig(); - float f11 = in.readFloatBig(); - float f12 = in.readFloatBig(); - float f13 = in.readFloatBig(); - u32 w13 = in.readUint32Big(); - float f14 = in.readFloatBig(); - float f15 = in.readFloatBig(); - float f16 = in.readFloatBig(); - CHealthInfo hInfo(in); - CDamageVulnerability dVulns(in); - u32 w14 = in.readUint32Big(); - u32 w15 = in.readUint32Big(); + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + bool active = in.readBool(); + CActorParameters aParams = LoadActorParameters(in); + u32 w1 = in.readUint32Big(); + u32 w2 = in.readUint32Big(); + u32 w3 = in.readUint32Big(); + u32 w4 = in.readUint32Big(); + u32 w5 = in.readUint32Big(); + u32 w6 = in.readUint32Big(); + u32 w7 = in.readUint32Big(); + u32 w8 = in.readUint32Big(); + u32 w9 = in.readUint32Big(); + u32 w10 = in.readUint32Big(); + CDamageInfo dInfo1(in); + float f1 = in.readFloatBig(); + CDamageInfo dInfo2(in); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + float f5 = in.readFloatBig(); + u32 w11 = in.readUint32Big(); + u32 w12 = in.readUint32Big(); + float f6 = in.readFloatBig(); + float f7 = in.readFloatBig(); + float f8 = in.readFloatBig(); + float f9 = in.readFloatBig(); + float f10 = in.readFloatBig(); + float f11 = in.readFloatBig(); + float f12 = in.readFloatBig(); + float f13 = in.readFloatBig(); + u32 w13 = in.readUint32Big(); + float f14 = in.readFloatBig(); + float f15 = in.readFloatBig(); + float f16 = in.readFloatBig(); + CHealthInfo hInfo(in); + CDamageVulnerability dVulns(in); + u32 w14 = in.readUint32Big(); + u32 w15 = in.readUint32Big(); - return new CWallCrawlerSwarm(mgr.AllocateUniqueId(), active, aHead.x0_name, info, aHead.x40_scale, - aHead.x10_transform, w1, CAnimRes(w2, w3, zeus::CVector3f(1.5f), w4, true), w5, w6, w7, - w8, w9, w10, dInfo1, dInfo2, f1, f2, f3, f4, w11, w12, f5, f6, f7, f8, f9, f10, f11, - f12, f13, w13, f14, f15, f16, hInfo, dVulns, w14, w15, aParams); + return new CWallCrawlerSwarm(mgr.AllocateUniqueId(), active, aHead.x0_name, info, aHead.x40_scale, + aHead.x10_transform, w1, CAnimRes(w2, w3, zeus::CVector3f(1.5f), w4, true), w5, w6, w7, + w8, w9, w10, dInfo1, dInfo2, f1, f2, f3, f4, w11, w12, f5, f6, f7, f8, f9, f10, f11, f12, + f13, w13, f14, f15, f16, hInfo, dVulns, w14, w15, aParams); } -CEntity* ScriptLoader::LoadAiJumpPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 5, "AiJumpPoint")) - return nullptr; +CEntity* ScriptLoader::LoadAiJumpPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 5, "AiJumpPoint")) + return nullptr; - SActorHead aHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - float f1 = in.readFloat(); + SActorHead aHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + float f1 = in.readFloat(); - return new CScriptAiJumpPoint(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, f1); + return new CScriptAiJumpPoint(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, f1); } CEntity* ScriptLoader::LoadFlaahgraTentacle(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ + const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadRoomAcoustics(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 32, "RoomAcoustics")) return nullptr; + + std::string name = mgr.HashInstanceName(in); + bool a = in.readBool(); + u32 b = in.readUint32Big(); + bool c = in.readBool(); + bool d = in.readBool(); + float e = in.readFloatBig(); + float f = in.readFloatBig(); + float g = in.readFloatBig(); + float h = in.readFloatBig(); + float i = in.readFloatBig(); + float j = in.readFloatBig(); + bool k = in.readBool(); + float l = in.readFloatBig(); + float m = in.readFloatBig(); + float n = in.readFloatBig(); + bool o = in.readBool(); + bool p = in.readBool(); + float q = in.readFloatBig(); + float r = in.readFloatBig(); + float s = in.readFloatBig(); + float t = in.readFloatBig(); + float u = in.readFloatBig(); + bool v = in.readBool(); + u32 w = in.readUint32Big(); + u32 x = in.readUint32Big(); + u32 y = in.readUint32Big(); + u32 z = in.readUint32Big(); + u32 _a = in.readUint32Big(); + u32 _b = in.readUint32Big(); + u32 _c = in.readUint32Big(); + u32 _d = in.readUint32Big(); + u32 _e = in.readUint32Big(); + + return new CScriptRoomAcoustics(mgr.AllocateUniqueId(), name, info, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, + r, s, t, u, v, w, x, y, z, _a, _b, _c, _d, _e); } -CEntity* ScriptLoader::LoadRoomAcoustics(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 32, "RoomAcoustics")) - return nullptr; +CEntity* ScriptLoader::LoadColorModulate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 12, "ColorModulate")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool a = in.readBool(); - u32 b = in.readUint32Big(); - bool c = in.readBool(); - bool d = in.readBool(); - float e = in.readFloatBig(); - float f = in.readFloatBig(); - float g = in.readFloatBig(); - float h = in.readFloatBig(); - float i = in.readFloatBig(); - float j = in.readFloatBig(); - bool k = in.readBool(); - float l = in.readFloatBig(); - float m = in.readFloatBig(); - float n = in.readFloatBig(); - bool o = in.readBool(); - bool p = in.readBool(); - float q = in.readFloatBig(); - float r = in.readFloatBig(); - float s = in.readFloatBig(); - float t = in.readFloatBig(); - float u = in.readFloatBig(); - bool v = in.readBool(); - u32 w = in.readUint32Big(); - u32 x = in.readUint32Big(); - u32 y = in.readUint32Big(); - u32 z = in.readUint32Big(); - u32 _a = in.readUint32Big(); - u32 _b = in.readUint32Big(); - u32 _c = in.readUint32Big(); - u32 _d = in.readUint32Big(); - u32 _e = in.readUint32Big(); - - return new CScriptRoomAcoustics(mgr.AllocateUniqueId(), name, info, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, - q, r, s, t, u, v, w, x, y, z, _a, _b, _c, _d, _e); -} - -CEntity* ScriptLoader::LoadColorModulate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 12, "ColorModulate")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CColor colorA; - colorA.readRGBABig(in); - zeus::CColor colorB; - colorB.readRGBABig(in); - CScriptColorModulate::EBlendMode blendMode = CScriptColorModulate::EBlendMode(in.readUint32Big()); - float timeA2B = in.readFloatBig(); - float timeB2A = in.readFloatBig(); - bool doReverse = in.readBool(); - bool resetTargetWhenDone = in.readBool(); - bool depthCompare = in.readBool(); - bool depthUpdate = in.readBool(); - bool depthBackwards = in.readBool(); - bool active = in.readBool(); - return new CScriptColorModulate(mgr.AllocateUniqueId(), name, info, colorA, colorB, blendMode, timeA2B, timeB2A, - doReverse, resetTargetWhenDone, depthCompare, depthUpdate, depthBackwards, active); + std::string name = mgr.HashInstanceName(in); + zeus::CColor colorA; + colorA.readRGBABig(in); + zeus::CColor colorB; + colorB.readRGBABig(in); + CScriptColorModulate::EBlendMode blendMode = CScriptColorModulate::EBlendMode(in.readUint32Big()); + float timeA2B = in.readFloatBig(); + float timeB2A = in.readFloatBig(); + bool doReverse = in.readBool(); + bool resetTargetWhenDone = in.readBool(); + bool depthCompare = in.readBool(); + bool depthUpdate = in.readBool(); + bool depthBackwards = in.readBool(); + bool active = in.readBool(); + return new CScriptColorModulate(mgr.AllocateUniqueId(), name, info, colorA, colorB, blendMode, timeA2B, timeB2A, + doReverse, resetTargetWhenDone, depthCompare, depthUpdate, depthBackwards, active); } CEntity* ScriptLoader::LoadThardusRockProjectile(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ + const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadMidi(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 6, "Midi")) return nullptr; + + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + u32 csng = in.readUint32Big(); + float fadeIn = in.readFloatBig(); + float fadeOut = in.readFloatBig(); + u32 vol = in.readUint32Big(); + return new CScriptMidi(mgr.AllocateUniqueId(), info, name, active, csng, fadeIn, fadeOut, vol); } -CEntity* ScriptLoader::LoadMidi(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 6, "Midi")) - return nullptr; +CEntity* ScriptLoader::LoadStreamedAudio(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 9, "StreamedAudio")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - u32 csng = in.readUint32Big(); - float fadeIn = in.readFloatBig(); - float fadeOut = in.readFloatBig(); - u32 vol = in.readUint32Big(); - return new CScriptMidi(mgr.AllocateUniqueId(), info, name, active, csng, fadeIn, fadeOut, vol); + const std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + std::string fileName = in.readString(); + bool noStopOnDeactivate = in.readBool(); + float fadeIn = in.readFloatBig(); + float fadeOut = in.readFloatBig(); + u32 volume = in.readUint32Big(); + u32 oneShot = in.readUint32Big(); + bool music = in.readBool(); + + return new CScriptStreamedMusic(mgr.AllocateUniqueId(), info, name, active, fileName, noStopOnDeactivate, fadeIn, + fadeOut, volume, !oneShot, music); } -CEntity* ScriptLoader::LoadStreamedAudio(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 9, "StreamedAudio")) - return nullptr; +CEntity* ScriptLoader::LoadRepulsor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "Repulsor")) + return nullptr; - const std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - std::string fileName = in.readString(); - bool noStopOnDeactivate = in.readBool(); - float fadeIn = in.readFloatBig(); - float fadeOut = in.readFloatBig(); - u32 volume = in.readUint32Big(); - u32 oneShot = in.readUint32Big(); - bool music = in.readBool(); + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f center = in.readVec3fBig(); + bool active = in.readBool(); + float radius = in.readFloatBig(); - return new CScriptStreamedMusic(mgr.AllocateUniqueId(), info, name, active, fileName, noStopOnDeactivate, fadeIn, - fadeOut, volume, !oneShot, music); + return new CRepulsor(mgr.AllocateUniqueId(), active, name, info, center, radius); } -CEntity* ScriptLoader::LoadRepulsor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "Repulsor")) - return nullptr; +CEntity* ScriptLoader::LoadGunTurret(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, CScriptGunTurretData::GetMinProperties(), "GunTurret")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f center = in.readVec3fBig(); - bool active = in.readBool(); - float radius = in.readFloatBig(); + std::string name = mgr.HashInstanceName(in); + CScriptGunTurret::ETurretComponent component = CScriptGunTurret::ETurretComponent(in.readUint32Big()); + zeus::CTransform xf = LoadEditorTransform(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + zeus::CVector3f collisionExtent = zeus::CVector3f::ReadBig(in); + zeus::CVector3f collisionOffset = zeus::CVector3f::ReadBig(in); + CAnimationParameters animParms = LoadAnimationParameters(in); + CActorParameters actParms = LoadActorParameters(in); + CHealthInfo hInfo(in); + CDamageVulnerability dVuln(in); + CScriptGunTurretData turretData(in, propCount); - return new CRepulsor(mgr.AllocateUniqueId(), active, name, info, center, radius); + if (!g_ResFactory->GetResourceTypeById(animParms.GetACSFile())) + return nullptr; + + CModelData mData( + CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); + zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, collisionOffset); + + if ((collisionExtent.x() < 0.f || collisionExtent.y() < 0.f || collisionExtent.z() < 0.f) || collisionExtent.isZero()) + aabb = mData.GetBounds(xf.getRotation()); + + return new CScriptGunTurret(mgr.AllocateUniqueId(), name, component, info, xf, std::move(mData), aabb, hInfo, dVuln, + actParms, turretData); } -CEntity* ScriptLoader::LoadGunTurret(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, CScriptGunTurretData::GetMinProperties(), "GunTurret")) - return nullptr; +CEntity* ScriptLoader::LoadFogVolume(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 7, "FogVolume")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - CScriptGunTurret::ETurretComponent component = CScriptGunTurret::ETurretComponent(in.readUint32Big()); - zeus::CTransform xf = LoadEditorTransform(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - zeus::CVector3f collisionExtent = zeus::CVector3f::ReadBig(in); - zeus::CVector3f collisionOffset = zeus::CVector3f::ReadBig(in); - CAnimationParameters animParms = LoadAnimationParameters(in); - CActorParameters actParms = LoadActorParameters(in); - CHealthInfo hInfo(in); - CDamageVulnerability dVuln(in); - CScriptGunTurretData turretData(in, propCount); + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f center = zeus::CVector3f::ReadBig(in); + zeus::CVector3f volume = zeus::CVector3f::ReadBig(in); + float flickerSpeed = in.readFloatBig(); + float f2 = in.readFloatBig(); + zeus::CColor fogColor = zeus::CColor::ReadRGBABig(in); + bool active = in.readBool(); - if (!g_ResFactory->GetResourceTypeById(animParms.GetACSFile())) - return nullptr; + volume.x() = std::fabs(volume.x()); + volume.y() = std::fabs(volume.y()); + volume.z() = std::fabs(volume.z()); - CModelData mData( - CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); - zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, collisionOffset); - - if ((collisionExtent.x() < 0.f || collisionExtent.y() < 0.f || collisionExtent.z() < 0.f) || collisionExtent.isZero()) - aabb = mData.GetBounds(xf.getRotation()); - - return new CScriptGunTurret(mgr.AllocateUniqueId(), name, component, info, xf, std::move(mData), aabb, hInfo, dVuln, - actParms, turretData); + return new CScriptSpecialFunction(mgr.AllocateUniqueId(), name, info, ConvertEditorEulerToTransform4f(center, {}), + CScriptSpecialFunction::ESpecialFunction::FogVolume, "", flickerSpeed, f2, 0.f, 0.f, + volume, fogColor, active, CDamageInfo(), -1, -1, CPlayerState::EItemType::Invalid, + -1, -1, -1); } -CEntity* ScriptLoader::LoadFogVolume(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 7, "FogVolume")) - return nullptr; +CEntity* ScriptLoader::LoadBabygoth(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 33, "Babygoth")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f center = zeus::CVector3f::ReadBig(in); - zeus::CVector3f volume = zeus::CVector3f::ReadBig(in); - float flickerSpeed = in.readFloatBig(); - float f2 = in.readFloatBig(); - zeus::CColor fogColor = zeus::CColor::ReadRGBABig(in); - bool active = in.readBool(); + SScaledActorHead actHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; - volume.x() = std::fabs(volume.x()); - volume.y() = std::fabs(volume.y()); - volume.z() = std::fabs(volume.z()); + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + MP1::CBabygothData babyData(in); - return new CScriptSpecialFunction(mgr.AllocateUniqueId(), name, info, ConvertEditorEulerToTransform4f(center, {}), - CScriptSpecialFunction::ESpecialFunction::FogVolume, "", flickerSpeed, f2, 0.f, - 0.f, volume, fogColor, active, CDamageInfo(), -1, -1, CPlayerState::EItemType::Invalid, - -1, -1, -1); + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + return new MP1::CBabygoth(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData), + pInfo, actParms, babyData); } -CEntity* ScriptLoader::LoadBabygoth(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 33, "Babygoth")) - return nullptr; +CEntity* ScriptLoader::LoadEyeball(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 21, "Eyeball")) + return nullptr; - SScaledActorHead actHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; + std::string name = mgr.HashInstanceName(in); + CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); + zeus::CTransform xf = LoadEditorTransform(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - MP1::CBabygothData babyData(in); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + CAssetId wpsc(in); + CDamageInfo dInfo(in); + CAssetId partId1(in); + CAssetId partId2(in); + CAssetId texture1(in); + CAssetId texture2(in); + u32 w1 = in.readUint32Big(); + u32 w2 = in.readUint32Big(); + u32 w3 = in.readUint32Big(); + u32 w4 = in.readUint32Big(); + u32 w5 = in.readUint32Big(); - CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), - pInfo.GetAnimationParameters().GetCharacter(), actHead.x40_scale, - pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - return new MP1::CBabygoth(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData), - pInfo, actParms, babyData); + if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) + return nullptr; + + bool b1 = in.readBool(); + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + + return new MP1::CEyeball(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, f1, f2, wpsc, dInfo, + partId1, partId2, texture1, texture2, w1, w2, w3, w4, w5, b1, actParms); } -CEntity* ScriptLoader::LoadEyeball(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 21, "Eyeball")) - return nullptr; +CEntity* ScriptLoader::LoadRadialDamage(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 5, "RadialDamage")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - CPatterned::EFlavorType flavor = CPatterned::EFlavorType(in.readUint32Big()); - zeus::CTransform xf = LoadEditorTransform(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f center = zeus::CVector3f::ReadBig(in); + bool active = in.readBool(); + CDamageInfo dInfo(in); + float radius = in.readFloatBig(); + zeus::CTransform xf = ConvertEditorEulerToTransform4f(zeus::CVector3f::skZero, center); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - CAssetId wpsc(in); - CDamageInfo dInfo(in); - CAssetId partId1(in); - CAssetId partId2(in); - CAssetId texture1(in); - CAssetId texture2(in); - u32 w1 = in.readUint32Big(); - u32 w2 = in.readUint32Big(); - u32 w3 = in.readUint32Big(); - u32 w4 = in.readUint32Big(); - u32 w5 = in.readUint32Big(); - - if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) - return nullptr; - - bool b1 = in.readBool(); - - CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), - pInfo.GetAnimationParameters().GetCharacter(), scale, - pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - - return new MP1::CEyeball(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, f1, f2, wpsc, - dInfo, partId1, partId2, texture1, texture2, w1, w2, w3, w4, w5, b1, actParms); -} - -CEntity* ScriptLoader::LoadRadialDamage(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 5, "RadialDamage")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f center = zeus::CVector3f::ReadBig(in); - bool active = in.readBool(); - CDamageInfo dInfo(in); - float radius = in.readFloatBig(); - zeus::CTransform xf = ConvertEditorEulerToTransform4f(zeus::CVector3f::skZero, center); - - return new CScriptSpecialFunction(mgr.AllocateUniqueId(), name, info, xf, - CScriptSpecialFunction::ESpecialFunction::RadialDamage, "", radius, 0.f, - 0.f, 0.f, zeus::CVector3f::skZero, zeus::CColor::skBlack, active, dInfo, -1, -1, - CPlayerState::EItemType::Invalid, -1, -1, -1); + return new CScriptSpecialFunction(mgr.AllocateUniqueId(), name, info, xf, + CScriptSpecialFunction::ESpecialFunction::RadialDamage, "", radius, 0.f, 0.f, 0.f, + zeus::CVector3f::skZero, zeus::CColor::skBlack, active, dInfo, -1, -1, + CPlayerState::EItemType::Invalid, -1, -1, -1); } CEntity* ScriptLoader::LoadCameraPitchVolume(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 8, "CameraPitchVolume")) - return nullptr; + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 8, "CameraPitchVolume")) + return nullptr; - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - bool active = in.readBool(); - zeus::CRelAngle f1 = zeus::CRelAngle::FromDegrees(in.readFloatBig()); - zeus::CRelAngle f2 = zeus::CRelAngle::FromDegrees(in.readFloatBig()); - float f3 = in.readFloatBig(); + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + bool active = in.readBool(); + zeus::CRelAngle f1 = zeus::CRelAngle::FromDegrees(in.readFloatBig()); + zeus::CRelAngle f2 = zeus::CRelAngle::FromDegrees(in.readFloatBig()); + float f3 = in.readFloatBig(); - return new CScriptCameraPitchVolume(mgr.AllocateUniqueId(), active, aHead.x0_name, info, aHead.x40_scale, - aHead.x10_transform, f1, f2, f3); + return new CScriptCameraPitchVolume(mgr.AllocateUniqueId(), active, aHead.x0_name, info, aHead.x40_scale, + aHead.x10_transform, f1, f2, f3); } CEntity* ScriptLoader::LoadEnvFxDensityController(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "EnvFxDensityController")) - return nullptr; + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "EnvFxDensityController")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - float density = in.readFloatBig(); - u32 w1 = in.readUint32Big(); + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + float density = in.readFloatBig(); + u32 w1 = in.readUint32Big(); - return new CScriptSpecialFunction(mgr.AllocateUniqueId(), name, info, zeus::CTransform::Identity(), - CScriptSpecialFunction::ESpecialFunction::EnvFxDensityController, "", density, w1, - 0.f, 0.f, zeus::CVector3f::skZero, zeus::CColor::skBlack, active, CDamageInfo(), - -1, -1, CPlayerState::EItemType::Invalid, -1, -1, -1); + return new CScriptSpecialFunction(mgr.AllocateUniqueId(), name, info, zeus::CTransform::Identity(), + CScriptSpecialFunction::ESpecialFunction::EnvFxDensityController, "", density, w1, + 0.f, 0.f, zeus::CVector3f::skZero, zeus::CColor::skBlack, active, CDamageInfo(), -1, + -1, CPlayerState::EItemType::Invalid, -1, -1, -1); } -CEntity* ScriptLoader::LoadMagdolite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 22, "Magdolite")) - return nullptr; +CEntity* ScriptLoader::LoadMagdolite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 22, "Magdolite")) + return nullptr; - SScaledActorHead actorHead = LoadScaledActorHead(in, mgr); + SScaledActorHead actorHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; - CPatternedInfo pInfo(in, pair.second); - CActorParameters actorParameters = LoadActorParameters(in); + CPatternedInfo pInfo(in, pair.second); + CActorParameters actorParameters = LoadActorParameters(in); - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - CDamageInfo damageInfo1(in); - CDamageInfo damageInfo2(in); - CDamageVulnerability damageVulnerability1(in); - CDamageVulnerability damageVulnerability2(in); - CAssetId modelId(in); - CAssetId skinId(in); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - float f5 = in.readFloatBig(); - float f6 = in.readFloatBig(); - MP1::CMagdolite::CMagdoliteData magData(in); - float f7 = in.readFloatBig(); - float f8 = in.readFloatBig(); - float f9 = in.readFloatBig(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + CDamageInfo damageInfo1(in); + CDamageInfo damageInfo2(in); + CDamageVulnerability damageVulnerability1(in); + CDamageVulnerability damageVulnerability2(in); + CAssetId modelId(in); + CAssetId skinId(in); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + float f5 = in.readFloatBig(); + float f6 = in.readFloatBig(); + MP1::CMagdolite::CMagdoliteData magData(in); + float f7 = in.readFloatBig(); + float f8 = in.readFloatBig(); + float f9 = in.readFloatBig(); - CModelData modelData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), - pInfo.GetAnimationParameters().GetCharacter(), actorHead.x40_scale, - pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + CModelData modelData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), + pInfo.GetAnimationParameters().GetCharacter(), actorHead.x40_scale, + pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - return new MP1::CMagdolite(mgr.AllocateUniqueId(), actorHead.x0_name, info, actorHead.x10_transform, - std::move(modelData), pInfo, actorParameters, f1, f2, damageInfo1, damageInfo2, - damageVulnerability1, - damageVulnerability2, modelId, skinId, f3, f4, f5, f6, magData, f7, f8, f9); + return new MP1::CMagdolite(mgr.AllocateUniqueId(), actorHead.x0_name, info, actorHead.x10_transform, + std::move(modelData), pInfo, actorParameters, f1, f2, damageInfo1, damageInfo2, + damageVulnerability1, damageVulnerability2, modelId, skinId, f3, f4, f5, f6, magData, f7, + f8, f9); } -CEntity* ScriptLoader::LoadTeamAIMgr(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 8, "TeamAiMgr")) - return nullptr; +CEntity* ScriptLoader::LoadTeamAIMgr(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 8, "TeamAiMgr")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - CTeamAiData data(in, propCount); - return new CTeamAiMgr(mgr.AllocateUniqueId(), name, info, data); + std::string name = mgr.HashInstanceName(in); + CTeamAiData data(in, propCount); + return new CTeamAiMgr(mgr.AllocateUniqueId(), name, info, data); } -CEntity* ScriptLoader::LoadSnakeWeedSwarm(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 25, "SnakeWeedSwarm") || propCount > 29) - return nullptr; +CEntity* ScriptLoader::LoadSnakeWeedSwarm(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 25, "SnakeWeedSwarm") || propCount > 29) + return nullptr; - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f pos = zeus::CVector3f::ReadBig(in); - zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); - bool active = in.readBool(); - CAnimationParameters animParms = LoadAnimationParameters(in); - CActorParameters actParms = LoadActorParameters(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - float f5 = in.readFloatBig(); - float f6 = in.readFloatBig(); - float f7 = in.readFloatBig(); - float f8 = in.readFloatBig(); - float f9 = in.readFloatBig(); - float f10 = in.readFloatBig(); - float f11 = in.readFloatBig(); - float f12 = in.readFloatBig(); - float f13 = in.readFloatBig(); - float f14 = in.readFloatBig(); - CDamageInfo dInfo(in); - float f15 = in.readFloatBig(); - u32 w4 = in.readUint32Big(); - u32 w5 = in.readUint32Big(); - u32 w6 = in.readUint32Big(); - u32 w7 = (propCount < 29 ? -1 : in.readUint32Big()); - u32 w8 = (propCount < 29 ? -1 : in.readUint32Big()); - u32 w9 = (propCount < 29 ? -1 : in.readUint32Big()); - u32 f16 = (propCount < 29 ? 0.f : in.readFloatBig()); + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f pos = zeus::CVector3f::ReadBig(in); + zeus::CVector3f scale = zeus::CVector3f::ReadBig(in); + bool active = in.readBool(); + CAnimationParameters animParms = LoadAnimationParameters(in); + CActorParameters actParms = LoadActorParameters(in); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + float f5 = in.readFloatBig(); + float f6 = in.readFloatBig(); + float f7 = in.readFloatBig(); + float f8 = in.readFloatBig(); + float f9 = in.readFloatBig(); + float f10 = in.readFloatBig(); + float f11 = in.readFloatBig(); + float f12 = in.readFloatBig(); + float f13 = in.readFloatBig(); + float f14 = in.readFloatBig(); + CDamageInfo dInfo(in); + float f15 = in.readFloatBig(); + u32 w4 = in.readUint32Big(); + u32 w5 = in.readUint32Big(); + u32 w6 = in.readUint32Big(); + u32 w7 = (propCount < 29 ? -1 : in.readUint32Big()); + u32 w8 = (propCount < 29 ? -1 : in.readUint32Big()); + u32 w9 = (propCount < 29 ? -1 : in.readUint32Big()); + u32 f16 = (propCount < 29 ? 0.f : in.readFloatBig()); - return new CSnakeWeedSwarm(mgr.AllocateUniqueId(), active, name, info, pos, scale, animParms, actParms, f1, f2, f3, - f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, dInfo, f15, w4, w5, w6, w7, w8, w9, - f16); + return new CSnakeWeedSwarm(mgr.AllocateUniqueId(), active, name, info, pos, scale, animParms, actParms, f1, f2, f3, + f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, dInfo, f15, w4, w5, w6, w7, w8, w9, f16); } CEntity* ScriptLoader::LoadActorContraption(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 15, "ActorContraption")) - return nullptr; - - SScaledActorHead head = LoadScaledActorHead(in, mgr); - zeus::CVector3f collisionExtent = zeus::CVector3f::ReadBig(in); - zeus::CVector3f collisionOrigin = zeus::CVector3f::ReadBig(in); - float mass = in.readFloatBig(); - float zMomentum = in.readFloatBig(); - CHealthInfo hInfo(in); - CDamageVulnerability dVuln(in); - CAnimationParameters animParams(in); - CActorParameters actParams = LoadActorParameters(in); - CAssetId flameFxId = in.readUint32Big(); - CDamageInfo dInfo(in); - bool active = in.readBool(); - - if (!g_ResFactory->GetResourceTypeById(animParams.GetACSFile())) - return nullptr; - - zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, collisionOrigin); - CMaterialList list; - list.Add(EMaterialTypes::Immovable); - list.Add(EMaterialTypes::Solid); - - CModelData data(CAnimRes(animParams.GetACSFile(), animParams.GetCharacter(), head.x40_scale, - animParams.GetInitialAnimation(), true)); - - if ((collisionExtent.x() < 0.f || collisionExtent.y() < 0.f || collisionExtent.z() < 0.f) || collisionExtent.isZero()) - aabb = data.GetBounds(head.x10_transform.getRotation()); - - return new MP1::CActorContraption(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(data), - aabb, list, mass, zMomentum, hInfo, dVuln, actParams, flameFxId, dInfo, active); -} - -CEntity* ScriptLoader::LoadOculus(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 15, "ActorContraption")) return nullptr; + + SScaledActorHead head = LoadScaledActorHead(in, mgr); + zeus::CVector3f collisionExtent = zeus::CVector3f::ReadBig(in); + zeus::CVector3f collisionOrigin = zeus::CVector3f::ReadBig(in); + float mass = in.readFloatBig(); + float zMomentum = in.readFloatBig(); + CHealthInfo hInfo(in); + CDamageVulnerability dVuln(in); + CAnimationParameters animParams(in); + CActorParameters actParams = LoadActorParameters(in); + CAssetId flameFxId = in.readUint32Big(); + CDamageInfo dInfo(in); + bool active = in.readBool(); + + if (!g_ResFactory->GetResourceTypeById(animParams.GetACSFile())) + return nullptr; + + zeus::CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, collisionOrigin); + CMaterialList list; + list.Add(EMaterialTypes::Immovable); + list.Add(EMaterialTypes::Solid); + + CModelData data(CAnimRes(animParams.GetACSFile(), animParams.GetCharacter(), head.x40_scale, + animParams.GetInitialAnimation(), true)); + + if ((collisionExtent.x() < 0.f || collisionExtent.y() < 0.f || collisionExtent.z() < 0.f) || collisionExtent.isZero()) + aabb = data.GetBounds(head.x10_transform.getRotation()); + + return new MP1::CActorContraption(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(data), + aabb, list, mass, zMomentum, hInfo, dVuln, actParams, flameFxId, dInfo, active); } -CEntity* ScriptLoader::LoadGeemer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 16, "Geemer")) - return nullptr; - SScaledActorHead actHead = LoadScaledActorHead(in, mgr); - - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - - if (pInfo.GetAnimationParameters().GetACSFile() == CAssetId()) - return nullptr; - - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - float f5 = in.readFloatBig(); - float f6 = in.readFloatBig(); - float f7 = in.readFloatBig(); - u16 sId1 = in.readUint32Big() & 0xFFFF; - u16 sId2 = in.readUint32Big() & 0xFFFF; - u16 sId3 = in.readUint32Big() & 0xFFFF; - - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - - return new MP1::CParasite(mgr.AllocateUniqueId(), actHead.x0_name, CPatterned::EFlavorType::Zero, info, - actHead.x10_transform, std::move(mData), pInfo, EBodyType::WallWalker, 0.f, f1, f2, f3, - f4, 0.2f, 0.4f, 0.f, - 0.f, 0.f, 0.f, 0.f, 1.f, f7, 0.f, 0.f, f5, f6, false, CWallWalker::EWalkerType::Geemer, - CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(), sId1, sId2, sId3, -1, - -1, 0.f, actParms); +CEntity* ScriptLoader::LoadOculus(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; } -CEntity* ScriptLoader::LoadSpindleCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 24, "SpindleCamera")) - return nullptr; +CEntity* ScriptLoader::LoadGeemer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 16, "Geemer")) + return nullptr; + SScaledActorHead actHead = LoadScaledActorHead(in, mgr); - SActorHead aHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - u32 flags = LoadParameterFlags(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; - SSpindleProperty seg1(in); - seg1.FixupAngles(); - SSpindleProperty seg2(in); - SSpindleProperty seg3(in); - SSpindleProperty seg4(in); - SSpindleProperty seg5(in); - seg5.FixupAngles(); - SSpindleProperty seg6(in); - seg6.FixupAngles(); - SSpindleProperty seg7(in); - seg7.FixupAngles(); - SSpindleProperty seg8(in); - seg8.FixupAngles(); - SSpindleProperty seg9(in); - SSpindleProperty seg10(in); - SSpindleProperty seg11(in); - seg11.FixupAngles(); - SSpindleProperty seg12(in); - seg12.FixupAngles(); - SSpindleProperty seg13(in); - seg13.FixupAngles(); - SSpindleProperty seg14(in); - SSpindleProperty seg15(in); - seg15.FixupAngles(); + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); - return new CScriptSpindleCamera(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, flags, f1, - f2, f3, f4, seg1, seg2, seg3, seg4, seg5, seg6, seg7, seg8, seg9, seg10, seg11, - seg12, seg13, seg14, seg15); + if (pInfo.GetAnimationParameters().GetACSFile() == CAssetId()) + return nullptr; + + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + float f5 = in.readFloatBig(); + float f6 = in.readFloatBig(); + float f7 = in.readFloatBig(); + u16 sId1 = in.readUint32Big() & 0xFFFF; + u16 sId2 = in.readUint32Big() & 0xFFFF; + u16 sId3 = in.readUint32Big() & 0xFFFF; + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + + return new MP1::CParasite(mgr.AllocateUniqueId(), actHead.x0_name, CPatterned::EFlavorType::Zero, info, + actHead.x10_transform, std::move(mData), pInfo, EBodyType::WallWalker, 0.f, f1, f2, f3, f4, + 0.2f, 0.4f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, f7, 0.f, 0.f, f5, f6, false, + CWallWalker::EWalkerType::Geemer, CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(), + sId1, sId2, sId3, -1, -1, 0.f, actParms); } -CEntity* ScriptLoader::LoadAtomicAlpha(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 14, "AtomicAlpha")) - return nullptr; +CEntity* ScriptLoader::LoadSpindleCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 24, "SpindleCamera")) + return nullptr; - SScaledActorHead actHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; + SActorHead aHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + u32 flags = LoadParameterFlags(in); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); + SSpindleProperty seg1(in); + seg1.FixupAngles(); + SSpindleProperty seg2(in); + SSpindleProperty seg3(in); + SSpindleProperty seg4(in); + SSpindleProperty seg5(in); + seg5.FixupAngles(); + SSpindleProperty seg6(in); + seg6.FixupAngles(); + SSpindleProperty seg7(in); + seg7.FixupAngles(); + SSpindleProperty seg8(in); + seg8.FixupAngles(); + SSpindleProperty seg9(in); + SSpindleProperty seg10(in); + SSpindleProperty seg11(in); + seg11.FixupAngles(); + SSpindleProperty seg12(in); + seg12.FixupAngles(); + SSpindleProperty seg13(in); + seg13.FixupAngles(); + SSpindleProperty seg14(in); + SSpindleProperty seg15(in); + seg15.FixupAngles(); - CAssetId wpsc(in); - CAssetId model(in); - CDamageInfo dInfo(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - bool b1 = in.readBool(); - bool b2 = in.readBool(); + return new CScriptSpindleCamera(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, flags, f1, + f2, f3, f4, seg1, seg2, seg3, seg4, seg5, seg6, seg7, seg8, seg9, seg10, seg11, seg12, + seg13, seg14, seg15); +} - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); +CEntity* ScriptLoader::LoadAtomicAlpha(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 14, "AtomicAlpha")) + return nullptr; - return new MP1::CAtomicAlpha(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData), - actParms, pInfo, wpsc, dInfo, f1, f2, f3, model, b1, b2); + SScaledActorHead actHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; + + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + + CAssetId wpsc(in); + CAssetId model(in); + CDamageInfo dInfo(in); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + bool b1 = in.readBool(); + bool b2 = in.readBool(); + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + + return new MP1::CAtomicAlpha(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData), + actParms, pInfo, wpsc, dInfo, f1, f2, f3, model, b1, b2); } CEntity* ScriptLoader::LoadCameraHintTrigger(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 7, "CameraHintTrigger")) - return nullptr; - - SActorHead aHead = LoadActorHead(in, mgr); - zeus::CVector3f scale = 0.5f * zeus::CVector3f::ReadBig(in); - bool active = in.readBool(); - bool b2 = in.readBool(); - bool b3 = in.readBool(); - - zeus::CTransform xfRot = aHead.x10_transform.getRotation(); - if (xfRot == zeus::CTransform::Identity()) - return new CScriptTrigger(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform.origin, - zeus::CAABox(-scale, scale), CDamageInfo(), zeus::CVector3f::skZero, - ETriggerFlags::DetectPlayer, active, b2, b3); - - return new CScriptCameraHintTrigger(mgr.AllocateUniqueId(), active, aHead.x0_name, info, scale, aHead.x10_transform, - b2, b3); -} - -CEntity* ScriptLoader::LoadRumbleEffect(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 6, "RumbleEffect")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f position; - position.readBig(in); - bool active = in.readBool(); - float f1 = in.readFloatBig(); - u32 w1 = in.readUint32Big(); - u32 pFlags = LoadParameterFlags(in); - - return new CScriptSpecialFunction( - mgr.AllocateUniqueId(), name, info, ConvertEditorEulerToTransform4f(zeus::CVector3f::skZero, position), - CScriptSpecialFunction::ESpecialFunction::RumbleEffect, "", f1, w1, pFlags, 0.f, zeus::CVector3f::skZero, - zeus::CColor::skBlack, active, {}, {}, {}, CPlayerState::EItemType::Invalid, -1, -1, -1); -} - -CEntity* ScriptLoader::LoadAmbientAI(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 16, "AmbientAI")) - return nullptr; - - SScaledActorHead head = LoadScaledActorHead(in, mgr); - zeus::CVector3f collisionExtent = zeus::CVector3f::ReadBig(in); - zeus::CVector3f collisionOffset = zeus::CVector3f::ReadBig(in); - float mass = in.readFloatBig(); - CHealthInfo hInfo(in); - CDamageVulnerability dVuln(in); - CAnimationParameters animParms = LoadAnimationParameters(in); - CActorParameters actParms = LoadActorParameters(in); - float alertRange = in.readFloatBig(); - float impactRange = in.readFloatBig(); - s32 alertAnim = in.readInt32Big(); - s32 impactAnim = in.readInt32Big(); - bool active = in.readBool(); - - if (!g_ResFactory->GetResourceTypeById(animParms.GetACSFile())) - return nullptr; - - zeus::CAABox aabox = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, collisionOffset); - - CMaterialList matList(EMaterialTypes::Immovable, EMaterialTypes::NonSolidDamageable); - - CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), head.x40_scale, - animParms.GetInitialAnimation(), true)); - if ((collisionExtent.x() < 0.f || collisionExtent.y() < 0.f || collisionExtent.z() < 0.f) || collisionExtent.isZero()) - aabox = mData.GetBounds(head.x10_transform.getRotation()); - - return new CAmbientAI(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(mData), aabox, - matList, mass, hInfo, dVuln, actParms, alertRange, impactRange, alertAnim, impactAnim, - active); -} - -CEntity* ScriptLoader::LoadAtomicBeta(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 7, "CameraHintTrigger")) return nullptr; + + SActorHead aHead = LoadActorHead(in, mgr); + zeus::CVector3f scale = 0.5f * zeus::CVector3f::ReadBig(in); + bool active = in.readBool(); + bool b2 = in.readBool(); + bool b3 = in.readBool(); + + zeus::CTransform xfRot = aHead.x10_transform.getRotation(); + if (xfRot == zeus::CTransform::Identity()) + return new CScriptTrigger(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform.origin, + zeus::CAABox(-scale, scale), CDamageInfo(), zeus::CVector3f::skZero, + ETriggerFlags::DetectPlayer, active, b2, b3); + + return new CScriptCameraHintTrigger(mgr.AllocateUniqueId(), active, aHead.x0_name, info, scale, aHead.x10_transform, + b2, b3); } -CEntity* ScriptLoader::LoadIceZoomer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ +CEntity* ScriptLoader::LoadRumbleEffect(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 6, "RumbleEffect")) return nullptr; + + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f position; + position.readBig(in); + bool active = in.readBool(); + float f1 = in.readFloatBig(); + u32 w1 = in.readUint32Big(); + u32 pFlags = LoadParameterFlags(in); + + return new CScriptSpecialFunction( + mgr.AllocateUniqueId(), name, info, ConvertEditorEulerToTransform4f(zeus::CVector3f::skZero, position), + CScriptSpecialFunction::ESpecialFunction::RumbleEffect, "", f1, w1, pFlags, 0.f, zeus::CVector3f::skZero, + zeus::CColor::skBlack, active, {}, {}, {}, CPlayerState::EItemType::Invalid, -1, -1, -1); } -CEntity* ScriptLoader::LoadPuffer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 16, "Puffer")) - return nullptr; +CEntity* ScriptLoader::LoadAmbientAI(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 16, "AmbientAI")) + return nullptr; - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; + SScaledActorHead head = LoadScaledActorHead(in, mgr); + zeus::CVector3f collisionExtent = zeus::CVector3f::ReadBig(in); + zeus::CVector3f collisionOffset = zeus::CVector3f::ReadBig(in); + float mass = in.readFloatBig(); + CHealthInfo hInfo(in); + CDamageVulnerability dVuln(in); + CAnimationParameters animParms = LoadAnimationParameters(in); + CActorParameters actParms = LoadActorParameters(in); + float alertRange = in.readFloatBig(); + float impactRange = in.readFloatBig(); + s32 alertAnim = in.readInt32Big(); + s32 impactAnim = in.readInt32Big(); + bool active = in.readBool(); - CPatternedInfo pInfo(in, pair.second); - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; + if (!g_ResFactory->GetResourceTypeById(animParms.GetACSFile())) + return nullptr; - CActorParameters actorParameters = LoadActorParameters(in); - float hoverSpeed = in.readFloatBig(); - CAssetId cloudEffect(in); - CDamageInfo cloudDamage(in); - CAssetId cloudSteam(in); - float f2 = in.readFloatBig(); - bool b1 = in.readBool(); - bool b2 = in.readBool(); - bool b3 = in.readBool(); - CDamageInfo explosionDamage(in); - s16 sfxId = in.readUint16Big(); + zeus::CAABox aabox = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, collisionOffset); - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - aHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - return new MP1::CPuffer(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), - actorParameters, pInfo, hoverSpeed, cloudEffect, cloudDamage, cloudSteam, f2, b1, b2, b3, - explosionDamage, sfxId); + CMaterialList matList(EMaterialTypes::Immovable, EMaterialTypes::NonSolidDamageable); + + CModelData mData(CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), head.x40_scale, + animParms.GetInitialAnimation(), true)); + if ((collisionExtent.x() < 0.f || collisionExtent.y() < 0.f || collisionExtent.z() < 0.f) || collisionExtent.isZero()) + aabox = mData.GetBounds(head.x10_transform.getRotation()); + + return new CAmbientAI(mgr.AllocateUniqueId(), head.x0_name, info, head.x10_transform, std::move(mData), aabox, + matList, mass, hInfo, dVuln, actParms, alertRange, impactRange, alertAnim, impactAnim, active); } -CEntity* ScriptLoader::LoadTryclops(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 10, "Tryclops")) - return nullptr; - - SScaledActorHead actorHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; - - CActorParameters actorParameters = LoadActorParameters(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - - CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), - pInfo.GetAnimationParameters().GetCharacter(), actorHead.x40_scale, - pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - - return new MP1::CTryclops(mgr.AllocateUniqueId(), actorHead.x0_name, info, actorHead.x10_transform, - std::move(mData), pInfo, actorParameters, f1, f2, f3, f4); +CEntity* ScriptLoader::LoadAtomicBeta(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; } -CEntity* ScriptLoader::LoadRidley(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 47, "Ridley")) - return nullptr; - - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; - - CPatternedInfo pInfo(in, pair.second); - CActorParameters actParms = LoadActorParameters(in); - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; - - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - aHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - return new MP1::CRidley(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), pInfo, - actParms, in, propCount); +CEntity* ScriptLoader::LoadIceZoomer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; } -CEntity* ScriptLoader::LoadSeedling(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 14, "Seedling")) - return nullptr; - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); +CEntity* ScriptLoader::LoadPuffer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 16, "Puffer")) + return nullptr; - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; - CPatternedInfo pInfo(in, pair.second); + CPatternedInfo pInfo(in, pair.second); + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; + CActorParameters actorParameters = LoadActorParameters(in); + float hoverSpeed = in.readFloatBig(); + CAssetId cloudEffect(in); + CDamageInfo cloudDamage(in); + CAssetId cloudSteam(in); + float f2 = in.readFloatBig(); + bool b1 = in.readBool(); + bool b2 = in.readBool(); + bool b3 = in.readBool(); + CDamageInfo explosionDamage(in); + s16 sfxId = in.readUint16Big(); - CActorParameters actParms = LoadActorParameters(in); - CAssetId needleId(in); - CAssetId weaponId(in); - CDamageInfo dInfo1(in); - CDamageInfo dInfo2(in); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + aHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + return new MP1::CPuffer(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), + actorParameters, pInfo, hoverSpeed, cloudEffect, cloudDamage, cloudSteam, f2, b1, b2, b3, + explosionDamage, sfxId); +} - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - aHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - return new MP1::CSeedling(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), pInfo, - actParms, needleId, weaponId, dInfo1, dInfo2, f1, f2, f3, f4); +CEntity* ScriptLoader::LoadTryclops(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 10, "Tryclops")) + return nullptr; + + SScaledActorHead actorHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + + if (!pair.first) + return nullptr; + + CPatternedInfo pInfo(in, pair.second); + + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; + + CActorParameters actorParameters = LoadActorParameters(in); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + actorHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + + return new MP1::CTryclops(mgr.AllocateUniqueId(), actorHead.x0_name, info, actorHead.x10_transform, std::move(mData), + pInfo, actorParameters, f1, f2, f3, f4); +} + +CEntity* ScriptLoader::LoadRidley(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 47, "Ridley")) + return nullptr; + + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; + + CPatternedInfo pInfo(in, pair.second); + CActorParameters actParms = LoadActorParameters(in); + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + aHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + return new MP1::CRidley(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), pInfo, + actParms, in, propCount); +} + +CEntity* ScriptLoader::LoadSeedling(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 14, "Seedling")) + return nullptr; + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; + + CPatternedInfo pInfo(in, pair.second); + + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; + + CActorParameters actParms = LoadActorParameters(in); + CAssetId needleId(in); + CAssetId weaponId(in); + CDamageInfo dInfo1(in); + CDamageInfo dInfo2(in); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + aHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + return new MP1::CSeedling(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), pInfo, + actParms, needleId, weaponId, dInfo1, dInfo2, f1, f2, f3, f4); } CEntity* ScriptLoader::LoadThermalHeatFader(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "ThermalHeatFader")) - return nullptr; + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "ThermalHeatFader")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - float fadedLevel = in.readFloatBig(); - float initialLevel = in.readFloatBig(); - return new CScriptDistanceFog(mgr.AllocateUniqueId(), name, info, ERglFogMode::None, zeus::CColor::skBlack, - zeus::CVector2f(), 0.f, zeus::CVector2f(), false, active, fadedLevel, initialLevel, - 0.f, 0.f); + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + float fadedLevel = in.readFloatBig(); + float initialLevel = in.readFloatBig(); + return new CScriptDistanceFog(mgr.AllocateUniqueId(), name, info, ERglFogMode::None, zeus::CColor::skBlack, + zeus::CVector2f(), 0.f, zeus::CVector2f(), false, active, fadedLevel, initialLevel, 0.f, + 0.f); } -CEntity* ScriptLoader::LoadBurrower(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 13, "Burrower")) - return nullptr; +CEntity* ScriptLoader::LoadBurrower(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 13, "Burrower")) + return nullptr; - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - auto pair = CPatternedInfo::HasCorrectParameterCount(in); - if (!pair.first) - return nullptr; + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + auto pair = CPatternedInfo::HasCorrectParameterCount(in); + if (!pair.first) + return nullptr; - CPatternedInfo pInfo(in, pair.second); + CPatternedInfo pInfo(in, pair.second); - if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) - return nullptr; + if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) + return nullptr; - CActorParameters actParms = LoadActorParameters(in); - CAssetId w1(in); - CAssetId w2(in); - CAssetId w3(in); - CDamageInfo dInfo(in); + CActorParameters actParms = LoadActorParameters(in); + CAssetId w1(in); + CAssetId w2(in); + CAssetId w3(in); + CDamageInfo dInfo(in); - CAssetId w4(in); - u32 w5 = in.readUint32Big(); - CAssetId w6(in); + CAssetId w4(in); + u32 w5 = in.readUint32Big(); + CAssetId w6(in); - CModelData mData( - CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), - aHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); + CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(), + aHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true)); - return new MP1::CBurrower(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), pInfo, - actParms, w1, w2, w3, dInfo, w4, w5, w6); + return new MP1::CBurrower(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, std::move(mData), pInfo, + actParms, w1, w2, w3, dInfo, w4, w5, w6); } -CEntity* ScriptLoader::LoadBeam(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 7, "Beam")) - return nullptr; +CEntity* ScriptLoader::LoadBeam(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 7, "Beam")) + return nullptr; - SActorHead aHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - u32 weaponDescId = in.readUint32Big(); - if (!g_ResFactory->GetResourceTypeById(weaponDescId)) - return nullptr; + SActorHead aHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + u32 weaponDescId = in.readUint32Big(); + if (!g_ResFactory->GetResourceTypeById(weaponDescId)) + return nullptr; - CBeamInfo beamInfo(in); - CDamageInfo dInfo(in); - TToken weaponDesc = g_SimplePool->GetObj({SBIG('WPSC'), weaponDescId}); + CBeamInfo beamInfo(in); + CDamageInfo dInfo(in); + TToken weaponDesc = g_SimplePool->GetObj({SBIG('WPSC'), weaponDescId}); - return new CScriptBeam(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, weaponDesc, - beamInfo, dInfo); + return new CScriptBeam(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, weaponDesc, beamInfo, + dInfo); } -CEntity* ScriptLoader::LoadWorldLightFader(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 4, "WorldLightFader")) - return nullptr; +CEntity* ScriptLoader::LoadWorldLightFader(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 4, "WorldLightFader")) + return nullptr; - std::string name = mgr.HashInstanceName(in); - bool active = in.readBool(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); + std::string name = mgr.HashInstanceName(in); + bool active = in.readBool(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); - return new CScriptDistanceFog(mgr.AllocateUniqueId(), name, info, ERglFogMode::None, zeus::CColor::skBlack, - zeus::CVector2f::skZero, 0.f, zeus::CVector2f::skZero, false, active, 0.f, 0.f, f1, - f2); + return new CScriptDistanceFog(mgr.AllocateUniqueId(), name, info, ERglFogMode::None, zeus::CColor::skBlack, + zeus::CVector2f::skZero, 0.f, zeus::CVector2f::skZero, false, active, 0.f, 0.f, f1, f2); } CEntity* ScriptLoader::LoadMetroidPrimeStage2(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - return nullptr; + const CEntityInfo& info) { + return nullptr; } CEntity* ScriptLoader::LoadMetroidPrimeStage1(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 22, "MetroidPrimeStage1")) - return nullptr; - u32 version = in.readUint32Big(); - if (version != 3) - return nullptr; - - SScaledActorHead aHead = LoadScaledActorHead(in, mgr); - bool active = in.readBool(); - float f1 = in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - u32 w1 = in.readUint32Big(); - bool b1 = in.readBool(); - u32 w2 = in.readUint32Big(); - CHealthInfo hInfo1(in); - CHealthInfo hInfo2(in); - u32 w3 = in.readUint32Big(); - rstl::reserved_vector roomParms; - for (int i = 0; i < 4; ++i) - roomParms.emplace_back(in); - u32 w4 = in.readUint32Big(); - u32 w5 = in.readUint32Big(); - MP1::SPrimeExoParameters primeParms(in); - - return new MP1::CMetroidPrimeRelay(mgr.AllocateUniqueId(), aHead.x0_name, info, active, aHead.x10_transform, - aHead.x40_scale, std::move(primeParms), f1, f2, f3, w1, b1, w2, hInfo1, hInfo2, - w3, w4, w5, std::move(roomParms)); -} - -CEntity* ScriptLoader::LoadMazeNode(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 10, "MazeNode")) - return nullptr; - - SActorHead aHead = LoadActorHead(in, mgr); - bool active = in.readBool(); - u32 w1 = in.readUint32Big(); - u32 w2 = in.readUint32Big(); - u32 w3 = in.readUint32Big(); - zeus::CVector3f vec1 = zeus::CVector3f::ReadBig(in); - zeus::CVector3f vec2 = zeus::CVector3f::ReadBig(in); - zeus::CVector3f vec3 = zeus::CVector3f::ReadBig(in); - - return new CScriptMazeNode(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, w1, w2, w3, - vec1, vec2, vec3); -} - -CEntity* ScriptLoader::LoadOmegaPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 22, "MetroidPrimeStage1")) return nullptr; + u32 version = in.readUint32Big(); + if (version != 3) + return nullptr; + + SScaledActorHead aHead = LoadScaledActorHead(in, mgr); + bool active = in.readBool(); + float f1 = in.readFloatBig(); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + u32 w1 = in.readUint32Big(); + bool b1 = in.readBool(); + u32 w2 = in.readUint32Big(); + CHealthInfo hInfo1(in); + CHealthInfo hInfo2(in); + u32 w3 = in.readUint32Big(); + rstl::reserved_vector roomParms; + for (int i = 0; i < 4; ++i) + roomParms.emplace_back(in); + u32 w4 = in.readUint32Big(); + u32 w5 = in.readUint32Big(); + MP1::SPrimeExoParameters primeParms(in); + + return new MP1::CMetroidPrimeRelay(mgr.AllocateUniqueId(), aHead.x0_name, info, active, aHead.x10_transform, + aHead.x40_scale, std::move(primeParms), f1, f2, f3, w1, b1, w2, hInfo1, hInfo2, w3, + w4, w5, std::move(roomParms)); } -CEntity* ScriptLoader::LoadPhazonPool(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ +CEntity* ScriptLoader::LoadMazeNode(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 10, "MazeNode")) return nullptr; + + SActorHead aHead = LoadActorHead(in, mgr); + bool active = in.readBool(); + u32 w1 = in.readUint32Big(); + u32 w2 = in.readUint32Big(); + u32 w3 = in.readUint32Big(); + zeus::CVector3f vec1 = zeus::CVector3f::ReadBig(in); + zeus::CVector3f vec2 = zeus::CVector3f::ReadBig(in); + zeus::CVector3f vec3 = zeus::CVector3f::ReadBig(in); + + return new CScriptMazeNode(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform, active, w1, w2, w3, vec1, + vec2, vec3); +} + +CEntity* ScriptLoader::LoadOmegaPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadPhazonPool(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; } CEntity* ScriptLoader::LoadPhazonHealingNodule(CStateManager& mgr, CInputStream& in, int propCount, - const CEntityInfo& info) -{ + const CEntityInfo& info) { + return nullptr; +} + +CEntity* ScriptLoader::LoadNewCameraShaker(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 8, "NewCameraShaker")) return nullptr; + + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f sfxPos = zeus::CVector3f::ReadBig(in); + bool active = in.readBool(); + u32 flags = LoadParameterFlags(in); + float duration = in.readFloatBig(); + float sfxDist = in.readFloatBig(); + CCameraShakerComponent shakerX = CCameraShakerComponent::LoadNewCameraShakerComponent(in); + CCameraShakerComponent shakerY = CCameraShakerComponent::LoadNewCameraShakerComponent(in); + CCameraShakerComponent shakerZ = CCameraShakerComponent::LoadNewCameraShakerComponent(in); + + CCameraShakeData shakeData(duration, sfxDist, flags, sfxPos, shakerX, shakerY, shakerZ); + + return new CScriptCameraShaker(mgr.AllocateUniqueId(), name, info, active, shakeData); } -CEntity* ScriptLoader::LoadNewCameraShaker(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 8, "NewCameraShaker")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f sfxPos = zeus::CVector3f::ReadBig(in); - bool active = in.readBool(); - u32 flags = LoadParameterFlags(in); - float duration = in.readFloatBig(); - float sfxDist = in.readFloatBig(); - CCameraShakerComponent shakerX = CCameraShakerComponent::LoadNewCameraShakerComponent(in); - CCameraShakerComponent shakerY = CCameraShakerComponent::LoadNewCameraShakerComponent(in); - CCameraShakerComponent shakerZ = CCameraShakerComponent::LoadNewCameraShakerComponent(in); - - CCameraShakeData shakeData(duration, sfxDist, flags, sfxPos, shakerX, shakerY, shakerZ); - - return new CScriptCameraShaker(mgr.AllocateUniqueId(), name, info, active, shakeData); -} - -CEntity* ScriptLoader::LoadShadowProjector(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ - if (!EnsurePropertyCount(propCount, 10, "ShadowProjector")) - return nullptr; - - std::string name = mgr.HashInstanceName(in); - zeus::CVector3f position(zeus::CVector3f::ReadBig(in)); - bool b1 = in.readBool(); - float f1 = in.readFloatBig(); - zeus::CVector3f vec2(zeus::CVector3f::ReadBig(in)); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); - float f4 = in.readFloatBig(); - bool b2 = in.readBool(); - u32 w1 = in.readUint32Big(); - return new CScriptShadowProjector(mgr.AllocateUniqueId(), name, info, zeus::CTransform::Translate(position), b1, - vec2, b2, f1, f2, f3, f4, w1); -} - -CEntity* ScriptLoader::LoadEnergyBall(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) -{ +CEntity* ScriptLoader::LoadShadowProjector(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (!EnsurePropertyCount(propCount, 10, "ShadowProjector")) return nullptr; + + std::string name = mgr.HashInstanceName(in); + zeus::CVector3f position(zeus::CVector3f::ReadBig(in)); + bool b1 = in.readBool(); + float f1 = in.readFloatBig(); + zeus::CVector3f vec2(zeus::CVector3f::ReadBig(in)); + float f2 = in.readFloatBig(); + float f3 = in.readFloatBig(); + float f4 = in.readFloatBig(); + bool b2 = in.readBool(); + u32 w1 = in.readUint32Big(); + return new CScriptShadowProjector(mgr.AllocateUniqueId(), name, info, zeus::CTransform::Translate(position), b1, vec2, + b2, f1, f2, f3, f4, w1); } -}// namespace urde + +CEntity* ScriptLoader::LoadEnergyBall(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) { + return nullptr; +} +} // namespace urde diff --git a/Runtime/World/ScriptLoader.hpp b/Runtime/World/ScriptLoader.hpp index 4dd1f6452..024f3480c 100644 --- a/Runtime/World/ScriptLoader.hpp +++ b/Runtime/World/ScriptLoader.hpp @@ -3,8 +3,7 @@ #include "IOStreams.hpp" #include "zeus/CTransform.hpp" -namespace urde -{ +namespace urde { class CStateManager; class CEntityInfo; class CEntity; @@ -17,150 +16,151 @@ class CAnimationParameters; class CFluidUVMotion; class CCameraShakeData; -typedef CEntity*(*FScriptLoader)(CStateManager& mgr, CInputStream& in, - int propCount, const CEntityInfo& info); +typedef CEntity* (*FScriptLoader)(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); -class ScriptLoader -{ +class ScriptLoader { public: - static u32 LoadParameterFlags(CInputStream& in); - static CGrappleParameters LoadGrappleParameters(CInputStream& in); - static CActorParameters LoadActorParameters(CInputStream& in); - static CVisorParameters LoadVisorParameters(CInputStream& in); - static CScannableParameters LoadScannableParameters(CInputStream& in); - static CLightParameters LoadLightParameters(CInputStream& in); - static CAnimationParameters LoadAnimationParameters(CInputStream& in); - static CFluidUVMotion LoadFluidUVMotion(CInputStream& in); - static zeus::CTransform ConvertEditorEulerToTransform4f(const zeus::CVector3f& orientation, - const zeus::CVector3f& position); + static u32 LoadParameterFlags(CInputStream& in); + static CGrappleParameters LoadGrappleParameters(CInputStream& in); + static CActorParameters LoadActorParameters(CInputStream& in); + static CVisorParameters LoadVisorParameters(CInputStream& in); + static CScannableParameters LoadScannableParameters(CInputStream& in); + static CLightParameters LoadLightParameters(CInputStream& in); + static CAnimationParameters LoadAnimationParameters(CInputStream& in); + static CFluidUVMotion LoadFluidUVMotion(CInputStream& in); + static zeus::CTransform ConvertEditorEulerToTransform4f(const zeus::CVector3f& orientation, + const zeus::CVector3f& position); - static CEntity* LoadActor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadDoor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadTimer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCounter(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadEffect(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPlatform(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSound(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadGenerator(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadDock(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCameraWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadNewIntroBoss(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSpawnPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCameraHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPickup(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadMemoryRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadRandomRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadBeetle(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadHUDMemo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCameraFilterKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCameraBlurKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadDamageableTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadDebris(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCameraShaker(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadActorKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadWater(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadWarWasp(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSpacePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadFlyingPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadElitePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadMetroidBeta(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadChozoGhost(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCoverPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSpiderBallWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadBloodFlower(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadFlickerBat(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPathCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadGrapplePoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPuddleSpore(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadDebugCameraWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSpiderBallAttractionSurface(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPuddleToadGamma(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadDistanceFog(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadFireFlea(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadMetaree(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadDockAreaChange(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadActorRotate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSpecialFunction(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSpankWeed(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadParasite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPlayerHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadRipper(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPickupGenerator(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadAIKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPointOfInterest(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadDrone(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadMetroidAlpha(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadDebrisExtended(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSteam(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadRipple(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadBallTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadTargetingPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadEMPulse(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadIceSheegoth(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPlayerActor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadFlaahgra(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadAreaAttributes(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadFishCloud(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadFishCloudModifier(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadVisorFlare(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadWorldTeleporter(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadVisorGoo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadJellyZap(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadControllerAction(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSwitch(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPlayerStateChange(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadThardus(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadWallCrawlerSwarm(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadAiJumpPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadFlaahgraTentacle(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadRoomAcoustics(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadColorModulate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadThardusRockProjectile(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadMidi(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadStreamedAudio(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadRepulsor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadGunTurret(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadFogVolume(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadBabygoth(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadEyeball(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadRadialDamage(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCameraPitchVolume(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadEnvFxDensityController(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadMagdolite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadTeamAIMgr(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSnakeWeedSwarm(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadActorContraption(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadOculus(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadGeemer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSpindleCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadAtomicAlpha(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadCameraHintTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadRumbleEffect(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadAmbientAI(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadAtomicBeta(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadIceZoomer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPuffer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadTryclops(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadRidley(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadSeedling(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadThermalHeatFader(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadBurrower(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadBeam(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadWorldLightFader(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadMetroidPrimeStage2(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadMetroidPrimeStage1(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadMazeNode(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadOmegaPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPhazonPool(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadPhazonHealingNodule(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadNewCameraShaker(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadShadowProjector(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); - static CEntity* LoadEnergyBall(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadActor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadDoor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadTimer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadCounter(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadEffect(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPlatform(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSound(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadGenerator(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadDock(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadCameraWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadNewIntroBoss(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSpawnPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadCameraHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPickup(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadMemoryRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadRandomRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadRelay(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadBeetle(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadHUDMemo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadCameraFilterKeyframe(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info); + static CEntity* LoadCameraBlurKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadDamageableTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadDebris(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadCameraShaker(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadActorKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadWater(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadWarWasp(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSpacePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadFlyingPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadElitePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadMetroidBeta(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadChozoGhost(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadCoverPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSpiderBallWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadBloodFlower(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadFlickerBat(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPathCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadGrapplePoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPuddleSpore(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadDebugCameraWaypoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSpiderBallAttractionSurface(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info); + static CEntity* LoadPuddleToadGamma(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadDistanceFog(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadFireFlea(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadMetaree(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadDockAreaChange(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadActorRotate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSpecialFunction(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSpankWeed(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadParasite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPlayerHint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadRipper(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPickupGenerator(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadAIKeyframe(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPointOfInterest(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadDrone(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadMetroidAlpha(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadDebrisExtended(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSteam(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadRipple(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadBallTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadTargetingPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadEMPulse(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadIceSheegoth(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPlayerActor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadFlaahgra(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadAreaAttributes(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadFishCloud(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadFishCloudModifier(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadVisorFlare(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadWorldTeleporter(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadVisorGoo(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadJellyZap(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadControllerAction(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSwitch(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPlayerStateChange(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadThardus(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadWallCrawlerSwarm(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadAiJumpPoint(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadFlaahgraTentacle(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadRoomAcoustics(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadColorModulate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadThardusRockProjectile(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info); + static CEntity* LoadMidi(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadStreamedAudio(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadRepulsor(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadGunTurret(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadFogVolume(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadBabygoth(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadEyeball(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadRadialDamage(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadCameraPitchVolume(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadEnvFxDensityController(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info); + static CEntity* LoadMagdolite(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadTeamAIMgr(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSnakeWeedSwarm(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadActorContraption(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadOculus(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadGeemer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSpindleCamera(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadAtomicAlpha(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadCameraHintTrigger(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadRumbleEffect(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadAmbientAI(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadAtomicBeta(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadIceZoomer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPuffer(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadTryclops(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadRidley(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadSeedling(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadThermalHeatFader(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadBurrower(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadBeam(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadWorldLightFader(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadMetroidPrimeStage2(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadMetroidPrimeStage1(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadMazeNode(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadOmegaPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPhazonPool(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadPhazonHealingNodule(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadNewCameraShaker(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadShadowProjector(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); + static CEntity* LoadEnergyBall(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info); }; -} - +} // namespace urde diff --git a/Runtime/World/ScriptObjectSupport.cpp b/Runtime/World/ScriptObjectSupport.cpp index 6d613169b..212e80e30 100644 --- a/Runtime/World/ScriptObjectSupport.cpp +++ b/Runtime/World/ScriptObjectSupport.cpp @@ -2,240 +2,445 @@ using namespace std::literals; -namespace urde -{ +namespace urde { -std::string_view ScriptObjectTypeToStr(EScriptObjectType type) -{ - switch (type) - { - case EScriptObjectType::Actor: return "Actor"sv; - case EScriptObjectType::Waypoint: return "Waypoint"sv; - case EScriptObjectType::Door: return "Door"sv; - case EScriptObjectType::Trigger: return "Trigger"sv; - case EScriptObjectType::Timer: return "Timer"sv; - case EScriptObjectType::Counter: return "Counter"sv; - case EScriptObjectType::Effect: return "Effect"sv; - case EScriptObjectType::Platform: return "Platform"sv; - case EScriptObjectType::Sound: return "Sound"sv; - case EScriptObjectType::Generator: return "Generator"sv; - case EScriptObjectType::Dock: return "Dock"sv; - case EScriptObjectType::Camera: return "Camera"sv; - case EScriptObjectType::CameraWaypoint: return "CameraWaypoint"sv; - case EScriptObjectType::NewIntroBoss: return "NewIntroBoss"sv; - case EScriptObjectType::SpawnPoint: return "SpawnPoint"sv; - case EScriptObjectType::CameraHint: return "CameraHint"sv; - case EScriptObjectType::Pickup: return "Pickup"sv; - case EScriptObjectType::MemoryRelay: return "MemoryRelay"sv; - case EScriptObjectType::RandomRelay: return "RandomRelay"sv; - case EScriptObjectType::Relay: return "Relay"sv; - case EScriptObjectType::Beetle: return "Beetle"sv; - case EScriptObjectType::HUDMemo: return "HUDMemo"sv; - case EScriptObjectType::CameraFilterKeyframe: return "CameraFilterKeyframe"sv; - case EScriptObjectType::CameraBlurKeyframe: return "CameraBlurKeyframe"sv; - case EScriptObjectType::DamageableTrigger: return "DamageableTrigger"sv; - case EScriptObjectType::Debris: return "Debris"sv; - case EScriptObjectType::CameraShaker: return "CameraShaker"sv; - case EScriptObjectType::ActorKeyframe: return "ActorKeyframe"sv; - case EScriptObjectType::Water: return "Water"sv; - case EScriptObjectType::Warwasp: return "Warwasp"sv; - case EScriptObjectType::SpacePirate: return "SpacePirate"sv; - case EScriptObjectType::FlyingPirate: return "FlyingPirate"sv; - case EScriptObjectType::ElitePirate: return "ElitePirate"sv; - case EScriptObjectType::MetroidBeta: return "MetroidBeta"sv; - case EScriptObjectType::ChozoGhost: return "ChozoGhost"sv; - case EScriptObjectType::CoverPoint: return "CoverPoint"sv; - case EScriptObjectType::SpiderBallWaypoint: return "SpiderBallWaypoint"sv; - case EScriptObjectType::BloodFlower: return "BloodFlower"sv; - case EScriptObjectType::FlickerBat: return "FlickerBat"sv; - case EScriptObjectType::PathCamera: return "PathCamera"sv; - case EScriptObjectType::GrapplePoint: return "GrapplePoint"sv; - case EScriptObjectType::PuddleSpore: return "PuddleSpore"sv; - case EScriptObjectType::DebugCameraWaypoint: return "DebugCameraWaypoint"sv; - case EScriptObjectType::SpiderBallAttractionSurface: return "SpiderBallAttractionSurface"sv; - case EScriptObjectType::PuddleToadGamma: return "PuddleToadGamma"sv; - case EScriptObjectType::DistanceFog: return "DistanceFog"sv; - case EScriptObjectType::FireFlea: return "FireFlea"sv; - case EScriptObjectType::Metaree: return "Metaree"sv; - case EScriptObjectType::DockAreaChange: return "DockAreaChange"sv; - case EScriptObjectType::ActorRotate: return "ActorRotate"sv; - case EScriptObjectType::SpecialFunction: return "SpecialFunction"sv; - case EScriptObjectType::SpankWeed: return "SpankWeed"sv; - case EScriptObjectType::Parasite: return "Parasite"sv; - case EScriptObjectType::PlayerHint: return "PlayerHint"sv; - case EScriptObjectType::Ripper: return "Ripper"sv; - case EScriptObjectType::PickupGenerator: return "PickupGenerator"sv; - case EScriptObjectType::AIKeyframe: return "AIKeyframe"sv; - case EScriptObjectType::PointOfInterest: return "PointOfInterest"sv; - case EScriptObjectType::Drone: return "Drone"sv; - case EScriptObjectType::MetroidAlpha: return "MetroidAlpha"sv; - case EScriptObjectType::DebrisExtended: return "DebrisExtended"sv; - case EScriptObjectType::Steam: return "Steam"sv; - case EScriptObjectType::Ripple: return "Ripple"sv; - case EScriptObjectType::BallTrigger: return "BallTrigger"sv; - case EScriptObjectType::TargetingPoint: return "TargetingPoint"sv; - case EScriptObjectType::EMPulse: return "EMPulse"sv; - case EScriptObjectType::IceSheegoth: return "IceSheegoth"sv; - case EScriptObjectType::PlayerActor: return "PlayerActor"sv; - case EScriptObjectType::Flaahgra: return "Flaahgra"sv; - case EScriptObjectType::AreaAttributes: return "AreaAttributes"sv; - case EScriptObjectType::FishCloud: return "FishCloud"sv; - case EScriptObjectType::FishCloudModifier: return "FishCloudModifier"sv; - case EScriptObjectType::VisorFlare: return "VisorFlare"sv; - case EScriptObjectType::WorldTeleporter: return "WorldTeleporter"sv; - case EScriptObjectType::VisorGoo: return "VisorGoo"sv; - case EScriptObjectType::JellyZap: return "JellyZap"sv; - case EScriptObjectType::ControllerAction: return "ControllerAction"sv; - case EScriptObjectType::Switch: return "Switch"sv; - case EScriptObjectType::PlayerStateChange: return "PlayerStateChange"sv; - case EScriptObjectType::Thardus: return "Thardus"sv; - case EScriptObjectType::WallCrawlerSwarm: return "WallCrawlerSwarm"sv; - case EScriptObjectType::AIJumpPoint: return "AIJumpPoint"sv; - case EScriptObjectType::FlaahgraTentacle: return "FlaahgraTentacle"sv; - case EScriptObjectType::RoomAcoustics: return "RoomAcoustics"sv; - case EScriptObjectType::ColorModulate: return "ColorModulate"sv; - case EScriptObjectType::ThardusRockProjectile: return "ThardusRockProjectile"sv; - case EScriptObjectType::Midi: return "Midi"sv; - case EScriptObjectType::StreamedAudio: return "StreamedAudio"sv; - case EScriptObjectType::WorldTeleporterToo: return "WorldTeleporterToo"sv; - case EScriptObjectType::Repulsor: return "Repulsor"sv; - case EScriptObjectType::GunTurret: return "GunTurret"sv; - case EScriptObjectType::FogVolume: return "FogVolume"sv; - case EScriptObjectType::Babygoth: return "Babygoth"sv; - case EScriptObjectType::Eyeball: return "Eyeball"sv; - case EScriptObjectType::RadialDamage: return "RadialDamage"sv; - case EScriptObjectType::CameraPitchVolume: return "CameraPitchVolume"sv; - case EScriptObjectType::EnvFxDensityController: return "EnvFxDensityController"sv; - case EScriptObjectType::Magdolite: return "Magdolite"sv; - case EScriptObjectType::TeamAIMgr: return "TeamAIMgr"sv; - case EScriptObjectType::SnakeWeedSwarm: return "SnakeWeedSwarm"sv; - case EScriptObjectType::ActorContraption: return "ActorContraption"sv; - case EScriptObjectType::Oculus: return "Oculus"sv; - case EScriptObjectType::Geemer: return "Geemer"sv; - case EScriptObjectType::SpindleCamera: return "SpindleCamera"sv; - case EScriptObjectType::AtomicAlpha: return "AtomicAlpha"sv; - case EScriptObjectType::CameraHintTrigger: return "CameraHintTrigger"sv; - case EScriptObjectType::RumbleEffect: return "RumbleEffect"sv; - case EScriptObjectType::AmbientAI: return "AmbientAI"sv; - case EScriptObjectType::AtomicBeta: return "AtomicBeta"sv; - case EScriptObjectType::IceZoomer: return "IceZoomer"sv; - case EScriptObjectType::Puffer: return "Puffer"sv; - case EScriptObjectType::Tryclops: return "Tryclops"sv; - case EScriptObjectType::Ridley: return "Ridley"sv; - case EScriptObjectType::Seedling: return "Seedling"sv; - case EScriptObjectType::ThermalHeatFader: return "ThermalHeatFader"sv; - case EScriptObjectType::Burrower: return "Burrower"sv; - case EScriptObjectType::ScriptBeam: return "ScriptBeam"sv; - case EScriptObjectType::WorldLightFader: return "WorldLightFader"sv; - case EScriptObjectType::MetroidPrimeStage2: return "MetroidPrimeStage2"sv; - case EScriptObjectType::MetroidPrimeStage1: return "MetroidPrimeStage1"sv; - case EScriptObjectType::MazeNode: return "MazeNode"sv; - case EScriptObjectType::OmegaPirate: return "OmegaPirate"sv; - case EScriptObjectType::PhazonPool: return "PhazonPool"sv; - case EScriptObjectType::PhazonHealingNodule: return "PhazonHealingNodule"sv; - case EScriptObjectType::NewCameraShaker: return "NewCameraShaker"sv; - case EScriptObjectType::ShadowProjector: return "ShadowProjector"sv; - case EScriptObjectType::EnergyBall: return "EnergyBall"sv; - default: return "..."sv; - } +std::string_view ScriptObjectTypeToStr(EScriptObjectType type) { + switch (type) { + case EScriptObjectType::Actor: + return "Actor"sv; + case EScriptObjectType::Waypoint: + return "Waypoint"sv; + case EScriptObjectType::Door: + return "Door"sv; + case EScriptObjectType::Trigger: + return "Trigger"sv; + case EScriptObjectType::Timer: + return "Timer"sv; + case EScriptObjectType::Counter: + return "Counter"sv; + case EScriptObjectType::Effect: + return "Effect"sv; + case EScriptObjectType::Platform: + return "Platform"sv; + case EScriptObjectType::Sound: + return "Sound"sv; + case EScriptObjectType::Generator: + return "Generator"sv; + case EScriptObjectType::Dock: + return "Dock"sv; + case EScriptObjectType::Camera: + return "Camera"sv; + case EScriptObjectType::CameraWaypoint: + return "CameraWaypoint"sv; + case EScriptObjectType::NewIntroBoss: + return "NewIntroBoss"sv; + case EScriptObjectType::SpawnPoint: + return "SpawnPoint"sv; + case EScriptObjectType::CameraHint: + return "CameraHint"sv; + case EScriptObjectType::Pickup: + return "Pickup"sv; + case EScriptObjectType::MemoryRelay: + return "MemoryRelay"sv; + case EScriptObjectType::RandomRelay: + return "RandomRelay"sv; + case EScriptObjectType::Relay: + return "Relay"sv; + case EScriptObjectType::Beetle: + return "Beetle"sv; + case EScriptObjectType::HUDMemo: + return "HUDMemo"sv; + case EScriptObjectType::CameraFilterKeyframe: + return "CameraFilterKeyframe"sv; + case EScriptObjectType::CameraBlurKeyframe: + return "CameraBlurKeyframe"sv; + case EScriptObjectType::DamageableTrigger: + return "DamageableTrigger"sv; + case EScriptObjectType::Debris: + return "Debris"sv; + case EScriptObjectType::CameraShaker: + return "CameraShaker"sv; + case EScriptObjectType::ActorKeyframe: + return "ActorKeyframe"sv; + case EScriptObjectType::Water: + return "Water"sv; + case EScriptObjectType::Warwasp: + return "Warwasp"sv; + case EScriptObjectType::SpacePirate: + return "SpacePirate"sv; + case EScriptObjectType::FlyingPirate: + return "FlyingPirate"sv; + case EScriptObjectType::ElitePirate: + return "ElitePirate"sv; + case EScriptObjectType::MetroidBeta: + return "MetroidBeta"sv; + case EScriptObjectType::ChozoGhost: + return "ChozoGhost"sv; + case EScriptObjectType::CoverPoint: + return "CoverPoint"sv; + case EScriptObjectType::SpiderBallWaypoint: + return "SpiderBallWaypoint"sv; + case EScriptObjectType::BloodFlower: + return "BloodFlower"sv; + case EScriptObjectType::FlickerBat: + return "FlickerBat"sv; + case EScriptObjectType::PathCamera: + return "PathCamera"sv; + case EScriptObjectType::GrapplePoint: + return "GrapplePoint"sv; + case EScriptObjectType::PuddleSpore: + return "PuddleSpore"sv; + case EScriptObjectType::DebugCameraWaypoint: + return "DebugCameraWaypoint"sv; + case EScriptObjectType::SpiderBallAttractionSurface: + return "SpiderBallAttractionSurface"sv; + case EScriptObjectType::PuddleToadGamma: + return "PuddleToadGamma"sv; + case EScriptObjectType::DistanceFog: + return "DistanceFog"sv; + case EScriptObjectType::FireFlea: + return "FireFlea"sv; + case EScriptObjectType::Metaree: + return "Metaree"sv; + case EScriptObjectType::DockAreaChange: + return "DockAreaChange"sv; + case EScriptObjectType::ActorRotate: + return "ActorRotate"sv; + case EScriptObjectType::SpecialFunction: + return "SpecialFunction"sv; + case EScriptObjectType::SpankWeed: + return "SpankWeed"sv; + case EScriptObjectType::Parasite: + return "Parasite"sv; + case EScriptObjectType::PlayerHint: + return "PlayerHint"sv; + case EScriptObjectType::Ripper: + return "Ripper"sv; + case EScriptObjectType::PickupGenerator: + return "PickupGenerator"sv; + case EScriptObjectType::AIKeyframe: + return "AIKeyframe"sv; + case EScriptObjectType::PointOfInterest: + return "PointOfInterest"sv; + case EScriptObjectType::Drone: + return "Drone"sv; + case EScriptObjectType::MetroidAlpha: + return "MetroidAlpha"sv; + case EScriptObjectType::DebrisExtended: + return "DebrisExtended"sv; + case EScriptObjectType::Steam: + return "Steam"sv; + case EScriptObjectType::Ripple: + return "Ripple"sv; + case EScriptObjectType::BallTrigger: + return "BallTrigger"sv; + case EScriptObjectType::TargetingPoint: + return "TargetingPoint"sv; + case EScriptObjectType::EMPulse: + return "EMPulse"sv; + case EScriptObjectType::IceSheegoth: + return "IceSheegoth"sv; + case EScriptObjectType::PlayerActor: + return "PlayerActor"sv; + case EScriptObjectType::Flaahgra: + return "Flaahgra"sv; + case EScriptObjectType::AreaAttributes: + return "AreaAttributes"sv; + case EScriptObjectType::FishCloud: + return "FishCloud"sv; + case EScriptObjectType::FishCloudModifier: + return "FishCloudModifier"sv; + case EScriptObjectType::VisorFlare: + return "VisorFlare"sv; + case EScriptObjectType::WorldTeleporter: + return "WorldTeleporter"sv; + case EScriptObjectType::VisorGoo: + return "VisorGoo"sv; + case EScriptObjectType::JellyZap: + return "JellyZap"sv; + case EScriptObjectType::ControllerAction: + return "ControllerAction"sv; + case EScriptObjectType::Switch: + return "Switch"sv; + case EScriptObjectType::PlayerStateChange: + return "PlayerStateChange"sv; + case EScriptObjectType::Thardus: + return "Thardus"sv; + case EScriptObjectType::WallCrawlerSwarm: + return "WallCrawlerSwarm"sv; + case EScriptObjectType::AIJumpPoint: + return "AIJumpPoint"sv; + case EScriptObjectType::FlaahgraTentacle: + return "FlaahgraTentacle"sv; + case EScriptObjectType::RoomAcoustics: + return "RoomAcoustics"sv; + case EScriptObjectType::ColorModulate: + return "ColorModulate"sv; + case EScriptObjectType::ThardusRockProjectile: + return "ThardusRockProjectile"sv; + case EScriptObjectType::Midi: + return "Midi"sv; + case EScriptObjectType::StreamedAudio: + return "StreamedAudio"sv; + case EScriptObjectType::WorldTeleporterToo: + return "WorldTeleporterToo"sv; + case EScriptObjectType::Repulsor: + return "Repulsor"sv; + case EScriptObjectType::GunTurret: + return "GunTurret"sv; + case EScriptObjectType::FogVolume: + return "FogVolume"sv; + case EScriptObjectType::Babygoth: + return "Babygoth"sv; + case EScriptObjectType::Eyeball: + return "Eyeball"sv; + case EScriptObjectType::RadialDamage: + return "RadialDamage"sv; + case EScriptObjectType::CameraPitchVolume: + return "CameraPitchVolume"sv; + case EScriptObjectType::EnvFxDensityController: + return "EnvFxDensityController"sv; + case EScriptObjectType::Magdolite: + return "Magdolite"sv; + case EScriptObjectType::TeamAIMgr: + return "TeamAIMgr"sv; + case EScriptObjectType::SnakeWeedSwarm: + return "SnakeWeedSwarm"sv; + case EScriptObjectType::ActorContraption: + return "ActorContraption"sv; + case EScriptObjectType::Oculus: + return "Oculus"sv; + case EScriptObjectType::Geemer: + return "Geemer"sv; + case EScriptObjectType::SpindleCamera: + return "SpindleCamera"sv; + case EScriptObjectType::AtomicAlpha: + return "AtomicAlpha"sv; + case EScriptObjectType::CameraHintTrigger: + return "CameraHintTrigger"sv; + case EScriptObjectType::RumbleEffect: + return "RumbleEffect"sv; + case EScriptObjectType::AmbientAI: + return "AmbientAI"sv; + case EScriptObjectType::AtomicBeta: + return "AtomicBeta"sv; + case EScriptObjectType::IceZoomer: + return "IceZoomer"sv; + case EScriptObjectType::Puffer: + return "Puffer"sv; + case EScriptObjectType::Tryclops: + return "Tryclops"sv; + case EScriptObjectType::Ridley: + return "Ridley"sv; + case EScriptObjectType::Seedling: + return "Seedling"sv; + case EScriptObjectType::ThermalHeatFader: + return "ThermalHeatFader"sv; + case EScriptObjectType::Burrower: + return "Burrower"sv; + case EScriptObjectType::ScriptBeam: + return "ScriptBeam"sv; + case EScriptObjectType::WorldLightFader: + return "WorldLightFader"sv; + case EScriptObjectType::MetroidPrimeStage2: + return "MetroidPrimeStage2"sv; + case EScriptObjectType::MetroidPrimeStage1: + return "MetroidPrimeStage1"sv; + case EScriptObjectType::MazeNode: + return "MazeNode"sv; + case EScriptObjectType::OmegaPirate: + return "OmegaPirate"sv; + case EScriptObjectType::PhazonPool: + return "PhazonPool"sv; + case EScriptObjectType::PhazonHealingNodule: + return "PhazonHealingNodule"sv; + case EScriptObjectType::NewCameraShaker: + return "NewCameraShaker"sv; + case EScriptObjectType::ShadowProjector: + return "ShadowProjector"sv; + case EScriptObjectType::EnergyBall: + return "EnergyBall"sv; + default: + return "..."sv; + } } -std::string_view ScriptObjectStateToStr(EScriptObjectState state) -{ - switch (state) - { - case EScriptObjectState::Active: return "Active"sv; - case EScriptObjectState::Arrived: return "Arrived"sv; - case EScriptObjectState::Closed: return "Closed"sv; - case EScriptObjectState::Entered: return "Entered"sv; - case EScriptObjectState::Exited: return "Exited"sv; - case EScriptObjectState::Inactive: return "Inactive"sv; - case EScriptObjectState::Inside: return "Inside"sv; - case EScriptObjectState::MaxReached: return "MaxReached"sv; - case EScriptObjectState::Open: return "Open"sv; - case EScriptObjectState::Zero: return "Zero"sv; - case EScriptObjectState::Attack: return "Attack"sv; - case EScriptObjectState::CloseIn: return "CloseIn"sv; - case EScriptObjectState::Retreat: return "Retreat"sv; - case EScriptObjectState::Patrol: return "Patrol"sv; - case EScriptObjectState::Dead: return "Dead"sv; - case EScriptObjectState::CameraPath: return "CameraPath"sv; - case EScriptObjectState::CameraTarget: return "CameraTarget"sv; - case EScriptObjectState::DeactivateState: return "DeactivateState"sv; - case EScriptObjectState::Play: return "Play"sv; - case EScriptObjectState::MassiveDeath: return "DeathExplosion"sv; - case EScriptObjectState::DeathRattle: return "DeathRattle"sv; - case EScriptObjectState::AboutToMassivelyDie: return "AboutToDie"sv; - case EScriptObjectState::Damage: return "Damage"sv; - case EScriptObjectState::InvulnDamage: return "InvulnDamage"sv; - case EScriptObjectState::MassiveFrozenDeath: return "IceDeathExplosion"sv; - case EScriptObjectState::Modify: return "Modify"sv; - case EScriptObjectState::ScanStart: return "ScanStart"sv; - case EScriptObjectState::ScanProcessing: return "ScanProcessing"sv; - case EScriptObjectState::ScanDone: return "ScanDone"sv; - case EScriptObjectState::UnFrozen: return "UnFrozen"sv; - case EScriptObjectState::Default: return "Default"sv; - case EScriptObjectState::ReflectedDamage: return "ReflectedDamage"sv; - case EScriptObjectState::InheritBounds: return "InheritBounds"sv; - default: return "..."sv; - } +std::string_view ScriptObjectStateToStr(EScriptObjectState state) { + switch (state) { + case EScriptObjectState::Active: + return "Active"sv; + case EScriptObjectState::Arrived: + return "Arrived"sv; + case EScriptObjectState::Closed: + return "Closed"sv; + case EScriptObjectState::Entered: + return "Entered"sv; + case EScriptObjectState::Exited: + return "Exited"sv; + case EScriptObjectState::Inactive: + return "Inactive"sv; + case EScriptObjectState::Inside: + return "Inside"sv; + case EScriptObjectState::MaxReached: + return "MaxReached"sv; + case EScriptObjectState::Open: + return "Open"sv; + case EScriptObjectState::Zero: + return "Zero"sv; + case EScriptObjectState::Attack: + return "Attack"sv; + case EScriptObjectState::CloseIn: + return "CloseIn"sv; + case EScriptObjectState::Retreat: + return "Retreat"sv; + case EScriptObjectState::Patrol: + return "Patrol"sv; + case EScriptObjectState::Dead: + return "Dead"sv; + case EScriptObjectState::CameraPath: + return "CameraPath"sv; + case EScriptObjectState::CameraTarget: + return "CameraTarget"sv; + case EScriptObjectState::DeactivateState: + return "DeactivateState"sv; + case EScriptObjectState::Play: + return "Play"sv; + case EScriptObjectState::MassiveDeath: + return "DeathExplosion"sv; + case EScriptObjectState::DeathRattle: + return "DeathRattle"sv; + case EScriptObjectState::AboutToMassivelyDie: + return "AboutToDie"sv; + case EScriptObjectState::Damage: + return "Damage"sv; + case EScriptObjectState::InvulnDamage: + return "InvulnDamage"sv; + case EScriptObjectState::MassiveFrozenDeath: + return "IceDeathExplosion"sv; + case EScriptObjectState::Modify: + return "Modify"sv; + case EScriptObjectState::ScanStart: + return "ScanStart"sv; + case EScriptObjectState::ScanProcessing: + return "ScanProcessing"sv; + case EScriptObjectState::ScanDone: + return "ScanDone"sv; + case EScriptObjectState::UnFrozen: + return "UnFrozen"sv; + case EScriptObjectState::Default: + return "Default"sv; + case EScriptObjectState::ReflectedDamage: + return "ReflectedDamage"sv; + case EScriptObjectState::InheritBounds: + return "InheritBounds"sv; + default: + return "..."sv; + } } -std::string_view ScriptObjectMessageToStr(EScriptObjectMessage message) -{ - switch (message) - { - case EScriptObjectMessage::UNKM0: return "UNKM0"sv; - case EScriptObjectMessage::Activate: return "Activate"sv; - case EScriptObjectMessage::Arrived: return "Arrived"sv; - case EScriptObjectMessage::Close: return "Close"sv; - case EScriptObjectMessage::Deactivate: return "Deactivate"sv; - case EScriptObjectMessage::Decrement: return "Decrement"sv; - case EScriptObjectMessage::Follow: return "Follow"sv; - case EScriptObjectMessage::Increment: return "Increment"sv; - case EScriptObjectMessage::Next: return "Next"sv; - case EScriptObjectMessage::Open: return "Open"sv; - case EScriptObjectMessage::Reset: return "Reset"sv; - case EScriptObjectMessage::ResetAndStart: return "ResetAndStart"sv; - case EScriptObjectMessage::SetToMax: return "SetToMax"sv; - case EScriptObjectMessage::SetToZero: return "SetToZero"sv; - case EScriptObjectMessage::Start: return "Start"sv; - case EScriptObjectMessage::Stop: return "Stop"sv; - case EScriptObjectMessage::StopAndReset: return "StopAndReset"sv; - case EScriptObjectMessage::ToggleActive: return "ToggleActive"sv; - case EScriptObjectMessage::UNKM18: return "UNKM18"sv; - case EScriptObjectMessage::Action: return "Action"sv; - case EScriptObjectMessage::Play: return "Play"sv; - case EScriptObjectMessage::Alert: return "Alert"sv; - case EScriptObjectMessage::InternalMessage00: return "InternalMessage00"sv; - case EScriptObjectMessage::OnFloor: return "OnFloor"sv; - case EScriptObjectMessage::InternalMessage02: return "InternalMessage02"sv; - case EScriptObjectMessage::InternalMessage03: return "InternalMessage03"sv; - case EScriptObjectMessage::Falling: return "Falling"sv; - case EScriptObjectMessage::OnIceSurface: return "OnIceSurface"sv; - case EScriptObjectMessage::OnMudSlowSurface: return "OnMudSlowSurface"sv; - case EScriptObjectMessage::OnNormalSurface: return "OnNormalSurface"sv; - case EScriptObjectMessage::Touched: return "Touched"sv; - case EScriptObjectMessage::AddPlatformRider: return "AddPlatformRider"sv; - case EScriptObjectMessage::LandOnNotFloor: return "LandOnNotFloor"sv; - case EScriptObjectMessage::Registered: return "Registered"sv; - case EScriptObjectMessage::Deleted: return "Deleted"sv; - case EScriptObjectMessage::InitializedInArea: return "InitializedInArea"sv; - case EScriptObjectMessage::WorldInitialized: return "WorldInitialized"sv; - case EScriptObjectMessage::AddSplashInhabitant: return "AddSplashInhabitant"sv; - case EScriptObjectMessage::UpdateSplashInhabitant: return "UpdateSplashInhabitant"sv; - case EScriptObjectMessage::RemoveSplashInhabitant: return "RemoveSplashInhabitant"sv; - case EScriptObjectMessage::Jumped: return "Jumped"sv; - case EScriptObjectMessage::Damage: return "Damage"sv; - case EScriptObjectMessage::InvulnDamage: return "InvulnDamage"sv; - case EScriptObjectMessage::ProjectileCollide: return "ProjectileCollide"sv; - case EScriptObjectMessage::InSnakeWeed: return "InSnakeWeed"sv; - case EScriptObjectMessage::AddPhazonPoolInhabitant: return "AddPhazonPoolInhabitant"sv; - case EScriptObjectMessage::UpdatePhazonPoolInhabitant: return "UpdatePhazonPoolInhabitant"sv; - case EScriptObjectMessage::RemovePhazonPoolInhabitant: return "RemovePhazonPoolInhabitant"sv; - case EScriptObjectMessage::SuspendedMove: return "SuspendedMove"sv; - default: return "..."sv; - } +std::string_view ScriptObjectMessageToStr(EScriptObjectMessage message) { + switch (message) { + case EScriptObjectMessage::UNKM0: + return "UNKM0"sv; + case EScriptObjectMessage::Activate: + return "Activate"sv; + case EScriptObjectMessage::Arrived: + return "Arrived"sv; + case EScriptObjectMessage::Close: + return "Close"sv; + case EScriptObjectMessage::Deactivate: + return "Deactivate"sv; + case EScriptObjectMessage::Decrement: + return "Decrement"sv; + case EScriptObjectMessage::Follow: + return "Follow"sv; + case EScriptObjectMessage::Increment: + return "Increment"sv; + case EScriptObjectMessage::Next: + return "Next"sv; + case EScriptObjectMessage::Open: + return "Open"sv; + case EScriptObjectMessage::Reset: + return "Reset"sv; + case EScriptObjectMessage::ResetAndStart: + return "ResetAndStart"sv; + case EScriptObjectMessage::SetToMax: + return "SetToMax"sv; + case EScriptObjectMessage::SetToZero: + return "SetToZero"sv; + case EScriptObjectMessage::Start: + return "Start"sv; + case EScriptObjectMessage::Stop: + return "Stop"sv; + case EScriptObjectMessage::StopAndReset: + return "StopAndReset"sv; + case EScriptObjectMessage::ToggleActive: + return "ToggleActive"sv; + case EScriptObjectMessage::UNKM18: + return "UNKM18"sv; + case EScriptObjectMessage::Action: + return "Action"sv; + case EScriptObjectMessage::Play: + return "Play"sv; + case EScriptObjectMessage::Alert: + return "Alert"sv; + case EScriptObjectMessage::InternalMessage00: + return "InternalMessage00"sv; + case EScriptObjectMessage::OnFloor: + return "OnFloor"sv; + case EScriptObjectMessage::InternalMessage02: + return "InternalMessage02"sv; + case EScriptObjectMessage::InternalMessage03: + return "InternalMessage03"sv; + case EScriptObjectMessage::Falling: + return "Falling"sv; + case EScriptObjectMessage::OnIceSurface: + return "OnIceSurface"sv; + case EScriptObjectMessage::OnMudSlowSurface: + return "OnMudSlowSurface"sv; + case EScriptObjectMessage::OnNormalSurface: + return "OnNormalSurface"sv; + case EScriptObjectMessage::Touched: + return "Touched"sv; + case EScriptObjectMessage::AddPlatformRider: + return "AddPlatformRider"sv; + case EScriptObjectMessage::LandOnNotFloor: + return "LandOnNotFloor"sv; + case EScriptObjectMessage::Registered: + return "Registered"sv; + case EScriptObjectMessage::Deleted: + return "Deleted"sv; + case EScriptObjectMessage::InitializedInArea: + return "InitializedInArea"sv; + case EScriptObjectMessage::WorldInitialized: + return "WorldInitialized"sv; + case EScriptObjectMessage::AddSplashInhabitant: + return "AddSplashInhabitant"sv; + case EScriptObjectMessage::UpdateSplashInhabitant: + return "UpdateSplashInhabitant"sv; + case EScriptObjectMessage::RemoveSplashInhabitant: + return "RemoveSplashInhabitant"sv; + case EScriptObjectMessage::Jumped: + return "Jumped"sv; + case EScriptObjectMessage::Damage: + return "Damage"sv; + case EScriptObjectMessage::InvulnDamage: + return "InvulnDamage"sv; + case EScriptObjectMessage::ProjectileCollide: + return "ProjectileCollide"sv; + case EScriptObjectMessage::InSnakeWeed: + return "InSnakeWeed"sv; + case EScriptObjectMessage::AddPhazonPoolInhabitant: + return "AddPhazonPoolInhabitant"sv; + case EScriptObjectMessage::UpdatePhazonPoolInhabitant: + return "UpdatePhazonPoolInhabitant"sv; + case EScriptObjectMessage::RemovePhazonPoolInhabitant: + return "RemovePhazonPoolInhabitant"sv; + case EScriptObjectMessage::SuspendedMove: + return "SuspendedMove"sv; + default: + return "..."sv; + } } -} +} // namespace urde diff --git a/Runtime/World/ScriptObjectSupport.hpp b/Runtime/World/ScriptObjectSupport.hpp index 1617d1d7b..ae4c18597 100644 --- a/Runtime/World/ScriptObjectSupport.hpp +++ b/Runtime/World/ScriptObjectSupport.hpp @@ -2,236 +2,231 @@ #include -namespace urde -{ +namespace urde { -enum class EScriptObjectType -{ - Actor = 0x00, - Waypoint = 0x02, - Door = 0x03, - Trigger = 0x04, - Timer = 0x05, - Counter = 0x06, - Effect = 0x07, - Platform = 0x08, - Sound = 0x09, - Generator = 0x0A, - Dock = 0x0B, - Camera = 0x0C, - CameraWaypoint = 0x0D, - NewIntroBoss = 0x0E, - SpawnPoint = 0x0F, - CameraHint = 0x10, - Pickup = 0x11, - MemoryRelay = 0x13, - RandomRelay = 0x14, - Relay = 0x15, - Beetle = 0x16, - HUDMemo = 0x17, - CameraFilterKeyframe = 0x18, - CameraBlurKeyframe = 0x19, - DamageableTrigger = 0x1A, - Debris = 0x1B, - CameraShaker = 0x1C, - ActorKeyframe = 0x1D, - Water = 0x20, - Warwasp = 0x21, - SpacePirate = 0x24, - FlyingPirate = 0x25, - ElitePirate = 0x26, - MetroidBeta = 0x27, - ChozoGhost = 0x28, - CoverPoint = 0x2A, - SpiderBallWaypoint = 0x2C, - BloodFlower = 0x2D, - FlickerBat = 0x2E, - PathCamera = 0x2F, - GrapplePoint = 0x30, - PuddleSpore = 0x31, - DebugCameraWaypoint = 0x32, - SpiderBallAttractionSurface = 0x33, - PuddleToadGamma = 0x34, - DistanceFog = 0x35, - FireFlea = 0x36, - Metaree = 0x37, - DockAreaChange = 0x38, - ActorRotate = 0x39, - SpecialFunction = 0x3A, - SpankWeed = 0x3B, - Parasite = 0x3D, - PlayerHint = 0x3E, - Ripper = 0x3F, - PickupGenerator = 0x40, - AIKeyframe = 0x41, - PointOfInterest = 0x42, - Drone = 0x43, - MetroidAlpha = 0x44, - DebrisExtended = 0x45, - Steam = 0x46, - Ripple = 0x47, - BallTrigger = 0x48, - TargetingPoint = 0x49, - EMPulse = 0x4A, - IceSheegoth = 0x4B, - PlayerActor = 0x4C, - Flaahgra = 0x4D, - AreaAttributes = 0x4E, - FishCloud = 0x4F, - FishCloudModifier = 0x50, - VisorFlare = 0x51, - WorldTeleporter = 0x52, - VisorGoo = 0x53, - JellyZap = 0x54, - ControllerAction = 0x55, - Switch = 0x56, - PlayerStateChange = 0x57, - Thardus = 0x58, - WallCrawlerSwarm = 0x5A, - AIJumpPoint = 0x5B, - FlaahgraTentacle = 0x5C, - RoomAcoustics = 0x5D, - ColorModulate = 0x5E, - ThardusRockProjectile = 0x5F, - Midi = 0x60, - StreamedAudio = 0x61, - WorldTeleporterToo = 0x62, - Repulsor = 0x63, - GunTurret = 0x64, - FogVolume = 0x65, - Babygoth = 0x66, - Eyeball = 0x67, - RadialDamage = 0x68, - CameraPitchVolume = 0x69, - EnvFxDensityController = 0x6A, - Magdolite = 0x6B, - TeamAIMgr = 0x6C, - SnakeWeedSwarm = 0x6D, - ActorContraption = 0x6E, - Oculus = 0x6F, - Geemer = 0x70, - SpindleCamera = 0x71, - AtomicAlpha = 0x72, - CameraHintTrigger = 0x73, - RumbleEffect = 0x74, - AmbientAI = 0x75, - AtomicBeta = 0x77, - IceZoomer = 0x78, - Puffer = 0x79, - Tryclops = 0x7A, - Ridley = 0x7B, - Seedling = 0x7C, - ThermalHeatFader = 0x7D, - Burrower = 0x7F, - ScriptBeam = 0x81, - WorldLightFader = 0x82, - MetroidPrimeStage2 = 0x83, - MetroidPrimeStage1 = 0x84, - MazeNode = 0x85, - OmegaPirate = 0x86, - PhazonPool = 0x87, - PhazonHealingNodule = 0x88, - NewCameraShaker = 0x89, - ShadowProjector = 0x8A, - EnergyBall = 0x8B, - ScriptObjectTypeMAX +enum class EScriptObjectType { + Actor = 0x00, + Waypoint = 0x02, + Door = 0x03, + Trigger = 0x04, + Timer = 0x05, + Counter = 0x06, + Effect = 0x07, + Platform = 0x08, + Sound = 0x09, + Generator = 0x0A, + Dock = 0x0B, + Camera = 0x0C, + CameraWaypoint = 0x0D, + NewIntroBoss = 0x0E, + SpawnPoint = 0x0F, + CameraHint = 0x10, + Pickup = 0x11, + MemoryRelay = 0x13, + RandomRelay = 0x14, + Relay = 0x15, + Beetle = 0x16, + HUDMemo = 0x17, + CameraFilterKeyframe = 0x18, + CameraBlurKeyframe = 0x19, + DamageableTrigger = 0x1A, + Debris = 0x1B, + CameraShaker = 0x1C, + ActorKeyframe = 0x1D, + Water = 0x20, + Warwasp = 0x21, + SpacePirate = 0x24, + FlyingPirate = 0x25, + ElitePirate = 0x26, + MetroidBeta = 0x27, + ChozoGhost = 0x28, + CoverPoint = 0x2A, + SpiderBallWaypoint = 0x2C, + BloodFlower = 0x2D, + FlickerBat = 0x2E, + PathCamera = 0x2F, + GrapplePoint = 0x30, + PuddleSpore = 0x31, + DebugCameraWaypoint = 0x32, + SpiderBallAttractionSurface = 0x33, + PuddleToadGamma = 0x34, + DistanceFog = 0x35, + FireFlea = 0x36, + Metaree = 0x37, + DockAreaChange = 0x38, + ActorRotate = 0x39, + SpecialFunction = 0x3A, + SpankWeed = 0x3B, + Parasite = 0x3D, + PlayerHint = 0x3E, + Ripper = 0x3F, + PickupGenerator = 0x40, + AIKeyframe = 0x41, + PointOfInterest = 0x42, + Drone = 0x43, + MetroidAlpha = 0x44, + DebrisExtended = 0x45, + Steam = 0x46, + Ripple = 0x47, + BallTrigger = 0x48, + TargetingPoint = 0x49, + EMPulse = 0x4A, + IceSheegoth = 0x4B, + PlayerActor = 0x4C, + Flaahgra = 0x4D, + AreaAttributes = 0x4E, + FishCloud = 0x4F, + FishCloudModifier = 0x50, + VisorFlare = 0x51, + WorldTeleporter = 0x52, + VisorGoo = 0x53, + JellyZap = 0x54, + ControllerAction = 0x55, + Switch = 0x56, + PlayerStateChange = 0x57, + Thardus = 0x58, + WallCrawlerSwarm = 0x5A, + AIJumpPoint = 0x5B, + FlaahgraTentacle = 0x5C, + RoomAcoustics = 0x5D, + ColorModulate = 0x5E, + ThardusRockProjectile = 0x5F, + Midi = 0x60, + StreamedAudio = 0x61, + WorldTeleporterToo = 0x62, + Repulsor = 0x63, + GunTurret = 0x64, + FogVolume = 0x65, + Babygoth = 0x66, + Eyeball = 0x67, + RadialDamage = 0x68, + CameraPitchVolume = 0x69, + EnvFxDensityController = 0x6A, + Magdolite = 0x6B, + TeamAIMgr = 0x6C, + SnakeWeedSwarm = 0x6D, + ActorContraption = 0x6E, + Oculus = 0x6F, + Geemer = 0x70, + SpindleCamera = 0x71, + AtomicAlpha = 0x72, + CameraHintTrigger = 0x73, + RumbleEffect = 0x74, + AmbientAI = 0x75, + AtomicBeta = 0x77, + IceZoomer = 0x78, + Puffer = 0x79, + Tryclops = 0x7A, + Ridley = 0x7B, + Seedling = 0x7C, + ThermalHeatFader = 0x7D, + Burrower = 0x7F, + ScriptBeam = 0x81, + WorldLightFader = 0x82, + MetroidPrimeStage2 = 0x83, + MetroidPrimeStage1 = 0x84, + MazeNode = 0x85, + OmegaPirate = 0x86, + PhazonPool = 0x87, + PhazonHealingNodule = 0x88, + NewCameraShaker = 0x89, + ShadowProjector = 0x8A, + EnergyBall = 0x8B, + ScriptObjectTypeMAX }; -enum class EScriptObjectState -{ - Any = -1, - Active = 0, - Arrived = 1, - Closed = 2, - Entered = 3, - Exited = 4, - Inactive = 5, - Inside = 6, - MaxReached = 7, - Open = 8, - Zero = 9, - Attack = 10, - CloseIn = 11, - Retreat = 12, - Patrol = 13, - Dead = 14, - CameraPath = 15, - CameraTarget = 16, - DeactivateState = 17, - Play = 18, - MassiveDeath = 19, - DeathRattle = 20, - AboutToMassivelyDie = 21, - Damage = 22, - InvulnDamage = 23, - MassiveFrozenDeath = 24, - Modify = 25, - ScanStart = 26, - ScanProcessing = 27, - ScanDone = 28, - UnFrozen = 29, - Default = 30, - ReflectedDamage = 31, - InheritBounds = 32 +enum class EScriptObjectState { + Any = -1, + Active = 0, + Arrived = 1, + Closed = 2, + Entered = 3, + Exited = 4, + Inactive = 5, + Inside = 6, + MaxReached = 7, + Open = 8, + Zero = 9, + Attack = 10, + CloseIn = 11, + Retreat = 12, + Patrol = 13, + Dead = 14, + CameraPath = 15, + CameraTarget = 16, + DeactivateState = 17, + Play = 18, + MassiveDeath = 19, + DeathRattle = 20, + AboutToMassivelyDie = 21, + Damage = 22, + InvulnDamage = 23, + MassiveFrozenDeath = 24, + Modify = 25, + ScanStart = 26, + ScanProcessing = 27, + ScanDone = 28, + UnFrozen = 29, + Default = 30, + ReflectedDamage = 31, + InheritBounds = 32 }; -enum class EScriptObjectMessage -{ - None = -1, - UNKM0 = 0, - Activate = 1, - Arrived = 2, - Close = 3, - Deactivate = 4, - Decrement = 5, - Follow = 6, - Increment = 7, - Next = 8, - Open = 9, - Reset = 10, - ResetAndStart = 11, - SetToMax = 12, - SetToZero = 13, - Start = 14, - Stop = 15, - StopAndReset = 16, - ToggleActive = 17, - UNKM18 = 18, - Action = 19, - Play = 20, - Alert = 21, - InternalMessage00 = 22, - OnFloor = 23, - InternalMessage02 = 24, - InternalMessage03 = 25, - Falling = 26, - OnIceSurface = 27, - OnMudSlowSurface = 28, - OnNormalSurface = 29, - Touched = 30, - AddPlatformRider = 31, - LandOnNotFloor = 32, - Registered = 33, - Deleted = 34, - InitializedInArea = 35, - WorldInitialized = 36, - AddSplashInhabitant = 37, - UpdateSplashInhabitant = 38, - RemoveSplashInhabitant = 39, - Jumped = 40, - Damage = 41, - InvulnDamage = 42, - ProjectileCollide = 43, - InSnakeWeed = 44, - AddPhazonPoolInhabitant = 45, - UpdatePhazonPoolInhabitant = 46, - RemovePhazonPoolInhabitant = 47, - SuspendedMove = 48 +enum class EScriptObjectMessage { + None = -1, + UNKM0 = 0, + Activate = 1, + Arrived = 2, + Close = 3, + Deactivate = 4, + Decrement = 5, + Follow = 6, + Increment = 7, + Next = 8, + Open = 9, + Reset = 10, + ResetAndStart = 11, + SetToMax = 12, + SetToZero = 13, + Start = 14, + Stop = 15, + StopAndReset = 16, + ToggleActive = 17, + UNKM18 = 18, + Action = 19, + Play = 20, + Alert = 21, + InternalMessage00 = 22, + OnFloor = 23, + InternalMessage02 = 24, + InternalMessage03 = 25, + Falling = 26, + OnIceSurface = 27, + OnMudSlowSurface = 28, + OnNormalSurface = 29, + Touched = 30, + AddPlatformRider = 31, + LandOnNotFloor = 32, + Registered = 33, + Deleted = 34, + InitializedInArea = 35, + WorldInitialized = 36, + AddSplashInhabitant = 37, + UpdateSplashInhabitant = 38, + RemoveSplashInhabitant = 39, + Jumped = 40, + Damage = 41, + InvulnDamage = 42, + ProjectileCollide = 43, + InSnakeWeed = 44, + AddPhazonPoolInhabitant = 45, + UpdatePhazonPoolInhabitant = 46, + RemovePhazonPoolInhabitant = 47, + SuspendedMove = 48 }; std::string_view ScriptObjectTypeToStr(EScriptObjectType type); std::string_view ScriptObjectStateToStr(EScriptObjectState state); std::string_view ScriptObjectMessageToStr(EScriptObjectMessage message); -} - +} // namespace urde diff --git a/Runtime/rstl.hpp b/Runtime/rstl.hpp index b609a42ea..3f4fe7c67 100644 --- a/Runtime/rstl.hpp +++ b/Runtime/rstl.hpp @@ -7,8 +7,7 @@ #include "optional.hpp" #include "logvisor/logvisor.hpp" -namespace rstl -{ +namespace rstl { #ifndef NDEBUG static logvisor::Module Log("rstl"); @@ -18,483 +17,523 @@ static logvisor::Module Log("rstl"); * @brief Base vector backed by statically-allocated array */ template -class _reserved_vector_base -{ +class _reserved_vector_base { public: - class const_iterator - { - friend class _reserved_vector_base; - protected: - const T* m_val; - public: - explicit const_iterator(const T* val) : m_val(val) {} - using value_type = T; - using difference_type = std::ptrdiff_t; - using pointer = T*; - using reference = T&; - using iterator_category = std::random_access_iterator_tag; + class const_iterator { + friend class _reserved_vector_base; - const T& operator*() const { return *m_val; } - const T* operator->() const { return m_val; } - const_iterator& operator++() { ++m_val; return *this; } - const_iterator& operator--() { --m_val; return *this; } - const_iterator operator++(int) { auto ret = *this; ++m_val; return ret; } - const_iterator operator--(int) { auto ret = *this; --m_val; return ret; } - bool operator!=(const const_iterator& other) const { return m_val != other.m_val; } - bool operator==(const const_iterator& other) const { return m_val == other.m_val; } - const_iterator operator+(std::ptrdiff_t i) const { return const_iterator(m_val + i); } - const_iterator operator-(std::ptrdiff_t i) const { return const_iterator(m_val - i); } - const_iterator& operator+=(std::ptrdiff_t i) { m_val += i; return *this; } - const_iterator& operator-=(std::ptrdiff_t i) { m_val -= i; return *this; } - std::ptrdiff_t operator-(const const_iterator& it) const { return m_val - it.m_val; } - bool operator>(const const_iterator& it) const { return m_val > it.m_val; } - bool operator<(const const_iterator& it) const { return m_val < it.m_val; } - bool operator>=(const const_iterator& it) const { return m_val >= it.m_val; } - bool operator<=(const const_iterator& it) const { return m_val <= it.m_val; } - const T& operator[](std::ptrdiff_t i) const { return m_val[i]; } - }; + protected: + const T* m_val; - class iterator : public const_iterator - { - friend class _reserved_vector_base; - public: - explicit iterator(T* val) : const_iterator(val) {} - T& operator*() const { return *const_cast(const_iterator::m_val); } - T* operator->() const { return const_cast(const_iterator::m_val); } - iterator& operator++() { ++const_iterator::m_val; return *this; } - iterator& operator--() { --const_iterator::m_val; return *this; } - iterator operator++(int) { auto ret = *this; ++const_iterator::m_val; return ret; } - iterator operator--(int) { auto ret = *this; --const_iterator::m_val; return ret; } - iterator operator+(std::ptrdiff_t i) const { return iterator(const_cast(const_iterator::m_val) + i); } - iterator operator-(std::ptrdiff_t i) const { return iterator(const_cast(const_iterator::m_val) - i); } - iterator& operator+=(std::ptrdiff_t i) { const_iterator::m_val += i; return *this; } - iterator& operator-=(std::ptrdiff_t i) { const_iterator::m_val -= i; return *this; } - std::ptrdiff_t operator-(const iterator& it) const { return const_iterator::m_val - it.m_val; } - bool operator>(const iterator& it) const { return const_iterator::m_val > it.m_val; } - bool operator<(const iterator& it) const { return const_iterator::m_val < it.m_val; } - bool operator>=(const iterator& it) const { return const_iterator::m_val >= it.m_val; } - bool operator<=(const iterator& it) const { return const_iterator::m_val <= it.m_val; } - T& operator[](std::ptrdiff_t i) const { return const_cast(const_iterator::m_val)[i]; } - }; + public: + explicit const_iterator(const T* val) : m_val(val) {} + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using reference = T&; + using iterator_category = std::random_access_iterator_tag; - class const_reverse_iterator - { - friend class _reserved_vector_base; - protected: - const T* m_val; - public: - explicit const_reverse_iterator(const T* val) : m_val(val) {} - using value_type = T; - using difference_type = std::ptrdiff_t; - using pointer = T*; - using reference = T&; - using iterator_category = std::random_access_iterator_tag; + const T& operator*() const { return *m_val; } + const T* operator->() const { return m_val; } + const_iterator& operator++() { + ++m_val; + return *this; + } + const_iterator& operator--() { + --m_val; + return *this; + } + const_iterator operator++(int) { + auto ret = *this; + ++m_val; + return ret; + } + const_iterator operator--(int) { + auto ret = *this; + --m_val; + return ret; + } + bool operator!=(const const_iterator& other) const { return m_val != other.m_val; } + bool operator==(const const_iterator& other) const { return m_val == other.m_val; } + const_iterator operator+(std::ptrdiff_t i) const { return const_iterator(m_val + i); } + const_iterator operator-(std::ptrdiff_t i) const { return const_iterator(m_val - i); } + const_iterator& operator+=(std::ptrdiff_t i) { + m_val += i; + return *this; + } + const_iterator& operator-=(std::ptrdiff_t i) { + m_val -= i; + return *this; + } + std::ptrdiff_t operator-(const const_iterator& it) const { return m_val - it.m_val; } + bool operator>(const const_iterator& it) const { return m_val > it.m_val; } + bool operator<(const const_iterator& it) const { return m_val < it.m_val; } + bool operator>=(const const_iterator& it) const { return m_val >= it.m_val; } + bool operator<=(const const_iterator& it) const { return m_val <= it.m_val; } + const T& operator[](std::ptrdiff_t i) const { return m_val[i]; } + }; - const T& operator*() const { return *m_val; } - const T* operator->() const { return m_val; } - const_reverse_iterator& operator++() { --m_val; return *this; } - const_reverse_iterator& operator--() { ++m_val; return *this; } - const_reverse_iterator operator++(int) { auto ret = *this; --m_val; return ret; } - const_reverse_iterator operator--(int) { auto ret = *this; ++m_val; return ret; } - bool operator!=(const const_reverse_iterator& other) const { return m_val != other.m_val; } - bool operator==(const const_reverse_iterator& other) const { return m_val == other.m_val; } - const_reverse_iterator operator+(std::ptrdiff_t i) const { return const_reverse_iterator(m_val - i); } - const_reverse_iterator operator-(std::ptrdiff_t i) const { return const_reverse_iterator(m_val + i); } - const_reverse_iterator& operator+=(std::ptrdiff_t i) { m_val -= i; return *this; } - const_reverse_iterator& operator-=(std::ptrdiff_t i) { m_val += i; return *this; } - std::ptrdiff_t operator-(const const_reverse_iterator& it) const { return it.m_val - m_val; } - bool operator>(const const_iterator& it) const { return it.m_val > m_val; } - bool operator<(const const_iterator& it) const { return it.m_val < m_val; } - bool operator>=(const const_iterator& it) const { return it.m_val >= m_val; } - bool operator<=(const const_iterator& it) const { return it.m_val <= m_val; } - const T& operator[](std::ptrdiff_t i) const { return m_val[-i]; } - }; + class iterator : public const_iterator { + friend class _reserved_vector_base; - class reverse_iterator : public const_reverse_iterator - { - friend class _reserved_vector_base; - public: - explicit reverse_iterator(T* val) : const_reverse_iterator(val) {} - T& operator*() const { return *const_cast(const_reverse_iterator::m_val); } - T* operator->() const { return const_cast(const_reverse_iterator::m_val); } - reverse_iterator& operator++() { --const_reverse_iterator::m_val; return *this; } - reverse_iterator& operator--() { ++const_reverse_iterator::m_val; return *this; } - reverse_iterator operator++(int) { auto ret = *this; --const_reverse_iterator::m_val; return ret; } - reverse_iterator operator--(int) { auto ret = *this; ++const_reverse_iterator::m_val; return ret; } - reverse_iterator operator+(std::ptrdiff_t i) const - { return reverse_iterator(const_cast(const_reverse_iterator::m_val) - i); } - reverse_iterator operator-(std::ptrdiff_t i) const - { return reverse_iterator(const_cast(const_reverse_iterator::m_val) + i); } - reverse_iterator& operator+=(std::ptrdiff_t i) { const_reverse_iterator::m_val -= i; return *this; } - reverse_iterator& operator-=(std::ptrdiff_t i) { const_reverse_iterator::m_val += i; return *this; } - std::ptrdiff_t operator-(const reverse_iterator& it) const { return it.m_val - const_reverse_iterator::m_val; } - bool operator>(const const_reverse_iterator& it) const { return it.m_val > const_reverse_iterator::m_val; } - bool operator<(const const_reverse_iterator& it) const { return it.m_val < const_reverse_iterator::m_val; } - bool operator>=(const const_reverse_iterator& it) const { return it.m_val >= const_reverse_iterator::m_val; } - bool operator<=(const const_reverse_iterator& it) const { return it.m_val <= const_reverse_iterator::m_val; } - T& operator[](std::ptrdiff_t i) const { return const_cast(const_reverse_iterator::m_val)[-i]; } - }; + public: + explicit iterator(T* val) : const_iterator(val) {} + T& operator*() const { return *const_cast(const_iterator::m_val); } + T* operator->() const { return const_cast(const_iterator::m_val); } + iterator& operator++() { + ++const_iterator::m_val; + return *this; + } + iterator& operator--() { + --const_iterator::m_val; + return *this; + } + iterator operator++(int) { + auto ret = *this; + ++const_iterator::m_val; + return ret; + } + iterator operator--(int) { + auto ret = *this; + --const_iterator::m_val; + return ret; + } + iterator operator+(std::ptrdiff_t i) const { return iterator(const_cast(const_iterator::m_val) + i); } + iterator operator-(std::ptrdiff_t i) const { return iterator(const_cast(const_iterator::m_val) - i); } + iterator& operator+=(std::ptrdiff_t i) { + const_iterator::m_val += i; + return *this; + } + iterator& operator-=(std::ptrdiff_t i) { + const_iterator::m_val -= i; + return *this; + } + std::ptrdiff_t operator-(const iterator& it) const { return const_iterator::m_val - it.m_val; } + bool operator>(const iterator& it) const { return const_iterator::m_val > it.m_val; } + bool operator<(const iterator& it) const { return const_iterator::m_val < it.m_val; } + bool operator>=(const iterator& it) const { return const_iterator::m_val >= it.m_val; } + bool operator<=(const iterator& it) const { return const_iterator::m_val <= it.m_val; } + T& operator[](std::ptrdiff_t i) const { return const_cast(const_iterator::m_val)[i]; } + }; + + class const_reverse_iterator { + friend class _reserved_vector_base; + + protected: + const T* m_val; + + public: + explicit const_reverse_iterator(const T* val) : m_val(val) {} + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using reference = T&; + using iterator_category = std::random_access_iterator_tag; + + const T& operator*() const { return *m_val; } + const T* operator->() const { return m_val; } + const_reverse_iterator& operator++() { + --m_val; + return *this; + } + const_reverse_iterator& operator--() { + ++m_val; + return *this; + } + const_reverse_iterator operator++(int) { + auto ret = *this; + --m_val; + return ret; + } + const_reverse_iterator operator--(int) { + auto ret = *this; + ++m_val; + return ret; + } + bool operator!=(const const_reverse_iterator& other) const { return m_val != other.m_val; } + bool operator==(const const_reverse_iterator& other) const { return m_val == other.m_val; } + const_reverse_iterator operator+(std::ptrdiff_t i) const { return const_reverse_iterator(m_val - i); } + const_reverse_iterator operator-(std::ptrdiff_t i) const { return const_reverse_iterator(m_val + i); } + const_reverse_iterator& operator+=(std::ptrdiff_t i) { + m_val -= i; + return *this; + } + const_reverse_iterator& operator-=(std::ptrdiff_t i) { + m_val += i; + return *this; + } + std::ptrdiff_t operator-(const const_reverse_iterator& it) const { return it.m_val - m_val; } + bool operator>(const const_iterator& it) const { return it.m_val > m_val; } + bool operator<(const const_iterator& it) const { return it.m_val < m_val; } + bool operator>=(const const_iterator& it) const { return it.m_val >= m_val; } + bool operator<=(const const_iterator& it) const { return it.m_val <= m_val; } + const T& operator[](std::ptrdiff_t i) const { return m_val[-i]; } + }; + + class reverse_iterator : public const_reverse_iterator { + friend class _reserved_vector_base; + + public: + explicit reverse_iterator(T* val) : const_reverse_iterator(val) {} + T& operator*() const { return *const_cast(const_reverse_iterator::m_val); } + T* operator->() const { return const_cast(const_reverse_iterator::m_val); } + reverse_iterator& operator++() { + --const_reverse_iterator::m_val; + return *this; + } + reverse_iterator& operator--() { + ++const_reverse_iterator::m_val; + return *this; + } + reverse_iterator operator++(int) { + auto ret = *this; + --const_reverse_iterator::m_val; + return ret; + } + reverse_iterator operator--(int) { + auto ret = *this; + ++const_reverse_iterator::m_val; + return ret; + } + reverse_iterator operator+(std::ptrdiff_t i) const { + return reverse_iterator(const_cast(const_reverse_iterator::m_val) - i); + } + reverse_iterator operator-(std::ptrdiff_t i) const { + return reverse_iterator(const_cast(const_reverse_iterator::m_val) + i); + } + reverse_iterator& operator+=(std::ptrdiff_t i) { + const_reverse_iterator::m_val -= i; + return *this; + } + reverse_iterator& operator-=(std::ptrdiff_t i) { + const_reverse_iterator::m_val += i; + return *this; + } + std::ptrdiff_t operator-(const reverse_iterator& it) const { return it.m_val - const_reverse_iterator::m_val; } + bool operator>(const const_reverse_iterator& it) const { return it.m_val > const_reverse_iterator::m_val; } + bool operator<(const const_reverse_iterator& it) const { return it.m_val < const_reverse_iterator::m_val; } + bool operator>=(const const_reverse_iterator& it) const { return it.m_val >= const_reverse_iterator::m_val; } + bool operator<=(const const_reverse_iterator& it) const { return it.m_val <= const_reverse_iterator::m_val; } + T& operator[](std::ptrdiff_t i) const { return const_cast(const_reverse_iterator::m_val)[-i]; } + }; protected: - static iterator _const_cast_iterator(const const_iterator& it) { return iterator(const_cast(it.m_val)); } + static iterator _const_cast_iterator(const const_iterator& it) { return iterator(const_cast(it.m_val)); } }; /** * @brief Vector backed by statically-allocated array with uninitialized storage */ template -class reserved_vector : public _reserved_vector_base -{ - union alignas(T) storage_t - { - struct {} _dummy; - T _value; - storage_t() : _dummy() {} - ~storage_t() {} - }; - size_t x0_size; - storage_t x4_data[N]; - T& _value(std::ptrdiff_t idx) { return x4_data[idx]._value; } - const T& _value(std::ptrdiff_t idx) const { return x4_data[idx]._value; } - template - static void destroy(Tp& t, std::enable_if_t::value && - !std::is_trivially_destructible::value>* = 0) { t.Tp::~Tp(); } - template - static void destroy(Tp& t, std::enable_if_t::value || - std::is_trivially_destructible::value>* = 0) {} +class reserved_vector : public _reserved_vector_base { + union alignas(T) storage_t { + struct { + } _dummy; + T _value; + storage_t() : _dummy() {} + ~storage_t() {} + }; + size_t x0_size; + storage_t x4_data[N]; + T& _value(std::ptrdiff_t idx) { return x4_data[idx]._value; } + const T& _value(std::ptrdiff_t idx) const { return x4_data[idx]._value; } + template + static void + destroy(Tp& t, std::enable_if_t::value && !std::is_trivially_destructible::value>* = 0) { + t.Tp::~Tp(); + } + template + static void + destroy(Tp& t, std::enable_if_t::value || std::is_trivially_destructible::value>* = 0) { + } public: - using base = _reserved_vector_base; - using iterator = typename base::iterator; - using const_iterator = typename base::const_iterator; - using reverse_iterator = typename base::reverse_iterator; - using const_reverse_iterator = typename base::const_reverse_iterator; - reserved_vector() : x0_size(0) {} + using base = _reserved_vector_base; + using iterator = typename base::iterator; + using const_iterator = typename base::const_iterator; + using reverse_iterator = typename base::reverse_iterator; + using const_reverse_iterator = typename base::const_reverse_iterator; + reserved_vector() : x0_size(0) {} - reserved_vector(const reserved_vector& other) : x0_size(other.x0_size) - { - for (size_t i=0 ; i(std::addressof(_value(i)))) T(other._value(i)); + reserved_vector(const reserved_vector& other) : x0_size(other.x0_size) { + for (size_t i = 0; i < x0_size; ++i) + ::new (static_cast(std::addressof(_value(i)))) T(other._value(i)); + } + + reserved_vector& operator=(const reserved_vector& other) { + size_t i = 0; + if (other.x0_size > x0_size) { + for (; i < x0_size; ++i) + _value(i) = other._value(i); + for (; i < other.x0_size; ++i) + ::new (static_cast(std::addressof(_value(i)))) T(other._value(i)); + } else if (other.x0_size < x0_size) { + for (; i < other.x0_size; ++i) + _value(i) = other._value(i); + if (std::is_destructible::value && !std::is_trivially_destructible::value) + for (; i < x0_size; ++i) + destroy(_value(i)); + } else { + for (; i < other.x0_size; ++i) + _value(i) = other._value(i); } + x0_size = other.x0_size; + return *this; + } - reserved_vector& operator=(const reserved_vector& other) - { - size_t i = 0; - if (other.x0_size > x0_size) - { - for (; i(std::addressof(_value(i)))) T(other._value(i)); - } - else if (other.x0_size < x0_size) - { - for (; i::value && !std::is_trivially_destructible::value) - for (; i(std::addressof(_value(i)))) T(std::forward(other._value(i))); + } + + reserved_vector& operator=(reserved_vector&& other) { + size_t i = 0; + if (other.x0_size > x0_size) { + for (; i < x0_size; ++i) + _value(i) = std::forward(other._value(i)); + for (; i < other.x0_size; ++i) + ::new (static_cast(std::addressof(_value(i)))) T(std::forward(other._value(i))); + } else if (other.x0_size < x0_size) { + for (; i < other.x0_size; ++i) + _value(i) = std::forward(other._value(i)); + if (std::is_destructible::value && !std::is_trivially_destructible::value) + for (; i < x0_size; ++i) + destroy(_value(i)); + } else { + for (; i < other.x0_size; ++i) + _value(i) = std::forward(other._value(i)); } + x0_size = other.x0_size; + return *this; + } - reserved_vector(reserved_vector&& other) : x0_size(other.x0_size) - { - for (size_t i=0 ; i(std::addressof(_value(i)))) T(std::forward(other._value(i))); - } + ~reserved_vector() { + if (std::is_destructible::value && !std::is_trivially_destructible::value) + for (size_t i = 0; i < x0_size; ++i) + destroy(_value(i)); + } - reserved_vector& operator=(reserved_vector&& other) - { - size_t i = 0; - if (other.x0_size > x0_size) - { - for (; i(other._value(i)); - for (; i(std::addressof(_value(i)))) T(std::forward(other._value(i))); - } - else if (other.x0_size < x0_size) - { - for (; i(other._value(i)); - if (std::is_destructible::value && !std::is_trivially_destructible::value) - for (; i(other._value(i)); - } - x0_size = other.x0_size; - return *this; - } - - ~reserved_vector() - { - if (std::is_destructible::value && !std::is_trivially_destructible::value) - for (size_t i=0 ; i(std::addressof(_value(x0_size)))) T(d); - ++x0_size; - } + ::new (static_cast(std::addressof(_value(x0_size)))) T(d); + ++x0_size; + } - void push_back(T&& d) - { + void push_back(T&& d) { #ifndef NDEBUG - if (x0_size == N) - Log.report(logvisor::Fatal, "push_back() called on full rstl::reserved_vector."); + if (x0_size == N) + Log.report(logvisor::Fatal, "push_back() called on full rstl::reserved_vector."); #endif - ::new (static_cast(std::addressof(_value(x0_size)))) T(std::forward(d)); - ++x0_size; - } + ::new (static_cast(std::addressof(_value(x0_size)))) T(std::forward(d)); + ++x0_size; + } - template - void emplace_back(_Args&&... args) - { + template + void emplace_back(_Args&&... args) { #ifndef NDEBUG - if (x0_size == N) - Log.report(logvisor::Fatal, "emplace_back() called on full rstl::reserved_vector."); + if (x0_size == N) + Log.report(logvisor::Fatal, "emplace_back() called on full rstl::reserved_vector."); #endif - ::new (static_cast(std::addressof(_value(x0_size)))) T(std::forward<_Args>(args)...); - ++x0_size; - } + ::new (static_cast(std::addressof(_value(x0_size)))) T(std::forward<_Args>(args)...); + ++x0_size; + } - void pop_back() - { + void pop_back() { #ifndef NDEBUG - if (x0_size == 0) - Log.report(logvisor::Fatal, "pop_back() called on empty rstl::reserved_vector."); + if (x0_size == 0) + Log.report(logvisor::Fatal, "pop_back() called on empty rstl::reserved_vector."); #endif - --x0_size; - destroy(_value(x0_size)); - } + --x0_size; + destroy(_value(x0_size)); + } - iterator insert(const_iterator pos, const T& value) - { + iterator insert(const_iterator pos, const T& value) { #ifndef NDEBUG - if (x0_size == N) - Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector."); + if (x0_size == N) + Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector."); #endif - auto target_it = base::_const_cast_iterator(pos); - if (pos == cend()) - { - ::new (static_cast(std::addressof(_value(x0_size)))) T(value); - } - else - { - ::new (static_cast(std::addressof(_value(x0_size)))) - T(std::forward(_value(x0_size - 1))); - for (auto it = end() - 1; it != target_it; --it) - *it = std::forward(*(it - 1)); - *target_it = value; - } - ++x0_size; - return target_it; + auto target_it = base::_const_cast_iterator(pos); + if (pos == cend()) { + ::new (static_cast(std::addressof(_value(x0_size)))) T(value); + } else { + ::new (static_cast(std::addressof(_value(x0_size)))) T(std::forward(_value(x0_size - 1))); + for (auto it = end() - 1; it != target_it; --it) + *it = std::forward(*(it - 1)); + *target_it = value; } + ++x0_size; + return target_it; + } - iterator insert(const_iterator pos, T&& value) - { + iterator insert(const_iterator pos, T&& value) { #ifndef NDEBUG - if (x0_size == N) - Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector."); + if (x0_size == N) + Log.report(logvisor::Fatal, "insert() called on full rstl::reserved_vector."); #endif - auto target_it = base::_const_cast_iterator(pos); - if (pos == cend()) - { - ::new (static_cast(std::addressof(_value(x0_size)))) T(std::forward(value)); - } - else - { - ::new (static_cast(std::addressof(_value(x0_size)))) - T(std::forward(_value(x0_size - 1))); - for (auto it = end() - 1; it != target_it; --it) - *it = std::forward(*(it - 1)); - *target_it = std::forward(value); - } - ++x0_size; - return target_it; + auto target_it = base::_const_cast_iterator(pos); + if (pos == cend()) { + ::new (static_cast(std::addressof(_value(x0_size)))) T(std::forward(value)); + } else { + ::new (static_cast(std::addressof(_value(x0_size)))) T(std::forward(_value(x0_size - 1))); + for (auto it = end() - 1; it != target_it; --it) + *it = std::forward(*(it - 1)); + *target_it = std::forward(value); } + ++x0_size; + return target_it; + } - void resize(size_t size) - { + void resize(size_t size) { #ifndef NDEBUG - if (size > N) - Log.report(logvisor::Fatal, "resize() call overflows rstl::reserved_vector."); + if (size > N) + Log.report(logvisor::Fatal, "resize() call overflows rstl::reserved_vector."); #endif - if (size > x0_size) - { - for (size_t i = x0_size; i < size; ++i) - ::new (static_cast(std::addressof(_value(i)))) T(); - x0_size = size; - } - else if (size < x0_size) - { - if (std::is_destructible::value && !std::is_trivially_destructible::value) - for (size_t i = size; i < x0_size; ++i) - destroy(_value(i)); - x0_size = size; - } + if (size > x0_size) { + for (size_t i = x0_size; i < size; ++i) + ::new (static_cast(std::addressof(_value(i)))) T(); + x0_size = size; + } else if (size < x0_size) { + if (std::is_destructible::value && !std::is_trivially_destructible::value) + for (size_t i = size; i < x0_size; ++i) + destroy(_value(i)); + x0_size = size; } + } - void resize(size_t size, const T& value) - { + void resize(size_t size, const T& value) { #ifndef NDEBUG - if (size > N) - Log.report(logvisor::Fatal, "resize() call overflows rstl::reserved_vector."); + if (size > N) + Log.report(logvisor::Fatal, "resize() call overflows rstl::reserved_vector."); #endif - if (size > x0_size) - { - for (size_t i = x0_size; i < size; ++i) - ::new (static_cast(std::addressof(_value(i)))) T(value); - x0_size = size; - } - else if (size < x0_size) - { - if (std::is_destructible::value && !std::is_trivially_destructible::value) - for (size_t i = size; i < x0_size; ++i) - destroy(_value(i)); - x0_size = size; - } + if (size > x0_size) { + for (size_t i = x0_size; i < size; ++i) + ::new (static_cast(std::addressof(_value(i)))) T(value); + x0_size = size; + } else if (size < x0_size) { + if (std::is_destructible::value && !std::is_trivially_destructible::value) + for (size_t i = size; i < x0_size; ++i) + destroy(_value(i)); + x0_size = size; } + } - iterator erase(const_iterator pos) - { + iterator erase(const_iterator pos) { #ifndef NDEBUG - if (x0_size == 0) - Log.report(logvisor::Fatal, "erase() called on empty rstl::reserved_vector."); + if (x0_size == 0) + Log.report(logvisor::Fatal, "erase() called on empty rstl::reserved_vector."); #endif - for (auto it = base::_const_cast_iterator(pos) + 1; it != end(); ++it) - *(it - 1) = std::forward(*it); - --x0_size; - destroy(_value(x0_size)); - return base::_const_cast_iterator(pos); - } + for (auto it = base::_const_cast_iterator(pos) + 1; it != end(); ++it) + *(it - 1) = std::forward(*it); + --x0_size; + destroy(_value(x0_size)); + return base::_const_cast_iterator(pos); + } - void pop_front() - { - if (x0_size != 0) - erase(begin()); - } + void pop_front() { + if (x0_size != 0) + erase(begin()); + } - void clear() - { - if (std::is_destructible::value && !std::is_trivially_destructible::value) - for (auto it = begin(); it != end(); ++it) - destroy(*it); - x0_size = 0; - } + void clear() { + if (std::is_destructible::value && !std::is_trivially_destructible::value) + for (auto it = begin(); it != end(); ++it) + destroy(*it); + x0_size = 0; + } - size_t size() const noexcept { return x0_size; } - bool empty() const noexcept { return x0_size == 0; } - constexpr size_t capacity() const noexcept { return N; } - const T* data() const noexcept { return std::addressof(_value(0)); } - T* data() noexcept { return std::addressof(_value(0)); } + size_t size() const noexcept { return x0_size; } + bool empty() const noexcept { return x0_size == 0; } + constexpr size_t capacity() const noexcept { return N; } + const T* data() const noexcept { return std::addressof(_value(0)); } + T* data() noexcept { return std::addressof(_value(0)); } - T& back() { return _value(x0_size - 1); } - T& front() { return _value(0); } - const T& back() const { return _value(x0_size - 1); } - const T& front() const { return _value(0); } + T& back() { return _value(x0_size - 1); } + T& front() { return _value(0); } + const T& back() const { return _value(x0_size - 1); } + const T& front() const { return _value(0); } - const_iterator begin() const noexcept { return const_iterator(std::addressof(_value(0))); } - const_iterator end() const noexcept { return const_iterator(std::addressof(_value(x0_size))); } - iterator begin() noexcept { return iterator(std::addressof(_value(0))); } - iterator end() noexcept { return iterator(std::addressof(_value(x0_size))); } - const_iterator cbegin() const noexcept { return begin(); } - const_iterator cend() const noexcept { return end(); } + const_iterator begin() const noexcept { return const_iterator(std::addressof(_value(0))); } + const_iterator end() const noexcept { return const_iterator(std::addressof(_value(x0_size))); } + iterator begin() noexcept { return iterator(std::addressof(_value(0))); } + iterator end() noexcept { return iterator(std::addressof(_value(x0_size))); } + const_iterator cbegin() const noexcept { return begin(); } + const_iterator cend() const noexcept { return end(); } - const_reverse_iterator rbegin() const noexcept - { return const_reverse_iterator(std::addressof(_value(x0_size - 1))); } - const_reverse_iterator rend() const noexcept { return const_reverse_iterator(std::addressof(_value(-1))); } - reverse_iterator rbegin() noexcept { return reverse_iterator(std::addressof(_value(x0_size - 1))); } - reverse_iterator rend() noexcept { return reverse_iterator(std::addressof(_value(-1))); } - const_reverse_iterator crbegin() const noexcept { return rbegin(); } - const_reverse_iterator crend() const noexcept { return rend(); } + const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(std::addressof(_value(x0_size - 1))); } + const_reverse_iterator rend() const noexcept { return const_reverse_iterator(std::addressof(_value(-1))); } + reverse_iterator rbegin() noexcept { return reverse_iterator(std::addressof(_value(x0_size - 1))); } + reverse_iterator rend() noexcept { return reverse_iterator(std::addressof(_value(-1))); } + const_reverse_iterator crbegin() const noexcept { return rbegin(); } + const_reverse_iterator crend() const noexcept { return rend(); } - T& operator[](size_t idx) { return _value(idx); } - const T& operator[](size_t idx) const { return _value(idx); } + T& operator[](size_t idx) { return _value(idx); } + const T& operator[](size_t idx) const { return _value(idx); } }; /** * @brief Vector-style view backed by externally-allocated storage */ template -class prereserved_vector : public _reserved_vector_base -{ - size_t x0_size; - T* x4_data; - T& _value(std::ptrdiff_t idx) { return x4_data[idx]; } - const T& _value(std::ptrdiff_t idx) const { return x4_data[idx]; } +class prereserved_vector : public _reserved_vector_base { + size_t x0_size; + T* x4_data; + T& _value(std::ptrdiff_t idx) { return x4_data[idx]; } + const T& _value(std::ptrdiff_t idx) const { return x4_data[idx]; } public: - using base = _reserved_vector_base; - using iterator = typename base::iterator; - using const_iterator = typename base::const_iterator; - using reverse_iterator = typename base::reverse_iterator; - using const_reverse_iterator = typename base::const_reverse_iterator; - prereserved_vector() : x0_size(0), x4_data(nullptr) {} - prereserved_vector(size_t size, T* data) : x0_size(size), x4_data(data) {} + using base = _reserved_vector_base; + using iterator = typename base::iterator; + using const_iterator = typename base::const_iterator; + using reverse_iterator = typename base::reverse_iterator; + using const_reverse_iterator = typename base::const_reverse_iterator; + prereserved_vector() : x0_size(0), x4_data(nullptr) {} + prereserved_vector(size_t size, T* data) : x0_size(size), x4_data(data) {} - void set_size(size_t n) { x0_size = n; } - void set_data(T* data) { x4_data = data; } + void set_size(size_t n) { x0_size = n; } + void set_data(T* data) { x4_data = data; } - size_t size() const noexcept { return x0_size; } - bool empty() const noexcept { return x0_size == 0; } - const T* data() const noexcept { return x4_data; } - T* data() noexcept { return x4_data; } + size_t size() const noexcept { return x0_size; } + bool empty() const noexcept { return x0_size == 0; } + const T* data() const noexcept { return x4_data; } + T* data() noexcept { return x4_data; } - T& back() { return _value(x0_size - 1); } - T& front() { return _value(0); } - const T& back() const { return _value(x0_size - 1); } - const T& front() const { return _value(0); } + T& back() { return _value(x0_size - 1); } + T& front() { return _value(0); } + const T& back() const { return _value(x0_size - 1); } + const T& front() const { return _value(0); } - const_iterator begin() const noexcept { return const_iterator(std::addressof(_value(0))); } - const_iterator end() const noexcept { return const_iterator(std::addressof(_value(x0_size))); } - iterator begin() noexcept { return iterator(std::addressof(_value(0))); } - iterator end() noexcept { return iterator(std::addressof(_value(x0_size))); } - const_iterator cbegin() const noexcept { return begin(); } - const_iterator cend() const noexcept { return end(); } + const_iterator begin() const noexcept { return const_iterator(std::addressof(_value(0))); } + const_iterator end() const noexcept { return const_iterator(std::addressof(_value(x0_size))); } + iterator begin() noexcept { return iterator(std::addressof(_value(0))); } + iterator end() noexcept { return iterator(std::addressof(_value(x0_size))); } + const_iterator cbegin() const noexcept { return begin(); } + const_iterator cend() const noexcept { return end(); } - const_reverse_iterator rbegin() const noexcept - { return const_reverse_iterator(std::addressof(_value(x0_size - 1))); } - const_reverse_iterator rend() const noexcept { return const_reverse_iterator(std::addressof(_value(-1))); } - reverse_iterator rbegin() noexcept { return reverse_iterator(std::addressof(_value(x0_size - 1))); } - reverse_iterator rend() noexcept { return reverse_iterator(std::addressof(_value(-1))); } - const_reverse_iterator crbegin() const noexcept { return rbegin(); } - const_reverse_iterator crend() const noexcept { return rend(); } + const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(std::addressof(_value(x0_size - 1))); } + const_reverse_iterator rend() const noexcept { return const_reverse_iterator(std::addressof(_value(-1))); } + reverse_iterator rbegin() noexcept { return reverse_iterator(std::addressof(_value(x0_size - 1))); } + reverse_iterator rend() noexcept { return reverse_iterator(std::addressof(_value(-1))); } + const_reverse_iterator crbegin() const noexcept { return rbegin(); } + const_reverse_iterator crend() const noexcept { return rend(); } - T& operator[](size_t idx) { return _value(idx); } - const T& operator[](size_t idx) const { return _value(idx); } + T& operator[](size_t idx) { return _value(idx); } + const T& operator[](size_t idx) const { return _value(idx); } }; -template -ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value) -{ - first = std::lower_bound(first, last, value); - return (!(first == last) && !(value < *first)) ? first : last; +template +ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value) { + first = std::lower_bound(first, last, value); + return (!(first == last) && !(value < *first)) ? first : last; } -template -ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, GetKey getkey) -{ - auto comp = [&](const auto& left, const T& right) { return getkey(left) < right; }; - first = std::lower_bound(first, last, value, comp); - return (!(first == last) && !(value < getkey(*first))) ? first : last; +template +ForwardIt binary_find(ForwardIt first, ForwardIt last, const T& value, GetKey getkey) { + auto comp = [&](const auto& left, const T& right) { return getkey(left) < right; }; + first = std::lower_bound(first, last, value, comp); + return (!(first == last) && !(value < getkey(*first))) ? first : last; } #if 0 @@ -599,5 +638,4 @@ string string_l(const char* data) } #endif -} - +} // namespace rstl diff --git a/Shaders/shader_CFluidPlaneShader.cpp b/Shaders/shader_CFluidPlaneShader.cpp index f2ca8187d..1d51a066b 100644 --- a/Shaders/shader_CFluidPlaneShader.cpp +++ b/Shaders/shader_CFluidPlaneShader.cpp @@ -1,17 +1,10 @@ #include "shader_CFluidPlaneShader.hpp" -const boo::VertexElementDescriptor Shader_CFluidPlaneShader::VtxFmtElems[5] = -{ - {boo::VertexSemantic::Position4}, - {boo::VertexSemantic::Normal4, 0}, - {boo::VertexSemantic::Normal4, 1}, - {boo::VertexSemantic::Normal4, 2}, - {boo::VertexSemantic::Color} -}; +const boo::VertexElementDescriptor Shader_CFluidPlaneShader::VtxFmtElems[5] = {{boo::VertexSemantic::Position4}, + {boo::VertexSemantic::Normal4, 0}, + {boo::VertexSemantic::Normal4, 1}, + {boo::VertexSemantic::Normal4, 2}, + {boo::VertexSemantic::Color}}; -const boo::VertexElementDescriptor Shader_CFluidPlaneShader::TessVtxFmtElems[3] = -{ - {boo::VertexSemantic::Position4}, - {boo::VertexSemantic::UV4, 0}, - {boo::VertexSemantic::UV4, 1} -}; +const boo::VertexElementDescriptor Shader_CFluidPlaneShader::TessVtxFmtElems[3] = { + {boo::VertexSemantic::Position4}, {boo::VertexSemantic::UV4, 0}, {boo::VertexSemantic::UV4, 1}}; diff --git a/Shaders/shader_CFluidPlaneShader.hpp b/Shaders/shader_CFluidPlaneShader.hpp index 87c41b42d..accbe369f 100644 --- a/Shaders/shader_CFluidPlaneShader.hpp +++ b/Shaders/shader_CFluidPlaneShader.hpp @@ -7,113 +7,106 @@ #define URDE_MAX_LIGHTS 8 #endif -enum class EFluidType -{ - NormalWater, - PoisonWater, - Lava, - PhazonFluid, - Four, - ThickLava +enum class EFluidType { NormalWater, PoisonWater, Lava, PhazonFluid, Four, ThickLava }; + +struct SFluidPlaneShaderInfo { + EFluidType m_type; + bool m_hasPatternTex1; + bool m_hasPatternTex2; + bool m_hasColorTex; + bool m_hasBumpMap; + bool m_hasEnvMap; + bool m_hasEnvBumpMap; + bool m_hasLightmap; + bool m_tessellation; + bool m_doubleLightmapBlend; + bool m_additive; + + SFluidPlaneShaderInfo(EFluidType type, bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex, bool hasBumpMap, + bool hasEnvMap, bool hasEnvBumpMap, bool hasLightmap, bool tessellation, + bool doubleLightmapBlend, bool additive) + : m_type(type) + , m_hasPatternTex1(hasPatternTex1) + , m_hasPatternTex2(hasPatternTex2) + , m_hasColorTex(hasColorTex) + , m_hasBumpMap(hasBumpMap) + , m_hasEnvMap(hasEnvMap) + , m_hasEnvBumpMap(hasEnvBumpMap) + , m_hasLightmap(hasLightmap) + , m_tessellation(tessellation) + , m_doubleLightmapBlend(doubleLightmapBlend) + , m_additive(additive) {} }; -struct SFluidPlaneShaderInfo -{ - EFluidType m_type; - bool m_hasPatternTex1; - bool m_hasPatternTex2; - bool m_hasColorTex; - bool m_hasBumpMap; - bool m_hasEnvMap; - bool m_hasEnvBumpMap; - bool m_hasLightmap; - bool m_tessellation; - bool m_doubleLightmapBlend; - bool m_additive; +struct SFluidPlaneDoorShaderInfo { + bool m_hasPatternTex1; + bool m_hasPatternTex2; + bool m_hasColorTex; - SFluidPlaneShaderInfo(EFluidType type, bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex, - bool hasBumpMap, bool hasEnvMap, bool hasEnvBumpMap, bool hasLightmap, - bool tessellation, bool doubleLightmapBlend, bool additive) - : m_type(type), m_hasPatternTex1(hasPatternTex1), m_hasPatternTex2(hasPatternTex2), m_hasColorTex(hasColorTex), - m_hasBumpMap(hasBumpMap), m_hasEnvMap(hasEnvMap), m_hasEnvBumpMap(hasEnvBumpMap), m_hasLightmap(hasLightmap), - m_tessellation(tessellation), m_doubleLightmapBlend(doubleLightmapBlend), m_additive(additive) - {} + SFluidPlaneDoorShaderInfo(bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex) + : m_hasPatternTex1(hasPatternTex1), m_hasPatternTex2(hasPatternTex2), m_hasColorTex(hasColorTex) {} }; -struct SFluidPlaneDoorShaderInfo -{ - bool m_hasPatternTex1; - bool m_hasPatternTex2; - bool m_hasColorTex; +class Shader_CFluidPlaneShader : public hecl::TessellationShader { + friend class Shader_CFluidPlaneDoorShader; + static const boo::VertexElementDescriptor VtxFmtElems[5]; + static const boo::VertexElementDescriptor TessVtxFmtElems[3]; + const SFluidPlaneShaderInfo& m_info; - SFluidPlaneDoorShaderInfo(bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex) - : m_hasPatternTex1(hasPatternTex1), m_hasPatternTex2(hasPatternTex2), m_hasColorTex(hasColorTex) - {} -}; - -class Shader_CFluidPlaneShader : public hecl::TessellationShader -{ - friend class Shader_CFluidPlaneDoorShader; - static const boo::VertexElementDescriptor VtxFmtElems[5]; - static const boo::VertexElementDescriptor TessVtxFmtElems[3]; - const SFluidPlaneShaderInfo& m_info; public: - Shader_CFluidPlaneShader(const SFluidPlaneShaderInfo& in, bool tessellation) - : m_info(in), VtxFmt(tessellation ? boo::VertexFormatInfo(TessVtxFmtElems) : boo::VertexFormatInfo(VtxFmtElems)), - PipelineInfo({in.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha, - in.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha, - boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, - boo::CullMode::None, tessellation ? 1u : 0u}), - HasTessellation(tessellation) {} + Shader_CFluidPlaneShader(const SFluidPlaneShaderInfo& in, bool tessellation) + : m_info(in) + , VtxFmt(tessellation ? boo::VertexFormatInfo(TessVtxFmtElems) : boo::VertexFormatInfo(VtxFmtElems)) + , PipelineInfo({in.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha, + in.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips, + boo::ZTest::LEqual, false, true, false, boo::CullMode::None, tessellation ? 1u : 0u}) + , HasTessellation(tessellation) {} - const boo::VertexFormatInfo VtxFmt; - const boo::AdditionalPipelineInfo PipelineInfo; - bool HasTessellation; - static constexpr bool HasHash = false; - static constexpr uint64_t Hash() { return 0; } - const SFluidPlaneShaderInfo& info() const { return m_info; } + const boo::VertexFormatInfo VtxFmt; + const boo::AdditionalPipelineInfo PipelineInfo; + bool HasTessellation; + static constexpr bool HasHash = false; + static constexpr uint64_t Hash() { return 0; } + const SFluidPlaneShaderInfo& info() const { return m_info; } }; -template -class StageObject_CFluidPlaneShader : public hecl::StageBinary -{ - static std::string BuildShader(const SFluidPlaneShaderInfo& in, bool tessellation); +template +class StageObject_CFluidPlaneShader : public hecl::StageBinary { + static std::string BuildShader(const SFluidPlaneShaderInfo& in, bool tessellation); + public: - StageObject_CFluidPlaneShader(hecl::StageConverter& conv, hecl::FactoryCtx& ctx, - const Shader_CFluidPlaneShader& in) - : hecl::StageBinary(conv, ctx, hecl::StageSourceText(BuildShader(in.info(), in.HasTessellation))) {} + StageObject_CFluidPlaneShader(hecl::StageConverter& conv, hecl::FactoryCtx& ctx, + const Shader_CFluidPlaneShader& in) + : hecl::StageBinary(conv, ctx, hecl::StageSourceText(BuildShader(in.info(), in.HasTessellation))) {} }; -class Shader_CFluidPlaneDoorShader : public hecl::GeneralShader -{ - const SFluidPlaneDoorShaderInfo& m_info; +class Shader_CFluidPlaneDoorShader : public hecl::GeneralShader { + const SFluidPlaneDoorShaderInfo& m_info; + public: - explicit Shader_CFluidPlaneDoorShader(const SFluidPlaneDoorShaderInfo& in) - : m_info(in), VtxFmt(boo::VertexFormatInfo(Shader_CFluidPlaneShader::VtxFmtElems)), - PipelineInfo({boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, - boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false, - boo::CullMode::None}) {} + explicit Shader_CFluidPlaneDoorShader(const SFluidPlaneDoorShaderInfo& in) + : m_info(in) + , VtxFmt(boo::VertexFormatInfo(Shader_CFluidPlaneShader::VtxFmtElems)) + , PipelineInfo({boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips, + boo::ZTest::LEqual, false, true, false, boo::CullMode::None}) {} - const boo::VertexFormatInfo VtxFmt; - const boo::AdditionalPipelineInfo PipelineInfo; - static constexpr bool HasHash = false; - static constexpr uint64_t Hash() { return 0; } - const SFluidPlaneDoorShaderInfo& info() const { return m_info; } + const boo::VertexFormatInfo VtxFmt; + const boo::AdditionalPipelineInfo PipelineInfo; + static constexpr bool HasHash = false; + static constexpr uint64_t Hash() { return 0; } + const SFluidPlaneDoorShaderInfo& info() const { return m_info; } }; -template -class StageObject_CFluidPlaneDoorShader : public hecl::StageBinary -{ - static std::string BuildShader(const SFluidPlaneDoorShaderInfo& in); +template +class StageObject_CFluidPlaneDoorShader : public hecl::StageBinary { + static std::string BuildShader(const SFluidPlaneDoorShaderInfo& in); + public: - StageObject_CFluidPlaneDoorShader(hecl::StageConverter& conv, hecl::FactoryCtx& ctx, - const Shader_CFluidPlaneDoorShader& in) - : hecl::StageBinary(conv, ctx, hecl::StageSourceText(BuildShader(in.info()))) {} + StageObject_CFluidPlaneDoorShader(hecl::StageConverter& conv, hecl::FactoryCtx& ctx, + const Shader_CFluidPlaneDoorShader& in) + : hecl::StageBinary(conv, ctx, hecl::StageSourceText(BuildShader(in.info()))) {} }; -#define UNIVERSAL_PIPELINES_shader_CFluidPlaneShader \ -::Shader_CFluidPlaneShader \ -::Shader_CFluidPlaneDoorShader -#define STAGES_shader_CFluidPlaneShader(P, S) \ -::StageObject_CFluidPlaneShader, \ -::StageObject_CFluidPlaneDoorShader, +#define UNIVERSAL_PIPELINES_shader_CFluidPlaneShader ::Shader_CFluidPlaneShader ::Shader_CFluidPlaneDoorShader +#define STAGES_shader_CFluidPlaneShader(P, S) \ + ::StageObject_CFluidPlaneShader, ::StageObject_CFluidPlaneDoorShader, diff --git a/Shaders/shader_CFluidPlaneShaderGLSL.cpp b/Shaders/shader_CFluidPlaneShaderGLSL.cpp index b83c8a6ad..685ac08e3 100644 --- a/Shaders/shader_CFluidPlaneShaderGLSL.cpp +++ b/Shaders/shader_CFluidPlaneShaderGLSL.cpp @@ -1,170 +1,170 @@ #include "shader_CFluidPlaneShader.hpp" static const char* VS = -"layout(location=0) in vec4 posIn;\n" -"layout(location=1) in vec4 normalIn;\n" -"layout(location=2) in vec4 binormalIn;\n" -"layout(location=3) in vec4 tangentIn;\n" -"layout(location=4) in vec4 colorIn;\n" -"\n" -"UBINDING0 uniform FluidPlaneUniform\n" -"{\n" -" mat4 mv;\n" -" mat4 mvNorm;\n" -" mat4 proj;\n" -" mat4 texMtxs[6];\n" -"};\n" -"\n" -"struct VertToFrag\n" -"{\n" -" vec4 mvPos;\n" -" vec4 mvNorm;\n" -" vec4 mvBinorm;\n" -" vec4 mvTangent;\n" -" vec4 color;\n" -" vec2 uvs[7];\n" -"};\n" -"\n" -"SBINDING(0) out VertToFrag vtf;\n" -"void main()\n" -"{\n" -" vec4 pos = vec4(posIn.xyz, 1.0);\n" -" vtf.mvPos = mv * pos;\n" -" gl_Position = proj * vtf.mvPos;\n" -" vtf.mvNorm = mvNorm * normalIn;\n" -" vtf.mvBinorm = mvNorm * binormalIn;\n" -" vtf.mvTangent = mvNorm * tangentIn;\n" -" vtf.color = vec4(colorIn.xyz, 1.0);\n" -" vtf.uvs[0] = (texMtxs[0] * pos).xy;\n" -" vtf.uvs[1] = (texMtxs[1] * pos).xy;\n" -" vtf.uvs[2] = (texMtxs[2] * pos).xy;\n" -"%s" // Additional TCGs here -"}\n"; + "layout(location=0) in vec4 posIn;\n" + "layout(location=1) in vec4 normalIn;\n" + "layout(location=2) in vec4 binormalIn;\n" + "layout(location=3) in vec4 tangentIn;\n" + "layout(location=4) in vec4 colorIn;\n" + "\n" + "UBINDING0 uniform FluidPlaneUniform\n" + "{\n" + " mat4 mv;\n" + " mat4 mvNorm;\n" + " mat4 proj;\n" + " mat4 texMtxs[6];\n" + "};\n" + "\n" + "struct VertToFrag\n" + "{\n" + " vec4 mvPos;\n" + " vec4 mvNorm;\n" + " vec4 mvBinorm;\n" + " vec4 mvTangent;\n" + " vec4 color;\n" + " vec2 uvs[7];\n" + "};\n" + "\n" + "SBINDING(0) out VertToFrag vtf;\n" + "void main()\n" + "{\n" + " vec4 pos = vec4(posIn.xyz, 1.0);\n" + " vtf.mvPos = mv * pos;\n" + " gl_Position = proj * vtf.mvPos;\n" + " vtf.mvNorm = mvNorm * normalIn;\n" + " vtf.mvBinorm = mvNorm * binormalIn;\n" + " vtf.mvTangent = mvNorm * tangentIn;\n" + " vtf.color = vec4(colorIn.xyz, 1.0);\n" + " vtf.uvs[0] = (texMtxs[0] * pos).xy;\n" + " vtf.uvs[1] = (texMtxs[1] * pos).xy;\n" + " vtf.uvs[2] = (texMtxs[2] * pos).xy;\n" + "%s" // Additional TCGs here + "}\n"; static const char* TessVS = -"layout(location=0) in vec4 posIn;\n" -"layout(location=1) in vec4 outerLevelsIn;\n" -"layout(location=2) in vec2 innerLevelsIn;\n" -"\n" -"struct VertToControl\n" -"{\n" -" vec4 minMaxPos;\n" -" vec4 outerLevels;\n" -" vec2 innerLevels;\n" -"};\n" -"\n" -"SBINDING(0) out VertToControl vtc;\n" -"\n" -"void main()\n" -"{\n" -" vtc.minMaxPos = posIn;\n" -" vtc.outerLevels = outerLevelsIn;\n" -" vtc.innerLevels = innerLevelsIn;\n" -"}\n"; + "layout(location=0) in vec4 posIn;\n" + "layout(location=1) in vec4 outerLevelsIn;\n" + "layout(location=2) in vec2 innerLevelsIn;\n" + "\n" + "struct VertToControl\n" + "{\n" + " vec4 minMaxPos;\n" + " vec4 outerLevels;\n" + " vec2 innerLevels;\n" + "};\n" + "\n" + "SBINDING(0) out VertToControl vtc;\n" + "\n" + "void main()\n" + "{\n" + " vtc.minMaxPos = posIn;\n" + " vtc.outerLevels = outerLevelsIn;\n" + " vtc.innerLevels = innerLevelsIn;\n" + "}\n"; static const char* TessCS = -"#extension GL_ARB_tessellation_shader: enable\n" -"layout(vertices = 1) out;\n" -"\n" -"struct VertToControl\n" -"{\n" -" vec4 minMaxPos;\n" -" vec4 outerLevels;\n" -" vec2 innerLevels;\n" -"};\n" -"\n" -"SBINDING(0) in VertToControl vtc[];\n" -"SBINDING(0) patch out vec4 minMaxPos;\n" -"\n" -"void main()\n" -"{\n" -" minMaxPos = vtc[gl_InvocationID].minMaxPos;\n" -" for (int i=0 ; i<4 ; ++i)\n" -" gl_TessLevelOuter[i] = vtc[gl_InvocationID].outerLevels[i];\n" -" for (int i=0 ; i<2 ; ++i)\n" -" gl_TessLevelInner[i] = vtc[gl_InvocationID].innerLevels[i];\n" -"}"; + "#extension GL_ARB_tessellation_shader: enable\n" + "layout(vertices = 1) out;\n" + "\n" + "struct VertToControl\n" + "{\n" + " vec4 minMaxPos;\n" + " vec4 outerLevels;\n" + " vec2 innerLevels;\n" + "};\n" + "\n" + "SBINDING(0) in VertToControl vtc[];\n" + "SBINDING(0) patch out vec4 minMaxPos;\n" + "\n" + "void main()\n" + "{\n" + " minMaxPos = vtc[gl_InvocationID].minMaxPos;\n" + " for (int i=0 ; i<4 ; ++i)\n" + " gl_TessLevelOuter[i] = vtc[gl_InvocationID].outerLevels[i];\n" + " for (int i=0 ; i<2 ; ++i)\n" + " gl_TessLevelInner[i] = vtc[gl_InvocationID].innerLevels[i];\n" + "}"; static const char* TessES = -"#extension GL_ARB_tessellation_shader: enable\n" -"layout(quads, equal_spacing) in;\n" -"\n" -"struct Ripple\n" -"{\n" -" vec4 center; // time, distFalloff\n" -" vec4 params; // amplitude, lookupPhase, lookupTime\n" -"};\n" -"\n" -"UBINDING0 uniform FluidPlaneUniform\n" -"{\n" -" mat4 mv;\n" -" mat4 mvNorm;\n" -" mat4 proj;\n" -" mat4 texMtxs[6];\n" -" Ripple ripples[20];\n" -" vec4 colorMul;\n" -" float rippleNormResolution;\n" -"};\n" -"\n" -"struct VertToFrag\n" -"{\n" -" vec4 mvPos;\n" -" vec4 mvNorm;\n" -" vec4 mvBinorm;\n" -" vec4 mvTangent;\n" -" vec4 color;\n" -" vec2 uvs[7];\n" -"};\n" -"\n" -"SBINDING(0) patch in vec4 minMaxPos;\n" -"SBINDING(0) out VertToFrag vtf;\n" -"\n" -"TBINDING%d uniform sampler2D RippleMap;\n" -"\n" -"const float PI_X2 = 6.283185307179586;\n" -"\n" -"void ApplyRipple(in Ripple ripple, in vec2 pos, inout float height)\n" -"{\n" -" float dist = length(ripple.center.xy - pos);\n" -" float rippleV = textureLod(RippleMap, vec2(dist * ripple.center.w, ripple.center.z), 0.0).r;\n" -" height += rippleV * ripple.params.x * sin((dist * ripple.params.y + ripple.params.z) * PI_X2);\n" -"}\n" -"\n" -"void main()\n" -"{\n" -" vec2 posIn = vec2(mix(minMaxPos.x, minMaxPos.z, gl_TessCoord.x),\n" -" mix(minMaxPos.y, minMaxPos.w, gl_TessCoord.y));\n" -" float height = 0.0;\n" -" float upHeight = 0.0;\n" -" float downHeight = 0.0;\n" -" float rightHeight = 0.0;\n" -" float leftHeight = 0.0;\n" -" for (int i=0 ; i<20 ; ++i)\n" -" {\n" -" ApplyRipple(ripples[i], posIn, height);\n" -" ApplyRipple(ripples[i], posIn + vec2(0.0, rippleNormResolution), upHeight);\n" -" ApplyRipple(ripples[i], posIn - vec2(0.0, rippleNormResolution), downHeight);\n" -" ApplyRipple(ripples[i], posIn + vec2(rippleNormResolution, 0.0), rightHeight);\n" -" ApplyRipple(ripples[i], posIn - vec2(rippleNormResolution, 0.0), leftHeight);\n" -" }\n" -" vec4 normalIn = vec4(normalize(vec3((leftHeight - rightHeight),\n" -" (downHeight - upHeight),\n" -" rippleNormResolution)), 1.0);\n" -" vec4 binormalIn = vec4(normalIn.x, normalIn.z, -normalIn.y, 1.0);\n" -" vec4 tangentIn = vec4(normalIn.z, normalIn.y, -normalIn.x, 1.0);\n" -" vec4 pos = vec4(posIn, height, 1.0);\n" -" vtf.mvPos = mv * pos;\n" -" gl_Position = proj * vtf.mvPos;\n" -" vtf.mvNorm = mvNorm * normalIn;\n" -" vtf.mvBinorm = mvNorm * binormalIn;\n" -" vtf.mvTangent = mvNorm * tangentIn;\n" -" vtf.color = max(height, 0.0) * colorMul;\n" -" vtf.color.a = 1.0;\n" -" vtf.uvs[0] = (texMtxs[0] * pos).xy;\n" -" vtf.uvs[1] = (texMtxs[1] * pos).xy;\n" -" vtf.uvs[2] = (texMtxs[2] * pos).xy;\n" -"%s\n" // Additional TCGs here -"}\n"; + "#extension GL_ARB_tessellation_shader: enable\n" + "layout(quads, equal_spacing) in;\n" + "\n" + "struct Ripple\n" + "{\n" + " vec4 center; // time, distFalloff\n" + " vec4 params; // amplitude, lookupPhase, lookupTime\n" + "};\n" + "\n" + "UBINDING0 uniform FluidPlaneUniform\n" + "{\n" + " mat4 mv;\n" + " mat4 mvNorm;\n" + " mat4 proj;\n" + " mat4 texMtxs[6];\n" + " Ripple ripples[20];\n" + " vec4 colorMul;\n" + " float rippleNormResolution;\n" + "};\n" + "\n" + "struct VertToFrag\n" + "{\n" + " vec4 mvPos;\n" + " vec4 mvNorm;\n" + " vec4 mvBinorm;\n" + " vec4 mvTangent;\n" + " vec4 color;\n" + " vec2 uvs[7];\n" + "};\n" + "\n" + "SBINDING(0) patch in vec4 minMaxPos;\n" + "SBINDING(0) out VertToFrag vtf;\n" + "\n" + "TBINDING%d uniform sampler2D RippleMap;\n" + "\n" + "const float PI_X2 = 6.283185307179586;\n" + "\n" + "void ApplyRipple(in Ripple ripple, in vec2 pos, inout float height)\n" + "{\n" + " float dist = length(ripple.center.xy - pos);\n" + " float rippleV = textureLod(RippleMap, vec2(dist * ripple.center.w, ripple.center.z), 0.0).r;\n" + " height += rippleV * ripple.params.x * sin((dist * ripple.params.y + ripple.params.z) * PI_X2);\n" + "}\n" + "\n" + "void main()\n" + "{\n" + " vec2 posIn = vec2(mix(minMaxPos.x, minMaxPos.z, gl_TessCoord.x),\n" + " mix(minMaxPos.y, minMaxPos.w, gl_TessCoord.y));\n" + " float height = 0.0;\n" + " float upHeight = 0.0;\n" + " float downHeight = 0.0;\n" + " float rightHeight = 0.0;\n" + " float leftHeight = 0.0;\n" + " for (int i=0 ; i<20 ; ++i)\n" + " {\n" + " ApplyRipple(ripples[i], posIn, height);\n" + " ApplyRipple(ripples[i], posIn + vec2(0.0, rippleNormResolution), upHeight);\n" + " ApplyRipple(ripples[i], posIn - vec2(0.0, rippleNormResolution), downHeight);\n" + " ApplyRipple(ripples[i], posIn + vec2(rippleNormResolution, 0.0), rightHeight);\n" + " ApplyRipple(ripples[i], posIn - vec2(rippleNormResolution, 0.0), leftHeight);\n" + " }\n" + " vec4 normalIn = vec4(normalize(vec3((leftHeight - rightHeight),\n" + " (downHeight - upHeight),\n" + " rippleNormResolution)), 1.0);\n" + " vec4 binormalIn = vec4(normalIn.x, normalIn.z, -normalIn.y, 1.0);\n" + " vec4 tangentIn = vec4(normalIn.z, normalIn.y, -normalIn.x, 1.0);\n" + " vec4 pos = vec4(posIn, height, 1.0);\n" + " vtf.mvPos = mv * pos;\n" + " gl_Position = proj * vtf.mvPos;\n" + " vtf.mvNorm = mvNorm * normalIn;\n" + " vtf.mvBinorm = mvNorm * binormalIn;\n" + " vtf.mvTangent = mvNorm * tangentIn;\n" + " vtf.color = max(height, 0.0) * colorMul;\n" + " vtf.color.a = 1.0;\n" + " vtf.uvs[0] = (texMtxs[0] * pos).xy;\n" + " vtf.uvs[1] = (texMtxs[1] * pos).xy;\n" + " vtf.uvs[2] = (texMtxs[2] * pos).xy;\n" + "%s\n" // Additional TCGs here + "}\n"; static const char* FS = "struct Light\n" @@ -317,552 +317,486 @@ static const char* FSDoor = "%s" // Combiner expression here "}\n"; -static std::string _BuildFS(const SFluidPlaneShaderInfo& info) -{ - std::string textures; - std::string combiner; - int nextTex = 0; - int nextTCG = 3; - int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv; +static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { + std::string textures; + std::string combiner; + int nextTex = 0; + int nextTCG = 3; + int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv; - if (info.m_hasPatternTex1) - { - textures += hecl::Format("TBINDING%d uniform sampler2D patternTex1;\n", nextTex++); - } - if (info.m_hasPatternTex2) - { - textures += hecl::Format("TBINDING%d uniform sampler2D patternTex2;\n", nextTex++); - } - if (info.m_hasColorTex) - { - textures += hecl::Format("TBINDING%d uniform sampler2D colorTex;\n", nextTex++); - } - if (info.m_hasBumpMap) - { - textures += hecl::Format("TBINDING%d uniform sampler2D bumpMap;\n", nextTex++); - } - if (info.m_hasEnvMap) - { - textures += hecl::Format("TBINDING%d uniform sampler2D envMap;\n", nextTex++); - } - if (info.m_hasEnvBumpMap) - { - textures += hecl::Format("TBINDING%d uniform sampler2D envBumpMap;\n", nextTex++); - } - if (info.m_hasLightmap) - { - textures += hecl::Format("TBINDING%d uniform sampler2D lightMap;\n", nextTex++); + if (info.m_hasPatternTex1) { + textures += hecl::Format("TBINDING%d uniform sampler2D patternTex1;\n", nextTex++); + } + if (info.m_hasPatternTex2) { + textures += hecl::Format("TBINDING%d uniform sampler2D patternTex2;\n", nextTex++); + } + if (info.m_hasColorTex) { + textures += hecl::Format("TBINDING%d uniform sampler2D colorTex;\n", nextTex++); + } + if (info.m_hasBumpMap) { + textures += hecl::Format("TBINDING%d uniform sampler2D bumpMap;\n", nextTex++); + } + if (info.m_hasEnvMap) { + textures += hecl::Format("TBINDING%d uniform sampler2D envMap;\n", nextTex++); + } + if (info.m_hasEnvBumpMap) { + textures += hecl::Format("TBINDING%d uniform sampler2D envBumpMap;\n", nextTex++); + } + if (info.m_hasLightmap) { + textures += hecl::Format("TBINDING%d uniform sampler2D lightMap;\n", nextTex++); + } + + if (info.m_hasBumpMap) { + bumpMapUv = nextTCG++; + } + if (info.m_hasEnvBumpMap) { + envBumpMapUv = nextTCG++; + } + if (info.m_hasEnvMap) { + envMapUv = nextTCG++; + } + if (info.m_hasLightmap) { + lightmapUv = nextTCG; + } + + switch (info.m_type) { + case EFluidType::NormalWater: + case EFluidType::PhazonFluid: + case EFluidType::Four: + if (info.m_hasLightmap) { + combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv); + // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 + // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS + // Output reg 2 + // KColor 2 + if (info.m_doubleLightmapBlend) { + // 1: Tex4TCG2, Tex4, GX_COLOR1A1 + // C2, TEX, KONST, RAS + // Output reg 2 + // KColor 3 + // Tex * K2 + Lighting + combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n"; + } else { + // mix(Tex * K2, Tex, K3) + Lighting + combiner += " lighting += lightMapTexel * kColor2;\n"; + } } - if (info.m_hasBumpMap) - { - bumpMapUv = nextTCG++; - } - if (info.m_hasEnvBumpMap) - { - envBumpMapUv = nextTCG++; - } - if (info.m_hasEnvMap) - { - envMapUv = nextTCG++; - } - if (info.m_hasLightmap) - { - lightmapUv = nextTCG; + // Next: Tex0TCG, Tex0, GX_COLOR1A1 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 + + // Next: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev + + // Next: Tex2TCG, Tex2, GX_COLOR1A1 + // ZERO, TEX, hasTex4 ? C2 : RAS, PREV + // Output reg prev + + // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + lighting) *\n" + " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; + else + combiner += " colorOut = lighting * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; } - switch (info.m_type) - { - case EFluidType::NormalWater: - case EFluidType::PhazonFluid: - case EFluidType::Four: - if (info.m_hasLightmap) - { - combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv); - // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 - // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS - // Output reg 2 - // KColor 2 - if (info.m_doubleLightmapBlend) - { - // 1: Tex4TCG2, Tex4, GX_COLOR1A1 - // C2, TEX, KONST, RAS - // Output reg 2 - // KColor 3 - // Tex * K2 + Lighting - combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n"; - } - else - { - // mix(Tex * K2, Tex, K3) + Lighting - combiner += " lighting += lightMapTexel * kColor2;\n"; - } - } + if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) { + // Make previous stage indirect, mtx0 + combiner += hecl::Format( + " vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n" + " vec2(fog.indScale, -fog.indScale);\n", + envBumpMapUv); + combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n"; + } else if (info.m_hasEnvMap) { + // Next: envTCG, envTex, NULL + // PREV, TEX, KONST, ZERO + // Output reg prev + // KColor 1 - // Next: Tex0TCG, Tex0, GX_COLOR1A1 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // Next: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // Next: Tex2TCG, Tex2, GX_COLOR1A1 - // ZERO, TEX, hasTex4 ? C2 : RAS, PREV - // Output reg prev - - // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + lighting) *\n" - " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; - else - combiner += " colorOut = lighting * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - - if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) - { - // Make previous stage indirect, mtx0 - combiner += hecl::Format(" vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n" - " vec2(fog.indScale, -fog.indScale);\n", envBumpMapUv); - combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n"; - } - else if (info.m_hasEnvMap) - { - // Next: envTCG, envTex, NULL - // PREV, TEX, KONST, ZERO - // Output reg prev - // KColor 1 - - // Make previous stage indirect, mtx0 - if (info.m_hasColorTex) - combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n"; - combiner += hecl::Format(" vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n" - " vec2(fog.indScale, -fog.indScale);\n", envBumpMapUv); - combiner += hecl::Format(" colorOut = mix(colorOut, texture(envMap, indUvs + vtf.uvs[%d]), kColor1);\n", - envMapUv); - } - else if (info.m_hasColorTex) - { - combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n"; - } - - break; - - case EFluidType::PoisonWater: - if (info.m_hasLightmap) - { - combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv); - // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 - // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS - // Output reg 2 - // KColor 2 - if (info.m_doubleLightmapBlend) - { - // 1: Tex4TCG2, Tex4, GX_COLOR1A1 - // C2, TEX, KONST, RAS - // Output reg 2 - // KColor 3 - // Tex * K2 + Lighting - combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n"; - } - else - { - // mix(Tex * K2, Tex, K3) + Lighting - combiner += " lighting += lightMapTexel * kColor2;\n"; - } - } - - // Next: Tex0TCG, Tex0, GX_COLOR1A1 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // Next: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // Next: Tex2TCG, Tex2, GX_COLOR1A1 - // ZERO, TEX, hasTex4 ? C2 : RAS, PREV - // Output reg prev - - // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + lighting) *\n" - " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; - else - combiner += " colorOut = lighting * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - if (info.m_hasColorTex) - { - if (info.m_hasEnvBumpMap) - { - // Make previous stage indirect, mtx0 - combiner += hecl::Format(" vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n" - " vec2(fog.indScale, -fog.indScale);\n", envBumpMapUv); - combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n"; - } - else - { - combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n"; - } - } - - break; - - case EFluidType::Lava: - // 0: Tex0TCG, Tex0, GX_COLOR0A0 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // 1: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // 2: Tex2TCG, Tex2, NULL - // ZERO, TEX, ONE, PREV - // Output reg prev - - // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + vtf.color) *\n" - " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; - else - combiner += " colorOut = vtf.color * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - if (info.m_hasColorTex) - combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n"; - - if (info.m_hasBumpMap) - { - // 3: bumpMapTCG, bumpMap, NULL - // ZERO, TEX, ONE, HALF - // Output reg 0, no clamp, no bias - - // 4: bumpMapTCG2, bumpMap, NULL - // ZERO, TEX, ONE, C0 - // Output reg 0, subtract, clamp, no bias - - combiner += " vec3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n" - " float lx = dot(vtf.mvTangent.xyz, lightVec);\n" - " float ly = dot(vtf.mvBinorm.xyz, lightVec);\n"; - combiner += hecl::Format(" vec4 emboss1 = texture(bumpMap, vtf.uvs[%d]) + vec4(0.5);\n" - " vec4 emboss2 = texture(bumpMap, vtf.uvs[%d] + vec2(lx, ly));\n", - bumpMapUv, bumpMapUv); - - // 5: NULL, NULL, NULL - // ZERO, PREV, C0, ZERO - // Output reg prev, scale 2, clamp - - // colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0 - combiner += "colorOut *= clamp((emboss1 + vec4(0.5) - emboss2) * vec4(2.0), vec4(0.0), vec4(1.0));\n"; - } - - break; - - case EFluidType::ThickLava: - // 0: Tex0TCG, Tex0, GX_COLOR0A0 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // 1: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // 2: Tex2TCG, Tex2, NULL - // ZERO, TEX, ONE, PREV - // Output reg prev - - // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + vtf.color) *\n" - " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; - else - combiner += " colorOut = vtf.color * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - if (info.m_hasColorTex) - combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n"; - - if (info.m_hasBumpMap) - { - // 3: bumpMapTCG, bumpMap, NULL - // ZERO, TEX, PREV, ZERO - // Output reg prev, scale 2 - combiner += hecl::Format(" vec4 emboss1 = texture(bumpMap, vtf.uvs[%d]) + vec4(0.5);\n", bumpMapUv); - combiner += "colorOut *= emboss1 * vec4(2.0);\n"; - } - - break; + // Make previous stage indirect, mtx0 + if (info.m_hasColorTex) + combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n"; + combiner += hecl::Format( + " vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n" + " vec2(fog.indScale, -fog.indScale);\n", + envBumpMapUv); + combiner += + hecl::Format(" colorOut = mix(colorOut, texture(envMap, indUvs + vtf.uvs[%d]), kColor1);\n", envMapUv); + } else if (info.m_hasColorTex) { + combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n"; } - combiner += " colorOut.a = kColor0.a;\n"; + break; - char *finalFSs; - asprintf(&finalFSs, FS, int(info.m_additive), textures.c_str(), combiner.c_str()); - std::string ret(finalFSs); - free(finalFSs); - return ret; -} - -static std::string _BuildAdditionalTCGs(const SFluidPlaneShaderInfo& info) -{ - std::string additionalTCGs; - int nextTCG = 3; - int nextMtx = 4; - - if (info.m_hasBumpMap) - { - additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[0] * pos).xy;\n", nextTCG++); - } - if (info.m_hasEnvBumpMap) - { - additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[3] * vec4(normalIn.xyz, 1.0)).xy;\n", nextTCG++); - } - if (info.m_hasEnvMap) - { - additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * pos).xy;\n", nextTCG++, nextMtx++); - } - if (info.m_hasLightmap) - { - additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * pos).xy;\n", nextTCG, nextMtx); + case EFluidType::PoisonWater: + if (info.m_hasLightmap) { + combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv); + // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 + // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS + // Output reg 2 + // KColor 2 + if (info.m_doubleLightmapBlend) { + // 1: Tex4TCG2, Tex4, GX_COLOR1A1 + // C2, TEX, KONST, RAS + // Output reg 2 + // KColor 3 + // Tex * K2 + Lighting + combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n"; + } else { + // mix(Tex * K2, Tex, K3) + Lighting + combiner += " lighting += lightMapTexel * kColor2;\n"; + } } - return additionalTCGs; -} + // Next: Tex0TCG, Tex0, GX_COLOR1A1 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 -static std::string _BuildVS(const SFluidPlaneShaderInfo& info, bool tessellation) -{ - if (tessellation) - return TessVS; + // Next: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev - std::string additionalTCGs = _BuildAdditionalTCGs(info); + // Next: Tex2TCG, Tex2, GX_COLOR1A1 + // ZERO, TEX, hasTex4 ? C2 : RAS, PREV + // Output reg prev - char *finalVSs; - asprintf(&finalVSs, VS, additionalTCGs.c_str()); - std::string ret(finalVSs); - free(finalVSs); - return ret; -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildVS(in, tessellation); -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildVS(in, tessellation); -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildVS(in, tessellation); -} - -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildFS(in); -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildFS(in); -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildFS(in); -} - -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return TessCS; -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return TessCS; -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return TessCS; -} - -static std::string BuildES(const SFluidPlaneShaderInfo& info) -{ - int nextTex = 0; - if (info.m_hasPatternTex1) - nextTex++; - if (info.m_hasPatternTex2) - nextTex++; - if (info.m_hasColorTex) - nextTex++; - if (info.m_hasBumpMap) - nextTex++; - if (info.m_hasEnvMap) - nextTex++; - if (info.m_hasEnvBumpMap) - nextTex++; - if (info.m_hasLightmap) - nextTex++; - - std::string additionalTCGs = _BuildAdditionalTCGs(info); - - char *finalESs; - asprintf(&finalESs, TessES, nextTex, additionalTCGs.c_str()); - std::string ret(finalESs); - free(finalESs); - - return ret; -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return BuildES(in); -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return BuildES(in); -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return BuildES(in); -} - -static std::string _BuildVS(const SFluidPlaneDoorShaderInfo& info) -{ - char *finalVSs; - asprintf(&finalVSs, VS, ""); - std::string ret(finalVSs); - free(finalVSs); - return ret; -} - -static std::string _BuildFS(const SFluidPlaneDoorShaderInfo& info) -{ - int nextTex = 0; - std::string textures; - std::string combiner; - - if (info.m_hasPatternTex1) - { - textures += hecl::Format("TBINDING%d uniform sampler2D patternTex1;\n", nextTex++); - } - if (info.m_hasPatternTex2) - { - textures += hecl::Format("TBINDING%d uniform sampler2D patternTex2;\n", nextTex++); - } - if (info.m_hasColorTex) - { - textures += hecl::Format("TBINDING%d uniform sampler2D colorTex;\n", nextTex++); + // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + lighting) *\n" + " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; + else + combiner += " colorOut = lighting * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; } - // Tex0 * kColor0 * Tex1 + Tex2 - if (info.m_hasPatternTex1 && info.m_hasPatternTex2) - { - combiner += " colorOut = texture(patternTex1, vtf.uvs[0]) * kColor0 *\n" - " texture(patternTex2, vtf.uvs[1]);\n"; + if (info.m_hasColorTex) { + if (info.m_hasEnvBumpMap) { + // Make previous stage indirect, mtx0 + combiner += hecl::Format( + " vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n" + " vec2(fog.indScale, -fog.indScale);\n", + envBumpMapUv); + combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n"; + } else { + combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n"; + } } - else - { - combiner += " colorOut = vec4(0.0);\n"; + + break; + + case EFluidType::Lava: + // 0: Tex0TCG, Tex0, GX_COLOR0A0 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 + + // 1: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev + + // 2: Tex2TCG, Tex2, NULL + // ZERO, TEX, ONE, PREV + // Output reg prev + + // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + vtf.color) *\n" + " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; + else + combiner += " colorOut = vtf.color * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; } if (info.m_hasColorTex) - { - combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n"; + combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n"; + + if (info.m_hasBumpMap) { + // 3: bumpMapTCG, bumpMap, NULL + // ZERO, TEX, ONE, HALF + // Output reg 0, no clamp, no bias + + // 4: bumpMapTCG2, bumpMap, NULL + // ZERO, TEX, ONE, C0 + // Output reg 0, subtract, clamp, no bias + + combiner += + " vec3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n" + " float lx = dot(vtf.mvTangent.xyz, lightVec);\n" + " float ly = dot(vtf.mvBinorm.xyz, lightVec);\n"; + combiner += hecl::Format( + " vec4 emboss1 = texture(bumpMap, vtf.uvs[%d]) + vec4(0.5);\n" + " vec4 emboss2 = texture(bumpMap, vtf.uvs[%d] + vec2(lx, ly));\n", + bumpMapUv, bumpMapUv); + + // 5: NULL, NULL, NULL + // ZERO, PREV, C0, ZERO + // Output reg prev, scale 2, clamp + + // colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0 + combiner += "colorOut *= clamp((emboss1 + vec4(0.5) - emboss2) * vec4(2.0), vec4(0.0), vec4(1.0));\n"; } - combiner += " colorOut.a = kColor0.a;\n"; + break; - char *finalFSs; - asprintf(&finalFSs, FSDoor, textures.c_str(), combiner.c_str()); - std::string ret(finalFSs); - free(finalFSs); - return ret; + case EFluidType::ThickLava: + // 0: Tex0TCG, Tex0, GX_COLOR0A0 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 + + // 1: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev + + // 2: Tex2TCG, Tex2, NULL + // ZERO, TEX, ONE, PREV + // Output reg prev + + // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + vtf.color) *\n" + " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; + else + combiner += " colorOut = vtf.color * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; + } + + if (info.m_hasColorTex) + combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n"; + + if (info.m_hasBumpMap) { + // 3: bumpMapTCG, bumpMap, NULL + // ZERO, TEX, PREV, ZERO + // Output reg prev, scale 2 + combiner += hecl::Format(" vec4 emboss1 = texture(bumpMap, vtf.uvs[%d]) + vec4(0.5);\n", bumpMapUv); + combiner += "colorOut *= emboss1 * vec4(2.0);\n"; + } + + break; + } + + combiner += " colorOut.a = kColor0.a;\n"; + + char* finalFSs; + asprintf(&finalFSs, FS, int(info.m_additive), textures.c_str(), combiner.c_str()); + std::string ret(finalFSs); + free(finalFSs); + return ret; +} + +static std::string _BuildAdditionalTCGs(const SFluidPlaneShaderInfo& info) { + std::string additionalTCGs; + int nextTCG = 3; + int nextMtx = 4; + + if (info.m_hasBumpMap) { + additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[0] * pos).xy;\n", nextTCG++); + } + if (info.m_hasEnvBumpMap) { + additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[3] * vec4(normalIn.xyz, 1.0)).xy;\n", nextTCG++); + } + if (info.m_hasEnvMap) { + additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * pos).xy;\n", nextTCG++, nextMtx++); + } + if (info.m_hasLightmap) { + additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * pos).xy;\n", nextTCG, nextMtx); + } + + return additionalTCGs; +} + +static std::string _BuildVS(const SFluidPlaneShaderInfo& info, bool tessellation) { + if (tessellation) + return TessVS; + + std::string additionalTCGs = _BuildAdditionalTCGs(info); + + char* finalVSs; + asprintf(&finalVSs, VS, additionalTCGs.c_str()); + std::string ret(finalVSs); + free(finalVSs); + return ret; +} +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildVS(in, tessellation); +} +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildVS(in, tessellation); +} +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildVS(in, tessellation); } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildVS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildFS(in); } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildVS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildFS(in); } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildVS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildFS(in); } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildFS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return TessCS; } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildFS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return TessCS; } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildFS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return TessCS; +} + +static std::string BuildES(const SFluidPlaneShaderInfo& info) { + int nextTex = 0; + if (info.m_hasPatternTex1) + nextTex++; + if (info.m_hasPatternTex2) + nextTex++; + if (info.m_hasColorTex) + nextTex++; + if (info.m_hasBumpMap) + nextTex++; + if (info.m_hasEnvMap) + nextTex++; + if (info.m_hasEnvBumpMap) + nextTex++; + if (info.m_hasLightmap) + nextTex++; + + std::string additionalTCGs = _BuildAdditionalTCGs(info); + + char* finalESs; + asprintf(&finalESs, TessES, nextTex, additionalTCGs.c_str()); + std::string ret(finalESs); + free(finalESs); + + return ret; +} +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return BuildES(in); +} +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return BuildES(in); +} +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return BuildES(in); +} + +static std::string _BuildVS(const SFluidPlaneDoorShaderInfo& info) { + char* finalVSs; + asprintf(&finalVSs, VS, ""); + std::string ret(finalVSs); + free(finalVSs); + return ret; +} + +static std::string _BuildFS(const SFluidPlaneDoorShaderInfo& info) { + int nextTex = 0; + std::string textures; + std::string combiner; + + if (info.m_hasPatternTex1) { + textures += hecl::Format("TBINDING%d uniform sampler2D patternTex1;\n", nextTex++); + } + if (info.m_hasPatternTex2) { + textures += hecl::Format("TBINDING%d uniform sampler2D patternTex2;\n", nextTex++); + } + if (info.m_hasColorTex) { + textures += hecl::Format("TBINDING%d uniform sampler2D colorTex;\n", nextTex++); + } + + // Tex0 * kColor0 * Tex1 + Tex2 + if (info.m_hasPatternTex1 && info.m_hasPatternTex2) { + combiner += + " colorOut = texture(patternTex1, vtf.uvs[0]) * kColor0 *\n" + " texture(patternTex2, vtf.uvs[1]);\n"; + } else { + combiner += " colorOut = vec4(0.0);\n"; + } + + if (info.m_hasColorTex) { + combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n"; + } + + combiner += " colorOut.a = kColor0.a;\n"; + + char* finalFSs; + asprintf(&finalFSs, FSDoor, textures.c_str(), combiner.c_str()); + std::string ret(finalFSs); + free(finalFSs); + return ret; +} + +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildVS(in); +} +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildVS(in); +} +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildVS(in); +} + +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildFS(in); +} +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildFS(in); +} +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildFS(in); } diff --git a/Shaders/shader_CFluidPlaneShaderHLSL.cpp b/Shaders/shader_CFluidPlaneShaderHLSL.cpp index 59a43437f..2e3a2a885 100644 --- a/Shaders/shader_CFluidPlaneShaderHLSL.cpp +++ b/Shaders/shader_CFluidPlaneShaderHLSL.cpp @@ -1,206 +1,206 @@ #include "shader_CFluidPlaneShader.hpp" static const char* VS = -"struct VertData\n" -"{\n" -" float4 posIn : POSITION;\n" -" float4 normalIn : NORMAL0;\n" -" float4 binormalIn : NORMAL1;\n" -" float4 tangentIn : NORMAL2;\n" -" float4 colorIn : COLOR;\n" -"};\n" -"\n" -"cbuffer FluidPlaneUniform : register(b0)\n" -"{\n" -" float4x4 mv;\n" -" float4x4 mvNorm;\n" -" float4x4 proj;\n" -" float4x4 texMtxs[6];\n" -"};\n" -"\n" -"struct VertToFrag\n" -"{\n" -" float4 pos : SV_Position;\n" -" float4 mvPos : POSITION;\n" -" float4 mvNorm : NORMAL;\n" -" float4 mvBinorm : BINORMAL;\n" -" float4 mvTangent : TANGENT;\n" -" float4 color : COLOR;\n" -" float2 uvs[7] : UV;\n" -"};\n" -"\n" -"VertToFrag main(in VertData v)\n" -"{\n" -" VertToFrag vtf;\n" -" float4 pos = float4(v.posIn.xyz, 1.0);\n" -" float4 normalIn = v.normalIn;\n" -" vtf.mvPos = mul(mv, pos);\n" -" vtf.pos = mul(proj, vtf.mvPos);\n" -" vtf.mvNorm = mul(mvNorm, v.normalIn);\n" -" vtf.mvBinorm = mul(mvNorm, v.binormalIn);\n" -" vtf.mvTangent = mul(mvNorm, v.tangentIn);\n" -" vtf.color = float4(v.colorIn.xyz, 1.0);\n" -" vtf.uvs[0] = mul(texMtxs[0], pos).xy;\n" -" vtf.uvs[1] = mul(texMtxs[1], pos).xy;\n" -" vtf.uvs[2] = mul(texMtxs[2], pos).xy;\n" -"%s" // Additional TCGs here -" return vtf;\n" -"}\n"; + "struct VertData\n" + "{\n" + " float4 posIn : POSITION;\n" + " float4 normalIn : NORMAL0;\n" + " float4 binormalIn : NORMAL1;\n" + " float4 tangentIn : NORMAL2;\n" + " float4 colorIn : COLOR;\n" + "};\n" + "\n" + "cbuffer FluidPlaneUniform : register(b0)\n" + "{\n" + " float4x4 mv;\n" + " float4x4 mvNorm;\n" + " float4x4 proj;\n" + " float4x4 texMtxs[6];\n" + "};\n" + "\n" + "struct VertToFrag\n" + "{\n" + " float4 pos : SV_Position;\n" + " float4 mvPos : POSITION;\n" + " float4 mvNorm : NORMAL;\n" + " float4 mvBinorm : BINORMAL;\n" + " float4 mvTangent : TANGENT;\n" + " float4 color : COLOR;\n" + " float2 uvs[7] : UV;\n" + "};\n" + "\n" + "VertToFrag main(in VertData v)\n" + "{\n" + " VertToFrag vtf;\n" + " float4 pos = float4(v.posIn.xyz, 1.0);\n" + " float4 normalIn = v.normalIn;\n" + " vtf.mvPos = mul(mv, pos);\n" + " vtf.pos = mul(proj, vtf.mvPos);\n" + " vtf.mvNorm = mul(mvNorm, v.normalIn);\n" + " vtf.mvBinorm = mul(mvNorm, v.binormalIn);\n" + " vtf.mvTangent = mul(mvNorm, v.tangentIn);\n" + " vtf.color = float4(v.colorIn.xyz, 1.0);\n" + " vtf.uvs[0] = mul(texMtxs[0], pos).xy;\n" + " vtf.uvs[1] = mul(texMtxs[1], pos).xy;\n" + " vtf.uvs[2] = mul(texMtxs[2], pos).xy;\n" + "%s" // Additional TCGs here + " return vtf;\n" + "}\n"; static const char* TessVS = -"struct VertData\n" -"{\n" -" float4 posIn : POSITION;\n" -" float4 outerLevelsIn : UV0;\n" -" float2 innerLevelsIn : UV1;\n" -"};\n" -"\n" -"struct VertToControl\n" -"{\n" -" float4 minMaxPos : POSITION;\n" -" float4 outerLevels : OUTERLEVELS;\n" -" float2 innerLevels : INNERLEVELS;\n" -"};\n" -"\n" -"VertToControl main(in VertData v)\n" -"{\n" -" VertToControl vtc;\n" -" vtc.minMaxPos = v.posIn;\n" -" vtc.outerLevels = v.outerLevelsIn;\n" -" vtc.innerLevels = v.innerLevelsIn;\n" -" return vtc;\n" -"}\n"; + "struct VertData\n" + "{\n" + " float4 posIn : POSITION;\n" + " float4 outerLevelsIn : UV0;\n" + " float2 innerLevelsIn : UV1;\n" + "};\n" + "\n" + "struct VertToControl\n" + "{\n" + " float4 minMaxPos : POSITION;\n" + " float4 outerLevels : OUTERLEVELS;\n" + " float2 innerLevels : INNERLEVELS;\n" + "};\n" + "\n" + "VertToControl main(in VertData v)\n" + "{\n" + " VertToControl vtc;\n" + " vtc.minMaxPos = v.posIn;\n" + " vtc.outerLevels = v.outerLevelsIn;\n" + " vtc.innerLevels = v.innerLevelsIn;\n" + " return vtc;\n" + "}\n"; static const char* TessCS = -"struct VertToControl\n" -"{\n" -" float4 minMaxPos : POSITION;\n" -" float4 outerLevels : OUTERLEVELS;\n" -" float2 innerLevels : INNERLEVELS;\n" -"};\n" -"\n" -"struct ControlToEvaluation\n" -"{\n" -" float4 minMaxPos : POSITION;\n" -" float outerLevels[4] : SV_TessFactor;\n" -" float innerLevels[2] : SV_InsideTessFactor;\n" -"};\n" -"\n" -"struct ControlPoint\n" -"{};\n" -"\n" -"ControlToEvaluation patchmain(InputPatch vtc, uint id : SV_PrimitiveID)\n" -"{\n" -" ControlToEvaluation cte;\n" -" cte.minMaxPos = vtc[id].minMaxPos;\n" -" for (int i=0 ; i<4 ; ++i)\n" -" cte.outerLevels[i] = vtc[id].outerLevels[i];\n" -" for (int i=0 ; i<2 ; ++i)\n" -" cte.innerLevels[i] = vtc[id].innerLevels[i];\n" -" return cte;\n" -"}\n" -"\n" -"[domain(\"quad\")]\n" -"[partitioning(\"integer\")]\n" -"[outputtopology(\"triangle_cw\")]\n" -"[outputcontrolpoints(1)]\n" -"[patchconstantfunc(\"patchmain\")]\n" -"ControlPoint main(InputPatch vtc, uint i : SV_OutputControlPointID, uint id : SV_PrimitiveID)\n" -"{\n" -" ControlPoint pt;\n" -" return pt;\n" -"}\n"; + "struct VertToControl\n" + "{\n" + " float4 minMaxPos : POSITION;\n" + " float4 outerLevels : OUTERLEVELS;\n" + " float2 innerLevels : INNERLEVELS;\n" + "};\n" + "\n" + "struct ControlToEvaluation\n" + "{\n" + " float4 minMaxPos : POSITION;\n" + " float outerLevels[4] : SV_TessFactor;\n" + " float innerLevels[2] : SV_InsideTessFactor;\n" + "};\n" + "\n" + "struct ControlPoint\n" + "{};\n" + "\n" + "ControlToEvaluation patchmain(InputPatch vtc, uint id : SV_PrimitiveID)\n" + "{\n" + " ControlToEvaluation cte;\n" + " cte.minMaxPos = vtc[id].minMaxPos;\n" + " for (int i=0 ; i<4 ; ++i)\n" + " cte.outerLevels[i] = vtc[id].outerLevels[i];\n" + " for (int i=0 ; i<2 ; ++i)\n" + " cte.innerLevels[i] = vtc[id].innerLevels[i];\n" + " return cte;\n" + "}\n" + "\n" + "[domain(\"quad\")]\n" + "[partitioning(\"integer\")]\n" + "[outputtopology(\"triangle_cw\")]\n" + "[outputcontrolpoints(1)]\n" + "[patchconstantfunc(\"patchmain\")]\n" + "ControlPoint main(InputPatch vtc, uint i : SV_OutputControlPointID, uint id : SV_PrimitiveID)\n" + "{\n" + " ControlPoint pt;\n" + " return pt;\n" + "}\n"; static const char* TessES = -"struct Ripple\n" -"{\n" -" float4 center; // time, distFalloff\n" -" float4 params; // amplitude, lookupPhase, lookupTime\n" -"};\n" -"\n" -"cbuffer FluidPlaneUniform : register(b0)\n" -"{\n" -" float4x4 mv;\n" -" float4x4 mvNorm;\n" -" float4x4 proj;\n" -" float4x4 texMtxs[6];\n" -" Ripple ripples[20];\n" -" float4 colorMul;\n" -" float rippleNormResolution;\n" -"};\n" -"\n" -"struct VertToFrag\n" -"{\n" -" float4 pos : SV_Position;\n" -" float4 mvPos : POSITION;\n" -" float4 mvNorm : NORMAL;\n" -" float4 mvBinorm : BINORMAL;\n" -" float4 mvTangent : TANGENT;\n" -" float4 color : COLOR;\n" -" float2 uvs[7] : UV;\n" -"};\n" -"\n" -"struct ControlToEvaluation\n" -"{\n" -" float4 minMaxPos : POSITION;\n" -" float outerLevels[4] : SV_TessFactor;\n" -" float innerLevels[2] : SV_InsideTessFactor;\n" -"};\n" -"\n" -"struct ControlPoint\n" -"{};\n" -"\n" -"Texture2D RippleMap : register(t%d);\n" -"SamplerState samp : register(s2);\n" -"\n" -"static const float PI_X2 = 6.283185307179586;\n" -"\n" -"static void ApplyRipple(in Ripple ripple, in float2 pos, inout float height)\n" -"{\n" -" float dist = length(ripple.center.xy - pos);\n" -" float rippleV = RippleMap.SampleLevel(samp, float2(dist * ripple.center.w, ripple.center.z), 0.0).r;\n" -" height += rippleV * ripple.params.x * sin((dist * ripple.params.y + ripple.params.z) * PI_X2);\n" -"}\n" -"\n" -"[domain(\"quad\")]\n" -"VertToFrag main(in ControlToEvaluation cte, in float2 TessCoord : SV_DomainLocation,\n" -" const OutputPatch bezpatch)\n" -"{\n" -" float2 posIn = float2(lerp(cte.minMaxPos.x, cte.minMaxPos.z, TessCoord.x),\n" -" lerp(cte.minMaxPos.y, cte.minMaxPos.w, TessCoord.y));\n" -" float height = 0.0;\n" -" float upHeight = 0.0;\n" -" float downHeight = 0.0;\n" -" float rightHeight = 0.0;\n" -" float leftHeight = 0.0;\n" -" for (int i=0 ; i<20 ; ++i)\n" -" {\n" -" ApplyRipple(ripples[i], posIn, height);\n" -" ApplyRipple(ripples[i], posIn + float2(0.0, rippleNormResolution), upHeight);\n" -" ApplyRipple(ripples[i], posIn - float2(0.0, rippleNormResolution), downHeight);\n" -" ApplyRipple(ripples[i], posIn + float2(rippleNormResolution, 0.0), rightHeight);\n" -" ApplyRipple(ripples[i], posIn - float2(rippleNormResolution, 0.0), leftHeight);\n" -" }\n" -" float4 normalIn = float4(normalize(float3((leftHeight - rightHeight),\n" -" (downHeight - upHeight),\n" -" rippleNormResolution)), 1.0);\n" -" float4 binormalIn = float4(normalIn.x, normalIn.z, -normalIn.y, 1.0);\n" -" float4 tangentIn = float4(normalIn.z, normalIn.y, -normalIn.x, 1.0);\n" -" float4 pos = float4(posIn, height, 1.0);\n" -" VertToFrag vtf;\n" -" vtf.mvPos = mul(mv, pos);\n" -" vtf.pos = mul(proj, vtf.mvPos);\n" -" vtf.mvNorm = mul(mvNorm, normalIn);\n" -" vtf.mvBinorm = mul(mvNorm, binormalIn);\n" -" vtf.mvTangent = mul(mvNorm, tangentIn);\n" -" vtf.color = max(height, 0.0) * colorMul;\n" -" vtf.color.a = 1.0;\n" -" vtf.uvs[0] = mul(texMtxs[0], pos).xy;\n" -" vtf.uvs[1] = mul(texMtxs[1], pos).xy;\n" -" vtf.uvs[2] = mul(texMtxs[2], pos).xy;\n" -"%s\n" // Additional TCGs here -" return vtf;\n" -"}\n"; + "struct Ripple\n" + "{\n" + " float4 center; // time, distFalloff\n" + " float4 params; // amplitude, lookupPhase, lookupTime\n" + "};\n" + "\n" + "cbuffer FluidPlaneUniform : register(b0)\n" + "{\n" + " float4x4 mv;\n" + " float4x4 mvNorm;\n" + " float4x4 proj;\n" + " float4x4 texMtxs[6];\n" + " Ripple ripples[20];\n" + " float4 colorMul;\n" + " float rippleNormResolution;\n" + "};\n" + "\n" + "struct VertToFrag\n" + "{\n" + " float4 pos : SV_Position;\n" + " float4 mvPos : POSITION;\n" + " float4 mvNorm : NORMAL;\n" + " float4 mvBinorm : BINORMAL;\n" + " float4 mvTangent : TANGENT;\n" + " float4 color : COLOR;\n" + " float2 uvs[7] : UV;\n" + "};\n" + "\n" + "struct ControlToEvaluation\n" + "{\n" + " float4 minMaxPos : POSITION;\n" + " float outerLevels[4] : SV_TessFactor;\n" + " float innerLevels[2] : SV_InsideTessFactor;\n" + "};\n" + "\n" + "struct ControlPoint\n" + "{};\n" + "\n" + "Texture2D RippleMap : register(t%d);\n" + "SamplerState samp : register(s2);\n" + "\n" + "static const float PI_X2 = 6.283185307179586;\n" + "\n" + "static void ApplyRipple(in Ripple ripple, in float2 pos, inout float height)\n" + "{\n" + " float dist = length(ripple.center.xy - pos);\n" + " float rippleV = RippleMap.SampleLevel(samp, float2(dist * ripple.center.w, ripple.center.z), 0.0).r;\n" + " height += rippleV * ripple.params.x * sin((dist * ripple.params.y + ripple.params.z) * PI_X2);\n" + "}\n" + "\n" + "[domain(\"quad\")]\n" + "VertToFrag main(in ControlToEvaluation cte, in float2 TessCoord : SV_DomainLocation,\n" + " const OutputPatch bezpatch)\n" + "{\n" + " float2 posIn = float2(lerp(cte.minMaxPos.x, cte.minMaxPos.z, TessCoord.x),\n" + " lerp(cte.minMaxPos.y, cte.minMaxPos.w, TessCoord.y));\n" + " float height = 0.0;\n" + " float upHeight = 0.0;\n" + " float downHeight = 0.0;\n" + " float rightHeight = 0.0;\n" + " float leftHeight = 0.0;\n" + " for (int i=0 ; i<20 ; ++i)\n" + " {\n" + " ApplyRipple(ripples[i], posIn, height);\n" + " ApplyRipple(ripples[i], posIn + float2(0.0, rippleNormResolution), upHeight);\n" + " ApplyRipple(ripples[i], posIn - float2(0.0, rippleNormResolution), downHeight);\n" + " ApplyRipple(ripples[i], posIn + float2(rippleNormResolution, 0.0), rightHeight);\n" + " ApplyRipple(ripples[i], posIn - float2(rippleNormResolution, 0.0), leftHeight);\n" + " }\n" + " float4 normalIn = float4(normalize(float3((leftHeight - rightHeight),\n" + " (downHeight - upHeight),\n" + " rippleNormResolution)), 1.0);\n" + " float4 binormalIn = float4(normalIn.x, normalIn.z, -normalIn.y, 1.0);\n" + " float4 tangentIn = float4(normalIn.z, normalIn.y, -normalIn.x, 1.0);\n" + " float4 pos = float4(posIn, height, 1.0);\n" + " VertToFrag vtf;\n" + " vtf.mvPos = mul(mv, pos);\n" + " vtf.pos = mul(proj, vtf.mvPos);\n" + " vtf.mvNorm = mul(mvNorm, normalIn);\n" + " vtf.mvBinorm = mul(mvNorm, binormalIn);\n" + " vtf.mvTangent = mul(mvNorm, tangentIn);\n" + " vtf.color = max(height, 0.0) * colorMul;\n" + " vtf.color.a = 1.0;\n" + " vtf.uvs[0] = mul(texMtxs[0], pos).xy;\n" + " vtf.uvs[1] = mul(texMtxs[1], pos).xy;\n" + " vtf.uvs[2] = mul(texMtxs[2], pos).xy;\n" + "%s\n" // Additional TCGs here + " return vtf;\n" + "}\n"; static const char* FS = "struct Light\n" @@ -354,472 +354,425 @@ static const char* FSDoor = " return colorOut;\n" "}\n"; -static std::string _BuildFS(const SFluidPlaneShaderInfo& info) -{ - std::string additionalTCGs; - std::string textures; - std::string combiner; - int nextTex = 0; - int nextTCG = 3; - int nextMtx = 4; - int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv; +static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { + std::string additionalTCGs; + std::string textures; + std::string combiner; + int nextTex = 0; + int nextTCG = 3; + int nextMtx = 4; + int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv; - if (info.m_hasPatternTex1) - textures += hecl::Format("Texture2D patternTex1 : register(t%d);\n", nextTex++); - if (info.m_hasPatternTex2) - textures += hecl::Format("Texture2D patternTex2 : register(t%d);\n", nextTex++); - if (info.m_hasColorTex) - textures += hecl::Format("Texture2D colorTex : register(t%d);\n", nextTex++); - if (info.m_hasBumpMap) - textures += hecl::Format("Texture2D bumpMap : register(t%d);\n", nextTex++); - if (info.m_hasEnvMap) - textures += hecl::Format("Texture2D envMap : register(t%d);\n", nextTex++); - if (info.m_hasEnvBumpMap) - textures += hecl::Format("Texture2D envBumpMap : register(t%d);\n", nextTex++); - if (info.m_hasLightmap) - textures += hecl::Format("Texture2D lightMap : register(t%d);\n", nextTex++); + if (info.m_hasPatternTex1) + textures += hecl::Format("Texture2D patternTex1 : register(t%d);\n", nextTex++); + if (info.m_hasPatternTex2) + textures += hecl::Format("Texture2D patternTex2 : register(t%d);\n", nextTex++); + if (info.m_hasColorTex) + textures += hecl::Format("Texture2D colorTex : register(t%d);\n", nextTex++); + if (info.m_hasBumpMap) + textures += hecl::Format("Texture2D bumpMap : register(t%d);\n", nextTex++); + if (info.m_hasEnvMap) + textures += hecl::Format("Texture2D envMap : register(t%d);\n", nextTex++); + if (info.m_hasEnvBumpMap) + textures += hecl::Format("Texture2D envBumpMap : register(t%d);\n", nextTex++); + if (info.m_hasLightmap) + textures += hecl::Format("Texture2D lightMap : register(t%d);\n", nextTex++); - if (info.m_hasBumpMap) - { - bumpMapUv = nextTCG; - additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[0], pos).xy;\n", nextTCG++); - } - if (info.m_hasEnvBumpMap) - { - envBumpMapUv = nextTCG; - additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[3], float4(normalIn.xyz, 1.0)).xy;\n", nextTCG++); - } - if (info.m_hasEnvMap) - { - envMapUv = nextTCG; - additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], pos).xy;\n", nextTCG++, nextMtx++); - } - if (info.m_hasLightmap) - { - lightmapUv = nextTCG; - additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], pos).xy;\n", nextTCG++, nextMtx++); + if (info.m_hasBumpMap) { + bumpMapUv = nextTCG; + additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[0], pos).xy;\n", nextTCG++); + } + if (info.m_hasEnvBumpMap) { + envBumpMapUv = nextTCG; + additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[3], float4(normalIn.xyz, 1.0)).xy;\n", nextTCG++); + } + if (info.m_hasEnvMap) { + envMapUv = nextTCG; + additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], pos).xy;\n", nextTCG++, nextMtx++); + } + if (info.m_hasLightmap) { + lightmapUv = nextTCG; + additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], pos).xy;\n", nextTCG++, nextMtx++); + } + + switch (info.m_type) { + case EFluidType::NormalWater: + case EFluidType::PhazonFluid: + case EFluidType::Four: + if (info.m_hasLightmap) { + combiner += hecl::Format(" float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[%d]);\n", lightmapUv); + // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 + // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS + // Output reg 2 + // KColor 2 + if (info.m_doubleLightmapBlend) { + // 1: Tex4TCG2, Tex4, GX_COLOR1A1 + // C2, TEX, KONST, RAS + // Output reg 2 + // KColor 3 + // Tex * K2 + Lighting + combiner += " lighting += lerp(lightMapTexel * kColor2, lightMapTexel, kColor3);\n"; + } else { + // mix(Tex * K2, Tex, K3) + Lighting + combiner += " lighting += lightMapTexel * kColor2;\n"; + } } - switch (info.m_type) - { - case EFluidType::NormalWater: - case EFluidType::PhazonFluid: - case EFluidType::Four: - if (info.m_hasLightmap) - { - combiner += hecl::Format(" float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[%d]);\n", lightmapUv); - // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 - // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS - // Output reg 2 - // KColor 2 - if (info.m_doubleLightmapBlend) - { - // 1: Tex4TCG2, Tex4, GX_COLOR1A1 - // C2, TEX, KONST, RAS - // Output reg 2 - // KColor 3 - // Tex * K2 + Lighting - combiner += " lighting += lerp(lightMapTexel * kColor2, lightMapTexel, kColor3);\n"; - } - else - { - // mix(Tex * K2, Tex, K3) + Lighting - combiner += " lighting += lightMapTexel * kColor2;\n"; - } - } + // Next: Tex0TCG, Tex0, GX_COLOR1A1 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 - // Next: Tex0TCG, Tex0, GX_COLOR1A1 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 + // Next: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev - // Next: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev + // Next: Tex2TCG, Tex2, GX_COLOR1A1 + // ZERO, TEX, hasTex4 ? C2 : RAS, PREV + // Output reg prev - // Next: Tex2TCG, Tex2, GX_COLOR1A1 - // ZERO, TEX, hasTex4 ? C2 : RAS, PREV - // Output reg prev - - // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + lighting) *\n" - " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; - else - combiner += " colorOut = lighting * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - - if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) - { - // Make previous stage indirect, mtx0 - combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n" - " float2(fog.indScale, -fog.indScale);\n", envBumpMapUv); - combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n"; - } - else if (info.m_hasEnvMap) - { - // Next: envTCG, envTex, NULL - // PREV, TEX, KONST, ZERO - // Output reg prev - // KColor 1 - - // Make previous stage indirect, mtx0 - if (info.m_hasColorTex) - combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n"; - combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n" - " float2(fog.indScale, -fog.indScale);\n", envBumpMapUv); - combiner += hecl::Format(" colorOut = lerp(colorOut, envMap.Sample(samp, indUvs + vtf.uvs[%d]), kColor1);\n", - envMapUv); - } - else if (info.m_hasColorTex) - { - combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n"; - } - - break; - - case EFluidType::PoisonWater: - if (info.m_hasLightmap) - { - combiner += hecl::Format(" float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[%d]);\n", lightmapUv); - // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 - // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS - // Output reg 2 - // KColor 2 - if (info.m_doubleLightmapBlend) - { - // 1: Tex4TCG2, Tex4, GX_COLOR1A1 - // C2, TEX, KONST, RAS - // Output reg 2 - // KColor 3 - // Tex * K2 + Lighting - combiner += " lighting += lerp(lightMapTexel * kColor2, lightMapTexel, kColor3);\n"; - } - else - { - // mix(Tex * K2, Tex, K3) + Lighting - combiner += " lighting += lightMapTexel * kColor2;\n"; - } - } - - // Next: Tex0TCG, Tex0, GX_COLOR1A1 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // Next: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // Next: Tex2TCG, Tex2, GX_COLOR1A1 - // ZERO, TEX, hasTex4 ? C2 : RAS, PREV - // Output reg prev - - // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + lighting) *\n" - " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; - else - combiner += " colorOut = lighting * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - if (info.m_hasColorTex) - { - if (info.m_hasEnvBumpMap) - { - // Make previous stage indirect, mtx0 - combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n" - " float2(fog.indScale, -fog.indScale);\n", envBumpMapUv); - combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n"; - } - else - { - combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n"; - } - } - - break; - - case EFluidType::Lava: - // 0: Tex0TCG, Tex0, GX_COLOR0A0 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // 1: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // 2: Tex2TCG, Tex2, NULL - // ZERO, TEX, ONE, PREV - // Output reg prev - - // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + vtf.color) *\n" - " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; - else - combiner += " colorOut = vtf.color * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - if (info.m_hasColorTex) - combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]);\n"; - - if (info.m_hasBumpMap) - { - // 3: bumpMapTCG, bumpMap, NULL - // ZERO, TEX, ONE, HALF - // Output reg 0, no clamp, no bias - - // 4: bumpMapTCG2, bumpMap, NULL - // ZERO, TEX, ONE, C0 - // Output reg 0, subtract, clamp, no bias - - combiner += " float3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n" - " float lx = dot(vtf.mvTangent.xyz, lightVec);\n" - " float ly = dot(vtf.mvBinorm.xyz, lightVec);\n"; - combiner += hecl::Format(" float4 emboss1 = bumpMap.Sample(samp, vtf.uvs[%d]) + float4(0.5);\n" - " float4 emboss2 = bumpMap.Sample(samp, vtf.uvs[%d] + float2(lx, ly));\n", - bumpMapUv, bumpMapUv); - - // 5: NULL, NULL, NULL - // ZERO, PREV, C0, ZERO - // Output reg prev, scale 2, clamp - - // colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0 - combiner += "colorOut *= clamp((emboss1 + float4(0.5) - emboss2) * float4(2.0), float4(0.0), float4(1.0));\n"; - } - - break; - - case EFluidType::ThickLava: - // 0: Tex0TCG, Tex0, GX_COLOR0A0 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // 1: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // 2: Tex2TCG, Tex2, NULL - // ZERO, TEX, ONE, PREV - // Output reg prev - - // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + vtf.color) *\n" - " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; - else - combiner += " colorOut = vtf.color * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - if (info.m_hasColorTex) - combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]);\n"; - - if (info.m_hasBumpMap) - { - // 3: bumpMapTCG, bumpMap, NULL - // ZERO, TEX, PREV, ZERO - // Output reg prev, scale 2 - combiner += hecl::Format(" float4 emboss1 = bumpMap.Sample(samp, vtf.uvs[%d]) + float4(0.5);\n", bumpMapUv); - combiner += "colorOut *= emboss1 * float4(2.0);\n"; - } - - break; + // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + lighting) *\n" + " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; + else + combiner += " colorOut = lighting * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; } - combiner += " colorOut.a = kColor0.a;\n"; + if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) { + // Make previous stage indirect, mtx0 + combiner += hecl::Format( + " float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n" + " float2(fog.indScale, -fog.indScale);\n", + envBumpMapUv); + combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n"; + } else if (info.m_hasEnvMap) { + // Next: envTCG, envTex, NULL + // PREV, TEX, KONST, ZERO + // Output reg prev + // KColor 1 - char *finalFS; - asprintf(&finalFS, FS, int(info.m_additive), textures.c_str(), combiner.c_str()); - std::string ret(finalFS); - free(finalFS); - return ret; -} - -static std::string _BuildAdditionalTCGs(const SFluidPlaneShaderInfo& info) -{ - std::string additionalTCGs; - int nextTCG = 3; - int nextMtx = 4; - - if (info.m_hasBumpMap) - { - additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[0], pos).xy;\n", nextTCG++); - } - if (info.m_hasEnvBumpMap) - { - additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[3], float4(normalIn.xyz, 1.0)).xy;\n", nextTCG++); - } - if (info.m_hasEnvMap) - { - additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], pos).xy;\n", nextTCG++, nextMtx++); - } - if (info.m_hasLightmap) - { - additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], pos).xy;\n", nextTCG, nextMtx); + // Make previous stage indirect, mtx0 + if (info.m_hasColorTex) + combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n"; + combiner += hecl::Format( + " float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n" + " float2(fog.indScale, -fog.indScale);\n", + envBumpMapUv); + combiner += hecl::Format(" colorOut = lerp(colorOut, envMap.Sample(samp, indUvs + vtf.uvs[%d]), kColor1);\n", + envMapUv); + } else if (info.m_hasColorTex) { + combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n"; } - return additionalTCGs; -} + break; -static std::string _BuildVS(const SFluidPlaneShaderInfo& info, bool tessellation) -{ - if (tessellation) - return TessVS; - - std::string additionalTCGs = _BuildAdditionalTCGs(info); - - char *finalVSs; - asprintf(&finalVSs, VS, additionalTCGs.c_str()); - std::string ret(finalVSs); - free(finalVSs); - return ret; -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildVS(in, tessellation); -} - -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildFS(in); -} - -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return TessCS; -} - -static std::string BuildES(const SFluidPlaneShaderInfo& info) -{ - int nextTex = 0; - if (info.m_hasPatternTex1) - nextTex++; - if (info.m_hasPatternTex2) - nextTex++; - if (info.m_hasColorTex) - nextTex++; - if (info.m_hasBumpMap) - nextTex++; - if (info.m_hasEnvMap) - nextTex++; - if (info.m_hasEnvBumpMap) - nextTex++; - if (info.m_hasLightmap) - nextTex++; - - std::string additionalTCGs = _BuildAdditionalTCGs(info); - - char *finalESs; - asprintf(&finalESs, TessES, nextTex, additionalTCGs.c_str()); - std::string ret(finalESs); - free(finalESs); - - return ret; -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return BuildES(in); -} - -static std::string _BuildVS(const SFluidPlaneDoorShaderInfo& info) -{ - char *finalVSs; - asprintf(&finalVSs, VS, ""); - std::string ret(finalVSs); - free(finalVSs); - return ret; -} - -static std::string _BuildFS(const SFluidPlaneDoorShaderInfo& info) -{ - int nextTex = 0; - std::string textures; - std::string combiner; - - if (info.m_hasPatternTex1) - { - textures += hecl::Format("Texture2D patternTex1 : register(t%d);\n", nextTex++); - } - if (info.m_hasPatternTex2) - { - textures += hecl::Format("Texture2D patternTex2 : register(t%d);\n", nextTex++); - } - if (info.m_hasColorTex) - { - textures += hecl::Format("Texture2D colorTex : register(t%d);\n", nextTex++); + case EFluidType::PoisonWater: + if (info.m_hasLightmap) { + combiner += hecl::Format(" float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[%d]);\n", lightmapUv); + // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 + // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS + // Output reg 2 + // KColor 2 + if (info.m_doubleLightmapBlend) { + // 1: Tex4TCG2, Tex4, GX_COLOR1A1 + // C2, TEX, KONST, RAS + // Output reg 2 + // KColor 3 + // Tex * K2 + Lighting + combiner += " lighting += lerp(lightMapTexel * kColor2, lightMapTexel, kColor3);\n"; + } else { + // mix(Tex * K2, Tex, K3) + Lighting + combiner += " lighting += lightMapTexel * kColor2;\n"; + } } - // Tex0 * kColor0 * Tex1 + Tex2 - if (info.m_hasPatternTex1 && info.m_hasPatternTex2) - { - combiner += " colorOut = patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 *\n" - " patternTex2.Sample(samp, vtf.uvs[1]);\n"; + // Next: Tex0TCG, Tex0, GX_COLOR1A1 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 + + // Next: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev + + // Next: Tex2TCG, Tex2, GX_COLOR1A1 + // ZERO, TEX, hasTex4 ? C2 : RAS, PREV + // Output reg prev + + // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + lighting) *\n" + " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; + else + combiner += " colorOut = lighting * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; } - else - { - combiner += " colorOut = float4(0.0);\n"; + + if (info.m_hasColorTex) { + if (info.m_hasEnvBumpMap) { + // Make previous stage indirect, mtx0 + combiner += hecl::Format( + " float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n" + " float2(fog.indScale, -fog.indScale);\n", + envBumpMapUv); + combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n"; + } else { + combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n"; + } + } + + break; + + case EFluidType::Lava: + // 0: Tex0TCG, Tex0, GX_COLOR0A0 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 + + // 1: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev + + // 2: Tex2TCG, Tex2, NULL + // ZERO, TEX, ONE, PREV + // Output reg prev + + // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + vtf.color) *\n" + " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; + else + combiner += " colorOut = vtf.color * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; } if (info.m_hasColorTex) - { - combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]);\n"; + combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]);\n"; + + if (info.m_hasBumpMap) { + // 3: bumpMapTCG, bumpMap, NULL + // ZERO, TEX, ONE, HALF + // Output reg 0, no clamp, no bias + + // 4: bumpMapTCG2, bumpMap, NULL + // ZERO, TEX, ONE, C0 + // Output reg 0, subtract, clamp, no bias + + combiner += + " float3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n" + " float lx = dot(vtf.mvTangent.xyz, lightVec);\n" + " float ly = dot(vtf.mvBinorm.xyz, lightVec);\n"; + combiner += hecl::Format( + " float4 emboss1 = bumpMap.Sample(samp, vtf.uvs[%d]) + float4(0.5);\n" + " float4 emboss2 = bumpMap.Sample(samp, vtf.uvs[%d] + float2(lx, ly));\n", + bumpMapUv, bumpMapUv); + + // 5: NULL, NULL, NULL + // ZERO, PREV, C0, ZERO + // Output reg prev, scale 2, clamp + + // colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0 + combiner += "colorOut *= clamp((emboss1 + float4(0.5) - emboss2) * float4(2.0), float4(0.0), float4(1.0));\n"; } - combiner += " colorOut.a = kColor0.a;\n"; + break; - char *finalFSs; - asprintf(&finalFSs, FSDoor, textures.c_str(), combiner.c_str()); - std::string ret(finalFSs); - free(finalFSs); - return ret; + case EFluidType::ThickLava: + // 0: Tex0TCG, Tex0, GX_COLOR0A0 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 + + // 1: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev + + // 2: Tex2TCG, Tex2, NULL + // ZERO, TEX, ONE, PREV + // Output reg prev + + // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + vtf.color) *\n" + " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; + else + combiner += " colorOut = vtf.color * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; + } + + if (info.m_hasColorTex) + combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]);\n"; + + if (info.m_hasBumpMap) { + // 3: bumpMapTCG, bumpMap, NULL + // ZERO, TEX, PREV, ZERO + // Output reg prev, scale 2 + combiner += hecl::Format(" float4 emboss1 = bumpMap.Sample(samp, vtf.uvs[%d]) + float4(0.5);\n", bumpMapUv); + combiner += "colorOut *= emboss1 * float4(2.0);\n"; + } + + break; + } + + combiner += " colorOut.a = kColor0.a;\n"; + + char* finalFS; + asprintf(&finalFS, FS, int(info.m_additive), textures.c_str(), combiner.c_str()); + std::string ret(finalFS); + free(finalFS); + return ret; +} + +static std::string _BuildAdditionalTCGs(const SFluidPlaneShaderInfo& info) { + std::string additionalTCGs; + int nextTCG = 3; + int nextMtx = 4; + + if (info.m_hasBumpMap) { + additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[0], pos).xy;\n", nextTCG++); + } + if (info.m_hasEnvBumpMap) { + additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[3], float4(normalIn.xyz, 1.0)).xy;\n", nextTCG++); + } + if (info.m_hasEnvMap) { + additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], pos).xy;\n", nextTCG++, nextMtx++); + } + if (info.m_hasLightmap) { + additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], pos).xy;\n", nextTCG, nextMtx); + } + + return additionalTCGs; +} + +static std::string _BuildVS(const SFluidPlaneShaderInfo& info, bool tessellation) { + if (tessellation) + return TessVS; + + std::string additionalTCGs = _BuildAdditionalTCGs(info); + + char* finalVSs; + asprintf(&finalVSs, VS, additionalTCGs.c_str()); + std::string ret(finalVSs); + free(finalVSs); + return ret; +} +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildVS(in, tessellation); } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildVS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildFS(in); } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildFS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return TessCS; +} + +static std::string BuildES(const SFluidPlaneShaderInfo& info) { + int nextTex = 0; + if (info.m_hasPatternTex1) + nextTex++; + if (info.m_hasPatternTex2) + nextTex++; + if (info.m_hasColorTex) + nextTex++; + if (info.m_hasBumpMap) + nextTex++; + if (info.m_hasEnvMap) + nextTex++; + if (info.m_hasEnvBumpMap) + nextTex++; + if (info.m_hasLightmap) + nextTex++; + + std::string additionalTCGs = _BuildAdditionalTCGs(info); + + char* finalESs; + asprintf(&finalESs, TessES, nextTex, additionalTCGs.c_str()); + std::string ret(finalESs); + free(finalESs); + + return ret; +} +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return BuildES(in); +} + +static std::string _BuildVS(const SFluidPlaneDoorShaderInfo& info) { + char* finalVSs; + asprintf(&finalVSs, VS, ""); + std::string ret(finalVSs); + free(finalVSs); + return ret; +} + +static std::string _BuildFS(const SFluidPlaneDoorShaderInfo& info) { + int nextTex = 0; + std::string textures; + std::string combiner; + + if (info.m_hasPatternTex1) { + textures += hecl::Format("Texture2D patternTex1 : register(t%d);\n", nextTex++); + } + if (info.m_hasPatternTex2) { + textures += hecl::Format("Texture2D patternTex2 : register(t%d);\n", nextTex++); + } + if (info.m_hasColorTex) { + textures += hecl::Format("Texture2D colorTex : register(t%d);\n", nextTex++); + } + + // Tex0 * kColor0 * Tex1 + Tex2 + if (info.m_hasPatternTex1 && info.m_hasPatternTex2) { + combiner += + " colorOut = patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 *\n" + " patternTex2.Sample(samp, vtf.uvs[1]);\n"; + } else { + combiner += " colorOut = float4(0.0);\n"; + } + + if (info.m_hasColorTex) { + combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]);\n"; + } + + combiner += " colorOut.a = kColor0.a;\n"; + + char* finalFSs; + asprintf(&finalFSs, FSDoor, textures.c_str(), combiner.c_str()); + std::string ret(finalFSs); + free(finalFSs); + return ret; +} + +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildVS(in); +} + +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildFS(in); } diff --git a/Shaders/shader_CFluidPlaneShaderMetal.cpp b/Shaders/shader_CFluidPlaneShaderMetal.cpp index c69230b17..39e446d26 100644 --- a/Shaders/shader_CFluidPlaneShaderMetal.cpp +++ b/Shaders/shader_CFluidPlaneShaderMetal.cpp @@ -1,190 +1,190 @@ #include "shader_CFluidPlaneShader.hpp" static const char* VS = -"struct VertData\n" -"{\n" -" float4 posIn [[ attribute(0) ]];\n" -" float4 normalIn [[ attribute(1) ]];\n" -" float4 binormalIn [[ attribute(2) ]];\n" -" float4 tangentIn [[ attribute(3) ]];\n" -" float4 colorIn [[ attribute(4) ]];\n" -"};\n" -"\n" -"struct FluidPlaneUniform\n" -"{\n" -" float4x4 mv;\n" -" float4x4 mvNorm;\n" -" float4x4 proj;\n" -" float4x4 texMtxs[6];\n" -"};\n" -"\n" -"struct VertToFrag\n" -"{\n" -" float4 pos [[ position ]];\n" -" float4 mvPos;\n" -" float4 mvNorm;\n" -" float4 mvBinorm;\n" -" float4 mvTangent;\n" -" float4 color;\n" -" float2 uv0;\n" -" float2 uv1;\n" -" float2 uv2;\n" -" float2 uv3;\n" -" float2 uv4;\n" -" float2 uv5;\n" -" float2 uv6;\n" -"};\n" -"\n" -"vertex VertToFrag vmain(VertData v [[ stage_in ]],\n" -" constant FluidPlaneUniform& fu [[ buffer(2) ]])\n" -"{\n" -" VertToFrag vtf;\n" -" float4 pos = float4(v.posIn.xyz, 1.0);\n" -" float4 normalIn = v.normalIn;\n" -" vtf.mvPos = fu.mv * pos;\n" -" vtf.pos = fu.proj * vtf.mvPos;\n" -" vtf.mvNorm = fu.mvNorm * v.normalIn;\n" -" vtf.mvBinorm = fu.mvNorm * v.binormalIn;\n" -" vtf.mvTangent = fu.mvNorm * v.tangentIn;\n" -" vtf.color = v.colorIn;\n" -" vtf.uv0 = (fu.texMtxs[0] * pos).xy;\n" -" vtf.uv1 = (fu.texMtxs[1] * pos).xy;\n" -" vtf.uv2 = (fu.texMtxs[2] * pos).xy;\n" -"%s" // Additional TCGs here -" return vtf;\n" -"}\n"; + "struct VertData\n" + "{\n" + " float4 posIn [[ attribute(0) ]];\n" + " float4 normalIn [[ attribute(1) ]];\n" + " float4 binormalIn [[ attribute(2) ]];\n" + " float4 tangentIn [[ attribute(3) ]];\n" + " float4 colorIn [[ attribute(4) ]];\n" + "};\n" + "\n" + "struct FluidPlaneUniform\n" + "{\n" + " float4x4 mv;\n" + " float4x4 mvNorm;\n" + " float4x4 proj;\n" + " float4x4 texMtxs[6];\n" + "};\n" + "\n" + "struct VertToFrag\n" + "{\n" + " float4 pos [[ position ]];\n" + " float4 mvPos;\n" + " float4 mvNorm;\n" + " float4 mvBinorm;\n" + " float4 mvTangent;\n" + " float4 color;\n" + " float2 uv0;\n" + " float2 uv1;\n" + " float2 uv2;\n" + " float2 uv3;\n" + " float2 uv4;\n" + " float2 uv5;\n" + " float2 uv6;\n" + "};\n" + "\n" + "vertex VertToFrag vmain(VertData v [[ stage_in ]],\n" + " constant FluidPlaneUniform& fu [[ buffer(2) ]])\n" + "{\n" + " VertToFrag vtf;\n" + " float4 pos = float4(v.posIn.xyz, 1.0);\n" + " float4 normalIn = v.normalIn;\n" + " vtf.mvPos = fu.mv * pos;\n" + " vtf.pos = fu.proj * vtf.mvPos;\n" + " vtf.mvNorm = fu.mvNorm * v.normalIn;\n" + " vtf.mvBinorm = fu.mvNorm * v.binormalIn;\n" + " vtf.mvTangent = fu.mvNorm * v.tangentIn;\n" + " vtf.color = v.colorIn;\n" + " vtf.uv0 = (fu.texMtxs[0] * pos).xy;\n" + " vtf.uv1 = (fu.texMtxs[1] * pos).xy;\n" + " vtf.uv2 = (fu.texMtxs[2] * pos).xy;\n" + "%s" // Additional TCGs here + " return vtf;\n" + "}\n"; static const char* TessCS = -"struct VertData\n" -"{\n" -" float4 minMaxPos [[ attribute(0) ]];\n" -" float4 outerLevelsIn [[ attribute(1) ]];\n" -" float2 innerLevelsIn [[ attribute(2) ]];\n" -"};\n" -"\n" -"struct KernelPatchInfo {\n" -" uint numPatches; // total number of patches to process.\n" -" // we need this because this value may\n" -" // not be a multiple of threadgroup size.\n" -" ushort numPatchesInThreadGroup; // number of patches processed by a\n" -" // thread-group\n" -" ushort numControlPointsPerPatch;\n" -"};\n" -"\n" -"kernel void\n" -"cmain(VertData v [[ stage_in ]],\n" -" constant KernelPatchInfo& patchInfo [[ buffer(2) ]],\n" -" device MTLQuadTessellationFactorsHalf* tessellationFactorBuffer [[ buffer(3) ]],\n" -" ushort lID [[ thread_position_in_threadgroup ]],\n" -" ushort groupID [[ threadgroup_position_in_grid ]])\n" -"{\n" -" uint patchGroupID = groupID * patchInfo.numPatchesInThreadGroup;\n" -"\n" -" // execute the per-patch hull function\n" -" if (lID < patchInfo.numPatchesInThreadGroup)\n" -" {\n" -" uint patchID = patchGroupID + lID;\n" -" device MTLQuadTessellationFactorsHalf& patchOut = tessellationFactorBuffer[patchID];\n" -" for (int i=0 ; i<4 ; ++i)\n" -" patchOut.edgeTessellationFactor[i] = v.outerLevelsIn[i];\n" -" for (int i=0 ; i<2 ; ++i)\n" -" patchOut.insideTessellationFactor[i] = v.innerLevelsIn[i];\n" -" }\n" -"}\n"; + "struct VertData\n" + "{\n" + " float4 minMaxPos [[ attribute(0) ]];\n" + " float4 outerLevelsIn [[ attribute(1) ]];\n" + " float2 innerLevelsIn [[ attribute(2) ]];\n" + "};\n" + "\n" + "struct KernelPatchInfo {\n" + " uint numPatches; // total number of patches to process.\n" + " // we need this because this value may\n" + " // not be a multiple of threadgroup size.\n" + " ushort numPatchesInThreadGroup; // number of patches processed by a\n" + " // thread-group\n" + " ushort numControlPointsPerPatch;\n" + "};\n" + "\n" + "kernel void\n" + "cmain(VertData v [[ stage_in ]],\n" + " constant KernelPatchInfo& patchInfo [[ buffer(2) ]],\n" + " device MTLQuadTessellationFactorsHalf* tessellationFactorBuffer [[ buffer(3) ]],\n" + " ushort lID [[ thread_position_in_threadgroup ]],\n" + " ushort groupID [[ threadgroup_position_in_grid ]])\n" + "{\n" + " uint patchGroupID = groupID * patchInfo.numPatchesInThreadGroup;\n" + "\n" + " // execute the per-patch hull function\n" + " if (lID < patchInfo.numPatchesInThreadGroup)\n" + " {\n" + " uint patchID = patchGroupID + lID;\n" + " device MTLQuadTessellationFactorsHalf& patchOut = tessellationFactorBuffer[patchID];\n" + " for (int i=0 ; i<4 ; ++i)\n" + " patchOut.edgeTessellationFactor[i] = v.outerLevelsIn[i];\n" + " for (int i=0 ; i<2 ; ++i)\n" + " patchOut.insideTessellationFactor[i] = v.innerLevelsIn[i];\n" + " }\n" + "}\n"; static const char* TessES = -"struct Ripple\n" -"{\n" -" float4 center; // time, distFalloff\n" -" float4 params; // amplitude, lookupPhase, lookupTime\n" -"};\n" -"\n" -"struct FluidPlaneUniform\n" -"{\n" -" float4x4 mv;\n" -" float4x4 mvNorm;\n" -" float4x4 proj;\n" -" float4x4 texMtxs[6];\n" -" Ripple ripples[20];\n" -" float4 colorMul;\n" -" float rippleNormResolution;\n" -"};\n" -"\n" -"struct VertToFrag\n" -"{\n" -" float4 pos [[ position ]];\n" -" float4 mvPos;\n" -" float4 mvNorm;\n" -" float4 mvBinorm;\n" -" float4 mvTangent;\n" -" float4 color;\n" -" float2 uv0;\n" -" float2 uv1;\n" -" float2 uv2;\n" -" float2 uv3;\n" -" float2 uv4;\n" -" float2 uv5;\n" -" float2 uv6;\n" -"};\n" -"\n" -"struct VertData\n" -"{\n" -" float4 minMaxPos [[ attribute(0) ]];\n" -" float4 outerLevelsIn [[ attribute(1) ]];\n" -" float2 innerLevelsIn [[ attribute(2) ]];\n" -"};\n" -"\n" -"#define PI_X2 6.283185307179586\n" -"\n" -"static void ApplyRipple(constant Ripple& ripple, float2 pos, thread float& height,\n" -" sampler samp, texture2d RippleMap)\n" -"{\n" -" float dist = length(ripple.center.xy - pos);\n" -" float rippleV = RippleMap.sample(samp, float2(dist * ripple.center.w, ripple.center.z), level(0.0)).r;\n" -" height += rippleV * ripple.params.x * sin((dist * ripple.params.y + ripple.params.z) * PI_X2);\n" -"}\n" -"\n" -"[[ patch(quad, 1) ]]\n" -"vertex VertToFrag emain(VertData v [[ stage_in ]], float2 TessCoord [[ position_in_patch ]],\n" -" constant FluidPlaneUniform& fu [[ buffer(2) ]],\n" -" sampler samp [[ sampler(2) ]],\n" -" texture2d RippleMap [[ texture(%d) ]])\n" -"{\n" -" float2 posIn = float2(mix(v.minMaxPos.x, v.minMaxPos.z, TessCoord.x),\n" -" mix(v.minMaxPos.y, v.minMaxPos.w, TessCoord.y));\n" -" float height = 0.0;\n" -" float upHeight = 0.0;\n" -" float downHeight = 0.0;\n" -" float rightHeight = 0.0;\n" -" float leftHeight = 0.0;\n" -" for (int i=0 ; i<20 ; ++i)\n" -" {\n" -" ApplyRipple(fu.ripples[i], posIn, height, samp, RippleMap);\n" -" ApplyRipple(fu.ripples[i], posIn + float2(0.0, fu.rippleNormResolution), upHeight, samp, RippleMap);\n" -" ApplyRipple(fu.ripples[i], posIn - float2(0.0, fu.rippleNormResolution), downHeight, samp, RippleMap);\n" -" ApplyRipple(fu.ripples[i], posIn + float2(fu.rippleNormResolution, 0.0), rightHeight, samp, RippleMap);\n" -" ApplyRipple(fu.ripples[i], posIn - float2(fu.rippleNormResolution, 0.0), leftHeight, samp, RippleMap);\n" -" }\n" -" float4 normalIn = float4(normalize(float3((leftHeight - rightHeight),\n" -" (downHeight - upHeight),\n" -" fu.rippleNormResolution)), 1.0);\n" -" float4 binormalIn = float4(normalIn.x, normalIn.z, -normalIn.y, 1.0);\n" -" float4 tangentIn = float4(normalIn.z, normalIn.y, -normalIn.x, 1.0);\n" -" float4 pos = float4(posIn, height, 1.0);\n" -" VertToFrag vtf;\n" -" vtf.mvPos = (fu.mv * pos);\n" -" vtf.pos = (fu.proj * vtf.mvPos);\n" -" vtf.mvNorm = (fu.mvNorm * normalIn);\n" -" vtf.mvBinorm = (fu.mvNorm * binormalIn);\n" -" vtf.mvTangent = (fu.mvNorm * tangentIn);\n" -" vtf.color = max(height, 0.0) * fu.colorMul;\n" -" vtf.color.a = 1.0;\n" -" vtf.uv0 = (fu.texMtxs[0] * pos).xy;\n" -" vtf.uv1 = (fu.texMtxs[1] * pos).xy;\n" -" vtf.uv2 = (fu.texMtxs[2] * pos).xy;\n" -"%s\n" // Additional TCGs here -" return vtf;\n" -"}\n"; + "struct Ripple\n" + "{\n" + " float4 center; // time, distFalloff\n" + " float4 params; // amplitude, lookupPhase, lookupTime\n" + "};\n" + "\n" + "struct FluidPlaneUniform\n" + "{\n" + " float4x4 mv;\n" + " float4x4 mvNorm;\n" + " float4x4 proj;\n" + " float4x4 texMtxs[6];\n" + " Ripple ripples[20];\n" + " float4 colorMul;\n" + " float rippleNormResolution;\n" + "};\n" + "\n" + "struct VertToFrag\n" + "{\n" + " float4 pos [[ position ]];\n" + " float4 mvPos;\n" + " float4 mvNorm;\n" + " float4 mvBinorm;\n" + " float4 mvTangent;\n" + " float4 color;\n" + " float2 uv0;\n" + " float2 uv1;\n" + " float2 uv2;\n" + " float2 uv3;\n" + " float2 uv4;\n" + " float2 uv5;\n" + " float2 uv6;\n" + "};\n" + "\n" + "struct VertData\n" + "{\n" + " float4 minMaxPos [[ attribute(0) ]];\n" + " float4 outerLevelsIn [[ attribute(1) ]];\n" + " float2 innerLevelsIn [[ attribute(2) ]];\n" + "};\n" + "\n" + "#define PI_X2 6.283185307179586\n" + "\n" + "static void ApplyRipple(constant Ripple& ripple, float2 pos, thread float& height,\n" + " sampler samp, texture2d RippleMap)\n" + "{\n" + " float dist = length(ripple.center.xy - pos);\n" + " float rippleV = RippleMap.sample(samp, float2(dist * ripple.center.w, ripple.center.z), level(0.0)).r;\n" + " height += rippleV * ripple.params.x * sin((dist * ripple.params.y + ripple.params.z) * PI_X2);\n" + "}\n" + "\n" + "[[ patch(quad, 1) ]]\n" + "vertex VertToFrag emain(VertData v [[ stage_in ]], float2 TessCoord [[ position_in_patch ]],\n" + " constant FluidPlaneUniform& fu [[ buffer(2) ]],\n" + " sampler samp [[ sampler(2) ]],\n" + " texture2d RippleMap [[ texture(%d) ]])\n" + "{\n" + " float2 posIn = float2(mix(v.minMaxPos.x, v.minMaxPos.z, TessCoord.x),\n" + " mix(v.minMaxPos.y, v.minMaxPos.w, TessCoord.y));\n" + " float height = 0.0;\n" + " float upHeight = 0.0;\n" + " float downHeight = 0.0;\n" + " float rightHeight = 0.0;\n" + " float leftHeight = 0.0;\n" + " for (int i=0 ; i<20 ; ++i)\n" + " {\n" + " ApplyRipple(fu.ripples[i], posIn, height, samp, RippleMap);\n" + " ApplyRipple(fu.ripples[i], posIn + float2(0.0, fu.rippleNormResolution), upHeight, samp, RippleMap);\n" + " ApplyRipple(fu.ripples[i], posIn - float2(0.0, fu.rippleNormResolution), downHeight, samp, RippleMap);\n" + " ApplyRipple(fu.ripples[i], posIn + float2(fu.rippleNormResolution, 0.0), rightHeight, samp, RippleMap);\n" + " ApplyRipple(fu.ripples[i], posIn - float2(fu.rippleNormResolution, 0.0), leftHeight, samp, RippleMap);\n" + " }\n" + " float4 normalIn = float4(normalize(float3((leftHeight - rightHeight),\n" + " (downHeight - upHeight),\n" + " fu.rippleNormResolution)), 1.0);\n" + " float4 binormalIn = float4(normalIn.x, normalIn.z, -normalIn.y, 1.0);\n" + " float4 tangentIn = float4(normalIn.z, normalIn.y, -normalIn.x, 1.0);\n" + " float4 pos = float4(posIn, height, 1.0);\n" + " VertToFrag vtf;\n" + " vtf.mvPos = (fu.mv * pos);\n" + " vtf.pos = (fu.proj * vtf.mvPos);\n" + " vtf.mvNorm = (fu.mvNorm * normalIn);\n" + " vtf.mvBinorm = (fu.mvNorm * binormalIn);\n" + " vtf.mvTangent = (fu.mvNorm * tangentIn);\n" + " vtf.color = max(height, 0.0) * fu.colorMul;\n" + " vtf.color.a = 1.0;\n" + " vtf.uv0 = (fu.texMtxs[0] * pos).xy;\n" + " vtf.uv1 = (fu.texMtxs[1] * pos).xy;\n" + " vtf.uv2 = (fu.texMtxs[2] * pos).xy;\n" + "%s\n" // Additional TCGs here + " return vtf;\n" + "}\n"; static const char* FS = "struct Light\n" @@ -351,459 +351,415 @@ static const char* FSDoor = " return colorOut;\n" "}\n"; -static std::string _BuildFS(const SFluidPlaneShaderInfo& info) -{ - std::string textures; - std::string combiner; - int nextTex = 0; - int nextTCG = 3; - int nextMtx = 4; - int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv; +static std::string _BuildFS(const SFluidPlaneShaderInfo& info) { + std::string textures; + std::string combiner; + int nextTex = 0; + int nextTCG = 3; + int nextMtx = 4; + int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv; - if (info.m_hasPatternTex1) - textures += hecl::Format(",\ntexture2d patternTex1 [[ texture(%d) ]]", nextTex++); - if (info.m_hasPatternTex2) - textures += hecl::Format(",\ntexture2d patternTex2 [[ texture(%d) ]]", nextTex++); - if (info.m_hasColorTex) - textures += hecl::Format(",\ntexture2d colorTex [[ texture(%d) ]]", nextTex++); - if (info.m_hasBumpMap) - textures += hecl::Format(",\ntexture2d bumpMap [[ texture(%d) ]]", nextTex++); - if (info.m_hasEnvMap) - textures += hecl::Format(",\ntexture2d envMap [[ texture(%d) ]]", nextTex++); - if (info.m_hasEnvBumpMap) - textures += hecl::Format(",\ntexture2d envBumpMap [[ texture(%d) ]]", nextTex++); - if (info.m_hasLightmap) - textures += hecl::Format(",\ntexture2d lightMap [[ texture(%d) ]]", nextTex++); + if (info.m_hasPatternTex1) + textures += hecl::Format(",\ntexture2d patternTex1 [[ texture(%d) ]]", nextTex++); + if (info.m_hasPatternTex2) + textures += hecl::Format(",\ntexture2d patternTex2 [[ texture(%d) ]]", nextTex++); + if (info.m_hasColorTex) + textures += hecl::Format(",\ntexture2d colorTex [[ texture(%d) ]]", nextTex++); + if (info.m_hasBumpMap) + textures += hecl::Format(",\ntexture2d bumpMap [[ texture(%d) ]]", nextTex++); + if (info.m_hasEnvMap) + textures += hecl::Format(",\ntexture2d envMap [[ texture(%d) ]]", nextTex++); + if (info.m_hasEnvBumpMap) + textures += hecl::Format(",\ntexture2d envBumpMap [[ texture(%d) ]]", nextTex++); + if (info.m_hasLightmap) + textures += hecl::Format(",\ntexture2d lightMap [[ texture(%d) ]]", nextTex++); - if (info.m_hasBumpMap) - { - bumpMapUv = nextTCG; - } - if (info.m_hasEnvBumpMap) - { - envBumpMapUv = nextTCG; - } - if (info.m_hasEnvMap) - { - envMapUv = nextTCG; - } - if (info.m_hasLightmap) - { - lightmapUv = nextTCG; + if (info.m_hasBumpMap) { + bumpMapUv = nextTCG; + } + if (info.m_hasEnvBumpMap) { + envBumpMapUv = nextTCG; + } + if (info.m_hasEnvMap) { + envMapUv = nextTCG; + } + if (info.m_hasLightmap) { + lightmapUv = nextTCG; + } + + switch (info.m_type) { + case EFluidType::NormalWater: + case EFluidType::PhazonFluid: + case EFluidType::Four: + if (info.m_hasLightmap) { + combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uv%d);\n", lightmapUv); + // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 + // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS + // Output reg 2 + // KColor 2 + if (info.m_doubleLightmapBlend) { + // 1: Tex4TCG2, Tex4, GX_COLOR1A1 + // C2, TEX, KONST, RAS + // Output reg 2 + // KColor 3 + // Tex * K2 + Lighting + combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n"; + } else { + // mix(Tex * K2, Tex, K3) + Lighting + combiner += " lighting += lightMapTexel * lu.kColor2;\n"; + } } - switch (info.m_type) - { - case EFluidType::NormalWater: - case EFluidType::PhazonFluid: - case EFluidType::Four: - if (info.m_hasLightmap) - { - combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uv%d);\n", lightmapUv); - // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 - // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS - // Output reg 2 - // KColor 2 - if (info.m_doubleLightmapBlend) - { - // 1: Tex4TCG2, Tex4, GX_COLOR1A1 - // C2, TEX, KONST, RAS - // Output reg 2 - // KColor 3 - // Tex * K2 + Lighting - combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n"; - } - else - { - // mix(Tex * K2, Tex, K3) + Lighting - combiner += " lighting += lightMapTexel * lu.kColor2;\n"; - } - } + // Next: Tex0TCG, Tex0, GX_COLOR1A1 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 - // Next: Tex0TCG, Tex0, GX_COLOR1A1 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 + // Next: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev - // Next: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev + // Next: Tex2TCG, Tex2, GX_COLOR1A1 + // ZERO, TEX, hasTex4 ? C2 : RAS, PREV + // Output reg prev - // Next: Tex2TCG, Tex2, GX_COLOR1A1 - // ZERO, TEX, hasTex4 ? C2 : RAS, PREV - // Output reg prev - - // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + lighting) *\n" - " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; - else - combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - - if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) - { - // Make previous stage indirect, mtx0 - combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n" - " float2(lu.fog.indScale, -lu.fog.indScale);\n", envBumpMapUv); - combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uv2) * lighting;\n"; - } - else if (info.m_hasEnvMap) - { - // Next: envTCG, envTex, NULL - // PREV, TEX, KONST, ZERO - // Output reg prev - // KColor 1 - - // Make previous stage indirect, mtx0 - if (info.m_hasColorTex) - combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n"; - combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n" - " float2(lu.fog.indScale, -lu.fog.indScale);\n", envBumpMapUv); - combiner += hecl::Format(" colorOut = mix(colorOut, envMap.sample(samp, indUvs + vtf.uv%d), lu.kColor1);\n", - envMapUv); - } - else if (info.m_hasColorTex) - { - combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n"; - } - - break; - - case EFluidType::PoisonWater: - if (info.m_hasLightmap) - { - combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uv%d);\n", lightmapUv); - // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 - // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS - // Output reg 2 - // KColor 2 - if (info.m_doubleLightmapBlend) - { - // 1: Tex4TCG2, Tex4, GX_COLOR1A1 - // C2, TEX, KONST, RAS - // Output reg 2 - // KColor 3 - // Tex * K2 + Lighting - combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n"; - } - else - { - // mix(Tex * K2, Tex, K3) + Lighting - combiner += " lighting += lightMapTexel * lu.kColor2;\n"; - } - } - - // Next: Tex0TCG, Tex0, GX_COLOR1A1 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // Next: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // Next: Tex2TCG, Tex2, GX_COLOR1A1 - // ZERO, TEX, hasTex4 ? C2 : RAS, PREV - // Output reg prev - - // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + lighting) *\n" - " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; - else - combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - if (info.m_hasColorTex) - { - if (info.m_hasEnvBumpMap) - { - // Make previous stage indirect, mtx0 - combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n" - " float2(lu.fog.indScale, -lu.fog.indScale);\n", envBumpMapUv); - combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uv2) * lighting;\n"; - } - else - { - combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n"; - } - } - - break; - - case EFluidType::Lava: - // 0: Tex0TCG, Tex0, GX_COLOR0A0 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // 1: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // 2: Tex2TCG, Tex2, NULL - // ZERO, TEX, ONE, PREV - // Output reg prev - - // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + vtf.color) *\n" - " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; - else - combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - if (info.m_hasColorTex) - combiner += " colorOut += colorTex.sample(samp, vtf.uv2);\n"; - - if (info.m_hasBumpMap) - { - // 3: bumpMapTCG, bumpMap, NULL - // ZERO, TEX, ONE, HALF - // Output reg 0, no clamp, no bias - - // 4: bumpMapTCG2, bumpMap, NULL - // ZERO, TEX, ONE, C0 - // Output reg 0, subtract, clamp, no bias - - combiner += " float3 lightVec = lu.lights[3].pos.xyz - vtf.mvPos.xyz;\n" - " float lx = dot(vtf.mvTangent.xyz, lightVec);\n" - " float ly = dot(vtf.mvBinorm.xyz, lightVec);\n"; - combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uv%d) + float4(0.5);\n" - " float4 emboss2 = bumpMap.sample(samp, vtf.uv%d + float2(lx, ly));\n", - bumpMapUv, bumpMapUv); - - // 5: NULL, NULL, NULL - // ZERO, PREV, C0, ZERO - // Output reg prev, scale 2, clamp - - // colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0 - combiner += "colorOut *= clamp((emboss1 + float4(0.5) - emboss2) * float4(2.0), float4(0.0), float4(1.0));\n"; - } - - break; - - case EFluidType::ThickLava: - // 0: Tex0TCG, Tex0, GX_COLOR0A0 - // ZERO, TEX, KONST, RAS - // Output reg prev - // KColor 0 - - // 1: Tex1TCG, Tex1, GX_COLOR0A0 - // ZERO, TEX, PREV, RAS - // Output reg prev - - // 2: Tex2TCG, Tex2, NULL - // ZERO, TEX, ONE, PREV - // Output reg prev - - // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 - if (info.m_hasPatternTex2) - { - if (info.m_hasPatternTex1) - combiner += " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + vtf.color) *\n" - " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; - else - combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; - } - else - { - combiner += " colorOut = vtf.color;\n"; - } - - if (info.m_hasColorTex) - combiner += " colorOut += colorTex.sample(samp, vtf.uv2);\n"; - - if (info.m_hasBumpMap) - { - // 3: bumpMapTCG, bumpMap, NULL - // ZERO, TEX, PREV, ZERO - // Output reg prev, scale 2 - combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uv%d) + float4(0.5);\n", bumpMapUv); - combiner += "colorOut *= emboss1 * float4(2.0);\n"; - } - - break; + // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + lighting) *\n" + " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; + else + combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; } - combiner += " colorOut.a = lu.kColor0.a;\n"; + if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap) { + // Make previous stage indirect, mtx0 + combiner += hecl::Format( + " float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n" + " float2(lu.fog.indScale, -lu.fog.indScale);\n", + envBumpMapUv); + combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uv2) * lighting;\n"; + } else if (info.m_hasEnvMap) { + // Next: envTCG, envTex, NULL + // PREV, TEX, KONST, ZERO + // Output reg prev + // KColor 1 - char *finalFS; - asprintf(&finalFS, FS, int(info.m_additive), textures.c_str(), combiner.c_str()); - std::string ret(finalFS); - free(finalFS); - return ret; -} - -static std::string _BuildAdditionalTCGs(const SFluidPlaneShaderInfo& info) -{ - std::string additionalTCGs; - int nextTCG = 3; - int nextMtx = 4; - - if (info.m_hasBumpMap) - { - additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[0] * pos).xy;\n", nextTCG++); - } - if (info.m_hasEnvBumpMap) - { - additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[3] * float4(normalIn.xyz, 1.0)).xy;\n", nextTCG++); - } - if (info.m_hasEnvMap) - { - additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[%d] * pos).xy;\n", nextTCG++, nextMtx++); - } - if (info.m_hasLightmap) - { - additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[%d] * pos).xy;\n", nextTCG++, nextMtx++); + // Make previous stage indirect, mtx0 + if (info.m_hasColorTex) + combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n"; + combiner += hecl::Format( + " float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n" + " float2(lu.fog.indScale, -lu.fog.indScale);\n", + envBumpMapUv); + combiner += + hecl::Format(" colorOut = mix(colorOut, envMap.sample(samp, indUvs + vtf.uv%d), lu.kColor1);\n", envMapUv); + } else if (info.m_hasColorTex) { + combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n"; } - return additionalTCGs; -} + break; -static std::string _BuildVS(const SFluidPlaneShaderInfo& info, bool tessellation) -{ - std::string additionalTCGs = _BuildAdditionalTCGs(info); - - char *finalVSs; - asprintf(&finalVSs, VS, additionalTCGs.c_str()); - std::string ret(finalVSs); - free(finalVSs); - return ret; -} -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildVS(in, tessellation); -} - -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return _BuildFS(in); -} - -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return TessCS; -} - -static std::string BuildES(const SFluidPlaneShaderInfo& info) -{ - int nextTex = 0; - if (info.m_hasPatternTex1) - nextTex++; - if (info.m_hasPatternTex2) - nextTex++; - if (info.m_hasColorTex) - nextTex++; - if (info.m_hasBumpMap) - nextTex++; - if (info.m_hasEnvMap) - nextTex++; - if (info.m_hasEnvBumpMap) - nextTex++; - if (info.m_hasLightmap) - nextTex++; - - std::string additionalTCGs = _BuildAdditionalTCGs(info); - - char *finalESs; - asprintf(&finalESs, TessES, nextTex, additionalTCGs.c_str()); - std::string ret(finalESs); - free(finalESs); - - return ret; -} - -template <> -std::string StageObject_CFluidPlaneShader::BuildShader - (const SFluidPlaneShaderInfo& in, bool tessellation) -{ - return BuildES(in); -} - -static std::string _BuildVS(const SFluidPlaneDoorShaderInfo& info) -{ - char *finalVSs; - asprintf(&finalVSs, VS, ""); - std::string ret(finalVSs); - free(finalVSs); - return ret; -} - -static std::string _BuildFS(const SFluidPlaneDoorShaderInfo& info) -{ - int nextTex = 0; - std::string textures; - std::string combiner; - - if (info.m_hasPatternTex1) - textures += hecl::Format(",\ntexture2d patternTex1 [[ texture(%d) ]]", nextTex++); - if (info.m_hasPatternTex2) - textures += hecl::Format(",\ntexture2d patternTex2 [[ texture(%d) ]]", nextTex++); - if (info.m_hasColorTex) - textures += hecl::Format(",\ntexture2d colorTex [[ texture(%d) ]]", nextTex++); - - // Tex0 * kColor0 * Tex1 + Tex2 - if (info.m_hasPatternTex1 && info.m_hasPatternTex2) - { - combiner += " colorOut = patternTex1.sample(samp, vtf.uv0) * lu.kColor0 *\n" - " patternTex2.sample(samp, vtf.uv1);\n"; + case EFluidType::PoisonWater: + if (info.m_hasLightmap) { + combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uv%d);\n", lightmapUv); + // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1 + // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS + // Output reg 2 + // KColor 2 + if (info.m_doubleLightmapBlend) { + // 1: Tex4TCG2, Tex4, GX_COLOR1A1 + // C2, TEX, KONST, RAS + // Output reg 2 + // KColor 3 + // Tex * K2 + Lighting + combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n"; + } else { + // mix(Tex * K2, Tex, K3) + Lighting + combiner += " lighting += lightMapTexel * lu.kColor2;\n"; + } } - else - { - combiner += " colorOut = float4(0.0);\n"; + + // Next: Tex0TCG, Tex0, GX_COLOR1A1 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 + + // Next: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev + + // Next: Tex2TCG, Tex2, GX_COLOR1A1 + // ZERO, TEX, hasTex4 ? C2 : RAS, PREV + // Output reg prev + + // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + lighting) *\n" + " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; + else + combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; + } + + if (info.m_hasColorTex) { + if (info.m_hasEnvBumpMap) { + // Make previous stage indirect, mtx0 + combiner += hecl::Format( + " float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n" + " float2(lu.fog.indScale, -lu.fog.indScale);\n", + envBumpMapUv); + combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uv2) * lighting;\n"; + } else { + combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n"; + } + } + + break; + + case EFluidType::Lava: + // 0: Tex0TCG, Tex0, GX_COLOR0A0 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 + + // 1: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev + + // 2: Tex2TCG, Tex2, NULL + // ZERO, TEX, ONE, PREV + // Output reg prev + + // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + vtf.color) *\n" + " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; + else + combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; } if (info.m_hasColorTex) - { - combiner += " colorOut += colorTex.sample(samp, vtf.uv2);\n"; + combiner += " colorOut += colorTex.sample(samp, vtf.uv2);\n"; + + if (info.m_hasBumpMap) { + // 3: bumpMapTCG, bumpMap, NULL + // ZERO, TEX, ONE, HALF + // Output reg 0, no clamp, no bias + + // 4: bumpMapTCG2, bumpMap, NULL + // ZERO, TEX, ONE, C0 + // Output reg 0, subtract, clamp, no bias + + combiner += + " float3 lightVec = lu.lights[3].pos.xyz - vtf.mvPos.xyz;\n" + " float lx = dot(vtf.mvTangent.xyz, lightVec);\n" + " float ly = dot(vtf.mvBinorm.xyz, lightVec);\n"; + combiner += hecl::Format( + " float4 emboss1 = bumpMap.sample(samp, vtf.uv%d) + float4(0.5);\n" + " float4 emboss2 = bumpMap.sample(samp, vtf.uv%d + float2(lx, ly));\n", + bumpMapUv, bumpMapUv); + + // 5: NULL, NULL, NULL + // ZERO, PREV, C0, ZERO + // Output reg prev, scale 2, clamp + + // colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0 + combiner += "colorOut *= clamp((emboss1 + float4(0.5) - emboss2) * float4(2.0), float4(0.0), float4(1.0));\n"; } - combiner += " colorOut.a = lu.kColor0.a;\n"; + break; - char *finalFSs; - asprintf(&finalFSs, FSDoor, textures.c_str(), combiner.c_str()); - std::string ret(finalFSs); - free(finalFSs); - return ret; + case EFluidType::ThickLava: + // 0: Tex0TCG, Tex0, GX_COLOR0A0 + // ZERO, TEX, KONST, RAS + // Output reg prev + // KColor 0 + + // 1: Tex1TCG, Tex1, GX_COLOR0A0 + // ZERO, TEX, PREV, RAS + // Output reg prev + + // 2: Tex2TCG, Tex2, NULL + // ZERO, TEX, ONE, PREV + // Output reg prev + + // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2 + if (info.m_hasPatternTex2) { + if (info.m_hasPatternTex1) + combiner += + " colorOut = (patternTex1.sample(samp, vtf.uv0) * lu.kColor0 + vtf.color) *\n" + " patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; + else + combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uv1) + vtf.color;\n"; + } else { + combiner += " colorOut = vtf.color;\n"; + } + + if (info.m_hasColorTex) + combiner += " colorOut += colorTex.sample(samp, vtf.uv2);\n"; + + if (info.m_hasBumpMap) { + // 3: bumpMapTCG, bumpMap, NULL + // ZERO, TEX, PREV, ZERO + // Output reg prev, scale 2 + combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uv%d) + float4(0.5);\n", bumpMapUv); + combiner += "colorOut *= emboss1 * float4(2.0);\n"; + } + + break; + } + + combiner += " colorOut.a = lu.kColor0.a;\n"; + + char* finalFS; + asprintf(&finalFS, FS, int(info.m_additive), textures.c_str(), combiner.c_str()); + std::string ret(finalFS); + free(finalFS); + return ret; +} + +static std::string _BuildAdditionalTCGs(const SFluidPlaneShaderInfo& info) { + std::string additionalTCGs; + int nextTCG = 3; + int nextMtx = 4; + + if (info.m_hasBumpMap) { + additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[0] * pos).xy;\n", nextTCG++); + } + if (info.m_hasEnvBumpMap) { + additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[3] * float4(normalIn.xyz, 1.0)).xy;\n", nextTCG++); + } + if (info.m_hasEnvMap) { + additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[%d] * pos).xy;\n", nextTCG++, nextMtx++); + } + if (info.m_hasLightmap) { + additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[%d] * pos).xy;\n", nextTCG++, nextMtx++); + } + + return additionalTCGs; +} + +static std::string _BuildVS(const SFluidPlaneShaderInfo& info, bool tessellation) { + std::string additionalTCGs = _BuildAdditionalTCGs(info); + + char* finalVSs; + asprintf(&finalVSs, VS, additionalTCGs.c_str()); + std::string ret(finalVSs); + free(finalVSs); + return ret; +} +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildVS(in, tessellation); } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildVS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return _BuildFS(in); } template <> -std::string StageObject_CFluidPlaneDoorShader::BuildShader - (const SFluidPlaneDoorShaderInfo& in) -{ - return _BuildFS(in); +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return TessCS; +} + +static std::string BuildES(const SFluidPlaneShaderInfo& info) { + int nextTex = 0; + if (info.m_hasPatternTex1) + nextTex++; + if (info.m_hasPatternTex2) + nextTex++; + if (info.m_hasColorTex) + nextTex++; + if (info.m_hasBumpMap) + nextTex++; + if (info.m_hasEnvMap) + nextTex++; + if (info.m_hasEnvBumpMap) + nextTex++; + if (info.m_hasLightmap) + nextTex++; + + std::string additionalTCGs = _BuildAdditionalTCGs(info); + + char* finalESs; + asprintf(&finalESs, TessES, nextTex, additionalTCGs.c_str()); + std::string ret(finalESs); + free(finalESs); + + return ret; +} + +template <> +std::string StageObject_CFluidPlaneShader::BuildShader( + const SFluidPlaneShaderInfo& in, bool tessellation) { + return BuildES(in); +} + +static std::string _BuildVS(const SFluidPlaneDoorShaderInfo& info) { + char* finalVSs; + asprintf(&finalVSs, VS, ""); + std::string ret(finalVSs); + free(finalVSs); + return ret; +} + +static std::string _BuildFS(const SFluidPlaneDoorShaderInfo& info) { + int nextTex = 0; + std::string textures; + std::string combiner; + + if (info.m_hasPatternTex1) + textures += hecl::Format(",\ntexture2d patternTex1 [[ texture(%d) ]]", nextTex++); + if (info.m_hasPatternTex2) + textures += hecl::Format(",\ntexture2d patternTex2 [[ texture(%d) ]]", nextTex++); + if (info.m_hasColorTex) + textures += hecl::Format(",\ntexture2d colorTex [[ texture(%d) ]]", nextTex++); + + // Tex0 * kColor0 * Tex1 + Tex2 + if (info.m_hasPatternTex1 && info.m_hasPatternTex2) { + combiner += + " colorOut = patternTex1.sample(samp, vtf.uv0) * lu.kColor0 *\n" + " patternTex2.sample(samp, vtf.uv1);\n"; + } else { + combiner += " colorOut = float4(0.0);\n"; + } + + if (info.m_hasColorTex) { + combiner += " colorOut += colorTex.sample(samp, vtf.uv2);\n"; + } + + combiner += " colorOut.a = lu.kColor0.a;\n"; + + char* finalFSs; + asprintf(&finalFSs, FSDoor, textures.c_str(), combiner.c_str()); + std::string ret(finalFSs); + free(finalFSs); + return ret; +} + +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildVS(in); +} + +template <> +std::string StageObject_CFluidPlaneDoorShader::BuildShader( + const SFluidPlaneDoorShaderInfo& in) { + return _BuildFS(in); } diff --git a/amuse b/amuse index b4c073c37..a7a408cc6 160000 --- a/amuse +++ b/amuse @@ -1 +1 @@ -Subproject commit b4c073c373b4a67dfe9cee4f52469565b8f8f4f6 +Subproject commit a7a408cc66aedc85802469ef89a72b8b7a70eb54 diff --git a/assetnameparser/main.cpp b/assetnameparser/main.cpp index cd04dd644..4f6ac5898 100644 --- a/assetnameparser/main.cpp +++ b/assetnameparser/main.cpp @@ -28,7 +28,6 @@ #endif #endif - static logvisor::Module Log("AssetNameParser"); // TODO: Clean this up #undef bswap16 @@ -37,57 +36,48 @@ static logvisor::Module Log("AssetNameParser"); /* Type-sensitive byte swappers */ template -static inline T bswap16(T val) -{ +static inline T bswap16(T val) { #if __GNUC__ - return __builtin_bswap16(val); + return __builtin_bswap16(val); #elif _WIN32 - return _byteswap_ushort(val); + return _byteswap_ushort(val); #else - return (val = (val << 8) | ((val >> 8) & 0xFF)); + return (val = (val << 8) | ((val >> 8) & 0xFF)); #endif } template -static inline T bswap32(T val) -{ +static inline T bswap32(T val) { #if __GNUC__ - return __builtin_bswap32(val); + return __builtin_bswap32(val); #elif _WIN32 - return _byteswap_ulong(val); + return _byteswap_ulong(val); #else - val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16; - val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8; - return val; + val = (val & 0x0000FFFF) << 16 | (val & 0xFFFF0000) >> 16; + val = (val & 0x00FF00FF) << 8 | (val & 0xFF00FF00) >> 8; + return val; #endif } template -static inline T bswap64(T val) -{ +static inline T bswap64(T val) { #if __GNUC__ - return __builtin_bswap64(val); + return __builtin_bswap64(val); #elif _WIN32 - return _byteswap_uint64(val); + return _byteswap_uint64(val); #else - return ((val & 0xFF00000000000000ULL) >> 56) | - ((val & 0x00FF000000000000ULL) >> 40) | - ((val & 0x0000FF0000000000ULL) >> 24) | - ((val & 0x000000FF00000000ULL) >> 8) | - ((val & 0x00000000FF000000ULL) << 8) | - ((val & 0x0000000000FF0000ULL) << 24) | - ((val & 0x000000000000FF00ULL) << 40) | - ((val & 0x00000000000000FFULL) << 56); + return ((val & 0xFF00000000000000ULL) >> 56) | ((val & 0x00FF000000000000ULL) >> 40) | + ((val & 0x0000FF0000000000ULL) >> 24) | ((val & 0x000000FF00000000ULL) >> 8) | + ((val & 0x00000000FF000000ULL) << 8) | ((val & 0x0000000000FF0000ULL) << 24) | + ((val & 0x000000000000FF00ULL) << 40) | ((val & 0x00000000000000FFULL) << 56); #endif } - #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -static inline uint32_t SBig(uint32_t val) {return bswap32(val);} -static inline uint64_t SBig(uint64_t val) {return bswap64(val);} +static inline uint32_t SBig(uint32_t val) { return bswap32(val); } +static inline uint64_t SBig(uint64_t val) { return bswap64(val); } #ifndef SBIG -#define SBIG(q) ( ( (q) & 0x000000FF ) << 24 | ( (q) & 0x0000FF00 ) << 8 \ - | ( (q) & 0x00FF0000 ) >> 8 | ( (q) & 0xFF000000 ) >> 24 ) +#define SBIG(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24) #endif #ifndef SLITTLE @@ -95,61 +85,50 @@ static inline uint64_t SBig(uint64_t val) {return bswap64(val);} #endif #else #ifndef SLITTLE -#define SLITTLE(q) ( ( (q) & 0x000000FF ) << 24 | ( (q) & 0x0000FF00 ) << 8 \ - | ( (q) & 0x00FF0000 ) >> 8 | ( (q) & 0xFF000000 ) >> 24 ) +#define SLITTLE(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24) #endif -static inline uint32_t SBig(uint32_t val) {return val;} -static inline uint64_t SBig(uint64_t val) {return val;} +static inline uint32_t SBig(uint32_t val) { return val; } +static inline uint64_t SBig(uint64_t val) { return val; } #ifndef SBIG #define SBIG(q) (q) #endif #endif -class FourCC -{ +class FourCC { protected: - union - { - char fcc[4]; - uint32_t num; - }; + union { + char fcc[4]; + uint32_t num; + }; + public: - FourCC() /* Sentinel FourCC */ - : num(0) {} - FourCC(const FourCC& other) - {num = other.num;} - FourCC(const char* name) - : num(*(uint32_t*)name) {} - FourCC(uint32_t n) - : num(n) {} - bool operator==(const FourCC& other) const {return num == other.num;} - bool operator!=(const FourCC& other) const {return num != other.num;} - bool operator==(const char* other) const {return num == *(uint32_t*)other;} - bool operator!=(const char* other) const {return num != *(uint32_t*)other;} - bool operator==(int32_t other) const { return num == other;} - bool operator!=(int32_t other) const { return num != other;} - bool operator==(uint32_t other) const {return num == other;} - bool operator!=(uint32_t other) const {return num != other;} - std::string toString() const {return std::string(fcc, 4);} - uint32_t toUint32() const {return num;} - operator uint32_t() const {return num;} + FourCC() /* Sentinel FourCC */ + : num(0) {} + FourCC(const FourCC& other) { num = other.num; } + FourCC(const char* name) : num(*(uint32_t*)name) {} + FourCC(uint32_t n) : num(n) {} + bool operator==(const FourCC& other) const { return num == other.num; } + bool operator!=(const FourCC& other) const { return num != other.num; } + bool operator==(const char* other) const { return num == *(uint32_t*)other; } + bool operator!=(const char* other) const { return num != *(uint32_t*)other; } + bool operator==(int32_t other) const { return num == other; } + bool operator!=(int32_t other) const { return num != other; } + bool operator==(uint32_t other) const { return num == other; } + bool operator!=(uint32_t other) const { return num != other; } + std::string toString() const { return std::string(fcc, 4); } + uint32_t toUint32() const { return num; } + operator uint32_t() const { return num; } }; -struct SAsset -{ - FourCC type; - uint64_t id; - std::string name; - std::string dir; +struct SAsset { + FourCC type; + uint64_t id; + std::string name; + std::string dir; }; -enum class FileLockType -{ - None = 0, - Read, - Write -}; +enum class FileLockType { None = 0, Read, Write }; #if IS_UCS2 typedef wchar_t SystemChar; @@ -167,133 +146,121 @@ typedef std::string SystemString; typedef struct stat Sstat; #endif -static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType lock = FileLockType::None) -{ +static inline FILE* Fopen(const SystemChar* path, const SystemChar* mode, FileLockType lock = FileLockType::None) { #if IS_UCS2 - FILE* fp = _wfopen(path, mode); - if (!fp) - return nullptr; + FILE* fp = _wfopen(path, mode); + if (!fp) + return nullptr; #else - FILE* fp = fopen(path, mode); - if (!fp) - return nullptr; + FILE* fp = fopen(path, mode); + if (!fp) + return nullptr; #endif - if (lock != FileLockType::None) - { + if (lock != FileLockType::None) { #if _WIN32 - OVERLAPPED ov = {}; - LockFileEx((HANDLE)(uintptr_t)_fileno(fp), (lock == FileLockType::Write) ? LOCKFILE_EXCLUSIVE_LOCK : 0, 0, 0, 1, - &ov); + OVERLAPPED ov = {}; + LockFileEx((HANDLE)(uintptr_t)_fileno(fp), (lock == FileLockType::Write) ? LOCKFILE_EXCLUSIVE_LOCK : 0, 0, 0, 1, + &ov); #else - if (flock(fileno(fp), ((lock == FileLockType::Write) ? LOCK_EX : LOCK_SH) | LOCK_NB)) - fprintf(stderr, "flock %s: %s", path, strerror(errno)); + if (flock(fileno(fp), ((lock == FileLockType::Write) ? LOCK_EX : LOCK_SH) | LOCK_NB)) + fprintf(stderr, "flock %s: %s", path, strerror(errno)); #endif - } + } - return fp; + return fp; } - #if _WIN32 int wmain(int argc, const wchar_t* argv[]) #else int main(int argc, const char* argv[]) #endif { - logvisor::RegisterStandardExceptions(); - logvisor::RegisterConsoleLogger(); - if (argc < 3) - { - Log.report(logvisor::Error, _SYS_STR("Usage: %s "), argv[0]); - return 1; - } - - SystemString inPath = argv[1]; - SystemString outPath = argv[2]; - - tinyxml2::XMLDocument doc; - std::vector assets; - FILE* docF = Fopen(inPath.c_str(), _SYS_STR("rb")); - if (!doc.LoadFile(docF)) - { - const tinyxml2::XMLElement* elm = doc.RootElement(); - if (strcmp(elm->Name(), "AssetNameMap")) - { - Log.report(logvisor::Fatal, _SYS_STR("Invalid database supplied")); - return 1; - } - - elm = elm->FirstChildElement("AssetNameMap"); - if (elm == nullptr) - { - Log.report(logvisor::Fatal, _SYS_STR("Malformed AssetName database")); - return 1; - } - - elm = elm->FirstChildElement("Asset"); - - while (elm) - { - const tinyxml2::XMLElement* keyElm = elm->FirstChildElement("Key"); - const tinyxml2::XMLElement* valueElm = elm->FirstChildElement("Value"); - - if (!keyElm || !valueElm) - { - Log.report(logvisor::Fatal, _SYS_STR("Malformed Asset entry, [Key,Value] required")); - return 0; - } - - const tinyxml2::XMLElement* nameElm = valueElm->FirstChildElement("Name"); - const tinyxml2::XMLElement* dirElm = valueElm->FirstChildElement("Directory"); - const tinyxml2::XMLElement* typeElm = valueElm->FirstChildElement("Type"); - - if (!nameElm || !dirElm || ! typeElm) - { - Log.report(logvisor::Fatal, _SYS_STR("Malformed Value entry, [Name,Directory,Type] required")); - return 0; - } - assets.emplace_back(); - SAsset& asset = assets.back(); - asset.type = typeElm->GetText(); - asset.id = strtoull(keyElm->GetText(), nullptr, 16); - asset.name = nameElm->GetText(); - asset.dir = dirElm->GetText(); - elm = elm->NextSiblingElement("Asset"); - } - - FILE* f = Fopen(outPath.c_str(), _SYS_STR("wb")); - if (!f) - { - Log.report(logvisor::Fatal, _SYS_STR("Unable to open destination")); - return 0; - } - - uint32_t assetCount = SBig(uint32_t(assets.size())); - FourCC sentinel(SBIG('AIDM')); - fwrite(&sentinel, 1, 4, f); - fwrite(&assetCount, 1, 4, f); - for (const SAsset& asset : assets) - { - fwrite(&asset.type, 1, 4, f); - uint64_t id = SBig(asset.id); - fwrite(&id, 1, 8, f); - uint32_t tmp = SBig(uint32_t(asset.name.length())); - fwrite(&tmp, 1, 4, f); - fwrite(asset.name.c_str(), 1, SBig(tmp), f); - tmp = SBig(uint32_t(asset.dir.length())); - fwrite(&tmp, 1, 4, f); - fwrite(asset.dir.c_str(), 1, SBig(tmp), f); - } - fflush(f); - fclose(f); - fclose(docF); - return 0; - } - - if (docF) - fclose(docF); - - Log.report(logvisor::Fatal, _SYS_STR("failed to load")); + logvisor::RegisterStandardExceptions(); + logvisor::RegisterConsoleLogger(); + if (argc < 3) { + Log.report(logvisor::Error, _SYS_STR("Usage: %s "), argv[0]); return 1; + } + + SystemString inPath = argv[1]; + SystemString outPath = argv[2]; + + tinyxml2::XMLDocument doc; + std::vector assets; + FILE* docF = Fopen(inPath.c_str(), _SYS_STR("rb")); + if (!doc.LoadFile(docF)) { + const tinyxml2::XMLElement* elm = doc.RootElement(); + if (strcmp(elm->Name(), "AssetNameMap")) { + Log.report(logvisor::Fatal, _SYS_STR("Invalid database supplied")); + return 1; + } + + elm = elm->FirstChildElement("AssetNameMap"); + if (elm == nullptr) { + Log.report(logvisor::Fatal, _SYS_STR("Malformed AssetName database")); + return 1; + } + + elm = elm->FirstChildElement("Asset"); + + while (elm) { + const tinyxml2::XMLElement* keyElm = elm->FirstChildElement("Key"); + const tinyxml2::XMLElement* valueElm = elm->FirstChildElement("Value"); + + if (!keyElm || !valueElm) { + Log.report(logvisor::Fatal, _SYS_STR("Malformed Asset entry, [Key,Value] required")); + return 0; + } + + const tinyxml2::XMLElement* nameElm = valueElm->FirstChildElement("Name"); + const tinyxml2::XMLElement* dirElm = valueElm->FirstChildElement("Directory"); + const tinyxml2::XMLElement* typeElm = valueElm->FirstChildElement("Type"); + + if (!nameElm || !dirElm || !typeElm) { + Log.report(logvisor::Fatal, _SYS_STR("Malformed Value entry, [Name,Directory,Type] required")); + return 0; + } + assets.emplace_back(); + SAsset& asset = assets.back(); + asset.type = typeElm->GetText(); + asset.id = strtoull(keyElm->GetText(), nullptr, 16); + asset.name = nameElm->GetText(); + asset.dir = dirElm->GetText(); + elm = elm->NextSiblingElement("Asset"); + } + + FILE* f = Fopen(outPath.c_str(), _SYS_STR("wb")); + if (!f) { + Log.report(logvisor::Fatal, _SYS_STR("Unable to open destination")); + return 0; + } + + uint32_t assetCount = SBig(uint32_t(assets.size())); + FourCC sentinel(SBIG('AIDM')); + fwrite(&sentinel, 1, 4, f); + fwrite(&assetCount, 1, 4, f); + for (const SAsset& asset : assets) { + fwrite(&asset.type, 1, 4, f); + uint64_t id = SBig(asset.id); + fwrite(&id, 1, 8, f); + uint32_t tmp = SBig(uint32_t(asset.name.length())); + fwrite(&tmp, 1, 4, f); + fwrite(asset.name.c_str(), 1, SBig(tmp), f); + tmp = SBig(uint32_t(asset.dir.length())); + fwrite(&tmp, 1, 4, f); + fwrite(asset.dir.c_str(), 1, SBig(tmp), f); + } + fflush(f); + fclose(f); + fclose(docF); + return 0; + } + + if (docF) + fclose(docF); + + Log.report(logvisor::Fatal, _SYS_STR("failed to load")); + return 1; } diff --git a/discord-rpc b/discord-rpc index ba9fe00c4..e6390c8c4 160000 --- a/discord-rpc +++ b/discord-rpc @@ -1 +1 @@ -Subproject commit ba9fe00c4de1d680cdc56605d9c0d2b4cf8e7a07 +Subproject commit e6390c8c4190b59f1cc98bcec688e0037b84974d diff --git a/gbalink/main.cpp b/gbalink/main.cpp index cb4adbb13..709e4260f 100644 --- a/gbalink/main.cpp +++ b/gbalink/main.cpp @@ -10,284 +10,257 @@ #undef min #undef max -class CGBASupport -{ +class CGBASupport { public: - enum class EPhase - { - LoadClientPad, - Standby, - StartProbeTimeout, - PollProbe, - StartJoyBusBoot, - PollJoyBusBoot, - DataTransfer, - Complete, - Failed - }; + enum class EPhase { + LoadClientPad, + Standby, + StartProbeTimeout, + PollProbe, + StartJoyBusBoot, + PollJoyBusBoot, + DataTransfer, + Complete, + Failed + }; private: - std::unique_ptr m_endpoint; - u32 x28_fileSize; - std::unique_ptr x2c_buffer; - EPhase x34_phase = EPhase::LoadClientPad; - float x38_timeout = 0.f; - u8 x3c_status = 0; - u32 x40_siChan = -1; - bool x44_fusionLinked = false; - bool x45_fusionBeat = false; - static CGBASupport* SharedInstance; + std::unique_ptr m_endpoint; + u32 x28_fileSize; + std::unique_ptr x2c_buffer; + EPhase x34_phase = EPhase::LoadClientPad; + float x38_timeout = 0.f; + u8 x3c_status = 0; + u32 x40_siChan = -1; + bool x44_fusionLinked = false; + bool x45_fusionBeat = false; + static CGBASupport* SharedInstance; - static u8 CalculateFusionJBusChecksum(const u8* data, size_t len); + static u8 CalculateFusionJBusChecksum(const u8* data, size_t len); public: - CGBASupport(const char* clientPadPath, std::unique_ptr&& ep); - ~CGBASupport(); - bool PollResponse(); - void Update(float dt); - bool IsReady(); - void InitializeSupport(); - void StartLink(); - EPhase GetPhase() const { return x34_phase; } - bool IsFusionLinked() const { return x44_fusionLinked; } - bool IsFusionBeat() const { return x45_fusionBeat; } + CGBASupport(const char* clientPadPath, std::unique_ptr&& ep); + ~CGBASupport(); + bool PollResponse(); + void Update(float dt); + bool IsReady(); + void InitializeSupport(); + void StartLink(); + EPhase GetPhase() const { return x34_phase; } + bool IsFusionLinked() const { return x44_fusionLinked; } + bool IsFusionBeat() const { return x45_fusionBeat; } }; CGBASupport* CGBASupport::SharedInstance; -CGBASupport::CGBASupport(const char* clientPadPath, std::unique_ptr&& ep) -: m_endpoint(std::move(ep)) -{ - FILE* fp = fopen(clientPadPath, "rb"); - if (!fp) - { - fprintf(stderr, "No file at %s\n", clientPadPath); - exit(1); +CGBASupport::CGBASupport(const char* clientPadPath, std::unique_ptr&& ep) : m_endpoint(std::move(ep)) { + FILE* fp = fopen(clientPadPath, "rb"); + if (!fp) { + fprintf(stderr, "No file at %s\n", clientPadPath); + exit(1); + } + fseek(fp, 0, SEEK_END); + x28_fileSize = ftell(fp); + fseek(fp, 0, SEEK_SET); + x2c_buffer.reset(new u8[x28_fileSize]); + fread(x2c_buffer.get(), 1, x28_fileSize, fp); + fclose(fp); + SharedInstance = this; +} + +CGBASupport::~CGBASupport() { SharedInstance = nullptr; } + +u8 CGBASupport::CalculateFusionJBusChecksum(const u8* data, size_t len) { + u32 sum = -1; + for (int i = 0; i < len; ++i) { + u8 ch = *data++; + sum ^= ch; + for (int j = 0; j < 8; ++j) { + if ((sum & 1)) { + sum >>= 1; + sum ^= 0xb010; + } else + sum >>= 1; } - fseek(fp, 0, SEEK_END); - x28_fileSize = ftell(fp); - fseek(fp, 0, SEEK_SET); - x2c_buffer.reset(new u8[x28_fileSize]); - fread(x2c_buffer.get(), 1, x28_fileSize, fp); - fclose(fp); - SharedInstance = this; + } + return sum; } -CGBASupport::~CGBASupport() -{ - SharedInstance = nullptr; -} - -u8 CGBASupport::CalculateFusionJBusChecksum(const u8* data, size_t len) -{ - u32 sum = -1; - for (int i = 0 ; i < len; ++i) - { - u8 ch = *data++; - sum ^= ch; - for (int j = 0; j < 8; ++j) - { - if ((sum & 1)) - { - sum >>= 1; - sum ^= 0xb010; - } - else - sum >>= 1; - } - } - return sum; -} - -bool CGBASupport::PollResponse() -{ - u8 status; +bool CGBASupport::PollResponse() { + u8 status; + if (m_endpoint->GBAReset(&status) == jbus::GBA_NOT_READY) if (m_endpoint->GBAReset(&status) == jbus::GBA_NOT_READY) - if (m_endpoint->GBAReset(&status) == jbus::GBA_NOT_READY) - return false; + return false; + + if (m_endpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) + return false; + if (status != (jbus::GBA_JSTAT_PSF1 | jbus::GBA_JSTAT_SEND)) + return false; + + u8 bytes[4]; + if (m_endpoint->GBARead(bytes, &status) == jbus::GBA_NOT_READY) + return false; + if (reinterpret_cast(bytes) != SBIG('AMTE')) + return false; + + if (m_endpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) + return false; + if (status != jbus::GBA_JSTAT_PSF1) + return false; + + if (m_endpoint->GBAWrite((unsigned char*)"AMTE", &status) == jbus::GBA_NOT_READY) + return false; + + if (m_endpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) + return false; + if ((status & jbus::GBA_JSTAT_FLAGS_MASK) != jbus::GBA_JSTAT_FLAGS_MASK) + return false; + + u64 profStart = jbus::GetGCTicks(); + const u64 timeToSpin = jbus::GetGCTicksPerSec() / 8000; + for (;;) { + u64 curTime = jbus::GetGCTicks(); + if (curTime - profStart > timeToSpin) + return true; if (m_endpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - return false; - if (status != (jbus::GBA_JSTAT_PSF1 | jbus::GBA_JSTAT_SEND)) - return false; - - u8 bytes[4]; - if (m_endpoint->GBARead(bytes, &status) == jbus::GBA_NOT_READY) - return false; - if (reinterpret_cast(bytes) != SBIG('AMTE')) - return false; + continue; + if (!(status & jbus::GBA_JSTAT_SEND)) + continue; if (m_endpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - return false; - if (status != jbus::GBA_JSTAT_PSF1) - return false; + continue; + if (status != (jbus::GBA_JSTAT_FLAGS_MASK | jbus::GBA_JSTAT_SEND)) + continue; + break; + } - if (m_endpoint->GBAWrite((unsigned char*)"AMTE", &status) == jbus::GBA_NOT_READY) - return false; + if (m_endpoint->GBARead(bytes, &status) != jbus::GBA_READY) + return false; - if (m_endpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - return false; - if ((status & jbus::GBA_JSTAT_FLAGS_MASK) != jbus::GBA_JSTAT_FLAGS_MASK) - return false; + if (bytes[3] != CalculateFusionJBusChecksum(bytes, 3)) + return false; - u64 profStart = jbus::GetGCTicks(); - const u64 timeToSpin = jbus::GetGCTicksPerSec() / 8000; - for (;;) - { - u64 curTime = jbus::GetGCTicks(); - if (curTime - profStart > timeToSpin) - return true; + x44_fusionLinked = (bytes[2] & 0x2) == 0; + if (x44_fusionLinked && (bytes[2] & 0x1) != 0) + x45_fusionBeat = true; - if (m_endpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - continue; - if (!(status & jbus::GBA_JSTAT_SEND)) - continue; - - if (m_endpoint->GBAGetStatus(&status) == jbus::GBA_NOT_READY) - continue; - if (status != (jbus::GBA_JSTAT_FLAGS_MASK | jbus::GBA_JSTAT_SEND)) - continue; - break; - } - - if (m_endpoint->GBARead(bytes, &status) != jbus::GBA_READY) - return false; - - if (bytes[3] != CalculateFusionJBusChecksum(bytes, 3)) - return false; - - x44_fusionLinked = (bytes[2] & 0x2) == 0; - if (x44_fusionLinked && (bytes[2] & 0x1) != 0) - x45_fusionBeat = true; - - return true; + return true; } static void JoyBootDone(jbus::ThreadLocalEndpoint& endpoint, jbus::EJoyReturn status) {} -void CGBASupport::Update(float dt) -{ - switch (x34_phase) - { - case EPhase::LoadClientPad: - IsReady(); - break; +void CGBASupport::Update(float dt) { + switch (x34_phase) { + case EPhase::LoadClientPad: + IsReady(); + break; - case EPhase::StartProbeTimeout: - x38_timeout = 4.f; - x34_phase = EPhase::PollProbe; + case EPhase::StartProbeTimeout: + x38_timeout = 4.f; + x34_phase = EPhase::PollProbe; - case EPhase::PollProbe: - /* SIProbe poll normally occurs here with 4 second timeout */ - x40_siChan = m_endpoint->getChan(); - x34_phase = EPhase::StartJoyBusBoot; + case EPhase::PollProbe: + /* SIProbe poll normally occurs here with 4 second timeout */ + x40_siChan = m_endpoint->getChan(); + x34_phase = EPhase::StartJoyBusBoot; - case EPhase::StartJoyBusBoot: - x34_phase = EPhase::PollJoyBusBoot; - if (m_endpoint->GBAJoyBootAsync(x40_siChan * 2, 2, - x2c_buffer.get(), x28_fileSize, &x3c_status, - std::bind(JoyBootDone, - std::placeholders::_1, - std::placeholders::_2)) != jbus::GBA_READY) - x34_phase = EPhase::Failed; - break; + case EPhase::StartJoyBusBoot: + x34_phase = EPhase::PollJoyBusBoot; + if (m_endpoint->GBAJoyBootAsync(x40_siChan * 2, 2, x2c_buffer.get(), x28_fileSize, &x3c_status, + std::bind(JoyBootDone, std::placeholders::_1, std::placeholders::_2)) != + jbus::GBA_READY) + x34_phase = EPhase::Failed; + break; - case EPhase::PollJoyBusBoot: - u8 percent; - if (m_endpoint->GBAGetProcessStatus(percent) == jbus::GBA_BUSY) - break; - if (m_endpoint->GBAGetStatus(&x3c_status) == jbus::GBA_NOT_READY) - { - x34_phase = EPhase::Failed; - break; - } - x38_timeout = 4.f; - x34_phase = EPhase::DataTransfer; - break; - - case EPhase::DataTransfer: - if (PollResponse()) - { - x34_phase = EPhase::Complete; - break; - } - x38_timeout = std::max(0.f, x38_timeout - dt); - if (x38_timeout == 0.f) - x34_phase = EPhase::Failed; - break; - - default: break; + case EPhase::PollJoyBusBoot: + u8 percent; + if (m_endpoint->GBAGetProcessStatus(percent) == jbus::GBA_BUSY) + break; + if (m_endpoint->GBAGetStatus(&x3c_status) == jbus::GBA_NOT_READY) { + x34_phase = EPhase::Failed; + break; } + x38_timeout = 4.f; + x34_phase = EPhase::DataTransfer; + break; + + case EPhase::DataTransfer: + if (PollResponse()) { + x34_phase = EPhase::Complete; + break; + } + x38_timeout = std::max(0.f, x38_timeout - dt); + if (x38_timeout == 0.f) + x34_phase = EPhase::Failed; + break; + + default: + break; + } } -bool CGBASupport::IsReady() -{ - if (x34_phase != EPhase::LoadClientPad) - return true; - - x34_phase = EPhase::Standby; - reinterpret_cast(x2c_buffer[0xc8]) = u32(jbus::GetGCTicks()); - x2c_buffer[0xaf] = 'E'; - x2c_buffer[0xbd] = 0xc9; +bool CGBASupport::IsReady() { + if (x34_phase != EPhase::LoadClientPad) return true; + + x34_phase = EPhase::Standby; + reinterpret_cast(x2c_buffer[0xc8]) = u32(jbus::GetGCTicks()); + x2c_buffer[0xaf] = 'E'; + x2c_buffer[0xbd] = 0xc9; + return true; } -void CGBASupport::InitializeSupport() -{ - x34_phase = EPhase::Standby; - x38_timeout = 0.f; - x3c_status = false; - x40_siChan = -1; - x44_fusionLinked = false; - x45_fusionBeat = false; +void CGBASupport::InitializeSupport() { + x34_phase = EPhase::Standby; + x38_timeout = 0.f; + x3c_status = false; + x40_siChan = -1; + x44_fusionLinked = false; + x45_fusionBeat = false; } -void CGBASupport::StartLink() -{ - x34_phase = EPhase::StartProbeTimeout; - x40_siChan = -1; +void CGBASupport::StartLink() { + x34_phase = EPhase::StartProbeTimeout; + x40_siChan = -1; } -int main(int argc, char** argv) -{ - jbus::Initialize(); - printf("Listening for client\n"); - jbus::Listener listener; - listener.start(); - std::unique_ptr endpoint; - while (true) - { - s64 frameStart = jbus::GetGCTicks(); - endpoint = listener.accept(); - if (endpoint) - break; - s64 frameEnd = jbus::GetGCTicks(); - s64 waitTicks = jbus::GetGCTicksPerSec() / 60; - if (waitTicks > 0) - jbus::WaitGCTicks(waitTicks); - } +int main(int argc, char** argv) { + jbus::Initialize(); + printf("Listening for client\n"); + jbus::Listener listener; + listener.start(); + std::unique_ptr endpoint; + while (true) { + s64 frameStart = jbus::GetGCTicks(); + endpoint = listener.accept(); + if (endpoint) + break; + s64 frameEnd = jbus::GetGCTicks(); + s64 waitTicks = jbus::GetGCTicksPerSec() / 60; + if (waitTicks > 0) + jbus::WaitGCTicks(waitTicks); + } - CGBASupport gba("client_pad.bin", std::move(endpoint)); - gba.Update(0.f); - gba.InitializeSupport(); - gba.StartLink(); + CGBASupport gba("client_pad.bin", std::move(endpoint)); + gba.Update(0.f); + gba.InitializeSupport(); + gba.StartLink(); - printf("Waiting 5 sec\n"); - jbus::WaitGCTicks(jbus::GetGCTicksPerSec() * 5); + printf("Waiting 5 sec\n"); + jbus::WaitGCTicks(jbus::GetGCTicksPerSec() * 5); - printf("Connecting\n"); - while (gba.GetPhase() < CGBASupport::EPhase::Complete) - { - gba.Update(1.f / 60.f); - s64 waitTicks = jbus::GetGCTicksPerSec() / 60; - if (waitTicks > 0) - jbus::WaitGCTicks(waitTicks); - } + printf("Connecting\n"); + while (gba.GetPhase() < CGBASupport::EPhase::Complete) { + gba.Update(1.f / 60.f); + s64 waitTicks = jbus::GetGCTicksPerSec() / 60; + if (waitTicks > 0) + jbus::WaitGCTicks(waitTicks); + } - CGBASupport::EPhase finalPhase = gba.GetPhase(); - printf("%s Linked: %d Beat: %d\n", - finalPhase == CGBASupport::EPhase::Complete ? "Complete" : "Failed", - gba.IsFusionLinked(), gba.IsFusionBeat()); + CGBASupport::EPhase finalPhase = gba.GetPhase(); + printf("%s Linked: %d Beat: %d\n", finalPhase == CGBASupport::EPhase::Complete ? "Complete" : "Failed", + gba.IsFusionLinked(), gba.IsFusionBeat()); - return 0; + return 0; } diff --git a/hecl b/hecl index 375fbcaa6..6013faad9 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 375fbcaa6a271296fa15bd7153d2ce2eb1ddc10f +Subproject commit 6013faad970e35c2fa990bb870bf704e55336b5d diff --git a/hecl-gui b/hecl-gui index 4a4591a48..7db4cf70b 160000 --- a/hecl-gui +++ b/hecl-gui @@ -1 +1 @@ -Subproject commit 4a4591a487c6a7df6b1cbf6ab01140ec2ec7c2e7 +Subproject commit 7db4cf70b4b53fbe52b299e003ffd99a1b5ee657 diff --git a/jbus b/jbus index 500f88d7a..e28b6551d 160000 --- a/jbus +++ b/jbus @@ -1 +1 @@ -Subproject commit 500f88d7a70c5118b05209ca2e513f8440606a04 +Subproject commit e28b6551d012182ef96cbb8c5fdba881ab0fdecd diff --git a/kabufuda b/kabufuda index a1e224269..f126245ee 160000 --- a/kabufuda +++ b/kabufuda @@ -1 +1 @@ -Subproject commit a1e224269104af52add34a737e41d1b56727e142 +Subproject commit f126245eeffa5df2f755949843cf850dd748384e diff --git a/mpcksum/main.cpp b/mpcksum/main.cpp index 4fa9ca385..086380988 100644 --- a/mpcksum/main.cpp +++ b/mpcksum/main.cpp @@ -6,46 +6,41 @@ #if __BYTE_ORDER__ == __BIG_ENDIAN #define SBIG(q) q #else -#define SBIG(q) ( ( (q) & 0x000000FF ) << 24 | ( (q) & 0x0000FF00 ) << 8 \ - | ( (q) & 0x00FF0000 ) >> 8 | ( (q) & 0xFF000000 ) >> 24 ) +#define SBIG(q) (((q)&0x000000FF) << 24 | ((q)&0x0000FF00) << 8 | ((q)&0x00FF0000) >> 8 | ((q)&0xFF000000) >> 24) #endif -int main(int argc, char* argv[]) -{ - if (argc < 2) - { - printf("mpcksum [output]\n"); - return 1; - } +int main(int argc, char* argv[]) { + if (argc < 2) { + printf("mpcksum [output]\n"); + return 1; + } - athena::io::MemoryCopyReader in(argv[1]); - std::unique_ptr out; - if (argc > 2) - out.reset(new athena::io::FileWriter(argv[2])); - else - out.reset(new athena::io::FileWriter(argv[1])); + athena::io::MemoryCopyReader in(argv[1]); + std::unique_ptr out; + if (argc > 2) + out.reset(new athena::io::FileWriter(argv[2])); + else + out.reset(new athena::io::FileWriter(argv[1])); - atUint32 magic; - in.readUBytesToBuf(&magic, 4); - if (magic != SBIG('GM8E') && magic != SBIG('GM8P') && magic != SBIG('GM8J')) - { - printf("Unsupported file, MP .gci file expected\n"); - return 1; - } + atUint32 magic; + in.readUBytesToBuf(&magic, 4); + if (magic != SBIG('GM8E') && magic != SBIG('GM8P') && magic != SBIG('GM8J')) { + printf("Unsupported file, MP .gci file expected\n"); + return 1; + } - if (in.length() != 8256) - { - printf("File too small expected 8,256 bytes got %" PRIu64, in.length()); - return 1; - } + if (in.length() != 8256) { + printf("File too small expected 8,256 bytes got %" PRIu64, in.length()); + return 1; + } - atUint8* data = in.data(); + atUint8* data = in.data(); - atUint32 newCkSum = athena::checksums::crc32(data + 68, 8188, ~0, 0); - *(atUint32*)(data + 64) = SBIG(newCkSum); - out->writeBytes(data, 8256); + atUint32 newCkSum = athena::checksums::crc32(data + 68, 8188, ~0, 0); + *(atUint32*)(data + 64) = SBIG(newCkSum); + out->writeBytes(data, 8256); - delete data; + delete data; - return 0; + return 0; } diff --git a/nod b/nod index 3d380fdc3..be8409681 160000 --- a/nod +++ b/nod @@ -1 +1 @@ -Subproject commit 3d380fdc3b1b243c057dac13c9019a08b7eb8700 +Subproject commit be8409681fd5e921be72a04f460e87f2de5f6280 diff --git a/rapidjson b/rapidjson index af223d44f..66eb6067b 160000 --- a/rapidjson +++ b/rapidjson @@ -1 +1 @@ -Subproject commit af223d44f4e8d3772cb1ac0ce8bc2a132b51717f +Subproject commit 66eb6067b10fd02e419f88816a8833a64eb33551 diff --git a/specter b/specter index b8da816de..96c8824a4 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit b8da816de24301d22dc874bfb47ca7f8238cde04 +Subproject commit 96c8824a43af0e2b65af7758d3e12d9bff146036 diff --git a/visigen/MainWin.cpp b/visigen/MainWin.cpp index 4d9f9c9cb..734fb4058 100644 --- a/visigen/MainWin.cpp +++ b/visigen/MainWin.cpp @@ -8,163 +8,142 @@ #include static logvisor::Module AthenaLog("Athena"); -static void AthenaExc(athena::error::Level level, const char* file, - const char*, int line, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - AthenaLog.report(logvisor::Level(level), fmt, ap); - va_end(ap); +static void AthenaExc(athena::error::Level level, const char* file, const char*, int line, const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + AthenaLog.report(logvisor::Level(level), fmt, ap); + va_end(ap); } static float s_Percent = 0.f; static DWORD s_mainThreadId; -static void UpdatePercent(float percent) -{ - s_Percent = percent; - PostThreadMessage(s_mainThreadId, WM_USER+1, 0, 0); +static void UpdatePercent(float percent) { + s_Percent = percent; + PostThreadMessage(s_mainThreadId, WM_USER + 1, 0, 0); } static const DWORD dwStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; static VISIRenderer* s_Renderer; -static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - if (uMsg == WM_SIZING) - { - RECT& dragRect = reinterpret_cast(lParam); - RECT tmpRect = dragRect; - tmpRect.bottom = tmpRect.top + 512; - tmpRect.right = tmpRect.left + 768; - AdjustWindowRect(&tmpRect, dwStyle, FALSE); - dragRect = tmpRect; - return TRUE; - } - else if (uMsg == WM_CLOSE) - { - s_Renderer->Terminate(); - return 0; - } - return DefWindowProc(hwnd, uMsg, wParam, lParam); +static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + if (uMsg == WM_SIZING) { + RECT& dragRect = reinterpret_cast(lParam); + RECT tmpRect = dragRect; + tmpRect.bottom = tmpRect.top + 512; + tmpRect.right = tmpRect.left + 768; + AdjustWindowRect(&tmpRect, dwStyle, FALSE); + dragRect = tmpRect; + return TRUE; + } else if (uMsg == WM_CLOSE) { + s_Renderer->Terminate(); + return 0; + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); } -int wmain(int argc, const hecl::SystemChar** argv) -{ - if (argc > 1 && !wcscmp(argv[1], L"--dlpackage")) - { - printf("%s\n", URDE_DLPACKAGE); - return 100; +int wmain(int argc, const hecl::SystemChar** argv) { + if (argc > 1 && !wcscmp(argv[1], L"--dlpackage")) { + printf("%s\n", URDE_DLPACKAGE); + return 100; + } + + logvisor::RegisterStandardExceptions(); + logvisor::RegisterConsoleLogger(); + atSetExceptionHandler(AthenaExc); + VISIRenderer renderer(argc, argv); + s_Renderer = &renderer; + + int instIdx = -1; + if (argc > 3) + instIdx = _wtoi(argv[3]); + + WNDCLASS wndClass = {CS_NOCLOSE, WindowProc, 0, 0, GetModuleHandle(nullptr), 0, 0, 0, 0, L"VISIGenWindow"}; + RegisterClassW(&wndClass); + + RECT clientRect = {0, 0, 768, 512}; + AdjustWindowRect(&clientRect, dwStyle, FALSE); + + int x = 0; + int y = 0; + if (instIdx != -1) { + x = (instIdx & 1) != 0; + y = (instIdx & 2) != 0; + } + + HWND window = CreateWindowW(L"VISIGenWindow", L"VISIGen", dwStyle, x, y, clientRect.right - clientRect.left, + clientRect.bottom - clientRect.top, NULL, NULL, NULL, NULL); + + PIXELFORMATDESCRIPTOR pfd = {sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, // Flags + PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. + 32, // Colordepth of the framebuffer. + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 24, // Number of bits for the depthbuffer + 8, // Number of bits for the stencilbuffer + 0, // Number of Aux buffers in the framebuffer. + PFD_MAIN_PLANE, + 0, + 0, + 0, + 0}; + + HDC deviceContext = GetDC(window); + int pf = ChoosePixelFormat(deviceContext, &pfd); + SetPixelFormat(deviceContext, pf, &pfd); + HGLRC glContext = wglCreateContext(deviceContext); + ShowWindow(window, SW_SHOW); + + s_mainThreadId = GetCurrentThreadId(); + + /* Spawn client thread */ + std::thread clientThread([&]() { + wglMakeCurrent(deviceContext, glContext); + renderer.Run(UpdatePercent); + PostThreadMessage(s_mainThreadId, WM_USER, 0, 0); + }); + + /* Pump messages */ + MSG msg = {0}; + while (GetMessage(&msg, NULL, 0, 0)) { + if (!msg.hwnd) { + /* PostThreadMessage events */ + switch (msg.message) { + case WM_USER: + /* Quit message from client thread */ + PostQuitMessage(0); + continue; + case WM_USER + 1: + /* Update window title from client thread */ + wchar_t title[256]; + StringCbPrintfW(title, 512, L"VISIGen [%g%%]", s_Percent * 100.f); + SetWindowTextW(window, title); + continue; + default: + break; + } } + TranslateMessage(&msg); + DispatchMessage(&msg); + } - logvisor::RegisterStandardExceptions(); - logvisor::RegisterConsoleLogger(); - atSetExceptionHandler(AthenaExc); - VISIRenderer renderer(argc, argv); - s_Renderer = &renderer; + renderer.Terminate(); + if (clientThread.joinable()) + clientThread.join(); - int instIdx = -1; - if (argc > 3) - instIdx = _wtoi(argv[3]); + wglDeleteContext(glContext); - WNDCLASS wndClass = - { - CS_NOCLOSE, - WindowProc, - 0, - 0, - GetModuleHandle(nullptr), - 0, - 0, - 0, - 0, - L"VISIGenWindow" - }; - RegisterClassW(&wndClass); - - RECT clientRect = {0, 0, 768, 512}; - AdjustWindowRect(&clientRect, dwStyle, FALSE); - - int x = 0; - int y = 0; - if (instIdx != -1) - { - x = (instIdx & 1) != 0; - y = (instIdx & 2) != 0; - } - - HWND window = CreateWindowW(L"VISIGenWindow", L"VISIGen", dwStyle, - x, y, - clientRect.right - clientRect.left, - clientRect.bottom - clientRect.top, - NULL, NULL, NULL, NULL); - - PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), - 1, - PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, //Flags - PFD_TYPE_RGBA, //The kind of framebuffer. RGBA or palette. - 32, //Colordepth of the framebuffer. - 0, 0, 0, 0, 0, 0, - 0, - 0, - 0, - 0, 0, 0, 0, - 24, //Number of bits for the depthbuffer - 8, //Number of bits for the stencilbuffer - 0, //Number of Aux buffers in the framebuffer. - PFD_MAIN_PLANE, - 0, - 0, 0, 0 - }; - - HDC deviceContext = GetDC(window); - int pf = ChoosePixelFormat(deviceContext, &pfd); - SetPixelFormat(deviceContext, pf, &pfd); - HGLRC glContext = wglCreateContext(deviceContext); - ShowWindow(window, SW_SHOW); - - s_mainThreadId = GetCurrentThreadId(); - - /* Spawn client thread */ - std::thread clientThread([&]() - { - wglMakeCurrent(deviceContext, glContext); - renderer.Run(UpdatePercent); - PostThreadMessage(s_mainThreadId, WM_USER, 0, 0); - }); - - /* Pump messages */ - MSG msg = {0}; - while (GetMessage(&msg, NULL, 0, 0)) - { - if (!msg.hwnd) - { - /* PostThreadMessage events */ - switch (msg.message) - { - case WM_USER: - /* Quit message from client thread */ - PostQuitMessage(0); - continue; - case WM_USER+1: - /* Update window title from client thread */ - wchar_t title[256]; - StringCbPrintfW(title, 512, L"VISIGen [%g%%]", s_Percent * 100.f); - SetWindowTextW(window, title); - continue; - default: break; - } - } - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - renderer.Terminate(); - if (clientThread.joinable()) - clientThread.join(); - - wglDeleteContext(glContext); - - return renderer.ReturnVal(); + return renderer.ReturnVal(); } diff --git a/visigen/MainXlib.cpp b/visigen/MainXlib.cpp index 2d8cc6c39..6943d6c9f 100644 --- a/visigen/MainXlib.cpp +++ b/visigen/MainXlib.cpp @@ -10,343 +10,296 @@ #include #include -#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_HINTS_DECORATIONS (1L << 1) -#define MWM_DECOR_BORDER (1L<<1) -#define MWM_DECOR_RESIZEH (1L<<2) -#define MWM_DECOR_TITLE (1L<<3) -#define MWM_DECOR_MENU (1L<<4) -#define MWM_DECOR_MINIMIZE (1L<<5) -#define MWM_DECOR_MAXIMIZE (1L<<6) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) -#define MWM_FUNC_RESIZE (1L<<1) -#define MWM_FUNC_MOVE (1L<<2) -#define MWM_FUNC_MINIMIZE (1L<<3) -#define MWM_FUNC_MAXIMIZE (1L<<4) -#define MWM_FUNC_CLOSE (1L<<5) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); static glXCreateContextAttribsARBProc glXCreateContextAttribsARB = nullptr; -static const int ContextAttribList[7][7] = -{ -{ GLX_CONTEXT_MAJOR_VERSION_ARB, 4, - GLX_CONTEXT_MINOR_VERSION_ARB, 5, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - 0 -}, -{ GLX_CONTEXT_MAJOR_VERSION_ARB, 4, - GLX_CONTEXT_MINOR_VERSION_ARB, 4, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - 0 -}, -{ GLX_CONTEXT_MAJOR_VERSION_ARB, 4, - GLX_CONTEXT_MINOR_VERSION_ARB, 3, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - 0 -}, -{ GLX_CONTEXT_MAJOR_VERSION_ARB, 4, - GLX_CONTEXT_MINOR_VERSION_ARB, 2, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - 0 -}, -{ GLX_CONTEXT_MAJOR_VERSION_ARB, 4, - GLX_CONTEXT_MINOR_VERSION_ARB, 1, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - 0 -}, -{ GLX_CONTEXT_MAJOR_VERSION_ARB, 4, - GLX_CONTEXT_MINOR_VERSION_ARB, 0, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - 0 -}, -{ GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 3, - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - 0 -}, +static const int ContextAttribList[7][7] = { + {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 5, GLX_CONTEXT_FLAGS_ARB, + GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0}, + {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 4, GLX_CONTEXT_FLAGS_ARB, + GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0}, + {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 3, GLX_CONTEXT_FLAGS_ARB, + GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0}, + {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 2, GLX_CONTEXT_FLAGS_ARB, + GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0}, + {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 1, GLX_CONTEXT_FLAGS_ARB, + GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0}, + {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 0, GLX_CONTEXT_FLAGS_ARB, + GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0}, + {GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 3, GLX_CONTEXT_FLAGS_ARB, + GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 0}, }; static bool s_glxError; -static int ctxErrorHandler(Display */*dpy*/, XErrorEvent */*ev*/) -{ - s_glxError = true; - return 0; +static int ctxErrorHandler(Display* /*dpy*/, XErrorEvent* /*ev*/) { + s_glxError = true; + return 0; } static logvisor::Module Log("visigen-xlib"); static logvisor::Module AthenaLog("Athena"); -static void AthenaExc(athena::error::Level level, const char* /*file*/, - const char*, int /*line*/, const char* fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - AthenaLog.report(logvisor::Level(level), fmt, ap); - va_end(ap); +static void AthenaExc(athena::error::Level level, const char* /*file*/, const char*, int /*line*/, const char* fmt, + ...) { + va_list ap; + va_start(ap, fmt); + AthenaLog.report(logvisor::Level(level), fmt, ap); + va_end(ap); } static Display* xDisp; static Window windowId; -static void UpdatePercent(float percent) -{ - XLockDisplay(xDisp); - char title[256]; - snprintf(title, 256, "VISIGen [%g%%]", double(percent * 100.f)); - XChangeProperty(xDisp, windowId, XA_WM_NAME, XA_STRING, 8, - PropModeReplace, reinterpret_cast(title), int(strlen(title))); - XUnlockDisplay(xDisp); +static void UpdatePercent(float percent) { + XLockDisplay(xDisp); + char title[256]; + snprintf(title, 256, "VISIGen [%g%%]", double(percent * 100.f)); + XChangeProperty(xDisp, windowId, XA_WM_NAME, XA_STRING, 8, PropModeReplace, reinterpret_cast(title), + int(strlen(title))); + XUnlockDisplay(xDisp); } /* Empty handler for SIGINT */ static void _sigint(int) {} -int main(int argc, const char** argv) -{ - if (argc > 1 && !strcmp(argv[1], "--dlpackage")) - { - printf("%s\n", URDE_DLPACKAGE); - return 100; +int main(int argc, const char** argv) { + if (argc > 1 && !strcmp(argv[1], "--dlpackage")) { + printf("%s\n", URDE_DLPACKAGE); + return 100; + } + + /* Program is portable to all locales */ + setlocale(LC_ALL, ""); + + logvisor::RegisterStandardExceptions(); + logvisor::RegisterConsoleLogger(); + atSetExceptionHandler(AthenaExc); + VISIRenderer renderer(argc, argv); + + if (!XInitThreads()) { + Log.report(logvisor::Error, "X doesn't support multithreading"); + return 1; + } + + /* Open Xlib Display */ + xDisp = XOpenDisplay(nullptr); + if (!xDisp) { + Log.report(logvisor::Error, "Can't open X display"); + return 1; + } + + /* Default screen */ + int xDefaultScreen = DefaultScreen(xDisp); + Screen* screen = ScreenOfDisplay(xDisp, xDefaultScreen); + + /* Query framebuffer configurations */ + GLXFBConfig* fbConfigs = nullptr; + int numFBConfigs = 0; + fbConfigs = glXGetFBConfigs(xDisp, xDefaultScreen, &numFBConfigs); + if (!fbConfigs || numFBConfigs == 0) { + Log.report(logvisor::Error, "glXGetFBConfigs failed"); + return 1; + } + + VisualID selVisualId = 0; + GLXFBConfig selFBConfig = nullptr; + for (int i = 0; i < numFBConfigs; ++i) { + GLXFBConfig config = fbConfigs[i]; + int visualId, depthSize, colorSize, doubleBuffer; + glXGetFBConfigAttrib(xDisp, config, GLX_VISUAL_ID, &visualId); + glXGetFBConfigAttrib(xDisp, config, GLX_DEPTH_SIZE, &depthSize); + glXGetFBConfigAttrib(xDisp, config, GLX_BUFFER_SIZE, &colorSize); + glXGetFBConfigAttrib(xDisp, config, GLX_DOUBLEBUFFER, &doubleBuffer); + + /* Single-buffer only */ + if (doubleBuffer) + continue; + + if (colorSize >= 32 && depthSize >= 24 && visualId != 0) { + selFBConfig = config; + selVisualId = VisualID(visualId); + break; + } + } + XFree(fbConfigs); + + if (!selFBConfig) { + Log.report(logvisor::Error, "unable to find suitable pixel format"); + return 1; + } + + XVisualInfo visTemplate = {}; + visTemplate.screen = xDefaultScreen; + int numVisuals; + XVisualInfo* visualList = XGetVisualInfo(xDisp, VisualScreenMask, &visTemplate, &numVisuals); + Visual* selectedVisual = nullptr; + for (int i = 0; i < numVisuals; ++i) { + if (visualList[i].visualid == selVisualId) { + selectedVisual = visualList[i].visual; + break; + } + } + XFree(visualList); + + /* Create colormap */ + Colormap colormapId = XCreateColormap(xDisp, screen->root, selectedVisual, AllocNone); + + /* Create window */ + XSetWindowAttributes swa; + swa.colormap = colormapId; + swa.border_pixmap = 0; + swa.event_mask = 0; + + int instIdx = -1; + if (argc > 3) + instIdx = atoi(argv[3]); + + int x = 0; + int y = 0; + if (instIdx != -1) { + x = (instIdx & 1) != 0; + y = (instIdx & 2) != 0; + } + + windowId = XCreateWindow(xDisp, screen->root, x, y, 768, 512, 10, CopyFromParent, CopyFromParent, selectedVisual, + CWBorderPixel | CWEventMask | CWColormap, &swa); + + if (!glXCreateContextAttribsARB) { + glXCreateContextAttribsARB = reinterpret_cast( + glXGetProcAddressARB(reinterpret_cast("glXCreateContextAttribsARB"))); + if (!glXCreateContextAttribsARB) { + Log.report(logvisor::Error, "unable to resolve glXCreateContextAttribsARB"); + return 1; + } + } + + s_glxError = false; + XErrorHandler oldHandler = XSetErrorHandler(ctxErrorHandler); + GLXContext glxCtx = nullptr; + for (uint32_t attribIdx = 0; attribIdx < std::extent::value; ++attribIdx) { + glxCtx = glXCreateContextAttribsARB(xDisp, selFBConfig, nullptr, True, ContextAttribList[attribIdx]); + if (glxCtx) + break; + } + XSetErrorHandler(oldHandler); + if (!glxCtx) { + Log.report(logvisor::Fatal, "unable to make new GLX context"); + return 1; + } + GLXWindow glxWindow = glXCreateWindow(xDisp, selFBConfig, windowId, nullptr); + if (!glxWindow) { + Log.report(logvisor::Fatal, "unable to make new GLX window"); + return 1; + } + + XMapWindow(xDisp, windowId); + + struct { + unsigned long flags = 0; + unsigned long functions = 0; + unsigned long decorations = 0; + long inputMode = 0; + unsigned long status = 0; + } wmHints; + + Atom motifWmHints = XInternAtom(xDisp, "_MOTIF_WM_HINTS", True); + if (motifWmHints) { + wmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; + wmHints.decorations |= MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MINIMIZE | MWM_DECOR_MENU; + wmHints.functions |= MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE; + XChangeProperty(xDisp, windowId, motifWmHints, motifWmHints, 32, PropModeReplace, + reinterpret_cast(&wmHints), 5); + } + + /* SIGINT will be used to cancel main thread when client thread ends + * (also enables graceful quitting via ctrl-c) */ + pthread_t mainThread = pthread_self(); + struct sigaction s; + s.sa_handler = _sigint; + sigemptyset(&s.sa_mask); + s.sa_flags = 0; + sigaction(SIGINT, &s, nullptr); + sigaction(SIGUSR2, &s, nullptr); + + sigset_t waitmask, origmask; + sigemptyset(&waitmask); + sigaddset(&waitmask, SIGINT); + sigaddset(&waitmask, SIGUSR2); + pthread_sigmask(SIG_BLOCK, &waitmask, &origmask); + + int x11Fd = ConnectionNumber(xDisp); + + /* Spawn client thread */ + bool clientRunning = true; + std::mutex initmt; + std::condition_variable initcv; + std::unique_lock outerLk(initmt); + std::thread clientThread([&]() { + std::unique_lock innerLk(initmt); + innerLk.unlock(); + initcv.notify_one(); + + XLockDisplay(xDisp); + if (!glXMakeContextCurrent(xDisp, glxWindow, glxWindow, glxCtx)) + Log.report(logvisor::Fatal, "unable to make GLX context current"); + XUnlockDisplay(xDisp); + + renderer.Run(UpdatePercent); + clientRunning = false; + + XLockDisplay(xDisp); + XClientMessageEvent exitEvent = {}; + exitEvent.type = ClientMessage; + exitEvent.window = windowId; + exitEvent.format = 32; + XSendEvent(xDisp, windowId, 0, 0, reinterpret_cast(&exitEvent)); + XFlush(xDisp); + XUnlockDisplay(xDisp); + }); + initcv.wait(outerLk); + + /* Begin application event loop */ + while (clientRunning) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(x11Fd, &fds); + if (pselect(x11Fd + 1, &fds, nullptr, nullptr, nullptr, &origmask) < 0) { + /* SIGINT/SIGUSR2 handled here */ + if (errno == EINTR || errno == SIGUSR2) + break; } - /* Program is portable to all locales */ - setlocale(LC_ALL, ""); - - logvisor::RegisterStandardExceptions(); - logvisor::RegisterConsoleLogger(); - atSetExceptionHandler(AthenaExc); - VISIRenderer renderer(argc, argv); - - if (!XInitThreads()) - { - Log.report(logvisor::Error, "X doesn't support multithreading"); - return 1; + if (FD_ISSET(x11Fd, &fds)) { + XLockDisplay(xDisp); + while (XPending(xDisp)) { + XEvent event; + XNextEvent(xDisp, &event); + if (XFilterEvent(&event, None)) + continue; + } + XUnlockDisplay(xDisp); } + } - /* Open Xlib Display */ - xDisp = XOpenDisplay(nullptr); - if (!xDisp) - { - Log.report(logvisor::Error, "Can't open X display"); - return 1; - } + renderer.Terminate(); + pthread_cancel(clientThread.native_handle()); + if (clientThread.joinable()) + clientThread.join(); - /* Default screen */ - int xDefaultScreen = DefaultScreen(xDisp); - Screen* screen = ScreenOfDisplay(xDisp, xDefaultScreen); - - /* Query framebuffer configurations */ - GLXFBConfig* fbConfigs = nullptr; - int numFBConfigs = 0; - fbConfigs = glXGetFBConfigs(xDisp, xDefaultScreen, &numFBConfigs); - if (!fbConfigs || numFBConfigs == 0) - { - Log.report(logvisor::Error, "glXGetFBConfigs failed"); - return 1; - } - - VisualID selVisualId = 0; - GLXFBConfig selFBConfig = nullptr; - for (int i=0 ; i= 32 && depthSize >= 24 && visualId != 0) - { - selFBConfig = config; - selVisualId = VisualID(visualId); - break; - } - } - XFree(fbConfigs); - - if (!selFBConfig) - { - Log.report(logvisor::Error, "unable to find suitable pixel format"); - return 1; - } - - XVisualInfo visTemplate = {}; - visTemplate.screen = xDefaultScreen; - int numVisuals; - XVisualInfo* visualList = XGetVisualInfo(xDisp, VisualScreenMask, &visTemplate, &numVisuals); - Visual* selectedVisual = nullptr; - for (int i=0 ; iroot, selectedVisual, AllocNone); - - /* Create window */ - XSetWindowAttributes swa; - swa.colormap = colormapId; - swa.border_pixmap = 0; - swa.event_mask = 0; - - int instIdx = -1; - if (argc > 3) - instIdx = atoi(argv[3]); - - int x = 0; - int y = 0; - if (instIdx != -1) - { - x = (instIdx & 1) != 0; - y = (instIdx & 2) != 0; - } - - windowId = XCreateWindow(xDisp, screen->root, x, y, 768, 512, 10, - CopyFromParent, CopyFromParent, selectedVisual, - CWBorderPixel | CWEventMask | CWColormap, &swa); - - if (!glXCreateContextAttribsARB) - { - glXCreateContextAttribsARB = reinterpret_cast( - glXGetProcAddressARB(reinterpret_cast("glXCreateContextAttribsARB"))); - if (!glXCreateContextAttribsARB) - { - Log.report(logvisor::Error, "unable to resolve glXCreateContextAttribsARB"); - return 1; - } - } - - s_glxError = false; - XErrorHandler oldHandler = XSetErrorHandler(ctxErrorHandler); - GLXContext glxCtx = nullptr; - for (uint32_t attribIdx=0 ; attribIdx::value ; ++attribIdx) - { - glxCtx = glXCreateContextAttribsARB(xDisp, selFBConfig, nullptr, True, ContextAttribList[attribIdx]); - if (glxCtx) - break; - } - XSetErrorHandler(oldHandler); - if (!glxCtx) - { - Log.report(logvisor::Fatal, "unable to make new GLX context"); - return 1; - } - GLXWindow glxWindow = glXCreateWindow(xDisp, selFBConfig, windowId, nullptr); - if (!glxWindow) - { - Log.report(logvisor::Fatal, "unable to make new GLX window"); - return 1; - } - - XMapWindow(xDisp, windowId); - - struct - { - unsigned long flags = 0; - unsigned long functions = 0; - unsigned long decorations = 0; - long inputMode = 0; - unsigned long status = 0; - } wmHints; - - Atom motifWmHints = XInternAtom(xDisp, "_MOTIF_WM_HINTS", True); - if (motifWmHints) - { - wmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; - wmHints.decorations |= MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MINIMIZE | MWM_DECOR_MENU; - wmHints.functions |= MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE; - XChangeProperty(xDisp, windowId, motifWmHints, motifWmHints, 32, PropModeReplace, reinterpret_cast(&wmHints), 5); - } - - /* SIGINT will be used to cancel main thread when client thread ends - * (also enables graceful quitting via ctrl-c) */ - pthread_t mainThread = pthread_self(); - struct sigaction s; - s.sa_handler = _sigint; - sigemptyset(&s.sa_mask); - s.sa_flags = 0; - sigaction(SIGINT, &s, nullptr); - sigaction(SIGUSR2, &s, nullptr); - - sigset_t waitmask, origmask; - sigemptyset(&waitmask); - sigaddset(&waitmask, SIGINT); - sigaddset(&waitmask, SIGUSR2); - pthread_sigmask(SIG_BLOCK, &waitmask, &origmask); - - int x11Fd = ConnectionNumber(xDisp); - - /* Spawn client thread */ - bool clientRunning = true; - std::mutex initmt; - std::condition_variable initcv; - std::unique_lock outerLk(initmt); - std::thread clientThread([&]() - { - std::unique_lock innerLk(initmt); - innerLk.unlock(); - initcv.notify_one(); - - XLockDisplay(xDisp); - if (!glXMakeContextCurrent(xDisp, glxWindow, glxWindow, glxCtx)) - Log.report(logvisor::Fatal, "unable to make GLX context current"); - XUnlockDisplay(xDisp); - - renderer.Run(UpdatePercent); - clientRunning = false; - - XLockDisplay(xDisp); - XClientMessageEvent exitEvent = {}; - exitEvent.type = ClientMessage; - exitEvent.window = windowId; - exitEvent.format = 32; - XSendEvent(xDisp, windowId, 0, 0, reinterpret_cast(&exitEvent)); - XFlush(xDisp); - XUnlockDisplay(xDisp); - }); - initcv.wait(outerLk); - - /* Begin application event loop */ - while (clientRunning) - { - fd_set fds; - FD_ZERO(&fds); - FD_SET(x11Fd, &fds); - if (pselect(x11Fd+1, &fds, nullptr, nullptr, nullptr, &origmask) < 0) - { - /* SIGINT/SIGUSR2 handled here */ - if (errno == EINTR || errno == SIGUSR2) - break; - } - - if (FD_ISSET(x11Fd, &fds)) - { - XLockDisplay(xDisp); - while (XPending(xDisp)) - { - XEvent event; - XNextEvent(xDisp, &event); - if (XFilterEvent(&event, None)) continue; - } - XUnlockDisplay(xDisp); - } - } - - renderer.Terminate(); - pthread_cancel(clientThread.native_handle()); - if (clientThread.joinable()) - clientThread.join(); - - return renderer.ReturnVal(); + return renderer.ReturnVal(); } diff --git a/visigen/VISIBuilder.cpp b/visigen/VISIBuilder.cpp index fd29f7b06..eeb04ada7 100644 --- a/visigen/VISIBuilder.cpp +++ b/visigen/VISIBuilder.cpp @@ -11,380 +11,318 @@ static logvisor::Module Log("VISIBuilder"); -VISIBuilder::PVSRenderCache::PVSRenderCache(VISIRenderer& renderer) -: m_renderer(renderer) -{ - m_cache.reserve(1000); -} +VISIBuilder::PVSRenderCache::PVSRenderCache(VISIRenderer& renderer) : m_renderer(renderer) { m_cache.reserve(1000); } static std::unique_ptr RGBABuf(new VISIRenderer::RGBA8[256 * 256 * 6]); -const VISIBuilder::Leaf& VISIBuilder::PVSRenderCache::GetLeaf(const zeus::CVector3f& vec) -{ - auto search = m_cache.find(vec); - if (search != m_cache.cend()) - { - //Log.report(logvisor::Info, "Cache hit"); - return *search->second; - } +const VISIBuilder::Leaf& VISIBuilder::PVSRenderCache::GetLeaf(const zeus::CVector3f& vec) { + auto search = m_cache.find(vec); + if (search != m_cache.cend()) { + // Log.report(logvisor::Info, "Cache hit"); + return *search->second; + } - //Log.report(logvisor::Info, "Rendering"); - bool needsTransparent = false; - m_renderer.RenderPVSOpaque(RGBABuf.get(), vec, needsTransparent); - std::unique_ptr leafOut = std::make_unique(); - for (unsigned i=0 ; i<768*512 ; ++i) - { - const VISIRenderer::RGBA8& pixel = RGBABuf[i]; - uint32_t id = (pixel.b << 16) | (pixel.g << 8) | pixel.r; - if (id != 0) - leafOut->setBit(id - 1); - } + // Log.report(logvisor::Info, "Rendering"); + bool needsTransparent = false; + m_renderer.RenderPVSOpaque(RGBABuf.get(), vec, needsTransparent); + std::unique_ptr leafOut = std::make_unique(); + for (unsigned i = 0; i < 768 * 512; ++i) { + const VISIRenderer::RGBA8& pixel = RGBABuf[i]; + uint32_t id = (pixel.b << 16) | (pixel.g << 8) | pixel.r; + if (id != 0) + leafOut->setBit(id - 1); + } - auto setBitLambda = [&](int idx) { leafOut->setBit(idx); }; - auto setLightLambda = [&](int idx, EPVSVisSetState state) - { - if (state != EPVSVisSetState::EndOfTree) - leafOut->setLightEnum(m_lightMetaBit + idx * 2, state); - }; - if (needsTransparent) - m_renderer.RenderPVSTransparent(setBitLambda, vec); - m_renderer.RenderPVSEntitiesAndLights(setBitLambda, setLightLambda, vec); + auto setBitLambda = [&](int idx) { leafOut->setBit(idx); }; + auto setLightLambda = [&](int idx, EPVSVisSetState state) { + if (state != EPVSVisSetState::EndOfTree) + leafOut->setLightEnum(m_lightMetaBit + idx * 2, state); + }; + if (needsTransparent) + m_renderer.RenderPVSTransparent(setBitLambda, vec); + m_renderer.RenderPVSEntitiesAndLights(setBitLambda, setLightLambda, vec); - return *m_cache.emplace(std::make_pair(vec, std::move(leafOut))).first->second; + return *m_cache.emplace(std::make_pair(vec, std::move(leafOut))).first->second; } -void VISIBuilder::Progress::report(int divisions) -{ - m_prog += 1.f / divisions; - //printf(" %g%% \r", m_prog * 100.f); - //fflush(stdout); - if (m_updatePercent) - m_updatePercent(m_prog); +void VISIBuilder::Progress::report(int divisions) { + m_prog += 1.f / divisions; + // printf(" %g%% \r", m_prog * 100.f); + // fflush(stdout); + if (m_updatePercent) + m_updatePercent(m_prog); } -void VISIBuilder::Node::buildChildren(int level, int divisions, const zeus::CAABox& curAabb, - PVSRenderCache& rc, Progress& prog, const std::function& terminate) -{ - if (terminate()) +void VISIBuilder::Node::buildChildren(int level, int divisions, const zeus::CAABox& curAabb, PVSRenderCache& rc, + Progress& prog, const std::function& terminate) { + if (terminate()) + return; + + // Recurse in while building node structure + if (level < VISI_MAX_LEVEL) { + // Heuristic split + int splits[3]; + splits[0] = (curAabb.max.x() - curAabb.min.x() >= VISI_MIN_LENGTH) ? 2 : 1; + splits[1] = (curAabb.max.y() - curAabb.min.y() >= VISI_MIN_LENGTH) ? 2 : 1; + splits[2] = (curAabb.max.z() - curAabb.min.z() >= VISI_MIN_LENGTH) ? 2 : 1; + + if (splits[0] == 2) + flags |= 0x1; + if (splits[1] == 2) + flags |= 0x2; + if (splits[2] == 2) + flags |= 0x4; + + int thisdiv = splits[0] * splits[1] * splits[2] * divisions; + + if (flags) { + childNodes.resize(8); + + // Inward subdivide + zeus::CAABox Z[2]; + if (flags & 0x4) + curAabb.splitZ(Z[0], Z[1]); + else + Z[0] = curAabb; + for (int i = 0; i < splits[2]; ++i) { + zeus::CAABox Y[2]; + if (flags & 0x2) + Z[i].splitY(Y[0], Y[1]); + else + Y[0] = Z[i]; + for (int j = 0; j < splits[1]; ++j) { + zeus::CAABox X[2]; + if (flags & 0x1) + Y[j].splitX(X[0], X[1]); + else + X[0] = Y[j]; + for (int k = 0; k < splits[0]; ++k) { + childNodes[i * 4 + j * 2 + k].buildChildren(level + 1, thisdiv, X[k], rc, prog, terminate); + } + } + } + + // Outward unsubdivide for like-leaves + for (int i = 0; i < 3; ++i) { + if (flags & 0x4 && childNodes[0] == childNodes[4] && (!(flags & 0x1) || childNodes[1] == childNodes[5]) && + (!(flags & 0x2) || childNodes[2] == childNodes[6]) && (!(flags & 0x3) || childNodes[3] == childNodes[7])) { + flags &= ~0x4; + // Log.report(logvisor::Info, "Unsub Z"); + continue; + } + if (flags & 0x2 && childNodes[0] == childNodes[2] && (!(flags & 0x1) || childNodes[1] == childNodes[3]) && + (!(flags & 0x4) || childNodes[4] == childNodes[6]) && (!(flags & 0x5) || childNodes[5] == childNodes[7])) { + flags &= ~0x2; + // Log.report(logvisor::Info, "Unsub Y"); + continue; + } + if (flags & 0x1 && childNodes[0] == childNodes[1] && (!(flags & 0x2) || childNodes[2] == childNodes[3]) && + (!(flags & 0x4) || childNodes[4] == childNodes[5]) && (!(flags & 0x6) || childNodes[6] == childNodes[7])) { + flags &= ~0x1; + // Log.report(logvisor::Info, "Unsub X"); + continue; + } + break; + } + + if (!flags) { + // This is now a leaf node + for (int i = 0; i < 8; ++i) + leaf |= childNodes[i].leaf; + // Log.report(logvisor::Info, "Leaf Promote"); return; - - // Recurse in while building node structure - if (level < VISI_MAX_LEVEL) - { - // Heuristic split - int splits[3]; - splits[0] = (curAabb.max.x() - curAabb.min.x() >= VISI_MIN_LENGTH) ? 2 : 1; - splits[1] = (curAabb.max.y() - curAabb.min.y() >= VISI_MIN_LENGTH) ? 2 : 1; - splits[2] = (curAabb.max.z() - curAabb.min.z() >= VISI_MIN_LENGTH) ? 2 : 1; - - if (splits[0] == 2) - flags |= 0x1; - if (splits[1] == 2) - flags |= 0x2; - if (splits[2] == 2) - flags |= 0x4; - - int thisdiv = splits[0] * splits[1] * splits[2] * divisions; - - if (flags) - { - childNodes.resize(8); - - // Inward subdivide - zeus::CAABox Z[2]; - if (flags & 0x4) - curAabb.splitZ(Z[0], Z[1]); - else - Z[0] = curAabb; - for (int i=0 ; i maxDelta) - maxDelta = delta; - childRelOffs[nodeSel] = delta; - childNodes[nodeSel].calculateSizesAndOffs(cur, leafSz); - } - - const int numChildren = NumChildTable[flags & 0x7]; - if (maxDelta > 0xffff) - { - cur += (numChildren - 1) * 3; - flags |= 0x40; - } - else if (maxDelta > 0xff) - { - cur += (numChildren - 1) * 2; - } - else - { - cur += numChildren - 1; - flags |= 0x20; + // Inward accumulate + const size_t startCur = cur; + size_t maxDelta = 0; + for (int i = 0; i < splits[2]; ++i) + for (int j = 0; j < splits[1]; ++j) + for (int k = 0; k < splits[0]; ++k) { + const size_t nodeSel = i * 4 + j * 2 + k; + const size_t delta = cur - startCur; + if (delta > maxDelta) + maxDelta = delta; + childRelOffs[nodeSel] = delta; + childNodes[nodeSel].calculateSizesAndOffs(cur, leafSz); } + + const int numChildren = NumChildTable[flags & 0x7]; + if (maxDelta > 0xffff) { + cur += (numChildren - 1) * 3; + flags |= 0x40; + } else if (maxDelta > 0xff) { + cur += (numChildren - 1) * 2; + } else { + cur += numChildren - 1; + flags |= 0x20; } + } else { + if (!leaf) + flags &= ~0x8; else - { - if (!leaf) - flags &= ~0x8; - else - cur += leafSz; - } + cur += leafSz; + } } -void VISIBuilder::Node::writeNodes(athena::io::MemoryWriter& w, size_t leafBytes) const -{ - w.writeUByte(flags); +void VISIBuilder::Node::writeNodes(athena::io::MemoryWriter& w, size_t leafBytes) const { + w.writeUByte(flags); - if (flags & 0x7) - { - int splits[3]; - splits[0] = (flags & 0x1) ? 2 : 1; - splits[1] = (flags & 0x2) ? 2 : 1; - splits[2] = (flags & 0x4) ? 2 : 1; + if (flags & 0x7) { + int splits[3]; + splits[0] = (flags & 0x1) ? 2 : 1; + splits[1] = (flags & 0x2) ? 2 : 1; + splits[2] = (flags & 0x4) ? 2 : 1; - // Write offsets - for (int i=0 ; i> 16) & 0xff); - w.writeUByte((offset >> 8) & 0xff); - w.writeUByte(offset & 0xff); - } - else if (flags & 0x20) - { - w.writeUByte(offset & 0xff); - } - else - { - w.writeUint16Big(offset); - } - } + // Write offsets + for (int i = 0; i < splits[2]; ++i) + for (int j = 0; j < splits[1]; ++j) + for (int k = 0; k < splits[0]; ++k) { + const size_t nodeSel = i * 4 + j * 2 + k; + if (nodeSel == 0) + continue; + const size_t offset = childRelOffs[nodeSel]; + if (flags & 0x40) { + w.writeUByte((offset >> 16) & 0xff); + w.writeUByte((offset >> 8) & 0xff); + w.writeUByte(offset & 0xff); + } else if (flags & 0x20) { + w.writeUByte(offset & 0xff); + } else { + w.writeUint16Big(offset); + } + } - // Inward iterate - for (int i=0 ; i VISIBuilder::build(const zeus::CAABox& fullAabb, - size_t modelCount, +std::vector VISIBuilder::build(const zeus::CAABox& fullAabb, size_t modelCount, const std::vector& entities, - const std::vector& lights, - size_t layer2LightCount, - FPercent updatePercent, - ProcessType parentPid) -{ - //Log.report(logvisor::Info, "Started!"); + const std::vector& lights, size_t layer2LightCount, + FPercent updatePercent, ProcessType parentPid) { + // Log.report(logvisor::Info, "Started!"); - size_t featureCount = modelCount + entities.size(); - renderCache.m_lightMetaBit = featureCount; + size_t featureCount = modelCount + entities.size(); + renderCache.m_lightMetaBit = featureCount; - Progress prog(updatePercent); + Progress prog(updatePercent); #ifndef _WIN32 - parentPid = getppid(); - auto terminate = [this, parentPid]() - { - return renderCache.m_renderer.m_terminate || (parentPid ? kill(parentPid, 0) : false); - }; + parentPid = getppid(); + auto terminate = [this, parentPid]() { + return renderCache.m_renderer.m_terminate || (parentPid ? kill(parentPid, 0) : false); + }; #else - auto terminate = [this, parentPid]() - { - DWORD exitCode = 0; - if (!GetExitCodeProcess(parentPid, &exitCode)) - return renderCache.m_renderer.m_terminate; - return renderCache.m_renderer.m_terminate || (parentPid ? exitCode != STILL_ACTIVE : false); - }; + auto terminate = [this, parentPid]() { + DWORD exitCode = 0; + if (!GetExitCodeProcess(parentPid, &exitCode)) + return renderCache.m_renderer.m_terminate; + return renderCache.m_renderer.m_terminate || (parentPid ? exitCode != STILL_ACTIVE : false); + }; #endif - rootNode.buildChildren(0, 1, fullAabb, renderCache, prog, terminate); - if (terminate()) - return {}; + rootNode.buildChildren(0, 1, fullAabb, renderCache, prog, terminate); + if (terminate()) + return {}; - // Lights cache their CPVSVisSet result enum as 2 bits - size_t leafBitsCount = featureCount + lights.size() * 2; - size_t leafBytesCount = ROUND_UP_8(leafBitsCount) / 8; + // Lights cache their CPVSVisSet result enum as 2 bits + size_t leafBitsCount = featureCount + lights.size() * 2; + size_t leafBytesCount = ROUND_UP_8(leafBitsCount) / 8; - // Calculate octree size and store relative offsets - size_t octreeSz = 0; - rootNode.calculateSizesAndOffs(octreeSz, leafBytesCount); + // Calculate octree size and store relative offsets + size_t octreeSz = 0; + rootNode.calculateSizesAndOffs(octreeSz, leafBytesCount); - size_t visiSz = 34 + entities.size() * 4 + lights.size() * leafBytesCount + 36 + octreeSz; - size_t roundedVisiSz = ROUND_UP_32(visiSz); + size_t visiSz = 34 + entities.size() * 4 + lights.size() * leafBytesCount + 36 + octreeSz; + size_t roundedVisiSz = ROUND_UP_32(visiSz); - std::vector dataOut(roundedVisiSz, 0); - athena::io::MemoryWriter w(dataOut.data(), roundedVisiSz); - w.writeUint32Big('VISI'); - w.writeUint32Big(2); - w.writeBool(true); - w.writeBool(true); - w.writeUint32Big(featureCount); - w.writeUint32Big(lights.size()); - w.writeUint32Big(layer2LightCount); - w.writeUint32Big(entities.size()); - w.writeUint32Big(leafBytesCount); - w.writeUint32Big(lights.size()); + std::vector dataOut(roundedVisiSz, 0); + athena::io::MemoryWriter w(dataOut.data(), roundedVisiSz); + w.writeUint32Big('VISI'); + w.writeUint32Big(2); + w.writeBool(true); + w.writeBool(true); + w.writeUint32Big(featureCount); + w.writeUint32Big(lights.size()); + w.writeUint32Big(layer2LightCount); + w.writeUint32Big(entities.size()); + w.writeUint32Big(leafBytesCount); + w.writeUint32Big(lights.size()); - for (const VISIRenderer::Entity& e : entities) - { - w.writeUint32Big(e.entityId); - } + for (const VISIRenderer::Entity& e : entities) { + w.writeUint32Big(e.entityId); + } - for (const VISIRenderer::Light& l : lights) - { - const VISIBuilder::Leaf& leaf = renderCache.GetLeaf(l.point); - leaf.write(w, leafBytesCount); - } + for (const VISIRenderer::Light& l : lights) { + const VISIBuilder::Leaf& leaf = renderCache.GetLeaf(l.point); + leaf.write(w, leafBytesCount); + } - w.writeVec3fBig(fullAabb.min); - w.writeVec3fBig(fullAabb.max); - w.writeUint32Big(featureCount + lights.size()); - w.writeUint32Big(lights.size()); - w.writeUint32Big(octreeSz); - rootNode.writeNodes(w, leafBytesCount); + w.writeVec3fBig(fullAabb.min); + w.writeVec3fBig(fullAabb.max); + w.writeUint32Big(featureCount + lights.size()); + w.writeUint32Big(lights.size()); + w.writeUint32Big(octreeSz); + rootNode.writeNodes(w, leafBytesCount); - w.seekAlign32(); + w.seekAlign32(); - //Log.report(logvisor::Info, "Finished!"); - return dataOut; + // Log.report(logvisor::Info, "Finished!"); + return dataOut; } diff --git a/visigen/VISIBuilder.hpp b/visigen/VISIBuilder.hpp index 0dc7156dd..982f1c278 100644 --- a/visigen/VISIBuilder.hpp +++ b/visigen/VISIBuilder.hpp @@ -12,125 +12,106 @@ using ProcessType = HANDLE; using ProcessType = pid_t; #endif -namespace std -{ -template <> struct hash -{ - size_t operator()(const zeus::CVector3f& val) const noexcept - { - zeus::simd_floats f(val.mSimd); - return XXH64(&f[0], 12, 0); +namespace std { +template <> +struct hash { + size_t operator()(const zeus::CVector3f& val) const noexcept { + zeus::simd_floats f(val.mSimd); + return XXH64(&f[0], 12, 0); + } +}; +} // namespace std + +struct VISIBuilder { + struct Leaf { + std::vector bits; + void setBit(size_t bit) { + size_t byte = bit / 8; + if (byte >= bits.size()) + bits.resize(byte + 1); + bits[byte] |= 1 << (bit & 0x7); } + void setLightEnum(size_t bit, EPVSVisSetState state) { + size_t byte0 = bit / 8; + size_t byte1 = (bit + 1) / 8; + if (byte1 >= bits.size()) + bits.resize(byte1 + 1); + + if (byte0 == byte1) { + bits[byte0] |= int(state) << (bit & 0x7); + } else { + bits[byte0] |= (int(state) << 7) & 0x1; + bits[byte1] |= (int(state) >> 1) & 0x1; + } + } + bool operator==(const Leaf& other) const { + if (bits.size() != other.bits.size()) + return false; + if (memcmp(bits.data(), other.bits.data(), bits.size())) + return false; + return true; + } + Leaf& operator|=(const Leaf& other) { + if (bits.size() < other.bits.size()) + bits.resize(other.bits.size()); + for (int i = 0; i < other.bits.size(); ++i) + bits[i] |= other.bits[i]; + return *this; + } + operator bool() const { return bits.size() != 0; } + + void write(athena::io::MemoryWriter& w, size_t leafBytes) const { + for (size_t i = 0; i < leafBytes; ++i) { + if (i < bits.size()) + w.writeUByte(bits[i]); + else + w.writeUByte(0); + } + } + }; + + class PVSRenderCache { + friend struct VISIBuilder; + VISIRenderer& m_renderer; + std::unordered_map> m_cache; + size_t m_lightMetaBit; + + public: + PVSRenderCache(VISIRenderer& renderer); + const Leaf& GetLeaf(const zeus::CVector3f& vec); + } renderCache; + + class Progress { + float m_prog = 0.f; + FPercent m_updatePercent; + + public: + void report(int divisions); + Progress(FPercent updatePercent) : m_updatePercent(updatePercent) {} + }; + + struct Node { + std::vector childNodes; + size_t childRelOffs[8] = {}; + Leaf leaf; + uint8_t flags = 0; + + void buildChildren(int level, int divisions, const zeus::CAABox& curAabb, PVSRenderCache& rc, Progress& prog, + const std::function& terminate); + void calculateSizesAndOffs(size_t& cur, size_t leafSz); + void writeNodes(athena::io::MemoryWriter& w, size_t leafBytes) const; + + bool operator==(const Node& other) const { + if ((flags & 0x7) || (other.flags & 0x7)) + return false; + return leaf == other.leaf; + } + } rootNode; + + std::vector build(const zeus::CAABox& fullAabb, size_t modelCount, + const std::vector& entities, + const std::vector& lights, size_t layer2LightCount, + FPercent updatePercent, ProcessType parentPid); + + VISIBuilder(VISIRenderer& renderer) : renderCache(renderer) {} }; -} - -struct VISIBuilder -{ - struct Leaf - { - std::vector bits; - void setBit(size_t bit) - { - size_t byte = bit / 8; - if (byte >= bits.size()) - bits.resize(byte + 1); - bits[byte] |= 1 << (bit & 0x7); - } - void setLightEnum(size_t bit, EPVSVisSetState state) - { - size_t byte0 = bit / 8; - size_t byte1 = (bit + 1) / 8; - if (byte1 >= bits.size()) - bits.resize(byte1 + 1); - - if (byte0 == byte1) - { - bits[byte0] |= int(state) << (bit & 0x7); - } - else - { - bits[byte0] |= (int(state) << 7) & 0x1; - bits[byte1] |= (int(state) >> 1) & 0x1; - } - } - bool operator==(const Leaf& other) const - { - if (bits.size() != other.bits.size()) - return false; - if (memcmp(bits.data(), other.bits.data(), bits.size())) - return false; - return true; - } - Leaf& operator|=(const Leaf& other) - { - if (bits.size() < other.bits.size()) - bits.resize(other.bits.size()); - for (int i=0 ; i> m_cache; - size_t m_lightMetaBit; - public: - PVSRenderCache(VISIRenderer& renderer); - const Leaf& GetLeaf(const zeus::CVector3f& vec); - } renderCache; - - class Progress - { - float m_prog = 0.f; - FPercent m_updatePercent; - public: - void report(int divisions); - Progress(FPercent updatePercent) : m_updatePercent(updatePercent) {} - }; - - struct Node - { - std::vector childNodes; - size_t childRelOffs[8] = {}; - Leaf leaf; - uint8_t flags = 0; - - void buildChildren(int level, int divisions, const zeus::CAABox& curAabb, - PVSRenderCache& rc, Progress& prog, const std::function& terminate); - void calculateSizesAndOffs(size_t& cur, size_t leafSz); - void writeNodes(athena::io::MemoryWriter& w, size_t leafBytes) const; - - bool operator==(const Node& other) const - { - if ((flags & 0x7) || (other.flags & 0x7)) - return false; - return leaf == other.leaf; - } - } rootNode; - - std::vector build(const zeus::CAABox& fullAabb, - size_t modelCount, - const std::vector& entities, - const std::vector& lights, - size_t layer2LightCount, - FPercent updatePercent, - ProcessType parentPid); - - VISIBuilder(VISIRenderer& renderer) : renderCache(renderer) {} -}; - diff --git a/visigen/VISIRenderer.cpp b/visigen/VISIRenderer.cpp index b45604e63..3b0f20c4b 100644 --- a/visigen/VISIRenderer.cpp +++ b/visigen/VISIRenderer.cpp @@ -8,601 +8,518 @@ static logvisor::Module Log("visigen"); static const char* VS = -"#version 330\n" -"layout(location=0) in vec4 posIn;\n" -"layout(location=1) in vec4 colorIn;\n" -"\n" -"uniform UniformBlock\n" -"{\n" -" mat4 xf;\n" -"};\n" -"\n" -"struct VertToFrag\n" -"{\n" -" vec4 color;\n" -"};\n" -"\n" -"out VertToFrag vtf;\n" -"void main()\n" -"{\n" -" vtf.color = colorIn;\n" -" gl_Position = xf * vec4(posIn.xyz, 1.0);\n" -"}\n"; + "#version 330\n" + "layout(location=0) in vec4 posIn;\n" + "layout(location=1) in vec4 colorIn;\n" + "\n" + "uniform UniformBlock\n" + "{\n" + " mat4 xf;\n" + "};\n" + "\n" + "struct VertToFrag\n" + "{\n" + " vec4 color;\n" + "};\n" + "\n" + "out VertToFrag vtf;\n" + "void main()\n" + "{\n" + " vtf.color = colorIn;\n" + " gl_Position = xf * vec4(posIn.xyz, 1.0);\n" + "}\n"; static const char* FS = -"#version 330\n" -"struct VertToFrag\n" -"{\n" -" vec4 color;\n" -"};\n" -"\n" -"in VertToFrag vtf;\n" -"layout(location=0) out vec4 colorOut;\n" -"void main()\n" -"{\n" -" colorOut = vtf.color;\n" -"}\n"; + "#version 330\n" + "struct VertToFrag\n" + "{\n" + " vec4 color;\n" + "};\n" + "\n" + "in VertToFrag vtf;\n" + "layout(location=0) out vec4 colorOut;\n" + "void main()\n" + "{\n" + " colorOut = vtf.color;\n" + "}\n"; -static const uint32_t AABBIdxs[20] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 7, 3, 5, 5, 0, 0, 2, 6, 4 -}; +static const uint32_t AABBIdxs[20] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 7, 3, 5, 5, 0, 0, 2, 6, 4}; -bool VISIRenderer::SetupShaders() -{ - m_vtxShader = glCreateShader(GL_VERTEX_SHADER); - m_fragShader = glCreateShader(GL_FRAGMENT_SHADER); - m_program = glCreateProgram(); +bool VISIRenderer::SetupShaders() { + m_vtxShader = glCreateShader(GL_VERTEX_SHADER); + m_fragShader = glCreateShader(GL_FRAGMENT_SHADER); + m_program = glCreateProgram(); - glShaderSource(m_vtxShader, 1, &VS, nullptr); - glCompileShader(m_vtxShader); - GLint status; - glGetShaderiv(m_vtxShader, GL_COMPILE_STATUS, &status); - if (status != GL_TRUE) - { - GLint logLen; - glGetShaderiv(m_vtxShader, GL_INFO_LOG_LENGTH, &logLen); - char* log = (char*)malloc(logLen); - glGetShaderInfoLog(m_vtxShader, logLen, nullptr, log); - Log.report(logvisor::Error, "unable to compile vert source\n%s\n%s\n", log, VS); - free(log); - return false; - } + glShaderSource(m_vtxShader, 1, &VS, nullptr); + glCompileShader(m_vtxShader); + GLint status; + glGetShaderiv(m_vtxShader, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) { + GLint logLen; + glGetShaderiv(m_vtxShader, GL_INFO_LOG_LENGTH, &logLen); + char* log = (char*)malloc(logLen); + glGetShaderInfoLog(m_vtxShader, logLen, nullptr, log); + Log.report(logvisor::Error, "unable to compile vert source\n%s\n%s\n", log, VS); + free(log); + return false; + } - glShaderSource(m_fragShader, 1, &FS, nullptr); - glCompileShader(m_fragShader); - glGetShaderiv(m_fragShader, GL_COMPILE_STATUS, &status); - if (status != GL_TRUE) - { - GLint logLen; - glGetShaderiv(m_fragShader, GL_INFO_LOG_LENGTH, &logLen); - char* log = (char*)malloc(logLen); - glGetShaderInfoLog(m_fragShader, logLen, nullptr, log); - Log.report(logvisor::Error, "unable to compile frag source\n%s\n%s\n", log, FS); - free(log); - return false; - } + glShaderSource(m_fragShader, 1, &FS, nullptr); + glCompileShader(m_fragShader); + glGetShaderiv(m_fragShader, GL_COMPILE_STATUS, &status); + if (status != GL_TRUE) { + GLint logLen; + glGetShaderiv(m_fragShader, GL_INFO_LOG_LENGTH, &logLen); + char* log = (char*)malloc(logLen); + glGetShaderInfoLog(m_fragShader, logLen, nullptr, log); + Log.report(logvisor::Error, "unable to compile frag source\n%s\n%s\n", log, FS); + free(log); + return false; + } - glAttachShader(m_program, m_vtxShader); - glAttachShader(m_program, m_fragShader); + glAttachShader(m_program, m_vtxShader); + glAttachShader(m_program, m_fragShader); - glLinkProgram(m_program); - glGetProgramiv(m_program, GL_LINK_STATUS, &status); - if (status != GL_TRUE) - { - GLint logLen; - glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &logLen); - char* log = (char*)malloc(logLen); - glGetProgramInfoLog(m_program, logLen, nullptr, log); - Log.report(logvisor::Error, "unable to link shader program\n%s\n", log); - free(log); - return false; - } + glLinkProgram(m_program); + glGetProgramiv(m_program, GL_LINK_STATUS, &status); + if (status != GL_TRUE) { + GLint logLen; + glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &logLen); + char* log = (char*)malloc(logLen); + glGetProgramInfoLog(m_program, logLen, nullptr, log); + Log.report(logvisor::Error, "unable to link shader program\n%s\n", log); + free(log); + return false; + } - glUseProgram(m_program); - m_uniLoc = glGetUniformBlockIndex(m_program, "UniformBlock"); + glUseProgram(m_program); + m_uniLoc = glGetUniformBlockIndex(m_program, "UniformBlock"); - glGenBuffers(1, &m_uniformBufferGL); - glBindBuffer(GL_UNIFORM_BUFFER, m_uniformBufferGL); - glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformBuffer), nullptr, GL_DYNAMIC_DRAW); + glGenBuffers(1, &m_uniformBufferGL); + glBindBuffer(GL_UNIFORM_BUFFER, m_uniformBufferGL); + glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformBuffer), nullptr, GL_DYNAMIC_DRAW); + + glGenBuffers(1, &m_aabbIBO); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_aabbIBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 20 * 4, AABBIdxs, GL_STATIC_DRAW); + + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(0xffffffff); + + return true; +} + +std::vector VISIRenderer::AABBToVerts(const zeus::CAABox& aabb, const zeus::CColor& color) { + std::vector verts; + verts.resize(8); + + for (int i = 0; i < 8; ++i) + verts[i].color = color; + + verts[0].pos = aabb.min; + verts[1].pos = {aabb.max.x(), aabb.min.y(), aabb.min.z()}; + verts[2].pos = {aabb.min.x(), aabb.min.y(), aabb.max.z()}; + verts[3].pos = {aabb.max.x(), aabb.min.y(), aabb.max.z()}; + verts[4].pos = {aabb.min.x(), aabb.max.y(), aabb.max.z()}; + verts[5].pos = aabb.max; + verts[6].pos = {aabb.min.x(), aabb.max.y(), aabb.min.z()}; + verts[7].pos = {aabb.max.x(), aabb.max.y(), aabb.min.z()}; + + return verts; +} + +static zeus::CColor ColorForIndex(int i) { + i += 1; + return zeus::CColor((i & 0xff) / 255.f, ((i >> 8) & 0xff) / 255.f, ((i >> 16) & 0xff) / 255.f, 1.f); +} + +bool VISIRenderer::SetupVertexBuffersAndFormats() { + for (Model& model : m_models) { + glGenVertexArrays(1, &model.vao); + glGenBuffers(1, &model.vbo); + glGenBuffers(1, &model.ibo); + + glBindVertexArray(model.vao); + + glBindBuffer(GL_ARRAY_BUFFER, model.vbo); + glBufferData(GL_ARRAY_BUFFER, model.verts.size() * sizeof(Model::Vert), model.verts.data(), GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), 0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), (void*)16); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.ibo); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, model.idxs.size() * 4, model.idxs.data(), GL_STATIC_DRAW); + } + + int idx = m_models.size(); + for (Entity& ent : m_entities) { + glGenVertexArrays(1, &ent.vao); + glGenBuffers(1, &ent.vbo); + + glBindVertexArray(ent.vao); + + auto verts = AABBToVerts(ent.aabb, ColorForIndex(idx++)); + glBindBuffer(GL_ARRAY_BUFFER, ent.vbo); + glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(Model::Vert), verts.data(), GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), 0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), (void*)16); - glGenBuffers(1, &m_aabbIBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_aabbIBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, 20 * 4, AABBIdxs, GL_STATIC_DRAW); + } - glEnable(GL_PRIMITIVE_RESTART); - glPrimitiveRestartIndex(0xffffffff); + for (Light& light : m_lights) { + glGenVertexArrays(1, &light.vao); + glGenBuffers(1, &light.vbo); - return true; -} + glBindVertexArray(light.vao); -std::vector VISIRenderer::AABBToVerts(const zeus::CAABox& aabb, - const zeus::CColor& color) -{ - std::vector verts; - verts.resize(8); + Model::Vert vert; + vert.pos = light.point; + vert.color = ColorForIndex(idx++); + glBindBuffer(GL_ARRAY_BUFFER, light.vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(Model::Vert), &vert, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), 0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), (void*)16); + } - for (int i=0 ; i<8 ; ++i) - verts[i].color = color; + m_queryCount = m_models.size() + m_entities.size() + m_lights.size(); + m_queries.reset(new GLuint[m_queryCount]); + m_queryBools.reset(new bool[m_queryCount]); + glGenQueries(GLsizei(m_queryCount), m_queries.get()); - verts[0].pos = aabb.min; - verts[1].pos = {aabb.max.x(), aabb.min.y(), aabb.min.z()}; - verts[2].pos = {aabb.min.x(), aabb.min.y(), aabb.max.z()}; - verts[3].pos = {aabb.max.x(), aabb.min.y(), aabb.max.z()}; - verts[4].pos = {aabb.min.x(), aabb.max.y(), aabb.max.z()}; - verts[5].pos = aabb.max; - verts[6].pos = {aabb.min.x(), aabb.max.y(), aabb.min.z()}; - verts[7].pos = {aabb.max.x(), aabb.max.y(), aabb.min.z()}; - - return verts; -} - -static zeus::CColor ColorForIndex(int i) -{ - i += 1; - return zeus::CColor((i & 0xff) / 255.f, - ((i >> 8) & 0xff) / 255.f, - ((i >> 16) & 0xff) / 255.f, - 1.f); -} - -bool VISIRenderer::SetupVertexBuffersAndFormats() -{ - for (Model& model : m_models) - { - glGenVertexArrays(1, &model.vao); - glGenBuffers(1, &model.vbo); - glGenBuffers(1, &model.ibo); - - glBindVertexArray(model.vao); - - glBindBuffer(GL_ARRAY_BUFFER, model.vbo); - glBufferData(GL_ARRAY_BUFFER, model.verts.size() * sizeof(Model::Vert), model.verts.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), 0); - glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), (void*)16); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.ibo); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, model.idxs.size() * 4, model.idxs.data(), GL_STATIC_DRAW); - } - - int idx = m_models.size(); - for (Entity& ent : m_entities) - { - glGenVertexArrays(1, &ent.vao); - glGenBuffers(1, &ent.vbo); - - glBindVertexArray(ent.vao); - - auto verts = AABBToVerts(ent.aabb, ColorForIndex(idx++)); - glBindBuffer(GL_ARRAY_BUFFER, ent.vbo); - glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(Model::Vert), verts.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), 0); - glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), (void*)16); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_aabbIBO); - } - - for (Light& light : m_lights) - { - glGenVertexArrays(1, &light.vao); - glGenBuffers(1, &light.vbo); - - glBindVertexArray(light.vao); - - Model::Vert vert; - vert.pos = light.point; - vert.color = ColorForIndex(idx++); - glBindBuffer(GL_ARRAY_BUFFER, light.vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(Model::Vert), &vert, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), 0); - glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), (void*)16); - } - - m_queryCount = m_models.size() + m_entities.size() + m_lights.size(); - m_queries.reset(new GLuint[m_queryCount]); - m_queryBools.reset(new bool[m_queryCount]); - glGenQueries(GLsizei(m_queryCount), m_queries.get()); - - return true; + return true; } static zeus::CMatrix4f g_Proj; -static void CalculateProjMatrix() -{ - float znear = 0.2f; - float zfar = 1000.f; - float tfov = std::tan(zeus::degToRad(90.f * 0.5f)); - float top = znear * tfov; - float bottom = -top; - float right = znear * tfov; - float left = -right; +static void CalculateProjMatrix() { + float znear = 0.2f; + float zfar = 1000.f; + float tfov = std::tan(zeus::degToRad(90.f * 0.5f)); + float top = znear * tfov; + float bottom = -top; + float right = znear * tfov; + float left = -right; - float rml = right - left; - float rpl = right + left; - float tmb = top - bottom; - float tpb = top + bottom; - float fpn = zfar + znear; - float fmn = zfar - znear; + float rml = right - left; + float rpl = right + left; + float tmb = top - bottom; + float tpb = top + bottom; + float fpn = zfar + znear; + float fmn = zfar - znear; - g_Proj = zeus::CMatrix4f(2.f * znear / rml, 0.f, rpl / rml, 0.f, - 0.f, 2.f * znear / tmb, tpb / tmb, 0.f, - 0.f, 0.f, -fpn / fmn, -2.f * zfar * znear / fmn, - 0.f, 0.f, -1.f, 0.f); + g_Proj = zeus::CMatrix4f(2.f * znear / rml, 0.f, rpl / rml, 0.f, 0.f, 2.f * znear / tmb, tpb / tmb, 0.f, 0.f, 0.f, + -fpn / fmn, -2.f * zfar * znear / fmn, 0.f, 0.f, -1.f, 0.f); } -static const zeus::CMatrix4f LookMATs[] = -{ - { // Forward - 1.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, -1.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }, - { // Backward - -1.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }, - { // Up - 1.f, 0.f, 0.f, 0.f, - 0.f, -1.f, 0.f, 0.f, - 0.f, 0.f, -1.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }, - { // Down - 1.f, 0.f, 0.f, 0.f, - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }, - { // Left - 0.f, 1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - 1.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }, - { // Right - 0.f, -1.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, - -1.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, 1.f - }, +static const zeus::CMatrix4f LookMATs[] = { + {// Forward + 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f}, + {// Backward + -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f}, + {// Up + 1.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 1.f}, + {// Down + 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f}, + {// Left + 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f}, + {// Right + 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f}, }; -void VISIRenderer::RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bool& needTransparent) -{ - glViewport(0, 0, 768, 512); - glEnable(GL_CULL_FACE); - glDepthMask(GL_TRUE); - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); - glClearColor(0.f, 0.f, 0.f, 1.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +void VISIRenderer::RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bool& needTransparent) { + glViewport(0, 0, 768, 512); + glEnable(GL_CULL_FACE); + glDepthMask(GL_TRUE); + glDepthFunc(GL_LEQUAL); + glEnable(GL_DEPTH_TEST); + glClearColor(0.f, 0.f, 0.f, 1.f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - for (int j=0 ; j<6 ; ++j) - { - GLint x = (j % 3) * 256; - GLint y = (j / 3) * 256; - glViewport(x, y, 256, 256); + for (int j = 0; j < 6; ++j) { + GLint x = (j % 3) * 256; + GLint y = (j / 3) * 256; + glViewport(x, y, 256, 256); - zeus::CMatrix4f mv = LookMATs[j] * zeus::CTransform::Translate(-pos).toMatrix4f(); - m_uniformBuffer.m_xf = g_Proj * mv; - glBindBuffer(GL_UNIFORM_BUFFER, m_uniformBufferGL); - glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformBuffer), &m_uniformBuffer, GL_DYNAMIC_DRAW); + zeus::CMatrix4f mv = LookMATs[j] * zeus::CTransform::Translate(-pos).toMatrix4f(); + m_uniformBuffer.m_xf = g_Proj * mv; + glBindBuffer(GL_UNIFORM_BUFFER, m_uniformBufferGL); + glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformBuffer), &m_uniformBuffer, GL_DYNAMIC_DRAW); - glUniformBlockBinding(m_program, m_uniLoc, 0); - glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_uniformBufferGL, 0, sizeof(UniformBuffer)); + glUniformBlockBinding(m_program, m_uniLoc, 0); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_uniformBufferGL, 0, sizeof(UniformBuffer)); - zeus::CFrustum frustum; - frustum.updatePlanes(mv, g_Proj); + zeus::CFrustum frustum; + frustum.updatePlanes(mv, g_Proj); - // Draw frontfaces - glCullFace(GL_BACK); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + // Draw frontfaces + glCullFace(GL_BACK); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - for (const Model& model : m_models) - { - if (!frustum.aabbFrustumTest(model.aabb)) - continue; - glBindVertexArray(model.vao); - for (const Model::Surface& surf : model.surfaces) - { - // Non-transparents first - if (!surf.transparent) - glDrawElements(model.topology, surf.count, GL_UNSIGNED_INT, - reinterpret_cast(uintptr_t(surf.first * 4))); - } - } + for (const Model& model : m_models) { + if (!frustum.aabbFrustumTest(model.aabb)) + continue; + glBindVertexArray(model.vao); + for (const Model::Surface& surf : model.surfaces) { + // Non-transparents first + if (!surf.transparent) + glDrawElements(model.topology, surf.count, GL_UNSIGNED_INT, + reinterpret_cast(uintptr_t(surf.first * 4))); + } } + } - //m_swapFunc(); - glFinish(); - glReadPixels(0, 0, 768, 512, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)bufOut); + // m_swapFunc(); + glFinish(); + glReadPixels(0, 0, 768, 512, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)bufOut); } -void VISIRenderer::RenderPVSTransparent(const std::function& passFunc, const zeus::CVector3f& pos) -{ - glDepthMask(GL_FALSE); +void VISIRenderer::RenderPVSTransparent(const std::function& passFunc, const zeus::CVector3f& pos) { + glDepthMask(GL_FALSE); - for (int j=0 ; j<6 ; ++j) - { - GLint x = (j % 3) * 256; - GLint y = (j / 3) * 256; - glViewport(x, y, 256, 256); + for (int j = 0; j < 6; ++j) { + GLint x = (j % 3) * 256; + GLint y = (j / 3) * 256; + glViewport(x, y, 256, 256); - zeus::CMatrix4f mv = LookMATs[j] * zeus::CTransform::Translate(-pos).toMatrix4f(); - m_uniformBuffer.m_xf = g_Proj * mv; - glBindBuffer(GL_UNIFORM_BUFFER, m_uniformBufferGL); - glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformBuffer), &m_uniformBuffer, GL_DYNAMIC_DRAW); + zeus::CMatrix4f mv = LookMATs[j] * zeus::CTransform::Translate(-pos).toMatrix4f(); + m_uniformBuffer.m_xf = g_Proj * mv; + glBindBuffer(GL_UNIFORM_BUFFER, m_uniformBufferGL); + glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformBuffer), &m_uniformBuffer, GL_DYNAMIC_DRAW); - glUniformBlockBinding(m_program, m_uniLoc, 0); - glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_uniformBufferGL, 0, sizeof(UniformBuffer)); + glUniformBlockBinding(m_program, m_uniLoc, 0); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_uniformBufferGL, 0, sizeof(UniformBuffer)); - zeus::CFrustum frustum; - frustum.updatePlanes(mv, g_Proj); + zeus::CFrustum frustum; + frustum.updatePlanes(mv, g_Proj); - memset(m_queryBools.get(), 0, m_queryCount); + memset(m_queryBools.get(), 0, m_queryCount); - int idx = 0; - for (const Model& model : m_models) - { - if (!frustum.aabbFrustumTest(model.aabb)) - { - ++idx; - continue; - } - glBindVertexArray(model.vao); - glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, m_queries[idx]); - m_queryBools[idx] = true; - for (const Model::Surface& surf : model.surfaces) - { - // transparents - if (surf.transparent) - glDrawElements(model.topology, surf.count, GL_UNSIGNED_INT, - reinterpret_cast(uintptr_t(surf.first * 4))); - } - glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE); - ++idx; - } - - for (int i=0 ; i(uintptr_t(surf.first * 4))); + } + glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE); + ++idx; } + + for (int i = 0; i < idx; ++i) { + if (m_queryBools[i]) { + GLint res; + glGetQueryObjectiv(m_queries[i], GL_QUERY_RESULT, &res); + if (res) + passFunc(i); + } + } + } } void VISIRenderer::RenderPVSEntitiesAndLights(const std::function& passFunc, const std::function& lightPassFunc, - const zeus::CVector3f& pos) -{ - glDepthMask(GL_FALSE); + const zeus::CVector3f& pos) { + glDepthMask(GL_FALSE); - for (int j=0 ; j<6 ; ++j) - { - GLint x = (j % 3) * 256; - GLint y = (j / 3) * 256; - glViewport(x, y, 256, 256); + for (int j = 0; j < 6; ++j) { + GLint x = (j % 3) * 256; + GLint y = (j / 3) * 256; + glViewport(x, y, 256, 256); - zeus::CMatrix4f mv = LookMATs[j] * zeus::CTransform::Translate(-pos).toMatrix4f(); - m_uniformBuffer.m_xf = g_Proj * mv; - glBindBuffer(GL_UNIFORM_BUFFER, m_uniformBufferGL); - glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformBuffer), &m_uniformBuffer, GL_DYNAMIC_DRAW); + zeus::CMatrix4f mv = LookMATs[j] * zeus::CTransform::Translate(-pos).toMatrix4f(); + m_uniformBuffer.m_xf = g_Proj * mv; + glBindBuffer(GL_UNIFORM_BUFFER, m_uniformBufferGL); + glBufferData(GL_UNIFORM_BUFFER, sizeof(UniformBuffer), &m_uniformBuffer, GL_DYNAMIC_DRAW); - glUniformBlockBinding(m_program, m_uniLoc, 0); - glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_uniformBufferGL, 0, sizeof(UniformBuffer)); + glUniformBlockBinding(m_program, m_uniLoc, 0); + glBindBufferRange(GL_UNIFORM_BUFFER, 0, m_uniformBufferGL, 0, sizeof(UniformBuffer)); - zeus::CFrustum frustum; - frustum.updatePlanes(mv, g_Proj); + zeus::CFrustum frustum; + frustum.updatePlanes(mv, g_Proj); - memset(m_queryBools.get(), 0, m_queryCount); + memset(m_queryBools.get(), 0, m_queryCount); - int idx = m_models.size(); - for (const Entity& ent : m_entities) - { - if (!frustum.aabbFrustumTest(ent.aabb)) - { - ++idx; - continue; - } - glBindVertexArray(ent.vao); - m_queryBools[idx] = true; - glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, m_queries[idx]); - glDrawElements(GL_TRIANGLE_STRIP, 20, GL_UNSIGNED_INT, 0); - glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE); - ++idx; - } - - for (const Light& light : m_lights) - { - if (!frustum.pointFrustumTest(light.point)) - { - ++idx; - continue; - } - glBindVertexArray(light.vao); - m_queryBools[idx] = true; - glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, m_queries[idx]); - glDrawArrays(GL_POINTS, 0, 1); - glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE); - ++idx; - } - - idx = m_models.size(); - for (const Entity& ent : m_entities) - { - (void)ent; - if (m_queryBools[idx]) - { - GLint res; - glGetQueryObjectiv(m_queries[idx], GL_QUERY_RESULT, &res); - if (res) - passFunc(idx); - } - ++idx; - } - - int lightIdx = 0; - for (const Light& light : m_lights) - { - if (m_queryBools[idx]) - { - GLint res; - glGetQueryObjectiv(m_queries[idx], GL_QUERY_RESULT, &res); - EPVSVisSetState state = m_totalAABB.pointInside(light.point) ? - EPVSVisSetState::EndOfTree : EPVSVisSetState::OutOfBounds; - if (res && state == EPVSVisSetState::EndOfTree) - state = EPVSVisSetState::NodeFound; - lightPassFunc(lightIdx, state); - } - ++lightIdx; - ++idx; - } + int idx = m_models.size(); + for (const Entity& ent : m_entities) { + if (!frustum.aabbFrustumTest(ent.aabb)) { + ++idx; + continue; + } + glBindVertexArray(ent.vao); + m_queryBools[idx] = true; + glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, m_queries[idx]); + glDrawElements(GL_TRIANGLE_STRIP, 20, GL_UNSIGNED_INT, 0); + glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE); + ++idx; } + + for (const Light& light : m_lights) { + if (!frustum.pointFrustumTest(light.point)) { + ++idx; + continue; + } + glBindVertexArray(light.vao); + m_queryBools[idx] = true; + glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, m_queries[idx]); + glDrawArrays(GL_POINTS, 0, 1); + glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE); + ++idx; + } + + idx = m_models.size(); + for (const Entity& ent : m_entities) { + (void)ent; + if (m_queryBools[idx]) { + GLint res; + glGetQueryObjectiv(m_queries[idx], GL_QUERY_RESULT, &res); + if (res) + passFunc(idx); + } + ++idx; + } + + int lightIdx = 0; + for (const Light& light : m_lights) { + if (m_queryBools[idx]) { + GLint res; + glGetQueryObjectiv(m_queries[idx], GL_QUERY_RESULT, &res); + EPVSVisSetState state = + m_totalAABB.pointInside(light.point) ? EPVSVisSetState::EndOfTree : EPVSVisSetState::OutOfBounds; + if (res && state == EPVSVisSetState::EndOfTree) + state = EPVSVisSetState::NodeFound; + lightPassFunc(lightIdx, state); + } + ++lightIdx; + ++idx; + } + } } -void VISIRenderer::Run(FPercent updatePercent) -{ - m_updatePercent = updatePercent; - CalculateProjMatrix(); +void VISIRenderer::Run(FPercent updatePercent) { + m_updatePercent = updatePercent; + CalculateProjMatrix(); - if (glewInit() != GLEW_OK) - { - Log.report(logvisor::Error, "unable to init glew"); - m_return = 1; - return; - } + if (glewInit() != GLEW_OK) { + Log.report(logvisor::Error, "unable to init glew"); + m_return = 1; + return; + } - if (!GLEW_ARB_occlusion_query2) - { - Log.report(logvisor::Error, "GL_ARB_occlusion_query2 extension not present"); - m_return = 1; - return; - } + if (!GLEW_ARB_occlusion_query2) { + Log.report(logvisor::Error, "GL_ARB_occlusion_query2 extension not present"); + m_return = 1; + return; + } - if (!SetupShaders()) - { - m_return = 1; - return; - } + if (!SetupShaders()) { + m_return = 1; + return; + } - if (m_argc < 3) - { - Log.report(logvisor::Error, "Missing input/output file args"); - m_return = 1; - return; - } + if (m_argc < 3) { + Log.report(logvisor::Error, "Missing input/output file args"); + m_return = 1; + return; + } - ProcessType parentPid = 0; - if (m_argc > 4) + ProcessType parentPid = 0; + if (m_argc > 4) #ifdef _WIN32 - parentPid = ProcessType(wcstoull(m_argv[4], nullptr, 16)); + parentPid = ProcessType(wcstoull(m_argv[4], nullptr, 16)); #else - parentPid = ProcessType(strtoull(m_argv[4], nullptr, 16)); + parentPid = ProcessType(strtoull(m_argv[4], nullptr, 16)); #endif - uint32_t layer2LightCount = 0; - { - athena::io::FileReader r(m_argv[1]); - if (r.hasError()) - return; + uint32_t layer2LightCount = 0; + { + athena::io::FileReader r(m_argv[1]); + if (r.hasError()) + return; - uint32_t modelCount = r.readUint32Big(); - m_models.resize(modelCount); - for (uint32_t i=0 ; i dataOut = builder.build(m_totalAABB, m_models.size(), - m_entities, m_lights, layer2LightCount, - m_updatePercent, parentPid); - if (dataOut.empty()) - { - m_return = 1; - return; + uint32_t lightCount = r.readUint32Big(); + layer2LightCount = r.readUint32Big(); + m_lights.resize(lightCount); + for (uint32_t i = 0; i < lightCount; ++i) { + Light& light = m_lights[i]; + light.point = r.readVec3fBig(); } + } - athena::io::FileWriter w(m_argv[2]); - w.writeUBytes(dataOut.data(), dataOut.size()); + if (!SetupVertexBuffersAndFormats()) { + m_return = 1; + return; + } + + VISIBuilder builder(*this); + std::vector dataOut = + builder.build(m_totalAABB, m_models.size(), m_entities, m_lights, layer2LightCount, m_updatePercent, parentPid); + if (dataOut.empty()) { + m_return = 1; + return; + } + + athena::io::FileWriter w(m_argv[2]); + w.writeUBytes(dataOut.data(), dataOut.size()); } -void VISIRenderer::Terminate() -{ - m_terminate = true; -} +void VISIRenderer::Terminate() { m_terminate = true; } diff --git a/visigen/VISIRenderer.hpp b/visigen/VISIRenderer.hpp index 5b7e53493..08d1bbd3f 100644 --- a/visigen/VISIRenderer.hpp +++ b/visigen/VISIRenderer.hpp @@ -6,104 +6,89 @@ #include "zeus/CMatrix4f.hpp" #include "zeus/CAABox.hpp" -typedef void(*FPercent)(float); +typedef void (*FPercent)(float); -enum class EPVSVisSetState -{ - EndOfTree, - NodeFound, - OutOfBounds -}; +enum class EPVSVisSetState { EndOfTree, NodeFound, OutOfBounds }; -class VISIRenderer -{ - friend struct VISIBuilder; +class VISIRenderer { + friend struct VISIBuilder; - int m_argc; - const hecl::SystemChar** m_argv; - int m_return = 0; + int m_argc; + const hecl::SystemChar** m_argv; + int m_return = 0; - zeus::CAABox m_totalAABB; + zeus::CAABox m_totalAABB; - struct UniformBuffer - { - zeus::CMatrix4f m_xf; - } m_uniformBuffer; + struct UniformBuffer { + zeus::CMatrix4f m_xf; + } m_uniformBuffer; - struct Model - { - GLenum topology; - zeus::CAABox aabb; + struct Model { + GLenum topology; + zeus::CAABox aabb; - struct Vert - { - zeus::CVector3f pos; - zeus::CColor color; - }; - std::vector verts; - - std::vector idxs; - GLuint vbo, ibo, vao; - - struct Surface - { - uint32_t first; - uint32_t count; - bool transparent; - }; - std::vector surfaces; + struct Vert { + zeus::CVector3f pos; + zeus::CColor color; }; + std::vector verts; - struct Entity - { - uint32_t entityId; - zeus::CAABox aabb; - GLuint vbo, vao; + std::vector idxs; + GLuint vbo, ibo, vao; + + struct Surface { + uint32_t first; + uint32_t count; + bool transparent; }; + std::vector surfaces; + }; - struct Light - { - zeus::CVector3f point; - GLuint vbo, vao; - }; + struct Entity { + uint32_t entityId; + zeus::CAABox aabb; + GLuint vbo, vao; + }; - GLuint m_vtxShader, m_fragShader, m_program, m_uniLoc; - GLuint m_uniformBufferGL; - GLuint m_aabbIBO; - bool SetupShaders(); + struct Light { + zeus::CVector3f point; + GLuint vbo, vao; + }; - std::vector m_models; - std::vector m_entities; - std::vector m_lights; - bool SetupVertexBuffersAndFormats(); + GLuint m_vtxShader, m_fragShader, m_program, m_uniLoc; + GLuint m_uniformBufferGL; + GLuint m_aabbIBO; + bool SetupShaders(); - size_t m_queryCount; - std::unique_ptr m_queries; - std::unique_ptr m_queryBools; + std::vector m_models; + std::vector m_entities; + std::vector m_lights; + bool SetupVertexBuffersAndFormats(); - FPercent m_updatePercent; + size_t m_queryCount; + std::unique_ptr m_queries; + std::unique_ptr m_queryBools; - static std::vector AABBToVerts(const zeus::CAABox& aabb, - const zeus::CColor& color); + FPercent m_updatePercent; + + static std::vector AABBToVerts(const zeus::CAABox& aabb, const zeus::CColor& color); public: - bool m_terminate = false; - struct RGBA8 - { - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; - }; + bool m_terminate = false; + struct RGBA8 { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + }; - VISIRenderer(int argc, const hecl::SystemChar** argv) : m_argc(argc), m_argv(argv) {} - void Run(FPercent updatePercent); - void Terminate(); - void RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bool& needTransparent); - void RenderPVSTransparent(const std::function& passFunc, const zeus::CVector3f& pos); - void RenderPVSEntitiesAndLights(const std::function& passFunc, - const std::function& lightPassFunc, - const zeus::CVector3f& pos); - int ReturnVal() const { return m_return; } + VISIRenderer(int argc, const hecl::SystemChar** argv) : m_argc(argc), m_argv(argv) {} + void Run(FPercent updatePercent); + void Terminate(); + void RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bool& needTransparent); + void RenderPVSTransparent(const std::function& passFunc, const zeus::CVector3f& pos); + void RenderPVSEntitiesAndLights(const std::function& passFunc, + const std::function& lightPassFunc, + const zeus::CVector3f& pos); + int ReturnVal() const { return m_return; } }; -